From a96dd013a4d2ce4f5f758fe51bea19f541743164 Mon Sep 17 00:00:00 2001 From: fcharrier Date: Fri, 16 Jan 2026 11:53:45 +0100 Subject: [PATCH 001/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20copy=20button=20in?= =?UTF-8?q?=20custom.js=20(#14722)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/js/custom.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/js/custom.js b/docs/en/docs/js/custom.js index 48e95901d5..be326d3029 100644 --- a/docs/en/docs/js/custom.js +++ b/docs/en/docs/js/custom.js @@ -81,8 +81,14 @@ function setupTermynal() { } } saveBuffer(); + const inputCommands = useLines + .filter(line => line.type === "input") + .map(line => line.value) + .join("\n"); + node.textContent = inputCommands; const div = document.createElement("div"); - node.replaceWith(div); + node.style.display = "none"; + node.after(div); const termynal = new Termynal(div, { lineData: useLines, noInit: true, From c597d9cb53415cf81188750ee946d69304922fbb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 Jan 2026 10:54:08 +0000 Subject: [PATCH 002/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 45bc9873ec..233fdb7434 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ๐Ÿ› Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier). * ๐Ÿ“ Add contribution instructions about LLM generated code and comments and automated tools for PRs. PR [#14706](https://github.com/fastapi/fastapi/pull/14706) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update docs for management tasks. PR [#14705](https://github.com/fastapi/fastapi/pull/14705) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update docs about managing translations. PR [#14704](https://github.com/fastapi/fastapi/pull/14704) by [@tiangolo](https://github.com/tiangolo). From f317ede223131a2822723602fb3f576f1ca0f5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 16 Jan 2026 03:54:01 -0800 Subject: [PATCH 003/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(add-missing)=20(#14699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ko/docs/_llm-test.md | 503 +++++++++++++++++ docs/ko/docs/advanced/additional-responses.md | 247 +++++++++ docs/ko/docs/advanced/behind-a-proxy.md | 466 ++++++++++++++++ docs/ko/docs/advanced/dataclasses.md | 95 ++++ docs/ko/docs/advanced/generate-clients.md | 208 ++++++++ docs/ko/docs/advanced/middleware.md | 97 ++++ docs/ko/docs/advanced/openapi-callbacks.md | 186 +++++++ docs/ko/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 172 ++++++ .../docs/advanced/security/http-basic-auth.md | 107 ++++ docs/ko/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++++++ docs/ko/docs/advanced/settings.md | 302 +++++++++++ docs/ko/docs/alternatives.md | 485 +++++++++++++++++ docs/ko/docs/deployment/concepts.md | 321 +++++++++++ docs/ko/docs/deployment/fastapicloud.md | 65 +++ docs/ko/docs/deployment/https.md | 231 ++++++++ docs/ko/docs/deployment/manually.md | 157 ++++++ .../authentication-error-status-code.md | 17 + docs/ko/docs/how-to/custom-docs-ui-assets.md | 185 +++++++ .../docs/how-to/custom-request-and-route.md | 109 ++++ docs/ko/docs/how-to/extending-openapi.md | 80 +++ docs/ko/docs/how-to/general.md | 39 ++ docs/ko/docs/how-to/graphql.md | 60 +++ docs/ko/docs/how-to/index.md | 13 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 +++++ .../docs/how-to/separate-openapi-schemas.md | 102 ++++ docs/ko/docs/how-to/testing-database.md | 7 + docs/ko/docs/tutorial/bigger-applications.md | 504 ++++++++++++++++++ docs/ko/docs/tutorial/body-updates.md | 100 ++++ .../tutorial/dependencies/sub-dependencies.md | 105 ++++ docs/ko/docs/tutorial/handling-errors.md | 244 +++++++++ docs/ko/docs/tutorial/security/first-steps.md | 203 +++++++ docs/ko/docs/tutorial/security/index.md | 106 ++++ 34 files changed, 5999 insertions(+) create mode 100644 docs/ko/docs/_llm-test.md create mode 100644 docs/ko/docs/advanced/additional-responses.md create mode 100644 docs/ko/docs/advanced/behind-a-proxy.md create mode 100644 docs/ko/docs/advanced/dataclasses.md create mode 100644 docs/ko/docs/advanced/generate-clients.md create mode 100644 docs/ko/docs/advanced/middleware.md create mode 100644 docs/ko/docs/advanced/openapi-callbacks.md create mode 100644 docs/ko/docs/advanced/openapi-webhooks.md create mode 100644 docs/ko/docs/advanced/path-operation-advanced-configuration.md create mode 100644 docs/ko/docs/advanced/security/http-basic-auth.md create mode 100644 docs/ko/docs/advanced/security/index.md create mode 100644 docs/ko/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/ko/docs/advanced/settings.md create mode 100644 docs/ko/docs/alternatives.md create mode 100644 docs/ko/docs/deployment/concepts.md create mode 100644 docs/ko/docs/deployment/fastapicloud.md create mode 100644 docs/ko/docs/deployment/https.md create mode 100644 docs/ko/docs/deployment/manually.md create mode 100644 docs/ko/docs/how-to/authentication-error-status-code.md create mode 100644 docs/ko/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/ko/docs/how-to/custom-request-and-route.md create mode 100644 docs/ko/docs/how-to/extending-openapi.md create mode 100644 docs/ko/docs/how-to/general.md create mode 100644 docs/ko/docs/how-to/graphql.md create mode 100644 docs/ko/docs/how-to/index.md create mode 100644 docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/ko/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/ko/docs/how-to/testing-database.md create mode 100644 docs/ko/docs/tutorial/bigger-applications.md create mode 100644 docs/ko/docs/tutorial/body-updates.md create mode 100644 docs/ko/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/ko/docs/tutorial/handling-errors.md create mode 100644 docs/ko/docs/tutorial/security/first-steps.md create mode 100644 docs/ko/docs/tutorial/security/index.md diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md new file mode 100644 index 0000000000..1b828c663e --- /dev/null +++ b/docs/ko/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM ํ…Œ์ŠคํŠธ ํŒŒ์ผ { #llm-test-file } + +์ด ๋ฌธ์„œ๋Š” ๋ฌธ์„œ๋ฅผ ๋ฒˆ์—ญํ•˜๋Š” LLM์ด `scripts/translate.py`์˜ `general_prompt`์™€ `docs/{language code}/llm-prompt.md`์˜ ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋Š” `general_prompt`์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์— ์ถ”๊ฐ€๋œ ํ…Œ์ŠคํŠธ๋Š” ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ `docs/{language code}/llm-prompt.md`๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. +* ์ด ๋ฌธ์„œ๋ฅผ ์›ํ•˜๋Š” ๋Œ€์ƒ ์–ธ์–ด๋กœ ์ƒˆ๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `translate.py`์˜ `translate-page` ๋ช…๋ น). ๊ทธ๋Ÿฌ๋ฉด `docs/{language code}/docs/_llm-test.md` ์•„๋ž˜์— ๋ฒˆ์—ญ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. +* ๋ฒˆ์—ญ์—์„œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. +* ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ, ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ, ๋˜๋Š” ์˜์–ด ๋ฌธ์„œ๋ฅผ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. +* ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฒˆ์—ญ์—์„œ ๋‚จ์•„ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ˆ˜์ •ํ•ด ์ข‹์€ ๋ฒˆ์—ญ์ด ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. +* ์ข‹์€ ๋ฒˆ์—ญ์„ ๋‘” ์ƒํƒœ์—์„œ ๋‹ค์‹œ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค. ์ด์ƒ์ ์ธ ๊ฒฐ๊ณผ๋Š” LLM์ด ๋” ์ด์ƒ ๋ฒˆ์—ญ์— ๋ณ€๊ฒฝ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์™€ ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ตœ์„ ์ด๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค(๋•Œ๋•Œ๋กœ ๋ช‡ ๊ฐ€์ง€ seemingly random ๋ณ€๊ฒฝ์„ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” LLM์€ ๊ฒฐ์ •๋ก ์  ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค). + +ํ…Œ์ŠคํŠธ: + +## ์ฝ”๋“œ ์Šค๋‹ˆํŽซ { #code-snippets } + +//// tab | ํ…Œ์ŠคํŠธ + +๋‹ค์Œ์€ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ž…๋‹ˆ๋‹ค: `foo`. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ๋˜ ๋‹ค๋ฅธ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ž…๋‹ˆ๋‹ค: `bar`. ๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•˜๋‚˜: `baz quux`. + +//// + +//// tab | ์ •๋ณด + +์ฝ”๋“œ ์Šค๋‹ˆํŽซ์˜ ๋‚ด์šฉ์€ ๊ทธ๋Œ€๋กœ ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Content of code snippets` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ๋”ฐ์˜ดํ‘œ { #quotes } + +//// tab | ํ…Œ์ŠคํŠธ + +์–ด์ œ ์ œ ์นœ๊ตฌ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ผ์Šต๋‹ˆ๋‹ค: "If you spell incorrectly correctly, you have spelled it incorrectly". ์ด์— ์ €๋Š” ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"". + +/// note | ์ฐธ๊ณ  + +LLM์€ ์•„๋งˆ ์ด๊ฒƒ์„ ์ž˜๋ชป ๋ฒˆ์—ญํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กœ์šด ์ ์€ ์žฌ๋ฒˆ์—ญํ•  ๋•Œ ๊ณ ์ •๋œ ๋ฒˆ์—ญ์„ ์œ ์ง€ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฟ์ž…๋‹ˆ๋‹ค. + +/// + +//// + +//// tab | ์ •๋ณด + +ํ”„๋กฌํ”„ํŠธ ์„ค๊ณ„์ž๋Š” ์ค‘๋ฆฝ ๋”ฐ์˜ดํ‘œ๋ฅผ ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ๋”ฐ์˜ดํ‘œ๋กœ ๋ณ€ํ™˜ํ• ์ง€ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Œ€๋กœ ๋‘์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### Quotes` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์˜ ๋”ฐ์˜ดํ‘œ { #quotes-in-code-snippets } + +//// tab | ํ…Œ์ŠคํŠธ + +`pip install "foo[bar]"` + +์ฝ”๋“œ ์Šค๋‹ˆํŽซ์—์„œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ์˜ˆ: `"this"`, `'that'`. + +์ฝ”๋“œ ์Šค๋‹ˆํŽซ์—์„œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ์–ด๋ ค์šด ์˜ˆ: `f"I like {'oranges' if orange else "apples"}"` + +ํ•˜๋“œ์ฝ”์–ด: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | ์ •๋ณด + +... ํ•˜์ง€๋งŒ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ ์•ˆ์˜ ๋”ฐ์˜ดํ‘œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +//// + +## ์ฝ”๋“œ ๋ธ”๋ก { #code-blocks } + +//// tab | ํ…Œ์ŠคํŠธ + +Bash ์ฝ”๋“œ ์˜ˆ์‹œ... + +```bash +# ์šฐ์ฃผ์— ์ธ์‚ฌ๋ง ์ถœ๋ ฅ +echo "Hello universe" +``` + +...๊ทธ๋ฆฌ๊ณ  ์ฝ˜์†” ์ฝ”๋“œ ์˜ˆ์‹œ... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...๊ทธ๋ฆฌ๊ณ  ๋˜ ๋‹ค๋ฅธ ์ฝ˜์†” ์ฝ”๋“œ ์˜ˆ์‹œ... + +```console +// "Code" ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ +$ mkdir code +// ํ•ด๋‹น ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ +$ cd code +``` + +...๊ทธ๋ฆฌ๊ณ  Python ์ฝ”๋“œ ์˜ˆ์‹œ... + +```Python +wont_work() # ์ด๊ฑด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๐Ÿ˜ฑ +works(foo="bar") # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ +``` + +...์ด์ƒ์ž…๋‹ˆ๋‹ค. + +//// + +//// tab | ์ •๋ณด + +์ฝ”๋“œ ๋ธ”๋ก์˜ ์ฝ”๋“œ๋Š”(์ฃผ์„์„ ์ œ์™ธํ•˜๊ณ ) ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Content of code blocks` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ํƒญ๊ณผ ์ƒ‰์ƒ ๋ฐ•์Šค { #tabs-and-colored-boxes } + +//// tab | ํ…Œ์ŠคํŠธ + +/// info | ์ •๋ณด +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// note | ์ฐธ๊ณ  +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// note Technical details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// check | ํ™•์ธ +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// tip | ํŒ +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// warning | ๊ฒฝ๊ณ  +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +/// danger | ์œ„ํ—˜ +์ผ๋ถ€ ํ…์ŠคํŠธ +/// + +//// + +//// tab | ์ •๋ณด + +ํƒญ๊ณผ `Info`/`Note`/`Warning`/๋“ฑ์˜ ๋ธ”๋ก์€ ์ œ๋ชฉ ๋ฒˆ์—ญ์„ ์ˆ˜์ง ๋ง‰๋Œ€(`|`) ๋’ค์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Special blocks`์™€ `### Tab blocks` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ์›น ๋ฐ ๋‚ด๋ถ€ ๋งํฌ { #web-and-internal-links } + +//// tab | ํ…Œ์ŠคํŠธ + +๋งํฌ ํ…์ŠคํŠธ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜๊ณ , ๋งํฌ ์ฃผ์†Œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +* [์œ„์˜ ์ œ๋ชฉ์œผ๋กœ ๊ฐ€๋Š” ๋งํฌ](#code-snippets) +* [๋‚ด๋ถ€ ๋งํฌ](index.md#installation){.internal-link target=_blank} +* ์™ธ๋ถ€ ๋งํฌ +* ์Šคํƒ€์ผ๋กœ ๊ฐ€๋Š” ๋งํฌ +* ์Šคํฌ๋ฆฝํŠธ๋กœ ๊ฐ€๋Š” ๋งํฌ +* ์ด๋ฏธ์ง€๋กœ ๊ฐ€๋Š” ๋งํฌ + +๋งํฌ ํ…์ŠคํŠธ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜๊ณ , ๋งํฌ ์ฃผ์†Œ๋Š” ๋ฒˆ์—ญ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +* FastAPI ๋งํฌ + +//// + +//// tab | ์ •๋ณด + +๋งํฌ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜์ง€๋งŒ, ์ฃผ์†Œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๋Š” FastAPI ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ํ–ฅํ•˜๋Š” ์ ˆ๋Œ€ ๋งํฌ์ด๋ฉฐ, ์ด ๊ฒฝ์šฐ ๋ฒˆ์—ญ ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Links` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## HTML "abbr" ์š”์†Œ { #html-abbr-elements } + +//// tab | ํ…Œ์ŠคํŠธ + +์—ฌ๊ธฐ HTML "abbr" ์š”์†Œ๋กœ ๊ฐ์‹ผ ๋ช‡ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ผ๋ถ€๋Š” ์ž„์˜๋กœ ๋งŒ๋“  ๊ฒƒ์ž…๋‹ˆ๋‹ค): + +### abbr๊ฐ€ ์ „์ฒด ๋ฌธ๊ตฌ๋ฅผ ์ œ๊ณต { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr๊ฐ€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-an-explanation } + +* cluster +* Deep Learning + +### abbr๊ฐ€ ์ „์ฒด ๋ฌธ๊ตฌ์™€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | ์ •๋ณด + +"abbr" ์š”์†Œ์˜ "title" ์†์„ฑ์€ ๋ช‡ ๊ฐ€์ง€ ๊ตฌ์ฒด์ ์ธ ์ง€์นจ์— ๋”ฐ๋ผ ๋ฒˆ์—ญ๋ฉ๋‹ˆ๋‹ค. + +๋ฒˆ์—ญ์—์„œ๋Š”(์˜์–ด ๋‹จ์–ด๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด) ์ž์ฒด "abbr" ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, LLM์€ ์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### HTML abbr elements` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ์ œ๋ชฉ { #headings } + +//// tab | ํ…Œ์ŠคํŠธ + +### ์›น์•ฑ ๊ฐœ๋ฐœํ•˜๊ธฐ - ํŠœํ† ๋ฆฌ์–ผ { #develop-a-webapp-a-tutorial } + +์•ˆ๋…•ํ•˜์„ธ์š”. + +### ํƒ€์ž… ํžŒํŠธ์™€ -์• ๋„ˆํ…Œ์ด์…˜ { #type-hints-and-annotations } + +๋‹ค์‹œ ์•ˆ๋…•ํ•˜์„ธ์š”. + +### super- ๋ฐ subclasses { #super-and-subclasses } + +๋‹ค์‹œ ์•ˆ๋…•ํ•˜์„ธ์š”. + +//// + +//// tab | ์ •๋ณด + +์ œ๋ชฉ์— ๋Œ€ํ•œ ์œ ์ผํ•œ ๊ฐ•ํ•œ ๊ทœ์น™์€, LLM์ด ์ค‘๊ด„ํ˜ธ ์•ˆ์˜ ํ•ด์‹œ ๋ถ€๋ถ„์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„ ๋งํฌ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Headings` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +์–ธ์–ด๋ณ„ ์ง€์นจ์€ ์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### Headings` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// + +## ๋ฌธ์„œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด { #terms-used-in-the-docs } + +//// tab | ํ…Œ์ŠคํŠธ + +* ๋‹น์‹  +* ๋‹น์‹ ์˜ + +* ์˜ˆ: (e.g.) +* ๋“ฑ (etc.) + +* `int`๋กœ์„œ์˜ `foo` +* `str`๋กœ์„œ์˜ `bar` +* `list`๋กœ์„œ์˜ `baz` + +* ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ +* ๊ณ ๊ธ‰ ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ +* SQLModel ๋ฌธ์„œ +* API ๋ฌธ์„œ +* ์ž๋™ ๋ฌธ์„œ + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO format +* JSON Schema ํ‘œ์ค€ +* JSON schema +* schema definition +* Password Flow +* Mobile + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น™ํ•˜๋‹ค +* ํŽ˜์ด์ง€๋ฅผ ์„œ๋น™ํ•˜๋‹ค + +* ์•ฑ +* ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ + +* ์š”์ฒญ +* ์‘๋‹ต +* ์˜ค๋ฅ˜ ์‘๋‹ต + +* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ +* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ +* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ + +* body +* ์š”์ฒญ body +* ์‘๋‹ต body +* JSON body +* form body +* file body +* ํ•จ์ˆ˜ body + +* parameter +* body parameter +* path parameter +* query parameter +* cookie parameter +* header parameter +* form parameter +* function parameter + +* event +* startup event +* ์„œ๋ฒ„ startup +* shutdown event +* lifespan event + +* handler +* event handler +* exception handler +* ์ฒ˜๋ฆฌํ•˜๋‹ค + +* model +* Pydantic model +* data model +* database model +* form model +* model object + +* class +* base class +* parent class +* subclass +* child class +* sibling class +* class method + +* header +* headers +* authorization header +* `Authorization` header +* forwarded header + +* dependency injection system +* dependency +* dependable +* dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* env var +* environment variable +* `PATH` +* `PATH` variable + +* authentication +* authentication provider +* authorization +* authorization form +* authorization provider +* ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆํ•œ๋‹ค +* ์‹œ์Šคํ…œ์ด ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•œ๋‹ค + +* CLI +* command line interface + +* server +* client + +* cloud provider +* cloud service + +* development +* development stages + +* dict +* dictionary +* enumeration +* enum +* enum member + +* encoder +* decoder +* encodeํ•˜๋‹ค +* decodeํ•˜๋‹ค + +* exception +* raiseํ•˜๋‹ค + +* expression +* statement + +* frontend +* backend + +* GitHub discussion +* GitHub issue + +* performance +* performance optimization + +* return type +* return value + +* security +* security scheme + +* task +* background task +* task function + +* template +* template engine + +* type annotation +* type hint + +* server worker +* Uvicorn worker +* Gunicorn Worker +* worker process +* worker class +* workload + +* deployment +* deployํ•˜๋‹ค + +* SDK +* software development kit + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* breaking change +* bug +* button +* callable +* code +* commit +* context manager +* coroutine +* database session +* disk +* domain +* engine +* fake X +* HTTP GET method +* item +* library +* lifespan +* lock +* middleware +* mobile application +* module +* mounting +* network +* origin +* override +* payload +* processor +* property +* proxy +* pull request +* query +* RAM +* remote machine +* status code +* string +* tag +* web framework +* wildcard +* returnํ•˜๋‹ค +* validateํ•˜๋‹ค + +//// + +//// tab | ์ •๋ณด + +์ด๊ฒƒ์€ ๋ฌธ์„œ์—์„œ ๋ณด์ด๋Š” (๋Œ€๋ถ€๋ถ„) ๊ธฐ์ˆ  ์šฉ์–ด์˜ ๋ถˆ์™„์ „ํ•˜๊ณ  ๋น„๊ทœ๋ฒ”์ ์ธ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ ์„ค๊ณ„์ž๊ฐ€ ์–ด๋–ค ์šฉ์–ด์— ๋Œ€ํ•ด LLM์— ์ถ”๊ฐ€์ ์ธ ๋„์›€์ด ํ•„์š”ํ•œ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ข‹์€ ๋ฒˆ์—ญ์„ ๊ณ„์† ๋œ ์ข‹์€ ๋ฒˆ์—ญ์œผ๋กœ ๋˜๋Œ๋ฆด ๋•Œ, ๋˜๋Š” ์–ธ์–ด์—์„œ ์šฉ์–ด์˜ ํ™œ์šฉ/๋ณ€ํ™”๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๋•Œ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### List of English terms and their preferred German translations` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +//// diff --git a/docs/ko/docs/advanced/additional-responses.md b/docs/ko/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..a6f51f5b93 --- /dev/null +++ b/docs/ko/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI์—์„œ ์ถ”๊ฐ€ ์‘๋‹ต { #additional-responses-in-openapi } + +/// warning | ๊ฒฝ๊ณ  + +์ด๋Š” ๊ฝค ๊ณ ๊ธ‰ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค. + +**FastAPI**๋ฅผ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด, ์ด ๋‚ด์šฉ์ด ํ•„์š” ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ, ๋ฏธ๋””์–ด ํƒ€์ž…, ์„ค๋ช… ๋“ฑ์„ ํฌํ•จํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์€ OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋˜๋ฏ€๋กœ API ๋ฌธ์„œ์—๋„ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์˜ ๊ฒฝ์šฐ, ์ƒํƒœ ์ฝ”๋“œ์™€ ์ฝ˜ํ…์ธ ๋ฅผ ํฌํ•จํ•˜์—ฌ `JSONResponse` ๊ฐ™์€ `Response`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ฐ˜๋“œ์‹œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +## `model`์„ ์‚ฌ์šฉํ•œ ์ถ”๊ฐ€ ์‘๋‹ต { #additional-response-with-model } + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” `dict`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํ‚ค๋Š” ๊ฐ ์‘๋‹ต์˜ ์ƒํƒœ ์ฝ”๋“œ(์˜ˆ: `200`)์ด๊ณ , ๊ฐ’์€ ๊ฐ ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๋‹ค๋ฅธ `dict`์ž…๋‹ˆ๋‹ค. + +๊ฐ ์‘๋‹ต `dict`์—๋Š” `response_model`์ฒ˜๋Ÿผ Pydantic ๋ชจ๋ธ์„ ๋‹ด๋Š” `model` ํ‚ค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ๊ทธ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด JSON Schema๋ฅผ ์ƒ์„ฑํ•˜๊ณ , OpenAPI์˜ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒํƒœ ์ฝ”๋“œ `404`์™€ Pydantic ๋ชจ๋ธ `Message`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์‘๋‹ต์„ ์„ ์–ธํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} + +/// note | ์ฐธ๊ณ  + +`JSONResponse`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +/// + +/// info | ์ •๋ณด + +`model` ํ‚ค๋Š” OpenAPI์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ์—ฌ๊ธฐ์—์„œ Pydantic ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€ JSON Schema๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๋„ฃ์Šต๋‹ˆ๋‹ค. + +์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ๊ฐ’์œผ๋กœ ๋˜ ๋‹ค๋ฅธ JSON ๊ฐ์ฒด(`dict`)๋ฅผ ๊ฐ€์ง€๋Š” `content` ํ‚ค ์•ˆ์—: + * ๋ฏธ๋””์–ด ํƒ€์ž…(์˜ˆ: `application/json`)์„ ํ‚ค๋กœ ๊ฐ€์ง€๋ฉฐ, ๊ฐ’์œผ๋กœ ๋˜ ๋‹ค๋ฅธ JSON ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๊ณ : + * `schema` ํ‚ค๊ฐ€ ์žˆ๊ณ , ๊ทธ ๊ฐ’์ด ๋ชจ๋ธ์—์„œ ์ƒ์„ฑ๋œ JSON Schema์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์ž…๋‹ˆ๋‹ค. + * **FastAPI**๋Š” ์ด๋ฅผ ์ง์ ‘ ํฌํ•จํ•˜๋Š” ๋Œ€์‹ , OpenAPI์˜ ๋‹ค๋ฅธ ์œ„์น˜์— ์žˆ๋Š” ์ „์—ญ JSON Schemas๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์—ฌ๊ธฐ์—์„œ reference๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ทธ JSON Schema๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋” ๋‚˜์€ ์ฝ”๋“œ ์ƒ์„ฑ ๋„๊ตฌ ๋“ฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด OpenAPI์— ์ƒ์„ฑ๋˜๋Š” ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +์Šคํ‚ค๋งˆ๋Š” OpenAPI ์Šคํ‚ค๋งˆ ๋‚ด๋ถ€์˜ ๋‹ค๋ฅธ ์œ„์น˜๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## ์ฃผ์š” ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋ฏธ๋””์–ด ํƒ€์ž… { #additional-media-types-for-the-main-response } + +๊ฐ™์€ `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋™์ผํ•œ ์ฃผ์š” ์‘๋‹ต์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ JSON ๊ฐ์ฒด(๋ฏธ๋””์–ด ํƒ€์ž… `application/json`) ๋˜๋Š” PNG ์ด๋ฏธ์ง€(๋ฏธ๋””์–ด ํƒ€์ž… `image/png`)๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด `image/png`๋ผ๋Š” ์ถ”๊ฐ€ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | ์ฐธ๊ณ  + +์ด๋ฏธ์ง€๋Š” `FileResponse`๋ฅผ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. + +/// + +/// info | ์ •๋ณด + +`responses` ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋‹ค๋ฅธ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ํ•œ, FastAPI๋Š” ์‘๋‹ต์ด ์ฃผ์š” ์‘๋‹ต ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๋ฏธ๋””์–ด ํƒ€์ž…(๊ธฐ๋ณธ๊ฐ’ `application/json`)์„ ๊ฐ€์ง„๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ปค์Šคํ…€ ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜๋ฉด์„œ ๋ฏธ๋””์–ด ํƒ€์ž…์„ `None`์œผ๋กœ ์„ค์ •ํ–ˆ๋‹ค๋ฉด, FastAPI๋Š” ์—ฐ๊ฒฐ๋œ ๋ชจ๋ธ์ด ์žˆ๋Š” ๋ชจ๋“  ์ถ”๊ฐ€ ์‘๋‹ต์— ๋Œ€ํ•ด `application/json`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// + +## ์ •๋ณด ๊ฒฐํ•ฉํ•˜๊ธฐ { #combining-information } + +`response_model`, `status_code`, `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•ด ์—ฌ๋Ÿฌ ์œ„์น˜์˜ ์‘๋‹ต ์ •๋ณด๋ฅผ ๊ฒฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ธฐ๋ณธ ์ƒํƒœ ์ฝ”๋“œ `200`(๋˜๋Š” ํ•„์š”ํ•˜๋‹ค๋ฉด ์ปค์Šคํ…€ ์ฝ”๋“œ)์„ ์‚ฌ์šฉํ•˜์—ฌ `response_model`์„ ์„ ์–ธํ•˜๊ณ , ๊ทธ์™€ ๋™์ผํ•œ ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ `responses`์—์„œ OpenAPI ์Šคํ‚ค๋งˆ์— ์ง์ ‘ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**FastAPI**๋Š” `responses`์˜ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๋ชจ๋ธ์˜ JSON Schema์™€ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ปค์Šคํ…€ `description`์„ ๊ฐ€์ง„ ์ƒํƒœ ์ฝ”๋“œ `404` ์‘๋‹ต์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ `response_model`์„ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ ์ฝ”๋“œ `200` ์‘๋‹ต์„ ์„ ์–ธํ•˜๋˜, ์ปค์Šคํ…€ `example`์„ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} + +์ด ๋ชจ๋“  ๋‚ด์šฉ์€ OpenAPI์— ๊ฒฐํ•ฉ๋˜์–ด ํฌํ•จ๋˜๊ณ , API ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: + + + +## ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต๊ณผ ์ปค์Šคํ…€ ์‘๋‹ต ๊ฒฐํ•ฉํ•˜๊ธฐ { #combine-predefined-responses-and-custom-ones } + +์—ฌ๋Ÿฌ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์ ์šฉ๋˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ํ•„์š”ํ•œ ์ปค์Šคํ…€ ์‘๋‹ต๊ณผ ๊ฒฐํ•ฉํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ Python์˜ `dict` โ€œunpackingโ€ ๊ธฐ๋ฒ•์ธ `**dict_to_unpack`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +์—ฌ๊ธฐ์„œ `new_dict`๋Š” `old_dict`์˜ ๋ชจ๋“  ํ‚ค-๊ฐ’ ์Œ์— ๋”ํ•ด ์ƒˆ ํ‚ค-๊ฐ’ ์Œ๊นŒ์ง€ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +์ด ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ์ผ๋ถ€ ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ์ถ”๊ฐ€ ์ปค์Šคํ…€ ์‘๋‹ต๊ณผ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## OpenAPI ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด { #more-information-about-openapi-responses } + +์‘๋‹ต์— ์ •ํ™•ํžˆ ๋ฌด์—‡์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด๋ ค๋ฉด, OpenAPI ์‚ฌ์–‘์˜ ๋‹ค์Œ ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”: + +* OpenAPI Responses Object: `Response Object`๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +* OpenAPI Response Object: `responses` ํŒŒ๋ผ๋ฏธํ„ฐ ์•ˆ์˜ ๊ฐ ์‘๋‹ต์— ์ด๊ฒƒ์˜ ์–ด๋–ค ํ•ญ๋ชฉ์ด๋“  ์ง์ ‘ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. `description`, `headers`, `content`(์—ฌ๊ธฐ์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฏธ๋””์–ด ํƒ€์ž…๊ณผ JSON Schema๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค), `links` ๋“ฑ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/behind-a-proxy.md b/docs/ko/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..92bddac51a --- /dev/null +++ b/docs/ko/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# ํ”„๋ก์‹œ ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ธฐ { #behind-a-proxy } + +๋งŽ์€ ๊ฒฝ์šฐ FastAPI ์•ฑ ์•ž๋‹จ์— Traefik์ด๋‚˜ Nginx ๊ฐ™์€ **ํ”„๋ก์‹œ(proxy)**๋ฅผ ๋‘๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฐ ํ”„๋ก์‹œ๋Š” HTTPS ์ธ์ฆ์„œ ์ฒ˜๋ฆฌ ๋“ฑ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋‹ด๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” { #proxy-forwarded-headers } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•ž๋‹จ์˜ **ํ”„๋ก์‹œ**๋Š” ๋ณดํ†ต **์„œ๋ฒ„**๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์—, ํ•ด๋‹น ์š”์ฒญ์ด ํ”„๋ก์‹œ์— ์˜ํ•ด **์ „๋‹ฌ(forwarded)**๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์„œ๋ฒ„๊ฐ€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๋ช‡๋ช‡ ํ—ค๋”๋ฅผ ๋™์ ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋Š” ๋„๋ฉ”์ธ์„ ํฌํ•จํ•œ ์›๋ž˜์˜ (๊ณต๊ฐœ) URL, HTTPS ์‚ฌ์šฉ ์—ฌ๋ถ€ ๋“ฑ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**์„œ๋ฒ„** ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: **FastAPI CLI**๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” **Uvicorn**)์€ ์ด๋Ÿฐ ํ—ค๋”๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ •๋ณด๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋ณด์•ˆ์ƒ, ์„œ๋ฒ„๋Š” ์ž์‹ ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ก์‹œ ๋’ค์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ํ•ด๋‹น ํ—ค๋”๋ฅผ ํ•ด์„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +ํ”„๋ก์‹œ ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #enable-proxy-forwarded-headers } + +FastAPI CLI๋ฅผ *CLI ์˜ต์…˜* `--forwarded-allow-ips`๋กœ ์‹คํ–‰ํ•˜๊ณ , ์ „๋‹ฌ ํ—ค๋”๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์‹ ๋ขฐํ•  IP ์ฃผ์†Œ๋“ค์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`--forwarded-allow-ips="*"`๋กœ ์„ค์ •ํ•˜๋ฉด ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  IP๋ฅผ ์‹ ๋ขฐํ•ฉ๋‹ˆ๋‹ค. + +**์„œ๋ฒ„**๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” **ํ”„๋ก์‹œ** ๋’ค์— ์žˆ๊ณ  ํ”„๋ก์‹œ๋งŒ ์„œ๋ฒ„์— ์ ‘๊ทผํ•œ๋‹ค๋ฉด, ์ด๋Š” ํ•ด๋‹น **ํ”„๋ก์‹œ**์˜ IP๊ฐ€ ๋ฌด์—‡์ด๋“  ๊ฐ„์— ๋ฐ›์•„๋“ค์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### HTTPS์—์„œ ๋ฆฌ๋””๋ ‰์…˜ { #redirects-with-https } + +์˜ˆ๋ฅผ ๋“ค์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `/items/`๋ฅผ ์ •์˜ํ–ˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} + +ํด๋ผ์ด์–ธํŠธ๊ฐ€ `/items`๋กœ ์ ‘๊ทผํ•˜๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ `/items/`๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ *CLI ์˜ต์…˜* `--forwarded-allow-ips`๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์ „์—๋Š” `http://localhost:8000/items/`๋กœ ๋ฆฌ๋””๋ ‰์…˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด `https://mysuperapp.com`์— ํ˜ธ์ŠคํŒ…๋˜์–ด ์žˆ๊ณ , ๋ฆฌ๋””๋ ‰์…˜๋„ `https://mysuperapp.com/items/`๋กœ ๋˜์–ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋•Œ `--proxy-headers`๋ฅผ ์„ค์ •ํ•˜๋ฉด FastAPI๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | ํŒ + +HTTPS์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๋ ค๋ฉด ๊ฐ€์ด๋“œ [HTTPS์— ๋Œ€ํ•˜์—ฌ](../deployment/https.md){.internal-link target=_blank}๋ฅผ ํ™•์ธํ•˜์„ธ์š”. + +/// + +### ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋”๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-proxy-forwarded-headers-work } + +๋‹ค์Œ์€ **ํ”„๋ก์‹œ**๊ฐ€ ํด๋ผ์ด์–ธํŠธ์™€ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„** ์‚ฌ์ด์—์„œ ์ „๋‹ฌ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์„ ์‹œ๊ฐ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**ํ”„๋ก์‹œ**๋Š” ์›๋ž˜์˜ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๊ณ , **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ํŠน์ˆ˜ํ•œ *forwarded* ํ—ค๋”(`X-Forwarded-*`)๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + +์ด ํ—ค๋”๋“ค์€ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š” ์›๋ž˜ ์š”์ฒญ์˜ ์ •๋ณด๋ฅผ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค: + +* **X-Forwarded-For**: ์›๋ž˜ ํด๋ผ์ด์–ธํŠธ์˜ IP ์ฃผ์†Œ +* **X-Forwarded-Proto**: ์›๋ž˜ ํ”„๋กœํ† ์ฝœ(`https`) +* **X-Forwarded-Host**: ์›๋ž˜ ํ˜ธ์ŠคํŠธ(`mysuperapp.com`) + +**FastAPI CLI**๋ฅผ `--forwarded-allow-ips`๋กœ ์„ค์ •ํ•˜๋ฉด, ์ด ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋””๋ ‰์…˜์—์„œ ์˜ฌ๋ฐ”๋ฅธ URL์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +## ์ œ๊ฑฐ๋œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ { #proxy-with-a-stripped-path-prefix } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ(prefix)๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ํ”„๋ก์‹œ๋ฅผ ๋‘˜ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Ÿฐ ๊ฒฝ์šฐ `root_path`๋ฅผ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`root_path`๋Š” (FastAPI๊ฐ€ Starlette๋ฅผ ํ†ตํ•ด ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š”) ASGI ์‚ฌ์–‘์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. + +`root_path`๋Š” ์ด๋Ÿฌํ•œ ํŠน์ • ์‚ฌ๋ก€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +๋˜ํ•œ ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งˆ์šดํŠธํ•  ๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ(stripped)๋˜๋Š” ํ”„๋ก์‹œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€, ์ฝ”๋“œ์—์„œ๋Š” `/app`์— ๊ฒฝ๋กœ๋ฅผ ์„ ์–ธํ•˜์ง€๋งŒ, ์œ„์— ํ•œ ๊ฒน(ํ”„๋ก์‹œ)์„ ์ถ”๊ฐ€ํ•ด **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ `/api/v1` ๊ฐ™์€ ๊ฒฝ๋กœ ์•„๋ž˜์— ๋‘๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ ์›๋ž˜ ๊ฒฝ๋กœ `/app`์€ ์‹ค์ œ๋กœ `/api/v1/app`์—์„œ ์„œ๋น„์Šค๋ฉ๋‹ˆ๋‹ค. + +์ฝ”๋“œ๋Š” ๋ชจ๋‘ `/app`๋งŒ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ๋„ ๋ง์ž…๋‹ˆ๋‹ค. + +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} + +๊ทธ๋ฆฌ๊ณ  ํ”„๋ก์‹œ๋Š” ์š”์ฒญ์„ ์•ฑ ์„œ๋ฒ„(์•„๋งˆ FastAPI CLI๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” Uvicorn)๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, ๋™์ ์œผ๋กœ **๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ**๋ฅผ **"์ œ๊ฑฐ"**ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—ฌ์ „ํžˆ `/app`์—์„œ ์„œ๋น„์Šค๋œ๋‹ค๊ณ  ๋ฏฟ๊ฒŒ ๋˜๊ณ , ์ฝ”๋“œ ์ „์ฒด๋ฅผ `/api/v1` ์ ‘๋‘์‚ฌ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง‘๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๋ณดํ†ต ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ํ†ตํ•ฉ ๋ฌธ์„œ UI(ํ”„๋ก ํŠธ์—”๋“œ)๋ฅผ ์—ด๋ฉด, OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ `/api/v1/openapi.json`์ด ์•„๋‹ˆ๋ผ `/openapi.json`์—์„œ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋Š” `/openapi.json`์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€๋งŒ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์–ป์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. + +์•ฑ์— ๋Œ€ํ•ด `/api/v1` ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ํ”„๋ก ํŠธ์—”๋“œ๋Š” `/api/v1/openapi.json`์—์„œ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | ํŒ + +IP `0.0.0.0`์€ ๋ณดํ†ต ํ•ด๋‹น ๋จธ์‹ /์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  IP์—์„œ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฆฌ์Šจํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +/// + +๋ฌธ์„œ UI๋Š” ๋˜ํ•œ OpenAPI ์Šคํ‚ค๋งˆ์—์„œ ์ด API `server`๊ฐ€ `/api/v1`(ํ”„๋ก์‹œ ๋’ค) ์œ„์น˜์— ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // More stuff here + } +} +``` + +์ด ์˜ˆ์‹œ์—์„œ "Proxy"๋Š” **Traefik** ๊ฐ™์€ ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๋Š” **Uvicorn**์œผ๋กœ ์‹คํ–‰๋˜๋Š” FastAPI CLI์ฒ˜๋Ÿผ, FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๊ตฌ์„ฑ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### `root_path` ์ œ๊ณตํ•˜๊ธฐ { #providing-the-root-path } + +์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Hypercorn์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, Hypercorn์—๋„ `--root-path` ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +ASGI ์‚ฌ์–‘์€ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด `root_path`๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๊ฐ€ ๊ทธ `root_path`๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +/// + +### ํ˜„์žฌ `root_path` ํ™•์ธํ•˜๊ธฐ { #checking-the-current-root-path } + +์š”์ฒญ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ ์ค‘์ธ ํ˜„์žฌ `root_path`๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” `scope` ๋”•์…”๋„ˆ๋ฆฌ(ASGI ์‚ฌ์–‘์˜ ์ผ๋ถ€)์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋Š” ๋ฐ๋ชจ ๋ชฉ์ ์„ ์œ„ํ•ด ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} + +๊ทธ ๋‹ค์Œ Uvicorn์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ•˜๋ฉด: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### FastAPI ์•ฑ์—์„œ `root_path` ์„ค์ •ํ•˜๊ธฐ { #setting-the-root-path-in-the-fastapi-app } + +๋˜๋Š” `--root-path` ๊ฐ™์€ ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜(๋˜๋Š” ๋™๋“ฑํ•œ ๋ฐฉ๋ฒ•)์„ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, FastAPI ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ `root_path` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} + +`FastAPI`์— `root_path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ Uvicorn์ด๋‚˜ Hypercorn์— ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +### `root_path`์— ๋Œ€ํ•˜์—ฌ { #about-root-path } + +์„œ๋ฒ„(Uvicorn)๋Š” ๊ทธ `root_path`๋ฅผ ์•ฑ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ๋‹ค๋ฅธ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +ํ•˜์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €๋กœ http://127.0.0.1:8000/app์— ์ ‘์†ํ•˜๋ฉด ์ •์ƒ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +๋”ฐ๋ผ์„œ `http://127.0.0.1:8000/api/v1/app`๋กœ ์ ‘๊ทผ๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. + +Uvicorn์€ ํ”„๋ก์‹œ๊ฐ€ `http://127.0.0.1:8000/app`์—์„œ Uvicorn์— ์ ‘๊ทผํ•  ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•˜๊ณ , ๊ทธ ์œ„์— `/api/v1` ์ ‘๋‘์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํ”„๋ก์‹œ์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. + +## ์ œ๊ฑฐ๋œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ์— ๋Œ€ํ•˜์—ฌ { #about-proxies-with-a-stripped-path-prefix } + +๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ๋˜๋Š” ํ”„๋ก์‹œ๋Š” ๊ตฌ์„ฑ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ผ ๋ฟ์ด๋ผ๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +๋งŽ์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ ํ”„๋ก์‹œ๊ฐ€ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ(๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ) ํ”„๋ก์‹œ๋Š” `https://myawesomeapp.com` ๊ฐ™์€ ๊ณณ์—์„œ ๋ฆฌ์Šจํ•˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๊ฐ€ `https://myawesomeapp.com/api/v1/app`๋กœ ์ ‘๊ทผํ•˜๋ฉด, ์„œ๋ฒ„(์˜ˆ: Uvicorn)๊ฐ€ `http://127.0.0.1:8000`์—์„œ ๋ฆฌ์Šจํ•˜๊ณ  ์žˆ์„ ๋•Œ ํ”„๋ก์‹œ(๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”)๋Š” ๋™์ผํ•œ ๊ฒฝ๋กœ๋กœ Uvicorn์— ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค: `http://127.0.0.1:8000/api/v1/app`. + +## Traefik์œผ๋กœ ๋กœ์ปฌ ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #testing-locally-with-traefik } + +Traefik์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ๋˜๋Š” ๊ตฌ์„ฑ์„ ๋กœ์ปฌ์—์„œ ์‰ฝ๊ฒŒ ์‹คํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +Traefik ๋‹ค์šด๋กœ๋“œ๋Š” ๋‹จ์ผ ๋ฐ”์ด๋„ˆ๋ฆฌ์ด๋ฉฐ, ์••์ถ• ํŒŒ์ผ์„ ํ’€๊ณ  ํ„ฐ๋ฏธ๋„์—์„œ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ๋‹ค์Œ ๋‚ด์šฉ์„ ๊ฐ€์ง„ `traefik.toml` ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์„ธ์š”: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +์ด๋Š” Traefik์ด 9999 ํฌํŠธ์—์„œ ๋ฆฌ์Šจํ•˜๊ณ , ๋‹ค๋ฅธ ํŒŒ์ผ `routes.toml`์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +ํ‘œ์ค€ HTTP ํฌํŠธ 80 ๋Œ€์‹  9999 ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ, ๊ด€๋ฆฌ์ž(`sudo`) ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. + +/// + +์ด์ œ ๋‹ค๋ฅธ ํŒŒ์ผ `routes.toml`์„ ์ƒ์„ฑํ•˜์„ธ์š”: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +์ด ํŒŒ์ผ์€ Traefik์ด ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ `/api/v1`์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  Traefik์€ ์š”์ฒญ์„ `http://127.0.0.1:8000`์—์„œ ์‹คํ–‰ ์ค‘์ธ Uvicorn์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + +์ด์ œ Traefik์„ ์‹œ์ž‘ํ•˜์„ธ์š”: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +๊ทธ๋ฆฌ๊ณ  `--root-path` ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด ์•ฑ์„ ์‹œ์ž‘ํ•˜์„ธ์š”: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ์‘๋‹ต ํ™•์ธํ•˜๊ธฐ { #check-the-responses } + +์ด์ œ Uvicorn์˜ ํฌํŠธ๋กœ ๋œ URL์ธ http://127.0.0.1:8000/app๋กœ ์ ‘์†ํ•˜๋ฉด ์ •์ƒ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | ํŒ + +`http://127.0.0.1:8000/app`๋กœ ์ ‘๊ทผํ–ˆ๋Š”๋ฐ๋„ `/api/v1`์˜ `root_path`๊ฐ€ ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์˜ต์…˜ `--root-path`์—์„œ ๊ฐ€์ ธ์˜จ ๊ฐ’์ž…๋‹ˆ๋‹ค. + +/// + +์ด์ œ Traefik์˜ ํฌํŠธ๊ฐ€ ํฌํ•จ๋˜๊ณ  ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ํฌํ•จ๋œ URL http://127.0.0.1:9999/api/v1/app์„ ์—ฌ์„ธ์š”. + +๋™์ผํ•œ ์‘๋‹ต์„ ์–ป์Šต๋‹ˆ๋‹ค: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ํ•˜์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•œ ์ ‘๋‘์‚ฌ ๊ฒฝ๋กœ `/api/v1`์ด ํฌํ•จ๋œ URL์—์„œ์˜ ์‘๋‹ต์ž…๋‹ˆ๋‹ค. + +๋ฌผ๋ก  ์—ฌ๊ธฐ์„œ์˜ ์•„์ด๋””์–ด๋Š” ๋ชจ๋‘๊ฐ€ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์•ฑ์— ์ ‘๊ทผํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, `/api/v1` ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์žˆ๋Š” ๋ฒ„์ „์ด "์˜ฌ๋ฐ”๋ฅธ" ์ ‘๊ทผ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์—†๋Š” ๋ฒ„์ „(`http://127.0.0.1:8000/app`)์€ Uvicorn์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ์˜ค์ง _ํ”„๋ก์‹œ_(Traefik)๊ฐ€ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„์ž…๋‹ˆ๋‹ค. + +์ด๋Š” ํ”„๋ก์‹œ(Traefik)๊ฐ€ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์„œ๋ฒ„(Uvicorn)๊ฐ€ ์˜ต์…˜ `--root-path`๋กœ๋ถ€ํ„ฐ์˜ `root_path`๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. + +### ๋ฌธ์„œ UI ํ™•์ธํ•˜๊ธฐ { #check-the-docs-ui } + +ํ•˜์ง€๋งŒ ์žฌ๋ฏธ์žˆ๋Š” ๋ถ€๋ถ„์€ ์—ฌ๊ธฐ์ž…๋‹ˆ๋‹ค. โœจ + +์•ฑ์— ์ ‘๊ทผํ•˜๋Š” "๊ณต์‹" ๋ฐฉ๋ฒ•์€ ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด์„œ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ๋Œ€ํ•˜๋Š” ๋Œ€๋กœ, URL์— ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์—†๋Š” ์ƒํƒœ์—์„œ Uvicorn์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” docs UI๋ฅผ ์‹œ๋„ํ•˜๋ฉด, ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +http://127.0.0.1:8000/docs์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +ํ•˜์ง€๋งŒ ํ”„๋ก์‹œ(ํฌํŠธ `9999`)๋ฅผ ์‚ฌ์šฉํ•ด "๊ณต์‹" URL์ธ `/api/v1/docs`์—์„œ docs UI์— ์ ‘๊ทผํ•˜๋ฉด, ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ + +http://127.0.0.1:9999/api/v1/docs์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +์›ํ•˜๋˜ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. โœ”๏ธ + +์ด๋Š” FastAPI๊ฐ€ ์ด `root_path`๋ฅผ ์‚ฌ์šฉํ•ด, OpenAPI์—์„œ ๊ธฐ๋ณธ `server`๋ฅผ `root_path`๊ฐ€ ์ œ๊ณตํ•œ URL๋กœ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +## ์ถ”๊ฐ€ ์„œ๋ฒ„ { #additional-servers } + +/// warning | ๊ฒฝ๊ณ  + +์ด๋Š” ๋” ๊ณ ๊ธ‰ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. + +/// + +๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋Š” OpenAPI ์Šคํ‚ค๋งˆ์—์„œ `root_path`์˜ URL๋กœ `server`๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์˜ˆ๋ฅผ ๋“ค์–ด ๋™์ผํ•œ docs UI๊ฐ€ ์Šคํ…Œ์ด์ง•๊ณผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ ๋ชจ๋‘์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋„๋ก ํ•˜๋ ค๋ฉด, ๋‹ค๋ฅธ ๋Œ€์•ˆ `servers`๋ฅผ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์‚ฌ์šฉ์ž ์ •์˜ `servers` ๋ฆฌ์ŠคํŠธ๋ฅผ ์ „๋‹ฌํ–ˆ๊ณ  `root_path`(API๊ฐ€ ํ”„๋ก์‹œ ๋’ค์— ์žˆ๊ธฐ ๋•Œ๋ฌธ)๊ฐ€ ์žˆ๋‹ค๋ฉด, **FastAPI**๋Š” ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ์•ž์— ์ด `root_path`๋ฅผ ๊ฐ€์ง„ "server"๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ: + +{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} + +๋‹ค์Œ๊ณผ ๊ฐ™์€ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // More stuff here + } +} +``` + +/// tip | ํŒ + +`root_path`์—์„œ ๊ฐ€์ ธ์˜จ ๊ฐ’์ธ `/api/v1`์˜ `url` ๊ฐ’์„ ๊ฐ€์ง„, ์ž๋™ ์ƒ์„ฑ๋œ server์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + +/// + +http://127.0.0.1:9999/api/v1/docs์˜ docs UI์—์„œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค: + + + +/// tip | ํŒ + +docs UI๋Š” ์„ ํƒํ•œ server์™€ ์ƒํ˜ธ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +OpenAPI ์‚ฌ์–‘์—์„œ `servers` ์†์„ฑ์€ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. + +`servers` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  `root_path`๊ฐ€ `/`์™€ ๊ฐ™๋‹ค๋ฉด, ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ์˜ `servers` ์†์„ฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์™„์ „ํžˆ ์ƒ๋žต๋˜๋ฉฐ, ์ด๋Š” `url` ๊ฐ’์ด `/`์ธ ๋‹จ์ผ server์™€ ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค. + +/// + +### `root_path`์—์„œ ์ž๋™ server ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-automatic-server-from-root-path } + +**FastAPI**๊ฐ€ `root_path`๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ server๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๋ ค๋ฉด, `root_path_in_servers=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} + +๊ทธ๋Ÿฌ๋ฉด OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +## ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งˆ์šดํŠธํ•˜๊ธฐ { #mounting-a-sub-application } + +ํ”„๋ก์‹œ์—์„œ `root_path`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„, [์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ๋งˆ์šดํŠธ](sub-applications.md){.internal-link target=_blank}์— ์„ค๋ช…๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งˆ์šดํŠธํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๊ธฐ๋Œ€ํ•˜๋Š” ๋Œ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +FastAPI๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ `root_path`๋ฅผ ๋˜‘๋˜‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ๊ทธ๋ƒฅ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. โœจ diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..92ad5545b3 --- /dev/null +++ b/docs/ko/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #using-dataclasses } + +FastAPI๋Š” **Pydantic** ์œ„์— ๊ตฌ์ถ•๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ง€๊ธˆ๊นŒ์ง€๋Š” Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ ธ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ FastAPI๋Š” `dataclasses`๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +์ด๋Š” **Pydantic** ๋•๋ถ„์— ์—ฌ์ „ํžˆ ์ง€์›๋˜๋Š”๋ฐ, Pydantic์ด `dataclasses`์— ๋Œ€ํ•œ ๋‚ด๋ถ€ ์ง€์›์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ Pydantic์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, FastAPI๋Š” Pydantic์„ ์‚ฌ์šฉํ•ด ํ‘œ์ค€ dataclasses๋ฅผ Pydantic์˜ dataclasses ๋ณ€ํ˜•์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋ฌผ๋ก  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ๋„ ๋™์ผํ•˜๊ฒŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: + +* ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ +* ๋ฐ์ดํ„ฐ ์ง๋ ฌํ™” +* ๋ฐ์ดํ„ฐ ๋ฌธ์„œํ™” ๋“ฑ + +์ด๋Š” Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ๋„ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” Pydantic์„ ์‚ฌ์šฉํ•ด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +dataclasses๋Š” Pydantic ๋ชจ๋ธ์ด ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ํ•  ์ˆ˜๋Š” ์—†๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +๊ทธ๋ž˜์„œ ์—ฌ์ „ํžˆ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด๋ฏธ ์—ฌ๋Ÿฌ dataclasses๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ์ด๊ฒƒ์€ FastAPI๋กœ ์›น API๋ฅผ ๊ตฌ๋™ํ•˜๋Š” ๋ฐ ๊ทธ๊ฒƒ๋“ค์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๐Ÿค“ + +/// + +## `response_model`์—์„œ Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #dataclasses-in-response-model } + +`response_model` ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ๋„ `dataclasses`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +dataclass๋Š” ์ž๋™์œผ๋กœ Pydantic dataclass๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ์Šคํ‚ค๋งˆ๊ฐ€ API docs ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: + + + +## ์ค‘์ฒฉ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์—์„œ Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #dataclasses-in-nested-data-structures } + +`dataclasses`๋ฅผ ๋‹ค๋ฅธ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ์กฐํ•ฉํ•ด ์ค‘์ฒฉ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” Pydantic ๋ฒ„์ „์˜ `dataclasses`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ž๋™ ์ƒ์„ฑ๋œ API ๋ฌธ์„œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ ํ‘œ์ค€ `dataclasses`๋ฅผ ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ธ `pydantic.dataclasses`๋กœ ๊ฐ„๋‹จํžˆ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. ํ‘œ์ค€ `dataclasses`์—์„œ `field`๋ฅผ ๊ณ„์† ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค. + +2. `pydantic.dataclasses`๋Š” `dataclasses`์˜ ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ž…๋‹ˆ๋‹ค. + +3. `Author` dataclass์—๋Š” `Item` dataclasses์˜ ๋ฆฌ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +4. `Author` dataclass๊ฐ€ `response_model` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +5. ์š”์ฒญ ๋ณธ๋ฌธ์œผ๋กœ dataclasses์™€ ํ•จ๊ป˜ ๋‹ค๋ฅธ ํ‘œ์ค€ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ์ด ๊ฒฝ์šฐ์—๋Š” `Item` dataclasses์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. + +6. ์—ฌ๊ธฐ์„œ๋Š” dataclasses ๋ฆฌ์ŠคํŠธ์ธ `items`๋ฅผ ํฌํ•จํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + + FastAPI๋Š” ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ serializingํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +7. ์—ฌ๊ธฐ์„œ `response_model`์€ `Author` dataclasses ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + + ๋‹ค์‹œ ๋งํ•ด, `dataclasses`๋ฅผ ํ‘œ์ค€ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +8. ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋Š” `async def` ๋Œ€์‹  ์ผ๋ฐ˜ `def`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + + ์–ธ์ œ๋‚˜์ฒ˜๋Ÿผ FastAPI์—์„œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ `def`์™€ `async def`๋ฅผ ์กฐํ•ฉํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + ์–ด๋–ค ๊ฒƒ์„ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, [`async`์™€ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ๋ฌธ์„œ์˜ _"๊ธ‰ํ•˜์‹ ๊ฐ€์š”?"_ ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”. + +9. ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋Š” dataclasses๋ฅผ(๋ฌผ๋ก  ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ) ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ , ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๋”•์…”๋„ˆ๋ฆฌ๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + + FastAPI๋Š” `response_model` ๋งค๊ฐœ๋ณ€์ˆ˜(dataclasses ํฌํ•จ)๋ฅผ ์‚ฌ์šฉํ•ด ์‘๋‹ต์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +`dataclasses`๋Š” ๋‹ค๋ฅธ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ๋งค์šฐ ๋‹ค์–‘ํ•œ ์กฐํ•ฉ์œผ๋กœ ๊ฒฐํ•ฉํ•ด ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋” ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ์€ ์œ„ ์ฝ”๋“œ ๋‚ด ์• ๋„ˆํ…Œ์ด์…˜ ํŒ์„ ํ™•์ธํ•˜์„ธ์š”. + +## ๋” ์•Œ์•„๋ณด๊ธฐ { #learn-more } + +`dataclasses`๋ฅผ ๋‹ค๋ฅธ Pydantic ๋ชจ๋ธ๊ณผ ์กฐํ•ฉํ•˜๊ฑฐ๋‚˜, ์ด๋ฅผ ์ƒ์†ํ•˜๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋ธ์— ํฌํ•จํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ž์„ธํ•œ ๋‚ด์šฉ์€ dataclasses์— ๊ด€ํ•œ Pydantic ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +## ๋ฒ„์ „ { #version } + +์ด ๊ธฐ๋Šฅ์€ FastAPI `0.67.0` ๋ฒ„์ „๋ถ€ํ„ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ”– diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..1def3efe12 --- /dev/null +++ b/docs/ko/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# SDK ์ƒ์„ฑํ•˜๊ธฐ { #generating-sdks } + +**FastAPI**๋Š” **OpenAPI** ์‚ฌ์–‘์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ, FastAPI์˜ API๋Š” ๋งŽ์€ ๋„๊ตฌ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ‘œ์ค€ ํ˜•์‹์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋•๋ถ„์— ์—ฌ๋Ÿฌ ์–ธ์–ด์šฉ ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(**SDKs**), ์ตœ์‹  **๋ฌธ์„œ**, ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์™€ ๋™๊ธฐํ™”๋œ **ํ…Œ์ŠคํŠธ** ๋˜๋Š” **์ž๋™ํ™” ์›Œํฌํ”Œ๋กœ**๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” FastAPI ๋ฐฑ์—”๋“œ์šฉ **TypeScript SDK**๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค. + +## ์˜คํ”ˆ ์†Œ์Šค SDK ์ƒ์„ฑ๊ธฐ { #open-source-sdk-generators } + +๋‹ค์–‘ํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์œผ๋กœ OpenAPI Generator๊ฐ€ ์žˆ์œผ๋ฉฐ, **๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด**๋ฅผ ์ง€์›ํ•˜๊ณ  OpenAPI ์‚ฌ์–‘์œผ๋กœ๋ถ€ํ„ฐ SDK๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +**TypeScript ํด๋ผ์ด์–ธํŠธ**์˜ ๊ฒฝ์šฐ Hey API๋Š” TypeScript ์ƒํƒœ๊ณ„์— ์ตœ์ ํ™”๋œ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ ์„ค๊ณ„๋œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. + +๋” ๋งŽ์€ SDK ์ƒ์„ฑ๊ธฐ๋Š” OpenAPI.Tools์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +FastAPI๋Š” **OpenAPI 3.1** ์‚ฌ์–‘์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๋Š” ์ด ๋ฒ„์ „์„ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +## FastAPI ์Šคํฐ์„œ์˜ SDK ์ƒ์„ฑ๊ธฐ { #sdk-generators-from-fastapi-sponsors } + +์ด ์„น์…˜์—์„œ๋Š” FastAPI๋ฅผ ํ›„์›ํ•˜๋Š” ํšŒ์‚ฌ๋“ค์ด ์ œ๊ณตํ•˜๋Š” **๋ฒค์ฒ˜ ํˆฌ์ž ๊ธฐ๋ฐ˜** ๋ฐ **๊ธฐ์—… ์ง€์›** ์†”๋ฃจ์…˜์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด ์ œํ’ˆ๋“ค์€ ๊ณ ํ’ˆ์งˆ๋กœ ์ƒ์„ฑ๋œ SDK์— ๋”ํ•ด **์ถ”๊ฐ€ ๊ธฐ๋Šฅ**๊ณผ **ํ†ตํ•ฉ**์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +โœจ [**FastAPI ํ›„์›ํ•˜๊ธฐ**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๋ฅผ ํ†ตํ•ด, ์ด ํšŒ์‚ฌ๋“ค์€ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๊ทธ **์ƒํƒœ๊ณ„**๊ฐ€ ๊ฑด๊ฐ•ํ•˜๊ณ  **์ง€์† ๊ฐ€๋Šฅ**ํ•˜๊ฒŒ ์œ ์ง€๋˜๋„๋ก ๋•์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ ์ด๋“ค์˜ ํ›„์›์€ FastAPI **์ปค๋ฎค๋‹ˆํ‹ฐ**(์—ฌ๋Ÿฌ๋ถ„)์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ํ—Œ์‹ ์„ ๋ณด์—ฌ์ฃผ๋ฉฐ, **์ข‹์€ ์„œ๋น„์Šค**๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋ฟ ์•„๋‹ˆ๋ผ, ๊ฒฌ๊ณ ํ•˜๊ณ  ํ™œ๋ฐœํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์ธ FastAPI๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ์—๋„ ๊ด€์‹ฌ์ด ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๐Ÿ™‡ + +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* Speakeasy +* Stainless +* liblab + +์ด ์ค‘ ์ผ๋ถ€๋Š” ์˜คํ”ˆ ์†Œ์Šค์ด๊ฑฐ๋‚˜ ๋ฌด๋ฃŒ ํ‹ฐ์–ด๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ๋น„์šฉ ๋ถ€๋‹ด ์—†์ด ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ƒ์šฉ SDK ์ƒ์„ฑ๊ธฐ๋„ ์žˆ์œผ๋ฉฐ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ + +## TypeScript SDK ๋งŒ๋“ค๊ธฐ { #create-a-typescript-sdk } + +๊ฐ„๋‹จํ•œ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} + +*path operation*์—์„œ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ์™€ ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์— ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋ธ์„ `Item`, `ResponseMessage` ๋ชจ๋ธ๋กœ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + +### API ๋ฌธ์„œ { #api-docs } + +`/docs`๋กœ ์ด๋™ํ•˜๋ฉด, ์š”์ฒญ์œผ๋กœ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ์™€ ์‘๋‹ต์œผ๋กœ ๋ฐ›์„ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ **์Šคํ‚ค๋งˆ(schemas)**๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +์ด ์Šคํ‚ค๋งˆ๋Š” ์•ฑ์—์„œ ๋ชจ๋ธ๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ ์ •๋ณด๋Š” ์•ฑ์˜ **OpenAPI ์Šคํ‚ค๋งˆ**์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์ดํ›„ API ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + +OpenAPI์— ํฌํ•จ๋œ ๋ชจ๋ธ์˜ ๋™์ผํ•œ ์ •๋ณด๊ฐ€ **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑ**์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### Hey API { #hey-api } + +๋ชจ๋ธ์ด ํฌํ•จ๋œ FastAPI ์•ฑ์ด ์ค€๋น„๋˜๋ฉด, Hey API๋ฅผ ์‚ฌ์šฉํ•ด TypeScript ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋น ๋ฅธ ๋ฐฉ๋ฒ•์€ npx๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +์ด ๋ช…๋ น์€ `./src/client`์— TypeScript SDK๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +`@hey-api/openapi-ts` ์„ค์น˜ ๋ฐฉ๋ฒ•๊ณผ ์ƒ์„ฑ๋œ ๊ฒฐ๊ณผ๋ฌผ์€ ํ•ด๋‹น ์›น์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### SDK ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-sdk } + +์ด์ œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ importํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ์ด ์ œ๊ณต๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +๋ณด๋‚ผ ํŽ˜์ด๋กœ๋“œ์— ๋Œ€ํ•ด์„œ๋„ ์ž๋™ ์™„์„ฑ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค: + + + +/// tip | ํŒ + +`name`๊ณผ `price`์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ์€ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ `Item` ๋ชจ๋ธ์— ์ •์˜๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. + +/// + +์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ์ธ๋ผ์ธ ์˜ค๋ฅ˜๋„ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: + + + +์‘๋‹ต ๊ฐ์ฒด๋„ ์ž๋™ ์™„์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: + + + +## ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” FastAPI ์•ฑ { #fastapi-app-with-tags } + +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ FastAPI ์•ฑ์€ ๋” ์ปค์ง€๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ *path operations* ๊ทธ๋ฃน์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด **items** ์„น์…˜๊ณผ **users** ์„น์…˜์ด ์žˆ๊ณ , ์ด๋ฅผ ํƒœ๊ทธ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} + +### ํƒœ๊ทธ๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-tags } + +ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” FastAPI ์•ฑ์— ๋Œ€ํ•ด ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ํƒœ๊ทธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๋ฆฌ๋ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ํ•ญ๋ชฉ๋“ค์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ •๋ ฌ๋˜๊ณ  ๊ทธ๋ฃนํ™”๋ฉ๋‹ˆ๋‹ค: + + + +์ด ๊ฒฝ์šฐ ๋‹ค์Œ์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +* `ItemsService` +* `UsersService` + +### ํด๋ผ์ด์–ธํŠธ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ { #client-method-names } + +ํ˜„์žฌ `createItemItemsPost` ๊ฐ™์€ ์ƒ์„ฑ๋œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ๊ทธ๋‹ค์ง€ ๊น”๋”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...์ด๋Š” ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ ๊ฐ *path operation*์— ๋Œ€ํ•ด OpenAPI ๋‚ด๋ถ€์˜ **operation ID**๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +OpenAPI๋Š” ๋ชจ๋“  *path operations* ์ „์ฒด์—์„œ operation ID๊ฐ€ ๊ฐ๊ฐ ์œ ์ผํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ FastAPI๋Š” operation ID๊ฐ€ ์œ ์ผํ•˜๋„๋ก **ํ•จ์ˆ˜ ์ด๋ฆ„**, **๊ฒฝ๋กœ**, **HTTP method/operation**์„ ์กฐํ•ฉํ•ด operation ID๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋‹ค์Œ์—์„œ ์ด๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ + +## ์ปค์Šคํ…€ Operation ID์™€ ๋” ๋‚˜์€ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ { #custom-operation-ids-and-better-method-names } + +ํด๋ผ์ด์–ธํŠธ์—์„œ **๋” ๋‹จ์ˆœํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„**์„ ๊ฐ–๋„๋ก, operation ID๊ฐ€ **์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹**์„ **์ˆ˜์ •**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ operation ID๊ฐ€ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ๋„ **์œ ์ผ**ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ *path operation*์ด ํƒœ๊ทธ๋ฅผ ๊ฐ–๋„๋ก ํ•œ ๋‹ค์Œ, **ํƒœ๊ทธ**์™€ *path operation* **์ด๋ฆ„**(ํ•จ์ˆ˜ ์ด๋ฆ„)์„ ๊ธฐ๋ฐ˜์œผ๋กœ operation ID๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์œ ์ผ ID ์ƒ์„ฑ ํ•จ์ˆ˜ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• { #custom-generate-unique-id-function } + +FastAPI๋Š” ๊ฐ *path operation*์— ๋Œ€ํ•ด **์œ ์ผ ID**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋Š” **operation ID** ๋ฐ ์š”์ฒญ/์‘๋‹ต์— ํ•„์š”ํ•œ ์ปค์Šคํ…€ ๋ชจ๋ธ ์ด๋ฆ„์—๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +์ด ํ•จ์ˆ˜๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” `APIRoute`๋ฅผ ๋ฐ›์•„ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ํƒœ๊ทธ(๋Œ€๋ถ€๋ถ„ ํƒœ๊ทธ๋Š” ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค)์™€ *path operation* ์ด๋ฆ„(ํ•จ์ˆ˜ ์ด๋ฆ„)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ์ด ์ปค์Šคํ…€ ํ•จ์ˆ˜๋ฅผ `generate_unique_id_function` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ **FastAPI**์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} + +### ์ปค์Šคํ…€ Operation ID๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-custom-operation-ids } + +์ด์ œ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‹ค์‹œ ์ƒ์„ฑํ•˜๋ฉด, ๊ฐœ์„ ๋œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +๋ณด์‹œ๋‹ค์‹œํ”ผ, ์ด์ œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ํƒœ๊ทธ ๋‹ค์Œ์— ํ•จ์ˆ˜ ์ด๋ฆ„์ด ์˜ค๋ฉฐ, URL ๊ฒฝ๋กœ์™€ HTTP operation์˜ ์ •๋ณด๋Š” ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +### ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๋ฅผ ์œ„ํ•œ OpenAPI ์‚ฌ์–‘ ์ „์ฒ˜๋ฆฌ { #preprocess-the-openapi-specification-for-the-client-generator } + +์ƒ์„ฑ๋œ ์ฝ”๋“œ์—๋Š” ์—ฌ์ „ํžˆ ์ผ๋ถ€ **์ค‘๋ณต ์ •๋ณด**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +`ItemsService`(ํƒœ๊ทธ์—์„œ ๊ฐ€์ ธ์˜ด)์— ์ด๋ฏธ **items**๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด ์ด ๋ฉ”์„œ๋“œ๊ฐ€ items์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฉ”์„œ๋“œ ์ด๋ฆ„์—๋„ ํƒœ๊ทธ ์ด๋ฆ„์ด ์ ‘๋‘์‚ฌ๋กœ ๋ถ™์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜• + +OpenAPI ์ „๋ฐ˜์—์„œ๋Š” operation ID๊ฐ€ **์œ ์ผ**ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ด ๋ฐฉ์‹์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š”, ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ง์ „์— OpenAPI operation ID๋ฅผ **์ˆ˜์ •**ํ•ด์„œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋” ๋ณด๊ธฐ ์ข‹๊ณ  **๊น”๋”ํ•˜๊ฒŒ** ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +OpenAPI JSON์„ `openapi.json` ํŒŒ์ผ๋กœ ๋‹ค์šด๋กœ๋“œํ•œ ๋’ค, ์•„๋ž˜์™€ ๊ฐ™์€ ์Šคํฌ๋ฆฝํŠธ๋กœ **์ ‘๋‘์‚ฌ ํƒœ๊ทธ๋ฅผ ์ œ๊ฑฐ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/generate_clients/tutorial004_py39.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด operation ID๊ฐ€ `items-get_items` ๊ฐ™์€ ํ˜•ํƒœ์—์„œ `get_items`๋กœ ๋ณ€๊ฒฝ๋˜์–ด, ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ ๋” ๋‹จ์ˆœํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์ „์ฒ˜๋ฆฌ๋œ OpenAPI๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-the-preprocessed-openapi } + +์ด์ œ ์ตœ์ข… ๊ฒฐ๊ณผ๊ฐ€ `openapi.json` ํŒŒ์ผ์— ์žˆ์œผ๋ฏ€๋กœ, ์ž…๋ ฅ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +์ƒˆ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” **๊น”๋”ํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„**์„ ๊ฐ€์ง€๋ฉด์„œ๋„, **์ž๋™ ์™„์„ฑ**, **์ธ๋ผ์ธ ์˜ค๋ฅ˜** ๋“ฑ์€ ๊ทธ๋Œ€๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค: + + + +## ์žฅ์  { #benefits } + +์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์— ๋Œ€ํ•ด **์ž๋™ ์™„์„ฑ**์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* ๋ฉ”์„œ๋“œ +* ๋ณธ๋ฌธ(body)์˜ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ, ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ +* ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ + +๋˜ํ•œ ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด **์ธ๋ผ์ธ ์˜ค๋ฅ˜**๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ๋’ค ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ **์žฌ์ƒ์„ฑ(regenerate)**ํ•˜๋ฉด, ์ƒˆ *path operations*๊ฐ€ ๋ฉ”์„œ๋“œ๋กœ ์ถ”๊ฐ€๋˜๊ณ  ๊ธฐ์กด ๊ฒƒ์€ ์ œ๊ฑฐ๋˜๋ฉฐ, ๊ทธ ๋ฐ–์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๐Ÿค“ + +์ด๋Š” ๋ฌด์–ธ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ ๋ณ€๊ฒฝ์ด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—๋„ ์ž๋™์œผ๋กœ **๋ฐ˜์˜**๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๋ฅผ **๋นŒ๋“œ(build)**ํ•˜๋ฉด ์‚ฌ์šฉ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ **๋ถˆ์ผ์น˜(mismatch)**ํ•  ๊ฒฝ์šฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋…ธ์ถœ๋œ ๋’ค ๋ฌธ์ œ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋Œ€์‹ , ๊ฐœ๋ฐœ ์‚ฌ์ดํด ์ดˆ๊ธฐ์— **๋งŽ์€ ์˜ค๋ฅ˜๋ฅผ ๋งค์šฐ ๋นจ๋ฆฌ ๊ฐ์ง€**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ diff --git a/docs/ko/docs/advanced/middleware.md b/docs/ko/docs/advanced/middleware.md new file mode 100644 index 0000000000..be2c972a6b --- /dev/null +++ b/docs/ko/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# ๊ณ ๊ธ‰ Middleware { #advanced-middleware } + +๋ฉ”์ธ ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— [์ปค์Šคํ…€ Middleware](../tutorial/middleware.md){.internal-link target=_blank}๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  [`CORSMiddleware`๋กœ CORS ์ฒ˜๋ฆฌํ•˜๊ธฐ](../tutorial/cors.md){.internal-link target=_blank}๋„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. + +์ด ์„น์…˜์—์„œ๋Š” ๋‹ค๋ฅธ middleware๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ASGI middleware ์ถ”๊ฐ€ํ•˜๊ธฐ { #adding-asgi-middlewares } + +**FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ASGI ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ์–ด๋–ค ASGI middleware๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ASGI ์‚ฌ์–‘์„ ๋”ฐ๋ฅด๊ธฐ๋งŒ ํ•˜๋ฉด, FastAPI๋‚˜ Starlette๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ middleware๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์œผ๋กœ ASGI middleware๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ASGI ์•ฑ์„ ๋ฐ›๋„๋ก ๊ธฐ๋Œ€ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ์„œ๋“œํŒŒํ‹ฐ ASGI middleware ๋ฌธ์„œ์—์„œ๋Š” ์•„๋งˆ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ผ๊ณ  ์•ˆ๋‚ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +ํ•˜์ง€๋งŒ FastAPI(์ •ํ™•ํžˆ๋Š” Starlette)๋Š” ๋” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋‚ด๋ถ€ middleware๊ฐ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด(๊ทธ๋ฆฌ๊ณ  CORS ์˜ˆ์ œ์—์„œ์ฒ˜๋Ÿผ) `app.add_middleware()`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()`๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ middleware ํด๋ž˜์Šค๋ฅผ ๋ฐ›๊ณ , ๊ทธ ๋’ค์—๋Š” middleware์— ์ „๋‹ฌํ•  ์ถ”๊ฐ€ ์ธ์ž๋“ค์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. + +## ํ†ตํ•ฉ middleware { #integrated-middlewares } + +**FastAPI**์—๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ middleware๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์—์„œ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” `from starlette.middleware.something import SomethingMiddleware`๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž ํŽธ์˜๋ฅผ ์œ„ํ•ด `fastapi.middleware`์— ์—ฌ๋Ÿฌ middleware๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ middleware๋Š” Starlette์—์„œ ์ง์ ‘ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์ด `https` ๋˜๋Š” `wss`์—ฌ์•ผ ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค. + +`http` ๋˜๋Š” `ws`๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ ๋Œ€์‹  ๋ณด์•ˆ ์Šคํ‚ด์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +HTTP Host Header ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด, ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋œ `Host` ํ—ค๋”๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} + +๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: + +* `allowed_hosts` - ํ˜ธ์ŠคํŠธ๋ช…์œผ๋กœ ํ—ˆ์šฉํ•  ๋„๋ฉ”์ธ ์ด๋ฆ„ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. `*.example.com` ๊ฐ™์€ ์™€์ผ๋“œ์นด๋“œ ๋„๋ฉ”์ธ์œผ๋กœ ์„œ๋ธŒ๋„๋ฉ”์ธ์„ ๋งค์นญํ•˜๋Š” ๊ฒƒ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ํ˜ธ์ŠคํŠธ๋ช…์ด๋“  ํ—ˆ์šฉํ•˜๋ ค๋ฉด `allowed_hosts=["*"]`๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ middleware๋ฅผ ์ƒ๋žตํ•˜์„ธ์š”. +* `www_redirect` - True๋กœ ์„ค์ •ํ•˜๋ฉด, ํ—ˆ์šฉ๋œ ํ˜ธ์ŠคํŠธ์˜ non-www ๋ฒ„์ „์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ www ๋ฒ„์ „์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `True`์ž…๋‹ˆ๋‹ค. + +๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ฒ€์ฆ๋˜์ง€ ์•Š์œผ๋ฉด `400` ์‘๋‹ต์ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค. + +## `GZipMiddleware` { #gzipmiddleware } + +`Accept-Encoding` ํ—ค๋”์— `"gzip"`์ด ํฌํ•จ๋œ ์–ด๋–ค ์š”์ฒญ์ด๋“  GZip ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +์ด middleware๋Š” ์ผ๋ฐ˜ ์‘๋‹ต๊ณผ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} + +๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: + +* `minimum_size` - ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ง€์ •ํ•œ ์ตœ์†Œ ํฌ๊ธฐ๋ณด๋‹ค ์ž‘์€ ์‘๋‹ต์€ GZip์œผ๋กœ ์••์ถ•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `500`์ž…๋‹ˆ๋‹ค. +* `compresslevel` - GZip ์••์ถ• ์ค‘์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 1๋ถ€ํ„ฐ 9๊นŒ์ง€์˜ ์ •์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `9`์ž…๋‹ˆ๋‹ค. ๊ฐ’์ด ๋‚ฎ์„์ˆ˜๋ก ์••์ถ•์€ ๋” ๋น ๋ฅด์ง€๋งŒ ํŒŒ์ผ ํฌ๊ธฐ๋Š” ๋” ์ปค์ง€๊ณ , ๊ฐ’์ด ๋†’์„์ˆ˜๋ก ์••์ถ•์€ ๋” ๋А๋ฆฌ์ง€๋งŒ ํŒŒ์ผ ํฌ๊ธฐ๋Š” ๋” ์ž‘์•„์ง‘๋‹ˆ๋‹ค. + +## ๋‹ค๋ฅธ middleware { #other-middlewares } + +๋‹ค๋ฅธ ASGI middleware๋„ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด: + +* Uvicorn์˜ `ProxyHeadersMiddleware` +* MessagePack + +์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ middleware๋ฅผ ๋ณด๋ ค๋ฉด Starlette์˜ Middleware ๋ฌธ์„œ์™€ ASGI Awesome List๋ฅผ ํ™•์ธํ•˜์„ธ์š”. diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..e4bdea9d6c --- /dev/null +++ b/docs/ko/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI ์ฝœ๋ฐฑ { #openapi-callbacks } + +๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  *external API*(์•„๋งˆ๋„ ๋‹น์‹ ์˜ API๋ฅผ *์‚ฌ์šฉ*ํ•  ๋™์ผํ•œ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์š”์ฒญ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“œ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ง„ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹น์‹ ์˜ API ์•ฑ์ด *external API*๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ผ์–ด๋‚˜๋Š” ๊ณผ์ •์„ "callback"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋‹น์‹ ์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๋‹ค์Œ, ๋‹น์‹ ์˜ API๊ฐ€ ๋‹ค์‹œ *external API*๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด *๋˜๋Œ๋ ค ํ˜ธ์ถœ*ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์•„๋งˆ๋„ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  API์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค). + +์ด ๊ฒฝ์šฐ, ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๋Š”์ง€, ์–ด๋–ค body๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š”์ง€, ์–ด๋–ค ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ๋“ฑ์ž…๋‹ˆ๋‹ค. + +## ์ฝœ๋ฐฑ์ด ์žˆ๋Š” ์•ฑ { #an-app-with-callbacks } + +์˜ˆ์‹œ๋กœ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์•ฑ์„ ๊ฐœ๋ฐœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด์„ธ์š”. + +์ด ์ฒญ๊ตฌ์„œ๋Š” `id`, `title`(์„ ํƒ ์‚ฌํ•ญ), `customer`, `total`์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. + +๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๋Š” POST ์š”์ฒญ์œผ๋กœ ๋‹น์‹ ์˜ API์—์„œ ์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ๋‹น์‹ ์˜ API๋Š”(๊ฐ€์ •ํ•ด ๋ณด๋ฉด): + +* ์ฒญ๊ตฌ์„œ๋ฅผ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ณ ๊ฐ์—๊ฒŒ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. +* ๋ˆ์„ ์ˆ˜๊ธˆํ•ฉ๋‹ˆ๋‹ค. +* API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)์˜ API๋กœ ๋‹ค์‹œ ์•Œ๋ฆผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + * ์ด๋Š” (๋‹น์‹ ์˜ API์—์„œ) ๊ทธ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์–ด๋–ค *external API*๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค(์ด๊ฒƒ์ด "callback"์ž…๋‹ˆ๋‹ค). + +## ์ผ๋ฐ˜์ ์ธ **FastAPI** ์•ฑ { #the-normal-fastapi-app } + +๋จผ์ € ์ฝœ๋ฐฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „, ์ผ๋ฐ˜์ ์ธ API ์•ฑ์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +`Invoice` body๋ฅผ ๋ฐ›๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€, ์ฝœ๋ฐฑ์„ ์œ„ํ•œ URL์„ ๋‹ด๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ `callback_url`์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด ๋ถ€๋ถ„์€ ๊ฝค ์ผ๋ฐ˜์ ์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ๋Š” ์ด๋ฏธ ์ต์ˆ™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | ํŒ + +`callback_url` ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” Pydantic์˜ Url ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// + +์œ ์ผํ•˜๊ฒŒ ์ƒˆ๋กœ์šด ๊ฒƒ์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์˜ ์ธ์ž๋กœ `callbacks=invoices_callback_router.routes`๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ๋‹ค์Œ์—์„œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์ฝœ๋ฐฑ ๋ฌธ์„œํ™”ํ•˜๊ธฐ { #documenting-the-callback } + +์‹ค์ œ ์ฝœ๋ฐฑ ์ฝ”๋“œ๋Š” ๋‹น์‹ ์˜ API ์•ฑ์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์•ฑ๋งˆ๋‹ค ๋งŽ์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ์ฒ˜๋Ÿผ ํ•œ๋‘ ์ค„์˜ ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +ํ•˜์ง€๋งŒ ์ฝœ๋ฐฑ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€, ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์ฝœ๋ฐฑ ์š”์ฒญ body๋กœ *๋‹น์‹ ์˜ API*๊ฐ€ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ ๋“ฑ์— ๋งž์ถฐ *external API*๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ๋‹ค์Œ์œผ๋กœ ํ•  ์ผ์€, *๋‹น์‹ ์˜ API*์—์„œ ๋ณด๋‚ด๋Š” ์ฝœ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ ๋ฌธ์„œ๋Š” ๋‹น์‹ ์˜ API์—์„œ `/docs`์˜ Swagger UI์— ํ‘œ์‹œ๋˜๋ฉฐ, ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์ด *external API*๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +์ด ์˜ˆ์‹œ๋Š” ์ฝœ๋ฐฑ ์ž์ฒด(ํ•œ ์ค„ ์ฝ”๋“œ๋กœ๋„ ๋  ์ˆ˜ ์žˆ์Œ)๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ๋ฌธ์„œํ™” ๋ถ€๋ถ„๋งŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์‹ค์ œ ์ฝœ๋ฐฑ์€ ๋‹จ์ง€ HTTP ์š”์ฒญ์ž…๋‹ˆ๋‹ค. + +์ฝœ๋ฐฑ์„ ์ง์ ‘ ๊ตฌํ˜„ํ•  ๋•Œ๋Š” HTTPX๋‚˜ Requests ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## ์ฝœ๋ฐฑ ๋ฌธ์„œํ™” ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ { #write-the-callback-documentation-code } + +์ด ์ฝ”๋“œ๋Š” ์•ฑ์—์„œ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ *๋ฌธ์„œํ™”*ํ•˜๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ **FastAPI**๋กœ API์˜ ์ž๋™ ๋ฌธ์„œ๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ๊ทธ์™€ ๊ฐ™์€ ์ง€์‹์„ ์‚ฌ์šฉํ•ด *external API*๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒจ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค... ์ฆ‰ ์™ธ๋ถ€ API๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(๋‹น์‹ ์˜ API๊ฐ€ ํ˜ธ์ถœํ•  ๊ฒƒ๋“ค)์„ ๋งŒ๋“ค์–ด์„œ ๋ง์ž…๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ฝœ๋ฐฑ์„ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š”, ์ž์‹ ์ด ๊ทธ *์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž*๋ผ๊ณ  ์ƒ์ƒํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ์€ *๋‹น์‹ ์˜ API*๊ฐ€ ์•„๋‹ˆ๋ผ *external API*๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”. + +์ด ๊ด€์ (์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ด€์ )์„ ์ž ์‹œ ์ฑ„ํƒํ•˜๋ฉด, ๊ทธ *external API*๋ฅผ ์œ„ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ, body์šฉ Pydantic ๋ชจ๋ธ, ์‘๋‹ต ๋“ฑ์„ ์–ด๋””์— ๋‘์–ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +### ์ฝœ๋ฐฑ `APIRouter` ์ƒ์„ฑํ•˜๊ธฐ { #create-a-callback-apirouter } + +๋จผ์ € ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฝœ๋ฐฑ์„ ๋‹ด์„ ์ƒˆ `APIRouter`๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### ์ฝœ๋ฐฑ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ƒ์„ฑํ•˜๊ธฐ { #create-the-callback-path-operation } + +์ฝœ๋ฐฑ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ์œ„์—์„œ ๋งŒ๋“  ๋™์ผํ•œ `APIRouter`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์ธ FastAPI *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์ฒ˜๋Ÿผ ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +* ์•„๋งˆ๋„ ๋ฐ›์•„์•ผ ํ•  body ์„ ์–ธ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ: `body: InvoiceEvent`). +* ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•  ์‘๋‹ต ์„ ์–ธ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: `response_model=InvoiceEventReceived`). + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +์ผ๋ฐ˜์ ์ธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€์˜ ์ฃผ์š” ์ฐจ์ด์ ์€ 2๊ฐ€์ง€์ž…๋‹ˆ๋‹ค: + +* ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์งˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์˜ ์•ฑ์€ ์ด ์ฝ”๋“œ๋ฅผ ์ ˆ๋Œ€ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” *external API*๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋Š” ๊ทธ๋ƒฅ `pass`๋งŒ ์žˆ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. +* *path*์—๋Š” OpenAPI 3 expression(์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ๊ณ )์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด *๋‹น์‹ ์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ผ๋ถ€ ๊ฐ’์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์ฝœ๋ฐฑ ๊ฒฝ๋กœ ํ‘œํ˜„์‹ { #the-callback-path-expression } + +์ฝœ๋ฐฑ *path*๋Š” *๋‹น์‹ ์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ์ผ๋ถ€๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” OpenAPI 3 expression์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ, ๋‹ค์Œ `str`์ž…๋‹ˆ๋‹ค: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +๋”ฐ๋ผ์„œ ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ *๋‹น์‹ ์˜ API*๋กœ ๋‹ค์Œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ : + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +JSON body๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๋ฉด: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +๊ทธ๋Ÿฌ๋ฉด *๋‹น์‹ ์˜ API*๋Š” ์ฒญ๊ตฌ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—์„œ `callback_url`(์ฆ‰ *external API*)๋กœ ์ฝœ๋ฐฑ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค: + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ JSON body๋ฅผ ํฌํ•จํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +๋˜ํ•œ ๊ทธ *external API*๋กœ๋ถ€ํ„ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ JSON body ์‘๋‹ต์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค: + +```JSON +{ + "ok": true +} +``` + +/// tip | ํŒ + +์ฝœ๋ฐฑ URL์—๋Š” `callback_url` ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ URL(`https://www.external.org/events`)๋ฟ ์•„๋‹ˆ๋ผ, JSON body ์•ˆ์˜ ์ฒญ๊ตฌ์„œ `id`(`2expen51ve`)๋„ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + +/// + +### ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-the-callback-router } + +์ด ์‹œ์ ์—์„œ, ์œ„์—์„œ ๋งŒ๋“  ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ ์•ˆ์— *์ฝœ๋ฐฑ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(์ฆ‰ *external developer*๊ฐ€ *external API*์— ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค)์„ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. + +์ด์ œ *๋‹น์‹ ์˜ API ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ `callbacks` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด, ๊ทธ ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ์˜ `.routes` ์†์„ฑ(์‹ค์ œ๋กœ๋Š” routes/*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `list`)์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | ํŒ + +`callback=`์— ๋ผ์šฐํ„ฐ ์ž์ฒด(`invoices_callback_router`)๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, `invoices_callback_router.routes`์ฒ˜๋Ÿผ `.routes` ์†์„ฑ์„ ๋„˜๊ธด๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + +/// + +### ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #check-the-docs } + +์ด์ œ ์•ฑ์„ ์‹คํ–‰ํ•˜๊ณ  http://127.0.0.1:8000/docs๋กœ ์ด๋™ํ•˜์„ธ์š”. + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด "Callbacks" ์„น์…˜์„ ํฌํ•จํ•œ ๋ฌธ์„œ๊ฐ€ ํ‘œ์‹œ๋˜๋ฉฐ, *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + diff --git a/docs/ko/docs/advanced/openapi-webhooks.md b/docs/ko/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..89cacf7b78 --- /dev/null +++ b/docs/ko/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhooks { #openapi-webhooks } + +์•ฑ์ด ์–ด๋–ค ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ (์š”์ฒญ์„ ๋ณด๋‚ด์„œ) *์‚ฌ์šฉ์ž์˜* ์•ฑ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ณ , ๋ณดํ†ต ์–ด๋–ค **์ด๋ฒคํŠธ**๋ฅผ **์•Œ๋ฆฌ๊ธฐ** ์œ„ํ•ด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ API **์‚ฌ์šฉ์ž**์—๊ฒŒ ์•Œ๋ ค์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ผ๋ฐ˜์ ์ธ ๊ณผ์ • ๋Œ€์‹ , **์—ฌ๋Ÿฌ๋ถ„์˜ API**(๋˜๋Š” ์•ฑ)๊ฐ€ **์‚ฌ์šฉ์ž์˜ ์‹œ์Šคํ…œ**(์‚ฌ์šฉ์ž์˜ API, ์‚ฌ์šฉ์ž์˜ ์•ฑ)์œผ๋กœ **์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค**๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. + +์ด๋ฅผ ๋ณดํ†ต **webhook**์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. + +## Webhooks ๋‹จ๊ณ„ { #webhooks-steps } + +์ผ๋ฐ˜์ ์ธ ๊ณผ์ •์€, ์—ฌ๋Ÿฌ๋ถ„์ด ์ฝ”๋“œ์—์„œ ๋ณด๋‚ผ ๋ฉ”์‹œ์ง€, ์ฆ‰ **์š”์ฒญ ๋ณธ๋ฌธ(body)**์ด ๋ฌด์—‡์ธ์ง€ **์ •์˜**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์–ด๋–ค **์‹œ์ **์— ๊ทธ ์š”์ฒญ(๋˜๋Š” ์ด๋ฒคํŠธ)์„ ๋ณด๋‚ผ์ง€๋„ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  **์‚ฌ์šฉ์ž**๋Š” (์˜ˆ: ์–ด๋”˜๊ฐ€์˜ ์›น ๋Œ€์‹œ๋ณด๋“œ์—์„œ) ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๊ทธ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•  **URL**์„ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + +webhook์˜ URL์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์‹ค์ œ๋กœ ๊ทธ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋ชจ๋“  **๋กœ์ง**์€ ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. **์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ**์—์„œ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. + +## **FastAPI**์™€ OpenAPI๋กœ webhooks ๋ฌธ์„œํ™”ํ•˜๊ธฐ { #documenting-webhooks-with-fastapi-and-openapi } + +**FastAPI**์—์„œ๋Š” OpenAPI๋ฅผ ์‚ฌ์šฉํ•ด, ์ด๋Ÿฌํ•œ webhook์˜ ์ด๋ฆ„, ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” HTTP ์ž‘์—… ํƒ€์ž…(์˜ˆ: `POST`, `PUT` ๋“ฑ), ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๋ณด๋‚ผ ์š”์ฒญ **๋ณธ๋ฌธ(body)**์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ **webhook** ์š”์ฒญ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด **์ž์‹ ๋“ค์˜ API๋ฅผ ๊ตฌํ˜„**ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›Œ์ง€๊ณ , ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ์ž์‹ ์˜ API ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +Webhooks๋Š” OpenAPI 3.1.0 ์ด์ƒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI `0.99.0` ์ด์ƒ์—์„œ ์ง€์›๋ฉ๋‹ˆ๋‹ค. + +/// + +## webhooks๊ฐ€ ์žˆ๋Š” ์•ฑ { #an-app-with-webhooks } + +**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ(์˜ˆ: `@app.webhooks.post()`), *webhooks*๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” `webhooks` ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} + +์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ webhook์€ **OpenAPI** ์Šคํ‚ค๋งˆ์™€ ์ž๋™ **docs UI**์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +`app.webhooks` ๊ฐ์ฒด๋Š” ์‹ค์ œ๋กœ `APIRouter`์ผ ๋ฟ์ด๋ฉฐ, ์—ฌ๋Ÿฌ ํŒŒ์ผ๋กœ ์•ฑ์„ ๊ตฌ์กฐํ™”ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํƒ€์ž…์ž…๋‹ˆ๋‹ค. + +/// + +webhook์—์„œ๋Š” ์‹ค์ œ๋กœ(`/items/` ๊ฐ™์€) *๊ฒฝ๋กœ(path)*๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ๊ทธ๊ณณ์— ์ „๋‹ฌํ•˜๋Š” ํ…์ŠคํŠธ๋Š” webhook์˜ **์‹๋ณ„์ž**(์ด๋ฒคํŠธ ์ด๋ฆ„)์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `@app.webhooks.post("new-subscription")`์—์„œ webhook ์ด๋ฆ„์€ `new-subscription`์ž…๋‹ˆ๋‹ค. + +์ด๋Š” **์‚ฌ์šฉ์ž**๊ฐ€ webhook ์š”์ฒญ์„ ๋ฐ›๊ณ  ์‹ถ์€ ์‹ค์ œ **URL ๊ฒฝ๋กœ**๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹(์˜ˆ: ์›น ๋Œ€์‹œ๋ณด๋“œ)์œผ๋กœ ์ •์˜ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +### ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #check-the-docs } + +์ด์ œ ์•ฑ์„ ์‹คํ–‰ํ•˜๊ณ  http://127.0.0.1:8000/docs๋กœ ์ด๋™ํ•˜์„ธ์š”. + +๋ฌธ์„œ์— ์ผ๋ฐ˜์ ์ธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ๋ณด์ด๊ณ , ์ด์ œ๋Š” ์ผ๋ถ€ **webhooks**๋„ ํ•จ๊ป˜ ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค: + + diff --git a/docs/ko/docs/advanced/path-operation-advanced-configuration.md b/docs/ko/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000..f20fa6d263 --- /dev/null +++ b/docs/ko/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,172 @@ +# ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ณ ๊ธ‰ ๊ตฌ์„ฑ { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | ๊ฒฝ๊ณ  + +OpenAPI โ€œ์ „๋ฌธ๊ฐ€โ€๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ์•„๋งˆ ์ด ๋‚ด์šฉ์€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// + +๋งค๊ฐœ๋ณ€์ˆ˜ `operation_id`๋ฅผ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์‚ฌ์šฉํ•  OpenAPI `operationId`๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ ์ž‘์—…๋งˆ๋‹ค ๊ณ ์œ ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} + +### *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ์ด๋ฆ„์„ operationId๋กœ ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-path-operation-function-name-as-the-operationid } + +API์˜ ํ•จ์ˆ˜ ์ด๋ฆ„์„ `operationId`๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋ชจ๋“  API๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ `APIRoute.name`์„ ์‚ฌ์šฉํ•ด ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `operation_id`๋ฅผ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ชจ๋“  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} + +/// tip | ํŒ + +`app.openapi()`๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด, ๊ทธ ์ „์— `operationId`๋“ค์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// warning | ๊ฒฝ๊ณ  + +์ด๋ ‡๊ฒŒ ํ•  ๊ฒฝ์šฐ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ์ด๋ฆ„์ด ๊ณ ์œ ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์„œ๋กœ ๋‹ค๋ฅธ ๋ชจ๋“ˆ(ํŒŒ์ด์ฌ ํŒŒ์ผ)์— ์žˆ์–ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. + +/// + +## OpenAPI์—์„œ ์ œ์™ธํ•˜๊ธฐ { #exclude-from-openapi } + +์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ(๋”ฐ๋ผ์„œ ์ž๋™ ๋ฌธ์„œํ™” ์‹œ์Šคํ…œ)์—์„œ ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด, `include_in_schema` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `False`๋กœ ์„ค์ •ํ•˜์„ธ์š”: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} + +## docstring์—์„œ ๊ณ ๊ธ‰ ์„ค๋ช… ๊ฐ€์ ธ์˜ค๊ธฐ { #advanced-description-from-docstring } + +OpenAPI์— ์‚ฌ์šฉํ•  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ docstring ์ค„ ์ˆ˜๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`\f`(์ด์Šค์ผ€์ดํ”„๋œ "form feed" ๋ฌธ์ž)๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด **FastAPI**๋Š” ์ด ์ง€์ ์—์„œ OpenAPI์— ์‚ฌ์šฉํ•  ์ถœ๋ ฅ ๋‚ด์šฉ์„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค. + +๋ฌธ์„œ์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š์ง€๋งŒ, Sphinx ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ๋Š” ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## ์ถ”๊ฐ€ ์‘๋‹ต { #additional-responses } + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด `response_model`๊ณผ `status_code`๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ๋ณด์…จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ๊ธฐ๋ณธ ์‘๋‹ต์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + +๋ชจ๋ธ, ์ƒํƒœ ์ฝ”๋“œ ๋“ฑ๊ณผ ํ•จ๊ป˜ ์ถ”๊ฐ€ ์‘๋‹ต๋„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด์— ๋Œ€ํ•œ ๋ฌธ์„œ์˜ ์ „์ฒด ์žฅ์ด ์žˆ์œผ๋‹ˆ, [OpenAPI์˜ ์ถ”๊ฐ€ ์‘๋‹ต](additional-responses.md){.internal-link target=_blank}์—์„œ ์ฝ์–ด๋ณด์„ธ์š”. + +## OpenAPI Extra { #openapi-extra } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์„ ์–ธํ•˜๋ฉด, **FastAPI**๋Š” OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋  ํ•ด๋‹น *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ๊ด€๋ จ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +OpenAPI ๋ช…์„ธ์—์„œ๋Š” ์ด๋ฅผ Operation Object๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. + +/// + +์—ฌ๊ธฐ์—๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ž๋™ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +`tags`, `parameters`, `requestBody`, `responses` ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ „์šฉ OpenAPI ์Šคํ‚ค๋งˆ๋Š” ๋ณดํ†ต **FastAPI**๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์ง€๋งŒ, ํ™•์žฅํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ด๋Š” ์ €์ˆ˜์ค€ ํ™•์žฅ ์ง€์ ์ž…๋‹ˆ๋‹ค. + +์ถ”๊ฐ€ ์‘๋‹ต๋งŒ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค๋ฉด, ๋” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์€ [OpenAPI์˜ ์ถ”๊ฐ€ ์‘๋‹ต](additional-responses.md){.internal-link target=_blank}์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// + +`openapi_extra` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### OpenAPI ํ™•์žฅ { #openapi-extensions } + +์˜ˆ๋ฅผ ๋“ค์–ด `openapi_extra`๋Š” [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} + +์ž๋™ API ๋ฌธ์„œ๋ฅผ ์—ด๋ฉด, ํ•ด๋‹น ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ํ•˜๋‹จ์— ํ™•์žฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + + + +๋˜ํ•œ API์˜ `/openapi.json`์—์„œ ๊ฒฐ๊ณผ OpenAPI๋ฅผ ๋ณด๋ฉด, ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ์ผ๋ถ€๋กœ ํ™•์žฅ์ด ํฌํ•จ๋œ ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์Šคํ‚ค๋งˆ { #custom-openapi-path-operation-schema } + +`openapi_extra`์˜ ๋”•์…”๋„ˆ๋ฆฌ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ์™€ ๊นŠ๊ฒŒ ๋ณ‘ํ•ฉ๋ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์ž๋™ ์ƒ์„ฑ๋œ ์Šคํ‚ค๋งˆ์— ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด Pydantic๊ณผ ํ•จ๊ป˜ FastAPI์˜ ์ž๋™ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ž์ฒด ์ฝ”๋“œ๋กœ ์š”์ฒญ์„ ์ฝ๊ณ  ๊ฒ€์ฆํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, OpenAPI ์Šคํ‚ค๋งˆ์—๋Š” ์—ฌ์ „ํžˆ ๊ทธ ์š”์ฒญ์„ ์ •์˜ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿด ๋•Œ `openapi_extra`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} + +์ด ์˜ˆ์‹œ์—์„œ๋Š” ์–ด๋–ค Pydantic ๋ชจ๋ธ๋„ ์„ ์–ธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์š”์ฒญ ๋ฐ”๋””๋Š” JSON์œผ๋กœ parsed๋˜์ง€๋„ ์•Š๊ณ , `bytes`๋กœ ์ง์ ‘ ์ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ `magic_data_reader()`๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ด๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์š”์ฒญ ๋ฐ”๋””์— ๋Œ€ํ•ด ๊ธฐ๋Œ€ํ•˜๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI ์ฝ˜ํ…์ธ  ํƒ€์ž… { #custom-openapi-content-type } + +๊ฐ™์€ ํŠธ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด, Pydantic ๋ชจ๋ธ์„ ์ด์šฉํ•ด JSON Schema๋ฅผ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI ์Šคํ‚ค๋งˆ ์„น์…˜์— ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์š”์ฒญ์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด JSON์ด ์•„๋‹ˆ๋”๋ผ๋„ ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” Pydantic ๋ชจ๋ธ์—์„œ JSON Schema๋ฅผ ์ถ”์ถœํ•˜๋Š” FastAPI์˜ ํ†ตํ•ฉ ๊ธฐ๋Šฅ๋„, JSON์— ๋Œ€ํ•œ ์ž๋™ ๊ฒ€์ฆ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์š”์ฒญ ์ฝ˜ํ…์ธ  ํƒ€์ž…์„ JSON์ด ์•„๋‹ˆ๋ผ YAML๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} + +๊ทธ๋Ÿผ์—๋„ ๊ธฐ๋ณธ ํ†ตํ•ฉ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, YAML๋กœ ๋ฐ›๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ JSON Schema๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Pydantic ๋ชจ๋ธ์„ ์—ฌ์ „ํžˆ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ์š”์ฒญ์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ณ , ๋ฐ”๋””๋ฅผ `bytes`๋กœ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” FastAPI๊ฐ€ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ๋ฅผ JSON์œผ๋กœ ํŒŒ์‹ฑํ•˜๋ ค๊ณ  ์‹œ๋„์กฐ์ฐจ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์—์„œ YAML ์ฝ˜ํ…์ธ ๋ฅผ ์ง์ ‘ ํŒŒ์‹ฑํ•œ ๋’ค, ๋‹ค์‹œ ๊ฐ™์€ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด YAML ์ฝ˜ํ…์ธ ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} + +/// tip | ํŒ + +์—ฌ๊ธฐ์„œ๋Š” ๊ฐ™์€ Pydantic ๋ชจ๋ธ์„ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// diff --git a/docs/ko/docs/advanced/security/http-basic-auth.md b/docs/ko/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..611aad7956 --- /dev/null +++ b/docs/ko/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ์—๋Š” HTTP Basic Auth๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +HTTP Basic Auth์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋“ค์–ด ์žˆ๋Š” ํ—ค๋”๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๋ฉด HTTP 401 "Unauthorized" ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๊ฐ’์ด `Basic`์ด๊ณ  ์„ ํƒ์ ์œผ๋กœ `realm` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” `WWW-Authenticate` ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ํ†ตํ•ฉ ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ‘œ์‹œํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค. + +๊ทธ๋‹ค์Œ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด๋‹น ๊ฐ’์„ ํ—ค๋”์— ๋‹ด์•„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + +## ๊ฐ„๋‹จํ•œ HTTP Basic Auth { #simple-http-basic-auth } + +* `HTTPBasic`๊ณผ `HTTPBasicCredentials`๋ฅผ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค. +* `HTTPBasic`์„ ์‚ฌ์šฉํ•ด "`security` scheme"์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. +* *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ dependency๋กœ ํ•ด๋‹น `security`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +* `HTTPBasicCredentials` ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค: + * ์ „์†ก๋œ `username`๊ณผ `password`๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} + +์ฒ˜์Œ์œผ๋กœ URL์„ ์—ด์–ด๋ณด๋ฉด(๋˜๋Š” ๋ฌธ์„œ์—์„œ "Execute" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด) ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฌผ์–ด๋ด…๋‹ˆ๋‹ค: + + + +## ์‚ฌ์šฉ์ž๋ช… ํ™•์ธํ•˜๊ธฐ { #check-the-username } + +๋” ์™„์ „ํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. + +dependency๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜์„ธ์š”. + +์ด๋ฅผ ์œ„ํ•ด Python ํ‘œ์ค€ ๋ชจ๋“ˆ `secrets`๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + +`secrets.compare_digest()`๋Š” `bytes` ๋˜๋Š” ASCII ๋ฌธ์ž(์˜์–ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž)๋งŒ ํฌํ•จํ•œ `str`์„ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, `Sebastiรกn`์˜ `รก` ๊ฐ™์€ ๋ฌธ์ž๊ฐ€ ์žˆ์œผ๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € `username`๊ณผ `password`๋ฅผ UTF-8๋กœ ์ธ์ฝ”๋”ฉํ•ด์„œ `bytes`๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๋‹ค์Œ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•ด `credentials.username`์ด `"stanleyjobson"`์ด๊ณ  `credentials.password`๊ฐ€ `"swordfish"`์ธ์ง€ ํ™•์‹คํžˆ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} + +์ด๋Š” ๋‹ค์Œ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Return some error + ... +``` + +ํ•˜์ง€๋งŒ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด "timing attacks"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ํ•œ ์œ ํ˜•์˜ ๊ณต๊ฒฉ์— ๋Œ€ํ•ด ์•ˆ์ „ํ•ด์ง‘๋‹ˆ๋‹ค. + +### Timing Attacks { #timing-attacks } + +๊ทธ๋ ‡๋‹ค๋ฉด "timing attack"์ด๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? + +๊ณต๊ฒฉ์ž๋“ค์ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ถ”์ธกํ•˜๋ ค๊ณ  ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋ช… `johndoe`, ๋น„๋ฐ€๋ฒˆํ˜ธ `love123`์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฌ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Python ์ฝ”๋“œ๋Š” ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +ํ•˜์ง€๋งŒ Python์ด `johndoe`์˜ ์ฒซ ๊ธ€์ž `j`๋ฅผ `stanleyjobson`์˜ ์ฒซ ๊ธ€์ž `s`์™€ ๋น„๊ตํ•˜๋Š” ์ˆœ๊ฐ„, ๋‘ ๋ฌธ์ž์—ด์ด ๊ฐ™์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์ด๋ฏธ ์•Œ๊ฒŒ ๋˜์–ด `False`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” โ€œ๋‚˜๋จธ์ง€ ๊ธ€์ž๋“ค์„ ๋น„๊ตํ•˜๋А๋ผ ๊ณ„์‚ฐ์„ ๋” ๋‚ญ๋น„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹คโ€๊ณ  ํŒ๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ "Incorrect username or password"๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ๋ฐ ๊ณต๊ฒฉ์ž๋“ค์ด ์‚ฌ์šฉ์ž๋ช…์„ `stanleyjobsox`, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ `love123`์œผ๋กœ ๋‹ค์‹œ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฌ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python์€ ๋‘ ๋ฌธ์ž์—ด์ด ๊ฐ™์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆฌ๊ธฐ ์ „๊นŒ์ง€ `stanleyjobsox`์™€ `stanleyjobson` ์–‘์ชฝ์˜ `stanleyjobso` ์ „์ฒด๋ฅผ ๋น„๊ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ "Incorrect username or password"๋ผ๊ณ  ์‘๋‹ตํ•˜๊ธฐ๊นŒ์ง€ ์ถ”๊ฐ€๋กœ ๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ๊ฐ€ ๋” ๊ฑธ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +#### ์‘๋‹ต ์‹œ๊ฐ„์€ ๊ณต๊ฒฉ์ž์—๊ฒŒ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค { #the-time-to-answer-helps-the-attackers } + +์ด ์‹œ์ ์—์„œ ์„œ๋ฒ„๊ฐ€ "Incorrect username or password" ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๋ฐ ๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ ๋” ๊ฑธ๋ ธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฑ„๋ฉด, ๊ณต๊ฒฉ์ž๋“ค์€ _๋ฌด์–ธ๊ฐ€_ ๋งž์•˜๋‹ค๋Š” ๊ฒƒ(์ดˆ๊ธฐ ๋ช‡ ๊ธ€์ž๊ฐ€ ๋งž์•˜๋‹ค๋Š” ๊ฒƒ)์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  `johndoe`๋ณด๋‹ค๋Š” `stanleyjobsox`์— ๋” ๊ฐ€๊นŒ์šด ๊ฐ’์„ ์‹œ๋„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +#### "์ „๋ฌธ์ ์ธ" ๊ณต๊ฒฉ { #a-professional-attack } + +๋ฌผ๋ก  ๊ณต๊ฒฉ์ž๋“ค์€ ์ด๋Ÿฐ ์ž‘์—…์„ ์†์œผ๋กœ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณดํ†ต ์ดˆ๋‹น ์ˆ˜์ฒœ~์ˆ˜๋ฐฑ๋งŒ ๋ฒˆ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ๊ฒƒ์ด๊ณ , ํ•œ ๋ฒˆ์— ์ •๋‹ต ๊ธ€์ž ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€๋กœ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ช‡ ๋ถ„ ๋˜๋Š” ๋ช‡ ์‹œ๊ฐ„ ๋งŒ์—, ์‘๋‹ต์— ๊ฑธ๋ฆฐ ์‹œ๊ฐ„๋งŒ์„ ์ด์šฉํ•ด(์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ โ€œ๋„์›€โ€์„ ๋ฐ›์•„) ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ถ”์ธกํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +#### `secrets.compare_digest()`๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ { #fix-it-with-secrets-compare-digest } + +ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +์š”์•ฝํ•˜๋ฉด, `stanleyjobsox`์™€ `stanleyjobson`์„ ๋น„๊ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ `johndoe`์™€ `stanleyjobson`์„ ๋น„๊ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„๊ณผ ๊ฐ™์•„์ง‘๋‹ˆ๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ด๋Ÿฌํ•œ ๋ฒ”์œ„์˜ ๋ณด์•ˆ ๊ณต๊ฒฉ ์ „๋ฐ˜์— ๋Œ€ํ•ด ์•ˆ์ „ํ•ด์ง‘๋‹ˆ๋‹ค. + +### ์˜ค๋ฅ˜ ๋ฐ˜ํ™˜ํ•˜๊ธฐ { #return-the-error } + +์ž๊ฒฉ ์ฆ๋ช…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จ๋˜๋ฉด, ์ƒํƒœ ์ฝ”๋“œ 401(์ž๊ฒฉ ์ฆ๋ช…์ด ์ œ๊ณต๋˜์ง€ ์•Š์•˜์„ ๋•Œ์™€ ๋™์ผ)์„ ์‚ฌ์šฉํ•˜๋Š” `HTTPException`์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋กœ๊ทธ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋‹ค์‹œ ํ‘œ์‹œํ•˜๋„๋ก `WWW-Authenticate` ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”: + +{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} diff --git a/docs/ko/docs/advanced/security/index.md b/docs/ko/docs/advanced/security/index.md new file mode 100644 index 0000000000..4c7abfacc7 --- /dev/null +++ b/docs/ko/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# ๊ณ ๊ธ‰ ๋ณด์•ˆ { #advanced-security } + +## ์ถ”๊ฐ€ ๊ธฐ๋Šฅ { #additional-features } + +[ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ: ๋ณด์•ˆ](../../tutorial/security/index.md){.internal-link target=_blank}์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ ์™ธ์—๋„, ๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +๋‹ค์Œ ์„น์…˜๋“ค์€ **๋ฐ˜๋“œ์‹œ "๊ณ ๊ธ‰"์ด๋ผ๊ณ  ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค**. + +๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ, ๊ทธ์ค‘ ํ•˜๋‚˜์— ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## ๋จผ์ € ํŠœํ† ๋ฆฌ์–ผ ์ฝ๊ธฐ { #read-the-tutorial-first } + +๋‹ค์Œ ์„น์…˜์€ ์ฃผ์š” [ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ: ๋ณด์•ˆ](../../tutorial/security/index.md){.internal-link target=_blank}์„ ์ด๋ฏธ ์ฝ์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. + +๋ชจ๋‘ ๋™์ผํ•œ ๊ฐœ๋…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/security/oauth2-scopes.md b/docs/ko/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..0f90f92ae9 --- /dev/null +++ b/docs/ko/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 ์Šค์ฝ”ํ”„ { #oauth2-scopes } + +**FastAPI**์—์„œ OAuth2 ์Šค์ฝ”ํ”„๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ฅผ ํ†ตํ•ด OAuth2 ํ‘œ์ค€์„ ๋”ฐ๋ฅด๋Š” ๋” ์„ธ๋ฐ€ํ•œ ๊ถŒํ•œ ์‹œ์Šคํ…œ์„ OpenAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋ฐ API ๋ฌธ์„œ)์— ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” OAuth2๋Š” Facebook, Google, GitHub, Microsoft, X(Twitter) ๋“ฑ ๋งŽ์€ ๋Œ€ํ˜• ์ธ์ฆ ์ œ๊ณต์ž๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํŠน์ • ๊ถŒํ•œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +Facebook, Google, GitHub, Microsoft, X(Twitter)๋กœ โ€œ๋กœ๊ทธ์ธโ€ํ•  ๋•Œ๋งˆ๋‹ค, ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ์„น์…˜์—์„œ๋Š” **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋™์ผํ•œ โ€œ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2โ€๋กœ ์ธ์ฆ(Authentication)๊ณผ ์ธ๊ฐ€(Authorization)๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + +/// warning | ๊ฒฝ๊ณ  + +์ด ์„น์…˜์€ ๋‹ค์†Œ ๊ณ ๊ธ‰ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +OAuth2 ์Šค์ฝ”ํ”„๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋Š” ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋Š” (OpenAPI์™€ ํ•จ๊ป˜) API ๋ฐ API ๋ฌธ์„œ์— ๊น”๋”ํ•˜๊ฒŒ ํ†ตํ•ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ํ•ด๋‹น ์Šค์ฝ”ํ”„(๋˜๋Š” ๊ทธ ๋ฐ–์˜ ์–ด๋–ค ๋ณด์•ˆ/์ธ๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ์ด๋“ )๋Š” ์ฝ”๋“œ์—์„œ ํ•„์š”์— ๋งž๊ฒŒ ์ง์ ‘ ๊ฐ•์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๋งŽ์€ ๊ฒฝ์šฐ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋Š” ๊ณผํ•œ ์„ ํƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ํ•„์š”ํ•˜๋‹ค๊ณ  ์•Œ๊ณ  ์žˆ๊ฑฐ๋‚˜ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด ๊ณ„์† ์ฝ์–ด๋ณด์„ธ์š”. + +/// + +## OAuth2 ์Šค์ฝ”ํ”„์™€ OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 ์‚ฌ์–‘์€ โ€œ์Šค์ฝ”ํ”„(scopes)โ€๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด ๋ชฉ๋ก์œผ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ ๋ฌธ์ž์—ด์˜ ๋‚ด์šฉ์€ ์–ด๋–ค ํ˜•์‹์ด๋“  ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +์ด ์Šค์ฝ”ํ”„๋“ค์€ โ€œ๊ถŒํ•œโ€์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. + +OpenAPI(์˜ˆ: API ๋ฌธ์„œ)์—์„œ๋Š” โ€œsecurity schemesโ€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด security scheme ์ค‘ ํ•˜๋‚˜๊ฐ€ OAuth2๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์Šค์ฝ”ํ”„๋„ ์„ ์–ธํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ โ€œ์Šค์ฝ”ํ”„โ€๋Š” (๊ณต๋ฐฑ ์—†๋Š”) ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. + +๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํŠน์ • ๋ณด์•ˆ ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +* `users:read` ๋˜๋Š” `users:write` ๋Š” ํ”ํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. +* `instagram_basic` ๋Š” Facebook/Instagram์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +* `https://www.googleapis.com/auth/drive` ๋Š” Google์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +OAuth2์—์„œ โ€œ์Šค์ฝ”ํ”„โ€๋Š” ํ•„์š”ํ•œ ํŠน์ • ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. + +`:` ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฌธ์ž๊ฐ€ ์žˆ๊ฑฐ๋‚˜ URL์ด์–ด๋„ ์ƒ๊ด€์—†์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ์„ธ๋ถ€์‚ฌํ•ญ์€ ๊ตฌํ˜„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. + +OAuth2 ์ž…์žฅ์—์„œ๋Š” ๊ทธ์ € ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. + +/// + +## ์ „์ฒด ๊ฐœ์š” { #global-view } + +๋จผ์ €, ๋ฉ”์ธ **ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ**์˜ [๋น„๋ฐ€๋ฒˆํ˜ธ(๋ฐ ํ•ด์‹ฑ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” OAuth2, JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” Bearer](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ์˜ˆ์ œ์—์„œ ์–ด๋–ค ๋ถ€๋ถ„์ด ๋ฐ”๋€Œ๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ OAuth2 ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +์ด์ œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## OAuth2 ๋ณด์•ˆ ์Šคํ‚ด { #oauth2-security-scheme } + +์ฒซ ๋ฒˆ์งธ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ด์ œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šค์ฝ”ํ”„ 2๊ฐœ(`me`, `items`)๋กœ OAuth2 ๋ณด์•ˆ ์Šคํ‚ด์„ ์„ ์–ธํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. + +`scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ฐ ์Šค์ฝ”ํ”„๋ฅผ ํ‚ค๋กœ ํ•˜๊ณ , ์„ค๋ช…์„ ๊ฐ’์œผ๋กœ ํ•˜๋Š” `dict`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +์ด์ œ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋กœ๊ทธ์ธ/์ธ๊ฐ€ํ•  ๋•Œ API ๋ฌธ์„œ์— ์Šค์ฝ”ํ”„๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์Šค์ฝ”ํ”„๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: `me`์™€ `items`. + +์ด๋Š” Facebook, Google, GitHub ๋“ฑ์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๋ฉด์„œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค: + + + +## ์Šค์ฝ”ํ”„๋ฅผ ํฌํ•จํ•œ JWT ํ† ํฐ { #jwt-token-with-scopes } + +์ด์ œ ํ† ํฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ˆ˜์ •ํ•ด, ์š”์ฒญ๋œ ์Šค์ฝ”ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + +์—ฌ์ „ํžˆ ๋™์ผํ•œ `OAuth2PasswordRequestForm`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์š”์ฒญ์—์„œ ๋ฐ›์€ ๊ฐ ์Šค์ฝ”ํ”„๋ฅผ ๋‹ด๋Š” `scopes` ์†์„ฑ์ด ์žˆ์œผ๋ฉฐ, ํƒ€์ž…์€ `str`์˜ `list`์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  JWT ํ† ํฐ์˜ ์ผ๋ถ€๋กœ ์Šค์ฝ”ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +/// danger | ์œ„ํ—˜ + +๋‹จ์ˆœํ™”๋ฅผ ์œ„ํ•ด, ์—ฌ๊ธฐ์„œ๋Š” ์š”์ฒญ์œผ๋กœ ๋ฐ›์€ ์Šค์ฝ”ํ”„๋ฅผ ๊ทธ๋Œ€๋กœ ํ† ํฐ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ณด์•ˆ์„ ์œ„ํ•ด, ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์Šค์ฝ”ํ”„๋งŒ(๋˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜ํ•œ ๊ฒƒ๋งŒ) ์ถ”๊ฐ€ํ•˜๋„๋ก ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ ์˜์กด์„ฑ์—์„œ ์Šค์ฝ”ํ”„ ์„ ์–ธํ•˜๊ธฐ { #declare-scopes-in-path-operations-and-dependencies } + +์ด์ œ `/users/me/items/`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์Šค์ฝ”ํ”„ `items`๋ฅผ ์š”๊ตฌํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด `fastapi`์—์„œ `Security`๋ฅผ importํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +`Security`๋Š” (`Depends`์ฒ˜๋Ÿผ) ์˜์กด์„ฑ์„ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, `Security`๋Š” ์Šค์ฝ”ํ”„(๋ฌธ์ž์—ด) ๋ชฉ๋ก์„ ๋ฐ›๋Š” `scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ๋ฐ›์Šต๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ, ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋ฅผ `Security`์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค(`Depends`๋กœ ํ•  ๋•Œ์™€ ๊ฐ™์€ ๋ฐฉ์‹). + +ํ•˜์ง€๋งŒ ์Šค์ฝ”ํ”„ `list`๋„ ํ•จ๊ป˜ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์Šค์ฝ”ํ”„ ํ•˜๋‚˜๋งŒ: `items`(๋” ๋งŽ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). + +๋˜ํ•œ ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋Š” `Depends`๋ฟ ์•„๋‹ˆ๋ผ `Security`๋กœ๋„ ํ•˜์œ„ ์˜์กด์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์ฒด ํ•˜์œ„ ์˜์กด์„ฑ ํ•จ์ˆ˜(`get_current_user`)์™€ ์ถ”๊ฐ€ ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ์—๋Š” ์Šค์ฝ”ํ”„ `me`๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค(์—ฌ๋Ÿฌ ์Šค์ฝ”ํ”„๋ฅผ ์š”๊ตฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). + +/// note | ์ฐธ๊ณ  + +๋ฐ˜๋“œ์‹œ ์„œ๋กœ ๋‹ค๋ฅธ ๊ณณ์— ์„œ๋กœ ๋‹ค๋ฅธ ์Šค์ฝ”ํ”„๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋Š” **FastAPI**๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ ˆ๋ฒจ์—์„œ ์„ ์–ธ๋œ ์Šค์ฝ”ํ”„๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ด๋ ‡๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +`Security`๋Š” ์‹ค์ œ๋กœ `Depends`์˜ ์„œ๋ธŒํด๋ž˜์Šค์ด๋ฉฐ, ๋‚˜์ค‘์— ๋ณด๊ฒŒ ๋  ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ํ•˜๋‚˜๋งŒ ๋” ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `Depends` ๋Œ€์‹  `Security`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, **FastAPI**๋Š” ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, OpenAPI๋กœ API๋ฅผ ๋ฌธ์„œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `fastapi`์—์„œ `Query`, `Path`, `Depends`, `Security` ๋“ฑ์„ importํ•  ๋•Œ, ์ด๊ฒƒ๋“ค์€ ์‹ค์ œ๋กœ ํŠน์ˆ˜ํ•œ ํด๋ž˜์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. + +/// + +## `SecurityScopes` ์‚ฌ์šฉํ•˜๊ธฐ { #use-securityscopes } + +์ด์ œ ์˜์กด์„ฑ `get_current_user`๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” ์œ„์˜ ์˜์กด์„ฑ๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์—์„œ ์•ž์„œ ๋งŒ๋“  ๋™์ผํ•œ OAuth2 ์Šคํ‚ด์„ ์˜์กด์„ฑ์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: `oauth2_scheme`. + +์ด ์˜์กด์„ฑ ํ•จ์ˆ˜ ์ž์ฒด์—๋Š” ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—, `oauth2_scheme`์™€ ํ•จ๊ป˜ `Depends`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ๋Š” `Security`๋ฅผ ์“ธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ `fastapi.security`์—์„œ importํ•œ `SecurityScopes` ํƒ€์ž…์˜ ํŠน๋ณ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + +์ด `SecurityScopes` ํด๋ž˜์Šค๋Š” `Request`์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค(`Request`๋Š” ์š”์ฒญ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์–ป๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## `scopes` ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-scopes } + +๋งค๊ฐœ๋ณ€์ˆ˜ `security_scopes`์˜ ํƒ€์ž…์€ `SecurityScopes`์ž…๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” `scopes` ์†์„ฑ์ด ์žˆ์œผ๋ฉฐ, ์ž๊ธฐ ์ž์‹ ๊ณผ ์ด ํ•จ์ˆ˜๋ฅผ ํ•˜์œ„ ์˜์กด์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์˜์กด์„ฑ์ด ์š”๊ตฌํ•˜๋Š” ์Šค์ฝ”ํ”„ ์ „์ฒด๋ฅผ ๋‹ด์€ `list`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  โ€œdependantsโ€... ๋‹ค์†Œ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋Š”๋ฐ, ์•„๋ž˜์—์„œ ๋‹ค์‹œ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. + +`security_scopes` ๊ฐ์ฒด(`SecurityScopes` ํด๋ž˜์Šค)์—๋Š” ๋˜ํ•œ `scope_str` ์†์„ฑ์ด ์žˆ๋Š”๋ฐ, ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋‹จ์ผ ๋ฌธ์ž์—ด๋กœ ์Šค์ฝ”ํ”„๋“ค์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค). + +๋‚˜์ค‘์— ์—ฌ๋Ÿฌ ์ง€์ ์—์„œ ์žฌ์‚ฌ์šฉ(`raise`)ํ•  ์ˆ˜ ์žˆ๋Š” `HTTPException`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +์ด ์˜ˆ์™ธ์—๋Š” ํ•„์š”ํ•œ ์Šค์ฝ”ํ”„(์žˆ๋‹ค๋ฉด)๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด(`scope_str`)๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์Šค์ฝ”ํ”„ ๋ฌธ์ž์—ด์„ `WWW-Authenticate` ํ—ค๋”์— ๋„ฃ์Šต๋‹ˆ๋‹ค(์ด๋Š” ์‚ฌ์–‘์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## `username`๊ณผ ๋ฐ์ดํ„ฐ ํ˜•ํƒœ ๊ฒ€์ฆํ•˜๊ธฐ { #verify-the-username-and-data-shape } + +`username`์„ ์–ป์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์Šค์ฝ”ํ”„๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๋‹ค์Œ Pydantic ๋ชจ๋ธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค(`ValidationError` ์˜ˆ์™ธ๋ฅผ ์žก์Šต๋‹ˆ๋‹ค). JWT ํ† ํฐ์„ ์ฝ๊ฑฐ๋‚˜ Pydantic์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฉด, ์•ž์—์„œ ๋งŒ๋“  `HTTPException`์„ raiseํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด Pydantic ๋ชจ๋ธ `TokenData`์— ์ƒˆ ์†์„ฑ `scopes`๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + +Pydantic์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด ์Šค์ฝ”ํ”„๊ฐ€ ์ •ํ™•ํžˆ `str`์˜ `list`์ด๊ณ  `username`์ด `str`์ธ์ง€ ๋“ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `dict`๋‚˜ ๋‹ค๋ฅธ ํ˜•ํƒœ๋ผ๋ฉด, ๋‚˜์ค‘์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ด๋А ์‹œ์ ์— ๊นจ์ง€๋ฉด์„œ ๋ณด์•ˆ ์œ„ํ—˜์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ ํ•ด๋‹น username์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์—†๋‹ค๋ฉด ์•ž์—์„œ ๋งŒ๋“  ๋™์ผํ•œ ์˜ˆ์™ธ๋ฅผ raiseํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## `scopes` ๊ฒ€์ฆํ•˜๊ธฐ { #verify-the-scopes } + +์ด์ œ ์ด ์˜์กด์„ฑ๊ณผ ๋ชจ๋“  dependant( *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ํฌํ•จ)๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๋ชจ๋“  ์Šค์ฝ”ํ”„๊ฐ€, ๋ฐ›์€ ํ† ํฐ์˜ ์Šค์ฝ”ํ”„์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `HTTPException`์„ raiseํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด, ๋ชจ๋“  ์Šค์ฝ”ํ”„๋ฅผ `str`๋กœ ๋‹ด๊ณ  ์žˆ๋Š” `security_scopes.scopes`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## ์˜์กด์„ฑ ํŠธ๋ฆฌ์™€ ์Šค์ฝ”ํ”„ { #dependency-tree-and-scopes } + +์ด ์˜์กด์„ฑ ํŠธ๋ฆฌ์™€ ์Šค์ฝ”ํ”„๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +`get_current_active_user` ์˜์กด์„ฑ์€ `get_current_user`๋ฅผ ํ•˜์œ„ ์˜์กด์„ฑ์œผ๋กœ ๊ฐ€์ง€๋ฏ€๋กœ, `get_current_active_user`์—์„œ ์„ ์–ธ๋œ ์Šค์ฝ”ํ”„ `"me"`๋Š” `get_current_user`์— ์ „๋‹ฌ๋˜๋Š” `security_scopes.scopes`์˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ ๋ชฉ๋ก์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ž์ฒด๋„ ์Šค์ฝ”ํ”„ `"items"`๋ฅผ ์„ ์–ธํ•˜๋ฏ€๋กœ, ์ด๊ฒƒ ๋˜ํ•œ `get_current_user`์— ์ „๋‹ฌ๋˜๋Š” `security_scopes.scopes` ๋ชฉ๋ก์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +์˜์กด์„ฑ๊ณผ ์Šค์ฝ”ํ”„์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_own_items`๋Š”: + * ์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ `["items"]`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค: + * `get_current_active_user`: + * ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋Š”: + * ์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ `["me"]`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค: + * `get_current_user`: + * ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_user`๋Š”: + * ์ž์ฒด์ ์œผ๋กœ๋Š” ์š”๊ตฌ ์Šค์ฝ”ํ”„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + * `oauth2_scheme`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜์กด์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + * `SecurityScopes` ํƒ€์ž…์˜ `security_scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: + * ์ด `security_scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์œ„์—์„œ ์„ ์–ธ๋œ ๋ชจ๋“  ์Šค์ฝ”ํ”„๋ฅผ ๋‹ด์€ `list`์ธ `scopes` ์†์„ฑ์„ ๊ฐ€์ง€๋ฏ€๋กœ: + * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_own_items`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `["me", "items"]`๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. + * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_users_me`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `["me"]`๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ด๋Š” ์˜์กด์„ฑ `get_current_active_user`์—์„œ ์„ ์–ธ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_system_status`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `[]`(์—†์Œ)๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. `scopes`๊ฐ€ ์žˆ๋Š” `Security`๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ณ , ๊ทธ ์˜์กด์„ฑ์ธ `get_current_user`๋„ `scopes`๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ โ€œ๋งˆ๋ฒ• ๊ฐ™์€โ€ ์ ์€ `get_current_user`๊ฐ€ ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜๋Š” `scopes` ๋ชฉ๋ก์ด ๋‹ฌ๋ผ์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด๋Š” ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•œ ์˜์กด์„ฑ ํŠธ๋ฆฌ์—์„œ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ ๊ฐ ์˜์กด์„ฑ์— ์„ ์–ธ๋œ `scopes`์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. + +/// + +## `SecurityScopes`์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์„ค๋ช… { #more-details-about-securityscopes } + +`SecurityScopes`๋Š” ์–ด๋А ์ง€์ ์—์„œ๋“ , ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, โ€œ๋ฃจํŠธโ€ ์˜์กด์„ฑ์—๋งŒ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +`SecurityScopes`๋Š” **ํ•ด๋‹น ํŠน์ •** *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ **ํ•ด๋‹น ํŠน์ •** ์˜์กด์„ฑ ํŠธ๋ฆฌ์— ๋Œ€ํ•ด, ํ˜„์žฌ `Security` ์˜์กด์„ฑ๊ณผ ๋ชจ๋“  dependant์— ์„ ์–ธ๋œ ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ํ•ญ์ƒ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +`SecurityScopes`์—๋Š” dependant๊ฐ€ ์„ ์–ธํ•œ ๋ชจ๋“  ์Šค์ฝ”ํ”„๊ฐ€ ํฌํ•จ๋˜๋ฏ€๋กœ, ์ค‘์•™์˜ ์˜์กด์„ฑ ํ•จ์ˆ˜์—์„œ ํ† ํฐ์ด ํ•„์š”ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•œ ๋‹ค์Œ, ์„œ๋กœ ๋‹ค๋ฅธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋“ค์€ ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ ๊ฒ€์‚ฌ๋ฉ๋‹ˆ๋‹ค. + +## ํ™•์ธํ•˜๊ธฐ { #check-it } + +API ๋ฌธ์„œ๋ฅผ ์—ด๋ฉด, ์ธ์ฆํ•˜๊ณ  ์ธ๊ฐ€ํ•  ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + + +์–ด๋–ค ์Šค์ฝ”ํ”„๋„ ์„ ํƒํ•˜์ง€ ์•Š์œผ๋ฉด โ€œ์ธ์ฆโ€์€ ๋˜์ง€๋งŒ, `/users/me/` ๋˜๋Š” `/users/me/items/`์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๊ถŒํ•œ์ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. `/status/`์—๋Š” ์—ฌ์ „ํžˆ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์Šค์ฝ”ํ”„ `me`๋Š” ์„ ํƒํ–ˆ์ง€๋งŒ ์Šค์ฝ”ํ”„ `items`๋Š” ์„ ํƒํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, `/users/me/`์—๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ `/users/me/items/`์—๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ, ์ œ3์ž ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ œ๊ณต๋ฐ›์€ ํ† ํฐ์œผ๋กœ ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋“ค ์ค‘ ํ•˜๋‚˜์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + +## ์ œ3์ž ํ†ตํ•ฉ์— ๋Œ€ํ•ด { #about-third-party-integrations } + +์ด ์˜ˆ์ œ์—์„œ๋Š” OAuth2 โ€œpasswordโ€ ํ”Œ๋กœ์šฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ๋ณดํ†ต ์ž์ฒด ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์žˆ๋Š” ์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋กœ๊ทธ์ธํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. + +์šฐ๋ฆฌ๊ฐ€ ์ด๋ฅผ ํ†ต์ œํ•˜๋ฏ€๋กœ `username`๊ณผ `password`๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์—ฐ๊ฒฐํ•  OAuth2 ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์ฆ‰, Facebook, Google, GitHub ๋“ฑ๊ณผ ๋™๋“ฑํ•œ ์ธ์ฆ ์ œ๊ณต์ž๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๋ฉด)์„ ๊ตฌ์ถ•ํ•œ๋‹ค๋ฉด, ๋‹ค๋ฅธ ํ”Œ๋กœ์šฐ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ€์žฅ ํ”ํ•œ ๊ฒƒ์€ implicit ํ”Œ๋กœ์šฐ์ž…๋‹ˆ๋‹ค. + +๊ฐ€์žฅ ์•ˆ์ „ํ•œ ๊ฒƒ์€ code ํ”Œ๋กœ์šฐ์ด์ง€๋งŒ, ๋” ๋งŽ์€ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•ด ๊ตฌํ˜„์ด ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. ๋ณต์žกํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ์ œ๊ณต์ž๋Š” implicit ํ”Œ๋กœ์šฐ๋ฅผ ๊ถŒ์žฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +/// note | ์ฐธ๊ณ  + +์ธ์ฆ ์ œ๊ณต์ž๋งˆ๋‹ค ์ž์‹ ๋“ค์˜ ๋ธŒ๋žœ๋“œ์˜ ์ผ๋ถ€๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด, ๊ฐ ํ”Œ๋กœ์šฐ๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฆ„ ๋ถ™์ด๋Š” ๊ฒฝ์šฐ๊ฐ€ ํ”ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ, ๋™์ผํ•œ OAuth2 ํ‘œ์ค€์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// + +**FastAPI**๋Š” `fastapi.security.oauth2`์— ์ด๋Ÿฌํ•œ ๋ชจ๋“  OAuth2 ์ธ์ฆ ํ”Œ๋กœ์šฐ๋ฅผ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. + +## ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ `dependencies`์—์„œ์˜ `Security` { #security-in-decorator-dependencies } + +[๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์˜ ์˜์กด์„ฑ](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์˜ `dependencies` ๋งค๊ฐœ๋ณ€์ˆ˜์— `Depends`์˜ `list`๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ๊ฑฐ๊ธฐ์—์„œ `scopes`์™€ ํ•จ๊ป˜ `Security`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/settings.md b/docs/ko/docs/advanced/settings.md new file mode 100644 index 0000000000..6fa7c644cc --- /dev/null +++ b/docs/ko/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# ์„ค์ •๊ณผ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ { #settings-and-environment-variables } + +๋งŽ์€ ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” ์™ธ๋ถ€ ์„ค์ •์ด๋‚˜ ๊ตฌ์„ฑ(์˜ˆ: secret key, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž๊ฒฉ ์ฆ๋ช…, ์ด๋ฉ”์ผ ์„œ๋น„์Šค ์ž๊ฒฉ ์ฆ๋ช… ๋“ฑ)์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Ÿฌํ•œ ์„ค์ • ๋Œ€๋ถ€๋ถ„์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค URL์ฒ˜๋Ÿผ ๋ณ€๋™ ๊ฐ€๋Šฅ(๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Œ)ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ์„ค์ •์€ secret์ฒ˜๋Ÿผ ๋ฏผ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋•Œ๋ฌธ์— ๋ณดํ†ต ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฝ์–ด๋“ค์ด๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. + +/// tip | ํŒ + +ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด [ํ™˜๊ฒฝ ๋ณ€์ˆ˜](../environment-variables.md){.internal-link target=_blank}๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +/// + +## ํƒ€์ž…๊ณผ ๊ฒ€์ฆ { #types-and-validation } + +์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์€ Python ์™ธ๋ถ€์— ์žˆ์œผ๋ฉฐ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ ๋ฐ ์‹œ์Šคํ…œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„(๊ทธ๋ฆฌ๊ณ  Linux, Windows, macOS ๊ฐ™์€ ์„œ๋กœ ๋‹ค๋ฅธ ์šด์˜์ฒด์ œ์™€๋„)๊ณผ ํ˜ธํ™˜๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ, ํ…์ŠคํŠธ ๋ฌธ์ž์—ด๋งŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ฆ‰, Python์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ๋ถ€ํ„ฐ ์ฝ์–ด์˜จ ์–ด๋–ค ๊ฐ’์ด๋“  `str`์ด ๋˜๋ฉฐ, ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ์˜ ๋ณ€ํ™˜์ด๋‚˜ ๊ฒ€์ฆ์€ ์ฝ”๋“œ์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +## Pydantic `Settings` { #pydantic-settings } + +๋‹คํ–‰ํžˆ Pydantic์€ Pydantic: Settings management๋ฅผ ํ†ตํ•ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ ์˜ค๋Š” ์ด๋Ÿฌํ•œ ์„ค์ •์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ›Œ๋ฅญํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +### `pydantic-settings` ์„ค์น˜ํ•˜๊ธฐ { #install-pydantic-settings } + +๋จผ์ € [๊ฐ€์ƒ ํ™˜๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, `pydantic-settings` ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +๋˜๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ `all` extras๋ฅผ ์„ค์น˜ํ•˜๋ฉด ํ•จ๊ป˜ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### `Settings` ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ { #create-the-settings-object } + +Pydantic์—์„œ `BaseSettings`๋ฅผ importํ•˜๊ณ , Pydantic ๋ชจ๋ธ๊ณผ ๋งค์šฐ ๋น„์Šทํ•˜๊ฒŒ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ์„ธ์š”. + +Pydantic ๋ชจ๋ธ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜(๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•˜๋‹ค๋ฉด ๊ธฐ๋ณธ๊ฐ’)๊ณผ ํ•จ๊ป˜ ํด๋ž˜์Šค ์†์„ฑ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + +๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…, `Field()`๋กœ ์ถ”๊ฐ€ ๊ฒ€์ฆ ๋“ฑ Pydantic ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋™์ผํ•œ ๊ฒ€์ฆ ๊ธฐ๋Šฅ๊ณผ ๋„๊ตฌ๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} + +/// tip | ํŒ + +๋น ๋ฅด๊ฒŒ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐํ•  ์˜ˆ์‹œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ด ์˜ˆ์‹œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์•„๋ž˜์˜ ๋งˆ์ง€๋ง‰ ์˜ˆ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. + +/// + +๊ทธ ๋‹ค์Œ, ํ•ด๋‹น `Settings` ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค(์—ฌ๊ธฐ์„œ๋Š” `settings` ๊ฐ์ฒด)๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Pydantic์ด ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋Œ€๋ฌธ์ž ๋ณ€์ˆ˜ `APP_NAME`๋„ `app_name` ์†์„ฑ์— ๋Œ€ํ•ด ์ฝํž™๋‹ˆ๋‹ค. + +์ดํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ `settings` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ ์–ธํ•œ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค(์˜ˆ: `items_per_user`๋Š” `int`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค). + +### `settings` ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-settings } + +์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ƒˆ `settings` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} + +### ์„œ๋ฒ„ ์‹คํ–‰ํ•˜๊ธฐ { #run-the-server } + +๋‹ค์Œ์œผ๋กœ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ์„ ์ „๋‹ฌํ•˜๋ฉด์„œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์ฒ˜๋Ÿผ `ADMIN_EMAIL`๊ณผ `APP_NAME`์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | ํŒ + +ํ•˜๋‚˜์˜ ๋ช…๋ น์— ์—ฌ๋Ÿฌ env var๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ณ , ๋ชจ๋‘ ๋ช…๋ น ์•ž์— ๋‘์„ธ์š”. + +/// + +๊ทธ๋Ÿฌ๋ฉด `admin_email` ์„ค์ •์€ `"deadpool@example.com"`์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. + +`app_name`์€ `"ChimichangApp"`์ด ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  `items_per_user`๋Š” ๊ธฐ๋ณธ๊ฐ’ `50`์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. + +## ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ์„ค์ • { #settings-in-another-module } + +[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ์„ค์ •์„ ๋‹ค๋ฅธ ๋ชจ๋“ˆ ํŒŒ์ผ์— ๋„ฃ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `config.py` ํŒŒ์ผ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/app01_py39/config.py *} + +๊ทธ๋ฆฌ๊ณ  `main.py` ํŒŒ์ผ์—์„œ ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} + +/// tip | ํŒ + +[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ `__init__.py` ํŒŒ์ผ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// + +## ์˜์กด์„ฑ์—์„œ ์„ค์ • ์‚ฌ์šฉํ•˜๊ธฐ { #settings-in-a-dependency } + +์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์–ด๋””์„œ๋‚˜ ์‚ฌ์šฉ๋˜๋Š” ์ „์—ญ `settings` ๊ฐ์ฒด๋ฅผ ๋‘๋Š” ๋Œ€์‹ , ์˜์กด์„ฑ์—์„œ ์„ค์ •์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ํŠนํžˆ ํ…Œ์ŠคํŠธ ์ค‘์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์‚ฌ์šฉ์ž ์ •์˜ ์„ค์ •์œผ๋กœ ์˜์กด์„ฑ์„ overrideํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +### config ํŒŒ์ผ { #the-config-file } + +์ด์ „ ์˜ˆ์‹œ์—์„œ ์ด์–ด์„œ, `config.py` ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} + +์ด์ œ๋Š” ๊ธฐ๋ณธ ์ธ์Šคํ„ด์Šค `settings = Settings()`๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. + +### ๋ฉ”์ธ ์•ฑ ํŒŒ์ผ { #the-main-app-file } + +์ด์ œ ์ƒˆ๋กœ์šด `config.Settings()`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์˜์กด์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} + +/// tip | ํŒ + +`@lru_cache`๋Š” ์กฐ๊ธˆ ๋’ค์— ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +์ง€๊ธˆ์€ `get_settings()`๊ฐ€ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋ผ๊ณ  ๊ฐ€์ •ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +/// + +๊ทธ ๋‹ค์Œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ ์ด๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์š”๊ตฌํ•˜๊ณ , ํ•„์š”ํ•œ ์–ด๋””์„œ๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} + +### ์„ค์ •๊ณผ ํ…Œ์ŠคํŠธ { #settings-and-testing } + +๊ทธ ๋‹ค์Œ, `get_settings`์— ๋Œ€ํ•œ ์˜์กด์„ฑ override๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ ์ค‘์— ๋‹ค๋ฅธ ์„ค์ • ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} + +์˜์กด์„ฑ override์—์„œ๋Š” ์ƒˆ `Settings` ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ `admin_email`์˜ ์ƒˆ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , ๊ทธ ์ƒˆ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ๊ทธ๊ฒƒ์ด ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## `.env` ํŒŒ์ผ ์ฝ๊ธฐ { #reading-a-env-file } + +๋งŽ์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ์„ค์ •์ด ๋งŽ๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ด๋ฅผ ํŒŒ์ผ์— ๋„ฃ์–ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ฝ๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ด€ํ–‰์€ ์ถฉ๋ถ„ํžˆ ํ”ํ•ด์„œ ์ด๋ฆ„๋„ ์žˆ๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์€ ๋ณดํ†ต `.env` ํŒŒ์ผ์— ๋‘๋ฉฐ, ๊ทธ ํŒŒ์ผ์„ "dotenv"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ (`.`)์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํŒŒ์ผ์€ Linux, macOS ๊ฐ™์€ Unix ๊ณ„์—ด ์‹œ์Šคํ…œ์—์„œ ์ˆจ๊น€ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ dotenv ํŒŒ์ผ์ด ๊ผญ ๊ทธ ์ •ํ™•ํ•œ ํŒŒ์ผ๋ช…์„ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +/// + +Pydantic์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋Ÿฐ ์œ ํ˜•์˜ ํŒŒ์ผ์—์„œ ์ฝ๋Š” ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Pydantic Settings: Dotenv (.env) support๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +/// tip | ํŒ + +์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด `pip install python-dotenv`๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// + +### `.env` ํŒŒ์ผ { #the-env-file } + +๋‹ค์Œ๊ณผ ๊ฐ™์€ `.env` ํŒŒ์ผ์„ ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### `.env`์—์„œ ์„ค์ • ์ฝ๊ธฐ { #read-settings-from-env } + +๊ทธ๋ฆฌ๊ณ  `config.py`๋ฅผ ๋‹ค์Œ์ฒ˜๋Ÿผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} + +/// tip | ํŒ + +`model_config` ์†์„ฑ์€ Pydantic ์„ค์ •์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Pydantic: Concepts: Configuration์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +/// + +์—ฌ๊ธฐ์„œ๋Š” Pydantic `Settings` ํด๋ž˜์Šค ์•ˆ์— config `env_file`์„ ์ •์˜ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๋ ค๋Š” dotenv ํŒŒ์ผ์˜ ํŒŒ์ผ๋ช…์„ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + +### `lru_cache`๋กœ `Settings`๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑํ•˜๊ธฐ { #creating-the-settings-only-once-with-lru-cache } + +๋””์Šคํฌ์—์„œ ํŒŒ์ผ์„ ์ฝ๋Š” ๊ฒƒ์€ ๋ณดํ†ต ๋น„์šฉ์ด ํฐ(๋А๋ฆฐ) ์ž‘์—…์ด๋ฏ€๋กœ, ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์ฝ๊ธฐ๋ณด๋‹ค๋Š” ํ•œ ๋ฒˆ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋™์ผํ•œ settings ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋งค๋ฒˆ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด: + +```Python +Settings() +``` + +์ƒˆ `Settings` ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ์ƒ์„ฑ ์‹œ์ ์— `.env` ํŒŒ์ผ์„ ๋‹ค์‹œ ์ฝ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +์˜์กด์„ฑ ํ•จ์ˆ˜๊ฐ€ ๋‹จ์ˆœํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๋ฉด: + +```Python +def get_settings(): + return Settings() +``` + +์š”์ฒญ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๊ณ , ์š”์ฒญ๋งˆ๋‹ค `.env` ํŒŒ์ผ์„ ์ฝ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โš ๏ธ + +ํ•˜์ง€๋งŒ ์œ„์— `@lru_cache` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, `Settings` ๊ฐ์ฒด๋Š” ์ตœ์ดˆ ํ˜ธ์ถœ ์‹œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} + +๊ทธ ๋‹ค์Œ ์š”์ฒญ๋“ค์—์„œ ์˜์กด์„ฑ์œผ๋กœ `get_settings()`๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค, `get_settings()`์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์„œ ์ƒˆ `Settings` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ์ฒซ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ๊ณ„์† ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +#### `lru_cache` Technical Details { #lru-cache-technical-details } + +`@lru_cache`๋Š” ๋ฐ์ฝ”๋ ˆ์ด์…˜ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋งค๋ฒˆ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ๋Œ€์‹ , ์ฒซ ๋ฒˆ์งธ์— ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋งค๋ฒˆ ํ•จ์ˆ˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค). + +๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ํ•จ์ˆ˜๋Š” ์ธ์ž ์กฐํ•ฉ๋งˆ๋‹ค ํ•œ ๋ฒˆ์”ฉ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ์ธ์ž ์กฐํ•ฉ์— ๋Œ€ํ•ด ๋ฐ˜ํ™˜๋œ ๊ฐ’์€, ํ•จ์ˆ˜๊ฐ€ ์ •ํ™•ํžˆ ๊ฐ™์€ ์ธ์ž ์กฐํ•ฉ์œผ๋กœ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +์šฐ๋ฆฌ์˜ ์˜์กด์„ฑ `get_settings()`์˜ ๊ฒฝ์šฐ, ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์ธ์ž๋„ ๋ฐ›์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฑฐ์˜ ์ „์—ญ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜์กด์„ฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์‰ฝ๊ฒŒ overrideํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`@lru_cache`๋Š” Python ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ `functools`์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ `@lru_cache`์— ๋Œ€ํ•œ Python ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ์ •๋ฆฌ { #recap } + +Pydantic Settings๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Pydantic ๋ชจ๋ธ์˜ ๋ชจ๋“  ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ • ๋˜๋Š” ๊ตฌ์„ฑ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +* ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `.env` ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `@lru_cache`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ์š”์ฒญ๋งˆ๋‹ค dotenv ํŒŒ์ผ์„ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋ฉด์„œ๋„, ํ…Œ์ŠคํŠธ ์ค‘์—๋Š” ์ด๋ฅผ overrideํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md new file mode 100644 index 0000000000..d8c2df2d8d --- /dev/null +++ b/docs/ko/docs/alternatives.md @@ -0,0 +1,485 @@ +# ๋Œ€์•ˆ, ์˜๊ฐ, ๋น„๊ต { #alternatives-inspiration-and-comparisons } + +**FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ๋“ค, ๋Œ€์•ˆ๊ณผ์˜ ๋น„๊ต, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋กœ๋ถ€ํ„ฐ ๋ฌด์—‡์„ ๋ฐฐ์› ๋Š”์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. + +## ์†Œ๊ฐœ { #intro } + +๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์ด์ „ ์ž‘์—…์ด ์—†์—ˆ๋‹ค๋ฉด **FastAPI**๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ ์ „์— ๋งŒ๋“ค์–ด์ง„ ๋งŽ์€ ๋„๊ตฌ๋“ค์ด **FastAPI**์˜ ํƒ„์ƒ์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. + +์ €๋Š” ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ ์ƒˆ๋กœ์šด framework๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € **FastAPI**๊ฐ€ ๋‹ค๋ฃจ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์—ฌ๋Ÿฌ ์„œ๋กœ ๋‹ค๋ฅธ framework, plug-in, ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•ด ๋ณด๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์–ด๋А ์‹œ์ ์—๋Š”, ์ด์ „ ๋„๊ตฌ๋“ค์˜ ๊ฐ€์žฅ ์ข‹์€ ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ€๋Šฅํ•œ ์ตœ์„ ์˜ ๋ฐฉ์‹์œผ๋กœ ์กฐํ•ฉํ•˜๊ณ , ์ด์ „์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜๋˜ ์–ธ์–ด ๊ธฐ๋Šฅ(Python 3.6+ type hints)์„ ํ™œ์šฉํ•ด ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ ์™ธ์—๋Š” ๋‹ค๋ฅธ ์„ ํƒ์ง€๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. + +## ์ด์ „ ๋„๊ตฌ๋“ค { #previous-tools } + +### Django { #django } + +๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” Python framework์ด๋ฉฐ ๋„๋ฆฌ ์‹ ๋ขฐ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Instagram ๊ฐ™์€ ์‹œ์Šคํ…œ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +์ƒ๋Œ€์ ์œผ๋กœ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(์˜ˆ: MySQL ๋˜๋Š” PostgreSQL)์™€ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์–ด์„œ, NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(์˜ˆ: Couchbase, MongoDB, Cassandra ๋“ฑ)๋ฅผ ์ฃผ ์ €์žฅ ์—”์ง„์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋ฆฌ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +๋ฐฑ์—”๋“œ์—์„œ HTML์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์ง€, ํ˜„๋Œ€์ ์ธ ํ”„๋ŸฐํŠธ์—”๋“œ(์˜ˆ: React, Vue.js, Angular)๋‚˜ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ(์˜ˆ: IoT ๊ธฐ๊ธฐ)์—์„œ ์‚ฌ์šฉ๋˜๋Š” API๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. + +### Django REST Framework { #django-rest-framework } + +Django REST framework๋Š” Django๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Web API๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ์œ ์—ฐํ•œ toolkit์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๊ณ , Django์˜ API ๊ธฐ๋Šฅ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +Mozilla, Red Hat, Eventbrite๋ฅผ ํฌํ•จํ•ด ๋งŽ์€ ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +**์ž๋™ API ๋ฌธ์„œํ™”**์˜ ์ดˆ๊ธฐ ์‚ฌ๋ก€ ์ค‘ ํ•˜๋‚˜์˜€๊ณ , ์ด๊ฒƒ์ด ํŠนํžˆ **FastAPI**๋ฅผ "์ฐพ๊ฒŒ ๋œ" ์ฒซ ์•„์ด๋””์–ด ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. + +/// note | ์ฐธ๊ณ  + +Django REST Framework๋Š” Tom Christie๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. **FastAPI**์˜ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” Starlette์™€ Uvicorn์„ ๋งŒ๋“  ์‚ฌ๋žŒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +์ž๋™ API ๋ฌธ์„œํ™” ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ. + +/// + +### Flask { #flask } + +Flask๋Š” "microframework"๋กœ, Django์— ๊ธฐ๋ณธ์œผ๋กœ ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ตํ•ฉ์ด๋‚˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์„ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ด ๋‹จ์ˆœํ•จ๊ณผ ์œ ์—ฐ์„ฑ ๋•๋ถ„์— NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ฃผ ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹œ์Šคํ…œ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ™์€ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. + +๋งค์šฐ ๋‹จ์ˆœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๊ต์  ์ง๊ด€์ ์œผ๋กœ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฌธ์„œ๊ฐ€ ์–ด๋–ค ์ง€์ ์—์„œ๋Š” ๋‹ค์†Œ ๊ธฐ์ˆ ์ ์œผ๋กœ ๊นŠ์–ด์ง€๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. + +๋˜ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ, ํ˜น์€ Django์— ๋ฏธ๋ฆฌ ๊ตฌ์ถ•๋˜์–ด ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ๊ผญ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋„ ํ”ํžˆ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค ์ค‘ ๋‹ค์ˆ˜๋Š” plug-in์œผ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Ÿฐ ๊ตฌ์„ฑ์š”์†Œ์˜ ๋ถ„๋ฆฌ์™€, ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์ •ํ™•ํžˆ ๋ง๋ถ™์—ฌ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” "microframework"๋ผ๋Š” ์ ์€ ์ œ๊ฐ€ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ํ•ต์‹ฌ ํŠน์„ฑ์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +Flask์˜ ๋‹จ์ˆœํ•จ์„ ๊ณ ๋ คํ•˜๋ฉด API๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ž˜ ๋งž๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์ฐพ๊ณ ์ž ํ–ˆ๋˜ ๊ฒƒ์€ Flask์šฉ "Django REST Framework"์˜€์Šต๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +micro-framework๊ฐ€ ๋˜๊ธฐ. ํ•„์š”ํ•œ ๋„๊ตฌ์™€ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ. + +๋‹จ์ˆœํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด routing ์‹œ์Šคํ…œ์„ ๊ฐ–๊ธฐ. + +/// + +### Requests { #requests } + +**FastAPI**๋Š” ์‹ค์ œ๋กœ **Requests**์˜ ๋Œ€์•ˆ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‘˜์˜ ๋ฒ”์œ„๋Š” ๋งค์šฐ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. + +์‹ค์ œ๋กœ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ *๋‚ด๋ถ€์—์„œ* Requests๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ํ”ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ์—๋„ FastAPI๋Š” Requests๋กœ๋ถ€ํ„ฐ ๊ฝค ๋งŽ์€ ์˜๊ฐ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. + +**Requests**๋Š” (ํด๋ผ์ด์–ธํŠธ๋กœ์„œ) API์™€ *์ƒํ˜ธ์ž‘์šฉ*ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ , **FastAPI**๋Š” (์„œ๋ฒ„๋กœ์„œ) API๋ฅผ *๊ตฌ์ถ•*ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. + +๋Œ€๋žต ๋งํ•˜๋ฉด ์„œ๋กœ ๋ฐ˜๋Œ€ํŽธ์— ์žˆ์œผ๋ฉฐ, ์„œ๋กœ๋ฅผ ๋ณด์™„ํ•ฉ๋‹ˆ๋‹ค. + +Requests๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ธ ์„ค๊ณ„๋ฅผ ๊ฐ€์กŒ๊ณ , ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์•„์ฃผ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋™์‹œ์— ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๊ณ  ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ๊ณต์‹ ์›น์‚ฌ์ดํŠธ์—์„œ ๋งํ•˜๋“ฏ์ด: + +> Requests is one of the most downloaded Python packages of all time + +์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `GET` ์š”์ฒญ์„ ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค: + +```Python +response = requests.get("http://example.com/some/url") +``` + +์ด์— ๋Œ€์‘ํ•˜๋Š” FastAPI์˜ API *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +`requests.get(...)`์™€ `@app.get(...)`์˜ ์œ ์‚ฌ์„ฑ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +* ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ธ API๋ฅผ ๊ฐ–๊ธฐ. +* HTTP method ์ด๋ฆ„(operations)์„ ์ง์ ‘, ์ง๊ด€์ ์ด๊ณ  ๋ช…ํ™•ํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ. +* ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•˜๋˜, ๊ฐ•๋ ฅํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ. + +/// + +### Swagger / OpenAPI { #swagger-openapi } + +์ œ๊ฐ€ Django REST Framework์—์„œ ๊ฐ€์žฅ ์›ํ–ˆ๋˜ ์ฃผ์š” ๊ธฐ๋Šฅ์€ ์ž๋™ API ๋ฌธ์„œํ™”์˜€์Šต๋‹ˆ๋‹ค. + +๊ทธ ํ›„ JSON(๋˜๋Š” JSON์˜ ํ™•์žฅ์ธ YAML)์„ ์‚ฌ์šฉํ•ด API๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ํ‘œ์ค€์ธ Swagger๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  Swagger API๋ฅผ ์œ„ํ•œ ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ API์— ๋Œ€ํ•œ Swagger ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ด ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž๋™์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +์–ด๋А ์‹œ์ ์— Swagger๋Š” Linux Foundation์œผ๋กœ ๋„˜์–ด๊ฐ€ OpenAPI๋กœ ์ด๋ฆ„์ด ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ 2.0 ๋ฒ„์ „์„ ์ด์•ผ๊ธฐํ•  ๋•Œ๋Š” "Swagger"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๊ณ , 3+ ๋ฒ„์ „์€ "OpenAPI"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +์ปค์Šคํ…€ schema ๋Œ€์‹ , API ์‚ฌ์–‘์„ ์œ„ํ•œ ์—ด๋ฆฐ ํ‘œ์ค€์„ ์ฑ„ํƒํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ. + +๋˜ํ•œ ํ‘œ์ค€ ๊ธฐ๋ฐ˜์˜ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ•˜๊ธฐ: + +* Swagger UI +* ReDoc + +์ด ๋‘ ๊ฐ€์ง€๋Š” ๊ฝค ๋Œ€์ค‘์ ์ด๊ณ  ์•ˆ์ •์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํžˆ ๊ฒ€์ƒ‰ํ•ด๋ณด๋ฉด OpenAPI๋ฅผ ์œ„ํ•œ ๋Œ€์•ˆ UI๊ฐ€ ์ˆ˜์‹ญ ๊ฐ€์ง€๋‚˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(**FastAPI**์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). + +/// + +### Flask REST framework๋“ค { #flask-rest-frameworks } + +Flask REST framework๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์žˆ์ง€๋งŒ, ์‹œ๊ฐ„์„ ๋“ค์—ฌ ์กฐ์‚ฌํ•ด ๋ณธ ๊ฒฐ๊ณผ, ์ƒ๋‹น์ˆ˜๊ฐ€ ์ค‘๋‹จ๋˜์—ˆ๊ฑฐ๋‚˜ ๋ฐฉ์น˜๋˜์–ด ์žˆ์—ˆ๊ณ , ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ์—ฌ๋Ÿฌ ์ด์Šˆ ๋•Œ๋ฌธ์— ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. + +### Marshmallow { #marshmallow } + +API ์‹œ์Šคํ…œ์— ํ•„์š”ํ•œ ์ฃผ์š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ "serialization"์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ(Python)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋„คํŠธ์›Œํฌ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ JSON ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, `datetime` ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค. + +API์— ๋˜ ํ•˜๋‚˜ ํฌ๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค ํ•„๋“œ๊ฐ€ `int`์ธ์ง€, ์ž„์˜์˜ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ์‹์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ์‹œ์Šคํ…œ์ด ์—†๋‹ค๋ฉด, ๋ชจ๋“  ๊ฒ€์‚ฌ๋ฅผ ์ฝ”๋“œ์—์„œ ์ˆ˜๋™์œผ๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด Marshmallow๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ํ›Œ๋ฅญํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฉฐ, ์ €๋„ ์ด์ „์— ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ Python type hints๊ฐ€ ์กด์žฌํ•˜๊ธฐ ์ „์— ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ schema๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด Marshmallow๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +๋ฐ์ดํ„ฐ ํƒ€์ž…๊ณผ ๊ฒ€์ฆ์„ ์ œ๊ณตํ•˜๋Š” "schema"๋ฅผ ์ฝ”๋“œ๋กœ ์ •์˜ํ•˜๊ณ , ์ด๋ฅผ ์ž๋™์œผ๋กœ ํ™œ์šฉํ•˜๊ธฐ. + +/// + +### Webargs { #webargs } + +API์— ํ•„์š”ํ•œ ๋˜ ๋‹ค๋ฅธ ํฐ ๊ธฐ๋Šฅ์€ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ parsingํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +Webargs๋Š” Flask๋ฅผ ํฌํ•จํ•œ ์—ฌ๋Ÿฌ framework ์œ„์—์„œ ์ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. + +๋‚ด๋ถ€์ ์œผ๋กœ Marshmallow๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. + +์•„์ฃผ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ด๋ฉฐ, ์ €๋„ **FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์ „์— ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +Webargs๋Š” Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +๋“ค์–ด์˜ค๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ์˜ ์ž๋™ ๊ฒ€์ฆ์„ ๊ฐ–๊ธฐ. + +/// + +### APISpec { #apispec } + +Marshmallow์™€ Webargs๋Š” plug-in ํ˜•ํƒœ๋กœ ๊ฒ€์ฆ, parsing, serialization์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋ฌธ์„œํ™”๋Š” ์—ฌ์ „ํžˆ ๋ถ€์กฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ APISpec์ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ์—ฌ๋Ÿฌ framework๋ฅผ ์œ„ํ•œ plug-in์ด๋ฉฐ(Starlette์šฉ plug-in๋„ ์žˆ์Šต๋‹ˆ๋‹ค). + +์ž‘๋™ ๋ฐฉ์‹์€, ๊ฐ route๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜์˜ docstring ์•ˆ์— YAML ํ˜•์‹์œผ๋กœ schema ์ •์˜๋ฅผ ์ž‘์„ฑํ•˜๊ณ , + +๊ทธ๋กœ๋ถ€ํ„ฐ OpenAPI schema๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +Flask, Starlette, Responder ๋“ฑ์—์„œ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋‹ค์‹œ, Python ๋ฌธ์ž์—ด ๋‚ด๋ถ€(ํฐ YAML)์—์„œ micro-syntax๋ฅผ ๋‹ค๋ฃจ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—๋””ํ„ฐ๊ฐ€ ์ด๋ฅผ ํฌ๊ฒŒ ๋„์™€์ฃผ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ Marshmallow schema๋ฅผ ์ˆ˜์ •ํ•ด๋†“๊ณ  YAML docstring๋„ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๋ฉด, ์ƒ์„ฑ๋œ schema๋Š” ์˜ค๋ž˜๋œ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +APISpec์€ Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +API๋ฅผ ์œ„ํ•œ ์—ด๋ฆฐ ํ‘œ์ค€์ธ OpenAPI๋ฅผ ์ง€์›ํ•˜๊ธฐ. + +/// + +### Flask-apispec { #flask-apispec } + +Flask plug-in์œผ๋กœ, Webargs, Marshmallow, APISpec์„ ๋ฌถ์–ด์ค๋‹ˆ๋‹ค. + +Webargs์™€ Marshmallow์˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•ด APISpec์œผ๋กœ OpenAPI schema๋ฅผ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ธ๋ฐ๋„ ๊ณผ์†Œํ‰๊ฐ€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋งŽ์€ Flask plug-in๋ณด๋‹ค ํ›จ์”ฌ ๋” ์œ ๋ช…ํ•ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ๊ฐ€ ๋„ˆ๋ฌด ๊ฐ„๊ฒฐํ•˜๊ณ  ์ถ”์ƒ์ ์ด๋ผ์„œ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋„๊ตฌ๋Š” Python docstring ๋‚ด๋ถ€์— YAML(๋˜ ๋‹ค๋ฅธ ๋ฌธ๋ฒ•)์„ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. + +Flask + Flask-apispec + Marshmallow + Webargs ์กฐํ•ฉ์€ **FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์ „๊นŒ์ง€ ์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋˜ ๋ฐฑ์—”๋“œ stack์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์—ฌ๋Ÿฌ Flask full-stack generator๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์ด ์ง€๊ธˆ๊นŒ์ง€ ์ €(๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ์™ธ๋ถ€ ํŒ€)๊ฐ€ ์‚ฌ์šฉํ•ด ์˜จ ์ฃผ์š” stack์ž…๋‹ˆ๋‹ค: + +* https://github.com/tiangolo/full-stack +* https://github.com/tiangolo/full-stack-flask-couchbase +* https://github.com/tiangolo/full-stack-flask-couchdb + +๊ทธ๋ฆฌ๊ณ  ์ด ๋™์ผํ•œ full-stack generator๋“ค์ด [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}์˜ ๊ธฐ๋ฐ˜์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +Flask-apispec์€ Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +serialization๊ณผ validation์„ ์ •์˜ํ•˜๋Š” ๋™์ผํ•œ ์ฝ”๋“œ๋กœ๋ถ€ํ„ฐ OpenAPI schema๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜๊ธฐ. + +/// + +### NestJS (๊ทธ๋ฆฌ๊ณ  Angular) { #nestjs-and-angular } + +์ด๊ฑด Python๋„ ์•„๋‹™๋‹ˆ๋‹ค. NestJS๋Š” Angular์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ JavaScript(TypeScript) NodeJS framework์ž…๋‹ˆ๋‹ค. + +Flask-apispec์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ์–ด๋А ์ •๋„ ๋น„์Šทํ•œ ๊ฒƒ์„ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +Angular 2์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์ด ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์•„๋Š” ๋‹ค๋ฅธ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ๋“ค์ฒ˜๋Ÿผ "injectable"์„ ์‚ฌ์ „์— ๋“ฑ๋กํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์žฅํ™ฉํ•จ๊ณผ ์ฝ”๋“œ ๋ฐ˜๋ณต์ด ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค. + +ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ TypeScript ํƒ€์ž…(Python type hints์™€ ์œ ์‚ฌํ•จ)์œผ๋กœ ์„ค๋ช…๋˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋””ํ„ฐ ์ง€์›์€ ๊ฝค ์ข‹์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ TypeScript ๋ฐ์ดํ„ฐ๋Š” JavaScript๋กœ ์ปดํŒŒ์ผ๋œ ๋’ค์—๋Š” ๋ณด์กด๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ํƒ€์ž…์— ์˜์กดํ•ด ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋ฅผ ๋™์‹œ์— ์ •์˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์ ๊ณผ ์ผ๋ถ€ ์„ค๊ณ„ ๊ฒฐ์ • ๋•Œ๋ฌธ์—, ๊ฒ€์ฆ/serialization/์ž๋™ schema ์ƒ์„ฑ์„ ํ•˜๋ ค๋ฉด ์—ฌ๋Ÿฌ ๊ณณ์— decorator๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋งค์šฐ ์žฅํ™ฉํ•ด์ง‘๋‹ˆ๋‹ค. + +์ค‘์ฒฉ ๋ชจ๋ธ์„ ์ž˜ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์š”์ฒญ์˜ JSON body๊ฐ€ ๋‚ด๋ถ€ ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ JSON ๊ฐ์ฒด์ด๊ณ  ๊ทธ ๋‚ด๋ถ€ ํ•„๋“œ๋“ค์ด ๋‹ค์‹œ ์ค‘์ฒฉ๋œ JSON ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ, ์ œ๋Œ€๋กœ ๋ฌธ์„œํ™”ํ•˜๊ณ  ๊ฒ€์ฆํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +Python ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ๋›ฐ์–ด๋‚œ ์—๋””ํ„ฐ ์ง€์›์„ ์ œ๊ณตํ•˜๊ธฐ. + +๊ฐ•๋ ฅํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์„ ๊ฐ–์ถ”๊ธฐ. ์ฝ”๋“œ ๋ฐ˜๋ณต์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ. + +/// + +### Sanic { #sanic } + +`asyncio` ๊ธฐ๋ฐ˜์˜ ๋งค์šฐ ๋น ๋ฅธ Python framework ์ค‘ ์ดˆ๊ธฐ ์‚ฌ๋ก€์˜€์Šต๋‹ˆ๋‹ค. Flask์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +๊ธฐ๋ณธ Python `asyncio` ๋ฃจํ”„ ๋Œ€์‹  `uvloop`๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“  ์š”์ธ์ž…๋‹ˆ๋‹ค. + +์ด๋Š” Uvicorn๊ณผ Starlette์— ๋ช…ํ™•ํžˆ ์˜๊ฐ์„ ์ฃผ์—ˆ๊ณ , ํ˜„์žฌ ๊ณต๊ฐœ benchmark์—์„œ๋Š” ์ด ๋‘˜์ด Sanic๋ณด๋‹ค ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +๋ฏธ์นœ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ. + +๊ทธ๋ž˜์„œ **FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. Starlette๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ framework ์ค‘ ๊ฐ€์žฅ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์„œ๋“œํŒŒํ‹ฐ benchmark๋กœ ํ…Œ์ŠคํŠธ๋จ). + +/// + +### Falcon { #falcon } + +Falcon์€ ๋˜ ๋‹ค๋ฅธ ๊ณ ์„ฑ๋Šฅ Python framework๋กœ, ์ตœ์†Œํ•œ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ณ  Hug ๊ฐ™์€ ๋‹ค๋ฅธ framework์˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. + +ํ•จ์ˆ˜๊ฐ€ ๋‘ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ(ํ•˜๋‚˜๋Š” "request", ํ•˜๋‚˜๋Š” "response")๋ฅผ ๋ฐ›๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ request์—์„œ ์ผ๋ถ€๋ฅผ "์ฝ๊ณ ", response์— ์ผ๋ถ€๋ฅผ "์ž‘์„ฑ"ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค๊ณ„ ๋•Œ๋ฌธ์—, ํ‘œ์ค€ Python type hints๋ฅผ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‚ฌ์šฉํ•ด ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ body๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋Š” ์ž๋™์œผ๋กœ ๋˜์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” Hug์ฒ˜๋Ÿผ Falcon ์œ„์— framework๋ฅผ ์–น์–ด ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. request ๊ฐ์ฒด ํ•˜๋‚˜์™€ response ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” Falcon์˜ ์„ค๊ณ„์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ๋‹ค๋ฅธ framework์—์„œ๋„ ๊ฐ™์€ ๊ตฌ๋ถ„์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +ํ›Œ๋ฅญํ•œ ์„ฑ๋Šฅ์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ. + +Hug(= Falcon ๊ธฐ๋ฐ˜)๊ณผ ํ•จ๊ป˜, ํ•จ์ˆ˜์—์„œ `response` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค๋งŒ FastAPI์—์„œ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ, ์ฃผ๋กœ ํ—ค๋”, ์ฟ ํ‚ค, ๊ทธ๋ฆฌ๊ณ  ๋Œ€์ฒด status code๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +/// + +### Molten { #molten } + +**FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ•œ ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ Molten์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ , ๊ฝค ๋น„์Šทํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ฐ–๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค: + +* Python type hints ๊ธฐ๋ฐ˜ +* ์ด ํƒ€์ž…์œผ๋กœ๋ถ€ํ„ฐ ๊ฒ€์ฆ๊ณผ ๋ฌธ์„œํ™” ์ƒ์„ฑ +* ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ + +Pydantic ๊ฐ™์€ ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ/serialization/๋ฌธ์„œํ™”๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ์ž์ฒด ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ •์˜๋ฅผ ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. + +์กฐ๊ธˆ ๋” ์žฅํ™ฉํ•œ ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ WSGI(ASGI๊ฐ€ ์•„๋‹ˆ๋ผ) ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ, Uvicorn, Starlette, Sanic ๊ฐ™์€ ๋„๊ตฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ์„ ํ™œ์šฉํ•˜๋„๋ก ์„ค๊ณ„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. + +์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์€ ์˜์กด์„ฑ์„ ์‚ฌ์ „์— ๋“ฑ๋กํ•ด์•ผ ํ•˜๊ณ , ์„ ์–ธ๋œ ํƒ€์ž…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜์กด์„ฑ์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŠน์ • ํƒ€์ž…์„ ์ œ๊ณตํ•˜๋Š” "component"๋ฅผ ๋‘ ๊ฐœ ์ด์ƒ ์„ ์–ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + +Route๋Š” ํ•œ ๊ณณ์—์„œ ์„ ์–ธํ•˜๊ณ , ๋‹ค๋ฅธ ๊ณณ์— ์„ ์–ธ๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์—”๋“œํฌ์ธํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜ ๋ฐ”๋กœ ์œ„์— ๋‘˜ ์ˆ˜ ์žˆ๋Š” decorator๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ ). ์ด๋Š” Flask(๋ฐ Starlette)๋ณด๋‹ค๋Š” Django ๋ฐฉ์‹์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ์ƒ๋Œ€์ ์œผ๋กœ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ๊ฒƒ๋“ค์„ ๋ถ„๋ฆฌํ•ด ๋†“์Šต๋‹ˆ๋‹ค. + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +๋ชจ๋ธ ์†์„ฑ์˜ "default" ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ ํƒ€์ž…์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๊ฒ€์ฆ์„ ์ •์˜ํ•˜๊ธฐ. ์ด๋Š” ์—๋””ํ„ฐ ์ง€์›์„ ๊ฐœ์„ ํ•˜๋ฉฐ, ์ด์ „์—๋Š” Pydantic์— ์—†์—ˆ์Šต๋‹ˆ๋‹ค. + +์ด๊ฒƒ์€ ์‹ค์ œ๋กœ Pydantic์˜ ์ผ๋ถ€๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ๊ฐ™์€ ๊ฒ€์ฆ ์„ ์–ธ ์Šคํƒ€์ผ์„ ์ง€์›ํ•˜๋„๋ก ํ•˜๋Š” ๋ฐ ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค(์ด ๊ธฐ๋Šฅ์€ ์ด์ œ Pydantic์— ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค). + +/// + +### Hug { #hug } + +Hug๋Š” Python type hints๋ฅผ ์‚ฌ์šฉํ•ด API ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ์ดˆ๊ธฐ framework ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค๋„ ๊ฐ™์€ ๋ฐฉ์‹์„ ํ•˜๋„๋ก ์˜๊ฐ์„ ์ค€ ํ›Œ๋ฅญํ•œ ์•„์ด๋””์–ด์˜€์Šต๋‹ˆ๋‹ค. + +ํ‘œ์ค€ Python ํƒ€์ž… ๋Œ€์‹  ์ปค์Šคํ…€ ํƒ€์ž…์„ ์„ ์–ธ์— ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ํฐ ์ง„์ „์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ ์ „์ฒด API๋ฅผ JSON์œผ๋กœ ์„ ์–ธํ•˜๋Š” ์ปค์Šคํ…€ schema๋ฅผ ์ƒ์„ฑํ•œ ์ดˆ๊ธฐ framework ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. + +OpenAPI๋‚˜ JSON Schema ๊ฐ™์€ ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— Swagger UI ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์€ ์ง๊ด€์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ญ์‹œ ๋งค์šฐ ํ˜์‹ ์ ์ธ ์•„์ด๋””์–ด์˜€์Šต๋‹ˆ๋‹ค. + +ํฅ๋ฏธ๋กญ๊ณ  ํ”์น˜ ์•Š์€ ๊ธฐ๋Šฅ์ด ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ framework๋กœ API๋ฟ ์•„๋‹ˆ๋ผ CLI๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋™๊ธฐ์‹ Python ์›น framework์˜ ์ด์ „ ํ‘œ์ค€(WSGI) ๊ธฐ๋ฐ˜์ด์–ด์„œ Websockets์™€ ๋‹ค๋ฅธ ๊ฒƒ๋“ค์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ์„ฑ๋Šฅ์€ ์—ฌ์ „ํžˆ ๋†’์Šต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +Hug๋Š” Timothy Crosley๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. Python ํŒŒ์ผ์—์„œ import๋ฅผ ์ž๋™์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ธ `isort`์˜ ์ œ์ž‘์ž์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ์•„์ด๋””์–ด๋“ค + +Hug๋Š” APIStar์˜ ์ผ๋ถ€์— ์˜๊ฐ์„ ์ฃผ์—ˆ๊ณ , ์ €๋Š” APIStar์™€ ํ•จ๊ป˜ Hug๋ฅผ ๊ฐ€์žฅ ์œ ๋งํ•œ ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๋กœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. + +Hug๋Š” Python type hints๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๊ณ , API๋ฅผ ์ •์˜ํ•˜๋Š” schema๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. + +Hug๋Š” ํ—ค๋”์™€ ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜์— `response` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. + +/// + +### APIStar (<= 0.5) { #apistar-0-5 } + +**FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ธฐ ์ง์ „์— **APIStar** ์„œ๋ฒ„๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฐพ๊ณ  ์žˆ๋˜ ๊ฑฐ์˜ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ–์ถ”๊ณ  ์žˆ์—ˆ๊ณ  ์„ค๊ณ„๋„ ํ›Œ๋ฅญํ–ˆ์Šต๋‹ˆ๋‹ค. + +NestJS์™€ Molten๋ณด๋‹ค ์•ž์„œ, Python type hints๋ฅผ ์‚ฌ์šฉํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์š”์ฒญ์„ ์„ ์–ธํ•˜๋Š” framework ๊ตฌํ˜„์„ ์ œ๊ฐ€ ์ฒ˜์Œ ๋ณธ ์‚ฌ๋ก€๋“ค ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. Hug์™€ ๊ฑฐ์˜ ๊ฐ™์€ ์‹œ๊ธฐ์— ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ APIStar๋Š” OpenAPI ํ‘œ์ค€์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ๋™์ผํ•œ type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, ๋ฐ์ดํ„ฐ serialization, OpenAPI schema ์ƒ์„ฑ์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. + +Body schema ์ •์˜๋Š” Pydantic์ฒ˜๋Ÿผ ๋™์ผํ•œ Python type hints๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋Š” ์•Š์•˜๊ณ  Marshmallow์™€ ์กฐ๊ธˆ ๋” ๋น„์Šทํ•ด์„œ ์—๋””ํ„ฐ ์ง€์›์€ ๊ทธ๋งŒํผ ์ข‹์ง€ ์•Š์•˜์ง€๋งŒ, ๊ทธ๋ž˜๋„ APIStar๋Š” ๋‹น์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์„ ์˜ ์„ ํƒ์ง€์˜€์Šต๋‹ˆ๋‹ค. + +๋‹น์‹œ ์ตœ๊ณ ์˜ ์„ฑ๋Šฅ benchmark๋ฅผ ๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค(Starlette์— ์˜ํ•ด์„œ๋งŒ ์ถ”์›”๋จ). + +์ฒ˜์Œ์—๋Š” ์ž๋™ API ๋ฌธ์„œํ™” ์›น UI๊ฐ€ ์—†์—ˆ์ง€๋งŒ, Swagger UI๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. + +์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค์ฒ˜๋Ÿผ component์˜ ์‚ฌ์ „ ๋“ฑ๋ก์ด ํ•„์š”ํ–ˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ํ›Œ๋ฅญํ•œ ๊ธฐ๋Šฅ์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +๋ณด์•ˆ ํ†ตํ•ฉ์ด ์—†์–ด์„œ ์ „์ฒด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Flask-apispec ๊ธฐ๋ฐ˜ full-stack generator๋กœ ๊ฐ–์ถ”๊ณ  ์žˆ๋˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” pull request๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ œ ๋ฐฑ๋กœ๊ทธ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ดํ›„ ํ”„๋กœ์ ํŠธ์˜ ์ดˆ์ ์ด ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. + +๋” ์ด์ƒ API web framework๊ฐ€ ์•„๋‹ˆ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ์ œ์ž‘์ž๊ฐ€ Starlette์— ์ง‘์ค‘ํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +์ด์ œ APIStar๋Š” web framework๊ฐ€ ์•„๋‹ˆ๋ผ OpenAPI ์‚ฌ์–‘์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +APIStar๋Š” Tom Christie๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ๋งŒ๋“  ์‚ฌ๋žŒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค: + +* Django REST Framework +* Starlette(**FastAPI**์˜ ๊ธฐ๋ฐ˜) +* Uvicorn(Starlette์™€ **FastAPI**์—์„œ ์‚ฌ์šฉ) + +/// + +/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ + +์กด์žฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ. + +๋™์ผํ•œ Python ํƒ€์ž…์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€(๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”)๋ฅผ ์„ ์–ธํ•˜๋ฉด์„œ ๋™์‹œ์— ๋›ฐ์–ด๋‚œ ์—๋””ํ„ฐ ์ง€์›์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด๋Š” ์ œ๊ฐ€ ๋งค์šฐ ํ›Œ๋ฅญํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์˜ค๋žซ๋™์•ˆ ๋น„์Šทํ•œ framework๋ฅผ ์ฐพ์•„ ์—ฌ๋Ÿฌ ๋Œ€์•ˆ์„ ํ…Œ์ŠคํŠธํ•œ ๋์—, APIStar๊ฐ€ ๊ทธ๋•Œ ์ด์šฉ ๊ฐ€๋Šฅํ•œ ์ตœ์„ ์˜ ์„ ํƒ์ง€์˜€์Šต๋‹ˆ๋‹ค. + +๊ทธ ํ›„ APIStar ์„œ๋ฒ„๊ฐ€ ๋”๋Š” ์กด์žฌํ•˜์ง€ ์•Š๊ฒŒ ๋˜๊ณ  Starlette๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๋Š”๋ฐ, ์ด๋Š” ๊ทธ๋Ÿฐ ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ๋” ์ƒˆ๋กญ๊ณ  ๋” ๋‚˜์€ ๊ธฐ๋ฐ˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด **FastAPI**๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋œ ์ตœ์ข… ์˜๊ฐ์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +์ €๋Š” **FastAPI**๋ฅผ APIStar์˜ "์ •์‹ ์  ํ›„๊ณ„์ž"๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋™์‹œ์—, ์ด ๋ชจ๋“  ์ด์ „ ๋„๊ตฌ๋“ค์—์„œ ๋ฐฐ์šด ๊ฒƒ๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ธฐ๋Šฅ, typing ์‹œ์Šคํ…œ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋ถ€๋ถ„๋“ค์„ ๊ฐœ์„ ํ•˜๊ณ  ํ™•์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. + +/// + +## **FastAPI**๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ { #used-by-fastapi } + +### Pydantic { #pydantic } + +Pydantic์€ Python type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”(JSON Schema ์‚ฌ์šฉ)๋ฅผ ์ •์˜ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. + +๊ทธ ๋•๋ถ„์— ๋งค์šฐ ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. + +Marshmallow์™€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ benchmark์—์„œ Marshmallow๋ณด๋‹ค ๋น ๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋™์ผํ•œ Python type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ ์—๋””ํ„ฐ ์ง€์›๋„ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค. + +/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์  + +๋ชจ๋“  ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, ๋ฐ์ดํ„ฐ serialization, ์ž๋™ ๋ชจ๋ธ ๋ฌธ์„œํ™”(JSON Schema ๊ธฐ๋ฐ˜)๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ. + +๊ทธ ๋‹ค์Œ **FastAPI**๋Š” ๊ทธ JSON Schema ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ OpenAPI์— ํฌํ•จ์‹œํ‚ค๋ฉฐ, ๊ทธ ์™ธ์—๋„ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. + +/// + +### Starlette { #starlette } + +Starlette๋Š” ๊ฒฝ๋Ÿ‰ ASGI framework/toolkit์œผ๋กœ, ๊ณ ์„ฑ๋Šฅ asyncio ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. + +๋งค์šฐ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๊ณ , ๋ชจ๋“ˆ์‹ component๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +* ์ •๋ง ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ. +* WebSocket ์ง€์›. +* ํ”„๋กœ์„ธ์Šค ๋‚ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…. +* ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ์ด๋ฒคํŠธ. +* HTTPX ๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ ํด๋ผ์ด์–ธํŠธ. +* CORS, GZip, Static Files, Streaming responses. +* ์„ธ์…˜ ๋ฐ ์ฟ ํ‚ค ์ง€์›. +* 100% ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€. +* 100% ํƒ€์ž… ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ์ฝ”๋“œ๋ฒ ์ด์Šค. +* ์†Œ์ˆ˜์˜ ํ•„์ˆ˜ ์˜์กด์„ฑ. + +Starlette๋Š” ํ˜„์žฌ ํ…Œ์ŠคํŠธ๋œ Python framework ์ค‘ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค. ๋‹จ, framework๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์ธ Uvicorn์ด ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค. + +Starlette๋Š” ์›น microframework์˜ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ž๋™ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +๊ทธ๊ฒƒ์ด **FastAPI**๊ฐ€ ์œ„์— ์ถ”๊ฐ€ํ•˜๋Š” ํ•ต์‹ฌ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๋ชจ๋‘ Python type hints(Pydantic ์‚ฌ์šฉ)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋”ํ•ด ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ, ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ, OpenAPI schema ์ƒ์„ฑ ๋“ฑ๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +ASGI๋Š” Django ์ฝ”์–ด ํŒ€ ๋ฉค๋ฒ„๋“ค์ด ๊ฐœ๋ฐœ ์ค‘์ธ ์ƒˆ๋กœ์šด "ํ‘œ์ค€"์ž…๋‹ˆ๋‹ค. ์•„์ง "Python ํ‘œ์ค€"(PEP)์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ทธ ๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿผ์—๋„ ์ด๋ฏธ ์—ฌ๋Ÿฌ ๋„๊ตฌ์—์„œ "ํ‘œ์ค€"์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ƒํ˜ธ์šด์šฉ์„ฑ์„ ํฌ๊ฒŒ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Uvicorn์„ ๋‹ค๋ฅธ ASGI ์„œ๋ฒ„(์˜ˆ: Daphne ๋˜๋Š” Hypercorn)๋กœ ๊ต์ฒดํ•  ์ˆ˜๋„ ์žˆ๊ณ , `python-socketio` ๊ฐ™์€ ASGI ํ˜ธํ™˜ ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์  + +ํ•ต์‹ฌ ์›น ๋ถ€๋ถ„์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ธฐ. ๊ทธ ์œ„์— ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ. + +`FastAPI` ํด๋ž˜์Šค ์ž์ฒด๋Š” `Starlette` ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ Starlette๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋กœ๋„ ์ง์ ‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, **FastAPI**๋Š” ์‚ฌ์‹ค์ƒ Starlette์— ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๋”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// + +### Uvicorn { #uvicorn } + +Uvicorn์€ uvloop๊ณผ httptools๋กœ ๊ตฌ์ถ•๋œ ์ดˆ๊ณ ์† ASGI ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. + +web framework๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ routing์„ ์œ„ํ•œ ๋„๊ตฌ๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒƒ์€ Starlette(๋˜๋Š” **FastAPI**) ๊ฐ™์€ framework๊ฐ€ ์œ„์—์„œ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +Starlette์™€ **FastAPI**์—์„œ ๊ถŒ์žฅํ•˜๋Š” ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. + +/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹ + +**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์š” ์›น ์„œ๋ฒ„. + +๋˜ํ•œ `--workers` ์ปค๋งจ๋“œ๋ผ์ธ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๋™๊ธฐ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค ์„œ๋ฒ„๋กœ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ž์„ธํ•œ ๋‚ด์šฉ์€ [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank} ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”. + +/// + +## ๋ฒค์น˜๋งˆํฌ์™€ ์†๋„ { #benchmarks-and-speed } + +Uvicorn, Starlette, FastAPI ์‚ฌ์ด์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋น„๊ตํ•˜๋ ค๋ฉด [๋ฒค์น˜๋งˆํฌ](benchmarks.md){.internal-link target=_blank} ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”. diff --git a/docs/ko/docs/deployment/concepts.md b/docs/ko/docs/deployment/concepts.md new file mode 100644 index 0000000000..dd7edd1bae --- /dev/null +++ b/docs/ko/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# ๋ฐฐํฌ ๊ฐœ๋… { #deployments-concepts } + +**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์‚ฌ์‹ค ์–ด๋–ค ์ข…๋ฅ˜์˜ ์›น API๋“ )์„ ๋ฐฐํฌํ•  ๋•Œ๋Š”, ์—ฌ๋Ÿฌ๋ถ„์ด ์‹ ๊ฒฝ ์จ์•ผ ํ•  ์—ฌ๋Ÿฌ ๊ฐœ๋…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๊ฐœ๋…๋“ค์„ ํ™œ์šฉํ•˜๋ฉด **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•**์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ค‘์š”ํ•œ ๊ฐœ๋… ๋ช‡ ๊ฐ€์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ๋ณด์•ˆ - HTTPS +* ์‹œ์ž‘ ์‹œ ์‹คํ–‰ +* ์žฌ์‹œ์ž‘ +* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜) +* ๋ฉ”๋ชจ๋ฆฌ +* ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„ + +์ด๊ฒƒ๋“ค์ด **๋ฐฐํฌ**์— ์–ด๋–ค ์˜ํ–ฅ์„ ์ฃผ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +๊ฒฐ๊ตญ ์ตœ์ข… ๋ชฉํ‘œ๋Š” **API ํด๋ผ์ด์–ธํŠธ์— ์„œ๋น„์Šค๋ฅผ ์ œ๊ณต**ํ•  ๋•Œ **๋ณด์•ˆ**์„ ๋ณด์žฅํ•˜๊ณ , **์ค‘๋‹จ์„ ํ”ผํ•˜๋ฉฐ**, **์ปดํ“จํŒ… ๋ฆฌ์†Œ์Šค**(์˜ˆ: ์›๊ฒฉ ์„œ๋ฒ„/๊ฐ€์ƒ ๋จธ์‹ )๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿš€ + +์—ฌ๊ธฐ์„œ ์ด **๊ฐœ๋…๋“ค**์„ ์กฐ๊ธˆ ๋” ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์„œ๋กœ ๋งค์šฐ ๋‹ค๋ฅธ ํ™˜๊ฒฝ, ์‹ฌ์ง€์–ด ์•„์ง ์กด์žฌํ•˜์ง€ ์•Š๋Š” **๋ฏธ๋ž˜**์˜ ํ™˜๊ฒฝ์—์„œ๋„ API๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐํฌํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ **์ง๊ด€**์„ ์–ป์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด ๊ฐœ๋…๋“ค์„ ๊ณ ๋ คํ•˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ **์ž์‹ ์˜ API**๋ฅผ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์„ **ํ‰๊ฐ€ํ•˜๊ณ  ์„ค๊ณ„**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ๋” **๊ตฌ์ฒด์ ์ธ ๋ ˆ์‹œํ”ผ**๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€, ์ด ์ค‘์š”ํ•œ **๊ฐœ๋…์  ์•„์ด๋””์–ด**๋“ค์„ ํ™•์ธํ•ด ๋ด…์‹œ๋‹ค. ์ด ๊ฐœ๋…๋“ค์€ ๋‹ค๋ฅธ ์–ด๋–ค ์ข…๋ฅ˜์˜ ์›น API์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ’ก + +## ๋ณด์•ˆ - HTTPS { #security-https } + +[์ด์ „ HTTPS ์žฅ](https.md){.internal-link target=_blank}์—์„œ HTTPS๊ฐ€ API์— ์•”ํ˜ธํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ HTTPS๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ๋ฐ”๊นฅ์˜ **์™ธ๋ถ€** ์ปดํฌ๋„ŒํŠธ์ธ **TLS Termination Proxy**๊ฐ€ ์ œ๊ณตํ•œ๋‹ค๋Š” ๊ฒƒ๋„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  **HTTPS ์ธ์ฆ์„œ ๊ฐฑ์‹ **์„ ๋‹ด๋‹นํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ทธ ์—ญํ• ์„ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€๊ฐ€ ๋‹ด๋‹นํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +### HTTPS๋ฅผ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-for-https } + +TLS Termination Proxy๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* Traefik + * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ โœจ +* Caddy + * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ โœจ +* Nginx + * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด Certbot ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ +* HAProxy + * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด Certbot ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ +* Nginx ๊ฐ™์€ Ingress Controller๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Kubernetes + * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด cert-manager ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ +* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ(์•„๋ž˜๋ฅผ ์ฝ์–ด๋ณด์„ธ์š” ๐Ÿ‘‡) + +๋˜ ๋‹ค๋ฅธ ์„ ํƒ์ง€๋Š” HTTPS ์„ค์ •์„ ํฌํ•จํ•ด ๋” ๋งŽ์€ ์ผ์„ ๋Œ€์‹ ํ•ด์ฃผ๋Š” **ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ์•ฝ์ด ์žˆ๊ฑฐ๋‚˜ ๋น„์šฉ์ด ๋” ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ๊ฒฝ์šฐ์—๋Š” TLS Termination Proxy๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ ์žฅ์—์„œ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. + +--- + +๋‹ค์Œ์œผ๋กœ ๊ณ ๋ คํ•  ๊ฐœ๋…๋“ค์€ ์‹ค์ œ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)๊ณผ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. + +## ํ”„๋กœ๊ทธ๋žจ๊ณผ ํ”„๋กœ์„ธ์Šค { #program-and-process } + +์‹คํ–‰ ์ค‘์ธ "**ํ”„๋กœ์„ธ์Šค**"์— ๋Œ€ํ•ด ๋งŽ์ด ์ด์•ผ๊ธฐํ•˜๊ฒŒ ๋  ํ…๋ฐ, ์ด ๋ง์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  "**ํ”„๋กœ๊ทธ๋žจ**"์ด๋ผ๋Š” ๋‹จ์–ด์™€ ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€ ๋ช…ํ™•ํžˆ ํ•ด๋‘๋Š” ๊ฒƒ์ด ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +### ํ”„๋กœ๊ทธ๋žจ์ด๋ž€ { #what-is-a-program } + +**ํ”„๋กœ๊ทธ๋žจ**์ด๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค: + +* ์—ฌ๋Ÿฌ๋ถ„์ด ์ž‘์„ฑํ•˜๋Š” **์ฝ”๋“œ**, ์ฆ‰ **Python ํŒŒ์ผ**๋“ค +* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰**ํ•  ์ˆ˜ ์žˆ๋Š” **ํŒŒ์ผ**, ์˜ˆ: `python`, `python.exe`, `uvicorn` +* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰ ์ค‘**์ธ ํŠน์ • ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ, CPU๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์— ๋‚ด์šฉ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ **ํ”„๋กœ์„ธ์Šค**๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค. + +### ํ”„๋กœ์„ธ์Šค๋ž€ { #what-is-a-process } + +**ํ”„๋กœ์„ธ์Šค**๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ๋” ๊ตฌ์ฒด์ ์œผ๋กœ, ์šด์˜์ฒด์ œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๊ฒƒ(์œ„ ๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์ฒ˜๋Ÿผ)๋งŒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค: + +* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰ ์ค‘**์ธ ํŠน์ • ํ”„๋กœ๊ทธ๋žจ + * ํŒŒ์ผ์ด๋‚˜ ์ฝ”๋“œ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์šด์˜์ฒด์ œ๊ฐ€ **์‹ค์ œ๋กœ ์‹คํ–‰**ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋Œ€์ƒ์„ **๊ตฌ์ฒด์ ์œผ๋กœ** ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. +* ์–ด๋–ค ํ”„๋กœ๊ทธ๋žจ์ด๋“  ์–ด๋–ค ์ฝ”๋“œ๋“ , **์‹คํ–‰**๋  ๋•Œ๋งŒ ๋ฌด์–ธ๊ฐ€๋ฅผ **ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค**. ์ฆ‰, **ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘**์ผ ๋•Œ์ž…๋‹ˆ๋‹ค. +* ํ”„๋กœ์„ธ์Šค๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด, ํ˜น์€ ์šด์˜์ฒด์ œ๊ฐ€ **์ข…๋ฃŒ**(๋˜๋Š” โ€œkillโ€)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์‹คํ–‰์ด ๋ฉˆ์ถ”๊ณ , ๋” ์ด์ƒ **์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค**. +* ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋’ค์—๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ, ๊ฐ ์ฐฝ ๋“ฑ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปดํ“จํ„ฐ๊ฐ€ ์ผœ์ ธ ์žˆ๋Š” ๋™์•ˆ ๋ณดํ†ต ๋งŽ์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ **๋™์‹œ์—** ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. +* **๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ**์˜ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์šด์˜์ฒด์ œ์˜ โ€œ์ž‘์—… ๊ด€๋ฆฌ์ž(task manager)โ€๋‚˜ โ€œ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ(system monitor)โ€(๋˜๋Š” ๋น„์Šทํ•œ ๋„๊ตฌ)๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด, ์ด๋Ÿฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋งŽ์ด ์‹คํ–‰ ์ค‘์ธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋˜ ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ™์€ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ๊ทธ๋žจ(Firefox, Chrome, Edge ๋“ฑ)์„ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋Š” ๊ฒƒ๋„ ๋ณด์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ๋ณดํ†ต ํƒญ๋งˆ๋‹ค ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ๊ทธ ์™ธ์—๋„ ์ถ”๊ฐ€ ํ”„๋กœ์„ธ์Šค ๋ช‡ ๊ฐœ๊ฐ€ ๋” ์žˆ์Šต๋‹ˆ๋‹ค. + + + +--- + +์ด์ œ **ํ”„๋กœ์„ธ์Šค**์™€ **ํ”„๋กœ๊ทธ๋žจ**์˜ ์ฐจ์ด๋ฅผ ์•Œ์•˜์œผ๋‹ˆ, ๋ฐฐํฌ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ๊ณ„์†ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์‹œ์ž‘ ์‹œ ์‹คํ–‰ { #running-on-startup } + +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์›น API๋ฅผ ๋งŒ๋“ค๋ฉด, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ธ์ œ๋‚˜ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก **ํ•ญ์ƒ ์‹คํ–‰**๋˜๊ณ  ์ค‘๋‹จ๋˜์ง€ ์•Š๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ํŠน์ • ์ƒํ™ฉ์—์„œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์žˆ์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์€ ์ง€์†์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ **์‚ฌ์šฉ ๊ฐ€๋Šฅ**ํ•œ ์ƒํƒœ์ด๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. + +### ์›๊ฒฉ ์„œ๋ฒ„์—์„œ { #in-a-remote-server } + +์›๊ฒฉ ์„œ๋ฒ„(ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„, ๊ฐ€์ƒ ๋จธ์‹  ๋“ฑ)๋ฅผ ์„ค์ •ํ•  ๋•Œ, ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ๋•Œ์ฒ˜๋Ÿผ ์ˆ˜๋™์œผ๋กœ `fastapi run`(Uvicorn์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค)์ด๋‚˜ ๋น„์Šทํ•œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด ๋ฐฉ์‹์€ ๋™์ž‘ํ•˜๊ณ , **๊ฐœ๋ฐœ ์ค‘์—๋Š”** ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์„œ๋ฒ„์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์ด ๋Š๊ธฐ๋ฉด, ์‹คํ–‰ ์ค‘์ธ **ํ”„๋กœ์„ธ์Šค**๋„ ์•„๋งˆ ์ข…๋ฃŒ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ ์„œ๋ฒ„๊ฐ€ ์žฌ์‹œ์ž‘๋˜๋ฉด(์˜ˆ: ์—…๋ฐ์ดํŠธ ์ดํ›„, ํ˜น์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ดํ›„) ์—ฌ๋Ÿฌ๋ถ„์€ ์•„๋งˆ **์•Œ์•„์ฐจ๋ฆฌ์ง€ ๋ชปํ• ** ๊ฒ๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ, ํ”„๋กœ์„ธ์Šค๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค๋„ ๋ชจ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด API๋Š” ๊ทธ๋ƒฅ ์ฃฝ์€ ์ƒํƒœ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ฑ + +### ์‹œ์ž‘ ์‹œ ์ž๋™ ์‹คํ–‰ { #run-automatically-on-startup } + +์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)์€ ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์ž๋™์œผ๋กœ ์‹œ์ž‘๋˜๊ณ , **์‚ฌ๋žŒ์˜ ๊ฐœ์ž…** ์—†์ด๋„ FastAPI ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•ญ์ƒ ์‹คํ–‰ ์ค‘์ด๋„๋ก(์˜ˆ: FastAPI ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” Uvicorn) ๊ตฌ์„ฑํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +### ๋ณ„๋„์˜ ํ”„๋กœ๊ทธ๋žจ { #separate-program } + +์ด๋ฅผ ์œ„ํ•ด ๋ณดํ†ต ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘ ์‹œ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” **๋ณ„๋„์˜ ํ”„๋กœ๊ทธ๋žจ**์„ ๋‘ก๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ™์€ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋„ ํ•จ๊ป˜ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. + +### ์‹œ์ž‘ ์‹œ ์‹คํ–‰์„ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-to-run-at-startup } + +์ด ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* Docker +* Kubernetes +* Docker Compose +* Swarm Mode์˜ Docker +* Systemd +* Supervisor +* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ +* ๊ธฐํƒ€... + +๋‹ค์Œ ์žฅ์—์„œ ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์žฌ์‹œ์ž‘ { #restarts } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘ ์‹œ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๊ฒŒ, ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ **์žฌ์‹œ์ž‘**๋˜๋„๋ก ๋ณด์žฅํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +### ์šฐ๋ฆฌ๋Š” ์‹ค์ˆ˜ํ•ฉ๋‹ˆ๋‹ค { #we-make-mistakes } + +์‚ฌ๋žŒ์€ ์–ธ์ œ๋‚˜ **์‹ค์ˆ˜**ํ•ฉ๋‹ˆ๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด์—๋Š” ๊ฑฐ์˜ *ํ•ญ์ƒ* ์—ฌ๊ธฐ์ €๊ธฐ์— ์ˆจ์€ **๋ฒ„๊ทธ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ› + +๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๋Š” ๋ฒ„๊ทธ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ๊ณ„์† ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค(์ƒˆ๋กœ์šด ๋ฒ„๊ทธ๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ  ๐Ÿ˜…). + +### ์ž‘์€ ์˜ค๋ฅ˜๋Š” ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋จ { #small-errors-automatically-handled } + +FastAPI๋กœ ์›น API๋ฅผ ๋งŒ๋“ค ๋•Œ ์ฝ”๋“œ์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์œผ๋ฉด, FastAPI๋Š” ๋ณดํ†ต ๊ทธ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ๋‹จ์ผ ์š”์ฒญ ์•ˆ์—๋งŒ ๋ฌธ์ œ๋ฅผ ๊ฐ€๋‘ก๋‹ˆ๋‹ค. ๐Ÿ›ก + +ํด๋ผ์ด์–ธํŠธ๋Š” ํ•ด๋‹น ์š”์ฒญ์— ๋Œ€ํ•ด **500 Internal Server Error**๋ฅผ ๋ฐ›์ง€๋งŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์™„์ „ํžˆ ํฌ๋ž˜์‹œํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ์š”์ฒญ๋ถ€ํ„ฐ๋Š” ๊ณ„์† ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +### ๋” ํฐ ์˜ค๋ฅ˜ - ํฌ๋ž˜์‹œ { #bigger-errors-crashes } + +๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ **์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํฌ๋ž˜์‹œ**์‹œ์ผœ Uvicorn๊ณผ Python ์ž์ฒด๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’ฅ + +๊ทธ๋ž˜๋„ ํ•œ ๊ตฐ๋ฐ ์˜ค๋ฅ˜ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฃฝ์€ ์ฑ„๋กœ ๋‚จ์•„ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ง๊ฐ€์ง„ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ผ๋„ **๊ณ„์† ์‹คํ–‰**๋˜๊ธฐ๋ฅผ ์›ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +### ํฌ๋ž˜์‹œ ํ›„ ์žฌ์‹œ์ž‘ { #restart-after-crash } + +ํ•˜์ง€๋งŒ ์‹คํ–‰ ์ค‘์ธ **ํ”„๋กœ์„ธ์Šค**๊ฐ€ ํฌ๋ž˜์‹œํ•˜๋Š” ์ •๋ง ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜์˜ ๊ฒฝ์šฐ์—๋Š”, ์ ์–ด๋„ ๋ช‡ ๋ฒˆ์€ ํ”„๋กœ์„ธ์Šค๋ฅผ **์žฌ์‹œ์ž‘**ํ•˜๋„๋ก ๋‹ด๋‹นํ•˜๋Š” ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค... + +/// tip | ํŒ + +...๋‹ค๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด๊ฐ€ **์ฆ‰์‹œ ๊ณ„์† ํฌ๋ž˜์‹œ**ํ•œ๋‹ค๋ฉด, ๋ฌดํ•œํžˆ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ์•„๋งˆ ์˜๋ฏธ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ๊ฐœ๋ฐœ ์ค‘์—, ๋˜๋Š” ์ตœ์†Œํ•œ ๋ฐฐํฌ ์งํ›„์— ์•Œ์•„์ฐจ๋ฆด ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฌ๋‹ˆ ์—ฌ๊ธฐ์„œ๋Š”, ํŠน์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ „์ฒด๊ฐ€ ํฌ๋ž˜์‹œํ•  ์ˆ˜ ์žˆ๊ณ  **๋ฏธ๋ž˜**์—๋„ ๊ทธ๋Ÿด ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ๋ž˜๋„ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์˜๋ฏธ ์žˆ๋Š” ์ฃผ์š” ์‚ฌ๋ก€์— ์ง‘์ค‘ํ•ด ๋ด…์‹œ๋‹ค. + +/// + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‹œ์ž‘ํ•˜๋Š” ์—ญํ• ์€ **์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ**๊ฐ€ ๋งก๋Š” ํŽธ์ด ๋ณดํ†ต ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ ์‹œ์ ์—๋Š” Uvicorn๊ณผ Python์„ ํฌํ•จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ด๋ฏธ ํฌ๋ž˜์‹œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ™์€ ์•ฑ์˜ ๊ฐ™์€ ์ฝ”๋“œ ์•ˆ์—์„œ ์ด๋ฅผ ํ•ด๊ฒฐํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +### ์ž๋™ ์žฌ์‹œ์ž‘์„ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-to-restart-automatically } + +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ **์‹œ์ž‘ ์‹œ ์‹คํ–‰**์— ์‚ฌ์šฉํ•œ ๋„๊ตฌ๊ฐ€ ์ž๋™ **์žฌ์‹œ์ž‘**๋„ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค: + +* Docker +* Kubernetes +* Docker Compose +* Swarm Mode์˜ Docker +* Systemd +* Supervisor +* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ +* ๊ธฐํƒ€... + +## ๋ณต์ œ - ํ”„๋กœ์„ธ์Šค์™€ ๋ฉ”๋ชจ๋ฆฌ { #replication-processes-and-memory } + +FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Uvicorn์„ ์‹คํ–‰ํ•˜๋Š” `fastapi` ๋ช…๋ น ๊ฐ™์€ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋ฉด, **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•˜๋”๋ผ๋„ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋งŽ์€ ๊ฒฝ์šฐ, ์—ฌ๋Ÿฌ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +### ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค - ์›Œ์ปค { #multiple-processes-workers } + +๋‹จ์ผ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋” ๋งŽ๊ณ (์˜ˆ: ๊ฐ€์ƒ ๋จธ์‹ ์ด ๊ทธ๋ฆฌ ํฌ์ง€ ์•Š์„ ๋•Œ), ์„œ๋ฒ„ CPU์— **์—ฌ๋Ÿฌ ์ฝ”์–ด**๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋™์‹œ์— ๋„์šฐ๊ณ  ์š”์ฒญ์„ ๋ถ„์‚ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ™์€ API ํ”„๋กœ๊ทธ๋žจ์„ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•  ๋•Œ, ์ด ํ”„๋กœ์„ธ์Šค๋“ค์„ ๋ณดํ†ต **workers**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. + +### ์›Œ์ปค ํ”„๋กœ์„ธ์Šค์™€ ํฌํŠธ { #worker-processes-and-ports } + +[HTTPS์— ๋Œ€ํ•œ ๋ฌธ์„œ](https.md){.internal-link target=_blank}์—์„œ, ์„œ๋ฒ„์—์„œ ํ•˜๋‚˜์˜ ํฌํŠธ์™€ IP ์ฃผ์†Œ ์กฐํ•ฉ์—๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? + +์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋ ค๋ฉด, ๋จผ์ € **ํฌํŠธ์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๊ทธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ๊ฐ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋กœ ํ†ต์‹ ์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +### ํ”„๋กœ์„ธ์Šค๋‹น ๋ฉ”๋ชจ๋ฆฌ { #memory-per-process } + +์ด์ œ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๋กœ๋“œํ•œ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ๋ณ€์ˆ˜์— ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜ ํฐ ํŒŒ์ผ ๋‚ด์šฉ์„ ๋ณ€์ˆ˜์— ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒƒ๋“ค์€ ์„œ๋ฒ„์˜ **๋ฉ”๋ชจ๋ฆฌ(RAM)**๋ฅผ ์–ด๋А ์ •๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋Š” ๋ณดํ†ต **๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ์ฆ‰, ๊ฐ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๋Š” ์ž์ฒด ๋ณ€์ˆ˜์™€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, **๊ฐ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ๊ทธ๋งŒํผ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +### ์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ { #server-memory } + +์˜ˆ๋ฅผ ๋“ค์–ด ์ฝ”๋“œ๊ฐ€ ํฌ๊ธฐ **1 GB**์˜ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ๋กœ๋“œํ•œ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. API๋ฅผ ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๋กœ ์‹คํ–‰ํ•˜๋ฉด RAM์„ ์ตœ์†Œ 1GB ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  **4๊ฐœ ํ”„๋กœ์„ธ์Šค**(์›Œ์ปค 4๊ฐœ)๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ๊ฐ๊ฐ 1GB RAM์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰ ์ด **4 GB RAM**์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ๋ฐ ์›๊ฒฉ ์„œ๋ฒ„๋‚˜ ๊ฐ€์ƒ ๋จธ์‹ ์˜ RAM์ด 3GB๋ฟ์ด๋ผ๋ฉด, 4GB๋ฅผ ๋„˜๊ฒŒ ๋กœ๋“œํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ๐Ÿšจ + +### ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค - ์˜ˆ์‹œ { #multiple-processes-an-example } + +์ด ์˜ˆ์‹œ์—์„œ๋Š” **Manager Process**๊ฐ€ ๋‘ ๊ฐœ์˜ **Worker Processes**๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. + +์ด Manager Process๋Š” ์•„๋งˆ IP์˜ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ํ†ต์‹ ์„ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + +์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋“ค์ด ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ฉฐ, **์š”์ฒญ**์„ ๋ฐ›์•„ **์‘๋‹ต**์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฃผ์š” ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ณ , RAM์— ๋ณ€์ˆ˜๋กœ ๋กœ๋“œํ•œ ๋ชจ๋“  ๋‚ด์šฉ์„ ๋‹ด์Šต๋‹ˆ๋‹ค. + + + +๊ทธ๋ฆฌ๊ณ  ๋ฌผ๋ก  ๊ฐ™์€ ๋จธ์‹ ์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์™ธ์—๋„ **๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค**๋“ค์ด ์‹คํ–‰ ์ค‘์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +ํฅ๋ฏธ๋กœ์šด ์ ์€ ๊ฐ ํ”„๋กœ์„ธ์Šค์˜ **CPU ์‚ฌ์šฉ๋ฅ **์€ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํฌ๊ฒŒ **๋ณ€๋™**ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, **๋ฉ”๋ชจ๋ฆฌ(RAM)**๋Š” ๋ณดํ†ต ๋Œ€์ฒด๋กœ **์•ˆ์ •์ **์œผ๋กœ ์œ ์ง€๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋งค๋ฒˆ ๋น„์Šทํ•œ ์–‘์˜ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” API์ด๊ณ  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งŽ๋‹ค๋ฉด, **CPU ์‚ฌ์šฉ๋ฅ **๋„ (๊ธ‰๊ฒฉํžˆ ์˜ค๋ฅด๋‚ด๋ฆฌ๊ธฐ๋ณด๋‹ค๋Š”) *์•ˆ์ •์ ์ผ* ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +### ๋ณต์ œ ๋„๊ตฌ์™€ ์ „๋žต ์˜ˆ์‹œ { #examples-of-replication-tools-and-strategies } + +์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ ์žฅ๋“ค์—์„œ Docker์™€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์„ค๋ช…ํ•  ๋•Œ ๊ตฌ์ฒด์ ์ธ ์ „๋žต์„ ๋” ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. + +๊ณ ๋ คํ•ด์•ผ ํ•  ์ฃผ์š” ์ œ์•ฝ์€ **๊ณต๊ฐœ IP**์˜ **ํฌํŠธ**๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” **๋‹จ์ผ** ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ณต์ œ๋œ **ํ”„๋กœ์„ธ์Šค/์›Œ์ปค**๋กœ ํ†ต์‹ ์„ **์ „๋‹ฌ**ํ•  ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ๊ณผ ์ „๋žต ๋ช‡ ๊ฐ€์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* `--workers` ์˜ต์…˜์„ ์‚ฌ์šฉํ•œ **Uvicorn** + * ํ•˜๋‚˜์˜ Uvicorn **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๊ฐ€ **IP**์™€ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๊ณ , **์—ฌ๋Ÿฌ Uvicorn ์›Œ์ปค ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. +* **Kubernetes** ๋ฐ ๊ธฐํƒ€ ๋ถ„์‚ฐ **์ปจํ…Œ์ด๋„ˆ ์‹œ์Šคํ…œ** + * **Kubernetes** ๋ ˆ์ด์–ด์˜ ๋ฌด์–ธ๊ฐ€๊ฐ€ **IP**์™€ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  **์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ๋‘์–ด ๋ณต์ œํ•˜๋ฉฐ, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—๋Š” **ํ•˜๋‚˜์˜ Uvicorn ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. +* ์ด๋ฅผ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” **ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค** + * ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๊ฐ€ **๋ณต์ œ๋ฅผ ๋Œ€์‹  ์ฒ˜๋ฆฌ**ํ•ด์ค„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ์‹คํ–‰ํ•  **ํ”„๋กœ์„ธ์Šค**๋‚˜ ์‚ฌ์šฉํ•  **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋ฅผ ์ •์˜ํ•˜๊ฒŒ ํ•ด์ค„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์–ด๋–ค ๊ฒฝ์šฐ๋“  ๋Œ€๊ฐœ **๋‹จ์ผ Uvicorn ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ณ , ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๊ฐ€ ์ด๋ฅผ ๋ณต์ œํ•˜๋Š” ์—ญํ• ์„ ๋งก์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +**์ปจํ…Œ์ด๋„ˆ**, Docker, Kubernetes์— ๋Œ€ํ•œ ์ผ๋ถ€ ๋‚ด์šฉ์ด ์•„์ง์€ ์ž˜ ์ดํ•ด๋˜์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ ์žฅ์—์„œ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€, Docker, Kubernetes ๋“ฑ์„ ๋” ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค: [์ปจํ…Œ์ด๋„ˆ์—์„œ FastAPI - Docker](docker.md){.internal-link target=_blank}. + +/// + +## ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„ { #previous-steps-before-starting } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ **์‹œ์ž‘ํ•˜๊ธฐ ์ „์—** ์–ด๋–ค ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜**์„ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ์ด๋Ÿฐ ๋‹จ๊ณ„๋Š” **ํ•œ ๋ฒˆ๋งŒ** ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๊ทธ **์‚ฌ์ „ ๋‹จ๊ณ„**๋ฅผ ์ˆ˜ํ–‰ํ•  **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋‘๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์ดํ›„์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž์ฒด๋ฅผ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**(์—ฌ๋Ÿฌ ์›Œ์ปค)๋กœ ์‹œ์ž‘ํ•˜๋”๋ผ๋„, ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” *๋ฐ˜๋“œ์‹œ* ํ•˜๋‚˜๋งŒ ์‹คํ–‰๋˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋ฉด, **๋ณ‘๋ ฌ๋กœ** ์‹คํ–‰ํ•˜๋ฉด์„œ ์ž‘์—…์ด **์ค‘๋ณต**๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ฒ˜๋Ÿผ ๋ฏผ๊ฐํ•œ ์ž‘์—…์ด๋ผ๋ฉด ์„œ๋กœ ์ถฉ๋Œ์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฌผ๋ก  ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ฒ˜๋ฆฌํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +๋˜ํ•œ ์„ค์ •์— ๋”ฐ๋ผ, ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— **์‚ฌ์ „ ๋‹จ๊ณ„๊ฐ€ ์ „ํ˜€ ํ•„์š” ์—†์„** ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ์ „ํ˜€ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿคท + +/// + +### ์‚ฌ์ „ ๋‹จ๊ณ„ ์ „๋žต ์˜ˆ์‹œ { #examples-of-previous-steps-strategies } + +์ด๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด **์‹œ์Šคํ…œ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ์‹**์— ํฌ๊ฒŒ ์ขŒ์šฐ๋˜๋ฉฐ, ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ์‹, ์žฌ์‹œ์ž‘ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ ๋“ฑ๊ณผ๋„ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +๊ฐ€๋Šฅํ•œ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์•ฑ ์ปจํ…Œ์ด๋„ˆ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜๋Š” Kubernetes์˜ โ€œInit Containerโ€ +* ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๋Š” bash ์Šคํฌ๋ฆฝํŠธ + * ์ด bash ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹œ์ž‘/์žฌ์‹œ์ž‘ํ•˜๊ณ , ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•๋„ ์—ฌ์ „ํžˆ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ปจํ…Œ์ด๋„ˆ๋กœ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ ์žฅ์—์„œ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค: [์ปจํ…Œ์ด๋„ˆ์—์„œ FastAPI - Docker](docker.md){.internal-link target=_blank}. + +/// + +## ๋ฆฌ์†Œ์Šค ํ™œ์šฉ { #resource-utilization } + +์„œ๋ฒ„๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์†Œ๋น„ํ•˜๊ฑฐ๋‚˜ **ํ™œ์šฉ(utilize)**ํ•  ์ˆ˜ ์žˆ๋Š” **๋ฆฌ์†Œ์Šค**์ž…๋‹ˆ๋‹ค. CPU์˜ ๊ณ„์‚ฐ ์‹œ๊ฐ„๊ณผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ RAM ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋Œ€ํ‘œ์ ์ž…๋‹ˆ๋‹ค. + +์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค๋ฅผ ์–ผ๋งˆ๋‚˜ ์†Œ๋น„/ํ™œ์šฉํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? โ€œ๋งŽ์ง€ ์•Š๊ฒŒโ€๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” **ํฌ๋ž˜์‹œํ•˜์ง€ ์•Š๋Š” ์„ ์—์„œ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด** ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +์„œ๋ฒ„ 3๋Œ€๋ฅผ ๋น„์šฉ์„ ๋‚ด๊ณ  ์“ฐ๊ณ  ์žˆ๋Š”๋ฐ RAM๊ณผ CPU๋ฅผ ์กฐ๊ธˆ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์•„๋งˆ **๋ˆ์„ ๋‚ญ๋น„**ํ•˜๊ณ  ๐Ÿ’ธ, **์„œ๋ฒ„ ์ „๋ ฅ๋„ ๋‚ญ๋น„**ํ•˜๊ณ  ๐ŸŒŽ, ๊ธฐํƒ€ ๋“ฑ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ ๊ฒฝ์šฐ์—๋Š” ์„œ๋ฒ„๋ฅผ 2๋Œ€๋งŒ ๋‘๊ณ , ๊ฐ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค(CPU, ๋ฉ”๋ชจ๋ฆฌ, ๋””์Šคํฌ, ๋„คํŠธ์›Œํฌ ๋Œ€์—ญํญ ๋“ฑ)๋ฅผ ๋” ๋†’์€ ๋น„์œจ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฐ˜๋Œ€๋กœ ์„œ๋ฒ„ 2๋Œ€๋ฅผ ๋‘๊ณ  CPU์™€ RAM์„ **100%** ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์–ด๋А ์‹œ์ ์— ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๊ฐ€ ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋˜๊ณ , ์„œ๋ฒ„๋Š” ๋””์Šคํฌ๋ฅผ โ€œ๋ฉ”๋ชจ๋ฆฌโ€์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค(์ˆ˜์ฒœ ๋ฐฐ ๋А๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๋˜๋Š” ์‹ฌ์ง€์–ด **ํฌ๋ž˜์‹œ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ ์–ด๋–ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณ„์‚ฐ์„ ํ•ด์•ผ ํ•˜๋Š”๋ฐ CPU๊ฐ€ ๋‹ค์‹œ ๋น„์›Œ์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ์—๋Š” **์„œ๋ฒ„ ํ•œ ๋Œ€๋ฅผ ์ถ”๊ฐ€**๋กœ ํ™•๋ณดํ•˜๊ณ  ์ผ๋ถ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ทธ์ชฝ์—์„œ ์‹คํ–‰ํ•ด, ๋ชจ๋‘๊ฐ€ **์ถฉ๋ถ„ํ•œ RAM๊ณผ CPU ์‹œ๊ฐ„**์„ ๊ฐ–๋„๋ก ํ•˜๋Š” ํŽธ์ด ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. + +๋˜ ์–ด๋–ค ์ด์œ ๋กœ API ์‚ฌ์šฉ๋Ÿ‰์ด **๊ธ‰์ฆ(spike)**ํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”์ด๋Ÿด์ด ๋˜์—ˆ๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์„œ๋น„์Šค๋‚˜ ๋ด‡์ด ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™•๋ณดํ•ด๋‘๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฆฌ์†Œ์Šค ํ™œ์šฉ๋ฅ  ๋ชฉํ‘œ๋กœ **์ž„์˜์˜ ์ˆ˜์น˜**๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด **50%์—์„œ 90% ์‚ฌ์ด**์ฒ˜๋Ÿผ์š”. ์š”์ ์€, ์ด๋Ÿฐ ๊ฒƒ๋“ค์ด ๋ฐฐํฌ๋ฅผ ์กฐ์ •ํ•  ๋•Œ ์ธก์ •ํ•˜๊ณ  ํŠœ๋‹ํ•˜๋Š” ์ฃผ์š” ์ง€ํ‘œ๊ฐ€ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +`htop` ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๋„๊ตฌ๋กœ ์„œ๋ฒ„์˜ CPU์™€ RAM ์‚ฌ์šฉ๋Ÿ‰, ๋˜๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค๋ณ„ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ ์„œ๋ฒ„ ์—ฌ๋Ÿฌ ๋Œ€์— ๋ถ„์‚ฐ๋  ์ˆ˜๋„ ์žˆ๋Š” ๋” ๋ณต์žกํ•œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ์š”์•ฝ { #recap } + +์—ฌ๊ธฐ๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ์ฃผ์š” ๊ฐœ๋…๋“ค์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค: + +* ๋ณด์•ˆ - HTTPS +* ์‹œ์ž‘ ์‹œ ์‹คํ–‰ +* ์žฌ์‹œ์ž‘ +* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜) +* ๋ฉ”๋ชจ๋ฆฌ +* ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„ + +์ด ์•„์ด๋””์–ด๋“ค์„ ์ดํ•ดํ•˜๊ณ  ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ฉด, ๋ฐฐํฌ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์กฐ์ •ํ•  ๋•Œ ํ•„์š”ํ•œ ์ง๊ด€์„ ์–ป๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿค“ + +๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๋”ฐ๋ผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ์ „๋žต์˜ ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿš€ diff --git a/docs/ko/docs/deployment/fastapicloud.md b/docs/ko/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..9a830b1579 --- /dev/null +++ b/docs/ko/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +**ํ•œ ๋ฒˆ์˜ ๋ช…๋ น**์œผ๋กœ FastAPI ์•ฑ์„ FastAPI Cloud์— ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ง์ด๋ผ๋ฉด ๋Œ€๊ธฐ์ž ๋ช…๋‹จ์— ๋“ฑ๋กํ•ด ๋ณด์„ธ์š”. ๐Ÿš€ + +## ๋กœ๊ทธ์ธํ•˜๊ธฐ { #login } + +๋จผ์ € **FastAPI Cloud** ๊ณ„์ •์ด ์ด๋ฏธ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”(๋Œ€๊ธฐ์ž ๋ช…๋‹จ์—์„œ ์ดˆ๋Œ€ํ•ด ๋“œ๋ ธ์„ ๊ฑฐ์˜ˆ์š” ๐Ÿ˜‰). + +๊ทธ๋‹ค์Œ ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค: + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## ๋ฐฐํฌํ•˜๊ธฐ { #deploy } + +์ด์ œ **ํ•œ ๋ฒˆ์˜ ๋ช…๋ น**์œผ๋กœ ์•ฑ์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค: + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +์ด๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค! ์ด์ œ ํ•ด๋‹น URL์—์„œ ์•ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ + +## FastAPI Cloud ์†Œ๊ฐœ { #about-fastapi-cloud } + +**FastAPI Cloud**๋Š” **FastAPI**๋ฅผ ๋งŒ๋“  ๋™์ผํ•œ ์ €์ž์™€ ํŒ€์ด ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค. + +์ตœ์†Œํ•œ์˜ ๋…ธ๋ ฅ์œผ๋กœ API๋ฅผ **๊ตฌ์ถ•**, **๋ฐฐํฌ**, **์ ‘๊ทผ**ํ•˜๋Š” ๊ณผ์ •์„ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค. + +FastAPI๋กœ ์•ฑ์„ ๋งŒ๋“ค ๋•Œ์˜ ๋™์ผํ•œ **๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜**์„, ํด๋ผ์šฐ๋“œ์— **๋ฐฐํฌ**ํ•  ๋•Œ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐ŸŽ‰ + +๋˜ํ•œ ์•ฑ์„ ๋ฐฐํฌํ•  ๋•Œ ๋ณดํ†ต ํ•„์š”ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒƒ๋“ค๋„ ์ฒ˜๋ฆฌํ•ด ์ค๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด: + +* HTTPS +* ์š”์ฒญ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™ ์Šค์ผ€์ผ๋งํ•˜๋Š” ๋ณต์ œ(Replication) +* ๋“ฑ + +FastAPI Cloud๋Š” *FastAPI and friends* ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ์Šคํฐ์„œ์ด์ž ์ž๊ธˆ ์ง€์› ์ œ๊ณต์ž์ž…๋‹ˆ๋‹ค. โœจ + +## ๋‹ค๋ฅธ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์— ๋ฐฐํฌํ•˜๊ธฐ { #deploy-to-other-cloud-providers } + +FastAPI๋Š” ์˜คํ”ˆ ์†Œ์Šค์ด๋ฉฐ ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ์–ด๋–ค ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์—๋„ FastAPI ์•ฑ์„ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•ด๋‹น ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์˜ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ผ FastAPI ์•ฑ์„ ๋ฐฐํฌํ•˜์„ธ์š”. ๐Ÿค“ + +## ์ž์ฒด ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜๊ธฐ { #deploy-your-own-server } + +๋˜ํ•œ ์ด **Deployment** ๊ฐ€์ด๋“œ์—์„œ ์ดํ›„์— ๋ชจ๋“  ์„ธ๋ถ€์‚ฌํ•ญ์„ ์•Œ๋ ค๋“œ๋ฆด ๊ฑฐ์˜ˆ์š”. ๊ทธ๋ž˜์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€, ๋ฌด์—‡์ด ํ•„์š”ํ•˜๋ฉฐ, ๋ณธ์ธ์˜ ์„œ๋ฒ„๋ฅผ ํฌํ•จํ•ด ์ง์ ‘ FastAPI ์•ฑ์„ ์–ด๋–ป๊ฒŒ ๋ฐฐํฌํ•˜๋Š”์ง€๊นŒ์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿค“ diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md new file mode 100644 index 0000000000..888ec61592 --- /dev/null +++ b/docs/ko/docs/deployment/https.md @@ -0,0 +1,231 @@ +# HTTPS ์•Œ์•„๋ณด๊ธฐ { #about-https } + +HTTPS๋Š” ๊ทธ๋ƒฅ โ€œ์ผœ์ ธ ์žˆ๊ฑฐ๋‚˜โ€ ์•„๋‹ˆ๋ฉด โ€œ๊บผ์ ธ ์žˆ๋Š”โ€ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ›จ์”ฌ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +๋ฐ”์˜๊ฑฐ๋‚˜ ๋ณ„๋กœ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด, ๋‹ค์Œ ์„น์…˜์—์„œ ๋‹ค์–‘ํ•œ ๊ธฐ๋ฒ•์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์„ ์„ค์ •ํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ์•ˆ๋‚ด๋ฅผ ๊ณ„์† ๋ณด์„ธ์š”. + +/// + +์†Œ๋น„์ž ๊ด€์ ์—์„œ **HTTPS์˜ ๊ธฐ๋ณธ์„ ๋ฐฐ์šฐ๋ ค๋ฉด** https://howhttps.works/๋ฅผ ํ™•์ธํ•˜์„ธ์š”. + +์ด์ œ **๊ฐœ๋ฐœ์ž ๊ด€์ **์—์„œ HTTPS๋ฅผ ์ƒ๊ฐํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: + +* HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, **์„œ๋ฒ„**๊ฐ€ **์ œ3์ž**๊ฐ€ ๋ฐœ๊ธ‰ํ•œ **"์ธ์ฆ์„œ(certificates)"**๋ฅผ **๋ณด์œ **ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + * ์ด ์ธ์ฆ์„œ๋Š” ์‹ค์ œ๋กœ ์ œ3์ž๊ฐ€ โ€œ์ƒ์„ฑโ€ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ œ3์ž๋กœ๋ถ€ํ„ฐ **๋ฐœ๊ธ‰/ํš๋“**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. +* ์ธ์ฆ์„œ์—๋Š” **์œ ํšจ ๊ธฐ๊ฐ„**์ด ์žˆ์Šต๋‹ˆ๋‹ค. + * ์ฆ‰, **๋งŒ๋ฃŒ**๋ฉ๋‹ˆ๋‹ค. + * ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋ฉด ์ œ3์ž๋กœ๋ถ€ํ„ฐ ๋‹ค์‹œ **๊ฐฑ์‹ **ํ•ด์„œ **์žฌ๋ฐœ๊ธ‰/์žฌํš๋“**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +* ์—ฐ๊ฒฐ์˜ ์•”ํ˜ธํ™”๋Š” **TCP ๋ ˆ๋ฒจ**์—์„œ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค. + * ์ด๋Š” **HTTP๋ณด๋‹ค ํ•œ ๊ณ„์ธต ์•„๋ž˜**์ž…๋‹ˆ๋‹ค. + * ๋”ฐ๋ผ์„œ **์ธ์ฆ์„œ์™€ ์•”ํ˜ธํ™”** ์ฒ˜๋ฆฌ๋Š” **HTTP ์ด์ „**์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. +* **TCP๋Š” "๋„๋ฉ”์ธ"์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.** IP ์ฃผ์†Œ๋งŒ ์••๋‹ˆ๋‹ค. + * ์–ด๋–ค **ํŠน์ • ๋„๋ฉ”์ธ**์„ ์š”์ฒญํ–ˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋Š” **HTTP ๋ฐ์ดํ„ฐ**์— ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +* **HTTPS ์ธ์ฆ์„œ**๋Š” ํŠน์ • **๋„๋ฉ”์ธ**์„ โ€œ์ธ์ฆโ€ํ•˜์ง€๋งŒ, ํ”„๋กœํ† ์ฝœ๊ณผ ์•”ํ˜ธํ™”๋Š” TCP ๋ ˆ๋ฒจ์—์„œ ์ผ์–ด๋‚˜๋ฉฐ, ์–ด๋–ค ๋„๋ฉ”์ธ์„ ๋‹ค๋ฃจ๋Š”์ง€ **์•Œ๊ธฐ ์ „์—** ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. +* **๊ธฐ๋ณธ์ ์œผ๋กœ** ์ด๋Š” IP ์ฃผ์†Œ ํ•˜๋‚˜๋‹น **HTTPS ์ธ์ฆ์„œ ํ•˜๋‚˜๋งŒ** ๋‘˜ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. + * ์„œ๋ฒ„๊ฐ€ ์•„๋ฌด๋ฆฌ ํฌ๋“ , ๊ทธ ์œ„์— ์˜ฌ๋ฆฐ ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์•„๋ฌด๋ฆฌ ์ž‘๋“  ์ƒ๊ด€์—†์Šต๋‹ˆ๋‹ค. + * ํ•˜์ง€๋งŒ ์ด์— ๋Œ€ํ•œ **ํ•ด๊ฒฐ์ฑ…**์ด ์žˆ์Šต๋‹ˆ๋‹ค. +* **TLS** ํ”„๋กœํ† ์ฝœ(HTTP ์ด์ „, TCP ๋ ˆ๋ฒจ์—์„œ ์•”ํ˜ธํ™”๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ)์— ๋Œ€ํ•œ **ํ™•์žฅ** ์ค‘์— **SNI**๋ผ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + * ์ด SNI ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋‹จ์ผ ์„œ๋ฒ„(**๋‹จ์ผ IP ์ฃผ์†Œ**)์—์„œ **์—ฌ๋Ÿฌ HTTPS ์ธ์ฆ์„œ**๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  **์—ฌ๋Ÿฌ HTTPS ๋„๋ฉ”์ธ/์• ํ”Œ๋ฆฌ์ผ€์ด์…˜**์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + * ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์„œ๋ฒ„์—์„œ **๊ณต๊ฐœ IP ์ฃผ์†Œ**๋กœ ๋ฆฌ์Šค๋‹ํ•˜๋Š” **ํ•˜๋‚˜์˜** ์ปดํฌ๋„ŒํŠธ(ํ”„๋กœ๊ทธ๋žจ)๊ฐ€ ์„œ๋ฒ„์— ์žˆ๋Š” **๋ชจ๋“  HTTPS ์ธ์ฆ์„œ**์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +* ๋ณด์•ˆ ์—ฐ๊ฒฐ์„ ์–ป์€ **์ดํ›„์—๋„**, ํ†ต์‹  ํ”„๋กœํ† ์ฝœ ์ž์ฒด๋Š” **์—ฌ์ „ํžˆ HTTP**์ž…๋‹ˆ๋‹ค. + * **HTTP ํ”„๋กœํ† ์ฝœ**๋กœ ์ „์†ก๋˜๋”๋ผ๋„, ๋‚ด์šฉ์€ **์•”ํ˜ธํ™”**๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋ฒ„(๋จธ์‹ , ํ˜ธ์ŠคํŠธ ๋“ฑ)์—๋Š” **ํ”„๋กœ๊ทธ๋žจ/HTTP ์„œ๋ฒ„ ํ•˜๋‚˜**๋ฅผ ์‹คํ–‰ํ•ด **HTTPS ๊ด€๋ จ ๋ถ€๋ถ„ ์ „์ฒด**๋ฅผ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค: **์•”ํ˜ธํ™”๋œ HTTPS ์š”์ฒญ**์„ ๋ฐ›๊ณ , ๋ณตํ˜ธํ™”๋œ **HTTP ์š”์ฒญ**์„ ๊ฐ™์€ ์„œ๋ฒ„์—์„œ ์‹คํ–‰ ์ค‘์ธ ์‹ค์ œ HTTP ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์ด ๊ฒฝ์šฐ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์œผ๋กœ ์ „๋‹ฌํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ **HTTP ์‘๋‹ต**์„ ๋ฐ›์•„ ์ ์ ˆํ•œ **HTTPS ์ธ์ฆ์„œ**๋กœ **์•”ํ˜ธํ™”**ํ•œ ๋’ค **HTTPS**๋กœ ํด๋ผ์ด์–ธํŠธ์— ๋‹ค์‹œ ๋ณด๋‚ด๋Š” ์—ญํ• ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์„œ๋ฒ„๋ฅผ ํ”ํžˆ **TLS Termination Proxy**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. + +TLS Termination Proxy๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* Traefik (์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ) +* Caddy (์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Let's Encrypt ์ด์ „์—๋Š” ์ด๋Ÿฌํ•œ **HTTPS ์ธ์ฆ์„œ**๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ œ3์ž์— ์˜ํ•ด ํŒ๋งค๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + +์ธ์ฆ์„œ๋ฅผ ํš๋“ํ•˜๋Š” ๊ณผ์ •์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ , ๊ฝค ๋งŽ์€ ์„œ๋ฅ˜ ์ž‘์—…์ด ํ•„์š”ํ–ˆ์œผ๋ฉฐ, ์ธ์ฆ์„œ๋„ ์ƒ๋‹นํžˆ ๋น„์ŒŒ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๊ทธ ํ›„ **Let's Encrypt**๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” Linux Foundation์˜ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ํ‘œ์ค€ ์•”ํ˜ธํ•™์  ๋ณด์•ˆ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋Š” **HTTPS ์ธ์ฆ์„œ**๋ฅผ **๋ฌด๋ฃŒ๋กœ**, ์ž๋™ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์ธ์ฆ์„œ๋“ค์€ ์ˆ˜๋ช…์ด ์งง๊ณ (์•ฝ 3๊ฐœ์›”) ๊ทธ๋ž˜์„œ ์œ ํšจ ๊ธฐ๊ฐ„์ด ์งง์€ ๋งŒํผ **์‹ค์ œ๋กœ ๋ณด์•ˆ์ด ๋” ์ข‹์•„์ง€๊ธฐ๋„** ํ•ฉ๋‹ˆ๋‹ค. + +๋„๋ฉ”์ธ์€ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฒ€์ฆ๋˜๋ฉฐ ์ธ์ฆ์„œ๋Š” ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด๋กœ ์ธํ•ด ์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ชฉํ‘œ๋Š” ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰๊ณผ ๊ฐฑ์‹ ์„ ์ž๋™ํ™”ํ•˜์—ฌ **๋ฌด๋ฃŒ๋กœ, ์˜๊ตฌํžˆ, ์•ˆ์ „ํ•œ HTTPS**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +## ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ HTTPS { #https-for-developers } + +๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ค‘์š”ํ•œ ๊ฐœ๋…๋“ค์„ ์ค‘์‹ฌ์œผ๋กœ, HTTPS API๊ฐ€ ๋‹จ๊ณ„๋ณ„๋กœ ์–ด๋–ป๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +### ๋„๋ฉ”์ธ ์ด๋ฆ„ { #domain-name } + +์•„๋งˆ๋„ ์‹œ์ž‘์€ **๋„๋ฉ”์ธ ์ด๋ฆ„**์„ **ํš๋“**ํ•˜๋Š” ๊ฒƒ์ผ ๊ฒ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ DNS ์„œ๋ฒ„(์•„๋งˆ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด)์—์„œ ์ด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + +๋Œ€๊ฐœ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„(๊ฐ€์ƒ ๋จธ์‹ ) ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ณ , ๊ฑฐ๊ธฐ์—๋Š” fixed **๊ณต๊ฐœ IP ์ฃผ์†Œ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +DNS ์„œ๋ฒ„(๋“ค)์—์„œ **๋„๋ฉ”์ธ**์ด ์„œ๋ฒ„์˜ **๊ณต๊ฐœ IP ์ฃผ์†Œ**๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ ˆ์ฝ”๋“œ(โ€œ`A record`โ€)๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + +๋ณดํ†ต์€ ์ฒ˜์Œ ํ•œ ๋ฒˆ, ๋ชจ๋“  ๊ฒƒ์„ ์„ค์ •ํ•  ๋•Œ๋งŒ ์ด ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +๋„๋ฉ”์ธ ์ด๋ฆ„ ๋ถ€๋ถ„์€ HTTPS๋ณด๋‹ค ํ›จ์”ฌ ์ด์ „ ๋‹จ๊ณ„์ง€๋งŒ, ๋ชจ๋“  ๊ฒƒ์ด ๋„๋ฉ”์ธ๊ณผ IP ์ฃผ์†Œ์— ์˜์กดํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +### DNS { #dns } + +์ด์ œ ์‹ค์ œ HTTPS ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +๋จผ์ € ๋ธŒ๋ผ์šฐ์ €๋Š” **DNS ์„œ๋ฒ„**์— ์งˆ์˜ํ•˜์—ฌ, ์—ฌ๊ธฐ์„œ๋Š” `someapp.example.com`์ด๋ผ๋Š” **๋„๋ฉ”์ธ์— ๋Œ€ํ•œ IP**๊ฐ€ ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + +DNS ์„œ๋ฒ„๋Š” ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ํŠน์ • **IP ์ฃผ์†Œ**๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์ด๋Š” DNS ์„œ๋ฒ„์— ์„ค์ •ํ•ด ๋‘”, ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ณต๊ฐœ IP ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค. + + + +### TLS ํ•ธ๋“œ์…ฐ์ดํฌ ์‹œ์ž‘ { #tls-handshake-start } + +๊ทธ ๋‹ค์Œ ๋ธŒ๋ผ์šฐ์ €๋Š” **ํฌํŠธ 443**(HTTPS ํฌํŠธ)์—์„œ ํ•ด๋‹น IP ์ฃผ์†Œ์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค. + +ํ†ต์‹ ์˜ ์ฒซ ๋ถ€๋ถ„์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•˜๊ณ , ์‚ฌ์šฉํ•  ์•”ํ˜ธํ™” ํ‚ค ๋“ฑ์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. + + + +ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ TLS ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ด ๊ณผ์ •์„ **TLS ํ•ธ๋“œ์…ฐ์ดํฌ**๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. + +### SNI ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๋Š” TLS { #tls-with-sni-extension } + +์„œ๋ฒ„์—์„œ๋Š” ํŠน์ • **IP ์ฃผ์†Œ**์˜ ํŠน์ • **ํฌํŠธ**์—์„œ **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ** ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ IP ์ฃผ์†Œ์—์„œ ๋‹ค๋ฅธ ํฌํŠธ๋กœ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, IP ์ฃผ์†Œ์™€ ํฌํŠธ ์กฐํ•ฉ๋งˆ๋‹ค ํ•˜๋‚˜๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. + +TLS(HTTPS)๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํŠน์ • ํฌํŠธ `443`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ํฌํŠธ๋Š” ์ด๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด ํฌํŠธ์—์„œ ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๊ทธ ์—ญํ• ์„ ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” **TLS Termination Proxy**๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. + +TLS Termination Proxy๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ **TLS ์ธ์ฆ์„œ**(HTTPS ์ธ์ฆ์„œ)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•ž์—์„œ ์„ค๋ช…ํ•œ **SNI ํ™•์žฅ**์„ ์‚ฌ์šฉํ•ด, TLS Termination Proxy๋Š” ์ด ์—ฐ๊ฒฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” TLS(HTTPS) ์ธ์ฆ์„œ๋“ค ์ค‘์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๋„๋ฉ”์ธ๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. + +์ด ๊ฒฝ์šฐ์—๋Š” `someapp.example.com`์— ๋Œ€ํ•œ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + + + +ํด๋ผ์ด์–ธํŠธ๋Š” ์ด๋ฏธ ํ•ด๋‹น TLS ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•œ ์ฃผ์ฒด(์—ฌ๊ธฐ์„œ๋Š” Let's Encrypt์ด์ง€๋งŒ, ์ด๋Š” ๋’ค์—์„œ ๋‹ค์‹œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค)๋ฅผ **์‹ ๋ขฐ**ํ•˜๋ฏ€๋กœ, ์ธ์ฆ์„œ๊ฐ€ ์œ ํšจํ•œ์ง€ **๊ฒ€์ฆ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ผ์ด์–ธํŠธ์™€ TLS Termination Proxy๋Š” ๋‚˜๋จธ์ง€ **TCP ํ†ต์‹ **์„ ์–ด๋–ป๊ฒŒ **์•”ํ˜ธํ™”ํ• ์ง€ ๊ฒฐ์ •**ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ์จ **TLS ํ•ธ๋“œ์…ฐ์ดํฌ** ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค. + +์ดํ›„ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” TLS๊ฐ€ ์ œ๊ณตํ•˜๋Š” **์•”ํ˜ธํ™”๋œ TCP ์—ฐ๊ฒฐ**์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•ด ์‹ค์ œ **HTTP ํ†ต์‹ **์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๊ฒƒ์ด ๋ฐ”๋กœ **HTTPS**์ž…๋‹ˆ๋‹ค. ์ˆœ์ˆ˜(์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€) TCP ์—ฐ๊ฒฐ ๋Œ€์‹  **์•ˆ์ „ํ•œ TLS ์—ฐ๊ฒฐ** ์•ˆ์—์„œ **HTTP**๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// tip | ํŒ + +ํ†ต์‹ ์˜ ์•”ํ˜ธํ™”๋Š” HTTP ๋ ˆ๋ฒจ์ด ์•„๋‹ˆ๋ผ **TCP ๋ ˆ๋ฒจ**์—์„œ ์ผ์–ด๋‚œ๋‹ค๋Š” ์ ์— ์ฃผ์˜ํ•˜์„ธ์š”. + +/// + +### HTTPS ์š”์ฒญ { #https-request } + +์ด์ œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„(๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ๋ธŒ๋ผ์šฐ์ €์™€ TLS Termination Proxy)๊ฐ€ **์•”ํ˜ธํ™”๋œ TCP ์—ฐ๊ฒฐ**์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์œผ๋‹ˆ **HTTP ํ†ต์‹ **์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ํด๋ผ์ด์–ธํŠธ๋Š” **HTTPS ์š”์ฒญ**์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋Š” ์•”ํ˜ธํ™”๋œ TLS ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์ „๋‹ฌ๋˜๋Š” HTTP ์š”์ฒญ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. + + + +### ์š”์ฒญ ๋ณตํ˜ธํ™” { #decrypt-the-request } + +TLS Termination Proxy๋Š” ํ•ฉ์˜๋œ ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•ด **์š”์ฒญ์„ ๋ณตํ˜ธํ™”**ํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค(์˜ˆ: FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” Uvicorn ํ”„๋กœ์„ธ์Šค)์— **์ผ๋ฐ˜(๋ณตํ˜ธํ™”๋œ) HTTP ์š”์ฒญ**์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + + + +### HTTP ์‘๋‹ต { #http-response } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  **์ผ๋ฐ˜(์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€) HTTP ์‘๋‹ต**์„ TLS Termination Proxy๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + + + +### HTTPS ์‘๋‹ต { #https-response } + +๊ทธ ๋‹ค์Œ TLS Termination Proxy๋Š” ์ด์ „์— ํ•ฉ์˜ํ•œ ์•”ํ˜ธํ™”( `someapp.example.com` ์ธ์ฆ์„œ๋กœ ์‹œ์ž‘๋œ ๊ฒƒ)๋ฅผ ์‚ฌ์šฉํ•ด **์‘๋‹ต์„ ์•”ํ˜ธํ™”**ํ•˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๋กœ ๋‹ค์‹œ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + +์ดํ›„ ๋ธŒ๋ผ์šฐ์ €๋Š” ์‘๋‹ต์ด ์œ ํšจํ•œ์ง€, ์˜ฌ๋ฐ”๋ฅธ ์•”ํ˜ธํ™” ํ‚ค๋กœ ์•”ํ˜ธํ™”๋˜์—ˆ๋Š”์ง€ ๋“ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ **์‘๋‹ต์„ ๋ณตํ˜ธํ™”**ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + + + +ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)๋Š” ์•ž์„œ **HTTPS ์ธ์ฆ์„œ**๋กœ ํ•ฉ์˜ํ•œ ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ํ•ด๋‹น ์‘๋‹ต์ด ์˜ฌ๋ฐ”๋ฅธ ์„œ๋ฒ„์—์„œ ์™”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ { #multiple-applications } + +๊ฐ™์€ ์„œ๋ฒ„(๋˜๋Š” ์—ฌ๋Ÿฌ ์„œ๋ฒ„)์—๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ API ํ”„๋กœ๊ทธ๋žจ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ฒ˜๋Ÿผ **์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜**์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํŠน์ • IP์™€ ํฌํŠธ ์กฐํ•ฉ์€ ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(์˜ˆ์‹œ์—์„œ๋Š” TLS Termination Proxy), ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/ํ”„๋กœ์„ธ์Šค๋„ **๊ณต๊ฐœ IP์™€ ํฌํŠธ ์กฐํ•ฉ**์„ ๋™์ผํ•˜๊ฒŒ ์“ฐ๋ ค๊ณ ๋งŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์„œ๋ฒ„์—์„œ ํ•จ๊ป˜ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + + + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด TLS Termination Proxy๊ฐ€ **์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ**์— ๋Œ€ํ•œ HTTPS์™€ ์ธ์ฆ์„œ๋ฅผ **์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜**์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ ๊ฒฝ์šฐ์— ๋งž๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์ธ์ฆ์„œ ๊ฐฑ์‹  { #certificate-renewal } + +๋ฏธ๋ž˜์˜ ์–ด๋А ์‹œ์ ์—๋Š” ๊ฐ ์ธ์ฆ์„œ๊ฐ€ **๋งŒ๋ฃŒ**๋ฉ๋‹ˆ๋‹ค(ํš๋“ ํ›„ ์•ฝ 3๊ฐœ์›”). + +๊ทธ ๋‹ค์Œ์—๋Š” ๋˜ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ(๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋ณ„๋„ ํ”„๋กœ๊ทธ๋žจ์ผ ์ˆ˜๋„ ์žˆ๊ณ , ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๊ฐ™์€ TLS Termination Proxy์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค)์ด Let's Encrypt์™€ ํ†ต์‹ ํ•˜์—ฌ ์ธ์ฆ์„œ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. + + + +**TLS ์ธ์ฆ์„œ**๋Š” IP ์ฃผ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ **๋„๋ฉ”์ธ ์ด๋ฆ„**๊ณผ **์—ฐ๊ฒฐ**๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์ธ์ฆ์„œ๋ฅผ ๊ฐฑ์‹ ํ•˜๋ ค๋ฉด, ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์ด ๊ถŒํ•œ ๊ธฐ๊ด€(Let's Encrypt)์—๊ฒŒ ํ•ด๋‹น ๋„๋ฉ”์ธ์„ ์‹ค์ œ๋กœ **โ€œ์†Œ์œ โ€ํ•˜๊ณ  ์ œ์–ดํ•˜๊ณ  ์žˆ์Œ**์„ **์ฆ๋ช…**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ฅผ ์œ„ํ•ด, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์–‘ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”๊ตฌ๋ฅผ ์ˆ˜์šฉํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋„๋ฆฌ ์“ฐ์ด๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* **์ผ๋ถ€ DNS ๋ ˆ์ฝ”๋“œ ์ˆ˜์ •**. + * ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์ด DNS ์ œ๊ณต์—…์ฒด์˜ API๋ฅผ ์ง€์›ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉํ•˜๋Š” DNS ์ œ๊ณต์—…์ฒด์— ๋”ฐ๋ผ ๊ฐ€๋Šฅํ•  ์ˆ˜๋„, ์•„๋‹ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋„๋ฉ”์ธ๊ณผ ์—ฐ๊ฒฐ๋œ ๊ณต๊ฐœ IP ์ฃผ์†Œ์—์„œ **์„œ๋ฒ„๋กœ ์‹คํ–‰**(์ ์–ด๋„ ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ ๊ณผ์ • ๋™์•ˆ). + * ์•ž์—์„œ ๋งํ–ˆ๋“ฏ ํŠน์ • IP์™€ ํฌํŠธ์—์„œ๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + * ์ด๊ฒƒ์ด ๋™์ผํ•œ TLS Termination Proxy๊ฐ€ ์ธ์ฆ์„œ ๊ฐฑ์‹  ๊ณผ์ •๊นŒ์ง€ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•œ ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. + * ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด TLS Termination Proxy๋ฅผ ์ž ์‹œ ์ค‘์ง€ํ•˜๊ณ , ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•ด ์ธ์ฆ์„œ๋ฅผ ํš๋“ํ•œ ๋‹ค์Œ, TLS Termination Proxy์— ์ธ์ฆ์„œ๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋‹ค์‹œ TLS Termination Proxy๋ฅผ ์žฌ์‹œ์ž‘ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” TLS Termination Proxy๊ฐ€ ๊บผ์ ธ ์žˆ๋Š” ๋™์•ˆ ์•ฑ(๋“ค)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์•ฑ์„ ๊ณ„์† ์ œ๊ณตํ•˜๋ฉด์„œ ์ด ๊ฐฑ์‹  ๊ณผ์ •์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„(์˜ˆ: Uvicorn)์—์„œ TLS ์ธ์ฆ์„œ๋ฅผ ์ง์ ‘ ์“ฐ๋Š” ๋Œ€์‹  TLS Termination Proxy๋กœ HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” **๋ณ„๋„์˜ ์‹œ์Šคํ…œ**์„ ๋‘๊ณ  ์‹ถ์–ด์ง€๋Š” ์ฃผ์š” ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. + +## ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” { #proxy-forwarded-headers } + +ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•ด HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**(์˜ˆ: FastAPI CLI๋ฅผ ํ†ตํ•œ Uvicorn)๋Š” HTTPS ๊ณผ์ •์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์•Œ์ง€ ๋ชปํ•˜๊ณ  **TLS Termination Proxy**์™€๋Š” ์ผ๋ฐ˜ HTTP๋กœ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค. + +์ด **ํ”„๋ก์‹œ**๋Š” ๋ณดํ†ต ์š”์ฒญ์„ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, ์š”์ฒญ์ด ํ”„๋ก์‹œ์— ์˜ํ•ด **์ „๋‹ฌ(forwarded)**๋˜๊ณ  ์žˆ์Œ์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๊ฐ€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์ผ๋ถ€ HTTP ํ—ค๋”๋ฅผ ์ฆ‰์„์—์„œ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +ํ”„๋ก์‹œ ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๋Š” ์ž์‹ ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” **ํ”„๋ก์‹œ** ๋’ค์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชจ๋ฅด๋ฏ€๋กœ, ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๊ทธ ํ—ค๋”๋“ค์„ ์‹ ๋ขฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๊ฐ€ **ํ”„๋ก์‹œ**๊ฐ€ ๋ณด๋‚ธ *forwarded* ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FastAPI CLI๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, *CLI Option* `--forwarded-allow-ips`๋ฅผ ์‚ฌ์šฉํ•ด ์–ด๋–ค IP์—์„œ ์˜จ *forwarded* ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ• ์ง€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๊ฐ€ ์‹ ๋ขฐํ•˜๋Š” **ํ”„๋ก์‹œ**๋กœ๋ถ€ํ„ฐ๋งŒ ํ†ต์‹ ์„ ๋ฐ›๋Š”๋‹ค๋ฉด, `--forwarded-allow-ips="*"`๋กœ ์„ค์ •ํ•ด ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  IP๋ฅผ ์‹ ๋ขฐํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด์ฐจํ”ผ **ํ”„๋ก์‹œ**๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” IP์—์„œ๋งŒ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ž์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ณต๊ฐœ URL์ด ๋ฌด์—‡์ธ์ง€, HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€, ๋„๋ฉ”์ธ์ด ๋ฌด์—‡์ธ์ง€ ๋“ฑ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ด์— ๋Œ€ํ•ด์„œ๋Š” [ํ”„๋ก์‹œ ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ธฐ - ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” ํ™œ์„ฑํ™”](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} ๋ฌธ์„œ์—์„œ ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## ์š”์•ฝ { #recap } + +**HTTPS**๋Š” ๋งค์šฐ ์ค‘์š”ํ•˜๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ƒ๋‹นํžˆ **ํ•ต์‹ฌ์ **์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ HTTPS์™€ ๊ด€๋ จํ•ด ํ•ด์•ผ ํ•˜๋Š” ๋…ธ๋ ฅ์˜ ๋Œ€๋ถ€๋ถ„์€ ๊ฒฐ๊ตญ **์ด ๊ฐœ๋…๋“ค์„ ์ดํ•ด**ํ•˜๊ณ  ๊ทธ๊ฒƒ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ **๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ HTTPS**์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์•Œ๊ณ  ๋‚˜๋ฉด, ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•˜๊ณ  ์„ค์ •ํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ **HTTPS** ์„ค์ • ๋ฐฉ๋ฒ•์„ ์—ฌ๋Ÿฌ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋กœ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ”’ diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md new file mode 100644 index 0000000000..e85dd02a32 --- /dev/null +++ b/docs/ko/docs/deployment/manually.md @@ -0,0 +1,157 @@ +# ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ { #run-a-server-manually } + +## `fastapi run` ๋ช…๋ น ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-fastapi-run-command } + +์š”์•ฝํ•˜๋ฉด, `fastapi run`์„ ์‚ฌ์šฉํ•ด FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น„์Šคํ•˜์„ธ์š”: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” ์ด๊ฒƒ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Ž + +์˜ˆ๋ฅผ ๋“ค์–ด ์ด ๋ช…๋ น์€ ์ปจํ…Œ์ด๋„ˆ๋‚˜ ์„œ๋ฒ„ ๋“ฑ์—์„œ **FastAPI** ์•ฑ์„ ์‹œ์ž‘ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ASGI ์„œ๋ฒ„ { #asgi-servers } + +์ด์ œ ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +FastAPI๋Š” ASGI๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”, Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. FastAPI๋Š” ASGI ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. + +์›๊ฒฉ ์„œ๋ฒ„ ๋จธ์‹ ์—์„œ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋˜๋Š” ๋‹ค๋ฅธ ASGI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํ•ต์‹ฌ ์š”์†Œ๋Š” **Uvicorn** ๊ฐ™์€ ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. `fastapi` ๋ช…๋ น์—๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์ด๊ฒƒ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์Œ์„ ํฌํ•จํ•ด ์—ฌ๋Ÿฌ ๋Œ€์•ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค: + +* Uvicorn: ๊ณ ์„ฑ๋Šฅ ASGI ์„œ๋ฒ„. +* Hypercorn: HTTP/2 ๋ฐ Trio ๋“ฑ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๊ณผ ํ˜ธํ™˜๋˜๋Š” ASGI ์„œ๋ฒ„. +* Daphne: Django Channels๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ASGI ์„œ๋ฒ„. +* Granian: Python ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ Rust HTTP ์„œ๋ฒ„. +* NGINX Unit: NGINX Unit์€ ๊ฐ€๋ณ๊ณ  ๋‹ค์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋Ÿฐํƒ€์ž„์ž…๋‹ˆ๋‹ค. + +## ์„œ๋ฒ„ ๋จธ์‹ ๊ณผ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ { #server-machine-and-server-program } + +์ด๋ฆ„์— ๊ด€ํ•ด ๊ธฐ์–ตํ•ด ๋‘˜ ์ž‘์€ ๋””ํ…Œ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’ก + +"**server**"๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ์›๊ฒฉ/ํด๋ผ์šฐ๋“œ ์ปดํ“จํ„ฐ(๋ฌผ๋ฆฌ ๋˜๋Š” ๊ฐ€์ƒ ๋จธ์‹ )์™€, ๊ทธ ๋จธ์‹ ์—์„œ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn) ๋‘˜ ๋‹ค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์œผ๋กœ "server"๋ฅผ ์ฝ์„ ๋•Œ, ์ด ๋‘ ๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. + +์›๊ฒฉ ๋จธ์‹ ์„ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ๋Š” **server**๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด์ง€๋งŒ, **machine**, **VM**(virtual machine), **node**๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ ๋ณดํ†ต Linux๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์›๊ฒฉ ๋จธ์‹ ์˜ ํ•œ ํ˜•ํƒœ๋ฅผ ๋œปํ•˜๋ฉฐ, ๊ทธ๊ณณ์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. + +## ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์„ค์น˜ํ•˜๊ธฐ { #install-the-server-program } + +FastAPI๋ฅผ ์„ค์น˜ํ•˜๋ฉด ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์ธ Uvicorn์ด ํ•จ๊ป˜ ์„ค์น˜๋˜๋ฉฐ, `fastapi run` ๋ช…๋ น์œผ๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ASGI ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +[๊ฐ€์ƒ ํ™˜๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค์น˜ํ•˜์„ธ์š”. + +์˜ˆ๋ฅผ ๋“ค์–ด Uvicorn์„ ์„ค์น˜ํ•˜๋ ค๋ฉด: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +๋‹ค๋ฅธ ์–ด๋–ค ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ๋„ ๋น„์Šทํ•œ ๊ณผ์ •์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +`standard`๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด Uvicorn์ด ๊ถŒ์žฅ๋˜๋Š” ์ถ”๊ฐ€ ์˜์กด์„ฑ ๋ช‡ ๊ฐ€์ง€๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” `asyncio`๋ฅผ ๊ณ ์„ฑ๋Šฅ์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ธ `uvloop`๊ฐ€ ํฌํ•จ๋˜๋ฉฐ, ํฐ ๋™์‹œ์„ฑ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +`pip install "fastapi[standard]"` ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ FastAPI๋ฅผ ์„ค์น˜ํ•˜๋ฉด `uvicorn[standard]`๋„ ํ•จ๊ป˜ ์„ค์น˜๋ฉ๋‹ˆ๋‹ค. + +/// + +## ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ํ•˜๊ธฐ { #run-the-server-program } + +ASGI ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด, ๋ณดํ†ต FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž„ํฌํŠธํ•˜๊ธฐ ์œ„ํ•ด ํŠน๋ณ„ํ•œ ํ˜•์‹์˜ import string์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | ์ฐธ๊ณ  + +`uvicorn main:app` ๋ช…๋ น์€ ๋‹ค์Œ์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค: + +* `main`: ํŒŒ์ผ `main.py`(Python "module"). +* `app`: `main.py` ์•ˆ์—์„œ `app = FastAPI()` ๋ผ์ธ์œผ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด. + +์ด๋Š” ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค: + +```Python +from main import app +``` + +/// + +๊ฐ ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์˜ ๋Œ€์•ˆ๋„ ๋น„์Šทํ•œ ๋ช…๋ น์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ฐ์ž์˜ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + +/// warning | ๊ฒฝ๊ณ  + +Uvicorn๊ณผ ๋‹ค๋ฅธ ์„œ๋ฒ„๋Š” ๊ฐœ๋ฐœ ์ค‘์— ์œ ์šฉํ•œ `--reload` ์˜ต์…˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. + +`--reload` ์˜ต์…˜์€ ํ›จ์”ฌ ๋” ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์†Œ๋น„ํ•˜๊ณ , ๋” ๋ถˆ์•ˆ์ •ํ•ฉ๋‹ˆ๋‹ค. + +**๊ฐœ๋ฐœ** ์ค‘์—๋Š” ํฐ ๋„์›€์ด ๋˜์ง€๋งŒ, **ํ”„๋กœ๋•์…˜**์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ **๋ง์•„์•ผ** ํ•ฉ๋‹ˆ๋‹ค. + +/// + +## ๋ฐฐํฌ ๊ฐœ๋… { #deployment-concepts } + +์ด ์˜ˆ์ œ๋“ค์€ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)์„ ์‹คํ–‰ํ•˜์—ฌ **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹œ์ž‘ํ•˜๊ณ , ์‚ฌ์ „์— ์ •ํ•œ ํฌํŠธ(์˜ˆ: `80`)์—์„œ ๋ชจ๋“  IP(`0.0.0.0`)๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ๋ฐ›๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + +์ด๊ฒƒ์ด ๊ธฐ๋ณธ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณดํ†ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถ”๊ฐ€ ์‚ฌํ•ญ๋“ค๋„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: + +* ๋ณด์•ˆ - HTTPS +* ์‹œ์ž‘ ์‹œ ์ž๋™ ์‹คํ–‰ +* ์žฌ์‹œ์ž‘ +* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜) +* ๋ฉ”๋ชจ๋ฆฌ +* ์‹œ์ž‘ ์ „ ์„ ํ–‰ ๋‹จ๊ณ„ + +๋‹ค์Œ ์žฅ๋“ค์—์„œ ์ด ๊ฐ๊ฐ์˜ ๊ฐœ๋…์„ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•ด์•ผ ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์ „๋žต์˜ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋” ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿš€ diff --git a/docs/ko/docs/how-to/authentication-error-status-code.md b/docs/ko/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..47120cae68 --- /dev/null +++ b/docs/ko/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# ์ด์ „ 403 ์ธ์ฆ ์˜ค๋ฅ˜ ์ƒํƒœ ์ฝ”๋“œ ์‚ฌ์šฉํ•˜๊ธฐ { #use-old-403-authentication-error-status-codes } + +FastAPI ๋ฒ„์ „ `0.122.0` ์ด์ „์—๋Š”, ํ†ตํ•ฉ ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์ธ์ฆ ์‹คํŒจ ํ›„ ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ HTTP ์ƒํƒœ ์ฝ”๋“œ `403 Forbidden`์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +FastAPI ๋ฒ„์ „ `0.122.0`๋ถ€ํ„ฐ๋Š” ๋” ์ ์ ˆํ•œ HTTP ์ƒํƒœ ์ฝ”๋“œ `401 Unauthorized`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, HTTP ๋ช…์„ธ์ธ RFC 7235, RFC 9110๋ฅผ ๋”ฐ๋ผ ์‘๋‹ต์— ํ•ฉ๋ฆฌ์ ์ธ `WWW-Authenticate` ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์–ด๋–ค ์ด์œ ๋กœ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด์ „ ๋™์ž‘์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋ณด์•ˆ ํด๋ž˜์Šค์—์„œ `make_not_authenticated_error` ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์ด์ „ ๋™์ž‘์œผ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ๋ณธ๊ฐ’์ธ `401 Unauthorized` ์˜ค๋ฅ˜ ๋Œ€์‹  `403 Forbidden` ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” `HTTPBearer`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} + +/// tip | ํŒ + +ํ•จ์ˆ˜๋Š” ์˜ˆ์™ธ๋ฅผ `raise`ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์˜ˆ์™ธ ์ธ์Šคํ„ด์Šค๋ฅผ `return`ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š”(`raise`) ์ž‘์—…์€ ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. + +/// diff --git a/docs/ko/docs/how-to/custom-docs-ui-assets.md b/docs/ko/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..d6383c29cb --- /dev/null +++ b/docs/ko/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ์ปค์Šคํ…€ Docs UI ์ •์  ์—์…‹(์ž์ฒด ํ˜ธ์ŠคํŒ…) { #custom-docs-ui-static-assets-self-hosting } + +API ๋ฌธ์„œ๋Š” **Swagger UI**์™€ **ReDoc**์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ๊ฐ JavaScript์™€ CSS ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ํŒŒ์ผ์€ CDN์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠน์ • CDN์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํŒŒ์ผ์„ ์ง์ ‘ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +## JavaScript์™€ CSS์šฉ ์ปค์Šคํ…€ CDN { #custom-cdn-for-javascript-and-css } + +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ CDN์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด `https://unpkg.com/`์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. + +์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ๊ตญ๊ฐ€์—์„œ ์ผ๋ถ€ URL์„ ์ œํ•œํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์ž๋™ ๋ฌธ์„œ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-the-automatic-docs } + +์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ์ž๋™ ๋ฌธ์„œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž๋™ ๋ฌธ์„œ๋Š” ๊ธฐ๋ณธ CDN์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”: + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} + +### ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs } + +์ด์ œ ์ปค์Šคํ…€ ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +FastAPI ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์šฉ HTML ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* `openapi_url`: ๋ฌธ์„œ HTML ํŽ˜์ด์ง€๊ฐ€ API์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” `app.openapi_url` ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `title`: API์˜ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค. +* `oauth2_redirect_url`: ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์„œ `app.swagger_ui_oauth2_redirect_url`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `swagger_js_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **JavaScript** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์ปค์Šคํ…€ CDN URL์ž…๋‹ˆ๋‹ค. +* `swagger_css_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **CSS** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์ปค์Šคํ…€ CDN URL์ž…๋‹ˆ๋‹ค. + +ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค... + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | ํŒ + +`swagger_ui_redirect`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋„์›€์ด ๋˜๋Š” ํ—ฌํผ์ž…๋‹ˆ๋‹ค. + +API๋ฅผ OAuth2 provider์™€ ํ†ตํ•ฉํ•˜๋ฉด ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค ํš๋“ํ•œ ์ž๊ฒฉ ์ฆ๋ช…์œผ๋กœ API ๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ OAuth2 ์ธ์ฆ์„ ์‚ฌ์šฉํ•ด API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์œ„ํ•ด ์ด "redirect" ํ—ฌํผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// + +### ํ…Œ์ŠคํŠธ์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋งŒ๋“ค๊ธฐ { #create-a-path-operation-to-test-it } + +์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”: + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} + +### ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-it } + +์ด์ œ http://127.0.0.1:8000/docs์—์„œ ๋ฌธ์„œ์— ์ ‘์†ํ•œ ๋’ค ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•˜๋ฉด, ์ƒˆ CDN์—์„œ ์—์…‹์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ๋ฌธ์„œ์šฉ JavaScript์™€ CSS ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๊ธฐ { #self-hosting-javascript-and-css-for-docs } + +JavaScript์™€ CSS๋ฅผ ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜คํ”„๋ผ์ธ ์ƒํƒœ์ด๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์ธํ„ฐ๋„ท์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ™˜๊ฒฝ, ๋˜๋Š” ๋กœ์ปฌ ๋„คํŠธ์›Œํฌ์—์„œ๋„ ์•ฑ์ด ๊ณ„์† ๋™์ž‘ํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋Š” ๋™์ผํ•œ FastAPI ์•ฑ์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ ์ง์ ‘ ์ œ๊ณตํ•˜๊ณ , ๋ฌธ์„œ๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค. + +### ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ { #project-file-structure } + +ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +์ด์ œ ํ•ด๋‹น ์ •์  ํŒŒ์ผ์„ ์ €์žฅํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“œ์„ธ์š”. + +์ƒˆ ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œํ•˜๊ธฐ { #download-the-files } + +๋ฌธ์„œ์— ํ•„์š”ํ•œ ์ •์  ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•ด์„œ `static/` ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋„ฃ์œผ์„ธ์š”. + +๊ฐ ๋งํฌ๋ฅผ ์šฐํด๋ฆญํ•œ ๋’ค "๋งํฌ๋ฅผ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์ €์žฅ..."๊ณผ ๋น„์Šทํ•œ ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +**Swagger UI**๋Š” ๋‹ค์Œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +* `swagger-ui-bundle.js` +* `swagger-ui.css` + +**ReDoc**์€ ๋‹ค์Œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +* `redoc.standalone.js` + +์ดํ›„ ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### ์ •์  ํŒŒ์ผ ์ œ๊ณตํ•˜๊ธฐ { #serve-the-static-files } + +* `StaticFiles`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. +* ํŠน์ • ๊ฒฝ๋กœ์— `StaticFiles()` ์ธ์Šคํ„ด์Šค๋ฅผ "๋งˆ์šดํŠธ(mount)"ํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} + +### ์ •์  ํŒŒ์ผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-the-static-files } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ณ  http://127.0.0.1:8000/static/redoc.standalone.js๋กœ ์ด๋™ํ•˜์„ธ์š”. + +**ReDoc**์šฉ ๋งค์šฐ ๊ธด JavaScript ํŒŒ์ผ์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +์ด๋Š” ์•ฑ์—์„œ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฌธ์„œ์šฉ ์ •์  ํŒŒ์ผ์„ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๋ฐฐ์น˜ํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด ์ค๋‹ˆ๋‹ค. + +์ด์ œ ๋ฌธ์„œ๊ฐ€ ์ด ์ •์  ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์•ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์ •์  ํŒŒ์ผ์„ ์œ„ํ•œ ์ž๋™ ๋ฌธ์„œ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-the-automatic-docs-for-static-files } + +์ปค์Šคํ…€ CDN์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ฒซ ๋‹จ๊ณ„๋Š” ์ž๋™ ๋ฌธ์„œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž๋™ ๋ฌธ์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ CDN์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”: + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} + +### ์ •์  ํŒŒ์ผ์„ ์œ„ํ•œ ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs-for-static-files } + +๊ทธ๋ฆฌ๊ณ  ์ปค์Šคํ…€ CDN์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ, ์ด์ œ ์ปค์Šคํ…€ ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋‹ค์‹œ ํ•œ ๋ฒˆ, FastAPI ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์šฉ HTML ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* `openapi_url`: ๋ฌธ์„œ HTML ํŽ˜์ด์ง€๊ฐ€ API์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” `app.openapi_url` ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `title`: API์˜ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค. +* `oauth2_redirect_url`: ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์„œ `app.swagger_ui_oauth2_redirect_url`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* `swagger_js_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **JavaScript** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. **์ด์ œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค**. +* `swagger_css_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **CSS** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. **์ด์ œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค**. + +ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค... + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | ํŒ + +`swagger_ui_redirect`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋„์›€์ด ๋˜๋Š” ํ—ฌํผ์ž…๋‹ˆ๋‹ค. + +API๋ฅผ OAuth2 provider์™€ ํ†ตํ•ฉํ•˜๋ฉด ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค ํš๋“ํ•œ ์ž๊ฒฉ ์ฆ๋ช…์œผ๋กœ API ๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ OAuth2 ์ธ์ฆ์„ ์‚ฌ์šฉํ•ด API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์œ„ํ•ด ์ด "redirect" ํ—ฌํผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// + +### ์ •์  ํŒŒ์ผ ํ…Œ์ŠคํŠธ์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋งŒ๋“ค๊ธฐ { #create-a-path-operation-to-test-static-files } + +์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”: + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} + +### ์ •์  ํŒŒ์ผ UI ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-static-files-ui } + +์ด์ œ WiFi ์—ฐ๊ฒฐ์„ ๋Š๊ณ  http://127.0.0.1:8000/docs์—์„œ ๋ฌธ์„œ์— ์ ‘์†ํ•œ ๋’ค ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•ด ๋ณด์„ธ์š”. + +์ธํ„ฐ๋„ท์ด ์—†์–ด๋„ API ๋ฌธ์„œ๋ฅผ ๋ณด๊ณ , API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/how-to/custom-request-and-route.md b/docs/ko/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..335193bb35 --- /dev/null +++ b/docs/ko/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ์ปค์Šคํ…€ Request ๋ฐ APIRoute ํด๋ž˜์Šค { #custom-request-and-apiroute-class } + +์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” `Request`์™€ `APIRoute` ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋กœ์ง์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํŠนํžˆ, ์ด๋Š” middleware์— ์žˆ๋Š” ๋กœ์ง์˜ ์ข‹์€ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „์— ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. + +/// danger | ์œ„ํ—˜ + +์ด ๊ธฐ๋Šฅ์€ "๊ณ ๊ธ‰" ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. + +**FastAPI**๋ฅผ ์ด์ œ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด ์ด ์„น์…˜์€ ๊ฑด๋„ˆ๋›ฐ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. + +/// + +## ์‚ฌ์šฉ ์‚ฌ๋ก€ { #use-cases } + +์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +* JSON์ด ์•„๋‹Œ ์š”์ฒญ ๋ฐ”๋””๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ(์˜ˆ: `msgpack`). +* gzip์œผ๋กœ ์••์ถ•๋œ ์š”์ฒญ ๋ฐ”๋”” ์••์ถ• ํ•ด์ œํ•˜๊ธฐ. +* ๋ชจ๋“  ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ž๋™์œผ๋กœ ๋กœ๊น…ํ•˜๊ธฐ. + +## ์ปค์Šคํ…€ ์š”์ฒญ ๋ฐ”๋”” ์ธ์ฝ”๋”ฉ ์ฒ˜๋ฆฌํ•˜๊ธฐ { #handling-custom-request-body-encodings } + +์ปค์Šคํ…€ `Request` ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด gzip ์š”์ฒญ์˜ ์••์ถ•์„ ํ•ด์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ปค์Šคํ…€ ์š”์ฒญ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ `APIRoute` ์„œ๋ธŒํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +### ์ปค์Šคํ…€ `GzipRequest` ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ { #create-a-custom-gziprequest-class } + +/// tip | ํŒ + +์ด ์˜ˆ์‹œ๋Š” ๋™์ž‘ ๋ฐฉ์‹ ์‹œ์—ฐ์„ ์œ„ํ•œ ์žฅ๋‚œ๊ฐ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. Gzip ์ง€์›์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์ œ๊ณต๋˜๋Š” [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +๋จผ์ €, `GzipRequest` ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” `Request.body()` ๋ฉ”์„œ๋“œ๋ฅผ ๋ฎ์–ด์จ์„œ, ์ ์ ˆํ•œ ํ—ค๋”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฐ”๋””๋ฅผ ์••์ถ• ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. + +ํ—ค๋”์— `gzip`์ด ์—†์œผ๋ฉด ๋ฐ”๋””๋ฅผ ์••์ถ• ํ•ด์ œํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋™์ผํ•œ route ํด๋ž˜์Šค๊ฐ€ gzip์œผ๋กœ ์••์ถ•๋œ ์š”์ฒญ๊ณผ ์••์ถ•๋˜์ง€ ์•Š์€ ์š”์ฒญ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ์ปค์Šคํ…€ `GzipRoute` ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ { #create-a-custom-gziproute-class } + +๋‹ค์Œ์œผ๋กœ, `GzipRequest`๋ฅผ ํ™œ์šฉํ•˜๋Š” `fastapi.routing.APIRoute`์˜ ์ปค์Šคํ…€ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. + +์ด๋ฒˆ์—๋Š” `APIRoute.get_route_handler()` ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ฉ๋‹ˆ๋‹ค. + +์ด ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์š”์ฒญ์„ ๋ฐ›์•„ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋Š” ์›๋ณธ ์š”์ฒญ์œผ๋กœ๋ถ€ํ„ฐ `GzipRequest`๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +`Request`์—๋Š” `request.scope` ์†์„ฑ์ด ์žˆ๋Š”๋ฐ, ์ด๋Š” ์š”์ฒญ๊ณผ ๊ด€๋ จ๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” Python `dict`์ž…๋‹ˆ๋‹ค. + +`Request`์—๋Š” ๋˜ํ•œ `request.receive`๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๋Š” ์š”์ฒญ์˜ ๋ฐ”๋””๋ฅผ "๋ฐ›๊ธฐ(receive)" ์œ„ํ•œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. + +`scope` `dict`์™€ `receive` ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ ASGI ๋ช…์„ธ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ด ๋‘ ๊ฐ€์ง€, `scope`์™€ `receive`๊ฐ€ ์ƒˆ๋กœ์šด `Request` ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. + +`Request`์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๋ ค๋ฉด Starlette์˜ Requests ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. + +/// + +`GzipRequest.get_route_handler`๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ํ•˜๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ `Request`๋ฅผ `GzipRequest`๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ์šฐ๋ฆฌ์˜ `GzipRequest`๊ฐ€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์—(ํ•„์š”ํ•˜๋‹ค๋ฉด) ๋ฐ์ดํ„ฐ์˜ ์••์ถ• ํ•ด์ œ๋ฅผ ๋‹ด๋‹นํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ ์ดํ›„์˜ ๋ชจ๋“  ์ฒ˜๋ฆฌ ๋กœ์ง์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `GzipRequest.body`์—์„œ ๋ณ€๊ฒฝ์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•„์š”ํ•  ๋•Œ **FastAPI**๊ฐ€ ๋กœ๋“œํ•˜๋Š” ์‹œ์ ์— ์š”์ฒญ ๋ฐ”๋””๋Š” ์ž๋™์œผ๋กœ ์••์ถ• ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค. + +## ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์š”์ฒญ ๋ฐ”๋”” ์ ‘๊ทผํ•˜๊ธฐ { #accessing-the-request-body-in-an-exception-handler } + +/// tip | ํŒ + +๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด `RequestValidationError`์— ๋Œ€ํ•œ ์ปค์Šคํ…€ ํ•ธ๋“ค๋Ÿฌ์—์„œ `body`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์•„๋งˆ ํ›จ์”ฌ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค([์˜ค๋ฅ˜ ์ฒ˜๋ฆฌํ•˜๊ธฐ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). + +ํ•˜์ง€๋งŒ ์ด ์˜ˆ์‹œ๋„ ์—ฌ์ „ํžˆ ์œ ํšจํ•˜๋ฉฐ, ๋‚ด๋ถ€ ์ปดํฌ๋„ŒํŠธ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. + +/// + +๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์š”์ฒญ ๋ฐ”๋””์— ์ ‘๊ทผํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•„์š”ํ•œ ๊ฒƒ์€ `try`/`except` ๋ธ”๋ก ์•ˆ์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ `Request` ์ธ์Šคํ„ด์Šค๋Š” ์—ฌ์ „ํžˆ ์Šค์ฝ”ํ”„ ์•ˆ์— ๋‚จ์•„ ์žˆ์œผ๋ฏ€๋กœ, ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ฝ๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## ๋ผ์šฐํ„ฐ์—์„œ์˜ ์ปค์Šคํ…€ `APIRoute` ํด๋ž˜์Šค { #custom-apiroute-class-in-a-router } + +`APIRouter`์˜ `route_class` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +์ด ์˜ˆ์‹œ์—์„œ๋Š” `router` ์•„๋ž˜์˜ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋“ค์ด ์ปค์Šคํ…€ `TimedRoute` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์‘๋‹ต์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„์„ ๋‹ด์€ ์ถ”๊ฐ€ `X-Response-Time` ํ—ค๋”๊ฐ€ ์‘๋‹ต์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/ko/docs/how-to/extending-openapi.md b/docs/ko/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..d04d6c23e3 --- /dev/null +++ b/docs/ko/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# OpenAPI ํ™•์žฅํ•˜๊ธฐ { #extending-openapi } + +์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ์„น์…˜์—์„œ ๊ทธ ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์ผ๋ฐ˜์ ์ธ ๊ณผ์ • { #the-normal-process } + +์ผ๋ฐ˜์ ์ธ(๊ธฐ๋ณธ) ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + +`FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์ธ์Šคํ„ด์Šค)์—๋Š” OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” `.openapi()` ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ `/openapi.json`(๋˜๋Š” `openapi_url`์— ์„ค์ •ํ•œ ๊ฒฝ๋กœ)์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. + +์ด ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ `.openapi()` ๋ฉ”์„œ๋“œ ๊ฒฐ๊ณผ๋ฅผ JSON ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค. + +๊ธฐ๋ณธ์ ์œผ๋กœ `.openapi()` ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœํผํ‹ฐ `.openapi_schema`์— ๋‚ด์šฉ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์žˆ์œผ๋ฉด ๊ทธ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์—†์œผ๋ฉด `fastapi.openapi.utils.get_openapi`์— ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  `get_openapi()` ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค: + +* `title`: ๋ฌธ์„œ์— ํ‘œ์‹œ๋˜๋Š” OpenAPI ์ œ๋ชฉ. +* `version`: API ๋ฒ„์ „. ์˜ˆ: `2.5.0`. +* `openapi_version`: ์‚ฌ์šฉ๋˜๋Š” OpenAPI ์ŠคํŽ™ ๋ฒ„์ „. ๊ธฐ๋ณธ๊ฐ’์€ ์ตœ์‹ ์ธ `3.1.0`. +* `summary`: API์— ๋Œ€ํ•œ ์งง์€ ์š”์•ฝ. +* `description`: API ์„ค๋ช…. markdown์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. +* `routes`: ๋ผ์šฐํŠธ ๋ชฉ๋ก. ๊ฐ๊ฐ ๋“ฑ๋ก๋œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์ž…๋‹ˆ๋‹ค. `app.routes`์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +`summary` ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” OpenAPI 3.1.0 ์ด์ƒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI 0.99.0 ์ด์ƒ์—์„œ ์ง€์›๋ฉ๋‹ˆ๋‹ค. + +/// + +## ๊ธฐ๋ณธ๊ฐ’ ๋ฎ์–ด์“ฐ๊ธฐ { #overriding-the-defaults } + +์œ„ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•„์š”ํ•œ ๊ฐ ๋ถ€๋ถ„์„ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ์ปค์Šคํ…€ ๋กœ๊ณ ๋ฅผ ํฌํ•จํ•˜๊ธฐ ์œ„ํ•œ ReDoc์˜ OpenAPI ํ™•์žฅ์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +### ์ผ๋ฐ˜์ ์ธ **FastAPI** { #normal-fastapi } + +๋จผ์ €, ํ‰์†Œ์ฒ˜๋Ÿผ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ชจ๋‘ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} + +### OpenAPI ์Šคํ‚ค๋งˆ ์ƒ์„ฑํ•˜๊ธฐ { #generate-the-openapi-schema } + +๊ทธ๋‹ค์Œ `custom_openapi()` ํ•จ์ˆ˜ ์•ˆ์—์„œ, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} + +### OpenAPI ์Šคํ‚ค๋งˆ ์ˆ˜์ •ํ•˜๊ธฐ { #modify-the-openapi-schema } + +์ด์ œ OpenAPI ์Šคํ‚ค๋งˆ์˜ `info` "object"์— ์ปค์Šคํ…€ `x-logo`๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ReDoc ํ™•์žฅ์„ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} + +### OpenAPI ์Šคํ‚ค๋งˆ ์บ์‹œํ•˜๊ธฐ { #cache-the-openapi-schema } + +์ƒ์„ฑํ•œ ์Šคํ‚ค๋งˆ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ "cache"๋กœ `.openapi_schema` ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ API ๋ฌธ์„œ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์Šคํ‚ค๋งˆ๋ฅผ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. + +์Šคํ‚ค๋งˆ๋Š” ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜๊ณ , ์ดํ›„ ์š”์ฒญ์—์„œ๋Š” ๊ฐ™์€ ์บ์‹œ๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} + +### ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-method } + +์ด์ œ `.openapi()` ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ ํ•จ์ˆ˜๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} + +### ํ™•์ธํ•˜๊ธฐ { #check-it } + +http://127.0.0.1:8000/redoc๋กœ ์ด๋™ํ•˜๋ฉด ์ปค์Šคํ…€ ๋กœ๊ณ (์ด ์˜ˆ์‹œ์—์„œ๋Š” **FastAPI** ๋กœ๊ณ )๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + diff --git a/docs/ko/docs/how-to/general.md b/docs/ko/docs/how-to/general.md new file mode 100644 index 0000000000..a18dc68a21 --- /dev/null +++ b/docs/ko/docs/how-to/general.md @@ -0,0 +1,39 @@ +# ์ผ๋ฐ˜ - ์‚ฌ์šฉ ๋ฐฉ๋ฒ• - ๋ ˆ์‹œํ”ผ { #general-how-to-recipes } + +์ผ๋ฐ˜์ ์ด๊ฑฐ๋‚˜ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์งˆ๋ฌธ์— ๋Œ€ํ•ด, ๋ฌธ์„œ์˜ ๋‹ค๋ฅธ ์œ„์น˜๋กœ ์•ˆ๋‚ดํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํฌ์ธํ„ฐ๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. + +## ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง - ๋ณด์•ˆ { #filter-data-security } + +๋ฐ˜ํ™˜ํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณผ๋„ํ•˜๊ฒŒ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด, [ํŠœํ† ๋ฆฌ์–ผ - ์‘๋‹ต ๋ชจ๋ธ - ๋ฐ˜ํ™˜ ํƒ€์ž…](../tutorial/response-model.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## ๋ฌธ์„œํ™” ํƒœ๊ทธ - OpenAPI { #documentation-tags-openapi } + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฌธ์„œ UI์—์„œ ์ด๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ํƒœ๊ทธ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## ๋ฌธ์„œํ™” ์š”์•ฝ ๋ฐ ์„ค๋ช… - OpenAPI { #documentation-summary-and-description-openapi } + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์š”์•ฝ๊ณผ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฌธ์„œ UI์— ํ‘œ์‹œํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์š”์•ฝ ๋ฐ ์„ค๋ช…](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## ๋ฌธ์„œํ™” ์‘๋‹ต ์„ค๋ช… - OpenAPI { #documentation-response-description-openapi } + +๋ฌธ์„œ UI์— ํ‘œ์‹œ๋˜๋Š” ์‘๋‹ต์˜ ์„ค๋ช…์„ ์ •์˜ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์‘๋‹ต ์„ค๋ช…](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## ๋ฌธ์„œํ™” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ง€์› ์ค‘๋‹จํ•˜๊ธฐ - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ง€์› ์ค‘๋‹จ(deprecate)์œผ๋กœ ํ‘œ์‹œํ•˜๊ณ , ๋ฌธ์„œ UI์— ๋ณด์—ฌ์ฃผ๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์ง€์› ์ค‘๋‹จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## ์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  JSON ํ˜ธํ™˜์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ { #convert-any-data-to-json-compatible } + +์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  JSON ํ˜ธํ™˜ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - JSON ํ˜ธํ™˜ ์ธ์ฝ”๋”](../tutorial/encoder.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## OpenAPI ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ - ๋ฌธ์„œ { #openapi-metadata-docs } + +๋ผ์ด์„ ์Šค, ๋ฒ„์ „, ์—ฐ๋ฝ์ฒ˜ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•ด OpenAPI ์Šคํ‚ค๋งˆ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## OpenAPI ์‚ฌ์šฉ์ž ์ •์˜ URL { #openapi-custom-url } + +OpenAPI URL์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ(๋˜๋Š” ์ œ๊ฑฐ)ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +## OpenAPI ๋ฌธ์„œ URL { #openapi-docs-urls } + +์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ๋ฌธ์„œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์‚ฌ์šฉํ•˜๋Š” URL์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. diff --git a/docs/ko/docs/how-to/graphql.md b/docs/ko/docs/how-to/graphql.md new file mode 100644 index 0000000000..3cc467eb71 --- /dev/null +++ b/docs/ko/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +**FastAPI**๋Š” **ASGI** ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ, ASGI์™€๋„ ํ˜ธํ™˜๋˜๋Š” ์–ด๋–ค **GraphQL** ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“  ๋งค์šฐ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ผ๋ฐ˜ FastAPI **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ**์™€ GraphQL์„ ํ•จ๊ป˜ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +**GraphQL**์€ ๋ช‡ ๊ฐ€์ง€ ๋งค์šฐ ํŠน์ •ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. + +์ผ๋ฐ˜์ ์ธ **web API**์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ **์žฅ์ **๊ณผ **๋‹จ์ **์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๋Ÿฌ๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ **์ด์ **์ด **๋‹จ์ **์„ ์ƒ์‡„ํ•˜๋Š”์ง€ ๊ผญ ํ‰๊ฐ€ํ•ด ๋ณด์„ธ์š”. ๐Ÿค“ + +/// + +## GraphQL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ { #graphql-libraries } + +๋‹ค์Œ์€ **ASGI** ์ง€์›์ด ์žˆ๋Š” **GraphQL** ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ž…๋‹ˆ๋‹ค. **FastAPI**์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* Strawberry ๐Ÿ“ + * FastAPI์šฉ ๋ฌธ์„œ ์ œ๊ณต +* Ariadne + * FastAPI์šฉ ๋ฌธ์„œ ์ œ๊ณต +* Tartiflette + * ASGI ํ†ตํ•ฉ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด Tartiflette ASGI ์‚ฌ์šฉ +* Graphene + * starlette-graphene3 ์‚ฌ์šฉ + +## Strawberry๋กœ GraphQL ์‚ฌ์šฉํ•˜๊ธฐ { #graphql-with-strawberry } + +**GraphQL**๋กœ ์ž‘์—…ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ์ž‘์—…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, **Strawberry**๋ฅผ **๊ถŒ์žฅ**ํ•ฉ๋‹ˆ๋‹ค. **FastAPI**์˜ ์„ค๊ณ„์™€ ๊ฐ€์žฅ ๊ฐ€๊น๊ณ , ๋ชจ๋“  ๊ฒƒ์ด **type annotations**์— ๊ธฐ๋ฐ˜ํ•ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ œ๊ฒŒ ๋ฌป๋Š”๋‹ค๋ฉด ์•„๋งˆ **Strawberry**๋ฅผ ๋จผ์ € ์‹œ๋„ํ•ด ๋ณด๋ผ๊ณ  ์ œ์•ˆํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋‹ค์Œ์€ Strawberry๋ฅผ FastAPI์™€ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค: + +{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} + +Strawberry ๋ฌธ์„œ์—์„œ Strawberry์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ FastAPI์—์„œ Strawberry ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋ฌธ์„œ๋„ ํ™•์ธํ•ด ๋ณด์„ธ์š”. + +## Starlette์˜ ์˜ˆ์ „ `GraphQLApp` { #older-graphqlapp-from-starlette } + +์ด์ „ ๋ฒ„์ „์˜ Starlette์—๋Š” Graphene๊ณผ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•œ `GraphQLApp` ํด๋ž˜์Šค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. + +์ด๊ฒƒ์€ Starlette์—์„œ deprecated ๋˜์—ˆ์ง€๋งŒ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋˜ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฐ™์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃจ๊ณ  **๊ฑฐ์˜ ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค**๋ฅผ ๊ฐ€์ง„ starlette-graphene3๋กœ ์‰ฝ๊ฒŒ **๋งˆ์ด๊ทธ๋ ˆ์ด์…˜**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +GraphQL์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ปค์Šคํ…€ ํด๋ž˜์Šค์™€ ํƒ€์ž… ๋Œ€์‹  type annotations์— ๊ธฐ๋ฐ˜ํ•œ Strawberry๋ฅผ ์—ฌ์ „ํžˆ ํ™•์ธํ•ด ๋ณด์‹œ๊ธธ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. + +/// + +## ๋” ์•Œ์•„๋ณด๊ธฐ { #learn-more } + +๊ณต์‹ GraphQL ๋ฌธ์„œ์—์„œ **GraphQL**์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋˜ํ•œ ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ๋„ ํ•ด๋‹น ๋งํฌ์—์„œ ๋” ์ž์„ธํžˆ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/how-to/index.md b/docs/ko/docs/how-to/index.md new file mode 100644 index 0000000000..9321c488bd --- /dev/null +++ b/docs/ko/docs/how-to/index.md @@ -0,0 +1,13 @@ +# How To - ๋ ˆ์‹œํ”ผ { #how-to-recipes } + +์—ฌ๊ธฐ์—์„œ๋Š” **์—ฌ๋Ÿฌ ์ฃผ์ œ**์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ๋ ˆ์‹œํ”ผ(โ€œhow toโ€ ๊ฐ€์ด๋“œ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋Œ€๋ถ€๋ถ„์˜ ์•„์ด๋””์–ด๋Š” ์–ด๋А ์ •๋„ **์„œ๋กœ ๋…๋ฆฝ์ **์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ **์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ**์— ์ง์ ‘ ์ ์šฉ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ•™์Šตํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. + +ํ”„๋กœ์ ํŠธ์— ํฅ๋ฏธ๋กญ๊ณ  ์œ ์šฉํ•ด ๋ณด์ด๋Š” ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด ํ™•์ธํ•ด ๋ณด์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์•„๋งˆ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +**FastAPI๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ํ•™์Šต**ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด(๊ถŒ์žฅ), ๋Œ€์‹  [ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ](../tutorial/index.md){.internal-link target=_blank}๋ฅผ ์žฅ๋ณ„๋กœ ์ฝ์–ด๋ณด์„ธ์š”. + +/// diff --git a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..6e528ecaf5 --- /dev/null +++ b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# Pydantic v1์—์„œ Pydantic v2๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ { #migrate-from-pydantic-v1-to-pydantic-v2 } + +์˜ค๋ž˜๋œ FastAPI ์•ฑ์ด ์žˆ๋‹ค๋ฉด Pydantic ๋ฒ„์ „ 1์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +FastAPI 0.100.0 ๋ฒ„์ „์€ Pydantic v1 ๋˜๋Š” v2 ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ์„ค์น˜๋˜์–ด ์žˆ๋Š” ์ชฝ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. + +FastAPI 0.119.0 ๋ฒ„์ „์—์„œ๋Š” v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, Pydantic v2 ๋‚ด๋ถ€์—์„œ Pydantic v1์„(`pydantic.v1`๋กœ) ๋ถ€๋ถ„์ ์œผ๋กœ ์ง€์›ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. + +FastAPI 0.126.0 ๋ฒ„์ „์—์„œ๋Š” Pydantic v1 ์ง€์›์„ ์ค‘๋‹จํ–ˆ์ง€๋งŒ, `pydantic.v1`์€ ์ž ์‹œ ๋™์•ˆ ๊ณ„์† ์ง€์›ํ–ˆ์Šต๋‹ˆ๋‹ค. + +/// warning | ๊ฒฝ๊ณ  + +Pydantic ํŒ€์€ **Python 3.14**๋ถ€ํ„ฐ ์ตœ์‹  Python ๋ฒ„์ „์—์„œ Pydantic v1 ์ง€์›์„ ์ค‘๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” `pydantic.v1`๋„ ํฌํ•จ๋˜๋ฉฐ, Python 3.14 ์ด์ƒ์—์„œ๋Š” ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +Python์˜ ์ตœ์‹  ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Pydantic v2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +/// + +Pydantic v1์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ค๋ž˜๋œ FastAPI ์•ฑ์ด ์žˆ๋‹ค๋ฉด, ์—ฌ๊ธฐ์„œ๋Š” ์ด๋ฅผ Pydantic v2๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ ์ง„์  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋•๋Š” **FastAPI 0.119.0์˜ ๊ธฐ๋Šฅ**์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ๊ณต์‹ ๊ฐ€์ด๋“œ { #official-guide } + +Pydantic์—๋Š” v1์—์„œ v2๋กœ์˜ ๊ณต์‹ Migration Guide๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” ๋ฌด์—‡์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€, ๊ฒ€์ฆ์ด ์ด์ œ ์–ด๋–ป๊ฒŒ ๋” ์ •ํ™•ํ•˜๊ณ  ์—„๊ฒฉํ•ด์กŒ๋Š”์ง€, ๊ฐ€๋Šฅํ•œ ์ฃผ์˜์‚ฌํ•ญ ๋“ฑ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์„ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ฝ์–ด๋ณด๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค. + +## ํ…Œ์ŠคํŠธ { #tests } + +์•ฑ์— ๋Œ€ํ•œ [tests](../tutorial/testing.md){.internal-link target=_blank}๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ง€์†์  ํ†ตํ•ฉ(CI)์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ๋„ ๋ชจ๋“  ๊ฒƒ์ด ๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ ๊ณ„์† ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## `bump-pydantic` { #bump-pydantic } + +๋งŽ์€ ๊ฒฝ์šฐ, ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์—†์ด ์ผ๋ฐ˜์ ์ธ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด Pydantic v1์—์„œ Pydantic v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณผ์ • ๋Œ€๋ถ€๋ถ„์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ™์€ Pydantic ํŒ€์ด ์ œ๊ณตํ•˜๋Š” `bump-pydantic`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ๋„๊ตฌ๋Š” ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์˜ ๋Œ€๋ถ€๋ถ„์„ ์ž๋™์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋ชจ๋“  ๊ฒƒ์ด ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ž˜ ๋œ๋‹ค๋ฉด ๋์ž…๋‹ˆ๋‹ค. ๐Ÿ˜Ž + +## v2 ์•ˆ์˜ Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2๋Š” Pydantic v1์˜ ๋ชจ๋“  ๊ฒƒ์„ ์„œ๋ธŒ๋ชจ๋“ˆ `pydantic.v1`๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” Python 3.13๋ณด๋‹ค ๋†’์€ ๋ฒ„์ „์—์„œ๋Š” ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ฆ‰, Pydantic v2์˜ ์ตœ์‹  ๋ฒ„์ „์„ ์„ค์น˜ํ•œ ๋’ค, ์ด ์„œ๋ธŒ๋ชจ๋“ˆ์—์„œ ์˜ˆ์ „ Pydantic v1 ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ importํ•˜์—ฌ ์˜ˆ์ „ Pydantic v1์„ ์„ค์น˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### v2 ์•ˆ์˜ Pydantic v1์— ๋Œ€ํ•œ FastAPI ์ง€์› { #fastapi-support-for-pydantic-v1-in-v2 } + +FastAPI 0.119.0๋ถ€ํ„ฐ๋Š” v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, Pydantic v2 ๋‚ด๋ถ€์˜ Pydantic v1์— ๋Œ€ํ•ด์„œ๋„ ๋ถ€๋ถ„์ ์ธ ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ Pydantic์„ ์ตœ์‹  v2๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , import๋ฅผ `pydantic.v1` ์„œ๋ธŒ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๊พธ๋ฉด, ๋งŽ์€ ๊ฒฝ์šฐ ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | ๊ฒฝ๊ณ  + +Pydantic ํŒ€์ด Python 3.14๋ถ€ํ„ฐ ์ตœ์‹  Python ๋ฒ„์ „์—์„œ Pydantic v1์„ ๋” ์ด์ƒ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, `pydantic.v1`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์—ญ์‹œ Python 3.14 ์ด์ƒ์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์—ผ๋‘์— ๋‘์„ธ์š”. + +/// + +### ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2 ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic์—์„œ๋Š” Pydantic v2 ๋ชจ๋ธ์˜ ํ•„๋“œ๋ฅผ Pydantic v1 ๋ชจ๋ธ๋กœ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๋ฐ˜๋Œ€๋กœ ํ•˜๋Š” ๊ฒƒ์„ **์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...ํ•˜์ง€๋งŒ ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2๋ฅผ ์‚ฌ์šฉํ•˜๋˜, ๋ชจ๋ธ์„ ๋ถ„๋ฆฌํ•ด์„œ ๋‘˜ ์ˆ˜๋Š” ์žˆ์Šต๋‹ˆ๋‹ค. + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” FastAPI ์•ฑ์˜ ๊ฐ™์€ **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ**์—์„œ Pydantic v1๊ณผ v2 ๋ชจ๋ธ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +์œ„ ์˜ˆ์ œ์—์„œ ์ž…๋ ฅ ๋ชจ๋ธ์€ Pydantic v1 ๋ชจ๋ธ์ด๊ณ , ์ถœ๋ ฅ ๋ชจ๋ธ(`response_model=ItemV2`๋กœ ์ •์˜๋จ)์€ Pydantic v2 ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. + +### Pydantic v1 ํŒŒ๋ผ๋ฏธํ„ฐ { #pydantic-v1-parameters } + +Pydantic v1 ๋ชจ๋ธ๊ณผ ํ•จ๊ป˜ `Body`, `Query`, `Form` ๋“ฑ ํŒŒ๋ผ๋ฏธํ„ฐ์šฉ FastAPI ์ „์šฉ ๋„๊ตฌ ์ผ๋ถ€๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด, Pydantic v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋งˆ์น  ๋•Œ๊นŒ์ง€ `fastapi.temp_pydantic_v1_params`์—์„œ importํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### ๋‹จ๊ณ„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ { #migrate-in-steps } + +/// tip | ํŒ + +๋จผ์ € `bump-pydantic`๋กœ ์‹œ๋„ํ•ด ๋ณด์„ธ์š”. ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•˜๊ณ  ์ž˜ ๋™์ž‘ํ•œ๋‹ค๋ฉด, ํ•œ ๋ฒˆ์˜ ๋ช…๋ น์œผ๋กœ ๋์ž…๋‹ˆ๋‹ค. โœจ + +/// + +`bump-pydantic`๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋งž์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2 ๋ชจ๋ธ์„ ๋ชจ๋‘ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด Pydantic v2๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋จผ์ € Pydantic์„ ์ตœ์‹  v2๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , ๋ชจ๋“  ๋ชจ๋ธ์˜ import๋ฅผ `pydantic.v1`์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ Pydantic v1์—์„œ v2๋กœ ๋ชจ๋ธ์„ ๊ทธ๋ฃน ๋‹จ์œ„๋กœ, ์ ์ง„์ ์ธ ๋‹จ๊ณ„๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹œ์ž‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿšถ diff --git a/docs/ko/docs/how-to/separate-openapi-schemas.md b/docs/ko/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..055429c26f --- /dev/null +++ b/docs/ko/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ๋Œ€ํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๋ถ„๋ฆฌํ• ์ง€ ์—ฌ๋ถ€ { #separate-openapi-schemas-for-input-and-output-or-not } + +**Pydantic v2**๊ฐ€ ๋ฆด๋ฆฌ์Šค๋œ ์ดํ›„, ์ƒ์„ฑ๋˜๋Š” OpenAPI๋Š” ์ด์ „๋ณด๋‹ค ์กฐ๊ธˆ ๋” ์ •ํ™•ํ•˜๊ณ  **์˜ฌ๋ฐ”๋ฅด๊ฒŒ** ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ๐Ÿ˜Ž + +์‹ค์ œ๋กœ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š”, ๊ฐ™์€ Pydantic ๋ชจ๋ธ์— ๋Œ€ํ•ด OpenAPI ์•ˆ์— **๋‘ ๊ฐœ์˜ JSON Schema**๊ฐ€ ์ƒ๊ธฐ๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. **๊ธฐ๋ณธ๊ฐ’(default value)**์ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ, ์ž…๋ ฅ์šฉ๊ณผ ์ถœ๋ ฅ์šฉ์œผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค. + +์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์„ ์œ„ํ•œ Pydantic ๋ชจ๋ธ { #pydantic-models-for-input-and-output } + +์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๋Š” Pydantic ๋ชจ๋ธ์ด ์žˆ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### ์ž…๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-input } + +์ด ๋ชจ๋ธ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...`description` ํ•„๋“œ๋Š” **ํ•„์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค**. `None`์ด๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +### ๋ฌธ์„œ์—์„œ์˜ ์ž…๋ ฅ ๋ชจ๋ธ { #input-model-in-docs } + +๋ฌธ์„œ์—์„œ `description` ํ•„๋“œ์— **๋นจ๊ฐ„ ๋ณ„ํ‘œ**๊ฐ€ ์—†๊ณ , ํ•„์ˆ˜๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +
+ +
+ +### ์ถœ๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-output } + +ํ•˜์ง€๋งŒ ๊ฐ™์€ ๋ชจ๋ธ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ถœ๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...`description`์— ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ ํ•„๋“œ์— ๋Œ€ํ•ด **์•„๋ฌด๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋”๋ผ๋„** ์—ฌ์ „ํžˆ ๊ทธ **๊ธฐ๋ณธ๊ฐ’**์ด ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +### ์ถœ๋ ฅ ์‘๋‹ต ๋ฐ์ดํ„ฐ์šฉ ๋ชจ๋ธ { #model-for-output-response-data } + +๋ฌธ์„œ์—์„œ ์ง์ ‘ ๋™์ž‘์‹œ์ผœ ์‘๋‹ต์„ ํ™•์ธํ•ด ๋ณด๋ฉด, ์ฝ”๋“œ๊ฐ€ `description` ํ•„๋“œ ์ค‘ ํ•˜๋‚˜์— ์•„๋ฌด๊ฒƒ๋„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๋”๋ผ๋„ JSON ์‘๋‹ต์—๋Š” ๊ธฐ๋ณธ๊ฐ’(`null`)์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค: + +
+ +
+ +์ด๋Š” ํ•ด๋‹น ํ•„๋“œ๊ฐ€ **ํ•ญ์ƒ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค๋Š” ๊ฒƒ**์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๊ทธ ๊ฐ’์ด ๋•Œ๋กœ๋Š” `None`(JSON์—์„œ๋Š” `null`)์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ฆ‰, API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๊ฐ’์ด ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์—†๊ณ , **ํ•„๋“œ๊ฐ€ ํ•ญ์ƒ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ธฐ๋ณธ๊ฐ’ `None`์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. + +์ด๋ฅผ OpenAPI์—์„œ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€, ๊ทธ ํ•„๋“œ๋ฅผ **required**๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ญ์ƒ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +์ด ๋•Œ๋ฌธ์—, ํ•˜๋‚˜์˜ ๋ชจ๋ธ์ด๋ผ๋„ **์ž…๋ ฅ์šฉ์ธ์ง€ ์ถœ๋ ฅ์šฉ์ธ์ง€**์— ๋”ฐ๋ผ JSON Schema๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +* **์ž…๋ ฅ**์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜** +* **์ถœ๋ ฅ**์—์„œ๋Š” **ํ•„์ˆ˜์ž„** (๊ทธ๋ฆฌ๊ณ  ๊ฐ’์€ `None`์ผ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, JSON ์šฉ์–ด๋กœ๋Š” `null`) + +### ๋ฌธ์„œ์—์„œ์˜ ์ถœ๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-output-in-docs } + +๋ฌธ์„œ์—์„œ ์ถœ๋ ฅ ๋ชจ๋ธ์„ ํ™•์ธํ•ด ๋ณด๋ฉด, `name`๊ณผ `description` **๋‘˜ ๋‹ค** **๋นจ๊ฐ„ ๋ณ„ํ‘œ**๋กœ **ํ•„์ˆ˜**๋กœ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค: + +
+ +
+ +### ๋ฌธ์„œ์—์„œ์˜ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋ธ { #model-for-input-and-output-in-docs } + +๋˜ OpenAPI์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  Schemas(JSON Schemas)๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด, `Item-Input` ํ•˜๋‚˜์™€ `Item-Output` ํ•˜๋‚˜, ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`Item-Input`์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉฐ**, ๋นจ๊ฐ„ ๋ณ„ํ‘œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `Item-Output`์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜์ด๋ฉฐ**, ๋นจ๊ฐ„ ๋ณ„ํ‘œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +
+ +
+ +**Pydantic v2**์˜ ์ด ๊ธฐ๋Šฅ ๋•๋ถ„์— API ๋ฌธ์„œ๋Š” ๋” **์ •๋ฐ€**ํ•ด์ง€๊ณ , ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ์™€ SDK๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ๋“ค๋„ ๋” ์ •๋ฐ€ํ•ด์ ธ์„œ ๋” ๋‚˜์€ **developer experience**์™€ ์ผ๊ด€์„ฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰ + +## ์Šคํ‚ค๋งˆ๋ฅผ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๊ธฐ { #do-not-separate-schemas } + +์ด์ œ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” **์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ๋Œ€ํ•ด ๊ฐ™์€ ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉ**ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๊ฒฝ์šฐ๋Š”, ์ด๋ฏธ ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ/SDK๊ฐ€ ์žˆ๊ณ , ์•„์ง์€ ๊ทธ ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ/SDK๋“ค์„ ์ „๋ถ€ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์–ธ์  ๊ฐ€๋Š” ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์ง€๋งŒ, ์ง€๊ธˆ ๋‹น์žฅ์€ ์•„๋‹ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š”, **FastAPI**์—์„œ `separate_input_output_schemas=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ด ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +`separate_input_output_schemas` ์ง€์›์€ FastAPI `0.102.0`์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### ๋ฌธ์„œ์—์„œ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋ธ์— ๊ฐ™์€ ์Šคํ‚ค๋งˆ ์‚ฌ์šฉ { #same-schema-for-input-and-output-models-in-docs } + +์ด์ œ ๋ชจ๋ธ์— ๋Œ€ํ•ด ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋‘์— ์‚ฌ์šฉ๋˜๋Š” ๋‹จ์ผ ์Šคํ‚ค๋งˆ(์˜ค์ง `Item`๋งŒ)๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, `description`์€ **ํ•„์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒƒ**์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: + +
+ +
diff --git a/docs/ko/docs/how-to/testing-database.md b/docs/ko/docs/how-to/testing-database.md new file mode 100644 index 0000000000..2d7798d707 --- /dev/null +++ b/docs/ko/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #testing-a-database } + +๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, SQL, SQLModel์— ๋Œ€ํ•ด์„œ๋Š” SQLModel ๋ฌธ์„œ์—์„œ ํ•™์Šตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ + +FastAPI์—์„œ SQLModel์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ฏธ๋‹ˆ ํŠœํ† ๋ฆฌ์–ผ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ + +ํ•ด๋‹น ํŠœํ† ๋ฆฌ์–ผ์—๋Š” SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ์„น์…˜๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..cfc3900d4c --- /dev/null +++ b/docs/ko/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# ๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ์—ฌ๋Ÿฌ ํŒŒ์ผ { #bigger-applications-multiple-files } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ์›น API๋ฅผ ๋งŒ๋“ค ๋•Œ, ๋ชจ๋“  ๊ฒƒ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ญ…๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ๋ชจ๋“  ์œ ์—ฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์กฐํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํŽธ๋ฆฌํ•œ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +Flask๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์…จ๋‹ค๋ฉด, ์ด๋Š” Flask์˜ Blueprints์— ํ•ด๋‹นํ•˜๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. + +/// + +## ์˜ˆ์‹œ ํŒŒ์ผ ๊ตฌ์กฐ { #an-example-file-structure } + +๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | ํŒ + +`__init__.py` ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค: ๊ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋˜๋Š” ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํ•˜๋‚˜์”ฉ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ํŒŒ์ผ๋“ค์ด ํ•œ ํŒŒ์ผ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ํŒŒ์ผ๋กœ importํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `app/main.py`์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ค„์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +``` +from app.routers import items +``` + +/// + +* `app` ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋น„์–ด ์žˆ๋Š” ํŒŒ์ผ `app/__init__.py`๊ฐ€ ์žˆ์–ด "Python package"(โ€œPython modulesโ€์˜ ๋ชจ์Œ)์ธ `app`์ด ๋ฉ๋‹ˆ๋‹ค. +* `app/main.py` ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. Python package(`__init__.py` ํŒŒ์ผ์ด ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ) ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ, ์ด package์˜ "module"์ž…๋‹ˆ๋‹ค: `app.main`. +* `app/dependencies.py` ํŒŒ์ผ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `app/main.py`์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ "module"์ž…๋‹ˆ๋‹ค: `app.dependencies`. +* `app/routers/` ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์žˆ๊ณ , ์—ฌ๊ธฐ์— ๋˜ `__init__.py` ํŒŒ์ผ์ด ์žˆ์œผ๋ฏ€๋กœ "Python subpackage"์ž…๋‹ˆ๋‹ค: `app.routers`. +* `app/routers/items.py` ํŒŒ์ผ์€ `app/routers/` package ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ, submodule์ž…๋‹ˆ๋‹ค: `app.routers.items`. +* `app/routers/users.py`๋„ ๋™์ผํ•˜๊ฒŒ ๋˜ ๋‹ค๋ฅธ submodule์ž…๋‹ˆ๋‹ค: `app.routers.users`. +* `app/internal/` ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋„ ์žˆ๊ณ  ์—ฌ๊ธฐ์— `__init__.py`๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋˜ ๋‹ค๋ฅธ "Python subpackage"์ž…๋‹ˆ๋‹ค: `app.internal`. +* ๊ทธ๋ฆฌ๊ณ  `app/internal/admin.py` ํŒŒ์ผ์€ ๋˜ ๋‹ค๋ฅธ submodule์ž…๋‹ˆ๋‹ค: `app.internal.admin`. + + + +๊ฐ™์€ ํŒŒ์ผ ๊ตฌ์กฐ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +```bash +. +โ”œโ”€โ”€ app # "app" is a Python package +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # this file makes "app" a "Python package" +โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module, e.g. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module, e.g. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" is a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # makes "routers" a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule, e.g. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule, e.g. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" is a "Python subpackage" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # makes "internal" a "Python subpackage" +โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule, e.g. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +์‚ฌ์šฉ์ž๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ์ „์šฉ ํŒŒ์ผ์ด `/app/routers/users.py`์˜ submodule์ด๋ผ๊ณ  ํ•ด๋ด…์‹œ๋‹ค. + +์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž์™€ ๊ด€๋ จ๋œ *path operations*๋ฅผ ๋‚˜๋จธ์ง€ ์ฝ”๋“œ์™€ ๋ถ„๋ฆฌํ•ด ๋‘๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ ๊ฐ™์€ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/์›น API์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค(๊ฐ™์€ "Python Package"์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค). + +`APIRouter`๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๋‹น ๋ชจ๋“ˆ์˜ *path operations*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### `APIRouter` importํ•˜๊ธฐ { #import-apirouter } + +`FastAPI` ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ importํ•˜๊ณ  "instance"๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### `APIRouter`๋กœ *path operations* ๋งŒ๋“ค๊ธฐ { #path-operations-with-apirouter } + +๊ทธ ๋‹ค์Œ ์ด๋ฅผ ์‚ฌ์šฉํ•ด *path operations*๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + +`FastAPI` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +`APIRouter`๋Š” "๋ฏธ๋‹ˆ `FastAPI`" ํด๋ž˜์Šค๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋™์ผํ•œ ์˜ต์…˜๋“ค์ด ๋ชจ๋‘ ์ง€์›๋ฉ๋‹ˆ๋‹ค. + +๋™์ผํ•œ `parameters`, `responses`, `dependencies`, `tags` ๋“ฑ๋“ฑ. + +/// tip | ํŒ + +์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋ณ€์ˆ˜ ์ด๋ฆ„์ด `router`์ด์ง€๋งŒ, ์›ํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ ์ง€์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +/// + +์ด์ œ ์ด `APIRouter`๋ฅผ ๋ฉ”์ธ `FastAPI` ์•ฑ์— ํฌํ•จ(include)ํ•  ๊ฒƒ์ด์ง€๋งŒ, ๋จผ์ € dependencies์™€ ๋‹ค๋ฅธ `APIRouter` ํ•˜๋‚˜๋ฅผ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## Dependencies { #dependencies } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” dependencies๊ฐ€ ์ผ๋ถ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ ์ด๋ฅผ ๋ณ„๋„์˜ `dependencies` ๋ชจ๋“ˆ(`app/dependencies.py`)์— ๋‘ก๋‹ˆ๋‹ค. + +์ด์ œ ๊ฐ„๋‹จํ•œ dependency๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ `X-Token` ํ—ค๋”๋ฅผ ์ฝ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | ํŒ + +์ด ์˜ˆ์‹œ๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ž„์˜๋กœ ๋งŒ๋“  ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์‹ค์ œ ์ƒํ™ฉ์—์„œ๋Š” ํ†ตํ•ฉ๋œ [Security ์œ ํ‹ธ๋ฆฌํ‹ฐ](security/index.md){.internal-link target=_blank}๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## `APIRouter`๊ฐ€ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ๋ชจ๋“ˆ { #another-module-with-apirouter } + +์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ "items"๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ „์šฉ endpoint๋“ค๋„ `app/routers/items.py` ๋ชจ๋“ˆ์— ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” ๋‹ค์Œ์— ๋Œ€ํ•œ *path operations*๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: + +* `/items/` +* `/items/{item_id}` + +๊ตฌ์กฐ๋Š” `app/routers/users.py`์™€ ์™„์ „ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์กฐ๊ธˆ ๋” ๋˜‘๋˜‘ํ•˜๊ฒŒ, ์ฝ”๋“œ๋ฅผ ์•ฝ๊ฐ„ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. + +์ด ๋ชจ๋“ˆ์˜ ๋ชจ๋“  *path operations*์—๋Š” ๋‹ค์Œ์ด ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค: + +* ๊ฒฝ๋กœ `prefix`: `/items`. +* `tags`: (ํƒœ๊ทธ ํ•˜๋‚˜: `items`). +* ์ถ”๊ฐ€ `responses`. +* `dependencies`: ๋ชจ๋‘ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  `X-Token` dependency๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ๊ฐ *path operation*๋งˆ๋‹ค ๋งค๋ฒˆ ๋ชจ๋‘ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹ , `APIRouter`์— ํ•œ ๋ฒˆ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +๊ฐ *path operation*์˜ ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ `/`๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๋ฏ€๋กœ: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...prefix์—๋Š” ๋งˆ์ง€๋ง‰ `/`๊ฐ€ ํฌํ•จ๋˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ prefix๋Š” `/items`์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์ด router์— ํฌํ•จ๋œ ๋ชจ๋“  *path operations*์— ์ ์šฉ๋  `tags` ๋ชฉ๋ก๊ณผ ์ถ”๊ฐ€ `responses`๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  router์˜ ๋ชจ๋“  *path operations*์— ์ถ”๊ฐ€๋  `dependencies` ๋ชฉ๋ก๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ๊ฒฝ๋กœ๋“ค๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์‹คํ–‰/ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +[*path operation decorator์˜ dependencies*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, *path operation function*์— ์–ด๋–ค ๊ฐ’๋„ ์ „๋‹ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +/// + +์ตœ์ข…์ ์œผ๋กœ item ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* `/items/` +* `/items/{item_id}` + +...์˜๋„ํ•œ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. + +* ๋‹จ์ผ ๋ฌธ์ž์—ด `"items"`๋ฅผ ํฌํ•จํ•˜๋Š” ํƒœ๊ทธ ๋ชฉ๋ก์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + * ์ด "tags"๋Š” ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ(OpenAPI ์‚ฌ์šฉ)์— ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. +* ๋ชจ๋‘ ๋ฏธ๋ฆฌ ์ •์˜๋œ `responses`๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +* ์ด ๋ชจ๋“  *path operations*๋Š” ์‹คํ–‰๋˜๊ธฐ ์ „์— `dependencies` ๋ชฉ๋ก์ด ํ‰๊ฐ€/์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. + * ํŠน์ • *path operation*์— dependencies๋ฅผ ์ถ”๊ฐ€๋กœ ์„ ์–ธํ•˜๋ฉด **๊ทธ๊ฒƒ๋“ค๋„ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค**. + * router dependencies๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๊ณ , ๊ทธ ๋‹ค์Œ์— [decorator์˜ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜ ํŒŒ๋ผ๋ฏธํ„ฐ dependencies๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. + * [`scopes`๊ฐ€ ์žˆ๋Š” `Security` dependencies](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +`APIRouter`์— `dependencies`๋ฅผ ๋‘๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด ์ „์ฒด *path operations* ๊ทธ๋ฃน์— ์ธ์ฆ์„ ์š”๊ตฌํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ์— ๊ฐœ๋ณ„์ ์œผ๋กœ dependencies๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. + +/// + +/// check | ํ™•์ธ + +`prefix`, `tags`, `responses`, `dependencies` ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” (๋‹ค๋ฅธ ๋งŽ์€ ๊ฒฝ์šฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ) ์ฝ”๋“œ ์ค‘๋ณต์„ ํ”ผํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” **FastAPI**์˜ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. + +/// + +### dependencies importํ•˜๊ธฐ { #import-the-dependencies } + +์ด ์ฝ”๋“œ๋Š” ๋ชจ๋“ˆ `app.routers.items`, ํŒŒ์ผ `app/routers/items.py`์— ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  dependency ํ•จ์ˆ˜๋Š” ๋ชจ๋“ˆ `app.dependencies`, ํŒŒ์ผ `app/dependencies.py`์—์„œ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ž˜์„œ dependencies์— ๋Œ€ํ•ด `..`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒ๋Œ€ import๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### ์ƒ๋Œ€ import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-relative-imports-work } + +/// tip | ํŒ + +import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์„ ์™„๋ฒฝํžˆ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, ์•„๋ž˜ ๋‹ค์Œ ์„น์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”. + +/// + +๋‹ค์Œ๊ณผ ๊ฐ™์ด ์  ํ•˜๋‚˜ `.`๋ฅผ ์“ฐ๋ฉด: + +```Python +from .dependencies import get_token_header +``` + +์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ... +* `dependencies` ๋ชจ๋“ˆ(๊ฐ€์ƒ์˜ ํŒŒ์ผ `app/routers/dependencies.py`)์„ ์ฐพ๊ณ ... +* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๊ทธ ํŒŒ์ผ์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. dependencies๋Š” `app/dependencies.py` ํŒŒ์ผ์— ์žˆ์Šต๋‹ˆ๋‹ค. + +์šฐ๋ฆฌ ์•ฑ/ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ๋‹ค์‹œ ๋– ์˜ฌ๋ ค ๋ณด์„ธ์š”: + + + +--- + +๋‹ค์Œ์ฒ˜๋Ÿผ ์  ๋‘ ๊ฐœ `..`๋ฅผ ์“ฐ๋ฉด: + +```Python +from ..dependencies import get_token_header +``` + +์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ... +* ์ƒ์œ„ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)๋กœ ์˜ฌ๋ผ๊ฐ€๊ณ ... +* ๊ทธ ์•ˆ์—์„œ `dependencies` ๋ชจ๋“ˆ(ํŒŒ์ผ `app/dependencies.py`)์„ ์ฐพ๊ณ ... +* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰ + +--- + +๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์  ์„ธ ๊ฐœ `...`๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด: + +```Python +from ...dependencies import get_token_header +``` + +์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ... +* ์ƒ์œ„ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)๋กœ ์˜ฌ๋ผ๊ฐ€๊ณ ... +* ๊ทธ package์˜ ์ƒ์œ„๋กœ ๋˜ ์˜ฌ๋ผ๊ฐ€๋Š”๋ฐ(์ƒ์œ„ package๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค, `app`์ด ์ตœ์ƒ์œ„์ž…๋‹ˆ๋‹ค ๐Ÿ˜ฑ)... +* ๊ทธ ์•ˆ์—์„œ `dependencies` ๋ชจ๋“ˆ(ํŒŒ์ผ `app/dependencies.py`)์„ ์ฐพ๊ณ ... +* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” `app/` ์œ„์ชฝ์˜ ์–ด๋–ค package(์ž์‹ ์˜ `__init__.py` ํŒŒ์ผ ๋“ฑ์„ ๊ฐ€์ง„)์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๊ทธ๋Ÿฐ ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๐Ÿšจ + +์ด์ œ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•˜์œผ๋‹ˆ, ์•ฑ์ด ์–ผ๋งˆ๋‚˜ ๋ณต์žกํ•˜๋“  ์ƒ๋Œ€ import๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ + +### ์ปค์Šคํ…€ `tags`, `responses`, `dependencies` ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-some-custom-tags-responses-and-dependencies } + +`APIRouter`์— ์ด๋ฏธ prefix `/items`์™€ `tags=["items"]`๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ *path operation*์— ์ด๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ํŠน์ • *path operation*์—๋งŒ ์ ์šฉ๋  _์ถ”๊ฐ€_ `tags`๋ฅผ ๋”ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ทธ *path operation* ์ „์šฉ์˜ ์ถ”๊ฐ€ `responses`๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | ํŒ + +์ด ๋งˆ์ง€๋ง‰ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋Š” `["items", "custom"]` ํƒœ๊ทธ ์กฐํ•ฉ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋ฌธ์„œ์—๋Š” `404`์šฉ ์‘๋‹ต๊ณผ `403`์šฉ ์‘๋‹ต, ๋‘ ๊ฐ€์ง€ ๋ชจ๋‘๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. + +/// + +## ๋ฉ”์ธ `FastAPI` { #the-main-fastapi } + +์ด์ œ `app/main.py` ๋ชจ๋“ˆ์„ ๋ด…์‹œ๋‹ค. + +์—ฌ๊ธฐ์—์„œ `FastAPI` ํด๋ž˜์Šค๋ฅผ importํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์ด ํŒŒ์ผ์€ ๋ชจ๋“  ๊ฒƒ์„ ํ•˜๋‚˜๋กœ ์—ฎ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฉ”์ธ ํŒŒ์ผ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๋กœ์ง์ด ๊ฐ์ž์˜ ํŠน์ • ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ๋ฉ”์ธ ํŒŒ์ผ์€ ๊ฝค ๋‹จ์ˆœํ•ด์ง‘๋‹ˆ๋‹ค. + +### `FastAPI` importํ•˜๊ธฐ { #import-fastapi } + +ํ‰์†Œ์ฒ˜๋Ÿผ `FastAPI` ํด๋ž˜์Šค๋ฅผ importํ•˜๊ณ  ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +๋˜ํ•œ ๊ฐ `APIRouter`์˜ dependencies์™€ ๊ฒฐํ•ฉ๋  [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}๋„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} + +### `APIRouter` importํ•˜๊ธฐ { #import-the-apirouter } + +์ด์ œ `APIRouter`๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ submodule๋“ค์„ importํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} + +`app/routers/users.py`์™€ `app/routers/items.py` ํŒŒ์ผ์€ ๊ฐ™์€ Python package `app`์— ์†ํ•œ submodule๋“ค์ด๋ฏ€๋กœ, ์  ํ•˜๋‚˜ `.`๋ฅผ ์‚ฌ์šฉํ•ด "์ƒ๋Œ€ import"๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-the-importing-works } + +๋‹ค์Œ ๊ตฌ๋ฌธ์€: + +```Python +from .routers import items, users +``` + +์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + +* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/main.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ... +* subpackage `routers`(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)๋ฅผ ์ฐพ๊ณ ... +* ๊ทธ ์•ˆ์—์„œ submodule `items`(ํŒŒ์ผ `app/routers/items.py`)์™€ `users`(ํŒŒ์ผ `app/routers/users.py`)๋ฅผ importํ•ฉ๋‹ˆ๋‹ค... + +`items` ๋ชจ๋“ˆ์—๋Š” `router` ๋ณ€์ˆ˜(`items.router`)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” `app/routers/items.py` ํŒŒ์ผ์—์„œ ๋งŒ๋“  ๊ฒƒ๊ณผ ๋™์ผํ•˜๋ฉฐ `APIRouter` ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  `users` ๋ชจ๋“ˆ๋„ ๊ฐ™์€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. + +๋‹ค์Œ์ฒ˜๋Ÿผ importํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +from app.routers import items, users +``` + +/// info | ์ •๋ณด + +์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „์€ "์ƒ๋Œ€ import"์ž…๋‹ˆ๋‹ค: + +```Python +from .routers import items, users +``` + +๋‘ ๋ฒˆ์งธ ๋ฒ„์ „์€ "์ ˆ๋Œ€ import"์ž…๋‹ˆ๋‹ค: + +```Python +from app.routers import items, users +``` + +Python Packages์™€ Modules์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๋ ค๋ฉด Modules์— ๋Œ€ํ•œ Python ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”. + +/// + +### ์ด๋ฆ„ ์ถฉ๋Œ ํ”ผํ•˜๊ธฐ { #avoid-name-collisions } + +submodule `items`๋ฅผ ์ง์ ‘ importํ•˜๊ณ , ๊ทธ ์•ˆ์˜ `router` ๋ณ€์ˆ˜๋งŒ importํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. + +์ด๋Š” submodule `users`์—๋„ `router`๋ผ๋Š” ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๋งŒ์•ฝ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ˆœ์„œ๋Œ€๋กœ importํ–ˆ๋‹ค๋ฉด: + +```Python +from .routers.items import router +from .routers.users import router +``` + +`users`์˜ `router`๊ฐ€ `items`์˜ `router`๋ฅผ ๋ฎ์–ด์จ์„œ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ๊ฐ™์€ ํŒŒ์ผ์—์„œ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก submodule๋“ค์„ ์ง์ ‘ importํ•ฉ๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} + +### `users`์™€ `items`์šฉ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-the-apirouters-for-users-and-items } + +์ด์ œ submodule `users`์™€ `items`์˜ `router`๋ฅผ ํฌํ•จํ•ด ๋ด…์‹œ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} + +/// info | ์ •๋ณด + +`users.router`๋Š” `app/routers/users.py` ํŒŒ์ผ ์•ˆ์˜ `APIRouter`๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +`items.router`๋Š” `app/routers/items.py` ํŒŒ์ผ ์•ˆ์˜ `APIRouter`๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +`app.include_router()`๋กœ ๊ฐ `APIRouter`๋ฅผ ๋ฉ”์ธ `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ router์˜ ๋ชจ๋“  route๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +/// note Technical Details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +๋‚ด๋ถ€์ ์œผ๋กœ๋Š” `APIRouter`์— ์„ ์–ธ๋œ ๊ฐ *path operation*๋งˆ๋‹ค *path operation*์„ ์‹ค์ œ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +์ฆ‰, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋™์ผํ•œ ํ•˜๋‚˜์˜ ์•ฑ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// check | ํ™•์ธ + +router๋ฅผ ํฌํ•จ(include)ํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. + +์ด ์ž‘์—…์€ ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„์ด๋ฉฐ ์‹œ์ž‘ ์‹œ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. โšก + +/// + +### ์ปค์Šคํ…€ `prefix`, `tags`, `responses`, `dependencies`๋กœ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +์ด์ œ ์กฐ์ง์—์„œ `app/internal/admin.py` ํŒŒ์ผ์„ ๋ฐ›์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. + +์—ฌ๊ธฐ์—๋Š” ์กฐ์ง์—์„œ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ ๊ฐ„์— ๊ณต์œ ํ•˜๋Š” ๊ด€๋ฆฌ์ž์šฉ *path operations*๊ฐ€ ์žˆ๋Š” `APIRouter`๊ฐ€ ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์™€ ๊ณต์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์–ด `prefix`, `dependencies`, `tags` ๋“ฑ์„ `APIRouter`์— ์ง์ ‘ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +ํ•˜์ง€๋งŒ `APIRouter`๋ฅผ ํฌํ•จํ•  ๋•Œ ์ปค์Šคํ…€ `prefix`๋ฅผ ์ง€์ •ํ•ด ๋ชจ๋“  *path operations*๊ฐ€ `/admin`์œผ๋กœ ์‹œ์ž‘ํ•˜๊ฒŒ ํ•˜๊ณ , ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ด๋ฏธ ๊ฐ€์ง„ `dependencies`๋กœ ๋ณดํ˜ธํ•˜๊ณ , `tags`์™€ `responses`๋„ ํฌํ•จํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. + +์›๋ž˜ `APIRouter`๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ `app.include_router()`์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์„œ ์ด๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›๋ž˜ `APIRouter`๋Š” ์ˆ˜์ •๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ๋™์ผํ•œ `app/internal/admin.py` ํŒŒ์ผ์„ ๊ณ„์† ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ ์•ฑ์—์„œ `admin` ๋ชจ๋“ˆ์˜ ๊ฐ *path operations*๋Š” ๋‹ค์Œ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: + +* prefix `/admin`. +* tag `admin`. +* dependency `get_token_header`. +* ์‘๋‹ต `418`. ๐Ÿต + +ํ•˜์ง€๋งŒ ์ด๋Š” ์šฐ๋ฆฌ ์•ฑ์—์„œ ๊ทธ `APIRouter`์—๋งŒ ์˜ํ–ฅ์„ ์ฃผ๋ฉฐ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋“ค์€ ๊ฐ™์€ `APIRouter`๋ฅผ ๋‹ค๋ฅธ ์ธ์ฆ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +### *path operation* ํฌํ•จํ•˜๊ธฐ { #include-a-path-operation } + +*path operations*๋ฅผ `FastAPI` ์•ฑ์— ์ง์ ‘ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๊ธฐ์„œ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด... ๊ทธ๋ƒฅ ํ•ด๋ด…๋‹ˆ๋‹ค ๐Ÿคท: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} + +๊ทธ๋ฆฌ๊ณ  `app.include_router()`๋กœ ์ถ”๊ฐ€ํ•œ ๋‹ค๋ฅธ ๋ชจ๋“  *path operations*์™€ ํ•จ๊ป˜ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +**์ฐธ๊ณ **: ์ด๋Š” ๋งค์šฐ ๊ธฐ์ˆ ์ ์ธ ์„ธ๋ถ€์‚ฌํ•ญ์ด๋ผ ์•„๋งˆ **๊ทธ๋ƒฅ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค**. + +--- + +`APIRouter`๋Š” "mount"๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ฉฐ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„๊ณผ ๊ฒฉ๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ด๋Š” OpenAPI ์Šคํ‚ค๋งˆ์™€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ๊ทธ๋“ค์˜ *path operations*๋ฅผ ํฌํ•จ์‹œํ‚ค๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +๋‚˜๋จธ์ง€์™€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฒฉ๋ฆฌํ•ด "mount"ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, *path operations*๋Š” ์ง์ ‘ ํฌํ•จ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "clone"(์žฌ์ƒ์„ฑ)๋ฉ๋‹ˆ๋‹ค. + +/// + +## ์ž๋™ API ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #check-the-automatic-api-docs } + +์ด์ œ ์•ฑ์„ ์‹คํ–‰ํ•˜์„ธ์š”: + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +๊ทธ๋ฆฌ๊ณ  http://127.0.0.1:8000/docs์—์„œ ๋ฌธ์„œ๋ฅผ ์—ฌ์„ธ์š”. + +์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ(๋ฐ prefix)์™€ ์˜ฌ๋ฐ”๋ฅธ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด, ๋ชจ๋“  submodule์˜ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•œ ์ž๋™ API ๋ฌธ์„œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +## ๊ฐ™์€ router๋ฅผ ๋‹ค๋ฅธ `prefix`๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จํ•˜๊ธฐ { #include-the-same-router-multiple-times-with-different-prefix } + +`.include_router()`๋ฅผ ์‚ฌ์šฉํ•ด *๊ฐ™์€* router๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ prefix๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด `/api/v1`๊ณผ `/api/latest`์ฒ˜๋Ÿผ ์„œ๋กœ ๋‹ค๋ฅธ prefix๋กœ ๋™์ผํ•œ API๋ฅผ ๋…ธ์ถœํ•  ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ๊ณ ๊ธ‰ ์‚ฌ์šฉ ๋ฐฉ์‹์ด๋ผ ์‹ค์ œ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ํ•„์š”ํ•  ๋•Œ๋ฅผ ์œ„ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. + +## `APIRouter`์— ๋‹ค๋ฅธ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-an-apirouter-in-another } + +`APIRouter`๋ฅผ `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ด `APIRouter`๋ฅผ ๋‹ค๋ฅธ `APIRouter`์— ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +router.include_router(other_router) +``` + +`FastAPI` ์•ฑ์— `router`๋ฅผ ํฌํ•จํ•˜๊ธฐ ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ๋ž˜์•ผ `other_router`์˜ *path operations*๋„ ํ•จ๊ป˜ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/body-updates.md b/docs/ko/docs/tutorial/body-updates.md new file mode 100644 index 0000000000..3719e1ffab --- /dev/null +++ b/docs/ko/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Body - ์—…๋ฐ์ดํŠธ { #body-updates } + +## `PUT`์œผ๋กœ ๊ต์ฒด ์—…๋ฐ์ดํŠธํ•˜๊ธฐ { #update-replacing-with-put } + +ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด HTTP `PUT` ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`jsonable_encoder`๋ฅผ ์‚ฌ์šฉํ•ด ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ ์‹œ). ์˜ˆ๋ฅผ ๋“ค์–ด `datetime`์„ `str`๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT`์€ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ **๋Œ€์ฒด**ํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +### ๋Œ€์ฒด ์‹œ ์ฃผ์˜์‚ฌํ•ญ { #warning-about-replacing } + +์ฆ‰, `PUT`์œผ๋กœ ํ•ญ๋ชฉ `bar`๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ body๋ฅผ ๋ณด๋‚ธ๋‹ค๋ฉด: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +์ด๋ฏธ ์ €์žฅ๋œ ์†์„ฑ `"tax": 20.2`๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ž…๋ ฅ ๋ชจ๋ธ์€ `"tax": 10.5`๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋Š” ๊ทธ โ€œ์ƒˆ๋กœ์šดโ€ `tax` ๊ฐ’ `10.5`๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. + +## `PATCH`๋กœ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ { #partial-updates-with-patch } + +HTTP `PATCH` ์ž‘์—…์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ *๋ถ€๋ถ„์ ์œผ๋กœ* ์—…๋ฐ์ดํŠธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” ์—…๋ฐ์ดํŠธํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋ณด๋‚ด๊ณ , ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ ๋‘๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +/// note | ์ฐธ๊ณ  + +`PATCH`๋Š” `PUT`๋ณด๋‹ค ๋œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ๋œ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ํŒ€์ด ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ์—๋„ `PUT`๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์—ฌ๋Ÿฌ๋ถ„์€ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ **์ž์œ ๋กญ๊ฒŒ** ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ์–ด๋–ค ์ œํ•œ๋„ ๊ฐ•์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +๋‹ค๋งŒ ์ด ๊ฐ€์ด๋“œ๋Š” ์˜๋„๋œ ์‚ฌ์šฉ ๋ฐฉ์‹์ด ๋Œ€๋žต ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. + +/// + +### Pydantic์˜ `exclude_unset` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ { #using-pydantics-exclude-unset-parameter } + +๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด Pydantic ๋ชจ๋ธ์˜ `.model_dump()`์—์„œ `exclude_unset` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. + +์˜ˆ: `item.model_dump(exclude_unset=True)`. + +์ด๋Š” `item` ๋ชจ๋ธ์„ ๋งŒ๋“ค ๋•Œ ์‹ค์ œ๋กœ ์„ค์ •๋œ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จํ•˜๋Š” `dict`๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ธฐ๋ณธ๊ฐ’์€ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ ๋‹ค์Œ ์ด๋ฅผ ์‚ฌ์šฉํ•ด (์š”์ฒญ์—์„œ ์ „์†ก๋˜์–ด) ์„ค์ •๋œ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จํ•˜๊ณ  ๊ธฐ๋ณธ๊ฐ’์€ ์ƒ๋žตํ•œ `dict`๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Pydantic์˜ `update` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ { #using-pydantics-update-parameter } + +์ด์ œ `.model_copy()`๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ์กด ๋ชจ๋ธ์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ , ์—…๋ฐ์ดํŠธํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋Š” `dict`๋ฅผ `update` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ: `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ ์š”์•ฝ { #partial-updates-recap } + +์ •๋ฆฌํ•˜๋ฉด, ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค: + +* (์„ ํƒ ์‚ฌํ•ญ) `PUT` ๋Œ€์‹  `PATCH`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +* ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. +* ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ Pydantic ๋ชจ๋ธ์— ๋„ฃ์Šต๋‹ˆ๋‹ค. +* ์ž…๋ ฅ ๋ชจ๋ธ์—์„œ ๊ธฐ๋ณธ๊ฐ’์ด ์ œ์™ธ๋œ `dict`๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค(`exclude_unset` ์‚ฌ์šฉ). + * ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋ธ์˜ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ด๋ฏธ ์ €์žฅ๋œ ๊ฐ’์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ์„ค์ •ํ•œ ๊ฐ’๋งŒ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ์ €์žฅ๋œ ๋ชจ๋ธ์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ , ๋ฐ›์€ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋กœ ํ•ด๋‹น ์†์„ฑ๋“ค์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค(`update` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ). +* ๋ณต์‚ฌํ•œ ๋ชจ๋ธ์„ DB์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `jsonable_encoder` ์‚ฌ์šฉ). + * ์ด๋Š” ๋ชจ๋ธ์˜ `.model_dump()` ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, JSON์œผ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์œผ๋กœ ๊ฐ’์ด ํ™•์‹คํžˆ ๋ณ€ํ™˜๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `datetime` โ†’ `str`). +* ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. +* ์—…๋ฐ์ดํŠธ๋œ ๋ชจ๋ธ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | ํŒ + +๋™์ผํ•œ ๊ธฐ๋ฒ•์„ HTTP `PUT` ์ž‘์—…์—์„œ๋„ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์˜ ์˜ˆ์‹œ๋Š” ์ด๋Ÿฐ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ `PATCH`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// + +/// note | ์ฐธ๊ณ  + +์ž…๋ ฅ ๋ชจ๋ธ์€ ์—ฌ์ „ํžˆ ๊ฒ€์ฆ๋œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. + +๋”ฐ๋ผ์„œ ๋ชจ๋“  ์†์„ฑ์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด, ๋ชจ๋“  ์†์„ฑ์ด optional๋กœ ํ‘œ์‹œ๋œ(๊ธฐ๋ณธ๊ฐ’์„ ๊ฐ€์ง€๊ฑฐ๋‚˜ `None`์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๊ฐ€์ง€๋Š”) ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + +**์—…๋ฐ์ดํŠธ**๋ฅผ ์œ„ํ•œ โ€œ๋ชจ๋“  ๊ฐ’์ด optional์ธโ€ ๋ชจ๋ธ๊ณผ, **์ƒ์„ฑ**์„ ์œ„ํ•œ โ€œํ•„์ˆ˜ ๊ฐ’์ด ์žˆ๋Š”โ€ ๋ชจ๋ธ์„ ๊ตฌ๋ถ„ํ•˜๋ ค๋ฉด [์ถ”๊ฐ€ ๋ชจ๋ธ](extra-models.md){.internal-link target=_blank}์— ์„ค๋ช…๋œ ์•„์ด๋””์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// diff --git a/docs/ko/docs/tutorial/dependencies/sub-dependencies.md b/docs/ko/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000..d81ccf00d0 --- /dev/null +++ b/docs/ko/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# ํ•˜์œ„ ์˜์กด์„ฑ { #sub-dependencies } + +**ํ•˜์œ„ ์˜์กด์„ฑ**์„ ๊ฐ€์ง€๋Š” ์˜์กด์„ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•„์š”ํ•œ ๋งŒํผ **๊นŠ๊ฒŒ** ์ค‘์ฒฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ์ผ์€ **FastAPI**๊ฐ€ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +## ์ฒซ ๋ฒˆ์งธ ์˜์กด์„ฑ "dependable" { #first-dependency-dependable } + +๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒซ ๋ฒˆ์งธ ์˜์กด์„ฑ("dependable")์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +์ด ์˜์กด์„ฑ์€ ์„ ํƒ์  ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ `q`๋ฅผ `str`๋กœ ์„ ์–ธํ•˜๊ณ , ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +๋งค์šฐ ๋‹จ์ˆœํ•œ ์˜ˆ์‹œ(๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง„ ์•Š์Œ)์ด์ง€๋งŒ, ํ•˜์œ„ ์˜์กด์„ฑ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€์— ์ง‘์ค‘ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. + +## ๋‘ ๋ฒˆ์งธ ์˜์กด์„ฑ "dependable"๊ณผ "dependant" { #second-dependency-dependable-and-dependant } + +๊ทธ๋‹ค์Œ, ๋˜ ๋‹ค๋ฅธ ์˜์กด์„ฑ ํ•จ์ˆ˜("dependable")๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ•จ์ˆ˜๋Š” ๋™์‹œ์— ์ž๊ธฐ ์ž์‹ ์˜ ์˜์กด์„ฑ๋„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋ž˜์„œ "dependant"์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค): + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +์„ ์–ธ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: + +* ์ด ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ์˜์กด์„ฑ("dependable")์ด์ง€๋งŒ, ๋‹ค๋ฅธ ์˜์กด์„ฑ๋„ ํ•˜๋‚˜ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€์— "์˜์กด"ํ•ฉ๋‹ˆ๋‹ค). + * `query_extractor`์— ์˜์กดํ•˜๋ฉฐ, ๊ทธ ๋ฐ˜ํ™˜๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ `q`์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. +* ๋˜ํ•œ ์„ ํƒ์  `last_query` ์ฟ ํ‚ค๋ฅผ `str`๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. + * ์‚ฌ์šฉ์ž๊ฐ€ ์ฟผ๋ฆฌ `q`๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ด์ „์— ์ฟ ํ‚ค์— ์ €์žฅํ•ด ๋‘” ๋งˆ์ง€๋ง‰ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +## ์˜์กด์„ฑ ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-dependency } + +๊ทธ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// info | ์ •๋ณด + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ๋Š” `query_or_cookie_extractor`๋ผ๋Š” ์˜์กด์„ฑ ํ•˜๋‚˜๋งŒ ์„ ์–ธํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. + +ํ•˜์ง€๋งŒ **FastAPI**๋Š” `query_or_cookie_extractor`๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋™์•ˆ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด, ๋จผ์ € `query_extractor`๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## ๊ฐ™์€ ์˜์กด์„ฑ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-same-dependency-multiple-times } + +๊ฐ™์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด ์˜์กด์„ฑ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ ์–ธ๋˜๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์—ฌ๋Ÿฌ ์˜์กด์„ฑ์ด ๊ณตํ†ต ํ•˜์œ„ ์˜์กด์„ฑ์„ ๊ฐ–๋Š” ๊ฒฝ์šฐ), **FastAPI**๋Š” ๊ทธ ํ•˜์œ„ ์˜์กด์„ฑ์„ ์š”์ฒญ๋‹น ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ์š”์ฒญ์— ๋Œ€ํ•ด ๋™์ผํ•œ ์˜์กด์„ฑ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹ , ๋ฐ˜ํ™˜๊ฐ’์„ "cache"์— ์ €์žฅํ•˜๊ณ , ๊ทธ ์š”์ฒญ์—์„œ ํ•ด๋‹น ๊ฐ’์ด ํ•„์š”ํ•œ ๋ชจ๋“  "dependants"์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. + +๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ, ๊ฐ™์€ ์š”์ฒญ์—์„œ "cached" ๊ฐ’์„ ์“ฐ๋Š” ๋Œ€์‹  ๋งค ๋‹จ๊ณ„๋งˆ๋‹ค(์•„๋งˆ๋„ ์—ฌ๋Ÿฌ ๋ฒˆ) ์˜์กด์„ฑ์ด ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, `Depends`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ `use_cache=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.9+ ๋น„ Annotated + +/// tip | ํŒ + +๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด `Annotated` ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## ์ •๋ฆฌ { #recap } + +์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•œ ๊ทธ๋Ÿด๋“ฏํ•œ ์šฉ์–ด๋“ค์„ ์ œ์™ธํ•˜๋ฉด, **Dependency Injection** ์‹œ์Šคํ…œ์€ ๊ฝค ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. + +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์™€ ๊ฐ™์€ ํ˜•ํƒœ์˜ ํ•จ์ˆ˜๋“ค์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๋ฉฐ, ์ž„์˜๋กœ ๊นŠ๊ฒŒ ์ค‘์ฒฉ๋œ ์˜์กด์„ฑ "๊ทธ๋ž˜ํ”„"(ํŠธ๋ฆฌ)๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// tip | ํŒ + +์ด ๋‹จ์ˆœํ•œ ์˜ˆ์‹œ๋งŒ ๋ณด๋ฉด ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•ด ๋ณด์ด์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ **๋ณด์•ˆ**์— ๊ด€ํ•œ ์ฑ•ํ„ฐ์—์„œ ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์œ ์šฉํ•œ์ง€ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์•„๊ปด์ฃผ๋Š”์ง€๋„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// diff --git a/docs/ko/docs/tutorial/handling-errors.md b/docs/ko/docs/tutorial/handling-errors.md new file mode 100644 index 0000000000..7cc37e80c0 --- /dev/null +++ b/docs/ko/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ { #handling-errors } + +API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜๋ฅผ ์•Œ๋ ค์•ผ ํ•˜๋Š” ์ƒํ™ฉ์€ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ํด๋ผ์ด์–ธํŠธ๋Š” ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์žˆ๋Š” ๋ธŒ๋ผ์šฐ์ €์ผ ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ๊ณ , IoT ์žฅ์น˜์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํด๋ผ์ด์–ธํŠธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ์•Œ๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: + +* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ถฉ๋ถ„ํ•œ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. +* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. +* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•œ ํ•ญ๋ชฉ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +* ๋“ฑ๋“ฑ. + +์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ณดํ†ต **400**๋ฒˆ๋Œ€(400์—์„œ 499) ๋ฒ”์œ„์˜ **HTTP ์ƒํƒœ ์ฝ”๋“œ**๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” 200๋ฒˆ๋Œ€ HTTP ์ƒํƒœ ์ฝ”๋“œ(200์—์„œ 299)์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. "200" ์ƒํƒœ ์ฝ”๋“œ๋Š” ์–ด๋–ค ํ˜•ํƒœ๋กœ๋“  ์š”์ฒญ์ด "์„ฑ๊ณต"ํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +400๋ฒˆ๋Œ€ ์ƒํƒœ ์ฝ”๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. + +**"404 Not Found"** ์˜ค๋ฅ˜(๊ทธ๋ฆฌ๊ณ  ๋†๋‹ด๋“ค)๋„ ๋‹ค๋“ค ๊ธฐ์–ตํ•˜์‹œ์ฃ ? + +## `HTTPException` ์‚ฌ์šฉํ•˜๊ธฐ { #use-httpexception } + +ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜๊ฐ€ ํฌํ•จ๋œ HTTP ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด `HTTPException`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +### `HTTPException` ๊ฐ€์ ธ์˜ค๊ธฐ { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} + +### ์ฝ”๋“œ์—์„œ `HTTPException` ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ { #raise-an-httpexception-in-your-code } + +`HTTPException`์€ API์™€ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง„ ์ผ๋ฐ˜์ ์ธ Python ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. + +Python ์˜ˆ์™ธ์ด๋ฏ€๋กœ `return` ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ `raise` ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” ๋˜ํ•œ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ์•ˆ์—์„œ `HTTPException`์„ `raise`ํ•˜๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ ํ•ด๋‹น ์š”์ฒญ์ด ์ข…๋ฃŒ๋˜๋ฉฐ `HTTPException`์˜ HTTP ์˜ค๋ฅ˜๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. + +๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์˜ ์ด์ ์€ ์˜์กด์„ฑ๊ณผ ๋ณด์•ˆ์— ๋Œ€ํ•œ ์„น์…˜์—์„œ ๋” ๋ถ„๋ช…ํ•ด์ง‘๋‹ˆ๋‹ค. + +์ด ์˜ˆ์‹œ์—์„œ๋Š”, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ID๋กœ ํ•ญ๋ชฉ์„ ์š”์ฒญํ•˜๋ฉด ์ƒํƒœ ์ฝ”๋“œ `404`๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค: + +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} + +### ๊ฒฐ๊ณผ ์‘๋‹ต { #the-resulting-response } + +ํด๋ผ์ด์–ธํŠธ๊ฐ€ `http://example.com/items/foo`( `item_id` `"foo"`)๋ฅผ ์š”์ฒญํ•˜๋ฉด, HTTP ์ƒํƒœ ์ฝ”๋“œ 200๊ณผ ๋‹ค์Œ JSON ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +ํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ `http://example.com/items/bar`(์กด์žฌํ•˜์ง€ ์•Š๋Š” `item_id` `"bar"`)๋ฅผ ์š”์ฒญํ•˜๋ฉด, HTTP ์ƒํƒœ ์ฝ”๋“œ 404("not found" ์˜ค๋ฅ˜)์™€ ๋‹ค์Œ JSON ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | ํŒ + +`HTTPException`์„ ๋ฐœ์ƒ์‹œํ‚ฌ ๋•Œ `detail` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ `str`๋งŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, JSON์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋–ค ๊ฐ’์ด๋“  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +`dict`, `list` ๋“ฑ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋“ค์€ **FastAPI**๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด JSON์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +/// + +## ์ปค์Šคํ…€ ํ—ค๋” ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-custom-headers } + +HTTP ์˜ค๋ฅ˜์— ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์œ ์šฉํ•œ ์ƒํ™ฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ๋ณด์•ˆ ์œ ํ˜•์—์„œ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. + +์•„๋งˆ ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ•„์š”ํ•˜๋‹ค๋ฉด ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} + +## ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์„ค์น˜ํ•˜๊ธฐ { #install-custom-exception-handlers } + +Starlette์˜ ๋™์ผํ•œ ์˜ˆ์™ธ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์—ฌ๋Ÿฌ๋ถ„(๋˜๋Š” ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์ด `raise`ํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ์˜ˆ์™ธ `UnicornException`์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ด ์˜ˆ์™ธ๋ฅผ FastAPI์—์„œ ์ „์—ญ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. + +`@app.exception_handler()`๋กœ ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} + +์—ฌ๊ธฐ์„œ `/unicorns/yolo`๋ฅผ ์š”์ฒญํ•˜๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ `UnicornException`์„ `raise`ํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `unicorn_exception_handler`๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ HTTP ์ƒํƒœ ์ฝ”๋“œ `418`๊ณผ ๋‹ค์Œ JSON ๋‚ด์šฉ์„ ๊ฐ€์ง„ ๊น”๋”ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +`from starlette.requests import Request`์™€ `from starlette.responses import JSONResponse`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด `starlette.responses`๋ฅผ `fastapi.responses`๋กœ๋„ ๋™์ผํ•˜๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์‘๋‹ต์€ Starlette์—์„œ ์ง์ ‘ ์˜ต๋‹ˆ๋‹ค. `Request`๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. + +/// + +## ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-default-exception-handlers } + +**FastAPI**์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ํ•ธ๋“ค๋Ÿฌ๋“ค์€ `HTTPException`์„ `raise`ํ–ˆ์„ ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ์š”์ฒญ์— ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ๊ธฐ๋ณธ JSON ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. + +์ด ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋“ค์„ ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฒƒ์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์š”์ฒญ ๊ฒ€์ฆ ์˜ˆ์™ธ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-request-validation-exceptions } + +์š”์ฒญ์— ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜๋ฉด, **FastAPI**๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ `RequestValidationError`๋ฅผ `raise`ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ์ด์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋ ค๋ฉด `RequestValidationError`๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , `@app.exception_handler(RequestValidationError)`๋กœ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ์ฝ”๋ ˆ์ดํŠธํ•ด ์‚ฌ์šฉํ•˜์„ธ์š”. + +์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋Š” `Request`์™€ ์˜ˆ์™ธ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} + +์ด์ œ `/items/foo`๋กœ ์ด๋™ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ JSON ์˜ค๋ฅ˜ ๋Œ€์‹ : + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ…์ŠคํŠธ ๋ฒ„์ „์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### `HTTPException` ์˜ค๋ฅ˜ ํ•ธ๋“ค๋Ÿฌ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-httpexception-error-handler } + +๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ `HTTPException` ํ•ธ๋“ค๋Ÿฌ๋„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Ÿฐ ์˜ค๋ฅ˜๋“ค์— ๋Œ€ํ•ด JSON ๋Œ€์‹  ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} + +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +`from starlette.responses import PlainTextResponse`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด `starlette.responses`๋ฅผ `fastapi.responses`๋กœ๋„ ๋™์ผํ•˜๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์‘๋‹ต์€ Starlette์—์„œ ์ง์ ‘ ์˜ต๋‹ˆ๋‹ค. + +/// + +/// warning | ๊ฒฝ๊ณ  + +`RequestValidationError`์—๋Š” ๊ฒ€์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ์ค„ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด, ์›ํ•œ๋‹ค๋ฉด ๊ด€๋ จ ์ •๋ณด์™€ ํ•จ๊ป˜ ๋กœ๊ทธ์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์œ ๋…ํ•˜์„ธ์š”. + +ํ•˜์ง€๋งŒ ์ด๋Š” ๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด ๊ทธ ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์ผ๋ถ€ ์ •๋ณด๋ฅผ ๋ˆ„์„คํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ์˜ ์ฝ”๋“œ๋Š” ๊ฐ ์˜ค๋ฅ˜๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์ถ”์ถœํ•ด ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. + +/// + +### `RequestValidationError`์˜ body ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-requestvalidationerror-body } + +`RequestValidationError`์—๋Š” ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๋ฐ›์€ `body`๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. + +์•ฑ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋™์•ˆ body๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ธฐ๊ณ  ๋””๋ฒ„๊ทธํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋“ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} + +์ด์ œ ๋‹ค์Œ์ฒ˜๋Ÿผ ์œ ํšจํ•˜์ง€ ์•Š์€ item์„ ๋ณด๋‚ด๋ณด์„ธ์š”: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +๋ฐ›์€ body๋ฅผ ํฌํ•จํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๋Š” ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### FastAPI์˜ `HTTPException` vs Starlette์˜ `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI**์—๋Š” ์ž์ฒด `HTTPException`์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  **FastAPI**์˜ `HTTPException` ์˜ค๋ฅ˜ ํด๋ž˜์Šค๋Š” Starlette์˜ `HTTPException` ์˜ค๋ฅ˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค. + +์œ ์ผํ•œ ์ฐจ์ด๋Š” **FastAPI**์˜ `HTTPException`์€ `detail` ํ•„๋“œ์— JSON์œผ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด, Starlette์˜ `HTTPException`์€ ๋ฌธ์ž์—ด๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์ฝ”๋“œ์—์„œ๋Š” ํ‰์†Œ์ฒ˜๋Ÿผ **FastAPI**์˜ `HTTPException`์„ ๊ณ„์† `raise`ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ๋Š” Starlette์˜ `HTTPException`์— ๋Œ€ํ•ด ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Starlette ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ์–ด๋–ค ๋ถ€๋ถ„, ๋˜๋Š” Starlette ํ™•์žฅ/ํ”Œ๋Ÿฌ๊ทธ์ธ์ด Starlette `HTTPException`์„ `raise`ํ•˜๋”๋ผ๋„, ์—ฌ๋Ÿฌ๋ถ„์˜ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ด๋ฅผ ์žก์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋™์ผํ•œ ์ฝ”๋“œ์—์„œ ๋‘ `HTTPException`์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก, Starlette์˜ ์˜ˆ์™ธ๋ฅผ `StarletteHTTPException`์œผ๋กœ ์ด๋ฆ„์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### **FastAPI**์˜ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ { #reuse-fastapis-exception-handlers } + +์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ **FastAPI**์˜ ๋™์ผํ•œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, `fastapi.exception_handlers`์—์„œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ ธ์™€ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} + +์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค์šฐ ํ‘œํ˜„๋ ฅ ์žˆ๋Š” ๋ฉ”์‹œ์ง€๋กœ ์˜ค๋ฅ˜๋ฅผ ์ถœ๋ ฅ๋งŒ ํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์š”์ง€๋Š” ์ดํ•ดํ•˜์…จ์„ ๊ฒ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•œ ๋’ค ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/security/first-steps.md b/docs/ko/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000..4c9181b31e --- /dev/null +++ b/docs/ko/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# ๋ณด์•ˆ - ์ฒซ ๋‹จ๊ณ„ { #security-first-steps } + +์–ด๋–ค ๋„๋ฉ”์ธ์— **backend** API๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์— **frontend**๊ฐ€ ์žˆ๊ฑฐ๋‚˜, ๊ฐ™์€ ๋„๋ฉ”์ธ์˜ ๋‹ค๋ฅธ ๊ฒฝ๋กœ์— ์žˆ๊ฑฐ๋‚˜(๋˜๋Š” ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). + +๊ทธ๋ฆฌ๊ณ  frontend๊ฐ€ **username**๊ณผ **password**๋ฅผ ์‚ฌ์šฉํ•ด backend์— ์ธ์ฆํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. + +**FastAPI**์™€ ํ•จ๊ป˜ **OAuth2**๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ํ•„์š”ํ•œ ์ž‘์€ ์ •๋ณด ์กฐ๊ฐ๋“ค์„ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ธธ๊ณ  ๊ธด ์ „์ฒด ์ŠคํŽ™์„ ์ฝ๋А๋ผ ์‹œ๊ฐ„์„ ์“ฐ์ง€ ์•Š๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด **FastAPI**๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋„๊ตฌ๋“ค์„ ์‚ฌ์šฉํ•ด ๋ด…์‹œ๋‹ค. + +## ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ { #how-it-looks } + +๋จผ์ € ์ฝ”๋“œ๋ฅผ ๊ทธ๋ƒฅ ์‚ฌ์šฉํ•ด์„œ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋ณด๊ณ , ๊ทธ๋‹ค์Œ์— ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์ดํ•ดํ•˜๋Ÿฌ ๋‹ค์‹œ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค. + +## `main.py` ๋งŒ๋“ค๊ธฐ { #create-main-py } + +์˜ˆ์ œ๋ฅผ ํŒŒ์ผ `main.py`์— ๋ณต์‚ฌํ•˜์„ธ์š”: + +{* ../../docs_src/security/tutorial001_an_py39.py *} + +## ์‹คํ–‰ํ•˜๊ธฐ { #run-it } + +/// info | ์ •๋ณด + +`python-multipart` ํŒจํ‚ค์ง€๋Š” `pip install "fastapi[standard]"` ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด **FastAPI**์™€ ํ•จ๊ป˜ ์ž๋™์œผ๋กœ ์„ค์น˜๋ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ `pip install fastapi` ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๋ฉด `python-multipart` ํŒจํ‚ค์ง€๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ•˜๋ ค๋ฉด, [๊ฐ€์ƒ ํ™˜๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, ์•„๋ž˜๋กœ ์„ค์น˜ํ•˜์„ธ์š”: + +```console +$ pip install python-multipart +``` + +์ด๋Š” **OAuth2**๊ฐ€ `username`๊ณผ `password`๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด "form data"๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +/// + +๋‹ค์Œ์œผ๋กœ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## ํ™•์ธํ•˜๊ธฐ { #check-it } + +๋Œ€ํ™”ํ˜• ๋ฌธ์„œ๋กœ ์ด๋™ํ•˜์„ธ์š”: http://127.0.0.1:8000/docs. + +๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ ํ™”๋ฉด์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค: + + + +/// check | Authorize ๋ฒ„ํŠผ! + +๋ฐ˜์ง์ด๋Š” ์ƒˆ "Authorize" ๋ฒ„ํŠผ์ด ์ด๋ฏธ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—๋Š” ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ์— ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์€ ์ž๋ฌผ์‡ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ํด๋ฆญํ•˜๋ฉด `username`๊ณผ `password`(๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์„ ํƒ์  ํ•„๋“œ๋“ค)๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์€ ์ธ์ฆ ํผ์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค: + + + +/// note | ์ฐธ๊ณ  + +ํผ์— ๋ฌด์—‡์„ ์ž…๋ ฅํ•˜๋“  ์•„์ง์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ณง ์—ฌ๊ธฐ๊นŒ์ง€ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// + +๋ฌผ๋ก  ์ด๊ฒƒ์€ ์ตœ์ข… ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ frontend๋Š” ์•„๋‹ˆ์ง€๋งŒ, ๋ชจ๋“  API๋ฅผ ๋Œ€ํ™”ํ˜•์œผ๋กœ ๋ฌธ์„œํ™”ํ•˜๋Š” ํ›Œ๋ฅญํ•œ ์ž๋™ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. + +frontend ํŒ€(๊ทธ๊ฒŒ ๋ณธ์ธ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค)์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์„œ๋“œํŒŒํ‹ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์‹œ์Šคํ…œ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋™์ผํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋””๋ฒ„๊ทธํ•˜๊ณ , ํ™•์ธํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋ณธ์ธ์ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +## `password` ํ”Œ๋กœ์šฐ { #the-password-flow } + +์ด์ œ ์กฐ๊ธˆ ๋Œ์•„๊ฐ€์„œ ์ด๊ฒƒ๋“ค์ด ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•ด ๋ด…์‹œ๋‹ค. + +`password` "flow"๋Š” ๋ณด์•ˆ๊ณผ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด OAuth2์—์„œ ์ •์˜ํ•œ ์—ฌ๋Ÿฌ ๋ฐฉ์‹("flows") ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. + +OAuth2๋Š” backend ๋˜๋Š” API๊ฐ€ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๋Š” ์„œ๋ฒ„์™€ ๋…๋ฆฝ์ ์ผ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋Š” ๊ฐ™์€ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด API์™€ ์ธ์ฆ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ, ๋‹จ์ˆœํ™”๋œ ๊ด€์ ์—์„œ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๋ฉด: + +* ์‚ฌ์šฉ์ž๊ฐ€ frontend์—์„œ `username`๊ณผ `password`๋ฅผ ์ž…๋ ฅํ•˜๊ณ  `Enter`๋ฅผ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค. +* frontend(์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋จ)๋Š” ํ•ด๋‹น `username`๊ณผ `password`๋ฅผ ์šฐ๋ฆฌ API์˜ ํŠน์ • URL๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค(`tokenUrl="token"`๋กœ ์„ ์–ธ๋จ). +* API๋Š” `username`๊ณผ `password`๋ฅผ ํ™•์ธํ•˜๊ณ  "token"์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค(์•„์ง ์•„๋ฌด๊ฒƒ๋„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค). + * "token"์€ ๋‚˜์ค‘์— ์ด ์‚ฌ์šฉ์ž๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋–ค ๋‚ด์šฉ์ด ๋‹ด๊ธด ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. + * ๋ณดํ†ต token์€ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋งŒ๋ฃŒ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + * ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๋Š” ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—” ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + * ๊ทธ๋ฆฌ๊ณ  token์ด ๋„๋‚œ๋‹นํ•˜๋”๋ผ๋„ ์œ„ํ—˜์ด ๋” ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์˜๊ตฌ์ ์œผ๋กœ ํ•ญ์ƒ ๋™์ž‘ํ•˜๋Š” ํ‚ค์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. +* frontend๋Š” ๊ทธ token์„ ์ž„์‹œ๋กœ ์–ด๋”˜๊ฐ€์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. +* ์‚ฌ์šฉ์ž๊ฐ€ frontend์—์„œ ํด๋ฆญํ•ด์„œ frontend ์›น ์•ฑ์˜ ๋‹ค๋ฅธ ์„น์…˜์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. +* frontend๋Š” API์—์„œ ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. + * ํ•˜์ง€๋งŒ ๊ทธ ํŠน์ • endpoint์—๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. + * ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ API์— ์ธ์ฆํ•˜๊ธฐ ์œ„ํ•ด `Authorization` ํ—ค๋”๋ฅผ, ๊ฐ’์€ `Bearer `์— token์„ ๋”ํ•œ ํ˜•ํƒœ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. + * token์— `foobar`๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค๋ฉด `Authorization` ํ—ค๋”์˜ ๋‚ด์šฉ์€ `Bearer foobar`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. + +## **FastAPI**์˜ `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } + +**FastAPI**๋Š” ์ด๋Ÿฐ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด, ์„œ๋กœ ๋‹ค๋ฅธ ์ถ”์ƒํ™” ์ˆ˜์ค€์—์„œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +์ด ์˜ˆ์ œ์—์„œ๋Š” **OAuth2**์˜ **Password** ํ”Œ๋กœ์šฐ์™€ **Bearer** token์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด `OAuth2PasswordBearer` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +"bearer" token๋งŒ์ด ์œ ์ผํ•œ ์„ ํƒ์ง€๋Š” ์•„๋‹™๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์„ ํƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ OAuth2 ์ „๋ฌธ๊ฐ€๋กœ์„œ ์™œ ๋‹ค๋ฅธ ์˜ต์…˜์ด ๋” ์ ํ•ฉํ•œ์ง€ ์ •ํ™•ํžˆ ์•„๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋„ ๊ฐ€์žฅ ์ ํ•ฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด์„œ๋„ **FastAPI**๋Š” ์ด๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +/// + +`OAuth2PasswordBearer` ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ `tokenUrl` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ํด๋ผ์ด์–ธํŠธ(์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” frontend)๊ฐ€ token์„ ๋ฐ›๊ธฐ ์œ„ํ•ด `username`๊ณผ `password`๋ฅผ ๋ณด๋‚ผ URL์ด ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} + +/// tip | ํŒ + +์—ฌ๊ธฐ์„œ `tokenUrl="token"`์€ ์•„์ง ๋งŒ๋“ค์ง€ ์•Š์€ ์ƒ๋Œ€ URL `token`์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์ƒ๋Œ€ URL์ด๋ฏ€๋กœ `./token`๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +์ƒ๋Œ€ URL์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ์˜ˆ๋ฅผ ๋“ค์–ด API๊ฐ€ `https://example.com/`์— ์žˆ๋‹ค๋ฉด `https://example.com/token`์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ API๊ฐ€ `https://example.com/api/v1/`์— ์žˆ๋‹ค๋ฉด `https://example.com/api/v1/token`์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. + +์ƒ๋Œ€ URL์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ [ํ”„๋ก์‹œ ๋’ค์—์„œ](../../advanced/behind-a-proxy.md){.internal-link target=_blank} ๊ฐ™์€ ๊ณ ๊ธ‰ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ณ„์† ๋™์ž‘ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. + +/// + +์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ทธ endpoint / *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค์ง€๋Š” ์•Š์ง€๋งŒ, URL `/token`์ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ token์„ ์–ป๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ด์•ผ ํ•  URL์ด๋ผ๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋Š” OpenAPI์— ์‚ฌ์šฉ๋˜๊ณ , ์ด์–ด์„œ ๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ ์‹œ์Šคํ…œ์—์„œ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + +๊ณง ์‹ค์ œ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +/// info | ์ •๋ณด + +์—„๊ฒฉํ•œ "Pythonista"๋ผ๋ฉด `token_url` ๋Œ€์‹  `tokenUrl` ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„ ์Šคํƒ€์ผ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋Š” OpenAPI ์ŠคํŽ™์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถ˜ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋ณด์•ˆ ์Šคํ‚ด์— ๋Œ€ํ•ด ๋” ์กฐ์‚ฌํ•ด์•ผ ํ•  ๋•Œ, ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ ๋„ฃ์–ด ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +`oauth2_scheme` ๋ณ€์ˆ˜๋Š” `OAuth2PasswordBearer`์˜ ์ธ์Šคํ„ด์Šค์ด์ง€๋งŒ, "callable"์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. + +๋‹ค์Œ์ฒ˜๋Ÿผ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +oauth2_scheme(some, parameters) +``` + +๋”ฐ๋ผ์„œ `Depends`์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ์‚ฌ์šฉํ•˜๊ธฐ { #use-it } + +์ด์ œ `Depends`๋กœ `oauth2_scheme`๋ฅผ ์˜์กด์„ฑ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} + +์ด ์˜์กด์„ฑ์€ `str`์„ ์ œ๊ณตํ•˜๊ณ , ๊ทธ ๊ฐ’์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ํŒŒ๋ผ๋ฏธํ„ฐ `token`์— ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. + +**FastAPI**๋Š” ์ด ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ(๋ฐ ์ž๋™ API ๋ฌธ์„œ)์— "security scheme"๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + +/// info | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ + +**FastAPI**๋Š” (์˜์กด์„ฑ์— ์„ ์–ธ๋œ) `OAuth2PasswordBearer` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI์—์„œ ๋ณด์•ˆ ์Šคํ‚ด์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” `OAuth2PasswordBearer`๊ฐ€ `fastapi.security.oauth2.OAuth2`๋ฅผ ์ƒ์†ํ•˜๊ณ , ์ด๊ฒƒ์ด ๋‹ค์‹œ `fastapi.security.base.SecurityBase`๋ฅผ ์ƒ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +OpenAPI(๋ฐ ์ž๋™ API ๋ฌธ์„œ)์™€ ํ†ตํ•ฉ๋˜๋Š” ๋ชจ๋“  ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” `SecurityBase`๋ฅผ ์ƒ์†ํ•˜๋ฉฐ, ๊ทธ๋ž˜์„œ **FastAPI**๊ฐ€ ์ด๋ฅผ OpenAPI์— ์–ด๋–ป๊ฒŒ ํ†ตํ•ฉํ• ์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ { #what-it-does } + +์š”์ฒญ์—์„œ `Authorization` ํ—ค๋”๋ฅผ ์ฐพ์•„, ๊ฐ’์ด `Bearer `์— ์–ด๋–ค token์ด ๋ถ™์€ ํ˜•ํƒœ์ธ์ง€ ํ™•์ธํ•œ ๋’ค, ๊ทธ token์„ `str`๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +`Authorization` ํ—ค๋”๊ฐ€ ์—†๊ฑฐ๋‚˜, ๊ฐ’์— `Bearer ` token์ด ์—†๋‹ค๋ฉด, ๊ณง๋ฐ”๋กœ 401 ์ƒํƒœ ์ฝ”๋“œ ์˜ค๋ฅ˜(`UNAUTHORIZED`)๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. + +์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด token์ด ์กด์žฌํ•˜๋Š”์ง€ ์ง์ ‘ ํ™•์ธํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์—ˆ๋‹ค๋ฉด ๊ทธ token์—๋Š” `str`์ด ๋“ค์–ด ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์—์„œ ์ด๋ฏธ ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + + + +์•„์ง token์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜์ง„ ์•Š์ง€๋งŒ, ์ด๊ฒƒ๋งŒ์œผ๋กœ๋„ ์‹œ์ž‘์€ ๋œ ์…ˆ์ž…๋‹ˆ๋‹ค. + +## ์š”์•ฝ { #recap } + +์ฆ‰, ์ถ”๊ฐ€๋กœ 3~4์ค„๋งŒ์œผ๋กœ๋„ ์ด๋ฏธ ์›์‹œ์ ์ธ ํ˜•ํƒœ์˜ ๋ณด์•ˆ์„ ๊ฐ–์ถ”๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/security/index.md b/docs/ko/docs/tutorial/security/index.md new file mode 100644 index 0000000000..2320b06571 --- /dev/null +++ b/docs/ko/docs/tutorial/security/index.md @@ -0,0 +1,106 @@ +# ๋ณด์•ˆ { #security } + +๋ณด์•ˆ, ์ธ์ฆ(authentication), ์ธ๊ฐ€(authorization)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ๋ณดํ†ต ๋ณต์žกํ•˜๊ณ  "์–ด๋ ค์šด" ์ฃผ์ œ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. + +๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์‹œ์Šคํ…œ์—์„œ ๋ณด์•ˆ๊ณผ ์ธ์ฆ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ๋„ ํฐ ๋…ธ๋ ฅ๊ณผ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๋งŽ์€ ๊ฒฝ์šฐ ์ž‘์„ฑ๋œ ์ „์ฒด ์ฝ”๋“œ์˜ 50% ์ด์ƒ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). + +**FastAPI**๋Š” ๋ชจ๋“  ๋ณด์•ˆ ๋ช…์„ธ๋ฅผ ์ „๋ถ€ ๊ณต๋ถ€ํ•˜๊ณ  ๋ฐฐ์šธ ํ•„์š” ์—†์ด, ํ‘œ์ค€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ **๋ณด์•ˆ(Security)** ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +ํ•˜์ง€๋งŒ ๋จผ์ €, ๋ช‡ ๊ฐ€์ง€ ์ž‘์€ ๊ฐœ๋…์„ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. + +## ๊ธ‰ํ•˜์‹ ๊ฐ€์š”? { #in-a-hurry } + +์ด ์šฉ์–ด๋“ค์— ๊ด€์‹ฌ์ด ์—†๊ณ  ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์‚ฌ์šฉํ•œ ๋ณด์•ˆ์„ *์ง€๊ธˆ ๋‹น์žฅ* ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค๋ฉด, ๋‹ค์Œ ์žฅ๋“ค๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”. + +## OAuth2 { #oauth2 } + +OAuth2๋Š” ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•˜๋Š” ๋ช…์„ธ์ž…๋‹ˆ๋‹ค. + +์ƒ๋‹นํžˆ ๋ฐฉ๋Œ€ํ•œ ๋ช…์„ธ์ด๋ฉฐ ์—ฌ๋Ÿฌ ๋ณต์žกํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. + +"์ œ3์ž"๋ฅผ ์‚ฌ์šฉํ•ด ์ธ์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. + +๋ฐ”๋กœ `"Facebook, Google, X (Twitter), GitHub๋กœ ๋กœ๊ทธ์ธ"` ๊ฐ™์€ ์‹œ์Šคํ…œ๋“ค์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. + +### OAuth 1 { #oauth-1 } + +OAuth 1๋„ ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋Š” OAuth2์™€ ๋งค์šฐ ๋‹ค๋ฅด๊ณ  ํ†ต์‹ ์„ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€ ์ง์ ‘ ๋ช…์„ธ์— ํฌํ•จํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋ณต์žกํ–ˆ์Šต๋‹ˆ๋‹ค. + +์š”์ฆ˜์—๋Š” ๊ทธ๋‹ค์ง€ ์ธ๊ธฐ ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. + +OAuth2๋Š” ํ†ต์‹ ์„ ์–ด๋–ป๊ฒŒ ์•”ํ˜ธํ™”ํ• ์ง€๋Š” ๋ช…์„ธํ•˜์ง€ ์•Š๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด HTTPS๋กœ ์ œ๊ณต๋  ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. + +/// tip | ํŒ + +**๋ฐฐํฌ**์— ๋Œ€ํ•œ ์„น์…˜์—์„œ Traefik๊ณผ Let's Encrypt๋ฅผ ์‚ฌ์šฉํ•ด ๋ฌด๋ฃŒ๋กœ HTTPS๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect๋Š” **OAuth2**๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋˜ ๋‹ค๋ฅธ ๋ช…์„ธ์ž…๋‹ˆ๋‹ค. + +OAuth2์—์„œ ๋น„๊ต์  ๋ชจํ˜ธํ•œ ๋ถ€๋ถ„์„ ์ผ๋ถ€ ๊ตฌ์ฒดํ™”ํ•˜์—ฌ ์ƒํ˜ธ ์šด์šฉ์„ฑ์„ ๋†’์ด๋ ค๋Š” ํ™•์žฅ์ž…๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, Google ๋กœ๊ทธ์ธ์€ OpenID Connect๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(๋‚ด๋ถ€์ ์œผ๋กœ๋Š” OAuth2๋ฅผ ์‚ฌ์šฉ). + +ํ•˜์ง€๋งŒ Facebook ๋กœ๊ทธ์ธ์€ OpenID Connect๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž์ฒด์ ์ธ ๋ณ€ํ˜•์˜ OAuth2๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + +### OpenID("OpenID Connect"๊ฐ€ ์•„๋‹˜) { #openid-not-openid-connect } + +"OpenID"๋ผ๋Š” ๋ช…์„ธ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” **OpenID Connect**์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ, OAuth2๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. + +๋”ฐ๋ผ์„œ ์™„์ „ํžˆ ๋ณ„๋„์˜ ์ถ”๊ฐ€ ์‹œ์Šคํ…œ์ด์—ˆ์Šต๋‹ˆ๋‹ค. + +์š”์ฆ˜์—๋Š” ๊ทธ๋‹ค์ง€ ์ธ๊ธฐ ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. + +## OpenAPI { #openapi } + +OpenAPI(์ด์ „์—๋Š” Swagger๋กœ ์•Œ๋ ค์ง)๋Š” API๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ๊ณต๊ฐœ ๋ช…์„ธ์ž…๋‹ˆ๋‹ค(ํ˜„์žฌ Linux Foundation์˜ ์ผ๋ถ€). + +**FastAPI**๋Š” **OpenAPI**๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. + +์ด ๋•๋ถ„์— ์—ฌ๋Ÿฌ ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์ธํ„ฐํŽ˜์ด์Šค, ์ฝ”๋“œ ์ƒ์„ฑ ๋“ฑ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +OpenAPI์—๋Š” ์—ฌ๋Ÿฌ ๋ณด์•ˆ "scheme"์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฌํ•œ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ์„ ํฌํ•จํ•ด, ํ‘œ์ค€ ๊ธฐ๋ฐ˜ ๋„๊ตฌ๋“ค์„ ๋ชจ๋‘ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +OpenAPI๋Š” ๋‹ค์Œ ๋ณด์•ˆ scheme๋“ค์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: + +* `apiKey`: ๋‹ค์Œ์—์„œ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์šฉ ํ‚ค: + * ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ + * ํ—ค๋” + * ์ฟ ํ‚ค +* `http`: ํ‘œ์ค€ HTTP ์ธ์ฆ ์‹œ์Šคํ…œ, ์˜ˆ: + * `bearer`: `Authorization` ํ—ค๋”์— `Bearer ` + ํ† ํฐ ๊ฐ’์„ ๋„ฃ๋Š” ๋ฐฉ์‹. OAuth2์—์„œ ์œ ๋ž˜ํ–ˆ์Šต๋‹ˆ๋‹ค. + * HTTP Basic ์ธ์ฆ + * HTTP Digest ๋“ฑ +* `oauth2`: ๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“  OAuth2 ๋ฐฉ์‹(์ด๋ฅผ "flow"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค). + * ์ด flow๋“ค ์ค‘ ์—ฌ๋Ÿฌ ๊ฐœ๋Š” OAuth 2.0 ์ธ์ฆ ์ œ๊ณต์ž(์˜ˆ: Google, Facebook, X (Twitter), GitHub ๋“ฑ)๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค: + * `implicit` + * `clientCredentials` + * `authorizationCode` + * ํ•˜์ง€๋งŒ ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์™„๋ฒฝํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ • "flow"๋„ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค: + * `password`: ๋‹ค์Œ ์žฅ๋“ค์—์„œ ์ด์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. +* `openIdConnect`: OAuth2 ์ธ์ฆ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ํƒ์ƒ‰(discover)ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. + * ์ด ์ž๋™ ํƒ์ƒ‰์€ OpenID Connect ๋ช…์„ธ์—์„œ ์ •์˜๋ฉ๋‹ˆ๋‹ค. + + +/// tip | ํŒ + +Google, Facebook, X (Twitter), GitHub ๋“ฑ ๋‹ค๋ฅธ ์ธ์ฆ/์ธ๊ฐ€ ์ œ๊ณต์ž๋ฅผ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋น„๊ต์  ์‰ฝ์Šต๋‹ˆ๋‹ค. + +๊ฐ€์žฅ ๋ณต์žกํ•œ ๋ฌธ์ œ๋Š” ๊ทธ๋Ÿฐ ์ธ์ฆ/์ธ๊ฐ€ ์ œ๊ณต์ž ์ž์ฒด๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, **FastAPI**๋Š” ์–ด๋ ค์šด ์ž‘์—…์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด ์ฃผ๋ฉด์„œ ์ด๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. + +/// + +## **FastAPI** ์œ ํ‹ธ๋ฆฌํ‹ฐ { #fastapi-utilities } + +FastAPI๋Š” `fastapi.security` ๋ชจ๋“ˆ์—์„œ ๊ฐ ๋ณด์•ˆ scheme์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + +๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” **FastAPI**๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด API์— ๋ณด์•ˆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +๋˜ํ•œ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ์— ์–ด๋–ป๊ฒŒ ์ž๋™์œผ๋กœ ํ†ตํ•ฉ๋˜๋Š”์ง€๋„ ํ™•์ธํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. From 23bcfa094d9baefbf0150cbcddd1b77ec33a23fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 Jan 2026 11:54:26 +0000 Subject: [PATCH 004/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 233fdb7434..912f215f09 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14589](https://github.com/fastapi/fastapi/pull/14589) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update-outdated). PR [#14587](https://github.com/fastapi/fastapi/pull/14587) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for es (update-outdated). PR [#14686](https://github.com/fastapi/fastapi/pull/14686) by [@tiangolo](https://github.com/tiangolo). From fb15bba819a71df10fee28891c6c7c29fdf48d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 16 Jan 2026 03:57:08 -0800 Subject: [PATCH 005/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20LLM=20prompt=20?= =?UTF-8?q?instructions=20file=20for=20French=20(#14618)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/fr/llm-prompt.md | 154 ++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/docs/fr/llm-prompt.md b/docs/fr/llm-prompt.md index 5ff18c4e8b..228500fe23 100644 --- a/docs/fr/llm-prompt.md +++ b/docs/fr/llm-prompt.md @@ -6,123 +6,127 @@ Language code: fr. ### Grammar to use when talking to the reader -Use the formal grammar (use ยซvousยป instead of ยซtuยป). +Use the formal grammar (use `vous` instead of `tu`). -### Quotes +Additionally, in instructional sentences, prefer the present tense for obligations: + +- Prefer `vous devez โ€ฆ` over `vous devrez โ€ฆ`, unless the English source explicitly refers to a future requirement. + +- When translating โ€œmake sure (that) โ€ฆ is โ€ฆโ€, prefer the indicative after `vous assurer que` (e.g. `Vous devez vous assurer qu'il est โ€ฆ`) instead of the subjunctive (e.g. `qu'il soit โ€ฆ`). -1) Convert neutral double quotes (ยซ"ยป) and English double typographic quotes (ยซโ€œยป and ยซโ€ยป) to French guillemets (ยซยซยป and ยซยปยป). +### Quotes -2) In the French docs, guillemets are written without extra spaces: use ยซtexteยป, not ยซ texte ยป. +- Convert neutral double quotes (`"`) to French guillemets (`ยซ` and `ยป`). -3) Do not convert quotes inside code blocks, inline code, paths, URLs, or anything wrapped in backticks. +- Do not convert quotes inside code blocks, inline code, paths, URLs, or anything wrapped in backticks. Examples: - Source (English): +Source (English): - ยซยซยซ - "Hello world" - โ€œHello Universeโ€ - "He said: 'Hello'" - "The module is `__main__`" - ยปยปยป +``` +"Hello world" +โ€œHello Universeโ€ +"He said: 'Hello'" +"The module is `__main__`" +``` - Result (French): +Result (French): - ยซยซยซ - ยซHello worldยป - ยซHello Universeยป - ยซHe said: 'Hello'ยป - ยซThe module is `__main__`ยป - ยปยปยป +``` +"Hello world" +โ€œHello Universeโ€ +"He said: 'Hello'" +"The module is `__main__`" +``` ### Ellipsis -1) Make sure there is a space between an ellipsis and a word following or preceding the ellipsis. +- Make sure there is a space between an ellipsis and a word following or preceding the ellipsis. Examples: - Source (English): +Source (English): - ยซยซยซ - ...as we intended. - ...this would work: - ...etc. - others... - More to come... - ยปยปยป +``` +...as we intended. +...this would work: +...etc. +others... +More to come... +``` - Result (French): +Result (French): - ยซยซยซ - ... comme prรฉvu. - ... cela fonctionnerait : - ... etc. - D'autres ... - La suite ... - ยปยปยป +``` +... comme prรฉvu. +... cela fonctionnerait : +... etc. +D'autres ... +La suite ... +``` -2) This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there. +- This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there. ### Headings -1) Prefer translating headings using the infinitive form (as is common in the existing French docs): ยซCrรฉerโ€ฆยป, ยซUtiliserโ€ฆยป, ยซAjouterโ€ฆยป. - -2) For headings that are instructions written in imperative in English (e.g. โ€œGo check โ€ฆโ€), keep them in imperative in French, using the formal grammar (e.g. ยซAllez voir โ€ฆยป). +- Prefer translating headings using the infinitive form (as is common in the existing French docs): `Crรฉerโ€ฆ`, `Utiliserโ€ฆ`, `Ajouterโ€ฆ`. -3) Keep heading punctuation as in the source. In particular, keep occurrences of literal ยซ - ยป (space-hyphen-space) as ยซ - ยป (the existing French docs use a hyphen here). +- For headings that are instructions written in imperative in English (e.g. `Go check โ€ฆ`), keep them in imperative in French, using the formal grammar (e.g. `Allez voir โ€ฆ`). ### French instructions about technical terms -Do not try to translate everything. In particular, keep common programming terms when that is the established usage in the French docs (e.g. ยซframeworkยป, ยซendpointยป, ยซplug-inยป, ยซpayloadยป). Use French where the existing docs already consistently use French (e.g. ยซrequรชteยป, ยซrรฉponseยป). +Do not try to translate everything. In particular, keep common programming terms (e.g. `framework`, `endpoint`, `plug-in`, `payload`). Keep class names, function names, modules, file names, and CLI commands unchanged. ### List of English terms and their preferred French translations -Below is a list of English terms and their preferred French translations, separated by a colon (ยซ:ยป). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. +Below is a list of English terms and their preferred French translations, separated by a colon (:). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. + +- /// note | Technical Detailsยป: /// note | Dรฉtails techniques +- /// note: /// note | Remarque +- /// tip: /// tip | Astuce +- /// warning: /// warning | Alertes +- /// check: /// check | Vรฉrifications +- /// info: /// info -* ยซ/// note | Technical Detailsยป: ยซ/// note | Dรฉtails techniquesยป -* ยซ/// noteยป: ยซ/// note | Remarqueยป -* ยซ/// tipยป: ยซ/// tip | Astuceยป -* ยซ/// warningยป: ยซ/// warning | Attentionยป -* ยซ/// checkยป: ยซ/// check | vรฉrifierยป -* ยซ/// infoยป: ยซ/// infoยป +- the docs: les documents +- the documentation: la documentation -* ยซthe docsยป: ยซles documentsยป -* ยซthe documentationยป: ยซla documentationยป +- Exclude from OpenAPI: Exclusion d'OpenAPI -* ยซframeworkยป: ยซframeworkยป (do not translate to ยซcadreยป) -* ยซperformanceยป: ยซperformanceยป +- framework: framework (do not translate to cadre) +- performance: performance -* ยซtype hintsยป: ยซannotations de typeยป -* ยซtype annotationsยป: ยซannotations de typeยป +- type hints: annotations de type +- type annotations: annotations de type -* ยซautocompleteยป: ยซautocomplรฉtionยป -* ยซautocompletionยป: ยซautocomplรฉtionยป +- autocomplete: autocomplรฉtion +- autocompletion: autocomplรฉtion -* ยซthe requestยป (what the client sends to the server): ยซla requรชteยป -* ยซthe responseยป (what the server sends back to the client): ยซla rรฉponseยป +- the request (what the client sends to the server): la requรชte +- the response (what the server sends back to the client): la rรฉponse -* ยซthe request bodyยป: ยซle corps de la requรชteยป -* ยซthe response bodyยป: ยซle corps de la rรฉponseยป +- the request body: le corps de la requรชte +- the response body: le corps de la rรฉponse -* ยซpath operationยป: ยซopรฉration de cheminยป -* ยซpath operationsยป (plural): ยซopรฉrations de cheminยป -* ยซpath operation functionยป: ยซfonction de cheminยป -* ยซpath operation decoratorยป: ยซdรฉcorateur d'opรฉration de cheminยป +- path operation: chemin d'accรจs +- path operations (plural): chemins d'accรจs +- path operation function: fonction de chemin d'accรจs +- path operation decorator: dรฉcorateur de chemin d'accรจs -* ยซpath parameterยป: ยซparamรจtre de cheminยป -* ยซquery parameterยป: ยซparamรจtre de requรชteยป +- path parameter: paramรจtre de chemin +- query parameter: paramรจtre de requรชte -* ยซthe `Request`ยป: ยซ`Request`ยป (keep as code identifier) -* ยซthe `Response`ยป: ยซ`Response`ยป (keep as code identifier) +- the `Request`: `Request` (keep as code identifier) +- the `Response`: `Response` (keep as code identifier) -* ยซdeploymentยป: ยซdรฉploiementยป -* ยซto upgradeยป: ยซmettre ร  niveauยป +- deployment: dรฉploiement +- to upgrade: mettre ร  niveau -* ยซdeprecatedยป: ยซdรฉprรฉciรฉยป -* ยซto deprecateยป: ยซdรฉprรฉcierยป +- deprecated: dรฉprรฉciรฉ +- to deprecate: dรฉprรฉcier -* ยซcheat sheetยป: ยซaide-mรฉmoireยป -* ยซplug-inยป: ยซplug-inยป +- cheat sheet: aide-mรฉmoire +- plug-in: plug-in From 8fa635c718fe71fa2e761b7fb33978d756e77a45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 Jan 2026 11:57:32 +0000 Subject: [PATCH 006/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 912f215f09..404a4e41d0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14589](https://github.com/fastapi/fastapi/pull/14589) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update-outdated). PR [#14587](https://github.com/fastapi/fastapi/pull/14587) by [@tiangolo](https://github.com/tiangolo). From 9fec72687f48db48d72bff6ba2aa023fe792206b Mon Sep 17 00:00:00 2001 From: Rafael de Oliveira Marques Date: Fri, 16 Jan 2026 09:27:02 -0300 Subject: [PATCH 007/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20portuguese=20ll?= =?UTF-8?q?m-prompt.md=20(#14702)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- docs/pt/llm-prompt.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/pt/llm-prompt.md b/docs/pt/llm-prompt.md index 3f5208e910..dd72e8d168 100644 --- a/docs/pt/llm-prompt.md +++ b/docs/pt/llm-prompt.md @@ -10,6 +10,26 @@ Keep existing translations as they are if the term is already translated. When translating documentation into Portuguese, use neutral and widely understandable language. Although Portuguese originated in Portugal and has its largest number of speakers in Brazil, it is also an official language in several countries and regions, such as Equatorial Guinea, Mozambique, Angola, Cape Verde, and Sรฃo Tomรฉ and Prรญncipe. Avoid words or expressions that are specific to a single country or region. +Only keep parentheses if they exist in the source text. Do not add parentheses to terms that do not have them. + +### Avoiding Repetition in Translation + +When translating sentences, avoid unnecessary repetition of words or phrases that are implied in context. +- Merge repeated words naturally while keeping the meaning. +- Do **not** introduce extra words to replace repeated phrases unnecessarily. +- Keep translations fluent and concise, but maintain the original meaning. + +**Example:** + +Source: +Let's see how that works and how to change it if you need to do that. + +Avoid translating literally as: +Vamos ver como isso funciona e como alterar isso se vocรช precisar fazer isso. + +Better translation: +Vamos ver como isso funciona e como alterar se vocรช precisar. + --- For the next terms, use the following translations: @@ -22,10 +42,11 @@ For the next terms, use the following translations: * /// note: /// note | Nota * /// tip: /// tip | Dica * /// warning: /// warning | Atenรงรฃo -* (you should): (vocรช deveria) +* you should: vocรช deveria * async context manager: gerenciador de contexto assรญncrono * autocomplete: autocompletar * autocompletion: preenchimento automรกtico +* auto-completion: preenchimento automรกtico * bug: bug * context manager: gerenciador de contexto * cross domain: cross domain (do not translate to "domรญnio cruzado") From 0c7f2b66d769d05df42ea73f85205a3566ba127b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 Jan 2026 12:27:29 +0000 Subject: [PATCH 008/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 404a4e41d0..d3f80fac93 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n). * ๐ŸŒ Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14589](https://github.com/fastapi/fastapi/pull/14589) by [@tiangolo](https://github.com/tiangolo). From 536a5bafe74a77f207b57cf6fb0cf3059121fffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 19 Jan 2026 12:40:17 -0800 Subject: [PATCH 009/367] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors,=20Lam?= =?UTF-8?q?bdaTest=20changes=20to=20TestMu=20AI=20(#14734)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/sponsors.yml | 6 +++--- docs/en/docs/img/sponsors/testmu.png | Bin 0 -> 5725 bytes 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 docs/en/docs/img/sponsors/testmu.png diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 50b1145301..c0bdb15f63 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -65,9 +65,9 @@ bronze: # - url: https://testdriven.io/courses/tdd-fastapi/ # title: Learn to build high-quality web apps with best practices # img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg - - url: https://lambdatest.com/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage - title: LambdaTest, AI-Powered Cloud-based Test Orchestration Platform - img: https://fastapi.tiangolo.com/img/sponsors/lambdatest.png + - url: https://www.testmu.ai/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage + title: TestMu AI. The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. + img: https://fastapi.tiangolo.com/img/sponsors/testmu.png - url: https://requestly.com/fastapi title: All-in-one platform to Test, Mock and Intercept APIs. Built for speed, privacy and offline support. img: https://fastapi.tiangolo.com/img/sponsors/requestly.png diff --git a/docs/en/docs/img/sponsors/testmu.png b/docs/en/docs/img/sponsors/testmu.png new file mode 100644 index 0000000000000000000000000000000000000000..5603b04faed5e917bd0ea78f1684ba3c7a747718 GIT binary patch literal 5725 zcmd6L_cvT`w6`7vBf5#+iOyGzE?S}l(Pc#RE_x4%8iPa-MvdO0M2kK~8-hsG=msN1 z57FHx>-`7b-|n5Y&YZQ*oO#;bpR#wnfu1HgDU=ik2Zvl+OWhFM_rYaHOa#7LK6VU% z8;O^exepEw1?u00JK$Mn2Ocu|J}~n&@^tVGc=o~`Cmj+ zP#hfEEp2rb{ag3)7-z&_{!ZjqU!N$&bPpwh=N-56}#<+myBe0Py}CX z;uv^rh}3#TaU~cyVn{w9Da9Ujlf}e6!*dW-C;MM~^{wpiodNF@EjJ~|Bc4>$H5V0$ zOw#tzeRcwe&tJxlJUl$4wjnefPa%clo4#H8x52qbj+jrE84Iwdjw^|!q6u>Jq@9*f z(Tx{BW@lyjSYJ~*HU3oTvqw7PCB?-lo0z1Jh)10N$YZ+3R9k(aLL!l2xm|$=9HTk% z)7Z1gN>kL>*jT~d7Gxla8MQu~k+b{PIp0{|;9}|K>Hc!Zi*?fLljbh+A?X2cv(FCX zmseN(7b6Jix`4e!l`|G$Jbe6vQTaUs5j<65|DB)F=jXw(S8nqycV2wSzL}q&Ph^(& zml4uiO?*C@E!)eoxVT7h(e`3JK^GQreU#@uRa0JGcXv#AaAd@9=n7h)R&4k-E{=FB z1#M?C92^|{ZgRF(Nb?ZPwz&Zg1JIeCga@n zmm?pLO}X$nIX3oIx(IC16ZaksY5Um*!rzfA*S@{IT{K|V3Ss~K`}bP=VY-IqW{8pT zRFDT@=+4jo5Lit(l)Dxzab+m&9{#yv5{4}mtxOz=w!>q$Qw|r@DmLV!A;o!#v|%tX z@~Q43q0mWK^5Au&^k*b6i_1`t^et{>|xt zQjGll1guFnDl#L3zCW2Yd4J#Q^x^_FG6K)TxH>x{t1X)i%+2GIk|<)Y`UVC##l@+v zudgpJ3rs4bH42enZw8MaNA~w?bW#j>pRS8Upd*@ia;vHY8yXuQH|Z;$^?KX~89q2T z*!{`6jVXZ@$E3;(*VNQBc8G|8fQ^&$Rejp~_xU9y{SF=7-O5F!rAAGwtG1yxSAQu6 zoZtNZ?N&iJJ~NTNa{f`WQmS;t5AuSNk&y%j zgDH~qI7xmiEW~g2T+(>(fG{B;!R!2wv#+0DBu1uU*0Xx)1mtIyPB8oH<(azY-?opX zYEm&WYin!ywY8MVtV&HGu%4bCQO8lHwspbRuU`|l3c9LR4rxw#*B zjk-zQ{{BEVNeuw>@bIwK1{sBf8H+%n&@xFK5Y*kG7Ie`FB*mQliiO+-XLWz`&H z8%P03Y3Wy#c&x0f02FKj0tq)_1Ox;&3$1=F{yR_*?$cJ+=}!+HJtDiwq>LIG(s`ee zfw{iAz`;>cQsUy`V&mb7`HRJ3WBsJJ_~ZldPZv*}Bq{dlI^3-BZ*mHrO^`_8Fp zX=!C;W%>P#wzjsS-mB`NXX_a#XeD7O$?3)jLdJKKvcA5)N(#R(sjW>O92X@ORnHtT zJ0Cwkas?IZeZ2JqY!DwOG&GcwnHes<7>Ex7x_o4#nZy*|-hMyy>Uer{Yb(m4x?ey1 zka{Z~W?_-wKG#$La8u;0e3&6z%p&FRnei3{)3VZCG9o6$P=-_<-PJv~m9VCX$&?Yb=yLD;IN+Wa%iXxP zlF;gnI}k_VhK}bGWsmXlBCfV!7lKOQ06$J|mmk{O+uLnTl!r~l$HlRg>g9ag+B^>K z)N^yIVv7NEs(4jgQbKCW$H$jHR0ZpLx-20nIZ>hH`sLd|GAl1TJ9|+R#Kpx8J7*cPawVF7L6Bba)PD0+}pT3JK_@-)^K*_ zkN6Ydi~vt1m)Fp#??=Ro?cmwjOfKkbv|Z0)M@Zh#{IPP-PUCdh6fMr>QQl4Ot6LC0 zOKWRp9UUD$O9KN+hp}9RH8Bg+FZYG4EU4RTJ)w9e*{@%}K90ujpeM?W2%8Qt14chc zr#8PNevK-IOwP>2jgIPV4dmtKQWP7;$HWjdG&Ozf=wRO2*=dQmQH0*TdvJZRXQT^z zC^0unLr2FUFONuu16GE0T8S3ZP*FuSG)Pu>Jb6Mpng@X6O-^W7Zd~i7QuSPZ8ke-f?C<&84?zDe~&Epgjf_G^~Mn<0YiG<^(qF>*Fu;c^s28{d7NfPKEOZe%^ zE#oIoRw`>cq2DDt0iLZ|yl_7|jI6rX)zxWfYa>C12U!LO%l%iTNsI(QKR7*jK2G)& z&MZ#{f?nbV#v&#r?*5u7LAai#!`)yZq>;#goa52WdR59CPQz zuKYh?0s=B!0}HUQQV@f}XPP}(4ULS>q~U-{Ej>G;eXyfQJMm||ad!sM=z>)b7nh#8 z=L0cZB?TN35~)<2`*u%*F#Yhbsb33M-T?uc4h|bfoHjTu!N&ssjuU7|rM`F_Tbd3b zgiSo|k8FFDT!k4+Y%E^yyZHU&Gwtzj`o9iq5!|CyH zz?VSqTZrOm&ayio3#DXS?}S@;YK9abu&Sk7ad8?q|X-50WDUwZu2y++1Rnq;9Fk_$=yz#g>=H zZ{6BH4t85;o!s53lFXHu0<^x0#nlYAMy%cu|rB_jeq(yFMa5R;L;PELjx3(x{S zUf$bF1`%65o`zu&M*x4ava+YkuOKmQ6E~aVg=WA9H+Gq6Xb>r0{FXqz_*&C-{c|^X zD;IbV5<}^o;%Gd5e==`6z(-Mn5}MN47@4Fk3v(irI{z|o=9epwh+6ZFANooU08MKo zF*#2!{hs}Nuyk|XJa!ajPeo1$Aa^t({eDIR4vlVUk!c%-pirnf=N~*+dxa=#32rkpDW$2L}gI+bylFa_&PsAdoek z=K}U^fJgj)&#V~GYnL0ZHg{bKaj%-f!e|Q$3Q(;FuZ(!!GtW+p0=BKPY)-l#{AbW( z_VhHcRM+29{v0t_7kFT6E1p?)sF}>d4a{iR6fjNP@&UU=TVTd|;KuP@u3@o8*hf6n znNsdqBP~j&%lInHX*zv*&FO<;!GD}8JI{62HmyB=HaM%7{vi2O$P4gSx{9MrLmEAz zPEl?wpq1<7;=&;&CT4 zoc4*HWIWT!=I(BPXV}F)nl~@bTrGdbOYhZXSr8x0%4Y$*mD+2MRRTP5CT&J=m1d8YKDdm7gZvYES0&r`QY%d z&ro23YC-oq?uTXDqEI+Rb!yYMg$4N4#a|;&S5RWvq2E12sNOv(S_f=u1FFx!gFbq~ zpzbkoAt9l`v9ST5S%dnrAegH=%}f2j1wRI*L3%nJIQGDh5KM8#Q&krifkuhKai?CO zPU9031k317Yd=3fVsi5J;r5fCu3kPqsOa1D2BxOBs!eW3t48MMvvF~AKl@&!ZES@d z%_(f9K0ZE<3SZCq&ow10OXoPXva+(8N5D+2W*UP@R?>L!qJFZ=)YbJ~5{trCO3fmZ zoGseBA7lBOmppd+1M=0ZvnBdO@=HHBtyUT#mp&y)9^EUq?%_LLlckh{}ca1u)h=Y6LVKpd^Q#q7A_?v*f%bY*OZ0h zT0iIJv|U{**SpFijP;_wDD=POf=0Y?^FOma0rK=xA5toEg(l$3?gg&-*d z4haPX&s?)7udc4Hf6a81NhLRMf$ZMi-gpr%jahDUP1Ue#V)mkniUgqA*;-swLwV{P z?0|@OeN^J3ufYhjt$vltT5>r_MMXtsLVIy9aZ>HYkCUc5!t@1E8TnP~)tGo3}*7#ozs2 zXv>&y4>HMcM`LJz*Q&0221kQo42AN;_9A9Jc|!ss*eV*vC6}?nHtY0|Nt<1=3V&rVASz zX+bY$-6z3a_sHxrEj`_~=QRm~gag^0zHkQ0NpcnJ%E`@5U00V}*t*ruhqYv{>xKm( z?b)9J3y&9j-mhG2NK)TcQBh$d%1|5f*TV%`3cSC5*FRAV4_Cy)!wa<3*4ECu*&C`C zD97gi0M%Aiy3oCQYGGjto#$Kk67Nb=h_vtH-B(axPt*BVKLeCbOig`kXrM8zc?xv& zV?V|3ox(}^PYZ1UMomaJJx5W7l)OBV5BSY%#G!x2H7D}Z?a6u>y-vHP_iZvI9FrEp zQjG=DCYhlimH5quo>*Hea6McX1j%!HdTJom@iaLW!g?~70jd+wk^+4a+{{P)w`au5 zCSjoKw2Z~x(%0A5=^hywxw;+;2P(*^kw{sUAkIJ*c)DM}R*7Cz*#GmVh~R90MGb+# zoSmN=LMUD#ZT_xQ84KK@p&<|v5do8J`pPvlG~`!T!|5|Y&w`sY#QRV0+?=JC5Yr3?qW%ZABJ|Aw literal 0 HcmV?d00001 From db5441eba1d4c3bee11dac239a685e3c0630cda5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 19 Jan 2026 20:40:38 +0000 Subject: [PATCH 010/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d3f80fac93..8b338f60d0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* ๐Ÿ”ง Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo). * โฌ† Bump actions/cache from 4 to 5. PR [#14511](https://github.com/fastapi/fastapi/pull/14511) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump actions/upload-artifact from 5 to 6. PR [#14525](https://github.com/fastapi/fastapi/pull/14525) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump actions/download-artifact from 6 to 7. PR [#14526](https://github.com/fastapi/fastapi/pull/14526) by [@dependabot[bot]](https://github.com/apps/dependabot). From 463a3a24d7aee142bede2bcdd0ef542646b1fe3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 19 Jan 2026 12:55:32 -0800 Subject: [PATCH 011/367] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20Requestly=20(#14735)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/sponsors.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index c0bdb15f63..f8085b4523 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -68,6 +68,3 @@ bronze: - url: https://www.testmu.ai/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage title: TestMu AI. The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. img: https://fastapi.tiangolo.com/img/sponsors/testmu.png - - url: https://requestly.com/fastapi - title: All-in-one platform to Test, Mock and Intercept APIs. Built for speed, privacy and offline support. - img: https://fastapi.tiangolo.com/img/sponsors/requestly.png From ad6b2901a6ab9350c55f261b06dfd1dc363e1fde Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 19 Jan 2026 20:56:10 +0000 Subject: [PATCH 012/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8b338f60d0..4cc8bf0188 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* ๐Ÿ”ง Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo). * โฌ† Bump actions/cache from 4 to 5. PR [#14511](https://github.com/fastapi/fastapi/pull/14511) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump actions/upload-artifact from 5 to 6. PR [#14525](https://github.com/fastapi/fastapi/pull/14525) by [@dependabot[bot]](https://github.com/apps/dependabot). From 6afb15c518e7c151c02639b3704424477997da87 Mon Sep 17 00:00:00 2001 From: Kader Miyanyedi <48386782+Kadermiyanyedi@users.noreply.github.com> Date: Tue, 20 Jan 2026 23:34:03 +0300 Subject: [PATCH 013/367] =?UTF-8?q?=F0=9F=8C=90=20Improve=20LLM=20prompt?= =?UTF-8?q?=20for=20Turkish=20translations=20(#14728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tr/llm-prompt.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/tr/llm-prompt.md b/docs/tr/llm-prompt.md index 297b0a0e6c..2ba922ec59 100644 --- a/docs/tr/llm-prompt.md +++ b/docs/tr/llm-prompt.md @@ -4,10 +4,16 @@ Translate to Turkish (Tรผrkรงe). Language code: tr. +### Core principle + +Don't translate word-by-word. Rewrite naturally in Turkish as if writing the doc from scratch. Preserve meaning, but prioritize fluency over literal accuracy. + ### Grammar and tone - Use instructional Turkish, consistent with existing Turkish docs. -- Use imperative/guide language when appropriate (e.g. โ€œaรงalฤฑmโ€, โ€œgidinโ€, โ€œkopyalayalฤฑmโ€). +- Use imperative/guide language (e.g. "aรงalฤฑm", "gidin", "kopyalayalฤฑm", "bir bakalฤฑm"). +- Avoid filler words and overly long sentences. +- Ensure sentences make sense in Turkish context โ€” adjust structure, conjunctions, and verb forms as needed for natural flow (e.g. use "Ancak" instead of "Ve" when connecting contrasting sentences, use "-maktadฤฑr/-mektedir" for formal statements). ### Headings @@ -15,13 +21,23 @@ Language code: tr. ### Quotes -- Alฤฑntฤฑ stili mevcut Tรผrkรงe dokรผmanlarla tutarlฤฑ tutun (genellikle metin iรงinde ASCII tฤฑrnak iลŸaretleri kullanฤฑlฤฑr). -- Satฤฑr iรงi kod, kod bloklarฤฑ, URL'ler veya dosya yollarฤฑ iรงindeki tฤฑrnak iลŸaretlerini asla deฤŸiลŸtirmeyin. +- Keep quote style consistent with existing Turkish docs (typically ASCII quotes in text). +- Never modify quotes inside inline code, code blocks, URLs, or file paths. ### Ellipsis -- รœรง nokta (...) stili mevcut Tรผrkรงe dokรผmanlarla tutarlฤฑ tutun. -- Kod, URL veya CLI รถrneklerindeki `...` ifadesini asla deฤŸiลŸtirmeyin. +- Keep ellipsis style (`...`) consistent with existing Turkish docs. +- Never modify `...` in code, URLs, or CLI examples. + +### Consistency + +- Use the same translation for the same term throughout the document. +- If you translate a concept one way, keep it consistent across all occurrences. + +### Links and references + +- Never modify link syntax like `{.internal-link target=_blank}`. +- Keep markdown link structure intact: `[text](url){.internal-link}`. ### Preferred translations / glossary From 7443bc7a4684b3d1754c0ab59bb9e878bac96a6b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 20 Jan 2026 20:34:36 +0000 Subject: [PATCH 014/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4cc8bf0188..8d97900394 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). * ๐ŸŒ Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n). * ๐ŸŒ Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo). From 0ab68a762f5fbf86777a45afc8df7059e07a0a7d Mon Sep 17 00:00:00 2001 From: "hy.lee" Date: Wed, 21 Jan 2026 05:37:04 +0900 Subject: [PATCH 015/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20Korean=20LLM=20?= =?UTF-8?q?prompt=20(#14740)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ko/llm-prompt.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ko/llm-prompt.md b/docs/ko/llm-prompt.md index df807c9496..533160eab9 100644 --- a/docs/ko/llm-prompt.md +++ b/docs/ko/llm-prompt.md @@ -8,6 +8,7 @@ Language code: ko. - Use polite, instructional Korean (e.g. ํ•ฉ๋‹ˆ๋‹ค/ํ•˜์„ธ์š” style). - Keep the tone consistent with the existing Korean FastAPI docs. +- Do not translate โ€œYouโ€ literally as โ€œ๋‹น์‹ โ€. Use โ€œ์—ฌ๋Ÿฌ๋ถ„โ€ where appropriate, or omit the subject if it sounds more natural in Korean. ### Headings From 7faa7089d665ad9e47a73d4a55457a23ba5cf643 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 20 Jan 2026 20:37:28 +0000 Subject: [PATCH 016/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8d97900394..7c5460f1df 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). * ๐ŸŒ Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). * ๐ŸŒ Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n). * ๐ŸŒ Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo). From 2d459e4845e8de9e080039d8f3ab2f1fd2e774a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 20 Jan 2026 12:40:17 -0800 Subject: [PATCH 017/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-outdated)=20(#14724)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/pt/docs/_llm-test.md | 48 +++++------ .../path-operation-advanced-configuration.md | 64 ++++---------- docs/pt/docs/advanced/settings.md | 44 ---------- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 22 ++--- .../docs/how-to/separate-openapi-schemas.md | 8 +- docs/pt/docs/index.md | 86 ++++++++++--------- docs/pt/docs/tutorial/bigger-applications.md | 84 +++++++++--------- docs/pt/docs/tutorial/body-updates.md | 42 +++------ docs/pt/docs/tutorial/body.md | 18 ++-- docs/pt/docs/tutorial/extra-models.md | 26 ++---- .../tutorial/query-params-str-validations.md | 34 +++----- docs/pt/docs/tutorial/response-model.md | 14 --- docs/pt/docs/tutorial/schema-extra-example.md | 36 ++------ 13 files changed, 188 insertions(+), 338 deletions(-) diff --git a/docs/pt/docs/_llm-test.md b/docs/pt/docs/_llm-test.md index 3da5e8a71d..b59292f47c 100644 --- a/docs/pt/docs/_llm-test.md +++ b/docs/pt/docs/_llm-test.md @@ -1,8 +1,8 @@ # Arquivo de teste de LLM { #llm-test-file } -Este documento testa se o LLM, que traduz a documentaรงรฃo, entende o `general_prompt` em `scripts/translate.py` e o prompt especรญfico do idioma em `docs/{language code}/llm-prompt.md`. O prompt especรญfico do idioma รฉ anexado ao `general_prompt`. +Este documento testa se o LLM, que traduz a documentaรงรฃo, entende o `general_prompt` em `scripts/translate.py` e o prompt especรญfico do idioma em `docs/{language code}/llm-prompt.md`. O prompt especรญfico do idioma รฉ anexado ao `general_prompt`. -Os testes adicionados aqui serรฃo vistos por todos os autores dos prompts especรญficos de idioma. +Os testes adicionados aqui serรฃo vistos por todos os designers dos prompts especรญficos de idioma. Use da seguinte forma: @@ -23,7 +23,7 @@ Este รฉ um trecho de cรณdigo: `foo`. E este รฉ outro trecho de cรณdigo: `bar`. E //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo O conteรบdo dos trechos de cรณdigo deve ser deixado como estรก. @@ -45,9 +45,9 @@ O LLM provavelmente vai traduzir isso errado. O interessante รฉ apenas se ele ma //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo -O autor do prompt pode escolher se deseja converter aspas neutras em aspas tipogrรกficas. Tambรฉm รฉ aceitรกvel deixรก-las como estรฃo. +O designer do prompt pode escolher se quer converter aspas neutras em aspas tipogrรกficas. Tambรฉm รฉ aceitรกvel deixรก-las como estรฃo. Veja, por exemplo, a seรงรฃo `### Quotes` em `docs/de/llm-prompt.md`. @@ -67,7 +67,7 @@ Pesado: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you ha //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo ... No entanto, as aspas dentro de trechos de cรณdigo devem permanecer como estรฃo. @@ -95,24 +95,24 @@ $ fastapi run GTD -* lt -* XWT -* PSGI +* GTD +* lt +* XWT +* PSGI ### O abbr fornece uma explicaรงรฃo { #the-abbr-gives-an-explanation } @@ -209,12 +209,12 @@ Aqui estรฃo algumas coisas envolvidas em elementos HTML "abbr" (algumas sรฃo inv ### O abbr fornece uma frase completa e uma explicaรงรฃo { #the-abbr-gives-a-full-phrase-and-an-explanation } -* MDN -* I/O. +* MDN +* I/O. //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo Os atributos "title" dos elementos "abbr" sรฃo traduzidos seguindo algumas instruรงรตes especรญficas. @@ -228,7 +228,7 @@ Veja a seรงรฃo `### HTML abbr elements` no prompt geral em `scripts/translate.py //// tab | Teste -### Desenvolver uma aplicaรงรฃo web - um tutorial { #develop-a-webapp-a-tutorial } +### Desenvolver uma webapp - um tutorial { #develop-a-webapp-a-tutorial } Olรก. @@ -242,7 +242,7 @@ Olรก novamente. //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo A รบnica regra rรญgida para tรญtulos รฉ que o LLM deixe a parte do hash dentro de chaves inalterada, o que garante que os links nรฃo quebrem. @@ -494,9 +494,9 @@ Para algumas instruรงรตes especรญficas do idioma, veja, por exemplo, a seรงรฃo ` //// -//// tab | Informaรงรตes +//// tab | Informaรงรฃo -Esta รฉ uma lista nรฃo completa e nรฃo normativa de termos (principalmente) tรฉcnicos vistos na documentaรงรฃo. Pode ser รบtil para o autor do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa traduรงรฃo para uma traduรงรฃo subรณtima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma. +Esta รฉ uma lista nรฃo completa e nรฃo normativa de termos (principalmente) tรฉcnicos vistos na documentaรงรฃo. Pode ser รบtil para o designer do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa traduรงรฃo para uma traduรงรฃo subรณtima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma. Veja, por exemplo, a seรงรฃo `### List of English terms and their preferred German translations` em `docs/de/llm-prompt.md`. diff --git a/docs/pt/docs/advanced/path-operation-advanced-configuration.md b/docs/pt/docs/advanced/path-operation-advanced-configuration.md index e1c3e5ab89..b3af116a28 100644 --- a/docs/pt/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/pt/docs/advanced/path-operation-advanced-configuration.md @@ -10,7 +10,7 @@ Se vocรช nรฃo รฉ um "especialista" no OpenAPI, vocรช provavelmente nรฃo precisa Vocรช pode definir o `operationId` do OpenAPI que serรก utilizado na sua *operaรงรฃo de rota* com o parรขmetro `operation_id`. -Vocรช precisa ter certeza que ele รฉ รบnico para cada operaรงรฃo. +Vocรช deveria ter certeza que ele รฉ รบnico para cada operaรงรฃo. {* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} @@ -18,13 +18,13 @@ Vocรช precisa ter certeza que ele รฉ รบnico para cada operaรงรฃo. Se vocรช quiser utilizar o nome das funรงรตes da sua API como `operationId`s, vocรช pode iterar sobre todos esses nomes e sobrescrever o `operation_id` em cada *operaรงรฃo de rota* utilizando o `APIRoute.name` dela. -Vocรช deve fazer isso depois de adicionar todas as suas *operaรงรตes de rota*. +Vocรช deveria fazer isso depois de adicionar todas as suas *operaรงรตes de rota*. {* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} /// tip | Dica -Se vocรช chamar `app.openapi()` manualmente, os `operationId`s devem ser atualizados antes dessa chamada. +Se vocรช chamar `app.openapi()` manualmente, vocรช deveria atualizar os `operationId`s antes dessa chamada. /// @@ -44,11 +44,11 @@ Para excluir uma *operaรงรฃo de rota* do esquema OpenAPI gerado (e por consequรช ## Descriรงรฃo avanรงada a partir de docstring { #advanced-description-from-docstring } -Vocรช pode limitar as linhas utilizadas a partir de uma docstring de uma *funรงรฃo de operaรงรฃo de rota* para o OpenAPI. +Vocรช pode limitar as linhas utilizadas a partir da docstring de uma *funรงรฃo de operaรงรฃo de rota* para o OpenAPI. -Adicionar um `\f` (um caractere de escape para alimentaรงรฃo de formulรกrio) faz com que o **FastAPI** restrinja a saรญda utilizada pelo OpenAPI atรฉ esse ponto. +Adicionar um `\f` (um caractere de escape para "form feed") faz com que o **FastAPI** trunque a saรญda usada para o OpenAPI atรฉ esse ponto. -Ele nรฃo serรก mostrado na documentaรงรฃo, mas outras ferramentas (como o Sphinx) serรฃo capazes de utilizar o resto do texto. +Ele nรฃo serรก mostrado na documentaรงรฃo, mas outras ferramentas (como o Sphinx) serรฃo capazes de utilizar o resto. {* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} @@ -131,70 +131,38 @@ E se vocรช olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua AP ### Esquema de *operaรงรฃo de rota* do OpenAPI personalizado { #custom-openapi-path-operation-schema } -O dicionรกrio em `openapi_extra` vai ter todos os seus nรญveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operaรงรฃo de rota*. +O dicionรกrio em `openapi_extra` vai ser mesclado profundamente com o esquema OpenAPI gerado automaticamente para a *operaรงรฃo de rota*. -Entรฃo, vocรช pode adicionar dados extras para o esquema gerado automaticamente. +Entรฃo, vocรช pode adicionar dados extras ao esquema gerado automaticamente. -Por exemplo, vocรช poderia optar por ler e validar a requisiรงรฃo com seu prรณprio cรณdigo, sem utilizar funcionalidades automatizadas do FastAPI com o Pydantic, mas vocรช ainda pode quere definir a requisiรงรฃo no esquema OpenAPI. +Por exemplo, vocรช poderia decidir ler e validar a requisiรงรฃo com seu prรณprio cรณdigo, sem usar as funcionalidades automรกticas do FastAPI com o Pydantic, mas ainda assim querer definir a requisiรงรฃo no esquema OpenAPI. Vocรช pode fazer isso com `openapi_extra`: {* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} -Nesse exemplo, nรณs nรฃo declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisiรงรฃo nรฃo estรก nem mesmo analisado como JSON, ele รฉ lido diretamente como `bytes` e a funรงรฃo `magic_data_reader()` seria a responsรกvel por analisar ele de alguma forma. +Nesse exemplo, nรณs nรฃo declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisiรงรฃo nรฃo estรก nem mesmo analisado como JSON, ele รฉ lido diretamente como `bytes`, e a funรงรฃo `magic_data_reader()` seria a responsรกvel por analisar ele de alguma forma. De toda forma, nรณs podemos declarar o esquema esperado para o corpo da requisiรงรฃo. ### Tipo de conteรบdo do OpenAPI personalizado { #custom-openapi-content-type } -Utilizando esse mesmo truque, vocรช pode utilizar um modelo Pydantic para definir o JSON Schema que รฉ entรฃo incluรญdo na seรงรฃo do esquema personalizado do OpenAPI na *operaรงรฃo de rota*. +Utilizando esse mesmo truque, vocรช pode usar um modelo Pydantic para definir o JSON Schema que รฉ entรฃo incluรญdo na seรงรฃo do esquema personalizado do OpenAPI na *operaรงรฃo de rota*. -E vocรช pode fazer isso atรฉ mesmo quando os dados da requisiรงรฃo nรฃo seguem o formato JSON. +E vocรช pode fazer isso atรฉ mesmo quando o tipo de dados na requisiรงรฃo nรฃo รฉ JSON. -Por exemplo, nesta aplicaรงรฃo nรณs nรฃo usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validaรงรฃo automรกtica do JSON. Na verdade, estamos declarando o tipo do conteรบdo da requisiรงรฃo como YAML, em vez de JSON: - -//// tab | Pydantic v2 +Por exemplo, nesta aplicaรงรฃo nรณs nรฃo usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validaรงรฃo automรกtica para JSON. Na verdade, estamos declarando o tipo de conteรบdo da requisiรงรฃo como YAML, em vez de JSON: {* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *} - -//// - -/// info | Informaรงรฃo - -Na versรฃo 1 do Pydantic, o mรฉtodo para obter o JSON Schema de um modelo รฉ `Item.schema()`, na versรฃo 2 do Pydantic, o mรฉtodo รฉ `Item.model_json_schema()`. - -/// - -Entretanto, mesmo que nรฃo utilizemos a funcionalidade integrada por padrรฃo, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber no formato YAML. +Entretanto, mesmo que nรฃo utilizemos a funcionalidade integrada por padrรฃo, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber em YAML. -Entรฃo utilizamos a requisiรงรฃo diretamente, e extraรญmos o corpo como `bytes`. Isso significa que o FastAPI nรฃo vai sequer tentar analisar o corpo da requisiรงรฃo como JSON. +Entรฃo utilizamos a requisiรงรฃo diretamente e extraรญmos o corpo como `bytes`. Isso significa que o FastAPI nรฃo vai sequer tentar analisar o payload da requisiรงรฃo como JSON. -E entรฃo no nosso cรณdigo, nรณs analisamos o conteรบdo YAML diretamente, e estamos utilizando o mesmo modelo Pydantic para validar o conteรบdo YAML: - -//// tab | Pydantic v2 +E entรฃo no nosso cรณdigo, nรณs analisamos o conteรบdo YAML diretamente e, em seguida, estamos usando novamente o mesmo modelo Pydantic para validar o conteรบdo YAML: {* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *} - -//// - -/// info | Informaรงรฃo - -Na versรฃo 1 do Pydantic, o mรฉtodo para analisar e validar um objeto era `Item.parse_obj()`, na versรฃo 2 do Pydantic, o mรฉtodo รฉ chamado de `Item.model_validate()`. - -/// - /// tip | Dica Aqui reutilizamos o mesmo modelo do Pydantic. diff --git a/docs/pt/docs/advanced/settings.md b/docs/pt/docs/advanced/settings.md index 6f5b7feae7..28411269bb 100644 --- a/docs/pt/docs/advanced/settings.md +++ b/docs/pt/docs/advanced/settings.md @@ -46,12 +46,6 @@ $ pip install "fastapi[all]" -/// info | Informaรงรฃo - -No Pydantic v1 ele vinha incluรญdo no pacote principal. Agora รฉ distribuรญdo como um pacote independente para que vocรช possa optar por instalรก-lo ou nรฃo, caso nรฃo precise dessa funcionalidade. - -/// - ### Criar o objeto `Settings` { #create-the-settings-object } Importe `BaseSettings` do Pydantic e crie uma subclasse, muito parecido com um modelo do Pydantic. @@ -60,24 +54,8 @@ Da mesma forma que com modelos do Pydantic, vocรช declara atributos de classe co Vocรช pode usar as mesmas funcionalidades e ferramentas de validaรงรฃo que usa em modelos do Pydantic, como diferentes tipos de dados e validaรงรตes adicionais com `Field()`. -//// tab | Pydantic v2 - {* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} -//// - -//// tab | Pydantic v1 - -/// info | Informaรงรฃo - -No Pydantic v1 vocรช importaria `BaseSettings` diretamente de `pydantic` em vez de `pydantic_settings`. - -/// - -{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *} - -//// - /// tip | Dica Se vocรช quer algo rรกpido para copiar e colar, nรฃo use este exemplo, use o รบltimo abaixo. @@ -215,8 +193,6 @@ APP_NAME="ChimichangApp" E entรฃo atualizar seu `config.py` com: -//// tab | Pydantic v2 - {* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} /// tip | Dica @@ -225,26 +201,6 @@ O atributo `model_config` รฉ usado apenas para configuraรงรฃo do Pydantic. Vocรช /// -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *} - -/// tip | Dica - -A classe `Config` รฉ usada apenas para configuraรงรฃo do Pydantic. Vocรช pode ler mais em Pydantic Model Config. - -/// - -//// - -/// info | Informaรงรฃo - -Na versรฃo 1 do Pydantic a configuraรงรฃo era feita em uma classe interna `Config`, na versรฃo 2 do Pydantic รฉ feita em um atributo `model_config`. Esse atributo recebe um `dict`, e para ter autocompletar e erros inline vocรช pode importar e usar `SettingsConfigDict` para definir esse `dict`. - -/// - Aqui definimos a configuraรงรฃo `env_file` dentro da sua classe `Settings` do Pydantic e definimos o valor como o nome do arquivo dotenv que queremos usar. ### Criando o `Settings` apenas uma vez com `lru_cache` { #creating-the-settings-only-once-with-lru-cache } diff --git a/docs/pt/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/pt/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 2a2659a03d..0995e10285 100644 --- a/docs/pt/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/pt/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -2,21 +2,23 @@ Se vocรช tem uma aplicaรงรฃo FastAPI antiga, pode estar usando o Pydantic versรฃo 1. -O FastAPI tem suporte ao Pydantic v1 ou v2 desde a versรฃo 0.100.0. +O FastAPI versรฃo 0.100.0 tinha suporte ao Pydantic v1 ou v2. Ele usaria aquele que vocรช tivesse instalado. -Se vocรช tiver o Pydantic v2 instalado, ele serรก utilizado. Se, em vez disso, tiver o Pydantic v1, serรก ele que serรก utilizado. +O FastAPI versรฃo 0.119.0 introduziu suporte parcial ao Pydantic v1 a partir de dentro do Pydantic v2 (como `pydantic.v1`), para facilitar a migraรงรฃo para o v2. -O Pydantic v1 estรก agora descontinuado e o suporte a ele serรก removido nas prรณximas versรตes do FastAPI, vocรช deveria migrar para o Pydantic v2. Assim, vocรช terรก as funcionalidades, melhorias e correรงรตes mais recentes. +O FastAPI 0.126.0 removeu o suporte ao Pydantic v1, enquanto ainda oferece suporte a `pydantic.v1` por mais algum tempo. /// warning | Atenรงรฃo -Alรฉm disso, a equipe do Pydantic interrompeu o suporte ao Pydantic v1 para as versรตes mais recentes do Python, a partir do **Python 3.14**. +A equipe do Pydantic interrompeu o suporte ao Pydantic v1 para as versรตes mais recentes do Python, a partir do **Python 3.14**. + +Isso inclui `pydantic.v1`, que nรฃo รฉ mais suportado no Python 3.14 e superiores. Se quiser usar as funcionalidades mais recentes do Python, vocรช precisarรก garantir que usa o Pydantic v2. /// -Se vocรช tem uma aplicaรงรฃo FastAPI antiga com Pydantic v1, aqui vou mostrar como migrรก-la para o Pydantic v2 e as **novas funcionalidades no FastAPI 0.119.0** para ajudar em uma migraรงรฃo gradual. +Se vocรช tem uma aplicaรงรฃo FastAPI antiga com Pydantic v1, aqui vou mostrar como migrรก-la para o Pydantic v2, e as **funcionalidades no FastAPI 0.119.0** para ajudar em uma migraรงรฃo gradual. ## Guia oficial { #official-guide } @@ -44,7 +46,7 @@ Depois disso, vocรช pode rodar os testes e verificar se tudo funciona. Se funcio ## Pydantic v1 no v2 { #pydantic-v1-in-v2 } -O Pydantic v2 inclui tudo do Pydantic v1 como um submรณdulo `pydantic.v1`. +O Pydantic v2 inclui tudo do Pydantic v1 como um submรณdulo `pydantic.v1`. Mas isso nรฃo รฉ mais suportado em versรตes acima do Python 3.13. Isso significa que vocรช pode instalar a versรฃo mais recente do Pydantic v2 e importar e usar os componentes antigos do Pydantic v1 a partir desse submรณdulo, como se tivesse o Pydantic v1 antigo instalado. @@ -66,7 +68,7 @@ Tenha em mente que, como a equipe do Pydantic nรฃo oferece mais suporte ao Pydan ### Pydantic v1 e v2 na mesma aplicaรงรฃo { #pydantic-v1-and-v2-on-the-same-app } -Nรฃo รฉ suportado pelo Pydantic ter um modelo do Pydantic v2 com campos prรณprios definidos como modelos do Pydantic v1, ou vice-versa. +Nรฃo รฉ **suportado** pelo Pydantic ter um modelo do Pydantic v2 com campos prรณprios definidos como modelos do Pydantic v1, ou vice-versa. ```mermaid graph TB @@ -86,7 +88,7 @@ graph TB style V2Field fill:#f9fff3 ``` -...but, you can have separated models using Pydantic v1 and v2 in the same app. +...mas, vocรช pode ter modelos separados usando Pydantic v1 e v2 na mesma aplicaรงรฃo. ```mermaid graph TB @@ -106,7 +108,7 @@ graph TB style V2Field fill:#f9fff3 ``` -Em alguns casos, รฉ atรฉ possรญvel ter modelos Pydantic v1 e v2 na mesma operaรงรฃo de rota na sua aplicaรงรฃo FastAPI: +Em alguns casos, รฉ atรฉ possรญvel ter modelos Pydantic v1 e v2 na mesma **operaรงรฃo de rota** na sua aplicaรงรฃo FastAPI: {* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} @@ -122,7 +124,7 @@ Se vocรช precisar usar algumas das ferramentas especรญficas do FastAPI para par /// tip | Dica -Primeiro tente com o `bump-pydantic`; se seus testes passarem e isso funcionar, entรฃo vocรช concluiu tudo com um รบnico comando. โœจ +Primeiro tente com o `bump-pydantic`, se seus testes passarem e isso funcionar, entรฃo vocรช concluiu tudo com um รบnico comando. โœจ /// diff --git a/docs/pt/docs/how-to/separate-openapi-schemas.md b/docs/pt/docs/how-to/separate-openapi-schemas.md index 8855934fd9..f757025a09 100644 --- a/docs/pt/docs/how-to/separate-openapi-schemas.md +++ b/docs/pt/docs/how-to/separate-openapi-schemas.md @@ -1,8 +1,8 @@ # Esquemas OpenAPI Separados para Entrada e Saรญda ou Nรฃo { #separate-openapi-schemas-for-input-and-output-or-not } -Ao usar **Pydantic v2**, o OpenAPI gerado รฉ um pouco mais exato e **correto** do que antes. ๐Ÿ˜Ž +Desde que o **Pydantic v2** foi lanรงado, o OpenAPI gerado รฉ um pouco mais exato e **correto** do que antes. ๐Ÿ˜Ž -Inclusive, em alguns casos, ele terรก atรฉ **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saรญda, dependendo se eles possuem **valores padrรฃo**. +De fato, em alguns casos, ele terรก atรฉ **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saรญda, dependendo se eles possuem **valores padrรฃo**. Vamos ver como isso funciona e como alterar se for necessรกrio. @@ -95,10 +95,8 @@ O suporte para `separate_input_output_schemas` foi adicionado no FastAPI `0.102. ### Mesmo Esquema para Modelos de Entrada e Saรญda na Documentaรงรฃo { #same-schema-for-input-and-output-models-in-docs } -E agora haverรก um รบnico esquema para entrada e saรญda para o modelo, apenas `Item`, e `description` **nรฃo serรก obrigatรณrio**: +E agora haverรก um รบnico esquema para entrada e saรญda para o modelo, apenas `Item`, e ele terรก `description` como **nรฃo obrigatรณrio**:
- -Esse รฉ o mesmo comportamento do Pydantic v1. ๐Ÿค“ diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index 0428c3a798..4e3be586da 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -40,8 +40,8 @@ Os recursos chave sรฃo: * **Rรกpido**: alta performance, equivalente a **NodeJS** e **Go** (graรงas ao Starlette e Pydantic). [Um dos frameworks mais rรกpidos disponรญveis](#performance). * **Rรกpido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. * * **Poucos bugs**: Reduz cerca de 40% de erros induzidos por humanos (desenvolvedores). * -* **Intuitivo**: Grande suporte a _IDEs_. Preenchimento automรกtico em todos os lugares. Menos tempo debugando. -* **Fรกcil**: Projetado para ser fรกcil de aprender e usar. Menos tempo lendo documentaรงรฃo. +* **Intuitivo**: Grande suporte a editores. Completaรงรฃo em todos os lugares. Menos tempo debugando. +* **Fรกcil**: Projetado para ser fรกcil de aprender e usar. Menos tempo lendo docs. * **Enxuto**: Minimize duplicaรงรฃo de cรณdigo. Mรบltiplas funcionalidades para cada declaraรงรฃo de parรขmetro. Menos bugs. * **Robusto**: Tenha cรณdigo pronto para produรงรฃo. E com documentaรงรฃo interativa automรกtica. * **Baseado em padrรตes**: Baseado em (e totalmente compatรญvel com) os padrรตes abertos para APIs: OpenAPI (anteriormente conhecido como Swagger) e JSON Schema. @@ -73,7 +73,7 @@ Os recursos chave sรฃo: ## Opiniรตes { #opinions } -"*[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviรงos _Machine Learning_ na Microsoft**. Alguns deles estรฃo sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**.*" +"_[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviรงos ML na Microsoft**. Alguns deles estรฃo sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**._"
Kabir Khan - Microsoft (ref)
@@ -91,39 +91,45 @@ Os recursos chave sรฃo: --- -"*Estou extremamente entusiasmado com o **FastAPI**. ร‰ tรฃo divertido!*" +"_Estou muito entusiasmado com o **FastAPI**. ร‰ tรฃo divertido!_" -
Brian Okken - Python Bytes podcaster (ref)
+
Brian Okken - Python Bytes apresentador do podcast (ref)
--- -"*Honestamente, o que vocรช construiu parece super sรณlido e rebuscado. De muitas formas, eu queria que o **Hug** fosse assim - รฉ realmente inspirador ver alguรฉm que construiu ele.*" +"_Honestamente, o que vocรช construiu parece super sรณlido e refinado. De muitas formas, รฉ o que eu queria que o **Hug** fosse - รฉ realmente inspirador ver alguรฉm construir isso._"
Timothy Crosley - criador doHug (ref)
--- -"*Se vocรช estรก procurando aprender um **_framework_ moderno** para construir aplicaรงรตes _REST_, dรช uma olhada no **FastAPI** [...] ร‰ rรกpido, fรกcil de usar e fรกcil de aprender [...]*" +"_Se vocรช estรก procurando aprender um **framework moderno** para construir APIs REST, dรช uma olhada no **FastAPI** [...] ร‰ rรกpido, fรกcil de usar e fรกcil de aprender [...]_" -"*Nรณs trocamos nossas **APIs** por **FastAPI** [...] Acredito que vocรชs gostarรฃo dele [...]*" +"_Nรณs trocamos nossas **APIs** por **FastAPI** [...] Acredito que vocรช gostarรก dele [...]_"
Ines Montani - Matthew Honnibal - fundadores da Explosion AI - criadores da spaCy (ref) - (ref)
--- -"_Se alguรฉm estiver procurando construir uma API Python para produรงรฃo, eu recomendaria fortemente o **FastAPI**. Ele รฉ **lindamente projetado**, **simples de usar** e **altamente escalรกvel**. Ele se tornou um **componente chave** para a nossa estratรฉgia API first de desenvolvimento e estรก impulsionando diversas automaรงรตes e serviรงos, como o nosso Virtual TAC Engineer._" +"_Se alguรฉm estiver procurando construir uma API Python para produรงรฃo, eu recomendaria fortemente o **FastAPI**. Ele รฉ **lindamente projetado**, **simples de usar** e **altamente escalรกvel**, e se tornou um **componente chave** para a nossa estratรฉgia de desenvolvimento API first, impulsionando diversas automaรงรตes e serviรงos, como o nosso Virtual TAC Engineer._"
Deon Pillsbury - Cisco (ref)
--- +## Mini documentรกrio do FastAPI { #fastapi-mini-documentary } + +Hรก um mini documentรกrio do FastAPI lanรงado no fim de 2025, vocรช pode assisti-lo online: + +FastAPI Mini Documentary + ## **Typer**, o FastAPI das interfaces de linhas de comando { #typer-the-fastapi-of-clis } -Se vocรช estiver construindo uma aplicaรงรฃo CLI para ser utilizada em um terminal ao invรฉs de uma aplicaรงรฃo web, dรช uma olhada no **Typer**. +Se vocรช estiver construindo uma aplicaรงรฃo CLI para ser utilizada no terminal ao invรฉs de uma API web, dรช uma olhada no **Typer**. -**Typer** รฉ o irmรฃo menor do FastAPI. E seu propรณsito รฉ ser o **FastAPI das _CLIs_**. โŒจ๏ธ ๐Ÿš€ +**Typer** รฉ o irmรฃo menor do FastAPI. E seu propรณsito รฉ ser o **FastAPI das CLIs**. โŒจ๏ธ ๐Ÿš€ ## Requisitos { #requirements } @@ -255,10 +261,10 @@ Vocรช verรก a resposta JSON como: Vocรช acabou de criar uma API que: -* Recebe requisiรงรตes HTTP nas _rotas_ `/` e `/items/{item_id}`. -* Ambas _rotas_ fazem operaรงรตes `GET` (tambรฉm conhecido como _mรฉtodos_ HTTP). -* A _rota_ `/items/{item_id}` tem um _parรขmetro de rota_ `item_id` que deve ser um `int`. -* A _rota_ `/items/{item_id}` tem um _parรขmetro query_ `q` `str` opcional. +* Recebe requisiรงรตes HTTP nos _paths_ `/` e `/items/{item_id}`. +* Ambos _paths_ fazem operaรงรตes `GET` (tambรฉm conhecido como _mรฉtodos_ HTTP). +* O _path_ `/items/{item_id}` tem um _parรขmetro de path_ `item_id` que deve ser um `int`. +* O _path_ `/items/{item_id}` tem um _parรขmetro query_ `q` `str` opcional. ### Documentaรงรฃo Interativa da API { #interactive-api-docs } @@ -278,7 +284,7 @@ Vocรช verรก a documentaรงรฃo automรกtica alternativa (fornecida por http://127.0.0.1:8000/redoc. -* A documentaรงรฃo alternativa tambรฉm irรก refletir o novo parรขmetro da _query_ e o corpo: +* A documentaรงรฃo alternativa tambรฉm irรก refletir o novo parรขmetro query e o corpo: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) @@ -368,15 +374,15 @@ item: Item * Validaรงรฃo de dados: * Erros automรกticos e claros quando o dado รฉ invรกlido. * Validaรงรฃo atรฉ para objetos JSON profundamente aninhados. -* Conversรฃo de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler: +* Conversรฃo de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler: * JSON. - * Parรขmetros de rota. - * Parรขmetros de _query_ . - * _Cookies_. + * Parรขmetros de path. + * Parรขmetros query. + * Cookies. * Cabeรงalhos. * Formulรกrios. * Arquivos. -* Conversรฃo de dados de saรญda de tipos e dados Python para dados de rede (como JSON): +* Conversรฃo de dados de saรญda: convertendo de tipos e dados Python para dados de rede (como JSON): * Converte tipos Python (`str`, `int`, `float`, `bool`, `list` etc). * Objetos `datetime`. * Objetos `UUID`. @@ -390,17 +396,17 @@ item: Item Voltando ao cรณdigo do exemplo anterior, **FastAPI** irรก: -* Validar que existe um `item_id` na rota para requisiรงรตes `GET` e `PUT`. +* Validar que existe um `item_id` no path para requisiรงรตes `GET` e `PUT`. * Validar que `item_id` รฉ do tipo `int` para requisiรงรตes `GET` e `PUT`. - * Se nรฃo รฉ validado, o cliente verรก um รบtil, claro erro. -* Verificar se existe um parรขmetro de _query_ opcional nomeado como `q` (como em `http://127.0.0.1:8000/items/foo?q=somequery`) para requisiรงรตes `GET`. + * Se nรฃo for, o cliente verรก um erro รบtil e claro. +* Verificar se existe um parรขmetro query opcional nomeado como `q` (como em `http://127.0.0.1:8000/items/foo?q=somequery`) para requisiรงรตes `GET`. * Como o parรขmetro `q` รฉ declarado com `= None`, ele รฉ opcional. - * Sem o `None` ele poderia ser obrigatรณrio (como o corpo no caso de `PUT`). + * Sem o `None` ele seria obrigatรณrio (como o corpo no caso de `PUT`). * Para requisiรงรตes `PUT` para `/items/{item_id}`, lerรก o corpo como JSON: * Verifica que tem um atributo obrigatรณrio `name` que deve ser `str`. - * Verifica que tem um atributo obrigatรณrio `price` que deve ser `float`. - * Verifica que tem an atributo opcional `is_offer`, que deve ser `bool`, se presente. - * Tudo isso tambรฉm funciona para objetos JSON profundamente aninhados. + * Verifica que tem um atributo obrigatรณrio `price` que tem que ser um `float`. + * Verifica que tem um atributo opcional `is_offer`, que deve ser um `bool`, se presente. + * Tudo isso tambรฉm funcionaria para objetos JSON profundamente aninhados. * Converter de e para JSON automaticamente. * Documentar tudo com OpenAPI, que poderรก ser usado por: * Sistemas de documentaรงรฃo interativos. @@ -409,7 +415,7 @@ Voltando ao cรณdigo do exemplo anterior, **FastAPI** irรก: --- -Nรณs apenas arranhamos a superfรญcie, mas vocรช jรก tem idรฉia de como tudo funciona. +Nรณs apenas arranhamos a superfรญcie, mas vocรช jรก tem ideia de como tudo funciona. Experimente mudar a seguinte linha: @@ -437,22 +443,22 @@ Para um exemplo mais completo incluindo mais recursos, veja Injeรงรฃo de Dependรชncia**. -* Seguranรงa e autenticaรงรฃo, incluindo suporte para **OAuth2** com autenticaรงรฃo **JWT tokens** e **HTTP Basic**. +* Declaraรงรฃo de **parรขmetros** de diferentes lugares como: **cabeรงalhos**, **cookies**, **campos de formulรกrios** e **arquivos**. +* Como configurar **limitaรงรตes de validaรงรฃo** como `maximum_length` ou `regex`. +* Um poderoso e fรกcil de usar sistema de **Injeรงรฃo de Dependรชncia**. +* Seguranรงa e autenticaรงรฃo, incluindo suporte para **OAuth2** com autenticaรงรฃo com **JWT tokens** e **HTTP Basic**. * Tรฉcnicas mais avanรงadas (mas igualmente fรกceis) para declaraรงรฃo de **modelos JSON profundamente aninhados** (graรงas ao Pydantic). * Integraรงรตes **GraphQL** com o Strawberry e outras bibliotecas. * Muitos recursos extras (graรงas ao Starlette) como: * **WebSockets** - * testes extrememamente fรกceis baseados em HTTPX e `pytest` + * testes extremamente fรกceis baseados em HTTPX e `pytest` * **CORS** * **Cookie Sessions** * ...e mais. ### Implemente sua aplicaรงรฃo (opcional) { #deploy-your-app-optional } -Vocรช pode opcionalmente implantar sua aplicaรงรฃo FastAPI na FastAPI Cloud, inscreva-se na lista de espera se ainda nรฃo o fez. ๐Ÿš€ +Vocรช pode opcionalmente implantar sua aplicaรงรฃo FastAPI na FastAPI Cloud, vรก e entre na lista de espera se ainda nรฃo o fez. ๐Ÿš€ Se vocรช jรก tem uma conta na **FastAPI Cloud** (nรณs convidamos vocรช da lista de espera ๐Ÿ˜‰), pode implantar sua aplicaรงรฃo com um รบnico comando. @@ -506,7 +512,7 @@ Siga os tutoriais do seu provedor de nuvem para implantar aplicaรงรตes FastAPI c Testes de performance da _Independent TechEmpower_ mostram aplicaรงรตes **FastAPI** rodando sob Uvicorn como um dos _frameworks_ Python mais rรกpidos disponรญveis, somente atrรกs de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) -Para entender mais sobre performance, veja a seรงรฃo Comparaรงรตes. +Para entender mais sobre isso, veja a seรงรฃo Comparaรงรตes. ## Dependรชncias { #dependencies } @@ -514,7 +520,7 @@ O FastAPI depende do Pydantic e do Starlette. ### Dependรชncias `standard` { #standard-dependencies } -Quando vocรช instala o FastAPI com `pip install "fastapi[standard]"`, ele vรชm com o grupo `standard` (padrรฃo) de dependรชncias opcionais: +Quando vocรช instala o FastAPI com `pip install "fastapi[standard]"`, ele vem com o grupo `standard` de dependรชncias opcionais: Utilizado pelo Pydantic: @@ -524,7 +530,7 @@ Utilizado pelo Starlette: * httpx - Obrigatรณrio caso vocรช queira utilizar o `TestClient`. * jinja2 - Obrigatรณrio se vocรช quer utilizar a configuraรงรฃo padrรฃo de templates. -* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. +* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. Utilizado pelo FastAPI: @@ -547,7 +553,7 @@ Existem algumas dependรชncias adicionais que vocรช pode querer instalar. Dependรชncias opcionais adicionais do Pydantic: * pydantic-settings - para gerenciamento de configuraรงรตes. -* pydantic-extra-types - tipos extras para serem utilizados com o Pydantic. +* pydantic-extra-types - para tipos extras a serem utilizados com o Pydantic. Dependรชncias opcionais adicionais do FastAPI: diff --git a/docs/pt/docs/tutorial/bigger-applications.md b/docs/pt/docs/tutorial/bigger-applications.md index 9dec7b1968..87bd13375a 100644 --- a/docs/pt/docs/tutorial/bigger-applications.md +++ b/docs/pt/docs/tutorial/bigger-applications.md @@ -31,7 +31,7 @@ Digamos que vocรช tenha uma estrutura de arquivos como esta: /// tip | Dica -Existem vรกrios arquivos `__init__.py` presentes em cada diretรณrio ou subdiretรณrio. +Existem vรกrios arquivos `__init__.py`: um em cada diretรณrio ou subdiretรณrio. Isso permite a importaรงรฃo de cรณdigo de um arquivo para outro. @@ -43,32 +43,32 @@ from app.routers import items /// -* O diretรณrio `app` contรฉm todo o cรณdigo da aplicaรงรฃo. Ele possui um arquivo `app/__init__.py` vazio, o que o torna um "pacote Python" (uma coleรงรฃo de "mรณdulos Python"): `app`. -* Dentro dele, o arquivo `app/main.py` estรก localizado em um pacote Python (diretรณrio com `__init__.py`). Portanto, ele รฉ um "mรณdulo" desse pacote: `app.main`. -* Existem tambรฉm um arquivo `app/dependencies.py`, assim como o `app/main.py`, ele รฉ um "mรณdulo": `app.dependencies`. +* O diretรณrio `app` contรฉm tudo. E possui um arquivo vazio `app/__init__.py`, entรฃo ele รฉ um "pacote Python" (uma coleรงรฃo de "mรณdulos Python"): `app`. +* Ele contรฉm um arquivo `app/main.py`. Como estรก dentro de um pacote Python (um diretรณrio com um arquivo `__init__.py`), ele รฉ um "mรณdulo" desse pacote: `app.main`. +* Existe tambรฉm um arquivo `app/dependencies.py`, assim como `app/main.py`, ele รฉ um "mรณdulo": `app.dependencies`. * Hรก um subdiretรณrio `app/routers/` com outro arquivo `__init__.py`, entรฃo ele รฉ um "subpacote Python": `app.routers`. -* O arquivo `app/routers/items.py` estรก dentro de um pacote, `app/routers/`, portanto, รฉ um "submรณdulo": `app.routers.items`. -* O mesmo com `app/routers/users.py`, ele รฉ outro submรณdulo: `app.routers.users`. -* Hรก tambรฉm um subdiretรณrio `app/internal/` com outro arquivo `__init__.py`, entรฃo ele รฉ outro "subpacote Python":`app.internal`. +* O arquivo `app/routers/items.py` estรก dentro de um pacote, `app/routers/`, portanto รฉ um submรณdulo: `app.routers.items`. +* O mesmo com `app/routers/users.py`, ele รฉ outro submรณdulo: `app.routers.users`. +* Hรก tambรฉm um subdiretรณrio `app/internal/` com outro arquivo `__init__.py`, entรฃo ele รฉ outro "subpacote Python": `app.internal`. * E o arquivo `app/internal/admin.py` รฉ outro submรณdulo: `app.internal.admin`. A mesma estrutura de arquivos com comentรกrios: -``` +```bash . -โ”œโ”€โ”€ app # "app" รฉ um pacote Python -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # este arquivo torna "app" um "pacote Python" -โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" mรณdulo, e.g. import app.main -โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" mรณdulo, e.g. import app.dependencies -โ”‚ย ย  โ””โ”€โ”€ routers # "routers" รฉ um "subpacote Python" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # torna "routers" um "subpacote Python" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submรณdulo, e.g. import app.routers.items -โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submรณdulo, e.g. import app.routers.users -โ”‚ย ย  โ””โ”€โ”€ internal # "internal" รฉ um "subpacote Python" -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # torna "internal" um "subpacote Python" -โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submรณdulo, e.g. import app.internal.admin +โ”œโ”€โ”€ app # "app" is a Python package +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # this file makes "app" a "Python package" +โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module, e.g. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module, e.g. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" is a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # makes "routers" a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule, e.g. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule, e.g. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" is a "Python subpackage" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # makes "internal" a "Python subpackage" +โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule, e.g. import app.internal.admin ``` ## `APIRouter` { #apirouter } @@ -79,11 +79,11 @@ Vocรช quer manter as *operaรงรตes de rota* relacionadas aos seus usuรกrios separ Mas ele ainda faz parte da mesma aplicaรงรฃo/web API **FastAPI** (faz parte do mesmo "pacote Python"). -Vocรช pode criar as *operaรงรตes de rotas* para esse mรณdulo usando o `APIRouter`. +Vocรช pode criar as *operaรงรตes de rota* para esse mรณdulo usando o `APIRouter`. ### Importe `APIRouter` { #import-apirouter } -vocรช o importa e cria uma "instรขncia" da mesma maneira que faria com a classe `FastAPI`: +Vocรช o importa e cria uma "instรขncia" da mesma maneira que faria com a classe `FastAPI`: {* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} @@ -91,7 +91,7 @@ vocรช o importa e cria uma "instรขncia" da mesma maneira que faria com a classe E entรฃo vocรช o utiliza para declarar suas *operaรงรตes de rota*. -Utilize-o da mesma maneira que utilizaria a classe `FastAPI`: +Utilize-o da mesma maneira que utilizaria a classe `FastAPI`: {* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} @@ -151,7 +151,7 @@ Entรฃo, em vez de adicionar tudo isso a cada *operaรงรฃo de rota*, podemos adici {* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} -Como o caminho de cada *operaรงรฃo de rota* deve comeรงar com `/`, como em: +Como o path de cada *operaรงรฃo de rota* tem que comeรงar com `/`, como em: ```Python hl_lines="1" @router.get("/{item_id}") @@ -163,9 +163,9 @@ async def read_item(item_id: str): Entรฃo, o prefixo neste caso รฉ `/items`. -Tambรฉm podemos adicionar uma lista de `tags` e `responses` extras que serรฃo aplicadas a todas as *operaรงรตes de rota* incluรญdas neste roteador. +Tambรฉm podemos adicionar uma list de `tags` e `responses` extras que serรฃo aplicadas a todas as *operaรงรตes de rota* incluรญdas neste router. -E podemos adicionar uma lista de `dependencies` que serรฃo adicionadas a todas as *operaรงรตes de rota* no roteador e serรฃo executadas/resolvidas para cada request feita a elas. +E podemos adicionar uma list de `dependencies` que serรฃo adicionadas a todas as *operaรงรตes de rota* no router e serรฃo executadas/resolvidas para cada request feita a elas. /// tip | Dica @@ -173,7 +173,7 @@ Observe que, assim como [dependรชncias em *decoradores de operaรงรฃo de rota*](d /// -O resultado final รฉ que os caminhos dos itens agora sรฃo: +O resultado final รฉ que os paths dos itens agora sรฃo: * `/items/` * `/items/{item_id}` @@ -183,9 +183,9 @@ O resultado final รฉ que os caminhos dos itens agora sรฃo: * Elas serรฃo marcadas com uma lista de tags que contรชm uma รบnica string `"items"`. * Essas "tags" sรฃo especialmente รบteis para os sistemas de documentaรงรฃo interativa automรกtica (usando OpenAPI). * Todas elas incluirรฃo as `responses` predefinidas. -* Todas essas *operaรงรตes de rota* terรฃo a lista de `dependencies` avaliada/executada antes delas. +* Todas essas *operaรงรตes de rota* terรฃo a list de `dependencies` avaliada/executada antes delas. * Se vocรช tambรฉm declarar dependรชncias em uma *operaรงรฃo de rota* especรญfica, **elas tambรฉm serรฃo executadas**. - * As dependรชncias do roteador sรฃo executadas primeiro, depois as [`dependencies` no decorador](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} e, em seguida, as dependรชncias de parรขmetros normais. + * As dependรชncias do router sรฃo executadas primeiro, depois as [`dependencies` no decorador](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} e, em seguida, as dependรชncias de parรขmetros normais. * Vocรช tambรฉm pode adicionar [dependรชncias de `Seguranรงa` com `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}. /// tip | Dica @@ -246,7 +246,7 @@ from ..dependencies import get_token_header significa: -* Comeรงando no mesmo pacote em que este mรณdulo (o arquivo `app/routers/items.py`) reside (o diretรณrio `app/routers/`)... +* Comeรงando no mesmo pacote em que este mรณdulo (o arquivo `app/routers/items.py`) vive (o diretรณrio `app/routers/`)... * vรก para o pacote pai (o diretรณrio `app/`)... * e lรก, encontre o mรณdulo `dependencies` (o arquivo em `app/dependencies.py`)... * e dele, importe a funรงรฃo `get_token_header`. @@ -283,9 +283,9 @@ Mas ainda podemos adicionar _mais_ `tags` que serรฃo aplicadas a uma *operaรงรฃo /// tip | Dica -Esta รบltima operaรงรฃo de caminho terรก a combinaรงรฃo de tags: `["items", "custom"]`. +Esta รบltima operaรงรฃo de rota terรก a combinaรงรฃo de tags: `["items", "custom"]`. -E tambรฉm terรก ambas as respostas na documentaรงรฃo, uma para `404` e uma para `403`. +E tambรฉm terรก ambas as responses na documentaรงรฃo, uma para `404` e uma para `403`. /// @@ -325,7 +325,7 @@ from .routers import items, users significa: -* Comeรงando no mesmo pacote em que este mรณdulo (o arquivo `app/main.py`) reside (o diretรณrio `app/`)... +* Comeรงando no mesmo pacote em que este mรณdulo (o arquivo `app/main.py`) vive (o diretรณrio `app/`)... * procure o subpacote `routers` (o diretรณrio em `app/routers/`)... * e dele, importe o submรณdulo `items` (o arquivo em `app/routers/items.py`) e `users` (o arquivo em `app/routers/users.py`)... @@ -376,7 +376,7 @@ Entรฃo, para poder usar ambos no mesmo arquivo, importamos os submรณdulos direta {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} -### Inclua os `APIRouter`s para `usuรกrios` e `itens` { #include-the-apirouters-for-users-and-items } +### Inclua os `APIRouter`s para `users` e `items` { #include-the-apirouters-for-users-and-items } Agora, vamos incluir os `router`s dos submรณdulos `users` e `items`: @@ -392,7 +392,7 @@ E `items.router` contรฉm o `APIRouter` dentro do arquivo `app/routers/items.py`. Com `app.include_router()` podemos adicionar cada `APIRouter` ao aplicativo principal `FastAPI`. -Ele incluirรก todas as rotas daquele roteador como parte dele. +Ele incluirรก todas as rotas daquele router como parte dele. /// note | Detalhes Tรฉcnicos @@ -404,7 +404,7 @@ Entรฃo, nos bastidores, ele realmente funcionarรก como se tudo fosse o mesmo apl /// check | Verifique -Vocรช nรฃo precisa se preocupar com desempenho ao incluir roteadores. +Vocรช nรฃo precisa se preocupar com desempenho ao incluir routers. Isso levarรก microssegundos e sรณ acontecerรก na inicializaรงรฃo. @@ -453,7 +453,7 @@ e funcionarรก corretamente, junto com todas as outras *operaรงรตes de rota* adic /// note | Detalhes Tรฉcnicos Avanรงados -**Observaรงรฃo**: este รฉ um detalhe muito tรฉcnico que vocรช provavelmente pode **simplesmente pular**. +**Nota**: este รฉ um detalhe muito tรฉcnico que vocรช provavelmente pode **simplesmente pular**. --- @@ -479,15 +479,15 @@ $ fastapi dev app/main.py -E abra os documentos em http://127.0.0.1:8000/docs. +E abra a documentaรงรฃo em http://127.0.0.1:8000/docs. -Vocรช verรก a documentaรงรฃo automรกtica da API, incluindo os caminhos de todos os submรณdulos, usando os caminhos (e prefixos) corretos e as tags corretas: +Vocรช verรก a documentaรงรฃo automรกtica da API, incluindo os paths de todos os submรณdulos, usando os paths (e prefixos) corretos e as tags corretas: -## Inclua o mesmo roteador vรกrias vezes com `prefix` diferentes { #include-the-same-router-multiple-times-with-different-prefix } +## Inclua o mesmo router vรกrias vezes com `prefix` diferentes { #include-the-same-router-multiple-times-with-different-prefix } -Vocรช tambรฉm pode usar `.include_router()` vรกrias vezes com o *mesmo* roteador usando prefixos diferentes. +Vocรช tambรฉm pode usar `.include_router()` vรกrias vezes com o *mesmo* router usando prefixos diferentes. Isso pode ser รบtil, por exemplo, para expor a mesma API sob prefixos diferentes, por exemplo, `/api/v1` e `/api/latest`. @@ -495,10 +495,10 @@ Esse รฉ um uso avanรงado que vocรช pode nรฃo precisar, mas estรก lรก caso precis ## Inclua um `APIRouter` em outro { #include-an-apirouter-in-another } -Da mesma forma que vocรช pode incluir um `APIRouter` em um aplicativo `FastAPI`, vocรช pode incluir um `APIRouter` em outro `APIRouter` usando: +Da mesma forma que vocรช pode incluir um `APIRouter` em uma aplicaรงรฃo `FastAPI`, vocรช pode incluir um `APIRouter` em outro `APIRouter` usando: ```Python router.include_router(other_router) ``` -Certifique-se de fazer isso antes de incluir `router` no aplicativo `FastAPI`, para que as *operaรงรตes de rota* de `other_router` tambรฉm sejam incluรญdas. +Certifique-se de fazer isso antes de incluir `router` na aplicaรงรฃo `FastAPI`, para que as *operaรงรตes de rota* de `other_router` tambรฉm sejam incluรญdas. diff --git a/docs/pt/docs/tutorial/body-updates.md b/docs/pt/docs/tutorial/body-updates.md index 67bf684925..95f89c8d23 100644 --- a/docs/pt/docs/tutorial/body-updates.md +++ b/docs/pt/docs/tutorial/body-updates.md @@ -1,6 +1,6 @@ # Corpo - Atualizaรงรตes { #body-updates } -## Atualizaรงรฃo de dados existentes com `PUT` { #update-replacing-with-put } +## Atualizaรงรฃo substituindo com `PUT` { #update-replacing-with-put } Para atualizar um item, vocรช pode usar a operaรงรฃo HTTP `PUT`. @@ -22,13 +22,13 @@ Isso significa que, se vocรช quiser atualizar o item `bar` usando `PUT` com um c } ``` -Como ele nรฃo inclui o atributo jรก armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrรฃo de `"tax": 10.5`. +como ele nรฃo inclui o atributo jรก armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrรฃo de `"tax": 10.5`. E os dados seriam salvos com esse "novo" `tax` de `10.5`. ## Atualizaรงรตes parciais com `PATCH` { #partial-updates-with-patch } -Vocรช tambรฉm pode usar a operaรงรฃo HTTP `PATCH` para atualizar parcialmente os dados. +Vocรช tambรฉm pode usar a operaรงรฃo HTTP `PATCH` para atualizar dados *parcialmente*. Isso significa que vocรช pode enviar apenas os dados que deseja atualizar, deixando o restante intacto. @@ -40,25 +40,17 @@ E muitas equipes usam apenas `PUT`, mesmo para atualizaรงรตes parciais. Vocรช รฉ **livre** para usรก-los como preferir, **FastAPI** nรฃo impรตe restriรงรตes. -Mas este guia te dรก uma ideia de como eles sรฃo destinados a serem usados. +Mas este guia mostra, mais ou menos, como eles sรฃo destinados a serem usados. /// ### Usando o parรขmetro `exclude_unset` do Pydantic { #using-pydantics-exclude-unset-parameter } -Se vocรช quiser receber atualizaรงรตes parciais, รฉ muito รบtil usar o parรขmetro `exclude_unset` no mรฉtodo `.model_dump()` do modelo do Pydantic. +Se vocรช quiser receber atualizaรงรตes parciais, รฉ muito รบtil usar o parรขmetro `exclude_unset` no `.model_dump()` do modelo do Pydantic. Como `item.model_dump(exclude_unset=True)`. -/// info | Informaรงรฃo - -No Pydantic v1, o mรฉtodo que era chamado `.dict()` e foi descontinuado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o mรฉtodo `.model_dump()`. - -Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas vocรช deve usar `.model_dump()` a partir do Pydantic v2. - -/// - -Isso gera um `dict` com apenas os dados definidos ao criar o modelo `item`, excluindo os valores padrรฃo. +Isso geraria um `dict` com apenas os dados que foram definidos ao criar o modelo `item`, excluindo os valores padrรฃo. Entรฃo, vocรช pode usar isso para gerar um `dict` com apenas os dados definidos (enviados na solicitaรงรฃo), omitindo valores padrรฃo: @@ -68,31 +60,23 @@ Entรฃo, vocรช pode usar isso para gerar um `dict` com apenas os dados definidos Agora, vocรช pode criar uma cรณpia do modelo existente usando `.model_copy()`, e passar o parรขmetro `update` com um `dict` contendo os dados para atualizar. -/// info | Informaรงรฃo - -No Pydantic v1, o mรฉtodo era chamado `.copy()`, ele foi descontinuado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`. - -Os exemplos aqui usam `.copy()` para compatibilidade com o Pydantic v1, mas vocรช deve usar `.model_copy()` com o Pydantic v2. - -/// - Como `stored_item_model.model_copy(update=update_data)`: {* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} ### Recapitulando as atualizaรงรตes parciais { #partial-updates-recap } -Resumindo, para aplicar atualizaรงรตes parciais vocรช pode: +Resumindo, para aplicar atualizaรงรตes parciais vocรช deveria: * (Opcionalmente) usar `PATCH` em vez de `PUT`. * Recuperar os dados armazenados. * Colocar esses dados em um modelo do Pydantic. * Gerar um `dict` sem valores padrรฃo a partir do modelo de entrada (usando `exclude_unset`). - * Dessa forma, vocรช pode atualizar apenas os valores definidos pelo usuรกrio, em vez de substituir os valores jรก armazenados com valores padrรฃo em seu modelo. + * Dessa forma, vocรช pode atualizar apenas os valores realmente definidos pelo usuรกrio, em vez de substituir valores jรก armazenados por valores padrรฃo do modelo. * Criar uma cรณpia do modelo armazenado, atualizando seus atributos com as atualizaรงรตes parciais recebidas (usando o parรขmetro `update`). -* Converter o modelo copiado em algo que possa ser armazenado no seu banco de dados (por exemplo, usando o `jsonable_encoder`). - * Isso รฉ comparรกvel ao uso do mรฉtodo `.model_dump()`, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`. -* Salvar os dados no seu banco de dados. +* Converter o modelo copiado em algo que possa ser armazenado no seu BD (por exemplo, usando o `jsonable_encoder`). + * Isso รฉ comparรกvel a usar o mรฉtodo `.model_dump()` do modelo novamente, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`. +* Salvar os dados no seu BD. * Retornar o modelo atualizado. {* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} @@ -109,8 +93,8 @@ Mas o exemplo aqui usa `PATCH` porque foi criado para esses casos de uso. Observe que o modelo de entrada ainda รฉ validado. -Portanto, se vocรช quiser receber atualizaรงรตes parciais que possam omitir todos os atributos, precisarรก ter um modelo com todos os atributos marcados como opcionais (com valores padrรฃo ou `None`). +Portanto, se vocรช quiser receber atualizaรงรตes parciais que possam omitir todos os atributos, vocรช precisa ter um modelo com todos os atributos marcados como opcionais (com valores padrรฃo ou `None`). -Para distinguir os modelos com todos os valores opcionais para **atualizaรงรตes** e modelos com valores obrigatรณrios para **criaรงรฃo**, vocรช pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}. +Para distinguir entre os modelos com todos os valores opcionais para **atualizaรงรตes** e modelos com valores obrigatรณrios para **criaรงรฃo**, vocรช pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}. /// diff --git a/docs/pt/docs/tutorial/body.md b/docs/pt/docs/tutorial/body.md index 1330f4458f..669334439a 100644 --- a/docs/pt/docs/tutorial/body.md +++ b/docs/pt/docs/tutorial/body.md @@ -10,11 +10,11 @@ Para declarar um corpo da **requisiรงรฃo**, vocรช utiliza os modelos do 0.95.0) exigiam que vocรช usasse `Query` como valor padrรฃo do seu parรขmetro, em vez de colocรก-lo em `Annotated`. ร‰ muito provรกvel que vocรช veja cรณdigo assim por aรญ, entรฃo vou te explicar. +Versรตes anteriores do FastAPI (antes de 0.95.0) exigiam que vocรช usasse `Query` como valor padrรฃo do seu parรขmetro, em vez de colocรก-lo em `Annotated`, hรก uma grande chance de vocรช ver cรณdigo usando isso por aรญ, entรฃo vou explicar. /// tip | Dica @@ -192,7 +192,7 @@ Vocรช tambรฉm pode adicionar um parรขmetro `min_length`: ## Adicione expressรตes regulares { #add-regular-expressions } -Vocรช pode definir um `pattern` de expressรฃo regular que o parรขmetro deve corresponder: +Vocรช pode definir um `pattern` de expressรฃo regular que o parรขmetro deve corresponder: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -206,20 +206,6 @@ Se vocรช se sentir perdido com essas ideias de **"expressรฃo regular"**, nรฃo se Agora vocรช sabe que, sempre que precisar delas, pode usรก-las no **FastAPI**. -### Pydantic v1 `regex` em vez de `pattern` { #pydantic-v1-regex-instead-of-pattern } - -Antes da versรฃo 2 do Pydantic e antes do FastAPI 0.100.0, o parรขmetro se chamava `regex` em vez de `pattern`, mas agora estรก descontinuado. - -Vocรช ainda pode ver algum cรณdigo usando isso: - -//// tab | Pydantic v1 - -{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *} - -//// - -Mas saiba que isso estรก descontinuado e deve ser atualizado para usar o novo parรขmetro `pattern`. ๐Ÿค“ - ## Valores padrรฃo { #default-values } Vocรช pode, claro, usar valores padrรฃo diferentes de `None`. @@ -280,7 +266,7 @@ Entรฃo, com uma URL como: http://localhost:8000/items/?q=foo&q=bar ``` -vocรช receberรก os mรบltiplos valores do *parรขmetro de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *funรงรฃo de operaรงรฃo de rota*, no *parรขmetro da funรงรฃo* `q`. +vocรช receberia os mรบltiplos valores dos *parรขmetros de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *funรงรฃo de operaรงรฃo de rota*, no *parรขmetro da funรงรฃo* `q`. Assim, a resposta para essa URL seria: @@ -350,7 +336,7 @@ Essas informaรงรตes serรฃo incluรญdas no OpenAPI gerado e usadas pelas interface Tenha em mente que ferramentas diferentes podem ter nรญveis diferentes de suporte ao OpenAPI. -Algumas delas podem ainda nรฃo mostrar todas as informaรงรตes extras declaradas, embora na maioria dos casos o recurso ausente jรก esteja planejado para desenvolvimento. +Algumas delas podem ainda nรฃo mostrar todas as informaรงรตes extras declaradas, embora na maioria dos casos a funcionalidade ausente jรก esteja planejada para desenvolvimento. /// @@ -386,7 +372,7 @@ Entรฃo vocรช pode declarar um `alias`, e esse alias serรก usado para encontrar o Agora digamos que vocรช nรฃo gosta mais desse parรขmetro. -Vocรช tem que deixรก-lo por um tempo, pois hรก clientes usando-o, mas quer que a documentaรงรฃo mostre claramente que ele estรก descontinuado. +Vocรช tem que deixรก-lo por um tempo, pois hรก clientes usando-o, mas quer que a documentaรงรฃo mostre claramente que ele estรก deprecated. Entรฃo passe o parรขmetro `deprecated=True` para `Query`: @@ -416,7 +402,7 @@ O Pydantic tambรฉm tem ISBN ou com `imdb-` para um ID de URL de filme IMDB: +Por exemplo, este validador personalizado verifica se o ID do item comeรงa com `isbn-` para um nรบmero de livro ISBN ou com `imdb-` para um ID de URL de filme IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -428,7 +414,7 @@ Isso estรก disponรญvel com a versรฃo 2 do Pydantic ou superior. ๐Ÿ˜Ž /// tip | Dica -Se vocรช precisar fazer qualquer tipo de validaรงรฃo que exija comunicaรงรฃo com algum **componente externo**, como um banco de dados ou outra API, vocรช deve usar **Dependรชncias do FastAPI** em vez disso; vocรช aprenderรก sobre elas mais adiante. +Se vocรช precisar fazer qualquer tipo de validaรงรฃo que exija comunicaรงรฃo com algum **componente externo**, como um banco de dados ou outra API, vocรช deveria usar **Dependรชncias do FastAPI** em vez disso; vocรช aprenderรก sobre elas mais adiante. Esses validadores personalizados sรฃo para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisiรงรฃo. @@ -440,7 +426,7 @@ O ponto importante รฉ apenas usar **`AfterValidator` com uma funรงรฃo dentro de --- -Mas se vocรช estรก curioso sobre este exemplo especรญfico e ainda entretido, aqui vรฃo alguns detalhes extras. +Mas se vocรช estiver curioso sobre este exemplo de cรณdigo especรญfico e ainda entretido, aqui vรฃo alguns detalhes extras. #### String com `value.startswith()` { #string-with-value-startswith } @@ -450,7 +436,7 @@ Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verif #### Um item aleatรณrio { #a-random-item } -Com `data.items()` obtemos um objeto iterรกvel com tuplas contendo a chave e o valor de cada item do dicionรกrio. +Com `data.items()` obtemos um objeto iterรกvel com tuplas contendo a chave e o valor de cada item do dicionรกrio. Convertimos esse objeto iterรกvel em uma `list` adequada com `list(data.items())`. diff --git a/docs/pt/docs/tutorial/response-model.md b/docs/pt/docs/tutorial/response-model.md index dc66bb46c4..8a7a712488 100644 --- a/docs/pt/docs/tutorial/response-model.md +++ b/docs/pt/docs/tutorial/response-model.md @@ -252,20 +252,6 @@ Entรฃo, se vocรช enviar uma solicitaรงรฃo para essa *operaรงรฃo de rota* para o /// info | Informaรงรฃo -No Pydantic v1, o mรฉtodo era chamado `.dict()`, ele foi descontinuado (mas ainda suportado) no Pydantic v2 e renomeado para `.model_dump()`. - -Os exemplos aqui usam `.dict()` para compatibilidade com Pydantic v1, mas vocรช deve usar `.model_dump()` em vez disso se puder usar Pydantic v2. - -/// - -/// info | Informaรงรฃo - -O FastAPI usa `.dict()` do modelo Pydantic com seu parรขmetro `exclude_unset` para chegar a isso. - -/// - -/// info | Informaรงรฃo - Vocรช tambรฉm pode usar: * `response_model_exclude_defaults=True` diff --git a/docs/pt/docs/tutorial/schema-extra-example.md b/docs/pt/docs/tutorial/schema-extra-example.md index bddd320cd3..2d62ffd851 100644 --- a/docs/pt/docs/tutorial/schema-extra-example.md +++ b/docs/pt/docs/tutorial/schema-extra-example.md @@ -8,39 +8,17 @@ Aqui estรฃo vรกrias maneiras de fazer isso. Vocรช pode declarar `examples` para um modelo Pydantic que serรฃo adicionados ao JSON Schema gerado. -//// tab | Pydantic v2 - {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *} - -//// - Essas informaรงรตes extras serรฃo adicionadas como estรฃo ao **JSON Schema** de saรญda para esse modelo e serรฃo usadas na documentaรงรฃo da API. -//// tab | Pydantic v2 - -Na versรฃo 2 do Pydantic, vocรช usaria o atributo `model_config`, que recebe um `dict`, conforme descrito na documentaรงรฃo do Pydantic: Configuration. +Vocรช pode usar o atributo `model_config`, que recebe um `dict`, conforme descrito na documentaรงรฃo do Pydantic: Configuration. Vocรช pode definir `"json_schema_extra"` com um `dict` contendo quaisquer dados adicionais que vocรช queira que apareรงam no JSON Schema gerado, incluindo `examples`. -//// - -//// tab | Pydantic v1 - -Na versรฃo 1 do Pydantic, vocรช usaria uma classe interna `Config` e `schema_extra`, conforme descrito na documentaรงรฃo do Pydantic: Schema customization. - -Vocรช pode definir `schema_extra` com um `dict` contendo quaisquer dados adicionais que vocรช queira que apareรงam no JSON Schema gerado, incluindo `examples`. - -//// - /// tip | Dica -Vocรช pode usar a mesma tรฉcnica para estender o JSON Schema e adicionar suas prรณprias informaรงรตes extras personalizadas. +Vocรช poderia usar a mesma tรฉcnica para estender o JSON Schema e adicionar suas prรณprias informaรงรตes extras personalizadas. Por exemplo, vocรช poderia usรก-la para adicionar metadados para uma interface de usuรกrio de front-end, etc. @@ -50,7 +28,7 @@ Por exemplo, vocรช poderia usรก-la para adicionar metadados para uma interface d O OpenAPI 3.1.0 (usado desde o FastAPI 0.99.0) adicionou suporte a `examples`, que faz parte do padrรฃo **JSON Schema**. -Antes disso, ele suportava apenas a palavraโ€‘chave `example` com um รบnico exemplo. Isso ainda รฉ suportado pelo OpenAPI 3.1.0, mas รฉ descontinuado e nรฃo faz parte do padrรฃo JSON Schema. Portanto, รฉ recomendado migrar de `example` para `examples`. ๐Ÿค“ +Antes disso, ele suportava apenas a palavraโ€‘chave `example` com um รบnico exemplo. Isso ainda รฉ suportado pelo OpenAPI 3.1.0, mas รฉ descontinuado e nรฃo faz parte do padrรฃo JSON Schema. Portanto, vocรช รฉ incentivado a migrar de `example` para `examples`. ๐Ÿค“ Vocรช pode ler mais no final desta pรกgina. @@ -102,7 +80,7 @@ No entanto, no momento em que isto foi escrito, Antes do **JSON Schema** suportar `examples`, o OpenAPI jรก tinha suporte para um campo diferente tambรฉm chamado `examples`. -Esse `examples` especรญfico do OpenAPI vai em outra seรงรฃo da especificaรงรฃo. Ele fica nos **detalhes de cada funรงรฃo de operaรงรฃo de rota**, nรฃo dentro de cada JSON Schema. +Esse `examples` **especรญfico do OpenAPI** vai em outra seรงรฃo da especificaรงรฃo OpenAPI. Ele fica nos **detalhes de cada *operaรงรฃo de rota***, nรฃo dentro de cada JSON Schema. E o Swagger UI tem suportado esse campo `examples` particular hรก algum tempo. Entรฃo, vocรช pode usรก-lo para **mostrar** diferentes **exemplos na UI da documentaรงรฃo**. @@ -189,9 +167,9 @@ Depois, o JSON Schema adicionou um campo Date: Tue, 20 Jan 2026 20:40:39 +0000 Subject: [PATCH 018/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7c5460f1df..33926e3afc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). * ๐ŸŒ Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). * ๐ŸŒ Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n). From 2eb978b87a2227801cc9abaeddd5e27d941af868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 20 Jan 2026 15:03:07 -0800 Subject: [PATCH 019/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#14693)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ๐ŸŒ Update translations for ru (update-outdated) * ๐ŸŽจ Auto format * Apply suggestions from code review * Apply suggestions from code review 2 * Apply suggestions from code review 3 --------- Co-authored-by: github-actions[bot] Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/ru/docs/_llm-test.md | 18 +- .../path-operation-advanced-configuration.md | 56 +--- docs/ru/docs/advanced/settings.md | 44 --- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 28 +- .../docs/how-to/separate-openapi-schemas.md | 16 +- docs/ru/docs/index.md | 40 +-- docs/ru/docs/tutorial/bigger-applications.md | 289 +++++++++--------- docs/ru/docs/tutorial/body-updates.md | 34 +-- docs/ru/docs/tutorial/body.md | 22 +- docs/ru/docs/tutorial/extra-models.md | 62 ++-- .../tutorial/query-params-str-validations.md | 30 +- docs/ru/docs/tutorial/response-model.md | 72 ++--- docs/ru/docs/tutorial/schema-extra-example.md | 30 +- 13 files changed, 297 insertions(+), 444 deletions(-) diff --git a/docs/ru/docs/_llm-test.md b/docs/ru/docs/_llm-test.md index 9a15f6bb21..6a0272f3a5 100644 --- a/docs/ru/docs/_llm-test.md +++ b/docs/ru/docs/_llm-test.md @@ -1,8 +1,8 @@ # ะขะตัั‚ะพะฒั‹ะน ั„ะฐะนะป LLM { #llm-test-file } -ะญั‚ะพั‚ ะดะพะบัƒะผะตะฝั‚ ะฟั€ะพะฒะตั€ัะตั‚, ะฟะพะฝะธะผะฐะตั‚ ะปะธ LLM, ะฟะตั€ะตะฒะพะดัั‰ะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ, `general_prompt` ะฒ `scripts/translate.py` ะธ ัะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะฒ `docs/{language code}/llm-prompt.md`. ะฏะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะดะพะฑะฐะฒะปัะตั‚ัั ะบ `general_prompt`. +ะญั‚ะพั‚ ะดะพะบัƒะผะตะฝั‚ ะฟั€ะพะฒะตั€ัะตั‚, ะฟะพะฝะธะผะฐะตั‚ ะปะธ LLM, ะฟะตั€ะตะฒะพะดัั‰ะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ, `general_prompt` ะฒ `scripts/translate.py` ะธ ัะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะฒ `docs/{language code}/llm-prompt.md`. ะฏะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะดะพะฑะฐะฒะปัะตั‚ัั ะบ `general_prompt`. -ะขะตัั‚ั‹, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะต ะทะดะตััŒ, ัƒะฒะธะดัั‚ ะฒัะต ัะพะทะดะฐั‚ะตะปะธ ัะทั‹ะบะพะฒั‹ั… ะฟั€ะพะผะฟั‚ะพะฒ. +ะขะตัั‚ั‹, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะต ะทะดะตััŒ, ัƒะฒะธะดัั‚ ะฒัะต ัะพะทะดะฐั‚ะตะปะธ ัะทั‹ะบะพะฒั‹ั… ัะฟะตั†ะธั„ะธั‡ะฝั‹ั… ะฟั€ะพะผะฟั‚ะพะฒ. ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต: @@ -11,7 +11,7 @@ * ะŸั€ะพะฒะตั€ัŒั‚ะต, ะฒัั‘ ะปะธ ะฒ ะฟะพั€ัะดะบะต ะฒ ะฟะตั€ะตะฒะพะดะต. * ะŸั€ะธ ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ ัƒะปัƒั‡ัˆะธั‚ะต ะฒะฐัˆ ัะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚, ะพะฑั‰ะธะน ะฟั€ะพะผะฟั‚ ะธะปะธ ะฐะฝะณะปะธะนัะบะธะน ะดะพะบัƒะผะตะฝั‚. * ะ—ะฐั‚ะตะผ ะฒั€ัƒั‡ะฝัƒัŽ ะธัะฟั€ะฐะฒัŒั‚ะต ะพัั‚ะฐะฒัˆะธะตัั ะฟั€ะพะฑะปะตะผั‹ ะฒ ะฟะตั€ะตะฒะพะดะต, ั‡ั‚ะพะฑั‹ ะพะฝ ะฑั‹ะป ั…ะพั€ะพัˆะธะผ. -* ะŸะตั€ะตะฒะตะดะธั‚ะต ะทะฐะฝะพะฒะพ, ะธะผะตั ั…ะพั€ะพัˆะธะน ะฟะตั€ะตะฒะพะด ะฝะฐ ะผะตัั‚ะต. ะ˜ะดะตะฐะปัŒะฝั‹ะผ ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะผ ะฑัƒะดะตั‚ ัะธั‚ัƒะฐั†ะธั, ะบะพะณะดะฐ LLM ะฑะพะปัŒัˆะต ะฝะต ะฒะฝะพัะธั‚ ะธะทะผะตะฝะตะฝะธะน ะฒ ะฟะตั€ะตะฒะพะด. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะพะฑั‰ะธะน ะฟั€ะพะผะฟั‚ ะธ ะฒะฐัˆ ัะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะผะฐะบัะธะผะฐะปัŒะฝะพ ั…ะพั€ะพัˆะธ (ะธะฝะพะณะดะฐ ะพะฝ ะฑัƒะดะตั‚ ะดะตะปะฐั‚ัŒ ะฝะตัะบะพะปัŒะบะพ, ะบะฐะทะฐะปะพััŒ ะฑั‹, ัะปัƒั‡ะฐะนะฝั‹ั… ะธะทะผะตะฝะตะฝะธะน, ะฟั€ะธั‡ะธะฝะฐ ะฒ ั‚ะพะผ, ั‡ั‚ะพ LLM โ€” ะฝะตะดะตั‚ะตั€ะผะธะฝะธั€ะพะฒะฐะฝะฝั‹ะต ะฐะปะณะพั€ะธั‚ะผั‹). +* ะŸะตั€ะตะฒะตะดะธั‚ะต ะทะฐะฝะพะฒะพ, ะธะผะตั ั…ะพั€ะพัˆะธะน ะฟะตั€ะตะฒะพะด ะฝะฐ ะผะตัั‚ะต. ะ˜ะดะตะฐะปัŒะฝั‹ะผ ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะผ ะฑัƒะดะตั‚ ัะธั‚ัƒะฐั†ะธั, ะบะพะณะดะฐ LLM ะฑะพะปัŒัˆะต ะฝะต ะฒะฝะพัะธั‚ ะธะทะผะตะฝะตะฝะธะน ะฒ ะฟะตั€ะตะฒะพะด. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะพะฑั‰ะธะน ะฟั€ะพะผะฟั‚ ะธ ะฒะฐัˆ ัะทั‹ะบะพะฒะพะน ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะฟั€ะพะผะฟั‚ ะฝะฐัั‚ะพะปัŒะบะพ ั…ะพั€ะพัˆะธ, ะฝะฐัะบะพะปัŒะบะพ ัั‚ะพ ะฒะพะทะผะพะถะฝะพ (ะธะฝะพะณะดะฐ ะพะฝ ะฑัƒะดะตั‚ ะดะตะปะฐั‚ัŒ ะฝะตัะบะพะปัŒะบะพ, ะบะฐะทะฐะปะพััŒ ะฑั‹, ัะปัƒั‡ะฐะนะฝั‹ั… ะธะทะผะตะฝะตะฝะธะน, ะฟั€ะธั‡ะธะฝะฐ ะฒ ั‚ะพะผ, ั‡ั‚ะพ LLM โ€” ะฝะตะดะตั‚ะตั€ะผะธะฝะธั€ะพะฒะฐะฝะฝั‹ะต ะฐะปะณะพั€ะธั‚ะผั‹). ะขะตัั‚ั‹: @@ -197,10 +197,10 @@ works(foo="bar") # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ๐ŸŽ‰ ### abbr ะดะฐั‘ั‚ ะฟะพะปะฝัƒัŽ ั€ะฐััˆะธั„ั€ะพะฒะบัƒ { #the-abbr-gives-a-full-phrase } -* GTD -* lt -* XWT -* PSGI +* GTD +* lt +* XWT +* PSGI ### abbr ะดะฐั‘ั‚ ะพะฑัŠััะฝะตะฝะธะต { #the-abbr-gives-an-explanation } @@ -209,8 +209,8 @@ works(foo="bar") # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ๐ŸŽ‰ ### abbr ะดะฐั‘ั‚ ะฟะพะปะฝัƒัŽ ั€ะฐััˆะธั„ั€ะพะฒะบัƒ ะธ ะพะฑัŠััะฝะตะฝะธะต { #the-abbr-gives-a-full-phrase-and-an-explanation } -* MDN -* I/O. +* MDN +* I/O. //// diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md index eaf9ad0528..86d3a5b630 100644 --- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md @@ -14,7 +14,7 @@ {* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} -### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะธะผะตะฝะธ ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ ะบะฐะบ operationId { #using-the-path-operation-function-name-as-the-operationid } +### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะธะผะตะฝะธ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ* ะบะฐะบ operationId { #using-the-path-operation-function-name-as-the-operationid } ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธะผะตะฝะฐ ั„ัƒะฝะบั†ะธะน ะฒะฐัˆะธั… API ะฒ ะบะฐั‡ะตัั‚ะฒะต `operationId`, ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพะนั‚ะธ ะฟะพ ะฒัะตะผ ะธะท ะฝะธั… ะธ ะฟะตั€ะตะพะฟั€ะตะดะตะปะธั‚ัŒ `operation_id` ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ั ะฟะพะผะพั‰ัŒัŽ ะธั… `APIRoute.name`. @@ -38,7 +38,7 @@ ## ะ˜ัะบะปัŽั‡ะธั‚ัŒ ะธะท OpenAPI { #exclude-from-openapi } -ะงั‚ะพะฑั‹ ะธัะบะปัŽั‡ะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะธะท ะณะตะฝะตั€ะธั€ัƒะตะผะพะน ัั…ะตะผั‹ OpenAPI (ะฐ ะทะฝะฐั‡ะธั‚, ะธ ะธะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ), ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `include_in_schema` ะธ ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะตะณะพ ะฒ `False`: +ะงั‚ะพะฑั‹ ะธัะบะปัŽั‡ะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะธะท ะณะตะฝะตั€ะธั€ัƒะตะผะพะน ัั…ะตะผั‹ OpenAPI (ะฐ ะทะฝะฐั‡ะธั‚, ะธ ะธะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธั… ัะธัั‚ะตะผ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ), ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `include_in_schema` ะธ ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะตะณะพ ะฒ `False`: {* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} @@ -48,7 +48,7 @@ ะ”ะพะฑะฐะฒะปะตะฝะธะต `\f` (ัะบั€ะฐะฝะธั€ะพะฒะฐะฝะฝะพะณะพ ัะธะผะฒะพะปะฐ ยซform feedยป) ะทะฐัั‚ะฐะฒะธั‚ **FastAPI** ะพะฑั€ะตะทะฐั‚ัŒ ั‚ะตะบัั‚, ะธัะฟะพะปัŒะทัƒะตะผั‹ะน ะดะปั OpenAPI, ะฒ ัั‚ะพะน ั‚ะพั‡ะบะต. -ะญั‚ะฐ ั‡ะฐัั‚ัŒ ะฝะต ะฟะพะฟะฐะดั‘ั‚ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ, ะฝะพ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ (ะฝะฐะฟั€ะธะผะตั€, Sphinx) ัะผะพะณัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพัั‚ะฐะปัŒะฝะพะต. +ะญั‚ะพ ะฝะต ะพั‚ะพะฑั€ะฐะทะธั‚ัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะฝะพ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ (ะฝะฐะฟั€ะธะผะตั€, Sphinx) ัะผะพะณัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพัั‚ะฐะปัŒะฝะพะต. {* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} @@ -56,7 +56,7 @@ ะ’ั‹, ะฒะตั€ะพัั‚ะฝะพ, ัƒะถะต ะฒะธะดะตะปะธ, ะบะฐะบ ะพะฑัŠัะฒะปัั‚ัŒ `response_model` ะธ `status_code` ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. -ะญั‚ะพ ะพะฟั€ะตะดะตะปัะตั‚ ะผะตั‚ะฐะดะฐะฝะฝั‹ะต ะพะฑ ะพัะฝะพะฒะฝะพะผ ะพั‚ะฒะตั‚ะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. +ะญั‚ะพ ะพะฟั€ะตะดะตะปัะตั‚ ะผะตั‚ะฐะดะฐะฝะฝั‹ะต ะพะฑ ะพัะฝะพะฒะฝะพะผ HTTP-ะพั‚ะฒะตั‚ะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. ะขะฐะบะถะต ะผะพะถะฝะพ ะพะฑัŠัะฒะปัั‚ัŒ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะพั‚ะฒะตั‚ั‹ ั ะธั… ะผะพะดะตะปัะผะธ, ัั‚ะฐั‚ัƒั-ะบะพะดะฐะผะธ ะธ ั‚.ะด. @@ -76,7 +76,7 @@ ะขะฐะผ ะตัั‚ัŒ `tags`, `parameters`, `requestBody`, `responses` ะธ ั‚.ะด. -ะญั‚ะฐ ัะฟะตั†ะธั„ะธะบะฐั†ะธั OpenAPI, ัะฟะตั†ะธั„ะธั‡ะฝะฐั ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะพะฑั‹ั‡ะฝะพ ะณะตะฝะตั€ะธั€ัƒะตั‚ัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ **FastAPI**, ะฝะพ ะฒั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะตั‘ ั€ะฐััˆะธั€ะธั‚ัŒ. +ะญั‚ะฐ ัะฟะตั†ะธั„ะธั‡ะฝะฐั ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ัั…ะตะผะฐ OpenAPI ะพะฑั‹ั‡ะฝะพ ะณะตะฝะตั€ะธั€ัƒะตั‚ัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ **FastAPI**, ะฝะพ ะฒั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะตั‘ ั€ะฐััˆะธั€ะธั‚ัŒ. /// tip | ะกะพะฒะตั‚ @@ -129,13 +129,13 @@ } ``` -### ะŸะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะฐั ัั…ะตะผะฐ OpenAPI ะดะปั ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ { #custom-openapi-path-operation-schema } +### ะŸะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะฐั ัั…ะตะผะฐ OpenAPI ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* { #custom-openapi-path-operation-schema } -ะกะปะพะฒะฐั€ัŒ ะฒ `openapi_extra` ะฑัƒะดะตั‚ ะพะฑัŠะตะดะธะฝั‘ะฝ ั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผะพะน OpenAPI ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. +ะกะปะพะฒะฐั€ัŒ ะฒ `openapi_extra` ะฑัƒะดะตั‚ ะณะปัƒะฑะพะบะพ ะพะฑัŠะตะดะธะฝั‘ะฝ ั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผะพะน OpenAPI ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะดะฐะฝะฝั‹ะต ะบ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผะต. -ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ั€ะตัˆะธั‚ัŒ ั‡ะธั‚ะฐั‚ัŒ ะธ ะฒะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ ะทะฐะฟั€ะพั ัะฒะพะธะผ ะบะพะดะพะผ, ะฝะต ะธัะฟะพะปัŒะทัƒั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะต ะฒะพะทะผะพะถะฝะพัั‚ะธ FastAPI ะธ Pydantic, ะฝะพ ะฟั€ะธ ัั‚ะพะผ ะทะฐั…ะพั‚ะธั‚ะต ะพะฟะธัะฐั‚ัŒ ะทะฐะฟั€ะพั ะฒ ัั…ะตะผะต OpenAPI. +ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ั€ะตัˆะธั‚ัŒ ั‡ะธั‚ะฐั‚ัŒ ะธ ะฒะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ HTTP-ะทะฐะฟั€ะพั ัะฒะพะธะผ ะบะพะดะพะผ, ะฝะต ะธัะฟะพะปัŒะทัƒั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะต ะฒะพะทะผะพะถะฝะพัั‚ะธ FastAPI ะธ Pydantic, ะฝะพ ะฟั€ะธ ัั‚ะพะผ ะทะฐั…ะพั‚ะธั‚ะต ะพะฟะธัะฐั‚ัŒ HTTP-ะทะฐะฟั€ะพั ะฒ ัั…ะตะผะต OpenAPI. ะญั‚ะพ ะผะพะถะฝะพ ัะดะตะปะฐั‚ัŒ ั ะฟะพะผะพั‰ัŒัŽ `openapi_extra`: @@ -149,52 +149,20 @@ ะ˜ัะฟะพะปัŒะทัƒั ั‚ะพั‚ ะถะต ะฟั€ะธั‘ะผ, ะฒั‹ ะผะพะถะตั‚ะต ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั Pydantic-ะผะพะดะตะปัŒัŽ, ั‡ั‚ะพะฑั‹ ะพะฟั€ะตะดะตะปะธั‚ัŒ JSON Schema, ะบะพั‚ะพั€ะฐั ะทะฐั‚ะตะผ ะฑัƒะดะตั‚ ะฒะบะปัŽั‡ะตะฝะฐ ะฒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน ั€ะฐะทะดะตะป ัั…ะตะผั‹ OpenAPI ะดะปั *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. -ะ˜ ะฒั‹ ะผะพะถะตั‚ะต ัะดะตะปะฐั‚ัŒ ัั‚ะพ, ะดะฐะถะต ะตัะปะธ ั‚ะธะฟ ะดะฐะฝะฝั‹ั… ะฒ ะทะฐะฟั€ะพัะต โ€” ะฝะต JSON. +ะ˜ ะฒั‹ ะผะพะถะตั‚ะต ัะดะตะปะฐั‚ัŒ ัั‚ะพ, ะดะฐะถะต ะตัะปะธ ั‚ะธะฟ ะดะฐะฝะฝั‹ั… ะฒ HTTP-ะทะฐะฟั€ะพัะต โ€” ะฝะต JSON. -ะะฐะฟั€ะธะผะตั€, ะฒ ัั‚ะพะผ ะฟั€ะธะปะพะถะตะฝะธะธ ะผั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตะผ ะฒัั‚ั€ะพะตะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ FastAPI ะดะปั ะธะทะฒะปะตั‡ะตะฝะธั JSON Schema ะธะท ะผะพะดะตะปะตะน Pydantic, ั€ะฐะฒะฝะพ ะบะฐะบ ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ JSON. ะœั‹ ะพะฑัŠัะฒะปัะตะผ ั‚ะธะฟ ัะพะดะตั€ะถะธะผะพะณะพ ะทะฐะฟั€ะพัะฐ ะบะฐะบ YAML, ะฐ ะฝะต JSON: - -//// tab | Pydantic v2 +ะะฐะฟั€ะธะผะตั€, ะฒ ัั‚ะพะผ ะฟั€ะธะปะพะถะตะฝะธะธ ะผั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตะผ ะฒัั‚ั€ะพะตะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ FastAPI ะดะปั ะธะทะฒะปะตั‡ะตะฝะธั JSON Schema ะธะท ะผะพะดะตะปะตะน Pydantic, ั€ะฐะฒะฝะพ ะบะฐะบ ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ JSON. ะœั‹ ะพะฑัŠัะฒะปัะตะผ ั‚ะธะฟ ัะพะดะตั€ะถะธะผะพะณะพ HTTP-ะทะฐะฟั€ะพัะฐ ะบะฐะบ YAML, ะฐ ะฝะต JSON: {* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *} - -//// - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic ะฒะตั€ัะธะธ 1 ะผะตั‚ะพะด ะดะปั ะฟะพะปัƒั‡ะตะฝะธั JSON Schema ะผะพะดะตะปะธ ะฝะฐะทั‹ะฒะฐะปัั `Item.schema()`, ะฒ Pydantic ะฒะตั€ัะธะธ 2 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะตั‚ัั `Item.model_json_schema()`. - -/// - ะขะตะผ ะฝะต ะผะตะฝะตะต, ั…ะพั‚ั ะผั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตะผ ะฒัั‚ั€ะพะตะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ะธัะฟะพะปัŒะทัƒะตะผ Pydantic-ะผะพะดะตะปัŒ, ั‡ั‚ะพะฑั‹ ะฒั€ัƒั‡ะฝัƒัŽ ัะณะตะฝะตั€ะธั€ะพะฒะฐั‚ัŒ JSON Schema ะดะปั ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะผั‹ ั…ะพั‚ะธะผ ะฟะพะปัƒั‡ะธั‚ัŒ ะฒ YAML. -ะ—ะฐั‚ะตะผ ะผั‹ ั€ะฐะฑะพั‚ะฐะตะผ ั ะทะฐะฟั€ะพัะพะผ ะฝะฐะฟั€ัะผัƒัŽ ะธ ะธะทะฒะปะตะบะฐะตะผ ั‚ะตะปะพ ะบะฐะบ `bytes`. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ FastAPI ะดะฐะถะต ะฝะต ะฟะพะฟั‹ั‚ะฐะตั‚ัั ั€ะฐัะฟะฐั€ัะธั‚ัŒ ะฟะพะปะตะทะฝัƒัŽ ะฝะฐะณั€ัƒะทะบัƒ ะทะฐะฟั€ะพัะฐ ะบะฐะบ JSON. +ะ—ะฐั‚ะตะผ ะผั‹ ั€ะฐะฑะพั‚ะฐะตะผ ั HTTP-ะทะฐะฟั€ะพัะพะผ ะฝะฐะฟั€ัะผัƒัŽ ะธ ะธะทะฒะปะตะบะฐะตะผ ั‚ะตะปะพ ะบะฐะบ `bytes`. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ FastAPI ะดะฐะถะต ะฝะต ะฟะพะฟั‹ั‚ะฐะตั‚ัั ั€ะฐัะฟะฐั€ัะธั‚ัŒ ะฟะพะปะตะทะฝัƒัŽ ะฝะฐะณั€ัƒะทะบัƒ HTTP-ะทะฐะฟั€ะพัะฐ ะบะฐะบ JSON. -ะ ะทะฐั‚ะตะผ ะฒ ะฝะฐัˆะตะผ ะบะพะดะต ะผั‹ ะฝะฐะฟั€ัะผัƒัŽ ะฟะฐั€ัะธะผ ัั‚ะพั‚ YAML ะธ ัะฝะพะฒะฐ ะธัะฟะพะปัŒะทัƒะตะผ ั‚ัƒ ะถะต Pydantic-ะผะพะดะตะปัŒ ะดะปั ะฒะฐะปะธะดะฐั†ะธะธ YAML-ัะพะดะตั€ะถะธะผะพะณะพ: - -//// tab | Pydantic v2 +ะ ะทะฐั‚ะตะผ ะฒ ะฝะฐัˆะตะผ ะบะพะดะต ะผั‹ ะฝะฐะฟั€ัะผัƒัŽ ะฟะฐั€ัะธะผ ัั‚ะพ ัะพะดะตั€ะถะธะผะพะต YAML ะธ ัะฝะพะฒะฐ ะธัะฟะพะปัŒะทัƒะตะผ ั‚ัƒ ะถะต Pydantic-ะผะพะดะตะปัŒ, ั‡ั‚ะพะฑั‹ ะฒะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ YAML-ัะพะดะตั€ะถะธะผะพะต: {* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *} - -//// - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic ะฒะตั€ัะธะธ 1 ะผะตั‚ะพะด ะดะปั ะฟะฐั€ัะธะฝะณะฐ ะธ ะฒะฐะปะธะดะฐั†ะธะธ ะพะฑัŠะตะบั‚ะฐ ะฝะฐะทั‹ะฒะฐะปัั `Item.parse_obj()`, ะฒ Pydantic ะฒะตั€ัะธะธ 2 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะตั‚ัั `Item.model_validate()`. - -/// - /// tip | ะกะพะฒะตั‚ ะ—ะดะตััŒ ะผั‹ ะฟะตั€ะตะธัะฟะพะปัŒะทัƒะตะผ ั‚ัƒ ะถะต Pydantic-ะผะพะดะตะปัŒ. diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index b96ee44a3a..8408faebff 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -46,12 +46,6 @@ $ pip install "fastapi[all]" -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic v1 ะพะฝ ะฒั…ะพะดะธะป ะฒ ะพัะฝะพะฒะฝะพะน ะฟะฐะบะตั‚. ะขะตะฟะตั€ัŒ ะพะฝ ั€ะฐัะฟั€ะพัั‚ั€ะฐะฝัะตั‚ัั ะบะฐะบ ะพั‚ะดะตะปัŒะฝั‹ะน ะฟะฐะบะตั‚, ั‡ั‚ะพะฑั‹ ะฒั‹ ะผะพะณะปะธ ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ ะตะณะพ ั‚ะพะปัŒะบะพ ะฟั€ะธ ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ. - -/// - ### ะกะพะทะดะฐะฝะธะต ะพะฑัŠะตะบั‚ะฐ `Settings` { #create-the-settings-object } ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `BaseSettings` ะธะท Pydantic ะธ ัะพะทะดะฐะนั‚ะต ะฟะพะดะบะปะฐัั, ะพั‡ะตะฝัŒ ะฟะพั…ะพะถะธะน ะฝะฐ Pydanticโ€‘ะผะพะดะตะปัŒ. @@ -60,24 +54,8 @@ $ pip install "fastapi[all]" ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒัะต ั‚ะต ะถะต ะฒะพะทะผะพะถะฝะพัั‚ะธ ะฒะฐะปะธะดะฐั†ะธะธ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ั‡ั‚ะพ ะธ ะดะปั Pydanticโ€‘ะผะพะดะตะปะตะน, ะฝะฐะฟั€ะธะผะตั€ ั€ะฐะทะฝั‹ะต ั‚ะธะฟั‹ ะดะฐะฝะฝั‹ั… ะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ ั‡ะตั€ะตะท `Field()`. -//// tab | Pydantic v2 - {* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} -//// - -//// tab | Pydantic v1 - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic v1 ะฒั‹ ะฑั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะปะธ `BaseSettings` ะฝะฐะฟั€ัะผัƒัŽ ะธะท `pydantic`, ะฐ ะฝะต ะธะท `pydantic_settings`. - -/// - -{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *} - -//// - /// tip | ะกะพะฒะตั‚ ะ•ัะปะธ ะฒะฐะผ ะฝัƒะถะฝะพ ั‡ั‚ะพ-ั‚ะพ ะฑั‹ัั‚ั€ะพ ัะบะพะฟะธั€ะพะฒะฐั‚ัŒ ะธ ะฒัั‚ะฐะฒะธั‚ัŒ, ะฝะต ะธัะฟะพะปัŒะทัƒะนั‚ะต ัั‚ะพั‚ ะฟั€ะธะผะตั€ โ€” ะฒะพัะฟะพะปัŒะทัƒะนั‚ะตััŒ ะฟะพัะปะตะดะฝะธะผ ะฝะธะถะต. @@ -215,8 +193,6 @@ APP_NAME="ChimichangApp" ะ—ะฐั‚ะตะผ ะพะฑะฝะพะฒะธั‚ะต ะฒะฐัˆ `config.py` ั‚ะฐะบ: -//// tab | Pydantic v2 - {* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} /// tip | ะกะพะฒะตั‚ @@ -225,26 +201,6 @@ APP_NAME="ChimichangApp" /// -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *} - -/// tip | ะกะพะฒะตั‚ - -ะšะปะฐัั `Config` ะธัะฟะพะปัŒะทัƒะตั‚ัั ั‚ะพะปัŒะบะพ ะดะปั ะบะพะฝั„ะธะณัƒั€ะฐั†ะธะธ Pydantic. ะŸะพะดั€ะพะฑะฝะตะต ัะผ. Pydantic Model Config. - -/// - -//// - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic ะฒะตั€ัะธะธ 1 ะบะพะฝั„ะธะณัƒั€ะฐั†ะธั ะทะฐะดะฐะฒะฐะปะฐััŒ ะฒะพ ะฒะฝัƒั‚ั€ะตะฝะฝะตะผ ะบะปะฐััะต `Config`, ะฒ Pydantic ะฒะตั€ัะธะธ 2 โ€” ะฒ ะฐั‚ั€ะธะฑัƒั‚ะต `model_config`. ะญั‚ะพั‚ ะฐั‚ั€ะธะฑัƒั‚ ะฟั€ะธะฝะธะผะฐะตั‚ `dict`, ะธ ั‡ั‚ะพะฑั‹ ะฟะพะปัƒั‡ะธั‚ัŒ ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะธ ะพัˆะธะฑะบะธ ยซะฝะฐ ะปะตั‚ัƒยป, ะฒั‹ ะผะพะถะตั‚ะต ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `SettingsConfigDict` ะดะปั ะพะฟะธัะฐะฝะธั ัั‚ะพะณะพ `dict`. - -/// - ะ—ะดะตััŒ ะผั‹ ะทะฐะดะฐะตะผ ะฟะฐั€ะฐะผะตั‚ั€ ะบะพะฝั„ะธะณัƒั€ะฐั†ะธะธ `env_file` ะฒะฝัƒั‚ั€ะธ ะฒะฐัˆะตะณะพ ะบะปะฐััะฐ Pydantic `Settings` ะธ ัƒัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะทะฝะฐั‡ะตะฝะธะต ั€ะฐะฒะฝั‹ะผ ะธะผะตะฝะธ ั„ะฐะนะปะฐ dotenv, ะบะพั‚ะพั€ั‹ะน ั…ะพั‚ะธะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ. ### ะกะพะทะดะฐะฝะธะต `Settings` ั‚ะพะปัŒะบะพ ะพะดะธะฝ ั€ะฐะท ั ะฟะพะผะพั‰ัŒัŽ `lru_cache` { #creating-the-settings-only-once-with-lru-cache } diff --git a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 95481bc668..2b47c08f67 100644 --- a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -2,21 +2,23 @@ ะ•ัะปะธ ัƒ ะฒะฐั ัั‚ะฐั€ะพะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI, ะฒะพะทะผะพะถะฝะพ, ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต Pydantic ะฒะตั€ัะธะธ 1. -FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะธ Pydantic v1, ะธ v2 ะฝะฐั‡ะธะฝะฐั ั ะฒะตั€ัะธะธ 0.100.0. +FastAPI ะฒะตั€ัะธะธ 0.100.0 ะฟะพะดะดะตั€ะถะธะฒะฐะป ะปะธะฑะพ Pydantic v1, ะปะธะฑะพ v2. ะžะฝ ะธัะฟะพะปัŒะทะพะฒะฐะป ั‚ัƒ ะฒะตั€ัะธัŽ, ะบะพั‚ะพั€ะฐั ะฑั‹ะปะฐ ัƒัั‚ะฐะฝะพะฒะปะตะฝะฐ. -ะ•ัะปะธ ัƒ ะฒะฐั ะฑั‹ะป ัƒัั‚ะฐะฝะพะฒะปะตะฝ Pydantic v2, ะธัะฟะพะปัŒะทะพะฒะฐะปัั ะพะฝ. ะ•ัะปะธ ะฒะผะตัั‚ะพ ัั‚ะพะณะพ ะฑั‹ะป ัƒัั‚ะฐะฝะพะฒะปะตะฝ Pydantic v1 โ€” ะธัะฟะพะปัŒะทะพะฒะฐะปัั ะพะฝ. +FastAPI ะฒะตั€ัะธะธ 0.119.0 ะดะพะฑะฐะฒะธะป ั‡ะฐัั‚ะธั‡ะฝัƒัŽ ะฟะพะดะดะตั€ะถะบัƒ Pydantic v1 ะธะทะฝัƒั‚ั€ะธ Pydantic v2 (ะบะฐะบ `pydantic.v1`), ั‡ั‚ะพะฑั‹ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะผะธะณั€ะฐั†ะธัŽ ะฝะฐ v2. -ะกะตะนั‡ะฐั Pydantic v1 ะพะฑัŠัะฒะปะตะฝ ัƒัั‚ะฐั€ะตะฒัˆะธะผ, ะธ ะฟะพะดะดะตั€ะถะบะฐ ะตะณะพ ะฑัƒะดะตั‚ ัƒะดะฐะปะตะฝะฐ ะฒ ัะปะตะดัƒัŽั‰ะธั… ะฒะตั€ัะธัั… FastAPI, ะฟะพัั‚ะพะผัƒ ะฒะฐะผ ัะปะตะดัƒะตั‚ **ะฟะตั€ะตะนั‚ะธ ะฝะฐ Pydantic v2**. ะขะฐะบ ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะฟะพัะปะตะดะฝะธะต ะฒะพะทะผะพะถะฝะพัั‚ะธ, ัƒะปัƒั‡ัˆะตะฝะธั ะธ ะธัะฟั€ะฐะฒะปะตะฝะธั. +FastAPI 0.126.0 ัƒะฑั€ะฐะป ะฟะพะดะดะตั€ะถะบัƒ Pydantic v1, ะฟั€ะธ ัั‚ะพะผ ะตั‰ั‘ ะฝะตะบะพั‚ะพั€ะพะต ะฒั€ะตะผั ะฟั€ะพะดะพะปะถะฐะป ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ `pydantic.v1`. /// warning | ะŸั€ะตะดัƒะฟั€ะตะถะดะตะฝะธะต -ะšั€ะพะผะต ั‚ะพะณะพ, ะบะพะผะฐะฝะดะฐ Pydantic ะฟั€ะตะบั€ะฐั‚ะธะปะฐ ะฟะพะดะดะตั€ะถะบัƒ Pydantic v1 ะดะปั ะฟะพัะปะตะดะฝะธั… ะฒะตั€ัะธะน Python, ะฝะฐั‡ะธะฝะฐั ั **Python 3.14**. +ะšะพะผะฐะฝะดะฐ Pydantic ะฟั€ะตะบั€ะฐั‚ะธะปะฐ ะฟะพะดะดะตั€ะถะบัƒ Pydantic v1 ะดะปั ะฟะพัะปะตะดะฝะธั… ะฒะตั€ัะธะน Python, ะฝะฐั‡ะธะฝะฐั ั **Python 3.14**. + +ะญั‚ะพ ะฒะบะปัŽั‡ะฐะตั‚ `pydantic.v1`, ะบะพั‚ะพั€ั‹ะน ะฑะพะปัŒัˆะต ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั ะฒ Python 3.14 ะธ ะฒั‹ัˆะต. ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะพัะปะตะดะฝะธะต ะฒะพะทะผะพะถะฝะพัั‚ะธ Python, ะฒะฐะผ ะฝัƒะถะฝะพ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต Pydantic v2. /// -ะ•ัะปะธ ัƒ ะฒะฐั ัั‚ะฐั€ะพะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI ั Pydantic v1, ะทะดะตััŒ ั ะฟะพะบะฐะถัƒ, ะบะฐะบ ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ ะฝะฐ Pydantic v2, ะธ **ะฝะพะฒั‹ะต ะฒะพะทะผะพะถะฝะพัั‚ะธ ะฒ FastAPI 0.119.0**, ะบะพั‚ะพั€ั‹ะต ะฟะพะผะพะณัƒั‚ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ะฟะพัั‚ะตะฟะตะฝะฝัƒัŽ ะผะธะณั€ะฐั†ะธัŽ. +ะ•ัะปะธ ัƒ ะฒะฐั ัั‚ะฐั€ะพะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI ั Pydantic v1, ะทะดะตััŒ ั ะฟะพะบะฐะถัƒ, ะบะฐะบ ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ ะฝะฐ Pydantic v2, ะธ **ะฒะพะทะผะพะถะฝะพัั‚ะธ FastAPI 0.119.0**, ะบะพั‚ะพั€ั‹ะต ะฟะพะผะพะณัƒั‚ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ะฟะพัั‚ะตะฟะตะฝะฝัƒัŽ ะผะธะณั€ะฐั†ะธัŽ. ## ะžั„ะธั†ะธะฐะปัŒะฝะพะต ั€ัƒะบะพะฒะพะดัั‚ะฒะพ { #official-guide } @@ -38,13 +40,13 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะธ Pydantic v1, ะธ v2 ะฝะฐั‡ะธะฝะฐั ั ะฒะตั€ ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `bump-pydantic` ะพั‚ ั‚ะพะน ะถะต ะบะพะผะฐะฝะดั‹ Pydantic. -ะญั‚ะพั‚ ะธะฝัั‚ั€ัƒะผะตะฝั‚ ะฟะพะผะพะถะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะฒะฝะตัั‚ะธ ะฑะพะปัŒัˆัƒัŽ ั‡ะฐัั‚ัŒ ะฝะตะพะฑั…ะพะดะธะผั‹ั… ะธะทะผะตะฝะตะฝะธะน ะฒ ะบะพะด. +ะญั‚ะพั‚ ะธะฝัั‚ั€ัƒะผะตะฝั‚ ะฟะพะผะพะถะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะธะทะผะตะฝะธั‚ัŒ ะฑะพะปัŒัˆัƒัŽ ั‡ะฐัั‚ัŒ ะบะพะดะฐ, ะบะพั‚ะพั€ั‹ะน ะฝัƒะถะฝะพ ะธะทะผะตะฝะธั‚ัŒ. -ะŸะพัะปะต ัั‚ะพะณะพ ะทะฐะฟัƒัั‚ะธั‚ะต ั‚ะตัั‚ั‹ ะธ ะฟั€ะพะฒะตั€ัŒั‚ะต, ั‡ั‚ะพ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚. ะ•ัะปะธ ะดะฐ โ€” ะฝะฐ ัั‚ะพะผ ะฒัั‘. ๐Ÿ˜Ž +ะŸะพัะปะต ัั‚ะพะณะพ ะฒั‹ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ัŒ ั‚ะตัั‚ั‹ ะธ ะฟั€ะพะฒะตั€ะธั‚ัŒ, ั‡ั‚ะพ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚. ะ•ัะปะธ ะดะฐ โ€” ะฝะฐ ัั‚ะพะผ ะฒัั‘. ๐Ÿ˜Ž ## Pydantic v1 ะฒ v2 { #pydantic-v1-in-v2 } -Pydantic v2 ะฒะบะปัŽั‡ะฐะตั‚ ะฒัั‘ ะธะท Pydantic v1 ะบะฐะบ ะฟะพะดะผะพะดัƒะปัŒ `pydantic.v1`. +Pydantic v2 ะฒะบะปัŽั‡ะฐะตั‚ ะฒัั‘ ะธะท Pydantic v1 ะบะฐะบ ะฟะพะดะผะพะดัƒะปัŒ `pydantic.v1`. ะะพ ัั‚ะพ ะฑะพะปัŒัˆะต ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั ะฒ ะฒะตั€ัะธัั… Python ะฒั‹ัˆะต 3.13. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะฒั‹ ะผะพะถะตั‚ะต ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ ะฟะพัะปะตะดะฝัŽัŽ ะฒะตั€ัะธัŽ Pydantic v2 ะธ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะฐั€ั‹ะต ะบะพะผะฟะพะฝะตะฝั‚ั‹ Pydantic v1 ะธะท ัั‚ะพะณะพ ะฟะพะดะผะพะดัƒะปั ั‚ะฐะบ, ะบะฐะบ ะตัะปะธ ะฑั‹ ัƒ ะฒะฐั ะฑั‹ะป ัƒัั‚ะฐะฝะพะฒะปะตะฝ ัั‚ะฐั€ั‹ะน Pydantic v1. @@ -52,7 +54,7 @@ Pydantic v2 ะฒะบะปัŽั‡ะฐะตั‚ ะฒัั‘ ะธะท Pydantic v1 ะบะฐะบ ะฟะพะดะผะพะดัƒะปัŒ ` ### ะŸะพะดะดะตั€ะถะบะฐ FastAPI ะดะปั Pydantic v1 ะฒะฝัƒั‚ั€ะธ v2 { #fastapi-support-for-pydantic-v1-in-v2 } -ะะฐั‡ะธะฝะฐั ั FastAPI 0.119.0, ะตัั‚ัŒ ั‚ะฐะบะถะต ั‡ะฐัั‚ะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ Pydantic v1 ะฒ ัะพัั‚ะฐะฒะต Pydantic v2, ั‡ั‚ะพะฑั‹ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะผะธะณั€ะฐั†ะธัŽ ะฝะฐ v2. +ะะฐั‡ะธะฝะฐั ั FastAPI 0.119.0, ะตัั‚ัŒ ั‚ะฐะบะถะต ั‡ะฐัั‚ะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ Pydantic v1 ะธะทะฝัƒั‚ั€ะธ Pydantic v2, ั‡ั‚ะพะฑั‹ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะผะธะณั€ะฐั†ะธัŽ ะฝะฐ v2. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑะฝะพะฒะธั‚ัŒ Pydantic ะดะพ ะฟะพัะปะตะดะฝะตะน ะฒะตั€ัะธะธ 2 ะธ ัะผะตะฝะธั‚ัŒ ะธะผะฟะพั€ั‚ั‹ ะฝะฐ ะฟะพะดะผะพะดัƒะปัŒ `pydantic.v1` โ€” ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฒัั‘ ะฟั€ะพัั‚ะพ ะทะฐั€ะฐะฑะพั‚ะฐะตั‚. @@ -106,7 +108,7 @@ graph TB style V2Field fill:#f9fff3 ``` -ะ’ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะผะพะดะตะปะธ Pydantic v1, ะธ v2 ะฒ ะพะดะฝะพะน ะธ ั‚ะพะน ะถะต ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ) ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั FastAPI: +ะ’ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะผะพะดะตะปะธ Pydantic v1, ะธ v2 ะฒ ะพะดะฝะพะน ะธ ั‚ะพะน ะถะต **ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ** (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ) ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั FastAPI: {* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} @@ -122,12 +124,12 @@ graph TB /// tip | ะกะพะฒะตั‚ -ะกะฝะฐั‡ะฐะปะฐ ะฟะพะฟั€ะพะฑัƒะนั‚ะต `bump-pydantic`. ะ•ัะปะธ ั‚ะตัั‚ั‹ ะฟั€ะพั…ะพะดัั‚ ะธ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚, ะฒั‹ ัะฟั€ะฐะฒะธะปะธััŒ ะพะดะฝะพะน ะบะพะผะฐะฝะดะพะน. โœจ +ะกะฝะฐั‡ะฐะปะฐ ะฟะพะฟั€ะพะฑัƒะนั‚ะต `bump-pydantic`: ะตัะปะธ ั‚ะตัั‚ั‹ ะฟั€ะพั…ะพะดัั‚ ะธ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚, ะฒั‹ ัะฟั€ะฐะฒะธะปะธััŒ ะพะดะฝะพะน ะบะพะผะฐะฝะดะพะน. โœจ /// ะ•ัะปะธ `bump-pydantic` ะฝะต ะฟะพะดั…ะพะดะธั‚ ะดะปั ะฒะฐัˆะตะณะพ ัะปัƒั‡ะฐั, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะพะดะดะตั€ะถะบัƒ ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพะน ั€ะฐะฑะพั‚ั‹ ะผะพะดะตะปะตะน Pydantic v1 ะธ v2 ะฒ ะพะดะฝะพะผ ะฟั€ะธะปะพะถะตะฝะธะธ, ั‡ั‚ะพะฑั‹ ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ ะฝะฐ Pydantic v2 ะฟะพัั‚ะตะฟะตะฝะฝะพ. -ะกะฝะฐั‡ะฐะปะฐ ะพะฑะฝะพะฒะธั‚ะต Pydantic ะดะพ ะฟะพัะปะตะดะฝะตะน 2-ะน ะฒะตั€ัะธะธ ะธ ะธะทะผะตะฝะธั‚ะต ะธะผะฟะพั€ั‚ั‹ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะฒัะต ะฒะฐัˆะธ ะผะพะดะตะปะธ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ `pydantic.v1`. +ะกะฝะฐั‡ะฐะปะฐ ะฒั‹ ะผะพะถะตั‚ะต ะพะฑะฝะพะฒะธั‚ัŒ Pydantic ะดะพ ะฟะพัะปะตะดะฝะตะน 2-ะน ะฒะตั€ัะธะธ ะธ ะธะทะผะตะฝะธั‚ัŒ ะธะผะฟะพั€ั‚ั‹ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะฒัะต ะฒะฐัˆะธ ะผะพะดะตะปะธ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ `pydantic.v1`. -ะ—ะฐั‚ะตะผ ะฝะฐั‡ะฝะธั‚ะต ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ ะฒะฐัˆะธ ะผะพะดะตะปะธ ั Pydantic v1 ะฝะฐ v2 ะณั€ัƒะฟะฟะฐะผะธ, ะฟะพัั‚ะฐะฟะฝะพ. ๐Ÿšถ +ะ—ะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ะฝะฐั‡ะฐั‚ัŒ ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ ะฒะฐัˆะธ ะผะพะดะตะปะธ ั Pydantic v1 ะฝะฐ v2 ะณั€ัƒะฟะฟะฐะผะธ, ะฟะพัั‚ะฐะฟะฝะพ. ๐Ÿšถ diff --git a/docs/ru/docs/how-to/separate-openapi-schemas.md b/docs/ru/docs/how-to/separate-openapi-schemas.md index 5b12140167..8f6c83e7ec 100644 --- a/docs/ru/docs/how-to/separate-openapi-schemas.md +++ b/docs/ru/docs/how-to/separate-openapi-schemas.md @@ -2,7 +2,7 @@ ะŸั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ **Pydantic v2** ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน OpenAPI ัั‚ะฐะฝะพะฒะธั‚ัั ั‡ัƒั‚ัŒ ะฑะพะปะตะต ั‚ะพั‡ะฝั‹ะผ ะธ **ะบะพั€ั€ะตะบั‚ะฝั‹ะผ**, ั‡ะตะผ ั€ะฐะฝัŒัˆะต. ๐Ÿ˜Ž -ะะฐ ัะฐะผะพะผ ะดะตะปะต, ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะฒ OpenAPI ะฑัƒะดะตั‚ ะดะฐะถะต **ะดะฒะต JSON ัั…ะตะผั‹** ะดะปั ะพะดะฝะพะน ะธ ั‚ะพะน ะถะต Pydanticโ€‘ะผะพะดะตะปะธ: ะดะปั ะฒั…ะพะดะฐ ะธ ะดะปั ะฒั‹ั…ะพะดะฐ โ€” ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ ะพั‚ ะฝะฐะปะธั‡ะธั **ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**. +ะะฐ ัะฐะผะพะผ ะดะตะปะต, ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะฒ OpenAPI ะฑัƒะดะตั‚ ะดะฐะถะต **ะดะฒะต JSON-ัั…ะตะผั‹** ะดะปั ะพะดะฝะพะน ะธ ั‚ะพะน ะถะต Pydanticโ€‘ะผะพะดะตะปะธ: ะดะปั ะฒั…ะพะดะฐ ะธ ะดะปั ะฒั‹ั…ะพะดะฐ โ€” ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ ะพั‚ ะฝะฐะปะธั‡ะธั **ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**. ะŸะพัะผะพั‚ั€ะธะผ, ะบะฐะบ ัั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, ะธ ะบะฐะบ ัั‚ะพ ะธะทะผะตะฝะธั‚ัŒ ะฟั€ะธ ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ. @@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -โ€ฆั‚ะพ, ะฟะพัะบะพะปัŒะบัƒ ัƒ `description` ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะดะฐะถะต ะตัะปะธ ะฒั‹ **ะฝะธั‡ะตะณะพ ะฝะต ะฒะตั€ะฝั‘ั‚ะต** ะดะปั ัั‚ะพะณะพ ะฟะพะปั, ะพะฝะพ ะฒัั‘ ั€ะฐะฒะฝะพ ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ัั‚ะพ **ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**. +โ€ฆั‚ะพ, ะฟะพัะบะพะปัŒะบัƒ ัƒ `description` ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะตัะปะธ ะฒั‹ **ะฝะธั‡ะตะณะพ ะฝะต ะฒะตั€ะฝั‘ั‚ะต** ะดะปั ัั‚ะพะณะพ ะฟะพะปั, ะพะฝะพ ะฒัั‘ ั€ะฐะฒะฝะพ ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ัั‚ะพ **ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**. ### ะœะพะดะตะปัŒ ะดะปั ะดะฐะฝะฝั‹ั… ะพั‚ะฒะตั‚ะฐ { #model-for-output-response-data } @@ -46,13 +46,13 @@ ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ัƒ ะฝะตะณะพ **ะฒัะตะณะดะฐ ะฑัƒะดะตั‚ ะบะฐะบะพะตโ€‘ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต**, ะฟั€ะพัั‚ะพ ะธะฝะพะณะดะฐ ัั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None` (ะธะปะธ `null` ะฒ JSON). -ะกะปะตะดะพะฒะฐั‚ะตะปัŒะฝะพ, ะบะปะธะตะฝั‚ะฐะผ, ะธัะฟะพะปัŒะทัƒัŽั‰ะธะผ ะฒะฐัˆ API, ะฝะต ะฝัƒะถะฝะพ ะฟั€ะพะฒะตั€ัั‚ัŒ ะฝะฐะปะธั‡ะธะต ัั‚ะพะณะพ ะทะฝะฐั‡ะตะฝะธั: ะพะฝะธ ะผะพะณัƒั‚ **ะธัั…ะพะดะธั‚ัŒ ะธะท ั‚ะพะณะพ, ั‡ั‚ะพ ะฟะพะปะต ะฒัะตะณะดะฐ ะฟั€ะธััƒั‚ัั‚ะฒัƒะตั‚**, ะฐ ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `None`. +ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะบะปะธะตะฝั‚ะฐะผ, ะธัะฟะพะปัŒะทัƒัŽั‰ะธะผ ะฒะฐัˆ API, ะฝะต ะฝัƒะถะฝะพ ะฟั€ะพะฒะตั€ัั‚ัŒ, ััƒั‰ะตัั‚ะฒัƒะตั‚ ะปะธ ัั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะธะปะธ ะฝะตั‚: ะพะฝะธ ะผะพะณัƒั‚ **ะธัั…ะพะดะธั‚ัŒ ะธะท ั‚ะพะณะพ, ั‡ั‚ะพ ะฟะพะปะต ะฒัะตะณะดะฐ ะฟั€ะธััƒั‚ัั‚ะฒัƒะตั‚**, ะฝะพ ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… ะพะฝะพ ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `None`. ะ’ OpenAPI ัั‚ะพ ะพะฟะธัั‹ะฒะฐะตั‚ัั ั‚ะตะผ, ั‡ั‚ะพ ะฟะพะปะต ะฟะพะผะตั‡ะฐะตั‚ัั ะบะฐะบ **ะพะฑัะทะฐั‚ะตะปัŒะฝะพะต**, ะฟะพัะบะพะปัŒะบัƒ ะพะฝะพ ะฒัะตะณะดะฐ ะฟั€ะธััƒั‚ัั‚ะฒัƒะตั‚. ะ˜ะทโ€‘ะทะฐ ัั‚ะพะณะพ JSON Schema ะดะปั ะผะพะดะตะปะธ ะผะพะถะตั‚ ะพั‚ะปะธั‡ะฐั‚ัŒัั ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ ะพั‚ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะดะปั **ะฒั…ะพะดะฐ** ะธะปะธ **ะฒั‹ั…ะพะดะฐ**: -* ะดะปั **ะฒั…ะพะดะฐ** `description` ะฝะต ะฑัƒะดะตั‚ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ +* ะดะปั **ะฒั…ะพะดะฐ** `description` **ะฝะต ะฑัƒะดะตั‚ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ** * ะดะปั **ะฒั‹ั…ะพะดะฐ** ะพะฝะพ ะฑัƒะดะตั‚ **ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ** (ะธ ะฟั€ะธ ัั‚ะพะผ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None`, ะธะปะธ, ะฒ ั‚ะตั€ะผะธะฝะฐั… JSON, `null`) ### ะ’ั‹ั…ะพะดะฝะฐั ะผะพะดะตะปัŒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #model-for-output-in-docs } @@ -81,9 +81,9 @@ ะžะดะฝะฐะบะพ ะฑั‹ะฒะฐัŽั‚ ัะปัƒั‡ะฐะธ, ะบะพะณะดะฐ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธะผะตั‚ัŒ **ะพะดะฝัƒ ะธ ั‚ัƒ ะถะต ัั…ะตะผัƒ ะดะปั ะฒั…ะพะดะฐ ะธ ะฒั‹ั…ะพะดะฐ**. -ะ“ะปะฐะฒะฝั‹ะน ัั†ะตะฝะฐั€ะธะน โ€” ะบะพะณะดะฐ ัƒ ะฒะฐั ัƒะถะต ะตัั‚ัŒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน ะบะปะธะตะฝั‚ัะบะธะน ะบะพะด/SDK, ะธ ะฒั‹ ะฟะพะบะฐ ะฝะต ั…ะพั‚ะธั‚ะต ะพะฑะฝะพะฒะปัั‚ัŒ ะฒะตััŒ ัั‚ะพั‚ ะฐะฒั‚ะพะณะตะฝะตั€ะธั€ัƒะตะผั‹ะน ะบะพะด/SDK (ั€ะฐะฝะพ ะธะปะธ ะฟะพะทะดะฝะพ ะฒั‹ ัั‚ะพ ัะดะตะปะฐะตั‚ะต, ะฝะพ ะฝะต ัะตะนั‡ะฐั). +ะ“ะปะฐะฒะฝั‹ะน ัั†ะตะฝะฐั€ะธะน โ€” ะบะพะณะดะฐ ัƒ ะฒะฐั ัƒะถะต ะตัั‚ัŒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน ะบะปะธะตะฝั‚ัะบะธะน ะบะพะด/SDK, ะธ ะฒั‹ ะฟะพะบะฐ ะฝะต ั…ะพั‚ะธั‚ะต ะพะฑะฝะพะฒะปัั‚ัŒ ะฒะตััŒ ัั‚ะพั‚ ะฐะฒั‚ะพะณะตะฝะตั€ะธั€ัƒะตะผั‹ะน ะบะปะธะตะฝั‚ัะบะธะน ะบะพะด/SDK, ะฒะตั€ะพัั‚ะฝะพ, ะฒั‹ ะทะฐั…ะพั‚ะธั‚ะต ัะดะตะปะฐั‚ัŒ ัั‚ะพ ะฒ ะบะฐะบะพะน-ั‚ะพ ะผะพะผะตะฝั‚, ะฝะพ, ะฒะพะทะผะพะถะฝะพ, ะฝะต ะฟั€ัะผะพ ัะตะนั‡ะฐั. -ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะพั‚ะบะปัŽั‡ะธั‚ัŒ ัั‚ัƒ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ ะฒ FastAPI ั ะฟะพะผะพั‰ัŒัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `separate_input_output_schemas=False`. +ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะพั‚ะบะปัŽั‡ะธั‚ัŒ ัั‚ัƒ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ ะฒ **FastAPI** ั ะฟะพะผะพั‰ัŒัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `separate_input_output_schemas=False`. /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั @@ -95,10 +95,8 @@ ### ะžะดะฝะฐ ะธ ั‚ะฐ ะถะต ัั…ะตะผะฐ ะดะปั ะฒั…ะพะดะฝะพะน ะธ ะฒั‹ั…ะพะดะฝะพะน ะผะพะดะตะปะตะน ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #same-schema-for-input-and-output-models-in-docs } -ะขะตะฟะตั€ัŒ ะดะปั ัั‚ะพะน ะผะพะดะตะปะธ ะฑัƒะดะตั‚ ะพะดะฝะฐ ะพะฑั‰ะฐั ัั…ะตะผะฐ ะธ ะดะปั ะฒั…ะพะดะฐ, ะธ ะดะปั ะฒั‹ั…ะพะดะฐ โ€” ั‚ะพะปัŒะบะพ `Item`, ะธ ะฒ ะฝะตะน `description` ะฑัƒะดะตั‚ **ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ**: +ะ˜ ั‚ะตะฟะตั€ัŒ ะดะปั ะผะพะดะตะปะธ ะฑัƒะดะตั‚ ะพะดะฝะฐ ะพะฑั‰ะฐั ัั…ะตะผะฐ ะธ ะดะปั ะฒั…ะพะดะฐ, ะธ ะดะปั ะฒั‹ั…ะพะดะฐ โ€” ั‚ะพะปัŒะบะพ `Item`, ะธ ะฒ ะฝะตะน `description` ะฑัƒะดะตั‚ **ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ**:
- -ะญั‚ะพ ั‚ะพ ะถะต ะฟะพะฒะตะดะตะฝะธะต, ั‡ั‚ะพ ะธ ะฒ Pydantic v1. ๐Ÿค“ diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index b562cbe5bc..02b1c9a286 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -5,10 +5,10 @@

- FastAPI + FastAPI

- ะคั€ะตะนะผะฒะพั€ะบ FastAPI: ะฒั‹ัะพะบะฐั ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ, ะฟั€ะพัั‚ ะฒ ะธะทัƒั‡ะตะฝะธะธ, ะฑั‹ัั‚ั€ั‹ะน ะฒ ั€ะฐะทั€ะฐะฑะพั‚ะบะต, ะณะพั‚ะพะฒ ะบ ะฟั€ะพะดะฐะบัˆะฝ + ะคั€ะตะนะผะฒะพั€ะบ FastAPI: ะฒั‹ัะพะบะฐั ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ, ะฟั€ะพัั‚ ะฒ ะธะทัƒั‡ะตะฝะธะธ, ะฟะพะทะฒะพะปัะตั‚ ะฑั‹ัั‚ั€ะพ ะฟะธัะฐั‚ัŒ ะบะพะด, ะณะพั‚ะพะฒ ะบ ะฟั€ะพะดะฐะบัˆะฝ

@@ -40,7 +40,7 @@ FastAPI โ€” ัั‚ะพ ัะพะฒั€ะตะผะตะฝะฝั‹ะน, ะฑั‹ัั‚ั€ั‹ะน (ะฒั‹ัะพะบะพะฟั€ะพะธ * **ะกะบะพั€ะพัั‚ัŒ**: ะžั‡ะตะฝัŒ ะฒั‹ัะพะบะฐั ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ, ะฝะฐ ัƒั€ะพะฒะฝะต **NodeJS** ะธ **Go** (ะฑะปะฐะณะพะดะฐั€ั Starlette ะธ Pydantic). [ะžะดะธะฝ ะธะท ัะฐะผั‹ั… ะฑั‹ัั‚ั€ั‹ั… ะดะพัั‚ัƒะฟะฝั‹ั… ั„ั€ะตะนะผะฒะพั€ะบะพะฒ Python](#performance). * **ะ‘ั‹ัั‚ั€ะพั‚ะฐ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ**: ะฃะฒะตะปะธั‡ัŒั‚ะต ัะบะพั€ะพัั‚ัŒ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ ั„ะธั‡ ะฟั€ะธะผะตั€ะฝะพ ะฝะฐ 200โ€“300%. * * **ะœะตะฝัŒัˆะต ะพัˆะธะฑะพะบ**: ะกะพะบั€ะฐั‚ะธั‚ะต ะฟั€ะธะผะตั€ะฝะพ ะฝะฐ 40% ะบะพะปะธั‡ะตัั‚ะฒะพ ะพัˆะธะฑะพะบ, ะฒั‹ะทะฒะฐะฝะฝั‹ั… ั‡ะตะปะพะฒะตะบะพะผ (ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะผ). * -* **ะ˜ะฝั‚ัƒะธั‚ะธะฒะฝะพัั‚ัŒ**: ะžั‚ะปะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ. ะะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะฒะตะทะดะต. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ะพั‚ะปะฐะดะบัƒ. +* **ะ˜ะฝั‚ัƒะธั‚ะธะฒะฝะพัั‚ัŒ**: ะžั‚ะปะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ. ะะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะฒะตะทะดะต. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ะพั‚ะปะฐะดะบัƒ. * **ะŸั€ะพัั‚ะพั‚ะฐ**: ะ ะฐะทั€ะฐะฑะพั‚ะฐะฝ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะตะณะพ ะฑั‹ะปะพ ะปะตะณะบะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะพัะฒะฐะธะฒะฐั‚ัŒ. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ั‡ั‚ะตะฝะธะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. * **ะšั€ะฐั‚ะบะพัั‚ัŒ**: ะœะธะฝะธะผะธะทะธั€ัƒะนั‚ะต ะดัƒะฑะปะธั€ะพะฒะฐะฝะธะต ะบะพะดะฐ. ะะตัะบะพะปัŒะบะพ ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะธะท ะบะฐะถะดะพะณะพ ะพะฑัŠัะฒะปะตะฝะธั ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ. ะœะตะฝัŒัˆะต ะพัˆะธะฑะพะบ. * **ะะฐะดะตะถะฝะพัั‚ัŒ**: ะŸะพะปัƒั‡ะธั‚ะต ะบะพะด, ะณะพั‚ะพะฒั‹ะน ะบ ะฟั€ะพะดะฐะบัˆะฝ. ะก ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน. @@ -117,6 +117,12 @@ FastAPI โ€” ัั‚ะพ ัะพะฒั€ะตะผะตะฝะฝั‹ะน, ะฑั‹ัั‚ั€ั‹ะน (ะฒั‹ัะพะบะพะฟั€ะพะธ --- +## ะœะธะฝะธ-ะดะพะบัƒะผะตะฝั‚ะฐะปัŒะฝั‹ะน ั„ะธะปัŒะผ ะพ FastAPI { #fastapi-mini-documentary } + +ะ’ ะบะพะฝั†ะต 2025 ะณะพะดะฐ ะฒั‹ัˆะตะป ะผะธะฝะธ-ะดะพะบัƒะผะตะฝั‚ะฐะปัŒะฝั‹ะน ั„ะธะปัŒะผ ะพ FastAPI, ะฒั‹ ะผะพะถะตั‚ะต ะฟะพัะผะพั‚ั€ะตั‚ัŒ ะตะณะพ ะพะฝะปะฐะนะฝ: + +FastAPI Mini Documentary + ## **Typer**, FastAPI ะดะปั CLI { #typer-the-fastapi-of-clis } @@ -257,7 +263,7 @@ INFO: Application startup complete. * ะŸะพะปัƒั‡ะฐะตั‚ HTTP-ะทะฐะฟั€ะพัั‹ ะฟะพ _ะฟัƒั‚ัะผ_ `/` ะธ `/items/{item_id}`. * ะžะฑะฐ _ะฟัƒั‚ะธ_ ะธัะฟะพะปัŒะทัƒัŽั‚ `GET` ะพะฟะตั€ะฐั†ะธะธ (ั‚ะฐะบะถะต ะธะทะฒะตัั‚ะฝั‹ะต ะบะฐะบ HTTP _ะผะตั‚ะพะดั‹_). -* _ะŸัƒั‚ัŒ_ `/items/{item_id}` ะธะผะตะตั‚ _ะฟะฐั€ะฐะผะตั‚ั€ ะฟัƒั‚ะธ_ `item_id`, ะบะพั‚ะพั€ั‹ะน ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `int`. +* _ะŸัƒั‚ัŒ_ `/items/{item_id}` ะธะผะตะตั‚ _path-ะฟะฐั€ะฐะผะตั‚ั€_ `item_id`, ะบะพั‚ะพั€ั‹ะน ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `int`. * _ะŸัƒั‚ัŒ_ `/items/{item_id}` ะธะผะตะตั‚ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน `str` _ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ_ `q`. ### ะ˜ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั API { #interactive-api-docs } @@ -278,9 +284,9 @@ INFO: Application startup complete. ## ะŸั€ะธะผะตั€ ะพะฑะฝะพะฒะปะตะฝะธั { #example-upgrade } -ะขะตะฟะตั€ัŒ ะธะทะผะตะฝะธั‚ะต ั„ะฐะนะป `main.py`, ั‡ั‚ะพะฑั‹ ะฟั€ะธะฝะธะผะฐั‚ัŒ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะธะท `PUT` ะทะฐะฟั€ะพัะฐ. +ะขะตะฟะตั€ัŒ ะธะทะผะตะฝะธั‚ะต ั„ะฐะนะป `main.py`, ั‡ั‚ะพะฑั‹ ะฟั€ะธะฝะธะผะฐั‚ัŒ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะธะท `PUT` HTTP-ะทะฐะฟั€ะพัะฐ. -ะžะฑัŠัะฒะธั‚ะต ั‚ะตะปะพ, ะธัะฟะพะปัŒะทัƒั ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ั‚ะธะฟั‹ Python, ัะฟะฐัะธะฑะพ Pydantic. +ะžะฑัŠัะฒะธั‚ะต ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ, ะธัะฟะพะปัŒะทัƒั ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ั‚ะธะฟั‹ Python, ัะฟะฐัะธะฑะพ Pydantic. ```Python hl_lines="4 9-12 25-27" from typing import Union @@ -318,7 +324,7 @@ def update_item(item_id: int, item: Item): ะŸะตั€ะตะนะดะธั‚ะต ะฝะฐ http://127.0.0.1:8000/docs. -* ะ˜ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั API ะฑัƒะดะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑะฝะพะฒะปะตะฝะฐ, ะฒะบะปัŽั‡ะฐั ะฝะพะฒะพะต ั‚ะตะปะพ: +* ะ˜ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั API ะฑัƒะดะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑะฝะพะฒะปะตะฝะฐ, ะฒะบะปัŽั‡ะฐั ะฝะพะฒะพะต ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ: ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -334,13 +340,13 @@ def update_item(item_id: int, item: Item): ะขะตะฟะตั€ัŒ ะพั‚ะบั€ะพะนั‚ะต http://127.0.0.1:8000/redoc. -* ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั ั‚ะฐะบะถะต ะพั‚ั€ะฐะทะธั‚ ะฝะพะฒั‹ะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ ะธ ั‚ะตะปะพ: +* ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั ั‚ะฐะบะถะต ะพั‚ั€ะฐะทะธั‚ ะฝะพะฒั‹ะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ ะธ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) ### ะŸะพะดะฒะตะดั‘ะผ ะธั‚ะพะณะธ { #recap } -ะ˜ั‚ะฐะบ, ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต **ะพะดะธะฝ ั€ะฐะท** ั‚ะธะฟั‹ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ั‚ะตะปะฐ ะทะฐะฟั€ะพัะฐ ะธ ั‚.ะด. ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั„ัƒะฝะบั†ะธะธ. +ะ˜ั‚ะฐะบ, ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต **ะพะดะธะฝ ั€ะฐะท** ั‚ะธะฟั‹ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะธ ั‚.ะด. ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั„ัƒะฝะบั†ะธะธ. ะ’ั‹ ะดะตะปะฐะตั‚ะต ัั‚ะพ ั ะฟะพะผะพั‰ัŒัŽ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ั… ัะพะฒั€ะตะผะตะฝะฝั‹ั… ั‚ะธะฟะพะฒ Python. @@ -390,13 +396,13 @@ item: Item ะ’ะพะทะฒั€ะฐั‰ะฐัััŒ ะบ ะฟั€ะตะดั‹ะดัƒั‰ะตะผัƒ ะฟั€ะธะผะตั€ัƒ ะบะพะดะฐ, **FastAPI** ะฑัƒะดะตั‚: -* ะ’ะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ ะฝะฐะปะธั‡ะธะต `item_id` ะฒ ะฟัƒั‚ะธ ะดะปั `GET` ะธ `PUT` ะทะฐะฟั€ะพัะพะฒ. -* ะ’ะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ, ั‡ั‚ะพ `item_id` ะธะผะตะตั‚ ั‚ะธะฟ `int` ะดะปั `GET` ะธ `PUT` ะทะฐะฟั€ะพัะพะฒ. +* ะ’ะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ ะฝะฐะปะธั‡ะธะต `item_id` ะฒ ะฟัƒั‚ะธ ะดะปั `GET` ะธ `PUT` HTTP-ะทะฐะฟั€ะพัะพะฒ. +* ะ’ะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ, ั‡ั‚ะพ `item_id` ะธะผะตะตั‚ ั‚ะธะฟ `int` ะดะปั `GET` ะธ `PUT` HTTP-ะทะฐะฟั€ะพัะพะฒ. * ะ•ัะปะธ ัั‚ะพ ะฝะต ั‚ะฐะบ, ะบะปะธะตะฝั‚ ัƒะฒะธะดะธั‚ ะฟะพะปะตะทะฝัƒัŽ ะฟะพะฝัั‚ะฝัƒัŽ ะพัˆะธะฑะบัƒ. -* ะŸั€ะพะฒะตั€ัั‚ัŒ, ะตัั‚ัŒ ะปะธ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ ั ะธะผะตะฝะตะผ `q` (ะฝะฐะฟั€ะธะผะตั€, `http://127.0.0.1:8000/items/foo?q=somequery`) ะดะปั `GET` ะทะฐะฟั€ะพัะพะฒ. +* ะŸั€ะพะฒะตั€ัั‚ัŒ, ะตัั‚ัŒ ะปะธ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ ั ะธะผะตะฝะตะผ `q` (ะฝะฐะฟั€ะธะผะตั€, `http://127.0.0.1:8000/items/foo?q=somequery`) ะดะปั `GET` HTTP-ะทะฐะฟั€ะพัะพะฒ. * ะŸะพัะบะพะปัŒะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ `q` ะพะฑัŠัะฒะปะตะฝ ั `= None`, ะพะฝ ะฝะตะพะฑัะทะฐั‚ะตะปะตะฝ. * ะ‘ะตะท `None` ะพะฝ ะฑั‹ะป ะฑั‹ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ (ะบะฐะบ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะฒ ัะปัƒั‡ะฐะต ั `PUT`). -* ะ”ะปั `PUT` ะทะฐะฟั€ะพัะพะฒ ะบ `/items/{item_id}` ั‡ะธั‚ะฐั‚ัŒ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะบะฐะบ JSON: +* ะ”ะปั `PUT` HTTP-ะทะฐะฟั€ะพัะพะฒ ะบ `/items/{item_id}` ั‡ะธั‚ะฐั‚ัŒ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะบะฐะบ JSON: * ะŸั€ะพะฒะตั€ัั‚ัŒ, ั‡ั‚ะพ ะตัั‚ัŒ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน ะฐั‚ั€ะธะฑัƒั‚ `name`, ะบะพั‚ะพั€ั‹ะน ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `str`. * ะŸั€ะพะฒะตั€ัั‚ัŒ, ั‡ั‚ะพ ะตัั‚ัŒ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน ะฐั‚ั€ะธะฑัƒั‚ `price`, ะบะพั‚ะพั€ั‹ะน ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `float`. * ะŸั€ะพะฒะตั€ัั‚ัŒ, ั‡ั‚ะพ ะตัั‚ัŒ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน ะฐั‚ั€ะธะฑัƒั‚ `is_offer`, ะบะพั‚ะพั€ั‹ะน ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `bool`, ะตัะปะธ ะพะฝ ะฟั€ะธััƒั‚ัั‚ะฒัƒะตั‚. @@ -435,11 +441,11 @@ item: Item ะ‘ะพะปะตะต ะฟะพะปะฝั‹ะน ะฟั€ะธะผะตั€ ั ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะผะธ ะฒะพะทะผะพะถะฝะพัั‚ัะผะธ ัะผ. ะฒ ะฃั‡ะตะฑะฝะธะบ - ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั. -**ะžัั‚ะพั€ะพะถะฝะพ, ัะฟะพะนะปะตั€**: ัƒั‡ะตะฑะฝะธะบ - ั€ัƒะบะพะฒะพะดัั‚ะฒะพ ะฒะบะปัŽั‡ะฐะตั‚: +**ะžัั‚ะพั€ะพะถะฝะพ, ัะฟะพะนะปะตั€**: ัƒั‡ะตะฑะฝะธะบ - ั€ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะฒะบะปัŽั‡ะฐะตั‚: * ะžะฑัŠัะฒะปะตะฝะธะต **ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ** ะธะท ะดั€ัƒะณะธั… ะธัั‚ะพั‡ะฝะธะบะพะฒ: **HTTP-ะทะฐะณะพะปะพะฒะบะธ**, **cookies**, **ะฟะพะปั ั„ะพั€ะผั‹** ะธ **ั„ะฐะนะปั‹**. * ะšะฐะบ ะทะฐะดะฐั‚ัŒ **ะพะณั€ะฐะฝะธั‡ะตะฝะธั ะฒะฐะปะธะดะฐั†ะธะธ** ะฒั€ะพะดะต `maximum_length` ะธะปะธ `regex`. -* ะžั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ ะธ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ัะธัั‚ะตะผัƒ **ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. +* ะžั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ ะธ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ัะธัั‚ะตะผัƒ **ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. * ะ‘ะตะทะพะฟะฐัะฝะพัั‚ัŒ ะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธัŽ, ะฒะบะปัŽั‡ะฐั ะฟะพะดะดะตั€ะถะบัƒ **OAuth2** ั **JWT ั‚ะพะบะตะฝะฐะผะธ** ะธ **HTTP Basic** ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธัŽ. * ะ‘ะพะปะตะต ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ะต (ะฝะพ ัั‚ะพะปัŒ ะถะต ะฟั€ะพัั‚ั‹ะต) ะฟั€ะธั‘ะผั‹ ะพะฑัŠัะฒะปะตะฝะธั **ะณะปัƒะฑะพะบะพ ะฒะปะพะถะตะฝะฝั‹ั… JSON-ะผะพะดะตะปะตะน** (ัะฟะฐัะธะฑะพ Pydantic). * ะ˜ะฝั‚ะตะณั€ะฐั†ะธัŽ **GraphQL** ั Strawberry ะธ ะดั€ัƒะณะธะผะธ ะฑะธะฑะปะธะพั‚ะตะบะฐะผะธ. @@ -524,11 +530,11 @@ FastAPI ะทะฐะฒะธัะธั‚ ะพั‚ Pydantic ะธ Starlette. * httpx โ€” ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `TestClient`. * jinja2 โ€” ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะพะฝั„ะธะณัƒั€ะฐั†ะธัŽ ัˆะฐะฑะปะพะฝะพะฒ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. -* python-multipart โ€” ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ยซะฟะฐั€ัะธะฝะณยป ั„ะพั€ะผ ั‡ะตั€ะตะท `request.form()`. +* python-multipart - ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ยซะฟะฐั€ัะธะฝะณยป ั„ะพั€ะผ ั‡ะตั€ะตะท `request.form()`. ะ˜ัะฟะพะปัŒะทัƒะตั‚ัั FastAPI: -* uvicorn โ€” ัะตั€ะฒะตั€, ะบะพั‚ะพั€ั‹ะน ะทะฐะณั€ัƒะถะฐะตั‚ ะธ ะพะฑัะปัƒะถะธะฒะฐะตั‚ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต. ะ’ะบะปัŽั‡ะฐะตั‚ `uvicorn[standard]`, ัะพะดะตั€ะถะฐั‰ะธะน ะฝะตะบะพั‚ะพั€ั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ (ะฝะฐะฟั€ะธะผะตั€, `uvloop`), ะฝัƒะถะฝั‹ะต ะดะปั ะฒั‹ัะพะบะพะน ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ. +* uvicorn โ€” ัะตั€ะฒะตั€, ะบะพั‚ะพั€ั‹ะน ะทะฐะณั€ัƒะถะฐะตั‚ ะธ ยซะพั‚ะดะฐั‘ั‚ยป ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต. ะ’ะบะปัŽั‡ะฐะตั‚ `uvicorn[standard]`, ัะพะดะตั€ะถะฐั‰ะธะน ะฝะตะบะพั‚ะพั€ั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ (ะฝะฐะฟั€ะธะผะตั€, `uvloop`), ะฝัƒะถะฝั‹ะต ะดะปั ะฒั‹ัะพะบะพะน ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ. * `fastapi-cli[standard]` โ€” ั‡ั‚ะพะฑั‹ ะฟั€ะตะดะพัั‚ะฐะฒะธั‚ัŒ ะบะพะผะฐะฝะดัƒ `fastapi`. * ะ’ะบะปัŽั‡ะฐะตั‚ `fastapi-cloud-cli`, ะบะพั‚ะพั€ั‹ะน ะฟะพะทะฒะพะปัะตั‚ ั€ะฐะทะฒะตั€ะฝัƒั‚ัŒ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI ะฒ FastAPI Cloud. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 5e5d6ada94..76304523c9 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -1,4 +1,4 @@ -# ะ‘ะพะปัŒัˆะธะต ะฟั€ะธะปะพะถะตะฝะธั, ะฒ ะบะพั‚ะพั€ั‹ั… ะผะฝะพะณะพ ั„ะฐะนะปะพะฒ { #bigger-applications-multiple-files } +# ะ‘ะพะปัŒัˆะธะต ะฟั€ะธะปะพะถะตะฝะธั โ€” ะฝะตัะบะพะปัŒะบะพ ั„ะฐะนะปะพะฒ { #bigger-applications-multiple-files } ะŸั€ะธ ะฟะพัั‚ั€ะพะตะฝะธะธ ะฟั€ะธะปะพะถะตะฝะธั ะธะปะธ ะฒะตะฑ-API ะฝะฐะผ ั€ะตะดะบะพ ัƒะดะฐะตั‚ัั ะฟะพะผะตัั‚ะธั‚ัŒ ะฒัั‘ ะฒ ะพะดะธะฝ ั„ะฐะนะป. @@ -31,7 +31,7 @@ /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ะฒ ะบะฐะถะดะพะผ ะบะฐั‚ะฐะปะพะณะต ะธ ะฟะพะดะบะฐั‚ะฐะปะพะณะต ะธะผะตะตั‚ัั ั„ะฐะนะป `__init__.py` +ะ•ัั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ั„ะฐะนะปะพะฒ `__init__.py`: ะฟะพ ะพะดะฝะพะผัƒ ะฒ ะบะฐะถะดะพะผ ะบะฐั‚ะฐะปะพะณะต ะธะปะธ ะฟะพะดะบะฐั‚ะฐะปะพะณะต. ะญั‚ะพ ะบะฐะบ ั€ะฐะท ั‚ะพ, ั‡ั‚ะพ ะฟะพะทะฒะพะปัะตั‚ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะบะพะด ะธะท ะพะดะฝะพะณะพ ั„ะฐะนะปะฐ ะฒ ะดั€ัƒะณะพะน. @@ -43,61 +43,63 @@ from app.routers import items /// -* ะ’ัั‘ ะฟะพะผะตั‰ะฐะตั‚ัั ะฒ ะบะฐั‚ะฐะปะพะณะต `app`. ะ’ ะฝั‘ะผ ั‚ะฐะบะถะต ะฝะฐั…ะพะดะธั‚ัั ะฟัƒัั‚ะพะน ั„ะฐะนะป `app/__init__.py`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, `app` ัะฒะปัะตั‚ัั "Python-ะฟะฐะบะตั‚ะพะผ" (ะบะพะปะปะตะบั†ะธะตะน ะผะพะดัƒะปะตะน Python). -* ะžะฝ ัะพะดะตั€ะถะธั‚ ั„ะฐะนะป `app/main.py`. ะ”ะฐะฝะฝั‹ะน ั„ะฐะนะป ัะฒะปัะตั‚ัั ั‡ะฐัั‚ัŒัŽ ะฟะฐะบะตั‚ะฐ (ั‚.ะต. ะฝะฐั…ะพะดะธั‚ัั ะฒะฝัƒั‚ั€ะธ ะบะฐั‚ะฐะปะพะณะฐ, ัะพะดะตั€ะถะฐั‰ะตะณะพ ั„ะฐะนะป `__init__.py`), ะธ, ัะพะพั‚ะฒะตั‚ัั‚ะฒะตะฝะฝะพ, ะพะฝ ัะฒะปัะตั‚ัั ะผะพะดัƒะปะตะผ ะฟะฐะบะตั‚ะฐ: `app.main`. +* ะ’ัั‘ ะฟะพะผะตั‰ะฐะตั‚ัั ะฒ ะบะฐั‚ะฐะปะพะณะต `app`. ะ’ ะฝั‘ะผ ั‚ะฐะบะถะต ะฝะฐั…ะพะดะธั‚ัั ะฟัƒัั‚ะพะน ั„ะฐะนะป `app/__init__.py`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, `app` ัะฒะปัะตั‚ัั "Python-ะฟะฐะบะตั‚ะพะผ" (ะบะพะปะปะตะบั†ะธะตะน "Python-ะผะพะดัƒะปะตะน"): `app`. +* ะžะฝ ัะพะดะตั€ะถะธั‚ ั„ะฐะนะป `app/main.py`. ะ”ะฐะฝะฝั‹ะน ั„ะฐะนะป ัะฒะปัะตั‚ัั ั‡ะฐัั‚ัŒัŽ Python-ะฟะฐะบะตั‚ะฐ (ั‚.ะต. ะฝะฐั…ะพะดะธั‚ัั ะฒะฝัƒั‚ั€ะธ ะบะฐั‚ะฐะปะพะณะฐ, ัะพะดะตั€ะถะฐั‰ะตะณะพ ั„ะฐะนะป `__init__.py`), ะธ, ัะพะพั‚ะฒะตั‚ัั‚ะฒะตะฝะฝะพ, ะพะฝ ัะฒะปัะตั‚ัั ะผะพะดัƒะปะตะผ ัั‚ะพะณะพ ะฟะฐะบะตั‚ะฐ: `app.main`. * ะžะฝ ั‚ะฐะบะถะต ัะพะดะตั€ะถะธั‚ ั„ะฐะนะป `app/dependencies.py`, ะบะพั‚ะพั€ั‹ะน ั‚ะฐะบะถะต, ะบะฐะบ ะธ `app/main.py`, ัะฒะปัะตั‚ัั ะผะพะดัƒะปะตะผ: `app.dependencies`. -* ะ—ะดะตััŒ ั‚ะฐะบะถะต ะฝะฐั…ะพะดะธั‚ัั ะฟะพะดะบะฐั‚ะฐะปะพะณ `app/routers/`, ัะพะดะตั€ะถะฐั‰ะธะน `__init__.py`. ะžะฝ ัะฒะปัะตั‚ัั ััƒะฑ-ะฟะฐะบะตั‚ะพะผ: `app.routers`. -* ะคะฐะนะป `app/routers/items.py` ะฝะฐั…ะพะดะธั‚ัั ะฒะฝัƒั‚ั€ะธ ะฟะฐะบะตั‚ะฐ `app/routers/`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะพะฝ ัะฒะปัะตั‚ัั ััƒะฑ-ะผะพะดัƒะปะตะผ: `app.routers.items`. -* ะขะพั‡ะฝะพ ั‚ะฐะบะถะต `app/routers/users.py` ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ ััƒะฑ-ะผะพะดัƒะปะตะผ: `app.routers.users`. -* ะŸะพะดะบะฐั‚ะฐะปะพะณ `app/internal/`, ัะพะดะตั€ะถะฐั‰ะธะน ั„ะฐะนะป `__init__.py`, ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ ััƒะฑ-ะฟะฐะบะตั‚ะพะผ: `app.internal`. -* ะ ั„ะฐะนะป `app/internal/admin.py` ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ ััƒะฑ-ะผะพะดัƒะปะตะผ: `app.internal.admin`. +* ะ—ะดะตััŒ ั‚ะฐะบะถะต ะฝะฐั…ะพะดะธั‚ัั ะฟะพะดะบะฐั‚ะฐะปะพะณ `app/routers/`, ัะพะดะตั€ะถะฐั‰ะธะน `__init__.py`. ะžะฝ ัะฒะปัะตั‚ัั Python-ะฟะพะดะฟะฐะบะตั‚ะพะผ: `app.routers`. +* ะคะฐะนะป `app/routers/items.py` ะฝะฐั…ะพะดะธั‚ัั ะฒะฝัƒั‚ั€ะธ ะฟะฐะบะตั‚ะฐ `app/routers/`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะพะฝ ัะฒะปัะตั‚ัั ะฟะพะดะผะพะดัƒะปะตะผ: `app.routers.items`. +* ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต `app/routers/users.py` ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ ะฟะพะดะผะพะดัƒะปะตะผ: `app.routers.users`. +* ะŸะพะดะบะฐั‚ะฐะปะพะณ `app/internal/`, ัะพะดะตั€ะถะฐั‰ะธะน ั„ะฐะนะป `__init__.py`, ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ Python-ะฟะพะดะฟะฐะบะตั‚ะพะผ: `app.internal`. +* ะ ั„ะฐะนะป `app/internal/admin.py` ัะฒะปัะตั‚ัั ะตั‰ั‘ ะพะดะฝะธะผ ะฟะพะดะผะพะดัƒะปะตะผ: `app.internal.admin`. ะขะฐ ะถะต ัะฐะผะฐั ั„ะฐะนะปะพะฒะฐั ัั‚ั€ัƒะบั‚ัƒั€ะฐ ะฟั€ะธะปะพะถะตะฝะธั, ะฝะพ ั ะบะพะผะผะตะฝั‚ะฐั€ะธัะผะธ: -``` +```bash . โ”œโ”€โ”€ app # "app" ะฟะฐะบะตั‚ โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ัั‚ะพั‚ ั„ะฐะนะป ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ "app" ะฒ "Python-ะฟะฐะบะตั‚" โ”‚ย ย  โ”œโ”€โ”€ main.py # ะผะพะดัƒะปัŒ "main", ะฝะฐะฟั€.: import app.main โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # ะผะพะดัƒะปัŒ "dependencies", ะฝะฐะฟั€.: import app.dependencies -โ”‚ย ย  โ””โ”€โ”€ routers # ััƒะฑ-ะฟะฐะบะตั‚ "routers" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ "routers" ะฒ ััƒะฑ-ะฟะฐะบะตั‚ -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # ััƒะฑ-ะผะพะดัƒะปัŒ "items", ะฝะฐะฟั€.: import app.routers.items -โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # ััƒะฑ-ะผะพะดัƒะปัŒ "users", ะฝะฐะฟั€.: import app.routers.users -โ”‚ย ย  โ””โ”€โ”€ internal # ััƒะฑ-ะฟะฐะบะตั‚ "internal" -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ "internal" ะฒ ััƒะฑ-ะฟะฐะบะตั‚ -โ”‚ย ย  โ””โ”€โ”€ admin.py # ััƒะฑ-ะผะพะดัƒะปัŒ "admin", ะฝะฐะฟั€.: import app.internal.admin +โ”‚ย ย  โ””โ”€โ”€ routers # ะฟะพะดะฟะฐะบะตั‚ "routers" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ "routers" ะฒ ะฟะพะดะฟะฐะบะตั‚ +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # ะฟะพะดะผะพะดัƒะปัŒ "items", ะฝะฐะฟั€.: import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # ะฟะพะดะผะพะดัƒะปัŒ "users", ะฝะฐะฟั€.: import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # ะฟะพะดะฟะฐะบะตั‚ "internal" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ "internal" ะฒ ะฟะพะดะฟะฐะบะตั‚ +โ”‚ย ย  โ””โ”€โ”€ admin.py # ะฟะพะดะผะพะดัƒะปัŒ "admin", ะฝะฐะฟั€.: import app.internal.admin ``` ## `APIRouter` { #apirouter } -ะ”ะฐะฒะฐะนั‚ะต ะฟั€ะตะดะฟะพะปะพะถะธะผ, ั‡ั‚ะพ ะดะปั ั€ะฐะฑะพั‚ั‹ ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัะผะธ ะธัะฟะพะปัŒะทัƒะตั‚ัั ะพั‚ะดะตะปัŒะฝั‹ะน ั„ะฐะนะป (ััƒะฑ-ะผะพะดัƒะปัŒ) `/app/routers/users.py`. +ะ”ะฐะฒะฐะนั‚ะต ะฟั€ะตะดะฟะพะปะพะถะธะผ, ั‡ั‚ะพ ะดะปั ั€ะฐะฑะพั‚ั‹ ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัะผะธ ะธัะฟะพะปัŒะทัƒะตั‚ัั ะพั‚ะดะตะปัŒะฝั‹ะน ั„ะฐะนะป (ะฟะพะดะผะพะดัƒะปัŒ) `/app/routers/users.py`. -ะ”ะปั ะปัƒั‡ัˆะตะน ะพั€ะณะฐะฝะธะทะฐั†ะธะธ ะฟั€ะธะปะพะถะตะฝะธั, ะฒั‹ ั…ะพั‚ะธั‚ะต ะพั‚ะดะตะปะธั‚ัŒ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ, ัะฒัะทะฐะฝะฝั‹ะต ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัะผะธ, ะพั‚ ะพัั‚ะฐะปัŒะฝะพะณะพ ะบะพะดะฐ. +ะ’ั‹ ั…ะพั‚ะธั‚ะต ะพั‚ะดะตะปะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ัะฒัะทะฐะฝะฝั‹ะต ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัะผะธ, ะพั‚ ะพัั‚ะฐะปัŒะฝะพะณะพ ะบะพะดะฐ, ั‡ั‚ะพะฑั‹ ัะพั…ั€ะฐะฝะธั‚ัŒ ะฟะพั€ัะดะพะบ. -ะะพ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ัั‚ะธ ะพะฟะตั€ะฐั†ะธะธ ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ะพัั‚ะฐะฒะฐะปะธััŒ ั‡ะฐัั‚ัŒัŽ **FastAPI** ะฟั€ะธะปะพะถะตะฝะธั/ะฒะตะฑ-API (ั‡ะฐัั‚ัŒัŽ ะพะดะฝะพะณะพ ะฟะฐะบะตั‚ะฐ) +ะะพ ัั‚ะพ ะฒัั‘ ั€ะฐะฒะฝะพ ั‡ะฐัั‚ัŒ ั‚ะพะณะพ ะถะต ะฟั€ะธะปะพะถะตะฝะธั/ะฒะตะฑ-API ะฝะฐ **FastAPI** (ั‡ะฐัั‚ัŒ ั‚ะพะณะพ ะถะต ยซPython-ะฟะฐะบะตั‚ะฐยป). -ะก ะฟะพะผะพั‰ัŒัŽ `APIRouter` ะฒั‹ ะผะพะถะตั‚ะต ัะพะทะดะฐั‚ัŒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* (*ัะฝะดะฟะพะธะฝั‚ั‹*) ะดะปั ะดะฐะฝะฝะพะณะพ ะผะพะดัƒะปั. +ะก ะฟะพะผะพั‰ัŒัŽ `APIRouter` ะฒั‹ ะผะพะถะตั‚ะต ัะพะทะดะฐั‚ัŒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะดะปั ัั‚ะพะณะพ ะผะพะดัƒะปั. ### ะ˜ะผะฟะพั€ั‚ `APIRouter` { #import-apirouter } -ะขะพั‡ะฝะพ ั‚ะฐะบะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั ะบะปะฐััะพะผ `FastAPI`, ะฒะฐะผ ะฝัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ัะพะทะดะฐั‚ัŒ ะพะฑัŠะตะบั‚ ะบะปะฐััะฐ `APIRouter`. +ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั ะบะปะฐััะพะผ `FastAPI`, ะฒะฐะผ ะฝัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ัะพะทะดะฐั‚ัŒ ะตะณะพ ยซัะบะทะตะผะฟะปัั€ยป: {* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} -### ะกะพะทะดะฐะฝะธะต *ัะฝะดะฟะพะธะฝั‚ะพะฒ* ั ะฟะพะผะพั‰ัŒัŽ `APIRouter` { #path-operations-with-apirouter } +### *ะžะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ั `APIRouter` { #path-operations-with-apirouter } + +ะ˜ ะทะฐั‚ะตะผ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะตะณะพ, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะธั‚ัŒ ะฒะฐัˆะธ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. -ะ’ ะดะฐะปัŒะฝะตะนัˆะตะผ ะธัะฟะพะปัŒะทัƒะนั‚ะต `APIRouter` ะดะปั ะพะฑัŠัะฒะปะตะฝะธั *ัะฝะดะฟะพะธะฝั‚ะพะฒ*, ั‚ะพั‡ะฝะพ ั‚ะฐะบะถะต, ะบะฐะบ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะบะปะฐัั `FastAPI`: +ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะตะณะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ ะฑั‹ ะบะปะฐัั `FastAPI`: {* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} -ะ’ั‹ ะผะพะถะตั‚ะต ะดัƒะผะฐั‚ัŒ ะพะฑ `APIRouter` ะบะฐะบ ะพะฑ "ัƒะผะตะฝัŒัˆะตะฝะฝะพะน ะฒะตั€ัะธะธ" ะบะปะฐััะฐ FastAPI`. +ะ’ั‹ ะผะพะถะตั‚ะต ะดัƒะผะฐั‚ัŒ ะพะฑ `APIRouter` ะบะฐะบ ะพะฑ ยซะผะธะฝะธ-ะบะปะฐััะต `FastAPI`ยป. -`APIRouter` ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฒัะต ั‚ะต ะถะต ัะฐะผั‹ะต ะพะฟั†ะธะธ. +ะŸะพะดะดะตั€ะถะธะฒะฐัŽั‚ัั ะฒัะต ั‚ะต ะถะต ะพะฟั†ะธะธ. -`APIRouter` ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฒัะต ั‚ะต ะถะต ัะฐะผั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹, ั‚ะฐะบะธะต ะบะฐะบ `parameters`, `responses`, `dependencies`, `tags`, ะธ ั‚. ะด. +ะ’ัะต ั‚ะต ะถะต `parameters`, `responses`, `dependencies`, `tags` ะธ ั‚.ะด. /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -105,21 +107,21 @@ from app.routers import items /// -ะœั‹ ัะพะฑะธั€ะฐะตะผัั ะฟะพะดะบะปัŽั‡ะธั‚ัŒ ะดะฐะฝะฝั‹ะน `APIRouter` ะบ ะฝะฐัˆะตะผัƒ ะพัะฝะพะฒะฝะพะผัƒ ะฟั€ะธะปะพะถะตะฝะธัŽ ะฝะฐ `FastAPI`, ะฝะพ ัะฝะฐั‡ะฐะปะฐ ะดะฐะฒะฐะนั‚ะต ะฟั€ะพะฒะตั€ะธะผ ะทะฐะฒะธัะธะผะพัั‚ะธ ะธ ัะพะทะดะฐะดะธะผ ะตั‰ั‘ ะพะดะธะฝ ะผะพะดัƒะปัŒ ั `APIRouter`. +ะœั‹ ัะพะฑะธั€ะฐะตะผัั ะฟะพะดะบะปัŽั‡ะธั‚ัŒ ะดะฐะฝะฝั‹ะน `APIRouter` ะบ ะฝะฐัˆะตะผัƒ ะพัะฝะพะฒะฝะพะผัƒ ะฟั€ะธะปะพะถะตะฝะธัŽ ะฝะฐ `FastAPI`, ะฝะพ ัะฝะฐั‡ะฐะปะฐ ะดะฐะฒะฐะนั‚ะต ะฟั€ะพะฒะตั€ะธะผ ะทะฐะฒะธัะธะผะพัั‚ะธ ะธ ะตั‰ั‘ ะพะดะธะฝ `APIRouter`. ## ะ—ะฐะฒะธัะธะผะพัั‚ะธ { #dependencies } -ะะฐะผ ะฟะพะฝะฐะดะพะฑัั‚ัั ะฝะตะบะพั‚ะพั€ั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะผั‹ ะฑัƒะดะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒ ั€ะฐะทะฝั‹ั… ะผะตัั‚ะฐั… ะฝะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั. +ะœั‹ ะฒะธะดะธะผ, ั‡ั‚ะพ ะฝะฐะผ ะฟะพะฝะฐะดะพะฑัั‚ัั ะฝะตะบะพั‚ะพั€ั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฒ ะฝะตัะบะพะปัŒะบะธั… ะผะตัั‚ะฐั… ะฟั€ะธะปะพะถะตะฝะธั. -ะœั‹ ะฟะพะผะตัั‚ะธะผ ะธั… ะฒ ะพั‚ะดะตะปัŒะฝั‹ะน ะผะพะดัƒะปัŒ `dependencies` (`app/dependencies.py`). +ะŸะพัั‚ะพะผัƒ ะผั‹ ะฟะพะผะตัั‚ะธะผ ะธั… ะฒ ะพั‚ะดะตะปัŒะฝั‹ะน ะผะพะดัƒะปัŒ `dependencies` (`app/dependencies.py`). -ะขะตะฟะตั€ัŒ ะผั‹ ะฒะพัะฟะพะปัŒะทัƒะตะผัั ะฟั€ะพัั‚ะพะน ะทะฐะฒะธัะธะผะพัั‚ัŒัŽ, ั‡ั‚ะพะฑั‹ ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ ะบะฐัั‚ะพะผะธะทะธั€ะพะฒะฐะฝะฝั‹ะน `X-Token` ะธะท ะทะฐะณะพะปะพะฒะบะฐ: +ะขะตะฟะตั€ัŒ ะผั‹ ะฒะพัะฟะพะปัŒะทัƒะตะผัั ะฟั€ะพัั‚ะพะน ะทะฐะฒะธัะธะผะพัั‚ัŒัŽ, ั‡ั‚ะพะฑั‹ ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ ะบะฐัั‚ะพะผะฝั‹ะน HTTP-ะทะฐะณะพะปะพะฒะพะบ `X-Token`: {* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ”ะปั ะฟั€ะพัั‚ะพั‚ั‹ ะผั‹ ะฒะพัะฟะพะปัŒะทะพะฒะฐะปะธััŒ ะฝะตะบะธะผ ะฒะพะพะฑั€ะฐะถะฐะตะผั‹ะผ ะทะฐะณะพะปะพะฒะพะบะพะผ. +ะ”ะปั ะฟั€ะพัั‚ะพั‚ั‹ ะผั‹ ะฒะพัะฟะพะปัŒะทะพะฒะฐะปะธััŒ ะฒั‹ะดัƒะผะฐะฝะฝั‹ะผ ะทะฐะณะพะปะพะฒะบะพะผ. ะ’ ั€ะตะฐะปัŒะฝั‹ั… ัะปัƒั‡ะฐัั… ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะฝะฐะธะปัƒั‡ัˆะธั… ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะฒ ะธัะฟะพะปัŒะทัƒะนั‚ะต ะธะฝั‚ะตะณั€ะธั€ะพะฒะฐะฝะฝั‹ะต [ัƒั‚ะธะปะธั‚ั‹ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ](security/index.md){.internal-link target=_blank}. @@ -127,30 +129,29 @@ from app.routers import items ## ะ•ั‰ั‘ ะพะดะธะฝ ะผะพะดัƒะปัŒ ั `APIRouter` { #another-module-with-apirouter } -ะ”ะฐะฒะฐะนั‚ะต ั‚ะฐะบะถะต ะฟั€ะตะดะฟะพะปะพะถะธะผ, ั‡ั‚ะพ ัƒ ะฒะฐั ะตัั‚ัŒ *ัะฝะดะฟะพะธะฝั‚ั‹*, ะพั‚ะฒะตั‡ะฐัŽั‰ะธะต ะทะฐ ะพะฑั€ะฐะฑะพั‚ะบัƒ "items", ะธ ะพะฝะธ ะฝะฐั…ะพะดัั‚ัั ะฒ ะผะพะดัƒะปะต `app/routers/items.py`. +ะ”ะฐะฒะฐะนั‚ะต ั‚ะฐะบะถะต ะฟั€ะตะดะฟะพะปะพะถะธะผ, ั‡ั‚ะพ ัƒ ะฒะฐั ะตัั‚ัŒ ัะฝะดะฟะพะธะฝั‚ั‹, ะพั‚ะฒะตั‡ะฐัŽั‰ะธะต ะทะฐ ะพะฑั€ะฐะฑะพั‚ะบัƒ ยซitemsยป ะฒ ะฒะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ, ะธ ะพะฝะธ ะฝะฐั…ะพะดัั‚ัั ะฒ ะผะพะดัƒะปะต `app/routers/items.py`. -ะฃ ะฒะฐั ะพะฟั€ะตะดะตะปะตะฝั‹ ัะปะตะดัƒัŽั‰ะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* (*ัะฝะดะฟะพะธะฝั‚ั‹*): +ะฃ ะฒะฐั ะพะฟั€ะตะดะตะปะตะฝั‹ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะดะปั: * `/items/` * `/items/{item_id}` -ะขัƒั‚ ะฒัั‘ ั‚ะพั‡ะฝะพ ั‚ะฐะบะถะต, ะบะฐะบ ะธ ะฒ ัะธั‚ัƒะฐั†ะธะธ ั `app/routers/users.py`. +ะขัƒั‚ ะฒัั‘ ั‚ะฐ ะถะต ัั‚ั€ัƒะบั‚ัƒั€ะฐ, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั `app/routers/users.py`. -ะะพ ั‚ะตะฟะตั€ัŒ ะผั‹ ั…ะพั‚ะธะผ ะฟะพัั‚ัƒะฟะธั‚ัŒ ะฝะตะผะฝะพะณะพ ัƒะผะฝะตะต ะธ ัะปะตะณะบะฐ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะบะพะด. +ะะพ ะผั‹ ั…ะพั‚ะธะผ ะฟะพัั‚ัƒะฟะธั‚ัŒ ัƒะผะฝะตะต ะธ ัะปะตะณะบะฐ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะบะพะด. -ะœั‹ ะทะฝะฐะตะผ, ั‡ั‚ะพ ะฒัะต *ัะฝะดะฟะพะธะฝั‚ั‹* ะดะฐะฝะฝะพะณะพ ะผะพะดัƒะปั ะธะผะตัŽั‚ ะฝะตะบะพั‚ะพั€ั‹ะต ะพะฑั‰ะธะต ัะฒะพะนัั‚ะฒะฐ: +ะœั‹ ะทะฝะฐะตะผ, ั‡ั‚ะพ ะฒัะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ัั‚ะพะณะพ ะผะพะดัƒะปั ะธะผะตัŽั‚ ะพะดะธะฝะฐะบะพะฒั‹ะต: -* ะŸั€ะตั„ะธะบั ะฟัƒั‚ะธ: `/items`. -* ะขะตะณะธ: (ะพะดะธะฝ ะตะดะธะฝัั‚ะฒะตะฝะฝั‹ะน ั‚ะตะณ: `items`). -* ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะพั‚ะฒะตั‚ั‹ (responses) -* ะ—ะฐะฒะธัะธะผะพัั‚ะธ: ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ัะพะทะดะฐะฝะฝะพะน ะฝะฐะผะธ ะทะฐะฒะธัะธะผะพัั‚ะธ `X-token` +* `prefix` ะฟัƒั‚ะธ: `/items`. +* `tags`: (ะพะดะธะฝ ะตะดะธะฝัั‚ะฒะตะฝะฝั‹ะน ั‚ะตะณ: `items`). +* ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต `responses`. +* `dependencies`: ะฒัะตะผ ะธะผ ะฝัƒะถะฝะฐ ั‚ะฐ ะทะฐะฒะธัะธะผะพัั‚ัŒ `X-Token`, ะบะพั‚ะพั€ัƒัŽ ะผั‹ ัะพะทะดะฐะปะธ. -ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะดะพะฑะฐะฒะปัั‚ัŒ ะฒัะต ัั‚ะธ ัะฒะพะนัั‚ะฒะฐ ะฒ ั„ัƒะฝะบั†ะธัŽ ะบะฐะถะดะพะณะพ ะพั‚ะดะตะปัŒะฝะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ*, -ะผั‹ ะดะพะฑะฐะฒะธะผ ะธั… ะฒ `APIRouter`. +ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะดะพะฑะฐะฒะปัั‚ัŒ ะฒัั‘ ัั‚ะพ ะฒ ะบะฐะถะดัƒัŽ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ*, ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ัั‚ะพ ะฒ `APIRouter`. {* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} -ะขะฐะบ ะบะฐะบ ะบะฐะถะดั‹ะน *ัะฝะดะฟะพะธะฝั‚* ะฝะฐั‡ะธะฝะฐะตั‚ัั ั ัะธะผะฒะพะปะฐ `/`: +ะขะฐะบ ะบะฐะบ ะฟัƒั‚ัŒ ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะดะพะปะถะตะฝ ะฝะฐั‡ะธะฝะฐั‚ัŒัั ั `/`, ะบะฐะบ ะทะดะตััŒ: ```Python hl_lines="1" @router.get("/{item_id}") @@ -162,73 +163,74 @@ async def read_item(item_id: str): ะ’ ะฝะฐัˆะตะผ ัะปัƒั‡ะฐะต ะฟั€ะตั„ะธะบัะพะผ ัะฒะปัะตั‚ัั `/items`. -ะœั‹ ั‚ะฐะบะถะต ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ะฒ ะฝะฐัˆ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ (router) ัะฟะธัะพะบ `ั‚ะตะณะพะฒ` (`tags`) ะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… `ะพั‚ะฒะตั‚ะพะฒ` (`responses`), ะบะพั‚ะพั€ั‹ะต ัะฒะปััŽั‚ัั ะพะฑั‰ะธะผะธ ะดะปั ะบะฐะถะดะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ*. +ะœั‹ ั‚ะฐะบะถะต ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ัะฟะธัะพะบ `tags` ะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต `responses`, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะฟั€ะธะผะตะฝัั‚ัŒัั ะบะพ ะฒัะตะผ *ะพะฟะตั€ะฐั†ะธัะผ ะฟัƒั‚ะธ*, ะฒะบะปัŽั‡ั‘ะฝะฝั‹ะผ ะฒ ัั‚ะพั‚ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€. -ะ˜ ะตั‰ั‘ ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ะฒ ะฝะฐัˆ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ ัะฟะธัะพะบ `ะทะฐะฒะธัะธะผะพัั‚ะตะน`, ะบะพั‚ะพั€ั‹ะต ะดะพะปะถะฝั‹ ะฒั‹ะทั‹ะฒะฐั‚ัŒัั ะฟั€ะธ ะบะฐะถะดะพะผ ะพะฑั€ะฐั‰ะตะฝะธะธ ะบ *ัะฝะดะฟะพะธะฝั‚ะฐะผ*. +ะ˜ ะตั‰ั‘ ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ัะฟะธัะพะบ `dependencies`, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะดะพะฑะฐะฒะปะตะฝั‹ ะบะพ ะฒัะตะผ *ะพะฟะตั€ะฐั†ะธัะผ ะฟัƒั‚ะธ* ะฒ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะต ะธ ะฑัƒะดัƒั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒัั/ั€ะฐะทั€ะตัˆะฐั‚ัŒัั ะดะปั ะบะฐะถะดะพะณะพ HTTP-ะทะฐะฟั€ะพัะฐ ะบ ะฝะธะผ. /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ั‚ะฐะบะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั ะทะฐะฒะธัะธะผะพัั‚ัะผะธ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… *ัะฝะดะฟะพะธะฝั‚ะพะฒ* ([ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), ะฝะธะบะฐะบะพะณะพ ะทะฝะฐั‡ะตะฝะธั ะฒ *ั„ัƒะฝะบั†ะธัŽ ัะฝะดะฟะพะธะฝั‚ะฐ* ะฟะตั€ะตะดะฐะฝะพ ะฝะต ะฑัƒะดะตั‚. +ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั [ะทะฐะฒะธัะธะผะพัั‚ัะผะธ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะฝะธะบะฐะบะพะต ะทะฝะฐั‡ะตะฝะธะต ะฝะต ะฑัƒะดะตั‚ ะฟะตั€ะตะดะฐะฝะพ ะฒ ะฒะฐัˆัƒ *ั„ัƒะฝะบั†ะธัŽ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ะฟัƒั‚ะธ*. /// -ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ะผั‹ ะฟะพะปัƒั‡ะธะผ ัะปะตะดัƒัŽั‰ะธะต ัะฝะดะฟะพะธะฝั‚ั‹: +ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ะฟัƒั‚ะธ ะดะปั items ั‚ะตะฟะตั€ัŒ ั‚ะฐะบะธะต: * `/items/` * `/items/{item_id}` ...ะบะฐะบ ะผั‹ ะธ ะฟะปะฐะฝะธั€ะพะฒะฐะปะธ. -* ะžะฝะธ ะฑัƒะดัƒั‚ ะฟะพะผะตั‡ะตะฝั‹ ั‚ะตะณะฐะผะธ ะธะท ะทะฐะดะฐะฝะฝะพะณะพ ัะฟะธัะบะฐ, ะฒ ะฝะฐัˆะตะผ ัะปัƒั‡ะฐะต ัั‚ะพ `"items"`. - * ะญั‚ะธ ั‚ะตะณะธ ะพัะพะฑะตะฝะฝะพ ะฟะพะปะตะทะฝั‹ ะดะปั ัะธัั‚ะตะผั‹ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ (ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ OpenAPI). -* ะšะฐะถะดั‹ะน ะธะท ะฝะธั… ะฑัƒะดะตั‚ ะฒะบะปัŽั‡ะฐั‚ัŒ ะฟั€ะตะดะพะฟั€ะตะดะตะปะตะฝะฝั‹ะต ะพั‚ะฒะตั‚ั‹ `responses`. -* ะšะฐะถะดั‹ะน *ัะฝะดะฟะพะธะฝั‚* ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ัะฟะธัะพะบ ะทะฐะฒะธัะธะผะพัั‚ะตะน (`dependencies`), ะธัะฟะพะปะฝัะตะผั‹ั… ะฟะตั€ะตะด ะฒั‹ะทะพะฒะพะผ *ัะฝะดะฟะพะธะฝั‚ะฐ*. - * ะ•ัะปะธ ะฒั‹ ะพะฟั€ะตะดะตะปะธะปะธ ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ัะฐะผะพะน ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ, **ั‚ะพ ะพะฝะฐ ั‚ะฐะบะถะต ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝะตะฝะฐ**. - * ะกะฝะฐั‡ะฐะปะฐ ะฒั‹ะฟะพะปะฝััŽั‚ัั ะทะฐะฒะธัะธะผะพัั‚ะธ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ, ะทะฐั‚ะตะผ ะฒั‹ะทั‹ะฒะฐัŽั‚ัั [ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะต](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะธ, ะฝะฐะบะพะฝะตั†, ะพะฑั‹ั‡ะฝั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ะธั‡ะตัะบะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ. - * ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ [ะทะฐะฒะธัะธะผะพัั‚ะธ `Security` ั `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}. +* ะžะฝะธ ะฑัƒะดัƒั‚ ะฟะพะผะตั‡ะตะฝั‹ ัะฟะธัะบะพะผ ั‚ะตะณะพะฒ, ัะพะดะตั€ะถะฐั‰ะธะผ ะพะดะฝัƒ ัั‚ั€ะพะบัƒ `"items"`. + * ะญั‚ะธ ยซั‚ะตะณะธยป ะพัะพะฑะตะฝะฝะพ ะฟะพะปะตะทะฝั‹ ะดะปั ัะธัั‚ะตะผ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ (ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ OpenAPI). +* ะ’ัะต ะพะฝะธ ะฑัƒะดัƒั‚ ะฒะบะปัŽั‡ะฐั‚ัŒ ะฟั€ะตะดะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ะต `responses`. +* ะ’ัะต ัั‚ะธ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฑัƒะดัƒั‚ ะธะผะตั‚ัŒ ัะฟะธัะพะบ `dependencies`, ะฒั‹ั‡ะธัะปัะตะผั‹ั…/ะฒั‹ะฟะพะปะฝัะตะผั‹ั… ะฟะตั€ะตะด ะฝะธะผะธ. + * ะ•ัะปะธ ะฒั‹ ั‚ะฐะบะถะต ะพะฑัŠัะฒะธั‚ะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, **ะพะฝะธ ั‚ะพะถะต ะฑัƒะดัƒั‚ ะฒั‹ะฟะพะปะฝะตะฝั‹**. + * ะกะฝะฐั‡ะฐะปะฐ ะฒั‹ะฟะพะปะฝััŽั‚ัั ะทะฐะฒะธัะธะผะพัั‚ะธ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ, ะทะฐั‚ะตะผ [`dependencies` ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะต](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะธ ะทะฐั‚ะตะผ ะพะฑั‹ั‡ะฝั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ะธั‡ะตัะบะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ. + * ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ [`Security`-ะทะฐะฒะธัะธะผะพัั‚ะธ ั `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}. /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะะฐะฟั€ะธะผะตั€, ั ะฟะพะผะพั‰ัŒัŽ ะทะฐะฒะธัะธะผะพัั‚ะตะน ะฒ `APIRouter` ะผั‹ ะผะพะถะตะผ ะฟะพั‚ั€ะตะฑะพะฒะฐั‚ัŒ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะดะปั ะดะพัั‚ัƒะฟะฐ ะบะพ ะฒัะตะน ะณั€ัƒะฟะฟะต *ัะฝะดะฟะพะธะฝั‚ะพะฒ*, ะฝะต ัƒะบะฐะทั‹ะฒะฐั ะทะฐะฒะธัะธะผะพัั‚ะธ ะดะปั ะบะฐะถะดะพะน ะพั‚ะดะตะปัŒะฝะพะน ั„ัƒะฝะบั†ะธะธ *ัะฝะดะฟะพะธะฝั‚ะฐ*. +ะะฐะฟั€ะธะผะตั€, ั ะฟะพะผะพั‰ัŒัŽ ะทะฐะฒะธัะธะผะพัั‚ะตะน ะฒ `APIRouter` ะผั‹ ะผะพะถะตะผ ะฟะพั‚ั€ะตะฑะพะฒะฐั‚ัŒ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะดะปั ะดะพัั‚ัƒะฟะฐ ะบะพ ะฒัะตะน ะณั€ัƒะฟะฟะต *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*. ะ”ะฐะถะต ะตัะปะธ ะทะฐะฒะธัะธะผะพัั‚ะธ ะฝะต ะดะพะฑะฐะฒะปััŽั‚ัั ะฟะพ ะพั‚ะดะตะปัŒะฝะพัั‚ะธ ะบ ะบะฐะถะดะพะน ะธะท ะฝะธั…. /// /// check | ะ—ะฐะผะตั‚ะบะฐ -ะŸะฐั€ะฐะผะตั‚ั€ั‹ `prefix`, `tags`, `responses` ะธ `dependencies` ะพั‚ะฝะพััั‚ัั ะบ ั„ัƒะฝะบั†ะธะพะฝะฐะปัƒ **FastAPI**, ะฟะพะผะพะณะฐัŽั‰ะตะผัƒ ะธะทะฑะตะถะฐั‚ัŒ ะดัƒะฑะปะธั€ะพะฒะฐะฝะธั ะบะพะดะฐ. +ะŸะฐั€ะฐะผะตั‚ั€ั‹ `prefix`, `tags`, `responses` ะธ `dependencies` โ€” ัั‚ะพ (ะบะฐะบ ะธ ะฒะพ ะผะฝะพะณะธั… ะดั€ัƒะณะธั… ัะปัƒั‡ะฐัั…) ะฟั€ะพัั‚ะพ ะฒะพะทะผะพะถะฝะพัั‚ัŒ **FastAPI**, ะฟะพะผะพะณะฐัŽั‰ะฐั ะธะทะฑะตะถะฐั‚ัŒ ะดัƒะฑะปะธั€ะพะฒะฐะฝะธั ะบะพะดะฐ. /// ### ะ˜ะผะฟะพั€ั‚ ะทะฐะฒะธัะธะผะพัั‚ะตะน { #import-the-dependencies } -ะะฐัˆ ะบะพะด ะฝะฐั…ะพะดะธั‚ัั ะฒ ะผะพะดัƒะปะต `app.routers.items` (ั„ะฐะนะป `app/routers/items.py`). +ะญั‚ะพั‚ ะบะพะด ะฝะฐั…ะพะดะธั‚ัั ะฒ ะผะพะดัƒะปะต `app.routers.items`, ะฒ ั„ะฐะนะปะต `app/routers/items.py`. -ะ˜ ะฝะฐะผ ะฝัƒะถะฝะพ ะฒั‹ะทะฒะฐั‚ัŒ ั„ัƒะฝะบั†ะธัŽ ะทะฐะฒะธัะธะผะพัั‚ะธ ะธะท ะผะพะดัƒะปั `app.dependencies` (ั„ะฐะนะป `app/dependencies.py`). +ะ˜ ะฝะฐะผ ะฝัƒะถะฝะพ ะฟะพะปัƒั‡ะธั‚ัŒ ั„ัƒะฝะบั†ะธัŽ ะทะฐะฒะธัะธะผะพัั‚ะธ ะธะท ะผะพะดัƒะปั `app.dependencies`, ั„ะฐะนะปะฐ `app/dependencies.py`. -ะœั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะพะฟะตั€ะฐั†ะธัŽ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพะณะพ ะธะผะฟะพั€ั‚ะฐ `..` ะดะปั ะธะผะฟะพั€ั‚ะฐ ะทะฐะฒะธัะธะผะพัั‚ะธ: +ะŸะพัั‚ะพะผัƒ ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚ ั `..` ะดะปั ะทะฐะฒะธัะธะผะพัั‚ะตะน: {* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} -#### ะšะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚? { #how-relative-imports-work } +#### ะšะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚ { #how-relative-imports-work } /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ•ัะปะธ ะฒั‹ ะฟั€ะตะบั€ะฐัะฝะพ ะทะฝะฐะตั‚ะต, ะบะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะธะผะฟะพั€ั‚ ะฒ Python, ั‚ะพ ะฟะตั€ะตั…ะพะดะธั‚ะต ะบ ัะปะตะดัƒัŽั‰ะตะผัƒ ั€ะฐะทะดะตะปัƒ. +ะ•ัะปะธ ะฒั‹ ะฟั€ะตะบั€ะฐัะฝะพ ะทะฝะฐะตั‚ะต, ะบะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะธะผะฟะพั€ั‚, ะฟะตั€ะตั…ะพะดะธั‚ะต ะบ ัะปะตะดัƒัŽั‰ะตะผัƒ ั€ะฐะทะดะตะปัƒ ะฝะธะถะต. /// -ะžะดะฝะฐ ั‚ะพั‡ะบะฐ `.`, ะบะฐะบ ะฒ ะดะฐะฝะฝะพะผ ะฟั€ะธะผะตั€ะต: +ะžะดะฝะฐ ั‚ะพั‡ะบะฐ `.`, ะบะฐะบ ะทะดะตััŒ: ```Python from .dependencies import get_token_header ``` + ะพะทะฝะฐั‡ะฐะตั‚: -* ะะฐั‡ะฝะธั‚ะต ั ะฟะฐะบะตั‚ะฐ, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ะดะฐะฝะฝั‹ะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py` ั€ะฐัะฟะพะปะพะถะตะฝ ะฒ ะบะฐั‚ะฐะปะพะณะต `app/routers/`)... -* ... ะฝะฐะนะดะธั‚ะต ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/routers/dependencies.py`)... -* ... ะธ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. +* ะะฐั‡ะฐั‚ัŒ ะฒ ั‚ะพะผ ะถะต ะฟะฐะบะตั‚ะต, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ัั‚ะพั‚ ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ะฒะพะพะฑั€ะฐะถะฐะตะผั‹ะน ั„ะฐะนะป `app/routers/dependencies.py`)... +* ะธ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. -ะš ัะพะถะฐะปะตะฝะธัŽ, ั‚ะฐะบะพะณะพ ั„ะฐะนะปะฐ ะฝะต ััƒั‰ะตัั‚ะฒัƒะตั‚, ะธ ะฝะฐัˆะธ ะทะฐะฒะธัะธะผะพัั‚ะธ ะฝะฐั…ะพะดัั‚ัั ะฒ ั„ะฐะนะปะต `app/dependencies.py`. +ะะพ ั‚ะฐะบะพะณะพ ั„ะฐะนะปะฐ ะฝะต ััƒั‰ะตัั‚ะฒัƒะตั‚, ะฝะฐัˆะธ ะทะฐะฒะธัะธะผะพัั‚ะธ ะฝะฐั…ะพะดัั‚ัั ะฒ ั„ะฐะนะปะต `app/dependencies.py`. ะ’ัะฟะพะผะฝะธั‚ะต, ะบะฐะบ ะฒั‹ะณะปัะดะธั‚ ั„ะฐะนะปะพะฒะฐั ัั‚ั€ัƒะบั‚ัƒั€ะฐ ะฝะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั: @@ -236,7 +238,7 @@ from .dependencies import get_token_header --- -ะ”ะฒะต ั‚ะพั‡ะบะธ `..`, ะบะฐะบ ะฒ ะดะฐะฝะฝะพะผ ะฟั€ะธะผะตั€ะต: +ะ”ะฒะต ั‚ะพั‡ะบะธ `..`, ะบะฐะบ ะทะดะตััŒ: ```Python from ..dependencies import get_token_header @@ -244,12 +246,12 @@ from ..dependencies import get_token_header ะพะทะฝะฐั‡ะฐัŽั‚: -* ะะฐั‡ะฝะธั‚ะต ั ะฟะฐะบะตั‚ะฐ, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ะดะฐะฝะฝั‹ะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py` ะฝะฐั…ะพะดะธั‚ัั ะฒ ะบะฐั‚ะฐะปะพะณะต `app/routers/`)... -* ... ะฟะตั€ะตะนะดะธั‚ะต ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ (ะบะฐั‚ะฐะปะพะณ `app/`)... -* ... ะฝะฐะนะดะธั‚ะต ะฒ ะฝั‘ะผ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... -* ... ะธ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. +* ะะฐั‡ะฐั‚ัŒ ะฒ ั‚ะพะผ ะถะต ะฟะฐะบะตั‚ะต, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ัั‚ะพั‚ ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะฟะตั€ะตะนั‚ะธ ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ (ะบะฐั‚ะฐะปะพะณ `app/`)... +* ะธ ั‚ะฐะผ ะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... +* ะธ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. -ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ะฒะตั€ะฝะพ! ๐ŸŽ‰ +ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ะบะพั€ั€ะตะบั‚ะฝะพ! ๐ŸŽ‰ --- @@ -261,29 +263,29 @@ from ...dependencies import get_token_header ั‚ะพ ัั‚ะพ ะฑั‹ ะพะทะฝะฐั‡ะฐะปะพ: -* ะะฐั‡ะฝะธั‚ะต ั ะฟะฐะบะตั‚ะฐ, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ะดะฐะฝะฝั‹ะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py` ะฝะฐั…ะพะดะธั‚ัั ะฒ ะบะฐั‚ะฐะปะพะณะต `app/routers/`)... -* ... ะฟะตั€ะตะนะดะธั‚ะต ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ (ะบะฐั‚ะฐะปะพะณ `app/`)... -* ... ะทะฐั‚ะตะผ ะฟะตั€ะตะนะดะธั‚ะต ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ ั‚ะตะบัƒั‰ะตะณะพ ะฟะฐะบะตั‚ะฐ (ั‚ะฐะบะพะณะพ ะฟะฐะบะตั‚ะฐ ะฝะต ััƒั‰ะตัั‚ะฒัƒะตั‚, `app` ะฝะฐั…ะพะดะธั‚ัั ะฝะฐ ัะฐะผะพะผ ะฒะตั€ั…ะฝะตะผ ัƒั€ะพะฒะฝะต ๐Ÿ˜ฑ)... -* ... ะฝะฐะนะดะธั‚ะต ะฒ ะฝั‘ะผ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... -* ... ะธ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. +* ะะฐั‡ะฐั‚ัŒ ะฒ ั‚ะพะผ ะถะต ะฟะฐะบะตั‚ะต, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ัั‚ะพั‚ ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) ั€ะฐัะฟะพะปะพะถะตะฝ ะฒ (ะบะฐั‚ะฐะปะพะณะต `app/routers/`)... +* ะฟะตั€ะตะนั‚ะธ ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ (ะบะฐั‚ะฐะปะพะณ `app/`)... +* ะทะฐั‚ะตะผ ะฟะตั€ะตะนั‚ะธ ะฒ ั€ะพะดะธั‚ะตะปัŒัะบะธะน ะฟะฐะบะตั‚ ัั‚ะพะณะพ ะฟะฐะบะตั‚ะฐ (ั€ะพะดะธั‚ะตะปัŒัะบะพะณะพ ะฟะฐะบะตั‚ะฐ ะฝะตั‚, `app` โ€” ะฒะตั€ั…ะฝะธะน ัƒั€ะพะฒะตะฝัŒ ๐Ÿ˜ฑ)... +* ะธ ั‚ะฐะผ ะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... +* ะธ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธะท ะฝะตะณะพ ั„ัƒะฝะบั†ะธัŽ `get_token_header`. -ะญั‚ะพ ะฑัƒะดะตั‚ ะพั‚ะฝะพัะธั‚ัŒัั ะบ ะฝะตะบะพั‚ะพั€ะพะผัƒ ะฟะฐะบะตั‚ัƒ, ะฝะฐั…ะพะดัั‰ะตะผัƒัั ะฝะฐ ะพะดะธะฝ ัƒั€ะพะฒะตะฝัŒ ะฒั‹ัˆะต ั‡ะตะผ `app/` ะธ ัะพะดะตั€ะถะฐั‰ะตะผัƒ ัะฒะพะน ัะพะฑัั‚ะฒะตะฝะฝั‹ะน ั„ะฐะนะป `__init__.py`. ะะพ ะฝะธั‡ะตะณะพ ั‚ะฐะบะพะณะพ ัƒ ะฝะฐั ะฝะตั‚. ะŸะพัั‚ะพะผัƒ ัั‚ะพ ะฟั€ะธะฒะตะดะตั‚ ะบ ะพัˆะธะฑะบะต ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะผะตั€ะต. ๐Ÿšจ +ะญั‚ะพ ััั‹ะปะฐะปะพััŒ ะฑั‹ ะฝะฐ ะบะฐะบะพะน-ั‚ะพ ะฟะฐะบะตั‚ ะฒั‹ัˆะต `app/`, ัะพ ัะฒะพะธะผ ั„ะฐะนะปะพะผ `__init__.py` ะธ ั‚.ะฟ. ะะพ ัƒ ะฝะฐั ั‚ะฐะบะพะณะพ ะฝะตั‚. ะŸะพัั‚ะพะผัƒ ัั‚ะพ ะฒั‹ะทะฒะฐะปะพ ะฑั‹ ะพัˆะธะฑะบัƒ ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะผะตั€ะต. ๐Ÿšจ -ะขะตะฟะตั€ัŒ ะฒั‹ ะทะฝะฐะตั‚ะต, ะบะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะธะผะฟะพั€ั‚ ะฒ Python, ะธ ัะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพะต ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะฝะธะต ะฒ ัะฒะพะธั… ัะพะฑัั‚ะฒะตะฝะฝั‹ั… ะฟั€ะธะปะพะถะตะฝะธัั… ะปัŽะฑะพะณะพ ัƒั€ะพะฒะฝั ัะปะพะถะฝะพัั‚ะธ. ๐Ÿค“ +ะะพ ั‚ะตะฟะตั€ัŒ ะฒั‹ ะทะฝะฐะตั‚ะต, ะบะฐะบ ัั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, ั‚ะฐะบ ั‡ั‚ะพ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะต ะธะผะฟะพั€ั‚ั‹ ะฒ ัะฒะพะธั… ะฟั€ะธะปะพะถะตะฝะธัั…, ะฝะตะทะฐะฒะธัะธะผะพ ะพั‚ ั‚ะพะณะพ, ะฝะฐัะบะพะปัŒะบะพ ะพะฝะธ ัะปะพะถะฝั‹ะต. ๐Ÿค“ -### ะ”ะพะฑะฐะฒะปะตะฝะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… ั‚ะตะณะพะฒ (`tags`), ะพั‚ะฒะตั‚ะพะฒ (`responses`) ะธ ะทะฐะฒะธัะธะผะพัั‚ะตะน (`dependencies`) { #add-some-custom-tags-responses-and-dependencies } +### ะ”ะพะฑะฐะฒะปะตะฝะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… `tags`, `responses` ะธ `dependencies` { #add-some-custom-tags-responses-and-dependencies } -ะœั‹ ะฝะต ะฑัƒะดะตะผ ะดะพะฑะฐะฒะปัั‚ัŒ ะฟั€ะตั„ะธะบั `/items` ะธ ัะฟะธัะพะบ ั‚ะตะณะพะฒ `tags=["items"]` ะดะปั ะบะฐะถะดะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ*, ั‚.ะบ. ะผั‹ ัƒะถะต ะธั… ะดะพะฑะฐะฒะธะปะธ ั ะฟะพะผะพั‰ัŒัŽ `APIRouter`. +ะœั‹ ะฝะต ะดะพะฑะฐะฒะปัะตะผ ะฟั€ะตั„ะธะบั `/items` ะธ `tags=["items"]` ะบ ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ะผั‹ ะดะพะฑะฐะฒะธะปะธ ะธั… ะฒ `APIRouter`. -ะะพ ะฟะพะผะธะผะพ ัั‚ะพะณะพ ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ะฝะพะฒั‹ะต ั‚ะตะณะธ ะดะปั ะบะฐะถะดะพะณะพ ะพั‚ะดะตะปัŒะฝะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ*, ะฐ ั‚ะฐะบะถะต ะฝะตะบะพั‚ะพั€ั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะพั‚ะฒะตั‚ั‹ (`responses`), ั…ะฐั€ะฐะบั‚ะตั€ะฝั‹ะต ะดะปั ะดะฐะฝะฝะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ*: +ะะพ ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ _ะตั‰ั‘_ `tags`, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะฟั€ะธะผะตะฝัั‚ัŒัั ะบ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะฐ ั‚ะฐะบะถะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต `responses`, ัะฟะตั†ะธั„ะธั‡ะฝั‹ะต ะดะปั ัั‚ะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*: {* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะŸะพัะปะตะดะฝะธะน *ัะฝะดะฟะพะธะฝั‚* ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ัะปะตะดัƒัŽั‰ัƒัŽ ะบะพะผะฑะธะฝะฐั†ะธัŽ ั‚ะตะณะพะฒ: `["items", "custom"]`. +ะญั‚ะฐ ะฟะพัะปะตะดะฝัั ะพะฟะตั€ะฐั†ะธั ะฟัƒั‚ะธ ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ะบะพะผะฑะธะฝะฐั†ะธัŽ ั‚ะตะณะพะฒ: `["items", "custom"]`. -ะ ั‚ะฐะบะถะต ะฒ ะตะณะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฑัƒะดัƒั‚ ัะพะดะตั€ะถะฐั‚ัŒัั ะพะฑะฐ ะพั‚ะฒะตั‚ะฐ: ะพะดะธะฝ ะดะปั `404` ะธ ะดั€ัƒะณะพะน ะดะปั `403`. +ะ˜ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ัƒ ะฝะตั‘ ะฑัƒะดัƒั‚ ะพะฑะฐ ะพั‚ะฒะตั‚ะฐ: ะพะดะธะฝ ะดะปั `404` ะธ ะพะดะธะฝ ะดะปั `403`. /// @@ -293,29 +295,29 @@ from ...dependencies import get_token_header ะ˜ะผะตะฝะฝะพ ััŽะดะฐ ะฒั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตั‚ะต ะธ ะธะผะตะฝะฝะพ ะทะดะตััŒ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะบะปะฐัั `FastAPI`. -ะญั‚ะพ ะพัะฝะพะฒะฝะพะน ั„ะฐะนะป ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั, ะบะพั‚ะพั€ั‹ะน ะพะฑัŠะตะดะธะฝัะตั‚ ะฒัั‘ ะฒ ะพะดะฝะพ ั†ะตะปะพะต. +ะญั‚ะพ ะพัะฝะพะฒะฝะพะน ั„ะฐะนะป ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั, ะบะพั‚ะพั€ั‹ะน ัะฒัะทั‹ะฒะฐะตั‚ ะฒัั‘ ะฒะพะตะดะธะฝะพ. -ะ˜ ั‚ะตะฟะตั€ัŒ, ะบะพะณะดะฐ ะฑะพะปัŒัˆะฐั ั‡ะฐัั‚ัŒ ะปะพะณะธะบะธ ะฟั€ะธะปะพะถะตะฝะธั ั€ะฐะทะดะตะปะตะฝะฐ ะฝะฐ ะพั‚ะดะตะปัŒะฝั‹ะต ะผะพะดัƒะปะธ, ะพัะฝะพะฒะฝะพะน ั„ะฐะนะป `app/main.py` ะฑัƒะดะตั‚ ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ะฟั€ะพัั‚ั‹ะผ. +ะ˜ ั‚ะฐะบ ะบะฐะบ ะฑะพะปัŒัˆะฐั ั‡ะฐัั‚ัŒ ะฒะฐัˆะตะน ะปะพะณะธะบะธ ั‚ะตะฟะตั€ัŒ ะฑัƒะดะตั‚ ะฝะฐั…ะพะดะธั‚ัŒัั ะฒ ะพั‚ะดะตะปัŒะฝั‹ั… ัะฟะตั†ะธั„ะธั‡ะฝั‹ั… ะผะพะดัƒะปัั…, ะพัะฝะพะฒะฝะพะน ั„ะฐะนะป ะฑัƒะดะตั‚ ะดะพะฒะพะปัŒะฝะพ ะฟั€ะพัั‚ั‹ะผ. ### ะ˜ะผะฟะพั€ั‚ `FastAPI` { #import-fastapi } -ะ’ั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตั‚ะต ะธ ัะพะทะดะฐะตั‚ะต ะบะปะฐัั `FastAPI` ะบะฐะบ ะพะฑั‹ั‡ะฝะพ. +ะ’ั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตั‚ะต ะธ ัะพะทะดะฐั‘ั‚ะต ะบะปะฐัั `FastAPI` ะบะฐะบ ะพะฑั‹ั‡ะฝะพ. -ะœั‹ ะดะฐะถะต ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ [ะณะปะพะฑะฐะปัŒะฝั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ](dependencies/global-dependencies.md){.internal-link target=_blank}, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะพะฑัŠะตะดะธะฝะตะฝั‹ ั ะทะฐะฒะธัะธะผะพัั‚ัะผะธ ะดะปั ะบะฐะถะดะพะณะพ ะพั‚ะดะตะปัŒะฝะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ: +ะ˜ ะผั‹ ะดะฐะถะต ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ [ะณะปะพะฑะฐะปัŒะฝั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ](dependencies/global-dependencies.md){.internal-link target=_blank}, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะพะฑัŠะตะดะธะฝะตะฝั‹ ั ะทะฐะฒะธัะธะผะพัั‚ัะผะธ ะดะปั ะบะฐะถะดะพะณะพ `APIRouter`: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} ### ะ˜ะผะฟะพั€ั‚ `APIRouter` { #import-the-apirouter } -ะขะตะฟะตั€ัŒ ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะดั€ัƒะณะธะต ััƒะฑ-ะผะพะดัƒะปะธ, ัะพะดะตั€ะถะฐั‰ะธะต `APIRouter`: +ะขะตะฟะตั€ัŒ ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะดั€ัƒะณะธะต ะฟะพะดะผะพะดัƒะปะธ, ัะพะดะตั€ะถะฐั‰ะธะต `APIRouter`: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} -ะขะฐะบ ะบะฐะบ ั„ะฐะนะปั‹ `app/routers/users.py` ะธ `app/routers/items.py` ัะฒะปััŽั‚ัั ััƒะฑ-ะผะพะดัƒะปัะผะธ ะพะดะฝะพะณะพ ะธ ั‚ะพะณะพ ะถะต Python-ะฟะฐะบะตั‚ะฐ `app`, ั‚ะพ ะผั‹ ัะผะพะถะตะผ ะธั… ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ, ะฒะพัะฟะพะปัŒะทะพะฒะฐะฒัˆะธััŒ ะพะฟะตั€ะฐั†ะธะตะน ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพะณะพ ะธะผะฟะพั€ั‚ะฐ `.`. +ะขะฐะบ ะบะฐะบ ั„ะฐะนะปั‹ `app/routers/users.py` ะธ `app/routers/items.py` ัะฒะปััŽั‚ัั ะฟะพะดะผะพะดัƒะปัะผะธ, ะฒั…ะพะดัั‰ะธะผะธ ะฒ ะพะดะธะฝ ะธ ั‚ะพั‚ ะถะต Python-ะฟะฐะบะตั‚ `app`, ะผั‹ ะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะดะฝัƒ ั‚ะพั‡ะบัƒ `.` ะดะปั ะธะผะฟะพั€ั‚ะฐ ั‡ะตั€ะตะท ยซะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะต ะธะผะฟะพั€ั‚ั‹ยป. -### ะšะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะธะผะฟะพั€ั‚? { #how-the-importing-works } +### ะšะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะธะผะฟะพั€ั‚ { #how-the-importing-works } -ะ”ะฐะฝะฝะฐั ัั‚ั€ะพะบะฐ ะบะพะดะฐ: +ะญั‚ะพั‚ ั„ั€ะฐะณะผะตะฝั‚: ```Python from .routers import items, users @@ -323,15 +325,15 @@ from .routers import items, users ะพะทะฝะฐั‡ะฐะตั‚: -* ะะฐั‡ะฝะธั‚ะต ั ะฟะฐะบะตั‚ะฐ, ะฒ ะบะพั‚ะพั€ะพะผ ัะพะดะตั€ะถะธั‚ัั ะดะฐะฝะฝั‹ะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/main.py` ัะพะดะตั€ะถะธั‚ัั ะฒ ะบะฐั‚ะฐะปะพะณะต `app/`)... -* ... ะฝะฐะนะดะธั‚ะต ััƒะฑ-ะฟะฐะบะตั‚ `routers` (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... -* ... ะธ ะธะท ะฝะตะณะพ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต ััƒะฑ-ะผะพะดัƒะปะธ `items` (ั„ะฐะนะป `app/routers/items.py`) ะธ `users` (ั„ะฐะนะป `app/routers/users.py`)... +* ะะฐั‡ะฐั‚ัŒ ะฒ ั‚ะพะผ ะถะต ะฟะฐะบะตั‚ะต, ะฒ ะบะพั‚ะพั€ะพะผ ะฝะฐั…ะพะดะธั‚ัั ัั‚ะพั‚ ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/main.py`) ั€ะฐัะฟะพะปะพะถะตะฝ ะฒ (ะบะฐั‚ะฐะปะพะณะต `app/`)... +* ะฝะฐะนั‚ะธ ะฟะพะดะฟะฐะบะตั‚ `routers` (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะธ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธะท ะฝะตะณะพ ะฟะพะดะผะพะดัƒะปะธ `items` (ั„ะฐะนะป `app/routers/items.py`) ะธ `users` (ั„ะฐะนะป `app/routers/users.py`)... -ะ’ ะผะพะดัƒะปะต `items` ัะพะดะตั€ะถะธั‚ัั ะฟะตั€ะตะผะตะฝะฝะฐั `router` (`items.router`), ั‚ะฐ ัะฐะผะฐั, ะบะพั‚ะพั€ัƒัŽ ะผั‹ ัะพะทะดะฐะปะธ ะฒ ั„ะฐะนะปะต `app/routers/items.py`, ะพะฝะฐ ัะฒะปัะตั‚ัั ะพะฑัŠะตะบั‚ะพะผ ะบะปะฐััะฐ `APIRouter`. +ะ’ ะผะพะดัƒะปะต `items` ะฑัƒะดะตั‚ ะฟะตั€ะตะผะตะฝะฝะฐั `router` (`items.router`). ะญั‚ะพ ั‚ะฐ ะถะต ัะฐะผะฐั, ะบะพั‚ะพั€ัƒัŽ ะผั‹ ัะพะทะดะฐะปะธ ะฒ ั„ะฐะนะปะต `app/routers/items.py`, ัั‚ะพ ะพะฑัŠะตะบั‚ `APIRouter`. -ะ˜ ะทะฐั‚ะตะผ ะผั‹ ัะดะตะปะฐะตะผ ั‚ะพ ะถะต ัะฐะผะพะต ะดะปั ะผะพะดัƒะปั `users`. +ะ˜ ะทะฐั‚ะตะผ ะผั‹ ะดะตะปะฐะตะผ ั‚ะพ ะถะต ัะฐะผะพะต ะดะปั ะผะพะดัƒะปั `users`. -ะœั‹ ั‚ะฐะบะถะต ะผะพะณะปะธ ะฑั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ะดั€ัƒะณะธะผ ะผะตั‚ะพะดะพะผ: +ะœั‹ ั‚ะฐะบะถะต ะผะพะณะปะธ ะฑั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธั… ั‚ะฐะบ: ```Python from app.routers import items, users @@ -339,44 +341,44 @@ from app.routers import items, users /// info | ะŸั€ะธะผะตั‡ะฐะฝะธะต -ะŸะตั€ะฒะฐั ะฒะตั€ัะธั ัะฒะปัะตั‚ัั ะฟั€ะธะผะตั€ะพะผ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพะณะพ ะธะผะฟะพั€ั‚ะฐ: +ะŸะตั€ะฒะฐั ะฒะตั€ัะธั โ€” ัั‚ะพ ยซะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚ยป: ```Python from .routers import items, users ``` -ะ’ั‚ะพั€ะฐั ะฒะตั€ัะธั ัะฒะปัะตั‚ัั ะฟั€ะธะผะตั€ะพะผ ะฐะฑัะพะปัŽั‚ะฝะพะณะพ ะธะผะฟะพั€ั‚ะฐ: +ะ’ั‚ะพั€ะฐั ะฒะตั€ัะธั โ€” ัั‚ะพ ยซะฐะฑัะพะปัŽั‚ะฝั‹ะน ะธะผะฟะพั€ั‚ยป: ```Python from app.routers import items, users ``` -ะฃะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพ ะฟะฐะบะตั‚ะฐั… ะธ ะผะพะดัƒะปัั… ะฒ Python ะฒั‹ ะผะพะถะตั‚ะต ะธะท ะพั„ะธั†ะธะฐะปัŒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Python ะพ ะผะพะดัƒะปัั… +ะงั‚ะพะฑั‹ ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพ Python-ะฟะฐะบะตั‚ะฐั… ะธ ะผะพะดัƒะปัั…, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะพั„ะธั†ะธะฐะปัŒะฝัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Python ะพ ะผะพะดัƒะปัั…. /// -### ะ˜ะทะฑะตะณะฐะนั‚ะต ะบะพะฝั„ะปะธะบั‚ะพะฒ ะธะผะตะฝ { #avoid-name-collisions } +### ะ˜ะทะฑะตะณะฐะนั‚ะต ะบะพะฝั„ะปะธะบั‚ะพะฒ ะธะผั‘ะฝ { #avoid-name-collisions } -ะ’ะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ั‚ะพะปัŒะบะพ ะฟะตั€ะตะผะตะฝะฝัƒัŽ `router`, ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ััƒะฑ-ะผะพะดัƒะปัŒ `items`. +ะœั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะฟะพะดะผะพะดัƒะปัŒ `items` ะฝะฐะฟั€ัะผัƒัŽ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ั‚ะพะปัŒะบะพ ะตะณะพ ะฟะตั€ะตะผะตะฝะฝัƒัŽ `router`. -ะœั‹ ะดะตะปะฐะตะผ ัั‚ะพ ะฟะพั‚ะพะผัƒ, ั‡ั‚ะพ ัƒ ะฝะฐั ะตัั‚ัŒ ะตั‰ั‘ ะพะดะฝะฐ ะฟะตั€ะตะผะตะฝะฝะฐั `router` ะฒ ััƒะฑ-ะผะพะดัƒะปะต `users`. +ะญั‚ะพ ะฟะพั‚ะพะผัƒ, ั‡ั‚ะพ ัƒ ะฝะฐั ั‚ะฐะบะถะต ะตัั‚ัŒ ะดั€ัƒะณะฐั ะฟะตั€ะตะผะตะฝะฝะฐั ั ะธะผะตะฝะตะผ `router` ะฒ ะฟะพะดะผะพะดัƒะปะต `users`. -ะ•ัะปะธ ะฑั‹ ะผั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะปะธ ะธั… ะพะดะฝัƒ ะทะฐ ะดั€ัƒะณะพะน, ะบะฐะบ ะฟะพะบะฐะทะฐะฝะพ ะฒ ะฟั€ะธะผะตั€ะต: +ะ•ัะปะธ ะฑั‹ ะผั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะปะธ ะธั… ะพะดะฝัƒ ะทะฐ ะดั€ัƒะณะพะน, ะบะฐะบ ะทะดะตััŒ: ```Python from .routers.items import router from .routers.users import router ``` -ั‚ะพ ะฟะตั€ะตะผะตะฝะฝะฐั `router` ะธะท `users` ะฟะตั€ะตะฟะธัะฐะป ะฑั‹ ะฟะตั€ะตะผะตะฝะฝัƒัŽ `router` ะธะท `items`, ะธ ัƒ ะฝะฐั ะฝะต ะฑั‹ะปะพ ะฑั‹ ะฒะพะทะผะพะถะฝะพัั‚ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ. +ั‚ะพ `router` ะธะท `users` ะฟะตั€ะตะทะฐะฟะธัะฐะป ะฑั‹ `router` ะธะท `items`, ะธ ะผั‹ ะฝะต ัะผะพะณะปะธ ะฑั‹ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ. -ะŸะพัั‚ะพะผัƒ, ะดะปั ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฑะต ัั‚ะธ ะฟะตั€ะตะผะตะฝะฝั‹ะต ะฒ ะพะดะฝะพะผ ั„ะฐะนะปะต, ะผั‹ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะปะธ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะธะต ััƒะฑ-ะผะพะดัƒะปะธ: +ะŸะพัั‚ะพะผัƒ, ั‡ั‚ะพะฑั‹ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฑะต ะฒ ะพะดะฝะพะผ ั„ะฐะนะปะต, ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะฟะพะดะผะพะดัƒะปะธ ะฝะฐะฟั€ัะผัƒัŽ: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} -### ะŸะพะดะบะปัŽั‡ะตะฝะธะต ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะพะฒ (`APIRouter`) ะดะปั `users` ะธ ะดะปั `items` { #include-the-apirouters-for-users-and-items } +### ะŸะพะดะบะปัŽั‡ะตะฝะธะต `APIRouter` ะดะปั `users` ะธ `items` { #include-the-apirouters-for-users-and-items } -ะ”ะฐะฒะฐะนั‚ะต ะฟะพะดะบะปัŽั‡ะธะผ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ั‹ (`router`) ะธะท ััƒะฑ-ะผะพะดัƒะปะตะน `users` ะธ `items`: +ะขะตะฟะตั€ัŒ ะดะฐะฒะฐะนั‚ะต ะฟะพะดะบะปัŽั‡ะธะผ `router` ะธะท ะฟะพะดะผะพะดัƒะปะตะน `users` ะธ `items`: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} @@ -388,79 +390,78 @@ from .routers.users import router /// -ะก ะฟะพะผะพั‰ัŒัŽ `app.include_router()` ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ะบะฐะถะดั‹ะน ะธะท ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะพะฒ (`APIRouter`) ะฒ ะพัะฝะพะฒะฝะพะต ะฟั€ะธะปะพะถะตะฝะธะต `FastAPI`. +ะก ะฟะพะผะพั‰ัŒัŽ `app.include_router()` ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ะบะฐะถะดั‹ะน `APIRouter` ะฒ ะพัะฝะพะฒะฝะพะต ะฟั€ะธะปะพะถะตะฝะธะต `FastAPI`. -ะžะฝ ะฟะพะดะบะปัŽั‡ะธั‚ ะฒัะต ะผะฐั€ัˆั€ัƒั‚ั‹ ะทะฐะดะฐะฝะฝะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ ะบ ะฝะฐัˆะตะผัƒ ะฟั€ะธะปะพะถะตะฝะธัŽ. +ะžะฝ ะฒะบะปัŽั‡ะธั‚ ะฒัะต ะผะฐั€ัˆั€ัƒั‚ั‹ ัั‚ะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ ะบะฐะบ ั‡ะฐัั‚ัŒ ะฟั€ะธะปะพะถะตะฝะธั. /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ -ะคะฐะบั‚ะธั‡ะตัะบะธ, ะฒะฝัƒั‚ั€ะธ ะพะฝ ัะพะทะดะฐัั‚ ะฒัะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะดะปั ะบะฐะถะดะพะน ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ ะพะฑัŠัะฒะปะตะฝะฝะพะน ะฒ `APIRouter`. +ะคะฐะบั‚ะธั‡ะตัะบะธ, ะฒะฝัƒั‚ั€ะธ ะพะฝ ัะพะทะดะฐัั‚ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะดะปั ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะพะฑัŠัะฒะปะตะฝะฝะพะน ะฒ `APIRouter`. -ะ˜ ะฟะพะด ะบะฐะฟะพั‚ะพะผ ะฒัั‘ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะฐะบ, ะบะฐะบ ะฑัƒะดั‚ะพ ะฑั‹ ะผั‹ ะธะผะตะตะผ ะดะตะปะพ ั ะพะดะฝะธะผ ั„ะฐะนะปะพะผ ะฟั€ะธะปะพะถะตะฝะธั. +ะขะฐะบ ั‡ั‚ะพ ะฟะพะด ะบะฐะฟะพั‚ะพะผ ะฒัั‘ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะฐะบ, ะบะฐะบ ะฑัƒะดั‚ะพ ะฒัั‘ ะฑั‹ะปะพ ะพะดะฝะธะผ ะฟั€ะธะปะพะถะตะฝะธะตะผ. /// /// check | ะ—ะฐะผะตั‚ะบะฐ -ะŸั€ะธ ะฟะพะดะบะปัŽั‡ะตะฝะธะธ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะพะฒ ะฝะต ัั‚ะพะธั‚ ะฑะตัะฟะพะบะพะธั‚ัŒัั ะพ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ. +ะŸั€ะธ ะฟะพะดะบะปัŽั‡ะตะฝะธะธ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะพะฒ ะฝะต ะฝัƒะถะฝะพ ะฑะตัะฟะพะบะพะธั‚ัŒัั ะพ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ. -ะžะฟะตั€ะฐั†ะธั ะฟะพะดะบะปัŽั‡ะตะฝะธั ะทะฐะนะผั‘ั‚ ะผะธะบั€ะพัะตะบัƒะฝะดั‹ ะธ ะฟะพะฝะฐะดะพะฑะธั‚ัั ั‚ะพะปัŒะบะพ ะฟั€ะธ ะทะฐะฟัƒัะบะต ะฟั€ะธะปะพะถะตะฝะธั. +ะญั‚ะพ ะทะฐะนะผั‘ั‚ ะผะธะบั€ะพัะตะบัƒะฝะดั‹ ะธ ะฟั€ะพะธะทะพะนะดั‘ั‚ ั‚ะพะปัŒะบะพ ะฟั€ะธ ัั‚ะฐั€ั‚ะต. -ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ัั‚ะพ ะฝะต ะฟะพะฒะปะธัะตั‚ ะฝะฐ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ. โšก +ะขะฐะบ ั‡ั‚ะพ ัั‚ะพ ะฝะต ะฟะพะฒะปะธัะตั‚ ะฝะฐ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ. โšก /// -### ะŸะพะดะบะปัŽั‡ะตะฝะธะต `APIRouter` ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะผะธ ะฟั€ะตั„ะธะบัะพะผ (`prefix`), ั‚ะตะณะฐะผะธ (`tags`), ะพั‚ะฒะตั‚ะฐะผะธ (`responses`), ะธ ะทะฐะฒะธัะธะผะพัั‚ัะผะธ (`dependencies`) { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } +### ะŸะพะดะบะปัŽั‡ะตะฝะธะต `APIRouter` ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะผะธ `prefix`, `tags`, `responses` ะธ `dependencies` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } ะขะตะฟะตั€ัŒ ะดะฐะฒะฐะนั‚ะต ะฟั€ะตะดัั‚ะฐะฒะธะผ, ั‡ั‚ะพ ะฒะฐัˆะฐ ะพั€ะณะฐะฝะธะทะฐั†ะธั ะฟะตั€ะตะดะฐะปะฐ ะฒะฐะผ ั„ะฐะนะป `app/internal/admin.py`. -ะžะฝ ัะพะดะตั€ะถะธั‚ `APIRouter` ั ะฝะตะบะพั‚ะพั€ั‹ะผะธ *ัะฝะดะฟะพะธั‚ะฐะผะธ* ะฐะดะผะธะฝะธัั‚ั€ะธั€ะพะฒะฐะฝะธั, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะฐ ะพั€ะณะฐะฝะธะทะฐั†ะธั ะธัะฟะพะปัŒะทัƒะตั‚ ะดะปั ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะพะฒ. +ะžะฝ ัะพะดะตั€ะถะธั‚ `APIRouter` ั ะฝะตะบะพั‚ะพั€ั‹ะผะธ ะฐะดะผะธะฝะธัั‚ั€ะฐั‚ะธะฒะฝั‹ะผะธ *ะพะฟะตั€ะฐั†ะธัะผะธ ะฟัƒั‚ะธ*, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะฐ ะพั€ะณะฐะฝะธะทะฐั†ะธั ะธัะฟะพะปัŒะทัƒะตั‚ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะฐั…. -ะ’ ะดะฐะฝะฝะพะผ ะฟั€ะธะผะตั€ะต ัั‚ะพ ัะดะตะปะฐั‚ัŒ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพ. ะะพ ะดะฐะฒะฐะนั‚ะต ะฟั€ะตะดะฟะพะปะพะถะธะผ, ั‡ั‚ะพ ะฟะพัะบะพะปัŒะบัƒ ั„ะฐะนะป ะธัะฟะพะปัŒะทัƒะตั‚ัั ะดะปั ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะพะฒ, -ั‚ะพ ะผั‹ ะฝะต ะผะพะถะตะผ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐั‚ัŒ ะตะณะพ, ะดะพะฑะฐะฒะปัั ะฟั€ะตั„ะธะบัั‹ (`prefix`), ะทะฐะฒะธัะธะผะพัั‚ะธ (`dependencies`), ั‚ะตะณะธ (`tags`), ะธ ั‚.ะด. ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ `APIRouter`: +ะ”ะปั ัั‚ะพะณะพ ะฟั€ะธะผะตั€ะฐ ะฒัั‘ ะฑัƒะดะตั‚ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพ. ะะพ ะดะพะฟัƒัั‚ะธะผ, ั‡ั‚ะพ ะฟะพัะบะพะปัŒะบัƒ ะพะฝ ะธัะฟะพะปัŒะทัƒะตั‚ัั ัะพะฒะผะตัั‚ะฝะพ ั ะดั€ัƒะณะธะผะธ ะฟั€ะพะตะบั‚ะฐะผะธ ะฒ ะพั€ะณะฐะฝะธะทะฐั†ะธะธ, ะผั‹ ะฝะต ะผะพะถะตะผ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐั‚ัŒ ะตะณะพ ะธ ะดะพะฑะฐะฒะธั‚ัŒ `prefix`, `dependencies`, `tags` ะธ ั‚.ะด. ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ `APIRouter`: {* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} -ะะพ, ะฝะตัะผะพั‚ั€ั ะฝะฐ ัั‚ะพ, ะผั‹ ั…ะพั‚ะธะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะฐัั‚ะพะผะฝั‹ะน ะฟั€ะตั„ะธะบั (`prefix`) ะดะปั ะฟะพะดะบะปัŽั‡ะตะฝะฝะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ (`APIRouter`), ะฒ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ั‡ะตะณะพ, ะบะฐะถะดะฐั *ะพะฟะตั€ะฐั†ะธั ะฟัƒั‚ะธ* ะฑัƒะดะตั‚ ะฝะฐั‡ะธะฝะฐั‚ัŒัั ั `/admin`. ะขะฐะบะถะต ะผั‹ ั…ะพั‚ะธะผ ะทะฐั‰ะธั‚ะธั‚ัŒ ะฝะฐัˆ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ ั ะฟะพะผะพั‰ัŒัŽ ะทะฐะฒะธัะธะผะพัั‚ะตะน, ัะพะทะดะฐะฝะฝั‹ั… ะดะปั ะฝะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ. ะ˜ ะตั‰ั‘ ะผั‹ ั…ะพั‚ะธะผ ะฒะบะปัŽั‡ะธั‚ัŒ ั‚ะตะณะธ (`tags`) ะธ ะพั‚ะฒะตั‚ั‹ (`responses`). +ะะพ ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ั…ะพั‚ะธะผ ะทะฐะดะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน `prefix` ะฟั€ะธ ะฟะพะดะบะปัŽั‡ะตะฝะธะธ `APIRouter`, ั‡ั‚ะพะฑั‹ ะฒัะต ะตะณะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฝะฐั‡ะธะฝะฐะปะธััŒ ั `/admin`, ั…ะพั‚ะธะผ ะทะฐั‰ะธั‚ะธั‚ัŒ ะตะณะพ ั ะฟะพะผะพั‰ัŒัŽ `dependencies`, ะบะพั‚ะพั€ั‹ะต ัƒ ะฝะฐั ัƒะถะต ะตัั‚ัŒ ะดะปั ัั‚ะพะณะพ ะฟั€ะพะตะบั‚ะฐ, ะธ ั…ะพั‚ะธะผ ะฒะบะปัŽั‡ะธั‚ัŒ `tags` ะธ `responses`. -ะœั‹ ะผะพะถะตะผ ะฟั€ะธะผะตะฝะธั‚ัŒ ะฒัะต ะฒั‹ัˆะตะฟะตั€ะตั‡ะธัะปะตะฝะฝั‹ะต ะฝะฐัั‚ั€ะพะนะบะธ, ะฝะต ะธะทะผะตะฝัั ะฝะฐั‡ะฐะปัŒะฝั‹ะน `APIRouter`. ะะฐะผ ะฒัะตะณะพ ะปะธัˆัŒ ะฝัƒะถะฝะพ ะฟะตั€ะตะดะฐั‚ัŒ ะฝัƒะถะฝั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฒ `app.include_router()`. +ะœั‹ ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ ะฒัั‘ ัั‚ะพ, ะฝะต ะธะทะผะตะฝัั ะธัั…ะพะดะฝั‹ะน `APIRouter`, ะฟะตั€ะตะดะฐะฒ ัั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฒ `app.include_router()`: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} -ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะพั€ะธะณะธะฝะฐะปัŒะฝั‹ะน `APIRouter` ะฝะต ะฑัƒะดะตั‚ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐะฝ, ะธ ะผั‹ ัะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั„ะฐะนะป `app/internal/admin.py` ัั€ะฐะทัƒ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะฐั… ะพั€ะณะฐะฝะธะทะฐั†ะธะธ. +ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะธัั…ะพะดะฝั‹ะน `APIRouter` ะฝะต ะฑัƒะดะตั‚ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐะฝ, ะธ ะผั‹ ัะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั„ะฐะนะป `app/internal/admin.py` ัั€ะฐะทัƒ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะฐั… ะพั€ะณะฐะฝะธะทะฐั†ะธะธ. -ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต, ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ ะบะฐะถะดั‹ะน *ัะฝะดะฟะพะธะฝั‚* ะผะพะดัƒะปั `admin` ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ: +ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ ะบะฐะถะดะฐั ะธะท *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ* ะธะท ะผะพะดัƒะปั `admin` ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ: * ะŸั€ะตั„ะธะบั `/admin`. * ะขะตะณ `admin`. * ะ—ะฐะฒะธัะธะผะพัั‚ัŒ `get_token_header`. * ะžั‚ะฒะตั‚ `418`. ๐Ÿต -ะญั‚ะพ ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ะผะตัั‚ะพ ะธัะบะปัŽั‡ะธั‚ะตะปัŒะฝะพ ะดะปั `APIRouter` ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ, ะธ ะฝะต ะทะฐั‚ั€ะพะฝะตั‚ ะปัŽะฑะพะน ะดั€ัƒะณะพะน ะบะพะด, ะธัะฟะพะปัŒะทัƒัŽั‰ะธะน ะตะณะพ. +ะะพ ัั‚ะพ ะฟะพะฒะปะธัะตั‚ ั‚ะพะปัŒะบะพ ะฝะฐ ัั‚ะพั‚ `APIRouter` ะฒ ะฝะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ, ะฐ ะฝะต ะฝะฐ ะปัŽะฑะพะน ะดั€ัƒะณะพะน ะบะพะด, ะบะพั‚ะพั€ั‹ะน ะตะณะพ ะธัะฟะพะปัŒะทัƒะตั‚. -ะะฐะฟั€ะธะผะตั€, ะดั€ัƒะณะธะต ะฟั€ะพะตะบั‚ั‹, ะผะพะณัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะพั‚ ะถะต ัะฐะผั‹ะน `APIRouter` ั ะดั€ัƒะณะธะผะธ ะผะตั‚ะพะดะฐะผะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ. +ะขะฐะบ ั‡ั‚ะพ, ะฝะฐะฟั€ะธะผะตั€, ะดั€ัƒะณะธะต ะฟั€ะพะตะบั‚ั‹ ะผะพะณัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะพั‚ ะถะต `APIRouter` ั ะดั€ัƒะณะธะผ ะผะตั‚ะพะดะพะผ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ. -### ะŸะพะดะบะปัŽั‡ะตะฝะธะต ะพั‚ะดะตะปัŒะฝะพะณะพ *ัะฝะดะฟะพะธะฝั‚ะฐ* { #include-a-path-operation } +### ะŸะพะดะบะปัŽั‡ะตะฝะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* { #include-a-path-operation } -ะœั‹ ั‚ะฐะบะถะต ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ *ัะฝะดะฟะพะธะฝั‚* ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ะพัะฝะพะฒะฝะพะต ะฟั€ะธะปะพะถะตะฝะธะต `FastAPI`. +ะœั‹ ั‚ะฐะบะถะต ะผะพะถะตะผ ะดะพะฑะฐะฒะปัั‚ัŒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฝะฐะฟั€ัะผัƒัŽ ะฒ ะฟั€ะธะปะพะถะตะฝะธะต `FastAPI`. -ะ—ะดะตััŒ ะผั‹ ัั‚ะพ ะดะตะปะฐะตะผ ... ะฟั€ะพัั‚ะพ, ั‡ั‚ะพะฑั‹ ะฟะพะบะฐะทะฐั‚ัŒ, ั‡ั‚ะพ ัั‚ะพ ะฒะพะทะผะพะถะฝะพ ๐Ÿคท: +ะ—ะดะตััŒ ะผั‹ ะดะตะปะฐะตะผ ัั‚ะพ... ะฟั€ะพัั‚ะพ ั‡ั‚ะพะฑั‹ ะฟะพะบะฐะทะฐั‚ัŒ, ั‡ั‚ะพ ะผะพะถะตะผ ๐Ÿคท: {* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} -ะธ ัั‚ะพ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝะพ ะฒะผะตัั‚ะต ั ะดั€ัƒะณะธะผะธ *ัะฝะดะฟะพะธะฝั‚ะฐะผะธ*, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะผะธ ั ะฟะพะผะพั‰ัŒัŽ `app.include_router()`. +ะธ ัั‚ะพ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝะพ ะฒะผะตัั‚ะต ัะพ ะฒัะตะผะธ ะดั€ัƒะณะธะผะธ *ะพะฟะตั€ะฐั†ะธัะผะธ ะฟัƒั‚ะธ*, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะผะธ ั‡ะตั€ะตะท `app.include_router()`. -/// info | ะกะปะพะถะฝั‹ะต ั‚ะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ +/// info | ะžั‡ะตะฝัŒ ั‚ะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ -**ะŸั€ะธะผะตั‡ะฐะฝะธะต**: ัั‚ะพ ัะปะพะถะฝะฐั ั‚ะตั…ะฝะธั‡ะตัะบะฐั ะดะตั‚ะฐะปัŒ, ะบะพั‚ะพั€ัƒัŽ, ัะบะพั€ะตะต ะฒัะตะณะพ, **ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ**. +**ะŸั€ะธะผะตั‡ะฐะฝะธะต**: ัั‚ะพ ะพั‡ะตะฝัŒ ั‚ะตั…ะฝะธั‡ะตัะบะฐั ะดะตั‚ะฐะปัŒ, ะบะพั‚ะพั€ัƒัŽ, ะฒะตั€ะพัั‚ะฝะพ, ะผะพะถะฝะพ **ะฟั€ะพัั‚ะพ ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ**. --- -ะœะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ั‹ (`APIRouter`) ะฝะต "ะผะพะฝั‚ะธั€ัƒัŽั‚ัั" ะฟะพ-ะพั‚ะดะตะปัŒะฝะพัั‚ะธ ะธ ะฝะต ะธะทะพะปะธั€ัƒัŽั‚ัั ะพั‚ ะพัั‚ะฐะปัŒะฝะพะณะพ ะฟั€ะธะปะพะถะตะฝะธั. +`APIRouter` ะฝะต ยซะผะพะฝั‚ะธั€ัƒัŽั‚ััยป, ะพะฝะธ ะฝะต ะธะทะพะปะธั€ะพะฒะฐะฝั‹ ะพั‚ ะพัั‚ะฐะปัŒะฝะพะณะพ ะฟั€ะธะปะพะถะตะฝะธั. -ะญั‚ะพ ะฟั€ะพะธัั…ะพะดะธั‚ ะฟะพั‚ะพะผัƒ, ั‡ั‚ะพ ะฝัƒะถะฝะพ ะฒะบะปัŽั‡ะธั‚ัŒ ะธั… *ัะฝะดะฟะพะธะฝั‚ั‹* ะฒ OpenAPI ัั…ะตะผัƒ ะธ ะฒ ะธะฝั‚ะตั€ั„ะตะนั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั. +ะญั‚ะพ ะฟะพั‚ะพะผัƒ, ั‡ั‚ะพ ะผั‹ ั…ะพั‚ะธะผ ะฒะบะปัŽั‡ะธั‚ัŒ ะธั… *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฒ OpenAPI-ัั…ะตะผัƒ ะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะธะฝั‚ะตั€ั„ะตะนัั‹. -ะ’ ัะธะปัƒ ั‚ะพะณะพ, ั‡ั‚ะพ ะผั‹ ะฝะต ะผะพะถะตะผ ะธั… ะธะทะพะปะธั€ะพะฒะฐั‚ัŒ ะธ "ะฟั€ะธะผะพะฝั‚ะธั€ะพะฒะฐั‚ัŒ" ะฝะตะทะฐะฒะธัะธะผะพ ะพั‚ ะพัั‚ะฐะปัŒะฝั‹ั…, *ัะฝะดะฟะพะธะฝั‚ั‹* ะบะปะพะฝะธั€ัƒัŽั‚ัั (ะฟะตั€ะตัะพะทะดะฐัŽั‚ัั) ะธ ะฝะต ะฟะพะดะบะปัŽั‡ะฐัŽั‚ัั ะฝะฐะฟั€ัะผัƒัŽ. +ะขะฐะบ ะบะฐะบ ะผั‹ ะฝะต ะผะพะถะตะผ ะฟั€ะพัั‚ะพ ะธะทะพะปะธั€ะพะฒะฐั‚ัŒ ะธั… ะธ ยซัะผะพะฝั‚ะธั€ะพะฒะฐั‚ัŒยป ะฝะตะทะฐะฒะธัะธะผะพ ะพั‚ ะพัั‚ะฐะปัŒะฝะพะณะพ, *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ยซะบะปะพะฝะธั€ัƒัŽั‚ััยป (ะฟะตั€ะตัะพะทะดะฐัŽั‚ัั), ะฐ ะฝะต ะฒะบะปัŽั‡ะฐัŽั‚ัั ะฝะฐะฟั€ัะผัƒัŽ. /// @@ -480,24 +481,24 @@ $ fastapi dev app/main.py ะžั‚ะบั€ะพะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ะฟะพ ะฐะดั€ะตััƒ http://127.0.0.1:8000/docs. -ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ API ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ. ะžะฝะฐ ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ะผะฐั€ัˆั€ัƒั‚ั‹ ะธะท ััƒะฑ-ะผะพะดัƒะปะตะน, ะธัะฟะพะปัŒะทัƒั ะฒะตั€ะฝั‹ะต ะผะฐั€ัˆั€ัƒั‚ั‹, ะฟั€ะตั„ะธะบัั‹ ะธ ั‚ะตะณะธ: +ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ API, ะฒะบะปัŽั‡ะฐั ะฟัƒั‚ะธ ะธะท ะฒัะตั… ะฟะพะดะผะพะดัƒะปะตะน, ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ ะบะพั€ั€ะตะบั‚ะฝั‹ั… ะฟัƒั‚ะตะน (ะธ ะฟั€ะตั„ะธะบัะพะฒ) ะธ ะบะพั€ั€ะตะบั‚ะฝั‹ั… ั‚ะตะณะพะฒ: -## ะŸะพะดะบะปัŽั‡ะตะฝะธะต ััƒั‰ะตัั‚ะฒัƒัŽั‰ะตะณะพ ะผะฐั€ัˆั€ัƒั‚ะฐ ั‡ะตั€ะตะท ะฝะพะฒั‹ะน ะฟั€ะตั„ะธะบั (`prefix`) { #include-the-same-router-multiple-times-with-different-prefix } +## ะŸะพะดะบะปัŽั‡ะตะฝะธะต ะพะดะฝะพะณะพ ะธ ั‚ะพะณะพ ะถะต ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ั ั€ะฐะทะฝั‹ะผะธ `prefix` { #include-the-same-router-multiple-times-with-different-prefix } -ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `.include_router()` ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ั ะพะดะฝะธะผ ะธ ั‚ะตะผ ะถะต ะผะฐั€ัˆั€ัƒั‚ะพะผ, ะฟั€ะธะผะตะฝะธะฒ ั€ะฐะทะปะธั‡ะฝั‹ะต ะฟั€ะตั„ะธะบัั‹. +ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `.include_router()` ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ั *ะพะดะฝะธะผ ะธ ั‚ะตะผ ะถะต* ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะพะผ, ะธัะฟะพะปัŒะทัƒั ั€ะฐะทะฝั‹ะต ะฟั€ะตั„ะธะบัั‹. -ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฟะพะปะตะทะฝั‹ะผ, ะตัะปะธ ะฝัƒะถะฝะพ ะฟั€ะตะดะพัั‚ะฐะฒะธั‚ัŒ ะดะพัั‚ัƒะฟ ะบ ะพะดะฝะพะผัƒ ะธ ั‚ะพะผัƒ ะถะต API ั‡ะตั€ะตะท ั€ะฐะทะปะธั‡ะฝั‹ะต ะฟั€ะตั„ะธะบัั‹, ะฝะฐะฟั€ะธะผะตั€, `/api/v1` ะธ `/api/latest`. +ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฟะพะปะตะทะฝะพ, ะฝะฐะฟั€ะธะผะตั€, ั‡ั‚ะพะฑั‹ ะฟั€ะตะดะพัั‚ะฐะฒะธั‚ัŒ ะดะพัั‚ัƒะฟ ะบ ะพะดะฝะพะผัƒ ะธ ั‚ะพะผัƒ ะถะต API ั ั€ะฐะทะฝั‹ะผะธ ะฟั€ะตั„ะธะบัะฐะผะธ, ะฝะฐะฟั€ะธะผะตั€ `/api/v1` ะธ `/api/latest`. -ะญั‚ะพ ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ะน ัะฟะพัะพะฑ, ะบะพั‚ะพั€ั‹ะน ะฒะฐะผ ะผะพะถะตั‚ ะธ ะฝะต ะฟั€ะธะณะพะดะธั‚ัั. ะœั‹ ะฟั€ะธะฒะพะดะธะผ ะตะณะพ ะฝะฐ ัะปัƒั‡ะฐะน, ะตัะปะธ ะฒะดั€ัƒะณ ะฒะฐะผ ัั‚ะพ ะฟะพะฝะฐะดะพะฑะธั‚ัั. +ะญั‚ะพ ะฟั€ะพะดะฒะธะฝัƒั‚ะพะต ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต, ะบะพั‚ะพั€ะพะต ะฒะฐะผ ะผะพะถะตั‚ ะธ ะฝะต ะฟะพะฝะฐะดะพะฑะธั‚ัŒัั, ะฝะพ ะพะฝะพ ะตัั‚ัŒ ะฝะฐ ัะปัƒั‡ะฐะน, ะตัะปะธ ะฟะพะฝะฐะดะพะฑะธั‚ัั. -## ะ’ะบะปัŽั‡ะตะฝะธะต ะพะดะฝะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ (`APIRouter`) ะฒ ะดั€ัƒะณะพะน { #include-an-apirouter-in-another } +## ะŸะพะดะบะปัŽั‡ะตะฝะธะต `APIRouter` ะฒ ะดั€ัƒะณะพะน `APIRouter` { #include-an-apirouter-in-another } -ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ะฒะบะปัŽั‡ะฐะตั‚ะต `APIRouter` ะฒ ะฟั€ะธะปะพะถะตะฝะธะต `FastAPI`, ะฒั‹ ะผะพะถะตั‚ะต ะฒะบะปัŽั‡ะธั‚ัŒ `APIRouter` ะฒ ะดั€ัƒะณะพะน `APIRouter`: +ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ะผะพะถะตั‚ะต ะฟะพะดะบะปัŽั‡ะธั‚ัŒ `APIRouter` ะบ ะฟั€ะธะปะพะถะตะฝะธัŽ `FastAPI`, ะฒั‹ ะผะพะถะตั‚ะต ะฟะพะดะบะปัŽั‡ะธั‚ัŒ `APIRouter` ะบ ะดั€ัƒะณะพะผัƒ `APIRouter`, ะธัะฟะพะปัŒะทัƒั: ```Python router.include_router(other_router) ``` -ะฃะดะพัั‚ะพะฒะตั€ัŒั‚ะตััŒ, ั‡ั‚ะพ ะฒั‹ ัะดะตะปะฐะปะธ ัั‚ะพ ะดะพ ั‚ะพะณะพ, ะบะฐะบ ะฟะพะดะบะปัŽั‡ะธั‚ัŒ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ (`router`) ะบ ะฒะฐัˆะตะผัƒ `FastAPI` ะฟั€ะธะปะพะถะตะฝะธัŽ, ะธ *ัะฝะดะฟะพะธะฝั‚ั‹* ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ `other_router` ะฑั‹ะปะธ ั‚ะฐะบะถะต ะฟะพะดะบะปัŽั‡ะตะฝั‹. +ะฃะฑะตะดะธั‚ะตััŒ, ั‡ั‚ะพ ะฒั‹ ัะดะตะปะฐะปะธ ัั‚ะพ ะดะพ ะฟะพะดะบะปัŽั‡ะตะฝะธั `router` ะบ ะฟั€ะธะปะพะถะตะฝะธัŽ `FastAPI`, ั‡ั‚ะพะฑั‹ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะธะท `other_router` ั‚ะฐะบะถะต ะฑั‹ะปะธ ะฟะพะดะบะปัŽั‡ะตะฝั‹. diff --git a/docs/ru/docs/tutorial/body-updates.md b/docs/ru/docs/tutorial/body-updates.md index 73f4e66c76..4a7adb2559 100644 --- a/docs/ru/docs/tutorial/body-updates.md +++ b/docs/ru/docs/tutorial/body-updates.md @@ -2,13 +2,13 @@ ## ะžะฑะฝะพะฒะปะตะฝะธะต ั ะทะฐะผะตะฝะพะน ะฟั€ะธ ะฟะพะผะพั‰ะธ `PUT` { #update-replacing-with-put } -ะ”ะปั ะฟะพะปะฝะพะณะพ ะพะฑะฝะพะฒะปะตะฝะธั ัะปะตะผะตะฝั‚ะฐ ะผะพะถะฝะพ ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะพะฟะตั€ะฐั†ะธะตะน HTTP `PUT`. +ะงั‚ะพะฑั‹ ะพะฑะฝะพะฒะธั‚ัŒ ัะปะตะผะตะฝั‚, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฟะตั€ะฐั†ะธัŽ HTTP `PUT`. ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `jsonable_encoder`, ั‡ั‚ะพะฑั‹ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะฒั…ะพะดะฝั‹ะต ะดะฐะฝะฝั‹ะต ะฒ ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะผะพะถะฝะพ ัะพั…ั€ะฐะฝะธั‚ัŒ ะบะฐะบ JSON (ะฝะฐะฟั€ะธะผะตั€, ะฒ NoSQL-ะฑะฐะทะต ะดะฐะฝะฝั‹ั…). ะะฐะฟั€ะธะผะตั€, ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต `datetime` ะฒ `str`. {* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} -`PUT` ะธัะฟะพะปัŒะทัƒะตั‚ัั ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะดะพะปะถะฝั‹ ะฟะพะปะฝะพัั‚ัŒัŽ ะทะฐะผะตะฝะธั‚ัŒ ััƒั‰ะตัั‚ะฒัƒัŽั‰ะธะต ะดะฐะฝะฝั‹ะต. +`PUT` ะธัะฟะพะปัŒะทัƒะตั‚ัั ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะดะพะปะถะฝั‹ ะทะฐะผะตะฝะธั‚ัŒ ััƒั‰ะตัั‚ะฒัƒัŽั‰ะธะต ะดะฐะฝะฝั‹ะต. ### ะŸั€ะตะดัƒะฟั€ะตะถะดะตะฝะธะต ะพ ะทะฐะผะตะฝะต { #warning-about-replacing } @@ -24,11 +24,11 @@ ะฟะพัะบะพะปัŒะบัƒ ะพะฝะพ ะฝะต ะฒะบะปัŽั‡ะฐะตั‚ ัƒะถะต ัะพั…ั€ะฐะฝะตะฝะฝั‹ะน ะฐั‚ั€ะธะฑัƒั‚ `"tax": 20.2`, ะฒั…ะพะดะฝะฐั ะผะพะดะตะปัŒ ะฟั€ะธะผะตั‚ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `"tax": 10.5`. -ะ˜ ะดะฐะฝะฝั‹ะต ะฑัƒะดัƒั‚ ัะพั…ั€ะฐะฝะตะฝั‹ ั ัั‚ะธะผ "ะฝะพะฒั‹ะผ" `tax`, ั€ะฐะฒะฝั‹ะผ `10,5`. +ะ˜ ะดะฐะฝะฝั‹ะต ะฑัƒะดัƒั‚ ัะพั…ั€ะฐะฝะตะฝั‹ ั ัั‚ะธะผ ยซะฝะพะฒั‹ะผยป `tax`, ั€ะฐะฒะฝั‹ะผ `10.5`. ## ะงะฐัั‚ะธั‡ะฝะพะต ะพะฑะฝะพะฒะปะตะฝะธะต ั ะฟะพะผะพั‰ัŒัŽ `PATCH` { #partial-updates-with-patch } -ะขะฐะบะถะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ HTTP `PATCH` ะพะฟะตั€ะฐั†ะธัŽ ะดะปั *ั‡ะฐัั‚ะธั‡ะฝะพะณะพ* ะพะฑะฝะพะฒะปะตะฝะธั ะดะฐะฝะฝั‹ั…. +ะขะฐะบะถะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฟะตั€ะฐั†ะธัŽ HTTP `PATCH` ะดะปั *ั‡ะฐัั‚ะธั‡ะฝะพะณะพ* ะพะฑะฝะพะฒะปะตะฝะธั ะดะฐะฝะฝั‹ั…. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะผะพะถะฝะพ ะฟะตั€ะตะดะฐะฒะฐั‚ัŒ ั‚ะพะปัŒะบะพ ั‚ะต ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฝะตะพะฑั…ะพะดะธะผะพ ะพะฑะฝะพะฒะธั‚ัŒ, ะพัั‚ะฐะฒะปัั ะพัั‚ะฐะปัŒะฝั‹ะต ะฝะตั‚ั€ะพะฝัƒั‚ั‹ะผะธ. @@ -46,19 +46,13 @@ ### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะฟะฐั€ะฐะผะตั‚ั€ะฐ `exclude_unset` ะฒ Pydantic { #using-pydantics-exclude-unset-parameter } -ะ•ัะปะธ ะฝะตะพะฑั…ะพะดะธะผะพ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ั‡ะฐัั‚ะธั‡ะฝะพะต ะพะฑะฝะพะฒะปะตะฝะธะต, ั‚ะพ ะพั‡ะตะฝัŒ ะฟะพะปะตะทะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `exclude_unset` ะฒ ะผะตั‚ะพะดะต `.model_dump()` ะผะพะดะตะปะธ Pydantic. +ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะปัƒั‡ะฐั‚ัŒ ั‡ะฐัั‚ะธั‡ะฝั‹ะต ะพะฑะฝะพะฒะปะตะฝะธั, ะพั‡ะตะฝัŒ ะฟะพะปะตะทะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `exclude_unset` ะฒ `.model_dump()` ะผะพะดะตะปะธ Pydantic. ะะฐะฟั€ะธะผะตั€, `item.model_dump(exclude_unset=True)`. -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั +ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ะฑัƒะดะตั‚ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝ `dict`, ัะพะดะตั€ะถะฐั‰ะธะน ั‚ะพะปัŒะบะพ ั‚ะต ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฑั‹ะปะธ ะทะฐะดะฐะฝั‹ ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะผะพะดะตะปะธ `item`, ะฑะตะท ัƒั‡ะตั‚ะฐ ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. -ะ’ Pydantic v1 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะปัั `.dict()`, ะฒ Pydantic v2 ะพะฝ ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน (ะฝะพ ะฒัะต ะตั‰ะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั) ะธ ะฟะตั€ะตะธะผะตะฝะพะฒะฐะฝ ะฒ `.model_dump()`. - -ะŸั€ะธะผะตั€ั‹ ะทะดะตััŒ ะธัะฟะพะปัŒะทัƒัŽั‚ `.dict()` ะดะปั ัะพะฒะผะตัั‚ะธะผะพัั‚ะธ ั Pydantic v1, ะฝะพ ะตัะปะธ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Pydantic v2, ะปัƒั‡ัˆะต ะธัะฟะพะปัŒะทัƒะนั‚ะต `.model_dump()`. - -/// - -ะ’ ั€ะตะทัƒะปัŒั‚ะฐั‚ะต ะฑัƒะดะตั‚ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝ ัะปะพะฒะฐั€ัŒ, ัะพะดะตั€ะถะฐั‰ะธะน ั‚ะพะปัŒะบะพ ั‚ะต ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฑั‹ะปะธ ะทะฐะดะฐะฝั‹ ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะผะพะดะตะปะธ `item`, ะฑะตะท ัƒั‡ะตั‚ะฐ ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. ะ—ะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพ ะดะปั ัะพะทะดะฐะฝะธั ัะปะพะฒะฐั€ั ั‚ะพะปัŒะบะพ ั ั‚ะตะผะธ ะดะฐะฝะฝั‹ะผะธ, ะบะพั‚ะพั€ั‹ะต ะฑั‹ะปะธ ัƒัั‚ะฐะฝะพะฒะปะตะฝั‹ (ะพั‚ะฟั€ะฐะฒะปะตะฝั‹ ะฒ ะทะฐะฟั€ะพัะต), ะพะฟัƒัะบะฐั ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ: +ะ—ะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพ ะดะปั ัะพะทะดะฐะฝะธั `dict` ั‚ะพะปัŒะบะพ ั ั‚ะตะผะธ ะดะฐะฝะฝั‹ะผะธ, ะบะพั‚ะพั€ั‹ะต ะฑั‹ะปะธ ัƒัั‚ะฐะฝะพะฒะปะตะฝั‹ (ะพั‚ะฟั€ะฐะฒะปะตะฝั‹ ะฒ ะทะฐะฟั€ะพัะต), ะพะฟัƒัะบะฐั ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ: {* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} @@ -66,14 +60,6 @@ ะขะตะฟะตั€ัŒ ะผะพะถะฝะพ ัะพะทะดะฐั‚ัŒ ะบะพะฟะธัŽ ััƒั‰ะตัั‚ะฒัƒัŽั‰ะตะน ะผะพะดะตะปะธ, ะธัะฟะพะปัŒะทัƒั `.model_copy()`, ะธ ะฟะตั€ะตะดะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `update` ั `dict`, ัะพะดะตั€ะถะฐั‰ะธะผ ะดะฐะฝะฝั‹ะต ะดะปั ะพะฑะฝะพะฒะปะตะฝะธั. -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic v1 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะปัั `.copy()`, ะฒ Pydantic v2 ะพะฝ ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน (ะฝะพ ะฒัะต ะตั‰ะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั) ะธ ะฟะตั€ะตะธะผะตะฝะพะฒะฐะฝ ะฒ `.model_copy()`. - -ะŸั€ะธะผะตั€ั‹ ะทะดะตััŒ ะธัะฟะพะปัŒะทัƒัŽั‚ `.copy()` ะดะปั ัะพะฒะผะตัั‚ะธะผะพัั‚ะธ ั Pydantic v1, ะฝะพ ะตัะปะธ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Pydantic v2, ะปัƒั‡ัˆะต ะธัะฟะพะปัŒะทัƒะนั‚ะต `.model_copy()`. - -/// - ะะฐะฟั€ะธะผะตั€, `stored_item_model.model_copy(update=update_data)`: {* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} @@ -84,9 +70,9 @@ * (ะžะฟั†ะธะพะฝะฐะปัŒะฝะพ) ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `PATCH` ะฒะผะตัั‚ะพ `PUT`. * ะ˜ะทะฒะปะตั‡ัŒ ัะพั…ั€ะฐะฝั‘ะฝะฝั‹ะต ะดะฐะฝะฝั‹ะต. -* ะŸะพะผะตัั‚ะธั‚ัŒ ัั‚ะธ ะดะฐะฝะฝั‹ะต ะฒ Pydantic ะผะพะดะตะปัŒ. +* ะŸะพะผะตัั‚ะธั‚ัŒ ัั‚ะธ ะดะฐะฝะฝั‹ะต ะฒ Pydantic-ะผะพะดะตะปัŒ. * ะกะณะตะฝะตั€ะธั€ะพะฒะฐั‚ัŒ `dict` ะฑะตะท ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะธะท ะฒั…ะพะดะฝะพะน ะผะพะดะตะปะธ (ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ `exclude_unset`). - * ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะผะพะถะฝะพ ะพะฑะฝะพะฒะปัั‚ัŒ ั‚ะพะปัŒะบะพ ั‚ะต ะทะฝะฐั‡ะตะฝะธั, ะบะพั‚ะพั€ั‹ะต ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ ัƒัั‚ะฐะฝะพะฒะปะตะฝั‹ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะผ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะฟะตั€ะตะพะฟั€ะตะดะตะปัั‚ัŒ ะทะฝะฐั‡ะตะฝะธั, ัƒะถะต ัะพั…ั€ะฐะฝะตะฝะฝั‹ะต ะฒ ะผะพะดะตะปะธ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. + * ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะผะพะถะฝะพ ะพะฑะฝะพะฒะปัั‚ัŒ ั‚ะพะปัŒะบะพ ั‚ะต ะทะฝะฐั‡ะตะฝะธั, ะบะพั‚ะพั€ั‹ะต ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ ัƒัั‚ะฐะฝะพะฒะปะตะฝั‹ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะผ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะฟะตั€ะตะพะฟั€ะตะดะตะปัั‚ัŒ ัƒะถะต ัะพั…ั€ะฐะฝะตะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ะทะฝะฐั‡ะตะฝะธัะผะธ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะธะท ะฒะฐัˆะตะน ะผะพะดะตะปะธ. * ะกะพะทะดะฐั‚ัŒ ะบะพะฟะธัŽ ั…ั€ะฐะฝะธะผะพะน ะผะพะดะตะปะธ, ะพะฑะฝะพะฒะธะฒ ะตะต ะฐั‚ั€ะธะฑัƒั‚ั‹ ะฟะพะปัƒั‡ะตะฝะฝั‹ะผะธ ั‡ะฐัั‚ะธั‡ะฝั‹ะผะธ ะพะฑะฝะพะฒะปะตะฝะธัะผะธ (ั ะฟะพะผะพั‰ัŒัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `update`). * ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ัะบะพะฟะธั€ะพะฒะฐะฝะฝัƒัŽ ะผะพะดะตะปัŒ ะฒ ั‚ะพ, ั‡ั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ัะพั…ั€ะฐะฝะตะฝะพ ะฒ ะฒะฐัˆะตะน ะ‘ะ” (ะฝะฐะฟั€ะธะผะตั€, ั ะฟะพะผะพั‰ัŒัŽ `jsonable_encoder`). * ะญั‚ะพ ัั€ะฐะฒะฝะธะผะพ ั ะฟะพะฒั‚ะพั€ะฝั‹ะผ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ ะผะตั‚ะพะดะฐ ะผะพะดะตะปะธ `.model_dump()`, ะฝะพ ะฟั€ะธ ัั‚ะพะผ ะฟั€ะพะธัั…ะพะดะธั‚ ะฟั€ะพะฒะตั€ะบะฐ (ะธ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต) ะทะฝะฐั‡ะตะฝะธะน ะฒ ั‚ะธะฟั‹ ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝั‹ ะฒ JSON, ะฝะฐะฟั€ะธะผะตั€, `datetime` ะฒ `str`. @@ -97,7 +83,7 @@ /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะญั‚ัƒ ะถะต ั‚ะตั…ะฝะธะบัƒ ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะดะปั ะพะฟะตั€ะฐั†ะธะธ HTTP `PUT`. +ะะฐ ัะฐะผะพะผ ะดะตะปะต ัั‚ัƒ ะถะต ั‚ะตั…ะฝะธะบัƒ ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะดะปั ะพะฟะตั€ะฐั†ะธะธ HTTP `PUT`. ะะพ ะฒ ะฟั€ะธะฒะตะดะตะฝะฝะพะผ ะฟั€ะธะผะตั€ะต ะธัะฟะพะปัŒะทัƒะตั‚ัั `PATCH`, ะฟะพัะบะพะปัŒะบัƒ ะพะฝ ะฑั‹ะป ัะพะทะดะฐะฝ ะธะผะตะฝะฝะพ ะดะปั ั‚ะฐะบะธั… ัะปัƒั‡ะฐะตะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั. diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md index b61f3e7a09..537d7ebc96 100644 --- a/docs/ru/docs/tutorial/body.md +++ b/docs/ru/docs/tutorial/body.md @@ -32,9 +32,10 @@ {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + ะขะฐะบ ะถะต, ะบะฐะบ ะฟั€ะธ ะพะฑัŠัะฒะปะตะฝะธะธ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ ะทะฐะฟั€ะพัะฐ: ะบะพะณะดะฐ ะฐั‚ั€ะธะฑัƒั‚ ะผะพะดะตะปะธ ะธะผะตะตั‚ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะพะฝ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ. ะ˜ะฝะฐั‡ะต ะพะฝ ะพะฑัะทะฐั‚ะตะปะตะฝ. ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต `None`, ั‡ั‚ะพะฑั‹ ัะดะตะปะฐั‚ัŒ ะตะณะพ ะฟั€ะพัั‚ะพ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ. -ะะฐะฟั€ะธะผะตั€, ะผะพะดะตะปัŒ ะฒั‹ัˆะต ะพะฟะธัั‹ะฒะฐะตั‚ ั‚ะฐะบะพะน JSON "ะพะฑัŠะตะบั‚" (ะธะปะธ Python `dict`): +ะะฐะฟั€ะธะผะตั€, ะผะพะดะตะปัŒ ะฒั‹ัˆะต ะพะฟะธัั‹ะฒะฐะตั‚ ั‚ะฐะบะพะน JSON "`object`" (ะธะปะธ Python `dict`): ```JSON { @@ -45,7 +46,7 @@ } ``` -...ั‚ะฐะบ ะบะฐะบ `description` ะธ `tax` ัะฒะปััŽั‚ัั ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผะธ (ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `None`), ั‚ะฐะบะพะน JSON "ะพะฑัŠะตะบั‚" ั‚ะพะถะต ะฑัƒะดะตั‚ ะบะพั€ั€ะตะบั‚ะฝั‹ะผ: +...ั‚ะฐะบ ะบะฐะบ `description` ะธ `tax` ัะฒะปััŽั‚ัั ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผะธ (ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `None`), ั‚ะฐะบะพะน JSON "`object`" ั‚ะพะถะต ะฑัƒะดะตั‚ ะบะพั€ั€ะตะบั‚ะฝั‹ะผ: ```JSON { @@ -73,7 +74,7 @@ * ะŸะตั€ะตะดะฐัั‚ ะฟะพะปัƒั‡ะตะฝะฝั‹ะต ะดะฐะฝะฝั‹ะต ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `item`. * ะŸะพัะบะพะปัŒะบัƒ ะฒะฝัƒั‚ั€ะธ ั„ัƒะฝะบั†ะธะธ ะฒั‹ ะพะฑัŠัะฒะธะปะธ ะตะณะพ ั ั‚ะธะฟะพะผ `Item`, ัƒ ะฒะฐั ะฑัƒะดะตั‚ ะฟะพะดะดะตั€ะถะบะฐ ัะพ ัั‚ะพั€ะพะฝั‹ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ (ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะธ ั‚. ะฟ.) ะดะปั ะฒัะตั… ะฐั‚ั€ะธะฑัƒั‚ะพะฒ ะธ ะธั… ั‚ะธะฟะพะฒ. * ะกะณะตะฝะตั€ะธั€ัƒะตั‚ ะพะฟั€ะตะดะตะปะตะฝะธั JSON Schema ะดะปั ะฒะฐัˆะตะน ะผะพะดะตะปะธ; ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะธ ะฒ ะดั€ัƒะณะธั… ะผะตัั‚ะฐั…, ะตัะปะธ ัั‚ะพ ะธะผะตะตั‚ ัะผั‹ัะป ะดะปั ะฒะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ. -* ะญั‚ะธ ัั…ะตะผั‹ ะฑัƒะดัƒั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผั‹ OpenAPI ะธ ะฑัƒะดัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน UIs. +* ะญั‚ะธ ัั…ะตะผั‹ ะฑัƒะดัƒั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผั‹ OpenAPI ะธ ะฑัƒะดัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน UIs. ## ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั { #automatic-docs } @@ -127,14 +128,6 @@ JSON Schema ะฒะฐัˆะธั… ะผะพะดะตะปะตะน ะฑัƒะดะตั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพ {* ../../docs_src/body/tutorial002_py310.py *} -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -ะ’ Pydantic v1 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะปัั `.dict()`, ะฒ Pydantic v2 ะพะฝ ะฑั‹ะป ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน (ะฝะพ ะฒัั‘ ะตั‰ั‘ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั) ะธ ะฟะตั€ะตะธะผะตะฝะพะฒะฐะฝ ะฒ `.model_dump()`. - -ะŸั€ะธะผะตั€ั‹ ะทะดะตััŒ ะธัะฟะพะปัŒะทัƒัŽั‚ `.dict()` ะดะปั ัะพะฒะผะตัั‚ะธะผะพัั‚ะธ ั Pydantic v1, ะฝะพ ะตัะปะธ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Pydantic v2, ะธัะฟะพะปัŒะทัƒะนั‚ะต `.model_dump()`. - -/// - ## ะขะตะปะพ ะทะฐะฟั€ะพัะฐ + ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟัƒั‚ะธ { #request-body-path-parameters } ะ’ั‹ ะผะพะถะตั‚ะต ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟัƒั‚ะธ ะธ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ. @@ -143,6 +136,7 @@ JSON Schema ะฒะฐัˆะธั… ะผะพะดะตะปะตะน ะฑัƒะดะตั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## ะขะตะปะพ ะทะฐะฟั€ะพัะฐ + ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟัƒั‚ะธ + ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะทะฐะฟั€ะพัะฐ { #request-body-path-query-parameters } ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ **ั‚ะตะปะฐ**, **ะฟัƒั‚ะธ** ะธ **ะทะฐะฟั€ะพัะฐ**. @@ -153,7 +147,7 @@ JSON Schema ะฒะฐัˆะธั… ะผะพะดะตะปะตะน ะฑัƒะดะตั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพ ะŸะฐั€ะฐะผะตั‚ั€ั‹ ั„ัƒะฝะบั†ะธะธ ะฑัƒะดัƒั‚ ั€ะฐัะฟะพะทะฝะฐะฝั‹ ัะปะตะดัƒัŽั‰ะธะผ ะพะฑั€ะฐะทะพะผ: -* ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะฐะบะถะต ะพะฑัŠัะฒะปะตะฝ ะฒ **ะฟัƒั‚ะธ**, ะพะฝ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ ะฟัƒั‚ะธ. +* ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะฐะบะถะต ะพะฑัŠัะฒะปะตะฝ ะฒ **ะฟัƒั‚ะธ**, ะพะฝ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะบะฐะบ path-ะฟะฐั€ะฐะผะตั‚ั€. * ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะธะผะตะตั‚ **ัะบะฐะปัั€ะฝั‹ะน ั‚ะธะฟ** (ะฝะฐะฟั€ะธะผะตั€, `int`, `float`, `str`, `bool` ะธ ั‚. ะฟ.), ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ **ะทะฐะฟั€ะพัะฐ**. * ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะพะฑัŠัะฒะปะตะฝ ะบะฐะบ ั‚ะธะฟ **ะผะพะดะตะปะธ Pydantic**, ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะบะฐะบ **ั‚ะตะปะพ** ะทะฐะฟั€ะพัะฐ. @@ -161,7 +155,7 @@ JSON Schema ะฒะฐัˆะธั… ะผะพะดะตะปะตะน ะฑัƒะดะตั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพ FastAPI ะฟะพะฝะธะผะฐะตั‚, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต `q` ะฝะต ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ ะธะท-ะทะฐ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. -ะะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ `str | None` (Python 3.10+) ะธะปะธ `Union[str, None]` (Python 3.9+) ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ัั FastAPI ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะพะฑัะทะฐั‚ะตะปัŒะฝะพัั‚ะธ; ะพะฝ ัƒะทะฝะฐะตั‚, ั‡ั‚ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัƒ ะฝะตะณะพ ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. +ะะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ `str | None` (Python 3.10+) ะธะปะธ `Union` ะฒ `Union[str, None]` (Python 3.9+) ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ัั FastAPI ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะพะฑัะทะฐั‚ะตะปัŒะฝะพัั‚ะธ; ะพะฝ ัƒะทะฝะฐะตั‚, ั‡ั‚ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัƒ ะฝะตะณะพ ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. ะะพ ะดะพะฑะฐะฒะปะตะฝะธะต ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ ะฟะพะทะฒะพะปะธั‚ ะฒะฐัˆะตะผัƒ ั€ะตะดะฐะบั‚ะพั€ัƒ ะบะพะดะฐ ะปัƒั‡ัˆะต ะฒะฐั ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ะธ ะพะฑะฝะฐั€ัƒะถะธะฒะฐั‚ัŒ ะพัˆะธะฑะบะธ. @@ -169,4 +163,4 @@ FastAPI ะฟะพะฝะธะผะฐะตั‚, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต `q` ะฝะต ัะฒะปัะตั‚ัั ะพะฑ ## ะ‘ะตะท Pydantic { #without-pydantic } -ะ•ัะปะธ ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะผะพะดะตะปะธ Pydantic, ะฒั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ **Body**. ะกะผ. ั€ะฐะทะดะตะป ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ [ะขะตะปะพ โ€” ะะตัะบะพะปัŒะบะพ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ: ะ•ะดะธะฝะธั‡ะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ะฒ ั‚ะตะปะต](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. +ะ•ัะปะธ ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะผะพะดะตะปะธ Pydantic, ะฒั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ **Body**. ะกะผ. ั€ะฐะทะดะตะป ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ [ะขะตะปะพ ะทะฐะฟั€ะพัะฐ - ะะตัะบะพะปัŒะบะพ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ: ะ•ะดะธะฝะธั‡ะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ะฒ ั‚ะตะปะต](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md index 2f0ce4e33e..03156f2b4e 100644 --- a/docs/ru/docs/tutorial/extra-models.md +++ b/docs/ru/docs/tutorial/extra-models.md @@ -22,21 +22,13 @@ {* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั +### ะŸั€ะพ `**user_in.model_dump()` { #about-user-in-model-dump } -ะ’ Pydantic v1 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะปัั `.dict()`, ะฒ Pydantic v2 ะพะฝ ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน (ะฝะพ ะฒัั‘ ะตั‰ั‘ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั) ะธ ะฟะตั€ะตะธะผะตะฝะพะฒะฐะฝ ะฒ `.model_dump()`. +#### `.model_dump()` ะธะท Pydantic { #pydantics-model-dump } -ะ’ ะฟั€ะธะผะตั€ะฐั… ะทะดะตััŒ ะธัะฟะพะปัŒะทัƒะตั‚ัั `.dict()` ะดะปั ัะพะฒะผะตัั‚ะธะผะพัั‚ะธ ั Pydantic v1, ะฝะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต Pydantic v2, ัะปะตะดัƒะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `.model_dump()`. +`user_in` โ€” ัั‚ะพ Pydantic-ะผะพะดะตะปัŒ ะบะปะฐััะฐ `UserIn`. -/// - -### ะŸั€ะพ `**user_in.dict()` { #about-user-in-dict } - -#### `.dict()` ะธะท Pydantic { #pydantics-dict } - -`user_in` - ัั‚ะพ Pydantic-ะผะพะดะตะปัŒ ะบะปะฐััะฐ `UserIn`. - -ะฃ Pydantic-ะผะพะดะตะปะตะน ะตัั‚ัŒ ะผะตั‚ะพะด `.dict()`, ะบะพั‚ะพั€ั‹ะน ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ `dict` ั ะดะฐะฝะฝั‹ะผะธ ะผะพะดะตะปะธ. +ะฃ Pydantic-ะผะพะดะตะปะตะน ะตัั‚ัŒ ะผะตั‚ะพะด `.model_dump()`, ะบะพั‚ะพั€ั‹ะน ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ `dict` ั ะดะฐะฝะฝั‹ะผะธ ะผะพะดะตะปะธ. ะŸะพัั‚ะพะผัƒ, ะตัะปะธ ะผั‹ ัะพะทะดะฐะดะธะผ Pydantic-ะพะฑัŠะตะบั‚ `user_in` ั‚ะฐะบะธะผ ัะฟะพัะพะฑะพะผ: @@ -47,10 +39,10 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com ะธ ะทะฐั‚ะตะผ ะฒั‹ะทะพะฒะตะผ: ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() ``` -ั‚ะพ ั‚ะตะฟะตั€ัŒ ัƒ ะฝะฐั ะตัั‚ัŒ `dict` ั ะดะฐะฝะฝั‹ะผะธ ะผะพะดะตะปะธ ะฒ ะฟะตั€ะตะผะตะฝะฝะพะน `user_dict` (ัั‚ะพ `dict` ะฒะผะตัั‚ะพ ะพะฑัŠะตะบั‚ะฐ Pydantic-ะผะพะดะตะปะธ). +ั‚ะพ ั‚ะตะฟะตั€ัŒ ัƒ ะฝะฐั ะตัั‚ัŒ `dict` ั ะดะฐะฝะฝั‹ะผะธ ะฒ ะฟะตั€ะตะผะตะฝะฝะพะน `user_dict` (ัั‚ะพ `dict` ะฒะผะตัั‚ะพ ะพะฑัŠะตะบั‚ะฐ Pydantic-ะผะพะดะตะปะธ). ะ˜ ะตัะปะธ ะผั‹ ะฒั‹ะทะพะฒะตะผ: @@ -58,7 +50,7 @@ user_dict = user_in.dict() print(user_dict) ``` -ะผั‹ ะผะพะถะตะผ ะฟะพะปัƒั‡ะธั‚ัŒ `dict` ั ั‚ะฐะบะธะผะธ ะดะฐะฝะฝั‹ะผะธ: +ะผั‹ ะฟะพะปัƒั‡ะธะผ Python `dict` ั: ```Python { @@ -71,7 +63,7 @@ print(user_dict) #### ะ ะฐัะฟะฐะบะพะฒะบะฐ `dict` { #unpacking-a-dict } -ะ•ัะปะธ ะผั‹ ะฒะพะทัŒะผั‘ะผ `dict` ะฝะฐะฟะพะดะพะฑะธะต `user_dict` ะธ ะฟะตั€ะตะดะฐะดะธะผ ะตะณะพ ะฒ ั„ัƒะฝะบั†ะธัŽ (ะธะปะธ ะบะปะฐัั), ะธัะฟะพะปัŒะทัƒั `**user_dict`, Python ั€ะฐัะฟะฐะบัƒะตั‚ ะตะณะพ. ะžะฝ ะฟะตั€ะตะดะฐัั‚ ะบะปัŽั‡ะธ ะธ ะทะฝะฐั‡ะตะฝะธั `user_dict` ะฝะฐะฟั€ัะผัƒัŽ ะบะฐะบ ะฐั€ะณัƒะผะตะฝั‚ั‹ ั‚ะธะฟะฐ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะธะต. +ะ•ัะปะธ ะผั‹ ะฒะพะทัŒะผั‘ะผ `dict` ะฝะฐะฟะพะดะพะฑะธะต `user_dict` ะธ ะฟะตั€ะตะดะฐะดะธะผ ะตะณะพ ะฒ ั„ัƒะฝะบั†ะธัŽ (ะธะปะธ ะบะปะฐัั), ะธัะฟะพะปัŒะทัƒั `**user_dict`, Python ะตะณะพ "ั€ะฐัะฟะฐะบัƒะตั‚". ะžะฝ ะฟะตั€ะตะดะฐัั‚ ะบะปัŽั‡ะธ ะธ ะทะฝะฐั‡ะตะฝะธั `user_dict` ะฝะฐะฟั€ัะผัƒัŽ ะบะฐะบ ะฐั€ะณัƒะผะตะฝั‚ั‹ ั‚ะธะฟะฐ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะธะต. ะŸะพัั‚ะพะผัƒ, ะฟั€ะพะดะพะปะถะฐั ะพะฟะธัะฐะฝะฝั‹ะน ะฒั‹ัˆะต ะฟั€ะธะผะตั€ ั `user_dict`, ะฝะฐะฟะธัะฐะฝะธะต ั‚ะฐะบะพะณะพ ะบะพะดะฐ: @@ -79,7 +71,7 @@ print(user_dict) UserInDB(**user_dict) ``` -ะ‘ัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฟั€ะธะผะตั€ะฝะพ ั‚ะฐะบะพะน ะบะพะด: +ะฑัƒะดะตั‚ ัะบะฒะธะฒะฐะปะตะฝั‚ะฝะพ: ```Python UserInDB( @@ -90,7 +82,7 @@ UserInDB( ) ``` -ะ˜ะปะธ, ะตัะปะธ ะดะปั ะฑะพะปัŒัˆะตะน ั‚ะพั‡ะฝะพัั‚ะธ ะผั‹ ะฝะฐะฟั€ัะผัƒัŽ ะธัะฟะพะปัŒะทัƒะตะผ `user_dict` ั ะปัŽะฑั‹ะผ ะฟะพั‚ะตะฝั†ะธะฐะปัŒะฝั‹ะผ ัะพะดะตั€ะถะธะผั‹ะผ, ั‚ะพ ัั‚ะพั‚ ะฟั€ะธะผะตั€ ะฑัƒะดะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: +ะ˜ะปะธ, ะฑะพะปะตะต ั‚ะพั‡ะฝะพ, ะตัะปะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `user_dict` ะฝะฐะฟั€ัะผัƒัŽ, ั ะปัŽะฑั‹ะผ ัะพะดะตั€ะถะธะผั‹ะผ, ะบะพั‚ะพั€ะพะต ะพะฝ ะผะพะถะตั‚ ะธะผะตั‚ัŒ ะฒ ะฑัƒะดัƒั‰ะตะผ: ```Python UserInDB( @@ -101,22 +93,22 @@ UserInDB( ) ``` -#### Pydantic-ะผะพะดะตะปัŒ ะธะท ัะพะดะตั€ะถะธะผะพะณะพ ะดั€ัƒะณะพะน ะผะพะดะตะปะธ { #a-pydantic-model-from-the-contents-of-another } +#### Pydantic-ะผะพะดะตะปัŒ ะธะท ัะพะดะตั€ะถะธะผะพะณะพ ะดั€ัƒะณะพะน { #a-pydantic-model-from-the-contents-of-another } -ะšะฐะบ ะฒ ะฟั€ะธะผะตั€ะต ะฒั‹ัˆะต ะผั‹ ะฟะพะปัƒั‡ะธะปะธ `user_dict` ะธะท `user_in.dict()`, ัั‚ะพั‚ ะบะพะด: +ะšะฐะบ ะฒ ะฟั€ะธะผะตั€ะต ะฒั‹ัˆะต ะผั‹ ะฟะพะปัƒั‡ะธะปะธ `user_dict` ะธะท `user_in.model_dump()`, ัั‚ะพั‚ ะบะพะด: ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() UserInDB(**user_dict) ``` ะฑัƒะดะตั‚ ั€ะฐะฒะฝะพะทะฝะฐั‡ะตะฝ ั‚ะฐะบะพะผัƒ: ```Python -UserInDB(**user_in.dict()) +UserInDB(**user_in.model_dump()) ``` -...ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ `user_in.dict()` - ัั‚ะพ `dict`, ะธ ะทะฐั‚ะตะผ ะผั‹ ัƒะบะฐะทั‹ะฒะฐะตะผ, ั‡ั‚ะพะฑั‹ Python ะตะณะพ "ั€ะฐัะฟะฐะบะพะฒะฐะป", ะบะพะณะดะฐ ะฟะตั€ะตะดะฐั‘ะผ ะตะณะพ ะฒ `UserInDB` ะธ ัั‚ะฐะฒะธะผ ะฟะตั€ะตะด ะฝะธะผ `**`. +...ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ `user_in.model_dump()` โ€” ัั‚ะพ `dict`, ะธ ะทะฐั‚ะตะผ ะผั‹ ัƒะบะฐะทั‹ะฒะฐะตะผ, ั‡ั‚ะพะฑั‹ Python ะตะณะพ "ั€ะฐัะฟะฐะบะพะฒะฐะป", ะบะพะณะดะฐ ะฟะตั€ะตะดะฐั‘ะผ ะตะณะพ ะฒ `UserInDB` ั ะฟั€ะตั„ะธะบัะพะผ `**`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะผั‹ ะฟะพะปัƒั‡ะฐะตะผ Pydantic-ะผะพะดะตะปัŒ ะฝะฐ ะพัะฝะพะฒะต ะดะฐะฝะฝั‹ั… ะธะท ะดั€ัƒะณะพะน Pydantic-ะผะพะดะตะปะธ. @@ -125,10 +117,10 @@ UserInDB(**user_in.dict()) ะ˜ ะทะฐั‚ะตะผ, ะตัะปะธ ะผั‹ ะดะพะฑะฐะฒะธะผ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะน ะธะผะตะฝะพะฒะฐะฝะฝั‹ะน ะฐั€ะณัƒะผะตะฝั‚ `hashed_password=hashed_password` ะบะฐะบ ะทะดะตััŒ: ```Python -UserInDB(**user_in.dict(), hashed_password=hashed_password) +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` -... ั‚ะพ ะผั‹ ะฟะพะปัƒั‡ะธะผ ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต: +...ั‚ะพ ะฒ ะธั‚ะพะณะต ะฟะพะปัƒั‡ะธั‚ัั ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต: ```Python UserInDB( @@ -142,13 +134,13 @@ UserInDB( /// warning | ะŸั€ะตะดัƒะฟั€ะตะถะดะตะฝะธะต -ะ’ัะฟะพะผะพะณะฐั‚ะตะปัŒะฝั‹ะต ั„ัƒะฝะบั†ะธะธ `fake_password_hasher` ะธ `fake_save_user` ะธัะฟะพะปัŒะทัƒัŽั‚ัั ั‚ะพะปัŒะบะพ ะดะปั ะดะตะผะพะฝัั‚ั€ะฐั†ะธะธ ะฒะพะทะผะพะถะฝะพะณะพ ะฟะพั‚ะพะบะฐ ะดะฐะฝะฝั‹ั… ะธ, ะบะพะฝะตั‡ะฝะพ, ะฝะต ะพะฑะตัะฟะตั‡ะธะฒะฐัŽั‚ ะฝะฐัั‚ะพัั‰ัƒัŽ ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒ. +ะ’ัะฟะพะผะพะณะฐั‚ะตะปัŒะฝั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ั„ัƒะฝะบั†ะธะธ `fake_password_hasher` ะธ `fake_save_user` ะธัะฟะพะปัŒะทัƒัŽั‚ัั ั‚ะพะปัŒะบะพ ะดะปั ะดะตะผะพะฝัั‚ั€ะฐั†ะธะธ ะฒะพะทะผะพะถะฝะพะณะพ ะฟะพั‚ะพะบะฐ ะดะฐะฝะฝั‹ั… ะธ, ะบะพะฝะตั‡ะฝะพ, ะฝะต ะพะฑะตัะฟะตั‡ะธะฒะฐัŽั‚ ะฝะฐัั‚ะพัั‰ัƒัŽ ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒ. /// ## ะกะพะบั€ะฐั‚ะธั‚ะต ะดัƒะฑะปะธั€ะพะฒะฐะฝะธะต { #reduce-duplication } -ะกะพะบั€ะฐั‰ะตะฝะธะต ะดัƒะฑะปะธั€ะพะฒะฐะฝะธั ะบะพะดะฐ - ัั‚ะพ ะพะดะฝะฐ ะธะท ะณะปะฐะฒะฝั‹ั… ะธะดะตะน **FastAPI**. +ะกะพะบั€ะฐั‰ะตะฝะธะต ะดัƒะฑะปะธั€ะพะฒะฐะฝะธั ะบะพะดะฐ โ€” ัั‚ะพ ะพะดะฝะฐ ะธะท ะณะปะฐะฒะฝั‹ั… ะธะดะตะน **FastAPI**. ะŸะพัะบะพะปัŒะบัƒ ะดัƒะฑะปะธั€ะพะฒะฐะฝะธะต ะบะพะดะฐ ะฟะพะฒั‹ัˆะฐะตั‚ ั€ะธัะบ ะฟะพัะฒะปะตะฝะธั ะฑะฐะณะพะฒ, ะฟั€ะพะฑะปะตะผ ั ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒัŽ, ะฟั€ะพะฑะปะตะผ ะดะตัะธะฝั…ั€ะพะฝะธะทะฐั†ะธะธ ะบะพะดะฐ (ะบะพะณะดะฐ ะฒั‹ ะพะฑะฝะพะฒะปัะตั‚ะต ะบะพะด ะฒ ะพะดะฝะพะผ ะผะตัั‚ะต, ะฝะพ ะฝะต ะพะฑะฝะพะฒะปัะตั‚ะต ะฒ ะดั€ัƒะณะพะผ), ะธ ั‚.ะด. @@ -166,7 +158,7 @@ UserInDB( ## `Union` ะธะปะธ `anyOf` { #union-or-anyof } -ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะพั‚ะฒะตั‚ ะบะฐะบ `Union` ะธะท ะดะฒัƒั… ะธะปะธ ะฑะพะปะตะต ั‚ะธะฟะพะฒ. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะพั‚ะฒะตั‚ ะดะพะปะถะตะฝ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ ะพะดะฝะพะผัƒ ะธะท ะฝะธั…. +ะ’ั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ HTTP-ะพั‚ะฒะตั‚ ะบะฐะบ `Union` ะธะท ะดะฒัƒั… ะธะปะธ ะฑะพะปะตะต ั‚ะธะฟะพะฒ. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ HTTP-ะพั‚ะฒะตั‚ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะปัŽะฑั‹ะผ ะธะท ะฝะธั…. ะžะฝ ะฑัƒะดะตั‚ ะพะฟั€ะตะดะตะปั‘ะฝ ะฒ OpenAPI ะบะฐะบ `anyOf`. @@ -174,7 +166,7 @@ UserInDB( /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต -ะŸั€ะธ ะพะฑัŠัะฒะปะตะฝะธะธ `Union`, ัะฝะฐั‡ะฐะปะฐ ัƒะบะฐะทั‹ะฒะฐะนั‚ะต ะฝะฐะธะฑะพะปะตะต ะดะตั‚ะฐะปัŒะฝั‹ะต ั‚ะธะฟั‹, ะทะฐั‚ะตะผ ะผะตะฝะตะต ะดะตั‚ะฐะปัŒะฝั‹ะต. ะ’ ะฟั€ะธะผะตั€ะต ะฝะธะถะต ะฑะพะปะตะต ะดะตั‚ะฐะปัŒะฝั‹ะน `PlaneItem` ัั‚ะพะธั‚ ะฟะตั€ะตะด `CarItem` ะฒ `Union[PlaneItem, CarItem]`. +ะŸั€ะธ ะพะฑัŠัะฒะปะตะฝะธะธ `Union` ัะฝะฐั‡ะฐะปะฐ ัƒะบะฐะทั‹ะฒะฐะนั‚ะต ะฝะฐะธะฑะพะปะตะต ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ั‚ะธะฟ, ะทะฐั‚ะตะผ ะผะตะฝะตะต ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน. ะ’ ะฟั€ะธะผะตั€ะต ะฝะธะถะต ะฑะพะปะตะต ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน `PlaneItem` ัั‚ะพะธั‚ ะฟะตั€ะตะด `CarItem` ะฒ `Union[PlaneItem, CarItem]`. /// @@ -192,19 +184,19 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -ะะพ ะตัะปะธ ะผั‹ ะฟะพะผะตั‰ะฐะตะผ ะตะณะพ ะฒ `response_model=PlaneItem | CarItem` ะผั‹ ะฟะพะปัƒั‡ะธะผ ะพัˆะธะฑะบัƒ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ Python ะฟะพะฟั‹ั‚ะฐะตั‚ัั ะฟั€ะพะธะทะฒะตัั‚ะธ **ะฝะตะบะพั€ั€ะตะบั‚ะฝัƒัŽ ะพะฟะตั€ะฐั†ะธัŽ** ะผะตะถะดัƒ `PlaneItem` ะธ `CarItem` ะฒะผะตัั‚ะพ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐั‚ัŒ ัั‚ะพ ะบะฐะบ ะฐะฝะฝะพั‚ะฐั†ะธัŽ ั‚ะธะฟะฐ. +ะะพ ะตัะปะธ ะผั‹ ะฟะพะผะตัั‚ะธะผ ัั‚ะพ ะฒ ะฟั€ะธัะฒะฐะธะฒะฐะฝะธะต `response_model=PlaneItem | CarItem`, ะผั‹ ะฟะพะปัƒั‡ะธะผ ะพัˆะธะฑะบัƒ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ Python ะฟะพะฟั‹ั‚ะฐะตั‚ัั ะฟั€ะพะธะทะฒะตัั‚ะธ **ะฝะตะบะพั€ั€ะตะบั‚ะฝัƒัŽ ะพะฟะตั€ะฐั†ะธัŽ** ะผะตะถะดัƒ `PlaneItem` ะธ `CarItem` ะฒะผะตัั‚ะพ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐั‚ัŒ ัั‚ะพ ะบะฐะบ ะฐะฝะฝะพั‚ะฐั†ะธัŽ ั‚ะธะฟะฐ. ## ะกะฟะธัะพะบ ะผะพะดะตะปะตะน { #list-of-models } -ะขะฐะบะธะผ ะถะต ะพะฑั€ะฐะทะพะผ ะฒั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปัั‚ัŒ ะพั‚ะฒะตั‚ั‹ ะบะฐะบ ัะฟะธัะบะธ ะพะฑัŠะตะบั‚ะพะฒ. +ะขะฐะบะธะผ ะถะต ะพะฑั€ะฐะทะพะผ ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะปัั‚ัŒ HTTP-ะพั‚ะฒะตั‚ั‹, ะฒะพะทะฒั€ะฐั‰ะฐัŽั‰ะธะต ัะฟะธัะบะธ ะพะฑัŠะตะบั‚ะพะฒ. -ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต `typing.List` ะธะท ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะน ะฑะธะฑะปะธะพั‚ะตะบะธ Python (ะธะปะธ ะฟั€ะพัั‚ะพ `list` ะฒ Python 3.9 ะธ ะฒั‹ัˆะต): +ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะน `typing.List` ะฒ Python (ะธะปะธ ะฟั€ะพัั‚ะพ `list` ะฒ Python 3.9 ะธ ะฒั‹ัˆะต): {* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} ## ะžั‚ะฒะตั‚ ั ะฟั€ะพะธะทะฒะพะปัŒะฝั‹ะผ `dict` { #response-with-arbitrary-dict } -ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะพั‚ะฒะตั‚, ะธัะฟะพะปัŒะทัƒั ะฟั€ะพะธะทะฒะพะปัŒะฝั‹ะน ะพะดะฝะพัƒั€ะพะฒะฝะตะฒั‹ะน `dict` ะธ ะพะฟั€ะตะดะตะปัั ั‚ะพะปัŒะบะพ ั‚ะธะฟั‹ ะบะปัŽั‡ะตะน ะธ ะทะฝะฐั‡ะตะฝะธะน ะฑะตะท ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั Pydantic-ะผะพะดะตะปะตะน. +ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ HTTP-ะพั‚ะฒะตั‚, ะธัะฟะพะปัŒะทัƒั ะพะฑั‹ั‡ะฝั‹ะน ะฟั€ะพะธะทะฒะพะปัŒะฝั‹ะน `dict`, ะพะฑัŠัะฒะธะฒ ั‚ะพะปัŒะบะพ ั‚ะธะฟ ะบะปัŽั‡ะตะน ะธ ะทะฝะฐั‡ะตะฝะธะน, ะฑะตะท ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั Pydantic-ะผะพะดะตะปะธ. ะญั‚ะพ ะฟะพะปะตะทะฝะพ, ะตัะปะธ ะฒั‹ ะทะฐั€ะฐะฝะตะต ะฝะต ะทะฝะฐะตั‚ะต ะบะพั€ั€ะตะบั‚ะฝั‹ั… ะฝะฐะทะฒะฐะฝะธะน ะฟะพะปะตะน/ะฐั‚ั€ะธะฑัƒั‚ะพะฒ (ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะฝัƒะถะฝั‹ ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ Pydantic-ะผะพะดะตะปะธ). @@ -214,6 +206,6 @@ some_variable: PlaneItem | CarItem ## ะ ะตะทัŽะผะต { #recap } -ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะฝะตัะบะพะปัŒะบะพ Pydantic-ะผะพะดะตะปะตะน ะธ ัะฒะพะฑะพะดะฝะพ ะฟั€ะธะผะตะฝัะนั‚ะต ะฝะฐัะปะตะดะพะฒะฐะฝะธะต ะดะปั ะบะฐะถะดะพะน ะธะท ะฝะธั…. +ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะฝะตัะบะพะปัŒะบะพ Pydantic-ะผะพะดะตะปะตะน ะธ ัะฒะพะฑะพะดะฝะพ ะฟั€ะธะผะตะฝัะนั‚ะต ะฝะฐัะปะตะดะพะฒะฐะฝะธะต ะดะปั ะบะฐะถะดะพะณะพ ัะปัƒั‡ะฐั. -ะ’ะฐะผ ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ ะธะผะตั‚ัŒ ะตะดะธะฝัั‚ะฒะตะฝะฝัƒัŽ ะผะพะดะตะปัŒ ะดะฐะฝะฝั‹ั… ะดะปั ะบะฐะถะดะพะน ััƒั‰ะฝะพัั‚ะธ, ะตัะปะธ ัั‚ะฐ ััƒั‰ะฝะพัั‚ัŒ ะดะพะปะถะฝะฐ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะฑั‹ั‚ัŒ ะฒ ั€ะฐะทะฝั‹ั… "ัะพัั‚ะพัะฝะธัั…". ะšะฐะบ ะฒ ัะปัƒั‡ะฐะต ั "ััƒั‰ะฝะพัั‚ัŒัŽ" ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั, ัƒ ะบะพั‚ะพั€ะพะณะพ ะตัั‚ัŒ ัะพัั‚ะพัะฝะธั ั ะฟะพะปัะผะธ `password`, `password_hash` ะธ ะฑะตะท ะฟะฐั€ะพะปั. +ะ’ะฐะผ ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ ะธะผะตั‚ัŒ ะตะดะธะฝัั‚ะฒะตะฝะฝัƒัŽ ะผะพะดะตะปัŒ ะดะฐะฝะฝั‹ั… ะดะปั ะบะฐะถะดะพะน ััƒั‰ะฝะพัั‚ะธ, ะตัะปะธ ัั‚ะฐ ััƒั‰ะฝะพัั‚ัŒ ะดะพะปะถะฝะฐ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะฑั‹ั‚ัŒ ะฒ ั€ะฐะทะฝั‹ั… "ัะพัั‚ะพัะฝะธัั…". ะšะฐะบ ะฒ ัะปัƒั‡ะฐะต ั "ััƒั‰ะฝะพัั‚ัŒัŽ" ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั, ัƒ ะบะพั‚ะพั€ะพะณะพ ะตัั‚ัŒ ัะพัั‚ะพัะฝะธะต, ะฒะบะปัŽั‡ะฐัŽั‰ะตะต `password`, `password_hash` ะธ ะพั‚ััƒั‚ัั‚ะฒะธะต ะฟะฐั€ะพะปั. diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 3a4ecc37dc..2bc2fb22c5 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -8,7 +8,7 @@ Query-ะฟะฐั€ะฐะผะตั‚ั€ `q` ะธะผะตะตั‚ ั‚ะธะฟ `str | None`, ัั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะพะฝ ะธะผะตะตั‚ ั‚ะธะฟ `str`, ะฝะพ ั‚ะฐะบะถะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None`. ะ—ะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ `None`, ะฟะพัั‚ะพะผัƒ FastAPI ะฑัƒะดะตั‚ ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะพะฝ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ. -/// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ +/// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต FastAPI ะฟะพะนะผั‘ั‚, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต `q` ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ, ะธะทโ€‘ะทะฐ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. @@ -177,7 +177,7 @@ q: str = Query(default="rick") **ะ—ะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ** ัƒ **ะฟะฐั€ะฐะผะตั‚ั€ะฐ ั„ัƒะฝะบั†ะธะธ** โ€” ัั‚ะพ **ะฝะฐัั‚ะพัั‰ะตะต ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**, ั‡ั‚ะพ ะฑะพะปะตะต ะธะฝั‚ัƒะธั‚ะธะฒะฝะพ ะดะปั Python. ๐Ÿ˜Œ -ะ’ั‹ ะผะพะถะตั‚ะต **ะฒั‹ะทะฒะฐั‚ัŒ** ัั‚ัƒ ะถะต ั„ัƒะฝะบั†ะธัŽ ะฒ **ะดั€ัƒะณะธั… ะผะตัั‚ะฐั…** ะฑะตะท FastAPI, ะธ ะพะฝะฐ ะฑัƒะดะตั‚ **ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะฐะบ ะพะถะธะดะฐะตั‚ัั**. ะ•ัะปะธ ะตัั‚ัŒ **ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน** ะฟะฐั€ะฐะผะตั‚ั€ (ะฑะตะท ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ), ะฒะฐัˆ **ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ** ัะพะพะฑั‰ะธั‚ ะพะฑ ะพัˆะธะฑะบะต, **Python** ั‚ะพะถะต ะฟะพะถะฐะปัƒะตั‚ัั, ะตัะปะธ ะฒั‹ ะทะฐะฟัƒัั‚ะธั‚ะต ะตั‘ ะฑะตะท ะฟะตั€ะตะดะฐั‡ะธ ะพะฑัะทะฐั‚ะตะปัŒะฝะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ. +ะ’ั‹ ะผะพะถะตั‚ะต **ะฒั‹ะทะฒะฐั‚ัŒ** ัั‚ัƒ ะถะต ั„ัƒะฝะบั†ะธัŽ ะฒ **ะดั€ัƒะณะธั… ะผะตัั‚ะฐั…** ะฑะตะท FastAPI, ะธ ะพะฝะฐ ะฑัƒะดะตั‚ **ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะฐะบ ะพะถะธะดะฐะตั‚ัั**. ะ•ัะปะธ ะตัั‚ัŒ **ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน** ะฟะฐั€ะฐะผะตั‚ั€ (ะฑะตะท ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ), ะฒะฐัˆ **ั€ะตะดะฐะบั‚ะพั€** ัะพะพะฑั‰ะธั‚ ะพะฑ ะพัˆะธะฑะบะต, **Python** ั‚ะพะถะต ะฟะพะถะฐะปัƒะตั‚ัั, ะตัะปะธ ะฒั‹ ะทะฐะฟัƒัั‚ะธั‚ะต ะตั‘ ะฑะตะท ะฟะตั€ะตะดะฐั‡ะธ ะพะฑัะทะฐั‚ะตะปัŒะฝะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ. ะ•ัะปะธ ะฒั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ะต `Annotated`, ะฐ ะฟั€ะธะผะตะฝัะตั‚ะต **(ัƒัั‚ะฐั€ะตะฒัˆะธะน) ัั‚ะธะปัŒ ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ**, ั‚ะพ ะฟั€ะธ ะฒั‹ะทะพะฒะต ัั‚ะพะน ั„ัƒะฝะบั†ะธะธ ะฑะตะท FastAPI ะฒ **ะดั€ัƒะณะธั… ะผะตัั‚ะฐั…** ะฒะฐะผ ะฝัƒะถะฝะพ **ะฟะพะผะฝะธั‚ัŒ** ะพ ั‚ะพะผ, ั‡ั‚ะพ ะฝะฐะดะพ ะฟะตั€ะตะดะฐั‚ัŒ ะฐั€ะณัƒะผะตะฝั‚ั‹, ั‡ั‚ะพะฑั‹ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะปะพ ะบะพั€ั€ะตะบั‚ะฝะพ, ะธะฝะฐั‡ะต ะทะฝะฐั‡ะตะฝะธั ะฑัƒะดัƒั‚ ะฝะต ั‚ะฐะบะธะผะธ, ะบะฐะบ ะฒั‹ ะพะถะธะดะฐะตั‚ะต (ะฝะฐะฟั€ะธะผะตั€, ะฒะผะตัั‚ะพ `str` ะฑัƒะดะตั‚ `QueryInfo` ะธะปะธ ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต). ะ˜ ะฝะธ ั€ะตะดะฐะบั‚ะพั€, ะฝะธ Python ะฝะต ะฑัƒะดัƒั‚ ั€ัƒะณะฐั‚ัŒัั ะฟั€ะธ ัะฐะผะพะผ ะฒั‹ะทะพะฒะต ั„ัƒะฝะบั†ะธะธ โ€” ะพัˆะธะฑะบะฐ ะฟั€ะพัะฒะธั‚ัั ะปะธัˆัŒ ะฟั€ะธ ะพะฟะตั€ะฐั†ะธัั… ะฒะฝัƒั‚ั€ะธ. @@ -191,7 +191,7 @@ q: str = Query(default="rick") ## ะ ะตะณัƒะปัั€ะฝั‹ะต ะฒั‹ั€ะฐะถะตะฝะธั { #add-regular-expressions } -ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ั€ะตะณัƒะปัั€ะฝะพะต ะฒั‹ั€ะฐะถะตะฝะธะต `pattern`, ะบะพั‚ะพั€ะพะผัƒ ะดะพะปะถะตะฝ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€: +ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ั€ะตะณัƒะปัั€ะฝะพะต ะฒั‹ั€ะฐะถะตะฝะธะต `pattern`, ะบะพั‚ะพั€ะพะผัƒ ะดะพะปะถะตะฝ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -205,20 +205,6 @@ q: str = Query(default="rick") ะขะตะฟะตั€ัŒ ะฒั‹ ะทะฝะฐะตั‚ะต, ั‡ั‚ะพ ะบะพะณะดะฐ ะพะฝะธ ะฟะพะฝะฐะดะพะฑัั‚ัั, ะฒั‹ ัะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะฒ **FastAPI**. -### `regex` ะธะท Pydantic v1 ะฒะผะตัั‚ะพ `pattern` { #pydantic-v1-regex-instead-of-pattern } - -ะ”ะพ Pydantic ะฒะตั€ัะธะธ 2 ะธ ะดะพ FastAPI 0.100.0 ัั‚ะพั‚ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะฐะทั‹ะฒะฐะปัั `regex`, ะฐ ะฝะต `pattern`, ะฝะพ ัะตะนั‡ะฐั ะพะฝ ัƒัั‚ะฐั€ะตะป. - -ะ’ั‹ ะฒัั‘ ะตั‰ั‘ ะผะพะถะตั‚ะต ะฒัั‚ั€ะตั‚ะธั‚ัŒ ั‚ะฐะบะพะน ะบะพะด: - -//// tab | Pydantic v1 - -{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *} - -//// - -ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ัั‚ะพ ัƒัั‚ะฐั€ะตะปะพ, ะธ ะบะพะด ัะปะตะดัƒะตั‚ ะพะฑะฝะพะฒะธั‚ัŒ ะฝะฐ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะฝะพะฒะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `pattern`. ๐Ÿค“ - ## ะ—ะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ { #default-values } ะšะพะฝะตั‡ะฝะพ, ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะดั€ัƒะณะธะต ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะฝะต ั‚ะพะปัŒะบะพ `None`. @@ -279,7 +265,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะผะฝะพะถะตัั‚ะฒะตะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั query-ะฟะฐั€ะฐะผะตั‚ั€ะฐ `q` (`foo` ะธ `bar`) ะฒ ะฒะธะดะต Python-`list` ะฒะฝัƒั‚ั€ะธ ะฒะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ ะพะฑั€ะฐะฑะพั‚ะบะธ ะฟัƒั‚ะธ*, ะฒ *ะฟะฐั€ะฐะผะตั‚ั€ะต ั„ัƒะฝะบั†ะธะธ* `q`. +ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะผะฝะพะถะตัั‚ะฒะตะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั *query-ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ* `q` (`foo` ะธ `bar`) ะฒ ะฒะธะดะต Python-`list` ะฒะฝัƒั‚ั€ะธ ะฒะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*, ะฒ *ะฟะฐั€ะฐะผะตั‚ั€ะต ั„ัƒะฝะบั†ะธะธ* `q`. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะพั‚ะฒะตั‚ ะฝะฐ ัั‚ะพั‚ URL ะฑัƒะดะตั‚: @@ -331,7 +317,7 @@ http://localhost:8000/items/ {* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} -/// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ +/// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ะฒ ัั‚ะพะผ ัะปัƒั‡ะฐะต FastAPI ะฝะต ะฑัƒะดะตั‚ ะฟั€ะพะฒะตั€ัั‚ัŒ ัะพะดะตั€ะถะธะผะพะต ัะฟะธัะบะฐ. @@ -345,7 +331,7 @@ http://localhost:8000/items/ ะญั‚ะฐ ะธะฝั„ะพั€ะผะฐั†ะธั ะฑัƒะดะตั‚ ะฒะบะปัŽั‡ะตะฝะฐ ะฒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝัƒัŽ OpenAPI-ัั…ะตะผัƒ ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะฐ ะธะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะธ ะฒะฝะตัˆะฝะธะผะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ. -/// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ +/// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ั€ะฐะทะฝั‹ะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะผะพะณัƒั‚ ะธะผะตั‚ัŒ ั€ะฐะทะฝั‹ะน ัƒั€ะพะฒะตะฝัŒ ะฟะพะดะดะตั€ะถะบะธ OpenAPI. @@ -415,7 +401,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems /// -ะะฐะฟั€ะธะผะตั€, ัั‚ะฐ ะบะฐัั‚ะพะผะฝะฐั ะฟั€ะพะฒะตั€ะบะฐ ัƒะฑะตะถะดะฐะตั‚ัั, ั‡ั‚ะพ ID ัะปะตะผะตะฝั‚ะฐ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั `isbn-` ะดะปั ะฝะพะผะตั€ะฐ ะบะฝะธะณะธ ISBN ะธะปะธ ั `imdb-` ะดะปั ID URL ั„ะธะปัŒะผะฐ ะฝะฐ IMDB: +ะะฐะฟั€ะธะผะตั€, ัั‚ะฐ ะบะฐัั‚ะพะผะฝะฐั ะฟั€ะพะฒะตั€ะบะฐ ัƒะฑะตะถะดะฐะตั‚ัั, ั‡ั‚ะพ ID ัะปะตะผะตะฝั‚ะฐ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั `isbn-` ะดะปั ะฝะพะผะตั€ะฐ ะบะฝะธะณะธ ISBN ะธะปะธ ั `imdb-` ะดะปั ID URL ั„ะธะปัŒะผะฐ ะฝะฐ IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -455,7 +441,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ะ—ะฐั‚ะตะผ ั `random.choice()` ะผะพะถะฝะพ ะฟะพะปัƒั‡ะธั‚ัŒ **ัะปัƒั‡ะฐะนะฝะพะต ะทะฝะฐั‡ะตะฝะธะต** ะธะท ัะฟะธัะบะฐ โ€” ั‚ะพ ะตัั‚ัŒ ะบะพั€ั‚ะตะถ ะฒะธะดะฐ `(id, name)`. ะญั‚ะพ ะฑัƒะดะตั‚ ั‡ั‚ะพโ€‘ั‚ะพ ะฒั€ะพะดะต `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -ะŸะพัะปะต ัั‚ะพะณะพ ะผั‹ **ั€ะฐัะฟะฐะบะพะฒั‹ะฒะฐะตะผ** ัั‚ะธ ะดะฒะฐ ะทะฝะฐั‡ะตะฝะธั ะบะพั€ั‚ะตะถะฐ ะฒ ะฟะตั€ะตะผะตะฝะฝั‹ะต `id` ะธ `name`. +ะŸะพัะปะต ัั‚ะพะณะพ ะผั‹ **ะฟั€ะธัะฒะฐะธะฒะฐะตะผ ัั‚ะธ ะดะฒะฐ ะทะฝะฐั‡ะตะฝะธั** ะบะพั€ั‚ะตะถะฐ ะฟะตั€ะตะผะตะฝะฝั‹ะผ `id` ะธ `name`. ะขะฐะบ ั‡ั‚ะพ, ะตัะปะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ ะฝะต ะฟะตั€ะตะดะฐะป ID ัะปะตะผะตะฝั‚ะฐ, ะพะฝ ะฒัั‘ ั€ะฐะฒะฝะพ ะฟะพะปัƒั‡ะธั‚ ัะปัƒั‡ะฐะนะฝัƒัŽ ั€ะตะบะพะผะตะฝะดะฐั†ะธัŽ. diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md index 07308c1db2..22a811cd57 100644 --- a/docs/ru/docs/tutorial/response-model.md +++ b/docs/ru/docs/tutorial/response-model.md @@ -6,11 +6,11 @@ {* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} -FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพั‚ ั‚ะธะฟ ะพั‚ะฒะตั‚ะฐ ะดะปั: +FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพั‚ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ, ั‡ั‚ะพะฑั‹: -* **ะ’ะฐะปะธะดะฐั†ะธะธ** ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ะดะฐะฝะฝั‹ั…. - * ะ•ัะปะธ ะดะฐะฝะฝั‹ะต ะฝะตะฒะฐะปะธะดะฝั‹ (ะฝะฐะฟั€ะธะผะตั€, ะพั‚ััƒั‚ัั‚ะฒัƒะตั‚ ะฟะพะปะต), ัั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะบะพะด *ะฒะฐัˆะตะณะพ* ะฟั€ะธะปะพะถะตะฝะธั ั€ะฐะฑะพั‚ะฐะตั‚ ะฝะตะบะพั€ั€ะตะบั‚ะฝะพ ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะฝะต ั‚ะพ, ั‡ั‚ะพ ะดะพะปะถะตะฝ. ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะตะฝะฐ ะพัˆะธะฑะบะฐ ัะตั€ะฒะตั€ะฐ ะฒะผะตัั‚ะพ ะฝะตะฟั€ะฐะฒะธะปัŒะฝั‹ั… ะดะฐะฝะฝั‹ั…. ะขะฐะบ ะฒั‹ ะธ ะฒะฐัˆะธ ะบะปะธะตะฝั‚ั‹ ะผะพะถะตั‚ะต ะฑั‹ั‚ัŒ ัƒะฒะตั€ะตะฝั‹, ั‡ั‚ะพ ะฟะพะปัƒั‡ะธั‚ะต ะพะถะธะดะฐะตะผั‹ะต ะดะฐะฝะฝั‹ะต ะธ ะพะถะธะดะฐะตะผัƒัŽ ัั‚ั€ัƒะบั‚ัƒั€ัƒ. -* ะ”ะพะฑะฐะฒะปะตะฝะธั **JSON Schema** ะดะปั ะพั‚ะฒะตั‚ะฐ ะฒ OpenAPI *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. +* **ะ’ะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ** ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะต ะดะฐะฝะฝั‹ะต. + * ะ•ัะปะธ ะดะฐะฝะฝั‹ะต ะฝะตะฒะฐะปะธะดะฝั‹ (ะฝะฐะฟั€ะธะผะตั€, ะพั‚ััƒั‚ัั‚ะฒัƒะตั‚ ะฟะพะปะต), ัั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะบะพะด *ะฒะฐัˆะตะณะพ* ะฟั€ะธะปะพะถะตะฝะธั ั€ะฐะฑะพั‚ะฐะตั‚ ะฝะตะบะพั€ั€ะตะบั‚ะฝะพ ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะฝะต ั‚ะพ, ั‡ั‚ะพ ะดะพะปะถะตะฝ. ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะตะฝะฐ ะพัˆะธะฑะบะฐ ัะตั€ะฒะตั€ะฐ ะฒะผะตัั‚ะพ ะฝะตะฟั€ะฐะฒะธะปัŒะฝั‹ั… ะดะฐะฝะฝั‹ั…. ะขะฐะบ ะฒั‹ ะธ ะฒะฐัˆะธ ะบะปะธะตะฝั‚ั‹ ะผะพะถะตั‚ะต ะฑั‹ั‚ัŒ ัƒะฒะตั€ะตะฝั‹, ั‡ั‚ะพ ะฟะพะปัƒั‡ะธั‚ะต ะพะถะธะดะฐะตะผั‹ะต ะดะฐะฝะฝั‹ะต ะธ ะพะถะธะดะฐะตะผัƒัŽ ัั‚ั€ัƒะบั‚ัƒั€ัƒ ะดะฐะฝะฝั‹ั…. +* ะ”ะพะฑะฐะฒะธั‚ัŒ **JSON Schema** ะดะปั ะพั‚ะฒะตั‚ะฐ ะฒ OpenAPI *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. * ะญั‚ะพ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐะฝะพ **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน**. * ะญั‚ะพ ั‚ะฐะบะถะต ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐะฝะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะณะตะฝะตั€ะฐั†ะธะธ ะบะปะธะตะฝั‚ัะบะพะณะพ ะบะพะดะฐ. @@ -23,7 +23,7 @@ FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพั‚ ั‚ะธะฟ ะพั‚ะฒะตั‚ะฐ ะดะปั: ะ‘ั‹ะฒะฐัŽั‚ ัะปัƒั‡ะฐะธ, ะบะพะณะดะฐ ะฒะฐะผ ะฝัƒะถะฝะพ ะธะปะธ ั…ะพั‡ะตั‚ัั ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฝะต ะฒ ั‚ะพั‡ะฝะพัั‚ะธ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‚ ะพะฑัŠัะฒะปะตะฝะฝะพะผัƒ ั‚ะธะฟัƒ. -ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ั…ะพั‚ะตั‚ัŒ **ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ัะปะพะฒะฐั€ัŒ (dict)** ะธะปะธ ะพะฑัŠะตะบั‚ ะธะท ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั…, ะฝะพ **ะพะฑัŠัะฒะธั‚ัŒ ะตะณะพ ะบะฐะบ Pydantic-ะผะพะดะตะปัŒ**. ะขะพะณะดะฐ Pydantic-ะผะพะดะตะปัŒ ะฒั‹ะฟะพะปะฝะธั‚ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั…, ะฒะฐะปะธะดะฐั†ะธัŽ ะธ ั‚.ะฟ. ะดะปั ะพะฑัŠะตะบั‚ะฐ, ะบะพั‚ะพั€ั‹ะน ะฒั‹ ะฒะตั€ะฝัƒะปะธ (ะฝะฐะฟั€ะธะผะตั€, ัะปะพะฒะฐั€ั ะธะปะธ ะพะฑัŠะตะบั‚ะฐ ะธะท ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั…). +ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ั…ะพั‚ะตั‚ัŒ **ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ัะปะพะฒะฐั€ัŒ** ะธะปะธ ะพะฑัŠะตะบั‚ ะธะท ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั…, ะฝะพ **ะพะฑัŠัะฒะธั‚ัŒ ะตะณะพ ะบะฐะบ Pydantic-ะผะพะดะตะปัŒ**. ะขะพะณะดะฐ Pydantic-ะผะพะดะตะปัŒ ะฒั‹ะฟะพะปะฝะธั‚ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั…, ะฒะฐะปะธะดะฐั†ะธัŽ ะธ ั‚.ะฟ. ะดะปั ะพะฑัŠะตะบั‚ะฐ, ะบะพั‚ะพั€ั‹ะน ะฒั‹ ะฒะตั€ะฝัƒะปะธ (ะฝะฐะฟั€ะธะผะตั€, ัะปะพะฒะฐั€ั ะธะปะธ ะพะฑัŠะตะบั‚ะฐ ะธะท ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั…). ะ•ัะปะธ ะฒั‹ ะดะพะฑะฐะฒะธั‚ะต ะฐะฝะฝะพั‚ะฐั†ะธัŽ ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะณะพ ั‚ะธะฟะฐ, ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะธ ั€ะตะดะฐะบั‚ะพั€ั‹ ะบะพะดะฐ ะฝะฐั‡ะฝัƒั‚ ะถะฐะปะพะฒะฐั‚ัŒัั (ะธ ะฑัƒะดัƒั‚ ะฟั€ะฐะฒั‹), ั‡ั‚ะพ ั„ัƒะฝะบั†ะธั ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ั‚ะธะฟ (ะฝะฐะฟั€ะธะผะตั€, dict), ะพั‚ะปะธั‡ะฝั‹ะน ะพั‚ ะพะฑัŠัะฒะปะตะฝะฝะพะณะพ (ะฝะฐะฟั€ะธะผะตั€, Pydantic-ะผะพะดะตะปัŒ). @@ -47,13 +47,13 @@ FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพั‚ ั‚ะธะฟ ะพั‚ะฒะตั‚ะฐ ะดะปั: `response_model` ะฟั€ะธะฝะธะผะฐะตั‚ ั‚ะพั‚ ะถะต ั‚ะธะฟ, ั‡ั‚ะพ ะฒั‹ ะฑั‹ ะพะฑัŠัะฒะธะปะธ ะดะปั ะฟะพะปั Pydantic-ะผะพะดะตะปะธ, ั‚ะพ ะตัั‚ัŒ ัั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะพะดะฝะฐ Pydantic-ะผะพะดะตะปัŒ, ะฐ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ, ะฝะฐะฟั€ะธะผะตั€, `list` Pydantic-ะผะพะดะตะปะตะน, ะบะฐะบ `List[Item]`. -FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `response_model` ะดะปั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะฒะฐะปะธะดะฐั†ะธะธ ะธ ั‚. ะฟ., ะฐ ั‚ะฐะบะถะต ะดะปั **ะบะพะฝะฒะตั€ั‚ะฐั†ะธะธ ะธ ั„ะธะปัŒั‚ั€ะฐั†ะธะธ ะฒั‹ั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…** ะบ ะพะฑัŠัะฒะปะตะฝะฝะพะผัƒ ั‚ะธะฟัƒ. +FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะพั‚ `response_model` ะดะปั ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธั, ะฒะฐะปะธะดะฐั†ะธะธ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะฟ., ะฐ ั‚ะฐะบะถะต ะดะปั **ะบะพะฝะฒะตั€ั‚ะฐั†ะธะธ ะธ ั„ะธะปัŒั‚ั€ะฐั†ะธะธ ะฒั‹ั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…** ะบ ะพะฑัŠัะฒะปะตะฝะฝะพะผัƒ ั‚ะธะฟัƒ. /// tip | ะกะพะฒะตั‚ -ะ•ัะปะธ ัƒ ะฒะฐั ะฒ ั€ะตะดะฐะบั‚ะพั€ะต ะบะพะดะฐ, mypy ะธ ั‚. ะฟ. ะฒะบะปัŽั‡ะตะฝั‹ ัั‚ั€ะพะณะธะต ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ ะบะฐะบ `Any`. +ะ•ัะปะธ ัƒ ะฒะฐั ะฒ ั€ะตะดะฐะบั‚ะพั€ะต ะบะพะดะฐ, mypy ะธ ั‚.ะฟ. ะฒะบะปัŽั‡ะตะฝั‹ ัั‚ั€ะพะณะธะต ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ ะบะฐะบ `Any`. -ะขะฐะบ ะฒั‹ ัะพะพะฑั‰ะธั‚ะต ั€ะตะดะฐะบั‚ะพั€ัƒ, ั‡ั‚ะพ ะฝะฐะผะตั€ะตะฝะฝะพ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‡ั‚ะพ ัƒะณะพะดะฝะพ. ะะพ FastAPI ะฒัั‘ ั€ะฐะฒะฝะพ ะฒั‹ะฟะพะปะฝะธั‚ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ะฒะฐะปะธะดะฐั†ะธัŽ, ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะธ ั‚.ะด. ั ะฟะพะผะพั‰ัŒัŽ `response_model`. +ะขะฐะบ ะฒั‹ ัะพะพะฑั‰ะธั‚ะต ั€ะตะดะฐะบั‚ะพั€ัƒ, ั‡ั‚ะพ ะฝะฐะผะตั€ะตะฝะฝะพ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‡ั‚ะพ ัƒะณะพะดะฝะพ. ะะพ FastAPI ะฒัั‘ ั€ะฐะฒะฝะพ ะฒั‹ะฟะพะปะฝะธั‚ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต, ะฒะฐะปะธะดะฐั†ะธัŽ, ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะด. ั ะฟะพะผะพั‰ัŒัŽ `response_model`. /// @@ -61,7 +61,7 @@ FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `response_model` ะดะปั ะดะพะบัƒะผะต ะ•ัะปะธ ะฒั‹ ะพะฑัŠัะฒะธั‚ะต ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ, ะธ `response_model`, ะฟั€ะธะพั€ะธั‚ะตั‚ ะฑัƒะดะตั‚ ัƒ `response_model`, ะธะผะตะฝะฝะพ ะตะณะพ ะธัะฟะพะปัŒะทัƒะตั‚ FastAPI. -ะขะฐะบ ะฒั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ ะบ ัะฒะพะธะผ ั„ัƒะฝะบั†ะธัะผ, ะดะฐะถะต ะตัะปะธ ั„ะฐะบั‚ะธั‡ะตัะบะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‚ะธะฟ, ะพั‚ะปะธั‡ะฝั‹ะน ะพั‚ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ, ั‡ั‚ะพะฑั‹ ะธะผะธ ะฟะพะปัŒะทะพะฒะฐะปะธััŒ ั€ะตะดะฐะบั‚ะพั€ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฒั€ะพะดะต mypy. ะ˜ ะฟั€ะธ ัั‚ะพะผ FastAPI ะฟั€ะพะดะพะปะถะธั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒ ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ะธ ั‚.ะด. ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ `response_model`. +ะขะฐะบ ะฒั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ ะบ ัะฒะพะธะผ ั„ัƒะฝะบั†ะธัะผ, ะดะฐะถะต ะตัะปะธ ั„ะฐะบั‚ะธั‡ะตัะบะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‚ะธะฟ, ะพั‚ะปะธั‡ะฝั‹ะน ะพั‚ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ, ั‡ั‚ะพะฑั‹ ะธะผะธ ะฟะพะปัŒะทะพะฒะฐะปะธััŒ ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฒั€ะพะดะต mypy. ะ˜ ะฟั€ะธ ัั‚ะพะผ FastAPI ะฟั€ะพะดะพะปะถะธั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒ ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ะธ ั‚.ะด. ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ `response_model`. ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ัƒะบะฐะทะฐั‚ัŒ `response_model=None`, ั‡ั‚ะพะฑั‹ ะพั‚ะบะปัŽั‡ะธั‚ัŒ ัะพะทะดะฐะฝะธะต ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ ะดะปั ะดะฐะฝะฝะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. ะญั‚ะพ ะผะพะถะตั‚ ะฟะพะฝะฐะดะพะฑะธั‚ัŒัั, ะตัะปะธ ะฒั‹ ะดะพะฑะฐะฒะปัะตั‚ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ ะดะปั ะฒะตั‰ะตะน, ะฝะต ัะฒะปััŽั‰ะธั…ัั ะฒะฐะปะธะดะฝั‹ะผะธ ะฟะพะปัะผะธ Pydantic. ะŸั€ะธะผะตั€ ะฒั‹ ัƒะฒะธะดะธั‚ะต ะฝะธะถะต. @@ -75,7 +75,7 @@ FastAPI ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `response_model` ะดะปั ะดะพะบัƒะผะต ะงั‚ะพะฑั‹ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `EmailStr`, ัะฝะฐั‡ะฐะปะฐ ัƒัั‚ะฐะฝะพะฒะธั‚ะต `email-validator`. -ะกะพะทะดะฐะนั‚ะต [ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะต ะพะบั€ัƒะถะตะฝะธะต](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒะธั€ัƒะนั‚ะต ะตะณะพ ะธ ะทะฐั‚ะตะผ ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะฟะฐะบะตั‚, ะฝะฐะฟั€ะธะผะตั€: +ะฃะฑะตะดะธั‚ะตััŒ, ั‡ั‚ะพ ะฒั‹ ัะพะทะดะฐะปะธ [ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะต ะพะบั€ัƒะถะตะฝะธะต](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒะธั€ะพะฒะฐะปะธ ะตะณะพ, ะฐ ะทะฐั‚ะตะผ ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะฟะฐะบะตั‚, ะฝะฐะฟั€ะธะผะตั€: ```console $ pip install email-validator @@ -105,7 +105,7 @@ $ pip install "pydantic[email]" /// -## ะ”ะพะฑะฐะฒะธั‚ัŒ ะผะพะดะตะปัŒ ะดะปั ะพั‚ะฒะตั‚ะฐ { #add-an-output-model } +## ะ”ะพะฑะฐะฒะธั‚ัŒ ะฒั‹ั…ะพะดะฝัƒัŽ ะผะพะดะตะปัŒ { #add-an-output-model } ะ’ะผะตัั‚ะพ ัั‚ะพะณะพ ะผั‹ ะผะพะถะตะผ ัะพะทะดะฐั‚ัŒ ะฒั…ะพะดะฝัƒัŽ ะผะพะดะตะปัŒ ั ะฟะฐั€ะพะปะตะผ ะฒ ะพั‚ะบั€ั‹ั‚ะพะผ ะฒะธะดะต ะธ ะฒั‹ั…ะพะดะฝัƒัŽ ะผะพะดะตะปัŒ ะฑะตะท ะฝะตะณะพ: @@ -123,7 +123,7 @@ $ pip install "pydantic[email]" ### `response_model` ะธะปะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ { #response-model-or-return-type } -ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต, ะฟะพัะบะพะปัŒะบัƒ ะดะฒะต ะผะพะดะตะปะธ ั€ะฐะทะปะธั‡ะฐัŽั‚ัั, ะตัะปะธ ะฑั‹ ะผั‹ ะฐะฝะฝะพั‚ะธั€ะพะฒะฐะปะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ ะบะฐะบ `UserOut`, ั€ะตะดะฐะบั‚ะพั€ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฟะพะถะฐะปะพะฒะฐะปะธััŒ ะฑั‹, ั‡ั‚ะพ ะผั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ะฝะตะฒะตั€ะฝั‹ะน ั‚ะธะฟ, ั‚ะฐะบ ะบะฐะบ ัั‚ะพ ั€ะฐะทะฝั‹ะต ะบะปะฐััั‹. +ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต, ะฟะพัะบะพะปัŒะบัƒ ะดะฒะต ะผะพะดะตะปะธ ั€ะฐะทะปะธั‡ะฐัŽั‚ัั, ะตัะปะธ ะฑั‹ ะผั‹ ะฐะฝะฝะพั‚ะธั€ะพะฒะฐะปะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ ะบะฐะบ `UserOut`, ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฟะพะถะฐะปะพะฒะฐะปะธััŒ ะฑั‹, ั‡ั‚ะพ ะผั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ะฝะตะฒะตั€ะฝั‹ะน ั‚ะธะฟ, ั‚ะฐะบ ะบะฐะบ ัั‚ะพ ั€ะฐะทะฝั‹ะต ะบะปะฐััั‹. ะŸะพัั‚ะพะผัƒ ะฒ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะดะพะปะถะฝั‹ ะพะฑัŠัะฒะธั‚ัŒ ั‚ะธะฟ ะพั‚ะฒะตั‚ะฐ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ะต `response_model`. @@ -135,33 +135,33 @@ $ pip install "pydantic[email]" ะœั‹ ั…ะพั‚ะธะผ, ั‡ั‚ะพะฑั‹ FastAPI ะฟั€ะพะดะพะปะถะฐะป **ั„ะธะปัŒั‚ั€ะพะฒะฐั‚ัŒ** ะดะฐะฝะฝั‹ะต ั ะฟะพะผะพั‰ัŒัŽ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ. ะขะฐะบ ั‡ั‚ะพ, ะดะฐะถะต ะตัะปะธ ั„ัƒะฝะบั†ะธั ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะฑะพะปัŒัˆะต ะดะฐะฝะฝั‹ั…, ะฒ ะพั‚ะฒะตั‚ ะฑัƒะดัƒั‚ ะฒะบะปัŽั‡ะตะฝั‹ ั‚ะพะปัŒะบะพ ะฟะพะปั, ะพะฑัŠัะฒะปะตะฝะฝั‹ะต ะฒ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ. -ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะตะผ ะฟั€ะธะผะตั€ะต, ะฟะพัะบะพะปัŒะบัƒ ะบะปะฐััั‹ ะฑั‹ะปะธ ั€ะฐะทะฝั‹ะผะธ, ะฝะฐะผ ะฟั€ะธัˆะปะพััŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `response_model`. ะะพ ัั‚ะพ ั‚ะฐะบะถะต ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะผั‹ ั‚ะตั€ัะตะผ ะฟะพะดะดะตั€ะถะบัƒ ะพั‚ ั€ะตะดะฐะบั‚ะพั€ะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะฟั€ะพะฒะตั€ััŽั‰ะธั… ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ. +ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะตะผ ะฟั€ะธะผะตั€ะต, ะฟะพัะบะพะปัŒะบัƒ ะบะปะฐััั‹ ะฑั‹ะปะธ ั€ะฐะทะฝั‹ะผะธ, ะฝะฐะผ ะฟั€ะธัˆะปะพััŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `response_model`. ะะพ ัั‚ะพ ั‚ะฐะบะถะต ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะผั‹ ั‚ะตั€ัะตะผ ะฟะพะดะดะตั€ะถะบัƒ ะพั‚ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะฟั€ะพะฒะตั€ััŽั‰ะธั… ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ. ะžะดะฝะฐะบะพ ะฒ ะฑะพะปัŒัˆะธะฝัั‚ะฒะต ั‚ะฐะบะธั… ัะปัƒั‡ะฐะตะฒ ะฝะฐะผ ะฝัƒะถะฝะพ ะปะธัˆัŒ **ะพั‚ั„ะธะปัŒั‚ั€ะพะฒะฐั‚ัŒ/ัƒะฑั€ะฐั‚ัŒ** ะฝะตะบะพั‚ะพั€ั‹ะต ะดะฐะฝะฝั‹ะต, ะบะฐะบ ะฒ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต. -ะ˜ ะฒ ัั‚ะธั… ัะปัƒั‡ะฐัั… ะผั‹ ะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะปะฐััั‹ ะธ ะฝะฐัะปะตะดะพะฒะฐะฝะธะต, ั‡ั‚ะพะฑั‹ ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั **ะฐะฝะฝะพั‚ะฐั†ะธัะผะธ ั‚ะธะฟะพะฒ** ั„ัƒะฝะบั†ะธะน ะดะปั ะปัƒั‡ัˆะตะน ะฟะพะดะดะตั€ะถะบะธ ะฒ ั€ะตะดะฐะบั‚ะพั€ะต ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะฐั… ะธ ะฟั€ะธ ัั‚ะพะผ ะฟะพะปัƒั‡ะธั‚ัŒ **ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…** ะพั‚ FastAPI. +ะ˜ ะฒ ัั‚ะธั… ัะปัƒั‡ะฐัั… ะผั‹ ะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะปะฐััั‹ ะธ ะฝะฐัะปะตะดะพะฒะฐะฝะธะต, ั‡ั‚ะพะฑั‹ ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั **ะฐะฝะฝะพั‚ะฐั†ะธัะผะธ ั‚ะธะฟะพะฒ** ั„ัƒะฝะบั†ะธะน ะดะปั ะปัƒั‡ัˆะตะน ะฟะพะดะดะตั€ะถะบะธ ะฒ ั€ะตะดะฐะบั‚ะพั€ะต ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะฐั… ะธ ะฟั€ะธ ัั‚ะพะผ ะฟะพะปัƒั‡ะธั‚ัŒ **ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…** ะพั‚ FastAPI. {* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} -ะขะฐะบ ะผั‹ ะฟะพะปัƒั‡ะฐะตะผ ะฟะพะดะดะตั€ะถะบัƒ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ (ั€ะตะดะฐะบั‚ะพั€ั‹, mypy) โ€” ะบะพะด ะบะพั€ั€ะตะบั‚ะตะฝ ั ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั ั‚ะธะฟะพะฒ โ€” ะธ ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ ะฟะพะปัƒั‡ะฐะตะผ ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… ะพั‚ FastAPI. +ะขะฐะบ ะผั‹ ะฟะพะปัƒั‡ะฐะตะผ ะฟะพะดะดะตั€ะถะบัƒ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ โ€” ั€ะตะดะฐะบั‚ะพั€ะพะฒ ะบะพะดะฐ ะธ mypy, ั‚ะฐะบ ะบะฐะบ ัั‚ะพั‚ ะบะพะด ะบะพั€ั€ะตะบั‚ะตะฝ ั ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั ั‚ะธะฟะพะฒ โ€” ะธ ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ ะฟะพะปัƒั‡ะฐะตะผ ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… ะพั‚ FastAPI. ะšะฐะบ ัั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚? ะ”ะฐะฒะฐะนั‚ะต ั€ะฐะทะฑะตั€ั‘ะผัั. ๐Ÿค“ ### ะะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ { #type-annotations-and-tooling } -ะกะฝะฐั‡ะฐะปะฐ ะฟะพัะผะพั‚ั€ะธะผ, ะบะฐะบ ัั‚ะพ ัƒะฒะธะดัั‚ ั€ะตะดะฐะบั‚ะพั€ั‹, mypy ะธ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹. +ะกะฝะฐั‡ะฐะปะฐ ะฟะพัะผะพั‚ั€ะธะผ, ะบะฐะบ ัั‚ะพ ัƒะฒะธะดัั‚ ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ, mypy ะธ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹. -`BaseUser` ัะพะดะตั€ะถะธั‚ ะฑะฐะทะพะฒั‹ะต ะฟะพะปั. ะ—ะฐั‚ะตะผ `UserIn` ะฝะฐัะปะตะดัƒะตั‚ัั ะพั‚ `BaseUser` ะธ ะดะพะฑะฐะฒะปัะตั‚ ะฟะพะปะต `password`, ั‚ะพ ะตัั‚ัŒ ะพะฝ ะฒะบะปัŽั‡ะฐะตั‚ ะฒัะต ะฟะพะปั ะพะฑะตะธั… ะผะพะดะตะปะตะน. +`BaseUser` ัะพะดะตั€ะถะธั‚ ะฑะฐะทะพะฒั‹ะต ะฟะพะปั. ะ—ะฐั‚ะตะผ `UserIn` ะฝะฐัะปะตะดัƒะตั‚ัั ะพั‚ `BaseUser` ะธ ะดะพะฑะฐะฒะปัะตั‚ ะฟะพะปะต `password`, ั‚ะพ ะตัั‚ัŒ ะพะฝ ะฑัƒะดะตั‚ ะฒะบะปัŽั‡ะฐั‚ัŒ ะฒัะต ะฟะพะปั ะพะฑะตะธั… ะผะพะดะตะปะตะน. ะœั‹ ะฐะฝะฝะพั‚ะธั€ัƒะตะผ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ั„ัƒะฝะบั†ะธะธ ะบะฐะบ `BaseUser`, ะฝะพ ั„ะฐะบั‚ะธั‡ะตัะบะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ัะบะทะตะผะฟะปัั€ `UserIn`. -ะ ะตะดะฐะบั‚ะพั€, mypy ะธ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฝะต ะฑัƒะดัƒั‚ ะฒะพะทั€ะฐะถะฐั‚ัŒ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ั ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั ั‚ะธะฟะพะฒ `UserIn` โ€” ะฟะพะดะบะปะฐัั `BaseUser`, ั‡ั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ัั‚ะพ *ะฒะฐะปะธะดะฝั‹ะน* ั‚ะธะฟ ะฒะตะทะดะต, ะณะดะต ะพะถะธะดะฐะตั‚ัั ั‡ั‚ะพ-ั‚ะพ, ัะฒะปััŽั‰ะตะตัั `BaseUser`. +ะ ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ, mypy ะธ ะดั€ัƒะณะธะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะฝะต ะฑัƒะดัƒั‚ ะฒะพะทั€ะฐะถะฐั‚ัŒ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ั ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั ั‚ะธะฟะพะฒ `UserIn` โ€” ะฟะพะดะบะปะฐัั `BaseUser`, ั‡ั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ัั‚ะพ *ะฒะฐะปะธะดะฝั‹ะน* ั‚ะธะฟ ะฒะตะทะดะต, ะณะดะต ะพะถะธะดะฐะตั‚ัั ั‡ั‚ะพ-ั‚ะพ, ัะฒะปััŽั‰ะตะตัั `BaseUser`. ### ะคะธะปัŒั‚ั€ะฐั†ะธั ะดะฐะฝะฝั‹ั… FastAPI { #fastapi-data-filtering } -ะขะตะฟะตั€ัŒ, ะดะปั FastAPI: ะพะฝ ัƒะฒะธะดะธั‚ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ะธ ัƒะฑะตะดะธั‚ัั, ั‡ั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต, ะฒะบะปัŽั‡ะฐะตั‚ **ั‚ะพะปัŒะบะพ** ะฟะพะปั, ะพะฑัŠัะฒะปะตะฝะฝั‹ะต ะฒ ัั‚ะพะผ ั‚ะธะฟะต. +ะขะตะฟะตั€ัŒ ะดะปั FastAPI: ะพะฝ ัƒะฒะธะดะธั‚ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ั‚ะธะฟ ะธ ัƒะฑะตะดะธั‚ัั, ั‡ั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต, ะฒะบะปัŽั‡ะฐะตั‚ **ั‚ะพะปัŒะบะพ** ะฟะพะปั, ะพะฑัŠัะฒะปะตะฝะฝั‹ะต ะฒ ัั‚ะพะผ ั‚ะธะฟะต. -FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั Pydantic, ั‡ั‚ะพะฑั‹ ะณะฐั€ะฐะฝั‚ะธั€ะพะฒะฐั‚ัŒ, ั‡ั‚ะพ ั‚ะต ะถะต ะฟั€ะฐะฒะธะปะฐ ะฝะฐัะปะตะดะพะฒะฐะฝะธั ะบะปะฐััะพะฒ ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ัั ะดะปั ั„ะธะปัŒั‚ั€ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ะดะฐะฝะฝั‹ั…, ะธะฝะฐั‡ะต ะฒั‹ ะผะพะณะปะธ ะฑั‹ ะฒะตั€ะฝัƒั‚ัŒ ะณะพั€ะฐะทะดะพ ะฑะพะปัŒัˆะต ะดะฐะฝะฝั‹ั…, ั‡ะตะผ ะพะถะธะดะฐะปะธ. +FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั Pydantic, ั‡ั‚ะพะฑั‹ ะณะฐั€ะฐะฝั‚ะธั€ะพะฒะฐั‚ัŒ, ั‡ั‚ะพ ั‚ะต ะถะต ะฟั€ะฐะฒะธะปะฐ ะฝะฐัะปะตะดะพะฒะฐะฝะธั ะบะปะฐััะพะฒ ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ัั ะดะปั ั„ะธะปัŒั‚ั€ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ะดะฐะฝะฝั‹ั…, ะธะฝะฐั‡ะต ะฒั‹ ะผะพะณะปะธ ะฑั‹ ะฒ ะธั‚ะพะณะต ะฒะตั€ะฝัƒั‚ัŒ ะฝะฐะผะฝะพะณะพ ะฑะพะปัŒัˆะต ะดะฐะฝะฝั‹ั…, ั‡ะตะผ ะพะถะธะดะฐะปะธ. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะฒั‹ ะฟะพะปัƒั‡ะฐะตั‚ะต ะปัƒั‡ัˆะตะต ะธะท ะพะฑะพะธั… ะผะธั€ะพะฒ: ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ ั **ะฟะพะดะดะตั€ะถะบะพะน ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ** ะธ **ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…**. @@ -171,17 +171,17 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั -ะ˜ ะพะฑะต ะผะพะดะตะปะธ ะธัะฟะพะปัŒะทัƒัŽั‚ัั ะฒ ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API: +ะ˜ ะพะฑะต ะผะพะดะตะปะธ ะฑัƒะดัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฒ ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API: ## ะ”ั€ัƒะณะธะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ั‚ะธะฟะพะฒ { #other-return-type-annotations } -ะ‘ั‹ะฒะฐัŽั‚ ัะปัƒั‡ะฐะธ, ะบะพะณะดะฐ ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‡ั‚ะพ-ั‚ะพ, ั‡ั‚ะพ ะฝะต ัะฒะปัะตั‚ัั ะฒะฐะปะธะดะฝั‹ะผ ะฟะพะปะตะผ Pydantic, ะธ ะฐะฝะฝะพั‚ะธั€ัƒะตั‚ะต ัั‚ะพ ะฒ ั„ัƒะฝะบั†ะธะธ ั‚ะพะปัŒะบะพ ั€ะฐะดะธ ะฟะพะดะดะตั€ะถะบะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ (ั€ะตะดะฐะบั‚ะพั€, mypy ะธ ั‚. ะด.). +ะ‘ั‹ะฒะฐัŽั‚ ัะปัƒั‡ะฐะธ, ะบะพะณะดะฐ ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ั‡ั‚ะพ-ั‚ะพ, ั‡ั‚ะพ ะฝะต ัะฒะปัะตั‚ัั ะฒะฐะปะธะดะฝั‹ะผ ะฟะพะปะตะผ Pydantic, ะธ ะฐะฝะฝะพั‚ะธั€ัƒะตั‚ะต ัั‚ะพ ะฒ ั„ัƒะฝะบั†ะธะธ ั‚ะพะปัŒะบะพ ั€ะฐะดะธ ะฟะพะดะดะตั€ะถะบะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ (ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ, mypy ะธ ั‚.ะด.). ### ะ’ะพะทะฒั€ะฐั‚ Response ะฝะฐะฟั€ัะผัƒัŽ { #return-a-response-directly } -ะกะฐะผั‹ะน ั€ะฐัะฟั€ะพัั‚ั€ะฐะฝั‘ะฝะฝั‹ะน ัะปัƒั‡ะฐะน โ€” [ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ Response ะฝะฐะฟั€ัะผัƒัŽ, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะดะฐะปะตะต ะฒ ั€ะฐะทะดะตะปะฐั… ะดะปั ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ั…](../advanced/response-directly.md){.internal-link target=_blank}. +ะกะฐะผั‹ะน ั€ะฐัะฟั€ะพัั‚ั€ะฐะฝั‘ะฝะฝั‹ะน ัะปัƒั‡ะฐะน โ€” [ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ Response ะฝะฐะฟั€ัะผัƒัŽ, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะดะฐะปะตะต ะฒ ั€ะฐะทะดะตะปะฐั… ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะดะปั ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ั…](../advanced/response-directly.md){.internal-link target=_blank}. {* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} @@ -195,7 +195,7 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั {* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} -ะญั‚ะพ ั‚ะพะถะต ัั€ะฐะฑะพั‚ะฐะตั‚, ั‚ะฐะบ ะบะฐะบ `RedirectResponse` โ€” ะฟะพะดะบะปะฐัั `Response`, ะธ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑั€ะฐะฑะพั‚ะฐะตั‚ ัั‚ะพั‚ ัะปัƒั‡ะฐะน. +ะญั‚ะพ ั‚ะพะถะต ัั€ะฐะฑะพั‚ะฐะตั‚, ั‚ะฐะบ ะบะฐะบ `RedirectResponse` โ€” ะฟะพะดะบะปะฐัั `Response`, ะธ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑั€ะฐะฑะพั‚ะฐะตั‚ ัั‚ะพั‚ ะฟั€ะพัั‚ะพะน ัะปัƒั‡ะฐะน. ### ะะตะบะพั€ั€ะตะบั‚ะฝั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ั‚ะธะฟะพะฒ { #invalid-return-type-annotations } @@ -209,15 +209,15 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั ### ะžั‚ะบะปัŽั‡ะธั‚ัŒ ะผะพะดะตะปัŒ ะพั‚ะฒะตั‚ะฐ { #disable-response-model } -ะŸั€ะพะดะพะปะถะฐั ะฟั€ะธะผะตั€ ะฒั‹ัˆะต, ะฒั‹ ะผะพะถะตั‚ะต ะฝะต ั…ะพั‚ะตั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ, ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะธ ั‚.ะด., ะฒั‹ะฟะพะปะฝัะตะผั‹ะต FastAPI. +ะŸั€ะพะดะพะปะถะฐั ะฟั€ะธะผะตั€ ะฒั‹ัˆะต, ะฒั‹ ะผะพะถะตั‚ะต ะฝะต ั…ะพั‚ะตั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต, ั„ะธะปัŒั‚ั€ะฐั†ะธัŽ ะธ ั‚.ะฟ., ะฒั‹ะฟะพะปะฝัะตะผั‹ะต FastAPI. -ะะพ ะฟั€ะธ ัั‚ะพะผ ะฒั‹ ะผะพะถะตั‚ะต ั…ะพั‚ะตั‚ัŒ ัะพั…ั€ะฐะฝะธั‚ัŒ ะฐะฝะฝะพั‚ะฐั†ะธัŽ ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะณะพ ั‚ะธะฟะฐ ะฒ ั„ัƒะฝะบั†ะธะธ, ั‡ั‚ะพะฑั‹ ะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฟะพะดะดะตั€ะถะบะพะน ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ (ั€ะตะดะฐะบั‚ะพั€ั‹, ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ ะฒั€ะพะดะต mypy). +ะะพ ะฟั€ะธ ัั‚ะพะผ ะฒั‹ ะผะพะถะตั‚ะต ั…ะพั‚ะตั‚ัŒ ัะพั…ั€ะฐะฝะธั‚ัŒ ะฐะฝะฝะพั‚ะฐั†ะธัŽ ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะณะพ ั‚ะธะฟะฐ ะฒ ั„ัƒะฝะบั†ะธะธ, ั‡ั‚ะพะฑั‹ ะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฟะพะดะดะตั€ะถะบะพะน ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ะฒั€ะพะดะต ั€ะตะดะฐะบั‚ะพั€ะพะฒ ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ (ะฝะฐะฟั€ะธะผะตั€, mypy). ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะพั‚ะบะปัŽั‡ะธั‚ัŒ ะณะตะฝะตั€ะฐั†ะธัŽ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ, ัƒัั‚ะฐะฝะพะฒะธะฒ `response_model=None`: {* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} -ะขะฐะบ FastAPI ะฟั€ะพะฟัƒัั‚ะธั‚ ะณะตะฝะตั€ะฐั†ะธัŽ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ, ะธ ะฒั‹ ัะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะปัŽะฑั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ั‚ะธะฟะพะฒ, ะฝะต ะฒะปะธัั ะฝะฐ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI. ๐Ÿค“ +ะขะฐะบ FastAPI ะฟั€ะพะฟัƒัั‚ะธั‚ ะณะตะฝะตั€ะฐั†ะธัŽ ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ, ะธ ะฒั‹ ัะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะปัŽะฑั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐะตะผั‹ั… ั‚ะธะฟะพะฒ, ะบะพั‚ะพั€ั‹ะต ะฒะฐะผ ะฝัƒะถะฝั‹, ะฑะตะท ะฒะปะธัะฝะธั ะฝะฐ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI. ๐Ÿค“ ## ะŸะฐั€ะฐะผะตั‚ั€ั‹ ะบะพะดะธั€ะพะฒะฐะฝะธั ะผะพะดะตะปะธ ะพั‚ะฒะตั‚ะฐ { #response-model-encoding-parameters } @@ -252,20 +252,6 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั -ะ’ Pydantic v1 ะผะตั‚ะพะด ะฝะฐะทั‹ะฒะฐะปัั `.dict()`, ะฒ Pydantic v2 ะพะฝ ะฑั‹ะป ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน (ะฝะพ ะฒัั‘ ะตั‰ั‘ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั) ะธ ะฟะตั€ะตะธะผะตะฝะพะฒะฐะฝ ะฒ `.model_dump()`. - -ะŸั€ะธะผะตั€ั‹ ะทะดะตััŒ ะธัะฟะพะปัŒะทัƒัŽั‚ `.dict()` ะดะปั ัะพะฒะผะตัั‚ะธะผะพัั‚ะธ ั Pydantic v1, ะฝะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต Pydantic v2, ะฟั€ะธะผะตะฝัะนั‚ะต `.model_dump()`. - -/// - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - -FastAPI ะธัะฟะพะปัŒะทัƒะตั‚ ะผะตั‚ะพะด `.dict()` ัƒ Pydantic-ะผะพะดะตะปะตะน ั ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `exclude_unset`, ั‡ั‚ะพะฑั‹ ะดะพะฑะธั‚ัŒัั ั‚ะฐะบะพะณะพ ะฟะพะฒะตะดะตะฝะธั. - -/// - -/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั - ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ: * `response_model_exclude_defaults=True` @@ -312,7 +298,7 @@ FastAPI ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ัƒะผะตะฝ (ะฝะฐ ัะฐะผะพะผ ะดะตะปะต, ัั‚ะพ Pydantic ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะปัŽะฑั‹ะผะธ, ะฝะต ั‚ะพะปัŒะบะพ `None`. -ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ัะฟะธัะพะบ (`[]`), ั‡ะธัะปะพ ั ะฟะปะฐะฒะฐัŽั‰ะตะน ั‚ะพั‡ะบะพะน `10.5` ะธ ั‚. ะด. +ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ัะฟะธัะพะบ (`[]`), ั‡ะธัะปะพ ั ะฟะปะฐะฒะฐัŽั‰ะตะน ั‚ะพั‡ะบะพะน `10.5` ะธ ั‚.ะด. /// @@ -346,7 +332,7 @@ FastAPI ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ัƒะผะตะฝ (ะฝะฐ ัะฐะผะพะผ ะดะตะปะต, ัั‚ะพ Pydantic #### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `list` ะฒะผะตัั‚ะพ `set` { #using-lists-instead-of-sets } -ะ•ัะปะธ ะฒั‹ ะทะฐะฑั‹ะปะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `set` ะธ ะฟั€ะธะผะตะฝะธะปะธ `list` ะธะปะธ `tuple`, FastAPI ะฒัั‘ ั€ะฐะฒะฝะพ ะฟั€ะตะพะฑั€ะฐะทัƒะตั‚ ัั‚ะพ ะฒ `set`, ะธ ะฒัั‘ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝะพ: +ะ•ัะปะธ ะฒั‹ ะทะฐะฑั‹ะปะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `set` ะธ ะฟั€ะธะผะตะฝะธะปะธ `list` ะธะปะธ `tuple` ะฒะผะตัั‚ะพ ะฝะตะณะพ, FastAPI ะฒัั‘ ั€ะฐะฒะฝะพ ะฟั€ะตะพะฑั€ะฐะทัƒะตั‚ ัั‚ะพ ะฒ `set`, ะธ ะฒัั‘ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝะพ: {* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md index 5891f0d12d..e4a97c8801 100644 --- a/docs/ru/docs/tutorial/schema-extra-example.md +++ b/docs/ru/docs/tutorial/schema-extra-example.md @@ -8,36 +8,14 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ `examples` ะดะปั ะผะพะดะตะปะธ Pydantic, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะดะพะฑะฐะฒะปะตะฝั‹ ะฒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝัƒัŽ JSON Schema. -//// tab | Pydantic v2 - {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -//// - -//// tab | Pydantic v1 - -{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *} - -//// - ะญั‚ะฐ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั ะฑัƒะดะตั‚ ะดะพะฑะฐะฒะปะตะฝะฐ ะบะฐะบ ะตัั‚ัŒ ะฒ ะฒั‹ั…ะพะดะฝัƒัŽ **JSON Schema** ัั‚ะพะน ะผะพะดะตะปะธ ะธ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API. -//// tab | Pydantic v2 - -ะ’ Pydantic ะฒะตั€ัะธะธ 2 ะฒั‹ ะฑัƒะดะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฐั‚ั€ะธะฑัƒั‚ `model_config`, ะบะพั‚ะพั€ั‹ะน ะฟั€ะธะฝะธะผะฐะตั‚ `dict`, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะฒ ะ”ะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Pydantic: ะšะพะฝั„ะธะณัƒั€ะฐั†ะธั. +ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฐั‚ั€ะธะฑัƒั‚ `model_config`, ะบะพั‚ะพั€ั‹ะน ะฟั€ะธะฝะธะผะฐะตั‚ `dict`, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะฒ ะ”ะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Pydantic: ะšะพะฝั„ะธะณัƒั€ะฐั†ะธั. ะ’ั‹ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ัŒ `"json_schema_extra"` ั `dict`, ัะพะดะตั€ะถะฐั‰ะธะผ ะปัŽะฑั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ั…ะพั‚ะธั‚ะต ะฒะธะดะตั‚ัŒ ะฒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน JSON Schema, ะฒะบะปัŽั‡ะฐั `examples`. -//// - -//// tab | Pydantic v1 - -ะ’ Pydantic ะฒะตั€ัะธะธ 1 ะฒั‹ ะฑัƒะดะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒะฝัƒั‚ั€ะตะฝะฝะธะน ะบะปะฐัั `Config` ะธ `schema_extra`, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะฒ ะ”ะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Pydantic: ะะฐัั‚ั€ะพะนะบะฐ ัั…ะตะผั‹. - -ะ’ั‹ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ัŒ `schema_extra` ัะพ `dict`, ัะพะดะตั€ะถะฐั‰ะธะผ ะปัŽะฑั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะดะฐะฝะฝั‹ะต, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ั…ะพั‚ะธั‚ะต ะฒะธะดะตั‚ัŒ ะฒ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน JSON Schema, ะฒะบะปัŽั‡ะฐั `examples`. - -//// - /// tip | ะŸะพะดัะบะฐะทะบะฐ ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะพั‚ ะถะต ะฟั€ะธั‘ะผ, ั‡ั‚ะพะฑั‹ ั€ะฐััˆะธั€ะธั‚ัŒ JSON Schema ะธ ะดะพะฑะฐะฒะธั‚ัŒ ัะฒะพัŽ ัะพะฑัั‚ะฒะตะฝะฝัƒัŽ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝัƒัŽ ะธะฝั„ะพั€ะผะฐั†ะธัŽ. @@ -124,7 +102,7 @@ OpenAPI 3.1.0 (ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฝะฐั‡ะธะฝะฐั ั FastAPI 0.99.0) ะดะพะฑ ะšะปัŽั‡ะธ `dict` ะธะดะตะฝั‚ะธั„ะธั†ะธั€ัƒัŽั‚ ะบะฐะถะดั‹ะน ะฟั€ะธะผะตั€, ะฐ ะบะฐะถะดะพะต ะทะฝะฐั‡ะตะฝะธะต โ€” ัั‚ะพ ะตั‰ั‘ ะพะดะธะฝ `dict`. -ะšะฐะถะดั‹ะน ะบะพะฝะบั€ะตั‚ะฝั‹ะน ะฟั€ะธะผะตั€โ€‘`dict` ะฒ `examples` ะผะพะถะตั‚ ัะพะดะตั€ะถะฐั‚ัŒ: +ะšะฐะถะดั‹ะน ะบะพะฝะบั€ะตั‚ะฝั‹ะน ะฟั€ะธะผะตั€ `dict` ะฒ `examples` ะผะพะถะตั‚ ัะพะดะตั€ะถะฐั‚ัŒ: * `summary`: ะšั€ะฐั‚ะบะพะต ะพะฟะธัะฐะฝะธะต ะฟั€ะธะผะตั€ะฐ. * `description`: ะŸะพะดั€ะพะฑะฝะพะต ะพะฟะธัะฐะฝะธะต, ะบะพั‚ะพั€ะพะต ะผะพะถะตั‚ ัะพะดะตั€ะถะฐั‚ัŒ ั‚ะตะบัั‚ ะฒ Markdown. @@ -135,7 +113,7 @@ OpenAPI 3.1.0 (ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฝะฐั‡ะธะฝะฐั ั FastAPI 0.99.0) ะดะพะฑ {* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} -### OpenAPI-ะฟั€ะธะผะตั€ั‹ ะฒ UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #openapi-examples-in-the-docs-ui } +### OpenAPI-ะฟั€ะธะผะตั€ั‹ ะฒ UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #openapi-examples-in-the-docs-ui } ะก `openapi_examples`, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะผ ะฒ `Body()`, ัั‚ั€ะฐะฝะธั†ะฐ `/docs` ะฑัƒะดะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: @@ -213,7 +191,7 @@ OpenAPI ั‚ะฐะบะถะต ะดะพะฑะฐะฒะธะปะฐ ะฟะพะปั `example` ะธ `examples` ะฒ ะดั€ัƒะณ ### Swagger UI ะธ ัะฟะตั†ะธั„ะธั‡ะฝั‹ะต ะดะปั OpenAPI `examples` { #swagger-ui-and-openapi-specific-examples } -ะ ะฐะฝัŒัˆะต, ะฟะพัะบะพะปัŒะบัƒ Swagger UI ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะป ะฝะตัะบะพะปัŒะบะพ ะฟั€ะธะผะตั€ะพะฒ JSON Schema (ะฟะพ ัะพัั‚ะพัะฝะธัŽ ะฝะฐ 2023-08-26), ัƒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน ะฝะต ะฑั‹ะปะพ ัะฟะพัะพะฑะฐ ะฟะพะบะฐะทะฐั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ะฟั€ะธะผะตั€ะพะฒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. +ะขะตะฟะตั€ัŒ, ะฟะพัะบะพะปัŒะบัƒ Swagger UI ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะป ะฝะตัะบะพะปัŒะบะพ ะฟั€ะธะผะตั€ะพะฒ JSON Schema (ะฟะพ ัะพัั‚ะพัะฝะธัŽ ะฝะฐ 2023-08-26), ัƒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน ะฝะต ะฑั‹ะปะพ ัะฟะพัะพะฑะฐ ะฟะพะบะฐะทะฐั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ะฟั€ะธะผะตั€ะพะฒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. ะงั‚ะพะฑั‹ ั€ะตัˆะธั‚ัŒ ัั‚ะพ, FastAPI `0.103.0` **ะดะพะฑะฐะฒะธะป ะฟะพะดะดะตั€ะถะบัƒ** ะพะฑัŠัะฒะปะตะฝะธั ั‚ะพะณะพ ะถะต ัั‚ะฐั€ะพะณะพ, **ัะฟะตั†ะธั„ะธั‡ะฝะพะณะพ ะดะปั OpenAPI**, ะฟะพะปั `examples` ั ะฝะพะฒั‹ะผ ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `openapi_examples`. ๐Ÿค“ From e0abd210f64110de77c09909245e9652a4fec78e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 20 Jan 2026 23:03:31 +0000 Subject: [PATCH 020/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 33926e3afc..f4572ffe8b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). * ๐ŸŒ Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). From b9b75ba5f1a51c2edcae3df4dffa2b0f1a2353d0 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Thu, 22 Jan 2026 10:07:05 +0300 Subject: [PATCH 021/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20LLM=20prompt=20?= =?UTF-8?q?for=20Russian=20translations=20(#14733)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some specific translations --- docs/ru/llm-prompt.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/ru/llm-prompt.md b/docs/ru/llm-prompt.md index 6a437bdd14..9131a5d3b4 100644 --- a/docs/ru/llm-prompt.md +++ b/docs/ru/llm-prompt.md @@ -90,5 +90,12 @@ For the following technical terms, use these specific translations to ensure con * serve (meaning providing access to something): ยซะพั‚ะดะฐะฒะฐั‚ัŒยป (or `ะฟั€ะตะดะพัั‚ะฐะฒะปัั‚ัŒ ะดะพัั‚ัƒะฟ ะบ`) * recap (noun): ั€ะตะทัŽะผะต * utility function: ะฒัะฟะพะผะพะณะฐั‚ะตะปัŒะฝะฐั ั„ัƒะฝะบั†ะธั +* fast to code: ะฟะพะทะฒะพะปัะตั‚ ะฑั‹ัั‚ั€ะพ ะฟะธัะฐั‚ัŒ ะบะพะด +* Tutorial - User Guide: ะฃั‡ะตะฑะฝะธะบ - ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั +* submodule: ะฟะพะดะผะพะดัƒะปัŒ +* subpackage: ะฟะพะดะฟะฐะบะตั‚ +* router: ั€ะพัƒั‚ะตั€ +* building, deploying, accessing (when describing features of FastAPI Cloud): ัะพะทะดะฐะฝะธe ะพะฑั€ะฐะทะฐ, ั€ะฐะทะฒะตั€ั‚ั‹ะฒะฐะฝะธะต ะธ ะดะพัั‚ัƒะฟ +* type checker tool: ะธะฝัั‚ั€ัƒะผะตะฝั‚ ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ Do not add whitespace in `ั‚.ะด.`, `ั‚.ะฟ.`. From 6e47171e9cb79a4616014cb9fce5b88912a820ee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 22 Jan 2026 07:07:28 +0000 Subject: [PATCH 022/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f4572ffe8b..62b611f8a9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). From 509afeb475e602bd11f2ffa165ccd0ed3d10a19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 22 Jan 2026 01:27:31 -0800 Subject: [PATCH 023/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-outdated)=20(#14690)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ๐ŸŒ Update translations for de (update-outdated) * Apply suggestions from code review --------- Co-authored-by: github-actions[bot] Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/de/docs/_llm-test.md | 2 +- docs/de/docs/tutorial/bigger-applications.md | 26 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index bc7ce363c7..0b95fe3a8d 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -189,7 +189,7 @@ Siehe Abschnitt `### Links` im allgemeinen Prompt in `scripts/translate.py`. //// -## HTML โ€žabbrโ€œ-Elemente { #html-abbr-elements } +## HTML-โ€žabbrโ€œ-Elemente { #html-abbr-elements } //// tab | Test diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index 963baf44d5..d478d77c27 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -56,19 +56,19 @@ from app.routers import items Die gleiche Dateistruktur mit Kommentaren: -``` +```bash . -โ”œโ”€โ”€ app # โ€žappโ€œ ist ein Python-Package -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # diese Datei macht โ€žappโ€œ zu einem โ€žPython-Packageโ€œ -โ”‚ย ย  โ”œโ”€โ”€ main.py # โ€žmainโ€œ-Modul, z. B. import app.main -โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # โ€ždependenciesโ€œ-Modul, z. B. import app.dependencies -โ”‚ย ย  โ””โ”€โ”€ routers # โ€žroutersโ€œ ist ein โ€žPython-Subpackageโ€œ -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # macht โ€žroutersโ€œ zu einem โ€žPython-Subpackageโ€œ -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # โ€žitemsโ€œ-Submodul, z. B. import app.routers.items -โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # โ€žusersโ€œ-Submodul, z. B. import app.routers.users -โ”‚ย ย  โ””โ”€โ”€ internal # โ€žinternalโ€œ ist ein โ€žPython-Subpackageโ€œ -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # macht โ€žinternalโ€œ zu einem โ€žPython-Subpackageโ€œ -โ”‚ย ย  โ””โ”€โ”€ admin.py # โ€žadminโ€œ-Submodul, z. B. import app.internal.admin +โ”œโ”€โ”€ app # "app" ist ein Python-Package +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # diese Datei macht "app" zu einem "Python-Package" +โ”‚ย ย  โ”œโ”€โ”€ main.py # "main"-Modul, z. B. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies"-Modul, z. B. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" ist ein "Python-Subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # macht "routers" zu einem "Python-Subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items"-Submodul, z. B. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users"-Submodul, z. B. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" ist ein "Python-Subpackage" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # macht "internal" zu einem "Python-Subpackage" +โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin"-Submodul, z. B. import app.internal.admin ``` ## `APIRouter` { #apirouter } @@ -479,7 +479,7 @@ $ fastapi dev app/main.py -und รถffnen Sie die Dokumentation unter http://127.0.0.1:8000/docs. +Und รถffnen Sie die Dokumentation unter http://127.0.0.1:8000/docs. Sie sehen die automatische API-Dokumentation, einschlieรŸlich der Pfade aller Submodule, mit den richtigen Pfaden (und Prรคfixen) und den richtigen Tags: From f1a39cab12c615ba50b21f32159e523baa560424 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 22 Jan 2026 09:27:58 +0000 Subject: [PATCH 024/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 62b611f8a9..1cd2b887f6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). From 74cc27fd5aa1e9376d30105fe014ab8b2b1319b1 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Thu, 22 Jan 2026 17:32:34 +0100 Subject: [PATCH 025/367] =?UTF-8?q?=F0=9F=94=A7=20Ensure=20that=20an=20edi?= =?UTF-8?q?t=20to=20`uv.lock`=20gets=20the=20`internal`=20label=20(#14759)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add uv.lock to files for labeling the PR with 'internal' --- .github/labeler.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index cdaefbf2d8..57c5e1120f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -31,6 +31,7 @@ internal: - .pre-commit-config.yaml - pdm_build.py - requirements*.txt + - uv.lock - docs/en/data/sponsors.yml - docs/en/overrides/main.html - all-globs-to-all-files: From 597b435ae7f0c4694f654bce6c7c27206aa690ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 22 Jan 2026 16:33:00 +0000 Subject: [PATCH 026/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1cd2b887f6..f1321b7809 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -36,6 +36,7 @@ hide: ### Internal +* ๐Ÿ”ง Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg). * ๐Ÿ”ง Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo). * โฌ† Bump actions/cache from 4 to 5. PR [#14511](https://github.com/fastapi/fastapi/pull/14511) by [@dependabot[bot]](https://github.com/apps/dependabot). From eaf07c5d849ce4564b8708b4965a232fd026f1fe Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sun, 25 Jan 2026 00:16:10 +0300 Subject: [PATCH 027/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update=20outdated,=20found=20by=20fixer=20tool)=20(?= =?UTF-8?q?#14738)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update outdated pages found by fixer tool * Re-translate with updated prompt (fixed translation for `you`) * Re-translate with `gtpt-5` model * Re-translate with new preferred translation for `burger` * Re-translate with new preferred translations for `app` and `command` --- docs/ko/docs/async.md | 370 ++++++++++++++------------ docs/ko/docs/fastapi-cli.md | 108 ++++---- docs/ko/docs/features.md | 176 ++++++------ docs/ko/docs/help-fastapi.md | 199 +++++++------- docs/ko/docs/history-design-future.md | 82 +++--- 5 files changed, 473 insertions(+), 462 deletions(-) diff --git a/docs/ko/docs/async.md b/docs/ko/docs/async.md index ec503d5406..36f1ca6bf1 100644 --- a/docs/ko/docs/async.md +++ b/docs/ko/docs/async.md @@ -1,18 +1,18 @@ -# ๋™์‹œ์„ฑ๊ณผ async / await +# ๋™์‹œ์„ฑ๊ณผ async / await { #concurrency-and-async-await } -*๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*์—์„œ์˜ `async def` ๋ฌธ๋ฒ•์— ๋Œ€ํ•œ ์„ธ๋ถ€์‚ฌํ•ญ๊ณผ ๋น„๋™๊ธฐ ์ฝ”๋“œ, ๋™์‹œ์„ฑ ๋ฐ ๋ณ‘๋ ฌ์„ฑ์— ๋Œ€ํ•œ ๋ฐฐ๊ฒฝ +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ์˜ `async def` ๋ฌธ๋ฒ•์— ๋Œ€ํ•œ ์„ธ๋ถ€์‚ฌํ•ญ๊ณผ ๋น„๋™๊ธฐ ์ฝ”๋“œ, ๋™์‹œ์„ฑ ๋ฐ ๋ณ‘๋ ฌ์„ฑ์— ๋Œ€ํ•œ ๋ฐฐ๊ฒฝ -## ๋ฐ”์˜์‹  ๊ฒฝ์šฐ +## ๋ฐ”์˜์‹ ๊ฐ€์š”? { #in-a-hurry } -์š”์•ฝ +TL;DR: -๋‹ค์Œ๊ณผ ๊ฐ™์ด `await`๋ฅผ ์‚ฌ์šฉํ•ด ํ˜ธ์ถœํ•˜๋Š” ์ œ3์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ: +๋‹ค์Œ๊ณผ ๊ฐ™์ด `await`๋ฅผ ์‚ฌ์šฉํ•ด ํ˜ธ์ถœํ•˜๋ผ๊ณ  ์•ˆ๋‚ดํ•˜๋Š” ์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ: ```Python results = await some_library() ``` -๋‹ค์Œ์ฒ˜๋Ÿผ *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๋ฅผ `async def`๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค: +๋‹ค์Œ์ฒ˜๋Ÿผ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋ฅผ `async def`๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค: ```Python hl_lines="2" @app.get('/') @@ -29,7 +29,7 @@ async def read_results(): --- -๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, API, ํŒŒ์ผ์‹œ์Šคํ…œ ๋“ฑ๊ณผ ์˜์‚ฌ์†Œํ†ตํ•˜๋Š” ์ œ3์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๊ฒƒ์ด `await`๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ(ํ˜„์žฌ ๊ฑฐ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ทธ๋Ÿฌํ•ฉ๋‹ˆ๋‹ค), *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๋ฅผ ์ผ๋ฐ˜์ ์ธ `def`๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค: +๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, API, ํŒŒ์ผ์‹œ์Šคํ…œ ๋“ฑ๊ณผ ์˜์‚ฌ์†Œํ†ตํ•˜๋Š” ์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๊ฒƒ์ด `await` ์‚ฌ์šฉ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ(ํ˜„์žฌ ๋Œ€๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ทธ๋Ÿฌํ•ฉ๋‹ˆ๋‹ค), *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋ฅผ ์ผ๋ฐ˜์ ์ธ `def`๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค: ```Python hl_lines="2" @app.get('/') @@ -40,23 +40,23 @@ def results(): --- -๋งŒ์•ฝ ๋‹น์‹ ์˜ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์ด (์–ด์งธ์„œ์ธ์ง€) ๋‹ค๋ฅธ ๋ฌด์—‡๊ณผ ์˜์‚ฌ์†Œํ†ตํ•˜๊ณ  ๊ทธ๊ฒƒ์ด ์‘๋‹ตํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด `async def`๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. +๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด (์–ด์งธ์„œ์ธ์ง€) ๋‹ค๋ฅธ ์–ด๋–ค ๊ฒƒ๊ณผ๋„ ํ†ต์‹ ํ•˜๊ณ  ๊ทธ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด, ๋‚ด๋ถ€์—์„œ `await`๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋”๋ผ๋„ `async def`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. --- -๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด, ๊ทธ๋ƒฅ `def`๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. +์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด, ์ผ๋ฐ˜์ ์ธ `def`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. --- -**์ฐธ๊ณ **: *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*์—์„œ ํ•„์š”ํ•œ๋งŒํผ `def`์™€ `async def`๋ฅผ ํ˜ผ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ€์žฅ ์•Œ๋งž์€ ๊ฒƒ์„ ์„ ํƒํ•ด์„œ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FastAPI๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ์•Œ๋งž์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +**์ฐธ๊ณ **: *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ ํ•„์š”ํ•œ ๋งŒํผ `def`์™€ `async def`๋ฅผ ํ˜ผ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๊ฐ€์žฅ ์•Œ๋งž์€ ์˜ต์…˜์„ ์„ ํƒํ•ด ์ •์˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. FastAPI๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -์–ด์ฐŒ๋˜์—ˆ๋“ , ์ƒ๊ธฐ ์–ด๋– ํ•œ ๊ฒฝ์šฐ๋ผ๋„, FastAPI๋Š” ์—ฌ์ „ํžˆ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ž‘๋™ํ•˜๊ณ  ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค. +์–ด์จŒ๋“  ์œ„์˜ ์–ด๋–ค ๊ฒฝ์šฐ์—์„œ๋„ FastAPI๋Š” ์—ฌ์ „ํžˆ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค. -๊ทธ๋Ÿฌ๋‚˜ ์ƒ๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•จ์œผ๋กœ์จ ์–ด๋А ์ •๋„์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ์œ„์˜ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด๋ฉด, ๋ช‡ ๊ฐ€์ง€ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ๊ธฐ์ˆ ์  ์„ธ๋ถ€์‚ฌํ•ญ +## ๊ธฐ์ˆ ์  ์„ธ๋ถ€์‚ฌํ•ญ { #technical-details } -์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์€ `async`์™€ `await` ๋ฌธ๋ฒ•๊ณผ ํ•จ๊ป˜ **โ€œ์ฝ”๋ฃจํ‹ดโ€**์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” **โ€œ๋น„๋™๊ธฐ ์ฝ”๋“œโ€**๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์€ **โ€œ์ฝ”๋ฃจํ‹ดโ€**์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” **โ€œ๋น„๋™๊ธฐ ์ฝ”๋“œโ€**๋ฅผ **`async` ๋ฐ `await`** ๋ฌธ๋ฒ•๊ณผ ํ•จ๊ป˜ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์„น์…˜๋“ค์—์„œ ํ•ด๋‹น ๋ฌธ์žฅ์„ ๋ถ€๋ถ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: @@ -64,251 +64,283 @@ def results(): * **`async`์™€ `await`** * **์ฝ”๋ฃจํ‹ด** -## ๋น„๋™๊ธฐ ์ฝ”๋“œ +## ๋น„๋™๊ธฐ ์ฝ”๋“œ { #asynchronous-code } -๋น„๋™๊ธฐ ์ฝ”๋“œ๋ž€ ์–ธ์–ด ๐Ÿ’ฌ ๊ฐ€ ์ฝ”๋“œ์˜ ์–ด๋А ํ•œ ๋ถ€๋ถ„์—์„œ, ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ๐Ÿค–์—๊ฒŒ *๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€*๊ฐ€ ์–ด๋”˜๊ฐ€์—์„œ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผํ•œ๋‹ค๊ณ  ๋งํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. *๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€*๊ฐ€ โ€œ๋А๋ฆฐ-ํŒŒ์ผ" ๐Ÿ“ ์ด๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค. +๋น„๋™๊ธฐ ์ฝ”๋“œ๋Š” ์–ธ์–ด ๐Ÿ’ฌ ๊ฐ€ ์ฝ”๋“œ์˜ ์–ด๋А ํ•œ ๋ถ€๋ถ„์—์„œ ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์—๊ฒŒ, ์–ด๋А ์‹œ์ ์—๋Š” ์–ด๋”˜๊ฐ€์—์„œ *๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€*๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๊ทธ *๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€*๋ฅผ "slow-file" ๐Ÿ“ ์ด๋ผ๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. -๋”ฐ๋ผ์„œ โ€œ๋А๋ฆฐ-ํŒŒ์ผโ€ ๐Ÿ“์ด ๋๋‚ ๋•Œ๊นŒ์ง€ ์ปดํ“จํ„ฐ๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋”ฐ๋ผ์„œ ๊ทธ ์‹œ๊ฐ„ ๋™์•ˆ ์ปดํ“จํ„ฐ๋Š” "slow-file" ๐Ÿ“ ์ด ๋๋‚˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•˜๋Ÿฌ ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -๊ทธ ๋‹ค์Œ ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์€ ๋‹ค์‹œ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐํšŒ๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋Œ์•„์˜ค๊ฑฐ๋‚˜, ํ˜น์€ ๋‹น์‹œ์— ์ˆ˜ํ–‰ํ•ด์•ผํ•˜๋Š” ์ž‘์—…๋“ค์ด ์™„๋ฃŒ๋  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ ๐Ÿค– ์€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋˜ ์ž‘์—… ์ค‘ ์–ด๋А ๊ฒƒ์ด ์ด๋ฏธ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€, ๊ทธ๊ฒƒ ๐Ÿค– ์ด ํ•ด์•ผํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉด์„œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. +๊ทธ ๋‹ค์Œ ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์€ ๋‹ค์‹œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐํšŒ๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋Œ์•„์˜ค๊ฑฐ๋‚˜, ํ˜น์€ ๊ทธ ์‹œ์ ์— ํ•ด์•ผ ํ•  ์ž‘์—…์„ ๋ชจ๋‘ ๋๋‚ผ ๋•Œ๋งˆ๋‹ค ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๋˜ ์ž‘์—… ์ค‘ ์ด๋ฏธ ๋๋‚œ ๊ฒƒ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ฉด์„œ, ํ•ด์•ผ ํ–ˆ๋˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. -๋‹ค์Œ์œผ๋กœ, ๊ทธ๊ฒƒ ๐Ÿค– ์€ ์™„๋ฃŒํ•  ์ฒซ๋ฒˆ์งธ ์ž‘์—…์— ์ฐฉ์ˆ˜ํ•˜๊ณ (์šฐ๋ฆฌ์˜ "๋А๋ฆฐ-ํŒŒ์ผ" ๐Ÿ“ ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ์‹œ๋‹ค) ๊ทธ์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•ด์•ผํ•˜๋Š” ์ž‘์—…์„ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค. +๋‹ค์Œ์œผ๋กœ, ์™„๋ฃŒ๋œ ์ฒซ ๋ฒˆ์งธ ์ž‘์—…(์šฐ๋ฆฌ์˜ "slow-file" ๐Ÿ“ ์ด๋ผ๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค)์„ ๊ฐ€์ ธ์™€์„œ, ๊ทธ์— ๋Œ€ํ•ด ํ•ด์•ผ ํ–ˆ๋˜ ์ž‘์—…์„ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค. -"๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ"์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋น„๊ต์  "๋А๋ฆฐ" (ํ”„๋กœ์„ธ์„œ์™€ RAM ๋ฉ”๋ชจ๋ฆฌ ์†๋„์— ๋น„ํ•ด) I/O ์ž‘์—…์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ์˜ ๊ฒƒ๋“ค์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค: +์ด "๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ"์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋กœ์„ธ์„œ์™€ RAM ๋ฉ”๋ชจ๋ฆฌ ์†๋„์— ๋น„ํ•ด ์ƒ๋Œ€์ ์œผ๋กœ "๋А๋ฆฐ" I/O ์ž‘์—…์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค: -* ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ -* ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ˆ˜์‹ ํ• , ๋‹น์‹ ์˜ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ๋ถ€ํ„ฐ ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ -* ์‹œ์Šคํ…œ์ด ์ฝ๊ณ  ํ”„๋กœ๊ทธ๋žจ์— ์ „๋‹ฌํ•  ๋””์Šคํฌ ๋‚ด์˜ ํŒŒ์ผ ๋‚ด์šฉ -* ๋‹น์‹ ์˜ ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์Šคํ…œ์— ์ „๋‹ฌํ•˜๋Š”, ๋””์Šคํฌ์— ์ž‘์„ฑ๋  ๋‚ด์šฉ +* ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ +* ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ์ด ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ +* ์‹œ์Šคํ…œ์ด ๋””์Šคํฌ์˜ ํŒŒ์ผ ๋‚ด์šฉ์„ ์ฝ์–ด์„œ ํ”„๋กœ๊ทธ๋žจ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ +* ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์Šคํ…œ์— ์ „๋‹ฌํ•œ ๋‚ด์šฉ์„ ๋””์Šคํฌ์— ์“ฐ๋Š” ๊ฒƒ * ์›๊ฒฉ API ์ž‘์—… -* ์™„๋ฃŒ๋  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—… -* ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ -* ๊ธฐํƒ€ +* ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋Š” ๊ฒƒ +* ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ +* ๊ธฐํƒ€ ๋“ฑ๋“ฑ -์ˆ˜ํ–‰ ์‹œ๊ฐ„์˜ ๋Œ€๋ถ€๋ถ„์ด I/O ์ž‘์—…์„ ๊ธฐ๋‹ค๋ฆฌ๋Š”๋ฐ์— ์†Œ์š”๋˜๊ธฐ ๋•Œ๋ฌธ์—, "I/O์— ๋ฌถ์ธ" ์ž‘์—…์ด๋ผ๊ณ  ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. +์‹คํ–‰ ์‹œ๊ฐ„์˜ ๋Œ€๋ถ€๋ถ„์ด I/O ์ž‘์—…์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐ ์†Œ๋น„๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฅผ "I/O bound" ์ž‘์—…์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. -์ด๊ฒƒ์€ "๋น„๋™๊ธฐ"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”๋ฐ ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ์ด ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ  ์ผ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก, ๋А๋ฆฐ ์ž‘์—…์— "๋™๊ธฐํ™”"๋˜์–ด ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์ž‘์—…์ด ์™„๋ฃŒ๋  ์ •ํ™•ํ•œ ์‹œ์ ๋งŒ์„ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ์ด ๋А๋ฆฐ ์ž‘์—…๊ณผ "๋™๊ธฐํ™”"๋˜์–ด, ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์€ ์ฑ„ ๊ทธ ์ž‘์—…์ด ๋๋‚˜๋Š” ์ •ํ™•ํ•œ ์‹œ์ ๋งŒ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์™€ ์ผ์„ ๊ณ„์†ํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— "๋น„๋™๊ธฐ"๋ผ๊ณ  ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. -์ด ๋Œ€์‹ ์—, "๋น„๋™๊ธฐ" ์‹œ์Šคํ…œ์—์„œ๋Š”, ์ž‘์—…์€ ์ผ๋‹จ ์™„๋ฃŒ๋˜๋ฉด, ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ์ด ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ์ผ์„ ์™„๋ฃŒํ•˜๊ณ  ์ดํ›„ ๋‹ค์‹œ ๋Œ์•„์™€์„œ ๊ทธ๊ฒƒ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ์ด๋ฅผ ์‚ฌ์šฉํ•ด ์ž‘์—…์„ ์ง€์†ํ•  ๋•Œ๊นŒ์ง€ ์ž ์‹œ (๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ) ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋Œ€์‹  "๋น„๋™๊ธฐ" ์‹œ์Šคํ…œ์—์„œ๋Š”, ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ์ด ํ•˜๋Ÿฌ ๊ฐ”๋˜ ์ผ์„ ๋งˆ์น  ๋•Œ๊นŒ์ง€ ์ž ์‹œ(๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ) ์ค„์—์„œ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€, ๋‹ค์‹œ ๋Œ์•„์™€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ์ด๋ฅผ ์‚ฌ์šฉํ•ด ์ž‘์—…์„ ๊ณ„์†ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -"๋™๊ธฐ"("๋น„๋™๊ธฐ"์˜ ๋ฐ˜๋Œ€)๋Š” ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ์ด ์ƒ์ดํ•œ ์ž‘์—…๋“ค๊ฐ„ ์ „ํ™˜์„ ํ•˜๊ธฐ ์ „์— ๊ทธ๊ฒƒ์ด ๋Œ€๊ธฐ๋ฅผ ๋™๋ฐ˜ํ•˜๊ฒŒ ๋ ์ง€๋ผ๋„ ๋ชจ๋“  ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— "์ˆœ์ฐจ"๋ผ๋Š” ์šฉ์–ด๋กœ๋„ ํ”ํžˆ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. +"๋™๊ธฐ"(โ€œ๋น„๋™๊ธฐโ€์˜ ๋ฐ˜๋Œ€)๋Š” ๋ณดํ†ต "์ˆœ์ฐจ"๋ผ๋Š” ์šฉ์–ด๋กœ๋„ ๋ถˆ๋ฆฌ๋Š”๋ฐ, ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ์ด ๋‹ค๋ฅธ ์ž‘์—…์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ๋‹จ๊ณ„๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ, ๊ทธ ๋‹จ๊ณ„๋“ค์— ๊ธฐ๋‹ค๋ฆผ์ด ํฌํ•จ๋˜์–ด ์žˆ๋”๋ผ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. -### ๋™์‹œ์„ฑ๊ณผ ๋ฒ„๊ฑฐ +### ๋™์‹œ์„ฑ๊ณผ ํ–„๋ฒ„๊ฑฐ { #concurrency-and-burgers } -์œ„์—์„œ ์„ค๋ช…ํ•œ **๋น„๋™๊ธฐ** ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ์ข…์ข… **"๋™์‹œ์„ฑ"**์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ **"๋ณ‘๋ ฌ์„ฑ"**๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. +์œ„์—์„œ ์„ค๋ช…ํ•œ **๋น„๋™๊ธฐ** ์ฝ”๋“œ์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ๋•Œ๋•Œ๋กœ **"๋™์‹œ์„ฑ"**์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. ์ด๋Š” **"๋ณ‘๋ ฌ์„ฑ"**๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. -**๋™์‹œ์„ฑ**๊ณผ **๋ณ‘๋ ฌ์„ฑ**์€ ๋ชจ๋‘ "๋™์‹œ์— ์ผ์–ด๋‚˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ผ๋“ค"๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +**๋™์‹œ์„ฑ**๊ณผ **๋ณ‘๋ ฌ์„ฑ**์€ ๋ชจ๋‘ "๋Œ€๋žต ๊ฐ™์€ ์‹œ๊ฐ„์— ์ผ์–ด๋‚˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ผ๋“ค"๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ *๋™์‹œ์„ฑ*๊ณผ *๋ณ‘๋ ฌ์„ฑ*์˜ ์„ธ๋ถ€์ ์ธ ๊ฐœ๋…์—๋Š” ๊ฝค ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. -์ฐจ์ด๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ์˜ ๋ฒ„๊ฑฐ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค: +์ฐจ์ด๋ฅผ ๋ณด๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ์˜ ํ–„๋ฒ„๊ฑฐ ์ด์•ผ๊ธฐ๋ฅผ ์ƒ์ƒํ•ด๋ณด์„ธ์š”: -### ๋™์‹œ ๋ฒ„๊ฑฐ +### ๋™์‹œ ํ–„๋ฒ„๊ฑฐ { #concurrent-burgers } -๋‹น์‹ ์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ํŒจ์ŠคํŠธํ‘ธ๋“œ ๐Ÿ” ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ”์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ์ ์› ๐Ÿ’ ์ด ๋‹น์‹  ์•ž์— ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์ฃผ๋ฌธ์„ ๋ฐ›์„ ๋™์•ˆ ์ค„์„ ์„œ์„œ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +์—ฌ๋Ÿฌ๋ถ„์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํŒจ์ŠคํŠธํ‘ธ๋“œ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ”๊ณ , ์ ์›์ด ์—ฌ๋Ÿฌ๋ถ„ ์•ž ์‚ฌ๋žŒ๋“ค์˜ ์ฃผ๋ฌธ์„ ๋ฐ›๋Š” ๋™์•ˆ ์ค„์„ ์„œ์„œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ๐Ÿ˜ -์ด์ œ ๋‹น์‹ ์˜ ์ˆœ์„œ๊ฐ€ ๋˜์–ด์„œ, ๋‹น์‹ ์€ ๋‹น์‹ ๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋ฅผ ์œ„ํ•œ ๋‘ ๊ฐœ์˜ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ์ฃผ๋ฌธํ•ฉ๋‹ˆ๋‹ค. + -๋‹น์‹ ์ด ๋ˆ์„ ๋ƒ…๋‹ˆ๋‹ค ๐Ÿ’ธ. +์ด์ œ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€๊ฐ€ ๋˜์–ด, ์—ฌ๋Ÿฌ๋ถ„๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๋ฅผ ์œ„ํ•ด ๋งค์šฐ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ํ–„๋ฒ„๊ฑฐ 2๊ฐœ๋ฅผ ์ฃผ๋ฌธํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ”๐Ÿ” -์ ์› ๐Ÿ’ ์€ ์ฃผ๋ฐฉ ๐Ÿ‘จโ€๐Ÿณ ์— ์š”๋ฆฌ๋ฅผ ํ•˜๋ผ๊ณ  ์ „๋‹ฌํ•˜๊ณ , ๋”ฐ๋ผ์„œ ๊ทธ๋“ค์€ ๋‹น์‹ ์˜ ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ์ค€๋น„ํ•ด์•ผํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ๋ฉ๋‹ˆ๋‹ค(๊ทธ๋“ค์ด ์ง€๊ธˆ์€ ๋‹น์‹  ์•ž ๊ณ ๊ฐ๋“ค์˜ ์ฃผ๋ฌธ์„ ์ค€๋น„ํ•˜๊ณ  ์žˆ์„์ง€๋ผ๋„ ๋ง์ž…๋‹ˆ๋‹ค). + -์ ์› ๐Ÿ’ ์€ ๋‹น์‹ ์˜ ์ˆœ์„œ๊ฐ€ ์ ํžŒ ๋ฒˆํ˜ธํ‘œ๋ฅผ ์ค๋‹ˆ๋‹ค. +์ ์›์€ ์ฃผ๋ฐฉ์˜ ์š”๋ฆฌ์‚ฌ์—๊ฒŒ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งํ•ด, (์ง€๊ธˆ์€ ์•ž์„  ์†๋‹˜๋“ค์˜ ์ฃผ๋ฌธ์„ ์ค€๋น„ํ•˜๊ณ  ์žˆ๋”๋ผ๋„) ์—ฌ๋Ÿฌ๋ถ„์˜ ํ–„๋ฒ„๊ฑฐ๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. -๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ, ๋‹น์‹ ์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ํ•จ๊ป˜ ํ…Œ์ด๋ธ”์„ ๊ณ ๋ฅด๊ณ , ์ž๋ฆฌ์— ์•‰์•„ ์˜ค๋žซ๋™์•ˆ (๋‹น์‹ ์ด ์ฃผ๋ฌธํ•œ ๋ฒ„๊ฑฐ๋Š” ๊ฝค๋‚˜ ๊ณ ๊ธ‰์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์— ์ค€๋น„ํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ์กฐ๊ธˆ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค โœจ๐Ÿ”โœจ) ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ•๋‹ˆ๋‹ค. + -์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ํ…Œ์ด๋ธ”์— ์•‰์•„์„œ ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ, ๊ทธ ์‚ฌ๋žŒ ๐Ÿ˜ ์ด ์–ผ๋งˆ๋‚˜ ๋ฉ‹์ง€๊ณ , ์‚ฌ๋ž‘์Šค๋Ÿฝ๊ณ , ๋˜‘๋˜‘ํ•œ์ง€ ๊ฐํƒ„ํ•˜๋ฉฐ ์‹œ๊ฐ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค โœจ๐Ÿ˜โœจ. +์—ฌ๋Ÿฌ๋ถ„์ด ๋ˆ์„ ๋ƒ…๋‹ˆ๋‹ค. ๐Ÿ’ธ -์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ๊ธฐ๋‹ค๋ฆฌ๋ฉด์„œ ์–˜๊ธฐํ•˜๋Š” ๋™์•ˆ, ๋•Œ๋•Œ๋กœ, ๋‹น์‹ ์€ ๋‹น์‹ ์˜ ์ฐจ๋ก€๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ๋ณด๊ธฐ ์œ„ํ•ด ์นด์šดํ„ฐ์˜ ๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. +์ ์›์€ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€ ๋ฒˆํ˜ธ๋ฅผ ์ค๋‹ˆ๋‹ค. -๊ทธ๋Ÿฌ๋‹ค ์–ด๋А ์ˆœ๊ฐ„, ๋‹น์‹ ์˜ ์ฐจ๋ก€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์นด์šดํ„ฐ์— ๊ฐ€์„œ, ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๋ฐ›๊ณ , ํ…Œ์ด๋ธ”๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. + -๋‹น์‹ ๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋Š” ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๋จน์œผ๋ฉฐ ์ข‹์€ ์‹œ๊ฐ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค โœจ. +๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํ•จ๊ป˜ ์ž๋ฆฌ๋ฅผ ๊ณ ๋ฅด๊ณ  ์•‰์•„ ์˜ค๋žซ๋™์•ˆ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ•๋‹ˆ๋‹ค(์—ฌ๋Ÿฌ๋ถ„์˜ ํ–„๋ฒ„๊ฑฐ๋Š” ๋งค์šฐ ๊ณ ๊ธ‰์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์— ์ค€๋น„ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค). + +์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํ…Œ์ด๋ธ”์— ์•‰์•„ ํ–„๋ฒ„๊ฑฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ, ๊ทธ ์‚ฌ๋žŒ์ด ์–ผ๋งˆ๋‚˜ ๋ฉ‹์ง€๊ณ  ๊ท€์—ฝ๊ณ  ๋˜‘๋˜‘ํ•œ์ง€ ๊ฐํƒ„ํ•˜๋ฉฐ ์‹œ๊ฐ„์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โœจ๐Ÿ˜โœจ. + + + +๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋Œ€ํ™”ํ•˜๋Š” ๋™์•ˆ, ๋•Œ๋•Œ๋กœ ์—ฌ๋Ÿฌ๋ถ„์€ ์นด์šดํ„ฐ์— ํ‘œ์‹œ๋˜๋Š” ๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€์ธ์ง€ ๋ด…๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฌ๋‹ค ์–ด๋А ์ˆœ๊ฐ„ ๋งˆ์นจ๋‚ด ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ์นด์šดํ„ฐ์— ๊ฐ€์„œ ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋ฐ›๊ณ , ํ…Œ์ด๋ธ”๋กœ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. + + + +์—ฌ๋Ÿฌ๋ถ„๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๋Š” ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋จน์œผ๋ฉฐ ์ข‹์€ ์‹œ๊ฐ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. โœจ + + + +/// info | ์ •๋ณด + +์•„๋ฆ„๋‹ค์šด ์ผ๋Ÿฌ์ŠคํŠธ: Ketrina Thompson. ๐ŸŽจ + +/// --- -๋‹น์‹ ์ด ์ด ์ด์•ผ๊ธฐ์—์„œ ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์ด๋ผ๊ณ  ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค. +์ด ์ด์•ผ๊ธฐ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์ด ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์ด๋ผ๊ณ  ์ƒ์ƒํ•ด๋ณด์„ธ์š”. -์ค„์„ ์„œ์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ, ๋‹น์‹ ์€ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๊ณ  ๐Ÿ˜ด ๋‹น์‹ ์˜ ์ฐจ๋ก€๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ, ์–ด๋– ํ•œ "์ƒ์‚ฐ์ ์ธ" ์ผ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ ์› ๐Ÿ’ ์ด (์Œ์‹์„ ์ค€๋น„ํ•˜์ง€๋Š” ์•Š๊ณ ) ์ฃผ๋ฌธ์„ ๋ฐ›๊ธฐ๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ค„์ด ๋นจ๋ฆฌ ์ค„์–ด๋“ค์–ด์„œ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. +์ค„์„ ์„œ ์žˆ๋Š” ๋™์•ˆ, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ทธ๋ƒฅ ์‰ฌ๊ณ  ๐Ÿ˜ด, ์ฐจ๋ก€๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ, ๊ทธ๋‹ค์ง€ "์ƒ์‚ฐ์ ์ธ" ์ผ์„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ ์›์€ ์ฃผ๋ฌธ๋งŒ ๋ฐ›์ง€(์Œ์‹์„ ์ค€๋น„ํ•˜์ง„ ์•Š๊ธฐ) ๋•Œ๋ฌธ์— ์ค„์ด ๋น ๋ฅด๊ฒŒ ์ค„์–ด๋“ค์–ด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. -๊ทธ๋‹ค์Œ, ๋‹น์‹ ์ด ์ฐจ๋ก€๊ฐ€ ์˜ค๋ฉด, ๋‹น์‹ ์€ ์‹ค์ œ๋กœ "์ƒ์‚ฐ์ ์ธ" ์ผ ๐Ÿค“ ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋ฉ”๋‰ด๋ฅผ ๋ณด๊ณ , ๋ฌด์—‡์„ ๋จน์„์ง€ ๊ฒฐ์ •ํ•˜๊ณ , ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์˜ ์„ ํƒ์„ ๋ฌป๊ณ , ๋ˆ์„ ๋‚ด๊ณ  ๐Ÿ’ธ , ๋งž๋Š” ์นด๋“œ๋ฅผ ๋ƒˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๋น„์šฉ์ด ์ œ๋Œ€๋กœ ์ง€๋ถˆ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ฃผ๋ฌธ์ด ์ œ๋Œ€๋กœ ๋“ค์–ด๊ฐ”๋Š”์ง€ ํ™•์ธ์„ ํ•˜๋Š” ์ž‘์—… ๋“ฑ๋“ฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. +๊ทธ ๋‹ค์Œ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€๊ฐ€ ๋˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์‹ค์ œ๋กœ "์ƒ์‚ฐ์ ์ธ" ์ผ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋‰ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋ฌด์—‡์„ ๋จน์„์ง€ ๊ฒฐ์ •ํ•˜๊ณ , ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์˜ ์„ ํƒ์„ ํ™•์ธํ•˜๊ณ , ๊ฒฐ์ œํ•˜๊ณ , ์˜ฌ๋ฐ”๋ฅธ ํ˜„๊ธˆ์ด๋‚˜ ์นด๋“œ๋ฅผ ๋ƒˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ •ํ™•ํžˆ ์ฒญ๊ตฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ฃผ๋ฌธ์— ์˜ฌ๋ฐ”๋ฅธ ํ•ญ๋ชฉ๋“ค์ด ๋“ค์–ด๊ฐ”๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋“ฑ๋“ฑ์„ ํ•ฉ๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ์ดํ›„์—๋Š”, ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ์•„์ง ๋ฐ›์ง€ ๋ชปํ–ˆ์Œ์—๋„, ๋ฒ„๊ฑฐ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ๐Ÿ•™ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์› ๐Ÿ’ ๊ณผ์˜ ์ž‘์—…์€ "์ผ์‹œ์ •์ง€" โธ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๊ทธ ๋‹ค์Œ์—๋Š”, ์•„์ง ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋ฐ›์ง€ ๋ชปํ–ˆ๋”๋ผ๋„, ํ–„๋ฒ„๊ฑฐ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ๐Ÿ•™ ํ•˜๋ฏ€๋กœ ์ ์›๊ณผ์˜ ์ž‘์—…์€ "์ผ์‹œ์ •์ง€" โธ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ๋ฒˆํ˜ธํ‘œ๋ฅผ ๋ฐ›๊ณ  ์นด์šดํ„ฐ์—์„œ ๋‚˜์™€ ํ…Œ์ด๋ธ”์— ์•‰์œผ๋ฉด, ๋‹น์‹ ์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ๊ทธ "์ž‘์—…" โฏ ๐Ÿค“ ์— ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ๐Ÿ”€ ์ง‘์ค‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋‹น์‹ ์€ ๋‹ค์‹œ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์—๊ฒŒ ์ž‘์—…์„ ๊ฑฐ๋Š” ๋งค์šฐ "์ƒ์‚ฐ์ ์ธ" ์ผ ๐Ÿค“ ์„ ํ•ฉ๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๋ฒˆํ˜ธ๋ฅผ ๋“ค๊ณ  ์นด์šดํ„ฐ์—์„œ ๋ฒ—์–ด๋‚˜ ํ…Œ์ด๋ธ”์— ์•‰์œผ๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์—๊ฒŒ ๊ด€์‹ฌ์„ ์ „ํ™˜ ๐Ÿ”€ ํ•˜๊ณ , ๊ทธ์— ๋Œ€ํ•œ "์ž‘์—…" โฏ ๐Ÿค“ ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์‹œ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์—๊ฒŒ ์ž‘์—…์„ ๊ฑฐ๋Š” ๋งค์šฐ "์ƒ์‚ฐ์ ์ธ" ์ผ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค ๐Ÿ˜. -์ ์› ๐Ÿ’ ์ด ์นด์šดํ„ฐ ํ™”๋ฉด์— ๋‹น์‹ ์˜ ๋ฒˆํ˜ธ๋ฅผ ํ‘œ์‹œํ•จ์œผ๋กœ์จ "๋ฒ„๊ฑฐ ๐Ÿ” ๊ฐ€ ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค"๋ผ๊ณ  ํ•ด๋„, ๋‹น์‹ ์€ ์ฆ‰์‹œ ๋›ฐ์ณ๋‚˜๊ฐ€์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋‹น์‹ ์˜ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ–๊ณ ์žˆ๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋“ค์˜ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ–๊ณ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์•„๋ฌด๋„ ๋‹น์‹ ์˜ ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ํ›”์ณ๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +๊ทธ ๋‹ค์Œ ์ ์› ๐Ÿ’ ์ด ์นด์šดํ„ฐ ํ™”๋ฉด์— ์—ฌ๋Ÿฌ๋ถ„ ๋ฒˆํ˜ธ๋ฅผ ๋„์›Œ "ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋งŒ๋“ค์—ˆ์–ด์š”"๋ผ๊ณ  ๋งํ•˜์ง€๋งŒ, ํ‘œ์‹œ๋œ ๋ฒˆํ˜ธ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ํ•ด์„œ ์ฆ‰์‹œ ๋ฏธ์นœ ๋“ฏ์ด ๋›ฐ์–ด๊ฐ€์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ์—ฌ๋Ÿฌ๋ถ„ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋“ค์˜ ๋ฒˆํ˜ธ๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋‹ˆ, ์•„๋ฌด๋„ ์—ฌ๋Ÿฌ๋ถ„ ํ–„๋ฒ„๊ฑฐ๋ฅผ ํ›”์ณ๊ฐˆ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. -๊ทธ๋ž˜์„œ ๋‹น์‹ ์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๊ฐ€ ์ด์•ผ๊ธฐ๋ฅผ ๋๋‚ผ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ํ›„ (ํ˜„์žฌ ์ž‘์—… ์™„๋ฃŒ โฏ / ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—… ์ฒ˜๋ฆฌ ๐Ÿค“ ), ์ •์ค‘ํ•˜๊ฒŒ ๋ฏธ์†Œ์ง“๊ณ  ๋ฒ„๊ฑฐ๋ฅผ ๊ฐ€์ง€๋Ÿฌ ๊ฐ€๊ฒ ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค โธ. +๊ทธ๋ž˜์„œ ์—ฌ๋Ÿฌ๋ถ„์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๊ฐ€ ์ด์•ผ๊ธฐ๋ฅผ ๋๋‚ผ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ๋‹ค์Œ(ํ˜„์žฌ ์ž‘์—… โฏ / ์ฒ˜๋ฆฌ ์ค‘์ธ ์ž‘์—… ๐Ÿค“ ์„ ๋๋‚ด๊ณ ), ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋ฏธ์†Œ ์ง€์œผ๋ฉฐ ํ–„๋ฒ„๊ฑฐ๋ฅผ ๊ฐ€์ง€๋Ÿฌ ๊ฐ€๊ฒ ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค โธ. -๊ทธ๋‹ค์Œ ๋‹น์‹ ์€ ์นด์šดํ„ฐ์— ๊ฐ€์„œ ๐Ÿ”€ , ์ดˆ๊ธฐ ์ž‘์—…์„ ์ด์ œ ์™„๋ฃŒํ•˜๊ณ  โฏ , ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๋ฐ›๊ณ , ๊ฐ์‚ฌํ•˜๋‹ค๊ณ  ๋งํ•˜๊ณ  ํ…Œ์ด๋ธ”๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด๋กœ์จ ์นด์šดํ„ฐ์™€์˜ ์ƒํ˜ธ์ž‘์šฉ ๋‹จ๊ณ„ / ์ž‘์—…์ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค โน. +๊ทธ ๋‹ค์Œ ์—ฌ๋Ÿฌ๋ถ„์€ ์นด์šดํ„ฐ๋กœ ๊ฐ€์„œ ๐Ÿ”€, ์ด์ œ ๋๋‚œ ์ดˆ๊ธฐ ์ž‘์—… โฏ ์œผ๋กœ ๋Œ์•„์™€ ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋ฐ›๊ณ , ๊ฐ์‚ฌ ์ธ์‚ฌ๋ฅผ ํ•˜๊ณ , ํ…Œ์ด๋ธ”๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด๋กœ์จ ์นด์šดํ„ฐ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ทธ ๋‹จ๊ณ„/์ž‘์—…์ด ๋๋‚ฉ๋‹ˆ๋‹ค โน. ๊ทธ๋ฆฌ๊ณ  ์ด๋Š” ์ƒˆ๋กœ์šด ์ž‘์—…์ธ "ํ–„๋ฒ„๊ฑฐ ๋จน๊ธฐ" ๐Ÿ”€ โฏ ๋ฅผ ๋งŒ๋“ค์ง€๋งŒ, ์ด์ „ ์ž‘์—…์ธ "ํ–„๋ฒ„๊ฑฐ ๋ฐ›๊ธฐ"๋Š” ๋๋‚ฌ์Šต๋‹ˆ๋‹ค โน. -์ด์ „ ์ž‘์—…์ธ "๋ฒ„๊ฑฐ ๋ฐ›๊ธฐ"๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด โน "๋ฒ„๊ฑฐ ๋จน๊ธฐ"๋ผ๋Š” ์ƒˆ๋กœ์šด ์ž‘์—…์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค ๐Ÿ”€ โฏ. +### ๋ณ‘๋ ฌ ํ–„๋ฒ„๊ฑฐ { #parallel-burgers } -### ๋ณ‘๋ ฌ ๋ฒ„๊ฑฐ +์ด์ œ ์ด๊ฒƒ์ด "๋™์‹œ ํ–„๋ฒ„๊ฑฐ"๊ฐ€ ์•„๋‹ˆ๋ผ "๋ณ‘๋ ฌ ํ–„๋ฒ„๊ฑฐ"๋ผ๊ณ  ์ƒ์ƒํ•ด๋ด…์‹œ๋‹ค. -์ด์ œ "๋™์‹œ ๋ฒ„๊ฑฐ"๊ฐ€ ์•„๋‹Œ "๋ณ‘๋ ฌ ๋ฒ„๊ฑฐ"๋ฅผ ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค. +์—ฌ๋Ÿฌ๋ถ„์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํ•จ๊ป˜ ๋ณ‘๋ ฌ ํŒจ์ŠคํŠธํ‘ธ๋“œ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ‘๋‹ˆ๋‹ค. -๋‹น์‹ ์€ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ์™€ ํ•จ๊ป˜ ๋ณ‘๋ ฌ ํŒจ์ŠคํŠธํ‘ธ๋“œ ๐Ÿ” ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ”์Šต๋‹ˆ๋‹ค. +์—ฌ๋Ÿฌ๋ถ„์€ ์—ฌ๋Ÿฌ ๋ช…(์˜ˆ: 8๋ช…)์˜ ์ ์›์ด ๋™์‹œ์— ์š”๋ฆฌ์‚ฌ์ด๊ธฐ๋„ ํ•˜์—ฌ ์—ฌ๋Ÿฌ๋ถ„ ์•ž ์‚ฌ๋žŒ๋“ค์˜ ์ฃผ๋ฌธ์„ ๋ฐ›๋Š” ๋™์•ˆ ์ค„์„ ์„œ ์žˆ์Šต๋‹ˆ๋‹ค. -๋‹น์‹ ์€ ์—ฌ๋Ÿฌ๋ช…(8๋ช…์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค)์˜ ์ ์›์ด ๋‹น์‹  ์•ž ์‚ฌ๋žŒ๋“ค์˜ ์ฃผ๋ฌธ์„ ๋ฐ›์œผ๋ฉฐ ๋™์‹œ์— ์š”๋ฆฌ ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ๋„ ํ•˜๋Š” ๋™์•ˆ ์ค„์„ ์„œ์„œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. +์—ฌ๋Ÿฌ๋ถ„ ์•ž์˜ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์€, 8๋ช…์˜ ์ ์› ๊ฐ๊ฐ์ด ๋‹ค์Œ ์ฃผ๋ฌธ์„ ๋ฐ›๊ธฐ ์ „์— ๋ฐ”๋กœ ํ–„๋ฒ„๊ฑฐ๋ฅผ ์ค€๋น„ํ•˜๋Ÿฌ ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์—, ์นด์šดํ„ฐ๋ฅผ ๋– ๋‚˜์ง€ ์•Š๊ณ  ํ–„๋ฒ„๊ฑฐ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. -๋‹น์‹  ์•ž ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ด ๋ฒ„๊ฑฐ๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ์นด์šดํ„ฐ์—์„œ ๋– ๋‚˜์ง€ ์•Š๊ณ  ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค ๐Ÿ•™ . ์™œ๋ƒํ•˜๋ฉด 8๋ช…์˜ ์ง์›๋“ค์ด ๋‹ค์Œ ์ฃผ๋ฌธ์„ ๋ฐ›๊ธฐ ์ „์— ๋ฒ„๊ฑฐ๋ฅผ ์ค€๋น„ํ•˜๋Ÿฌ ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + -๋งˆ์นจ๋‚ด ๋‹น์‹ ์˜ ์ฐจ๋ก€๊ฐ€ ์™”๊ณ , ๋‹น์‹ ์€ ๋‹น์‹ ๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋ฅผ ์œ„ํ•œ ๋‘ ๊ฐœ์˜ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ์ฃผ๋ฌธํ•ฉ๋‹ˆ๋‹ค. +๋งˆ์นจ๋‚ด ์—ฌ๋Ÿฌ๋ถ„ ์ฐจ๋ก€๊ฐ€ ๋˜์–ด, ์—ฌ๋Ÿฌ๋ถ„๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๋ฅผ ์œ„ํ•ด ๋งค์šฐ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ํ–„๋ฒ„๊ฑฐ 2๊ฐœ๋ฅผ ์ฃผ๋ฌธํ•ฉ๋‹ˆ๋‹ค. -๋‹น์‹ ์ด ๋น„์šฉ์„ ์ง€๋ถˆํ•ฉ๋‹ˆ๋‹ค ๐Ÿ’ธ . +์—ฌ๋Ÿฌ๋ถ„์ด ๋ˆ์„ ๋ƒ…๋‹ˆ๋‹ค ๐Ÿ’ธ. -์ ์›์ด ์ฃผ๋ฐฉ์— ๊ฐ‘๋‹ˆ๋‹ค ๐Ÿ‘จโ€๐Ÿณ . + -๋‹น์‹ ์€ ๋ฒˆํ˜ธํ‘œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ˆ„๊ตฌ๋„ ๋‹น์‹ ์˜ ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๋Œ€์‹  ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์—†๋„๋ก ์นด์šดํ„ฐ์— ์„œ์„œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค ๐Ÿ•™ . +์ ์›์€ ์ฃผ๋ฐฉ์œผ๋กœ ๊ฐ‘๋‹ˆ๋‹ค. -๋‹น์‹ ๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ƒˆ์น˜๊ธฐํ•ด์„œ ๋ฒ„๊ฑฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋А๋ผ ๋ฐ”์˜๊ธฐ ๋•Œ๋ฌธ์— ๐Ÿ•™ , ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์—๊ฒŒ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ๐Ÿ˜ž . +์—ฌ๋Ÿฌ๋ถ„์€ ๋ฒˆํ˜ธํ‘œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ, ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์—ฌ๋Ÿฌ๋ถ„๋ณด๋‹ค ๋จผ์ € ํ–„๋ฒ„๊ฑฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€์ง€ ๋ชปํ•˜๋„๋ก ์นด์šดํ„ฐ ์•ž์— ์„œ์„œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค ๐Ÿ•™. -์ด๊ฒƒ์€ "๋™๊ธฐ" ์ž‘์—…์ด๊ณ , ๋‹น์‹ ์€ ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ์™€ "๋™๊ธฐํ™”" ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๐Ÿ•™ , ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ๊ฐ€ ๋ฒ„๊ฑฐ ๐Ÿ” ์ค€๋น„๋ฅผ ์™„๋ฃŒํ•œ ํ›„ ๋‹น์‹ ์—๊ฒŒ ์ฃผ๊ฑฐ๋‚˜, ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ทธ๊ฒƒ์„ ๊ฐ€์ ธ๊ฐ€๋Š” ๊ทธ ์ˆœ๊ฐ„์— ๊ทธ ๊ณณ์— ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. + -์นด์šดํ„ฐ ์•ž์—์„œ ์˜ค๋žซ๋™์•ˆ ๊ธฐ๋‹ค๋ฆฐ ํ›„์— ๐Ÿ•™ , ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ๊ฐ€ ๋‹น์‹ ์˜ ๋ฒ„๊ฑฐ ๐Ÿ” ๋ฅผ ๊ฐ€์ง€๊ณ  ๋Œ์•„์˜ต๋‹ˆ๋‹ค. +์—ฌ๋Ÿฌ๋ถ„๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๋Š” ํ–„๋ฒ„๊ฑฐ๊ฐ€ ๋‚˜์˜ค๋ฉด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋ผ์–ด๋“ค์–ด ๊ฐ€์ ธ๊ฐ€์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋А๋ผ ๋ฐ”์˜๊ธฐ ๋•Œ๋ฌธ์—, ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์—๊ฒŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ž -๋‹น์‹ ์€ ๋ฒ„๊ฑฐ๋ฅผ ๋ฐ›๊ณ  ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํ•จ๊ป˜ ํ…Œ์ด๋ธ”๋กœ ๋Œ์•„์˜ต๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ "๋™๊ธฐ" ์ž‘์—…์ด๋ฉฐ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ์™€ "๋™๊ธฐํ™”"๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ๊ฐ€ ํ–„๋ฒ„๊ฑฐ๋ฅผ ์™„์„ฑํ•ด ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ์ฃผ๋Š” ์ •ํ™•ํ•œ ์ˆœ๊ฐ„์— ๊ทธ ์ž๋ฆฌ์— ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ธฐ๋‹ค๋ ค์•ผ ๐Ÿ•™ ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๊ฐ€์ ธ๊ฐˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -๋‹จ์ง€ ๋จน๊ธฐ๋งŒ ํ•˜๋‹ค๊ฐ€, ๋‹ค ๋จน์—ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ” โน. + -์นด์šดํ„ฐ ์•ž์—์„œ ๊ธฐ๋‹ค๋ฆฌ๋ฉด์„œ ๐Ÿ•™ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์„ ํ—ˆ๋น„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€ํ™”๋ฅผ ํ•˜๊ฑฐ๋‚˜ ์ž‘์—…์„ ๊ฑธ ์‹œ๊ฐ„์ด ๊ฑฐ์˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜ž . +๊ทธ๋Ÿฌ๋‹ค ์ ์›/์š”๋ฆฌ์‚ฌ ๐Ÿ‘จโ€๐Ÿณ ๊ฐ€ ์นด์šดํ„ฐ ์•ž์—์„œ ์˜ค๋žซ๋™์•ˆ ๊ธฐ๋‹ค๋ฆฐ ๐Ÿ•™ ๋์— ๋งˆ์นจ๋‚ด ํ–„๋ฒ„๊ฑฐ๋ฅผ ๊ฐ€์ง€๊ณ  ๋Œ์•„์˜ต๋‹ˆ๋‹ค. ---- + + +์—ฌ๋Ÿฌ๋ถ„์€ ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋ฐ›์•„ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€ ํ…Œ์ด๋ธ”๋กœ ๊ฐ‘๋‹ˆ๋‹ค. + +๊ทธ๋ƒฅ ๋จน๊ณ , ๋์ž…๋‹ˆ๋‹ค. โน + + + +๋Œ€๋ถ€๋ถ„์˜ ์‹œ๊ฐ„์„ ์นด์šดํ„ฐ ์•ž์—์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐ ๐Ÿ•™ ์ผ๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€ํ™”ํ•˜๊ฑฐ๋‚˜ ์ž‘์—…์„ ๊ฑธ ์‹œ๊ฐ„์€ ๋งŽ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ž -์ด ๋ณ‘๋ ฌ ๋ฒ„๊ฑฐ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ, ๋‹น์‹ ์€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๐Ÿ•™ , ์˜ค๋žœ ์‹œ๊ฐ„๋™์•ˆ "์นด์šดํ„ฐ์—์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š”" ๐Ÿ•™ ๋ฐ์— ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ด๋Š” โฏ ๋‘ ๊ฐœ์˜ ํ”„๋กœ์„ธ์„œ(๋‹น์‹ ๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€๐Ÿ˜)๋ฅผ ๊ฐ€์ง„ ์ปดํ“จํ„ฐ / ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์ž…๋‹ˆ๋‹ค. +/// info | ์ •๋ณด -ํŒจ์ŠคํŠธํ‘ธ๋“œ์ ์—๋Š” 8๊ฐœ์˜ ํ”„๋กœ์„ธ์„œ(์ ์›/์š”๋ฆฌ์‚ฌ) ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์‹œ ๋ฒ„๊ฑฐ๋Š” ๋‹จ ๋‘ ๊ฐœ(ํ•œ ๋ช…์˜ ์ง์›๊ณผ ํ•œ ๋ช…์˜ ์š”๋ฆฌ์‚ฌ) ๐Ÿ’ ๐Ÿ‘จโ€๐Ÿณ ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. +์•„๋ฆ„๋‹ค์šด ์ผ๋Ÿฌ์ŠคํŠธ: Ketrina Thompson. ๐ŸŽจ -ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ, ๋ณ‘๋ ฌ ๋ฒ„๊ฑฐ ์˜ˆ์‹œ๊ฐ€ ์ตœ์„ ์€ ์•„๋‹™๋‹ˆ๋‹ค ๐Ÿ˜ž . +/// --- -์ด ์˜ˆ์‹œ๋Š” ๋ฒ„๊ฑฐ๐Ÿ” ์ด์•ผ๊ธฐ์™€ ๊ฒฐ์ด ๊ฐ™์Šต๋‹ˆ๋‹ค. +์ด ๋ณ‘๋ ฌ ํ–„๋ฒ„๊ฑฐ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ, ์—ฌ๋Ÿฌ๋ถ„์€ ๋‘ ๊ฐœ์˜ ํ”„๋กœ์„ธ์„œ(์—ฌ๋Ÿฌ๋ถ„๊ณผ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€)๋ฅผ ๊ฐ€์ง„ ์ปดํ“จํ„ฐ/ํ”„๋กœ๊ทธ๋žจ ๐Ÿค– ์ด๋ฉฐ, ๋‘˜ ๋‹ค ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๐Ÿ•™ ์˜ค๋žซ๋™์•ˆ "์นด์šดํ„ฐ์—์„œ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ" ๐Ÿ•™ ์— ์ฃผ์˜๋ฅผ โฏ ๊ธฐ์šธ์ž…๋‹ˆ๋‹ค. + +ํŒจ์ŠคํŠธํ‘ธ๋“œ์ ์—๋Š” 8๊ฐœ์˜ ํ”„๋กœ์„ธ์„œ(์ ์›/์š”๋ฆฌ์‚ฌ)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์‹œ ํ–„๋ฒ„๊ฑฐ ๊ฐ€๊ฒŒ๋Š” 2๊ฐœ(์ ์› 1๋ช…, ์š”๋ฆฌ์‚ฌ 1๋ช…)๋งŒ ์žˆ์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๋” "ํ˜„์‹ค์ ์ธ" ์˜ˆ์‹œ๋กœ, ์€ํ–‰์„ ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค. +ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์ตœ์ข… ๊ฒฝํ—˜์€ ๊ทธ๋‹ค์ง€ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ž -์ตœ๊ทผ๊นŒ์ง€, ๋Œ€๋‹ค์ˆ˜์˜ ์€ํ–‰์—๋Š” ๋‹ค์ˆ˜์˜ ์€ํ–‰์›๋“ค ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ๊ณผ ๊ธด ์ค„ ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +--- -๋ชจ๋“  ์€ํ–‰์›๋“ค์€ ํ•œ ๋ช… ํ•œ ๋ช…์˜ ๊ณ ๊ฐ๋“ค์„ ์ฐจ๋ก€๋กœ ์ƒ๋Œ€ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘จโ€๐Ÿ’ผโฏ . +์ด๊ฒƒ์ด ํ–„๋ฒ„๊ฑฐ์˜ ๋ณ‘๋ ฌ ๋ฒ„์ „์— ํ•ด๋‹นํ•˜๋Š” ์ด์•ผ๊ธฐ์ž…๋‹ˆ๋‹ค. ๐Ÿ” -๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ ์€ ์˜ค๋žซ๋™์•ˆ ์ค„์—์„œ ๊ธฐ๋‹ค๋ ค์•ผํ•˜๊ณ  ๐Ÿ•™ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‹น์‹ ์˜ ์ฐจ๋ก€๋ฅผ ์žƒ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +์ข€ ๋” "ํ˜„์‹ค์ ์ธ" ์˜ˆ์‹œ๋กœ, ์€ํ–‰์„ ์ƒ์ƒํ•ด๋ณด์„ธ์š”. -์•„๋งˆ ๋‹น์‹ ์€ ์€ํ–‰ ๐Ÿฆ ์‹ฌ๋ถ€๋ฆ„์— ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋ฅผ ๋ฐ๋ ค๊ฐ€๊ณ  ์‹ถ์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +์ตœ๊ทผ๊นŒ์ง€ ๋Œ€๋ถ€๋ถ„์˜ ์€ํ–‰์—๋Š” ์—ฌ๋Ÿฌ ์€ํ–‰์› ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ๊ณผ ๊ธด ์ค„ ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. -### ๋ฒ„๊ฑฐ ์˜ˆ์‹œ์˜ ๊ฒฐ๋ก  +๋ชจ๋“  ์€ํ–‰์›์ด ํ•œ ๊ณ ๊ฐ์”ฉ ์ˆœ์„œ๋Œ€๋กœ ๋ชจ๋“  ์ผ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘จโ€๐Ÿ’ผโฏ. -"์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€์˜ ํŒจ์ŠคํŠธํ‘ธ๋“œ์  ๋ฒ„๊ฑฐ" ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ, ์˜ค๋žœ ๊ธฐ๋‹ค๋ฆผ ๐Ÿ•™ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ ์‹œ์Šคํ…œ โธ๐Ÿ”€โฏ ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. +๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„์€ ์˜ค๋žซ๋™์•ˆ ์ค„์—์„œ ๊ธฐ๋‹ค๋ ค์•ผ ๐Ÿ•™ ํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ฐจ๋ก€๋ฅผ ์žƒ์Šต๋‹ˆ๋‹ค. -๋Œ€๋‹ค์ˆ˜์˜ ์›น ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ๊ฐ€ ๊ทธ๋Ÿฌํ•ฉ๋‹ˆ๋‹ค. +์•„๋งˆ ์€ํ–‰ ๐Ÿฆ ์—…๋ฌด๋ฅผ ๋ณด๋Ÿฌ ๊ฐˆ ๋•Œ ์ง์‚ฌ๋ž‘ ์ƒ๋Œ€ ๐Ÿ˜ ๋ฅผ ๋ฐ๋ ค๊ฐ€๊ณ  ์‹ถ์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๋งค์šฐ ๋งŽ์€ ์ˆ˜์˜ ์œ ์ €๊ฐ€ ์žˆ์ง€๋งŒ, ์„œ๋ฒ„๋Š” ๊ทธ๋“ค์˜ ์š”์ฒญ์„ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ๋‹ฅ-์ข‹์ง€-์•Š์€ ์—ฐ๊ฒฐ์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ•™ . +### ํ–„๋ฒ„๊ฑฐ ์˜ˆ์‹œ์˜ ๊ฒฐ๋ก  { #burger-conclusion } -๊ทธ๋ฆฌ๊ณ  ์‘๋‹ต์ด ๋Œ์•„์˜ฌ ๋•Œ๊นŒ์ง€ ๋‹ค์‹œ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ•™ . +"์ง์‚ฌ๋ž‘ ์ƒ๋Œ€์™€์˜ ํŒจ์ŠคํŠธํ‘ธ๋“œ์  ํ–„๋ฒ„๊ฑฐ" ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๊ธฐ๋‹ค๋ฆผ ๐Ÿ•™ ์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์—, ๋™์‹œ ์‹œ์Šคํ…œ โธ๐Ÿ”€โฏ ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. -์ด "๊ธฐ๋‹ค๋ฆผ" ๐Ÿ•™ ์€ ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„์ด์ง€๋งŒ, ๋ชจ๋‘ ๋”ํ•ด์ง€๋ฉด, ๊ฒฐ๊ตญ์—๋Š” ๋งค์šฐ ๊ธด ๋Œ€๊ธฐ์‹œ๊ฐ„์ด ๋ฉ๋‹ˆ๋‹ค. +๋Œ€๋ถ€๋ถ„์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. -๋”ฐ๋ผ์„œ ์›น API๋ฅผ ์œ„ํ•ด ๋น„๋™๊ธฐ โธ๐Ÿ”€โฏ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. +๋งค์šฐ ๋งŽ์€ ์‚ฌ์šฉ์ž๋“ค์ด ์žˆ๊ณ , ์„œ๋ฒ„๋Š” ๊ทธ๋“ค์˜ ์ข‹์ง€ ์•Š์€ ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์š”์ฒญ์ด ์ „์†ก๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค ๐Ÿ•™. -๋Œ€๋ถ€๋ถ„์˜ ์กด์žฌํ•˜๋Š” ์œ ๋ช…ํ•œ ํŒŒ์ด์ฌ ํ”„๋ ˆ์ž„์›Œํฌ (Flask์™€ Django ๋“ฑ)์€ ์ƒˆ๋กœ์šด ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ๋“ค์ด ํŒŒ์ด์ฌ์— ์กด์žฌํ•˜๊ธฐ ์ „์— ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ, ๊ทธ๋“ค์˜ ๋ฐฐํฌ ๋ฐฉ์‹์€ ๋ณ‘๋ ฌ ์‹คํ–‰๊ณผ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๋งŒํผ ๊ฐ•๋ ฅํ•˜์ง€๋Š” ์•Š์€ ์˜ˆ์ „ ๋ฒ„์ „์˜ ๋น„๋™๊ธฐ ์‹คํ–‰์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +๊ทธ๋ฆฌ๊ณ  ์‘๋‹ต์ด ๋Œ์•„์˜ค๊ธฐ๋ฅผ ๋‹ค์‹œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค ๐Ÿ•™. -๋น„๋™๊ธฐ ์›น ํŒŒ์ด์ฌ(ASGI)์— ๋Œ€ํ•œ ์ฃผ์š” ๋ช…์„ธ๊ฐ€ ์›น์†Œ์ผ“์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด Django์—์„œ ๊ฐœ๋ฐœ ๋˜์—ˆ์Œ์—๋„ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. +์ด "๊ธฐ๋‹ค๋ฆผ" ๐Ÿ•™ ์€ ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„๋กœ ์ธก์ •๋˜์ง€๋งŒ, ๋ชจ๋‘ ํ•ฉ์น˜๋ฉด ๊ฒฐ๊ตญ ๊ฝค ๋งŽ์€ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋ฉ๋‹ˆ๋‹ค. -์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋น„๋™๊ธฐ์„ฑ์€ (NodeJS๋Š” ๋ณ‘๋ ฌ์ ์ด์ง€ ์•Š์Œ์—๋„) NodeJS๊ฐ€ ์‚ฌ๋ž‘๋ฐ›๋Š” ์ด์œ ์ด๊ณ , ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ์„œ์˜ Go์˜ ๊ฐ•์ ์ž…๋‹ˆ๋‹ค. +๊ทธ๋ž˜์„œ ์›น API์—๋Š” ๋น„๋™๊ธฐ โธ๐Ÿ”€โฏ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. -๊ทธ๋ฆฌ๊ณ  **FastAPI**๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋™์ผํ•œ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋น„๋™๊ธฐ์„ฑ์€ NodeJS๊ฐ€ ์ธ๊ธฐ ์žˆ๋Š” ์ด์œ (๋น„๋ก NodeJS๊ฐ€ ๋ณ‘๋ ฌ์€ ์•„๋‹ˆ์ง€๋งŒ)์ด์ž, ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ์„œ Go์˜ ๊ฐ•์ ์ž…๋‹ˆ๋‹ค. -๋˜ํ•œ ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋น„๋™๊ธฐ์„ฑ์„ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€๋ถ€๋ถ„์˜ ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ NodeJS ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ๋” ๋†’์€ ์„ฑ๋Šฅ์„ ์–ป๊ณ  C์— ๋” ๊ฐ€๊นŒ์šด ์ปดํŒŒ์ผ ์–ธ์–ด์ธ Go์™€ ๋™๋“ฑํ•œ ์„ฑ๋Šฅ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ชจ๋‘ Starlette ๋•๋ถ„์ž…๋‹ˆ๋‹ค). +๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์ด **FastAPI**๋กœ ์–ป๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ˆ˜์ค€์˜ ์„ฑ๋Šฅ์ž…๋‹ˆ๋‹ค. -### ๋™์‹œ์„ฑ์ด ๋ณ‘๋ ฌ์„ฑ๋ณด๋‹ค ๋” ๋‚˜์€๊ฐ€? +๋˜ํ•œ ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋น„๋™๊ธฐ์„ฑ์„ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋Œ€๋ถ€๋ถ„์˜ ํ…Œ์ŠคํŠธ๋œ NodeJS ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ๋” ๋†’์€ ์„ฑ๋Šฅ์„ ์–ป๊ณ , C์— ๋” ๊ฐ€๊นŒ์šด ์ปดํŒŒ์ผ ์–ธ์–ด์ธ Go์™€ ๋™๋“ฑํ•œ ์„ฑ๋Šฅ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๋ชจ๋‘ Starlette ๋•๋ถ„์ž…๋‹ˆ๋‹ค). -๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๊ทธ๊ฒƒ์ด ์ด์•ผ๊ธฐ์˜ ๊ตํ›ˆ์€ ์•„๋‹™๋‹ˆ๋‹ค. +### ๋™์‹œ์„ฑ์ด ๋ณ‘๋ ฌ์„ฑ๋ณด๋‹ค ๋” ๋‚˜์€๊ฐ€์š”? { #is-concurrency-better-than-parallelism } -๋™์‹œ์„ฑ์€ ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๋งŽ์€ ๋Œ€๊ธฐ๋ฅผ ํ•„์š”๋กœํ•˜๋Š” **ํŠน์ •ํ•œ** ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด, ์›น ์‘์šฉํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ์—์„œ ๋™์‹œ์„ฑ์ด ๋ณ‘๋ ฌ์„ฑ๋ณด๋‹ค ์ผ๋ฐ˜์ ์œผ๋กœ ํ›จ์”ฌ ๋‚ซ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ฒฝ์šฐ์— ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. +์•„๋‹ˆ์š”! ๊ทธ๊ฒŒ ์ด ์ด์•ผ๊ธฐ์˜ ๊ตํ›ˆ์€ ์•„๋‹™๋‹ˆ๋‹ค. -๋”ฐ๋ผ์„œ, ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ์˜ ์งง์€ ์ด์•ผ๊ธฐ๋ฅผ ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค: +๋™์‹œ์„ฑ์€ ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ๊ธฐ๋‹ค๋ฆผ์ด ํฌํ•จ๋˜๋Š” **ํŠน์ •ํ•œ** ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋•Œ๋ฌธ์— ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณ‘๋ ฌ์„ฑ๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ฒƒ์— ํ•ด๋‹นํ•˜์ง„ ์•Š์Šต๋‹ˆ๋‹ค. -> ๋‹น์‹ ์€ ํฌ๊ณ , ๋”๋Ÿฌ์šด ์ง‘์„ ์ฒญ์†Œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. +๊ทธ๋ž˜์„œ ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ์˜ ์งง์€ ์ด์•ผ๊ธฐ๋ฅผ ์ƒ์ƒํ•ด๋ณด์„ธ์š”: + +> ์—ฌ๋Ÿฌ๋ถ„์€ ํฌ๊ณ  ๋”๋Ÿฌ์šด ์ง‘์„ ์ฒญ์†Œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. *๋„ค, ์ด๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค*. --- -์–ด๋””์—๋„ ๋Œ€๊ธฐ ๐Ÿ•™ ๋Š” ์—†๊ณ , ์ง‘์•ˆ ๊ณณ๊ณณ์—์„œ ํ•ด์•ผํ•˜๋Š” ๋งŽ์€ ์ž‘์—…๋“ค๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค. +์–ด๋””์—๋„ ๊ธฐ๋‹ค๋ฆผ ๐Ÿ•™ ์€ ์—†๊ณ , ์ง‘์˜ ์—ฌ๋Ÿฌ ์žฅ์†Œ์—์„œ ํ•ด์•ผ ํ•  ์ผ์ด ๋งŽ์„ ๋ฟ์ž…๋‹ˆ๋‹ค. -๋ฒ„๊ฑฐ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์ฒ˜์Œ์—๋Š” ๊ฑฐ์‹ค, ๊ทธ ๋‹ค์Œ์€ ๋ถ€์—Œ๊ณผ ๊ฐ™์€ ์‹์œผ๋กœ ์ˆœ์„œ๋ฅผ ์ •ํ•  ์ˆ˜๋„ ์žˆ์œผ๋‚˜, ๋ฌด์—‡๋„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ๐Ÿ•™ ์•Š๊ณ  ๊ณ„์†ํ•ด์„œ ์ฒญ์†Œ ์ž‘์—…๋งŒ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ˆœ์„œ๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +ํ–„๋ฒ„๊ฑฐ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๊ฑฐ์‹ค๋ถ€ํ„ฐ, ๊ทธ ๋‹ค์Œ์€ ๋ถ€์—Œ์ฒ˜๋Ÿผ ์ˆœ์„œ๋ฅผ ์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์–ด๋–ค ๊ฒƒ๋„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ๐Ÿ•™ ์•Š๊ณ  ๊ณ„์† ์ฒญ์†Œ๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ˆœ์„œ๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -์ˆœ์„œ๊ฐ€ ์žˆ๋“  ์—†๋“  ๋™์ผํ•œ ์‹œ๊ฐ„์ด ์†Œ์š”๋  ๊ฒƒ์ด๊ณ (๋™์‹œ์„ฑ) ๋™์ผํ•œ ์–‘์˜ ์ž‘์—…์„ ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +์ˆœ์„œ๊ฐ€ ์žˆ๋“  ์—†๋“ (๋™์‹œ์„ฑ) ๋๋‚ด๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ ๊ฐ™๊ณ , ๊ฐ™์€ ์–‘์˜ ์ผ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—์„œ, 8๋ช…์˜ ์ „(ๅ‰)-์ ์›/์š”๋ฆฌ์‚ฌ์ด๋ฉด์„œ-ํ˜„(็พ)-์ฒญ์†Œ๋ถ€ ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ๋ฅผ ๊ณ ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ๋“ค ๊ฐ์ž(๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ )๊ฐ€ ์ง‘์˜ ํ•œ ๋ถ€๋ถ„์”ฉ ๋งก์•„ ์ฒญ์†Œ๋ฅผ ํ•œ๋‹ค๋ฉด, ๋‹น์‹ ์€ **๋ณ‘๋ ฌ์ **์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ , ์กฐ๊ธˆ์˜ ๋„์›€์ด ์žˆ๋‹ค๋ฉด, ํ›จ์”ฌ ๋” ๋นจ๋ฆฌ ๋๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ, ์ „(ๅ‰) ์ ์›/์š”๋ฆฌ์‚ฌ์ด์ž ํ˜„(็พ) ์ฒญ์†Œ๋ถ€๊ฐ€ ๋œ 8๋ช…์„ ๋ฐ๋ ค์˜ฌ ์ˆ˜ ์žˆ๊ณ , ๊ฐ์ž(๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„)๊ฐ€ ์ง‘์˜ ๊ตฌ์—ญ์„ ํ•˜๋‚˜์”ฉ ๋งก์•„ ์ฒญ์†Œํ•œ๋‹ค๋ฉด, ์ถ”๊ฐ€ ๋„์›€๊ณผ ํ•จ๊ป˜ ๋ชจ๋“  ์ผ์„ **๋ณ‘๋ ฌ**๋กœ ์ˆ˜ํ–‰ํ•˜์—ฌ ํ›จ์”ฌ ๋” ๋นจ๋ฆฌ ๋๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ, (๋‹น์‹ ์„ ํฌํ•จํ•œ) ๊ฐ๊ฐ์˜ ์ฒญ์†Œ๋ถ€๋“ค์€ ํ”„๋กœ์„ธ์„œ๊ฐ€ ๋  ๊ฒƒ์ด๊ณ , ๊ฐ์ž์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. +์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ (์—ฌ๋Ÿฌ๋ถ„์„ ํฌํ•จํ•œ) ๊ฐ ์ฒญ์†Œ๋ถ€๋Š” ํ”„๋กœ์„ธ์„œ๊ฐ€ ๋˜์–ด, ๋งก์€ ์ผ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. -์‹คํ–‰ ์‹œ๊ฐ„์˜ ๋Œ€๋ถ€๋ถ„์ด ๋Œ€๊ธฐ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ์ž‘์—…์— ์†Œ์š”๋˜๊ณ , ์ปดํ“จํ„ฐ์—์„œ ์ž‘์—…์€ CPU์—์„œ ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ, ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ "CPU์— ๋ฌถ์˜€"๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. +๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ ์‹œ๊ฐ„์˜ ๋Œ€๋ถ€๋ถ„์ด ๊ธฐ๋‹ค๋ฆผ์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ ์ž‘์—…์— ์“ฐ์ด๊ณ , ์ปดํ“จํ„ฐ์—์„œ ์ž‘์—…์€ CPU๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ, ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ "CPU bound"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. --- -CPU์— ๋ฌถ์ธ ์—ฐ์‚ฐ์— ๊ด€ํ•œ ํ”ํ•œ ์˜ˆ์‹œ๋Š” ๋ณต์žกํ•œ ์ˆ˜ํ•™ ์ฒ˜๋ฆฌ๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. +CPU bound ์ž‘์—…์˜ ํ”ํ•œ ์˜ˆ์‹œ๋Š” ๋ณต์žกํ•œ ์ˆ˜ํ•™ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด: -* **์˜ค๋””์˜ค** ๋˜๋Š” **์ด๋ฏธ์ง€** ์ฒ˜๋ฆฌ. -* **์ปดํ“จํ„ฐ ๋น„์ „**: ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋Š” ์ˆ˜๋ฐฑ๊ฐœ์˜ ํ”ฝ์…€๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๊ณ , ๊ฐ ํ”ฝ์…€์€ 3๊ฐœ์˜ ๊ฐ’ / ์ƒ‰์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ํ•ด๋‹น ํ”ฝ์…€๋“ค์— ๋Œ€ํ•ด ๋™์‹œ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ณ„์‚ฐํ•ด์•ผํ•˜๋Š” ์ฒ˜๋ฆฌ. -* **๋จธ์‹ ๋Ÿฌ๋‹**: ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์€ "ํ–‰๋ ฌ"๊ณผ "๋ฒกํ„ฐ" ๊ณฑ์…ˆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฑฐ๋Œ€ํ•œ ์Šคํ”„๋ ˆ๋“œ ์‹œํŠธ์— ์ˆ˜๋“ค์ด ์žˆ๊ณ  ๊ทธ ์ˆ˜๋“ค์„ ๋™์‹œ์— ๊ณฑํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์‹ญ์‹œ์˜ค. -* **๋”ฅ๋Ÿฌ๋‹**: ๋จธ์‹ ๋Ÿฌ๋‹์˜ ํ•˜์œ„์˜์—ญ์œผ๋กœ, ๋™์ผํ•œ ์˜ˆ์‹œ๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‹จ์ง€ ์ด ๊ฒฝ์šฐ์—๋Š” ํ•˜๋‚˜์˜ ์Šคํ”„๋ ˆ๋“œ ์‹œํŠธ์— ๊ณฑํ•ด์•ผํ•  ์ˆ˜๋“ค์ด ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ฑฐ๋Œ€ํ•œ ์„ธํŠธ์˜ ์Šคํ”„๋ ˆ๋“œ ์‹œํŠธ๋“ค์ด ์žˆ๊ณ , ๋งŽ์€ ๊ฒฝ์šฐ์—, ์ด ๋ชจ๋ธ๋“ค์„ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ˆ˜ํ•œ ํ”„๋กœ์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +* **์˜ค๋””์˜ค** ๋˜๋Š” **์ด๋ฏธ์ง€** ์ฒ˜๋ฆฌ +* **์ปดํ“จํ„ฐ ๋น„์ „**: ์ด๋ฏธ์ง€๋Š” ์ˆ˜๋ฐฑ๋งŒ ๊ฐœ์˜ ํ”ฝ์…€๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ๊ฐ ํ”ฝ์…€์€ 3๊ฐœ์˜ ๊ฐ’/์ƒ‰์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. ๋ณดํ†ต ๊ทธ ํ”ฝ์…€๋“ค์— ๋Œ€ํ•ด ๋™์‹œ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +* **๋จธ์‹ ๋Ÿฌ๋‹**: ๋ณดํ†ต ๋งŽ์€ "matrix"์™€ "vector" ๊ณฑ์…ˆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ˆซ์ž๊ฐ€ ์žˆ๋Š” ๊ฑฐ๋Œ€ํ•œ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ๋ฅผ ์ƒ๊ฐํ•˜๊ณ , ๊ทธ ๋ชจ๋“  ์ˆ˜๋ฅผ ๋™์‹œ์— ๊ณฑํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. +* **๋”ฅ๋Ÿฌ๋‹**: ๋จธ์‹ ๋Ÿฌ๋‹์˜ ํ•˜์œ„ ๋ถ„์•ผ์ด๋ฏ€๋กœ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๊ณฑํ•ด์•ผ ํ•  ์ˆซ์ž๊ฐ€ ์žˆ๋Š” ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ๊ฐ€ ํ•˜๋‚˜๊ฐ€ ์•„๋‹ˆ๋ผ, ์•„์ฃผ ํฐ ์ง‘ํ•ฉ์ด๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ ๊ทธ ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ /๋˜๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํŠน๋ณ„ํ•œ ํ”„๋กœ์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -### ๋™์‹œ์„ฑ + ๋ณ‘๋ ฌ์„ฑ: ์›น + ๋จธ์‹ ๋Ÿฌ๋‹ +### ๋™์‹œ์„ฑ + ๋ณ‘๋ ฌ์„ฑ: ์›น + ๋จธ์‹ ๋Ÿฌ๋‹ { #concurrency-parallelism-web-machine-learning } -**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›น ๊ฐœ๋ฐœ์—์„œ๋Š” ๋งค์šฐ ํ”ํ•œ ๋™์‹œ์„ฑ์˜ ์ด์ ์„ (NodeJS์˜ ์ฃผ๋œ ๋งค๋ ฅ๋งŒํผ) ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›น ๊ฐœ๋ฐœ์—์„œ ๋งค์šฐ ํ”ํ•œ ๋™์‹œ์„ฑ์˜ ์ด์ ์„( NodeJS์˜ ์ฃผ์š” ๋งค๋ ฅ๊ณผ ๊ฐ™์€) ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋จธ์‹ ๋Ÿฌ๋‹ ์‹œ์Šคํ…œ๊ณผ ๊ฐ™์ด **CPU์— ๋ฌถ์ธ** ์ž‘์—…์„ ์œ„ํ•ด ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ(๋‹ค์ˆ˜์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ‘๋ ฌ์ ์œผ๋กœ ๋™์ž‘์‹œํ‚ค๋Š” ๊ฒƒ)์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +๋˜ํ•œ ๋จธ์‹ ๋Ÿฌ๋‹ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ **CPU bound** ์›Œํฌ๋กœ๋“œ์— ๋Œ€ํ•ด ๋ณ‘๋ ฌ์„ฑ๊ณผ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ(์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰)์„ ํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -ํŒŒ์ด์ฌ์ด **๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธ์Šค**, ๋จธ์‹ ๋Ÿฌ๋‹๊ณผ ํŠนํžˆ ๋”ฅ๋Ÿฌ๋‹์— ์˜ ์ฃผ๋œ ์–ธ์–ด๋ผ๋Š” ๊ฐ„๋‹จํ•œ ์‚ฌ์‹ค์— ๋”ํ•ด์„œ, ์ด๊ฒƒ์€ FastAPI๋ฅผ ๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธ์Šค / ๋จธ์‹ ๋Ÿฌ๋‹ ์›น API์™€ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์— (๋‹ค๋ฅธ ๊ฒƒ๋“ค๋ณด๋‹ค) ์ข‹์€ ์„ ํƒ์ง€๊ฐ€ ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ ํŒŒ์ด์ฌ์ด **๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธ์Šค**, ๋จธ์‹ ๋Ÿฌ๋‹, ํŠนํžˆ ๋”ฅ๋Ÿฌ๋‹์˜ ์ฃผ์š” ์–ธ์–ด๋ผ๋Š” ๋‹จ์ˆœํ•œ ์‚ฌ์‹ค๊ณผ ๋”ํ•ด์ ธ, FastAPI๋ฅผ ๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธ์Šค/๋จธ์‹ ๋Ÿฌ๋‹ ์›น API ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๊ทธ ์™ธ์—๋„ ๋งŽ์€ ๊ฒƒ๋“ค)์— ๋งค์šฐ ์ž˜ ๋งž๋Š” ์„ ํƒ์œผ๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. -๋ฐฐํฌ์‹œ ๋ณ‘๋ ฌ์„ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š”์ง€ ์•Œ๊ณ ์‹ถ๋‹ค๋ฉด, [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank}๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค. +ํ”„๋กœ๋•์…˜์—์„œ ์ด ๋ณ‘๋ ฌ์„ฑ์„ ์–ด๋–ป๊ฒŒ ๋‹ฌ์„ฑํ•˜๋Š”์ง€ ๋ณด๋ ค๋ฉด [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank} ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. -## `async`์™€ `await` +## `async`์™€ `await` { #async-and-await } -์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์—๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๋งค์šฐ ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ด๊ฒƒ์„ ํ‰๋ฒ”ํ•œ "์ˆœ์ฐจ์ " ์ฝ”๋“œ๋กœ ๋ณด์ด๊ฒŒ ํ•˜๊ณ , ์ ์ ˆํ•œ ์ˆœ๊ฐ„์— ๋‹น์‹ ์„ ์œ„ํ•ด "๋Œ€๊ธฐ"ํ•ฉ๋‹ˆ๋‹ค. +์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์—๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๋งค์šฐ ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์ด๋ฅผ ํ‰๋ฒ”ํ•œ "์ˆœ์ฐจ" ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•˜๊ณ , ์ ์ ˆํ•œ ์ˆœ๊ฐ„์— ์—ฌ๋Ÿฌ๋ถ„์„ ์œ„ํ•ด "๊ธฐ๋‹ค๋ฆผ"์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. -์—ฐ์‚ฐ์ด ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ๋Œ€๊ธฐ๋ฅผ ํ•ด์•ผํ•˜๊ณ  ์ƒˆ๋กœ์šด ํŒŒ์ด์ฌ ๊ธฐ๋Šฅ๋“ค์„ ์ง€์›ํ•œ๋‹ค๋ฉด, ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +๊ฒฐ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์ „์— ๊ธฐ๋‹ค๋ฆผ์ด ํ•„์š”ํ•œ ์ž‘์—…์ด ์žˆ๊ณ , ์ด๋Ÿฌํ•œ ์ƒˆ๋กœ์šด ํŒŒ์ด์ฌ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```Python burgers = await get_burgers(2) ``` -์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ `await`์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŒŒ์ด์ฌ์—๊ฒŒ `burgers` ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์ด์ „์— `get_burgers(2)`์˜ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๐Ÿ•™ ๊ธฐ๋‹ค๋ฆฌ๋ผ๊ณ  โธ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด, ํŒŒ์ด์ฌ์€ ๊ทธ๋™์•ˆ (๋‹ค๋ฅธ ์š”์ฒญ์„ ๋ฐ›๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€) ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด๋„ ๋œ๋‹ค๋Š” ๊ฒƒ์„ ๐Ÿ”€ โฏ ์•Œ๊ฒŒ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ `await`์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํŒŒ์ด์ฌ์—๊ฒŒ `get_burgers(2)`๊ฐ€ ๊ทธ ์ผ์„ ๋๋‚ผ ๋•Œ๊นŒ์ง€ ๐Ÿ•™ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก โธ ๋งํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ `burgers`์— ์ €์žฅํ•˜๊ธฐ ์ „์— ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํŒŒ์ด์ฌ์€ ๊ทธ๋™์•ˆ(์˜ˆ: ๋‹ค๋ฅธ ์š”์ฒญ์„ ๋ฐ›๋Š” ๊ฒƒ์ฒ˜๋Ÿผ) ๋‹ค๋ฅธ ์ผ์„ ํ•˜๋Ÿฌ ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ ๐Ÿ”€ โฏ ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -`await`๊ฐ€ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด, ์ด๊ฒƒ์€ ๋น„๋™๊ธฐ๋ฅผ ์ง€์›ํ•˜๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ ํ•จ์ˆ˜๋ฅผ `async def`๋ฅผ ์‚ฌ์šฉํ•ด ์ •์˜ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: +`await`๊ฐ€ ๋™์ž‘ํ•˜๋ ค๋ฉด, ์ด ๋น„๋™๊ธฐ์„ฑ์„ ์ง€์›ํ•˜๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ ค๋ฉด `async def`๋กœ ์„ ์–ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: ```Python hl_lines="1" async def get_burgers(number: int): - # Do some asynchronous stuff to create the burgers + # ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ return burgers ``` -...`def`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ : +...`def` ๋Œ€์‹ : ```Python hl_lines="2" -# This is not asynchronous +# ๋น„๋™๊ธฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค def get_sequential_burgers(number: int): - # Do some sequential stuff to create the burgers + # ํ–„๋ฒ„๊ฑฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ˆœ์ฐจ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ return burgers ``` -`async def`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ํŒŒ์ด์ฌ์€ ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด์—์„œ `await` ํ‘œํ˜„์— ์ฃผ์˜ํ•ด์•ผํ•œ๋‹ค๋Š” ์‚ฌ์‹ค๊ณผ, ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ "์ผ์‹œ์ •์ง€"โธํ•˜๊ณ  ๋‹ค์‹œ ๋Œ์•„์˜ค๊ธฐ ์ „๊นŒ์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰๐Ÿ”€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋ฉ๋‹ˆ๋‹ค. +`async def`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ํŒŒ์ด์ฌ์€ ๊ทธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ `await` ํ‘œํ˜„์‹์— ์ฃผ์˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ "์ผ์‹œ์ •์ง€" โธ ํ•˜๊ณ  ๋‹ค์‹œ ๋Œ์•„์˜ค๊ธฐ ์ „์— ๋‹ค๋ฅธ ์ผ์„ ํ•˜๋Ÿฌ ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ ๐Ÿ”€ ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -`async def`f ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•  ๋•Œ, "๋Œ€๊ธฐ"ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์•„๋ž˜๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +`async def` ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š”, ๊ทธ ํ•จ์ˆ˜๋ฅผ "await" ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: ```Python -# This won't work, because get_burgers was defined with: async def +# ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. get_burgers๋Š” async def๋กœ ์ •์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค burgers = get_burgers(2) ``` --- -๋”ฐ๋ผ์„œ, `await`f๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด `async def`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: +๋”ฐ๋ผ์„œ, `await`๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋งํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋ฅผ `async def`๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: ```Python hl_lines="2-3" @app.get('/burgers') @@ -317,94 +349,96 @@ async def read_burgers(): return burgers ``` -### ๋” ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์  ์‚ฌํ•ญ +### ๋” ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์  ์‚ฌํ•ญ { #more-technical-details } + +`await`๋Š” `async def`๋กœ ์ •์˜๋œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ˆˆ์น˜์ฑ„์…จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -`await`๊ฐ€ `async def`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ˆˆ์น˜์ฑ„์…จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๋™์‹œ์—, `async def`๋กœ ์ •์˜๋œ ํ•จ์ˆ˜๋Š” "await" ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `async def`๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜๋Š” `async def`๋กœ ์ •์˜๋œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ๋™์‹œ์—, `async def`๋กœ ์ •์˜๋œ ํ•จ์ˆ˜๋“ค์€ "๋Œ€๊ธฐ"๋˜์–ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, `async def`๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜๋“ค์€ ์—ญ์‹œ `async def`๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋ ‡๋‹ค๋ฉด, ๋‹ญ์ด ๋จผ์ €๋ƒ ๋‹ฌ๊ฑ€์ด ๋จผ์ €๋ƒ์ฒ˜๋Ÿผ, ์ฒซ ๋ฒˆ์งธ `async` ํ•จ์ˆ˜๋Š” ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? -๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ญ์ด ๋จผ์ €๋ƒ, ๋‹ฌ๊ฑ€์ด ๋จผ์ €๋ƒ, ์ฒซ `async` ํ•จ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒ ์Šต๋‹ˆ๊นŒ? +**FastAPI**๋กœ ์ž‘์—…ํ•œ๋‹ค๋ฉด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ "์ฒซ" ํ•จ์ˆ˜๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๊ฐ€ ๋  ๊ฒƒ์ด๊ณ , FastAPI๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. -**FastAPI**๋ฅผ ์‚ฌ์šฉํ•ด ์ž‘์—…ํ•œ๋‹ค๋ฉด ์ด๊ฒƒ์„ ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ "์ฒซ" ํ•จ์ˆ˜๋Š” ๋‹น์‹ ์˜ *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๊ฐ€ ๋  ๊ฒƒ์ด๊ณ , FastAPI๋Š” ์–ด๋–ป๊ฒŒ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ์•Œ๊ณ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ FastAPI ์—†์ด `async` / `await`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๊ทธ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ FastAPI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  `async` / `await`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์ด ์—ญ์‹œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +### ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ async ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ { #write-your-own-async-code } -### ๋‹น์‹ ๋งŒ์˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ +Starlette(๊ทธ๋ฆฌ๊ณ  **FastAPI**)๋Š” AnyIO๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ํŒŒ์ด์ฌ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ asyncio์™€ Trio ๋ชจ๋‘์™€ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. -Starlette(๊ทธ๋ฆฌ๊ณ  FastAPI)๋Š” AnyIO๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ ์žˆ๊ณ , ๋”ฐ๋ผ์„œ ํŒŒ์ด์ฌ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ asyncio ๋ฐ Trio์™€ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. +ํŠนํžˆ, ์ฝ”๋“œ์—์„œ ๋” ๊ณ ๊ธ‰ ํŒจํ„ด์ด ํ•„์š”ํ•œ ๊ณ ๊ธ‰ ๋™์‹œ์„ฑ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋Š” ์ง์ ‘ AnyIO๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -ํŠนํžˆ, ์ฝ”๋“œ์—์„œ ๊ณ ๊ธ‰ ํŒจํ„ด์ด ํ•„์š”ํ•œ ๊ณ ๊ธ‰ ๋™์‹œ์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ง์ ‘์ ์œผ๋กœ AnyIO๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋ฆฌ๊ณ  FastAPI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋†’์€ ํ˜ธํ™˜์„ฑ์„ ํ™•๋ณดํ•˜๊ณ  ๊ทธ ์ด์ (์˜ˆ: *structured concurrency*)์„ ์–ป๊ธฐ ์œ„ํ•ด AnyIO๋กœ ์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ async ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -FastAPI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, ๋†’์€ ํ˜ธํ™˜์„ฑ ๋ฐ AnyIO์˜ ์ด์ (์˜ˆ: *๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ*)์„ ์ทจํ•˜๊ธฐ ์œ„ํ•ด AnyIO๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ €๋Š” AnyIO ์œ„์— ์–‡์€ ๋ ˆ์ด์–ด๋กœ ๋˜ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์„ ์กฐ๊ธˆ ๊ฐœ์„ ํ•˜๊ณ  ๋” ๋‚˜์€ **์ž๋™์™„์„ฑ**, **์ธ๋ผ์ธ ์˜ค๋ฅ˜** ๋“ฑ์„ ์–ป๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ **์ดํ•ด**ํ•˜๊ณ  **์—ฌ๋Ÿฌ๋ถ„๋งŒ์˜ async ์ฝ”๋“œ**๋ฅผ ์ž‘์„ฑํ•˜๋„๋ก ๋•๋Š” ์นœ์ ˆํ•œ ์†Œ๊ฐœ์™€ ํŠœํ† ๋ฆฌ์–ผ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: Asyncer. ํŠนํžˆ **async ์ฝ”๋“œ์™€ ์ผ๋ฐ˜**(blocking/๋™๊ธฐ) ์ฝ”๋“œ๋ฅผ **๊ฒฐํ•ฉ**ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์•„์ฃผ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. -### ๋น„๋™๊ธฐ ์ฝ”๋“œ์˜ ๋‹ค๋ฅธ ํ˜•ํƒœ +### ๋น„๋™๊ธฐ ์ฝ”๋“œ์˜ ๋‹ค๋ฅธ ํ˜•ํƒœ { #other-forms-of-asynchronous-code } -ํŒŒ์ด์ฌ์—์„œ `async`์™€ `await`๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ ๊ฒƒ์€ ๋น„๊ต์  ์ตœ๊ทผ์˜ ์ผ์ž…๋‹ˆ๋‹ค. +`async`์™€ `await`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด ์Šคํƒ€์ผ์€ ์–ธ์–ด์—์„œ ๋น„๊ต์  ์ตœ๊ทผ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ์ด๋กœ ์ธํ•ด ๋น„๋™๊ธฐ ์ฝ”๋“œ ์ž‘์—…์ด ํ›จ์”ฌ ๊ฐ„๋‹จํ•ด์กŒ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ผ์„ ํ›จ์”ฌ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. -๊ฐ™์€ (๋˜๋Š” ๊ฑฐ์˜ ์œ ์‚ฌํ•œ) ๋ฌธ๋ฒ•์€ ์ตœ์‹  ๋ฒ„์ „์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ(๋ธŒ๋ผ์šฐ์ €์™€ NodeJS)์—๋„ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. +๊ฑฐ์˜ ๋™์ผํ•œ ๋ฌธ๋ฒ•์ด ์ตœ๊ทผ ๋ธŒ๋ผ์šฐ์ €์™€ NodeJS์˜ ์ตœ์‹  JavaScript์—๋„ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ๊ทธ ์ด์ „์—, ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๊ฝค ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์šด ์ผ์ด์—ˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ๊ทธ ์ด์ „์—๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค. -ํŒŒ์ด์ฌ์˜ ์˜ˆ์ „ ๋ฒ„์ „์ด๋ผ๋ฉด, ์Šค๋ ˆ๋“œ ๋˜๋Š” Gevent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ , ๋””๋ฒ„๊น…ํ•˜๊ณ , ์ด์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š”๊ฒŒ ํ›จ์”ฌ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. +์ด์ „ ๋ฒ„์ „์˜ ํŒŒ์ด์ฌ์—์„œ๋Š” ์Šค๋ ˆ๋“œ ๋˜๋Š” Gevent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ , ๋””๋ฒ„๊น…ํ•˜๊ณ , ์ด์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. -์˜ˆ์ „ ๋ฒ„์ „์˜ NodeJS / ๋ธŒ๋ผ์šฐ์ € ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ผ๋ฉด, "์ฝœ๋ฐฑ ํ•จ์ˆ˜"๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋กœ ์ธํ•ด "์ฝœ๋ฐฑ ์ง€์˜ฅ"์— ๋น ์ง€๊ฒŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด์ „ ๋ฒ„์ „์˜ NodeJS/๋ธŒ๋ผ์šฐ์ € JavaScript์—์„œ๋Š” "callback"์„ ์‚ฌ์šฉํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” "callback hell"๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. -## ์ฝ”๋ฃจํ‹ด +## ์ฝ”๋ฃจํ‹ด { #coroutines } -**์ฝ”๋ฃจํ‹ด**์€ `async def` ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์นญํ•˜๋Š” ๋งค์šฐ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์šฉ์–ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ํŒŒ์ด์ฌ์€ ๊ทธ๊ฒƒ์ด ์‹œ์ž‘๋˜๊ณ  ์–ด๋А ์‹œ์ ์—์„œ ์™„๋ฃŒ๋˜์ง€๋งŒ ๋‚ด๋ถ€์— `await`๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋‚ด๋ถ€์ ์œผ๋กœ ์ผ์‹œ์ •์ง€โธ๋  ์ˆ˜๋„ ์žˆ๋Š” ํ•จ์ˆ˜์™€ ์œ ์‚ฌํ•œ ๊ฒƒ์ด๋ผ๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ ์žˆ์Šต๋‹ˆ๋‹ค. +**์ฝ”๋ฃจํ‹ด**์€ `async def` ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋งค์šฐ ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์šฉ์–ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ํŒŒ์ด์ฌ์€ ๊ทธ๊ฒƒ์ด ํ•จ์ˆ˜์™€ ๋น„์Šทํ•œ ๋ฌด์–ธ๊ฐ€๋กœ์„œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๊ณ , ์–ด๋А ์‹œ์ ์— ๋๋‚˜์ง€๋งŒ, ๋‚ด๋ถ€์— `await`๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋‚ด๋ถ€์ ์œผ๋กœ๋„ ์ผ์‹œ์ •์ง€ โธ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -๊ทธ๋Ÿฌ๋‚˜ `async` ๋ฐ `await`์™€ ํ•จ๊ป˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ๋“ค์€ "์ฝ”๋ฃจํ‹ด"์œผ๋กœ ๊ฐ„๋‹จํžˆ ์š”์•ฝ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Go์˜ ์ฃผ๋œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ "๊ณ ๋ฃจํ‹ด"์— ๊ฒฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ `async` ๋ฐ `await`์™€ ํ•จ๊ป˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์€ ์ข…์ข… "์ฝ”๋ฃจํ‹ด"์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์š”์•ฝ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” Go์˜ ์ฃผ์š” ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ "Goroutines"์— ๋น„๊ฒฌ๋ฉ๋‹ˆ๋‹ค. -## ๊ฒฐ๋ก  +## ๊ฒฐ๋ก  { #conclusion } -์ƒ๊ธฐ ๋ฌธ์žฅ์„ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋ด…์‹œ๋‹ค: +์œ„์˜ ๊ฐ™์€ ๋ฌธ์žฅ์„ ๋‹ค์‹œ ๋ด…์‹œ๋‹ค: -> ์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์€ **`async` ๋ฐ `await`** ๋ฌธ๋ฒ•๊ณผ ํ•จ๊ป˜ **โ€œ์ฝ”๋ฃจํ‹ดโ€**์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” **โ€œ๋น„๋™๊ธฐ ์ฝ”๋“œโ€**๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +> ์ตœ์‹  ํŒŒ์ด์ฌ ๋ฒ„์ „์€ **โ€œ์ฝ”๋ฃจํ‹ดโ€**์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” **โ€œ๋น„๋™๊ธฐ ์ฝ”๋“œโ€**๋ฅผ **`async` ๋ฐ `await`** ๋ฌธ๋ฒ•๊ณผ ํ•จ๊ป˜ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. -์ด์ œ ์ด ๋ง์„ ์กฐ๊ธˆ ๋” ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. โœจ +์ด์ œ ๋” ์ดํ•ด๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. โœจ -์ด๊ฒƒ์ด (Starlette์„ ํ†ตํ•ด) FastAPI๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ํ•˜๋ฉด์„œ ๊ทธ๊ฒƒ์ด ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. +์ด ๋ชจ๋“  ๊ฒƒ์ด FastAPI(Starlette์„ ํ†ตํ•ด)๋ฅผ ๊ตฌ๋™ํ•˜๊ณ , ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ์„ ๋‚ด๊ฒŒ ํ•˜๋Š” ์›๋™๋ ฅ์ž…๋‹ˆ๋‹ค. -## ๋งค์šฐ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์  ์‚ฌํ•ญ +## ๋งค์šฐ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์  ์‚ฌํ•ญ { #very-technical-details } /// warning | ๊ฒฝ๊ณ  -์ด ๋ถ€๋ถ„์€ ๋„˜์–ด๊ฐ€๋„ ๋ฉ๋‹ˆ๋‹ค. +์ด ๋ถ€๋ถ„์€ ์•„๋งˆ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ **FastAPI**๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋งค์šฐ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. -๋งŒ์•ฝ ๊ธฐ์ˆ ์  ์ง€์‹(์ฝ”๋ฃจํ‹ด, ์Šค๋ ˆ๋“œ, ๋ธ”๋กํ‚น ๋“ฑ)์ด ์žˆ๊ณ  FastAPI๊ฐ€ ์–ด๋–ป๊ฒŒ `async def` vs `def`๋ฅผ ๋‹ค๋ฃจ๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, ๊ณ„์†ํ•˜์‹ญ์‹œ์˜ค. +(์ฝ”๋ฃจํ‹ด, ์Šค๋ ˆ๋“œ, ๋ธ”๋กœํ‚น ๋“ฑ) ๊ฐ™์€ ๊ธฐ์ˆ  ์ง€์‹์ด ๊ฝค ์žˆ๊ณ  FastAPI๊ฐ€ `async def`์™€ ์ผ๋ฐ˜ `def`๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, ๊ณ„์† ์ฝ์–ด๋ณด์„ธ์š”. /// -### ๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜ +### ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ { #path-operation-functions } -๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜๋ฅผ `async def` ๋Œ€์‹  ์ผ๋ฐ˜์ ์ธ `def`๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒฝ์šฐ, (์„œ๋ฒ„๋ฅผ ์ฐจ๋‹จํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ) ๊ทธ๊ฒƒ์„ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹  ๋Œ€๊ธฐ์ค‘์ธ ์™ธ๋ถ€ ์Šค๋ ˆ๋“œํ’€์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋ฅผ `async def` ๋Œ€์‹  ์ผ๋ฐ˜์ ์ธ `def`๋กœ ์„ ์–ธํ•˜๋ฉด, (์„œ๋ฒ„๋ฅผ ๋ธ”๋กœํ‚นํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹ ) ์™ธ๋ถ€ ์Šค๋ ˆ๋“œํ’€์—์„œ ์‹คํ–‰๋˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ await ํ•ฉ๋‹ˆ๋‹ค. -๋งŒ์•ฝ ์ƒ๊ธฐ์— ๋ฌ˜์‚ฌ๋œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•ด์™”๊ณ  ์•ฝ๊ฐ„์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ (์•ฝ 100 ๋‚˜๋…ธ์ดˆ)์„ ์œ„ํ•ด `def`๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ณ„์‚ฐ๋งŒ์„ ์œ„ํ•œ ์‚ฌ์†Œํ•œ *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๋ฅผ ์ •์˜ํ•ด์™”๋‹ค๋ฉด, **FastAPI**๋Š” ์ด์™€๋Š” ๋ฐ˜๋Œ€๋ผ๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์—, *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*๊ฐ€ ๋ธ”๋กœํ‚น I/O๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ `async def`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. +์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ async ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ณธ ์ ์ด ์žˆ๊ณ , ์•„์ฃผ ์ž‘์€ ์„ฑ๋Šฅ ํ–ฅ์ƒ(์•ฝ 100 ๋‚˜๋…ธ์ดˆ)์„ ์œ„ํ•ด ๊ณ„์‚ฐ๋งŒ ํ•˜๋Š” ์‚ฌ์†Œํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋ฅผ ์ผ๋ฐ˜ `def`๋กœ ์ •์˜ํ•˜๊ณค ํ–ˆ๋‹ค๋ฉด, **FastAPI**์—์„œ๋Š” ๊ทธ ํšจ๊ณผ๊ฐ€ ์ •๋ฐ˜๋Œ€๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ ๋ธ”๋กœํ‚น I/O ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ `async def`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘, FastAPI๊ฐ€ ๋‹น์‹ ์ด ์ „์— ์‚ฌ์šฉํ•˜๋˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค [๋” ๋น ๋ฅผ](index.md#_11){.internal-link target=_blank} (์ตœ์†Œํ•œ ๋น„๊ฒฌ๋ ) ํ™•๋ฅ ์ด ๋†’์Šต๋‹ˆ๋‹ค. +๊ทธ๋Ÿผ์—๋„ ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘, **FastAPI**๋Š” ์ด์ „์— ์‚ฌ์šฉํ•˜๋˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค [์—ฌ์ „ํžˆ ๋” ๋น ๋ฅผ](index.md#performance){.internal-link target=_blank} ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค(๋˜๋Š” ์ตœ์†Œํ•œ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค). -### ์˜์กด์„ฑ +### ์˜์กด์„ฑ { #dependencies } -์˜์กด์„ฑ์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜์กด์„ฑ์ด `async def`๊ฐ€ ์•„๋‹Œ ํ‘œ์ค€ `def` ํ•จ์ˆ˜๋ผ๋ฉด, ์™ธ๋ถ€ ์Šค๋ ˆ๋“œํ’€์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. +[์˜์กด์„ฑ](tutorial/dependencies/index.md){.internal-link target=_blank}์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜์กด์„ฑ์ด `async def` ๋Œ€์‹  ํ‘œ์ค€ `def` ํ•จ์ˆ˜๋ผ๋ฉด, ์™ธ๋ถ€ ์Šค๋ ˆ๋“œํ’€์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. -### ํ•˜์œ„-์˜์กด์„ฑ +### ํ•˜์œ„ ์˜์กด์„ฑ { #sub-dependencies } -ํ•จ์ˆ˜ ์ •์˜์‹œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„œ๋กœ๋ฅผ ํ•„์š”๋กœํ•˜๋Š” ๋‹ค์ˆ˜์˜ ์˜์กด์„ฑ๊ณผ ํ•˜์œ„-์˜์กด์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ค‘ ์ผ๋ถ€๋Š” `async def`๋กœ, ๋‹ค๋ฅธ ์ผ๋ถ€๋Š” ์ผ๋ฐ˜์ ์ธ `def`๋กœ ์ƒ์„ฑ๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ ์ž˜ ๋™์ž‘ํ•˜๊ณ , ์ผ๋ฐ˜์ ์ธ `def`๋กœ ์ƒ์„ฑ๋œ ๊ฒƒ๋“ค์€ "๋Œ€๊ธฐ"๋˜๋Š” ๋Œ€์‹ ์— (์Šค๋ ˆ๋“œํ’€๋กœ๋ถ€ํ„ฐ) ์™ธ๋ถ€ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. +์„œ๋กœ๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์˜์กด์„ฑ๊ณผ [ํ•˜์œ„ ์˜์กด์„ฑ](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}์„ ํ•จ์ˆ˜ ์ •์˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ์ค‘ ์ผ๋ถ€๋Š” `async def`๋กœ, ๋‹ค๋ฅธ ์ผ๋ถ€๋Š” ์ผ๋ฐ˜ `def`๋กœ ์ƒ์„ฑ๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ •์ƒ ๋™์ž‘ํ•˜๋ฉฐ, ์ผ๋ฐ˜ `def`๋กœ ์ƒ์„ฑ๋œ ๊ฒƒ๋“ค์€ "await"๋˜๋Š” ๋Œ€์‹  (์Šค๋ ˆ๋“œํ’€์—์„œ) ์™ธ๋ถ€ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -### ๋‹ค๋ฅธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ +### ๋‹ค๋ฅธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ { #other-utility-functions } -์ง์ ‘ ํ˜ธ์ถœ๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜์ ์ธ `def`๋‚˜ `async def`๋กœ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๊ณ  FastAPI๋Š” ์ด๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜ `def`๋‚˜ `async def`๋กœ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI๋Š” ํ˜ธ์ถœ ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -์ด๊ฒƒ์€ FastAPI๊ฐ€ ๋‹น์‹ ์„ ์œ„ํ•ด ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜์™€๋Š” ๋ฐ˜๋Œ€์ž…๋‹ˆ๋‹ค: *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*์™€ ์˜์กด์„ฑ +์ด๋Š” FastAPI๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์„ ์œ„ํ•ด ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜(์ฆ‰, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์™€ ์˜์กด์„ฑ)์™€ ๋Œ€๋น„๋ฉ๋‹ˆ๋‹ค. -๋งŒ์•ฝ ๋‹น์‹ ์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๊ฐ€ `def`๋ฅผ ์‚ฌ์šฉํ•œ ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๋ผ๋ฉด, ์Šค๋ ˆ๋“œํ’€์—์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ง์ ‘ ํ˜ธ์ถœ(๋‹น์‹ ์ด ์ฝ”๋“œ์— ์ž‘์„ฑํ•œ ๋Œ€๋กœ)๋  ๊ฒƒ์ด๊ณ , `async def`๋กœ ์ƒ์„ฑ๋œ ํ•จ์ˆ˜๋ผ๋ฉด ์ฝ”๋“œ์—์„œ ํ˜ธ์ถœํ•  ๋•Œ ๊ทธ ํ•จ์ˆ˜๋ฅผ `await` ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๊ฐ€ `def`๋กœ ๋งŒ๋“  ์ผ๋ฐ˜ ํ•จ์ˆ˜๋ผ๋ฉด, ์Šค๋ ˆ๋“œํ’€์ด ์•„๋‹ˆ๋ผ ์ง์ ‘(์ฝ”๋“œ์— ์ž‘์„ฑํ•œ ๋Œ€๋กœ) ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  `async def`๋กœ ์ƒ์„ฑ๋œ ํ•จ์ˆ˜๋ผ๋ฉด, ์ฝ”๋“œ์—์„œ ํ˜ธ์ถœํ•  ๋•Œ ๊ทธ ํ•จ์ˆ˜๋ฅผ `await` ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. --- -๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ์ด๊ฒƒ์€ ๋‹น์‹ ์ด ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ฐพ๊ณ ์žˆ๋˜ ๊ฒฝ์šฐ์— ํ•œํ•ด ์œ ์šฉํ•  ๋งค์šฐ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. +๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ์ด๊ฒƒ๋“ค์€ ์•„๋งˆ๋„ ์ด๋ฅผ ์ฐพ๊ณ  ์žˆ์—ˆ๋˜ ๊ฒฝ์šฐ์— ์œ ์šฉํ•œ ๋งค์šฐ ์„ธ๋ถ€์ ์ธ ๊ธฐ์ˆ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. -๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ƒ๊ธฐ์˜ ๊ฐ€์ด๋“œ๋ผ์ธ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: [๋ฐ”์˜์‹  ๊ฒฝ์šฐ](#_1). +๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด, ์œ„ ์„น์…˜์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์ด๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค: ๋ฐ”์˜์‹ ๊ฐ€์š”?. diff --git a/docs/ko/docs/fastapi-cli.md b/docs/ko/docs/fastapi-cli.md index a1160c71fc..0d87ce3219 100644 --- a/docs/ko/docs/fastapi-cli.md +++ b/docs/ko/docs/fastapi-cli.md @@ -1,83 +1,75 @@ -# FastAPI CLI +# FastAPI CLI { #fastapi-cli } -**FastAPI CLI**๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ณ , ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋งจ๋“œ ๋ผ์ธ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. +**FastAPI CLI**๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น™ํ•˜๊ณ , FastAPI ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ์ž‘์—…์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋งจ๋“œ ๋ผ์ธ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. -FastAPI๋ฅผ ์„ค์น˜ํ•  ๋•Œ (์˜ˆ: `pip install "fastapi[standard]"` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ), `fastapi-cli`๋ผ๋Š” ํŒจํ‚ค์ง€๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด ํŒจํ‚ค์ง€๋Š” ํ„ฐ๋ฏธ๋„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” `fastapi` ๋ช…๋ น์–ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. +FastAPI๋ฅผ ์„ค์น˜ํ•  ๋•Œ(์˜ˆ: `pip install "fastapi[standard]"`), `fastapi-cli`๋ผ๋Š” ํŒจํ‚ค์ง€๊ฐ€ ํฌํ•จ๋˜๋ฉฐ, ์ด ํŒจํ‚ค์ง€๋Š” ํ„ฐ๋ฏธ๋„์—์„œ `fastapi` ๋ช…๋ น์–ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -๊ฐœ๋ฐœ์šฉ์œผ๋กœ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด `fastapi dev` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +๊ฐœ๋ฐœ์šฉ์œผ๋กœ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด `fastapi dev` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

```console -$ fastapi dev main.py -INFO Using path main.py -INFO Resolved absolute path /home/user/code/awesomeapp/main.py -INFO Searching for package file structure from directories with __init__.py files -INFO Importing from /home/user/code/awesomeapp - - โ•ญโ”€ Python module file โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ ๐Ÿ main.py โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Importing module main -INFO Found importable FastAPI app - - โ•ญโ”€ Importable FastAPI app โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ from main import app โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Using import string main:app - - โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ - โ”‚ โ”‚ - โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ - โ”‚ โ”‚ - โ”‚ Running in development mode, for production use: โ”‚ - โ”‚ โ”‚ - โ”‚ fastapi run โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2265862] using WatchFiles -INFO: Started server process [2265873] -INFO: Waiting for application startup. -INFO: Application startup complete. +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-`fastapi`๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋ช…๋ น์–ด ํ”„๋กœ๊ทธ๋žจ์€ **FastAPI CLI**์ž…๋‹ˆ๋‹ค. +`fastapi`๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ปค๋งจ๋“œ ๋ผ์ธ ํ”„๋กœ๊ทธ๋žจ์€ **FastAPI CLI**์ž…๋‹ˆ๋‹ค. -FastAPI CLI๋Š” Python ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ๋กœ(์˜ˆ: `main.py`)๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„, `FastAPI` ์ธ์Šคํ„ด์Šค(์ผ๋ฐ˜์ ์œผ๋กœ `app`์œผ๋กœ ๋ช…๋ช…)๋ฅผ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ์ž„ํฌํŠธ ๊ณผ์ •์„ ๊ฒฐ์ •ํ•œ ํ›„ ์ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. +FastAPI CLI๋Š” Python ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ๋กœ(์˜ˆ: `main.py`)๋ฅผ ๋ฐ›์•„ `FastAPI` ์ธ์Šคํ„ด์Šค(์ผ๋ฐ˜์ ์œผ๋กœ `app`์œผ๋กœ ์ด๋ฆ„์„ ๋ถ™์ž„)๋ฅผ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ , ์˜ฌ๋ฐ”๋ฅธ ์ž„ํฌํŠธ ๊ณผ์ •์„ ๊ฒฐ์ •ํ•œ ๋‹ค์Œ ์„œ๋น™ํ•ฉ๋‹ˆ๋‹ค. -ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” `fastapi run` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€ +ํ”„๋กœ๋•์…˜์—์„œ๋Š” ๋Œ€์‹  `fastapi run`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€ -๋‚ด๋ถ€์ ์œผ๋กœ, **FastAPI CLI**๋Š” ๊ณ ์„ฑ๋Šฅ์˜, ํ”„๋กœ๋•์…˜์— ์ ํ•ฉํ•œ, ASGI ์„œ๋ฒ„์ธ Uvicorn์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Ž +๋‚ด๋ถ€์ ์œผ๋กœ **FastAPI CLI**๋Š” ๊ณ ์„ฑ๋Šฅ์˜, ํ”„๋กœ๋•์…˜์— ์ ํ•ฉํ•œ ASGI ์„œ๋ฒ„์ธ Uvicorn์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Ž -## `fastapi dev` +## `fastapi dev` { #fastapi-dev } -`fastapi dev` ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ๊ฐœ๋ฐœ ๋ชจ๋“œ๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. +`fastapi dev`๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ฐœ๋ฐœ ๋ชจ๋“œ๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. -๊ธฐ๋ณธ์ ์œผ๋กœ **์ž๋™ ์žฌ์‹œ์ž‘(auto-reload)** ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜์–ด, ์ฝ”๋“œ์— ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋ฉด ์„œ๋ฒ„๋ฅผ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ธฐ๋Šฅ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉฐ, ๋น„ํ™œ์„ฑํ™”ํ–ˆ์„ ๋•Œ๋ณด๋‹ค ์•ˆ์ •์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์„œ๋ฒ„๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋Š” IP ์ฃผ์†Œ(`localhost`)์ธ `127.0.0.1`์—์„œ ์—ฐ๊ฒฐ์„ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. +๊ธฐ๋ณธ์ ์œผ๋กœ **auto-reload**๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์ฝ”๋“œ์— ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋ฉด ์„œ๋ฒ„๋ฅผ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉฐ, ๋น„ํ™œ์„ฑํ™”ํ–ˆ์„ ๋•Œ๋ณด๋‹ค ์•ˆ์ •์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ปดํ“จํ„ฐ๊ฐ€ ์ž์‹ ๊ณผ๋งŒ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ(`localhost`) IP์ธ `127.0.0.1`์—์„œ ์—ฐ๊ฒฐ์„ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. -## `fastapi run` +## `fastapi run` { #fastapi-run } -`fastapi run` ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ๋กœ FastAPI๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. +`fastapi run`์„ ์‹คํ–‰ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ๋กœ FastAPI๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. -๊ธฐ๋ณธ์ ์œผ๋กœ **์ž๋™ ์žฌ์‹œ์ž‘(auto-reload)** ๊ธฐ๋Šฅ์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  IP ์ฃผ์†Œ์ธ `0.0.0.0`์—์„œ ์—ฐ๊ฒฐ์„ ๋Œ€๊ธฐํ•˜๋ฏ€๋กœ ํ•ด๋‹น ์ปดํ“จํ„ฐ์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๊ณต๊ฐœ์ ์œผ๋กœ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ปจํ…Œ์ด๋„ˆ์™€ ๊ฐ™์€ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +๊ธฐ๋ณธ์ ์œผ๋กœ **auto-reload**๋Š” ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  IP ์ฃผ์†Œ๋ฅผ ์˜๋ฏธํ•˜๋Š” `0.0.0.0`์—์„œ ์—ฐ๊ฒฐ์„ ๋Œ€๊ธฐํ•˜๋ฏ€๋กœ, ํ•ด๋‹น ์ปดํ“จํ„ฐ์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ˆ„๊ตฌ์—๊ฒŒ๋‚˜ ๊ณต๊ฐœ์ ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค. ๋ณดํ†ต ํ”„๋กœ๋•์…˜์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ์‹คํ–‰ํ•˜๋ฉฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. -์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋‹ค๋ฅด์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„ "์ข…๋ฃŒ ํ”„๋ก์‹œ(termination proxy)"๋ฅผ ํ™œ์šฉํ•ด HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ ์„œ๋น„์Šค ์ œ๊ณต์ž๊ฐ€ ์ด ์ž‘์—…์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜๋„ ์žˆ๊ณ , ์ง์ ‘ ์„ค์ •ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์œ„์— "termination proxy"๋ฅผ ๋‘๊ณ  HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ(๊ทธ๋ฆฌ๊ณ  ์ฒ˜๋ฆฌํ•ด์•ผ) ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋ฉฐ, ์ œ๊ณต์ž๊ฐ€ ์ด ์ž‘์—…์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜๋„ ์žˆ๊ณ  ์ง์ ‘ ์„ค์ •ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -/// tip +/// tip | ํŒ -์ž์„ธํ•œ ๋‚ด์šฉ์€ [deployment documentation](deployment/index.md){.internal-link target=\_blank}์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ž์„ธํ•œ ๋‚ด์šฉ์€ [๋ฐฐํฌ ๋ฌธ์„œ](deployment/index.md){.internal-link target=_blank}์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. /// diff --git a/docs/ko/docs/features.md b/docs/ko/docs/features.md index dfbf479998..17cc9289f7 100644 --- a/docs/ko/docs/features.md +++ b/docs/ko/docs/features.md @@ -1,43 +1,43 @@ -# ๊ธฐ๋Šฅ +# ๊ธฐ๋Šฅ { #features } -## FastAPI์˜ ๊ธฐ๋Šฅ +## FastAPI์˜ ๊ธฐ๋Šฅ { #fastapi-features } **FastAPI**๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค: -### ๊ฐœ๋ฐฉํ˜• ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ +### ๊ฐœ๋ฐฉํ˜• ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ { #based-on-open-standards } -* ๊ฒฝ๋กœ์ž‘๋™, ๋งค๊ฐœ๋ณ€์ˆ˜, ๋ณธ๋ฌธ ์š”์ฒญ, ๋ณด์•ˆ ๊ทธ ์™ธ์˜ ์„ ์–ธ์„ ํฌํ•จํ•œ API ์ƒ์„ฑ์„ ์œ„ํ•œ OpenAPI -* JSON Schema (OpenAPI ์ž์ฒด๊ฐ€ JSON Schema๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค)๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๋ฌธ์„œํ™”. -* ๋‹จ์ˆœํžˆ ๋– ์˜ฌ๋ ค์„œ ๋ง๋ถ™์ธ ๊ธฐ๋Šฅ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์„ธ์‹ฌํ•œ ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์นœ ํ›„, ์ด๋Ÿฌํ•œ ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -* ์ด๋Š” ๋˜ํ•œ ๋‹ค์–‘ํ•œ ์–ธ์–ด๋กœ ์ž๋™์ ์ธ **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑ**์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +* OpenAPI: path operations, ๋งค๊ฐœ๋ณ€์ˆ˜, ์š”์ฒญ ๋ณธ๋ฌธ, ๋ณด์•ˆ ๋“ฑ์˜ ์„ ์–ธ์„ ํฌํ•จํ•˜์—ฌ API๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. +* JSON Schema๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๋ฌธ์„œํ™”(OpenAPI ์ž์ฒด๊ฐ€ JSON Schema๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค). +* ๋‹จ์ˆœํžˆ ๋– ์˜ฌ๋ ค์„œ ๋ง๋ถ™์ธ ๋ ˆ์ด์–ด๊ฐ€ ์•„๋‹ˆ๋ผ, ์„ธ์‹ฌํ•œ ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์นœ ๋’ค ์ด๋Ÿฌํ•œ ํ‘œ์ค€์„ ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. +* ์ด๋Š” ๋˜ํ•œ ๋‹ค์–‘ํ•œ ์–ธ์–ด๋กœ ์ž๋™ **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑ**์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. -### ๋ฌธ์„œ ์ž๋™ํ™” +### ๋ฌธ์„œ ์ž๋™ํ™” { #automatic-docs } -๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ์™€ ์›น ํƒ์ƒ‰ ์œ ์ € ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ OpenAPI๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ์—, 2๊ฐ€์ง€ ์˜ต์…˜์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋“ค์–ด๊ฐ„ ์—ฌ๋Ÿฌ ์˜ต์…˜์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. +๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ์™€ ํƒ์ƒ‰์šฉ ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ OpenAPI๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ์— ์—ฌ๋Ÿฌ ์˜ต์…˜์ด ์žˆ์œผ๋ฉฐ, ๊ธฐ๋ณธ์œผ๋กœ 2๊ฐ€์ง€๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. -* ๋Œ€ํ™”ํ˜• ํƒ์ƒ‰ Swagger UI๋ฅผ ์ด์šฉํ•ด, ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฐ”๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋Œ€ํ™”ํ˜• ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•œ Swagger UI๋กœ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ API๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDoc์„ ์ด์šฉํ•ด API ๋ฌธ์„œํ™”๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ReDoc์„ ์ด์šฉํ•œ ๋Œ€์ฒด API ๋ฌธ์„œํ™”. ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ๊ทธ์ € ํ˜„๋Œ€ ํŒŒ์ด์ฌ +### ๊ทธ์ € ํ˜„๋Œ€ ํŒŒ์ด์ฌ { #just-modern-python } -(Pydantic ๋•๋ถ„์—) FastAPI๋Š” ํ‘œ์ค€ **ํŒŒ์ด์ฌ 3.6 ํƒ€์ž…** ์„ ์–ธ์— ๊ธฐ๋ฐ˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ ๋ฐฐ์šธ ๋ฌธ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ์ € ํ‘œ์ค€์ ์ธ ํ˜„๋Œ€ ํŒŒ์ด์ฌ์ž…๋‹ˆ๋‹ค. +( Pydantic ๋•๋ถ„์—) ๋ชจ๋“  ๊ฒƒ์ด ํ‘œ์ค€ **Python ํƒ€์ž…** ์„ ์–ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ ๋ฐฐ์šธ ๋ฌธ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ์ € ํ‘œ์ค€์ ์ธ ํ˜„๋Œ€ ํŒŒ์ด์ฌ์ž…๋‹ˆ๋‹ค. -๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ํŒŒ์ด์ฌ ํƒ€์ž…์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•œ 2๋ถ„ ์ •๋„์˜ ๋ณต์Šต์ด ํ•„์š”ํ•˜๋‹ค๋ฉด (๋น„๋ก ์—ฌ๋Ÿฌ๋ถ„์ด FastAPI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค ํ•˜๋”๋ผ๋„), ๋‹ค์Œ์˜ ์งง์€ ์ž์Šต์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”: [ํŒŒ์ด์ฌ ํƒ€์ž…](python-types.md){.internal-link target=\_blank}. +Python ํƒ€์ž…์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ 2๋ถ„ ์ •๋„ ๋ณต์Šต์ด ํ•„์š”ํ•˜๋‹ค๋ฉด(FastAPI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„), ๋‹ค์Œ์˜ ์งง์€ ์ž์Šต์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”: [Python ํƒ€์ž…](python-types.md){.internal-link target=_blank}. -์—ฌ๋Ÿฌ๋ถ„์€ ํƒ€์ž…์„ ์ด์šฉํ•œ ํ‘œ์ค€ ํŒŒ์ด์ฌ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +์—ฌ๋Ÿฌ๋ถ„์€ ํƒ€์ž…์ด ์žˆ๋Š” ํ‘œ์ค€ Python์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค: ```Python from datetime import date from pydantic import BaseModel -# ๋ณ€์ˆ˜๋ฅผ str๋กœ ์„ ์–ธ -# ๊ทธ ํ›„ ํ•จ์ˆ˜ ์•ˆ์—์„œ ํŽธ์ง‘๊ธฐ ์ง€์›์„ ๋ฐ›์œผ์„ธ์š” +# ๋ณ€์ˆ˜๋ฅผ str๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค +# ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ํŽธ์ง‘๊ธฐ ์ง€์›์„ ๋ฐ›์Šต๋‹ˆ๋‹ค def main(user_id: str): return user_id @@ -49,7 +49,7 @@ class User(BaseModel): joined: date ``` -์œ„์˜ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +๊ทธ ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") @@ -65,23 +65,23 @@ my_second_user: User = User(**second_user_data) /// info | ์ •๋ณด -`**second_user_data`๊ฐ€ ๋œปํ•˜๋Š” ๊ฒƒ: +`**second_user_data`๋Š” ๋‹ค์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค: -`second_user_data` ๋”•์…”๋„ˆ๋ฆฌ์˜ ํ‚ค์™€ ๊ฐ’์„ ํ‚ค-๊ฐ’ ์ธ์ž๋กœ์„œ ๋ฐ”๋กœ ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค: `User(id=4, name="Mary", joined="2018-11-30")` +`second_user_data` `dict`์˜ ํ‚ค์™€ ๊ฐ’์„ ํ‚ค-๊ฐ’ ์ธ์ž๋กœ์„œ ๋ฐ”๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ์œผ๋กœ, ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค: `User(id=4, name="Mary", joined="2018-11-30")` /// -### ํŽธ์ง‘๊ธฐ ์ง€์› +### ํŽธ์ง‘๊ธฐ ์ง€์› { #editor-support } -๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ์ง๊ด€์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, ์ข‹์€ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•˜๊ธฐ๋„ ์ „์— ๋ชจ๋“  ๊ฒฐ์ •๋“ค์€ ์—ฌ๋Ÿฌ ํŽธ์ง‘๊ธฐ์—์„œ ํ…Œ์ŠคํŠธ๋ฉ๋‹ˆ๋‹ค. +ํ”„๋ ˆ์ž„์›Œํฌ ์ „์ฒด๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ์ง๊ด€์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, ์ตœ๊ณ ์˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•˜๊ธฐ๋„ ์ „์— ๋ชจ๋“  ๊ฒฐ์ •์€ ์—ฌ๋Ÿฌ ํŽธ์ง‘๊ธฐ์—์„œ ํ…Œ์ŠคํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -์ตœ๊ทผ ํŒŒ์ด์ฌ ๊ฐœ๋ฐœ์ž ์„ค๋ฌธ์กฐ์‚ฌ์—์„œ "์ž๋™ ์™„์„ฑ"์ด ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ์ด๋ผ๋Š” ๊ฒƒ์ด ๋ฐํ˜€์กŒ์Šต๋‹ˆ๋‹ค. +Python ๊ฐœ๋ฐœ์ž ์„ค๋ฌธ์กฐ์‚ฌ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๊ฐ€ "์ž๋™ ์™„์„ฑ"์ด๋ผ๋Š” ์ ์ด ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค. -**FastAPI** ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์€ ์ด๋ฅผ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ž๋™์™„์„ฑ์€ ์–ด๋А ๊ณณ์—์„œ๋‚˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. +**FastAPI** ํ”„๋ ˆ์ž„์›Œํฌ ์ „์ฒด๋Š” ์ด๋ฅผ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ž๋™ ์™„์„ฑ์€ ์–ด๋””์„œ๋‚˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. -์—ฌ๋Ÿฌ๋ถ„์€ ๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ผ์ด ๊ฑฐ์˜ ์—†์„ ๊ฒ๋‹ˆ๋‹ค. +๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ผ์€ ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๋‹ค์Œ์€ ํŽธ์ง‘๊ธฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์—ฌ๋Ÿฌ๋ถ„์„ ๋„์™€์ฃผ๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค: +ํŽธ์ง‘๊ธฐ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์„ ์–ด๋–ป๊ฒŒ ๋„์™€์ค„ ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด์„ธ์š”: * Visual Studio Code์—์„œ: @@ -91,111 +91,111 @@ my_second_user: User = User(**second_user_data) ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -์—ฌ๋Ÿฌ๋ถ„์ด ์ด์ „์— ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ๊ณ ๋ คํ–ˆ๋˜ ์ฝ”๋“œ๋„ ์™„์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์š”์ฒญ์—์„œ ์ „๋‹ฌ๋˜๋Š” (์ค‘์ฒฉ๋  ์ˆ˜๋„ ์žˆ๋Š”)JSON ๋ณธ๋ฌธ ๋‚ด๋ถ€์— ์žˆ๋Š” `price` ํ‚ค์ž…๋‹ˆ๋‹ค. +์ด์ „์— ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์„ ์ฝ”๋“œ์—์„œ๋„ ์ž๋™ ์™„์„ฑ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์š”์ฒญ์—์„œ ์ „๋‹ฌ๋˜๋Š”(์ค‘์ฒฉ๋  ์ˆ˜๋„ ์žˆ๋Š”) JSON ๋ณธ๋ฌธ ๋‚ด๋ถ€์˜ `price` ํ‚ค ๊ฐ™์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. -์ž˜๋ชป๋œ ํ‚ค ์ด๋ฆ„์„ ์ ์„ ์ผ๋„, ๋ฌธ์„œ๋ฅผ ์™”๋‹ค ๊ฐ”๋‹คํ•  ์ผ๋„ ์—†์œผ๋ฉฐ, ํ˜น์€ ๋งˆ์ง€๋ง‰์œผ๋กœ `username` ๋˜๋Š” `user_name`์„ ์‚ฌ์šฉํ–ˆ๋Š”์ง€ ์ฐพ๊ธฐ ์œ„ํ•ด ์œ„ ์•„๋ž˜๋กœ ์Šคํฌ๋กคํ•  ์ผ๋„ ์—†์Šต๋‹ˆ๋‹ค. +๋” ์ด์ƒ ์ž˜๋ชป๋œ ํ‚ค ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜, ๋ฌธ์„œ ์‚ฌ์ด๋ฅผ ์™”๋‹ค ๊ฐ”๋‹ค ํ•˜๊ฑฐ๋‚˜, `username`์„ ์ผ๋Š”์ง€ `user_name`์„ ์ผ๋Š”์ง€ ์ฐพ์œผ๋ ค๊ณ  ์œ„์•„๋ž˜๋กœ ์Šคํฌ๋กคํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. -### ํ† ๋ง‰ ์ •๋ณด +### ๊ฐ„๊ฒฐํ•จ { #short } -์–ด๋А ๊ณณ์—์„œ๋‚˜ ์„ ํƒ์  ๊ตฌ์„ฑ์ด ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ฒƒ์— ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์ด ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ์›ํ•˜๋Š” API๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฏธ์„ธํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์„ ํƒ์  ๊ตฌ์„ฑ์„ ์–ด๋””์„œ๋‚˜ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด์„œ๋„, ๋ชจ๋“  ๊ฒƒ์— ํ•ฉ๋ฆฌ์ ์ธ **๊ธฐ๋ณธ๊ฐ’**์ด ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•„์š”ํ•œ ์ž‘์—…์„ ํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ API๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋ฏธ์„ธํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์ด "๊ทธ๋ƒฅ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค". +ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์ด **"๊ทธ๋ƒฅ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค"**. -### ๊ฒ€์ฆ +### ๊ฒ€์ฆ { #validation } -* ๋‹ค์Œ์„ ํฌํ•จํ•œ, ๋Œ€๋ถ€๋ถ„์˜ (ํ˜น์€ ๋ชจ๋“ ?) ํŒŒ์ด์ฌ **๋ฐ์ดํ„ฐ ํƒ€์ž…** ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +* ๋‹ค์Œ์„ ํฌํ•จํ•ด ๋Œ€๋ถ€๋ถ„(ํ˜น์€ ์ „๋ถ€?)์˜ Python **๋ฐ์ดํ„ฐ ํƒ€์ž…**์— ๋Œ€ํ•œ ๊ฒ€์ฆ: * JSON ๊ฐ์ฒด (`dict`). * ์•„์ดํ…œ ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š” JSON ๋ฐฐ์—ด (`list`). - * ์ตœ์†Œ ๊ธธ์ด์™€ ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฌธ์ž์—ด (`str`) ํ•„๋“œ. - * ์ตœ์†Ÿ๊ฐ’๊ณผ ์ตœ๋Œ“๊ฐ’์„ ๊ฐ€์ง€๋Š” ์ˆซ์ž (`int`, `float`), ๊ทธ ์™ธ. + * ์ตœ์†Œ/์ตœ๋Œ€ ๊ธธ์ด๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฌธ์ž์—ด(`str`) ํ•„๋“œ. + * ์ตœ์†Œ/์ตœ๋Œ€ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์ˆซ์ž(`int`, `float`) ๋“ฑ. -* ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋”์šฑ ์ด์ƒ‰์ ์ธ ํƒ€์ž…์— ๋Œ€ํ•ด ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +* ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ข€ ๋” ์ด์ƒ‰์ ์ธ ํƒ€์ž…์— ๋Œ€ํ•œ ๊ฒ€์ฆ: * URL. - * ์ด๋ฉ”์ผ. + * Email. * UUID. - * ...๋‹ค๋ฅธ ๊ฒƒ๋“ค. + * ...๊ทธ ์™ธ. -๋ชจ๋“  ๊ฒ€์ฆ์€ ๊ฒฌ๊ณ ํ•˜๋ฉด์„œ ์ž˜ ํ™•๋ฆฝ๋œ **Pydantic**์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. +๋ชจ๋“  ๊ฒ€์ฆ์€ ์ž˜ ํ™•๋ฆฝ๋˜์–ด ์žˆ๊ณ  ๊ฒฌ๊ณ ํ•œ **Pydantic**์ด ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -### ๋ณด์•ˆ๊ณผ ์ธ์ฆ +### ๋ณด์•ˆ๊ณผ ์ธ์ฆ { #security-and-authentication } -๋ณด์•ˆ๊ณผ ์ธ์ฆ์ด ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๊ณผ์˜ ํƒ€ํ˜‘์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋ณด์•ˆ๊ณผ ์ธ์ฆ์ด ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๊ณผ ํƒ€ํ˜‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -๋‹ค์Œ์„ ํฌํ•จํ•˜๋Š”, ๋ชจ๋“  ๋ณด์•ˆ ์Šคํ‚ค๋งˆ๊ฐ€ OpenAPI์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹ค์Œ์„ ํฌํ•จํ•ด OpenAPI์— ์ •์˜๋œ ๋ชจ๋“  ๋ณด์•ˆ ์Šคํ‚ค๋งˆ: * HTTP Basic. -* **OAuth2** (**JWT tokens** ๋˜ํ•œ ํฌํ•จ). [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=\_blank}์— ์žˆ๋Š” ์ž์Šต์„œ๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”. +* **OAuth2**(**JWT tokens** ๋˜ํ•œ ํฌํ•จ). [JWT๋ฅผ ์‚ฌ์šฉํ•œ OAuth2](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ์ž์Šต์„œ๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”. * ๋‹ค์Œ์— ๋“ค์–ด ์žˆ๋Š” API ํ‚ค: * ํ—ค๋”. - * ๋งค๊ฐœ๋ณ€์ˆ˜. - * ์ฟ ํ‚ค ๋ฐ ๊ทธ ์™ธ. + * ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜. + * ์ฟ ํ‚ค ๋“ฑ. -์ถ”๊ฐ€์ ์œผ๋กœ (**์„ธ์…˜ ์ฟ ํ‚ค**๋ฅผ ํฌํ•จํ•œ) ๋ชจ๋“  ๋ณด์•ˆ ๊ธฐ๋Šฅ์€ Starlette์— ์žˆ์Šต๋‹ˆ๋‹ค. +์ถ”๊ฐ€๋กœ Starlette์˜ ๋ชจ๋“  ๋ณด์•ˆ ๊ธฐ๋Šฅ(**์„ธ์…˜ ์ฟ ํ‚ค** ํฌํ•จ)๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. -๋ชจ๋‘ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์™€ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ์–ด ์—ฌ๋Ÿฌ๋ถ„์˜ ์‹œ์Šคํ…œ, ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ, ๊ด€๊ณ„ํ˜• ๋ฐ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋ชจ๋‘ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋„๊ตฌ์™€ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ์–ด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์‹œ์Šคํ…œ, ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ, ๊ด€๊ณ„ํ˜• ๋ฐ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### ์˜์กด์„ฑ ์ฃผ์ž… +### ์˜์กด์„ฑ ์ฃผ์ž… { #dependency-injection } -FastAPI๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ๋งค์šฐ ๊ฐ„ํŽธํ•˜์ง€๋งŒ, ์—„์ฒญ๋‚œ ์˜์กด์„ฑ ์ฃผ์ž…์‹œ์Šคํ…œ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +FastAPI๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ๋งค์šฐ ์‰ฝ์ง€๋งŒ, ๋งค์šฐ ๊ฐ•๋ ฅํ•œ Dependency Injection ์‹œ์Šคํ…œ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -* ์˜์กด์„ฑ์€ ์˜์กด์„ฑ์„ ๊ฐ€์งˆ์ˆ˜๋„ ์žˆ์–ด, ์ด๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์˜ ๊ณ„์ธต์ด๋‚˜ **์˜์กด์„ฑ์˜ "๊ทธ๋ž˜ํ”„"**๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค. -* ๋ชจ๋“  ๊ฒƒ์ด ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด **์ž๋™์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค**. -* ๋ชจ๋“  ์˜์กด์„ฑ์€ ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”๊ตฌํ•˜์—ฌ ์ž๋™ ๋ฌธ์„œํ™”์™€ **๊ฒฝ๋กœ ์ž‘๋™ ์ œ์•ฝ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค**. -* ์˜์กด์„ฑ์—์„œ ์ •์˜๋œ _๊ฒฝ๋กœ ์ž‘๋™_ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด์„œ๋„ **์ž๋™ ๊ฒ€์ฆ**์ด ์ด๋ฃจ์–ด ์ง‘๋‹ˆ๋‹ค. -* ๋ณต์žกํ•œ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์‹œ์Šคํ…œ, **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ**, ๋“ฑ๋“ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. -* ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ํ”„๋ก ํŠธ์—”๋“œ ๋“ฑ๊ณผ ๊ด€๋ จ๋˜์–ด **ํƒ€ํ˜‘ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค**. ํ•˜์ง€๋งŒ ๊ทธ ๋ชจ๋“  ๊ฒƒ๊ณผ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +* ์˜์กด์„ฑ๋„ ์˜์กด์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์–ด, ์˜์กด์„ฑ์˜ ๊ณ„์ธต ๋˜๋Š” **์˜์กด์„ฑ์˜ "๊ทธ๋ž˜ํ”„"**๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. +* ๋ชจ๋“  ๊ฒƒ์ด ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด **์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค**. +* ๋ชจ๋“  ์˜์กด์„ฑ์€ ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”๊ตฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ** ์ œ์•ฝ๊ณผ ์ž๋™ ๋ฌธ์„œํ™”๋ฅผ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ์˜์กด์„ฑ์— ์ •์˜๋œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด์„œ๋„ **์ž๋™ ๊ฒ€์ฆ**์„ ํ•ฉ๋‹ˆ๋‹ค. +* ๋ณต์žกํ•œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์‹œ์Šคํ…œ, **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ** ๋“ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +* ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ํ”„๋ก ํŠธ์—”๋“œ ๋“ฑ๊ณผ **ํƒ€ํ˜‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ํ•˜์ง€๋งŒ ๋ชจ๋‘์™€ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### ์ œํ•œ ์—†๋Š” "ํ”Œ๋Ÿฌ๊ทธ์ธ" +### ์ œํ•œ ์—†๋Š” "ํ”Œ๋Ÿฌ๊ทธ์ธ" { #unlimited-plug-ins } -๋˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ, ๊ทธ๊ฒƒ๋“ค์„ ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋˜ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ๋Š”, ๊ทธ๊ฒƒ๋“ค์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ž„ํฌํŠธํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. -์–ด๋А ํ†ตํ•ฉ๋„ (์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜) ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๊ณ„๋˜์–ด ์žˆ์–ด, *๊ฒฝ๋กœ ์ž‘๋™*์— ์‚ฌ์šฉ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ตฌ์กฐ์™€ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ 2์ค„์˜ ์ฝ”๋“œ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์‚ฌ์šฉํ•  "ํ”Œ๋Ÿฌ๊ทธ์ธ"์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์–ด๋–ค ํ†ตํ•ฉ์ด๋“ (์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜) ์‚ฌ์šฉํ•˜๊ธฐ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์‚ฌ์šฉ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ตฌ์กฐ์™€ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•ด 2์ค„์˜ ์ฝ”๋“œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์šฉ "ํ”Œ๋Ÿฌ๊ทธ์ธ"์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ +### ํ…Œ์ŠคํŠธ๋จ { #tested } -* 100% ํ…Œ์ŠคํŠธ ๋ฒ”์œ„. -* 100% ํƒ€์ž…์ด ๋ช…์‹œ๋œ ์ฝ”๋“œ ๋ฒ ์ด์Šค. -* ์ƒ์šฉ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ์˜ ์‚ฌ์šฉ. +* 100% test coverage. +* 100% type annotated ์ฝ”๋“œ ๋ฒ ์ด์Šค. +* ํ”„๋กœ๋•์…˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -## Starlette ๊ธฐ๋Šฅ +## Starlette ๊ธฐ๋Šฅ { #starlette-features } -**FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋˜์—ˆ์œผ๋ฉฐ, ์ด์™€ ์™„์ „ํžˆ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์—ฌ๋Ÿฌ๋ถ„์ด ๋ณด์œ ํ•˜๊ณ  ์žˆ๋Š” ์–ด๋–ค ์ถ”๊ฐ€์ ์ธ Starlette ์ฝ”๋“œ๋„ ์ž‘๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +**FastAPI**๋Š” Starlette์™€ ์™„์ „ํžˆ ํ˜ธํ™˜๋˜๋ฉฐ(๋˜ํ•œ ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค). ๋”ฐ๋ผ์„œ ์ถ”๊ฐ€๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Starlette ์ฝ”๋“œ๋„ ๋ชจ๋‘ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. -`FastAPI`๋Š” ์‹ค์ œ๋กœ `Starlette`์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ, ์—ฌ๋Ÿฌ๋ถ„์ด ์ด๋ฏธ Starlette์„ ์•Œ๊ณ  ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉด, ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์ด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +`FastAPI`๋Š” ์‹ค์ œ๋กœ `Starlette`์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Starlette์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์ด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ **Starlette**์˜ ๊ธฐ๋Šฅ ๋Œ€๋ถ€๋ถ„์„ ์–ป๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค(FastAPI๊ฐ€ ๋‹จ์ˆœํžˆ Starlette๋ฅผ ๊ฐ•ํ™”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค): +**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด **Starlette**์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค(FastAPI๋Š” Starlette์— ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๋”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค): -* ์•„์ฃผ ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ. ์ด๋Š” **NodeJS**์™€ **Go**์™€ ๋™๋“ฑํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋น ๋ฅธ ํŒŒ์ด์ฌ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. +* ์ •๋ง ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ. **NodeJS**์™€ **Go**์— ๋ฒ„๊ธˆ๊ฐ€๋Š”, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋น ๋ฅธ Python ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. * **WebSocket** ์ง€์›. -* ํ”„๋กœ์„ธ์Šค ๋‚ด์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…. -* ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ ์ด๋ฒคํŠธ. +* ํ”„๋กœ์„ธ์Šค ๋‚ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…. +* ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ์ด๋ฒคํŠธ. * HTTPX ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ํด๋ผ์ด์–ธํŠธ. * **CORS**, GZip, ์ •์  ํŒŒ์ผ, ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต. * **์„ธ์…˜๊ณผ ์ฟ ํ‚ค** ์ง€์›. -* 100% ํ…Œ์ŠคํŠธ ๋ฒ”์œ„. -* 100% ํƒ€์ž…์ด ๋ช…์‹œ๋œ ์ฝ”๋“œ ๋ฒ ์ด์Šค. +* 100% test coverage. +* 100% type annotated codebase. -## Pydantic ๊ธฐ๋Šฅ +## Pydantic ๊ธฐ๋Šฅ { #pydantic-features } -**FastAPI**๋Š” Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ Pydantic๊ณผ ์™„๋ฒฝํ•˜๊ฒŒ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋А ์ถ”๊ฐ€์ ์ธ Pydantic ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฐ€์ง€๊ณ  ์žˆ๋“  ์ž‘๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +**FastAPI**๋Š” Pydantic๊ณผ ์™„๋ฒฝํ•˜๊ฒŒ ํ˜ธํ™˜๋˜๋ฉฐ(๋˜ํ•œ ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค). ๋”ฐ๋ผ์„œ ์ถ”๊ฐ€๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Pydantic ์ฝ”๋“œ๋„ ๋ชจ๋‘ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. -Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š”, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์œ„ํ•œ ORM, ODM์„ ํฌํ•จํ•œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์œ„ํ•œ ORM, ODM๊ณผ ๊ฐ™์€, Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. -์ด๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ž๋™์œผ๋กœ ๊ฒ€์ฆ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋งŽ์€ ๊ฒฝ์šฐ์—์„œ ์š”์ฒญ์„ ํ†ตํ•ด ์–ป์€ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ, **์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ** ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ž๋™์œผ๋กœ ๊ฒ€์ฆ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋งŽ์€ ๊ฒฝ์šฐ ์š”์ฒญ์—์„œ ์–ป์€ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ **์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ** ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. -๋ฐ˜๋Œ€๋กœ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ **์ง์ ‘ ํด๋ผ์ด์–ธํŠธ๋กœ** ๊ทธ์ € ๊ฐ์ฒด๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋ฐ˜๋Œ€๋กœ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์–ป์€ ๊ฐ์ฒด๋ฅผ **์ง์ ‘ ํด๋ผ์ด์–ธํŠธ๋กœ** ๊ทธ๋Œ€๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด (๋ชจ๋“  ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด FastAPI๊ฐ€ Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ ์žˆ๊ธฐ์—) **Pydantic**์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: +**FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด(๋ชจ๋“  ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด FastAPI๊ฐ€ Pydantic์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ์—) **Pydantic**์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: -* **์–ด๋ ต์ง€ ์•Š์€ ์–ธ์–ด**: - * ์ƒˆ๋กœ์šด ์Šคํ‚ค๋งˆ ์ •์˜ ๋งˆ์ดํฌ๋กœ ์–ธ์–ด๋ฅผ ๋ฐฐ์šฐ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. - * ์—ฌ๋Ÿฌ๋ถ„์ด ํŒŒ์ด์ฌ ํƒ€์ž…์„ ์•ˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ Pydantic์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•„๋Š” ๊ฒ๋‹ˆ๋‹ค. -* ์—ฌ๋Ÿฌ๋ถ„์˜ **IDE/๋ฆฐํ„ฐ/๋‡Œ**์™€ ์ž˜ ์–ด์šธ๋ฆฝ๋‹ˆ๋‹ค: - * Pydantic ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ๋‹จ์ˆœ ์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ž๋™ ์™„์„ฑ, ๋ฆฐํŒ…, mypy ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„์˜ ์ง๊ด€๊นŒ์ง€ ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฒ€์ฆ๋œ ๋ฐ์ดํ„ฐ์™€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. +* **No brainfuck**: + * ์ƒˆ๋กœ์šด ์Šคํ‚ค๋งˆ ์ •์˜ ๋งˆ์ดํฌ๋กœ ์–ธ์–ด๋ฅผ ๋ฐฐ์šธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + * Python ํƒ€์ž…์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด Pydantic ์‚ฌ์šฉ๋ฒ•๋„ ์•Œ๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. +* ์—ฌ๋Ÿฌ๋ถ„์˜ **IDE/linter/๋‡Œ**์™€ ์ž˜ ์–ด์šธ๋ฆฝ๋‹ˆ๋‹ค: + * pydantic ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์ผ ๋ฟ์ด๋ฏ€๋กœ, ์ž๋™ ์™„์„ฑ, ๋ฆฐํŒ…, mypy, ๊ทธ๋ฆฌ๊ณ  ์ง๊ด€๊นŒ์ง€๋„ ๊ฒ€์ฆ๋œ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. * **๋ณต์žกํ•œ ๊ตฌ์กฐ**๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค: - * ๊ณ„์ธต์ ์ธ Pydantic ๋ชจ๋ธ, ํŒŒ์ด์ฌ `typing`์˜ `List`์™€ `Dict`, ๊ทธ ์™ธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - * ๊ทธ๋ฆฌ๊ณ  ๊ฒ€์ฆ์ž๋Š” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ๋ฅผ ๋ช…ํ™•ํ•˜๊ณ  ์‰ฝ๊ฒŒ ์ •์˜ ๋ฐ ํ™•์ธํ•˜๋ฉฐ JSON ์Šคํ‚ค๋งˆ๋กœ ๋ฌธ์„œํ™”ํ•ฉ๋‹ˆ๋‹ค. - * ์—ฌ๋Ÿฌ๋ถ„์€ ๊นŠ๊ฒŒ **์ค‘์ฒฉ๋œ JSON** ๊ฐ์ฒด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ๊ฐ์ฒด ๋ชจ๋‘ ๊ฒ€์ฆํ•˜๊ณ  ์„ค๋ช…์„ ๋ถ™์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* **ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ**: - * Pydantic์€ ์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ฑฐ๋‚˜, ๊ฒ€์ฆ์ž ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ๋ถ™์€ ๋ชจ๋ธ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ฆ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* 100% ํ…Œ์ŠคํŠธ ๋ฒ”์œ„. + * ๊ณ„์ธต์ ์ธ Pydantic ๋ชจ๋ธ, Python `typing`์˜ `List`์™€ `Dict` ๋“ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + * ๊ทธ๋ฆฌ๊ณ  validator๋Š” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ๋ฅผ ๋ช…ํ™•ํ•˜๊ณ  ์‰ฝ๊ฒŒ ์ •์˜ํ•˜๊ณ , ๊ฒ€์‚ฌํ•˜๊ณ , JSON Schema๋กœ ๋ฌธ์„œํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. + * ๊นŠ๊ฒŒ **์ค‘์ฒฉ๋œ JSON** ๊ฐ์ฒด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ๋ชจ๋‘ ๊ฒ€์ฆํ•˜๊ณ  ์ฃผ์„์„ ๋‹ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **ํ™•์žฅ ๊ฐ€๋Šฅ**: + * Pydantic์€ ์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ฑฐ๋‚˜, validator decorator๊ฐ€ ๋ถ™์€ ๋ชจ๋ธ ๋ฉ”์„œ๋“œ๋กœ ๊ฒ€์ฆ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* 100% test coverage. diff --git a/docs/ko/docs/help-fastapi.md b/docs/ko/docs/help-fastapi.md index b65ef959cb..a4abbe7afa 100644 --- a/docs/ko/docs/help-fastapi.md +++ b/docs/ko/docs/help-fastapi.md @@ -1,4 +1,4 @@ -# FastAPI ์ง€์› - ๋„์›€ ๋ฐ›๊ธฐ +# FastAPI ์ง€์› - ๋„์›€ ๋ฐ›๊ธฐ { #help-fastapi-get-help } **FastAPI** ๊ฐ€ ๋งˆ์Œ์— ๋“œ์‹œ๋‚˜์š”? @@ -10,9 +10,9 @@ FastAPI, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž, ๊ฐœ๋ฐœ์ž๋ฅผ ์‘์›ํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? ๋˜ํ•œ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋„ ๋ช‡ ๊ฐ€์ง€ ์žˆ์Šต๋‹ˆ๋‹ค. -## ๋‰ด์Šค๋ ˆํ„ฐ ๊ตฌ๋… +## ๋‰ด์Šค๋ ˆํ„ฐ ๊ตฌ๋… { #subscribe-to-the-newsletter } -[**FastAPI and friends** ๋‰ด์Šค๋ ˆํ„ฐ](newsletter.md){.internal-link target=\_blank}๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ์ตœ์‹  ์ •๋ณด๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +(์ž์ฃผ ๋ฐœ์†ก๋˜์ง€ ์•Š๋Š”) [**FastAPI and friends** ๋‰ด์Šค๋ ˆํ„ฐ](newsletter.md){.internal-link target=_blank}๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ์ตœ์‹  ์ •๋ณด๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: * FastAPI and friends์— ๋Œ€ํ•œ ๋‰ด์Šค ๐Ÿš€ * ๊ฐ€์ด๋“œ ๐Ÿ“ @@ -20,65 +20,65 @@ FastAPI, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž, ๊ฐœ๋ฐœ์ž๋ฅผ ์‘์›ํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? * ํš๊ธฐ์ ์ธ ๋ณ€ํ™” ๐Ÿšจ * ํŒ๊ณผ ์š”๋ น โœ… -## ํŠธ์œ„ํ„ฐ์—์„œ FastAPI ํŒ”๋กœ์šฐํ•˜๊ธฐ +## X(Twitter)์—์„œ FastAPI ํŒ”๋กœ์šฐํ•˜๊ธฐ { #follow-fastapi-on-x-twitter } **X (Twitter)**์˜ @fastapi๋ฅผ ํŒ”๋กœ์šฐํ•˜์—ฌ **FastAPI** ์— ๋Œ€ํ•œ ์ตœ์‹  ๋‰ด์Šค๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿฆ -## Star **FastAPI** in GitHub +## GitHub์—์„œ **FastAPI**์— Star ์ฃผ๊ธฐ { #star-fastapi-in-github } GitHub์—์„œ FastAPI์— "star"๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ์˜ star ๋ฒ„ํŠผ์„ ํด๋ฆญ): https://github.com/fastapi/fastapi. โญ๏ธ ์Šคํƒ€๋ฅผ ๋Š˜๋ฆผ์œผ๋กœ์จ, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋“ค์ด ์ข€ ๋” ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๊ณ , ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์œ ์šฉํ•œ ๊ฒƒ์ž„์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## GitHub ์ €์žฅ์†Œ์—์„œ ๋ฆด๋ฆฌ์ฆˆ ํ™•์ธ +## ๋ฆด๋ฆฌ์ฆˆ ํ™•์ธ์„ ์œ„ํ•ด GitHub ์ €์žฅ์†Œ ๋ณด๊ธฐ { #watch-the-github-repository-for-releases } -GitHub์—์„œ FastAPI๋ฅผ "watch"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ watch ๋ฒ„ํŠผ์„ ํด๋ฆญ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ +GitHub์—์„œ FastAPI๋ฅผ "watch"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ "watch" ๋ฒ„ํŠผ์„ ํด๋ฆญ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ -์—ฌ๊ธฐ์„œ "Releases only"์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์—ฌ๊ธฐ์„œ "Releases only"๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์ด๋ ‡๊ฒŒํ•˜๋ฉด, **FastAPI** ์˜ ๋ฒ„๊ทธ ์ˆ˜์ • ๋ฐ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์˜ ๊ตฌํ˜„ ๋“ฑ์˜ ์ƒˆ๋กœ์šด ์ž๋ฃŒ (์ตœ์‹  ๋ฒ„์ „)์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค (์ด๋ฉ”์ผ) ํ†ต์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋ ‡๊ฒŒํ•˜๋ฉด, **FastAPI** ์˜ ๋ฒ„๊ทธ ์ˆ˜์ • ๋ฐ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์˜ ๊ตฌํ˜„ ๋“ฑ์˜ ์ƒˆ๋กœ์šด ๋ฆด๋ฆฌ์ฆˆ(์ƒˆ ๋ฒ„์ „)๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค (์ด๋ฉ”์ผ) ํ†ต์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ๊ฐœ๋ฐœ์ž์™€์˜ ์—ฐ๊ฒฐ +## ๊ฐœ๋ฐœ์ž์™€์˜ ์—ฐ๊ฒฐ { #connect-with-the-author } -๊ฐœ๋ฐœ์ž(Sebastiรกn Ramรญrez / `tiangolo`)์™€ ์—ฐ๋ฝ์„ ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ฐœ๋ฐœ์ž(์ž‘์„ฑ์ž)์ธ ์ €(Sebastiรกn Ramรญrez / `tiangolo`)์™€ ์—ฐ๋ฝ์„ ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -* **GitHub**์—์„œ ํŒ”๋กœ์šฐํ•˜๊ธฐ.. - * ๋‹น์‹ ์—๊ฒŒ ๋„์›€์ด ๋  ์ €์˜ ๋‹ค๋ฅธ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. +* **GitHub**์—์„œ ํŒ”๋กœ์šฐํ•˜๊ธฐ. + * ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ๋„์›€์ด ๋  ์ €์˜ ๋‹ค๋ฅธ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. * ์ƒˆ๋กœ์šด ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์„ ๋•Œ ํ™•์ธํ•˜๋ ค๋ฉด ํŒ”๋กœ์šฐ ํ•˜์‹ญ์‹œ์˜ค. * **X (Twitter)** ๋˜๋Š” Mastodon์—์„œ ํŒ”๋กœ์šฐํ•˜๊ธฐ. * FastAPI์˜ ์‚ฌ์šฉ ์šฉ๋„๋ฅผ ์•Œ๋ ค์ฃผ์„ธ์š” (๊ทธ๊ฒƒ์„ ๋“ฃ๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค). * ๋ฐœํ‘œ๋‚˜ ์ƒˆ๋กœ์šด ํˆด ์ถœ์‹œ ์†Œ์‹์„ ๋ฐ›์•„๋ณด์‹ญ์‹œ์˜ค. - * **X (Twitter)**์˜ @fastapi๋ฅผ ํŒ”๋กœ์šฐ (๋ณ„๋„ ๊ณ„์ •์—์„œ) ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* **LinkedIn**์—์„œ ํŒ”๋กœ์šฐํ•˜๊ธฐ.. - * ์ƒˆ๋กœ์šด ํˆด์˜ ๋ฐœํ‘œ๋‚˜ ์ถœ์‹œ ์†Œ์‹์„ ๋ฐ›์•„๋ณด์‹ญ์‹œ์˜ค. (๋‹จ, X (Twitter)๋ฅผ ๋” ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค ๐Ÿคทโ€โ™‚). + * X(Twitter)์—์„œ @fastapi๋ฅผ ํŒ”๋กœ์šฐ (๋ณ„๋„ ๊ณ„์ •์—์„œ) ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* **LinkedIn**์—์„œ ํŒ”๋กœ์šฐํ•˜๊ธฐ. + * ์ƒˆ๋กœ์šด ํˆด์˜ ๋ฐœํ‘œ๋‚˜ ์ถœ์‹œ ์†Œ์‹์„ ๋ฐ›์•„๋ณด์‹ญ์‹œ์˜ค (๋‹จ, X (Twitter)๋ฅผ ๋” ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค ๐Ÿคทโ€โ™‚). * **Dev.to** ๋˜๋Š” **Medium**์—์„œ ์ œ๊ฐ€ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์„ ์ฝ์–ด ๋ณด์‹ญ์‹œ์˜ค (๋˜๋Š” ํŒ”๋กœ์šฐ). - * ๋‹ค๋ฅธ ๊ธฐ์‚ฌ๋‚˜ ์•„์ด๋””์–ด๋“ค์„ ์ฝ๊ณ , ์ œ๊ฐ€ ๋งŒ๋“ค์–ด์™”๋˜ ํˆด์— ๋Œ€ํ•ด์„œ๋„ ์ฝ์œผ์‹ญ์‹œ์˜ค. - * ์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ๋ฅผ ์ฝ๊ธฐ ์œ„ํ•ด ํŒ”๋กœ์šฐ ํ•˜์‹ญ์‹œ์˜ค. + * ๋‹ค๋ฅธ ์•„์ด๋””์–ด์™€ ๊ธฐ์‚ฌ๋“ค์„ ์ฝ๊ณ , ์ œ๊ฐ€ ๋งŒ๋“ค์–ด์™”๋˜ ํˆด์— ๋Œ€ํ•ด์„œ๋„ ์ฝ์œผ์‹ญ์‹œ์˜ค. + * ์ƒˆ๋กœ์šด ๋‚ด์šฉ์„ ๊ฒŒ์‹œํ•  ๋•Œ ์ฝ๊ธฐ ์œ„ํ•ด ํŒ”๋กœ์šฐ ํ•˜์‹ญ์‹œ์˜ค. -## **FastAPI**์— ๋Œ€ํ•œ ํŠธ์œ— +## **FastAPI**์— ๋Œ€ํ•ด ํŠธ์œ—ํ•˜๊ธฐ { #tweet-about-fastapi } -**FastAPI**์— ๋Œ€ํ•ด ํŠธ์œ— ํ•˜๊ณ  FastAPI๊ฐ€ ๋งˆ์Œ์— ๋“œ๋Š” ์ด์œ ๋ฅผ ์•Œ๋ ค์ฃผ์„ธ์š”. ๐ŸŽ‰ +**FastAPI**์— ๋Œ€ํ•ด ํŠธ์œ— ํ•˜๊ณ  ์ €์™€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ FastAPI๊ฐ€ ๋งˆ์Œ์— ๋“œ๋Š” ์ด์œ ๋ฅผ ์•Œ๋ ค์ฃผ์„ธ์š”. ๐ŸŽ‰ **FastAPI**๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”์ง€, ์–ด๋–ค ์ ์ด ๋งˆ์Œ์— ๋“ค์—ˆ๋Š”์ง€, ์–ด๋–ค ํ”„๋กœ์ ํŠธ/ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋“ฑ์— ๋Œ€ํ•ด ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. -## FastAPI์— ํˆฌํ‘œํ•˜๊ธฐ +## FastAPI์— ํˆฌํ‘œํ•˜๊ธฐ { #vote-for-fastapi } * Slant์—์„œ **FastAPI** ์— ๋Œ€ํ•ด ํˆฌํ‘œํ•˜์‹ญ์‹œ์˜ค. * AlternativeTo์—์„œ **FastAPI** ์— ๋Œ€ํ•ด ํˆฌํ‘œํ•˜์‹ญ์‹œ์˜ค. -* StackShare์—์„œ **FastAPI** ์— ๋Œ€ํ•ด ํˆฌํ‘œํ•˜์‹ญ์‹œ์˜ค. +* StackShare์—์„œ **FastAPI**๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ‘œ์‹œํ•˜์„ธ์š”. -## GitHub์˜ ์ด์Šˆ๋กœ ๋‹ค๋ฅธ์‚ฌ๋žŒ ๋•๊ธฐ +## GitHub์—์„œ ์งˆ๋ฌธ์œผ๋กœ ๋‹ค๋ฅธ ์‚ฌ๋žŒ ๋•๊ธฐ { #help-others-with-questions-in-github } ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์งˆ๋ฌธ์— ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -* GitHub ๋””์Šค์ปค์…˜ -* GitHub ์ด์Šˆ +* GitHub Discussions +* GitHub Issues ๋งŽ์€ ๊ฒฝ์šฐ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ด๋ฏธ ๊ทธ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์„ ์•Œ๊ณ  ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ -๋งŒ์•ฝ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์˜ ๋ฌธ์ œ๋ฅผ ๋„์™€์ค€๋‹ค๋ฉด, ๊ณต์‹์ ์ธ [FastAPI ์ „๋ฌธ๊ฐ€](fastapi-people.md#fastapi-experts){.internal-link target=\_blank} ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐ŸŽ‰ +๋งŒ์•ฝ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์˜ ์งˆ๋ฌธ์„ ๋„์™€์ค€๋‹ค๋ฉด, ๊ณต์‹์ ์ธ [FastAPI ์ „๋ฌธ๊ฐ€](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐ŸŽ‰ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ ์€: ์นœ์ ˆํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ์ขŒ์ ˆ๊ฐ์„ ์•ˆ๊ณ  ์˜ค๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ ์ตœ์„ ์˜ ๋ฐฉ์‹์œผ๋กœ ์งˆ๋ฌธํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ตœ๋Œ€ํ•œ ์นœ์ ˆํ•˜๊ฒŒ ๋Œ€ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜์„ธ์š”. ๐Ÿค— @@ -86,183 +86,170 @@ GitHub์—์„œ FastAPI๋ฅผ "watch"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ watch ๋ฒ„ --- -๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์งˆ๋ฌธ (๋””์Šค์ปค์…˜ ๋˜๋Š” ์ด์Šˆ์—์„œ) ํ•ด๊ฒฐ์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. +๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์งˆ๋ฌธ(๋””์Šค์ปค์…˜ ๋˜๋Š” ์ด์Šˆ์—์„œ) ํ•ด๊ฒฐ์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. -### ์งˆ๋ฌธ ์ดํ•ดํ•˜๊ธฐ +### ์งˆ๋ฌธ ์ดํ•ดํ•˜๊ธฐ { #understand-the-question } * ์งˆ๋ฌธํ•˜๋Š” ์‚ฌ๋žŒ์ด ๊ฐ€์ง„ **๋ชฉ์ **๊ณผ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. -* ์งˆ๋ฌธ (๋Œ€๋ถ€๋ถ„์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค)์ด **๋ช…ํ™•**ํ•œ์ง€ ํ™•์ธํ•˜์„ธ์š”. +* ๊ทธ๋Ÿฐ ๋‹ค์Œ ์งˆ๋ฌธ(๋Œ€๋ถ€๋ถ„์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค)์ด **๋ช…ํ™•**ํ•œ์ง€ ํ™•์ธํ•˜์„ธ์š”. -* ๋งŽ์€ ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ •ํ•œ ํ•ด๊ฒฐ์ฑ…์— ๋Œ€ํ•œ ์งˆ๋ฌธ์„ ํ•˜์ง€๋งŒ, ๋” **์ข‹์€** ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ์™€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•˜๋ฉด ๋” ๋‚˜์€ **๋Œ€์•ˆ์ ์ธ ํ•ด๊ฒฐ์ฑ…**์„ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋งŽ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์ƒํ•œ ํ•ด๊ฒฐ์ฑ…์— ๋Œ€ํ•œ ์งˆ๋ฌธ์„ ํ•˜์ง€๋งŒ, ๋” **์ข‹์€** ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ์™€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•˜๋ฉด ๋” ๋‚˜์€ **๋Œ€์•ˆ์ ์ธ ํ•ด๊ฒฐ์ฑ…**์„ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * ์งˆ๋ฌธ์„ ์ดํ•ดํ•  ์ˆ˜ ์—†๋‹ค๋ฉด, ๋” **์ž์„ธํ•œ ์ •๋ณด**๋ฅผ ์š”์ฒญํ•˜์„ธ์š”. -### ๋ฌธ์ œ ์žฌํ˜„ํ•˜๊ธฐ +### ๋ฌธ์ œ ์žฌํ˜„ํ•˜๊ธฐ { #reproduce-the-problem } -๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ์งˆ๋ฌธ์€ ์งˆ๋ฌธ์ž์˜ **์›๋ณธ ์ฝ”๋“œ**์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ์งˆ๋ฌธ์—์„œ๋Š” ์งˆ๋ฌธ์ž์˜ **์›๋ณธ ์ฝ”๋“œ**์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ ๊ฒฝ์šฐ, ์ฝ”๋“œ์˜ ์ผ๋ถ€๋งŒ ๋ณต์‚ฌํ•ด์„œ ์˜ฌ๋ฆฌ์ง€๋งŒ, ๊ทธ๊ฒƒ๋งŒ์œผ๋กœ๋Š” **๋ฌธ์ œ๋ฅผ ์žฌํ˜„**ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -* ์งˆ๋ฌธ์ž์—๊ฒŒ ์ตœ์†Œํ•œ์˜ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ์˜ˆ์ œ๋ฅผ ์ œ๊ณตํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜์„ธ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ **๋ณต์‚ฌ-๋ถ™์—ฌ๋„ฃ๊ธฐ**ํ•˜์—ฌ ์ง์ ‘ ์‹คํ–‰ํ•˜๊ณ , ๋™์ผํ•œ ์˜ค๋ฅ˜๋‚˜ ๋™์ž‘์„ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ์งˆ๋ฌธ์ž์—๊ฒŒ ์ตœ์†Œํ•œ์˜ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ์˜ˆ์ œ๋ฅผ ์ œ๊ณตํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ **๋ณต์‚ฌ-๋ถ™์—ฌ๋„ฃ๊ธฐ**ํ•˜์—ฌ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•˜๊ณ , ์งˆ๋ฌธ์ž๊ฐ€ ๋ณด๊ณ  ์žˆ๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์˜ค๋ฅ˜๋‚˜ ๋™์ž‘์„ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* ๋„ˆ๊ทธ๋Ÿฌ์šด ๋งˆ์Œ์ด ๋“ ๋‹ค๋ฉด, ๋ฌธ์ œ ์„ค๋ช…๋งŒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง์ ‘ **์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด**๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Š” ์‹œ๊ฐ„์ด ๋งŽ์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋จผ์ € ์งˆ๋ฌธ์„ ๋ช…ํ™•ํžˆ ํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +* ๋„ˆ๊ทธ๋Ÿฌ์šด ๋งˆ์Œ์ด ๋“ ๋‹ค๋ฉด, ๋ฌธ์ œ ์„ค๋ช…๋งŒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง์ ‘ **์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด**๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ด๋Š” ์‹œ๊ฐ„์ด ๋งŽ์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋จผ์ € ๋ฌธ์ œ๋ฅผ ๋ช…ํ™•ํžˆ ํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. -### ํ•ด๊ฒฐ์ฑ… ์ œ์•ˆํ•˜๊ธฐ +### ํ•ด๊ฒฐ์ฑ… ์ œ์•ˆํ•˜๊ธฐ { #suggest-solutions } * ์งˆ๋ฌธ์„ ์ถฉ๋ถ„ํžˆ ์ดํ•ดํ•œ ํ›„์—๋Š” ๊ฐ€๋Šฅํ•œ **๋‹ต๋ณ€**์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* ๋งŽ์€ ๊ฒฝ์šฐ, ์งˆ๋ฌธ์ž์˜ **๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋‚˜ ์‚ฌ์šฉ ์‚ฌ๋ก€**๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ์‹œ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋” ๋‚˜์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +* ๋งŽ์€ ๊ฒฝ์šฐ, ์งˆ๋ฌธ์ž์˜ **๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋‚˜ ์‚ฌ์šฉ ์‚ฌ๋ก€**๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ์‹œ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋” ๋‚˜์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. -### ํ•ด๊ฒฐ ์š”์ฒญํ•˜๊ธฐ +### ์ข…๋ฃŒ ์š”์ฒญํ•˜๊ธฐ { #ask-to-close } -์งˆ๋ฌธ์ž๊ฐ€ ๋‹ต๋ณ€์„ ํ™•์ธํ•˜๊ณ  ๋‚˜๋ฉด, ๋‹น์‹ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค, **๋‹น์‹ ์€ ์˜์›…์ž…๋‹ˆ๋‹ค**! ๐Ÿฆธ +์งˆ๋ฌธ์ž๊ฐ€ ๋‹ต๋ณ€์„ ํ•˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค, **์—ฌ๋Ÿฌ๋ถ„์€ ์˜์›…์ž…๋‹ˆ๋‹ค**! ๐Ÿฆธ * ์ด์ œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค๋ฉด, ์งˆ๋ฌธ์ž์—๊ฒŒ ๋‹ค์Œ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - * GitHub ๋””์Šค์ปค์…˜์—์„œ: ๋Œ“๊ธ€์„ **๋‹ต๋ณ€**์œผ๋กœ ํ‘œ์‹œํ•˜๋„๋ก ์š”์ฒญํ•˜์„ธ์š”. - * GitHub ์ด์Šˆ์—์„œ: ์ด์Šˆ๋ฅผ **๋‹ซ์•„๋‹ฌ๋ผ๊ณ ** ์š”์ฒญํ•˜์„ธ์š”. + * GitHub Discussions์—์„œ: ๋Œ“๊ธ€์„ **๋‹ต๋ณ€**์œผ๋กœ ํ‘œ์‹œํ•˜๋„๋ก ์š”์ฒญํ•˜์„ธ์š”. + * GitHub Issues์—์„œ: ์ด์Šˆ๋ฅผ **๋‹ซ์•„๋‹ฌ๋ผ๊ณ ** ์š”์ฒญํ•˜์„ธ์š”. -## GitHub ์ €์žฅ์†Œ ๋ณด๊ธฐ +## GitHub ์ €์žฅ์†Œ ๋ณด๊ธฐ { #watch-the-github-repository } -GitHub์—์„œ FastAPI๋ฅผ "watch"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ watch ๋ฒ„ํŠผ์„ ํด๋ฆญ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ +GitHub์—์„œ FastAPI๋ฅผ "watch"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ "watch" ๋ฒ„ํŠผ์„ ํด๋ฆญ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ -"Releases only" ๋Œ€์‹  "Watching"์„ ์„ ํƒํ•˜๋ฉด, ์ƒˆ๋กœ์šด ์ด์Šˆ๋‚˜ ์งˆ๋ฌธ์ด ์ƒ์„ฑ๋  ๋•Œ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ํŠน์ •ํ•˜๊ฒŒ ์ƒˆ๋กœ์šด ์ด์Šˆ, ๋””์Šค์ปค์…˜, PR ๋“ฑ๋งŒ ์•Œ๋ฆผ ๋ฐ›๋„๋ก ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +"Releases only" ๋Œ€์‹  "Watching"์„ ์„ ํƒํ•˜๋ฉด ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ƒˆ ์ด์Šˆ๋‚˜ ์งˆ๋ฌธ์„ ๋งŒ๋“ค ๋•Œ ์•Œ๋ฆผ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ƒˆ ์ด์Šˆ, ๋””์Šค์ปค์…˜, PR ๋“ฑ๋งŒ ์•Œ๋ฆผ์„ ๋ฐ›๋„๋ก ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด๋Ÿฐ ์ด์Šˆ๋“ค์„ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด๋Ÿฐ ์งˆ๋ฌธ๋“ค์„ ํ•ด๊ฒฐํ•˜๋„๋ก ๋„์™€์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## ์ด์Šˆ ์ƒ์„ฑํ•˜๊ธฐ +## ์งˆ๋ฌธํ•˜๊ธฐ { #ask-questions } -GitHub ์ €์žฅ์†Œ์— ์ƒˆ๋กœ์šด ์ด์Šˆ ์ƒ์„ฑ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค, ์˜ˆ๋ฅผ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: +GitHub ์ €์žฅ์†Œ์—์„œ ์ƒˆ ์งˆ๋ฌธ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: * **์งˆ๋ฌธ**์„ ํ•˜๊ฑฐ๋‚˜ **๋ฌธ์ œ**์— ๋Œ€ํ•ด ์งˆ๋ฌธํ•ฉ๋‹ˆ๋‹ค. * ์ƒˆ๋กœ์šด **๊ธฐ๋Šฅ**์„ ์ œ์•ˆ ํ•ฉ๋‹ˆ๋‹ค. -**์ฐธ๊ณ **: ๋งŒ์•ฝ ์ด์Šˆ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋ฉด, ์ €๋Š” ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์„ ๋„์™€๋‹ฌ๋ผ๊ณ  ๋ถ€ํƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜‰ +**์ฐธ๊ณ **: ๋งŒ์•ฝ ์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด, ์ €๋Š” ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๋„ ๋„์™€๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜‰ -## Pull Requests ๋ฆฌ๋ทฐํ•˜๊ธฐ +## Pull Request ๋ฆฌ๋ทฐํ•˜๊ธฐ { #review-pull-requests } -๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ pull request๋ฅผ ๋ฆฌ๋ทฐํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ๋งŒ๋“  pull request๋ฅผ ๋ฆฌ๋ทฐํ•˜๋Š” ๋ฐ ์ €๋ฅผ ๋„์™€์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ๋ฒˆ ๋งํ•˜์ง€๋งŒ, ์ตœ๋Œ€ํ•œ ์นœ์ ˆํ•˜๊ฒŒ ๋ฆฌ๋ทฐํ•ด ์ฃผ์„ธ์š”. ๐Ÿค— --- -Pull Rrquest๋ฅผ ๋ฆฌ๋ทฐํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ๊ณผ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: +Pull request๋ฅผ ๋ฆฌ๋ทฐํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ๊ณผ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -### ๋ฌธ์ œ ์ดํ•ดํ•˜๊ธฐ +### ๋ฌธ์ œ ์ดํ•ดํ•˜๊ธฐ { #understand-the-problem } -* ๋จผ์ €, ํ•ด๋‹น pull request๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๋Š” **๋ฌธ์ œ๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€** ํ™•์ธํ•˜์„ธ์š”. GitHub ๋””์Šค์ปค์…˜ ๋˜๋Š” ์ด์Šˆ์—์„œ ๋” ๊ธด ๋…ผ์˜๊ฐ€ ์žˆ์—ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋จผ์ €, ํ•ด๋‹น pull request๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๋Š” **๋ฌธ์ œ๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€** ํ™•์ธํ•˜์„ธ์š”. GitHub Discussion ๋˜๋Š” ์ด์Šˆ์—์„œ ๋” ๊ธด ๋…ผ์˜๊ฐ€ ์žˆ์—ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -* Pull request๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. **๋‹ค๋ฅธ ๋ฐฉ์‹**์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ๊ทธ ๋ฐฉ๋ฒ•์„ ์ œ์•ˆํ•˜๊ฑฐ๋‚˜ ์งˆ๋ฌธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* Pull request๊ฐ€ ์‹ค์ œ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ๋„ ํฝ๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ **๋‹ค๋ฅธ ๋ฐฉ์‹**์œผ๋กœ ํ•ด๊ฒฐ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ ๊ทธ ๋ฐฉ๋ฒ•์„ ์ œ์•ˆํ•˜๊ฑฐ๋‚˜ ์งˆ๋ฌธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -### ์Šคํƒ€์ผ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๊ธฐ +### ์Šคํƒ€์ผ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๊ธฐ { #dont-worry-about-style } -* ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ์Šคํƒ€์ผ ๊ฐ™์€ ๊ฒƒ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์ง์ ‘ ์ปค๋ฐ‹์„ ์ˆ˜์ •ํ•˜์—ฌ squash and merge๋ฅผ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +* ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ์Šคํƒ€์ผ ๊ฐ™์€ ๊ฒƒ์— ๋„ˆ๋ฌด ์‹ ๊ฒฝ ์“ฐ์ง€ ๋งˆ์„ธ์š”. ์ €๋Š” ์ปค๋ฐ‹์„ ์ˆ˜๋™์œผ๋กœ ์กฐ์ •ํ•ด์„œ squash and merge๋ฅผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. * ์ฝ”๋“œ ์Šคํƒ€์ผ ๊ทœ์น™๋„ ๊ฑฑ์ •ํ•  ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์ž๋™ํ™”๋œ ๋„๊ตฌ๋“ค์ด ์ด๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -์Šคํƒ€์ผ์ด๋‚˜ ์ผ๊ด€์„ฑ ๊ด€๋ จ ์š”์ฒญ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ์ œ๊ฐ€ ์ง์ ‘ ์š”์ฒญํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ ์ปค๋ฐ‹์œผ๋กœ ์ˆ˜์ •ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์Šคํƒ€์ผ์ด๋‚˜ ์ผ๊ด€์„ฑ ๊ด€๋ จ ํ•„์š” ์‚ฌํ•ญ์ด ์žˆ๋‹ค๋ฉด, ์ œ๊ฐ€ ์ง์ ‘ ์š”์ฒญํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์œ„์— ์ปค๋ฐ‹์œผ๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -### ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ +### ์ฝ”๋“œ ํ™•์ธํ•˜๊ธฐ { #check-the-code } -* ์ฝ”๋“œ๋ฅผ ์ฝ๊ณ , **๋…ผ๋ฆฌ์ ์œผ๋กœ ํƒ€๋‹น**ํ•œ์ง€ ํ™•์ธํ•œ ํ›„ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. +* ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ฝ์–ด์„œ ๋ง์ด ๋˜๋Š”์ง€ ๋ณด๊ณ , **๋กœ์ปฌ์—์„œ ์‹คํ–‰**ํ•ด ์‹ค์ œ๋กœ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. -* ๊ทธ๋Ÿฐ ๋‹ค์Œ, ํ™•์ธํ–ˆ๋‹ค๊ณ  **๋Œ“๊ธ€**์„ ๋‚จ๊ฒจ ์ฃผ์„ธ์š”. ๊ทธ๋ž˜์•ผ ์ œ๊ฐ€ ๊ฒ€ํ† ํ–ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ทธ๋ ‡๊ฒŒ ํ–ˆ๋‹ค๊ณ  **๋Œ“๊ธ€**๋กœ ๋‚จ๊ฒจ ์ฃผ์„ธ์š”. ๊ทธ๋ž˜์•ผ ์ œ๊ฐ€ ์ •๋ง๋กœ ํ™•์ธํ–ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -/// info +/// info | ์ •๋ณด ๋ถˆํ–‰ํžˆ๋„, ์ œ๊ฐ€ ๋‹จ์ˆœํžˆ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šน์ธ๋งŒ์œผ๋กœ PR์„ ์‹ ๋ขฐํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. -3๊ฐœ, 5๊ฐœ ์ด์ƒ์˜ ์Šน์ธ์ด ๋‹ฌ๋ฆฐ PR์ด ์‹ค์ œ๋กœ๋Š” ๊นจ์ ธ ์žˆ๊ฑฐ๋‚˜, ๋ฒ„๊ทธ๊ฐ€ ์žˆ๊ฑฐ๋‚˜, ์ฃผ์žฅํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜… +์—ฌ๋Ÿฌ ๋ฒˆ, ์„ค๋ช…์ด ๊ทธ๋Ÿด๋“ฏํ•ด์„œ์ธ์ง€ 3๊ฐœ, 5๊ฐœ ์ด์ƒ์˜ ์Šน์ธ์ด ๋‹ฌ๋ฆฐ PR์ด ์žˆ์—ˆ์ง€๋งŒ, ์ œ๊ฐ€ ํ™•์ธํ•ด๋ณด๋ฉด ์‹ค์ œ๋กœ๋Š” ๊นจ์ ธ ์žˆ๊ฑฐ๋‚˜, ๋ฒ„๊ทธ๊ฐ€ ์žˆ๊ฑฐ๋‚˜, ์ฃผ์žฅํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜… ๋”ฐ๋ผ์„œ, ์ •๋ง๋กœ ์ฝ”๋“œ๋ฅผ ์ฝ๊ณ  ์‹คํ–‰ํ•œ ๋’ค, ๋Œ“๊ธ€๋กœ ํ™•์ธ ๋‚ด์šฉ์„ ๋‚จ๊ฒจ ์ฃผ๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿค“ /// -* PR์„ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋„ˆ๋ฌด ๊นŒ๋‹ค๋กœ์šธ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ฃผ๊ด€์ ์ธ ๊ฒฌํ•ด๊ฐ€ ๋งŽ์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค (๊ทธ๋ฆฌ๊ณ  ์ €๋„ ์ œ ๊ฒฌํ•ด๊ฐ€ ์žˆ์„ ๊ฑฐ์˜ˆ์š” ๐Ÿ™ˆ). ๋”ฐ๋ผ์„œ ํ•ต์‹ฌ์ ์ธ ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. +* PR์„ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋„ˆ๋ฌด ๊นŒ๋‹ค๋กœ์šธ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ฃผ๊ด€์ ์ธ ๊ฒฌํ•ด๊ฐ€ ๋งŽ์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๊ทธ๋ฆฌ๊ณ  ์ €๋„ ์ œ ๊ฒฌํ•ด๊ฐ€ ์žˆ์„ ๊ฑฐ์˜ˆ์š” ๐Ÿ™ˆ). ๋”ฐ๋ผ์„œ ํ•ต์‹ฌ์ ์ธ ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. -### ํ…Œ์ŠคํŠธ +### ํ…Œ์ŠคํŠธ { #tests } * PR์— **ํ…Œ์ŠคํŠธ**๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์„ธ์š”. -* PR์„ ์ ์šฉํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ๊ฐ€ **์‹คํŒจ**ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ๐Ÿšจ +* PR ์ „์—๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ **์‹คํŒจ**ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ๐Ÿšจ -* PR์„ ์ ์šฉํ•œ ํ›„ ํ…Œ์ŠคํŠธ๊ฐ€ **ํ†ต๊ณผ**ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. โœ… +* ๊ทธ๋Ÿฐ ๋‹ค์Œ PR ํ›„์—๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ **ํ†ต๊ณผ**ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. โœ… -* ๋งŽ์€ PR์—๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก **์ƒ๊ธฐ**์‹œ์ผœ์ค„ ์ˆ˜๋„ ์žˆ๊ณ , ์ง์ ‘ ํ…Œ์ŠคํŠธ๋ฅผ **์ œ์•ˆ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๊ทธ ๋ถ€๋ถ„์„ ๋งŽ์ด ๋„์™€์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ๋งŽ์€ PR์—๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก **์ƒ๊ธฐ**์‹œ์ผœ์ค„ ์ˆ˜๋„ ์žˆ๊ณ , ์ง์ ‘ ํ…Œ์ŠคํŠธ๋ฅผ **์ œ์•ˆ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‹œ๊ฐ„์ด ๊ฐ€์žฅ ๋งŽ์ด ๋“œ๋Š” ๊ฒƒ๋“ค ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๊ทธ ๋ถ€๋ถ„์„ ๋งŽ์ด ๋„์™€์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * ๊ทธ๋ฆฌ๊ณ  ์‹œ๋„ํ•œ ๋‚ด์šฉ์„ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”. ๊ทธ๋Ÿฌ๋ฉด ์ œ๊ฐ€ ํ™•์ธํ–ˆ๋‹ค๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“ -## Pull Request๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค +## Pull Request ๋งŒ๋“ค๊ธฐ { #create-a-pull-request } -Pull Requests๋ฅผ ์ด์šฉํ•˜์—ฌ ์†Œ์Šค์ฝ”๋“œ์— [์ปจํŠธ๋ฆฌ๋ทฐํŠธ](contributing.md){.internal-link target=\_blank} ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: +Pull Requests๋ฅผ ์ด์šฉํ•˜์—ฌ ์†Œ์Šค ์ฝ”๋“œ์— [๊ธฐ์—ฌ](contributing.md){.internal-link target=_blank}ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: * ๋ฌธ์„œ์—์„œ ๋ฐœ๊ฒฌํ•œ ์˜คํƒ€๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ. -* FastAPI ๊ด€๋ จ ๋ฌธ์„œ, ๋น„๋””์˜ค ๋˜๋Š” ํŒŸ์บ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ๊ฑฐ๋‚˜ ๋ฐœ๊ฒฌํ•˜์—ฌ ์ด ํŒŒ์ผ์„ ํŽธ์ง‘ํ•˜์—ฌ ๊ณต์œ ํ•  ๋•Œ. +* FastAPI์— ๋Œ€ํ•œ ๊ธ€, ๋น„๋””์˜ค, ํŒŸ์บ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ๊ฑฐ๋‚˜ ๋ฐœ๊ฒฌํ–ˆ๋‹ค๋ฉด ์ด ํŒŒ์ผ์„ ํŽธ์ง‘ํ•˜์—ฌ ๊ณต์œ ํ•  ๋•Œ. * ํ•ด๋‹น ์„น์…˜์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์— ๋งํฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -* ๋‹น์‹ ์˜ ์–ธ์–ด๋กœ [๋ฌธ์„œ ๋ฒˆ์—ญํ•˜๋Š”๋ฐ](contributing.md#translations){.internal-link target=\_blank} ๊ธฐ์—ฌํ•  ๋•Œ. +* ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ธ์–ด๋กœ [๋ฌธ์„œ ๋ฒˆ์—ญ์—](contributing.md#translations){.internal-link target=_blank} ๋„์›€์„ ์ค„ ๋•Œ. * ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ž‘์„ฑํ•œ ๋ฒˆ์—ญ์„ ๊ฒ€ํ† ํ•˜๋Š” ๊ฒƒ๋„ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* ์ƒˆ๋กœ์šด ๋ฌธ์„œ์˜ ์„น์…˜์„ ์ œ์•ˆํ•  ๋•Œ. -* ๊ธฐ์กด ๋ฌธ์ œ/๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ. +* ์ƒˆ๋กœ์šด ๋ฌธ์„œ ์„น์…˜์„ ์ œ์•ˆํ•  ๋•Œ. +* ๊ธฐ์กด ์ด์Šˆ/๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ. * ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -* ์ƒˆ๋กœ์šด feature๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ. +* ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ๋•Œ. * ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - * ๊ด€๋ จ ๋ฌธ์„œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + * ๊ด€๋ จ ๋ฌธ์„œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -## FastAPI ์œ ์ง€ ๊ด€๋ฆฌ์— ๋„์›€ ์ฃผ๊ธฐ +## FastAPI ์œ ์ง€ ๊ด€๋ฆฌ ๋•๊ธฐ { #help-maintain-fastapi } -**FastAPI**์˜ ์œ ์ง€ ๊ด€๋ฆฌ๋ฅผ ๋„์™€์ฃผ์„ธ์š”! ๐Ÿค“ +**FastAPI** ์œ ์ง€๋ฅผ ๋„์™€์ฃผ์„ธ์š”! ๐Ÿค“ -ํ•  ์ผ์ด ๋งŽ๊ณ , ๊ทธ ์ค‘ ๋Œ€๋ถ€๋ถ„์€ **์—ฌ๋Ÿฌ๋ถ„**์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +ํ•  ์ผ์ด ๋งŽ๊ณ , ๊ทธ์ค‘ ๋Œ€๋ถ€๋ถ„์€ **์—ฌ๋Ÿฌ๋ถ„**์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ์ž‘์—…์€: -* [GitHub์—์„œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์งˆ๋ฌธ์— ๋„์›€ ์ฃผ๊ธฐ](#github_1){.internal-link target=_blank} (์œ„์˜ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”). -* [Pull Request ๋ฆฌ๋ทฐํ•˜๊ธฐ](#pull-requests){.internal-link target=_blank} (์œ„์˜ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”). +* [GitHub์—์„œ ์งˆ๋ฌธ์œผ๋กœ ๋‹ค๋ฅธ ์‚ฌ๋žŒ ๋•๊ธฐ](#help-others-with-questions-in-github){.internal-link target=_blank} (์œ„์˜ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”). +* [Pull Request ๋ฆฌ๋ทฐํ•˜๊ธฐ](#review-pull-requests){.internal-link target=_blank} (์œ„์˜ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”). -์ด ๋‘ ์ž‘์—…์ด **๊ฐ€์žฅ ๋งŽ์€ ์‹œ๊ฐ„์„ ์†Œ๋ชจ**ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด FastAPI ์œ ์ง€ ๊ด€๋ฆฌ์˜ ์ฃผ์š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. +์ด ๋‘ ์ž‘์—…์ด **๊ฐ€์žฅ ๋งŽ์€ ์‹œ๊ฐ„์„ ์†Œ๋ชจ**ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด FastAPI๋ฅผ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋Š” ์ฃผ์š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. -์ด ์ž‘์—…์„ ๋„์™€์ฃผ์‹ ๋‹ค๋ฉด, **FastAPI ์œ ์ง€ ๊ด€๋ฆฌ์— ๋„์›€์„ ์ฃผ๋Š” ๊ฒƒ**์ด๋ฉฐ ๊ทธ๊ฒƒ์ด **๋” ๋น ๋ฅด๊ณ  ๋” ์ž˜ ๋ฐœ์ „ํ•˜๋Š” ๊ฒƒ**์„ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿš€ +์ด ์ž‘์—…์„ ๋„์™€์ฃผ์‹ ๋‹ค๋ฉด, **FastAPI ์œ ์ง€๋ฅผ ๋•๋Š” ๊ฒƒ**์ด๋ฉฐ FastAPI๊ฐ€ **๋” ๋น ๋ฅด๊ณ  ๋” ์ž˜ ๋ฐœ์ „ํ•˜๋Š” ๊ฒƒ**์„ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿš€ -## ์ฑ„ํŒ…์— ์ฐธ์—ฌํ•˜์‹ญ์‹œ์˜ค +## ์ฑ„ํŒ…์— ์ฐธ์—ฌํ•˜๊ธฐ { #join-the-chat } -๐Ÿ‘ฅ ๋””์Šค์ฝ”๋“œ ์ฑ„ํŒ… ์„œ๋ฒ„ ๐Ÿ‘ฅ ์— ๊ฐ€์ž…ํ•˜๊ณ  FastAPI ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ์–ด์šธ๋ฆฌ์„ธ์š”. +๐Ÿ‘ฅ Discord ์ฑ„ํŒ… ์„œ๋ฒ„ ๐Ÿ‘ฅ ์— ์ฐธ์—ฌํ•ด์„œ FastAPI ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ์–ด์šธ๋ฆฌ์„ธ์š”. -/// tip +/// tip | ํŒ -์งˆ๋ฌธ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, GitHub ๋””์Šค์ปค์…˜ ์—์„œ ์งˆ๋ฌธํ•˜์‹ญ์‹œ์˜ค, [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank} ์˜ ๋„์›€์„ ๋ฐ›์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. +์งˆ๋ฌธ์€ GitHub Discussions์—์„œ ํ•˜์„ธ์š”. [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๋กœ๋ถ€ํ„ฐ ๋„์›€์„ ๋ฐ›์„ ๊ฐ€๋Šฅ์„ฑ์ด ํ›จ์”ฌ ๋†’์Šต๋‹ˆ๋‹ค. -๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋Œ€ํ™”์—์„œ๋งŒ ์ฑ„ํŒ…์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. +์ฑ„ํŒ…์€ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋Œ€ํ™”๋ฅผ ์œ„ํ•ด์„œ๋งŒ ์‚ฌ์šฉํ•˜์„ธ์š”. /// -### ์งˆ๋ฌธ์„ ์œ„ํ•ด ์ฑ„ํŒ…์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค +### ์งˆ๋ฌธ์„ ์œ„ํ•ด ์ฑ„ํŒ…์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š” { #dont-use-the-chat-for-questions } -์ฑ„ํŒ…์€ ๋” ๋งŽ์€ "์ž์œ ๋กœ์šด ๋Œ€ํ™”"๋ฅผ ํ—ˆ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ธ ์งˆ๋ฌธ์ด๋‚˜ ๋Œ€๋‹ตํ•˜๊ธฐ ์–ด๋ ค์šด ์งˆ๋ฌธ์„ ์‰ฝ๊ฒŒ ์งˆ๋ฌธ์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋‹ต๋ณ€์„ ๋ฐ›์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ฑ„ํŒ…์€ ๋” ๋งŽ์€ "์ž์œ ๋กœ์šด ๋Œ€ํ™”"๋ฅผ ํ—ˆ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ธ ์งˆ๋ฌธ์ด๋‚˜ ๋‹ตํ•˜๊ธฐ ์–ด๋ ค์šด ์งˆ๋ฌธ์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด ๋‹ต๋ณ€์„ ๋ฐ›์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. -GitHub ์ด์Šˆ์—์„œ์˜ ํ…œํ”Œ๋ฆฟ์€ ์˜ฌ๋ฐ”๋ฅธ ์งˆ๋ฌธ์„ ์ž‘์„ฑํ•˜๋„๋ก ์•ˆ๋‚ดํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ์ข‹์€ ๋‹ต๋ณ€์„ ์–ป๊ฑฐ๋‚˜ ์งˆ๋ฌธํ•˜๊ธฐ ์ „์— ์Šค์Šค๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  GitHub์—์„œ๋Š” ์‹œ๊ฐ„์ด ์กฐ๊ธˆ ๊ฑธ๋ฆฌ๋”๋ผ๋„ ํ•ญ์ƒ ๋ชจ๋“  ๊ฒƒ์— ๋‹ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฑ„ํŒ… ์‹œ์Šคํ…œ์—์„œ๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿ˜… +GitHub์—์„œ๋Š” ํ…œํ”Œ๋ฆฟ์ด ์˜ฌ๋ฐ”๋ฅธ ์งˆ๋ฌธ์„ ์ž‘์„ฑํ•˜๋„๋ก ์•ˆ๋‚ดํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ์ข‹์€ ๋‹ต๋ณ€์„ ์–ป๊ฑฐ๋‚˜, ์งˆ๋ฌธํ•˜๊ธฐ ์ „์— ์Šค์Šค๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  GitHub์—์„œ๋Š” ์‹œ๊ฐ„์ด ์กฐ๊ธˆ ๊ฑธ๋ฆฌ๋”๋ผ๋„ ์ œ๊ฐ€ ํ•ญ์ƒ ๋ชจ๋“  ๊ฒƒ์— ๋‹ตํ•˜๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฑ„ํŒ… ์‹œ์Šคํ…œ์—์„œ๋Š” ์ œ๊ฐ€ ๊ฐœ์ธ์ ์œผ๋กœ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿ˜… -์ฑ„ํŒ… ์‹œ์Šคํ…œ์—์„œ์˜ ๋Œ€ํ™” ๋˜ํ•œ GitHub์—์„œ ์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€ํ™” ์ค‘์— ์งˆ๋ฌธ๊ณผ ๋‹ต๋ณ€์ด ์†์‹ค๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  GitHub ์ด์Šˆ์— ์žˆ๋Š” ๊ฒƒ๋งŒ [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๊ฐ€ ๋˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜๋ฏ€๋กœ, GitHub ์ด์Šˆ์—์„œ ๋” ๋งŽ์€ ๊ด€์‹ฌ์„ ๋ฐ›์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +์ฑ„ํŒ… ์‹œ์Šคํ…œ์—์„œ์˜ ๋Œ€ํ™” ๋˜ํ•œ GitHub๋งŒํผ ์‰ฝ๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์งˆ๋ฌธ๊ณผ ๋‹ต๋ณ€์ด ๋Œ€ํ™” ์†์—์„œ ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  GitHub์— ์žˆ๋Š” ๊ฒƒ๋งŒ [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๊ฐ€ ๋˜๋Š” ๊ฒƒ์œผ๋กœ ์ธ์ •๋˜๋ฏ€๋กœ, GitHub์—์„œ ๋” ๋งŽ์€ ๊ด€์‹ฌ์„ ๋ฐ›๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. -๋ฐ˜๋ฉด, ์ฑ„ํŒ… ์‹œ์Šคํ…œ์—๋Š” ์ˆ˜์ฒœ ๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฑฐ์˜ ํ•ญ์ƒ ๋Œ€ํ™” ์ƒ๋Œ€๋ฅผ ์ฐพ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๐Ÿ˜„ +๋ฐ˜๋ฉด, ์ฑ„ํŒ… ์‹œ์Šคํ…œ์—๋Š” ์ˆ˜์ฒœ ๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ๊ฑฐ์˜ ํ•ญ์ƒ ๋Œ€ํ™” ์ƒ๋Œ€๋ฅผ ์ฐพ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๐Ÿ˜„ -## ๊ฐœ๋ฐœ์ž ์Šคํฐ์„œ๊ฐ€ ๋˜์‹ญ์‹œ์˜ค +## ๊ฐœ๋ฐœ์ž ์Šคํฐ์„œ ๋˜๊ธฐ { #sponsor-the-author } -GitHub ์Šคํฐ์„œ ๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋ฅผ ๊ฒฝ์ œ์ ์œผ๋กœ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - -๊ฐ์‚ฌํ•˜๋‹ค๋Š” ๋ง๋กœ ์ปคํ”ผ๋ฅผ โ˜•๏ธ ํ•œ์ž” ์‚ฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜„ - -๋˜ํ•œ FastAPI์˜ ์‹ค๋ฒ„ ๋˜๋Š” ๊ณจ๋“œ ์Šคํฐ์„œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ…๐ŸŽ‰ - -## FastAPI๋ฅผ ๊ฐ•ํ™”ํ•˜๋Š” ๋„๊ตฌ์˜ ์Šคํฐ์„œ๊ฐ€ ๋˜์‹ญ์‹œ์˜ค - -๋ฌธ์„œ์—์„œ ๋ณด์•˜๋“ฏ์ด, FastAPI๋Š” Starlette๊ณผ Pydantic ๋ผ๋Š” ๊ฑฐ์ธ์˜ ์–ด๊นจ์— ํƒ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. - -๋‹ค์Œ์˜ ์Šคํฐ์„œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค - -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +์—ฌ๋Ÿฌ๋ถ„์˜ **์ œํ’ˆ/ํšŒ์‚ฌ**๊ฐ€ **FastAPI**์— ์˜์กดํ•˜๊ฑฐ๋‚˜ ๊ด€๋ จ๋˜์–ด ์žˆ๊ณ , FastAPI ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์•Œ๋ฆฌ๊ณ  ์‹ถ๋‹ค๋ฉด GitHub sponsors๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž(์ €)๋ฅผ ์Šคํฐ์„œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ‹ฐ์–ด์— ๋”ฐ๋ผ ๋ฌธ์„œ์— ๋ฐฐ์ง€ ๊ฐ™์€ ์ถ”๊ฐ€ ํ˜œํƒ์„ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ --- diff --git a/docs/ko/docs/history-design-future.md b/docs/ko/docs/history-design-future.md index 98f01d70d3..d972001215 100644 --- a/docs/ko/docs/history-design-future.md +++ b/docs/ko/docs/history-design-future.md @@ -1,81 +1,79 @@ -# ์—ญ์‚ฌ, ๋””์ž์ธ ๊ทธ๋ฆฌ๊ณ  ๋ฏธ๋ž˜ +# ์—ญ์‚ฌ, ๋””์ž์ธ ๊ทธ๋ฆฌ๊ณ  ๋ฏธ๋ž˜ { #history-design-and-future } -์–ด๋А ๋‚ , [ํ•œ FastAPI ์‚ฌ์šฉ์ž](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920)๊ฐ€ ์ด๋ ‡๊ฒŒ ๋ฌผ์—ˆ์Šต๋‹ˆ๋‹ค: +์–ผ๋งˆ ์ „, ํ•œ **FastAPI** ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ ‡๊ฒŒ ๋ฌผ์—ˆ์Šต๋‹ˆ๋‹ค: -> ์ด ํ”„๋กœ์ ํŠธ์˜ ์—ญ์‚ฌ๋ฅผ ์•Œ๋ ค ์ฃผ์‹ค ์ˆ˜ ์žˆ๋‚˜์š”? ๋ช‡ ์ฃผ ๋งŒ์— ๋ฉ‹์ง„ ๊ฒฐ๊ณผ๋ฅผ ๋‚ธ ๊ฒƒ ๊ฐ™์•„์š”. [...] +> ์ด ํ”„๋กœ์ ํŠธ์˜ ์—ญ์‚ฌ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? ๋ช‡ ์ฃผ ๋งŒ์— ์•„๋ฌด ๋ฐ์„œ๋„ ๊ฐ‘์ž๊ธฐ ๋‚˜ํƒ€๋‚˜ ์—„์ฒญ๋‚˜๊ฒŒ ์ข‹์•„์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„ค์š” [...] ์—ฌ๊ธฐ์„œ ๊ทธ ์—ญ์‚ฌ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ---- +## ๋Œ€์•ˆ { #alternatives } -## ๋Œ€์•ˆ +์ €๋Š” ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ ๋ณต์žกํ•œ ์š”๊ตฌ์‚ฌํ•ญ(๋จธ์‹ ๋Ÿฌ๋‹, ๋ถ„์‚ฐ ์‹œ์Šคํ…œ, ๋น„๋™๊ธฐ ์ž‘์—…, NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ)์„ ๊ฐ€์ง„ API๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ ํŒ€์„ ์ด๋Œ์–ด ์™”์Šต๋‹ˆ๋‹ค. -์ €๋Š” ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ ๋จธ์‹ ๋Ÿฌ๋‹, ๋ถ„์‚ฐ ์‹œ์Šคํ…œ, ๋น„๋™๊ธฐ ์ž‘์—…, NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ™์€ ๋ณต์žกํ•œ ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ฐ€์ง„ API๋ฅผ ๊ฐœ๋ฐœํ•˜๋ฉฐ ์—ฌ๋Ÿฌ ํŒ€์„ ์ด๋Œ์–ด ์™”์Šต๋‹ˆ๋‹ค. +๊ทธ ๊ณผ์ •์—์„œ ๋งŽ์€ ๋Œ€์•ˆ์„ ์กฐ์‚ฌํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๊ณ , ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. -์ด ๊ณผ์ •์—์„œ ๋งŽ์€ ๋Œ€์•ˆ์„ ์กฐ์‚ฌํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๋ฉฐ, ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. **FastAPI**์˜ ์—ญ์‚ฌ๋Š” ๊ทธ ์ด์ „์— ๋‚˜์™”๋˜ ์—ฌ๋Ÿฌ ๋„๊ตฌ์˜ ์—ญ์‚ฌ์™€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ด€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. +**FastAPI**์˜ ์—ญ์‚ฌ๋Š” ์ƒ๋‹น ๋ถ€๋ถ„ ๊ทธ ์ด์ „์— ์žˆ๋˜ ๋„๊ตฌ๋“ค์˜ ์—ญ์‚ฌ์ž…๋‹ˆ๋‹ค. [๋Œ€์•ˆ](alternatives.md){.internal-link target=_blank} ์„น์…˜์—์„œ ์–ธ๊ธ‰๋œ ๊ฒƒ์ฒ˜๋Ÿผ: -> **FastAPI**๋Š” ์ด์ „์— ๋‚˜์™”๋˜ ๋งŽ์€ ๋„๊ตฌ๋“ค์˜ ๋…ธ๋ ฅ ์—†์ด๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -> -> ์ด์ „์— ๊ฐœ๋ฐœ๋œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋“ค์ด ์ด ํ”„๋กœ์ ํŠธ์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. -> -> ์ €๋Š” ์˜ค๋žซ๋™์•ˆ ์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” **FastAPI**๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์„ ๋‹ค์–‘ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ”Œ๋Ÿฌ๊ทธ์ธ, ๋„๊ตฌ๋“ค์„ ์กฐํ•ฉํ•ด ํ•ด๊ฒฐํ•˜๋ ค ํ–ˆ์Šต๋‹ˆ๋‹ค. -> -> ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ์—๋Š” ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ†ตํ•ฉํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด์ „ ๋„๊ตฌ๋“ค๋กœ๋ถ€ํ„ฐ ์ตœ๊ณ ์˜ ์•„์ด๋””์–ด๋“ค์„ ๋ชจ์œผ๊ณ , ์ด๋ฅผ ์ตœ์ ์˜ ๋ฐฉ์‹์œผ๋กœ ์กฐํ•ฉํ•ด์•ผ๋งŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” :term:Python 3.6+ ํƒ€์ž… ํžŒํŠธ ์™€ ๊ฐ™์€, ์ด์ „์—๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์—ˆ๋˜ ์–ธ์–ด ๊ธฐ๋Šฅ์ด ๊ฐ€๋Šฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +
---- +**FastAPI**๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์ด์ „์— ํ•ด์˜จ ์ž‘์—…์ด ์—†์—ˆ๋‹ค๋ฉด ์กด์žฌํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. -## ์กฐ์‚ฌ +๊ทธ ์ „์— ๋งŒ๋“ค์–ด์ง„ ๋งŽ์€ ๋„๊ตฌ๋“ค์ด ์ด๊ฒƒ์˜ ํƒ„์ƒ์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. -์—ฌ๋Ÿฌ ๋Œ€์•ˆ์„ ์‚ฌ์šฉํ•ด ๋ณด๋ฉฐ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์—์„œ ๋ฐฐ์šด ์ ๋“ค์„ ๋ชจ์•„ ์ €์™€ ๊ฐœ๋ฐœํŒ€์—๊ฒŒ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ฐฉ์‹์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. +์ €๋Š” ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ ์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” **FastAPI**๊ฐ€ ๋‹ค๋ฃจ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ, ํ”Œ๋Ÿฌ๊ทธ์ธ, ๋„๊ตฌ๋“ค์„ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด, ํ‘œ์ค€ :term:Python ํƒ€์ž… ํžŒํŠธ ์— ๊ธฐ๋ฐ˜ํ•˜๋Š” ๊ฒƒ์ด ์ด์ƒ์ ์ด๋ผ๋Š” ์ ์ด ๋ช…ํ™•ํ–ˆ์Šต๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ์–ด๋А ์‹œ์ ์—๋Š”, ์ด์ „ ๋„๊ตฌ๋“ค์˜ ์ตœ๊ณ ์˜ ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ตœ์„ ์˜ ๋ฐฉ์‹์œผ๋กœ ์กฐํ•ฉํ•˜๊ณ , ์ด์ „์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜๋˜ ์–ธ์–ด ๊ธฐ๋Šฅ(Python 3.6+ type hints)์„ ์‚ฌ์šฉํ•ด ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ ์™ธ์—๋Š” ๋‹ค๋ฅธ ์„ ํƒ์ง€๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. -๋˜ํ•œ, ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํ‘œ์ค€์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ์ ‘๊ทผ๋ฒ•์ด๋ผ ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. +
-๊ทธ๋ž˜์„œ **FastAPI**์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ๋ช‡ ๋‹ฌ ๋™์•ˆ OpenAPI, JSON Schema, OAuth2 ๋ช…์„ธ๋ฅผ ์—ฐ๊ตฌํ•˜๋ฉฐ ์ด๋“ค์˜ ๊ด€๊ณ„์™€ ๊ฒน์น˜๋Š” ๋ถ€๋ถ„, ์ฐจ์ด์ ์„ ์ดํ•ดํ–ˆ์Šต๋‹ˆ๋‹ค. +## ์กฐ์‚ฌ { #investigation } ---- +์ด์ „์˜ ๋ชจ๋“  ๋Œ€์•ˆ์„ ์‚ฌ์šฉํ•ด ๋ณด๋ฉด์„œ, ๊ฐ ๋„๊ตฌ๋กœ๋ถ€ํ„ฐ ๋ฐฐ์šธ ๊ธฐํšŒ๋ฅผ ์–ป์—ˆ๊ณ , ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ ธ์™€ ์ œ๊ฐ€ ์ผํ•ด์˜จ ๊ฐœ๋ฐœ ํŒ€๋“ค๊ณผ ์ € ์ž์‹ ์—๊ฒŒ ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค๊ณ  ์ฐพ์€ ๋ฐฉ์‹์œผ๋กœ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. -## ๋””์ž์ธ +์˜ˆ๋ฅผ ๋“ค์–ด, ์ด์ƒ์ ์œผ๋กœ๋Š” ํ‘œ์ค€ Python ํƒ€์ž… ํžŒํŠธ์— ๊ธฐ๋ฐ˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด ๋ถ„๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค. -๊ทธ ํ›„, **FastAPI** ์‚ฌ์šฉ์ž๊ฐ€ ๋  ๊ฐœ๋ฐœ์ž๋กœ์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฐœ๋ฐœ์ž "API"๋ฅผ ๋””์ž์ธํ–ˆ์Šต๋‹ˆ๋‹ค. +๋˜ํ•œ, ๊ฐ€์žฅ ์ข‹์€ ์ ‘๊ทผ๋ฒ•์€ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํ‘œ์ค€์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. -[Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)์— ๋”ฐ๋ฅด๋ฉด ์•ฝ 80%์˜ Python ๊ฐœ๋ฐœ์ž๊ฐ€ PyCharm, VS Code, Jedi ๊ธฐ๋ฐ˜ ํŽธ์ง‘๊ธฐ ๋“ฑ์—์„œ ๊ฐœ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์—ฌ๋Ÿฌ ์•„์ด๋””์–ด๋ฅผ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋ž˜์„œ **FastAPI**์˜ ์ฝ”๋”ฉ์„ ์‹œ์ž‘ํ•˜๊ธฐ๋„ ์ „์—, OpenAPI, JSON Schema, OAuth2 ๋“ฑ๊ณผ ๊ฐ™์€ ๋ช…์„ธ๋ฅผ ๋ช‡ ๋‹ฌ ๋™์•ˆ ๊ณต๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋“ค์˜ ๊ด€๊ณ„, ๊ฒน์น˜๋Š” ๋ถ€๋ถ„, ์ฐจ์ด์ ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ์˜€์Šต๋‹ˆ๋‹ค. -๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ํŽธ์ง‘๊ธฐ๋„ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, **FastAPI**์˜ ์ด์ ์€ ๊ฑฐ์˜ ๋ชจ๋“  ํŽธ์ง‘๊ธฐ์—์„œ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +## ๋””์ž์ธ { #design } -์ด ๊ณผ์ •์„ ํ†ตํ•ด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ตœ์†Œํ™”ํ•˜๊ณ , ๋ชจ๋“  ๊ณณ์—์„œ ์ž๋™ ์™„์„ฑ, ํƒ€์ž… ๊ฒ€์‚ฌ, ์—๋Ÿฌ ํ™•์ธ ๊ธฐ๋Šฅ์ด ์ œ๊ณต๋˜๋Š” ์ตœ์ ์˜ ๋ฐฉ์‹์„ ์ฐพ์•„๋ƒˆ์Šต๋‹ˆ๋‹ค. +๊ทธ ๋‹ค์Œ์—๋Š” (FastAPI๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋กœ์„œ) ์‚ฌ์šฉ์ž๋กœ์„œ ๊ฐ–๊ณ  ์‹ถ์—ˆ๋˜ ๊ฐœ๋ฐœ์ž "API"๋ฅผ ๋””์ž์ธํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์„ ์ผ์Šต๋‹ˆ๋‹ค. -์ด ๋ชจ๋“  ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์ตœ๊ณ ์˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. +๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” Python ํŽธ์ง‘๊ธฐ๋“ค: PyCharm, VS Code, Jedi ๊ธฐ๋ฐ˜ ํŽธ์ง‘๊ธฐ์—์„œ ์—ฌ๋Ÿฌ ์•„์ด๋””์–ด๋ฅผ ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ---- +์•ฝ 80%์˜ ์‚ฌ์šฉ์ž๋ฅผ ํฌํ•จํ•˜๋Š” ์ตœ๊ทผ Python Developer Survey์— ๋”ฐ๋ฅด๋ฉด ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. -## ํ•„์š”์กฐ๊ฑด +์ฆ‰, **FastAPI**๋Š” Python ๊ฐœ๋ฐœ์ž์˜ 80%๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ง‘๊ธฐ๋“ค๋กœ ํŠน๋ณ„ํžˆ ํ…Œ์ŠคํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ํŽธ์ง‘๊ธฐ๋„ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์œผ๋ฏ€๋กœ, ๊ทธ ๋ชจ๋“  ์ด์ ์€ ์‚ฌ์‹ค์ƒ ๋ชจ๋“  ํŽธ์ง‘๊ธฐ์—์„œ ๋™์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -์—ฌ๋Ÿฌ ๋Œ€์•ˆ์„ ํ…Œ์ŠคํŠธํ•œ ํ›„, [Pydantic](https://docs.pydantic.dev/)์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋ ‡๊ฒŒ ํ•ด์„œ ์ฝ”๋“œ ์ค‘๋ณต์„ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด ์ค„์ด๊ณ , ์–ด๋””์„œ๋‚˜ ์ž๋™ ์™„์„ฑ, ํƒ€์ž… ๋ฐ ์—๋Ÿฌ ๊ฒ€์‚ฌ ๋“ฑ์„ ์ œ๊ณตํ•˜๋Š” ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. -์ดํ›„ ์ €๋Š” **Pydantic**์ด JSON Schema์™€ ์™„๋ฒฝํžˆ ํ˜ธํ™˜๋˜๋„๋ก ๊ฐœ์„ ํ•˜๊ณ , ๋‹ค์–‘ํ•œ ์ œ์•ฝ ์กฐ๊ฑด ์„ ์–ธ์„ ์ง€์›ํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ํŽธ์ง‘๊ธฐ์—์„œ์˜ ์ž๋™ ์™„์„ฑ๊ณผ ํƒ€์ž… ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. +๋ชจ๋“  ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ตœ๊ณ ์˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ง์ž…๋‹ˆ๋‹ค. -๋˜ํ•œ, ๋˜ ๋‹ค๋ฅธ ์ฃผ์š” ํ•„์š”์กฐ๊ฑด์ด์—ˆ๋˜ [Starlette](https://www.starlette.dev/)์—๋„ ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. +## ํ•„์š”์กฐ๊ฑด { #requirements } ---- +์—ฌ๋Ÿฌ ๋Œ€์•ˆ์„ ํ…Œ์ŠคํŠธํ•œ ํ›„, ์žฅ์  ๋•Œ๋ฌธ์— **Pydantic**์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. -## ๊ฐœ๋ฐœ +๊ทธ ํ›„, JSON Schema๋ฅผ ์™„์ „ํžˆ ์ค€์ˆ˜ํ•˜๋„๋ก ํ•˜๊ณ , ์ œ์•ฝ ์กฐ๊ฑด ์„ ์–ธ์„ ์ •์˜ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์„ ์ง€์›ํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ํŽธ์ง‘๊ธฐ์—์„œ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŽธ์ง‘๊ธฐ ์ง€์›(ํƒ€์ž… ๊ฒ€์‚ฌ, ์ž๋™ ์™„์„ฑ)์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. -**FastAPI**๋ฅผ ๊ฐœ๋ฐœํ•˜๊ธฐ ์‹œ์ž‘ํ•  ์ฆˆ์Œ์—๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ค€๋น„๊ฐ€ ์ด๋ฏธ ์™„๋ฃŒ๋œ ์ƒํƒœ์˜€์Šต๋‹ˆ๋‹ค. ์„ค๊ณ„๊ฐ€ ์ •์˜๋˜์—ˆ๊ณ , ํ•„์š”์กฐ๊ฑด๊ณผ ๋„๊ตฌ๊ฐ€ ์ค€๋น„๋˜์—ˆ์œผ๋ฉฐ, ํ‘œ์ค€๊ณผ ๋ช…์„ธ์— ๋Œ€ํ•œ ์ง€์‹๋„ ์ถฉ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค. +๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ, ๋˜ ๋‹ค๋ฅธ ํ•ต์‹ฌ ํ•„์š”์กฐ๊ฑด์ธ **Starlette**์—๋„ ๊ธฐ์—ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ---- +## ๊ฐœ๋ฐœ { #development } -## ๋ฏธ๋ž˜ +**FastAPI** ์ž์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ์ฏค์—๋Š”, ๋Œ€๋ถ€๋ถ„์˜ ์กฐ๊ฐ๋“ค์ด ์ด๋ฏธ ๊ฐ–์ถฐ์ ธ ์žˆ์—ˆ๊ณ , ๋””์ž์ธ์€ ์ •์˜๋˜์–ด ์žˆ์—ˆ์œผ๋ฉฐ, ํ•„์š”์กฐ๊ฑด๊ณผ ๋„๊ตฌ๋Š” ์ค€๋น„๋˜์–ด ์žˆ์—ˆ๊ณ , ํ‘œ์ค€๊ณผ ๋ช…์„ธ์— ๋Œ€ํ•œ ์ง€์‹๋„ ๋ช…ํ™•ํ•˜๊ณ  ์ตœ์‹  ์ƒํƒœ์˜€์Šต๋‹ˆ๋‹ค. -ํ˜„์‹œ์ ์—์„œ **FastAPI**๊ฐ€ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ช…๋ฐฑํ•ด์กŒ์Šต๋‹ˆ๋‹ค. +## ๋ฏธ๋ž˜ { #future } -์—ฌ๋Ÿฌ ์šฉ๋„์— ๋” ์ ํ•ฉํ•œ ๋„๊ตฌ๋กœ์„œ ๊ธฐ์กด ๋Œ€์•ˆ๋ณด๋‹ค ์„ ํ˜ธ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -์ด๋ฏธ ๋งŽ์€ ๊ฐœ๋ฐœ์ž์™€ ํŒ€๋“ค์ด **FastAPI**์— ์˜์กดํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค (์ €์™€ ์ œ ํŒ€๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค). +์ด ์‹œ์ ์—๋Š”, **FastAPI**๊ฐ€ ๊ทธ ์•„์ด๋””์–ด์™€ ํ•จ๊ป˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์ด ์ด๋ฏธ ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ฐœ์„ ํ•ด์•ผ ํ•  ์ ๊ณผ ์ถ”๊ฐ€ํ•  ๊ธฐ๋Šฅ๋“ค์ด ๋งŽ์ด ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. +๋งŽ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋” ์ž˜ ๋งž๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ๋Œ€์•ˆ๋“ค๋ณด๋‹ค ์„ ํƒ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + +๋งŽ์€ ๊ฐœ๋ฐœ์ž์™€ ํŒ€์ด ์ด๋ฏธ ์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•ด **FastAPI**์— ์˜์กดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(์ €์™€ ์ œ ํŒ€๋„ ํฌํ•จํ•ด์„œ์š”). + +ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ, ์•ž์œผ๋กœ ๋‚˜์˜ฌ ๊ฐœ์„  ์‚ฌํ•ญ๊ณผ ๊ธฐ๋Šฅ๋“ค์ด ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + +**FastAPI**์˜ ๋ฏธ๋ž˜๋Š” ๋ฐ์Šต๋‹ˆ๋‹ค. -**FastAPI**๋Š” ๋ฐ์€ ๋ฏธ๋ž˜๋กœ ๋‚˜์•„๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  [์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์›€](help-fastapi.md){.internal-link target=_blank}์€ ํฐ ํž˜์ด ๋ฉ๋‹ˆ๋‹ค. From 442d007e761fdee34ec01d2365d138d0a746c971 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Jan 2026 21:16:33 +0000 Subject: [PATCH 028/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f1321b7809..cf84ae9b53 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). From 7a0589466c1c0129ff7291ea0b663d52859d651d Mon Sep 17 00:00:00 2001 From: JUNG SEUNGHOON Date: Sun, 25 Jan 2026 06:17:54 +0900 Subject: [PATCH 029/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20`llm-prompt.md`?= =?UTF-8?q?=20for=20Korean=20language=20(#14763)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs(ko): refine 'burger' to 'ํ–„๋ฒ„๊ฑฐ' and update glossary * Update docs/ko/llm-prompt.md Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> * Add app and command to glossary Update glossary: add ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ (app) and ๋ช…๋ น์–ด (command) --------- Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/ko/llm-prompt.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/ko/llm-prompt.md b/docs/ko/llm-prompt.md index 533160eab9..be2f5be5de 100644 --- a/docs/ko/llm-prompt.md +++ b/docs/ko/llm-prompt.md @@ -33,6 +33,9 @@ Use the following preferred translations when they apply in documentation prose: - response (HTTP): ์‘๋‹ต - path operation: ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ - path operation function: ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ +- app: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ +- command: ๋ช…๋ น์–ด +- burger: ํ–„๋ฒ„๊ฑฐ (NOT ๋ฒ„๊ฑฐ) ### `///` admonitions From 8c32e91c10cbf13da8be4d27f03d9fdaa9a6730c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 24 Jan 2026 21:18:15 +0000 Subject: [PATCH 030/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index cf84ae9b53..1fefe908ba 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* ๐ŸŒ Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev). * ๐ŸŒ Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov). From a3dccaeb14ed511ed548d88254b96131299851bf Mon Sep 17 00:00:00 2001 From: Vineet Kumar <108144301+whyvineet@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:53:25 +0530 Subject: [PATCH 031/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20minor=20typos=20in?= =?UTF-8?q?=20release=20notes=20(#14780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ“ Fix typos in release notes --- docs/en/docs/release-notes.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1fefe908ba..62dae4da71 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -283,7 +283,7 @@ hide: ### Refactors -* ๐Ÿ”ฅ Remove dangling extra condiitonal no longer needed. PR [#14435](https://github.com/fastapi/fastapi/pull/14435) by [@tiangolo](https://github.com/tiangolo). +* ๐Ÿ”ฅ Remove dangling extra conditional no longer needed. PR [#14435](https://github.com/fastapi/fastapi/pull/14435) by [@tiangolo](https://github.com/tiangolo). * โ™ป๏ธ Refactor internals, update `is_coroutine` check to reuse internal supported variants (unwrap, check class). PR [#14434](https://github.com/fastapi/fastapi/pull/14434) by [@tiangolo](https://github.com/tiangolo). ### Translations @@ -418,7 +418,7 @@ hide: ### Docs -* ๐Ÿ“ Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). +* ๐Ÿ“ Update docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). ### Internal @@ -2646,7 +2646,7 @@ Read more in the [advisory: Content-Type Header ReDoS](https://github.com/tiango * ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/handling-errors.md`. PR [#1953](https://github.com/tiangolo/fastapi/pull/1953) by [@SwftAlpc](https://github.com/SwftAlpc). * ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/response-status-code.md`. PR [#1942](https://github.com/tiangolo/fastapi/pull/1942) by [@SwftAlpc](https://github.com/SwftAlpc). * ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/extra-models.md`. PR [#1941](https://github.com/tiangolo/fastapi/pull/1941) by [@SwftAlpc](https://github.com/SwftAlpc). -* ๐ŸŒ Add Japanese tranlsation for `docs/ja/docs/tutorial/schema-extra-example.md`. PR [#1931](https://github.com/tiangolo/fastapi/pull/1931) by [@SwftAlpc](https://github.com/SwftAlpc). +* ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/schema-extra-example.md`. PR [#1931](https://github.com/tiangolo/fastapi/pull/1931) by [@SwftAlpc](https://github.com/SwftAlpc). * ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/body-nested-models.md`. PR [#1930](https://github.com/tiangolo/fastapi/pull/1930) by [@SwftAlpc](https://github.com/SwftAlpc). * ๐ŸŒ Add Japanese translation for `docs/ja/docs/tutorial/body-fields.md`. PR [#1923](https://github.com/tiangolo/fastapi/pull/1923) by [@SwftAlpc](https://github.com/SwftAlpc). * ๐ŸŒ Add German translation for `docs/de/docs/tutorial/index.md`. PR [#9502](https://github.com/tiangolo/fastapi/pull/9502) by [@fhabers21](https://github.com/fhabers21). @@ -4022,7 +4022,7 @@ You hopefully updated to a supported version of Python a while ago. If you haven ### Fixes * ๐Ÿ› Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen). -* ๐Ÿ› Fix empty reponse body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel). +* ๐Ÿ› Fix empty response body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel). ### Docs From 9348a5e2cf55440ff3da3bd4b7876acd3b3f57e5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 29 Jan 2026 08:23:48 +0000 Subject: [PATCH 032/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 62dae4da71..975bf774e9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ๐Ÿ“ Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). * ๐Ÿ› Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier). * ๐Ÿ“ Add contribution instructions about LLM generated code and comments and automated tools for PRs. PR [#14706](https://github.com/fastapi/fastapi/pull/14706) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update docs for management tasks. PR [#14705](https://github.com/fastapi/fastapi/pull/14705) by [@tiangolo](https://github.com/tiangolo). From c9629e0eb245836b7ecd7b12c1eb7ef12dbdb1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 31 Jan 2026 10:32:27 -0800 Subject: [PATCH 033/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-outdated)=20(#14745)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/tr/docs/about/index.md | 2 +- docs/tr/docs/advanced/index.md | 31 +- docs/tr/docs/advanced/security/index.md | 12 +- docs/tr/docs/advanced/testing-websockets.md | 10 +- docs/tr/docs/advanced/wsgi.md | 24 +- docs/tr/docs/benchmarks.md | 36 +- docs/tr/docs/deployment/cloud.md | 25 +- docs/tr/docs/deployment/index.md | 22 +- docs/tr/docs/how-to/general.md | 40 +- docs/tr/docs/how-to/index.md | 10 +- docs/tr/docs/index.md | 425 ++++++++++++-------- docs/tr/docs/learn/index.md | 4 +- docs/tr/docs/project-generation.md | 112 ++---- docs/tr/docs/python-types.md | 421 ++++++++++++------- docs/tr/docs/resources/index.md | 4 +- docs/tr/docs/tutorial/cookie-params.md | 34 +- docs/tr/docs/tutorial/first-steps.md | 311 ++++++++------ docs/tr/docs/tutorial/path-params.md | 190 +++++---- docs/tr/docs/tutorial/query-params.md | 94 ++--- docs/tr/docs/tutorial/request-forms.md | 48 ++- docs/tr/docs/tutorial/static-files.md | 38 +- 21 files changed, 1065 insertions(+), 828 deletions(-) diff --git a/docs/tr/docs/about/index.md b/docs/tr/docs/about/index.md index e9dee5217c..a638fb0cf8 100644 --- a/docs/tr/docs/about/index.md +++ b/docs/tr/docs/about/index.md @@ -1,3 +1,3 @@ -# Hakkฤฑnda +# Hakkฤฑnda { #about } FastAPI, tasarฤฑmฤฑ, ilham kaynaฤŸฤฑ ve daha fazlasฤฑ hakkฤฑnda. ๐Ÿค“ diff --git a/docs/tr/docs/advanced/index.md b/docs/tr/docs/advanced/index.md index 836e63c8ab..3995109e25 100644 --- a/docs/tr/docs/advanced/index.md +++ b/docs/tr/docs/advanced/index.md @@ -1,36 +1,21 @@ -# GeliลŸmiลŸ Kullanฤฑcฤฑ Rehberi +# GeliลŸmiลŸ Kullanฤฑcฤฑ Rehberi { #advanced-user-guide } -## Ek ร–zellikler +## Ek ร–zellikler { #additional-features } -[Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑ **FastAPI**'ฤฑn tรผm ana รถzelliklerini tanฤฑtmaya yetecektir. +Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑ, **FastAPI**'ฤฑn tรผm temel รถzelliklerini tanฤฑmanฤฑz iรงin yeterli olmalฤฑdฤฑr. -ฤฐlerleyen bรถlรผmlerde diฤŸer seรงenekler, konfigรผrasyonlar ve ek รถzellikleri gรถreceฤŸiz. +Sonraki bรถlรผmlerde diฤŸer seรงenekleri, konfigรผrasyonlarฤฑ ve ek รถzellikleri gรถreceksiniz. /// tip | ฤฐpucu Sonraki bรถlรผmler **mutlaka "geliลŸmiลŸ" olmak zorunda deฤŸildir**. -Kullanฤฑm ลŸeklinize baฤŸlฤฑ olarak, รงรถzรผmรผnรผz bu bรถlรผmlerden birinde olabilir. +Ve kullanฤฑm amacฤฑnฤฑza baฤŸlฤฑ olarak, รงรถzรผm bunlardan birinde olabilir. /// -## ร–nce ร–ฤŸreticiyi Okuyun +## ร–nce Tutorial'ฤฑ Okuyun { #read-the-tutorial-first } -[Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑndaki bilgilerle **FastAPI**'nฤฑn รงoฤŸu รถzelliฤŸini kullanabilirsiniz. +Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑndaki bilgilerle **FastAPI**'nฤฑn รงoฤŸu รถzelliฤŸini yine de kullanabilirsiniz. -Sonraki bรถlรผmler bu sayfayฤฑ okuduฤŸunuzu ve bu ana fikirleri bildiฤŸinizi varsayarak hazฤฑrlanmฤฑลŸtฤฑr. - -## DiฤŸer Kurslar - -[Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑ ve bu **GeliลŸmiลŸ Kullanฤฑcฤฑ Rehberi**, รถฤŸretici bir kฤฑlavuz (bir kitap gibi) ลŸeklinde yazฤฑlmฤฑลŸtฤฑr ve **FastAPI'ฤฑ รถฤŸrenmek** iรงin yeterli olsa da, ek kurslarla desteklemek isteyebilirsiniz. - -Belki de รถฤŸrenme tarzฤฑnฤฑza daha iyi uyduฤŸu iรงin baลŸka kurslarฤฑ tercih edebilirsiniz. - -Bazฤฑ kurs saฤŸlayฤฑcฤฑlarฤฑ โœจ [**FastAPI destekรงileridir**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ, bu FastAPI ve **ekosisteminin** sรผrekli ve saฤŸlฤฑklฤฑ bir ลŸekilde **geliลŸmesini** saฤŸlar. - -Ayrฤฑca, size **iyi bir รถฤŸrenme deneyimi** saฤŸlamakla kalmayฤฑp, **iyi ve saฤŸlฤฑklฤฑ bir framework** olan FastAPI'a ve ve **topluluฤŸuna** (yani size) olan gerรงek baฤŸlฤฑlฤฑklarฤฑnฤฑ gรถsterir. - -Onlarฤฑn kurslarฤฑnฤฑ denemek isteyebilirsiniz: - -* Talk Python Training -* Test-Driven Development +Ve sonraki bรถlรผmler, onu zaten okuduฤŸunuzu ve bu temel fikirleri bildiฤŸinizi varsayar. diff --git a/docs/tr/docs/advanced/security/index.md b/docs/tr/docs/advanced/security/index.md index 709f74c721..9b30781f29 100644 --- a/docs/tr/docs/advanced/security/index.md +++ b/docs/tr/docs/advanced/security/index.md @@ -1,6 +1,6 @@ -# GeliลŸmiลŸ Gรผvenlik +# GeliลŸmiลŸ Gรผvenlik { #advanced-security } -## Ek ร–zellikler +## Ek ร–zellikler { #additional-features } [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank} sayfasฤฑnda ele alฤฑnanlarฤฑn dฤฑลŸฤฑnda gรผvenlikle ilgili bazฤฑ ek รถzellikler vardฤฑr. @@ -8,12 +8,12 @@ Sonraki bรถlรผmler **mutlaka "geliลŸmiลŸ" olmak zorunda deฤŸildir**. -Kullanฤฑm ลŸeklinize baฤŸlฤฑ olarak, รงรถzรผmรผnรผz bu bรถlรผmlerden birinde olabilir. +Ve kullanฤฑm durumunuza gรถre, รงรถzรผm bu bรถlรผmlerden birinde olabilir. /// -## ร–nce ร–ฤŸreticiyi Okuyun +## ร–nce ร–ฤŸreticiyi Okuyun { #read-the-tutorial-first } -Sonraki bรถlรผmler [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank} sayfasฤฑnฤฑ okuduฤŸunuzu varsayarak hazฤฑrlanmฤฑลŸtฤฑr. +Sonraki bรถlรผmler, ana [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank} sayfasฤฑnฤฑ zaten okuduฤŸunuzu varsayar. -Bu bรถlรผmler aynฤฑ kavramlara dayanฤฑr, ancak bazฤฑ ek iลŸlevsellikler saฤŸlar. +Hepsi aynฤฑ kavramlara dayanฤฑr, ancak bazฤฑ ek iลŸlevselliklere izin verir. diff --git a/docs/tr/docs/advanced/testing-websockets.md b/docs/tr/docs/advanced/testing-websockets.md index effe557d19..da12abadb8 100644 --- a/docs/tr/docs/advanced/testing-websockets.md +++ b/docs/tr/docs/advanced/testing-websockets.md @@ -1,13 +1,13 @@ -# WebSockets'i Test Etmek +# WebSockets'i Test Etmek { #testing-websockets } -WebSockets testi yapmak iรงin `TestClient`'ฤฑ kullanabilirsiniz. +WebSockets'i test etmek iรงin aynฤฑ `TestClient`'ฤฑ kullanabilirsiniz. -Bu iลŸlem iรงin, `TestClient`'ฤฑ bir `with` ifadesinde kullanarak WebSocket'e baฤŸlanabilirsiniz: +Bunun iรงin `TestClient`'ฤฑ bir `with` ifadesinde kullanarak WebSocket'e baฤŸlanฤฑrsฤฑnฤฑz: -{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} /// note | Not -Daha fazla detay iรงin Starlette'in Websockets'i Test Etmek dokรผmantasyonunu inceleyin. +Daha fazla detay iรงin Starlette'in WebSockets'i test etme dokรผmantasyonuna bakฤฑn. /// diff --git a/docs/tr/docs/advanced/wsgi.md b/docs/tr/docs/advanced/wsgi.md index 00815a4b2f..442f83a59a 100644 --- a/docs/tr/docs/advanced/wsgi.md +++ b/docs/tr/docs/advanced/wsgi.md @@ -1,32 +1,32 @@ -# WSGI - Flask, Django ve Daha Fazlasฤฑnฤฑ FastAPI ile Kullanma +# WSGI'yi Dahil Etme - Flask, Django ve DiฤŸerleri { #including-wsgi-flask-django-others } -WSGI uygulamalarฤฑnฤฑ [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bรถlรผmlerinde gรถrdรผฤŸรผnรผz gibi baฤŸlayabilirsiniz. +WSGI uygulamalarฤฑnฤฑ [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bรถlรผmlerinde gรถrdรผฤŸรผnรผz gibi mount edebilirsiniz. -Bunun iรงin `WSGIMiddleware` ile Flask, Django vb. WSGI uygulamanฤฑzฤฑ sarmalayabilir ve FastAPI'ya baฤŸlayabilirsiniz. +Bunun iรงin `WSGIMiddleware`'ฤฑ kullanabilir ve bunu WSGI uygulamanฤฑzฤฑ (รถrneฤŸin Flask, Django vb.) sarmalamak iรงin kullanabilirsiniz. -## `WSGIMiddleware` Kullanฤฑmฤฑ +## `WSGIMiddleware` Kullanฤฑmฤฑ { #using-wsgimiddleware } -`WSGIMiddleware`'ฤฑ projenize dahil edin. +`WSGIMiddleware`'ฤฑ import etmeniz gerekir. -Ardฤฑndan WSGI (รถrneฤŸin Flask) uygulamanฤฑzฤฑ middleware ile sarmalayฤฑn. +Ardฤฑndan WSGI (รถrn. Flask) uygulamasฤฑnฤฑ middleware ile sarmalayฤฑn. -Son olarak da bir yol altฤฑnda baฤŸlama iลŸlemini gerรงekleลŸtirin. +Ve sonra bunu bir path'in altฤฑna mount edin. -{* ../../docs_src/wsgi/tutorial001.py hl[2:3,23] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} -## Kontrol Edelim +## Kontrol Edelim { #check-it } -Artฤฑk `/v1/` yolunun altฤฑndaki her istek Flask uygulamasฤฑ tarafฤฑndan iลŸlenecektir. +Artฤฑk `/v1/` path'i altฤฑndaki her request Flask uygulamasฤฑ tarafฤฑndan iลŸlenecektir. Geri kalanฤฑ ise **FastAPI** tarafฤฑndan iลŸlenecektir. -EฤŸer uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑrฤฑp http://localhost:8000/v1/ adresine giderseniz, Flask'tan gelen yanฤฑtฤฑ gรถreceksiniz: +EฤŸer uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑrฤฑp http://localhost:8000/v1/ adresine giderseniz, Flask'tan gelen response'u gรถreceksiniz: ```txt Hello, World from Flask! ``` -EฤŸer http://localhost:8000/v2/ adresine giderseniz, FastAPI'dan gelen yanฤฑtฤฑ gรถreceksiniz: +Ve eฤŸer http://localhost:8000/v2 adresine giderseniz, FastAPI'dan gelen response'u gรถreceksiniz: ```JSON { diff --git a/docs/tr/docs/benchmarks.md b/docs/tr/docs/benchmarks.md index eb5472869a..f2b8585856 100644 --- a/docs/tr/docs/benchmarks.md +++ b/docs/tr/docs/benchmarks.md @@ -1,34 +1,34 @@ -# Kฤฑyaslamalar +# Kฤฑyaslamalar { #benchmarks } -BaฤŸฤฑmsฤฑz TechEmpower kฤฑyaslamalarฤฑ gรถsteriyor ki en hฤฑzlฤฑ Python frameworklerinden birisi olan Uvicorn ile รงalฤฑลŸtฤฑrฤฑlan **FastAPI** uygulamalarฤฑ, sadece Starlette ve Uvicorn'dan daha dรผลŸรผk sฤฑralamada (FastAPI bu frameworklerin รผzerine kurulu) yer alฤฑyor. (*) +BaฤŸฤฑmsฤฑz TechEmpower kฤฑyaslamalarฤฑ, Uvicorn altฤฑnda รงalฤฑลŸan **FastAPI** uygulamalarฤฑnฤฑn mevcut en hฤฑzlฤฑ Python frameworklerinden biri olduฤŸunu, yalnฤฑzca Starlette ve Uvicorn'un kendilerinin altฤฑnda yer aldฤฑฤŸฤฑnฤฑ gรถsteriyor (FastAPI bunlarฤฑ dahili olarak kullanฤฑr). Fakat kฤฑyaslamalarฤฑ ve karลŸฤฑlaลŸtฤฑrmalarฤฑ incelerken ลŸunlarฤฑ aklฤฑnฤฑzda bulundurmalฤฑsฤฑnฤฑz. -## Kฤฑyaslamalar ve Hฤฑz +## Kฤฑyaslamalar ve Hฤฑz { #benchmarks-and-speed } -Kฤฑyaslamalarฤฑ incelediฤŸinizde, farklฤฑ รถzelliklere sahip araรงlarฤฑn eลŸdeฤŸer olarak karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnฤฑ yaygฤฑn bir ลŸekilde gรถrebilirsiniz. +Kฤฑyaslamalara baktฤฑฤŸฤฑnฤฑzda, farklฤฑ tรผrlerdeki birkaรง aracฤฑn eลŸdeฤŸermiลŸ gibi karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnฤฑ gรถrmek yaygฤฑndฤฑr. ร–zellikle, (diฤŸer birรงok araรง arasฤฑnda) Uvicorn, Starlette ve FastAPI'ฤฑn birlikte karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnฤฑ gรถrebilirsiniz. -Aracฤฑn รงรถzdรผฤŸรผ problem ne kadar basitse, performansฤฑ o kadar iyi olacaktฤฑr. Ancak kฤฑyaslamalarฤฑn รงoฤŸu, aracฤฑn saฤŸladฤฑฤŸฤฑ ek รถzellikleri test etmez. +Aracฤฑn รงรถzdรผฤŸรผ problem ne kadar basitse, elde edeceฤŸi performans o kadar iyi olur. Ayrฤฑca kฤฑyaslamalarฤฑn รงoฤŸu, aracฤฑn saฤŸladฤฑฤŸฤฑ ek รถzellikleri test etmez. HiyerarลŸi ลŸรถyledir: * **Uvicorn**: bir ASGI sunucusu - * **Starlette**: (Uvicorn'u kullanฤฑr) bir web mikroframeworkรผ - * **FastAPI**: (Starlette'i kullanฤฑr) veri doฤŸrulama vb. รงeลŸitli ek รถzelliklere sahip, API oluลŸturmak iรงin kullanฤฑlan bir API mikroframeworkรผ + * **Starlette**: (Uvicorn'u kullanฤฑr) bir web mikroframework'รผ + * **FastAPI**: (Starlette'i kullanฤฑr) veri doฤŸrulama vb. ile API'lar oluลŸturmak iรงin รงeลŸitli ek รถzelliklere sahip bir API mikroframework'รผ * **Uvicorn**: - * Sunucunun kendisi dฤฑลŸฤฑnda ekstra bir kod iรงermediฤŸi iรงin en iyi performansa sahip olacaktฤฑr. - * DoฤŸrudan Uvicorn ile bir uygulama yazmazsฤฑnฤฑz. Bu, yazdฤฑฤŸฤฑnฤฑz kodun en azฤฑndan Starlette tarafฤฑndan saฤŸlanan tรผm kodu (veya **FastAPI**) az รงok iรงermesi gerektiฤŸi anlamฤฑna gelir. EฤŸer bunu yaptฤฑysanฤฑz, son uygulamanฤฑz bir framework kullanmak ve uygulama kodlarฤฑnฤฑ ve hatalarฤฑ en aza indirmekle aynฤฑ ek yรผke sahip olacaktฤฑr. - * EฤŸer Uvicorn'u karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Daphne, Hypercorn, uWSGI, vb. uygulama sunucularฤฑ ile karลŸฤฑlaลŸtฤฑrฤฑn. + * Sunucunun kendisi dฤฑลŸฤฑnda รงok fazla ekstra kod iรงermediฤŸi iรงin en iyi performansa sahip olacaktฤฑr. + * Uvicorn ile doฤŸrudan bir uygulama yazmazsฤฑnฤฑz. Bu, kodunuzun en azฤฑndan Starlette'in (veya **FastAPI**'ฤฑn) saฤŸladฤฑฤŸฤฑ kodun aลŸaฤŸฤฑ yukarฤฑ tamamฤฑnฤฑ iรงermesi gerektiฤŸi anlamฤฑna gelir. Bunu yaparsanฤฑz, nihai uygulamanฤฑz; bir framework kullanmฤฑลŸ olmanฤฑn ve uygulama kodunu ve bug'larฤฑ en aza indirmenin getirdiฤŸi ek yรผkle aynฤฑ ek yรผke sahip olur. + * Uvicorn'u karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Daphne, Hypercorn, uWSGI vb. application server'larla karลŸฤฑlaลŸtฤฑrฤฑn. * **Starlette**: - * Uvicorn'dan sonraki en iyi performansa sahip olacaktฤฑr. ฤฐลŸin aslฤฑ, Starlette รงalฤฑลŸmak iรงin Uvicorn'u kullanฤฑyor. Dolayฤฑsฤฑyla, daha fazla kod รงalฤฑลŸtฤฑrmaasฤฑ gerektiฤŸinden muhtemelen Uvicorn'dan sadece "daha yavaลŸ" olabilir. - * Ancak yol bazlฤฑ yรถnlendirme vb. basit web uygulamalarฤฑ oluลŸturmak iรงin araรงlar saฤŸlar. - * EฤŸer Starlette'i karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Sanic, Flask, Django, vb. frameworkler (veya mikroframeworkler) ile karลŸฤฑlaลŸtฤฑrฤฑn. + * Uvicorn'dan sonra en iyi performansa sahip olacaktฤฑr. Aslฤฑnda Starlette รงalฤฑลŸmak iรงin Uvicorn'u kullanฤฑr. Bu yรผzden muhtemelen yalnฤฑzca daha fazla kod รงalฤฑลŸtฤฑrmak zorunda kaldฤฑฤŸฤฑ iรงin Uvicorn'dan "daha yavaลŸ" olabilir. + * Ancak path tabanlฤฑ routing vb. ile basit web uygulamalarฤฑ oluลŸturmanฤฑz iรงin araรงlar saฤŸlar. + * Starlette'i karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Sanic, Flask, Django vb. web framework'lerle (veya mikroframework'lerle) karลŸฤฑlaลŸtฤฑrฤฑn. * **FastAPI**: - * Starlette'in Uvicorn'u kullandฤฑฤŸฤฑ ve ondan daha hฤฑzlฤฑ olamayacaฤŸฤฑ gibi, **FastAPI**'da Starlette'i kullanฤฑr, dolayฤฑsฤฑyla ondan daha hฤฑzlฤฑ olamaz. - * FastAPI, Starlette'e ek olarak daha fazla รถzellik sunar. Bunlar veri doฤŸrulama ve dรถnรผลŸรผmรผ gibi API'lar oluลŸtururken neredeyse ve her zaman ihtiyaรง duyduฤŸunuz รถzelliklerdir. Ve bunu kullanarak, รผcretsiz olarak otomatik dokรผmantasyon elde edersiniz (otomatik dokรผmantasyon รงalฤฑลŸan uygulamalara ek yรผk getirmez, baลŸlangฤฑรงta oluลŸturulur). - * FastAPI'ฤฑ kullanmadฤฑysanฤฑz ve Starlette'i doฤŸrudan kullandฤฑysanฤฑz (veya baลŸka bir araรง, Sanic, Flask, Responder, vb.) tรผm veri doฤŸrulama ve dรถnรผลŸtรผrme araรงlarฤฑnฤฑ kendiniz geliลŸtirmeniz gerekir. Dolayฤฑsฤฑyla, son uygulamanฤฑz FastAPI kullanฤฑlarak oluลŸturulmuลŸ gibi hรขlรข aynฤฑ ek yรผke sahip olacaktฤฑr. ร‡oฤŸu durumda, uygulamalarda yazฤฑlan kodun bรผyรผk bir kฤฑsmฤฑnฤฑ veri doฤŸrulama ve dรถnรผลŸtรผrme kodlarฤฑ oluลŸturur. - * Dolayฤฑsฤฑyla, FastAPI'ฤฑ kullanarak geliลŸtirme sรผresinden, hatalardan, kod satฤฑrlarฤฑndan tasarruf edersiniz ve kullanmadฤฑฤŸฤฑnฤฑz durumda (birรงok รถzelliฤŸi geliลŸtirmek zorunda kalmakla birlikte) muhtemelen aynฤฑ performansฤฑ (veya daha iyisini) elde ederdiniz. - * EฤŸer FastAPI'ฤฑ karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Flask-apispec, NestJS, Molten, vb. gibi veri doฤŸrulama, dรถnรผลŸtรผrme ve dokรผmantasyon saฤŸlayan bir web uygulamasฤฑ frameworkรผ ile (veya araรง setiyle) karลŸฤฑlaลŸtฤฑrฤฑn. + * Starlette'in Uvicorn'u kullanฤฑp ondan daha hฤฑzlฤฑ olamamasฤฑ gibi, **FastAPI** da Starlette'i kullanฤฑr; dolayฤฑsฤฑyla ondan daha hฤฑzlฤฑ olamaz. + * FastAPI, Starlette'in รผzerine daha fazla รถzellik saฤŸlar. API'lar oluลŸtururken neredeyse her zaman ihtiyaรง duyduฤŸunuz veri doฤŸrulama ve serialization gibi รถzellikler. Ayrฤฑca bunu kullanarak รผcretsiz olarak otomatik dokรผmantasyon elde edersiniz (otomatik dokรผmantasyon, รงalฤฑลŸan uygulamalara ek yรผk bile getirmez; startup'ta รผretilir). + * FastAPI'ฤฑ kullanmayฤฑp Starlette'i doฤŸrudan kullansaydฤฑnฤฑz (veya Sanic, Flask, Responder vb. baลŸka bir aracฤฑ), tรผm veri doฤŸrulama ve serialization iลŸlemlerini kendiniz uygulamak zorunda kalฤฑrdฤฑnฤฑz. Dolayฤฑsฤฑyla nihai uygulamanฤฑz, FastAPI kullanฤฑlarak inลŸa edilmiลŸ olsaydฤฑ sahip olacaฤŸฤฑ ek yรผkle hรขlรข aynฤฑ ek yรผke sahip olurdu. Ve รงoฤŸu durumda, uygulamalarda yazฤฑlan en bรผyรผk kod miktarฤฑ veri doฤŸrulama ve serialization kฤฑsmฤฑdฤฑr. + * Bu nedenle FastAPI kullanarak geliลŸtirme sรผresinden, bug'lardan, kod satฤฑrlarฤฑndan tasarruf edersiniz; ayrฤฑca muhtemelen, onu kullanmasaydฤฑnฤฑz (tรผm bunlarฤฑ kodunuzda kendiniz uygulamak zorunda kalacaฤŸฤฑnฤฑz iรงin) elde edeceฤŸiniz performansฤฑn aynฤฑsฤฑnฤฑ (veya daha iyisini) elde edersiniz. + * FastAPI'ฤฑ karลŸฤฑlaลŸtฤฑrฤฑyorsanฤฑz, Flask-apispec, NestJS, Molten vb. veri doฤŸrulama, serialization ve dokรผmantasyon saฤŸlayan bir web uygulamasฤฑ framework'รผ (veya araรง seti) ile karลŸฤฑlaลŸtฤฑrฤฑn. Entegre otomatik veri doฤŸrulama, serialization ve dokรผmantasyona sahip framework'ler. diff --git a/docs/tr/docs/deployment/cloud.md b/docs/tr/docs/deployment/cloud.md index 4f82e9d0bb..25ce6ca8dd 100644 --- a/docs/tr/docs/deployment/cloud.md +++ b/docs/tr/docs/deployment/cloud.md @@ -1,13 +1,24 @@ -# FastAPI Uygulamasฤฑnฤฑ Bulut SaฤŸlayฤฑcฤฑlar รœzerinde Yayฤฑnlama +# Bulut SaฤŸlayฤฑcฤฑlar รœzerinde FastAPI Yayฤฑnlama { #deploy-fastapi-on-cloud-providers } -FastAPI uygulamasฤฑnฤฑ yayฤฑnlamak iรงin hemen hemen **herhangi bir bulut saฤŸlayฤฑcฤฑyฤฑ** kullanabilirsiniz. +FastAPI uygulamanฤฑzฤฑ yayฤฑnlamak iรงin neredeyse **herhangi bir bulut saฤŸlayฤฑcฤฑyฤฑ** kullanabilirsiniz. -Bรผyรผk bulut saฤŸlayฤฑcฤฑlarฤฑn รงoฤŸu FastAPI uygulamasฤฑnฤฑ yayฤฑnlamak iรงin kฤฑlavuzlara sahiptir. +ร‡oฤŸu durumda, ana bulut saฤŸlayฤฑcฤฑlarฤฑn FastAPI'yi onlarla birlikte yayฤฑnlamak iรงin kฤฑlavuzlarฤฑ vardฤฑr. -## Bulut SaฤŸlayฤฑcฤฑlar - Sponsorlar +## FastAPI Cloud { #fastapi-cloud } -Bazฤฑ bulut saฤŸlayฤฑcฤฑlar โœจ [**FastAPI destekรงileridir**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ, bu FastAPI ve **ekosisteminin** sรผrekli ve saฤŸlฤฑklฤฑ bir ลŸekilde **geliลŸmesini** saฤŸlar. +**FastAPI Cloud**, **FastAPI**'nin arkasฤฑndaki aynฤฑ yazar ve ekip tarafฤฑndan geliลŸtirilmiลŸtir. -Ayrฤฑca, size **iyi servisler** saฤŸlamakla kalmayฤฑp, **iyi ve saฤŸlฤฑklฤฑ bir framework** olan FastAPI'a baฤŸlฤฑlฤฑklarฤฑnฤฑ gรถsterir. +Bir API'yi minimum รงabayla **oluลŸturma**, **yayฤฑnlama** ve **eriลŸme** sรผrecini kolaylaลŸtฤฑrฤฑr. -Bu hizmetleri denemek ve kฤฑlavuzlarฤฑnฤฑ incelemek isteyebilirsiniz. +FastAPI ile uygulama geliลŸtirirken elde edilen aynฤฑ **geliลŸtirici deneyimini**, onlarฤฑ buluta **yayฤฑnlamaya** da taลŸฤฑr. ๐ŸŽ‰ + +FastAPI Cloud, *FastAPI and friends* aรงฤฑk kaynak projelerinin birincil sponsoru ve finansman saฤŸlayฤฑcฤฑsฤฑdฤฑr. โœจ + +## Bulut SaฤŸlayฤฑcฤฑlar - Sponsorlar { #cloud-providers-sponsors } + +DiฤŸer bazฤฑ bulut saฤŸlayฤฑcฤฑlar da โœจ [**FastAPI'ye sponsor olur**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ. ๐Ÿ™‡ + +Kฤฑlavuzlarฤฑnฤฑ takip etmek ve servislerini denemek iรงin onlarฤฑ da deฤŸerlendirmek isteyebilirsiniz: + +* Render +* Railway diff --git a/docs/tr/docs/deployment/index.md b/docs/tr/docs/deployment/index.md index e03bb4ee0e..055d999294 100644 --- a/docs/tr/docs/deployment/index.md +++ b/docs/tr/docs/deployment/index.md @@ -1,21 +1,23 @@ -# Deployment (Yayฤฑnlama) +# Deployment { #deployment } -**FastAPI** uygulamasฤฑnฤฑ deploy etmek oldukรงa kolaydฤฑr. +**FastAPI** uygulamasฤฑnฤฑ deploy etmek nispeten kolaydฤฑr. -## Deployment Ne Anlama Gelir? +## Deployment Ne Anlama Gelir? { #what-does-deployment-mean } -Bir uygulamayฤฑ **deploy** etmek (yayฤฑnlamak), uygulamayฤฑ **kullanฤฑcฤฑlara eriลŸilebilir hale getirmek** iรงin gerekli adฤฑmlarฤฑ gerรงekleลŸtirmek anlamฤฑna gelir. +Bir uygulamayฤฑ **deploy** etmek, onu **kullanฤฑcฤฑlara eriลŸilebilir hale getirmek** iรงin gerekli adฤฑmlarฤฑ gerรงekleลŸtirmek anlamฤฑna gelir. -Bir **Web API** iรงin bu sรผreรง normalde uygulamayฤฑ **uzak bir makineye** yerleลŸtirmeyi, iyi performans, kararlฤฑlฤฑk vb. รถzellikler saฤŸlayan bir **sunucu programฤฑ** ile **kullanฤฑcฤฑlarฤฑnฤฑzฤฑn** uygulamaya etkili ve kesintisiz bir ลŸekilde **eriลŸebilmesini** kapsar. +Bir **web API** iรงin bu sรผreรง normalde uygulamayฤฑ **uzak bir makineye** yerleลŸtirmeyi, iyi performans, kararlฤฑlฤฑk vb. รถzellikler saฤŸlayan bir **sunucu programฤฑ** ile **kullanฤฑcฤฑlarฤฑnฤฑzฤฑn** uygulamaya etkili ve kesintisiz bir ลŸekilde, sorun yaลŸamadan **eriลŸebilmesini** kapsar. -Bu, kodu sรผrekli olarak deฤŸiลŸtirdiฤŸiniz, hata alฤฑp hata giderdiฤŸiniz, geliลŸtirme sunucusunu durdurup yeniden baลŸlattฤฑฤŸฤฑnฤฑz vb. **geliลŸtirme** aลŸamalarฤฑnฤฑn tam tersidir. +Bu, kodu sรผrekli olarak deฤŸiลŸtirdiฤŸiniz, bozup dรผzelttiฤŸiniz, geliลŸtirme sunucusunu durdurup yeniden baลŸlattฤฑฤŸฤฑnฤฑz vb. **geliลŸtirme** aลŸamalarฤฑnฤฑn tam tersidir. -## Deployment Stratejileri +## Deployment Stratejileri { #deployment-strategies } -Kullanฤฑm durumunuza ve kullandฤฑฤŸฤฑnฤฑz araรงlara baฤŸlฤฑ olarak bir kaรง farklฤฑ yol izleyebilirsiniz. +Kullanฤฑm durumunuza ve kullandฤฑฤŸฤฑnฤฑz araรงlara baฤŸlฤฑ olarak bunu yapmanฤฑn birkaรง yolu vardฤฑr. -Bir dizi araรง kombinasyonunu kullanarak kendiniz **bir sunucu yayฤฑnlayabilirsiniz**, yayฤฑnlama sรผrecinin bir kฤฑsmฤฑnฤฑ sizin iรงin gerรงekleลŸtiren bir **bulut hizmeti** veya diฤŸer olasฤฑ seรงenekleri kullanabilirsiniz. +Bir dizi araรง kombinasyonunu kullanarak kendiniz **bir sunucu deploy edebilirsiniz**, yayฤฑnlama sรผrecinin bir kฤฑsmฤฑnฤฑ sizin iรงin gerรงekleลŸtiren bir **bulut hizmeti** veya diฤŸer olasฤฑ seรงenekleri kullanabilirsiniz. + +ร–rneฤŸin, FastAPI'nin arkasฤฑndaki ekip olarak, FastAPI uygulamalarฤฑnฤฑ buluta mรผmkรผn olduฤŸunca akฤฑcฤฑ ลŸekilde deploy etmeyi saฤŸlamak iรงin, FastAPI ile รงalฤฑลŸmanฤฑn aynฤฑ geliลŸtirici deneyimini sunarak **FastAPI Cloud**'u oluลŸturduk. **FastAPI** uygulamasฤฑnฤฑ yayฤฑnlarken aklฤฑnฤฑzda bulundurmanฤฑz gereken ana kavramlardan bazฤฑlarฤฑnฤฑ size gรถstereceฤŸim (ancak bunlarฤฑn รงoฤŸu diฤŸer web uygulamalarฤฑ iรงin de geรงerlidir). -Sonraki bรถlรผmlerde akฤฑlda tutulmasฤฑ gereken diฤŸer ayrฤฑntฤฑlarฤฑ ve yayฤฑnlama tekniklerinden bazฤฑlarฤฑnฤฑ gรถreceksiniz. โœจ +Sonraki bรถlรผmlerde akฤฑlda tutulmasฤฑ gereken diฤŸer ayrฤฑntฤฑlarฤฑ ve bunu yapmaya yรถnelik bazฤฑ teknikleri gรถreceksiniz. โœจ diff --git a/docs/tr/docs/how-to/general.md b/docs/tr/docs/how-to/general.md index cbfa7beb27..e3154921a4 100644 --- a/docs/tr/docs/how-to/general.md +++ b/docs/tr/docs/how-to/general.md @@ -1,39 +1,39 @@ -# Genel - Nasฤฑl Yapฤฑlฤฑr - Tarifler +# Genel - Nasฤฑl Yapฤฑlฤฑr - Tarifler { #general-how-to-recipes } -Bu sayfada genel ve sฤฑkรงa sorulan sorular iรงin dokรผmantasyonun diฤŸer sayfalarฤฑna yรถnlendirmeler bulunmaktadฤฑr. +Bu sayfada genel veya sฤฑk sorulan sorular iรงin dokรผmantasyonun diฤŸer bรถlรผmlerine รงeลŸitli yรถnlendirmeler bulunmaktadฤฑr. -## Veri Filtreleme - Gรผvenlik +## Veri Filtreleme - Gรผvenlik { #filter-data-security } -Dรถndรผrmeniz gereken veriden fazlasฤฑnฤฑ dรถndรผrmediฤŸinizden emin olmak iรงin, [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Dรถndรผrmeniz gerekenden daha fazla veri dรถndรผrmediฤŸinizden emin olmak iรงin, [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## Dokรผmantasyon Etiketleri - OpenAPI +## Dokรผmantasyon Etiketleri - OpenAPI { #documentation-tags-openapi } -*Yol operasyonlarฤฑnฤฑza* etiketler ekleyerek dokรผmantasyon arayรผzรผnde gruplar halinde gรถrรผnmesini saฤŸlamak iรงin, [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +*path operation*'larฤฑnฤฑza etiketler eklemek ve dokรผmantasyon arayรผzรผnde gruplamak iรงin, [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## Dokรผmantasyon ร–zeti ve Aรงฤฑklamasฤฑ - OpenAPI +## Dokรผmantasyon ร–zeti ve Aรงฤฑklamasฤฑ - OpenAPI { #documentation-summary-and-description-openapi } -*Yol operasyonlarฤฑnฤฑza* รถzet ve aรงฤฑklama ekleyip dokรผmantasyon arayรผzรผnde gรถrรผnmesini saฤŸlamak iรงin, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +*path operation*'larฤฑnฤฑza รถzet ve aรงฤฑklama eklemek ve bunlarฤฑ dokรผmantasyon arayรผzรผnde gรถstermek iรงin, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## Yanฤฑt Aรงฤฑklamasฤฑ Dokรผmantasyonu - OpenAPI +## Dokรผmantasyon Yanฤฑt Aรงฤฑklamasฤฑ - OpenAPI { #documentation-response-description-openapi } -Dokรผmantasyon arayรผzรผnde yer alan yanฤฑt aรงฤฑklamasฤฑnฤฑ tanฤฑmlamak iรงin, [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Dokรผmantasyon arayรผzรผnde gรถsterilen response aรงฤฑklamasฤฑnฤฑ tanฤฑmlamak iรงin, [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## *Yol Operasyonunu* Kullanฤฑmdan Kaldฤฑrma - OpenAPI +## Dokรผmantasyonda Bir *Path Operation*'ฤฑ Kullanฤฑmdan Kaldฤฑrma - OpenAPI { #documentation-deprecate-a-path-operation-openapi } -Bir *yol iลŸlemi*ni kullanฤฑmdan kaldฤฑrmak ve bunu dokรผmantasyon arayรผzรผnde gรถstermek iรงin, [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Bir *path operation*'ฤฑ kullanฤฑmdan kaldฤฑrmak ve bunu dokรผmantasyon arayรผzรผnde gรถstermek iรงin, [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## Herhangi Bir Veriyi JSON Uyumlu Hale Getirme +## Herhangi Bir Veriyi JSON Uyumlu Hale Getirme { #convert-any-data-to-json-compatible } -Herhangi bir veriyi JSON uyumlu hale getirmek iรงin, [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Herhangi bir veriyi JSON uyumlu hale getirmek iรงin, [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## OpenAPI Meta Verileri - Dokรผmantasyon +## OpenAPI Meta Verileri - Dokรผmantasyon { #openapi-metadata-docs } -OpenAPI ลŸemanฤฑza lisans, sรผrรผm, iletiลŸim vb. meta veriler eklemek iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Lisans, sรผrรผm, iletiลŸim vb. dahil olmak รผzere OpenAPI ลŸemanฤฑza meta veriler eklemek iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## OpenAPI BaฤŸlantฤฑ ร–zelleลŸtirme +## OpenAPI ร–zel URL { #openapi-custom-url } -OpenAPI baฤŸlantฤฑsฤฑnฤฑ รถzelleลŸtirmek (veya kaldฤฑrmak) iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +OpenAPI URL'ini รถzelleลŸtirmek (veya kaldฤฑrmak) iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## OpenAPI Dokรผmantasyon BaฤŸlantฤฑlarฤฑ +## OpenAPI Dokรผmantasyon URL'leri { #openapi-docs-urls } -Dokรผmantasyonu arayรผzรผnde kullanฤฑlan baฤŸlantฤฑlarฤฑ gรผncellemek iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} sayfasฤฑnฤฑ okuyun. +Otomatik olarak oluลŸturulan dokรผmantasyon kullanฤฑcฤฑ arayรผzlerinde kullanฤฑlan URL'leri gรผncellemek iรงin, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} dokรผmantasyonunu okuyun. diff --git a/docs/tr/docs/how-to/index.md b/docs/tr/docs/how-to/index.md index 26dd9026ce..5ec2e0268f 100644 --- a/docs/tr/docs/how-to/index.md +++ b/docs/tr/docs/how-to/index.md @@ -1,13 +1,13 @@ -# Nasฤฑl Yapฤฑlฤฑr - Tarifler +# Nasฤฑl Yapฤฑlฤฑr - Tarifler { #how-to-recipes } -Burada รงeลŸitli konular hakkฤฑnda farklฤฑ tarifler veya "nasฤฑl yapฤฑlฤฑr" kฤฑlavuzlarฤฑ yer alฤฑyor. +Burada **รงeลŸitli konular** hakkฤฑnda farklฤฑ tarifler veya "nasฤฑl yapฤฑlฤฑr" kฤฑlavuzlarฤฑ gรถreceksiniz. -Bu fikirlerin bรผyรผk bir kฤฑsmฤฑ aลŸaฤŸฤฑ yukarฤฑ **baฤŸฤฑmsฤฑz** olacaktฤฑr, รงoฤŸu durumda bunlarฤฑ sadece **projenize** hitap ediyorsa incelemelisiniz. +Bu fikirlerin bรผyรผk bir kฤฑsmฤฑ aลŸaฤŸฤฑ yukarฤฑ **baฤŸฤฑmsฤฑz** olacaktฤฑr ve รงoฤŸu durumda bunlarฤฑ yalnฤฑzca doฤŸrudan **projenize** uygulanฤฑyorsa incelemeniz yeterli olacaktฤฑr. -Projeniz iรงin ilginรง ve yararlฤฑ gรถrรผnen bir ลŸey varsa devam edin ve inceleyin, aksi halde bunlarฤฑ atlayabilirsiniz. +Projeniz iรงin ilginรง ve yararlฤฑ gรถrรผnen bir ลŸey varsa devam edin ve inceleyin; aksi halde muhtemelen bunlarฤฑ atlayabilirsiniz. /// tip | ฤฐpucu -**FastAPI**'ฤฑ dรผzgรผn (ve รถnerilen) ลŸekilde รถฤŸrenmek istiyorsanฤฑz [ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bรถlรผm bรถlรผm okuyun. +**FastAPI**'ฤฑ yapฤฑlandฤฑrฤฑlmฤฑลŸ bir ลŸekilde (รถnerilir) **รถฤŸrenmek** istiyorsanฤฑz bunun yerine [ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bรถlรผm bรถlรผm okuyun. /// diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index 516d5959ef..9cffd4274f 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -1,14 +1,14 @@ -# FastAPI +# FastAPI { #fastapi }

- FastAPI + FastAPI

- FastAPI framework, yรผksek performanslฤฑ, รถฤŸrenmesi oldukรงa kolay, kodlamasฤฑ hฤฑzlฤฑ, kullanฤฑma hazฤฑr + FastAPI framework, yรผksek performanslฤฑ, รถฤŸrenmesi kolay, kodlamasฤฑ hฤฑzlฤฑ, production'a hazฤฑr

@@ -27,59 +27,65 @@ --- -**Dokรผmantasyon**: https://fastapi.tiangolo.com +**Dokรผmantasyon**: https://fastapi.tiangolo.com **Kaynak Kod**: https://github.com/fastapi/fastapi --- -FastAPI, Python 'nin standart tip belirteรงlerine dayalฤฑ, modern ve hฤฑzlฤฑ (yรผksek performanslฤฑ) API'lar oluลŸturmak iรงin kullanฤฑlabilecek web framework'tรผr. +FastAPI, Python'un standart type hints'lerine dayalฤฑ olarak Python ile API'lar oluลŸturmak iรงin kullanฤฑlan modern ve hฤฑzlฤฑ (yรผksek performanslฤฑ) bir web framework'รผdรผr. Temel รถzellikleri ลŸunlardฤฑr: -* **Hฤฑzlฤฑ**: ร‡ok yรผksek performanslฤฑ, **NodeJS** ve **Go** ile eลŸit dรผzeyde (Starlette ve Pydantic sayesinde). [En hฤฑzlฤฑ Python framework'lerinden bir tanesidir](#performans). -* **Kodlamasฤฑ Hฤฑzlฤฑ**: GeliลŸtirme hฤฑzฤฑnฤฑ yaklaลŸฤฑk %200 ile %300 aralฤฑฤŸฤฑnda arttฤฑrฤฑr. * +* **Hฤฑzlฤฑ**: ร‡ok yรผksek performanslฤฑ, **NodeJS** ve **Go** ile eลŸit dรผzeyde (Starlette ve Pydantic sayesinde). [Mevcut en hฤฑzlฤฑ Python framework'lerinden biri](#performance). +* **Kodlamasฤฑ Hฤฑzlฤฑ**: ร–zellik geliลŸtirme hฤฑzฤฑnฤฑ yaklaลŸฤฑk %200 ile %300 aralฤฑฤŸฤฑnda artฤฑrฤฑr. * * **Daha az hata**: ฤฐnsan (geliลŸtirici) kaynaklฤฑ hatalarฤฑ yaklaลŸฤฑk %40 azaltฤฑr. * -* **Sezgisel**: MuhteลŸem bir editรถr desteฤŸi. Her yerde otomatik tamamlama. Hata ayฤฑklama ile daha az zaman harcayacaksฤฑnฤฑz. -* **Kolay**: ร–ฤŸrenmesi ve kullanmasฤฑ kolay olacak ลŸekilde tasarlandฤฑ. Dokรผman okuma ile daha az zaman harcayacaksฤฑnฤฑz. -* **Kฤฑsa**: Kod tekrarฤฑ minimize edildi. Her parametre tanฤฑmlamasฤฑnda birden fazla รถzellik ve daha az hatayla karลŸฤฑlaลŸacaksฤฑnฤฑz. -* **Gรผรงlรผ**: Otomatik ve etkileลŸimli dokรผmantasyon ile birlikte, kullanฤฑma hazฤฑr kod elde edebilirsiniz. -* **Standard รถncelikli**: API'lar iรงin aรงฤฑk standartlara dayalฤฑ (ve tamamen uyumlu); OpenAPI (eski adฤฑyla Swagger) ve JSON Schema. +* **Sezgisel**: Harika bir editรถr desteฤŸi. Her yerde Completion. Hata ayฤฑklamaya daha az zaman. +* **Kolay**: Kullanฤฑmฤฑ ve รถฤŸrenmesi kolay olacak ลŸekilde tasarlandฤฑ. Dokรผman okumaya daha az zaman. +* **Kฤฑsa**: Kod tekrarฤฑnฤฑ minimize eder. Her parametre tanฤฑmฤฑndan birden fazla รถzellik. Daha az hata. +* **SaฤŸlam**: Production'a hazฤฑr kod elde edersiniz. Otomatik etkileลŸimli dokรผmantasyon ile birlikte. +* **Standardlara dayalฤฑ**: API'lar iรงin aรงฤฑk standartlara dayalฤฑdฤฑr (ve tamamen uyumludur); OpenAPI (รถnceden Swagger olarak biliniyordu) ve JSON Schema. -* ilgili kanฤฑlar, dahili geliลŸtirme ekibinin geliลŸtirdikleri รผrรผnlere yaptฤฑklarฤฑ testlere dayanmaktadฤฑr. +* tahmin, production uygulamalar geliลŸtiren dahili bir geliลŸtirme ekibinin yaptฤฑฤŸฤฑ testlere dayanmaktadฤฑr. -## Sponsorlar +## Sponsorlar { #sponsors } -{% if sponsors %} +### Keystone Sponsor { #keystone-sponsor } + +{% for sponsor in sponsors.keystone -%} + +{% endfor -%} + +### Gold and Silver Sponsors { #gold-and-silver-sponsors } + {% for sponsor in sponsors.gold -%} {% endfor -%} {%- for sponsor in sponsors.silver -%} {% endfor %} -{% endif %} -DiฤŸer Sponsorlar +DiฤŸer sponsorlar -## GรถrรผลŸler +## GรถrรผลŸler { #opinions } -"_[...] Bugรผnlerde **FastAPI**'ฤฑ รงok fazla kullanฤฑyorum. [...] Aslฤฑnda bunu ekibimin **Microsoft'taki Machine Learning servislerinin** tamamฤฑnda kullanmayฤฑ planlฤฑyorum. Bunlardan bazฤฑlarฤฑ **Windows**'un ana รผrรผnlerine ve **Office** รผrรผnlerine entegre ediliyor._" +"_[...] Bugรผnlerde **FastAPI**'ฤฑ รงok fazla kullanฤฑyorum. [...] Aslฤฑnda bunu ekibimin **Microsoft'taki ML servislerinin** tamamฤฑnda kullanmayฤฑ planlฤฑyorum. Bunlardan bazฤฑlarฤฑ ana **Windows** รผrรผnรผne ve bazฤฑ **Office** รผrรผnlerine entegre ediliyor._"

Kabir Khan - Microsoft (ref)
--- -"_**FastAPI**'ฤฑ **tahminlerimiz**'i sorgulanabilir hale getirecek bir **REST** sunucu oluลŸturmak iรงin benimsedik/kullanmaya baลŸladฤฑk._" +"_**predictions** almak iรงin sorgulanabilecek bir **REST** server oluลŸturmak amacฤฑyla **FastAPI** kรผtรผphanesini benimsedik. [Ludwig iรงin]_"
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"_**Netflix**, **kriz yรถnetiminde** orkestrasyon yapabilmek iรงin geliลŸtirdiฤŸi yeni framework'รผ **Dispatch**'in, aรงฤฑk kaynak sรผrรผmรผnรผ paylaลŸmaktan gurur duyuyor. [**FastAPI** ile yapฤฑldฤฑ.]_" +"_**Netflix**, **kriz yรถnetimi** orkestrasyon framework'รผmรผz: **Dispatch**'in open-source sรผrรผmรผnรผ duyurmaktan memnuniyet duyar! [**FastAPI** ile geliลŸtirildi]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
@@ -91,70 +97,68 @@ Temel รถzellikleri ลŸunlardฤฑr: --- -"_Dรผrรผst olmak gerekirse, inลŸa ettiฤŸiniz ลŸey gerรงekten saฤŸlam ve profesyonel gรถrรผnรผyor. Birรงok aรงฤฑdan **Hug**'ฤฑn olmasฤฑnฤฑ istediฤŸim ลŸey tam da bu - bรถyle bir ลŸeyi inลŸa eden birini gรถrmek gerรงekten ilham verici._" +"_Dรผrรผst olmak gerekirse, inลŸa ettiฤŸiniz ลŸey gerรงekten saฤŸlam ve profesyonel gรถrรผnรผyor. Birรงok aรงฤฑdan, **Hug**'ฤฑn olmasฤฑnฤฑ istediฤŸim ลŸey tam da bu - bรถyle bir ลŸeyi inลŸa eden birini gรถrmek gerรงekten ilham verici._" -
Timothy Crosley - Hug'ฤฑn Yaratฤฑcฤฑsฤฑ (ref)
+
Timothy Crosley - Hug yaratฤฑcฤฑsฤฑ (ref)
--- -"_EฤŸer REST API geliลŸtirmek iรงin **modern bir framework** รถฤŸrenme arayฤฑลŸฤฑnda isen, **FastAPI**'a bir gรถz at [...] Hฤฑzlฤฑ, kullanฤฑmฤฑ ve รถฤŸrenmesi kolay. [...]_" +"_REST API'lar geliลŸtirmek iรงin **modern bir framework** รถฤŸrenmek istiyorsanฤฑz, **FastAPI**'a bir gรถz atฤฑn [...] Hฤฑzlฤฑ, kullanฤฑmฤฑ ve รถฤŸrenmesi kolay [...]_" -"_**API** servislerimizi **FastAPI**'a taลŸฤฑdฤฑk [...] Sizin de beฤŸeneceฤŸinizi dรผลŸรผnรผyoruz. [...]_" +"_**API**'larฤฑmฤฑz iรงin **FastAPI**'a geรงtik [...] Bence hoลŸunuza gidecek [...]_"
Ines Montani - Matthew Honnibal - Explosion AI kurucularฤฑ - spaCy yaratฤฑcฤฑlarฤฑ (ref) - (ref)
--- -"_Python ile kullanฤฑma hazฤฑr bir API oluลŸturmak isteyen herhangi biri iรงin, **FastAPI**'ฤฑ ลŸiddetle tavsiye ederim. **Harika tasarlanmฤฑลŸ**, **kullanฤฑmฤฑ kolay** ve **yรผksek รถlรงeklenebilir**, API odaklฤฑ geliลŸtirme stratejimizin **ana bileลŸeni** haline geldi ve Virtual TAC Engineer gibi birรงok otomasyon ve servisi yรถnetiyor._" +"_Production'da Python API geliลŸtirmek isteyen herkese **FastAPI**'ฤฑ ลŸiddetle tavsiye ederim. **Harika tasarlanmฤฑลŸ**, **kullanฤฑmฤฑ kolay** ve **yรผksek รถlรงeklenebilir**; API-first geliลŸtirme stratejimizin **kilit bir bileลŸeni** haline geldi ve Virtual TAC Engineer gibi birรงok otomasyon ve servise gรผรง veriyor._"
Deon Pillsbury - Cisco (ref)
--- -## Komut Satฤฑrฤฑ Uygulamalarฤฑnฤฑn FastAPI'ฤฑ: **Typer** +## FastAPI mini belgeseli { #fastapi-mini-documentary } - +2025'in sonunda yayฤฑnlanan bir FastAPI mini belgeseli var, online olarak izleyebilirsiniz: -EฤŸer API yerine, terminalde kullanฤฑlmak รผzere bir komut satฤฑrฤฑ uygulamasฤฑ geliลŸtiriyorsanฤฑz **Typer**'a gรถz atabilirsiniz. +FastAPI Mini Documentary -**Typer** kฤฑsaca FastAPI'ฤฑn kรผรงรผk kardeลŸi. Ve hedefi komut satฤฑrฤฑ uygulamalarฤฑnฤฑn **FastAPI'ฤฑ** olmak. โŒจ๏ธ ๐Ÿš€ +## CLI'larฤฑn FastAPI'ฤฑ: **Typer** { #typer-the-fastapi-of-clis } -## Gereksinimler + -FastAPI iki devin omuzlarฤฑ รผstรผnde duruyor: +Web API yerine terminalde kullanฤฑlacak bir CLI uygulamasฤฑ geliลŸtiriyorsanฤฑz **Typer**'a gรถz atฤฑn. -* Web tarafฤฑ iรงin Starlette. -* Data tarafฤฑ iรงin Pydantic. +**Typer**, FastAPI'ฤฑn kรผรงรผk kardeลŸi. Ve hedefi CLI'larฤฑn **FastAPI'ฤฑ** olmak. โŒจ๏ธ ๐Ÿš€ -## Kurulum +## Gereksinimler { #requirements } -
- -```console -$ pip install fastapi +FastAPI iki devin omuzlarฤฑ รผstรผnde duruyor: ----> 100% -``` +* Web kฤฑsฤฑmlarฤฑ iรงin Starlette. +* Data kฤฑsฤฑmlarฤฑ iรงin Pydantic. -
+## Kurulum { #installation } -Uygulamamฤฑzฤฑ kullanฤฑlabilir hale getirmek iรงin Uvicorn ya da Hypercorn gibi bir ASGI sunucusuna ihtiyacฤฑmฤฑz olacak. +Bir virtual environment oluลŸturup etkinleลŸtirelim ve ardฤฑndan FastAPI'ฤฑ yรผkleyelim:
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
-## ร–rnek +**Not**: Tรผm terminallerde รงalฤฑลŸtฤฑฤŸฤฑndan emin olmak iรงin `"fastapi[standard]"` ifadesini tฤฑrnak iรงinde yazdฤฑฤŸฤฑnฤฑzdan emin olun. -### Kodu OluลŸturalฤฑm +## ร–rnek { #example } -* `main.py` adฤฑnda bir dosya oluลŸturup iรงine ลŸu kodu yapฤฑลŸtฤฑralฤฑm: +### OluลŸturalฤฑm { #create-it } + +ลžu iรงerikle `main.py` adฤฑnda bir dosya oluลŸturalฤฑm: ```Python from typing import Union @@ -175,9 +179,9 @@ def read_item(item_id: int, q: Union[str, None] = None): ```
-Ya da async def... +Ya da async def kullanalฤฑm... -EฤŸer kodunuzda `async` / `await` varsa, `async def` kullanalฤฑm: +EฤŸer kodunuz `async` / `await` kullanฤฑyorsa, `async def` kullanฤฑn: ```Python hl_lines="9 14" from typing import Union @@ -199,22 +203,35 @@ async def read_item(item_id: int, q: Union[str, None] = None): **Not**: -EฤŸer bu konu hakkฤฑnda bilginiz yoksa `async` ve `await` dokรผmantasyonundaki _"Aceleniz mi var?"_ kฤฑsmฤฑnฤฑ kontrol edebilirsiniz. +EฤŸer bilmiyorsanฤฑz, dokรผmanlardaki `async` ve `await` hakkฤฑnda _"Aceleniz mi var?"_ bรถlรผmรผne bakฤฑn.
-### Kodu ร‡alฤฑลŸtฤฑralฤฑm +### ร‡alฤฑลŸtฤฑralฤฑm { #run-it } -Sunucuyu aลŸaฤŸฤฑdaki komutla รงalฤฑลŸtฤฑralฤฑm: +Sunucuyu ลŸu komutla รงalฤฑลŸtฤฑralฤฑm:
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ + โ”‚ โ”‚ + โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ + โ”‚ โ”‚ + โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ + โ”‚ โ”‚ + โ”‚ Running in development mode, for production use: โ”‚ + โ”‚ โ”‚ + โ”‚ fastapi run โ”‚ + โ”‚ โ”‚ + โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -222,54 +239,54 @@ INFO: Application startup complete.
-uvicorn main:app --reload komutuyla ilgili... +fastapi dev main.py komutu hakkฤฑnda... -`uvicorn main:app` komutunu ลŸu ลŸekilde aรงฤฑklayabiliriz: +`fastapi dev` komutu, `main.py` dosyanฤฑzฤฑ okur, iรงindeki **FastAPI** uygulamasฤฑnฤฑ algฤฑlar ve Uvicorn kullanarak bir server baลŸlatฤฑr. -* `main`: dosya olan `main.py` (yani Python "modรผlรผ"). -* `app`: ise `main.py` dosyasฤฑnฤฑn iรงerisinde `app = FastAPI()` satฤฑrฤฑnda oluลŸturduฤŸumuz `FastAPI` nesnesi. -* `--reload`: kod deฤŸiลŸikliklerinin ardฤฑndan sunucuyu otomatik olarak yeniden baลŸlatฤฑr. Bu parameteyi sadece geliลŸtirme aลŸamasฤฑnda kullanmalฤฑyฤฑz. +Varsayฤฑlan olarak `fastapi dev`, local geliลŸtirme iรงin auto-reload etkin ลŸekilde baลŸlar. + +Daha fazla bilgi iรงin FastAPI CLI dokรผmantasyonu'nu okuyabilirsiniz.
-### ลžimdi de Kontrol Edelim +### Kontrol Edelim { #check-it } -Tarayฤฑcฤฑmฤฑzda ลŸu baฤŸlantฤฑyฤฑ aรงalฤฑm http://127.0.0.1:8000/items/5?q=somequery. +Tarayฤฑcฤฑnฤฑzda ลŸu baฤŸlantฤฑyฤฑ aรงฤฑn: http://127.0.0.1:8000/items/5?q=somequery. -AลŸaฤŸฤฑdaki gibi bir JSON yanฤฑtฤฑyla karลŸฤฑlaลŸacaฤŸฤฑz: +ลžu JSON response'unu gรถreceksiniz: ```JSON {"item_id": 5, "q": "somequery"} ``` -Az รถnce oluลŸturduฤŸumuz API: +Artฤฑk ลŸunlarฤฑ yapan bir API oluลŸturdunuz: -* `/` ve `/items/{item_id}` _yollarฤฑna_ HTTP isteฤŸi alabilir. -* ฤฐki _yolda_ `GET` operasyonlarฤฑnฤฑ (HTTP _metodlarฤฑ_ olarak da bilinen) kabul ediyor. -* `/items/{item_id}` _yolu_ `item_id` adฤฑnda bir _yol parametresine_ sahip ve bu parametre `int` deฤŸer almak zorundadฤฑr. -* `/items/{item_id}` _yolu_ `q` adฤฑnda bir _yol parametresine_ sahip ve bu parametre opsiyonel olmakla birlikte, `str` deฤŸer almak zorundadฤฑr. +* `/` ve `/items/{item_id}` _path_'lerinde HTTP request'leri alฤฑr. +* Her iki _path_ de `GET` operasyonlarฤฑnฤฑ (HTTP _method_'larฤฑ olarak da bilinir) kabul eder. +* `/items/{item_id}` _path_'i, `int` olmasฤฑ gereken `item_id` adlฤฑ bir _path parameter_'a sahiptir. +* `/items/{item_id}` _path_'i, opsiyonel `str` bir _query parameter_ olan `q`'ya sahiptir. -### EtkileลŸimli API Dokรผmantasyonu +### EtkileลŸimli API dokรผmantasyonu { #interactive-api-docs } -ลžimdi http://127.0.0.1:8000/docs baฤŸlantฤฑsฤฑnฤฑ aรงalฤฑm. +ลžimdi http://127.0.0.1:8000/docs adresine gidin. -Swagger UI tarafฤฑndan saฤŸlanan otomatik etkileลŸimli bir API dokรผmantasyonu gรถreceฤŸiz: +Otomatik etkileลŸimli API dokรผmantasyonunu gรถreceksiniz (Swagger UI tarafฤฑndan saฤŸlanฤฑr): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### Alternatif API Dokรผmantasyonu +### Alternatif API dokรผmantasyonu { #alternative-api-docs } -ลžimdi http://127.0.0.1:8000/redoc baฤŸlantฤฑsฤฑnฤฑ aรงalฤฑm. +Ve ลŸimdi http://127.0.0.1:8000/redoc adresine gidin. -ReDoc tarafฤฑndan saฤŸlanan otomatik dokรผmantasyonu gรถreceฤŸiz: +Alternatif otomatik dokรผmantasyonu gรถreceksiniz (ReDoc tarafฤฑndan saฤŸlanฤฑr): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## ร–rneฤŸi Gรผncelleyelim +## ร–rneฤŸi Gรผncelleyelim { #example-upgrade } -ลžimdi `main.py` dosyasฤฑnฤฑ, `PUT` isteฤŸiyle birlikte bir gรถvde alacak ลŸekilde deฤŸiลŸtirelim. +ลžimdi `main.py` dosyasฤฑnฤฑ, `PUT` request'iyle gelen bir body alacak ลŸekilde deฤŸiลŸtirelim. -Gรถvdeyi Pydantic sayesinde standart python tiplerini kullanarak tanฤฑmlayalฤฑm. +Body'yi Pydantic sayesinde standart Python tiplerini kullanarak tanฤฑmlayalฤฑm. ```Python hl_lines="4 9-12 25-27" from typing import Union @@ -301,174 +318,248 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -Sunucu otomatik olarak yeniden baลŸlamฤฑลŸ olmalฤฑ (รงรผnkรผ yukarฤฑda `uvicorn` komutuyla birlikte `--reload` parametresini kullandฤฑk). +`fastapi dev` server'ฤฑ otomatik olarak yeniden yรผklemelidir. -### EtkileลŸimli API Dokรผmantasyonundaki DeฤŸiลŸimi Gรถrelim +### EtkileลŸimli API dokรผmantasyonu gรผncellemesi { #interactive-api-docs-upgrade } -ลžimdi http://127.0.0.1:8000/docs baฤŸlantฤฑsฤฑna tekrar gidelim. +ลžimdi http://127.0.0.1:8000/docs adresine gidin. -* EtkileลŸimli API dokรผmantasyonu, yeni gรถvdede dahil olmak รผzere otomatik olarak gรผncellenmiลŸ olacak: +* EtkileลŸimli API dokรผmantasyonu, yeni body dahil olacak ลŸekilde otomatik olarak gรผncellenecek: ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* "Try it out" butonuna tฤฑklayalฤฑm, bu iลŸlem API parametleri รผzerinde deฤŸiลŸiklik yapmamฤฑza ve doฤŸrudan API ile etkileลŸime geรงmemize imkan saฤŸlayacak: +* "Try it out" butonuna tฤฑklayฤฑn; parametreleri doldurmanฤฑza ve API ile doฤŸrudan etkileลŸime girmenize olanak saฤŸlar: ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -* ลžimdi "Execute" butonuna tฤฑklayalฤฑm, kullanฤฑcฤฑ arayรผzรผ API'ฤฑmฤฑz ile baฤŸlantฤฑ kurup parametreleri gรถnderecek ve sonucu ekranฤฑmฤฑza getirecek: +* Sonra "Execute" butonuna tฤฑklayฤฑn; kullanฤฑcฤฑ arayรผzรผ API'nฤฑz ile iletiลŸim kuracak, parametreleri gรถnderecek, sonuรงlarฤฑ alacak ve ekranda gรถsterecek: ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) -### Alternatif API Dokรผmantasyonundaki DeฤŸiลŸimi Gรถrelim +### Alternatif API dokรผmantasyonu gรผncellemesi { #alternative-api-docs-upgrade } -ลžimdi ise http://127.0.0.1:8000/redoc baฤŸlantฤฑsฤฑna tekrar gidelim. +Ve ลŸimdi http://127.0.0.1:8000/redoc adresine gidin. -* Alternatif dokรผmantasyonda yaptฤฑฤŸฤฑmฤฑz deฤŸiลŸiklikler ile birlikte yeni sorgu parametresi ve gรถvde bilgisi ile gรผncelemiลŸ olacak: +* Alternatif dokรผmantasyon da yeni query parameter ve body'yi yansฤฑtacak: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ร–zet +### ร–zet { #recap } -ร–zetlemek gerekirse, parametrelerin, gรถvdenin, vb. veri tiplerini fonksiyon parametreleri olarak **bir kere** tanฤฑmlฤฑyoruz. +ร–zetle, parametrelerin, body'nin vb. type'larฤฑnฤฑ fonksiyon parametreleri olarak **bir kere** tanฤฑmlarsฤฑnฤฑz. -Bu iลŸlemi standart modern Python tipleriyle yapฤฑyoruz. +Bunu standart modern Python tipleriyle yaparsฤฑnฤฑz. -Yeni bir sรถzdizimi yapฤฑsฤฑnฤฑ, bir kรผtรผphane รถzel metod veya sฤฑnฤฑflarฤฑ รถฤŸrenmeye gerek yoktur. +Yeni bir syntax, belirli bir kรผtรผphanenin method'larฤฑnฤฑ ya da class'larฤฑnฤฑ vb. รถฤŸrenmeniz gerekmez. -Hepsi sadece **Python** standartlarฤฑna dayalฤฑdฤฑr. +Sadece standart **Python**. -ร–rnek olarak, `int` tanฤฑmlamak iรงin: +ร–rneฤŸin bir `int` iรงin: ```Python item_id: int ``` -ya da daha kompleks herhangi bir python modelini tanฤฑmlayabiliriz, รถrneฤŸin `Item` modeli iรงin: +ya da daha karmaลŸฤฑk bir `Item` modeli iรงin: ```Python item: Item ``` -...ve sadece kฤฑsa bir parametre tipi belirterek elde ettiklerimiz: +...ve bu tek tanฤฑmla ลŸunlarฤฑ elde edersiniz: -* Editรถr desteฤŸiyle birlikte: - * Otomatik tamamlama. - * Tip kontrolรผ. -* Veri DoฤŸrulama: - * Veri geรงerli deฤŸilse, otomatik olarak aรงฤฑklayฤฑcฤฑ hatalar gรถsterir. - * ร‡ok derin JSON nesnelerinde bile doฤŸrulama yapar. -* Gelen verinin dรถnรผลŸรผmรผnรผ aลŸaฤŸฤฑdaki veri tiplerini kullanarak gerรงekleลŸtirir: +* ลžunlar dahil editรถr desteฤŸi: + * Completion. + * Type kontrolleri. +* Verinin doฤŸrulanmasฤฑ: + * Veri geรงersiz olduฤŸunda otomatik ve anlaลŸฤฑlฤฑr hatalar. + * ร‡ok derin iรง iรงe JSON nesneleri iรงin bile doฤŸrulama. +* Girdi verisinin DรถnรผลŸรผmรผ: network'ten gelen veriyi Python verisine ve type'larฤฑna รงevirir. ลžunlardan okur: * JSON. - * Yol parametreleri. - * Sorgu parametreleri. - * ร‡erezler. - * Headers. - * Formlar. - * Dosyalar. -* Giden verinin dรถnรผลŸรผmรผnรผ aลŸaฤŸฤฑdaki veri tiplerini kullanarak gerรงekleลŸtirir (JSON olarak): - * Python tiplerinin (`str`, `int`, `float`, `bool`, `list`, vb) dรถnรผลŸรผmรผ. - * `datetime` nesnesi. - * `UUID` nesnesi. + * Path parameter'lar. + * Query parameter'lar. + * Cookie'ler. + * Header'lar. + * Form'lar. + * File'lar. +* ร‡ฤฑktฤฑ verisinin DรถnรผลŸรผmรผ: Python verisini ve type'larฤฑnฤฑ network verisine รงevirir (JSON olarak): + * Python type'larฤฑnฤฑ dรถnรผลŸtรผrรผr (`str`, `int`, `float`, `bool`, `list`, vb.). + * `datetime` nesneleri. + * `UUID` nesneleri. * Veritabanฤฑ modelleri. - * ve รงok daha fazlasฤฑ... -* 2 alternatif kullanฤฑcฤฑ arayรผzรผ dahil olmak รผzere, otomatik etkileลŸimli API dokรผmantasyonu saฤŸlar: + * ...ve daha fazlasฤฑ. +* 2 alternatif kullanฤฑcฤฑ arayรผzรผ dahil otomatik etkileลŸimli API dokรผmantasyonu: * Swagger UI. * ReDoc. --- -Az รถnceki รถrneฤŸe geri dรถnelim, **FastAPI**'ฤฑn yapacaklarฤฑna bir bakฤฑลŸ atalฤฑm: - -* `item_id`'nin `GET` ve `PUT` istekleri iรงin, yolda olup olmadฤฑฤŸฤฑnฤฑn kontol edecek. -* `item_id`'nin `GET` ve `PUT` istekleri iรงin, tipinin `int` olduฤŸunu doฤŸrulayacak. - * EฤŸer deฤŸilse, sebebini belirten bir hata mesajฤฑ gรถsterecek. -* Opsiyonel bir `q` parametresinin `GET` isteฤŸi iรงinde (`http://127.0.0.1:8000/items/foo?q=somequery` gibi) olup olmadฤฑฤŸฤฑnฤฑ kontrol edecek - * `q` parametresini `= None` ile oluลŸturduฤŸumuz iรงin, opsiyonel bir parametre olacak. - * EฤŸer `None` olmasa zorunlu bir parametre olacaktฤฑ (`PUT` metodunun gรถvdesinde olduฤŸu gibi). -* `PUT` isteฤŸi iรงin `/items/{item_id}`'nin gรถvdesini, JSON olarak doฤŸrulayฤฑp okuyacak: - * `name` adฤฑnda zorunlu bir parametre olup olmadฤฑฤŸฤฑnฤฑ ve varsa tipinin `str` olup olmadฤฑฤŸฤฑnฤฑ kontol edecek. - * `price` adฤฑnda zorunlu bir parametre olup olmadฤฑฤŸฤฑnฤฑ ve varsa tipinin `float` olup olmadฤฑฤŸฤฑnฤฑ kontol edecek. - * `is_offer` adฤฑnda opsiyonel bir parametre olup olmadฤฑฤŸฤฑnฤฑ ve varsa tipinin `float` olup olmadฤฑฤŸฤฑnฤฑ kontol edecek. - * Bunlarฤฑn hepsi en derin JSON nesnelerinde bile รงalฤฑลŸacak. -* Verilerin JSON'a ve JSON'ฤฑn python nesnesine dรถnรผลŸรผmรผ otomatik olarak yapฤฑlacak. -* Her ลŸeyi OpenAPI ile uyumlu bir ลŸekilde otomatik olarak dokรผmanlayacak ve bunlarda aลŸaฤŸฤฑdaki gibi kullanฤฑlabilecek: +ร–nceki kod รถrneฤŸine dรถnersek, **FastAPI** ลŸunlarฤฑ yapacaktฤฑr: + +* `GET` ve `PUT` request'leri iรงin path'te `item_id` olduฤŸunu doฤŸrular. +* `GET` ve `PUT` request'leri iรงin `item_id`'nin type'ฤฑnฤฑn `int` olduฤŸunu doฤŸrular. + * DeฤŸilse, client faydalฤฑ ve anlaลŸฤฑlฤฑr bir hata gรถrรผr. +* `GET` request'leri iรงin `q` adlฤฑ opsiyonel bir query parameter olup olmadฤฑฤŸฤฑnฤฑ kontrol eder (`http://127.0.0.1:8000/items/foo?q=somequery` รถrneฤŸindeki gibi). + * `q` parametresi `= None` ile tanฤฑmlandฤฑฤŸฤฑ iรงin opsiyoneldir. + * `None` olmasaydฤฑ zorunlu olurdu (tฤฑpkฤฑ `PUT` รถrneฤŸindeki body gibi). +* `/items/{item_id}`'ye yapฤฑlan `PUT` request'leri iรงin body'yi JSON olarak okur: + * `str` olmasฤฑ gereken, zorunlu `name` alanฤฑ olduฤŸunu kontrol eder. + * `float` olmasฤฑ gereken, zorunlu `price` alanฤฑ olduฤŸunu kontrol eder. + * Varsa, `bool` olmasฤฑ gereken opsiyonel `is_offer` alanฤฑnฤฑ kontrol eder. + * Bunlarฤฑn hepsi รงok derin iรง iรงe JSON nesneleri iรงin de รงalฤฑลŸฤฑr. +* JSON'a ve JSON'dan dรถnรผลŸรผmรผ otomatik yapar. +* Her ลŸeyi OpenAPI ile dokรผmante eder; bu dokรผmantasyon ลŸunlar tarafฤฑndan kullanฤฑlabilir: * EtkileลŸimli dokรผmantasyon sistemleri. - * Bir รงok programlama dili iรงin otomatik istemci kodu รผretim sistemleri. -* ฤฐki ayrฤฑ etkileลŸimli dokรผmantasyon arayรผzรผnรผ doฤŸrudan saฤŸlayacak. + * Birรงok dil iรงin otomatik client kodu รผretim sistemleri. +* 2 etkileลŸimli dokรผmantasyon web arayรผzรผnรผ doฤŸrudan sunar. --- -Daha yeni baลŸladฤฑk ama รงalฤฑลŸma mantฤฑฤŸฤฑnฤฑ รงoktan anlamฤฑลŸ oldunuz. +Daha yolun baลŸฤฑndayฤฑz, ama bunun nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑ hakkฤฑnda fikri kaptฤฑnฤฑz. -ลžimdi aลŸaฤŸฤฑdaki satฤฑrฤฑ deฤŸiลŸtirmeyi deneyin: +ลžu satฤฑrฤฑ deฤŸiลŸtirmeyi deneyin: ```Python return {"item_name": item.name, "item_id": item_id} ``` -...bundan: +...ลŸundan: ```Python ... "item_name": item.name ... ``` -...buna: +...ลŸuna: ```Python ... "item_price": item.price ... ``` -...ve editรถrรผnรผn veri tiplerini bildiฤŸini ve otomatik tamamladฤฑฤŸฤฑnฤฑ gรถreceksiniz: +...ve editรถrรผnรผzรผn alanlarฤฑ otomatik tamamladฤฑฤŸฤฑnฤฑ ve type'larฤฑnฤฑ bildiฤŸini gรถrรผn: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -Daha fazal รถzellik iรงeren, daha eksiksiz bir รถrnek iรงin ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi sayfasฤฑnฤฑ ziyaret edebilirsin. +Daha fazla รถzellik iรงeren daha kapsamlฤฑ bir รถrnek iรงin ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi'ne bakฤฑn. -**Spoiler**: ร–ฤŸretici - Kullanฤฑcฤฑ rehberi ลŸunlarฤฑ iรงerir: +**Spoiler alert**: รถฤŸretici - kullanฤฑcฤฑ rehberi ลŸunlarฤฑ iรงerir: -* **Parameterlerin**, **headers**, **รงerezler**, **form alanlarฤฑ** ve **dosyalar** olarak tanฤฑmlanmasฤฑ. -* `maximum_length` ya da `regex` gibi **doฤŸrulama kฤฑsฤฑtlamalarฤฑnฤฑn** nasฤฑl yapฤฑlabileceฤŸi. -* ร‡ok gรผรงlรผ ve kullanฤฑmฤฑ kolay **BaฤŸฤฑmlฤฑlฤฑk Enjeksiyonu** sistemi oluลŸturmayฤฑ. -* Gรผvenlik ve kimlik doฤŸrulama, **JWT tokenleri** ile **OAuth2** desteฤŸi, ve **HTTP Basic** doฤŸrulamasฤฑ. -* ฤฐleri seviye fakat bir o kadarda basit olan **รงok derin JSON modelleri** (Pydantic sayesinde). -* **GraphQL** entegrasyonu: Strawberry ve diฤŸer kรผtรผphaneleri kullanarak. -* DiฤŸer ekstra รถzellikler (Starlette sayesinde): - * **WebSocketler** - * HTTPX ve `pytest` sayesinde aลŸฤฑrฤฑ kolay testler. +* **parameter**'larฤฑn farklฤฑ yerlerden: **header**'lar, **cookie**'ler, **form alanlarฤฑ** ve **file**'lar olarak tanฤฑmlanmasฤฑ. +* `maximum_length` ya da `regex` gibi **doฤŸrulama kฤฑsฤฑtlamalarฤฑnฤฑn** nasฤฑl ayarlanacaฤŸฤฑ. +* ร‡ok gรผรงlรผ ve kullanฤฑmฤฑ kolay bir **Dependency Injection** sistemi. +* **JWT tokens** ve **HTTP Basic** auth ile **OAuth2** desteฤŸi dahil gรผvenlik ve kimlik doฤŸrulama. +* **ร‡ok derin iรง iรงe JSON modelleri** tanฤฑmlamak iรงin daha ileri (ama aynฤฑ derecede kolay) teknikler (Pydantic sayesinde). +* Strawberry ve diฤŸer kรผtรผphaneler ile **GraphQL** entegrasyonu. +* Starlette sayesinde gelen birรงok ek รถzellik: + * **WebSockets** + * HTTPX ve `pytest` tabanlฤฑ aลŸฤฑrฤฑ kolay testler * **CORS** * **Cookie Sessions** * ...ve daha fazlasฤฑ. -## Performans +### Uygulamanฤฑzฤฑ deploy edin (opsiyonel) { #deploy-your-app-optional } + +ฤฐsterseniz FastAPI uygulamanฤฑzฤฑ FastAPI Cloud'a deploy edebilirsiniz; eฤŸer henรผz yapmadฤฑysanฤฑz gidip bekleme listesine katฤฑlฤฑn. ๐Ÿš€ + +Zaten bir **FastAPI Cloud** hesabฤฑnฤฑz varsa (bekleme listesinden sizi davet ettiysek ๐Ÿ˜‰), uygulamanฤฑzฤฑ tek bir komutla deploy edebilirsiniz. + +Deploy etmeden รถnce, giriลŸ yaptฤฑฤŸฤฑnฤฑzdan emin olun: + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +Sonra uygulamanฤฑzฤฑ deploy edin: -BaฤŸฤฑmsฤฑz TechEmpower kฤฑyaslamalarฤฑ gรถsteriyor ki, Uvicorn ile รงalฤฑลŸtฤฑrฤฑlan **FastAPI** uygulamalarฤฑ en hฤฑzlฤฑ Python framework'lerinden birisi, sadece Starlette ve Uvicorn'dan yavaลŸ, ki FastAPI bunlarฤฑn รผzerine kurulu bir kรผtรผphanedir. +
-Daha fazla bilgi iรงin, bu bรถlรผme bir gรถz at Kฤฑyaslamalar. +```console +$ fastapi deploy -## Opsiyonel Gereksinimler +Deploying to FastAPI Cloud... -Pydantic tarafฤฑnda kullanฤฑlan: +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Hepsi bu! Artฤฑk uygulamanฤฑza bu URL'den eriลŸebilirsiniz. โœจ + +#### FastAPI Cloud hakkฤฑnda { #about-fastapi-cloud } + +**FastAPI Cloud**, **FastAPI**'ฤฑn arkasฤฑndaki aynฤฑ yazar ve ekip tarafฤฑndan geliลŸtirilmiลŸtir. + +**Bir API'ฤฑ build etmek**, **deploy etmek** ve **eriลŸmek** sรผreรงlerini minimum eforla kolaylaลŸtฤฑrฤฑr. + +FastAPI ile uygulama geliลŸtirmenin saฤŸladฤฑฤŸฤฑ aynฤฑ **developer experience**'ฤฑ, onlarฤฑ cloud'a **deploy etmeye** de taลŸฤฑr. ๐ŸŽ‰ + +FastAPI Cloud, *FastAPI and friends* open source projelerinin ana sponsoru ve finansman saฤŸlayฤฑcฤฑsฤฑdฤฑr. โœจ + +#### DiฤŸer cloud saฤŸlayฤฑcฤฑlarฤฑna deploy { #deploy-to-other-cloud-providers } + +FastAPI open source'tur ve standartlara dayanฤฑr. FastAPI uygulamalarฤฑnฤฑ seรงtiฤŸiniz herhangi bir cloud saฤŸlayฤฑcฤฑsฤฑna deploy edebilirsiniz. + +FastAPI uygulamalarฤฑnฤฑ onlarla deploy etmek iรงin cloud saฤŸlayฤฑcฤฑnฤฑzฤฑn rehberlerini takip edin. ๐Ÿค“ + +## Performans { #performance } + +BaฤŸฤฑmsฤฑz TechEmpower kฤฑyaslamalarฤฑ, Uvicorn altฤฑnda รงalฤฑลŸan **FastAPI** uygulamalarฤฑnฤฑn mevcut en hฤฑzlฤฑ Python framework'lerinden biri olduฤŸunu gรถsteriyor; sadece Starlette ve Uvicorn'un kendisinin gerisinde (FastAPI tarafฤฑndan dahili olarak kullanฤฑlฤฑr). (*) + +Daha iyi anlamak iรงin Kฤฑyaslamalar bรถlรผmรผne bakฤฑn. + +## BaฤŸฤฑmlฤฑlฤฑklar { #dependencies } + +FastAPI, Pydantic ve Starlette'a baฤŸฤฑmlฤฑdฤฑr. + +### `standard` BaฤŸฤฑmlฤฑlฤฑklarฤฑ { #standard-dependencies } + +FastAPI'ฤฑ `pip install "fastapi[standard]"` ile yรผklediฤŸinizde, opsiyonel baฤŸฤฑmlฤฑlฤฑklarฤฑn `standard` grubuyla birlikte gelir: + +Pydantic tarafฤฑndan kullanฤฑlanlar: * email-validator - email doฤŸrulamasฤฑ iรงin. -* pydantic-settings - ayar yรถnetimi iรงin. -* pydantic-extra-types - Pydantic ile birlikte kullanฤฑlabilecek ek tipler iรงin. -Starlette tarafฤฑnda kullanฤฑlan: +Starlette tarafฤฑndan kullanฤฑlanlar: + +* httpx - `TestClient` kullanmak istiyorsanฤฑz gereklidir. +* jinja2 - varsayฤฑlan template yapฤฑlandฤฑrmasฤฑnฤฑ kullanmak istiyorsanฤฑz gereklidir. +* python-multipart - `request.form()` ile, form "parsing" desteฤŸi istiyorsanฤฑz gereklidir. + +FastAPI tarafฤฑndan kullanฤฑlanlar: -* httpx - EฤŸer `TestClient` yapฤฑsฤฑnฤฑ kullanacaksanฤฑz gereklidir. -* jinja2 - EฤŸer varsayฤฑlan template konfigรผrasyonunu kullanacaksanฤฑz gereklidir. -* python-multipart - EฤŸer `request.form()` ile form dรถnรผลŸรผmรผ desteฤŸini kullanacaksanฤฑz gereklidir. -* itsdangerous - `SessionMiddleware` desteฤŸi iรงin gerekli. -* pyyaml - `SchemaGenerator` desteฤŸi iรงin gerekli (Muhtemelen FastAPI kullanฤฑrken ihtiyacฤฑnฤฑz olmaz). +* uvicorn - uygulamanฤฑzฤฑ yรผkleyen ve servis eden server iรงin. Buna, yรผksek performanslฤฑ servis iรงin gereken bazฤฑ baฤŸฤฑmlฤฑlฤฑklarฤฑ (รถrn. `uvloop`) iรงeren `uvicorn[standard]` dahildir. +* `fastapi-cli[standard]` - `fastapi` komutunu saฤŸlamak iรงin. + * Buna, FastAPI uygulamanฤฑzฤฑ FastAPI Cloud'a deploy etmenizi saฤŸlayan `fastapi-cloud-cli` dahildir. -Hem FastAPI hem de Starlette tarafฤฑndan kullanฤฑlan: +### `standard` BaฤŸฤฑmlฤฑlฤฑklarฤฑ Olmadan { #without-standard-dependencies } + +`standard` opsiyonel baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ dahil etmek istemiyorsanฤฑz, `pip install "fastapi[standard]"` yerine `pip install fastapi` ile kurabilirsiniz. + +### `fastapi-cloud-cli` Olmadan { #without-fastapi-cloud-cli } + +FastAPI'ฤฑ standard baฤŸฤฑmlฤฑlฤฑklarla ama `fastapi-cloud-cli` olmadan kurmak istiyorsanฤฑz, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile yรผkleyebilirsiniz. + +### Ek Opsiyonel BaฤŸฤฑmlฤฑlฤฑklar { #additional-optional-dependencies } + +Yรผklemek isteyebileceฤŸiniz bazฤฑ ek baฤŸฤฑmlฤฑlฤฑklar da vardฤฑr. + +Ek opsiyonel Pydantic baฤŸฤฑmlฤฑlฤฑklarฤฑ: + +* pydantic-settings - ayar yรถnetimi iรงin. +* pydantic-extra-types - Pydantic ile kullanฤฑlacak ek type'lar iรงin. -* uvicorn - oluลŸturduฤŸumuz uygulamayฤฑ servis edecek web sunucusu gรถrevini รผstlenir. -* orjson - `ORJSONResponse` kullanacaksanฤฑz gereklidir. -* ujson - `UJSONResponse` kullanacaksanฤฑz gerekli. +Ek opsiyonel FastAPI baฤŸฤฑmlฤฑlฤฑklarฤฑ: -Bunlarฤฑn hepsini `pip install fastapi[all]` ile yรผkleyebilirsin. +* orjson - `ORJSONResponse` kullanmak istiyorsanฤฑz gereklidir. +* ujson - `UJSONResponse` kullanmak istiyorsanฤฑz gereklidir. -## Lisans +## Lisans { #license } -Bu proje, MIT lisansฤฑ ลŸartlarฤฑ altฤฑnda lisanslanmฤฑลŸtฤฑr. +Bu proje MIT lisansฤฑ ลŸartlarฤฑ altฤฑnda lisanslanmฤฑลŸtฤฑr. diff --git a/docs/tr/docs/learn/index.md b/docs/tr/docs/learn/index.md index 52e3aa54df..accf971aa7 100644 --- a/docs/tr/docs/learn/index.md +++ b/docs/tr/docs/learn/index.md @@ -1,5 +1,5 @@ -# ร–ฤŸren +# ร–ฤŸren { #learn } **FastAPI** รถฤŸrenmek iรงin giriลŸ bรถlรผmleri ve รถฤŸreticiler burada yer alฤฑyor. -Burayฤฑ, bir **kitap**, bir **kurs**, ve FastAPI รถฤŸrenmenin **resmi** ve รถnerilen yolu olarak dรผลŸรผnรผlebilirsiniz. ๐Ÿ˜Ž +Burayฤฑ, bir **kitap**, bir **kurs**, FastAPI รถฤŸrenmenin **resmi** ve รถnerilen yolu olarak dรผลŸรผnebilirsiniz. ๐Ÿ˜Ž diff --git a/docs/tr/docs/project-generation.md b/docs/tr/docs/project-generation.md index c9dc24acc4..bdc28f0c01 100644 --- a/docs/tr/docs/project-generation.md +++ b/docs/tr/docs/project-generation.md @@ -1,84 +1,28 @@ -# Proje oluลŸturma - ลžablonlar - -BaลŸlamak iรงin bir proje oluลŸturucu kullanabilirsiniz, รงรผnkรผ sizin iรงin รถnceden yapฤฑlmฤฑลŸ birรงok baลŸlangฤฑรง โ€‹โ€‹kurulumu, gรผvenlik, veritabanฤฑ ve temel API endpoinlerini iรงerir. - -Bir proje oluลŸturucu, her zaman kendi ihtiyaรงlarฤฑnฤฑza gรถre gรผncellemeniz ve uyarlamanฤฑz gereken esnek bir kuruluma sahip olacaktฤฑr, ancak bu, projeniz iรงin iyi bir baลŸlangฤฑรง โ€‹โ€‹noktasฤฑ olabilir. - -## Full Stack FastAPI PostgreSQL - -GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql - -### Full Stack FastAPI PostgreSQL - ร–zellikler - -* Full **Docker** entegrasyonu (Docker based). -* Docker Swarm Mode ile deployment. -* **Docker Compose** entegrasyonu ve lokal geliลŸtirme iรงin optimizasyon. -* Uvicorn ve Gunicorn ile **Production ready** Python web server'ฤฑ. -* Python **FastAPI** backend: - * **Hฤฑzlฤฑ**: **NodeJS** ve **Go** ile eลŸit, รงok yรผksek performans (Starlette ve Pydantic'e teลŸekkรผrler). - * **Sezgisel**: Editor desteฤŸฤฑ. Otomatik tamamlama. Daha az debugging. - * **Kolay**: Kolay รถฤŸrenip kolay kullanmak iรงin tasarlandฤฑ. Daha az dรถkรผman okuma daha รงok iลŸ. - * **Kฤฑsa**: Minimum kod tekrarฤฑ. Her parametre bildiriminde birden รงok รถzellik. - * **Gรผรงlรผ**: Production-ready. Otomatik interaktif dรถkรผmantasyon. - * **Standartlara dayalฤฑ**: API'ler iรงin aรงฤฑk standartlara dayanฤฑr (ve tamamen uyumludur): OpenAPI ve JSON ลžemasฤฑ. - * **Birรงok diger รถzelliฤŸi** dahili otomatik doฤŸrulama, serialization, interaktif dokรผmantasyon, OAuth2 JWT token ile authentication, vb. -* **Gรผvenli ลŸifreleme** . -* **JWT token** kimlik doฤŸrulama. -* **SQLAlchemy** models (Flask dan baฤŸฤฑmsฤฑzdฤฑr. Celery worker'larฤฑ ile kullanฤฑlabilir). -* Kullanฤฑcฤฑlar iรงin temel baลŸlangฤฑรง โ€‹โ€‹modeli (gerektiฤŸi gibi deฤŸiลŸtirin ve kaldฤฑrฤฑn). -* **Alembic** migration. -* **CORS** (Cross Origin Resource Sharing). -* **Celery** worker'larฤฑ ile backend iรงerisinden seรงilen iลŸleri รงalฤฑลŸtฤฑrabilirsiniz. -* **Pytest**'e dayalฤฑ, Docker ile entegre REST backend testleri ile veritabanฤฑndan baฤŸฤฑmsฤฑz olarak tam API etkileลŸimini test edebilirsiniz. Docker'da รงalฤฑลŸtฤฑฤŸฤฑ iรงin her seferinde sฤฑfฤฑrdan yeni bir veri deposu oluลŸturabilir (bรถylece ElasticSearch, MongoDB, CouchDB veya ne istersen kullanabilirsin ve sadece API'nin รงalฤฑลŸฤฑp รงalฤฑลŸmadฤฑฤŸฤฑnฤฑ test edebilirsin). -* Atom Hydrogen veya Visual Studio Code Jupyter gibi uzantฤฑlarla uzaktan veya Docker iรงi geliลŸtirme iรงin **Jupyter ร‡ekirdekleri** ile kolay Python entegrasyonu. -* **Vue** ile frontend: - * Vue CLI ile oluลŸturulmuลŸ. - * Dahili **JWT kimlik doฤŸrulama**. - * Dahili Login. - * Login sonrasฤฑ, Kontrol paneli. - * Kullanฤฑcฤฑ oluลŸturma ve dรผzenleme kontrol paneli - * Kendi kendine kullanฤฑcฤฑ sรผrรผmรผ. - * **Vuex**. - * **Vue-router**. - * **Vuetify** gรผzel material design kompanentleri iรงin. - * **TypeScript**. - * **Nginx** tabanlฤฑ Docker sunucusu (Vue-router iรงin yapฤฑlandฤฑrฤฑlmฤฑลŸ). - * Docker ile multi-stage yapฤฑ, bรถylece kodu derlemeniz, kaydetmeniz veya iลŸlemeniz gerekmez. - * Derleme zamanฤฑnda Frontend testi (devre dฤฑลŸฤฑ bฤฑrakฤฑlabilir). - * Mรผmkรผn olduฤŸu kadar modรผler yapฤฑlmฤฑลŸtฤฑr, bu nedenle kutudan รงฤฑktฤฑฤŸฤฑ gibi รงalฤฑลŸฤฑr, ancak Vue CLI ile yeniden oluลŸturabilir veya ihtiyaรง duyduฤŸunuz ลŸekilde oluลŸturabilir ve istediฤŸinizi yeniden kullanabilirsiniz. -* **PGAdmin** PostgreSQL database admin tool'u, PHPMyAdmin ve MySQL ile kolayca deฤŸiลŸtirilebilir. -* **Flower** ile Celery job'larฤฑnฤฑ monitรถrleme. -* **Traefik** ile backend ve frontend arasฤฑnda yรผk dengeleme, bรถylece her ikisini de aynฤฑ domain altฤฑnda, path ile ayrฤฑlmฤฑลŸ, ancak farklฤฑ kapsayฤฑcฤฑlar tarafฤฑndan sunulabilirsiniz. -* Let's Encrypt **HTTPS** sertifikalarฤฑnฤฑn otomatik oluลŸturulmasฤฑ dahil olmak รผzere Traefik entegrasyonu. -* GitLab **CI** (sรผrekli entegrasyon), backend ve frontend testi dahil. - -## Full Stack FastAPI Couchbase - -GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase - -โš ๏ธ **UYARI** โš ๏ธ - -Sฤฑfฤฑrdan bir projeye baลŸlฤฑyorsanฤฑz alternatiflerine bakฤฑn. - -ร–rneฤŸin, Full Stack FastAPI PostgreSQL daha iyi bir alternatif olabilir, aktif olarak geliลŸtiriliyor ve kullanฤฑlฤฑyor. Ve yeni รถzellik ve ilerlemelere sahip. - -ฤฐsterseniz Couchbase tabanlฤฑ generator'ฤฑ kullanmakta รถzgรผrsรผnรผz, hala iyi รงalฤฑลŸฤฑyor olmalฤฑ ve onunla oluลŸturulmuลŸ bir projeniz varsa bu da sorun deฤŸil (ve muhtemelen zaten ihtiyaรงlarฤฑnฤฑza gรถre gรผncellediniz). - -Bununla ilgili daha fazla bilgiyi repo belgelerinde okuyabilirsiniz. - -## Full Stack FastAPI MongoDB - -... mรผsaitliฤŸime ve diฤŸer faktรถrlere baฤŸlฤฑ olarak daha sonra gelebilir. ๐Ÿ˜… ๐ŸŽ‰ - -## Machine Learning modelleri, spaCy ve FastAPI - -GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi - -### Machine Learning modelleri, spaCy ve FastAPI - Features - -* **spaCy** NER model entegrasyonu. -* **Azure Cognitive Search** yerleลŸik istek biรงimi. -* Uvicorn ve Gunicorn ile **Production ready** Python web server'ฤฑ. -* Dahili **Azure DevOps** Kubernetes (AKS) CI/CD deployment. -* **Multilingual**, Proje kurulumu sฤฑrasฤฑnda spaCy'nin yerleลŸik dillerinden birini kolayca seรงin. -* **Esnetilebilir** diฤŸer frameworkler (Pytorch, Tensorflow) ile de รงalฤฑลŸฤฑr sadece spaCy deฤŸil. +# Full Stack FastAPI ลžablonu { #full-stack-fastapi-template } + +ลžablonlar genellikle belirli bir kurulumla gelir, ancak esnek ve รถzelleลŸtirilebilir olacak ลŸekilde tasarlanฤฑrlar. Bu sayede ลŸablonu projenizin gereksinimlerine gรถre deฤŸiลŸtirip uyarlayabilir, รงok iyi bir baลŸlangฤฑรง noktasฤฑ olarak kullanabilirsiniz. ๐Ÿ + +Bu ลŸablonu baลŸlangฤฑรง iรงin kullanabilirsiniz; รงรผnkรผ ilk kurulumun, gรผvenliฤŸin, veritabanฤฑnฤฑn ve bazฤฑ API endpoint'lerinin รถnemli bir kฤฑsmฤฑ sizin iรงin zaten hazฤฑrlanmฤฑลŸtฤฑr. + +GitHub Repository: Full Stack FastAPI Template + +## Full Stack FastAPI ลžablonu - Teknoloji YฤฑฤŸฤฑnฤฑ ve ร–zellikler { #full-stack-fastapi-template-technology-stack-and-features } + +- โšก Python backend API iรงin [**FastAPI**](https://fastapi.tiangolo.com/tr). + - ๐Ÿงฐ Python SQL veritabanฤฑ etkileลŸimleri (ORM) iรงin [SQLModel](https://sqlmodel.tiangolo.com). + - ๐Ÿ” FastAPI'nin kullandฤฑฤŸฤฑ; veri doฤŸrulama ve ayarlar yรถnetimi iรงin [Pydantic](https://docs.pydantic.dev). + - ๐Ÿ’พ SQL veritabanฤฑ olarak [PostgreSQL](https://www.postgresql.org). +- ๐Ÿš€ frontend iรงin [React](https://react.dev). + - ๐Ÿ’ƒ TypeScript, hooks, Vite ve modern bir frontend stack'inin diฤŸer parรงalarฤฑnฤฑ kullanฤฑr. + - ๐ŸŽจ frontend component'leri iรงin [Tailwind CSS](https://tailwindcss.com) ve [shadcn/ui](https://ui.shadcn.com). + - ๐Ÿค– Otomatik รผretilen bir frontend client. + - ๐Ÿงช End-to-End testleri iรงin [Playwright](https://playwright.dev). + - ๐Ÿฆ‡ Dark mode desteฤŸi. +- ๐Ÿ‹ GeliลŸtirme ve production iรงin [Docker Compose](https://www.docker.com). +- ๐Ÿ”’ Varsayฤฑlan olarak gรผvenli password hashing. +- ๐Ÿ”‘ JWT (JSON Web Token) authentication. +- ๐Ÿ“ซ E-posta tabanlฤฑ ลŸifre kurtarma. +- โœ… [Pytest](https://pytest.org) ile testler. +- ๐Ÿ“ž Reverse proxy / load balancer olarak [Traefik](https://traefik.io). +- ๐Ÿšข Docker Compose kullanarak deployment talimatlarฤฑ; otomatik HTTPS sertifikalarฤฑnฤฑ yรถnetmek iรงin bir frontend Traefik proxy'sini nasฤฑl kuracaฤŸฤฑnฤฑz dahil. +- ๐Ÿญ GitHub Actions tabanlฤฑ CI (continuous integration) ve CD (continuous deployment). diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md index b44aa3b9d5..01a3efe98c 100644 --- a/docs/tr/docs/python-types.md +++ b/docs/tr/docs/python-types.md @@ -1,76 +1,74 @@ -# Python Veri Tiplerine GiriลŸ +# Python Tiplerine GiriลŸ { #python-types-intro } -Python isteฤŸe baฤŸlฤฑ olarak "tip belirteรงlerini" destekler. +Python, isteฤŸe baฤŸlฤฑ "type hints" (diฤŸer adฤฑyla "type annotations") desteฤŸine sahiptir. - **"Tip belirteรงleri"** bir deฤŸiลŸkenin tipinin belirtilmesine olanak saฤŸlayan รถzel bir sรถzdizimidir. +Bu **"type hints"** veya annotations, bir deฤŸiลŸkenin type'ฤฑnฤฑ bildirmeye yarayan รถzel bir sรถzdizimidir. -DeฤŸiลŸkenlerin tiplerini belirterek editรถr ve araรงlardan daha fazla destek alabilirsiniz. +DeฤŸiลŸkenleriniz iรงin type bildirerek, editรถrler ve araรงlar size daha iyi destek saฤŸlayabilir. -Bu pythonda tip belirteรงleri iรงin **hฤฑzlฤฑ bir baลŸlangฤฑรง / bilgi tazeleme** rehberidir . Bu rehber **FastAPI** kullanmak iรงin gereken minimum konuyu kapsar ki bu da รงok az bir miktardฤฑr. +Bu, Python type hints hakkฤฑnda sadece **hฤฑzlฤฑ bir eฤŸitim / bilgi tazeleme** dokรผmanฤฑdฤฑr. **FastAPI** ile kullanmak iรงin gereken minimum bilgiyi kapsar... ki aslฤฑnda bu รงok azdฤฑr. -**FastAPI' nin** tamamฤฑ bu tรผr tip belirteรงleri ile donatฤฑlmฤฑลŸtฤฑr ve birรงok avantaj saฤŸlamaktadฤฑr. +**FastAPI** tamamen bu type hints รผzerine kuruludur; bunlar ona birรงok avantaj ve fayda saฤŸlar. -**FastAPI** kullanmayacak olsanฤฑz bile tรผr belirteรงleri hakkฤฑnda bilgi edinmenizde fayda var. +Ancak hiรง **FastAPI** kullanmasanฤฑz bile, bunlar hakkฤฑnda biraz รถฤŸrenmeniz size fayda saฤŸlayacaktฤฑr. /// note | Not -Python uzmanฤฑysanฤฑz ve tip belirteรงleri ilgili her ลŸeyi zaten biliyorsanฤฑz, sonraki bรถlรผme geรงin. +EฤŸer bir Python uzmanฤฑysanฤฑz ve type hints hakkฤฑnda her ลŸeyi zaten biliyorsanฤฑz, sonraki bรถlรผme geรงin. /// -## Motivasyon +## Motivasyon { #motivation } -Basit bir รถrnek ile baลŸlayalฤฑm: +Basit bir รถrnekle baลŸlayalฤฑm: -{* ../../docs_src/python_types/tutorial001.py *} +{* ../../docs_src/python_types/tutorial001_py39.py *} - -Programฤฑn รงฤฑktฤฑsฤฑ: +Bu programฤฑ รงalฤฑลŸtฤฑrฤฑnca ลŸu รงฤฑktฤฑyฤฑ alฤฑrsฤฑnฤฑz: ``` John Doe ``` -Fonksiyon sฤฑrayla ลŸunlarฤฑ yapar: +Fonksiyon ลŸunlarฤฑ yapar: * `first_name` ve `last_name` deฤŸerlerini alฤฑr. -* `title()` ile deฤŸiลŸkenlerin ilk karakterlerini bรผyรผtรผr. -* DeฤŸiลŸkenleri aralarฤฑnda bir boลŸlukla beraber BirleลŸtirir. - -{* ../../docs_src/python_types/tutorial001.py hl[2] *} +* `title()` ile her birinin ilk harfini bรผyรผk harfe รงevirir. +* Ortada bir boลŸluk olacak ลŸekilde Concatenates eder. +{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} -### Dรผzenle +### Dรผzenleyelim { #edit-it } Bu รงok basit bir program. -Ama ลŸimdi sฤฑfฤฑrdan yazdฤฑฤŸฤฑnฤฑzฤฑ hayal edin. +Ama ลŸimdi bunu sฤฑfฤฑrdan yazdฤฑฤŸฤฑnฤฑzฤฑ hayal edin. -Bir noktada fonksiyonun tanฤฑmฤฑna baลŸlayacaktฤฑnฤฑz, parametreleri hazฤฑr hale getirdiniz... +Bir noktada fonksiyon tanฤฑmฤฑnฤฑ yazmaya baลŸlamฤฑลŸ olacaktฤฑnฤฑz, parametreler hazฤฑr... -Ama sonra "ilk harfi bรผyรผk harfe dรถnรผลŸtรผren yรถntemi" รงaฤŸฤฑrmanฤฑz gerekir. +Ama sonra "ilk harfi bรผyรผk harfe รงeviren method"u รงaฤŸฤฑrmanฤฑz gerekiyor. - `upper` mฤฑydฤฑ ? Yoksa `uppercase`' mi? `first_uppercase`? `capitalize`? +`upper` mฤฑydฤฑ? `uppercase` miydi? `first_uppercase`? `capitalize`? -Ardฤฑndan, programcฤฑlarฤฑn en iyi arkadaลŸฤฑ olan otomatik tamamlama ile denediniz. +Sonra eski programcฤฑ dostuyla denersiniz: editรถr autocomplete. -'first_name', ardฤฑndan bir nokta ('.') yazฤฑp otomatik tamamlamayฤฑ tetiklemek iรงin 'Ctrl+Space' tuลŸlarฤฑna bastฤฑnฤฑz. +Fonksiyonun ilk parametresi olan `first_name`'i yazarsฤฑnฤฑz, sonra bir nokta (`.`) ve ardฤฑndan autocomplete'i tetiklemek iรงin `Ctrl+Space`'e basarsฤฑnฤฑz. -Ancak, ne yazฤฑk ki, yararlฤฑ hiรงbir ลŸey elde edemediniz: +Ama ne yazฤฑk ki, iลŸe yarar bir ลŸey gรถremezsiniz: -### Tipleri ekle +### Tipleri ekleyelim { #add-types } -ร–nceki sรผrรผmden sadece bir satฤฑrฤฑ deฤŸiลŸtirelim. +ร–nceki sรผrรผmden tek bir satฤฑrฤฑ deฤŸiลŸtirelim. -Tam olarak bu parรงayฤฑ, iลŸlevin parametrelerini deฤŸiลŸtireceฤŸiz: +Fonksiyonun parametreleri olan ลŸu parรงayฤฑ: ```Python first_name, last_name ``` -ve bu hale getireceฤŸiz: +ลŸuna รงevireceฤŸiz: ```Python first_name: str, last_name: str @@ -78,58 +76,55 @@ ve bu hale getireceฤŸiz: Bu kadar. -ฤฐลŸte bunlar "tip belirteรงleri": - -{* ../../docs_src/python_types/tutorial002.py hl[1] *} +Bunlar "type hints": +{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} -Bu, aลŸaฤŸฤฑdaki gibi varsayฤฑlan deฤŸerleri bildirmekle aynฤฑ ลŸey deฤŸildir: +Bu, aลŸaฤŸฤฑdaki gibi default deฤŸerler bildirmekle aynฤฑ ลŸey deฤŸildir: ```Python first_name="john", last_name="doe" ``` -Bu tamamen farklฤฑ birลŸey +Bu farklฤฑ bir ลŸey. -ฤฐki nokta รผst รผste (`:`) kullanฤฑyoruz , eลŸittir (`=`) deฤŸil. +EลŸittir (`=`) deฤŸil, iki nokta (`:`) kullanฤฑyoruz. -Normalde tip belirteรงleri eklemek, kod รผzerinde olacaklarฤฑ deฤŸiลŸtirmez. +Ve type hints eklemek, normalde onlarsฤฑz ne oluyorsa onu deฤŸiลŸtirmez. -ลžimdi programฤฑ sฤฑfฤฑrdan birdaha yazdฤฑฤŸฤฑnฤฑzฤฑ hayal edin. +Ama ลŸimdi, type hints ile o fonksiyonu oluลŸturmanฤฑn ortasฤฑnda olduฤŸunuzu tekrar hayal edin. -Aynฤฑ noktada, `Ctrl+Space` ile otomatik tamamlamayฤฑ tetiklediniz ve ลŸunu gรถrรผyorsunuz: +Aynฤฑ noktada, `Ctrl+Space` ile autocomplete'i tetiklemeye รงalฤฑลŸฤฑrsฤฑnฤฑz ve ลŸunu gรถrรผrsรผnรผz: -AradฤฑฤŸฤฑnฤฑzฤฑ bulana kadar seรงenekleri kaydฤฑrabilirsiniz: +Bununla birlikte, seรงenekleri gรถrerek kaydฤฑrabilirsiniz; ta ki "tanฤฑdฤฑk gelen" seรงeneฤŸi bulana kadar: -## Daha fazla motivasyon +## Daha fazla motivasyon { #more-motivation } -Bu fonksiyon, zaten tรผr belirteรงlerine sahip: +ลžu fonksiyona bakฤฑn, zaten type hints iรงeriyor: -{* ../../docs_src/python_types/tutorial003.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} - -Editรถr deฤŸiลŸkenlerin tiplerini bildiฤŸinden, yalnฤฑzca otomatik tamamlama deฤŸil, hata kontrolleri de saฤŸlar: +Editรถr deฤŸiลŸkenlerin tiplerini bildiฤŸi iรงin, sadece completion deฤŸil, aynฤฑ zamanda hata kontrolleri de alฤฑrsฤฑnฤฑz: -Artฤฑk `age` deฤŸiลŸkenini `str(age)` olarak kullanmanฤฑz gerektiฤŸini biliyorsunuz: - -{* ../../docs_src/python_types/tutorial004.py hl[2] *} +Artฤฑk bunu dรผzeltmeniz gerektiฤŸini, `age`'i `str(age)` ile string'e รงevirmeniz gerektiฤŸini biliyorsunuz: +{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} -## Tip bildirme +## Tipleri bildirmek { #declaring-types } -Az รถnce tip belirteรงlerinin en รงok kullanฤฑldฤฑฤŸฤฑ yeri gรถrdรผnรผz. +Type hints bildirmek iรงin ana yeri az รถnce gรถrdรผnรผz: fonksiyon parametreleri. - **FastAPI**ile รงalฤฑลŸฤฑrken tip belirteรงlerini en รงok kullanacaฤŸฤฑmฤฑz yer yine fonksiyonlardฤฑr. +Bu, **FastAPI** ile kullanฤฑrken de onlarฤฑ en รงok kullanacaฤŸฤฑnฤฑz yerdir. -### Basit tipler +### Basit tipler { #simple-types } -Yalnฤฑzca `str` deฤŸil, tรผm standart Python tiplerinin bildirebilirsiniz. +Sadece `str` deฤŸil, tรผm standart Python tiplerini bildirebilirsiniz. ร–rneฤŸin ลŸunlarฤฑ kullanabilirsiniz: @@ -138,176 +133,332 @@ Yalnฤฑzca `str` deฤŸil, tรผm standart Python tiplerinin bildirebilirsiniz. * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} + +### Tip parametreleri ile Generic tipler { #generic-types-with-type-parameters } +`dict`, `list`, `set` ve `tuple` gibi, baลŸka deฤŸerler iรงerebilen bazฤฑ veri yapฤฑlarฤฑ vardฤฑr. Ve iรง deฤŸerlerin kendi tipi de olabilir. -### Tip parametreleri ile Generic tipler +ฤฐรง tipleri olan bu tiplere "**generic**" tipler denir. Ve bunlarฤฑ, iรง tipleriyle birlikte bildirmek mรผmkรผndรผr. -"dict", "list", "set" ve "tuple" gibi diฤŸer deฤŸerleri iรงerebilen bazฤฑ veri yapฤฑlarฤฑ vardฤฑr. Ve dahili deฤŸerlerinin de tip belirtecleri olabilir. +Bu tipleri ve iรง tipleri bildirmek iรงin standart Python modรผlรผ `typing`'i kullanabilirsiniz. Bu modรผl, รถzellikle bu type hints desteฤŸi iรงin vardฤฑr. -Bu tipleri ve dahili tpileri bildirmek iรงin standart Python modรผlรผnรผ "typing" kullanabilirsiniz. +#### Python'un daha yeni sรผrรผmleri { #newer-versions-of-python } -Bu tรผr tip belirteรงlerini desteklemek iรงin รถzel olarak mevcuttur. +`typing` kullanan sรถzdizimi, Python 3.6'dan en yeni sรผrรผmlere kadar (Python 3.9, Python 3.10, vb. dahil) tรผm sรผrรผmlerle **uyumludur**. -#### `List` +Python geliลŸtikรงe, **daha yeni sรผrรผmler** bu type annotations iรงin daha iyi destekle gelir ve รงoฤŸu durumda type annotations bildirmek iรงin `typing` modรผlรผnรผ import edip kullanmanฤฑz bile gerekmez. -ร–rneฤŸin `str` deฤŸerlerden oluลŸan bir `list` tanฤฑmlayalฤฑm. +Projeniz iรงin daha yeni bir Python sรผrรผmรผ seรงebiliyorsanฤฑz, bu ek sadelikten yararlanabilirsiniz. -From `typing`, import `List` (bรผyรผk harf olan `L` ile): +Tรผm dokรผmanlarda her Python sรผrรผmรผyle uyumlu รถrnekler vardฤฑr (fark olduฤŸunda). -{* ../../docs_src/python_types/tutorial006.py hl[1] *} +ร–rneฤŸin "**Python 3.6+**", Python 3.6 veya รผstรผyle (3.7, 3.8, 3.9, 3.10, vb. dahil) uyumludur. "**Python 3.9+**" ise Python 3.9 veya รผstรผyle (3.10 vb. dahil) uyumludur. +EฤŸer **Python'un en gรผncel sรผrรผmlerini** kullanabiliyorsanฤฑz, en gรผncel sรผrรผme ait รถrnekleri kullanฤฑn; bunlar **en iyi ve en basit sรถzdizimine** sahip olur, รถrneฤŸin "**Python 3.10+**". -DeฤŸiลŸkenin tipini yine iki nokta รผstรผste (`:`) ile belirleyin. +#### List { #list } -tip olarak `List` kullanฤฑn. +ร–rneฤŸin, `str`'lerden oluลŸan bir `list` olan bir deฤŸiลŸken tanฤฑmlayalฤฑm. -Liste, bazฤฑ dahili tipleri iรงeren bir tรผr olduฤŸundan, bunlarฤฑ kรถลŸeli parantez iรงine alฤฑrsฤฑnฤฑz: +DeฤŸiลŸkeni, aynฤฑ iki nokta (`:`) sรถzdizimiyle bildirin. -{* ../../docs_src/python_types/tutorial006.py hl[4] *} +Type olarak `list` yazฤฑn. +`list`, bazฤฑ iรง tipleri barฤฑndฤฑran bir tip olduฤŸundan, bunlarฤฑ kรถลŸeli parantez iรงine yazarsฤฑnฤฑz: -/// tip | Ipucu +{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} -KรถลŸeli parantez iรงindeki bu dahili tiplere "tip parametreleri" denir. +/// info | Bilgi -Bu durumda `str`, `List`e iletilen tรผr parametresidir. +KรถลŸeli parantez iรงindeki bu iรง tiplere "type parameters" denir. + +Bu durumda `str`, `list`'e verilen type parameter'dฤฑr. /// -Bunun anlamฤฑ ลŸudur: "`items` deฤŸiลŸkeni bir `list`tir ve bu listedeki รถฤŸelerin her biri bir `str`dir". +Bu ลŸu demektir: "`items` deฤŸiลŸkeni bir `list` ve bu listedeki her bir รถฤŸe `str`". -Bunu yaparak, dรผzenleyicinizin listedeki รถฤŸeleri iลŸlerken bile destek saฤŸlamasฤฑnฤฑ saฤŸlayabilirsiniz: +Bunu yaparak, editรถrรผnรผz listeden รถฤŸeleri iลŸlerken bile destek saฤŸlayabilir: -Tip belirteรงleri olmadan, bunu baลŸarmak neredeyse imkansฤฑzdฤฑr. +Tipler olmadan, bunu baลŸarmak neredeyse imkansฤฑzdฤฑr. -`item` deฤŸiลŸkeninin `items` listesindeki รถฤŸelerden biri olduฤŸuna dikkat edin. +`item` deฤŸiลŸkeninin, `items` listesindeki elemanlardan biri olduฤŸuna dikkat edin. -Ve yine, editรถr bunun bir `str` โ€‹โ€‹olduฤŸunu biliyor ve bunun iรงin destek saฤŸlฤฑyor. +Ve yine de editรถr bunun bir `str` olduฤŸunu bilir ve buna gรถre destek saฤŸlar. -#### `Tuple` ve `Set` +#### Tuple ve Set { #tuple-and-set } -`Tuple` ve `set`lerin tiplerini bildirmek iรงin de aynฤฑsฤฑnฤฑ yapฤฑyoruz: +`tuple`'larฤฑ ve `set`'leri bildirmek iรงin de aynฤฑsฤฑnฤฑ yaparsฤฑnฤฑz: -{* ../../docs_src/python_types/tutorial007.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +Bu ลŸu anlama gelir: -Bu ลŸu anlama geliyor: +* `items_t` deฤŸiลŸkeni 3 รถฤŸeli bir `tuple`'dฤฑr: bir `int`, bir baลŸka `int` ve bir `str`. +* `items_s` deฤŸiลŸkeni bir `set`'tir ve her bir รถฤŸesi `bytes` tipindedir. -* `items_t` deฤŸiลŸkeni sฤฑrasฤฑyla `int`, `int`, ve `str` tiplerinden oluลŸan bir `tuple` tรผrรผndedir . -* `items_s` ise her รถฤŸesi `bytes` tรผrรผnde olan bir `set` รถrneฤŸidir. +#### Dict { #dict } -#### `Dict` +Bir `dict` tanฤฑmlamak iรงin, virgรผlle ayrฤฑlmฤฑลŸ 2 type parameter verirsiniz. -Bir `dict` tanฤฑmlamak iรงin virgรผlle ayrฤฑlmฤฑลŸ iki parametre verebilirsiniz. +ฤฐlk type parameter, `dict`'in key'leri iรงindir. -ฤฐlk tip parametresi `dict` deฤŸerinin `key` deฤŸeri iรงindir. +ฤฐkinci type parameter, `dict`'in value'larฤฑ iรงindir: -ฤฐkinci parametre ise `dict` deฤŸerinin `value` deฤŸeri iรงindir: +{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} -{* ../../docs_src/python_types/tutorial008.py hl[1,4] *} +Bu ลŸu anlama gelir: +* `prices` deฤŸiลŸkeni bir `dict`'tir: + * Bu `dict`'in key'leri `str` tipindedir (รถrneฤŸin her bir รถฤŸenin adฤฑ). + * Bu `dict`'in value'larฤฑ `float` tipindedir (รถrneฤŸin her bir รถฤŸenin fiyatฤฑ). -Bu ลŸu anlama gelir: +#### Union { #union } + +Bir deฤŸiลŸkenin **birkaรง tipten herhangi biri** olabileceฤŸini bildirebilirsiniz; รถrneฤŸin bir `int` veya bir `str`. + +Python 3.6 ve รผzeri sรผrรผmlerde (Python 3.10 dahil), `typing` iรงinden `Union` tipini kullanabilir ve kรถลŸeli parantez iรงine kabul edilecek olasฤฑ tipleri yazabilirsiniz. + +Python 3.10'da ayrฤฑca, olasฤฑ tipleri vertical bar (`|`) ile ayฤฑrabildiฤŸiniz **yeni bir sรถzdizimi** de vardฤฑr. + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008b_py39.py!} +``` + +//// -* `prices` deฤŸiลŸkeni `dict` tipindedir: - * `dict` deฤŸiลŸkeninin `key` deฤŸeri `str` tipindedir (herbir item'ฤฑn "name" deฤŸeri). - * `dict` deฤŸiลŸkeninin `value` deฤŸeri `float` tipindedir (lherbir item'ฤฑn "price" deฤŸeri). +Her iki durumda da bu, `item`'ฤฑn `int` veya `str` olabileceฤŸi anlamฤฑna gelir. -#### `Optional` +#### Muhtemelen `None` { #possibly-none } -`Optional` bir deฤŸiลŸkenin `str`gibi bir tipi olabileceฤŸini ama isteฤŸe baฤŸlฤฑ olarak tipinin `None` olabileceฤŸini belirtir: +Bir deฤŸerin `str` gibi bir tipi olabileceฤŸini ama aynฤฑ zamanda `None` da olabileceฤŸini bildirebilirsiniz. + +Python 3.6 ve รผzeri sรผrรผmlerde (Python 3.10 dahil), `typing` modรผlรผnden `Optional` import edip kullanarak bunu bildirebilirsiniz. + +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009_py39.py!} +``` + +Sadece `str` yerine `Optional[str]` kullanmak, aslฤฑnda deฤŸer `None` olabilecekken her zaman `str` olduฤŸunu varsaydฤฑฤŸฤฑnฤฑz hatalarฤฑ editรถrรผn yakalamanฤฑza yardฤฑmcฤฑ olmasฤฑnฤฑ saฤŸlar. + +`Optional[Something]`, aslฤฑnda `Union[Something, None]` iรงin bir kฤฑsayoldur; eลŸdeฤŸerdirler. + +Bu aynฤฑ zamanda Python 3.10'da `Something | None` kullanabileceฤŸiniz anlamฤฑna gelir: + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009_py39.py!} +``` + +//// + +//// tab | Python 3.9+ alternatif ```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009.py!} +{!> ../../docs_src/python_types/tutorial009b_py39.py!} +``` + +//// + +#### `Union` veya `Optional` kullanmak { #using-union-or-optional } + +Python sรผrรผmรผnรผz 3.10'un altฤฑndaysa, benim oldukรงa **รถznel** bakฤฑลŸ aรงฤฑma gรถre kรผรงรผk bir ipucu: + +* ๐Ÿšจ `Optional[SomeType]` kullanmaktan kaรงฤฑnฤฑn +* Bunun yerine โœจ **`Union[SomeType, None]` kullanฤฑn** โœจ. + +ฤฐkisi eลŸdeฤŸerdir ve altta aynฤฑ ลŸeydir; ama ben `Optional` yerine `Union` รถnermeyi tercih ederim. ร‡รผnkรผ "**optional**" kelimesi deฤŸerin optional olduฤŸunu ima ediyor gibi durur; ama gerรงekte anlamฤฑ "deฤŸer `None` olabilir"dir. DeฤŸer optional olmasa ve hรขlรข required olsa bile. + +Bence `Union[SomeType, None]` ne anlama geldiฤŸini daha aรงฤฑk ลŸekilde ifade ediyor. + +Bu, tamamen kelimeler ve isimlendirmelerle ilgili. Ancak bu kelimeler, sizin ve ekip arkadaลŸlarฤฑnฤฑzฤฑn kod hakkฤฑnda nasฤฑl dรผลŸรผndรผฤŸรผnรผ etkileyebilir. + +ร–rnek olarak ลŸu fonksiyonu ele alalฤฑm: + +{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} + +`name` parametresi `Optional[str]` olarak tanฤฑmlanmฤฑลŸ, ama **optional deฤŸil**; parametre olmadan fonksiyonu รงaฤŸฤฑramazsฤฑnฤฑz: + +```Python +say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ +``` + +`name` parametresi **hรขlรข required**'dฤฑr (*optional* deฤŸildir) รงรผnkรผ bir default deฤŸeri yoktur. Yine de `name`, deฤŸer olarak `None` kabul eder: + +```Python +say_hi(name=None) # This works, None is valid ๐ŸŽ‰ ``` -`str` yerine `Optional[str]` kullanmak editorรผn bu deฤŸerin her zaman `str` tipinde deฤŸil bazen `None` tipinde de olabileceฤŸini belirtir ve hatalarฤฑ tespit etmemizde yardฤฑmcฤฑ olur. +ฤฐyi haber ลŸu ki, Python 3.10'a geรงtiฤŸinizde bununla uฤŸraลŸmanฤฑz gerekmeyecek; รงรผnkรผ tiplerin union'larฤฑnฤฑ tanฤฑmlamak iรงin doฤŸrudan `|` kullanabileceksiniz: + +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} + +Ve bรถylece `Optional` ve `Union` gibi isimlerle de uฤŸraลŸmanฤฑz gerekmeyecek. ๐Ÿ˜Ž + +#### Generic tipler { #generic-types } + +KรถลŸeli parantez iรงinde type parameter alan bu tiplere **Generic types** veya **Generics** denir, รถrneฤŸin: + +//// tab | Python 3.10+ -#### Generic tipler +Aynฤฑ builtin tipleri generics olarak kullanabilirsiniz (kรถลŸeli parantez ve iรงindeki tiplerle): -KรถลŸeli parantez iรงinde tip parametreleri alan bu tรผrler, รถrneฤŸin: +* `list` +* `tuple` +* `set` +* `dict` -* `List` -* `Tuple` -* `Set` -* `Dict` +Ve รถnceki Python sรผrรผmlerinde olduฤŸu gibi `typing` modรผlรผnden: + +* `Union` * `Optional` * ...and others. -**Generic types** yada **Generics** olarak adlandฤฑrฤฑlฤฑr. +Python 3.10'da, `Union` ve `Optional` generics'lerini kullanmaya alternatif olarak, tip union'larฤฑnฤฑ bildirmek iรงin vertical bar (`|`) kullanabilirsiniz; bu รงok daha iyi ve daha basittir. + +//// + +//// tab | Python 3.9+ + +Aynฤฑ builtin tipleri generics olarak kullanabilirsiniz (kรถลŸeli parantez ve iรงindeki tiplerle): + +* `list` +* `tuple` +* `set` +* `dict` -### Tip olarak Sฤฑnฤฑflar +Ve `typing` modรผlรผnden gelen generics: -Bir deฤŸiลŸkenin tipini bir sฤฑnฤฑf ile bildirebilirsiniz. +* `Union` +* `Optional` +* ...and others. + +//// -Diyelim ki `name` deฤŸerine sahip `Person` sฤฑnฤฑfฤฑnฤฑz var: +### Tip olarak sฤฑnฤฑflar { #classes-as-types } -{* ../../docs_src/python_types/tutorial010.py hl[1:3] *} +Bir sฤฑnฤฑfฤฑ da bir deฤŸiลŸkenin tipi olarak bildirebilirsiniz. +ร–rneฤŸin, adฤฑ olan bir `Person` sฤฑnฤฑfฤฑnฤฑz olsun: -Sonra bir deฤŸiลŸkeni 'Person' tipinde tanฤฑmlayabilirsiniz: +{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} -{* ../../docs_src/python_types/tutorial010.py hl[6] *} +Sonra bir deฤŸiลŸkeni `Person` tipinde olacak ลŸekilde bildirebilirsiniz: +{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} -Ve yine bรผtรผn editรถr desteฤŸini alฤฑrsฤฑnฤฑz: +Ve sonra, yine tรผm editรถr desteฤŸini alฤฑrsฤฑnฤฑz: -## Pydantic modelleri +Bunun "`one_person`, `Person` sฤฑnฤฑfฤฑnฤฑn bir **instance**'ฤฑdฤฑr" anlamฤฑna geldiฤŸine dikkat edin. -Pydantic veri doฤŸrulamasฤฑ yapmak iรงin bir Python kรผtรผphanesidir. +"`one_person`, `Person` adlฤฑ **class**'tฤฑr" anlamฤฑna gelmez. -Verilerin "biรงimini" niteliklere sahip sฤฑnฤฑflar olarak dรผzenlersiniz. +## Pydantic modelleri { #pydantic-models } -Ve her niteliฤŸin bir tรผrรผ vardฤฑr. +Pydantic, data validation yapmak iรงin bir Python kรผtรผphanesidir. -Sฤฑnฤฑfฤฑn bazฤฑ deฤŸerlerle bir รถrneฤŸini oluลŸturursunuz ve deฤŸerleri doฤŸrular, bunlarฤฑ uygun tรผre dรถnรผลŸtรผrรผr ve size tรผm verileri iรงeren bir nesne verir. +Verinin "shape"'ini attribute'lara sahip sฤฑnฤฑflar olarak tanฤฑmlarsฤฑnฤฑz. -Ve ortaya รงฤฑkan nesne รผzerindeki bรผtรผn editรถr desteฤŸini alฤฑrsฤฑnฤฑz. +Ve her attribute'un bir tipi vardฤฑr. -Resmi Pydantic dokรผmanlarฤฑndan alฤฑnmฤฑลŸtฤฑr: +Ardฤฑndan o sฤฑnฤฑfฤฑn bir instance'ฤฑnฤฑ bazฤฑ deฤŸerlerle oluลŸturursunuz; bu deฤŸerleri doฤŸrular, uygun tipe dรถnรผลŸtรผrรผr (gerekliyse) ve size tรผm veriyi iรงeren bir nesne verir. -{* ../../docs_src/python_types/tutorial011.py *} +Ve bu ortaya รงฤฑkan nesne ile tรผm editรถr desteฤŸini alฤฑrsฤฑnฤฑz. +Resmรฎ Pydantic dokรผmanlarฤฑndan bir รถrnek: -/// info +{* ../../docs_src/python_types/tutorial011_py310.py *} -Daha fazla ลŸey รถฤŸrenmek iรงin Pydantic'i takip edin. +/// info | Bilgi + +Daha fazlasฤฑnฤฑ รถฤŸrenmek iรงin Pydantic'in dokรผmanlarฤฑna bakฤฑn. /// -**FastAPI** tamamen Pydantic'e dayanmaktadฤฑr. +**FastAPI** tamamen Pydantic รผzerine kuruludur. + +Bunlarฤฑn pratikte nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank} iรงinde รงok daha fazla gรถreceksiniz. + +/// tip | ฤฐpucu + +Pydantic, default value olmadan `Optional` veya `Union[Something, None]` kullandฤฑฤŸฤฑnฤฑzda รถzel bir davranฤฑลŸa sahiptir; bununla ilgili daha fazla bilgiyi Pydantic dokรผmanlarฤฑnda Required Optional fields bรถlรผmรผnde okuyabilirsiniz. + +/// + +## Metadata Annotations ile Type Hints { #type-hints-with-metadata-annotations } + +Python'da ayrฤฑca, `Annotated` kullanarak bu type hints iรงine **ek metadata** koymayฤฑ saฤŸlayan bir รถzellik de vardฤฑr. -Daha fazlasini gรถrmek iรงin [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}. +Python 3.9'dan itibaren `Annotated`, standart kรผtรผphanenin bir parรงasฤฑdฤฑr; bu yรผzden `typing` iรงinden import edebilirsiniz. + +{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} + +Python'un kendisi bu `Annotated` ile bir ลŸey yapmaz. Editรถrler ve diฤŸer araรงlar iรงin tip hรขlรข `str`'dir. + +Ama **FastAPI**'ye uygulamanฤฑzฤฑn nasฤฑl davranmasฤฑnฤฑ istediฤŸinize dair ek metadata saฤŸlamak iรงin `Annotated` iรงindeki bu alanฤฑ kullanabilirsiniz. + +Hatฤฑrlanmasฤฑ gereken รถnemli nokta: `Annotated`'a verdiฤŸiniz **ilk *type parameter***, **gerรงek tip**tir. Geri kalanฤฑ ise diฤŸer araรงlar iรงin metadatadฤฑr. + +ลžimdilik, sadece `Annotated`'ฤฑn var olduฤŸunu ve bunun standart Python olduฤŸunu bilmeniz yeterli. ๐Ÿ˜Ž + +ฤฐleride bunun ne kadar **gรผรงlรผ** olabildiฤŸini gรถreceksiniz. + +/// tip | ฤฐpucu + +Bunun **standart Python** olmasฤฑ, editรถrรผnรผzde mรผmkรผn olan **en iyi developer experience**'ฤฑ almaya devam edeceฤŸiniz anlamฤฑna gelir; kodu analiz etmek ve refactor etmek iรงin kullandฤฑฤŸฤฑnฤฑz araรงlarla da, vb. โœจ + +Ayrฤฑca kodunuzun pek รงok baลŸka Python aracฤฑ ve kรผtรผphanesiyle รงok uyumlu olacaฤŸฤฑ anlamฤฑna gelir. ๐Ÿš€ + +/// -## **FastAPI** tip belirteรงleri +## **FastAPI**'de type hints { #type-hints-in-fastapi } -**FastAPI** birkaรง ลŸey yapmak iรงin bu tรผr tip belirteรงlerinden faydalanฤฑr. +**FastAPI**, birkaรง ลŸey yapmak iรงin bu type hints'ten faydalanฤฑr. -**FastAPI** ile parametre tiplerini bildirirsiniz ve ลŸunlarฤฑ elde edersiniz: +**FastAPI** ile type hints kullanarak parametreleri bildirirsiniz ve ลŸunlarฤฑ elde edersiniz: -* **Editor desteฤŸi**. -* **Tip kontrolรผ**. +* **Editรถr desteฤŸi**. +* **Tip kontrolleri**. -...ve **FastAPI** aynฤฑ belirteรงleri ลŸunlar iรงin de kullanฤฑyor: +...ve **FastAPI** aynฤฑ bildirimleri ลŸunlar iรงin de kullanฤฑr: -* **Gereksinimleri tanฤฑmlama**: request path parameters, query parameters, headers, bodies, dependencies, ve benzeri gereksinimlerden -* **Verileri รงevirme**: Gรถnderilen veri tipinden istenilen veri tipine รงevirme. -* **Verileri doฤŸrulama**: Her gรถnderilen verinin: - * doฤŸrulanmasฤฑ ve geรงersiz olduฤŸunda **otomatik hata** oluลŸturma. -* OpenAPI kullanarak apinizi **Belgeleyin** : - * bu daha sonra otomatik etkileลŸimli dokรผmantasyon kullanฤฑcฤฑ arayรผzรผ tarafฤฑndan kullanฤฑlฤฑr. +* **Gereksinimleri tanฤฑmlamak**: request path parameters, query parameters, headers, bodies, dependencies, vb. +* **Veriyi dรถnรผลŸtรผrmek**: request'ten gerekli tipe. +* **Veriyi doฤŸrulamak**: her request'ten gelen veriyi: + * Veri geรงersiz olduฤŸunda client'a dรถnen **otomatik hatalar** รผretmek. +* OpenAPI kullanarak API'yi **dokรผmante etmek**: + * bu, daha sonra otomatik etkileลŸimli dokรผmantasyon kullanฤฑcฤฑ arayรผzleri tarafฤฑndan kullanฤฑlฤฑr. -Bรผtรผn bunlar kulaฤŸa soyut gelebilir. Merak etme. Tรผm bunlarฤฑ รงalฤฑลŸฤฑrken gรถreceksiniz. [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}. +Bunlarฤฑn hepsi kulaฤŸa soyut gelebilir. Merak etmeyin. Tรผm bunlarฤฑ [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank} iรงinde รงalฤฑลŸฤฑrken gรถreceksiniz. -ร–nemli olan, standart Python tรผrlerini tek bir yerde kullanarak (daha fazla sฤฑnฤฑf, dekoratรถr vb. eklemek yerine), **FastAPI**'nin bizim iรงin iลŸi yapmasฤฑnฤฑ saฤŸlamak. +ร–nemli olan, standart Python tiplerini tek bir yerde kullanarak (daha fazla sฤฑnฤฑf, decorator vb. eklemek yerine), **FastAPI**'nin sizin iรงin iลŸin bรผyรผk kฤฑsmฤฑnฤฑ yapmasฤฑdฤฑr. -/// info +/// info | Bilgi -Tรผm รถฤŸreticiyi zaten okuduysanฤฑz ve tรผrler hakkฤฑnda daha fazla bilgi iรงin geri dรถndรผyseniz, iyi bir kaynak: the "cheat sheet" from `mypy`. +Tรผm tutorial'ฤฑ zaten bitirdiyseniz ve tipler hakkฤฑnda daha fazlasฤฑnฤฑ gรถrmek iรงin geri dรถndรผyseniz, iyi bir kaynak: `mypy`'nin "cheat sheet"i. /// diff --git a/docs/tr/docs/resources/index.md b/docs/tr/docs/resources/index.md index fc71a9ca1b..884052f79c 100644 --- a/docs/tr/docs/resources/index.md +++ b/docs/tr/docs/resources/index.md @@ -1,3 +1,3 @@ -# Kaynaklar +# Kaynaklar { #resources } -Ek kaynaklar, dฤฑลŸ baฤŸlantฤฑlar, makaleler ve daha fazlasฤฑ. โœˆ๏ธ +Ek kaynaklar, dฤฑลŸ baฤŸlantฤฑlar ve daha fazlasฤฑ. โœˆ๏ธ diff --git a/docs/tr/docs/tutorial/cookie-params.md b/docs/tr/docs/tutorial/cookie-params.md index f07508c2fd..18eedab7f0 100644 --- a/docs/tr/docs/tutorial/cookie-params.md +++ b/docs/tr/docs/tutorial/cookie-params.md @@ -1,35 +1,45 @@ -# ร‡erez (Cookie) Parametreleri +# ร‡erez (Cookie) Parametreleri { #cookie-parameters } -`Query` (Sorgu) ve `Path` (Yol) parametrelerini tanฤฑmladฤฑฤŸฤฑnฤฑz ลŸekilde รงerez parametreleri tanฤฑmlayabilirsiniz. +`Query` ve `Path` parametrelerini tanฤฑmladฤฑฤŸฤฑnฤฑz ลŸekilde Cookie parametreleri tanฤฑmlayabilirsiniz. -## Import `Cookie` +## `Cookie`'yi Import Edin { #import-cookie } -ร–ncelikle, `Cookie`'yi projenize dahil edin: +ร–ncelikle, `Cookie`'yi import edin: {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} -## `Cookie` Parametrelerini Tanฤฑmlayฤฑn +## `Cookie` Parametrelerini Tanฤฑmlayฤฑn { #declare-cookie-parameters } -ร‡erez parametrelerini `Path` veya `Query` tanฤฑmlamasฤฑ yapar gibi tanฤฑmlayฤฑn. +Ardฤฑndan, `Path` ve `Query` ile aynฤฑ yapฤฑyฤฑ kullanarak Cookie parametrelerini tanฤฑmlayฤฑn. -ฤฐlk deฤŸer varsayฤฑlan deฤŸerdir; tรผm ekstra doฤŸrulama veya belirteรง parametrelerini kullanabilirsiniz: +Varsayฤฑlan deฤŸeri ve tรผm ekstra doฤŸrulama veya annotation parametrelerini tanฤฑmlayabilirsiniz: {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} /// note | Teknik Detaylar -`Cookie` sฤฑnฤฑfฤฑ `Path` ve `Query` sฤฑnฤฑflarฤฑnฤฑn kardeลŸidir. DiฤŸerleri gibi `Param` sฤฑnฤฑfฤฑnฤฑ miras alan bir sฤฑnฤฑftฤฑr. +`Cookie`, `Path` ve `Query`'nin "kardeลŸ" sฤฑnฤฑfฤฑdฤฑr. O da aynฤฑ ortak `Param` sฤฑnฤฑfฤฑndan miras alฤฑr. -Ancak `fastapi`'dan projenize dahil ettiฤŸiniz `Query`, `Path`, `Cookie` ve diฤŸerleri aslฤฑnda รถzel sฤฑnฤฑflar dรถndรผren birer fonksiyondur. +Ancak `fastapi`'dan `Query`, `Path`, `Cookie` ve diฤŸerlerini import ettiฤŸinizde, bunlar aslฤฑnda รถzel sฤฑnฤฑflar dรถndรผren fonksiyonlardฤฑr, bunu unutmayฤฑn. /// /// info | Bilgi -ร‡erez tanฤฑmlamak iรงin `Cookie` sฤฑnฤฑfฤฑnฤฑ kullanmanฤฑz gerekmektedir, aksi taktirde parametreler sorgu parametreleri olarak yorumlanฤฑr. +ร‡erezleri tanฤฑmlamak iรงin `Cookie` kullanmanฤฑz gerekir, aksi halde parametreler query parametreleri olarak yorumlanฤฑr. /// -## ร–zet +/// info | Bilgi + +**Tarayฤฑcฤฑlar รงerezleri** รถzel ลŸekillerde ve arka planda iลŸlediฤŸi iรงin, **JavaScript**'in onlara dokunmasฤฑna kolayca izin **vermezler**. + +`/docs` adresindeki **API docs UI**'a giderseniz, *path operation*'larฤฑnฤฑz iรงin รงerezlerin **dokรผmantasyonunu** gรถrebilirsiniz. + +Ancak **veriyi doldurup** "Execute" dรผฤŸmesine tฤฑklasanฤฑz bile, docs UI **JavaScript** ile รงalฤฑลŸtฤฑฤŸฤฑ iรงin รงerezler gรถnderilmez ve herhangi bir deฤŸer yazmamฤฑลŸsฤฑnฤฑz gibi bir **hata** mesajฤฑ gรถrรผrsรผnรผz. + +/// + +## ร–zet { #recap } -ร‡erez tanฤฑmlamalarฤฑnฤฑ `Cookie` sฤฑnฤฑfฤฑnฤฑ kullanarak `Query` ve `Path` tanฤฑmlar gibi tanฤฑmlayฤฑn. +`Query` ve `Path` ile aynฤฑ ortak deseni kullanarak, รงerezleri `Cookie` ile tanฤฑmlayฤฑn. diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md index 9a8ef762dc..332f5c5590 100644 --- a/docs/tr/docs/tutorial/first-steps.md +++ b/docs/tr/docs/tutorial/first-steps.md @@ -1,102 +1,118 @@ -# ฤฐlk Adฤฑmlar +# ฤฐlk Adฤฑmlar { #first-steps } En sade FastAPI dosyasฤฑ ลŸu ลŸekilde gรถrรผnรผr: -{* ../../docs_src/first_steps/tutorial001.py *} +{* ../../docs_src/first_steps/tutorial001_py39.py *} -Yukarฤฑdaki iรงeriฤŸi bir `main.py` dosyasฤฑna kopyalayalฤฑm. +Yukarฤฑdakini `main.py` adlฤฑ bir dosyaya kopyalayฤฑn. -Uygulamayฤฑ รงalฤฑลŸtฤฑralฤฑm: +Canlฤฑ sunucuyu รงalฤฑลŸtฤฑrฤฑn:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. -``` + FastAPI Starting development server ๐Ÿš€ -
+ Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -/// note | Not + module ๐Ÿ main.py -`uvicorn main:app` komutunu ลŸu ลŸekilde aรงฤฑklayabiliriz: + code Importing the FastAPI app object from the module with + the following code: -* `main`: dosya olan `main.py` (yani Python "modรผlรผ"). -* `app`: ise `main.py` dosyasฤฑnฤฑn iรงerisinde `app = FastAPI()` satฤฑrฤฑnda oluลŸturduฤŸumuz `FastAPI` nesnesi. -* `--reload`: kod deฤŸiลŸikliklerinin ardฤฑndan sunucuyu otomatik olarak yeniden baลŸlatฤฑr. Bu parameteyi sadece geliลŸtirme aลŸamasฤฑnda kullanmalฤฑyฤฑz. + from main import app -/// + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run -ร‡ฤฑktฤฑ olarak ลŸรถyle bir satฤฑr ile karลŸฤฑlaลŸacaksฤฑnฤฑz: + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + + + +ร‡ฤฑktฤฑda, ลŸuna benzer bir satฤฑr gรถreceksiniz: ```hl_lines="4" INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -Bu satฤฑr, yerel makinenizde uygulamanฤฑzฤฑn รงalฤฑลŸtฤฑฤŸฤฑ baฤŸlantฤฑyฤฑ gรถsterir. +Bu satฤฑr, uygulamanฤฑzฤฑn yerel makinenizde hangi URL'de sunulduฤŸunu gรถsterir. -### Kontrol Edelim +### Kontrol Edelim { #check-it } -Tarayฤฑcฤฑnฤฑzฤฑ aรงฤฑp http://127.0.0.1:8000 baฤŸlantฤฑsฤฑna gidin. +Tarayฤฑcฤฑnฤฑzฤฑ aรงฤฑp http://127.0.0.1:8000 adresine gidin. -ลžu ลŸekilde bir JSON yanฤฑtฤฑ ile karลŸฤฑlaลŸacaฤŸฤฑz: +ลžu ลŸekilde bir JSON response gรถreceksiniz: ```JSON {"message": "Hello World"} ``` -### EtkileลŸimli API Dokรผmantasyonu +### EtkileลŸimli API Dokรผmantasyonu { #interactive-api-docs } -ลžimdi http://127.0.0.1:8000/docs baฤŸlantฤฑsฤฑnฤฑ aรงalฤฑm. +ลžimdi http://127.0.0.1:8000/docs adresine gidin. -Swagger UI tarafฤฑndan saฤŸlanan otomatik etkileลŸimli bir API dokรผmantasyonu gรถreceฤŸiz: +Otomatik etkileลŸimli API dokรผmantasyonunu ( Swagger UI tarafฤฑndan saฤŸlanan) gรถreceksiniz: ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### Alternatif API Dokรผmantasyonu +### Alternatif API Dokรผmantasyonu { #alternative-api-docs } -ลžimdi http://127.0.0.1:8000/redoc baฤŸlantฤฑsฤฑnฤฑ aรงalฤฑm. +Ve ลŸimdi http://127.0.0.1:8000/redoc adresine gidin. -ReDoc tarafฤฑndan saฤŸlanan otomatik dokรผmantasyonu gรถreceฤŸiz: +Alternatif otomatik dokรผmantasyonu ( ReDoc tarafฤฑndan saฤŸlanan) gรถreceksiniz: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } -**FastAPI**, **OpenAPI** standardฤฑnฤฑ kullanarak tรผm API'ฤฑnฤฑzฤฑn tamamฤฑnฤฑ tanฤฑmlayan bir "ลŸema" oluลŸturur. +**FastAPI**, API'larฤฑ tanฤฑmlamak iรงin **OpenAPI** standardฤฑnฤฑ kullanarak tรผm API'nฤฑzฤฑn tamamฤฑnฤฑ iรงeren bir "ลŸema" รผretir. -#### "ลžema" +#### "ลžema" { #schema } -"ลžema", bir ลŸeyin tanฤฑmฤฑ veya aรงฤฑklamasฤฑdฤฑr. GeliลŸtirilen koddan ziyade soyut bir aรงฤฑklamadฤฑr. +"ลžema", bir ลŸeyin tanฤฑmฤฑ veya aรงฤฑklamasฤฑdฤฑr. Onu uygulayan kod deฤŸil, sadece soyut bir aรงฤฑklamadฤฑr. -#### API "ลžemasฤฑ" +#### API "ลŸemasฤฑ" { #api-schema } -Bu durumda, OpenAPI, API ลŸemasฤฑnฤฑ nasฤฑl tanฤฑmlayacaฤŸฤฑnฤฑzฤฑ belirten bir ลŸartnamedir. +Bu durumda, OpenAPI, API'nฤฑzฤฑn ลŸemasฤฑnฤฑ nasฤฑl tanฤฑmlayacaฤŸฤฑnฤฑzฤฑ belirleyen bir ลŸartnamedir. -Bu ลŸema tanฤฑmฤฑ, API yollarฤฑnฤฑzla birlikte yollarฤฑnฤฑzฤฑn aldฤฑฤŸฤฑ olasฤฑ parametreler gibi tanฤฑmlamalarฤฑ iรงerir. +Bu ลŸema tanฤฑmฤฑ, API path'leriniz, alabilecekleri olasฤฑ parametreler vb. ลŸeyleri iรงerir. -#### Veri "ลžemasฤฑ" +#### Veri "ลŸemasฤฑ" { #data-schema } "ลžema" terimi, JSON iรงeriฤŸi gibi bazฤฑ verilerin ลŸeklini de ifade edebilir. -Bu durumda, JSON รถzellikleri ve sahip olduklarฤฑ veri tรผrleri gibi anlamlarฤฑna gelir. +Bu durumda, JSON attribute'larฤฑ ve sahip olduklarฤฑ veri tรผrleri vb. anlamฤฑna gelir. -#### OpenAPI ve JSON ลžema +#### OpenAPI ve JSON Schema { #openapi-and-json-schema } -OpenAPI, API'niz iรงin bir API ลŸemasฤฑ tanฤฑmlar. Ve bu ลŸema, JSON veri ลŸemalarฤฑ standardฤฑ olan **JSON ลžema** kullanฤฑlarak API'niz tarafฤฑndan gรถnderilen ve alฤฑnan verilerin tanฤฑmlarฤฑnฤฑ (veya "ลŸemalarฤฑnฤฑ") iรงerir. +OpenAPI, API'nฤฑz iรงin bir API ลŸemasฤฑ tanฤฑmlar. Ve bu ลŸema, JSON veri ลŸemalarฤฑ standardฤฑ olan **JSON Schema** kullanฤฑlarak API'nฤฑz tarafฤฑndan gรถnderilen ve alฤฑnan verilerin tanฤฑmlarฤฑnฤฑ (veya "ลŸemalarฤฑnฤฑ") iรงerir. -#### `openapi.json` Dosyasฤฑna Gรถz At +#### `openapi.json` Dosyasฤฑna Gรถz At { #check-the-openapi-json } -Ham OpenAPI ลŸemasฤฑnฤฑn nasฤฑl gรถrรผndรผฤŸรผnรผ merak ediyorsanฤฑz, FastAPI otomatik olarak tรผm API'ฤฑnฤฑzฤฑn tanฤฑmlamalarฤฑnฤฑ iรงeren bir JSON (ลŸemasฤฑ) oluลŸturur. +Ham OpenAPI ลŸemasฤฑnฤฑn nasฤฑl gรถrรผndรผฤŸรผnรผ merak ediyorsanฤฑz, FastAPI otomatik olarak tรผm API'nฤฑzฤฑn aรงฤฑklamalarฤฑnฤฑ iรงeren bir JSON (ลŸema) รผretir. -Bu ลŸemayฤฑ direkt olarak http://127.0.0.1:8000/openapi.json baฤŸlantฤฑsฤฑndan gรถrรผntรผleyebilirsiniz. +Bunu doฤŸrudan ลŸuradan gรถrebilirsiniz: http://127.0.0.1:8000/openapi.json. -AลŸaฤŸฤฑdaki gibi baลŸlayan bir JSON ile karลŸฤฑlaลŸacaksฤฑnฤฑz: +ลžuna benzer bir ลŸekilde baลŸlayan bir JSON gรถsterecektir: ```JSON { @@ -119,79 +135,87 @@ AลŸaฤŸฤฑdaki gibi baลŸlayan bir JSON ile karลŸฤฑlaลŸacaksฤฑnฤฑz: ... ``` -#### OpenAPI Ne ฤฐลŸe Yarar? - -OpenAPI ลŸemasฤฑ, FastAPI projesinde bulunan iki etkileลŸimli dokรผmantasyon sistemine gรผรง veren ลŸeydir. +#### OpenAPI Ne ฤฐลŸe Yarar? { #what-is-openapi-for } -OpenAPI'ya dayalฤฑ dรผzinelerce alternatif etkileลŸimli dokรผmantasyon aracฤฑ mevcuttur. **FastAPI** ile oluลŸturulmuลŸ uygulamanฤฑza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz. +OpenAPI ลŸemasฤฑ, dahil edilen iki etkileลŸimli dokรผmantasyon sistemine gรผรง veren ลŸeydir. -Ayrฤฑca, API'ฤฑnฤฑzla iletiลŸim kuracak รถnyรผz, mobil veya IoT uygulamalarฤฑ gibi istemciler iรงin otomatik olarak kod oluลŸturabilirsiniz. +Ve OpenAPI tabanlฤฑ dรผzinelerce alternatif vardฤฑr. **FastAPI** ile oluลŸturulmuลŸ uygulamanฤฑza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz. -## Adฤฑm Adฤฑm ร–zetleyelim +Ayrฤฑca, API'nฤฑzla iletiลŸim kuran istemciler iรงin otomatik olarak kod รผretmekte de kullanabilirsiniz. ร–rneฤŸin frontend, mobil veya IoT uygulamalarฤฑ. -### Adฤฑm 1: `FastAPI`yฤฑ Projemize Dahil Edelim +### Uygulamanฤฑzฤฑ Yayฤฑnlayฤฑn (opsiyonel) { #deploy-your-app-optional } -{* ../../docs_src/first_steps/tutorial001.py hl[1] *} +ฤฐsterseniz FastAPI uygulamanฤฑzฤฑ FastAPI Cloud'a deploy edebilirsiniz; henรผz katฤฑlmadฤฑysanฤฑz gidip bekleme listesine yazฤฑlฤฑn. ๐Ÿš€ -`FastAPI`, API'niz iรงin tรผm iลŸlevselliฤŸi saฤŸlayan bir Python sฤฑnฤฑfฤฑdฤฑr. +Zaten bir **FastAPI Cloud** hesabฤฑnฤฑz varsa (bekleme listesinden sizi davet ettiysek ๐Ÿ˜‰), uygulamanฤฑzฤฑ tek komutla deploy edebilirsiniz. -/// note | Teknik Detaylar - -`FastAPI` doฤŸrudan `Starlette`'i miras alan bir sฤฑnฤฑftฤฑr. - -Starlette'in tรผm iลŸlevselliฤŸini `FastAPI` ile de kullanabilirsiniz. - -/// +Deploy etmeden รถnce giriลŸ yaptฤฑฤŸฤฑnฤฑzdan emin olun: -### Adฤฑm 2: Bir `FastAPI` "ร–rneฤŸi" OluลŸturalฤฑm +
-{* ../../docs_src/first_steps/tutorial001.py hl[3] *} +```console +$ fastapi login -Burada `app` deฤŸiลŸkeni `FastAPI` sฤฑnฤฑfฤฑnฤฑn bir รถrneฤŸi olacaktฤฑr. +You are logged in to FastAPI Cloud ๐Ÿš€ +``` -Bu, tรผm API'yฤฑ oluลŸturmak iรงin ana etkileลŸim noktasฤฑ olacaktฤฑr. +
-Bu `app` deฤŸiลŸkeni, `uvicorn` komutunda atฤฑfta bulunulan deฤŸiลŸkenin ta kendisidir. +Ardฤฑndan uygulamanฤฑzฤฑ deploy edin:
```console -$ uvicorn main:app --reload +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev ```
-Uygulamanฤฑzฤฑ aลŸaฤŸฤฑdaki gibi oluลŸturursanฤฑz: +Bu kadar! Artฤฑk uygulamanฤฑza o URL รผzerinden eriลŸebilirsiniz. โœจ -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} +## Adฤฑm Adฤฑm ร–zetleyelim { #recap-step-by-step } -Ve bunu `main.py` dosyasฤฑna yerleลŸtirirseniz eฤŸer `uvicorn` komutunu ลŸu ลŸekilde รงalฤฑลŸtฤฑrabilirsiniz: +### Adฤฑm 1: `FastAPI` import edin { #step-1-import-fastapi } -
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} -```console -$ uvicorn main:my_awesome_api --reload +`FastAPI`, API'nฤฑz iรงin tรผm iลŸlevselliฤŸi saฤŸlayan bir Python class'ฤฑdฤฑr. -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` +/// note | Teknik Detaylar -
+`FastAPI`, doฤŸrudan `Starlette`'ten miras alan bir class'tฤฑr. + +Starlette'in tรผm iลŸlevselliฤŸini `FastAPI` ile de kullanabilirsiniz. + +/// + +### Adฤฑm 2: bir `FastAPI` "instance"ฤฑ oluลŸturun { #step-2-create-a-fastapi-instance } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} + +Burada `app` deฤŸiลŸkeni `FastAPI` class'ฤฑnฤฑn bir "instance"ฤฑ olacaktฤฑr. -### Adฤฑm 3: Bir *Yol Operasyonu* OluลŸturalฤฑm +Bu, tรผm API'nฤฑzฤฑ oluลŸturmak iรงin ana etkileลŸim noktasฤฑ olacaktฤฑr. -#### Yol +### Adฤฑm 3: bir *path operation* oluลŸturun { #step-3-create-a-path-operation } -Burada "yol" baฤŸlantฤฑda bulunan ilk `/` ile baลŸlayan ve sonrasฤฑnda gelen kฤฑsmฤฑ ifade eder. +#### Path { #path } -Yani, ลŸu ลŸekilde bir baฤŸlantฤฑda: +Buradaki "Path", URL'in ilk `/` iลŸaretinden baลŸlayarak son kฤฑsmฤฑnฤฑ ifade eder. + +Yani, ลŸu ลŸekilde bir URL'de: ``` https://example.com/items/foo ``` -... yol ลŸรถyle olur: +...path ลŸรถyle olur: ``` /items/foo @@ -199,77 +223,77 @@ https://example.com/items/foo /// info | Bilgi -"Yol" genellikle "endpoint" veya "route" olarak adlandฤฑrฤฑlฤฑr. +Bir "path" genellikle "endpoint" veya "route" olarak da adlandฤฑrฤฑlฤฑr. /// -Bir API oluลŸtururken, "yol", "kaynaklar" ile "endiลŸeleri" ayฤฑrmanฤฑn ana yรถntemidir. +Bir API oluลŸtururken, "path", "concerns" ve "resources" ayrฤฑmฤฑnฤฑ yapmanฤฑn ana yoludur. -#### Operasyonlar +#### Operation { #operation } -Burada "operasyon" HTTP "metodlarฤฑndan" birini ifade eder. +Burada "Operation", HTTP "method"larฤฑndan birini ifade eder. -Bunlardan biri: +ลžunlardan biri: * `POST` * `GET` * `PUT` * `DELETE` -...veya daha az kullanฤฑlan diฤŸerleri: +...ve daha egzotik olanlar: * `OPTIONS` * `HEAD` * `PATCH` * `TRACE` -HTTP protokolรผnde, bu "metodlardan" birini (veya daha fazlasฤฑnฤฑ) kullanarak her bir yol ile iletiลŸim kurabilirsiniz. +HTTP protokolรผnde, her bir path ile bu "method"lardan biri (veya birden fazlasฤฑ) ile iletiลŸim kurabilirsiniz. --- -API oluลŸtururkan, belirli bir amaca hizmet eden belirli HTTP metodlarฤฑnฤฑ kullanฤฑrsฤฑnฤฑz. +API oluลŸtururken, normalde belirli bir aksiyon iรงin bu spesifik HTTP method'larฤฑnฤฑ kullanฤฑrsฤฑnฤฑz. -Normalde kullanฤฑlan: +Normalde ลŸunlarฤฑ kullanฤฑrsฤฑnฤฑz: -* `POST`: veri oluลŸturmak. -* `GET`: veri okumak. -* `PUT`: veriyi gรผncellemek. -* `DELETE`: veriyi silmek. +* `POST`: veri oluลŸturmak iรงin. +* `GET`: veri okumak iรงin. +* `PUT`: veriyi gรผncellemek iรงin. +* `DELETE`: veriyi silmek iรงin. -Bu nedenle, OpenAPI'da HTTP metodlarฤฑndan her birine "operasyon" denir. +Bu nedenle, OpenAPI'da HTTP method'larฤฑnฤฑn her birine "operation" denir. -Biz de onlarฤฑ "**operasyonlar**" olarak adlandฤฑracaฤŸฤฑz. +Biz de bunlara "**operation**" diyeceฤŸiz. -#### Bir *Yol Operasyonu Dekoratรถrรผ* Tanฤฑmlayalฤฑm +#### Bir *path operation decorator* tanฤฑmlayฤฑn { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} -`@app.get("/")` dekoratรถrรผ, **FastAPI**'a hemen altฤฑndaki fonksiyonun aลŸaฤŸฤฑdaki durumlardan sorumlu olduฤŸunu sรถyler: +`@app.get("/")`, **FastAPI**'a hemen altฤฑndaki fonksiyonun ลŸuraya giden request'leri ele almakla sorumlu olduฤŸunu sรถyler: -* get operasyonu ile -* `/` yoluna gelen istekler +* path `/` +* get operation kullanarak /// info | `@decorator` Bilgisi -Python'da `@something` sรถzdizimi "dekoratรถr" olarak adlandฤฑrฤฑlฤฑr. +Python'daki `@something` sรถz dizimi "decorator" olarak adlandฤฑrฤฑlฤฑr. -Dekoratรถrler, dekoratif bir ลŸapka gibi (sanฤฑrฤฑm terim buradan geliyor) fonksiyonlarฤฑn รผzerlerine yerleลŸtirilirler. +Onu bir fonksiyonun รผstรผne koyarsฤฑnฤฑz. Gรผzel, dekoratif bir ลŸapka gibi (sanฤฑrฤฑm terim de buradan geliyor). -Bir "dekoratรถr" hemen altฤฑnda bulunan fonksiyonu alฤฑr ve o fonksiyon ile bazฤฑ iลŸlemler gerรงekleลŸtirir. +Bir "decorator", altฤฑndaki fonksiyonu alฤฑr ve onunla bir ลŸey yapar. -Bizim durumumuzda, kullandฤฑฤŸฤฑmฤฑz dekoratรถr, **FastAPI**'a altฤฑndaki fonksiyonun `/` yoluna gelen `get` metodlu isteklerden sorumlu olduฤŸunu sรถyler. +Bizim durumumuzda bu decorator, **FastAPI**'a altฤฑndaki fonksiyonun **path** `/` ile **operation** `get`'e karลŸฤฑlฤฑk geldiฤŸini sรถyler. -Bu bir **yol operasyonu dekoratรถrรผdรผr**. +Bu, "**path operation decorator**"dฤฑr. /// -Ayrฤฑca diฤŸer operasyonlarฤฑ da kullanabilirsiniz: +DiฤŸer operation'larฤฑ da kullanabilirsiniz: * `@app.post()` * `@app.put()` * `@app.delete()` -Daha az kullanฤฑlanlarฤฑ da kullanabilirsiniz: +Ve daha egzotik olanlarฤฑ: * `@app.options()` * `@app.head()` @@ -278,58 +302,79 @@ Daha az kullanฤฑlanlarฤฑ da kullanabilirsiniz: /// tip | ฤฐpucu -Her iลŸlemi (HTTP metod) istediฤŸiniz gibi kullanmakta รถzgรผrsรผnรผz. +Her bir operation'ฤฑ (HTTP method'unu) istediฤŸiniz gibi kullanmakta รถzgรผrsรผnรผz. -**FastAPI** herhangi bir รถzel amacฤฑ veya anlamฤฑ olmasฤฑ konusunda ฤฑsrarcฤฑ olmaz. +**FastAPI** herhangi bir รถzel anlamฤฑ zorunlu kฤฑlmaz. Buradaki bilgiler bir gereklilik deฤŸil, bir kฤฑlavuz olarak sunulmaktadฤฑr. -Mesela GraphQL kullanฤฑrkan genelde tรผm iลŸlemleri yalnฤฑzca `POST` operasyonunu kullanarak gerรงekleลŸtirirsiniz. +ร–rneฤŸin GraphQL kullanฤฑrken, normalde tรผm aksiyonlarฤฑ yalnฤฑzca `POST` operation'larฤฑ kullanarak gerรงekleลŸtirirsiniz. /// -### Adฤฑm 4: **Yol Operasyonu Fonksiyonunu** Tanฤฑmlayฤฑn +### Adฤฑm 4: **path operation function**'ฤฑ tanฤฑmlayฤฑn { #step-4-define-the-path-operation-function } -AลŸaฤŸฤฑdaki, bizim **yol operasyonu fonksiyonumuzdur**: +Bu bizim "**path operation function**"ฤฑmฤฑz: -* **yol**: `/` -* **operasyon**: `get` -* **fonksiyon**: "dekoratรถr"รผn (`@app.get("/")`'in) altฤฑndaki fonksiyondur. +* **path**: `/`. +* **operation**: `get`. +* **function**: "decorator"รผn altฤฑndaki fonksiyondur (`@app.get("/")`'in altฤฑndaki). -{* ../../docs_src/first_steps/tutorial001.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} Bu bir Python fonksiyonudur. -Bu fonksiyon bir `GET` iลŸlemi kullanฤฑlarak "`/`" baฤŸlantฤฑsฤฑna bir istek geldiฤŸinde **FastAPI** tarafฤฑndan รงaฤŸrฤฑlฤฑr. +**FastAPI**, "`/`" URL'ine `GET` operation kullanarak bir request aldฤฑฤŸฤฑnda bu fonksiyonu รงaฤŸฤฑracaktฤฑr. -Bu durumda bu fonksiyon bir `async` fonksiyondur. +Bu durumda, bu bir `async` fonksiyondur. --- -Bu fonksiyonu `async def` yerine normal bir fonksiyon olarak da tanฤฑmlayabilirsiniz. +Bunu `async def` yerine normal bir fonksiyon olarak da tanฤฑmlayabilirsiniz: -{* ../../docs_src/first_steps/tutorial003.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} /// note | Not -EฤŸer farkฤฑ bilmiyorsanฤฑz, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} sayfasฤฑnฤฑ kontrol edebilirsiniz. +EฤŸer farkฤฑ bilmiyorsanฤฑz, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} sayfasฤฑna bakฤฑn. /// -### Adฤฑm 5: ฤฐรงeriฤŸi Geri Dรถndรผrรผn +### Adฤฑm 5: iรงeriฤŸi dรถndรผrรผn { #step-5-return-the-content } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} + +Bir `dict`, `list`, `str`, `int` vb. tekil deฤŸerler dรถndรผrebilirsiniz. + +Ayrฤฑca Pydantic modelleri de dรถndรผrebilirsiniz (bununla ilgili daha fazlasฤฑnฤฑ ileride gรถreceksiniz). + +Otomatik olarak JSON'a dรถnรผลŸtรผrรผlecek (ORM'ler vb. dahil) baลŸka birรงok nesne ve model vardฤฑr. En sevdiฤŸiniz nesne/model'leri kullanmayฤฑ deneyin; bรผyรผk ihtimalle zaten destekleniyordur. + +### Adฤฑm 6: Deploy edin { #step-6-deploy-it } + +Uygulamanฤฑzฤฑ tek komutla **FastAPI Cloud**'a deploy edin: `fastapi deploy`. ๐ŸŽ‰ + +#### FastAPI Cloud Hakkฤฑnda { #about-fastapi-cloud } + +**FastAPI Cloud**, **FastAPI**'ฤฑn arkasฤฑndaki aynฤฑ yazar ve ekip tarafฤฑndan geliลŸtirilmiลŸtir. + +Minimum eforla bir API'ฤฑ **oluลŸturma**, **deploy etme** ve **eriลŸme** sรผrecini sadeleลŸtirir. + +FastAPI ile uygulama geliลŸtirirken yaลŸadฤฑฤŸฤฑnฤฑz aynฤฑ **developer experience**'ฤฑ, onlarฤฑ buluta **deploy etme** aลŸamasฤฑna da taลŸฤฑr. ๐ŸŽ‰ -{* ../../docs_src/first_steps/tutorial001.py hl[8] *} +FastAPI Cloud, *FastAPI and friends* aรงฤฑk kaynak projelerinin birincil sponsoru ve finansman saฤŸlayฤฑcฤฑsฤฑdฤฑr. โœจ -Bir `dict`, `list` veya `str`, `int` gibi tekil deฤŸerler dรถndรผrebilirsiniz. +#### DiฤŸer cloud saฤŸlayฤฑcฤฑlarฤฑna deploy edin { #deploy-to-other-cloud-providers } -Ayrฤฑca, Pydantic modelleri de dรถndรผrebilirsiniz (bu konu ileriki aลŸamalarda irdelenecektir). +FastAPI aรงฤฑk kaynaklฤฑdฤฑr ve standartlara dayanฤฑr. FastAPI uygulamalarฤฑnฤฑ seรงtiฤŸiniz herhangi bir cloud saฤŸlayฤฑcฤฑsฤฑna deploy edebilirsiniz. -Otomatik olarak JSON'a dรถnรผลŸtรผrรผlecek (ORM'ler vb. dahil) baลŸka birรงok nesne ve model vardฤฑr. En beฤŸendiklerinizi kullanmayฤฑ deneyin, yรผksek ihtimalle destekleniyordur. +FastAPI uygulamalarฤฑnฤฑ onlarla deploy etmek iรงin cloud saฤŸlayฤฑcฤฑnฤฑzฤฑn kฤฑlavuzlarฤฑnฤฑ takip edin. ๐Ÿค“ -## ร–zet +## ร–zet { #recap } -* `FastAPI`'yฤฑ projemize dahil ettik. -* Bir `app` รถrneฤŸi oluลŸturduk. -* Bir **yol operasyonu dekoratรถrรผ** (`@app.get("/")` gibi) yazdฤฑk. -* Bir **yol operasyonu fonksiyonu** (`def root(): ...` gibi) yazdฤฑk. -* GeliลŸtirme sunucumuzu (`uvicorn main:app --reload` gibi) รงalฤฑลŸtฤฑrdฤฑk. +* `FastAPI` import edin. +* Bir `app` instance'ฤฑ oluลŸturun. +* `@app.get("/")` gibi decorator'larฤฑ kullanarak bir **path operation decorator** yazฤฑn. +* Bir **path operation function** tanฤฑmlayฤฑn; รถrneฤŸin `def root(): ...`. +* `fastapi dev` komutunu kullanarak geliลŸtirme sunucusunu รงalฤฑลŸtฤฑrฤฑn. +* ฤฐsterseniz `fastapi deploy` ile uygulamanฤฑzฤฑ deploy edin. diff --git a/docs/tr/docs/tutorial/path-params.md b/docs/tr/docs/tutorial/path-params.md index 408dd25ca2..db676f1eed 100644 --- a/docs/tr/docs/tutorial/path-params.md +++ b/docs/tr/docs/tutorial/path-params.md @@ -1,34 +1,34 @@ -# Yol Parametreleri +# Yol Parametreleri { #path-parameters } -Yol "parametrelerini" veya "deฤŸiลŸkenlerini" Python string biรงimlemede kullanฤฑlan sรถzdizimi ile tanฤฑmlayabilirsiniz. +Python string biรงimlemede kullanฤฑlan sรถzdizimiyle path "parametreleri"ni veya "deฤŸiลŸkenleri"ni tanฤฑmlayabilirsiniz: -{* ../../docs_src/path_params/tutorial001.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} -Yol parametresi olan `item_id`'nin deฤŸeri, fonksiyonunuza `item_id` argรผmanฤฑ olarak aktarฤฑlacaktฤฑr. +Path parametresi `item_id`'nin deฤŸeri, fonksiyonunuza `item_id` argรผmanฤฑ olarak aktarฤฑlacaktฤฑr. -EฤŸer bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp http://127.0.0.1:8000/items/foo sayfasฤฑna giderseniz, ลŸรถyle bir รงฤฑktฤฑ ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +Yani, bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp http://127.0.0.1:8000/items/foo adresine giderseniz, ลŸรถyle bir response gรถrรผrsรผnรผz: ```JSON {"item_id":"foo"} ``` -## Tip ฤฐรงeren Yol Parametreleri +## Tip ฤฐรงeren Yol Parametreleri { #path-parameters-with-types } -Standart Python tip belirteรงlerini kullanarak yol parametresinin tipini fonksiyonun iรงerisinde tanฤฑmlayabilirsiniz. +Standart Python tip belirteรงlerini kullanarak path parametresinin tipini fonksiyonun iรงinde tanฤฑmlayabilirsiniz: -{* ../../docs_src/path_params/tutorial002.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} -Bu durumda, `item_id` bir `int` olarak tanฤฑmlanacaktฤฑr. +Bu durumda, `item_id` bir `int` olarak tanฤฑmlanฤฑr. /// check | Ek bilgi -Bu sayede, fonksiyon iรงerisinde hata denetimi, kod tamamlama gibi konularda editรถr desteฤŸine kavuลŸacaksฤฑnฤฑz. +Bu sayede, fonksiyon iรงinde hata denetimi, kod tamamlama vb. konularda editรถr desteฤŸine kavuลŸursunuz. /// -## Veri DรถnรผลŸรผmรผ +## Veri conversion { #data-conversion } -EฤŸer bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/3 sayfasฤฑnฤฑ aรงarsanฤฑz, ลŸรถyle bir yanฤฑt ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +Bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/3 adresini aรงarsanฤฑz, ลŸรถyle bir response gรถrรผrsรผnรผz: ```JSON {"item_id":3} @@ -36,15 +36,15 @@ EฤŸer bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp tarayฤฑcฤฑnฤฑzda "ayrฤฑลŸtฤฑrma" รถzelliฤŸi saฤŸlar. +Yani, bu tip tanฤฑmฤฑyla birlikte **FastAPI** size otomatik request "parsing" saฤŸlar. /// -## Veri DoฤŸrulama +## Veri DoฤŸrulama { #data-validation } -EฤŸer tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/foo sayfasฤฑnฤฑ aรงarsanฤฑz, ลŸuna benzer gรผzel bir HTTP hatasฤฑ ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +Ancak tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/foo adresine giderseniz, ลŸuna benzer gรผzel bir HTTP hatasฤฑ gรถrรผrsรผnรผz: ```JSON { @@ -62,141 +62,135 @@ EฤŸer tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/4.2 sayfasฤฑnda olduฤŸu gibi `int` yerine `float` bir deฤŸer verseydik de ortaya รงฤฑkardฤฑ. +Aynฤฑ hata, ลŸu รถrnekte olduฤŸu gibi `int` yerine `float` verirseniz de ortaya รงฤฑkar: http://127.0.0.1:8000/items/4.2 /// check | Ek bilgi -Bรถylece, aynฤฑ Python tip tanฤฑmlamasฤฑ ile birlikte, **FastAPI** veri doฤŸrulama รถzelliฤŸi saฤŸlar. +Yani, aynฤฑ Python tip tanฤฑmฤฑyla birlikte **FastAPI** size veri doฤŸrulama saฤŸlar. -Dikkatinizi รงekerim ki, karลŸฤฑlaลŸtฤฑฤŸฤฑnฤฑz hata, doฤŸrulamanฤฑn geรงersiz olduฤŸu mutlak noktayฤฑ da aรงฤฑk bir ลŸekilde belirtiyor. +Dikkat edin: hata ayrฤฑca doฤŸrulamanฤฑn geรงmediฤŸi noktayฤฑ da aรงฤฑkรงa belirtir. -Bu รถzellik, API'ฤฑnฤฑzla iletiลŸime geรงen kodu geliลŸtirirken ve ayฤฑklarken inanฤฑlmaz derecede yararlฤฑ olacaktฤฑr. +Bu, API'ฤฑnฤฑzla etkileลŸime giren kodu geliลŸtirirken ve debug ederken inanฤฑlmaz derecede faydalฤฑdฤฑr. /// -## Dokรผmantasyon +## Dokรผmantasyon { #documentation } -Ayrฤฑca, tarayฤฑcฤฑnฤฑzฤฑ http://127.0.0.1:8000/docs adresinde aรงarsanฤฑz, aลŸaฤŸฤฑdaki gibi otomatik ve interaktif bir API dรถkรผmantasyonu ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +Tarayฤฑcฤฑnฤฑzฤฑ http://127.0.0.1:8000/docs adresinde aรงtฤฑฤŸฤฑnฤฑzda, aลŸaฤŸฤฑdaki gibi otomatik ve interaktif bir API dokรผmantasyonu gรถrรผrsรผnรผz: /// check | Ek bilgi -รœstelik, sadece aynฤฑ Python tip tanฤฑmlamasฤฑ ile, **FastAPI** size otomatik ve interaktif (Swagger UI ile entegre) bir dokรผmantasyon saฤŸlar. +Yine, sadece aynฤฑ Python tip tanฤฑmฤฑyla **FastAPI** size otomatik ve interaktif dokรผmantasyon (Swagger UI entegrasyonuyla) saฤŸlar. -Dikkatinizi รงekerim ki, yol parametresi integer olarak tanฤฑmlanmฤฑลŸtฤฑr. +Dikkat edin: path parametresi integer olarak tanฤฑmlanmฤฑลŸtฤฑr. /// -## Standartlara Dayalฤฑ Avantajlar, Alternatif Dokรผmantasyon +## Standartlara Dayalฤฑ Avantajlar, Alternatif Dokรผmantasyon { #standards-based-benefits-alternative-documentation } -OluลŸturulan ลŸema OpenAPI standardฤฑna uygun olduฤŸu iรงin birรงok uyumlu araรง mevcuttur. +รœretilen ลŸema OpenAPI standardฤฑndan geldiฤŸi iรงin birรงok uyumlu araรง vardฤฑr. -Bu sayede, **FastAPI**'ฤฑn bizzat kendisi http://127.0.0.1:8000/redoc sayfasฤฑndan eriลŸebileceฤŸiniz alternatif (ReDoc kullanan) bir API dokรผmantasyonu saฤŸlar: +Bu nedenle **FastAPI**'ฤฑn kendisi, http://127.0.0.1:8000/redoc adresinden eriลŸebileceฤŸiniz alternatif bir API dokรผmantasyonu (ReDoc kullanarak) saฤŸlar: -Aynฤฑ ลŸekilde, farklฤฑ diller iรงin kod tรผretme araรงlarฤฑ da dahil olmak รผzere รงok sayฤฑda uyumlu araรง bulunur. +Aynฤฑ ลŸekilde, birรงok uyumlu araรง vardฤฑr. Birรงok dil iรงin kod รผretme araรงlarฤฑ da buna dahildir. -## Pydantic +## Pydantic { #pydantic } -Tรผm veri doฤŸrulamalarฤฑ Pydantic tarafฤฑndan arka planda gerรงekleลŸtirilir, bu sayede tรผm avantajlardan faydalanabilirsiniz. Bรถylece, emin ellerde olduฤŸunuzu hissedebilirsiniz. +Tรผm veri doฤŸrulamalarฤฑ, arka planda Pydantic tarafฤฑndan gerรงekleลŸtirilir; bรถylece onun tรผm avantajlarฤฑndan faydalanฤฑrsฤฑnฤฑz. Ve emin ellerde olduฤŸunuzu bilirsiniz. -Aynฤฑ tip tanฤฑmlamalarฤฑnฤฑ `str`, `float`, `bool` ve diฤŸer karmaลŸฤฑk veri tipleri ile kullanma imkanฤฑnฤฑz vardฤฑr. +Aynฤฑ tip tanฤฑmlarฤฑnฤฑ `str`, `float`, `bool` ve daha birรงok karmaลŸฤฑk veri tipiyle kullanabilirsiniz. -Bunlardan birkaรงฤฑ, bu eฤŸitimin ileriki bรถlรผmlerinde irdelenmiลŸtir. +Bunlarฤฑn birkaรงฤฑ, eฤŸitimin sonraki bรถlรผmlerinde ele alฤฑnacaktฤฑr. -## Sฤฑralama ร–nem Arz Eder +## Sฤฑralama ร–nemlidir { #order-matters } -*Yol operasyonlarฤฑ* tasarlarken sabit yol barฤฑndฤฑran durumlar ile karลŸฤฑlaลŸabilirsiniz. +*Path operation*'lar oluลŸtururken sabit bir path'e sahip olduฤŸunuz durumlarla karลŸฤฑlaลŸabilirsiniz. -Farz edelim ki `/users/me` yolu geรงerli kullanฤฑcฤฑ hakkฤฑnda bilgi almak iรงin kullanฤฑlฤฑyor olsun. +ร–rneฤŸin `/users/me`'nin, geรงerli kullanฤฑcฤฑ hakkฤฑnda veri almak iรงin kullanฤฑldฤฑฤŸฤฑnฤฑ varsayalฤฑm. -Benzer ลŸekilde `/users/{user_id}` gibi tanฤฑmlanmฤฑลŸ ve belirli bir kullanฤฑcฤฑ hakkฤฑnda veri almak iรงin kullanฤฑcฤฑnฤฑn ID bilgisini kullanan bir yolunuz da mevcut olabilir. +Sonra belirli bir kullanฤฑcฤฑ hakkฤฑnda, kullanฤฑcฤฑ ID'si ile veri almak iรงin `/users/{user_id}` ลŸeklinde bir path'iniz de olabilir. -*Yol operasyonlarฤฑ* sฤฑralฤฑ bir ลŸekilde gรถzden geรงirildiฤŸinden dolayฤฑ `/users/me` yolunun `/users/{user_id}` yolundan รถnce tanฤฑmlanmฤฑลŸ olmasฤฑndan emin olmanฤฑz gerekmektedir: +*Path operation*'lar sฤฑrayla deฤŸerlendirildiฤŸi iรงin, `/users/me` iรงin olan path'in `/users/{user_id}` olandan รถnce tanฤฑmlandฤฑฤŸฤฑndan emin olmanฤฑz gerekir: -{* ../../docs_src/path_params/tutorial003.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} -Aksi halde, `/users/{user_id}` yolu `"me"` deฤŸerinin `user_id` parametresi iรงin gรถnderildiฤŸini "dรผลŸรผnerek" `/users/me` ile de eลŸleลŸir. +Aksi halde, `/users/{user_id}` iรงin olan path, `"me"` deฤŸerini `user_id` parametresi olarak aldฤฑฤŸฤฑnฤฑ "dรผลŸรผnerek" `/users/me` iรงin de eลŸleลŸir. -Benzer ลŸekilde, bir yol operasyonunu yeniden tanฤฑmlamanฤฑz mรผmkรผn deฤŸildir: +Benzer ลŸekilde, bir path operation'ฤฑ yeniden tanฤฑmlayamazsฤฑnฤฑz: -{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} -Yol, ilk kฤฑsฤฑm ile eลŸleลŸtiฤŸinden dolayฤฑ her koลŸulda ilk yol operasyonu kullanฤฑlacaktฤฑr. +Path รถnce eลŸleลŸtiฤŸi iรงin her zaman ilk olan kullanฤฑlฤฑr. -## ร–n Tanฤฑmlฤฑ DeฤŸerler +## ร–n Tanฤฑmlฤฑ DeฤŸerler { #predefined-values } -EฤŸer *yol parametresi* alan bir *yol operasyonunuz* varsa ve alabileceฤŸi *yol parametresi* deฤŸerlerinin รถn tanฤฑmlฤฑ olmasฤฑnฤฑ istiyorsanฤฑz, standart Python `Enum` tipini kullanabilirsiniz. +Bir *path operation*'ฤฑnฤฑz *path parameter* alฤฑyorsa ama olasฤฑ geรงerli *path parameter* deฤŸerlerinin รถnceden tanฤฑmlฤฑ olmasฤฑnฤฑ istiyorsanฤฑz, standart bir Python `Enum` kullanabilirsiniz. -### Bir `Enum` Sฤฑnฤฑfฤฑ OluลŸturalฤฑm +### Bir `Enum` Sฤฑnฤฑfฤฑ OluลŸturalฤฑm { #create-an-enum-class } -`Enum` sฤฑnฤฑfฤฑnฤฑ projemize dahil edip `str` ile `Enum` sฤฑnฤฑflarฤฑnฤฑ miras alan bir alt sฤฑnฤฑf yaratalฤฑm. +`Enum`'u import edin ve `str` ile `Enum`'dan miras alan bir alt sฤฑnฤฑf oluลŸturun. -`str` sฤฑnฤฑfฤฑ miras alฤฑndฤฑฤŸฤฑndan dolayฤฑ, API dokรผmanฤฑ, deฤŸerlerin `string` tipinde olmasฤฑ gerektiฤŸini anlayabilecek ve doฤŸru bir ลŸekilde iลŸlenecektir. +`str`'den miras aldฤฑฤŸฤฑnฤฑzda API dokรผmanlarฤฑ deฤŸerlerin `string` tipinde olmasฤฑ gerektiฤŸini anlayabilir ve doฤŸru ลŸekilde render edebilir. -Sonrasฤฑnda, sฤฑnฤฑf iรงerisinde, mevcut ve geรงerli deฤŸerler olacak olan sabit deฤŸerli รถzelliklerini oluลŸturalฤฑm: +Sonra, kullanฤฑlabilir geรงerli deฤŸerler olacak sabit deฤŸerli class attribute'larฤฑ oluลŸturun: -{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *} - -/// info | Bilgi - -3.4 sรผrรผmรผnden beri enumerationlar (ya da enumlar) Python'da mevcuttur. - -/// +{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} /// tip | ฤฐpucu -Merak ediyorsanฤฑz sรถyleyeyim, "AlexNet", "ResNet" ve "LeNet" isimleri Makine ร–ฤŸrenmesi modellerini temsil eder. +Merak ediyorsanฤฑz: "AlexNet", "ResNet" ve "LeNet", Makine ร–ฤŸrenmesi modellerinin sadece isimleridir. /// -### Bir *Yol Parametresi* Tanฤฑmlayalฤฑm +### Bir *Path Parameter* Tanฤฑmlayalฤฑm { #declare-a-path-parameter } -Sonrasฤฑnda, yarattฤฑฤŸฤฑmฤฑz enum sฤฑnฤฑfฤฑnฤฑ (`ModelName`) kullanarak tip belirteci aracฤฑlฤฑฤŸฤฑyla bir *yol parametresi* oluลŸturalฤฑm: +Ardฤฑndan oluลŸturduฤŸunuz enum sฤฑnฤฑfฤฑnฤฑ (`ModelName`) kullanarak tip belirteciyle bir *path parameter* oluลŸturun: -{* ../../docs_src/path_params/tutorial005.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} -### Dokรผmana Gรถz Atalฤฑm +### Dokรผmana Gรถz Atalฤฑm { #check-the-docs } -*Yol parametresi* iรงin mevcut deฤŸerler รถn tanฤฑmlฤฑ olduฤŸundan dolayฤฑ, interaktif dรถkรผman onlarฤฑ gรผzel bir ลŸekilde gรถsterebilir: +*Path parameter* iรงin kullanฤฑlabilir deฤŸerler รถn tanฤฑmlฤฑ olduฤŸu iรงin, interaktif dokรผmanlar bunlarฤฑ gรผzelce gรถsterebilir: -### Python *Enumerationlarฤฑ* ile ร‡alฤฑลŸmak +### Python *Enumeration*'larฤฑ ile ร‡alฤฑลŸmak { #working-with-python-enumerations } -*Yol parametresinin* deฤŸeri bir *enumeration รผyesi* olacaktฤฑr. +*Path parameter*'ฤฑn deฤŸeri bir *enumeration member* olacaktฤฑr. -#### *Enumeration รœyelerini* KarลŸฤฑlaลŸtฤฑralฤฑm +#### *Enumeration Member*'larฤฑ KarลŸฤฑlaลŸtฤฑralฤฑm { #compare-enumeration-members } -Parametreyi, yarattฤฑฤŸฤฑnฤฑz enum olan `ModelName` iรงerisindeki *enumeration รผyesi* ile karลŸฤฑlaลŸtฤฑrabilirsiniz: +Bunu, oluลŸturduฤŸunuz enum `ModelName` iรงindeki *enumeration member* ile karลŸฤฑlaลŸtฤฑrabilirsiniz: -{* ../../docs_src/path_params/tutorial005.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} -#### *Enumeration DeฤŸerini* Edinelim +#### *Enumeration Value*'yu Alalฤฑm { #get-the-enumeration-value } -`model_name.value` veya genel olarak `your_enum_member.value` tanฤฑmlarฤฑnฤฑ kullanarak (bu durumda bir `str` olan) gerรงek deฤŸere ulaลŸabilirsiniz: +Gerรงek deฤŸeri (bu durumda bir `str`) `model_name.value` ile veya genel olarak `your_enum_member.value` ile alabilirsiniz: -{* ../../docs_src/path_params/tutorial005.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} /// tip | ฤฐpucu -`"lenet"` deฤŸerine `ModelName.lenet.value` tanฤฑmฤฑ ile de ulaลŸabilirsiniz. +`"lenet"` deฤŸerine `ModelName.lenet.value` ile de eriลŸebilirsiniz. /// -#### *Enumeration รœyelerini* Dรถndรผrelim +#### *Enumeration Member*'larฤฑ Dรถndรผrelim { #return-enumeration-members } -JSON gรถvdesine (รถrneฤŸin bir `dict`) gรถmรผlรผ olsalar bile *yol operasyonundaki* *enum รผyelerini* dรถndรผrebilirsiniz. +*Path operation*'ฤฑnฤฑzdan, bir JSON body'nin iรงine gรถmรผlรผ olsalar bile (รถr. bir `dict`) *enum member*'larฤฑ dรถndรผrebilirsiniz. -Bu รผyeler istemciye iletilmeden รถnce kendilerine karลŸฤฑlฤฑk gelen deฤŸerlerine (bu durumda string) dรถnรผลŸtรผrรผleceklerdir: +ฤฐstemciye dรถnmeden รถnce, karลŸฤฑlฤฑk gelen deฤŸerlerine (bu durumda string) dรถnรผลŸtรผrรผlรผrler: -{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} -ฤฐstemci tarafฤฑnda ลŸuna benzer bir JSON yanฤฑtฤฑ ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +ฤฐstemcinizde ลŸรถyle bir JSON response alฤฑrsฤฑnฤฑz: ```JSON { @@ -205,53 +199,53 @@ Bu รผyeler istemciye iletilmeden รถnce kendilerine karลŸฤฑlฤฑk gelen deฤŸerlerin } ``` -## Yol ฤฐรงeren Yol Parametreleri +## Path ฤฐรงeren Path Parametreleri { #path-parameters-containing-paths } -Farz edelim ki elinizde `/files/{file_path}` isminde bir *yol operasyonu* var. +Diyelim ki `/files/{file_path}` path'ine sahip bir *path operation*'ฤฑnฤฑz var. -Fakat `file_path` deฤŸerinin `home/johndoe/myfile.txt` gibi bir *yol* barฤฑndฤฑrmasฤฑnฤฑ istiyorsunuz. +Ama `file_path`'in kendisinin `home/johndoe/myfile.txt` gibi bir *path* iรงermesi gerekiyor. -Sonuรง olarak, oluลŸturmak istediฤŸin URL `/files/home/johndoe/myfile.txt` gibi bir ลŸey olacaktฤฑr. +Bรถylece, o dosyanฤฑn URL'si ลŸu ลŸekilde olur: `/files/home/johndoe/myfile.txt`. -### OpenAPI DesteฤŸi +### OpenAPI DesteฤŸi { #openapi-support } -Test etmesi ve tanฤฑmlamasฤฑ zor senaryolara sebebiyet vereceฤŸinden dolayฤฑ OpenAPI, *yol* barฤฑndฤฑran *yol parametrelerini* tanฤฑmlayacak bir รงรถzรผm sunmuyor. +OpenAPI, iรงinde bir *path* barฤฑndฤฑracak bir *path parameter* tanฤฑmlamak iรงin bir yรถntem desteklemez; รงรผnkรผ bu, test etmesi ve tanฤฑmlamasฤฑ zor senaryolara yol aรงabilir. -Ancak bunu, Starlette kรผtรผphanesinin dahili araรงlarฤฑndan birini kullanarak **FastAPI**'da gerรงekleลŸtirebilirsiniz. +Yine de, Starlette'in dahili araรงlarฤฑndan birini kullanarak bunu **FastAPI**'da yapabilirsiniz. -Parametrenin bir yol iรงermesi gerektiฤŸini belirten herhangi bir dokรผman eklemememize raฤŸmen dokรผmanlar yine de รงalฤฑลŸacaktฤฑr. +Ve dokรผmanlar, parametrenin bir path iรงermesi gerektiฤŸini sรถyleyen herhangi bir dokรผmantasyon eklemese bile รงalฤฑลŸmaya devam eder. -### Yol DรถnรผลŸtรผrรผcรผ +### Path DรถnรผลŸtรผrรผcรผ { #path-convertor } -Direkt olarak Starlette kรผtรผphanesinden gelen bir opsiyon sayesinde aลŸaฤŸฤฑdaki gibi *yol* iรงeren bir *yol parametresi* baฤŸlantฤฑsฤฑ tanฤฑmlayabilirsiniz: +Starlette'ten doฤŸrudan gelen bir seรงenekle, *path* iรงeren bir *path parameter*'ฤฑ ลŸu URL ile tanฤฑmlayabilirsiniz: ``` /files/{file_path:path} ``` -Bu durumda, parametrenin adฤฑ `file_path` olacaktฤฑr ve son kฤฑsฤฑm olan `:path` kฤฑsmฤฑ, parametrenin herhangi bir *yol* ile eลŸleลŸmesi gerektiฤŸini belirtecektir. +Bu durumda parametrenin adฤฑ `file_path`'tir ve son kฤฑsฤฑm olan `:path`, parametrenin herhangi bir *path* ile eลŸleลŸmesi gerektiฤŸini sรถyler. -Bรถylece ลŸunun gibi bir kullanฤฑm yapabilirsiniz: +Yani ลŸununla kullanabilirsiniz: -{* ../../docs_src/path_params/tutorial004.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} /// tip | ฤฐpucu -Parametrenin baลŸฤฑnda `/home/johndoe/myfile.txt` yolunda olduฤŸu gibi (`/`) iลŸareti ile birlikte kullanmanฤฑz gerektiฤŸi durumlar olabilir. +Parametrenin baลŸฤฑnda `/home/johndoe/myfile.txt` รถrneฤŸinde olduฤŸu gibi bir eฤŸik รงizgi (`/`) ile baลŸlamasฤฑ gerekebilir. -Bu durumda, URL, `files` ile `home` arasฤฑnda iki eฤŸik รงizgiye (`//`) sahip olup `/files//home/johndoe/myfile.txt` gibi gรถzรผkecektir. +Bu durumda URL, `files` ile `home` arasฤฑnda รงift eฤŸik รงizgi (`//`) olacak ลŸekilde `/files//home/johndoe/myfile.txt` olur. /// -## ร–zet +## ร–zet { #recap } -**FastAPI** ile kฤฑsa, sezgisel ve standart Python tip tanฤฑmlamalarฤฑ kullanarak ลŸunlarฤฑ elde edersiniz: +**FastAPI** ile kฤฑsa, sezgisel ve standart Python tip tanฤฑmlarฤฑnฤฑ kullanarak ลŸunlarฤฑ elde edersiniz: -* Editรถr desteฤŸi: hata denetimi, otomatik tamamlama, vb. -* Veri "dรถnรผลŸtรผrme" +* Editรถr desteฤŸi: hata denetimleri, otomatik tamamlama vb. +* Veri "parsing" * Veri doฤŸrulama -* API tanฤฑmlamalarฤฑ ve otomatik dokรผmantasyon +* API annotation ve otomatik dokรผmantasyon -Ve sadece, bunlarฤฑ bir kez tanฤฑmlamanฤฑz yeterli. +Ve bunlarฤฑ sadece bir kez tanฤฑmlamanฤฑz yeterlidir. -DiฤŸer frameworkler ile karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnda (ham performans dฤฑลŸฤฑnda), รผstte anlatฤฑlan durum muhtemelen **FastAPI**'ฤฑn gรถze รงarpan baลŸlฤฑca avantajฤฑdฤฑr. +Bu, (ham performans dฤฑลŸฤฑnda) **FastAPI**'ฤฑn alternatif framework'lere kฤฑyasla muhtemelen en gรถrรผnรผr ana avantajฤฑdฤฑr. diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md index a8ba883edc..89cfa3fb35 100644 --- a/docs/tr/docs/tutorial/query-params.md +++ b/docs/tr/docs/tutorial/query-params.md @@ -1,83 +1,83 @@ -# Sorgu Parametreleri +# Sorgu Parametreleri { #query-parameters } -Fonksiyonda yol parametrelerinin parรงasฤฑ olmayan diฤŸer tanฤฑmlamalar otomatik olarak "sorgu" parametresi olarak yorumlanฤฑr. +Fonksiyonda path parametrelerinin parรงasฤฑ olmayan diฤŸer parametreleri tanฤฑmladฤฑฤŸฤฑnฤฑzda, bunlar otomatik olarak "query" parametreleri olarak yorumlanฤฑr. -{* ../../docs_src/query_params/tutorial001.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} -Sorgu, baฤŸlantฤฑdaki `?` kฤฑsmฤฑndan sonra gelen ve `&` iลŸareti ile ayrฤฑlan anahtar-deฤŸer รงiftlerinin oluลŸturduฤŸu bir kรผmedir. +Query, bir URL'de `?` iลŸaretinden sonra gelen ve `&` karakterleriyle ayrฤฑlan anahtar-deฤŸer รงiftlerinin kรผmesidir. -ร–rneฤŸin, aลŸaฤŸฤฑdaki baฤŸlantฤฑda: +ร–rneฤŸin, ลŸu URL'de: ``` http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...sorgu parametreleri ลŸunlardฤฑr: +...query parametreleri ลŸunlardฤฑr: -* `skip`: deฤŸeri `0`'dฤฑr -* `limit`: deฤŸeri `10`'dฤฑr +* `skip`: deฤŸeri `0` +* `limit`: deฤŸeri `10` -Parametreler baฤŸlantฤฑnฤฑn bir parรงasฤฑ olduklarฤฑ iรงin doฤŸal olarak string olarak deฤŸerlendirilirler. +URL'nin bir parรงasฤฑ olduklarฤฑ iรงin "doฤŸal olarak" string'tirler. -Fakat, Python tipleri ile tanฤฑmlandฤฑklarฤฑ zaman (yukarฤฑdaki รถrnekte `int` olduklarฤฑ gibi), parametreler o tiplere dรถnรผลŸtรผrรผlรผr ve o tipler รงerรงevesinde doฤŸrulanฤฑrlar. +Ancak, bunlarฤฑ Python tipleriyle (yukarฤฑdaki รถrnekte `int` olarak) tanฤฑmladฤฑฤŸฤฑnฤฑzda, o tipe dรถnรผลŸtรผrรผlรผrler ve o tipe gรถre doฤŸrulanฤฑrlar. -Yol parametreleri iรงin geรงerli olan her tรผrlรผ iลŸlem aynฤฑ ลŸekilde sorgu parametreleri iรงin de geรงerlidir: +Path parametreleri iรงin geรงerli olan aynฤฑ sรผreรง query parametreleri iรงin de geรงerlidir: -* Editรถr desteฤŸi (ลŸรผphesiz) -* Veri "ayrฤฑลŸtฤฑrma" +* Editรถr desteฤŸi (tabii ki) +* Veri "parsing" * Veri doฤŸrulama * Otomatik dokรผmantasyon -## Varsayฤฑlanlar +## Varsayฤฑlanlar { #defaults } -Sorgu parametreleri, adres yolunun sabit bir parรงasฤฑ olmadฤฑklarฤฑndan dolayฤฑ isteฤŸe baฤŸlฤฑ ve varsayฤฑlan deฤŸere sahip olabilirler. +Query parametreleri path'in sabit bir parรงasฤฑ olmadฤฑฤŸฤฑndan, opsiyonel olabilir ve varsayฤฑlan deฤŸerlere sahip olabilir. -Yukarฤฑdaki รถrnekte `skip=0` ve `limit=10` varsayฤฑlan deฤŸere sahiplerdir. +Yukarฤฑdaki รถrnekte varsayฤฑlan deฤŸerleri `skip=0` ve `limit=10`'dur. -Yani, aลŸaฤŸฤฑdaki baฤŸlantฤฑya gitmek: +Yani ลŸu URL'ye gitmek: ``` http://127.0.0.1:8000/items/ ``` -ลŸu adrese gitmek ile aynฤฑ etkiye sahiptir: +ลŸuraya gitmekle aynฤฑ olur: ``` http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -Ancak, mesela ลŸรถyle bir adresi ziyaret ederseniz: +Ancak รถrneฤŸin ลŸuraya giderseniz: ``` http://127.0.0.1:8000/items/?skip=20 ``` -Fonksiyonunuzdaki parametre deฤŸerleri aลŸaฤŸฤฑdaki gibi olacaktฤฑr: +Fonksiyonunuzdaki parametre deฤŸerleri ลŸรถyle olacaktฤฑr: -* `skip=20`: รงรผnkรผ baฤŸlantฤฑda bรถyle tanฤฑmlandฤฑ. -* `limit=10`: รงรผnkรผ varsayฤฑlan deฤŸer buydu. +* `skip=20`: รงรผnkรผ URL'de siz ayarladฤฑnฤฑz +* `limit=10`: รงรผnkรผ varsayฤฑlan deฤŸer oydu -## ฤฐsteฤŸe BaฤŸlฤฑ Parametreler +## ฤฐsteฤŸe baฤŸlฤฑ parametreler { #optional-parameters } -Aynฤฑ ลŸekilde, varsayฤฑlan deฤŸerlerini `None` olarak atayarak isteฤŸe baฤŸlฤฑ parametreler tanฤฑmlayabilirsiniz: +Aynฤฑ ลŸekilde, varsayฤฑlan deฤŸerlerini `None` yaparak isteฤŸe baฤŸlฤฑ query parametreleri tanฤฑmlayabilirsiniz: {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} -Bu durumda, `q` fonksiyon parametresi isteฤŸe baฤŸlฤฑ olacak ve varsayฤฑlan deฤŸer olarak `None` alacaktฤฑr. +Bu durumda, fonksiyon parametresi `q` isteฤŸe baฤŸlฤฑ olur ve varsayฤฑlan olarak `None` olur. /// check | Ek bilgi -Ayrฤฑca, dikkatinizi รงekerim ki; **FastAPI**, `item_id` parametresinin bir yol parametresi olduฤŸunu ve `q` parametresinin yol deฤŸil bir sorgu parametresi olduฤŸunu fark edecek kadar beceriklidir. +Ayrฤฑca, **FastAPI** path parametresi olan `item_id`'nin bir path parametresi olduฤŸunu ve `q`'nun path olmadฤฑฤŸฤฑnฤฑ fark edecek kadar akฤฑllฤฑdฤฑr; dolayฤฑsฤฑyla bu bir query parametresidir. /// -## Sorgu Parametresi Tip DรถnรผลŸรผmรผ +## Sorgu parametresi tip dรถnรผลŸรผmรผ { #query-parameter-type-conversion } -AลŸaฤŸฤฑda gรถrรผldรผฤŸรผ gibi dรถnรผลŸtรผrรผlmek รผzere `bool` tipleri de tanฤฑmlayabilirsiniz: +`bool` tipleri de tanฤฑmlayabilirsiniz, ve bunlar dรถnรผลŸtรผrรผlรผr: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -Bu durumda, eฤŸer ลŸu adrese giderseniz: +Bu durumda, ลŸuraya giderseniz: ``` http://127.0.0.1:8000/items/foo?short=1 @@ -107,38 +107,38 @@ veya http://127.0.0.1:8000/items/foo?short=yes ``` -veya adres, herhangi farklฤฑ bir harf varyasyonu iรงermesi durumuna raฤŸmen (bรผyรผk harf, sadece baลŸ harfi bรผyรผk kelime, vb.) fonksiyonunuz, `bool` tipli `short` parametresini `True` olarak algฤฑlayacaktฤฑr. Aksi halde `False` olarak algฤฑlanacaktฤฑr. +veya baลŸka herhangi bir bรผyรผk/kรผรงรผk harf varyasyonunda (tamamฤฑ bรผyรผk, ilk harf bรผyรผk, vb.), fonksiyonunuz `short` parametresini `bool` deฤŸeri `True` olarak gรถrecektir. Aksi halde `False` olarak gรถrรผr. -## ร‡oklu Yol ve Sorgu Parametreleri +## ร‡oklu path ve query parametreleri { #multiple-path-and-query-parameters } -**FastAPI** neyin ne olduฤŸunu ayฤฑrt edebileceฤŸinden dolayฤฑ aynฤฑ anda birden fazla yol ve sorgu parametresi tanฤฑmlayabilirsiniz. +Aynฤฑ anda birden fazla path parametresi ve query parametresi tanฤฑmlayabilirsiniz; **FastAPI** hangisinin hangisi olduฤŸunu bilir. -Ve parametreleri, herhangi bir sฤฑraya koymanฤฑza da gerek yoktur. +Ayrฤฑca bunlarฤฑ belirli bir sฤฑrayla tanฤฑmlamanฤฑz gerekmez. -ฤฐsimlerine gรถre belirleneceklerdir: +ฤฐsme gรถre tespit edilirler: {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## Zorunlu Sorgu Parametreleri +## Zorunlu query parametreleri { #required-query-parameters } -Tรผrรผ yol olmayan bir parametre (ลŸu ana kadar sadece sorgu parametrelerini gรถrdรผk) iรงin varsayฤฑlan deฤŸer tanฤฑmlarsanฤฑz o parametre zorunlu olmayacaktฤฑr. +Path olmayan parametreler (ลŸimdilik sadece query parametrelerini gรถrdรผk) iรงin varsayฤฑlan deฤŸer tanฤฑmladฤฑฤŸฤฑnฤฑzda, bu parametre zorunlu olmaz. -Parametre iรงin belirli bir deฤŸer atamak istemeyip parametrenin sadece isteฤŸe baฤŸlฤฑ olmasฤฑnฤฑ istiyorsanฤฑz deฤŸerini `None` olarak atayabilirsiniz. +Belirli bir deฤŸer eklemek istemiyor ama sadece opsiyonel olmasฤฑnฤฑ istiyorsanฤฑz, varsayฤฑlanฤฑ `None` olarak ayarlayฤฑn. -Fakat, bir sorgu parametresini zorunlu yapmak istiyorsanฤฑz varsayฤฑlan bir deฤŸer atamamanฤฑz yeterli olacaktฤฑr: +Ancak bir query parametresini zorunlu yapmak istediฤŸinizde, herhangi bir varsayฤฑlan deฤŸer tanฤฑmlamamanฤฑz yeterlidir: -{* ../../docs_src/query_params/tutorial005.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} -Burada `needy` parametresi `str` tipinden oluลŸan zorunlu bir sorgu parametresidir. +Burada query parametresi `needy`, `str` tipinde zorunlu bir query parametresidir. -EฤŸer tarayฤฑcฤฑnฤฑzda ลŸu baฤŸlantฤฑyฤฑ: +Tarayฤฑcฤฑnฤฑzda ลŸรถyle bir URL aรงarsanฤฑz: ``` http://127.0.0.1:8000/items/foo-item ``` -...`needy` parametresini eklemeden aรงarsanฤฑz ลŸuna benzer bir hata ile karลŸฤฑlaลŸฤฑrsฤฑnฤฑz: +...zorunlu `needy` parametresini eklemeden, ลŸuna benzer bir hata gรถrรผrsรผnรผz: ```JSON { @@ -156,13 +156,13 @@ http://127.0.0.1:8000/items/foo-item } ``` -`needy` zorunlu bir parametre olduฤŸundan dolayฤฑ baฤŸlantฤฑda tanฤฑmlanmasฤฑ gerekir: +`needy` zorunlu bir parametre olduฤŸundan, URL'de ayarlamanฤฑz gerekir: ``` http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ``` -...bu iลŸ gรถrรผr: +...bu รงalฤฑลŸฤฑr: ```JSON { @@ -171,11 +171,11 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -Ve elbette, bazฤฑ parametreleri zorunlu, bazฤฑlarฤฑnฤฑ varsayฤฑlan deฤŸerli ve bazฤฑlarฤฑnฤฑ tamamen opsiyonel olarak tanฤฑmlayabilirsiniz: +Ve elbette, bazฤฑ parametreleri zorunlu, bazฤฑlarฤฑnฤฑ varsayฤฑlan deฤŸerli, bazฤฑlarฤฑnฤฑ da tamamen isteฤŸe baฤŸlฤฑ olarak tanฤฑmlayabilirsiniz: {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -Bu durumda, 3 tane sorgu parametresi var olacaktฤฑr: +Bu durumda, 3 tane query parametresi vardฤฑr: * `needy`, zorunlu bir `str`. * `skip`, varsayฤฑlan deฤŸeri `0` olan bir `int`. @@ -183,6 +183,6 @@ Bu durumda, 3 tane sorgu parametresi var olacaktฤฑr: /// tip | ฤฐpucu -Ayrฤฑca, [Yol Parametrelerinde](path-params.md#on-tanml-degerler){.internal-link target=_blank} de kullanฤฑldฤฑฤŸฤฑ ลŸekilde `Enum` sฤฑnฤฑfฤฑndan faydalanabilirsiniz. +[Path Parametreleri](path-params.md#predefined-values){.internal-link target=_blank} ile aynฤฑ ลŸekilde `Enum`'larฤฑ da kullanabilirsiniz. /// diff --git a/docs/tr/docs/tutorial/request-forms.md b/docs/tr/docs/tutorial/request-forms.md index e4e04f5f99..4608a6b79b 100644 --- a/docs/tr/docs/tutorial/request-forms.md +++ b/docs/tr/docs/tutorial/request-forms.md @@ -1,69 +1,73 @@ -# Form Verisi +# Form Verisi { #form-data } -ฤฐstek gรถvdesinde JSON verisi yerine form alanlarฤฑnฤฑ karลŸฤฑlamanฤฑz gerketiฤŸinde `Form` sฤฑnฤฑfฤฑnฤฑ kullanabilirsiniz. +JSON yerine form alanlarฤฑnฤฑ almanฤฑz gerektiฤŸinde `Form` kullanabilirsiniz. /// info | Bilgi -Formlarฤฑ kullanmak iรงin รถncelikle `python-multipart` paketini indirmeniz gerekmektedir. +Formlarฤฑ kullanmak iรงin รถnce `python-multipart` paketini kurun. -ร–rneฤŸin `pip install python-multipart`. +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu etkinleลŸtirdiฤŸinizden emin olun ve ardฤฑndan รถrneฤŸin ลŸรถyle kurun: + +```console +$ pip install python-multipart +``` /// -## `Form` Sฤฑnฤฑfฤฑnฤฑ Projenize Dahil Edin +## `Form`'u Import Edin { #import-form } -`Form` sฤฑnฤฑfฤฑnฤฑ `fastapi`'den projenize dahil edin: +`Form`'u `fastapi`'den import edin: {* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} -## `Form` Parametrelerini Tanฤฑmlayฤฑn +## `Form` Parametrelerini Tanฤฑmlayฤฑn { #define-form-parameters } Form parametrelerini `Body` veya `Query` iรงin yaptฤฑฤŸฤฑnฤฑz gibi oluลŸturun: {* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} -ร–rneฤŸin, OAuth2 spesifikasyonunun kullanฤฑlabileceฤŸi ("ลŸifre akฤฑลŸฤฑ" olarak adlandฤฑrฤฑlan) yollardan birinde, form alanlarฤฑ olarak "username" ve "password" gรถnderilmesi gerekir. +ร–rneฤŸin OAuth2 spesifikasyonunun kullanฤฑlabileceฤŸi ("password flow" olarak adlandฤฑrฤฑlan) yollardan birinde, form alanlarฤฑ olarak bir `username` ve `password` gรถndermek zorunludur. -Bu spesifikasyon form alanlarฤฑnฤฑ adlandฤฑrฤฑrken isimlerinin birebir `username` ve `password` olmasฤฑnฤฑ ve JSON verisi yerine form verisi olarak gรถnderilmesini gerektirir. +spec, alanlarฤฑn adฤฑnฤฑn tam olarak `username` ve `password` olmasฤฑnฤฑ ve JSON deฤŸil form alanlarฤฑ olarak gรถnderilmesini gerektirir. -`Form` sฤฑnฤฑfฤฑyla tanฤฑmlama yaparken `Body`, `Query`, `Path` ve `Cookie` sฤฑnฤฑflarฤฑnda kullandฤฑฤŸฤฑnฤฑz aynฤฑ validasyon, รถrnekler, isimlendirme (รถrneฤŸin `username` yerine `user-name` kullanฤฑmฤฑ) ve daha fazla konfigurasyonu kullanabilirsiniz. +`Form` ile `Body` (ve `Query`, `Path`, `Cookie`) ile yaptฤฑฤŸฤฑnฤฑz aynฤฑ konfigรผrasyonlarฤฑ tanฤฑmlayabilirsiniz; validasyon, รถrnekler, alias (รถrn. `username` yerine `user-name`) vb. dahil. /// info | Bilgi -`Form` doฤŸrudan `Body` sฤฑnฤฑfฤฑnฤฑ miras alan bir sฤฑnฤฑftฤฑr. +`Form`, doฤŸrudan `Body`'den miras alan bir sฤฑnฤฑftฤฑr. /// /// tip | ฤฐpucu -Form gรถvdelerini tanฤฑmlamak iรงin `Form` sฤฑnฤฑfฤฑnฤฑ kullanmanฤฑz gerekir; รงรผnkรผ bu olmadan parametreler sorgu parametreleri veya gรถvde (JSON) parametreleri olarak yorumlanฤฑr. +Form gรถvdelerini tanฤฑmlamak iรงin `Form`'u aรงฤฑkรงa kullanmanฤฑz gerekir; รงรผnkรผ bunu yapmazsanฤฑz parametreler query parametreleri veya body (JSON) parametreleri olarak yorumlanฤฑr. /// -## "Form Alanlarฤฑ" Hakkฤฑnda +## "Form Alanlarฤฑ" Hakkฤฑnda { #about-form-fields } -HTML formlarฤฑnฤฑn (`
`) verileri sunucuya gรถnderirken JSON'dan farklฤฑ รถzel bir kodlama kullanฤฑr. +HTML formlarฤฑnฤฑn (`
`) verileri sunucuya gรถnderme ลŸekli normalde bu veri iรงin JSON'dan farklฤฑ "รถzel" bir encoding kullanฤฑr. -**FastAPI** bu verilerin JSON yerine doฤŸru ลŸekilde okunmasฤฑnฤฑ saฤŸlayacaktฤฑr. +**FastAPI** bu veriyi JSON yerine doฤŸru yerden okuyacaktฤฑr. /// note | Teknik Detaylar -Form verileri normalde `application/x-www-form-urlencoded` medya tipiyle kodlanฤฑr. +Formlardan gelen veri normalde "media type" `application/x-www-form-urlencoded` kullanฤฑlarak encode edilir. -Ancak form iรงerisinde dosyalar yer aldฤฑฤŸฤฑnda `multipart/form-data` olarak kodlanฤฑr. Bir sonraki bรถlรผmde dosyalarฤฑn iลŸlenmesi hakkฤฑnda bilgi edineceksiniz. +Ancak form dosyalar iรงerdiฤŸinde `multipart/form-data` olarak encode edilir. Dosyalarฤฑ ele almayฤฑ bir sonraki bรถlรผmde okuyacaksฤฑnฤฑz. -Form kodlama tรผrleri ve form alanlarฤฑ hakkฤฑnda daha fazla bilgi edinmek istiyorsanฤฑz MDN web docs for POST sayfasฤฑnฤฑ ziyaret edebilirsiniz. +Bu encoding'ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz, MDN web docs for POST sayfasฤฑna gidin. /// /// warning | Uyarฤฑ -*Yol operasyonlarฤฑ* iรงerisinde birden fazla `Form` parametresi tanฤฑmlayabilirsiniz ancak bunlarla birlikte JSON verisi kabul eden `Body` alanlarฤฑ tanฤฑmlayamazsฤฑnฤฑz รงรผnkรผ bu durumda istek gรถvdesi `application/json` yerine `application/x-www-form-urlencoded` ile kodlanmฤฑลŸ olur. +Bir *path operation* iรงinde birden fazla `Form` parametresi tanฤฑmlayabilirsiniz, ancak JSON olarak almayฤฑ beklediฤŸiniz `Body` alanlarฤฑnฤฑ da ayrฤฑca tanฤฑmlayamazsฤฑnฤฑz; รงรผnkรผ bu durumda request'in body'si `application/json` yerine `application/x-www-form-urlencoded` ile encode edilmiลŸ olur. -Bu **FastAPI**'ฤฑn getirdiฤŸi bir kฤฑsฤฑtlama deฤŸildir, HTTP protokolรผnรผn bir parรงasฤฑdฤฑr. +Bu **FastAPI**'ฤฑn bir kฤฑsฤฑtlamasฤฑ deฤŸildir, HTTP protokolรผnรผn bir parรงasฤฑdฤฑr. /// -## ร–zet +## ร–zet { #recap } -Form verisi girdi parametreleri tanฤฑmlamak iรงin `Form` sฤฑnฤฑfฤฑnฤฑ kullanฤฑn. +Form verisi girdi parametrelerini tanฤฑmlamak iรงin `Form` kullanฤฑn. diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md index 4542aca773..d30b4389d0 100644 --- a/docs/tr/docs/tutorial/static-files.md +++ b/docs/tr/docs/tutorial/static-files.md @@ -1,40 +1,40 @@ -# Statik Dosyalar +# Statik Dosyalar { #static-files } -`StaticFiles`'ฤฑ kullanarak statik dosyalarฤฑ bir yol altฤฑnda sunabilirsiniz. +`StaticFiles` kullanarak bir dizindeki statik dosyalarฤฑ otomatik olarak sunabilirsiniz. -## `StaticFiles` Kullanฤฑmฤฑ +## `StaticFiles` Kullanฤฑmฤฑ { #use-staticfiles } -* `StaticFiles` sฤฑnฤฑfฤฑnฤฑ projenize dahil edin. -* Bir `StaticFiles()` รถrneฤŸini belirli bir yola baฤŸlayฤฑn. +* `StaticFiles`'ฤฑ import edin. +* Belirli bir path'te bir `StaticFiles()` รถrneฤŸini "mount" edin. -{* ../../docs_src/static_files/tutorial001.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} /// note | Teknik Detaylar -Projenize dahil etmek iรงin `from starlette.staticfiles import StaticFiles` kullanabilirsiniz. +`from starlette.staticfiles import StaticFiles` da kullanabilirsiniz. -**FastAPI**, geliลŸtiricilere kolaylฤฑk saฤŸlamak amacฤฑyla `starlette.staticfiles`'ฤฑ `fastapi.staticfiles` olarak saฤŸlar. Ancak `StaticFiles` sฤฑnฤฑfฤฑ aslฤฑnda doฤŸrudan Starlette'den gelir. +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.staticfiles`'ฤฑ `fastapi.staticfiles` olarak da saฤŸlar. Ancak aslฤฑnda doฤŸrudan Starlette'den gelir. /// -### BaฤŸlama (Mounting) Nedir? +### "Mounting" Nedir { #what-is-mounting } -"BaฤŸlamak", belirli bir yola tamamen "baฤŸฤฑmsฤฑz" bir uygulama eklemek anlamฤฑna gelir ve ardฤฑndan tรผm alt yollara gelen istekler bu uygulama tarafฤฑndan iลŸlenir. +"Mounting", belirli bir path'te tamamen "baฤŸฤฑmsฤฑz" bir uygulama eklemek ve sonrasฤฑnda tรผm alt path'leri handle etmesini saฤŸlamak demektir. -Bu, bir `APIRouter` kullanmaktan farklฤฑdฤฑr รงรผnkรผ baฤŸlanmฤฑลŸ bir uygulama tamamen baฤŸฤฑmsฤฑzdฤฑr. Ana uygulamanฤฑzฤฑn OpenAPI ve dokรผmanlar, baฤŸlanmฤฑลŸ uygulamadan hiรงbir ลŸey iรงermez, vb. +Bu, bir `APIRouter` kullanmaktan farklฤฑdฤฑr; รงรผnkรผ mount edilen uygulama tamamen baฤŸฤฑmsฤฑzdฤฑr. Ana uygulamanฤฑzฤฑn OpenAPI ve docs'larฤฑ, mount edilen uygulamadan hiรงbir ลŸey iรงermez, vb. -[Advanced User Guide](../advanced/index.md){.internal-link target=_blank} bรถlรผmรผnde daha fazla bilgi edinebilirsiniz. +Bununla ilgili daha fazla bilgiyi [Advanced User Guide](../advanced/index.md){.internal-link target=_blank} iรงinde okuyabilirsiniz. -## Detaylar +## Detaylar { #details } -`"/static"` ifadesi, bu "alt uygulamanฤฑn" "baฤŸlanacaฤŸฤฑ" alt yolu belirtir. Bu nedenle, `"/static"` ile baลŸlayan her yol, bu uygulama tarafฤฑndan iลŸlenir. +ฤฐlk `"/static"`, bu "alt uygulamanฤฑn" "mount" edileceฤŸi alt path'i ifade eder. Dolayฤฑsฤฑyla `"/static"` ile baลŸlayan herhangi bir path bunun tarafฤฑndan handle edilir. -`directory="static"` ifadesi, statik dosyalarฤฑnฤฑzฤฑ iรงeren dizinin adฤฑnฤฑ belirtir. +`directory="static"`, statik dosyalarฤฑnฤฑzฤฑ iรงeren dizinin adฤฑnฤฑ ifade eder. -`name="static"` ifadesi, alt uygulamanฤฑn **FastAPI** tarafฤฑndan kullanฤฑlacak ismini belirtir. +`name="static"`, **FastAPI**'nin dahili olarak kullanabileceฤŸi bir isim verir. -Bu parametrelerin hepsi "`static`"den farklฤฑ olabilir, bunlarฤฑ kendi uygulamanฤฑzฤฑn ihtiyaรงlarฤฑna gรถre belirleyebilirsiniz. +Bu parametrelerin hepsi "`static`" ile aynฤฑ olmak zorunda deฤŸildir; kendi uygulamanฤฑzฤฑn ihtiyaรงlarฤฑna ve รถzel detaylarฤฑna gรถre ayarlayฤฑn. -## Daha Fazla Bilgi +## Daha Fazla Bilgi { #more-info } -Daha fazla detay ve seรงenek iรงin Starlette'in Statik Dosyalar hakkฤฑndaki dokรผmantasyonunu incelleyin. +Daha fazla detay ve seรงenek iรงin Starlette'in Statik Dosyalar hakkฤฑndaki dokรผmanlarฤฑnฤฑ inceleyin. From 08924400c2c75533685148b029defcf6913f1def Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 31 Jan 2026 18:32:52 +0000 Subject: [PATCH 034/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 975bf774e9..eb72d559d0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -19,6 +19,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev). * ๐ŸŒ Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo). From df6530e0020f0b26951fff58b02d0a7e9ab834d3 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sun, 1 Feb 2026 12:44:39 +0300 Subject: [PATCH 035/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(update=20outdated,=20found=20by=20fixer=20tool)=20(?= =?UTF-8?q?#14739)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/alternatives.md | 80 ++++++++++---------- docs/uk/docs/fastapi-cli.md | 108 +++++++++++++-------------- docs/uk/docs/features.md | 138 +++++++++++++++++++---------------- 3 files changed, 166 insertions(+), 160 deletions(-) diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md index 786df45c50..d44ca794f8 100644 --- a/docs/uk/docs/alternatives.md +++ b/docs/uk/docs/alternatives.md @@ -1,8 +1,8 @@ -# ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ, ะฝะฐั‚ั…ะฝะตะฝะฝั ั‚ะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั +# ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ, ะฝะฐั‚ั…ะฝะตะฝะฝั ั‚ะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั { #alternatives-inspiration-and-comparisons } -ะฉะพ ะฝะฐะดะธั…ะฝัƒะปะพ ะฝะฐ ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**, ัะบะธะน ะฒั–ะฝ ัƒ ะฟะพั€ั–ะฝัะฝะฝั– ะท ั–ะฝัˆะธะผะธ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฐะผะธ ั‚ะฐ ั‡ะพะณะพ ะฒั–ะฝ ัƒ ะฝะธั… ะฝะฐะฒั‡ะธะฒัั. +ะฉะพ ะฝะฐะดะธั…ะฝัƒะปะพ **FastAPI**, ัะบ ะฒั–ะฝ ะฟะพั€ั–ะฒะฝัŽั”ั‚ัŒัั ะท ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฐะผะธ ั‚ะฐ ั‡ะพะณะพ ะฒั–ะฝ ัƒ ะฝะธั… ะฝะฐะฒั‡ะธะฒัั. -## ะ’ัั‚ัƒะฟ +## ะ’ัั‚ัƒะฟ { #intro } **FastAPI** ะฝะต ั–ัะฝัƒะฒะฐะปะพ ะฑ, ัะบะฑะธ ะฝะต ะฟะพะฟะตั€ะตะดะฝั– ั€ะพะฑะพั‚ะธ ั–ะฝัˆะธั…. @@ -12,17 +12,17 @@ ะะปะต ะฒ ัะบะธะนััŒ ะผะพะผะตะฝั‚ ะฝะต ะฑัƒะปะพ ั–ะฝัˆะพะณะพ ะฒะธั…ะพะดัƒ, ะพะบั€ั–ะผ ัั‚ะฒะพั€ะตะฝะฝั ั‡ะพะณะพััŒ, ั‰ะพ ะฝะฐะดะฐะฒะฐะปะพ ะฑ ัƒัั– ั†ั– ั„ัƒะฝะบั†ั–ั—, ะฒะทัะฒัˆะธ ะฝะฐะนะบั€ะฐั‰ั– ั–ะดะตั— ะท ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั– ะฟะพั”ะดะฝะฐะฒัˆะธ ั—ั… ะฝะฐะนะบั€ะฐั‰ะธะผ ั‡ะธะฝะพะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะพะฒะฝั– ั„ัƒะฝะบั†ั–ั—, ัะบั– ะฝะฐะฒั–ั‚ัŒ ะฝะต ะฑัƒะปะธ ะดะพัั‚ัƒะฟะฝั– ั€ะฐะฝั–ัˆะต (Python 3.6+ ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ). -## ะŸะพะฟะตั€ะตะดะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ +## ะŸะพะฟะตั€ะตะดะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ { #previous-tools } -### Django +### Django { #django } ะฆะต ะฝะฐะนะฟะพะฟัƒะปัั€ะฝั–ัˆะธะน ั„ั€ะตะนะผะฒะพั€ะบ Python, ัะบะธะน ะบะพั€ะธัั‚ัƒั”ั‚ัŒัั ัˆะธั€ะพะบะพัŽ ะดะพะฒั–ั€ะพัŽ. ะ’ั–ะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ั‚ะฐะบะธั… ัะธัั‚ะตะผ, ัะบ Instagram. ะ’ั–ะฝ ะฒั–ะดะฝะพัะฝะพ ั‚ั–ัะฝะพ ะฟะพะฒโ€™ัะทะฐะฝะธะน ะท ั€ะตะปัั†ั–ะนะฝะธะผะธ ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… (ะฝะฐะฟั€ะธะบะปะฐะด, MySQL ะฐะฑะพ PostgreSQL), ั‚ะพะผัƒ ะผะฐั‚ะธ ะฑะฐะทัƒ ะดะฐะฝะธั… NoSQL (ะฝะฐะฟั€ะธะบะปะฐะด, Couchbase, MongoDB, Cassandra ั‚ะพั‰ะพ) ัะบ ะพัะฝะพะฒะฝะธะน ะผะตั…ะฐะฝั–ะทะผ ะทะฑะตั€ั–ะณะฐะฝะฝั ะฝะต ะดัƒะถะต ะฟั€ะพัั‚ะพ. -ะ’ั–ะฝ ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ะดะปั ัั‚ะฒะพั€ะตะฝะฝั HTML ัƒ ัะตั€ะฒะตั€ะฝั–ะน ั‡ะฐัั‚ะธะฝั–, ะฐ ะฝะต ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ััƒั‡ะฐัะฝะธะผ ั–ะฝั‚ะตั€ั„ะตะนัะพะผ (ัะบ-ะพั‚ React, Vue.js ั– Angular) ะฐะฑะพ ั–ะฝัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ (ัะบ-ะพั‚ IoT ะฟั€ะธัั‚ั€ะพั—), ัะบั– ัะฟั–ะปะบัƒัŽั‚ัŒัั ะท ะฝะธะผ. +ะ’ั–ะฝ ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ะดะปั ัั‚ะฒะพั€ะตะฝะฝั HTML ัƒ ัะตั€ะฒะตั€ะฝั–ะน ั‡ะฐัั‚ะธะฝั–, ะฐ ะฝะต ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ััƒั‡ะฐัะฝะธะผ ั–ะฝั‚ะตั€ั„ะตะนัะพะผ (ัะบ-ะพั‚ React, Vue.js ั– Angular) ะฐะฑะพ ั–ะฝัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ (ัะบ-ะพั‚ IoT ะฟั€ะธัั‚ั€ะพั—), ัะบั– ัะฟั–ะปะบัƒัŽั‚ัŒัั ะท ะฝะธะผ. -### Django REST Framework +### Django REST Framework { #django-rest-framework } ะคั€ะตะนะผะฒะพั€ะบ Django REST ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ัะบ ะณะฝัƒั‡ะบะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐั€ั–ะน ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒะตะฑ-ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ API ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ Django ะฒ ะพัะฝะพะฒั–, ั‰ะพะฑ ะฟะพะบั€ะฐั‰ะธั‚ะธ ะนะพะณะพ ะผะพะถะปะธะฒะพัั‚ั– API. @@ -42,7 +42,7 @@ Django REST Framework ัั‚ะฒะพั€ะธะฒ ะขะพะผ ะšั€ั–ัั‚ั–. ะขะพะน ัะฐะผะธะน ั‚ะฒ /// -### Flask +### Flask { #flask } Flask โ€” ั†ะต ยซะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบยป, ะฒั–ะฝ ะฝะต ะฒะบะปัŽั‡ะฐั” ั–ะฝั‚ะตะณั€ะฐั†ั–ัŽ ะฑะฐะทะธ ะดะฐะฝะธั…, ะฐ ั‚ะฐะบะพะถ ะฑะฐะณะฐั‚ะพ ั€ะตั‡ะตะน, ัะบั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ั” ะฒ Django. @@ -64,7 +64,7 @@ Flask โ€” ั†ะต ยซะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบยป, ะฒั–ะฝ ะฝะต ะฒะบะปัŽั‡ะฐั” ั–ะฝ /// -### Requests +### Requests { #requests } **FastAPI** ะฝะฐัะฟั€ะฐะฒะดั– ะฝะต ั” ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะพัŽ **Requests**. ะกั„ะตั€ะฐ ั—ั… ะทะฐัั‚ะพััƒะฒะฐะฝะฝั ะดัƒะถะต ั€ั–ะทะฝะฐ. @@ -88,12 +88,12 @@ Requests ะผะฐัŽั‚ัŒ ะดัƒะถะต ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒ response = requests.get("http://example.com/some/url") ``` -ะ’ั–ะดะฟะพะฒั–ะดะฝะฐ ะพะฟะตั€ะฐั†ั–ั *ั€ะพัƒั‚ัƒ* API FastAPI ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: +ะ’ั–ะดะฟะพะฒั–ะดะฝะฐ ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ API FastAPI ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: ```Python hl_lines="1" @app.get("/some/url") def read_url(): - return {"message": "Hello World"} + return {"message": "Hello World"} ``` ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ ัั…ะพะถั–ัั‚ัŒ ัƒ `requests.get(...)` ั– `@app.get(...)`. @@ -101,12 +101,12 @@ def read_url(): /// check | ะะฐะดะธั…ะฝัƒะปะพ **FastAPI** ะฝะฐ * ะœะฐะนั‚ะต ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะน API. - * ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั–ะผะตะฝะฐ (ะพะฟะตั€ะฐั†ั–ั—) ะผะตั‚ะพะดั–ะฒ HTTP ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฟั€ะพัั‚ะธะผ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะผ ัะฟะพัะพะฑะพะผ. - * ะ ะพะทัƒะผะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฐะปะต ะฟะพั‚ัƒะถะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. +* ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั–ะผะตะฝะฐ (ะพะฟะตั€ะฐั†ั–ั—) ะผะตั‚ะพะดั–ะฒ HTTP ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฟั€ะพัั‚ะธะผ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะผ ัะฟะพัะพะฑะพะผ. +* ะ ะพะทัƒะผะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฐะปะต ะฟะพั‚ัƒะถะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } ะ“ะพะปะพะฒะฝะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ, ัะบัƒ ั ั…ะพั‚ั–ะฒ ะฒั–ะด Django REST Framework, ะฑัƒะปะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ API ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั. @@ -124,18 +124,18 @@ def read_url(): ะ†ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะฝะฐ ะพัะฝะพะฒั– ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ: - * ะ†ะฝั‚ะตั€ั„ะตะนั Swagger - * ReDoc +* ะ†ะฝั‚ะตั€ั„ะตะนั Swagger +* ReDoc ะฆั– ะดะฒะฐ ะฑัƒะปะพ ะพะฑั€ะฐะฝะพ ั‡ะตั€ะตะท ั‚ะต, ั‰ะพ ะฒะพะฝะธ ะดะพัะธั‚ัŒ ะฟะพะฟัƒะปัั€ะฝั– ั‚ะฐ ัั‚ะฐะฑั–ะปัŒะฝั–, ะฐะปะต, ะฒะธะบะพะฝะฐะฒัˆะธ ัˆะฒะธะดะบะธะน ะฟะพัˆัƒะบ, ะฒะธ ะผะพะถะตั‚ะต ะทะฝะฐะนั‚ะธ ะดะตััั‚ะบะธ ะดะพะดะฐั‚ะบะพะฒะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะดะปั OpenAPI (ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท **FastAPI**). /// -### ะคั€ะตะนะผะฒะพั€ะบะธ REST ะดะปั Flask +### ะคั€ะตะนะผะฒะพั€ะบะธ REST ะดะปั Flask { #flask-rest-frameworks } ะ†ัะฝัƒั” ะบั–ะปัŒะบะฐ ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ Flask REST, ะฐะปะต, ะฒะธั‚ั€ะฐั‚ะธะฒัˆะธ ั‡ะฐั ั– ั€ะพะฑะพั‚ัƒ ะฝะฐ ั—ั… ะดะพัะปั–ะดะถะตะฝะฝั, ั ะฒะธัะฒะธะฒ, ั‰ะพ ะฑะฐะณะฐั‚ะพ ะท ะฝะธั… ะฟั€ะธะฟะธะฝะตะฝะพ ะฐะฑะพ ะทะฐะปะธัˆะตะฝะพ, ะท ะบั–ะปัŒะบะพะผะฐ ะฟะพัั‚ั–ะนะฝะธะผะธ ะฟั€ะพะฑะปะตะผะฐะผะธ, ัะบั– ะทั€ะพะฑะธะปะธ ั—ั… ะฝะตะฟั€ะธะดะฐั‚ะฝะธะผะธ. -### Marshmallow +### Marshmallow { #marshmallow } ะžะดะฝั–ั”ัŽ ะท ะณะพะปะพะฒะฝะธั… ั„ัƒะฝะบั†ั–ะน, ะฝะตะพะฑั…ั–ะดะฝะธั… ะดะปั ัะธัั‚ะตะผ API, ั” "ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั", ัะบะฐ ะฑะตั€ะต ะดะฐะฝั– ะท ะบะพะดัƒ (Python) ั– ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั—ั… ะฝะฐ ั‰ะพััŒ, ั‰ะพ ะผะพะถะฝะฐ ะฝะฐะดั–ัะปะฐั‚ะธ ั‡ะตั€ะตะท ะผะตั€ะตะถัƒ. ะะฐะฟั€ะธะบะปะฐะด, ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ะฐ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะดะฐะฝั– ะท ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะฐ ะพะฑโ€™ั”ะบั‚ JSON. ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ั–ะฒ `datetime` ะฝะฐ ัั‚ั€ะพะบะธ ั‚ะพั‰ะพ. @@ -153,7 +153,7 @@ Marshmallow ัั‚ะฒะพั€ะตะฝะพ ะดะปั ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั ั†ะธั… ั„ัƒะฝะบั†ั– /// -### Webargs +### Webargs { #webargs } ะ†ะฝัˆะพัŽ ะฒะฐะถะปะธะฒะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ, ะฝะตะพะฑั…ั–ะดะฝะพัŽ ะดะปั API, ั” ะฐะฝะฐะปั–ะท ะดะฐะฝะธั… ั–ะท ะฒั…ั–ะดะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. @@ -175,7 +175,7 @@ Webargs ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Marshmall /// -### APISpec +### APISpec { #apispec } Marshmallow ั– Webargs ะทะฐะฑะตะทะฟะตั‡ัƒัŽั‚ัŒ ะฟะตั€ะตะฒั–ั€ะบัƒ, ะฐะฝะฐะปั–ะท ั– ัะตั€ั–ะฐะปั–ะทะฐั†ั–ัŽ ัะบ ะฟะปะฐะณั–ะฝะธ. @@ -205,7 +205,7 @@ APISpec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Marshmall /// -### Flask-apispec +### Flask-apispec { #flask-apispec } ะฆะต ะฟะปะฐะณั–ะฝ Flask, ัะบะธะน ะพะฑโ€™ั”ะดะฝัƒั” Webargs, Marshmallow ั– APISpec. @@ -237,13 +237,13 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar /// -### NestJS (ั‚ะฐ Angular) +### NestJS (ั‚ะฐ Angular) { #nestjs-and-angular } ะฆะต ะฝะฐะฒั–ั‚ัŒ ะฝะต Python, NestJS โ€” ั†ะต ั„ั€ะตะนะผะฒะพั€ะบ NodeJS JavaScript (TypeScript), ะฝะฐั‚ั…ะฝะตะฝะฝะธะน Angular. ะฆะต ะดะพััะณะฐั” ั‡ะพะณะพััŒ ะฟะพะดั–ะฑะฝะพะณะพ ะดะพ ั‚ะพะณะพ, ั‰ะพ ะผะพะถะฝะฐ ะทั€ะพะฑะธั‚ะธ ะท Flask-apispec. -ะ’ั–ะฝ ะผะฐั” ั–ะฝั‚ะตะณั€ะพะฒะฐะฝัƒ ัะธัั‚ะตะผัƒ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน, ะฝะฐั‚ั…ะฝะตะฝะฝัƒ Angular two. ะ’ั–ะฝ ะฟะพั‚ั€ะตะฑัƒั” ะฟะพะฟะตั€ะตะดะฝัŒะพั— ั€ะตั”ัั‚ั€ะฐั†ั–ั— ยซinjectablesยป (ัะบ ั– ะฒัั– ั–ะฝัˆั– ัะธัั‚ะตะผะธ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน, ัะบั– ั ะทะฝะฐัŽ), ั‚ะพะผัƒ ั†ะต ะทะฑั–ะปัŒัˆัƒั” ะฑะฐะณะฐั‚ะพัะปั–ะฒะฝั–ัั‚ัŒ ั‚ะฐ ะฟะพะฒั‚ะพั€ะตะฝะฝั ะบะพะดัƒ. +ะ’ั–ะฝ ะผะฐั” ั–ะฝั‚ะตะณั€ะพะฒะฐะฝัƒ ัะธัั‚ะตะผัƒ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน, ะฝะฐั‚ั…ะฝะตะฝะฝัƒ Angular 2. ะ’ั–ะฝ ะฟะพั‚ั€ะตะฑัƒั” ะฟะพะฟะตั€ะตะดะฝัŒะพั— ั€ะตั”ัั‚ั€ะฐั†ั–ั— ยซinjectablesยป (ัะบ ั– ะฒัั– ั–ะฝัˆั– ัะธัั‚ะตะผะธ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน, ัะบั– ั ะทะฝะฐัŽ), ั‚ะพะผัƒ ั†ะต ะทะฑั–ะปัŒัˆัƒั” ะฑะฐะณะฐั‚ะพัะปั–ะฒะฝั–ัั‚ัŒ ั‚ะฐ ะฟะพะฒั‚ะพั€ะตะฝะฝั ะบะพะดัƒ. ะžัะบั–ะปัŒะบะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะพะฟะธัะฐะฝั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะธะฟั–ะฒ TypeScript (ะฟะพะดั–ะฑะฝะพ ะดะพ ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python), ะฟั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะดะพัะธั‚ัŒ ั…ะพั€ะพัˆะฐ. @@ -259,7 +259,7 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar /// -### Sanic +### Sanic { #sanic } ะฆะต ะฑัƒะฒ ะพะดะธะฝ ั–ะท ะฟะตั€ัˆะธั… ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ัˆะฒะธะดะบะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ Python ะฝะฐ ะพัะฝะพะฒั– `asyncio`. ะ’ั–ะฝ ะฑัƒะฒ ะดัƒะถะต ัั…ะพะถะธะน ะฝะฐ Flask. @@ -279,7 +279,7 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar /// -### Falcon +### Falcon { #falcon } Falcon โ€” ั‰ะต ะพะดะธะฝ ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ั„ั€ะตะนะผะฒะพั€ะบ Python, ะฒั–ะฝ ั€ะพะทั€ะพะฑะปะตะฝะธะน ัะบ ะผั–ะฝั–ะผะฐะปัŒะฝะธะน ั– ะฟั€ะฐั†ัŽั” ัะบ ะพัะฝะพะฒะฐ ั–ะฝัˆะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ, ั‚ะฐะบะธั… ัะบ Hug. @@ -297,7 +297,7 @@ Falcon โ€” ั‰ะต ะพะดะธะฝ ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ั„ั€ะตะนะผะฒะพั€ะบ /// -### Molten +### Molten { #molten } ะฏ ะฒั–ะดะบั€ะธะฒ ะดะปั ัะตะฑะต Molten ะฝะฐ ะฟะตั€ัˆะธั… ะตั‚ะฐะฟะฐั… ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. ะ† ะฒั–ะฝ ะผะฐั” ะดะพัะธั‚ัŒ ัั…ะพะถั– ั–ะดะตั—: @@ -321,7 +321,7 @@ Falcon โ€” ั‰ะต ะพะดะธะฝ ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ั„ั€ะตะนะผะฒะพั€ะบ /// -### Hug +### Hug { #hug } Hug ะฑัƒะฒ ะพะดะฝะธะผ ั–ะท ะฟะตั€ัˆะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ, ัะบะธะน ั€ะตะฐะปั–ะทัƒะฒะฐะฒ ะพะณะพะปะพัˆะตะฝะฝั ั‚ะธะฟั–ะฒ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python. ะฆะต ะฑัƒะปะฐ ั‡ัƒะดะพะฒะฐ ั–ะดะตั, ัะบะฐ ะฝะฐะดะธั…ะฝัƒะปะฐ ั–ะฝัˆั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะทั€ะพะฑะธั‚ะธ ั‚ะต ัะฐะผะต. @@ -351,7 +351,7 @@ Hug ะฝะฐะดะธั…ะฝัƒะฒ ั‡ะฐัั‚ะธะฝัƒ APIStar ั– ะฑัƒะฒ ะพะดะฝะธะผ ั–ะท ะฝะฐะนะฑั– /// -### APIStar (<= 0,5) +### APIStar (<= 0,5) { #apistar-0-5 } ะ‘ะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะฒะธั€ั–ัˆะธั‚ะธ ัั‚ะฒะพั€ะธั‚ะธ **FastAPI**, ั ะทะฝะฐะนัˆะพะฒ ัะตั€ะฒะตั€ **APIStar**. ะ’ั–ะฝ ะผะฐะฒ ะผะฐะนะถะต ะฒัะต, ั‰ะพ ั ัˆัƒะบะฐะฒ, ั– ะผะฐะฒ ั‡ัƒะดะพะฒะธะน ะดะธะทะฐะนะฝ. @@ -379,9 +379,9 @@ Hug ะฝะฐะดะธั…ะฝัƒะฒ ั‡ะฐัั‚ะธะฝัƒ APIStar ั– ะฑัƒะฒ ะพะดะฝะธะผ ั–ะท ะฝะฐะนะฑั– APIStar ัั‚ะฒะพั€ะธะฒ ะขะพะผ ะšั€ั–ัั‚ั–. ะขะพะน ัะฐะผะธะน ั…ะปะพะฟะตั†ัŒ, ัะบะธะน ัั‚ะฒะพั€ะธะฒ: - * Django REST Framework - * Starlette (ะฝะฐ ัะบะพะผัƒ ะฑะฐะทัƒั”ั‚ัŒัั **FastAPI**) - * Uvicorn (ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Starlette ั– **FastAPI**) +* Django REST Framework +* Starlette (ะฝะฐ ัะบะพะผัƒ ะฑะฐะทัƒั”ั‚ัŒัั **FastAPI**) +* Uvicorn (ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Starlette ั– **FastAPI**) /// @@ -393,13 +393,15 @@ APIStar ัั‚ะฒะพั€ะธะฒ ะขะพะผ ะšั€ั–ัั‚ั–. ะขะพะน ัะฐะผะธะน ั…ะปะพะฟะตั†ัŒ, ั ะ† ะฟั–ัะปั ั‚ั€ะธะฒะฐะปะพะณะพ ะฟะพัˆัƒะบัƒ ะฟะพะดั–ะฑะฝะพั— ัั‚ั€ัƒะบั‚ัƒั€ะธ ั‚ะฐ ั‚ะตัั‚ัƒะฒะฐะฝะฝั ะฑะฐะณะฐั‚ัŒะพั… ั€ั–ะทะฝะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, APIStar ัั‚ะฐะฒ ะฝะฐะนะบั€ะฐั‰ะธะผ ะดะพัั‚ัƒะฟะฝะธะผ ะฒะฐั€ั–ะฐะฝั‚ะพะผ. - ะŸะพั‚ั–ะผ APIStar ะฟะตั€ะตัั‚ะฐะฒ ั–ัะฝัƒะฒะฐั‚ะธ ัะบ ัะตั€ะฒะตั€, ั– ะฑัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ Starlette, ัะบะธะน ัั‚ะฐะฒ ะฝะพะฒะพัŽ ะบั€ะฐั‰ะพัŽ ะพัะฝะพะฒะพัŽ ะดะปั ั‚ะฐะบะพั— ัะธัั‚ะตะผะธ. ะฆะต ัั‚ะฐะปะพ ะพัั‚ะฐะฝะฝั–ะผ ะดะถะตั€ะตะปะพะผ ะฝะฐั‚ั…ะฝะตะฝะฝั ะดะปั ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. ะฏ ะฒะฒะฐะถะฐัŽ **FastAPI** ยซะดัƒั…ะพะฒะฝะธะผ ัะฟะฐะดะบะพั”ะผั†ะตะผยป APIStar, ัƒะดะพัะบะพะฝะฐะปัŽัŽั‡ะธ ั‚ะฐ ั€ะพะทัˆะธั€ัŽัŽั‡ะธ ั„ัƒะฝะบั†ั–ั—, ัะธัั‚ะตะผัƒ ะฒะฒะตะดะตะฝะฝั ั‚ะตะบัั‚ัƒ ั‚ะฐ ั–ะฝัˆั– ั‡ะฐัั‚ะธะฝะธ ะฝะฐ ะพัะฝะพะฒั– ะดะพัะฒั–ะดัƒ, ะพั‚ั€ะธะผะฐะฝะพะณะพ ะฒั–ะด ัƒัั–ั… ั†ะธั… ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. + ะŸะพั‚ั–ะผ APIStar ะฟะตั€ะตัั‚ะฐะฒ ั–ัะฝัƒะฒะฐั‚ะธ ัะบ ัะตั€ะฒะตั€, ั– ะฑัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ Starlette, ัะบะธะน ัั‚ะฐะฒ ะฝะพะฒะพัŽ ะบั€ะฐั‰ะพัŽ ะพัะฝะพะฒะพัŽ ะดะปั ั‚ะฐะบะพั— ัะธัั‚ะตะผะธ. ะฆะต ัั‚ะฐะปะพ ะพัั‚ะฐะฝะฝั–ะผ ะดะถะตั€ะตะปะพะผ ะฝะฐั‚ั…ะฝะตะฝะฝั ะดะปั ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. + + ะฏ ะฒะฒะฐะถะฐัŽ **FastAPI** ยซะดัƒั…ะพะฒะฝะธะผ ัะฟะฐะดะบะพั”ะผั†ะตะผยป APIStar, ัƒะดะพัะบะพะฝะฐะปัŽัŽั‡ะธ ั‚ะฐ ั€ะพะทัˆะธั€ัŽัŽั‡ะธ ั„ัƒะฝะบั†ั–ั—, ัะธัั‚ะตะผัƒ ั‚ะธะฟั–ะทะฐั†ั–ั— ั‚ะฐ ั–ะฝัˆั– ั‡ะฐัั‚ะธะฝะธ ะฝะฐ ะพัะฝะพะฒั– ะดะพัะฒั–ะดัƒ, ะพั‚ั€ะธะผะฐะฝะพะณะพ ะฒั–ะด ัƒัั–ั… ั†ะธั… ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. /// -## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั **FastAPI** +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั **FastAPI** { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } Pydantic โ€” ั†ะต ะฑั–ะฑะปั–ะพั‚ะตะบะฐ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ัั…ะตะผะธ JSON) ะฝะฐ ะพัะฝะพะฒั– ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python. @@ -415,9 +417,9 @@ Pydantic โ€” ั†ะต ะฑั–ะฑะปั–ะพั‚ะตะบะฐ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะฒั– /// -### Starlette +### Starlette { #starlette } -Starlette โ€” ั†ะต ะปะตะณะบะธะน ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑั–ั€ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ASGI, ัะบะธะน ั–ะดะตะฐะปัŒะฝะพ ะฟั–ะดั…ะพะดะธั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธั… asyncio ัะตั€ะฒั–ัั–ะฒ. +Starlette โ€” ั†ะต ะปะตะณะบะธะน ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑั–ั€ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ASGI, ัะบะธะน ั–ะดะตะฐะปัŒะฝะพ ะฟั–ะดั…ะพะดะธั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธั… asyncio ัะตั€ะฒั–ัั–ะฒ. ะ’ั–ะฝ ะดัƒะถะต ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะน. ะ™ะพะณะพ ั€ะพะทั€ะพะฑะปะตะฝะพ ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ, ั‰ะพะฑ ะนะพะณะพ ะผะพะถะฝะฐ ะฑัƒะปะพ ะปะตะณะบะพ ั€ะพะทัˆะธั€ัŽะฒะฐั‚ะธ ั‚ะฐ ะผะฐั‚ะธ ะผะพะดัƒะปัŒะฝั– ะบะพะผะฟะพะฝะตะฝั‚ะธ. @@ -460,7 +462,7 @@ ASGI โ€” ั†ะต ะฝะพะฒะธะน ยซัั‚ะฐะฝะดะฐั€ั‚ยป, ัะบะธะน ั€ะพะทั€ะพะฑะปัั”ั‚ัŒั /// -### Uvicorn +### Uvicorn { #uvicorn } Uvicorn โ€” ั†ะต ะฑะปะธัะบะฐะฒะธั‡ะฝะธะน ัะตั€ะฒะตั€ ASGI, ะฟะพะฑัƒะดะพะฒะฐะฝะธะน ะฝะฐ uvloop ั– httptools. @@ -472,12 +474,12 @@ Uvicorn โ€” ั†ะต ะฑะปะธัะบะฐะฒะธั‡ะฝะธะน ัะตั€ะฒะตั€ ASGI, ะฟะพะฑัƒะดะพะฒะฐะฝ ะžัะฝะพะฒะฝะธะน ะฒะตะฑ-ัะตั€ะฒะตั€ ะดะปั ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผ **FastAPI**. - ะ’ะธ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝะฐั‚ะธ ะนะพะณะพ ะท Gunicorn, ั‰ะพะฑ ะผะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะฝะธะน ัะตั€ะฒะตั€. + ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`, ั‰ะพะฑ ะผะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะฝะธะน ัะตั€ะฒะตั€. ะ”ะพะดะฐั‚ะบะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะดะธะฒ. ัƒ ั€ะพะทะดั–ะปั– [ะ ะพะทะณะพั€ั‚ะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. /// -## ะžั€ั–ั”ะฝั‚ะธั€ะธ ั‚ะฐ ัˆะฒะธะดะบั–ัั‚ัŒ +## ะžั€ั–ั”ะฝั‚ะธั€ะธ ั‚ะฐ ัˆะฒะธะดะบั–ัั‚ัŒ { #benchmarks-and-speed } ะฉะพะฑ ะทั€ะพะทัƒะผั–ั‚ะธ, ะฟะพั€ั–ะฒะฝัั‚ะธ ั‚ะฐ ะฟะพะฑะฐั‡ะธั‚ะธ ั€ั–ะทะฝะธั†ัŽ ะผั–ะถ Uvicorn, Starlette ั– FastAPI, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ั€ะพะทะดั–ะป ะฟั€ะพ [ะ‘ะตะฝั‡ะผะฐั€ะบะธ](benchmarks.md){.internal-link target=_blank}. diff --git a/docs/uk/docs/fastapi-cli.md b/docs/uk/docs/fastapi-cli.md index f18b104718..eb55382302 100644 --- a/docs/uk/docs/fastapi-cli.md +++ b/docs/uk/docs/fastapi-cli.md @@ -1,83 +1,75 @@ -# FastAPI CLI +# FastAPI CLI { #fastapi-cli } -**FastAPI CLI** ั†ะต ะฟั€ะพะณั€ะฐะผะฐ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ, ัะบัƒ ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ั‰ะพะฑ ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะ’ะฐัˆ ะดะพะดะฐั‚ะพะบ FastAPI, ะบะตั€ัƒะฒะฐั‚ะธ ะ’ะฐัˆะธะผะธ FastApi ะฟั€ะพะตะบั‚ะฐะผะธ, ั‚ะพั‰ะพ. +**FastAPI CLI** โ€” ั†ะต ะฟั€ะพะณั€ะฐะผะฐ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ, ัะบัƒ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ั‰ะพะฑ ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI, ะบะตั€ัƒะฒะฐั‚ะธ ะฒะฐัˆะธะผ ะฟั€ะพั”ะบั‚ะพะผ FastAPI ั‚ะพั‰ะพ. -ะšะพะปะธ ะ’ะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต FastApi (ั‚ะพะฑั‚ะพ ะฒะธะบะพะฝัƒั”ั‚ะต `pip install "fastapi[standard]"`), ะ’ะธ ั‚ะฐะบะพะถ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะฟะฐะบัƒะฝะพะบ `fastapi-cli`, ั†ะตะน ะฟะฐะบัƒะฝะพะบ ะฝะฐะดะฐั” ะบะพะผะฐะฝะดัƒ `fastapi` ะฒ ั‚ะตั€ะผั–ะฝะฐะปั–. +ะšะพะปะธ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต FastAPI (ะฝะฐะฟั€ะธะบะปะฐะด, ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `pip install "fastapi[standard]"`), ะฒั–ะฝ ะฒะบะปัŽั‡ะฐั” ะฟะฐะบะตั‚ ะฟั–ะด ะฝะฐะทะฒะพัŽ `fastapi-cli`, ั†ะตะน ะฟะฐะบะตั‚ ะฝะฐะดะฐั” ะบะพะผะฐะฝะดัƒ `fastapi` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–. -ะ”ะปั ะทะฐะฟัƒัะบัƒ ะ’ะฐัˆะพะณะพ FastAPI ะฟั€ะพะตะบั‚ัƒ ะดะปั ั€ะพะทั€ะพะฑะบะธ, ะ’ะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธััŒ ะบะพะผะฐะฝะดะพัŽ `fastapi dev`: +ะฉะพะฑ ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ะดะปั ั€ะพะทั€ะพะฑะบะธ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะผะฐะฝะดัƒ `fastapi dev`:
```console -$ fastapi dev main.py -INFO Using path main.py -INFO Resolved absolute path /home/user/code/awesomeapp/main.py -INFO Searching for package file structure from directories with __init__.py files -INFO Importing from /home/user/code/awesomeapp - - โ•ญโ”€ Python module file โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ ๐Ÿ main.py โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Importing module main -INFO Found importable FastAPI app - - โ•ญโ”€ Importable FastAPI app โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ from main import app โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Using import string main:app - - โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ - โ”‚ โ”‚ - โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ - โ”‚ โ”‚ - โ”‚ Running in development mode, for production use: โ”‚ - โ”‚ โ”‚ - โ”‚ fastapi run โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2265862] using WatchFiles -INFO: Started server process [2265873] -INFO: Waiting for application startup. -INFO: Application startup complete. +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-ะŸั€ะพะณั€ะฐะผะฐ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `fastapi` ั†ะต **FastAPI CLI**. +ะŸั€ะพะณั€ะฐะผะฐ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ ะฟั–ะด ะฝะฐะทะฒะพัŽ `fastapi` โ€” ั†ะต **FastAPI CLI**. -FastAPI CLI ะฟั€ะธะนะผะฐั” ัˆะปัั… ะดะพ ะ’ะฐัˆะพั— Python ะฟั€ะพะณั€ะฐะผะธ (ะฝะฐะฟั€. `main.py`) ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฒะธัะฒะปัั” ะตะบะทะตะผะฟะปัั€ `FastAPI` (ะทะฐะทะฒะธั‡ะฐะน ะฝะฐะทะฒะฐะฝะธะน `app`), ะพะฑะธั€ะฐั” ะบะพั€ะตะบั‚ะฝะธะน ะฟั€ะพั†ะตั ั–ะผะฟะพั€ั‚ัƒ, ะฐ ะฟะพั‚ั–ะผ ะพะฑัะปัƒะณะพะฒัƒั” ะนะพะณะพ. +FastAPI CLI ะฑะตั€ะต ัˆะปัั… ะดะพ ะฒะฐัˆะพั— Python-ะฟั€ะพะณั€ะฐะผะธ (ะฝะฐะฟั€ะธะบะปะฐะด, `main.py`) ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฒะธัะฒะปัั” ะตะบะทะตะผะฟะปัั€ `FastAPI` (ะทะฐะทะฒะธั‡ะฐะน ะท ะฝะฐะทะฒะพัŽ `app`), ะฒะธะทะฝะฐั‡ะฐั” ะฟั€ะฐะฒะธะปัŒะฝะธะน ะฟั€ะพั†ะตั ั–ะผะฟะพั€ั‚ัƒ, ะฐ ะฟะพั‚ั–ะผ ะพะฑัะปัƒะณะพะฒัƒั” ะนะพะณะพ. -ะะฐั‚ะพะผั–ัั‚ัŒ, ะดะปั ะทะฐะฟัƒัะบัƒ ัƒ ะฟั€ะพะดะฐะบัˆะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `fastapi run`. ๐Ÿš€ +ะะฐั‚ะพะผั–ัั‚ัŒ, ะดะปั ะฟั€ะพะดะฐะบัˆะฝ ะฒะธ ะฒะธะบะพั€ะธัั‚ะฐะปะธ ะฑ `fastapi run`. ๐Ÿš€ -ะ’ัะตั€ะตะดะธะฝั– **FastAPI CLI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn, ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน, production-ready, ASGI cะตั€ะฒะตั€. ๐Ÿ˜Ž +ะ’ะฝัƒั‚ั€ั–ัˆะฝัŒะพ **FastAPI CLI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn, ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน, production-ready, ASGI ัะตั€ะฒะตั€. ๐Ÿ˜Ž -## `fastapi dev` +## `fastapi dev` { #fastapi-dev } -ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `fastapi dev` ั–ะฝั–ั†ั–ัŽั” ั€ะตะถะธะผ ั€ะพะทั€ะพะฑะบะธ. +ะ—ะฐะฟัƒัะบ `fastapi dev` ั–ะฝั–ั†ั–ัŽั” ั€ะตะถะธะผ ั€ะพะทั€ะพะฑะบะธ. -ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั** ัƒะฒั–ะผะบะฝะตะฝะต, ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถัƒัŽั‡ะธ ัะตั€ะฒะตั€ ะบะพะถะฝะพะณะพ ั€ะฐะทัƒ, ะบะพะปะธ ะ’ะธ ะทะผั–ะฝัŽั”ั‚ะต ะ’ะฐัˆ ะบะพะด. ะฆะต ั€ะตััƒั€ัะพ-ะทะฐั‚ั€ะฐั‚ะฝะพ, ั‚ะฐ ะผะพะถะต ะฑัƒั‚ะธ ะผะตะฝัˆ ัั‚ะฐะฑั–ะปัŒะฝะธะผ, ะฝั–ะถ ะบะพะปะธ ะฒะพะฝะพ ะฒะธะผะบะฝะตะฝะต. ะ’ะธ ะฟะพะฒะธะฝะฝั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ั‚ั–ะปัŒะบะธ ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ. ะ’ะพะฝะพ ั‚ะฐะบะพะถ ัะปัƒั…ะฐั” IP-ะฐะดั€ะตััƒ `127.0.0.1`, ั‰ะพ ั” IP ะ’ะฐัˆะพะณะพ ะดะตะฒะฐะนััƒ ะดะปั ัะฐะผะพัั‚ั–ะนะฝะพั— ะบะพะผัƒะฝั–ะบะฐั†ั–ั— ะท ัะฐะผะธะผ ัะพะฑะพัŽ (`localhost`). +ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ **auto-reload** ัƒะฒั–ะผะบะฝะตะฝะพ, ั– ัะตั€ะฒะตั€ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถัƒั”ั‚ัŒัั, ะบะพะปะธ ะฒะธ ะฒะฝะพัะธั‚ะต ะทะผั–ะฝะธ ัƒ ะฒะฐัˆ ะบะพะด. ะฆะต ั€ะตััƒั€ัะพั”ะผะฝะพ ั‚ะฐ ะผะพะถะต ะฑัƒั‚ะธ ะผะตะฝัˆ ัั‚ะฐะฑั–ะปัŒะฝะธะผ, ะฝั–ะถ ะบะพะปะธ ะนะพะณะพ ะฒะธะผะบะฝะตะฝะพ. ะ’ะฐะผ ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ะต ะปะธัˆะต ะดะปั ั€ะพะทั€ะพะฑะบะธ. ะขะฐะบะพะถ ะฒั–ะฝ ัะปัƒั…ะฐั” IP-ะฐะดั€ะตััƒ `127.0.0.1`, ัะบะฐ ั” IP-ะฐะดั€ะตัะพัŽ ะดะปั ั‚ะพะณะพ, ั‰ะพะฑ ะฒะฐัˆะฐ ะผะฐัˆะธะฝะฐ ะผะพะณะปะฐ ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะปะธัˆะต ัะฐะผะฐ ะท ัะพะฑะพัŽ (`localhost`). -## `fastapi run` +## `fastapi run` { #fastapi-run } -ะ’ะธะบะพะฝะฐะฝะฝั `fastapi run` ะทะฐะฟัƒัั‚ะธั‚ัŒ FastAPI ัƒ ะฟั€ะพะดะฐะบัˆะฝ-ั€ะตะถะธะผั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +ะ’ะธะบะพะฝะฐะฝะฝั `fastapi run` ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะทะฐะฟัƒัะบะฐั” FastAPI ัƒ ะฟั€ะพะดะฐะบัˆะฝ-ั€ะตะถะธะผั–. -ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั** ะฒะธะผะบะฝะตะฝะต. ะ’ะพะฝะพ ั‚ะฐะบะพะถ ะฟั€ะพัะปัƒั…ะพะฒัƒั” IP-ะฐะดั€ะตััƒ `0.0.0.0`, ั‰ะพ ะพะทะฝะฐั‡ะฐั” ะฒัั– ะดะพัั‚ัƒะฟะฝั– IP ะฐะดั€ะตัะธ, ั‚ะธะผ ัะฐะผะธะผ ะดะฐัŽั‡ะธ ะทะผะพะณัƒ ะฑัƒะดัŒ-ะบะพะผัƒ ะบะพะผัƒะฝั–ะบัƒะฒะฐั‚ะธ ะท ะดะตะฒะฐะนัะพะผ. ะขะฐะบ ะ’ะธ ะทะฐะทะฒะธั‡ะฐะน ะฑัƒะดะตั‚ะต ะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ัƒ ะฟั€ะพะดะฐะบัˆะฝ, ะฝะฐะฟั€ะธะบะปะฐะด ัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–. +ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ **auto-reload** ะฒะธะผะบะฝะตะฝะพ. ะขะฐะบะพะถ ะฒั–ะฝ ัะปัƒั…ะฐั” IP-ะฐะดั€ะตััƒ `0.0.0.0`, ั‰ะพ ะพะทะฝะฐั‡ะฐั” ะฒัั– ะดะพัั‚ัƒะฟะฝั– IP-ะฐะดั€ะตัะธ, ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ ะฒั–ะฝ ะฑัƒะดะต ะฟัƒะฑะปั–ั‡ะฝะพ ะดะพัั‚ัƒะฟะฝะธะผ ะดะปั ะฑัƒะดัŒ-ะบะพะณะพ, ั…ั‚ะพ ะผะพะถะต ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะผะฐัˆะธะฝะพัŽ. ะ—ะฐะทะฒะธั‡ะฐะน ัะฐะผะต ั‚ะฐะบ ะฒะธ ะทะฐะฟัƒัะบะฐั‚ะธะผะตั‚ะต ะนะพะณะพ ะฒ ะฟั€ะพะดะฐะบัˆะฝ, ะฝะฐะฟั€ะธะบะปะฐะด ัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–. -ะ’ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะ’ะธ ะผะพะถะตั‚ะต (ั– ะผะฐั”ั‚ะต) ะผะฐั‚ะธ "termination proxy", ัะบะธะน ะพะฑั€ะพะฑะปัั” HTTPS ะดะปั ะ’ะฐั, ั†ะต ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด ัะฟะพัะพะฑัƒ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะฒะฐัˆะพะณะพ ะดะพะดะฐั‚ะบัƒ, ะ’ะฐัˆ ะฟั€ะพะฒะฐะนะดะตั€ ะผะพะถะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะดะปั ะ’ะฐั, ะฐะฑะพ ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ัะฐะผะพัั‚ั–ะนะฝะพ. +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ (ั– ะฒะฐะผ ัะปั–ะด) ะผะฐั‚ะธะผะตั‚ะต ยซtermination proxyยป, ัะบะธะน ะพะฑั€ะพะฑะปัั” HTTPS ะดะปั ะฒะฐั ะทะฒะตั€ั…ัƒ; ั†ะต ะทะฐะปะตะถะฐั‚ะธะผะต ะฒั–ะด ั‚ะพะณะพ, ัะบ ะฒะธ ั€ะพะทะณะพั€ั‚ะฐั”ั‚ะต ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ: ะฒะฐัˆ ะฟั€ะพะฒะฐะนะดะตั€ ะผะพะถะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะทะฐ ะฒะฐั, ะฐะฑะพ ะฒะฐะผ ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั†ะต ัะฐะผะพัั‚ั–ะนะฝะพ. -/// tip +/// tip | ะŸะพั€ะฐะดะฐ -ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธััŒ ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ะต ัƒ [ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะพ ั€ะพะทะณะพั€ั‚ัƒะฒะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ะต ะฒ [ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะท ั€ะพะทะณะพั€ั‚ะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. /// diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md index aa0ef7c79d..d8233115fd 100644 --- a/docs/uk/docs/features.md +++ b/docs/uk/docs/features.md @@ -1,21 +1,21 @@ -# ะคัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั– ะผะพะถะปะธะฒะพัั‚ั– +# ะคัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั– ะผะพะถะปะธะฒะพัั‚ั– { #features } -## ะคัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั– ะผะพะถะปะธะฒะพัั‚ั– FastAPI +## ะคัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั– ะผะพะถะปะธะฒะพัั‚ั– FastAPI { #fastapi-features } **FastAPI** ะฝะฐะดะฐั” ะฒะฐะผ ั‚ะฐะบั– ะผะพะถะปะธะฒะพัั‚ั–: -### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒั–ะดะบั€ะธั‚ะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ +### ะะฐ ะพัะฝะพะฒั– ะฒั–ะดะบั€ะธั‚ะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ { #based-on-open-standards } * OpenAPI ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ะฒะบะปัŽั‡ะฐัŽั‡ะธ ะพะณะพะปะพัˆะตะฝะฝั ัˆะปัั…ั–ะฒ, ะพะฟะตั€ะฐั†ั–ะน, ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ, ะฑะตะทะฟะตะบะธ ั‚ะพั‰ะพ. * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะผะพะดะตะปะตะน ะดะฐะฝะธั… ะทะฐ ะดะพะฟะพะผะพะณะพัŽ JSON Schema (ะพัะบั–ะปัŒะบะธ OpenAPI ะฑะฐะทัƒั”ั‚ัŒัั ัะฐะผะต ะฝะฐ JSON Schema). * ะ ะพะทั€ะพะฑะปะตะฝะพ ะฝะฐ ะพัะฝะพะฒั– ั†ะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ ะฟั–ัะปั ั€ะตั‚ะตะปัŒะฝะพะณะพ ะฐะฝะฐะปั–ะทัƒ, ะฐ ะฝะต ัะบ ะดะพะดะฐั‚ะบะพะฒะธะน ั€ั–ะฒะตะฝัŒ ะฟะพะฒะตั€ั… ะพัะฝะพะฒะฝะพั— ะฐั€ั…ั–ั‚ะตะบั‚ัƒั€ะธ. -* ะฆะต ั‚ะฐะบะพะถ ะดะฐั” ะทะผะพะณัƒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ **ะณะตะฝะตั€ัƒะฒะฐั‚ะธ ะบะพะด ะบะปั–ั”ะฝั‚ะฐ** ะฑะฐะณะฐั‚ัŒะผะฐ ะผะพะฒะฐะผะธ. +* ะฆะต ั‚ะฐะบะพะถ ะดะฐั” ะทะผะพะณัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ **ะณะตะฝะตั€ะฐั†ั–ัŽ ะบะปั–ั”ะฝั‚ััŒะบะพะณะพ ะบะพะดัƒ** ะฑะฐะณะฐั‚ัŒะผะฐ ะผะพะฒะฐะผะธ. -### ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะณะตะฝะตั€ะฐั†ั–ั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— +### ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั { #automatic-docs } -ะ†ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API ั‚ะฐ ะฒะตะฑั–ะฝั‚ะตั€ั„ะตะนั ะดะปั ะนะพะณะพ ะดะพัะปั–ะดะถะตะฝะฝั. ะžัะบั–ะปัŒะบะธ ั„ั€ะตะนะผะฒะพั€ะบ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ OpenAPI, ั” ะบั–ะปัŒะบะฐ ะฒะฐั€ั–ะฐะฝั‚ั–ะฒ, ะดะฒะฐ ะท ัะบะธั… ะฒะบะปัŽั‡ะตะฝั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +ะ†ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API ั‚ะฐ ะฒะตะฑั–ะฝั‚ะตั€ั„ะตะนัะธ ะดะปั ะนะพะณะพ ะดะพัะปั–ะดะถะตะฝะฝั. ะžัะบั–ะปัŒะบะธ ั„ั€ะตะนะผะฒะพั€ะบ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ OpenAPI, ั” ะบั–ะปัŒะบะฐ ะฒะฐั€ั–ะฐะฝั‚ั–ะฒ, 2 ะท ัะบะธั… ะฒะบะปัŽั‡ะตะฝั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. -* Swagger UI โ€” ะดะพะทะฒะพะปัั” ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพ ะฟะตั€ะตะณะปัะดะฐั‚ะธ API, ะฒะธะบะปะธะบะฐั‚ะธ ั‚ะฐ ั‚ะตัั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ะฟั€ัะผะพ ัƒ ะฑั€ะฐัƒะทะตั€ั–. +* Swagger UI โ€” ะท ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะธะผ ะดะพัะปั–ะดะถะตะฝะฝัะผ, ะฒะธะบะปะธะบะพะผ ั– ั‚ะตัั‚ัƒะฒะฐะฝะฝัะผ ะฒะฐัˆะพะณะพ API ะฟั€ัะผะพ ะท ะฑั€ะฐัƒะทะตั€ะฐ. ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -23,23 +23,25 @@ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ะขั–ะปัŒะบะธ ััƒั‡ะฐัะฝะธะน Python +### ะ›ะธัˆะต ััƒั‡ะฐัะฝะธะน Python { #just-modern-python } -FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัั‚ะฐะฝะดะฐั€ั‚ะฝั– **ั‚ะธะฟะธ Python** (ะทะฐะฒะดัะบะธ Pydantic). ะ’ะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะฒั‡ะฐั‚ะธ ะฝะพะฒะธะน ัะธะฝั‚ะฐะบัะธั โ€” ะปะธัˆะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน ััƒั‡ะฐัะฝะธะน Python. +ะฃัะต ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… ะพะณะพะปะพัˆะตะฝะฝัั… **ั‚ะธะฟั–ะฒ Python** (ะทะฐะฒะดัะบะธ Pydantic). ะ–ะพะดะฝะพะณะพ ะฝะพะฒะพะณะพ ัะธะฝั‚ะฐะบัะธััƒ ะดะปั ะฒะธะฒั‡ะตะฝะฝั. ะ›ะธัˆะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน ััƒั‡ะฐัะฝะธะน Python. -ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะต ะบะพั€ะพั‚ะบะต ะฝะฐะณะฐะดัƒะฒะฐะฝะฝั ะฟั€ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ะธะฟั–ะฒ ัƒ Python (ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต FastAPI), ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะบะพั€ะพั‚ะบะธะน ะฟั–ะดั€ัƒั‡ะฝะธะบ: [ะ’ัั‚ัƒะฟ ะดะพ ั‚ะธะฟั–ะฒ Python](python-types.md){.internal-link target=_blank}. +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ 2-ั…ะฒะธะปะธะฝะฝะต ะฝะฐะณะฐะดัƒะฒะฐะฝะฝั ะฟั€ะพ ั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะธะฟะธ Python (ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต FastAPI), ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะบะพั€ะพั‚ะบะธะน ะฟั–ะดั€ัƒั‡ะฝะธะบ: [ะขะธะฟะธ Python](python-types.md){.internal-link target=_blank}. -ะžััŒ ะฟั€ะธะบะปะฐะด ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะณะพ Python-ะบะพะดัƒ ะท ั‚ะธะฟะฐะผะธ: +ะ’ะธ ะฟะธัˆะตั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน Python ะท ั‚ะธะฟะฐะผะธ: ```Python from datetime import date + from pydantic import BaseModel -# ะžะณะพะปะพัˆะตะฝะฝั ะทะผั–ะฝะฝะพั— ัะบ str -# ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ัƒ ั€ะตะดะฐะบั‚ะพั€ั– +# ะžะณะพะปะพัั–ั‚ัŒ ะทะผั–ะฝะฝัƒ ัะบ str +# ั‚ะฐ ะพั‚ั€ะธะผะฐะนั‚ะต ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— def main(user_id: str): return user_id + # ะœะพะดะตะปัŒ Pydantic class User(BaseModel): id: int @@ -47,7 +49,7 @@ class User(BaseModel): joined: date ``` -ะŸั€ะธะบะปะฐะด ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั†ั–ั”ั— ะผะพะดะตะปั–: +ะ”ะฐะปั– ั†ะต ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะฐะบ: ```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") @@ -65,19 +67,21 @@ my_second_user: User = User(**second_user_data) `**second_user_data` ะพะทะฝะฐั‡ะฐั”: -ะŸะตั€ะตะดะฐั‚ะธ ะบะปัŽั‡ั– ั‚ะฐ ะทะฝะฐั‡ะตะฝะฝั ัะปะพะฒะฝะธะบะฐ `second_user_data` ัะบ ะฐั€ะณัƒะผะตะฝั‚ะธ ัƒ ะฒะธะณะปัะดั– "ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั", ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ `User(id=4, name="Mary", joined="2018-11-30")`. +ะŸะตั€ะตะดะฐั‚ะธ ะบะปัŽั‡ั– ั‚ะฐ ะทะฝะฐั‡ะตะฝะฝั ัะปะพะฒะฝะธะบะฐ `second_user_data` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัะบ ะฐั€ะณัƒะผะตะฝั‚ะธ ัƒ ะฒะธะณะปัะดั– ยซะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝัยป, ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ: `User(id=4, name="Mary", joined="2018-11-30")` /// -### ะŸั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ั–ะฒ (IDE) +### ะŸั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ั–ะฒ (IDE) { #editor-support } -ะคั€ะตะนะผะฒะพั€ะบ ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะธะน ั‚ะฐะบ, ั‰ะพะฑ ะฑัƒั‚ะธ ะปะตะณะบะธะผ ั– ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะผ. ะฃัั– ั€ั–ัˆะตะฝะฝั ั‚ะตัั‚ัƒะฒะฐะปะธัั ัƒ ั€ั–ะทะฝะธั… ั€ะตะดะฐะบั‚ะพั€ะฐั… ั‰ะต ะดะพ ะฟะพั‡ะฐั‚ะบัƒ ั€ะพะทั€ะพะฑะบะธ, ั‰ะพะฑ ะทะฐะฑะตะทะฟะตั‡ะธั‚ะธ ะฝะฐะนะบั€ะฐั‰ะธะน ะดะพัะฒั–ะด ะฟั€ะพะณั€ะฐะผัƒะฒะฐะฝะฝั. +ะฃะฒะตััŒ ั„ั€ะตะนะผะฒะพั€ะบ ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะพ ั‚ะฐะบ, ั‰ะพะฑ ะฝะธะผ ะฑัƒะปะพ ะปะตะณะบะพ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธัั; ัƒัั– ั€ั–ัˆะตะฝะฝั ั‚ะตัั‚ัƒะฒะฐะปะธัั ัƒ ะบั–ะปัŒะบะพั… ั€ะตะดะฐะบั‚ะพั€ะฐั… ั‰ะต ะดะพ ะฟะพั‡ะฐั‚ะบัƒ ั€ะพะทั€ะพะฑะบะธ, ั‰ะพะฑ ะทะฐะฑะตะทะฟะตั‡ะธั‚ะธ ะฝะฐะนะบั€ะฐั‰ะธะน ะดะพัะฒั–ะด ั€ะพะทั€ะพะฑะบะธ. -ะ—ะฐ ั€ะตะทัƒะปัŒั‚ะฐั‚ะฐะผะธ ะพะฟะธั‚ัƒะฒะฐะฝัŒ ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ Python ะพะดะฝั–ั”ัŽ ะท ะฝะฐะนะฟะพะฟัƒะปัั€ะฝั–ัˆะธั… ั„ัƒะฝะบั†ั–ะน ั” "ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั". +ะ— ะพะฟะธั‚ัƒะฒะฐะฝัŒ ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ Python ะทั€ะพะทัƒะผั–ะปะพ ั‰ะพ ะพะดะฝั–ั”ัŽ ะท ะฝะฐะนัƒะถะธะฒะฐะฝั–ัˆะธั… ั„ัƒะฝะบั†ั–ะน ั” ยซะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัยป. -**FastAPI** ะฟะพะฒะฝั–ัั‚ัŽ ะฟั–ะดั‚ั€ะธะผัƒั” ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ัƒ ะฒัั–ั… ะผั–ัั†ัั…, ั‚ะพะผัƒ ะฒะฐะผ ั€ั–ะดะบะพ ะดะพะฒะตะดะตั‚ัŒัั ะฟะพะฒะตั€ั‚ะฐั‚ะธัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +ะฃะฒะตััŒ ั„ั€ะตะนะผะฒะพั€ะบ **FastAPI** ะฟะพะฑัƒะดะพะฒะฐะฝะธะน ั‚ะฐะบ, ั‰ะพะฑ ั†ะต ะทะฐะฑะตะทะฟะตั‡ะธั‚ะธ. ะะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฟั€ะฐั†ัŽั” ะฒััŽะดะธ. -ะŸั€ะธะบะปะฐะด ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ัƒ ั€ะตะดะฐะบั‚ะพั€ะฐั…: +ะ’ะฐะผ ั€ั–ะดะบะพ ะดะพะฒะตะดะตั‚ัŒัั ะฟะพะฒะตั€ั‚ะฐั‚ะธัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะžััŒ ัะบ ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€ ะผะพะถะต ะฒะฐะผ ะดะพะฟะพะผะพะณั‚ะธ: * ัƒ Visual Studio Code: @@ -87,17 +91,25 @@ my_second_user: User = User(**second_user_data) ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -### ะšะพั€ะพั‚ะบะธะน ะบะพะด -FastAPI ะผะฐั” ั€ะพะทัƒะผะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั **ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ**, ะฐะปะต ะฒัั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะผะพะถะฝะฐ ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะดะพ ะฒะฐัˆะธั… ะฟะพั‚ั€ะตะฑ. ะžะดะฝะฐะบ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฒัะต "ะฟั€ะพัั‚ะพ ะฟั€ะฐั†ัŽั”". +ะ’ะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒ ะบะพะดั–, ัะบะธะน ั€ะฐะฝั–ัˆะต ะผะพะณะปะธ ะฒะฒะฐะถะฐั‚ะธ ะฝะฐะฒั–ั‚ัŒ ะฝะตะผะพะถะปะธะฒะธะผ. ะะฐะฟั€ะธะบะปะฐะด, ะดะปั ะบะปัŽั‡ะฐ `price` ะฒัะตั€ะตะดะธะฝั– JSON body (ัะบะธะน ะผั–ะณ ะฑัƒั‚ะธ ะฒะบะปะฐะดะตะฝะธะผ), ั‰ะพ ะฝะฐะดั…ะพะดะธั‚ัŒ ั–ะท ะทะฐะฟะธั‚ัƒ. + +ะ‘ั–ะปัŒัˆะต ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ะฒะฒะพะดะธั‚ะธ ะฝะตะฟั€ะฐะฒะธะปัŒะฝั– ะฝะฐะทะฒะธ ะบะปัŽั‡ั–ะฒ, ะฟะพัั‚ั–ะนะฝะพ ะฟะพะฒะตั€ั‚ะฐั‚ะธัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฐะฑะพ ะฟั€ะพะบั€ัƒั‡ัƒะฒะฐั‚ะธ ะฒะณะพั€ัƒ-ะฒะฝะธะท, ั‰ะพะฑ ะทะฝะฐะนั‚ะธ, ั‡ะธ ะฒะธ ะทั€ะตัˆั‚ะพัŽ ะฒะธะบะพั€ะธัั‚ะฐะปะธ `username` ั‡ะธ `user_name`. + +### ะšะพั€ะพั‚ะบะธะน ะบะพะด { #short } + +FastAPI ะผะฐั” ั€ะพะทัƒะผะฝั– **ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ** ะดะปั ะฒััŒะพะณะพ, ะท ะผะพะถะปะธะฒั–ัั‚ัŽ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— ะฒััŽะดะธ. ะฃัั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะผะพะถะฝะฐ ั‚ะพั‡ะฝะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะฟั–ะด ะฒะฐัˆั– ะฟะพั‚ั€ะตะฑะธ ั‚ะฐ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะฟะพั‚ั€ั–ะฑะฝะธะน ะฒะฐะผ API. + +ะะปะต ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ัƒัะต **ยซะฟั€ะพัั‚ะพ ะฟั€ะฐั†ัŽั”ยป**. + +### ะ’ะฐะปั–ะดะฐั†ั–ั { #validation } -### ะ’ะฐะปั–ะดะฐั†ั–ั * ะŸั–ะดั‚ั€ะธะผะบะฐ ะฒะฐะปั–ะดะฐั†ั–ั— ะดะปั ะฑั–ะปัŒัˆะพัั‚ั– (ะฐะฑะพ ะฒัั–ั…?) **ั‚ะธะฟั–ะฒ ะดะฐะฝะธั… Python**, ะทะพะบั€ะตะผะฐ: * JSON-ะพะฑ'ั”ะบั‚ั–ะฒ (`dict`). - * JSON-ัะฟะธัะบั–ะฒ (`list`) ะท ะฒะธะทะฝะฐั‡ะตะฝะฝัะผ ั‚ะธะฟั–ะฒ ะตะปะตะผะตะฝั‚ั–ะฒ. - * ะ ัะดะบั–ะฒ (`str`) ั–ะท ะผั–ะฝั–ะผะฐะปัŒะฝะพัŽ ั‚ะฐ ะผะฐะบัะธะผะฐะปัŒะฝะพัŽ ะดะพะฒะถะธะฝะพัŽ. - * ะงะธัะตะป (`int`, `float`) ะท ะพะฑะผะตะถะตะฝะฝัะผะธ ะผั–ะฝั–ะผะฐะปัŒะฝะธั… ั‚ะฐ ะผะฐะบัะธะผะฐะปัŒะฝะธั… ะทะฝะฐั‡ะตะฝัŒ ั‚ะพั‰ะพ. + * JSON-ะผะฐัะธะฒั–ะฒ (`list`) ั–ะท ะฒะธะทะฝะฐั‡ะตะฝะฝัะผ ั‚ะธะฟั–ะฒ ะตะปะตะผะตะฝั‚ั–ะฒ. + * ะŸะพะปั–ะฒ-ั€ัะดะบั–ะฒ (`str`) ั–ะท ะฒะธะทะฝะฐั‡ะตะฝะฝัะผ ะผั–ะฝั–ะผะฐะปัŒะฝะพั— ั‚ะฐ ะผะฐะบัะธะผะฐะปัŒะฝะพั— ะดะพะฒะถะธะฝะธ. + * ะงะธัะตะป (`int`, `float`) ะท ะผั–ะฝั–ะผะฐะปัŒะฝะธะผะธ ั‚ะฐ ะผะฐะบัะธะผะฐะปัŒะฝะธะผะธ ะทะฝะฐั‡ะตะฝะฝัะผะธ ั‚ะพั‰ะพ. -* ะ’ะฐะปั–ะดะฐั†ั–ั ัะบะปะฐะดะฝั–ัˆะธั… ั‚ะธะฟั–ะฒ, ั‚ะฐะบะธั… ัะบ: +* ะ’ะฐะปั–ะดะฐั†ั–ั ะดะปั ะฑั–ะปัŒัˆ ะตะบะทะพั‚ะธั‡ะฝะธั… ั‚ะธะฟั–ะฒ, ัะบ-ะพั‚: * URL. * Email. * UUID. @@ -105,55 +117,55 @@ FastAPI ะผะฐั” ั€ะพะทัƒะผะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั **ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐ ะฃัั ะฒะฐะปั–ะดะฐั†ั–ั ะฒะธะบะพะฝัƒั”ั‚ัŒัั ั‡ะตั€ะตะท ะฝะฐะดั–ะนะฝะธะน ั‚ะฐ ะฟะตั€ะตะฒั–ั€ะตะฝะธะน **Pydantic**. -### ะ‘ะตะทะฟะตะบะฐ ั‚ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั +### ะ‘ะตะทะฟะตะบะฐ ั‚ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั { #security-and-authentication } -**FastAPI** ะฟั–ะดั‚ั€ะธะผัƒั” ะฒะฑัƒะดะพะฒะฐะฝัƒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ ั‚ะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ัŽ, ะฑะตะท ะฟั€ะธะฒโ€™ัะทะบะธ ะดะพ ะบะพะฝะบั€ะตั‚ะฝะธั… ะฑะฐะท ะดะฐะฝะธั… ั‡ะธ ะผะพะดะตะปะตะน ะดะฐะฝะธั…. +ะ†ะฝั‚ะตะณั€ะพะฒะฐะฝั– ะฑะตะทะฟะตะบะฐ ั‚ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั. ะ‘ะตะท ะถะพะดะฝะธั… ะบะพะผะฟั€ะพะผั–ัั–ะฒ ั–ะท ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… ั‡ะธ ะผะพะดะตะปัะผะธ ะดะฐะฝะธั…. -ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ะฒัั– ัั…ะตะผะธ ะฑะตะทะฟะตะบะธ OpenAPI, ะฒะบะปัŽั‡ะฐัŽั‡ะธ: +ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ะฒัั– ัั…ะตะผะธ ะฑะตะทะฟะตะบะธ, ะฒะธะทะฝะฐั‡ะตะฝั– ะฒ OpenAPI, ะฒะบะปัŽั‡ะฝะพ ะท: * HTTP Basic. -* **OAuth2** (ั‚ะฐะบะพะถ ั–ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ **JWT-ั‚ะพะบะตะฝั–ะฒ**). ะ”ะธะฒ. ะฟั–ะดั€ัƒั‡ะฝะธะบ: [OAuth2 ั–ะท JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. +* **OAuth2** (ั‚ะฐะบะพะถ ั–ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ **JWT tokens**). ะŸะตั€ะตะณะปัะฝัŒั‚ะต ะฟั–ะดั€ัƒั‡ะฝะธะบ: [OAuth2 ั–ะท JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. * ะšะปัŽั‡ั– API ะฒ: * ะ—ะฐะณะพะปะพะฒะบะฐั…. * ะŸะฐั€ะฐะผะตั‚ั€ะฐั… ะทะฐะฟะธั‚ัƒ. * Cookies ั‚ะพั‰ะพ. -ะ ั‚ะฐะบะพะถ ัƒัั– ะผะพะถะปะธะฒะพัั‚ั– ะฑะตะทะฟะตะบะธ ะฒั–ะด Starlette (ะทะพะบั€ะตะผะฐ **ัะตัั–ะนะฝั– cookies**). +ะ ั‚ะฐะบะพะถ ัƒัั– ะผะพะถะปะธะฒะพัั‚ั– ะฑะตะทะฟะตะบะธ ะฒั–ะด Starlette (ะทะพะบั€ะตะผะฐ **session cookies**). -ะฃัั– ะฒะพะฝะธ ัั‚ะฒะพั€ะตะฝั– ัะบ ะฑะฐะณะฐั‚ะพั€ะฐะทะพะฒั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั‚ะฐ ะบะพะผะฟะพะฝะตะฝั‚ะธ, ัะบั– ะปะตะณะบะพ ั–ะฝั‚ะตะณั€ัƒัŽั‚ัŒัั ะท ะฒะฐัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ัั…ะพะฒะธั‰ะฐะผะธ ะดะฐะฝะธั…, ั€ะตะปัั†ั–ะนะฝะธะผะธ ั‚ะฐ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ. +ะฃัะต ั†ะต ะทั€ะพะฑะปะตะฝะพ ัะบ ะฑะฐะณะฐั‚ะพั€ะฐะทะพะฒั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั‚ะฐ ะบะพะผะฟะพะฝะตะฝั‚ะธ, ัะบั– ะปะตะณะบะพ ั–ะฝั‚ะตะณั€ัƒัŽั‚ัŒัั ะท ะฒะฐัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ัั…ะพะฒะธั‰ะฐะผะธ ะดะฐะฝะธั…, ั€ะตะปัั†ั–ะนะฝะธะผะธ ั‚ะฐ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ. -### ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน +### ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน { #dependency-injection } -**FastAPI** ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั–, ะฐะปะต ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. +FastAPI ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั–, ะฐะปะต ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ Dependency Injection. -* ะ—ะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะปะตะถะฝะพัั‚ั–, ัƒั‚ะฒะพั€ัŽัŽั‡ะธ ั–ั”ั€ะฐั€ั…ั–ัŽ ะฐะฑะพ **"ะณั€ะฐั„ ะทะฐะปะตะถะฝะพัั‚ะตะน"**. -* ะฃัั– ะทะฐะปะตะถะฝะพัั‚ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะบะตั€ัƒัŽั‚ัŒัั ั„ั€ะตะนะผะฒะพั€ะบะพะผ. -* ะฃัั– ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะดะฐะฝั– ะท ะทะฐะฟะธั‚ั–ะฒ ั– ั€ะพะทัˆะธั€ัŽะฒะฐั‚ะธ **ะพะฑะผะตะถะตะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ะทะฐ ัˆะปัั…ะพะผ** ั‚ะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ. -* **ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะฒะฐะปั–ะดะฐั†ั–ั** ะฝะฐะฒั–ั‚ัŒ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*, ะฒะธะทะฝะฐั‡ะตะฝะธั… ัƒ ะทะฐะปะตะถะฝะพัั‚ัั…. -* ะŸั–ะดั‚ั€ะธะผะบะฐ ัะบะปะฐะดะฝะธั… ัะธัั‚ะตะผ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, **ะท'ั”ะดะฝะฐะฝัŒ ั–ะท ะฑะฐะทะฐะผะธ ะดะฐะฝะธั…** ั‚ะพั‰ะพ. -* **ะ–ะพะดะฝะธั… ะพะฑะผะตะถะตะฝัŒ** ั‰ะพะดะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฑะฐะท ะดะฐะฝะธั…, ั„ั€ะพะฝั‚ะตะฝะดั–ะฒ ั‚ะพั‰ะพ, ะฐะปะต ะฒะพะดะฝะพั‡ะฐั ะฟั€ะพัั‚ะฐ ั–ะฝั‚ะตะณั€ะฐั†ั–ั ะท ัƒัั–ะผะฐ ะฝะธะผะธ. +* ะะฐะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะปะตะถะฝะพัั‚ั–, ัƒั‚ะฒะพั€ัŽัŽั‡ะธ ั–ั”ั€ะฐั€ั…ั–ัŽ ะฐะฑะพ **ยซะณั€ะฐั„ยป ะทะฐะปะตะถะฝะพัั‚ะตะน**. +* ะฃัะต **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั”ั‚ัŒัั** ั„ั€ะตะนะผะฒะพั€ะบะพะผ. +* ะฃัั– ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะฒะธะผะฐะณะฐั‚ะธ ะดะฐะฝั– ั–ะท ะทะฐะฟะธั‚ั–ะฒ ั– **ั€ะพะทัˆะธั€ัŽะฒะฐั‚ะธ ะพะฑะผะตะถะตะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ** ั‚ะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ. +* **ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะฒะฐะปั–ะดะฐั†ั–ั** ะฝะฐะฒั–ั‚ัŒ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธะทะฝะฐั‡ะตะฝะธั… ัƒ ะทะฐะปะตะถะฝะพัั‚ัั…. +* ะŸั–ะดั‚ั€ะธะผะบะฐ ัะบะปะฐะดะฝะธั… ัะธัั‚ะตะผ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, **ะฟั–ะดะบะปัŽั‡ะตะฝัŒ ะดะพ ะฑะฐะท ะดะฐะฝะธั…** ั‚ะพั‰ะพ. +* **ะ–ะพะดะฝะธั… ะบะพะผะฟั€ะพะผั–ัั–ะฒ** ั–ะท ะฑะฐะทะฐะผะธ ะดะฐะฝะธั…, ั„ั€ะพะฝั‚ะตะฝะดะฐะผะธ ั‚ะพั‰ะพ. ะะปะต ะฟั€ะพัั‚ะฐ ั–ะฝั‚ะตะณั€ะฐั†ั–ั ะท ัƒัั–ะผะฐ ะฝะธะผะธ. -### ะะตะผะฐั” ะพะฑะผะตะถะตะฝัŒ ะฝะฐ "ะฟะปะฐะณั–ะฝะธ" +### ะะตะพะฑะผะตะถะตะฝั– ยซะฟะปะฐะณั–ะฝะธยป { #unlimited-plug-ins } -ะะฑะพ ั–ะฝัˆะธะผะธ ัะปะพะฒะฐะผะธ, ะฒะพะฝะธ ะฝะต ะฟะพั‚ั€ั–ะฑะฝั– โ€“ ะฟั€ะพัั‚ะพ ั–ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฝะตะพะฑั…ั–ะดะฝะธะน ะบะพะด. +ะ†ะฝะฐะบัˆะต ะบะฐะถัƒั‡ะธ, ะฒะพะฝะธ ะฝะต ะฟะพั‚ั€ั–ะฑะฝั– โ€” ั–ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะบะพะด, ัะบะธะน ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะตะฝ. -ะ‘ัƒะดัŒ-ัะบะฐ ั–ะฝั‚ะตะณั€ะฐั†ั–ั ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะฐ ะฝะฐัั‚ั–ะปัŒะบะธ ะฟั€ะพัั‚ะพ (ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ ะทะฐะปะตะถะฝะพัั‚ะตะน), ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ "ะฟะปะฐะณั–ะฝ" ะดะปั ัะฒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒััŒะพะณะพ ัƒ 2 ั€ัะดะบะฐั… ะบะพะดัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ัƒ ัะฐะผัƒ ัั‚ั€ัƒะบั‚ัƒั€ัƒ ั‚ะฐ ัะธะฝั‚ะฐะบัะธั, ั‰ะพ ะน ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. +ะ‘ัƒะดัŒ-ัะบะฐ ั–ะฝั‚ะตะณั€ะฐั†ั–ั ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะฐ ั‚ะฐะบ, ั‰ะพะฑ ั—ั— ะฑัƒะปะพ ะดัƒะถะต ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ (ั–ะท ะทะฐะปะตะถะฝะพัั‚ัะผะธ), ั‚ะพะถ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ยซะฟะปะฐะณั–ะฝยป ะดะปั ัะฒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ัƒ 2 ั€ัะดะบะฐั… ะบะพะดัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ัƒ ัะฐะผัƒ ัั‚ั€ัƒะบั‚ัƒั€ัƒ ั‚ะฐ ัะธะฝั‚ะฐะบัะธั, ั‰ะพ ะน ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. -### ะŸั€ะพั‚ะตัั‚ะพะฒะฐะฝะพ +### ะŸั€ะพั‚ะตัั‚ะพะฒะฐะฝะพ { #tested } * 100% ะฟะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ. * 100% ะฐะฝะพั‚ะพะฒะฐะฝะฐ ั‚ะธะฟะฐะผะธ ะบะพะดะพะฒะฐ ะฑะฐะทะฐ. -* ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒ ั€ะพะฑะพั‡ะธั… ัะตั€ะตะดะพะฒะธั‰ะฐั…. +* ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒ production-ะทะฐัั‚ะพััƒะฝะบะฐั…. -## ะœะพะถะปะธะฒะพัั‚ั– Starlette +## ะœะพะถะปะธะฒะพัั‚ั– Starlette { #starlette-features } **FastAPI** ะฟะพะฒะฝั–ัั‚ัŽ ััƒะผั–ัะฝะธะน ั–ะท (ั‚ะฐ ะฟะพะฑัƒะดะพะฒะฐะฝะธะน ะฝะฐ ะพัะฝะพะฒั–) Starlette. ะขะพะผัƒ ะฑัƒะดัŒ-ัะบะธะน ะดะพะดะฐั‚ะบะพะฒะธะน ะบะพะด Starlette, ัะบะธะน ะฒะธ ะผะฐั”ั‚ะต, ั‚ะฐะบะพะถ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต. -**FastAPI** ั„ะฐะบั‚ะธั‡ะฝะพ ั” ะฟั–ะดะบะปะฐัะพะผ **Starlette**. ะขะพะผัƒ, ัะบั‰ะพ ะฒะธ ะฒะถะต ะทะฝะฐะนะพะผั– ะทั– Starlette ะฐะฑะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะนะพะณะพ, ะฑั–ะปัŒัˆั–ัั‚ัŒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝะพัั‚ั– ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ั‚ะฐะบ ัะฐะผะพ. +`FastAPI` ั„ะฐะบั‚ะธั‡ะฝะพ ั” ะฟั–ะดะบะปะฐัะพะผ `Starlette`. ะขะพะผัƒ, ัะบั‰ะพ ะฒะธ ะฒะถะต ะทะฝะฐะนะพะผั– ะทั– Starlette ะฐะฑะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะนะพะณะพ, ะฑั–ะปัŒัˆั–ัั‚ัŒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝะพัั‚ั– ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ั‚ะฐะบ ัะฐะผะพ. -ะ— **FastAPI** ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฒัั– ะผะพะถะปะธะฒะพัั‚ั– **Starlette** (ะฐะดะถะต FastAPI โ€” ั†ะต, ะฟะพ ััƒั‚ั–, Starlette ะฝะฐ ัั‚ะตั€ะพั—ะดะฐั…): +ะ— **FastAPI** ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฒัั– ะผะพะถะปะธะฒะพัั‚ั– **Starlette** (ะฐะดะถะต FastAPI โ€” ั†ะต ะฟั€ะพัั‚ะพ Starlette ะฝะฐ ัั‚ะตั€ะพั—ะดะฐั…): -* ะ ะฐะทัŽั‡ะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. ะฆะต ะพะดะธะฝ ั–ะท ะฝะฐะนัˆะฒะธะดัˆะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ ะฝะฐ Python, ะฝะฐ ั€ั–ะฒะฝั– ะท **NodeJS** ั– **Go**. +* ะ ะฐะทัŽั‡ะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. ะฆะต ะพะดะธะฝ ั–ะท ะฝะฐะนัˆะฒะธะดัˆะธั… ะดะพัั‚ัƒะฟะฝะธั… Python-ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ, ะฝะฐ ั€ั–ะฒะฝั– ะท **NodeJS** ั– **Go**. * ะŸั–ะดั‚ั€ะธะผะบะฐ **WebSocket**. * ะคะพะฝะพะฒั– ะทะฐะดะฐั‡ั– ัƒ ะฟั€ะพั†ะตัั–. * ะŸะพะดั–ั— ะทะฐะฟัƒัะบัƒ ั‚ะฐ ะทะฐะฒะตั€ัˆะตะฝะฝั ั€ะพะฑะพั‚ะธ. @@ -163,27 +175,27 @@ FastAPI ะผะฐั” ั€ะพะทัƒะผะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั **ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐ * 100% ะฟะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ. * 100% ะฐะฝะพั‚ะพะฒะฐะฝะฐ ั‚ะธะฟะฐะผะธ ะบะพะดะพะฒะฐ ะฑะฐะทะฐ. -## ะœะพะถะปะธะฒะพัั‚ั– Pydantic +## ะœะพะถะปะธะฒะพัั‚ั– Pydantic { #pydantic-features } **FastAPI** ะฟะพะฒะฝั–ัั‚ัŽ ััƒะผั–ัะฝะธะน ั–ะท (ั‚ะฐ ะฟะพะฑัƒะดะพะฒะฐะฝะธะน ะฝะฐ ะพัะฝะพะฒั–) Pydantic. ะขะพะผัƒ ะฑัƒะดัŒ-ัะบะธะน ะดะพะดะฐั‚ะบะพะฒะธะน ะบะพะด Pydantic, ัะบะธะน ะฒะธ ะผะฐั”ั‚ะต, ั‚ะฐะบะพะถ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต. -ะ’ะบะปัŽั‡ะฐัŽั‡ะธ ะทะพะฒะฝั–ัˆะฝั– ะฑั–ะฑะปั–ะพั‚ะตะบะธ, ะฟะพะฑัƒะดะพะฒะฐะฝั– ั‚ะฐะบะพะถ ะฝะฐ Pydantic, ั‚ะฐะบั– ัะบ ORM, ODM ะดะปั ะฑะฐะท ะดะฐะฝะธั…. +ะ’ะบะปัŽั‡ะฝะพ ั–ะท ะทะพะฒะฝั–ัˆะฝั–ะผะธ ะฑั–ะฑะปั–ะพั‚ะตะบะฐะผะธ, ัะบั– ั‚ะฐะบะพะถ ะฑะฐะทัƒัŽั‚ัŒัั ะฝะฐ Pydantic, ัะบ-ะพั‚ ORM-ะธ, ODM-ะธ ะดะปั ะฑะฐะท ะดะฐะฝะธั…. -ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚, ัะบะธะน ะพั‚ั€ะธะผัƒั”ั‚ะต ะท ะทะฐะฟะธั‚ัƒ, **ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ะฑะฐะทัƒ ะดะฐะฝะธั…**, ะพัะบั–ะปัŒะบะธ ะฒัะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตะฒั–ั€ัั”ั‚ัŒัั. +ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚, ัะบะธะน ะพั‚ั€ะธะผัƒั”ั‚ะต ั–ะท ะทะฐะฟะธั‚ัƒ, **ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ะฑะฐะทัƒ ะดะฐะฝะธั…**, ะพัะบั–ะปัŒะบะธ ะฒัะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตะฒั–ั€ัั”ั‚ัŒัั. -ะขะต ะถ ัะฐะผะต ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั ะน ัƒ ะทะฒะพั€ะพั‚ะฝะพะผัƒ ะฝะฐะฟั€ัะผะบัƒ โ€” ัƒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฟะตั€ะตะดะฐั‚ะธ ะพะฑ'ั”ะบั‚, ัะบะธะน ะพั‚ั€ะธะผัƒั”ั‚ะต ะท ะฑะฐะทะธ ะดะฐะฝะธั…, **ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะบะปั–ั”ะฝั‚ัƒ**. +ะขะต ัะฐะผะต ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั ะน ัƒ ะทะฒะพั€ะพั‚ะฝะพะผัƒ ะฝะฐะฟั€ัะผะบัƒ โ€” ัƒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฟะตั€ะตะดะฐั‚ะธ ะพะฑ'ั”ะบั‚, ัะบะธะน ะพั‚ั€ะธะผัƒั”ั‚ะต ะท ะฑะฐะทะธ ะดะฐะฝะธั…, **ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะบะปั–ั”ะฝั‚ัƒ**. ะ— **FastAPI** ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฒัั– ะผะพะถะปะธะฒะพัั‚ั– **Pydantic** (ะฐะดะถะต FastAPI ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Pydantic ะดะปั ะพะฑั€ะพะฑะบะธ ะฒัั–ั… ะดะฐะฝะธั…): -* **ะั–ัะบะพั— ะฟะปัƒั‚ะฐะฝะธะฝะธ** : - * ะะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒั‡ะธั‚ะธ ะฝะพะฒัƒ ะผะพะฒัƒ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ัั…ะตะผ. +* **ะั–ัะบะพั— ะฟะปัƒั‚ะฐะฝะธะฝะธ**: + * ะะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒั‡ะธั‚ะธ ะฝะพะฒัƒ ะผั–ะบั€ะพะผะพะฒัƒ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ัั…ะตะผ. * ะฏะบั‰ะพ ะฒะธ ะทะฝะฐั”ั‚ะต ั‚ะธะฟะธ Python, ะฒะธ ะทะฝะฐั”ั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Pydantic. -* ะ›ะตะณะบะพ ะฟั€ะฐั†ัŽั” ะท ะฒะฐัˆะธะผ **IDE/ะปั–ะฝั‚ะตั€ะพะผ/ะผะพะทะบะพะผ**: - * ะžัะบั–ะปัŒะบะธ ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั… Pydantic ั” ะฟั€ะพัั‚ะพ ะตะบะทะตะผะฟะปัั€ะฐะผะธ ะบะปะฐัั–ะฒ, ัะบั– ะฒะธ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต; ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั, ะปั–ะฝั‚ะธะฝะณ, mypy ั– ะฒะฐัˆะฐ ั–ะฝั‚ัƒั—ั†ั–ั ะฟะพะฒะธะฝะฝั– ะดะพะฑั€ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท ะฒะฐัˆะธะผะธ ะฟะตั€ะตะฒั–ั€ะตะฝะธะผะธ ะดะฐะฝะธะผะธ. -* ะ’ะฐะปั–ะดะฐั†ั–ั **ัะบะปะฐะดะฝะธั… ัั‚ั€ัƒะบั‚ัƒั€**: - * ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั–ั”ั€ะฐั€ั…ั–ั‡ะฝะธั… ะผะพะดะตะปะตะน Pydantic. Python `typing`, `List` ั– `Dict` ั‚ะพั‰ะพ. - * ะ’ะฐะปั–ะดะฐั‚ะพั€ะธ ะดะพะทะฒะพะปััŽั‚ัŒ ั‡ั–ั‚ะบะพ ั– ะฟั€ะพัั‚ะพ ะฒะธะทะฝะฐั‡ะฐั‚ะธ, ะฟะตั€ะตะฒั–ั€ัั‚ะธ ะน ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ัะบะปะฐะดะฝั– ัั…ะตะผะธ ะดะฐะฝะธั… ัƒ ะฒะธะณะปัะดั– JSON-ัั…ะตะผะธ. - * ะ’ะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะณะปะธะฑะพะบะพ **ะฒะบะปะฐะดะตะฝั– JSON ะพะฑ'ั”ะบั‚ะธ** ั‚ะฐ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั‚ะฐ ะฐะฝะพั‚ัƒะฒะฐั‚ะธ ั—ั… ะฒัั–. +* ะ›ะตะณะบะพ ะฟั€ะฐั†ัŽั” ะท ะฒะฐัˆะธะผ **IDE/linter/ะผะพะทะบะพะผ**: + * ะžัะบั–ะปัŒะบะธ ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั… pydantic ั” ะฟั€ะพัั‚ะพ ะตะบะทะตะผะฟะปัั€ะฐะผะธ ะบะปะฐัั–ะฒ, ัะบั– ะฒะธ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต; ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั, ะปั–ะฝั‚ะธะฝะณ, mypy ั– ะฒะฐัˆะฐ ั–ะฝั‚ัƒั—ั†ั–ั ะฟะพะฒะธะฝะฝั– ะดะพะฑั€ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท ะฒะฐัˆะธะผะธ ะฟะตั€ะตะฒั–ั€ะตะฝะธะผะธ ะดะฐะฝะธะผะธ. +* ะ’ะฐะปั–ะดัƒั” **ัะบะปะฐะดะฝั– ัั‚ั€ัƒะบั‚ัƒั€ะธ**: + * ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั–ั”ั€ะฐั€ั…ั–ั‡ะฝะธั… ะผะพะดะตะปะตะน Pydantic, Python `typing`โ€™s `List` ั– `Dict` ั‚ะพั‰ะพ. + * ะ’ะฐะปั–ะดะฐั‚ะพั€ะธ ะดะฐัŽั‚ัŒ ะทะผะพะณัƒ ัะบะปะฐะดะฝั– ัั…ะตะผะธ ะดะฐะฝะธั… ั‡ั–ั‚ะบะพ ะน ะฟั€ะพัั‚ะพ ะฒะธะทะฝะฐั‡ะฐั‚ะธ, ะฟะตั€ะตะฒั–ั€ัั‚ะธ ะน ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ัะบ JSON Schema. + * ะ’ะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะณะปะธะฑะพะบะพ **ะฒะบะปะฐะดะตะฝั– JSON** ะพะฑ'ั”ะบั‚ะธ, ั– ะฒัั– ะฒะพะฝะธ ะฑัƒะดัƒั‚ัŒ ะฒะฐะปั–ะดะพะฒะฐะฝั– ั‚ะฐ ะฐะฝะพั‚ะพะฒะฐะฝั–. * **ะ ะพะทัˆะธั€ัŽะฒะฐะฝั–ัั‚ัŒ**: - * Pydantic ะดะพะทะฒะพะปัั” ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ั‚ะธะฟะธ ะดะฐะฝะธั… ะฐะฑะพ ั€ะพะทัˆะธั€ัŽะฒะฐั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะผะตั‚ะพะดะฐะผะธ ะฒ ะผะพะดะตะปั– ะดะตะบะพั€ะฐั‚ะพั€ะพะผ `validator`. + * Pydantic ะดะพะทะฒะพะปัั” ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ั‚ะธะฟะธ ะดะฐะฝะธั… ะฐะฑะพ ะฒะธ ะผะพะถะตั‚ะต ั€ะพะทัˆะธั€ะธั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะผะตั‚ะพะดะฐะผะธ ะฒ ะผะพะดะตะปั–, ะฟะพะทะฝะฐั‡ะตะฝะธะผะธ ะดะตะบะพั€ะฐั‚ะพั€ะพะผ validator. * 100% ะฟะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ. From 07f08fc79a021cbc06d194f0a32f521253c6ed8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Feb 2026 09:44:59 +0000 Subject: [PATCH 036/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index eb72d559d0..699b966966 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -19,6 +19,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for uk (update outdated, found by fixer tool). PR [#14739](https://github.com/fastapi/fastapi/pull/14739) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev). * ๐ŸŒ Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov). From 3626d764c13cb12414b2b1a254af075f2799c716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 2 Feb 2026 02:24:23 -0800 Subject: [PATCH 037/367] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#14796)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/contributors.yml | 18 ++-- docs/en/data/translation_reviewers.yml | 114 ++++++++++++++----------- docs/en/data/translators.yml | 43 +++++----- 3 files changed, 95 insertions(+), 80 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 0c144cd4ce..41115ccbd4 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,17 +1,17 @@ tiangolo: login: tiangolo - count: 857 + count: 871 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 130 + count: 133 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: login: alejsdev count: 53 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci @@ -20,8 +20,8 @@ pre-commit-ci: url: https://github.com/apps/pre-commit-ci YuriiMotov: login: YuriiMotov - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 38 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov github-actions: login: github-actions @@ -40,7 +40,7 @@ dmontagu: url: https://github.com/dmontagu svlandeg: login: svlandeg - count: 16 + count: 17 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg nilslindemann: @@ -126,7 +126,7 @@ hitrust: ShahriyarR: login: ShahriyarR count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=631b2ae59360ab380c524b32bc3d245aff1165af&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=2dc6402d9053ee53f7afc407089cbab21c68f21d&v=4 url: https://github.com/ShahriyarR adriangb: login: adriangb @@ -266,7 +266,7 @@ Nimitha-jagadeesha: lucaromagnoli: login: lucaromagnoli count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=a09a2e916625fa035f9dfa25ebc58e07aac8ec36&v=4 url: https://github.com/lucaromagnoli salmantec: login: salmantec @@ -521,7 +521,7 @@ s111d: estebanx64: login: estebanx64 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=1900887aeed268699e5ea6f3fb7db614f7b77cd3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=812422ae5d6a4bc5ff331c901fc54f9ab3cecf5c&v=4 url: https://github.com/estebanx64 ndimares: login: ndimares diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 62db8e805d..3d321818fc 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,12 +10,12 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 127 + count: 128 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: login: ceb10n - count: 117 + count: 119 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n tokusumi: @@ -25,7 +25,7 @@ tokusumi: url: https://github.com/tokusumi hard-coders: login: hard-coders - count: 96 + count: 102 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 url: https://github.com/hard-coders hasansezertasan: @@ -50,7 +50,7 @@ AlertRED: url: https://github.com/AlertRED tiangolo: login: tiangolo - count: 73 + count: 78 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo Alexandrhub: @@ -58,26 +58,31 @@ Alexandrhub: count: 68 avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 url: https://github.com/Alexandrhub +cassiobotaro: + login: cassiobotaro + count: 64 + avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4 + url: https://github.com/cassiobotaro waynerv: login: waynerv count: 63 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv -cassiobotaro: - login: cassiobotaro - count: 62 - avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4 - url: https://github.com/cassiobotaro +nilslindemann: + login: nilslindemann + count: 61 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann mattwang44: login: mattwang44 count: 61 avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4 url: https://github.com/mattwang44 -nilslindemann: - login: nilslindemann - count: 59 - avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 - url: https://github.com/nilslindemann +YuriiMotov: + login: YuriiMotov + count: 56 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov Laineyzhang55: login: Laineyzhang55 count: 48 @@ -88,26 +93,21 @@ Kludex: count: 47 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -YuriiMotov: - login: YuriiMotov - count: 46 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 - url: https://github.com/YuriiMotov komtaki: login: komtaki count: 45 avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 url: https://github.com/komtaki +svlandeg: + login: svlandeg + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg rostik1410: login: rostik1410 count: 42 avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 url: https://github.com/rostik1410 -svlandeg: - login: svlandeg - count: 42 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg alperiox: login: alperiox count: 42 @@ -136,7 +136,7 @@ JavierSanchezCastro: alejsdev: login: alejsdev count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev mezgoodle: login: mezgoodle @@ -383,6 +383,11 @@ Joao-Pedro-P-Holanda: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 url: https://github.com/Joao-Pedro-P-Holanda +maru0123-2004: + login: maru0123-2004 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 JaeHyuckSa: login: JaeHyuckSa count: 16 @@ -418,11 +423,6 @@ mattkoehne: count: 14 avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4 url: https://github.com/mattkoehne -maru0123-2004: - login: maru0123-2004 - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 - url: https://github.com/maru0123-2004 jovicon: login: jovicon count: 13 @@ -458,6 +458,11 @@ wesinalves: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/13563128?u=9eb17ed50645dd684bfec47e75dba4e9772ec9c1&v=4 url: https://github.com/wesinalves +andersonrocha0: + login: andersonrocha0 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 + url: https://github.com/andersonrocha0 NastasiaSaby: login: NastasiaSaby count: 12 @@ -471,7 +476,7 @@ oandersonmagalhaes: mkdir700: login: mkdir700 count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=3d6ea8714f5000829b60dcf7b13a75b1e73aaf47&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=818e5f4b4dcc1a6ffb3e5aaa08fd827e5a726dfd&v=4 url: https://github.com/mkdir700 batlopes: login: batlopes @@ -493,11 +498,6 @@ KaniKim: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/19832624?u=296dbdd490e0eb96e3d45a2608c065603b17dc31&v=4 url: https://github.com/KaniKim -andersonrocha0: - login: andersonrocha0 - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 - url: https://github.com/andersonrocha0 gitgernit: login: gitgernit count: 12 @@ -558,6 +558,11 @@ Zhongheng-Cheng: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 url: https://github.com/Zhongheng-Cheng +Pyth3rEx: + login: Pyth3rEx + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4 + url: https://github.com/Pyth3rEx mariacamilagl: login: mariacamilagl count: 10 @@ -611,7 +616,7 @@ socket-socket: nick-cjyx9: login: nick-cjyx9 count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=7227a2de948c68fb8396d5beff1ee5b0e057c42e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=3d51dcbd79222ecb6538642f31dc7c8bb708d191&v=4 url: https://github.com/nick-cjyx9 marcelomarkus: login: marcelomarkus @@ -683,11 +688,6 @@ Yarous: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4 url: https://github.com/Yarous -Pyth3rEx: - login: Pyth3rEx - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4 - url: https://github.com/Pyth3rEx dimaqq: login: dimaqq count: 8 @@ -736,7 +736,7 @@ minaton-ru: sungchan1: login: sungchan1 count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=fadbf24840186aca639d344bb3e0ecf7ff3441cf&v=4 url: https://github.com/sungchan1 Serrones: login: Serrones @@ -761,7 +761,7 @@ anthonycepeda: fabioueno: login: fabioueno count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/14273852?u=edd700982b16317ac6ebfd24c47bc0029b21d360&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/14273852?u=a3d546449cdc96621c32bcc26cf74be6e4390209&v=4 url: https://github.com/fabioueno cfraboulet: login: cfraboulet @@ -793,6 +793,11 @@ Zerohertz: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4 url: https://github.com/Zerohertz +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues deniscapeto: login: deniscapeto count: 6 @@ -1028,11 +1033,6 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 url: https://github.com/11kkw -EdmilsonRodrigues: - login: EdmilsonRodrigues - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 - url: https://github.com/EdmilsonRodrigues lpdswing: login: lpdswing count: 4 @@ -1178,6 +1178,11 @@ SBillion: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/1070649?u=3ab493dfc88b39da0eb1600e3b8e7df1c90a5dee&v=4 url: https://github.com/SBillion +seuthootDev: + login: seuthootDev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/175179350?u=7c2cbc48ab43b52e0c86592111d92e013d72ea4d&v=4 + url: https://github.com/seuthootDev tyronedamasceno: login: tyronedamasceno count: 3 @@ -1266,7 +1271,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=fd8d408946633acc4bea057c207e6c0833871527&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=cba345870d8d6b25dd6d56ee18f7120581e3c573&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan @@ -1593,6 +1598,11 @@ ayr-ton: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4 url: https://github.com/ayr-ton +Kadermiyanyedi: + login: Kadermiyanyedi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4 + url: https://github.com/Kadermiyanyedi raphaelauv: login: raphaelauv count: 2 @@ -1831,7 +1841,7 @@ EgorOnishchuk: iamantonreznik: login: iamantonreznik count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=bf6de9a1ab17326fe14de0709719fff3826526d0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=b9ba8d9b4d3940198bc3a4353dfce70c044a39b1&v=4 url: https://github.com/iamantonreznik Azazul123: login: Azazul123 @@ -1851,7 +1861,7 @@ NavesSapnis: isgin01: login: isgin01 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=ddffde10876b50f35dc90d1337f507a630530a6a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 url: https://github.com/isgin01 syedasamina56: login: syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 940b128da2..dd5900a417 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -8,9 +8,14 @@ jaystone776: count: 46 avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 url: https://github.com/jaystone776 +tiangolo: + login: tiangolo + count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo ceb10n: login: ceb10n - count: 29 + count: 30 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n valentinDruzhinin: @@ -28,11 +33,6 @@ SwftAlpc: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -tiangolo: - login: tiangolo - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo hasansezertasan: login: hasansezertasan count: 22 @@ -43,16 +43,16 @@ waynerv: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv +hard-coders: + login: hard-coders + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 + url: https://github.com/hard-coders AlertRED: login: AlertRED count: 16 avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4 url: https://github.com/AlertRED -hard-coders: - login: hard-coders - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 - url: https://github.com/hard-coders Joao-Pedro-P-Holanda: login: Joao-Pedro-P-Holanda count: 14 @@ -108,6 +108,11 @@ pablocm83: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 url: https://github.com/pablocm83 +YuriiMotov: + login: YuriiMotov + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov ptt3199: login: ptt3199 count: 7 @@ -133,11 +138,6 @@ Alexandrhub: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 url: https://github.com/Alexandrhub -YuriiMotov: - login: YuriiMotov - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 - url: https://github.com/YuriiMotov Serrones: login: Serrones count: 5 @@ -291,7 +291,7 @@ hsuanchi: alejsdev: login: alejsdev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev riroan: login: riroan @@ -361,7 +361,7 @@ Rishat-F: ruzia: login: ruzia count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24503?u=abce66d26c9611818720f11e6ae6773a6e0928f8&v=4 url: https://github.com/ruzia izaguerreiro: login: izaguerreiro @@ -413,6 +413,11 @@ ayr-ton: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4 url: https://github.com/ayr-ton +Kadermiyanyedi: + login: Kadermiyanyedi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4 + url: https://github.com/Kadermiyanyedi KdHyeon0661: login: KdHyeon0661 count: 2 @@ -461,7 +466,7 @@ ArtemKhymenko: hasnatsajid: login: hasnatsajid count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=6668823c3b029bfecf10a8918ed3af1aafb8b15e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86589885?v=4 url: https://github.com/hasnatsajid alperiox: login: alperiox From 779f7ddc37e1e03e199cf5b243e4d5d3c5f7c4e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 10:24:48 +0000 Subject: [PATCH 038/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 699b966966..0fe3eebf97 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* ๐Ÿ‘ฅ Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg). * ๐Ÿ”ง Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo). From 20ff394d7540dd560df1e9252584e3965d59b0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 2 Feb 2026 02:26:58 -0800 Subject: [PATCH 039/367] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#14803)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/topic_repos.yml | 336 +++++++++++++++++------------------ 1 file changed, 168 insertions(+), 168 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index d089c7e5a7..a37cb6dcfd 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,176 +1,181 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 40334 + stars: 41312 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 33628 + stars: 34206 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21817 + stars: 21832 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 20409 + stars: 20661 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 17415 + stars: 17567 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 15776 + stars: 16291 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 15588 + stars: 16132 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal -- name: machine-learning-zoomcamp - html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp - stars: 12447 - owner_login: DataTalksClub - owner_html_url: https://github.com/DataTalksClub - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 12128 + stars: 12723 owner_login: MODSetter owner_html_url: https://github.com/MODSetter +- name: machine-learning-zoomcamp + html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp + stars: 12575 + owner_login: DataTalksClub + owner_html_url: https://github.com/DataTalksClub - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 11326 + stars: 11478 owner_login: tadata-org owner_html_url: https://github.com/tadata-org - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 10901 + stars: 11018 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 9584 + stars: 9938 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier - name: polar html_url: https://github.com/polarsource/polar - stars: 8951 + stars: 9348 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8934 + stars: 8949 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 7934 + stars: 8060 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7248 + stars: 7311 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 6392 + stars: 6479 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5899 + stars: 5970 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: serge html_url: https://github.com/serge-chat/serge - stars: 5754 + stars: 5751 owner_login: serge-chat owner_html_url: https://github.com/serge-chat - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4577 + stars: 4598 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql +- name: devpush + html_url: https://github.com/hunvreus/devpush + stars: 4407 + owner_login: hunvreus + owner_html_url: https://github.com/hunvreus +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 4359 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: poem html_url: https://github.com/poem-web/poem - stars: 4303 + stars: 4337 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4287 + stars: 4279 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4221 + stars: 4244 owner_login: dynaconf owner_html_url: https://github.com/dynaconf -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 4181 - owner_login: remsky - owner_html_url: https://github.com/remsky +- name: Yuxi-Know + html_url: https://github.com/xerrors/Yuxi-Know + stars: 4154 + owner_login: xerrors + owner_html_url: https://github.com/xerrors - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4090 + stars: 4086 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs -- name: devpush - html_url: https://github.com/hunvreus/devpush - stars: 4037 - owner_login: hunvreus - owner_html_url: https://github.com/hunvreus - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3896 + stars: 3975 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3756 + stars: 3797 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3702 + stars: 3785 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor -- name: Yuxi-Know - html_url: https://github.com/xerrors/Yuxi-Know - stars: 3680 - owner_login: xerrors - owner_html_url: https://github.com/xerrors - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3675 + stars: 3731 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3659 + stars: 3697 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3497 + stars: 3506 owner_login: rashadphz owner_html_url: https://github.com/rashadphz - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3421 + stars: 3458 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 3216 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3136 + stars: 3134 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: docarray @@ -180,316 +185,311 @@ owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 3051 + stars: 3072 owner_login: nsidnev owner_html_url: https://github.com/nsidnev -- name: mcp-context-forge - html_url: https://github.com/IBM/mcp-context-forge - stars: 3034 - owner_login: IBM - owner_html_url: https://github.com/IBM - name: uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2904 + stars: 2908 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2680 + stars: 2728 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2662 + stars: 2686 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: YC-Killer html_url: https://github.com/sahibzada-allahyar/YC-Killer - stars: 2614 + stars: 2648 owner_login: sahibzada-allahyar owner_html_url: https://github.com/sahibzada-allahyar - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2587 + stars: 2637 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2566 + stars: 2573 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2456 + stars: 2460 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2394 + stars: 2428 owner_login: supabase owner_html_url: https://github.com/supabase +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2347 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2338 + stars: 2337 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2289 + stars: 2299 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2234 + stars: 2255 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: 30-Days-of-Python - html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2232 - owner_login: codingforentrepreneurs - owner_html_url: https://github.com/codingforentrepreneurs +- name: NoteDiscovery + html_url: https://github.com/gamosoft/NoteDiscovery + stars: 2182 + owner_login: gamosoft + owner_html_url: https://github.com/gamosoft - name: solara html_url: https://github.com/widgetti/solara - stars: 2141 + stars: 2154 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 2046 + stars: 2071 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1963 + stars: 2036 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices -- name: NoteDiscovery - html_url: https://github.com/gamosoft/NoteDiscovery - stars: 1943 - owner_login: gamosoft - owner_html_url: https://github.com/gamosoft -- name: agentkit - html_url: https://github.com/BCG-X-Official/agentkit - stars: 1936 - owner_login: BCG-X-Official - owner_html_url: https://github.com/BCG-X-Official - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1909 + stars: 1983 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao -- name: manage-fastapi - html_url: https://github.com/ycd/manage-fastapi - stars: 1887 - owner_login: ycd - owner_html_url: https://github.com/ycd +- name: agentkit + html_url: https://github.com/BCG-X-Official/agentkit + stars: 1941 + owner_login: BCG-X-Official + owner_html_url: https://github.com/BCG-X-Official +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1920 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1879 + stars: 1900 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators +- name: manage-fastapi + html_url: https://github.com/ycd/manage-fastapi + stars: 1894 + owner_login: ycd + owner_html_url: https://github.com/ycd - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1845 + stars: 1891 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1843 + stars: 1854 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm +- name: fastapi-cache + html_url: https://github.com/long2ice/fastapi-cache + stars: 1816 + owner_login: long2ice + owner_html_url: https://github.com/long2ice - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 stars: 1813 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: fastapi-cache - html_url: https://github.com/long2ice/fastapi-cache - stars: 1805 - owner_login: long2ice - owner_html_url: https://github.com/long2ice - name: ormar html_url: https://github.com/collerek/ormar - stars: 1785 + stars: 1797 owner_login: collerek owner_html_url: https://github.com/collerek -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 1780 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 - name: FastAPI-boilerplate html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1734 + stars: 1792 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: termpair html_url: https://github.com/cs01/termpair - stars: 1724 + stars: 1727 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1671 + stars: 1677 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1633 + stars: 1634 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1588 + stars: 1607 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1583 + stars: 1592 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: coronavirus-tracker-api - html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1571 - owner_login: ExpDev07 - owner_html_url: https://github.com/ExpDev07 - name: bracket html_url: https://github.com/evroon/bracket - stars: 1549 + stars: 1580 owner_login: evroon owner_html_url: https://github.com/evroon +- name: coronavirus-tracker-api + html_url: https://github.com/ExpDev07/coronavirus-tracker-api + stars: 1570 + owner_login: ExpDev07 + owner_html_url: https://github.com/ExpDev07 - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1491 + stars: 1512 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: fastapi-boilerplate - html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1452 - owner_login: teamhide - owner_html_url: https://github.com/teamhide - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1452 + stars: 1471 owner_login: benavlabs owner_html_url: https://github.com/benavlabs +- name: fastapi-boilerplate + html_url: https://github.com/teamhide/fastapi-boilerplate + stars: 1461 + owner_login: teamhide + owner_html_url: https://github.com/teamhide - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1430 + stars: 1435 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1399 + stars: 1417 owner_login: trallnag owner_html_url: https://github.com/trallnag - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1371 + stars: 1382 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: fastapi-scaff + html_url: https://github.com/atpuxiner/fastapi-scaff + stars: 1367 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1346 + stars: 1360 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1345 + stars: 1343 owner_login: ebhy owner_html_url: https://github.com/ebhy -- name: fastapi-scaff - html_url: https://github.com/atpuxiner/fastapi-scaff - stars: 1331 - owner_login: atpuxiner - owner_html_url: https://github.com/atpuxiner - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1266 + stars: 1276 owner_login: slackapi owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1266 + stars: 1268 owner_login: aws-samples owner_html_url: https://github.com/aws-samples - name: fastapi-alembic-sqlmodel-async - html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1260 - owner_login: jonra1993 - owner_html_url: https://github.com/jonra1993 + html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async + stars: 1265 + owner_login: vargasjona + owner_html_url: https://github.com/vargasjona - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1222 + stars: 1227 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1179 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai - name: restish html_url: https://github.com/rest-sh/restish - stars: 1152 + stars: 1200 owner_login: rest-sh owner_html_url: https://github.com/rest-sh +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1183 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1143 + stars: 1162 owner_login: art049 owner_html_url: https://github.com/art049 -- name: authx - html_url: https://github.com/yezz123/authx - stars: 1128 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 -- name: SAG - html_url: https://github.com/Zleap-AI/SAG - stars: 1104 - owner_login: Zleap-AI - owner_html_url: https://github.com/Zleap-AI - name: aktools html_url: https://github.com/akfamily/aktools - stars: 1072 + stars: 1155 owner_login: akfamily owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 1063 + stars: 1155 owner_login: insistence owner_html_url: https://github.com/insistence +- name: authx + html_url: https://github.com/yezz123/authx + stars: 1142 + owner_login: yezz123 + owner_html_url: https://github.com/yezz123 +- name: SAG + html_url: https://github.com/Zleap-AI/SAG + stars: 1110 + owner_login: Zleap-AI + owner_html_url: https://github.com/Zleap-AI - name: flock html_url: https://github.com/Onelevenvy/flock - stars: 1059 + stars: 1069 owner_login: Onelevenvy owner_html_url: https://github.com/Onelevenvy - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 1046 + stars: 1063 owner_login: blueswen owner_html_url: https://github.com/blueswen - name: enterprise-deep-research html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research - stars: 1019 + stars: 1061 owner_login: SalesforceAIResearch owner_html_url: https://github.com/SalesforceAIResearch - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 1016 + stars: 1039 owner_login: developmentseed owner_html_url: https://github.com/developmentseed - name: every-pdf html_url: https://github.com/DDULDDUCK/every-pdf - stars: 1004 + stars: 1017 owner_login: DDULDDUCK owner_html_url: https://github.com/DDULDDUCK - name: autollm html_url: https://github.com/viddexa/autollm - stars: 1003 + stars: 1005 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 996 + stars: 995 owner_login: ajndkr owner_html_url: https://github.com/ajndkr From 6173733200c3498408942a86792871b245dec032 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 10:27:24 +0000 Subject: [PATCH 040/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0fe3eebf97..8f8edd5f62 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* ๐Ÿ‘ฅ Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ฅ Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg). * ๐Ÿ”ง Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo). From b833e53ade85dcb330145ac6e95a5b7c74a78fcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:54:49 +0100 Subject: [PATCH 041/367] =?UTF-8?q?=E2=AC=86=20Bump=20typer=20from=200.16.?= =?UTF-8?q?0=20to=200.21.1=20(#14799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [typer](https://github.com/fastapi/typer) from 0.16.0 to 0.21.1. - [Release notes](https://github.com/fastapi/typer/releases) - [Changelog](https://github.com/fastapi/typer/blob/master/docs/release-notes.md) - [Commits](https://github.com/fastapi/typer/compare/0.16.0...0.21.1) --- updated-dependencies: - dependency-name: typer dependency-version: 0.21.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fe9b3a7ea1..b104eed80c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,7 +147,7 @@ docs = [ "pillow==11.3.0", "python-slugify==8.0.4", "pyyaml>=5.3.1,<7.0.0", - "typer==0.16.0", + "typer==0.21.1", ] docs-tests = [ "httpx>=0.23.0,<1.0.0", diff --git a/uv.lock b/uv.lock index 9ae2220e0c..5cdf5f7679 100644 --- a/uv.lock +++ b/uv.lock @@ -1230,7 +1230,7 @@ dev = [ { name = "ruff", specifier = "==0.14.3" }, { name = "sqlmodel", specifier = "==0.0.27" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, - { name = "typer", specifier = "==0.16.0" }, + { name = "typer", specifier = "==0.21.1" }, { name = "types-orjson", specifier = "==3.6.2" }, { name = "types-ujson", specifier = "==5.10.0.20240515" }, ] @@ -1251,7 +1251,7 @@ docs = [ { name = "python-slugify", specifier = "==8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = "==0.14.3" }, - { name = "typer", specifier = "==0.16.0" }, + { name = "typer", specifier = "==0.21.1" }, ] docs-tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, @@ -4737,7 +4737,7 @@ wheels = [ [[package]] name = "typer" -version = "0.16.0" +version = "0.21.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -4746,9 +4746,9 @@ dependencies = [ { name = "shellingham" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c5/8c/7d682431efca5fd290017663ea4588bf6f2c6aad085c7f108c5dbc316e70/typer-0.16.0.tar.gz", hash = "sha256:af377ffaee1dbe37ae9440cb4e8f11686ea5ce4e9bae01b84ae7c63b87f1dd3b", size = 102625, upload-time = "2025-05-26T14:30:31.824Z" } +sdist = { url = "https://files.pythonhosted.org/packages/36/bf/8825b5929afd84d0dabd606c67cd57b8388cb3ec385f7ef19c5cc2202069/typer-0.21.1.tar.gz", hash = "sha256:ea835607cd752343b6b2b7ce676893e5a0324082268b48f27aa058bdb7d2145d", size = 110371, upload-time = "2026-01-06T11:21:10.989Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/42/3efaf858001d2c2913de7f354563e3a3a2f0decae3efe98427125a8f441e/typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", size = 46317, upload-time = "2025-05-26T14:30:30.523Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/d9257dd49ff2ca23ea5f132edf1281a0c4f9de8a762b9ae399b670a59235/typer-0.21.1-py3-none-any.whl", hash = "sha256:7985e89081c636b88d172c2ee0cfe33c253160994d47bdfdc302defd7d1f1d01", size = 47381, upload-time = "2026-01-06T11:21:09.824Z" }, ] [[package]] From da4083c30fcd1f4e2a4cc4bb5bb286545d124788 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 14:55:12 +0000 Subject: [PATCH 042/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8f8edd5f62..afe456a3fa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot). * ๐Ÿ‘ฅ Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ฅ Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg). From a0e34c747340b5b731a363f6b683fa0d0062ca49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:56:33 +0100 Subject: [PATCH 043/367] =?UTF-8?q?=E2=AC=86=20Bump=20gitpython=20from=203?= =?UTF-8?q?.1.45=20to=203.1.46=20(#14800)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.45 to 3.1.46. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.45...3.1.46) --- updated-dependencies: - dependency-name: gitpython dependency-version: 3.1.46 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b104eed80c..39a6bd155b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -180,7 +180,7 @@ tests = [ "types-ujson==5.10.0.20240515", ] translations = [ - "gitpython==3.1.45", + "gitpython==3.1.46", "pydantic-ai==0.4.10", "pygithub==2.8.1", ] diff --git a/uv.lock b/uv.lock index 5cdf5f7679..f3a5f8e6d9 100644 --- a/uv.lock +++ b/uv.lock @@ -1203,7 +1203,7 @@ dev = [ { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, { name = "dirty-equals", specifier = "==0.9.0" }, { name = "flask", specifier = ">=1.1.2,<4.0.0" }, - { name = "gitpython", specifier = "==3.1.45" }, + { name = "gitpython", specifier = "==3.1.46" }, { name = "griffe-typingdoc", specifier = "==0.3.0" }, { name = "griffe-warnings-deprecated", specifier = "==1.1.0" }, { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, @@ -1285,7 +1285,7 @@ tests = [ { name = "types-ujson", specifier = "==5.10.0.20240515" }, ] translations = [ - { name = "gitpython", specifier = "==3.1.45" }, + { name = "gitpython", specifier = "==3.1.46" }, { name = "pydantic-ai", specifier = "==0.4.10" }, { name = "pygithub", specifier = "==2.8.1" }, ] @@ -1632,15 +1632,15 @@ wheels = [ [[package]] name = "gitpython" -version = "3.1.45" +version = "3.1.46" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "gitdb" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" } +sdist = { url = "https://files.pythonhosted.org/packages/df/b5/59d16470a1f0dfe8c793f9ef56fd3826093fc52b3bd96d6b9d6c26c7e27b/gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", size = 215371, upload-time = "2026-01-01T15:37:32.073Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, + { url = "https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058", size = 208620, upload-time = "2026-01-01T15:37:30.574Z" }, ] [[package]] From f2487ce88c4ae8f7e64668409770427b245c3a60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:57:22 +0100 Subject: [PATCH 044/367] =?UTF-8?q?=E2=AC=86=20Bump=20mkdocs-macros-plugin?= =?UTF-8?q?=20from=201.4.1=20to=201.5.0=20(#14801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mkdocs-macros-plugin](https://github.com/fralau/mkdocs_macros_plugin) from 1.4.1 to 1.5.0. - [Release notes](https://github.com/fralau/mkdocs_macros_plugin/releases) - [Changelog](https://github.com/fralau/mkdocs-macros-plugin/blob/master/CHANGELOG.md) - [Commits](https://github.com/fralau/mkdocs_macros_plugin/compare/v1.4.1...v1.5.0) --- updated-dependencies: - dependency-name: mkdocs-macros-plugin dependency-version: 1.5.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 39a6bd155b..524d527186 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -140,7 +140,7 @@ docs = [ "jieba==0.42.1", "markdown-include-variants==0.0.8", "mdx-include>=1.4.1,<2.0.0", - "mkdocs-macros-plugin==1.4.1", + "mkdocs-macros-plugin==1.5.0", "mkdocs-material==9.7.0", "mkdocs-redirects>=1.2.1,<1.3.0", "mkdocstrings[python]==0.30.1", diff --git a/uv.lock b/uv.lock index f3a5f8e6d9..312181b4e8 100644 --- a/uv.lock +++ b/uv.lock @@ -1211,7 +1211,7 @@ dev = [ { name = "jieba", specifier = "==0.42.1" }, { name = "markdown-include-variants", specifier = "==0.0.8" }, { name = "mdx-include", specifier = ">=1.4.1,<2.0.0" }, - { name = "mkdocs-macros-plugin", specifier = "==1.4.1" }, + { name = "mkdocs-macros-plugin", specifier = "==1.5.0" }, { name = "mkdocs-material", specifier = "==9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" }, @@ -1243,7 +1243,7 @@ docs = [ { name = "jieba", specifier = "==0.42.1" }, { name = "markdown-include-variants", specifier = "==0.0.8" }, { name = "mdx-include", specifier = ">=1.4.1,<2.0.0" }, - { name = "mkdocs-macros-plugin", specifier = "==1.4.1" }, + { name = "mkdocs-macros-plugin", specifier = "==1.5.0" }, { name = "mkdocs-material", specifier = "==9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" }, @@ -2652,7 +2652,7 @@ wheels = [ [[package]] name = "mkdocs-macros-plugin" -version = "1.4.1" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "hjson" }, @@ -2667,9 +2667,9 @@ dependencies = [ { name = "termcolor", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "termcolor", version = "3.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/42/bb2ceed148c77f82b57c6d3b7f584f0f34ababf7a9a8ff85809380d1f400/mkdocs_macros_plugin-1.4.1.tar.gz", hash = "sha256:55a9c93871e3744cdeb0736316783d60830a6d5d97b1132364e6b491607f2332", size = 35094, upload-time = "2025-10-25T12:37:20.689Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/15/e6a44839841ebc9c5872fa0e6fad1c3757424e4fe026093b68e9f386d136/mkdocs_macros_plugin-1.5.0.tar.gz", hash = "sha256:12aa45ce7ecb7a445c66b9f649f3dd05e9b92e8af6bc65e4acd91d26f878c01f", size = 37730, upload-time = "2025-11-13T08:08:55.545Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/ec/e6e96a7ae8df414f03f43681821234b0d3b86666f7b91f70ab26775a8809/mkdocs_macros_plugin-1.4.1-py3-none-any.whl", hash = "sha256:5a9e483f6056fe7ad0923802affe699233ca468672e20a9640dba237165b3240", size = 40155, upload-time = "2025-10-25T12:37:19.417Z" }, + { url = "https://files.pythonhosted.org/packages/51/62/9fffba5bb9ed3d31a932ad35038ba9483d59850256ee0fea7f1187173983/mkdocs_macros_plugin-1.5.0-py3-none-any.whl", hash = "sha256:c10fabd812bf50f9170609d0ed518e54f1f0e12c334ac29141723a83c881dd6f", size = 44626, upload-time = "2025-11-13T08:08:53.878Z" }, ] [[package]] From 5c3f0307ae475fd0ceeb47aaa2404119f2b6da8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:57:43 +0100 Subject: [PATCH 045/367] =?UTF-8?q?=E2=AC=86=20Bump=20sqlmodel=20from=200.?= =?UTF-8?q?0.27=20to=200.0.31=20(#14802)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sqlmodel](https://github.com/fastapi/sqlmodel) from 0.0.27 to 0.0.31. - [Release notes](https://github.com/fastapi/sqlmodel/releases) - [Changelog](https://github.com/fastapi/sqlmodel/blob/main/docs/release-notes.md) - [Commits](https://github.com/fastapi/sqlmodel/compare/0.0.27...0.0.31) --- updated-dependencies: - dependency-name: sqlmodel dependency-version: 0.0.31 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 524d527186..ef4330a0e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -174,7 +174,7 @@ tests = [ "pytest>=7.1.3,<9.0.0", "pytest-codspeed==4.2.0", "pyyaml>=5.3.1,<7.0.0", - "sqlmodel==0.0.27", + "sqlmodel==0.0.31", "strawberry-graphql>=0.200.0,<1.0.0", "types-orjson==3.6.2", "types-ujson==5.10.0.20240515", diff --git a/uv.lock b/uv.lock index 312181b4e8..8b202e0891 100644 --- a/uv.lock +++ b/uv.lock @@ -1228,7 +1228,7 @@ dev = [ { name = "python-slugify", specifier = "==8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = "==0.14.3" }, - { name = "sqlmodel", specifier = "==0.0.27" }, + { name = "sqlmodel", specifier = "==0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "typer", specifier = "==0.21.1" }, { name = "types-orjson", specifier = "==3.6.2" }, @@ -1279,7 +1279,7 @@ tests = [ { name = "pytest-codspeed", specifier = "==4.2.0" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = "==0.14.3" }, - { name = "sqlmodel", specifier = "==0.0.27" }, + { name = "sqlmodel", specifier = "==0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "types-orjson", specifier = "==3.6.2" }, { name = "types-ujson", specifier = "==5.10.0.20240515" }, @@ -4415,15 +4415,15 @@ wheels = [ [[package]] name = "sqlmodel" -version = "0.0.27" +version = "0.0.31" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "sqlalchemy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/5a/693d90866233e837d182da76082a6d4c2303f54d3aaaa5c78e1238c5d863/sqlmodel-0.0.27.tar.gz", hash = "sha256:ad1227f2014a03905aef32e21428640848ac09ff793047744a73dfdd077ff620", size = 118053, upload-time = "2025-10-08T16:39:11.938Z" } +sdist = { url = "https://files.pythonhosted.org/packages/56/b8/e7cd6def4a773f25d6e29ffce63ccbfd6cf9488b804ab6fb9b80d334b39d/sqlmodel-0.0.31.tar.gz", hash = "sha256:2d41a8a9ee05e40736e2f9db8ea28cbfe9b5d4e5a18dd139e80605025e0c516c", size = 94952, upload-time = "2025-12-28T12:35:01.436Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/92/c35e036151fe53822893979f8a13e6f235ae8191f4164a79ae60a95d66aa/sqlmodel-0.0.27-py3-none-any.whl", hash = "sha256:667fe10aa8ff5438134668228dc7d7a08306f4c5c4c7e6ad3ad68defa0e7aa49", size = 29131, upload-time = "2025-10-08T16:39:10.917Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/5aa5be921800f6418a949a73c9bb7054890881143e6bc604a93d228a95a3/sqlmodel-0.0.31-py3-none-any.whl", hash = "sha256:6d946d56cac4c2db296ba1541357cee2e795d68174e2043cd138b916794b1513", size = 27093, upload-time = "2025-12-28T12:35:00.108Z" }, ] [[package]] From ecb1444738a3315167a8c11eac9b8503aec5a3d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 14:57:46 +0000 Subject: [PATCH 046/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index afe456a3fa..997bd98d5e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot). * ๐Ÿ‘ฅ Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ฅ Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo). From 87b5333e8ae48cd68ef90ac29897bce25bb6540c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 15:00:26 +0000 Subject: [PATCH 047/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 997bd98d5e..7fd3b91786 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot). * ๐Ÿ‘ฅ Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo). From 608ff552ba249c0a6cc8fdf755b43135cd45a9fa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 15:00:28 +0000 Subject: [PATCH 048/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7fd3b91786..fb08caca47 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot). From bc9ad6b1342bd191693942cbcbd0fee954cf1a3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 15:09:12 +0000 Subject: [PATCH 049/367] =?UTF-8?q?=E2=AC=86=20Bump=20pyasn1=20from=200.6.?= =?UTF-8?q?1=20to=200.6.2=20(#14804)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pyasn1](https://github.com/pyasn1/pyasn1) from 0.6.1 to 0.6.2. - [Release notes](https://github.com/pyasn1/pyasn1/releases) - [Changelog](https://github.com/pyasn1/pyasn1/blob/main/CHANGES.rst) - [Commits](https://github.com/pyasn1/pyasn1/compare/v0.6.1...v0.6.2) --- updated-dependencies: - dependency-name: pyasn1 dependency-version: 0.6.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 8b202e0891..3be38bb80f 100644 --- a/uv.lock +++ b/uv.lock @@ -3238,11 +3238,11 @@ argon2 = [ [[package]] name = "pyasn1" -version = "0.6.1" +version = "0.6.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" }, ] [[package]] From 82959de14c755e898c4216b2a2d241801c2606eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 15:09:37 +0000 Subject: [PATCH 050/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fb08caca47..0252730c8f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot). From ec07e62e1c3c054cd3fa0608708103f2acfc3a03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 17:34:26 +0100 Subject: [PATCH 051/367] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20from=200.14.3?= =?UTF-8?q?=20to=200.14.14=20(#14798)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ruff](https://github.com/astral-sh/ruff) from 0.14.3 to 0.14.14. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.14.3...0.14.14) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.14.14 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- pyproject.toml | 2 +- uv.lock | 52 +++++++++++++++++++++++++------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ef4330a0e5..dea61c6a10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -151,7 +151,7 @@ docs = [ ] docs-tests = [ "httpx>=0.23.0,<1.0.0", - "ruff==0.14.3", + "ruff==0.14.14", ] github-actions = [ "httpx>=0.27.0,<1.0.0", diff --git a/uv.lock b/uv.lock index 3be38bb80f..2df0b256b8 100644 --- a/uv.lock +++ b/uv.lock @@ -1227,7 +1227,7 @@ dev = [ { name = "pytest-codspeed", specifier = "==4.2.0" }, { name = "python-slugify", specifier = "==8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.3" }, + { name = "ruff", specifier = "==0.14.14" }, { name = "sqlmodel", specifier = "==0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "typer", specifier = "==0.21.1" }, @@ -1250,12 +1250,12 @@ docs = [ { name = "pillow", specifier = "==11.3.0" }, { name = "python-slugify", specifier = "==8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.3" }, + { name = "ruff", specifier = "==0.14.14" }, { name = "typer", specifier = "==0.21.1" }, ] docs-tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, - { name = "ruff", specifier = "==0.14.3" }, + { name = "ruff", specifier = "==0.14.14" }, ] github-actions = [ { name = "httpx", specifier = ">=0.27.0,<1.0.0" }, @@ -1278,7 +1278,7 @@ tests = [ { name = "pytest", specifier = ">=7.1.3,<9.0.0" }, { name = "pytest-codspeed", specifier = "==4.2.0" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.3" }, + { name = "ruff", specifier = "==0.14.14" }, { name = "sqlmodel", specifier = "==0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "types-orjson", specifier = "==3.6.2" }, @@ -4248,28 +4248,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.14.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/75/62/50b7727004dfe361104dfbf898c45a9a2fdfad8c72c04ae62900224d6ecf/ruff-0.14.3.tar.gz", hash = "sha256:4ff876d2ab2b161b6de0aa1f5bd714e8e9b4033dc122ee006925fbacc4f62153", size = 5558687, upload-time = "2025-10-31T00:26:26.878Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/8e/0c10ff1ea5d4360ab8bfca4cb2c9d979101a391f3e79d2616c9bf348cd26/ruff-0.14.3-py3-none-linux_armv6l.whl", hash = "sha256:876b21e6c824f519446715c1342b8e60f97f93264012de9d8d10314f8a79c371", size = 12535613, upload-time = "2025-10-31T00:25:44.302Z" }, - { url = "https://files.pythonhosted.org/packages/d3/c8/6724f4634c1daf52409fbf13fefda64aa9c8f81e44727a378b7b73dc590b/ruff-0.14.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6fd8c79b457bedd2abf2702b9b472147cd860ed7855c73a5247fa55c9117654", size = 12855812, upload-time = "2025-10-31T00:25:47.793Z" }, - { url = "https://files.pythonhosted.org/packages/de/03/db1bce591d55fd5f8a08bb02517fa0b5097b2ccabd4ea1ee29aa72b67d96/ruff-0.14.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:71ff6edca490c308f083156938c0c1a66907151263c4abdcb588602c6e696a14", size = 11944026, upload-time = "2025-10-31T00:25:49.657Z" }, - { url = "https://files.pythonhosted.org/packages/0b/75/4f8dbd48e03272715d12c87dc4fcaaf21b913f0affa5f12a4e9c6f8a0582/ruff-0.14.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:786ee3ce6139772ff9272aaf43296d975c0217ee1b97538a98171bf0d21f87ed", size = 12356818, upload-time = "2025-10-31T00:25:51.949Z" }, - { url = "https://files.pythonhosted.org/packages/ec/9b/506ec5b140c11d44a9a4f284ea7c14ebf6f8b01e6e8917734a3325bff787/ruff-0.14.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cd6291d0061811c52b8e392f946889916757610d45d004e41140d81fb6cd5ddc", size = 12336745, upload-time = "2025-10-31T00:25:54.248Z" }, - { url = "https://files.pythonhosted.org/packages/c7/e1/c560d254048c147f35e7f8131d30bc1f63a008ac61595cf3078a3e93533d/ruff-0.14.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a497ec0c3d2c88561b6d90f9c29f5ae68221ac00d471f306fa21fa4264ce5fcd", size = 13101684, upload-time = "2025-10-31T00:25:56.253Z" }, - { url = "https://files.pythonhosted.org/packages/a5/32/e310133f8af5cd11f8cc30f52522a3ebccc5ea5bff4b492f94faceaca7a8/ruff-0.14.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e231e1be58fc568950a04fbe6887c8e4b85310e7889727e2b81db205c45059eb", size = 14535000, upload-time = "2025-10-31T00:25:58.397Z" }, - { url = "https://files.pythonhosted.org/packages/a2/a1/7b0470a22158c6d8501eabc5e9b6043c99bede40fa1994cadf6b5c2a61c7/ruff-0.14.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:469e35872a09c0e45fecf48dd960bfbce056b5db2d5e6b50eca329b4f853ae20", size = 14156450, upload-time = "2025-10-31T00:26:00.889Z" }, - { url = "https://files.pythonhosted.org/packages/0a/96/24bfd9d1a7f532b560dcee1a87096332e461354d3882124219bcaff65c09/ruff-0.14.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d6bc90307c469cb9d28b7cfad90aaa600b10d67c6e22026869f585e1e8a2db0", size = 13568414, upload-time = "2025-10-31T00:26:03.291Z" }, - { url = "https://files.pythonhosted.org/packages/a7/e7/138b883f0dfe4ad5b76b58bf4ae675f4d2176ac2b24bdd81b4d966b28c61/ruff-0.14.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2f8a0bbcffcfd895df39c9a4ecd59bb80dca03dc43f7fb63e647ed176b741e", size = 13315293, upload-time = "2025-10-31T00:26:05.708Z" }, - { url = "https://files.pythonhosted.org/packages/33/f4/c09bb898be97b2eb18476b7c950df8815ef14cf956074177e9fbd40b7719/ruff-0.14.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:678fdd7c7d2d94851597c23ee6336d25f9930b460b55f8598e011b57c74fd8c5", size = 13539444, upload-time = "2025-10-31T00:26:08.09Z" }, - { url = "https://files.pythonhosted.org/packages/9c/aa/b30a1db25fc6128b1dd6ff0741fa4abf969ded161599d07ca7edd0739cc0/ruff-0.14.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1ec1ac071e7e37e0221d2f2dbaf90897a988c531a8592a6a5959f0603a1ecf5e", size = 12252581, upload-time = "2025-10-31T00:26:10.297Z" }, - { url = "https://files.pythonhosted.org/packages/da/13/21096308f384d796ffe3f2960b17054110a9c3828d223ca540c2b7cc670b/ruff-0.14.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afcdc4b5335ef440d19e7df9e8ae2ad9f749352190e96d481dc501b753f0733e", size = 12307503, upload-time = "2025-10-31T00:26:12.646Z" }, - { url = "https://files.pythonhosted.org/packages/cb/cc/a350bac23f03b7dbcde3c81b154706e80c6f16b06ff1ce28ed07dc7b07b0/ruff-0.14.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7bfc42f81862749a7136267a343990f865e71fe2f99cf8d2958f684d23ce3dfa", size = 12675457, upload-time = "2025-10-31T00:26:15.044Z" }, - { url = "https://files.pythonhosted.org/packages/cb/76/46346029fa2f2078826bc88ef7167e8c198e58fe3126636e52f77488cbba/ruff-0.14.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a65e448cfd7e9c59fae8cf37f9221585d3354febaad9a07f29158af1528e165f", size = 13403980, upload-time = "2025-10-31T00:26:17.81Z" }, - { url = "https://files.pythonhosted.org/packages/9f/a4/35f1ef68c4e7b236d4a5204e3669efdeefaef21f0ff6a456792b3d8be438/ruff-0.14.3-py3-none-win32.whl", hash = "sha256:f3d91857d023ba93e14ed2d462ab62c3428f9bbf2b4fbac50a03ca66d31991f7", size = 12500045, upload-time = "2025-10-31T00:26:20.503Z" }, - { url = "https://files.pythonhosted.org/packages/03/15/51960ae340823c9859fb60c63301d977308735403e2134e17d1d2858c7fb/ruff-0.14.3-py3-none-win_amd64.whl", hash = "sha256:d7b7006ac0756306db212fd37116cce2bd307e1e109375e1c6c106002df0ae5f", size = 13594005, upload-time = "2025-10-31T00:26:22.533Z" }, - { url = "https://files.pythonhosted.org/packages/b7/73/4de6579bac8e979fca0a77e54dec1f1e011a0d268165eb8a9bc0982a6564/ruff-0.14.3-py3-none-win_arm64.whl", hash = "sha256:26eb477ede6d399d898791d01961e16b86f02bc2486d0d1a7a9bb2379d055dc1", size = 12590017, upload-time = "2025-10-31T00:26:24.52Z" }, +version = "0.14.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" }, + { url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" }, + { url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" }, + { url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" }, + { url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" }, + { url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" }, + { url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" }, + { url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" }, + { url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" }, + { url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" }, + { url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" }, ] [[package]] From 2247750d74b26bc212300cdaff9d82a15bf71eca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Feb 2026 16:34:52 +0000 Subject: [PATCH 052/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0252730c8f..e009de8a09 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* โฌ† Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot). From f3f498100f1d0edc344e200b215d42a6e46473fd Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:08:08 +0300 Subject: [PATCH 053/367] =?UTF-8?q?=F0=9F=91=B7=20Run=20mypy=20by=20pre-co?= =?UTF-8?q?mmit=20(#14806)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastiรกn Ramรญrez --- .pre-commit-config.yaml | 7 +++++++ fastapi/_compat/v2.py | 8 ++++---- fastapi/dependencies/utils.py | 4 ++-- fastapi/utils.py | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d88b70b7b6..64b84bfbd2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,6 +30,13 @@ repos: language: unsupported types: [python] + - id: local-mypy + name: mypy check + entry: uv run mypy fastapi + require_serial: true + language: unsupported + pass_filenames: false + - id: add-permalinks-pages language: unsupported name: add-permalinks-pages diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 25b6814536..dae78a32e0 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -477,7 +477,7 @@ def get_model_fields(model: type[BaseModel]) -> list[ModelField]: @lru_cache def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]: - return get_model_fields(model) # type: ignore[return-value] + return get_model_fields(model) # Duplicate of several schema functions from Pydantic v1 to make them compatible with @@ -500,13 +500,13 @@ def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap: - all_flat_models = set() + all_flat_models: TypeModelSet = set() v2_model_fields = [field for field in fields if isinstance(field, ModelField)] v2_flat_models = get_flat_models_from_fields(v2_model_fields, known_models=set()) - all_flat_models = all_flat_models.union(v2_flat_models) # type: ignore[arg-type] + all_flat_models = all_flat_models.union(v2_flat_models) - model_name_map = get_model_name_map(all_flat_models) # type: ignore[arg-type] + model_name_map = get_model_name_map(all_flat_models) return model_name_map diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 45e1ff3ed1..2afc734ba4 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -399,7 +399,7 @@ def analyze_param( if isinstance(fastapi_annotation, FieldInfo): # Copy `field_info` because we mutate `field_info.default` below. field_info = copy_field_info( - field_info=fastapi_annotation, # type: ignore[arg-type] + field_info=fastapi_annotation, annotation=use_annotation, ) assert ( @@ -433,7 +433,7 @@ def analyze_param( "Cannot specify FastAPI annotations in `Annotated` and default value" f" together for {param_name!r}" ) - field_info = value # type: ignore[assignment] + field_info = value if isinstance(field_info, FieldInfo): field_info.annotation = type_annotation diff --git a/fastapi/utils.py b/fastapi/utils.py index 78fdcbb5b4..1c3a0881f7 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -90,7 +90,7 @@ def create_model_field( field_info = field_info or FieldInfo(annotation=type_, default=default, alias=alias) kwargs = {"mode": mode, "name": name, "field_info": field_info} try: - return v2.ModelField(**kwargs) # type: ignore[return-value,arg-type] + return v2.ModelField(**kwargs) # type: ignore[arg-type] except PydanticSchemaGenerationError: raise fastapi.exceptions.FastAPIError( _invalid_args_message.format(type_=type_) From eacbce24c9d299c6a28110d9fc8ac50f53cddb08 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 3 Feb 2026 18:08:36 +0000 Subject: [PATCH 054/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e009de8a09..ebf3a348f5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* ๐Ÿ‘ท Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov). * โฌ† Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot). From 7621a3aa4b29713aa2ce0ab9605a008a5a8b9335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 03:46:32 -0800 Subject: [PATCH 055/367] =?UTF-8?q?=F0=9F=91=B7=20Run=20tests=20only=20on?= =?UTF-8?q?=20relevant=20code=20changes=20(not=20on=20docs)=20(#14813)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 891f767175..5cbbde61fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,35 @@ env: UV_NO_SYNC: true jobs: + changes: + runs-on: ubuntu-latest + # Required permissions + permissions: + pull-requests: read + # Set job outputs to values from filter step + outputs: + src: ${{ steps.filter.outputs.src }} + steps: + - uses: actions/checkout@v6 + # For pull requests it's not necessary to checkout the code but for the main branch it is + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + src: + - .github/workflows/test.yml + - docs_src/** + - fastapi/** + - scripts/** + - tests/** + - .python-version + - pyproject.toml + - uv.lock + test: + needs: + - changes + if: needs.changes.outputs.src == 'true' strategy: matrix: os: [ windows-latest, macos-latest ] @@ -91,7 +119,8 @@ jobs: include-hidden-files: true coverage-combine: - needs: [test] + needs: + - test runs-on: ubuntu-latest steps: - name: Dump GitHub context @@ -143,3 +172,4 @@ jobs: uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} + allowed-skips: coverage-combine,test From dd780f8caa13e3fa755cfabbec0e603f485cae97 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 11:46:55 +0000 Subject: [PATCH 056/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ebf3a348f5..85c1128fcc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* ๐Ÿ‘ท Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov). * โฌ† Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot). From 261736ab4c3d7a3ec642071ba6f9408ebf9618d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 03:49:00 -0800 Subject: [PATCH 057/367] =?UTF-8?q?=F0=9F=92=A1=20Update=20comment=20for?= =?UTF-8?q?=20Pydantic=20internals=20(#14814)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/shared.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py index 419b58f7f2..68b9bbdf1e 100644 --- a/fastapi/_compat/shared.py +++ b/fastapi/_compat/shared.py @@ -17,7 +17,7 @@ from pydantic.version import VERSION as PYDANTIC_VERSION from starlette.datastructures import UploadFile from typing_extensions import get_args, get_origin -# Copy from Pydantic v2, compatible with v1 +# Copy from Pydantic: pydantic/_internal/_typing_extra.py if sys.version_info < (3, 10): WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # type: ignore[attr-defined] else: @@ -45,7 +45,7 @@ sequence_types = tuple(sequence_annotation_to_type.keys()) Url: type[Any] -# Copy of Pydantic v2, compatible with v1 +# Copy of Pydantic: pydantic/_internal/_utils.py def lenient_issubclass( cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None] ) -> bool: From 573c593dd04365f0d1dddde2e167851f6d19cef7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 11:49:22 +0000 Subject: [PATCH 058/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 85c1128fcc..20af681fd9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* ๐Ÿ’ก Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo). + ### Docs * ๐Ÿ“ Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). From dc3278654f13614d255edca66954326966f6620d Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:54:23 +0300 Subject: [PATCH 059/367] =?UTF-8?q?=F0=9F=93=9D=20Use=20`WSGIMiddleware`?= =?UTF-8?q?=20from=20`a2wsgi`=20instead=20of=20deprecated=20`fastapi.middl?= =?UTF-8?q?eware.wsgi.WSGIMiddleware`=20(#14756)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/advanced/wsgi.md | 20 ++++++++++++++++++-- docs/en/docs/reference/middleware.md | 8 -------- docs_src/wsgi/tutorial001_py39.py | 2 +- fastapi/middleware/wsgi.py | 4 +++- pyproject.toml | 2 +- uv.lock | 16 ++++++++++++++++ 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md index 07147df0a8..aa68617cf4 100644 --- a/docs/en/docs/advanced/wsgi.md +++ b/docs/en/docs/advanced/wsgi.md @@ -6,13 +6,29 @@ For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI applicat ## Using `WSGIMiddleware` { #using-wsgimiddleware } -You need to import `WSGIMiddleware`. +/// info + +This requires installing `a2wsgi` for example with `pip install a2wsgi`. + +/// + +You need to import `WSGIMiddleware` from `a2wsgi`. Then wrap the WSGI (e.g. Flask) app with the middleware. And then mount that under a path. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note + +Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated. + +Itโ€™s advised to use the `a2wsgi` package instead. The usage remains the same. + +Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`. + +/// ## Check it { #check-it } diff --git a/docs/en/docs/reference/middleware.md b/docs/en/docs/reference/middleware.md index 3c666ccdaa..48ff85158d 100644 --- a/docs/en/docs/reference/middleware.md +++ b/docs/en/docs/reference/middleware.md @@ -35,11 +35,3 @@ It can be imported from `fastapi`: ```python from fastapi.middleware.trustedhost import TrustedHostMiddleware ``` - -::: fastapi.middleware.wsgi.WSGIMiddleware - -It can be imported from `fastapi`: - -```python -from fastapi.middleware.wsgi import WSGIMiddleware -``` diff --git a/docs_src/wsgi/tutorial001_py39.py b/docs_src/wsgi/tutorial001_py39.py index 7f27a85a19..8eeceb829e 100644 --- a/docs_src/wsgi/tutorial001_py39.py +++ b/docs_src/wsgi/tutorial001_py39.py @@ -1,5 +1,5 @@ +from a2wsgi import WSGIMiddleware from fastapi import FastAPI -from fastapi.middleware.wsgi import WSGIMiddleware from flask import Flask, request from markupsafe import escape diff --git a/fastapi/middleware/wsgi.py b/fastapi/middleware/wsgi.py index c4c6a797d2..69e4dcab96 100644 --- a/fastapi/middleware/wsgi.py +++ b/fastapi/middleware/wsgi.py @@ -1 +1,3 @@ -from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa +from starlette.middleware.wsgi import ( + WSGIMiddleware as WSGIMiddleware, +) # pragma: no cover # noqa diff --git a/pyproject.toml b/pyproject.toml index dea61c6a10..0f6bf1e4ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -178,6 +178,7 @@ tests = [ "strawberry-graphql>=0.200.0,<1.0.0", "types-orjson==3.6.2", "types-ujson==5.10.0.20240515", + "a2wsgi>=1.9.0,<=2.0.0", ] translations = [ "gitpython==3.1.46", @@ -231,7 +232,6 @@ xfail_strict = true junit_family = "xunit2" filterwarnings = [ "error", - 'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', # see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28 "ignore:You seem to already have a custom.*:RuntimeWarning:trio", # TODO: remove after upgrading SQLAlchemy to a version that includes the following changes diff --git a/uv.lock b/uv.lock index 2df0b256b8..931a27021b 100644 --- a/uv.lock +++ b/uv.lock @@ -7,6 +7,18 @@ resolution-markers = [ "python_full_version < '3.10'", ] +[[package]] +name = "a2wsgi" +version = "1.10.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/cb/822c56fbea97e9eee201a2e434a80437f6750ebcb1ed307ee3a0a7505b14/a2wsgi-1.10.10.tar.gz", hash = "sha256:a5bcffb52081ba39df0d5e9a884fc6f819d92e3a42389343ba77cbf809fe1f45", size = 18799, upload-time = "2025-06-18T09:00:10.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/d5/349aba3dc421e73cbd4958c0ce0a4f1aa3a738bc0d7de75d2f40ed43a535/a2wsgi-1.10.10-py3-none-any.whl", hash = "sha256:d2b21379479718539dc15fce53b876251a0efe7615352dfe49f6ad1bc507848d", size = 17389, upload-time = "2025-06-18T09:00:09.676Z" }, +] + [[package]] name = "ag-ui-protocol" version = "0.1.10" @@ -1058,6 +1070,7 @@ standard-no-fastapi-cloud-cli = [ [package.dev-dependencies] dev = [ + { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, { name = "black" }, { name = "cairosvg" }, @@ -1131,6 +1144,7 @@ github-actions = [ { name = "smokeshow" }, ] tests = [ + { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, { name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, @@ -1197,6 +1211,7 @@ provides-extras = ["standard", "standard-no-fastapi-cloud-cli", "all"] [package.metadata.requires-dev] dev = [ + { name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "black", specifier = "==25.1.0" }, { name = "cairosvg", specifier = "==2.8.2" }, @@ -1266,6 +1281,7 @@ github-actions = [ { name = "smokeshow", specifier = ">=0.5.0" }, ] tests = [ + { name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, { name = "dirty-equals", specifier = "==0.9.0" }, From e3a66494c91c0dc4fc423d812c5bf04795358e03 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 11:54:46 +0000 Subject: [PATCH 060/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 20af681fd9..8fc6e86216 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ๐Ÿ“ Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). * ๐Ÿ› Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier). * ๐Ÿ“ Add contribution instructions about LLM generated code and comments and automated tools for PRs. PR [#14706](https://github.com/fastapi/fastapi/pull/14706) by [@tiangolo](https://github.com/tiangolo). From 27b91d4ad606876a06f25ea82c989374d54311fd Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:05:19 +0300 Subject: [PATCH 061/367] =?UTF-8?q?=F0=9F=94=A8=20Update=20translation=20s?= =?UTF-8?q?cript=20to=20retry=20if=20LLM-response=20doesn't=20pass=20valid?= =?UTF-8?q?ation=20with=20Translation=20Fixer=20tool=20(#14749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- scripts/translate.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index eba4ad6a2f..9eda7b3903 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -10,6 +10,7 @@ from typing import Annotated import git import typer import yaml +from doc_parsing_utils import check_translation from github import Github from pydantic_ai import Agent from rich import print @@ -119,9 +120,30 @@ def translate_page( ] ) prompt = "\n\n".join(prompt_segments) - print(f"Running agent for {out_path}") - result = agent.run_sync(prompt) - out_content = f"{result.output.strip()}\n" + + MAX_ATTEMPTS = 3 + for attempt_no in range(1, MAX_ATTEMPTS + 1): + print(f"Running agent for {out_path} (attempt {attempt_no}/{MAX_ATTEMPTS})") + result = agent.run_sync(prompt) + out_content = f"{result.output.strip()}\n" + try: + check_translation( + doc_lines=out_content.splitlines(), + en_doc_lines=original_content.splitlines(), + lang_code=language, + auto_fix=False, + path=str(out_path), + ) + break # Exit loop if no errors + except ValueError as e: + print( + f"Translation check failed on attempt {attempt_no}/{MAX_ATTEMPTS}: {e}" + ) + continue # Retry if not reached max attempts + else: # Max retry attempts reached + print(f"Translation failed for {out_path} after {MAX_ATTEMPTS} attempts") + raise typer.Exit(code=1) + print(f"Saving translation to {out_path}") out_path.write_text(out_content, encoding="utf-8", newline="\n") From f6ba0141f4736fb78ec80e509634be8d505ae768 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 12:05:41 +0000 Subject: [PATCH 062/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8fc6e86216..30704f3e52 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Internal +* ๐Ÿ”จ Update translation script to retry if LLM-response doesn't pass validation with Translation Fixer tool. PR [#14749](https://github.com/fastapi/fastapi/pull/14749) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov). * โฌ† Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot). From 741c7345eaecbeedd3ea83f6e7d1048b33ce332b Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:07:26 +0300 Subject: [PATCH 063/367] =?UTF-8?q?=F0=9F=93=9D=20Use=20return=20type=20an?= =?UTF-8?q?notation=20instead=20of=20`response=5Fmodel`=20when=20possible?= =?UTF-8?q?=20(#14753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/path-operation-configuration.md | 4 ++-- docs_src/app_testing/app_b_an_py310/main.py | 4 ++-- docs_src/app_testing/app_b_an_py39/main.py | 4 ++-- docs_src/app_testing/app_b_py310/main.py | 4 ++-- docs_src/app_testing/app_b_py39/main.py | 4 ++-- docs_src/body_updates/tutorial002_py310.py | 4 ++-- docs_src/body_updates/tutorial002_py39.py | 4 ++-- .../tutorial004_py310.py | 4 ++-- .../path_operation_advanced_configuration/tutorial004_py39.py | 4 ++-- docs_src/path_operation_configuration/tutorial001_py310.py | 4 ++-- docs_src/path_operation_configuration/tutorial001_py39.py | 4 ++-- docs_src/path_operation_configuration/tutorial002_py310.py | 4 ++-- docs_src/path_operation_configuration/tutorial002_py39.py | 4 ++-- docs_src/path_operation_configuration/tutorial003_py310.py | 3 +-- docs_src/path_operation_configuration/tutorial003_py39.py | 3 +-- docs_src/path_operation_configuration/tutorial004_py310.py | 4 ++-- docs_src/path_operation_configuration/tutorial004_py39.py | 4 ++-- docs_src/path_operation_configuration/tutorial005_py310.py | 3 +-- docs_src/path_operation_configuration/tutorial005_py39.py | 3 +-- docs_src/security/tutorial004_an_py310.py | 4 ++-- docs_src/security/tutorial004_an_py39.py | 4 ++-- docs_src/security/tutorial004_py310.py | 4 ++-- docs_src/security/tutorial004_py39.py | 4 ++-- docs_src/security/tutorial005_an_py310.py | 4 ++-- docs_src/security/tutorial005_an_py39.py | 4 ++-- docs_src/security/tutorial005_py310.py | 4 ++-- docs_src/security/tutorial005_py39.py | 4 ++-- 27 files changed, 50 insertions(+), 54 deletions(-) diff --git a/docs/en/docs/tutorial/path-operation-configuration.md b/docs/en/docs/tutorial/path-operation-configuration.md index 59be5ab376..1bb7ee5544 100644 --- a/docs/en/docs/tutorial/path-operation-configuration.md +++ b/docs/en/docs/tutorial/path-operation-configuration.md @@ -52,7 +52,7 @@ In these cases, it could make sense to store the tags in an `Enum`. You can add a `summary` and `description`: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## Description from docstring { #description-from-docstring } @@ -70,7 +70,7 @@ It will be used in the interactive docs: You can specify the response description with the parameter `response_description`: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info diff --git a/docs_src/app_testing/app_b_an_py310/main.py b/docs_src/app_testing/app_b_an_py310/main.py index c5952be0b3..120289f56d 100644 --- a/docs_src/app_testing/app_b_an_py310/main.py +++ b/docs_src/app_testing/app_b_an_py310/main.py @@ -28,8 +28,8 @@ async def read_main(item_id: str, x_token: Annotated[str, Header()]): return fake_db[item_id] -@app.post("/items/", response_model=Item) -async def create_item(item: Item, x_token: Annotated[str, Header()]): +@app.post("/items/") +async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item: if x_token != fake_secret_token: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: diff --git a/docs_src/app_testing/app_b_an_py39/main.py b/docs_src/app_testing/app_b_an_py39/main.py index 142e23a26a..801d5f21ea 100644 --- a/docs_src/app_testing/app_b_an_py39/main.py +++ b/docs_src/app_testing/app_b_an_py39/main.py @@ -28,8 +28,8 @@ async def read_main(item_id: str, x_token: Annotated[str, Header()]): return fake_db[item_id] -@app.post("/items/", response_model=Item) -async def create_item(item: Item, x_token: Annotated[str, Header()]): +@app.post("/items/") +async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item: if x_token != fake_secret_token: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: diff --git a/docs_src/app_testing/app_b_py310/main.py b/docs_src/app_testing/app_b_py310/main.py index eccedcc7ce..6c5c341308 100644 --- a/docs_src/app_testing/app_b_py310/main.py +++ b/docs_src/app_testing/app_b_py310/main.py @@ -26,8 +26,8 @@ async def read_main(item_id: str, x_token: str = Header()): return fake_db[item_id] -@app.post("/items/", response_model=Item) -async def create_item(item: Item, x_token: str = Header()): +@app.post("/items/") +async def create_item(item: Item, x_token: str = Header()) -> Item: if x_token != fake_secret_token: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: diff --git a/docs_src/app_testing/app_b_py39/main.py b/docs_src/app_testing/app_b_py39/main.py index 45a1033783..89053c432c 100644 --- a/docs_src/app_testing/app_b_py39/main.py +++ b/docs_src/app_testing/app_b_py39/main.py @@ -28,8 +28,8 @@ async def read_main(item_id: str, x_token: str = Header()): return fake_db[item_id] -@app.post("/items/", response_model=Item) -async def create_item(item: Item, x_token: str = Header()): +@app.post("/items/") +async def create_item(item: Item, x_token: str = Header()) -> Item: if x_token != fake_secret_token: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: diff --git a/docs_src/body_updates/tutorial002_py310.py b/docs_src/body_updates/tutorial002_py310.py index e5db711108..d30e41027c 100644 --- a/docs_src/body_updates/tutorial002_py310.py +++ b/docs_src/body_updates/tutorial002_py310.py @@ -25,8 +25,8 @@ async def read_item(item_id: str): return items[item_id] -@app.patch("/items/{item_id}", response_model=Item) -async def update_item(item_id: str, item: Item): +@app.patch("/items/{item_id}") +async def update_item(item_id: str, item: Item) -> Item: stored_item_data = items[item_id] stored_item_model = Item(**stored_item_data) update_data = item.model_dump(exclude_unset=True) diff --git a/docs_src/body_updates/tutorial002_py39.py b/docs_src/body_updates/tutorial002_py39.py index eddd7af716..3714b5a55d 100644 --- a/docs_src/body_updates/tutorial002_py39.py +++ b/docs_src/body_updates/tutorial002_py39.py @@ -27,8 +27,8 @@ async def read_item(item_id: str): return items[item_id] -@app.patch("/items/{item_id}", response_model=Item) -async def update_item(item_id: str, item: Item): +@app.patch("/items/{item_id}") +async def update_item(item_id: str, item: Item) -> Item: stored_item_data = items[item_id] stored_item_model = Item(**stored_item_data) update_data = item.model_dump(exclude_unset=True) diff --git a/docs_src/path_operation_advanced_configuration/tutorial004_py310.py b/docs_src/path_operation_advanced_configuration/tutorial004_py310.py index a815a564b7..f222b11dc6 100644 --- a/docs_src/path_operation_advanced_configuration/tutorial004_py310.py +++ b/docs_src/path_operation_advanced_configuration/tutorial004_py310.py @@ -12,8 +12,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, summary="Create an item") -async def create_item(item: Item): +@app.post("/items/", summary="Create an item") +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/path_operation_advanced_configuration/tutorial004_py39.py b/docs_src/path_operation_advanced_configuration/tutorial004_py39.py index d5fe6705ca..8fabe7cb80 100644 --- a/docs_src/path_operation_advanced_configuration/tutorial004_py39.py +++ b/docs_src/path_operation_advanced_configuration/tutorial004_py39.py @@ -14,8 +14,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, summary="Create an item") -async def create_item(item: Item): +@app.post("/items/", summary="Create an item") +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/path_operation_configuration/tutorial001_py310.py b/docs_src/path_operation_configuration/tutorial001_py310.py index da078fdf58..2e7488ea4f 100644 --- a/docs_src/path_operation_configuration/tutorial001_py310.py +++ b/docs_src/path_operation_configuration/tutorial001_py310.py @@ -12,6 +12,6 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED) -async def create_item(item: Item): +@app.post("/items/", status_code=status.HTTP_201_CREATED) +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial001_py39.py b/docs_src/path_operation_configuration/tutorial001_py39.py index a9dcbf3898..09b3182821 100644 --- a/docs_src/path_operation_configuration/tutorial001_py39.py +++ b/docs_src/path_operation_configuration/tutorial001_py39.py @@ -14,6 +14,6 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED) -async def create_item(item: Item): +@app.post("/items/", status_code=status.HTTP_201_CREATED) +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial002_py310.py b/docs_src/path_operation_configuration/tutorial002_py310.py index 9a8af54327..59908ed7c8 100644 --- a/docs_src/path_operation_configuration/tutorial002_py310.py +++ b/docs_src/path_operation_configuration/tutorial002_py310.py @@ -12,8 +12,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, tags=["items"]) -async def create_item(item: Item): +@app.post("/items/", tags=["items"]) +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial002_py39.py b/docs_src/path_operation_configuration/tutorial002_py39.py index e7ced7de7e..fca3b0de9e 100644 --- a/docs_src/path_operation_configuration/tutorial002_py39.py +++ b/docs_src/path_operation_configuration/tutorial002_py39.py @@ -14,8 +14,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, tags=["items"]) -async def create_item(item: Item): +@app.post("/items/", tags=["items"]) +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial003_py310.py b/docs_src/path_operation_configuration/tutorial003_py310.py index 3d94afe2c0..56bd7e36aa 100644 --- a/docs_src/path_operation_configuration/tutorial003_py310.py +++ b/docs_src/path_operation_configuration/tutorial003_py310.py @@ -14,9 +14,8 @@ class Item(BaseModel): @app.post( "/items/", - response_model=Item, summary="Create an item", description="Create an item with all the information, name, description, price, tax and a set of unique tags", ) -async def create_item(item: Item): +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial003_py39.py b/docs_src/path_operation_configuration/tutorial003_py39.py index 607c5707e6..a77fb34d89 100644 --- a/docs_src/path_operation_configuration/tutorial003_py39.py +++ b/docs_src/path_operation_configuration/tutorial003_py39.py @@ -16,9 +16,8 @@ class Item(BaseModel): @app.post( "/items/", - response_model=Item, summary="Create an item", description="Create an item with all the information, name, description, price, tax and a set of unique tags", ) -async def create_item(item: Item): +async def create_item(item: Item) -> Item: return item diff --git a/docs_src/path_operation_configuration/tutorial004_py310.py b/docs_src/path_operation_configuration/tutorial004_py310.py index 4cb8bdd438..44404aa083 100644 --- a/docs_src/path_operation_configuration/tutorial004_py310.py +++ b/docs_src/path_operation_configuration/tutorial004_py310.py @@ -12,8 +12,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, summary="Create an item") -async def create_item(item: Item): +@app.post("/items/", summary="Create an item") +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/path_operation_configuration/tutorial004_py39.py b/docs_src/path_operation_configuration/tutorial004_py39.py index fc25680c5a..31dfbff1d2 100644 --- a/docs_src/path_operation_configuration/tutorial004_py39.py +++ b/docs_src/path_operation_configuration/tutorial004_py39.py @@ -14,8 +14,8 @@ class Item(BaseModel): tags: set[str] = set() -@app.post("/items/", response_model=Item, summary="Create an item") -async def create_item(item: Item): +@app.post("/items/", summary="Create an item") +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/path_operation_configuration/tutorial005_py310.py b/docs_src/path_operation_configuration/tutorial005_py310.py index b176631d84..a4129d600a 100644 --- a/docs_src/path_operation_configuration/tutorial005_py310.py +++ b/docs_src/path_operation_configuration/tutorial005_py310.py @@ -14,11 +14,10 @@ class Item(BaseModel): @app.post( "/items/", - response_model=Item, summary="Create an item", response_description="The created item", ) -async def create_item(item: Item): +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/path_operation_configuration/tutorial005_py39.py b/docs_src/path_operation_configuration/tutorial005_py39.py index ddf29b733d..0a53a8f2dd 100644 --- a/docs_src/path_operation_configuration/tutorial005_py39.py +++ b/docs_src/path_operation_configuration/tutorial005_py39.py @@ -16,11 +16,10 @@ class Item(BaseModel): @app.post( "/items/", - response_model=Item, summary="Create an item", response_description="The created item", ) -async def create_item(item: Item): +async def create_item(item: Item) -> Item: """ Create an item with all the information: diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py index 18ea96bc5c..368c743bf9 100644 --- a/docs_src/security/tutorial004_an_py310.py +++ b/docs_src/security/tutorial004_an_py310.py @@ -133,10 +133,10 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) +@app.get("/users/me/") async def read_users_me( current_user: Annotated[User, Depends(get_current_active_user)], -): +) -> User: return current_user diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py index d3fd29e5a5..73b3d456d1 100644 --- a/docs_src/security/tutorial004_an_py39.py +++ b/docs_src/security/tutorial004_an_py39.py @@ -133,10 +133,10 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) +@app.get("/users/me/") async def read_users_me( current_user: Annotated[User, Depends(get_current_active_user)], -): +) -> User: return current_user diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py index cd1dcff460..8d0785b404 100644 --- a/docs_src/security/tutorial004_py310.py +++ b/docs_src/security/tutorial004_py310.py @@ -130,8 +130,8 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) -async def read_users_me(current_user: User = Depends(get_current_active_user)): +@app.get("/users/me/") +async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: return current_user diff --git a/docs_src/security/tutorial004_py39.py b/docs_src/security/tutorial004_py39.py index 130dc699a0..e67403d5d7 100644 --- a/docs_src/security/tutorial004_py39.py +++ b/docs_src/security/tutorial004_py39.py @@ -131,8 +131,8 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) -async def read_users_me(current_user: User = Depends(get_current_active_user)): +@app.get("/users/me/") +async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: return current_user diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py index df55951c07..fef0ab71ca 100644 --- a/docs_src/security/tutorial005_an_py310.py +++ b/docs_src/security/tutorial005_an_py310.py @@ -160,10 +160,10 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) +@app.get("/users/me/") async def read_users_me( current_user: Annotated[User, Depends(get_current_active_user)], -): +) -> User: return current_user diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py index 983c1c22cf..1aeba688a6 100644 --- a/docs_src/security/tutorial005_an_py39.py +++ b/docs_src/security/tutorial005_an_py39.py @@ -160,10 +160,10 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) +@app.get("/users/me/") async def read_users_me( current_user: Annotated[User, Depends(get_current_active_user)], -): +) -> User: return current_user diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py index d08e2c59f3..412fbf7984 100644 --- a/docs_src/security/tutorial005_py310.py +++ b/docs_src/security/tutorial005_py310.py @@ -159,8 +159,8 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) -async def read_users_me(current_user: User = Depends(get_current_active_user)): +@app.get("/users/me/") +async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: return current_user diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py index 5bde47ef47..32280aa48b 100644 --- a/docs_src/security/tutorial005_py39.py +++ b/docs_src/security/tutorial005_py39.py @@ -160,8 +160,8 @@ async def login_for_access_token( return Token(access_token=access_token, token_type="bearer") -@app.get("/users/me/", response_model=User) -async def read_users_me(current_user: User = Depends(get_current_active_user)): +@app.get("/users/me/") +async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: return current_user From 5083f27e034ee3b1b3dad459bb420596a952e769 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 12:07:48 +0000 Subject: [PATCH 064/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 30704f3e52..819c58897f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ๐Ÿ“ Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). * ๐Ÿ› Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier). From 21b7b0893b43c1ea359a62b0ec74323d533635fb Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:30:47 +0300 Subject: [PATCH 065/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20dependency=20insta?= =?UTF-8?q?llation=20command=20in=20`docs/en/docs/contributing.md`=20(#147?= =?UTF-8?q?57)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index a4d896109b..1505dfd1e9 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -13,7 +13,7 @@ Create a virtual environment and install the required packages with ```console -$ uv sync +$ uv sync --extra all ---> 100% ``` @@ -32,9 +32,9 @@ That way, you don't have to "install" your local version to be able to test ever /// note | Technical Details -This only happens when you install using `uv sync` instead of running `pip install fastapi` directly. +This only happens when you install using `uv sync --extra all` instead of running `pip install fastapi` directly. -That is because `uv sync` will install the local version of FastAPI in "editable" mode by default. +That is because `uv sync --extra all` will install the local version of FastAPI in "editable" mode by default. /// From 938c5f3500f4b052ecb5bf73c7ef9058607bfd31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 12:31:13 +0000 Subject: [PATCH 066/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 819c58897f..926a26a304 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ๐Ÿ“ Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). From 4414286f2c2bfad302dd87637641d635e9a45c00 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:33:07 +0300 Subject: [PATCH 067/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20embedded=20code?= =?UTF-8?q?=20examples=20to=20Python=203.10=20syntax=20(#14758)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++++++------------ docs/en/docs/deployment/docker.md | 4 +--- docs/en/docs/index.md | 18 ++++++------------ docs/en/docs/tutorial/body-multiple-params.md | 7 ++++--- 4 files changed, 17 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 1057b86942..963de51edf 100644 --- a/README.md +++ b/README.md @@ -164,8 +164,6 @@ $ pip install "fastapi[standard]" Create a file `main.py` with: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -177,7 +175,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -186,9 +184,7 @@ def read_item(item_id: int, q: Union[str, None] = None): If your code uses `async` / `await`, use `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -200,7 +196,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -291,9 +287,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request. Declare the body using standard Python types, thanks to Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -303,7 +297,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -312,7 +306,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index 6b71f7360d..7219f3afca 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -145,8 +145,6 @@ There are other formats and tools to define and install package dependencies. * Create a `main.py` file with: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 5eb47c7b32..ff0f4e9d9d 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" Create a file `main.py` with: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): If your code uses `async` / `await`, use `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request. Declare the body using standard Python types, thanks to Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index ed23c81490..bb0c583685 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -103,15 +103,16 @@ Of course, you can also declare additional query parameters whenever you need, a As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do: ```Python -q: Union[str, None] = None +q: str | None = None ``` -Or in Python 3.10 and above: +Or in Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` + For example: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} From c9e512d808de5eb4196aaaf11ceebf0e9500e55b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 12:33:37 +0000 Subject: [PATCH 068/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 926a26a304..d5bc816683 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ๐Ÿ“ Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov). From 3a41403ccda1a727135fec91dea118ad8f2cf50a Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:41:54 +0300 Subject: [PATCH 069/367] =?UTF-8?q?=F0=9F=93=9D=20Add=20links=20to=20relat?= =?UTF-8?q?ed=20sections=20of=20docs=20to=20docstrings=20(#14776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/reference/request.md | 2 + docs/en/docs/reference/response.md | 2 + docs/en/docs/reference/responses.md | 2 + docs/en/docs/reference/security/index.md | 2 + docs/en/docs/reference/websockets.md | 24 +++--- fastapi/applications.py | 7 +- fastapi/exceptions.py | 10 +++ fastapi/openapi/docs.py | 30 ++++++++ fastapi/param_functions.py | 94 +++++++++++++++++++++++- fastapi/security/oauth2.py | 30 ++++++++ 10 files changed, 190 insertions(+), 13 deletions(-) diff --git a/docs/en/docs/reference/request.md b/docs/en/docs/reference/request.md index f1de216424..7994bf8a88 100644 --- a/docs/en/docs/reference/request.md +++ b/docs/en/docs/reference/request.md @@ -2,6 +2,8 @@ You can declare a parameter in a *path operation function* or dependency to be of type `Request` and then you can access the raw request object directly, without any validation, etc. +Read more about it in the [FastAPI docs about using Request directly](https://fastapi.tiangolo.com/advanced/using-request-directly/) + You can import it directly from `fastapi`: ```python diff --git a/docs/en/docs/reference/response.md b/docs/en/docs/reference/response.md index 00cf2c499c..c9085766c9 100644 --- a/docs/en/docs/reference/response.md +++ b/docs/en/docs/reference/response.md @@ -4,6 +4,8 @@ You can declare a parameter in a *path operation function* or dependency to be o You can also use it directly to create an instance of it and return it from your *path operations*. +Read more about it in the [FastAPI docs about returning a custom Response](https://fastapi.tiangolo.com/advanced/response-directly/#returning-a-custom-response) + You can import it directly from `fastapi`: ```python diff --git a/docs/en/docs/reference/responses.md b/docs/en/docs/reference/responses.md index 46f014fcc8..bd57861294 100644 --- a/docs/en/docs/reference/responses.md +++ b/docs/en/docs/reference/responses.md @@ -56,6 +56,8 @@ There are a couple of custom FastAPI response classes, you can use them to optim ## Starlette Responses +You can read more about all of them in the [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/) and in the [Starlette docs about Responses](https://starlette.dev/responses/). + ::: fastapi.responses.FileResponse options: members: diff --git a/docs/en/docs/reference/security/index.md b/docs/en/docs/reference/security/index.md index 9a5c5e15fb..8163aa2df2 100644 --- a/docs/en/docs/reference/security/index.md +++ b/docs/en/docs/reference/security/index.md @@ -28,6 +28,8 @@ from fastapi.security import ( ) ``` +Read more about them in the [FastAPI docs about Security](https://fastapi.tiangolo.com/tutorial/security/). + ## API Key Security Schemes ::: fastapi.security.APIKeyCookie diff --git a/docs/en/docs/reference/websockets.md b/docs/en/docs/reference/websockets.md index 4b7244e080..bd9f438be6 100644 --- a/docs/en/docs/reference/websockets.md +++ b/docs/en/docs/reference/websockets.md @@ -2,6 +2,8 @@ When defining WebSockets, you normally declare a parameter of type `WebSocket` and with it you can read data from the client and send data to it. +Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/) + It is provided directly by Starlette, but you can import it from `fastapi`: ```python @@ -44,16 +46,6 @@ When you want to define dependencies that should be compatible with both HTTP an - send_json - close -When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it. - -You can import it directly form `fastapi`: - -```python -from fastapi import WebSocketDisconnect -``` - -::: fastapi.WebSocketDisconnect - ## WebSockets - additional classes Additional classes for handling WebSockets. @@ -66,4 +58,16 @@ from fastapi.websockets import WebSocketDisconnect, WebSocketState ::: fastapi.websockets.WebSocketDisconnect +When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it. + +You can import it directly form `fastapi`: + +```python +from fastapi import WebSocketDisconnect +``` + +Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/#handling-disconnections-and-multiple-clients) + ::: fastapi.websockets.WebSocketState + +`WebSocketState` is an enumeration of the possible states of a WebSocket connection. diff --git a/fastapi/applications.py b/fastapi/applications.py index 54175cb3b0..340cabfc29 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -672,7 +672,7 @@ class FastAPI(Starlette): in the autogenerated OpenAPI using the `root_path`. Read more about it in the - [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root_path). + [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root-path). **Example** @@ -739,7 +739,7 @@ class FastAPI(Starlette): It will be added to the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#deprecate-a-path-operation). """ ), ] = None, @@ -812,6 +812,9 @@ class FastAPI(Starlette): In this case, there would be two different schemas, one for input and another one for output. + + Read more about it in the + [FastAPI docs about how to separate schemas for input and output](https://fastapi.tiangolo.com/how-to/separate-openapi-schemas) """ ), ] = True, diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index 1a3abd80c2..62b4674de3 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -49,6 +49,9 @@ class HTTPException(StarletteHTTPException): Doc( """ HTTP status code to send to the client. + + Read more about it in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception) """ ), ], @@ -58,6 +61,9 @@ class HTTPException(StarletteHTTPException): """ Any data to be sent to the client in the `detail` key of the JSON response. + + Read more about it in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception) """ ), ] = None, @@ -66,6 +72,10 @@ class HTTPException(StarletteHTTPException): Doc( """ Any headers to send to the client in the response. + + Read more about it in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#add-custom-headers) + """ ), ] = None, diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index 82380f85d9..632cc2c1d9 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -33,6 +33,9 @@ def get_swagger_ui_html( This is normally done automatically by FastAPI using the default URL `/openapi.json`. + + Read more about it in the + [FastAPI docs for Conditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/#conditional-openapi-from-settings-and-env-vars) """ ), ], @@ -41,6 +44,9 @@ def get_swagger_ui_html( Doc( """ The HTML `` content, normally shown in the browser tab. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ], @@ -51,6 +57,9 @@ def get_swagger_ui_html( The URL to use to load the Swagger UI JavaScript. It is normally set to a CDN URL. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js", @@ -61,6 +70,9 @@ def get_swagger_ui_html( The URL to use to load the Swagger UI CSS. It is normally set to a CDN URL. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css", @@ -77,6 +89,9 @@ def get_swagger_ui_html( Doc( """ The OAuth2 redirect URL, it is normally automatically handled by FastAPI. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ] = None, @@ -85,6 +100,9 @@ def get_swagger_ui_html( Doc( """ A dictionary with Swagger UI OAuth2 initialization configurations. + + Read more about the available configuration options in the + [Swagger UI docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). """ ), ] = None, @@ -95,6 +113,9 @@ def get_swagger_ui_html( Configuration parameters for Swagger UI. It defaults to [swagger_ui_default_parameters][fastapi.openapi.docs.swagger_ui_default_parameters]. + + Read more about it in the + [FastAPI docs about how to Configure Swagger UI](https://fastapi.tiangolo.com/how-to/configure-swagger-ui/). """ ), ] = None, @@ -168,6 +189,9 @@ def get_redoc_html( This is normally done automatically by FastAPI using the default URL `/openapi.json`. + + Read more about it in the + [FastAPI docs for Conditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/#conditional-openapi-from-settings-and-env-vars) """ ), ], @@ -176,6 +200,9 @@ def get_redoc_html( Doc( """ The HTML `<title>` content, normally shown in the browser tab. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ], @@ -186,6 +213,9 @@ def get_redoc_html( The URL to use to load the ReDoc JavaScript. It is normally set to a CDN URL. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) """ ), ] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js", diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 0834fd741a..9bd92be4c7 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -79,6 +79,9 @@ def Path( # noqa: N802 Doc( """ Human-readable title. + + Read more about it in the + [FastAPI docs for Path Parameters and Numeric Validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#declare-metadata) """ ), ] = None, @@ -96,6 +99,9 @@ def Path( # noqa: N802 """ Greater than. If set, value must be greater than this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -105,6 +111,9 @@ def Path( # noqa: N802 """ Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -113,6 +122,9 @@ def Path( # noqa: N802 Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -122,6 +134,9 @@ def Path( # noqa: N802 """ Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -213,6 +228,9 @@ def Path( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -343,6 +361,9 @@ def Query( # noqa: N802 Doc( """ Default value if the parameter field is not set. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alternative-old-query-as-the-default-value) """ ), ] = Undefined, @@ -367,6 +388,9 @@ def Query( # noqa: N802 This will be used to extract the data and for the generated OpenAPI. It is particularly useful when you can't use the name you want because it is a Python reserved keyword or similar. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alias-parameters) """ ), ] = None, @@ -402,6 +426,9 @@ def Query( # noqa: N802 Doc( """ Human-readable title. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata) """ ), ] = None, @@ -410,6 +437,9 @@ def Query( # noqa: N802 Doc( """ Human-readable description. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata) """ ), ] = None, @@ -419,6 +449,9 @@ def Query( # noqa: N802 """ Greater than. If set, value must be greater than this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -428,6 +461,9 @@ def Query( # noqa: N802 """ Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -436,6 +472,9 @@ def Query( # noqa: N802 Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -445,6 +484,9 @@ def Query( # noqa: N802 """ Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers. + + Read more about it in the + [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) """ ), ] = None, @@ -453,6 +495,9 @@ def Query( # noqa: N802 Doc( """ Minimum length for strings. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/) """ ), ] = None, @@ -461,6 +506,9 @@ def Query( # noqa: N802 Doc( """ Maximum length for strings. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/) """ ), ] = None, @@ -469,6 +517,9 @@ def Query( # noqa: N802 Doc( """ RegEx pattern for strings. + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#add-regular-expressions """ ), ] = None, @@ -536,6 +587,9 @@ def Query( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -570,6 +624,9 @@ def Query( # noqa: N802 Mark this parameter field as deprecated. It will affect the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#deprecating-parameters) """ ), ] = None, @@ -581,6 +638,9 @@ def Query( # noqa: N802 You probably don't need it, but it's available. This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi """ ), ] = True, @@ -849,6 +909,9 @@ def Header( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -1152,6 +1215,9 @@ def Cookie( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -1477,6 +1543,9 @@ def Body( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -1790,6 +1859,9 @@ def Form( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -2102,6 +2174,9 @@ def File( # noqa: N802 Doc( """ Example values for this field. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) """ ), ] = None, @@ -2215,6 +2290,9 @@ def Depends( # noqa: N802 Don't call it directly, FastAPI will call it for you, just pass the object directly. + + Read more about it in the + [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/) """ ), ] = None, @@ -2230,6 +2308,9 @@ def Depends( # noqa: N802 Set `use_cache` to `False` to disable this behavior and ensure the dependency is called again (if declared more than once) in the same request. + + Read more about it in the + [FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times) """ ), ] = True, @@ -2250,6 +2331,9 @@ def Depends( # noqa: N802 that handles the request (similar to when using `"function"`), but end **after** the response is sent back to the client. So, the dependency function will be executed **around** the **request** and response cycle. + + Read more about it in the + [FastAPI docs for FastAPI Dependencies with yield](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope) """ ), ] = None, @@ -2295,6 +2379,9 @@ def Security( # noqa: N802 Don't call it directly, FastAPI will call it for you, just pass the object directly. + + Read more about it in the + [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/) """ ), ] = None, @@ -2312,7 +2399,9 @@ def Security( # noqa: N802 These scopes are integrated with OpenAPI (and the API docs at `/docs`). So they are visible in the OpenAPI specification. - ) + + Read more about it in the + [FastAPI docs about OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/) """ ), ] = None, @@ -2327,6 +2416,9 @@ def Security( # noqa: N802 Set `use_cache` to `False` to disable this behavior and ensure the dependency is called again (if declared more than once) in the same request. + + Read more about it in the + [FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times) """ ), ] = True, diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index fc49ba1903..58ffc5c762 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -68,6 +68,9 @@ class OAuth2PasswordRequestForm: "password". Nevertheless, this dependency class is permissive and allows not passing it. If you want to enforce it, use instead the `OAuth2PasswordRequestFormStrict` dependency. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ] = None, @@ -78,6 +81,9 @@ class OAuth2PasswordRequestForm: """ `username` string. The OAuth2 spec requires the exact field name `username`. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -88,6 +94,9 @@ class OAuth2PasswordRequestForm: """ `password` string. The OAuth2 spec requires the exact field name `password`. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -112,6 +121,9 @@ class OAuth2PasswordRequestForm: * `users:read` * `profile` * `openid` + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ] = "", @@ -222,6 +234,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): "password". This dependency is strict about it. If you want to be permissive, use instead the `OAuth2PasswordRequestForm` dependency class. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -232,6 +247,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): """ `username` string. The OAuth2 spec requires the exact field name `username`. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -242,6 +260,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): """ `password` string. The OAuth2 spec requires the exact field name `password`. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -266,6 +287,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): * `users:read` * `profile` * `openid` + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ] = "", @@ -423,6 +447,9 @@ class OAuth2PasswordBearer(OAuth2): """ The URL to obtain the OAuth2 token. This would be the *path operation* that has `OAuth2PasswordRequestForm` as a dependency. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ], @@ -442,6 +469,9 @@ class OAuth2PasswordBearer(OAuth2): """ The OAuth2 scopes that would be required by the *path operations* that use this dependency. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). """ ), ] = None, From 6ab68c62b86c5d222659a37cb2abbd4a52136a94 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:42:18 +0000 Subject: [PATCH 070/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d5bc816683..0c7d440490 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ๐Ÿ“ Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov). From 08dad5c69fbeac83616226b4d56b6c79b8683767 Mon Sep 17 00:00:00 2001 From: DJ Melisso <DJMcoder@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:23:08 -0800 Subject: [PATCH 071/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20OpenAPI=20duplicat?= =?UTF-8?q?ion=20of=20`anyOf`=20refs=20for=20app-level=20responses=20with?= =?UTF-8?q?=20specified=20`content`=20and=20`model`=20as=20`Union`=20(#144?= =?UTF-8?q?63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/openapi/utils.py | 3 +- ...itional_responses_union_duplicate_anyof.py | 123 ++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 tests/test_additional_responses_union_duplicate_anyof.py diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 75ff261025..d56027b500 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -1,3 +1,4 @@ +import copy import http.client import inspect import warnings @@ -377,7 +378,7 @@ def get_openapi_path( additional_status_code, additional_response, ) in route.responses.items(): - process_response = additional_response.copy() + process_response = copy.deepcopy(additional_response) process_response.pop("model", None) status_code_key = str(additional_status_code).upper() if status_code_key == "DEFAULT": diff --git a/tests/test_additional_responses_union_duplicate_anyof.py b/tests/test_additional_responses_union_duplicate_anyof.py new file mode 100644 index 0000000000..f5d987ca31 --- /dev/null +++ b/tests/test_additional_responses_union_duplicate_anyof.py @@ -0,0 +1,123 @@ +""" +Regression test: Ensure app-level responses with Union models and content/examples +don't accumulate duplicate $ref entries in anyOf arrays. +See https://github.com/fastapi/fastapi/pull/14463 +""" + +from typing import Union + +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel + + +class ModelA(BaseModel): + a: str + + +class ModelB(BaseModel): + b: str + + +app = FastAPI( + responses={ + 500: { + "model": Union[ModelA, ModelB], + "content": {"application/json": {"examples": {"Case A": {"value": "a"}}}}, + } + } +) + + +@app.get("/route1") +async def route1(): + pass # pragma: no cover + + +@app.get("/route2") +async def route2(): + pass # pragma: no cover + + +client = TestClient(app) + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/route1": { + "get": { + "summary": "Route1", + "operationId": "route1_route1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/ModelA"}, + {"$ref": "#/components/schemas/ModelB"}, + ], + "title": "Response 500 Route1 Route1 Get", + }, + "examples": {"Case A": {"value": "a"}}, + } + }, + }, + }, + } + }, + "/route2": { + "get": { + "summary": "Route2", + "operationId": "route2_route2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/ModelA"}, + {"$ref": "#/components/schemas/ModelB"}, + ], + "title": "Response 500 Route2 Route2 Get", + }, + "examples": {"Case A": {"value": "a"}}, + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "ModelA": { + "properties": {"a": {"type": "string", "title": "A"}}, + "type": "object", + "required": ["a"], + "title": "ModelA", + }, + "ModelB": { + "properties": {"b": {"type": "string", "title": "B"}}, + "type": "object", + "required": ["b"], + "title": "ModelB", + }, + } + }, + } From ca4692a8c6552de17646a4eabed8ea3cafce597b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:23:34 +0000 Subject: [PATCH 072/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0c7d440490..59cf84c863 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* ๐Ÿ› Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). + ### Refactors * ๐Ÿ’ก Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo). From 41352de24c41f3df540ea410696aa2116ab59394 Mon Sep 17 00:00:00 2001 From: Anton <34218036+retwish@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:24:59 +0100 Subject: [PATCH 073/367] =?UTF-8?q?=F0=9F=9A=B8=20Improve=20error=20messag?= =?UTF-8?q?e=20for=20invalid=20query=20parameter=20type=20annotations=20(#?= =?UTF-8?q?14479)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anton.D <anton.dehtiarenko@chdp-tech.net> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/dependencies/utils.py | 2 +- tests/test_invalid_sequence_param.py | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 2afc734ba4..b647818c4b 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -519,7 +519,7 @@ def analyze_param( # For Pydantic v1 and getattr(field, "shape", 1) == 1 ) - ) + ), f"Query parameter {param_name!r} must be one of the supported types" return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) diff --git a/tests/test_invalid_sequence_param.py b/tests/test_invalid_sequence_param.py index 2b8fd059e1..3695344f7a 100644 --- a/tests/test_invalid_sequence_param.py +++ b/tests/test_invalid_sequence_param.py @@ -6,7 +6,10 @@ from pydantic import BaseModel def test_invalid_sequence(): - with pytest.raises(AssertionError): + with pytest.raises( + AssertionError, + match="Query parameter 'q' must be one of the supported types", + ): app = FastAPI() class Item(BaseModel): @@ -18,7 +21,10 @@ def test_invalid_sequence(): def test_invalid_tuple(): - with pytest.raises(AssertionError): + with pytest.raises( + AssertionError, + match="Query parameter 'q' must be one of the supported types", + ): app = FastAPI() class Item(BaseModel): @@ -30,7 +36,10 @@ def test_invalid_tuple(): def test_invalid_dict(): - with pytest.raises(AssertionError): + with pytest.raises( + AssertionError, + match="Query parameter 'q' must be one of the supported types", + ): app = FastAPI() class Item(BaseModel): @@ -42,7 +51,10 @@ def test_invalid_dict(): def test_invalid_simple_dict(): - with pytest.raises(AssertionError): + with pytest.raises( + AssertionError, + match="Query parameter 'q' must be one of the supported types", + ): app = FastAPI() class Item(BaseModel): From 9e0f4ca77ae27798764766fb5dfd48fb15812f86 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:25:27 +0000 Subject: [PATCH 074/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 59cf84c863..0f0b9dd0aa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ๐Ÿšธ Improve error message for invalid query parameter type annotations. PR [#14479](https://github.com/fastapi/fastapi/pull/14479) by [@retwish](https://github.com/retwish). + ### Fixes * ๐Ÿ› Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). From 61f95c9606ff548d449e9d1e0612d93e2ec3c97f Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:26:02 +0300 Subject: [PATCH 075/367] =?UTF-8?q?=F0=9F=93=9D=20Add=20banner=20to=20tran?= =?UTF-8?q?slated=20pages=20(#14809)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add banner to translated pages * Add link to English version. Use modern syntax for details block * ๐ŸŽจ Auto format * Move `translation-banner.md` inside `docs` directory * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> --- docs/en/docs/translation-banner.md | 11 +++++++++++ docs/ru/docs/translation-banner.md | 11 +++++++++++ scripts/mkdocs_hooks.py | 30 +++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 docs/en/docs/translation-banner.md create mode 100644 docs/ru/docs/translation-banner.md diff --git a/docs/en/docs/translation-banner.md b/docs/en/docs/translation-banner.md new file mode 100644 index 0000000000..1422870744 --- /dev/null +++ b/docs/en/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ Translation by AI and humans + +This translation was made by AI guided by humans. ๐Ÿค + +It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. ๐Ÿค– + +You can improve this translation by [helping us guide the AI LLM better](https://fastapi.tiangolo.com/contributing/#translations). + +[English version](ENGLISH_VERSION_URL) + +/// diff --git a/docs/ru/docs/translation-banner.md b/docs/ru/docs/translation-banner.md new file mode 100644 index 0000000000..78ebd676c5 --- /dev/null +++ b/docs/ru/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ ะŸะตั€ะตะฒะพะด ะฒั‹ะฟะพะปะฝะตะฝ ั ะฟะพะผะพั‰ัŒัŽ ะ˜ะ˜ ะธ ะปัŽะดะตะน + +ะญั‚ะพั‚ ะฟะตั€ะตะฒะพะด ะฑั‹ะป ัะดะตะปะฐะฝ ะ˜ะ˜ ะฟะพะด ั€ัƒะบะพะฒะพะดัั‚ะฒะพะผ ะปัŽะดะตะน. ๐Ÿค + +ะ’ ะฝะตะผ ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะพัˆะธะฑะบะธ ะธะท-ะทะฐ ะฝะตะฟั€ะฐะฒะธะปัŒะฝะพะณะพ ะฟะพะฝะธะผะฐะฝะธั ะพั€ะธะณะธะฝะฐะปัŒะฝะพะณะพ ัะผั‹ัะปะฐ ะธะปะธ ะฝะตะตัั‚ะตัั‚ะฒะตะฝะฝะพัั‚ะธ ะธ ั‚. ะด. ๐Ÿค– + +ะ’ั‹ ะผะพะถะตั‚ะต ัƒะปัƒั‡ัˆะธั‚ัŒ ัั‚ะพั‚ ะฟะตั€ะตะฒะพะด, [ะฟะพะผะพะณะฐั ะฝะฐะผ ะปัƒั‡ัˆะต ะฝะฐะฟั€ะฐะฒะปัั‚ัŒ ะ˜ะ˜ LLM](https://fastapi.tiangolo.com/ru/contributing/#translations). + +[ะะฝะณะปะธะนัะบะฐั ะฒะตั€ัะธั](ENGLISH_VERSION_URL) + +/// diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py index 4b781270a2..567c0111dc 100644 --- a/scripts/mkdocs_hooks.py +++ b/scripts/mkdocs_hooks.py @@ -26,6 +26,17 @@ def get_missing_translation_content(docs_dir: str) -> str: return missing_translation_path.read_text(encoding="utf-8") +@lru_cache +def get_translation_banner_content(docs_dir: str) -> str: + docs_dir_path = Path(docs_dir) + translation_banner_path = docs_dir_path / "translation-banner.md" + if not translation_banner_path.is_file(): + translation_banner_path = ( + docs_dir_path.parent.parent / "en" / "docs" / "translation-banner.md" + ) + return translation_banner_path.read_text(encoding="utf-8") + + @lru_cache def get_mkdocs_material_langs() -> list[str]: material_path = Path(material.__file__).parent @@ -151,4 +162,21 @@ def on_page_markdown( if markdown.startswith("#"): header, _, body = markdown.partition("\n\n") return f"{header}\n\n{missing_translation_content}\n\n{body}" - return markdown + + docs_dir_path = Path(config.docs_dir) + en_docs_dir_path = docs_dir_path.parent.parent / "en/docs" + + if docs_dir_path == en_docs_dir_path: + return markdown + + # For translated pages add translation banner + translation_banner_content = get_translation_banner_content(config.docs_dir) + en_url = "https://fastapi.tiangolo.com/" + page.url.lstrip("/") + translation_banner_content = translation_banner_content.replace( + "ENGLISH_VERSION_URL", en_url + ) + header = "" + body = markdown + if markdown.startswith("#"): + header, _, body = markdown.partition("\n\n") + return f"{header}\n\n{translation_banner_content}\n\n{body}" From a4297066c22071e89f55fcb9f720dec57bd95814 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:26:29 +0000 Subject: [PATCH 076/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0f0b9dd0aa..7658ab970e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -21,6 +21,7 @@ hide: ### Docs +* ๐Ÿ“ Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov). From 3ee652dd0c9e5c1bc38b6cadb6a2a036866c0dd3 Mon Sep 17 00:00:00 2001 From: johnson-earls <125391700+johnson-earls@users.noreply.github.com> Date: Wed, 4 Feb 2026 05:29:02 -0800 Subject: [PATCH 077/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20example=20of=20lic?= =?UTF-8?q?ense=20identifier=20in=20documentation=20(#14492)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg <svlandeg@github.com> --- docs_src/metadata/tutorial001_1_py39.py | 2 +- tests/test_tutorial/test_metadata/test_tutorial001_1.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs_src/metadata/tutorial001_1_py39.py b/docs_src/metadata/tutorial001_1_py39.py index a8f5b94588..419232d861 100644 --- a/docs_src/metadata/tutorial001_1_py39.py +++ b/docs_src/metadata/tutorial001_1_py39.py @@ -28,7 +28,7 @@ app = FastAPI( }, license_info={ "name": "Apache 2.0", - "identifier": "MIT", + "identifier": "Apache-2.0", }, ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial001_1.py b/tests/test_tutorial/test_metadata/test_tutorial001_1.py index 40878ccfd4..10cb35c546 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001_1.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001_1.py @@ -28,7 +28,7 @@ def test_openapi_schema(): }, "license": { "name": "Apache 2.0", - "identifier": "MIT", + "identifier": "Apache-2.0", }, "version": "0.0.1", }, From b134f406d1ef4c0b2241f7a0402f3fcb9e99dc8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:29:24 +0000 Subject: [PATCH 078/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7658ab970e..95d0d794b4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -21,6 +21,7 @@ hide: ### Docs +* ๐Ÿ“ Fix example of license identifier in documentation. PR [#14492](https://github.com/fastapi/fastapi/pull/14492) by [@johnson-earls](https://github.com/johnson-earls). * ๐Ÿ“ Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov). From 9df1f8293d979506cd75280ed4812658323c2c98 Mon Sep 17 00:00:00 2001 From: Tima <126619011+timakaa@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:32:24 +0300 Subject: [PATCH 079/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20typing=20issue=20i?= =?UTF-8?q?n=20`docs=5Fsrc/app=5Ftesting/app=5Fb`=20code=20example=20(#145?= =?UTF-8?q?73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs_src/app_testing/app_b_an_py310/main.py | 2 +- docs_src/app_testing/app_b_an_py39/main.py | 2 +- docs_src/app_testing/app_b_py310/main.py | 2 +- docs_src/app_testing/app_b_py39/main.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs_src/app_testing/app_b_an_py310/main.py b/docs_src/app_testing/app_b_an_py310/main.py index 120289f56d..1b77dd1379 100644 --- a/docs_src/app_testing/app_b_an_py310/main.py +++ b/docs_src/app_testing/app_b_an_py310/main.py @@ -34,5 +34,5 @@ async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item + fake_db[item.id] = item.model_dump() return item diff --git a/docs_src/app_testing/app_b_an_py39/main.py b/docs_src/app_testing/app_b_an_py39/main.py index 801d5f21ea..42026a81a0 100644 --- a/docs_src/app_testing/app_b_an_py39/main.py +++ b/docs_src/app_testing/app_b_an_py39/main.py @@ -34,5 +34,5 @@ async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item + fake_db[item.id] = item.model_dump() return item diff --git a/docs_src/app_testing/app_b_py310/main.py b/docs_src/app_testing/app_b_py310/main.py index 6c5c341308..83f6fa142a 100644 --- a/docs_src/app_testing/app_b_py310/main.py +++ b/docs_src/app_testing/app_b_py310/main.py @@ -32,5 +32,5 @@ async def create_item(item: Item, x_token: str = Header()) -> Item: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item + fake_db[item.id] = item.model_dump() return item diff --git a/docs_src/app_testing/app_b_py39/main.py b/docs_src/app_testing/app_b_py39/main.py index 89053c432c..ed38f4721c 100644 --- a/docs_src/app_testing/app_b_py39/main.py +++ b/docs_src/app_testing/app_b_py39/main.py @@ -34,5 +34,5 @@ async def create_item(item: Item, x_token: str = Header()) -> Item: raise HTTPException(status_code=400, detail="Invalid X-Token header") if item.id in fake_db: raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item + fake_db[item.id] = item.model_dump() return item From a1bb70e5a5a29cea2c3fce50ab3510b341fdaf8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:32:48 +0000 Subject: [PATCH 080/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 95d0d794b4..aa516c0d62 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -21,6 +21,7 @@ hide: ### Docs +* ๐Ÿ“ Fix typing issue in `docs_src/app_testing/app_b` code example. PR [#14573](https://github.com/fastapi/fastapi/pull/14573) by [@timakaa](https://github.com/timakaa). * ๐Ÿ“ Fix example of license identifier in documentation. PR [#14492](https://github.com/fastapi/fastapi/pull/14492) by [@johnson-earls](https://github.com/johnson-earls). * ๐Ÿ“ Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ“ Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov). From 0748214c43d0793b56a309199f45b9bf78c0da26 Mon Sep 17 00:00:00 2001 From: mvanderlee <918128+mvanderlee@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:34:01 +0100 Subject: [PATCH 081/367] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20Re-export=20`In?= =?UTF-8?q?cEx`=20type=20from=20Pydantic=20instead=20of=20duplicating=20it?= =?UTF-8?q?=20(#14641)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/types.py b/fastapi/types.py index d3e980cb43..1c3a6de749 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -3,9 +3,9 @@ from enum import Enum from typing import Any, Callable, Optional, TypeVar, Union from pydantic import BaseModel +from pydantic.main import IncEx as IncEx DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) UnionType = getattr(types, "UnionType", Union) ModelNameMap = dict[Union[type[BaseModel], type[Enum]], str] -IncEx = Union[set[int], set[str], dict[int, Any], dict[str, Any]] DependencyCacheKey = tuple[Optional[Callable[..., Any]], tuple[str, ...], str] From 9656e925a9b53dbb288c24f5dd4cea805c02429b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:34:29 +0000 Subject: [PATCH 082/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index aa516c0d62..12a9ac8a1f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Refactors +* ๐Ÿท๏ธ Re-export `IncEx` type from Pydantic instead of duplicating it. PR [#14641](https://github.com/fastapi/fastapi/pull/14641) by [@mvanderlee](https://github.com/mvanderlee). * ๐Ÿ’ก Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo). ### Docs From 741f77d571eeeb2cde4fe11dcfe038c4d925a046 Mon Sep 17 00:00:00 2001 From: Joab <joab0@proton.me> Date: Wed, 4 Feb 2026 10:35:58 -0300 Subject: [PATCH 083/367] =?UTF-8?q?=E2=9C=A8=20Add=20`viewport`=20meta=20t?= =?UTF-8?q?ag=20to=20improve=20Swagger=20UI=20on=20mobile=20devices=20(#14?= =?UTF-8?q?777)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/openapi/docs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index 632cc2c1d9..bb387c609a 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -139,6 +139,7 @@ def get_swagger_ui_html( <!DOCTYPE html> <html> <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link type="text/css" rel="stylesheet" href="{swagger_css_url}"> <link rel="shortcut icon" href="{swagger_favicon_url}"> <title>{title} From 3675e284abfae4f43dd321301ddfa45bcc494056 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 13:36:24 +0000 Subject: [PATCH 084/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 12a9ac8a1f..45e6cf1c22 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Features +* โœจ Add `viewport` meta tag to improve Swagger UI on mobile devices. PR [#14777](https://github.com/fastapi/fastapi/pull/14777) by [@Joab0](https://github.com/Joab0). * ๐Ÿšธ Improve error message for invalid query parameter type annotations. PR [#14479](https://github.com/fastapi/fastapi/pull/14479) by [@retwish](https://github.com/retwish). ### Fixes From 1d96b3e3f14fa5a226ae817d1095b868796beb60 Mon Sep 17 00:00:00 2001 From: Cecilia Madrid <61908819+WaveTheory1@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:46:46 +0100 Subject: [PATCH 085/367] =?UTF-8?q?=F0=9F=90=9B=20Strip=20whitespaces=20fr?= =?UTF-8?q?om=20`Authorization`=20header=20credentials=20(#14786)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/security/utils.py | 2 +- tests/test_security_http_base.py | 6 ++++++ tests/test_security_oauth2_authorization_code_bearer.py | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/fastapi/security/utils.py b/fastapi/security/utils.py index 002e68b445..fd349aec74 100644 --- a/fastapi/security/utils.py +++ b/fastapi/security/utils.py @@ -7,4 +7,4 @@ def get_authorization_scheme_param( if not authorization_header_value: return "", "" scheme, _, param = authorization_header_value.partition(" ") - return scheme, param + return scheme, param.strip() diff --git a/tests/test_security_http_base.py b/tests/test_security_http_base.py index 8cf259a750..ac38ee718e 100644 --- a/tests/test_security_http_base.py +++ b/tests/test_security_http_base.py @@ -21,6 +21,12 @@ def test_security_http_base(): assert response.json() == {"scheme": "Other", "credentials": "foobar"} +def test_security_http_base_with_whitespaces(): + response = client.get("/users/me", headers={"Authorization": "Other foobar "}) + assert response.status_code == 200, response.text + assert response.json() == {"scheme": "Other", "credentials": "foobar"} + + def test_security_http_base_no_credentials(): response = client.get("/users/me") assert response.status_code == 401, response.text diff --git a/tests/test_security_oauth2_authorization_code_bearer.py b/tests/test_security_oauth2_authorization_code_bearer.py index f2097b1490..66f53ab00d 100644 --- a/tests/test_security_oauth2_authorization_code_bearer.py +++ b/tests/test_security_oauth2_authorization_code_bearer.py @@ -37,6 +37,12 @@ def test_token(): assert response.json() == {"token": "testtoken"} +def test_token_with_whitespaces(): + response = client.get("/items", headers={"Authorization": "Bearer testtoken "}) + assert response.status_code == 200, response.text + assert response.json() == {"token": "testtoken"} + + def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text From c944add5a9680f7b3dea3a5bab4787949671d2c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 13:47:09 +0000 Subject: [PATCH 086/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 45e6cf1c22..091a4c0aa7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Fixes +* ๐Ÿ› Strip whitespaces from `Authorization` header credentials. PR [#14786](https://github.com/fastapi/fastapi/pull/14786) by [@WaveTheory1](https://github.com/WaveTheory1). * ๐Ÿ› Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). ### Refactors From 09f5941f0e18db2b28b40d35a5da7a94c23eb9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Gu=C3=A9rin?= Date: Wed, 4 Feb 2026 14:49:44 +0100 Subject: [PATCH 087/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20TYPE=5FCHECKING=20?= =?UTF-8?q?annotations=20for=20Python=203.14=20(PEP=20649)=20(#14789)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 7 ++++- ...stringified_annotation_dependency_py314.py | 30 +++++++++++++++++++ .../test_dependencies/test_tutorial008.py | 10 +++++-- tests/utils.py | 4 +-- 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 tests/test_stringified_annotation_dependency_py314.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index b647818c4b..fc5dfed85a 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -204,7 +204,12 @@ def _get_signature(call: Callable[..., Any]) -> inspect.Signature: except NameError: # Handle type annotations with if TYPE_CHECKING, not used by FastAPI # e.g. dependency return types - signature = inspect.signature(call) + if sys.version_info >= (3, 14): + from annotationlib import Format + + signature = inspect.signature(call, annotation_format=Format.FORWARDREF) + else: + signature = inspect.signature(call) else: signature = inspect.signature(call) return signature diff --git a/tests/test_stringified_annotation_dependency_py314.py b/tests/test_stringified_annotation_dependency_py314.py new file mode 100644 index 0000000000..da9b429fc0 --- /dev/null +++ b/tests/test_stringified_annotation_dependency_py314.py @@ -0,0 +1,30 @@ +from typing import TYPE_CHECKING, Annotated + +from fastapi import Depends, FastAPI +from fastapi.testclient import TestClient + +from .utils import needs_py314 + +if TYPE_CHECKING: # pragma: no cover + + class DummyUser: ... + + +@needs_py314 +def test_stringified_annotation(): + # python3.14: Use forward reference without "from __future__ import annotations" + async def get_current_user() -> DummyUser | None: + return None + + app = FastAPI() + + client = TestClient(app) + + @app.get("/") + async def get( + current_user: Annotated[DummyUser | None, Depends(get_current_user)], + ) -> str: + return "hello world" + + response = client.get("/") + assert response.status_code == 200 diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008.py b/tests/test_tutorial/test_dependencies/test_tutorial008.py index 9d7377ebe4..5a2d226bff 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008.py @@ -1,4 +1,5 @@ import importlib +import sys from types import ModuleType from typing import Annotated, Any from unittest.mock import Mock, patch @@ -12,8 +13,13 @@ from fastapi.testclient import TestClient name="module", params=[ "tutorial008_py39", - # Fails with `NameError: name 'DepA' is not defined` - pytest.param("tutorial008_an_py39", marks=pytest.mark.xfail), + pytest.param( + "tutorial008_an_py39", + marks=pytest.mark.xfail( + sys.version_info < (3, 14), + reason="Fails with `NameError: name 'DepA' is not defined`", + ), + ), ], ) def get_module(request: pytest.FixtureRequest): diff --git a/tests/utils.py b/tests/utils.py index efa0bfd52b..4cbfee79f5 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -6,8 +6,8 @@ needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires pyth needs_py310 = pytest.mark.skipif( sys.version_info < (3, 10), reason="requires python3.10+" ) -needs_py_lt_314 = pytest.mark.skipif( - sys.version_info >= (3, 14), reason="requires python3.13-" +needs_py314 = pytest.mark.skipif( + sys.version_info < (3, 14), reason="requires python3.14+" ) From 5d50b7491579d6b9e9a30cdbe24b08f70dcb8d61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 13:51:56 +0000 Subject: [PATCH 088/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 091a4c0aa7..eff732da1e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Fixes +* ๐Ÿ› Fix TYPE_CHECKING annotations for Python 3.14 (PEP 649). PR [#14789](https://github.com/fastapi/fastapi/pull/14789) by [@mgu](https://github.com/mgu). * ๐Ÿ› Strip whitespaces from `Authorization` header credentials. PR [#14786](https://github.com/fastapi/fastapi/pull/14786) by [@WaveTheory1](https://github.com/WaveTheory1). * ๐Ÿ› Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). From 440bfd70a948c187dadb2e89ee7e94933e867a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 06:20:36 -0800 Subject: [PATCH 089/367] =?UTF-8?q?=F0=9F=8E=A8=20Tweak=20types=20for=20my?= =?UTF-8?q?py=20(#14816)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/encoders.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/encoders.py b/fastapi/encoders.py index e8610c983b..b4661be4fa 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -219,9 +219,9 @@ def jsonable_encoder( if isinstance(obj, encoder_type): return encoder_instance(obj) if include is not None and not isinstance(include, (set, dict)): - include = set(include) + include = set(include) # type: ignore[assignment] if exclude is not None and not isinstance(exclude, (set, dict)): - exclude = set(exclude) + exclude = set(exclude) # type: ignore[assignment] if isinstance(obj, BaseModel): obj_dict = obj.model_dump( mode="json", From 1e5e8b44cb042f774a8637f27bce93b4ceb68f7d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 14:21:00 +0000 Subject: [PATCH 090/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index eff732da1e..8d90983d44 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Refactors +* ๐ŸŽจ Tweak types for mypy. PR [#14816](https://github.com/fastapi/fastapi/pull/14816) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿท๏ธ Re-export `IncEx` type from Pydantic instead of duplicating it. PR [#14641](https://github.com/fastapi/fastapi/pull/14641) by [@mvanderlee](https://github.com/mvanderlee). * ๐Ÿ’ก Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo). From 75c47187f31b6f60e59dda2d6db26984043ab95c Mon Sep 17 00:00:00 2001 From: Jonathan Fulton Date: Wed, 4 Feb 2026 09:34:02 -0500 Subject: [PATCH 091/367] =?UTF-8?q?=F0=9F=90=9B=20Update=20`ValidationErro?= =?UTF-8?q?r`=20schema=20to=20include=20`input`=20and=20`ctx`=20(#14791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- fastapi/openapi/utils.py | 2 ++ tests/test_additional_properties.py | 2 ++ tests/test_additional_properties_bool.py | 2 ++ ...dditional_responses_custom_model_in_callback.py | 2 ++ ...additional_responses_default_validationerror.py | 2 ++ tests/test_annotated.py | 2 ++ tests/test_application.py | 2 ++ tests/test_dependency_duplicates.py | 2 ++ tests/test_enforce_once_required_parameter.py | 2 ++ tests/test_extra_routes.py | 2 ++ tests/test_filter_pydantic_sub_model_pv2.py | 2 ++ tests/test_forms_single_param.py | 2 ++ tests/test_generate_unique_id_function.py | 14 ++++++++++++++ .../test_get_model_definitions_formfeed_escape.py | 2 ++ tests/test_get_request_body.py | 2 ++ tests/test_include_router_defaults_overrides.py | 2 ++ tests/test_infer_param_optionality.py | 2 ++ tests/test_modules_same_name_body/test_main.py | 2 ++ tests/test_multi_body_errors.py | 2 ++ tests/test_multi_query_errors.py | 2 ++ tests/test_no_schema_split.py | 2 ++ tests/test_openapi_examples.py | 2 ++ tests/test_openapi_query_parameter_extension.py | 2 ++ .../test_openapi_separate_input_output_schemas.py | 4 ++++ tests/test_param_in_path_and_dependency.py | 2 ++ tests/test_param_include_in_schema.py | 2 ++ tests/test_put_no_body.py | 2 ++ tests/test_regex_deprecated_body.py | 2 ++ tests/test_regex_deprecated_params.py | 2 ++ tests/test_repeated_dependency_schema.py | 2 ++ tests/test_repeated_parameter_alias.py | 2 ++ tests/test_reponse_set_reponse_code_empty.py | 2 ++ tests/test_request_body_parameters_media_type.py | 2 ++ tests/test_schema_extra_examples.py | 2 ++ tests/test_security_oauth2.py | 2 ++ tests/test_security_oauth2_optional.py | 2 ++ tests/test_security_oauth2_optional_description.py | 2 ++ tests/test_starlette_exception.py | 2 ++ tests/test_sub_callbacks.py | 2 ++ tests/test_tuples.py | 2 ++ .../test_additional_responses/test_tutorial001.py | 2 ++ .../test_additional_responses/test_tutorial002.py | 2 ++ .../test_additional_responses/test_tutorial003.py | 2 ++ .../test_additional_responses/test_tutorial004.py | 2 ++ .../test_bigger_applications/test_main.py | 2 ++ tests/test_tutorial/test_body/test_tutorial001.py | 2 ++ tests/test_tutorial/test_body/test_tutorial002.py | 2 ++ tests/test_tutorial/test_body/test_tutorial003.py | 2 ++ tests/test_tutorial/test_body/test_tutorial004.py | 2 ++ .../test_body_fields/test_tutorial001.py | 2 ++ .../test_body_multiple_params/test_tutorial001.py | 2 ++ .../test_body_multiple_params/test_tutorial002.py | 2 ++ .../test_body_multiple_params/test_tutorial003.py | 2 ++ .../test_body_multiple_params/test_tutorial004.py | 2 ++ .../test_body_multiple_params/test_tutorial005.py | 2 ++ .../test_tutorial001_tutorial002_tutorial003.py | 2 ++ .../test_body_nested_models/test_tutorial004.py | 2 ++ .../test_body_nested_models/test_tutorial005.py | 2 ++ .../test_body_nested_models/test_tutorial006.py | 2 ++ .../test_body_nested_models/test_tutorial007.py | 2 ++ .../test_body_nested_models/test_tutorial008.py | 2 ++ .../test_body_nested_models/test_tutorial009.py | 2 ++ .../test_body_updates/test_tutorial001.py | 2 ++ .../test_body_updates/test_tutorial002.py | 2 ++ .../test_cookie_param_models/test_tutorial001.py | 2 ++ .../test_cookie_param_models/test_tutorial002.py | 2 ++ .../test_cookie_params/test_tutorial001.py | 2 ++ .../test_dataclasses/test_tutorial001.py | 2 ++ .../test_dataclasses/test_tutorial003.py | 2 ++ .../test_tutorial001_tutorial001_02.py | 2 ++ .../test_tutorial002_tutorial003_tutorial004.py | 2 ++ .../test_dependencies/test_tutorial005.py | 2 ++ .../test_dependencies/test_tutorial006.py | 2 ++ .../test_dependencies/test_tutorial011.py | 2 ++ .../test_dependencies/test_tutorial012.py | 2 ++ .../test_tutorial/test_encoder/test_tutorial001.py | 2 ++ .../test_tutorial/test_events/test_tutorial001.py | 2 ++ .../test_tutorial/test_events/test_tutorial003.py | 2 ++ .../test_extra_data_types/test_tutorial001.py | 2 ++ .../test_tutorial001_tutorial002.py | 2 ++ .../test_extra_models/test_tutorial003.py | 2 ++ .../test_generate_clients/test_tutorial001.py | 2 ++ .../test_generate_clients/test_tutorial002.py | 2 ++ .../test_generate_clients/test_tutorial003.py | 2 ++ .../test_generate_clients/test_tutorial004.py | 2 ++ .../test_handling_errors/test_tutorial001.py | 2 ++ .../test_handling_errors/test_tutorial002.py | 2 ++ .../test_handling_errors/test_tutorial003.py | 2 ++ .../test_handling_errors/test_tutorial004.py | 2 ++ .../test_handling_errors/test_tutorial005.py | 2 ++ .../test_handling_errors/test_tutorial006.py | 2 ++ .../test_header_param_models/test_tutorial001.py | 2 ++ .../test_header_param_models/test_tutorial002.py | 2 ++ .../test_header_param_models/test_tutorial003.py | 2 ++ .../test_header_params/test_tutorial001.py | 2 ++ .../test_header_params/test_tutorial002.py | 2 ++ .../test_header_params/test_tutorial003.py | 2 ++ .../test_openapi_callbacks/test_tutorial001.py | 2 ++ .../test_openapi_webhooks/test_tutorial001.py | 2 ++ .../test_tutorial004.py | 2 ++ .../test_tutorial001.py | 2 ++ .../test_tutorial002.py | 2 ++ .../test_tutorial003_tutorial004.py | 2 ++ .../test_tutorial005.py | 2 ++ .../test_path_params/test_tutorial001.py | 2 ++ .../test_path_params/test_tutorial002.py | 2 ++ .../test_path_params/test_tutorial003.py | 2 ++ .../test_path_params/test_tutorial004.py | 2 ++ .../test_path_params/test_tutorial005.py | 2 ++ .../test_tutorial001.py | 2 ++ .../test_tutorial002_tutorial003.py | 2 ++ .../test_tutorial004.py | 2 ++ .../test_tutorial005.py | 2 ++ .../test_tutorial006.py | 2 ++ .../test_query_param_models/test_tutorial001.py | 2 ++ .../test_query_param_models/test_tutorial002.py | 2 ++ .../test_query_params/test_tutorial001.py | 2 ++ .../test_query_params/test_tutorial002.py | 2 ++ .../test_query_params/test_tutorial003.py | 2 ++ .../test_query_params/test_tutorial004.py | 2 ++ .../test_query_params/test_tutorial005.py | 2 ++ .../test_query_params/test_tutorial006.py | 2 ++ .../test_tutorial001.py | 2 ++ .../test_tutorial002.py | 2 ++ .../test_tutorial003.py | 2 ++ .../test_tutorial004.py | 2 ++ .../test_tutorial005.py | 2 ++ .../test_tutorial006.py | 2 ++ .../test_tutorial006c.py | 2 ++ .../test_tutorial007.py | 2 ++ .../test_tutorial008.py | 2 ++ .../test_tutorial009.py | 2 ++ .../test_tutorial010.py | 2 ++ .../test_tutorial011.py | 2 ++ .../test_tutorial012.py | 2 ++ .../test_tutorial013.py | 2 ++ .../test_tutorial014.py | 2 ++ .../test_tutorial015.py | 2 ++ .../test_request_files/test_tutorial001.py | 2 ++ .../test_request_files/test_tutorial001_02.py | 2 ++ .../test_request_files/test_tutorial001_03.py | 2 ++ .../test_request_files/test_tutorial002.py | 2 ++ .../test_request_files/test_tutorial003.py | 2 ++ .../test_request_form_models/test_tutorial001.py | 2 ++ .../test_request_form_models/test_tutorial002.py | 2 ++ .../test_request_forms/test_tutorial001.py | 2 ++ .../test_tutorial001.py | 2 ++ .../test_response_directly/test_tutorial001.py | 2 ++ .../test_tutorial001_tutorial001_01.py | 2 ++ .../test_response_model/test_tutorial002.py | 2 ++ .../test_response_model/test_tutorial003.py | 2 ++ .../test_response_model/test_tutorial003_01.py | 2 ++ .../test_response_model/test_tutorial003_02.py | 2 ++ .../test_response_model/test_tutorial003_05.py | 2 ++ .../test_response_model/test_tutorial004.py | 2 ++ .../test_response_model/test_tutorial005.py | 2 ++ .../test_response_model/test_tutorial006.py | 2 ++ .../test_tutorial001_tutorial002.py | 2 ++ .../test_schema_extra_example/test_tutorial001.py | 2 ++ .../test_schema_extra_example/test_tutorial002.py | 2 ++ .../test_schema_extra_example/test_tutorial003.py | 2 ++ .../test_schema_extra_example/test_tutorial004.py | 2 ++ .../test_schema_extra_example/test_tutorial005.py | 2 ++ .../test_security/test_tutorial003.py | 2 ++ .../test_security/test_tutorial004.py | 2 ++ .../test_security/test_tutorial005.py | 2 ++ .../test_tutorial001.py | 2 ++ .../test_tutorial002.py | 2 ++ .../test_sql_databases/test_tutorial001.py | 2 ++ .../test_sql_databases/test_tutorial002.py | 2 ++ .../test_tutorial001.py | 2 ++ tests/test_union_body.py | 2 ++ tests/test_union_body_discriminator.py | 2 ++ tests/test_union_body_discriminator_annotated.py | 2 ++ tests/test_union_forms.py | 2 ++ tests/test_union_inherited_body.py | 2 ++ tests/test_webhooks_security.py | 2 ++ 177 files changed, 368 insertions(+) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index d56027b500..5736af3b78 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -50,6 +50,8 @@ validation_error_definition = { }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, "required": ["loc", "msg", "type"], } diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py index 2622366400..935acca42e 100644 --- a/tests/test_additional_properties.py +++ b/tests/test_additional_properties.py @@ -89,6 +89,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_additional_properties_bool.py b/tests/test_additional_properties_bool.py index 063297a3f2..3b323ad463 100644 --- a/tests/test_additional_properties_bool.py +++ b/tests/test_additional_properties_bool.py @@ -101,6 +101,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_additional_responses_custom_model_in_callback.py b/tests/test_additional_responses_custom_model_in_callback.py index 376d7714ed..3a37c924d2 100644 --- a/tests/test_additional_responses_custom_model_in_callback.py +++ b/tests/test_additional_responses_custom_model_in_callback.py @@ -128,6 +128,8 @@ def test_openapi_schema(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_additional_responses_default_validationerror.py b/tests/test_additional_responses_default_validationerror.py index 153f04f579..acc081fb16 100644 --- a/tests/test_additional_responses_default_validationerror.py +++ b/tests/test_additional_responses_default_validationerror.py @@ -66,6 +66,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_annotated.py b/tests/test_annotated.py index 39f6f83b29..99bd03ae6f 100644 --- a/tests/test_annotated.py +++ b/tests/test_annotated.py @@ -284,6 +284,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_application.py b/tests/test_application.py index 001586ff78..fe97e674c0 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1260,6 +1260,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py index a8658e03bb..3ca6a3e891 100644 --- a/tests/test_dependency_duplicates.py +++ b/tests/test_dependency_duplicates.py @@ -223,6 +223,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index 2e5ac6c062..c46a543576 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -42,6 +42,8 @@ expected_schema = { }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "title": "Location", diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index 45734ec28a..251af4a59e 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -347,6 +347,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_filter_pydantic_sub_model_pv2.py b/tests/test_filter_pydantic_sub_model_pv2.py index fc5876410d..1de2b50f7f 100644 --- a/tests/test_filter_pydantic_sub_model_pv2.py +++ b/tests/test_filter_pydantic_sub_model_pv2.py @@ -165,6 +165,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_forms_single_param.py b/tests/test_forms_single_param.py index 67f054b34e..fc163cb1ef 100644 --- a/tests/test_forms_single_param.py +++ b/tests/test_forms_single_param.py @@ -81,6 +81,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_generate_unique_id_function.py b/tests/test_generate_unique_id_function.py index 62ebfbc964..49510d08a9 100644 --- a/tests/test_generate_unique_id_function.py +++ b/tests/test_generate_unique_id_function.py @@ -213,6 +213,8 @@ def test_top_level_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -414,6 +416,8 @@ def test_router_overrides_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -615,6 +619,8 @@ def test_router_include_overrides_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -889,6 +895,8 @@ def test_subrouter_top_level_include_overrides_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -1093,6 +1101,8 @@ def test_router_path_operation_overrides_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -1301,6 +1311,8 @@ def test_app_path_operation_overrides_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", @@ -1587,6 +1599,8 @@ def test_callback_override_generate_unique_id(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_get_model_definitions_formfeed_escape.py b/tests/test_get_model_definitions_formfeed_escape.py index eb7939b69a..46f8aa5959 100644 --- a/tests/test_get_model_definitions_formfeed_escape.py +++ b/tests/test_get_model_definitions_formfeed_escape.py @@ -98,6 +98,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index cc567b88f6..b21889e30f 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -100,6 +100,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_include_router_defaults_overrides.py b/tests/test_include_router_defaults_overrides.py index 33baa25e6a..6d2ffc44a5 100644 --- a/tests/test_include_router_defaults_overrides.py +++ b/tests/test_include_router_defaults_overrides.py @@ -7290,6 +7290,8 @@ def test_openapi(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_infer_param_optionality.py b/tests/test_infer_param_optionality.py index 147018996e..b11a1ca433 100644 --- a/tests/test_infer_param_optionality.py +++ b/tests/test_infer_param_optionality.py @@ -325,6 +325,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index 263d87df26..276de539db 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -131,6 +131,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index 4418c77cb0..fa3e0c6359 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -167,6 +167,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py index 5df51ba185..7540367a6f 100644 --- a/tests/test_multi_query_errors.py +++ b/tests/test_multi_query_errors.py @@ -97,6 +97,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_no_schema_split.py b/tests/test_no_schema_split.py index 131a3755e7..66bb89902a 100644 --- a/tests/test_no_schema_split.py +++ b/tests/test_no_schema_split.py @@ -154,6 +154,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index bd0d55452e..93e5b366f1 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -398,6 +398,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_openapi_query_parameter_extension.py b/tests/test_openapi_query_parameter_extension.py index 084cb695d4..b6c3c3d8da 100644 --- a/tests/test_openapi_query_parameter_extension.py +++ b/tests/test_openapi_query_parameter_extension.py @@ -119,6 +119,8 @@ def test_openapi(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_openapi_separate_input_output_schemas.py b/tests/test_openapi_separate_input_output_schemas.py index 1891f0bde0..f941e323bf 100644 --- a/tests/test_openapi_separate_input_output_schemas.py +++ b/tests/test_openapi_separate_input_output_schemas.py @@ -418,6 +418,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] @@ -649,6 +651,8 @@ def test_openapi_schema_no_separate(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_param_in_path_and_dependency.py b/tests/test_param_in_path_and_dependency.py index 08eb0f40f3..6b1f660cb7 100644 --- a/tests/test_param_in_path_and_dependency.py +++ b/tests/test_param_in_path_and_dependency.py @@ -86,6 +86,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index f461947c97..5060920f14 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -151,6 +151,8 @@ openapi_schema = { }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_put_no_body.py b/tests/test_put_no_body.py index 8f4c82532c..2b9299bc58 100644 --- a/tests/test_put_no_body.py +++ b/tests/test_put_no_body.py @@ -78,6 +78,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_regex_deprecated_body.py b/tests/test_regex_deprecated_body.py index 5b4daa450f..6074206ffe 100644 --- a/tests/test_regex_deprecated_body.py +++ b/tests/test_regex_deprecated_body.py @@ -132,6 +132,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_regex_deprecated_params.py b/tests/test_regex_deprecated_params.py index d6eaa45fb1..6074b62828 100644 --- a/tests/test_regex_deprecated_params.py +++ b/tests/test_regex_deprecated_params.py @@ -121,6 +121,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index c21829bd97..0fc7e3d3ef 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -35,6 +35,8 @@ schema = { }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "title": "Location", diff --git a/tests/test_repeated_parameter_alias.py b/tests/test_repeated_parameter_alias.py index fd72eaab29..49e4ad4a2e 100644 --- a/tests/test_repeated_parameter_alias.py +++ b/tests/test_repeated_parameter_alias.py @@ -41,6 +41,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_reponse_set_reponse_code_empty.py index bf3aa758c3..b31aefa479 100644 --- a/tests/test_reponse_set_reponse_code_empty.py +++ b/tests/test_reponse_set_reponse_code_empty.py @@ -90,6 +90,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index d1bff9ddf4..8731c3e5d3 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -168,6 +168,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index ac8999c90a..8caf6ce7af 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -845,6 +845,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index 7ad9369956..bff1226ad9 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -237,6 +237,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index 57c16058af..5bcd5040fd 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -240,6 +240,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index 60c6c242e0..0353ba4c27 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -241,6 +241,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 229fe80163..2be37b8bb8 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -184,6 +184,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index cc7e5f5c6a..442e709fb1 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -277,6 +277,8 @@ def test_openapi_schema(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tuples.py b/tests/test_tuples.py index d3c89045b4..de9487df2a 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -262,6 +262,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index 1a18db75ce..78ccb84426 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -98,6 +98,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index 8208605956..cdab56d7a6 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -115,6 +115,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index 90dc4e371e..fda786b398 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -102,6 +102,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index c6abf5e466..f36d3d79c2 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -118,6 +118,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index f5e243b95a..f80563d142 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -593,6 +593,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 5a7cae1603..9a837483f2 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -328,6 +328,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body/test_tutorial002.py b/tests/test_tutorial/test_body/test_tutorial002.py index b6d51d5235..e8b23e8f61 100644 --- a/tests/test_tutorial/test_body/test_tutorial002.py +++ b/tests/test_tutorial/test_body/test_tutorial002.py @@ -143,6 +143,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body/test_tutorial003.py b/tests/test_tutorial/test_body/test_tutorial003.py index 227a125e78..7b8b7ea89f 100644 --- a/tests/test_tutorial/test_body/test_tutorial003.py +++ b/tests/test_tutorial/test_body/test_tutorial003.py @@ -153,6 +153,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body/test_tutorial004.py b/tests/test_tutorial/test_body/test_tutorial004.py index 10212843ee..d78c760f5d 100644 --- a/tests/test_tutorial/test_body/test_tutorial004.py +++ b/tests/test_tutorial/test_body/test_tutorial004.py @@ -164,6 +164,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index 0ecadbb660..cb6da29085 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -166,6 +166,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index 63c9c16d62..a4f24627b0 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -162,6 +162,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py index e98d5860fe..155bda0c99 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py @@ -325,6 +325,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index 76b7ff7099..2f403797fe 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -202,6 +202,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py index 979c054cd0..506e55eebc 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py @@ -272,6 +272,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py index d47aa1b4f9..20859d12c8 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py @@ -236,6 +236,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py index d452929c38..ae494350b3 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py @@ -233,6 +233,8 @@ def test_openapi_schema(client: TestClient, mod_name: str): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py index ff9596943d..c1410330c4 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py @@ -257,6 +257,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py index 9a07a904e6..c09e0c1b10 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py @@ -283,6 +283,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py index 088177cb95..f26c50167b 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py @@ -251,6 +251,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py index a302819505..dac168e242 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py @@ -326,6 +326,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py index 32eb8ee75c..2101b7bbe5 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py @@ -139,6 +139,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index f2e56d40fb..f7481a5f7f 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -98,6 +98,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index 0401eb7d0d..9c6a90576c 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -168,6 +168,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_body_updates/test_tutorial002.py b/tests/test_tutorial/test_body_updates/test_tutorial002.py index 466e6af8fd..7d79cf5e63 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial002.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial002.py @@ -189,6 +189,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py index ac8e7bdae1..f391c569a8 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py @@ -151,6 +151,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py index d7c3d15f1b..6583045dc8 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py @@ -161,6 +161,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index 9b47cbc67a..ab71148764 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -101,6 +101,8 @@ def test_openapi_schema(mod: ModuleType): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index 4683062f59..756eacf233 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -129,6 +129,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index a6a9fc1c7e..de63a94766 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -195,6 +195,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py index 50d7c4108c..15919c63f7 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py @@ -170,6 +170,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py index f09d6f268d..96300a2599 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py @@ -161,6 +161,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial005.py b/tests/test_tutorial/test_dependencies/test_tutorial005.py index a914936ba1..e595859cb8 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial005.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial005.py @@ -121,6 +121,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index 59202df3bf..cdea27b7c0 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -125,6 +125,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial011.py b/tests/test_tutorial/test_dependencies/test_tutorial011.py index 4868254c0b..3374c54b5e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial011.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial011.py @@ -102,6 +102,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index d5599ac73a..f342ff842e 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -219,6 +219,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_encoder/test_tutorial001.py b/tests/test_tutorial/test_encoder/test_tutorial001.py index 5c8ee054d8..5a4edbc66e 100644 --- a/tests/test_tutorial/test_encoder/test_tutorial001.py +++ b/tests/test_tutorial/test_encoder/test_tutorial001.py @@ -172,6 +172,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index 5fe99d50df..48b838d5a0 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -63,6 +63,8 @@ def test_openapi_schema(app: FastAPI): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py index 38710edfea..aed9def7ae 100644 --- a/tests/test_tutorial/test_events/test_tutorial003.py +++ b/tests/test_tutorial/test_events/test_tutorial003.py @@ -76,6 +76,8 @@ def test_openapi_schema(): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py index 5479e29252..28fe68f285 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py @@ -133,6 +133,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py index 3f2f508a11..9981699862 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py @@ -138,6 +138,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index 872af53830..38e8741582 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -127,6 +127,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial001.py b/tests/test_tutorial/test_generate_clients/test_tutorial001.py index bbb66b4516..83ae38c5b5 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial001.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial001.py @@ -135,6 +135,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial002.py b/tests/test_tutorial/test_generate_clients/test_tutorial002.py index ab8bc4c11c..b9255325aa 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial002.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial002.py @@ -180,6 +180,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index bac52e4fd6..d054845879 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -180,6 +180,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial004.py b/tests/test_tutorial/test_generate_clients/test_tutorial004.py index e66f6d2a12..eea60e3428 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial004.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial004.py @@ -82,6 +82,8 @@ def test_remove_tags(tmp_path: pathlib.Path): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index c01850fae6..e22f1dafd4 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -72,6 +72,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index 09366a86fa..991478a0fe 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -72,6 +72,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index 51ac3e7b28..c303960bde 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -73,6 +73,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index 376bc8266f..f6ec59b4d0 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -78,6 +78,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index 7bd947f194..a7fa4f0b64 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -102,6 +102,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index e95e53d5ed..9cb57d857d 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -86,6 +86,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial001.py b/tests/test_tutorial/test_header_param_models/test_tutorial001.py index 1fa8aee461..2d14c698e0 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial001.py @@ -187,6 +187,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py index 079a8f5402..478ac84087 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py @@ -184,6 +184,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial003.py b/tests/test_tutorial/test_header_param_models/test_tutorial003.py index 4c89d80ee2..00636c2b53 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial003.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial003.py @@ -224,6 +224,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 88591b8225..60342f70a4 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -93,6 +93,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py index 229f96c1f8..f1ced99b1b 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002.py @@ -104,6 +104,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py index cf067ccf9e..382c3ae191 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003.py @@ -112,6 +112,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index 6fde96cb5b..e8c98e8063 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -195,6 +195,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py index 27619489fa..c58e0fd02c 100644 --- a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py @@ -98,6 +98,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index a95540731d..75b08a4e75 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -118,6 +118,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py index 085d1f5e19..de81251d04 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py @@ -150,6 +150,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py index c7414d756a..28e5e7d8d1 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py @@ -187,6 +187,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py index 791db24625..e42c3e2b73 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py @@ -172,6 +172,8 @@ def test_openapi_schema(client: TestClient, mod_name: str): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index c5a3aec1d9..b684c9f5c2 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -117,6 +117,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_path_params/test_tutorial001.py b/tests/test_tutorial/test_path_params/test_tutorial001.py index a898e386fb..f54626f339 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params/test_tutorial001.py @@ -80,6 +80,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params/test_tutorial002.py b/tests/test_tutorial/test_path_params/test_tutorial002.py index 0bfc9f807e..46da41b481 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial002.py +++ b/tests/test_tutorial/test_path_params/test_tutorial002.py @@ -88,6 +88,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params/test_tutorial003.py b/tests/test_tutorial/test_path_params/test_tutorial003.py index cd2c39ab06..6ac92c87e3 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial003.py +++ b/tests/test_tutorial/test_path_params/test_tutorial003.py @@ -97,6 +97,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index f7f233ccff..8f460fb695 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -73,6 +73,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index 86ccce7b6d..3e3766e845 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -110,6 +110,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py index f1e3041030..a4d68d01b4 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py @@ -128,6 +128,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py index 467c915dcd..37533bd228 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py @@ -134,6 +134,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py index d3593c984c..a9c111a594 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py @@ -149,6 +149,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py index 296192593b..e0e976d6f3 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py @@ -166,6 +166,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py index 9dc7d7aac2..2004ad1d2b 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py @@ -185,6 +185,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial001.py b/tests/test_tutorial/test_query_param_models/test_tutorial001.py index d3ce57121d..38b767154a 100644 --- a/tests/test_tutorial/test_query_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_query_param_models/test_tutorial001.py @@ -207,6 +207,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial002.py b/tests/test_tutorial/test_query_param_models/test_tutorial002.py index 96abce6ab9..b173a2df45 100644 --- a/tests/test_tutorial/test_query_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_query_param_models/test_tutorial002.py @@ -213,6 +213,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_query_params/test_tutorial001.py b/tests/test_tutorial/test_query_params/test_tutorial001.py index 4c92b57b8d..84e4557272 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params/test_tutorial001.py @@ -108,6 +108,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial002.py b/tests/test_tutorial/test_query_params/test_tutorial002.py index ae3ee7613d..f725c80b32 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params/test_tutorial002.py @@ -109,6 +109,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial003.py b/tests/test_tutorial/test_query_params/test_tutorial003.py index c0b7e3b133..9f1f2e6e4c 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params/test_tutorial003.py @@ -130,6 +130,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial004.py b/tests/test_tutorial/test_query_params/test_tutorial004.py index 9be18b74df..e834f973a9 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params/test_tutorial004.py @@ -138,6 +138,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index 1030781472..36129dbc96 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -86,6 +86,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index 157322c7e3..473dc33661 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -137,6 +137,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py index f1af7e08c1..069921629e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py @@ -103,6 +103,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py index 62018b80b5..a043b5b2e7 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py @@ -124,6 +124,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py index a4ad7a63ba..68c6e6174f 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py @@ -135,6 +135,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py index 585989a827..79538f952b 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py @@ -129,6 +129,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py index 52462fe33b..fafbd0a7d0 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py @@ -113,6 +113,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py index 640cedce19..1d01492c66 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py @@ -118,6 +118,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py index f287b5dcd8..d31cb5036a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py @@ -130,6 +130,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py index b17bc27719..e030902451 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py @@ -118,6 +118,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py index c631115744..186de5e062 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py @@ -120,6 +120,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py index 7e9d69d41c..b242a75c90 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py @@ -105,6 +105,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index 00889c5bf7..6a39130af2 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -136,6 +136,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index 11de33ae14..6ab279bf3e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -98,6 +98,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index 1826928611..41bfeb3a7a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -93,6 +93,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 46c367c86b..52c8147ffb 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -93,6 +93,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 0feaccfa44..bb168f0fc3 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -93,6 +93,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py index 82bb606a9b..32a990e748 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py @@ -122,6 +122,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index e0e1bbe639..db9b83b31a 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -183,6 +183,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index 18948c5444..feeb5363ed 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -173,6 +173,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index 53a7a0cf85..903452ac76 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -163,6 +163,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 03772419ad..4d9ff0e93d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -223,6 +223,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index fa4bfd5695..c9f7f09940 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -206,6 +206,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial001.py b/tests/test_tutorial/test_request_form_models/test_tutorial001.py index 0c43dd7b21..c4740ee72d 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial001.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial001.py @@ -159,6 +159,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002.py b/tests/test_tutorial/test_request_form_models/test_tutorial002.py index 238f8fa2ef..b07fce432a 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial002.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial002.py @@ -177,6 +177,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py index 4276414fc2..f5f76306e9 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py @@ -161,6 +161,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index 7fa4c3de57..cd05a1ccf1 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -216,6 +216,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_response_directly/test_tutorial001.py b/tests/test_tutorial/test_response_directly/test_tutorial001.py index 2d0c387195..76e7143bda 100644 --- a/tests/test_tutorial/test_response_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_response_directly/test_tutorial001.py @@ -130,6 +130,8 @@ def test_openapi_schema_pv2(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py index 10692f9904..265162f15f 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py @@ -175,6 +175,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial002.py b/tests/test_tutorial/test_response_model/test_tutorial002.py index 216d4c420c..17027d3c10 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial002.py +++ b/tests/test_tutorial/test_response_model/test_tutorial002.py @@ -111,6 +111,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index 35ed5572dd..a1477b7dfd 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -126,6 +126,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01.py b/tests/test_tutorial/test_response_model/test_tutorial003_01.py index fa1eb62770..a60a14ae8d 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01.py @@ -139,6 +139,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_02.py b/tests/test_tutorial/test_response_model/test_tutorial003_02.py index b7507b7110..fcd5f9a1d4 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_02.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_02.py @@ -86,6 +86,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05.py b/tests/test_tutorial/test_response_model/test_tutorial003_05.py index 19a7c601bb..e64ed1a804 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_05.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_05.py @@ -101,6 +101,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py index 9c0d95ebd0..d40bce261b 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004.py @@ -117,6 +117,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py index 63e8535db0..55b2334d46 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005.py @@ -135,6 +135,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py index 08ab659527..5d6f542b5d 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006.py @@ -135,6 +135,8 @@ def test_openapi_schema(client: TestClient): "required": ["loc", "msg", "type"], "type": "object", "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "title": "Location", "type": "array", diff --git a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py index ddf55a045d..8b6213e33d 100644 --- a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py @@ -78,6 +78,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py index 82f69fd463..7f0105a26d 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py @@ -120,6 +120,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py index 4f52408605..32707c2993 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py @@ -122,6 +122,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py index 3529a9bf02..4f8f1394c1 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py @@ -124,6 +124,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py index 9326e06290..3a0a7704bf 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -140,6 +140,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py index 2d0dee48ca..b10f25e262 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py @@ -149,6 +149,8 @@ def test_openapi_schema(client: TestClient) -> None: }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index 6a786348cf..924b36b3ab 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -182,6 +182,8 @@ def test_openapi_schema(client: TestClient): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_security/test_tutorial004.py b/tests/test_tutorial/test_security/test_tutorial004.py index b5e3d39ef7..2b0df66a2e 100644 --- a/tests/test_tutorial/test_security/test_tutorial004.py +++ b/tests/test_tutorial/test_security/test_tutorial004.py @@ -334,6 +334,8 @@ def test_openapi_schema(mod: ModuleType): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index 25b47f0adc..76b08860f5 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -379,6 +379,8 @@ def test_openapi_schema(mod: ModuleType): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py index 275b234877..d0a0d5d388 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py @@ -121,6 +121,8 @@ def test_openapi_schema(client: TestClient) -> None: }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py index 8230e39226..a2fa56f932 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py @@ -121,6 +121,8 @@ def test_openapi_schema(client: TestClient) -> None: }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_sql_databases/test_tutorial001.py index 2c628f5257..aec20e42e1 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial001.py @@ -335,6 +335,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial002.py b/tests/test_tutorial/test_sql_databases/test_tutorial002.py index c72c16e9ae..4ea7d5f647 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial002.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial002.py @@ -416,6 +416,8 @@ def test_openapi_schema(client: TestClient): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py index 33e661b164..b55bfb4567 100644 --- a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py @@ -76,6 +76,8 @@ def test_openapi(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [ diff --git a/tests/test_union_body.py b/tests/test_union_body.py index ee7fcc4231..ee56bb6eb1 100644 --- a/tests/test_union_body.py +++ b/tests/test_union_body.py @@ -111,6 +111,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_union_body_discriminator.py b/tests/test_union_body_discriminator.py index 6c31649bcc..4afe7be4b4 100644 --- a/tests/test_union_body_discriminator.py +++ b/tests/test_union_body_discriminator.py @@ -154,6 +154,8 @@ def test_discriminator_pydantic_v2() -> None: }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_union_body_discriminator_annotated.py b/tests/test_union_body_discriminator_annotated.py index 42a6aed24c..6644d106c8 100644 --- a/tests/test_union_body_discriminator_annotated.py +++ b/tests/test_union_body_discriminator_annotated.py @@ -181,6 +181,8 @@ def test_openapi_schema(client: TestClient) -> None: }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py index 018949f0c7..d90d0753a9 100644 --- a/tests/test_union_forms.py +++ b/tests/test_union_forms.py @@ -136,6 +136,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] diff --git a/tests/test_union_inherited_body.py b/tests/test_union_inherited_body.py index 3c062e7f5a..6b284c68c3 100644 --- a/tests/test_union_inherited_body.py +++ b/tests/test_union_inherited_body.py @@ -117,6 +117,8 @@ def test_openapi_schema(): }, "msg": {"title": "Message", "type": "string"}, "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, "HTTPValidationError": { diff --git a/tests/test_webhooks_security.py b/tests/test_webhooks_security.py index 982ae1e21d..c2c2809b2f 100644 --- a/tests/test_webhooks_security.py +++ b/tests/test_webhooks_security.py @@ -106,6 +106,8 @@ def test_openapi_schema(): }, "ValidationError": { "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, "loc": { "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] From 4a3a71f1c15c415c60faab3de59e35b97dd632e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 14:34:39 +0000 Subject: [PATCH 092/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8d90983d44..b4fd20de20 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Fixes +* ๐Ÿ› Update `ValidationError` schema to include `input` and `ctx`. PR [#14791](https://github.com/fastapi/fastapi/pull/14791) by [@jonathan-fulton](https://github.com/jonathan-fulton). * ๐Ÿ› Fix TYPE_CHECKING annotations for Python 3.14 (PEP 649). PR [#14789](https://github.com/fastapi/fastapi/pull/14789) by [@mgu](https://github.com/mgu). * ๐Ÿ› Strip whitespaces from `Authorization` header credentials. PR [#14786](https://github.com/fastapi/fastapi/pull/14786) by [@WaveTheory1](https://github.com/WaveTheory1). * ๐Ÿ› Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). From ee0c12521fa0817cc19a4cbbd949c1e9d5fec1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 06:35:17 -0800 Subject: [PATCH 093/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20for=20co?= =?UTF-8?q?ntributing=20translations,=20simplify=20title=20(#14817)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 1505dfd1e9..5e6d821b31 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -181,7 +181,7 @@ Help with translations is VERY MUCH appreciated! And it can't be done without th Here are the steps to help with translations. -#### Review Translation PRs +#### Translation PRs Translation pull requests are made by LLMs guided with prompts designed by the FastAPI team together with the community of native speakers for each supported language. From fe5b617aecaeba0261dc8c7a1b82afe483814cd2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 14:36:09 +0000 Subject: [PATCH 094/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b4fd20de20..937e2930df 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -27,6 +27,7 @@ hide: ### Docs +* ๐Ÿ“ Update docs for contributing translations, simplify title. PR [#14817](https://github.com/fastapi/fastapi/pull/14817) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Fix typing issue in `docs_src/app_testing/app_b` code example. PR [#14573](https://github.com/fastapi/fastapi/pull/14573) by [@timakaa](https://github.com/timakaa). * ๐Ÿ“ Fix example of license identifier in documentation. PR [#14492](https://github.com/fastapi/fastapi/pull/14492) by [@johnson-earls](https://github.com/johnson-earls). * ๐Ÿ“ Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov). From aea61373ae0c97b32611fc2dc993e84a9729edf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 06:49:18 -0800 Subject: [PATCH 095/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20translation=20scri?= =?UTF-8?q?pt=20commit=20in=20place=20(#14818)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/translate.py b/scripts/translate.py index 9eda7b3903..072383514b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -411,7 +411,8 @@ def make_pr( print(f"Creating a new branch {branch_name}") subprocess.run(["git", "checkout", "-b", branch_name], check=True) else: - print(f"Committing in place on branch {current_branch}") + branch_name = current_branch + print(f"Committing in place on branch {branch_name}") print("Adding updated files") git_path = Path("docs") subprocess.run(["git", "add", str(git_path)], check=True) From cec4be00ba524427cc52e9894112199c27fce9f1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 14:49:41 +0000 Subject: [PATCH 096/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 937e2930df..1a56e5eca9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -68,6 +68,7 @@ hide: ### Internal +* ๐Ÿ› Fix translation script commit in place. PR [#14818](https://github.com/fastapi/fastapi/pull/14818) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update translation script to retry if LLM-response doesn't pass validation with Translation Fixer tool. PR [#14749](https://github.com/fastapi/fastapi/pull/14749) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov). From b0e99d66e80426f3f13dd4bcbcb78d2a39ec10b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 08:44:21 -0800 Subject: [PATCH 097/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(update-outdated)=20(#14588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Maruo.S --- docs/en/mkdocs.yml | 2 + .../docs/advanced/additional-status-codes.md | 34 +- docs/ja/docs/advanced/custom-response.md | 216 ++++++--- docs/ja/docs/advanced/index.md | 24 +- .../path-operation-advanced-configuration.md | 157 +++++- docs/ja/docs/advanced/response-directly.md | 14 +- docs/ja/docs/advanced/websockets.md | 72 ++- docs/ja/docs/benchmarks.md | 36 +- docs/ja/docs/deployment/concepts.md | 92 ++-- docs/ja/docs/deployment/docker.md | 428 ++++++---------- docs/ja/docs/deployment/https.md | 86 ++-- docs/ja/docs/deployment/index.md | 24 +- docs/ja/docs/deployment/server-workers.md | 170 +++---- docs/ja/docs/deployment/versions.md | 72 +-- docs/ja/docs/environment-variables.md | 115 +++-- docs/ja/docs/how-to/conditional-openapi.md | 12 +- docs/ja/docs/index.md | 455 +++++++++++------- docs/ja/docs/learn/index.md | 4 +- docs/ja/docs/project-generation.md | 112 ++--- docs/ja/docs/python-types.md | 356 ++++++++++---- docs/ja/docs/tutorial/background-tasks.md | 46 +- docs/ja/docs/tutorial/body-fields.md | 22 +- docs/ja/docs/tutorial/body-multiple-params.md | 63 +-- docs/ja/docs/tutorial/body-nested-models.md | 108 ++--- docs/ja/docs/tutorial/body-updates.md | 38 +- docs/ja/docs/tutorial/body.md | 138 +++--- docs/ja/docs/tutorial/cookie-param-models.md | 25 +- docs/ja/docs/tutorial/cookie-params.md | 24 +- docs/ja/docs/tutorial/cors.md | 42 +- docs/ja/docs/tutorial/debugging.md | 14 +- .../dependencies/classes-as-dependencies.md | 150 +++++- ...pendencies-in-path-operation-decorators.md | 62 ++- .../dependencies/dependencies-with-yield.md | 177 ++++--- docs/ja/docs/tutorial/dependencies/index.md | 128 +++-- .../tutorial/dependencies/sub-dependencies.md | 49 +- docs/ja/docs/tutorial/encoder.md | 10 +- docs/ja/docs/tutorial/extra-data-types.md | 42 +- docs/ja/docs/tutorial/extra-models.md | 90 ++-- docs/ja/docs/tutorial/first-steps.md | 198 +++++--- docs/ja/docs/tutorial/handling-errors.md | 103 ++-- docs/ja/docs/tutorial/header-params.md | 36 +- docs/ja/docs/tutorial/index.md | 90 ++-- docs/ja/docs/tutorial/metadata.md | 105 ++-- docs/ja/docs/tutorial/middleware.md | 47 +- .../tutorial/path-operation-configuration.md | 58 ++- .../path-params-numeric-validations.md | 109 +++-- docs/ja/docs/tutorial/path-params.md | 123 ++--- docs/ja/docs/tutorial/query-param-models.md | 22 +- .../tutorial/query-params-str-validations.md | 336 ++++++++++--- docs/ja/docs/tutorial/query-params.md | 64 +-- .../docs/tutorial/request-forms-and-files.md | 20 +- docs/ja/docs/tutorial/request-forms.md | 24 +- docs/ja/docs/tutorial/response-model.md | 295 ++++++++---- docs/ja/docs/tutorial/response-status-code.md | 40 +- docs/ja/docs/tutorial/schema-extra-example.md | 199 +++++++- docs/ja/docs/tutorial/security/first-steps.md | 66 +-- .../tutorial/security/get-current-user.md | 47 +- docs/ja/docs/tutorial/security/oauth2-jwt.md | 88 ++-- docs/ja/docs/tutorial/static-files.md | 18 +- docs/ja/docs/tutorial/testing.md | 99 +++- docs/ja/docs/virtual-environments.md | 102 ++-- docs/ja/llm-prompt.md | 3 +- scripts/docs.py | 1 + 63 files changed, 3599 insertions(+), 2403 deletions(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 1c29546198..34d489d92a 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -317,6 +317,8 @@ extra: name: de - Deutsch - link: /es/ name: es - espaรฑol + - link: /ja/ + name: ja - ๆ—ฅๆœฌ่ชž - link: /ko/ name: ko - ํ•œ๊ตญ์–ด - link: /pt/ diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index 33457f591c..14b7e8ba87 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -1,41 +1,41 @@ -# ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ +# ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ { #additional-status-codes } -ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€ **FastAPI** ใฏ `JSONResponse` ใ‚’ไฝฟใฃใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ใใฎ `JSONResponse` ใฎไธญใซใฏใ€ *path operation* ใŒ่ฟ”ใ—ใŸๅ†…ๅฎนใŒๅ…ฅใ‚Šใพใ™ใ€‚ +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€ **FastAPI** ใฏ `JSONResponse` ใ‚’ไฝฟใฃใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใ€*path operation* ใ‹ใ‚‰่ฟ”ใ—ใŸๅ†…ๅฎนใ‚’ใใฎ `JSONResponse` ใฎไธญใซๅ…ฅใ‚Œใพใ™ใ€‚ -ใใ‚Œใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‹ใ€ *path operation* ใงใ‚ปใƒƒใƒˆใ—ใŸใ‚‚ใฎใ‚’ๅˆฉ็”จใ—ใพใ™ใ€‚ +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ€ใพใŸใฏ *path operation* ใง่จญๅฎšใ—ใŸใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใŒไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -## ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ +## ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ { #additional-status-codes_1 } -ใƒกใ‚คใƒณใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใฏๅˆฅใซใ€ไป–ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’่ฟ”ใ—ใŸใ„ๅ ดๅˆใฏใ€`Response` (`JSONResponse` ใชใฉ) ใซ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’่จญๅฎšใ—ใฆ็›ดๆŽฅ่ฟ”ใ—ใพใ™ใ€‚ +ใƒกใ‚คใƒณใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใฏๅˆฅใซ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’่ฟ”ใ—ใŸใ„ๅ ดๅˆใฏใ€`JSONResponse` ใฎใ‚ˆใ†ใช `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ—ใ€่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’็›ดๆŽฅ่จญๅฎšใงใใพใ™ใ€‚ -ไพ‹ใˆใฐใ€itemใ‚’ๆ›ดๆ–ฐใ—ใ€ๆˆๅŠŸใ—ใŸๅ ดๅˆใฏ200 "OK"ใฎHTTPใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’่ฟ”ใ™ *path operation* ใ‚’ไฝœใ‚ŠใŸใ„ใจใ—ใพใ™ใ€‚ +ใŸใจใˆใฐใ€item ใ‚’ๆ›ดๆ–ฐใงใใ€ๆˆๅŠŸๆ™‚ใซ HTTP ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ 200 "OK" ใ‚’่ฟ”ใ™ *path operation* ใ‚’ไฝœใ‚ŠใŸใ„ใจใ—ใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ๆ–ฐใ—ใ„itemใ‚‚่จฑๅฏใ—ใŸใ„ใงใ™ใ€‚itemใŒๅญ˜ๅœจใ—ใชใ„ๅ ดๅˆใฏใ€ใใ‚Œใ‚‰ใ‚’ไฝœๆˆใ—ใฆ201 "Created"ใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ๆ–ฐใ—ใ„ item ใ‚‚ๅ—ใ‘ไป˜ใ‘ใŸใ„ใจใ—ใพใ™ใ€‚ใใ—ใฆใ€item ใŒไปฅๅ‰ๅญ˜ๅœจใ—ใชใ‹ใฃใŸๅ ดๅˆใซใฏไฝœๆˆใ—ใ€HTTP ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ 201ใ€ŒCreatedใ€ใ‚’่ฟ”ใ—ใพใ™ใ€‚ -ใ“ใ‚Œใ‚’้”ๆˆใ™ใ‚‹ใซใฏใ€ `JSONResponse` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€ `status_code` ใ‚’่จญๅฎšใ—ใฆ็›ดๆŽฅๅ†…ๅฎนใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ€`JSONResponse` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€ๆœ›ใ‚€ `status_code` ใ‚’่จญๅฎšใ—ใฆใ€ใใ“ใงๅ†…ๅฎนใ‚’็›ดๆŽฅ่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *} +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} /// warning | ๆณจๆ„ -ไธŠ่จ˜ใฎไพ‹ใฎใ‚ˆใ†ใซ `Response` ใ‚’ๆ˜Ž็คบ็š„ใซ่ฟ”ใ™ๅ ดๅˆใ€ใใ‚Œใฏ็›ดๆŽฅ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ +ไธŠใฎไพ‹ใฎใ‚ˆใ†ใซ `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใจใ€ใใ‚Œใฏใใฎใพใพ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ -ใƒขใƒ‡ใƒซใชใฉใฏใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ•ใ‚Œใพใ›ใ‚“ใ€‚ +ใƒขใƒ‡ใƒซใชใฉใซใ‚ˆใฃใฆใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ•ใ‚Œใพใ›ใ‚“ใ€‚ -ๅฟ…่ฆใชใƒ‡ใƒผใ‚ฟใŒๅซใพใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚„ใ€ๅ€คใŒๆœ‰ๅŠนใชJSONใงใ‚ใ‚‹ใ“ใจ (`JSONResponse` ใ‚’ไฝฟใ†ๅ ดๅˆ) ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +ๅฟ…่ฆใชใƒ‡ใƒผใ‚ฟใŒๅซใพใ‚Œใฆใ„ใ‚‹ใ“ใจใ€ใใ—ใฆ๏ผˆ`JSONResponse` ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆ๏ผ‰ๅ€คใŒๆœ‰ๅŠนใช JSON ใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ /// /// note | ๆŠ€่ก“่ฉณ็ดฐ -`from starlette.responses import JSONResponse` ใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +`from starlette.responses import JSONResponse` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -**FastAPI** ใฏ `fastapi.responses` ใจๅŒใ˜ `starlette.responses` ใ‚’ใ€้–‹็™บ่€…ใฎๅˆฉไพฟๆ€งใฎใŸใ‚ใซๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ๆœ‰ๅŠนใชใƒฌใ‚นใƒใƒณใ‚นใฏใปใจใ‚“ใฉStarletteใ‹ใ‚‰ๆฅใฆใ„ใพใ™ใ€‚ `status` ใซใคใ„ใฆใ‚‚ๅŒใ˜ใงใ™ใ€‚ +**FastAPI** ใฏ้–‹็™บ่€…ใฎๅˆฉไพฟๆ€งใฎใŸใ‚ใซใ€`fastapi.responses` ใจๅŒใ˜ `starlette.responses` ใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎใปใจใ‚“ใฉใฏ Starlette ใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚`status` ใ‚‚ๅŒๆง˜ใงใ™ใ€‚ /// -## OpenAPIใจAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +## OpenAPI ใจ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #openapi-and-api-docs } -ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใ€ใใ‚Œใ‚‰ใฏOpenAPIใ‚นใ‚ญใƒผใƒž (APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ) ใซใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚ใชใœใชใ‚‰ใ€FastAPIใฏไฝ•ใŒ่ฟ”ใ•ใ‚Œใ‚‹ใฎใ‹ไบ‹ๅ‰ใซ็Ÿฅใ‚‹ใ“ใจใŒใงใใชใ„ใ‹ใ‚‰ใงใ™ใ€‚ +่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใ€ใใ‚Œใ‚‰ใฏ OpenAPI ใ‚นใ‚ญใƒผใƒž๏ผˆAPI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ๏ผ‰ใซใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚FastAPI ใซใฏใ€ไบ‹ๅ‰ใซไฝ•ใŒ่ฟ”ใ•ใ‚Œใ‚‹ใ‹ใ‚’็Ÿฅใ‚‹ๆ–นๆณ•ใŒใชใ„ใ‹ใ‚‰ใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€ [Additional Responses](additional-responses.md){.internal-link target=_blank} ใ‚’ไฝฟใฃใฆใ‚ณใƒผใƒ‰ใฎไธญใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๆ›ธใใ“ใจใŒใงใใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€[Additional Responses](additional-responses.md){.internal-link target=_blank} ใ‚’ไฝฟใฃใฆใ‚ณใƒผใƒ‰ๅ†…ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/custom-response.md b/docs/ja/docs/advanced/custom-response.md index 1b2cd914d4..9d881c013c 100644 --- a/docs/ja/docs/advanced/custom-response.md +++ b/docs/ja/docs/advanced/custom-response.md @@ -1,34 +1,40 @@ -# ใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚น - HTMLใ€ใ‚นใƒˆใƒชใƒผใƒ ใ€ใƒ•ใ‚กใ‚คใƒซใ€ใใฎไป–ใฎใƒฌใ‚นใƒใƒณใ‚น +# ใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚น - HTMLใ€ใ‚นใƒˆใƒชใƒผใƒ ใ€ใƒ•ใ‚กใ‚คใƒซใ€ใใฎไป–ใฎใƒฌใ‚นใƒใƒณใ‚น { #custom-response-html-stream-file-others } ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€**FastAPI** ใฏ `JSONResponse` ใ‚’ไฝฟใฃใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ [ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™](response-directly.md){.internal-link target=_blank}ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€ `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใ“ใจใงใ“ใฎๆŒ™ๅ‹•ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€`Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใจใ€ใƒ‡ใƒผใ‚ฟใฏ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ•ใ‚Œใšใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚‚่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใพใ›ใ‚“ (ไพ‹ใˆใฐใ€็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใฎไธ€้ƒจใจใ—ใฆHTTPใƒ˜ใƒƒใƒ€ใƒผ `Content-Type` ใซ็‰นๅฎšใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅซใ‚ใ‚‹ใชใฉ) ใ€‚ +ใ—ใ‹ใ—ใ€`Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใจ๏ผˆใพใŸใฏ `JSONResponse` ใฎใ‚ˆใ†ใชไปปๆ„ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’่ฟ”ใ™ใจ๏ผ‰ใ€ใƒ‡ใƒผใ‚ฟใฏ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ•ใ‚Œใš๏ผˆ`response_model` ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใฆใ‚‚๏ผ‰ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚‚่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใพใ›ใ‚“๏ผˆไพ‹ใˆใฐใ€็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใฎไธ€้ƒจใจใ—ใฆHTTPใƒ˜ใƒƒใƒ€ใƒผ `Content-Type` ใซ็‰นๅฎšใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅซใ‚ใ‚‹ใชใฉ๏ผ‰ใ€‚ -ใ—ใ‹ใ—ใ€*path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใซใ€ไฝฟใ„ใŸใ„ `Response` ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +`response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ€*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใงไฝฟ็”จใ—ใŸใ„ `Response`๏ผˆไปปๆ„ใฎ `Response` ใ‚ตใƒ–ใ‚ฏใƒฉใ‚น๏ผ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -*path operation้–ขๆ•ฐ* ใ‹ใ‚‰่ฟ”ใ•ใ‚Œใ‚‹ใ‚ณใƒณใƒ†ใƒณใƒ„ใฏใ€ใใฎ `Response` ใซๅซใพใ‚Œใพใ™ใ€‚ +*path operation ้–ขๆ•ฐ* ใ‹ใ‚‰่ฟ”ใ•ใ‚Œใ‚‹ใ‚ณใƒณใƒ†ใƒณใƒ„ใฏใ€ใใฎ `Response` ใซๅซใพใ‚Œใพใ™ใ€‚ -ใใ—ใฆใ‚‚ใ—ใ€`Response` ใŒใ€`JSONResponse` ใ‚„ `UJSONResponse` ใฎๅ ดๅˆใฎใ‚ˆใ†ใซJSONใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ— (`application/json`) ใชใ‚‰ใฐใ€ใƒ‡ใƒผใ‚ฟใฏ *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใซๅฎฃ่จ€ใ—ใŸPydantic `response_model` ใซใ‚ˆใ‚Š่‡ชๅ‹•็š„ใซๅค‰ๆ› (ใ‚‚ใ—ใใฏใƒ•ใ‚ฃใƒซใ‚ฟ) ใ•ใ‚Œใพใ™ใ€‚ +ใใ—ใฆใใฎ `Response` ใŒใ€`JSONResponse` ใ‚„ `UJSONResponse` ใฎๅ ดๅˆใฎใ‚ˆใ†ใซJSONใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—๏ผˆ`application/json`๏ผ‰ใชใ‚‰ใ€้–ขๆ•ฐใฎ่ฟ”ใ‚Šๅ€คใฏ *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใซๅฎฃ่จ€ใ—ใŸไปปๆ„ใฎPydantic `response_model` ใซใ‚ˆใ‚Š่‡ชๅ‹•็š„ใซๅค‰ๆ›๏ผˆใŠใ‚ˆใณใƒ•ใ‚ฃใƒซใ‚ฟ๏ผ‰ใ•ใ‚Œใพใ™ใ€‚ /// note | ๅ‚™่€ƒ -ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’ๆŒ‡ๅฎšใ›ใšใซใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ๅˆฉ็”จใ™ใ‚‹ใจใ€FastAPIใฏไฝ•ใ‚‚ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒใชใ„ใ“ใจใ‚’ๆœŸๅพ…ใ—ใพใ™ใ€‚ใใฎใŸใ‚ใ€็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใƒฌใ‚นใƒใƒณใ‚นใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใŒ่จ˜่ผ‰ใ•ใ‚Œใพใ›ใ‚“ใ€‚ +ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’ๆŒ‡ๅฎšใ›ใšใซใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ๅˆฉ็”จใ™ใ‚‹ใจใ€FastAPIใฏใƒฌใ‚นใƒใƒณใ‚นใซใ‚ณใƒณใƒ†ใƒณใƒ„ใŒใชใ„ใ“ใจใ‚’ๆœŸๅพ…ใ—ใพใ™ใ€‚ใใฎใŸใ‚ใ€็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใƒฌใ‚นใƒใƒณใ‚นใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใŒ่จ˜่ผ‰ใ•ใ‚Œใพใ›ใ‚“ใ€‚ /// -## `ORJSONResponse` ใ‚’ไฝฟใ† +## `ORJSONResponse` ใ‚’ไฝฟใ† { #use-orjsonresponse } -ไพ‹ใˆใฐใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’ๅ‡บใ—ใŸใ„ๅ ดๅˆใฏใ€`orjson`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใ€`ORJSONResponse`ใ‚’ใƒฌใ‚นใƒใƒณใ‚นใจใ—ใฆใ‚ปใƒƒใƒˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ไพ‹ใˆใฐใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’็ตžใ‚Šๅ‡บใ—ใŸใ„ๅ ดๅˆใฏใ€`orjson`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใ€ใƒฌใ‚นใƒใƒณใ‚นใจใ—ใฆ `ORJSONResponse` ใ‚’ใ‚ปใƒƒใƒˆใงใใพใ™ใ€‚ -ไฝฟใ„ใŸใ„ `Response` ใ‚ฏใƒฉใ‚น (ใ‚ตใƒ–ใ‚ฏใƒฉใ‚น) ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€ *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใซๅฎฃ่จ€ใ—ใพใ™ใ€‚ +ไฝฟใ„ใŸใ„ `Response` ใ‚ฏใƒฉใ‚น๏ผˆใ‚ตใƒ–ใ‚ฏใƒฉใ‚น๏ผ‰ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€*path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใซๅฎฃ่จ€ใ—ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *} +ๅคงใใชใƒฌใ‚นใƒใƒณใ‚นใฎๅ ดๅˆใ€`Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใปใ†ใŒใ€่พžๆ›ธใ‚’่ฟ”ใ™ใ‚ˆใ‚Šใ‚‚ใฏใ‚‹ใ‹ใซ้ซ˜้€Ÿใงใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏFastAPIใŒใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใง่ชฌๆ˜Žใ—ใŸๅŒใ˜[JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}ใ‚’ไฝฟใฃใฆใ€ๅ†…้ƒจใฎๅ„ใ‚ขใ‚คใƒ†ใƒ ใ‚’ๆคœๆŸปใ—ใ€JSONใจใ—ใฆใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บๅฏ่ƒฝใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ไพ‹ใˆใฐใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใช**ไปปๆ„ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ**ใ‚’่ฟ”ใ›ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€่ฟ”ใใ†ใจใ—ใฆใ„ใ‚‹ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒ **JSONใงใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บๅฏ่ƒฝ**ใงใ‚ใ‚‹ใ“ใจใŒ็ขบๅฎŸใชใ‚‰ใ€ใใ‚Œใ‚’็›ดๆŽฅใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใซๆธกใ—ใฆใ€FastAPIใŒใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใธๆธกใ™ๅ‰ใซ่ฟ”ๅดใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ `jsonable_encoder` ใซ้€šใ™ใ“ใจใง็™บ็”Ÿใ™ใ‚‹่ฟฝๅŠ ใฎใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใ‚’ๅ›ž้ฟใงใใพใ™ใ€‚ + +{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} /// info | ๆƒ…ๅ ฑ -ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซๅˆฉ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซใ‚‚ๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ ใ“ใฎๅ ดๅˆใ€HTTPใƒ˜ใƒƒใƒ€ใƒผ `Content-Type` ใซใฏ `application/json` ใŒใ‚ปใƒƒใƒˆใ•ใ‚Œใพใ™ใ€‚ @@ -38,70 +44,70 @@ /// tip | ่ฑ†็Ÿฅ่ญ˜ -`ORJSONResponse` ใฏใ€็พๅœจใฏFastAPIใฎใฟใงๅˆฉ็”จๅฏ่ƒฝใงใ€Starletteใงใฏๅˆฉ็”จใงใใพใ›ใ‚“ใ€‚ +`ORJSONResponse` ใฏFastAPIใงใฎใฟๅˆฉ็”จๅฏ่ƒฝใงใ€Starletteใงใฏๅˆฉ็”จใงใใพใ›ใ‚“ใ€‚ /// -## HTMLใƒฌใ‚นใƒใƒณใ‚น +## HTMLใƒฌใ‚นใƒใƒณใ‚น { #html-response } **FastAPI** ใ‹ใ‚‰HTMLใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใฏใ€`HTMLResponse` ใ‚’ไฝฟใ„ใพใ™ใ€‚ * `HTMLResponse` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ€‚ -* *path operation* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `content_type` ใซ `HTMLResponse` ใ‚’ๆธกใ™ใ€‚ +* *path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใซ `HTMLResponse` ใ‚’ๆธกใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} /// info | ๆƒ…ๅ ฑ -ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซใ‚‚ๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ ใ“ใฎๅ ดๅˆใ€HTTPใƒ˜ใƒƒใƒ€ใƒผ `Content-Type` ใซใฏ `text/html` ใŒใ‚ปใƒƒใƒˆใ•ใ‚Œใพใ™ใ€‚ -ใใ—ใฆใ€OpenAPIใซใฏใใฎใ‚ˆใ†ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ•ใ‚Œใพใ™ใ€‚ +ใใ—ใฆใ€OpenAPIใซใฏใใฎใ‚ˆใ†ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ•ใ‚Œใพใ™ใ€‚ /// -### `Response` ใ‚’่ฟ”ใ™ +### `Response` ใ‚’่ฟ”ใ™ { #return-a-response } -[ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™](response-directly.md){.internal-link target=_blank}ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ใ“ใจใงใ€*path operation* ใฎไธญใงใƒฌใ‚นใƒใƒณใ‚นใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ +[ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™](response-directly.md){.internal-link target=_blank}ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ™ใ“ใจใงใ€*path operation* ใฎไธญใงใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ไธŠ่จ˜ใจๅŒใ˜ไพ‹ใซใŠใ„ใฆใ€ `HTMLResponse` ใ‚’่ฟ”ใ™ใจใ€ใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} /// warning | ๆณจๆ„ -*path operation้–ขๆ•ฐ* ใ‹ใ‚‰็›ดๆŽฅ่ฟ”ใ•ใ‚Œใ‚‹ `Response` ใฏใ€OpenAPIใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ•ใ‚Œใš (ไพ‹ใˆใฐใ€ `Content-Type` ใŒใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ•ใ‚Œใชใ„) ใ€่‡ชๅ‹•็š„ใชๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰ใ‚‚้–ฒ่ฆงใงใใพใ›ใ‚“ใ€‚ +*path operation้–ขๆ•ฐ* ใ‹ใ‚‰็›ดๆŽฅ่ฟ”ใ•ใ‚Œใ‚‹ `Response` ใฏใ€OpenAPIใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ•ใ‚Œใš๏ผˆไพ‹ใˆใฐใ€`Content-Type` ใŒใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ•ใ‚Œใชใ„๏ผ‰ใ€่‡ชๅ‹•็š„ใชๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ‚‚่กจ็คบใ•ใ‚Œใพใ›ใ‚“ใ€‚ /// /// info | ๆƒ…ๅ ฑ -ใ‚‚ใกใ‚ใ‚“ใ€ๅฎŸ้š›ใฎ `Content-Type` ใƒ˜ใƒƒใƒ€ใƒผใ‚„ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใชใฉใฏใ€่ฟ”ใ•ใ‚ŒใŸ `Response` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซ็”ฑๆฅใ—ใฆใ„ใพใ™ใ€‚ +ใ‚‚ใกใ‚ใ‚“ใ€ๅฎŸ้š›ใฎ `Content-Type` ใƒ˜ใƒƒใƒ€ใƒผใ‚„ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใชใฉใฏใ€่ฟ”ใ•ใ‚ŒใŸ `Response` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซ็”ฑๆฅใ—ใพใ™ใ€‚ /// -### OpenAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใจ `Response` ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ +### OpenAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใจ `Response` ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ { #document-in-openapi-and-override-response } -้–ขๆ•ฐใฎไธญใงใƒฌใ‚นใƒใƒณใ‚นใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใคใคใ‚‚ใ€OpenAPI ใซใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ—ใŸใ„ใชใ‚‰ใ€ `response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใ„ใ€ `Response` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ +้–ขๆ•ฐใฎไธญใงใƒฌใ‚นใƒใƒณใ‚นใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใคใคใ‚‚ใ€OpenAPI ใซใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ—ใŸใ„ใชใ‚‰ใ€`response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใ€ใ‹ใค `Response` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ -`response_class` ใฏOpenAPIใฎ *path operation* ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฎใฟไฝฟ็”จใ•ใ‚Œใพใ™ใŒใ€ `Response` ใฏใใฎใพใพไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +`response_class` ใฏOpenAPIใฎ*path operation*ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใฎใŸใ‚ใซใฎใฟไฝฟ็”จใ•ใ‚Œใ€`Response` ใฏใใฎใพใพไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -#### `HTMLResponse` ใ‚’็›ดๆŽฅ่ฟ”ใ™ +#### `HTMLResponse` ใ‚’็›ดๆŽฅ่ฟ”ใ™ { #return-an-htmlresponse-directly } ไพ‹ใˆใฐใ€ใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} -ใ“ใฎไพ‹ใงใฏใ€้–ขๆ•ฐ `generate_html_response()` ใฏใ€`str` ใฎHTMLใ‚’่ฟ”ใ™ใฎใงใฏใชใ `Response` ใ‚’็”Ÿๆˆใ—ใฆ่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ +ใ“ใฎไพ‹ใงใฏใ€้–ขๆ•ฐ `generate_html_response()` ใฏใ€`str` ใฎHTMLใ‚’่ฟ”ใ™ใฎใงใฏใชใใ€`Response` ใ‚’็”Ÿๆˆใ—ใฆ่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ -`generate_html_response()` ใ‚’ๅ‘ผใณๅ‡บใ—ใŸ็ตๆžœใ‚’่ฟ”ใ™ใ“ใจใซใ‚ˆใ‚Šใ€**FastAPI** ใฎๆŒฏใ‚‹่ˆžใ„ใ‚’ไธŠๆ›ธใใ™ใ‚‹ `Response` ใŒๆ—ขใซ่ฟ”ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +`generate_html_response()` ใ‚’ๅ‘ผใณๅ‡บใ—ใŸ็ตๆžœใ‚’่ฟ”ใ™ใ“ใจใซใ‚ˆใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ **FastAPI** ใฎๆŒ™ๅ‹•ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ `Response` ใ‚’ใ™ใงใซ่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ไธ€ๆ–นใงใฏ `response_class` ใซ `HTMLResponse` ใ‚’ๆธกใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ **FastAPI** ใฏOpenAPIใ‚„ๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงHTMLใจใ—ใฆ `text/html` ใงใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚‹ๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€`response_class` ใซใ‚‚ `HTMLResponse` ใ‚’ๆธกใ—ใฆใ„ใ‚‹ใŸใ‚ใ€**FastAPI** ใฏOpenAPIใจๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ€`text/html` ใฎHTMLใจใ—ใฆใฉใฎใ‚ˆใ†ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚Œใฐใ‚ˆใ„ใ‹ใ‚’็†่งฃใงใใพใ™: -## ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚น +## ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚น { #available-responses } ไปฅไธ‹ใŒๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใงใ™ใ€‚ @@ -111,11 +117,11 @@ `from starlette.responses import HTMLResponse` ใ‚‚ๅˆฉ็”จใงใใพใ™ใ€‚ -**FastAPI** ใฏ้–‹็™บ่€…ใฎๅˆฉไพฟๆ€งใฎใŸใ‚ใซ `fastapi.responses` ใจใ—ใฆ `starlette.responses` ใจๅŒใ˜ใ‚‚ใฎใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎใปใจใ‚“ใฉใฏStarletteใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใพใ™ใ€‚ +**FastAPI** ใฏ้–‹็™บ่€…ใฎๅˆฉไพฟๆ€งใฎใŸใ‚ใซใ€`starlette.responses` ใจๅŒใ˜ใ‚‚ใฎใ‚’ `fastapi.responses` ใจใ—ใฆๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎใปใจใ‚“ใฉใฏStarletteใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใพใ™ใ€‚ /// -### `Response` +### `Response` { #response } ใƒกใ‚คใƒณใฎ `Response` ใ‚ฏใƒฉใ‚นใงใ€ไป–ใฎๅ…จใฆใฎใƒฌใ‚นใƒใƒณใ‚นใฏใ“ใ‚Œใ‚’็ถ™ๆ‰ฟใ—ใฆใ„ใพใ™ใ€‚ @@ -128,41 +134,53 @@ * `headers` - ๆ–‡ๅญ—ๅˆ—ใฎ `dict` ใ€‚ * `media_type` - ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’็คบใ™ `str` ใ€‚ไพ‹ใˆใฐ `"text/html"` ใ€‚ -FastAPI (ๅฎŸ้š›ใซใฏStarlette) ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใพใ™ใ€‚ใพใŸใ€media_typeใซๅŸบใฅใ„ใŸContent-Typeใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใ€ใƒ†ใ‚ญใ‚นใƒˆใ‚ฟใ‚คใƒ—ใฎใŸใ‚ใซcharsetใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ +FastAPI๏ผˆๅฎŸ้š›ใซใฏStarlette๏ผ‰ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใพใ™ใ€‚ใพใŸใ€`media_type` ใซๅŸบใฅใ„ใŸContent-Typeใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใ€ใƒ†ใ‚ญใ‚นใƒˆใ‚ฟใ‚คใƒ—ใฎใŸใ‚ใซcharsetใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ -{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} -### `HTMLResponse` +### `HTMLResponse` { #htmlresponse } ไธŠใง่ชญใ‚“ใ ใ‚ˆใ†ใซใ€ใƒ†ใ‚ญใ‚นใƒˆใ‚„ใƒใ‚คใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€HTMLใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ -### `PlainTextResponse` +### `PlainTextResponse` { #plaintextresponse } ใƒ†ใ‚ญใ‚นใƒˆใ‚„ใƒใ‚คใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒ—ใƒฌใƒผใƒณใƒ†ใ‚ญใ‚นใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} -### `JSONResponse` +### `JSONResponse` { #jsonresponse } -ใƒ‡ใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ `application/json` ใจใ—ใฆใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚ŒใŸใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ใƒ‡ใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€`application/json` ใจใ—ใฆใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚ŒใŸใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ ไธŠใง่ชญใ‚“ใ ใ‚ˆใ†ใซใ€**FastAPI** ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใจใ—ใฆๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ -### `ORJSONResponse` +### `ORJSONResponse` { #orjsonresponse } ไธŠใง่ชญใ‚“ใ ใ‚ˆใ†ใซใ€`orjson`ใ‚’ไฝฟใฃใŸใ€้ซ˜้€Ÿใชไปฃๆ›ฟใฎJSONใƒฌใ‚นใƒใƒณใ‚นใงใ™ใ€‚ -### `UJSONResponse` +/// info | ๆƒ…ๅ ฑ + +ใ“ใ‚Œใฏใ€ไพ‹ใˆใฐ `pip install orjson` ใง `orjson` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// + +### `UJSONResponse` { #ujsonresponse } `ujson`ใ‚’ไฝฟใฃใŸใ€ไปฃๆ›ฟใฎJSONใƒฌใ‚นใƒใƒณใ‚นใงใ™ใ€‚ +/// info | ๆƒ…ๅ ฑ + +ใ“ใ‚Œใฏใ€ไพ‹ใˆใฐ `pip install ujson` ใง `ujson` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// + /// warning | ๆณจๆ„ -`ujson` ใฏใ€ใ„ใใคใ‹ใฎใ‚จใƒƒใ‚ธใ‚ฑใƒผใ‚นใฎๅ–ใ‚Šๆ‰ฑใ„ใซใคใ„ใฆใ€Pythonใซใƒ“ใƒซใƒˆใ‚คใƒณใ•ใ‚ŒใŸๅฎŸ่ฃ…ใ‚ˆใ‚Šใ‚‚ไฝœใ‚Šใ“ใพใ‚Œใฆใ„ใพใ›ใ‚“ใ€‚ +`ujson` ใฏใ€ใ„ใใคใ‹ใฎใ‚จใƒƒใ‚ธใ‚ฑใƒผใ‚นใฎๅ–ใ‚Šๆ‰ฑใ„ใซใคใ„ใฆใ€Pythonใซใƒ“ใƒซใƒˆใ‚คใƒณใ•ใ‚ŒใŸๅฎŸ่ฃ…ใปใฉๆณจๆ„ๆทฑใใ‚ใ‚Šใพใ›ใ‚“ใ€‚ /// -{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -170,33 +188,61 @@ FastAPI (ๅฎŸ้š›ใซใฏStarlette) ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซ /// -### `RedirectResponse` +### `RedirectResponse` { #redirectresponse } + +HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰๏ผˆTemporary Redirect๏ผ‰ใจใชใ‚Šใพใ™ใ€‚ + +`RedirectResponse` ใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™: + +{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} + +--- + +ใพใŸใฏใ€`response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงไฝฟ็”จใงใใพใ™: + +{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} + +ใใฎๅ ดๅˆใ€*path operation*้–ขๆ•ฐใ‹ใ‚‰URLใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™ใ€‚ -HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ (Temporary Redirect) ใจใชใ‚Šใพใ™ใ€‚ +ใ“ใฎๅ ดๅˆใซไฝฟ็”จใ•ใ‚Œใ‚‹ `status_code` ใฏ `RedirectResponse` ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใ‚ใ‚‹ `307` ใซใชใ‚Šใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *} +--- -### `StreamingResponse` +ใพใŸใ€`status_code` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจ็ต„ใฟๅˆใ‚ใ›ใฆไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -้žๅŒๆœŸใชใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใ‹้€šๅธธใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒปใ‚คใƒ†ใƒฌใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃใ‚’ใ‚นใƒˆใƒชใƒผใƒ ใ—ใพใ™ใ€‚ +{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} -{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} +### `StreamingResponse` { #streamingresponse } -#### `StreamingResponse` ใ‚’ใƒ•ใ‚กใ‚คใƒซใƒฉใ‚คใ‚ฏใชใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใจใจใ‚‚ใซไฝฟใ† +้žๅŒๆœŸใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใ€ใพใŸใฏ้€šๅธธใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ/ใ‚คใƒ†ใƒฌใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃใ‚’ใ‚นใƒˆใƒชใƒผใƒ ใ—ใพใ™ใ€‚ -ใƒ•ใ‚กใ‚คใƒซใƒฉใ‚คใ‚ฏใชใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ (ไพ‹ใˆใฐใ€ `open()` ใง่ฟ”ใ•ใ‚ŒใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ) ใŒใ‚ใ‚‹ๅ ดๅˆใ€ `StreamingResponse` ใซๅซใ‚ใฆ่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚ +{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} -ใ“ใ‚Œใซใฏใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚นใƒˆใƒฌใƒผใ‚ธใจใฎ้€ฃๆบใ‚„ๆ˜ ๅƒๅ‡ฆ็†ใชใฉใ€ๅคšใใฎใƒฉใ‚คใƒ–ใƒฉใƒชใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ +#### ใƒ•ใ‚กใ‚คใƒซใƒฉใ‚คใ‚ฏใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใง `StreamingResponse` ใ‚’ไฝฟใ† { #using-streamingresponse-with-file-like-objects } -{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *} +file-like ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆไพ‹: `open()` ใง่ฟ”ใ•ใ‚Œใ‚‹ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใŒใ‚ใ‚‹ๅ ดๅˆใ€ใใฎfile-likeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅๅพฉๅ‡ฆ็†ใ™ใ‚‹ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใ‚’ไฝœใ‚Œใพใ™ใ€‚ + +ใใ†ใ™ใ‚Œใฐใ€ๆœ€ๅˆใซใ™ในใฆใ‚’ใƒกใƒขใƒชใธ่ชญใฟ่พผใ‚€ๅฟ…่ฆใฏใชใใ€ใใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใ‚’ `StreamingResponse` ใซๆธกใ—ใฆ่ฟ”ใ›ใพใ™ใ€‚ + +ใ“ใ‚Œใซใฏใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚นใƒˆใƒฌใƒผใ‚ธใจใฎ้€ฃๆบใ€ๆ˜ ๅƒๅ‡ฆ็†ใชใฉใ€ๅคšใใฎใƒฉใ‚คใƒ–ใƒฉใƒชใŒๅซใพใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} + +1. ใ“ใ‚Œใฏใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใงใ™ใ€‚ๅ†…้ƒจใซ `yield` ๆ–‡ใ‚’ๅซใ‚€ใŸใ‚ใ€Œใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใ€ใงใ™ใ€‚ +2. `with` ใƒ–ใƒญใƒƒใ‚ฏใ‚’ไฝฟใ†ใ“ใจใงใ€ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใŒ็ต‚ใ‚ใฃใŸๅพŒ๏ผˆใคใพใ‚Šใƒฌใ‚นใƒใƒณใ‚นใฎ้€ไฟกใŒๅฎŒไบ†ใ—ใŸๅพŒ๏ผ‰ใซfile-likeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒ็ขบๅฎŸใซใ‚ฏใƒญใƒผใ‚บใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ +3. ใ“ใฎ `yield from` ใฏใ€`file_like` ใจใ„ใ†ๅๅ‰ใฎใ‚‚ใฎใ‚’ๅๅพฉๅ‡ฆ็†ใ™ใ‚‹ใ‚ˆใ†ใซ้–ขๆ•ฐใธๆŒ‡็คบใ—ใพใ™ใ€‚ใใ—ใฆๅๅพฉใ•ใ‚ŒใŸๅ„ใƒ‘ใƒผใƒˆใซใคใ„ใฆใ€ใใฎใƒ‘ใƒผใƒˆใ‚’ใ“ใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐ๏ผˆ`iterfile`๏ผ‰ใ‹ใ‚‰ๆฅใŸใ‚‚ใฎใจใ—ใฆ `yield` ใ—ใพใ™ใ€‚ + + ใคใพใ‚Šใ€ๅ†…้ƒจ็š„ใซใ€Œ็”Ÿๆˆใ€ใฎไฝœๆฅญใ‚’ๅˆฅใฎใ‚‚ใฎใธ็งป่ญฒใ™ใ‚‹ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใงใ™ใ€‚ + + ใ“ใฎใ‚ˆใ†ใซใ™ใ‚‹ใ“ใจใง `with` ใƒ–ใƒญใƒƒใ‚ฏใซๅ…ฅใ‚Œใ‚‰ใ‚Œใ€ๅฎŒไบ†ๅพŒใซfile-likeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒ็ขบๅฎŸใซใ‚ฏใƒญใƒผใ‚บใ•ใ‚Œใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ“ใ“ใงใฏ `async` ใ‚„ `await` ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ„ๆจ™ๆบ–ใฎ `open()` ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใฎใงใ€้€šๅธธใฎ `def` ใงpath operationใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +ใ“ใ“ใงใฏ `async` ใจ `await` ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ„ๆจ™ๆบ–ใฎ `open()` ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใŸใ‚ใ€้€šๅธธใฎ `def` ใงpath operationใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// -### `FileResponse` +### `FileResponse` { #fileresponse } ใƒฌใ‚นใƒใƒณใ‚นใจใ—ใฆใƒ•ใ‚กใ‚คใƒซใ‚’้žๅŒๆœŸ็š„ใซใ‚นใƒˆใƒชใƒผใƒ ใ—ใพใ™ใ€‚ @@ -204,29 +250,63 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น * `path` - ใ‚นใƒˆใƒชใƒผใƒ ใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซใฎใƒ•ใ‚กใ‚คใƒซใƒ‘ใ‚นใ€‚ * `headers` - ๅซใ‚ใŸใ„ไปปๆ„ใฎใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใฎ่พžๆ›ธใ€‚ -* `media_type` - ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’็คบใ™ๆ–‡ๅญ—ๅˆ—ใ€‚ใ‚ปใƒƒใƒˆใ•ใ‚Œใชใ‹ใฃใŸๅ ดๅˆใฏใ€ใƒ•ใ‚กใ‚คใƒซๅใ‚„ใƒ‘ใ‚นใ‹ใ‚‰ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใŒๆŽจๅฏŸใ•ใ‚Œใพใ™ใ€‚ -* `filename` - ใ‚ปใƒƒใƒˆใ•ใ‚ŒใŸๅ ดๅˆใ€ใƒฌใ‚นใƒใƒณใ‚นใฎ `Content-Disposition` ใซๅซใพใ‚Œใพใ™ใ€‚ +* `media_type` - ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’็คบใ™ๆ–‡ๅญ—ๅˆ—ใ€‚ๆœช่จญๅฎšใฎๅ ดๅˆใ€ใƒ•ใ‚กใ‚คใƒซๅใ‚„ใƒ‘ใ‚นใ‹ใ‚‰ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใŒๆŽจๆธฌใ•ใ‚Œใพใ™ใ€‚ +* `filename` - ่จญๅฎšใ—ใŸๅ ดๅˆใ€ใƒฌใ‚นใƒใƒณใ‚นใฎ `Content-Disposition` ใซๅซใพใ‚Œใพใ™ใ€‚ + +ใƒ•ใ‚กใ‚คใƒซใƒฌใ‚นใƒใƒณใ‚นใซใฏใ€้ฉๅˆ‡ใช `Content-Length`ใ€`Last-Modified`ใ€`ETag` ใƒ˜ใƒƒใƒ€ใƒผใŒๅซใพใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} + +`response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: + +{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} + +ใ“ใฎๅ ดๅˆใ€*path operation*้–ขๆ•ฐใ‹ใ‚‰ใƒ•ใ‚กใ‚คใƒซใƒ‘ใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™ใ€‚ + +## ใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚น { #custom-response-class } + +`Response` ใ‚’็ถ™ๆ‰ฟใ—ใŸ็‹ฌ่‡ชใฎใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใฆๅˆฉ็”จใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`orjson`ใ‚’ไฝฟใ„ใŸใ„ใŒใ€ๅŒๆขฑใฎ `ORJSONResponse` ใ‚ฏใƒฉใ‚นใงไฝฟใ‚ใ‚Œใฆใ„ใชใ„ใ‚ซใ‚นใ‚ฟใƒ ่จญๅฎšใ‚‚ไฝฟใ„ใŸใ„ใจใ—ใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ‚คใƒณใƒ‡ใƒณใƒˆใ•ใ‚Œๆ•ดๅฝขใ•ใ‚ŒใŸJSONใ‚’่ฟ”ใ—ใŸใ„ใฎใงใ€orjsonใ‚ชใƒ—ใ‚ทใƒงใƒณ `orjson.OPT_INDENT_2` ใ‚’ไฝฟใ„ใŸใ„ใจใ—ใพใ™ใ€‚ + +`CustomORJSONResponse` ใ‚’ไฝœใ‚Œใพใ™ใ€‚ไธปใซๅฟ…่ฆใชใฎใฏใ€ใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ `bytes` ใจใ—ใฆ่ฟ”ใ™ `Response.render(content)` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝœใ‚‹ใ“ใจใงใ™: + +{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} + +ใ“ใ‚Œใพใงใฏๆฌกใฎใ‚ˆใ†ใซ่ฟ”ใ—ใฆใ„ใŸใ‚‚ใฎใŒ: + +```json +{"message": "Hello World"} +``` + +...ใ“ใฎใƒฌใ‚นใƒใƒณใ‚นใงใฏๆฌกใฎใ‚ˆใ†ใซ่ฟ”ใ•ใ‚Œใพใ™: -ใƒ•ใ‚กใ‚คใƒซใƒฌใ‚นใƒใƒณใ‚นใซใฏใ€้ฉๅˆ‡ใช `Content-Length` ใ€ `Last-Modified` ใ€ `ETag` ใƒ˜ใƒƒใƒ€ใƒผใŒๅซใพใ‚Œใพใ™ใ€‚ +```json +{ + "message": "Hello World" +} +``` -{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *} +ใ‚‚ใกใ‚ใ‚“ใ€JSONใฎๆ•ดๅฝขใ‚ˆใ‚Šใ‚‚ใ€ใ“ใ‚Œใ‚’ๆดป็”จใ™ใ‚‹ใ‚‚ใฃใจ่‰ฏใ„ๆ–นๆณ•ใŒ่ฆ‹ใคใ‹ใ‚‹ใฏใšใงใ™ใ€‚ ๐Ÿ˜‰ -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚น +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚น { #default-response-class } -**FastAPI** ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‹ `APIRouter` ใ‚’็”Ÿๆˆใ™ใ‚‹ใจใใซใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ +**FastAPI** ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใพใŸใฏ `APIRouter` ใ‚’ไฝœๆˆใ™ใ‚‹้š›ใซใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงไฝฟ็”จใ™ใ‚‹ใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ -ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€ `default_response_class` ใงใ™ใ€‚ +ใ“ใ‚Œใ‚’ๅฎš็พฉใ™ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ `default_response_class` ใงใ™ใ€‚ -ไปฅไธ‹ใฎไพ‹ใงใฏใ€ **FastAPI** ใฏใ€ๅ…จใฆใฎ *path operation* ใง `JSONResponse` ใฎไปฃใ‚ใ‚Šใซ `ORJSONResponse` ใ‚’ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใจใ—ใฆๅˆฉ็”จใ—ใพใ™ใ€‚ +ไปฅไธ‹ใฎไพ‹ใงใฏใ€**FastAPI** ใฏใ™ในใฆใฎ*path operation*ใงใ€`JSONResponse` ใฎไปฃใ‚ใ‚Šใซ `ORJSONResponse` ใ‚’ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใจใ—ใฆไฝฟใ„ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ -ๅ‰ใซ่ฆ‹ใŸใ‚ˆใ†ใซใ€ *path operation* ใฎไธญใง `response_class` ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ +ใ“ใ‚ŒใพใงใจๅŒๆง˜ใซใ€*path operation*ใง `response_class` ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ /// -## ใใฎไป–ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +## ใใฎไป–ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #additional-documentation } -ใพใŸใ€OpenAPIใงใฏ `responses` ใ‚’ไฝฟใฃใฆใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚„ใใฎไป–ใฎ่ฉณ็ดฐใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} +OpenAPIใงใฏ `responses` ใ‚’ไฝฟใฃใฆใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚„ใใฎไป–ใฎ่ฉณ็ดฐใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/ja/docs/advanced/index.md b/docs/ja/docs/advanced/index.md index 22eaf6eb80..1d0f7566cd 100644 --- a/docs/ja/docs/advanced/index.md +++ b/docs/ja/docs/advanced/index.md @@ -1,27 +1,21 @@ -# ้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ +# ้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ { #advanced-user-guide } -## ใ•ใ‚‰ใชใ‚‹ๆฉŸ่ƒฝ +## ใ•ใ‚‰ใชใ‚‹ๆฉŸ่ƒฝ { #additional-features } -[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../tutorial/index.md){.internal-link target=_blank}ใซใ‚ˆใ‚Šใ€**FastAPI**ใฎไธป่ฆใชๆฉŸ่ƒฝใฏๅๅˆ†ใซ็†่งฃใงใใŸใ“ใจใงใ—ใ‚‡ใ†ใ€‚ +ใƒกใ‚คใƒณใฎ[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../tutorial/index.md){.internal-link target=_blank}ใ ใ‘ใงใ€**FastAPI**ใฎไธป่ฆใชๆฉŸ่ƒฝใ‚’ไธ€้€šใ‚ŠๆŠŠๆกใ™ใ‚‹ใซใฏๅๅˆ†ใชใฏใšใงใ™ใ€‚ -ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏ่ชฌๆ˜Žใ—ใใ‚Œใชใ‹ใฃใŸใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚„่จญๅฎšใ€ใŠใ‚ˆใณๆฉŸ่ƒฝใซใคใ„ใฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ +ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใใฎไป–ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ€่จญๅฎšใ€่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏใ€ **ๅฟ…ใšใ—ใ‚‚"ๅฟœ็”จ็ทจ"ใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ +ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏใ€**ๅฟ…ใšใ—ใ‚‚ใ€Œ้ซ˜ๅบฆใ€ใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ -ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซใ‚ˆใฃใฆใฏใ€ใใฎไธญใ‹ใ‚‰่งฃๆฑบ็ญ–ใ‚’่ฆ‹ใคใ‘ใ‚‰ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใพใŸใ€ใ‚ใชใŸใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซๅฏพใ™ใ‚‹่งฃๆฑบ็ญ–ใŒใ€ใใฎไธญใฎใฉใ‚Œใ‹ใซใ‚ใ‚‹ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ /// -## ๅ…ˆใซใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’่ชญใ‚€ +## ๅ…ˆใซใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’่ชญใ‚€ { #read-the-tutorial-first } -[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../tutorial/index.md){.internal-link target=_blank}ใฎ็Ÿฅ่ญ˜ใŒใ‚ใ‚Œใฐใ€**FastAPI**ใฎไธป่ฆใชๆฉŸ่ƒฝใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใƒกใ‚คใƒณใฎ[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../tutorial/index.md){.internal-link target=_blank}ใงๅพ—ใŸ็Ÿฅ่ญ˜ใŒใ‚ใ‚Œใฐใ€**FastAPI**ใฎๆฉŸ่ƒฝใฎๅคšใใฏๅผ•ใ็ถšใๅˆฉ็”จใงใใพใ™ใ€‚ -ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏใ€ใ™ใงใซใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’่ชญใ‚“ใงใ€ใใฎไธป่ฆใชใ‚ขใ‚คใƒ‡ใ‚ขใ‚’็†่งฃใงใใฆใ„ใ‚‹ใ“ใจใ‚’ๅ‰ๆใจใ—ใฆใ„ใพใ™ใ€‚ - -## ใƒ†ใ‚นใƒˆ้ง†ๅ‹•้–‹็™บใฎใ‚ณใƒผใ‚น - -ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎๅ†…ๅฎนใ‚’่ฃœๅฎŒใ™ใ‚‹ใŸใ‚ใซ่„ฑๅˆๅฟƒ่€…็”จใ‚ณใƒผใ‚นใ‚’ๅ—ใ‘ใŸใ„ๅ ดๅˆใฏใ€**TestDriven.io**ใซใ‚ˆใ‚‹ใ€Test-Driven Development with FastAPI and Dockerใ‚’็ขบ่ชใ™ใ‚‹ใฎใŒใ‚ˆใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ - -็พๅœจใ€ใ“ใฎใ‚ณใƒผใ‚นใงๅพ—ใ‚‰ใ‚ŒใŸๅˆฉ็›Šใฎ10%ใŒ**FastAPI**ใฎ้–‹็™บใฎใŸใ‚ใซๅฏ„ไป˜ใ•ใ‚Œใฆใ„ใพใ™ใ€‚๐ŸŽ‰ ๐Ÿ˜„ +ใพใŸใ€ไปฅ้™ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใ™ใงใซใใ‚Œใ‚’่ชญใ‚“ใงใ„ใฆใ€ไธป่ฆใช่€ƒใˆๆ–นใ‚’็†่งฃใ—ใฆใ„ใ‚‹ใ“ใจใ‚’ๅ‰ๆใจใ—ใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/path-operation-advanced-configuration.md b/docs/ja/docs/advanced/path-operation-advanced-configuration.md index 05188d5b25..a78c3cb026 100644 --- a/docs/ja/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ja/docs/advanced/path-operation-advanced-configuration.md @@ -1,30 +1,30 @@ -# Path Operationใฎ้ซ˜ๅบฆใช่จญๅฎš +# Path Operationใฎ้ซ˜ๅบฆใช่จญๅฎš { #path-operation-advanced-configuration } -## OpenAPI operationId +## OpenAPI operationId { #openapi-operationid } /// warning | ๆณจๆ„ -ใ‚ใชใŸใŒOpenAPIใฎใ€Œใ‚จใ‚ญใ‚นใƒ‘ใƒผใƒˆใ€ใงใชใ‘ใ‚Œใฐใ€ใ“ใ‚Œใฏๅฟ…่ฆใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +OpenAPIใฎใ€Œใ‚จใ‚ญใ‚นใƒ‘ใƒผใƒˆใ€ใงใชใ‘ใ‚Œใฐใ€ใ“ใ‚ŒใฏใŠใใ‚‰ใๅฟ…่ฆใ‚ใ‚Šใพใ›ใ‚“ใ€‚ /// *path operation* ใง `operation_id` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใงใ€OpenAPIใฎ `operationId` ใ‚’่จญๅฎšใงใใพใ™ใ€‚ -`operation_id` ใฏๅ„ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใงไธ€ๆ„ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ๅ„ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใงไธ€ๆ„ใซใชใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} -### *path operation้–ขๆ•ฐ* ใฎๅๅ‰ใ‚’operationIdใจใ—ใฆไฝฟ็”จใ™ใ‚‹ +### *path operation้–ขๆ•ฐ* ใฎๅๅ‰ใ‚’operationIdใจใ—ใฆไฝฟ็”จใ™ใ‚‹ { #using-the-path-operation-function-name-as-the-operationid } -APIใฎ้–ขๆ•ฐๅใ‚’ `operationId` ใจใ—ใฆๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใ€ใ™ในใฆใฎAPIใฎ้–ขๆ•ฐใ‚’ใ‚คใƒ†ใƒฌใƒผใ‚ทใƒงใƒณใ—ใ€ๅ„ *path operation* ใฎ `operationId` ใ‚’ `APIRoute.name` ใงไธŠๆ›ธใใ™ใ‚Œใฐๅฏ่ƒฝใงใ™ใ€‚ +APIใฎ้–ขๆ•ฐๅใ‚’ `operationId` ใจใ—ใฆๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใ€ใ™ในใฆใฎAPI้–ขๆ•ฐใ‚’ใ‚คใƒ†ใƒฌใƒผใ‚ทใƒงใƒณใ—ใ€ๅ„ *path operation* ใฎ `operation_id` ใ‚’ `APIRoute.name` ใงไธŠๆ›ธใใ™ใ‚Œใฐๅฏ่ƒฝใงใ™ใ€‚ -ใใ†ใ™ใ‚‹ๅ ดๅˆใฏใ€ใ™ในใฆใฎ *path operation* ใ‚’่ฟฝๅŠ ใ—ใŸๅพŒใซ่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ™ในใฆใฎ *path operation* ใ‚’่ฟฝๅŠ ใ—ใŸๅพŒใซ่กŒใ†ในใใงใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ -`app.openapi()` ใ‚’ๆ‰‹ๅ‹•ใงใ‚ณใƒผใƒซใ™ใ‚‹ๅ ดๅˆใ€ใใฎๅ‰ใซ`operationId`ใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +`app.openapi()` ใ‚’ๆ‰‹ๅ‹•ใงๅ‘ผใณๅ‡บใ™ๅ ดๅˆใ€ใใฎๅ‰ใซ `operationId` ใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ในใใงใ™ใ€‚ /// @@ -32,22 +32,141 @@ APIใฎ้–ขๆ•ฐๅใ‚’ `operationId` ใจใ—ใฆๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใ€ใ™ในใฆใฎAP ใ“ใฎๆ–นๆณ•ใ‚’ใจใ‚‹ๅ ดๅˆใ€ๅ„ *path operation้–ขๆ•ฐ* ใŒไธ€ๆ„ใชๅๅ‰ใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใ‚Œใ‚‰ใŒ็•ฐใชใ‚‹ใƒขใ‚ธใƒฅใƒผใƒซ (Pythonใƒ•ใ‚กใ‚คใƒซ) ใซใ‚ใ‚‹ใจใ—ใฆใ‚‚ใงใ™ใ€‚ +็•ฐใชใ‚‹ใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆPythonใƒ•ใ‚กใ‚คใƒซ๏ผ‰ใซใ‚ใ‚‹ๅ ดๅˆใงใ‚‚ๅŒๆง˜ใงใ™ใ€‚ /// -## OpenAPIใ‹ใ‚‰้™คๅค–ใ™ใ‚‹ +## OpenAPIใ‹ใ‚‰้™คๅค–ใ™ใ‚‹ { #exclude-from-openapi } -็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒž (ใคใพใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆใฎไป•็ต„ใฟ) ใ‹ใ‚‰ *path operation* ใ‚’้™คๅค–ใ™ใ‚‹ใซใฏใ€ `include_in_schema` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `False` ใซใ—ใพใ™ใ€‚ +็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒž๏ผˆใคใพใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆใฎไป•็ต„ใฟ๏ผ‰ใ‹ใ‚‰ *path operation* ใ‚’้™คๅค–ใ™ใ‚‹ใซใฏใ€`include_in_schema` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆ `False` ใซ่จญๅฎšใ—ใพใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} -## docstringใซใ‚ˆใ‚‹่ชฌๆ˜Žใฎ้ซ˜ๅบฆใช่จญๅฎš +## docstringใซใ‚ˆใ‚‹่ชฌๆ˜Žใฎ้ซ˜ๅบฆใช่จญๅฎš { #advanced-description-from-docstring } -*path operation้–ขๆ•ฐ* ใฎdocstringใ‹ใ‚‰OpenAPIใซไฝฟ็”จใ™ใ‚‹่กŒใ‚’ๅˆถ้™ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +*path operation้–ขๆ•ฐ* ใฎdocstringใ‹ใ‚‰OpenAPIใซไฝฟ็”จใ™ใ‚‹่กŒใ‚’ๅˆถ้™ใงใใพใ™ใ€‚ -`\f` (ใ€Œๆ›ธๅผ้€ใ‚Š (Form Feed)ใ€ใฎใ‚จใ‚นใ‚ฑใƒผใƒ—ๆ–‡ๅญ—) ใ‚’ไป˜ไธŽใ™ใ‚‹ใ“ใจใงใ€**FastAPI** ใฏOpenAPIใซไฝฟ็”จใ•ใ‚Œใ‚‹ๅ‡บๅŠ›ใ‚’ใใฎ็ฎ‡ๆ‰€ใพใงใซๅˆถ้™ใ—ใพใ™ใ€‚ +`\f`๏ผˆใ‚จใ‚นใ‚ฑใƒผใƒ—ใ•ใ‚ŒใŸใ€Œๆ›ธๅผ้€ใ‚Š๏ผˆform feed๏ผ‰ใ€ๆ–‡ๅญ—๏ผ‰ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€**FastAPI** ใฏใใฎๅœฐ็‚นใงOpenAPIใซไฝฟ็”จใ•ใ‚Œใ‚‹ๅ‡บๅŠ›ใ‚’ๅˆ‡ใ‚Š่ฉฐใ‚ใพใ™ใ€‚ -ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏ่กจ็คบใ•ใ‚Œใพใ›ใ‚“ใŒใ€ไป–ใฎใƒ„ใƒผใƒซ (ไพ‹ใˆใฐSphinx) ใงใฏๆฎ‹ใ‚Šใฎ้ƒจๅˆ†ใ‚’ๅˆฉ็”จใงใใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏ่กจ็คบใ•ใ‚Œใพใ›ใ‚“ใŒใ€ไป–ใฎใƒ„ใƒผใƒซ๏ผˆSphinxใชใฉ๏ผ‰ใฏๆฎ‹ใ‚Šใฎ้ƒจๅˆ†ใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚น { #additional-responses } + +*path operation* ใซๅฏพใ—ใฆ `response_model` ใจ `status_code` ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใฏใ™ใงใซ่ฆ‹ใŸใ“ใจใŒใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +ใใ‚Œใซใ‚ˆใ‚Šใ€*path operation* ใฎใƒกใ‚คใƒณใฎใƒฌใ‚นใƒใƒณใ‚นใซ้–ขใ™ใ‚‹ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใŒๅฎš็พฉใ•ใ‚Œใพใ™ใ€‚ + +่ฟฝๅŠ ใฎใƒฌใ‚นใƒใƒณใ‚นใซใคใ„ใฆใ‚‚ใ€ใƒขใƒ‡ใƒซใ‚„ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใชใฉใจใจใ‚‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚ + +ใ“ใ‚Œใซใคใ„ใฆใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ็ซ ๅ…จไฝ“ใŒใ‚ใ‚Šใพใ™ใ€‚ [OpenAPIใฎ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚น](additional-responses.md){.internal-link target=_blank} ใง่ชญใ‚ใพใ™ใ€‚ + +## OpenAPI Extra { #openapi-extra } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใง *path operation* ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€**FastAPI** ใฏOpenAPIใ‚นใ‚ญใƒผใƒžใซๅซใ‚ใ‚‹ใŸใ‚ใซใ€ใใฎ *path operation* ใซ้–ข้€ฃใ™ใ‚‹ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ—ใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +OpenAPIไป•ๆง˜ใงใฏ Operation Object ใจๅ‘ผใฐใ‚Œใฆใ„ใพใ™ใ€‚ + +/// + +ใ“ใ‚Œใซใฏ *path operation* ใซ้–ขใ™ใ‚‹ใ™ในใฆใฎๆƒ…ๅ ฑใŒๅซใพใ‚Œใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็”Ÿๆˆใ™ใ‚‹ใŸใ‚ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +`tags`ใ€`parameters`ใ€`requestBody`ใ€`responses` ใชใฉใŒๅซใพใ‚Œใพใ™ใ€‚ + +ใ“ใฎ *path operation* ๅ›บๆœ‰ใฎOpenAPIใ‚นใ‚ญใƒผใƒžใฏ้€šๅธธ **FastAPI** ใซใ‚ˆใ‚Š่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใพใ™ใŒใ€ๆ‹กๅผตใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚ŒใฏไฝŽใƒฌใƒ™ใƒซใชๆ‹กๅผตใƒใ‚คใƒณใƒˆใงใ™ใ€‚ + +่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ ใ‘ใชใ‚‰ใ€ใ‚ˆใ‚Šไพฟๅˆฉใชๆ–นๆณ•ใจใ—ใฆ [OpenAPIใฎ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚น](additional-responses.md){.internal-link target=_blank} ใ‚’ไฝฟใ†ใ“ใจใŒใงใใพใ™ใ€‚ + +/// + +`openapi_extra` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใฃใฆใ€*path operation* ใฎOpenAPIใ‚นใ‚ญใƒผใƒžใ‚’ๆ‹กๅผตใงใใพใ™ใ€‚ + +### OpenAPI Extensions { #openapi-extensions } + +ใ“ใฎ `openapi_extra` ใฏใ€ไพ‹ใˆใฐ [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} + +่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’้–‹ใใจใ€ใใฎๆ‹กๅผตใฏ็‰นๅฎšใฎ *path operation* ใฎไธ‹้ƒจใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + + + +ใใ—ใฆ๏ผˆAPIใฎ `/openapi.json` ใซใ‚ใ‚‹๏ผ‰็”Ÿๆˆใ•ใ‚ŒใŸOpenAPIใ‚’่ฆ‹ใ‚‹ใจใ€ใใฎๆ‹กๅผตใ‚‚็‰นๅฎšใฎ *path operation* ใฎไธ€้ƒจใจใ—ใฆ็ขบ่ชใงใใพใ™ใ€‚ + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ใ‚ซใ‚นใ‚ฟใƒ OpenAPI *path operation* ใ‚นใ‚ญใƒผใƒž { #custom-openapi-path-operation-schema } + +`openapi_extra` ๅ†…ใฎ่พžๆ›ธใฏใ€*path operation* ็”จใซ่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸOpenAPIใ‚นใ‚ญใƒผใƒžใจๆทฑใใƒžใƒผใ‚ธใ•ใ‚Œใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใซ่ฟฝๅŠ ใƒ‡ใƒผใ‚ฟใ‚’ๅŠ ใˆใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€Pydanticใ‚’ไฝฟใฃใŸFastAPIใฎ่‡ชๅ‹•ๆฉŸ่ƒฝใ‚’ไฝฟใ‚ใšใซ็‹ฌ่‡ชใฎใ‚ณใƒผใƒ‰ใงใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’่ชญใฟๅ–ใ‚Šใƒปๆคœ่จผใ™ใ‚‹ใ“ใจใ‚’้ธในใพใ™ใŒใ€ใใ‚Œใงใ‚‚OpenAPIใ‚นใ‚ญใƒผใƒžใงใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅฎš็พฉใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใ‚Œใฏ `openapi_extra` ใง่กŒใˆใพใ™ใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} + +ใ“ใฎไพ‹ใงใฏใ€Pydanticใƒขใƒ‡ใƒซใ‚’ไธ€ๅˆ‡ๅฎฃ่จ€ใ—ใฆใ„ใพใ›ใ‚“ใ€‚ๅฎŸ้š›ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฏJSONใจใ—ใฆ parsed ใ•ใ‚Œใšใ€็›ดๆŽฅ `bytes` ใจใ—ใฆ่ชญใฟๅ–ใ‚‰ใ‚Œใพใ™ใ€‚ใใ—ใฆ `magic_data_reader()` ้–ขๆ•ฐใŒใ€ไฝ•ใ‚‰ใ‹ใฎๆ–นๆณ•ใงใใ‚Œใ‚’ใƒ‘ใƒผใ‚นใ™ใ‚‹่ฒฌๅ‹™ใ‚’ๆ‹…ใ„ใพใ™ใ€‚ + +ใใ‚Œใงใ‚‚ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใซๆœŸๅพ…ใ•ใ‚Œใ‚‹ใ‚นใ‚ญใƒผใƒžใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +### ใ‚ซใ‚นใ‚ฟใƒ OpenAPI content type { #custom-openapi-content-type } + +ๅŒใ˜ใƒˆใƒชใƒƒใ‚ฏใ‚’ไฝฟใฃใฆใ€Pydanticใƒขใƒ‡ใƒซใงJSON Schemaใ‚’ๅฎš็พฉใ—ใ€ใใ‚Œใ‚’ *path operation* ็”จใฎใ‚ซใ‚นใ‚ฟใƒ OpenAPIใ‚นใ‚ญใƒผใƒžใ‚ปใ‚ฏใ‚ทใƒงใƒณใซๅซใ‚ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ + +ใพใŸใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆๅ†…ใฎใƒ‡ใƒผใ‚ฟๅž‹ใŒJSONใงใชใ„ๅ ดๅˆใงใ‚‚ใ“ใ‚Œใ‚’่กŒใˆใพใ™ใ€‚ + +ไพ‹ใˆใฐใ“ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Pydanticใƒขใƒ‡ใƒซใ‹ใ‚‰JSON Schemaใ‚’ๆŠฝๅ‡บใ™ใ‚‹FastAPIใฎ็ตฑๅˆๆฉŸ่ƒฝใ‚„ใ€JSONใฎ่‡ชๅ‹•ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ไฝฟใฃใฆใ„ใพใ›ใ‚“ใ€‚ๅฎŸ้š›ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎcontent typeใ‚’JSONใงใฏใชใYAMLใจใ—ใฆๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} + +ใใ‚Œใงใ‚‚ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ็ตฑๅˆๆฉŸ่ƒฝใ‚’ไฝฟใฃใฆใ„ใชใ„ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€YAMLใงๅ—ใ‘ๅ–ใ‚ŠใŸใ„ใƒ‡ใƒผใ‚ฟใฎใŸใ‚ใซใ€Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใฆๆ‰‹ๅ‹•ใงJSON Schemaใ‚’็”Ÿๆˆใ—ใฆใ„ใพใ™ใ€‚ + +ใใ—ใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’็›ดๆŽฅไฝฟใ„ใ€ใƒœใƒ‡ใ‚ฃใ‚’ `bytes` ใจใ—ใฆๆŠฝๅ‡บใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€FastAPIใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใƒšใ‚คใƒญใƒผใƒ‰ใ‚’JSONใจใ—ใฆใƒ‘ใƒผใ‚นใ—ใ‚ˆใ†ใจใ™ใ‚‰ใ—ใชใ„ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ + +ใใฎๅพŒใ€ใ‚ณใƒผใƒ‰ๅ†…ใงใใฎYAMLใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’็›ดๆŽฅใƒ‘ใƒผใ‚นใ—ใ€ใ•ใ‚‰ใซๅŒใ˜Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใฆYAMLใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ๆคœ่จผใ—ใฆใ„ใพใ™ใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ“ใงใฏๅŒใ˜Pydanticใƒขใƒ‡ใƒซใ‚’ๅ†ๅˆฉ็”จใ—ใฆใ„ใพใ™ใ€‚ + +ใŸใ ใ—ๅŒๆง˜ใซใ€ๅˆฅใฎๆ–นๆณ•ใงๆคœ่จผใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +/// diff --git a/docs/ja/docs/advanced/response-directly.md b/docs/ja/docs/advanced/response-directly.md index 42412d5070..7e83b9ffb2 100644 --- a/docs/ja/docs/advanced/response-directly.md +++ b/docs/ja/docs/advanced/response-directly.md @@ -1,4 +1,4 @@ -# ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ +# ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ { #return-a-response-directly } **FastAPI** ใฎ *path operation* ใงใฏใ€้€šๅธธใฏไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™: ไพ‹ใˆใฐใ€ `dict`ใ€`list`ใ€Pydanticใƒขใƒ‡ใƒซใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซใชใฉใงใ™ใ€‚ @@ -10,7 +10,7 @@ ใ“ใ‚Œใฏไพ‹ใˆใฐใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใ‚„cookieใ‚’่ฟ”ใ™ใจใใซไพฟๅˆฉใงใ™ใ€‚ -## `Response` ใ‚’่ฟ”ใ™ +## `Response` ใ‚’่ฟ”ใ™ { #return-a-response } ๅฎŸ้š›ใฏใ€`Response` ใ‚„ใใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚ @@ -26,7 +26,7 @@ ใ“ใ‚ŒใฏๅคšใใฎๆŸ”่ปŸๆ€งใ‚’ๆไพ›ใ—ใพใ™ใ€‚ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟๅž‹ใ‚’่ฟ”ใ—ใŸใ‚Šใ€ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟๅฎฃ่จ€ใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ -## `jsonable_encoder` ใ‚’ `Response` ใฎไธญใงไฝฟใ† +## `jsonable_encoder` ใ‚’ `Response` ใฎไธญใงไฝฟใ† { #using-the-jsonable-encoder-in-a-response } **FastAPI** ใฏใ‚ใชใŸใŒ่ฟ”ใ™ `Response` ใซๅฏพใ—ใฆไฝ•ใ‚‚ๅค‰ๆ›ดใ‚’ๅŠ ใˆใชใ„ใฎใงใ€ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒๆบ–ๅ‚™ใงใใฆใ„ใ‚‹ใ“ใจใ‚’ไฟ่จผใ—ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ @@ -34,7 +34,7 @@ ใ“ใฎใ‚ˆใ†ใชใ‚ฑใƒผใ‚นใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใซใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚ใ‚‹ๅ‰ใซ `jsonable_encoder` ใ‚’ไฝฟใฃใฆใƒ‡ใƒผใ‚ฟใ‚’ๅค‰ๆ›ใงใใพใ™ใ€‚ -{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *} +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -44,7 +44,7 @@ /// -## ใ‚ซใ‚นใ‚ฟใƒ  `Response` ใ‚’่ฟ”ใ™ +## ใ‚ซใ‚นใ‚ฟใƒ  `Response` ใ‚’่ฟ”ใ™ { #returning-a-custom-response } ไธŠ่จ˜ใฎไพ‹ใงใฏๅฟ…่ฆใช้ƒจๅˆ†ใ‚’ๅ…จใฆ็คบใ—ใฆใ„ใพใ™ใŒใ€ใ‚ใพใ‚Šไพฟๅˆฉใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚`item` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใ“ใจใŒใงใใ‚‹ใ—ใ€**FastAPI** ใฏใใ‚Œใ‚’ `dict` ใซๅค‰ๆ›ใ—ใฆ `JSONResponse`ใ€€ใซๅซใ‚ใฆใใ‚Œใ‚‹ใชใฉใ€‚ใ™ในใฆใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎๅ‹•ไฝœใงใ™ใ€‚ @@ -54,9 +54,9 @@ XMLใ‚’ๆ–‡ๅญ—ๅˆ—ใซใ—ใ€`Response` ใซๅซใ‚ใ€ใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} -## ๅ‚™่€ƒ +## ๅ‚™่€ƒ { #notes } `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใ€ๅค‰ๆ› (ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บ) ใ‚„ใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏ่กŒใ‚ใ‚Œใพใ›ใ‚“ใ€‚ diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md index 2517530abe..6c68c9f0b1 100644 --- a/docs/ja/docs/advanced/websockets.md +++ b/docs/ja/docs/advanced/websockets.md @@ -1,10 +1,10 @@ -# WebSocket +# WebSockets { #websockets } -**FastAPI**ใงWebSocketใŒไฝฟ็”จใงใใพใ™ใ€‚ +**FastAPI**ใงWebSocketsใŒไฝฟ็”จใงใใพใ™ใ€‚ -## `WebSockets`ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ +## `websockets`ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-websockets } -ใพใš `WebSockets`ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใŒๅฟ…่ฆใงใ™ใ€‚ +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ใ€ŒWebSocketใ€ใƒ—ใƒญใƒˆใ‚ณใƒซใ‚’็ฐกๅ˜ใซไฝฟใˆใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹Pythonใƒฉใ‚คใƒ–ใƒฉใƒชใฎ`websockets`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚
@@ -16,13 +16,13 @@ $ pip install websockets
-## WebSocket ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ +## WebSockets ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ { #websockets-client } -### ๆœฌ็•ช็’ฐๅขƒ +### ๆœฌ็•ช็’ฐๅขƒ { #in-production } ๆœฌ็•ช็’ฐๅขƒใงใฏใ€Reactใ€Vue.jsใ€Angularใชใฉใฎๆœ€ๆ–ฐใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงไฝœๆˆใ•ใ‚ŒใŸใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -ใใ—ใฆใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจWebSocketใ‚’ไฝฟ็”จใ—ใฆ้€šไฟกใ™ใ‚‹ใŸใ‚ใซใ€ใŠใใ‚‰ใใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใใ—ใฆใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจWebSocketsใ‚’ไฝฟ็”จใ—ใฆ้€šไฟกใ™ใ‚‹ใŸใ‚ใซใ€ใŠใใ‚‰ใใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ ใพใŸใฏใ€ใƒใ‚คใƒ†ใ‚ฃใƒ–ใ‚ณใƒผใƒ‰ใงWebSocketใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจ็›ดๆŽฅ้€šไฟกใ™ใ‚‹ใƒใ‚คใƒ†ใ‚ฃใƒ–ใƒขใƒใ‚คใƒซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ @@ -30,21 +30,21 @@ $ pip install websockets --- -ใŸใ ใ—ใ€ใ“ใฎไพ‹ใงใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใชHTMLๆ–‡ๆ›ธใจใ„ใใคใ‹ใฎJavaScriptใ‚’ใ€ใ™ในใฆใ‚ฝใƒผใ‚นใ‚ณใƒผใƒ‰ใฎไธญใซๅ…ฅใ‚Œใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใซใ—ใพใ™ใ€‚ +ใŸใ ใ—ใ€ใ“ใฎไพ‹ใงใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใชHTMLๆ–‡ๆ›ธใจใ„ใใคใ‹ใฎJavaScriptใ‚’ใ€ใ™ในใฆ้•ทใ„ๆ–‡ๅญ—ๅˆ—ใฎไธญใซๅ…ฅใ‚Œใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใซใ—ใพใ™ใ€‚ ใ‚‚ใกใ‚ใ‚“ใ€ใ“ใ‚Œใฏๆœ€้ฉใชๆ–นๆณ•ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ—ใ€ๆœฌ็•ช็’ฐๅขƒใงไฝฟใ†ใ“ใจใฏใชใ„ใงใ—ใ‚‡ใ†ใ€‚ ๆœฌ็•ช็’ฐๅขƒใงใฏใ€ไธŠ่จ˜ใฎๆ–นๆณ•ใฎใ„ใšใ‚Œใ‹ใฎ้ธๆŠž่‚ขใ‚’ๆŽก็”จใ™ใ‚‹ใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -ใ—ใ‹ใ—ใ€ใ“ใ‚ŒใฏWebSocketใฎใ‚ตใƒผใƒใƒผใ‚ตใ‚คใƒ‰ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ€ๅฎŸ็”จ็š„ใชไพ‹ใ‚’็คบใ™ๆœ€ใ‚‚็ฐกๅ˜ใชๆ–นๆณ•ใงใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใ“ใ‚ŒใฏWebSocketsใฎใ‚ตใƒผใƒใƒผใ‚ตใ‚คใƒ‰ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ€ๅ‹•ไฝœใ™ใ‚‹ไพ‹ใ‚’็คบใ™ๆœ€ใ‚‚็ฐกๅ˜ใชๆ–นๆณ•ใงใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} -## `websocket` ใ‚’ไฝœๆˆใ™ใ‚‹ +## `websocket` ใ‚’ไฝœๆˆใ™ใ‚‹ { #create-a-websocket } **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ€`websocket` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -54,22 +54,22 @@ $ pip install websockets /// -## ใƒกใƒƒใ‚ปใƒผใ‚ธใฎ้€ๅ—ไฟก +## ใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๅพ…ๆฉŸใ—ใฆ้€ไฟกใ™ใ‚‹ { #await-for-messages-and-send-messages } -WebSocketใƒซใƒผใƒˆใงใฏใ€ `await` ใ‚’ไฝฟใฃใฆใƒกใƒƒใ‚ปใƒผใ‚ธใฎ้€ๅ—ไฟกใŒใงใใพใ™ใ€‚ +WebSocketใƒซใƒผใƒˆใงใฏใ€ใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๅพ…ๆฉŸใ—ใฆ้€ไฟกใ™ใ‚‹ใŸใ‚ใซ `await` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} ใƒใ‚คใƒŠใƒชใ‚„ใƒ†ใ‚ญใ‚นใƒˆใƒ‡ใƒผใ‚ฟใ€JSONใƒ‡ใƒผใ‚ฟใ‚’้€ๅ—ไฟกใงใใพใ™ใ€‚ -## ่ฉฆใ—ใฆใฟใ‚‹ +## ่ฉฆใ—ใฆใฟใ‚‹ { #try-it } -ใƒ•ใ‚กใ‚คใƒซๅใŒ `main.py` ใงใ‚ใ‚‹ๅ ดๅˆใ€ไปฅไธ‹ใฎๆ–นๆณ•ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ +ใƒ•ใ‚กใ‚คใƒซๅใŒ `main.py` ใงใ‚ใ‚‹ๅ ดๅˆใ€ไปฅไธ‹ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -86,7 +86,7 @@ $ uvicorn main:app --reload -ใใ—ใฆใ€ WebSocketใ‚’ไฝฟ็”จใ—ใŸ**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฟœ็ญ”ใ—ใพใ™ใ€‚ +ใใ—ใฆใ€ WebSocketsใ‚’ไฝฟ็”จใ—ใŸ**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฟœ็ญ”ใ—ใพใ™ใ€‚ @@ -96,7 +96,7 @@ $ uvicorn main:app --reload ใใ—ใฆใ€ใ“ใ‚Œใ‚‰ใฎ้€šไฟกใฏใ™ในใฆๅŒใ˜WebSocketๆŽฅ็ถšใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -## ไพๅญ˜้–ขไฟ‚ +## `Depends` ใชใฉใฎไฝฟ็”จ { #using-depends-and-others } WebSocketใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใงใฏใ€`fastapi` ใ‹ใ‚‰ไปฅไธ‹ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟ็”จใงใใพใ™ใ€‚ @@ -107,28 +107,26 @@ WebSocketใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใงใฏใ€`fastapi` ใ‹ใ‚‰ไปฅไธ‹ใ‚’ใ‚คใƒณใƒใƒผใƒˆ * `Path` * `Query` -ใ“ใ‚Œใ‚‰ใฏใ€ไป–ใฎFastAPI ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ/*path operation* ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฏใ€ไป–ใฎFastAPI ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ/*path operations* ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซๆฉŸ่ƒฝใ—ใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial002.py hl[58:65,68:83] *} +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} /// info | ๆƒ…ๅ ฑ -WebSocket ใง `HTTPException` ใ‚’็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใฏใ‚ใพใ‚Šๆ„ๅ‘ณใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ—ใŸใŒใฃใฆใ€WebSocketใฎๆŽฅ็ถšใ‚’็›ดๆŽฅ้–‰ใ˜ใ‚‹ๆ–นใŒใ‚ˆใ„ใงใ—ใ‚‡ใ†ใ€‚ +ใ“ใ‚ŒใฏWebSocketใงใ‚ใ‚‹ใŸใ‚ใ€`HTTPException` ใ‚’็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใฏใ‚ใพใ‚Šๆ„ๅ‘ณใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ไปฃใ‚ใ‚Šใซ `WebSocketException` ใ‚’็™บ็”Ÿใ•ใ›ใพใ™ใ€‚ ใ‚ฏใƒญใƒผใ‚ธใƒณใ‚ฐใ‚ณใƒผใƒ‰ใฏใ€ไป•ๆง˜ใงๅฎš็พฉใ•ใ‚ŒใŸๆœ‰ๅŠนใชใ‚ณใƒผใƒ‰ใฎไธญใ‹ใ‚‰ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ๅฐ†ๆฅ็š„ใซใฏใ€ใฉใ“ใ‹ใ‚‰ใงใ‚‚ `raise` ใงใใ‚‹ `WebSocketException` ใŒ็”จๆ„ใ•ใ‚Œใ€ๅฐ‚็”จใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’่ฟฝๅŠ ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚‹ไบˆๅฎšใงใ™ใ€‚ใ“ใ‚Œใฏใ€Starlette ใฎ PR #527 ใซไพๅญ˜ใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ - /// -### ไพๅญ˜้–ขไฟ‚ใ‚’็”จใ„ใฆWebSocketsใ‚’่ฉฆใ—ใฆใฟใ‚‹ +### ไพๅญ˜้–ขไฟ‚ใ‚’็”จใ„ใฆWebSocketsใ‚’่ฉฆใ—ใฆใฟใ‚‹ { #try-the-websockets-with-dependencies } -ใƒ•ใ‚กใ‚คใƒซๅใŒ `main.py` ใงใ‚ใ‚‹ๅ ดๅˆใ€ไปฅไธ‹ใฎๆ–นๆณ•ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ +ใƒ•ใ‚กใ‚คใƒซๅใŒ `main.py` ใงใ‚ใ‚‹ๅ ดๅˆใ€ไปฅไธ‹ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -137,14 +135,14 @@ $ uvicorn main:app --reload ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000 ใ‚’้–‹ใใพใ™ใ€‚ -ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ่จญๅฎšใงใใ‚‹้ …็›ฎใฏไปฅไธ‹ใฎ้€šใ‚Šใงใ™ใ€‚ +ใใ“ใงใ€ไปฅไธ‹ใ‚’่จญๅฎšใงใใพใ™ใ€‚ * ใƒ‘ใ‚นใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ€ŒItem IDใ€ * ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ€ŒTokenใ€ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ‚ฏใ‚จใƒช `token` ใฏไพๅญ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +ใ‚ฏใ‚จใƒช `token` ใฏไพๅญ˜้–ขไฟ‚ใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -152,11 +150,11 @@ $ uvicorn main:app --reload -## ๅˆ‡ๆ–ญใ‚„่ค‡ๆ•ฐใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใธใฎๅฏพๅฟœ +## ๅˆ‡ๆ–ญใ‚„่ค‡ๆ•ฐใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎๅ‡ฆ็† { #handling-disconnections-and-multiple-clients } WebSocketๆŽฅ็ถšใŒ้–‰ใ˜ใ‚‰ใ‚Œใ‚‹ใจใ€ `await websocket.receive_text()` ใฏไพ‹ๅค– `WebSocketDisconnect` ใ‚’็™บ็”Ÿใ•ใ›ใ€ใ“ใฎไพ‹ใฎใ‚ˆใ†ใซใ‚ญใƒฃใƒƒใƒใ—ใฆๅ‡ฆ็†ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial003.py hl[81:83] *} +{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} ่ฉฆใ—ใฆใฟใ‚‹ใซใฏใ€ @@ -174,15 +172,15 @@ Client #1596980209979 left the chat ไธŠ่จ˜ใฎใ‚ขใƒ—ใƒชใฏใ€่ค‡ๆ•ฐใฎ WebSocket ๆŽฅ็ถšใซๅฏพใ—ใฆใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๅ‡ฆ็†ใ—ใ€ใƒ–ใƒญใƒผใƒ‰ใ‚ญใƒฃใ‚นใƒˆใ™ใ‚‹ๆ–นๆณ•ใ‚’็คบใ™ใŸใ‚ใฎๆœ€ๅฐ้™ใฎใ‚ทใƒณใƒ—ใƒซใชไพ‹ใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใ™ในใฆใฎๆŽฅ็ถšใŒใƒกใƒขใƒชๅ†…ใฎๅ˜ไธ€ใฎใƒชใ‚นใƒˆใงๅ‡ฆ็†ใ•ใ‚Œใ‚‹ใŸใ‚ใ€ใƒ—ใƒญใ‚ปใ‚นใฎๅฎŸ่กŒไธญใซใฎใฟๆฉŸ่ƒฝใ—ใ€ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใงใฎใฟๆฉŸ่ƒฝใ™ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +ใ—ใ‹ใ—ใ€ใ™ในใฆใŒใƒกใƒขใƒชๅ†…ใฎๅ˜ไธ€ใฎใƒชใ‚นใƒˆใงๅ‡ฆ็†ใ•ใ‚Œใ‚‹ใŸใ‚ใ€ใƒ—ใƒญใ‚ปใ‚นใฎๅฎŸ่กŒไธญใซใฎใฟๆฉŸ่ƒฝใ—ใ€ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใงใฎใฟๆฉŸ่ƒฝใ™ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใ‚‚ใ—FastAPIใจ็ฐกๅ˜ใซ็ตฑๅˆใงใใฆใ€Redisใ‚„PostgreSQLใชใฉใงใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใ‚‹ใ€ใ‚ˆใ‚Šๅ …็‰ขใชใ‚‚ใฎใŒๅฟ…่ฆใชใ‚‰ใ€encode/broadcaster ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +FastAPIใจ็ฐกๅ˜ใซ็ตฑๅˆใงใใฆใ€Redisใ‚„PostgreSQLใชใฉใงใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใ‚‹ใ€ใ‚ˆใ‚Šๅ …็‰ขใชใ‚‚ใฎใŒๅฟ…่ฆใชใ‚‰ใ€encode/broadcaster ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ใใฎไป–ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +## ่ฉณ็ดฐๆƒ…ๅ ฑ { #more-info } ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ่ฉณ็ดฐใซใคใ„ใฆใฏใ€Starletteใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ -* `WebSocket` ใ‚ฏใƒฉใ‚น -* ใ‚ฏใƒฉใ‚นใƒ™ใƒผใ‚นใฎWebSocketๅ‡ฆ็† +* `WebSocket` ใ‚ฏใƒฉใ‚น. +* ใ‚ฏใƒฉใ‚นใƒ™ใƒผใ‚นใฎWebSocketๅ‡ฆ็†. diff --git a/docs/ja/docs/benchmarks.md b/docs/ja/docs/benchmarks.md index 966d199c5e..fbfba2e637 100644 --- a/docs/ja/docs/benchmarks.md +++ b/docs/ja/docs/benchmarks.md @@ -1,34 +1,34 @@ -# ใƒ™ใƒณใƒใƒžใƒผใ‚ฏ +# ใƒ™ใƒณใƒใƒžใƒผใ‚ฏ { #benchmarks } -TechEmpowerใฎ็‹ฌ็ซ‹ใ—ใŸใƒ™ใƒณใƒใƒžใƒผใ‚ฏใงใฏใ€Uvicornใฎไธ‹ใงๅ‹•ไฝœใ™ใ‚‹**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€ๅˆฉ็”จๅฏ่ƒฝใชๆœ€้€ŸใฎPythonใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎ1ใคใงใ‚ใ‚Šใ€ไธ‹ๅ›žใฃใฆใ„ใ‚‹ใฎใฏStarletteใจUvicorn่‡ชไฝ“ (FastAPIใซใ‚ˆใฃใฆๅ†…้ƒจใงไฝฟ็”จใ•ใ‚Œใ‚‹) ใฎใฟใ ใจ็คบใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +TechEmpowerใฎ็‹ฌ็ซ‹ใ—ใŸใƒ™ใƒณใƒใƒžใƒผใ‚ฏใงใฏใ€Uvicornใฎไธ‹ใงๅ‹•ไฝœใ™ใ‚‹**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€ๅˆฉ็”จๅฏ่ƒฝใชๆœ€้€ŸใฎPythonใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎ1ใคใงใ‚ใ‚Šใ€ไธ‹ๅ›žใฃใฆใ„ใ‚‹ใฎใฏStarletteใจUvicorn่‡ชไฝ“๏ผˆFastAPIใซใ‚ˆใฃใฆๅ†…้ƒจใงไฝฟ็”จใ•ใ‚Œใ‚‹๏ผ‰ใฎใฟใ ใจ็คบใ•ใ‚Œใฆใ„ใพใ™ใ€‚ ใŸใ ใ—ใ€ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใ‚’็ขบ่ชใ—ใ€ๆฏ”่ผƒใ™ใ‚‹้š›ใซใฏไธ‹่จ˜ใฎๅ†…ๅฎนใซๆฐ—ใ‚’ไป˜ใ‘ใฆใใ ใ•ใ„ใ€‚ -## ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใจ้€Ÿๅบฆ +## ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใจ้€Ÿๅบฆ { #benchmarks-and-speed } -ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใ‚’็ขบ่ชใ™ใ‚‹ๆ™‚ใ€็•ฐใชใ‚‹ใƒ„ใƒผใƒซใ‚’ๅŒ็ญ‰ใชใ‚‚ใฎใจๆฏ”่ผƒใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ +ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใ‚’็ขบ่ชใ™ใ‚‹ๆ™‚ใ€็•ฐใชใ‚‹ใ‚ฟใ‚คใƒ—ใฎ่ค‡ๆ•ฐใฎใƒ„ใƒผใƒซใŒๅŒ็ญ‰ใฎใ‚‚ใฎใจใ—ใฆๆฏ”่ผƒใ•ใ‚Œใฆใ„ใ‚‹ใฎใ‚’็›ฎใซใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ -ๅ…ทไฝ“็š„ใซใฏใ€Uvicornใ€Starletteใ€FastAPIใ‚’ (ไป–ใฎๅคšใใฎใƒ„ใƒผใƒซใจ) ๆฏ”่ผƒใ—ใพใ—ใŸใ€‚ +ๅ…ทไฝ“็š„ใซใฏใ€Uvicornใ€Starletteใ€FastAPIใ‚’๏ผˆไป–ใฎๅคšใใฎใƒ„ใƒผใƒซใฎไธญใง๏ผ‰ใพใจใ‚ใฆๆฏ”่ผƒใ—ใฆใ„ใ‚‹ใฎใ‚’็›ฎใซใ™ใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ ใƒ„ใƒผใƒซใง่งฃๆฑบใ™ใ‚‹ๅ•้กŒใŒใ‚ทใƒณใƒ—ใƒซใชใปใฉใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใŒๅ‘ไธŠใ—ใพใ™ใ€‚ใพใŸใ€ใปใจใ‚“ใฉใฎใƒ™ใƒณใƒใƒžใƒผใ‚ฏใฏใ€ใƒ„ใƒผใƒซใ‹ใ‚‰ๆไพ›ใ•ใ‚Œใ‚‹่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ใƒ†ใ‚นใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚ ้šŽๅฑค้–ขไฟ‚ใฏใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ * **Uvicorn**: ASGIใ‚ตใƒผใƒใƒผ - * **Starlette**: (Uvicornใ‚’ไฝฟ็”จ) WEBใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ - * **FastAPI**: (Starletteใ‚’ไฝฟ็”จ) ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใชใฉใฎใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ๅ‚™ใˆใŸAPIใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ + * **Starlette**: ๏ผˆUvicornใ‚’ไฝฟ็”จ๏ผ‰webใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ + * **FastAPI**: ๏ผˆStarletteใ‚’ไฝฟ็”จ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใชใฉใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎใ„ใใคใ‹ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ๅ‚™ใˆใŸAPIใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ * **Uvicorn**: - * ใ‚ตใƒผใƒใƒผ่‡ชไฝ“ใซไฝ™ๅˆ†ใชใ‚ณใƒผใƒ‰ใŒๅฐ‘ใชใ„ใฎใงใ€ๆœ€้ซ˜ใฎใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ - * Uvicornใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’็›ดๆŽฅๆ›ธใใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ใคใพใ‚Šใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใซใฏใ€Starlette (ใพใŸใฏ** FastAPI **) ใŒๆไพ›ใ™ใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ใ€ๅคšใ‹ใ‚Œๅฐ‘ใชใ‹ใ‚Œๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใ†ใ™ใ‚‹ใจใ€ๆœ€็ต‚็š„ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚’ไฝฟ็”จใ—ใฆใ‚ขใƒ—ใƒชใฎใ‚ณใƒผใƒ‰ใจใƒใ‚ฐใ‚’ๆœ€ๅฐ้™ใซๆŠ‘ใˆใŸๅ ดๅˆใจๅŒใ˜ใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใซใชใ‚Šใพใ™ใ€‚ - * ใ‚‚ใ—Uvicornใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Daphneใ€Hypercornใ€uWSGIใชใฉใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚ + * ใ‚ตใƒผใƒใƒผ่‡ชไฝ“ไปฅๅค–ใซไฝ™ๅˆ†ใชใ‚ณใƒผใƒ‰ใŒใ‚ใพใ‚Šใชใ„ใŸใ‚ใ€ๆœ€้ซ˜ใฎใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใซใชใ‚Šใพใ™ใ€‚ + * Uvicornใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’็›ดๆŽฅๆ›ธใใ“ใจใฏใชใ„ใงใ—ใ‚‡ใ†ใ€‚ใใ‚Œใฏใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใซใ€Starlette๏ผˆใพใŸใฏ**FastAPI**๏ผ‰ใŒๆไพ›ใ™ใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ใ€ๅฐ‘ใชใใจใ‚‚ๅคšใ‹ใ‚Œๅฐ‘ใชใ‹ใ‚Œๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ใใ—ใฆใ€ใ‚‚ใ—ใใ†ใ—ใŸๅ ดๅˆใ€ๆœ€็ต‚็š„ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚’ไฝฟ็”จใ—ใฆใ‚ขใƒ—ใƒชใฎใ‚ณใƒผใƒ‰ใจใƒใ‚ฐใ‚’ๆœ€ๅฐ้™ใซๆŠ‘ใˆใŸๅ ดๅˆใจๅŒใ˜ใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใซใชใ‚Šใพใ™ใ€‚ + * Uvicornใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Daphneใ€Hypercornใ€uWSGIใชใฉใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚ * **Starlette**: - * Uvicornใซๆฌกใๆ€ง่ƒฝใ‚’ๆŒใคใงใ—ใ‚‡ใ†ใ€‚ๅฎŸ้š›ใ€StarletteใฏUvicornใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ใ ใ‹ใ‚‰ใ€ใ‚ˆใ‚Šๅคšใใฎใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใ€Uvicornใ‚ˆใ‚Šใ‚‚ใ€Œ้…ใใ€ใชใฃใฆใ—ใพใ†ใ ใ‘ใชใฎใงใ™ใ€‚ - * ใ—ใ‹ใ—ใ€ใƒ‘ใ‚นใƒ™ใƒผใ‚นใฎใƒซใƒผใƒ†ใ‚ฃใƒณใ‚ฐใชใฉใฎใ‚ทใƒณใƒ—ใƒซใชWEBใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใพใ™ใ€‚ - * ใ‚‚ใ—Starletteใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Sanicใ€Flaskใ€DjangoใชใฉใฎWEBใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ (ใ‚‚ใ—ใใฏใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ) ใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚ + * Uvicornใซๆฌกใๆ€ง่ƒฝใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ๅฎŸ้š›ใ€StarletteใฏๅฎŸ่กŒใซUvicornใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ใŠใใ‚‰ใใ€ใ‚ˆใ‚Šๅคšใใฎใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ—ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ๅˆ†ใ ใ‘ใ€Uvicornใ‚ˆใ‚Šใ€Œ้…ใใ€ใชใ‚‹ใ ใ‘ใงใ™ใ€‚ + * ใ—ใ‹ใ—ใ€ใƒ‘ใ‚นใซๅŸบใฅใใƒซใƒผใƒ†ใ‚ฃใƒณใ‚ฐใชใฉใ‚’ไฝฟใฃใฆใ€ใ‚ทใƒณใƒ—ใƒซใชwebใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎใƒ„ใƒผใƒซใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + * Starletteใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Sanicใ€Flaskใ€Djangoใชใฉใฎwebใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ๏ผˆใพใŸใฏใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ๏ผ‰ใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚ * **FastAPI**: - * StarletteใŒUvicornใ‚’ไฝฟใฃใฆใ„ใ‚‹ใฎใจๅŒใ˜ใงใ€**FastAPI**ใฏStarletteใ‚’ไฝฟใฃใฆใŠใ‚Šใ€ใใ‚Œใ‚ˆใ‚Š้€Ÿใใงใใพใ›ใ‚“ใ€‚ - * FastAPIใฏStarletteใฎไธŠใซใ•ใ‚‰ใซๅคšใใฎๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใพใ™ใ€‚ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผใ‚„ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใชใฉใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซๅธธใซๅฟ…่ฆใชๆฉŸ่ƒฝใงใ™ใ€‚ใพใŸใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ‚’็„กๆ–™ใงๅ–ๅพ—ใงใใพใ™ (ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๅฎŸ่กŒไธญใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใ‚’่ฟฝๅŠ ใ›ใšใ€่ตทๅ‹•ๆ™‚ใซ็”Ÿๆˆใ•ใ‚Œใพใ™) ใ€‚ - * FastAPIใ‚’ไฝฟ็”จใ›ใšใ€็›ดๆŽฅStarlette (ใพใŸใฏSanic, Flask, Responderใชใฉ) ใ‚’ไฝฟ็”จใ—ใŸๅ ดๅˆใ€ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผใจใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ‚’ใ™ในใฆ่‡ชๅˆ†ใงๅฎŸ่ฃ…ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใฎใŸใ‚ใ€ๆœ€็ต‚็š„ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏFastAPIใ‚’ไฝฟ็”จใ—ใฆๆง‹็ฏ‰ใ—ใŸๅ ดๅˆใจๅŒใ˜ใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใŒ็™บ็”Ÿใ—ใพใ™ใ€‚ใใ—ใฆใ€ๅคšใใฎๅ ดๅˆใ€ใ“ใฎใƒ‡ใƒผใ‚ฟๆคœ่จผใจใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ‚ณใƒผใƒ‰ใฎไธญใงๆœ€ๅคงใฎ่จ˜่ฟฐ้‡ใซใชใ‚Šใพใ™ใ€‚ - * FastAPIใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€้–‹็™บๆ™‚้–“ใ€ใƒใ‚ฐใ€ใ‚ณใƒผใƒ‰่กŒๆ•ฐใ‚’็ฏ€็ด„ใงใใ€ไฝฟ็”จใ—ใชใ„ๅ ดๅˆ (ใ‚ใชใŸใŒๅ…จใฆใฎๆฉŸ่ƒฝใ‚’ๅฎŸ่ฃ…ใ—็›ดใ—ใŸๅ ดๅˆ) ใจๅŒใ˜ใ‹ใใ‚ŒไปฅไธŠใฎใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ - * ใ‚‚ใ—FastAPIใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Flask-apispecใ€NestJSใ€Moltenใชใฉใฎใƒ‡ใƒผใ‚ฟๆคœ่จผใ‚„ใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใฎๆฉŸ่ƒฝใ‚’ๆไพ›ใ™ใ‚‹WEBใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ (ใ‚„ๆฉŸ่ƒฝใฎใ‚ปใƒƒใƒˆ) ใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใ‚Œใ‚‰ใฏใƒ‡ใƒผใ‚ฟใฎ่‡ชๅ‹•ๆคœ่จผใ‚„ใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใŒ็ตฑๅˆใ•ใ‚ŒใŸใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ + * StarletteใŒUvicornใ‚’ไฝฟ็”จใ—ใฆใŠใ‚Šใ€ใใ‚Œใ‚ˆใ‚Š้€Ÿใใงใใชใ„ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€**FastAPI**ใฏStarletteใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใใ‚Œใ‚ˆใ‚Š้€Ÿใใงใใพใ›ใ‚“ใ€‚ + * FastAPIใฏStarletteใฎไธŠใซใ€ใ‚ˆใ‚ŠๅคšใใฎๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใพใ™ใ€‚ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใฎใ‚ˆใ†ใซใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใปใจใ‚“ใฉๅธธใซๅฟ…่ฆใชๆฉŸ่ƒฝใงใ™ใ€‚ใพใŸใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ‚’็„กๆ–™ใงๅˆฉ็”จใงใใพใ™๏ผˆ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๅฎŸ่กŒไธญใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใ‚’่ฟฝๅŠ ใ›ใšใ€่ตทๅ‹•ๆ™‚ใซ็”Ÿๆˆใ•ใ‚Œใพใ™๏ผ‰ใ€‚ + * FastAPIใ‚’ไฝฟ็”จใ›ใšใ€Starletteใ‚’็›ดๆŽฅ๏ผˆใพใŸใฏSanicใ€Flaskใ€Responderใชใฉๅˆฅใฎใƒ„ใƒผใƒซใ‚’๏ผ‰ไฝฟ็”จใ—ใŸๅ ดๅˆใ€ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ‚’ใ™ในใฆ่‡ชๅˆ†ใงๅฎŸ่ฃ…ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใฎใŸใ‚ใ€ๆœ€็ต‚็š„ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏFastAPIใ‚’ไฝฟ็”จใ—ใฆๆง‹็ฏ‰ใ—ใŸๅ ดๅˆใจๅŒใ˜ใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใŒ็™บ็”Ÿใ—ใพใ™ใ€‚ใใ—ใฆๅคšใใฎๅ ดๅˆใ€ใ“ใฎใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๆ›ธใ‹ใ‚Œใ‚‹ใ‚ณใƒผใƒ‰ใฎๅคง้ƒจๅˆ†ใซใชใ‚Šใพใ™ใ€‚ + * ใใฎใŸใ‚ใ€FastAPIใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€้–‹็™บๆ™‚้–“ใ€ใƒใ‚ฐใ€ใ‚ณใƒผใƒ‰่กŒๆ•ฐใ‚’็ฏ€็ด„ใงใใ€ไฝฟ็”จใ—ใชใ„ๅ ดๅˆ๏ผˆใ‚ใชใŸใŒใใ‚Œใ‚’ใ™ในใฆ่‡ชๅˆ†ใฎใ‚ณใƒผใƒ‰ใงๅฎŸ่ฃ…ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚๏ผ‰ใจๆฏ”ในใฆใ€ๅŒใ˜ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น๏ผˆใพใŸใฏใใ‚ŒไปฅไธŠ๏ผ‰ใ‚’ๅพ—ใ‚‰ใ‚Œใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ + * FastAPIใ‚’ๆฏ”่ผƒใ™ใ‚‹ๅ ดๅˆใฏใ€Flask-apispecใ€NestJSใ€Moltenใชใฉใ€ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ‚’ๆไพ›ใ™ใ‚‹webใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ๏ผˆใพใŸใฏใƒ„ใƒผใƒซ็พค๏ผ‰ใจๆฏ”่ผƒใ—ใฆใใ ใ•ใ„ใ€‚่‡ชๅ‹•ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใŒ็ตฑๅˆใ•ใ‚ŒใŸใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md index a0d4fb35b1..787eb2e73f 100644 --- a/docs/ja/docs/deployment/concepts.md +++ b/docs/ja/docs/deployment/concepts.md @@ -1,4 +1,4 @@ -# ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ +# ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ { #deployments-concepts } **FastAPI**ใ‚’็”จใ„ใŸใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใจใใ€ใ‚‚ใ—ใใฏใฉใฎใ‚ˆใ†ใชใ‚ฟใ‚คใƒ—ใฎWeb APIใงใ‚ใฃใฆใ‚‚ใ€ใŠใใ‚‰ใๆฐ—ใซใชใ‚‹ใ‚ณใƒณใ‚ปใƒ—ใƒˆใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ @@ -10,12 +10,12 @@ * ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ * ๅ†่ตทๅ‹• * ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ -* ใƒกใƒขใƒชใƒผ +* ใƒกใƒขใƒช * ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ— ใ“ใ‚Œใ‚‰ใŒ**ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆ**ใซใฉใฎใ‚ˆใ†ใชๅฝฑ้Ÿฟใ‚’ไธŽใˆใ‚‹ใ‹ใ‚’่ฆ‹ใฆใ„ใใพใ—ใ‚‡ใ†ใ€‚ -ๆœ€็ต‚็š„ใช็›ฎ็š„ใฏใ€**ๅฎ‰ๅ…จใชๆ–นๆณ•ใง**APIใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ**ใ‚ตใƒผใƒ“ใ‚นใ‚’ๆไพ›**ใ—ใ€**ไธญๆ–ญใ‚’ๅ›ž้ฟ**ใ™ใ‚‹ใ ใ‘ใงใชใใ€**่จˆ็ฎ—ใƒชใ‚ฝใƒผใ‚น**๏ผˆไพ‹ใˆใฐใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผ/ไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‚’ๅฏ่ƒฝใช้™ใ‚ŠๅŠน็އ็š„ใซไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ™ใ€‚๐Ÿš€ +ๆœ€็ต‚็š„ใช็›ฎ็š„ใฏใ€**ๅฎ‰ๅ…จใชๆ–นๆณ•ใง**APIใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ**ใ‚ตใƒผใƒ“ใ‚นใ‚’ๆไพ›**ใ—ใ€**ไธญๆ–ญใ‚’ๅ›ž้ฟ**ใ™ใ‚‹ใ ใ‘ใงใชใใ€**่จˆ็ฎ—ใƒชใ‚ฝใƒผใ‚น**๏ผˆไพ‹ใˆใฐใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผ/ไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‚’ๅฏ่ƒฝใช้™ใ‚ŠๅŠน็އ็š„ใซไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ™ใ€‚ ๐Ÿš€ ใ“ใฎ็ซ ใงใฏๅ‰่ฟฐใ—ใŸ**ใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใซใคใ„ใฆใใ‚Œใžใ‚Œ่ชฌๆ˜Žใ—ใพใ™ใ€‚ @@ -27,16 +27,16 @@ ใ—ใ‹ใ—ใ€ไปŠใฏใ“ใ‚Œใ‚‰ใฎ้‡่ฆใช**ใ‚ณใƒณใ‚ปใƒ—ใƒˆใซๅŸบใฅใใ‚ขใ‚คใƒ‡ใ‚ข**ใ‚’็ขบ่ชใ—ใพใ—ใ‚‡ใ†ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆใฏใ€ไป–ใฎใฉใฎใ‚ฟใ‚คใƒ—ใฎWeb APIใซใ‚‚ๅฝ“ใฆใฏใพใ‚Šใพใ™ใ€‚๐Ÿ’ก -## ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS +## ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS { #security-https } [ๅ‰ใƒใƒฃใƒ—ใ‚ฟใƒผใฎHTTPSใซใคใ„ใฆ](https.md){.internal-link target=_blank}ใงใฏใ€HTTPSใŒใฉใฎใ‚ˆใ†ใซAPIใ‚’ๆš—ๅทๅŒ–ใ™ใ‚‹ใฎใ‹ใซใคใ„ใฆๅญฆใณใพใ—ใŸใ€‚ ้€šๅธธใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใซใจใฃใฆ**ๅค–้ƒจใฎ**ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใงใ‚ใ‚‹**TLS Termination Proxy**ใซใ‚ˆใฃใฆๆไพ›ใ•ใ‚Œใ‚‹ใ“ใจใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ใ“ใฎใƒ—ใƒญใ‚ญใ‚ทใฏ้€šไฟกใฎๆš—ๅทๅŒ–ใ‚’ๆ‹…ๅฝ“ใ—ใพใ™ใ€‚ -ใ•ใ‚‰ใซใ‚ปใ‚ญใƒฅใ‚ขใช้€šไฟกใซใŠใ„ใฆใ€HTTPS่จผๆ˜Žๆ›ธใฎๅฎšๆœŸ็š„ใชๆ›ดๆ–ฐใ‚’่กŒใ„ใพใ™ใŒใ€ใ“ใ‚ŒใฏTLS Termination ProxyใจๅŒใ˜ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Œใฐใ€ๅˆฅใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ใ•ใ‚‰ใซใ€HTTPS่จผๆ˜Žๆ›ธใฎๆ›ดๆ–ฐใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใ‚‚ใฎใŒๅฟ…่ฆใงใ€ๅŒใ˜ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Œใฐใ€ๅˆฅใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -### HTTPS ็”จใƒ„ใƒผใƒซใฎไพ‹ +### HTTPS ็”จใƒ„ใƒผใƒซใฎไพ‹ { #example-tools-for-https } TLS Termination Proxyใจใ—ใฆไฝฟ็”จใงใใ‚‹ใƒ„ใƒผใƒซใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚‚ใฎใŒใ‚ใ‚Šใพใ™๏ผš * Traefik @@ -59,11 +59,11 @@ TLS Termination Proxyใจใ—ใฆไฝฟ็”จใงใใ‚‹ใƒ„ใƒผใƒซใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใช ๆฌกใซ่€ƒๆ…ฎใ™ในใใ‚ณใƒณใ‚ปใƒ—ใƒˆใฏใ€ๅฎŸ้š›ใฎAPIใ‚’ๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆไพ‹๏ผšUvicorn๏ผ‰ใซ้–ข้€ฃใ™ใ‚‹ใ‚‚ใฎใ™ในใฆใงใ™ใ€‚ -## ใƒ—ใƒญใ‚ฐใƒฉใƒ  ใจ ใƒ—ใƒญใ‚ปใ‚น +## ใƒ—ใƒญใ‚ฐใƒฉใƒ  ใจ ใƒ—ใƒญใ‚ปใ‚น { #program-and-process } ็งใŸใกใฏใ€Œ**ใƒ—ใƒญใ‚ปใ‚น**ใ€ใจใ„ใ†่จ€่‘‰ใซใคใ„ใฆใŸใใ•ใ‚“่ฉฑใ™ใฎใงใ€ใใฎๆ„ๅ‘ณใ‚„ใ€Œ**ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ€ใจใ„ใ†่จ€่‘‰ใจใฎ้•ใ„ใ‚’ๆ˜Ž็ขบใซใ—ใฆใŠใใจไพฟๅˆฉใงใ™ใ€‚ -### ใƒ—ใƒญใ‚ฐใƒฉใƒ ใจใฏไฝ•ใ‹ +### ใƒ—ใƒญใ‚ฐใƒฉใƒ ใจใฏไฝ•ใ‹ { #what-is-a-program } **ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใจใ„ใ†่จ€่‘‰ใฏใ€ไธ€่ˆฌ็š„ใซใ„ใ‚ใ„ใ‚ใชใ‚‚ใฎใ‚’่กจ็พใ™ใ‚‹ใฎใซไฝฟใ‚ใ‚Œใพใ™๏ผš @@ -71,7 +71,7 @@ TLS Termination Proxyใจใ—ใฆไฝฟ็”จใงใใ‚‹ใƒ„ใƒผใƒซใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใช * OSใซใ‚ˆใฃใฆๅฎŸ่กŒใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ใƒ•ใ‚กใ‚คใƒซ๏ผˆไพ‹: `python`, `python.exe` or `uvicorn`๏ผ‰ * OSไธŠใง**ๅฎŸ่กŒ**ใ—ใฆใ„ใ‚‹้–“ใ€CPUใ‚’ไฝฟ็”จใ—ใ€ใƒกใƒขใƒชไธŠใซไฝ•ใ‹ใ‚’ไฟๅญ˜ใ™ใ‚‹็‰นๅฎšใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆ**ใƒ—ใƒญใ‚ปใ‚น**ใจใ‚‚ๅ‘ผใฐใ‚Œใ‚‹๏ผ‰ -### ใƒ—ใƒญใ‚ปใ‚นใจใฏไฝ•ใ‹ +### ใƒ—ใƒญใ‚ปใ‚นใจใฏไฝ•ใ‹ { #what-is-a-process } **ใƒ—ใƒญใ‚ปใ‚น**ใจใ„ใ†่จ€่‘‰ใฏ้€šๅธธใ€ใ‚ˆใ‚Šๅ…ทไฝ“็š„ใชๆ„ๅ‘ณใงไฝฟใ‚ใ‚Œใ€OSใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใ‚‚ใฎใ ใ‘ใ‚’ๆŒ‡ใ—ใพใ™๏ผˆๅ…ˆใปใฉใฎๆœ€ๅพŒใฎ่ชฌๆ˜Žใฎใ‚ˆใ†ใซ๏ผ‰๏ผš @@ -92,27 +92,29 @@ OSใฎใ€Œใ‚ฟใ‚นใ‚ฏใƒปใƒžใƒใƒผใ‚ธใƒฃใƒผใ€ใ‚„ใ€Œใ‚ทใ‚นใƒ†ใƒ ใƒปใƒขใƒ‹ใ‚ฟใƒผใ€๏ผˆ ใ•ใฆใ€**ใƒ—ใƒญใ‚ปใ‚น**ใจ**ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใจใ„ใ†็”จ่ชžใฎ้•ใ„ใ‚’็ขบ่ชใ—ใŸใจใ“ใ‚ใงใ€ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใซใคใ„ใฆ่ฉฑใ‚’็ถšใ‘ใพใ™ใ€‚ -## ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ +## ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ { #running-on-startup } ใปใจใ‚“ใฉใฎๅ ดๅˆใ€Web APIใ‚’ไฝœๆˆใ™ใ‚‹ใจใใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใคใงใ‚‚ใ‚ขใ‚ฏใ‚ปใ‚นใงใใ‚‹ใ‚ˆใ†ใซใ€**ๅธธใซ**ไธญๆ–ญใ•ใ‚Œใ‚‹ใ“ใจใชใ**ๅฎŸ่กŒใ•ใ‚Œใ‚‹**ใ“ใจใ‚’ๆœ›ใฟใพใ™ใ€‚ใ‚‚ใกใ‚ใ‚“ใ€็‰นๅฎšใฎ็ŠถๆณใงใฎใฟๅฎŸ่กŒใ•ใ›ใŸใ„็‰นๅˆฅใช็†็”ฑใŒใ‚ใ‚‹ๅ ดๅˆใฏๅˆฅใงใ™ใŒใ€ใใฎๆ™‚้–“ใฎใปใจใ‚“ใฉใฏใ€ๅธธใซๅฎŸ่กŒใ•ใ‚Œใ€**ๅˆฉ็”จๅฏ่ƒฝ**ใงใ‚ใ‚‹ใ“ใจใ‚’ๆœ›ใฟใพใ™ใ€‚ -### ใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผไธŠใงใฎๅฎŸ่กŒ +### ใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผไธŠใงใฎๅฎŸ่กŒ { #in-a-remote-server } -ใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผ๏ผˆใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผใ€ไปฎๆƒณใƒžใ‚ทใƒณใชใฉ๏ผ‰ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ใจใใซใงใใ‚‹ๆœ€ใ‚‚็ฐกๅ˜ใชใ“ใจใฏใ€ใƒญใƒผใ‚ซใƒซใง้–‹็™บใ™ใ‚‹ใจใใจๅŒใ˜ใ‚ˆใ†ใซใ€Uvicorn๏ผˆใพใŸใฏๅŒๆง˜ใฎใ‚‚ใฎ๏ผ‰ใ‚’ๆ‰‹ๅ‹•ใงๅฎŸ่กŒใ™ใ‚‹ใ“ใจใงใ™ใ€‚ ใ“ใฎๆ–นๆณ•ใฏ**้–‹็™บไธญ**ใซใฏๅฝนใซ็ซ‹ใคใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ +ใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผ๏ผˆใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผใ€ไปฎๆƒณใƒžใ‚ทใƒณใชใฉ๏ผ‰ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ใจใใซใงใใ‚‹ๆœ€ใ‚‚็ฐกๅ˜ใชใ“ใจใฏใ€ใƒญใƒผใ‚ซใƒซใง้–‹็™บใ™ใ‚‹ใจใใจๅŒใ˜ใ‚ˆใ†ใซใ€`fastapi run`๏ผˆUvicornใ‚’ไฝฟ็”จใ—ใพใ™๏ผ‰ใ‚„ๅŒๆง˜ใฎใ‚‚ใฎใ‚’ๆ‰‹ๅ‹•ใงๅฎŸ่กŒใ™ใ‚‹ใ“ใจใงใ™ใ€‚ + +ใใ—ใฆใ“ใ‚Œใฏๅ‹•ไฝœใ—ใ€**้–‹็™บไธญ**ใซใฏๅฝนใซ็ซ‹ใคใงใ—ใ‚‡ใ†ใ€‚ ใ—ใ‹ใ—ใ€ใ‚ตใƒผใƒใƒผใธใฎๆŽฅ็ถšใŒๅˆ‡ใ‚ŒใŸๅ ดๅˆใ€**ๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚น**ใฏใŠใใ‚‰ใใƒ€ใ‚ฆใƒณใ—ใฆใ—ใพใ†ใงใ—ใ‚‡ใ†ใ€‚ ใใ—ใฆใ‚ตใƒผใƒใƒผใŒๅ†่ตทๅ‹•ใ•ใ‚ŒใŸๅ ดๅˆ๏ผˆใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆใ‚„ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผใ‹ใ‚‰ใฎใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใฎๅพŒใชใฉ๏ผ‰ใ€ใŠใใ‚‰ใใ‚ใชใŸใฏใใ‚Œใซ**ๆฐ—ใฅใ‹ใชใ„ใงใ—ใ‚‡ใ†**ใ€‚ใใฎใŸใ‚ใ€ใƒ—ใƒญใ‚ปใ‚นใ‚’ๆ‰‹ๅ‹•ใงๅ†่ตทๅ‹•ใ—ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ“ใจใ™ใ‚‰ๆฐ—ใฅใ‹ใชใ„ใงใ—ใ‚‡ใ†ใ€‚ใคใพใ‚Šใ€APIใฏใƒ€ใ‚ฆใƒณใ—ใŸใพใพใชใฎใงใ™ใ€‚๐Ÿ˜ฑ -### ่ตทๅ‹•ๆ™‚ใซ่‡ชๅ‹•็š„ใซๅฎŸ่กŒ +### ่ตทๅ‹•ๆ™‚ใซ่‡ชๅ‹•็š„ใซๅฎŸ่กŒ { #run-automatically-on-startup } ไธ€่ˆฌ็š„ใซใ€ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆUvicornใชใฉ๏ผ‰ใฏใ‚ตใƒผใƒใƒผ่ตทๅ‹•ๆ™‚ใซ่‡ชๅ‹•็š„ใซ้–‹ๅง‹ใ•ใ‚Œใ€**ไบบใฎไป‹ๅ…ฅ**ใ‚’ๅฟ…่ฆใจใ›ใšใซใ€APIใจไธ€็ท’ใซใƒ—ใƒญใ‚ปใ‚นใŒๅธธใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใŸใ„ใจๆ€ใ‚ใ‚Œใพใ™๏ผˆUvicornใŒFastAPIใ‚ขใƒ—ใƒชใ‚’ๅฎŸ่กŒใ™ใ‚‹ใชใฉ๏ผ‰ใ€‚ -### ๅˆฅใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎ็”จๆ„ +### ๅˆฅใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎ็”จๆ„ { #separate-program } ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใŸใ‚ใซใ€้€šๅธธใฏ**ๅˆฅใฎใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’็”จๆ„ใ—ใ€่ตทๅ‹•ๆ™‚ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ใใ—ใฆๅคšใใฎๅ ดๅˆใ€ไป–ใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใ‚„ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ€ไพ‹ใˆใฐใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚‚ๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ -### ่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒใ™ใ‚‹ใƒ„ใƒผใƒซใฎไพ‹ +### ่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒใ™ใ‚‹ใƒ„ใƒผใƒซใฎไพ‹ { #example-tools-to-run-at-startup } ๅฎŸ่กŒใ™ใ‚‹ใƒ„ใƒผใƒซใฎไพ‹ใ‚’ใ„ใใคใ‹ๆŒ™ใ’ใพใ™: @@ -127,31 +129,33 @@ OSใฎใ€Œใ‚ฟใ‚นใ‚ฏใƒปใƒžใƒใƒผใ‚ธใƒฃใƒผใ€ใ‚„ใ€Œใ‚ทใ‚นใƒ†ใƒ ใƒปใƒขใƒ‹ใ‚ฟใƒผใ€๏ผˆ ๆฌกใฎ็ซ ใงใ€ใ‚ˆใ‚Šๅ…ทไฝ“็š„ใชไพ‹ใ‚’ๆŒ™ใ’ใฆใ„ใใพใ™ใ€‚ -## ๅ†่ตทๅ‹• +## ๅ†่ตทๅ‹• { #restarts } ่ตทๅ‹•ๆ™‚ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ใฎใจๅŒๆง˜ใซใ€ๅคฑๆ•—ๅพŒใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ**ๅ†่ตทๅ‹•**ใ•ใ‚Œใ‚‹ใ“ใจใ‚‚็ขบ่ชใ—ใŸใ„ใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ -### ๆˆ‘ใ€…ใฏ้–“้•ใ„ใ‚’็Šฏใ™ +### ๆˆ‘ใ€…ใฏ้–“้•ใ„ใ‚’็Šฏใ™ { #we-make-mistakes } ็งใŸใกไบบ้–“ใฏๅธธใซ**้–“้•ใ„**ใ‚’็Šฏใ—ใพใ™ใ€‚ใ‚ฝใƒ•ใƒˆใ‚ฆใ‚งใ‚ขใซใฏใ€ใปใจใ‚“ใฉๅธธใซ**ใƒใ‚ฐ**ใŒใ‚ใ‚‰ใ‚†ใ‚‹็ฎ‡ๆ‰€ใซ้š ใ•ใ‚Œใฆใ„ใพใ™ใ€‚๐Ÿ› -### ๅฐใ•ใชใ‚จใƒฉใƒผใฏ่‡ชๅ‹•็š„ใซๅ‡ฆ็†ใ•ใ‚Œใ‚‹ +ใใ—ใฆ็งใŸใก้–‹็™บ่€…ใฏใ€ใใ‚Œใ‚‰ใฎใƒใ‚ฐใ‚’่ฆ‹ใคใ‘ใŸใ‚Šๆ–ฐใ—ใ„ๆฉŸ่ƒฝใ‚’ๅฎŸ่ฃ…ใ—ใŸใ‚Šใ—ใชใŒใ‚‰ใ‚ณใƒผใƒ‰ใ‚’ๆ”นๅ–„ใ—็ถšใ‘ใพใ™๏ผˆๆ–ฐใ—ใ„ใƒใ‚ฐใ‚‚่ฟฝๅŠ ใ—ใฆใ—ใพใ†ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“๐Ÿ˜…๏ผ‰ใ€‚ + +### ๅฐใ•ใชใ‚จใƒฉใƒผใฏ่‡ชๅ‹•็š„ใซๅ‡ฆ็†ใ•ใ‚Œใ‚‹ { #small-errors-automatically-handled } FastAPIใงWeb APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใ€ใ‚ณใƒผใƒ‰ใซใ‚จใƒฉใƒผใŒใ‚ใ‚‹ๅ ดๅˆใ€FastAPIใฏ้€šๅธธใ€ใ‚จใƒฉใƒผใ‚’ๅผ•ใ่ตทใ“ใ—ใŸๅ˜ไธ€ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใซใ‚จใƒฉใƒผใ‚’ๅซใ‚ใพใ™ใ€‚๐Ÿ›ก ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆ**500 Internal Server Error**ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใŒใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏๅฎŒๅ…จใซใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ™ใ‚‹ใฎใงใฏใชใใ€ๆฌกใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใŸใ‚ใซๅ‹•ไฝœใ‚’็ถšใ‘ใพใ™ใ€‚ -### ้‡ๅคงใชใ‚จใƒฉใƒผ - ใ‚ฏใƒฉใƒƒใ‚ทใƒฅ +### ้‡ๅคงใชใ‚จใƒฉใƒผ - ใ‚ฏใƒฉใƒƒใ‚ทใƒฅ { #bigger-errors-crashes } ใ—ใ‹ใ—ใชใŒใ‚‰ใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ…จไฝ“ใ‚’ใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ•ใ›ใ‚‹ใ‚ˆใ†ใชใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ„ใฆ**UvicornใจPythonใ‚’ใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ•ใ›ใ‚‹ใ‚ˆใ†ใชใ‚ฑใƒผใ‚นใ‚‚ใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿ’ฅ -ใใ‚Œใงใ‚‚ใ€ใ‚ใ‚‹็ฎ‡ๆ‰€ใงใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ—ใŸใ‹ใ‚‰ใจใ„ใฃใฆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅœๆญขใ•ใ›ใŸใพใพใซใ—ใŸใใชใ„ใงใ—ใ‚‡ใ†ใ€‚ ๅฐ‘ใชใใจใ‚‚ๅฃŠใ‚Œใฆใ„ใชใ„*ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ*ใซใคใ„ใฆใฏใ€**ๅฎŸ่กŒใ—็ถšใ‘ใŸใ„**ใฏใšใงใ™ใ€‚ +ใใ‚Œใงใ‚‚ใ€ใ‚ใ‚‹็ฎ‡ๆ‰€ใงใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ—ใŸใ‹ใ‚‰ใจใ„ใฃใฆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅœๆญขใ•ใ›ใŸใพใพใซใ—ใŸใใชใ„ใงใ—ใ‚‡ใ†ใ€‚ ๅฐ‘ใชใใจใ‚‚ๅฃŠใ‚Œใฆใ„ใชใ„*path operation*ใซใคใ„ใฆใฏใ€**ๅฎŸ่กŒใ—็ถšใ‘ใŸใ„**ใฏใšใงใ™ใ€‚ -### ใ‚ฏใƒฉใƒƒใ‚ทใƒฅๅพŒใฎๅ†่ตทๅ‹• +### ใ‚ฏใƒฉใƒƒใ‚ทใƒฅๅพŒใฎๅ†่ตทๅ‹• { #restart-after-crash } ใ—ใ‹ใ—ใ€ๅฎŸ่กŒไธญใฎ**ใƒ—ใƒญใ‚ปใ‚น**ใ‚’ใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ•ใ›ใ‚‹ใ‚ˆใ†ใชๆœฌๅฝ“ใซใฒใฉใ„ใ‚จใƒฉใƒผใฎๅ ดๅˆใ€ๅฐ‘ใชใใจใ‚‚2ใ€œ3ๅ›žใปใฉใƒ—ใƒญใ‚ปใ‚นใ‚’**ๅ†่ตทๅ‹•**ใ•ใ›ใ‚‹ๅค–้ƒจใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒๅฟ…่ฆใงใ—ใ‚‡ใ†ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ...ใจใฏใ„ใˆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ…จไฝ“ใŒ**ใ™ใใซใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ™ใ‚‹**ใฎใงใ‚ใ‚Œใฐใ€ใ„ใคใพใงใ‚‚ๅ†่ตทๅ‹•ใ—็ถšใ‘ใ‚‹ใฎใฏๆ„ๅ‘ณใŒใชใ„ใงใ—ใ‚‡ใ†ใ€‚ใ—ใ‹ใ—ใ€ใใฎๅ ดๅˆใฏใŠใใ‚‰ใ้–‹็™บไธญใ‹ๅฐ‘ใชใใจใ‚‚ใƒ‡ใƒ—ใƒญใ‚ค็›ดๅพŒใซๆฐ—ใฅใใจๆ€ใ‚ใ‚Œใพใ™ใ€‚ @@ -161,7 +165,7 @@ FastAPIใงWeb APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใ€ใ‚ณใƒผใƒ‰ใซใ‚จใƒฉใƒผใŒใ‚ใ‚‹ๅ ดๅˆใ€ ใ‚ใชใŸใฏใŠใใ‚‰ใ**ๅค–้ƒจใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ**ใŒใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ†่ตทๅ‹•ใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚’ๆœ›ใ‚€ใจ่€ƒใˆใพใ™ใ€‚ ใชใœใชใ‚‰ใ€ใใฎๆ™‚็‚นใงUvicornใจPythonใ‚’ไฝฟใฃใŸๅŒใ˜ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ™ใงใซใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ—ใฆใŠใ‚Šใ€ๅŒใ˜ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅŒใ˜ใ‚ณใƒผใƒ‰ใซๅฏพใ—ใฆไฝ•ใ‚‚ใงใใชใ„ใŸใ‚ใงใ™ใ€‚ -### ่‡ชๅ‹•็š„ใซๅ†่ตทๅ‹•ใ™ใ‚‹ใƒ„ใƒผใƒซใฎไพ‹ +### ่‡ชๅ‹•็š„ใซๅ†่ตทๅ‹•ใ™ใ‚‹ใƒ„ใƒผใƒซใฎไพ‹ { #example-tools-to-restart-automatically } ใปใจใ‚“ใฉใฎๅ ดๅˆใ€ๅ‰่ฟฐใ—ใŸ**่ตทๅ‹•ๆ™‚ใซใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใ™ใ‚‹**ใŸใ‚ใซไฝฟ็”จใ•ใ‚Œใ‚‹ใƒ„ใƒผใƒซใฏใ€่‡ชๅ‹•ใง**ๅ†่ตทๅ‹•**ใ™ใ‚‹ใ“ใจใซใ‚‚ๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ @@ -176,19 +180,19 @@ FastAPIใงWeb APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใ€ใ‚ณใƒผใƒ‰ใซใ‚จใƒฉใƒผใŒใ‚ใ‚‹ๅ ดๅˆใ€ * ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผใŒใ‚ตใƒผใƒ“ใ‚นใฎไธ€้ƒจใจใ—ใฆๅ†…้ƒจ็š„ใซๅ‡ฆ็† * ใใฎใปใ‹... -## ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒ—ใƒญใ‚ปใ‚นใจใƒกใƒขใƒชใƒผ +## ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒ—ใƒญใ‚ปใ‚นใจใƒกใƒขใƒช { #replication-processes-and-memory } -FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ไฝฟ็”จใ—ใ€**1ใคใฎใƒ—ใƒญใ‚ปใ‚น**ใง1ๅบฆใซ่ค‡ๆ•ฐใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซๅŒๆ™‚ใซๅฏพๅฟœใงใใพใ™ใ€‚ +FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใ‚’ๅฎŸ่กŒใ™ใ‚‹ `fastapi` ใ‚ณใƒžใƒณใƒ‰ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ไฝฟ็”จใ—ใ€**1ใคใฎใƒ—ใƒญใ‚ปใ‚น**ใง1ๅบฆใซ่ค‡ๆ•ฐใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซๅŒๆ™‚ใซๅฏพๅฟœใงใใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ๅคšใใฎๅ ดๅˆใ€่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใ‚’ๅŒๆ™‚ใซๅฎŸ่กŒใ—ใŸใ„ใจ่€ƒใˆใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -### ่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น - Worker +### ่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น - Worker { #multiple-processes-workers } ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎๆ•ฐใŒๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใงๅ‡ฆ็†ใงใใ‚‹ๆ•ฐใ‚’่ถ…ใˆใฆใŠใ‚Š๏ผˆใŸใจใˆใฐไปฎๆƒณใƒžใ‚ทใƒณใŒใใ‚Œใปใฉๅคงใใใชใ„ๅ ดๅˆ๏ผ‰ใ€ใ‹ใคใ‚ตใƒผใƒใƒผใฎ CPU ใซ**่ค‡ๆ•ฐใฎใ‚ณใ‚ข**ใŒใ‚ใ‚‹ๅ ดๅˆใ€ๅŒใ˜ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๅŒๆ™‚ใซ**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ•ใ›ใ€ใ™ในใฆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅˆ†ๆ•ฃใ•ใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ๅŒใ˜APIใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎ**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใ€ใใ‚Œใ‚‰ใฏไธ€่ˆฌ็š„ใซ**Worker๏ผใƒฏใƒผใ‚ซใƒผ**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ -### ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น ใจ ใƒใƒผใƒˆ +### ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น ใจ ใƒใƒผใƒˆ { #worker-processes-and-ports } [HTTPSใซใคใ„ใฆ](https.md){.internal-link target=_blank}ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ€1ใคใฎใ‚ตใƒผใƒใƒผใง1ใคใฎใƒใƒผใƒˆใจIPใ‚ขใƒ‰ใƒฌใ‚นใฎ็ต„ใฟๅˆใ‚ใ›ใงใƒชใƒƒใ‚นใƒณใงใใ‚‹ใฎใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใงใ‚ใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใ„ใพใ™ใงใ—ใ‚‡ใ†ใ‹๏ผŸ @@ -197,13 +201,13 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ ใใฎใŸใ‚ใ€**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅŒๆ™‚ใซๆŒใคใซใฏ**ใƒใƒผใƒˆใงใƒชใƒƒใ‚นใƒณใ—ใฆใ„ใ‚‹ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚น**ใŒๅฟ…่ฆใงใ‚ใ‚Šใ€ใใ‚ŒใŒไฝ•ใ‚‰ใ‹ใฎๆ–นๆณ•ใงๅ„ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใซ้€šไฟกใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใŒๆฑ‚ใ‚ใ‚‰ใ‚Œใพใ™ใ€‚ -### ใƒ—ใƒญใ‚ปใ‚นใ‚ใŸใ‚Šใฎใƒกใƒขใƒชใƒผ +### ใƒ—ใƒญใ‚ปใ‚นใ‚ใŸใ‚Šใฎใƒกใƒขใƒช { #memory-per-process } ใ•ใฆใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใƒกใƒขใƒชใซใƒญใƒผใƒ‰ใ™ใ‚‹้š›ใซใฏใ€ไพ‹ใˆใฐๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใ‚„ๅคงใใชใƒ•ใ‚กใ‚คใƒซใฎๅ†…ๅฎนใ‚’ๅค‰ๆ•ฐใซๅ…ฅใ‚ŒใŸใ‚Šใ™ใ‚‹ๅ ดๅˆใงใฏใ€**ใ‚ตใƒผใƒใƒผใฎใƒกใƒขใƒช๏ผˆRAM๏ผ‰**ใ‚’ๅฐ‘ใ—ๆถˆ่ฒปใ—ใพใ™ใ€‚ ใใ—ใฆ่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใฏ้€šๅธธใ€**ใƒกใƒขใƒชใ‚’ๅ…ฑๆœ‰ใ—ใพใ›ใ‚“**ใ€‚ใ“ใ‚Œใฏใ€ๅฎŸ่กŒไธญใฎๅ„ใƒ—ใƒญใ‚ปใ‚นใŒใใ‚Œใžใ‚Œ็‹ฌ่‡ชใฎๅค‰ๆ•ฐใ‚„ใƒกใƒขใƒช็ญ‰ใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใคใพใ‚Šใ€ใ‚ณใƒผใƒ‰ๅ†…ใงๅคง้‡ใฎใƒกใƒขใƒชใ‚’ๆถˆ่ฒปใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€**ๅ„ใƒ—ใƒญใ‚ปใ‚น**ใฏๅŒ็ญ‰ใฎ้‡ใฎใƒกใƒขใƒชใ‚’ๆถˆ่ฒปใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ -### ใ‚ตใƒผใƒใƒผใƒกใƒขใƒชใƒผ +### ใ‚ตใƒผใƒใƒผใƒกใƒขใƒช { #server-memory } ไพ‹ใˆใฐใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใŒ **1GBใฎใ‚ตใ‚คใ‚บใฎๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซ**ใ‚’ใƒญใƒผใƒ‰ใ™ใ‚‹ๅ ดๅˆใ€APIใง1ใคใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€ๅฐ‘ใชใใจใ‚‚1GBใฎRAMใ‚’ๆถˆ่ฒปใ—ใพใ™ใ€‚ @@ -211,7 +215,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ ใƒชใƒขใƒผใƒˆใ‚ตใƒผใƒใƒผใ‚„ไปฎๆƒณใƒžใ‚ทใƒณใฎRAMใŒ3GBใ—ใ‹ใชใ„ๅ ดๅˆใ€4GBไปฅไธŠใฎRAMใ‚’ใƒญใƒผใƒ‰ใ—ใ‚ˆใ†ใจใ™ใ‚‹ใจๅ•้กŒใŒ็™บ็”Ÿใ—ใพใ™ใ€‚๐Ÿšจ -### ่ค‡ๆ•ฐใƒ—ใƒญใ‚ปใ‚น - ไพ‹ +### ่ค‡ๆ•ฐใƒ—ใƒญใ‚ปใ‚น - ไพ‹ { #multiple-processes-an-example } ใ“ใฎไพ‹ใงใฏใ€2ใคใฎ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ—ๅˆถๅพกใ™ใ‚‹**ใƒžใƒใƒผใ‚ธใƒฃใƒผใƒป ใƒ—ใƒญใ‚ปใ‚น**ใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -227,7 +231,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ ๆฏŽๅ›žๅŒ็จ‹ๅบฆใฎ่จˆ็ฎ—ใ‚’่กŒใ†APIใŒใ‚ใ‚Šใ€ๅคšใใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใ‚‹ใฎใงใ‚ใ‚Œใฐใ€**CPUไฝฟ็”จ็އ**ใ‚‚ใŠใใ‚‰ใ**ๅฎ‰ๅฎš**ใ™ใ‚‹ใงใ—ใ‚‡ใ†๏ผˆๅธธใซๆ€ฅๆฟ€ใซไธŠไธ‹ใ™ใ‚‹ใฎใงใฏใชใ๏ผ‰ใ€‚ -### ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใƒปใƒ„ใƒผใƒซใจๆˆฆ็•ฅใฎไพ‹ +### ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใƒปใƒ„ใƒผใƒซใจๆˆฆ็•ฅใฎไพ‹ { #examples-of-replication-tools-and-strategies } ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ„ใใคใ‹ใฎใ‚ขใƒ—ใƒญใƒผใƒใŒใ‚ใ‚Šใพใ™ใŒใ€ๅ…ทไฝ“็š„ใชๆˆฆ็•ฅใซใคใ„ใฆใฏๆฌกใฎ็ซ (Dockerใ‚„ใ‚ณใƒณใƒ†ใƒŠใฎ็ซ ใชใฉ)ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™ใ€‚ @@ -237,25 +241,22 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ ่€ƒใˆใ‚‰ใ‚Œใ‚‹็ต„ใฟๅˆใ‚ใ›ใจๆˆฆ็•ฅใ‚’ใ„ใใคใ‹็ดนไป‹ใ—ใพใ™๏ผš -* **Gunicorn**ใŒ**Uvicornใƒฏใƒผใ‚ซใƒผ**ใ‚’็ฎก็† - * Gunicornใฏ**IP**ใจ**ใƒใƒผใƒˆ**ใ‚’ใƒชใƒƒใ‚นใƒณใ™ใ‚‹**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใงใ€ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏ**่ค‡ๆ•ฐใฎUvicornใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๆŒใคใ“ใจใซใ‚ˆใฃใฆ่กŒใ‚ใ‚Œใ‚‹ใ€‚ -* **Uvicorn**ใŒ**Uvicornใƒฏใƒผใ‚ซใƒผ**ใ‚’็ฎก็† +* `--workers` ใ‚’ๆŒ‡ๅฎšใ—ใŸ **Uvicorn** * 1ใคใฎUvicornใฎ**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผ**ใŒ**IP**ใจ**ใƒใƒผใƒˆ**ใ‚’ใƒชใƒƒใ‚นใƒณใ—ใ€**่ค‡ๆ•ฐใฎUvicornใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ™ใ‚‹ใ€‚ * **Kubernetes**ใ‚„ใใฎไป–ใฎๅˆ†ๆ•ฃ**ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚ทใ‚นใƒ†ใƒ ** * **Kubernetes**ใƒฌใ‚คใƒคใƒผใฎไฝ•ใ‹ใŒ**IP**ใจ**ใƒใƒผใƒˆ**ใ‚’ใƒชใƒƒใ‚นใƒณใ™ใ‚‹ใ€‚ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€**่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠ**ใซใใ‚Œใžใ‚Œ**1ใคใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ•ใ›ใ‚‹ใ“ใจใง่กŒใ‚ใ‚Œใ‚‹ใ€‚ * **ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒปใ‚ตใƒผใƒ“ใ‚น**ใซใ‚ˆใ‚‹ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ * ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒปใ‚ตใƒผใƒ“ใ‚นใฏใŠใใ‚‰ใ**ใ‚ใชใŸใฎใŸใ‚ใซใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅ‡ฆ็†**ใ—ใพใ™ใ€‚**ๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚น**ใ‚„ไฝฟ็”จใ™ใ‚‹**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใ‚’ๅฎš็พฉใงใใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใŒใ€ใ„ใšใ‚Œใซใ›ใ‚ˆใ€ใใ‚ŒใฏใŠใใ‚‰ใ**ๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใงใ‚ใ‚Šใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒ“ใ‚นใฏใใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ใ“ใ‚Œใ‚‰ใฎ**ใ‚ณใƒณใƒ†ใƒŠ**ใ‚„Dockerใใ—ใฆKubernetesใซ้–ขใ™ใ‚‹้ …็›ฎใŒใ€ใพใ ใ‚ใพใ‚Šๆ„ๅ‘ณใ‚’ใชใ—ใฆใ„ใชใใฆใ‚‚ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ - -ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใ€Dockerใ€Kubernetesใชใฉใซใคใ„ใฆใฏใ€ๆฌกใฎ็ซ ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™: [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}. +ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใ€Dockerใ€Kubernetesใชใฉใซใคใ„ใฆใฏใ€ๅฐ†ๆฅใฎ็ซ ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™: [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}. /// -## ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ— +## ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ— { #previous-steps-before-starting } ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’**้–‹ๅง‹ใ™ใ‚‹ๅ‰**ใซใ€ใ„ใใคใ‹ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅฎŸ่กŒใ—ใŸใ„ๅ ดๅˆใŒๅคšใใ‚ใ‚Šใพใ™ใ€‚ @@ -271,7 +272,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ ใ‚‚ใกใ‚ใ‚“ใ€ไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ไฝ•ๅบฆใ‚‚ๅฎŸ่กŒใ—ใฆใ‚‚ๅ•้กŒใŒใชใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใ€ใใฎ้š›ใฏๅฏพๅ‡ฆใŒใ‹ใชใ‚Šๆฅฝใซใชใ‚Šใพใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ใพใŸใ€ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใซใ‚ˆใฃใฆใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’้–‹ๅง‹ใ™ใ‚‹ๅ‰ใฎ**ไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—**ใŒๅฟ…่ฆใชใ„ๅ ดๅˆใ‚‚ใ‚ใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ @@ -279,7 +280,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ /// -### ไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—ใฎๆˆฆ็•ฅไพ‹ +### ไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—ใฎๆˆฆ็•ฅไพ‹ { #examples-of-previous-steps-strategies } ใ“ใ‚Œใฏ**ใ‚ทใ‚นใƒ†ใƒ ใ‚’**ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๆ–นๆณ•ใซ**ๅคงใใไพๅญ˜**ใ™ใ‚‹ใ ใ‚ใ†ใ—ใ€ใŠใใ‚‰ใใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎ่ตทๅ‹•ๆ–นๆณ•ใ‚„ๅ†่ตทๅ‹•ใฎๅ‡ฆ็†ใชใฉใซใ‚‚้–ขไฟ‚ใ—ใฆใใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ @@ -289,14 +290,13 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ * ไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅฎŸ่กŒใ—ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ตทๅ‹•ใ™ใ‚‹bashใ‚นใ‚ฏใƒชใƒ—ใƒˆ * ๅˆฉ็”จใ™ใ‚‹bashใ‚นใ‚ฏใƒชใƒ—ใƒˆใ‚’่ตทๅ‹•๏ผๅ†่ตทๅ‹•ใ—ใŸใ‚Šใ€ใ‚จใƒฉใƒผใ‚’ๆคœๅ‡บใ—ใŸใ‚Šใ™ใ‚‹ๆ–นๆณ•ใฏไปฅๅ‰ใจใ—ใฆๅฟ…่ฆใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ - -ใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟใฃใŸๅ…ทไฝ“็š„ใชไพ‹ใซใคใ„ใฆใฏใ€ๆฌกใฎ็ซ ใง็ดนไป‹ใ—ใพใ™: [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}. +ใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟใฃใŸๅ…ทไฝ“็š„ใชไพ‹ใซใคใ„ใฆใฏใ€ๅฐ†ๆฅใฎ็ซ ใง็ดนไป‹ใ—ใพใ™: [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}. /// -## ใƒชใ‚ฝใƒผใ‚นใฎๅˆฉ็”จ +## ใƒชใ‚ฝใƒผใ‚นใฎๅˆฉ็”จ { #resource-utilization } ใ‚ใชใŸใฎใ‚ตใƒผใƒใƒผใฏ**ใƒชใ‚ฝใƒผใ‚น**ใงใ‚ใ‚Šใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใ—CPUใฎ่จˆ็ฎ—ๆ™‚้–“ใ‚„ๅˆฉ็”จๅฏ่ƒฝใชRAMใƒกใƒขใƒชใ‚’ๆถˆ่ฒปใพใŸใฏ**ๅˆฉ็”จ**ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -319,7 +319,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ `htop`ใฎใ‚ˆใ†ใชๅ˜็ด”ใชใƒ„ใƒผใƒซใ‚’ไฝฟใฃใฆใ€ใ‚ตใƒผใƒใƒผใงไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹CPUใ‚„RAMใ€ใ‚ใ‚‹ใ„ใฏๅ„ใƒ—ใƒญใ‚ปใ‚นใงไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹้‡ใ‚’่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ‚ใ‚‹ใ„ใฏใ€ใ‚ˆใ‚Š่ค‡้›‘ใช็›ฃ่ฆ–ใƒ„ใƒผใƒซใ‚’ไฝฟใฃใฆใ€ใ‚ตใƒผใƒใซๅˆ†ๆ•ฃใ—ใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‡ใƒ—ใƒญใ‚คๆ–นๆณ•ใ‚’ๆฑบๅฎšใ™ใ‚‹้š›ใซใ€่€ƒๆ…ฎใ™ในใใงใ‚ใ‚ใ†ไธป่ฆใชใ‚ณใƒณใ‚ปใƒ—ใƒˆใฎใ„ใใคใ‹ใ‚’็ดนไป‹ใ—ใฆใ„ใใพใ—ใŸ๏ผš @@ -327,7 +327,7 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใฎใ‚ˆใ†ใชใ‚ตใƒผใƒใƒผใƒ—ใƒญ * ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ * ๅ†่ตทๅ‹• * ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ -* ใƒกใƒขใƒชใƒผ +* ใƒกใƒขใƒช * ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ— ใ“ใ‚Œใ‚‰ใฎ่€ƒใˆๆ–นใจใใฎ้ฉ็”จๆ–นๆณ•ใ‚’็†่งฃใ™ใ‚‹ใ“ใจใงใ€ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใ‚’่จญๅฎšใ—ใŸใ‚Š่ชฟๆ•ดใ—ใŸใ‚Šใ™ใ‚‹้š›ใซๅฟ…่ฆใช็›ดๆ„Ÿ็š„ใชๅˆคๆ–ญใŒใงใใ‚‹ใ‚ˆใ†ใซใชใ‚‹ใฏใšใงใ™ใ€‚๐Ÿค“ diff --git a/docs/ja/docs/deployment/docker.md b/docs/ja/docs/deployment/docker.md index 53fc851f1e..6c182448c9 100644 --- a/docs/ja/docs/deployment/docker.md +++ b/docs/ja/docs/deployment/docker.md @@ -1,20 +1,17 @@ -# ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker +# ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker { #fastapi-in-containers-docker } -FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๅ ดๅˆใ€ไธ€่ˆฌ็š„ใชใ‚ขใƒ—ใƒญใƒผใƒใฏ**Linuxใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ - -ๅŸบๆœฌ็š„ใซใฏ **Docker**ใ‚’็”จใ„ใฆ่กŒใ‚ใ‚Œใพใ™ใ€‚็”Ÿๆˆใ•ใ‚ŒใŸใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใฏใ€ใ„ใใคใ‹ใฎๆ–นๆณ•ใฎใ„ใšใ‚Œใ‹ใงใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ +FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๅ ดๅˆใ€ไธ€่ˆฌ็š„ใชใ‚ขใƒ—ใƒญใƒผใƒใฏ**Linuxใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ๅŸบๆœฌ็š„ใซใฏ **Docker**ใ‚’็”จใ„ใฆ่กŒใ‚ใ‚Œใพใ™ใ€‚็”Ÿๆˆใ•ใ‚ŒใŸใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใฏใ€ใ„ใใคใ‹ใฎๆ–นๆณ•ใฎใ„ใšใ‚Œใ‹ใงใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ Linuxใ‚ณใƒณใƒ†ใƒŠใฎไฝฟ็”จใซใฏใ€**ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ**ใ€**ๅๅพฉๅฏ่ƒฝๆ€ง๏ผˆใƒฌใƒ—ใƒชใ‚ซใƒ“ใƒชใƒ†ใ‚ฃ๏ผ‰**ใ€**ใ‚ทใƒณใƒ—ใƒชใ‚ทใƒ†ใ‚ฃ**ใชใฉใ€ใ„ใใคใ‹ใฎๅˆฉ็‚นใŒใ‚ใ‚Šใพใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ -TODO: ใชใœใ‹้ท็งปใงใใชใ„ ใŠๆ€ฅใŽใงใ€ใ™ใงใซใ“ใ‚Œใ‚‰ใฎๆƒ…ๅ ฑใ‚’ใ”ๅญ˜ใ˜ใงใ™ใ‹๏ผŸ [ไปฅไธ‹ใฎ`Dockerfile`ใฎ็ฎ‡ๆ‰€๐Ÿ‘‡](#build-a-docker-image-for-fastapi)ใธใ‚ธใƒฃใƒณใƒ—ใ—ใฆใใ ใ•ใ„ใ€‚ ///
-Dockerfile ใƒ—ใƒฌใƒ“ใƒฅใƒผ ๐Ÿ‘€ +Dockerfile Preview ๐Ÿ‘€ ```Dockerfile FROM python:3.9 @@ -27,15 +24,15 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./app /code/app -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--port", "80"] # If running behind a proxy like Nginx or Traefik add --proxy-headers -# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"] +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ```
-## ใ‚ณใƒณใƒ†ใƒŠใจใฏไฝ•ใ‹ +## ใ‚ณใƒณใƒ†ใƒŠใจใฏไฝ•ใ‹ { #what-is-a-container } ใ‚ณใƒณใƒ†ใƒŠ๏ผˆไธปใซLinuxใ‚ณใƒณใƒ†ใƒŠ๏ผ‰ใฏใ€ๅŒใ˜ใ‚ทใ‚นใƒ†ใƒ ๅ†…ใฎไป–ใฎใ‚ณใƒณใƒ†ใƒŠ๏ผˆไป–ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚„ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ๏ผ‰ใ‹ใ‚‰้š”้›ขใ•ใ‚ŒใŸ็Šถๆ…‹ใ‚’ไฟใกใชใŒใ‚‰ใ€ใ™ในใฆใฎไพๅญ˜้–ขไฟ‚ใ‚„ๅฟ…่ฆใชใƒ•ใ‚กใ‚คใƒซใ‚’ๅซใ‚€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธๅŒ–ใ™ใ‚‹้žๅธธใซ**่ปฝ้‡**ใชๆ–นๆณ•ใงใ™ใ€‚ @@ -45,7 +42,7 @@ Linuxใ‚ณใƒณใƒ†ใƒŠใฏใ€ใƒ›ใ‚นใƒˆ๏ผˆใƒžใ‚ทใƒณใ€ไปฎๆƒณใƒžใ‚ทใƒณใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ต ใ‚ณใƒณใƒ†ใƒŠใฏใพใŸใ€็‹ฌ่‡ชใฎ**ๅˆ†้›ขใ•ใ‚ŒใŸ**ๅฎŸ่กŒใƒ—ใƒญใ‚ปใ‚น๏ผˆ้€šๅธธใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใฎใฟ๏ผ‰ใ‚„ใ€ใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ใ€ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‚’ๆŒใกใพใ™ใ€‚ ใ“ใฎใ“ใจใฏใƒ‡ใƒ—ใƒญใ‚คใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ€้–‹็™บใชใฉใ‚’็ฐก็ด ๅŒ–ใ•ใ›ใพใ™ใ€‚ -## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใจใฏไฝ•ใ‹ +## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใจใฏไฝ•ใ‹ { #what-is-a-container-image } **ใ‚ณใƒณใƒ†ใƒŠ**ใฏใ€**ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใ‹ใ‚‰ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ @@ -53,23 +50,17 @@ Linuxใ‚ณใƒณใƒ†ใƒŠใฏใ€ใƒ›ใ‚นใƒˆ๏ผˆใƒžใ‚ทใƒณใ€ไปฎๆƒณใƒžใ‚ทใƒณใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ต ไฟๅญ˜ใ•ใ‚ŒใŸ้™็š„ใ‚ณใƒณใƒ†ใƒณใƒ„ใงใ‚ใ‚‹ใ€Œ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใ€ใจใฏๅฏพ็…ง็š„ใซใ€ใ€Œ**ใ‚ณใƒณใƒ†ใƒŠ**ใ€ใฏ้€šๅธธใ€ๅฎŸ่กŒไธญใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใคใพใ‚Š**ๅฎŸ่กŒ**ใ•ใ‚Œใฆใ„ใ‚‹ใ‚‚ใฎใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ -**ใ‚ณใƒณใƒ†ใƒŠ**ใŒ่ตทๅ‹•ใ•ใ‚ŒๅฎŸ่กŒใ•ใ‚Œใ‚‹ใจใ๏ผˆ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใ‹ใ‚‰่ตทๅ‹•ใ•ใ‚Œใ‚‹ใจใ๏ผ‰ใ€ใƒ•ใ‚กใ‚คใƒซใ‚„็’ฐๅขƒๅค‰ๆ•ฐใชใฉใŒไฝœๆˆใ•ใ‚ŒใŸใ‚Šๅค‰ๆ›ดใ•ใ‚ŒใŸใ‚Šใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ - -ใ“ใ‚Œใ‚‰ใฎๅค‰ๆ›ดใฏใใฎใ‚ณใƒณใƒ†ใƒŠๅ†…ใซใฎใฟๅญ˜ๅœจใ—ใพใ™ใŒใ€ๅŸบ็›คใจใชใ‚‹ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใซใฏๆฎ‹ใ‚Šใพใ›ใ‚“๏ผˆใƒ‡ใ‚ฃใ‚นใ‚ฏใซไฟๅญ˜ใ•ใ‚Œใพใ›ใ‚“๏ผ‰ใ€‚ +**ใ‚ณใƒณใƒ†ใƒŠ**ใŒ่ตทๅ‹•ใ•ใ‚ŒๅฎŸ่กŒใ•ใ‚Œใ‚‹ใจใ๏ผˆ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใ‹ใ‚‰่ตทๅ‹•ใ•ใ‚Œใ‚‹ใจใ๏ผ‰ใ€ใƒ•ใ‚กใ‚คใƒซใ‚„็’ฐๅขƒๅค‰ๆ•ฐใชใฉใŒไฝœๆˆใ•ใ‚ŒใŸใ‚Šๅค‰ๆ›ดใ•ใ‚ŒใŸใ‚Šใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎๅค‰ๆ›ดใฏใใฎใ‚ณใƒณใƒ†ใƒŠๅ†…ใซใฎใฟๅญ˜ๅœจใ—ใพใ™ใŒใ€ๅŸบ็›คใจใชใ‚‹ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใซใฏๆฎ‹ใ‚Šใพใ›ใ‚“๏ผˆใƒ‡ใ‚ฃใ‚นใ‚ฏใซไฟๅญ˜ใ•ใ‚Œใพใ›ใ‚“๏ผ‰ใ€‚ ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใฏ **ใƒ—ใƒญใ‚ฐใƒฉใƒ ** ใƒ•ใ‚กใ‚คใƒซใ‚„ใใฎๅ†…ๅฎนใ€ไพ‹ใˆใฐ `python` ใจ `main.py` ใƒ•ใ‚กใ‚คใƒซใซๅŒนๆ•ตใ—ใพใ™ใ€‚ -ใใ—ใฆใ€**ใ‚ณใƒณใƒ†ใƒŠ**่‡ชไฝ“ใฏ๏ผˆ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใจใฏๅฏพ็…ง็š„ใซ๏ผ‰ใ‚คใƒกใƒผใ‚ธใ‚’ใ‚‚ใจใซใ—ใŸๅฎŸ้š›ใฎๅฎŸ่กŒไธญใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใงใ‚ใ‚Šใ€**ใƒ—ใƒญใ‚ปใ‚น**ใซๅŒนๆ•ตใ—ใพใ™ใ€‚ +ใใ—ใฆใ€**ใ‚ณใƒณใƒ†ใƒŠ**่‡ชไฝ“ใฏ๏ผˆ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใจใฏๅฏพ็…ง็š„ใซ๏ผ‰ใ‚คใƒกใƒผใ‚ธใ‚’ใ‚‚ใจใซใ—ใŸๅฎŸ้š›ใฎๅฎŸ่กŒไธญใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใงใ‚ใ‚Šใ€**ใƒ—ใƒญใ‚ปใ‚น**ใซๅŒนๆ•ตใ—ใพใ™ใ€‚ๅฎŸ้š›ใ€ใ‚ณใƒณใƒ†ใƒŠใŒๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใฎใฏใ€**ใƒ—ใƒญใ‚ปใ‚นใŒๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹**ใจใใ ใ‘ใงใ™๏ผˆ้€šๅธธใฏๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใงใ™๏ผ‰ใ€‚ ใ‚ณใƒณใƒ†ใƒŠๅ†…ใงๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นใŒใชใ„ๅ ดๅˆใ€ใ‚ณใƒณใƒ†ใƒŠใฏๅœๆญขใ—ใพใ™ใ€‚ -ๅฎŸ้š›ใ€ใ‚ณใƒณใƒ†ใƒŠใŒๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใฎใฏใ€**ใƒ—ใƒญใ‚ปใ‚นใŒๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹**ใจใใ ใ‘ใงใ™๏ผˆ้€šๅธธใฏๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใงใ™๏ผ‰ใ€‚ ใ‚ณใƒณใƒ†ใƒŠๅ†…ใงๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นใŒใชใ„ๅ ดๅˆใ€ใ‚ณใƒณใƒ†ใƒŠใฏๅœๆญขใ—ใพใ™ใ€‚ - -## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ +## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ { #container-images } Dockerใฏใ€**ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใจ**ใ‚ณใƒณใƒ†ใƒŠ**ใ‚’ไฝœๆˆใƒป็ฎก็†ใ™ใ‚‹ใŸใ‚ใฎไธป่ฆใชใƒ„ใƒผใƒซใฎ1ใคใงใ™ใ€‚ -ใใ—ใฆใ€DockerใซใฏDockerใ‚คใƒกใƒผใ‚ธ๏ผˆใ‚ณใƒณใƒ†ใƒŠ๏ผ‰ใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹Docker Hubใจใ„ใ†ใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ - -Docker Hubใฏ ๅคšใใฎใƒ„ใƒผใƒซใ‚„็’ฐๅขƒใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฏพๅฟœใ—ใฆใ„ใ‚‹ไบˆใ‚ไฝœๆˆใ•ใ‚ŒใŸ**ๅ…ฌๅผใฎใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใ‚’ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏใซๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ +ใใ—ใฆใ€ๅคšใใฎใƒ„ใƒผใƒซใ‚„็’ฐๅขƒใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฏพๅฟœใ—ใฆใ„ใ‚‹ไบˆใ‚ไฝœๆˆใ•ใ‚ŒใŸ**ๅ…ฌๅผใฎใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใ‚’ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏใซๆไพ›ใ—ใฆใ„ใ‚‹Docker Hubใจใ„ใ†ใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ ไพ‹ใˆใฐใ€ๅ…ฌๅผใ‚คใƒกใƒผใ‚ธใฎ1ใคใซPython ImageใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -88,7 +79,7 @@ Docker Hubใฏ ๅคšใใฎใƒ„ใƒผใƒซใ‚„็’ฐๅขƒใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผ ใ™ในใฆใฎใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ๏ผˆDockerใ‚„Kubernetesใชใฉ๏ผ‰ใซใฏใ€ใ“ใ†ใ—ใŸใƒใƒƒใƒˆใƒฏใƒผใ‚ญใƒณใ‚ฐๆฉŸ่ƒฝใŒ็ตฑๅˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -## ใ‚ณใƒณใƒ†ใƒŠใจใƒ—ใƒญใ‚ปใ‚น +## ใ‚ณใƒณใƒ†ใƒŠใจใƒ—ใƒญใ‚ปใ‚น { #containers-and-processes } ้€šๅธธใ€**ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธ**ใฏใใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใซ**ใ‚ณใƒณใƒ†ใƒŠ**ใฎ่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใพใŸใฏใ‚ณใƒžใƒณใƒ‰ใจใ€ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใซๆธกใ•ใ‚Œใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅซใฟใพใ™ใ€‚ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใงใฎๆ“ไฝœใจใ‚ˆใไผผใฆใ„ใพใ™ใ€‚ @@ -100,7 +91,7 @@ Docker Hubใฏ ๅคšใใฎใƒ„ใƒผใƒซใ‚„็’ฐๅขƒใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผ ใ—ใ‹ใ—ใ€**ๅฐ‘ใชใใจใ‚‚1ใคใฎๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚น**ใŒใชใ‘ใ‚Œใฐใ€ๅฎŸ่กŒไธญใฎใ‚ณใƒณใƒ†ใƒŠใ‚’ๆŒใคใ“ใจใฏใงใใชใ„ใงใ™ใ€‚ใƒกใ‚คใƒณใƒปใƒ—ใƒญใ‚ปใ‚นใŒๅœๆญขใ™ใ‚Œใฐใ€ใ‚ณใƒณใƒ†ใƒŠใ‚‚ๅœๆญขใ—ใพใ™ใ€‚ -## Build a Docker Image for FastAPI +## FastAPI็”จใฎDockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ { #build-a-docker-image-for-fastapi } ใจใ„ใ†ใ“ใจใงใ€ไฝ•ใ‹ไฝœใ‚Šใพใ—ใ‚‡ใ†๏ผ๐Ÿš€ @@ -112,7 +103,7 @@ FastAPI็”จใฎ**Dockerใ‚คใƒกใƒผใ‚ธ**ใ‚’ใ€**ๅ…ฌๅผPython**ใ‚คใƒกใƒผใ‚ธใซๅŸบใฅ * **Raspberry Pi**ใงๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆ * ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใ‚’ๅฎŸ่กŒใ—ใฆใใ‚Œใ‚‹ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒปใ‚ตใƒผใƒ“ใ‚นใชใฉใ‚’ๅˆฉ็”จใ™ใ‚‹ๅ ดๅˆ -### ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ่ฆไปถ๏ผˆpackage requirements๏ผ‰ +### ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ่ฆไปถ { #package-requirements } ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ**ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ่ฆไปถ**ใฏ้€šๅธธใ€ไฝ•ใ‚‰ใ‹ใฎใƒ•ใ‚กใ‚คใƒซใซ่จ˜่ฟฐใ•ใ‚Œใฆใ„ใ‚‹ใฏใšใงใ™ใ€‚ @@ -125,9 +116,8 @@ FastAPI็”จใฎ**Dockerใ‚คใƒกใƒผใ‚ธ**ใ‚’ใ€**ๅ…ฌๅผPython**ใ‚คใƒกใƒผใ‚ธใซๅŸบใฅ ไพ‹ใˆใฐใ€`requirements.txt` ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™๏ผš ``` -fastapi>=0.68.0,<0.69.0 -pydantic>=1.8.0,<2.0.0 -uvicorn>=0.15.0,<0.16.0 +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 ``` ใใ—ใฆ้€šๅธธใ€ไพ‹ใˆใฐ `pip` ใ‚’ไฝฟใฃใฆใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™๏ผš @@ -137,28 +127,24 @@ uvicorn>=0.15.0,<0.16.0 ```console $ pip install -r requirements.txt ---> 100% -Successfully installed fastapi pydantic uvicorn +Successfully installed fastapi pydantic ```
-/// info +/// info | ๆƒ…ๅ ฑ ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅฎš็พฉใ—ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใŸใ‚ใฎใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใ‚„ใƒ„ใƒผใƒซใฏไป–ใซใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -Poetryใ‚’ไฝฟใฃใŸไพ‹ใฏใ€ๅพŒ่ฟฐใ™ใ‚‹ใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใ”็ดนไป‹ใ—ใพใ™ใ€‚๐Ÿ‘‡ - /// -### **FastAPI**ใ‚ณใƒผใƒ‰ใ‚’ไฝœๆˆใ™ใ‚‹ +### **FastAPI**ใ‚ณใƒผใƒ‰ใ‚’ไฝœๆˆใ™ใ‚‹ { #create-the-fastapi-code } -* `app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ไฝœๆˆใ—ใ€ใใฎไธญใซๅ…ฅใ‚Šใพใ™ -* ็ฉบใฎใƒ•ใ‚กใ‚คใƒซ `__init__.py` ใ‚’ไฝœๆˆใ—ใพใ™ -* `main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใพใ™๏ผš +* `app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ไฝœๆˆใ—ใ€ใใฎไธญใซๅ…ฅใ‚Šใพใ™ใ€‚ +* ็ฉบใฎใƒ•ใ‚กใ‚คใƒซ `__init__.py` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +* ๆฌกใฎๅ†…ๅฎนใง `main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใพใ™๏ผš ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -170,32 +156,32 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -### Dockerfile +### Dockerfile { #dockerfile } ๅŒใ˜ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใƒปใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ`Dockerfile`ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใพใ™๏ผš ```{ .dockerfile .annotate } -# (1) +# (1)! FROM python:3.9 -# (2) +# (2)! WORKDIR /code -# (3) +# (3)! COPY ./requirements.txt /code/requirements.txt -# (4) +# (4)! RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -# (5) +# (5)! COPY ./app /code/app -# (6) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` 1. ๅ…ฌๅผใฎPythonใƒ™ใƒผใ‚นใ‚คใƒกใƒผใ‚ธใ‹ใ‚‰ๅง‹ใ‚ใพใ™ @@ -211,9 +197,10 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏ**้ ป็นใซใฏๅค‰ๆ›ดใ•ใ‚Œใชใ„**ใฎใงใ€Dockerใฏใ“ใฎใ‚นใƒ†ใƒƒใƒ—ใงใฏใใ‚Œใ‚’ๆคœ็Ÿฅใ—**ใ‚ญใƒฃใƒƒใ‚ทใƒฅ**ใ‚’ไฝฟ็”จใ—ใ€ๆฌกใฎใ‚นใƒ†ใƒƒใƒ—ใงใ‚‚ใ‚ญใƒฃใƒƒใ‚ทใƒฅใ‚’ๆœ‰ๅŠนใซใ—ใพใ™ใ€‚ 4. ่ฆไปถใƒ•ใ‚กใ‚คใƒซใซใ‚ใ‚‹ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ + `--no-cache-dir` ใ‚ชใƒ—ใ‚ทใƒงใƒณใฏใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ—ใŸใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใƒญใƒผใ‚ซใƒซใซไฟๅญ˜ใ—ใชใ„ใ‚ˆใ†ใซ `pip` ใซๆŒ‡็คบใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€ๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใŸใ‚ใซ `pip` ใ‚’ๅ†ๅบฆๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใซใฎใฟๆœ‰ๅŠนใงใ™ใŒใ€ใ‚ณใƒณใƒ†ใƒŠใงไฝœๆฅญใ™ใ‚‹ๅ ดๅˆใฏใใ†ใงใฏใชใ„ใงใ™ใ€‚ - /// note + /// note | ๅ‚™่€ƒ `--no-cache-dir`ใฏ`pip`ใซ้–ข้€ฃใ—ใฆใ„ใ‚‹ใ ใ‘ใงใ€Dockerใ‚„ใ‚ณใƒณใƒ†ใƒŠใจใฏไฝ•ใฎ้–ขไฟ‚ใ‚‚ใชใ„ใงใ™ใ€‚ @@ -225,26 +212,56 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] ใ“ใฎใ‚นใƒ†ใƒƒใƒ—ใงใ‚ญใƒฃใƒƒใ‚ทใƒฅใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€้–‹็™บไธญใซใ‚คใƒกใƒผใ‚ธใ‚’ไฝ•ๅบฆใ‚‚ใƒ“ใƒซใƒ‰ใ™ใ‚‹้š›ใซใ€**ๆฏŽๅ›ž**ใ™ในใฆใฎไพๅญ˜้–ขไฟ‚ใ‚’**ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ—ใฆใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹**ไปฃใ‚ใ‚Šใซๅคšใใฎ**ๆ™‚้–“**ใ‚’**็ฏ€็ด„**ใงใใพใ™ใ€‚ -5. ./app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ `/code` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฎไธญใซใ‚ณใƒ”ใƒผใ™ใ‚‹ใ€‚ +5. `./app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ `/code` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฎไธญใซใ‚ณใƒ”ใƒผใ™ใ‚‹ใ€‚ ใ“ใ‚Œใซใฏ**ๆœ€ใ‚‚้ ป็นใซๅค‰ๆ›ดใ•ใ‚Œใ‚‹**ใ™ในใฆใฎใ‚ณใƒผใƒ‰ใŒๅซใพใ‚Œใฆใ„ใ‚‹ใŸใ‚ใ€Dockerใฎ**ใ‚ญใƒฃใƒƒใ‚ทใƒฅ**ใฏ**ใ“ใ‚Œไปฅ้™ใฎใ‚นใƒ†ใƒƒใƒ—**ใซ็ฐกๅ˜ใซไฝฟ็”จใ•ใ‚Œใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ใใฎใŸใ‚ใ€ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใฎใƒ“ใƒซใƒ‰ๆ™‚้–“ใ‚’ๆœ€้ฉๅŒ–ใ™ใ‚‹ใŸใ‚ใซใ€`Dockerfile`ใฎ **ๆœ€ๅพŒ** ใซใ“ใ‚Œใ‚’็ฝฎใใ“ใจใŒ้‡่ฆใงใ™ใ€‚ -6. `uvicorn`ใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใฎ**ใ‚ณใƒžใƒณใƒ‰**ใ‚’่จญๅฎšใ—ใพใ™ +6. ๅ†…้ƒจใงUvicornใ‚’ไฝฟ็”จใ™ใ‚‹ `fastapi run` ใ‚’ไฝฟใ†ใŸใ‚ใฎ**ใ‚ณใƒžใƒณใƒ‰**ใ‚’่จญๅฎšใ—ใพใ™ `CMD` ใฏๆ–‡ๅญ—ๅˆ—ใฎใƒชใ‚นใƒˆใ‚’ๅ–ใ‚Šใ€ใใ‚Œใžใ‚Œใฎๆ–‡ๅญ—ๅˆ—ใฏใ‚นใƒšใƒผใ‚นใงๅŒบๅˆ‡ใ‚‰ใ‚ŒใŸใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใซๅ…ฅๅŠ›ใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใฏ **็พๅœจใฎไฝœๆฅญใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใ‹ใ‚‰ๅฎŸ่กŒใ•ใ‚Œใ€ไธŠ่จ˜ใฎ `WORKDIR /code` ใซใฆ่จญๅฎšใ—ใŸ `/code` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใจๅŒใ˜ใงใ™ใ€‚ - ใใฎใŸใ‚ใƒ—ใƒญใ‚ฐใƒฉใƒ ใฏ `/code` ใง้–‹ๅง‹ใ—ใใฎไธญใซใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใŒใ‚ใ‚‹ `./app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใŒใ‚ใ‚‹ใฎใงใ€**Uvicorn** ใฏ `app.main` ใ‹ใ‚‰ `app` ใ‚’ๅ‚็…งใ—ใ€**ใ‚คใƒณใƒใƒผใƒˆ** ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +/// tip | ่ฑ†็Ÿฅ่ญ˜ -/// tip +ใ‚ณใƒผใƒ‰ๅ†…ใฎๅ„็•ชๅทใƒใƒ–ใƒซใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ€ๅ„่กŒใŒไฝ•ใ‚’ใ™ใ‚‹ใฎใ‹ใ‚’ใƒฌใƒ“ใƒฅใƒผใ—ใฆใใ ใ•ใ„ใ€‚๐Ÿ‘† -ใ‚ณใƒผใƒ‰ๅ†…ใฎ"+"ใฎๅนใๅ‡บใ—ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ€ๅ„่กŒใŒไฝ•ใ‚’ใ™ใ‚‹ใฎใ‹ใ‚’ใƒฌใƒ“ใƒฅใƒผใ—ใฆใใ ใ•ใ„ใ€‚๐Ÿ‘† +/// + +/// warning | ๆณจๆ„ + +ไปฅไธ‹ใง่ชฌๆ˜Žใ™ใ‚‹้€šใ‚Šใ€`CMD` ๅ‘ฝไปคใฏ**ๅธธใซ** **execๅฝขๅผ**ใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ /// +#### `CMD` ใ‚’ไฝฟใ† - Execๅฝขๅผ { #use-cmd-exec-form } + +Dockerๅ‘ฝไปค `CMD` ใฏ2ใคใฎๅฝขๅผใงๆ›ธใ‘ใพใ™๏ผš + +โœ… **Exec** ๅฝขๅผ๏ผš + +```Dockerfile +# โœ… Do this +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ **Shell** ๅฝขๅผ๏ผš + +```Dockerfile +# โ›”๏ธ Don't do this +CMD fastapi run app/main.py --port 80 +``` + +FastAPIใŒๆญฃๅธธใซใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใงใใ€[lifespan events](../advanced/events.md){.internal-link target=_blank}ใŒใƒˆใƒชใ‚ฌใƒผใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ€ๅธธใซ **exec** ๅฝขๅผใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ + +่ฉณใ—ใใฏใ€shellๅฝขๅผใจexecๅฝขๅผใซ้–ขใ™ใ‚‹Dockerใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ + +ใ“ใ‚Œใฏ `docker compose` ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใซใ‹ใชใ‚Š็›ฎ็ซ‹ใคใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใ‚ˆใ‚ŠๆŠ€่ก“็š„ใช่ฉณ็ดฐใฏใ€ใ“ใฎDocker ComposeใฎFAQใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ”่ฆงใใ ใ•ใ„๏ผšWhy do my services take 10 seconds to recreate or stop?ใ€‚ + +#### ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชๆง‹้€  { #directory-structure } + ใ“ใ‚Œใงใ€ๆฌกใฎใ‚ˆใ†ใชใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชๆง‹้€ ใซใชใ‚‹ใฏใšใงใ™๏ผš ``` @@ -256,17 +273,15 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] โ””โ”€โ”€ requirements.txt ``` -#### TLS Termination Proxyใฎ่ฃๅด +#### TLS Termination Proxyใฎ่ฃๅด { #behind-a-tls-termination-proxy } -Nginx ใ‚„ Traefik ใฎใ‚ˆใ†ใช TLS Termination Proxy (ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ต) ใฎๅพŒใ‚ใงใ‚ณใƒณใƒ†ใƒŠใ‚’ๅ‹•ใ‹ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€`--proxy-headers`ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ - -ใ“ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฏใ€Uvicornใซใƒ—ใƒญใ‚ญใ‚ท็ตŒ็”ฑใงHTTPSใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฏพใ—ใฆใ€้€ไฟกใ•ใ‚Œใ‚‹ใƒ˜ใƒƒใƒ€ใ‚’ไฟก้ ผใ™ใ‚‹ใ‚ˆใ†ๆŒ‡็คบใ—ใพใ™ใ€‚ +Nginx ใ‚„ Traefik ใฎใ‚ˆใ†ใช TLS Termination Proxy (ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ต) ใฎๅพŒใ‚ใงใ‚ณใƒณใƒ†ใƒŠใ‚’ๅ‹•ใ‹ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€`--proxy-headers`ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€๏ผˆFastAPI CLI็ตŒ็”ฑใง๏ผ‰Uvicornใซๅฏพใ—ใฆใ€ใใฎใƒ—ใƒญใ‚ญใ‚ทใ‹ใ‚‰้€ไฟกใ•ใ‚Œใ‚‹ใƒ˜ใƒƒใƒ€ใ‚’ไฟก้ ผใ—ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒHTTPSใฎ่ฃใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใชใฉใ‚’็คบใ™ใ‚ˆใ†ๆŒ‡็คบใ—ใพใ™ใ€‚ ```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] ``` -#### Dockerใ‚ญใƒฃใƒƒใ‚ทใƒฅ +#### Dockerใ‚ญใƒฃใƒƒใ‚ทใƒฅ { #docker-cache } ใ“ใฎ`Dockerfile`ใซใฏ้‡่ฆใชใƒˆใƒชใƒƒใ‚ฏใŒใ‚ใ‚Šใ€ใพใš**ไพๅญ˜้–ขไฟ‚ใ ใ‘ใฎใƒ•ใ‚กใ‚คใƒซ**ใ‚’ใ‚ณใƒ”ใƒผใ—ใพใ™ใ€‚ใใฎ็†็”ฑใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ @@ -300,11 +315,11 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./app /code/app ``` -### Dockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ +### Dockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ { #build-the-docker-image } ใ™ในใฆใฎใƒ•ใ‚กใ‚คใƒซใŒๆƒใฃใŸใฎใงใ€ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ—ใพใ—ใ‚‡ใ†ใ€‚ -* ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ็งปๅ‹•ใ—ใพใ™๏ผˆ`Dockerfile`ใŒใ‚ใ‚‹ๅ ดๆ‰€ใงใ€`app`ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใŒใ‚ใ‚Šใพใ™๏ผ‰ +* ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ็งปๅ‹•ใ—ใพใ™๏ผˆ`Dockerfile`ใŒใ‚ใ‚‹ๅ ดๆ‰€ใงใ€`app`ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใŒใ‚ใ‚Šใพใ™๏ผ‰ใ€‚ * FastAPI ใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ—ใพใ™๏ผš
@@ -317,7 +332,7 @@ $ docker build -t myimage .
-/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ๆœซๅฐพใฎ `.` ใซๆณจ็›ฎใ—ใฆใปใ—ใ„ใงใ™ใ€‚ใ“ใ‚Œใฏ `./` ใจๅŒใ˜ๆ„ๅ‘ณใงใ™ใ€‚ ใ“ใ‚ŒใฏDockerใซใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใฎใƒ“ใƒซใƒ‰ใซไฝฟ็”จใ™ใ‚‹ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ๆŒ‡็คบใ—ใพใ™ใ€‚ @@ -325,7 +340,7 @@ $ docker build -t myimage . /// -### Dockerใ‚ณใƒณใƒ†ใƒŠใฎ่ตทๅ‹•ใ™ใ‚‹ +### Dockerใ‚ณใƒณใƒ†ใƒŠใฎ่ตทๅ‹•ใ™ใ‚‹ { #start-the-docker-container } * ใ‚คใƒกใƒผใ‚ธใซๅŸบใฅใ„ใฆใ‚ณใƒณใƒ†ใƒŠใ‚’ๅฎŸ่กŒใ—ใพใ™๏ผš @@ -337,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
-## ็ขบ่ชใ™ใ‚‹ +## ็ขบ่ชใ™ใ‚‹ { #check-it } Dockerใ‚ณใƒณใƒ†ใƒŠใฎhttp://192.168.99.100/items/5?q=somequery ใ‚„ http://127.0.0.1/items/5?q=somequery (ใพใŸใฏใใ‚Œใซ็›ธๅฝ“ใ™ใ‚‹Dockerใƒ›ใ‚นใƒˆใ‚’ไฝฟ็”จใ—ใŸใ‚‚ใฎ๏ผ‰ใจใ„ใฃใŸURLใง็ขบ่ชใงใใ‚‹ใฏใšใงใ™ใ€‚ @@ -347,7 +362,7 @@ Dockerใ‚ณใƒณใƒ†ใƒŠใฎhttp://192.168.99.100/docs ใ‚„ http://127.0.0.1/docs (ใพใŸใฏใใ‚Œใซ็›ธๅฝ“ใ™ใ‚‹Dockerใƒ›ใ‚นใƒˆใ‚’ไฝฟ็”จใ—ใŸใ‚‚ใฎ๏ผ‰ @@ -355,7 +370,7 @@ Dockerใ‚ณใƒณใƒ†ใƒŠใฎhttp://192.168.99.100/redoc ใ‚„ http://127.0.0.1/redoc (ใพใŸใฏใใ‚Œใซ็›ธๅฝ“ใ™ใ‚‹Dockerใƒ›ใ‚นใƒˆใ‚’ไฝฟ็”จใ—ใŸใ‚‚ใฎ๏ผ‰ใซใ‚‚ใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ @@ -363,9 +378,10 @@ Dockerใ‚ณใƒณใƒ†ใƒŠใฎTraefikใฎใ‚ˆใ†ใซใ€**HTTPS**ใจ**่จผๆ˜Žๆ›ธ**ใฎ**่‡ชๅ‹•**ๅ–ๅพ—ใ‚’ๆ‰ฑใ†ๅˆฅใฎใ‚ณใƒณใƒ†ใƒŠใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ TraefikใฏDockerใ‚„Kubernetesใชใฉใจ็ตฑๅˆใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ใ‚ณใƒณใƒ†ใƒŠ็”จใฎHTTPSใฎ่จญๅฎšใ‚„ๆง‹ๆˆใฏใจใฆใ‚‚็ฐกๅ˜ใงใ™ใ€‚ @@ -428,7 +444,7 @@ TraefikใฏDockerใ‚„Kubernetesใชใฉใจ็ตฑๅˆใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ใ‚ณใƒณใƒ†ใƒŠ ใ‚ใ‚‹ใ„ใฏใ€๏ผˆใ‚ณใƒณใƒ†ใƒŠๅ†…ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใชใŒใ‚‰๏ผ‰ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒปใƒ—ใƒญใƒใ‚คใƒ€ใƒผใŒใ‚ตใƒผใƒ“ใ‚นใฎ1ใคใจใ—ใฆHTTPSใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -## ่ตทๅ‹•ๆ™‚ใŠใ‚ˆใณๅ†่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ +## ่ตทๅ‹•ๆ™‚ใŠใ‚ˆใณๅ†่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ { #running-on-startup-and-restarts } ้€šๅธธใ€ใ‚ณใƒณใƒ†ใƒŠใฎ**่ตทๅ‹•ใจๅฎŸ่กŒ**ใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ๅˆฅใฎใƒ„ใƒผใƒซใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -438,21 +454,21 @@ TraefikใฏDockerใ‚„Kubernetesใชใฉใจ็ตฑๅˆใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ใ‚ณใƒณใƒ†ใƒŠ ใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟใ‚ใชใ‘ใ‚Œใฐใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ตทๅ‹•ๆ™‚ใ‚„ๅ†่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒใ•ใ›ใ‚‹ใฎใฏ้ขๅ€’ใง้›ฃใ—ใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€**ใ‚ณใƒณใƒ†ใƒŠ**ใงไฝœๆฅญใ™ใ‚‹ๅ ดๅˆใ€ใปใจใ‚“ใฉใฎใ‚ฑใƒผใ‚นใงใใฎๆฉŸ่ƒฝใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๅซใพใ‚Œใฆใ„ใพใ™ใ€‚โœจ -## ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒ—ใƒญใ‚ปใ‚นๆ•ฐ +## ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒ—ใƒญใ‚ปใ‚นๆ•ฐ { #replication-number-of-processes } -**Kubernetes** ใ‚„ Docker Swarm ใƒขใƒผใƒ‰ใ€Nomadใ€ใ‚ใ‚‹ใ„ใฏ่ค‡ๆ•ฐใฎใƒžใ‚ทใƒณไธŠใงๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใฎๅŒๆง˜ใฎ่ค‡้›‘ใชใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆใƒžใ‚ทใƒณใฎใ‚ฏใƒฉใ‚นใ‚ฟใƒผใ‚’ๆง‹ๆˆใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ ๅ„ใ‚ณใƒณใƒ†ใƒŠใง๏ผˆWorkerใ‚’ๆŒใคGunicornใฎใ‚ˆใ†ใช๏ผ‰**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใ‚’ไฝฟ็”จใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€**ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใƒปใƒฌใƒ™ใƒซ**ใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ—ใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ +**Kubernetes** ใ‚„ Docker Swarm ใƒขใƒผใƒ‰ใ€Nomadใ€ใ‚ใ‚‹ใ„ใฏ่ค‡ๆ•ฐใฎใƒžใ‚ทใƒณไธŠใงๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใฎๅŒๆง˜ใฎ่ค‡้›‘ใชใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆใƒžใ‚ทใƒณใฎclusterใ‚’ๆง‹ๆˆใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ ๅ„ใ‚ณใƒณใƒ†ใƒŠใง๏ผˆWorkerใ‚’ๆŒใคUvicornใฎใ‚ˆใ†ใช๏ผ‰**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใ‚’ไฝฟ็”จใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€**ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใƒปใƒฌใƒ™ใƒซ**ใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ—ใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ Kubernetesใฎใ‚ˆใ†ใชๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ใฎ1ใคใฏ้€šๅธธใ€ๅ…ฅใฃใฆใใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ทใƒณใ‚ฐ**ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใชใŒใ‚‰ใ€**ใ‚ณใƒณใƒ†ใƒŠใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ™ใ‚‹็ตฑๅˆใ•ใ‚ŒใŸๆ–นๆณ•ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ใ“ใฎใ“ใจใฏใ™ในใฆ**ใ‚ฏใƒฉใ‚นใ‚ฟใƒฌใƒ™ใƒซ**ใซใฆใงใ™ใ€‚ -ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€Uvicornใƒฏใƒผใ‚ซใƒผใงGunicornใฎใ‚ˆใ†ใชใ‚‚ใฎใ‚’ๅฎŸ่กŒใ™ใ‚‹ใฎใงใฏใชใใ€[ไธŠ่จ˜ใฎ่ชฌๆ˜Ž](#dockerfile)ใฎใ‚ˆใ†ใซ**Dockerใ‚คใƒกใƒผใ‚ธใ‚’ใ‚ผใƒญใ‹ใ‚‰**ใƒ“ใƒซใƒ‰ใ—ใ€ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€**ๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ—ใŸใ„ใงใ—ใ‚‡ใ†ใ€‚ +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€[ไธŠ่จ˜ใฎ่ชฌๆ˜Ž](#dockerfile)ใฎใ‚ˆใ†ใซ**Dockerใ‚คใƒกใƒผใ‚ธใ‚’ใ‚ผใƒญใ‹ใ‚‰**ใƒ“ใƒซใƒ‰ใ—ใ€ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€**ๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ—ใŸใ„ใงใ—ใ‚‡ใ†ใ€‚่ค‡ๆ•ฐใฎUvicornใƒฏใƒผใ‚ซใƒผใ‚’ไฝฟใ†ไปฃใ‚ใ‚Šใซใงใ™ใ€‚ -### ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ +### ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ { #load-balancer } ใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€้€šๅธธใฏใƒกใ‚คใƒณใƒปใƒใƒผใƒˆ**ใงใƒชใ‚นใƒ‹ใƒณใ‚ฐ**ใ—ใฆใ„ใ‚‹ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใŒใ‚ใ‚‹ใฏใšใงใ™ใ€‚ใใ‚ŒใฏใŠใใ‚‰ใใ€**HTTPS**ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใฎ**TLS Termination Proxy**ใงใ‚‚ใ‚ใ‚‹ๅˆฅใฎใ‚ณใƒณใƒ†ใƒŠใงใ‚ใฃใŸใ‚Šใ€ๅŒๆง˜ใฎใƒ„ใƒผใƒซใงใ‚ใฃใŸใ‚Šใ™ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ ใ“ใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ **่ฒ ่ท** ใ‚’ๅ—ใ‘ใ€ (ใ†ใพใใ„ใ‘ใฐ) ใใฎ่ฒ ่ทใ‚’**ใƒใƒฉใƒณใ‚นใ‚ˆใ** ใƒฏใƒผใ‚ซใƒผใซๅˆ†้…ใ™ใ‚‹ใฎใงใ€ไธ€่ˆฌใซ **ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ต** ใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ HTTPSใซไฝฟใ‚ใ‚Œใ‚‹ใ‚‚ใฎใจๅŒใ˜**TLS Termination Proxy**ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใฏใ€ใŠใใ‚‰ใ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ**ใซใ‚‚ใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ @@ -460,7 +476,7 @@ HTTPSใซไฝฟใ‚ใ‚Œใ‚‹ใ‚‚ใฎใจๅŒใ˜**TLS Termination Proxy**ใ‚ณใƒณใƒใƒผใƒใƒณ ใใ—ใฆใ‚ณใƒณใƒ†ใƒŠใงไฝœๆฅญใ™ใ‚‹ๅ ดๅˆใ€ใ‚ณใƒณใƒ†ใƒŠใฎ่ตทๅ‹•ใจ็ฎก็†ใซไฝฟ็”จใ™ใ‚‹ๅŒใ˜ใ‚ทใ‚นใƒ†ใƒ ใซใฏใ€**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ**๏ผˆ**TLS Termination Proxy**ใฎๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚‹๏ผ‰ใ‹ใ‚‰**ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ้€šไฟก**๏ผˆHTTPใƒชใ‚ฏใ‚จใ‚นใƒˆใชใฉ๏ผ‰ใ‚’ใ‚ขใƒ—ใƒชใฎใ‚ใ‚‹ใ‚ณใƒณใƒ†ใƒŠ๏ผˆ่ค‡ๆ•ฐๅฏ๏ผ‰ใซ้€ไฟกใ™ใ‚‹ใŸใ‚ใฎๅ†…้ƒจใƒ„ใƒผใƒซใŒๆ—ขใซใ‚ใ‚‹ใฏใšใงใ™ใ€‚ -### 1ใคใฎใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ - ่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใ‚ณใƒณใƒ†ใƒŠใƒผ +### 1ใคใฎใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ - ่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใ‚ณใƒณใƒ†ใƒŠใƒผ { #one-load-balancer-multiple-worker-containers } **Kubernetes**ใ‚„ๅŒๆง˜ใฎๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ใงไฝœๆฅญใ™ใ‚‹ๅ ดๅˆใ€ใใฎๅ†…้ƒจใฎใƒใƒƒใƒˆใƒฏใƒผใ‚ญใƒณใ‚ฐใฎใƒกใ‚ซใƒ‹ใ‚บใƒ ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ใƒกใ‚คใƒณใฎ**ใƒใƒผใƒˆ**ใงใƒชใƒƒใ‚นใƒณใ—ใฆใ„ใ‚‹ๅ˜ไธ€ใฎ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ**ใŒใ€ใ‚ขใƒ—ใƒชใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹**่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠ**ใซ้€šไฟก๏ผˆใƒชใ‚ฏใ‚จใ‚นใƒˆ๏ผ‰ใ‚’้€ไฟกใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ @@ -470,56 +486,61 @@ HTTPSใซไฝฟใ‚ใ‚Œใ‚‹ใ‚‚ใฎใจๅŒใ˜**TLS Termination Proxy**ใ‚ณใƒณใƒใƒผใƒใƒณ ใใ—ใฆ้€šๅธธใ€ใ“ใฎ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ**ใฏใ€ใ‚ฏใƒฉใ‚นใ‚ฟๅ†…ใฎ*ไป–ใฎ*ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆไพ‹ใˆใฐใ€็•ฐใชใ‚‹ใƒ‰ใƒกใ‚คใƒณใ‚„็•ฐใชใ‚‹URLใƒ‘ใ‚นใฎใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใฎ้…ไธ‹๏ผ‰ใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ“ใจใŒใงใใ€ใใฎ้€šไฟกใ‚’ใ‚ฏใƒฉใ‚นใ‚ฟๅ†…ใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹*ไป–ใฎ*ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใŸใ‚ใฎ้ฉๅˆ‡ใชใ‚ณใƒณใƒ†ใƒŠใซ้€ไฟกใ—ใพใ™ใ€‚ -### 1ใ‚ณใƒณใƒ†ใƒŠใซใคใ1ใƒ—ใƒญใ‚ปใ‚น +### 1ใ‚ณใƒณใƒ†ใƒŠใซใคใ1ใƒ—ใƒญใ‚ปใ‚น { #one-process-per-container } ใ“ใฎ็จฎใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ใ™ใงใซใ‚ฏใƒฉใ‚นใ‚ฟใƒปใƒฌใƒ™ใƒซใงใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅ‡ฆ็†ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใŠใใ‚‰ใใ‚ณใƒณใƒ†ใƒŠใ”ใจใซ**ๅ˜ไธ€ใฎ๏ผˆUvicorn๏ผ‰ใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๆŒใกใŸใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใ“ใฎๅ ดๅˆใ€Uvicornใƒฏใƒผใ‚ซใƒผใ‚’ๆŒใคGunicornใฎใ‚ˆใ†ใชใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผใ‚„ใ€Uvicornใƒฏใƒผใ‚ซใƒผใ‚’ไฝฟใ†Uvicornใฏ**้ฟใ‘ใŸใ„**ใงใ—ใ‚‡ใ†ใ€‚**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซUvicornใฎใƒ—ใƒญใ‚ปใ‚นใฏ1ใคใ ใ‘**ใซใ—ใŸใ„ใงใ—ใ‚‡ใ†๏ผˆใŠใใ‚‰ใ่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠใŒๅฟ…่ฆใงใ—ใ‚‡ใ†๏ผ‰ใ€‚ +ใ“ใฎๅ ดๅˆใ€ไพ‹ใˆใฐใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `--workers` ใงใ€ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซ่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใ‚’ๆŒใคใ“ใจใฏ**้ฟใ‘ใŸใ„**ใงใ—ใ‚‡ใ†ใ€‚**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซUvicornใฎใƒ—ใƒญใ‚ปใ‚นใฏ1ใคใ ใ‘**ใซใ—ใŸใ„ใงใ—ใ‚‡ใ†๏ผˆใŠใใ‚‰ใ่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠใŒๅฟ…่ฆใงใ—ใ‚‡ใ†๏ผ‰ใ€‚ -๏ผˆGunicornใ‚„UvicornใŒUvicornใƒฏใƒผใ‚ซใƒผใ‚’็ฎก็†ใ™ใ‚‹ใ‚ˆใ†ใซ๏ผ‰ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซๅˆฅใฎใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผใ‚’ๆŒใคใ“ใจใฏใ€ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใ‚ทใ‚นใƒ†ใƒ ใงใ™ใงใซๅฏพๅ‡ฆใ—ใฆใ„ใ‚‹ใงใ‚ใ‚ใ†**ไธ่ฆใช่ค‡้›‘ใ•**ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ +๏ผˆ่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใฎๅ ดๅˆใฎใ‚ˆใ†ใซ๏ผ‰ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซๅˆฅใฎใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผใ‚’ๆŒใคใ“ใจใฏใ€ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใ‚ทใ‚นใƒ†ใƒ ใงใ™ใงใซๅฏพๅ‡ฆใ—ใฆใ„ใ‚‹ใงใ‚ใ‚ใ†**ไธ่ฆใช่ค‡้›‘ใ•**ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ -### Containers with Multiple Processes and Special Cases +### ่ค‡ๆ•ฐใƒ—ใƒญใ‚ปใ‚นใฎใ‚ณใƒณใƒ†ใƒŠใจ็‰นๆฎŠใชใ‚ฑใƒผใ‚น { #containers-with-multiple-processes-and-special-cases } -ใ‚‚ใกใ‚ใ‚“ใ€**็‰นๆฎŠใชใ‚ฑใƒผใ‚น**ใจใ—ใฆใ€**Gunicornใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใ‚’ๆŒใค**ใ‚ณใƒณใƒ†ใƒŠ**ๅ†…ใง่ค‡ๆ•ฐใฎ**Uvicornใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ•ใ›ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ‚‚ใกใ‚ใ‚“ใ€**็‰นๆฎŠใชใ‚ฑใƒผใ‚น**ใจใ—ใฆใ€**ใ‚ณใƒณใƒ†ใƒŠ**ๅ†…ใง่ค‡ๆ•ฐใฎ**Uvicornใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ•ใ›ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใ“ใฎใ‚ˆใ†ใชๅ ดๅˆใ€**ๅ…ฌๅผใฎDockerใ‚คใƒกใƒผใ‚ธ**ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใฎใ‚คใƒกใƒผใ‚ธใซใฏใ€่ค‡ๆ•ฐใฎ**Uvicornใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใจใ—ใฆ**Gunicorn**ใŒๅซใพใ‚ŒใฆใŠใ‚Šใ€็พๅœจใฎCPUใ‚ณใ‚ขใซๅŸบใฅใ„ใฆใƒฏใƒผใ‚ซใƒผใฎๆ•ฐใ‚’่‡ชๅ‹•็š„ใซ่ชฟๆ•ดใ™ใ‚‹ใŸใ‚ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ่จญๅฎšใŒใ„ใใคใ‹ๅซใพใ‚Œใฆใ„ใพใ™ใ€‚่ฉณใ—ใใฏๅพŒ่ฟฐใฎ[Gunicornใซใ‚ˆใ‚‹ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธ - Uvicorn](#gunicorndocker-uvicorn)ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€`--workers` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟใฃใฆใ€ๅฎŸ่กŒใ—ใŸใ„ใƒฏใƒผใ‚ซใƒผๆ•ฐใ‚’่จญๅฎšใงใใพใ™๏ผš -ไปฅไธ‹ใฏใ€ใใ‚ŒใŒ็†ใซใ‹ใชใฃใฆใ„ใ‚‹ๅ ดๅˆใฎไพ‹ใงใ™๏ผš +```{ .dockerfile .annotate } +FROM python:3.9 -#### ใ‚ทใƒณใƒ—ใƒซใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ +WORKDIR /code -ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’**ใ‚ทใƒณใƒ—ใƒซ**ใชๅฝขใงๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใ€ใƒ—ใƒญใ‚ปใ‚นๆ•ฐใฎ็ดฐใ‹ใ„่ชฟๆ•ดใŒๅฟ…่ฆใชใ„ๅ ดๅˆใ€่‡ชๅ‹•ๅŒ–ใ•ใ‚ŒใŸใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ‚’ไฝฟ็”จใ™ใ‚‹ใ ใ‘ใงใ€ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใŒๅฟ…่ฆใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ไพ‹ใˆใฐใ€ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธใงใ‚ทใƒณใƒ—ใƒซใช่จญๅฎšใŒๅฏ่ƒฝใงใ™ใ€‚ +COPY ./requirements.txt /code/requirements.txt -#### Docker Compose +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -Docker Composeใง**ใ‚ทใƒณใ‚ฐใƒซใ‚ตใƒผใƒ**๏ผˆใ‚ฏใƒฉใ‚นใ‚ฟใงใฏใชใ„๏ผ‰ใซใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใฎใงใ€ๅ…ฑๆœ‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใจ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ทใƒณใ‚ฐ**ใ‚’็ถญๆŒใ—ใชใŒใ‚‰๏ผˆDocker Composeใง๏ผ‰ใ‚ณใƒณใƒ†ใƒŠใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’็ฎก็†ใ™ใ‚‹็ฐกๅ˜ใชๆ–นๆณ•ใฏใชใ„ใงใ—ใ‚‡ใ†ใ€‚ +COPY ./app /code/app -ใใฎๅ ดๅˆใ€**ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠ**ใงใ€**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใŒๅ†…้ƒจใง**่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` -#### Prometheusใจใใฎไป–ใฎ็†็”ฑ +1. ใ“ใ“ใงใฏ `--workers` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟใฃใฆใ€ใƒฏใƒผใ‚ซใƒผๆ•ฐใ‚’4ใซ่จญๅฎšใ—ใฆใ„ใพใ™ใ€‚ -ใพใŸใ€**1ใคใฎใ‚ณใƒณใƒ†ใƒŠ**ใซ**1ใคใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๆŒใŸใ›ใ‚‹ใฎใงใฏใชใใ€**1ใคใฎใ‚ณใƒณใƒ†ใƒŠ**ใซ**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๆŒใŸใ›ใ‚‹ๆ–นใŒ็ฐกๅ˜ใ ใจใ„ใ†**ไป–ใฎ็†็”ฑ**ใ‚‚ใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ไปฅไธ‹ใฏใ€ใใ‚ŒใŒ็†ใซใ‹ใชใฃใฆใ„ใ‚‹ๅ ดๅˆใฎไพ‹ใงใ™๏ผš -ไพ‹ใˆใฐใ€(ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใซใ‚‚ใ‚ˆใ‚Šใพใ™ใŒ)Prometheusใ‚จใ‚ฏใ‚นใƒใƒผใ‚ฟใƒผใฎใ‚ˆใ†ใชใƒ„ใƒผใƒซใ‚’ๅŒใ˜ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ +#### ใ‚ทใƒณใƒ—ใƒซใชใ‚ขใƒ—ใƒช { #a-simple-app } -ใ“ใฎๅ ดๅˆใ€**่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠ**ใŒใ‚ใ‚‹ใจใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€PrometheusใŒ**ใƒกใƒˆใƒชใ‚ฏใ‚นใ‚’**่ชญใฟใซๆฅใŸใจใใ€ใ™ในใฆใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใƒˆใ•ใ‚ŒใŸใ‚ณใƒณใƒ†ใƒŠใฎ**่“„็ฉใ•ใ‚ŒใŸใƒกใƒˆใƒชใ‚ฏใ‚น**ใ‚’ๅ–ๅพ—ใ™ใ‚‹ใฎใงใฏใชใใ€ๆฏŽๅ›ž**ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠ**๏ผˆใใฎ็‰นๅฎšใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ—ใŸใ‚ณใƒณใƒ†ใƒŠ๏ผ‰ใฎใ‚‚ใฎใ‚’ๅ–ๅพ—ใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ€ใ‚ฏใƒฉใ‚นใ‚ฟใงใฏใชใ**ๅ˜ไธ€ใ‚ตใƒผใƒ**ใงๅฎŸ่กŒใงใใ‚‹ใปใฉ**ใ‚ทใƒณใƒ—ใƒซ**ใงใ‚ใ‚‹ๅ ดๅˆใ€ใ‚ณใƒณใƒ†ใƒŠๅ†…ใซใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใŒๆฌฒใ—ใใชใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใฎๅ ดๅˆใ€**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๆŒใค**1ใคใฎใ‚ณใƒณใƒ†ใƒŠ**ใ‚’็”จๆ„ใ—ใ€ๅŒใ˜ใ‚ณใƒณใƒ†ใƒŠไธŠใฎใƒญใƒผใ‚ซใƒซใƒ„ใƒผใƒซ๏ผˆไพ‹ใˆใฐPrometheusใ‚จใ‚ฏใ‚นใƒใƒผใ‚ฟใƒผ๏ผ‰ใŒใ™ในใฆใฎๅ†…้ƒจใƒ—ใƒญใ‚ปใ‚นใฎPrometheusใƒกใƒˆใƒชใ‚ฏใ‚นใ‚’ๅŽ้›†ใ—ใ€ใใฎ1ใคใฎใ‚ณใƒณใƒ†ใƒŠไธŠใงใใ‚Œใ‚‰ใฎใƒกใƒˆใƒชใ‚ฏใ‚นใ‚’ๅ…ฌ้–‹ใ™ใ‚‹ๆ–นใŒใ‚ทใƒณใƒ—ใƒซใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +#### Docker Compose { #docker-compose } ---- +Docker Composeใง**ๅ˜ไธ€ใ‚ตใƒผใƒ**๏ผˆใ‚ฏใƒฉใ‚นใ‚ฟใงใฏใชใ„๏ผ‰ใซใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใฎใงใ€ๅ…ฑๆœ‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใจ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ทใƒณใ‚ฐ**ใ‚’็ถญๆŒใ—ใชใŒใ‚‰๏ผˆDocker Composeใง๏ผ‰ใ‚ณใƒณใƒ†ใƒŠใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’็ฎก็†ใ™ใ‚‹็ฐกๅ˜ใชๆ–นๆณ•ใฏใชใ„ใงใ—ใ‚‡ใ†ใ€‚ -้‡่ฆใชใฎใฏใ€็›ฒ็›ฎ็š„ใซๅพ“ใ‚ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ๆ™ฎ้ใฎใƒซใƒผใƒซใฏใชใ„ใจใ„ใ†ใ“ใจใงใ™ใ€‚ +ใใฎๅ ดๅˆใ€**ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠ**ใงใ€**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใŒๅ†…้ƒจใง**่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฏใ€**ใ‚ใชใŸ่‡ช่บซใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น**ใ‚’่ฉ•ไพกใ—ใ€ใ‚ใชใŸใฎใ‚ทใ‚นใƒ†ใƒ ใซๆœ€้ฉใชใ‚ขใƒ—ใƒญใƒผใƒใ‚’ๆฑบๅฎšใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผš +--- + +้‡่ฆใชใฎใฏใ€ใ“ใ‚Œใ‚‰ใฎใฉใ‚Œใ‚‚ใ€็›ฒ็›ฎ็š„ใซๅพ“ใ‚ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ€Œ**็ตถๅฏพ็š„ใชใƒซใƒผใƒซ**ใ€ใงใฏใชใ„ใจใ„ใ†ใ“ใจใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฏใ€**ใ‚ใชใŸ่‡ช่บซใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น**ใ‚’่ฉ•ไพกใ—ใ€ใ‚ใชใŸใฎใ‚ทใ‚นใƒ†ใƒ ใซๆœ€้ฉใชใ‚ขใƒ—ใƒญใƒผใƒใ‚’ๆฑบๅฎšใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใงใใพใ™ใ€‚ๆฌกใฎๆฆ‚ๅฟตใ‚’ใฉใ†็ฎก็†ใ™ใ‚‹ใ‹ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„๏ผš * ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS * ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ * ๅ†่ตทๅ‹• -* **ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰** +* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ * ใƒกใƒขใƒช * ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ— -## ใƒกใƒขใƒชใƒผ +## ใƒกใƒขใƒช { #memory } ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซ**ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ๅฎŸ่กŒใ™ใ‚‹**ใจใ€ใใ‚Œใ‚‰ใฎใ‚ณใƒณใƒ†ใƒŠ๏ผˆใƒฌใƒ—ใƒชใ‚ฑใƒผใƒˆใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใฏ1ใคไปฅไธŠ๏ผ‰ใซใ‚ˆใฃใฆๆถˆ่ฒปใ•ใ‚Œใ‚‹ๅคšใ‹ใ‚Œๅฐ‘ใชใ‹ใ‚Œๆ˜Ž็ขบใซๅฎš็พฉใ•ใ‚ŒใŸใ€ๅฎ‰ๅฎšใ—ๅˆถ้™ใ•ใ‚ŒใŸ้‡ใฎใƒกใƒขใƒชใ‚’ๆŒใคใ“ใจใซใชใ‚Šใพใ™ใ€‚ @@ -531,109 +552,47 @@ Docker Composeใง**ใ‚ทใƒณใ‚ฐใƒซใ‚ตใƒผใƒ**๏ผˆใ‚ฏใƒฉใ‚นใ‚ฟใงใฏใชใ„๏ผ‰ใซใƒ‡ ใ—ใ‹ใ—ใ€**ๅคšใใฎใƒกใƒขใƒชใ‚’ไฝฟ็”จ**ใ—ใฆใ„ใ‚‹ๅ ดๅˆ๏ผˆใŸใจใˆใฐ**ๆฉŸๆขฐๅญฆ็ฟ’**ใƒขใƒ‡ใƒซใชใฉ๏ผ‰ใ€ใฉใ‚Œใ ใ‘ใฎใƒกใƒขใƒชใ‚’ๆถˆ่ฒปใ—ใฆใ„ใ‚‹ใ‹ใ‚’็ขบ่ชใ—ใ€**ๅ„ใƒžใ‚ทใƒณใงๅฎŸ่กŒใ™ใ‚‹ใ‚ณใƒณใƒ†ใƒŠใฎๆ•ฐ**ใ‚’่ชฟๆ•ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™๏ผˆใใ—ใฆใŠใใ‚‰ใใ‚ฏใƒฉใ‚นใ‚ฟใซใƒžใ‚ทใƒณใ‚’่ฟฝๅŠ ใ—ใพใ™๏ผ‰ใ€‚ -**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซ่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆ๏ผˆใŸใจใˆใฐๅ…ฌๅผใฎDockerใ‚คใƒกใƒผใ‚ธใง๏ผ‰ใ€่ตทๅ‹•ใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚นใฎๆ•ฐใŒ**ๅˆฉ็”จๅฏ่ƒฝใชใƒกใƒขใƒชไปฅไธŠใซๆถˆ่ฒปใ—ใชใ„**ใ‚ˆใ†ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซ่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใ€่ตทๅ‹•ใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚นใฎๆ•ฐใŒ**ๅˆฉ็”จๅฏ่ƒฝใชใƒกใƒขใƒชไปฅไธŠใซๆถˆ่ฒปใ—ใชใ„**ใ‚ˆใ†ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -## ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—ใจใ‚ณใƒณใƒ†ใƒŠ +## ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—ใจใ‚ณใƒณใƒ†ใƒŠ { #previous-steps-before-starting-and-containers } ใ‚ณใƒณใƒ†ใƒŠ๏ผˆDockerใ‚„Kubernetesใชใฉ๏ผ‰ใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใ€ไธปใซ2ใคใฎใ‚ขใƒ—ใƒญใƒผใƒใŒใ‚ใ‚Šใพใ™ใ€‚ -### ่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠ +### ่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠ { #multiple-containers } -่ค‡ๆ•ฐใฎ**ใ‚ณใƒณใƒ†ใƒŠ**ใŒใ‚ใ‚Šใ€ใŠใใ‚‰ใใใ‚Œใžใ‚ŒใŒ**ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ๅ ดๅˆ๏ผˆ**Kubernetes**ใ‚ฏใƒฉใ‚นใ‚ฟใชใฉ๏ผ‰ใ€ใƒฌใƒ—ใƒชใ‚ฑใƒผใƒˆใ•ใ‚ŒใŸใƒฏใƒผใ‚ซใƒผใ‚ณใƒณใƒ†ใƒŠใ‚’ๅฎŸ่กŒใ™ใ‚‹**ๅ‰ใซ**ใ€ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠใง**ไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—**ใฎไฝœๆฅญใ‚’่กŒใ†**ๅˆฅใฎใ‚ณใƒณใƒ†ใƒŠ**ใ‚’ๆŒใกใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ +่ค‡ๆ•ฐใฎ**ใ‚ณใƒณใƒ†ใƒŠ**ใŒใ‚ใ‚Šใ€ใŠใใ‚‰ใใใ‚Œใžใ‚ŒใŒ**ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ๅ ดๅˆ๏ผˆไพ‹ใˆใฐใ€**Kubernetes**ใ‚ฏใƒฉใ‚นใ‚ฟใชใฉ๏ผ‰ใ€ใƒฌใƒ—ใƒชใ‚ฑใƒผใƒˆใ•ใ‚ŒใŸใƒฏใƒผใ‚ซใƒผใ‚ณใƒณใƒ†ใƒŠใ‚’ๅฎŸ่กŒใ™ใ‚‹**ๅ‰ใซ**ใ€ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠใง**ไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—**ใฎไฝœๆฅญใ‚’่กŒใ†**ๅˆฅใฎใ‚ณใƒณใƒ†ใƒŠ**ใ‚’ๆŒใกใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ -/// info +/// info | ๆƒ…ๅ ฑ -ใ‚‚ใ—Kubernetesใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆ, ใ“ใ‚ŒใฏใŠใใ‚‰ใInit ใ‚ณใƒณใƒ†ใƒŠใงใ—ใ‚‡ใ†ใ€‚ +ใ‚‚ใ—Kubernetesใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆ, ใ“ใ‚ŒใฏใŠใใ‚‰ใInit Containerใงใ—ใ‚‡ใ†ใ€‚ /// -ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’**ไธฆๅˆ—ใง่ค‡ๆ•ฐๅ›ž**ๅฎŸ่กŒใ™ใ‚‹ใฎใซๅ•้กŒใŒใชใ„ๅ ดๅˆ๏ผˆไพ‹๏ผšใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎๆบ–ๅ‚™ใƒใ‚งใƒƒใ‚ฏ๏ผ‰ใ€ใƒกใ‚คใƒณใƒ—ใƒญใ‚ปใ‚นใ‚’้–‹ๅง‹ใ™ใ‚‹ๅ‰ใซใ€ใใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅ„ใ‚ณใƒณใƒ†ใƒŠใซๅ…ฅใ‚Œใ‚‹ใ“ใจใŒๅฏ่ƒฝใงใ™ใ€‚ - -### ๅ˜ไธ€ใ‚ณใƒณใƒ†ใƒŠ - -ๅ˜็ด”ใชใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใงใ€**ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠ**ใง่ค‡ๆ•ฐใฎ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**๏ผˆใพใŸใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใฎใฟ๏ผ‰ใ‚’่ตทๅ‹•ใ™ใ‚‹ๅ ดๅˆใ€ใ‚ขใƒ—ใƒชใงใƒ—ใƒญใ‚ปใ‚นใ‚’้–‹ๅง‹ใ™ใ‚‹็›ดๅ‰ใซใ€ๅŒใ˜ใ‚ณใƒณใƒ†ใƒŠใงไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅฎŸ่กŒใงใใพใ™ใ€‚ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธใฏใ€ๅ†…้ƒจ็š„ใซใ“ใ‚Œใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ +ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’**ไธฆๅˆ—ใง่ค‡ๆ•ฐๅ›ž**ๅฎŸ่กŒใ™ใ‚‹ใฎใซๅ•้กŒใŒใชใ„ๅ ดๅˆ๏ผˆไพ‹๏ผšใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ™ใ‚‹ใฎใงใฏใชใใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎๆบ–ๅ‚™ใŒใงใใŸใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ™ใ‚‹ใ ใ‘ใฎๅ ดๅˆ๏ผ‰ใ€ใƒกใ‚คใƒณใƒ—ใƒญใ‚ปใ‚นใ‚’้–‹ๅง‹ใ™ใ‚‹็›ดๅ‰ใซใ€ใใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅ„ใ‚ณใƒณใƒ†ใƒŠใซๅ…ฅใ‚Œใ‚‹ใ“ใจใ‚‚ๅฏ่ƒฝใงใ™ใ€‚ -## Gunicornใซใ‚ˆใ‚‹ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธ - Uvicorn +### ๅ˜ไธ€ใ‚ณใƒณใƒ†ใƒŠ { #single-container } -ๅ‰ใฎ็ซ ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใŸใ‚ˆใ†ใซใ€Uvicornใƒฏใƒผใ‚ซใƒผใงๅ‹•ไฝœใ™ใ‚‹Gunicornใ‚’ๅซใ‚€ๅ…ฌๅผใฎDockerใ‚คใƒกใƒผใ‚ธใŒใ‚ใ‚Šใพใ™๏ผš [Server Workers - Gunicorn ใจ Uvicorn](server-workers.md){.internal-link target=_blank}ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใฆใ„ใพใ™ใ€‚ +ๅ˜็ด”ใชใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใงใ€**ๅ˜ไธ€ใฎใ‚ณใƒณใƒ†ใƒŠ**ใง่ค‡ๆ•ฐใฎ**ใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**๏ผˆใพใŸใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใฎใฟ๏ผ‰ใ‚’่ตทๅ‹•ใ™ใ‚‹ๅ ดๅˆใ€ใ‚ขใƒ—ใƒชใงใƒ—ใƒญใ‚ปใ‚นใ‚’้–‹ๅง‹ใ™ใ‚‹็›ดๅ‰ใซใ€ๅŒใ˜ใ‚ณใƒณใƒ†ใƒŠใงไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๅฎŸ่กŒใงใใพใ™ใ€‚ -ใ“ใฎใ‚คใƒกใƒผใ‚ธใฏใ€ไธปใซไธŠ่จ˜ใง่ชฌๆ˜Žใ—ใŸ็Šถๆณใงๅฝนใซ็ซ‹ใคใงใ—ใ‚‡ใ†๏ผš [่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใจ็‰นๆฎŠใชใ‚ฑใƒผใ‚นใ‚’ๆŒใคใ‚ณใƒณใƒ†ใƒŠ๏ผˆContainers with Multiple Processes and Special Cases๏ผ‰](#containers-with-multiple-processes-and-special-cases) +### ใƒ™ใƒผใ‚นDockerใ‚คใƒกใƒผใ‚ธ { #base-docker-image } -* tiangolo/uvicorn-gunicorn-fastapi. +ไปฅๅ‰ใฏใ€ๅ…ฌๅผใฎFastAPI Dockerใ‚คใƒกใƒผใ‚ธใŒใ‚ใ‚Šใพใ—ใŸ๏ผštiangolo/uvicorn-gunicorn-fastapiใ€‚ใ—ใ‹ใ—ใ€็พๅœจใฏ้žๆŽจๅฅจใงใ™ใ€‚โ›”๏ธ -/// warning +ใŠใใ‚‰ใใ€ใ“ใฎใƒ™ใƒผใ‚นDockerใ‚คใƒกใƒผใ‚ธ๏ผˆใพใŸใฏใใฎไป–ใฎ้กžไผผใฎใ‚‚ใฎ๏ผ‰ใฏ**ไฝฟ็”จใ—ใชใ„**ๆ–นใŒใ‚ˆใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใ“ใฎใƒ™ใƒผใ‚นใ‚คใƒกใƒผใ‚ธใ‚„้กžไผผใฎใ‚คใƒกใƒผใ‚ธใฏ**ๅฟ…่ฆใชใ„**ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใฎใงใ€[ไธŠ่จ˜ใฎ: FastAPI็”จใฎDockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹๏ผˆBuild a Docker Image for FastAPI๏ผ‰](#build-a-docker-image-for-fastapi)ใฎใ‚ˆใ†ใซใ‚ผใƒญใ‹ใ‚‰ใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹ๆ–นใŒ่‰ฏใ„ใงใ—ใ‚‡ใ†ใ€‚ +ใ™ใงใซ**Kubernetes**๏ผˆใพใŸใฏไป–ใฎใ‚‚ใฎ๏ผ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใฆใ€่ค‡ๆ•ฐใฎ**ใ‚ณใƒณใƒ†ใƒŠ**ใงใ€ใ‚ฏใƒฉใ‚นใ‚ฟใƒฌใƒ™ใƒซใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’่จญๅฎšใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€‚ใใฎใ‚ˆใ†ใชๅ ดๅˆใฏใ€ไธŠ่จ˜ใง่ชฌๆ˜Žใ—ใŸใ‚ˆใ†ใซ**ใ‚ผใƒญใ‹ใ‚‰**ใ‚คใƒกใƒผใ‚ธใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๆ–นใŒใ‚ˆใ„ใงใ—ใ‚‡ใ†๏ผš[FastAPI็”จใฎDockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹](#build-a-docker-image-for-fastapi)ใ€‚ -/// - -ใ“ใฎใ‚คใƒกใƒผใ‚ธใซใฏใ€ๅˆฉ็”จๅฏ่ƒฝใชCPUใ‚ณใ‚ขใซๅŸบใฅใ„ใฆ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใฎๆ•ฐ**ใ‚’่จญๅฎšใ™ใ‚‹**ใ‚ชใƒผใƒˆใƒใƒฅใƒผใƒ‹ใƒณใ‚ฐ**ใƒกใ‚ซใƒ‹ใ‚บใƒ ใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ +ใพใŸใ€่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใŒๅฟ…่ฆใชๅ ดๅˆใฏใ€ๅ˜็ด”ใซ `--workers` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -ใ“ใ‚Œใฏ**่ณขๆ˜Žใชใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ**ใ‚’ๅ‚™ใˆใฆใ„ใพใ™ใŒใ€**็’ฐๅขƒๅค‰ๆ•ฐ**ใ‚„่จญๅฎšใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟใฃใฆใ™ในใฆใฎ่จญๅฎšใ‚’ๅค‰ๆ›ดใ—ใŸใ‚Šๆ›ดๆ–ฐใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +/// note | ๆŠ€่ก“่ฉณ็ดฐ -ใพใŸใ€ใ‚นใ‚ฏใƒชใƒ—ใƒˆใง**้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใ‚‚ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใ‚‹ใ€‚ +ใ“ใฎDockerใ‚คใƒกใƒผใ‚ธใฏใ€UvicornใŒๅœๆญขใ—ใŸใƒฏใƒผใ‚ซใƒผใฎ็ฎก็†ใจๅ†่ตทๅ‹•ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ‹ใฃใŸ้ ƒใซไฝœๆˆใ•ใ‚ŒใŸใŸใ‚ใ€Uvicornใจไธ€็ท’ใซGunicornใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ—ใŸใ€‚ใ“ใ‚Œใฏใ€GunicornใซUvicornใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚นใฎ็ฎก็†ใจๅ†่ตทๅ‹•ใ‚’ใ•ใ›ใ‚‹ใ ใ‘ใฎใŸใ‚ใซใ€ใ‹ใชใ‚Šใฎ่ค‡้›‘ใ•ใ‚’่ฟฝๅŠ ใ—ใฆใ„ใพใ—ใŸใ€‚ -/// tip - -ใ™ในใฆใฎ่จญๅฎšใจใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฆ‹ใ‚‹ใซใฏใ€Dockerใ‚คใƒกใƒผใ‚ธใฎใƒšใƒผใ‚ธใ‚’ใ”่ฆงใใ ใ•ใ„: tiangolo/uvicorn-gunicorn-fastapi +ใ—ใ‹ใ—็พๅœจใฏใ€Uvicorn๏ผˆใŠใ‚ˆใณ `fastapi` ใ‚ณใƒžใƒณใƒ‰๏ผ‰ใŒ `--workers` ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใ‚‹ใŸใ‚ใ€่‡ชๅˆ†ใงใƒ“ใƒซใƒ‰ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใƒ™ใƒผใ‚นDockerใ‚คใƒกใƒผใ‚ธใ‚’ไฝฟใ†็†็”ฑใฏใ‚ใ‚Šใพใ›ใ‚“๏ผˆใ‚ณใƒผใƒ‰้‡ใ‚‚ใ ใ„ใŸใ„ๅŒใ˜ใงใ™ ๐Ÿ˜…๏ผ‰ใ€‚ /// -### ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ - -ใ“ใฎใ‚คใƒกใƒผใ‚ธใฎ**ใƒ—ใƒญใ‚ปใ‚นๆ•ฐ**ใฏใ€ๅˆฉ็”จๅฏ่ƒฝใชCPU**ใ‚ณใ‚ข**ใ‹ใ‚‰**่‡ชๅ‹•็š„ใซ่จˆ็ฎ—**ใ•ใ‚Œใพใ™ใ€‚ - -ใคใพใ‚Šใ€CPUใ‹ใ‚‰ๅฏ่ƒฝใช้™ใ‚Š**ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น**ใ‚’**ๅผ•ใๅ‡บใใ†**ใจใ—ใพใ™ใ€‚ - -ใพใŸใ€**็’ฐๅขƒๅค‰ๆ•ฐ**ใชใฉใ‚’ไฝฟใฃใŸ่จญๅฎšใง่ชฟๆ•ดใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ - -ใ—ใ‹ใ—ใ€ใƒ—ใƒญใ‚ปใ‚นใฎๆ•ฐใฏใ‚ณใƒณใƒ†ใƒŠใŒๅฎŸ่กŒใ—ใฆใ„ใ‚‹CPUใซไพๅญ˜ใ™ใ‚‹ใŸใ‚ใ€**ๆถˆ่ฒปใ•ใ‚Œใ‚‹ใƒกใƒขใƒชใฎ้‡**ใ‚‚ใใ‚Œใซไพๅญ˜ใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ - -ใใฎใŸใ‚ใ€๏ผˆๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใชใฉใง๏ผ‰ๅคง้‡ใฎใƒกใƒขใƒชใ‚’ๆถˆ่ฒปใ™ใ‚‹ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ€ใ‚ตใƒผใƒใƒผใฎCPUใ‚ณใ‚ขใŒๅคšใ„ใŒ**ใƒกใƒขใƒชใŒๅฐ‘ใชใ„**ๅ ดๅˆใ€ใ‚ณใƒณใƒ†ใƒŠใฏๅˆฉ็”จๅฏ่ƒฝใชใƒกใƒขใƒชใ‚ˆใ‚Šใ‚‚ๅคšใใฎใƒกใƒขใƒชใ‚’ไฝฟใŠใ†ใจใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ - -ใใฎ็ตๆžœใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใŒๅคงๅน…ใซไฝŽไธ‹ใ™ใ‚‹๏ผˆใ‚ใ‚‹ใ„ใฏใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ™ใ‚‹๏ผ‰ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚๐Ÿšจ - -### Dockerfileใ‚’ไฝœๆˆใ™ใ‚‹ - -ใ“ใฎ็”ปๅƒใซๅŸบใฅใ„ใฆ`Dockerfile`ใ‚’ไฝœๆˆใ™ใ‚‹ๆ–นๆณ•ใ‚’ไปฅไธ‹ใซ็คบใ—ใพใ™๏ผš - -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt - -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app -``` - -### ใ‚ˆใ‚Šๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - -[่ค‡ๆ•ฐใฎใƒ•ใ‚กใ‚คใƒซใ‚’ๆŒใคๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ](../tutorial/bigger-applications.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ™ใ‚‹ใ‚ปใ‚ฏใ‚ทใƒงใƒณใซๅพ“ใฃใŸๅ ดๅˆใ€`Dockerfile`ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™๏ผš - -```Dockerfile hl_lines="7" -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt - -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app/app -``` - -### ใ„ใคไฝฟใ†ใฎใ‹ - -ใŠใใ‚‰ใใ€**Kubernetes**๏ผˆใพใŸใฏไป–ใฎใ‚‚ใฎ๏ผ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใฆใ€ใ™ใงใซใ‚ฏใƒฉใ‚นใ‚ฟใƒฌใƒ™ใƒซใง่ค‡ๆ•ฐใฎ**ใ‚ณใƒณใƒ†ใƒŠ**ใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’่จญๅฎšใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใ“ใฎๅ…ฌๅผใƒ™ใƒผใ‚นใ‚คใƒกใƒผใ‚ธ๏ผˆใพใŸใฏไป–ใฎ้กžไผผใฎใ‚‚ใฎ๏ผ‰ใฏ**ไฝฟ็”จใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ - -ใใฎใ‚ˆใ†ใชๅ ดๅˆใฏใ€ไธŠ่จ˜ใฎใ‚ˆใ†ใซ**ใ‚ผใƒญใ‹ใ‚‰**ใ‚คใƒกใƒผใ‚ธใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๆ–นใŒใ‚ˆใ„ใงใ—ใ‚‡ใ†๏ผš [FastAPI็”จใฎDockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ™ใ‚‹๏ผˆBuild a Docker Image for FastAPI๏ผ‰](#build-a-docker-image-for-fastapi) ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ - -ใ“ใฎใ‚คใƒกใƒผใ‚ธใฏใ€ไธปใซไธŠ่จ˜ใฎ[่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใจ็‰นๆฎŠใชใ‚ฑใƒผใ‚นใ‚’ๆŒใคใ‚ณใƒณใƒ†ใƒŠ๏ผˆContainers with Multiple Processes and Special Cases๏ผ‰](#containers-with-multiple-processes-and-special-cases)ใง่ชฌๆ˜Žใ—ใŸใ‚ˆใ†ใช็‰นๆฎŠใชใ‚ฑใƒผใ‚นใงๅฝนใซ็ซ‹ใกใพใ™ใ€‚ - -ไพ‹ใˆใฐใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ**ใ‚ทใƒณใƒ—ใƒซ**ใงใ€CPUใซๅฟœใ˜ใŸใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐใ‚’่จญๅฎšใ™ใ‚Œใฐใ†ใพใใ„ใๅ ดๅˆใ‚„ใ€ใ‚ฏใƒฉใ‚นใ‚ฟใƒฌใƒ™ใƒซใงใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆ‰‹ๅ‹•ใง่จญๅฎšใ™ใ‚‹ๆ‰‹้–“ใ‚’็œใใŸใ„ๅ ดๅˆใ€ใ‚ขใƒ—ใƒชใง่ค‡ๆ•ฐใฎใ‚ณใƒณใƒ†ใƒŠใ‚’ๅฎŸ่กŒใ—ใชใ„ๅ ดๅˆใชใฉใงใ™ใ€‚ - -ใพใŸใฏใ€**Docker Compose**ใงใƒ‡ใƒ—ใƒญใ‚คใ—ใ€ๅ˜ไธ€ใฎใ‚ตใƒผใƒใงๅฎŸ่กŒใ—ใฆใ„ใ‚‹ๅ ดๅˆใชใฉใงใ™ใ€‚ - -## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใฎใƒ‡ใƒ—ใƒญใ‚ค +## ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใฎใƒ‡ใƒ—ใƒญใ‚ค { #deploy-the-container-image } ใ‚ณใƒณใƒ†ใƒŠ๏ผˆDocker๏ผ‰ใ‚คใƒกใƒผใ‚ธใ‚’ๆ‰‹ใซๅ…ฅใ‚ŒใŸๅพŒใ€ใใ‚Œใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใซใฏใ„ใใคใ‹ใฎๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -645,104 +604,21 @@ COPY ./app /app/app * Nomadใฎใ‚ˆใ†ใชๅˆฅใฎใƒ„ใƒผใƒซ * ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒปใ‚ตใƒผใƒ“ใ‚น -## Poetryใ‚’ๅˆฉ็”จใ—ใŸDockerใ‚คใƒกใƒผใ‚ธ - -ใ‚‚ใ—ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไพๅญ˜้–ขไฟ‚ใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใซPoetryใ‚’ๅˆฉ็”จใ™ใ‚‹ๅ ดๅˆใ€ใƒžใƒซใƒใ‚นใƒ†ใƒผใ‚ธใƒ“ใƒซใƒ‰ใ‚’ไฝฟใ†ใจ่‰ฏใ„ใงใ—ใ‚‡ใ†ใ€‚ - -```{ .dockerfile .annotate } -# (1) -FROM python:3.9 as requirements-stage - -# (2) -WORKDIR /tmp - -# (3) -RUN pip install poetry - -# (4) -COPY ./pyproject.toml ./poetry.lock* /tmp/ - -# (5) -RUN poetry export -f requirements.txt --output requirements.txt --without-hashes - -# (6) -FROM python:3.9 - -# (7) -WORKDIR /code - -# (8) -COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt - -# (9) -RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt - -# (10) -COPY ./app /code/app - -# (11) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] -``` - -1. ใ“ใ‚Œใฏๆœ€ๅˆใฎใ‚นใƒ†ใƒผใ‚ธใงใ€`requirements-stage`ใจๅไป˜ใ‘ใ‚‰ใ‚Œใพใ™ -2. `/tmp` ใ‚’็พๅœจใฎไฝœๆฅญใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ่จญๅฎšใ—ใพใ™ - ใ“ใ“ใง `requirements.txt` ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ - -3. ใ“ใฎDockerใ‚นใƒ†ใƒผใ‚ธใซPoetryใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ - -4. pyproject.toml`ใจ`poetry.lock`ใƒ•ใ‚กใ‚คใƒซใ‚’`/tmp` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซใ‚ณใƒ”ใƒผใ—ใพใ™ - - `./poetry.lock*`๏ผˆๆœซๅฐพใซ`*`๏ผ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใŸใ‚ใ€ใใฎใƒ•ใ‚กใ‚คใƒซใŒใพใ ๅˆฉ็”จใงใใชใ„ๅ ดๅˆใงใ‚‚ใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ™ใ‚‹ใ“ใจใฏใชใ„ใงใ™ใ€‚ -5. requirements.txt`ใƒ•ใ‚กใ‚คใƒซใ‚’็”Ÿๆˆใ—ใพใ™ - -6. ใ“ใ‚Œใฏๆœ€ๅพŒใฎใ‚นใƒ†ใƒผใ‚ธใงใ‚ใ‚Šใ€ใ“ใ“ใซใ‚ใ‚‹ใ‚‚ใฎใฏใ™ในใฆๆœ€็ต‚็š„ใชใ‚ณใƒณใƒ†ใƒŠใƒปใ‚คใƒกใƒผใ‚ธใซไฟๅญ˜ใ•ใ‚Œใพใ™ -7. ็พๅœจใฎไฝœๆฅญใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ `/code` ใซ่จญๅฎšใ—ใพใ™ -8. `requirements.txt`ใƒ•ใ‚กใ‚คใƒซใ‚’ `/code` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซใ‚ณใƒ”ใƒผใ—ใพใ™ - ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏๅ‰ใฎDockerใ‚นใƒ†ใƒผใ‚ธใซใ—ใ‹ๅญ˜ๅœจใ—ใชใ„ใŸใ‚ใ€`--from-requirements-stage`ใ‚’ไฝฟใฃใฆใ‚ณใƒ”ใƒผใ—ใพใ™ใ€‚ -9. ็”Ÿๆˆใ•ใ‚ŒใŸ `requirements.txt` ใƒ•ใ‚กใ‚คใƒซใซใ‚ใ‚‹ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ -10. app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ `/code` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซใ‚ณใƒ”ใƒผใ—ใพใ™ -11. uvicorn` ใ‚ณใƒžใƒณใƒ‰ใ‚’ๅฎŸ่กŒใ—ใฆใ€`app.main` ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใ—ใŸ `app` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซๆŒ‡็คบใ—ใพใ™ -/// tip - -"+"ใฎๅนใๅ‡บใ—ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใจใ€ใใ‚Œใžใ‚Œใฎ่กŒใŒไฝ•ใ‚’ใ™ใ‚‹ใฎใ‹ใ‚’่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ - -/// - -**Dockerใ‚นใƒ†ใƒผใ‚ธ**ใฏ`Dockerfile`ใฎไธ€้ƒจใงใ€**ไธ€ๆ™‚็š„ใชใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธ**ใจใ—ใฆๅ‹•ไฝœใ—ใพใ™ใ€‚ - -ๆœ€ๅˆใฎใ‚นใƒ†ใƒผใ‚ธใฏ **Poetryใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ**ใจ Poetry ใฎ `pyproject.toml` ใƒ•ใ‚กใ‚คใƒซใ‹ใ‚‰ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅซใ‚€**`requirements.txt`ใ‚’็”Ÿๆˆ**ใ™ใ‚‹ใŸใ‚ใ ใ‘ใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ - -ใ“ใฎ `requirements.txt` ใƒ•ใ‚กใ‚คใƒซใฏๅพŒๅŠใฎ **ๆฌกใฎใ‚นใƒ†ใƒผใ‚ธ**ใง `pip` ใจๅ…ฑใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ - -ๆœ€็ต‚็š„ใชใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใงใฏใ€**ๆœ€็ต‚ใ‚นใƒ†ใƒผใ‚ธ**ใฎใฟใŒไฟๅญ˜ใ•ใ‚Œใพใ™ใ€‚ๅ‰ใฎใ‚นใƒ†ใƒผใ‚ธใฏ็ ดๆฃ„ใ•ใ‚Œใพใ™ใ€‚ - -Poetryใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€**Dockerใƒžใƒซใƒใ‚นใƒ†ใƒผใ‚ธใƒ“ใƒซใƒ‰**ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใฏ็†ใซใ‹ใชใฃใฆใ„ใพใ™ใ€‚ - -ใชใœใชใ‚‰ใ€ๆœ€็ต‚็š„ใชใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใซPoetryใจใใฎไพๅญ˜้–ขไฟ‚ใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ๅฟ…่ฆใฏใชใใ€**ๅฟ…่ฆใชใฎใฏ**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใŸใ‚ใซ็”Ÿๆˆใ•ใ‚ŒใŸ `requirements.txt` ใƒ•ใ‚กใ‚คใƒซใ ใ‘ใ ใ‹ใ‚‰ใงใ™ใ€‚ +## `uv` ใ‚’ไฝฟใฃใŸDockerใ‚คใƒกใƒผใ‚ธ { #docker-image-with-uv } -ใใ—ใฆๆฌกใฎ๏ผˆใใ—ใฆๆœ€็ต‚็š„ใช๏ผ‰ใ‚นใƒ†ใƒผใ‚ธใงใฏใ€ๅ‰่ฟฐใจใปใผๅŒใ˜ๆ–นๆณ•ใงใ‚คใƒกใƒผใ‚ธใ‚’ใƒ“ใƒซใƒ‰ใ—ใพใ™ใ€‚ +uv ใ‚’ไฝฟใฃใฆใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใจ็ฎก็†ใ‚’ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€uv Docker guideใซๅพ“ใฃใฆใใ ใ•ใ„ใ€‚ -### TLS Termination Proxyใฎ่ฃๅด - Poetry - -็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€Nginxใ‚„Traefikใฎใ‚ˆใ†ใชTLS Termination Proxy๏ผˆใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใƒผ๏ผ‰ใฎๅพŒใ‚ใงใ‚ณใƒณใƒ†ใƒŠใ‚’ๅ‹•ใ‹ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€`--proxy-headers`ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ใ‚ณใƒžใƒณใƒ‰ใซ่ฟฝๅŠ ใ—ใพใ™๏ผš - -```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] -``` - -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ใ‚ณใƒณใƒ†ใƒŠใƒปใ‚ทใ‚นใƒ†ใƒ ๏ผˆไพ‹ใˆใฐ**Docker**ใ‚„**Kubernetes**ใชใฉ๏ผ‰ใ‚’ไฝฟใˆใฐใ€ใ™ในใฆใฎ**ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใ‚’ๆ‰ฑใ†ใฎใŒใ‹ใชใ‚Š็ฐกๅ˜ใซใชใ‚Šใพใ™๏ผš -* ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS +* HTTPS * ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ * ๅ†่ตทๅ‹• -* **ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰** +* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ * ใƒกใƒขใƒช * ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ— ใปใจใ‚“ใฉใฎๅ ดๅˆใ€ใƒ™ใƒผใ‚นใจใชใ‚‹ใ‚คใƒกใƒผใ‚ธใฏไฝฟ็”จใ›ใšใ€ๅ…ฌๅผใฎPython Dockerใ‚คใƒกใƒผใ‚ธใ‚’ใƒ™ใƒผใ‚นใซใ—ใŸ**ใ‚ณใƒณใƒ†ใƒŠใ‚คใƒกใƒผใ‚ธใ‚’ใ‚ผใƒญใ‹ใ‚‰ใƒ“ใƒซใƒ‰**ใ—ใพใ™ใ€‚ -`Dockerfile`ใจ**Dockerใ‚ญใƒฃใƒƒใ‚ทใƒฅ**ๅ†…ใฎๅ‘ฝไปคใฎ**้ †็•ช**ใซๆณจๆ„ใ™ใ‚‹ใ“ใจใงใ€**ใƒ“ใƒซใƒ‰ๆ™‚้–“ใ‚’ๆœ€ๅฐๅŒ–**ใ™ใ‚‹ใ“ใจใŒใงใใ€็”Ÿ็”ฃๆ€งใ‚’ๆœ€ๅคงๅŒ–ใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆใใ—ใฆ้€€ๅฑˆใ‚’้ฟใ‘ใ‚‹ใ“ใจใŒใงใใพใ™๏ผ‰ใ€‚๐Ÿ˜Ž - -็‰นๅˆฅใชใ‚ฑใƒผใ‚นใงใฏใ€FastAPI็”จใฎๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธใ‚’ไฝฟใ„ใŸใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿค“ +`Dockerfile`ใจ**Dockerใ‚ญใƒฃใƒƒใ‚ทใƒฅ**ๅ†…ใฎๅ‘ฝไปคใฎ**้ †็•ช**ใซๆณจๆ„ใ™ใ‚‹ใ“ใจใงใ€**ใƒ“ใƒซใƒ‰ๆ™‚้–“ใ‚’ๆœ€ๅฐๅŒ–**ใ—ใ€็”Ÿ็”ฃๆ€งใ‚’ๆœ€ๅคงๅŒ–ใงใใพใ™๏ผˆใใ—ใฆ้€€ๅฑˆใ‚’้ฟใ‘ใ‚‹ใ“ใจใŒใงใใพใ™๏ผ‰ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index 7b0f567aa5..d5a6daf0c0 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -1,10 +1,10 @@ -# HTTPS ใซใคใ„ใฆ +# HTTPS ใซใคใ„ใฆ { #about-https } HTTPSใฏๅ˜ใซใ€Œๆœ‰ๅŠนใ€ใ‹ใ€Œ็„กๅŠนใ€ใ‹ใงๆฑบใพใ‚‹ใ‚‚ใฎใ ใจๆ€ใ„ใŒใกใงใ™ใ€‚ ใ—ใ‹ใ—ใ€ใใ‚Œใ‚ˆใ‚Šใ‚‚ใฏใ‚‹ใ‹ใซ่ค‡้›‘ใงใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ใ‚‚ใ—ๆ€ฅใ„ใงใ„ใŸใ‚Šใ€HTTPSใฎไป•็ต„ใฟใซใคใ„ใฆๆฐ—ใซใ—ใชใ„ใฎใงใ‚ใ‚Œใฐใ€ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใซ้€ฒใฟใ€ใ•ใพใ–ใพใชใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใ‚’ไฝฟใฃใฆใ™ในใฆใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ใ‚นใƒ†ใƒƒใƒ—ใƒปใƒใ‚คใƒปใ‚นใƒ†ใƒƒใƒ—ใฎๆ‰‹้ †ใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ @@ -22,25 +22,19 @@ HTTPSใฏๅ˜ใซใ€Œๆœ‰ๅŠนใ€ใ‹ใ€Œ็„กๅŠนใ€ใ‹ใงๆฑบใพใ‚‹ใ‚‚ใฎใ ใจๆ€ใ„ใŒใก * ๆŽฅ็ถšใฎๆš—ๅทๅŒ–ใฏ**TCPใƒฌใƒ™ใƒซ**ใง่กŒใ‚ใ‚Œใพใ™ใ€‚ * ใใ‚Œใฏ**HTTPใฎ1ใคไธ‹**ใฎใƒฌใ‚คใƒคใƒผใงใ™ใ€‚ * ใคใพใ‚Šใ€**่จผๆ˜Žๆ›ธใจๆš—ๅทๅŒ–**ใฎๅ‡ฆ็†ใฏใ€**HTTPใฎๅ‰**ใซ่กŒใ‚ใ‚Œใพใ™ใ€‚ -* **TCPใฏ "ใƒ‰ใƒกใ‚คใƒณ "ใซใคใ„ใฆ็Ÿฅใ‚Šใพใ›ใ‚“**ใ€‚IPใ‚ขใƒ‰ใƒฌใ‚นใซใคใ„ใฆใฎใฟ็Ÿฅใฃใฆใ„ใพใ™ใ€‚ +* **TCPใฏใ€Œใƒ‰ใƒกใ‚คใƒณใ€ใซใคใ„ใฆ็Ÿฅใ‚Šใพใ›ใ‚“**ใ€‚IPใ‚ขใƒ‰ใƒฌใ‚นใซใคใ„ใฆใฎใฟ็Ÿฅใฃใฆใ„ใพใ™ใ€‚ * ่ฆๆฑ‚ใ•ใ‚ŒใŸ**็‰นๅฎšใฎใƒ‰ใƒกใ‚คใƒณ**ใซ้–ขใ™ใ‚‹ๆƒ…ๅ ฑใฏใ€**HTTPใƒ‡ใƒผใ‚ฟ**ใซๅ…ฅใ‚Šใพใ™ใ€‚ * **HTTPS่จผๆ˜Žๆ›ธ**ใฏใ€**็‰นๅฎšใฎใƒ‰ใƒกใ‚คใƒณ**ใ‚’ใ€Œ่จผๆ˜Žใ€ใ—ใพใ™ใŒใ€ใƒ—ใƒญใƒˆใ‚ณใƒซใจๆš—ๅทๅŒ–ใฏTCPใƒฌใƒ™ใƒซใง่กŒใ‚ใ‚Œใ€ใฉใฎใƒ‰ใƒกใ‚คใƒณใŒๆ‰ฑใ‚ใ‚Œใฆใ„ใ‚‹ใ‹ใ‚’**็Ÿฅใ‚‹ๅ‰**ใซ่กŒใ‚ใ‚Œใพใ™ใ€‚ * **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ**ใ€**IPใ‚ขใƒ‰ใƒฌใ‚นใ”ใจใซ1ใคใฎHTTPS่จผๆ˜Žๆ›ธ**ใ—ใ‹ๆŒใฆใชใ„ใ“ใจใซใชใ‚Šใพใ™ใ€‚ * ใ“ใ‚Œใฏใ€ใ‚ตใƒผใƒใƒผใฎ่ฆๆจกใ‚„ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่ฆๆจกใซๅฏ„ใ‚Šใพใ›ใ‚“ใ€‚ * ใ—ใ‹ใ—ใ€ใ“ใ‚Œใซใฏ**่งฃๆฑบ็ญ–**ใŒใ‚ใ‚Šใพใ™ใ€‚ -* **TLS**ใƒ—ใƒญใƒˆใ‚ณใƒซ(HTTPใฎๅ‰ใซใ€TCPใƒฌใƒ™ใƒซใงๆš—ๅทๅŒ–ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ‚‚ใฎ)ใซใฏใ€**SNI**ใจๅ‘ผใฐใ‚Œใ‚‹**ๆ‹กๅผต**ใŒใ‚ใ‚Šใพใ™ใ€‚ +* **TLS**ใƒ—ใƒญใƒˆใ‚ณใƒซ(HTTPใฎๅ‰ใซใ€TCPใƒฌใƒ™ใƒซใงๆš—ๅทๅŒ–ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ‚‚ใฎ)ใซใฏใ€**SNI**ใจๅ‘ผใฐใ‚Œใ‚‹**ๆ‹กๅผต**ใŒใ‚ใ‚Šใพใ™ใ€‚ * ใ“ใฎSNIๆ‹กๅผตๆฉŸ่ƒฝใซใ‚ˆใ‚Šใ€1ใคใฎใ‚ตใƒผใƒใƒผ๏ผˆ**ๅ˜ไธ€ใฎIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใค๏ผ‰ใŒ**่ค‡ๆ•ฐใฎHTTPS่จผๆ˜Žๆ›ธ**ใ‚’ๆŒใกใ€**่ค‡ๆ•ฐใฎHTTPSใƒ‰ใƒกใ‚คใƒณ/ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใซใ‚ตใƒผใƒ“ใ‚นใ‚’ๆไพ›ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ * ใ“ใ‚ŒใŒๆฉŸ่ƒฝใ™ใ‚‹ใŸใ‚ใซใฏใ€**ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใงใƒชใƒƒใ‚นใƒณใ—ใฆใ„ใ‚‹ใ€ใ‚ตใƒผใƒใƒผไธŠใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹**ๅ˜ไธ€ใฎ**ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ(ใƒ—ใƒญใ‚ฐใƒฉใƒ )ใŒใ€ใ‚ตใƒผใƒใƒผๅ†…ใฎ**ใ™ในใฆใฎHTTPS่จผๆ˜Žๆ›ธ**ใ‚’ๆŒใฃใฆใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ - * ใ‚ปใ‚ญใƒฅใ‚ขใชๆŽฅ็ถšใ‚’ๅ–ๅพ—ใ—ใŸ**ๅพŒ**ใงใ‚‚ใ€้€šไฟกใƒ—ใƒญใƒˆใ‚ณใƒซใฏ**HTTPใฎใพใพ**ใงใ™ใ€‚ * ใ‚ณใƒณใƒ†ใƒณใƒ„ใฏ**HTTPใƒ—ใƒญใƒˆใ‚ณใƒซ**ใง้€ไฟกใ•ใ‚Œใฆใ„ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€**ๆš—ๅทๅŒ–**ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ - -ใ‚ตใƒผใƒใƒผ๏ผˆใƒžใ‚ทใƒณใ€ใƒ›ใ‚นใƒˆใชใฉ๏ผ‰ไธŠใง**1ใคใฎใƒ—ใƒญใ‚ฐใƒฉใƒ /HTTPใ‚ตใƒผใƒใƒผ**ใ‚’ๅฎŸ่กŒใ•ใ›ใ€**HTTPSใซ้–ขใ™ใ‚‹ๅ…จใฆใฎใ“ใจ**ใ‚’็ฎก็†ใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ - -**ๆš—ๅทๅŒ–ใ•ใ‚ŒใŸ HTTPS ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใ‚’ๅ—ไฟกใ—ใ€**ๅพฉๅทๅŒ–ใ•ใ‚ŒใŸ HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใ‚’ๅŒใ˜ใ‚ตใƒผใƒใƒผใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ๅฎŸ้š›ใฎ HTTP ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใ“ใฎๅ ดๅˆใฏ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผ‰ใซ้€ไฟกใ—ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‹ใ‚‰ **HTTP ใƒฌใ‚นใƒใƒณใ‚น** ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€้ฉๅˆ‡ใช **HTTPS ่จผๆ˜Žๆ›ธ** ใ‚’ไฝฟ็”จใ—ใฆ **ๆš—ๅทๅŒ–** ใ—ใ€ใใ—ใฆ**HTTPS** ใ‚’ไฝฟ็”จใ—ใฆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ้€ใ‚Š่ฟ”ใ—ใพใ™ใ€‚ - -ใ“ใฎใ‚ตใƒผใƒใƒผใฏใ—ใฐใ—ใฐ **TLS Termination Proxy**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ +ใ‚ตใƒผใƒใƒผ๏ผˆใƒžใ‚ทใƒณใ€ใƒ›ใ‚นใƒˆใชใฉ๏ผ‰ไธŠใง**1ใคใฎใƒ—ใƒญใ‚ฐใƒฉใƒ /HTTPใ‚ตใƒผใƒใƒผ**ใ‚’ๅฎŸ่กŒใ•ใ›ใ€**HTTPSใซ้–ขใ™ใ‚‹ๅ…จใฆใฎใ“ใจ**ใ‚’็ฎก็†ใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚**ๆš—ๅทๅŒ–ใ•ใ‚ŒใŸ HTTPS ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใ‚’ๅ—ไฟกใ—ใ€**ๅพฉๅทๅŒ–ใ•ใ‚ŒใŸ HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใ‚’ๅŒใ˜ใ‚ตใƒผใƒใƒผใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ๅฎŸ้š›ใฎ HTTP ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใ“ใฎๅ ดๅˆใฏ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผ‰ใซ้€ไฟกใ—ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‹ใ‚‰ **HTTP ใƒฌใ‚นใƒใƒณใ‚น** ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€้ฉๅˆ‡ใช **HTTPS ่จผๆ˜Žๆ›ธ** ใ‚’ไฝฟ็”จใ—ใฆ **ๆš—ๅทๅŒ–** ใ—ใ€ใใ—ใฆ**HTTPS** ใ‚’ไฝฟ็”จใ—ใฆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ้€ใ‚Š่ฟ”ใ—ใพใ™ใ€‚ใ“ใฎใ‚ตใƒผใƒใƒผใฏใ—ใฐใ—ใฐ **TLS Termination Proxy**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ TLS Termination Proxyใจใ—ใฆไฝฟใˆใ‚‹ใ‚ชใƒ—ใ‚ทใƒงใƒณใซใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚‚ใฎใŒใ‚ใ‚Šใพใ™๏ผš @@ -50,7 +44,7 @@ TLS Termination Proxyใจใ—ใฆไฝฟใˆใ‚‹ใ‚ชใƒ—ใ‚ทใƒงใƒณใซใฏใ€ไปฅไธ‹ใฎใ‚ˆใ† * HAProxy -## Let's Encrypt +## Let's Encrypt { #lets-encrypt } Let's Encryptไปฅๅ‰ใฏใ€ใ“ใ‚Œใ‚‰ใฎ**HTTPS่จผๆ˜Žๆ›ธ**ใฏไฟก้ ผใงใใ‚‹็ฌฌไธ‰่€…ใซใ‚ˆใฃใฆ่ฒฉๅฃฒใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ @@ -64,27 +58,27 @@ Let's Encryptไปฅๅ‰ใฏใ€ใ“ใ‚Œใ‚‰ใฎ**HTTPS่จผๆ˜Žๆ›ธ**ใฏไฟก้ ผใงใใ‚‹็ฌฌไธ‰ ใ“ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฏใ€ใ“ใ‚Œใ‚‰ใฎ่จผๆ˜Žๆ›ธใฎๅ–ๅพ—ใจๆ›ดๆ–ฐใ‚’่‡ชๅ‹•ๅŒ–ใ™ใ‚‹ใ“ใจใงใ€**ๅฎ‰ๅ…จใชHTTPSใ‚’ใ€็„กๆ–™ใงใ€ๆฐธ้ ใซ**ๅˆฉ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใ“ใจใงใ™ใ€‚ -## ้–‹็™บ่€…ใฎใŸใ‚ใฎ HTTPS +## ้–‹็™บ่€…ใฎใŸใ‚ใฎ HTTPS { #https-for-developers } ใ“ใ“ใงใฏใ€HTTPS APIใŒใฉใฎใ‚ˆใ†ใซ่ฆ‹ใˆใ‚‹ใ‹ใฎไพ‹ใ‚’ใ€ไธปใซ้–‹็™บ่€…ใซใจใฃใฆ้‡่ฆใชใ‚ขใ‚คใƒ‡ใ‚ขใซๆณจๆ„ใ‚’ๆ‰•ใ„ใชใŒใ‚‰ใ€ใ‚นใƒ†ใƒƒใƒ—ใƒปใƒใ‚คใƒปใ‚นใƒ†ใƒƒใƒ—ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ -### ใƒ‰ใƒกใ‚คใƒณๅ +### ใƒ‰ใƒกใ‚คใƒณๅ { #domain-name } ใ‚นใƒ†ใƒƒใƒ—ใฎๅˆใ‚ใฏใ€**ใƒ‰ใƒกใ‚คใƒณๅ**ใ‚’**ๅ–ๅพ—ใ™ใ‚‹ใ“ใจ**ใ‹ใ‚‰ๅง‹ใพใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใใฎๅพŒใ€DNSใ‚ตใƒผใƒใƒผ๏ผˆใŠใใ‚‰ใๅŒใ˜ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผ๏ผ‰ใซ่จญๅฎšใ—ใพใ™ใ€‚ -ใŠใใ‚‰ใใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผ๏ผˆไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‹ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใ‚’ๆ‰‹ใซๅ…ฅใ‚Œใ€ๅ›บๅฎšใฎ **ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใคใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใŠใใ‚‰ใใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผ๏ผˆไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‹ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใ‚’ๆ‰‹ใซๅ…ฅใ‚Œใ€fixed **ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใคใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -DNSใ‚ตใƒผใƒใƒผใงใฏใ€**ๅ–ๅพ—ใ—ใŸใƒ‰ใƒกใ‚คใƒณ**ใ‚’ใ‚ใชใŸใฎใ‚ตใƒผใƒใƒผใฎใƒ‘ใƒ—ใƒชใƒƒใ‚ฏ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใซๅ‘ใ‘ใ‚‹ใƒฌใ‚ณใƒผใƒ‰๏ผˆใ€Œ`Aใƒฌใ‚ณใƒผใƒ‰`ใ€๏ผ‰ใ‚’่จญๅฎšใ—ใพใ™ใ€‚ +DNSใ‚ตใƒผใƒใƒผใงใฏใ€**ๅ–ๅพ—ใ—ใŸใƒ‰ใƒกใ‚คใƒณ**ใ‚’ใ‚ใชใŸใฎใ‚ตใƒผใƒใƒผใฎใƒ‘ใƒ—ใƒชใƒƒใ‚ฏ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใซๅ‘ใ‘ใ‚‹ใƒฌใ‚ณใƒผใƒ‰๏ผˆใ€Œ`A record`ใ€๏ผ‰ใ‚’่จญๅฎšใ—ใพใ™ใ€‚ ใ“ใ‚ŒใฏใŠใใ‚‰ใใ€ๆœ€ๅˆใฎ1ๅ›žใ ใ‘ใ‚ใ‚Šใ€ใ™ในใฆใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ใจใใซ่กŒใ†ใงใ—ใ‚‡ใ†ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ใƒ‰ใƒกใ‚คใƒณๅใฎ่ฉฑใฏHTTPSใซ้–ขใ™ใ‚‹่ฉฑใฎใฏใ‚‹ใ‹ๅ‰ใซใ‚ใ‚Šใพใ™ใŒใ€ใ™ในใฆใŒใƒ‰ใƒกใ‚คใƒณใจIPใ‚ขใƒ‰ใƒฌใ‚นใซไพๅญ˜ใ™ใ‚‹ใŸใ‚ใ€ใ“ใ“ใง่จ€ๅŠใ™ใ‚‹ไพกๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚ /// -### DNS +### DNS { #dns } ใงใฏใ€ๅฎŸ้š›ใฎHTTPSใฎ้ƒจๅˆ†ใซๆณจ็›ฎใ—ใฆใฟใ‚ˆใ†ใ€‚ @@ -94,7 +88,7 @@ DNSใ‚ตใƒผใƒใƒผใฏใ€ใƒ–ใƒฉใ‚ฆใ‚ถใซ็‰นๅฎšใฎ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ไฝฟ็”จใ™ใ‚‹ -### TLS Handshake ใฎ้–‹ๅง‹ +### TLS Handshake ใฎ้–‹ๅง‹ { #tls-handshake-start } ใƒ–ใƒฉใ‚ฆใ‚ถใฏIPใ‚ขใƒ‰ใƒฌใ‚นใจ**ใƒใƒผใƒˆ443**๏ผˆHTTPSใƒใƒผใƒˆ๏ผ‰ใง้€šไฟกใ—ใพใ™ใ€‚ @@ -104,7 +98,7 @@ DNSใ‚ตใƒผใƒใƒผใฏใ€ใƒ–ใƒฉใ‚ฆใ‚ถใซ็‰นๅฎšใฎ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ไฝฟ็”จใ™ใ‚‹ TLSๆŽฅ็ถšใ‚’็ขบ็ซ‹ใ™ใ‚‹ใŸใ‚ใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใจใ‚ตใƒผใƒใƒผ้–“ใฎใ“ใฎใ‚„ใ‚Šใจใ‚Šใฏใ€**TLSใƒใƒณใƒ‰ใ‚ทใ‚งใ‚คใ‚ฏ**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ -### SNIๆ‹กๅผตๆฉŸ่ƒฝไป˜ใใฎTLS +### SNIๆ‹กๅผตๆฉŸ่ƒฝไป˜ใใฎTLS { #tls-with-sni-extension } ใ‚ตใƒผใƒใƒผๅ†…ใฎ**1ใคใฎใƒ—ใƒญใ‚ปใ‚น**ใ ใ‘ใŒใ€็‰นๅฎš ใฎ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใฎ็‰นๅฎšใฎ**ใƒใƒผใƒˆ** ใงๅพ…ใกๅ—ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -112,7 +106,7 @@ TLSๆŽฅ็ถšใ‚’็ขบ็ซ‹ใ™ใ‚‹ใŸใ‚ใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใจใ‚ตใƒผใƒใƒผ้–“ใฎใ“ใฎ TLS๏ผˆHTTPS๏ผ‰ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง`443`ใจใ„ใ†็‰นๅฎšใฎใƒใƒผใƒˆใ‚’ไฝฟ็”จใ™ใ‚‹ใ€‚ใคใพใ‚Šใ€ใ“ใ‚ŒใŒๅฟ…่ฆใชใƒใƒผใƒˆใงใ™ใ€‚ -ใ“ใฎใƒใƒผใƒˆใ‚’ใƒชใƒƒใ‚นใƒณใงใใ‚‹ใฎใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใชใฎใงใ€ใ“ใ‚Œใ‚’ๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚นใฏ**TLS Termination Proxy**ใจใชใ‚Šใพใ™ใ€‚ +ใ“ใฎใƒใƒผใƒˆใ‚’ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใใ‚‹ใฎใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใชใฎใงใ€ใ“ใ‚Œใ‚’ๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ปใ‚นใฏ**TLS Termination Proxy**ใจใชใ‚Šใพใ™ใ€‚ TLS Termination Proxyใฏใ€1ใคไปฅไธŠใฎ**TLS่จผๆ˜Žๆ›ธ**๏ผˆHTTPS่จผๆ˜Žๆ›ธ๏ผ‰ใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ @@ -130,13 +124,13 @@ TLS Termination Proxyใฏใ€1ใคไปฅไธŠใฎ**TLS่จผๆ˜Žๆ›ธ**๏ผˆHTTPS่จผๆ˜Žๆ›ธ๏ผ‰ใซ ใ“ใ‚ŒใŒ**HTTPS**ใงใ‚ใ‚Šใ€็ด”็ฒ‹ใช๏ผˆๆš—ๅทๅŒ–ใ•ใ‚Œใฆใ„ใชใ„๏ผ‰TCPๆŽฅ็ถšใงใฏใชใใ€**ใ‚ปใ‚ญใƒฅใ‚ขใชTLSๆŽฅ็ถš**ใฎไธญใซ**HTTP**ใŒใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ้€šไฟกใฎๆš—ๅทๅŒ–ใฏใ€HTTPใƒฌใƒ™ใƒซใงใฏใชใใ€**TCPใƒฌใƒ™ใƒซ**ใง่กŒใ‚ใ‚Œใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// -### HTTPS ใƒชใ‚ฏใ‚จใ‚นใƒˆ +### HTTPS ใƒชใ‚ฏใ‚จใ‚นใƒˆ { #https-request } ใ“ใ‚Œใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใจใ‚ตใƒผใƒใƒผ๏ผˆๅ…ทไฝ“็š„ใซใฏใƒ–ใƒฉใ‚ฆใ‚ถใจTLS Termination Proxy๏ผ‰ใฏ**ๆš—ๅทๅŒ–ใ•ใ‚ŒใŸTCPๆŽฅ็ถš**ใ‚’ๆŒใคใ“ใจใซใชใ‚Šใ€**HTTP้€šไฟก**ใ‚’้–‹ๅง‹ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -144,19 +138,19 @@ TLS Termination Proxyใฏใ€1ใคไปฅไธŠใฎ**TLS่จผๆ˜Žๆ›ธ**๏ผˆHTTPS่จผๆ˜Žๆ›ธ๏ผ‰ใซ -### ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅพฉๅทๅŒ– +### ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅพฉๅทๅŒ– { #decrypt-the-request } TLS Termination Proxy ใฏใ€ๅˆๆ„ใŒๅ–ใ‚Œใฆใ„ใ‚‹ๆš—ๅทๅŒ–ใ‚’ไฝฟ็”จใ—ใฆใ€**ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅพฉๅทๅŒ–**ใ—ใ€**ใƒ—ใƒฌใƒผใƒณ (ๅพฉๅทๅŒ–ใ•ใ‚ŒใŸ) HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใ‚’ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ใƒ—ใƒญใ‚ปใ‚น (ไพ‹ใˆใฐใ€FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ Uvicorn ใ‚’ๆŒใคใƒ—ใƒญใ‚ปใ‚น) ใซ้€ไฟกใ—ใพใ™ใ€‚ -### HTTP ใƒฌใ‚นใƒใƒณใ‚น +### HTTP ใƒฌใ‚นใƒใƒณใ‚น { #http-response } ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ—ใ€**ใƒ—ใƒฌใƒผใƒณ(ๆš—ๅทๅŒ–ใ•ใ‚Œใฆใ„ใชใ„)HTTPใƒฌใ‚นใƒใƒณใ‚น** ใ‚’TLS Termination Proxyใซ้€ไฟกใ—ใพใ™ใ€‚ -### HTTPS ใƒฌใ‚นใƒใƒณใ‚น +### HTTPS ใƒฌใ‚นใƒใƒณใ‚น { #https-response } TLS Termination Proxyใฏๆฌกใซใ€ไบ‹ๅ‰ใซๅˆๆ„ใŒๅ–ใ‚Œใฆใ„ใ‚‹ๆš—ๅท(`someapp.example.com`ใฎ่จผๆ˜Žๆ›ธใ‹ใ‚‰ๅง‹ใพใ‚‹)ใ‚’ไฝฟใฃใฆ**ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๆš—ๅทๅŒ–ใ—**ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใซ้€ใ‚Š่ฟ”ใ™ใ€‚ @@ -166,7 +160,7 @@ TLS Termination Proxyใฏๆฌกใซใ€ไบ‹ๅ‰ใซๅˆๆ„ใŒๅ–ใ‚Œใฆใ„ใ‚‹ๆš—ๅท(`someap ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ๏ผˆใƒ–ใƒฉใ‚ฆใ‚ถ๏ผ‰ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใŒๆญฃใ—ใ„ใ‚ตใƒผใƒใƒผใ‹ใ‚‰ๆฅใŸใ“ใจใ‚’็Ÿฅใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใชใœใชใ‚‰ใ€ใใฎใ‚ตใƒผใƒใƒผใฏใ€ไปฅๅ‰ใซ**HTTPS่จผๆ˜Žๆ›ธ**ใ‚’ไฝฟใฃใฆๅˆๆ„ใ—ใŸๆš—ๅทใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ -### ่ค‡ๆ•ฐใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ +### ่ค‡ๆ•ฐใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ { #multiple-applications } ๅŒใ˜ใ‚ตใƒผใƒใƒผ๏ผˆใพใŸใฏ่ค‡ๆ•ฐใฎใ‚ตใƒผใƒใƒผ๏ผ‰ใซใ€ไพ‹ใˆใฐไป–ใฎAPIใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚„ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใชใฉใ€**่ค‡ๆ•ฐใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใŒๅญ˜ๅœจใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -176,7 +170,7 @@ TLS Termination Proxyใฏๆฌกใซใ€ไบ‹ๅ‰ใซๅˆๆ„ใŒๅ–ใ‚Œใฆใ„ใ‚‹ๆš—ๅท(`someap ใใ†ใ™ใ‚Œใฐใ€TLS Termination Proxy ใฏใ€**่ค‡ๆ•ฐใฎใƒ‰ใƒกใ‚คใƒณ**ใ‚„่ค‡ๆ•ฐใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎHTTPSใจ่จผๆ˜Žๆ›ธใ‚’ๅ‡ฆ็†ใ—ใ€ใใ‚Œใžใ‚Œใฎใ‚ฑใƒผใ‚นใง้ฉๅˆ‡ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -### ่จผๆ˜Žๆ›ธใฎๆ›ดๆ–ฐ +### ่จผๆ˜Žๆ›ธใฎๆ›ดๆ–ฐ { #certificate-renewal } ๅฐ†ๆฅใฎใ‚ใ‚‹ๆ™‚็‚นใงใ€ๅ„่จผๆ˜Žๆ›ธใฏ๏ผˆๅ–ๅพ—ๅพŒ็ด„3ใƒถๆœˆใง๏ผ‰**ๅคฑๅŠน**ใ—ใพใ™ใ€‚ @@ -200,10 +194,42 @@ TLS Termination Proxyใฏๆฌกใซใ€ไบ‹ๅ‰ใซๅˆๆ„ใŒๅ–ใ‚Œใฆใ„ใ‚‹ๆš—ๅท(`someap ใ‚ขใƒ—ใƒชใ‚’ๆไพ›ใ—ใชใŒใ‚‰ใ“ใฎใ‚ˆใ†ใชๆ›ดๆ–ฐๅ‡ฆ็†ใ‚’่กŒใ†ใ“ใจใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใƒปใ‚ตใƒผใƒใƒผ๏ผˆUvicornใชใฉ๏ผ‰ใงTLS่จผๆ˜Žๆ›ธใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใฎใงใฏใชใใ€TLS Termination Proxyใ‚’ไฝฟ็”จใ—ใฆ**HTTPSใ‚’ๅ‡ฆ็†ใ™ใ‚‹ๅˆฅใฎใ‚ทใ‚นใƒ†ใƒ **ใ‚’็”จๆ„ใ—ใŸใใชใ‚‹ไธปใช็†็”ฑใฎ1ใคใงใ™ใ€‚ -## ใพใจใ‚ +## ใƒ—ใƒญใ‚ญใ‚ท่ปข้€ใƒ˜ใƒƒใƒ€ใƒผ { #proxy-forwarded-headers } + +ใƒ—ใƒญใ‚ญใ‚ทใ‚’ไฝฟใฃใฆHTTPSใ‚’ๅ‡ฆ็†ใ™ใ‚‹ๅ ดๅˆใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ**๏ผˆใŸใจใˆใฐFastAPI CLI็ตŒ็”ฑใฎUvicorn๏ผ‰ใฏHTTPSๅ‡ฆ็†ใซใคใ„ใฆไฝ•ใ‚‚็Ÿฅใ‚‰ใšใ€**TLS Termination Proxy**ใจใฏใƒ—ใƒฌใƒผใƒณใชHTTPใง้€šไฟกใ—ใพใ™ใ€‚ + +ใ“ใฎ**ใƒ—ใƒญใ‚ญใ‚ท**ใฏ้€šๅธธใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ**ใซ่ปข้€ใ™ใ‚‹ๅ‰ใซใ€ใใฎๅ ดใงใ„ใใคใ‹ใฎHTTPใƒ˜ใƒƒใƒ€ใƒผใ‚’่จญๅฎšใ—ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใŒใƒ—ใƒญใ‚ญใ‚ทใซใ‚ˆใฃใฆ**่ปข้€**ใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผใซ็Ÿฅใ‚‰ใ›ใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ใƒ—ใƒญใ‚ญใ‚ทใƒ˜ใƒƒใƒ€ใƒผใฏๆฌกใฎใจใŠใ‚Šใงใ™๏ผš + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +ใใ‚Œใงใ‚‚ใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ**ใฏไฟก้ ผใงใใ‚‹**ใƒ—ใƒญใ‚ญใ‚ท**ใฎ่ƒŒๅพŒใซใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใ‚‰ใชใ„ใŸใ‚ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใใ‚Œใ‚‰ใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฟก้ ผใ—ใพใ›ใ‚“ใ€‚ + +ใ—ใ‹ใ—ใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ**ใŒ**ใƒ—ใƒญใ‚ญใ‚ท**ใ‹ใ‚‰้€ไฟกใ•ใ‚Œใ‚‹*forwarded*ใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฟก้ ผใ™ใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™ใ€‚FastAPI CLIใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€*CLI Option* `--forwarded-allow-ips` ใ‚’ไฝฟใฃใฆใ€ใฉใฎIPใ‹ใ‚‰ใฎ*forwarded*ใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฟก้ ผใ™ในใใ‹ใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ + +ใŸใจใˆใฐใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ**ใŒไฟก้ ผใงใใ‚‹**ใƒ—ใƒญใ‚ญใ‚ท**ใ‹ใ‚‰ใฎ้€šไฟกใฎใฟใ‚’ๅ—ใ‘ๅ–ใฃใฆใ„ใ‚‹ๅ ดๅˆใ€`--forwarded-allow-ips="*"` ใซ่จญๅฎšใ—ใฆใ€ๅ—ไฟกใ™ใ‚‹ใ™ในใฆใฎIPใ‚’ไฟก้ ผใ™ใ‚‹ใ‚ˆใ†ใซใงใใพใ™ใ€‚ๅ—ใ‘ๅ–ใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใฏใ€**ใƒ—ใƒญใ‚ญใ‚ท**ใŒไฝฟ็”จใ™ใ‚‹IPใ‹ใ‚‰ใฎใ‚‚ใฎใ ใ‘ใซใชใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€HTTPSใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ‹ใฉใ†ใ‹ใ€ใƒ‰ใƒกใ‚คใƒณใชใฉใ€่‡ช่บซใฎใƒ‘ใƒ–ใƒชใƒƒใ‚ฏURLใŒไฝ•ใงใ‚ใ‚‹ใ‹ใ‚’ๆŠŠๆกใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใŸใจใˆใฐใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’้ฉๅˆ‡ใซๅ‡ฆ็†ใ™ใ‚‹ใฎใซไพฟๅˆฉใงใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚Œใซใคใ„ใฆใฏใ€[Behind a Proxy - Enable Proxy Forwarded Headers](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ฉณใ—ใๅญฆในใพใ™ใ€‚ + +/// + +## ใพใจใ‚ { #recap } **HTTPS**ใ‚’ๆŒใคใ“ใจใฏ้žๅธธใซ้‡่ฆใงใ‚ใ‚Šใ€ใปใจใ‚“ใฉใฎๅ ดๅˆใ€ใ‹ใชใ‚Š**ใ‚ฏใƒชใƒ†ใ‚ฃใ‚ซใƒซ**ใงใ™ใ€‚้–‹็™บ่€…ใจใ—ใฆ HTTPS ใซ้–ขใ‚ใ‚‹ๅŠดๅŠ›ใฎใปใจใ‚“ใฉใฏใ€ใ“ใ‚Œใ‚‰ใฎ**ๆฆ‚ๅฟตใจใใฎไป•็ต„ใฟใ‚’็†่งฃใ™ใ‚‹**ใ“ใจใงใ™ใ€‚ ใ—ใ‹ใ—ใ€ใฒใจใŸใณ**้–‹็™บ่€…ๅ‘ใ‘HTTPS**ใฎๅŸบๆœฌ็š„ใชๆƒ…ๅ ฑใ‚’็Ÿฅใ‚Œใฐใ€็ฐกๅ˜ใชๆ–นๆณ•ใงใ™ในใฆใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใซใ€ใ•ใพใ–ใพใชใƒ„ใƒผใƒซใ‚’็ต„ใฟๅˆใ‚ใ›ใฆ่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ๆฌกใฎ็ซ ใงใฏใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใŸใ‚ใซ **HTTPS** ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆใ€ใ„ใใคใ‹ใฎๅ…ทไฝ“ไพ‹ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚๐Ÿ”’ +ๆฌกใฎ็ซ ใฎใ„ใใคใ‹ใงใฏใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใŸใ‚ใซ **HTTPS** ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆใ€ใ„ใใคใ‹ใฎๅ…ทไฝ“ไพ‹ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚๐Ÿ”’ diff --git a/docs/ja/docs/deployment/index.md b/docs/ja/docs/deployment/index.md index 897956e38f..eba6eae6ea 100644 --- a/docs/ja/docs/deployment/index.md +++ b/docs/ja/docs/deployment/index.md @@ -1,7 +1,23 @@ -# ใƒ‡ใƒ—ใƒญใ‚ค +# ใƒ‡ใƒ—ใƒญใ‚ค { #deployment } -**FastAPI** ่ฃฝใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏๆฏ”่ผƒ็š„ๅฎนๆ˜“ใซใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ +**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‡ใƒ—ใƒญใ‚คใฏๆฏ”่ผƒ็š„็ฐกๅ˜ใงใ™ใ€‚ -ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚„ไฝฟ็”จใ—ใฆใ„ใ‚‹ใƒ„ใƒผใƒซใซใ‚ˆใฃใฆใ„ใใคใ‹ใฎๆ–นๆณ•ใซๅˆ†ใ‹ใ‚Œใพใ™ใ€‚ +## ใƒ‡ใƒ—ใƒญใ‚คใจใฏ { #what-does-deployment-mean } -ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใ‚ˆใ‚Š่ฉณใ—ใใใ‚Œใ‚‰ใฎๆ–นๆณ•ใซใคใ„ใฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’**ใƒ‡ใƒ—ใƒญใ‚ค**ใ™ใ‚‹ใจใฏใ€**ใƒฆใƒผใ‚ถใƒผใŒๅˆฉ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹**ใŸใ‚ใซๅฟ…่ฆใชๆ‰‹้ †ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ + +**Web API** ใฎๅ ดๅˆใ€้€šๅธธใฏ **ใƒชใƒขใƒผใƒˆใƒžใ‚ทใƒณ** ไธŠใซ้…็ฝฎใ—ใ€ๅ„ชใ‚ŒใŸใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ€ๅฎ‰ๅฎšๆ€งใชใฉใ‚’ๆไพ›ใ™ใ‚‹ **ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ** ใจ็ต„ใฟๅˆใ‚ใ›ใฆใ€**ใƒฆใƒผใ‚ถใƒผ** ใŒไธญๆ–ญใ‚„ๅ•้กŒใชใๅŠน็އ็š„ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธ**ใ‚ขใ‚ฏใ‚ปใ‚น**ใงใใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใฏ **้–‹็™บ** ๆฎต้šŽใจใฏๅฏพ็…ง็š„ใงใ™ใ€‚้–‹็™บใงใฏใ€ใ‚ณใƒผใƒ‰ใ‚’ๅธธใซๅค‰ๆ›ดใ—ใ€ๅฃŠใ—ใฆใฏ็›ดใ—ใ€้–‹็™บใ‚ตใƒผใƒใƒผใ‚’ๅœๆญขใ—ใŸใ‚Šๅ†่ตทๅ‹•ใ—ใŸใ‚Šใ—ใพใ™ใ€‚ + +## ใƒ‡ใƒ—ใƒญใ‚คๆˆฆ็•ฅ { #deployment-strategies } + +ๅ…ทไฝ“็š„ใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚„ไฝฟ็”จใ™ใ‚‹ใƒ„ใƒผใƒซใซใ‚ˆใฃใฆใ€ใ„ใใคใ‹ใฎๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ + +่ค‡ๆ•ฐใฎใƒ„ใƒผใƒซใ‚’็ต„ใฟๅˆใ‚ใ›ใฆ่‡ชๅˆ†ใง**ใ‚ตใƒผใƒใƒผใ‚’ใƒ‡ใƒ—ใƒญใ‚ค**ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ—ใ€ไฝœๆฅญใฎไธ€้ƒจใ‚’ไปฃ่กŒใ—ใฆใใ‚Œใ‚‹ **ใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒ“ใ‚น** ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ใปใ‹ใซใ‚‚้ธๆŠž่‚ขใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใŸใจใˆใฐใ€FastAPI ใฎ้–‹็™บใƒใƒผใƒ ใงใ‚ใ‚‹็งใŸใกใฏใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใธใฎ FastAPI ใ‚ขใƒ—ใƒชใฎใƒ‡ใƒ—ใƒญใ‚คใ‚’ๅฏ่ƒฝใช้™ใ‚Šๅˆ็†ๅŒ–ใ—ใ€FastAPI ใ‚’ไฝฟใฃใฆ้–‹็™บใ™ใ‚‹ใฎใจๅŒใ˜้–‹็™บ่€…ไฝ“้จ“ใ‚’ๆไพ›ใ™ใ‚‹ใŸใ‚ใซใ€**FastAPI Cloud** ใ‚’ๆง‹็ฏ‰ใ—ใพใ—ใŸใ€‚ + +**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹้š›ใซใ€ใŠใใ‚‰ใๅฟต้ ญใซ็ฝฎใในใไธป่ฆใชๆฆ‚ๅฟตใ‚’ใ„ใใคใ‹็ดนไป‹ใ—ใพใ™๏ผˆใŸใ ใ—ใ€ใใฎใปใจใ‚“ใฉใฏไป–ใฎ็จฎ้กžใฎ Web ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚‚ๅฝ“ใฆใฏใพใ‚Šใพใ™๏ผ‰ใ€‚ + +ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€็•™ๆ„ใ™ในใ็‚นใฎ่ฉณ็ดฐใ‚„ใ€ใใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใŸใ‚ใฎใ„ใใคใ‹ใฎๆ‰‹ๆณ•ใ‚’็ขบ่ชใ—ใพใ™ใ€‚ โœจ diff --git a/docs/ja/docs/deployment/server-workers.md b/docs/ja/docs/deployment/server-workers.md index 38ceab0172..933b875d76 100644 --- a/docs/ja/docs/deployment/server-workers.md +++ b/docs/ja/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# Server Workers - Gunicorn ใจ Uvicorn +# Server Workers - ใƒฏใƒผใ‚ซใƒผไป˜ใUvicorn { #server-workers-uvicorn-with-workers } ๅ‰ๅ›žใฎใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆใ‚’ๆŒฏใ‚Š่ฟ”ใฃใฆใฟใพใ—ใ‚‡ใ†๏ผš @@ -9,124 +9,79 @@ * ใƒกใƒขใƒช * ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ— -ใ“ใ“ใพใงใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏใ€ใŠใใ‚‰ใUvicornใฎใ‚ˆใ†ใช**ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’**ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚น**ใงๅฎŸ่กŒใ—ใฆใ„ใพใ™ใ€‚ +ใ“ใ“ใพใงใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏใ€ใŠใใ‚‰ใ `fastapi` ใ‚ณใƒžใƒณใƒ‰ใชใฉ๏ผˆUvicornใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ‚‚ใฎ๏ผ‰ใ‚’ไฝฟใฃใฆใ€**ๅ˜ไธ€ใฎใƒ—ใƒญใ‚ปใ‚น**ใจใ—ใฆๅ‹•ไฝœใ™ใ‚‹**ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’ๅฎŸ่กŒใ—ใฆใใŸใฏใšใงใ™ใ€‚ ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹้š›ใซใฏใ€**่ค‡ๆ•ฐใฎใ‚ณใ‚ข**ใ‚’ๅˆฉ็”จใ—ใ€ใใ—ใฆใ‚ˆใ‚Šๅคšใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใซใ€ใƒ—ใƒญใ‚ปใ‚นใฎ**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๆŒใคใ“ใจใ‚’ๆœ›ใ‚€ใงใ—ใ‚‡ใ†ใ€‚ ๅ‰ใฎใƒใƒฃใƒ—ใ‚ฟใƒผใงใ‚ใ‚‹[ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ](concepts.md){.internal-link target=_blank}ใซใฆ่ฆ‹ใฆใใŸใ‚ˆใ†ใซใ€ๆœ‰ๅŠนใชๆˆฆ็•ฅใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ -ใ“ใ“ใงใฏ**Gunicorn**ใŒ**Uvicornใฎใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’็ฎก็†ใ™ใ‚‹ๅ ดๅˆใฎไฝฟใ„ๆ–นใซใคใ„ใฆ็ดนไป‹ใ—ใฆใ„ใใพใ™ใ€‚ +ใ“ใ“ใงใฏใ€`fastapi` ใ‚ณใƒžใƒณใƒ‰ใ€ใพใŸใฏ `uvicorn` ใ‚ณใƒžใƒณใƒ‰ใ‚’็›ดๆŽฅไฝฟใฃใฆใ€**ใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น**ไป˜ใใฎ **Uvicorn** ใ‚’ไฝฟใ†ๆ–นๆณ•ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ -/// info +/// info | ๆƒ…ๅ ฑ - -Dockerใ‚„Kubernetesใชใฉใฎใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎ็ซ ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™๏ผš [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank} +Dockerใ‚„Kubernetesใชใฉใฎใ‚ณใƒณใƒ†ใƒŠใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎ็ซ ใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™๏ผš [ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ -็‰นใซ**Kubernetes**ไธŠใงๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใฏใ€ใŠใใ‚‰ใ**Gunicornใ‚’ไฝฟ็”จใ›ใš**ใ€**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใŒใ€ใใ‚Œใซใคใ„ใฆใฏใ“ใฎ็ซ ใฎๅพŒๅŠใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ +็‰นใซ**Kubernetes**ไธŠใงๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใฏใ€ใŠใใ‚‰ใใƒฏใƒผใ‚ซใƒผใฏไฝฟใ‚ใšใ€ไปฃใ‚ใ‚Šใซ**ใ‚ณใƒณใƒ†ใƒŠใ”ใจใซๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ—ใŸใ„ใฏใšใงใ™ใŒใ€ใใ‚Œใซใคใ„ใฆใฏใใฎ็ซ ใฎๅพŒๅŠใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ /// -## Gunicornใซใ‚ˆใ‚‹Uvicornใฎใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใฎ็ฎก็† +## ่ค‡ๆ•ฐใƒฏใƒผใ‚ซใƒผ { #multiple-workers } -**Gunicorn**ใฏ**WSGIๆจ™ๆบ–**ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผใงใ™ใ€‚ใ“ใฎใ“ใจใฏใ€GunicornใฏFlaskใ‚„Djangoใฎใ‚ˆใ†ใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚ตใƒผใƒ“ใ‚นใ‚’ๆไพ›ใงใใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚Gunicornใใ‚Œ่‡ชไฝ“ใฏ**FastAPI**ใจไบ’ๆ›ๆ€งใŒใชใ„ใงใ™ใŒใ€ใจใ„ใ†ใฎใ‚‚FastAPIใฏๆœ€ๆ–ฐใฎ**ASGI ๆจ™ๆบ–**ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ +`--workers` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใง่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใ‚’่ตทๅ‹•ใงใใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€Gunicornใฏ**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผ**ใจใ—ใฆๅ‹•ไฝœใ—ใ€ใƒฆใƒผใ‚ถใƒผใŒ็‰นๅฎšใฎ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใ‚ฏใƒฉใ‚น**ใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซๆŒ‡็คบใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ™ใ‚‹ใจGunicornใฏใใฎใ‚ฏใƒฉใ‚นใ‚’ไฝฟใ„1ใคไปฅไธŠใฎ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’้–‹ๅง‹ใ—ใพใ™ใ€‚ +//// tab | `fastapi` -ใใ—ใฆ**Uvicorn**ใซใฏ**Gunicornไบ’ๆ›ใฎใƒฏใƒผใ‚ซใƒผใ‚ฏใƒฉใ‚น**ใŒใ‚ใ‚Šใพใ™ใ€‚ - -ใ“ใฎ็ต„ใฟๅˆใ‚ใ›ใงใ€Gunicornใฏ**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผ**ใจใ—ใฆๅ‹•ไฝœใ—ใ€**ใƒใƒผใƒˆ**ใจ**IP**ใ‚’ใƒชใƒƒใ‚นใƒณใ—ใพใ™ใ€‚ใใ—ใฆใ€**Uvicornใ‚ฏใƒฉใ‚น**ใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใซ้€šไฟกใ‚’**่ปข้€**ใ—ใพใ™ใ€‚ - -ใใ—ใฆใ€Gunicornไบ’ๆ›ใฎ**Uvicornใƒฏใƒผใ‚ซใƒผ**ใ‚ฏใƒฉใ‚นใŒใ€FastAPIใŒไฝฟใˆใ‚‹ใ‚ˆใ†ใซใ€Gunicornใ‹ใ‚‰้€ใ‚‰ใ‚ŒใฆใใŸใƒ‡ใƒผใ‚ฟใ‚’ASGIๆจ™ๆบ–ใซๅค‰ๆ›ใ™ใ‚‹ๅฝนๅ‰ฒใ‚’ๆ‹…ใ„ใพใ™ใ€‚ - -## GunicornใจUvicornใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ - -
- -```console -$ pip install "uvicorn[standard]" gunicorn - ----> 100% -``` - -
- -ใ“ใ‚Œใซใ‚ˆใ‚ŠUvicornใจ๏ผˆ้ซ˜ๆ€ง่ƒฝใ‚’ๅพ—ใ‚‹ใŸใ‚ใฎ๏ผ‰ๆจ™ๆบ–๏ผˆ`standard`๏ผ‰ใฎ่ฟฝๅŠ ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใจGunicornใฎไธกๆ–นใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใพใ™ใ€‚ - -## Uvicornใฎใƒฏใƒผใ‚ซใƒผใจใจใ‚‚ใซGunicornใ‚’ๅฎŸ่กŒใ™ใ‚‹ - -Gunicornใ‚’ไปฅไธ‹ใฎใ‚ˆใ†ใซ่ตทๅ‹•ใ•ใ›ใ‚‹ใ“ใจใŒใงใใพใ™: +`fastapi` ใ‚ณใƒžใƒณใƒ‰ใ‚’ไฝฟใ†ๅ ดๅˆ๏ผš
```console -$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80 - -[19499] [INFO] Starting gunicorn 20.1.0 -[19499] [INFO] Listening at: http://0.0.0.0:80 (19499) -[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker -[19511] [INFO] Booting worker with pid: 19511 -[19513] [INFO] Booting worker with pid: 19513 -[19514] [INFO] Booting worker with pid: 19514 -[19515] [INFO] Booting worker with pid: 19515 -[19511] [INFO] Started server process [19511] -[19511] [INFO] Waiting for application startup. -[19511] [INFO] Application startup complete. -[19513] [INFO] Started server process [19513] -[19513] [INFO] Waiting for application startup. -[19513] [INFO] Application startup complete. -[19514] [INFO] Started server process [19514] -[19514] [INFO] Waiting for application startup. -[19514] [INFO] Application startup complete. -[19515] [INFO] Started server process [19515] -[19515] [INFO] Waiting for application startup. -[19515] [INFO] Application startup complete. -``` - -
- -ใใ‚Œใžใ‚Œใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฎๆ„ๅ‘ณใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†๏ผš - -* `main:app`๏ผš `main`ใฏ"`main`"ใจใ„ใ†ๅๅ‰ใฎPythonใƒขใ‚ธใƒฅใƒผใƒซใ€ใคใพใ‚Šใƒ•ใ‚กใ‚คใƒซ`main.py`ใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใใ—ใฆ `app` ใฏ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅค‰ๆ•ฐๅใงใ™ใ€‚ - * main:app`ใฏPythonใฎ`import`ๆ–‡ใจๅŒใ˜ใ‚ˆใ†ใชใ‚‚ใฎใ ใจๆƒณๅƒใงใใพใ™๏ผš - - ```Python - from main import app - ``` - - * ใคใพใ‚Šใ€`main:app`ใฎใ‚ณใƒญใƒณใฏใ€`from main import app`ใฎPythonใฎ`import`ใฎ้ƒจๅˆ†ใจๅŒใ˜ใซใชใ‚Šใพใ™ใ€‚ +$ fastapi run --workers 4 main.py -* `--workers`๏ผš ไฝฟ็”จใ™ใ‚‹ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใฎๆ•ฐใงใ€ใใ‚Œใžใ‚ŒใŒUvicornใฎใƒฏใƒผใ‚ซใƒผใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ + FastAPI Starting production server ๐Ÿš€ -* `--worker-class`๏ผš ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใงไฝฟ็”จใ™ใ‚‹Gunicornไบ’ๆ›ใฎใƒฏใƒผใ‚ซใƒผใ‚ฏใƒฉใ‚นใงใ™ใ€‚ - * ใ“ใ“ใงใฏGunicornใŒใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟ็”จใงใใ‚‹ใ‚ฏใƒฉใ‚นใ‚’ๆธกใ—ใพใ™๏ผš + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp - ```Python - import uvicorn.workers.UvicornWorker - ``` + module ๐Ÿ main.py -* `--bind`๏ผš Gunicornใซใƒชใƒƒใ‚นใƒณใ™ใ‚‹IPใจใƒใƒผใƒˆใ‚’ไผใˆใพใ™ใ€‚ใ‚ณใƒญใƒณ(`:`)ใงIPใจใƒใƒผใƒˆใ‚’ๅŒบๅˆ‡ใ‚Šใพใ™ใ€‚ - * Uvicornใ‚’็›ดๆŽฅๅฎŸ่กŒใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€`--bind 0.0.0.0:80` ๏ผˆGunicornใฎใ‚ชใƒ—ใ‚ทใƒงใƒณ๏ผ‰ใฎไปฃใ‚ใ‚Šใซใ€`--host 0.0.0.0`ใจ `--port 80`ใ‚’ไฝฟใ„ใพใ™ใ€‚ + code Importing the FastAPI app object from the module with the + following code: -ๅ‡บๅŠ›ใงใฏใ€ๅ„ใƒ—ใƒญใ‚ปใ‚นใฎ**PID**๏ผˆใƒ—ใƒญใ‚ปใ‚นID๏ผ‰ใŒ่กจ็คบใ•ใ‚Œใฆใ„ใ‚‹ใฎใŒใ‚ใ‹ใ‚Šใพใ™๏ผˆๅ˜ใชใ‚‹ๆ•ฐๅญ—ใงใ™๏ผ‰ใ€‚ + from main import app -ไปฅไธ‹ใฎ้€šใ‚Šใงใ™๏ผš + app Using import string: main:app -* Gunicornใฎ**ใƒ—ใƒญใ‚ปใ‚นใƒปใƒžใƒใƒผใ‚ธใƒฃใƒผ**ใฏPID `19499`๏ผˆใ‚ใชใŸใฎๅ ดๅˆใฏ้•ใ†็•ชๅทใงใ—ใ‚‡ใ†๏ผ‰ใงๅง‹ใพใ‚Šใพใ™ใ€‚ -* ๆฌกใซใ€`Listening at: http://0.0.0.0:80`ใ‚’้–‹ๅง‹ใ—ใพใ™ใ€‚ -* ใใ‚Œใ‹ใ‚‰ `uvicorn.workers.UvicornWorker` ใงใƒฏใƒผใ‚ซใƒผใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆคœๅ‡บใ—ใพใ™ใ€‚ -* ใใ—ใฆใ€**4ใคใฎใƒฏใƒผใ‚ซใƒผ**ใ‚’่ตทๅ‹•ใ—ใพใ™ใ€‚ใใ‚Œใžใ‚Œใฎใƒฏใƒผใ‚ซใƒผใฎPIDใฏใ€`19511`ใ€`19513`ใ€`19514`ใ€`19515`ใงใ™ใ€‚ + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs -GunicornใฏใพใŸใ€ใƒฏใƒผใ‚ซใƒผใฎๆ•ฐใ‚’็ถญๆŒใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใงใ‚ใ‚Œใฐใ€**ใƒ€ใ‚ฆใƒณใ—ใŸใƒ—ใƒญใ‚ปใ‚น**ใ‚’็ฎก็†ใ—ใ€**ๆ–ฐใ—ใ„ใƒ—ใƒญใ‚ปใ‚นใ‚’**ๅ†่ตทๅ‹•**ใ•ใ›ใพใ™ใ€‚ใใฎใŸใ‚ใ€ไธŠ่จ˜ใฎใƒชใ‚นใƒˆใซใ‚ใ‚‹**ๅ†่ตทๅ‹•**ใฎๆฆ‚ๅฟตใซไธ€้ƒจๅฝน็ซ‹ใกใพใ™ใ€‚ + Logs: -ใ—ใ‹ใ—ใชใŒใ‚‰ใ€ๅฟ…่ฆใงใ‚ใ‚ŒใฐGunicornใ‚’**ๅ†่ตทๅ‹•**ใ•ใ›ใ€**่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒ**ใ•ใ›ใ‚‹ใชใฉใ€ๅค–้ƒจใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใ‚’ๆŒใŸใ›ใ‚‹ใ“ใจใ‚‚ๅฟ…่ฆใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` -## Uvicornใจใƒฏใƒผใ‚ซใƒผ + -Uvicornใซใฏ่ค‡ๆ•ฐใฎ**ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’่ตทๅ‹•ใ—ๅฎŸ่กŒใ™ใ‚‹ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +//// -ใจใฏใ„ใ†ใ‚‚ใฎใฎใ€ไปŠใฎใจใ“ใ‚Uvicornใฎใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใ‚’ๆ‰ฑใ†ๆฉŸ่ƒฝใฏGunicornใ‚ˆใ‚Šใ‚‚ๅˆถ้™ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ใ“ใฎใƒฌใƒ™ใƒซ๏ผˆPythonใƒฌใƒ™ใƒซ๏ผ‰ใงใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผใ‚’ๆŒใกใŸใ„ใฎใงใ‚ใ‚Œใฐใ€Gunicornใ‚’ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผใจใ—ใฆไฝฟใฃใฆใฟใŸๆ–นใŒ่ณขๆ˜Žใ‹ใ‚‚ใ—ใ‚Œใชใ„ใงใ™ใ€‚ +//// tab | `uvicorn` -ใฉใ‚“ใชๅ ดๅˆใงใ‚ใ‚Œใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซๅฎŸ่กŒใ—ใพใ™๏ผš +`uvicorn` ใ‚ณใƒžใƒณใƒ‰ใ‚’็›ดๆŽฅไฝฟใ„ใŸใ„ๅ ดๅˆ๏ผš
@@ -150,36 +105,35 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
-ใ“ใ“ใงๅ”ฏไธ€ใฎๆ–ฐใ—ใ„ใ‚ชใƒ—ใ‚ทใƒงใƒณใฏ `--workers` ใงใ€Uvicornใซ4ใคใฎใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใ‚’่ตทๅ‹•ใ™ใ‚‹ใ‚ˆใ†ใซๆŒ‡็คบใ—ใฆใ„ใพใ™ใ€‚ +//// -ๅ„ใƒ—ใƒญใ‚ปใ‚นใฎ **PID** ใŒ่กจ็คบใ•ใ‚Œใ€่ฆชใƒ—ใƒญใ‚ปใ‚นใฎ `27365` (ใ“ใ‚Œใฏ **ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**) ใจใ€ๅ„ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚นใฎ **PID** ใŒ่กจ็คบใ•ใ‚Œใพใ™๏ผš `27368`ใ€`27369`ใ€`27370`ใ€`27367`ใซใชใ‚Šใพใ™ใ€‚ +ใ“ใ“ใงๅ”ฏไธ€ใฎๆ–ฐใ—ใ„ใ‚ชใƒ—ใ‚ทใƒงใƒณใฏ `--workers` ใงใ€Uvicornใซ4ใคใฎใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚นใ‚’่ตทๅ‹•ใ™ใ‚‹ใ‚ˆใ†ใซๆŒ‡็คบใ—ใฆใ„ใพใ™ใ€‚ -## ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ +ๅ„ใƒ—ใƒญใ‚ปใ‚นใฎ **PID** ใ‚‚่กจ็คบใ•ใ‚Œใฆใ„ใฆใ€่ฆชใƒ—ใƒญใ‚ปใ‚น๏ผˆใ“ใ‚Œใฏ**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใƒผ**๏ผ‰ใŒ `27365`ใ€ๅ„ใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚นใŒใใ‚Œใžใ‚Œ `27368`ใ€`27369`ใ€`27370`ใ€`27367` ใงใ™ใ€‚ -ใ“ใ“ใงใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅฎŸ่กŒใ‚’**ไธฆๅˆ—ๅŒ–**ใ—ใ€CPUใฎ**ใƒžใƒซใƒใ‚ณใ‚ข**ใ‚’ๆดป็”จใ—ใ€**ใ‚ˆใ‚Šๅคšใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใซๅฏพๅฟœใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใซใ€**Gunicorn**๏ผˆใพใŸใฏUvicorn๏ผ‰ใ‚’ไฝฟ็”จใ—ใฆ**Uvicornใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น**ใ‚’็ฎก็†ใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ—ใŸใ€‚ +## ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ { #deployment-concepts } -ไธŠ่จ˜ใฎใƒ‡ใƒ—ใƒญใ‚คใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆใฎใƒชใ‚นใƒˆใ‹ใ‚‰ใ€ใƒฏใƒผใ‚ซใƒผใ‚’ไฝฟใ†ใ“ใจใฏไธปใซ**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใฎ้ƒจๅˆ†ใจใ€**ๅ†่ตทๅ‹•**ใ‚’ๅฐ‘ใ—ๅŠฉใ‘ใฆใใ‚Œใพใ™๏ผš +ใ“ใ“ใงใฏใ€่ค‡ๆ•ฐใฎ **ใƒฏใƒผใ‚ซใƒผ** ใ‚’ไฝฟใฃใฆใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅฎŸ่กŒใ‚’**ไธฆๅˆ—ๅŒ–**ใ—ใ€CPUใฎ**่ค‡ๆ•ฐใ‚ณใ‚ข**ใ‚’ๆดป็”จใ—ใฆใ€**ใ‚ˆใ‚Šๅคšใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใ‚’ๅ‡ฆ็†ใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚ -* ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS -* ่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ -* ๅ†่ตทๅ‹• -* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ -* ใƒกใƒขใƒชใƒผ -* ้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใฎใ‚นใƒ†ใƒƒใƒ— +ไธŠใฎใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆใฎใƒชใ‚นใƒˆใ‹ใ‚‰ใ€ใƒฏใƒผใ‚ซใƒผใ‚’ไฝฟใ†ใ“ใจใฏไธปใซ**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใฎ้ƒจๅˆ†ใจใ€**ๅ†่ตทๅ‹•**ใ‚’ๅฐ‘ใ—ๅŠฉใ‘ใฆใใ‚Œใพใ™ใŒใ€ใใ‚Œไปฅๅค–ใซใคใ„ใฆใฏๅผ•ใ็ถšใๅฏพๅ‡ฆใŒๅฟ…่ฆใงใ™๏ผš +* **ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS** +* **่ตทๅ‹•ๆ™‚ใฎๅฎŸ่กŒ** +* ***ๅ†่ตทๅ‹•*** +* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒไธญใฎใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ +* **ใƒกใƒขใƒช** +* **้–‹ๅง‹ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ—** -## ใ‚ณใƒณใƒ†ใƒŠใจDocker - -ๆฌก็ซ ใฎ[ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}ใงใฏใ€ใใฎไป–ใฎ**ใƒ‡ใƒ—ใƒญใ‚คใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใ‚’ๆ‰ฑใ†ใŸใ‚ใซๅฎŸๆ–ฝใ™ใ‚‹ใงใ‚ใ‚ใ†ๆˆฆ็•ฅใ‚’ใ„ใใคใ‹็ดนไป‹ใ—ใพใ™ใ€‚ +## ใ‚ณใƒณใƒ†ใƒŠใจDocker { #containers-and-docker } -ใพใŸใ€**GunicornใจUvicornใƒฏใƒผใ‚ซใƒผ**ใ‚’ๅซใ‚€**ๅ…ฌๅผDockerใ‚คใƒกใƒผใ‚ธ**ใจใ€็ฐกๅ˜ใชใ‚ฑใƒผใ‚นใซๅฝน็ซ‹ใคใ„ใใคใ‹ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ่จญๅฎšใ‚‚็ดนไป‹ใ—ใพใ™ใ€‚ +ๆฌก็ซ ใฎ[ใ‚ณใƒณใƒ†ใƒŠๅ†…ใฎFastAPI - Docker](docker.md){.internal-link target=_blank}ใงใฏใ€ใใฎไป–ใฎ**ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใ‚’ๆ‰ฑใ†ใŸใ‚ใซไฝฟใˆใ‚‹ๆˆฆ็•ฅใ‚’ใ„ใใคใ‹่ชฌๆ˜Žใ—ใพใ™ใ€‚ -ใพใŸใ€(Gunicornใ‚’ไฝฟใ‚ใšใซ)Uvicornใƒ—ใƒญใ‚ปใ‚นใ‚’1ใคใ ใ‘ๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใซใ€**ใ‚ผใƒญใ‹ใ‚‰็‹ฌ่‡ชใฎใ‚คใƒกใƒผใ‚ธใ‚’**ๆง‹็ฏ‰ใ™ใ‚‹ๆ–นๆณ•ใ‚‚็ดนไป‹ใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ็ฐกๅ˜ใชใƒ—ใƒญใ‚ปใ‚นใงใ€ใŠใใ‚‰ใ**Kubernetes**ใฎใ‚ˆใ†ใชๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใ†ใจใใซใ‚„ใ‚ŠใŸใ„ใ“ใจใงใ—ใ‚‡ใ†ใ€‚ +ๅ˜ไธ€ใฎUvicornใƒ—ใƒญใ‚ปใ‚นใ‚’ๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใซใ€**ใ‚ผใƒญใ‹ใ‚‰็‹ฌ่‡ชใฎใ‚คใƒกใƒผใ‚ธใ‚’ๆง‹็ฏ‰ใ™ใ‚‹**ๆ–นๆณ•ใ‚‚็ดนไป‹ใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ็ฐกๅ˜ใชใƒ—ใƒญใ‚ปใ‚นใงใ€**Kubernetes**ใฎใ‚ˆใ†ใชๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใ†ๅ ดๅˆใซใ€ใŠใใ‚‰ใใ‚„ใ‚ŠใŸใ„ใ“ใจใงใ—ใ‚‡ใ†ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #recap } -Uvicornใƒฏใƒผใ‚ซใƒผใ‚’ไฝฟใฃใŸใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃใจใ—ใฆ**Gunicorn**๏ผˆใพใŸใฏUvicorn๏ผ‰ใ‚’ไฝฟใˆใฐใ€**ใƒžใƒซใƒใ‚ณใ‚ขCPU**ใ‚’ๆดป็”จใ—ใฆ**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ไธฆๅˆ—ๅฎŸ่กŒ**ใงใใพใ™ใ€‚ +`fastapi` ใพใŸใฏ `uvicorn` ใ‚ณใƒžใƒณใƒ‰ใง `--workers` CLIใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟใ†ใ“ใจใงใ€**ใƒžใƒซใƒใ‚ณใ‚ขCPU**ใ‚’ๆดป็”จใ—ใ€**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ไธฆๅˆ—ๅฎŸ่กŒ**ใงใใ‚‹ใ‚ˆใ†ใซ่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚นใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎใƒ„ใƒผใƒซใ‚„ใ‚ขใ‚คใƒ‡ใ‚ขใฏใ€**ใ‚ใชใŸ่‡ช่บซใฎใƒ‡ใƒ—ใƒญใ‚คใ‚ทใ‚นใƒ†ใƒ **ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ—ใชใŒใ‚‰ใ€ไป–ใฎใƒ‡ใƒ—ใƒญใ‚คใ‚ณใƒณใ‚ปใƒ—ใƒˆใ‚’่‡ชๅˆ†ใง่กŒใ†ๅ ดๅˆใซใ‚‚ไฝฟใˆใพใ™ใ€‚ +ไป–ใฎใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆใ‚’่‡ชๅˆ†ใงๅฏพๅฟœใ—ใชใŒใ‚‰ใ€**็‹ฌ่‡ชใฎใƒ‡ใƒ—ใƒญใ‚คใ‚ทใ‚นใƒ†ใƒ **ใ‚’ๆง‹็ฏ‰ใ—ใฆใ„ใ‚‹ๅ ดๅˆใซใ‚‚ใ€ใ“ใ‚Œใ‚‰ใฎใƒ„ใƒผใƒซใ‚„ใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ไฝฟใˆใพใ™ใ€‚ -ๆฌกใฎ็ซ ใงใฏใ€ใ‚ณใƒณใƒ†ใƒŠ๏ผˆDockerใ‚„Kubernetesใชใฉ๏ผ‰ใ‚’ไฝฟใฃใŸ**FastAPI**ใซใคใ„ใฆๅญฆใ‚“ใงใ„ใใพใ—ใ‚‡ใ†ใ€‚ใ“ใ‚Œใ‚‰ใฎใƒ„ใƒผใƒซใซใฏใ€ไป–ใฎ**ใƒ‡ใƒ—ใƒญใ‚คใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใ‚‚่งฃๆฑบใ™ใ‚‹็ฐกๅ˜ใชๆ–นๆณ•ใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚โœจ +ๆฌกใฎ็ซ ใงใ€ใ‚ณใƒณใƒ†ใƒŠ๏ผˆไพ‹๏ผšDockerใ‚„Kubernetes๏ผ‰ใ‚’ไฝฟใฃใŸ **FastAPI** ใซใคใ„ใฆๅญฆใณใพใ—ใ‚‡ใ†ใ€‚ใ“ใ‚Œใ‚‰ใฎใƒ„ใƒผใƒซใซใ‚‚ใ€ไป–ใฎ**ใƒ‡ใƒ—ใƒญใ‚คใƒกใƒณใƒˆใฎใ‚ณใƒณใ‚ปใƒ—ใƒˆ**ใ‚’่งฃๆฑบใ™ใ‚‹็ฐกๅ˜ใชๆ–นๆณ•ใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚โœจ diff --git a/docs/ja/docs/deployment/versions.md b/docs/ja/docs/deployment/versions.md index 7575fc4f70..7980b8be2a 100644 --- a/docs/ja/docs/deployment/versions.md +++ b/docs/ja/docs/deployment/versions.md @@ -1,93 +1,93 @@ -# FastAPIใฎใƒใƒผใ‚ธใƒงใƒณใซใคใ„ใฆ +# FastAPIใฎใƒใƒผใ‚ธใƒงใƒณใซใคใ„ใฆ { #about-fastapi-versions } -**FastAPI** ใฏๆ—ขใซๅคšใใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚„ใ‚ทใ‚นใƒ†ใƒ ใซๆœฌ็•ช็’ฐๅขƒใงไฝฟใ‚ใ‚Œใฆใ„ใพใ™ใ€‚ใพใŸใ€100%ใฎใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธใ‚’็ถญๆŒใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๆดป็™บใช้–‹็™บใŒ็ถšใ„ใฆใ„ใพใ™ใ€‚ +**FastAPI** ใฏใ™ใงใซๅคšใใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚„ใ‚ทใ‚นใƒ†ใƒ ใงๆœฌ็•ช็’ฐๅขƒใซใฆไฝฟใ‚ใ‚Œใฆใ„ใพใ™ใ€‚ใพใŸใ€ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธใฏ 100% ใซ็ถญๆŒใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€้–‹็™บใฏไพ็„ถใจใ—ใฆๆ€ฅ้€Ÿใซ้€ฒใ‚“ใงใ„ใพใ™ใ€‚ -้ซ˜้ ปๅบฆใงๆ–ฐๆฉŸ่ƒฝใŒ่ฟฝๅŠ ใ•ใ‚Œใ€ๅฎšๆœŸ็š„ใซใƒใ‚ฐใŒไฟฎๆญฃใ•ใ‚Œใ€ๅฎŸ่ฃ…ใฏ็ถ™็ถš็š„ใซๆ”นๅ–„ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +ๆ–ฐๆฉŸ่ƒฝใŒ้ซ˜้ ปๅบฆใง่ฟฝๅŠ ใ•ใ‚Œใ€ๅฎšๆœŸ็š„ใซใƒใ‚ฐใŒไฟฎๆญฃใ•ใ‚Œใ€ใ‚ณใƒผใƒ‰ใฏ็ถ™็ถš็š„ใซๆ”นๅ–„ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ ใ“ใ‚ŒใŒ็พๅœจใฎใƒใƒผใ‚ธใƒงใƒณใŒใ„ใพใ ใซ `0.x.x` ใช็†็”ฑใงใ‚ใ‚Šใ€ใใ‚Œใžใ‚Œใฎใƒใƒผใ‚ธใƒงใƒณใฏ็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใŒใชใ•ใ‚Œใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใ‚ปใƒžใƒณใƒ†ใ‚ฃใƒƒใ‚ฏ ใƒใƒผใ‚ธใƒงใƒ‹ใƒณใ‚ฐใฎ่ฆๅ‰‡ใซๅ‰‡ใฃใฆใ„ใพใ™ใ€‚ -**FastAPI** ใ‚’ไฝฟ็”จใ™ใ‚‹ใจๆœฌ็•ช็”จใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใ™ใใซไฝœๆˆใงใใพใ™ใŒ (ใ™ใงใซไฝ•ๅบฆใ‚‚็ตŒ้จ“ใ—ใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใŒ)ใ€ๆฎ‹ใ‚Šใฎใ‚ณใƒผใƒ‰ใŒๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ใƒใƒผใ‚ธใƒงใƒณใชใฎใ‹็ขบ่ชใ—ใชใ‘ใ‚Œใฐใ„ใ‘ใพใ›ใ‚“ใ€‚ +**FastAPI** ใ‚’ไฝฟ็”จใ™ใ‚‹ใจๆœฌ็•ช็”จใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ไปŠใ™ใไฝœๆˆใงใใพใ™๏ผˆใใ—ใฆใ€ใŠใใ‚‰ใใ‚ใชใŸใฏใ—ใฐใ‚‰ใๅ‰ใ‹ใ‚‰ใใ†ใ—ใฆใ„ใ‚‹ใฏใšใงใ™๏ผ‰ใ€‚ๅฟ…่ฆใชใฎใฏใ€ๆฎ‹ใ‚Šใฎใ‚ณใƒผใƒ‰ใจๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ใ“ใจใ ใ‘ใงใ™ใ€‚ -## `fastapi` ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๅ›บๅฎš +## `fastapi` ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๅ›บๅฎš { #pin-your-fastapi-version } -ๆœ€ๅˆใซใ™ในใใ“ใจใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ **FastAPI** ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๅ›บๅฎšใ™ใ‚‹ใ“ใจใงใ™ใ€‚ +ๆœ€ๅˆใซใ™ในใใ“ใจใฏใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹ **FastAPI** ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ใ“ใจใŒๅˆ†ใ‹ใฃใฆใ„ใ‚‹็‰นๅฎšใฎๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใซใ€Œๅ›บๅฎš๏ผˆpin๏ผ‰ใ€ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ -ไพ‹ใˆใฐใ€ใƒใƒผใ‚ธใƒงใƒณ `0.45.0` ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ +ไพ‹ใˆใฐใ€ใ‚ขใƒ—ใƒชใงใƒใƒผใ‚ธใƒงใƒณ `0.112.0` ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ -`requirements.txt` ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใชใ‚‰ใ€ไปฅไธ‹ใฎๆง˜ใซใƒใƒผใ‚ธใƒงใƒณใ‚’ๆŒ‡ๅฎšใงใใพใ™: +`requirements.txt` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟใ†ๅ ดๅˆใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใƒใƒผใ‚ธใƒงใƒณใ‚’ๆŒ‡ๅฎšใงใใพใ™: ```txt -fastapi==0.45.0 +fastapi[standard]==0.112.0 ``` -ใ“ใ‚Œใฏใ€ๅŽณๅฏ†ใซใƒใƒผใ‚ธใƒงใƒณ `0.45.0` ใ ใ‘ใ‚’ไฝฟใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€ๅŽณๅฏ†ใซใƒใƒผใ‚ธใƒงใƒณ `0.112.0` ใ ใ‘ใ‚’ไฝฟใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -ใพใŸใฏใ€ไปฅไธ‹ใฎๆง˜ใซๅ›บๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: +ใพใŸใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซๅ›บๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: ```txt -fastapi>=0.45.0,<0.46.0 +fastapi[standard]>=0.112.0,<0.113.0 ``` -ใ“ใ‚Œใฏ `0.45.0` ไปฅไธŠใ€`0.46.0` ๆœชๆบ€ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒใƒผใ‚ธใƒงใƒณ `0.45.2` ใฏไฝฟ็”จๅฏ่ƒฝใงใ™ใ€‚ +ใ“ใ‚Œใฏ `0.112.0` ไปฅไธŠใ€`0.113.0` ๆœชๆบ€ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒใƒผใ‚ธใƒงใƒณ `0.112.2` ใฏไฝฟ็”จๅฏ่ƒฝใงใ™ใ€‚ -Poetryใ‚„Pipenvใชใฉใ€ไป–ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ็ฎก็†ใƒ„ใƒผใƒซใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใงใ‚‚ใ€ใใ‚Œใžใ‚Œใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ๆฉŸ่ƒฝใŒใ‚ใ‚Šใพใ™ใ€‚ +`uv`ใ€Poetryใ€Pipenv ใชใฉใ€ไป–ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ็ฎก็†ใƒ„ใƒผใƒซใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใงใ‚‚ใ€ใ„ใšใ‚Œใ‚‚ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎ็‰นๅฎšใƒใƒผใ‚ธใƒงใƒณใ‚’ๅฎš็พฉใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ -## ๅˆฉ็”จๅฏ่ƒฝใชใƒใƒผใ‚ธใƒงใƒณ +## ๅˆฉ็”จๅฏ่ƒฝใชใƒใƒผใ‚ธใƒงใƒณ { #available-versions } -[Release Notes](../release-notes.md){.internal-link target=_blank}ใงๅˆฉ็”จๅฏ่ƒฝใชใƒใƒผใ‚ธใƒงใƒณใŒ็ขบ่ชใงใใพใ™ (็พๅœจใฎๆœ€ๆ–ฐ็‰ˆใฎ็ขบ่ชใชใฉใฎใŸใ‚)ใ€‚ +ๅˆฉ็”จๅฏ่ƒฝใชใƒใƒผใ‚ธใƒงใƒณ๏ผˆไพ‹: ็พๅœจใฎๆœ€ๆ–ฐใŒไฝ•ใ‹ใ‚’็ขบ่ชใ™ใ‚‹ใŸใ‚๏ผ‰ใฏใ€[Release Notes](../release-notes.md){.internal-link target=_blank} ใง็ขบ่ชใงใใพใ™ใ€‚ -## ใƒใƒผใ‚ธใƒงใƒณใซใคใ„ใฆ +## ใƒใƒผใ‚ธใƒงใƒณใซใคใ„ใฆ { #about-versions } -ใ‚ปใƒžใƒณใƒ†ใ‚ฃใƒƒใ‚ฏ ใƒใƒผใ‚ธใƒงใƒ‹ใƒณใ‚ฐใฎ่ฆ็ด„ใซๅพ“ใฃใฆใ€`1.0.0` ๆœชๆบ€ใฎๅ…จใฆใฎใƒใƒผใ‚ธใƒงใƒณใฏ็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใŒๅŠ ใ‚ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ‚ปใƒžใƒณใƒ†ใ‚ฃใƒƒใ‚ฏ ใƒใƒผใ‚ธใƒงใƒ‹ใƒณใ‚ฐใฎ่ฆ็ด„ใซๅพ“ใฃใฆใ€`1.0.0` ๆœชๆบ€ใฎใƒใƒผใ‚ธใƒงใƒณใฏ็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใŒๅŠ ใ‚ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -FastAPIใงใฏใ€Œใƒ‘ใƒƒใƒใ€ใƒใƒผใ‚ธใƒงใƒณใฏใƒใ‚ฐไฟฎๆญฃใจ้ž็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใซ็•™ใ‚ใ‚‹ใจใ„ใ†่ฆ็ด„ใซๅพ“ใฃใฆใ„ใพใ™ใ€‚ +FastAPI ใงใฏใ€ŒPATCHใ€ใƒใƒผใ‚ธใƒงใƒณใฎๅค‰ๆ›ดใฏใƒใ‚ฐไฟฎๆญฃใจ้ž็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใซไฝฟใ†ใ€ใจใ„ใ†่ฆ็ด„ใซใ‚‚ๅพ“ใฃใฆใ„ใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ€Œใƒ‘ใƒƒใƒใ€ใฏๆœ€ๅพŒใฎๆ•ฐๅญ—ใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ไพ‹ใˆใฐใ€`0.2.3` ใงใฏใƒ‘ใƒƒใƒใƒใƒผใ‚ธใƒงใƒณใฏ `3` ใงใ™ใ€‚ +ใ€ŒPATCHใ€ใฏๆœ€ๅพŒใฎๆ•ฐๅญ—ใงใ™ใ€‚ไพ‹ใˆใฐใ€`0.2.3` ใงใฏ PATCH ใƒใƒผใ‚ธใƒงใƒณใฏ `3` ใงใ™ใ€‚ /// -ๅพ“ใฃใฆใ€ไปฅไธ‹ใฎๆง˜ใชใƒใƒผใ‚ธใƒงใƒณใฎๅ›บๅฎšใŒๆœ›ใพใ—ใ„ใงใ™: +ๅพ“ใฃใฆใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชใƒใƒผใ‚ธใƒงใƒณใฎๅ›บๅฎšใŒใงใใ‚‹ใฏใšใงใ™: ```txt fastapi>=0.45.0,<0.46.0 ``` -็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใจๆ–ฐๆฉŸ่ƒฝๅฎŸ่ฃ…ใฏใ€Œใƒžใ‚คใƒŠใƒผใ€ใƒใƒผใ‚ธใƒงใƒณใงๅŠ ใˆใ‚‰ใ‚Œใพใ™ใ€‚ +็ ดๅฃŠ็š„ใชๅค‰ๆ›ดใจๆ–ฐๆฉŸ่ƒฝใฏใ€ŒMINORใ€ใƒใƒผใ‚ธใƒงใƒณใง่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ€Œใƒžใ‚คใƒŠใƒผใ€ใฏ็œŸใ‚“ไธญใฎๆ•ฐๅญ—ใงใ™ใ€‚ไพ‹ใˆใฐใ€`0.2.3` ใงใฏใƒžใ‚คใƒŠใƒผใƒใƒผใ‚ธใƒงใƒณใฏ `2` ใงใ™ใ€‚ +ใ€ŒMINORใ€ใฏ็œŸใ‚“ไธญใฎๆ•ฐๅญ—ใงใ™ใ€‚ไพ‹ใˆใฐใ€`0.2.3` ใงใฏ MINOR ใƒใƒผใ‚ธใƒงใƒณใฏ `2` ใงใ™ใ€‚ /// -## FastAPIใฎใƒใƒผใ‚ธใƒงใƒณใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ +## FastAPIใฎใƒใƒผใ‚ธใƒงใƒณใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ { #upgrading-the-fastapi-versions } -ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒ†ใ‚นใƒˆใ‚’ๅŠ ใˆใ‚‹ในใใงใ™ใ€‚ +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒ†ใ‚นใƒˆใ‚’่ฟฝๅŠ ใ™ในใใงใ™ใ€‚ -**FastAPI** ใงใฏ้žๅธธใซ็ฐกๅ˜ใซๅฎŸ็พใงใใพใ™ (StarletteใฎใŠใ‹ใ’ใง)ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ—ใฆไธ‹ใ•ใ„: [ใƒ†ใ‚นใƒˆ](../tutorial/testing.md){.internal-link target=_blank} +**FastAPI** ใงใฏ้žๅธธใซ็ฐกๅ˜ใซๅฎŸ็พใงใใพใ™๏ผˆStarlette ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ—ใฆไธ‹ใ•ใ„: [ใƒ†ใ‚นใƒˆ](../tutorial/testing.md){.internal-link target=_blank} -ใƒ†ใ‚นใƒˆใ‚’ๅŠ ใˆใŸๅพŒใงใ€**FastAPI** ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ˆใ‚Šๆœ€ๆ–ฐใฎใ‚‚ใฎใซใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใ€ใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใงๅ…จใฆใฎใ‚ณใƒผใƒ‰ใŒๆญฃๅธธใซๅ‹•ไฝœใ™ใ‚‹ใ‹็ขบ่ชใงใใพใ™ใ€‚ +ใƒ†ใ‚นใƒˆใ‚’่ฟฝๅŠ ใ—ใŸใ‚‰ใ€**FastAPI** ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ˆใ‚Šๆ–ฐใ—ใ„ใ‚‚ใฎใซใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใ€ใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ“ใจใงๅ…จใฆใฎใ‚ณใƒผใƒ‰ใŒๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ใ‹็ขบ่ชใงใใพใ™ใ€‚ -ๅ…จใฆใŒๅ‹•ไฝœใ™ใ‚‹ใ‹ใ€ไฟฎๆญฃใ‚’่กŒใฃใŸไธŠใงๅ…จใฆใฎใƒ†ใ‚นใƒˆใ‚’้€š้Žใ—ใŸๅ ดๅˆใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹`fastapi` ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ˆใ‚Šๆœ€ๆ–ฐใฎใƒใƒผใ‚ธใƒงใƒณใซๅ›บๅฎšใงใใพใ™ใ€‚ +ๅ…จใฆใŒๅ‹•ไฝœใ™ใ‚‹ใ€ใพใŸใฏๅฟ…่ฆใชๅค‰ๆ›ดใ‚’่กŒใฃใŸๅพŒใซๅ…จใฆใฎใƒ†ใ‚นใƒˆใŒ้€šใ‚‹ใชใ‚‰ใ€ใใฎๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณใซ `fastapi` ใ‚’ๅ›บๅฎšใงใใพใ™ใ€‚ -## Starletteใซใคใ„ใฆ +## Starletteใซใคใ„ใฆ { #about-starlette } -`Starlette` ใฎใƒใƒผใ‚ธใƒงใƒณใฏๅ›บๅฎšใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +`starlette` ใฎใƒใƒผใ‚ธใƒงใƒณใฏๅ›บๅฎšใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -**FastAPI** ใฏใ€ใƒใƒผใ‚ธใƒงใƒณๆฏŽใซStarletteใฎใ‚ˆใ‚Šๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ +**FastAPI** ใฎใƒใƒผใ‚ธใƒงใƒณใŒ็•ฐใชใ‚Œใฐใ€Starlette ใฎ็‰นๅฎšใฎใ‚ˆใ‚Šๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณใŒไฝฟใ‚ใ‚Œใพใ™ใ€‚ -ใ‚ˆใฃใฆใ€ๆœ€้ฉใชStarletteใฎใƒใƒผใ‚ธใƒงใƒณ้ธๆŠžใ‚’**FastAPI** ใซไปปใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใใฎใŸใ‚ใ€ๆญฃใ—ใ„ Starlette ใƒใƒผใ‚ธใƒงใƒณใ‚’ **FastAPI** ใซไปปใ›ใ‚Œใฐใ‚ˆใ„ใงใ™ใ€‚ -## Pydanticใซใคใ„ใฆ +## Pydanticใซใคใ„ใฆ { #about-pydantic } -Pydanticใฏ่‡ช่บซใฎใƒ†ใ‚นใƒˆใ ใ‘ใงใชใ**FastAPI** ใฎใŸใ‚ใฎใƒ†ใ‚นใƒˆใ‚’ๅซใ‚“ใงใ„ใพใ™ใ€‚ใชใฎใงใ€Pydanticใฎๆ–ฐใŸใชใƒใƒผใ‚ธใƒงใƒณ ( `1.0.0` ไปฅ้™) ใฏๅ…จใฆFastAPIใจๆ•ดๅˆๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ +Pydantic ใฏ่‡ช่บซใฎใƒ†ใ‚นใƒˆใซ **FastAPI** ใฎใƒ†ใ‚นใƒˆใ‚‚ๅซใ‚“ใงใ„ใ‚‹ใŸใ‚ใ€Pydantic ใฎๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ๏ผˆ`1.0.0` ใ‚ˆใ‚ŠไธŠ๏ผ‰ใฏๅธธใซ FastAPI ใจไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -Pydanticใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ€ๅ‹•ไฝœใŒไฟ่จผใงใใ‚‹`1.0.0`ไปฅ้™ใฎใ„ใšใ‚Œใ‹ใฎใƒใƒผใ‚ธใƒงใƒณใ‹ใ‚‰`2.0.0` ๆœชๆบ€ใฎ้–“ใซๅ›บๅฎšใงใใพใ™ใ€‚ +Pydantic ใฏใ€่‡ชๅˆ†ใซใจใฃใฆๅ‹•ไฝœใ™ใ‚‹ `1.0.0` ใ‚ˆใ‚ŠไธŠใฎไปปๆ„ใฎใƒใƒผใ‚ธใƒงใƒณใซๅ›บๅฎšใงใใพใ™ใ€‚ ไพ‹ใˆใฐ: ```txt -pydantic>=1.2.0,<2.0.0 +pydantic>=2.7.0,<3.0.0 ``` diff --git a/docs/ja/docs/environment-variables.md b/docs/ja/docs/environment-variables.md index 507af3a0cc..45dbfc71fd 100644 --- a/docs/ja/docs/environment-variables.md +++ b/docs/ja/docs/environment-variables.md @@ -1,18 +1,18 @@ -# ็’ฐๅขƒๅค‰ๆ•ฐ +# ็’ฐๅขƒๅค‰ๆ•ฐ { #environment-variables } -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ใ‚‚ใ—ใ€ใ€Œ็’ฐๅขƒๅค‰ๆ•ฐใ€ใจใฏไฝ•ใ‹ใ€ใใ‚Œใ‚’ใฉใ†ไฝฟใ†ใ‹ใ‚’ๆ—ขใซ็Ÿฅใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ‚นใ‚ญใƒƒใƒ—ใ—ใฆๆง‹ใ„ใพใ›ใ‚“ใ€‚ /// -็’ฐๅขƒๅค‰ๆ•ฐ๏ผˆ**env var**ใจใ‚‚ๅ‘ผใฐใ‚Œใ‚‹๏ผ‰ใฏPythonใ‚ณใƒผใƒ‰ใฎ**ๅค–ๅด**ใ€ใคใพใ‚Š**OS**ใซๅญ˜ๅœจใ™ใ‚‹ๅค‰ๆ•ฐใงใ€Pythonใ‹ใ‚‰่ชญใฟๅ–ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚๏ผˆไป–ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ‚‚ๅŒๆง˜ใซ่ชญใฟๅ–ใ‚Œใพใ™ใ€‚๏ผ‰ +็’ฐๅขƒๅค‰ๆ•ฐ๏ผˆใ€Œ**env var**ใ€ใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™๏ผ‰ใจใฏใ€Pythonใ‚ณใƒผใƒ‰ใฎ**ๅค–ๅด**ใ€ใคใพใ‚Š**ใ‚ชใƒšใƒฌใƒผใƒ†ใ‚ฃใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ **ใซๅญ˜ๅœจใ™ใ‚‹ๅค‰ๆ•ฐใงใ€Pythonใ‚ณใƒผใƒ‰๏ผˆใพใŸใฏไป–ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผ‰ใ‹ใ‚‰่ชญใฟๅ–ใ‚Œใพใ™ใ€‚ -็’ฐๅขƒๅค‰ๆ•ฐใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ**่จญๅฎš**ใฎ็ฎก็†ใ‚„ใ€Pythonใฎ**ใ‚คใƒณใ‚นใƒˆใƒผใƒซ**ใชใฉใซๅฝน็ซ‹ใกใพใ™ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ**่จญๅฎš**ใฎๆ‰ฑใ„ใ€Pythonใฎ**ใ‚คใƒณใ‚นใƒˆใƒผใƒซ**ใฎไธ€้ƒจใชใฉใงๅฝน็ซ‹ใกใพใ™ใ€‚ -## ็’ฐๅขƒๅค‰ๆ•ฐใฎไฝœๆˆใจไฝฟ็”จ +## ็’ฐๅขƒๅค‰ๆ•ฐใฎไฝœๆˆใจไฝฟ็”จ { #create-and-use-env-vars } -็’ฐๅขƒๅค‰ๆ•ฐใฏ**ใ‚ทใ‚งใƒซ๏ผˆใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผ‰**ๅ†…ใง**ไฝœๆˆ**ใ—ใฆไฝฟ็”จใงใใ€ใใ‚Œใ‚‰ใซPythonใฏไธ่ฆใงใ™ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใฏใ€Pythonใ‚’ๅฟ…่ฆใจใ›ใšใ€**ใ‚ทใ‚งใƒซ๏ผˆใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผ‰**ใง**ไฝœๆˆ**ใ—ใฆไฝฟ็”จใงใใพใ™ใ€‚ //// tab | Linux, macOS, Windows Bash @@ -36,7 +36,6 @@ Hello Wade Wilson
- ```console // Create an env var MY_NAME $ $Env:MY_NAME = "Wade Wilson" @@ -51,9 +50,9 @@ Hello Wade Wilson //// -## Pythonใง็’ฐๅขƒๅค‰ๆ•ฐใ‚’่ชญใฟๅ–ใ‚‹ +## Pythonใง็’ฐๅขƒๅค‰ๆ•ฐใ‚’่ชญใฟๅ–ใ‚‹ { #read-env-vars-in-python } -็’ฐๅขƒๅค‰ๆ•ฐใ‚’Pythonใฎ**ๅค–ๅด**ใ€ใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผˆใ‚„ไป–ใฎๆ–นๆณ•๏ผ‰ใงไฝœๆˆใ—ใ€**Pythonๅ†…ใง่ชญใฟๅ–ใ‚‹**ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใฏPythonใฎ**ๅค–ๅด**๏ผˆใ‚ฟใƒผใƒŸใƒŠใƒซใ€ใพใŸใฏใใฎไป–ใฎๆ–นๆณ•๏ผ‰ใงไฝœๆˆใ—ใ€ใใฎๅพŒใซ**Pythonใง่ชญใฟๅ–ใ‚‹**ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€ไปฅไธ‹ใฎใ‚ˆใ†ใช`main.py`ใƒ•ใ‚กใ‚คใƒซใ‚’็”จๆ„ใ—ใพใ™: @@ -64,11 +63,11 @@ name = os.getenv("MY_NAME", "World") print(f"Hello {name} from Python") ``` -/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ -`os.getenv()` ใฎ็ฌฌ2ๅผ•ๆ•ฐใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง่ฟ”ใ•ใ‚Œใ‚‹ๅ€คใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ +`os.getenv()` ใฎ็ฌฌ2ๅผ•ๆ•ฐใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง่ฟ”ใ•ใ‚Œใ‚‹ๅ€คใงใ™ใ€‚ -ใ“ใฎๅผ•ๆ•ฐใ‚’็œ็•ฅใ™ใ‚‹ใจใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ`None`ใŒ่ฟ”ใ•ใ‚Œใพใ™ใŒใ€ใ“ใ“ใงใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ`"World"`ใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใพใ™ใ€‚ +ๆŒ‡ๅฎšใ—ใชใ„ๅ ดๅˆใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ`None`ใงใ™ใŒใ€ใ“ใ“ใงใฏไฝฟ็”จใ™ใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ`"World"`ใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใพใ™ใ€‚ /// @@ -128,11 +127,11 @@ Hello Wade Wilson from Python //// -็’ฐๅขƒๅค‰ๆ•ฐใฏใ‚ณใƒผใƒ‰ใฎๅค–ๅดใง่จญๅฎšใ—ใ€ๅ†…ๅดใ‹ใ‚‰่ชญใฟๅ–ใ‚‹ใ“ใจใŒใงใใ‚‹ใฎใงใ€ไป–ใฎใƒ•ใ‚กใ‚คใƒซใจไธ€็ท’ใซ๏ผˆ`git`ใซ๏ผ‰ไฟๅญ˜ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใฎใŸใ‚ใ€็’ฐๅขƒๅค‰ๆ•ฐใ‚’ใ‚ณใƒณใƒ•ใ‚ฃใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ‚„**่จญๅฎš**ใซไฝฟ็”จใ™ใ‚‹ใ“ใจใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใฏใ‚ณใƒผใƒ‰ใฎๅค–ๅดใง่จญๅฎšใงใใ€ใ‚ณใƒผใƒ‰ใ‹ใ‚‰่ชญใฟๅ–ใ‚Œใ€ไป–ใฎใƒ•ใ‚กใ‚คใƒซใจไธ€็ท’ใซ๏ผˆ`git`ใซ๏ผ‰ไฟๅญ˜๏ผˆใ‚ณใƒŸใƒƒใƒˆ๏ผ‰ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ใŸใ‚ใ€่จญๅฎšใ‚„**settings**ใซไฝฟใ†ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ -ใพใŸใ€**็‰นๅฎšใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎๅ‘ผใณๅ‡บใ—**ใฎใŸใ‚ใฎ็’ฐๅขƒๅค‰ๆ•ฐใ‚’ใ€ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎใฟใ€ใใฎๅฎŸ่กŒไธญใซ้™ๅฎšใ—ใฆๅˆฉ็”จใงใใ‚‹ใ‚ˆใ†ไฝœๆˆใงใใพใ™ใ€‚ +ใพใŸใ€**็‰นๅฎšใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎๅ‘ผใณๅ‡บใ—**ใฎใŸใ‚ใ ใ‘ใซใ€ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใฎใฟใ€ๅฎŸ่กŒไธญใฎ้–“ใ ใ‘ๅˆฉ็”จใงใใ‚‹็’ฐๅขƒๅค‰ๆ•ฐใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ใใฎใŸใ‚ใซใฏใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ่ตทๅ‹•ใ‚ณใƒžใƒณใƒ‰ใจๅŒใ˜ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณไธŠใฎใ€่ตทๅ‹•ใ‚ณใƒžใƒณใƒ‰็›ดๅ‰ใง็’ฐๅขƒๅค‰ๆ•ฐใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ +ใใฎใŸใ‚ใซใฏใ€ๅŒใ˜่กŒใงใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ่‡ชไฝ“ใฎ็›ดๅ‰ใซไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚
@@ -152,25 +151,25 @@ Hello World from Python
-/// tip +/// tip | ่ฑ†็Ÿฅ่ญ˜ ่ฉณใ—ใใฏ The Twelve-Factor App: Config ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ๅž‹ใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ +## ๅž‹ใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ { #types-and-validation } -็’ฐๅขƒๅค‰ๆ•ฐใฏ**ใƒ†ใ‚ญใ‚นใƒˆๆ–‡ๅญ—ๅˆ—**ใฎใฟใ‚’ๆ‰ฑใ†ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใ‚Œใฏใ€็’ฐๅขƒๅค‰ๆ•ฐใŒPythonๅค–้ƒจใซๅญ˜ๅœจใ—ใ€ไป–ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚„ใ‚ทใ‚นใƒ†ใƒ ๅ…จไฝ“๏ผˆLinuxใ€Windowsใ€macOS้–“ใฎไบ’ๆ›ๆ€งใ‚’ๅซใ‚€๏ผ‰ใจ้€ฃๆบใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใงใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎ็’ฐๅขƒๅค‰ๆ•ฐใŒๆ‰ฑใˆใ‚‹ใฎใฏ**ใƒ†ใ‚ญใ‚นใƒˆๆ–‡ๅญ—ๅˆ—**ใฎใฟใงใ™ใ€‚็’ฐๅขƒๅค‰ๆ•ฐใฏPythonใฎๅค–้ƒจใซใ‚ใ‚Šใ€ไป–ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚„ใ‚ทใ‚นใƒ†ใƒ ๅ…จไฝ“๏ผˆLinuxใ€Windowsใ€macOSใชใฉ็•ฐใชใ‚‹ใ‚ชใƒšใƒฌใƒผใƒ†ใ‚ฃใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ ้–“ใ‚‚๏ผ‰ใจใฎไบ’ๆ›ๆ€งใŒๅฟ…่ฆใซใชใ‚‹ใŸใ‚ใงใ™ใ€‚ -ใคใพใ‚Šใ€PythonใŒ็’ฐๅขƒๅค‰ๆ•ฐใ‹ใ‚‰่ชญใฟๅ–ใ‚‹**ใ‚ใ‚‰ใ‚†ใ‚‹ๅ€ค**ใฏ **`str`ๅž‹ใจใชใ‚Š**ใ€ไป–ใฎๅž‹ใธใฎๅค‰ๆ›ใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏใ‚ณใƒผใƒ‰ๅ†…ใง่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใคใพใ‚Šใ€็’ฐๅขƒๅค‰ๆ•ฐใ‹ใ‚‰Pythonใง่ชญใฟๅ–ใ‚‹**ใ‚ใ‚‰ใ‚†ใ‚‹ๅ€ค**ใฏ **`str`ใซใชใ‚Š**ใ€ไป–ใฎๅž‹ใธใฎๅค‰ๆ›ใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏใ‚ณใƒผใƒ‰ๅ†…ใง่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -็’ฐๅขƒๅค‰ๆ•ฐใ‚’ไฝฟ็”จใ—ใฆ**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ่จญๅฎš**ใ‚’็ฎก็†ใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆใฏใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}ใง่ฉณใ—ใๅญฆในใพใ™ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใ‚’ไฝฟใฃใฆ**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ่จญๅฎš**ใ‚’ๆ‰ฑใ†ๆ–นๆณ•ใซใคใ„ใฆใฏใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank} ใง่ฉณใ—ใๅญฆในใพใ™ใ€‚ -## `PATH`็’ฐๅขƒๅค‰ๆ•ฐ +## `PATH`็’ฐๅขƒๅค‰ๆ•ฐ { #path-environment-variable } -**`PATH`**ใจใ„ใ†**็‰นๅˆฅใช**็’ฐๅขƒๅค‰ๆ•ฐใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎ็’ฐๅขƒๅค‰ๆ•ฐใฏใ€OS๏ผˆLinuxใ€macOSใ€Windows๏ผ‰ใŒๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’็™บ่ฆ‹ใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +**`PATH`**ใจใ„ใ†**็‰นๅˆฅใช**็’ฐๅขƒๅค‰ๆ•ฐใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ‚ชใƒšใƒฌใƒผใƒ†ใ‚ฃใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ ๏ผˆLinuxใ€macOSใ€Windows๏ผ‰ใŒๅฎŸ่กŒใ™ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ‚‹ใŸใ‚ใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -`PATH`ๅค‰ๆ•ฐใฏใ€่ค‡ๆ•ฐใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฎใƒ‘ใ‚นใ‹ใ‚‰ๆˆใ‚‹้•ทใ„ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ใ“ใฎใƒ‘ใ‚นใฏLinuxใ‚„MacOSใฎๅ ดๅˆใฏ`:`ใงใ€Windowsใฎๅ ดๅˆใฏ`;`ใงๅŒบๅˆ‡ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ +ๅค‰ๆ•ฐ`PATH`ใฎๅ€คใฏ้•ทใ„ๆ–‡ๅญ—ๅˆ—ใงใ€LinuxใจmacOSใงใฏใ‚ณใƒญใƒณ`:`ใ€Windowsใงใฏใ‚ปใƒŸใ‚ณใƒญใƒณ`;`ใงๅŒบๅˆ‡ใ‚‰ใ‚ŒใŸใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใงๆง‹ๆˆใ•ใ‚Œใพใ™ใ€‚ ไพ‹ใˆใฐใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใฏๆฌกใฎใ‚ˆใ†ใชๆ–‡ๅญ—ๅˆ—ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“: @@ -180,7 +179,7 @@ Hello World from Python /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin ``` -ใ“ใ‚Œใฏใ€OSใฏใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ‚‹ใŸใ‚ใซไปฅไธ‹ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ๆŽขใ™ใ€ใจใ„ใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: +ใ“ใ‚Œใฏใ€ใ‚ทใ‚นใƒ†ใƒ ใŒๆฌกใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใงใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๆŽขใ™ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: * `/usr/local/bin` * `/usr/bin` @@ -196,7 +195,7 @@ Hello World from Python C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 ``` -ใ“ใ‚Œใฏใ€OSใฏใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ‚‹ใŸใ‚ใซไปฅไธ‹ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ๆŽขใ™ใ€ใจใ„ใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: +ใ“ใ‚Œใฏใ€ใ‚ทใ‚นใƒ†ใƒ ใŒๆฌกใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใงใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๆŽขใ™ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: * `C:\Program Files\Python312\Scripts` * `C:\Program Files\Python312` @@ -204,63 +203,61 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 //// -ใ‚ฟใƒผใƒŸใƒŠใƒซไธŠใง**ใ‚ณใƒžใƒณใƒ‰**ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ OSใฏใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ‚‹ใŸใ‚ใซใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใฎใƒชใ‚นใƒˆใซ่จ˜่ผ‰ใ•ใ‚ŒใŸ**ใใ‚Œใžใ‚Œใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ๆŽขใ—**ใพใ™ใ€‚ +ใ‚ฟใƒผใƒŸใƒŠใƒซไธŠใง**ใ‚ณใƒžใƒณใƒ‰**ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ใ‚ชใƒšใƒฌใƒผใƒ†ใ‚ฃใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ ใฏ`PATH`็’ฐๅขƒๅค‰ๆ•ฐใซ่จ˜่ผ‰ใ•ใ‚ŒใŸ**ใใ‚Œใžใ‚Œใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใฎไธญใ‹ใ‚‰ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**ๆŽขใ—**ใพใ™ใ€‚ -ไพ‹ใˆใฐใ€ใ‚ฟใƒผใƒŸใƒŠใƒซไธŠใง`python`ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€OSใฏ`python`ใซใ‚ˆใฃใฆๅ‘ผใฐใ‚Œใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ‚‹ใŸใ‚ใซใ€ใใฎใƒชใ‚นใƒˆใฎ**ๅ…ˆ้ ญใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใ‚’ๆœ€ๅˆใซๆŽขใ—ใพใ™ใ€‚ +ไพ‹ใˆใฐใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใง`python`ใจๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ใ‚ชใƒšใƒฌใƒผใƒ†ใ‚ฃใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ ใฏใใฎใƒชใ‚นใƒˆใฎ**ๆœ€ๅˆใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใง`python`ใจใ„ใ†ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๆŽขใ—ใพใ™ใ€‚ -OSใฏใ€ใ‚‚ใ—ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ใใ“ใง็™บ่ฆ‹ใ™ใ‚Œใฐ**ๅฎŸ่กŒใ—**ใพใ™ใŒใ€ใใ†ใงใชใ‘ใ‚Œใฐใƒชใ‚นใƒˆใฎ**ไป–ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใ‚’ๆŽขใ—ใฆใ„ใใพใ™ใ€‚ +่ฆ‹ใคใ‹ใ‚Œใฐใใ‚Œใ‚’**ไฝฟ็”จ**ใ—ใพใ™ใ€‚่ฆ‹ใคใ‹ใ‚‰ใชใ‘ใ‚Œใฐใ€**ไป–ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช**ใ‚’ๆŽขใ—็ถšใ‘ใพใ™ใ€‚ -### Pythonใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใจPATH็’ฐๅขƒๅค‰ๆ•ฐใฎๆ›ดๆ–ฐ +### Pythonใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใจ`PATH`ใฎๆ›ดๆ–ฐ { #installing-python-and-updating-the-path } -Pythonใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๆ™‚ใซ`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ—ใŸใ„ใ‹่žใ‹ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +Pythonใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๆ™‚ใซใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ๅฐ‹ใญใ‚‰ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ -/// tab | Linux, macOS +//// tab | Linux, macOS -Pythonใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒ`/opt/custompython/bin`ใจใ„ใ†ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ้…็ฝฎใ•ใ‚ŒใŸใจใ—ใพใ™ใ€‚ +Pythonใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€ใใฎ็ตๆžœ`/opt/custompython/bin`ใจใ„ใ†ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ้…็ฝฎใ•ใ‚ŒใŸใจใ—ใพใ™ใ€‚ -ใ‚‚ใ—ใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ‚ˆใ†ใซ็ญ”ใˆใ‚‹ใจใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใซ`/opt/custompython/bin`ใŒ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ +`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ“ใจใซๅŒๆ„ใ™ใ‚‹ใจใ€ใ‚คใƒณใ‚นใƒˆใƒผใƒฉใƒผใฏ`PATH`็’ฐๅขƒๅค‰ๆ•ฐใซ`/opt/custompython/bin`ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ -`PATH`็’ฐๅขƒๅค‰ๆ•ฐใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ดๆ–ฐใ•ใ‚Œใ‚‹ใงใ—ใ‚‡ใ†๏ผš +ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -``` plaintext +```plaintext /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin ``` -ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใง`python`ใจๅ…ฅๅŠ›ใ—ใŸใจใใซใ€OSใฏ`/opt/custompython/bin`๏ผˆใƒชใ‚นใƒˆใฎๆœซๅฐพใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช๏ผ‰ใซใ‚ใ‚‹Pythonใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ€ไฝฟ็”จใ—ใพใ™ใ€‚ - -/// +ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใง`python`ใจๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ใ‚ทใ‚นใƒ†ใƒ ใฏ`/opt/custompython/bin`๏ผˆๆœ€ๅพŒใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช๏ผ‰ใซใ‚ใ‚‹Pythonใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ€ใใ‚Œใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -/// tab | Windows +//// -Pythonใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€ใใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒ`C:\opt\custompython\bin`ใจใ„ใ†ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ้…็ฝฎใ•ใ‚ŒใŸใจใ—ใพใ™ใ€‚ +//// tab | Windows -ใ‚‚ใ—ใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ‚ˆใ†ใซ็ญ”ใˆใ‚‹ใจใ€`PATH`็’ฐๅขƒๅค‰ๆ•ฐใซ`C:\opt\custompython\bin`ใŒ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ +Pythonใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ€ใใฎ็ตๆžœ`C:\opt\custompython\bin`ใจใ„ใ†ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ้…็ฝฎใ•ใ‚ŒใŸใจใ—ใพใ™ใ€‚ -`PATH`็’ฐๅขƒๅค‰ๆ•ฐใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ดๆ–ฐใ•ใ‚Œใ‚‹ใงใ—ใ‚‡ใ†๏ผš +`PATH`็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ“ใจใซๅŒๆ„ใ™ใ‚‹ใจใ€ใ‚คใƒณใ‚นใƒˆใƒผใƒฉใƒผใฏ`PATH`็’ฐๅขƒๅค‰ๆ•ฐใซ`C:\opt\custompython\bin`ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ ```plaintext C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin ``` -ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใง`python`ใจๅ…ฅๅŠ›ใ—ใŸใจใใซใ€OSใฏ`C:\opt\custompython\bin\python`๏ผˆใƒชใ‚นใƒˆใฎๆœซๅฐพใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช๏ผ‰ใซใ‚ใ‚‹Pythonใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ€ไฝฟ็”จใ—ใพใ™ใ€‚ +ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใง`python`ใจๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ใ‚ทใ‚นใƒ†ใƒ ใฏ`C:\opt\custompython\bin`๏ผˆๆœ€ๅพŒใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช๏ผ‰ใซใ‚ใ‚‹Pythonใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ฆ‹ใคใ‘ใ€ใใ‚Œใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -/// +//// -ใคใพใ‚Šใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใงไปฅไธ‹ใฎใ‚ณใƒžใƒณใƒ‰ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจ๏ผš +ใคใพใ‚Šใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใงๆฌกใฎใ‚ˆใ†ใซๅ…ฅๅŠ›ใ™ใ‚‹ใจ:
-``` console +```console $ python ```
-/// tab | Linux, macOS +//// tab | Linux, macOS -OSใฏ`/opt/custompython/bin`ใซใ‚ใ‚‹`python`ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**่ฆ‹ใคใ‘**ใฆๅฎŸ่กŒใ—ใพใ™ใ€‚ +ใ‚ทใ‚นใƒ†ใƒ ใฏ`/opt/custompython/bin`ใซใ‚ใ‚‹`python`ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**่ฆ‹ใคใ‘**ใฆๅฎŸ่กŒใ—ใพใ™ใ€‚ -ใ“ใ‚Œใฏใ€ๆฌกใฎใ‚ณใƒžใƒณใƒ‰ใ‚’ๅ…ฅๅŠ›ใ—ใŸๅ ดๅˆใจใปใจใ‚“ใฉๅŒ็ญ‰ใงใ™๏ผš +ใ“ใ‚Œใฏใ€ๆฌกใฎใ‚ˆใ†ใซๅ…ฅๅŠ›ใ™ใ‚‹ใฎใจใŠใŠใ‚€ใญๅŒ็ญ‰ใงใ™:
@@ -270,13 +267,13 @@ $ /opt/custompython/bin/python
-/// +//// -/// tab | Windows +//// tab | Windows -OSใฏ`C:\opt\custompython\bin\python`ใซใ‚ใ‚‹`python`ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**่ฆ‹ใคใ‘**ใฆๅฎŸ่กŒใ—ใพใ™ใ€‚ +ใ‚ทใ‚นใƒ†ใƒ ใฏ`C:\opt\custompython\bin\python`ใซใ‚ใ‚‹`python`ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**่ฆ‹ใคใ‘**ใฆๅฎŸ่กŒใ—ใพใ™ใ€‚ -ใ“ใ‚Œใฏใ€ๆฌกใฎใ‚ณใƒžใƒณใƒ‰ใ‚’ๅ…ฅๅŠ›ใ—ใŸๅ ดๅˆใจใปใจใ‚“ใฉๅŒ็ญ‰ใงใ™๏ผš +ใ“ใ‚Œใฏใ€ๆฌกใฎใ‚ˆใ†ใซๅ…ฅๅŠ›ใ™ใ‚‹ใฎใจใŠใŠใ‚€ใญๅŒ็ญ‰ใงใ™:
@@ -286,16 +283,16 @@ $ C:\opt\custompython\bin\python
-/// +//// -ใ“ใฎๆƒ…ๅ ฑใฏใ€[Virtual Environments](virtual-environments.md) ใซใคใ„ใฆๅญฆใถ้š›ใซใ‚‚ๅฝน็ซ‹ใกใพใ™ใ€‚ +ใ“ใฎๆƒ…ๅ ฑใฏใ€[Virtual Environments](virtual-environments.md){.internal-link target=_blank} ใซใคใ„ใฆๅญฆใถ้š›ใซใ‚‚ๅฝน็ซ‹ใกใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #conclusion } ใ“ใ‚Œใงใ€**็’ฐๅขƒๅค‰ๆ•ฐ**ใจใฏไฝ•ใ‹ใ€Pythonใงใฉใฎใ‚ˆใ†ใซไฝฟ็”จใ™ใ‚‹ใ‹ใซใคใ„ใฆใ€ๅŸบๆœฌ็š„ใช็†่งฃใŒๅพ—ใ‚‰ใ‚ŒใŸใฏใšใงใ™ใ€‚ -็’ฐๅขƒๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏใ€Wikipedia: Environment Variable ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏใ€Wikipedia for Environment Variable ใ‚‚ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ -็’ฐๅขƒๅค‰ๆ•ฐใฎ็”จ้€”ใ‚„้ฉ็”จๆ–นๆณ•ใŒๆœ€ๅˆใฏ็›ดๆ„Ÿ็š„ใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใŒใ€้–‹็™บไธญใฎใ•ใพใ–ใพใชใ‚ทใƒŠใƒชใ‚ชใง็นฐใ‚Š่ฟ”ใ—็™ปๅ ดใ—ใพใ™ใ€‚ใใฎใŸใ‚ใ€ๅŸบๆœฌใ‚’็ŸฅใฃใฆใŠใใ“ใจใŒ้‡่ฆใงใ™ใ€‚ +ๅคšใใฎๅ ดๅˆใ€็’ฐๅขƒๅค‰ๆ•ฐใŒใฉใฎใ‚ˆใ†ใซๅฝน็ซ‹ใกใ€ใ™ใใซ้ฉ็”จใงใใ‚‹ใฎใ‹ใฏใ‚ใพใ‚Šๆ˜Ž็ขบใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€้–‹็™บไธญใฎใ•ใพใ–ใพใชใ‚ทใƒŠใƒชใ‚ชใงไฝ•ๅบฆใ‚‚็™ปๅ ดใ™ใ‚‹ใŸใ‚ใ€็ŸฅใฃใฆใŠใใจใ‚ˆใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใŸใจใˆใฐใ€ใ“ใฎๆƒ…ๅ ฑใฏๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงๆ‰ฑใ†[Virtual Environments](virtual-environments.md)ใซใ‚‚้–ข้€ฃใ—ใพใ™ใ€‚ +ไพ‹ใˆใฐใ€ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎ[Virtual Environments](virtual-environments.md)ใงใ“ใฎๆƒ…ๅ ฑใŒๅฟ…่ฆใซใชใ‚Šใพใ™ใ€‚ diff --git a/docs/ja/docs/how-to/conditional-openapi.md b/docs/ja/docs/how-to/conditional-openapi.md index bfaa9e6d75..9478f5c032 100644 --- a/docs/ja/docs/how-to/conditional-openapi.md +++ b/docs/ja/docs/how-to/conditional-openapi.md @@ -1,8 +1,8 @@ -# ๆกไปถไป˜ใ OpenAPI +# ๆกไปถไป˜ใ OpenAPI { #conditional-openapi } ๅฟ…่ฆใงใ‚ใ‚Œใฐใ€่จญๅฎšใจ็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๅˆฉ็”จใ—ใฆใ€็’ฐๅขƒใซๅฟœใ˜ใฆๆกไปถไป˜ใใงOpenAPIใ‚’ๆง‹ๆˆใ™ใ‚‹ใ“ใจใŒๅฏ่ƒฝใงใ™ใ€‚ใพใŸใ€ๅฎŒๅ…จใซOpenAPIใ‚’็„กๅŠนใซใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -## ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจAPIใ€ใŠใ‚ˆใณใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใคใ„ใฆ +## ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจAPIใ€ใŠใ‚ˆใณใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใคใ„ใฆ { #about-security-apis-and-docs } ๆœฌ็•ช็’ฐๅขƒใซใŠใ„ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎUIใ‚’้ž่กจ็คบใซใ™ใ‚‹ใ“ใจใซใ‚ˆใฃใฆใ€APIใ‚’ไฟ่ญทใ—ใ‚ˆใ†ใจ *ใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“*ใ€‚ @@ -17,19 +17,19 @@ * ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใจใƒฌใ‚นใƒใƒณใ‚นใฎใŸใ‚ใฎPydanticใƒขใƒ‡ใƒซใฎๅฎš็พฉใ‚’่ฆ‹็›ดใ™ใ€‚ * ไพๅญ˜้–ขไฟ‚ใซๅŸบใฅใใ™ในใฆใฎๅฟ…่ฆใชใƒ‘ใƒผใƒŸใƒƒใ‚ทใƒงใƒณใจใƒญใƒผใƒซใ‚’่จญๅฎšใ™ใ‚‹ใ€‚ * ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’็ตถๅฏพใซๅนณๆ–‡ใงไฟๅญ˜ใ—ใชใ„ใ€‚ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅใฎใฟใ‚’ไฟๅญ˜ใ™ใ‚‹ใ€‚ -* Passlibใ‚„JWTใƒˆใƒผใ‚ฏใƒณใซไปฃ่กจใ•ใ‚Œใ‚‹ใ€ใ‚ˆใ็Ÿฅใ‚‰ใ‚ŒใŸๆš—ๅทๅŒ–ใƒ„ใƒผใƒซใ‚’ไฝฟใฃใฆๅฎŸ่ฃ…ใ™ใ‚‹ใ€‚ +* pwdlibใ‚„JWTใƒˆใƒผใ‚ฏใƒณใซไปฃ่กจใ•ใ‚Œใ‚‹ใ€ใ‚ˆใ็Ÿฅใ‚‰ใ‚ŒใŸๆš—ๅทๅŒ–ใƒ„ใƒผใƒซใ‚’ไฝฟใฃใฆๅฎŸ่ฃ…ใ™ใ‚‹ใ€‚ * ใใ—ใฆๅฟ…่ฆใชใจใ“ใ‚ใงใฏใ€ใ‚‚ใฃใจ็ดฐใ‹ใ„ใƒ‘ใƒผใƒŸใƒƒใ‚ทใƒงใƒณๅˆถๅพกใ‚’OAuth2ใ‚นใ‚ณใƒผใƒ—ใ‚’ไฝฟใฃใฆ่กŒใ†ใ€‚ -* ใชใฉ +* ...ใชใฉ ใใ‚Œใงใ‚‚ใ€ไพ‹ใˆใฐๆœฌ็•ช็’ฐๅขƒใฎใ‚ˆใ†ใช็‰นๅฎšใฎ็’ฐๅขƒใฎใฟใงใ€ใ‚ใ‚‹ใ„ใฏ็’ฐๅขƒๅค‰ๆ•ฐใฎ่จญๅฎšใซใ‚ˆใฃใฆAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใฉใ†ใ—ใฆใ‚‚็„กๅŠนใซใ—ใŸใ„ใจใ„ใ†ใ€้žๅธธใซ็‰นๆฎŠใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ -## ่จญๅฎšใจ็’ฐๅขƒๅค‰ๆ•ฐใซใ‚ˆใ‚‹ๆกไปถไป˜ใ OpenAPI +## ่จญๅฎšใจ็’ฐๅขƒๅค‰ๆ•ฐใซใ‚ˆใ‚‹ๆกไปถไป˜ใ OpenAPI { #conditional-openapi-from-settings-and-env-vars } ็”Ÿๆˆใ™ใ‚‹OpenAPIใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฎๆง‹ๆˆใฏใ€ๅ…ฑ้€šใฎPydanticใฎ่จญๅฎšใ‚’ไฝฟ็”จใ—ใฆ็ฐกๅ˜ใซๅˆ‡ใ‚Šๆ›ฟใˆใ‚‰ใ‚Œใพใ™ใ€‚ ไพ‹ใˆใฐใ€ -{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} ใ“ใ“ใงใฏ `openapi_url` ใฎ่จญๅฎšใ‚’ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ `"/openapi.json"` ใฎใพใพๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index 8dee1ee035..67e01ed535 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -1,14 +1,14 @@ -# FastAPI +# FastAPI { #fastapi }

- FastAPI + FastAPI

- FastAPI framework, high performance, easy to learn, fast to code, ready for production + FastAPI ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ€้ซ˜ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ€ๅญฆใณใ‚„ใ™ใ„ใ€็ด ๆ—ฉใใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใงใใ‚‹ใ€ๆœฌ็•ช้‹็”จใซๅฏพๅฟœ

@@ -27,129 +27,138 @@ --- -**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ**: https://fastapi.tiangolo.com +**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ**: https://fastapi.tiangolo.com **ใ‚ฝใƒผใ‚นใ‚ณใƒผใƒ‰**: https://github.com/fastapi/fastapi --- -FastAPI ใฏใ€Pythonใฎๆจ™ๆบ–ใงใ‚ใ‚‹ๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆPython ไปฅ้™ใงAPI ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎใ€ใƒขใƒ€ใƒณใงใ€้ซ˜้€Ÿ(้ซ˜ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น)ใชใ€Web ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ +FastAPI ใฏใ€Python ใฎๆจ™ๆบ–ใงใ‚ใ‚‹ๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆ Python ใง API ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎใ€ใƒขใƒ€ใƒณใงใ€้ซ˜้€Ÿ๏ผˆ้ซ˜ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น๏ผ‰ใช Web ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ ไธปใช็‰นๅพด: -- **้ซ˜้€Ÿ**: **NodeJS** ใ‚„ **Go** ไธฆใฟใฎใจใฆใ‚‚้ซ˜ใ„ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น (Starlette ใจ Pydantic ใฎใŠใ‹ใ’ใงใ™)ใ€‚ [ๆœ€ใ‚‚้ซ˜้€Ÿใช Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธ€ใคใงใ™](#_10). +* **้ซ˜้€Ÿ**: **NodeJS** ใ‚„ **Go** ไธฆใฟใฎใจใฆใ‚‚้ซ˜ใ„ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น๏ผˆStarlette ใจ Pydantic ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ [ๅˆฉ็”จๅฏ่ƒฝใชๆœ€ใ‚‚้ซ˜้€Ÿใช Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธ€ใคใงใ™](#performance)ใ€‚ +* **้ซ˜้€Ÿใชใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐ**: ้–‹็™บ้€Ÿๅบฆใ‚’็ด„ 200%ใ€œ300% ๅ‘ไธŠใ•ใ›ใพใ™ใ€‚* +* **ๅฐ‘ใชใ„ใƒใ‚ฐ**: ้–‹็™บ่€…่ตทๅ› ใฎใƒ’ใƒฅใƒผใƒžใƒณใ‚จใƒฉใƒผใ‚’็ด„ 40% ๅ‰Šๆธ›ใ—ใพใ™ใ€‚* +* **็›ดๆ„Ÿ็š„**: ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใ€‚ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใง ่ฃœๅฎŒ ใŒไฝฟใˆใพใ™ใ€‚ใƒ‡ใƒใƒƒใ‚ฐๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ +* **็ฐกๅ˜**: ็ฐกๅ˜ใซๅˆฉ็”จใƒป็ฟ’ๅพ—ใงใใ‚‹ใ‚ˆใ†ใซใƒ‡ใ‚ถใ‚คใƒณใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชญใ‚€ๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ +* **็Ÿญใ„**: ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡ใ‚’ๆœ€ๅฐ้™ใซใ—ใพใ™ใ€‚ๅ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅฎฃ่จ€ใ‹ใ‚‰่ค‡ๆ•ฐใฎๆฉŸ่ƒฝใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ใƒใ‚ฐใ‚‚ๆธ›ใ‚Šใพใ™ใ€‚ +* **ๅ …็‰ขๆ€ง**: ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚ˆใ‚Šใ€ๆœฌ็•ช็’ฐๅขƒๅ‘ใ‘ใฎใ‚ณใƒผใƒ‰ใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ +* **Standards-based**: API ใฎใ‚ชใƒผใƒ—ใƒณใ‚นใ‚ฟใƒณใƒ€ใƒผใƒ‰ใซๅŸบใฅใ„ใฆใŠใ‚Š๏ผˆใใ—ใฆๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™๏ผ‰ใ€OpenAPI๏ผˆไปฅๅ‰ใฏ Swagger ใจใ—ใฆ็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ—ใŸ๏ผ‰ใ‚„ JSON Schema ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใพใ™ใ€‚ -- **้ซ˜้€Ÿใชใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐ**: ้–‹็™บ้€Ÿๅบฆใ‚’็ด„ 200%~300%ๅ‘ไธŠใ•ใ›ใพใ™ใ€‚ \* -- **ๅฐ‘ใชใ„ใƒใ‚ฐ**: ้–‹็™บ่€…่ตทๅ› ใฎใƒ’ใƒฅใƒผใƒžใƒณใ‚จใƒฉใƒผใ‚’็ด„ 40๏ผ…ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ \* -- **็›ดๆ„Ÿ็š„**: ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚„ ใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใ€‚ ใƒ‡ใƒใƒƒใ‚ฐๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ -- **็ฐกๅ˜**: ็ฐกๅ˜ใซๅˆฉ็”จใ€็ฟ’ๅพ—ใงใใ‚‹ใ‚ˆใ†ใซใƒ‡ใ‚ถใ‚คใƒณใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชญใ‚€ๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ -- **็Ÿญใ„**: ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡ใ‚’ๆœ€ๅฐ้™ใซใ—ใฆใ„ใพใ™ใ€‚ๅ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‹ใ‚‰ใฎ่ค‡ๆ•ฐใฎๆฉŸ่ƒฝใ€‚ๅฐ‘ใชใ„ใƒใ‚ฐใ€‚ -- **ๅ …็‰ขๆ€ง**: ่‡ชๅ‹•ๅฏพ่ฉฑใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ไฝฟ็”จใ—ใฆใ€ๆœฌ็•ช็’ฐๅขƒใงไฝฟ็”จใงใใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ -- **Standards-based**: API ใฎใ‚ชใƒผใƒ—ใƒณใ‚นใ‚ฟใƒณใƒ€ใƒผใƒ‰ใซๅŸบใฅใ„ใฆใŠใ‚Šใ€ๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™: OpenAPI (ไปฅๅ‰ใฏ Swagger ใจใ—ใฆ็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ—ใŸ) ใ‚„ JSON ใ‚นใ‚ญใƒผใƒž. +* ๆœฌ็•ชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใ—ใฆใ„ใ‚‹็คพๅ†…้–‹็™บใƒใƒผใƒ ใฎใƒ†ใ‚นใƒˆใซๅŸบใฅใ่ฆ‹็ฉใ‚‚ใ‚Šใงใ™ใ€‚ -\* ๆœฌ็•ชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใ—ใฆใ„ใ‚‹้–‹็™บใƒใƒผใƒ ใฎใƒ†ใ‚นใƒˆใซใ‚ˆใ‚‹่ฆ‹็ฉใ‚‚ใ‚Šใ€‚ - -## Sponsors +## Sponsors { #sponsors } -{% if sponsors %} +### Keystone Sponsor { #keystone-sponsor } + +{% for sponsor in sponsors.keystone -%} + +{% endfor -%} + +### Gold and Silver Sponsors { #gold-and-silver-sponsors } + {% for sponsor in sponsors.gold -%} {% endfor -%} {%- for sponsor in sponsors.silver -%} {% endfor %} -{% endif %} -Other sponsors +ใใฎไป–ใฎใ‚นใƒใƒณใ‚ตใƒผ -## ่ฉ•ไพก +## ่ฉ•ไพก { #opinions } -"_[...] ๆœ€่ฟ‘ **FastAPI** ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ [...] ๅฎŸ้š›ใซ็งใฎใƒใƒผใƒ ใฎๅ…จใฆใฎ **Microsoft ใฎๆฉŸๆขฐๅญฆ็ฟ’ใ‚ตใƒผใƒ“ใ‚น** ใงไฝฟ็”จใ™ใ‚‹ไบˆๅฎšใงใ™ใ€‚ ใใฎใ†ใกใฎใ„ใใคใ‹ใฎใ‚ณใ‚ขใช**Windows**่ฃฝๅ“ใจ**Office**่ฃฝๅ“ใซ็ตฑๅˆใ•ใ‚Œใคใคใ‚ใ‚Šใพใ™ใ€‚_" +"_[...] ๆœ€่ฟ‘ **FastAPI** ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ [...] ๅฎŸ้š›ใซ็งใฎใƒใƒผใƒ ใฎๅ…จใฆใฎ **Microsoft ใฎๆฉŸๆขฐๅญฆ็ฟ’ใ‚ตใƒผใƒ“ใ‚น** ใงไฝฟ็”จใ™ใ‚‹ไบˆๅฎšใงใ™ใ€‚ ใใฎใ†ใกใฎใ„ใใคใ‹ใฎใ‚ณใ‚ขใช **Windows** ่ฃฝๅ“ใจ **Office** ่ฃฝๅ“ใซ็ตฑๅˆใ•ใ‚Œใคใคใ‚ใ‚Šใพใ™ใ€‚_"

Kabir Khan - Microsoft (ref)
--- -"_FastAPIใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ๆŽก็”จใ—ใ€ใ‚ฏใ‚จใƒชใง**ไบˆๆธฌๅ€ค**ใ‚’ๅ–ๅพ—ใงใใ‚‹**REST**ใ‚ตใƒผใƒใ‚’ๆง‹็ฏ‰ใ—ใพใ—ใŸใ€‚ [for Ludwig]_" +"_FastAPIใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ๆŽก็”จใ—ใ€ใ‚ฏใ‚จใƒชใง **ไบˆๆธฌๅ€ค** ใ‚’ๅ–ๅพ—ใงใใ‚‹ **REST** ใ‚ตใƒผใƒใ‚’ๆง‹็ฏ‰ใ—ใพใ—ใŸใ€‚ [for Ludwig]_"
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"_**Netflix** ใฏใ€**ๅฑๆฉŸ็ฎก็†**ใ‚ชใƒผใ‚ฑใ‚นใƒˆใƒฌใƒผใ‚ทใƒงใƒณใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ€**Dispatch**ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒชใƒชใƒผใ‚นใ‚’็™บ่กจใงใใ‚‹ใ“ใจใ‚’ใ†ใ‚Œใ—ใๆ€ใ„ใพใ™ใ€‚ [built with **FastAPI**]_" +"_**Netflix** ใฏใ€**ๅฑๆฉŸ็ฎก็†**ใ‚ชใƒผใ‚ฑใ‚นใƒˆใƒฌใƒผใ‚ทใƒงใƒณใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ€**Dispatch** ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒชใƒชใƒผใ‚นใ‚’็™บ่กจใงใใ‚‹ใ“ใจใ‚’ใ†ใ‚Œใ—ใๆ€ใ„ใพใ™ใ€‚ [built with **FastAPI**]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_็งใฏ**FastAPI**ใซใƒฏใ‚ฏใƒฏใ‚ฏใ—ใฆใ„ใพใ™ใ€‚ ใ‚ใกใ‚ƒใใกใ‚ƒๆฅฝใ—ใ„ใงใ™๏ผ_" +"_็งใฏ **FastAPI** ใซใƒฏใ‚ฏใƒฏใ‚ฏใ—ใฆใ„ใพใ™ใ€‚ ใ‚ใกใ‚ƒใใกใ‚ƒๆฅฝใ—ใ„ใงใ™๏ผ_"
Brian Okken - Python Bytes podcast host (ref)
--- -"_ๆญฃ็›ดใ€่ถ…ๅ …ๅฎŸใงๆด—็ทดใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใˆใพใ™ใ€‚ใ„ใ‚ใ‚“ใชๆ„ๅ‘ณใงใ€ใใ‚Œใฏ็งใŒใƒใ‚ฐใ—ใŸใ‹ใฃใŸใ‚‚ใฎใงใ™ใ€‚_" +"_ๆญฃ็›ดใ€ใ‚ใชใŸใŒไฝœใฃใŸใ‚‚ใฎใฏ่ถ…ๅ …ๅฎŸใงๆด—็ทดใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใˆใพใ™ใ€‚ใ„ใ‚ใ‚“ใชๆ„ๅ‘ณใงใ€ใใ‚Œใฏ็งใŒ **Hug** ใซใใ†ใชใฃใฆใปใ—ใ‹ใฃใŸใ‚‚ใฎใงใ™ใ€‚่ชฐใ‹ใŒใใ‚Œใ‚’ไฝœใ‚‹ใฎใ‚’่ฆ‹ใ‚‹ใฎใฏๆœฌๅฝ“ใซๅˆบๆฟ€็š„ใงใ™ใ€‚_"
Timothy Crosley - Hug creator (ref)
--- -"_REST API ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎ**ใƒขใƒ€ใƒณใชใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ**ใ‚’ๅญฆใณใŸใ„ๆ–นใฏใ€**FastAPI** [...] ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ [...] ้ซ˜้€Ÿใง, ไฝฟ็”จใ€็ฟ’ๅพ—ใŒ็ฐกๅ˜ใงใ™ใ€‚[...]_" +"_REST API ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎ **ใƒขใƒ€ใƒณใชใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ** ใ‚’ๅญฆใณใŸใ„ๆ–นใฏใ€**FastAPI** [...] ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ [...] ้ซ˜้€Ÿใงใ€ไฝฟ็”จใƒป็ฟ’ๅพ—ใŒ็ฐกๅ˜ใงใ™ [...]_" -"_็งใŸใกใฎ**API**ใฏ**FastAPI**ใซๅˆ‡ใ‚Šๆ›ฟใˆใพใ—ใŸใ€‚[...] ใใฃใจๆฐ—ใซๅ…ฅใ‚‹ใจๆ€ใ„ใพใ™ใ€‚ [...]_" +"_็งใŸใกใฎ **API** ใฏ **FastAPI** ใซๅˆ‡ใ‚Šๆ›ฟใˆใพใ—ใŸ [...] ใใฃใจๆฐ—ใซๅ…ฅใ‚‹ใจๆ€ใ„ใพใ™ [...]_"
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
--- -## **Typer**, the FastAPI of CLIs +"_ๆœฌ็•ช้‹็”จใฎ Python API ใ‚’ๆง‹็ฏ‰ใ—ใŸใ„ๆ–นใซใฏใ€**FastAPI** ใ‚’ๅผทใใŠใ™ใ™ใ‚ใ—ใพใ™ใ€‚**็พŽใ—ใ่จญ่จˆ**ใ•ใ‚ŒใฆใŠใ‚Šใ€**ไฝฟใ„ใ‚„ใ™ใ**ใ€**้ซ˜ใ„ใ‚นใ‚ฑใƒผใƒฉใƒ“ใƒชใƒ†ใ‚ฃ**ใŒใ‚ใ‚Šใพใ™ใ€‚็งใŸใกใฎ API ใƒ•ใ‚กใƒผใ‚นใƒˆ้–‹็™บๆˆฆ็•ฅใฎ **ไธป่ฆใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ** ใจใชใ‚Šใ€Virtual TAC Engineer ใชใฉใฎๅคšใใฎ่‡ชๅ‹•ๅŒ–ใ‚„ใ‚ตใƒผใƒ“ใ‚นใ‚’ๆŽจ้€ฒใ—ใฆใ„ใพใ™ใ€‚_" - +
Deon Pillsbury - Cisco (ref)
-ใ‚‚ใ— Web API ใฎไปฃใ‚ใ‚Šใซใ‚ฟใƒผใƒŸใƒŠใƒซใงไฝฟ็”จใ™ใ‚‹CLIใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๅ ดๅˆใฏใ€**Typer**ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +--- -**Typer**ใฏ FastAPI ใฎๅผŸๅˆ†ใงใ™ใ€‚ใใ—ใฆใ€**CLI ็‰ˆ ใฎ FastAPI**ใ‚’ๆ„ๅ‘ณใ—ใฆใ„ใพใ™ใ€‚ +## FastAPI ใƒŸใƒ‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใ‚ฟใƒชใƒผ { #fastapi-mini-documentary } -## ๅฟ…่ฆๆกไปถ +2025 ๅนดๆœซใซๅ…ฌ้–‹ใ•ใ‚ŒใŸ FastAPI ใƒŸใƒ‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใ‚ฟใƒชใƒผใŒใ‚ใ‚Šใพใ™ใ€‚ใ‚ชใƒณใƒฉใ‚คใƒณใง่ฆ–่ดใงใใพใ™: -FastAPI ใฏๅทจไบบใฎ่‚ฉใฎไธŠใซ็ซ‹ใฃใฆใ„ใพใ™ใ€‚ +FastAPI Mini Documentary -- Web ใฎ้ƒจๅˆ†ใฏStarlette -- ใƒ‡ใƒผใ‚ฟใฎ้ƒจๅˆ†ใฏPydantic +## **Typer**ใ€CLI ็‰ˆ FastAPI { #typer-the-fastapi-of-clis } -## ใ‚คใƒณใ‚นใƒˆใƒผใƒซ + -
+Web API ใฎไปฃใ‚ใ‚Šใซใ‚ฟใƒผใƒŸใƒŠใƒซใงไฝฟ็”จใ™ใ‚‹ CLI ใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๅ ดๅˆใฏใ€**Typer** ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ -```console -$ pip install fastapi +**Typer** ใฏ FastAPI ใฎๅผŸๅˆ†ใงใ™ใ€‚ใใ—ใฆใ€**CLI ็‰ˆ FastAPI** ใ‚’ๆ„ๅ›ณใ—ใฆใ„ใพใ™ใ€‚ โŒจ๏ธ ๐Ÿš€ ----> 100% -``` +## ๅฟ…่ฆๆกไปถ { #requirements } -
+FastAPI ใฏๅทจไบบใฎ่‚ฉใฎไธŠใซ็ซ‹ใฃใฆใ„ใพใ™ใ€‚ + +* Web ใฎ้ƒจๅˆ†ใฏ Starlette +* ใƒ‡ใƒผใ‚ฟใฎ้ƒจๅˆ†ใฏ Pydantic -ๆœฌ็•ช็’ฐๅขƒใงใฏใ€Uvicorn ใพใŸใฏใ€ Hypercornใฎใ‚ˆใ†ใชใ€ ASGI ใ‚ตใƒผใƒใƒผใŒๅฟ…่ฆใซใชใ‚Šใพใ™ใ€‚ +## ใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #installation } + +virtual environment ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ใใ‚Œใ‹ใ‚‰ FastAPI ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
-## ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณไพ‹ +**ๆณจ**: ใ™ในใฆใฎใ‚ฟใƒผใƒŸใƒŠใƒซใงๅ‹•ไฝœใ™ใ‚‹ใ‚ˆใ†ใซใ€`"fastapi[standard]"` ใฏๅฟ…ใšใ‚ฏใ‚ฉใƒผใƒˆใงๅ›ฒใ‚“ใงใใ ใ•ใ„ใ€‚ + +## ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณไพ‹ { #example } -### ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎไฝœๆˆ +### ไฝœๆˆ { #create-it } -- `main.py` ใ‚’ไฝœๆˆใ—ใ€ไปฅไธ‹ใฎใ‚ณใƒผใƒ‰ใ‚’ๅ…ฅๅŠ›ใ—ใพใ™: +`main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใ€ไปฅไธ‹ใฎใ‚ณใƒผใƒ‰ใ‚’ๅ…ฅๅŠ›ใ—ใพใ™ใ€‚ ```Python from fastapi import FastAPI @@ -163,16 +172,16 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: str = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ```
-ใพใŸใฏasync defใ‚’ไฝฟใ„ใพใ™... +ใพใŸใฏ async def ใ‚’ไฝฟใ„ใพใ™... -`async` / `await`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใใฏใ€ `async def`ใ‚’ไฝฟใ„ใพใ™: +ใ‚ณใƒผใƒ‰ใง `async` / `await` ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฏใ€`async def` ใ‚’ไฝฟใ„ใพใ™ใ€‚ -```Python hl_lines="7 12" +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -184,28 +193,41 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: str = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` **ๆณจ**: -ใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ`async` ใจ `await`ใซใ‚ใ‚‹"In a hurry?"ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใใ ใ•ใ„ใ€‚ +ใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ `async` ใจ `await` ใฎ _"In a hurry?"_ ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚
-### ๅฎŸ่กŒ +### ๅฎŸ่กŒ { #run-it } -ไปฅไธ‹ใฎใ‚ณใƒžใƒณใƒ‰ใงใ‚ตใƒผใƒใƒผใ‚’่ตทๅ‹•ใ—ใพใ™: +ไปฅไธ‹ใฎใ‚ณใƒžใƒณใƒ‰ใงใ‚ตใƒผใƒใƒผใ‚’่ตทๅ‹•ใ—ใพใ™ใ€‚
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ + โ”‚ โ”‚ + โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ + โ”‚ โ”‚ + โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ + โ”‚ โ”‚ + โ”‚ Running in development mode, for production use: โ”‚ + โ”‚ โ”‚ + โ”‚ fastapi run โ”‚ + โ”‚ โ”‚ + โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -213,56 +235,56 @@ INFO: Application startup complete.
-uvicorn main:app --reloadใ‚ณใƒžใƒณใƒ‰ใซใคใ„ใฆ +fastapi dev main.py ใ‚ณใƒžใƒณใƒ‰ใซใคใ„ใฆ + +`fastapi dev` ใ‚ณใƒžใƒณใƒ‰ใฏ `main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’่ชญใฟๅ–ใ‚Šใ€ใใฎไธญใฎ **FastAPI** ใ‚ขใƒ—ใƒชใ‚’ๆคœๅ‡บใ—ใ€Uvicorn ใ‚’ไฝฟ็”จใ—ใฆใ‚ตใƒผใƒใƒผใ‚’่ตทๅ‹•ใ—ใพใ™ใ€‚ -`uvicorn main:app`ใ‚ณใƒžใƒณใƒ‰ใฏไปฅไธ‹ใฎ้ …็›ฎใ‚’ๅ‚็…งใ—ใพใ™: +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€`fastapi dev` ใฏใƒญใƒผใ‚ซใƒซ้–‹็™บๅ‘ใ‘ใซ่‡ชๅ‹•ใƒชใƒญใƒผใƒ‰ใ‚’ๆœ‰ๅŠนใซใ—ใฆ่ตทๅ‹•ใ—ใพใ™ใ€‚ -- `main`: `main.py`ใƒ•ใ‚กใ‚คใƒซ (Python "ใƒขใ‚ธใƒฅใƒผใƒซ") -- `app`: `main.py` ใฎ`app = FastAPI()`ใฎ่กŒใง็”Ÿๆˆใ•ใ‚ŒใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ -- `--reload`: ใ‚ณใƒผใƒ‰ใ‚’ๅค‰ๆ›ดใ—ใŸใ‚‰ใ‚ตใƒผใƒใƒผใ‚’ๅ†่ตทๅ‹•ใ—ใพใ™ใ€‚ใ“ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฏ้–‹็™บ็’ฐๅขƒใงใฎใฟไฝฟ็”จใ—ใพใ™ +่ฉณใ—ใใฏ FastAPI CLI docs ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚
-### ๅ‹•ไฝœ็ขบ่ช +### ๅ‹•ไฝœ็ขบ่ช { #check-it } -ใƒ–ใƒฉใ‚ฆใ‚ถใ‹ใ‚‰http://127.0.0.1:8000/items/5?q=somequeryใ‚’้–‹ใใพใ™ใ€‚ +ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/items/5?q=somequery ใ‚’้–‹ใใพใ™ใ€‚ -ไปฅไธ‹ใฎ JSON ใฎใƒฌใ‚นใƒใƒณใ‚นใŒ็ขบ่ชใงใใพใ™: +ไปฅไธ‹ใฎ JSON ใฎใƒฌใ‚นใƒใƒณใ‚นใŒ็ขบ่ชใงใใพใ™ใ€‚ ```JSON {"item_id": 5, "q": "somequery"} ``` -ใ‚‚ใ†ใ™ใงใซไปฅไธ‹ใฎ API ใŒไฝœๆˆใ•ใ‚Œใฆใ„ใพใ™: +ใ™ใงใซไปฅไธ‹ใฎ API ใŒไฝœๆˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -- `/` ใจ `/items/{item_id}`ใฎใƒ‘ใ‚นใง HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ใพใ™ใ€‚ -- ใฉใกใ‚‰ใฎใƒ‘ใ‚นใ‚‚ `GET` ๆ“ไฝœ ใ‚’ๅ–ใ‚Šใพใ™ใ€‚(HTTP ใƒกใ‚ฝใƒƒใƒ‰ใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚) -- `/items/{item_id}` ใƒ‘ใ‚นใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item_id` ใฏ `int` ใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ -- ใƒ‘ใ‚น `/items/{item_id}` ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `str` ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใ‚’ๆŒใกใพใ™ใ€‚ +* _ใƒ‘ใ‚น_ `/` ใจ `/items/{item_id}` ใง HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ +* ไธกๆ–นใฎ _ใƒ‘ใ‚น_ ใฏ `GET` ๆ“ไฝœ๏ผˆHTTP _ใƒกใ‚ฝใƒƒใƒ‰_ ใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™๏ผ‰ใ‚’ๅ–ใ‚Šใพใ™ใ€‚ +* _ใƒ‘ใ‚น_ `/items/{item_id}` ใฏ `int` ใงใ‚ใ‚‹ในใ _ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ_ `item_id` ใ‚’ๆŒใกใพใ™ใ€‚ +* _ใƒ‘ใ‚น_ `/items/{item_id}` ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `str` _ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ_ `q` ใ‚’ๆŒใกใพใ™ใ€‚ -### ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +### ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #interactive-api-docs } -http://127.0.0.1:8000/docsใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ +ๆฌกใซใ€http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ -่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ (Swagger UIใŒๆไพ›ใ—ใฆใ„ใพใ™ใ€‚): +่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™๏ผˆSwagger UI ใŒๆไพ›ใ—ใฆใ„ใพใ™๏ผ‰ใ€‚ ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ไปฃๆ›ฟใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +### ไปฃๆ›ฟ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #alternative-api-docs } -http://127.0.0.1:8000/redocใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ +ๆฌกใซใ€http://127.0.0.1:8000/redoc ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ -ไปฃๆ›ฟใฎ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚(ReDocใŒๆไพ›ใ—ใฆใ„ใพใ™ใ€‚): +ไปฃๆ›ฟใฎ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™๏ผˆReDoc ใŒๆไพ›ใ—ใฆใ„ใพใ™๏ผ‰ใ€‚ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ไพ‹ +## ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ไพ‹ { #example-upgrade } -`PUT`ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒœใƒ‡ใ‚ฃใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใซ`main.py`ใ‚’ไฟฎๆญฃใ—ใพใ—ใ‚‡ใ†ใ€‚ +ๆฌกใซใ€`PUT` ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒœใƒ‡ใ‚ฃใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใซ `main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฟฎๆญฃใ—ใพใ—ใ‚‡ใ†ใ€‚ -Pydantic ใซใ‚ˆใฃใฆใ€Python ใฎๆจ™ๆบ–็š„ใชๅž‹ใ‚’ไฝฟใฃใฆใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +Pydantic ใซใ‚ˆใฃใฆใ€ๆจ™ๆบ–็š„ใช Python ใฎๅž‹ใ‚’ไฝฟใฃใฆใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ -```Python hl_lines="2 7 8 9 10 23 24 25" +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -272,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: bool = None + is_offer: bool | None = None @app.get("/") @@ -281,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: str = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -290,173 +312,248 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -ใ‚ตใƒผใƒใƒผใฏ่‡ชๅ‹•ใงใƒชใƒญใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚(ไธŠ่ฟฐใฎ`uvicorn`ใ‚ณใƒžใƒณใƒ‰ใง`--reload`ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚) +`fastapi dev` ใ‚ตใƒผใƒใƒผใฏ่‡ชๅ‹•ใงใƒชใƒญใƒผใƒ‰ใ•ใ‚Œใ‚‹ใฏใšใงใ™ใ€‚ -### ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ +### ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ { #interactive-api-docs-upgrade } -http://127.0.0.1:8000/docsใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ—ใ‚‡ใ†ใ€‚ +ๆฌกใซใ€http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ -- ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒๆ–ฐใ—ใ„ใƒœใƒ‡ใ‚ฃใ‚‚ๅซใ‚ใฆ่‡ชๅ‹•ใงใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆใ•ใ‚Œใพใ™: +* ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๆ–ฐใ—ใ„ใƒœใƒ‡ใ‚ฃใ‚‚ๅซใ‚ใฆ่‡ชๅ‹•ใงใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆใ•ใ‚Œใพใ™ใ€‚ ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -- "Try it out"ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใใ ใ•ใ„ใ€‚ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…ฅๅŠ›ใ—ใฆ API ใจ็›ดๆŽฅใ‚„ใ‚Šใจใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +* ใ€ŒTry it outใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใพใ™ใ€‚ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…ฅๅŠ›ใ—ใฆ API ใจ็›ดๆŽฅใ‚„ใ‚Šใจใ‚Šใงใใพใ™ใ€‚ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -- ใใ‚Œใ‹ใ‚‰ใ€"Execute" ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใใ ใ•ใ„ใ€‚ ใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใฏ API ใจ้€šไฟกใ—ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’้€ไฟกใ—ใ€็ตๆžœใ‚’ๅ–ๅพ—ใ—ใฆ็”ป้ขใซ่กจ็คบใ—ใพใ™: +* ๆฌกใซใ€ใ€ŒExecuteใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใพใ™ใ€‚ใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใฏ API ใจ้€šไฟกใ—ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’้€ไฟกใ—ใ€็ตๆžœใ‚’ๅ–ๅพ—ใ—ใฆ็”ป้ขใซ่กจ็คบใ—ใพใ™ใ€‚ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) -### ไปฃๆ›ฟใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ +### ไปฃๆ›ฟ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ { #alternative-api-docs-upgrade } -http://127.0.0.1:8000/redocใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ—ใ‚‡ใ†ใ€‚ +ๆฌกใซใ€http://127.0.0.1:8000/redoc ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ -- ไปฃๆ›ฟใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚‚ๆ–ฐใ—ใ„ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใŒๅๆ˜ ใ•ใ‚Œใพใ™ใ€‚ +* ไปฃๆ›ฟใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚‚ๆ–ฐใ—ใ„ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใŒๅๆ˜ ใ•ใ‚Œใพใ™ใ€‚ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ใพใจใ‚ +### ใพใจใ‚ { #recap } -่ฆ็ด„ใ™ใ‚‹ใจใ€้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃ ใชใฉใฎๅž‹ใ‚’**ไธ€ๅบฆใ ใ‘**ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +่ฆ็ด„ใ™ใ‚‹ใจใ€้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใชใฉใฎๅž‹ใ‚’ **ไธ€ๅบฆใ ใ‘** ๅฎฃ่จ€ใ—ใพใ™ใ€‚ -ๆจ™ๆบ–็š„ใชๆœ€ๆ–ฐใฎ Python ใฎๅž‹ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ +ๆจ™ๆบ–็š„ใชๆœ€ๆ–ฐใฎ Python ใฎๅž‹ใ‚’ไฝฟใ„ใพใ™ใ€‚ ๆ–ฐใ—ใ„ๆง‹ๆ–‡ใ‚„็‰นๅฎšใฎใƒฉใ‚คใƒ–ใƒฉใƒชใฎใƒกใ‚ฝใƒƒใƒ‰ใ‚„ใ‚ฏใƒฉใ‚นใชใฉใ‚’่ฆšใˆใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ๅ˜ใชใ‚‹ๆจ™ๆบ–็š„ใช**3.8 ไปฅ้™ใฎ Python**ใงใ™ใ€‚ +ๅ˜ใชใ‚‹ๆจ™ๆบ–็š„ใช **Python** ใงใ™ใ€‚ -ไพ‹ใˆใฐใ€`int`ใฎๅ ดๅˆ: +ไพ‹ใˆใฐใ€`int` ใฎๅ ดๅˆ: ```Python item_id: int ``` -ใพใŸใฏใ€ใ‚ˆใ‚Š่ค‡้›‘ใช`Item`ใƒขใƒ‡ใƒซใฎๅ ดๅˆ: +ใพใŸใฏใ€ใ‚ˆใ‚Š่ค‡้›‘ใช `Item` ใƒขใƒ‡ใƒซใฎๅ ดๅˆ: ```Python item: Item ``` -...ใใ—ใฆใ€ใ“ใฎไธ€ๅบฆใฎๅฎฃ่จ€ใงใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: - -- ไปฅไธ‹ใ‚’ๅซใ‚€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ: - - ่ฃœๅฎŒ - - ใ‚ฟใ‚คใƒ—ใƒใ‚งใƒƒใ‚ฏ -- ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ: - - ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใซ่‡ชๅ‹•ใงใ‚จใƒฉใƒผใ‚’ใ‚ฏใƒชใ‚ขใ—ใพใ™ใ€‚ - - ๆทฑใ„ๅ…ฅใ‚ŒๅญใซใชใฃใŸ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ‚‚ๆคœ่จผใŒๅฏ่ƒฝใงใ™ใ€‚ -- ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›: ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‹ใ‚‰ Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใซๅค‰ๆ›ใ—ใฆใ‹ใ‚‰่ชญใฟๅ–ใ‚Šใพใ™: - - JSON. - - ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ - - ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ - - ใ‚ฏใƒƒใ‚ญใƒผ - - ใƒ˜ใƒƒใƒ€ใƒผ - - ใƒ•ใ‚ฉใƒผใƒ  - - ใƒ•ใ‚กใ‚คใƒซ -- ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›: Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใ‹ใ‚‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใƒ‡ใƒผใ‚ฟใธๅค‰ๆ›ใ—ใพใ™ (JSON ใจใ—ใฆ): - - Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). - - `datetime` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ - - `UUID` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ - - ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซ - - ...ใชใฉใชใฉ -- 2 ใคใฎไปฃๆ›ฟใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚’ๅซใ‚€่‡ชๅ‹•ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ– API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ: - - Swagger UI. - - ReDoc. +...ใใ—ใฆใ€ใ“ใฎไธ€ๅบฆใฎๅฎฃ่จ€ใงใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ + +* ไปฅไธ‹ใ‚’ๅซใ‚€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ: + * ่ฃœๅฎŒใ€‚ + * ๅž‹ใƒใ‚งใƒƒใ‚ฏใ€‚ +* ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ: + * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใซ่‡ชๅ‹•ใงๆ˜Ž็ขบใชใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ + * ๆทฑใ„ๅ…ฅใ‚ŒๅญใซใชใฃใŸ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ‚‚ๆคœ่จผใŒๅฏ่ƒฝใงใ™ใ€‚ +* ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‹ใ‚‰ Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใธใ€‚ไปฅไธ‹ใ‹ใ‚‰่ชญใฟๅ–ใ‚Šใพใ™: + * JSONใ€‚ + * ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ + * ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ + * Cookieใ€‚ + * ใƒ˜ใƒƒใƒ€ใƒผใ€‚ + * ใƒ•ใ‚ฉใƒผใƒ ใ€‚ + * ใƒ•ใ‚กใ‚คใƒซใ€‚ +* ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใ‹ใ‚‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใƒ‡ใƒผใ‚ฟใธ๏ผˆJSON ใจใ—ใฆ๏ผ‰ๅค‰ๆ›ใ—ใพใ™: + * Python ใฎๅž‹๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ใชใฉ๏ผ‰ใฎๅค‰ๆ›ใ€‚ + * `datetime` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€‚ + * `UUID` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€‚ + * ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซใ€‚ + * ...ใชใฉใชใฉใ€‚ +* 2 ใคใฎไปฃๆ›ฟใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚’ๅซใ‚€่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ: + * Swagger UIใ€‚ + * ReDocใ€‚ --- -ใ‚ณใƒผใƒ‰ไพ‹ใซๆˆปใ‚Šใพใ—ใ‚‡ใ†ใ€**FastAPI** ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: - -- `GET`ใŠใ‚ˆใณ`PUT`ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‘ใ‚นใซ`item_id` ใŒใ‚ใ‚‹ใ“ใจใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ -- `item_id`ใŒ`GET`ใŠใ‚ˆใณ`PUT`ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆ`int` ๅž‹ใงใ‚ใ‚‹ใ“ใจใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ - - ใใ†ใงใชใ„ๅ ดๅˆใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๆœ‰็”จใงๆ˜Ž็ขบใชใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ -- `GET` ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` (`http://127.0.0.1:8000/items/foo?q=somequery` ใฎใ‚ˆใ†ใซ) ใŒๅญ˜ๅœจใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’่ชฟในใพใ™ใ€‚ - - ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฏ `= None` ใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ™ใ€‚ - - `None`ใŒใชใ‘ใ‚Œใฐๅฟ…้ ˆใซใชใ‚Šใพใ™๏ผˆ`PUT`ใฎๅ ดๅˆใฎใƒœใƒ‡ใ‚ฃใจๅŒๆง˜ใงใ™๏ผ‰ใ€‚ -- `PUT` ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ `/items/{item_id}` ใซ้€ไฟกใ™ใ‚‹ๅ ดๅˆใฏใ€ใƒœใƒ‡ใ‚ฃใ‚’ JSON ใจใ—ใฆ่ชญใฟ่พผใฟใพใ™: - - ๅฟ…้ ˆใฎๅฑžๆ€ง `name` ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ ใใ‚Œใฏ `str` ใงใ‚ใ‚‹ในใใงใ™ใ€‚ - - ๅฟ…้ ˆใฎๅฑžๆ€ง `price` ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ใใ‚Œใฏ `float` ใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใงใ™ใ€‚ - - ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎๅฑžๆ€ง `is_offer` ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ๅ€คใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€`bool` ใงใ‚ใ‚‹ในใใงใ™ใ€‚ - - ใ“ใ‚Œใ‚‰ใฏใ™ในใฆใ€ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๅฏพใ—ใฆใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚ -- JSON ใ‹ใ‚‰ JSON ใซ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -- OpenAPIใงใ™ในใฆใ‚’ๆ–‡ๆ›ธๅŒ–ใ—ใ€ไปฅไธ‹ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: - - ๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใ€‚ - - ๅคšใใฎ่จ€่ชžใซๅฏพๅฟœใ—ใŸ่‡ชๅ‹•ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰็”Ÿๆˆใ‚ทใ‚นใƒ†ใƒ ใ€‚ -- 2 ใคใฎๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎWebใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใ‚คใ‚นใ‚’็›ดๆŽฅๆไพ›ใ—ใพใ™ใ€‚ +ๅ‰ใฎใ‚ณใƒผใƒ‰ไพ‹ใซๆˆปใ‚‹ใจใ€**FastAPI** ใฏๆฌกใฎใ‚ˆใ†ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ + +* `GET` ใŠใ‚ˆใณ `PUT` ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‘ใ‚นใซ `item_id` ใŒใ‚ใ‚‹ใ“ใจใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ +* `GET` ใŠใ‚ˆใณ `PUT` ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆ `item_id` ใŒ `int` ๅž‹ใงใ‚ใ‚‹ใ“ใจใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ + * ใใ†ใงใชใ„ๅ ดๅˆใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๆœ‰็”จใงๆ˜Ž็ขบใชใ‚จใƒฉใƒผใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ +* `GET` ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆใ€`q` ใจใ„ใ†ๅๅ‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆ`http://127.0.0.1:8000/items/foo?q=somequery` ใฎใ‚ˆใ†ใช๏ผ‰ใŒๅญ˜ๅœจใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’่ชฟในใพใ™ใ€‚ + * `q` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ `= None` ใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใŸใ‚ใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ™ใ€‚ + * `None` ใŒใชใ‘ใ‚Œใฐๅฟ…้ ˆใซใชใ‚Šใพใ™๏ผˆ`PUT` ใฎๅ ดๅˆใฎใƒœใƒ‡ใ‚ฃใจๅŒๆง˜ใงใ™๏ผ‰ใ€‚ +* `PUT` ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ `/items/{item_id}` ใซ้€ไฟกใ™ใ‚‹ๅ ดๅˆใ€ใƒœใƒ‡ใ‚ฃใ‚’ JSON ใจใ—ใฆ่ชญใฟ่พผใฟใพใ™: + * ๅฟ…้ ˆใฎๅฑžๆ€ง `name` ใŒใ‚ใ‚Šใ€`str` ใงใ‚ใ‚‹ในใใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + * ๅฟ…้ ˆใฎๅฑžๆ€ง `price` ใŒใ‚ใ‚Šใ€`float` ใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + * ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎๅฑžๆ€ง `is_offer` ใŒใ‚ใ‚Šใ€ๅญ˜ๅœจใ™ใ‚‹ๅ ดๅˆใฏ `bool` ใงใ‚ใ‚‹ในใใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใ‚‰ใฏใ™ในใฆใ€ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๅฏพใ—ใฆใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚ +* JSON ใธใฎ/ใ‹ใ‚‰ใฎๅค‰ๆ›ใ‚’่‡ชๅ‹•็š„ใซ่กŒใ„ใพใ™ใ€‚ +* OpenAPI ใงใ™ในใฆใ‚’ๆ–‡ๆ›ธๅŒ–ใ—ใ€ไปฅไธ‹ใงๅˆฉ็”จใงใใพใ™: + * ๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใ€‚ + * ๅคšใใฎ่จ€่ชžใซๅฏพๅฟœใ—ใŸ่‡ชๅ‹•ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰็”Ÿๆˆใ‚ทใ‚นใƒ†ใƒ ใ€‚ +* 2 ใคใฎๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ Web ใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚’็›ดๆŽฅๆไพ›ใ—ใพใ™ใ€‚ --- -ใพใ ่กจ้ข็š„ใช้ƒจๅˆ†ใซ่งฆใ‚ŒใŸใ ใ‘ใงใ™ใŒใ€ใ‚‚ใ†ๅ…จใฆใฎไป•็ต„ใฟใฏๅˆ†ใ‹ใฃใฆใ„ใ‚‹ใฏใšใงใ™ใ€‚ +ใพใ ่กจ้ข็š„ใช้ƒจๅˆ†ใซ่งฆใ‚ŒใŸใ ใ‘ใงใ™ใŒใ€ไป•็ต„ใฟใฏใ™ใงใซใ‚คใƒกใƒผใ‚ธใงใใฆใ„ใ‚‹ใฏใšใงใ™ใ€‚ -ไปฅไธ‹ใฎ่กŒใ‚’ๅค‰ๆ›ดใ—ใฆใฟใฆใใ ใ•ใ„: +ไปฅไธ‹ใฎ่กŒใ‚’ๅค‰ๆ›ดใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ ```Python return {"item_name": item.name, "item_id": item_id} ``` -...ไปฅไธ‹ใ‚’: +...ไปฅไธ‹ใฎ: ```Python ... "item_name": item.name ... ``` -...ไปฅไธ‹ใฎใ‚ˆใ†ใซ: +...ใ‚’: ```Python ... "item_price": item.price ... ``` -...ใใ—ใฆใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒๅฑžๆ€งใ‚’่‡ชๅ‹•่ฃœๅฎŒใ—ใ€ใใฎใ‚ฟใ‚คใƒ—ใ‚’็Ÿฅใ‚‹ๆ–นๆณ•ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚: +...ใซๅค‰ๆ›ดใ—ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒๅฑžๆ€งใ‚’่‡ชๅ‹•่ฃœๅฎŒใ—ใ€ใใฎๅž‹ใ‚’็Ÿฅใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -ใ‚ˆใ‚ŠๅคšใใฎๆฉŸ่ƒฝใ‚’ๅซใ‚€ใ€ใ‚ˆใ‚ŠๅฎŒๅ…จใชไพ‹ใซใคใ„ใฆใฏใ€ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ +ใ‚ˆใ‚ŠๅคšใใฎๆฉŸ่ƒฝใ‚’ๅซใ‚€ใ€ใ‚ˆใ‚ŠๅฎŒๅ…จใชไพ‹ใซใคใ„ใฆใฏใ€Tutorial - User Guide ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +**ใƒใ‚ฟใƒใƒฌๆณจๆ„**: tutorial - user guide ใซใฏไปฅไธ‹ใŒๅซใพใ‚Œใพใ™ใ€‚ + +* **ใƒ˜ใƒƒใƒ€ใƒผ**ใ€**Cookie**ใ€**ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใ€**ใƒ•ใ‚กใ‚คใƒซ**ใชใฉใ€ไป–ใฎใ•ใพใ–ใพใชๅ ดๆ‰€ใ‹ใ‚‰ใฎ **ใƒ‘ใƒฉใƒกใƒผใ‚ฟ** ๅฎฃ่จ€ใ€‚ +* `maximum_length` ใ‚„ `regex` ใฎใ‚ˆใ†ใช **ๆคœ่จผๅˆถ็ด„** ใ‚’่จญๅฎšใ™ใ‚‹ๆ–นๆณ•ใ€‚ +* ้žๅธธใซๅผทๅŠ›ใงไฝฟใ„ใ‚„ใ™ใ„ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ€‚ +* **JWT ใƒˆใƒผใ‚ฏใƒณ**ใ‚’็”จใ„ใŸ **OAuth2** ใ‚„ **HTTP Basic** ่ช่จผใฎใ‚ตใƒใƒผใƒˆใ‚’ๅซใ‚€ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใ€‚ +* **ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON ใƒขใƒ‡ใƒซ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎใ€ใ‚ˆใ‚Š้ซ˜ๅบฆใช๏ผˆใ—ใ‹ใ—ๅŒๆง˜ใซ็ฐกๅ˜ใช๏ผ‰ๆ‰‹ๆณ•๏ผˆPydantic ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ +* Strawberry ใŠใ‚ˆใณไป–ใฎใƒฉใ‚คใƒ–ใƒฉใƒชใซใ‚ˆใ‚‹ **GraphQL** ็ตฑๅˆใ€‚ +* ไปฅไธ‹ใฎใ‚ˆใ†ใชใŸใใ•ใ‚“ใฎใŠใพใ‘ๆฉŸ่ƒฝ๏ผˆStarlette ใฎใŠใ‹ใ’ใงใ™๏ผ‰: + * **WebSockets** + * HTTPX ใจ `pytest` ใซๅŸบใฅใๆฅตใ‚ใฆ็ฐกๅ˜ใชใƒ†ใ‚นใƒˆ + * **CORS** + * **Cookie Sessions** + * ...ใชใฉใชใฉใ€‚ + +### ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚ค๏ผˆไปปๆ„๏ผ‰ { #deploy-your-app-optional } + +ๅฟ…่ฆใซๅฟœใ˜ใฆ FastAPI ใ‚ขใƒ—ใƒชใ‚’ FastAPI Cloud ใซใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ใพใ ใฎๅ ดๅˆใฏใ‚ฆใ‚งใ‚คใƒ†ใ‚ฃใƒณใ‚ฐใƒชใ‚นใƒˆใซๅ‚ๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ ๐Ÿš€ -**ใƒใ‚ฟใƒใƒฌๆณจๆ„**: ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ใฏไปฅไธ‹ใฎๆƒ…ๅ ฑใŒๅซใพใ‚Œใฆใ„ใพใ™: +ใ™ใงใซ **FastAPI Cloud** ใ‚ขใ‚ซใ‚ฆใƒณใƒˆ๏ผˆใ‚ฆใ‚งใ‚คใƒ†ใ‚ฃใƒณใ‚ฐใƒชใ‚นใƒˆใ‹ใ‚‰ๆ‹›ๅพ…ใ•ใ‚Œใพใ—ใŸ ๐Ÿ˜‰๏ผ‰ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€1 ใ‚ณใƒžใƒณใƒ‰ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ -- **ใƒ˜ใƒƒใƒ€ใƒผ**ใ€**ใ‚ฏใƒƒใ‚ญใƒผ**ใ€**ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใ€**ใƒ•ใ‚กใ‚คใƒซ**ใชใฉใฎไป–ใฎๅ ดๆ‰€ใ‹ใ‚‰ใฎ **ใƒ‘ใƒฉใƒกใƒผใ‚ฟ** ๅฎฃ่จ€ใ€‚ -- `maximum_length`ใ‚„`regex`ใฎใ‚ˆใ†ใช**ๆคœ่จผใ‚„ๅˆถ็ด„**ใ‚’่จญๅฎšใ™ใ‚‹ๆ–นๆณ•ใ€‚ -- ้žๅธธใซๅผทๅŠ›ใงไฝฟใ„ใ‚„ใ™ใ„ **ไพๅญ˜ๆ€งๆณจๅ…ฅ**ใ‚ทใ‚นใƒ†ใƒ ใ€‚ -- **JWT ใƒˆใƒผใ‚ฏใƒณ**ใ‚’็”จใ„ใŸ **OAuth2** ใ‚„ **HTTP Basic ่ช่จผ** ใฎใ‚ตใƒใƒผใƒˆใ‚’ๅซใ‚€ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใ€‚ -- **ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON ใƒขใƒ‡ใƒซ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎใ‚ˆใ‚Š้ซ˜ๅบฆใช๏ผˆใ—ใ‹ใ—ๅŒๆง˜ใซ็ฐกๅ˜ใช๏ผ‰ๆŠ€่ก“๏ผˆPydantic ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ -- ไปฅไธ‹ใฎใ‚ˆใ†ใชใŸใใ•ใ‚“ใฎใŠใพใ‘ๆฉŸ่ƒฝ(Starlette ใฎใŠใ‹ใ’ใงใ™): - - **WebSockets** - - **GraphQL** - - `httpx` ใ‚„ `pytest`ใ‚’ใ‚‚ใจใซใ—ใŸๆฅต้™ใซ็ฐกๅ˜ใชใƒ†ใ‚นใƒˆ - - **CORS** - - **ใ‚ฏใƒƒใ‚ญใƒผใ‚ปใƒƒใ‚ทใƒงใƒณ** - - ...ใชใฉใชใฉใ€‚ +ใƒ‡ใƒ—ใƒญใ‚คๅ‰ใซใ€ใƒญใ‚ฐใ‚คใƒณใ—ใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ -## ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` -็‹ฌ็ซ‹ใ—ใŸ TechEmpower ใฎใƒ™ใƒณใƒใƒžใƒผใ‚ฏใงใฏใ€Uvicorn ใงๅ‹•ไฝœใ™ใ‚‹**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ€Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธญใงๆœ€ใ‚‚้ซ˜้€Ÿใชใ‚‚ใฎใฎ 1 ใคใงใ‚ใ‚Šใ€Starlette ใจ Uvicorn๏ผˆFastAPI ใงๅ†…้ƒจ็š„ใซไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ™๏ผ‰ใซใฎใฟไธ‹ๅ›žใฃใฆใ„ใ‚‹ใจ็คบใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +
-่ฉณ็ดฐใฏใƒ™ใƒณใƒใƒžใƒผใ‚ฏใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ +ๆฌกใซใ€ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใพใ™ใ€‚ -## ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎไพๅญ˜้–ขไฟ‚ +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ใ“ใ‚ŒใงๅฎŒไบ†ใงใ™๏ผใใฎ URL ใงใ‚ขใƒ—ใƒชใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ โœจ + +#### FastAPI Cloud ใซใคใ„ใฆ { #about-fastapi-cloud } + +**FastAPI Cloud** ใฏ **FastAPI** ใฎไฝœ่€…ใจๅŒใ˜ใƒใƒผใƒ ใซใ‚ˆใฃใฆไฝœใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ + +ๆœ€ๅฐ้™ใฎๅŠดๅŠ›ใง API ใ‚’ **ๆง‹็ฏ‰**ใ€**ใƒ‡ใƒ—ใƒญใ‚ค**ใ€**ใ‚ขใ‚ฏใ‚ปใ‚น** ใ™ใ‚‹ใŸใ‚ใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ๅŠน็އๅŒ–ใ—ใพใ™ใ€‚ + +FastAPI ใงใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใฎใจๅŒใ˜ **้–‹็™บ่€…ไฝ“้จ“** ใ‚’ใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใธใฎ **ใƒ‡ใƒ—ใƒญใ‚ค** ใซใ‚‚ใ‚‚ใŸใ‚‰ใ—ใพใ™ใ€‚ ๐ŸŽ‰ + +FastAPI Cloud ใฏ *FastAPI and friends* ใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไธป่ฆใ‚นใƒใƒณใ‚ตใƒผใงใ‚ใ‚Šใ€่ณ‡้‡‘ๆไพ›ๅ…ƒใงใ™ใ€‚ โœจ + +#### ไป–ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใซใƒ‡ใƒ—ใƒญใ‚ค { #deploy-to-other-cloud-providers } + +FastAPI ใฏใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใงใ‚ใ‚Šใ€ๆจ™ๆบ–ใซๅŸบใฅใ„ใฆใ„ใพใ™ใ€‚้ธๆŠžใ—ใŸไปปๆ„ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใซ FastAPI ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ + +ๅ„ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใฎใ‚ฌใ‚คใƒ‰ใซๅพ“ใฃใฆใ€FastAPI ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใฆใใ ใ•ใ„ใ€‚ ๐Ÿค“ + +## ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น { #performance } + +็‹ฌ็ซ‹ใ—ใŸ TechEmpower ใฎใƒ™ใƒณใƒใƒžใƒผใ‚ฏใงใฏใ€Uvicorn ใงๅ‹•ไฝœใ™ใ‚‹ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ€ๅˆฉ็”จๅฏ่ƒฝใชๆœ€ใ‚‚้ซ˜้€Ÿใช Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธ€ใคใงใ‚ใ‚Šใ€Starlette ใจ Uvicorn๏ผˆFastAPI ใงๅ†…้ƒจ็š„ใซไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ™๏ผ‰ใซใฎใฟไธ‹ๅ›žใฃใฆใ„ใ‚‹ใจ็คบใ•ใ‚Œใฆใ„ใพใ™ใ€‚๏ผˆ*๏ผ‰ + +่ฉณ็ดฐใฏ Benchmarks ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ + +## ไพๅญ˜้–ขไฟ‚ { #dependencies } + +FastAPI ใฏ Pydantic ใจ Starlette ใซไพๅญ˜ใ—ใฆใ„ใพใ™ใ€‚ + +### `standard` ไพๅญ˜้–ขไฟ‚ { #standard-dependencies } + +FastAPI ใ‚’ `pip install "fastapi[standard]"` ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจใ€`standard` ใ‚ฐใƒซใƒผใƒ—ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณไพๅญ˜้–ขไฟ‚ใŒๅซใพใ‚Œใพใ™ใ€‚ Pydantic ใซใ‚ˆใฃใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: -- email-validator - E ใƒกใƒผใƒซใฎๆคœ่จผ +* email-validator - ใƒกใƒผใƒซๆคœ่จผใฎใŸใ‚ใ€‚ Starlette ใซใ‚ˆใฃใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: -- httpx - `TestClient`ใ‚’ไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใงใ™ใ€‚ -- jinja2 - ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ่จญๅฎšใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฏๅฟ…่ฆใงใ™ใ€‚ -- python-multipart - "parsing"`request.form()`ใ‹ใ‚‰ใฎๅค‰ๆ›ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใŸใ„ๅ ดๅˆใฏๅฟ…่ฆใงใ™ใ€‚ -- itsdangerous - `SessionMiddleware` ใ‚ตใƒใƒผใƒˆใฎใŸใ‚ใซใฏๅฟ…่ฆใงใ™ใ€‚ -- pyyaml - Starlette ใฎ `SchemaGenerator` ใ‚ตใƒใƒผใƒˆใฎใŸใ‚ใซๅฟ…่ฆใงใ™ใ€‚ (FastAPI ใงใฏๅฟ…่ฆใชใ„ใงใ—ใ‚‡ใ†ใ€‚) -- graphene - `GraphQLApp` ใ‚ตใƒใƒผใƒˆใฎใŸใ‚ใซใฏๅฟ…่ฆใงใ™ใ€‚ +* httpx - `TestClient` ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ +* jinja2 - ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ่จญๅฎšใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ +* python-multipart - `request.form()` ใจใจใ‚‚ใซใ€ใƒ•ใ‚ฉใƒผใƒ ใฎ ใ€Œparsingใ€ ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ + +FastAPI ใซใ‚ˆใฃใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: + +* uvicorn - ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒญใƒผใƒ‰ใ—ใฆๆไพ›ใ™ใ‚‹ใ‚ตใƒผใƒใƒผใฎใŸใ‚ใ€‚ใ“ใ‚Œใซใฏ `uvicorn[standard]` ใ‚‚ๅซใพใ‚Œใ€้ซ˜ๆ€ง่ƒฝใชใ‚ตใƒผใƒ“ใƒณใ‚ฐใซๅฟ…่ฆใชไพๅญ˜้–ขไฟ‚๏ผˆไพ‹: `uvloop`๏ผ‰ใŒๅซใพใ‚Œใพใ™ใ€‚ +* `fastapi-cli[standard]` - `fastapi` ใ‚ณใƒžใƒณใƒ‰ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใซใฏ `fastapi-cloud-cli` ใŒๅซใพใ‚Œใ€FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ FastAPI Cloud ใซใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ + +### `standard` ไพๅญ˜้–ขไฟ‚ใชใ— { #without-standard-dependencies } + +`standard` ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณไพๅญ˜้–ขไฟ‚ใ‚’ๅซใ‚ใŸใใชใ„ๅ ดๅˆใฏใ€`pip install "fastapi[standard]"` ใฎไปฃใ‚ใ‚Šใซ `pip install fastapi` ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ + +### `fastapi-cloud-cli` ใชใ— { #without-fastapi-cloud-cli } + +ๆจ™ๆบ–ใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅซใ‚ใคใค `fastapi-cloud-cli` ใ‚’้™คๅค–ใ—ใฆ FastAPI ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใ„ๅ ดๅˆใฏใ€`pip install "fastapi[standard-no-fastapi-cloud-cli]"` ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ + +### ่ฟฝๅŠ ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณไพๅญ˜้–ขไฟ‚ { #additional-optional-dependencies } + +่ฟฝๅŠ ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใ„ไพๅญ˜้–ขไฟ‚ใŒใ‚ใ‚Šใพใ™ใ€‚ + +่ฟฝๅŠ ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณ Pydantic ไพๅญ˜้–ขไฟ‚: -FastAPI / Starlette ใซไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: +* pydantic-settings - ่จญๅฎš็ฎก็†ใฎใŸใ‚ใ€‚ +* pydantic-extra-types - Pydantic ใงไฝฟ็”จใ™ใ‚‹่ฟฝๅŠ ใฎๅž‹ใฎใŸใ‚ใ€‚ -- uvicorn - ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒญใƒผใƒ‰ใ—ใฆใ‚ตใƒผใƒ–ใ™ใ‚‹ใ‚ตใƒผใƒใƒผใฎใŸใ‚ใ€‚ -- orjson - `ORJSONResponse`ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใฏๅฟ…่ฆใงใ™ใ€‚ -- ujson - `UJSONResponse`ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฏๅฟ…้ ˆใงใ™ใ€‚ +่ฟฝๅŠ ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณ FastAPI ไพๅญ˜้–ขไฟ‚: -ใ“ใ‚Œใ‚‰ใฏๅ…จใฆ `pip install fastapi[all]`ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ +* orjson - `ORJSONResponse` ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ +* ujson - `UJSONResponse` ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ -## ใƒฉใ‚คใ‚ปใƒณใ‚น +## ใƒฉใ‚คใ‚ปใƒณใ‚น { #license } -ใ“ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฏ MIT ใƒฉใ‚คใ‚ปใƒณใ‚นใงใ™ใ€‚ +ใ“ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฏ MIT ใƒฉใ‚คใ‚ปใƒณใ‚นใฎๆก้ …ใฎไธ‹ใงใƒฉใ‚คใ‚ปใƒณใ‚นใ•ใ‚Œใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/learn/index.md b/docs/ja/docs/learn/index.md index 2f24c670a7..bcdb1e37ee 100644 --- a/docs/ja/docs/learn/index.md +++ b/docs/ja/docs/learn/index.md @@ -1,5 +1,5 @@ -# ๅญฆ็ฟ’ +# ๅญฆ็ฟ’ { #learn } ใ“ใ“ใงใฏใ€**FastAPI** ใ‚’ๅญฆ็ฟ’ใ™ใ‚‹ใŸใ‚ใฎๅ…ฅ้–€ใ‚ปใ‚ฏใ‚ทใƒงใƒณใจใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ -ใ“ใ‚Œใฏใ€FastAPIใ‚’ๅญฆ็ฟ’ใ™ใ‚‹ใซใ‚ใŸใฃใฆใฎ**ๆ›ธ็ฑ**ใ‚„**ใ‚ณใƒผใ‚น**ใงใ‚ใ‚Šใ€**ๅ…ฌๅผ**ใ‹ใคๆŽจๅฅจใ•ใ‚Œใ‚‹ๆ–นๆณ•ใจใฟใชใ™ใ“ใจใŒใงใใพใ™ ๐Ÿ˜Ž +ใ“ใ‚Œใฏใ€**ๆ›ธ็ฑ**ใ‚„**ใ‚ณใƒผใ‚น**ใ€FastAPIใ‚’ๅญฆ็ฟ’ใ™ใ‚‹ใŸใ‚ใฎ**ๅ…ฌๅผ**ใ‹ใคๆŽจๅฅจใ•ใ‚Œใ‚‹ๆ–นๆณ•ใจใฟใชใ™ใ“ใจใŒใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/project-generation.md b/docs/ja/docs/project-generation.md index daef52efae..c930fb557c 100644 --- a/docs/ja/docs/project-generation.md +++ b/docs/ja/docs/project-generation.md @@ -1,84 +1,28 @@ -# ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ็”Ÿๆˆ - ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ - -ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใฏใ€ๅˆๆœŸ่จญๅฎšใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ๅˆๆœŸAPIใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใชใฉใฎๅคšใใŒๅซใพใ‚Œใฆใ„ใ‚‹ใŸใ‚ใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎ้–‹ๅง‹ใซๅˆฉ็”จใงใใพใ™ใ€‚ - -ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใฏๅธธใซ้žๅธธใซๆ„่ฆ‹ใŒๅˆ†ใ‹ใ‚Œใ‚‹่จญๅฎšใŒใ•ใ‚ŒใฆใŠใ‚Šใ€ใƒ‹ใƒผใ‚บใซๅˆใ‚ใ›ใฆๆ›ดๆ–ฐใŠใ‚ˆใณ่ชฟๆ•ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ—ใ‹ใ—ใใฃใจใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎ่‰ฏใ„ๅ‡บ็™บ็‚นใจใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ - -## ใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏ FastAPI PostgreSQL - -GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql - -### ใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏ FastAPI PostgreSQL - ๆฉŸ่ƒฝ - -* ๅฎŒๅ…จใช**Docker**ใ‚คใƒณใƒ†ใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณ (Dockerใƒ™ใƒผใ‚น)ใ€‚ -* Docker Swarm ใƒขใƒผใƒ‰ใƒ‡ใƒ—ใƒญใ‚คใ€‚ -* ใƒญใƒผใ‚ซใƒซ้–‹็™บ็’ฐๅขƒๅ‘ใ‘ใฎ**Docker Compose**ใ‚คใƒณใƒ†ใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใจๆœ€้ฉๅŒ–ใ€‚ -* UvicornใจGunicornใ‚’ไฝฟ็”จใ—ใŸ**ใƒชใƒชใƒผใ‚นๅฏ่ƒฝใช** Python web ใ‚ตใƒผใƒใ€‚ -* Python **FastAPI** ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰: - * **้ซ˜้€Ÿ**: **NodeJS** ใ‚„ **Go** ไธฆใฟใฎใจใฆใ‚‚้ซ˜ใ„ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น (Starlette ใจ Pydantic ใฎใŠใ‹ใ’)ใ€‚ - * **็›ดๆ„Ÿ็š„**: ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚„ ่ฃœๅฎŒใ€‚ ใƒ‡ใƒใƒƒใ‚ฐๆ™‚้–“ใฎ็Ÿญ็ธฎใ€‚ - * **็ฐกๅ˜**: ็ฐกๅ˜ใซๅˆฉ็”จใ€็ฟ’ๅพ—ใงใใ‚‹ใ‚ˆใ†ใชใƒ‡ใ‚ถใ‚คใƒณใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชญใ‚€ๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ€‚ - * **็Ÿญใ„**: ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡ใ‚’ๆœ€ๅฐ้™ใซใ€‚ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅฎฃ่จ€ใซใ‚ˆใ‚‹่ค‡ๆ•ฐใฎๆฉŸ่ƒฝใ€‚ - * **ๅ …็‰ขๆ€ง**: ่‡ชๅ‹•ๅฏพ่ฉฑใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ไฝฟ็”จใ—ใŸใ€ๆœฌ็•ช็’ฐๅขƒใงไฝฟ็”จใงใใ‚‹ใ‚ณใƒผใƒ‰ใ€‚ - * **ๆจ™ๆบ–่ฆๆ ผๆบ–ๆ‹ **: API ใฎใ‚ชใƒผใƒ—ใƒณใ‚นใ‚ฟใƒณใƒ€ใƒผใƒ‰ใซๅŸบใใ€ๅฎŒๅ…จใชไบ’ๆ›ๆ€ง: OpenAPIใ‚„ JSON ใ‚นใ‚ญใƒผใƒžใ€‚ - * ่‡ชๅ‹•ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ€OAuth2 JWTใƒˆใƒผใ‚ฏใƒณใ‚’็”จใ„ใŸ่ช่จผใชใฉใ‚’ๅซใ‚€ใ€**ใใฎไป–ๅคšใใฎๆฉŸ่ƒฝ**ใ€‚ -* **ใ‚ปใ‚ญใƒฅใ‚ขใชใƒ‘ใ‚นใƒฏใƒผใƒ‰** ใƒใƒƒใ‚ทใƒฅๅŒ– (ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง)ใ€‚ -* **JWTใƒˆใƒผใ‚ฏใƒณ** ่ช่จผใ€‚ -* **SQLAlchemy** ใƒขใƒ‡ใƒซ (Flask็”จใฎๆ‹กๅผตใจ็‹ฌ็ซ‹ใ—ใฆใ„ใ‚‹ใฎใงใ€Celeryใƒฏใƒผใ‚ซใƒผใจ็›ดๆŽฅ็š„ใซไฝต็”จใงใใพใ™)ใ€‚ -* ๅŸบๆœฌ็š„ใชใƒฆใƒผใ‚ถใƒผใƒขใƒ‡ใƒซ (ไปปๆ„ใฎไฟฎๆญฃใ‚„ๅ‰Š้™คใŒๅฏ่ƒฝ)ใ€‚ -* **Alembic** ใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ€‚ -* **CORS** (Cross Origin Resource Sharing (ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฝใƒผใ‚นๅ…ฑๆœ‰))ใ€‚ -* **Celery** ใƒฏใƒผใ‚ซใƒผใ€‚ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใฎๆฎ‹ใ‚Šใฎ้ƒจๅˆ†ใ‹ใ‚‰ใƒขใƒ‡ใƒซใจใ‚ณใƒผใƒ‰ใ‚’้ธๆŠž็š„ใซใ‚คใƒณใƒใƒผใƒˆใ—ใ€ไฝฟ็”จๅฏ่ƒฝใ€‚ -* Dockerใจ็ตฑๅˆใ•ใ‚ŒใŸ**Pytest**ใƒ™ใƒผใ‚นใฎRESTใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใƒ†ใ‚นใƒˆใ€‚ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซไพๅญ˜ใ›ใšใซใ€ๅ…จใฆใฎAPIใ‚’ใƒ†ใ‚นใƒˆๅฏ่ƒฝใ€‚DockerไธŠใงๅ‹•ไฝœใ™ใ‚‹ใฎใงใ€ๆฏŽๅ›žใ‚ผใƒญใ‹ใ‚‰ๆ–ฐใŸใชใƒ‡ใƒผใ‚ฟใ‚นใƒˆใ‚ขใ‚’ๆง‹็ฏ‰ๅฏ่ƒฝใ€‚(ElasticSearchใ€MongoDBใ€CouchDBใชใฉใ‚’ไฝฟ็”จใ—ใฆใ€APIใฎๅ‹•ไฝœใ‚’ใƒ†ใ‚นใƒˆๅฏ่ƒฝ) -* Atom Hydrogenใ‚„Visual Studio Code Jupyterใชใฉใฎๆ‹กๅผตๆฉŸ่ƒฝใ‚’ไฝฟ็”จใ—ใŸใ€ใƒชใƒขใƒผใƒˆใพใŸใฏDocker้–‹็™บ็”จใฎ**Jupyterใ‚ซใƒผใƒใƒซ**ใจใฎ็ฐกๅ˜ใชPython็ตฑๅˆใ€‚ -* **Vue** ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰: - * Vue CLIใซใ‚ˆใ‚Š็”Ÿๆˆใ€‚ - * **JWT่ช่จผ**ใฎๅ‡ฆ็†ใ€‚ - * ใƒญใ‚ฐใ‚คใƒณใƒ“ใƒฅใƒผใ€‚ - * ใƒญใ‚ฐใ‚คใƒณๅพŒใฎใ€ใƒกใ‚คใƒณใƒ€ใƒƒใ‚ทใƒฅใƒœใƒผใƒ‰ใƒ“ใƒฅใƒผใ€‚ - * ใƒกใ‚คใƒณใƒ€ใƒƒใ‚ทใƒฅใƒœใƒผใƒ‰ใงใฎใƒฆใƒผใ‚ถใƒผไฝœๆˆใจ็ทจ้›†ใ€‚ - * ใ‚ปใƒซใƒ•ใƒฆใƒผใ‚ถใƒผ็‰ˆ - * **Vuex**ใ€‚ - * **Vue-router**ใ€‚ - * ็พŽใ—ใ„ใƒžใƒ†ใƒชใ‚ขใƒซใƒ‡ใ‚ถใ‚คใƒณใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใฎใŸใ‚ใฎ**Vuetify**ใ€‚ - * **TypeScript**ใ€‚ - * **Nginx**ใƒ™ใƒผใ‚นใฎDockerใ‚ตใƒผใƒ (Vue-routerใจใ†ใพใๅ”่ชฟใ™ใ‚‹ๆง‹ๆˆ)ใ€‚ - * Dockerใƒžใƒซใƒใ‚นใƒ†ใƒผใ‚ธใƒ“ใƒซใƒ‰ใ€‚ใ‚ณใƒณใƒ‘ใ‚คใƒซใ•ใ‚ŒใŸใ‚ณใƒผใƒ‰ใฎไฟๅญ˜ใ‚„ใ‚ณใƒŸใƒƒใƒˆใŒไธ่ฆใ€‚ - * ใƒ“ใƒซใƒ‰ๆ™‚ใซใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใƒ†ใ‚นใƒˆๅฎŸ่กŒ (็„กๅŠนๅŒ–ใ‚‚ๅฏ่ƒฝ)ใ€‚ - * ๅฏ่ƒฝใช้™ใ‚Šใƒขใ‚ธใƒฅใƒผใƒซๅŒ–ใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใใฎใพใพไฝฟ็”จใงใใพใ™ใŒใ€Vue CLIใงๅ†็”Ÿๆˆใ—ใŸใ‚Šใ€ๅฟ…่ฆใซๅฟœใ˜ใฆไฝœๆˆใ—ใŸใ‚Šใ—ใฆใ€ๅฟ…่ฆใชใ‚‚ใฎใ‚’ๅ†ๅˆฉ็”จๅฏ่ƒฝใ€‚ -* PostgreSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใŸใ‚ใฎ**PGAdmin**ใ€‚(PHPMyAdminใจMySQLใ‚’ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซ็ฐกๅ˜ใซๅค‰ๆ›ดๅฏ่ƒฝ) -* Celeryใ‚ธใƒงใƒ–็›ฃ่ฆ–ใฎใŸใ‚ใฎ**Flower**ใ€‚ -* **Traefik**ใ‚’ไฝฟ็”จใ—ใฆใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใจใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰้–“ใ‚’ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ทใƒณใ‚ฐใ€‚ๅŒไธ€ใƒ‰ใƒกใ‚คใƒณใซ้…็ฝฎใ—ใƒ‘ใ‚นใงๅŒบๅˆ‡ใ‚‹ใ€ใŸใ ใ—ใ€็•ฐใชใ‚‹ใ‚ณใƒณใƒ†ใƒŠใงๅ‡ฆ็†ใ€‚ -* Traefik็ตฑๅˆใ€‚Let's Encrypt **HTTPS**่จผๆ˜Žๆ›ธใฎ่‡ชๅ‹•็”Ÿๆˆใ‚’ๅซใ‚€ใ€‚ -* GitLab **CI** (็ถ™็ถš็š„ใ‚คใƒณใƒ†ใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณ)ใ€‚ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใŠใ‚ˆใณใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใƒ†ใ‚นใƒˆใ‚’ๅซใ‚€ใ€‚ - -## ใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏ FastAPI Couchbase - -GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase - -โš ๏ธ **่ญฆๅ‘Š** โš ๏ธ - -ใ‚ผใƒญใ‹ใ‚‰ๆ–ฐ่ฆใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅง‹ใ‚ใ‚‹ๅ ดๅˆใฏใ€ใ“ใ“ใงไปฃๆ›ฟๆกˆใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ - -ไพ‹ใˆใฐใ€ใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏ FastAPI PostgreSQLใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใฏใ€็ฉๆฅต็š„ใซใƒกใƒณใƒ†ใƒŠใƒณใ‚นใ•ใ‚Œใ€ๅˆฉ็”จใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ‚ˆใ‚Š่‰ฏใ„ไปฃๆ›ฟๆกˆใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใพใŸใ€ใ™ในใฆใฎๆ–ฐๆฉŸ่ƒฝใจๆ”นๅ–„็‚นใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ - -Couchbaseใƒ™ใƒผใ‚นใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใฏไปŠใ‚‚็„กๅ„Ÿๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ๆใ‚‰ใๆญฃๅธธใซๅ‹•ไฝœใ™ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใพใŸใ€ใ™ใงใซใใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใง็”Ÿๆˆใ•ใ‚ŒใŸใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใŒๅญ˜ๅœจใ™ใ‚‹ๅ ดๅˆใงใ‚‚ (ใƒ‹ใƒผใ‚บใซๅˆใ‚ใ›ใฆใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆใ—ใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“)ใ€ๅŒๆง˜ใซๆญฃๅธธใซๅ‹•ไฝœใ™ใ‚‹ใฏใšใงใ™ใ€‚ - -่ฉณ็ดฐใฏใƒฌใƒใ‚ธใƒˆใƒชใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ - -## ใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏ FastAPI MongoDB - -...ๆ™‚้–“ใฎ้ƒฝๅˆ็ญ‰ใซใ‚ˆใฃใฆใฏใ€ไปŠๅพŒไฝœๆˆใ•ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿ˜… ๐ŸŽ‰ - -## spaCyใจFastAPIใ‚’ไฝฟ็”จใ—ใŸๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซ - -GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi - -### spaCyใจFastAPIใ‚’ไฝฟ็”จใ—ใŸๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซ - ๆฉŸ่ƒฝ - -* **spaCy** ใฎNERใƒขใƒ‡ใƒซใฎ็ตฑๅˆใ€‚ -* **Azure Cognitive Search** ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใ‚’ๆญ่ผ‰ใ€‚ -* **ใƒชใƒชใƒผใ‚นๅฏ่ƒฝใช** UvicornใจGunicornใ‚’ไฝฟ็”จใ—ใŸPythonใ‚ฆใ‚งใƒ–ใ‚ตใƒผใƒใ€‚ -* **Azure DevOps** ใฎKubernetes (AKS) CI/CD ใƒ‡ใƒ—ใƒญใ‚คใ‚’ๆญ่ผ‰ใ€‚ -* **ๅคš่จ€่ชž** ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใŸใ‚ใซใ€ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ๆ™‚ใซ่จ€่ชžใ‚’ๅฎนๆ˜“ใซ้ธๆŠžๅฏ่ƒฝ (spaCyใซ็ต„ใฟ่พผใพใ‚Œใฆใ„ใ‚‹่จ€่ชžใฎไธญใ‹ใ‚‰)ใ€‚ -* **็ฐกๅ˜ใซๆ‹กๅผตๅฏ่ƒฝ**ใ€‚spaCyใ ใ‘ใงใชใใ€ไป–ใฎใƒขใƒ‡ใƒซใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ (Pytorchใ€Tensorflow) ใธใ€‚ +# Full Stack FastAPI ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ { #full-stack-fastapi-template } + +ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฏ้€šๅธธใ€็‰นๅฎšใฎใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใŒๅซใพใ‚Œใฆใ„ใพใ™ใŒใ€ๆŸ”่ปŸใงใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎ่ฆไปถใซๅˆใ‚ใ›ใฆๅค‰ๆ›ดใƒป้ฉๅฟœใงใใ€ๅ„ชใ‚ŒใŸๅ‡บ็™บ็‚นใซใชใ‚Šใพใ™ใ€‚๐Ÿ + +ใ“ใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚’ไฝฟใฃใฆ้–‹ๅง‹ใงใใพใ™ใ€‚ๅˆๆœŸใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ„ใใคใ‹ใฎAPIใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใŒใ™ใงใซ็”จๆ„ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +GitHubใƒชใƒใ‚ธใƒˆใƒช: Full Stack FastAPI Template + +## Full Stack FastAPI ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ - ๆŠ€่ก“ใ‚นใ‚ฟใƒƒใ‚ฏใจๆฉŸ่ƒฝ { #full-stack-fastapi-template-technology-stack-and-features } + +- โšก Pythonใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰APIๅ‘ใ‘ใฎ [**FastAPI**](https://fastapi.tiangolo.com/ja)ใ€‚ + - ๐Ÿงฐ PythonใฎSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆ“ไฝœ๏ผˆORM๏ผ‰ๅ‘ใ‘ใฎ [SQLModel](https://sqlmodel.tiangolo.com)ใ€‚ + - ๐Ÿ” FastAPIใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ€ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจ่จญๅฎš็ฎก็†ๅ‘ใ‘ใฎ [Pydantic](https://docs.pydantic.dev)ใ€‚ + - ๐Ÿ’พ SQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใจใ—ใฆใฎ [PostgreSQL](https://www.postgresql.org)ใ€‚ +- ๐Ÿš€ ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ๅ‘ใ‘ใฎ [React](https://react.dev)ใ€‚ + - ๐Ÿ’ƒ TypeScriptใ€hooksใ€Viteใ€ใใฎไป–ใฎใƒขใƒ€ใƒณใชใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚นใ‚ฟใƒƒใ‚ฏใฎๅ„่ฆ็ด ใ‚’ไฝฟ็”จใ€‚ + - ๐ŸŽจ ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆๅ‘ใ‘ใฎ [Tailwind CSS](https://tailwindcss.com) ใจ [shadcn/ui](https://ui.shadcn.com)ใ€‚ + - ๐Ÿค– ่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ€‚ + - ๐Ÿงช End-to-Endใƒ†ใ‚นใƒˆๅ‘ใ‘ใฎ [Playwright](https://playwright.dev)ใ€‚ + - ๐Ÿฆ‡ ใƒ€ใƒผใ‚ฏใƒขใƒผใƒ‰ใฎใ‚ตใƒใƒผใƒˆใ€‚ +- ๐Ÿ‹ ้–‹็™บใŠใ‚ˆใณๆœฌ็•ชๅ‘ใ‘ใฎ [Docker Compose](https://www.docker.com)ใ€‚ +- ๐Ÿ”’ ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฎๅฎ‰ๅ…จใชใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅๅŒ–ใ€‚ +- ๐Ÿ”‘ JWT๏ผˆJSON Web Token๏ผ‰่ช่จผใ€‚ +- ๐Ÿ“ซ ใƒกใƒผใƒซใƒ™ใƒผใ‚นใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒชใ‚ซใƒใƒชใ€‚ +- โœ… [Pytest](https://pytest.org) ใซใ‚ˆใ‚‹ใƒ†ใ‚นใƒˆใ€‚ +- ๐Ÿ“ž ใƒชใƒใƒผใ‚นใƒ—ใƒญใ‚ญใ‚ท / ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ตใจใ—ใฆใฎ [Traefik](https://traefik.io)ใ€‚ +- ๐Ÿšข Docker Composeใ‚’ไฝฟ็”จใ—ใŸใƒ‡ใƒ—ใƒญใ‚คๆ‰‹้ †๏ผˆ่‡ชๅ‹•HTTPS่จผๆ˜Žๆ›ธใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰Traefikใƒ—ใƒญใ‚ญใ‚ทใฎใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ๆ–นๆณ•ใ‚’ๅซใ‚€๏ผ‰ใ€‚ +- ๐Ÿญ GitHub ActionsใซๅŸบใฅใCI๏ผˆcontinuous integration๏ผ‰ใจCD๏ผˆcontinuous deployment๏ผ‰ใ€‚ diff --git a/docs/ja/docs/python-types.md b/docs/ja/docs/python-types.md index a847ce5d54..26a9e2193c 100644 --- a/docs/ja/docs/python-types.md +++ b/docs/ja/docs/python-types.md @@ -1,16 +1,16 @@ -# Pythonใฎๅž‹ใฎ็ดนไป‹ +# Pythonใฎๅž‹ใฎ็ดนไป‹ { #python-types-intro } -**Python 3.6ไปฅ้™** ใงใฏใ€Œๅž‹ใƒ’ใƒณใƒˆใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +Pythonใงใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ€Œๅž‹ใƒ’ใƒณใƒˆใ€๏ผˆใ€Œๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ€ใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™๏ผ‰ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎ **"ๅž‹ใƒ’ใƒณใƒˆ"** ใฏๅค‰ๆ•ฐใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ๆ–ฐใ—ใ„ๆง‹ๆ–‡ใงใ™ใ€‚๏ผˆPython 3.6ไปฅ้™๏ผ‰ +ใ“ใ‚Œใ‚‰ใฎ **ใ€Œๅž‹ใƒ’ใƒณใƒˆใ€** ใพใŸใฏใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใฏใ€ๅค‰ๆ•ฐใฎๅž‹ใ‚’ๅฎฃ่จ€ใงใใ‚‹็‰นๅˆฅใชๆง‹ๆ–‡ใงใ™ใ€‚ -ๅค‰ๆ•ฐใซๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใงใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚„ใƒ„ใƒผใƒซใŒใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ๅค‰ๆ•ฐใซๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚„ใƒ„ใƒผใƒซใŒใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใงใใพใ™ใ€‚ -ใ“ใ“ใงใฏPythonใฎๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใฎ **ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ/ใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅ** ใงใ€**FastAPI**ใงใใ‚Œใ‚‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชๆœ€ไฝŽ้™ใฎใ“ใจใ ใ‘ใ‚’ใ‚ซใƒใƒผใ—ใฆใ„ใพใ™ใ€‚...ๅฎŸ้š›ใซใฏๆœฌๅฝ“ใซๅฐ‘ใชใ„ใงใ™ใ€‚ +ใ“ใ‚ŒใฏPythonใฎๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใฎ **ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ/ใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅ** ใซใ™ใŽใพใ›ใ‚“ใ€‚**FastAPI** ใงไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชๆœ€ไฝŽ้™ใฎใ“ใจใ ใ‘ใ‚’ใ‚ซใƒใƒผใ—ใฆใ„ใพใ™ใ€‚...ๅฎŸ้š›ใซใฏๆœฌๅฝ“ใซๅฐ‘ใชใ„ใงใ™ใ€‚ **FastAPI** ใฏใ™ในใฆใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆใŠใ‚Šใ€ๅคšใใฎๅผทใฟใจๅˆฉ็‚นใ‚’ไธŽใˆใฆใใ‚Œใพใ™ใ€‚ -ใ—ใ‹ใ—ใŸใจใˆใพใฃใŸใ **FastAPI** ใ‚’ไฝฟ็”จใ—ใชใ„ๅ ดๅˆใงใ‚‚ใ€ใใ‚Œใ‚‰ใซใคใ„ใฆๅฐ‘ใ—ๅญฆใถใ“ใจใงๅˆฉ็‚นใ‚’ๅพ—ใ‚‹ใ“ใจใŒใงใใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใ—ใ‹ใ—ใ€ใŸใจใˆ **FastAPI** ใ‚’ใพใฃใŸใไฝฟ็”จใ—ใชใ„ๅ ดๅˆใงใ‚‚ใ€ใใ‚Œใ‚‰ใซใคใ„ใฆๅฐ‘ใ—ๅญฆใถใ“ใจใงๅˆฉ็‚นใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ /// note | ๅ‚™่€ƒ @@ -18,14 +18,13 @@ /// -## ๅ‹•ๆฉŸ +## ๅ‹•ๆฉŸ { #motivation } ็ฐกๅ˜ใชไพ‹ใ‹ใ‚‰ๅง‹ใ‚ใฆใฟใพใ—ใ‚‡ใ†: -{* ../../docs_src/python_types/tutorial001.py *} +{* ../../docs_src/python_types/tutorial001_py39.py *} - -ใ“ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจไปฅไธ‹ใŒๅ‡บๅŠ›ใ•ใ‚Œใพใ™: +ใ“ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‘ผใณๅ‡บใ™ใจใ€ไปฅไธ‹ใŒๅ‡บๅŠ›ใ•ใ‚Œใพใ™: ``` John Doe @@ -35,12 +34,11 @@ John Doe * `first_name`ใจ`last_name`ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ * `title()`ใ‚’็”จใ„ใฆใ€ใใ‚Œใžใ‚Œใฎๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -* ็œŸใ‚“ไธญใซใ‚นใƒšใƒผใ‚นใ‚’ๅ…ฅใ‚Œใฆ้€ฃ็ตใ—ใพใ™ใ€‚ - -{* ../../docs_src/python_types/tutorial001.py hl[2] *} +* ็œŸใ‚“ไธญใซใ‚นใƒšใƒผใ‚นใ‚’ๅ…ฅใ‚Œใฆ้€ฃ็ตใ—ใพใ™ใ€‚ +{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} -### ็ทจ้›† +### ็ทจ้›† { #edit-it } ใ“ใ‚Œใฏใจใฆใ‚‚็ฐกๅ˜ใชใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ™ใ€‚ @@ -50,7 +48,7 @@ John Doe ใ—ใ‹ใ—ใ€ใใ†ใ™ใ‚‹ใจใ€Œๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซๅค‰ๆ›ใ™ใ‚‹ใ‚ใฎใƒกใ‚ฝใƒƒใƒ‰ใ€ใ‚’ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใ‚Œใฏ`upper`ใงใ—ใŸใ‹๏ผŸ`uppercase`ใงใ—ใŸใ‹๏ผŸใใ‚Œใจใ‚‚`first_uppercase`๏ผŸใพใŸใฏ`capitalize`๏ผŸ +ใใ‚Œใฏ`upper`ใงใ—ใŸใ‹๏ผŸ`uppercase`ใงใ—ใŸใ‹๏ผŸ`first_uppercase`๏ผŸ`capitalize`๏ผŸ ใใ—ใฆใ€ๅคใใ‹ใ‚‰ใƒ—ใƒญใ‚ฐใƒฉใƒžใƒผใฎๅ‹ไบบใงใ‚ใ‚‹ใ‚จใƒ‡ใ‚ฃใ‚ฟใง่‡ชๅ‹•่ฃœๅฎŒใ‚’่ฉฆใ—ใฆใฟใพใ™ใ€‚ @@ -58,13 +56,13 @@ John Doe ใ—ใ‹ใ—ใ€ๆ‚ฒใ—ใ„ใ“ใจใซใ€ใ“ใ‚Œใฏใชใ‚“ใฎๅฝนใซใ‚‚็ซ‹ใกใพใ›ใ‚“: - + -### ๅž‹ใฎ่ฟฝๅŠ  +### ๅž‹ใฎ่ฟฝๅŠ  { #add-types } ๅ…ˆใปใฉใฎใ‚ณใƒผใƒ‰ใ‹ใ‚‰ไธ€่กŒๅค‰ๆ›ดใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -ไปฅไธ‹ใฎ้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ้ƒจๅˆ†ใ‚’: +้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹ๆฌกใฎๆ–ญ็‰‡ใ‚’ใ€ไปฅไธ‹ใ‹ใ‚‰: ```Python first_name, last_name @@ -80,8 +78,7 @@ John Doe ใใ‚ŒใŒใ€Œๅž‹ใƒ’ใƒณใƒˆใ€ใงใ™: -{* ../../docs_src/python_types/tutorial002.py hl[1] *} - +{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} ใ“ใ‚Œใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใฎใจๅŒใ˜ใงใฏใ‚ใ‚Šใพใ›ใ‚“: @@ -95,41 +92,39 @@ John Doe ใใ—ใฆใ€้€šๅธธใ€ๅž‹ใƒ’ใƒณใƒˆใ‚’่ฟฝๅŠ ใ—ใฆใ‚‚ใ€ใใ‚Œใ‚‰ใŒใชใ„็Šถๆ…‹ใจ่ตทใ“ใ‚‹ใ“ใจใฏไฝ•ใ‚‚ๅค‰ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใ—ใ‹ใ—ไปŠใ€ใ‚ใชใŸใŒๅ†ใณใใฎ้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใฆใ„ใ‚‹ๆœ€ไธญใซใ€ๅž‹ใƒ’ใƒณใƒˆใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจๆƒณๅƒใ—ใฆใฟใฆไธ‹ใ•ใ„ใ€‚ +ใ—ใ‹ใ—ไปŠใ€ใ‚ใชใŸใŒๅ†ใณใใฎ้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใฆใ„ใ‚‹ๆœ€ไธญใซใ€ๅž‹ใƒ’ใƒณใƒˆใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ ๅŒใ˜ใ‚ฟใ‚คใƒŸใƒณใ‚ฐใง`Ctrl+Space`ใง่‡ชๅ‹•่ฃœๅฎŒใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: - + -ใ“ใ‚Œใงใ‚ใ‚Œใฐใ€ใ‚ใชใŸใฏใ€Œใƒ™ใƒซใ‚’้ณดใ‚‰ใ™ใ€ไธ€ใคใ‚’่ฆ‹ใคใ‘ใ‚‹ใพใงใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฆ‹ใฆใ€ใ‚นใ‚ฏใƒญใƒผใƒซใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใ“ใ‚Œใงใ‚ใ‚Œใฐใ€ใ‚ใชใŸใฏใ€Œใƒ™ใƒซใ‚’้ณดใ‚‰ใ™ใ€ใ‚‚ใฎใ‚’่ฆ‹ใคใ‘ใ‚‹ใพใงใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’่ฆ‹ใฆใ‚นใ‚ฏใƒญใƒผใƒซใงใใพใ™: - + -## ใ‚ˆใ‚Šๅผทใ„ๅ‹•ๆฉŸ +## ใ‚ˆใ‚Šๅผทใ„ๅ‹•ๆฉŸ { #more-motivation } ใ“ใฎ้–ขๆ•ฐใ‚’่ฆ‹ใฆใใ ใ•ใ„ใ€‚ใ™ใงใซๅž‹ใƒ’ใƒณใƒˆใ‚’ๆŒใฃใฆใ„ใพใ™: -{* ../../docs_src/python_types/tutorial003.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏๅค‰ๆ•ฐใฎๅž‹ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ€่ฃœๅฎŒใ ใ‘ใงใชใใ€ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ‚’ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏๅค‰ๆ•ฐใฎๅž‹ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ€่ฃœๅฎŒใ ใ‘ใงใชใใ€ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ‚’ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ - - + ใ“ใ‚Œใง`age`ใ‚’`str(age)`ใงๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ—ใฆไฟฎๆญฃใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™: -{* ../../docs_src/python_types/tutorial004.py hl[2] *} - +{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} -## ๅž‹ใฎๅฎฃ่จ€ +## ๅž‹ใฎๅฎฃ่จ€ { #declaring-types } -้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆใ€ๅž‹ใƒ’ใƒณใƒˆใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ไธปใชๅ ดๆ‰€ใ‚’็ขบ่ชใ—ใพใ—ใŸใ€‚ +ๅž‹ใƒ’ใƒณใƒˆใ‚’ๅฎฃ่จ€ใ™ใ‚‹ไธปใชๅ ดๆ‰€ใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ ใ“ใ‚Œใฏ **FastAPI** ใงไฝฟ็”จใ™ใ‚‹ไธปใชๅ ดๆ‰€ใงใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -### ๅ˜็ด”ใชๅž‹ +### ๅ˜็ด”ใชๅž‹ { #simple-types } -`str`ใ ใ‘ใงใชใใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ™ในใฆใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +`str`ใ ใ‘ใงใชใใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ™ในใฆใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€ไปฅไธ‹ใ‚’ไฝฟ็”จๅฏ่ƒฝใงใ™: @@ -138,40 +133,47 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +### ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใคใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ { #generic-types-with-type-parameters } -### ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใคใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ +ใƒ‡ใƒผใ‚ฟๆง‹้€ ใฎไธญใซใฏใ€`dict`ใ€`list`ใ€`set`ใ€`tuple`ใฎใ‚ˆใ†ใซไป–ใฎๅ€คใ‚’ๅซใ‚€ใ“ใจใŒใงใใ‚‹ใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ใพใŸๅ†…้ƒจใฎๅ€คใ‚‚็‹ฌ่‡ชใฎๅž‹ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ -ใƒ‡ใƒผใ‚ฟๆง‹้€ ใฎไธญใซใฏใ€`dict`ใ€`list`ใ€`set`ใ€ใใ—ใฆ`tuple`ใฎใ‚ˆใ†ใซไป–ใฎๅ€คใ‚’ๅซใ‚€ใ“ใจใŒใงใใ‚‹ใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ใพใŸๅ†…้ƒจใฎๅ€คใ‚‚็‹ฌ่‡ชใฎๅž‹ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ +ๅ†…้ƒจใฎๅž‹ใ‚’ๆŒใคใ“ใ‚Œใ‚‰ใฎๅž‹ใฏใ€Œ**generic**ใ€ๅž‹ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ใใ—ใฆใ€ๅ†…้ƒจใฎๅž‹ใ‚‚ๅซใ‚ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒๅฏ่ƒฝใงใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎๅž‹ใ‚„ๅ†…้ƒจใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€Pythonใฎๆจ™ๆบ–ใƒขใ‚ธใƒฅใƒผใƒซ`typing`ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎๅž‹ใ‚„ๅ†…้ƒจใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€Pythonใฎๆจ™ๆบ–ใƒขใ‚ธใƒฅใƒผใƒซ`typing`ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใŸใ‚ใซ็‰นๅˆฅใซๅญ˜ๅœจใ—ใฆใ„ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใŸใ‚ใซ็‰นๅˆฅใซๅญ˜ๅœจใ—ใฆใ„ใพใ™ใ€‚ +#### ๆ–ฐใ—ใ„Pythonใƒใƒผใ‚ธใƒงใƒณ { #newer-versions-of-python } -#### `List` +`typing`ใ‚’ไฝฟใ†ๆง‹ๆ–‡ใฏใ€Python 3.6ใ‹ใ‚‰ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใพใง๏ผˆPython 3.9ใ€Python 3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใ™ในใฆใฎใƒใƒผใ‚ธใƒงใƒณใจ **ไบ’ๆ›ๆ€ง** ใŒใ‚ใ‚Šใพใ™ใ€‚ -ไพ‹ใˆใฐใ€`str`ใฎ`list`ใฎๅค‰ๆ•ฐใ‚’ๅฎš็พฉใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +PythonใŒ้€ฒๅŒ–ใ™ใ‚‹ใซใคใ‚Œใ€**ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ** ใงใฏใ“ใ‚Œใ‚‰ใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใธใฎใ‚ตใƒใƒผใƒˆใŒๆ”นๅ–„ใ•ใ‚Œใ€ๅคšใใฎๅ ดๅˆใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ†ๅฟ…่ฆใ™ใ‚‰ใชใใชใ‚Šใพใ™ใ€‚ -`typing`ใ‹ใ‚‰`List`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™๏ผˆๅคงๆ–‡ๅญ—ใฎ`L`ใ‚’ๅซใ‚€๏ผ‰: +ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใ‚ˆใ‚Šๆ–ฐใ—ใ„Pythonใƒใƒผใ‚ธใƒงใƒณใ‚’้ธในใ‚‹ใชใ‚‰ใ€ใใฎ่ฟฝๅŠ ใฎใ‚ทใƒณใƒ—ใƒซใ•ใ‚’ๆดป็”จใงใใพใ™ใ€‚ -{* ../../docs_src/python_types/tutorial006.py hl[1] *} +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅ…จไฝ“ใงใ€Pythonใฎๅ„ใƒใƒผใ‚ธใƒงใƒณใจไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ไพ‹๏ผˆๅทฎๅˆ†ใŒใ‚ใ‚‹ๅ ดๅˆ๏ผ‰ใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚ +ไพ‹ใˆใฐใ€Œ**Python 3.6+**ใ€ใฏPython 3.6ไปฅไธŠ๏ผˆ3.7ใ€3.8ใ€3.9ใ€3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใจไบ’ๆ›ๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใพใŸใ€Œ**Python 3.9+**ใ€ใฏPython 3.9ไปฅไธŠ๏ผˆ3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใจไบ’ๆ›ๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -ๅŒใ˜ใ‚ˆใ†ใซใ‚ณใƒญใƒณ๏ผˆ`:`๏ผ‰ใฎๆง‹ๆ–‡ใงๅค‰ๆ•ฐใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +**ๆœ€ๆ–ฐใฎPythonใƒใƒผใ‚ธใƒงใƒณ** ใ‚’ไฝฟใˆใ‚‹ใชใ‚‰ใ€ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณๅ‘ใ‘ใฎไพ‹ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ไพ‹ใˆใฐใ€Œ**Python 3.10+**ใ€ใฎใ‚ˆใ†ใซใ€ใใ‚Œใ‚‰ใฏ **ๆœ€่‰ฏใ‹ใคๆœ€ใ‚‚ใ‚ทใƒณใƒ—ใƒซใชๆง‹ๆ–‡** ใซใชใ‚Šใพใ™ใ€‚ -ๅž‹ใจใ—ใฆใ€`List`ใ‚’ๅ…ฅๅŠ›ใ—ใพใ™ใ€‚ +#### List { #list } -ใƒชใ‚นใƒˆใฏใ„ใใคใ‹ใฎๅ†…้ƒจใฎๅž‹ใ‚’ๅซใ‚€ๅž‹ใชใฎใงใ€ใใ‚Œใ‚‰ใ‚’่ง’ๆ‹ฌๅผงใงๅ›ฒใ‚“ใงใ„ใพใ™ใ€‚ +ไพ‹ใˆใฐใ€`str`ใฎ`list`ใฎๅค‰ๆ•ฐใ‚’ๅฎš็พฉใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -{* ../../docs_src/python_types/tutorial006.py hl[4] *} +ๅŒใ˜ใ‚ณใƒญใƒณ๏ผˆ`:`๏ผ‰ใฎๆง‹ๆ–‡ใงๅค‰ๆ•ฐใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +ๅž‹ใจใ—ใฆใ€`list`ใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ -/// tip | ่ฑ†็Ÿฅ่ญ˜ +ใƒชใ‚นใƒˆใฏใ„ใใคใ‹ใฎๅ†…้ƒจใฎๅž‹ใ‚’ๅซใ‚€ๅž‹ใชใฎใงใ€ใใ‚Œใ‚‰ใ‚’่ง’ๆ‹ฌๅผงใงๅ›ฒใฟใพใ™: + +{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} + +/// info | ๆƒ…ๅ ฑ ่ง’ๆ‹ฌๅผงๅ†…ใฎๅ†…้ƒจใฎๅž‹ใฏใ€Œๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใจๅ‘ผใฐใ‚Œใฆใ„ใพใ™ใ€‚ -ใ“ใฎๅ ดๅˆใ€`str`ใฏ`List`ใซๆธกใ•ใ‚Œใ‚‹ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ +ใ“ใฎๅ ดๅˆใ€`str`ใฏ`list`ใซๆธกใ•ใ‚Œใ‚‹ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ /// @@ -179,86 +181,203 @@ John Doe ใใ†ใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใƒชใ‚นใƒˆใฎ้ …็›ฎใ‚’ๅ‡ฆ็†ใ—ใฆใ„ใ‚‹้–“ใซใ‚‚ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใงใใพใ™ใ€‚ - + -ใ‚ฟใ‚คใƒ—ใŒใชใ‘ใ‚Œใฐใ€ใใ‚Œใฏใปใผไธๅฏ่ƒฝใงใ™ใ€‚ +ๅž‹ใŒใชใ‘ใ‚Œใฐใ€ใใ‚Œใฏใปใผไธๅฏ่ƒฝใงใ™ใ€‚ ๅค‰ๆ•ฐ`item`ใฏใƒชใ‚นใƒˆ`items`ใฎ่ฆ็ด ใฎไธ€ใคใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ ใใ‚Œใงใ‚‚ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใใ‚ŒใŒ`str`ใงใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใฃใฆใ„ใฆใ€ใใฎใŸใ‚ใฎใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ -#### `Tuple` ใจ `Set` +#### Tuple ใจ Set { #tuple-and-set } `tuple`ใจ`set`ใฎๅฎฃ่จ€ใ‚‚ๅŒๆง˜ใงใ™: -{* ../../docs_src/python_types/tutorial007.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} + +ใคใพใ‚Š: + +* ๅค‰ๆ•ฐ`items_t`ใฏ`int`ใ€ๅˆฅใฎ`int`ใ€`str`ใฎ3ใคใฎ้ …็›ฎใ‚’ๆŒใค`tuple`ใงใ™ใ€‚ +* ๅค‰ๆ•ฐ`items_s`ใฏ`set`ใงใ‚ใ‚Šใ€ใใฎๅ„้ …็›ฎใฏ`bytes`ๅž‹ใงใ™ใ€‚ + +#### Dict { #dict } + +`dict`ใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€ใ‚ซใƒณใƒžๅŒบๅˆ‡ใ‚Šใง2ใคใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™ใ€‚ + +ๆœ€ๅˆใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎใ‚ญใƒผใงใ™ใ€‚ +2็•ช็›ฎใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎๅ€คใงใ™: + +{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} ใคใพใ‚Š: -* ๅค‰ๆ•ฐ`items_t`ใฏ`int`ใ€`int`ใ€`str`ใฎ3ใคใฎ้ …็›ฎใ‚’ๆŒใค`tuple`ใงใ™ +* ๅค‰ๆ•ฐ`prices`ใฏ`dict`ใงใ™: + * ใ“ใฎ`dict`ใฎใ‚ญใƒผใฏ`str`ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎๅๅ‰๏ผ‰ใ€‚ + * ใ“ใฎ`dict`ใฎๅ€คใฏ`float`ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎไพกๆ ผ๏ผ‰ใ€‚ -* ๅค‰ๆ•ฐ`items_s`ใฏใใ‚Œใžใ‚Œใฎ้ …็›ฎใŒ`bytes`ๅž‹ใงใ‚ใ‚‹`set`ใงใ™ใ€‚ +#### Union { #union } -#### `Dict` +ๅค‰ๆ•ฐใŒ**่ค‡ๆ•ฐใฎๅž‹ใฎใ„ใšใ‚Œใ‹**ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€`int`ใพใŸใฏ`str`ใงใ™ใ€‚ -`dict`ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใฏใ€ใ‚ซใƒณใƒžๅŒบๅˆ‡ใ‚Šใง2ใคใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™ใ€‚ +Python 3.6ไปฅไธŠ๏ผˆPython 3.10ใ‚’ๅซใ‚€๏ผ‰ใงใฏใ€`typing`ใฎ`Union`ๅž‹ใ‚’ไฝฟใ„ใ€่ง’ๆ‹ฌๅผงใฎไธญใซๅ—ใ‘ไป˜ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ๅž‹ใ‚’ๅ…ฅใ‚Œใ‚‰ใ‚Œใพใ™ใ€‚ -ๆœ€ๅˆใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎใ‚ญใƒผใงใ™ใ€‚ +Python 3.10ใงใฏใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ๅž‹ใ‚’็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใงๅŒบๅˆ‡ใฃใฆๆ›ธใ‘ใ‚‹ **ๆ–ฐใ—ใ„ๆง‹ๆ–‡** ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +//// tab | Python 3.10+ -๏ผ’็•ช็›ฎใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎๅ€คใงใ™ใ€‚ +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` -{* ../../docs_src/python_types/tutorial008.py hl[1,4] *} +//// +//// tab | Python 3.9+ -ใคใพใ‚Š: +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008b_py39.py!} +``` + +//// + +ใฉใกใ‚‰ใฎๅ ดๅˆใ‚‚ใ€`item`ใฏ`int`ใพใŸใฏ`str`ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ + +#### `None`ใฎๅฏ่ƒฝๆ€ง { #possibly-none } + +ๅ€คใŒ`str`ใฎใ‚ˆใ†ใชๅž‹ใ‚’ๆŒใคๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ไธ€ๆ–นใงใ€`None`ใซใ‚‚ใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +Python 3.6ไปฅไธŠ๏ผˆPython 3.10ใ‚’ๅซใ‚€๏ผ‰ใงใฏใ€`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰`Optional`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ†ใ“ใจใงๅฎฃ่จ€ใงใใพใ™ใ€‚ + +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009_py39.py!} +``` + +ใŸใ ใฎ`str`ใฎไปฃใ‚ใ‚Šใซ`Optional[str]`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ๅ€คใŒๅธธใซ`str`ใงใ‚ใ‚‹ใจไปฎๅฎšใ—ใฆใ„ใ‚‹ใจใใซใ€ๅฎŸ้š›ใซใฏ`None`ใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚‹ใจใ„ใ†ใ‚จใƒฉใƒผใ‚’ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒๆคœๅ‡บใ™ใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ + +`Optional[Something]`ใฏๅฎŸ้š›ใซใฏ`Union[Something, None]`ใฎใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆใงใ€ไธก่€…ใฏ็ญ‰ไพกใงใ™ใ€‚ + +ใ“ใ‚Œใฏใ€Python 3.10ใงใฏ`Something | None`ใ‚‚ไฝฟใˆใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009_py39.py!} +``` + +//// + +//// tab | Python 3.9+ alternative + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009b_py39.py!} +``` + +//// + +#### `Union`ใพใŸใฏ`Optional`ใฎไฝฟ็”จ { #using-union-or-optional } -* ๅค‰ๆ•ฐ`prices`ใฏ`dict`ใงใ‚ใ‚Š: - * ใ“ใฎ`dict`ใฎใ‚ญใƒผใฏ`str`ๅž‹ใงใ™ใ€‚๏ผˆใคใพใ‚Šใ€ๅ„้ …็›ฎใฎๅๅ‰๏ผ‰ - * ใ“ใฎ`dict`ใฎๅ€คใฏ`float`ๅž‹ใงใ™ใ€‚๏ผˆใคใพใ‚Šใ€ๅ„้ …็›ฎใฎไพกๆ ผ๏ผ‰ +Python 3.10ๆœชๆบ€ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใ€ใ“ใ‚Œใฏ็งใฎใจใฆใ‚‚ **ไธป่ฆณ็š„** ใช่ฆณ็‚นใ‹ใ‚‰ใฎใƒ’ใƒณใƒˆใงใ™: -#### `Optional` +* ๐Ÿšจ `Optional[SomeType]`ใฏ้ฟใ‘ใฆใใ ใ•ใ„ +* ไปฃใ‚ใ‚Šใซ โœจ **`Union[SomeType, None]`ใ‚’ไฝฟใฃใฆใใ ใ•ใ„** โœจ -ใพใŸใ€`Optional`ใ‚’ไฝฟ็”จใ—ใฆใ€ๅค‰ๆ•ฐใŒ`str`ใฎใ‚ˆใ†ใชๅž‹ใ‚’ๆŒใคใ“ใจใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใŒใ€ใใ‚Œใฏใ€Œใ‚ชใƒ—ใ‚ทใƒงใƒณใ€ใงใ‚ใ‚Šใ€`None`ใซใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใฉใกใ‚‰ใ‚‚็ญ‰ไพกใงใ€ๅ†…้ƒจ็š„ใซใฏๅŒใ˜ใงใ™ใŒใ€`Optional`ใ‚ˆใ‚Š`Union`ใ‚’ใŠใ™ใ™ใ‚ใ—ใพใ™ใ€‚ใจใ„ใ†ใฎใ‚‚ใ€Œ**optional**ใ€ใจใ„ใ†ๅ˜่ชžใฏๅ€คใŒใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ‚ใ‚‹ใ“ใจใ‚’็คบๅ”†ใ™ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใˆใพใ™ใŒใ€ๅฎŸ้š›ใซใฏใ€Œ`None`ใซใชใ‚Šๅพ—ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใ‚ใ‚Šใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใฏใชใๅฟ…้ ˆใงใ‚ใ‚‹ๅ ดๅˆใงใ‚‚ใใ†ใ ใ‹ใ‚‰ใงใ™ใ€‚ -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009.py!} +`Union[SomeType, None]`ใฎใปใ†ใŒๆ„ๅ‘ณใŒใ‚ˆใ‚Šๆ˜Ž็คบ็š„ใ ใจๆ€ใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใฏ่จ€่‘‰ใ‚„ๅๅ‰ใฎ่ฉฑใซใ™ใŽใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ใใฎ่จ€่‘‰ใฏใ‚ใชใŸใ‚„ใƒใƒผใƒ ใƒกใ‚คใƒˆใŒใ‚ณใƒผใƒ‰ใ‚’ใฉใ†่€ƒใˆใ‚‹ใ‹ใซๅฝฑ้Ÿฟใ—ๅพ—ใพใ™ใ€‚ + +ไพ‹ใจใ—ใฆใ€ใ“ใฎ้–ขๆ•ฐใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: + +{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} + +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ`name`ใฏ`Optional[str]`ใจใ—ใฆๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใŒใ€**ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใ—ใง้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ›ใพใ›ใ‚“: + +```Python +say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ ``` -ใŸใ ใฎ`str`ใฎไปฃใ‚ใ‚Šใซ`Optional[str]`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏๅ€คใŒๅธธใซ`str`ใงใ‚ใ‚‹ใจไปฎๅฎšใ—ใฆใ„ใ‚‹ๅ ดๅˆใซๅฎŸ้š›ใซใฏ`None`ใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใ‚จใƒฉใƒผใ‚’ๆคœๅ‡บใ™ใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ +`name`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใ„ใŸใ‚ใ€**ไพ็„ถใจใ—ใฆๅฟ…้ ˆ**๏ผˆ*optional*ใงใฏใชใ„๏ผ‰ใงใ™ใ€‚ใใ‚Œใงใ‚‚ใ€`name`ใฏๅ€คใจใ—ใฆ`None`ใ‚’ๅ—ใ‘ไป˜ใ‘ใพใ™: + +```Python +say_hi(name=None) # This works, None is valid ๐ŸŽ‰ +``` + +่‰ฏใ„็Ÿฅใ‚‰ใ›ใจใ—ใฆใ€Python 3.10ใซใชใ‚Œใฐใใฎๅฟƒ้…ใฏไธ่ฆใงใ™ใ€‚ๅž‹ใฎใƒฆใƒ‹ใ‚ชใƒณใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซ`|`ใ‚’ๅ˜็ด”ใซไฝฟใˆใ‚‹ใ‹ใ‚‰ใงใ™: + +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} + +ใใ—ใฆใ€`Optional`ใ‚„`Union`ใฎใ‚ˆใ†ใชๅๅ‰ใซใคใ„ใฆๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใ‚‚ใชใใชใ‚Šใพใ™ใ€‚๐Ÿ˜Ž -#### ใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ +#### ใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ { #generic-types } -ไปฅไธ‹ใฎใ‚ˆใ†ใซ่ง’ๆ‹ฌๅผงใงๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚‹ๅž‹ใ‚’: +่ง’ๆ‹ฌๅผงใงๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚‹ใ“ใ‚Œใ‚‰ใฎๅž‹ใฏใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซ **Generic types** ใพใŸใฏ **Generics** ใจๅ‘ผใฐใ‚Œใพใ™: -* `List` -* `Tuple` -* `Set` -* `Dict` +//// tab | Python 3.10+ + +ๅŒใ˜็ต„ใฟ่พผใฟๅž‹ใ‚’ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใจใ—ใฆ๏ผˆ่ง’ๆ‹ฌๅผงใจๅ†…้ƒจใฎๅž‹ใง๏ผ‰ไฝฟใˆใพใ™: + +* `list` +* `tuple` +* `set` +* `dict` + +ใพใŸใ€ใ“ใ‚ŒใพใงใฎPythonใƒใƒผใ‚ธใƒงใƒณใจๅŒๆง˜ใซใ€`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰: + +* `Union` * `Optional` -* ...ใชใฉ +* ...and others. -**ใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹** ใพใŸใฏ **ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚น** ใจๅ‘ผใณใพใ™ใ€‚ +Python 3.10ใงใฏใ€ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใฎ`Union`ใ‚„`Optional`ใ‚’ไฝฟใ†ไปฃๆ›ฟใจใ—ใฆใ€ๅž‹ใฎใƒฆใƒ‹ใ‚ชใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใ‚’ไฝฟใˆใพใ™ใ€‚ใ“ใ‚Œใฏใšใฃใจ่‰ฏใใ€ใ‚ˆใ‚Šใ‚ทใƒณใƒ—ใƒซใงใ™ใ€‚ -### ๅž‹ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น +//// -ๅค‰ๆ•ฐใฎๅž‹ใจใ—ใฆใ‚ฏใƒฉใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +//// tab | Python 3.9+ + +ๅŒใ˜็ต„ใฟ่พผใฟๅž‹ใ‚’ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใจใ—ใฆ๏ผˆ่ง’ๆ‹ฌๅผงใจๅ†…้ƒจใฎๅž‹ใง๏ผ‰ไฝฟใˆใพใ™: -ไพ‹ใˆใฐใ€`Person`ใ‚ฏใƒฉใ‚นใจใ„ใ†ๅๅ‰ใฎใ‚ฏใƒฉใ‚นใŒใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†: +* `list` +* `tuple` +* `set` +* `dict` -{* ../../docs_src/python_types/tutorial010.py hl[1,2,3] *} +ใใ—ใฆ`typing`ใƒขใ‚ธใƒฅใƒผใƒซใฎใ‚ธใ‚งใƒใƒชใ‚ฏใ‚น: + +* `Union` +* `Optional` +* ...and others. + +//// + +### ๅž‹ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น { #classes-as-types } + +ๅค‰ๆ•ฐใฎๅž‹ใจใ—ใฆใ‚ฏใƒฉใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ๅๅ‰ใ‚’ๆŒใค`Person`ใ‚ฏใƒฉใ‚นใŒใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†: -ๅค‰ๆ•ฐใฎๅž‹ใ‚’`Person`ใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} -{* ../../docs_src/python_types/tutorial010.py hl[6] *} +ๅค‰ๆ•ฐใ‚’`Person`ๅž‹ใจใ—ใฆๅฎฃ่จ€ใงใใพใ™: +{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} ใใ—ใฆใ€ๅ†ใณใ€ใ™ในใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚’ๅพ—ใ‚‹ใ“ใจใŒใงใใพใ™: - + -## Pydanticใฎใƒขใƒ‡ใƒซ +ใ“ใ‚Œใฏใ€Œ`one_person`ใฏใ‚ฏใƒฉใ‚น`Person`ใฎ**ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น**ใงใ‚ใ‚‹ใ€ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ + +ใ€Œ`one_person`ใฏ`Person`ใจใ„ใ†ๅๅ‰ใฎ**ใ‚ฏใƒฉใ‚น**ใงใ‚ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +## Pydanticใฎใƒขใƒ‡ใƒซ { #pydantic-models } Pydantic ใฏใƒ‡ใƒผใ‚ฟๆคœ่จผใ‚’่กŒใ†ใŸใ‚ใฎPythonใƒฉใ‚คใƒ–ใƒฉใƒชใงใ™ใ€‚ @@ -266,18 +385,17 @@ John Doe ใใ—ใฆใ€ใใ‚Œใžใ‚Œใฎๅฑžๆ€งใฏๅž‹ใ‚’ๆŒใกใพใ™ใ€‚ -ใ•ใ‚‰ใซใ€ใ„ใใคใ‹ใฎๅ€คใ‚’ๆŒใคใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€ใใฎๅ€คใ‚’ๆคœ่จผใ—ใ€้ฉๅˆ‡ใชๅž‹ใซๅค‰ๆ›ใ—ใฆ๏ผˆใ‚‚ใ—ใใ†ใงใ‚ใ‚Œใฐ๏ผ‰ๅ…จใฆใฎใƒ‡ใƒผใ‚ฟใ‚’ๆŒใคใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆไพ›ใ—ใฆใใ‚Œใพใ™ใ€‚ +ใ•ใ‚‰ใซใ€ใ„ใใคใ‹ใฎๅ€คใ‚’ๆŒใคใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€ใใฎๅ€คใ‚’ๆคœ่จผใ—ใ€้ฉๅˆ‡ใชๅž‹ใซๅค‰ๆ›ใ—ใฆ๏ผˆใ‚‚ใ—ใใ†ใงใ‚ใ‚Œใฐ๏ผ‰ใ™ในใฆใฎใƒ‡ใƒผใ‚ฟใ‚’ๆŒใคใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆไพ›ใ—ใฆใใ‚Œใพใ™ใ€‚ ใพใŸใ€ใใฎ็ตๆžœใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ™ในใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚’ๅ—ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -Pydanticใฎๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰ๅผ•็”จ: - -{* ../../docs_src/python_types/tutorial011.py *} +Pydanticใฎๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰ใฎไพ‹: +{* ../../docs_src/python_types/tutorial011_py310.py *} /// info | ๆƒ…ๅ ฑ -Pydanticใซใคใ„ใฆใ‚ˆใ‚ŠๅญฆใณใŸใ„ๆ–นใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„. +Pydanticใฎ่ฉณ็ดฐใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -285,30 +403,62 @@ Pydanticใซใคใ„ใฆใ‚ˆใ‚ŠๅญฆใณใŸใ„ๆ–นใฏRequired Optional fieldsใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณไป˜ใๅž‹ใƒ’ใƒณใƒˆ { #type-hints-with-metadata-annotations } + +Pythonใซใฏใ€`Annotated`ใ‚’ไฝฟใฃใฆๅž‹ใƒ’ใƒณใƒˆใซ**่ฟฝๅŠ ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ**ใ‚’ไป˜ไธŽใงใใ‚‹ๆฉŸ่ƒฝใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +Python 3.9ไปฅ้™ใ€`Annotated`ใฏๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎไธ€้ƒจใชใฎใงใ€`typing`ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™ใ€‚ + +{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} + +Python่‡ชไฝ“ใฏใ€ใ“ใฎ`Annotated`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใพใŸใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ไป–ใฎใƒ„ใƒผใƒซใซใจใฃใฆใ‚‚ใ€ๅž‹ใฏไพ็„ถใจใ—ใฆ`str`ใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€`Annotated`ๅ†…ใฎใ“ใฎใ‚นใƒšใƒผใ‚นใ‚’ไฝฟใฃใฆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใฉใฎใ‚ˆใ†ใซๅ‹•ไฝœใ•ใ›ใŸใ„ใ‹ใซใคใ„ใฆใฎ่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ **FastAPI** ใซๆไพ›ใงใใพใ™ใ€‚ + +่ฆšใˆใฆใŠใในใ้‡่ฆใช็‚นใฏใ€`Annotated`ใซๆธกใ™**ๆœ€ๅˆใฎ*ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ***ใŒ**ๅฎŸ้š›ใฎๅž‹**ใงใ‚ใ‚‹ใ“ใจใงใ™ใ€‚ๆฎ‹ใ‚Šใฏใ€ไป–ใฎใƒ„ใƒผใƒซๅ‘ใ‘ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใซใ™ใŽใพใ›ใ‚“ใ€‚ + +ไปŠใฎใจใ“ใ‚ใฏใ€`Annotated`ใŒๅญ˜ๅœจใ—ใ€ใใ‚ŒใŒๆจ™ๆบ–ใฎPythonใงใ‚ใ‚‹ใ“ใจใ‚’็ŸฅใฃใฆใŠใ‘ใฐๅๅˆ†ใงใ™ใ€‚๐Ÿ˜Ž + +ๅพŒใงใ€ใ“ใ‚ŒใŒใฉใ‚Œใปใฉ**ๅผทๅŠ›**ใซใชใ‚Šๅพ—ใ‚‹ใ‹ใ‚’่ฆ‹ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚ŒใŒ **ๆจ™ๆบ–ใฎPython** ใงใ‚ใ‚‹ใจใ„ใ†ไบ‹ๅฎŸใฏใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹ใƒ„ใƒผใƒซ๏ผˆใ‚ณใƒผใƒ‰ใฎ่งฃๆžใ‚„ใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐใชใฉ๏ผ‰ใจใจใ‚‚ใซใ€**ๅฏ่ƒฝใช้™ใ‚Šๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“**ใŒๅพ—ใ‚‰ใ‚Œใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ โœจ + +ใพใŸใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใŒไป–ใฎๅคšใใฎPythonใƒ„ใƒผใƒซใ‚„ใƒฉใ‚คใƒ–ใƒฉใƒชใจใ‚‚้žๅธธใซไบ’ๆ›ๆ€งใŒ้ซ˜ใ„ใ“ใจใ‚‚ๆ„ๅ‘ณใ—ใพใ™ใ€‚ ๐Ÿš€ + +/// + +## **FastAPI**ใงใฎๅž‹ใƒ’ใƒณใƒˆ { #type-hints-in-fastapi } **FastAPI** ใฏใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ๅˆฉ็”จใ—ใฆใ„ใใคใ‹ใฎใ“ใจใ‚’่กŒใ„ใพใ™ใ€‚ -**FastAPI** ใงใฏๅž‹ใƒ’ใƒณใƒˆใ‚’ไฝฟใฃใฆๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจไปฅไธ‹ใฎใ‚‚ใฎใŒๅพ—ใ‚‰ใ‚Œใพใ™: +**FastAPI** ใงใฏๅž‹ใƒ’ใƒณใƒˆใ‚’ไฝฟใฃใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจไปฅไธ‹ใฎใ‚‚ใฎใŒๅพ—ใ‚‰ใ‚Œใพใ™: -* **ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ**. -* **ๅž‹ใƒใ‚งใƒƒใ‚ฏ**. +* **ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ**ใ€‚ +* **ๅž‹ใƒใ‚งใƒƒใ‚ฏ**ใ€‚ -...ใใ—ใฆ **FastAPI** ใฏๅŒใ˜ใ‚ˆใ†ใซๅฎฃ่จ€ใ‚’ใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใ“ใจใ‚’่กŒใ„ใพใ™: +...ใใ—ใฆ **FastAPI** ใฏๅŒใ˜ๅฎฃ่จ€ใ‚’ไฝฟใฃใฆใ€ไปฅไธ‹ใฎใ“ใจใ‚’่กŒใ„ใพใ™: -* **่ฆไปถใฎๅฎš็พฉ**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒ˜ใƒƒใƒ€ใƒผใ€ใƒœใƒ‡ใ‚ฃใ€ไพๅญ˜้–ขไฟ‚ใชใฉใ‹ใ‚‰่ฆไปถใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ -* **ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‡ใƒผใ‚ฟใ‚’ๅฟ…่ฆใชๅž‹ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -* **ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ: +* **่ฆไปถใฎๅฎš็พฉ**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒ˜ใƒƒใƒ€ใƒผใ€ใƒœใƒ‡ใ‚ฃใ€ไพๅญ˜้–ขไฟ‚ใชใฉใ‹ใ‚‰่ฆไปถใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ +* **ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๅฟ…่ฆใชๅž‹ใซใƒ‡ใƒผใ‚ฟใ‚’ๅค‰ๆ›ใ—ใพใ™ใ€‚ +* **ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ**: ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๆฅใ‚‹ใƒ‡ใƒผใ‚ฟใซใคใ„ใฆ: * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใซใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ•ใ‚Œใ‚‹ **่‡ชๅ‹•ใ‚จใƒฉใƒผ** ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ -* **ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ** OpenAPIใ‚’ไฝฟ็”จใ—ใŸAPI: - * ่‡ชๅ‹•็š„ใซๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใ‚คใ‚นใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +* OpenAPIใ‚’ไฝฟ็”จใ—ใฆAPIใ‚’**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–**ใ—ใพใ™: + * ใ“ใ‚Œใฏ่‡ชๅ‹•ใฎๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใ‚คใ‚นใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ ใ™ในใฆใŒๆŠฝ่ฑก็š„ใซ่žใ“ใˆใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ ใ“ใฎๅ…จใฆใฎๅ‹•ไฝœใฏ [ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](tutorial/index.md){.internal-link target=_blank}ใง่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -้‡่ฆใชใฎใฏใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ‚’ไฝฟใ†ใ“ใจใงใ€๏ผˆใ‚ฏใƒฉใ‚นใ‚„ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใชใฉใ‚’่ฟฝๅŠ ใ™ใ‚‹ใฎใงใฏใชใ๏ผ‰๏ผ‘ใคใฎๅ ดๆ‰€ใง **FastAPI** ใŒๅคšใใฎไฝœๆฅญใ‚’ไปฃใ‚ใ‚Šใซใ‚„ใฃใฆใใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ +้‡่ฆใชใฎใฏใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ‚’ไฝฟใ†ใ“ใจใงใ€๏ผˆใ‚ฏใƒฉใ‚นใ‚„ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใชใฉใ‚’่ฟฝๅŠ ใ™ใ‚‹ใฎใงใฏใชใ๏ผ‰1ใคใฎๅ ดๆ‰€ใง **FastAPI** ใŒๅคšใใฎไฝœๆฅญใ‚’ไปฃใ‚ใ‚Šใซใ‚„ใฃใฆใใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ /// info | ๆƒ…ๅ ฑ -ใ™ใงใซใ™ในใฆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’็ต‚ใˆใฆใ€ๅž‹ใซใคใ„ใฆใฎ่ฉณ็ดฐใ‚’่ฆ‹ใ‚‹ใŸใ‚ใซใ“ใฎใƒšใƒผใ‚ธใซๆˆปใฃใฆใใŸๅ ดๅˆใฏใ€`mypy`ใฎใƒใƒผใƒˆใ‚ทใƒผใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ +ใ™ใงใซใ™ในใฆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’็ต‚ใˆใฆใ€ๅž‹ใซใคใ„ใฆใฎ่ฉณ็ดฐใ‚’่ฆ‹ใ‚‹ใŸใ‚ใซใ“ใฎใƒšใƒผใ‚ธใซๆˆปใฃใฆใใŸๅ ดๅˆใฏใ€่‰ฏใ„ใƒชใ‚ฝใƒผใ‚นใจใ—ใฆ`mypy`ใฎใ€Œใƒใƒผใƒˆใ‚ทใƒผใƒˆใ€ใŒใ‚ใ‚Šใพใ™ใ€‚ /// diff --git a/docs/ja/docs/tutorial/background-tasks.md b/docs/ja/docs/tutorial/background-tasks.md index b289faf12d..0ed41ce114 100644 --- a/docs/ja/docs/tutorial/background-tasks.md +++ b/docs/ja/docs/tutorial/background-tasks.md @@ -1,4 +1,4 @@ -# ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ +# ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ { #background-tasks } ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใŸ *ๅพŒใซ* ๅฎŸ่กŒใ•ใ‚Œใ‚‹ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ @@ -9,17 +9,17 @@ * ไฝœๆฅญๅฎŸ่กŒๅพŒใฎใƒกใƒผใƒซ้€š็Ÿฅ: * ใƒกใƒผใƒซใ‚ตใƒผใƒใƒผใธใฎๆŽฅ็ถšใจใƒกใƒผใƒซใฎ้€ไฟกใฏใ€Œ้…ใ„ใ€(ๆ•ฐ็ง’) ๅ‚พๅ‘ใŒใ‚ใ‚‹ใŸใ‚ใ€ใ™ใใซใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใงใƒกใƒผใƒซ้€š็ŸฅใŒใงใใพใ™ใ€‚ * ใƒ‡ใƒผใ‚ฟๅ‡ฆ็†: - * ใŸใจใˆใฐใ€ๆ™‚้–“ใฎใ‹ใ‹ใ‚‹ๅ‡ฆ็†ใ‚’ๅฟ…่ฆใจใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซๅ—ไฟกๆ™‚ใซใฏใ€ใ€Œๅ—ไฟกๆธˆใฟใ€(HTTP 202) ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใงๅ‡ฆ็†ใงใใพใ™ใ€‚ + * ใŸใจใˆใฐใ€ๆ™‚้–“ใฎใ‹ใ‹ใ‚‹ๅ‡ฆ็†ใ‚’ๅฟ…่ฆใจใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซๅ—ไฟกๆ™‚ใซใฏใ€ใ€ŒAcceptedใ€(HTTP 202) ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใงๅ‡ฆ็†ใงใใพใ™ใ€‚ -## `BackgroundTasks` ใฎไฝฟ็”จ +## `BackgroundTasks` ใฎไฝฟ็”จ { #using-backgroundtasks } -ใพใšๅˆใ‚ใซใ€`BackgroundTasks` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€` BackgroundTasks` ใฎๅž‹ๅฎฃ่จ€ใจๅ…ฑใซใ€*path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ๅฎš็พฉใ—ใพใ™: +ใพใšๅˆใ‚ใซใ€`BackgroundTasks` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€`BackgroundTasks` ใฎๅž‹ๅฎฃ่จ€ใจๅ…ฑใซใ€*path operation function* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ๅฎš็พฉใ—ใพใ™: -{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} **FastAPI** ใฏใ€`BackgroundTasks` ๅž‹ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซๆธกใ—ใพใ™ใ€‚ -## ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใฎไฝœๆˆ +## ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใฎไฝœๆˆ { #create-a-task-function } ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใจใ—ใฆๅฎŸ่กŒใ•ใ‚Œใ‚‹้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ @@ -31,13 +31,13 @@ ใพใŸใ€ๆ›ธใ่พผใฟๆ“ไฝœใงใฏ `async` ใจ `await` ใ‚’ไฝฟ็”จใ—ใชใ„ใŸใ‚ใ€้€šๅธธใฎ `def` ใง้–ขๆ•ฐใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ -{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} -## ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฎ่ฟฝๅŠ  +## ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฎ่ฟฝๅŠ  { #add-the-background-task } -*path operations ้–ขๆ•ฐ* ๅ†…ใงใ€`.add_task()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ—ใฆใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใ‚’ *background tasks* ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๆธกใ—ใพใ™ใ€‚ +*path operation function* ๅ†…ใงใ€`.add_task()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ—ใฆใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใ‚’ *background tasks* ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๆธกใ—ใพใ™ใ€‚ -{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} `.add_task()` ใฏไปฅไธ‹ใฎๅผ•ๆ•ฐใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™: @@ -45,40 +45,42 @@ * ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใซ้ †็•ชใซๆธกใ™ๅฟ…่ฆใฎใ‚ใ‚‹ๅผ•ๆ•ฐใฎๅˆ— (`email`)ใ€‚ * ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใซๆธกใ™ๅฟ…่ฆใฎใ‚ใ‚‹ใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐ (`message="some notification"`)ใ€‚ -## ไพๅญ˜ๆ€งๆณจๅ…ฅ +## ไพๅญ˜ๆ€งๆณจๅ…ฅ { #dependency-injection } -`BackgroundTasks` ใฎไฝฟ็”จใฏไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใงใ‚‚ๆฉŸ่ƒฝใ—ใ€ๆง˜ใ€…ใช้šŽๅฑค (*path operations ้–ขๆ•ฐ*ใ€ไพๅญ˜ๆ€ง (ไพๅญ˜ๅฏ่ƒฝๆ€ง)ใ€ใ‚ตใƒ–ไพๅญ˜ๆ€งใชใฉ) ใง `BackgroundTasks` ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ +`BackgroundTasks` ใฎไฝฟ็”จใฏไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใงใ‚‚ๆฉŸ่ƒฝใ—ใ€ๆง˜ใ€…ใช้šŽๅฑค (*path operation function*ใ€ไพๅญ˜ๆ€ง (dependable)ใ€ใ‚ตใƒ–ไพๅญ˜ๆ€งใชใฉ) ใง `BackgroundTasks` ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ -**FastAPI** ใฏใ€ใใ‚Œใžใ‚Œใฎๅ ดๅˆใฎๅ‡ฆ็†โ€‹โ€‹ๆ–นๆณ•ใจๅŒใ˜ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๅ†ๅˆฉ็”จๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใŸใ‚ใ€ใ™ในใฆใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใŒใƒžใƒผใ‚ธใ•ใ‚Œใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใงๅพŒใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +**FastAPI** ใฏใ€ใใ‚Œใžใ‚Œใฎๅ ดๅˆใฎๅ‡ฆ็†โ€‹โ€‹ๆ–นๆณ•ใจๅŒใ˜ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎๅ†ๅˆฉ็”จๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใŸใ‚ใ€ใ™ในใฆใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใŒใƒžใƒผใ‚ธใ•ใ‚Œใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใงๅพŒใงๅฎŸ่กŒใ•ใ‚Œใพใ™: + + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} -{* ../../docs_src/background_tasks/tutorial002.py hl[13,15,22,25] *} ใ“ใฎไพ‹ใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใŒ้€ไฟกใ•ใ‚ŒใŸ *ๅพŒ* ใซใƒกใƒƒใ‚ปใƒผใ‚ธใŒ `log.txt` ใƒ•ใ‚กใ‚คใƒซใซๆ›ธใ่พผใพใ‚Œใพใ™ใ€‚ ใƒชใ‚ฏใ‚จใ‚นใƒˆใซใ‚ฏใ‚จใƒชใŒใ‚ใฃใŸๅ ดๅˆใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใงใƒญใ‚ฐใซๆ›ธใ่พผใพใ‚Œใพใ™ใ€‚ -ใใ—ใฆใ€*path operations ้–ขๆ•ฐ* ใง็”Ÿๆˆใ•ใ‚ŒใŸๅˆฅใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฏใ€`email` ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๆ›ธใ่พผใฟใพใ™ใ€‚ +ใใ—ใฆใ€*path operation function* ใง็”Ÿๆˆใ•ใ‚ŒใŸๅˆฅใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฏใ€`email` ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๆ›ธใ่พผใฟใพใ™ใ€‚ -## ๆŠ€่ก“็š„ใช่ฉณ็ดฐ +## ๆŠ€่ก“็š„ใช่ฉณ็ดฐ { #technical-details } `BackgroundTasks` ใ‚ฏใƒฉใ‚นใฏใ€`starlette.background`ใ‹ใ‚‰็›ดๆŽฅๅ–ๅพ—ใ•ใ‚Œใพใ™ใ€‚ ใ“ใ‚Œใฏใ€FastAPI ใซ็›ดๆŽฅใ‚คใƒณใƒใƒผใƒˆ/ใ‚คใƒณใ‚ฏใƒซใƒผใƒ‰ใ•ใ‚Œใ‚‹ใŸใ‚ใ€`fastapi` ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใงใใ‚‹ไธŠใซใ€`starlette.background`ใ‹ใ‚‰ๅˆฅใฎ `BackgroundTask` (ๆœซๅฐพใซ `s` ใŒใชใ„) ใ‚’่ชคใฃใฆใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ“ใจใ‚’ๅ›ž้ฟใงใใพใ™ใ€‚ -`BackgroundTasks`ใฎใฟใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใง (`BackgroundTask` ใงใฏใชใ)ใ€`Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใจๅŒๆง˜ใซใ€ใใ‚Œใ‚’ *path operations ้–ขๆ•ฐ* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใจใ—ใฆไฝฟ็”จใ—ใ€**FastAPI** ใซๆฎ‹ใ‚Šใฎๅ‡ฆ็†ใ‚’ไปปใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +`BackgroundTasks`ใฎใฟใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใง (`BackgroundTask` ใงใฏใชใ)ใ€`Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใจๅŒๆง˜ใซใ€ใใ‚Œใ‚’ *path operation function* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใจใ—ใฆไฝฟ็”จใ—ใ€**FastAPI** ใซๆฎ‹ใ‚Šใฎๅ‡ฆ็†ใ‚’ไปปใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใใ‚Œใงใ‚‚ใ€FastAPI ใง `BackgroundTask` ใ‚’ๅ˜็‹ฌใงไฝฟ็”จใ™ใ‚‹ใ“ใจใฏๅฏ่ƒฝใงใ™ใŒใ€ใ‚ณใƒผใƒ‰ๅ†…ใงใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ๅซใ‚€Starlette `Response` ใ‚’่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -่ฉณ็ดฐใซใคใ„ใฆใฏใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใซ้–ขใ™ใ‚‹ Starlette ใฎๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ +่ฉณ็ดฐใซใคใ„ใฆใฏใ€Starlette ใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใซ้–ขใ™ใ‚‹ๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ -## ่ญฆๅ‘Š +## ๆณจๆ„ { #caveat } -ๅคง้‡ใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰่จˆ็ฎ—ใŒๅฟ…่ฆใงใ‚ใ‚Šใ€ๅฟ…ใšใ—ใ‚‚ๅŒใ˜ใƒ—ใƒญใ‚ปใ‚นใงๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆ (ใŸใจใˆใฐใ€ใƒกใƒขใƒชใ‚„ๅค‰ๆ•ฐใชใฉใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆ)ใ€Celery ใฎใ‚ˆใ†ใชใ‚ˆใ‚Šๅคงใใชไป–ใฎใƒ„ใƒผใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ใจใƒกใƒชใƒƒใƒˆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ๅคง้‡ใฎใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰่จˆ็ฎ—ใŒๅฟ…่ฆใงใ‚ใ‚Šใ€ๅฟ…ใšใ—ใ‚‚ๅŒใ˜ใƒ—ใƒญใ‚ปใ‚นใงๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆ (ใŸใจใˆใฐใ€ใƒกใƒขใƒชใ‚„ๅค‰ๆ•ฐใชใฉใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆ)ใ€Celery ใฎใ‚ˆใ†ใชใ‚ˆใ‚Šๅคงใใชไป–ใฎใƒ„ใƒผใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ใจใƒกใƒชใƒƒใƒˆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ ใ“ใ‚Œใ‚‰ใฏใ€ใ‚ˆใ‚Š่ค‡้›‘ใชๆง‹ๆˆใ€RabbitMQ ใ‚„ Redis ใชใฉใฎใƒกใƒƒใ‚ปใƒผใ‚ธ/ใ‚ธใƒงใƒ–ใ‚ญใƒฅใƒผใƒžใƒใƒผใ‚ธใƒฃใƒผใ‚’ๅฟ…่ฆใจใ™ใ‚‹ๅ‚พๅ‘ใŒใ‚ใ‚Šใพใ™ใŒใ€่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใ€็‰นใซ่ค‡ๆ•ฐใฎใ‚ตใƒผใƒใƒผใงใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’ๅฎŸ่กŒใงใใพใ™ใ€‚ ใŸใ ใ—ใ€ๅŒใ˜ **FastAPI** ใ‚ขใƒ—ใƒชใ‹ใ‚‰ๅค‰ๆ•ฐใจใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ€ใพใŸใฏๅฐใ•ใชใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ (้›ปๅญใƒกใƒผใƒซ้€š็Ÿฅใฎ้€ไฟกใชใฉ) ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๅ˜ใซ `BackgroundTasks` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #recap } -`BackgroundTasks` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆใ€*path operations ้–ขๆ•ฐ* ใ‚„ไพๅญ˜้–ขไฟ‚ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ `BackgroundTasks`ใ‚’ไฝฟ็”จใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’่ฟฝๅŠ ใ—ใฆไธ‹ใ•ใ„ใ€‚ +*path operation functions* ใจไพๅญ˜ๆ€งใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใง `BackgroundTasks`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟ็”จใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’่ฟฝๅŠ ใ—ใฆไธ‹ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/body-fields.md b/docs/ja/docs/tutorial/body-fields.md index ce5630351e..234c99d529 100644 --- a/docs/ja/docs/tutorial/body-fields.md +++ b/docs/ja/docs/tutorial/body-fields.md @@ -1,12 +1,13 @@ -# ใƒœใƒ‡ใ‚ฃ - ใƒ•ใ‚ฃใƒผใƒซใƒ‰ +# ใƒœใƒ‡ใ‚ฃ - ใƒ•ใ‚ฃใƒผใƒซใƒ‰ { #body-fields } `Query`ใ‚„`Path`ใ€`Body`ใ‚’ไฝฟใฃใฆ *path operation้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€Pydanticใฎ`Field`ใ‚’ไฝฟใฃใฆPydanticใƒขใƒ‡ใƒซใฎๅ†…้ƒจใงใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -## `Field`ใฎใ‚คใƒณใƒใƒผใƒˆ +## `Field`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-field } ใพใšใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/body_fields/tutorial001.py hl[4] *} +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + /// warning | ๆณจๆ„ @@ -14,11 +15,11 @@ /// -## ใƒขใƒ‡ใƒซใฎๅฑžๆ€งใฎๅฎฃ่จ€ +## ใƒขใƒ‡ใƒซใฎๅฑžๆ€งใฎๅฎฃ่จ€ { #declare-model-attributes } ไปฅไธ‹ใฎใ‚ˆใ†ใซ`Field`ใ‚’ใƒขใƒ‡ใƒซใฎๅฑžๆ€งใจใ—ใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_fields/tutorial001.py hl[11,12,13,14] *} +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} `Field`ใฏ`Query`ใ‚„`Path`ใ€`Body`ใจๅŒใ˜ใ‚ˆใ†ใซๅ‹•ไฝœใ—ใ€ๅ…จใๅŒๆง˜ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใฉใ‚’ๆŒใกใพใ™ใ€‚ @@ -40,13 +41,20 @@ /// -## ่ฟฝๅŠ ๆƒ…ๅ ฑใฎ่ฟฝๅŠ  +## ่ฟฝๅŠ ๆƒ…ๅ ฑใฎ่ฟฝๅŠ  { #add-extra-information } ่ฟฝๅŠ ๆƒ…ๅ ฑใฏ`Field`ใ‚„`Query`ใ€`Body`ใชใฉใงๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใใ—ใฆใใ‚Œใฏ็”Ÿๆˆใ•ใ‚ŒใŸJSONใ‚นใ‚ญใƒผใƒžใซๅซใพใ‚Œใพใ™ใ€‚ ๅพŒใซไพ‹ใ‚’็”จใ„ใฆๅฎฃ่จ€ใ‚’ๅญฆใถ้š›ใซใ€่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’่ฟฝๅŠ ใ™ใ‚‹ๆ–นๆณ•ใ‚’ๅญฆในใพใ™ใ€‚ -## ใพใจใ‚ +/// warning | ๆณจๆ„ + +`Field`ใซๆธกใ•ใ‚ŒใŸ่ฟฝๅŠ ใฎใ‚ญใƒผใฏใ€็ตๆžœใจใ—ใฆ็”Ÿๆˆใ•ใ‚Œใ‚‹ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎOpenAPIใ‚นใ‚ญใƒผใƒžใซใ‚‚ๅซใพใ‚Œใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎใ‚ญใƒผใฏๅฟ…ใšใ—ใ‚‚OpenAPIไป•ๆง˜ใฎไธ€้ƒจใงใ‚ใ‚‹ใจใฏ้™ใ‚‰ใชใ„ใŸใ‚ใ€ไพ‹ใˆใฐ[OpenAPI validator](https://validator.swagger.io/)ใชใฉใฎไธ€้ƒจใฎOpenAPIใƒ„ใƒผใƒซใฏใ€็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใงใฏๅ‹•ไฝœใ—ใชใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// + +## ใพใจใ‚ { #recap } Pydanticใฎ`Field`ใ‚’ไฝฟ็”จใ—ใฆใ€ใƒขใƒ‡ใƒซใฎๅฑžๆ€งใซ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/body-multiple-params.md b/docs/ja/docs/tutorial/body-multiple-params.md index cbfdda4b21..4ce77cc0dc 100644 --- a/docs/ja/docs/tutorial/body-multiple-params.md +++ b/docs/ja/docs/tutorial/body-multiple-params.md @@ -1,24 +1,24 @@ -# ใƒœใƒ‡ใ‚ฃ - ่ค‡ๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ +# ใƒœใƒ‡ใ‚ฃ - ่ค‡ๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #body-multiple-parameters } -ใ“ใ‚Œใพใง`Path`ใจ`Query`ใ‚’ใฉใ†ไฝฟใ†ใ‹ใ‚’่ฆ‹ใฆใใพใ—ใŸใŒใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎๅฎฃ่จ€ใฎใ‚ˆใ‚Š้ซ˜ๅบฆใชไฝฟใ„ๆ–นใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +ใ“ใ‚Œใพใง`Path`ใจ`Query`ใ‚’ใฉใ†ไฝฟใ†ใ‹ใ‚’่ฆ‹ใฆใใพใ—ใŸใŒใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃๅฎฃ่จ€ใฎใ‚ˆใ‚Š้ซ˜ๅบฆใชไฝฟใ„ๆ–นใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -## `Path`ใ€`Query`ใจใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆททใœใ‚‹ +## `Path`ใ€`Query`ใจใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆททใœใ‚‹ { #mix-path-query-and-body-parameters } -ใพใšใ€ใ‚‚ใกใ‚ใ‚“ใ€`Path`ใจ`Query`ใจใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎฃ่จ€ใฏ่‡ช็”ฑใซๆททใœใ‚‹ใ“ใจใŒใงใใ€ **FastAPI** ใฏไฝ•ใ‚’ใ™ใ‚‹ในใใ‹ใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ +ใพใšใ€ใ‚‚ใกใ‚ใ‚“ใ€`Path`ใจ`Query`ใจใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟๅฎฃ่จ€ใฏ่‡ช็”ฑใซๆททใœใ‚‹ใ“ใจใŒใงใใ€ **FastAPI** ใฏไฝ•ใ‚’ใ™ใ‚‹ในใใ‹ใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ -ใพใŸใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ`None`ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใงใ€ใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ‚ชใƒ—ใ‚ทใƒงใƒณใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: +ใพใŸใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ‚’`None`ใซ่จญๅฎšใ™ใ‚‹ใ“ใจใงใ€ใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ‚ชใƒ—ใ‚ทใƒงใƒณใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/body_multiple_params/tutorial001.py hl[19,20,21] *} +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} /// note | ๅ‚™่€ƒ -ใ“ใฎๅ ดๅˆใ€ใƒœใƒ‡ใ‚ฃใ‹ใ‚‰ๅ–ๅพ—ใ™ใ‚‹`item`ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏ`None`ใงใ™ใ€‚ +ใ“ใฎๅ ดๅˆใ€ใƒœใƒ‡ใ‚ฃใ‹ใ‚‰ๅ–ๅพ—ใ™ใ‚‹`item`ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ`None`ใซใชใฃใฆใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ /// -## ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #multiple-body-parameters } -ไธŠ่ฟฐใฎไพ‹ใงใฏใ€*path operations*ใฏ`item`ใฎๅฑžๆ€งใ‚’ๆŒใคไปฅไธ‹ใฎใ‚ˆใ†ใชJSONใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใฆใ„ใพใ—ใŸ: +ไธŠ่ฟฐใฎไพ‹ใงใฏใ€*path operations*ใฏ`Item`ใฎๅฑžๆ€งใ‚’ๆŒใคไปฅไธ‹ใฎใ‚ˆใ†ใชJSONใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใฆใ„ใพใ—ใŸ: ```JSON { @@ -31,11 +31,12 @@ ใ—ใ‹ใ—ใ€`item`ใจ`user`ใฎใ‚ˆใ†ใซ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/body_multiple_params/tutorial002.py hl[22] *} +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} -ใ“ใฎๅ ดๅˆใ€**FastAPI**ใฏ้–ขๆ•ฐๅ†…ใซ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆPydanticใƒขใƒ‡ใƒซใงใ‚ใ‚‹๏ผ’ใคใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผ‰ใŒใ‚ใ‚‹ใ“ใจใซๆฐ—ไป˜ใใพใ™ใ€‚ -ใใฎใŸใ‚ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅใ‚’ใƒœใƒ‡ใ‚ฃใฎใ‚ญใƒผ๏ผˆใƒ•ใ‚ฃใƒผใƒซใƒ‰ๅ๏ผ‰ใจใ—ใฆไฝฟ็”จใ—ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใฆใ„ใพใ™: +ใ“ใฎๅ ดๅˆใ€**FastAPI**ใฏ้–ขๆ•ฐๅ†…ใซ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ใ‚‹ใ“ใจใซๆฐ—ไป˜ใใพใ™๏ผˆPydanticใƒขใƒ‡ใƒซใงใ‚ใ‚‹2ใคใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ใ‚Šใพใ™๏ผ‰ใ€‚ + +ใใฎใŸใ‚ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅใ‚’ใƒœใƒ‡ใ‚ฃใฎใ‚ญใƒผ๏ผˆใƒ•ใ‚ฃใƒผใƒซใƒ‰ๅ๏ผ‰ใจใ—ใฆไฝฟ็”จใ—ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใพใ™: ```JSON { @@ -62,7 +63,7 @@ ่ค‡ๅˆใƒ‡ใƒผใ‚ฟใฎๆคœ่จผใ‚’่กŒใ„ใ€OpenAPIใ‚นใ‚ญใƒผใƒžใ‚„่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ˆใ†ใซๆ–‡ๆ›ธๅŒ–ใ—ใฆใใ‚Œใพใ™ใ€‚ -## ใƒœใƒ‡ใ‚ฃๅ†…ใฎๅ˜ๆ•ฐๅ€ค +## ใƒœใƒ‡ใ‚ฃๅ†…ใฎๅ˜ๆ•ฐๅ€ค { #singular-values-in-body } ใ‚ฏใ‚จใƒชใจใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎ่ฟฝๅŠ ใƒ‡ใƒผใ‚ฟใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใฎ `Query` ใจ `Path` ใŒใ‚ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ **FastAPI** ใฏๅŒ็ญ‰ใฎ `Body` ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ @@ -72,12 +73,11 @@ ใ—ใ‹ใ—ใ€`Body`ใ‚’ไฝฟ็”จใ—ใฆใ€**FastAPI** ใซๅˆฅใฎใƒœใƒ‡ใ‚ฃใ‚ญใƒผใจใ—ใฆๆ‰ฑใ†ใ‚ˆใ†ใซๆŒ‡็คบใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} -{* ../../docs_src/body_multiple_params/tutorial003.py hl[23] *} ใ“ใฎๅ ดๅˆใ€**FastAPI** ใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใพใ™: - ```JSON { "item": { @@ -96,41 +96,48 @@ ็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€ใƒ‡ใƒผใ‚ฟๅž‹ใฎๅค‰ๆ›ใ€ๆคœ่จผใ€ๆ–‡ๆ›ธๅŒ–ใชใฉใ‚’่กŒใ„ใพใ™ใ€‚ -## ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒช +## ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒช { #multiple-body-params-and-query } ใ‚‚ใกใ‚ใ‚“ใ€ใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅŠ ใˆใฆใ€ๅฟ…่ฆใซๅฟœใ˜ใฆ่ฟฝๅŠ ใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€ๅ˜ๆ•ฐๅ€คใฏใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใ‚‹ใฎใงใ€ๆ˜Ž็คบ็š„ใซ `Query` ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€ๅ˜ๆ•ฐๅ€คใฏใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใ‚‹ใฎใงใ€ๆ˜Ž็คบ็š„ใซ `Query` ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใฏใชใใ€ๆฌกใฎใ‚ˆใ†ใซใงใใพใ™: ```Python -q: str = None +q: str | None = None ``` -ไปฅไธ‹ใซใŠใ„ใฆ: +ใพใŸใฏPython 3.10ไปฅไธŠใงใฏ: + +```Python +q: Union[str, None] = None +``` -{* ../../docs_src/body_multiple_params/tutorial004.py hl[27] *} +ไพ‹ใˆใฐ: + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} /// info | ๆƒ…ๅ ฑ -`Body`ใ‚‚ใพใŸใ€ๅพŒ่ฟฐใ™ใ‚‹ `Query` ใ‚„ `Path` ใชใฉใจๅŒๆง˜ใซใ€ใ™ในใฆใฎๆคœ่จผใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ +`Body`ใ‚‚ใพใŸใ€ๅพŒ่ฟฐใ™ใ‚‹ `Query` ใ‚„ `Path` ใชใฉใจๅŒๆง˜ใซใ€ใ™ในใฆใฎ่ฟฝๅŠ ๆคœ่จผใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ /// -## ๅ˜ไธ€ใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅŸ‹ใ‚่พผใฟ +## ๅ˜ไธ€ใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅŸ‹ใ‚่พผใฟ { #embed-a-single-body-parameter } -Pydanticใƒขใƒ‡ใƒซ`Item`ใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item`ใ‚’1ใคใ ใ‘ๆŒใฃใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ +Pydanticใƒขใƒ‡ใƒซ`Item`ใฎๅ˜ไธ€ใฎ`item`ใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ—ใ‹ใชใ„ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€**FastAPI**ใฏใใฎใƒœใƒ‡ใ‚ฃใ‚’็›ดๆŽฅๆœŸๅพ…ใ—ใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€่ฟฝๅŠ ใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใŸใจใใฎใ‚ˆใ†ใซใ€ใ‚ญใƒผ `item` ใ‚’ๆŒใค JSON ใจใใฎไธญใฎใƒขใƒ‡ใƒซใฎๅ†…ๅฎนใ‚’ๆœŸๅพ…ใ—ใŸใ„ๅ ดๅˆใฏใ€็‰นๅˆฅใช `Body` ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `embed` ใ‚’ไฝฟใ†ใ“ใจใŒใงใใพใ™: +ใ—ใ‹ใ—ใ€่ฟฝๅŠ ใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใŸใจใใฎใ‚ˆใ†ใซใ€ใ‚ญใƒผ `item` ใ‚’ๆŒใค JSON ใจใ€ใใฎไธญใฎใƒขใƒ‡ใƒซๅ†…ๅฎนใ‚’ๆœŸๅพ…ใ—ใŸใ„ๅ ดๅˆใฏใ€็‰นๅˆฅใช `Body` ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `embed` ใ‚’ไฝฟใ†ใ“ใจใŒใงใใพใ™: ```Python -item: Item = Body(..., embed=True) +item: Item = Body(embed=True) ``` ไปฅไธ‹ใซใŠใ„ใฆ: -{* ../../docs_src/body_multiple_params/tutorial005.py hl[17] *} +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + ใ“ใฎๅ ดๅˆใ€**FastAPI** ใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใพใ™: @@ -156,9 +163,9 @@ item: Item = Body(..., embed=True) } ``` -## ใพใจใ‚ +## ใพใจใ‚ { #recap } -ใƒชใ‚ฏใ‚จใ‚นใƒˆใŒๅ˜ไธ€ใฎใƒœใƒ‡ใ‚ฃใ—ใ‹ๆŒใฆใชใ„ๅ ดๅˆใงใ‚‚ใ€*path operation้–ขๆ•ฐ*ใซ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใƒชใ‚ฏใ‚จใ‚นใƒˆใŒๅ˜ไธ€ใฎใƒœใƒ‡ใ‚ฃใ—ใ‹ๆŒใฆใชใ„ๅ ดๅˆใงใ‚‚ใ€*path operation function*ใซ่ค‡ๆ•ฐใฎใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใ—ใ‹ใ—ใ€**FastAPI** ใฏใใ‚Œใ‚’ๅ‡ฆ็†ใ—ใ€้–ขๆ•ฐๅ†…ใฎๆญฃใ—ใ„ใƒ‡ใƒผใ‚ฟใ‚’ไธŽใˆใ€*path operation*ๅ†…ใฎๆญฃใ—ใ„ใ‚นใ‚ญใƒผใƒžใ‚’ๆคœ่จผใ—ใ€ๆ–‡ๆ›ธๅŒ–ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/body-nested-models.md b/docs/ja/docs/tutorial/body-nested-models.md index a1680d10f2..24eb302082 100644 --- a/docs/ja/docs/tutorial/body-nested-models.md +++ b/docs/ja/docs/tutorial/body-nested-models.md @@ -1,36 +1,26 @@ -# ใƒœใƒ‡ใ‚ฃ - ใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ +# ใƒœใƒ‡ใ‚ฃ - ใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ { #body-nested-models } **FastAPI** ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸไปปๆ„ใฎใƒขใƒ‡ใƒซใ‚’ๅฎš็พฉใ€ๆคœ่จผใ€ๆ–‡ๆ›ธๅŒ–ใ€ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆPydanticใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ -## ใƒชใ‚นใƒˆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ +## ใƒชใ‚นใƒˆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ { #list-fields } -ๅฑžๆ€งใ‚’ใ‚ตใƒ–ใ‚ฟใ‚คใƒ—ใจใ—ใฆๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€Pythonใฎ`list`ใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๅฎš็พฉใงใใพใ™: +ๅฑžๆ€งใ‚’ใ‚ตใƒ–ใ‚ฟใ‚คใƒ—ใจใ—ใฆๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€Pythonใฎ`list`: -{* ../../docs_src/body_nested_models/tutorial001.py hl[12] *} +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} -ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๅ„้ …็›ฎใฎๅž‹ใฏๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใพใ›ใ‚“ใŒใ€`tags`ใฏใ‚ใ‚‹้ …็›ฎใฎใƒชใ‚นใƒˆใซใชใ‚Šใพใ™ใ€‚ +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๅ„้ …็›ฎใฎๅž‹ใฏๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใพใ›ใ‚“ใŒใ€`tags`ใฏใƒชใ‚นใƒˆใซใชใ‚Šใพใ™ใ€‚ -## ใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใคใƒชใ‚นใƒˆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ +## ใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใคใƒชใ‚นใƒˆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ { #list-fields-with-type-parameter } -ใ—ใ‹ใ—ใ€Pythonใซใฏๅž‹ใ‚„ใ€Œใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚’ไฝฟใฃใฆใƒชใ‚นใƒˆใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™: +ใ—ใ‹ใ—ใ€Pythonใซใฏๅ†…้ƒจใฎๅž‹ใ€ใพใŸใฏใ€Œใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚’ไฝฟใฃใฆใƒชใ‚นใƒˆใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎ็‰นๅฎšใฎๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™: -### typingใฎ`List`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ +### ใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใค`list`ใฎๅฎฃ่จ€ { #declare-a-list-with-a-type-parameter } -ใพใšใ€Pythonใฎๆจ™ๆบ–ใฎ`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰`List`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: - -{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *} - -### ใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใค`List`ใฎๅฎฃ่จ€ - -`list`ใ‚„`dict`ใ€`tuple`ใฎใ‚ˆใ†ใชใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆๅ†…้ƒจใฎๅž‹๏ผ‰ใ‚’ๆŒใคๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏ: - -* `typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰ใใ‚Œใ‚‰ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ -* ่ง’ๆ‹ฌๅผง๏ผˆ`[`ใจ`]`๏ผ‰ใ‚’ไฝฟใฃใฆใ€Œใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใจใ—ใฆๅ†…้ƒจใฎๅž‹ใ‚’ๆธกใ—ใพใ™: +`list`ใ€`dict`ใ€`tuple`ใฎใ‚ˆใ†ใซใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆๅ†…้ƒจใฎๅž‹๏ผ‰ใ‚’ๆŒใคๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€ +่ง’ๆ‹ฌๅผง๏ผˆ`[`ใจ`]`๏ผ‰ใ‚’ไฝฟใฃใฆๅ†…้ƒจใฎๅž‹ใ‚’ใ€Œใ‚ฟใ‚คใƒ—ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใจใ—ใฆๆธกใ—ใพใ™ใ€‚ ```Python -from typing import List - -my_list: List[str] +my_list: list[str] ``` ๅž‹ๅฎฃ่จ€ใฎๆจ™ๆบ–็š„ใชPythonใฎๆง‹ๆ–‡ใฏใ“ใ‚Œใ ใ‘ใงใ™ใ€‚ @@ -39,17 +29,17 @@ my_list: List[str] ใใฎใŸใ‚ใ€ไปฅไธ‹ใฎไพ‹ใงใฏ`tags`ใ‚’ๅ…ทไฝ“็š„ใชใ€Œๆ–‡ๅญ—ๅˆ—ใฎใƒชใ‚นใƒˆใ€ใซใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial002.py hl[14] *} +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} -## ใ‚ปใƒƒใƒˆๅž‹ +## ใ‚ปใƒƒใƒˆๅž‹ { #set-types } ใ—ใ‹ใ—ใ€ใ‚ˆใ่€ƒใˆใฆใฟใ‚‹ใจใ€ใ‚ฟใ‚ฐใฏ็นฐใ‚Š่ฟ”ใ™ในใใงใฏใชใใ€ใŠใใ‚‰ใใƒฆใƒ‹ใƒผใ‚ฏใชๆ–‡ๅญ—ๅˆ—ใซใชใ‚‹ใฎใงใฏใชใ„ใ‹ใจๆฐ—ไป˜ใ„ใŸใจใ—ใพใ™ใ€‚ ใใ—ใฆใ€Pythonใซใฏใƒฆใƒ‹ใƒผใ‚ฏใช้ …็›ฎใฎใ‚ปใƒƒใƒˆใฎใŸใ‚ใฎ็‰นๅˆฅใชใƒ‡ใƒผใ‚ฟๅž‹`set`ใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใฎใŸใ‚ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใ€`Set`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆ`str`ใฎ`set`ใจใ—ใฆ`tags`ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใใ—ใฆใ€`tags`ใ‚’ๆ–‡ๅญ—ๅˆ—ใฎใ‚ปใƒƒใƒˆใจใ—ใฆๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial003.py hl[1,14] *} +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} ใ“ใ‚Œใ‚’ไฝฟใˆใฐใ€ใƒ‡ใƒผใ‚ฟใŒ้‡่ค‡ใ—ใฆใ„ใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ใŸๅ ดๅˆใงใ‚‚ใ€ใƒฆใƒ‹ใƒผใ‚ฏใช้ …็›ฎใฎใ‚ปใƒƒใƒˆใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ @@ -57,27 +47,27 @@ my_list: List[str] ใพใŸใ€ใใ‚Œใซๅฟœใ˜ใฆๆณจ้‡ˆใ‚’ใคใ‘ใŸใ‚Šใ€ๆ–‡ๆ›ธๅŒ–ใ—ใŸใ‚Šใ—ใพใ™ใ€‚ -## ใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ +## ใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ { #nested-models } Pydanticใƒขใƒ‡ใƒซใฎๅ„ๅฑžๆ€งใซใฏๅž‹ใŒใ‚ใ‚Šใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ใใฎๅž‹ใฏใใ‚Œ่‡ชไฝ“ใŒๅˆฅใฎPydanticใƒขใƒ‡ใƒซใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใฎใŸใ‚ใ€็‰นๅฎšใฎๅฑžๆ€งๅใ€ๅž‹ใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๆŒ‡ๅฎšใ—ใฆใ€ๆทฑใใƒใ‚นใƒˆใ—ใŸJSON`object`ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใใฎใŸใ‚ใ€็‰นๅฎšใฎๅฑžๆ€งๅใ€ๅž‹ใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๆŒ‡ๅฎšใ—ใฆใ€ๆทฑใใƒใ‚นใƒˆใ—ใŸJSONใ€Œใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใ™ในใฆใฏใ€ไปปๆ„ใฎใƒใ‚นใƒˆใซใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -### ใ‚ตใƒ–ใƒขใƒ‡ใƒซใฎๅฎš็พฉ +### ใ‚ตใƒ–ใƒขใƒ‡ใƒซใฎๅฎš็พฉ { #define-a-submodel } ไพ‹ใˆใฐใ€`Image`ใƒขใƒ‡ใƒซใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial004.py hl[9,10,11] *} +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} -### ใ‚ตใƒ–ใƒขใƒ‡ใƒซใ‚’ๅž‹ใจใ—ใฆไฝฟ็”จ +### ใ‚ตใƒ–ใƒขใƒ‡ใƒซใ‚’ๅž‹ใจใ—ใฆไฝฟ็”จ { #use-the-submodel-as-a-type } ใใ—ใฆใ€ใใ‚Œใ‚’ๅฑžๆ€งใฎๅž‹ใจใ—ใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial004.py hl[20] *} +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} ใ“ใ‚Œใฏ **FastAPI** ใŒไปฅไธ‹ใฎใ‚ˆใ†ใชใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ™ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: @@ -102,23 +92,23 @@ Pydanticใƒขใƒ‡ใƒซใฎๅ„ๅฑžๆ€งใซใฏๅž‹ใŒใ‚ใ‚Šใพใ™ใ€‚ * ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ * ่‡ชๅ‹•ๆ–‡ๆ›ธๅŒ– -## ็‰นๆฎŠใชๅž‹ใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ +## ็‰นๆฎŠใชๅž‹ใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ { #special-types-and-validation } -`str`ใ‚„`int`ใ€`float`ใฎใ‚ˆใ†ใช้€šๅธธใฎๅ˜ๆ•ฐๅž‹ใฎไป–ใซใ‚‚ใ€`str`ใ‚’็ถ™ๆ‰ฟใ—ใŸใ‚ˆใ‚Š่ค‡้›‘ใชๅ˜ๆ•ฐๅž‹ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +`str`ใ‚„`int`ใ€`float`ใชใฉใฎ้€šๅธธใฎๅ˜ๆ•ฐๅž‹ใฎไป–ใซใ‚‚ใ€`str`ใ‚’็ถ™ๆ‰ฟใ—ใŸใ‚ˆใ‚Š่ค‡้›‘ใชๅ˜ๆ•ฐๅž‹ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ใ™ในใฆใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ใฟใ‚‹ใซใฏใ€Pydanticใฎใ‚จใ‚ญใ‚พใƒใƒƒใ‚ฏ ใชๅž‹ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ๆฌกใฎ็ซ ใงใ„ใใคใ‹ใฎไพ‹ใ‚’ใฟใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ™ในใฆใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ใฟใ‚‹ใซใฏใ€Pydanticใฎๅž‹ใฎๆฆ‚่ฆใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ๆฌกใฎ็ซ ใงใ„ใใคใ‹ใฎไพ‹ใ‚’ใฟใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ไพ‹ใˆใฐใ€`Image`ใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใซ`url`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใ‚ใ‚‹ๅ ดๅˆใ€`str`ใฎไปฃใ‚ใ‚ŠใซPydanticใฎ`HttpUrl`ใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ไพ‹ใˆใฐใ€`Image`ใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใซ`url`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใ‚ใ‚‹ๅ ดๅˆใ€`str`ใฎไปฃใ‚ใ‚ŠใซPydanticใฎ`HttpUrl`ใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial005.py hl[4,10] *} +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} -ๆ–‡ๅญ—ๅˆ—ใฏๆœ‰ๅŠนใชURLใงใ‚ใ‚‹ใ“ใจใŒ็ขบ่ชใ•ใ‚Œใ€ใใฎใ‚ˆใ†ใซJSONใ‚นใ‚ญใƒผใƒžใƒปOpenAPIใงๆ–‡ๆ›ธๅŒ–ใ•ใ‚Œใพใ™ใ€‚ +ๆ–‡ๅญ—ๅˆ—ใฏๆœ‰ๅŠนใชURLใงใ‚ใ‚‹ใ“ใจใŒ็ขบ่ชใ•ใ‚Œใ€ใใฎใ‚ˆใ†ใซJSON Schema / OpenAPIใงๆ–‡ๆ›ธๅŒ–ใ•ใ‚Œใพใ™ใ€‚ -## ใ‚ตใƒ–ใƒขใƒ‡ใƒซใฎใƒชใ‚นใƒˆใ‚’ๆŒใคๅฑžๆ€ง +## ใ‚ตใƒ–ใƒขใƒ‡ใƒซใฎใƒชใ‚นใƒˆใ‚’ๆŒใคๅฑžๆ€ง { #attributes-with-lists-of-submodels } Pydanticใƒขใƒ‡ใƒซใ‚’`list`ใ‚„`set`ใชใฉใฎใ‚ตใƒ–ใ‚ฟใ‚คใƒ—ใจใ—ใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial006.py hl[20] *} +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} ใ“ใ‚Œใฏใ€ๆฌกใฎใ‚ˆใ†ใชJSONใƒœใƒ‡ใ‚ฃใ‚’ๆœŸๅพ…ใ—ใพใ™๏ผˆๅค‰ๆ›ใ€ๆคœ่จผใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใชใฉ๏ผ‰: @@ -152,59 +142,59 @@ Pydanticใƒขใƒ‡ใƒซใ‚’`list`ใ‚„`set`ใชใฉใฎใ‚ตใƒ–ใ‚ฟใ‚คใƒ—ใจใ—ใฆไฝฟ็”จใ™ใ‚‹ /// -## ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ +## ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸใƒขใƒ‡ใƒซ { #deeply-nested-models } ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸไปปๆ„ใฎใƒขใƒ‡ใƒซใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial007.py hl[9,14,20,23,27] *} +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} /// info | ๆƒ…ๅ ฑ -`Offer`ใฏ`Item`ใฎใƒชใ‚นใƒˆใงใ‚ใ‚Šใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ`Image`ใฎใƒชใ‚นใƒˆใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ +`Offer`ใฏ`Item`ใฎใƒชใ‚นใƒˆใงใ‚ใ‚Šใ€ใใ‚Œใ‚‰ใŒใ•ใ‚‰ใซใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ`Image`ใฎใƒชใ‚นใƒˆใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ็ด”็ฒ‹ใชใƒชใ‚นใƒˆใฎใƒœใƒ‡ใ‚ฃ +## ็ด”็ฒ‹ใชใƒชใ‚นใƒˆใฎใƒœใƒ‡ใ‚ฃ { #bodies-of-pure-lists } ๆœŸๅพ…ใ™ใ‚‹JSONใƒœใƒ‡ใ‚ฃใฎใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซใฎๅ€คใŒJSON`array`๏ผˆPythonใฎ`list`๏ผ‰ใงใ‚ใ‚Œใฐใ€Pydanticใƒขใƒ‡ใƒซใจๅŒใ˜ใ‚ˆใ†ใซใ€้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: ```Python -images: List[Image] +images: list[Image] ``` ไปฅไธ‹ใฎใ‚ˆใ†ใซ: -{* ../../docs_src/body_nested_models/tutorial008.py hl[15] *} +{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} -## ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ +## ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ { #editor-support-everywhere } -ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚‚ใฉใ“ใงใ‚‚ๅ—ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใใ—ใฆใ€ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ ไปฅไธ‹ใฎใ‚ˆใ†ใซใƒชใ‚นใƒˆใฎไธญใฎ้ …็›ฎใงใ‚‚: - + Pydanticใƒขใƒ‡ใƒซใงใฏใชใใ€`dict`ใ‚’็›ดๆŽฅไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ“ใฎใ‚ˆใ†ใชใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใฏๅพ—ใ‚‰ใ‚Œใพใ›ใ‚“ใ€‚ -ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใซใคใ„ใฆๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ๅ…ฅๅŠ›ใ•ใ‚ŒใŸ่พžๆ›ธใฏ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ•ใ‚Œใ€ๅ‡บๅŠ›ใ‚‚่‡ชๅ‹•็š„ใซJSONใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใซใคใ„ใฆๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ๅ…ฅๅŠ›ใ•ใ‚ŒใŸdictใฏ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ•ใ‚Œใ€ๅ‡บๅŠ›ใ‚‚่‡ชๅ‹•็š„ใซJSONใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ -## ไปปๆ„ใฎ`dict`ใฎใƒœใƒ‡ใ‚ฃ +## ไปปๆ„ใฎ`dict`ใฎใƒœใƒ‡ใ‚ฃ { #bodies-of-arbitrary-dicts } ใพใŸใ€ใ‚ใ‚‹ๅž‹ใฎใ‚ญใƒผใจๅˆฅใฎๅž‹ใฎๅ€คใ‚’ๆŒใค`dict`ใจใ—ใฆใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ๆœ‰ๅŠนใชใƒ•ใ‚ฃใƒผใƒซใƒ‰ใƒปๅฑžๆ€งๅใ‚’ไบ‹ๅ‰ใซ็Ÿฅใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“๏ผˆPydanticใƒขใƒ‡ใƒซใฎๅ ดๅˆใฎใ‚ˆใ†ใซ๏ผ‰ใ€‚ +ใ“ใฎๆ–นๆณ•ใงใ€ๆœ‰ๅŠนใชใƒ•ใ‚ฃใƒผใƒซใƒ‰/ๅฑžๆ€งๅใ‚’ไบ‹ๅ‰ใซ็Ÿฅใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“๏ผˆPydanticใƒขใƒ‡ใƒซใฎๅ ดๅˆใฎใ‚ˆใ†ใซ๏ผ‰ใ€‚ -ใ“ใ‚Œใฏใ€ใพใ ็Ÿฅใ‚‰ใชใ„ใ‚ญใƒผใ‚’ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ใจใใซไพฟๅˆฉใ ใจๆ€ใ„ใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€ใพใ ็Ÿฅใ‚‰ใชใ„ใ‚ญใƒผใ‚’ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ใจใใซไพฟๅˆฉใงใ™ใ€‚ --- -ไป–ใซใ‚‚ใ€`int`ใฎใ‚ˆใ†ใซไป–ใฎๅž‹ใฎใ‚ญใƒผใ‚’ๆŒใกใŸใ„ๅ ดๅˆใชใฉใซไพฟๅˆฉใงใ™ใ€‚ +ใ‚‚ใ†ใฒใจใคไพฟๅˆฉใชใ‚ฑใƒผใ‚นใฏใ€ๅˆฅใฎๅž‹๏ผˆไพ‹: `int`๏ผ‰ใฎใ‚ญใƒผใ‚’ๆŒใกใŸใ„ๅ ดๅˆใงใ™ใ€‚ -ใใ‚Œใ‚’ใ“ใ“ใง่ฆ‹ใฆใ„ใใพใ—ใ‚‡ใ†ใ€‚ +ใใ‚Œใ‚’ใ“ใ“ใง่ฆ‹ใฆใ„ใใพใ™ใ€‚ ใ“ใฎๅ ดๅˆใ€`int`ใฎใ‚ญใƒผใจ`float`ใฎๅ€คใ‚’ๆŒใคใ‚‚ใฎใงใ‚ใ‚Œใฐใ€ใฉใ‚“ใช`dict`ใงใ‚‚ๅ—ใ‘ๅ…ฅใ‚Œใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial009.py hl[15] *} +{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -218,14 +208,14 @@ JSONใฏใ‚ญใƒผใจใ—ใฆ`str`ใ—ใ‹ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ„ใ“ใจใซๆณจๆ„ใ— /// -## ใพใจใ‚ +## ใพใจใ‚ { #recap } **FastAPI** ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€Pydanticใƒขใƒ‡ใƒซใŒๆไพ›ใ™ใ‚‹ๆœ€ๅคง้™ใฎๆŸ”่ปŸๆ€งใ‚’ๆŒใกใชใŒใ‚‰ใ€ใ‚ณใƒผใƒ‰ใ‚’ใ‚ทใƒณใƒ—ใƒซใซ็Ÿญใใ€ใ‚จใƒฌใ‚ฌใƒณใƒˆใซไฟใคใ“ใจใŒใงใใพใ™ใ€‚ -ไปฅไธ‹ใฎใ‚ˆใ†ใชๅˆฉ็‚นใŒใ‚ใ‚Šใพใ™: +ใ—ใ‹ใ—ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชๅˆฉ็‚นใŒใ‚ใ‚Šใพใ™: * ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆ๏ผˆใฉใ“ใงใ‚‚่ฃœๅฎŒ๏ผ๏ผ‰ -* ใƒ‡ใƒผใ‚ฟๅค‰ๆ›๏ผˆๅˆฅๅ๏ผšๆง‹ๆ–‡่งฃๆžใƒปใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บ๏ผ‰ +* ใƒ‡ใƒผใ‚ฟๅค‰ๆ›๏ผˆๅˆฅๅ๏ผšๆง‹ๆ–‡่งฃๆž / ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บ๏ผ‰ * ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ * ใ‚นใ‚ญใƒผใƒžๆ–‡ๆ›ธ -* ่‡ชๅ‹•ๆ–‡ๆ›ธๅŒ– +* ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ diff --git a/docs/ja/docs/tutorial/body-updates.md b/docs/ja/docs/tutorial/body-updates.md index ffbe52e1db..e888d5a0d9 100644 --- a/docs/ja/docs/tutorial/body-updates.md +++ b/docs/ja/docs/tutorial/body-updates.md @@ -1,16 +1,16 @@ -# ใƒœใƒ‡ใ‚ฃ - ๆ›ดๆ–ฐ +# ใƒœใƒ‡ใ‚ฃ - ๆ›ดๆ–ฐ { #body-updates } -## `PUT`ใซใ‚ˆใ‚‹็ฝฎๆ›ใงใฎๆ›ดๆ–ฐ +## `PUT`ใซใ‚ˆใ‚‹็ฝฎๆ›ใงใฎๆ›ดๆ–ฐ { #update-replacing-with-put } ้ …็›ฎใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใซใฏHTTPใฎ`PUT`ๆ“ไฝœใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -`jsonable_encoder`ใ‚’็”จใ„ใฆใ€ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’JSONๅฝขๅผใงไฟๅญ˜ใงใใ‚‹ใƒ‡ใƒผใ‚ฟใซๅค‰ๆ›ใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆไพ‹๏ผšNoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น๏ผ‰ใ€‚ไพ‹ใˆใฐใ€`datetime`ใ‚’`str`ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ +`jsonable_encoder`ใ‚’็”จใ„ใฆใ€ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’JSONใจใ—ใฆไฟๅญ˜ใงใใ‚‹ใƒ‡ใƒผใ‚ฟใซๅค‰ๆ›ใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆไพ‹๏ผšNoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น๏ผ‰ใ€‚ไพ‹ใˆใฐใ€`datetime`ใ‚’`str`ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -{* ../../docs_src/body_updates/tutorial001.py hl[30,31,32,33,34,35] *} +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} -ๆ—ขๅญ˜ใฎใƒ‡ใƒผใ‚ฟใ‚’็ฝฎใๆ›ใˆใ‚‹ในใใƒ‡ใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใซ`PUT`ใฏไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +`PUT`ใฏใ€ๆ—ขๅญ˜ใฎใƒ‡ใƒผใ‚ฟใ‚’็ฝฎใๆ›ใˆใ‚‹ในใใƒ‡ใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -### ็ฝฎๆ›ใซใคใ„ใฆใฎๆณจๆ„ +### ็ฝฎๆ›ใซใคใ„ใฆใฎๆณจๆ„ { #warning-about-replacing } ใคใพใ‚Šใ€`PUT`ใ‚’ไฝฟ็”จใ—ใฆไปฅไธ‹ใฎใƒœใƒ‡ใ‚ฃใง้ …็›ฎ`bar`ใ‚’ๆ›ดๆ–ฐใ—ใŸใ„ๅ ดๅˆใฏ: @@ -22,11 +22,11 @@ } ``` -ใ™ใงใซๆ ผ็ดใ•ใ‚Œใฆใ„ใ‚‹ๅฑžๆ€ง`"tax": 20.2`ใ‚’ๅซใพใชใ„ใŸใ‚ใ€ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏ`"tax": 10.5`ใงใ™ใ€‚ +ใ™ใงใซๆ ผ็ดใ•ใ‚Œใฆใ„ใ‚‹ๅฑžๆ€ง`"tax": 20.2`ใ‚’ๅซใพใชใ„ใŸใ‚ใ€ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใฏ`"tax": 10.5`ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅ–ใ‚Šใพใ™ใ€‚ ใใ—ใฆใ€ใƒ‡ใƒผใ‚ฟใฏใใฎใ€Œๆ–ฐใ—ใ„ใ€`10.5`ใฎ`tax`ใจๅ…ฑใซไฟๅญ˜ใ•ใ‚Œใพใ™ใ€‚ -## `PATCH`ใซใ‚ˆใ‚‹้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐ +## `PATCH`ใซใ‚ˆใ‚‹้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐ { #partial-updates-with-patch } ใพใŸใ€HTTPใฎ`PATCH`ๆ“ไฝœใงใƒ‡ใƒผใ‚ฟใ‚’*้ƒจๅˆ†็š„ใซ*ๆ›ดๆ–ฐใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ @@ -44,27 +44,27 @@ /// -### Pydanticใฎ`exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ +### Pydanticใฎ`exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ { #using-pydantics-exclude-unset-parameter } -้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐใ‚’ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ๅ ดๅˆใฏใ€Pydanticใƒขใƒ‡ใƒซใฎ`.dict()`ใฎ`exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ™ใ‚‹ใจ้žๅธธใซไพฟๅˆฉใงใ™ใ€‚ +้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐใ‚’ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ๅ ดๅˆใฏใ€Pydanticใƒขใƒ‡ใƒซใฎ`.model_dump()`ใฎ`exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ™ใ‚‹ใจ้žๅธธใซไพฟๅˆฉใงใ™ใ€‚ -`item.dict(exclude_unset=True)`ใฎใ‚ˆใ†ใซใ€‚ +`item.model_dump(exclude_unset=True)`ใฎใ‚ˆใ†ใซใ€‚ ใ“ใ‚Œใซใ‚ˆใ‚Šใ€`item`ใƒขใƒ‡ใƒซใฎไฝœๆˆๆ™‚ใซ่จญๅฎšใ•ใ‚ŒใŸใƒ‡ใƒผใ‚ฟใฎใฟใ‚’ๆŒใค`dict`ใŒ็”Ÿๆˆใ•ใ‚Œใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏ้™คๅค–ใ•ใ‚Œใพใ™ใ€‚ ใ“ใ‚Œใ‚’ไฝฟใ†ใ“ใจใงใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’็œ็•ฅใ—ใฆใ€่จญๅฎšใ•ใ‚ŒใŸ๏ผˆใƒชใ‚ฏใ‚จใ‚นใƒˆใง้€ใ‚‰ใ‚ŒใŸ๏ผ‰ใƒ‡ใƒผใ‚ฟใฎใฟใ‚’ๅซใ‚€`dict`ใ‚’็”Ÿๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_updates/tutorial002.py hl[34] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} -### Pydanticใฎ`update`ใƒ‘ใƒฉใƒกใƒผใ‚ฟ +### Pydanticใฎ`update`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ { #using-pydantics-update-parameter } -ใ“ใ“ใงใ€`.copy()`ใ‚’็”จใ„ใฆๆ—ขๅญ˜ใฎใƒขใƒ‡ใƒซใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ—ใ€`update`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆ›ดๆ–ฐใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`dict`ใ‚’ๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใ“ใงใ€`.model_copy()`ใ‚’็”จใ„ใฆๆ—ขๅญ˜ใฎใƒขใƒ‡ใƒซใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ—ใ€`update`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆ›ดๆ–ฐใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`dict`ใ‚’ๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ -`stored_item_model.copy(update=update_data)`ใฎใ‚ˆใ†ใซ: +`stored_item_model.model_copy(update=update_data)`ใฎใ‚ˆใ†ใซ: -{* ../../docs_src/body_updates/tutorial002.py hl[35] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} -### ้ƒจๅˆ†็š„ๆ›ดๆ–ฐใฎใพใจใ‚ +### ้ƒจๅˆ†็š„ๆ›ดๆ–ฐใฎใพใจใ‚ { #partial-updates-recap } ใพใจใ‚ใ‚‹ใจใ€้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐใ‚’้ฉ็”จใ™ใ‚‹ใซใฏใ€ๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: @@ -75,11 +75,11 @@ * ใ“ใฎๆ–นๆณ•ใงใฏใ€ใƒขใƒ‡ใƒซๅ†…ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ™ใงใซไฟๅญ˜ใ•ใ‚Œใฆใ„ใ‚‹ๅ€คใ‚’ไธŠๆ›ธใใ™ใ‚‹ใฎใงใฏใชใใ€ใƒฆใƒผใ‚ถใƒผใŒๅฎŸ้š›ใซ่จญๅฎšใ—ใŸๅ€คใฎใฟใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ * ไฟๅญ˜ใ•ใ‚Œใฆใ„ใ‚‹ใƒขใƒ‡ใƒซใฎใ‚ณใƒ”ใƒผใ‚’ไฝœๆˆใ—ใ€ๅ—ใ‘ๅ–ใฃใŸ้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐใงๅฑžๆ€งใ‚’ๆ›ดๆ–ฐใ—ใพใ™๏ผˆ`update`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใพใ™๏ผ‰ใ€‚ * ใ‚ณใƒ”ใƒผใ—ใŸใƒขใƒ‡ใƒซใ‚’DBใซไฟๅญ˜ใงใใ‚‹ใ‚‚ใฎใซๅค‰ๆ›ใ—ใพใ™๏ผˆไพ‹ใˆใฐใ€`jsonable_encoder`ใ‚’ไฝฟ็”จใ—ใพใ™๏ผ‰ใ€‚ - * ใ“ใ‚Œใฏใƒขใƒ‡ใƒซใฎ`.dict()`ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅ†ๅบฆๅˆฉ็”จใ™ใ‚‹ใ“ใจใซๅŒนๆ•ตใ—ใพใ™ใŒใ€ๅ€คใ‚’JSONใซๅค‰ๆ›ใงใใ‚‹ใƒ‡ใƒผใ‚ฟๅž‹ใ€ไพ‹ใˆใฐ`datetime`ใ‚’`str`ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใฏใƒขใƒ‡ใƒซใฎ`.model_dump()`ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅ†ๅบฆๅˆฉ็”จใ™ใ‚‹ใ“ใจใซๅŒนๆ•ตใ—ใพใ™ใŒใ€ๅ€คใ‚’JSONใซๅค‰ๆ›ใงใใ‚‹ใƒ‡ใƒผใ‚ฟๅž‹ใซใชใ‚‹ใ‚ˆใ†ใซใ—๏ผˆๅค‰ๆ›ใ—๏ผ‰ใ€ไพ‹ใˆใฐ`datetime`ใ‚’`str`ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ * ใƒ‡ใƒผใ‚ฟใ‚’DBใซไฟๅญ˜ใ—ใพใ™ใ€‚ * ๆ›ดๆ–ฐใ•ใ‚ŒใŸใƒขใƒ‡ใƒซใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/body_updates/tutorial002.py hl[30,31,32,33,34,35,36,37] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 1298eec7eb..a219faed04 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -1,40 +1,41 @@ -# ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ +# ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ { #request-body } -ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ (ใƒ–ใƒฉใ‚ฆใ‚ถใชใฉ) ใ‹ใ‚‰APIใซใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใใ€ใƒ‡ใƒผใ‚ฟใ‚’ **ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ (request body)** ใจใ—ใฆ้€ใ‚Šใพใ™ใ€‚ +ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ๏ผˆไพ‹ใˆใฐใƒ–ใƒฉใ‚ฆใ‚ถ๏ผ‰ใ‹ใ‚‰APIใซใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ€**ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ**ใจใ—ใฆ้€ไฟกใ—ใพใ™ใ€‚ -**ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใƒœใƒ‡ใ‚ฃใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใ‚ˆใฃใฆAPIใธ้€ใ‚‰ใ‚Œใพใ™ใ€‚**ใƒฌใ‚นใƒใƒณใ‚น** ใƒœใƒ‡ใ‚ฃใฏAPIใŒใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ้€ใ‚‹ใƒ‡ใƒผใ‚ฟใงใ™ใ€‚ +**ใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใƒœใƒ‡ใ‚ฃใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰APIใธ้€ไฟกใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใงใ™ใ€‚**ใƒฌใ‚นใƒใƒณใ‚น**ใƒœใƒ‡ใ‚ฃใฏใ€APIใŒใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ้€ไฟกใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใงใ™ใ€‚ -APIใฏใปใจใ‚“ใฉใฎๅ ดๅˆ **ใƒฌใ‚นใƒใƒณใ‚น** ใƒœใƒ‡ใ‚ฃใ‚’้€ใ‚‰ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๅฟ…ใšใ—ใ‚‚ **ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใƒœใƒ‡ใ‚ฃใ‚’้€ใ‚‰ใชใ‘ใ‚Œใฐใ„ใ‘ใชใ„ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +APIใฏใปใจใ‚“ใฉใฎๅ ดๅˆ **ใƒฌใ‚นใƒใƒณใ‚น** ใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ—ใ‹ใ—ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏใ€ๅธธใซ **ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ** ใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใฏ้™ใ‚Šใพใ›ใ‚“ใ€‚ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟไป˜ใใฎใƒ‘ใ‚นใ ใ‘ใ‚’ใƒชใ‚ฏใ‚จใ‚นใƒˆใ—ใฆใ€ใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ—ใชใ„ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -**ใƒชใ‚ฏใ‚จใ‚นใƒˆ** ใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ใใ—ใฆใ€ใใฎๅ…จใฆใฎใƒ‘ใƒฏใƒผใจใƒกใƒชใƒƒใƒˆใ‚’ๅˆฉ็”จใ—ใพใ™ใ€‚ +**ใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใ€ใใฎๅผทๅŠ›ใชๆฉŸ่ƒฝใจใƒกใƒชใƒƒใƒˆใ‚’ใ™ในใฆๅˆฉ็”จใ—ใพใ™ใ€‚ /// info | ๆƒ…ๅ ฑ -ใƒ‡ใƒผใ‚ฟใ‚’้€ใ‚‹ใซใฏใ€`POST` (ใ‚‚ใฃใจใ‚‚ใ‚ˆใไฝฟใ‚ใ‚Œใ‚‹)ใ€`PUT`ใ€`DELETE` ใพใŸใฏ `PATCH` ใ‚’ไฝฟใ†ในใใงใ™ใ€‚ +ใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ใซใฏใ€`POST`๏ผˆใ‚ˆใ‚Šไธ€่ˆฌ็š„๏ผ‰ใ€`PUT`ใ€`DELETE`ใ€`PATCH` ใฎใ„ใšใ‚Œใ‹ใ‚’ไฝฟ็”จใ™ในใใงใ™ใ€‚ -GET ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใฏใ€ไป•ๆง˜ใงใฏๆœชๅฎš็พฉใฎๅ‹•ไฝœใงใ™ใŒใ€FastAPI ใงใ‚ตใƒใƒผใƒˆใ•ใ‚ŒใฆใŠใ‚Šใ€้žๅธธใซ่ค‡้›‘ใช๏ผˆๆฅต็ซฏใช๏ผ‰ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซใฎใฟๅฏพๅฟœใ—ใฆใ„ใพใ™ใ€‚ +`GET` ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใฏไป•ๆง˜ไธŠใฏๆœชๅฎš็พฉใฎๅ‹•ไฝœใงใ™ใŒใ€ใใ‚Œใงใ‚‚FastAPIใงใฏใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใŸใ ใ—ใ€้žๅธธใซ่ค‡้›‘๏ผๆฅต็ซฏใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใฎใŸใ‚ใ ใ‘ใงใ™ใ€‚ -้žๆŽจๅฅจใชใฎใงใ€Swagger UIใ‚’ไฝฟใฃใŸๅฏพ่ฉฑๅž‹ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏGETใฎใƒœใƒ‡ใ‚ฃๆƒ…ๅ ฑใฏ่กจ็คบใ•ใ‚Œใพใ›ใ‚“ใ€‚ใ•ใ‚‰ใซใ€ไธญ็ถ™ใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใŒๅฏพๅฟœใ—ใฆใ„ใชใ„ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ +ๆŽจๅฅจใ•ใ‚Œใชใ„ใŸใ‚ใ€Swagger UIใซใ‚ˆใ‚‹ๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฏ `GET` ไฝฟ็”จๆ™‚ใฎใƒœใƒ‡ใ‚ฃใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏ่กจ็คบใ•ใ‚Œใšใ€้€”ไธญใฎใƒ—ใƒญใ‚ญใ‚ทใŒๅฏพๅฟœใ—ใฆใ„ใชใ„ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ /// -## Pydanticใฎ `BaseModel` ใ‚’ใ‚คใƒณใƒใƒผใƒˆ +## Pydanticใฎ `BaseModel` ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #import-pydantics-basemodel } -ใพใ™ๅˆใ‚ใซใ€ `pydantic` ใ‹ใ‚‰ `BaseModel` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: +ใพใšใ€`pydantic` ใ‹ใ‚‰ `BaseModel` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: -{* ../../docs_src/body/tutorial001.py hl[4] *} +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} -## ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใฎไฝœๆˆ +## ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใฎไฝœๆˆ { #create-your-data-model } -ใใ—ใฆใ€`BaseModel` ใ‚’็ถ™ๆ‰ฟใ—ใŸใ‚ฏใƒฉใ‚นใจใ—ใฆใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +ๆฌกใซใ€`BaseModel` ใ‚’็ถ™ๆ‰ฟใ™ใ‚‹ใ‚ฏใƒฉใ‚นใจใ—ใฆใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ -ใ™ในใฆใฎๅฑžๆ€งใซpythonๆจ™ๆบ–ใฎๅž‹ใ‚’ไฝฟ็”จใ—ใพใ™: +ใ™ในใฆใฎๅฑžๆ€งใซๆจ™ๆบ–ใฎPythonๅž‹ใ‚’ไฝฟ็”จใ—ใพใ™: -{* ../../docs_src/body/tutorial001.py hl[7:11] *} +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎฃ่จ€ใจๅŒๆง˜ใซใ€ใƒขใƒ‡ใƒซๅฑžๆ€งใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ใ‚‚ใคใจใใ€ๅฟ…้ ˆใชๅฑžๆ€งใงใฏใชใใชใ‚Šใพใ™ใ€‚ใใ‚Œไปฅๅค–ใฏๅฟ…้ ˆใซใชใ‚Šใพใ™ใ€‚ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใชๅฑžๆ€งใซใ—ใŸใ„ๅ ดๅˆใฏ `None` ใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ -ไพ‹ใˆใฐใ€ไธŠ่จ˜ใฎใƒขใƒ‡ใƒซใฏไปฅไธ‹ใฎๆง˜ใชJSONใ€Œ`ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ`ใ€(ใ‚‚ใ—ใใฏPythonใฎ `dict` ) ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใพใ™: +ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎฃ่จ€ใจๅŒๆง˜ใซใ€ใƒขใƒ‡ใƒซๅฑžๆ€งใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคๅ ดๅˆใฏๅฟ…้ ˆใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใ†ใงใชใ‘ใ‚Œใฐๅฟ…้ ˆใงใ™ใ€‚ๅ˜ใซใ‚ชใƒ—ใ‚ทใƒงใƒณใซใ™ใ‚‹ใซใฏ `None` ใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ + +ไพ‹ใˆใฐใ€ไธŠ่จ˜ใฎใƒขใƒ‡ใƒซใฏๆฌกใฎใ‚ˆใ†ใชJSONใ€Œ`object`ใ€๏ผˆใพใŸใฏPythonใฎ `dict`๏ผ‰ใ‚’ๅฎฃ่จ€ใ—ใพใ™: ```JSON { @@ -45,7 +46,7 @@ GET ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใฏใ€ไป•ๆง˜ใงใฏๆœชๅฎš็พฉ } ``` -...`description` ใจ `tax` ใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซ (ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏ `None`) ใชใฎใงใ€ไปฅไธ‹ใฎJSONใ€Œ`ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ`ใ€ใ‚‚ๆœ‰ๅŠนใงใ™: +...`description` ใจ `tax` ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณ๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `None`๏ผ‰ใชใฎใงใ€ใ“ใฎJSONใ€Œ`object`ใ€ใ‚‚ๆœ‰ๅŠนใงใ™: ```JSON { @@ -54,109 +55,112 @@ GET ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ใ“ใจใฏใ€ไป•ๆง˜ใงใฏๆœชๅฎš็พฉ } ``` -## ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๅฎฃ่จ€ +## ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๅฎฃ่จ€ { #declare-it-as-a-parameter } -*ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ* ใซๅŠ ใˆใ‚‹ใŸใ‚ใซใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๅŒใ˜ๆง˜ใซๅฎฃ่จ€ใ—ใพใ™: +*path operation* ใซ่ฟฝๅŠ ใ™ใ‚‹ใซใฏใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใŸใฎใจๅŒใ˜ๆ–นๆณ•ใงๅฎฃ่จ€ใ—ใพใ™: -{* ../../docs_src/body/tutorial001.py hl[18] *} +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} -...ใใ—ใฆใ€ไฝœๆˆใ—ใŸใƒขใƒ‡ใƒซ `Item` ใงๅž‹ใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +...ใใ—ใฆใ€ไฝœๆˆใ—ใŸใƒขใƒ‡ใƒซ `Item` ใ‚’ๅž‹ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ™ใ€‚ -## ็ตๆžœ +## ็ตๆžœ { #results } -ใใฎPythonใฎๅž‹ๅฎฃ่จ€ใ ใ‘ใง **FastAPI** ใฏไปฅไธ‹ใฎใ“ใจใ‚’่กŒใ„ใพใ™: +ใใฎPythonใฎๅž‹ๅฎฃ่จ€ใ ใ‘ใง **FastAPI** ใฏไปฅไธ‹ใ‚’่กŒใ„ใพใ™: -* ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‚’JSONใจใ—ใฆ่ชญใฟๅ–ใ‚Šใพใ™ใ€‚ -* ้ฉๅฝ“ใชๅž‹ใซๅค‰ๆ›ใ—ใพใ™๏ผˆๅฟ…่ฆใชๅ ดๅˆ๏ผ‰ใ€‚ +* ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒœใƒ‡ใ‚ฃใ‚’JSONใจใ—ใฆ่ชญใฟๅ–ใ‚Šใพใ™ใ€‚ +* ๅฏพๅฟœใ™ใ‚‹ๅž‹ใซๅค‰ๆ›ใ—ใพใ™๏ผˆๅฟ…่ฆใชๅ ดๅˆ๏ผ‰ใ€‚ * ใƒ‡ใƒผใ‚ฟใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ - * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใฏใ€ๆ˜Ž็ขบใชใ‚จใƒฉใƒผใŒ่ฟ”ใ•ใ‚Œใ€ใฉใ“ใŒไธๆญฃใชใƒ‡ใƒผใ‚ฟใงใ‚ใฃใŸใ‹ใ‚’็คบใ—ใพใ™ใ€‚ -* ๅ—ใ‘ๅ–ใฃใŸใƒ‡ใƒผใ‚ฟใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item` ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ - * ้–ขๆ•ฐๅ†…ใง `Item` ๅž‹ใงใ‚ใ‚‹ใจๅฎฃ่จ€ใ—ใŸใฎใงใ€ใ™ในใฆใฎๅฑžๆ€งใจใใฎๅž‹ใซๅฏพใ™ใ‚‹ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ๏ผˆ่ฃœๅฎŒใชใฉ๏ผ‰ใ‚’ใ™ในใฆไฝฟ็”จใงใใพใ™ใ€‚ -* ใƒขใƒ‡ใƒซใฎJSONใ‚นใ‚ญใƒผใƒžๅฎš็พฉใ‚’็”Ÿๆˆใ—ใ€ๅฅฝใใชๅ ดๆ‰€ใงไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -* ใ“ใ‚Œใ‚‰ใฎใ‚นใ‚ญใƒผใƒžใฏใ€็”Ÿๆˆใ•ใ‚ŒใŸOpenAPIใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใจใชใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎUIใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใฏใ€ใฉใ“ใงไฝ•ใŒไธๆญฃใชใƒ‡ใƒผใ‚ฟใ ใฃใŸใฎใ‹ใ‚’ๆญฃ็ขบใซ็คบใ™ใ€ๅˆ†ใ‹ใ‚Šใ‚„ใ™ใ„ๆ˜Ž็ขบใชใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ +* ๅ—ใ‘ๅ–ใฃใŸใƒ‡ใƒผใ‚ฟใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item` ใซๆธกใ—ใพใ™ใ€‚ + * ้–ขๆ•ฐๅ†…ใง `Item` ๅž‹ใจใ—ใฆๅฎฃ่จ€ใ—ใŸใŸใ‚ใ€ใ™ในใฆใฎๅฑžๆ€งใจใใฎๅž‹ใซใคใ„ใฆใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ๏ผˆ่ฃœๅฎŒใชใฉ๏ผ‰ใ‚‚ๅˆฉ็”จใงใใพใ™ใ€‚ +* ใƒขใƒ‡ใƒซๅ‘ใ‘ใฎ JSON Schema ๅฎš็พฉใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซใจใฃใฆๆ„ๅ‘ณใŒใ‚ใ‚‹ใชใ‚‰ใ€ไป–ใฎๅ ดๆ‰€ใงใ‚‚ๅฅฝใใชใ‚ˆใ†ใซๅˆฉ็”จใงใใพใ™ใ€‚ +* ใใ‚Œใ‚‰ใฎใ‚นใ‚ญใƒผใƒžใฏ็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใจใชใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ UIs ใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -## ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆ +## ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #automatic-docs } -ใƒขใƒ‡ใƒซใฎJSONใ‚นใ‚ญใƒผใƒžใฏOpenAPIใง็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใซใชใ‚Šใ€ๅฏพ่ฉฑ็š„ใชAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™: +ใƒขใƒ‡ใƒซใฎJSON Schemaใฏใ€OpenAPIใง็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใซใชใ‚Šใ€ๅฏพ่ฉฑ็š„ใชAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™: -ใใ—ใฆใ€ใใ‚Œใ‚‰ใŒไฝฟใ‚ใ‚Œใ‚‹ *ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ* ใฎใใ‚Œใžใ‚ŒใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚‚่กจ็คบใ•ใ‚Œใพใ™: +ใพใŸใ€ใใ‚Œใ‚‰ใŒๅฟ…่ฆใชๅ„ *path operation* ๅ†…ใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ‚‚ไฝฟ็”จใ•ใ‚Œใพใ™: -## ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆ +## ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ { #editor-support } -ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใซใ‚ˆใ‚‹ๅž‹ใƒ’ใƒณใƒˆใจ่ฃœๅฎŒใŒ้–ขๆ•ฐๅ†…ใงๅˆฉ็”จใงใใพใ™ (Pydanticใƒขใƒ‡ใƒซใงใฏใชใ `dict` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใจใ€ๅŒใ˜ใ‚ตใƒใƒผใƒˆใฏๅ—ใ‘ใ‚‰ใ‚Œใพใ›ใ‚“): +ใ‚จใƒ‡ใ‚ฃใ‚ฟไธŠใงใ€้–ขๆ•ฐๅ†…ใฎใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงๅž‹ใƒ’ใƒณใƒˆใจ่ฃœๅฎŒใŒๅพ—ใ‚‰ใ‚Œใพใ™๏ผˆPydanticใƒขใƒ‡ใƒซใฎไปฃใ‚ใ‚Šใซ `dict` ใ‚’ๅ—ใ‘ๅ–ใฃใŸๅ ดๅˆใฏ่ตทใใพใ›ใ‚“๏ผ‰: -ๅž‹ใซใ‚ˆใ‚‹ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ‚‚ๅฏ่ƒฝใงใ™: +ไธๆญฃใชๅž‹ๆ“ไฝœใซๅฏพใ™ใ‚‹ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ‚‚ๅพ—ใ‚‰ใ‚Œใพใ™: -ใ“ใ‚Œใฏๅถ็„ถใงใฏใชใใ€ใ“ใฎใƒ‡ใ‚ถใ‚คใƒณใซๅŸบใฅใ„ใฆใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใŒไฝœใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ +ใ“ใ‚Œใฏๅถ็„ถใงใฏใชใใ€ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏๅ…จไฝ“ใŒใใฎ่จญ่จˆใ‚’ไธญๅฟƒใซๆง‹็ฏ‰ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -ๅ…จใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใงๆฉŸ่ƒฝใ™ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ใŸใ‚ใซใ€ๅฎŸ่ฃ…ๅ‰ใฎ่จญ่จˆๆ™‚ใซๅพนๅบ•็š„ใซใƒ†ใ‚นใƒˆใ—ใพใ—ใŸใ€‚ +ใใ—ใฆใ€ใ™ในใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใงๅ‹•ไฝœใ™ใ‚‹ใ“ใจใ‚’็ขบๅฎŸใซใ™ใ‚‹ใŸใ‚ใซใ€ๅฎŸ่ฃ…ๅ‰ใฎ่จญ่จˆใƒ•ใ‚งใƒผใ‚บใงๅพนๅบ•็š„ใซใƒ†ใ‚นใƒˆใ•ใ‚Œใพใ—ใŸใ€‚ -ใ“ใ‚Œใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใŸใ‚ใซPydantic่‡ชไฝ“ใซใ‚‚ใ„ใใคใ‹ใฎๅค‰ๆ›ดใŒใ‚ใ‚Šใพใ—ใŸใ€‚ +ใ“ใ‚Œใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใŸใ‚ใซใ€Pydantic่‡ชไฝ“ใซใ‚‚ใ„ใใคใ‹ใฎๅค‰ๆ›ดใŒๅŠ ใˆใ‚‰ใ‚Œใพใ—ใŸใ€‚ -ไธŠ่จ˜ใฎใ‚นใ‚ฏใƒชใƒผใƒณใ‚ทใƒงใƒƒใƒˆใฏVisual Studio Codeใ‚’ๆ’ฎใฃใŸใ‚‚ใฎใงใ™ใ€‚ +ๅ‰่ฟฐใฎใ‚นใ‚ฏใƒชใƒผใƒณใ‚ทใƒงใƒƒใƒˆใฏ Visual Studio Code ใงๆ’ฎๅฝฑใ•ใ‚ŒใŸใ‚‚ใฎใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€PyCharmใ‚„ใปใจใ‚“ใฉใฎPythonใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ‚‚ๅŒๆง˜ใชใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆใ‚’ๅ—ใ‘ใ‚‰ใ‚Œใพใ™: +ใŸใ ใ—ใ€PyCharm ใ‚„ใ€ไป–ใฎใปใจใ‚“ใฉใฎPythonใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ‚‚ๅŒใ˜ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™: /// tip | ่ฑ†็Ÿฅ่ญ˜ -PyCharmใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€Pydantic PyCharm PluginใŒไฝฟ็”จๅฏ่ƒฝใงใ™ใ€‚ +ใ‚จใƒ‡ใ‚ฃใ‚ฟใจใ—ใฆ PyCharm ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€Pydantic PyCharm Plugin ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -ไปฅไธ‹ใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆใŒๅผทๅŒ–ใ•ใ‚Œใพใ™: +ไปฅไธ‹ใซใ‚ˆใ‚Šใ€Pydanticใƒขใƒ‡ใƒซใซๅฏพใ™ใ‚‹ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใŒๆ”นๅ–„ใ•ใ‚Œใพใ™: -* ่‡ชๅ‹•่ฃœๅฎŒ -* ๅž‹ใƒใ‚งใƒƒใ‚ฏ -* ใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐ -* ๆคœ็ดข -* ใ‚คใƒณใ‚นใƒšใ‚ฏใ‚ทใƒงใƒณ +* auto-completion +* type checks +* refactoring +* searching +* inspections /// -## ใƒขใƒ‡ใƒซใฎไฝฟ็”จ +## ใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ { #use-the-model } -้–ขๆ•ฐๅ†…้ƒจใงใ€ใƒขใƒ‡ใƒซใฎๅ…จใฆใฎๅฑžๆ€งใซ็›ดๆŽฅใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™: +้–ขๆ•ฐๅ†…ใงใฏใ€ใƒขใƒ‡ใƒซใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใ™ในใฆใฎๅฑžๆ€งใซ็›ดๆŽฅใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™: -{* ../../docs_src/body/tutorial002.py hl[21] *} +{* ../../docs_src/body/tutorial002_py310.py *} -## ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ + ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ + ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #request-body-path-parameters } ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‚’ๅŒๆ™‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚ -**FastAPI** ใฏใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ**ใƒ‘ใ‚นใ‹ใ‚‰ๅ—ใ‘ๅ–ใ‚Š**ใ€Pydanticใƒขใƒ‡ใƒซใซใ‚ˆใฃใฆๅฎฃ่จ€ใ•ใ‚ŒใŸ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ**ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‹ใ‚‰ๅ—ใ‘ๅ–ใ‚‹**ใจใ„ใ†ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ +**FastAPI** ใฏใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใซไธ€่‡ดใ™ใ‚‹้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ **ใƒ‘ใ‚นใ‹ใ‚‰ๅ–ๅพ—** ใ—ใ€Pydanticใƒขใƒ‡ใƒซใจใ—ใฆๅฎฃ่จ€ใ•ใ‚ŒใŸ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ **ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‹ใ‚‰ๅ–ๅพ—** ใ™ในใใ ใจ่ช่ญ˜ใ—ใพใ™ใ€‚ + +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} -{* ../../docs_src/body/tutorial003.py hl[17:18] *} -## ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ + ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ + ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ + ใƒ‘ใ‚น + ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #request-body-path-query-parameters } -ใพใŸใ€**ใƒœใƒ‡ใ‚ฃ**ใจ**ใƒ‘ใ‚น**ใจ**ใ‚ฏใ‚จใƒช**ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚ๅŒๆ™‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚ +**body**ใ€**path**ใ€**query** ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚ใ™ในใฆๅŒๆ™‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚ -**FastAPI** ใฏใใ‚Œใžใ‚Œใ‚’่ช่ญ˜ใ—ใ€้ฉๅˆ‡ใชๅ ดๆ‰€ใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ +**FastAPI** ใฏใใ‚Œใžใ‚Œใ‚’่ช่ญ˜ใ—ใ€ๆญฃใ—ใ„ๅ ดๆ‰€ใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ -{* ../../docs_src/body/tutorial004.py hl[18] *} +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} -้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏไปฅไธ‹ใฎๆง˜ใซ่ช่ญ˜ใ•ใ‚Œใพใ™: +้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏไปฅไธ‹ใฎใ‚ˆใ†ใซ่ช่ญ˜ใ•ใ‚Œใพใ™: -* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ**ใƒ‘ใ‚น**ใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๅ„ชๅ…ˆ็š„ใซใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๆ‰ฑใ‚ใ‚Œใพใ™ใ€‚ -* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ**ๅ˜ๆ•ฐๅž‹** (`int`ใ€`float`ใ€`str`ใ€`bool` ใชใฉ)ใฎๅ ดๅˆใฏ**ใ‚ฏใ‚จใƒช**ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ -* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ **Pydantic ใƒขใƒ‡ใƒซ**ๅž‹ใงๅฎฃ่จ€ใ•ใ‚ŒใŸๅ ดๅˆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใƒœใƒ‡ใ‚ฃ**ใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ +* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ **path** ใงใ‚‚ๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ **ๅ˜ๆ•ฐๅž‹**๏ผˆ`int`ใ€`float`ใ€`str`ใ€`bool` ใชใฉ๏ผ‰ใฎๅ ดๅˆใ€**query** ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ +* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ **Pydanticใƒขใƒ‡ใƒซ** ใฎๅž‹ใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆ **body** ใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ /// note | ๅ‚™่€ƒ -FastAPIใฏใ€`= None`ใŒใ‚ใ‚‹ใŠใ‹ใ’ใงใ€`q`ใŒใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใ ใจใ‚ใ‹ใ‚Šใพใ™ใ€‚ +FastAPIใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค `= None` ใŒใ‚ใ‚‹ใŸใ‚ใ€`q` ใฎๅ€คใŒๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ + +`str | None`๏ผˆPython 3.10+๏ผ‰ใ‚„ `Union[str, None]`๏ผˆPython 3.9+๏ผ‰ใฎ `Union` ใฏใ€ๅ€คใŒๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’ๅˆคๆ–ญใ™ใ‚‹ใŸใ‚ใซFastAPIใงใฏไฝฟ็”จใ•ใ‚Œใพใ›ใ‚“ใ€‚`= None` ใจใ„ใ†ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ -`Optional[str]` ใฎ`Optional` ใฏFastAPIใงใฏไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ›ใ‚“๏ผˆFastAPIใฏ`str`ใฎ้ƒจๅˆ†ใฎใฟไฝฟ็”จใ—ใพใ™๏ผ‰ใ€‚ใ—ใ‹ใ—ใ€`Optional[str]` ใฏใ‚จใƒ‡ใ‚ฃใ‚ฟใŒใ‚ณใƒผใƒ‰ใฎใ‚จใƒฉใƒผใ‚’่ฆ‹ใคใ‘ใ‚‹ใฎใ‚’ๅŠฉใ‘ใฆใใ‚Œใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ—ใ€ใ‚จใƒฉใƒผใ‚’ๆคœๅ‡บใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ /// -## Pydanticใ‚’ไฝฟใ‚ใชใ„ๆ–นๆณ• +## Pydanticใ‚’ไฝฟใ‚ใชใ„ๆ–นๆณ• { #without-pydantic } -ใ‚‚ใ—Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใŸใใชใ„ๅ ดๅˆใฏใ€**Body**ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅˆฉ็”จใงใใพใ™ใ€‚[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#_2){.internal-link target=_blank}ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟใ„ใŸใใชใ„ๅ ดๅˆใฏใ€**Body** ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚ไฝฟ็”จใงใใพใ™ใ€‚[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/cookie-param-models.md b/docs/ja/docs/tutorial/cookie-param-models.md index 8285f44efd..10ffb2566e 100644 --- a/docs/ja/docs/tutorial/cookie-param-models.md +++ b/docs/ja/docs/tutorial/cookie-param-models.md @@ -1,8 +1,8 @@ -# ใ‚ฏใƒƒใ‚ญใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒขใƒ‡ใƒซ +# ใ‚ฏใƒƒใ‚ญใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒขใƒ‡ใƒซ { #cookie-parameter-models } ใ‚‚ใ—้–ข้€ฃใ™ใ‚‹**่ค‡ๆ•ฐใฎใ‚ฏใƒƒใ‚ญใƒผ**ใ‹ใ‚‰ๆˆใ‚‹ใ‚ฐใƒซใƒผใƒ—ใŒใ‚ใ‚‹ใชใ‚‰ใ€ใใ‚Œใ‚‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝœๆˆใงใใพใ™ใ€‚๐Ÿช -ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€**่ค‡ๆ•ฐใฎๅ ดๆ‰€**ใง**ใใฎPydanticใƒขใƒ‡ใƒซใ‚’ๅ†ๅˆฉ็”จ**ใงใใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ใ€ใ™ในใฆใฎใ‚ฏใƒƒใ‚ญใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆไธ€ๅบฆใซๅฎฃ่จ€ใงใใพใ™ใ€‚๐Ÿ˜Ž +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€**่ค‡ๆ•ฐใฎๅ ดๆ‰€**ใง**ใใฎPydanticใƒขใƒ‡ใƒซใ‚’ๅ†ๅˆฉ็”จ**ใงใใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ใ€ใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆไธ€ๅบฆใซๅฎฃ่จ€ใงใใพใ™ใ€‚๐Ÿ˜Ž /// note | ๅ‚™่€ƒ @@ -16,15 +16,15 @@ /// -## ใ‚ฏใƒƒใ‚ญใƒผใซPydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ +## Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใŸใ‚ฏใƒƒใ‚ญใƒผ { #cookies-with-a-pydantic-model } -ๅฟ…่ฆใช่ค‡ๆ•ฐใฎ**ใ‚ฏใƒƒใ‚ญใƒผ**ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’**Pydanticใƒขใƒ‡ใƒซ**ใงๅฎฃ่จ€ใ—ใ€ใ•ใ‚‰ใซใ€ใใ‚Œใ‚’ `Cookie` ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ—ใ‚‡ใ†: +ๅฟ…่ฆใช่ค‡ๆ•ฐใฎ**ใ‚ฏใƒƒใ‚ญใƒผ**ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’**Pydanticใƒขใƒ‡ใƒซ**ใงๅฎฃ่จ€ใ—ใ€ใ•ใ‚‰ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `Cookie` ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ—ใ‚‡ใ†: {* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} -**FastAPI**ใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใ‚ฏใƒƒใ‚ญใƒผ**ใ‹ใ‚‰**ใใ‚Œใžใ‚Œใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใฎใƒ‡ใƒผใ‚ฟใ‚’**ๆŠฝๅ‡บ**ใ—ใ€ๅฎš็พฉใ•ใ‚ŒใŸ**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ +**FastAPI**ใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใงๅ—ใ‘ๅ–ใฃใŸ**ใ‚ฏใƒƒใ‚ญใƒผ**ใ‹ใ‚‰**ใใ‚Œใžใ‚Œใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใฎใƒ‡ใƒผใ‚ฟใ‚’**ๆŠฝๅ‡บ**ใ—ใ€ๅฎš็พฉใ—ใŸPydanticใƒขใƒ‡ใƒซใ‚’ๆไพ›ใ—ใพใ™ใ€‚ -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUI `/docs` ใงใ€ๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใ‚ฏใƒƒใ‚ญใƒผใ‚’็ขบ่ชใงใใพใ™: @@ -32,18 +32,17 @@
-/// info | ๅ‚™่€ƒ - +/// info | ๆƒ…ๅ ฑ **ใƒ–ใƒฉใ‚ฆใ‚ถใŒใ‚ฏใƒƒใ‚ญใƒผใ‚’ๅ‡ฆ็†ใ—**ใฆใ„ใพใ™ใŒใ€็‰นๅˆฅใชๆ–นๆณ•ใงๅ†…้ƒจ็š„ใซๅ‡ฆ็†ใ‚’่กŒใฃใฆใ„ใ‚‹ใŸใ‚ใซใ€**JavaScript**ใ‹ใ‚‰ใฏ็ฐกๅ˜ใซๆ“ไฝœ**ใงใใชใ„**ใ“ใจใซ็•™ๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -**ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUI** `/docs` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚Œใฐใ€*ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ*ใซ้–ขใ™ใ‚‹ใ‚ฏใƒƒใ‚ญใƒผใฎ**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณ**ใ‚’็ขบ่ชใงใใพใ™ใ€‚ +**APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUI** `/docs` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚Œใฐใ€*path operation*ใซ้–ขใ™ใ‚‹ใ‚ฏใƒƒใ‚ญใƒผใฎ**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณ**ใ‚’็ขบ่ชใงใใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใŸใจใˆ**ใ‚ฏใƒƒใ‚ญใƒผใƒ‡ใƒผใ‚ฟใ‚’ๅ…ฅๅŠ›ใ—ใฆ**ใ€ŒExecuteใ€ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ‚‚ใ€ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฏ**JavaScript**ใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹ใŸใ‚ใ‚ฏใƒƒใ‚ญใƒผใฏ้€ไฟกใ•ใ‚Œใšใ€ใพใ‚‹ใงๅ€คใ‚’ๅ…ฅๅŠ›ใ—ใชใ‹ใฃใŸใ‹ใฎใ‚ˆใ†ใช**ใ‚จใƒฉใƒผ**ใƒกใƒƒใ‚ปใƒผใ‚ธใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใŸใจใˆ**ใƒ‡ใƒผใ‚ฟใ‚’ๅ…ฅๅŠ›ใ—ใฆ**ใ€ŒExecuteใ€ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ‚‚ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฏ**JavaScript**ใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹ใŸใ‚ใ‚ฏใƒƒใ‚ญใƒผใฏ้€ไฟกใ•ใ‚Œใšใ€ใพใ‚‹ใงๅ€คใ‚’ๅ…ฅๅŠ›ใ—ใชใ‹ใฃใŸใ‹ใฎใ‚ˆใ†ใช**ใ‚จใƒฉใƒผ**ใƒกใƒƒใ‚ปใƒผใ‚ธใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ /// -## ไฝ™ๅˆ†ใชใ‚ฏใƒƒใ‚ญใƒผใ‚’็ฆๆญขใ™ใ‚‹ +## ไฝ™ๅˆ†ใชใ‚ฏใƒƒใ‚ญใƒผใ‚’็ฆๆญขใ™ใ‚‹ { #forbid-extra-cookies } ็‰นๅฎšใฎ๏ผˆใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„๏ผ‰ใ‚ฑใƒผใ‚นใงใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ใ‚ฏใƒƒใ‚ญใƒผใ‚’**ๅˆถ้™**ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ @@ -51,7 +50,7 @@ Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใจใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} ใ‚‚ใ—ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ**ไฝ™ๅˆ†ใชใ‚ฏใƒƒใ‚ญใƒผ**ใ‚’้€ใ‚ใ†ใจใ™ใ‚‹ใจใ€**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ @@ -72,6 +71,6 @@ Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ } ``` -## ใพใจใ‚ +## ใพใจใ‚ { #summary } **FastAPI**ใงใฏใ€**ใ‚ฏใƒƒใ‚ญใƒผ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/cookie-params.md b/docs/ja/docs/tutorial/cookie-params.md index 13af6d3c77..1e5a0d3cfd 100644 --- a/docs/ja/docs/tutorial/cookie-params.md +++ b/docs/ja/docs/tutorial/cookie-params.md @@ -1,20 +1,20 @@ -# ใ‚ฏใƒƒใ‚ญใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ +# ใ‚ฏใƒƒใ‚ญใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #cookie-parameters } ใ‚ฏใƒƒใ‚ญใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€`Query`ใ‚„`Path`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใจๅŒใ˜ๆ–นๆณ•ใงๅฎš็พฉใงใใพใ™ใ€‚ -## `Cookie`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ +## `Cookie`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #import-cookie } ใพใšใ€`Cookie`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/cookie_params/tutorial001.py hl[3] *} +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} -## `Cookie`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ +## `Cookie`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ { #declare-cookie-parameters } ๆฌกใซใ€`Path`ใ‚„`Query`ใจๅŒใ˜ๆง‹้€ ใ‚’ไฝฟใฃใฆใ‚ฏใƒƒใ‚ญใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ ๆœ€ๅˆใฎๅ€คใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ€่ฟฝๅŠ ใฎๆคœ่จผใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ๆณจ้‡ˆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ™ในใฆๆธกใ™ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/cookie_params/tutorial001.py hl[9] *} +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -30,6 +30,16 @@ /// -## ใพใจใ‚ +/// info | ๆƒ…ๅ ฑ + +**ใƒ–ใƒฉใ‚ฆใ‚ถใŒใ‚ฏใƒƒใ‚ญใƒผใ‚’**็‰นๆฎŠใชๆ–นๆณ•ใง่ฃๅดใงๆ‰ฑใ†ใŸใ‚ใ€**JavaScript** ใ‹ใ‚‰็ฐกๅ˜ใซใฏ่งฆใ‚Œใ‚‰ใ‚Œใชใ„ใ“ใจใ‚’ๅฟต้ ญใซ็ฝฎใ„ใฆใใ ใ•ใ„ใ€‚ + +`/docs` ใฎ **API docs UI** ใซ็งปๅ‹•ใ™ใ‚‹ใจใ€*path operation* ใฎใ‚ฏใƒƒใ‚ญใƒผใซ้–ขใ™ใ‚‹ **documentation** ใ‚’็ขบ่ชใงใใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใƒ‡ใƒผใ‚ฟใ‚’ **ๅ…ฅๅŠ›** ใ—ใฆใ€ŒExecuteใ€ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ‚‚ใ€docs UI ใฏ **JavaScript** ใงๅ‹•ไฝœใ™ใ‚‹ใŸใ‚ใ‚ฏใƒƒใ‚ญใƒผใฏ้€ไฟกใ•ใ‚Œใšใ€ๅ€คใ‚’ไฝ•ใ‚‚ๆ›ธใ‹ใชใ‹ใฃใŸใ‹ใฎใ‚ˆใ†ใช **error** ใƒกใƒƒใ‚ปใƒผใ‚ธใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +/// + +## ใพใจใ‚ { #recap } -ใ‚ฏใƒƒใ‚ญใƒผใฏ`Cookie`ใ‚’ไฝฟใฃใฆๅฎฃ่จ€ใ—ใ€`Query`ใ‚„`Path`ใจๅŒใ˜ใƒ‘ใ‚ฟใƒผใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ€‚ +ใ‚ฏใƒƒใ‚ญใƒผใฏ`Cookie`ใ‚’ไฝฟใฃใฆๅฎฃ่จ€ใ—ใ€`Query`ใ‚„`Path`ใจๅŒใ˜ๅ…ฑ้€šใฎใƒ‘ใ‚ฟใƒผใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ€‚ diff --git a/docs/ja/docs/tutorial/cors.md b/docs/ja/docs/tutorial/cors.md index f7bd59b709..a1dfe8e624 100644 --- a/docs/ja/docs/tutorial/cors.md +++ b/docs/ja/docs/tutorial/cors.md @@ -1,8 +1,8 @@ -# CORS (ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฝใƒผใ‚นๅ…ฑๆœ‰) +# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } -CORSใพใŸใฏใ€Œใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฝใƒผใ‚นๅ…ฑๆœ‰ใ€ ใฏใ€ใƒ–ใƒฉใ‚ฆใ‚ถใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใซใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจ้€šไฟกใ™ใ‚‹JavaScriptใ‚ณใƒผใƒ‰ใŒใ‚ใ‚Šใ€ใใฎใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใŒใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใจใฏ็•ฐใชใ‚‹ใ€Œใ‚ชใƒชใ‚ธใƒณใ€ใซใ‚ใ‚‹็Šถๆณใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ +CORSใพใŸใฏใ€ŒCross-Origin Resource Sharingใ€ ใฏใ€ใƒ–ใƒฉใ‚ฆใ‚ถใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใซใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจ้€šไฟกใ™ใ‚‹JavaScriptใ‚ณใƒผใƒ‰ใŒใ‚ใ‚Šใ€ใใฎใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใŒใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใจใฏ็•ฐใชใ‚‹ใ€Œใ‚ชใƒชใ‚ธใƒณใ€ใซใ‚ใ‚‹็Šถๆณใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ -## ใ‚ชใƒชใ‚ธใƒณ +## ใ‚ชใƒชใ‚ธใƒณ { #origin } ใ‚ชใƒชใ‚ธใƒณใฏใƒ—ใƒญใƒˆใ‚ณใƒซ (`http`ใ€`https`) ใจใƒ‰ใƒกใ‚คใƒณ (`myapp.com`ใ€`localhost`ใ€`localhost.tiangolo.com`) ใจใƒใƒผใƒˆ (`80`ใ€`443`ใ€`8080`) ใฎ็ต„ใฟๅˆใ‚ใ›ใงใ™ใ€‚ @@ -14,25 +14,25 @@ ใ™ในใฆ `localhost` ใงใ‚ใฃใฆใ‚‚ใ€็•ฐใชใ‚‹ใƒ—ใƒญใƒˆใ‚ณใƒซใ‚„ใƒใƒผใƒˆใ‚’ไฝฟ็”จใ™ใ‚‹ใฎใงใ€็•ฐใชใ‚‹ใ€Œใ‚ชใƒชใ‚ธใƒณใ€ใงใ™ใ€‚ -## ใ‚นใƒ†ใƒƒใƒ— +## ใ‚นใƒ†ใƒƒใƒ— { #steps } ใใ—ใฆใ€ใƒ–ใƒฉใ‚ฆใ‚ถไธŠใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ (`http://localhost:8080`) ใŒใ‚ใ‚Šใ€ใใฎJavaScriptใŒ `http://localhost` ใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใจ้€šไฟกใ™ใ‚‹ใจใ—ใพใ™ใ€‚(ใƒใƒผใƒˆใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใชใ„ใฎใงใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ`80`ใƒใƒผใƒˆใ‚’ไฝฟ็”จใ—ใพใ™) -ๆฌกใซใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏHTTPใฎ `OPTIONS` ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใซ้€ไฟกใ—ใพใ™ใ€‚ใใ—ใฆใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใŒใ“ใฎ็•ฐใชใ‚‹ใ‚ชใƒชใ‚ธใƒณ (`http://localhost:8080`) ใ‹ใ‚‰ใฎ้€šไฟกใ‚’่จฑๅฏใ™ใ‚‹้ฉๅˆ‡ใชใƒ˜ใƒƒใƒ€ใƒผใ‚’้€ไฟกใ™ใ‚‹ใจใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎJavaScriptใซใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ไฟกใ•ใ›ใพใ™ใ€‚ +ๆฌกใซใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏHTTPใฎ `OPTIONS` ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ `:80` ใฎใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใซ้€ไฟกใ—ใพใ™ใ€‚ใใ—ใฆใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใŒใ“ใฎ็•ฐใชใ‚‹ใ‚ชใƒชใ‚ธใƒณ (`http://localhost:8080`) ใ‹ใ‚‰ใฎ้€šไฟกใ‚’่จฑๅฏใ™ใ‚‹้ฉๅˆ‡ใชใƒ˜ใƒƒใƒ€ใƒผใ‚’้€ไฟกใ™ใ‚‹ใจใ€`:8080` ใฎใƒ–ใƒฉใ‚ฆใ‚ถใฏใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎJavaScriptใซ `:80` ใฎใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ไฟกใ•ใ›ใพใ™ใ€‚ -ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใซใ€Œ่จฑๅฏใ•ใ‚ŒใŸใ‚ชใƒชใ‚ธใƒณใ€ใฎใƒชใ‚นใƒˆใŒใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ +ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ€`:80` ใฎใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใซใ€Œ่จฑๅฏใ•ใ‚ŒใŸใ‚ชใƒชใ‚ธใƒณใ€ใฎใƒชใ‚นใƒˆใŒใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ -ใ“ใฎๅ ดๅˆใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚’ๆญฃใ—ใๆฉŸ่ƒฝใ•ใ›ใ‚‹ใซใฏใ€ใใฎใƒชใ‚นใƒˆใซ `http://localhost:8080` ใ‚’ๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ“ใฎๅ ดๅˆใ€`:8080` ใฎใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚’ๆญฃใ—ใๆฉŸ่ƒฝใ•ใ›ใ‚‹ใซใฏใ€ใใฎใƒชใ‚นใƒˆใซ `http://localhost:8080` ใ‚’ๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -## ใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ +## ใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ { #wildcards } -ใƒชใ‚นใƒˆใ‚’ `"*"` (ใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰) ใจๅฎฃ่จ€ใ—ใฆใ€ใ™ในใฆใ‚’่จฑๅฏใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใƒชใ‚นใƒˆใ‚’ `"*"` (ใ€Œใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ใ€) ใจๅฎฃ่จ€ใ—ใฆใ€ใ™ในใฆใ‚’่จฑๅฏใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ใŸใ ใ—ใ€Bearer Tokenใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ˆใ†ใช่ช่จผใƒ˜ใƒƒใƒ€ใƒผใ‚„Cookieใชใฉใฎใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซๆƒ…ๅ ฑใซ้–ขใ™ใ‚‹ใ‚‚ใฎใ‚’้™คใ„ใฆใ€็‰นๅฎšใฎ็จฎ้กžใฎ้€šไฟกใฎใฟใŒ่จฑๅฏใ•ใ‚Œใพใ™ใ€‚ +ใŸใ ใ—ใ€ใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซๆƒ…ๅ ฑใซ้–ขใ™ใ‚‹ใ‚‚ใฎใ€ใคใพใ‚ŠCookieใ€Bearer Tokenใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ˆใ†ใชAuthorizationใƒ˜ใƒƒใƒ€ใƒผใชใฉใ‚’ๅซใ‚€ใ‚‚ใฎใฏ้™คๅค–ใ•ใ‚Œใ€็‰นๅฎšใฎ็จฎ้กžใฎ้€šไฟกใฎใฟใŒ่จฑๅฏใ•ใ‚Œใพใ™ใ€‚ ใ—ใŸใŒใฃใฆใ€ใ™ในใฆใ‚’ๆญฃใ—ใๆฉŸ่ƒฝใ•ใ›ใ‚‹ใŸใ‚ใซใ€่จฑๅฏใ•ใ‚ŒใŸใ‚ชใƒชใ‚ธใƒณใฎๆ˜Ž็คบ็š„ใชๆŒ‡ๅฎšใ‚’ใŠๅ‹งใ‚ใ—ใพใ™ใ€‚ -## `CORSMiddleware` ใฎไฝฟ็”จ +## `CORSMiddleware` ใฎไฝฟ็”จ { #use-corsmiddleware } **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏ `CORSMiddleware` ใ‚’ไฝฟ็”จใ—ใฆใ€CORSใซ้–ขใ™ใ‚‹่จญๅฎšใŒใงใใพใ™ใ€‚ @@ -42,39 +42,43 @@ ไปฅไธ‹ใ‚‚ใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใซ่จฑๅฏใ•ใ›ใ‚‹ใ‹ใฉใ†ใ‹ๆŒ‡ๅฎšใงใใพใ™: -* ใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซๆƒ…ๅ ฑ (่ช่จผใƒ˜ใƒƒใƒ€ใƒผใ€Cookieใชใฉ) ใ€‚ +* ใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซๆƒ…ๅ ฑ (Authorizationใƒ˜ใƒƒใƒ€ใƒผใ€Cookieใชใฉ) ใ€‚ * ็‰นๅฎšใฎHTTPใƒกใ‚ฝใƒƒใƒ‰ (`POST`ใ€`PUT`) ใพใŸใฏใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ `"*"` ใ‚’ไฝฟ็”จใ—ใฆใ™ในใฆ่จฑๅฏใ€‚ * ็‰นๅฎšใฎHTTPใƒ˜ใƒƒใƒ€ใƒผใ€ใพใŸใฏใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ `"*"`ใ‚’ไฝฟ็”จใ—ใฆใ™ในใฆ่จฑๅฏใ€‚ -{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} -`CORSMiddleware` ๅฎŸ่ฃ…ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏCORSใซ้–ขใ—ใฆๅˆถ้™ใ‚’ไธŽใˆใ‚‹ใ‚‚ใฎใซใชใฃใฆใ„ใ‚‹ใฎใงใ€ใƒ–ใƒฉใ‚ฆใ‚ถใซใƒ‰ใƒกใ‚คใƒณใ‚’่ทจใ„ใง็‰นๅฎšใฎใ‚ชใƒชใ‚ธใƒณใ€ใƒกใ‚ฝใƒƒใƒ‰ใ€ใพใŸใฏใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฝฟ็”จๅฏ่ƒฝใซใ™ใ‚‹ใŸใ‚ใซใฏใ€ใใ‚Œใ‚‰ใ‚’ๆ˜Ž็คบ็š„ใซๆœ‰ๅŠนใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ + +`CORSMiddleware` ๅฎŸ่ฃ…ใงไฝฟ็”จใ•ใ‚Œใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๅˆถ้™ใŒๅŽณใ—ใ„ใŸใ‚ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใŒใ‚ฏใƒญใ‚นใƒ‰ใƒกใ‚คใƒณใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใงใใ‚Œใ‚‰ใ‚’ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใซใฏใ€็‰นๅฎšใฎใ‚ชใƒชใ‚ธใƒณใ€ใƒกใ‚ฝใƒƒใƒ‰ใ€ใพใŸใฏใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆ˜Ž็คบ็š„ใซๆœ‰ๅŠนใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ ไปฅไธ‹ใฎๅผ•ๆ•ฐใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™: * `allow_origins` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’่จฑๅฏใ™ใ‚‹ใ‚ชใƒชใ‚ธใƒณใฎใƒชใ‚นใƒˆใ€‚ไพ‹ใˆใฐใ€`['https://example.org', 'https://www.example.org']`ใ€‚`['*']`ใ‚’ไฝฟ็”จใ—ใฆไปปๆ„ใฎใ‚ชใƒชใ‚ธใƒณใ‚’่จฑๅฏใงใใพใ™ใ€‚ * `allow_origin_regex` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’่จฑๅฏใ™ใ‚‹ใ‚ชใƒชใ‚ธใƒณใฎๆญฃ่ฆ่กจ็พๆ–‡ๅญ—ๅˆ—ใ€‚ไพ‹ใˆใฐใ€`'https://.*\.example\.org'`ใ€‚ * `allow_methods` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใง่จฑๅฏใ™ใ‚‹HTTPใƒกใ‚ฝใƒƒใƒ‰ใฎใƒชใ‚นใƒˆใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `['GET']` ใงใ™ใ€‚`['*']`ใ‚’ไฝฟ็”จใ—ใฆใ™ในใฆใฎๆจ™ๆบ–ใƒกใ‚ฝใƒƒใƒ‰ใ‚’่จฑๅฏใงใใพใ™ใ€‚ -* `allow_headers` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ‚ตใƒใƒผใƒˆใ™ใ‚‹HTTPใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ˜ใƒƒใƒ€ใƒผใฎใƒชใ‚นใƒˆใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `[]` ใงใ™ใ€‚`['*']`ใ‚’ไฝฟ็”จใ—ใฆใ€ใ™ในใฆใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’่จฑๅฏใงใใพใ™ใ€‚CORSใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฏใ€ `Accept` ใ€ `Accept-Language` ใ€ `Content-Language` ใ€ `Content-Type` ใƒ˜ใƒƒใƒ€ใƒผใŒๅธธใซ่จฑๅฏใ•ใ‚Œใพใ™ใ€‚ +* `allow_headers` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ‚ตใƒใƒผใƒˆใ™ใ‚‹HTTPใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ˜ใƒƒใƒ€ใƒผใฎใƒชใ‚นใƒˆใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `[]` ใงใ™ใ€‚`['*']`ใ‚’ไฝฟ็”จใ—ใฆใ€ใ™ในใฆใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’่จฑๅฏใงใใพใ™ใ€‚ใ‚ทใƒณใƒ—ใƒซใชCORSใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฏใ€ `Accept` ใ€ `Accept-Language` ใ€ `Content-Language` ใ€ `Content-Type` ใƒ˜ใƒƒใƒ€ใƒผใŒๅธธใซ่จฑๅฏใ•ใ‚Œใพใ™ใ€‚ * `allow_credentials` - ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฏใ‚จใ‚นใƒˆใงCookieใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใ‚’็คบใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `False` ใงใ™ใ€‚ + + `allow_credentials` ใŒ `True` ใซ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€`allow_origins`ใ€`allow_methods`ใ€`allow_headers` ใฎใ„ใšใ‚Œใ‚‚ `['*']` ใซ่จญๅฎšใงใใพใ›ใ‚“ใ€‚ใ“ใ‚Œใ‚‰ใฏใ™ในใฆๆ˜Ž็คบ็š„ใซๆŒ‡ๅฎšใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + * `expose_headers` - ใƒ–ใƒฉใ‚ฆใ‚ถใ‹ใ‚‰ใ‚ขใ‚ฏใ‚ปใ‚นใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใƒฌใ‚นใƒใƒณใ‚นใƒ˜ใƒƒใƒ€ใƒผใ‚’็คบใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `[]` ใงใ™ใ€‚ * `max_age` - ใƒ–ใƒฉใ‚ฆใ‚ถใŒCORSใƒฌใ‚นใƒใƒณใ‚นใ‚’ใ‚ญใƒฃใƒƒใ‚ทใƒฅใ™ใ‚‹ๆœ€ๅคงๆ™‚้–“ใ‚’็ง’ๅ˜ไฝใง่จญๅฎšใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `600` ใงใ™ใ€‚ ใ“ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏ2็จฎ้กžใฎHTTPใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฟœ็ญ”ใ—ใพใ™... -### CORSใƒ—ใƒชใƒ•ใƒฉใ‚คใƒˆใƒชใ‚ฏใ‚จใ‚นใƒˆ +### CORSใƒ—ใƒชใƒ•ใƒฉใ‚คใƒˆใƒชใ‚ฏใ‚จใ‚นใƒˆ { #cors-preflight-requests } ใ“ใ‚Œใ‚‰ใฏใ€ `Origin` ใƒ˜ใƒƒใƒ€ใƒผใจ `Access-Control-Request-Method` ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆŒใค `OPTIONS` ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ™ใ€‚ ใ“ใฎๅ ดๅˆใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๆจชๅ–ใ‚Šใ—ใ€้ฉๅˆ‡ใชCORSใƒ˜ใƒƒใƒ€ใƒผใจๅ…ฑใซๆƒ…ๅ ฑๆไพ›ใฎใŸใ‚ใซ `200` ใพใŸใฏ `400` ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ -### ใ‚ทใƒณใƒ—ใƒซใชใƒชใ‚ฏใ‚จใ‚นใƒˆ +### ใ‚ทใƒณใƒ—ใƒซใชใƒชใ‚ฏใ‚จใ‚นใƒˆ { #simple-requests } `Origin` ใƒ˜ใƒƒใƒ€ใƒผใฎใ‚ใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใ€‚ใ“ใฎๅ ดๅˆใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏ้€šๅธธใฉใŠใ‚Šใƒชใ‚ฏใ‚จใ‚นใƒˆใซไฝ•ใ‚‚ใ—ใชใ„ใงใ™ใŒใ€ใƒฌใ‚นใƒใƒณใ‚นใซ้ฉๅˆ‡ใชCORSใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅŠ ใˆใพใ™ใ€‚ -## ใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑ +## ใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑ { #more-info } -CORSใซใคใ„ใฆใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑใฏใ€Mozilla CORS documentation ใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ +CORSใซใคใ„ใฆใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑใฏใ€Mozilla CORS documentation ใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ /// note | ๆŠ€่ก“่ฉณ็ดฐ diff --git a/docs/ja/docs/tutorial/debugging.md b/docs/ja/docs/tutorial/debugging.md index 6c29679efd..8fe5b2d5d3 100644 --- a/docs/ja/docs/tutorial/debugging.md +++ b/docs/ja/docs/tutorial/debugging.md @@ -1,14 +1,14 @@ -# ใƒ‡ใƒใƒƒใ‚ฐ +# ใƒ‡ใƒใƒƒใ‚ฐ { #debugging } Visual Studio Codeใ‚„PyCharmใชใฉใ‚’ไฝฟ็”จใ—ใฆใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผไธŠใงใƒ‡ใƒใƒƒใ‚ฌใƒผใจ้€ฃๆบใงใใพใ™ใ€‚ -## `uvicorn` ใฎๅฎŸ่กŒ +## `uvicorn` ใ‚’ๅ‘ผใณๅ‡บใ™ { #call-uvicorn } FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณไธŠใงใ€`uvicorn` ใ‚’็›ดๆŽฅใ‚คใƒณใƒใƒผใƒˆใ—ใฆๅฎŸ่กŒใ—ใพใ™: -{* ../../docs_src/debugging/tutorial001.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} -### `__name__ == "__main__"` ใซใคใ„ใฆ +### `__name__ == "__main__"` ใซใคใ„ใฆ { #about-name-main } `__name__ == "__main__"` ใฎไธปใช็›ฎ็š„ใฏใ€ใƒ•ใ‚กใ‚คใƒซใŒๆฌกใฎใ‚ณใƒžใƒณใƒ‰ใงๅ‘ผใณๅ‡บใ•ใ‚ŒใŸใจใใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ณใƒผใƒ‰ใ‚’็”จๆ„ใ™ใ‚‹ใ“ใจใงใ™: @@ -26,7 +26,7 @@ $ python myapp.py from myapp import app ``` -#### ใ‚ˆใ‚Š่ฉณใ—ใ„่ชฌๆ˜Ž +#### ใ‚ˆใ‚Š่ฉณใ—ใ„่ชฌๆ˜Ž { #more-details } ใƒ•ใ‚กใ‚คใƒซใฎๅๅ‰ใŒ `myapp.py` ใ ใจใ—ใพใ™ใ€‚ @@ -62,7 +62,7 @@ from myapp import app # Some more code ``` -`myapp.py` ๅ†…ใฎ่‡ชๅ‹•ๅค‰ๆ•ฐใซใฏใ€ๅ€คใŒ `"__main __"` ใฎๅค‰ๆ•ฐ `__name__` ใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใใฎๅ ดๅˆใ€`myapp.py` ๅ†…ใฎ่‡ชๅ‹•็š„ใซไฝœๆˆใ•ใ‚ŒใŸๅค‰ๆ•ฐ `__name__` ใฏใ€ๅ€คใจใ—ใฆ `"__main__"` ใ‚’ๆŒใกใพใ›ใ‚“ใ€‚ ใ—ใŸใŒใฃใฆใ€ไปฅไธ‹ใฎ่กŒ: @@ -78,7 +78,7 @@ from myapp import app /// -## ใƒ‡ใƒใƒƒใ‚ฌใƒผใงใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒ +## ใƒ‡ใƒใƒƒใ‚ฌใƒผใงใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒ { #run-your-code-with-your-debugger } ใ‚ณใƒผใƒ‰ใ‹ใ‚‰็›ดๆŽฅUvicornใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใƒ‡ใƒใƒƒใ‚ฌใƒผใ‹ใ‚‰็›ดๆŽฅPythonใƒ—ใƒญใ‚ฐใƒฉใƒ  (FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ) ใ‚’ๅ‘ผใณๅ‡บใ›ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md index 80153529e5..3cb1fe73d9 100644 --- a/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md @@ -1,12 +1,12 @@ -# ไพๅญ˜้–ขไฟ‚ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น +# ไพๅญ˜้–ขไฟ‚ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น { #classes-as-dependencies } **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ‚’ๆทฑใๆŽ˜ใ‚Šไธ‹ใ’ใ‚‹ๅ‰ใซใ€ๅ…ˆใปใฉใฎไพ‹ใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -## ๅ‰ใฎไพ‹ใฎ`dict` +## ๅ‰ใฎไพ‹ใฎ`dict` { #a-dict-from-the-previous-example } ๅ‰ใฎไพ‹ใงใฏใ€ไพๅญ˜้–ขไฟ‚๏ผˆ"dependable"๏ผ‰ใ‹ใ‚‰`dict`ใ‚’่ฟ”ใ—ใฆใ„ใพใ—ใŸ: -{* ../../docs_src/dependencies/tutorial001.py hl[9] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} ใ—ใ‹ใ—ใ€*path operation้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ`commons`ใซ`dict`ใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ @@ -14,7 +14,7 @@ ใ‚‚ใฃใจใ†ใพใใ‚„ใ‚Œใ‚‹ใฏใšใงใ™...ใ€‚ -## ไพๅญ˜้–ขไฟ‚ใ‚’ไฝœใ‚‹ใ‚‚ใฎ +## ไพๅญ˜้–ขไฟ‚ใ‚’ไฝœใ‚‹ใ‚‚ใฎ { #what-makes-a-dependency } ใ“ใ‚Œใพใงใฏใ€ไพๅญ˜้–ขไฟ‚ใŒ้–ขๆ•ฐใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใฎใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚ @@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo") ใ“ใ‚Œใ‚’ใ€Œๅ‘ผใณๅ‡บใ—ๅฏ่ƒฝใ€ใชใ‚‚ใฎใจๅ‘ผใณใพใ™ใ€‚ -## ไพๅญ˜้–ขไฟ‚ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น +## ไพๅญ˜้–ขไฟ‚ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น { #classes-as-dependencies_1 } Pythonใฎใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹้š›ใซใ€ๅŒใ˜ๆง‹ๆ–‡ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ“ใจใซๆฐ—ใฅใใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ @@ -67,48 +67,66 @@ FastAPIใŒๅฎŸ้š›ใซใƒใ‚งใƒƒใ‚ฏใ—ใฆใ„ใ‚‹ใฎใฏใ€ใใ‚ŒใŒใ€Œๅ‘ผใณๅ‡บใ—ๅฏ ใใ‚Œใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅ…จใใชใ„ๅ‘ผใณๅ‡บใ—ๅฏ่ƒฝใชใ‚‚ใฎใซใ‚‚้ฉ็”จใ•ใ‚Œใพใ™ใ€‚ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใชใ„*path operation้–ขๆ•ฐ*ใจๅŒใ˜ใ‚ˆใ†ใซใ€‚ -ใใ“ใงใ€ไธŠใง็ดนไป‹ใ—ใŸไพๅญ˜้–ขไฟ‚ใฎ`common_parameters`ใ‚’`CommonQueryParams`ใ‚ฏใƒฉใ‚นใซๅค‰ๆ›ดใ—ใพใ™: +ใใ“ใงใ€ไธŠใง็ดนไป‹ใ—ใŸไพๅญ˜้–ขไฟ‚ใฎ"dependable" `common_parameters`ใ‚’`CommonQueryParams`ใ‚ฏใƒฉใ‚นใซๅค‰ๆ›ดใ—ใพใ™: -{* ../../docs_src/dependencies/tutorial002.py hl[11,12,13,14,15] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ•ใ‚Œใ‚‹`__init__`ใƒกใ‚ฝใƒƒใƒ‰ใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„: -{* ../../docs_src/dependencies/tutorial002.py hl[12] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} ...ไปฅๅ‰ใฎ`common_parameters`ใจๅŒใ˜ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใฃใฆใ„ใพใ™: -{* ../../docs_src/dependencies/tutorial001.py hl[8] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} ใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ **FastAPI** ใŒไพๅญ˜้–ขไฟ‚ใ‚’ใ€Œ่งฃๆฑบใ€ใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ ใฉใกใ‚‰ใฎๅ ดๅˆใ‚‚ไปฅไธ‹ใ‚’ๆŒใฃใฆใ„ใพใ™: -* ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใฎ`q`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ -* `skip`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ`0`ใ€‚ -* `limit`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ`100`ใ€‚ +* `str`ใงใ‚ใ‚‹ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใฎ`q`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ +* ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใŒ`0`ใงใ‚ใ‚‹`int`ใฎ`skip`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ +* ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใŒ`100`ใงใ‚ใ‚‹`int`ใฎ`limit`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ ใฉใกใ‚‰ใฎๅ ดๅˆใ‚‚ใ€ใƒ‡ใƒผใ‚ฟใฏๅค‰ๆ›ใ•ใ‚Œใ€ๆคœ่จผใ•ใ‚Œใ€OpenAPIใ‚นใ‚ญใƒผใƒžใชใฉใงๆ–‡ๆ›ธๅŒ–ใ•ใ‚Œใพใ™ใ€‚ -## ไฝฟ็”จ +## ไฝฟ็”จ { #use-it } ใ“ใ‚Œใงใ€ใ“ใฎใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ—ใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/dependencies/tutorial002.py hl[19] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} **FastAPI** ใฏ`CommonQueryParams`ใ‚ฏใƒฉใ‚นใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใใฎใ‚ฏใƒฉใ‚นใฎใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใŒไฝœๆˆใ•ใ‚Œใ€ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟ`commons`ใจใ—ใฆ้–ขๆ•ฐใซๆธกใ•ใ‚Œใพใ™ใ€‚ -## ๅž‹ๆณจ้‡ˆใจ`Depends` +## ๅž‹ๆณจ้‡ˆใจ`Depends` { #type-annotation-vs-depends } ไธŠใฎใ‚ณใƒผใƒ‰ใงใฏ`CommonQueryParams`ใ‚’๏ผ’ๅ›žๆ›ธใ„ใฆใ„ใ‚‹ใ“ใจใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + ไปฅไธ‹ใซใ‚ใ‚‹ๆœ€ๅพŒใฎ`CommonQueryParams`: ```Python -... = Depends(CommonQueryParams) +... Depends(CommonQueryParams) ``` ...ใฏใ€**FastAPI** ใŒไพๅญ˜้–ขไฟ‚ใ‚’็Ÿฅใ‚‹ใŸใ‚ใซๅฎŸ้š›ใซไฝฟ็”จใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ @@ -119,55 +137,145 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ใ“ใฎๅ ดๅˆใ€ไปฅไธ‹ใซใ‚ใ‚‹ๆœ€ๅˆใฎ`CommonQueryParams`: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons: CommonQueryParams ... ``` -...ใฏ **FastAPI** ใซๅฏพใ—ใฆ็‰นๅˆฅใชๆ„ๅ‘ณใ‚’ใ‚‚ใกใพใ›ใ‚“ใ€‚FastAPIใฏใƒ‡ใƒผใ‚ฟๅค‰ๆ›ใ‚„ๆคœ่จผใชใฉใซใฏไฝฟ็”จใ—ใพใ›ใ‚“๏ผˆใใ‚Œใ‚‰ใฎใŸใ‚ใซใฏ`= Depends(CommonQueryParams)`ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™๏ผ‰ใ€‚ +//// + +...ใฏ **FastAPI** ใซๅฏพใ—ใฆ็‰นๅˆฅใชๆ„ๅ‘ณใ‚’ใ‚‚ใกใพใ›ใ‚“ใ€‚FastAPIใฏใƒ‡ใƒผใ‚ฟๅค‰ๆ›ใ‚„ๆคœ่จผใชใฉใซใฏไฝฟ็”จใ—ใพใ›ใ‚“๏ผˆใใ‚Œใ‚‰ใฎใŸใ‚ใซใฏ`Depends(CommonQueryParams)`ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™๏ผ‰ใ€‚ ๅฎŸ้š›ใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใ‘ใฐใ„ใ„ใ ใ‘ใงใ™: +//// tab | Python 3.9+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons = Depends(CommonQueryParams) ``` +//// + ไปฅไธ‹ใซใ‚ใ‚‹ใ‚ˆใ†ใซ: -{* ../../docs_src/dependencies/tutorial003.py hl[19] *} +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} ใ—ใ‹ใ—ใ€ๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใฏๆŽจๅฅจใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใใ†ใ™ใ‚Œใฐใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏ`commons`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆไฝ•ใŒๆธกใ•ใ‚Œใ‚‹ใ‹ใ‚’็Ÿฅใ‚‹ใ“ใจใŒใงใใ€ใ‚ณใƒผใƒ‰ใฎ่ฃœๅฎŒใ‚„ๅž‹ใƒใ‚งใƒƒใ‚ฏใชใฉใ‚’่กŒใ†ใฎใซๅฝน็ซ‹ใกใพใ™: - + -## ใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆ +## ใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆ { #shortcut } ใ—ใ‹ใ—ใ€ใ“ใ“ใงใฏ`CommonQueryParams`ใ‚’๏ผ’ๅ›žๆ›ธใใจใ„ใ†ใ‚ณใƒผใƒ‰ใฎ็นฐใ‚Š่ฟ”ใ—ใŒ็™บ็”Ÿใ—ใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + ไพๅญ˜้–ขไฟ‚ใŒใ€ใ‚ฏใƒฉใ‚น่‡ชไฝ“ใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซ**FastAPI**ใŒใ€Œๅ‘ผใณๅ‡บใ™ใ€*็‰นๅฎšใฎ*ใ‚ฏใƒฉใ‚นใงใ‚ใ‚‹ๅ ดๅˆใ€**FastAPI** ใฏใ“ใ‚Œใ‚‰ใฎใ‚ฑใƒผใ‚นใฎใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ ใใ‚Œใ‚‰ใฎๅ…ทไฝ“็š„ใชใ‚ฑใƒผใ‚นใซใคใ„ใฆใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใ—ใพใ™: ไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใไปฃใ‚ใ‚Šใซ: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + ...ไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใใพใ™: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends() ``` +//// + ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ใจใ—ใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใ€`Depends()`ใฎไธญใงใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒ‡ๅฎšใ›ใšใ€`Depends()`ใ‚’ใใฎ้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ๅ€ค๏ผˆ`=`ใฎใ‚ใจใฎๅ€ค๏ผ‰ใจใ—ใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€`Depends(CommonQueryParams)`ใฎไธญใงใ‚ฏใƒฉใ‚นๅ…จไฝ“ใ‚’*ใ‚‚ใ†ไธ€ๅบฆ*ๆ›ธใ‹ใชใใฆใ‚‚ใ‚ˆใใชใ‚Šใพใ™ใ€‚ ๅŒใ˜ไพ‹ใงใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/dependencies/tutorial004.py hl[19] *} +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} ...ใใ—ใฆ **FastAPI** ใฏไฝ•ใ‚’ใ™ในใใ‹็Ÿฅใฃใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 0fb15ae02c..2051afc05b 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -1,57 +1,69 @@ -# path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใฎไพๅญ˜้–ขไฟ‚ +# path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใฎไพๅญ˜้–ขไฟ‚ { #dependencies-in-path-operation-decorators } -ๅ ดๅˆใซใ‚ˆใฃใฆใฏ*path operation้–ขๆ•ฐ*ใฎไธญใงไพๅญ˜้–ขไฟ‚ใฎๆˆปใ‚Šๅ€คใ‚’ๆœฌๅฝ“ใซๅฟ…่ฆใจใ—ใชใ„ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€*path operation ้–ขๆ•ฐ*ใฎไธญใงไพๅญ˜้–ขไฟ‚ใฎๆˆปใ‚Šๅ€คใ‚’ๅฎŸ้š›ใซใฏๅฟ…่ฆใจใ—ใชใ„ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ -ใ‚‚ใ—ใใฏใ€ไพๅญ˜้–ขไฟ‚ใŒๅ€คใ‚’่ฟ”ใ•ใชใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ใพใŸใฏใ€ไพๅญ˜้–ขไฟ‚ใŒๅ€คใ‚’่ฟ”ใ•ใชใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใใ‚Œใงใ‚‚ๅฎŸ่กŒใƒป่งฃๆฑบใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใใ‚Œใงใ‚‚ๅฎŸ่กŒใƒป่งฃๆฑบใ•ใ‚Œใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใ“ใฎใ‚ˆใ†ใชๅ ดๅˆใ€*path operation้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’`Depends`ใงๅฎฃ่จ€ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€*path operation decorator*ใซ`dependencies`ใฎ`list`ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€`Depends` ใง *path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ `dependencies` ใฎ `list` ใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ -## *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใธใฎ`dependencies`ใฎ่ฟฝๅŠ  +## *path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ`dependencies`ใ‚’่ฟฝๅŠ  { #add-dependencies-to-the-path-operation-decorator } -*path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใฎๅผ•ๆ•ฐ`dependencies`ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ +*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฏใ‚ชใƒ—ใ‚ทใƒงใƒณๅผ•ๆ•ฐ`dependencies`ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ ใใ‚Œใฏ`Depends()`ใฎ`list`ใงใ‚ใ‚‹ในใใงใ™: -{* ../../docs_src/dependencies/tutorial006.py hl[17] *} +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} -ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏใ€้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒๆง˜ใซๅฎŸ่กŒใƒป่งฃๆฑบใ•ใ‚Œใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใฎๅ€ค๏ผˆไฝ•ใ‹ใ‚’่ฟ”ใ™ๅ ดๅˆ๏ผ‰ใฏ*path operation้–ขๆ•ฐ*ใซใฏๆธกใ•ใ‚Œใพใ›ใ‚“ใ€‚ +ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏใ€้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒๆง˜ใซๅฎŸ่กŒใƒป่งฃๆฑบใ•ใ‚Œใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใฎๅ€ค๏ผˆไฝ•ใ‹ใ‚’่ฟ”ใ™ๅ ดๅˆ๏ผ‰ใฏ*path operation ้–ขๆ•ฐ*ใซใฏๆธกใ•ใ‚Œใพใ›ใ‚“ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ‚จใƒ‡ใ‚ฃใ‚ฟใซใ‚ˆใฃใฆใฏใ€ๆœชไฝฟ็”จใฎ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ‚จใƒฉใƒผใจใ—ใฆ่กจ็คบใ™ใ‚‹ใ‚‚ใฎใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ไธ€้ƒจใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใ€ๆœชไฝฟ็”จใฎ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ‚จใƒฉใƒผใจใ—ใฆ่กจ็คบใ—ใพใ™ใ€‚ -`dependencies`ใ‚’`path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ`ใงไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ใƒ„ใƒผใƒซใฎใ‚จใƒฉใƒผใ‚’ๅ›ž้ฟใ—ใชใŒใ‚‰็ขบๅฎŸใซๅฎŸ่กŒใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎ`dependencies`ใ‚’*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใงไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟ/ใƒ„ใƒผใƒซใฎใ‚จใƒฉใƒผใ‚’ๅ›ž้ฟใ—ใคใคใ€็ขบๅฎŸใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใงใใพใ™ใ€‚ -ใพใŸใ€ใ‚ณใƒผใƒ‰ใฎๆœชไฝฟ็”จใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ใ‚‹ใฎใ‚’่ฆ‹ใฆใ€ใใ‚ŒใŒไธ่ฆใ ใจๆ€ใฃใฆใ—ใพใ†ใ‚ˆใ†ใชๆ–ฐใ—ใ„้–‹็™บ่€…ใฎๆททไนฑใ‚’้ฟใ‘ใ‚‹ใฎใซใ‚‚ๅฝน็ซ‹ใคใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใพใŸใ€ใ‚ณใƒผใƒ‰ๅ†…ใฎๆœชไฝฟ็”จใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่ฆ‹ใŸๆ–ฐใ—ใ„้–‹็™บ่€…ใŒใ€ใใ‚Œใ‚’ไธ่ฆใ ใจๆ€ใฃใฆๆททไนฑใ™ใ‚‹ใฎใ‚’้ฟใ‘ใ‚‹ๅŠฉใ‘ใซใ‚‚ใชใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ /// -## ไพๅญ˜้–ขไฟ‚ใฎใ‚จใƒฉใƒผใจๆˆปใ‚Šๅ€ค +/// info | ๆƒ…ๅ ฑ -้€šๅธธไฝฟ็”จใ—ใฆใ„ใ‚‹ไพๅญ˜้–ขไฟ‚ใฎ*้–ขๆ•ฐ*ใจๅŒใ˜ใ‚‚ใฎใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใฎไพ‹ใงใฏใ€ๆžถ็ฉบใฎใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผ `X-Key` ใจ `X-Token` ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ -### ไพๅญ˜้–ขไฟ‚ใฎ่ฆไปถ +ใ—ใ‹ใ—ๅฎŸ้š›ใฎใ‚ฑใƒผใ‚นใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹้š›ใฏใ€็ตฑๅˆใ•ใ‚ŒใŸ[Security utilities๏ผˆๆฌกใฎ็ซ ๏ผ‰](../security/index.md){.internal-link target=_blank}ใ‚’ไฝฟใ†ใ“ใจใงใ€ใ‚ˆใ‚Šๅคšใใฎๅˆฉ็‚นใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ่ฆไปถ๏ผˆใƒ˜ใƒƒใƒ€ใฎใ‚ˆใ†ใชใ‚‚ใฎ๏ผ‰ใ‚„ใใฎไป–ใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +/// + +## ไพๅญ˜้–ขไฟ‚ใฎใ‚จใƒฉใƒผใจๆˆปใ‚Šๅ€ค { #dependencies-errors-and-return-values } + +้€šๅธธไฝฟ็”จใ—ใฆใ„ใ‚‹ไพๅญ˜้–ขไฟ‚ใฎ*้–ขๆ•ฐ*ใจๅŒใ˜ใ‚‚ใฎใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +### ไพๅญ˜้–ขไฟ‚ใฎ่ฆไปถ { #dependency-requirements } -{* ../../docs_src/dependencies/tutorial006.py hl[6,11] *} +ใ“ใ‚Œใ‚‰ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ่ฆไปถ๏ผˆใƒ˜ใƒƒใƒ€ใƒผใฎใ‚ˆใ†ใชใ‚‚ใฎ๏ผ‰ใ‚„ใใฎไป–ใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใงใใพใ™: -### ไพ‹ๅค–ใฎ็™บ็”Ÿ +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} -ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏ้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒใ˜ใ‚ˆใ†ใซใ€ไพ‹ๅค–ใ‚’`raise`็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใŒใงใใพใ™: +### ไพ‹ๅค–ใฎ็™บ็”Ÿ { #raise-exceptions } -{* ../../docs_src/dependencies/tutorial006.py hl[8,13] *} +ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏใ€้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒใ˜ใ‚ˆใ†ใซไพ‹ๅค–ใ‚’`raise`ใงใใพใ™: -### ๆˆปใ‚Šๅ€ค +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} + +### ๆˆปใ‚Šๅ€ค { #return-values } ใใ—ใฆใ€ๅ€คใ‚’่ฟ”ใ™ใ“ใจใ‚‚่ฟ”ใ•ใชใ„ใ“ใจใ‚‚ใงใใพใ™ใŒใ€ๅ€คใฏไฝฟใ‚ใ‚Œใพใ›ใ‚“ใ€‚ -ใคใพใ‚Šใ€ใ™ใงใซใฉใ“ใ‹ใงไฝฟใฃใฆใ„ใ‚‹้€šๅธธใฎไพๅญ˜้–ขไฟ‚๏ผˆๅ€คใ‚’่ฟ”ใ™ใ‚‚ใฎ๏ผ‰ใ‚’ๅ†ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใ€ๅ€คใฏไฝฟใ‚ใ‚Œใชใใฆใ‚‚ไพๅญ˜้–ขไฟ‚ใฏๅฎŸ่กŒใ•ใ‚Œใพใ™: +ใคใพใ‚Šใ€ใ™ใงใซใฉใ“ใ‹ใงไฝฟใฃใฆใ„ใ‚‹้€šๅธธใฎไพๅญ˜้–ขไฟ‚๏ผˆๅ€คใ‚’่ฟ”ใ™ใ‚‚ใฎ๏ผ‰ใ‚’ๅ†ๅˆฉ็”จใงใใ€ๅ€คใฏไฝฟใ‚ใ‚Œใชใใฆใ‚‚ไพๅญ˜้–ขไฟ‚ใฏๅฎŸ่กŒใ•ใ‚Œใพใ™: + +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} + +## *path operation*ใฎใ‚ฐใƒซใƒผใƒ—ใซๅฏพใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ { #dependencies-for-a-group-of-path-operations } -{* ../../docs_src/dependencies/tutorial006.py hl[9,14] *} +ๅพŒใงใ€ใ‚ˆใ‚Šๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’๏ผˆใŠใใ‚‰ใ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซใง๏ผ‰ๆง‹้€ ๅŒ–ใ™ใ‚‹ๆ–นๆณ•๏ผˆ[Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}๏ผ‰ใซใคใ„ใฆ่ชญใ‚€ใจใใซใ€*path operation*ใฎใ‚ฐใƒซใƒผใƒ—ใซๅฏพใ—ใฆๅ˜ไธ€ใฎ`dependencies`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใ‚’ๅญฆใณใพใ™ใ€‚ -## *path operations*ใฎใ‚ฐใƒซใƒผใƒ—ใซๅฏพใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ +## ใ‚ฐใƒญใƒผใƒใƒซไพๅญ˜้–ขไฟ‚ { #global-dependencies } -ๅพŒใงใ€ใ‚ˆใ‚Šๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๆง‹้€ ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank})ใซใคใ„ใฆ่ชญใ‚€ๆ™‚ใซใ€ใŠใใ‚‰ใ่ค‡ๆ•ฐใฎใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟ็”จใ—ใฆใ€*path operations*ใฎใ‚ฐใƒซใƒผใƒ—ใซๅฏพใ—ใฆๅ˜ไธ€ใฎ`dependencies`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใ‚’ๅญฆใถใงใ—ใ‚‡ใ†ใ€‚ +ๆฌกใซใ€`FastAPI`ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ…จไฝ“ใซไพๅญ˜้–ขไฟ‚ใ‚’่ฟฝๅŠ ใ—ใฆใ€ๅ„*path operation*ใซ้ฉ็”จใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md index 35a69de0df..8095114c3f 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,24 +1,12 @@ -# yieldใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ +# `yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield } -FastAPIใฏใ€ใ„ใใคใ‹ใฎ็ต‚ไบ†ๅพŒใฎ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’่กŒใ†ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ +FastAPIใฏใ€ใ„ใใคใ‹ใฎ็ต‚ไบ†ๅพŒใฎ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’่กŒใ†ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ -ใ“ใ‚Œใ‚’่กŒใ†ใซใฏใ€`return`ใฎไปฃใ‚ใ‚Šใซ`yield`ใ‚’ไฝฟใ„ใ€ใใฎๅพŒใซ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ๆ›ธใใพใ™ใ€‚ +ใ“ใ‚Œใ‚’่กŒใ†ใซใฏใ€`return`ใฎไปฃใ‚ใ‚Šใซ`yield`ใ‚’ไฝฟใ„ใ€ใใฎๅพŒใซ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—๏ผˆใ‚ณใƒผใƒ‰๏ผ‰ใ‚’ๆ›ธใใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -`yield`ใฏๅฟ…ใšไธ€ๅบฆใ ใ‘ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ - -/// - -/// info | ๆƒ…ๅ ฑ - -ใ“ใ‚Œใ‚’ๅ‹•ไฝœใ•ใ›ใ‚‹ใซใฏใ€**Python 3.7** ไปฅไธŠใ‚’ไฝฟ็”จใ™ใ‚‹ใ‹ใ€**Python 3.6** ใงใฏ"backports"ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: - -``` -pip install async-exit-stack async-generator -``` - -ใ“ใ‚Œใซใ‚ˆใ‚Šasync-exit-stackใจasync-generatorใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใพใ™ใ€‚ +`yield`ใฏๅฟ…ใšไพๅญ˜้–ขไฟ‚ใ”ใจใซ1ๅ›žใ ใ‘ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -35,21 +23,21 @@ pip install async-exit-stack async-generator /// -## `yield`ใ‚’ๆŒใคใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎไพๅญ˜้–ขไฟ‚ +## `yield`ใ‚’ๆŒใคใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎไพๅญ˜้–ขไฟ‚ { #a-database-dependency-with-yield } ไพ‹ใˆใฐใ€ใ“ใ‚Œใ‚’ไฝฟใฃใฆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝœๆˆใ—ใ€็ต‚ไบ†ๅพŒใซใใ‚Œใ‚’้–‰ใ˜ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใƒฌใ‚นใƒใƒณใ‚นใ‚’้€ไฟกใ™ใ‚‹ๅ‰ใซ`yield`ๆ–‡ใ‚’ๅซใ‚€ๅ‰ใฎใ‚ณใƒผใƒ‰ใฎใฟใŒๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +ใƒฌใ‚นใƒใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๅ‰ใซใ€`yield`ๆ–‡ใ‚ˆใ‚Šๅ‰ใฎใ‚ณใƒผใƒ‰๏ผˆใŠใ‚ˆใณ`yield`ๆ–‡ใ‚’ๅซใ‚€๏ผ‰ใŒๅฎŸ่กŒใ•ใ‚Œใพใ™: -{* ../../docs_src/dependencies/tutorial007.py hl[2,3,4] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} ็”Ÿๆˆใ•ใ‚ŒใŸๅ€คใฏใ€*path operations*ใ‚„ไป–ใฎไพๅญ˜้–ขไฟ‚ใซๆณจๅ…ฅใ•ใ‚Œใ‚‹ใ‚‚ใฎใงใ™: -{* ../../docs_src/dependencies/tutorial007.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} -`yield`ๆ–‡ใซ็ถšใใ‚ณใƒผใƒ‰ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใŒ้€ไฟกใ•ใ‚ŒใŸๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™: +`yield`ๆ–‡ใซ็ถšใใ‚ณใƒผใƒ‰ใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™: -{* ../../docs_src/dependencies/tutorial007.py hl[5,6] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -59,27 +47,27 @@ pip install async-exit-stack async-generator /// -## `yield`ใจ`try`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ +## `yield`ใจ`try`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #a-dependency-with-yield-and-try } -`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใง`try`ใƒ–ใƒญใƒƒใ‚ฏใ‚’ไฝฟ็”จใ—ใŸๅ ดๅˆใ€ใใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ—ใŸ้š›ใซ็™บ็”Ÿใ—ใŸไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใง`try`ใƒ–ใƒญใƒƒใ‚ฏใ‚’ไฝฟ็”จใ—ใŸๅ ดๅˆใ€ใใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ—ใŸ้š›ใซใ‚นใƒญใƒผใ•ใ‚ŒใŸใ‚ใ‚‰ใ‚†ใ‚‹ไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ -ไพ‹ใˆใฐใ€้€”ไธญใฎใฉใ“ใ‹ใฎๆ™‚็‚นใงใ€ๅˆฅใฎไพๅญ˜้–ขไฟ‚ใ‚„*path operation*ใฎไธญใงใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒˆใƒฉใƒณใ‚ถใ‚ฏใ‚ทใƒงใƒณใ‚’ใ€Œใƒญใƒผใƒซใƒใƒƒใ‚ฏใ€ใ—ใŸใ‚Šใ€ใใฎไป–ใฎใ‚จใƒฉใƒผใ‚’ไฝœๆˆใ—ใŸใ‚Šใ™ใ‚‹ใ‚ณใƒผใƒ‰ใŒใ‚ใฃใŸๅ ดๅˆใ€ไพๅญ˜้–ขไฟ‚ใฎไธญใงไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ไพ‹ใˆใฐใ€้€”ไธญใฎใฉใ“ใ‹ใฎๆ™‚็‚นใงใ€ๅˆฅใฎไพๅญ˜้–ขไฟ‚ใ‚„*path operation*ใฎไธญใงใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒˆใƒฉใƒณใ‚ถใ‚ฏใ‚ทใƒงใƒณใ‚’ใ€Œใƒญใƒผใƒซใƒใƒƒใ‚ฏใ€ใ—ใŸใ‚Šใ€ใใฎไป–ใฎไพ‹ๅค–ใ‚’ไฝœๆˆใ—ใŸใ‚Šใ™ใ‚‹ใ‚ณใƒผใƒ‰ใŒใ‚ใฃใŸๅ ดๅˆใ€ไพๅญ˜้–ขไฟ‚ใฎไธญใงไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ ใใฎใŸใ‚ใ€ไพๅญ˜้–ขไฟ‚ใฎไธญใซใ‚ใ‚‹็‰นๅฎšใฎไพ‹ๅค–ใ‚’`except SomeException`ใงๆŽขใ™ใ“ใจใŒใงใใพใ™ใ€‚ ๅŒๆง˜ใซใ€`finally`ใ‚’็”จใ„ใฆไพ‹ๅค–ใŒใ‚ใฃใŸใ‹ใฉใ†ใ‹ใซใ‹ใ‹ใ‚ใ‚‰ใšใ€็ต‚ไบ†ใ‚นใƒ†ใƒƒใƒ—ใ‚’็ขบๅฎŸใซๅฎŸ่กŒใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} -## `yield`ใ‚’ๆŒใคใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ +## `yield`ใ‚’ๆŒใคใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ { #sub-dependencies-with-yield } ไปปๆ„ใฎๅคงใใ•ใ‚„ๅฝขใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚„ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใฎใ€Œใƒ„ใƒชใƒผใ€ใ‚’ๆŒใคใ“ใจใŒใงใใ€ใใฎไธญใง`yield`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ **FastAPI** ใฏใ€`yield`ใ‚’ๆŒใคๅ„ไพๅญ˜้–ขไฟ‚ใฎใ€Œ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใ€ใŒๆญฃใ—ใ„้ †็•ชใงๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ -ไพ‹ใˆใฐใ€`dependency_c`ใฏ`dependency_b`ใจ`dependency_b`ใซไพๅญ˜ใ™ใ‚‹`dependency_a`ใซใ€ไพๅญ˜ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ไพ‹ใˆใฐใ€`dependency_c`ใฏ`dependency_b`ใซใ€ใใ—ใฆ`dependency_b`ใฏ`dependency_a`ใซไพๅญ˜ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/dependencies/tutorial008.py hl[4,12,20] *} +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} ใใ—ใฆใ€ใใ‚Œใ‚‰ใฏใ™ในใฆ`yield`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -87,11 +75,11 @@ pip install async-exit-stack async-generator ใใ—ใฆใ€`dependency_b`ใฏ`dependency_a`๏ผˆใ“ใ“ใงใฏ`dep_a`ใจใ„ใ†ๅๅ‰๏ผ‰ใฎๅ€คใ‚’็ต‚ไบ†ใ‚ณใƒผใƒ‰ใงๅˆฉ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -{* ../../docs_src/dependencies/tutorial008.py hl[16,17,24,25] *} +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} -ๅŒๆง˜ใซใ€`yield`ใจ`return`ใŒๆททๅœจใ—ใŸไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใคใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ๅŒๆง˜ใซใ€`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใจ`return`ใ‚’ๆŒใคไป–ใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ„ใใคใ‹ๆŒใกใ€ใใ‚Œใ‚‰ใฎไธ€้ƒจใŒไป–ใฎไธ€้ƒจใซไพๅญ˜ใ™ใ‚‹ใ‚ˆใ†ใซใ‚‚ใงใใพใ™ใ€‚ -ใพใŸใ€ๅ˜ไธ€ใฎไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใฃใฆใ„ใฆใ€`yield`ใชใฉใฎไป–ใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ„ใใคใ‹ๅฟ…่ฆใจใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใพใŸใ€ๅ˜ไธ€ใฎไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใฃใฆใ„ใฆใ€`yield`ใ‚’ๆŒใคไป–ใฎไพๅญ˜้–ขไฟ‚ใ‚’ใ„ใใคใ‹ๅฟ…่ฆใจใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ไพๅญ˜้–ขไฟ‚ใฎ็ต„ใฟๅˆใ‚ใ›ใฏ่‡ช็”ฑใงใ™ใ€‚ @@ -105,31 +93,45 @@ pip install async-exit-stack async-generator /// -## `yield`ใจ`HTTPException`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ +## `yield`ใจ`HTTPException`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield-and-httpexception } -`yield`ใจไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ™ใ‚‹`try`ใƒ–ใƒญใƒƒใ‚ฏใ‚’ๆŒใคใ“ใจใŒใงใใ‚‹ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ—ใŸใ€‚ +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ„ใ€ไฝ•ใ‚‰ใ‹ใฎใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ—ใ€ใใฎๅพŒใซ`finally`ใฎๅพŒใง็ต‚ไบ†ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ—ใ‚ˆใ†ใจใ™ใ‚‹`try`ใƒ–ใƒญใƒƒใ‚ฏใ‚’ๆŒใฆใ‚‹ใ“ใจใŒๅˆ†ใ‹ใ‚Šใพใ—ใŸใ€‚ -`yield`ใฎๅพŒใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใง`HTTPException`ใชใฉใ‚’็™บ็”Ÿใ•ใ›ใŸใใชใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—**ใใ‚Œใฏใ†ใพใใ„ใใพใ›ใ‚“** +ใพใŸใ€`except`ใ‚’ไฝฟใฃใฆ็™บ็”Ÿใ—ใŸไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใ€ใใ‚Œใซๅฏพใ—ใฆไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏ[ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ](../handling-errors.md#_4){.internal-link target=_blank}ใฎ*ๅพŒใซ*ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ไพๅญ˜้–ขไฟ‚ใซใ‚ˆใฃใฆๆŠ•ใ’ใ‚‰ใ‚ŒใŸไพ‹ๅค–ใ‚’็ต‚ไบ†ใ‚ณใƒผใƒ‰๏ผˆ`yield`ใฎๅพŒ๏ผ‰ใงใ‚ญใƒฃใƒƒใƒใ™ใ‚‹ใ‚‚ใฎใฏใชใซใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ไพ‹ใˆใฐใ€`HTTPException`ใฎใ‚ˆใ†ใซๅˆฅใฎไพ‹ๅค–ใ‚’็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใคใพใ‚Šใ€`yield`ใฎๅพŒใซ`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›ใŸๅ ดๅˆใ€`HTTTPException`ใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใฆHTTP 400ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ™ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ๏ผˆใ‚ใ‚‹ใ„ใฏไปปๆ„ใฎใ‚ซใ‚นใ‚ฟใƒ ใฎ๏ผ‰ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฏใ€ใใฎไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ™ใ‚‹ใ“ใจใŒใงใใชใใชใ‚Šใพใ™ใ€‚ +/// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ“ใ‚Œใฏใ€ไพๅญ˜้–ขไฟ‚ใซ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ใ‚‚ใฎ๏ผˆไพ‹ใˆใฐใ€DBใ‚ปใƒƒใ‚ทใƒงใƒณ๏ผ‰ใ‚’ใ€ไพ‹ใˆใฐใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใงไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ +ใ“ใ‚Œใฏใ‚„ใ‚„้ซ˜ๅบฆใชใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใงใ€ใปใจใ‚“ใฉใฎๅ ดๅˆใฏๆœฌๅฝ“ใซๅฟ…่ฆใซใฏใชใ‚Šใพใ›ใ‚“ใ€‚ไพ‹ใˆใฐใ€*path operation ้–ขๆ•ฐ*ใชใฉใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ณใƒผใƒ‰ใฎไป–ใฎๅ ดๆ‰€ใ‹ใ‚‰๏ผˆ`HTTPException`ใ‚’ๅซใ‚€๏ผ‰ไพ‹ๅค–ใ‚’็™บ็”Ÿใ•ใ›ใ‚‰ใ‚Œใ‚‹ใŸใ‚ใงใ™ใ€‚ -ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฏใƒฌใ‚นใƒใƒณใ‚นใŒ้€ไฟกใ•ใ‚ŒใŸ*ๅพŒ*ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ใใฎใŸใ‚ใ€*ใ™ใงใซ้€ไฟกใ•ใ‚Œใฆใ„ใ‚‹*ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅค‰ๆ›ดใ™ใ‚‹ๆ–นๆณ•ใ™ใ‚‰ใชใ„ใฎใงใ€`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›ใ‚‹ๆ–นๆณ•ใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใŸใ ใ—ๅฟ…่ฆใงใ‚ใ‚Œใฐไฝฟใˆใพใ™ใ€‚ ๐Ÿค“ -ใ—ใ‹ใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใŒDBใ‚จใƒฉใƒผใ‚’็™บ็”Ÿใ•ใ›ใŸๅ ดๅˆใ€ๅฐ‘ใชใใจใ‚‚`yield`ใงไพๅญ˜้–ขไฟ‚ใฎใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ใƒญใƒผใƒซใƒใƒƒใ‚ฏใ—ใŸใ‚Šใ€ใใ‚Œใ„ใซ้–‰ใ˜ใŸใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใ€ใ‚จใƒฉใƒผใ‚’ใƒญใ‚ฐใซ่จ˜้Œฒใ—ใŸใ‚Šใ€ใƒชใƒขใƒผใƒˆใฎใƒˆใƒฉใƒƒใ‚ญใƒณใ‚ฐใ‚ทใ‚นใƒ†ใƒ ใซๅ ฑๅ‘Šใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +/// -ไพ‹ๅค–ใŒ็™บ็”Ÿใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใ‚ณใƒผใƒ‰ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๆœ€ใ‚‚ๆ™ฎ้€šใฎใ€ŒPythonๆตใ€ใชใ“ใจใ‚’ใ—ใฆใ€ใ‚ณใƒผใƒ‰ใฎใใฎ้ƒจๅˆ†ใซ`try`ใƒ–ใƒญใƒƒใ‚ฏใ‚’่ฟฝๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ +{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} -ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใŸใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅค‰ๆ›ดใ—ใŸใ‚Šใ€`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›ใŸใ‚Šใ™ใ‚‹*ๅ‰ใซ*ๅ‡ฆ็†ใ—ใŸใ„ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€[ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ](../handling-errors.md#_4){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ +ไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใฆใ€ใใ‚ŒใซๅŸบใฅใ„ใฆใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚นใ‚’ไฝœๆˆใ—ใŸใ„ๅ ดๅˆใฏใ€[ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ -/// tip | ่ฑ†็Ÿฅ่ญ˜ +## `yield`ใจ`except`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield-and-except } -`HTTPException`ใ‚’ๅซใ‚€ไพ‹ๅค–ใฏใ€`yield`ใฎ*ๅ‰*ใงใ‚‚็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใŸใ ใ—ใ€ๅพŒใงใฏใงใใพใ›ใ‚“ใ€‚ +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใง`except`ใ‚’ไฝฟใฃใฆไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใ€ใใ‚Œใ‚’ๅ†ๅบฆraiseใ—ใชใ„๏ผˆใพใŸใฏๆ–ฐใ—ใ„ไพ‹ๅค–ใ‚’raiseใ—ใชใ„๏ผ‰ๅ ดๅˆใ€้€šๅธธใฎPythonใจๅŒใ˜ใ‚ˆใ†ใซใ€FastAPIใฏไพ‹ๅค–ใŒใ‚ใฃใŸใ“ใจใซๆฐ—ใฅใ‘ใพใ›ใ‚“: -/// +{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} + +ใ“ใฎๅ ดๅˆใ€๏ผˆ`HTTPException`ใ‚„ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใ‚’raiseใ—ใฆใ„ใชใ„ใŸใ‚๏ผ‰ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใฏ้ฉๅˆ‡ใซ*HTTP 500 Internal Server Error*ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ‚Šใพใ™ใŒใ€ใ‚ตใƒผใƒใƒผใซใฏ**ใƒญใ‚ฐใŒไธ€ๅˆ‡ๆฎ‹ใ‚‰ใš**ใ€ไฝ•ใŒใ‚จใƒฉใƒผใ ใฃใŸใฎใ‹ใ‚’็คบใ™ไป–ใฎๆ‰‹ใŒใ‹ใ‚Šใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ๐Ÿ˜ฑ + +### `yield`ใจ`except`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงใฏๅธธใซ`raise`ใ™ใ‚‹ { #always-raise-in-dependencies-with-yield-and-except } + +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงไพ‹ๅค–ใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใŸๅ ดๅˆใ€ๅˆฅใฎ`HTTPException`ใชใฉใ‚’raiseใ™ใ‚‹ใฎใงใชใ„้™ใ‚Šใ€**ๅ…ƒใฎไพ‹ๅค–ใ‚’ๅ†raiseใ™ในใใงใ™**ใ€‚ + +`raise`ใ‚’ไฝฟใ†ใจๅŒใ˜ไพ‹ๅค–ใ‚’ๅ†raiseใงใใพใ™: + +{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} + +ใ“ใ‚Œใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๅŒใ˜*HTTP 500 Internal Server Error*ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใŒใ€ใ‚ตใƒผใƒใƒผใฎใƒญใ‚ฐใซใฏใ‚ซใ‚นใ‚ฟใƒ ใฎ`InternalError`ใŒๆฎ‹ใ‚Šใพใ™ใ€‚ ๐Ÿ˜Ž + +## `yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎๅฎŸ่กŒ { #execution-of-dependencies-with-yield } ๅฎŸ่กŒใฎ้ †ๅบใฏๅคšใ‹ใ‚Œๅฐ‘ใชใ‹ใ‚Œไปฅไธ‹ใฎๅ›ณใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ๆ™‚้–“ใฏไธŠใ‹ใ‚‰ไธ‹ใธใจๆตใ‚Œใฆใ„ใใพใ™ใ€‚ใใ—ใฆใ€ๅ„ๅˆ—ใฏใ‚ณใƒผใƒ‰ใ‚’็›ธไบ’ไฝœ็”จใ•ใ›ใŸใ‚Šใ€ๅฎŸ่กŒใ—ใŸใ‚Šใ—ใฆใ„ใ‚‹้ƒจๅˆ†ใฎไธ€ใคใงใ™ใ€‚ @@ -142,32 +144,29 @@ participant dep as Dep with yield participant operation as Path Operation participant tasks as Background tasks - Note over client,tasks: Can raise exception for dependency, handled after response is sent - Note over client,operation: Can raise HTTPException and can change the response + Note over client,operation: Can raise exceptions, including HTTPException client ->> dep: Start request Note over dep: Run code up to yield - opt raise - dep -->> handler: Raise HTTPException + opt raise Exception + dep -->> handler: Raise Exception handler -->> client: HTTP error response - dep -->> dep: Raise other exception end dep ->> operation: Run dependency, e.g. DB session opt raise - operation -->> handler: Raise HTTPException + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end handler -->> client: HTTP error response - operation -->> dep: Raise other exception end + operation ->> client: Return response to client Note over client,operation: Response is already sent, can't change it anymore opt Tasks operation -->> tasks: Send background tasks end opt Raise other exception - tasks -->> dep: Raise other exception - end - Note over dep: After yield - opt Handle other exception - dep -->> dep: Handle exception, can't change response. E.g. close DB session. + tasks -->> tasks: Handle exceptions in the background task code end ``` @@ -181,15 +180,63 @@ participant tasks as Background tasks /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ“ใฎๅ›ณใฏ`HTTPException`ใ‚’็คบใ—ใฆใ„ใพใ™ใŒใ€[ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ](../handling-errors.md#_4){.internal-link target=_blank}ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใงใ€ไป–ใฎไพ‹ๅค–ใ‚’็™บ็”Ÿใ•ใ›ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ใใ—ใฆใ€ใใฎไพ‹ๅค–ใฏไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใงใฏใชใใ€ใใฎใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใพใ™ใ€‚ - -ใ—ใ‹ใ—ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใงๅ‡ฆ็†ใ•ใ‚Œใชใ„ไพ‹ๅค–ใ‚’็™บ็”Ÿใ•ใ›ใŸๅ ดๅˆใฏใ€ไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใงๅ‡ฆ็†ใ•ใ‚Œใพใ™ใ€‚ +*path operation ้–ขๆ•ฐ*ใฎใ‚ณใƒผใƒ‰ใงไพ‹ๅค–ใ‚’raiseใ—ใŸๅ ดๅˆใ€`HTTPException`ใ‚’ๅซใ‚ใ€ใใ‚Œใฏyieldใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใซๆธกใ•ใ‚Œใพใ™ใ€‚ใปใจใ‚“ใฉใฎๅ ดๅˆใ€ใใฎไพ‹ๅค–ใŒๆญฃใ—ใๅ‡ฆ็†ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ€`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‹ใ‚‰ๅŒใ˜ไพ‹ๅค–ใ€ใพใŸใฏๆ–ฐใ—ใ„ไพ‹ๅค–ใ‚’ๅ†raiseใ—ใŸใใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ /// -## ใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ +## ๆ—ฉๆœŸ็ต‚ไบ†ใจ`scope` { #early-exit-and-scope } + +้€šๅธธใ€`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ**ใƒฌใ‚นใƒใƒณใ‚นใŒ้€ไฟกใ•ใ‚ŒใŸๅพŒ**ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€*path operation ้–ขๆ•ฐ*ใ‹ใ‚‰returnใ—ใŸๅพŒใซไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใชใ„ใจๅˆ†ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€`Depends(scope="function")`ใ‚’ไฝฟใฃใฆใ€**ใƒฌใ‚นใƒใƒณใ‚นใŒ้€ไฟกใ•ใ‚Œใ‚‹ๅ‰**ใซใ€*path operation ้–ขๆ•ฐ*ใฎreturnๅพŒใซไพๅญ˜้–ขไฟ‚ใ‚’้–‰ใ˜ใ‚‹ในใใ ใจFastAPIใซไผใˆใ‚‰ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} + +`Depends()`ใฏใ€ไปฅไธ‹ใฎใ„ใšใ‚Œใ‹ใ‚’ๅ–ใ‚‹`scope`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™: + +* `"function"`: ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹*path operation ้–ขๆ•ฐ*ใฎๅ‰ใซไพๅญ˜้–ขไฟ‚ใ‚’้–‹ๅง‹ใ—ใ€*path operation ้–ขๆ•ฐ*ใฎ็ต‚ไบ†ๅพŒใซไพๅญ˜้–ขไฟ‚ใ‚’็ต‚ไบ†ใ—ใพใ™ใŒใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใ‚‹**ๅ‰**ใซ็ต‚ไบ†ใ—ใพใ™ใ€‚ใคใพใ‚Šใ€ไพๅญ˜้–ขไฟ‚้–ขๆ•ฐใฏ*path operation ้–ขๆ•ฐ*ใฎ**ๅ‘จๅ›ฒ**ใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +* `"request"`: ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹*path operation ้–ขๆ•ฐ*ใฎๅ‰ใซไพๅญ˜้–ขไฟ‚ใ‚’้–‹ๅง‹ใ—๏ผˆ`"function"`ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใจๅŒๆง˜๏ผ‰ใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚ŒใŸ**ๅพŒ**ใซ็ต‚ไบ†ใ—ใพใ™ใ€‚ใคใพใ‚Šใ€ไพๅญ˜้–ขไฟ‚้–ขๆ•ฐใฏ**ใƒชใ‚ฏใ‚จใ‚นใƒˆ**ใจใƒฌใ‚นใƒใƒณใ‚นใฎใ‚ตใ‚คใ‚ฏใƒซใฎ**ๅ‘จๅ›ฒ**ใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ๆŒ‡ๅฎšใ•ใ‚ŒใฆใŠใ‚‰ใšใ€ไพๅญ˜้–ขไฟ‚ใซ`yield`ใŒใ‚ใ‚‹ๅ ดๅˆใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง`scope`ใฏ`"request"`ใซใชใ‚Šใพใ™ใ€‚ + +### ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใฎ`scope` { #scope-for-sub-dependencies } + +`scope="request"`๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ๏ผ‰ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๅ ดๅˆใ€ใฉใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚‚`"request"`ใฎ`scope`ใ‚’ๆŒใคๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€`"function"`ใฎ`scope`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฏใ€`"function"`ใจ`"request"`ใฎ`scope`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใฆใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใ„ใšใ‚Œใฎไพๅญ˜้–ขไฟ‚ใ‚‚ใ€ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚ˆใ‚Šๅ‰ใซ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใงใใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใงใ™๏ผˆ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฎๅฎŸ่กŒไธญใซใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ใพใ ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใŸใ‚ใงใ™๏ผ‰ใ€‚ + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` + +## `yield`ใ€`HTTPException`ใ€`except`ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฏใ€ใ•ใพใ–ใพใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’ใ‚ซใƒใƒผใ—ใ€ใ„ใใคใ‹ใฎๅ•้กŒใ‚’ไฟฎๆญฃใ™ใ‚‹ใŸใ‚ใซใ€ๆ™‚้–“ใจใจใ‚‚ใซ้€ฒๅŒ–ใ—ใฆใใพใ—ใŸใ€‚ + +FastAPIใฎ็•ฐใชใ‚‹ใƒใƒผใ‚ธใƒงใƒณใงไฝ•ใŒๅค‰ใ‚ใฃใŸใฎใ‹ใ‚’็Ÿฅใ‚ŠใŸใ„ๅ ดๅˆใฏใ€ไธŠ็ดšใ‚ฌใ‚คใƒ‰ใฎ[ไธŠ็ดšใฎไพๅญ˜้–ขไฟ‚ - `yield`ใ€`HTTPException`ใ€`except`ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}ใง่ฉณใ—ใ่ชญใ‚ใพใ™ใ€‚ +## ใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ { #context-managers } -### ใ€Œใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใจใฏ +### ใ€Œใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใจใฏ { #what-are-context-managers } ใ€Œใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใจใฏใ€`with`ๆ–‡ใฎไธญใงไฝฟ็”จใงใใ‚‹Pythonใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใ“ใจใงใ™ใ€‚ @@ -205,9 +252,9 @@ with open("./somefile.txt") as f: `with`ใƒ–ใƒญใƒƒใ‚ฏใŒ็ต‚ไบ†ใ™ใ‚‹ใจใ€ไพ‹ๅค–ใŒใ‚ใฃใŸใจใ—ใฆใ‚‚ใƒ•ใ‚กใ‚คใƒซใ‚’็ขบใ‹ใซ้–‰ใ˜ใพใ™ใ€‚ -`yield`ใ‚’ไพๅญ˜้–ขไฟ‚ใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€**FastAPI** ใฏๅ†…้ƒจ็š„ใซใใ‚Œใ‚’ใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใซๅค‰ๆ›ใ—ใ€ไป–ใฎ้–ข้€ฃใƒ„ใƒผใƒซใจ็ต„ใฟๅˆใ‚ใ›ใพใ™ใ€‚ +`yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€**FastAPI** ใฏๅ†…้ƒจ็š„ใซใใ‚Œใ‚’ใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใซๅค‰ๆ›ใ—ใ€ไป–ใฎ้–ข้€ฃใƒ„ใƒผใƒซใจ็ต„ใฟๅˆใ‚ใ›ใพใ™ใ€‚ -### `yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใฎไฝฟ็”จ +### `yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใฎไฝฟ็”จ { #using-context-managers-in-dependencies-with-yield } /// warning | ๆณจๆ„ @@ -221,7 +268,7 @@ Pythonใงใฏใ€ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ +**FastAPI** ใฏ้žๅธธใซๅผทๅŠ›ใงใ‚ใ‚ŠใชใŒใ‚‰็›ดๆ„Ÿ็š„ใช **Dependency Injection** ใ‚ทใ‚นใƒ†ใƒ ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ ใใ‚Œใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใซไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€้–‹็™บ่€…ใŒไป–ใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ **FastAPI** ใจ็ตฑๅˆใ™ใ‚‹ใฎใŒ้žๅธธใซ็ฐกๅ˜ใซใชใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -## ใ€Œไพๅญ˜ๆ€งๆณจๅ…ฅใ€ใจใฏ +## ใ€ŒDependency Injectionใ€ใจใฏ { #what-is-dependency-injection } -**ใ€Œไพๅญ˜ๆ€งๆณจๅ…ฅใ€** ใจใฏใ€ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐใซใŠใ„ใฆใ€ใ‚ณใƒผใƒ‰๏ผˆใ“ใฎๅ ดๅˆใฏใ€*path operation้–ขๆ•ฐ*๏ผ‰ใŒๅ‹•ไฝœใ—ใŸใ‚Šไฝฟ็”จใ—ใŸใ‚Šใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชใ‚‚ใฎ๏ผˆใ€Œไพๅญ˜้–ขไฟ‚ใ€๏ผ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: +**ใ€ŒDependency Injectionใ€** ใจใฏใ€ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐใซใŠใ„ใฆใ€ใ‚ณใƒผใƒ‰๏ผˆใ“ใฎๅ ดๅˆใฏใ€*path operation ้–ขๆ•ฐ*๏ผ‰ใŒๅ‹•ไฝœใ—ใŸใ‚Šไฝฟ็”จใ—ใŸใ‚Šใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชใ‚‚ใฎ๏ผˆใ€Œไพๅญ˜้–ขไฟ‚ใ€๏ผ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: ใใ—ใฆใ€ใใฎใ‚ทใ‚นใƒ†ใƒ ๏ผˆใ“ใฎๅ ดๅˆใฏใ€**FastAPI**๏ผ‰ใฏใ€ๅฟ…่ฆใชไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ณใƒผใƒ‰ใซๆไพ›ใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชใ“ใจใฏไฝ•ใงใ‚‚่กŒใ„ใพใ™๏ผˆไพๅญ˜้–ขไฟ‚ใ‚’ใ€Œๆณจๅ…ฅใ€ใ—ใพใ™๏ผ‰ใ€‚ @@ -19,27 +19,27 @@ ใ“ใ‚Œใ‚‰ใ™ในใฆใ‚’ใ€ใ‚ณใƒผใƒ‰ใฎ็นฐใ‚Š่ฟ”ใ—ใ‚’ๆœ€ๅฐ้™ใซๆŠ‘ใˆใชใŒใ‚‰่กŒใ„ใพใ™ใ€‚ -## ๆœ€ๅˆใฎใ‚นใƒ†ใƒƒใƒ— +## ๆœ€ๅˆใฎใ‚นใƒ†ใƒƒใƒ— { #first-steps } ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใชไพ‹ใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ใ‚ใพใ‚Šใซใ‚‚ใ‚ทใƒณใƒ—ใƒซใชใฎใงใ€ไปŠใฎใจใ“ใ‚ใฏใ‚ใพใ‚Šๅ‚่€ƒใซใชใ‚‰ใชใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใ—ใ‹ใ—ใ€ใ“ใฎๆ–นๆณ•ใงใฏ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใŒใฉใฎใ‚ˆใ†ใซๆฉŸ่ƒฝใ™ใ‚‹ใ‹ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใ“ใฎๆ–นๆณ•ใงใฏ **Dependency Injection** ใ‚ทใ‚นใƒ†ใƒ ใŒใฉใฎใ‚ˆใ†ใซๆฉŸ่ƒฝใ™ใ‚‹ใ‹ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -### ไพๅญ˜้–ขไฟ‚ใฎไฝœๆˆ +### ไพๅญ˜้–ขไฟ‚๏ผˆใ€Œdependableใ€๏ผ‰ใฎไฝœๆˆ { #create-a-dependency-or-dependable } ใพใšใฏไพๅญ˜้–ขไฟ‚ใซๆณจ็›ฎใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -ไปฅไธ‹ใฎใ‚ˆใ†ใซใ€*path operation้–ขๆ•ฐ*ใจๅŒใ˜ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…จใฆๅ–ใ‚‹ใ“ใจใŒใงใใ‚‹้–ขๆ•ฐใซใ™ใŽใพใ›ใ‚“: +ไปฅไธ‹ใฎใ‚ˆใ†ใซใ€*path operation ้–ขๆ•ฐ*ใจๅŒใ˜ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…จใฆๅ–ใ‚‹ใ“ใจใŒใงใใ‚‹้–ขๆ•ฐใซใ™ใŽใพใ›ใ‚“: -{* ../../docs_src/dependencies/tutorial001.py hl[8,9] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} ใ“ใ‚Œใ ใ‘ใงใ™ใ€‚ **๏ผ’่กŒ**ใ€‚ -ใใ—ใฆใ€ใใ‚Œใฏใ™ในใฆใฎ*path operation้–ขๆ•ฐ*ใŒๆŒใฃใฆใ„ใ‚‹ใฎใจๅŒใ˜ๅฝขใจๆง‹้€ ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ +ใใ—ใฆใ€ใใ‚Œใฏใ™ในใฆใฎ*path operation ้–ขๆ•ฐ*ใŒๆŒใฃใฆใ„ใ‚‹ใฎใจๅŒใ˜ๅฝขใจๆง‹้€ ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ -ใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใ‚’ๅซใพใชใ„๏ผˆ`@app.get("/some-path")`ใ‚’ๅซใพใชใ„๏ผ‰*path operation้–ขๆ•ฐ*ใจ่€ƒใˆใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใ‚’ๅซใพใชใ„๏ผˆ`@app.get("/some-path")`ใ‚’ๅซใพใชใ„๏ผ‰*path operation ้–ขๆ•ฐ*ใจ่€ƒใˆใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ใใ—ใฆไฝ•ใงใ‚‚่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚ @@ -51,15 +51,25 @@ ใใ—ใฆใ€ใ“ใ‚Œใ‚‰ใฎๅ€คใ‚’ๅซใ‚€`dict`ใ‚’่ฟ”ใ—ใพใ™ใ€‚ -### `Depends`ใฎใ‚คใƒณใƒใƒผใƒˆ +/// info | ๆƒ…ๅ ฑ -{* ../../docs_src/dependencies/tutorial001.py hl[3] *} +FastAPI ใฏใƒใƒผใ‚ธใƒงใƒณ 0.95.0 ใง `Annotated` ใฎใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ ใ—๏ผˆใใ—ใฆๆŽจๅฅจใ—ๅง‹ใ‚ใพใ—ใŸ๏ผ‰ใ€‚ -### "dependant"ใงใฎไพๅญ˜้–ขไฟ‚ใฎๅฎฃ่จ€ +ๅคใ„ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€`Annotated` ใ‚’ไฝฟใŠใ†ใจใ™ใ‚‹ใจใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ -*path operation้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`Body`ใ‚„`Query`ใชใฉใ‚’ไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ๆ–ฐใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`Depends`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +`Annotated` ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ‰ใซใ€ๅฐ‘ใชใใจใ‚‚ 0.95.1 ใพใง [FastAPI ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ใ—ใฆใใ ใ•ใ„ใ€‚ -{* ../../docs_src/dependencies/tutorial001.py hl[13,18] *} +/// + +### `Depends`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### ใ€Œdependantใ€ใงใฎไพๅญ˜้–ขไฟ‚ใฎๅฎฃ่จ€ { #declare-the-dependency-in-the-dependant } + +*path operation ้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`Body`ใ‚„`Query`ใชใฉใ‚’ไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ๆ–ฐใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`Depends`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} ้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`Depends`ใ‚’ไฝฟ็”จใ™ใ‚‹ใฎใฏ`Body`ใ‚„`Query`ใชใฉใจๅŒใ˜ใงใ™ใŒใ€`Depends`ใฎๅ‹•ไฝœใฏๅฐ‘ใ—็•ฐใชใ‚Šใพใ™ใ€‚ @@ -67,7 +77,9 @@ ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ้–ขๆ•ฐใฎใ‚ˆใ†ใชใ‚‚ใฎใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใ—ใฆใ€ใใฎ้–ขๆ•ฐใฏใ€*path operation้–ขๆ•ฐ*ใŒ่กŒใ†ใฎใจๅŒใ˜ๆ–นๆณ•ใงใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚Šใพใ™ใ€‚ +็›ดๆŽฅ**ๅ‘ผใณๅ‡บใ—ใพใ›ใ‚“**๏ผˆๆœซๅฐพใซๆ‹ฌๅผงใ‚’ไป˜ใ‘ใพใ›ใ‚“๏ผ‰ใ€‚`Depends()` ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๆธกใ™ใ ใ‘ใงใ™ใ€‚ + +ใใ—ใฆใ€ใใฎ้–ขๆ•ฐใฏใ€*path operation ้–ขๆ•ฐ*ใŒ่กŒใ†ใฎใจๅŒใ˜ๆ–นๆณ•ใงใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚Šใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -79,7 +91,7 @@ * ไพๅญ˜้–ขไฟ‚๏ผˆ"dependable"๏ผ‰้–ขๆ•ฐใ‚’ๆญฃใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ * ้–ขๆ•ฐใฎ็ตๆžœใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ -* *path operation้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใใฎ็ตๆžœใ‚’ไปฃๅ…ฅใ—ใฆใใ ใ•ใ„ใ€‚ +* *path operation ้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใใฎ็ตๆžœใ‚’ไปฃๅ…ฅใ—ใฆใใ ใ•ใ„ใ€‚ ```mermaid graph TB @@ -92,7 +104,7 @@ common_parameters --> read_items common_parameters --> read_users ``` -ใ“ใฎๆ–นๆณ•ใงใฏใ€ๅ…ฑๆœ‰ใ•ใ‚Œใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ไธ€ๅบฆๆ›ธใใ€**FastAPI** ใŒ*path operations*ใฎใŸใ‚ใฎๅ‘ผใณๅ‡บใ—ใ‚’่กŒใ„ใพใ™ใ€‚ +ใ“ใฎๆ–นๆณ•ใงใฏใ€ๅ…ฑๆœ‰ใ•ใ‚Œใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ไธ€ๅบฆๆ›ธใใ€**FastAPI** ใŒ*path operation*ใฎใŸใ‚ใฎๅ‘ผใณๅ‡บใ—ใ‚’่กŒใ„ใพใ™ใ€‚ /// check | ็ขบ่ช @@ -102,59 +114,85 @@ common_parameters --> read_users /// -## `async`ใซใ™ใ‚‹ใ‹ใฉใ†ใ‹ +## `Annotated` ไพๅญ˜้–ขไฟ‚ใฎๅ…ฑๆœ‰ { #share-annotated-dependencies } + +ไธŠใฎไพ‹ใงใฏใ€ใปใ‚“ใฎๅฐ‘ใ— **ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡** ใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚ + +`common_parameters()` ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ใจใใฏใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจ `Depends()` ใ‚’ๅซใ‚€ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅ…จไฝ“ใ‚’ๆ›ธใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +ใ—ใ‹ใ—ใ€`Annotated` ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใฎใงใ€ใใฎ `Annotated` ๅ€คใ‚’ๅค‰ๆ•ฐใซๆ ผ็ดใ—ใฆ่ค‡ๆ•ฐ็ฎ‡ๆ‰€ใงไฝฟใˆใพใ™: + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚ŒใฏใŸใ ใฎๆจ™ๆบ– Python ใงใ€ใ€Œtype aliasใ€ใจๅ‘ผใฐใ‚Œใ€**FastAPI** ๅ›บๆœ‰ใฎใ‚‚ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ—ใ‹ใ— **FastAPI** ใฏ `Annotated` ใ‚’ๅซใ‚€ Python ๆจ™ๆบ–ใซๅŸบใฅใ„ใฆใ„ใ‚‹ใŸใ‚ใ€ใ“ใฎใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใ‚’ใ‚ณใƒผใƒ‰ใงไฝฟใˆใพใ™ใ€‚ ๐Ÿ˜Ž + +/// + +ไพๅญ˜้–ขไฟ‚ใฏๆœŸๅพ…ใฉใŠใ‚Šใซๅ‹•ไฝœใ—็ถšใ‘ใ€**ไธ€็•ช่‰ฏใ„็‚น** ใฏ **ๅž‹ๆƒ…ๅ ฑใŒไฟๆŒใ•ใ‚Œใ‚‹** ใ“ใจใงใ™ใ€‚ใคใพใ‚Šใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏ **่‡ชๅ‹•่ฃœๅฎŒ**ใ€**ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผ** ใชใฉใ‚’ๆไพ›ใ—็ถšใ‘ใ‚‰ใ‚Œใพใ™ใ€‚`mypy` ใฎใ‚ˆใ†ใชไป–ใฎใƒ„ใƒผใƒซใงใ‚‚ๅŒๆง˜ใงใ™ใ€‚ + +ใ“ใ‚Œใฏ **ๅคง่ฆๆจกใชใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚น** ใงใ€**ๅŒใ˜ไพๅญ˜้–ขไฟ‚** ใ‚’ **ๅคšใใฎ *path operation*** ใงไฝ•ๅบฆใ‚‚ไฝฟใ†ๅ ดๅˆใซ็‰นใซๅฝน็ซ‹ใกใพใ™ใ€‚ + +## `async`ใซใ™ใ‚‹ใ‹ใฉใ†ใ‹ { #to-async-or-not-to-async } -ไพๅญ˜้–ขไฟ‚ใฏ **FastAPI**๏ผˆ*path operation้–ขๆ•ฐ*ใจๅŒใ˜๏ผ‰ใ‹ใ‚‰ใ‚‚ๅ‘ผใณๅ‡บใ•ใ‚Œใ‚‹ใŸใ‚ใ€้–ขๆ•ฐใ‚’ๅฎš็พฉใ™ใ‚‹้š›ใซใ‚‚ๅŒใ˜ใƒซใƒผใƒซใŒ้ฉ็”จใ•ใ‚Œใพใ™ใ€‚ +ไพๅญ˜้–ขไฟ‚ใฏ **FastAPI**๏ผˆ*path operation ้–ขๆ•ฐ*ใจๅŒใ˜๏ผ‰ใ‹ใ‚‰ใ‚‚ๅ‘ผใณๅ‡บใ•ใ‚Œใ‚‹ใŸใ‚ใ€้–ขๆ•ฐใ‚’ๅฎš็พฉใ™ใ‚‹้š›ใซใ‚‚ๅŒใ˜ใƒซใƒผใƒซใŒ้ฉ็”จใ•ใ‚Œใพใ™ใ€‚ `async def`ใ‚„้€šๅธธใฎ`def`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใพใŸใ€้€šๅธธใฎ`def`*path operation้–ขๆ•ฐ*ใฎไธญใซ`async def`ใ‚’ๅ…ฅใ‚Œใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใŸใ‚Šใ€`async def`*path operation้–ขๆ•ฐ*ใฎไธญใซ`def`ใ‚’ๅ…ฅใ‚Œใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใชใฉใŒใงใใพใ™ใ€‚ +ใพใŸใ€้€šๅธธใฎ`def`*path operation ้–ขๆ•ฐ*ใฎไธญใซ`async def`ใ‚’ๅ…ฅใ‚Œใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใŸใ‚Šใ€`async def`*path operation ้–ขๆ•ฐ*ใฎไธญใซ`def`ใ‚’ๅ…ฅใ‚Œใฆไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใชใฉใŒใงใใพใ™ใ€‚ ใใ‚Œใฏ้‡่ฆใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚**FastAPI** ใฏไฝ•ใ‚’ใ™ในใใ‹ใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ /// note | ๅ‚™่€ƒ -ใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ[Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank}ใฎไธญใฎ`async`ใจ`await`ใซใคใ„ใฆใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +ใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ[Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank}ใฎไธญใฎ`async`ใจ`await`ใซใคใ„ใฆใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ /// -## OpenAPIใจใฎ็ตฑๅˆ +## OpenAPIใจใฎ็ตฑๅˆ { #integrated-with-openapi } ไพๅญ˜้–ขไฟ‚๏ผˆใŠใ‚ˆใณใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚๏ผ‰ใฎใ™ในใฆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆๅฎฃ่จ€ใ€ๆคœ่จผใ€ใŠใ‚ˆใณ่ฆไปถใฏใ€ๅŒใ˜OpenAPIใ‚นใ‚ญใƒผใƒžใซ็ตฑๅˆใ•ใ‚Œใพใ™ใ€‚ ใคใพใ‚Šใ€ๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใ‹ใ‚‰ๅพ—ใ‚‰ใ‚Œใ‚‹ๅ…จใฆใฎๆƒ…ๅ ฑใ‚‚ๅซใพใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™: - + -## ็ฐกๅ˜ใชไฝฟใ„ๆ–น +## ็ฐกๅ˜ใชไฝฟใ„ๆ–น { #simple-usage } -่ฆ‹ใฆใฟใ‚‹ใจใ€*path*ใจ*operation*ใŒไธ€่‡ดใ—ใŸๆ™‚ใซ*path operation้–ขๆ•ฐ*ใŒๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใฆใ€**FastAPI** ใŒๆญฃใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใง้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ—ใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๆŠฝๅ‡บใ™ใ‚‹ๅ‡ฆ็†ใ‚’ใ—ใฆใ„ใพใ™ใ€‚ +่ฆ‹ใฆใฟใ‚‹ใจใ€*path*ใจ*operation*ใŒไธ€่‡ดใ—ใŸๆ™‚ใซ*path operation ้–ขๆ•ฐ*ใŒๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใฆใ€**FastAPI** ใŒๆญฃใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใง้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ—ใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๆŠฝๅ‡บใ™ใ‚‹ๅ‡ฆ็†ใ‚’ใ—ใฆใ„ใพใ™ใ€‚ ๅฎŸใฏใ€ใ™ในใฆใฎ๏ผˆใ‚ใ‚‹ใ„ใฏใปใจใ‚“ใฉใฎ๏ผ‰Webใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฏใ€ใ“ใฎใ‚ˆใ†ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ ใ“ใ‚Œใ‚‰ใฎ้–ขๆ•ฐใ‚’็›ดๆŽฅๅ‘ผใณๅ‡บใ™ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใ‚Œใ‚‰ใฎ้–ขๆ•ฐใฏใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ๏ผˆใ“ใฎๅ ดๅˆใฏใ€**FastAPI**๏ผ‰ใซใ‚ˆใฃใฆๅ‘ผใณๅ‡บใ•ใ‚Œใพใ™ใ€‚ -ไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใงใฏใ€**FastAPI** ใซ*path operation*ใ‚‚ใพใŸใ€*path operation้–ขๆ•ฐ*ใฎๅ‰ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ในใไป–ใฎไฝ•ใ‹ใซใ€Œไพๅญ˜ใ€ใ—ใฆใ„ใ‚‹ใ“ใจใ‚’ไผใˆใ‚‹ใ“ใจใŒใงใใ€**FastAPI** ใŒใใ‚Œใ‚’ๅฎŸ่กŒใ—ใ€็ตๆžœใ‚’ใ€Œๆณจๅ…ฅใ€ใ™ใ‚‹ใ“ใจใ‚’ๅผ•ใๅ—ใ‘ใพใ™ใ€‚ +Dependency Injection ใ‚ทใ‚นใƒ†ใƒ ใงใฏใ€**FastAPI** ใซ*path operation ้–ขๆ•ฐ*ใ‚‚ใพใŸใ€*path operation ้–ขๆ•ฐ*ใฎๅ‰ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ในใไป–ใฎไฝ•ใ‹ใซใ€Œไพๅญ˜ใ€ใ—ใฆใ„ใ‚‹ใ“ใจใ‚’ไผใˆใ‚‹ใ“ใจใŒใงใใ€**FastAPI** ใŒใใ‚Œใ‚’ๅฎŸ่กŒใ—ใ€็ตๆžœใ‚’ใ€Œๆณจๅ…ฅใ€ใ™ใ‚‹ใ“ใจใ‚’ๅผ•ใๅ—ใ‘ใพใ™ใ€‚ -ไป–ใซใ‚‚ใ€ใ€Œไพๅญ˜ๆ€งๆณจๅ…ฅใ€ใจๅŒใ˜ใ‚ˆใ†ใช่€ƒใˆใฎไธ€่ˆฌ็š„ใช็”จ่ชžใŒใ‚ใ‚Šใพใ™: +ไป–ใซใ‚‚ใ€ใ€Œdependency injectionใ€ใจๅŒใ˜ใ‚ˆใ†ใช่€ƒใˆใฎไธ€่ˆฌ็š„ใช็”จ่ชžใŒใ‚ใ‚Šใพใ™: -* ใƒชใ‚ฝใƒผใ‚น -* ใƒ—ใƒญใƒใ‚คใƒ€ -* ใ‚ตใƒผใƒ“ใ‚น -* ใ‚คใƒณใ‚ธใ‚งใ‚ฏใ‚ฟใƒ–ใƒซ -* ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ +* resources +* providers +* services +* injectables +* components -## **FastAPI** ใƒ—ใƒฉใ‚ฐใ‚คใƒณ +## **FastAPI** ใƒ—ใƒฉใ‚ฐใ‚คใƒณ { #fastapi-plug-ins } -็ตฑๅˆใ‚„ใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใฏ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆๆง‹็ฏ‰ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅฎŸ้š›ใซใฏใ€**ใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€็„ก้™ใฎๆ•ฐใฎ็ตฑๅˆใ‚„ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใ€ใใ‚ŒใŒ**path operation้–ขๆ•ฐ*ใงๅˆฉ็”จๅฏ่ƒฝใซใชใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ +็ตฑๅˆใ‚„ใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใฏ **Dependency Injection** ใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆๆง‹็ฏ‰ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅฎŸ้š›ใซใฏใ€**ใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€็„ก้™ใฎๆ•ฐใฎ็ตฑๅˆใ‚„ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใ€ใใ‚ŒใŒ*path operation ้–ขๆ•ฐ*ใงๅˆฉ็”จๅฏ่ƒฝใซใชใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ ไพๅญ˜้–ขไฟ‚ใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใง็›ดๆ„Ÿ็š„ใชๆ–นๆณ•ใงไฝœๆˆใ™ใ‚‹ใ“ใจใŒใงใใ€ๅฟ…่ฆใชPythonใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ ใ‘ใงใ€*ๆ–‡ๅญ—้€šใ‚Š*ๆ•ฐ่กŒใฎใ‚ณใƒผใƒ‰ใงAPI้–ขๆ•ฐใจ็ตฑๅˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ๆฌกใฎ็ซ ใงใฏใ€ใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚„NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใชใฉใซใคใ„ใฆใ€ใใฎไพ‹ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ -## **FastAPI** ไบ’ๆ›ๆ€ง +## **FastAPI** ไบ’ๆ›ๆ€ง { #fastapi-compatibility } -ไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใŒใ‚ทใƒณใƒ—ใƒซใชใฎใงใ€**FastAPI** ใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚‚ใฎใจไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™: +dependency injection ใ‚ทใ‚นใƒ†ใƒ ใŒใ‚ทใƒณใƒ—ใƒซใชใฎใงใ€**FastAPI** ใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚‚ใฎใจไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™: * ใ™ในใฆใฎใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น * NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น @@ -165,15 +203,15 @@ common_parameters --> read_users * ใƒฌใ‚นใƒใƒณใ‚นใƒ‡ใƒผใ‚ฟๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ  * ใชใฉใ€‚ -## ใ‚ทใƒณใƒ—ใƒซใงใƒ‘ใƒฏใƒ•ใƒซ +## ใ‚ทใƒณใƒ—ใƒซใงใƒ‘ใƒฏใƒ•ใƒซ { #simple-and-powerful } -้šŽๅฑคไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใฏใ€ๅฎš็พฉใ‚„ไฝฟ็”จๆ–นๆณ•ใŒ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใงใ‚ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€้žๅธธใซๅผทๅŠ›ใชใ‚‚ใฎใจใชใฃใฆใ„ใพใ™ใ€‚ +้šŽๅฑค็š„ใช dependency injection ใ‚ทใ‚นใƒ†ใƒ ใฏใ€ๅฎš็พฉใ‚„ไฝฟ็”จๆ–นๆณ•ใŒ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใงใ‚ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€้žๅธธใซๅผทๅŠ›ใชใ‚‚ใฎใจใชใฃใฆใ„ใพใ™ใ€‚ -ไพๅญ˜้–ขไฟ‚ไบ‹ๆ…‹ใ‚’ๅฎš็พฉใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ไพๅญ˜้–ขไฟ‚ใŒใ€ใ•ใ‚‰ใซไพๅญ˜้–ขไฟ‚ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ๆœ€็ต‚็š„ใซใฏใ€ไพๅญ˜้–ขไฟ‚ใฎ้šŽๅฑคใƒ„ใƒชใƒผใŒๆง‹็ฏ‰ใ•ใ‚Œใ€**ไพๅญ˜ๆ€งๆณจๅ…ฅ**ใ‚ทใ‚นใƒ†ใƒ ใŒใ€ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚๏ผˆใŠใ‚ˆใณใใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚๏ผ‰ใ‚’ใ™ในใฆ่งฃๆฑบใ—ใ€ๅ„ใ‚นใƒ†ใƒƒใƒ—ใง็ตๆžœใ‚’ๆไพ›๏ผˆๆณจๅ…ฅ๏ผ‰ใ—ใพใ™ใ€‚ +ๆœ€็ต‚็š„ใซใฏใ€ไพๅญ˜้–ขไฟ‚ใฎ้šŽๅฑคใƒ„ใƒชใƒผใŒๆง‹็ฏ‰ใ•ใ‚Œใ€**Dependency Injection**ใ‚ทใ‚นใƒ†ใƒ ใŒใ€ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚๏ผˆใŠใ‚ˆใณใใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚๏ผ‰ใ‚’ใ™ในใฆ่งฃๆฑบใ—ใ€ๅ„ใ‚นใƒ†ใƒƒใƒ—ใง็ตๆžœใ‚’ๆไพ›๏ผˆๆณจๅ…ฅ๏ผ‰ใ—ใพใ™ใ€‚ -ไพ‹ใˆใฐใ€๏ผ”ใคใฎAPIใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ๏ผˆ*path operations*๏ผ‰ใŒใ‚ใ‚‹ใจใ—ใพใ™: +ไพ‹ใˆใฐใ€๏ผ”ใคใฎAPIใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ๏ผˆ*path operation*๏ผ‰ใŒใ‚ใ‚‹ใจใ—ใพใ™: * `/items/public/` * `/items/private/` @@ -205,8 +243,8 @@ admin_user --> activate_user paying_user --> pro_items ``` -## **OpenAPI** ใจใฎ็ตฑๅˆ +## **OpenAPI** ใจใฎ็ตฑๅˆ { #integrated-with-openapi_1 } -ใ“ใ‚Œใ‚‰ๅ…จใฆใฎไพๅญ˜้–ขไฟ‚ใฏใ€่ฆไปถใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจๅŒๆ™‚ใซใ€*path operations*ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ๅ…จใฆใฎไพๅญ˜้–ขไฟ‚ใฏใ€่ฆไปถใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจๅŒๆ™‚ใซใ€*path operation*ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ **FastAPI** ใฏใใ‚Œใ‚’ใ™ในใฆOpenAPIใ‚นใ‚ญใƒผใƒžใซ่ฟฝๅŠ ใ—ใฆใ€ๅฏพ่ฉฑๅž‹ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใซ่กจ็คบใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/dependencies/sub-dependencies.md b/docs/ja/docs/tutorial/dependencies/sub-dependencies.md index 211a86a0ab..007c320f33 100644 --- a/docs/ja/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/ja/docs/tutorial/dependencies/sub-dependencies.md @@ -1,4 +1,4 @@ -# ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ +# ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ { #sub-dependencies } **ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚** ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -6,21 +6,21 @@ **FastAPI** ใฏใใ‚Œใ‚‰ใ‚’่งฃๆฑบใ—ใฆใใ‚Œใพใ™ใ€‚ -### ๆœ€ๅˆใฎไพๅญ˜้–ขไฟ‚ใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€ +## ๆœ€ๅˆใฎไพๅญ˜้–ขไฟ‚ใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€ { #first-dependency-dependable } ไปฅไธ‹ใฎใ‚ˆใ†ใชๆœ€ๅˆใฎไพๅญ˜้–ขไฟ‚๏ผˆใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€๏ผ‰ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/dependencies/tutorial005.py hl[8,9] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} ใ“ใ‚Œใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใ‚’`str`ใจใ—ใฆๅฎฃ่จ€ใ—ใ€ใใ‚Œใ‚’่ฟ”ใ™ใ ใ‘ใงใ™ใ€‚ ใ“ใ‚Œใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใงใ™๏ผˆใ‚ใพใ‚Šไพฟๅˆฉใงใฏใ‚ใ‚Šใพใ›ใ‚“๏ผ‰ใŒใ€ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใŒใฉใฎใ‚ˆใ†ใซๆฉŸ่ƒฝใ™ใ‚‹ใ‹ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ -### ็ฌฌไบŒใฎไพๅญ˜้–ขไฟ‚ ใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€ใจใ€Œไพๅญ˜ใ€ +## ็ฌฌไบŒใฎไพๅญ˜้–ขไฟ‚ ใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€ใจใ€Œไพๅญ˜ใ€ { #second-dependency-dependable-and-dependant } ใใ—ใฆใ€ๅˆฅใฎไพๅญ˜้–ขๆ•ฐ๏ผˆใ€Œไพๅญ˜ๅฏ่ƒฝใชใ‚‚ใฎใ€๏ผ‰ใ‚’ไฝœๆˆใ—ใฆใ€ๅŒๆ™‚ใซใใ‚Œ่‡ช่บซใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆใคใพใ‚Šใใ‚Œ่‡ช่บซใ‚‚ใ€Œไพๅญ˜ใ€ใงใ™๏ผ‰: -{* ../../docs_src/dependencies/tutorial005.py hl[13] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} ๅฎฃ่จ€ใ•ใ‚ŒใŸใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆณจ็›ฎใ—ใฆใฟใพใ—ใ‚‡ใ†: @@ -29,15 +29,15 @@ * ใพใŸใ€ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใฎ`last_query`ใ‚ฏใƒƒใ‚ญใƒผใ‚’`str`ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ™ใ€‚ * ใƒฆใƒผใ‚ถใƒผใŒใ‚ฏใ‚จใƒช`q`ใ‚’ๆไพ›ใ—ใชใ‹ใฃใŸๅ ดๅˆใ€ใ‚ฏใƒƒใ‚ญใƒผใซไฟๅญ˜ใ—ใฆใ„ใŸๆœ€ๅพŒใซไฝฟ็”จใ—ใŸใ‚ฏใ‚จใƒชใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -### ไพๅญ˜้–ขไฟ‚ใฎไฝฟ็”จ +## ไพๅญ˜้–ขไฟ‚ใฎไฝฟ็”จ { #use-the-dependency } ไปฅไธ‹ใฎใ‚ˆใ†ใซไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/dependencies/tutorial005.py hl[21] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} /// info | ๆƒ…ๅ ฑ -*path operation้–ขๆ•ฐ*ใฎไธญใงๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ไพๅญ˜้–ขไฟ‚ใฏ`query_or_cookie_extractor`ใฎ๏ผ‘ใคใ ใ‘ใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +*path operation ้–ขๆ•ฐ*ใฎไธญใงๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ไพๅญ˜้–ขไฟ‚ใฏ`query_or_cookie_extractor`ใฎ1ใคใ ใ‘ใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ ใ—ใ‹ใ—ใ€**FastAPI** ใฏ`query_extractor`ใ‚’ๆœ€ๅˆใซ่งฃๆฑบใ—ใ€ใใฎ็ตๆžœใ‚’`query_or_cookie_extractor`ใ‚’ๅ‘ผใณๅ‡บใ™ๆ™‚ใซๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ @@ -54,24 +54,43 @@ read_query["/items/"] query_extractor --> query_or_cookie_extractor --> read_query ``` -## ๅŒใ˜ไพๅญ˜้–ขไฟ‚ใฎ่ค‡ๆ•ฐๅ›žใฎไฝฟ็”จ +## ๅŒใ˜ไพๅญ˜้–ขไฟ‚ใฎ่ค‡ๆ•ฐๅ›žใฎไฝฟ็”จ { #using-the-same-dependency-multiple-times } -ไพๅญ˜้–ขไฟ‚ใฎ๏ผ‘ใคใŒๅŒใ˜*path operation*ใซๅฏพใ—ใฆ่ค‡ๆ•ฐๅ›žๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ไพ‹ใˆใฐใ€่ค‡ๆ•ฐใฎไพๅญ˜้–ขไฟ‚ใŒๅ…ฑ้€šใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใฃใฆใ„ใ‚‹ๅ ดๅˆใ€**FastAPI** ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ๏ผ‘ๅ›žใ ใ‘ใใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ +ไพๅญ˜้–ขไฟ‚ใฎ1ใคใŒๅŒใ˜*path operation*ใซๅฏพใ—ใฆ่ค‡ๆ•ฐๅ›žๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€ไพ‹ใˆใฐใ€่ค‡ๆ•ฐใฎไพๅญ˜้–ขไฟ‚ใŒๅ…ฑ้€šใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใฃใฆใ„ใ‚‹ๅ ดๅˆใ€**FastAPI** ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ1ๅ›žใ ใ‘ใใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ -ใใ—ใฆใ€่ฟ”ใ•ใ‚ŒใŸๅ€คใ‚’ใ€Œใ‚ญใƒฃใƒƒใ‚ทใƒฅใ€ใซไฟๅญ˜ใ—ใ€ๅŒใ˜ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆไพๅญ˜้–ขไฟ‚ใ‚’ไฝ•ๅบฆใ‚‚ๅ‘ผใณๅ‡บใ™ไปฃใ‚ใ‚Šใซใ€็‰นๅฎšใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใงใใ‚Œใ‚’ๅฟ…่ฆใจใ™ใ‚‹ๅ…จใฆใฎใ€Œไพๅญ˜้–ขไฟ‚ใ€ใซๆธกใ™ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ใใ—ใฆใ€่ฟ”ใ•ใ‚ŒใŸๅ€คใ‚’ใ€Œใ‚ญใƒฃใƒƒใ‚ทใƒฅใ€ใซไฟๅญ˜ใ—ใ€ๅŒใ˜ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆไพๅญ˜้–ขไฟ‚ใ‚’ไฝ•ๅบฆใ‚‚ๅ‘ผใณๅ‡บใ™ไปฃใ‚ใ‚Šใซใ€ใใฎ็‰นๅฎšใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใงใใ‚Œใ‚’ๅฟ…่ฆใจใ™ใ‚‹ๅ…จใฆใฎใ€Œไพๅญ˜ใ€ใซๆธกใ™ใ“ใจใซใชใ‚Šใพใ™ใ€‚ -้ซ˜ๅบฆใชใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ใ€Œใ‚ญใƒฃใƒƒใ‚ทใƒฅใ•ใ‚ŒใŸใ€ๅ€คใ‚’ไฝฟใ†ใฎใงใฏใชใใ€ๅŒใ˜ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ„ใ‚นใƒ†ใƒƒใƒ—๏ผˆใŠใใ‚‰ใ่ค‡ๆ•ฐๅ›ž๏ผ‰ใงไพๅญ˜้–ขไฟ‚ใ‚’ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใ€`Depens`ใ‚’ไฝฟ็”จใ™ใ‚‹้š›ใซใ€`use_cache=False`ใจใ„ใ†ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +้ซ˜ๅบฆใชใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ใ€Œใ‚ญใƒฃใƒƒใ‚ทใƒฅใ•ใ‚ŒใŸใ€ๅ€คใ‚’ไฝฟใ†ใฎใงใฏใชใใ€ๅŒใ˜ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ„ใ‚นใƒ†ใƒƒใƒ—๏ผˆใŠใใ‚‰ใ่ค‡ๆ•ฐๅ›ž๏ผ‰ใงไพๅญ˜้–ขไฟ‚ใ‚’ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใ€`Depends`ใ‚’ไฝฟ็”จใ™ใ‚‹้š›ใซใ€`use_cache=False`ใจใ„ใ†ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.9+ ้žAnnotated + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฏ่ƒฝใงใ‚ใ‚Œใฐ`Annotated`็‰ˆใ‚’ไฝฟใ†ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ + +/// ```Python hl_lines="1" async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): return {"fresh_value": fresh_value} ``` -## ใพใจใ‚ +//// + +## ใพใจใ‚ { #recap } -ใ“ใ“ใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ๆดพๆ‰‹ใช่จ€่‘‰ใฏๅˆฅใซใ—ใฆใ€**ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใงใ™ใ€‚ +ใ“ใ“ใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ๆดพๆ‰‹ใช่จ€่‘‰ใฏๅˆฅใซใ—ใฆใ€**Dependency Injection** ใ‚ทใ‚นใƒ†ใƒ ใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใงใ™ใ€‚ -*path operation้–ขๆ•ฐ*ใจๅŒใ˜ใ‚ˆใ†ใซ่ฆ‹ใˆใ‚‹ใŸใ ใฎ้–ขๆ•ฐใงใ™ใ€‚ +*path operation ้–ขๆ•ฐ*ใจๅŒใ˜ใ‚ˆใ†ใซ่ฆ‹ใˆใ‚‹ใŸใ ใฎ้–ขๆ•ฐใงใ™ใ€‚ ใ—ใ‹ใ—ใ€ใใ‚Œใงใ‚‚้žๅธธใซๅผทๅŠ›ใงใ€ไปปๆ„ใฎๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸไพๅญ˜้–ขไฟ‚ใ€Œใ‚ฐใƒฉใƒ•ใ€๏ผˆใƒ„ใƒชใƒผ๏ผ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/encoder.md b/docs/ja/docs/tutorial/encoder.md index 309cf88577..33cc6ae48c 100644 --- a/docs/ja/docs/tutorial/encoder.md +++ b/docs/ja/docs/tutorial/encoder.md @@ -1,16 +1,16 @@ -# JSONไบ’ๆ›ใ‚จใƒณใ‚ณใƒผใƒ€ +# JSONไบ’ๆ›ใ‚จใƒณใ‚ณใƒผใƒ€ { #json-compatible-encoder } -ใƒ‡ใƒผใ‚ฟๅž‹๏ผˆPydanticใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใช๏ผ‰ใ‚’JSONใจไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใ‚‚ใฎ๏ผˆ`dict`ใ‚„`list`ใชใฉ๏ผ‰ใซๅค‰ๆ›ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใƒ‡ใƒผใ‚ฟๅž‹๏ผˆPydanticใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใช๏ผ‰ใ‚’JSONใจไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใ‚‚ใฎ๏ผˆ`dict`ใ‚„`list`ใชใฉ๏ผ‰ใซๅค‰ๆ›ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‚ฑใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ ไพ‹ใˆใฐใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซไฟๅญ˜ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใงใ™ใ€‚ ใใฎใŸใ‚ใซใ€**FastAPI** ใฏ`jsonable_encoder()`้–ขๆ•ฐใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ -## `jsonable_encoder`ใฎไฝฟ็”จ +## `jsonable_encoder`ใฎไฝฟ็”จ { #using-the-jsonable-encoder } JSONไบ’ๆ›ใฎใƒ‡ใƒผใ‚ฟใฎใฟใ‚’ๅ—ไฟกใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น`fake_db`ใŒใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ -ไพ‹ใˆใฐใ€`datetime`ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏJSONใจไบ’ๆ›ๆ€งใŒใชใ„ใฎใงใ€ใ“ใฎใƒ‡ใƒผใ‚ฟใƒผใƒ™ใƒผใ‚นใซใฏๅ—ใ‘ๅ–ใ‚‰ใ‚Œใพใ›ใ‚“ใ€‚ +ไพ‹ใˆใฐใ€`datetime`ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏJSONใจไบ’ๆ›ๆ€งใŒใชใ„ใฎใงใ€ๅ—ใ‘ๅ–ใ‚‰ใ‚Œใพใ›ใ‚“ใ€‚ ใใฎใŸใ‚ใ€`datetime`ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏISOๅฝขๅผใฎใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`str`ใซๅค‰ๆ›ใ•ใ‚Œใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ @@ -20,7 +20,7 @@ JSONไบ’ๆ›ใฎใƒ‡ใƒผใ‚ฟใฎใฟใ‚’ๅ—ไฟกใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น`fake_db`ใŒใ‚ใ‚‹ Pydanticใƒขใƒ‡ใƒซใฎใ‚ˆใ†ใชใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€JSONไบ’ๆ›็‰ˆใ‚’่ฟ”ใ—ใพใ™: -{* ../../docs_src/encoder/tutorial001.py hl[5,22] *} +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} ใ“ใฎไพ‹ใงใฏใ€Pydanticใƒขใƒ‡ใƒซใ‚’`dict`ใซใ€`datetime`ใ‚’`str`ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/extra-data-types.md b/docs/ja/docs/tutorial/extra-data-types.md index 1be1c3f923..4ed84e86f8 100644 --- a/docs/ja/docs/tutorial/extra-data-types.md +++ b/docs/ja/docs/tutorial/extra-data-types.md @@ -1,6 +1,6 @@ -# ่ฟฝๅŠ ใƒ‡ใƒผใ‚ฟๅž‹ +# ่ฟฝๅŠ ใƒ‡ใƒผใ‚ฟๅž‹ { #extra-data-types } -ไปŠใพใงใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชไธ€่ˆฌ็š„ใชใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ไฝฟ็”จใ—ใฆใใพใ—ใŸ: +ไปŠใพใงใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชไธ€่ˆฌ็š„ใชใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ไฝฟ็”จใ—ใฆใใพใ—ใŸ: * `int` * `float` @@ -11,13 +11,13 @@ ใใ—ใฆใ€ไปŠใพใง่ฆ‹ใฆใใŸใฎใจๅŒใ˜ๆฉŸ่ƒฝใ‚’ๆŒใคใ“ใจใซใชใ‚Šใพใ™: -* ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆ -* ๅ—ไฟกใ—ใŸใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใฎใƒ‡ใƒผใ‚ฟๅค‰ๆ› -* ใƒฌใ‚นใƒใƒณใ‚นใƒ‡ใƒผใ‚ฟใฎใƒ‡ใƒผใ‚ฟๅค‰ๆ› -* ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ -* ่‡ชๅ‹•ๆณจ้‡ˆใจๆ–‡ๆ›ธๅŒ– +* ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ€‚ +* ๅ—ไฟกใ—ใŸใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใฎใƒ‡ใƒผใ‚ฟๅค‰ๆ›ใ€‚ +* ใƒฌใ‚นใƒใƒณใ‚นใƒ‡ใƒผใ‚ฟใฎใƒ‡ใƒผใ‚ฟๅค‰ๆ›ใ€‚ +* ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผใ€‚ +* ่‡ชๅ‹•ๆณจ้‡ˆใจๆ–‡ๆ›ธๅŒ–ใ€‚ -## ไป–ใฎใƒ‡ใƒผใ‚ฟๅž‹ +## ไป–ใฎใƒ‡ใƒผใ‚ฟๅž‹ { #other-data-types } ใ“ใ“ใงใฏใ€ไฝฟ็”จใงใใ‚‹่ฟฝๅŠ ใฎใƒ‡ใƒผใ‚ฟๅž‹ใฎใ„ใใคใ‹ใ‚’็ดนไป‹ใ—ใพใ™: @@ -26,17 +26,17 @@ * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใงใฏ`str`ใจใ—ใฆ่กจ็พใ•ใ‚Œใพใ™ใ€‚ * `datetime.datetime`: * Pythonใฎ`datetime.datetime`ใงใ™ใ€‚ - * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™: `2008-09-15T15:53:00+05:00` + * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™๏ผˆไพ‹: `2008-09-15T15:53:00+05:00`๏ผ‰ใ€‚ * `datetime.date`: - * Pythonใฎ`datetime.date`ใงใ™ใ€‚ - * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™: `2008-09-15` + * Python `datetime.date`ใ€‚ + * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™๏ผˆไพ‹: `2008-09-15`๏ผ‰ใ€‚ * `datetime.time`: - * Pythonใฎ`datetime.time`. - * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™: `14:23:55.003` + * Pythonใฎ`datetime.time`ใ€‚ + * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฏISO 8601ๅฝขๅผใฎ`str`ใง่กจ็พใ•ใ‚Œใพใ™๏ผˆไพ‹: `14:23:55.003`๏ผ‰ใ€‚ * `datetime.timedelta`: * Pythonใฎ`datetime.timedelta`ใงใ™ใ€‚ * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใงใฏๅˆ่จˆ็ง’ๆ•ฐใฎ`float`ใง่กจ็พใ•ใ‚Œใพใ™ใ€‚ - * Pydanticใงใฏใ€ŒISO 8601 time diff encodingใ€ใจใ—ใฆ่กจ็พใ™ใ‚‹ใ“ใจใ‚‚ๅฏ่ƒฝใงใ™ใ€‚่ฉณ็ดฐใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + * Pydanticใงใฏใ€ŒISO 8601 time diff encodingใ€ใจใ—ใฆ่กจ็พใ™ใ‚‹ใ“ใจใ‚‚ๅฏ่ƒฝใงใ™ใ€‚่ฉณ็ดฐใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ * `frozenset`: * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใงใฏ`set`ใจๅŒใ˜ใ‚ˆใ†ใซๆ‰ฑใ‚ใ‚Œใพใ™: * ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฏใ€ใƒชใ‚นใƒˆใŒ่ชญใฟ่พผใพใ‚Œใ€้‡่ค‡ใ‚’ๆŽ’้™คใ—ใฆ`set`ใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ @@ -45,18 +45,18 @@ * `bytes`: * Pythonใฎๆจ™ๆบ–็š„ใช`bytes`ใงใ™ใ€‚ * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใงใฏ`str`ใจใ—ใฆๆ‰ฑใ‚ใ‚Œใพใ™ใ€‚ - * ็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใฏ`str`ใง`binary`ใฎใ€Œใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใ€ๆŒใคใ“ใจใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ + * ็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใฏ`str`ใง`binary`ใฎใ€Œใƒ•ใ‚ฉใƒผใƒžใƒƒใƒˆใ€ใ‚’ๆŒใคใ“ใจใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ * `Decimal`: * Pythonใฎๆจ™ๆบ–็š„ใช`Decimal`ใงใ™ใ€‚ - * ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚„ใƒฌใ‚นใƒใƒณใ‚นใงใฏ`float`ใจๅŒใ˜ใ‚ˆใ†ใซๆ‰ฑใ„ใพใ™ใ€‚ + * ใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใงใฏ`float`ใจๅŒใ˜ใ‚ˆใ†ใซๆ‰ฑใ‚ใ‚Œใพใ™ใ€‚ +* Pydanticใฎๅ…จใฆใฎๆœ‰ๅŠนใชๅž‹ใฏใ“ใกใ‚‰ใง็ขบ่ชใงใใพใ™: Pydantic data typesใ€‚ -* Pydanticใฎๅ…จใฆใฎๆœ‰ๅŠนใชๅž‹ใฏใ“ใกใ‚‰ใง็ขบ่ชใงใใพใ™: Pydantic data typesใ€‚ -## ไพ‹ +## ไพ‹ { #example } ใ“ใ“ใงใฏใ€ไธŠ่จ˜ใฎๅž‹ใฎใ„ใใคใ‹ใ‚’ไฝฟ็”จใ—ใŸใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใค*path operation*ใฎไพ‹ใ‚’็คบใ—ใพใ™ใ€‚ -{* ../../docs_src/extra_data_types/tutorial001.py hl[1,2,12:16] *} +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} -้–ขๆ•ฐๅ†…ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ่‡ช็„ถใชใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใใ—ใฆใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซ้€šๅธธใฎๆ—ฅไป˜ๆ“ไฝœใ‚’่กŒใ†ใ“ใจใŒใงใใพใ™: +้–ขๆ•ฐๅ†…ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ่‡ช็„ถใชใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใใ—ใฆใ€ไพ‹ใˆใฐใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซ้€šๅธธใฎๆ—ฅไป˜ๆ“ไฝœใ‚’่กŒใ†ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/extra_data_types/tutorial001.py hl[18,19] *} +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/ja/docs/tutorial/extra-models.md b/docs/ja/docs/tutorial/extra-models.md index b7e2154099..05e267818c 100644 --- a/docs/ja/docs/tutorial/extra-models.md +++ b/docs/ja/docs/tutorial/extra-models.md @@ -1,6 +1,6 @@ -# ใƒขใƒ‡ใƒซ - ใ‚ˆใ‚Š่ฉณใ—ใ +# Extra Models { #extra-models } -ๅ…ˆใปใฉใฎไพ‹ใซ็ถšใใ€่ค‡ๆ•ฐใฎ้–ข้€ฃใƒขใƒ‡ใƒซใ‚’ๆŒใคใ“ใจใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ +ๅ…ˆใปใฉใฎไพ‹ใซ็ถšใใ€่ค‡ๆ•ฐใฎ้–ข้€ฃใƒขใƒ‡ใƒซใ‚’ๆŒใคใ“ใจใฏไธ€่ˆฌ็š„ใงใ™ใ€‚ ใ“ใ‚Œใฏใƒฆใƒผใ‚ถใƒผใƒขใƒ‡ใƒซใฎๅ ดๅˆใฏ็‰นใซใใ†ใงใ™ใ€‚ใชใœใชใ‚‰: @@ -8,27 +8,27 @@ * **ๅ‡บๅŠ›ใƒขใƒ‡ใƒซ**ใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ใ‚‚ใคในใใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ * **ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซ**ใฏใŠใใ‚‰ใใƒใƒƒใ‚ทใƒฅๅŒ–ใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๅฟ…่ฆใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ -/// danger | ๅฑ้™บ +/// danger -ใƒฆใƒผใ‚ถใƒผใฎๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฏ็ตถๅฏพใซไฟๅญ˜ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ๅธธใซ่ช่จผใซๅˆฉ็”จๅฏ่ƒฝใชใ€Œๅฎ‰ๅ…จใชใƒใƒƒใ‚ทใƒฅใ€ใ‚’ไฟๅญ˜ใ—ใฆใใ ใ•ใ„ใ€‚ +ใƒฆใƒผใ‚ถใƒผใฎๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฏ็ตถๅฏพใซไฟๅญ˜ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ๅธธใซๆคœ่จผใงใใ‚‹ใ€Œๅฎ‰ๅ…จใชใƒใƒƒใ‚ทใƒฅใ€ใ‚’ไฟๅญ˜ใ—ใฆใใ ใ•ใ„ใ€‚ ็Ÿฅใ‚‰ใชใ„ๆ–นใฏใ€[ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎ็ซ ](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}ใงใ€Œใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅใ€ใจใฏไฝ•ใ‹ใ‚’ๅญฆใถใ“ใจใŒใงใใพใ™ใ€‚ /// -## ่ค‡ๆ•ฐใฎใƒขใƒ‡ใƒซ +## Multiple models { #multiple-models } ใ“ใ“ใงใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ใ‚‚ใคใƒขใƒ‡ใƒซใŒใฉใฎใ‚ˆใ†ใซ่ฆ‹ใˆใ‚‹ใฎใ‹ใ€ใพใŸใ€ใฉใ“ใงไฝฟใ‚ใ‚Œใ‚‹ใฎใ‹ใ€ๅคงใพใ‹ใชใ‚คใƒกใƒผใ‚ธใ‚’็ดนไป‹ใ—ใพใ™: -{* ../../docs_src/extra_models/tutorial001.py hl[9,11,16,22,24,29:30,33:35,40:41] *} +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} -### `**user_in.dict()`ใซใคใ„ใฆ +### About `**user_in.model_dump()` { #about-user-in-model-dump } -#### Pydanticใฎ`.dict()` +#### Pydanticใฎ`.model_dump()` { #pydantics-model-dump } `user_in`ใฏ`UserIn`ใ‚ฏใƒฉใ‚นใฎPydanticใƒขใƒ‡ใƒซใงใ™ใ€‚ -Pydanticใƒขใƒ‡ใƒซใซใฏใ€ใƒขใƒ‡ใƒซใฎใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`dict`ใ‚’่ฟ”ใ™`.dict()`ใƒกใ‚ฝใƒƒใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ +Pydanticใƒขใƒ‡ใƒซใซใฏใ€ใƒขใƒ‡ใƒซใฎใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`dict`ใ‚’่ฟ”ใ™`.model_dump()`ใƒกใ‚ฝใƒƒใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ ใใ“ใงใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชPydanticใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ`user_in`ใ‚’ไฝœๆˆใ™ใ‚‹ใจ: @@ -39,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com ใใ—ใฆๅ‘ผใณๅ‡บใ™ใจ: ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() ``` ใ“ใ‚Œใงๅค‰ๆ•ฐ`user_dict`ใฎใƒ‡ใƒผใ‚ฟใ‚’ๆŒใค`dict`ใŒใงใใพใ—ใŸใ€‚๏ผˆใ“ใ‚ŒใฏPydanticใƒขใƒ‡ใƒซใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎไปฃใ‚ใ‚Šใซ`dict`ใงใ™๏ผ‰ใ€‚ @@ -61,7 +61,7 @@ print(user_dict) } ``` -#### `dict`ใฎๅฑ•้–‹ +#### `dict`ใฎๅฑ•้–‹ { #unpacking-a-dict } `user_dict`ใฎใ‚ˆใ†ใช`dict`ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใใ‚Œใ‚’`**user_dict`ใ‚’ๆŒใค้–ขๆ•ฐ๏ผˆใพใŸใฏใ‚ฏใƒฉใ‚น๏ผ‰ใซๆธกใ™ใจใ€Pythonใฏใใ‚Œใ‚’ใ€Œๅฑ•้–‹ใ€ใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ`user_dict`ใฎใ‚ญใƒผใจๅ€คใ‚’็›ดๆŽฅใ‚ญใƒผใƒปใƒใƒชใƒฅใƒผใฎๅผ•ๆ•ฐใจใ—ใฆๆธกใ—ใพใ™ใ€‚ @@ -93,31 +93,31 @@ UserInDB( ) ``` -#### ๅˆฅใฎใƒขใƒ‡ใƒซใ‹ใ‚‰ใคใใ‚‹Pydanticใƒขใƒ‡ใƒซ +#### ๅˆฅใฎใƒขใƒ‡ใƒซใฎๅ†…ๅฎนใ‹ใ‚‰ใคใใ‚‹Pydanticใƒขใƒ‡ใƒซ { #a-pydantic-model-from-the-contents-of-another } -ไธŠ่ฟฐใฎไพ‹ใงใฏ`user_in.dict()`ใ‹ใ‚‰`user_dict`ใ‚’ใ“ใฎใ‚ณใƒผใƒ‰ใฎใ‚ˆใ†ใซๅ–ๅพ—ใ—ใฆใ„ใพใ™ใŒ: +ไธŠ่ฟฐใฎไพ‹ใงใฏ`user_in.model_dump()`ใ‹ใ‚‰`user_dict`ใ‚’ใ“ใฎใ‚ณใƒผใƒ‰ใฎใ‚ˆใ†ใซๅ–ๅพ—ใ—ใฆใ„ใพใ™ใŒ: ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() UserInDB(**user_dict) ``` ใ“ใ‚Œใฏไปฅไธ‹ใจๅŒ็ญ‰ใงใ™: ```Python -UserInDB(**user_in.dict()) +UserInDB(**user_in.model_dump()) ``` -...ใชใœใชใ‚‰`user_in.dict()`ใฏ`dict`ใงใ‚ใ‚Šใ€`**`ใ‚’ไป˜ไธŽใ—ใฆ`UserInDB`ใ‚’ๆธกใ—ใฆPythonใซใ€Œๅฑ•้–‹ใ€ใ•ใ›ใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ +...ใชใœใชใ‚‰`user_in.model_dump()`ใฏ`dict`ใงใ‚ใ‚Šใ€`**`ใ‚’ไป˜ไธŽใ—ใฆ`UserInDB`ใ‚’ๆธกใ—ใฆPythonใซใ€Œๅฑ•้–‹ใ€ใ•ใ›ใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ ใใ“ใงใ€ๅˆฅใฎPydanticใƒขใƒ‡ใƒซใฎใƒ‡ใƒผใ‚ฟใ‹ใ‚‰Pydanticใƒขใƒ‡ใƒซใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ -#### `dict`ใฎๅฑ•้–‹ใจ่ฟฝๅŠ ๅผ•ๆ•ฐ +#### `dict`ใฎๅฑ•้–‹ใจ่ฟฝๅŠ ใ‚ญใƒผใƒฏใƒผใƒ‰ { #unpacking-a-dict-and-extra-keywords } ใใ—ใฆใ€่ฟฝๅŠ ใฎใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐ`hashed_password=hashed_password`ใ‚’ไปฅไธ‹ใฎใ‚ˆใ†ใซ่ฟฝๅŠ ใ™ใ‚‹ใจ: ```Python -UserInDB(**user_in.dict(), hashed_password=hashed_password) +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` ...ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: @@ -132,13 +132,13 @@ UserInDB( ) ``` -/// warning | ๆณจๆ„ +/// warning -ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใ‚‹่ฟฝๅŠ ๆฉŸ่ƒฝใฏใ€ใƒ‡ใƒผใ‚ฟใฎๅฏ่ƒฝใชๆตใ‚Œใ‚’ใƒ‡ใƒขใ™ใ‚‹ใ ใ‘ใงใ‚ใ‚Šใ€ใ‚‚ใกใ‚ใ‚“ๆœฌๅฝ“ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๆไพ›ใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +่ฟฝๅŠ ใฎใ‚ตใƒใƒผใƒˆ้–ขๆ•ฐ`fake_password_hasher`ใจ`fake_save_user`ใฏใ€ใƒ‡ใƒผใ‚ฟใฎๅฏ่ƒฝใชๆตใ‚Œใ‚’ใƒ‡ใƒขใ™ใ‚‹ใ ใ‘ใงใ‚ใ‚Šใ€ใ‚‚ใกใ‚ใ‚“ๆœฌๅฝ“ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๆไพ›ใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ /// -## ้‡่ค‡ใฎๅ‰Šๆธ› +## Reduce duplication { #reduce-duplication } ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡ใ‚’ๆธ›ใ‚‰ใ™ใ“ใจใฏใ€**FastAPI**ใฎไธญๆ ธ็š„ใชใ‚ขใ‚คใƒ‡ใ‚ขใฎ๏ผ‘ใคใงใ™ใ€‚ @@ -152,40 +152,60 @@ UserInDB( ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›ใ€ๆคœ่จผใ€ๆ–‡ๆ›ธๅŒ–ใชใฉใฏใ™ในใฆ้€šๅธธ้€šใ‚Šใซๅ‹•ไฝœใ—ใพใ™ใ€‚ -ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใƒขใƒ‡ใƒซ้–“ใฎ้•ใ„ใ ใ‘ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใ“ใฎใ‚ˆใ†ใซใ—ใฆใ€ใƒขใƒ‡ใƒซ้–“ใฎ้•ใ„ใ ใ‘ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆๅนณๆ–‡ใฎ`password`ใ€`hashed_password`ใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใชใ—๏ผ‰: -{* ../../docs_src/extra_models/tutorial002.py hl[9,15,16,19,20,23,24] *} +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} -## `Union`ใพใŸใฏ`anyOf` +## `Union` or `anyOf` { #union-or-anyof } -ใƒฌใ‚นใƒใƒณใ‚นใ‚’๏ผ’ใคใฎๅž‹ใฎ`Union`ใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใƒฌใ‚นใƒใƒณใ‚นใ‚’2ใคไปฅไธŠใฎๅž‹ใฎ`Union`ใจใ—ใฆๅฎฃ่จ€ใงใใพใ™ใ€‚ใคใพใ‚Šใ€ใใฎใƒฌใ‚นใƒใƒณใ‚นใฏใใ‚Œใ‚‰ใฎใ„ใšใ‚Œใ‹ใซใชใ‚Šใพใ™ใ€‚ OpenAPIใงใฏ`anyOf`ใงๅฎš็พฉใ•ใ‚Œใพใ™ใ€‚ ใใฎใŸใ‚ใซใฏใ€ๆจ™ๆบ–็š„ใชPythonใฎๅž‹ใƒ’ใƒณใƒˆ`typing.Union`ใ‚’ไฝฟ็”จใ—ใพใ™: -{* ../../docs_src/extra_models/tutorial003.py hl[1,14,15,18,19,20,33] *} +/// note | ๅ‚™่€ƒ -## ใƒขใƒ‡ใƒซใฎใƒชใ‚นใƒˆ +`Union`ใ‚’ๅฎš็พฉใ™ใ‚‹ๅ ดๅˆใฏใ€ๆœ€ใ‚‚ๅ…ทไฝ“็š„ใชๅž‹ใ‚’ๅ…ˆใซใ€ใใฎๅพŒใซใ‚ˆใ‚Šๅ…ทไฝ“ๆ€งใฎไฝŽใ„ๅž‹ใ‚’ๅซใ‚ใฆใใ ใ•ใ„ใ€‚ไปฅไธ‹ใฎไพ‹ใงใฏใ€ใ‚ˆใ‚Šๅ…ทไฝ“็š„ใช`PlaneItem`ใŒ`Union[PlaneItem, CarItem]`ๅ†…ใง`CarItem`ใ‚ˆใ‚Šๅ‰ใซๆฅใฆใ„ใพใ™ใ€‚ -ๅŒใ˜ใ‚ˆใ†ใซใ€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใƒชใ‚นใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### Python 3.10ใฎ`Union` { #union-in-python-3-10 } + +ใ“ใฎไพ‹ใงใฏใ€ๅผ•ๆ•ฐ`response_model`ใฎๅ€คใจใ—ใฆ`Union[PlaneItem, CarItem]`ใ‚’ๆธกใ—ใฆใ„ใพใ™ใ€‚ + +**ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ**ใซๆ›ธใใฎใงใฏใชใใ€**ๅผ•ๆ•ฐใฎๅ€ค**ใจใ—ใฆๆธกใ—ใฆใ„ใ‚‹ใŸใ‚ใ€Python 3.10ใงใ‚‚`Union`ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใงใ‚ใ‚Œใฐใ€ๆฌกใฎใ‚ˆใ†ใซ็ธฆๆฃ’ใ‚’ไฝฟ็”จใงใใพใ—ใŸ: + +```Python +some_variable: PlaneItem | CarItem +``` + +ใ—ใ‹ใ—ใ€ใ“ใ‚Œใ‚’ไปฃๅ…ฅใง`response_model=PlaneItem | CarItem`ใฎใ‚ˆใ†ใซๆ›ธใใจใ€Pythonใฏใใ‚Œใ‚’ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจใ—ใฆ่งฃ้‡ˆใ™ใ‚‹ใฎใงใฏใชใใ€`PlaneItem`ใจ`CarItem`ใฎ้–“ใง**็„กๅŠนใชๆ“ไฝœ**ใ‚’่กŒใŠใ†ใจใ—ใฆใ—ใพใ†ใŸใ‚ใ€ใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ + +## List of models { #list-of-models } + +ๅŒใ˜ใ‚ˆใ†ใซใ€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใƒชใ‚นใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ -ใใฎใŸใ‚ใซใฏใ€ๆจ™ๆบ–ใฎPythonใฎ`typing.List`ใ‚’ไฝฟ็”จใ™ใ‚‹: +ใใฎใŸใ‚ใซใฏใ€ๆจ™ๆบ–ใฎPythonใฎ`typing.List`๏ผˆใพใŸใฏPython 3.9ไปฅ้™ใงใฏๅ˜ใซ`list`๏ผ‰ใ‚’ไฝฟ็”จใ—ใพใ™: -{* ../../docs_src/extra_models/tutorial004.py hl[1,20] *} +{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} -## ไปปๆ„ใฎ`dict`ใ‚’ๆŒใคใƒฌใ‚นใƒใƒณใ‚น +## Response with arbitrary `dict` { #response-with-arbitrary-dict } ใพใŸใ€Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ›ใšใซใ€ใ‚ญใƒผใจๅ€คใฎๅž‹ใ ใ‘ใ‚’ๅฎš็พฉใ—ใŸไปปๆ„ใฎ`dict`ใ‚’ไฝฟใฃใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ใ“ใ‚Œใฏใ€ๆœ‰ๅŠนใชใƒ•ใ‚ฃใƒผใƒซใƒ‰ใƒปๅฑžๆ€งๅ๏ผˆPydanticใƒขใƒ‡ใƒซใซๅฟ…่ฆใชใ‚‚ใฎ๏ผ‰ใ‚’ไบ‹ๅ‰ใซ็Ÿฅใ‚‰ใชใ„ๅ ดๅˆใซไพฟๅˆฉใงใ™ใ€‚ -ใ“ใฎๅ ดๅˆใ€`typing.Dict`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใ“ใฎๅ ดๅˆใ€`typing.Dict`๏ผˆใพใŸใฏPython 3.9ไปฅ้™ใงใฏๅ˜ใซ`dict`๏ผ‰ใ‚’ไฝฟ็”จใงใใพใ™: -{* ../../docs_src/extra_models/tutorial005.py hl[1,8] *} +{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} -## ใพใจใ‚ +## Recap { #recap } ่ค‡ๆ•ฐใฎPydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใ€ใ‚ฑใƒผใ‚นใ”ใจใซ่‡ช็”ฑใซ็ถ™ๆ‰ฟใ—ใพใ™ใ€‚ -ใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใŒ็•ฐใชใ‚‹ใ€Œ็Šถๆ…‹ใ€ใ‚’ๆŒใŸใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใ”ใจใซๅ˜ไธ€ใฎใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๆŒใคๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚`password` ใ‚„ `password_hash` ใ‚„ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใชใ—ใชใฉใฎใ„ใใคใ‹ใฎใ€Œ็Šถๆ…‹ใ€ใ‚’ใ‚‚ใคใƒฆใƒผใ‚ถใƒผใ€Œใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใ€ใฎๅ ดๅˆใฎๆง˜ใซใ™ใ‚Œใฐ่‰ฏใ„ใงใ™ใ€‚ +ใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใŒ็•ฐใชใ‚‹ใ€Œ็Šถๆ…‹ใ€ใ‚’ๆŒใŸใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใ”ใจใซๅ˜ไธ€ใฎใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๆŒใคๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚`password`ใ€`password_hash`ใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใชใ—ใ‚’ๅซใ‚€็Šถๆ…‹ใ‚’ๆŒใคใƒฆใƒผใ‚ถใƒผใ€Œใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใ€ใฎๅ ดๅˆใจๅŒๆง˜ใงใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/first-steps.md b/docs/ja/docs/tutorial/first-steps.md index 77f9cba43b..ecad2f6ff9 100644 --- a/docs/ja/docs/tutorial/first-steps.md +++ b/docs/ja/docs/tutorial/first-steps.md @@ -1,8 +1,8 @@ -# ๆœ€ๅˆใฎใ‚นใƒ†ใƒƒใƒ— +# ๆœ€ๅˆใฎใ‚นใƒ†ใƒƒใƒ— { #first-steps } ๆœ€ใ‚‚ใ‚ทใƒณใƒ—ใƒซใชFastAPIใƒ•ใ‚กใ‚คใƒซใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/first_steps/tutorial001.py *} +{* ../../docs_src/first_steps/tutorial001_py39.py *} ใ“ใ‚Œใ‚’`main.py`ใซใ‚ณใƒ”ใƒผใ—ใพใ™ใ€‚ @@ -11,26 +11,42 @@
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. -``` + FastAPI Starting development server ๐Ÿš€ -
+ Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -/// note | ๅ‚™่€ƒ + module ๐Ÿ main.py -`uvicorn main:app`ใฏไปฅไธ‹ใ‚’็คบใ—ใพใ™: + code Importing the FastAPI app object from the module with + the following code: -* `main`: `main.py`ใƒ•ใ‚กใ‚คใƒซ (Python "module")ใ€‚ -* `app`: `main.py`ๅ†…้ƒจใงไฝœใ‚‰ใ‚Œใ‚‹object๏ผˆ`app = FastAPI()`ใฎใ‚ˆใ†ใซ่จ˜่ฟฐใ•ใ‚Œใ‚‹๏ผ‰ใ€‚ -* `--reload`: ใ‚ณใƒผใƒ‰ใฎๅค‰ๆ›ดๆ™‚ใซใ‚ตใƒผใƒใƒผใ‚’ๅ†่ตทๅ‹•ใ•ใ›ใ‚‹ใ€‚้–‹็™บ็”จใ€‚ + from main import app -/// + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + + ๅ‡บๅŠ›ใซใฏๆฌกใฎใ‚ˆใ†ใช่กŒใŒใ‚ใ‚Šใพใ™: @@ -40,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ใ“ใฎ่กŒใฏใƒญใƒผใ‚ซใƒซใƒžใ‚ทใƒณใงใ‚ขใƒ—ใƒชใŒๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹URLใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚ -### ใƒใ‚งใƒƒใ‚ฏ +### ใƒใ‚งใƒƒใ‚ฏ { #check-it } ใƒ–ใƒฉใ‚ฆใ‚ถใงhttp://127.0.0.1:8000ใ‚’้–‹ใใพใ™ใ€‚ @@ -50,7 +66,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) {"message": "Hello World"} ``` -### ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +### ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #interactive-api-docs } ๆฌกใซใ€http://127.0.0.1:8000/docsใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ @@ -58,7 +74,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ไป–ใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +### ไปฃๆ›ฟAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #alternative-api-docs } ๆฌกใซใ€http://127.0.0.1:8000/redocใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ @@ -66,31 +82,31 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } **FastAPI**ใฏใ€APIใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใฎ**OpenAPI**ๆจ™ๆบ–่ฆๆ ผใ‚’ไฝฟ็”จใ—ใฆใ€ใ™ในใฆใฎAPIใฎใ€Œใ‚นใ‚ญใƒผใƒžใ€ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ -#### ใ€Œใ‚นใ‚ญใƒผใƒžใ€ +#### ใ€Œใ‚นใ‚ญใƒผใƒžใ€ { #schema } ใ€Œใ‚นใ‚ญใƒผใƒžใ€ใฏๅฎš็พฉใพใŸใฏ่ชฌๆ˜Žใงใ™ใ€‚ๅฎŸ่ฃ…ใ‚ณใƒผใƒ‰ใงใฏใชใใ€ๅ˜ใชใ‚‹ๆŠฝ่ฑก็š„ใช่ชฌๆ˜Žใงใ™ใ€‚ -#### APIใ€Œใ‚นใ‚ญใƒผใƒžใ€ +#### APIใ€Œใ‚นใ‚ญใƒผใƒžใ€ { #api-schema } ใ“ใ“ใงใฏใ€OpenAPIใฏAPIใฎใ‚นใ‚ญใƒผใƒžๅฎš็พฉใฎๆ–นๆณ•ใ‚’่ฆๅฎšใ™ใ‚‹ไป•ๆง˜ใงใ™ใ€‚ ใ“ใฎใ‚นใ‚ญใƒผใƒžๅฎš็พฉใฏAPIใƒ‘ใ‚นใ€ๅ—ใ‘ๅ–ใ‚Šๅฏ่ƒฝใชใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใฉใŒๅซใพใ‚Œใพใ™ใ€‚ -#### ใƒ‡ใƒผใ‚ฟใ€Œใ‚นใ‚ญใƒผใƒžใ€ +#### ใƒ‡ใƒผใ‚ฟใ€Œใ‚นใ‚ญใƒผใƒžใ€ { #data-schema } ใ€Œใ‚นใ‚ญใƒผใƒžใ€ใจใ„ใ†็”จ่ชžใฏใ€JSONใ‚ณใƒณใƒ†ใƒณใƒ„ใชใฉใฎไธ€้ƒจใฎใƒ‡ใƒผใ‚ฟใฎๅฝข็Šถใ‚’ๆŒ‡ใ™ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€ใ‚นใ‚ญใƒผใƒžใฏJSONๅฑžๆ€งใจใใ‚Œใ‚‰ใŒๆŒใคใƒ‡ใƒผใ‚ฟๅž‹ใชใฉใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -#### OpenAPIใŠใ‚ˆใณJSONใ‚นใ‚ญใƒผใƒž +#### OpenAPIใŠใ‚ˆใณJSONใ‚นใ‚ญใƒผใƒž { #openapi-and-json-schema } OpenAPIใฏAPIใฎใŸใ‚ใฎAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ใใ—ใฆใ€ใใฎใ‚นใ‚ญใƒผใƒžใฏ**JSONใƒ‡ใƒผใ‚ฟใ‚นใ‚ญใƒผใƒž**ใฎๆจ™ๆบ–่ฆๆ ผใซๆบ–ๆ‹ ใ—ใŸJSONใ‚นใ‚ญใƒผใƒžใ‚’ๅˆฉ็”จใ™ใ‚‹APIใซใ‚ˆใฃใฆ้€ๅ—ใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใฎๅฎš็พฉ๏ผˆใพใŸใฏใ€Œใ‚นใ‚ญใƒผใƒžใ€๏ผ‰ใ‚’ๅซใ‚“ใงใ„ใพใ™ใ€‚ -#### `openapi.json`ใ‚’็ขบ่ช +#### `openapi.json`ใ‚’็ขบ่ช { #check-the-openapi-json } ็ด ใฎOpenAPIใ‚นใ‚ญใƒผใƒžใŒใฉใฎใ‚ˆใ†ใชใ‚‚ใฎใ‹่ˆˆๅ‘ณใŒใ‚ใ‚‹ๅ ดๅˆใ€FastAPIใฏใ™ในใฆใฎAPIใฎ่ชฌๆ˜Žใ‚’ๅซใ‚€JSON๏ผˆใ‚นใ‚ญใƒผใƒž๏ผ‰ใ‚’่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ—ใพใ™ใ€‚ @@ -100,7 +116,7 @@ OpenAPIใฏAPIใฎใŸใ‚ใฎAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ใใ—ใฆใ€ใใฎ ```JSON { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" @@ -119,7 +135,7 @@ OpenAPIใฏAPIใฎใŸใ‚ใฎAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ใใ—ใฆใ€ใใฎ ... ``` -#### OpenAPIใฎ็›ฎ็š„ +#### OpenAPIใฎ็›ฎ็š„ { #what-is-openapi-for } OpenAPIใ‚นใ‚ญใƒผใƒžใฏใ€FastAPIใซๅซใพใ‚Œใฆใ„ใ‚‹2ใคใฎใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใฎๅ‹•ๅŠ›ๆบใงใ™ใ€‚ @@ -127,60 +143,68 @@ OpenAPIใ‚นใ‚ญใƒผใƒžใฏใ€FastAPIใซๅซใพใ‚Œใฆใ„ใ‚‹2ใคใฎใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ† ใพใŸใ€APIใจ้€šไฟกใ™ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ็”จใฎใ‚ณใƒผใƒ‰ใ‚’่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ใŸใจใˆใฐใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ€ใƒขใƒใ‚คใƒซใ€ใพใŸใฏIoTใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ™ใ€‚ -## ใ‚นใƒ†ใƒƒใƒ—ๆฏŽใฎ่ฆ็ด„ +### ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚ค๏ผˆไปปๆ„๏ผ‰ { #deploy-your-app-optional } -### Step 1: `FastAPI`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ +ไปปๆ„ใงFastAPIใ‚ขใƒ—ใƒชใ‚’FastAPI Cloudใซใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ใพใ ใชใ‚‰ใ€ๅพ…ๆฉŸใƒชใ‚นใƒˆใซ็™ป้Œฒใ—ใฆใใ ใ•ใ„ใ€‚ ๐Ÿš€ -{* ../../docs_src/first_steps/tutorial001.py hl[1] *} +ใ™ใงใซ**FastAPI Cloud**ใ‚ขใ‚ซใ‚ฆใƒณใƒˆใŒใ‚ใ‚‹ๅ ดๅˆ๏ผˆๅพ…ๆฉŸใƒชใ‚นใƒˆใ‹ใ‚‰ๆ‹›ๅพ…ๆธˆใฟใฎๅ ดๅˆ๐Ÿ˜‰๏ผ‰ใ€1ใ‚ณใƒžใƒณใƒ‰ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ -`FastAPI`ใฏใ€APIใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๆไพ›ใ™ใ‚‹Pythonใ‚ฏใƒฉใ‚นใงใ™ใ€‚ - -/// note | ๆŠ€่ก“่ฉณ็ดฐ +ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๅ‰ใซใ€ใƒญใ‚ฐใ‚คใƒณใ—ใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„: -`FastAPI`ใฏ`Starlette`ใ‚’็›ดๆŽฅ็ถ™ๆ‰ฟใ™ใ‚‹ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ - -`FastAPI`ใงใ‚‚Starletteใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๅˆฉ็”จๅฏ่ƒฝใงใ™ใ€‚ - -/// +
-### Step 2: `FastAPI`ใฎใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใ‚’็”Ÿๆˆ +```console +$ fastapi login -{* ../../docs_src/first_steps/tutorial001.py hl[3] *} -ใ“ใ“ใงใ€`app`ๅค‰ๆ•ฐใŒ`FastAPI`ใ‚ฏใƒฉใ‚นใฎใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใซใชใ‚Šใพใ™ใ€‚ +You are logged in to FastAPI Cloud ๐Ÿš€ +``` -ใ“ใ‚ŒใŒใ€ใ™ในใฆใฎAPIใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใฎไธป่ฆใชใƒใ‚คใƒณใƒˆใซใชใ‚Šใพใ™ใ€‚ +
-ใ“ใฎ`app`ใฏใ‚ณใƒžใƒณใƒ‰ใง`uvicorn`ใŒๅ‚็…งใ™ใ‚‹ใ‚‚ใฎใจๅŒใ˜ใงใ™: +ใใฎๅพŒใ€ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใพใ™:
```console -$ uvicorn main:app --reload +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev ```
-ไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚ขใƒ—ใƒชใ‚’ไฝœๆˆใ—ใŸใจใ: +ไปฅไธŠใงใ™๏ผใ“ใ‚Œใงใ€ใใฎURLใงใ‚ขใƒ—ใƒชใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ โœจ -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} +## ใ‚นใƒ†ใƒƒใƒ—ๆฏŽใฎ่ฆ็ด„ { #recap-step-by-step } -ใใ—ใฆใ€ใใ‚Œใ‚’`main.py`ใƒ•ใ‚กใ‚คใƒซใซ็ฝฎใใ€ๆฌกใฎใ‚ˆใ†ใซ`uvicorn`ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™: +### Step 1: `FastAPI`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #step-1-import-fastapi } -
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} -```console -$ uvicorn main:my_awesome_api --reload +`FastAPI`ใฏใ€APIใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๆไพ›ใ™ใ‚‹Pythonใ‚ฏใƒฉใ‚นใงใ™ใ€‚ -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` +/// note | ๆŠ€่ก“่ฉณ็ดฐ -
+`FastAPI`ใฏ`Starlette`ใ‚’็›ดๆŽฅ็ถ™ๆ‰ฟใ™ใ‚‹ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ -### Step 3: *path operation*ใ‚’ไฝœๆˆ +`FastAPI`ใงใ‚‚Starletteใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๅˆฉ็”จๅฏ่ƒฝใงใ™ใ€‚ + +/// + +### Step 2: `FastAPI`ใฎใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใ‚’็”Ÿๆˆ { #step-2-create-a-fastapi-instance } -#### ใƒ‘ใ‚น +{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +ใ“ใ“ใงใ€`app`ๅค‰ๆ•ฐใŒ`FastAPI`ใ‚ฏใƒฉใ‚นใฎใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใซใชใ‚Šใพใ™ใ€‚ + +ใ“ใ‚ŒใŒใ€ใ™ในใฆใฎAPIใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใฎไธป่ฆใชใƒใ‚คใƒณใƒˆใซใชใ‚Šใพใ™ใ€‚ + +### Step 3: *path operation*ใ‚’ไฝœๆˆ { #step-3-create-a-path-operation } + +#### ใƒ‘ใ‚น { #path } ใ“ใ“ใงใฎใ€Œใƒ‘ใ‚นใ€ใจใฏใ€ๆœ€ๅˆใฎ`/`ใ‹ใ‚‰ๅง‹ใพใ‚‹URLใฎๆœ€ๅพŒใฎ้ƒจๅˆ†ใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ @@ -204,7 +228,7 @@ https://example.com/items/foo APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใ€ใ€Œใƒ‘ใ‚นใ€ใฏใ€Œ้–ขๅฟƒไบ‹ใ€ใจใ€Œใƒชใ‚ฝใƒผใ‚นใ€ใ‚’ๅˆ†้›ขใ™ใ‚‹ใŸใ‚ใฎไธป่ฆใชๆ–นๆณ•ใงใ™ใ€‚ -#### Operation +#### Operation { #operation } ใ“ใ“ใงใฎใ€Œใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใ€ใจใฏใ€HTTPใฎใ€Œใƒกใ‚ฝใƒƒใƒ‰ใ€ใฎ1ใคใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ @@ -239,15 +263,16 @@ APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใจใใฏใ€้€šๅธธใ€ใ“ใ‚Œใ‚‰ใฎ็‰นๅฎšใฎHTTPใƒกใ‚ฝใƒƒใƒ‰ใ‚’ ใ€Œ**ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใ‚บ**ใ€ใจใ‚‚ๅ‘ผใถใ“ใจใซใ—ใพใ™ใ€‚ -#### *ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใ‚’ๅฎš็พฉ +#### *path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใ‚’ๅฎš็พฉ { #define-a-path-operation-decorator } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} -{* ../../docs_src/first_steps/tutorial001.py hl[6] *} `@app.get("/")`ใฏ็›ดไธ‹ใฎ้–ขๆ•ฐใŒไธ‹่จ˜ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ‡ฆ็†ใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใ“ใจใ‚’**FastAPI**ใซไผใˆใพใ™: * ใƒ‘ใ‚น `/` * get ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ -/// info | `@decorator` ใซใคใ„ใฆ +/// info | `@decorator` Info PythonใซใŠใ‘ใ‚‹`@something`ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใฏใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ @@ -255,9 +280,9 @@ PythonใซใŠใ‘ใ‚‹`@something`ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใฏใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใจๅ‘ผใฐใ‚Œ ใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใฏ็›ดไธ‹ใฎ้–ขๆ•ฐใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใใ‚Œใ‚’ไฝฟใฃใฆไฝ•ใ‹ใ‚’่กŒใ„ใพใ™ใ€‚ -็งใŸใกใฎๅ ดๅˆใ€ใ“ใฎใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใƒผใฏ็›ดไธ‹ใฎ้–ขๆ•ฐใŒ**ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ** `get`ใ‚’ไฝฟ็”จใ—ใŸ**ใƒ‘ใ‚น**` / `ใซๅฏพๅฟœใ™ใ‚‹ใ“ใจใ‚’**FastAPI** ใซ้€š็Ÿฅใ—ใพใ™ใ€‚ +็งใŸใกใฎๅ ดๅˆใ€ใ“ใฎใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใƒผใฏ็›ดไธ‹ใฎ้–ขๆ•ฐใŒ**ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ** `get`ใ‚’ไฝฟ็”จใ—ใŸ**ใƒ‘ใ‚น** `/`ใซๅฏพๅฟœใ™ใ‚‹ใ“ใจใ‚’**FastAPI** ใซ้€š็Ÿฅใ—ใพใ™ใ€‚ -ใ“ใ‚ŒใŒใ€Œ*ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใ€ใงใ™ใ€‚ +ใ“ใ‚ŒใŒใ€Œ*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใ€ใงใ™ใ€‚ /// @@ -286,15 +311,15 @@ PythonใซใŠใ‘ใ‚‹`@something`ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใฏใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใจๅ‘ผใฐใ‚Œ /// -### Step 4: **ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ**ใ‚’ๅฎš็พฉ +### Step 4: **path operation ้–ขๆ•ฐ**ใ‚’ๅฎš็พฉ { #step-4-define-the-path-operation-function } -ไปฅไธ‹ใฏใ€Œ**ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ้–ขๆ•ฐ**ใ€ใงใ™: +ไปฅไธ‹ใฏใ€Œ**path operation ้–ขๆ•ฐ**ใ€ใงใ™: * **ใƒ‘ใ‚น**: ใฏ`/`ใงใ™ใ€‚ * **ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ**: ใฏ`get`ใงใ™ใ€‚ * **้–ขๆ•ฐ**: ใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใฎ็›ดไธ‹ใซใ‚ใ‚‹้–ขๆ•ฐ (`@app.get("/")`ใฎ็›ดไธ‹) ใงใ™ใ€‚ -{* ../../docs_src/first_steps/tutorial001.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} ใ“ใ‚Œใฏใ€Pythonใฎ้–ขๆ•ฐใงใ™ใ€‚ @@ -306,28 +331,49 @@ PythonใซใŠใ‘ใ‚‹`@something`ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใฏใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใจๅ‘ผใฐใ‚Œ `async def`ใฎไปฃใ‚ใ‚Šใซ้€šๅธธใฎ้–ขๆ•ฐใจใ—ใฆๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/first_steps/tutorial003.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} /// note | ๅ‚™่€ƒ -้•ใ„ใŒๅˆ†ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€[Async: *"ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸ"*](../async.md#_1){.internal-link target=_blank}ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +้•ใ„ใŒๅˆ†ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€[Async: *"ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸ"*](../async.md#in-a-hurry){.internal-link target=_blank}ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ /// -### Step 5: ใ‚ณใƒณใƒ†ใƒณใƒ„ใฎ่ฟ”ไฟก +### Step 5: ใ‚ณใƒณใƒ†ใƒณใƒ„ใฎ่ฟ”ไฟก { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} -`dict`ใ€`list`ใ€`str`ใ€`int`ใชใฉใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚ +`dict`ใ€`list`ใ€`str`ใ€`int`ใชใฉใฎๅ˜ไธ€ใฎๅ€คใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚ Pydanticใƒขใƒ‡ใƒซใ‚’่ฟ”ใ™ใ“ใจใ‚‚ใงใใพใ™๏ผˆๅพŒใง่ฉณใ—ใ่ชฌๆ˜Žใ—ใพใ™๏ผ‰ใ€‚ JSONใซ่‡ชๅ‹•็š„ใซๅค‰ๆ›ใ•ใ‚Œใ‚‹ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚„ใƒขใƒ‡ใƒซใฏไป–ใซใ‚‚ใŸใใ•ใ‚“ใ‚ใ‚Šใพใ™๏ผˆORMใชใฉ๏ผ‰ใ€‚ ใŠๆฐ—ใซๅ…ฅใ‚Šใฎใ‚‚ใฎใ‚’ไฝฟใฃใฆใฟใฆใใ ใ•ใ„ใ€‚ใ™ใงใซใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใงใ™ใ€‚ -## ใพใจใ‚ +### Step 6: ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ { #step-6-deploy-it } + +**FastAPI Cloud**ใซ1ใ‚ณใƒžใƒณใƒ‰ใงใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใพใ™: `fastapi deploy`. ๐ŸŽ‰ + +#### FastAPI Cloudใซใคใ„ใฆ { #about-fastapi-cloud } + +**FastAPI Cloud**ใฏใ€**FastAPI**ใฎไฝœ่€…ใจใใฎใƒใƒผใƒ ใซใ‚ˆใฃใฆ้–‹็™บใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ๆœ€ๅฐ้™ใฎๅŠดๅŠ›ใงAPIใฎ**ๆง‹็ฏ‰**ใ€**ใƒ‡ใƒ—ใƒญใ‚ค**ใ€**ใ‚ขใ‚ฏใ‚ปใ‚น**ใ‚’่กŒใ†ใƒ—ใƒญใ‚ปใ‚นใ‚’ๅˆ็†ๅŒ–ใ—ใพใ™ใ€‚ + +FastAPIใงใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใฎใจๅŒใ˜**้–‹็™บไฝ“้จ“**ใ‚’ใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใธใฎ**ใƒ‡ใƒ—ใƒญใ‚ค**ใซใ‚‚ใŸใ‚‰ใ—ใพใ™ใ€‚ ๐ŸŽ‰ + +FastAPI Cloudใฏใ€*FastAPI and friends*ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅฏพใ™ใ‚‹ไธป่ฆใ‚นใƒใƒณใ‚ตใƒผใงใ‚ใ‚Šใ€่ณ‡้‡‘ๆไพ›ๅ…ƒใงใ™ใ€‚ โœจ + +#### ไป–ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใซใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ { #deploy-to-other-cloud-providers } + +FastAPIใฏใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใงใ€ๆจ™ๆบ–ใซๅŸบใฅใ„ใฆใ„ใพใ™ใ€‚้ธๆŠžใ—ใŸไปปๆ„ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใซFastAPIใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ + +ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใฎใ‚ฌใ‚คใƒ‰ใซๅพ“ใฃใฆใ€FastAPIใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใฆใใ ใ•ใ„ใ€‚ ๐Ÿค“ + +## ใพใจใ‚ { #recap } -* `FastAPI`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ -* `app`ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’็”Ÿๆˆ -* **ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ**ใ‚’่จ˜่ฟฐ (`@app.get("/")`) -* **ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ้–ขๆ•ฐ**ใ‚’ๅฎš็พฉ (ไธŠ่จ˜ใฎ`def root(): ...`ใฎใ‚ˆใ†ใซ) -* ้–‹็™บใ‚ตใƒผใƒใƒผใ‚’่ตทๅ‹• (`uvicorn main:app --reload`) +* `FastAPI`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ +* `app`ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ +* `@app.get("/")`ใฎใ‚ˆใ†ใชใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ€**path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ**ใ‚’่จ˜่ฟฐใ—ใพใ™ใ€‚ +* **path operation ้–ขๆ•ฐ**ใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ไพ‹: `def root(): ...`ใ€‚ +* `fastapi dev`ใ‚ณใƒžใƒณใƒ‰ใง้–‹็™บใ‚ตใƒผใƒใƒผใ‚’่ตทๅ‹•ใ—ใพใ™ใ€‚ +* ไปปๆ„ใง`fastapi deploy`ใ‚’ไฝฟใฃใฆใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index 8578ca3356..945fe07772 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -1,4 +1,4 @@ -# ใ‚จใƒฉใƒผใƒใƒณใƒ‰ใƒชใƒณใ‚ฐ +# ใ‚จใƒฉใƒผใƒใƒณใƒ‰ใƒชใƒณใ‚ฐ { #handling-errors } APIใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใ‚จใƒฉใƒผใ‚’้€š็Ÿฅใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹็ŠถๆณใฏใŸใใ•ใ‚“ใ‚ใ‚Šใพใ™ใ€‚ @@ -19,15 +19,15 @@ APIใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใ‚จใƒฉใƒผใ‚’้€š็Ÿฅใ™ใ‚‹ๅฟ…่ฆใŒ **"404 Not Found"** ใฎใ‚จใƒฉใƒผ๏ผˆใŠใ‚ˆใณใ‚ธใƒงใƒผใ‚ฏ๏ผ‰ใ‚’่ฆšใˆใฆใ„ใพใ™ใ‹๏ผŸ -## `HTTPException`ใฎไฝฟ็”จ +## `HTTPException`ใฎไฝฟ็”จ { #use-httpexception } HTTPใƒฌใ‚นใƒใƒณใ‚นใ‚’ใ‚จใƒฉใƒผใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ™ใซใฏใ€`HTTPException`ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -### `HTTPException`ใฎใ‚คใƒณใƒใƒผใƒˆ +### `HTTPException`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} -### ใ‚ณใƒผใƒ‰ๅ†…ใงใฎ`HTTPException`ใฎ็™บ็”Ÿ +### ใ‚ณใƒผใƒ‰ๅ†…ใงใฎ`HTTPException`ใฎ็™บ็”Ÿ { #raise-an-httpexception-in-your-code } `HTTPException`ใฏ้€šๅธธใฎPythonใฎไพ‹ๅค–ใงใ‚ใ‚Šใ€APIใซ้–ข้€ฃใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใ—ใŸใ‚‚ใฎใงใ™ใ€‚ @@ -39,9 +39,9 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ ใ“ใฎไพ‹ใงใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅญ˜ๅœจใ—ใชใ„IDใงใ‚ขใ‚คใƒ†ใƒ ใ‚’่ฆๆฑ‚ใ—ใŸๅ ดๅˆใ€`404`ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ๆŒใคไพ‹ๅค–ใ‚’็™บ็”Ÿใ•ใ›ใพใ™: -{* ../../docs_src/handling_errors/tutorial001.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} -### ใƒฌใ‚นใƒใƒณใ‚น็ตๆžœ +### ใƒฌใ‚นใƒใƒณใ‚น็ตๆžœ { #the-resulting-response } ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ`http://example.com/items/foo`๏ผˆ`item_id` `"foo"`๏ผ‰ใ‚’ใƒชใ‚ฏใ‚จใ‚นใƒˆใ™ใ‚‹ใจใ€HTTPใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใŒ200ใงใ€ไปฅไธ‹ใฎJSONใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™: @@ -69,7 +69,7 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ /// -## ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใฎ่ฟฝๅŠ  +## ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใฎ่ฟฝๅŠ  { #add-custom-headers } ไพ‹ใˆใฐใ€ใ„ใใคใ‹ใฎใ‚ฟใ‚คใƒ—ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎใŸใ‚ใซใ€HTTPใ‚จใƒฉใƒผใซใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใ‚’่ฟฝๅŠ ใงใใ‚‹ใจไพฟๅˆฉใช็ŠถๆณใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ @@ -77,9 +77,9 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ ใ—ใ‹ใ—ใ€้ซ˜ๅบฆใชใ‚ทใƒŠใƒชใ‚ชใฎใŸใ‚ใซๅฟ…่ฆใชๅ ดๅˆใซใฏใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/handling_errors/tutorial002.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} -## ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ +## ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-custom-exception-handlers } ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฏStarletteใจๅŒใ˜ไพ‹ๅค–ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟ็”จใ—ใฆ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -89,7 +89,7 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’`@app.exception_handler()`ใง่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/handling_errors/tutorial003.py hl[5,6,7,13,14,15,16,17,18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} ใ“ใ“ใงใ€`/unicorns/yolo`ใ‚’ใƒชใ‚ฏใ‚จใ‚นใƒˆใ™ใ‚‹ใจใ€*path operation*ใฏ`UnicornException`ใ‚’`raise`ใ—ใพใ™ใ€‚ @@ -109,7 +109,7 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ /// -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ { #override-the-default-exception-handlers } **FastAPI** ใซใฏใ„ใใคใ‹ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -117,7 +117,7 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ ใ“ใ‚Œใ‚‰ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’็‹ฌ่‡ชใฎใ‚‚ใฎใงใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -### ใƒชใ‚ฏใ‚จใ‚นใƒˆๆคœ่จผใฎไพ‹ๅค–ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ +### ใƒชใ‚ฏใ‚จใ‚นใƒˆๆคœ่จผใฎไพ‹ๅค–ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ { #override-request-validation-exceptions } ใƒชใ‚ฏใ‚จใ‚นใƒˆใซ็„กๅŠนใชใƒ‡ใƒผใ‚ฟใŒๅซใพใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€**FastAPI** ใฏๅ†…้ƒจ็š„ใซ`RequestValidationError`ใ‚’็™บ็”Ÿใ•ใ›ใพใ™ใ€‚ @@ -125,11 +125,11 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ ใ“ใ‚Œใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใซใฏ`RequestValidationError`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆ`@app.exception_handler(RequestValidationError)`ใจไธ€็ท’ใซไฝฟ็”จใ—ใฆไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’ใƒ‡ใ‚ณใƒฌใƒผใƒˆใ—ใพใ™ใ€‚ -ใ“ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฏ`Requset`ใจไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ +ใ“ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฏ`Request`ใจไพ‹ๅค–ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ -{* ../../docs_src/handling_errors/tutorial004.py hl[2,14,15,16] *} +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} -ใ“ใ‚Œใงใ€`/items/foo`ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎJSONใ‚จใƒฉใƒผใฎไปฃใ‚ใ‚Šใซไปฅไธ‹ใŒ่ฟ”ใ•ใ‚Œใพใ™: +ใ“ใ‚Œใงใ€`/items/foo`ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎJSONใ‚จใƒฉใƒผใฎไปฃใ‚ใ‚Šใซ: ```JSON { @@ -146,39 +146,20 @@ Pythonใฎไพ‹ๅค–ใชใฎใงใ€`return`ใงใฏใชใใ€`raise`ใงใ™ใ€‚ } ``` -ไปฅไธ‹ใฎใ‚ˆใ†ใชใƒ†ใ‚ญใ‚นใƒˆ็‰ˆใ‚’ๅ–ๅพ—ใ—ใพใ™: +ไปฅไธ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ็‰ˆใ‚’ๅ–ๅพ—ใ—ใพใ™: ``` -1 validation error -path -> item_id - value is not a valid integer (type=type_error.integer) +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer ``` -#### `RequestValidationError`ใจ`ValidationError` - -/// warning | ๆณจๆ„ - -ใ“ใ‚Œใ‚‰ใฏไปŠใฎใ‚ใชใŸใซใจใฃใฆ้‡่ฆใงใชใ„ๅ ดๅˆใฏ็œ็•ฅใ—ใฆใ‚‚่‰ฏใ„ๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ™ใ€‚ - -/// - -`RequestValidationError`ใฏPydanticใฎ`ValidationError`ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ - -**FastAPI** ใฏ`response_model`ใงPydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใฆใ„ใฆใ€ใƒ‡ใƒผใ‚ฟใซใ‚จใƒฉใƒผใŒใ‚ใฃใŸๅ ดๅˆใ€ใƒญใ‚ฐใซใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ“ใ‚Œใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ - -ใ—ใ‹ใ—ใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚„ใƒฆใƒผใ‚ถใƒผใฏใใ‚Œใ‚’่ฆ‹ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใฎไปฃใ‚ใ‚Šใซใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏHTTPใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰`500`ใฎใ€ŒInternal Server Errorใ€ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ - -*ใƒฌใ‚นใƒใƒณใ‚น*ใ‚„ใ‚ณใƒผใƒ‰ใฎใฉใ“ใ‹๏ผˆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎ*ใƒชใ‚ฏใ‚จใ‚นใƒˆ*ใงใฏใชใ๏ผ‰ใซPydanticใฎ`ValidationError`ใŒใ‚ใ‚‹ๅ ดๅˆใ€ใใ‚ŒใฏๅฎŸ้š›ใซใฏใ‚ณใƒผใƒ‰ใฎใƒใ‚ฐใชใฎใงใ“ใฎใ‚ˆใ†ใซใ™ในใใงใ™ใ€‚ - -ใพใŸใ€ใ‚ใชใŸใŒใใ‚Œใ‚’ไฟฎๆญฃใ—ใฆใ„ใ‚‹้–“ใฏใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎ่„†ๅผฑๆ€งใŒ้œฒๅ‘ˆใ™ใ‚‹ๅ ดๅˆใŒใ‚ใ‚‹ใŸใ‚ใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚„ใƒฆใƒผใ‚ถใƒผใŒใ‚จใƒฉใƒผใซ้–ขใ™ใ‚‹ๅ†…้ƒจๆƒ…ๅ ฑใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใชใ„ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ - -### ใ‚จใƒฉใƒผใƒใƒณใƒ‰ใƒฉ`HTTPException`ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ +### `HTTPException`ใ‚จใƒฉใƒผใƒใƒณใƒ‰ใƒฉใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ { #override-the-httpexception-error-handler } ๅŒๆง˜ใซใ€`HTTPException`ใƒใƒณใƒ‰ใƒฉใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€ใ“ใ‚Œใ‚‰ใฎใ‚จใƒฉใƒผใซๅฏพใ—ใฆใฏใ€JSONใงใฏใชใใƒ—ใƒฌใƒผใƒณใƒ†ใ‚ญใ‚นใƒˆใ‚’่ฟ”ใ™ใ‚ˆใ†ใซใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/handling_errors/tutorial004.py hl[3,4,9,10,11,22] *} +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -188,13 +169,21 @@ path -> item_id /// -### `RequestValidationError`ใฎใƒœใƒ‡ใ‚ฃใฎไฝฟ็”จ +/// warning | ๆณจๆ„ + +`RequestValidationError`ใซใฏใ€ๆคœ่จผใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ—ใŸใƒ•ใ‚กใ‚คใƒซๅใจ่กŒ็•ชๅทใฎๆƒ…ๅ ฑใŒๅซใพใ‚Œใฆใ„ใ‚‹ใŸใ‚ใ€ๅฟ…่ฆใงใ‚ใ‚Œใฐ้–ข้€ฃๆƒ…ๅ ฑใจไธ€็ท’ใซใƒญใ‚ฐใซ่กจ็คบใงใใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใใฎใพใพๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ—ใฆ็›ดๆŽฅใใฎๆƒ…ๅ ฑใ‚’่ฟ”ใ™ใจใ€ใ‚ทใ‚นใƒ†ใƒ ใซ้–ขใ™ใ‚‹ๆƒ…ๅ ฑใŒๅคšๅฐ‘ๆผใˆใ„ใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ใใฎใŸใ‚ใ€ใ“ใ“ใงใฏใ‚ณใƒผใƒ‰ใŒๅ„ใ‚จใƒฉใƒผใ‚’ๅ€‹ๅˆฅใซๆŠฝๅ‡บใ—ใฆ่กจ็คบใ—ใพใ™ใ€‚ + +/// + +### `RequestValidationError`ใฎใƒœใƒ‡ใ‚ฃใฎไฝฟ็”จ { #use-the-requestvalidationerror-body } `RequestValidationError`ใซใฏ็„กๅŠนใชใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€`body`ใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ -ใ‚ขใƒ—ใƒช้–‹็™บไธญใซๆœฌไฝ“ใฎใƒญใ‚ฐใ‚’ๅ–ใฃใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใŸใ‚Šใ€ใƒฆใƒผใ‚ถใƒผใซ่ฟ”ใ—ใŸใ‚Šใชใฉใซไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ‚ขใƒ—ใƒช้–‹็™บไธญใซใƒœใƒ‡ใ‚ฃใฎใƒญใ‚ฐใ‚’ๅ–ใฃใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใŸใ‚Šใ€ใƒฆใƒผใ‚ถใƒผใซ่ฟ”ใ—ใŸใ‚Šใชใฉใซไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/handling_errors/tutorial005.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} ใ“ใ“ใงใ€ไปฅไธ‹ใฎใ‚ˆใ†ใช็„กๅŠนใช้ …็›ฎใ‚’้€ไฟกใ—ใฆใฟใฆใใ ใ•ใ„: @@ -207,7 +196,7 @@ path -> item_id ๅ—ไฟกใ—ใŸใƒœใƒ‡ใ‚ฃใ‚’ๅซใ‚€ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใงใ‚ใ‚‹ใ“ใจใ‚’็คบใ™ใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: -```JSON hl_lines="12 13 14 15" +```JSON hl_lines="12-15" { "detail": [ { @@ -226,36 +215,30 @@ path -> item_id } ``` -#### FastAPIใฎ`HTTPException`ใจStarletteใฎ`HTTPException` +#### FastAPIใฎ`HTTPException`ใจStarletteใฎ`HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } **FastAPI**ใฏ็‹ฌ่‡ชใฎ`HTTPException`ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ -ใพใŸใ€ **FastAPI**ใฎใ‚จใƒฉใƒผใ‚ฏใƒฉใ‚น`HTTPException`ใฏStarletteใฎใ‚จใƒฉใƒผใ‚ฏใƒฉใ‚น`HTTPException`ใ‚’็ถ™ๆ‰ฟใ—ใฆใ„ใพใ™ใ€‚ - -ๅ”ฏไธ€ใฎ้•ใ„ใฏใ€**FastAPI** ใฎ`HTTPException`ใฏใƒฌใ‚นใƒใƒณใ‚นใซๅซใพใ‚Œใ‚‹ใƒ˜ใƒƒใƒ€ใ‚’่ฟฝๅŠ ใงใใ‚‹ใ“ใจใงใ™ใ€‚ +ใพใŸใ€ **FastAPI**ใฎ`HTTPException`ใ‚จใƒฉใƒผใ‚ฏใƒฉใ‚นใฏStarletteใฎ`HTTPException`ใ‚จใƒฉใƒผใ‚ฏใƒฉใ‚นใ‚’็ถ™ๆ‰ฟใ—ใฆใ„ใพใ™ใ€‚ -ใ“ใ‚ŒใฏOAuth 2.0ใจใ„ใใคใ‹ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใฎใŸใ‚ใซๅ†…้ƒจ็š„ใซๅฟ…่ฆใจใ•ใ‚Œใ€ไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +ๅ”ฏไธ€ใฎ้•ใ„ใฏใ€**FastAPI** ใฎ`HTTPException`ใฏ`detail`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซJSONใซๅค‰ๆ›ๅฏ่ƒฝใชไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใ‚’ๅ—ใ‘ไป˜ใ‘ใ‚‹ใฎใซๅฏพใ—ใ€Starletteใฎ`HTTPException`ใฏๆ–‡ๅญ—ๅˆ—ใฎใฟใ‚’ๅ—ใ‘ไป˜ใ‘ใ‚‹ใ“ใจใงใ™ใ€‚ ใใฎใŸใ‚ใ€ใ‚ณใƒผใƒ‰ๅ†…ใงใฏ้€šๅธธ้€šใ‚Š **FastAPI** ใฎ`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›็ถšใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’็™ป้Œฒใ™ใ‚‹้š›ใซใฏใ€Starletteใฎ`HTTPException`ใ‚’็™ป้Œฒใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’็™ป้Œฒใ™ใ‚‹้š›ใซใฏใ€Starletteใฎ`HTTPException`ใซๅฏพใ—ใฆ็™ป้Œฒใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใ“ใ‚Œใซใ‚ˆใ‚Šใ€Starletteใฎๅ†…้ƒจใ‚ณใƒผใƒ‰ใ‚„Starletteใฎๆ‹กๅผตๆฉŸ่ƒฝใ‚„ใƒ—ใƒฉใ‚ฐใ‚คใƒณใฎไธ€้ƒจใŒ`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›ใŸๅ ดๅˆใ€ใƒใƒณใƒ‰ใƒฉใŒใใ‚Œใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใฆๅ‡ฆ็†ใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€Starletteใฎๅ†…้ƒจใ‚ณใƒผใƒ‰ใ‚„Starletteใฎๆ‹กๅผตๆฉŸ่ƒฝใ‚„ใƒ—ใƒฉใ‚ฐใ‚คใƒณใฎไธ€้ƒจใŒStarletteใฎ`HTTPException`ใ‚’็™บ็”Ÿใ•ใ›ใŸๅ ดๅˆใ€ใƒใƒณใƒ‰ใƒฉใŒใใ‚Œใ‚’ใ‚ญใƒฃใƒƒใƒใ—ใฆๅ‡ฆ็†ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ -ไปฅไธ‹ใฎไพ‹ใงใฏใ€ๅŒใ˜ใ‚ณใƒผใƒ‰ๅ†…ใงไธกๆ–นใฎ`HTTPException`ใ‚’ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใซใ€Starletteใฎไพ‹ๅค–ใฎๅๅ‰ใ‚’`StarletteHTTPException`ใซๅค‰ๆ›ดใ—ใฆใ„ใพใ™: +ใ“ใฎไพ‹ใงใฏใ€ๅŒใ˜ใ‚ณใƒผใƒ‰ๅ†…ใงไธกๆ–นใฎ`HTTPException`ใ‚’ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใซใ€Starletteใฎไพ‹ๅค–ใ‚’`StarletteHTTPException`ใซใƒชใƒใƒผใƒ ใ—ใฆใ„ใพใ™: ```Python from starlette.exceptions import HTTPException as StarletteHTTPException ``` -### **FastAPI** ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎๅ†ๅˆฉ็”จ - -ใพใŸใ€ไฝ•ใ‚‰ใ‹ใฎๆ–นๆณ•ใงไพ‹ๅค–ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใŒใ€**FastAPI** ใ‹ใ‚‰ๅŒใ˜ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ - -ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’`fastapi.exception_handlers`ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใ—ใฆๅ†ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +### **FastAPI** ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใฎๅ†ๅˆฉ็”จ { #reuse-fastapis-exception-handlers } -{* ../../docs_src/handling_errors/tutorial006.py hl[2,3,4,5,15,21] *} +**FastAPI** ใ‹ใ‚‰ๅŒใ˜ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใจไธ€็ท’ใซไพ‹ๅค–ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใฏใ€`fastapi.exception_handlers`ใ‹ใ‚‰ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆๅ†ๅˆฉ็”จใงใใพใ™: -ใ“ใฎไพ‹ใงใฏใ€้žๅธธใซ่กจ็พๅŠ›ใฎใ‚ใ‚‹ใƒกใƒƒใ‚ปใƒผใ‚ธใงใ‚จใƒฉใƒผใ‚’`print`ใ—ใฆใ„ใพใ™ใ€‚ +{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} -ใ—ใ‹ใ—ใ€ไพ‹ๅค–ใ‚’ไฝฟ็”จใ—ใฆใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’ๅ†ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใ‚‹ใจใ„ใ†ใ“ใจใŒ็†่งฃใงใใพใ™ใ€‚ +ใ“ใฎไพ‹ใงใฏใ€้žๅธธใซ่กจ็พๅŠ›ใฎใ‚ใ‚‹ใƒกใƒƒใ‚ปใƒผใ‚ธใงใ‚จใƒฉใƒผใ‚’`print`ใ—ใฆใ„ใ‚‹ใ ใ‘ใงใ™ใŒใ€่ฆ็‚นใฏ็†่งฃใงใใ‚‹ใฏใšใงใ™ใ€‚ไพ‹ๅค–ใ‚’ไฝฟ็”จใ—ใ€ใใฎๅพŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใ‚’ๅ†ๅˆฉ็”จใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/header-params.md b/docs/ja/docs/tutorial/header-params.md index ac89afbdba..1916baf613 100644 --- a/docs/ja/docs/tutorial/header-params.md +++ b/docs/ja/docs/tutorial/header-params.md @@ -1,20 +1,20 @@ -# ใƒ˜ใƒƒใƒ€ใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ +# ใƒ˜ใƒƒใƒ€ใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #header-parameters } ใƒ˜ใƒƒใƒ€ใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€`Query`ใ‚„`Path`ใ€`Cookie`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซๅฎš็พฉใงใใพใ™ใ€‚ -## `Header`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ +## `Header`ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #import-header } ใพใšใ€`Header`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/header_params/tutorial001.py hl[3] *} +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} -## `Header`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎฃ่จ€ +## `Header`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎฃ่จ€ { #declare-header-parameters } ๆฌกใซใ€`Path`ใ‚„`Query`ใ€`Cookie`ใจๅŒใ˜ๆง‹้€ ใ‚’็”จใ„ใฆใƒ˜ใƒƒใƒ€ใƒผใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ -ๆœ€ๅˆใฎๅ€คใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ€่ฟฝๅŠ ใฎๆคœ่จผใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ๆณจ้‡ˆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ™ในใฆๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใซๅŠ ใˆใฆใ€่ฟฝๅŠ ใฎๆคœ่จผใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ๆณจ้‡ˆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ™ในใฆๅฎš็พฉใงใใพใ™: -{* ../../docs_src/header_params/tutorial001.py hl[9] *} +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -30,23 +30,23 @@ /// -## ่‡ชๅ‹•ๅค‰ๆ› +## ่‡ชๅ‹•ๅค‰ๆ› { #automatic-conversion } `Header`ใฏ`Path`ใ‚„`Query`ใ€`Cookie`ใŒๆไพ›ใ™ใ‚‹ๆฉŸ่ƒฝใซๅŠ ใˆใ€ๅฐ‘ใ—ใ ใ‘่ฟฝๅŠ ใฎๆฉŸ่ƒฝใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ -ใปใจใ‚“ใฉใฎๆจ™ๆบ–ใƒ˜ใƒƒใƒ€ใƒผใฏใ€ใ€Œใƒžใ‚คใƒŠใ‚น่จ˜ๅทใ€๏ผˆ`-`๏ผ‰ใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใ‚‹ใ€Œใƒใ‚คใƒ•ใƒณใ€ใงๅŒบๅˆ‡ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ +ใปใจใ‚“ใฉใฎๆจ™ๆบ–ใƒ˜ใƒƒใƒ€ใƒผใฏใ€ใ€Œใƒžใ‚คใƒŠใ‚น่จ˜ๅทใ€๏ผˆ`-`๏ผ‰ใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใ‚‹ใ€Œใƒใ‚คใƒ•ใƒณใ€ๆ–‡ๅญ—ใงๅŒบๅˆ‡ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ ใ—ใ‹ใ—ใ€`user-agent`ใฎใ‚ˆใ†ใชๅค‰ๆ•ฐใฏPythonใงใฏ็„กๅŠนใงใ™ใ€‚ -ใใฎใŸใ‚ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€`Header`ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๆ–‡ๅญ—ใ‚’ใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ข๏ผˆ`_`๏ผ‰ใ‹ใ‚‰ใƒใ‚คใƒ•ใƒณ๏ผˆ`-`๏ผ‰ใซๅค‰ๆ›ใ—ใฆใ€ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆŠฝๅ‡บใ—ใฆๆ–‡ๆ›ธๅŒ–ใ—ใพใ™ใ€‚ +ใใฎใŸใ‚ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€`Header`ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟๅใฎๆ–‡ๅญ—ใ‚’ใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ข๏ผˆ`_`๏ผ‰ใ‹ใ‚‰ใƒใ‚คใƒ•ใƒณ๏ผˆ`-`๏ผ‰ใซๅค‰ๆ›ใ—ใฆใ€ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆŠฝๅ‡บใ—ใฆๆ–‡ๆ›ธๅŒ–ใ—ใพใ™ใ€‚ ใพใŸใ€HTTPใƒ˜ใƒƒใƒ€ใฏๅคงๆ–‡ๅญ—ๅฐๆ–‡ๅญ—ใ‚’ๅŒบๅˆฅใ—ใชใ„ใฎใงใ€Pythonใฎๆจ™ๆบ–ใ‚นใ‚ฟใ‚คใƒซ๏ผˆๅˆฅๅใ€Œใ‚นใƒใƒผใ‚ฏใ‚ฑใƒผใ‚นใ€๏ผ‰ใงๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใใฎใŸใ‚ใ€`User_Agent`ใชใฉใฎใ‚ˆใ†ใซๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซใ™ใ‚‹ๅฟ…่ฆใฏใชใใ€้€šๅธธใฎPythonใ‚ณใƒผใƒ‰ใจๅŒใ˜ใ‚ˆใ†ใซ`user_agent`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใ‚‚ใ—ใชใ‚“ใ‚‰ใ‹ใฎ็†็”ฑใงใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขใ‹ใ‚‰ใƒใ‚คใƒ•ใƒณใธใฎ่‡ชๅ‹•ๅค‰ๆ›ใ‚’็„กๅŠนใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€`Header`ใฎ`convert_underscores`ใซ`False`ใ‚’่จญๅฎšใ—ใฆใใ ใ•ใ„: +ใ‚‚ใ—ใชใ‚“ใ‚‰ใ‹ใฎ็†็”ฑใงใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขใ‹ใ‚‰ใƒใ‚คใƒ•ใƒณใธใฎ่‡ชๅ‹•ๅค‰ๆ›ใ‚’็„กๅŠนใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€`Header`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ`convert_underscores`ใ‚’`False`ใซ่จญๅฎšใ—ใฆใใ ใ•ใ„: -{* ../../docs_src/header_params/tutorial002.py hl[9] *} +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} /// warning | ๆณจๆ„ @@ -54,26 +54,26 @@ /// -## ใƒ˜ใƒƒใƒ€ใƒผใฎ้‡่ค‡ +## ใƒ˜ใƒƒใƒ€ใƒผใฎ้‡่ค‡ { #duplicate-headers } ๅ—ไฟกใ—ใŸใƒ˜ใƒƒใƒ€ใƒผใŒ้‡่ค‡ใ™ใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใคใพใ‚Šใ€ๅŒใ˜ใƒ˜ใƒƒใƒ€ใƒผใง่ค‡ๆ•ฐใฎๅ€คใ‚’ๆŒใคใจใ„ใ†ใ“ใจใงใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎๅ ดๅˆใ€ใƒชใ‚นใƒˆใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ—ใฆๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎๅ ดๅˆใ€ๅž‹ๅฎฃ่จ€ใงใƒชใ‚นใƒˆใ‚’ไฝฟ็”จใ—ใฆๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ้‡่ค‡ใ—ใŸใƒ˜ใƒƒใƒ€ใƒผใฎใ™ในใฆใฎๅ€คใ‚’Pythonใฎ`list`ใจใ—ใฆๅ—ใ‘ๅ–ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€่ค‡ๆ•ฐๅ›žๅ‡บ็พใ™ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹`X-Token`ใฎใƒ˜ใƒƒใƒ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใใ“ใจใŒใงใใพใ™: -{* ../../docs_src/header_params/tutorial003.py hl[9] *} +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} -ใ‚‚ใ—ใ€ใใฎ*path operation*ใง้€šไฟกใ™ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎใ‚ˆใ†ใซ๏ผ’ใคใฎHTTPใƒ˜ใƒƒใƒ€ใƒผใ‚’้€ไฟกใ—ใพใ™: +ใใฎ*path operation*ใจ้€šไฟกใ™ใ‚‹้š›ใซใ€ๆฌกใฎใ‚ˆใ†ใซ2ใคใฎHTTPใƒ˜ใƒƒใƒ€ใƒผใ‚’้€ไฟกใ™ใ‚‹ๅ ดๅˆ: ``` X-Token: foo X-Token: bar ``` -ใ“ใฎใƒฌใ‚นใƒใƒณใ‚นใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: +ใƒฌใ‚นใƒใƒณใ‚นใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: ```JSON { @@ -84,8 +84,8 @@ X-Token: bar } ``` -## ใพใจใ‚ +## ใพใจใ‚ { #recap } -ใƒ˜ใƒƒใƒ€ใƒผใฏ`Header`ใงๅฎฃ่จ€ใ—ใ€`Query`ใ‚„`Path`ใ€`Cookie`ใจๅŒใ˜ใƒ‘ใ‚ฟใƒผใƒณใ‚’ไฝฟ็”จใ™ใ‚‹ใ€‚ +ใƒ˜ใƒƒใƒ€ใƒผใฏ`Header`ใงๅฎฃ่จ€ใ—ใ€`Query`ใ‚„`Path`ใ€`Cookie`ใจๅŒใ˜ๅ…ฑ้€šใƒ‘ใ‚ฟใƒผใƒณใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ ใพใŸใ€ๅค‰ๆ•ฐใฎใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขใ‚’ๆฐ—ใซใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚**FastAPI** ใŒใใ‚Œใ‚‰ใฎๅค‰ๆ›ใ‚’ใ™ในใฆๅ–ใ‚ŠๆŒใฃใฆใใ‚Œใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/index.md b/docs/ja/docs/tutorial/index.md index 87d3751fd9..d298abc62d 100644 --- a/docs/ja/docs/tutorial/index.md +++ b/docs/ja/docs/tutorial/index.md @@ -1,83 +1,95 @@ -# ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ +# ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ { #tutorial-user-guide } -ใ“ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใฏ**FastAPI**ใฎใปใผใ™ในใฆใฎๆฉŸ่ƒฝใฎไฝฟใ„ๆ–นใ‚’ๆฎต้šŽ็š„ใซ็ดนไป‹ใ—ใพใ™ใ€‚ +ใ“ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏใ€**FastAPI**ใฎใปใจใ‚“ใฉใฎๆฉŸ่ƒฝใ‚’ไฝฟใ†ๆ–นๆณ•ใ‚’ๆฎต้šŽ็š„ใซ็ดนไป‹ใ—ใพใ™ใ€‚ -ๅ„ใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏๅ‰ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’่ธใพใˆใŸๅ†…ๅฎนใซใชใฃใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใƒˆใƒ”ใƒƒใ‚ฏใ”ใจใซๅˆ†ๅ‰ฒใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€็‰นๅฎšใฎAPIใฎ่ฆๆฑ‚ใ‚’ๆบ€ใŸใ™ใ‚ˆใ†ใชใƒˆใƒ”ใƒƒใ‚ฏใซ็›ดๆŽฅใŸใฉใ‚Š็€ใ‘ใ‚‹ใ‚ˆใ†ใซใชใฃใฆใ„ใพใ™ใ€‚ +ๅ„ใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏๅ‰ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’่ธใพใˆใŸๅ†…ๅฎนใซใชใฃใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใƒˆใƒ”ใƒƒใ‚ฏใ”ใจใซๅˆ†ๅ‰ฒใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€็‰นๅฎšใฎAPIใฎใƒ‹ใƒผใ‚บใ‚’ๆบ€ใŸใ™ใŸใ‚ใซใ€ไปปๆ„ใฎ็‰นๅฎšใฎใƒˆใƒ”ใƒƒใ‚ฏใซ็›ดๆŽฅ้€ฒใ‚ใ‚‹ใ‚ˆใ†ใซใชใฃใฆใ„ใพใ™ใ€‚ -ใพใŸใ€ๅฐ†ๆฅ็š„ใซใƒชใƒ•ใ‚กใƒฌใƒณใ‚นใจใ—ใฆๆฉŸ่ƒฝใ™ใ‚‹ใ‚ˆใ†ใซๆง‹็ฏ‰ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +ใพใŸใ€ๅฐ†ๆฅ็š„ใซใƒชใƒ•ใ‚กใƒฌใƒณใ‚นใจใ—ใฆๆฉŸ่ƒฝใ™ใ‚‹ใ‚ˆใ†ใซๆง‹็ฏ‰ใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ๅพŒใงๆˆปใฃใฆใใฆๅฟ…่ฆใชใ‚‚ใฎใ‚’ๆญฃ็ขบใซ็ขบ่ชใงใใพใ™ใ€‚ -ๅพ“ใฃใฆใ€ๅพŒใงใ“ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใซๆˆปใฃใฆใใฆๅฟ…่ฆใชใ‚‚ใฎใ‚’็ขบ่ชใงใใพใ™ใ€‚ - -## ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ +## ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ { #run-the-code } ใ™ในใฆใฎใ‚ณใƒผใƒ‰ใƒ–ใƒญใƒƒใ‚ฏใ‚’ใ‚ณใƒ”ใƒผใ—ใฆ็›ดๆŽฅไฝฟ็”จใงใใพใ™๏ผˆๅฎŸ้š›ใซใƒ†ใ‚นใƒˆใ•ใ‚ŒใŸPythonใƒ•ใ‚กใ‚คใƒซใงใ™๏ผ‰ใ€‚ -ใ„ใšใ‚Œใ‹ใฎไพ‹ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใซใฏใ€ใ‚ณใƒผใƒ‰ใ‚’ `main.py`ใƒ•ใ‚กใ‚คใƒซใซใ‚ณใƒ”ใƒผใ—ใ€` uvicorn`ใ‚’ๆฌกใฎใ‚ˆใ†ใซ่ตทๅ‹•ใ—ใพใ™: +ใ„ใšใ‚Œใ‹ใฎไพ‹ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใซใฏใ€ใ‚ณใƒผใƒ‰ใ‚’ `main.py`ใƒ•ใ‚กใ‚คใƒซใซใ‚ณใƒ”ใƒผใ—ใ€ๆฌกใฎใ‚ˆใ†ใซ `fastapi dev` ใ‚’่ตทๅ‹•ใ—ใพใ™:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-ใ‚ณใƒผใƒ‰ใ‚’่จ˜่ฟฐใพใŸใฏใ‚ณใƒ”ใƒผใ—ใ€็ทจ้›†ใ—ใฆใƒญใƒผใ‚ซใƒซใงๅฎŸ่กŒใ™ใ‚‹ใ“ใจใ‚’**ๅผทใใŠๅ‹งใ‚ใ—ใพใ™**ใ€‚ +ใ‚ณใƒผใƒ‰ใ‚’่จ˜่ฟฐใพใŸใฏใ‚ณใƒ”ใƒผใ—ใ€็ทจ้›†ใ—ใฆใƒญใƒผใ‚ซใƒซใงๅฎŸ่กŒใ™ใ‚‹ใ“ใจใ‚’**ๅผทใๆŽจๅฅจใ—ใพใ™**ใ€‚ -ใพใŸใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใงไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ๆ›ธใๅฟ…่ฆใฎใ‚ใ‚‹ใ‚ณใƒผใƒ‰ใฎๅฐ‘ใชใ•ใ€ใ™ในใฆใฎๅž‹ใƒใ‚งใƒƒใ‚ฏใ€่‡ชๅ‹•่ฃœๅฎŒใชใฉใฎFastAPIใฎๅˆฉ็‚นใ‚’ๅฎŸๆ„Ÿใงใใพใ™ใ€‚ +ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใงไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ๆ›ธใๅฟ…่ฆใฎใ‚ใ‚‹ใ‚ณใƒผใƒ‰ใฎๅฐ‘ใชใ•ใ€ใ™ในใฆใฎๅž‹ใƒใ‚งใƒƒใ‚ฏใ€่‡ชๅ‹•่ฃœๅฎŒใชใฉใ€FastAPIใฎๅˆฉ็‚นใ‚’ๆœฌๅฝ“ใซๅฎŸๆ„Ÿใงใใพใ™ใ€‚ --- -## FastAPIใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ +## FastAPIใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ { #install-fastapi } ๆœ€ๅˆใฎใ‚นใƒ†ใƒƒใƒ—ใฏใ€FastAPIใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใ™ใ€‚ -ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใฎใŸใ‚ใซใ€ใ™ในใฆใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใฎไพๅญ˜้–ขไฟ‚ใจๆฉŸ่ƒฝใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใ„ใจใ: +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ใใ‚Œใ‹ใ‚‰ **FastAPIใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซ** ใ—ใฆใใ ใ•ใ„:
```console -$ pip install "fastapi[all]" +$ pip install "fastapi[standard]" ---> 100% ```
-...ใ“ใ‚Œใซใฏใ€ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ‚ตใƒผใƒใƒผใจใ—ใฆไฝฟ็”จใงใใ‚‹ `uvicorn`ใ‚‚ๅซใพใ‚Œใพใ™ใ€‚ - /// note | ๅ‚™่€ƒ -ใƒ‘ใƒผใƒ„ๆฏŽใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใ“ใจใ‚‚ๅฏ่ƒฝใงใ™ใ€‚ - -ไปฅไธ‹ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆœฌ็•ช็’ฐๅขƒใซใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹้š›ใซ่กŒใ†ใงใ‚ใ‚ใ†ใ‚‚ใฎใงใ™: +`pip install "fastapi[standard]"` ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจใ€`fastapi-cloud-cli` ใ‚’ๅซใ‚€ใ„ใใคใ‹ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚ชใƒ—ใ‚ทใƒงใƒณๆจ™ๆบ–ไพๅญ˜้–ขไฟ‚ใŒไป˜ๅฑžใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€FastAPI Cloud ใซใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ -``` -pip install fastapi -``` - -ใพใŸใ€ใ‚ตใƒผใƒใƒผใจใ—ใฆๅ‹•ไฝœใ™ใ‚‹ใ‚ˆใ†ใซ`uvicorn` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™: - -``` -pip install "uvicorn[standard]" -``` +ใ“ใ‚Œใ‚‰ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณไพๅญ˜้–ขไฟ‚ใŒไธ่ฆใชๅ ดๅˆใฏใ€ไปฃใ‚ใ‚Šใซ `pip install fastapi` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ -ใใ—ใฆใ€ไฝฟ็”จใ—ใŸใ„ไพๅญ˜้–ขไฟ‚ใ‚’ใใ‚Œใžใ‚ŒๅŒๆง˜ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ +ๆจ™ๆบ–ไพๅญ˜้–ขไฟ‚ใฏใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใ„ใŒ `fastapi-cloud-cli` ใฏไธ่ฆใชๅ ดๅˆใฏใ€`pip install "fastapi[standard-no-fastapi-cloud-cli]"` ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ /// -## ้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ +## ้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ { #advanced-user-guide } -**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใ‚‚ใ‚ใ‚Šใ€**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใฎๅพŒใง่ชญใ‚€ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใฎ **ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใฎๅพŒใงใ€ๅพŒใ‹ใ‚‰่ชญใ‚ใ‚‹ **้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใฏ**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใซๅŸบใฅใ„ใฆใŠใ‚Šใ€ๅŒใ˜ๆฆ‚ๅฟตใ‚’ไฝฟ็”จใ—ใ€ใ„ใใคใ‹ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’็ดนไป‹ใ—ใฆใ„ใพใ™ใ€‚ +**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใฏๆœฌใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใŠใ‚Šใ€ๅŒใ˜ๆฆ‚ๅฟตใ‚’ไฝฟ็”จใ—ใ€ใ„ใใคใ‹ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ๆ•™ใˆใพใ™ใ€‚ -ใŸใ ใ—ใ€ๆœ€ๅˆใซ**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**๏ผˆ็พๅœจ่ชญใ‚“ใงใ„ใ‚‹ๅ†…ๅฎน๏ผ‰ใ‚’ใŠ่ชญใฟใใ ใ•ใ„ใ€‚ +ใŸใ ใ—ใ€ๆœ€ๅˆใซ **ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**๏ผˆไปŠ่ชญใ‚“ใงใ„ใ‚‹ๅ†…ๅฎน๏ผ‰ใ‚’ใŠ่ชญใฟใใ ใ•ใ„ใ€‚ -**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ-ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใ ใ‘ใงๅฎŒๅ…จใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ๅŠ ใˆใฆใ€**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใฎไธญใ‹ใ‚‰ใƒ‹ใƒผใ‚บใซๅฟœใ˜ใŸใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ไฝฟ็”จใ—ใฆใ€ๆง˜ใ€…ใชๆ‹กๅผตใŒๅฏ่ƒฝใงใ™ใ€‚ +**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใ ใ‘ใงๅฎŒๅ…จใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹็ฏ‰ใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€ใใฎๅพŒใƒ‹ใƒผใ‚บใซๅฟœใ˜ใฆใ€**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใฎ่ฟฝๅŠ ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฎใ„ใใคใ‹ใ‚’ไฝฟใฃใฆใ€ใ•ใพใ–ใพใชๆ–นๆณ•ใงๆ‹กๅผตใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/metadata.md b/docs/ja/docs/tutorial/metadata.md index b93dedcb91..0ffb8f3505 100644 --- a/docs/ja/docs/tutorial/metadata.md +++ b/docs/ja/docs/tutorial/metadata.md @@ -1,47 +1,66 @@ -# ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURL +# ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURL { #metadata-and-docs-urls } -**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ„ใใคใ‹ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎ่จญๅฎšใ‚’ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใงใใพใ™ใ€‚ +**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ„ใใคใ‹ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ่จญๅฎšใ‚’ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใงใใพใ™ใ€‚ -## ใ‚ฟใ‚คใƒˆใƒซใ€่ชฌๆ˜Žๆ–‡ใ€ใƒใƒผใ‚ธใƒงใƒณ +## APIใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ { #metadata-for-api } -ไปฅไธ‹ใ‚’่จญๅฎšใงใใพใ™: +OpenAPIไป•ๆง˜ใŠใ‚ˆใณ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงไฝฟ็”จใ•ใ‚Œใ‚‹ๆฌกใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’่จญๅฎšใงใใพใ™: -* **ใ‚ฟใ‚คใƒˆใƒซ**: OpenAPIใŠใ‚ˆใณ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงAPIใฎใ‚ฟใ‚คใƒˆใƒซ/ๅๅ‰ใจใ—ใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ€‚ -* **่ชฌๆ˜Žๆ–‡**: OpenAPIใŠใ‚ˆใณ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงใฎAPIใฎ่ชฌๆ˜Žๆ–‡ใ€‚ -* **ใƒใƒผใ‚ธใƒงใƒณ**: APIใฎใƒใƒผใ‚ธใƒงใƒณใ€‚ไพ‹: `v2` ใพใŸใฏ `2.5.0`ใ€‚ - *ใŸใจใˆใฐใ€ไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใ€OpenAPIใ‚‚ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใซไพฟๅˆฉใงใ™ใ€‚ +| ใƒ‘ใƒฉใƒกใƒผใ‚ฟ | ๅž‹ | ่ชฌๆ˜Ž | +|------------|------|-------------| +| `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` ใงใ™ใ€‚ | +| `terms_of_service` | `str` | APIใฎๅˆฉ็”จ่ฆ็ด„ใธใฎURLใงใ™ใ€‚ๆŒ‡ๅฎšใ™ใ‚‹ๅ ดๅˆใ€URLใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ | +| `contact` | `dict` | ๅ…ฌ้–‹ใ•ใ‚Œใ‚‹APIใฎ้€ฃ็ตกๅ…ˆๆƒ…ๅ ฑใงใ™ใ€‚่ค‡ๆ•ฐใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚
contact fields
ParameterTypeDescription
namestr้€ฃ็ตกๅ…ˆใฎๅ€‹ไบบ/็ต„็น”ใ‚’่ญ˜ๅˆฅใ™ใ‚‹ๅๅ‰ใงใ™ใ€‚
urlstr้€ฃ็ตกๅ…ˆๆƒ…ๅ ฑใ‚’ๆŒ‡ใ™URLใงใ™ใ€‚URLๅฝขๅผใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
emailstr้€ฃ็ตกๅ…ˆใฎๅ€‹ไบบ/็ต„็น”ใฎใƒกใƒผใƒซใ‚ขใƒ‰ใƒฌใ‚นใงใ™ใ€‚ใƒกใƒผใƒซใ‚ขใƒ‰ใƒฌใ‚นๅฝขๅผใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
| +| `license_info` | `dict` | ๅ…ฌ้–‹ใ•ใ‚Œใ‚‹APIใฎใƒฉใ‚คใ‚ปใƒณใ‚นๆƒ…ๅ ฑใงใ™ใ€‚่ค‡ๆ•ฐใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚
license_info fields
ParameterTypeDescription
namestrๅฟ…้ ˆ๏ผˆlicense_info ใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆ๏ผ‰ใ€‚APIใซไฝฟ็”จใ•ใ‚Œใ‚‹ใƒฉใ‚คใ‚ปใƒณใ‚นๅใงใ™ใ€‚
identifierstrAPIใฎ SPDX ใƒฉใ‚คใ‚ปใƒณใ‚นๅผใงใ™ใ€‚identifier ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏ url ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจๅŒๆ™‚ใซๆŒ‡ๅฎšใงใใพใ›ใ‚“ใ€‚ OpenAPI 3.1.0ใ€FastAPI 0.99.0 ไปฅ้™ใงๅˆฉ็”จใงใใพใ™ใ€‚
urlstrAPIใซไฝฟ็”จใ•ใ‚Œใ‚‹ใƒฉใ‚คใ‚ปใƒณใ‚นใธใฎURLใงใ™ใ€‚URLๅฝขๅผใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
| -ใ“ใ‚Œใ‚‰ใ‚’่จญๅฎšใ™ใ‚‹ใซใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `title`ใ€`description`ใ€`version` ใ‚’ไฝฟ็”จใ—ใพใ™: +ไปฅไธ‹ใฎใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™: -{* ../../docs_src/metadata/tutorial001.py hl[4:6] *} +{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} -ใ“ใฎ่จญๅฎšใงใฏใ€่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏไปฅไธ‹ใฎๆง˜ใซใชใ‚Šใพใ™: +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`description` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซใฏMarkdownใ‚’ๆ›ธใ‘ใฆใ€ๅ‡บๅŠ›ใงใฏใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใ•ใ‚Œใพใ™ใ€‚ + +/// + +ใ“ใฎ่จญๅฎšใงใฏใ€่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -## ใ‚ฟใ‚ฐใฎใŸใ‚ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ +## ใƒฉใ‚คใ‚ปใƒณใ‚น่ญ˜ๅˆฅๅญ { #license-identifier } + +OpenAPI 3.1.0 ใŠใ‚ˆใณ FastAPI 0.99.0 ไปฅ้™ใงใฏใ€`license_info` ใ‚’ `url` ใฎไปฃใ‚ใ‚Šใซ `identifier` ใง่จญๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ไพ‹: + +{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} + +## ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ { #metadata-for-tags } -ใ•ใ‚‰ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `openapi_tags` ใ‚’ไฝฟใ†ใจใ€path operations ใ‚’ใ‚ฐใƒซใƒผใƒ—ๅˆ†ใ‘ใ™ใ‚‹ใŸใ‚ใฎ่ค‡ๆ•ฐใฎใ‚ฟใ‚ฐใซ้–ขใ™ใ‚‹ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `openapi_tags` ใ‚’ไฝฟใ†ใจใ€path operation ใ‚’ใ‚ฐใƒซใƒผใƒ—ๅˆ†ใ‘ใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ๅ„ใ‚ฟใ‚ฐใซ่ฟฝๅŠ ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ -ใใ‚Œใžใ‚Œใฎใ‚ฟใ‚ฐๆฏŽใซใฒใจใคใฎ่พžๆ›ธใ‚’ๅซใ‚€ใƒชใ‚นใƒˆใ‚’ใจใ‚Šใพใ™ใ€‚ +ใใ‚Œใžใ‚Œใฎใ‚ฟใ‚ฐใ”ใจใซ1ใคใฎ่พžๆ›ธใ‚’ๅซใ‚€ใƒชใ‚นใƒˆใ‚’ๅ–ใ‚Šใพใ™ใ€‚ -ใใ‚Œใžใ‚Œใฎ่พžๆ›ธใฏไปฅไธ‹ใ‚’ใ‚‚ใคใ“ใจใŒใงใใพใ™: +ใใ‚Œใžใ‚Œใฎ่พžๆ›ธใฏไปฅไธ‹ใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™: -* `name` (**ๅฟ…้ ˆ**): *path operations* ใŠใ‚ˆใณ `APIRouter` ใฎ `tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใงไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ฟใ‚ฐๅใงใ‚ใ‚‹ `str`ใ€‚ -* `description`: ใ‚ฟใ‚ฐใฎ็ฐกๅ˜ใช่ชฌๆ˜Žๆ–‡ใงใ‚ใ‚‹ `str`ใ€‚ Markdownใง่จ˜่ฟฐใงใใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ -* `externalDocs`: ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชฌๆ˜Žใ™ใ‚‹ใŸใ‚ใฎ `dict`: - * `description`: ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ฐกๅ˜ใช่ชฌๆ˜Žๆ–‡ใงใ‚ใ‚‹ `str`ใ€‚ - * `url` (**ๅฟ…้ ˆ**): ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURLใงใ‚ใ‚‹ `str`ใ€‚ +* `name` (**ๅฟ…้ ˆ**): *path operation* ใŠใ‚ˆใณ `APIRouter` ใฎ `tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ฟใ‚ฐๅใฎ `str`ใ€‚ +* `description`: ใ‚ฟใ‚ฐใฎ็Ÿญใ„่ชฌๆ˜Žใฎ `str`ใ€‚Markdownใ‚’ๅซใ‚ใ‚‰ใ‚Œใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +* `externalDocs`: ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชฌๆ˜Žใ™ใ‚‹ `dict`ใ€‚ไปฅไธ‹ใ‚’ๅซใฟใพใ™: + * `description`: ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็Ÿญใ„่ชฌๆ˜Žใฎ `str`ใ€‚ + * `url` (**ๅฟ…้ ˆ**): ๅค–้ƒจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURLใฎ `str`ใ€‚ -### ใ‚ฟใ‚ฐใฎใŸใ‚ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎไฝœๆˆ +### ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎไฝœๆˆ { #create-metadata-for-tags } -`users` ใจ `items` ใฎใ‚ฟใ‚ฐใ‚’ไฝฟใฃใŸไพ‹ใงใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎ่ฟฝๅŠ ใ‚’่ฉฆใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +`users` ใจ `items` ใฎใ‚ฟใ‚ฐใ‚’ไฝฟใฃใŸไพ‹ใง่ฉฆใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -ใ‚ฟใ‚ฐใฎใŸใ‚ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ `openapi_tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆธกใ—ใพใ™ใ€‚ +ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ `openapi_tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆธกใ—ใพใ™: -{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} -่ชฌๆ˜Žๆ–‡ (description) ใฎไธญใง Markdown ใ‚’ไฝฟ็”จใงใใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใŸใจใˆใฐใ€ใ€Œloginใ€ใฏๅคชๅญ— (**login**) ใง่กจ็คบใ•ใ‚Œใ€ใ€Œfancyใ€ใฏๆ–œไฝ“ (_fancy_) ใง่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +่ชฌๆ˜ŽใฎไธญใงMarkdownใ‚’ไฝฟ็”จใงใใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใŸใจใˆใฐใ€Œloginใ€ใฏๅคชๅญ— (**login**) ใง่กจ็คบใ•ใ‚Œใ€ใ€Œfancyใ€ใฏๆ–œไฝ“ (_fancy_) ใง่กจ็คบใ•ใ‚Œใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -49,31 +68,31 @@ /// -### ่‡ชไฝœใ‚ฟใ‚ฐใฎไฝฟ็”จ +### ใ‚ฟใ‚ฐใฎไฝฟ็”จ { #use-your-tags } -`tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใžใ‚Œใฎ *path operations* (ใŠใ‚ˆใณ `APIRouter`) ใ‚’็•ฐใชใ‚‹ใ‚ฟใ‚ฐใซๅ‰ฒใ‚Šๅฝ“ใฆใพใ™: +*path operation*๏ผˆใŠใ‚ˆใณ `APIRouter`๏ผ‰ใฎ `tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใ‚‰ใ‚’็•ฐใชใ‚‹ใ‚ฟใ‚ฐใซๅ‰ฒใ‚Šๅฝ“ใฆใพใ™: -{* ../../docs_src/metadata/tutorial004.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} /// info | ๆƒ…ๅ ฑ -ใ‚ฟใ‚ฐใฎใ‚ˆใ‚Š่ฉณใ—ใ„่ชฌๆ˜Žใ‚’็Ÿฅใ‚ŠใŸใ„ๅ ดๅˆใฏ [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ +ใ‚ฟใ‚ฐใฎ่ฉณ็ดฐใฏ [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// -### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } -ใ“ใ“ใงใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ™ใ‚‹ใจใ€่ฟฝๅŠ ใ—ใŸใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใŒใ™ในใฆ่กจ็คบใ•ใ‚Œใพใ™: +ใ“ใ“ใงใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ™ใ‚‹ใจใ€่ฟฝๅŠ ใ—ใŸใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใŒใ™ในใฆ่กจ็คบใ•ใ‚Œใพใ™: -### ใ‚ฟใ‚ฐใฎ้ †็•ช +### ใ‚ฟใ‚ฐใฎ้ †็•ช { #order-of-tags } ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ่พžๆ›ธใฎ้ †ๅบใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใซ่กจ็คบใ•ใ‚Œใ‚‹้ †ๅบใฎๅฎš็พฉใซใ‚‚ใชใ‚Šใพใ™ใ€‚ -ใŸใจใˆใฐใ€`users` ใฏใ‚ขใƒซใƒ•ใ‚กใƒ™ใƒƒใƒˆ้ †ใงใฏ `items` ใฎๅพŒใซ็ถšใใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใƒชใ‚นใƒˆใฎๆœ€ๅˆใซ `users` ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ่พžๆ›ธใ‚’่ฟฝๅŠ ใ—ใŸใŸใ‚ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงใฏ `users` ใŒๅ…ˆใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +ใŸใจใˆใฐใ€`users` ใฏใ‚ขใƒซใƒ•ใ‚กใƒ™ใƒƒใƒˆ้ †ใงใฏ `items` ใฎๅพŒใซ็ถšใใพใ™ใŒใ€ใƒชใ‚นใƒˆใฎๆœ€ๅˆใฎ่พžๆ›ธใจใ—ใฆใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใ—ใŸใŸใ‚ใ€ใใ‚Œใ‚ˆใ‚Šๅ‰ใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ -## OpenAPI URL +## OpenAPI URL { #openapi-url } ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€OpenAPIใ‚นใ‚ญใƒผใƒžใฏ `/openapi.json` ใงๆไพ›ใ•ใ‚Œใพใ™ใ€‚ @@ -81,21 +100,21 @@ ใŸใจใˆใฐใ€`/api/v1/openapi.json` ใงๆไพ›ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ™ใ‚‹ใซใฏ: -{* ../../docs_src/metadata/tutorial002.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} OpenAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎŒๅ…จใซ็„กๅŠนใซใ™ใ‚‹ๅ ดๅˆใฏใ€`openapi_url=None` ใ‚’่จญๅฎšใงใใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใ‚‚็„กๅŠนใซใชใ‚Šใพใ™ใ€‚ -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURL +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎURL { #docs-urls } -ไปฅไธ‹ใฎ2ใคใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใ‚’ๆง‹็ฏ‰ใงใใพใ™: +ๅซใพใ‚Œใฆใ„ใ‚‹2ใคใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใ‚’่จญๅฎšใงใใพใ™: * **Swagger UI**: `/docs` ใงๆไพ›ใ•ใ‚Œใพใ™ใ€‚ - * URL ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟ `docs_url` ใง่จญๅฎšใงใใพใ™ใ€‚ - * `docs_url=None` ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใง็„กๅŠนใซใงใใพใ™ใ€‚ -* ReDoc: `/redoc` ใงๆไพ›ใ•ใ‚Œใพใ™ใ€‚ - * URL ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟ `redoc_url` ใง่จญๅฎšใงใใพใ™ใ€‚ - * `redoc_url=None` ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใง็„กๅŠนใซใงใใพใ™ใ€‚ + * URL ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟ `docs_url` ใง่จญๅฎšใงใใพใ™ใ€‚ + * `docs_url=None` ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใง็„กๅŠนใซใงใใพใ™ใ€‚ +* **ReDoc**: `/redoc` ใงๆไพ›ใ•ใ‚Œใพใ™ใ€‚ + * URL ใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟ `redoc_url` ใง่จญๅฎšใงใใพใ™ใ€‚ + * `redoc_url=None` ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใง็„กๅŠนใซใงใใพใ™ใ€‚ ใŸใจใˆใฐใ€`/documentation` ใงSwagger UIใŒๆไพ›ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ—ใ€ReDocใ‚’็„กๅŠนใซใ™ใ‚‹ใซใฏ: -{* ../../docs_src/metadata/tutorial003.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} diff --git a/docs/ja/docs/tutorial/middleware.md b/docs/ja/docs/tutorial/middleware.md index 539ec5b8c9..12fb57a640 100644 --- a/docs/ja/docs/tutorial/middleware.md +++ b/docs/ja/docs/tutorial/middleware.md @@ -1,4 +1,4 @@ -# ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข +# ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข { #middleware } **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ @@ -15,11 +15,11 @@ `yield` ใ‚’ไฝฟใฃใŸไพๅญ˜้–ขไฟ‚ใ‚’ใ‚‚ใคๅ ดๅˆใฏใ€็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ *ๅพŒใซ* ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ -ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ (ๅพŒ่ฟฐ) ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใใ‚Œใ‚‰ใฏๅ…จใฆใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ *ๅพŒใซ* ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ ([ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ](background-tasks.md){.internal-link target=_blank} ใ‚ปใ‚ฏใ‚ทใƒงใƒณใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ๅพŒใง็ขบ่ชใงใใพใ™) ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใใ‚Œใ‚‰ใฏๅ…จใฆใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ *ๅพŒใซ* ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ /// -## ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎไฝœๆˆ +## ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎไฝœๆˆ { #create-a-middleware } ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ไฝœๆˆใ™ใ‚‹ใซใฏใ€้–ขๆ•ฐใฎไธŠ้ƒจใงใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ `@app.middleware("http")` ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ @@ -31,13 +31,13 @@ * ๆฌกใซใ€ๅฏพๅฟœใ™ใ‚‹*path operation*ใซใ‚ˆใฃใฆ็”Ÿๆˆใ•ใ‚ŒใŸ `response` ใ‚’่ฟ”ใ—ใพใ™ใ€‚ * ใใฎๅพŒใ€`response` ใ‚’่ฟ”ใ™ๅ‰ใซใ•ใ‚‰ใซ `response` ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ -'X-'ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไฝฟ็”จใ—ใฆใ‚ซใ‚นใ‚ฟใƒ ใฎ็‹ฌ่‡ชใƒ˜ใƒƒใƒ€ใƒผใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ +ใ‚ซใ‚นใ‚ฟใƒ ใฎ็‹ฌ่‡ชใƒ˜ใƒƒใƒ€ใƒผใฏ `X-` ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไฝฟ็”จใ—ใฆ่ฟฝๅŠ ใงใใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใŸใ ใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่กจ็คบใ•ใ›ใŸใ„ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€StarletteใฎCORSใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่จ˜่ผ‰ใ•ใ‚Œใฆใ„ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `expose_headers` ใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใ‚‰ใ‚’CORS่จญๅฎšใซ่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ ([CORS (ใ‚ชใƒชใ‚ธใƒณ้–“ใƒชใ‚ฝใƒผใ‚นๅ…ฑๆœ‰)](cors.md){.internal-link target=_blank}) +ใŸใ ใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่กจ็คบใ•ใ›ใŸใ„ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€StarletteใฎCORSใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่จ˜่ผ‰ใ•ใ‚Œใฆใ„ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `expose_headers` ใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใ‚‰ใ‚’CORS่จญๅฎšใซ่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})ใ€‚ /// @@ -49,7 +49,7 @@ /// -### `response` ใฎๅ‰ๅพŒ +### `response` ใฎๅ‰ๅพŒ { #before-and-after-the-response } *path operation* ใŒ `request` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅ‰ใซใ€ `request` ใจใจใ‚‚ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ณใƒผใƒ‰ใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ @@ -57,9 +57,38 @@ ไพ‹ใˆใฐใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ‡ฆ็†ใจใƒฌใ‚นใƒใƒณใ‚นใฎ็”Ÿๆˆใซใ‹ใ‹ใฃใŸ็ง’ๆ•ฐใ‚’ๅซใ‚€ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผ `X-Process-Time` ใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} -## ใใฎไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ“ใงใฏใ€ใ“ใ‚Œใ‚‰ใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซๅฏพใ—ใฆใ‚ˆใ‚Šๆญฃ็ขบใซใชใ‚Šๅพ—ใ‚‹ใŸใ‚ใ€`time.time()` ใฎไปฃใ‚ใ‚Šใซ `time.perf_counter()` ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ ๐Ÿค“ + +/// + +## ่ค‡ๆ•ฐใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎๅฎŸ่กŒ้ †ๅบ { #multiple-middleware-execution-order } + +`@app.middleware()` ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใพใŸใฏ `app.add_middleware()` ใƒกใ‚ฝใƒƒใƒ‰ใฎใ„ใšใ‚Œใ‹ใ‚’ไฝฟใฃใฆ่ค‡ๆ•ฐใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€ๆ–ฐใ—ใ่ฟฝๅŠ ใ•ใ‚ŒใŸๅ„ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒฉใƒƒใƒ—ใ—ใ€ใ‚นใ‚ฟใƒƒใ‚ฏใ‚’ๅฝขๆˆใ—ใพใ™ใ€‚ๆœ€ๅพŒใซ่ฟฝๅŠ ใ•ใ‚ŒใŸใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒ *ๆœ€ใ‚‚ๅค–ๅด*ใ€ๆœ€ๅˆใซ่ฟฝๅŠ ใ•ใ‚ŒใŸใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒ *ๆœ€ใ‚‚ๅ†…ๅด* ใซใชใ‚Šใพใ™ใ€‚ + +ใƒชใ‚ฏใ‚จใ‚นใƒˆ็ตŒ่ทฏใงใฏใ€*ๆœ€ใ‚‚ๅค–ๅด* ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒๆœ€ๅˆใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ใƒฌใ‚นใƒใƒณใ‚น็ตŒ่ทฏใงใฏใ€ๆœ€ๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ไพ‹: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๅฎŸ่กŒ้ †ๅบใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +* **ใƒชใ‚ฏใ‚จใ‚นใƒˆ**: MiddlewareB โ†’ MiddlewareA โ†’ route + +* **ใƒฌใ‚นใƒใƒณใ‚น**: route โ†’ MiddlewareA โ†’ MiddlewareB + +ใ“ใฎใ‚นใ‚ฟใƒƒใ‚ฏๅ‹•ไฝœใซใ‚ˆใ‚Šใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒไบˆๆธฌๅฏ่ƒฝใงๅˆถๅพกใ—ใ‚„ใ™ใ„้ †ๅบใงๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ“ใจใŒไฟ่จผใ•ใ‚Œใพใ™ใ€‚ + +## ใใฎไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข { #other-middlewares } ไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ่ฉณ็ดฐใซใคใ„ใฆใฏใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰: ้ซ˜ๅบฆใชใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข](../advanced/middleware.md){.internal-link target=_blank}ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/path-operation-configuration.md b/docs/ja/docs/tutorial/path-operation-configuration.md index 0cc38cb255..eb6b6b11a5 100644 --- a/docs/ja/docs/tutorial/path-operation-configuration.md +++ b/docs/ja/docs/tutorial/path-operation-configuration.md @@ -1,14 +1,14 @@ -# Path Operationใฎ่จญๅฎš +# Path Operationใฎ่จญๅฎš { #path-operation-configuration } *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใ‚’่จญๅฎšใ™ใ‚‹ใŸใ‚ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ /// warning | ๆณจๆ„ -ใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ*path operation้–ขๆ•ฐ*ใงใฏใชใใ€*path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ็›ดๆŽฅๆธกใ•ใ‚Œใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +ใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ*path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ็›ดๆŽฅๆธกใ•ใ‚Œใ€*path operation้–ขๆ•ฐ*ใซๆธกใ•ใ‚Œใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ใƒฌใ‚นใƒใƒณใ‚นใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ +## ใƒฌใ‚นใƒใƒณใ‚นใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ { #response-status-code } *path operation*ใฎใƒฌใ‚นใƒใƒณใ‚นใงไฝฟ็”จใ™ใ‚‹๏ผˆHTTP๏ผ‰`status_code`ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -16,55 +16,65 @@ ใ—ใ‹ใ—ใ€ใใ‚Œใžใ‚Œใฎ็•ชๅทใ‚ณใƒผใƒ‰ใŒไฝ•ใฎใŸใ‚ใฎใ‚‚ใฎใ‹่ฆšใˆใฆใ„ใชใ„ๅ ดๅˆใฏใ€`status`ใฎใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆๅฎšๆ•ฐใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial001.py hl[3,17] *} +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} ใใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใฏใƒฌใ‚นใƒใƒณใ‚นใงไฝฟ็”จใ•ใ‚Œใ€OpenAPIใ‚นใ‚ญใƒผใƒžใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ /// note | ๆŠ€่ก“่ฉณ็ดฐ -ใพใŸใ€`from starlette import status`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +`from starlette import status`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ **FastAPI** ใฏ้–‹็™บ่€…ใฎๅˆฉไพฟๆ€งใ‚’่€ƒๆ…ฎใ—ใฆใ€`fastapi.status`ใจๅŒใ˜`starlette.status`ใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใ“ใ‚ŒใฏStarletteใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ /// -## ใ‚ฟใ‚ฐ +## ใ‚ฟใ‚ฐ { #tags } `tags`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’`str`ใฎ`list`๏ผˆ้€šๅธธใฏ๏ผ‘ใคใฎ`str`๏ผ‰ใจไธ€็ท’ใซๆธกใ™ใจใ€*path operation*ใซใ‚ฟใ‚ฐใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial002.py hl[17,22,27] *} +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} ใ“ใ‚Œใ‚‰ใฏOpenAPIใ‚นใ‚ญใƒผใƒžใซ่ฟฝๅŠ ใ•ใ‚Œใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใงไฝฟ็”จใ•ใ‚Œใพใ™: - + -## ๆฆ‚่ฆใจ่ชฌๆ˜Ž +### Enumใ‚’ไฝฟใฃใŸใ‚ฟใ‚ฐ { #tags-with-enums } + +ๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ ดๅˆใ€**่ค‡ๆ•ฐใฎใ‚ฟใ‚ฐ**ใŒ่“„็ฉใ•ใ‚Œใฆใ„ใใ€้–ข้€ฃใ™ใ‚‹*path operations*ใซๅฏพใ—ใฆๅธธใซ**ๅŒใ˜ใ‚ฟใ‚ฐ**ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใŸใใชใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใ“ใฎใ‚ˆใ†ใชๅ ดๅˆใ€ใ‚ฟใ‚ฐใ‚’`Enum`ใซๆ ผ็ดใ™ใ‚‹ใจ็†ใซใ‹ใชใฃใฆใ„ใพใ™ใ€‚ + +**FastAPI** ใฏใ€ใƒ—ใƒฌใƒผใƒณใชๆ–‡ๅญ—ๅˆ—ใฎๅ ดๅˆใจๅŒใ˜ๆ–นๆณ•ใงใใ‚Œใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™: + +{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} + +## ๆฆ‚่ฆใจ่ชฌๆ˜Ž { #summary-and-description } `summary`ใจ`description`ใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial003.py hl[20:21] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} -## docstringใ‚’็”จใ„ใŸ่ชฌๆ˜Ž +## docstringใ‚’็”จใ„ใŸ่ชฌๆ˜Ž { #description-from-docstring } -่ชฌๆ˜Žๆ–‡ใฏ้•ทใใฆ่ค‡ๆ•ฐ่กŒใซใŠใ‚ˆใถๅ‚พๅ‘ใŒใ‚ใ‚‹ใฎใงใ€้–ขๆ•ฐdocstringๅ†…ใซ*path operation*ใฎ่ชฌๆ˜Žๆ–‡ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ใ™ใ‚‹ใจใ€**FastAPI** ใฏ่ชฌๆ˜Žๆ–‡ใ‚’่ชญใฟ่พผใ‚“ใงใใ‚Œใพใ™ใ€‚ +่ชฌๆ˜Žๆ–‡ใฏ้•ทใใฆ่ค‡ๆ•ฐ่กŒใซใŠใ‚ˆใถๅ‚พๅ‘ใŒใ‚ใ‚‹ใฎใงใ€้–ขๆ•ฐdocstringๅ†…ใซ*path operation*ใฎ่ชฌๆ˜Žๆ–‡ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ใ™ใ‚‹ใจใ€**FastAPI** ใฏ่ชฌๆ˜Žๆ–‡ใ‚’่ชญใฟ่พผใ‚“ใงใใ‚Œใพใ™ใ€‚ docstringใซMarkdownใ‚’่จ˜่ฟฐใ™ใ‚Œใฐใ€ๆญฃใ—ใ่งฃ้‡ˆใ•ใ‚Œใฆ่กจ็คบใ•ใ‚Œใพใ™ใ€‚๏ผˆdocstringใฎใ‚คใƒณใƒ‡ใƒณใƒˆใ‚’่€ƒๆ…ฎใ—ใฆ๏ผ‰ -{* ../../docs_src/path_operation_configuration/tutorial004.py hl[19:27] *} +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} ใ“ใ‚Œใฏๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงไฝฟ็”จใ•ใ‚Œใพใ™: - + -## ใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Ž +## ใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Ž { #response-description } `response_description`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Žใ‚’ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/path_operation_configuration/tutorial005.py hl[21] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | ๆƒ…ๅ ฑ -`respnse_description`ใฏๅ…ทไฝ“็š„ใซใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ‚็…งใ—ใ€`description`ใฏ*path operation*ๅ…จ่ˆฌใ‚’ๅ‚็…งใ—ใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +`response_description`ใฏๅ…ทไฝ“็š„ใซใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ‚็…งใ—ใ€`description`ใฏ*path operation*ๅ…จ่ˆฌใ‚’ๅ‚็…งใ—ใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -76,22 +86,22 @@ OpenAPIใฏ*path operation*ใ”ใจใซใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Žใ‚’ๅฟ…่ฆใจใ—ใฆใ„ /// - + -## ้žๆŽจๅฅจใฎ*path operation* +## *path operation*ใ‚’้žๆŽจๅฅจใซใ™ใ‚‹ { #deprecate-a-path-operation } -*path operation*ใ‚’deprecatedใจใ—ใฆใƒžใƒผใ‚ฏใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŒใ€ใใ‚Œใ‚’ๅ‰Š้™คใ—ใชใ„ๅ ดๅˆใฏใ€`deprecated`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™: +*path operation*ใ‚’deprecatedใจใ—ใฆใƒžใƒผใ‚ฏใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŒใ€ใใ‚Œใ‚’ๅ‰Š้™คใ—ใชใ„ๅ ดๅˆใฏใ€`deprecated`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} ๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฏ้žๆŽจๅฅจใจๆ˜Ž่จ˜ใ•ใ‚Œใพใ™: - + *path operations*ใŒ้žๆŽจๅฅจใงใ‚ใ‚‹ๅ ดๅˆใจใใ†ใงใชใ„ๅ ดๅˆใงใฉใฎใ‚ˆใ†ใซ่ฆ‹ใˆใ‚‹ใ‹ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„: - + -## ใพใจใ‚ +## ใพใจใ‚ { #recap } *path operationใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ™ใ“ใจใงใ€*path operations*ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’็ฐกๅ˜ใซ่จญๅฎšใƒป่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/path-params-numeric-validations.md b/docs/ja/docs/tutorial/path-params-numeric-validations.md index a1810ae37b..6a9ecc4e7b 100644 --- a/docs/ja/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ja/docs/tutorial/path-params-numeric-validations.md @@ -1,40 +1,52 @@ -# ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๆ•ฐๅ€คใฎๆคœ่จผ +# ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๆ•ฐๅ€คใฎๆคœ่จผ { #path-parameters-and-numeric-validations } ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆ`Query`ใงใ‚ˆใ‚Šๅคšใใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใงใใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆใ‚‚`Path`ใงๅŒใ˜็จฎ้กžใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -## Pathใฎใ‚คใƒณใƒใƒผใƒˆ +## `Path`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-path } -ใพใšๅˆใ‚ใซใ€`fastapi`ใ‹ใ‚‰`Path`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: +ใพใšๅˆใ‚ใซใ€`fastapi`ใ‹ใ‚‰`Path`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€`Annotated`ใ‚‚ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/path_params_numeric_validations/tutorial001.py hl[1] *} +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -## ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎๅฎฃ่จ€ +/// info | ๆƒ…ๅ ฑ + +FastAPI ใฏใƒใƒผใ‚ธใƒงใƒณ 0.95.0 ใง`Annotated`ใฎใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ ใ—๏ผˆใใ—ใฆๆŽจๅฅจใ—ๅง‹ใ‚ใพใ—ใŸ๏ผ‰ใ€‚ + +ๅคใ„ใƒใƒผใ‚ธใƒงใƒณใฎๅ ดๅˆใ€`Annotated`ใ‚’ไฝฟใŠใ†ใจใ™ใ‚‹ใจใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ + +`Annotated`ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ‰ใซใ€FastAPI ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๅฐ‘ใชใใจใ‚‚ 0.95.1 ใพใง[ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใฆใใ ใ•ใ„](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ใ€‚ + +/// + +## ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎๅฎฃ่จ€ { #declare-metadata } ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`Query`ใจๅŒใ˜ใ‚‚ใฎใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item_id`ใซๅฏพใ—ใฆ`title`ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใ—ใพใ™: -{* ../../docs_src/path_params_numeric_validations/tutorial001.py hl[8] *} +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} /// note | ๅ‚™่€ƒ -ใƒ‘ใ‚นใฎไธ€้ƒจใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใฎใงใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏๅธธใซๅฟ…้ ˆใงใ™ใ€‚ +ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‘ใ‚นใฎไธ€้ƒจใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใฎใงใ€ๅธธใซๅฟ…้ ˆใงใ™ใ€‚`None`ใงๅฎฃ่จ€ใ—ใŸใ‚Šใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ—ใŸใ‚Šใ—ใฆใ‚‚ไฝ•ใ‚‚ๅฝฑ้Ÿฟใ›ใšใ€ๅธธใซๅฟ…้ ˆใฎใพใพใงใ™ใ€‚ -ใใฎใŸใ‚ใ€`...`ใ‚’ไฝฟ็”จใ—ใฆๅฟ…้ ˆใจ็คบใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +/// -ใใ‚Œใงใ‚‚ใ€`None`ใงๅฎฃ่จ€ใ—ใฆใ‚‚ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ—ใฆใ‚‚ใ€ไฝ•ใฎๅฝฑ้Ÿฟใ‚‚ใชใใ€ๅธธใซๅฟ…่ฆใจใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใซๅค‰ใ‚ใ‚Šใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +## ๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไธฆใณๆ›ฟใˆใ‚‹ { #order-the-parameters-as-you-need } -/// +/// tip | ่ฑ†็Ÿฅ่ญ˜ -## ๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไธฆใณๆ›ฟใˆใ‚‹ +`Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใ€ใ“ใ‚ŒใฏใŠใใ‚‰ใใใ‚Œใปใฉ้‡่ฆใงใ‚‚ๅฟ…่ฆใงใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +/// ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใ‚’ๅฟ…้ ˆใฎ`str`ใจใ—ใฆๅฎฃ่จ€ใ—ใŸใ„ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ ใพใŸใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใฏไฝ•ใ‚‚ๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ใฎใงใ€`Query`ใ‚’ไฝฟใ†ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใ—ใ‹ใ—ใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item_id`ใฎใŸใ‚ใซ`Path`ใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item_id`ใฎใŸใ‚ใซ`Path`ใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใ—ใฆไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใง`Annotated`ใ‚’ไฝฟใ„ใŸใใชใ„ใจใ—ใพใ™ใ€‚ -Pythonใฏใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใŸใชใ„ๅ€คใฎๅ‰ใซใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใคๅ€คใ‚’็ฝฎใใ“ใจใŒใงใใพใ›ใ‚“ใ€‚ +Pythonใฏใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใคๅ€คใ‚’ใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใŸใชใ„ๅ€คใฎๅ‰ใซ็ฝฎใใจใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใ‚’ไธฆใณๆ›ฟใˆใ‚‹ใ“ใจใŒใงใใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใŸใชใ„ๅ€ค๏ผˆใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`๏ผ‰ใ‚’ๆœ€ๅˆใซๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ @@ -42,63 +54,88 @@ Pythonใฏใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใŸใชใ„ๅ€คใฎๅ‰ใซใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ ใใฎใŸใ‚ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซ้–ขๆ•ฐใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[8] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} + +ใŸใ ใ—ใ€`Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใฏใ“ใฎๅ•้กŒใฏ่ตทใใชใ„ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚`Query()`ใ‚„`Path()`ใซ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ไฝฟใ‚ใชใ„ใŸใ‚ใงใ™ใ€‚ -## ๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไธฆใณๆ›ฟใˆใ‚‹ใƒˆใƒชใƒƒใ‚ฏ +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใ‚’`Query`ใ‚„ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใชใ—ใงๅฎฃ่จ€ใ—ใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item_id`ใ‚’`Path`ใ‚’็”จใ„ใฆๅฎฃ่จ€ใ—ใ€ใใ‚Œใ‚‰ใ‚’ๅˆฅใฎ้ †็•ชใซไธฆใณใŸใ„ๅ ดๅˆใ€Pythonใซใฏๅฐ‘ใ—็‰นๆฎŠใชๆง‹ๆ–‡ใŒ็”จๆ„ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +## ๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไธฆใณๆ›ฟใˆใ‚‹ใƒˆใƒชใƒƒใ‚ฏ { #order-the-parameters-as-you-need-tricks } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใ€ใ“ใ‚ŒใฏใŠใใ‚‰ใใใ‚Œใปใฉ้‡่ฆใงใ‚‚ๅฟ…่ฆใงใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +/// + +ใ“ใ‚Œใฏ**ๅฐใ•ใชใƒˆใƒชใƒƒใ‚ฏ**ใงใ€ไพฟๅˆฉใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใŒใ€้ ป็นใซๅฟ…่ฆใซใชใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ๆฌกใฎใ“ใจใ‚’ใ—ใŸใ„ๅ ดๅˆ: + +* `q`ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’`Query`ใ‚‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚‚ใชใ—ใงๅฎฃ่จ€ใ™ใ‚‹ +* ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ`item_id`ใ‚’`Path`ใ‚’ไฝฟใฃใฆๅฎฃ่จ€ใ™ใ‚‹ +* ใใ‚Œใ‚‰ใ‚’ๅˆฅใฎ้ †็•ชใซใ™ใ‚‹ +* `Annotated`ใ‚’ไฝฟใ‚ใชใ„ + +...PythonใซใฏใใฎใŸใ‚ใฎๅฐ‘ใ—็‰นๆฎŠใชๆง‹ๆ–‡ใŒใ‚ใ‚Šใพใ™ใ€‚ ้–ขๆ•ฐใฎๆœ€ๅˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ`*`ใ‚’ๆธกใ—ใพใ™ใ€‚ Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ใฎใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐ๏ผˆใ‚ญใƒผใจๅ€คใฎใƒšใ‚ข๏ผ‰ใจใ—ใฆๅ‘ผใฐใ‚Œใ‚‹ในใใ‚‚ใฎใงใ‚ใ‚‹ใจ็Ÿฅใฃใฆใ„ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใใ‚Œใฏkwargsใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ใŸใจใˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใใฆใ‚‚ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[8] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} + +### `Annotated`ใฎใปใ†ใŒใ‚ˆใ„ { #better-with-annotated } + +`Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใฏใ€้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ไฝฟใ‚ใชใ„ใŸใ‚ใ€ใ“ใฎๅ•้กŒใฏ่ตทใใšใ€ใŠใใ‚‰ใ`*`ใ‚’ไฝฟใ†ๅฟ…่ฆใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} -## ๆ•ฐๅ€คใฎๆคœ่จผ: ไปฅไธŠ +## ๆ•ฐๅ€คใฎๆคœ่จผ: ไปฅไธŠ { #number-validations-greater-than-or-equal } -`Query`ใจ`Path`๏ผˆใ€ใใ—ใฆๅพŒ่ฟฐใ™ใ‚‹ไป–ใฎใ‚‚ใฎ๏ผ‰ใ‚’็”จใ„ใฆใ€ๆ–‡ๅญ—ๅˆ—ใฎๅˆถ็ด„ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใŒใ€ๆ•ฐๅ€คใฎๅˆถ็ด„ใ‚‚ๅŒๆง˜ใซๅฎฃ่จ€ใงใใพใ™ใ€‚ +`Query`ใจ`Path`๏ผˆใ€ใใ—ใฆๅพŒ่ฟฐใ™ใ‚‹ไป–ใฎใ‚‚ใฎ๏ผ‰ใ‚’็”จใ„ใฆใ€ๆ•ฐๅ€คใฎๅˆถ็ด„ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ -ใ“ใ“ใงใ€`ge=1`ใฎๅ ดๅˆใ€`item_id`ใฏ`1`ใ€Œใ‚ˆใ‚Šๅคงใใ„`g`ใ‹ใ€ๅŒใ˜`e`ใ€ๆ•ดๆ•ฐใงใชใ‚Œใ‘ใฐใชใ‚Šใพใ›ใ‚“ใ€‚ +ใ“ใ“ใงใ€`ge=1`ใฎๅ ดๅˆใ€`item_id`ใฏ`1`ใ€Œใ‚ˆใ‚Šๅคงใใ„`g`ใ‹ใ€ๅŒใ˜`e`ใ€ๆ•ดๆ•ฐใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial004.py hl[8] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} -## ๆ•ฐๅ€คใฎๆคœ่จผ: ใ‚ˆใ‚Šๅคงใใ„ใจๅฐใชใ‚Šใ‚คใ‚ณใƒผใƒซ +## ๆ•ฐๅ€คใฎๆคœ่จผ: ใ‚ˆใ‚Šๅคงใใ„ใจๅฐใชใ‚Šใ‚คใ‚ณใƒผใƒซ { #number-validations-greater-than-and-less-than-or-equal } ไปฅไธ‹ใ‚‚ๅŒๆง˜ใงใ™: -* `gt`: ใ‚ˆใ‚Šๅคงใใ„๏ผˆ`g`reater `t`han๏ผ‰ -* `le`: ๅฐใชใ‚Šใ‚คใ‚ณใƒผใƒซ๏ผˆ`l`ess than or `e`qual๏ผ‰ +* `gt`: `g`reater `t`han +* `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005.py hl[9] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} -## ๆ•ฐๅ€คใฎๆคœ่จผ: ๆตฎๅ‹•ๅฐๆ•ฐ็‚นใ€ ๅคงใชใ‚Šๅฐใชใ‚Š +## ๆ•ฐๅ€คใฎๆคœ่จผ: ๆตฎๅ‹•ๅฐๆ•ฐ็‚นใ€ ๅคงใชใ‚Šๅฐใชใ‚Š { #number-validations-floats-greater-than-and-less-than } ๆ•ฐๅ€คใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏ`float`ใฎๅ€คใซๅฏพใ—ใฆใ‚‚ๆœ‰ๅŠนใงใ™ใ€‚ -ใ“ใ“ใง้‡่ฆใซใชใฃใฆใใ‚‹ใฎใฏgtใ ใ‘ใงใชใgeใ‚‚ๅฎฃ่จ€ใงใใ‚‹ใ“ใจใงใ™ใ€‚ใ“ใ‚ŒใจๅŒๆง˜ใซใ€ไพ‹ใˆใฐใ€ๅ€คใŒ`1`ใ‚ˆใ‚Šๅฐใ•ใใฆใ‚‚`0`ใ‚ˆใ‚Šๅคงใใใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ“ใจใ‚’่ฆๆฑ‚ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใ“ใง้‡่ฆใซใชใฃใฆใใ‚‹ใฎใฏgtใ ใ‘ใงใชใgeใ‚‚ๅฎฃ่จ€ใงใใ‚‹ใ“ใจใงใ™ใ€‚ใ“ใ‚ŒใจๅŒๆง˜ใซใ€ไพ‹ใˆใฐใ€ๅ€คใŒ`1`ใ‚ˆใ‚Šๅฐใ•ใใฆใ‚‚`0`ใ‚ˆใ‚Šๅคงใใใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ“ใจใ‚’่ฆๆฑ‚ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใ—ใŸใŒใฃใฆใ€`0.5`ใฏๆœ‰ๅŠนใชๅ€คใงใ™ใŒใ€`0.0`ใ‚„`0`ใฏใใ†ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใ“ใ‚Œใฏltใ‚‚ๅŒใ˜ใงใ™ใ€‚ +ใ“ใ‚Œใฏltใ‚‚ๅŒใ˜ใงใ™ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial006.py hl[11] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} -## ใพใจใ‚ +## ใพใจใ‚ { #recap } `Query`ใจ`Path`๏ผˆใใ—ใฆใพใ ่ฆ‹ใŸใ“ใจใชใ„ไป–ใฎใ‚‚ใฎ๏ผ‰ใงใฏใ€[ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๆ–‡ๅญ—ๅˆ—ใฎๆคœ่จผ](query-params-str-validations.md){.internal-link target=_blank}ใจๅŒใ˜ใ‚ˆใ†ใซใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจๆ–‡ๅญ—ๅˆ—ใฎๆคœ่จผใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใพใŸใ€ๆ•ฐๅ€คใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -* `gt`: ใ‚ˆใ‚Šๅคงใใ„๏ผˆ`g`reater `t`han๏ผ‰ -* `ge`: ไปฅไธŠ๏ผˆ`g`reater than or `e`qual๏ผ‰ -* `lt`: ใ‚ˆใ‚Šๅฐใ•ใ„๏ผˆ`l`ess `t`han๏ผ‰ -* `le`: ไปฅไธ‹๏ผˆ`l`ess than or `e`qual๏ผ‰ +* `gt`: `g`reater `t`han +* `ge`: `g`reater than or `e`qual +* `lt`: `l`ess `t`han +* `le`: `l`ess than or `e`qual /// info | ๆƒ…ๅ ฑ -`Query`ใ€`Path`ใชใฉใฏๅพŒใซๅ…ฑ้€šใฎ`Param`ใ‚ฏใƒฉใ‚นใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’่ฆ‹ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚๏ผˆไฝฟใ†ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“๏ผ‰ +`Query`ใ€`Path`ใ€ใŠใ‚ˆใณๅพŒใง่ฆ‹ใ‚‹ไป–ใฎใ‚ฏใƒฉใ‚นใฏใ€ๅ…ฑ้€šใฎ`Param`ใ‚ฏใƒฉใ‚นใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ -ใใ—ใฆใ€ใใ‚Œใ‚‰ใ™ในใฆใฏใ€ใ“ใ‚Œใพใง่ฆ‹ใฆใใŸ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจๅŒใ˜ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…ฑๆœ‰ใ—ใฆใ„ใพใ™ใ€‚ +ใใ‚Œใ‚‰ใฏใ™ในใฆใ€ใ“ใ‚Œใพใง่ฆ‹ใฆใใŸ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใฎๅŒใ˜ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ…ฑๆœ‰ใ—ใฆใ„ใพใ™ใ€‚ /// diff --git a/docs/ja/docs/tutorial/path-params.md b/docs/ja/docs/tutorial/path-params.md index 1893ec12f4..96a1fe9d10 100644 --- a/docs/ja/docs/tutorial/path-params.md +++ b/docs/ja/docs/tutorial/path-params.md @@ -1,22 +1,22 @@ -# ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ +# ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #path-parameters } Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚„ใ€Œใƒ‘ใ‚นๅค‰ๆ•ฐใ€ใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/path_params/tutorial001.py hl[6,7] *} +{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item_id` ใฎๅ€คใฏใ€ๅผ•ๆ•ฐ `item_id` ใจใ—ใฆ้–ขๆ•ฐใซๆธกใ•ใ‚Œใพใ™ใ€‚ -ใ—ใŒใŸใฃใฆใ€ใ“ใฎไพ‹ใ‚’ๅฎŸ่กŒใ—ใฆ http://127.0.0.1:8000/items/foo ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ๆฌกใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +ใ—ใŸใŒใฃใฆใ€ใ“ใฎไพ‹ใ‚’ๅฎŸ่กŒใ—ใฆ http://127.0.0.1:8000/items/foo ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ๆฌกใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ ```JSON {"item_id":"foo"} ``` -## ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๅž‹ +## ๅž‹ไป˜ใใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #path-parameters-with-types } ๆจ™ๆบ–ใฎPythonใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไฝฟ็”จใ—ใฆใ€้–ขๆ•ฐๅ†…ใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/path_params/tutorial002.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} ใ“ใ“ใงใฏใ€ `item_id` ใฏ `int` ใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -26,7 +26,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ /// -## ใƒ‡ใƒผใ‚ฟๅค‰ๆ› +## ใƒ‡ใƒผใ‚ฟๅค‰ๆ› { #data-conversion } ใ“ใฎไพ‹ใ‚’ๅฎŸ่กŒใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/items/3 ใ‚’้–‹ใใจใ€ๆฌกใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: @@ -38,68 +38,69 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ้–ขๆ•ฐใŒๅ—ใ‘ๅ–ใฃใŸ๏ผˆใŠใ‚ˆใณ่ฟ”ใ—ใŸ๏ผ‰ๅ€คใฏใ€ๆ–‡ๅญ—ๅˆ—ใฎ `"3"` ใงใฏใชใใ€Pythonใฎ `int` ใจใ—ใฆใฎ `3` ใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใ—ใŸใŒใฃใฆใ€ๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€**FastAPI**ใฏ่‡ชๅ‹•ใƒชใ‚ฏใ‚จใ‚นใƒˆ "่งฃๆž" ใ‚’่กŒใ„ใพใ™ใ€‚ +ใ—ใŸใŒใฃใฆใ€ใใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟใ†ใจใ€**FastAPI**ใฏ่‡ชๅ‹•ใƒชใ‚ฏใ‚จใ‚นใƒˆ "่งฃๆž" ใ‚’่กŒใ„ใพใ™ใ€‚ /// -## ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ +## ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ { #data-validation } ใ—ใ‹ใ—ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/items/foo ใ‚’้–‹ใใจใ€ๆฌกใฎHTTPใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใพใ™: ```JSON { - "detail": [ - { - "loc": [ - "path", - "item_id" - ], - "msg": "value is not a valid integer", - "type": "type_error.integer" - } - ] + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] } ``` ใ“ใ‚Œใฏใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item_id` ใŒ `int` ใงใฏใชใ„ๅ€ค `"foo"` ใ ใ‹ใ‚‰ใงใ™ใ€‚ -http://127.0.0.1:8000/items/4.2 ใง่ฆ‹ใ‚‰ใ‚Œใ‚‹ใ‚ˆใ†ใซใ€intใฎใ‹ใ‚ใ‚Šใซ `float` ใŒไธŽใˆใ‚‰ใ‚ŒใŸๅ ดๅˆใซใ‚‚ๅŒๆง˜ใชใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +http://127.0.0.1:8000/items/4.2 ใง่ฆ‹ใ‚‰ใ‚Œใ‚‹ใ‚ˆใ†ใซใ€`int` ใฎใ‹ใ‚ใ‚Šใซ `float` ใŒไธŽใˆใ‚‰ใ‚ŒใŸๅ ดๅˆใซใ‚‚ๅŒๆง˜ใชใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ /// check | ็ขบ่ช -ใ—ใŸใŒใฃใฆใ€Pythonใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€**FastAPI**ใฏใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’่กŒใ„ใพใ™ใ€‚ +ใ—ใŸใŒใฃใฆใ€ๅŒใ˜Pythonใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€**FastAPI**ใฏใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’่กŒใ„ใพใ™ใ€‚ -่กจ็คบใ•ใ‚ŒใŸใ‚จใƒฉใƒผใซใฏๅ•้กŒใฎใ‚ใ‚‹็ฎ‡ๆ‰€ใŒๆ˜Ž็ขบใซๆŒ‡ๆ‘˜ใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +่กจ็คบใ•ใ‚ŒใŸใ‚จใƒฉใƒผใซใฏใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใŒ้€šใ‚‰ใชใ‹ใฃใŸ็ฎ‡ๆ‰€ใŒๆ˜Ž็ขบใซ็คบใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใ“ใ‚Œใฏใ€APIใซ้–ข้€ฃใ™ใ‚‹ใ‚ณใƒผใƒ‰ใฎ้–‹็™บใŠใ‚ˆใณใƒ‡ใƒใƒƒใ‚ฐใซ้žๅธธใซๅฝน็ซ‹ใกใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€APIใจใ‚„ใ‚Šๅ–ใ‚Šใ™ใ‚‹ใ‚ณใƒผใƒ‰ใ‚’้–‹็™บใƒปใƒ‡ใƒใƒƒใ‚ฐใ™ใ‚‹้š›ใซ้žๅธธใซๅฝน็ซ‹ใกใพใ™ใ€‚ /// -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #documentation } -ใใ—ใฆใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/docs ใ‚’้–‹ใใจใ€ไปฅไธ‹ใฎๆง˜ใช่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ•ใ‚ŒใŸๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +ใใ—ใฆใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/docs ใ‚’้–‹ใใจใ€ไปฅไธ‹ใฎๆง˜ใช่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ•ใ‚ŒใŸๅฏพ่ฉฑ็š„ใชAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ /// check | ็ขบ่ช -็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€Pythonๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ ใ‘ใงใ€**FastAPI**ใฏๅฏพ่ฉฑ็š„ใชAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ—ใพใ™๏ผˆSwagger UIใ‚’็ตฑๅˆ๏ผ‰ใ€‚ +็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€ๅŒใ˜Pythonๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ ใ‘ใงใ€**FastAPI**ใฏๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่‡ชๅ‹•็š„ใซ็”Ÿๆˆใ—ใพใ™๏ผˆSwagger UIใ‚’็ตฑๅˆ๏ผ‰ใ€‚ ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๆ•ดๆ•ฐใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ๆจ™ๆบ–ใงใ‚ใ‚‹ใ“ใจใฎใƒกใƒชใƒƒใƒˆใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณใฎไปฃๆ›ฟ็‰ฉ +## ๆจ™ๆบ–ใƒ™ใƒผใ‚นใฎใƒกใƒชใƒƒใƒˆใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณใฎไปฃๆ›ฟ็‰ฉ { #standards-based-benefits-alternative-documentation } -ใพใŸใ€็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใŒ OpenAPI ๆจ™ๆบ–ใซๅพ“ใฃใฆใ„ใ‚‹ใฎใงใ€ไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใƒ„ใƒผใƒซใŒๅคšๆ•ฐใ‚ใ‚Šใพใ™ใ€‚ +ใพใŸใ€็”Ÿๆˆใ•ใ‚ŒใŸใ‚นใ‚ญใƒผใƒžใŒ OpenAPI ๆจ™ๆบ–ใซๅพ“ใฃใฆใ„ใ‚‹ใฎใงใ€ไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใƒ„ใƒผใƒซใŒๅคšๆ•ฐใ‚ใ‚Šใพใ™ใ€‚ ใ“ใฎใŸใ‚ใ€**FastAPI**่‡ชไฝ“ใŒไปฃๆ›ฟใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๆไพ›ใ—ใพใ™๏ผˆReDocใ‚’ไฝฟ็”จ๏ผ‰ใ€‚ใ“ใ‚Œใฏใ€ http://127.0.0.1:8000/redoc ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจ็ขบ่ชใงใใพใ™ใ€‚ -ๅŒๆง˜ใซใ€ไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใƒ„ใƒผใƒซใŒๅคšๆ•ฐใ‚ใ‚Šใพใ™๏ผˆๅคšใใฎ่จ€่ชž็”จใฎใ‚ณใƒผใƒ‰็”Ÿๆˆใƒ„ใƒผใƒซใ‚’ๅซใ‚€๏ผ‰ใ€‚ +ๅŒๆง˜ใซใ€ไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใƒ„ใƒผใƒซใŒๅคšๆ•ฐใ‚ใ‚Šใพใ™ใ€‚ๅคšใใฎ่จ€่ชž็”จใฎใ‚ณใƒผใƒ‰็”Ÿๆˆใƒ„ใƒผใƒซใ‚’ๅซใฟใพใ™ใ€‚ -## Pydantic +## Pydantic { #pydantic } ใ™ในใฆใฎใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏ Pydantic ใซใ‚ˆใฃใฆๅ†…้ƒจใงๅฎŸ่กŒใ•ใ‚Œใ‚‹ใŸใ‚ใ€Pydanticใฎๅ…จใฆใฎใƒกใƒชใƒƒใƒˆใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ใใ—ใฆใ€ๅฎ‰ๅฟƒใ—ใฆๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -107,7 +108,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ใ“ใ‚Œใ‚‰ใฎใ„ใใคใ‹ใซใคใ„ใฆใฏใ€ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใฎๆฌกใฎ็ซ ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ -## ้ †ๅบใฎๅ•้กŒ +## ้ †ๅบใฎๅ•้กŒ { #order-matters } *path operations* ใ‚’ไฝœๆˆใ™ใ‚‹้š›ใ€ๅ›บๅฎšใƒ‘ใ‚นใ‚’ใ‚‚ใค็ŠถๆณใŒใ‚ใ‚Šๅพ—ใพใ™ใ€‚ @@ -117,29 +118,29 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ *path operations* ใฏ้ †ใซ่ฉ•ไพกใ•ใ‚Œใ‚‹ใฎใงใ€ `/users/me` ใŒ `/users/{user_id}` ใ‚ˆใ‚Šใ‚‚ๅ…ˆใซๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใ‹็ขบ่ชใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: -{* ../../docs_src/path_params/tutorial003.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} -ใใ‚Œไปฅๅค–ใฎๅ ดๅˆใ€ `/users/{users_id}` ใฏ `/users/me` ใจใ—ใฆใ‚‚ใƒžใƒƒใƒใ—ใพใ™ใ€‚ๅ€คใŒใ€Œ"me"ใ€ใงใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `user_id` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใจใ€Œ่€ƒใˆใ€ใพใ™ใ€‚ +ใใ‚Œไปฅๅค–ใฎๅ ดๅˆใ€ `/users/{user_id}` ใฏ `/users/me` ใจใ—ใฆใ‚‚ใƒžใƒƒใƒใ—ใพใ™ใ€‚ๅ€คใŒ `"me"` ใงใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `user_id` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใจใ€Œ่€ƒใˆใ€ใพใ™ใ€‚ -## ๅฎš็พฉๆธˆใฟใฎๅ€ค +ๅŒๆง˜ใซใ€path operation ใ‚’ๅ†ๅฎš็พฉใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“: -*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใ‚’ๅ—ใ‘ๅ–ใ‚‹ *path operation* ใ‚’ใ‚‚ใกใ€ๆœ‰ๅŠนใช*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅ€คใ‚’ไบ‹ๅ‰ใซๅฎš็พฉใ—ใŸใ„ๅ ดๅˆใฏใ€ๆจ™ๆบ–ใฎPython `Enum` ใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ +{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} -### `Enum` ใ‚ฏใƒฉใ‚นใฎไฝœๆˆ +ใƒ‘ใ‚นใฏๆœ€ๅˆใซใƒžใƒƒใƒใ—ใŸใ‚‚ใฎใŒๅธธใซไฝฟใ‚ใ‚Œใ‚‹ใŸใ‚ใ€ๆœ€ๅˆใฎใ‚‚ใฎใŒๅธธใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -`Enum` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€ `str` ใจ `Enum` ใ‚’็ถ™ๆ‰ฟใ—ใŸใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +## ๅฎš็พฉๆธˆใฟใฎๅ€ค { #predefined-values } -`str` ใ‚’็ถ™ๆ‰ฟใ™ใ‚‹ใ“ใจใงใ€APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๅ€คใŒ `ๆ–‡ๅญ—ๅˆ—` ใงใชใ‘ใ‚Œใฐใ„ใ‘ใชใ„ใ“ใจใ‚’็Ÿฅใ‚Šใ€ๆญฃ็ขบใซใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ +*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใ‚’ๅ—ใ‘ๅ–ใ‚‹ *path operation* ใ‚’ใ‚‚ใกใ€ๆœ‰ๅŠนใช*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅ€คใ‚’ไบ‹ๅ‰ใซๅฎš็พฉใ—ใŸใ„ๅ ดๅˆใฏใ€ๆจ™ๆบ–ใฎPython `Enum` ใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ -ใใ—ใฆใ€ๅ›บๅฎšๅ€คใฎใ‚ฏใƒฉใ‚นๅฑžๆ€งใ‚’ไฝœใ‚Šใพใ™ใ€‚ใ™ใ‚‹ใจใ€ใใฎๅ€คใŒไฝฟ็”จๅฏ่ƒฝใชๅ€คใจใชใ‚Šใพใ™: +### `Enum` ใ‚ฏใƒฉใ‚นใฎไฝœๆˆ { #create-an-enum-class } -{* ../../docs_src/path_params/tutorial005.py hl[1,6,7,8,9] *} +`Enum` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€ `str` ใจ `Enum` ใ‚’็ถ™ๆ‰ฟใ—ใŸใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -/// info | ๆƒ…ๅ ฑ +`str` ใ‚’็ถ™ๆ‰ฟใ™ใ‚‹ใ“ใจใงใ€APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๅ€คใŒ `string` ๅž‹ใงใชใ‘ใ‚Œใฐใ„ใ‘ใชใ„ใ“ใจใ‚’็Ÿฅใ‚Šใ€ๆญฃ็ขบใซใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ -Enumerations (ใ‚‚ใ—ใใฏใ€enums)ใฏPython 3.4ไปฅ้™ใงๅˆฉ็”จใงใใพใ™ใ€‚ +ใใ—ใฆใ€ๅ›บๅฎšๅ€คใฎใ‚ฏใƒฉใ‚นๅฑžๆ€งใ‚’ไฝœใ‚Šใพใ™ใ€‚ใ™ใ‚‹ใจใ€ใใฎๅ€คใŒไฝฟ็”จๅฏ่ƒฝใชๅ€คใจใชใ‚Šใพใ™: -/// +{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -147,33 +148,33 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ /// -### *ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅฎฃ่จ€ +### *ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅฎฃ่จ€ { #declare-a-path-parameter } ๆฌกใซใ€ไฝœๆˆใ—ใŸenumใ‚ฏใƒฉใ‚นใงใ‚ใ‚‹`ModelName`ใ‚’ไฝฟ็”จใ—ใŸๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ใ‚‚ใค*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใ‚’ไฝœๆˆใ—ใพใ™: -{* ../../docs_src/path_params/tutorial005.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} -### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } *ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅˆฉ็”จๅฏ่ƒฝใชๅ€คใŒไบ‹ๅ‰ใซๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ๅฏพ่ฉฑ็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง้ฉๅˆ‡ใซ่กจ็คบใงใใพใ™: -### Python*ๅˆ—ๆŒ™ๅž‹*ใฎๅˆฉ็”จ +### Python*ๅˆ—ๆŒ™ๅž‹*ใฎๅˆฉ็”จ { #working-with-python-enumerations } *ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅ€คใฏ*ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใจใชใ‚Šใพใ™ใ€‚ -#### *ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใฎๆฏ”่ผƒ +#### *ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใฎๆฏ”่ผƒ { #compare-enumeration-members } ใ“ใ‚Œใฏใ€ไฝœๆˆใ—ใŸๅˆ—ๆŒ™ๅž‹ `ModelName` ใฎ*ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใจๆฏ”่ผƒใงใใพใ™: -{* ../../docs_src/path_params/tutorial005.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} -#### *ๅˆ—ๆŒ™ๅ€ค*ใฎๅ–ๅพ— +#### *ๅˆ—ๆŒ™ๅ€ค*ใฎๅ–ๅพ— { #get-the-enumeration-value } `model_name.value` ใ€ใ‚‚ใ—ใใฏไธ€่ˆฌใซใ€ `your_enum_member.value` ใ‚’ไฝฟ็”จใ—ใฆๅฎŸ้š›ใฎๅ€ค (ใ“ใฎๅ ดๅˆใฏ `str`) ใ‚’ๅ–ๅพ—ใงใใพใ™ใ€‚ -{* ../../docs_src/path_params/tutorial005.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -181,13 +182,13 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ /// -#### *ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใฎ่ฟ”ๅด +#### *ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใฎ่ฟ”ๅด { #return-enumeration-members } -*path operation* ใ‹ใ‚‰*ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚JSONใƒœใƒ‡ใ‚ฃ๏ผˆ`dict` ใชใฉ๏ผ‰ใงใƒใ‚นใƒˆใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +*path operation* ใ‹ใ‚‰*ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใ‚’่ฟ”ใ™ใ“ใจใŒใงใใพใ™ใ€‚JSONใƒœใƒ‡ใ‚ฃ๏ผˆไพ‹: `dict`๏ผ‰ใงใƒใ‚นใƒˆใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ใใ‚Œใ‚‰ใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ•ใ‚Œใ‚‹ๅ‰ใซ้ฉๅˆ‡ใชๅ€ค (ใ“ใฎๅ ดๅˆใฏๆ–‡ๅญ—ๅˆ—) ใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ -{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏไปฅไธ‹ใฎๆง˜ใชJSONใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅพ—ใพใ™: @@ -198,23 +199,23 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ } ``` -## ใƒ‘ใ‚นใ‚’ๅซใ‚“ใ ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใƒ‘ใ‚นใ‚’ๅซใ‚“ใ ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #path-parameters-containing-paths } ใƒ‘ใ‚น `/files/{file_path}` ใจใชใ‚‹ *path operation* ใ‚’ๆŒใฃใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ ใŸใ ใ—ใ€ `home/johndoe/myfile.txt` ใฎใ‚ˆใ†ใช*ใƒ‘ใ‚น*ใ‚’ๅซใ‚“ใ  `file_path` ใŒๅฟ…่ฆใงใ™ใ€‚ -ใ—ใŸใŒใฃใฆใ€URLใฏ `/files/home/johndoe/myfile.txt` ใฎๆง˜ใซใชใ‚Šใพใ™ใ€‚ +ใ—ใŸใŒใฃใฆใ€ใใฎใƒ•ใ‚กใ‚คใƒซใฎURLใฏ `/files/home/johndoe/myfile.txt` ใฎๆง˜ใซใชใ‚Šใพใ™ใ€‚ -### OpenAPIใ‚ตใƒใƒผใƒˆ +### OpenAPIใ‚ตใƒใƒผใƒˆ { #openapi-support } OpenAPIใฏใƒ†ใ‚นใƒˆใ‚„ๅฎš็พฉใŒๅ›ฐ้›ฃใชใ‚ทใƒŠใƒชใ‚ชใซใคใชใŒใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใŸใ‚ใ€ๅ†…้ƒจใซ*ใƒ‘ใ‚น*ใ‚’ๅซใ‚€*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅฎฃ่จ€ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚ ใใ‚Œใซใ‚‚้–ขใ‚ใ‚‰ใšใ€Starletteใฎๅ†…้ƒจใƒ„ใƒผใƒซใฎใฒใจใคใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€**FastAPI**ใฏใใ‚ŒใŒๅฎŸ็พใงใใพใ™ใ€‚ -ใใ—ใฆใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใƒ‘ใ‚นใ‚’ๅซใ‚€ในใใงใ‚ใ‚‹ใ“ใจใ‚’ๆ˜Ž็คบ็š„ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใชใใ€ๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +ใใ—ใฆใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใƒ‘ใ‚นใ‚’ๅซใ‚€ในใใงใ‚ใ‚‹ใ“ใจใ‚’็คบใ™ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฟฝๅŠ ใ—ใชใใฆใ‚‚ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏๅ‹•ไฝœใ—ใพใ™ใ€‚ -### ใƒ‘ใ‚นๅค‰ๆ› +### ใƒ‘ใ‚นใ‚ณใƒณใƒใƒผใ‚ฟใƒผ { #path-convertor } Starletteใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ไปฅไธ‹ใฎURLใฎๆง˜ใช*ใƒ‘ใ‚น*ใ‚’ๅซใ‚“ใ ใ€*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅฎฃ่จ€ใŒใงใใพใ™: @@ -226,17 +227,17 @@ Starletteใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ไปฅไธ‹ใฎURLใฎๆง˜ ใ—ใŸใŒใฃใฆใ€ไปฅไธ‹ใฎๆง˜ใซไฝฟ็”จใงใใพใ™: -{* ../../docs_src/path_params/tutorial004.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ -ๆœ€ๅˆใฎใ‚นใƒฉใƒƒใ‚ทใƒฅ (`/`)ใŒไป˜ใ„ใฆใ„ใ‚‹ `/home/johndoe/myfile.txt` ใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅซใ‚“ใงใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ๆœ€ๅˆใฎใ‚นใƒฉใƒƒใ‚ทใƒฅ (`/`)ใŒไป˜ใ„ใฆใ„ใ‚‹ `/home/johndoe/myfile.txt` ใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅซใ‚“ใงใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ ใ“ใฎๅ ดๅˆใ€URLใฏ `files` ใจ `home` ใฎ้–“ใซใƒ€ใƒ–ใƒซใ‚นใƒฉใƒƒใ‚ทใƒฅ (`//`) ใฎใ‚ใ‚‹ใ€ `/files//home/johndoe/myfile.txt` ใซใชใ‚Šใพใ™ใ€‚ /// -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ็ฐกๆฝ”ใงใ€ๆœฌ่ณช็š„ใงใ€ๆจ™ๆบ–็š„ใชPythonใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€**FastAPI**ใฏไปฅไธ‹ใ‚’่กŒใ„ใพใ™: diff --git a/docs/ja/docs/tutorial/query-param-models.md b/docs/ja/docs/tutorial/query-param-models.md index 053d0740bc..d892a57d22 100644 --- a/docs/ja/docs/tutorial/query-param-models.md +++ b/docs/ja/docs/tutorial/query-param-models.md @@ -1,8 +1,8 @@ -# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒขใƒ‡ใƒซ +# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒขใƒ‡ใƒซ { #query-parameter-models } ใ‚‚ใ—้–ข้€ฃใ™ใ‚‹**่ค‡ๆ•ฐใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‹ใ‚‰ๆˆใ‚‹ใ‚ฐใƒซใƒผใƒ—ใŒใ‚ใ‚‹ใชใ‚‰ใ€ใใ‚Œใ‚‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ -ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€**่ค‡ๆ•ฐใฎๅ ดๆ‰€**ใง**ใใฎPydanticใƒขใƒ‡ใƒซใ‚’ๅ†ๅˆฉ็”จ**ใงใใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ใ€ใ™ในใฆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆไธ€ๅบฆใซๅฎฃ่จ€ใงใใพใ™ใ€‚๐Ÿ˜Ž +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€**่ค‡ๆ•ฐใฎๅ ดๆ‰€**ใง**ใใฎใƒขใƒ‡ใƒซใ‚’ๅ†ๅˆฉ็”จ**ใงใใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ใ€ใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅฏพใ—ใฆไธ€ๅบฆใซๅฎฃ่จ€ใงใใพใ™ใ€‚๐Ÿ˜Ž /// note | ๅ‚™่€ƒ @@ -10,15 +10,15 @@ /// -## ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซPydanticใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ +## Pydanticใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใŸใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #query-parameters-with-a-pydantic-model } -ๅฟ…่ฆใช**่ค‡ๆ•ฐใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‚’**Pydanticใƒขใƒ‡ใƒซ**ใงๅฎฃ่จ€ใ—ใ€ใ•ใ‚‰ใซใ€ใใ‚Œใ‚’ `Query` ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ—ใ‚‡ใ†: +ๅฟ…่ฆใช**ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‚’**Pydanticใƒขใƒ‡ใƒซ**ใงๅฎฃ่จ€ใ—ใ€ใ•ใ‚‰ใซใ€ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `Query` ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ—ใ‚‡ใ†: {* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} -**FastAPI**ใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‹ใ‚‰ใใ‚Œใžใ‚Œใฎ**ใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใฎใƒ‡ใƒผใ‚ฟใ‚’**ๆŠฝๅ‡บ**ใ—ใ€ๅฎš็พฉใ•ใ‚ŒใŸ**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ +**FastAPI**ใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‹ใ‚‰ใใ‚Œใžใ‚Œใฎ**ใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใฎใƒ‡ใƒผใ‚ฟใ‚’**ๆŠฝๅ‡บ**ใ—ใ€ๅฎš็พฉใ—ใŸPydanticใƒขใƒ‡ใƒซใ‚’ๆไพ›ใ—ใพใ™ใ€‚ -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ `/docs` ใงใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’็ขบ่ชใงใใพใ™: @@ -26,11 +26,11 @@ -## ไฝ™ๅˆ†ใชใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’็ฆๆญขใ™ใ‚‹ +## ไฝ™ๅˆ†ใชใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’็ฆๆญขใ™ใ‚‹ { #forbid-extra-query-parameters } -็‰นๅฎšใฎ๏ผˆใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„๏ผ‰ใ‚ฑใƒผใ‚นใงใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’**ๅˆถ้™**ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +็‰นๅฎšใฎ๏ผˆใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„๏ผ‰ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใ€ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’**ๅˆถ้™**ใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ -Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใจใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +Pydanticใฎใƒขใƒ‡ใƒซ่จญๅฎšใ‚’ไฝฟใฃใฆใ€ใ‚ใ‚‰ใ‚†ใ‚‹ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใซใงใใพใ™ใ€‚ {* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} @@ -42,7 +42,7 @@ Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ https://example.com/items/?limit=10&tool=plumbus ``` -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `tool` ใŒ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ใ“ใจใ‚’้€š็Ÿฅใ™ใ‚‹**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ +ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `tool` ใŒ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ใ“ใจใ‚’ไผใˆใ‚‹**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ ```json { @@ -57,7 +57,7 @@ https://example.com/items/?limit=10&tool=plumbus } ``` -## ใพใจใ‚ +## ใพใจใ‚ { #summary } **FastAPI**ใงใฏใ€**ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index 22b89e452f..e230ef29af 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -1,120 +1,228 @@ -# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๆ–‡ๅญ—ๅˆ—ใฎๆคœ่จผ +# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๆ–‡ๅญ—ๅˆ—ใฎๆคœ่จผ { #query-parameters-and-string-validations } **FastAPI** ใงใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ไปฅไธ‹ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ไพ‹ใซใ—ใฆใฟใพใ—ใ‚‡ใ†: -{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฏ `Optional[str]` ๅž‹ใงใ€`None` ใ‚’่จฑๅฎนใ™ใ‚‹ `str` ๅž‹ใ‚’ๆ„ๅ‘ณใ—ใฆใŠใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `None` ใงใ™ใ€‚ใใฎใŸใ‚ใ€FastAPIใฏใใ‚ŒใŒๅฟ…้ ˆใงใฏใชใ„ใจ็†่งฃใ—ใพใ™ใ€‚ +ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฏ `str | None` ๅž‹ใงใ€`str` ๅž‹ใงใ™ใŒ `None` ใซใ‚‚ใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใ€ๅฎŸ้š›ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏ `None` ใชใฎใงใ€FastAPIใฏใใ‚ŒใŒๅฟ…้ ˆใงใฏใชใ„ใจ็†่งฃใ—ใพใ™ใ€‚ /// note | ๅ‚™่€ƒ -FastAPIใฏใ€ `q` ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `=None` ใงใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…้ ˆใงใฏใชใ„ใจ็†่งฃใ—ใพใ™ใ€‚ +FastAPIใฏใ€ `q` ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `= None` ใงใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…้ ˆใงใฏใชใ„ใจ็†่งฃใ—ใพใ™ใ€‚ -`Optional[str]` ใซใŠใ‘ใ‚‹ `Optional` ใฏFastAPIใซใฏๅˆฉ็”จใ•ใ‚Œใพใ›ใ‚“ใŒใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใซใ‚ˆใ‚‹ใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใจใ‚จใƒฉใƒผๆคœๅ‡บใ‚’ๅฏ่ƒฝใซใ—ใพใ™ใ€‚ +`str | None` ใ‚’ไฝฟใ†ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใซใ‚ˆใ‚‹ใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใจใ‚จใƒฉใƒผๆคœๅ‡บใ‚’ๅฏ่ƒฝใซใ—ใพใ™ใ€‚ /// -## ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฎ่ฟฝๅŠ  +## ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฎ่ฟฝๅŠ  { #additional-validation } -`q`ใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใงใ™ใŒใ€ใ‚‚ใ—ๅ€คใŒๆธกใ•ใ‚ŒใฆใใŸๅ ดๅˆใซใฏใ€**50ๆ–‡ๅญ—ใ‚’่ถ…ใˆใชใ„ใ“ใจ**ใ‚’ๅผทๅˆถใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +`q`ใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใงใ™ใŒใ€ใ‚‚ใ—ๅ€คใŒๆธกใ•ใ‚ŒใฆใใŸๅ ดๅˆใซใฏใ€**้•ทใ•ใŒ50ๆ–‡ๅญ—ใ‚’่ถ…ใˆใชใ„ใ“ใจ**ใ‚’ๅผทๅˆถใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -### `Query`ใฎใ‚คใƒณใƒใƒผใƒˆ +### `Query` ใจ `Annotated` ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-query-and-annotated } -ใใฎใŸใ‚ใซใ€ใพใšใฏ`fastapi`ใ‹ใ‚‰`Query`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: +ใใฎใŸใ‚ใซใ€ใพใšใฏไปฅไธ‹ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *} +* `fastapi` ใ‹ใ‚‰ `Query` +* `typing` ใ‹ใ‚‰ `Annotated` -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ`Query`ใ‚’ไฝฟ็”จ +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆไฝฟ็”จใ—ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ`max_length`ใ‚’50ใซ่จญๅฎšใ—ใพใ™: +/// info | ๆƒ…ๅ ฑ -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *} +FastAPI ใฏใƒใƒผใ‚ธใƒงใƒณ 0.95.0 ใง `Annotated` ใฎใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ ใ—๏ผˆๆŽจๅฅจใ—ๅง‹ใ‚๏ผ‰ใพใ—ใŸใ€‚ -ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค`None`ใ‚’`Query(default=None)`ใซ็ฝฎใๆ›ใˆใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใฎใงใ€`Query`ใฎๆœ€ๅˆใฎๅผ•ๆ•ฐใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใจๅŒใ˜ใงใ™ใ€‚ +ๅคใ„ใƒใƒผใ‚ธใƒงใƒณใฎๅ ดๅˆใ€`Annotated` ใ‚’ไฝฟใŠใ†ใจใ™ใ‚‹ใจใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ -ใชใฎใง: +`Annotated` ใ‚’ไฝฟใ†ๅ‰ใซใ€FastAPI ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ๅฐ‘ใชใใจใ‚‚ 0.95.1 ใซใ™ใ‚‹ใŸใ‚ใซใ€[FastAPI ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## `q` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ใง `Annotated` ใ‚’ไฝฟใ† { #use-annotated-in-the-type-for-the-q-parameter } + +ไปฅๅ‰ใ€[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} ใง `Annotated` ใ‚’ไฝฟใฃใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใงใใ‚‹ใจ่ชฌๆ˜Žใ—ใŸใ“ใจใ‚’่ฆšใˆใฆใ„ใพใ™ใ‹๏ผŸ + +ใ„ใ‚ˆใ„ใ‚ˆ FastAPI ใงไฝฟใ†ใจใใงใ™ใ€‚ ๐Ÿš€ + +ๆฌกใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ—ใŸ: + +//// tab | Python 3.10+ ```Python -q: Optional[str] = Query(default=None) +q: str | None = None ``` -...ใ‚’ไปฅไธ‹ใจๅŒใ˜ใ‚ˆใ†ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ‚ชใƒ—ใ‚ทใƒงใƒณใซใ—ใพใ™: +//// + +//// tab | Python 3.9+ ```Python -q: Optional[str] = None +q: Union[str, None] = None ``` -ใ—ใ‹ใ—ใ€ใ“ใ‚Œใฏใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๆ˜Ž็คบ็š„ใซๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ +//// -/// info | ๆƒ…ๅ ฑ +ใ“ใ‚Œใ‚’ `Annotated` ใงๅŒ…ใ‚“ใงใ€ๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: -FastAPIใฏไปฅไธ‹ใฎ้ƒจๅˆ†ใ‚’ๆฐ—ใซใ™ใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„: +//// tab | Python 3.10+ ```Python -= None +q: Annotated[str | None] = None ``` -ใ‚‚ใ—ใใฏ: +//// + +//// tab | Python 3.9+ ```Python -= Query(default=None) +q: Annotated[Union[str, None]] = None ``` -ใใ—ใฆใ€ `None` ใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใงใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅฟ…้ ˆใงใฏใชใ„ใจๆคœ็Ÿฅใ—ใพใ™ใ€‚ +//// + +ใฉใกใ‚‰ใ‚‚ๅŒใ˜ๆ„ๅ‘ณใงใ€`q` ใฏ `str` ใพใŸใฏ `None` ใซใชใ‚Šๅพ—ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ `None` ใงใ™ใ€‚ + +ใงใฏใ€้ข็™ฝใ„ใจใ“ใ‚ใซ้€ฒใฟใพใ—ใ‚‡ใ†ใ€‚ ๐ŸŽ‰ + +## `q` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎ `Annotated` ใซ `Query` ใ‚’่ฟฝๅŠ ใ™ใ‚‹ { #add-query-to-annotated-in-the-q-parameter } + +่ฟฝๅŠ ๆƒ…ๅ ฑ๏ผˆใ“ใฎๅ ดๅˆใฏ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ๏ผ‰ใ‚’ๅ…ฅใ‚Œใ‚‰ใ‚Œใ‚‹ `Annotated` ใŒใงใใŸใฎใงใ€`Annotated` ใฎไธญใซ `Query` ใ‚’่ฟฝๅŠ ใ—ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `max_length` ใ‚’ `50` ใซ่จญๅฎšใ—ใพใ™: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏๅผ•ใ็ถšใ `None` ใชใฎใงใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏไพ็„ถใจใ—ใฆใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€`Annotated` ใฎไธญใซ `Query(max_length=50)` ใ‚’ๅ…ฅใ‚Œใ‚‹ใ“ใจใงใ€ใ“ใฎๅ€คใซ **่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ** ใ‚’ใ—ใŸใ„ใ€ๆœ€ๅคง 50 ๆ–‡ๅญ—ใซใ—ใŸใ„ใ€ใจ FastAPI ใซไผใˆใฆใ„ใพใ™ใ€‚ ๐Ÿ˜Ž + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ“ใงใฏ **ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ** ใชใฎใง `Query()` ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ๅพŒใง `Path()`ใ€`Body()`ใ€`Header()`ใ€`Cookie()` ใชใฉใ€`Query()` ใจๅŒใ˜ๅผ•ๆ•ฐใ‚’ๅ—ใ‘ๅ–ใ‚Œใ‚‹ใ‚‚ใฎใ‚‚่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +/// + +FastAPI ใฏๆฌกใ‚’่กŒใ„ใพใ™: + +* ๆœ€ๅคง้•ทใŒ 50 ๆ–‡ๅญ—ใงใ‚ใ‚‹ใ“ใจใ‚’็ขบใ‹ใ‚ใ‚‹ใ‚ˆใ†ใƒ‡ใƒผใ‚ฟใ‚’ **ๆคœ่จผ** ใ™ใ‚‹ +* ใƒ‡ใƒผใ‚ฟใŒๆœ‰ๅŠนใงใชใ„ใจใใซใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ **ๆ˜Ž็ขบใชใ‚จใƒฉใƒผ** ใ‚’่กจ็คบใ™ใ‚‹ +* OpenAPI ใ‚นใ‚ญใƒผใƒžใฎ *path operation* ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ **ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–** ใ™ใ‚‹๏ผˆใใฎ็ตๆžœใ€**่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI** ใซ่กจ็คบใ•ใ‚Œใพใ™๏ผ‰ + +## ไปฃๆ›ฟ๏ผˆๅคใ„ๆ–นๆณ•๏ผ‰: ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆใฎ `Query` { #alternative-old-query-as-the-default-value } -`Optional` ใฎ้ƒจๅˆ†ใฏใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใซใ‚ˆใ‚‹ใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๅฏ่ƒฝใซใ—ใพใ™ใ€‚ +FastAPI ใฎไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณ๏ผˆ0.95.0 ใ‚ˆใ‚Šๅ‰๏ผ‰ใงใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ `Query` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใ€`Annotated` ใฎไธญใซๅ…ฅใ‚Œใ‚‹ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ใ“ใ‚Œใ‚’ไฝฟใฃใŸใ‚ณใƒผใƒ‰ใ‚’่ฆ‹ใ‹ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใฎใงใ€่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆ–ฐใ—ใ„ใ‚ณใƒผใƒ‰ใงใฏใ€ๅฏ่ƒฝใช้™ใ‚ŠไธŠใง่ชฌๆ˜Žใ—ใŸใจใŠใ‚Š `Annotated` ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚่ค‡ๆ•ฐใฎๅˆฉ็‚น๏ผˆๅพŒ่ฟฐ๏ผ‰ใŒใ‚ใ‚Šใ€ๆฌ ็‚นใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ๐Ÿฐ /// +้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ `Query()` ใ‚’ไฝฟใ„ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `max_length` ใ‚’ 50 ใซ่จญๅฎšใ™ใ‚‹ๆ–นๆณ•ใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +ใ“ใฎๅ ดๅˆ๏ผˆ`Annotated` ใ‚’ไฝฟใ‚ใชใ„ๅ ดๅˆ๏ผ‰ใ€้–ขๆ•ฐๅ†…ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค `None` ใ‚’ `Query()` ใซ็ฝฎใๆ›ใˆใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€`Query(default=None)` ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏ๏ผˆๅฐ‘ใชใใจใ‚‚ FastAPI ใซใจใฃใฆใฏ๏ผ‰ใใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใจๅŒใ˜็›ฎ็š„ใ‚’ๆžœใŸใ—ใพใ™ใ€‚ + +ใชใฎใง: + +```Python +q: str | None = Query(default=None) +``` + +...ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค `None` ใ‚’ๆŒใคใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใชใ‚Šใ€ไปฅไธ‹ใจๅŒใ˜ใงใ™: + + +```Python +q: str | None = None +``` + +ใŸใ ใ— `Query` ใฎใƒใƒผใ‚ธใƒงใƒณใงใฏใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹ใ“ใจใ‚’ๆ˜Ž็คบ็š„ใซๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ + ใใ—ใฆใ€ใ•ใ‚‰ใซๅคšใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’`Query`ใซๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใฎๅ ดๅˆใ€ๆ–‡ๅญ—ๅˆ—ใซ้ฉ็”จใ•ใ‚Œใ‚‹ใ€`max_length`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ ```Python -q: Union[str, None] = Query(default=None, max_length=50) +q: str | None = Query(default=None, max_length=50) ``` ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒ‡ใƒผใ‚ฟใ‚’ๆคœ่จผใ—ใ€ใƒ‡ใƒผใ‚ฟใŒๆœ‰ๅŠนใงใชใ„ๅ ดๅˆใฏๆ˜Ž็ขบใชใ‚จใƒฉใƒผใ‚’่กจ็คบใ—ใ€OpenAPIใ‚นใ‚ญใƒผใƒžใฎใ€€*path operation* ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จ˜่ผ‰ใ—ใพใ™ใ€‚ -## ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ใ•ใ‚‰ใซ่ฟฝๅŠ ใ™ใ‚‹ +### ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆใฎ `Query` ใพใŸใฏ `Annotated` ๅ†…ใฎ `Query` { #query-as-the-default-value-or-in-annotated } + +`Annotated` ใฎไธญใง `Query` ใ‚’ไฝฟใ†ๅ ดๅˆใ€`Query` ใฎ `default` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏไฝฟใˆใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +ใใฎไปฃใ‚ใ‚Šใซใ€้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎŸ้š›ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ไฝฟใ„ใพใ™ใ€‚ใใ†ใ—ใชใ„ใจๆ•ดๅˆๆ€งใŒๅ–ใ‚Œใชใใชใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ“ใ‚Œใฏ่จฑๅฏใ•ใ‚Œใพใ›ใ‚“: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...ใชใœใชใ‚‰ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `"rick"` ใชใฎใ‹ `"morty"` ใชใฎใ‹ใŒไธๆ˜Ž็ขบใ ใ‹ใ‚‰ใงใ™ใ€‚ + +ใใฎใŸใ‚ใ€๏ผˆใงใใ‚Œใฐ๏ผ‰ๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...ใพใŸใฏใ€ๅคใ„ใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚นใงใฏๆฌกใฎใ‚ˆใ†ใชใ‚‚ใฎใŒ่ฆ‹ใคใ‹ใ‚‹ใงใ—ใ‚‡ใ†: + +```Python +q: str = Query(default="rick") +``` + +### `Annotated` ใฎๅˆฉ็‚น { #advantages-of-annotated } + +้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚นใ‚ฟใ‚คใƒซใงใฏใชใใ€**`Annotated` ใ‚’ไฝฟใ†ใ“ใจใŒๆŽจๅฅจ** ใ•ใ‚Œใพใ™ใ€‚่ค‡ๆ•ฐใฎ็†็”ฑใง **ใ‚ˆใ‚Š่‰ฏใ„** ใ‹ใ‚‰ใงใ™ใ€‚ ๐Ÿค“ + +**้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ** ใฎ **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค** ใฏ **ๅฎŸ้š›ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค** ใงใ‚ใ‚Šใ€Python ๅ…จ่ˆฌใจใ—ใฆใ‚ˆใ‚Š็›ดๆ„Ÿ็š„ใงใ™ใ€‚ ๐Ÿ˜Œ + +FastAPI ใชใ—ใงๅŒใ˜้–ขๆ•ฐใ‚’ **ๅˆฅใฎๅ ดๆ‰€** ใ‹ใ‚‰ **ๅ‘ผใณๅ‡บใ—ใฆใ‚‚**ใ€**ๆœŸๅพ…ใฉใŠใ‚Šใซๅ‹•ไฝœ** ใ—ใพใ™ใ€‚**ๅฟ…้ ˆ** ใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใ„๏ผ‰ใŒใ‚ใ‚Œใฐใ€**ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผ** ใŒใ‚จใƒฉใƒผใง็Ÿฅใ‚‰ใ›ใฆใใ‚Œใพใ™ใ—ใ€**Python** ใ‚‚ๅฟ…้ ˆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ•ใšใซๅฎŸ่กŒใ™ใ‚‹ใจๆ–‡ๅฅใ‚’่จ€ใ„ใพใ™ใ€‚ + +`Annotated` ใ‚’ไฝฟใ‚ใšใซ **๏ผˆๅคใ„๏ผ‰ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚นใ‚ฟใ‚คใƒซ** ใ‚’ไฝฟใ†ๅ ดๅˆใ€FastAPI ใชใ—ใงใใฎ้–ขๆ•ฐใ‚’ **ๅˆฅใฎๅ ดๆ‰€** ใงๅ‘ผใณๅ‡บใ™ใจใใ€ๆญฃใ—ใๅ‹•ใ‹ใ™ใŸใ‚ใซ้–ขๆ•ฐใธๅผ•ๆ•ฐใ‚’ๆธกใ™ใ“ใจใ‚’ **่ฆšใˆใฆใŠใ** ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใ†ใ—ใชใ„ใจๅ€คใŒๆœŸๅพ…ใจ็•ฐใชใ‚Šใพใ™๏ผˆไพ‹ใˆใฐ `str` ใฎไปฃใ‚ใ‚Šใซ `QueryInfo` ใ‹ใ€ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใซใชใ‚Šใพใ™๏ผ‰ใ€‚ใพใŸใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚‚่ญฆๅ‘Šใ›ใšใ€Python ใ‚‚ใใฎ้–ขๆ•ฐใฎๅฎŸ่กŒใงๆ–‡ๅฅใ‚’่จ€ใ„ใพใ›ใ‚“ใ€‚ๅ†…้ƒจใฎๅ‡ฆ็†ใŒใ‚จใƒฉใƒผใซใชใ‚‹ใจใใซๅˆใ‚ใฆๅ•้กŒใŒๅ‡บใพใ™ใ€‚ + +`Annotated` ใฏ่ค‡ๆ•ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ๆŒใฆใ‚‹ใฎใงใ€Typer ใฎใ‚ˆใ†ใชๅˆฅใƒ„ใƒผใƒซใจๅŒใ˜้–ขๆ•ฐใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ๐Ÿš€ + +## ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ใ•ใ‚‰ใซ่ฟฝๅŠ ใ™ใ‚‹ { #add-more-validations } ใƒ‘ใƒฉใƒกใƒผใ‚ฟ`min_length`ใ‚‚่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial003.py hl[10] *} +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} -## ๆญฃ่ฆ่กจ็พใฎ่ฟฝๅŠ  +## ๆญฃ่ฆ่กจ็พใฎ่ฟฝๅŠ  { #add-regular-expressions } -ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒไธ€่‡ดใ™ใ‚‹ในใๆญฃ่ฆ่กจ็พใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒไธ€่‡ดใ™ใ‚‹ในใ ๆญฃ่ฆ่กจ็พ `pattern` ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial004.py hl[11] *} +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} -ใ“ใฎ็‰นๅฎšใฎๆญฃ่ฆ่กจ็พใฏๅ—ใ‘ๅ–ใฃใŸใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅ€คใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: +ใ“ใฎ็‰นๅฎšใฎๆญฃ่ฆ่กจ็พใƒ‘ใ‚ฟใƒผใƒณใฏๅ—ใ‘ๅ–ใฃใŸใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅ€คใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: * `^`: ใฏใ€ใ“ใ‚Œไปฅ้™ใฎๆ–‡ๅญ—ใงๅง‹ใพใ‚Šใ€ใ“ใ‚Œใ‚ˆใ‚Šไปฅๅ‰ใซใฏๆ–‡ๅญ—ใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ * `fixedquery`: ใฏใ€ๆญฃ็ขบใช`fixedquery`ใ‚’ๆŒใฃใฆใ„ใพใ™. * `$`: ใง็ต‚ใ‚ใ‚‹ๅ ดๅˆใ€`fixedquery`ไปฅ้™ใซใฏๆ–‡ๅญ—ใฏใ‚ใ‚Šใพใ›ใ‚“. -ใ‚‚ใ—ใ“ใ‚Œใ‚‰ใ™ในใฆใฎ **ๆญฃ่ฆ่กจ็พ**ใฎใ‚ขใ‚คใƒ‡ใ‚ขใซใคใ„ใฆ่ฟทใฃใฆใ„ใฆใ‚‚ใ€ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ๅคšใใฎไบบใซใจใฃใฆ้›ฃใ—ใ„่ฉฑ้กŒใงใ™ใ€‚ๆญฃ่ฆ่กจ็พใ‚’ๅฟ…่ฆใจใ—ใชใใฆใ‚‚ใ€ใพใ ใ€ๅคšใใฎใ“ใจใŒใงใใพใ™ใ€‚ +ใ‚‚ใ—ใ“ใ‚Œใ‚‰ใ™ในใฆใฎ **ใ€Œๆญฃ่ฆ่กจ็พใ€** ใฎใ‚ขใ‚คใƒ‡ใ‚ขใซใคใ„ใฆ่ฟทใฃใฆใ„ใฆใ‚‚ใ€ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ๅคšใใฎไบบใซใจใฃใฆ้›ฃใ—ใ„่ฉฑ้กŒใงใ™ใ€‚ๆญฃ่ฆ่กจ็พใ‚’ๅฟ…่ฆใจใ—ใชใใฆใ‚‚ใ€ใพใ ใ€ๅคšใใฎใ“ใจใŒใงใใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใ‚ใชใŸใŒใใ‚Œใ‚‰ใ‚’ๅฟ…่ฆใจใ—ใ€ๅญฆใถใจใใซใฏใ™ใงใซใ€ **FastAPI**ใง็›ดๆŽฅใใ‚Œใ‚‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใ‚Œใงใ€ๅฟ…่ฆใซใชใฃใŸใจใใซใฏใ„ใคใงใ‚‚ **FastAPI** ใงไฝฟใˆใ‚‹ใ“ใจใŒๅˆ†ใ‹ใ‚Šใพใ—ใŸใ€‚ -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค { #default-values } -็ฌฌไธ€ๅผ•ๆ•ฐใซ`None`ใ‚’ๆธกใ—ใฆใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ไป–ใฎๅ€คใ‚’ๆธกใ™ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใ‚‚ใกใ‚ใ‚“ใ€`None` ไปฅๅค–ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚‚ไฝฟใˆใพใ™ใ€‚ -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใฎ`min_length`ใ‚’`3`ใจใ—ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’`fixedquery`ใจใ—ใฆใฟใพใ—ใ‚‡ใ†: +ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฎ `min_length` ใ‚’ `3` ใจใ—ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ `"fixedquery"` ใจใ—ใฆๅฎฃ่จ€ใ—ใŸใ„ใจใ—ใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} /// note | ๅ‚™่€ƒ -ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใจใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏไปปๆ„ใซใชใ‚Šใพใ™ใ€‚ +`None` ใ‚’ๅซใ‚€ไปปๆ„ใฎๅž‹ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใ‚ใ‚‹ใจใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซ๏ผˆๅฟ…้ ˆใงใฏใชใ„๏ผ‰ใซใชใ‚Šใพใ™ใ€‚ /// -## ๅฟ…้ ˆใซใ™ใ‚‹ +## ๅฟ…้ ˆใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #required-parameters } -ใ“ใ‚ŒไปฅไธŠใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใฎใชใ„ๅ ดๅˆใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒ‡ๅฎšใ—ใชใ„ใ ใ‘ใงใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใ‚’ๅฟ…้ ˆใซใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ไปฅไธ‹ใฎใ‚ˆใ†ใซ: +ใ“ใ‚ŒไปฅไธŠใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚„ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใชใ„ใ ใ‘ใงใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใ‚’ๅฟ…้ ˆใซใงใใพใ™ใ€‚ไปฅไธ‹ใฎใ‚ˆใ†ใซ: ```Python q: str @@ -123,42 +231,42 @@ q: str ไปฅไธ‹ใฎไปฃใ‚ใ‚Šใซ: ```Python -q: Union[str, None] = None +q: str | None = None ``` -็พๅœจใฏไปฅไธ‹ใฎไพ‹ใฎใ‚ˆใ†ใซ`Query`ใงๅฎฃ่จ€ใ—ใฆใ„ใพใ™: +ใ—ใ‹ใ—ไปŠใฏใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซ `Query` ใงๅฎฃ่จ€ใ—ใฆใ„ใพใ™: ```Python -q: Union[str, None] = Query(default=None, min_length=3) +q: Annotated[str | None, Query(min_length=3)] = None ``` -ใใฎใŸใ‚ใ€`Query`ใ‚’ไฝฟ็”จใ—ใฆๅฟ…้ ˆใฎๅ€คใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€็ฌฌไธ€ๅผ•ๆ•ฐใซ`...`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใใฎใŸใ‚ใ€`Query` ใ‚’ไฝฟใ„ใชใŒใ‚‰ๅ€คใ‚’ๅฟ…้ ˆใจใ—ใฆๅฎฃ่จ€ใ—ใŸใ„ๅ ดๅˆใฏใ€ๅ˜ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใพใ›ใ‚“: -{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -/// info | ๆƒ…ๅ ฑ +### ๅฟ…้ ˆใ€`None` ใซใงใใ‚‹ { #required-can-be-none } -ใ“ใ‚Œใพใง`...`ใ‚’่ฆ‹ใŸใ“ใจใŒใชใ„ๆ–นใธ: ใ“ใ‚Œใฏ็‰นๆฎŠใชๅ˜ไธ€ๅ€คใงใ™ใ€‚Pythonใฎไธ€้ƒจใงใ‚ใ‚Šใ€"Ellipsis"ใจๅ‘ผใฐใ‚Œใฆใ„ใพใ™ใ€‚ +ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ `None` ใ‚’ๅ—ใ‘ไป˜ใ‘ใ‚‹ใŒใ€ใใ‚Œใงใ‚‚ๅฟ…้ ˆใงใ‚ใ‚‹ใ€ใจๅฎฃ่จ€ใงใใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๅ€คใŒ `None` ใงใ‚ใฃใฆใ‚‚ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๅ€คใ‚’้€ใ‚‰ใชใ‘ใ‚Œใฐใชใ‚‰ใชใใชใ‚Šใพใ™ใ€‚ -/// +ใใฎใŸใ‚ใซใ€`None` ใŒๆœ‰ๅŠนใชๅž‹ใงใ‚ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใ—ใคใคใ€ๅ˜ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใพใ›ใ‚“: -ใ“ใ‚Œใฏ **FastAPI** ใซใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅฟ…้ ˆใงใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใ‚‰ใ›ใพใ™ใ€‚ +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -## ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒชใ‚นใƒˆ / ่ค‡ๆ•ฐใฎๅ€ค +## ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒชใ‚นใƒˆ / ่ค‡ๆ•ฐใฎๅ€ค { #query-parameter-list-multiple-values } -ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆ˜Ž็คบ็š„ใซ`Query`ใงๅฎฃ่จ€ใ—ใŸๅ ดๅˆใ€ๅ€คใฎใƒชใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซๅฎฃ่จ€ใ—ใŸใ‚Šใ€่ค‡ๆ•ฐใฎๅ€คใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซๅฎฃ่จ€ใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆ˜Ž็คบ็š„ใซ `Query` ใงๅฎš็พฉใ™ใ‚‹ใจใ€ๅ€คใฎใƒชใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซๅฎฃ่จ€ใ—ใŸใ‚Šใ€่จ€ใ„ๆ›ใˆใ‚‹ใจ่ค‡ๆ•ฐใฎๅ€คใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซๅฎฃ่จ€ใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€URLๅ†…ใซ่ค‡ๆ•ฐๅ›žๅ‡บ็พใ™ใ‚‹ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ`q`ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -ใใ—ใฆURLใฏไปฅไธ‹ใงใ™: +ใใ—ใฆใ€ๆฌกใฎใ‚ˆใ†ใช URL ใชใ‚‰: ``` http://localhost:8000/items/?q=foo&q=bar ``` -่ค‡ๆ•ฐใฎ*ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใฎๅ€ค`q`๏ผˆ`foo`ใจ`bar`๏ผ‰ใ‚’*path operation้–ขๆ•ฐ*ๅ†…ใง*้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ*`q`ใจใ—ใฆPythonใฎ`list`ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +*path operation function* ๅ†…ใฎ *function parameter* `q` ใงใ€่ค‡ๆ•ฐใฎ `q` *query parameters'* ๅ€ค๏ผˆ`foo` ใจ `bar`๏ผ‰ใ‚’ Python ใฎ `list` ใจใ—ใฆๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ ใใฎใŸใ‚ใ€ใ“ใฎURLใฎใƒฌใ‚นใƒใƒณใ‚นใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: @@ -179,15 +287,15 @@ http://localhost:8000/items/?q=foo&q=bar ๅฏพ่ฉฑ็š„APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏ่ค‡ๆ•ฐใฎๅ€คใ‚’่จฑๅฏใ™ใ‚‹ใŸใ‚ใซ่‡ชๅ‹•็š„ใซๆ›ดๆ–ฐใ•ใ‚Œใพใ™ใ€‚ - + -### ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒชใ‚นใƒˆ / ่ค‡ๆ•ฐใฎๅ€ค +### ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒชใ‚นใƒˆ / ่ค‡ๆ•ฐใฎๅ€ค { #query-parameter-list-multiple-values-with-defaults } -ใพใŸใ€ๅ€คใŒๆŒ‡ๅฎšใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ`list`ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ใพใŸใ€ๅ€คใŒๆŒ‡ๅฎšใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ `list` ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} -ไปฅไธ‹ใฎURLใ‚’้–‹ใใจ: +ไปฅไธ‹ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจ: ``` http://localhost:8000/items/ @@ -204,21 +312,21 @@ http://localhost:8000/items/ } ``` -#### `list`ใ‚’ไฝฟใ† +#### `list` ใ ใ‘ใ‚’ไฝฟใ† { #using-just-list } -`List[str]`ใฎไปฃใ‚ใ‚Šใซ็›ดๆŽฅ`list`ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: +`list[str]` ใฎไปฃใ‚ใ‚Šใซ็›ดๆŽฅ `list` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} /// note | ๅ‚™่€ƒ ใ“ใฎๅ ดๅˆใ€FastAPIใฏใƒชใ‚นใƒˆใฎๅ†…ๅฎนใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใชใ„ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ -ไพ‹ใˆใฐ`List[int]`ใฏใƒชใ‚นใƒˆใฎๅ†…ๅฎนใŒๆ•ดๆ•ฐใงใ‚ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™(ใใ—ใฆใ€ๆ–‡ๆ›ธๅŒ–ใ—ใพใ™)ใ€‚ใ—ใ‹ใ—`list`ใ ใ‘ใงใฏใใ†ใ—ใพใ›ใ‚“ใ€‚ +ไพ‹ใˆใฐ`list[int]`ใฏใƒชใ‚นใƒˆใฎๅ†…ๅฎนใŒๆ•ดๆ•ฐใงใ‚ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™(ใใ—ใฆใ€ๆ–‡ๆ›ธๅŒ–ใ—ใพใ™)ใ€‚ใ—ใ‹ใ—`list`ใ ใ‘ใงใฏใใ†ใ—ใพใ›ใ‚“ใ€‚ /// -## ใ‚ˆใ‚Šๅคšใใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ +## ใ‚ˆใ‚Šๅคšใใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ { #declare-more-metadata } ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ้–ขใ™ใ‚‹ๆƒ…ๅ ฑใ‚’ใ•ใ‚‰ใซ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -234,13 +342,13 @@ http://localhost:8000/items/ `title`ใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial007.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} `description`ใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *} +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} -## ใ‚จใ‚คใƒชใ‚ขใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใ‚จใ‚คใƒชใ‚ขใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #alias-parameters } ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ`item-query`ใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใจใ—ใพใ™. @@ -258,23 +366,91 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ใใ‚Œใชใ‚‰ใฐใ€`alias`ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ‚จใ‚คใƒชใ‚ขใ‚นใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅ€คใ‚’่ฆ‹ใคใ‘ใ‚‹ใฎใซไฝฟ็”จใ•ใ‚Œใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} -## ้žๆŽจๅฅจใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’้žๆŽจๅฅจใซใ™ใ‚‹ { #deprecating-parameters } -ใ•ใฆใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๆฐ—ใซๅ…ฅใ‚‰ใชใใชใฃใŸใจใ—ใพใ—ใ‚‡ใ† +ใ•ใฆใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๆฐ—ใซๅ…ฅใ‚‰ใชใใชใฃใŸใจใ—ใพใ—ใ‚‡ใ†ใ€‚ -ใใ‚Œใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใ‚‹ใฎใงใ€ใ—ใฐใ‚‰ใใฏๆฎ‹ใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใŒใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏ้žๆŽจๅฅจใจๆ˜Ž่จ˜ใ—ใฆใŠใใŸใ„ใงใ™ใ€‚ +ใใ‚Œใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใ‚‹ใฎใงใ€ใ—ใฐใ‚‰ใใฏๆฎ‹ใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใŒใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏdeprecatedใจๆ˜Ž่จ˜ใ—ใฆใŠใใŸใ„ใงใ™ใ€‚ ใใฎๅ ดๅˆใ€`Query`ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟ`deprecated=True`ใ‚’ๆธกใ—ใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *} +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: - + -## ใพใจใ‚ +## OpenAPI ใ‹ใ‚‰ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’้™คๅค–ใ™ใ‚‹ { #exclude-parameters-from-openapi } + +็”Ÿๆˆใ•ใ‚Œใ‚‹ OpenAPI ใ‚นใ‚ญใƒผใƒž๏ผˆใคใพใ‚Š่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ๏ผ‰ใ‹ใ‚‰ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’้™คๅค–ใ™ใ‚‹ใซใฏใ€`Query` ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `include_in_schema` ใ‚’ `False` ใซ่จญๅฎšใ—ใพใ™: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## ใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ { #custom-validation } + +ไธŠใง็คบใ—ใŸใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใงใใชใ„ **ใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ** ใŒๅฟ…่ฆใซใชใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใฎๅ ดๅˆใ€้€šๅธธใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ๏ผˆไพ‹: ๅ€คใŒ `str` ใงใ‚ใ‚‹ใ“ใจใฎๆคœ่จผ๏ผ‰ใฎๅพŒใซ้ฉ็”จใ•ใ‚Œใ‚‹ **ใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ฟ้–ขๆ•ฐ** ใ‚’ไฝฟใˆใพใ™ใ€‚ + +ใ“ใ‚Œใ‚’่กŒใ†ใซใฏใ€`Annotated` ใฎไธญใง Pydantic ใฎ `AfterValidator` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +Pydantic ใซใฏ `BeforeValidator` ใชใฉใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ ๐Ÿค“ + +/// + +ไพ‹ใˆใฐใ€ใ“ใฎใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ฟใฏใ€ISBN ใฎๆ›ธ็ฑ็•ชๅทใชใ‚‰ item ID ใŒ `isbn-` ใงๅง‹ใพใ‚‹ใ“ใจใ€IMDB ใฎ movie URL ID ใชใ‚‰ `imdb-` ใงๅง‹ใพใ‚‹ใ“ใจใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | ๆƒ…ๅ ฑ + +ใ“ใ‚Œใฏ Pydantic ใƒใƒผใ‚ธใƒงใƒณ 2 ไปฅไธŠใงๅˆฉ็”จใงใใพใ™ใ€‚ ๐Ÿ˜Ž + +/// + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚„ๅˆฅใฎ API ใชใฉใ€ไฝ•ใ‚‰ใ‹ใฎ **ๅค–้ƒจใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ** ใจใฎ้€šไฟกใŒๅฟ…่ฆใชใ‚ฟใ‚คใƒ—ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ไปฃใ‚ใ‚Šใซ **FastAPI Dependencies** ใ‚’ไฝฟใ†ในใใงใ™ใ€‚ใ“ใ‚Œใซใคใ„ใฆใฏๅพŒใงๅญฆใณใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ฟใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใงๆไพ›ใ•ใ‚ŒใŸ **ๅŒใ˜ใƒ‡ใƒผใ‚ฟใฎใฟ** ใงใƒใ‚งใƒƒใ‚ฏใงใใ‚‹ใ‚‚ใฎๅ‘ใ‘ใงใ™ใ€‚ + +/// + +### ใใฎใ‚ณใƒผใƒ‰ใ‚’็†่งฃใ™ใ‚‹ { #understand-that-code } + +้‡่ฆใชใฎใฏใ€**`Annotated` ใฎไธญใง้–ขๆ•ฐใจไธ€็ท’ใซ `AfterValidator` ใ‚’ไฝฟใ†ใ“ใจ** ใ ใ‘ใงใ™ใ€‚ใ“ใฎ้ƒจๅˆ†ใฏ้ฃ›ใฐใ—ใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ ๐Ÿคธ + +--- + +ใŸใ ใ—ใ€ใ“ใฎๅ…ทไฝ“็š„ใชใ‚ณใƒผใƒ‰ไพ‹ใŒๆฐ—ใซใชใฃใฆใ„ใฆใ€ใพใ ่ˆˆๅ‘ณใŒ็ถšใใชใ‚‰ใ€่ฟฝๅŠ ใฎ่ฉณ็ดฐใ‚’็คบใ—ใพใ™ใ€‚ + +#### `value.startswith()` ใ‚’ไฝฟใ†ๆ–‡ๅญ—ๅˆ— { #string-with-value-startswith } + +ๆฐ—ใฅใใพใ—ใŸใ‹๏ผŸ`value.startswith()` ใ‚’ไฝฟใ†ๆ–‡ๅญ—ๅˆ—ใฏใ‚ฟใƒ—ใƒซใ‚’ๅ—ใ‘ๅ–ใ‚Œใ€ใใฎใ‚ฟใƒ—ใƒซๅ†…ใฎๅ„ๅ€คใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### ใƒฉใƒณใƒ€ใƒ ใชใ‚ขใ‚คใƒ†ใƒ  { #a-random-item } + +`data.items()` ใงใ€่พžๆ›ธใฎๅ„ใ‚ขใ‚คใƒ†ใƒ ใฎใ‚ญใƒผใจๅ€คใ‚’ๅซใ‚€ใ‚ฟใƒ—ใƒซใ‚’ๆŒใค ๅๅพฉๅฏ่ƒฝใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ + +ใ“ใฎๅๅพฉๅฏ่ƒฝใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ `list(data.items())` ใง้ฉๅˆ‡ใช `list` ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ + +ใใ—ใฆ `random.choice()` ใงใใฎ `list` ใ‹ใ‚‰ **ใƒฉใƒณใƒ€ใƒ ใชๅ€ค** ใ‚’ๅ–ๅพ—ใ™ใ‚‹ใฎใงใ€`(id, name)` ใฎใ‚ฟใƒ—ใƒซใ‚’ๅพ—ใพใ™ใ€‚ใ“ใ‚Œใฏ `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ + +ๆฌกใซใ€ใใฎใ‚ฟใƒ—ใƒซใฎ **2ใคใฎๅ€คใ‚’ไปฃๅ…ฅ** ใ—ใฆใ€ๅค‰ๆ•ฐ `id` ใจ `name` ใซๅ…ฅใ‚Œใพใ™ใ€‚ + +ใคใพใ‚Šใ€ใƒฆใƒผใ‚ถใƒผใŒ item ID ใ‚’ๆไพ›ใ—ใชใ‹ใฃใŸๅ ดๅˆใงใ‚‚ใ€ใƒฉใƒณใƒ€ใƒ ใชๆๆกˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ + +...ใ“ใ‚Œใ‚’ **ๅ˜ไธ€ใฎใ‚ทใƒณใƒ—ใƒซใช1่กŒ** ใง่กŒใฃใฆใ„ใพใ™ใ€‚ ๐Ÿคฏ Python ใŒๅฅฝใใซใชใ‚Šใพใ›ใ‚“ใ‹๏ผŸ ๐Ÿ + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## ใพใจใ‚ { #recap } ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ่ฟฝๅŠ ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -285,12 +461,14 @@ http://127.0.0.1:8000/items/?item-query=foobaritems * `description` * `deprecated` -ๆ–‡ๅญ—ๅˆ—ใฎใŸใ‚ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ: +ๆ–‡ๅญ—ๅˆ—ใซๅ›บๆœ‰ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ: * `min_length` * `max_length` -* `regex` +* `pattern` + +`AfterValidator` ใ‚’ไฝฟใฃใŸใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€‚ -ใ“ใฎไพ‹ใงใฏใ€`str`ใฎๅ€คใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚ +ใ“ใฎไพ‹ใงใฏใ€`str` ใฎๅ€คใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚ ๆ•ฐๅ€คใฎใ‚ˆใ†ใชไป–ใฎๅž‹ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใฏๆฌกใฎ็ซ ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 74e455579e..41e51ed782 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -1,8 +1,8 @@ -# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ +# ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #query-parameters } -ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใชใ„้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใใ‚Œใ‚‰ใฏ่‡ชๅ‹•็š„ใซ "ใ‚ฏใ‚จใƒช" ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ +ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใชใ„้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใใ‚Œใ‚‰ใฏ่‡ชๅ‹•็š„ใซใ€Œใ‚ฏใ‚จใƒชใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ -{* ../../docs_src/query_params/tutorial001.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} ใ‚ฏใ‚จใƒชใฏURLๅ†…ใง `?` ใฎๅพŒใซ็ถšใใ‚ญใƒผใจใƒใƒชใƒฅใƒผใฎ็ต„ใงใ€ `&` ใงๅŒบๅˆ‡ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -24,11 +24,11 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ้ฉ็”จใ•ใ‚Œใ‚‹ๅ‡ฆ็†ใจๅฎŒๅ…จใซๅŒๆง˜ใชๅ‡ฆ็†ใŒใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใ‚‚ๆ–ฝใ•ใ‚Œใพใ™: * ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆ (ๆ˜Žใ‚‰ใ‹ใซ) -* ใƒ‡ใƒผใ‚ฟใ€Œ่งฃๆžใ€ +* ใƒ‡ใƒผใ‚ฟ ใ€Œ่งฃๆžใ€ * ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ * ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆ -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ { #defaults } ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‘ใ‚นใฎๅ›บๅฎš้ƒจๅˆ†ใงใฏใชใ„ใฎใงใ€ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใจใ—ใŸใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ใ‚‚ใคใ“ใจใŒใงใใพใ™ใ€‚ @@ -55,13 +55,13 @@ http://127.0.0.1:8000/items/?skip=20 ้–ขๆ•ฐๅ†…ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅ€คใฏไปฅไธ‹ใฎๆง˜ใซใชใ‚Šใพใ™: * `skip=20`: URLๅ†…ใซใ‚ปใƒƒใƒˆใ—ใŸใŸใ‚ -* `limit=10`: ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค +* `limit=10`: ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ ใฃใŸใŸใ‚ -## ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใชใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #optional-parameters } ๅŒๆง˜ใซใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ `None` ใจใ™ใ‚‹ใ“ใจใงใ€ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใชใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/query_params/tutorial002.py hl[9] *} +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} ใ“ใฎๅ ดๅˆใ€้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฏใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใจใชใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ `None` ใซใชใ‚Šใพใ™ใ€‚ @@ -71,11 +71,11 @@ http://127.0.0.1:8000/items/?skip=20 /// -## ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ๅค‰ๆ› +## ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ๅค‰ๆ› { #query-parameter-type-conversion } -`bool` ๅž‹ใ‚‚ๅฎฃ่จ€ใงใใพใ™ใ€‚ใ“ใ‚Œใฏไปฅไธ‹ใฎๆง˜ใซๅค‰ๆ›ใ•ใ‚Œใพใ™: +`bool` ๅž‹ใ‚‚ๅฎฃ่จ€ใงใใ€ๅค‰ๆ›ใ•ใ‚Œใพใ™: -{* ../../docs_src/query_params/tutorial003.py hl[9] *} +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} ใ“ใฎๅ ดๅˆใ€ไปฅไธ‹ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจ: @@ -109,27 +109,28 @@ http://127.0.0.1:8000/items/foo?short=yes ใ‚‚ใ—ใใฏใ€ไป–ใฎๅคงๆ–‡ๅญ—ๅฐๆ–‡ๅญ—ใฎใƒใƒชใ‚จใƒผใ‚ทใƒงใƒณ (ใ‚ขใƒƒใƒ‘ใƒผใ‚ฑใƒผใ‚นใ€ๆœ€ๅˆใฎๆ–‡ๅญ—ใ ใ‘ใ‚ขใƒƒใƒ‘ใƒผใ‚ฑใƒผใ‚นใ€ใชใฉ)ใงใ€้–ขๆ•ฐใฏ `short` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `True` ใช `bool` ๅ€คใจใ—ใฆๆ‰ฑใ„ใพใ™ใ€‚ใใ‚Œไปฅๅค–ใฏ `False` ใซใชใ‚Šใพใ™ใ€‚ -## ่ค‡ๆ•ฐใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ -่ค‡ๆ•ฐใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅŒๆ™‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚**FastAPI**ใฏไบ’ใ„ใ‚’ๅŒบๅˆฅใงใใพใ™ใ€‚ +## ่ค‡ๆ•ฐใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #multiple-path-and-query-parameters } + +่ค‡ๆ•ฐใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅŒๆ™‚ใซๅฎฃ่จ€ใงใใพใ™ใ€‚**FastAPI**ใฏใฉใ‚ŒใŒใฉใ‚Œใ‹ใ‚’ๆŠŠๆกใ—ใฆใ„ใพใ™ใ€‚ ใใ—ใฆ็‰นๅฎšใฎ้ †ๅบใงๅฎฃ่จ€ใ—ใชใใฆใ‚‚ใ‚ˆใ„ใงใ™ใ€‚ ๅๅ‰ใงๅˆคๅˆฅใ•ใ‚Œใพใ™: -{* ../../docs_src/query_params/tutorial004.py hl[8,10] *} +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## ๅฟ…้ ˆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ +## ๅฟ…้ ˆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #required-query-parameters } -ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟไปฅๅค–ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ (ไปŠใฎใจใ“ใ‚ใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใฟ่ชฌๆ˜Žใ—ใพใ—ใŸ) ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใŸๅ ดๅˆใ€ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏๅฟ…้ ˆใงใฏใชใใชใ‚Šใพใ™ใ€‚ +ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟไปฅๅค–ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ (ไปŠใฎใจใ“ใ‚ใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใฟ่ฆ‹ใฆใใพใ—ใŸ) ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใŸๅ ดๅˆใ€ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏๅฟ…้ ˆใงใฏใชใใชใ‚Šใพใ™ใ€‚ ็‰นๅฎšใฎๅ€คใ‚’ไธŽใˆใšใซใŸใ ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใซใ—ใŸใ„ๅ ดๅˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ `None` ใซใ—ใฆไธ‹ใ•ใ„ใ€‚ ใ—ใ‹ใ—ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฟ…้ ˆใซใ—ใŸใ„ๅ ดๅˆใฏใ€ใŸใ ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใชใ‘ใ‚Œใฐใ‚ˆใ„ใงใ™: -{* ../../docs_src/query_params/tutorial005.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} -ใ“ใ“ใงใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `needy` ใฏ `str` ๅž‹ใฎๅฟ…้ ˆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ +ใ“ใ“ใงใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `needy` ใฏ `str` ๅž‹ใฎๅฟ…้ ˆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ ไปฅไธ‹ใฎURLใ‚’ใƒ–ใƒฉใ‚ฆใ‚ถใง้–‹ใใจ: @@ -141,16 +142,17 @@ http://127.0.0.1:8000/items/foo-item ```JSON { - "detail": [ - { - "loc": [ - "query", - "needy" - ], - "msg": "field required", - "type": "value_error.missing" - } - ] + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] } ``` @@ -169,9 +171,9 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -ใใ—ใฆๅฝ“็„ถใ€ใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฟ…้ ˆใซใ€ๅˆฅใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ—ใ€ใพใŸๅˆฅใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใซใงใใพใ™: +ใใ—ใฆๅฝ“็„ถใ€ใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฟ…้ ˆใซใ€ใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ—ใ€ใพใŸใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎŒๅ…จใซใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซใซใงใใพใ™: -{* ../../docs_src/query_params/tutorial006.py hl[10] *} +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} ใ“ใฎๅ ดๅˆใ€3ใคใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ใ‚Šใพใ™ใ€‚: @@ -181,6 +183,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip | ่ฑ†็Ÿฅ่ญ˜ -[ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ](path-params.md#_8){.internal-link target=_blank}ใจๅŒๆง˜ใซ `Enum` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ +[ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ](path-params.md#predefined-values){.internal-link target=_blank}ใจๅŒๆง˜ใซ `Enum` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ /// diff --git a/docs/ja/docs/tutorial/request-forms-and-files.md b/docs/ja/docs/tutorial/request-forms-and-files.md index 110e3106a6..09e1277c8c 100644 --- a/docs/ja/docs/tutorial/request-forms-and-files.md +++ b/docs/ja/docs/tutorial/request-forms-and-files.md @@ -1,24 +1,28 @@ -# ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ•ใ‚ฉใƒผใƒ ใจใƒ•ใ‚กใ‚คใƒซ +# ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ•ใ‚ฉใƒผใƒ ใจใƒ•ใ‚กใ‚คใƒซ { #request-forms-and-files } `File`ใจ`Form`ใ‚’ๅŒๆ™‚ใซไฝฟใ†ใ“ใจใงใƒ•ใ‚กใ‚คใƒซใจใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ /// info | ๆƒ…ๅ ฑ -ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚ŒใŸใƒ•ใ‚กใ‚คใƒซใ‚„ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใ‚’ๅ—ไฟกใ™ใ‚‹ใซใฏใ€ใพใš`python-multipart`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ +ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚ŒใŸใƒ•ใ‚กใ‚คใƒซใ‚„ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใ‚’ๅ—ไฟกใ™ใ‚‹ใซใฏใ€ใพใš`python-multipart`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ -ไพ‹ใˆใฐใ€`pip install python-multipart`ใฎใ‚ˆใ†ใซใ€‚ +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install python-multipart +``` /// -## `File`ใจ`Form`ใฎใ‚คใƒณใƒใƒผใƒˆ +## `File`ใจ`Form`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001.py hl[1] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} -## `File`ใจ`Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ +## `File`ใจ`Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ { #define-file-and-form-parameters } ใƒ•ใ‚กใ‚คใƒซใ‚„ใƒ•ใ‚ฉใƒผใƒ ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`Body`ใ‚„`Query`ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซไฝœๆˆใ—ใพใ™: -{* ../../docs_src/request_forms_and_files/tutorial001.py hl[8] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} ใƒ•ใ‚กใ‚คใƒซใจใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใจใ—ใฆใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚Œใ€ใƒ•ใ‚กใ‚คใƒซใจใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ @@ -32,6 +36,6 @@ /// -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ๅŒใ˜ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒ‡ใƒผใ‚ฟใ‚„ใƒ•ใ‚กใ‚คใƒซใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€`File` ใจ`Form`ใ‚’ไธ€็ท’ใซไฝฟ็”จใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index eca2cd6dc7..1bdc28670b 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -1,4 +1,4 @@ -# ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟ +# ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟ { #form-data } JSONใฎไปฃใ‚ใ‚Šใซใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅ ดๅˆใฏใ€`Form`ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ @@ -6,27 +6,31 @@ JSONใฎไปฃใ‚ใ‚Šใซใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅ ดๅˆใฏใ€`Form`ใ‚’ไฝฟ็”จใ— ใƒ•ใ‚ฉใƒผใƒ ใ‚’ไฝฟใ†ใŸใ‚ใซใฏใ€ใพใš`python-multipart`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ -ใŸใจใˆใฐใ€`pip install python-multipart`ใฎใ‚ˆใ†ใซใ€‚ +ๅฟ…ใš[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install python-multipart +``` /// -## `Form`ใฎใ‚คใƒณใƒใƒผใƒˆ +## `Form`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-form } `fastapi`ใ‹ใ‚‰`Form`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/request_forms/tutorial001.py hl[1] *} +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} -## `Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ +## `Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ { #define-form-parameters } `Body`ใ‚„`Query`ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซใƒ•ใ‚ฉใƒผใƒ ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใพใ™: -{* ../../docs_src/request_forms/tutorial001.py hl[7] *} +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} ไพ‹ใˆใฐใ€OAuth2ไป•ๆง˜ใŒไฝฟ็”จใงใใ‚‹ๆ–นๆณ•ใฎ๏ผ‘ใค๏ผˆใ€Œใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒ•ใƒญใƒผใ€ใจๅ‘ผใฐใ‚Œใ‚‹๏ผ‰ใงใฏใ€ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ`username`ใจ`password`ใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ไป•ๆง˜ใงใฏใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅๅ‰ใŒ`username`ใจ`password`ใงใ‚ใ‚‹ใ“ใจใจใ€JSONใงใฏใชใใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใ“ใจใ‚’่ฆๆฑ‚ใ—ใฆใ„ใพใ™ใ€‚ +specใงใฏใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅๅ‰ใŒ`username`ใจ`password`ใงใ‚ใ‚‹ใ“ใจใจใ€JSONใงใฏใชใใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใ“ใจใ‚’่ฆๆฑ‚ใ—ใฆใ„ใพใ™ใ€‚ -`Form`ใงใฏ`Body`๏ผˆใŠใ‚ˆใณ`Query`ใ‚„`Path`ใ€`Cookie`๏ผ‰ใจๅŒใ˜ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +`Form`ใงใฏ`Body`๏ผˆใŠใ‚ˆใณ`Query`ใ‚„`Path`ใ€`Cookie`๏ผ‰ใจๅŒใ˜่จญๅฎšใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใ‚Œใซใฏใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ไพ‹ใ€ใ‚จใ‚คใƒชใ‚ขใ‚น๏ผˆไพ‹ใˆใฐ`username`ใฎไปฃใ‚ใ‚Šใซ`user-name`๏ผ‰ใชใฉใŒๅซใพใ‚Œใพใ™ใ€‚ /// info | ๆƒ…ๅ ฑ @@ -40,7 +44,7 @@ JSONใฎไปฃใ‚ใ‚Šใซใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅ ดๅˆใฏใ€`Form`ใ‚’ไฝฟ็”จใ— /// -## ใ€Œใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ€ใซใคใ„ใฆ +## ใ€Œใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ€ใซใคใ„ใฆ { #about-form-fields } HTMLใƒ•ใ‚ฉใƒผใƒ ๏ผˆ`
`๏ผ‰ใŒใ‚ตใƒผใƒใซใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ๆ–นๆณ•ใฏใ€้€šๅธธใ€ใใฎใƒ‡ใƒผใ‚ฟใซใ€Œ็‰นๅˆฅใชใ€ใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใŒใ€ใ“ใ‚ŒใฏJSONใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ @@ -64,6 +68,6 @@ HTMLใƒ•ใ‚ฉใƒผใƒ ๏ผˆ`
`๏ผ‰ใŒใ‚ตใƒผใƒใซใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ๆ–น /// -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใฎๅ…ฅๅŠ›ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€`Form`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ€‚ diff --git a/docs/ja/docs/tutorial/response-model.md b/docs/ja/docs/tutorial/response-model.md index b8464a4c73..258eac8e67 100644 --- a/docs/ja/docs/tutorial/response-model.md +++ b/docs/ja/docs/tutorial/response-model.md @@ -1,6 +1,35 @@ -# ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซ +# ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซ - ๆˆปใ‚Šๅ€คใฎๅž‹ { #response-model-return-type } -*path operations* ใฎใ„ใšใ‚ŒใซใŠใ„ใฆใ‚‚ใ€`response_model`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ€ใƒฌใ‚นใƒใƒณใ‚นใฎใƒขใƒ‡ใƒซใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +*path operation ้–ขๆ•ฐ*ใฎ**ๆˆปใ‚Šๅ€คใฎๅž‹**ใซใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไป˜ใ‘ใ‚‹ใ“ใจใงใ€ใƒฌใ‚นใƒใƒณใ‚นใซไฝฟ็”จใ•ใ‚Œใ‚‹ๅž‹ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +้–ขๆ•ฐ**ใƒ‘ใƒฉใƒกใƒผใ‚ฟ**ใฎๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใจๅŒใ˜ใ‚ˆใ†ใซ **ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ** ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚Pydanticใƒขใƒ‡ใƒซใ€ใƒชใ‚นใƒˆใ€่พžๆ›ธใ€ๆ•ดๆ•ฐใ‚„็œŸๅฝๅ€คใชใฉใฎใ‚นใ‚ซใƒฉใƒผๅ€คใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPIใฏใ“ใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’ไฝฟใฃใฆไปฅไธ‹ใ‚’่กŒใ„ใพใ™: + +* ่ฟ”ๅดใƒ‡ใƒผใ‚ฟใ‚’**ๆคœ่จผ**ใ—ใพใ™ใ€‚ + * ใƒ‡ใƒผใ‚ฟใŒไธๆญฃ๏ผˆไพ‹: ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒๆฌ ใ‘ใฆใ„ใ‚‹๏ผ‰ใงใ‚ใ‚Œใฐใ€ใใ‚Œใฏ*ใ‚ใชใŸ*ใฎใ‚ขใƒ—ใƒชใ‚ณใƒผใƒ‰ใŒๅฃŠใ‚Œใฆใ„ใฆใ€่ฟ”ใ™ในใใ‚‚ใฎใ‚’่ฟ”ใ—ใฆใ„ใชใ„ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใ€ไธๆญฃใชใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ™ไปฃใ‚ใ‚Šใซใ‚ตใƒผใƒใƒผใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ใชใŸใจใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏใ€ๆœŸๅพ…ใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใจใƒ‡ใƒผใ‚ฟๅฝข็Šถใ‚’ๅ—ใ‘ๅ–ใ‚Œใ‚‹ใ“ใจใ‚’็ขบๅฎŸใซใงใใพใ™ใ€‚ +* OpenAPIใฎ *path operation* ใซใ€ใƒฌใ‚นใƒใƒณใ‚น็”จใฎ **JSON Schema** ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใฏ**่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ**ใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + * ่‡ชๅ‹•ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰็”Ÿๆˆใƒ„ใƒผใƒซใงใ‚‚ไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ๆœ€ใ‚‚้‡่ฆใชใฎใฏ: + +* ๆˆปใ‚Šๅ€คใฎๅž‹ใงๅฎš็พฉใ•ใ‚ŒใŸๅ†…ๅฎนใซๅˆใ‚ใ›ใฆใ€ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’**ๅˆถ้™ใ—ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ**ใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใฏ**ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ**ใฎ่ฆณ็‚นใง็‰นใซ้‡่ฆใงใ™ใ€‚ไปฅไธ‹ใง่ฉณใ—ใ่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +## `response_model`ใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #response-model-parameter } + +ๅž‹ใŒๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ๅ†…ๅฎนใจใพใฃใŸใๅŒใ˜ใงใฏใชใ„ใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚‹ใ€ใพใŸใฏใใ†ใ—ใŸใ„ใ‚ฑใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€**่พžๆ›ธใ‚’่ฟ”ใ™**ใ€ใพใŸใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’่ฟ”ใ—ใŸใ„ใŒใ€**Pydanticใƒขใƒ‡ใƒซใจใ—ใฆๅฎฃ่จ€**ใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€Pydanticใƒขใƒ‡ใƒซใŒ่ฟ”ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆไพ‹: ่พžๆ›ธใ‚„ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใชใฉใ‚’ใ™ในใฆ่กŒใฃใฆใใ‚Œใพใ™ใ€‚ + +ๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€ใƒ„ใƒผใƒซใ‚„ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒ๏ผˆๆญฃใ—ใ๏ผ‰ใ‚จใƒฉใƒผใจใ—ใฆใ€้–ขๆ•ฐใŒๅฎฃ่จ€ใ—ใŸๅž‹๏ผˆไพ‹: Pydanticใƒขใƒ‡ใƒซ๏ผ‰ใจใฏ็•ฐใชใ‚‹ๅž‹๏ผˆไพ‹: dict๏ผ‰ใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ใจ่ญฆๅ‘Šใ—ใพใ™ใ€‚ + +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€ๆˆปใ‚Šๅ€คใฎๅž‹ใฎไปฃใ‚ใ‚Šใซใ€*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_model` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +`response_model`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€ใ„ใšใ‚Œใฎ *path operation* ใงใ‚‚ไฝฟ็”จใงใใพใ™: * `@app.get()` * `@app.post()` @@ -8,104 +37,211 @@ * `@app.delete()` * ใชใฉใ€‚ -{* ../../docs_src/response_model/tutorial001.py hl[17] *} +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} /// note | ๅ‚™่€ƒ -`response_model`ใฏใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใƒกใ‚ฝใƒƒใƒ‰๏ผˆ`get`ใ€`post`ใชใฉ๏ผ‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใฎใ‚ˆใ†ใซใ€*path operation้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +`response_model`ใฏใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใƒกใ‚ฝใƒƒใƒ‰๏ผˆ`get`ใ€`post`ใชใฉ๏ผ‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใฎใ‚ˆใ†ใซใ€*path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ /// -Pydanticใƒขใƒ‡ใƒซใฎๅฑžๆ€งใซๅฏพใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใฎใจๅŒใ˜ๅž‹ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใฎใงใ€Pydanticใƒขใƒ‡ใƒซใซใชใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใŒใ€ไพ‹ใˆใฐใ€`List[Item]`ใฎใ‚ˆใ†ใชPydanticใƒขใƒ‡ใƒซใฎ`list`ใซใชใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +`response_model`ใฏใ€Pydanticใƒขใƒ‡ใƒซใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใงๅฎฃ่จ€ใ™ใ‚‹ใฎใจๅŒใ˜ๅž‹ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ใใฎใŸใ‚ใ€Pydanticใƒขใƒ‡ใƒซใซใ‚‚ใงใใพใ™ใ—ใ€ไพ‹ใˆใฐ `List[Item]` ใฎใ‚ˆใ†ใซใ€Pydanticใƒขใƒ‡ใƒซใฎ `list` ใซใ‚‚ใงใใพใ™ใ€‚ -FastAPIใฏ`response_model`ใ‚’ไฝฟใฃใฆไปฅไธ‹ใฎใ“ใจใ‚’ใ—ใพใ™: +FastAPIใฏใ“ใฎ `response_model` ใ‚’ไฝฟใฃใฆใ€ใƒ‡ใƒผใ‚ฟใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ‚„ๆคœ่จผใชใฉใ‚’่กŒใ„ใ€ใ•ใ‚‰ใซๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’ๅž‹ๅฎฃ่จ€ใซๅˆใ‚ใ›ใฆ**ๅค‰ๆ›ใƒปใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ**ใ—ใพใ™ใ€‚ -* ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’ๅž‹ๅฎฃ่จ€ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -* ใƒ‡ใƒผใ‚ฟใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ -* OpenAPIใฎ *path operation* ใงใ€ใƒฌใ‚นใƒใƒณใ‚น็”จใฎJSON Schemaใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ -* ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +/// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ—ใ‹ใ—ใ€ๆœ€ใ‚‚้‡่ฆใชใฎใฏ: +ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„mypyใชใฉใงๅŽณๅฏ†ใชๅž‹ใƒใ‚งใƒƒใ‚ฏใ‚’ใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’ `Any` ใจใ—ใฆๅฎฃ่จ€ใงใใพใ™ใ€‚ -* ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใ‚’ใƒขใƒ‡ใƒซใฎใƒ‡ใƒผใ‚ฟใซ้™ๅฎšใ—ใพใ™ใ€‚ใ“ใ‚ŒใŒใฉใฎใ‚ˆใ†ใซ้‡่ฆใชใฎใ‹ไปฅไธ‹ใง่ฆ‹ใฆใ„ใใพใ—ใ‚‡ใ†ใ€‚ +ใใ†ใ™ใ‚‹ใจใ€ๆ„ๅ›ณ็š„ใซไฝ•ใงใ‚‚่ฟ”ใ—ใฆใ„ใ‚‹ใ“ใจใ‚’ใ‚จใƒ‡ใ‚ฃใ‚ฟใซไผใˆใ‚‰ใ‚Œใพใ™ใ€‚ใใ‚Œใงใ‚‚FastAPIใฏ `response_model` ใ‚’ไฝฟใฃใฆใ€ใƒ‡ใƒผใ‚ฟใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ€ๆคœ่จผใ€ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใชใฉใ‚’่กŒใ„ใพใ™ใ€‚ -/// note | ๆŠ€่ก“่ฉณ็ดฐ +/// -ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใฏใ€้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใงใฏใชใใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใชใœใชใ‚‰ใ€ใƒ‘ใ‚น้–ขๆ•ฐใฏๅฎŸ้š›ใซใฏใใฎใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใ‚’่ฟ”ใ™ใฎใงใฏใชใใ€`dict`ใ‚„ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€ใ‚ใ‚‹ใ„ใฏไป–ใฎใƒขใƒ‡ใƒซใ‚’่ฟ”ใ—ใ€`response_model`ใ‚’ไฝฟ็”จใ—ใฆใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅˆถ้™ใ‚„ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ‚’่กŒใ†ใ‹ใ‚‰ใงใ™ใ€‚ +### `response_model`ใฎๅ„ชๅ…ˆ้ †ไฝ { #response-model-priority } -/// +ๆˆปใ‚Šๅ€คใฎๅž‹ใจ `response_model` ใฎไธกๆ–นใ‚’ๅฎฃ่จ€ใ—ใŸๅ ดๅˆใ€`response_model` ใŒๅ„ชๅ…ˆใ•ใ‚Œใ€FastAPIใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใจใฏ็•ฐใชใ‚‹ๅž‹ใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ๅ ดๅˆใงใ‚‚ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„mypyใชใฉใฎใƒ„ใƒผใƒซใงไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซ้–ขๆ•ฐใธๆญฃใ—ใ„ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ใใ‚Œใงใ‚‚FastAPIใฏ `response_model` ใ‚’ไฝฟ็”จใ—ใฆใƒ‡ใƒผใ‚ฟใฎๆคœ่จผใ‚„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใชใฉใ‚’ๅฎŸ่กŒใงใใพใ™ใ€‚ + +ใพใŸ `response_model=None` ใ‚’ไฝฟ็”จใ—ใฆใ€ใใฎ*path operation*ใฎใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซ็”Ÿๆˆใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ใ“ใ‚Œใฏใ€Pydanticใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ใ‚‚ใฎใซๅฏพใ—ใฆๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅ ดๅˆใซๅฟ…่ฆใซใชใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ไปฅไธ‹ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎใ„ใšใ‚Œใ‹ใงไพ‹ใ‚’็คบใ—ใพใ™ใ€‚ + +## ๅŒใ˜ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎ่ฟ”ๅด { #return-the-same-input-data } -## ๅŒใ˜ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎ่ฟ”ๅด +ใ“ใ“ใงใฏ `UserIn` ใƒขใƒ‡ใƒซใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใซใฏๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๅซใพใ‚Œใพใ™: -ใ“ใ“ใงใฏ`UserIn`ใƒขใƒ‡ใƒซใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ใใ‚Œใซใฏๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๅซใพใ‚Œใฆใ„ใพใ™: +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -{* ../../docs_src/response_model/tutorial002.py hl[9,11] *} +/// info | ๆƒ…ๅ ฑ + +`EmailStr` ใ‚’ไฝฟ็”จใ™ใ‚‹ใซใฏใ€ๆœ€ๅˆใซ `email-validator` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚ + +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install email-validator +``` + +ใพใŸใฏๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: + +```console +$ pip install "pydantic[email]" +``` + +/// ใใ—ใฆใ€ใ“ใฎใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใฆๅ…ฅๅŠ›ใ‚’ๅฎฃ่จ€ใ—ใ€ๅŒใ˜ใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใฆๅ‡บๅŠ›ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใพใ™: -{* ../../docs_src/response_model/tutorial002.py hl[17,18] *} +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} ใ“ใ‚Œใงใ€ใƒ–ใƒฉใ‚ฆใ‚ถใŒใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฝฟใฃใฆใƒฆใƒผใ‚ถใƒผใ‚’ไฝœๆˆใ™ใ‚‹้š›ใซใ€APIใŒใƒฌใ‚นใƒใƒณใ‚นใงๅŒใ˜ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’่ฟ”ใ™ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ -ใ“ใฎๅ ดๅˆใ€ใƒฆใƒผใ‚ถใƒผ่‡ช่บซใŒใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’้€ไฟกใ—ใฆใ„ใ‚‹ใฎใงๅ•้กŒใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใ“ใฎๅ ดๅˆใ€ๅŒใ˜ใƒฆใƒผใ‚ถใƒผใŒใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’้€ไฟกใ—ใฆใ„ใ‚‹ใฎใงๅ•้กŒใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ -ใ—ใ‹ใ—ใ€ๅŒใ˜ใƒขใƒ‡ใƒซใ‚’ๅˆฅใฎ*path operation*ใซไฝฟ็”จใ™ใ‚‹ใจใ€ใ™ในใฆใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใƒฆใƒผใ‚ถใƒผใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’้€ไฟกใ—ใฆใ—ใพใ†ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ๅŒใ˜ใƒขใƒ‡ใƒซใ‚’ๅˆฅใฎ*path operation*ใซไฝฟ็”จใ™ใ‚‹ใจใ€ใ™ในใฆใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซใƒฆใƒผใ‚ถใƒผใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’้€ไฟกใ—ใฆใ—ใพใ†ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -/// danger | ๅฑ้™บ +/// danger | ่ญฆๅ‘Š -ใƒฆใƒผใ‚ถใƒผใฎๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฟๅญ˜ใ—ใŸใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใง้€ไฟกใ—ใŸใ‚Šใ™ใ‚‹ใ“ใจใฏ็ตถๅฏพใซใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ +ใ™ในใฆใฎๆณจๆ„็‚นใ‚’็†่งฃใ—ใฆใ„ใฆใ€่‡ชๅˆ†ใŒไฝ•ใ‚’ใ—ใฆใ„ใ‚‹ใ‹ๅˆ†ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใ‚’้™คใใ€ใƒฆใƒผใ‚ถใƒผใฎๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฟๅญ˜ใ—ใŸใ‚Šใ€ใ“ใฎใ‚ˆใ†ใซใƒฌใ‚นใƒใƒณใ‚นใง้€ไฟกใ—ใŸใ‚Šใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ /// -## ๅ‡บๅŠ›ใƒขใƒ‡ใƒซใฎ่ฟฝๅŠ  +## ๅ‡บๅŠ›ใƒขใƒ‡ใƒซใฎ่ฟฝๅŠ  { #add-an-output-model } + +ไปฃใ‚ใ‚Šใซใ€ๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŒใคๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใจใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŒใŸใชใ„ๅ‡บๅŠ›ใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใงใใพใ™: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +ใ“ใ“ใงใฏใ€*path operation ้–ขๆ•ฐ*ใŒใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅซใ‚€ๅŒใ˜ๅ…ฅๅŠ›ใƒฆใƒผใ‚ถใƒผใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใš: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...`response_model`ใ‚’ใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅซใพใชใ„ `UserOut` ใƒขใƒ‡ใƒซใจใ—ใฆๅฎฃ่จ€ใ—ใพใ—ใŸ: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +ใใฎใŸใ‚ใ€**FastAPI** ใฏๅ‡บๅŠ›ใƒขใƒ‡ใƒซใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใชใ„ใ™ในใฆใฎใƒ‡ใƒผใ‚ฟใ‚’ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ—ใฆใใ‚Œใพใ™๏ผˆPydanticใ‚’ไฝฟ็”จ๏ผ‰ใ€‚ + +### `response_model`ใพใŸใฏๆˆปใ‚Šๅ€คใฎๅž‹ { #response-model-or-return-type } + +ใ“ใฎใ‚ฑใƒผใ‚นใงใฏ2ใคใฎใƒขใƒ‡ใƒซใŒ็•ฐใชใ‚‹ใŸใ‚ใ€้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’ `UserOut` ใจใ—ใฆใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ™ใ‚‹ใจใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ใƒ„ใƒผใƒซใฏใ€็•ฐใชใ‚‹ใ‚ฏใƒฉใ‚นใชใฎใงไธๆญฃใชๅž‹ใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ใจ่ญฆๅ‘Šใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใ“ใฎไพ‹ใงใฏ `response_model` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ไปฃใ‚ใ‚Šใซใ€ๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŒใคๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใจใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŒใŸใชใ„ๅ‡บๅŠ›ใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +...ใ—ใ‹ใ—ใ€ใ“ใ‚Œใ‚’่งฃๆฑบใ™ใ‚‹ๆ–นๆณ•ใ‚’ไปฅไธ‹ใง็ขบ่ชใ—ใพใ—ใ‚‡ใ†ใ€‚ -{* ../../docs_src/response_model/tutorial003.py hl[9,11,16] *} +## ๆˆปใ‚Šๅ€คใฎๅž‹ใจใƒ‡ใƒผใ‚ฟใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ { #return-type-and-data-filtering } -ใ“ใ“ใงใฏใ€*path operation้–ขๆ•ฐ*ใŒใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅซใ‚€ๅŒใ˜ๅ…ฅๅŠ›ใƒฆใƒผใ‚ถใƒผใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใš: +ๅ‰ใฎไพ‹ใ‹ใ‚‰็ถšใ‘ใพใ™ใ€‚**้–ขๆ•ฐใซ1ใคใฎๅž‹ใ‚’ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ**ใ—ใŸใ„ไธ€ๆ–นใงใ€้–ขๆ•ฐใ‹ใ‚‰ใฏๅฎŸ้š›ใซใฏ**ใ‚ˆใ‚Šๅคšใใฎใƒ‡ใƒผใ‚ฟ**ใ‚’ๅซใ‚€ใ‚‚ใฎใ‚’่ฟ”ใ›ใ‚‹ใ‚ˆใ†ใซใ—ใŸใ„ใจใ—ใพใ™ใ€‚ -{* ../../docs_src/response_model/tutorial003.py hl[24] *} +FastAPIใซใฏใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใ—ใฆใƒ‡ใƒผใ‚ฟใ‚’**ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ**ใ—็ถšใ‘ใฆใปใ—ใ„ใงใ™ใ€‚ใคใพใ‚Šใ€้–ขๆ•ฐใŒใ‚ˆใ‚Šๅคšใใฎใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ—ใฆใ‚‚ใ€ใƒฌใ‚นใƒใƒณใ‚นใซใฏใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใงๅฎฃ่จ€ใ•ใ‚ŒใŸใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎใฟใŒๅซใพใ‚Œใพใ™ใ€‚ -...`response_model`ใ‚’`UserOut`ใจๅฎฃ่จ€ใ—ใŸใ“ใจใงใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๅซใพใ‚Œใฆใ„ใพใ›ใ‚“: +ๅ‰ใฎไพ‹ใงใฏใ‚ฏใƒฉใ‚นใŒ็•ฐใชใ‚‹ใŸใ‚ `response_model` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ—ใŸใ€‚ใ—ใ‹ใ—ใใ‚Œใฏใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ใƒ„ใƒผใƒซใซใ‚ˆใ‚‹้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใƒใ‚งใƒƒใ‚ฏใฎใ‚ตใƒใƒผใƒˆใ‚’ๅ—ใ‘ใ‚‰ใ‚Œใชใ„ใ“ใจใ‚‚ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -{* ../../docs_src/response_model/tutorial003.py hl[22] *} +ใ—ใ‹ใ—ใ€ใ“ใฎใ‚ˆใ†ใชใ“ใจใŒๅฟ…่ฆใซใชใ‚‹ๅคšใใฎใ‚ฑใƒผใ‚นใงใฏใ€ใ“ใฎไพ‹ใฎใ‚ˆใ†ใซใƒขใƒ‡ใƒซใงใƒ‡ใƒผใ‚ฟใฎไธ€้ƒจใ‚’**ใƒ•ใ‚ฃใƒซใ‚ฟ/ๅ‰Š้™ค**ใ—ใŸใ„ใ ใ‘ใงใ™ใ€‚ -ใใฎใŸใ‚ใ€**FastAPI** ใฏๅ‡บๅŠ›ใƒขใƒ‡ใƒซใงๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใชใ„ๅ…จใฆใฎใƒ‡ใƒผใ‚ฟใ‚’ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ—ใฆใใ‚Œใพใ™๏ผˆPydanticใ‚’ไฝฟ็”จ๏ผ‰ใ€‚ +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€ใ‚ฏใƒฉใ‚นใจ็ถ™ๆ‰ฟใ‚’ๅˆฉ็”จใ—ใฆ้–ขๆ•ฐใฎ**ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ**ใ‚’ๆดป็”จใ—ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ใƒ„ใƒผใƒซใฎใ‚ตใƒใƒผใƒˆใ‚’ๆ”นๅ–„ใ—ใคใคใ€FastAPIใฎ**ใƒ‡ใƒผใ‚ฟใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ**ใ‚‚ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฆ‹ใ‚‹ +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} -่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฆ‹ใ‚‹ใจใ€ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใจๅ‡บๅŠ›ใƒขใƒ‡ใƒซใŒใใ‚Œใžใ‚Œ็‹ฌ่‡ชใฎJSON Schemaใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใŒ็ขบ่ชใงใใพใ™ใ€‚ +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ“ใฎใ‚ณใƒผใƒ‰ใฏๅž‹ใจใ—ใฆๆญฃใ—ใ„ใŸใ‚ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„mypyใ‹ใ‚‰ใฎใƒ„ใƒผใƒซๆ”ฏๆดใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ—ใ€FastAPIใซใ‚ˆใ‚‹ใƒ‡ใƒผใ‚ฟใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใ‚‚ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ - +ใ“ใ‚Œใฏใฉใฎใ‚ˆใ†ใซๅ‹•ไฝœใ™ใ‚‹ใฎใงใ—ใ‚‡ใ†ใ‹๏ผŸ็ขบ่ชใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚๐Ÿค“ -ใใ—ใฆใ€ไธกๆ–นใฎใƒขใƒ‡ใƒซใฏใ€ๅฏพ่ฉฑๅž‹ใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซไฝฟ็”จใ•ใ‚Œใพใ™: +### ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจใƒ„ใƒผใƒซๆ”ฏๆด { #type-annotations-and-tooling } - +ใพใšใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ€mypyใ€ใใฎไป–ใฎใƒ„ใƒผใƒซใŒใ“ใ‚Œใ‚’ใฉใ†่ฆ‹ใ‚‹ใ‹ใ‚’่ฆ‹ใฆใฟใพใ™ใ€‚ -## ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ +`BaseUser` ใซใฏๅŸบๆœฌใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ๆฌกใซ `UserIn` ใŒ `BaseUser` ใ‚’็ถ™ๆ‰ฟใ—ใฆ `password` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใŸใ‚ใ€ไธกๆ–นใฎใƒขใƒ‡ใƒซใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใ™ในใฆๅซใพใ‚Œใพใ™ใ€‚ -ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใซใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’ `BaseUser` ใจใ—ใฆใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ—ใพใ™ใŒใ€ๅฎŸ้š›ใซใฏ `UserIn` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ -{* ../../docs_src/response_model/tutorial004.py hl[11,13,14] *} +ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„mypyใชใฉใฎใƒ„ใƒผใƒซใฏใ“ใ‚Œใซๆ–‡ๅฅใ‚’่จ€ใ„ใพใ›ใ‚“ใ€‚typingใฎ่ฆณ็‚นใงใฏใ€`UserIn` ใฏ `BaseUser` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ‚ใ‚Šใ€ๆœŸๅพ…ใ•ใ‚Œใ‚‹ใ‚‚ใฎใŒ `BaseUser` ใงใ‚ใ‚Œใฐ `UserIn` ใฏ*ๆœ‰ๅŠน*ใชๅž‹ใ ใ‹ใ‚‰ใงใ™ใ€‚ -* `description: str = None`ใฏ`None`ใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ™ใ€‚ -* `tax: float = 10.5`ใฏ`10.5`ใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ™ใ€‚ -* `tags: List[str] = []` ใฏ็ฉบใฎใƒชใ‚นใƒˆ๏ผˆ`[]`๏ผ‰ใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ™ใ€‚ +### FastAPIใฎใƒ‡ใƒผใ‚ฟใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ { #fastapi-data-filtering } -ใ—ใ‹ใ—ใ€ๅฎŸ้š›ใซไฟๅญ˜ใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใซใฏ็ตๆžœใ‹ใ‚‰ใใ‚Œใ‚‰ใ‚’็œ็•ฅใ—ใŸๆ–นใŒ่‰ฏใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ไธ€ๆ–นFastAPIใงใฏใ€ๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’่ฆ‹ใฆใ€่ฟ”ใ™ๅ†…ๅฎนใซใใฎๅž‹ใงๅฎฃ่จ€ใ•ใ‚ŒใŸใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใ ใ‘**ใŒๅซใพใ‚Œใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + +FastAPIใฏใ€่ฟ”ๅดใƒ‡ใƒผใ‚ฟใฎใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใซใ‚ฏใƒฉใ‚น็ถ™ๆ‰ฟใฎๅŒใ˜ใƒซใƒผใƒซใŒไฝฟใ‚ใ‚Œใฆใ—ใพใ‚ใชใ„ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใ€ๅ†…้ƒจใงPydanticใ‚’ไฝฟใฃใฆใ„ใใคใ‹ใฎๅ‡ฆ็†ใ‚’่กŒใฃใฆใ„ใพใ™ใ€‚ใใ†ใงใชใ„ใจใ€ๆœŸๅพ…ไปฅไธŠใซๅคšใใฎใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ—ใฆใ—ใพใ†ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใฎๆ–นๆณ•ใงใ€**ใƒ„ใƒผใƒซๆ”ฏๆด**ไป˜ใใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจ**ใƒ‡ใƒผใ‚ฟใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ**ใฎไธกๆ–นใจใ„ใ†ใ€ใ„ใ„ใจใ“ๅ–ใ‚ŠใŒใงใใพใ™ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฆ‹ใ‚‹ { #see-it-in-the-docs } + +่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฆ‹ใ‚‹ใจใ€ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใจๅ‡บๅŠ›ใƒขใƒ‡ใƒซใŒใใ‚Œใžใ‚Œ็‹ฌ่‡ชใฎJSON Schemaใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใŒ็ขบ่ชใงใใพใ™: + + + +ใใ—ใฆใ€ไธกๆ–นใฎใƒขใƒ‡ใƒซใฏๅฏพ่ฉฑๅž‹ใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซไฝฟ็”จใ•ใ‚Œใพใ™: + + + +## ใใฎไป–ใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ { #other-return-type-annotations } + +Pydanticใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ใ‚‚ใฎใ‚’่ฟ”ใ—ใ€ใƒ„ใƒผใƒซ๏ผˆใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„mypyใชใฉ๏ผ‰ใŒๆไพ›ใ™ใ‚‹ใ‚ตใƒใƒผใƒˆใ‚’ๅพ—ใ‚‹ใŸใ‚ใ ใ‘ใซใ€้–ขๆ•ฐใงใใ‚Œใ‚’ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ™ใ‚‹ใ‚ฑใƒผใ‚นใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +### ใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ { #return-a-response-directly } + +ๆœ€ใ‚‚ไธ€่ˆฌ็š„ใชใ‚ฑใƒผใ‚นใฏใ€[้ซ˜ๅบฆใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงๅพŒ่ฟฐใ™ใ‚‹ใ€ŒResponseใ‚’็›ดๆŽฅ่ฟ”ใ™ใ€](../advanced/response-directly.md){.internal-link target=_blank}ๅ ดๅˆใงใ™ใ€‚ + +{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} + +ใ“ใฎใ‚ทใƒณใƒ—ใƒซใชใ‚ฑใƒผใ‚นใฏใ€ๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒ `Response` ใฎใ‚ฏใƒฉใ‚น๏ผˆใพใŸใฏใ‚ตใƒ–ใ‚ฏใƒฉใ‚น๏ผ‰ใงใ‚ใ‚‹ใŸใ‚ใ€FastAPIใŒ่‡ชๅ‹•็š„ใซๅ‡ฆ็†ใ—ใพใ™ใ€‚ + +ใพใŸ `RedirectResponse` ใจ `JSONResponse` ใฎไธกๆ–นใฏ `Response` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใชใฎใงใ€ใƒ„ใƒผใƒซใ‚‚ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒๆญฃใ—ใ„ใจใ—ใฆๅ•้กŒใซใ—ใพใ›ใ‚“ใ€‚ + +### `Response`ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ™ใ‚‹ { #annotate-a-response-subclass } + +ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใง `Response` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: + +{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} + +ใ“ใ‚Œใฏ `RedirectResponse` ใŒ `Response` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ‚ใ‚Šใ€FastAPIใŒใ“ใฎใ‚ทใƒณใƒ—ใƒซใชใ‚ฑใƒผใ‚นใ‚’่‡ชๅ‹•ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใ€ๅŒๆง˜ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ + +### ็„กๅŠนใชๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ { #invalid-return-type-annotations } + +ใ—ใ‹ใ—ใ€Pydanticๅž‹ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ๅˆฅใฎไปปๆ„ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆไพ‹: ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใ‚’่ฟ”ใ—ใ€้–ขๆ•ฐใงใใฎใ‚ˆใ†ใซใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ™ใ‚‹ใจใ€FastAPIใฏใใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‹ใ‚‰Pydanticใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ—ใ‚ˆใ†ใจใ—ใฆๅคฑๆ•—ใ—ใพใ™ใ€‚ + +ๅŒๆง˜ใซใ€unionใฎใ‚ˆใ†ใซใ€่ค‡ๆ•ฐใฎๅž‹ใฎใ†ใก1ใคไปฅไธŠใŒPydanticๅž‹ใจใ—ใฆๆœ‰ๅŠนใงใชใ„ใ‚‚ใฎใ‚’ๅซใ‚€ๅ ดๅˆใ‚‚่ตทใ“ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐๆฌกใฏๅคฑๆ•—ใ—ใพใ™ ๐Ÿ’ฅ: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...ใ“ใ‚Œใฏใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒPydanticๅž‹ใงใฏใชใใ€ๅ˜ไธ€ใฎ `Response` ใ‚ฏใƒฉใ‚น๏ผˆใพใŸใฏใ‚ตใƒ–ใ‚ฏใƒฉใ‚น๏ผ‰ใงใ‚‚ใชใ„ใŸใ‚ใซๅคฑๆ•—ใ—ใพใ™ใ€‚`Response` ใจ `dict` ใฎ้–“ใฎunion๏ผˆใฉใกใ‚‰ใ‹๏ผ‰ใซใชใฃใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ + +### ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ { #disable-response-model } + +ไธŠใฎไพ‹ใ‚’็ถšใ‘ใ‚‹ใจใ€FastAPIใŒๅฎŸ่กŒใ™ใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ‡ใƒผใ‚ฟๆคœ่จผใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ€ใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐใชใฉใ‚’่กŒใ„ใŸใใชใ„ใ“ใจใ‚‚ใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +ใ—ใ‹ใ—ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ๅž‹ใƒใ‚งใƒƒใ‚ซใƒผ๏ผˆไพ‹: mypy๏ผ‰ใชใฉใฎใƒ„ใƒผใƒซๆ”ฏๆดใ‚’ๅพ—ใ‚‹ใŸใ‚ใซใ€้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใฏๆฎ‹ใ—ใŸใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใใฎๅ ดๅˆใ€`response_model=None` ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใงใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใฎ็”Ÿๆˆใ‚’็„กๅŠนใซใงใใพใ™: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +ใ“ใ‚Œใซใ‚ˆใ‚ŠFastAPIใฏใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซ็”Ÿๆˆใ‚’ใ‚นใ‚ญใƒƒใƒ—ใ—ใ€FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฝฑ้Ÿฟใ•ใ›ใšใซๅฟ…่ฆใชๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไป˜ใ‘ใ‚‰ใ‚Œใพใ™ใ€‚๐Ÿค“ + +## ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #response-model-encoding-parameters } + +ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใซใฏๆฌกใฎใ‚ˆใ†ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’่จญๅฎšใงใใพใ™: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None`๏ผˆใพใŸใฏPython 3.10ใงใฏ `str | None = None`๏ผ‰ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใŒ `None` ใงใ™ใ€‚ +* `tax: float = 10.5` ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใŒ `10.5` ใงใ™ใ€‚ +* `tags: List[str] = []` ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใŒ็ฉบใฎใƒชใ‚นใƒˆ `[]` ใงใ™ใ€‚ + +ใŸใ ใ—ใ€ใใ‚Œใ‚‰ใŒๅฎŸ้š›ใซใฏไฟๅญ˜ใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใ€็ตๆžœใ‹ใ‚‰็œ็•ฅใ—ใŸใ„ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ ไพ‹ใˆใฐใ€NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซๅคšใใฎใ‚ชใƒ—ใ‚ทใƒงใƒณๅฑžๆ€งใ‚’ๆŒใคใƒขใƒ‡ใƒซใŒใ‚ใ‚‹ใŒใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใงใ„ใฃใฑใ„ใฎ้žๅธธใซ้•ทใ„JSONใƒฌใ‚นใƒใƒณใ‚นใ‚’้€ไฟกใ—ใŸใใชใ„ๅ ดๅˆใงใ™ใ€‚ -### `response_model_exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ +### `response_model_exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ { #use-the-response-model-exclude-unset-parameter } -*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ`response_model_exclude_unset=True`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_model_exclude_unset=True` ใ‚’่จญๅฎšใงใใพใ™: -{* ../../docs_src/response_model/tutorial004.py hl[24] *} +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} -ใใ—ใฆใ€ใ“ใ‚Œใ‚‰ใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏใƒฌใ‚นใƒใƒณใ‚นใซๅซใพใ‚Œใšใ€ๅฎŸ้š›ใซ่จญๅฎšใ•ใ‚ŒใŸๅ€คใฎใฟใŒๅซใพใ‚Œใพใ™ใ€‚ +ใใ†ใ™ใ‚‹ใจใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฏใƒฌใ‚นใƒใƒณใ‚นใซๅซใพใ‚Œใšใ€ๅฎŸ้š›ใซ่จญๅฎšใ•ใ‚ŒใŸๅ€คใฎใฟใŒๅซใพใ‚Œใพใ™ใ€‚ -ใใฎใŸใ‚ใ€*path operation*ใซID`foo`ใŒ่จญๅฎšใ•ใ‚ŒใŸitemใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใจใ€ใƒฌใ‚นใƒใƒณใ‚นใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅซใพใชใ„๏ผ‰: +ใใฎใŸใ‚ใ€ID `foo` ใฎitemใซๅฏพใ—ใฆใใฎ *path operation* ใธใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใจใ€ใƒฌใ‚นใƒใƒณใ‚นใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅซใพใชใ„๏ผ‰: ```JSON { @@ -116,26 +252,20 @@ FastAPIใฏ`response_model`ใ‚’ไฝฟใฃใฆไปฅไธ‹ใฎใ“ใจใ‚’ใ—ใพใ™: /// info | ๆƒ…ๅ ฑ -FastAPIใฏใ“ใ‚Œใ‚’ใ™ใ‚‹ใŸใ‚ใซใ€Pydanticใƒขใƒ‡ใƒซใฎ`.dict()`ใ‚’ใใฎ`exclude_unset`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ - -/// - -/// info | ๆƒ…ๅ ฑ - -ไปฅไธ‹ใ‚‚ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ไปฅไธ‹ใ‚‚ไฝฟ็”จใงใใพใ™: * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -`exclude_defaults`ใจ`exclude_none`ใซใคใ„ใฆใฏใ€Pydanticใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹้€šใ‚Šใงใ™ใ€‚ +`exclude_defaults` ใจ `exclude_none` ใซใคใ„ใฆใฏใ€Pydanticใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹้€šใ‚Šใงใ™ใ€‚ /// -#### ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅ€คใ‚’ๆŒใคใƒ‡ใƒผใ‚ฟ +#### ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซๅ€คใŒใ‚ใ‚‹ใƒ‡ใƒผใ‚ฟ { #data-with-values-for-fields-with-defaults } -ใ—ใ‹ใ—ใ€ID`bar`ใฎitemใฎใ‚ˆใ†ใซใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ใƒขใƒ‡ใƒซใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซๅ€คใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆ: +ใ—ใ‹ใ—ใ€ID `bar` ใฎitemใฎใ‚ˆใ†ใซใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ใƒขใƒ‡ใƒซใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซๅ€คใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆ: -```Python hl_lines="3 5" +```Python hl_lines="3 5" { "name": "Bar", "description": "The bartenders", @@ -146,11 +276,11 @@ FastAPIใฏใ“ใ‚Œใ‚’ใ™ใ‚‹ใŸใ‚ใซใ€Pydanticใƒขใƒ‡ใƒซใฎ`.dict()`ใ‚’ + /// note | ๅ‚™่€ƒ @@ -39,7 +39,7 @@ FastAPIใฏใ“ใ‚Œใ‚’็Ÿฅใฃใฆใ„ใฆใ€ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃใŒใชใ„ใจใ„ใ†O /// -## HTTPใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใซใคใ„ใฆ +## HTTPใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใซใคใ„ใฆ { #about-http-status-codes } /// note | ๅ‚™่€ƒ @@ -47,34 +47,34 @@ FastAPIใฏใ“ใ‚Œใ‚’็Ÿฅใฃใฆใ„ใฆใ€ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃใŒใชใ„ใจใ„ใ†O /// -HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ๏ผ“ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’้€ไฟกใ—ใพใ™ใ€‚ +HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ3ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’้€ไฟกใ—ใพใ™ใ€‚ ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใฏใ€ใใ‚Œใ‚‰ใ‚’่ช่ญ˜ใ™ใ‚‹ใŸใ‚ใซ้–ข้€ฃไป˜ใ‘ใ‚‰ใ‚ŒใŸๅๅ‰ใ‚’ๆŒใฃใฆใ„ใพใ™ใŒใ€้‡่ฆใช้ƒจๅˆ†ใฏ็•ชๅทใงใ™ใ€‚ ใคใพใ‚Š: -* `100`ไปฅไธŠใฏใ€Œๆƒ…ๅ ฑใ€ใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ€‚็›ดๆŽฅไฝฟใ†ใ“ใจใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ๆŒใคใƒฌใ‚นใƒใƒณใ‚นใฏใƒœใƒ‡ใ‚ฃใ‚’ๆŒใคใ“ใจใŒใงใใพใ›ใ‚“ใ€‚ -* **`200`** ไปฅไธŠใฏใ€ŒๆˆๅŠŸใ€ใฎใƒฌใ‚นใƒใƒณใ‚นใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฏๆœ€ใ‚‚ๅˆฉ็”จใ™ใ‚‹ใงใ‚ใ‚ใ†ใ‚‚ใฎใงใ™ใ€‚ +* `100 - 199` ใฏใ€Œๆƒ…ๅ ฑใ€ใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚็›ดๆŽฅไฝฟใ†ใ“ใจใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ๆŒใคใƒฌใ‚นใƒใƒณใ‚นใฏใƒœใƒ‡ใ‚ฃใ‚’ๆŒใคใ“ใจใŒใงใใพใ›ใ‚“ใ€‚ +* **`200 - 299`** ใฏใ€ŒๆˆๅŠŸใ€ใฎใƒฌใ‚นใƒใƒณใ‚นใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฏๆœ€ใ‚‚ๅˆฉ็”จใ™ใ‚‹ใงใ‚ใ‚ใ†ใ‚‚ใฎใงใ™ใ€‚ * `200`ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใงใ€ใ™ในใฆใŒใ€ŒOKใ€ใงใ‚ใฃใŸใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ * ๅˆฅใฎไพ‹ใจใ—ใฆใฏใ€`201`๏ผˆCreated๏ผ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซๆ–ฐใ—ใ„ใƒฌใ‚ณใƒผใƒ‰ใ‚’ไฝœๆˆใ—ใŸๅพŒใซใ‚ˆใไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ - * ็‰นๆฎŠใชใ‚ฑใƒผใ‚นใจใ—ใฆใ€`204`๏ผˆNo Content๏ผ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎใƒฌใ‚นใƒใƒณใ‚นใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ™ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒใชใ„ๅ ดๅˆใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ใใ—ใฆใ“ใฎใƒฌใ‚นใƒใƒณใ‚นใฏใƒœใƒ‡ใ‚ฃใ‚’ๆŒใคใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ -* **`300`** ไปฅไธŠใฏใ€Œใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ€ใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ๆŒใคใƒฌใ‚นใƒใƒณใ‚นใฏ`304`๏ผˆNot Modified๏ผ‰ใ‚’้™คใใ€ใƒœใƒ‡ใ‚ฃใ‚’ๆŒใคใ“ใจใ‚‚ๆŒใŸใชใ„ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -* **`400`** ไปฅไธŠใฏใ€Œใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚จใƒฉใƒผใ€ใฎใƒฌใ‚นใƒใƒณใ‚นใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฏใ€ใŠใใ‚‰ใๆœ€ใ‚‚ๅคš็”จใ™ใ‚‹ใงใ‚ใ‚ใ†๏ผ’็•ช็›ฎใฎใ‚ฟใ‚คใƒ—ใงใ™ใ€‚ + * ็‰นๆฎŠใชใ‚ฑใƒผใ‚นใจใ—ใฆใ€`204`๏ผˆNo Content๏ผ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎใƒฌใ‚นใƒใƒณใ‚นใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ™ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒใชใ„ๅ ดๅˆใซไฝฟ็”จใ•ใ‚Œใ‚‹ใŸใ‚ใ€ใƒฌใ‚นใƒใƒณใ‚นใฏใƒœใƒ‡ใ‚ฃใ‚’ๆŒใฃใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ +* **`300 - 399`** ใฏใ€Œใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ€ใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ๆŒใคใƒฌใ‚นใƒใƒณใ‚นใฏ`304`๏ผˆNot Modified๏ผ‰ใ‚’้™คใใ€ใƒœใƒ‡ใ‚ฃใ‚’ๆŒใคใ“ใจใ‚‚ๆŒใŸใชใ„ใ“ใจใ‚‚ใงใใพใ™ใ€‚`304`ใฏใƒœใƒ‡ใ‚ฃใ‚’ๆŒใฃใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ +* **`400 - 499`** ใฏใ€Œใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚จใƒฉใƒผใ€ใฎใƒฌใ‚นใƒใƒณใ‚นใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใฏใ€ใŠใใ‚‰ใๆœ€ใ‚‚ๅคš็”จใ™ใ‚‹ใงใ‚ใ‚ใ†2็•ช็›ฎใฎใ‚ฟใ‚คใƒ—ใงใ™ใ€‚ * ไพ‹ใˆใฐใ€`404`ใฏใ€ŒNot Foundใ€ใƒฌใ‚นใƒใƒณใ‚นใงใ™ใ€‚ * ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰ใฎไธ€่ˆฌ็š„ใชใ‚จใƒฉใƒผใซใคใ„ใฆใฏใ€`400`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -* `500`ไปฅไธŠใฏใ‚ตใƒผใƒใƒผใ‚จใƒฉใƒผใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใ‚’็›ดๆŽฅไฝฟใ†ใ“ใจใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ณใƒผใƒ‰ใ‚„ใ‚ตใƒผใƒใƒผใฎใฉใ“ใ‹ใงไฝ•ใ‹ๅ•้กŒใŒ็™บ็”Ÿใ—ใŸๅ ดๅˆใ€ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใฎใ„ใšใ‚Œใ‹ใŒ่‡ชๅ‹•็š„ใซ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ +* `500 - 599` ใฏใ‚ตใƒผใƒใƒผใ‚จใƒฉใƒผใฎใŸใ‚ใฎใ‚‚ใฎใงใ™ใ€‚ใ“ใ‚Œใ‚‰ใ‚’็›ดๆŽฅไฝฟใ†ใ“ใจใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ณใƒผใƒ‰ใ‚„ใ‚ตใƒผใƒใƒผใฎใฉใ“ใ‹ใงไฝ•ใ‹ๅ•้กŒใŒ็™บ็”Ÿใ—ใŸๅ ดๅˆใ€ใ“ใ‚Œใ‚‰ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใฎใ„ใšใ‚Œใ‹ใŒ่‡ชๅ‹•็š„ใซ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใใ‚Œใžใ‚Œใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใฉใฎใ‚ณใƒผใƒ‰ใŒไฝ•ใฎใŸใ‚ใฎใ‚ณใƒผใƒ‰ใชใฎใ‹ใซใคใ„ใฆ่ฉณ็ดฐใฏMDN HTTP ใƒฌใ‚นใƒใƒณใ‚นใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใซใคใ„ใฆใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +ใใ‚Œใžใ‚Œใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใฉใฎใ‚ณใƒผใƒ‰ใŒไฝ•ใฎใŸใ‚ใฎใ‚ณใƒผใƒ‰ใชใฎใ‹ใซใคใ„ใฆ่ฉณ็ดฐใฏMDN documentation about HTTP status codesใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ๅๅ‰ใ‚’่ฆšใˆใ‚‹ใŸใ‚ใฎ่ฟ‘้“ +## ๅๅ‰ใ‚’่ฆšใˆใ‚‹ใŸใ‚ใฎ่ฟ‘้“ { #shortcut-to-remember-the-names } ๅ…ˆใปใฉใฎไพ‹ใ‚’ใ‚‚ใ†ไธ€ๅบฆ่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: -{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} `201`ใฏใ€ŒไฝœๆˆๅฎŒไบ†ใ€ใฎใŸใ‚ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใงใ™ใ€‚ @@ -82,11 +82,11 @@ HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ๏ผ“ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚น `fastapi.status`ใฎไพฟๅˆฉใชๅค‰ๆ•ฐใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} -ใใ‚Œใ‚‰ใฏไพฟๅˆฉใงใ™ใ€‚ใใ‚Œใ‚‰ใฏๅŒใ˜็•ชๅทใ‚’ไฟๆŒใ—ใฆใŠใ‚Šใ€ใใฎๆ–นๆณ•ใงใฏใ‚จใƒ‡ใ‚ฃใ‚ฟใฎ่‡ชๅ‹•่ฃœๅฎŒใ‚’ไฝฟ็”จใ—ใฆใใ‚Œใ‚‰ใ‚’่ฆ‹ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใใ‚Œใ‚‰ใฏๅ˜ใชใ‚‹ไพฟๅˆฉใชใ‚‚ใฎใงใ‚ใ‚Šใ€ๅŒใ˜็•ชๅทใ‚’ไฟๆŒใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใฎๆ–นๆณ•ใงใฏใ‚จใƒ‡ใ‚ฃใ‚ฟใฎ่‡ชๅ‹•่ฃœๅฎŒใ‚’ไฝฟ็”จใ—ใฆใใ‚Œใ‚‰ใ‚’่ฆ‹ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ - + /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -96,6 +96,6 @@ HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ๏ผ“ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚น /// -## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎๅค‰ๆ›ด +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎๅค‰ๆ›ด { #changing-the-default } ๅพŒใซใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../advanced/response-change-status-code.md){.internal-link target=_blank}ใงใ€ใ“ใ“ใงๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใจใฏ็•ฐใชใ‚‹ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’่ฟ”ใ™ๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/schema-extra-example.md b/docs/ja/docs/tutorial/schema-extra-example.md index 1834e67b27..e526685c2f 100644 --- a/docs/ja/docs/tutorial/schema-extra-example.md +++ b/docs/ja/docs/tutorial/schema-extra-example.md @@ -1,55 +1,202 @@ -# ใ‚นใ‚ญใƒผใƒžใฎ่ฟฝๅŠ  - ไพ‹ +# ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎExampleใƒ‡ใƒผใ‚ฟใฎๅฎฃ่จ€ { #declare-request-example-data } -JSON Schemaใซ่ฟฝๅŠ ใ™ใ‚‹ๆƒ…ๅ ฑใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ‚ขใƒ—ใƒชใŒๅ—ใ‘ๅ–ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใฎไพ‹ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ -ไธ€่ˆฌ็š„ใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใฏใ“ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง็คบใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซ`example`ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ +ใ“ใ“ใงใฏใ€ใใ‚Œใ‚’่กŒใ†ใ„ใใคใ‹ใฎๆ–นๆณ•ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ -JSON Schemaใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๆ–นๆณ•ใฏใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ +## Pydanticใƒขใƒ‡ใƒซใงใฎ่ฟฝๅŠ JSON Schemaใƒ‡ใƒผใ‚ฟ { #extra-json-schema-data-in-pydantic-models } -## Pydanticใฎ`schema_extra` +็”Ÿๆˆใ•ใ‚Œใ‚‹JSON Schemaใซ่ฟฝๅŠ ใ•ใ‚Œใ‚‹Pydanticใƒขใƒ‡ใƒซใฎ`examples`ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ -Pydanticใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ: ใ‚นใ‚ญใƒผใƒžใฎใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซใ€`Config`ใจ`schema_extra`ใ‚’ไฝฟใฃใฆPydanticใƒขใƒ‡ใƒซใฎไพ‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -{* ../../docs_src/schema_extra_example/tutorial001.py hl[15,16,17,18,19,20,21,22,23] *} +ใใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใฏใ€ใใฎใƒขใƒ‡ใƒซใฎๅ‡บๅŠ›**JSON Schema**ใซใใฎใพใพ่ฟฝๅŠ ใ•ใ‚Œใ€APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ -ใใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใฏใใฎใพใพๅ‡บๅŠ›ใ•ใ‚Œใ€JSON Schemaใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ +Pydanticใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ: Configurationใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซใ€`dict`ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅฑžๆ€ง`model_config`ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -## `Field`ใฎ่ฟฝๅŠ ๅผ•ๆ•ฐ +็”Ÿๆˆใ•ใ‚Œใ‚‹JSON Schemaใซ่กจ็คบใ—ใŸใ„่ฟฝๅŠ ใƒ‡ใƒผใ‚ฟ๏ผˆ`examples`ใ‚’ๅซใ‚€๏ผ‰ใ‚’ๅซใ‚€`dict`ใ‚’ไฝฟใฃใฆใ€`"json_schema_extra"`ใ‚’่จญๅฎšใงใใพใ™ใ€‚ -ๅพŒ่ฟฐใ™ใ‚‹`Field`ใ€`Path`ใ€`Query`ใ€`Body`ใชใฉใงใฏใ€ไปปๆ„ใฎๅผ•ๆ•ฐใ‚’้–ขๆ•ฐใซๆธกใ™ใ“ใจใงJSON Schemaใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: +/// tip | ่ฑ†็Ÿฅ่ญ˜ -{* ../../docs_src/schema_extra_example/tutorial002.py hl[4,10,11,12,13] *} +ๅŒใ˜ๆ‰‹ๆณ•ใ‚’ไฝฟใฃใฆJSON Schemaใ‚’ๆ‹กๅผตใ—ใ€็‹ฌ่‡ชใฎใ‚ซใ‚นใ‚ฟใƒ ่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ -/// warning | ๆณจๆ„ +ไพ‹ใˆใฐใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใฎใŸใ‚ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ€ใชใฉใซไฝฟใˆใพใ™ใ€‚ + +/// + +/// info | ๆƒ…ๅ ฑ + +OpenAPI 3.1.0๏ผˆFastAPI 0.99.0ไปฅ้™ใงไฝฟ็”จ๏ผ‰ใงใฏใ€**JSON Schema**ๆจ™ๆบ–ใฎไธ€้ƒจใงใ‚ใ‚‹`examples`ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ—ใŸใ€‚ -ใ“ใ‚Œใ‚‰ใฎ่ฟฝๅŠ ๅผ•ๆ•ฐใŒๆธกใ•ใ‚Œใฆใ‚‚ใ€ๆ–‡ๆ›ธๅŒ–ใฎใŸใ‚ใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏ่ฟฝๅŠ ใ•ใ‚Œใšใ€ๆณจ้‡ˆใ ใ‘ใŒ่ฟฝๅŠ ใ•ใ‚Œใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ +ใใ‚Œไปฅๅ‰ใฏใ€ๅ˜ไธ€ใฎไพ‹ใ‚’ๆŒใคใ‚ญใƒผใƒฏใƒผใƒ‰`example`ใฎใฟใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ใ“ใ‚ŒใฏOpenAPI 3.1.0ใงใ‚‚ๅผ•ใ็ถšใใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใŒใ€้žๆŽจๅฅจใงใ‚ใ‚Šใ€JSON Schemaๆจ™ๆบ–ใฎไธ€้ƒจใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใฎใŸใ‚ใ€`example`ใ‹ใ‚‰`examples`ใธใฎ็งป่กŒใŒๆŽจๅฅจใ•ใ‚Œใพใ™ใ€‚๐Ÿค“ + +่ฉณ็ดฐใฏใ“ใฎใƒšใƒผใ‚ธใฎๆœ€ๅพŒใง่ชญใ‚ใพใ™ใ€‚ /// -## `Body`ใฎ่ฟฝๅŠ ๅผ•ๆ•ฐ +## `Field`ใฎ่ฟฝๅŠ ๅผ•ๆ•ฐ { #field-additional-arguments } + +Pydanticใƒขใƒ‡ใƒซใง`Field()`ใ‚’ไฝฟใ†ๅ ดๅˆใ€่ฟฝๅŠ ใฎ`examples`ใ‚‚ๅฎฃ่จ€ใงใใพใ™: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## JSON Schemaๅ†…ใฎ`examples` - OpenAPI { #examples-in-json-schema-openapi } -่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’`Field`ใซๆธกใ™ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€`Path`ใ€`Query`ใ€`Body`ใชใฉใงใ‚‚ๅŒใ˜ใ“ใจใŒใงใใพใ™ใ€‚ +ไปฅไธ‹ใฎใ„ใšใ‚Œใ‹ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆ: -ไพ‹ใˆใฐใ€`Body`ใซใƒœใƒ‡ใ‚ฃใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ`example`ใ‚’ๆธกใ™ใ“ใจใŒใงใใพใ™: +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` -{* ../../docs_src/schema_extra_example/tutorial003.py hl[21,22,23,24,25,26] *} +่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’ๅซใ‚€`examples`ใฎใ‚ฐใƒซใƒผใƒ—ใ‚’ๅฎฃ่จ€ใงใใ€ใใ‚Œใ‚‰ใฏ**OpenAPI**ๅ†…ใฎใใ‚Œใžใ‚Œใฎ**JSON Schemas**ใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ -## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎUIใฎไพ‹ +### `examples`ใ‚’ไฝฟใ†`Body` { #body-with-examples } + +ใ“ใ“ใงใฏใ€`Body()`ใงๆœŸๅพ…ใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใฎไพ‹ใ‚’1ใคๅซใ‚€`examples`ใ‚’ๆธกใ—ใพใ™: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงใฎไพ‹ { #example-in-the-docs-ui } ไธŠ่จ˜ใฎใ„ใšใ‚Œใฎๆ–นๆณ•ใงใ‚‚ใ€`/docs`ใฎไธญใงใฏไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: - + + +### ่ค‡ๆ•ฐใฎ`examples`ใ‚’ไฝฟใ†`Body` { #body-with-multiple-examples } + +ใ‚‚ใกใ‚ใ‚“ใ€่ค‡ๆ•ฐใฎ`examples`ใ‚’ๆธกใ™ใ“ใจใ‚‚ใงใใพใ™: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +ใ“ใฎๅ ดๅˆใ€examplesใฏใใฎใƒœใƒ‡ใ‚ฃใƒ‡ใƒผใ‚ฟใฎๅ†…้ƒจ**JSON Schema**ใฎไธ€้ƒจใซใชใ‚Šใพใ™ใ€‚ + +ใใ‚Œใงใ‚‚ใ€ๅŸท็ญ†ๆ™‚็‚นใงใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฎ่กจ็คบใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใƒ„ใƒผใƒซใงใ‚ใ‚‹Swagger UIใฏใ€**JSON Schema**ๅ†…ใฎใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆ่ค‡ๆ•ฐใฎไพ‹ใ‚’่กจ็คบใ™ใ‚‹ใ“ใจใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ๅ›ž้ฟ็ญ–ใซใคใ„ใฆใฏไปฅไธ‹ใ‚’่ชญใ‚“ใงใใ ใ•ใ„ใ€‚ + +### OpenAPIๅ›บๆœ‰ใฎ`examples` { #openapi-specific-examples } + +**JSON Schema**ใŒ`examples`ใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ๅ‰ใ‹ใ‚‰ใ€OpenAPIใฏๅŒใ˜ใ`examples`ใจใ„ใ†ๅˆฅใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ—ใŸใ€‚ + +ใ“ใฎ**OpenAPIๅ›บๆœ‰**ใฎ`examples`ใฏใ€OpenAPIไป•ๆง˜ใฎๅˆฅใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใซๅ…ฅใ‚Šใพใ™ใ€‚ๅ„JSON Schemaใฎไธญใงใฏใชใใ€**ๅ„*path operation*ใฎ่ฉณ็ดฐ**ใซๅ…ฅใ‚Šใพใ™ใ€‚ + +ใใ—ใฆSwagger UIใฏใ€ใ“ใฎ็‰นๅฎšใฎ`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ไปฅๅ‰ใ‹ใ‚‰ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ใ“ใ‚Œใ‚’ไฝฟใฃใฆ**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใซ็•ฐใชใ‚‹ไพ‹ใ‚’่กจ็คบ**ใงใใพใ™ใ€‚ + +ใ“ใฎOpenAPIๅ›บๆœ‰ใƒ•ใ‚ฃใƒผใƒซใƒ‰`examples`ใฎๅฝขใฏ**่ค‡ๆ•ฐใฎไพ‹**๏ผˆ`list`ใงใฏใชใ๏ผ‰ใ‚’ๆŒใค`dict`ใงใ‚ใ‚Šใ€ใใ‚Œใžใ‚Œใซ่ฟฝๅŠ ๆƒ…ๅ ฑใŒๅซใพใ‚Œใ€ใใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใฏ**OpenAPI**ใซใ‚‚่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ‚ŒใฏOpenAPIใซๅซใพใ‚Œใ‚‹ๅ„JSON Schemaใฎไธญใซใฏๅ…ฅใ‚‰ใšใ€ๅค–ๅดใฎใ€*path operation*ใซ็›ดๆŽฅๅ…ฅใ‚Šใพใ™ใ€‚ + +### `openapi_examples`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎไฝฟ็”จ { #using-the-openapi-examples-parameter } + +FastAPIใงใฏใ€ไปฅไธ‹ใซๅฏพใ—ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟ`openapi_examples`ใ‚’ไฝฟใฃใฆใ€OpenAPIๅ›บๆœ‰ใฎ`examples`ใ‚’ๅฎฃ่จ€ใงใใพใ™: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +`dict`ใฎใ‚ญใƒผใฏๅ„ไพ‹ใ‚’่ญ˜ๅˆฅใ—ใ€ๅ„ๅ€คใฏๅˆฅใฎ`dict`ใงใ™ใ€‚ + +`examples`ๅ†…ใฎๅ„็‰นๅฎšใฎไพ‹`dict`ใซใฏใ€ๆฌกใฎๅ†…ๅฎนใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™: + +* `summary`: ไพ‹ใฎ็Ÿญใ„่ชฌๆ˜Žใ€‚ +* `description`: Markdownใƒ†ใ‚ญใ‚นใƒˆใ‚’ๅซใ‚ใ‚‰ใ‚Œใ‚‹้•ทใ„่ชฌๆ˜Žใ€‚ +* `value`: ๅฎŸ้š›ใซ่กจ็คบใ•ใ‚Œใ‚‹ไพ‹๏ผˆไพ‹: `dict`๏ผ‰ใ€‚ +* `externalValue`: `value`ใฎไปฃๆ›ฟใงใ€ไพ‹ใ‚’ๆŒ‡ใ™URLใงใ™ใ€‚ใŸใ ใ—ใ€`value`ใปใฉๅคšใใฎใƒ„ใƒผใƒซใงใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใชใ„ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใซไฝฟใˆใพใ™: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฎOpenAPI Examples { #openapi-examples-in-the-docs-ui } + +`Body()`ใซ`openapi_examples`ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€`/docs`ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + + + +## ๆŠ€่ก“่ฉณ็ดฐ { #technical-details } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ™ใงใซ**FastAPI**ใƒใƒผใ‚ธใƒงใƒณ**0.99.0ไปฅไธŠ**ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ใŠใใ‚‰ใใ“ใ‚Œใ‚‰ใฎ่ฉณ็ดฐใฏ**ใ‚นใ‚ญใƒƒใƒ—**ใงใใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฏใ€OpenAPI 3.1.0ใŒๅˆฉ็”จๅฏ่ƒฝใซใชใ‚‹ๅ‰ใฎๅคใ„ใƒใƒผใ‚ธใƒงใƒณใซใ‚ˆใ‚Š้–ข้€ฃใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใฏ็ฐกๅ˜ใชOpenAPIใจJSON Schemaใฎ**ๆญดๅฒใฎๆŽˆๆฅญ**ใ ใจ่€ƒใˆใ‚‰ใ‚Œใพใ™ใ€‚๐Ÿค“ + +/// + +/// warning | ๆณจๆ„ + +ใ“ใ“ใงใฏใ€ๆจ™ๆบ–ใงใ‚ใ‚‹**JSON Schema**ใจ**OpenAPI**ใซใคใ„ใฆใฎ้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐใ‚’ๆ‰ฑใ„ใพใ™ใ€‚ + +ไธŠใฎใ‚ขใ‚คใƒ‡ใ‚ขใŒใ™ใงใซใ†ใพใๅ‹•ใ„ใฆใ„ใ‚‹ใชใ‚‰ใ€ใใ‚Œใงๅๅˆ†ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ—ใ€ใŠใใ‚‰ใใ“ใฎ่ฉณ็ดฐใฏไธ่ฆใงใ™ใ€‚ๆฐ—่ปฝใซใ‚นใ‚ญใƒƒใƒ—ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +OpenAPI 3.1.0ใ‚ˆใ‚Šๅ‰ใฏใ€OpenAPIใฏๅคใๆ”นๅค‰ใ•ใ‚ŒใŸใƒใƒผใ‚ธใƒงใƒณใฎ**JSON Schema**ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ—ใŸใ€‚ + +JSON Schemaใซใฏ`examples`ใŒใชใ‹ใฃใŸใŸใ‚ใ€OpenAPIใฏ่‡ช่บซใŒๆ”นๅค‰ใ—ใŸใƒใƒผใ‚ธใƒงใƒณใซ็‹ฌ่‡ชใฎ`example`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’่ฟฝๅŠ ใ—ใพใ—ใŸใ€‚ + +OpenAPIใฏใ€ไป•ๆง˜ใฎไป–ใฎ้ƒจๅˆ†ใซใ‚‚`example`ใจ`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’่ฟฝๅŠ ใ—ใพใ—ใŸ: + +* `Parameter Object`๏ผˆไป•ๆง˜ๅ†…๏ผ‰ใ€‚FastAPIใฎไปฅไธ‹ใงไฝฟ็”จใ•ใ‚Œใพใ—ใŸ: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`ใ€‚ไป•ๆง˜ๅ†…ใฎ`Media Type Object`ใฎ`content`ใƒ•ใ‚ฃใƒผใƒซใƒ‰๏ผˆไป•ๆง˜ๅ†…๏ผ‰ใ€‚FastAPIใฎไปฅไธ‹ใงไฝฟ็”จใ•ใ‚Œใพใ—ใŸ: + * `Body()` + * `File()` + * `Form()` + +/// info | ๆƒ…ๅ ฑ + +ใ“ใฎๅคใ„OpenAPIๅ›บๆœ‰ใฎ`examples`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€FastAPI `0.103.0`ไปฅ้™ใฏ`openapi_examples`ใซใชใ‚Šใพใ—ใŸใ€‚ + +/// + +### JSON Schemaใฎ`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ { #json-schemas-examples-field } + +ใ—ใ‹ใ—ใใฎๅพŒใ€JSON Schemaใฏๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณใฎไป•ๆง˜ใซ`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’่ฟฝๅŠ ใ—ใพใ—ใŸใ€‚ + +ใใ—ใฆใ€ๆ–ฐใ—ใ„OpenAPI 3.1.0ใฏใ€ใ“ใฎๆ–ฐใ—ใ„ใƒ•ใ‚ฃใƒผใƒซใƒ‰`examples`ใ‚’ๅซใ‚€ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณ๏ผˆJSON Schema 2020-12๏ผ‰ใซๅŸบใฅใใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ + +ใใ—ใฆ็พๅœจใ€ใ“ใฎๆ–ฐใ—ใ„`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏใ€ๅคใ„ๅ˜ไธ€๏ผˆใ‹ใคใ‚ซใ‚นใ‚ฟใƒ ๏ผ‰ใฎ`example`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚ˆใ‚Šๅ„ชๅ…ˆใ•ใ‚Œใ€`example`ใฏ็พๅœจ้žๆŽจๅฅจใงใ™ใ€‚ + +JSON Schemaใฎใ“ใฎๆ–ฐใ—ใ„`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏใ€OpenAPIใฎไป–ใฎๅ ดๆ‰€๏ผˆไธŠใง่ชฌๆ˜Ž๏ผ‰ใซใ‚ใ‚‹ใ‚ˆใ†ใช่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๆŒใคdictใงใฏใชใใ€**ๅ˜ใชใ‚‹ไพ‹ใฎ`list`**ใงใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +OpenAPI 3.1.0ใŒใ“ใฎJSON Schemaใจใฎๆ–ฐใ—ใ„ใ‚ˆใ‚Šใ‚ทใƒณใƒ—ใƒซใช็ตฑๅˆใจใจใ‚‚ใซใƒชใƒชใƒผใ‚นใ•ใ‚ŒใŸๅพŒใ‚‚ใ€ใ—ใฐใ‚‰ใใฎ้–“ใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๆไพ›ใ™ใ‚‹ใƒ„ใƒผใƒซใงใ‚ใ‚‹Swagger UIใฏOpenAPI 3.1.0ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใงใ—ใŸ๏ผˆใƒใƒผใ‚ธใƒงใƒณ5.0.0ใ‹ใ‚‰ใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™๐ŸŽ‰๏ผ‰ใ€‚ + +ใใฎใŸใ‚ใ€FastAPI 0.99.0ใ‚ˆใ‚Šๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใฏใ€OpenAPI 3.1.0ใ‚ˆใ‚ŠไฝŽใ„ใƒใƒผใ‚ธใƒงใƒณใฎOpenAPIใ‚’ใพใ ไฝฟ็”จใ—ใฆใ„ใพใ—ใŸใ€‚ + +/// + +### PydanticใจFastAPIใฎ`examples` { #pydantic-and-fastapi-examples } + +Pydanticใƒขใƒ‡ใƒซๅ†…ใงใ€`schema_extra`ใพใŸใฏ`Field(examples=["something"])`ใ‚’ไฝฟใฃใฆ`examples`ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€ใใฎไพ‹ใฏใใฎPydanticใƒขใƒ‡ใƒซใฎ**JSON Schema**ใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ + +ใใ—ใฆใใฎPydanticใƒขใƒ‡ใƒซใฎ**JSON Schema**ใฏAPIใฎ**OpenAPI**ใซๅซใพใ‚Œใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +FastAPI 0.99.0ใ‚ˆใ‚Šๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณ๏ผˆ0.99.0ไปฅไธŠใฏๆ–ฐใ—ใ„OpenAPI 3.1.0ใ‚’ไฝฟ็”จ๏ผ‰ใงใฏใ€ไป–ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ๏ผˆ`Query()`ใ€`Body()`ใชใฉ๏ผ‰ใง`example`ใพใŸใฏ`examples`ใ‚’ไฝฟใฃใฆใ‚‚ใ€ใใ‚Œใ‚‰ใฎไพ‹ใฏใใฎใƒ‡ใƒผใ‚ฟใ‚’่ชฌๆ˜Žใ™ใ‚‹JSON Schema๏ผˆOpenAPI็‹ฌ่‡ช็‰ˆใฎJSON Schemaใงใ•ใˆ๏ผ‰ใซใฏ่ฟฝๅŠ ใ•ใ‚Œใšใ€OpenAPIๅ†…ใฎ*path operation*ๅฎฃ่จ€ใซ็›ดๆŽฅ่ฟฝๅŠ ใ•ใ‚Œใฆใ„ใพใ—ใŸ๏ผˆJSON Schemaใ‚’ไฝฟ็”จใ™ใ‚‹OpenAPIใฎ้ƒจๅˆ†ใฎๅค–ๅด๏ผ‰ใ€‚ -## ๆŠ€่ก“่ฉณ็ดฐ +ใ—ใ‹ใ—ใ€FastAPI 0.99.0ไปฅไธŠใงใฏOpenAPI 3.1.0ใ‚’ไฝฟ็”จใ—ใ€ใใ‚ŒใฏJSON Schema 2020-12ใจSwagger UI 5.0.0ไปฅไธŠใ‚’ไฝฟใ†ใŸใ‚ใ€ใ™ในใฆใŒใ‚ˆใ‚Šไธ€่ฒซใ—ใ€ไพ‹ใฏJSON Schemaใซๅซใพใ‚Œใพใ™ใ€‚ -`example` ใจ `examples`ใซใคใ„ใฆ... +### Swagger UIใจOpenAPIๅ›บๆœ‰ใฎ`examples` { #swagger-ui-and-openapi-specific-examples } -JSON Schemaใฎๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใงใฏ`examples`ใจใ„ใ†ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎš็พฉใ—ใฆใ„ใพใ™ใŒใ€OpenAPIใฏ`examples`ใ‚’ๆŒใŸใชใ„ๅคใ„ใƒใƒผใ‚ธใƒงใƒณใฎJSON Schemaใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใพใ™ใ€‚ +Swagger UIใฏ่ค‡ๆ•ฐใฎJSON Schema examplesใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ‹ใฃใŸ๏ผˆ2023-08-26ๆ™‚็‚น๏ผ‰ใŸใ‚ใ€ใƒฆใƒผใ‚ถใƒผใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ค‡ๆ•ฐใฎไพ‹ใ‚’่กจ็คบใ™ใ‚‹ๆ‰‹ๆฎตใŒใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ -ใใฎใŸใ‚ใ€OpenAPIใงใฏๅŒใ˜็›ฎ็š„ใฎใŸใ‚ใซ`example`ใ‚’็‹ฌ่‡ชใซๅฎš็พฉใ—ใฆใŠใ‚Š๏ผˆ`examples`ใงใฏใชใ`example`ใจใ—ใฆ๏ผ‰ใ€ใใ‚ŒใŒdocs UI๏ผˆSwagger UIใ‚’ไฝฟ็”จ๏ผ‰ใงไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +ใใ‚Œใ‚’่งฃๆฑบใ™ใ‚‹ใŸใ‚ใ€FastAPI `0.103.0`ใฏใ€ๆ–ฐใ—ใ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟ`openapi_examples`ใงใ€ๅŒใ˜ๅคใ„**OpenAPIๅ›บๆœ‰**ใฎ`examples`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎ**ใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ **ใ—ใพใ—ใŸใ€‚๐Ÿค“ -ใคใพใ‚Šใ€`example`ใฏJSON Schemaใฎไธ€้ƒจใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€OpenAPIใฎไธ€้ƒจใงใ‚ใ‚Šใ€ใใ‚ŒใŒdocs UIใงไฝฟ็”จใ•ใ‚Œใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +### ใพใจใ‚ { #summary } -## ใใฎไป–ใฎๆƒ…ๅ ฑ +ๆ˜”ใฏๆญดๅฒใŒใ‚ใพใ‚Šๅฅฝใใงใฏใชใ„ใจ่จ€ใฃใฆใ„ใพใ—ใŸ...ใŒใ€ไปŠใฎ็งใฏใ€ŒๆŠ€่ก“ใฎๆญดๅฒใ€ใฎๆŽˆๆฅญใ‚’ใ—ใฆใ„ใพใ™ใ€‚๐Ÿ˜… -ๅŒใ˜ใ‚ˆใ†ใซใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฎใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใชใฉใ‚’ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใ™ใ‚‹ใŸใ‚ใซใ€ๅ„ใƒขใƒ‡ใƒซใฎJSON Schemaใซ่ฟฝๅŠ ใ•ใ‚Œใ‚‹็‹ฌ่‡ชใฎ่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +่ฆใ™ใ‚‹ใซใ€**FastAPI 0.99.0ไปฅไธŠใซใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰**ใ—ใฆใใ ใ•ใ„ใ€‚ใใ†ใ™ใ‚Œใฐใ€็‰ฉไบ‹ใฏใ‚‚ใฃใจ**ใ‚ทใƒณใƒ—ใƒซใงไธ€่ฒซๆ€งใŒใ‚ใ‚Š็›ดๆ„Ÿ็š„**ใซใชใ‚Šใ€ใ“ใ‚Œใ‚‰ใฎๆญดๅฒ็š„่ฉณ็ดฐใ‚’็Ÿฅใ‚‹ๅฟ…่ฆใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/security/first-steps.md b/docs/ja/docs/tutorial/security/first-steps.md index 0ce0f929be..76ef04db8d 100644 --- a/docs/ja/docs/tutorial/security/first-steps.md +++ b/docs/ja/docs/tutorial/security/first-steps.md @@ -1,4 +1,4 @@ -# ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - ๆœ€ๅˆใฎไธ€ๆญฉ +# ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - ๆœ€ๅˆใฎไธ€ๆญฉ { #security-first-steps } ใ‚ใ‚‹ใƒ‰ใƒกใ‚คใƒณใซใ€**ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰** APIใ‚’ๆŒใฃใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ @@ -12,25 +12,31 @@ **FastAPI**ใŒๆไพ›ใ™ใ‚‹ใƒ„ใƒผใƒซใ‚’ไฝฟใฃใฆใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๅˆถๅพกใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -## ใฉใ†่ฆ‹ใˆใ‚‹ใ‹ +## ใฉใ†่ฆ‹ใˆใ‚‹ใ‹ { #how-it-looks } ใพใšใฏใ“ใฎใ‚ณใƒผใƒ‰ใ‚’ไฝฟใฃใฆใ€ใฉใ†ๅ‹•ใใ‹่ฆณๅฏŸใ—ใพใ™ใ€‚ใใฎๅพŒใงใ€ไฝ•ใŒ่ตทใ“ใฃใฆใ„ใ‚‹ใฎใ‹็†่งฃใ—ใพใ—ใ‚‡ใ†ใ€‚ -## `main.py`ใ‚’ไฝœๆˆ +## `main.py`ใ‚’ไฝœๆˆ { #create-main-py } `main.py`ใซใ€ไธ‹่จ˜ใฎไพ‹ใ‚’ใ‚ณใƒ”ใƒผใ—ใพใ™: -{* ../../docs_src/security/tutorial001.py *} +{* ../../docs_src/security/tutorial001_an_py39.py *} -## ๅฎŸ่กŒ +## ๅฎŸ่กŒ { #run-it } /// info | ๆƒ…ๅ ฑ -ใพใš`python-multipart`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ +`python-multipart` ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏใ€`pip install "fastapi[standard]"` ใ‚ณใƒžใƒณใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจ **FastAPI** ใจไธ€็ท’ใซ่‡ชๅ‹•็š„ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใพใ™ใ€‚ -ไพ‹ใˆใฐใ€`pip install python-multipart`ใ€‚ +ใ—ใ‹ใ—ใ€`pip install fastapi` ใ‚ณใƒžใƒณใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใ€`python-multipart` ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚ -ใ“ใ‚Œใฏใ€**OAuth2**ใŒ `ใƒฆใƒผใ‚ถใƒผๅ` ใ‚„ `ใƒ‘ใ‚นใƒฏใƒผใƒ‰` ใ‚’้€ไฟกใ™ใ‚‹ใŸใ‚ใซใ€ใ€Œใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใ€ใ‚’ไฝฟใ†ใ‹ใ‚‰ใงใ™ใ€‚ +ๆ‰‹ๅ‹•ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใซใฏใ€[ไปฎๆƒณ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ๆฌกใฎใ‚ณใƒžใƒณใƒ‰ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install python-multipart +``` + +ใ“ใ‚Œใฏใ€**OAuth2**ใŒ `username` ใจ `password` ใ‚’้€ไฟกใ™ใ‚‹ใŸใ‚ใซใ€ใ€Œใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใ€ใ‚’ไฝฟใ†ใ‹ใ‚‰ใงใ™ใ€‚ /// @@ -39,14 +45,14 @@
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-## ็ขบ่ช +## ็ขบ่ช { #check-it } ๆฌกใฎใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใใ ใ•ใ„: http://127.0.0.1:8000/docsใ€‚ @@ -62,7 +68,7 @@ $ uvicorn main:app --reload /// -ใใ‚Œใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใจใ€`ใƒฆใƒผใ‚ถใƒผๅ`ใจ`ใƒ‘ใ‚นใƒฏใƒผใƒ‰` (ใŠใ‚ˆใณใใฎไป–ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใƒ•ใ‚ฃใƒผใƒซใƒ‰) ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ๅฐใ•ใช่ช่จผใƒ•ใ‚ฉใƒผใƒ ใŒ่กจ็คบใ•ใ‚Œใพใ™: +ใใ‚Œใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใจใ€`username` ใจ `password`๏ผˆใŠใ‚ˆใณใใฎไป–ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใƒ•ใ‚ฃใƒผใƒซใƒ‰๏ผ‰ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ๅฐใ•ใช่ชๅฏใƒ•ใ‚ฉใƒผใƒ ใŒ่กจ็คบใ•ใ‚Œใพใ™: @@ -80,11 +86,11 @@ $ uvicorn main:app --reload ใพใŸใ€ๅŒใ˜ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‡ใƒใƒƒใ‚ฐใ€ใƒใ‚งใƒƒใ‚ฏใ€ใƒ†ใ‚นใƒˆใฎใŸใ‚ใซใ‚‚ๅˆฉ็”จใงใใพใ™ใ€‚ -## `ใƒ‘ใ‚นใƒฏใƒผใƒ‰` ใƒ•ใƒญใƒผ +## `password` ใƒ•ใƒญใƒผ { #the-password-flow } ใงใฏใ€ๅฐ‘ใ—่ฉฑใ‚’ๆˆปใ—ใฆใ€ใฉใ†ใชใฃใฆใ„ใ‚‹ใ‹็†่งฃใ—ใพใ—ใ‚‡ใ†ใ€‚ -`ใƒ‘ใ‚นใƒฏใƒผใƒ‰`ใฎใ€Œใƒ•ใƒญใƒผใ€ใฏใ€OAuth2ใงๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใ‚’ๆ‰ฑใ†ๆ–นๆณ• (ใ€Œใƒ•ใƒญใƒผใ€) ใฎ1ใคใงใ™ใ€‚ +`password`ใฎใ€Œใƒ•ใƒญใƒผใ€ใฏใ€OAuth2ใงๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใ‚’ๆ‰ฑใ†ๆ–นๆณ• (ใ€Œใƒ•ใƒญใƒผใ€) ใฎ1ใคใงใ™ใ€‚ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผใ‹ใ‚‰็‹ฌ็ซ‹ใ—ใŸใ‚‚ใฎใจใ—ใฆ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ @@ -92,9 +98,9 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ ใใ“ใงใ€็ฐก็•ฅๅŒ–ใ—ใŸ็ฎ‡ๆ‰€ใ‹ใ‚‰่ฆ‹็›ดใ—ใฆใฟใพใ—ใ‚‡ใ†: -* ใƒฆใƒผใ‚ถใƒผใฏใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใง`ใƒฆใƒผใ‚ถใƒผๅ`ใจ`ใƒ‘ใ‚นใƒฏใƒผใƒ‰`ใ‚’ๅ…ฅๅŠ›ใ—ใ€`Enter`ใ‚’ๆŠผใ—ใพใ™ใ€‚ -* ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ (ใƒฆใƒผใ‚ถใƒผใฎใƒ–ใƒฉใ‚ฆใ‚ถใงๅฎŸ่กŒไธญ) ใฏใ€`ใƒฆใƒผใ‚ถใƒผๅ`ใจ`ใƒ‘ใ‚นใƒฏใƒผใƒ‰`ใ‚’APIใฎ็‰นๅฎšใฎURL (`tokenUrl="token"`ใงๅฎฃ่จ€ใ•ใ‚ŒใŸ) ใซ้€ไฟกใ—ใพใ™ใ€‚ -* APIใฏ`ใƒฆใƒผใ‚ถใƒผๅ`ใจ`ใƒ‘ใ‚นใƒฏใƒผใƒ‰`ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใ€ใ€Œใƒˆใƒผใ‚ฏใƒณใ€ใ‚’่ฟ”ๅดใ—ใพใ™ (ใพใ ๅฎŸ่ฃ…ใ—ใฆใ„ใพใ›ใ‚“)ใ€‚ +* ใƒฆใƒผใ‚ถใƒผใฏใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใง`username`ใจ`password`ใ‚’ๅ…ฅๅŠ›ใ—ใ€`Enter`ใ‚’ๆŠผใ—ใพใ™ใ€‚ +* ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ (ใƒฆใƒผใ‚ถใƒผใฎใƒ–ใƒฉใ‚ฆใ‚ถใงๅฎŸ่กŒไธญ) ใฏใ€`username`ใจ`password`ใ‚’APIใฎ็‰นๅฎšใฎURL (`tokenUrl="token"`ใงๅฎฃ่จ€ใ•ใ‚ŒใŸ) ใซ้€ไฟกใ—ใพใ™ใ€‚ +* APIใฏ`username`ใจ`password`ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใ€ใ€Œใƒˆใƒผใ‚ฏใƒณใ€ใ‚’่ฟ”ๅดใ—ใพใ™ (ใพใ ๅฎŸ่ฃ…ใ—ใฆใ„ใพใ›ใ‚“)ใ€‚ * ใ€Œใƒˆใƒผใ‚ฏใƒณใ€ใฏใŸใ ใฎๆ–‡ๅญ—ๅˆ—ใงใ‚ใ‚Šใ€ใ‚ใจใงใ“ใฎใƒฆใƒผใ‚ถใƒผใ‚’ๆคœ่จผใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ—ใพใ™ใ€‚ * ้€šๅธธใ€ใƒˆใƒผใ‚ฏใƒณใฏๆ™‚้–“ใŒ็ตŒใคใจๆœŸ้™ๅˆ‡ใ‚Œใซใชใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ•ใ‚Œใฆใ„ใพใ™ใ€‚ * ใƒˆใƒผใ‚ฏใƒณใŒๆœŸ้™ๅˆ‡ใ‚Œใฎๅ ดๅˆใฏใ€ๅ†ๅบฆใƒญใ‚ฐใ‚คใƒณใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -106,11 +112,11 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ * ใ—ใŸใŒใฃใฆใ€APIใง่ช่จผใ™ใ‚‹ใŸใ‚ใ€HTTPใƒ˜ใƒƒใƒ€ใƒผ`Authorization`ใซ`Bearer`ใฎๆ–‡ๅญ—ๅˆ—ใจใƒˆใƒผใ‚ฏใƒณใ‚’ๅŠ ใˆใŸๅ€คใ‚’้€ไฟกใ—ใพใ™ใ€‚ * ใƒˆใƒผใ‚ฏใƒณใซ`foobar`ใŒๅซใพใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€`Authorization`ใƒ˜ใƒƒใƒ€ใƒผใฎๅ†…ๅฎนใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: `Bearer foobar`ใ€‚ -## **FastAPI**ใฎ`OAuth2PasswordBearer` +## **FastAPI**ใฎ`OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } **FastAPI**ใฏใ€ใ“ใ‚Œใ‚‰ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆฉŸ่ƒฝใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹ใŸใ‚ใซใ€ๆŠฝ่ฑกๅบฆใฎ็•ฐใชใ‚‹่ค‡ๆ•ฐใฎใƒ„ใƒผใƒซใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ -ใ“ใฎไพ‹ใงใฏใ€**Bearer**ใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟ็”จใ—ใฆ**OAuth2**ใ‚’**ใƒ‘ใ‚นใƒฏใƒผใƒ‰**ใƒ•ใƒญใƒผใงไฝฟ็”จใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏ`OAuth2PasswordBearer`ใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ +ใ“ใฎไพ‹ใงใฏใ€**Bearer**ใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟ็”จใ—ใฆ**OAuth2**ใ‚’**Password**ใƒ•ใƒญใƒผใงไฝฟ็”จใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏ`OAuth2PasswordBearer`ใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ /// info | ๆƒ…ๅ ฑ @@ -124,9 +130,9 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ /// -`OAuth2PasswordBearer` ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๆ™‚ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`tokenUrl`ใ‚’ๆธกใ—ใพใ™ใ€‚ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ (ใƒฆใƒผใ‚ถใƒผใฎใƒ–ใƒฉใ‚ฆใ‚ถใงๅ‹•ไฝœใ™ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰) ใŒใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซ`ใƒฆใƒผใ‚ถใƒผๅ`ใจ`ใƒ‘ใ‚นใƒฏใƒผใƒ‰`ใ‚’้€ไฟกใ™ใ‚‹URLใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ +`OAuth2PasswordBearer` ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๆ™‚ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`tokenUrl`ใ‚’ๆธกใ—ใพใ™ใ€‚ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ (ใƒฆใƒผใ‚ถใƒผใฎใƒ–ใƒฉใ‚ฆใ‚ถใงๅ‹•ไฝœใ™ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰) ใŒใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซ`username`ใจ`password`ใ‚’้€ไฟกใ™ใ‚‹URLใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial001.py hl[6] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -134,13 +140,13 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ ็›ธๅฏพURLใ‚’ไฝฟใฃใฆใ„ใ‚‹ใฎใงใ€APIใŒ`https://example.com/`ใซใ‚ใ‚‹ๅ ดๅˆใ€`https://example.com/token`ใ‚’ๅ‚็…งใ—ใพใ™ใ€‚ใ—ใ‹ใ—ใ€APIใŒ`https://example.com/api/v1/`ใซใ‚ใ‚‹ๅ ดๅˆใฏ`https://example.com/api/v1/token`ใ‚’ๅ‚็…งใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ -็›ธๅฏพ URL ใ‚’ไฝฟใ†ใ“ใจใฏใ€[ใƒ—ใƒญใ‚ญใ‚ทใจๆŽฅ็ถš](../../advanced/behind-a-proxy.md){.internal-link target=_blank}ใฎใ‚ˆใ†ใช้ซ˜ๅบฆใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใ‚‚ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅ‹•ไฝœใ•ใ›็ถšใ‘ใ‚‹ใŸใ‚ใซ้‡่ฆใงใ™ใ€‚ +็›ธๅฏพ URL ใ‚’ไฝฟใ†ใ“ใจใฏใ€[ใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒ](../../advanced/behind-a-proxy.md){.internal-link target=_blank}ใฎใ‚ˆใ†ใช้ซ˜ๅบฆใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใ‚‚ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅ‹•ไฝœใ•ใ›็ถšใ‘ใ‚‹ใŸใ‚ใซ้‡่ฆใงใ™ใ€‚ /// ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใฏใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ/ *path operation*ใ‚’ไฝœๆˆใ—ใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€URL`/token`ใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ใ‚‚ใฎใงใ‚ใ‚‹ใจๅฎฃ่จ€ใ—ใพใ™ใ€‚ใ“ใฎๆƒ…ๅ ฑใฏ OpenAPI ใ‚„ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใช API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ -ๅฎŸ้š›ใฎpath operationใ‚‚ใ™ใใซไฝœใ‚Šใพใ™ใ€‚ +ๅฎŸ้š›ใฎ path operation ใ‚‚ใ™ใใซไฝœใ‚Šใพใ™ใ€‚ /// info | ๆƒ…ๅ ฑ @@ -160,13 +166,13 @@ oauth2_scheme(some, parameters) ใใฎใŸใ‚ใ€`Depends`ใจไธ€็ท’ใซไฝฟใ†ใ“ใจใŒใงใใพใ™ใ€‚ -### ไฝฟใ„ๆ–น +### ไฝฟใ„ๆ–น { #use-it } ใ“ใ‚Œใง`oauth2_scheme`ใ‚’`Depends`ใงไพๅญ˜้–ขไฟ‚ใซๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/security/tutorial001.py hl[10] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} -ใ“ใฎไพๅญ˜้–ขไฟ‚ใฏใ€*path operation function*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`token`ใซไปฃๅ…ฅใ•ใ‚Œใ‚‹`str`ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ +ใ“ใฎไพๅญ˜้–ขไฟ‚ใฏใ€*path operation ้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`token`ใซไปฃๅ…ฅใ•ใ‚Œใ‚‹`str`ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ **FastAPI**ใฏใ€ใ“ใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ—ใฆOpenAPIใ‚นใ‚ญใƒผใƒž (ใŠใ‚ˆใณ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ) ใงใ€Œใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ€ใ‚’ๅฎš็พฉใงใใ‚‹ใ“ใจใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ @@ -178,13 +184,13 @@ OpenAPIใจ็ตฑๅˆใ™ใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ (ใŠใ‚ˆใณ่‡ชๅ‹•AP /// -## ใฉใฎใ‚ˆใ†ใซๅ‹•ไฝœใ™ใ‚‹ใ‹ +## ไฝ•ใ‚’ใ™ใ‚‹ใ‹ { #what-it-does } -ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎไธญใซ`Authorization`ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆŽขใ—ใซ่กŒใใ€ใใฎๅ€คใŒ`Bearer`ใจไฝ•ใ‚‰ใ‹ใฎใƒˆใƒผใ‚ฏใƒณใ‚’ๅซใ‚“ใงใ„ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใ€ใใฎใƒˆใƒผใ‚ฏใƒณใ‚’`str`ใจใ—ใฆ่ฟ”ใ—ใพใ™ใ€‚ +ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎไธญใซ`Authorization`ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆŽขใ—ใซ่กŒใใ€ใใฎๅ€คใŒ`Bearer `ใจไฝ•ใ‚‰ใ‹ใฎใƒˆใƒผใ‚ฏใƒณใ‚’ๅซใ‚“ใงใ„ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใ€ใใฎใƒˆใƒผใ‚ฏใƒณใ‚’`str`ใจใ—ใฆ่ฟ”ใ—ใพใ™ใ€‚ -ใ‚‚ใ—`Authorization`ใƒ˜ใƒƒใƒ€ใƒผใŒ่ฆ‹ใคใ‹ใ‚‰ใชใ‹ใฃใŸใ‚Šใ€ๅ€คใŒ`Bearer`ใƒˆใƒผใ‚ฏใƒณใ‚’ๆŒใฃใฆใ„ใชใ‹ใฃใŸใ‚Šใ™ใ‚‹ใจใ€401 ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚จใƒฉใƒผ (`UNAUTHORIZED`) ใง็›ดๆŽฅๅฟœ็ญ”ใ—ใพใ™ใ€‚ +ใ‚‚ใ—`Authorization`ใƒ˜ใƒƒใƒ€ใƒผใŒ่ฆ‹ใคใ‹ใ‚‰ใชใ‹ใฃใŸใ‚Šใ€ๅ€คใŒ`Bearer `ใƒˆใƒผใ‚ฏใƒณใ‚’ๆŒใฃใฆใ„ใชใ‹ใฃใŸใ‚Šใ™ใ‚‹ใจใ€401 ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚จใƒฉใƒผ (`UNAUTHORIZED`) ใง็›ดๆŽฅๅฟœ็ญ”ใ—ใพใ™ใ€‚ -ใƒˆใƒผใ‚ฏใƒณใŒๅญ˜ๅœจใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚้–ขๆ•ฐใŒๅฎŸ่กŒใ•ใ‚ŒใŸๅ ดๅˆใ€ใใฎใƒˆใƒผใ‚ฏใƒณใซ`str`ใŒๅซใพใ‚Œใฆใ„ใ‚‹ใ‹็ขบ่ชใงใใพใ™ใ€‚ +ใƒˆใƒผใ‚ฏใƒณใŒๅญ˜ๅœจใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚้–ขๆ•ฐใŒๅฎŸ่กŒใ•ใ‚ŒใŸๅ ดๅˆใ€ใใฎใƒˆใƒผใ‚ฏใƒณใซ`str`ใŒๅซใพใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’็ขบไฟกใงใใพใ™ใ€‚ ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ™ใงใซ่ฉฆใ™ใ“ใจใŒใงใใพใ™: @@ -192,6 +198,6 @@ OpenAPIใจ็ตฑๅˆใ™ใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ (ใŠใ‚ˆใณ่‡ชๅ‹•AP ใพใ ใƒˆใƒผใ‚ฏใƒณใฎๆœ‰ๅŠนๆ€งใ‚’ๆคœ่จผใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใ“ใ‚Œใฏใ‚‚ใ†ๅง‹ใพใฃใฆใ„ใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ใคใพใ‚Šใ€ใŸใฃใŸ3~4่กŒใฎ่ฟฝๅŠ ใงใ€ใ™ใงใซไฝ•ใ‚‰ใ‹ใฎๅŸบ็คŽ็š„ใชใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎๅฝขใซใชใฃใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/security/get-current-user.md b/docs/ja/docs/tutorial/security/get-current-user.md index 9fc46c07c5..39b97cca52 100644 --- a/docs/ja/docs/tutorial/security/get-current-user.md +++ b/docs/ja/docs/tutorial/security/get-current-user.md @@ -1,22 +1,22 @@ -# ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใฎๅ–ๅพ— +# ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใฎๅ–ๅพ— { #get-current-user } -ไธ€ใคๅ‰ใฎ็ซ ใงใฏใ€๏ผˆไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใซๅŸบใฅใ„ใŸ๏ผ‰ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใฏใ€ *path operation้–ขๆ•ฐ* ใซ `str` ใจใ—ใฆ `token` ใ‚’ไธŽใˆใฆใ„ใพใ—ใŸ: +ไธ€ใคๅ‰ใฎ็ซ ใงใฏใ€๏ผˆไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใซๅŸบใฅใ„ใŸ๏ผ‰ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใฏใ€ *path operation ้–ขๆ•ฐ* ใซ `str` ใจใ—ใฆ `token` ใ‚’ไธŽใˆใฆใ„ใพใ—ใŸ: -{* ../../docs_src/security/tutorial001.py hl[10] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} ใ—ใ‹ใ—ใ€ใใ‚Œใฏใพใ ใใ‚“ใชใซๆœ‰็”จใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’ๅ–ๅพ—ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ -## ใƒฆใƒผใ‚ถใƒผใƒขใƒ‡ใƒซใฎไฝœๆˆ +## ใƒฆใƒผใ‚ถใƒผใƒขใƒ‡ใƒซใฎไฝœๆˆ { #create-a-user-model } ใพใšใฏใ€Pydanticใฎใƒฆใƒผใ‚ถใƒผใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ—ใพใ—ใ‚‡ใ†ใ€‚ ใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใฎใซPydanticใ‚’ไฝฟ็”จใ™ใ‚‹ใฎใจๅŒใ˜ใ‚„ใ‚Šๆ–นใงใ€Pydanticใ‚’ๅˆฅใฎใฉใ‚“ใชใจใ“ใ‚ใงใ‚‚ไฝฟใ†ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/security/tutorial002.py hl[5,12:16] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} -## ไพๅญ˜้–ขไฟ‚ `get_current_user` ใ‚’ไฝœๆˆ +## ไพๅญ˜้–ขไฟ‚ `get_current_user` ใ‚’ไฝœๆˆ { #create-a-get-current-user-dependency } ไพๅญ˜้–ขไฟ‚ `get_current_user` ใ‚’ไฝœใฃใฆใฟใพใ—ใ‚‡ใ†ใ€‚ @@ -24,21 +24,21 @@ `get_current_user` ใฏๅ‰ใซไฝœๆˆใ—ใŸ `oauth2_scheme` ใจๅŒใ˜ไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใกใพใ™ใ€‚ -ไปฅๅ‰็›ดๆŽฅ *path operation* ใฎไธญใงใ—ใฆใ„ใŸใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ๆ–ฐใ—ใ„ไพๅญ˜้–ขไฟ‚ใงใ‚ใ‚‹ `get_current_user` ใฏ `str` ใจใ—ใฆ `token` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™: +ไปฅๅ‰็›ดๆŽฅ *path operation* ใฎไธญใงใ—ใฆใ„ใŸใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€ๆ–ฐใ—ใ„ไพๅญ˜้–ขไฟ‚ใงใ‚ใ‚‹ `get_current_user` ใฏใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใงใ‚ใ‚‹ `oauth2_scheme` ใ‹ใ‚‰ `str` ใจใ—ใฆ `token` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/security/tutorial002.py hl[25] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} -## ใƒฆใƒผใ‚ถใƒผใฎๅ–ๅพ— +## ใƒฆใƒผใ‚ถใƒผใฎๅ–ๅพ— { #get-the-user } `get_current_user` ใฏไฝœๆˆใ—ใŸ๏ผˆๅฝ็‰ฉใฎ๏ผ‰ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใ‚’ไฝฟใฃใฆใ€ `str` ใจใ—ใฆใƒˆใƒผใ‚ฏใƒณใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ๅ…ˆใปใฉใฎPydanticใฎ `User` ใƒขใƒ‡ใƒซใ‚’่ฟ”ๅดใ—ใพใ™: -{* ../../docs_src/security/tutorial002.py hl[19:22,26:27] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} -## ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใฎๆณจๅ…ฅ +## ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใฎๆณจๅ…ฅ { #inject-the-current-user } ใงใ™ใฎใงใ€ `get_current_user` ใซๅฏพใ—ใฆๅŒๆง˜ใซ *path operation* ใฎไธญใง `Depends` ใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ -{* ../../docs_src/security/tutorial002.py hl[31] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} Pydanticใƒขใƒ‡ใƒซใฎ `User` ใจใ—ใฆใ€ `current_user` ใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ @@ -54,15 +54,15 @@ Pydanticใƒขใƒ‡ใƒซใฎ `User` ใจใ—ใฆใ€ `current_user` ใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ /// check | ็ขบ่ช -ไพๅญ˜้–ขไฟ‚ใ‚ทใ‚นใƒ†ใƒ ใŒใ“ใฎใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใ‚‹ใŠใ‹ใ’ใงใ€ `User` ใƒขใƒ‡ใƒซใ‚’่ฟ”ๅดใ™ใ‚‹ๅˆฅใฎไพๅญ˜้–ขไฟ‚๏ผˆๅˆฅใฎ"dependables"๏ผ‰ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ +ไพๅญ˜้–ขไฟ‚ใ‚ทใ‚นใƒ†ใƒ ใŒใ“ใฎใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใ‚‹ใŠใ‹ใ’ใงใ€ `User` ใƒขใƒ‡ใƒซใ‚’่ฟ”ๅดใ™ใ‚‹ๅˆฅใฎไพๅญ˜้–ขไฟ‚๏ผˆๅˆฅใฎใ€Œdependablesใ€๏ผ‰ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ ๅŒใ˜ใƒ‡ใƒผใ‚ฟๅž‹ใ‚’่ฟ”ๅดใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ใฏไธ€ใคใ ใ‘ใ—ใ‹ๆŒใฆใชใ„ใ€ใจใ„ใ†ๅˆถ็ด„ใŒๅ…ฅใ‚‹ใ“ใจใฏใชใ„ใฎใงใ™ใ€‚ /// -## ๅˆฅใฎใƒขใƒ‡ใƒซ +## ๅˆฅใฎใƒขใƒ‡ใƒซ { #other-models } -ใ“ใ‚Œใงใ€*path operation้–ขๆ•ฐ* ใฎไธญใง็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’็›ดๆŽฅๅ–ๅพ—ใ—ใ€`Depends` ใ‚’ไฝฟใฃใฆใ€ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใƒฌใƒ™ใƒซใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒกใ‚ซใƒ‹ใ‚บใƒ ใ‚’ๅ‡ฆ็†ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ +ใ“ใ‚Œใงใ€*path operation ้–ขๆ•ฐ* ใฎไธญใง็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’็›ดๆŽฅๅ–ๅพ—ใ—ใ€`Depends` ใ‚’ไฝฟใฃใฆใ€ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใƒฌใƒ™ใƒซใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒกใ‚ซใƒ‹ใ‚บใƒ ใ‚’ๅ‡ฆ็†ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ ใใ—ใฆใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ่ฆไปถใฎใŸใ‚ใซใฉใ‚“ใชใƒขใƒ‡ใƒซใ‚„ใƒ‡ใƒผใ‚ฟใงใ‚‚ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚๏ผˆใ“ใฎๅ ดๅˆใฏใ€ Pydanticใƒขใƒ‡ใƒซใฎ `User`๏ผ‰ @@ -76,10 +76,9 @@ Pydanticใƒขใƒ‡ใƒซใฎ `User` ใจใ—ใฆใ€ `current_user` ใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ ใ‚ใชใŸใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฟ…่ฆใชใฎใŒใฉใ‚“ใช็จฎ้กžใฎใƒขใƒ‡ใƒซใ€ใฉใ‚“ใช็จฎ้กžใฎใ‚ฏใƒฉใ‚นใ€ใฉใ‚“ใช็จฎ้กžใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใงใ‚ใฃใŸใจใ—ใฆใ‚‚ใ€ **FastAPI** ใฏไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใงใ‚ซใƒใƒผใ—ใฆใใ‚Œใพใ™ใ€‚ +## ใ‚ณใƒผใƒ‰ใ‚ตใ‚คใ‚บ { #code-size } -## ใ‚ณใƒผใƒ‰ใ‚ตใ‚คใ‚บ - -ใ“ใฎไพ‹ใฏๅ†—้•ทใซ่ฆ‹ใˆใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใŠใ‚ˆใณ *path operations* ใŒๅŒใ˜ใƒ•ใ‚กใ‚คใƒซใซๆททๅœจใ—ใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ +ใ“ใฎไพ‹ใฏๅ†—้•ทใซ่ฆ‹ใˆใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใŠใ‚ˆใณ *path operation* ใŒๅŒใ˜ใƒ•ใ‚กใ‚คใƒซใซๆททๅœจใ—ใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ ใ—ใ‹ใ—ใ€ใ“ใ“ใซ้‡่ฆใชใƒใ‚คใƒณใƒˆใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -87,20 +86,20 @@ Pydanticใƒขใƒ‡ใƒซใฎ `User` ใจใ—ใฆใ€ `current_user` ใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ ใใ—ใฆใ€ใใ‚Œใฏๅฅฝใใชใ ใ‘่ค‡้›‘ใซใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใใ‚Œใงใ‚‚ใ€ไธ€็ฎ‡ๆ‰€ใซใ€ไธ€ๅบฆใ ใ‘ๆ›ธใใฎใงใ™ใ€‚ใ™ในใฆใฎๆŸ”่ปŸๆ€งใ‚’ๅ‚™ใˆใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ๅŒใ˜ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆไฝ•ๅƒใ‚‚ใฎใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ๏ผˆ*path operations*๏ผ‰ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ๅŒใ˜ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆไฝ•ๅƒใ‚‚ใฎใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆ๏ผˆ*path operation*๏ผ‰ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ ใใ—ใฆใ€ใใ‚Œใ‚‰ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใฎใ™ในใฆ๏ผˆๅฟ…่ฆใชใ€ใฉใฎ้ƒจๅˆ†ใงใ‚‚๏ผ‰ใŒใ“ใ†ใ—ใŸไพๅญ˜้–ขไฟ‚ใ‚„ใ€ใ‚ใชใŸใŒไฝœๆˆใ™ใ‚‹ๅˆฅใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅ†ๅˆฉ็”จใ™ใ‚‹ๅˆฉ็‚นใ‚’ไบซๅ—ใงใใ‚‹ใฎใงใ™ใ€‚ -ใ•ใ‚‰ใซใ€ใ“ใ†ใ—ใŸไฝ•ๅƒใ‚‚ใฎ *path operations* ใฏใ€ใŸใฃใŸ3่กŒใง่กจ็พใงใใ‚‹ใฎใงใ™: +ใ•ใ‚‰ใซใ€ใ“ใ†ใ—ใŸไฝ•ๅƒใ‚‚ใฎ *path operation* ใฏใ€ใŸใฃใŸ3่กŒใง่กจ็พใงใใ‚‹ใฎใงใ™: -{* ../../docs_src/security/tutorial002.py hl[30:32] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} -## ใพใจใ‚ +## ใพใจใ‚ { #recap } -ใ“ใ‚Œใงใ€ *path operation้–ขๆ•ฐ* ใฎไธญใง็›ดๆŽฅ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’ๅ–ๅพ—ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ +ใ“ใ‚Œใงใ€ *path operation ้–ขๆ•ฐ* ใฎไธญใง็›ดๆŽฅ็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’ๅ–ๅพ—ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ ๆ—ขใซๅŠๅˆ†ใฎใจใ“ใ‚ใพใงๆฅใฆใ„ใพใ™ใ€‚ -ใ‚ใจใฏใ€ `username` ใจ `password` ใ‚’ๅฎŸ้š›ใซใใฎใƒฆใƒผใ‚ถใƒผใ‚„ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ้€ใ‚‹ใ€ *path operation* ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ +ใ‚ใจใฏใ€ใƒฆใƒผใ‚ถใƒผ/ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅฎŸ้š›ใซ `username` ใจ `password` ใ‚’้€ไฟกใ™ใ‚‹ใŸใ‚ใฎ *path operation* ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ ๆฌกใฏใใ‚Œใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/security/oauth2-jwt.md b/docs/ja/docs/tutorial/security/oauth2-jwt.md index 599fc7b069..186936f1ba 100644 --- a/docs/ja/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ja/docs/tutorial/security/oauth2-jwt.md @@ -1,4 +1,4 @@ -# ใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผˆใŠใ‚ˆใณใƒใƒƒใ‚ทใƒฅๅŒ–๏ผ‰ใซใ‚ˆใ‚‹OAuth2ใ€JWTใƒˆใƒผใ‚ฏใƒณใซใ‚ˆใ‚‹Bearer +# ใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผˆใŠใ‚ˆใณใƒใƒƒใ‚ทใƒฅๅŒ–๏ผ‰ใซใ‚ˆใ‚‹OAuth2ใ€JWTใƒˆใƒผใ‚ฏใƒณใซใ‚ˆใ‚‹Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } ใ“ใ‚Œใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎๆตใ‚ŒใŒๅ…จใฆใ‚ใ‹ใฃใŸใฎใงใ€JWTใƒˆใƒผใ‚ฏใƒณใจๅฎ‰ๅ…จใชใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚’ไฝฟ็”จใ—ใฆใ€ๅฎŸ้š›ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎ‰ๅ…จใซใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ @@ -6,7 +6,7 @@ ๆœฌ็ซ ใงใฏใ€ๅ‰็ซ ใฎ็ถšใใ‹ใ‚‰ๅง‹ใ‚ใฆใ€ใ‚ณใƒผใƒ‰ใ‚’ใ‚ขใƒƒใƒ—ใƒ‡ใƒผใƒˆใ—ใฆใ„ใใพใ™ใ€‚ -## JWT ใซใคใ„ใฆ +## JWT ใซใคใ„ใฆ { #about-jwt } JWTใจใฏใ€ŒJSON Web Tokensใ€ใฎ็•ฅ็งฐใงใ™ใ€‚ @@ -26,33 +26,31 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 JWT ใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟใฃใฆ้Šใ‚“ใงใฟใŸใ„ใจใ„ใ†ๆ–นใฏใ€https://jwt.io ใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใใ ใ•ใ„ใ€‚ -## `python-jose` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ +## `PyJWT` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-pyjwt } -PythonใงJWTใƒˆใƒผใ‚ฏใƒณใฎ็”Ÿๆˆใจๆคœ่จผใ‚’่กŒใ†ใŸใ‚ใซใ€`python-jose`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™๏ผš +PythonใงJWTใƒˆใƒผใ‚ฏใƒณใฎ็”Ÿๆˆใจๆคœ่จผใ‚’่กŒใ†ใŸใ‚ใซใ€`PyJWT`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +[ไปฎๆƒณ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใ€ใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ™ใƒผใƒˆใ—ใฆใ‹ใ‚‰ใ€`pyjwt`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚
```console -$ pip install python-jose[cryptography] +$ pip install pyjwt ---> 100% ```
-ใพใŸใ€Python-joseใ ใ‘ใงใฏใชใใ€ๆš—ๅทใ‚’ๆ‰ฑใ†ใŸใ‚ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’่ฟฝๅŠ ใงๅฟ…่ฆใจใ—ใพใ™ใ€‚ - -ใ“ใ“ใงใฏใ€ๆŽจๅฅจใ•ใ‚Œใฆใ„ใ‚‹ใ‚‚ใฎใ‚’ไฝฟ็”จใ—ใพใ™๏ผšpyca/cryptographyใ€‚ - -/// tip | ่ฑ†็Ÿฅ่ญ˜ +/// info | ๆƒ…ๅ ฑ -ใ“ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏไปฅๅ‰ใ€PyJWTใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ—ใŸใ€‚ +RSAใ‚„ECDSAใฎใ‚ˆใ†ใชใƒ‡ใ‚ธใ‚ฟใƒซ็ฝฒๅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ™ใ‚‹ไบˆๅฎšใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€cryptographyใƒฉใ‚คใƒ–ใƒฉใƒชใฎไพๅญ˜้–ขไฟ‚`pyjwt[crypto]`ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚ -ใ—ใ‹ใ—ใ€Python-joseใฏใ€PyJWTใฎใ™ในใฆใฎๆฉŸ่ƒฝใซๅŠ ใˆใฆใ€ๅพŒใซไป–ใฎใƒ„ใƒผใƒซใจ็ตฑๅˆใ—ใฆๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใŠใใ‚‰ใๅฟ…่ฆใจใชใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ใ„ใใคใ‹ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ไปฃใ‚ใ‚ŠใซPython-joseใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซๆ›ดๆ–ฐใ•ใ‚Œใพใ—ใŸใ€‚ +่ฉณ็ดฐใฏPyJWT Installation docsใง็ขบ่ชใงใใพใ™ใ€‚ /// -## ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ– +## ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ– { #password-hashing } ใ€Œใƒใƒƒใ‚ทใƒฅๅŒ–ใ€ใจใฏใ€ใ‚ใ‚‹ใ‚ณใƒณใƒ†ใƒณใƒ„๏ผˆใ“ใ“ใงใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผ‰ใ‚’ใ€่ฆๅ‰‡ๆ€งใฎใชใ„ใƒใ‚คใƒˆๅˆ—๏ผˆๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—๏ผ‰ใซๅค‰ๆ›ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ @@ -60,26 +58,26 @@ $ pip install python-jose[cryptography] ใ—ใ‹ใ—ใ€่ฆๅ‰‡ๆ€งใฎใชใ„ใƒใ‚คใƒˆๅˆ—ใ‹ใ‚‰ๅ…ƒใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใซๆˆปใ™ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ -### ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚’ไฝฟใ†็†็”ฑ +### ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚’ไฝฟใ†็†็”ฑ { #why-use-password-hashing } ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใŒ็›—ใพใ‚Œใฆใ‚‚ใ€ใƒฆใƒผใ‚ถใƒผใฎๅนณๆ–‡ใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฏ็›—ใพใ‚Œใšใ€ใƒใƒƒใ‚ทใƒฅๅ€คใ ใ‘ใŒ็›—ใพใ‚Œใพใ™ใ€‚ ใ—ใŸใŒใฃใฆใ€ๆณฅๆฃ’ใฏใใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅˆฅใฎใ‚ทใ‚นใƒ†ใƒ ใงไฝฟใˆใพใ›ใ‚“๏ผˆๅคšใใฎใƒฆใƒผใ‚ถใƒผใฏใฉใ“ใงใ‚‚ๅŒใ˜ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ๅฑ้™บๆ€งใŒใ‚ใ‚Šใพใ™๏ผ‰ใ€‚ -## `passlib` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ +## `pwdlib` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-pwdlib } -PassLib ใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใฎๅ„ชใ‚ŒใŸPythonใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใงใ™ใ€‚ +pwdlib ใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใฎๅ„ชใ‚ŒใŸPythonใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใงใ™ใ€‚ ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏใ€ๅคšใใฎๅฎ‰ๅ…จใชใƒใƒƒใ‚ทใƒฅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใจใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ใ‚ตใƒใƒผใƒˆใ—ใพใ™ใ€‚ -ๆŽจๅฅจใ•ใ‚Œใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏใ€ŒBcryptใ€ใงใ™ใ€‚ +ๆŽจๅฅจใ•ใ‚Œใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏใ€ŒArgon2ใ€ใงใ™ใ€‚ -ใใฎใŸใ‚ใ€Bcryptใ‚’ๆŒ‡ๅฎšใ—ใฆPassLibใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™๏ผš +[ไปฎๆƒณ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใ€ใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ™ใƒผใƒˆใ—ใฆใ‹ใ‚‰ใ€Argon2ไป˜ใใงpwdlibใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚
```console -$ pip install passlib[bcrypt] +$ pip install "pwdlib[argon2]" ---> 100% ``` @@ -88,7 +86,7 @@ $ pip install passlib[bcrypt] /// tip | ่ฑ†็Ÿฅ่ญ˜ -`passlib`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€**Django**ใ‚„**Flask**ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒ—ใƒฉใ‚ฐใ‚คใƒณใชใฉใงไฝœๆˆใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’่ชญใฟๅ–ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™ใ€‚ +`pwdlib`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€**Django**ใ‚„**Flask**ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒ—ใƒฉใ‚ฐใ‚คใƒณใชใฉใงไฝœๆˆใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’่ชญใฟๅ–ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€Djangoใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๅ†…ใฎๅŒใ˜ใƒ‡ใƒผใ‚ฟใ‚’FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใจๅ…ฑๆœ‰ใงใใ‚‹ใ ใ‘ใงใฏใชใใ€ๅŒใ˜ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚’ไฝฟ็”จใ—ใฆDjangoใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅพใ€…ใซ็งป่กŒใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ @@ -96,17 +94,17 @@ $ pip install passlib[bcrypt] /// -## ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใจๆคœ่จผ +## ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใจๆคœ่จผ { #hash-and-verify-the-passwords } -ๅฟ…่ฆใชใƒ„ใƒผใƒซใ‚’ `passlib`ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ +ๅฟ…่ฆใชใƒ„ใƒผใƒซใ‚’ `pwdlib`ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ -PassLib ใฎใ€Œcontextใ€ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใจๆคœ่จผใซไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎใงใ™ใ€‚ +ๆŽจๅฅจ่จญๅฎšใงPasswordHashใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใจๆคœ่จผใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -PassLibใฎcontextใซใฏใ€ๆคœ่จผใ ใ‘ใŒ่จฑใ•ใ‚ŒใŸ้žๆŽจๅฅจใฎๅคใ„ใƒใƒƒใ‚ทใƒฅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ๅซใ‚€ใ€ๆง˜ใ€…ใชใƒใƒƒใ‚ทใƒฅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ—ใŸๆคœ่จผๆฉŸ่ƒฝใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +pwdlibใฏbcryptใƒใƒƒใ‚ทใƒฅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚‚ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใŒใ€ใƒฌใ‚ฌใ‚ทใƒผใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใฏๅซใฟใพใ›ใ‚“ใ€‚ๅคใ„ใƒใƒƒใ‚ทใƒฅใ‚’ๆ‰ฑใ†ใซใฏใ€passlibใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒๆŽจๅฅจใ•ใ‚Œใพใ™ใ€‚ -ไพ‹ใˆใฐใ€ใ“ใฎๆฉŸ่ƒฝใ‚’ไฝฟ็”จใ—ใฆใ€ๅˆฅใฎใ‚ทใ‚นใƒ†ใƒ ๏ผˆDjangoใชใฉ๏ผ‰ใซใ‚ˆใฃใฆ็”Ÿๆˆใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’่ชญใฟๅ–ใฃใฆๆคœ่จผใ—ใ€Bcryptใชใฉใฎๅˆฅใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ—ใฆๆ–ฐใ—ใ„ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ใƒใƒƒใ‚ทใƒฅใ™ใ‚‹ใจใ„ใฃใŸใ“ใจใŒใงใใพใ™ใ€‚ +ไพ‹ใˆใฐใ€ใ“ใฎๆฉŸ่ƒฝใ‚’ไฝฟ็”จใ—ใฆใ€ๅˆฅใฎใ‚ทใ‚นใƒ†ใƒ ๏ผˆDjangoใชใฉ๏ผ‰ใซใ‚ˆใฃใฆ็”Ÿๆˆใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’่ชญใฟๅ–ใฃใฆๆคœ่จผใ—ใ€Argon2ใ‚„Bcryptใชใฉใฎๅˆฅใฎใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚’ไฝฟ็”จใ—ใฆๆ–ฐใ—ใ„ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ใƒใƒƒใ‚ทใƒฅใ™ใ‚‹ใจใ„ใฃใŸใ“ใจใŒใงใใพใ™ใ€‚ ใใ—ใฆใ€ๅŒๆ™‚ใซใใ‚Œใ‚‰ใฏใ™ในใฆใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -118,15 +116,15 @@ PassLibใฎcontextใซใฏใ€ๆคœ่จผใ ใ‘ใŒ่จฑใ•ใ‚ŒใŸ้žๆŽจๅฅจใฎๅคใ„ใƒใƒƒใ‚ท ใ•ใ‚‰ใซใ€ใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ—ใฆ่ฟ”ใ™้–ขๆ•ฐใ‚‚ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004.py hl[7,48,55:56,59:60,69:75] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} /// note | ๅ‚™่€ƒ -ๆ–ฐใ—ใ„๏ผˆๅฝใฎ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น`fake_users_db`ใ‚’็ขบ่ชใ™ใ‚‹ใจใ€ใƒใƒƒใ‚ทใƒฅๅŒ–ใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™๏ผš`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"` +ๆ–ฐใ—ใ„๏ผˆๅฝใฎ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น`fake_users_db`ใ‚’็ขบ่ชใ™ใ‚‹ใจใ€ใƒใƒƒใ‚ทใƒฅๅŒ–ใ•ใ‚ŒใŸใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™๏ผš`"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`ใ€‚ /// -## JWTใƒˆใƒผใ‚ฏใƒณใฎๅ–ใ‚Šๆ‰ฑใ„ +## JWTใƒˆใƒผใ‚ฏใƒณใฎๅ–ใ‚Šๆ‰ฑใ„ { #handle-jwt-tokens } ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸ่ค‡ๆ•ฐใฎใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ @@ -148,33 +146,33 @@ $ openssl rand -hex 32 JWTใƒˆใƒผใ‚ฏใƒณใฎ็ฝฒๅใซไฝฟ็”จใ™ใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ `"HS256"`ใ‚’ๆŒ‡ๅฎšใ—ใŸๅค‰ๆ•ฐ`ALGORITHM`ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -ใƒˆใƒผใ‚ฏใƒณใฎๆœ‰ๅŠนๆœŸ้™ใ‚’ๆŒ‡ๅฎšใ—ใŸๅค‰ๆ•ฐ`ACCESS_TOKEN_EXPIRE_MINUTES`ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +ใƒˆใƒผใ‚ฏใƒณใฎๆœ‰ๅŠนๆœŸ้™ใ‚’ๆŒ‡ๅฎšใ—ใŸๅค‰ๆ•ฐใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ ใƒฌใ‚นใƒใƒณใ‚นใฎใƒˆใƒผใ‚ฏใƒณใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใงไฝฟ็”จใ™ใ‚‹Pydanticใƒขใƒ‡ใƒซใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ ๆ–ฐใ—ใ„ใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’็”Ÿๆˆใ™ใ‚‹ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004.py hl[6,12:14,28:30,78:86] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} -## ไพๅญ˜้–ขไฟ‚ใฎๆ›ดๆ–ฐ +## ไพๅญ˜้–ขไฟ‚ใฎๆ›ดๆ–ฐ { #update-the-dependencies } `get_current_user`ใ‚’ๆ›ดๆ–ฐใ—ใฆใ€ๅ…ˆใปใฉใจๅŒใ˜ใƒˆใƒผใ‚ฏใƒณใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใŒใ€ไปŠๅ›žใฏJWTใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -ๅ—ใ‘ๅ–ใฃใŸใƒˆใƒผใ‚ฏใƒณใ‚’ๅพฉๅทใ—ใฆๆคœ่จผใ—ใ€็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ๅ—ใ‘ๅ–ใฃใŸใƒˆใƒผใ‚ฏใƒณใ‚’ใƒ‡ใ‚ณใƒผใƒ‰ใ—ใฆๆคœ่จผใ—ใ€็พๅœจใฎใƒฆใƒผใ‚ถใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ ใƒˆใƒผใ‚ฏใƒณใŒ็„กๅŠนใชๅ ดๅˆใฏใ€ใ™ใใซHTTPใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004.py hl[89:106] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} -## `/token` ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใฎๆ›ดๆ–ฐ +## `/token` *path operation* ใฎๆ›ดๆ–ฐ { #update-the-token-path-operation } ใƒˆใƒผใ‚ฏใƒณใฎๆœ‰ๅŠนๆœŸ้™ใ‚’่กจใ™`timedelta`ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -JWTใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ๅฎŸ้š›ใฎJWTใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004.py hl[115:130] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} -### JWTใฎ"subject" `sub` ใซใคใ„ใฆใฎๆŠ€่ก“็š„ใช่ฉณ็ดฐ +### JWTใฎใ€Œsubjectใ€`sub` ใซใคใ„ใฆใฎๆŠ€่ก“็š„ใช่ฉณ็ดฐ { #technical-details-about-the-jwt-subject-sub } JWTใฎไป•ๆง˜ใงใฏใ€ใƒˆใƒผใ‚ฏใƒณใฎsubjectใ‚’่กจใ™ใ‚ญใƒผ`sub`ใŒใ‚ใ‚‹ใจใ•ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -192,13 +190,13 @@ JWTใฏใ€ใƒฆใƒผใ‚ถใƒผใ‚’่ญ˜ๅˆฅใ—ใฆใ€ใใฎใƒฆใƒผใ‚ถใƒผใŒAPIไธŠใง็›ดๆŽฅๆ“ ใ—ใ‹ใ—ใชใŒใ‚‰ใ€ใใ‚Œใ‚‰ใฎใ‚จใƒณใƒ†ใ‚ฃใƒ†ใ‚ฃใฎใ„ใใคใ‹ใŒๅŒใ˜IDใ‚’ๆŒใคๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐใ€`foo`๏ผˆใƒฆใƒผใ‚ถใƒผ`foo`ใ€่ปŠ `foo`ใ€ใƒ–ใƒญใ‚ฐๆŠ•็จฟ`foo`๏ผ‰ใชใฉใงใ™ใ€‚ -IDใฎ่ก็ชใ‚’ๅ›ž้ฟใ™ใ‚‹ใŸใ‚ใซใ€ใƒฆใƒผใ‚ถใƒผใฎJWTใƒˆใƒผใ‚ฏใƒณใ‚’ไฝœๆˆใ™ใ‚‹ใจใใ€subใ‚ญใƒผใฎๅ€คใซใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไป˜ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆไพ‹ใˆใฐใ€`username:`๏ผ‰ใ€‚ใ—ใŸใŒใฃใฆใ€ใ“ใฎไพ‹ใงใฏใ€`sub`ใฎๅ€คใฏๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™๏ผš`username:johndoe` +IDใฎ่ก็ชใ‚’ๅ›ž้ฟใ™ใ‚‹ใŸใ‚ใซใ€ใƒฆใƒผใ‚ถใƒผใฎJWTใƒˆใƒผใ‚ฏใƒณใ‚’ไฝœๆˆใ™ใ‚‹ใจใใ€subใ‚ญใƒผใฎๅ€คใซใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไป˜ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆไพ‹ใˆใฐใ€`username:`๏ผ‰ใ€‚ใ—ใŸใŒใฃใฆใ€ใ“ใฎไพ‹ใงใฏใ€`sub`ใฎๅ€คใฏๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™๏ผš`username:johndoe`ใ€‚ ่ฆšใˆใฆใŠใในใ้‡่ฆใชใ“ใจใฏใ€`sub`ใ‚ญใƒผใฏใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ…จไฝ“ใงไธ€ๆ„ใฎ่ญ˜ๅˆฅๅญใ‚’ๆŒใกใ€ๆ–‡ๅญ—ๅˆ—ใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ -## ็ขบ่ช +## ็ขบ่ช { #check-it } -ใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ็งปๅ‹•ใ—ใพใ™๏ผšhttp://127.0.0.1:8000/docs +ใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ็งปๅ‹•ใ—ใพใ™๏ผšhttp://127.0.0.1:8000/docsใ€‚ ๆฌกใฎใ‚ˆใ†ใชใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใ‚คใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™๏ผš @@ -232,17 +230,17 @@ Password: `secret` -้–‹็™บ่€…ใƒ„ใƒผใƒซใ‚’้–‹ใใจใ€้€ไฟกใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใซใฏใƒˆใƒผใ‚ฏใƒณใ ใ‘ใŒๅซใพใ‚ŒใฆใŠใ‚Šใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฏใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ—ใฆใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ๆœ€ๅˆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฎใฟ้€ไฟกใ•ใ‚Œใ€ใใฎๅพŒใฏ้€ไฟกใ•ใ‚Œใชใ„ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚ +้–‹็™บ่€…ใƒ„ใƒผใƒซใ‚’้–‹ใใจใ€้€ไฟกใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟใซใฏใƒˆใƒผใ‚ฏใƒณใ ใ‘ใŒๅซใพใ‚ŒใฆใŠใ‚Šใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฏใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ—ใฆใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ๆœ€ๅˆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฎใฟ้€ไฟกใ•ใ‚Œใ€ใใฎๅพŒใฏ้€ไฟกใ•ใ‚Œใชใ„ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™๏ผš /// note | ๅ‚™่€ƒ -ใƒ˜ใƒƒใƒ€ใƒผใฎ`Authorization`ใซใฏใ€`Bearer`ใงๅง‹ใพใ‚‹ๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚ +ใƒ˜ใƒƒใƒ€ใƒผใฎ`Authorization`ใซใฏใ€`Bearer `ใงๅง‹ใพใ‚‹ๅ€คใŒใ‚ใ‚Šใพใ™ใ€‚ /// -## `scopes` ใ‚’ไฝฟใฃใŸ้ซ˜ๅบฆใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น +## `scopes` ใ‚’ไฝฟใฃใŸ้ซ˜ๅบฆใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น { #advanced-usage-with-scopes } OAuth2ใซใฏใ€ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใจใ„ใ†ๆฆ‚ๅฟตใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -252,7 +250,7 @@ OAuth2ใซใฏใ€ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใจใ„ใ†ๆฆ‚ๅฟตใŒใ‚ใ‚Šใพใ™ใ€‚ ใ“ใ‚Œใ‚‰ใฎไฝฟ็”จๆ–นๆณ•ใ‚„**FastAPI**ใธใฎ็ตฑๅˆๆ–นๆณ•ใซใคใ„ใฆใฏใ€**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใงๅพŒใปใฉ่ชฌๆ˜Žใ—ใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #recap } ใ“ใ“ใพใงใฎ่ชฌๆ˜Žใงใ€OAuth2ใ‚„JWTใชใฉใฎ่ฆๆ ผใ‚’ไฝฟใฃใŸๅฎ‰ๅ…จใช**FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -266,7 +264,7 @@ OAuth2ใซใฏใ€ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใจใ„ใ†ๆฆ‚ๅฟตใŒใ‚ใ‚Šใพใ™ใ€‚ ใใฎใŸใ‚ใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅˆใ‚ใ›ใฆ่‡ช็”ฑใซ้ธๆŠžใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -ใพใŸใ€**FastAPI**ใฏๅค–้ƒจใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็ตฑๅˆใ™ใ‚‹ใŸใ‚ใซ่ค‡้›‘ใชไป•็ต„ใฟใ‚’ๅฟ…่ฆใจใ—ใชใ„ใŸใ‚ใ€`passlib`ใ‚„`python-jose`ใฎใ‚ˆใ†ใชใ‚ˆใๆ•ดๅ‚™ใ•ใ‚Œๅบƒใไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ๅคšใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใพใŸใ€**FastAPI**ใฏๅค–้ƒจใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็ตฑๅˆใ™ใ‚‹ใŸใ‚ใซ่ค‡้›‘ใชไป•็ต„ใฟใ‚’ๅฟ…่ฆใจใ—ใชใ„ใŸใ‚ใ€`pwdlib`ใ‚„`PyJWT`ใฎใ‚ˆใ†ใชใ‚ˆใๆ•ดๅ‚™ใ•ใ‚Œๅบƒใไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ๅคšใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ๆŸ”่ปŸๆ€งใ€ๅ …็‰ขๆ€งใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๆใชใ†ใ“ใจใชใใ€ๅฏ่ƒฝใช้™ใ‚Šใƒ—ใƒญใ‚ปใ‚นใ‚’็ฐก็ด ๅŒ–ใ™ใ‚‹ใŸใ‚ใฎใƒ„ใƒผใƒซใ‚’ๆไพ›ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index f910d7e36d..c79789494c 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -1,13 +1,13 @@ -# ้™็š„ใƒ•ใ‚กใ‚คใƒซ +# ้™็š„ใƒ•ใ‚กใ‚คใƒซ { #static-files } `StaticFiles` ใ‚’ไฝฟ็”จใ—ใฆใ€ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‹ใ‚‰้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’่‡ชๅ‹•็š„ใซๆไพ›ใงใใพใ™ใ€‚ -## `StaticFiles` ใฎไฝฟ็”จ +## `StaticFiles` ใฎไฝฟ็”จ { #use-staticfiles } * `StaticFiles` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ€‚ -* `StaticFiles()` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’็”Ÿๆˆใ—ใ€็‰นๅฎšใฎใƒ‘ใ‚นใซใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ€‚ +* `StaticFiles()` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’็‰นๅฎšใฎใƒ‘ใ‚นใซใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ€‚ -{* ../../docs_src/static_files/tutorial001.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -17,15 +17,15 @@ /// -### ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใจใฏ +### ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใจใฏ { #what-is-mounting } ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใจใฏใ€็‰นๅฎšใฎใƒ‘ใ‚นใซๅฎŒๅ…จใชใ€Œ็‹ฌ็ซ‹ใ—ใŸใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ™ในใฆใฎใ‚ตใƒ–ใƒ‘ใ‚นใฎๅ‡ฆ็†ใŒใชใ•ใ‚Œใพใ™ใ€‚ ใ“ใ‚Œใฏใ€ใƒžใ‚ฆใƒณใƒˆใ•ใ‚ŒใŸใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฎŒๅ…จใซ็‹ฌ็ซ‹ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€`APIRouter` ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ใƒกใ‚คใƒณใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎOpenAPIใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏใ€ใƒžใ‚ฆใƒณใƒˆใ•ใ‚ŒใŸใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ†…ๅฎนใชใฉใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚ -ใ“ใ‚Œใซใคใ„ใฆ่ฉณใ—ใใฏใ€**้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰** ใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ +ใ“ใ‚Œใซใคใ„ใฆ่ฉณใ—ใใฏใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../advanced/index.md){.internal-link target=_blank} ใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ -## ่ฉณ็ดฐ +## ่ฉณ็ดฐ { #details } ๆœ€ๅˆใฎ `"/static"` ใฏใ€ใ“ใฎใ€Œใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ€ใŒใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ•ใ‚Œใ‚‹ใ‚ตใƒ–ใƒ‘ใ‚นใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ใ—ใŸใŒใฃใฆใ€`"/static"` ใ‹ใ‚‰ๅง‹ใพใ‚‹ใƒ‘ใ‚นใฏใ™ในใฆใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใพใ™ใ€‚ @@ -33,8 +33,8 @@ `name="static"` ใฏใ€**FastAPI** ใŒๅ†…้ƒจใงไฝฟ็”จใงใใ‚‹ๅๅ‰ใ‚’ไป˜ใ‘ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ™ในใฆใ€Œ`้™็š„`ใ€ใจใฏ็•ฐใชใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใ€็‹ฌ่‡ชใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‹ใƒผใ‚บใจ่ฉณ็ดฐใซๅˆใ‚ใ›ใฆ่ชฟๆ•ดใ—ใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ™ในใฆใ€Œ`static`ใ€ใจใฏ็•ฐใชใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใ€็‹ฌ่‡ชใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‹ใƒผใ‚บใจ่ฉณ็ดฐใซๅˆใ‚ใ›ใฆ่ชฟๆ•ดใ—ใพใ™ใ€‚ -## ใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑ +## ใ‚ˆใ‚Š่ฉณใ—ใ„ๆƒ…ๅ ฑ { #more-info } ่ฉณ็ดฐใจใ‚ชใƒ—ใ‚ทใƒงใƒณใซใคใ„ใฆใฏใ€Starletteใฎ้™็š„ใƒ•ใ‚กใ‚คใƒซใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index 4e8ad4f7cc..0ec6250f31 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -1,12 +1,24 @@ -# ใƒ†ใ‚นใƒˆ +# ใƒ†ใ‚นใƒˆ { #testing } Starlette ใฎใŠใ‹ใ’ใงใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ†ใ‚นใƒˆใฏ็ฐกๅ˜ใงๆฅฝใ—ใ„ใ‚‚ใฎใซใชใฃใฆใ„ใพใ™ใ€‚ -HTTPX ใŒใƒ™ใƒผใ‚นใชใฎใงใ€้žๅธธใซไฝฟใ„ใ‚„ใ™ใ็›ดๆ„Ÿ็š„ใงใ™ใ€‚ +HTTPX ใŒใƒ™ใƒผใ‚นใงใ€ใ•ใ‚‰ใซใใฎ่จญ่จˆใฏ Requests ใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใจใฆใ‚‚้ฆดๆŸ“ใฟใŒใ‚ใ‚Š็›ดๆ„Ÿ็š„ใงใ™ใ€‚ ใ“ใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€**FastAPI** ใจๅ…ฑใซ pytest ใ‚’็›ดๆŽฅๅˆฉ็”จใงใใพใ™ใ€‚ -## `TestClient` ใ‚’ไฝฟ็”จ +## `TestClient` ใ‚’ไฝฟ็”จ { #using-testclient } + +/// info | ๆƒ…ๅ ฑ + +`TestClient` ใ‚’ไฝฟ็”จใ™ใ‚‹ใซใฏใ€ใพใš `httpx` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ + +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ไพ‹ใˆใฐไปฅไธ‹ใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install httpx +``` + +/// `TestClient` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ @@ -16,9 +28,9 @@ `httpx` ใจๅŒใ˜ๆง˜ใซ `TestClient` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ -ใƒใ‚งใƒƒใ‚ฏใ—ใŸใ„ Python ใฎๆจ™ๆบ–็š„ใชๅผใจๅ…ฑใซใ€ใ‚ทใƒณใƒ—ใƒซใซ `assert` ๆ–‡ใ‚’่จ˜่ฟฐใ—ใพใ™ใ€‚ +ใƒใ‚งใƒƒใ‚ฏใ—ใŸใ„ Python ใฎๆจ™ๆบ–็š„ใชๅผใจๅ…ฑใซใ€ใ‚ทใƒณใƒ—ใƒซใซ `assert` ๆ–‡ใ‚’่จ˜่ฟฐใ—ใพใ™ (ใ“ใ‚Œใ‚‚ `pytest` ใฎๆจ™ๆบ–ใงใ™)ใ€‚ -{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -44,48 +56,81 @@ FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ้€ไฟกใจใฏๅˆฅใซใ€ใƒ† /// -## ใƒ†ใ‚นใƒˆใฎๅˆ†้›ข +## ใƒ†ใ‚นใƒˆใฎๅˆ†้›ข { #separating-tests } ๅฎŸ้š›ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€ใŠใใ‚‰ใใƒ†ใ‚นใƒˆใ‚’ๅˆฅใฎใƒ•ใ‚กใ‚คใƒซใซไฟๅญ˜ใ—ใพใ™ใ€‚ ใพใŸใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€่ค‡ๆ•ฐใฎใƒ•ใ‚กใ‚คใƒซ/ใƒขใ‚ธใƒฅใƒผใƒซใชใฉใงๆง‹ๆˆใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -### **FastAPI** ใ‚ขใƒ—ใƒชใƒ•ใ‚กใ‚คใƒซ +### **FastAPI** ใ‚ขใƒ—ใƒชใƒ•ใ‚กใ‚คใƒซ { #fastapi-app-file } + +[Bigger Applications](bigger-applications.md){.internal-link target=_blank} ใง่ชฌๆ˜Žใ•ใ‚Œใฆใ„ใ‚‹ใ€ๆฌกใฎใ‚ˆใ†ใชใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใŒใ‚ใ‚‹ใจใ—ใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ main.py +``` + +ใƒ•ใ‚กใ‚คใƒซ `main.py` ใซ **FastAPI** ใ‚ขใƒ—ใƒชใŒใ‚ใ‚Šใพใ™: + + +{* ../../docs_src/app_testing/app_a_py39/main.py *} + +### ใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ { #testing-file } + +ๆฌกใซใ€ใƒ†ใ‚นใƒˆใ‚’ๅซใ‚€ `test_main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’็”จๆ„ใงใใพใ™ใ€‚ใ“ใ‚ŒใฏๅŒใ˜ Python ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ (`__init__.py` ใƒ•ใ‚กใ‚คใƒซใŒใ‚ใ‚‹ๅŒใ˜ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช) ใซ็ฝฎใ‘ใพใ™: -**FastAPI** ใ‚ขใƒ—ใƒชใซ `main.py` ใƒ•ใ‚กใ‚คใƒซใŒใ‚ใ‚‹ใจใ—ใพใ™: +``` hl_lines="5" +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` -{* ../../docs_src/app_testing/main.py *} +ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธๅ†…ใซใ‚ใ‚‹ใŸใ‚ใ€็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ‚’ไฝฟใฃใฆ `main` ใƒขใ‚ธใƒฅใƒผใƒซ (`main.py`) ใ‹ใ‚‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ `app` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™: -### ใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ +{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} -ๆฌกใซใ€ใƒ†ใ‚นใƒˆใ‚’ๅซใ‚€ `test_main.py` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใ€`main` ใƒขใ‚ธใƒฅใƒผใƒซ (`main.py`) ใ‹ใ‚‰ `app` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/app_testing/test_main.py *} +...ใใ—ใฆใ€ใ“ใ‚ŒใพใงใจๅŒใ˜ใ‚ˆใ†ใซใƒ†ใ‚นใƒˆใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ‘ใพใ™ใ€‚ -## ใƒ†ใ‚นใƒˆ: ไพ‹ใฎๆ‹กๅผต +## ใƒ†ใ‚นใƒˆ: ไพ‹ใฎๆ‹กๅผต { #testing-extended-example } ๆฌกใซใ€ใ“ใฎไพ‹ใ‚’ๆ‹กๅผตใ—ใ€่ฉณ็ดฐใ‚’่ฟฝๅŠ ใ—ใฆใ€ใ•ใพใ–ใพใชใƒ‘ใƒผใƒ„ใ‚’ใƒ†ใ‚นใƒˆใ™ใ‚‹ๆ–นๆณ•ใ‚’็ขบ่ชใ—ใพใ—ใ‚‡ใ†ใ€‚ +### ๆ‹กๅผต็‰ˆ **FastAPI** ใ‚ขใƒ—ใƒชใƒ•ใ‚กใ‚คใƒซ { #extended-fastapi-app-file } + +ๅ…ˆใปใฉใจๅŒใ˜ใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใง็ถšใ‘ใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` -### ๆ‹กๅผต็‰ˆ **FastAPI** ใ‚ขใƒ—ใƒชใƒ•ใ‚กใ‚คใƒซ +ใ“ใ“ใงใ€**FastAPI** ใ‚ขใƒ—ใƒชใŒใ‚ใ‚‹ `main.py` ใƒ•ใ‚กใ‚คใƒซใซใฏใ€ไป–ใฎ path operation ใŒใ‚ใ‚Šใพใ™ใ€‚ -**FastAPI** ใ‚ขใƒ—ใƒชใซ `main_b.py` ใƒ•ใ‚กใ‚คใƒซใŒใ‚ใ‚‹ใจใ—ใพใ™ใ€‚ +ใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ `GET` ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใฎใƒ•ใ‚กใ‚คใƒซใซใฏใ€ใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ `GET` ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ„ใใคใ‹ใฎใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ `POST` ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -ใพใŸใ€ใ„ใใคใ‹ใฎใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ `POST` ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ไธกๆ–นใฎ *path operation* ใซใฏ `X-Token` ใƒ˜ใƒƒใƒ€ใƒผใŒๅฟ…่ฆใงใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎ *path operation* ใซใฏ `X-Token` ใƒ˜ใƒƒใƒ€ใƒผใŒๅฟ…่ฆใงใ™ใ€‚ +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} -{* ../../docs_src/app_testing/app_b_py310/main.py *} +### ๆ‹กๅผต็‰ˆใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ { #extended-testing-file } -### ๆ‹กๅผต็‰ˆใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ +ๆฌกใซใ€ๆ‹กๅผต็‰ˆใฎใƒ†ใ‚นใƒˆใง `test_main.py` ใ‚’ๆ›ดๆ–ฐใงใใพใ™: -ๆฌกใซใ€ๅ…ˆ็จ‹ใฎใ‚‚ใฎใซๆ‹กๅผต็‰ˆใฎใƒ†ใ‚นใƒˆใ‚’ๅŠ ใˆใŸใ€`test_main_b.py` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -{* ../../docs_src/app_testing/app_b/test_main.py *} -ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๆƒ…ๅ ฑใ‚’ๆธกใ›ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅฟ…่ฆใงใ€ใใฎๆ–นๆณ•ใŒใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ„ใคใงใ‚‚ใ€`httpx` ใงใฎๅฎŸ็พๆ–นๆณ•ใ‚’ๆคœ็ดข (Google) ใงใใพใ™ใ€‚ +ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๆƒ…ๅ ฑใ‚’ๆธกใ›ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅฟ…่ฆใงใ€ใใฎๆ–นๆณ•ใŒใ‚ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ„ใคใงใ‚‚ใ€`httpx` ใงใฎๅฎŸ็พๆ–นๆณ•ใ€ใ‚ใ‚‹ใ„ใฏ HTTPX ใฎ่จญ่จˆใŒ Requests ใฎ่จญ่จˆใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใ‚‹ใŸใ‚ `requests` ใงใฎๅฎŸ็พๆ–นๆณ•ใ‚’ๆคœ็ดข (Google) ใงใใพใ™ใ€‚ ใƒ†ใ‚นใƒˆใงใ‚‚ๅŒใ˜ใ“ใจใ‚’่กŒใ„ใพใ™ใ€‚ @@ -107,9 +152,11 @@ FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ้€ไฟกใจใฏๅˆฅใซใ€ใƒ† /// -## ๅฎŸ่กŒ +## ๅฎŸ่กŒ { #run-it } + +ใใฎๅพŒใ€`pytest` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ -ๅพŒใฏใ€`pytest` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใ ใ‘ใงใ™: +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใฆใ‹ใ‚‰ใ€ไพ‹ใˆใฐไปฅไธ‹ใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„:
@@ -121,7 +168,7 @@ $ pip install pytest
-ใƒ•ใ‚กใ‚คใƒซใ‚’ๆคœ็Ÿฅใ—ใ€่‡ชๅ‹•ใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ—ใ€็ตๆžœใฎใƒฌใƒใƒผใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ +ใƒ•ใ‚กใ‚คใƒซใจใƒ†ใ‚นใƒˆใ‚’่‡ชๅ‹•็š„ใซๆคœๅ‡บใ—ใ€ๅฎŸ่กŒใ—ใฆใ€็ตๆžœใฎใƒฌใƒใƒผใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ ไปฅไธ‹ใงใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ—ใพใ™: diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 791cf64a84..6723230632 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -1,10 +1,10 @@ -# ไปฎๆƒณ็’ฐๅขƒ +# ไปฎๆƒณ็’ฐๅขƒ { #virtual-environments } Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใงใฏใ€**ไปฎๆƒณ็’ฐๅขƒ**๏ผˆใพใŸใฏ้กžไผผใฎไป•็ต„ใฟ๏ผ‰ใ‚’ไฝฟ็”จใ—ใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ”ใจใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ๅˆ†้›ขใ™ใ‚‹ในใใงใ—ใ‚‡ใ†ใ€‚ /// info | ๆƒ…ๅ ฑ -ใ‚‚ใ—ใ€ไปฎๆƒณ็’ฐๅขƒใฎๆฆ‚่ฆใ‚„ไฝœๆˆๆ–นๆณ•ใ€ไฝฟ็”จๆ–นๆณ•ใซใคใ„ใฆๆ—ขใซใ”ๅญ˜็Ÿฅใชใ‚‰ใ€ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ‚นใ‚ญใƒƒใƒ—ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚๐Ÿค“ +ใ‚‚ใ—ใ€ไปฎๆƒณ็’ฐๅขƒใฎๆฆ‚่ฆใ‚„ไฝœๆˆๆ–นๆณ•ใ€ไฝฟ็”จๆ–นๆณ•ใซใคใ„ใฆๆ—ขใซใ”ๅญ˜็Ÿฅใชใ‚‰ใ€ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ใ‚นใ‚ญใƒƒใƒ—ใ—ใŸๆ–นใŒใ‚ˆใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿค“ /// @@ -25,7 +25,7 @@ Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใงใฏใ€**ไปฎๆƒณ็’ฐๅขƒ**๏ผˆใพใŸใฏ้กžไผผใฎ /// -## ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆˆ +## ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆˆ { #create-a-project } ใพใšใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ็”จใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ @@ -48,9 +48,9 @@ $ cd awesome-project
-## ไปฎๆƒณ็’ฐๅขƒใฎไฝœๆˆ +## ไปฎๆƒณ็’ฐๅขƒใฎไฝœๆˆ { #create-a-virtual-environment } -Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฎ**ๅˆใ‚ใฆใฎ**ไฝœๆฅญใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆๅ†…**ใซไปฎๆƒณ็’ฐๅขƒใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ +Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฎ**ๅˆใ‚ใฆใฎ**ไฝœๆฅญใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆๅ†…**ใซไปฎๆƒณ็’ฐๅขƒใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -72,10 +72,10 @@ $ python -m venv .venv /// details | ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใฎๆ„ๅ‘ณ -- `python` : `python` ใจใ„ใ†ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ -- `-m` : ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚นใ‚ฏใƒชใƒ—ใƒˆใจใ—ใฆๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ใฉใฎใƒขใ‚ธใƒฅใƒผใƒซใ‚’ๅ‘ผใณๅ‡บใ™ใฎใ‹ใ€ใ“ใฎๆฌกใซๆŒ‡ๅฎšใ—ใพใ™ -- `venv` : ้€šๅธธPythonใซไป˜้šใ—ใฆใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใ‚‹ `venv`ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ไฝฟ็”จใ—ใพใ™ -- `.venv` : ไปฎๆƒณ็’ฐๅขƒใ‚’`.venv`ใจใ„ใ†ๆ–ฐใ—ใ„ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซไฝœๆˆใ—ใพใ™ +* `python`: `python` ใจใ„ใ†ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ +* `-m`: ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚นใ‚ฏใƒชใƒ—ใƒˆใจใ—ใฆๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ใฉใฎใƒขใ‚ธใƒฅใƒผใƒซใ‚’ๅ‘ผใณๅ‡บใ™ใฎใ‹ใ€ใ“ใฎๆฌกใซๆŒ‡ๅฎšใ—ใพใ™ +* `venv`: ้€šๅธธPythonใซไป˜้šใ—ใฆใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใ‚‹ `venv`ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ไฝฟ็”จใ—ใพใ™ +* `.venv`: ไปฎๆƒณ็’ฐๅขƒใ‚’`.venv`ใจใ„ใ†ๆ–ฐใ—ใ„ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซไฝœๆˆใ—ใพใ™ /// @@ -111,13 +111,13 @@ $ uv venv /// -## ไปฎๆƒณ็’ฐๅขƒใฎๆœ‰ๅŠนๅŒ– +## ไปฎๆƒณ็’ฐๅขƒใฎๆœ‰ๅŠนๅŒ– { #activate-the-virtual-environment } ๅฎŸ่กŒใ•ใ‚Œใ‚‹Pythonใ‚ณใƒžใƒณใƒ‰ใ‚„ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใ‚‹ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒๆ–ฐใ—ใไฝœๆˆใ—ใŸไปฎๆƒณ็’ฐๅขƒใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใ€ใใฎไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใพใ—ใ‚‡ใ†ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใง**ๆ–ฐใ—ใ„ใ‚ฟใƒผใƒŸใƒŠใƒซใ‚ปใƒƒใ‚ทใƒงใƒณ**ใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ๆฏŽๅ›ž**ๆœ‰ๅŠนๅŒ–ใŒๅฟ…่ฆใงใ™ใ€‚ +ใใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใง**ๆ–ฐใ—ใ„ใ‚ฟใƒผใƒŸใƒŠใƒซใ‚ปใƒƒใ‚ทใƒงใƒณ**ใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ๆฏŽๅ›ž**ๆœ‰ๅŠนๅŒ–ใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -161,13 +161,13 @@ $ source .venv/Scripts/activate /// tip | ่ฑ†็Ÿฅ่ญ˜ -**ๆ–ฐใ—ใ„ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ**ใ‚’ไปฎๆƒณ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจใใซใฏใ€ๅ†ๅบฆ**ๆœ‰ๅŠนๅŒ–**ใ—ใฆใใ ใ•ใ„ใ€‚ +**ๆ–ฐใ—ใ„ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ**ใ‚’ไปฎๆƒณ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใŸใณใซใ€็’ฐๅขƒใ‚’ใ‚‚ใ†ไธ€ๅบฆ**ๆœ‰ๅŠนๅŒ–**ใ—ใฆใใ ใ•ใ„ใ€‚ ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€ใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸ**ใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผˆCLI๏ผ‰ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใซใ€ไปฎๆƒณ็’ฐๅขƒๅ†…ใฎใ‚‚ใฎใŒ็ขบๅฎŸใซไฝฟใ‚ใ‚Œใ€ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ๅˆฅใฎใ‚‚ใฎ๏ผˆใŠใใ‚‰ใๅฟ…่ฆใชใ‚‚ใฎใจใฏ็•ฐใชใ‚‹ใƒใƒผใ‚ธใƒงใƒณ๏ผ‰ใ‚’่ชคใฃใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’้˜ฒใŽใพใ™ใ€‚ /// -## ไปฎๆƒณ็’ฐๅขƒใŒๆœ‰ๅŠนใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ +## ไปฎๆƒณ็’ฐๅขƒใŒๆœ‰ๅŠนใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ { #check-the-virtual-environment-is-active } ไปฎๆƒณ็’ฐๅขƒใŒๆœ‰ๅŠนใงใ‚ใ‚‹๏ผˆๅ‰ใฎใ‚ณใƒžใƒณใƒ‰ใŒๆญฃๅธธใซๆฉŸ่ƒฝใ—ใŸ๏ผ‰ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ @@ -197,7 +197,7 @@ $ which python
-``` console +```console $ Get-Command python C:\Users\user\code\awesome-project\.venv\Scripts\python @@ -209,7 +209,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -## `pip` ใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ™ใ‚‹ +## `pip` ใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ™ใ‚‹ { #upgrade-pip } /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -239,7 +239,27 @@ $ python -m pip install --upgrade pip
-## `.gitignore` ใ‚’่ฟฝๅŠ ใ™ใ‚‹ +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใจใใฉใใ€pip ใ‚’ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใ‚ˆใ†ใจใ™ใ‚‹ใจ **`No module named pip`** ใ‚จใƒฉใƒผใŒ่กจ็คบใ•ใ‚Œใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใฎๅ ดๅˆใฏใ€ไปฅไธ‹ใฎใ‚ณใƒžใƒณใƒ‰ใง pip ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใฆใใ ใ•ใ„: + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใฏใ€pip ใŒใพใ ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใชใ‘ใ‚Œใฐ pip ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใ€ใพใŸใ€ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใ‚‹ pip ใฎใƒใƒผใ‚ธใƒงใƒณใŒ `ensurepip` ใงๅˆฉ็”จๅฏ่ƒฝใชใ‚‚ใฎไปฅไธŠใซๆ–ฐใ—ใ„ใ“ใจใ‚‚ไฟ่จผใ—ใพใ™ใ€‚ + +/// + +## `.gitignore` ใ‚’่ฟฝๅŠ ใ™ใ‚‹ { #add-gitignore } **Git**ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆ๏ผˆไฝฟ็”จใ™ใ‚‹ในใใงใ—ใ‚‡ใ†๏ผ‰ใ€ `.gitignore` ใƒ•ใ‚กใ‚คใƒซใ‚’่ฟฝๅŠ ใ—ใฆใ€ `.venv` ๅ†…ใฎใ‚ใ‚‰ใ‚†ใ‚‹ใƒ•ใ‚กใ‚คใƒซใ‚’Gitใฎ็ฎก็†ๅฏพ่ฑกใ‹ใ‚‰้™คๅค–ใ—ใพใ™ใ€‚ @@ -265,9 +285,9 @@ $ echo "*" > .venv/.gitignore /// details | ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใฎๆ„ๅ‘ณ -- `echo "*"` : ใ‚ฟใƒผใƒŸใƒŠใƒซใซ `*` ใจใ„ใ†ใƒ†ใ‚ญใ‚นใƒˆใ‚’ใ€Œ่กจ็คบใ€ใ—ใ‚ˆใ†ใจใ—ใพใ™ใ€‚๏ผˆๆฌกใฎ้ƒจๅˆ†ใซใ‚ˆใฃใฆใใฎๅ‹•ไฝœใŒๅฐ‘ใ—ๅค‰ใ‚ใ‚Šใพใ™๏ผ‰ -- `>` : `>` ใฎๅทฆๅดใฎใ‚ณใƒžใƒณใƒ‰ใŒใ‚ฟใƒผใƒŸใƒŠใƒซใซ่กจ็คบใ—ใ‚ˆใ†ใจใ™ใ‚‹ๅ†…ๅฎนใ‚’ใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใซใฏ่กจ็คบใ›ใšใ€ `>` ใฎๅณๅดใฎใƒ•ใ‚กใ‚คใƒซใซๆ›ธใ่พผใฟใพใ™ใ€‚ -- `.gitignore` : `*` ใ‚’ๆ›ธใ่พผใ‚€ใƒ•ใ‚กใ‚คใƒซๅใ€‚ +* `echo "*"`: ใ‚ฟใƒผใƒŸใƒŠใƒซใซ `*` ใจใ„ใ†ใƒ†ใ‚ญใ‚นใƒˆใ‚’ใ€Œ่กจ็คบใ€ใ—ใ‚ˆใ†ใจใ—ใพใ™ใ€‚๏ผˆๆฌกใฎ้ƒจๅˆ†ใซใ‚ˆใฃใฆใใฎๅ‹•ไฝœใŒๅฐ‘ใ—ๅค‰ใ‚ใ‚Šใพใ™๏ผ‰ +* `>`: `>` ใฎๅทฆๅดใฎใ‚ณใƒžใƒณใƒ‰ใŒใ‚ฟใƒผใƒŸใƒŠใƒซใซ่กจ็คบใ—ใ‚ˆใ†ใจใ™ใ‚‹ๅ†…ๅฎนใ‚’ใ€ใ‚ฟใƒผใƒŸใƒŠใƒซใซใฏ่กจ็คบใ›ใšใ€ `>` ใฎๅณๅดใฎใƒ•ใ‚กใ‚คใƒซใซๆ›ธใ่พผใฟใพใ™ใ€‚ +* `.gitignore`: `*` ใ‚’ๆ›ธใ่พผใ‚€ใƒ•ใ‚กใ‚คใƒซๅใ€‚ ใ“ใ“ใงใ€GitใซใŠใ‘ใ‚‹ `*` ใฏใ€Œใ™ในใฆใ€ใ‚’ๆ„ๅ‘ณใ™ใ‚‹ใฎใงใ€ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใซใ‚ˆใฃใฆ `.venv` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชๅ†…ใฎใ™ในใฆใŒGitใซ็„ก่ฆ–ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ @@ -279,7 +299,7 @@ $ echo "*" > .venv/.gitignore /// -## ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ +## ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-packages } ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใŸๅพŒใ€ใใฎไธญใงใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ @@ -291,7 +311,7 @@ $ echo "*" > .venv/.gitignore /// -### ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็›ดๆŽฅใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ +### ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็›ดๆŽฅใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ { #install-packages-directly } ๆ€ฅใ„ใงใ„ใฆใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ่ฆไปถใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟใ„ใŸใใชใ„ๅ ดๅˆใ€ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’็›ดๆŽฅใ‚คใƒณใ‚นใƒˆใƒผใƒซใงใใพใ™ใ€‚ @@ -330,7 +350,7 @@ $ uv pip install "fastapi[standard]" //// -### `requirements.txt` ใ‹ใ‚‰ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ +### `requirements.txt` ใ‹ใ‚‰ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ { #install-from-requirements-txt } ใ‚‚ใ— `requirements.txt` ใŒใ‚ใ‚‹ใชใ‚‰ใ€ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใซไฝฟ็”จใงใใพใ™ใ€‚ @@ -373,7 +393,7 @@ pydantic==2.8.0 /// -## ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใ™ใ‚‹ +## ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใ™ใ‚‹ { #run-your-program } ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนๅŒ–ใ—ใŸๅพŒใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅฎŸ่กŒใงใใพใ™ใ€‚ใ“ใฎ้š›ใ€ไปฎๆƒณ็’ฐๅขƒๅ†…ใฎPythonใจใ€ใใ“ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ @@ -387,7 +407,7 @@ Hello World -## ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎ่จญๅฎš +## ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎ่จญๅฎš { #configure-your-editor } ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฏใŠใใ‚‰ใใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚’ไฝฟ็”จใ™ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใ‚ณใƒผใƒ‰่ฃœๅฎŒใ‚„ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผใฎ่กจ็คบใŒใงใใ‚‹ใ‚ˆใ†ใซใ€ไฝœๆˆใ—ใŸไปฎๆƒณ็’ฐๅขƒใ‚’ใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ‚‚ไฝฟใˆใ‚‹ใ‚ˆใ†่จญๅฎšใ—ใฆใใ ใ•ใ„ใ€‚๏ผˆๅคšใใฎๅ ดๅˆใ€่‡ชๅ‹•ๆคœๅ‡บใ•ใ‚Œใพใ™๏ผ‰ @@ -402,7 +422,7 @@ Hello World /// -## ไปฎๆƒณ็’ฐๅขƒใฎ็„กๅŠนๅŒ– +## ไปฎๆƒณ็’ฐๅขƒใฎ็„กๅŠนๅŒ– { #deactivate-the-virtual-environment } ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใŒ็ต‚ไบ†ใ—ใŸใ‚‰ใ€ใใฎไปฎๆƒณ็’ฐๅขƒใ‚’**็„กๅŠนๅŒ–**ใงใใพใ™ใ€‚ @@ -416,9 +436,11 @@ $ deactivate ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ `python` ใ‚ณใƒžใƒณใƒ‰ใ‚’ๅฎŸ่กŒใ—ใฆใ‚‚ใ€ใใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ็”จ๏ผˆใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚ŒใŸ๏ผ‰ไปฎๆƒณ็’ฐๅขƒใ‹ใ‚‰ `python` ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‘ผใณๅ‡บใใ†ใจใฏใ—ใชใใชใ‚Šใพใ™ใ€‚ -## ไฝœๆฅญๆบ–ๅ‚™ๅฎŒไบ† +## ไฝœๆฅญๆบ–ๅ‚™ๅฎŒไบ† { #ready-to-work } + +ใ“ใ‚Œใงใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใ‚’ๅง‹ใ‚ใ‚‹ๆบ–ๅ‚™ใŒๆ•ดใ„ใพใ—ใŸใ€‚ + -ใ“ใ“ใพใงใงใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆฅญใ‚’ๅง‹ใ‚ใ‚‹ๆบ–ๅ‚™ใŒๆ•ดใ„ใพใ—ใŸใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -428,9 +450,9 @@ $ deactivate /// -## ใชใœไปฎๆƒณ็’ฐๅขƒ๏ผŸ +## ใชใœไปฎๆƒณ็’ฐๅขƒ๏ผŸ { #why-virtual-environments } -FastAPIใ‚’ไฝฟใฃใŸไฝœๆฅญใ‚’ใ™ใ‚‹ใซใฏใ€ [Python](https://www.python.org/) ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใŒๅฟ…่ฆใงใ™ใ€‚ +FastAPIใ‚’ไฝฟใฃใŸไฝœๆฅญใ‚’ใ™ใ‚‹ใซใฏใ€Python ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใŒๅฟ…่ฆใงใ™ใ€‚ ใใ‚Œใ‹ใ‚‰ใ€FastAPIใ‚„ใ€ไฝฟ็”จใ—ใŸใ„ใใฎไป–ใฎ**ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ**ใ‚’**ใ‚คใƒณใ‚นใƒˆใƒผใƒซ**ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -438,7 +460,7 @@ FastAPIใ‚’ไฝฟใฃใŸไฝœๆฅญใ‚’ใ™ใ‚‹ใซใฏใ€ [Python](https://www.python.org/) ใŸใ ใ—ใ€`pip` ใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใจใ€ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏ**ใ‚ฐใƒญใƒผใƒใƒซใชPython็’ฐๅขƒ**๏ผˆOSๅ…จไฝ“ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚ŒใŸPython็’ฐๅขƒ๏ผ‰ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใพใ™ใ€‚ -### ๅ•้กŒ็‚น +### ๅ•้กŒ็‚น { #the-problem } ใงใฏใ€ใ‚ฐใƒญใƒผใƒใƒซPython็’ฐๅขƒใซใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใ“ใจใฎๅ•้กŒ็‚นใฏไฝ•ใงใ—ใ‚‡ใ†ใ‹๏ผŸ @@ -521,7 +543,7 @@ Pythonใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใงใฏใ€**ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ**ใง**ไบ’ๆ›ๆ€งใ‚’ ใพใŸใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹OS๏ผˆLinuxใ€Windowsใ€macOS ใชใฉ๏ผ‰ใซใ‚ˆใฃใฆใฏใ€PythonใŒใ™ใงใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎๅ ดๅˆใ€็‰นๅฎšใฎใƒใƒผใ‚ธใƒงใƒณใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒ**OSใฎๅ‹•ไฝœใซๅฟ…่ฆใงใ‚ใ‚‹**ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒใซใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจใ€OSใซไป˜ๅฑžใ™ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’**ๅฃŠใ—ใฆใ—ใพใ†**ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -## ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๅ…ˆ +## ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๅ…ˆ { #where-are-packages-installed } Pythonใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸใจใใ€ใƒ•ใ‚กใ‚คใƒซใ‚’ๅซใ‚“ใ ใ„ใใคใ‹ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ @@ -539,7 +561,7 @@ $ pip install "fastapi[standard]" -FastAPIใฎใ‚ณใƒผใƒ‰ใ‚’ๅซใ‚€ๅœง็ธฎใƒ•ใ‚กใ‚คใƒซใŒใ€้€šๅธธใฏ [PyPI](https://pypi.org/project/fastapi/) ใ‹ใ‚‰ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚ +FastAPIใฎใ‚ณใƒผใƒ‰ใ‚’ๅซใ‚€ๅœง็ธฎใƒ•ใ‚กใ‚คใƒซใŒใ€้€šๅธธใฏ PyPI ใ‹ใ‚‰ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚ ใพใŸใ€FastAPIใŒไพๅญ˜ใ™ใ‚‹ไป–ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚‚**ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰**ใ•ใ‚Œใพใ™ใ€‚ @@ -547,7 +569,7 @@ FastAPIใฎใ‚ณใƒผใƒ‰ใ‚’ๅซใ‚€ๅœง็ธฎใƒ•ใ‚กใ‚คใƒซใŒใ€้€šๅธธใฏ [PyPI](https://pyp ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€ใ“ใ‚Œใ‚‰ใฎใƒ•ใ‚กใ‚คใƒซใฏPythonใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๆ™‚ใซไฝœๆˆใ•ใ‚Œใ‚‹ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ€ใคใพใ‚Š**ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒ**ใซ้…็ฝฎใ•ใ‚Œใพใ™ใ€‚ -## ไปฎๆƒณ็’ฐๅขƒใจใฏ +## ไปฎๆƒณ็’ฐๅขƒใจใฏ { #what-are-virtual-environments } ใ™ในใฆใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒใซ้…็ฝฎใ™ใ‚‹ใ“ใจใซใ‚ˆใฃใฆ็”Ÿใ˜ใ‚‹ๅ•้กŒใฎ่งฃๆฑบ็ญ–ใฏใ€ไฝœๆฅญใ™ใ‚‹**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ”ใจใฎไปฎๆƒณ็’ฐๅขƒ**ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ™ใ€‚ @@ -572,7 +594,7 @@ flowchart TB stone-project ~~~ azkaban-project ``` -## ไปฎๆƒณ็’ฐๅขƒใฎๆœ‰ๅŠนๅŒ–ใจใฏ +## ไปฎๆƒณ็’ฐๅขƒใฎๆœ‰ๅŠนๅŒ–ใจใฏ { #what-does-activating-a-virtual-environment-mean } ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนใซใ—ใŸใจใใ€ไพ‹ใˆใฐๆฌกใฎใ‚ณใƒžใƒณใƒ‰ใ‚’ๅฎŸ่กŒใ—ใŸๅ ดๅˆใ‚’่€ƒใˆใพใ™๏ผš @@ -620,7 +642,7 @@ $ source .venv/Scripts/activate /// tip | ่ฑ†็Ÿฅ่ญ˜ -`PATH` ๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏ [็’ฐๅขƒๅค‰ๆ•ฐ](environment-variables.md#path็’ฐๅขƒๅค‰ๆ•ฐ){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +`PATH` ๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏ [็’ฐๅขƒๅค‰ๆ•ฐ](environment-variables.md#path-environment-variable){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -701,7 +723,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนใซใ—ใฆๅค‰ๆ›ดใ•ใ‚Œใ‚‹ใ“ใจใฏไป–ใซใ‚‚ใ‚ใ‚Šใพใ™ใŒใ€ใ“ใ‚ŒใŒๆœ€ใ‚‚้‡่ฆใชๅค‰ๆ›ดใฎใฒใจใคใงใ™ใ€‚ -## ไปฎๆƒณ็’ฐๅขƒใฎ็ขบ่ช +## ไปฎๆƒณ็’ฐๅขƒใฎ็ขบ่ช { #checking-a-virtual-environment } ไปฎๆƒณ็’ฐๅขƒใŒๆœ‰ๅŠนใ‹ใฉใ†ใ‹ใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซ็ขบ่ชใงใใพใ™ใ€‚๏ผš @@ -753,7 +775,7 @@ Linuxใ‚„macOSใงใฏ `which` ใ‚’ใ€Windows PowerShellใงใฏ `Get-Command` ใ‚’ไฝฟ /// -## ใชใœไปฎๆƒณ็’ฐๅขƒใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใฎใ‹ +## ใชใœไปฎๆƒณ็’ฐๅขƒใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใฎใ‹ { #why-deactivate-a-virtual-environment } ไพ‹ใˆใฐใ€`philosophers-stone` ๏ผˆ่ณข่€…ใฎ็Ÿณ๏ผ‰ใจใ„ใ†ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงไฝœๆฅญใ‚’ใ—ใฆใ„ใฆใ€**ใใฎไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนใซใ—**ใ€ๅฟ…่ฆใชใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใฎ็’ฐๅขƒๅ†…ใงไฝœๆฅญใ‚’้€ฒใ‚ใฆใ„ใ‚‹ใจใ—ใพใ™ใ€‚ @@ -786,7 +808,7 @@ Traceback (most recent call last): -ใ—ใ‹ใ—ใ€ใใฎไปฎๆƒณ็’ฐๅขƒใ‚’็„กๅŠนๅŒ–ใ—ใ€ `prisoner-of-azkaban` ๏ผˆใ‚ขใ‚บใ‚ซใƒใƒณใฎๅ›šไบบ๏ผ‰ใฎใŸใ‚ใฎๆ–ฐใ—ใ„ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนใซใ™ใ‚Œใฐใ€ `python` ใ‚’ๅฎŸ่กŒใ—ใŸใจใใซ `prisoner-of-azkaban` ๏ผˆใ‚ขใ‚บใ‚ซใƒใƒณใฎๅ›šไบบ๏ผ‰ใฎไปฎๆƒณ็’ฐๅขƒใฎ Python ใŒไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใใฎไปฎๆƒณ็’ฐๅขƒใ‚’็„กๅŠนๅŒ–ใ—ใ€ `prisoner-of-askaban` ใฎใŸใ‚ใฎๆ–ฐใ—ใ„ไปฎๆƒณ็’ฐๅขƒใ‚’ๆœ‰ๅŠนใซใ™ใ‚Œใฐใ€ `python` ใ‚’ๅฎŸ่กŒใ—ใŸใจใใซ `prisoner-of-azkaban` ๏ผˆใ‚ขใ‚บใ‚ซใƒใƒณใฎๅ›šไบบ๏ผ‰ใฎไปฎๆƒณ็’ฐๅขƒใฎ Python ใŒไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚
@@ -807,7 +829,7 @@ I solemnly swear ๐Ÿบ
-## ไปฃๆ›ฟๆ‰‹ๆฎต +## ไปฃๆ›ฟๆ‰‹ๆฎต { #alternatives } ใ“ใ‚Œใฏใ€ใ‚ใ‚‰ใ‚†ใ‚‹ไป•็ต„ใฟใ‚’**ๆ นๆœฌใ‹ใ‚‰**ๅญฆใถใŸใ‚ใฎใ‚ทใƒณใƒ—ใƒซใชๅ…ฅ้–€ใ‚ฌใ‚คใƒ‰ใงใ™ใ€‚ @@ -824,7 +846,7 @@ I solemnly swear ๐Ÿบ * ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใจใใฎใƒใƒผใ‚ธใƒงใƒณใฎใ€ไพๅญ˜้–ขไฟ‚ใ‚’ๅซใ‚ใŸ**ๅŽณๅฏ†ใช**็ต„ใฟๅˆใ‚ใ›ใ‚’ไฟๆŒใ—ใ€ใ“ใ‚Œใซใ‚ˆใฃใฆใ€ๆœฌ็•ช็’ฐๅขƒใงใ€้–‹็™บ็’ฐๅขƒใจๅ…จใๅŒใ˜ใ‚ˆใ†ใซใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅฎŸ่กŒใงใใ‚‹๏ผˆใ“ใ‚Œใฏ**locking**ใจๅ‘ผใฐใ‚Œใพใ™๏ผ‰ * ใใฎไป–ใฎใ•ใพใ–ใพใชๆฉŸ่ƒฝ -## ใพใจใ‚ +## ใพใจใ‚ { #conclusion } ใ“ใ“ใพใง่ชญใฟใ™ในใฆ็†่งฃใ—ใŸใชใ‚‰ใ€ไธ–้–“ใฎๅคšใใฎ้–‹็™บ่€…ใจๆฏ”ในใฆใ€ไปฎๆƒณ็’ฐๅขƒใซใคใ„ใฆ**ใ‚ใชใŸใฏใ‚ˆใ‚Šๅคšใใฎใ“ใจใ‚’็Ÿฅใฃใฆใ„ใพใ™**ใ€‚๐Ÿค“ diff --git a/docs/ja/llm-prompt.md b/docs/ja/llm-prompt.md index 18909cd595..de26167461 100644 --- a/docs/ja/llm-prompt.md +++ b/docs/ja/llm-prompt.md @@ -30,8 +30,7 @@ Use the following preferred translations when they apply in documentation prose: - request (HTTP): ใƒชใ‚ฏใ‚จใ‚นใƒˆ - response (HTTP): ใƒฌใ‚นใƒใƒณใ‚น -- path operation: ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ -- path operation function: ใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ้–ขๆ•ฐ +- path operation: path operation (do not translate) ### `///` admonitions diff --git a/scripts/docs.py b/scripts/docs.py index 20bf1c1688..ca2baf97dc 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -23,6 +23,7 @@ SUPPORTED_LANGS = { "en", "de", "es", + "ja", "ko", "pt", "ru", From 71ceac20dad852db7741118325cdf2499bd30592 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 16:44:48 +0000 Subject: [PATCH 098/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1a56e5eca9..38d51d821e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ja (update-outdated). PR [#14588](https://github.com/fastapi/fastapi/pull/14588) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update outdated, found by fixer tool). PR [#14739](https://github.com/fastapi/fastapi/pull/14739) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev). From ad29e44c810c1fb1107d1cdc7b0409acc7e0feed Mon Sep 17 00:00:00 2001 From: Roman Mashevskyi Date: Wed, 4 Feb 2026 18:47:51 +0200 Subject: [PATCH 099/367] =?UTF-8?q?=F0=9F=8C=90=20Improve=20LLM=20prompt?= =?UTF-8?q?=20of=20`uk`=20documentation=20(#14795)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/llm-prompt.md | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/uk/llm-prompt.md b/docs/uk/llm-prompt.md index f1c5377a48..e8cd3dabc0 100644 --- a/docs/uk/llm-prompt.md +++ b/docs/uk/llm-prompt.md @@ -8,6 +8,7 @@ Language code: uk. - Use polite/formal address consistent with existing Ukrainian docs (use โ€œะฒะธ/ะฒะฐัˆโ€). - Keep the tone concise and technical. +- Use one style of dashes. For example, if text contains "-" then use only this symbol to represent a dash. ### Headings @@ -32,6 +33,71 @@ Use the following preferred translations when they apply in documentation prose: - response (HTTP): ะฒั–ะดะฟะพะฒั–ะดัŒ - path operation: ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ - path operation function: ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ +- prompt: ะฟั–ะดัะบะฐะทะบะฐ +- check: ะฟะตั€ะตะฒั–ั€ะบะฐ +- Parallel Server Gateway Interface: ะ†ะฝั‚ะตั€ั„ะตะนั ะจะปัŽะทัƒ ะŸะฐั€ะฐะปะตะปัŒะฝะพะณะพ ะกะตั€ะฒะตั€ะฐ +- Mozilla Developer Network: ะœะตั€ะตะถะฐ ะ ะพะทั€ะพะฑะฝะธะบั–ะฒ Mozilla +- tutorial: ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ +- advanced user guide: ะฟั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ +- deep learning: ะณะปะธะฑะพะบะต ะฝะฐะฒั‡ะฐะฝะฝั +- machine learning: ะผะฐัˆะธะฝะฝะต ะฝะฐะฒั‡ะฐะฝะฝั +- dependency injection: ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน +- digest (HTTP): ะดะฐะนะดะถะตัั‚ +- basic authentication (HTTP): ะฑะฐะทะพะฒะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั +- JSON schema: ะกั…ะตะผะฐ JSON +- password flow: ะฟะพั‚ั–ะบ ะฟะฐั€ะพะปัŽ +- mobile: ะผะพะฑั–ะปัŒะฝะธะน +- body: ั‚ั–ะปะพ +- form: ั„ะพั€ะผะฐ +- path: ัˆะปัั… +- query: ะทะฐะฟะธั‚ +- cookie: ะบัƒะบั– +- header: ะทะฐะณะพะปะพะฒะพะบ +- startup: ะทะฐะฟัƒัะบ +- shutdown: ะฒะธะผะบะฝะตะฝะฝั +- lifespan: ั‚ั€ะธะฒะฐะปั–ัั‚ัŒ ะถะธั‚ั‚ั +- authorization: ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั +- forwarded header: ะฝะฐะฟั€ะฐะฒะปะตะฝะธะน ะทะฐะณะพะปะพะฒะพะบ +- dependable: ะทะฐะปะตะถะฝะธะน +- dependent: ะทะฐะปะตะถะฝะธะน +- bound: ะผะตะถะฐ +- concurrency: ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ +- parallelism: ะฟะฐั€ะฐะปะตะปั–ะทะผ +- multiprocessing: ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะพั€ะฝั–ัั‚ัŒ +- env var: ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั +- dict: ัะปะพะฒะฝะธะบ +- enum: ะฟะตั€ะตะปั–ะบ +- issue: ะฟั€ะพะฑะปะตะผะฐ +- server worker: ัะตั€ะฒะตั€ะฝะธะน ะฟั€ะฐั†ั–ะฒะฝะธะบ +- worker: ะฟั€ะฐั†ั–ะฒะฝะธะบ +- software development kit: ะฝะฐะฑั–ั€ ะดะปั ั€ะพะทั€ะพะฑะบะธ ะฟั€ะพะณั€ะฐะผะฝะพะณะพ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั +- bearer token: ั‚ะพะบะตะฝ ะฝะพัั–ั +- breaking change: ะฝะตััƒะผั–ัะฝะฐ ะทะผั–ะฝะฐ +- bug: ะฟะพะผะธะปะบะฐ +- button: ะบะฝะพะฟะบะฐ +- callable: ะฒะธะบะปะธะบะฐั”ะผะธะน +- code: ะบะพะด +- commit: ั„ั–ะบัะฐั†ั–ั +- context manager: ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ +- coroutine: ัะฟั–ะฒะฟั€ะพะณั€ะฐะผะฐ +- engine: ั€ัƒัˆั–ะน +- fake X: ั„ะฐะปัŒัˆะธะฒะธะน X +- item: ะฟั€ะตะดะผะตั‚ +- lock: ะฑะปะพะบัƒะฒะฐะฝะฝั +- middleware: ะฟั€ะพะผั–ะถะฝะต ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั +- mounting: ะผะพะฝั‚ัƒะฒะฐะฝะฝั +- origin: ะดะถะตั€ะตะปะพ +- override: ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั +- payload: ะบะพั€ะธัะฝะต ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั +- processor: ะฟั€ะพั†ะตัะพั€ +- property: ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ +- proxy: ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ +- pull request: ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ +- random-access memory: ะฟะฐะผ'ัั‚ัŒ ะท ะดะพะฒั–ะปัŒะฝะธะผ ะดะพัั‚ัƒะฟะพะผ +- status code: ะบะพะด ัั‚ะฐั‚ัƒััƒ +- string: ัั‚ั€ะพะบะฐ +- tag: ะผั–ั‚ะบะฐ +- wildcard: ะดะธะบะฐ ะบะฐั€ั‚ะฐ ### `///` admonitions @@ -44,3 +110,4 @@ Use the following preferred translations when they apply in documentation prose: - `/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั` - `/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั` - `/// danger | ะžะฑะตั€ะตะถะฝะพ` +- `/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต` From 0e064009fb02773cd90d515647cda177776b2fbb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 16:48:16 +0000 Subject: [PATCH 100/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 38d51d821e..50dedf7885 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Translations +* ๐ŸŒ Improve LLM prompt of `uk` documentation. PR [#14795](https://github.com/fastapi/fastapi/pull/14795) by [@roli2py](https://github.com/roli2py). * ๐ŸŒ Update translations for ja (update-outdated). PR [#14588](https://github.com/fastapi/fastapi/pull/14588) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update outdated, found by fixer tool). PR [#14739](https://github.com/fastapi/fastapi/pull/14739) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo). From 84a5bcf82d265eb72fc2845f6625785a1524f023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 09:00:40 -0800 Subject: [PATCH 101/367] =?UTF-8?q?=E2=AC=87=EF=B8=8F=20Downgrade=20LLM=20?= =?UTF-8?q?translations=20model=20to=20GPT-5=20to=20reduce=20mistakes=20(#?= =?UTF-8?q?14823)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/translate.py b/scripts/translate.py index 072383514b..31c44583d1 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -86,7 +86,7 @@ def translate_page( print(f"Found existing translation: {out_path}") old_translation = out_path.read_text(encoding="utf-8") print(f"Translating {en_path} to {language} ({language_name})") - agent = Agent("openai:gpt-5.2") + agent = Agent("openai:gpt-5") prompt_segments = [ general_prompt, From 734c95b05a19aac1a87abce53fba3fda18fc9b9b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 17:01:08 +0000 Subject: [PATCH 102/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 50dedf7885..0dd61444bb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -70,6 +70,7 @@ hide: ### Internal +* โฌ‡๏ธ Downgrade LLM translations model to GPT-5 to reduce mistakes. PR [#14823](https://github.com/fastapi/fastapi/pull/14823) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ› Fix translation script commit in place. PR [#14818](https://github.com/fastapi/fastapi/pull/14818) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update translation script to retry if LLM-response doesn't pass validation with Translation Fixer tool. PR [#14749](https://github.com/fastapi/fastapi/pull/14749) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo). From 1de0de56c8e9f90d1e8f5fe82323f343d0c2a936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 18:33:29 +0100 Subject: [PATCH 103/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0dd61444bb..e3a133c18a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.1 + ### Features * โœจ Add `viewport` meta tag to improve Swagger UI on mobile devices. PR [#14777](https://github.com/fastapi/fastapi/pull/14777) by [@Joab0](https://github.com/Joab0). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 6133787b06..160e7235c3 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.0" +__version__ = "0.128.1" from starlette import status as status From 0e68d36cd5796384e833e97b57e98d17adc3c5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 4 Feb 2026 09:35:21 -0800 Subject: [PATCH 104/367] =?UTF-8?q?=F0=9F=94=A8=20Update=20docs=20and=20tr?= =?UTF-8?q?anslations=20scripts,=20enable=20Turkish=20(#14824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 2 ++ scripts/docs.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 34d489d92a..f713f2b122 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -325,6 +325,8 @@ extra: name: pt - portuguรชs - link: /ru/ name: ru - ั€ัƒััะบะธะน ัะทั‹ะบ + - link: /tr/ + name: tr - Tรผrkรงe - link: /uk/ name: uk - ัƒะบั€ะฐั—ะฝััŒะบะฐ ะผะพะฒะฐ extra_css: diff --git a/scripts/docs.py b/scripts/docs.py index ca2baf97dc..c1fb84bba7 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -20,14 +20,18 @@ from slugify import slugify as py_slugify logging.basicConfig(level=logging.INFO) SUPPORTED_LANGS = { - "en", "de", + "en", "es", + # "fr", "ja", "ko", "pt", "ru", + "tr", "uk", + # "zh", + # "zh-hant", } From 5ca11c59e36e8a177cec8341861a26a084415a11 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Feb 2026 17:36:12 +0000 Subject: [PATCH 105/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e3a133c18a..983e19fdb8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.1 ### Features From 2e170b9585fbbf57120598632cd7e13a11028c57 Mon Sep 17 00:00:00 2001 From: Rayyan oumlil Date: Thu, 5 Feb 2026 07:48:51 -0500 Subject: [PATCH 106/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20duplicate=20word?= =?UTF-8?q?=20in=20`advanced-dependencies.md`=20(#14815)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/advanced-dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index 37f5c78f2d..0d03507b7e 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -120,7 +120,7 @@ The exit code, the automatic closing of the `Session` in: {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} -...would be run after the the response finishes sending the slow data: +...would be run after the response finishes sending the slow data: {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} From 64d0ee9104da25bfe11e0df5d560d3f989845b6f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 12:49:18 +0000 Subject: [PATCH 107/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 983e19fdb8..6f3674911a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* ๐Ÿ“ Fix duplicate word in `advanced-dependencies.md`. PR [#14815](https://github.com/fastapi/fastapi/pull/14815) by [@Rayyan-Oumlil](https://github.com/Rayyan-Oumlil). + ### Translations * ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). From 31faba8e41da15d3b71a46dadea8366f548e8892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:31:31 -0800 Subject: [PATCH 108/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(update-outdated)=20(#14822)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Maksym Zavalniuk Co-authored-by: Roman Mashevskyi --- docs/uk/docs/index.md | 42 ++++++++----------- docs/uk/docs/tutorial/body-multiple-params.md | 9 ++-- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 526409c5cf..4f089c4e1a 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -8,7 +8,7 @@ FastAPI

- ะคั€ะตะนะผะฒะพั€ะบ FastAPI: ะฒะธัะพะบะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะปะตะณะบะพ ะฒะธะฒั‡ะฐั‚ะธ, ัˆะฒะธะดะบะพ ะฟะธัะฐั‚ะธ ะบะพะด, ะณะพั‚ะพะฒะธะน ะดะพ ะฟั€ะพะดะฐะบัˆะธะฝัƒ + ะคั€ะตะนะผะฒะพั€ะบ FastAPI - ั†ะต ะฒะธัะพะบะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะปะตะณะบะพ ะฒะธะฒั‡ะฐั‚ะธ, ัˆะฒะธะดะบะพ ะฟะธัะฐั‚ะธ ะบะพะด, ะณะพั‚ะพะฒะธะน ะดะพ ะฟั€ะพะดะฐะบัˆะธะฝัƒ

@@ -33,14 +33,14 @@ --- -FastAPI โ€” ั†ะต ััƒั‡ะฐัะฝะธะน, ัˆะฒะธะดะบะธะน (ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน) ะฒะตะฑั„ั€ะตะนะผะฒะพั€ะบ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Python, ั‰ะพ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… ะฟั–ะดะบะฐะทะบะฐั… ั‚ะธะฟั–ะฒ Python. +FastAPI - ั†ะต ััƒั‡ะฐัะฝะธะน, ัˆะฒะธะดะบะธะน (ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน) ะฒะตะฑั„ั€ะตะนะผะฒะพั€ะบ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Python, ั‰ะพ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… ะฟั–ะดะบะฐะทะบะฐั… ั‚ะธะฟั–ะฒ Python. ะšะปัŽั‡ะพะฒั– ะพัะพะฑะปะธะฒะพัั‚ั–: * **ะจะฒะธะดะบะธะน**: ะดัƒะถะต ะฒะธัะพะบะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะฝะฐ ั€ั–ะฒะฝั– ะท **NodeJS** ั‚ะฐ **Go** (ะทะฐะฒะดัะบะธ Starlette ั‚ะฐ Pydantic). [ะžะดะธะฝ ั–ะท ะฝะฐะนัˆะฒะธะดัˆะธั… Python-ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ](#performance). * **ะจะฒะธะดะบะต ะฝะฐะฟะธัะฐะฝะฝั ะบะพะดัƒ**: ะฟั€ะธัˆะฒะธะดัˆัƒั” ั€ะพะทั€ะพะฑะบัƒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัƒ ะฟั€ะธะฑะปะธะทะฝะพ ะฝะฐ 200%โ€“300%. * * **ะœะตะฝัˆะต ะฟะพะผะธะปะพะบ**: ะทะผะตะฝัˆัƒั” ะฟั€ะธะฑะปะธะทะฝะพ ะฝะฐ 40% ะบั–ะปัŒะบั–ัั‚ัŒ ะฟะพะผะธะปะพะบ, ัะฟั€ะธั‡ะธะฝะตะฝะธั… ะปัŽะดะธะฝะพัŽ (ั€ะพะทั€ะพะฑะฝะธะบะพะผ). * -* **ะ†ะฝั‚ัƒั—ั‚ะธะฒะฝะธะน**: ั‡ัƒะดะพะฒะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐะผะธ ะบะพะดัƒ. ะะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั. +* **ะ†ะฝั‚ัƒั—ั‚ะธะฒะฝะธะน**: ั‡ัƒะดะพะฒะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐะผะธ ะบะพะดัƒ. ะะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั. * **ะŸั€ะพัั‚ะธะน**: ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะธะน ั‚ะฐะบ, ั‰ะพะฑ ะฑัƒั‚ะธ ะฟั€ะพัั‚ะธะผ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ั‚ะฐ ะฒะธะฒั‡ะตะฝะฝั–. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ั‡ะธั‚ะฐะฝะฝั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. * **ะšะพั€ะพั‚ะบะธะน**: ะผั–ะฝั–ะผั–ะทัƒั” ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ. ะšั–ะปัŒะบะฐ ะผะพะถะปะธะฒะพัั‚ะตะน ะท ะบะพะถะฝะพะณะพ ะพะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ะฐ. ะœะตะฝัˆะต ะฟะพะผะธะปะพะบ. * **ะะฐะดั–ะนะฝะธะน**: ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะบะพะด, ะณะพั‚ะพะฒะธะน ะดะพ ะฟั€ะพะดะฐะบัˆะธะฝัƒ. ะ— ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ. @@ -127,9 +127,9 @@ FastAPI โ€” ั†ะต ััƒั‡ะฐัะฝะธะน, ัˆะฒะธะดะบะธะน (ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธ -ะฏะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ CLI ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒ ั‚ะตั€ะผั–ะฝะฐะปั– ะทะฐะผั–ัั‚ัŒ ะฒะตะฑ-API, ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ **Typer**. +ะฏะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ CLI ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒ ั‚ะตั€ะผั–ะฝะฐะปั– ะทะฐะผั–ัั‚ัŒ ะฒะตะฑ-API, ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ **Typer**. -**Typer** โ€” ะผะพะปะพะดัˆะธะน ะฑั€ะฐั‚ FastAPI. ะ† ะนะพะณะพ ะทะฐะดัƒะผะฐะฝะพ ัะบ **FastAPI ะดะปั CLI**. โŒจ๏ธ ๐Ÿš€ +**Typer** - ะผะพะปะพะดัˆะธะน ะฑั€ะฐั‚ FastAPI. ะ† ะนะพะณะพ ะทะฐะดัƒะผะฐะฝะพ ัะบ **FastAPI ะดะปั CLI**. โŒจ๏ธ ๐Ÿš€ ## ะ’ะธะผะพะณะธ { #requirements } @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" ะกั‚ะฒะพั€ั–ั‚ัŒ ั„ะฐะนะป `main.py` ะท: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): ะฏะบั‰ะพ ะฒะฐัˆ ะบะพะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `async` / `await`, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ INFO: Application startup complete. ะžะณะพะปะพัั–ั‚ัŒ ั‚ั–ะปะพ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ั‚ะธะฟะธ Python, ะทะฐะฒะดัะบะธ Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -374,7 +368,7 @@ item: Item * ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…: * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝั– ั‚ะฐ ะทั€ะพะทัƒะผั–ะปั– ะฟะพะผะธะปะบะธ, ะบะพะปะธ ะดะฐะฝั– ะฝะตะบะพั€ะตะบั‚ะฝั–. * ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะฝะฐะฒั–ั‚ัŒ ะดะปั ะณะปะธะฑะพะบะพ ะฒะบะปะฐะดะตะฝะธั… JSON-ะพะฑสผั”ะบั‚ั–ะฒ. -* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะท ะผะตั€ะตะถั– ะดะพ ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python. ะงะธั‚ะฐะฝะฝั ะท: +* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะท ะผะตั€ะตะถั– ะดะพ ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python. ะงะธั‚ะฐะฝะฝั ะท: * JSON. * ะŸะฐั€ะฐะผะตั‚ั€ั–ะฒ ัˆะปัั…ัƒ. * ะŸะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ. @@ -382,7 +376,7 @@ item: Item * Headers. * Forms. * Files. -* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒะธั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะท ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python ัƒ ะผะตั€ะตะถะตะฒั– ะดะฐะฝั– (ัะบ JSON): +* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒะธั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะท ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python ัƒ ะผะตั€ะตะถะตะฒั– ะดะฐะฝั– (ัะบ JSON): * ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ั‚ะธะฟั–ะฒ Python (`str`, `int`, `float`, `bool`, `list`, ั‚ะพั‰ะพ). * ะžะฑสผั”ะบั‚ั–ะฒ `datetime`. * ะžะฑสผั”ะบั‚ั–ะฒ `UUID`. @@ -439,9 +433,9 @@ item: Item ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -ะ”ะปั ะฑั–ะปัŒัˆ ะฟะพะฒะฝะพะณะพ ะฟั€ะธะบะปะฐะดัƒ, ั‰ะพ ะฒะบะปัŽั‡ะฐั” ะฑั–ะปัŒัˆะต ะผะพะถะปะธะฒะพัั‚ะตะน, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะขัƒั‚ะพั€ั–ะฐะป โ€” ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. +ะ”ะปั ะฑั–ะปัŒัˆ ะฟะพะฒะฝะพะณะพ ะฟั€ะธะบะปะฐะดัƒ, ั‰ะพ ะฒะบะปัŽั‡ะฐั” ะฑั–ะปัŒัˆะต ะผะพะถะปะธะฒะพัั‚ะตะน, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. -**Spoiler alert**: ั‚ัƒั‚ะพั€ั–ะฐะป โ€” ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะผั–ัั‚ะธั‚ัŒ: +**ะŸะพะฟะตั€ะตะดะถะตะฝะฝั ะฟั€ะพ ัะฟะพะนะปะตั€**: ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะผั–ัั‚ะธั‚ัŒ: * ะžะณะพะปะพัˆะตะฝะฝั **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ** ะท ั–ะฝัˆะธั… ั€ั–ะทะฝะธั… ะผั–ัั†ัŒ, ัะบ-ะพั‚: **headers**, **cookies**, **form fields** ั‚ะฐ **files**. * ะฏะบ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ **ะพะฑะผะตะถะตะฝะฝั ะฒะฐะปั–ะดะฐั†ั–ั—** ัะบ `maximum_length` ะฐะฑะพ `regex`. @@ -500,11 +494,11 @@ Deploying to FastAPI Cloud... ะ’ั–ะฝ ะทะฐะฑะตะทะฟะตั‡ัƒั” ั‚ะพะน ัะฐะผะธะน **developer experience** ัั‚ะฒะพั€ะตะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะฝะฐ FastAPI ะฟั–ะด ั‡ะฐั ั—ั… **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั** ัƒ ั…ะผะฐั€ั–. ๐ŸŽ‰ -FastAPI Cloud โ€” ะพัะฝะพะฒะฝะธะน ัะฟะพะฝัะพั€ ั– ะดะถะตั€ะตะปะพ ั„ั–ะฝะฐะฝััƒะฒะฐะฝะฝั open source ะฟั€ะพั”ะบั‚ั–ะฒ *FastAPI and friends*. โœจ +FastAPI Cloud - ะพัะฝะพะฒะฝะธะน ัะฟะพะฝัะพั€ ั– ะดะถะตั€ะตะปะพ ั„ั–ะฝะฐะฝััƒะฒะฐะฝะฝั open source ะฟั€ะพั”ะบั‚ั–ะฒ *FastAPI and friends*. โœจ #### ะ ะพะทะณะพั€ั‚ะฐะฝะฝั ะฒ ั–ะฝัˆะธั… ั…ะผะฐั€ะฝะธั… ะฟั€ะพะฒะฐะนะดะตั€ั–ะฒ { #deploy-to-other-cloud-providers } -FastAPI โ€” open source ั– ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฐั…. ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ะฒ ะฑัƒะดัŒ-ัะบะพะผัƒ ั…ะผะฐั€ะฝะพะผัƒ ะฟั€ะพะฒะฐะนะดะตั€ั–, ัะบะธะน ะฒะธ ะพะฑะตั€ะตั‚ะต. +FastAPI - open source ะฟั€ะพะตะบั‚ ั– ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฐั…. ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ะฒ ะฑัƒะดัŒ-ัะบะพะผัƒ ั…ะผะฐั€ะฝะพะผัƒ ะฟั€ะพะฒะฐะนะดะตั€ั–, ัะบะธะน ะฒะธ ะพะฑะตั€ะตั‚ะต. ะ”ะพั‚ั€ะธะผัƒะนั‚ะตัั ั–ะฝัั‚ั€ัƒะบั†ั–ะน ะฒะฐัˆะพะณะพ ั…ะผะฐั€ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ, ั‰ะพะฑ ั€ะพะทะณะพั€ะฝัƒั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ัƒ ะฝัŒะพะณะพ. ๐Ÿค“ @@ -530,7 +524,7 @@ FastAPI ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด Pydantic ั– Starlette. * httpx - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `TestClient`. * jinja2 - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ ัˆะฐะฑะปะพะฝั–ะฒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. -* python-multipart - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ยซparsingยป ั„ะพั€ะผ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `request.form()`. +* python-multipart - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ยซparsingยป ั„ะพั€ะผ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `request.form()`. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั FastAPI: diff --git a/docs/uk/docs/tutorial/body-multiple-params.md b/docs/uk/docs/tutorial/body-multiple-params.md index dc9a768c35..f541beea76 100644 --- a/docs/uk/docs/tutorial/body-multiple-params.md +++ b/docs/uk/docs/tutorial/body-multiple-params.md @@ -103,15 +103,16 @@ ะžัะบั–ะปัŒะบะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะพะดะธะฝะธั‡ะฝั– ะทะฝะฐั‡ะตะฝะฝั ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒัŽั‚ัŒัั ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ัะฒะฝะพ ะดะพะดะฐะฒะฐั‚ะธ `Query`, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะทั€ะพะฑะธั‚ะธ: ```Python -q: Union[str, None] = None +q: str | None = None ``` -ะะฑะพ ะฒ Python 3.10 ั– ะฒะธั‰ะต: +ะะฑะพ ะฒ Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` + ะะฐะฟั€ะธะบะปะฐะด: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} @@ -129,7 +130,7 @@ q: str | None = None ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ **FastAPI** ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต ะนะพะณะพ ั‚ั–ะปะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. -ะะปะต ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฒั–ะฝ ะพั‡ั–ะบัƒะฒะฐะฒ JSON ะท ะบะปัŽั‡ะตะผ `item`, ะฐ ะฒัะตั€ะตะดะธะฝั– ะฝัŒะพะณะพ โ€” ะฒะผั–ัั‚ ะผะพะดะตะปั–, ัะบ ั†ะต ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั, ะบะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ะดะพะดะฐั‚ะบะพะฒั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ั–ะปะฐ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ `Body` โ€” `embed`: +ะะปะต ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฒั–ะฝ ะพั‡ั–ะบัƒะฒะฐะฒ JSON ะท ะบะปัŽั‡ะตะผ `item`, ะฐ ะฒัะตั€ะตะดะธะฝั– ะฝัŒะพะณะพ - ะฒะผั–ัั‚ ะผะพะดะตะปั–, ัะบ ั†ะต ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั, ะบะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ะดะพะดะฐั‚ะบะพะฒั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ั–ะปะฐ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ `Body` - `embed`: ```Python item: Item = Body(embed=True) From c00cebc5c68331046741f862359b83d0f428e518 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 15:31:55 +0000 Subject: [PATCH 109/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6f3674911a..f52be20d3b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). ## 0.128.1 From b4ed7e5b0644d180a2e437aa266f8696a0b89424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:32:56 -0800 Subject: [PATCH 110/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(update-outdated)=20(#14825)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh-hant/docs/about/index.md | 2 +- docs/zh-hant/docs/benchmarks.md | 6 +- docs/zh-hant/docs/deployment/cloud.md | 21 +- docs/zh-hant/docs/deployment/index.md | 8 +- docs/zh-hant/docs/environment-variables.md | 26 +- docs/zh-hant/docs/how-to/index.md | 2 +- docs/zh-hant/docs/index.md | 465 +++++++++++------- docs/zh-hant/docs/learn/index.md | 4 +- docs/zh-hant/docs/resources/index.md | 4 +- docs/zh-hant/docs/tutorial/first-steps.md | 217 ++++---- docs/zh-hant/docs/tutorial/index.md | 93 ++-- .../docs/tutorial/query-param-models.md | 10 +- docs/zh-hant/docs/virtual-environments.md | 68 ++- 13 files changed, 546 insertions(+), 380 deletions(-) diff --git a/docs/zh-hant/docs/about/index.md b/docs/zh-hant/docs/about/index.md index 5dcee68f2d..cf5b5742c5 100644 --- a/docs/zh-hant/docs/about/index.md +++ b/docs/zh-hant/docs/about/index.md @@ -1,3 +1,3 @@ -# ้—œๆ–ผ FastAPI +# ้—œๆ–ผ { #about } ้—œๆ–ผ FastAPIใ€ๅ…ถ่จญ่จˆใ€้ˆๆ„Ÿไพ†ๆบ็ญ‰ๆ›ดๅคš่ณ‡่จŠใ€‚ ๐Ÿค“ diff --git a/docs/zh-hant/docs/benchmarks.md b/docs/zh-hant/docs/benchmarks.md index c59e8e71c6..df49621c53 100644 --- a/docs/zh-hant/docs/benchmarks.md +++ b/docs/zh-hant/docs/benchmarks.md @@ -1,10 +1,10 @@ -# ๅŸบๆบ–ๆธฌ่ฉฆ +# ๅŸบๆบ–ๆธฌ่ฉฆ { #benchmarks } ็”ฑ็ฌฌไธ‰ๆ–นๆฉŸๆง‹ TechEmpower ็š„ๅŸบๆบ–ๆธฌ่ฉฆ่กจๆ˜Žๅœจ Uvicorn ไธ‹้‹่กŒ็š„ **FastAPI** ๆ‡‰็”จ็จ‹ๅผๆ˜ฏ ๆœ€ๅฟซ็š„ Python ๅฏ็”จๆก†ๆžถไน‹ไธ€๏ผŒๅƒ…ๆฌกๆ–ผ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ๏ผˆๆ–ผ FastAPI ๅ…ง้ƒจไฝฟ็”จ๏ผ‰ใ€‚ ไฝ†ๆ˜ฏๅœจๆŸฅ็œ‹ๅŸบๆบ–ๅพ—ๅˆ†ๅ’Œๅฐๆฏ”ๆ™‚๏ผŒ่ซ‹ๆณจๆ„ไปฅไธ‹ๅนพ้ปžใ€‚ -## ๅŸบๆบ–ๆธฌ่ฉฆๅ’Œ้€Ÿๅบฆ +## ๅŸบๆบ–ๆธฌ่ฉฆๅ’Œ้€Ÿๅบฆ { #benchmarks-and-speed } ็•ถไฝ ๆŸฅ็œ‹ๅŸบๆบ–ๆธฌ่ฉฆๆ™‚๏ผŒๆ™‚ๅธธๆœƒ่ฆ‹ๅˆฐๅนพๅ€‹ไธๅŒ้กžๅž‹็š„ๅทฅๅ…ท่ขซๅŒๆ™‚้€ฒ่กŒๆธฌ่ฉฆใ€‚ @@ -31,4 +31,4 @@ * FastAPI ๅœจ Starlette ๅŸบ็คŽไน‹ไธŠๆไพ›ไบ†ๆ›ดๅคšๅŠŸ่ƒฝใ€‚ๅŒ…ๅซๅปบๆง‹ API ๆ™‚ๆ‰€้œ€่ฆ็š„ๅŠŸ่ƒฝ๏ผŒไพ‹ๅฆ‚่ณ‡ๆ–™้ฉ—่ญ‰ๅ’Œๅบๅˆ—ๅŒ–ใ€‚FastAPI ๅฏไปฅๅนซๅŠฉไฝ ่‡ชๅ‹•็”ข็”Ÿ API ๆ–‡ไปถ๏ผŒ๏ผˆๆ‡‰็”จ็จ‹ๅผๅ•Ÿๅ‹•ๆ™‚ๅฐ‡ๆœƒ่‡ชๅ‹•็”Ÿๆˆๆ–‡ไปถ๏ผŒๆ‰€ไปฅไธๆœƒๅขžๅŠ ๆ‡‰็”จ็จ‹ๅผ้‹่กŒๆ™‚็š„้–‹้Šท๏ผ‰ใ€‚ * ๅฆ‚ๆžœไฝ ๆฒ’ๆœ‰ไฝฟ็”จ FastAPI ่€Œๆ˜ฏ็›ดๆŽฅไฝฟ็”จ Starlette๏ผˆๆˆ–ๅ…ถไป–ๅทฅๅ…ท๏ผŒๅฆ‚ Sanicใ€Flaskใ€Responder ็ญ‰๏ผ‰๏ผŒไฝ ๅฐ‡ๅฟ…้ ˆ่‡ช่กŒๅฏฆ็พๆ‰€ๆœ‰่ณ‡ๆ–™้ฉ—่ญ‰ๅ’Œๅบๅˆ—ๅŒ–ใ€‚ๅ› ๆญค๏ผŒไฝ ็š„ๆœ€็ต‚ๆ‡‰็”จ็จ‹ๅผไป็„ถๅ…ทๆœ‰่ˆ‡ไฝฟ็”จ FastAPI ๅปบ็ฝฎ็›ธๅŒ็š„้–‹้Šทใ€‚ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒ้€™็จฎ่ณ‡ๆ–™้ฉ—่ญ‰ๅ’Œๅบๅˆ—ๅŒ–ๆ˜ฏๆ‡‰็”จ็จ‹ๅผไธญ็ทจๅฏซๆœ€ๅคง้‡็š„็จ‹ๅผ็ขผใ€‚ * ๅ› ๆญค้€้Žไฝฟ็”จ FastAPI๏ผŒไฝ ๅฏไปฅ็ฏ€็œ้–‹็™ผๆ™‚้–“ใ€้Œฏ่ชค่ˆ‡็จ‹ๅผ็ขผๆ•ธ้‡๏ผŒไธฆไธ”็›ธๆฏ”ไธไฝฟ็”จ FastAPI ไฝ ๅพˆๅคงๅฏ่ƒฝๆœƒ็ฒๅพ—็›ธๅŒๆˆ–ๆ›ดๅฅฝ็š„ๆ•ˆ่ƒฝ๏ผˆๅ› ็‚บ้‚ฃๆจฃไฝ ๅฟ…้ ˆๅœจ็จ‹ๅผ็ขผไธญๅฏฆ็พๆ‰€ๆœ‰็›ธๅŒ็š„ๅŠŸ่ƒฝ๏ผ‰ใ€‚ - * ๅฆ‚ๆžœไฝ ่ฆ่ˆ‡ FastAPI ๆฏ”่ผƒ๏ผŒ่ซ‹ๅฐ‡ๅ…ถ่ˆ‡่ƒฝๅค ๆไพ›่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–ๅ’Œๆ–‡ไปถ็š„็ถฒ้ ๆ‡‰็”จ็จ‹ๅผๆก†ๆžถ๏ผˆๆˆ–ๅทฅๅ…ท้›†๏ผ‰้€ฒ่กŒๆฏ”่ผƒ๏ผŒไพ‹ๅฆ‚ Flask-apispecใ€NestJSใ€Molten ็ญ‰ๆก†ๆžถใ€‚ + * ๅฆ‚ๆžœไฝ ่ฆ่ˆ‡ FastAPI ๆฏ”่ผƒ๏ผŒ่ซ‹ๅฐ‡ๅ…ถ่ˆ‡่ƒฝๅค ๆไพ›่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–ๅ’Œๆ–‡ไปถ็š„็ถฒ้ ๆ‡‰็”จ็จ‹ๅผๆก†ๆžถ๏ผˆๆˆ–ๅทฅๅ…ท้›†๏ผ‰้€ฒ่กŒๆฏ”่ผƒ๏ผŒไพ‹ๅฆ‚ Flask-apispecใ€NestJSใ€Molten ็ญ‰ๆก†ๆžถใ€‚ๅ…ทๅ‚™ๆ•ดๅˆๅผ่‡ชๅ‹•่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถ็š„ๆก†ๆžถใ€‚ diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md index 426937d3e4..fffb2fcfeb 100644 --- a/docs/zh-hant/docs/deployment/cloud.md +++ b/docs/zh-hant/docs/deployment/cloud.md @@ -1,13 +1,24 @@ -# ๅœจ้›ฒ็ซฏ้ƒจ็ฝฒ FastAPI +# ๅœจ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ไธŠ้ƒจ็ฝฒ FastAPI { #deploy-fastapi-on-cloud-providers } ไฝ ๅนพไนŽๅฏไปฅไฝฟ็”จ**ไปปไฝ•้›ฒ็ซฏไพ›ๆ‡‰ๅ•†**ไพ†้ƒจ็ฝฒไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผใ€‚ ๅœจๅคงๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไธป่ฆ็š„้›ฒ็ซฏไพ›ๆ‡‰ๅ•†้ƒฝๆœ‰้ƒจ็ฝฒ FastAPI ็š„ๆŒ‡ๅ—ใ€‚ -## ้›ฒ็ซฏไพ›ๆ‡‰ๅ•† - ่ดŠๅŠฉๅ•† +## FastAPI Cloud { #fastapi-cloud } -ไธ€ไบ›้›ฒ็ซฏไพ›ๆ‡‰ๅ•† โœจ [**่ดŠๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๏ผŒ้€™็ขบไฟไบ† FastAPI ๅŠๅ…ถ**็”Ÿๆ…‹็ณป็ตฑ**ๆŒ็บŒๅฅๅบทๅœฐ**็™ผๅฑ•**ใ€‚ +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ๅŒไธ€ไฝไฝœ่€…่ˆ‡ๅœ˜้šŠๆ‰“้€ ใ€‚ -้€™ไนŸๅฑ•็พไบ†ไป–ๅ€‘ๅฐ FastAPI ๅ’Œๅ…ถ**็คพ็พค**๏ผˆๅŒ…ๆ‹ฌไฝ ๏ผ‰็š„็œŸๆญฃๆ‰ฟ่ซพ๏ผŒไป–ๅ€‘ไธๅƒ…ๅธŒๆœ›็‚บไฝ ๆไพ›**ๅ„ช่ณช็š„ๆœๅ‹™**๏ผŒ้‚„ๅธŒๆœ›็ขบไฟไฝ ๆ“ๆœ‰ไธ€ๅ€‹**่‰ฏๅฅฝไธ”ๅฅๅบท็š„ๆก†ๆžถ**๏ผšFastAPIใ€‚๐Ÿ™‡ +ๅฎƒ่ฎ“ไฝ ไปฅๆœ€ๅฐ‘็š„ๆŠ•ๅ…ฅ๏ผŒ็ฐกๅŒ– **ๅปบ็ฝฎ**ใ€**้ƒจ็ฝฒ** ่ˆ‡ **ๅญ˜ๅ–** API ็š„ๆต็จ‹ใ€‚ -ไฝ ๅฏ่ƒฝๆœƒๆƒณๅ˜—่ฉฆไป–ๅ€‘็š„ๆœๅ‹™๏ผŒไปฅไธ‹ๆœ‰ไป–ๅ€‘็š„ๆŒ‡ๅ—. +ๅฎƒๆŠŠไฝฟ็”จ FastAPI ้–‹็™ผๆ‡‰็”จ็š„ๅŒๆจฃ**ๅ„ช็ง€็š„้–‹็™ผ่€…้ซ”้ฉ—**๏ผŒๅธถๅˆฐๅฐ‡ๅฎƒๅ€‘**้ƒจ็ฝฒ**ๅˆฐ้›ฒ็ซฏ็š„้Ž็จ‹ไธญใ€‚๐ŸŽ‰ + +FastAPI Cloud ๆ˜ฏ *FastAPI and friends* ้–‹ๆบๅฐˆๆกˆ็š„ไธป่ฆ่ดŠๅŠฉ่ˆ‡่ณ‡้‡‘ๆไพ›่€…ใ€‚โœจ + +## ้›ฒ็ซฏไพ›ๆ‡‰ๅ•† - ่ดŠๅŠฉๅ•† { #cloud-providers-sponsors } + +ๅ…ถไป–ไธ€ไบ›้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ไนŸๆœƒ โœจ [**่ดŠๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจใ€‚๐Ÿ™‡ + +ไฝ ไนŸๅฏไปฅๅƒ่€ƒไป–ๅ€‘็š„ๆŒ‡ๅ—ไธฆ่ฉฆ็”จๅ…ถๆœๅ‹™๏ผš + +* Render +* Railway diff --git a/docs/zh-hant/docs/deployment/index.md b/docs/zh-hant/docs/deployment/index.md index 1726562b40..9edd3368b2 100644 --- a/docs/zh-hant/docs/deployment/index.md +++ b/docs/zh-hant/docs/deployment/index.md @@ -1,8 +1,8 @@ -# ้ƒจ็ฝฒ +# ้ƒจ็ฝฒ { #deployment } ้ƒจ็ฝฒ **FastAPI** ๆ‡‰็”จ็จ‹ๅผ็›ธๅฐๅฎนๆ˜“ใ€‚ -## ้ƒจ็ฝฒๆ˜ฏไป€้บผๆ„ๆ€ +## ้ƒจ็ฝฒๆ˜ฏไป€้บผๆ„ๆ€ { #what-does-deployment-mean } **้ƒจ็ฝฒ**ๆ‡‰็”จ็จ‹ๅผๆŒ‡็š„ๆ˜ฏๅŸท่กŒไธ€็ณปๅˆ—ๅฟ…่ฆ็š„ๆญฅ้ฉŸ๏ผŒไฝฟๅ…ถ่ƒฝๅค **่ฎ“ไฝฟ็”จ่€…ๅญ˜ๅ–ๅ’Œไฝฟ็”จ**ใ€‚ @@ -10,12 +10,14 @@ ้€™่ˆ‡**้–‹็™ผ**้šŽๆฎตๅฝขๆˆ้ฎฎๆ˜Žๅฐๆฏ”๏ผŒๅœจ**้–‹็™ผ**้šŽๆฎต๏ผŒไฝ ๆœƒไธๆ–ทๆ›ดๆ”น็จ‹ๅผ็ขผใ€็ ดๅฃž็จ‹ๅผ็ขผใ€ไฟฎๅพฉ็จ‹ๅผ็ขผ๏ผŒ็„ถๅพŒๅœๆญขๅ’Œ้‡ๆ–ฐๅ•Ÿๅ‹•ไผบๆœๅ™จ็ญ‰ใ€‚ -## ้ƒจ็ฝฒ็ญ–็•ฅ +## ้ƒจ็ฝฒ็ญ–็•ฅ { #deployment-strategies } ๆ นๆ“šไฝ ็š„ไฝฟ็”จๅ ดๆ™ฏๅ’Œไฝฟ็”จๅทฅๅ…ท๏ผŒๆœ‰ๅคš็จฎๆ–นๆณ•ๅฏไปฅๅฏฆ็พๆญค็›ฎ็š„ใ€‚ ไฝ ๅฏไปฅไฝฟ็”จไธ€ไบ›ๅทฅๅ…ท่‡ช่กŒ**้ƒจ็ฝฒไผบๆœๅ™จ**๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ่ƒฝ็‚บไฝ ๅฎŒๆˆ้ƒจๅˆ†ๅทฅไฝœ็š„**้›ฒ็ซฏๆœๅ‹™**๏ผŒๆˆ–ๅ…ถไป–ๅฏ่ƒฝ็š„้ธ้ …ใ€‚ +ไพ‹ๅฆ‚๏ผŒๆˆ‘ๅ€‘๏ผˆFastAPI ็š„ๅœ˜้šŠ๏ผ‰ๆ‰“้€ ไบ† **FastAPI Cloud**๏ผŒ่ฎ“ๅฐ‡ FastAPI ๆ‡‰็”จ็จ‹ๅผ้ƒจ็ฝฒๅˆฐ้›ฒ็ซฏ่ฎŠๅพ—็›กๅฏ่ƒฝๆตๆšข๏ผŒไธฆไฟๆŒ่ˆ‡ไฝฟ็”จ FastAPI ้–‹็™ผๆ™‚็›ธๅŒ็š„้–‹็™ผ่€…้ซ”้ฉ—ใ€‚ + ๆˆ‘ๅฐ‡ๅ‘ไฝ ๅฑ•็คบๅœจ้ƒจ็ฝฒ **FastAPI** ๆ‡‰็”จ็จ‹ๅผๆ™‚ไฝ ๅฏ่ƒฝๆ‡‰่ฉฒ่จ˜ไฝ็š„ไธ€ไบ›ไธป่ฆๆฆ‚ๅฟต๏ผˆๅ„˜็ฎกๅ…ถไธญๅคง้ƒจๅˆ†้ฉ็”จๆ–ผไปปไฝ•ๅ…ถไป–้กžๅž‹็š„ Web ๆ‡‰็”จ็จ‹ๅผ๏ผ‰ใ€‚ ๅœจๆŽฅไธ‹ไพ†็š„้ƒจๅˆ†ไธญ๏ผŒไฝ ๅฐ‡็œ‹ๅˆฐๆ›ดๅคš้œ€่ฆ่จ˜ไฝ็š„็ดฐ็ฏ€ไปฅๅŠไธ€ไบ›ๆŠ€ๅทงใ€‚ โœจ diff --git a/docs/zh-hant/docs/environment-variables.md b/docs/zh-hant/docs/environment-variables.md index a1598fc018..5b684b9e6a 100644 --- a/docs/zh-hant/docs/environment-variables.md +++ b/docs/zh-hant/docs/environment-variables.md @@ -1,4 +1,4 @@ -# ็’ฐๅขƒ่ฎŠๆ•ธ +# ็’ฐๅขƒ่ฎŠๆ•ธ { #environment-variables } /// tip @@ -10,7 +10,7 @@ ็’ฐๅขƒ่ฎŠๆ•ธๅฐๆ–ผ่™•็†ๆ‡‰็”จ็จ‹ๅผ**่จญๅฎš**๏ผˆไฝœ็‚บ Python **ๅฎ‰่ฃ**็š„ไธ€้ƒจๅˆ†็ญ‰ๆ–น้ข๏ผ‰้žๅธธๆœ‰็”จใ€‚ -## ๅปบ็ซ‹ๅ’Œไฝฟ็”จ็’ฐๅขƒ่ฎŠๆ•ธ +## ๅปบ็ซ‹ๅ’Œไฝฟ็”จ็’ฐๅขƒ่ฎŠๆ•ธ { #create-and-use-env-vars } ไฝ ๅœจ **shell๏ผˆ็ต‚็ซฏๆฉŸ๏ผ‰**ไธญๅฐฑๅฏไปฅ**ๅปบ็ซ‹**ๅ’Œไฝฟ็”จ็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒไธฆไธ้œ€่ฆ็”จๅˆฐ Python๏ผš @@ -50,7 +50,7 @@ Hello Wade Wilson //// -## ๅœจ Python ไธญ่ฎ€ๅ–็’ฐๅขƒ่ฎŠๆ•ธ +## ๅœจ Python ไธญ่ฎ€ๅ–็’ฐๅขƒ่ฎŠๆ•ธ { #read-env-vars-in-python } ไฝ ไนŸๅฏไปฅๅœจ Python **ไน‹ๅค–**็š„็ต‚็ซฏๆฉŸไธญๅปบ็ซ‹็’ฐๅขƒ่ฎŠๆ•ธ๏ผˆๆˆ–ไฝฟ็”จๅ…ถไป–ๆ–นๆณ•๏ผ‰๏ผŒ็„ถๅพŒๅœจ Python ไธญ**่ฎ€ๅ–**ๅฎƒๅ€‘ใ€‚ @@ -65,7 +65,7 @@ print(f"Hello {name} from Python") /// tip -็ฌฌไบŒๅ€‹ๅƒๆ•ธๆ˜ฏ `os.getenv()` ็š„้ ่จญๅ›žๅ‚ณๅ€ผใ€‚ +็ฌฌไบŒๅ€‹ๅƒๆ•ธๆ˜ฏ `os.getenv()` ็š„้ ่จญๅ›žๅ‚ณๅ€ผใ€‚ ๅฆ‚ๆžœๆฒ’ๆœ‰ๆไพ›๏ผŒ้ ่จญๅ€ผ็‚บ `None`๏ผŒ้€™่ฃกๆˆ‘ๅ€‘ๆไพ› `"World"` ไฝœ็‚บ้ ่จญๅ€ผใ€‚ @@ -153,19 +153,19 @@ Hello World from Python /// tip -ไฝ ๅฏไปฅๅœจ The Twelve-Factor App: ้…็ฝฎไธญไบ†่งฃๆ›ดๅคš่ณ‡่จŠใ€‚ +ไฝ ๅฏไปฅๅœจ The Twelve-Factor App: ้…็ฝฎไธญไบ†่งฃๆ›ดๅคš่ณ‡่จŠใ€‚ /// -## ๅž‹ๅˆฅๅ’Œ้ฉ—่ญ‰ +## ๅž‹ๅˆฅๅ’Œ้ฉ—่ญ‰ { #types-and-validation } ้€™ไบ›็’ฐๅขƒ่ฎŠๆ•ธๅช่ƒฝ่™•็†**ๆ–‡ๅญ—ๅญ—ไธฒ**๏ผŒๅ› ็‚บๅฎƒๅ€‘ๆ˜ฏไฝๆ–ผ Python ็ฏ„็–‡ไน‹ๅค–็š„๏ผŒๅฟ…้ ˆ่ˆ‡ๅ…ถไป–็จ‹ๅผๅ’Œไฝœๆฅญ็ณป็ตฑ็š„ๅ…ถ้ค˜้ƒจๅˆ†็›ธๅฎน๏ผˆ็”š่‡ณ่ˆ‡ไธๅŒ็š„ไฝœๆฅญ็ณป็ตฑ็›ธๅฎน๏ผŒๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰ใ€‚ ้€™ๆ„ๅ‘ณ่‘—ๅพž็’ฐๅขƒ่ฎŠๆ•ธไธญ่ฎ€ๅ–็š„**ไปปไฝ•ๅ€ผ**ๅœจ Python ไธญ้ƒฝๅฐ‡ๆ˜ฏไธ€ๅ€‹ `str`๏ผŒไปปไฝ•ๅž‹ๅˆฅ่ฝ‰ๆ›ๆˆ–้ฉ—่ญ‰้ƒฝๅฟ…้ ˆๅœจ็จ‹ๅผ็ขผไธญๅฎŒๆˆใ€‚ -ไฝ ๅฐ‡ๅœจ[้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— - ่จญๅฎšๅ’Œ็’ฐๅขƒ่ฎŠๆ•ธ](./advanced/settings.md)ไธญไบ†่งฃๆ›ดๅคš้—œๆ–ผไฝฟ็”จ็’ฐๅขƒ่ฎŠๆ•ธ่™•็†**ๆ‡‰็”จ็จ‹ๅผ่จญๅฎš**็š„่ณ‡่จŠใ€‚ +ไฝ ๅฐ‡ๅœจ[้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— - ่จญๅฎšๅ’Œ็’ฐๅขƒ่ฎŠๆ•ธ](./advanced/settings.md){.internal-link target=_blank}ไธญไบ†่งฃๆ›ดๅคš้—œๆ–ผไฝฟ็”จ็’ฐๅขƒ่ฎŠๆ•ธ่™•็†**ๆ‡‰็”จ็จ‹ๅผ่จญๅฎš**็š„่ณ‡่จŠใ€‚ -## `PATH` ็’ฐๅขƒ่ฎŠๆ•ธ +## `PATH` ็’ฐๅขƒ่ฎŠๆ•ธ { #path-environment-variable } ๆœ‰ไธ€ๅ€‹**็‰นๆฎŠ็š„**็’ฐๅขƒ่ฎŠๆ•ธ็จฑ็‚บ **`PATH`**๏ผŒไฝœๆฅญ็ณป็ตฑ๏ผˆLinuxใ€macOSใ€Windows๏ผ‰็”จๅฎƒไพ†ๆŸฅๆ‰พ่ฆๅŸท่กŒ็š„็จ‹ๅผใ€‚ @@ -209,7 +209,7 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 ๅฆ‚ๆžœๆ‰พๅˆฐไบ†๏ผŒ้‚ฃ้บผไฝœๆฅญ็ณป็ตฑๅฐ‡**ไฝฟ็”จๅฎƒ**๏ผ›ๅฆๅ‰‡๏ผŒไฝœๆฅญ็ณป็ตฑๆœƒ็นผ็บŒๅœจ**ๅ…ถไป–็›ฎ้Œ„**ไธญๆŸฅๆ‰พใ€‚ -### ๅฎ‰่ฃ Python ไธฆๆ›ดๆ–ฐ `PATH` +### ๅฎ‰่ฃ Python ไธฆๆ›ดๆ–ฐ `PATH` { #installing-python-and-updating-the-path } ๅฎ‰่ฃ Python ๆ™‚๏ผŒๅฏ่ƒฝๆœƒ่ฉขๅ•ไฝ ๆ˜ฏๅฆ่ฆๆ›ดๆ–ฐ `PATH` ็’ฐๅขƒ่ฎŠๆ•ธใ€‚ @@ -233,7 +233,7 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 ๅ‡่จญไฝ ๅฎ‰่ฃไบ† Python๏ผŒไธฆๅฐ‡ๅ…ถๅฎ‰่ฃๅœจ็›ฎ้Œ„ `C:\opt\custompython\bin` ไธญใ€‚ -ๅฆ‚ๆžœไฝ ้ธๆ“‡ๆ›ดๆ–ฐ `PATH` ็’ฐๅขƒ่ฎŠๆ•ธ๏ผˆๅœจ Python ๅฎ‰่ฃ็จ‹ๅผไธญ๏ผŒ้€™ๅ€‹้ธ้ …ๆ˜ฏๅ็‚บ `Add Python x.xx to PATH` ็š„ๅ‹พ้ธๆก†โ€”โ€”่ญฏ่€…่จป๏ผ‰๏ผŒ้‚ฃ้บผๅฎ‰่ฃ็จ‹ๅผๆœƒๅฐ‡ `C:\opt\custompython\bin` ๅŠ ๅ…ฅๅˆฐ `PATH` ็’ฐๅขƒ่ฎŠๆ•ธไธญใ€‚ +ๅฆ‚ๆžœไฝ ้ธๆ“‡ๆ›ดๆ–ฐ `PATH` ็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒ้‚ฃ้บผๅฎ‰่ฃ็จ‹ๅผๆœƒๅฐ‡ `C:\opt\custompython\bin` ๅŠ ๅ…ฅๅˆฐ `PATH` ็’ฐๅขƒ่ฎŠๆ•ธไธญใ€‚ ```plaintext C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -็•ถๅญธ็ฟ’[่™›ๆ“ฌ็’ฐๅขƒ](virtual-environments.md)ๆ™‚๏ผŒ้€™ไบ›่ณ‡่จŠๅฐ‡ๆœƒๅพˆๆœ‰็”จใ€‚ +็•ถๅญธ็ฟ’[่™›ๆ“ฌ็’ฐๅขƒ](virtual-environments.md){.internal-link target=_blank}ๆ™‚๏ผŒ้€™ไบ›่ณ‡่จŠๅฐ‡ๆœƒๅพˆๆœ‰็”จใ€‚ -## ็ต่ซ– +## ็ต่ซ– { #conclusion } ้€้Ž้€™ๅ€‹ๆ•™ๅญธ๏ผŒไฝ ๆ‡‰่ฉฒๅฐ**็’ฐๅขƒ่ฎŠๆ•ธ**ๆ˜ฏไป€้บผไปฅๅŠๅฆ‚ไฝ•ๅœจ Python ไธญไฝฟ็”จๅฎƒๅ€‘ๆœ‰ไบ†ๅŸบๆœฌ็š„ไบ†่งฃใ€‚ -ไฝ ไนŸๅฏไปฅๅœจ็’ฐๅขƒ่ฎŠๆ•ธ - ็ถญๅŸบ็™พ็ง‘ (Wikipedia for Environment Variable) ไธญไบ†่งฃๆ›ดๅคš้—œๆ–ผๅฎƒๅ€‘็š„่ณ‡่จŠใ€‚ +ไฝ ไนŸๅฏไปฅๅœจ ็’ฐๅขƒ่ฎŠๆ•ธ็š„็ถญๅŸบ็™พ็ง‘ๆข็›ฎ ไธญ้–ฑ่ฎ€ๆ›ดๅคšใ€‚ ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒ็’ฐๅขƒ่ฎŠๆ•ธ็š„็”จ้€”ๅ’Œ้ฉ็”จๆ€งๅฏ่ƒฝไธๆœƒ็ซ‹ๅˆป้กฏ็พใ€‚ไฝ†ๆ˜ฏๅœจ้–‹็™ผ้Ž็จ‹ไธญ๏ผŒๅฎƒๅ€‘ๆœƒๅœจ่จฑๅคšไธๅŒ็š„ๅ ดๆ™ฏไธญๅ‡บ็พ๏ผŒๅ› ๆญค็žญ่งฃๅฎƒๅ€‘ๆ˜ฏ้žๅธธๅฟ…่ฆ็š„ใ€‚ diff --git a/docs/zh-hant/docs/how-to/index.md b/docs/zh-hant/docs/how-to/index.md index db740140d0..6c9a8202c0 100644 --- a/docs/zh-hant/docs/how-to/index.md +++ b/docs/zh-hant/docs/how-to/index.md @@ -1,4 +1,4 @@ -# ไฝฟ็”จๆŒ‡ๅ— - ็ฏ„ไพ‹้›† +# ไฝฟ็”จๆŒ‡ๅ— - ็ฏ„ไพ‹้›† { #how-to-recipes } ๅœจ้€™่ฃก๏ผŒไฝ ๅฐ‡ๆœƒ็œ‹ๅˆฐ**ไธๅŒไธป้กŒ**็š„็ฏ„ไพ‹ๆˆ–ใ€Œๅฆ‚ไฝ•ไฝฟ็”จใ€็š„ๆŒ‡ๅ—ใ€‚ diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index 4390d96096..a31647f3cd 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -1,5 +1,11 @@ +# FastAPI { #fastapi } + + +

- FastAPI + FastAPI

FastAPI ๆก†ๆžถ๏ผŒ้ซ˜ๆ•ˆ่ƒฝ๏ผŒๆ˜“ๆ–ผๅญธ็ฟ’๏ผŒๅฟซ้€Ÿ้–‹็™ผ๏ผŒ้ฉ็”จๆ–ผ็”Ÿ็”ข็’ฐๅขƒ @@ -21,138 +27,140 @@ --- -**ๆ–‡ไปถ**๏ผš https://fastapi.tiangolo.com +**ๆ–‡ไปถ**๏ผš https://fastapi.tiangolo.com/zh-hant **็จ‹ๅผ็ขผ**๏ผš https://github.com/fastapi/fastapi --- -FastAPI ๆ˜ฏไธ€ๅ€‹็พไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ•ˆ่ƒฝ๏ผ‰็š„ web ๆก†ๆžถ๏ผŒ็”จๆ–ผ Python ไธฆๆŽก็”จๆจ™ๆบ– Python ๅž‹ๅˆฅๆ็คบใ€‚ +FastAPI ๆ˜ฏไธ€ๅ€‹็พไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ•ˆ่ƒฝ๏ผ‰็š„ Web ๆก†ๆžถ๏ผŒ็”จๆ–ผไปฅ Python ไธฆๅŸบๆ–ผๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๆ็คบไพ†ๆง‹ๅปบ APIใ€‚ ไธป่ฆ็‰น้ปžๅŒ…ๅซ๏ผš -- **ๅฟซ้€Ÿ**๏ผš ้žๅธธ้ซ˜็š„ๆ•ˆ่ƒฝ๏ผŒๅฏ่ˆ‡ **NodeJS** ๅ’Œ **Go** ๆ•ˆ่ƒฝ็›ธ็•ถ (ๆญธๅŠŸๆ–ผ Starlette and Pydantic)ใ€‚ [FastAPI ๆ˜ฏๆœ€ๅฟซ็š„ Python web ๆก†ๆžถไน‹ไธ€](#performance)ใ€‚ -- **ๆฅต้€Ÿ้–‹็™ผ**๏ผš ๆ้ซ˜้–‹็™ผๅŠŸ่ƒฝ็š„้€Ÿๅบฆ็ด„ 200% ่‡ณ 300%ใ€‚ \* -- **ๆ›ดๅฐ‘็š„ Bug**๏ผš ๆธ›ๅฐ‘็ด„ 40% ็š„ไบบ็‚บ๏ผˆ้–‹็™ผ่€…๏ผ‰ๅฐŽ่‡ด็š„้Œฏ่ชคใ€‚ \* -- **็›ด่ฆบ**๏ผš ๅ…ทๆœ‰ๅ‡บ่‰ฒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ่™•่™•้ƒฝๆœ‰่‡ชๅ‹•่ฃœๅ…จไปฅๆธ›ๅฐ‘ๅต้Œฏๆ™‚้–“ใ€‚ -- **็ฐกๅ–ฎ**๏ผš ่จญ่จˆไธŠๆ˜“ๆ–ผไฝฟ็”จๅ’Œๅญธ็ฟ’๏ผŒๅคงๅน…ๆธ›ๅฐ‘้–ฑ่ฎ€ๆ–‡ไปถ็š„ๆ™‚้–“ใ€‚ -- **็ฐกๆฝ”**๏ผš ๆœ€ๅฐๅŒ–็จ‹ๅผ็ขผ้‡่ค‡ๆ€งใ€‚ๅฏไปฅ้€š้ŽไธๅŒ็š„ๅƒๆ•ธ่ฒๆ˜Žไพ†ๅฏฆ็พๆ›ด่ฑๅฏŒ็š„ๅŠŸ่ƒฝ๏ผŒๅ’Œๆ›ดๅฐ‘็š„้Œฏ่ชคใ€‚ -- **็ฉฉๅฅ**๏ผš ็ซ‹ๅณ็ฒๅพ—็”Ÿ็”ข็ดšๅฏ็”จ็š„็จ‹ๅผ็ขผ๏ผŒ้‚„ๆœ‰่‡ชๅ‹•็”Ÿๆˆไบ’ๅ‹•ๅผๆ–‡ไปถใ€‚ -- **ๆจ™ๆบ–ๅŒ–**๏ผš ๅŸบๆ–ผ (ไธ”ๅฎŒๅ…จ็›ธๅฎนๆ–ผ) OpenAPIs ็š„็›ธ้—œๆจ™ๆบ–๏ผšOpenAPI๏ผˆไน‹ๅ‰่ขซ็จฑ็‚บ Swagger๏ผ‰ๅ’ŒJSON Schemaใ€‚ +* **ๅฟซ้€Ÿ**๏ผš้žๅธธ้ซ˜็š„ๆ•ˆ่ƒฝ๏ผŒๅฏ่ˆ‡ **NodeJS** ๅ’Œ **Go** ็›ธ็•ถ๏ผˆๆญธๅŠŸๆ–ผ Starlette ๅ’Œ Pydantic๏ผ‰ใ€‚[ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€](#performance)ใ€‚ +* **ๆฅต้€Ÿ้–‹็™ผ**๏ผš้–‹็™ผๅŠŸ่ƒฝ็š„้€Ÿๅบฆๅฏๆๅ‡็ด„ 200% ่‡ณ 300%ใ€‚* +* **ๆ›ดๅฐ‘็š„ Bug**๏ผšๆธ›ๅฐ‘็ด„ 40% ็š„ไบบ็‚บ๏ผˆ้–‹็™ผ่€…๏ผ‰้Œฏ่ชคใ€‚* +* **็›ด่ฆบ**๏ผšๅ…ทๆœ‰ๅ‡บ่‰ฒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ่™•่™•้ƒฝๆœ‰ ่‡ชๅ‹•่ฃœๅ…จใ€‚ๆ›ดๅฐ‘็š„ๅต้Œฏๆ™‚้–“ใ€‚ +* **็ฐกๅ–ฎ**๏ผš่จญ่จˆไธŠๆ˜“ๆ–ผไฝฟ็”จ่ˆ‡ๅญธ็ฟ’ใ€‚ๆ›ดๅฐ‘็š„่ฎ€ๆ–‡ไปถๆ™‚้–“ใ€‚ +* **็ฐกๆฝ”**๏ผšๆœ€ๅฐๅŒ–็จ‹ๅผ็ขผ้‡่ค‡ๆ€งใ€‚ๆฏๅ€‹ๅƒๆ•ธๅฎฃๅ‘Šๅฏๅธถไพ†ๅคšๅ€‹ๅŠŸ่ƒฝใ€‚ๆ›ดๅฐ‘็š„้Œฏ่ชคใ€‚ +* **็ฉฉๅฅ**๏ผš็ซ‹ๅณ็ฒๅพ—ๅฏๆŠ•ๅ…ฅ็”Ÿ็”ข็š„็จ‹ๅผ็ขผ๏ผŒไธฆ่‡ชๅ‹•็”Ÿๆˆไบ’ๅ‹•ๅผๆ–‡ไปถใ€‚ +* **ๆจ™ๆบ–ๅŒ–**๏ผšๅŸบๆ–ผ๏ผˆไธ”ๅฎŒๅ…จ็›ธๅฎนๆ–ผ๏ผ‰API ็š„้–‹ๆ”พๆจ™ๆบ–๏ผšOpenAPI๏ผˆไน‹ๅ‰็จฑ็‚บ Swagger๏ผ‰ๅ’Œ JSON Schemaใ€‚ -\* ๅŸบๆ–ผๅ…ง้ƒจ้–‹็™ผๅœ˜้šŠๅœจๅปบ็ซ‹็”Ÿ็”ขๆ‡‰็”จ็จ‹ๅผๆ™‚็š„ๆธฌ่ฉฆ้ ไผฐใ€‚ +* ๅŸบๆ–ผๅ…ง้ƒจ้–‹็™ผๅœ˜้šŠๅœจๅปบ็ซ‹็”Ÿ็”ขๆ‡‰็”จ็จ‹ๅผๆ™‚็š„ๆธฌ่ฉฆ้ ไผฐใ€‚ -## ่ดŠๅŠฉ +## ่ดŠๅŠฉ { #sponsors } -{% if sponsors %} +### ๅŸบ็Ÿณ่ดŠๅŠฉๅ•† { #keystone-sponsor } + +{% for sponsor in sponsors.keystone -%} + +{% endfor -%} + +### ้‡‘็ดš่ˆ‡้Š€็ดš่ดŠๅŠฉๅ•† { #gold-and-silver-sponsors } + {% for sponsor in sponsors.gold -%} {% endfor -%} {%- for sponsor in sponsors.silver -%} {% endfor %} -{% endif %} -ๅ…ถไป–่ดŠๅŠฉๅ•† +ๅ…ถไป–่ดŠๅŠฉๅ•† -## ่ฉ•ๅƒน +## ่ฉ•ๅƒน { #opinions } -"_[...] ่ฟ‘ๆœŸๅคง้‡็š„ไฝฟ็”จ **FastAPI**ใ€‚ [...] ็›ฎๅ‰ๆญฃๅœจ่จˆ็•ซๅœจ**ๅพฎ่ปŸ**ๅœ˜้šŠ็š„**ๆฉŸๅ™จๅญธ็ฟ’**ๆœๅ‹™ไธญๅฐŽๅ…ฅใ€‚ๅ…ถไธญไธ€ไบ›ๆญฃๅœจๆ•ดๅˆๅˆฐๆ ธๅฟƒ็š„ **Windows** ็”ขๅ“ๅ’Œไธ€ไบ› **Office** ็”ขๅ“ใ€‚_" +"_[...] ่ฟ‘ๆœŸๅคง้‡ไฝฟ็”จ **FastAPI**ใ€‚[...] ๆˆ‘ๅฏฆ้š›ไธŠๆ‰“็ฎ—ๅœจๆˆ‘ๅœจ**ๅพฎ่ปŸ**ๅœ˜้šŠ็š„ๆ‰€ๆœ‰**ๆฉŸๅ™จๅญธ็ฟ’**ๆœๅ‹™ไธŠไฝฟ็”จๅฎƒใ€‚ๅ…ถไธญไธ€ไบ›ๆญฃๅœจๆ•ดๅˆๅˆฐๆ ธๅฟƒ็š„ **Windows** ็”ขๅ“๏ผŒไปฅๅŠไธ€ไบ› **Office** ็”ขๅ“ใ€‚_"

Kabir Khan - Microsoft (ref)
--- -"_ๆˆ‘ๅ€‘ไฝฟ็”จ **FastAPI** ไพ†ๅปบ็ซ‹็”ข็”Ÿ**้ ๆธฌ**็ตๆžœ็š„ **REST** ไผบๆœๅ™จใ€‚ [for Ludwig]_" +"_ๆˆ‘ๅ€‘ๆŽก็”จไบ† **FastAPI** ๅ‡ฝๅผๅบซไพ†ๅ•Ÿๅ‹•ไธ€ๅ€‹ **REST** ไผบๆœๅ™จ๏ผŒไพ›ๆŸฅ่ฉขไปฅๅ–ๅพ—**้ ๆธฌ**ใ€‚[for Ludwig]_"
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"_**Netflix** ๅพˆๆฆฎๅนธๅœฐๅฎฃๅธƒ้–‹ๆบ**ๅฑๆฉŸ็ฎก็†**ๅ”่ชฟๆก†ๆžถ๏ผš **Dispatch**! [ๆ˜ฏไฝฟ็”จ **FastAPI** ๅปบๆง‹]_" +"_**Netflix** ๅพˆ้ซ˜่ˆˆๅฎฃๅธƒๆˆ‘ๅ€‘็š„**ๅฑๆฉŸ็ฎก็†**ๅ”่ชฟๆก†ๆžถ **Dispatch** ้–‹ๆบ๏ผ[ไฝฟ็”จ **FastAPI** ๅปบๆง‹]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_ๆˆ‘ๅฐ **FastAPI** ่ˆˆๅฅฎๅพ—ไธๅพ—ไบ†ใ€‚ๅฎƒๅคชๆœ‰่ถฃไบ†๏ผ_" +"_ๆˆ‘ๅฐ **FastAPI** ่ˆˆๅฅฎๅพ—ไธๅพ—ไบ†ใ€‚่ถ…ๅฅฝ็Žฉ๏ผ_" -
Brian Okken - Python Bytes podcast host (ref)
+
Brian Okken - Python Bytes podcast ไธปๆŒไบบ (ref)
--- -"_่€ๅฏฆ่ชช๏ผŒไฝ ๅปบ้€ ็š„ๆฑ่ฅฟ็œ‹่ตทไพ†้žๅธธๅ …ๅ›บๅ’Œ็ฒพ็ทปใ€‚ๅœจๅพˆๅคšๆ–น้ข๏ผŒ้€™ๅฐฑๆ˜ฏๆˆ‘ๆƒณ่ฆ็š„๏ผŒ็œ‹ๅˆฐๆœ‰ไบบๅปบ้€ ๅฎƒ็œŸ็š„ๅพˆ้ผ“่ˆžไบบๅฟƒใ€‚_" +"_่€ๅฏฆ่ชช๏ผŒไฝ ๅ€‘ๅš็š„็œ‹่ตทไพ†้žๅธธ็ฉฉๅฅๅˆ็ฒพ็ทปใ€‚ๅพˆๅคšๆ–น้ข้ƒฝๆญฃๆ˜ฏๆˆ‘ๅธŒๆœ› **Hug** ๆˆ็‚บ็š„ๆจฃๅญโ€”โ€”็œ‹ๅˆฐๆœ‰ไบบๆŠŠๅฎƒๅปบๅ‡บไพ†็œŸ็š„ๅพˆ้ผ“่ˆžไบบๅฟƒใ€‚_" -
Timothy Crosley - Hug creator (ref)
+
Timothy Crosley - Hug ๅ‰ตไฝœ่€… (ref)
--- -"_ๅฆ‚ๆžœๆ‚จๆƒณๅญธ็ฟ’ไธ€็จฎ็”จๆ–ผๆง‹ๅปบ REST API ็š„**็พไปฃๆก†ๆžถ**๏ผŒไธ่ƒฝ้Œฏ้Ž **FastAPI** [...] ๅฎƒ้žๅธธๅฟซ้€Ÿใ€ไธ”ๆ˜“ๆ–ผไฝฟ็”จๅ’Œๅญธ็ฟ’ [...]_" +"_ๅฆ‚ๆžœไฝ ๆƒณๅญธไธ€ๅ€‹็”จๆ–ผๆง‹ๅปบ REST API ็š„**็พไปฃๆก†ๆžถ**๏ผŒ็œ‹็œ‹ **FastAPI** [...] ๅฎƒๅพˆๅฟซใ€ๆ˜“็”จใ€ไนŸๅฎนๆ˜“ๅญธ็ฟ’ [...]_" -"_ๆˆ‘ๅ€‘็š„ **APIs** ๅทฒ็ถ“ๆ”น็”จ **FastAPI** [...] ๆˆ‘ๆƒณไฝ ๆœƒๅ–œๆญกๅฎƒ [...]_" +"_ๆˆ‘ๅ€‘็š„ **API** ๅทฒ็ถ“ๆ”น็”จ **FastAPI** [...] ๆˆ‘ๆƒณไฝ ๆœƒๅ–œๆญกๅฎƒ [...]_" -
Ines Montani - Matthew Honnibal - Explosion AI ๅ‰ต่พฆไบบ - spaCy creators (ref) - (ref)
+
Ines Montani - Matthew Honnibal - Explosion AI ๅ‰ต่พฆไบบ - spaCy ๅ‰ตไฝœ่€… (ref) - (ref)
--- -"_ๅฆ‚ๆžœๆœ‰ไบบๆƒณ่ฆๅปบ็ซ‹ไธ€ๅ€‹็”Ÿ็”ข็’ฐๅขƒ็š„ Python API๏ผŒๆˆ‘ๅผท็ƒˆๆŽจ่–ฆ **FastAPI**๏ผŒๅฎƒ**่จญ่จˆ็ฒพ็พŽ**๏ผŒ**ไฝฟ็”จ็ฐกๅ–ฎ**ไธ”**้ซ˜ๅบฆๅฏๆ“ดๅ……**๏ผŒๅฎƒๅทฒๆˆ็‚บๆˆ‘ๅ€‘ API ๅ„ชๅ…ˆ้–‹็™ผ็ญ–็•ฅไธญ็š„**้—œ้ต็ต„ไปถ**๏ผŒไธฆไธ”้ฉ…ๅ‹•ไบ†่จฑๅคš่‡ชๅ‹•ๅŒ–ๆœๅ‹™๏ผŒไพ‹ๅฆ‚ๆˆ‘ๅ€‘็š„ Virtual TAC Engineerใ€‚_" +"_ๅฆ‚ๆžœๆœ‰ไบบๆƒณ่ฆๅปบ็ซ‹ไธ€ๅ€‹ๅฏๆŠ•ๅ…ฅ็”Ÿ็”ข็š„ Python API๏ผŒๆˆ‘ๅผท็ƒˆๆŽจ่–ฆ **FastAPI**ใ€‚ๅฎƒ**่จญ่จˆ็ฒพ็พŽ**ใ€**ไฝฟ็”จ็ฐกๅ–ฎ**ไธ”**้ซ˜ๅบฆๅฏๆ“ดๅ……**๏ผŒๅทฒๆˆ็‚บๆˆ‘ๅ€‘ API ๅ„ชๅ…ˆ้–‹็™ผ็ญ–็•ฅไธญ็š„**้—œ้ต็ต„ไปถ**๏ผŒๆŽจๅ‹•ไบ†่จฑๅคš่‡ชๅ‹•ๅŒ–่ˆ‡ๆœๅ‹™๏ผŒไพ‹ๅฆ‚ๆˆ‘ๅ€‘็š„ Virtual TAC Engineerใ€‚_"
Deon Pillsbury - Cisco (ref)
--- -## **Typer**๏ผŒๅ‘ฝไปคๅˆ—ไธญ็š„ FastAPI - - +## FastAPI ่ฟทไฝ ็ด€้Œ„็‰‡ { #fastapi-mini-documentary } -ๅฆ‚ๆžœไฝ ไธๆ˜ฏๅœจ้–‹็™ผ็ถฒ้  API๏ผŒ่€Œๆ˜ฏๆญฃๅœจ้–‹็™ผไธ€ๅ€‹ๅœจ็ต‚็ซฏๆฉŸไธญ้‹่กŒ็š„ๅ‘ฝไปคๅˆ—ๆ‡‰็”จ็จ‹ๅผ๏ผŒไธๅฆจๅ˜—่ฉฆ **Typer**ใ€‚ +ๅœจ 2025 ๅนดๅบ•็™ผๅธƒไบ†ไธ€ๆ”ฏ FastAPI ่ฟทไฝ ็ด€้Œ„็‰‡๏ผŒไฝ ๅฏไปฅๅœจ็ทšไธŠ่ง€็œ‹๏ผš -**Typer** ๆ˜ฏ FastAPI ็š„ๅฐๅ…„ๅผŸใ€‚ไป–็ซ‹ๅฟ—ๆˆ็‚บๅ‘ฝไปคๅˆ—็š„ **FastAPI**ใ€‚ โŒจ๏ธ ๐Ÿš€ +FastAPI Mini Documentary -## ๅฎ‰่ฃ้œ€ๆฑ‚ +## **Typer**๏ผŒๅ‘ฝไปคๅˆ—็š„ FastAPI { #typer-the-fastapi-of-clis } -FastAPI ๆ˜ฏ็ซ™ๅœจไปฅไธ‹ๅทจไบบ็š„่‚ฉ่†€ไธŠ๏ผš + -- Starlette ่ฒ ่ฒฌ็ถฒ้ ็š„้ƒจๅˆ† -- Pydantic ่ฒ ่ฒฌ่ณ‡ๆ–™็š„้ƒจๅˆ† +ๅฆ‚ๆžœไฝ ไธๆ˜ฏๅœจๅš Web API๏ผŒ่€Œๆ˜ฏ่ฆๅปบ็ซ‹ไธ€ๅ€‹ๅœจ็ต‚็ซฏๆฉŸไธญไฝฟ็”จ็š„ CLI ๆ‡‰็”จ็จ‹ๅผ๏ผŒๅฏไปฅ็œ‹็œ‹ **Typer**ใ€‚ -## ๅฎ‰่ฃ +**Typer** ๆ˜ฏ FastAPI ็š„ๅฐ่€ๅผŸใ€‚ไป–็ซ‹ๅฟ—ๆˆ็‚บๅ‘ฝไปคๅˆ—ไธ–็•Œ็š„ **FastAPI**ใ€‚โŒจ๏ธ ๐Ÿš€ -
+## ้œ€ๆฑ‚ { #requirements } -```console -$ pip install fastapi +FastAPI ๆ˜ฏ็ซ™ๅœจไปฅไธ‹ๅทจไบบ็š„่‚ฉ่†€ไธŠ๏ผš ----> 100% -``` +* Starlette ่ฒ ่ฒฌ Web ้ƒจๅˆ†ใ€‚ +* Pydantic ่ฒ ่ฒฌ่ณ‡ๆ–™้ƒจๅˆ†ใ€‚ -
+## ๅฎ‰่ฃ { #installation } -ไฝ ๅŒๆ™‚ไนŸๆœƒ้œ€่ฆ ASGI ไผบๆœๅ™จ็”จๆ–ผ็”Ÿ็”ข็’ฐๅขƒ๏ผŒๅƒๆ˜ฏ Uvicorn ๆˆ– Hypercornใ€‚ +ๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ FastAPI๏ผš
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
-## ็ฏ„ไพ‹ +**ๆณจๆ„**๏ผš่ซ‹ๅ‹™ๅฟ…ๅฐ‡ `"fastapi[standard]"` ็”จๅผ•่™ŸๅŒ…่ตทไพ†๏ผŒไปฅ็ขบไฟๅœจๆ‰€ๆœ‰็ต‚็ซฏๆฉŸไธญ้ƒฝ่ƒฝๆญฃๅธธ้‹ไฝœใ€‚ -### ๅปบ็ซ‹ +## ็ฏ„ไพ‹ { #example } -- ๅปบ็ซ‹ไธ€ๅ€‹ python ๆช”ๆกˆ `main.py`๏ผŒไธฆๅฏซๅ…ฅไปฅไธ‹็จ‹ๅผ็ขผ๏ผš +### ๅปบ็ซ‹ { #create-it } -```Python -from typing import Union +ๅปบ็ซ‹ๆช”ๆกˆ `main.py`๏ผŒๅ…งๅฎนๅฆ‚ไธ‹๏ผš +```Python from fastapi import FastAPI app = FastAPI() @@ -164,18 +172,16 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ```
-ๆˆ–ๅฏไปฅไฝฟ็”จ async def... - -ๅฆ‚ๆžœไฝ ็š„็จ‹ๅผไฝฟ็”จ `async` / `await`๏ผŒ่ซ‹ไฝฟ็”จ `async def`๏ผš +ๆˆ–ไฝฟ็”จ async def... -```Python hl_lines="9 14" -from typing import Union +ๅฆ‚ๆžœไฝ ็š„็จ‹ๅผ็ขผไฝฟ็”จ `async` / `await`๏ผŒ่ซ‹ไฝฟ็”จ `async def`๏ผš +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -187,28 +193,41 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` **ๆณจๆ„**๏ผš -ๅฆ‚ๆžœไฝ ไธ็Ÿฅ้“ๆ˜ฏๅฆๆœƒ็”จๅˆฐ๏ผŒๅฏไปฅๆŸฅ็œ‹ _"In a hurry?"_ ็ซ ็ฏ€ไธญ๏ผŒ้—œๆ–ผ `async` ๅ’Œ `await` ็š„้ƒจๅˆ†ใ€‚ +ๅฆ‚ๆžœไฝ ไธ็ขบๅฎš๏ผŒ่ซ‹ๆŸฅ็œ‹ๆ–‡ไปถไธญ _"In a hurry?"_ ็ซ ็ฏ€็š„ `async` ่ˆ‡ `await`ใ€‚
-### ้‹่กŒ +### ้‹่กŒ { #run-it } ไฝฟ็”จไปฅไธ‹ๆŒ‡ไปค้‹่กŒไผบๆœๅ™จ๏ผš
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ + โ”‚ โ”‚ + โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ + โ”‚ โ”‚ + โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ + โ”‚ โ”‚ + โ”‚ Running in development mode, for production use: โ”‚ + โ”‚ โ”‚ + โ”‚ fastapi run โ”‚ + โ”‚ โ”‚ + โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -216,21 +235,21 @@ INFO: Application startup complete.
-้—œๆ–ผๆŒ‡ไปค uvicorn main:app --reload... +้—œๆ–ผๆŒ‡ไปค fastapi dev main.py... + +ๆŒ‡ไปค `fastapi dev` ๆœƒ่ฎ€ๅ–ไฝ ็š„ `main.py`๏ผŒๅตๆธฌๅ…ถไธญ็š„ **FastAPI** ๆ‡‰็”จ๏ผŒไธฆไฝฟ็”จ Uvicorn ๅ•Ÿๅ‹•ไผบๆœๅ™จใ€‚ -่ฉฒๆŒ‡ไปค `uvicorn main:app` ๆŒ‡็š„ๆ˜ฏ๏ผš +้ ่จญๆƒ…ๆณไธ‹๏ผŒ`fastapi dev` ๆœƒๅœจๆœฌๆฉŸ้–‹็™ผๆ™‚ๅ•Ÿ็”จ่‡ชๅ‹•้‡ๆ–ฐ่ผ‰ๅ…ฅใ€‚ -- `main`๏ผš`main.py` ๆช”ๆกˆ๏ผˆไธ€ๅ€‹ python ็š„ "ๆจก็ต„"๏ผ‰ใ€‚ -- `app`๏ผšๅœจ `main.py` ๆช”ๆกˆไธญ๏ผŒไฝฟ็”จ `app = FastAPI()` ๅปบ็ซ‹็š„็‰ฉไปถใ€‚ -- `--reload`๏ผš็จ‹ๅผ็ขผๆ›ดๆ”นๅพŒๆœƒ่‡ชๅ‹•้‡ๆ–ฐๅ•Ÿๅ‹•๏ผŒ่ซ‹ๅƒ…ๅœจ้–‹็™ผๆ™‚ไฝฟ็”จๆญคๅƒๆ•ธใ€‚ +ๅฏๅœจ FastAPI CLI ๆ–‡ไปถไธญ้–ฑ่ฎ€ๆ›ดๅคš่ณ‡่จŠใ€‚
-### ๆชขๆŸฅ +### ๆชขๆŸฅ { #check-it } ไฝฟ็”จ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/items/5?q=somequeryใ€‚ -ไฝ ๅฐ‡ๆœƒ็œ‹ๅˆฐไปฅไธ‹็š„ JSON ๅ›žๆ‡‰๏ผš +ไฝ ๅฐ‡ๆœƒ็œ‹ๅˆฐไปฅไธ‹ JSON ๅ›žๆ‡‰๏ผš ```JSON {"item_id": 5, "q": "somequery"} @@ -238,36 +257,34 @@ INFO: Application startup complete. ไฝ ๅทฒ็ถ“ๅปบ็ซ‹ไบ†ไธ€ๅ€‹ๅ…ทๆœ‰ไปฅไธ‹ๅŠŸ่ƒฝ็š„ API๏ผš -- ้€้Ž่ทฏๅพ‘ `/` ๅ’Œ `/items/{item_id}` ๆŽฅๅ— HTTP ่ซ‹ๆฑ‚ใ€‚ -- ไปฅไธŠ่ทฏ็ถ“้ƒฝๆŽฅๅ— `GET` ่ซ‹ๆฑ‚๏ผˆไนŸ่ขซ็จฑ็‚บ HTTP _ๆ–นๆณ•_๏ผ‰ใ€‚ -- ่ทฏๅพ‘ `/items/{item_id}` ๆœ‰ไธ€ๅ€‹ `int` ๅž‹ๅˆฅ็š„ `item_id` ๅƒๆ•ธใ€‚ -- ่ทฏๅพ‘ `/items/{item_id}` ๆœ‰ไธ€ๅ€‹ `str` ๅž‹ๅˆฅ็š„ๆŸฅ่ฉขๅƒๆ•ธ `q`ใ€‚ +* ้€้Ž่ทฏๅพ‘ `/` ๅ’Œ `/items/{item_id}` ๆŽฅๅ— HTTP ่ซ‹ๆฑ‚ใ€‚ +* ไปฅไธŠๅ…ฉๅ€‹่ทฏๅพ‘้ƒฝๆŽฅๅ— `GET` ๆ“ไฝœ๏ผˆไนŸ่ขซ็จฑ็‚บ HTTP _ๆ–นๆณ•_๏ผ‰ใ€‚ +* ่ทฏๅพ‘ `/items/{item_id}` ๆœ‰ไธ€ๅ€‹ `int` ๅž‹ๅˆฅ็š„่ทฏๅพ‘ๅƒๆ•ธ `item_id`ใ€‚ +* ่ทฏๅพ‘ `/items/{item_id}` ๆœ‰ไธ€ๅ€‹ๅฏ้ธ็š„ `str` ๆŸฅ่ฉขๅƒๆ•ธ `q`ใ€‚ -### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ +### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ { #interactive-api-docs } -ไฝฟ็”จ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/docsใ€‚ +ๆŽฅ่‘—ๅ‰ๅพ€ http://127.0.0.1:8000/docsใ€‚ -ไฝ ๆœƒ็œ‹ๅˆฐ่‡ชๅ‹•็”Ÿๆˆ็š„ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ๏ผˆ็”ฑ Swagger UI ็”Ÿๆˆ๏ผ‰๏ผš +ไฝ ๆœƒ็œ‹ๅˆฐ่‡ชๅ‹•็”Ÿๆˆ็š„ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ๏ผˆ็”ฑ Swagger UI ๆไพ›๏ผ‰๏ผš ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ReDoc API ๆ–‡ไปถ +### ๆ›ฟไปฃ API ๆ–‡ไปถ { #alternative-api-docs } -ไฝฟ็”จ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/redocใ€‚ +็พๅœจๅ‰ๅพ€ http://127.0.0.1:8000/redocใ€‚ -ไฝ ๅฐ‡็œ‹ๅˆฐ ReDoc ๆ–‡ไปถ (็”ฑ ReDoc ็”Ÿๆˆ)๏ผš +ไฝ ๆœƒ็œ‹ๅˆฐๅฆไธ€็จฎ่‡ชๅ‹•ๆ–‡ไปถ๏ผˆ็”ฑ ReDoc ๆไพ›๏ผ‰๏ผš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## ็ฏ„ไพ‹ๅ‡็ดš +## ็ฏ„ไพ‹ๅ‡็ดš { #example-upgrade } -็พๅœจ็นผ็บŒไฟฎๆ”น `main.py` ๆช”ๆกˆ๏ผŒไพ†ๆŽฅๆ”ถไธ€ๅ€‹ๅธถๆœ‰ body ็š„ `PUT` ่ซ‹ๆฑ‚ใ€‚ +็พๅœจไฟฎๆ”น `main.py` ๆช”ๆกˆ๏ผŒไฝฟๅ…ถ่ƒฝๅพž `PUT` ่ซ‹ๆฑ‚ๆŽฅๆ”ถ bodyใ€‚ -ๆˆ‘ๅ€‘ไฝฟ็”จ Pydantic ไพ†ไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅ่ฒๆ˜Ž่ซ‹ๆฑ‚ใ€‚ - -```Python hl_lines="4 9-12 25-27" -from typing import Union +ๅคš่™งไบ† Pydantic๏ผŒไฝ ๅฏไปฅ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅไพ†ๅฎฃๅ‘Š bodyใ€‚ +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -277,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -286,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -295,43 +312,43 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -ไผบๆœๅ™จๅฐ‡่‡ชๅ‹•้‡ๆ–ฐ่ผ‰ๅ…ฅ๏ผˆๅ› ็‚บๅœจไธŠไธ€ๆญฅไธญ๏ผŒไฝ ๅ‘ `uvicorn` ๆŒ‡ไปคๆทปๅŠ ไบ† `--reload` ็š„้ธ้ …๏ผ‰ใ€‚ +`fastapi dev` ไผบๆœๅ™จๆ‡‰ๆœƒ่‡ชๅ‹•้‡ๆ–ฐ่ผ‰ๅ…ฅใ€‚ -### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถๅ‡็ดš +### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถๅ‡็ดš { #interactive-api-docs-upgrade } -ไฝฟ็”จ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/docsใ€‚ +ๅ‰ๅพ€ http://127.0.0.1:8000/docsใ€‚ -- ไบ’ๅ‹•ๅผ API ๆ–‡ไปถๆœƒ่‡ชๅ‹•ๆ›ดๆ–ฐ๏ผŒไธฆๅŠ ๅ…ฅๆ–ฐ็š„ body ่ซ‹ๆฑ‚๏ผš +* ไบ’ๅ‹•ๅผ API ๆ–‡ไปถๆœƒ่‡ชๅ‹•ๆ›ดๆ–ฐ๏ผŒๅŒ…ๅซๆ–ฐ็š„ body๏ผš ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -- ้ปžๆ“Š "Try it out" ๆŒ‰้ˆ•๏ผŒ ไฝ ๅฏไปฅๅกซๅฏซๅƒๆ•ธไธฆ็›ดๆŽฅ่ˆ‡ API ไบ’ๅ‹•๏ผš +* ้ปžๆ“Šใ€ŒTry it outใ€ๆŒ‰้ˆ•๏ผŒไฝ ๅฏไปฅๅกซๅฏซๅƒๆ•ธไธฆ็›ดๆŽฅ่ˆ‡ API ไบ’ๅ‹•๏ผš ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -- ็„ถๅพŒ้ปžๆ“Š "Execute" ๆŒ‰้ˆ•๏ผŒไฝฟ็”จ่€…ไป‹้ขๅฐ‡ๆœƒๅ‘ API ็™ผ้€่ซ‹ๆฑ‚๏ผŒไธฆๅฐ‡็ตๆžœ้กฏ็คบๅœจ่žขๅน•ไธŠ๏ผš +* ็„ถๅพŒ้ปžๆ“Šใ€ŒExecuteใ€ๆŒ‰้ˆ•๏ผŒไฝฟ็”จ่€…ไป‹้ขๆœƒ่ˆ‡ไฝ ็š„ API ๆบ้€šใ€้€ๅ‡บๅƒๆ•ธใ€ๅ–ๅพ—็ตๆžœไธฆ้กฏ็คบๅœจ่žขๅน•ไธŠ๏ผš ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) -### ReDoc API ๆ–‡ไปถๅ‡็ดš +### ๆ›ฟไปฃ API ๆ–‡ไปถๅ‡็ดš { #alternative-api-docs-upgrade } -ไฝฟ็”จ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/redocใ€‚ +็พๅœจๅ‰ๅพ€ http://127.0.0.1:8000/redocใ€‚ -- ReDoc API ๆ–‡ไปถๆœƒ่‡ชๅ‹•ๆ›ดๆ–ฐ๏ผŒไธฆๅŠ ๅ…ฅๆ–ฐ็š„ๅƒๆ•ธๅ’Œ body ่ซ‹ๆฑ‚๏ผš +* ๆ›ฟไปฃๆ–‡ไปถไนŸๆœƒๅๆ˜ ๆ–ฐ็š„ๆŸฅ่ฉขๅƒๆ•ธ่ˆ‡ body๏ผš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ็ธฝ็ต +### ็ธฝ็ต { #recap } -็ธฝ็ตไพ†่ชช๏ผŒ ไฝ ๅฐฑๅƒๅฎฃๅ‘Šๅ‡ฝๅผ็š„ๅƒๆ•ธๅž‹ๅˆฅไธ€ๆจฃ๏ผŒๅชๅฎฃๅ‘Šไบ†ไธ€ๆฌก่ซ‹ๆฑ‚ๅƒๆ•ธๅ’Œ่ซ‹ๆฑ‚ไธป้ซ”ๅƒๆ•ธ็ญ‰ๅž‹ๅˆฅใ€‚ +็ธฝ็ตไพ†่ชช๏ผŒไฝ ๅช้œ€ๅœจๅ‡ฝๅผๅƒๆ•ธไธญ**ไธ€ๆฌก**ๅฎฃๅ‘Šๅƒๆ•ธใ€body ็ญ‰็š„ๅž‹ๅˆฅใ€‚ -ไฝ ไฝฟ็”จ Python ๆจ™ๆบ–ๅž‹ๅˆฅไพ†ๅฎŒๆˆ่ฒๆ˜Žใ€‚ +ไฝ ไฝฟ็”จ็š„ๆ˜ฏ็พไปฃๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅใ€‚ -ไฝ ไธ้œ€่ฆๅญธ็ฟ’ๆ–ฐ็š„่ชžๆณ•ใ€้กžๅˆฅใ€ๆ–นๆณ•ๆˆ–ๅ‡ฝๅผๅบซ็ญ‰็ญ‰ใ€‚ +ไฝ ไธ้œ€่ฆๅญธๆ–ฐ็š„่ชžๆณ•ใ€็‰นๅฎšๅ‡ฝๅผๅบซ็š„ๆ–นๆณ•ๆˆ–้กžๅˆฅ๏ผŒ็ญ‰็ญ‰ใ€‚ -ๅช้œ€่ฆไฝฟ็”จ **Python ไปฅไธŠ็š„็‰ˆๆœฌ**ใ€‚ +ๅฐฑ็”จๆจ™ๆบ–็š„ **Python**ใ€‚ -่ˆ‰ๅ€‹็ฏ„ไพ‹๏ผŒๆฏ”ๅฆ‚ๅฎฃๅ‘Š int ็š„ๅž‹ๅˆฅ๏ผš +ไพ‹ๅฆ‚๏ผŒๅฐๆ–ผไธ€ๅ€‹ `int`๏ผš ```Python item_id: int @@ -343,126 +360,200 @@ item_id: int item: Item ``` -ๅœจ้€ฒ่กŒไธ€ๆฌกๅฎฃๅ‘ŠๅพŒ๏ผŒไฝ ๅฐ‡็ฒๅพ—๏ผš - -- ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผš - - ่‡ชๅ‹•่ฃœๅ…จ - - ๅž‹ๅˆฅๆชขๆŸฅ -- ่ณ‡ๆ–™้ฉ—่ญ‰๏ผš - - ้ฉ—่ญ‰ๅคฑๆ•—ๆ™‚่‡ชๅ‹•็”Ÿๆˆๆธ…ๆฅš็š„้Œฏ่ชค่จŠๆฏ - - ๅฏ้ฉ—่ญ‰ๅคšๅฑคๅทข็‹€็š„ JSON ็‰ฉไปถ -- ่ฝ‰ๆ›่ผธๅ…ฅ็š„่ณ‡ๆ–™๏ผš ่ฝ‰ๆ›ไพ†่‡ช็ถฒ่ทฏ่ซ‹ๆฑ‚ๅˆฐ Python ่ณ‡ๆ–™ๅž‹ๅˆฅใ€‚ๅŒ…ๅซไปฅไธ‹ๆ•ธๆ“š๏ผš - - JSON - - ่ทฏๅพ‘ๅƒๆ•ธ - - ๆŸฅ่ฉขๅƒๆ•ธ - - Cookies - - ่ซ‹ๆฑ‚ๆจ™้ ญ - - ่กจๅ–ฎ - - ๆ–‡ไปถ -- ่ฝ‰ๆ›่ผธๅ‡บ็š„่ณ‡ๆ–™๏ผš ่ฝ‰ๆ› Python ่ณ‡ๆ–™ๅž‹ๅˆฅๅˆฐ็ถฒ่ทฏๅ‚ณ่ผธ็š„ JSON๏ผš - - ่ฝ‰ๆ› Python ๅž‹ๅˆฅ (`str`ใ€ `int`ใ€ `float`ใ€ `bool`ใ€ `list` ็ญ‰) - - `datetime` ็‰ฉไปถ - - `UUID` ็‰ฉไปถ - - ๆ•ธๆ“šๆจกๅž‹ - - ...้‚„ๆœ‰ๅ…ถไป–ๆ›ดๅคš -- ่‡ชๅ‹•็”Ÿๆˆ็š„ API ๆ–‡ไปถ๏ผŒๅŒ…ๅซ 2 ็จฎไธๅŒ็š„ไฝฟ็”จไป‹้ข๏ผš - - Swagger UI - - ReDoc +โ€ฆ้€้Žไธ€ๆฌกๅฎฃๅ‘Š๏ผŒไฝ ๅฐ‡็ฒๅพ—๏ผš + +* ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒๅŒ…ๆ‹ฌ๏ผš + * ่‡ชๅ‹•่ฃœๅ…จใ€‚ + * ๅž‹ๅˆฅๆชขๆŸฅใ€‚ +* ่ณ‡ๆ–™้ฉ—่ญ‰๏ผš + * ็•ถ่ณ‡ๆ–™็„กๆ•ˆๆ™‚๏ผŒ่‡ชๅ‹•ไธ”ๆธ…ๆฅš็š„้Œฏ่ชคใ€‚ + * ๅณไฝฟๆ˜ฏๆทฑๅบฆๅทข็‹€็š„ JSON ็‰ฉไปถไนŸ่ƒฝ้ฉ—่ญ‰ใ€‚ +* ่ผธๅ…ฅ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž็ถฒ่ทฏ่ฎ€ๅ…ฅๅˆฐ Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅใ€‚ๅŒ…ๅซ๏ผš + * JSONใ€‚ + * ่ทฏๅพ‘ๅƒๆ•ธใ€‚ + * ๆŸฅ่ฉขๅƒๆ•ธใ€‚ + * Cookiesใ€‚ + * ๆจ™้ ญใ€‚ + * ่กจๅ–ฎใ€‚ + * ๆช”ๆกˆใ€‚ +* ่ผธๅ‡บ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅ่ฝ‰ๆ›็‚บ็ถฒ่ทฏ่ณ‡ๆ–™๏ผˆJSON๏ผ‰๏ผš + * ่ฝ‰ๆ› Python ๅž‹ๅˆฅ๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ็ญ‰๏ผ‰ใ€‚ + * `datetime` ็‰ฉไปถใ€‚ + * `UUID` ็‰ฉไปถใ€‚ + * ่ณ‡ๆ–™ๅบซๆจกๅž‹ใ€‚ + * ...้‚„ๆœ‰ๆ›ดๅคšใ€‚ +* ่‡ชๅ‹•็”Ÿๆˆ็š„ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ๏ผŒๅŒ…ๅซ 2 ็จฎๆ›ฟไปฃ็š„ไฝฟ็”จ่€…ไป‹้ข๏ผš + * Swagger UIใ€‚ + * ReDocใ€‚ --- -ๅ›žๅˆฐๅ‰้ข็š„็š„็จ‹ๅผ็ขผ็ฏ„ไพ‹๏ผŒ**FastAPI** ้‚„ๆœƒ๏ผš - -- ้ฉ—่ญ‰ `GET` ๅ’Œ `PUT` ่ซ‹ๆฑ‚่ทฏๅพ‘ไธญๆ˜ฏๅฆๅŒ…ๅซ `item_id`ใ€‚ -- ้ฉ—่ญ‰ `GET` ๅ’Œ `PUT` ่ซ‹ๆฑ‚ไธญ็š„ `item_id` ๆ˜ฏๅฆๆ˜ฏ `int` ๅž‹ๅˆฅใ€‚ - - ๅฆ‚ๆžœ้ฉ—่ญ‰ๅคฑๆ•—๏ผŒๅฐ‡ๆœƒ่ฟ”ๅ›žๆธ…ๆฅšๆœ‰็”จ็š„้Œฏ่ชค่จŠๆฏใ€‚ -- ๆŸฅ็œ‹ `GET` ่ซ‹ๆฑ‚ไธญๆ˜ฏๅฆๆœ‰ๅ‘ฝๅ็‚บ `q` ็š„ๆŸฅ่ฉขๅƒๆ•ธ (ไพ‹ๅฆ‚ `http://127.0.0.1:8000/items/foo?q=somequery`)ใ€‚ - - ๅ› ็‚บ `q` ๅƒๆ•ธ่ขซๅฎฃๅ‘Š็‚บ `= None`๏ผŒๆ‰€ไปฅๆ˜ฏ้ธๅกซ็š„ใ€‚ - - ๅฆ‚ๆžœๆฒ’ๆœ‰ๅฎฃๅ‘Š `None`๏ผŒๅ‰‡ๆญคๅƒๆ•ธๅฐ‡ๆœƒๆ˜ฏๅฟ…ๅกซ (ไพ‹ๅฆ‚ `PUT` ็ฏ„ไพ‹็š„่ซ‹ๆฑ‚ body)ใ€‚ -- ๅฐๆ–ผ `PUT` ็š„่ซ‹ๆฑ‚ `/items/{item_id}`๏ผŒๅฐ‡ๆœƒ่ฎ€ๅ– body ็‚บ JSON๏ผš - - ้ฉ—่ญ‰ๆ˜ฏๅฆๆœ‰ๅฟ…ๅกซๅฑฌๆ€ง `name` ไธ”ๅž‹ๅˆฅๆ˜ฏ `str`ใ€‚ - - ้ฉ—่ญ‰ๆ˜ฏๅฆๆœ‰ๅฟ…ๅกซๅฑฌๆ€ง `price` ไธ”ๅž‹ๅˆฅๆ˜ฏ `float`ใ€‚ - - ้ฉ—่ญ‰ๆ˜ฏๅฆๆœ‰้ธๅกซๅฑฌๆ€ง `is_offer` ไธ”ๅž‹ๅˆฅๆ˜ฏ `bool`ใ€‚ - - ไปฅไธŠ้ฉ—่ญ‰้ƒฝ้ฉ็”จๆ–ผๅคšๅฑคๆฌกๅทข็‹€ JSON ็‰ฉไปถใ€‚ -- ่‡ชๅ‹•่ฝ‰ๆ› JSON ๆ ผๅผใ€‚ -- ้€้Ž OpenAPI ๆ–‡ไปถไพ†่จ˜้Œ„ๆ‰€ๆœ‰ๅ…งๅฎน๏ผŒๅฏไปฅ่ขซ็”จๆ–ผ๏ผš - - ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑใ€‚ - - ่‡ชๅ‹•็‚บๅคš็จฎ็จ‹ๅผ่ชž่จ€็”Ÿๆˆ็”จๆˆถ็ซฏ็š„็จ‹ๅผ็ขผใ€‚ -- ๆไพ›ๅ…ฉ็จฎไบคไบ’ๅผๆ–‡ไปถไป‹้ขใ€‚ +ๅ›žๅˆฐๅ‰้ข็š„็จ‹ๅผ็ขผ็ฏ„ไพ‹๏ผŒ**FastAPI** ๆœƒ๏ผš + +* ้ฉ—่ญ‰ `GET` ่ˆ‡ `PUT` ่ซ‹ๆฑ‚็š„่ทฏๅพ‘ไธญๆ˜ฏๅฆๅŒ…ๅซ `item_id`ใ€‚ +* ้ฉ—่ญ‰ `GET` ่ˆ‡ `PUT` ่ซ‹ๆฑ‚ไธญ็š„ `item_id` ๆ˜ฏๅฆ็‚บ `int` ๅž‹ๅˆฅใ€‚ + * ๅฆ‚ๆžœไธๆ˜ฏ๏ผŒๅฎขๆˆถ็ซฏๆœƒ็œ‹ๅˆฐๆธ…ๆฅšๆœ‰็”จ็š„้Œฏ่ชคใ€‚ +* ๅœจ `GET` ่ซ‹ๆฑ‚ไธญๆชขๆŸฅๆ˜ฏๅฆๆœ‰ๅ็‚บ `q` ็š„ๅฏ้ธๆŸฅ่ฉขๅƒๆ•ธ๏ผˆๅฆ‚ `http://127.0.0.1:8000/items/foo?q=somequery`๏ผ‰ใ€‚ + * ๅ› ็‚บ `q` ๅƒๆ•ธ่ขซๅฎฃๅ‘Š็‚บ `= None`๏ผŒๆ‰€ไปฅๅฎƒๆ˜ฏๅฏ้ธ็š„ใ€‚ + * ่‹ฅๆฒ’ๆœ‰ `None`๏ผŒๅ‰‡ๅฎƒๆœƒๆ˜ฏๅฟ…ๅกซ๏ผˆๅฐฑๅƒ `PUT` ๆ™‚็š„ body๏ผ‰ใ€‚ +* ๅฐๆ–ผ `/items/{item_id}` ็š„ `PUT` ่ซ‹ๆฑ‚๏ผŒไปฅ JSON ่ฎ€ๅ– body๏ผš + * ๆชขๆŸฅๆ˜ฏๅฆๆœ‰ๅฟ…ๅกซๅฑฌๆ€ง `name`๏ผŒไธ”็‚บ `str`ใ€‚ + * ๆชขๆŸฅๆ˜ฏๅฆๆœ‰ๅฟ…ๅกซๅฑฌๆ€ง `price`๏ผŒไธ”็‚บ `float`ใ€‚ + * ๆชขๆŸฅๆ˜ฏๅฆๆœ‰ๅฏ้ธๅฑฌๆ€ง `is_offer`๏ผŒ่‹ฅๅญ˜ๅœจๅ‰‡ๆ‡‰็‚บ `bool`ใ€‚ + * ไปฅไธŠไนŸ้ฉ็”จๆ–ผๆทฑๅบฆๅทข็‹€็š„ JSON ็‰ฉไปถใ€‚ +* ่‡ชๅ‹•ๅœจ JSON ่ˆ‡ Python ไน‹้–“่ฝ‰ๆ›ใ€‚ +* ไปฅ OpenAPI ่จ˜้Œ„ๆ‰€ๆœ‰ๅ…งๅฎน๏ผŒๅฏ็”จๆ–ผ๏ผš + * ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑใ€‚ + * ็‚บๅคš็จฎ่ชž่จ€่‡ชๅ‹•็”ข็”Ÿ็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ็š„็ณป็ตฑใ€‚ +* ็›ดๆŽฅๆไพ›ๅ…ฉ็จฎไบ’ๅ‹•ๅผๆ–‡ไปถ็ถฒ้ ไป‹้ขใ€‚ --- -้›–็„ถๆˆ‘ๅ€‘ๅชๆ•˜่ฟฐไบ†่กจ้ข็š„ๅŠŸ่ƒฝ๏ผŒไฝ†ๅ…ถๅฏฆไฝ ๅทฒ็ถ“็†่งฃไบ†ๅฎƒๆ˜ฏๅฆ‚ไฝ•ๅŸท่กŒใ€‚ +ๆˆ‘ๅ€‘ๅช่งธๅŠไบ†่กจ้ข๏ผŒไฝ†ไฝ ๅทฒ็ถ“ไบ†่งฃๅฎƒ็š„้‹ไฝœๆ–นๅผไบ†ใ€‚ -่ฉฆ่‘—ไฟฎๆ”นไปฅไธ‹็จ‹ๅผ็ขผ๏ผš +่ฉฆ่‘—ๆŠŠ้€™ไธ€่กŒ๏ผš ```Python return {"item_name": item.name, "item_id": item_id} ``` -ๅพž๏ผš +โ€ฆๅพž๏ผš ```Python ... "item_name": item.name ... ``` -ไฟฎๆ”น็‚บ๏ผš +โ€ฆๆ”น็‚บ๏ผš ```Python ... "item_price": item.price ... ``` -็„ถๅพŒ่ง€ๅฏŸไฝ ็š„็ทจ่ผฏๅ™จ๏ผŒๆœƒ่‡ชๅ‹•่ฃœๅ…จไธฆไธ”้‚„็Ÿฅ้“ไป–ๅ€‘็š„ๅž‹ๅˆฅ๏ผš +โ€ฆ็„ถๅพŒ็œ‹็œ‹ไฝ ็š„็ทจ่ผฏๅ™จๅฆ‚ไฝ•่‡ชๅ‹•่ฃœๅ…จๅฑฌๆ€งไธฆ็Ÿฅ้“ๅฎƒๅ€‘็š„ๅž‹ๅˆฅ๏ผš ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -ๆœ‰้—œๆ›ดๅคšๅŠŸ่ƒฝ็š„ๅฎŒๆ•ด็ฏ„ไพ‹๏ผŒๅฏไปฅๅƒ่€ƒ ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—ใ€‚ +่‹ฅๆƒณ็œ‹ๅŒ…ๅซๆ›ดๅคšๅŠŸ่ƒฝ็š„ๅฎŒๆ•ด็ฏ„ไพ‹๏ผŒ่ซ‹ๅƒ่€ƒ ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—ใ€‚ + +**ๅЇ้€่ญฆๅ‘Š**๏ผšๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—ๅŒ…ๅซ๏ผš + +* ไพ†่‡ชไธๅŒไพ†ๆบ็š„**ๅƒๆ•ธ**ๅฎฃๅ‘Š๏ผšไพ‹ๅฆ‚ **headers**ใ€**cookies**ใ€**form fields** ๅ’Œ **files**ใ€‚ +* ๅฆ‚ไฝ•่จญๅฎš**้ฉ—่ญ‰้™ๅˆถ**๏ผŒๅฆ‚ `maximum_length` ๆˆ– `regex`ใ€‚ +* ไธ€ๅ€‹้žๅธธๅผทๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑใ€‚ +* ๅฎ‰ๅ…จ่ˆ‡้ฉ—่ญ‰๏ผŒๅŒ…ๅซๆ”ฏๆด **OAuth2** ๆญ้… **JWT tokens** ่ˆ‡ **HTTP Basic** ้ฉ—่ญ‰ใ€‚ +* ๅฎฃๅ‘Š**ๆทฑๅบฆๅทข็‹€ JSON ๆจกๅž‹**็š„้€ฒ้šŽ๏ผˆไฝ†ๅŒๆจฃ็ฐกๅ–ฎ๏ผ‰ๆŠ€ๅทง๏ผˆๆ„Ÿ่ฌ Pydantic๏ผ‰ใ€‚ +* ่ˆ‡ Strawberry ๅŠๅ…ถไป–ๅ‡ฝๅผๅบซ็š„ **GraphQL** ๆ•ดๅˆใ€‚ +* ่จฑๅคš้กๅค–ๅŠŸ่ƒฝ๏ผˆๆ„Ÿ่ฌ Starlette๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + * **WebSockets** + * ๅŸบๆ–ผ HTTPX ่ˆ‡ `pytest` ็š„ๆฅตๅ…ถ็ฐกๅ–ฎ็š„ๆธฌ่ฉฆ + * **CORS** + * **Cookie Sessions** + * ...ไปฅๅŠๆ›ดๅคšใ€‚ + +### ้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ๏ผˆๅฏ้ธ๏ผ‰ { #deploy-your-app-optional } + +ไฝ ไนŸๅฏไปฅ้ธๆ“‡ๅฐ‡ FastAPI ๆ‡‰็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloud๏ผŒๅฆ‚ๆžœไฝ ้‚„ๆฒ’ๅŠ ๅ…ฅ๏ผŒๅŽป็™ป่จ˜็ญ‰ๅ€™ๅๅ–ฎๅงใ€‚๐Ÿš€ + +ๅฆ‚ๆžœไฝ ๅทฒ็ถ“ๆœ‰ **FastAPI Cloud** ๅธณ่™Ÿ๏ผˆๆˆ‘ๅ€‘ๅทฒๅพž็ญ‰ๅ€™ๅๅ–ฎ้‚€่ซ‹ไฝ  ๐Ÿ˜‰๏ผ‰๏ผŒไฝ ๅฏไปฅ็”จไธ€ๅ€‹ๆŒ‡ไปค้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จใ€‚ + +้ƒจ็ฝฒๅ‰๏ผŒๅ…ˆ็ขบ่ชไฝ ๅทฒ็™ปๅ…ฅ๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +ๆŽฅ่‘—้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ้€™ๆจฃ๏ผ็พๅœจไฝ ๅฏไปฅๅœจ่ฉฒ URL ้€ ่จชไฝ ็š„ๆ‡‰็”จใ€‚โœจ + +#### ้—œๆ–ผ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ๅŒไธ€ไฝไฝœ่€…่ˆ‡ๅœ˜้šŠๆ‰“้€ ใ€‚ + +ๅฎƒ่ฎ“ไฝ ไปฅๆœ€ๅฐ็š„ๅŠชๅŠ›็ฒพ็ฐกๅœฐๅฎŒๆˆ API ็š„**ๅปบ็ฝฎ**ใ€**้ƒจ็ฝฒ**่ˆ‡**ๅญ˜ๅ–**ๆต็จ‹ใ€‚ + +ๅฎƒๆŠŠ็”จ FastAPI ้–‹็™ผๆ‡‰็”จ็š„**้–‹็™ผ่€…้ซ”้ฉ—**ๅธถๅˆฐ**้ƒจ็ฝฒ**ๅˆฐ้›ฒ็ซฏ็š„ๆต็จ‹ไธญใ€‚๐ŸŽ‰ + +FastAPI Cloud ๆ˜ฏใ€ŒFastAPI ่ˆ‡ๅฅฝๆœ‹ๅ‹ๅ€‘ใ€้€™ไบ›้–‹ๆบๅฐˆๆกˆ็š„ไธป่ฆ่ดŠๅŠฉ่ˆ‡่ณ‡้‡‘ไพ†ๆบใ€‚โœจ + +#### ้ƒจ็ฝฒๅˆฐๅ…ถไป–้›ฒ็ซฏไพ›ๆ‡‰ๅ•† { #deploy-to-other-cloud-providers } + +FastAPI ๆ˜ฏ้–‹ๆบไธ”ๅŸบๆ–ผๆจ™ๆบ–ใ€‚ไฝ ๅฏไปฅๆŠŠ FastAPI ๆ‡‰็”จ้ƒจ็ฝฒๅˆฐไปปไฝ•ไฝ ้ธๆ“‡็š„้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ใ€‚ + +ไพ็…งไฝ ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†็š„ๆŒ‡ๅ—ไพ†้ƒจ็ฝฒ FastAPI ๆ‡‰็”จๅงใ€‚๐Ÿค“ + +## ๆ•ˆ่ƒฝ { #performance } + +็จ็ซ‹็š„ TechEmpower ๅŸบๆบ–ๆธฌ่ฉฆ้กฏ็คบ๏ผŒๅœจ Uvicorn ไธ‹้‹่กŒ็š„ **FastAPI** ๆ‡‰็”จๆ˜ฏๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€๏ผŒๅƒ…ๆฌกๆ–ผ Starlette ่ˆ‡ Uvicorn ๆœฌ่บซ๏ผˆFastAPI ๅ…ง้ƒจไฝฟ็”จๅฎƒๅ€‘๏ผ‰ใ€‚(*) + +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ซ‹ๅƒ้–ฑๆธฌ่ฉฆ็ตๆžœใ€‚ + +## ไพ่ณดๅฅ—ไปถ { #dependencies } + +FastAPI ไพ่ณด Pydantic ่ˆ‡ Starletteใ€‚ + +### `standard` ไพ่ณดๅฅ—ไปถ { #standard-dependencies } + +็•ถไฝ ไปฅ `pip install "fastapi[standard]"` ๅฎ‰่ฃ FastAPI ๆ™‚๏ผŒๆœƒๅŒ…ๅซ `standard` ้€™็ต„ๅฏ้ธไพ่ณดๅฅ—ไปถ๏ผš + +Pydantic ๆœƒไฝฟ็”จ๏ผš + +* email-validator - ็”จๆ–ผ้›ปๅญ้ƒตไปถ้ฉ—่ญ‰ใ€‚ + +Starlette ๆœƒไฝฟ็”จ๏ผš -**ๅЇ้€่ญฆๅ‘Š**๏ผš ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—ๅ…งๅฎนๆœ‰๏ผš +* httpx - ่‹ฅ่ฆไฝฟ็”จ `TestClient` ๅฟ…้ ˆๅฎ‰่ฃใ€‚ +* jinja2 - ่‹ฅ่ฆไฝฟ็”จ้ ่จญ็š„ๆจกๆฟ่จญๅฎšๅฟ…้ ˆๅฎ‰่ฃใ€‚ +* python-multipart - ่‹ฅ่ฆๆ”ฏๆด่กจๅ–ฎ "่งฃๆž"๏ผŒๆญ้… `request.form()`ใ€‚ -- ๅฐไพ†่‡ชไธๅŒๅœฐๆ–น็š„**ๅƒๆ•ธ**้€ฒ่กŒๅฎฃๅ‘Š๏ผšๅƒๆ˜ฏ **headers**, **cookies**, **form ่กจๅ–ฎ**ไปฅๅŠ**ไธŠๅ‚ณๆช”ๆกˆ**ใ€‚ -- ๅฆ‚ไฝ•่จญๅฎš **้ฉ—่ญ‰้™ๅˆถ** ๅƒๆ˜ฏ `maximum_length` or `regex`ใ€‚ -- ็ฐกๅ–ฎไธ”้žๅธธๅฎนๆ˜“ไฝฟ็”จ็š„ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑใ€‚ -- ๅฎ‰ๅ…จๆ€งๅ’Œ่บซไปฝ้ฉ—่ญ‰๏ผŒๅŒ…ๅซๆไพ›ๆ”ฏๆด **OAuth2**ใ€**JWT tokens** ๅ’Œ **HTTP Basic** ้ฉ—่ญ‰ใ€‚ -- ๆ›ด้€ฒ้šŽ (ไฝ†ๅŒๆจฃ็ฐกๅ–ฎ) ็š„ๅฎฃๅ‘Š **ๅคšๅฑคๆฌก็š„ๅทข็‹€ JSON ๆ ผๅผ** (ๆ„Ÿ่ฌ Pydantic)ใ€‚ -- **GraphQL** ่ˆ‡ Strawberry ไปฅๅŠๅ…ถไป–็š„็›ธ้—œๅ‡ฝๅผๅบซ้€ฒ่กŒๆ•ดๅˆใ€‚ -- ๆ›ดๅคšๅ…ถไป–็š„ๅŠŸ่ƒฝ (ๆ„Ÿ่ฌ Starlette) ๅƒๆ˜ฏ๏ผš - - **WebSockets** - - ๆ–ผ HTTPX ๅ’Œ `pytest` ็š„้žๅธธ็ฐกๅ–ฎๆธฌ่ฉฆ - - **CORS** - - **Cookie Sessions** - - ...ไปฅๅŠๆ›ดๅคš +FastAPI ๆœƒไฝฟ็”จ๏ผš -## ๆ•ˆ่ƒฝ +* uvicorn - ็”จๆ–ผ่ผ‰ๅ…ฅไธฆๆœๅ‹™ไฝ ็š„ๆ‡‰็”จ็š„ไผบๆœๅ™จใ€‚้€™ๅŒ…ๅซ `uvicorn[standard]`๏ผŒๅ…ถไธญๅซๆœ‰ไธ€ไบ›้ซ˜ๆ•ˆ่ƒฝๆœๅ‹™ๆ‰€้œ€็š„ไพ่ณด๏ผˆไพ‹ๅฆ‚ `uvloop`๏ผ‰ใ€‚ +* `fastapi-cli[standard]` - ๆไพ› `fastapi` ๆŒ‡ไปคใ€‚ + * ๅ…ถไธญๅŒ…ๅซ `fastapi-cloud-cli`๏ผŒๅฏ่ฎ“ไฝ ๅฐ‡ FastAPI ๆ‡‰็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloudใ€‚ -ไพ†่‡ช็จ็ซ‹ๆฉŸๆง‹ TechEmpower ็š„ๆธฌ่ฉฆ็ตๆžœ๏ผŒ้กฏ็คบๅœจ Uvicorn ๅŸท่กŒไธ‹็š„ **FastAPI** ๆ˜ฏ ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€๏ผŒ ๅƒ…ๆฌกๆ–ผ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ (ๅ…ฉ่€…ๆ˜ฏ FastAPI ็š„ๅบ•ๅฑค)ใ€‚ (\*) +### ไธๅซ `standard` ไพ่ณดๅฅ—ไปถ { #without-standard-dependencies } -ๆƒณไบ†่งฃๆ›ดๅคš่จŠๆฏ๏ผŒๅฏไปฅๅƒ่€ƒ ๆธฌ่ฉฆ็ตๆžœใ€‚ +ๅฆ‚ๆžœไฝ ไธๆƒณๅŒ…ๅซ `standard` ๅฏ้ธไพ่ณด๏ผŒๅฏไปฅๆ”น็”จ `pip install fastapi`๏ผˆ่€Œไธๆ˜ฏ `pip install "fastapi[standard]"`๏ผ‰ใ€‚ -## ๅฏ้ธ็š„ไพ่ณดๅฅ—ไปถ +### ไธๅซ `fastapi-cloud-cli` { #without-fastapi-cloud-cli } -็”จๆ–ผ Pydantic๏ผš +ๅฆ‚ๆžœไฝ ๆƒณๅฎ‰่ฃๅธถๆœ‰ standard ไพ่ณดใ€ไฝ†ไธๅŒ…ๅซ `fastapi-cloud-cli`๏ผŒๅฏไปฅไฝฟ็”จ `pip install "fastapi[standard-no-fastapi-cloud-cli]"`ใ€‚ -- email-validator - ็”จๆ–ผ้›ปๅญ้ƒตไปถ้ฉ—่ญ‰ใ€‚ -- pydantic-settings - ็”จๆ–ผ่จญๅฎš็ฎก็†ใ€‚ -- pydantic-extra-types - ็”จๆ–ผ่ˆ‡ Pydantic ไธ€่ตทไฝฟ็”จ็š„้กๅค–ๅž‹ๅˆฅใ€‚ +### ้กๅค–ๅฏ้ธไพ่ณดๅฅ—ไปถ { #additional-optional-dependencies } -็”จๆ–ผ Starlette๏ผš +ๆœ‰ไบ›้กๅค–ไพ่ณดไฝ ๅฏ่ƒฝไนŸๆœƒๆƒณๅฎ‰่ฃใ€‚ -- httpx - ไฝฟ็”จ `TestClient`ๆ™‚ๅฟ…้ ˆๅฎ‰่ฃใ€‚ -- jinja2 - ไฝฟ็”จ้ ่จญ็š„ๆจกๆฟ้…็ฝฎๆ™‚ๅฟ…้ ˆๅฎ‰่ฃใ€‚ -- python-multipart - ้œ€่ฆไฝฟ็”จ `request.form()` ๅฐ่กจๅ–ฎ้€ฒ่กŒ "่งฃๆž" ๆ™‚ๅฎ‰่ฃใ€‚ -- itsdangerous - ้œ€่ฆไฝฟ็”จ `SessionMiddleware` ๆ”ฏๆดๆ™‚ๅฎ‰่ฃใ€‚ -- pyyaml - ็”จๆ–ผๆ”ฏๆด Starlette ็š„ `SchemaGenerator` (ๅฆ‚ๆžœไฝ ไฝฟ็”จ FastAPI๏ผŒๅฏ่ƒฝไธ้œ€่ฆๅฎƒ)ใ€‚ +Pydantic ็š„้กๅค–ๅฏ้ธไพ่ณด๏ผš -็”จๆ–ผ FastAPI / Starlette๏ผš +* pydantic-settings - ่จญๅฎš็ฎก็†ใ€‚ +* pydantic-extra-types - ่ˆ‡ Pydantic ไธ€่ตทไฝฟ็”จ็š„้กๅค–ๅž‹ๅˆฅใ€‚ -- uvicorn - ็”จๆ–ผๅŠ ่ผ‰ๅ’Œ้‹่กŒๆ‡‰็”จ็จ‹ๅผ็š„ๆœๅ‹™ๅ™จใ€‚ -- orjson - ไฝฟ็”จ `ORJSONResponse`ๆ™‚ๅฟ…้ ˆๅฎ‰่ฃใ€‚ -- ujson - ไฝฟ็”จ `UJSONResponse` ๆ™‚ๅฟ…้ ˆๅฎ‰่ฃใ€‚ +FastAPI ็š„้กๅค–ๅฏ้ธไพ่ณด๏ผš -ไฝ ๅฏไปฅไฝฟ็”จ `pip install "fastapi[all]"` ไพ†ๅฎ‰่ฃ้€™ไบ›ๆ‰€ๆœ‰ไพ่ณดๅฅ—ไปถใ€‚ +* orjson - ่‹ฅ่ฆไฝฟ็”จ `ORJSONResponse` ๅฟ…้ ˆๅฎ‰่ฃใ€‚ +* ujson - ่‹ฅ่ฆไฝฟ็”จ `UJSONResponse` ๅฟ…้ ˆๅฎ‰่ฃใ€‚ -## ๆŽˆๆฌŠ +## ๆŽˆๆฌŠ { #license } -่ฉฒ้ …็›ฎ้ตๅพช MIT ่จฑๅฏๅ”่ญฐใ€‚ +ๆœฌๅฐˆๆกˆไปฅ MIT ๆŽˆๆฌŠๆขๆฌพ้‡‹ๅ‡บใ€‚ diff --git a/docs/zh-hant/docs/learn/index.md b/docs/zh-hant/docs/learn/index.md index eb7d7096a5..43e4519a50 100644 --- a/docs/zh-hant/docs/learn/index.md +++ b/docs/zh-hant/docs/learn/index.md @@ -1,5 +1,5 @@ -# ๅญธ็ฟ’ +# ๅญธ็ฟ’ { #learn } -ไปฅไธ‹ๆ˜ฏๅญธ็ฟ’ FastAPI ็š„ๅ…ฅ้–€ไป‹็ดนๅ’Œๆ•™ๅญธใ€‚ +ไปฅไธ‹ๆ˜ฏๅญธ็ฟ’ **FastAPI** ็š„ๅ…ฅ้–€ไป‹็ดนๅ’Œๆ•™ๅญธใ€‚ ไฝ ๅฏไปฅๅฐ‡ๅ…ถ่ฆ–็‚บไธ€ๆœฌ**ๆ›ธ็ฑ**ๆˆ–ไธ€้–€**่ชฒ็จ‹**๏ผŒ้€™ๆ˜ฏ**ๅฎ˜ๆ–น**่ชๅฏไธฆๆŽจ่–ฆ็š„ FastAPI ๅญธ็ฟ’ๆ–นๅผใ€‚ ๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/resources/index.md b/docs/zh-hant/docs/resources/index.md index f4c70a3a04..ea77cb728e 100644 --- a/docs/zh-hant/docs/resources/index.md +++ b/docs/zh-hant/docs/resources/index.md @@ -1,3 +1,3 @@ -# ่ณ‡ๆบ +# ่ณ‡ๆบ { #resources } -้กๅค–็š„่ณ‡ๆบใ€ๅค–้ƒจ้€ฃ็ตใ€ๆ–‡็ซ ็ญ‰ใ€‚ โœˆ๏ธ +้กๅค–็š„่ณ‡ๆบใ€ๅค–้ƒจ้€ฃ็ต็ญ‰ใ€‚ โœˆ๏ธ diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index d6684bc513..6bcb453bff 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -1,8 +1,8 @@ -# ็ฌฌไธ€ๆญฅ +# ็ฌฌไธ€ๆญฅ { #first-steps } ๆœ€็ฐกๅ–ฎ็š„ FastAPI ๆช”ๆกˆๅฏ่ƒฝ็œ‹่ตทไพ†ๅƒ้€™ๆจฃ๏ผš -{* ../../docs_src/first_steps/tutorial001.py *} +{* ../../docs_src/first_steps/tutorial001_py39.py *} ๅฐ‡ๅ…ถ่ค‡่ฃฝๅˆฐไธ€ๅ€‹ๅ็‚บ `main.py` ็š„ๆ–‡ไปถไธญใ€‚ @@ -11,47 +11,39 @@
```console -$ fastapi dev main.py -INFO Using path main.py -INFO Resolved absolute path /home/user/code/awesomeapp/main.py -INFO Searching for package file structure from directories with __init__.py files -INFO Importing from /home/user/code/awesomeapp - - โ•ญโ”€ Python module file โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ ๐Ÿ main.py โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Importing module main -INFO Found importable FastAPI app - - โ•ญโ”€ Importable FastAPI app โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ from main import app โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Using import string main:app - - โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ - โ”‚ โ”‚ - โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ - โ”‚ โ”‚ - โ”‚ Running in development mode, for production use: โ”‚ - โ”‚ โ”‚ - โ”‚ fastapi run โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2265862] using WatchFiles -INFO: Started server process [2265873] -INFO: Waiting for application startup. -INFO: Application startup complete. +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
@@ -64,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ้‚ฃๅˆ—้กฏ็คบไบ†ไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๆญฃๅœจๆœฌๅœฐ็ซฏๆฉŸๅ™จไธŠ้‹่กŒ็š„ URLใ€‚ -### ๆŸฅ็œ‹ๅฎƒ +### ๆŸฅ็œ‹ๅฎƒ { #check-it } ๅœจ็€่ฆฝๅ™จไธญๆ‰“้–‹ http://127.0.0.1:8000. @@ -74,7 +66,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) {"message": "Hello World"} ``` -### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ +### ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ { #interactive-api-docs } ็พๅœจ๏ผŒๅ‰ๅพ€ http://127.0.0.1:8000/docs. @@ -82,7 +74,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ๆ›ฟไปฃ API ๆ–‡ไปถ +### ๆ›ฟไปฃ API ๆ–‡ไปถ { #alternative-api-docs } ็พๅœจ๏ผŒๅ‰ๅพ€ http://127.0.0.1:8000/redoc. @@ -90,33 +82,33 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } -**FastAPI** ไฝฟ็”จๅฎš็พฉ API ็š„ **OpenAPI** ๆจ™ๆบ–ไพ†็”Ÿๆˆไธ€ๅ€‹ ใ€Œschemaใ€ ่ˆ‡ไฝ ็š„ๆ‰€ๆœ‰ APIใ€‚ +**FastAPI** ไฝฟ็”จๅฎš็พฉ API ็š„ **OpenAPI** ๆจ™ๆบ–ไพ†็”Ÿๆˆไธ€ๅ€‹ใ€Œschemaใ€๏ผŒๆถต่“‹ไฝ ็š„ๅ…จ้ƒจ APIใ€‚ -#### ใ€ŒSchemaใ€ +#### ใ€ŒSchemaใ€ { #schema } ใ€Œschemaใ€ๆ˜ฏๅฐๆŸๅ€‹ไบ‹็‰ฉ็š„ๅฎš็พฉๆˆ–ๆ่ฟฐใ€‚ๅฎƒไธฆไธๆ˜ฏๅฏฆไฝœๅฎƒ็š„็จ‹ๅผ็ขผ๏ผŒ่€Œๅƒ…ๅƒ…ๆ˜ฏไธ€ๅ€‹ๆŠฝ่ฑก็š„ๆ่ฟฐใ€‚ -#### API ใ€Œschemaใ€ +#### API ใ€Œschemaใ€ { #api-schema } ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒOpenAPI ๆ˜ฏไธ€ๅ€‹่ฆ็ฏ„๏ผŒๅฎƒ่ฆๅฎšไบ†ๅฆ‚ไฝ•ๅฎš็พฉ API ็š„ schemaใ€‚ ้€™ๅ€‹ schema ๅฎš็พฉๅŒ…ๅซไบ†ไฝ ็š„ API ่ทฏๅพ‘ใ€ๅฏ่ƒฝๆŽฅๆ”ถ็š„ๅƒๆ•ธ็ญ‰ๅ…งๅฎนใ€‚ -#### ่ณ‡ๆ–™ ใ€Œschemaใ€ +#### ่ณ‡ๆ–™ใ€Œschemaใ€ { #data-schema } ใ€Œschemaใ€้€™ๅ€‹่ก“่ชžไนŸๅฏ่ƒฝๆŒ‡ๆŸไบ›่ณ‡ๆ–™็š„็ตๆง‹๏ผŒๆฏ”ๅฆ‚ JSON ๅ…งๅฎน็š„็ตๆง‹ใ€‚ ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฎƒๆŒ‡็š„ๆ˜ฏ JSON ็š„ๅฑฌๆ€งใ€่ณ‡ๆ–™ๅž‹ๅˆฅ็ญ‰ใ€‚ -#### OpenAPI ๅ’Œ JSON Schema +#### OpenAPI ๅ’Œ JSON Schema { #openapi-and-json-schema } -OpenAPI ๅฎš็พฉไบ† API ็š„ schemaใ€‚้€™ๅ€‹ schema ๅŒ…ๅซไบ†ไฝฟ็”จ **JSON Schema** ๅฎš็พฉ็š„่ณ‡ๆ–™๏ผŒ้€™ๆ˜ฏ JSON ่ณ‡ๆ–™ schema ็š„ๆจ™ๆบ–ใ€‚ +OpenAPI ็‚บไฝ ็š„ API ๅฎš็พฉไบ† API ็š„ schemaใ€‚่€Œ่ฉฒ schema ๆœƒๅŒ…ๅซไฝ ็š„ API ๆ‰€ๅ‚ณ้€่ˆ‡ๆŽฅๆ”ถ่ณ‡ๆ–™็š„ๅฎš็พฉ๏ผˆๆˆ–็จฑใ€Œschemasใ€๏ผ‰๏ผŒไฝฟ็”จ **JSON Schema**๏ผŒ้€™ๆ˜ฏ JSON ่ณ‡ๆ–™ schema ็š„ๆจ™ๆบ–ใ€‚ -#### ๆชขๆŸฅ `openapi.json` +#### ๆชขๆŸฅ `openapi.json` { #check-the-openapi-json } -ๅฆ‚ๆžœไฝ ๅฅฝๅฅ‡ๅŽŸๅง‹็š„ OpenAPI schema ้•ทไป€้บผๆจฃๅญ๏ผŒFastAPI ๆœƒ่‡ชๅ‹•็”Ÿๆˆไธ€ๅ€‹ๅŒ…ๅซๆ‰€ๆœ‰ API ๆ่ฟฐ็š„ JSON (schema)ใ€‚ +ๅฆ‚ๆžœไฝ ๅฅฝๅฅ‡ๅŽŸๅง‹็š„ OpenAPI schema ้•ทไป€้บผๆจฃๅญ๏ผŒFastAPI ๆœƒ่‡ชๅ‹•็”Ÿๆˆไธ€ๅ€‹ๅŒ…ๅซๆ‰€ๆœ‰ API ๆ่ฟฐ็š„ JSON๏ผˆschema๏ผ‰ใ€‚ ไฝ ๅฏไปฅ็›ดๆŽฅๅœจ http://127.0.0.1:8000/openapi.json ๆŸฅ็œ‹ๅฎƒใ€‚ @@ -143,23 +135,59 @@ OpenAPI ๅฎš็พฉไบ† API ็š„ schemaใ€‚้€™ๅ€‹ schema ๅŒ…ๅซไบ†ไฝฟ็”จ **JSON Schema** ... ``` -#### OpenAPI ็š„็”จ้€” +#### OpenAPI ็š„็”จ้€” { #what-is-openapi-for } OpenAPI schema ้ฉ…ๅ‹•ไบ†ๅ…ฉๅ€‹ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑใ€‚ ่€Œไธ”ๆœ‰่จฑๅคšๆ›ฟไปฃๆ–นๆกˆ๏ผŒๆ‰€ๆœ‰้€™ไบ›้ƒฝๆ˜ฏๅŸบๆ–ผ OpenAPIใ€‚ไฝ ๅฏไปฅ่ผ•้ฌ†ๅœฐๅฐ‡ไปปไฝ•้€™ไบ›ๆ›ฟไปฃๆ–นๆกˆๆทปๅŠ ๅˆฐไฝฟ็”จ **FastAPI** ๅปบ็ฝฎ็š„ๆ‡‰็”จ็จ‹ๅผไธญใ€‚ -ไฝ ไนŸๅฏไปฅ็”จๅฎƒ่‡ชๅ‹•็”Ÿๆˆ็จ‹ๅผ็ขผ๏ผŒ่ฎ“ๅ‰็ซฏใ€ๆ‰‹ๆฉŸๆ‡‰็”จ็จ‹ๅผๆˆ–็‰ฉ่ฏ็ถฒ่จญๅ‚™็ญ‰่ˆ‡ไฝ ็š„ API ้€ฒ่กŒ้€š่จŠใ€‚ +ไฝ ไนŸๅฏไปฅ็”จๅฎƒ่‡ชๅ‹•็”Ÿๆˆ็จ‹ๅผ็ขผ๏ผŒ่ฎ“็”จๆˆถ็ซฏ่ˆ‡ไฝ ็š„ API ้€š่จŠใ€‚ไพ‹ๅฆ‚ๅ‰็ซฏใ€ๆ‰‹ๆฉŸๆˆ–็‰ฉ่ฏ็ถฒ๏ผˆIoT๏ผ‰ๆ‡‰็”จ็จ‹ๅผใ€‚ + +### ้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ๏ผˆๅฏ้ธ๏ผ‰ { #deploy-your-app-optional } + +ไฝ ๅฏไปฅ้ธๆ“‡ๅฐ‡ไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผ้ƒจ็ฝฒๅˆฐ FastAPI Cloud๏ผŒๅฆ‚ๆžœ้‚„ๆฒ’ๆœ‰๏ผŒๅŽปๅŠ ๅ…ฅๅ€™่ฃœๅๅ–ฎๅงใ€‚๐Ÿš€ + +ๅฆ‚ๆžœไฝ ๅทฒ็ถ“ๆœ‰ **FastAPI Cloud** ๅธณ่™Ÿ๏ผˆๆˆ‘ๅ€‘ๅทฒๅพžๅ€™่ฃœๅๅ–ฎ้‚€่ซ‹ไฝ  ๐Ÿ˜‰๏ผ‰๏ผŒไฝ ๅฏไปฅ็”จไธ€ๅ€‹ๆŒ‡ไปค้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผใ€‚ + +้ƒจ็ฝฒไน‹ๅ‰๏ผŒๅ…ˆ็ขบไฟไฝ ๅทฒ็™ปๅ…ฅ๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +ๆŽฅ่‘—้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ้€™ๆจฃ๏ผ็พๅœจไฝ ๅฏไปฅ้€้Ž่ฉฒ URL ๅญ˜ๅ–ไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไบ†ใ€‚โœจ -## ้€ๆญฅๅ›ž้กง +## ้€ๆญฅๅ›ž้กง { #recap-step-by-step } -### ็ฌฌไธ€ๆญฅ๏ผšๅผ•ๅ…ฅ `FastAPI` +### ็ฌฌไธ€ๆญฅ๏ผšๅผ•ๅ…ฅ `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001.py h1[1] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} `FastAPI` ๆ˜ฏไธ€ๅ€‹ Python ้กžๅˆฅ๏ผŒๆไพ›ๆ‰€ๆœ‰ API ็š„ๅ…จ้ƒจๅŠŸ่ƒฝใ€‚ -/// note | Technical Details +/// note | ๆŠ€่ก“็ดฐ็ฏ€ `FastAPI` ๆ˜ฏไธ€ๅ€‹็›ดๆŽฅ็นผๆ‰ฟ่‡ช `Starlette` ็š„้กžๅˆฅใ€‚ @@ -167,17 +195,17 @@ OpenAPI schema ้ฉ…ๅ‹•ไบ†ๅ…ฉๅ€‹ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑใ€‚ /// -### ็ฌฌไบŒๆญฅ๏ผšๅปบ็ซ‹ไธ€ๅ€‹ `FastAPI` ใ€Œๅฏฆไพ‹ใ€ +### ็ฌฌไบŒๆญฅ๏ผšๅปบ็ซ‹ไธ€ๅ€‹ `FastAPI`ใ€Œๅฏฆไพ‹ใ€ { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001.py h1[3] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} ้€™่ฃก็š„ `app` ่ฎŠๆ•ธๅฐ‡ๆœƒๆ˜ฏ `FastAPI` ้กžๅˆฅ็š„ใ€Œๅฏฆไพ‹ใ€ใ€‚ ้€™ๅฐ‡ๆ˜ฏไฝ ๅปบ็ซ‹ๆ‰€ๆœ‰ API ็š„ไธป่ฆไบ’ๅ‹•้ปžใ€‚ -### ็ฌฌไธ‰ๆญฅ๏ผšๅปบ็ซ‹ไธ€ๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ* +### ็ฌฌไธ‰ๆญฅ๏ผšๅปบ็ซ‹ไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ { #step-3-create-a-path-operation } -#### ่ทฏๅพ‘ +#### ่ทฏๅพ‘ { #path } ้€™่ฃก็š„ใ€Œ่ทฏๅพ‘ใ€ๆŒ‡็š„ๆ˜ฏ URL ไธญ่‡ช็ฌฌไธ€ๅ€‹ `/` ไปฅๅพŒ็š„้ƒจๅˆ†ใ€‚ @@ -201,7 +229,7 @@ https://example.com/items/foo ๅœจๅปบ็ฝฎ API ๆ™‚๏ผŒใ€Œ่ทฏๅพ‘ใ€ๆ˜ฏๅˆ†้›ขใ€Œ้—œๆณจ้ปžใ€ๅ’Œใ€Œ่ณ‡ๆบใ€็š„ไธป่ฆๆ–นๅผใ€‚ -#### ๆ“ไฝœ +#### ๆ“ไฝœ { #operation } ้€™่ฃก็š„ใ€Œๆ“ไฝœใ€ๆŒ‡็š„ๆ˜ฏ HTTP ็š„ใ€Œๆ–นๆณ•ใ€ไน‹ไธ€ใ€‚ @@ -236,16 +264,16 @@ https://example.com/items/foo ๆˆ‘ๅ€‘ๅฐ‡ๆœƒ็จฑๅฎƒๅ€‘็‚บใ€Œ**ๆ“ไฝœ**ใ€ใ€‚ -#### ๅฎš็พฉไธ€ๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ* +#### ๅฎš็พฉไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001.py h1[6] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} `@app.get("/")` ๅ‘Š่จด **FastAPI** ้‚ฃๅ€‹ๅ‡ฝๅผ่ฒ ่ฒฌ่™•็†่ซ‹ๆฑ‚๏ผš * ่ทฏๅพ‘ `/` * ไฝฟ็”จ getๆ“ไฝœ -/// info | `@decorator` Info +/// info | `@decorator` ่ชชๆ˜Ž Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ @@ -253,7 +281,7 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ ไธ€ๅ€‹ใ€Œ่ฃ้ฃพๅ™จใ€ๆœƒๅฐไธ‹้ข็š„ๅ‡ฝๅผๅšไธ€ไบ›ไบ‹ๆƒ…ใ€‚ -ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒ้€™ๅ€‹่ฃ้ฃพๅ™จๅ‘Š่จด **FastAPI** ้‚ฃๅ€‹ๅ‡ฝๅผๅฐๆ‡‰ๆ–ผ **่ทฏๅพ‘** `/` ๅ’Œ **ๆ“ไฝœ** `get`. +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒ้€™ๅ€‹่ฃ้ฃพๅ™จๅ‘Š่จด **FastAPI** ้‚ฃๅ€‹ๅ‡ฝๅผๅฐๆ‡‰ๆ–ผ **่ทฏๅพ‘** `/` ๅ’Œ **ๆ“ไฝœ** `get`ใ€‚ ้€™ๅฐฑๆ˜ฏใ€Œ**่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ**ใ€ใ€‚ @@ -284,27 +312,27 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ /// -### ็ฌฌๅ››ๆญฅ๏ผšๅฎš็พฉ **่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ** +### ็ฌฌๅ››ๆญฅ๏ผšๅฎš็พฉใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ { #step-4-define-the-path-operation-function } ้€™ๆ˜ฏๆˆ‘ๅ€‘็š„ใ€Œ**่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ**ใ€๏ผš -* **path**: ๆ˜ฏ `/`. -* **operation**: ๆ˜ฏ `get`. -* **function**: ๆ˜ฏ่ฃ้ฃพๅ™จไธ‹้ข็š„ๅ‡ฝๅผ๏ผˆๅœจ `@app.get("/")` ไธ‹้ข๏ผ‰ใ€‚ +* **path**๏ผšๆ˜ฏ `/`ใ€‚ +* **operation**๏ผšๆ˜ฏ `get`ใ€‚ +* **function**๏ผšๆ˜ฏ่ฃ้ฃพๅ™จไธ‹้ข็š„ๅ‡ฝๅผ๏ผˆๅœจ `@app.get("/")` ไธ‹้ข๏ผ‰ใ€‚ -{* ../../docs_src/first_steps/tutorial001.py h1[7] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} ้€™ๅฐฑๆ˜ฏไธ€ๅ€‹ Python ๅ‡ฝๅผใ€‚ -ๅฎƒๅฐ‡ๆœƒๅœจ **FastAPI** ๆ”ถๅˆฐไธ€ๅ€‹่ซ‹ๆฑ‚ๆ™‚่ขซๅ‘ผๅซ๏ผŒไฝฟ็”จ `GET` ๆ“ไฝœใ€‚ +ๅฎƒๅฐ‡ๆœƒๅœจ **FastAPI** ๆ”ถๅˆฐไธ€ๅ€‹ไฝฟ็”จ `GET` ๆ“ไฝœใ€็ถฒๅ€็‚บใ€Œ`/`ใ€็š„่ซ‹ๆฑ‚ๆ™‚่ขซๅ‘ผๅซใ€‚ ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฎƒๆ˜ฏไธ€ๅ€‹ `async` ๅ‡ฝๅผใ€‚ --- -ไฝ ๅฏไปฅๅฐ‡ๅฎƒๅฎš็พฉ็‚บไธ€ๅ€‹ๆญฃๅธธ็š„ๅ‡ฝๅผ๏ผŒ่€Œไธๆ˜ฏ `async def`: +ไฝ ไนŸๅฏไปฅๅฐ‡ๅฎƒๅฎš็พฉ็‚บไธ€่ˆฌๅ‡ฝๅผ๏ผŒ่€Œไธๆ˜ฏ `async def`๏ผš -{* ../../docs_src/first_steps/tutorial003.py h1[7] *} +{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} /// note @@ -312,9 +340,9 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ /// -### ็ฌฌไบ”ๆญฅ๏ผšๅ›žๅ‚ณๅ…งๅฎน +### ็ฌฌไบ”ๆญฅ๏ผšๅ›žๅ‚ณๅ…งๅฎน { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001.py h1[8] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} ไฝ ๅฏไปฅ่ฟ”ๅ›žไธ€ๅ€‹ `dict`ใ€`list`ใ€ๅ–ฎๅ€‹ๅ€ผไฝœ็‚บ `str`ใ€`int` ็ญ‰ใ€‚ @@ -322,10 +350,31 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ ๆœ‰ๅพˆๅคšๅ…ถไป–็‰ฉไปถๅ’Œๆจกๅž‹ๆœƒ่‡ชๅ‹•่ฝ‰ๆ›็‚บ JSON๏ผˆๅŒ…ๆ‹ฌ ORMs๏ผŒ็ญ‰็ญ‰๏ผ‰ใ€‚่ฉฆ็”จไฝ ๆœ€ๅ–œๆญก็š„๏ผŒๅพˆๆœ‰ๅฏ่ƒฝๅฎƒๅ€‘ๅทฒ็ถ“ๆœ‰ๆ”ฏๆดใ€‚ -## ๅ›ž้กง +### ็ฌฌๅ…ญๆญฅ๏ผš้ƒจ็ฝฒ { #step-6-deploy-it } + +็”จไธ€่กŒๆŒ‡ไปคๅฐ‡ไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ้ƒจ็ฝฒๅˆฐ **FastAPI Cloud**๏ผš`fastapi deploy`ใ€‚๐ŸŽ‰ + +#### ้—œๆ–ผ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ไฝœ่€…่ˆ‡ๅœ˜้šŠๆ‰“้€ ใ€‚ + +ๅฎƒ่ฎ“ไฝ ไปฅๆœ€ๅฐ็š„ๆˆๆœฌๅฎŒๆˆ API ็š„**ๅปบ็ฝฎ**ใ€**้ƒจ็ฝฒ**่ˆ‡**ๅญ˜ๅ–**ๆต็จ‹ใ€‚ + +ๅฎƒๆŠŠ็”จ FastAPI ้–‹็™ผๆ‡‰็”จ็š„ๅŒๆจฃ**้–‹็™ผ่€…้ซ”้ฉ—**ๅธถๅˆฐๅฐ‡ๆ‡‰็”จ**้ƒจ็ฝฒ**ๅˆฐ้›ฒ็ซฏ็š„ๆต็จ‹ไธญใ€‚๐ŸŽ‰ + +FastAPI Cloud ไนŸๆ˜ฏใ€ŒFastAPI ่ˆ‡ๅ…ถๅฅฝๅ‹ใ€้€™ไบ›้–‹ๆบๅฐˆๆกˆ็š„ไธป่ฆ่ดŠๅŠฉ่ˆ‡่ณ‡้‡‘ๆไพ›่€…ใ€‚โœจ + +#### ้ƒจ็ฝฒๅˆฐๅ…ถไป–้›ฒ็ซฏไพ›ๆ‡‰ๅ•† { #deploy-to-other-cloud-providers } + +FastAPI ๆ˜ฏ้–‹ๆบไธฆๅŸบๆ–ผๆจ™ๆบ–็š„ใ€‚ไฝ ๅฏไปฅๆŠŠ FastAPI ๆ‡‰็”จ้ƒจ็ฝฒๅˆฐไฝ ้ธๆ“‡็š„ไปปไฝ•้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ใ€‚ + +ไพ็…งไฝ ็š„้›ฒ็ซฏไพ›ๆ‡‰ๅ•†็š„ๆŒ‡ๅ—้ƒจ็ฝฒ FastAPI ๆ‡‰็”จๅงใ€‚๐Ÿค“ + +## ๅ›ž้กง { #recap } -* ๅผ•ๅ…ฅ `FastAPI`. +* ๅผ•ๅ…ฅ `FastAPI`ใ€‚ * ๅปบ็ซ‹ไธ€ๅ€‹ `app` ๅฏฆไพ‹ใ€‚ -* ๅฏซไธ€ๅ€‹ **่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ** ไฝฟ็”จ่ฃ้ฃพๅ™จๅƒ `@app.get("/")`ใ€‚ -* ๅฎš็พฉไธ€ๅ€‹ **่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ**๏ผ›ไพ‹ๅฆ‚๏ผŒ`def root(): ...`ใ€‚ +* ๅฏซไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€๏ผŒๅƒๆ˜ฏ `@app.get("/")`ใ€‚ +* ๅฎš็พฉไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€๏ผ›ไพ‹ๅฆ‚๏ผŒ`def root(): ...`ใ€‚ * ไฝฟ็”จๅ‘ฝไปค `fastapi dev` ๅŸท่กŒ้–‹็™ผไผบๆœๅ™จใ€‚ +* ๅฏ้ธ๏ผšไฝฟ็”จ `fastapi deploy` ้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผใ€‚ diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md index ae0056f528..5e1961fd7b 100644 --- a/docs/zh-hant/docs/tutorial/index.md +++ b/docs/zh-hant/docs/tutorial/index.md @@ -1,4 +1,4 @@ -# ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ— +# ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ— { #tutorial-user-guide } ๆœฌๆ•™ๅญธๅฐ‡ไธ€ๆญฅไธ€ๆญฅๅฑ•็คบๅฆ‚ไฝ•ไฝฟ็”จ **FastAPI** ๅŠๅ…ถๅคงๅคšๆ•ธๅŠŸ่ƒฝใ€‚ @@ -6,7 +6,7 @@ ๅฎƒไนŸ่ขซ่จญ่จˆๆˆๅฏไฝœ็‚บๆœชไพ†็š„ๅƒ่€ƒ๏ผŒ่ฎ“ไฝ ้šจๆ™‚ๅ›žไพ†ๆŸฅ็œ‹ๆ‰€้œ€็š„ๅ…งๅฎนใ€‚ -## ้‹่กŒ็จ‹ๅผ็ขผ +## ้‹่กŒ็จ‹ๅผ็ขผ { #run-the-code } ๆ‰€ๆœ‰็จ‹ๅผ็ขผๅ€ๅกŠ้ƒฝๅฏไปฅ็›ดๆŽฅ่ค‡่ฃฝๅ’Œไฝฟ็”จ๏ผˆๅฎƒๅ€‘ๅฏฆ้š›ไธŠๆ˜ฏ็ถ“้Žๆธฌ่ฉฆ็š„ Python ๆช”ๆกˆ๏ผ‰ใ€‚ @@ -15,48 +15,39 @@
```console -$ fastapi dev main.py -INFO Using path main.py -INFO Resolved absolute path /home/user/code/awesomeapp/main.py -INFO Searching for package file structure from directories with __init__.py files -INFO Importing from /home/user/code/awesomeapp - - โ•ญโ”€ Python module file โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ ๐Ÿ main.py โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Importing module main -INFO Found importable FastAPI app - - โ•ญโ”€ Importable FastAPI app โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ from main import app โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Using import string main:app - - โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ - โ”‚ โ”‚ - โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ - โ”‚ โ”‚ - โ”‚ Running in development mode, for production use: โ”‚ - โ”‚ โ”‚ - โ”‚ fastapi run โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2265862] using WatchFiles -INFO: Started server process [2265873] -INFO: Waiting for application startup. -INFO: Application startup complete. - +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
@@ -67,7 +58,7 @@ $ fastapi dev -/// note +/// note | ๆณจๆ„ + +็•ถไฝ ไฝฟ็”จ `pip install "fastapi[standard]"` ๅฎ‰่ฃๆ™‚๏ผŒๆœƒๅŒ…ๅซไธ€ไบ›้ ่จญ็š„ๅฏ้ธๆจ™ๆบ–ไพ่ณด้ …๏ผŒๅ…ถไธญๅŒ…ๆ‹ฌ `fastapi-cloud-cli`๏ผŒๅฎƒๅฏไปฅ่ฎ“ไฝ ้ƒจ็ฝฒๅˆฐ FastAPI Cloudใ€‚ -็•ถไฝ ไฝฟ็”จ `pip install "fastapi[standard]"` ๅฎ‰่ฃๆ™‚๏ผŒๆœƒๅŒ…ๅซไธ€ไบ›้ ่จญ็š„ๅฏ้ธๆจ™ๆบ–ไพ่ณด้ …ใ€‚ +ๅฆ‚ๆžœไฝ ไธๆƒณๅŒ…ๅซ้‚ฃไบ›ๅฏ้ธ็š„ไพ่ณด้ …๏ผŒไฝ ๅฏไปฅๆ”น็‚บๅฎ‰่ฃ `pip install fastapi`ใ€‚ -ๅฆ‚ๆžœไฝ ไธๆƒณๅŒ…ๅซ้‚ฃไบ›ๅฏ้ธ็š„ไพ่ณด้ …๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `pip install fastapi` ไพ†ๅฎ‰่ฃใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณๅฎ‰่ฃๆจ™ๆบ–ไพ่ณด้ …๏ผŒไฝ†ไธๅŒ…ๅซ `fastapi-cloud-cli`๏ผŒๅฏไปฅไฝฟ็”จ `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ๅฎ‰่ฃใ€‚ /// -## ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— +## ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— { #advanced-user-guide } -้‚„ๆœ‰ไธ€ๅ€‹**้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—**ไฝ ๅฏไปฅ็จๅพŒ้–ฑ่ฎ€ใ€‚ +้‚„ๆœ‰ไธ€ๅ€‹**้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—**ไฝ ๅฏไปฅๅœจ่ฎ€ๅฎŒ้€™ๅ€‹**ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—**ๅพŒๅ†้–ฑ่ฎ€ใ€‚ **้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—**ๅปบ็ซ‹ๅœจ้€™ๅ€‹ๆ•™ๅญธไน‹ไธŠ๏ผŒไฝฟ็”จ็›ธๅŒ็š„ๆฆ‚ๅฟต๏ผŒไธฆๆ•™ไฝ ไธ€ไบ›้กๅค–็š„ๅŠŸ่ƒฝใ€‚ diff --git a/docs/zh-hant/docs/tutorial/query-param-models.md b/docs/zh-hant/docs/tutorial/query-param-models.md index 76ee740169..e360281990 100644 --- a/docs/zh-hant/docs/tutorial/query-param-models.md +++ b/docs/zh-hant/docs/tutorial/query-param-models.md @@ -1,4 +1,4 @@ -# ๆŸฅ่ฉขๅƒๆ•ธๆจกๅž‹ +# ๆŸฅ่ฉขๅƒๆ•ธๆจกๅž‹ { #query-parameter-models } ๅฆ‚ๆžœไฝ ๆœ‰ไธ€็ต„ๅ…ทๆœ‰็›ธ้—œๆ€ง็š„**ๆŸฅ่ฉขๅƒๆ•ธ**๏ผŒไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹ **Pydantic ๆจกๅž‹**ไพ†่ฒๆ˜Žๅฎƒๅ€‘ใ€‚ @@ -10,7 +10,7 @@ FastAPI ๅพž `0.115.0` ็‰ˆๆœฌ้–‹ๅง‹ๆ”ฏๆด้€™ๅ€‹็‰นๆ€งใ€‚๐Ÿค“ /// -## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ๆŸฅ่ฉขๅƒๆ•ธ +## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ๆŸฅ่ฉขๅƒๆ•ธ { #query-parameters-with-a-pydantic-model } ๅœจไธ€ๅ€‹ **Pydantic ๆจกๅž‹**ไธญ่ฒๆ˜Žไฝ ้œ€่ฆ็š„**ๆŸฅ่ฉขๅƒๆ•ธ**๏ผŒ็„ถๅพŒๅฐ‡ๅƒๆ•ธ่ฒๆ˜Ž็‚บ `Query`๏ผš @@ -18,7 +18,7 @@ FastAPI ๅพž `0.115.0` ็‰ˆๆœฌ้–‹ๅง‹ๆ”ฏๆด้€™ๅ€‹็‰นๆ€งใ€‚๐Ÿค“ **FastAPI** ๅฐ‡ๆœƒๅพž่ซ‹ๆฑ‚็š„**ๆŸฅ่ฉขๅƒๆ•ธ**ไธญ**ๆๅ–**ๅ‡บ**ๆฏๅ€‹ๆฌ„ไฝ**็š„่ณ‡ๆ–™๏ผŒไธฆๅฐ‡ๅ…ถๆไพ›็ตฆไฝ ๅฎš็พฉ็š„ Pydantic ๆจกๅž‹ใ€‚ -## ๆŸฅ็œ‹ๆ–‡ไปถ +## ๆŸฅ็œ‹ๆ–‡ไปถ { #check-the-docs } ไฝ ๅฏไปฅๅœจ `/docs` ้ ้ข็š„ UI ไธญๆŸฅ็œ‹ๆŸฅ่ฉขๅƒๆ•ธ๏ผš @@ -26,7 +26,7 @@ FastAPI ๅพž `0.115.0` ็‰ˆๆœฌ้–‹ๅง‹ๆ”ฏๆด้€™ๅ€‹็‰นๆ€งใ€‚๐Ÿค“ -## ็ฆๆญข้กๅค–็š„ๆŸฅ่ฉขๅƒๆ•ธ +## ็ฆๆญข้กๅค–็š„ๆŸฅ่ฉขๅƒๆ•ธ { #forbid-extra-query-parameters } ๅœจไธ€ไบ›็‰นๆฎŠ็š„ไฝฟ็”จๅ ดๆ™ฏไธญ๏ผˆๅฏ่ƒฝไธๆ˜ฏๅพˆๅธธ่ฆ‹๏ผ‰๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›**้™ๅˆถ**ไฝ ่ฆๆ”ถๅˆฐ็š„ๆŸฅ่ฉขๅƒๆ•ธใ€‚ @@ -57,7 +57,7 @@ https://example.com/items/?limit=10&tool=plumbus } ``` -## ็ธฝ็ต +## ็ธฝ็ต { #summary } ไฝ ๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญ่ฒๆ˜Ž**ๆŸฅ่ฉขๅƒๆ•ธ**ใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index d8e31e08e0..acd1d914ea 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -1,4 +1,4 @@ -# ่™›ๆ“ฌ็’ฐๅขƒ +# ่™›ๆ“ฌ็’ฐๅขƒ { #virtual-environments } ็•ถไฝ ๅœจ Python ๅฐˆๆกˆไธญๅทฅไฝœๆ™‚๏ผŒไฝ ๅฏ่ƒฝๆœƒ้œ€่ฆไฝฟ็”จไธ€ๅ€‹**่™›ๆ“ฌ็’ฐๅขƒ**๏ผˆๆˆ–้กžไผผ็š„ๆฉŸๅˆถ๏ผ‰ไพ†้š”้›ขไฝ ็‚บๆฏๅ€‹ๅฐˆๆกˆๅฎ‰่ฃ็š„ๅฅ—ไปถใ€‚ @@ -26,7 +26,7 @@ /// -## ๅปบ็ซ‹ไธ€ๅ€‹ๅฐˆๆกˆ +## ๅปบ็ซ‹ไธ€ๅ€‹ๅฐˆๆกˆ { #create-a-project } ้ฆ–ๅ…ˆ๏ผŒ็‚บไฝ ็š„ๅฐˆๆกˆๅปบ็ซ‹ไธ€ๅ€‹็›ฎ้Œ„ใ€‚ @@ -51,7 +51,7 @@ $ cd awesome-project -## ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒ +## ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒ { #create-a-virtual-environment } ๅœจ้–‹ๅง‹ไธ€ๅ€‹ Python ๅฐˆๆกˆ็š„**็ฌฌไธ€ๆ™‚้–“**๏ผŒ**ๅœจไฝ ็š„ๅฐˆๆกˆๅ…ง้ƒจ**ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒใ€‚ @@ -114,7 +114,7 @@ $ uv venv /// -## ๅ•Ÿๅ‹•่™›ๆ“ฌ็’ฐๅขƒ +## ๅ•Ÿๅ‹•่™›ๆ“ฌ็’ฐๅขƒ { #activate-the-virtual-environment } ๅ•Ÿๅ‹•ๆ–ฐ็š„่™›ๆ“ฌ็’ฐๅขƒไพ†็ขบไฟไฝ ้‹่กŒ็š„ไปปไฝ• Python ๆŒ‡ไปคๆˆ–ๅฎ‰่ฃ็š„ๅฅ—ไปถ้ƒฝ่ƒฝไฝฟ็”จๅˆฐๅฎƒใ€‚ @@ -166,11 +166,11 @@ $ source .venv/Scripts/activate ๆฏๆฌกไฝ ๅœจ้€™ๅ€‹็’ฐๅขƒไธญๅฎ‰่ฃไธ€ๅ€‹**ๆ–ฐ็š„ๅฅ—ไปถ**ๆ™‚๏ผŒ้ƒฝ้œ€่ฆ**้‡ๆ–ฐๅ•Ÿๅ‹•**้€™ๅ€‹็’ฐๅขƒใ€‚ -้€™้บผๅš็ขบไฟไบ†็•ถไฝ ไฝฟ็”จไธ€ๅ€‹็”ฑ้€™ๅ€‹ๅฅ—ไปถๅฎ‰่ฃ็š„**็ต‚็ซฏ๏ผˆCLI๏ผ‰็จ‹ๅผ**ๆ™‚๏ผŒไฝ ไฝฟ็”จ็š„ๆ˜ฏไฝ ็š„่™›ๆ“ฌ็’ฐๅขƒไธญ็š„็จ‹ๅผ๏ผŒ่€Œไธๆ˜ฏๅ…จๅŸŸๅฎ‰่ฃใ€ๅฏ่ƒฝ็‰ˆๆœฌไธๅŒ็š„็จ‹ๅผใ€‚ +้€™้บผๅš็ขบไฟไบ†็•ถไฝ ไฝฟ็”จไธ€ๅ€‹็”ฑ้€™ๅ€‹ๅฅ—ไปถๅฎ‰่ฃ็š„**็ต‚็ซฏ๏ผˆCLI๏ผ‰็จ‹ๅผ**ๆ™‚๏ผŒไฝ ไฝฟ็”จ็š„ๆ˜ฏไฝ ็š„่™›ๆ“ฌ็’ฐๅขƒไธญ็š„็จ‹ๅผ๏ผŒ่€Œไธๆ˜ฏๅ…จๅŸŸๅฎ‰่ฃใ€ๅฏ่ƒฝ็‰ˆๆœฌไธๅŒ็š„็จ‹ๅผใ€‚ /// -## ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒๆ˜ฏๅฆๅ•Ÿๅ‹• +## ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒๆ˜ฏๅฆๅ•Ÿๅ‹• { #check-the-virtual-environment-is-active } ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒๆ˜ฏๅฆๅ•Ÿๅ‹•๏ผˆๅ‰้ข็š„ๆŒ‡ไปคๆ˜ฏๅฆ็”Ÿๆ•ˆ๏ผ‰ใ€‚ @@ -212,7 +212,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -## ๅ‡็ดš `pip` +## ๅ‡็ดš `pip` { #upgrade-pip } /// tip @@ -242,7 +242,27 @@ $ python -m pip install --upgrade pip -## ๅŠ ๅ…ฅ `.gitignore` +/// tip | ๆณจๆ„ + +ๆœ‰ๆ™‚ไฝ ๅœจๅ˜—่ฉฆๅ‡็ดš pip ๆ™‚๏ผŒๅฏ่ƒฝๆœƒ้‡ๅˆฐ **`No module named pip`** ็š„้Œฏ่ชคใ€‚ + +ๅฆ‚ๆžœ็™ผ็”Ÿ้€™็จฎๆƒ…ๆณ๏ผŒ่ซ‹็”จไธ‹้ข็š„ๆŒ‡ไปคๅฎ‰่ฃไธฆๅ‡็ดš pip๏ผš + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +ๆญคๆŒ‡ไปคๆœƒๅœจๆœชๅฎ‰่ฃ pip ๆ™‚็‚บไฝ ๅฎ‰่ฃๅฎƒ๏ผŒไธฆ็ขบไฟๅฎ‰่ฃ็š„ pip ็‰ˆๆœฌ่‡ณๅฐ‘่ˆ‡ `ensurepip` ๆ‰€ๆไพ›็š„็‰ˆๆœฌไธ€ๆจฃๆ–ฐใ€‚ + +/// + +## ๅŠ ๅ…ฅ `.gitignore` { #add-gitignore } ๅฆ‚ๆžœไฝ ไฝฟ็”จ **Git**๏ผˆ้€™ๆ˜ฏไฝ ๆ‡‰่ฉฒไฝฟ็”จ็š„๏ผ‰๏ผŒๅŠ ๅ…ฅไธ€ๅ€‹ `.gitignore` ๆช”ๆกˆไพ†ๆŽ’้™คไฝ ็š„ `.venv` ไธญ็š„ๆ‰€ๆœ‰ๅ…งๅฎนใ€‚ @@ -282,7 +302,7 @@ $ echo "*" > .venv/.gitignore /// -## ๅฎ‰่ฃๅฅ—ไปถ +## ๅฎ‰่ฃๅฅ—ไปถ { #install-packages } ๅœจๅ•Ÿ็”จ่™›ๆ“ฌ็’ฐๅขƒๅพŒ๏ผŒไฝ ๅฏไปฅๅœจๅ…ถไธญๅฎ‰่ฃๅฅ—ไปถใ€‚ @@ -294,7 +314,7 @@ $ echo "*" > .venv/.gitignore /// -### ็›ดๆŽฅๅฎ‰่ฃๅฅ—ไปถ +### ็›ดๆŽฅๅฎ‰่ฃๅฅ—ไปถ { #install-packages-directly } ๅฆ‚ๆžœไฝ ๆ€ฅๆ–ผๅฎ‰่ฃ๏ผŒไธๆƒณไฝฟ็”จๆช”ๆกˆไพ†่ฒๆ˜Žๅฐˆๆกˆ็š„ๅฅ—ไปถไพ่ณด๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅฎ‰่ฃๅฎƒๅ€‘ใ€‚ @@ -333,7 +353,7 @@ $ uv pip install "fastapi[standard]" //// -### ๅพž `requirements.txt` ๅฎ‰่ฃ +### ๅพž `requirements.txt` ๅฎ‰่ฃ { #install-from-requirements-txt } ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹ `requirements.txt` ๆช”ๆกˆ๏ผŒไฝ ๅฏไปฅไฝฟ็”จๅฎƒไพ†ๅฎ‰่ฃๅ…ถไธญ็š„ๅฅ—ไปถใ€‚ @@ -376,7 +396,7 @@ pydantic==2.8.0 /// -## ๅŸท่กŒ็จ‹ๅผ +## ๅŸท่กŒ็จ‹ๅผ { #run-your-program } ๅœจๅ•Ÿ็”จ่™›ๆ“ฌ็’ฐๅขƒๅพŒ๏ผŒไฝ ๅฏไปฅๅŸท่กŒไฝ ็š„็จ‹ๅผ๏ผŒๅฎƒๅฐ‡ไฝฟ็”จ่™›ๆ“ฌ็’ฐๅขƒไธญ็š„ Python ๅ’Œไฝ ๅœจๅ…ถไธญๅฎ‰่ฃ็š„ๅฅ—ไปถใ€‚ @@ -390,7 +410,7 @@ Hello World -## ่จญๅฎš็ทจ่ผฏๅ™จ +## ่จญๅฎš็ทจ่ผฏๅ™จ { #configure-your-editor } ไฝ ๅฏ่ƒฝๆœƒ็”จๅˆฐ็ทจ่ผฏๅ™จ๏ผŒ่ซ‹็ขบไฟ่จญๅฎšๅฎƒไฝฟ็”จไฝ ๅปบ็ซ‹็š„็›ธๅŒ่™›ๆ“ฌ็’ฐๅขƒ๏ผˆๅฎƒๅฏ่ƒฝๆœƒ่‡ชๅ‹•ๅตๆธฌๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ็ฒๅพ—่‡ชๅ‹•ๅฎŒๆˆๅ’Œๅ†…ๅตŒ้Œฏ่ชคๆ็คบใ€‚ @@ -405,7 +425,7 @@ Hello World /// -## ้€€ๅ‡บ่™›ๆ“ฌ็’ฐๅขƒ +## ้€€ๅ‡บ่™›ๆ“ฌ็’ฐๅขƒ { #deactivate-the-virtual-environment } ็•ถไฝ ๅฎŒๆˆๅทฅไฝœๅพŒ๏ผŒไฝ ๅฏไปฅ**้€€ๅ‡บ**่™›ๆ“ฌ็’ฐๅขƒใ€‚ @@ -419,7 +439,7 @@ $ deactivate ้€™ๆจฃ๏ผŒ็•ถไฝ ๅŸท่กŒ `python` ๆ™‚ๅฎƒไธๆœƒๅ˜—่ฉฆๅพžๅทฒๅฎ‰่ฃๅฅ—ไปถ็š„่™›ๆ“ฌ็’ฐๅขƒไธญๅŸท่กŒใ€‚ -## ้–‹ๅง‹ๅทฅไฝœ +## ้–‹ๅง‹ๅทฅไฝœ { #ready-to-work } ็พๅœจไฝ ๅทฒ็ถ“ๆบ–ๅ‚™ๅฅฝ้–‹ๅง‹ไฝ ็š„ๅทฅไฝœไบ†ใ€‚ @@ -433,7 +453,7 @@ $ deactivate /// -## ็‚บไป€้บผ่ฆไฝฟ็”จ่™›ๆ“ฌ็’ฐๅขƒ +## ็‚บไป€้บผ่ฆไฝฟ็”จ่™›ๆ“ฌ็’ฐๅขƒ { #why-virtual-environments } ไฝ ้œ€่ฆๅฎ‰่ฃ Python ๆ‰่ƒฝไฝฟ็”จ FastAPIใ€‚ @@ -443,7 +463,7 @@ $ deactivate ็„ถ่€Œ๏ผŒๅฆ‚ๆžœไฝ ็›ดๆŽฅไฝฟ็”จ `pip`๏ผŒๅฅ—ไปถๅฐ‡ๆœƒๅฎ‰่ฃๅœจไฝ ็š„**ๅ…จๅŸŸ Python ็’ฐๅขƒ**ไธญ๏ผˆๅณ Python ็š„ๅ…จๅŸŸๅฎ‰่ฃ๏ผ‰ใ€‚ -### ๅญ˜ๅœจ็š„ๅ•้กŒ +### ๅญ˜ๅœจ็š„ๅ•้กŒ { #the-problem } ้‚ฃ้บผ๏ผŒๅœจๅ…จๅŸŸ Python ็’ฐๅขƒไธญๅฎ‰่ฃๅฅ—ไปถๆœ‰ไป€้บผๅ•้กŒๅ‘ข๏ผŸ @@ -526,7 +546,7 @@ Python ๅฅ—ไปถๅœจๆŽจๅ‡บ**ๆ–ฐ็‰ˆๆœฌ**ๆ™‚้€šๅธธๆœƒๅ„˜้‡**้ฟๅ…็ ดๅฃžๆ€งๆ›ดๆ”น** ๆญคๅค–๏ผŒๅ–ๆฑบๆ–ผไฝ ็š„ๆ“ไฝœ็ณป็ตฑ๏ผˆไพ‹ๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰๏ผŒๅฎƒๅฏ่ƒฝๅทฒ็ถ“้ ๅ…ˆๅฎ‰่ฃไบ† Pythonใ€‚ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฎƒๅฏ่ƒฝๅทฒ็ถ“ๆœ‰ไธ€ไบ›็ณป็ตฑๆ‰€้œ€็š„ๅฅ—ไปถๅ’Œ็‰นๅฎš็‰ˆๆœฌใ€‚ๅฆ‚ๆžœไฝ ๅœจๅ…จๅŸŸ Python ็’ฐๅขƒไธญๅฎ‰่ฃๅฅ—ไปถ๏ผŒๅฏ่ƒฝๆœƒ**็ ดๅฃž**ๆŸไบ›้šจไฝœๆฅญ็ณป็ตฑไธ€่ตทๅฎ‰่ฃ็š„็จ‹ๅผใ€‚ -## ๅฅ—ไปถๅฎ‰่ฃๅœจๅ“ช่ฃก +## ๅฅ—ไปถๅฎ‰่ฃๅœจๅ“ช่ฃก { #where-are-packages-installed } ็•ถไฝ ๅฎ‰่ฃ Python ๆ™‚๏ผŒๅฎƒๆœƒๅœจไฝ ็š„้›ป่…ฆไธญๅปบ็ซ‹ไธ€ไบ›็›ฎ้Œ„ไธฆๆ”พ็ฝฎไธ€ไบ›ๆช”ๆกˆใ€‚ @@ -552,7 +572,7 @@ $ pip install "fastapi[standard]" ้ ่จญๆƒ…ๆณไธ‹๏ผŒ้€™ไบ›ไธ‹่ผ‰ๅ’Œ่งฃๅฃ“็š„ๆช”ๆกˆๆœƒๆ”พ็ฝฎๆ–ผ้šจ Python ๅฎ‰่ฃ็š„็›ฎ้Œ„ไธญ๏ผŒๅณ**ๅ…จๅŸŸ็’ฐๅขƒ**ใ€‚ -## ไป€้บผๆ˜ฏ่™›ๆ“ฌ็’ฐๅขƒ +## ไป€้บผๆ˜ฏ่™›ๆ“ฌ็’ฐๅขƒ { #what-are-virtual-environments } ่งฃๆฑบๅฅ—ไปถ้ƒฝๅฎ‰่ฃๅœจๅ…จๅŸŸ็’ฐๅขƒไธญ็š„ๅ•้กŒๆ–นๆณ•ๆ˜ฏ็‚บไฝ ๆ‰€ๅš็š„ๆฏๅ€‹ๅฐˆๆกˆไฝฟ็”จไธ€ๅ€‹**่™›ๆ“ฌ็’ฐๅขƒ**ใ€‚ @@ -577,7 +597,7 @@ flowchart TB stone-project ~~~ azkaban-project ``` -## ๅ•Ÿ็”จ่™›ๆ“ฌ็’ฐๅขƒๆ„ๅ‘ณ่‘—ไป€้บผ +## ๅ•Ÿ็”จ่™›ๆ“ฌ็’ฐๅขƒๆ„ๅ‘ณ่‘—ไป€้บผ { #what-does-activating-a-virtual-environment-mean } ็•ถไฝ ๅ•Ÿ็”จไบ†่™›ๆ“ฌ็’ฐๅขƒ๏ผŒไพ‹ๅฆ‚๏ผš @@ -714,7 +734,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ๅ•Ÿ็”จ่™›ๆ“ฌ็’ฐๅขƒ้‚„ๆœƒๆ”น่ฎŠๅ…ถไป–ไธ€ไบ›ๅ…งๅฎน๏ผŒไฝ†้€™ๆ˜ฏๅฎƒๆ‰€ๅš็š„ๆœ€้‡่ฆ็š„ไบ‹ๆƒ…ไน‹ไธ€ใ€‚ -## ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒ +## ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒ { #checking-a-virtual-environment } ็•ถไฝ ๆชขๆŸฅ่™›ๆ“ฌ็’ฐๅขƒๆ˜ฏๅฆๅ•Ÿๅ‹•ๆ™‚๏ผŒไพ‹ๅฆ‚๏ผš @@ -766,7 +786,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// -## ็‚บไป€้บผ่ฆๅœ็”จ่™›ๆ“ฌ็’ฐๅขƒ +## ็‚บไป€้บผ่ฆๅœ็”จ่™›ๆ“ฌ็’ฐๅขƒ { #why-deactivate-a-virtual-environment } ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๆญฃๅœจไธ€ๅ€‹ๅฐˆๆกˆ `philosophers-stone` ไธŠๅทฅไฝœ๏ผŒ**ๅ•Ÿๅ‹•ไบ†่ฉฒ่™›ๆ“ฌ็’ฐๅขƒ**๏ผŒๅฎ‰่ฃไบ†ๅฅ—ไปถไธฆไฝฟ็”จไบ†่ฉฒ็’ฐๅขƒ๏ผŒ @@ -820,7 +840,7 @@ I solemnly swear ๐Ÿบ -## ๆ›ฟไปฃๆ–นๆกˆ +## ๆ›ฟไปฃๆ–นๆกˆ { #alternatives } ้€™ๆ˜ฏไธ€ๅ€‹็ฐกๅ–ฎ็š„ๆŒ‡ๅ—๏ผŒๅนซๅŠฉไฝ ๅ…ฅ้–€ไธฆๆ•™ๆœƒไฝ ๅฆ‚ไฝ•็†่งฃไธ€ๅˆ‡**ๅบ•ๅฑค**็š„ๅŽŸ็†ใ€‚ @@ -837,7 +857,7 @@ I solemnly swear ๐Ÿบ * ็ขบไฟไฝ ๆœ‰ไธ€ๅ€‹**็ฒพ็ขบ**็š„ๅฅ—ไปถๅ’Œ็‰ˆๆœฌ้›†ๅˆไพ†ๅฎ‰่ฃ๏ผŒๅŒ…ๆ‹ฌๅฎƒๅ€‘็š„ไพ่ณด้ …๏ผŒ้€™ๆจฃไฝ ๅฏไปฅ็ขบไฟๅฐˆๆกˆๅœจ็”Ÿ็”ข็’ฐๅขƒไธญ้‹่กŒ็š„็‹€ๆ…‹่ˆ‡้–‹็™ผๆ™‚ๅœจไฝ ็š„้›ป่…ฆไธŠ้‹่กŒ็š„็‹€ๆ…‹ๅฎŒๅ…จ็›ธๅŒ๏ผŒ้€™่ขซ็จฑ็‚บ**้Ž–ๅฎš** * ้‚„ๆœ‰ๅพˆๅคšๅ…ถไป–ๅŠŸ่ƒฝ -## ็ต่ซ– +## ็ต่ซ– { #conclusion } ๅฆ‚ๆžœไฝ ่ฎ€้Žไธฆ็†่งฃไบ†ๆ‰€ๆœ‰้€™ไบ›๏ผŒ็พๅœจ**ไฝ ๅฐ่™›ๆ“ฌ็’ฐๅขƒ็š„ไบ†่งฃๅทฒ่ถ…้Ž่จฑๅคš้–‹็™ผ่€…**ใ€‚๐Ÿค“ From f23ea3bd957df9add546af378407b058473b453b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 15:33:24 +0000 Subject: [PATCH 111/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f52be20d3b..9f70eccb59 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). From 6ff8ff5b57bdbfb93030899091fe8219a722a74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:34:19 -0800 Subject: [PATCH 112/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(update-outdated)=20(#14826)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/fr/docs/advanced/additional-responses.md | 38 +- .../docs/advanced/additional-status-codes.md | 20 +- docs/fr/docs/advanced/index.md | 18 +- .../path-operation-advanced-configuration.md | 114 ++-- docs/fr/docs/advanced/response-directly.md | 30 +- docs/fr/docs/benchmarks.md | 36 +- docs/fr/docs/deployment/docker.md | 587 +++++++++++++++--- docs/fr/docs/deployment/https.md | 259 ++++++-- docs/fr/docs/deployment/index.md | 8 +- docs/fr/docs/deployment/versions.md | 76 +-- docs/fr/docs/index.md | 401 +++++++----- docs/fr/docs/learn/index.md | 4 +- docs/fr/docs/project-generation.md | 112 +--- docs/fr/docs/python-types.md | 413 ++++++++---- docs/fr/docs/tutorial/background-tasks.md | 50 +- docs/fr/docs/tutorial/body-multiple-params.md | 82 +-- docs/fr/docs/tutorial/body.md | 80 +-- docs/fr/docs/tutorial/debugging.md | 24 +- docs/fr/docs/tutorial/first-steps.md | 311 ++++++---- docs/fr/docs/tutorial/index.md | 78 ++- .../path-params-numeric-validations.md | 49 +- docs/fr/docs/tutorial/path-params.md | 225 ++++--- .../tutorial/query-params-str-validations.md | 409 ++++++++---- docs/fr/docs/tutorial/query-params.md | 133 ++-- 24 files changed, 2279 insertions(+), 1278 deletions(-) diff --git a/docs/fr/docs/advanced/additional-responses.md b/docs/fr/docs/advanced/additional-responses.md index 38527aad3c..dabcded52e 100644 --- a/docs/fr/docs/advanced/additional-responses.md +++ b/docs/fr/docs/advanced/additional-responses.md @@ -1,6 +1,6 @@ -# Rรฉponses supplรฉmentaires dans OpenAPI +# Rรฉponses supplรฉmentaires dans OpenAPI { #additional-responses-in-openapi } -/// warning | Attention +/// warning | Alertes Ceci concerne un sujet plutรดt avancรฉ. @@ -14,9 +14,9 @@ Ces rรฉponses supplรฉmentaires seront incluses dans le schรฉma OpenAPI, elles ap Mais pour ces rรฉponses supplรฉmentaires, vous devez vous assurer de renvoyer directement une `Response` comme `JSONResponse`, avec votre code HTTP et votre contenu. -## Rรฉponse supplรฉmentaire avec `model` +## Rรฉponse supplรฉmentaire avec `model` { #additional-response-with-model } -Vous pouvez ajouter ร  votre dรฉcorateur de *paramรจtre de chemin* un paramรจtre `responses`. +Vous pouvez passer ร  vos dรฉcorateurs de *chemin d'accรจs* un paramรจtre `responses`. Il prend comme valeur un `dict` dont les clรฉs sont des codes HTTP pour chaque rรฉponse, comme `200`, et la valeur de ces clรฉs sont d'autres `dict` avec des informations pour chacun d'eux. @@ -26,7 +26,7 @@ Chacun de ces `dict` de rรฉponse peut avoir une clรฉ `model`, contenant un modรจ Par exemple, pour dรฉclarer une autre rรฉponse avec un code HTTP `404` et un modรจle Pydantic `Message`, vous pouvez รฉcrireย : -{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} /// note | Remarque @@ -49,7 +49,7 @@ Le bon endroit est : /// -Les rรฉponses gรฉnรฉrรฉes au format OpenAPI pour cette *opรฉration de chemin* serontย : +Les rรฉponses gรฉnรฉrรฉes au format OpenAPI pour ce *chemin d'accรจs* serontย : ```JSON hl_lines="3-12" { @@ -169,13 +169,13 @@ Les schรฉmas sont rรฉfรฉrencรฉs ร  un autre endroit du modรจle OpenAPIย : } ``` -## Types de mรฉdias supplรฉmentaires pour la rรฉponse principale +## Types de mรฉdias supplรฉmentaires pour la rรฉponse principale { #additional-media-types-for-the-main-response } Vous pouvez utiliser ce mรชme paramรจtre `responses` pour ajouter diffรฉrents types de mรฉdias pour la mรชme rรฉponse principale. -Par exemple, vous pouvez ajouter un type de mรฉdia supplรฉmentaire `image/png`, en dรฉclarant que votre *opรฉration de chemin* peut renvoyer un objet JSON (avec le type de mรฉdia `application/json`) ou une image PNGย : +Par exemple, vous pouvez ajouter un type de mรฉdia supplรฉmentaire `image/png`, en dรฉclarant que votre *chemin d'accรจs* peut renvoyer un objet JSON (avec le type de mรฉdia `application/json`) ou une image PNGย : -{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *} +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} /// note | Remarque @@ -191,7 +191,7 @@ Mais si vous avez spรฉcifiรฉ une classe de rรฉponse personnalisรฉe avec `None` c /// -## Combinaison d'informations +## Combiner les informations { #combining-information } Vous pouvez รฉgalement combiner des informations de rรฉponse provenant de plusieurs endroits, y compris les paramรจtres `response_model`, `status_code` et `responses`. @@ -203,17 +203,17 @@ Par exemple, vous pouvez dรฉclarer une rรฉponse avec un code HTTP `404` qui util Et une rรฉponse avec un code HTTP `200` qui utilise votre `response_model`, mais inclut un `example` personnalisรฉย : -{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} Tout sera combinรฉ et inclus dans votre OpenAPI, et affichรฉ dans la documentation de l'APIย : -##ย Combinez les rรฉponses prรฉdรฉfinies et les rรฉponses personnalisรฉes +## Combinez les rรฉponses prรฉdรฉfinies et les rรฉponses personnalisรฉes { #combine-predefined-responses-and-custom-ones } -Vous voulez peut-รชtre avoir des rรฉponses prรฉdรฉfinies qui s'appliquent ร  de nombreux *paramรจtre de chemin*, mais vous souhaitez les combiner avec des rรฉponses personnalisรฉes nรฉcessaires ร  chaque *opรฉration de chemin*. +Vous voulez peut-รชtre avoir des rรฉponses prรฉdรฉfinies qui s'appliquent ร  de nombreux *chemins d'accรจs*, mais vous souhaitez les combiner avec des rรฉponses personnalisรฉes nรฉcessaires ร  chaque *chemin d'accรจs*. -Dans ces cas, vous pouvez utiliser la technique Python "d'affection par dรฉcomposition" (appelรฉ _unpacking_ en anglais) d'un `dict` avec `**dict_to_unpack`ย : +Dans ces cas, vous pouvez utiliser la technique Python ยซ unpacking ยป d'un `dict` avec `**dict_to_unpack`ย : ```Python old_dict = { @@ -233,15 +233,15 @@ Ici, `new_dict` contiendra toutes les paires clรฉ-valeur de `old_dict` plus la n } ``` -Vous pouvez utiliser cette technique pour rรฉutiliser certaines rรฉponses prรฉdรฉfinies dans vos *paramรจtres de chemin* et les combiner avec des rรฉponses personnalisรฉes supplรฉmentaires. +Vous pouvez utiliser cette technique pour rรฉutiliser certaines rรฉponses prรฉdรฉfinies dans vos *chemins d'accรจs* et les combiner avec des rรฉponses personnalisรฉes supplรฉmentaires. Par exemple: -{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} -## Plus d'informations sur les rรฉponses OpenAPI +## Plus d'informations sur les rรฉponses OpenAPI { #more-information-about-openapi-responses } Pour voir exactement ce que vous pouvez inclure dans les rรฉponses, vous pouvez consulter ces sections dans la spรฉcification OpenAPIย : -* Objet Responses de OpenAPI , il inclut le `Response Object`. -* Objet Response de OpenAPI , vous pouvez inclure n'importe quoi directement dans chaque rรฉponse ร  l'intรฉrieur de votre paramรจtre `responses`. Y compris `description`, `headers`, `content` (ร  l'intรฉrieur de cela, vous dรฉclarez diffรฉrents types de mรฉdias et schรฉmas JSON) et `links`. +* Objet Responses de OpenAPI, il inclut le `Response Object`. +* Objet Response de OpenAPI, vous pouvez inclure n'importe quoi directement dans chaque rรฉponse ร  l'intรฉrieur de votre paramรจtre `responses`. Y compris `description`, `headers`, `content` (ร  l'intรฉrieur de cela, vous dรฉclarez diffรฉrents types de mรฉdias et schรฉmas JSON) et `links`. diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md index dde6b9a63f..b2befffa8d 100644 --- a/docs/fr/docs/advanced/additional-status-codes.md +++ b/docs/fr/docs/advanced/additional-status-codes.md @@ -1,28 +1,28 @@ -# Codes HTTP supplรฉmentaires +# Codes HTTP supplรฉmentaires { #additional-status-codes } Par dรฉfaut, **FastAPI** renverra les rรฉponses ร  l'aide d'une structure de donnรฉes `JSONResponse`, en plaรงant la rรฉponse de votre *chemin d'accรจs* ร  l'intรฉrieur de cette `JSONResponse`. Il utilisera le code HTTP par dรฉfaut ou celui que vous avez dรฉfini dans votre *chemin d'accรจs*. -## Codes HTTP supplรฉmentaires +## Codes HTTP supplรฉmentaires { #additional-status-codes_1 } Si vous souhaitez renvoyer des codes HTTP supplรฉmentaires en plus du code principal, vous pouvez le faire en renvoyant directement une `Response`, comme une `JSONResponse`, et en dรฉfinissant directement le code HTTP supplรฉmentaire. -Par exemple, disons que vous voulez avoir un *chemin d'accรจs* qui permet de mettre ร  jour les รฉlรฉments et renvoie les codes HTTP 200 "OK" en cas de succรจs. +Par exemple, disons que vous voulez avoir un *chemin d'accรจs* qui permet de mettre ร  jour les รฉlรฉments et renvoie les codes HTTP 200 ยซ OK ยป en cas de succรจs. -Mais vous voulez aussi qu'il accepte de nouveaux รฉlรฉments. Et lorsque les รฉlรฉments n'existaient pas auparavant, il les crรฉe et renvoie un code HTTP de 201 "Crรฉรฉ". +Mais vous voulez aussi qu'il accepte de nouveaux รฉlรฉments. Et lorsque les รฉlรฉments n'existaient pas auparavant, il les crรฉe et renvoie un code HTTP de 201 ยซ Crรฉรฉ ยป. Pour y parvenir, importez `JSONResponse` et renvoyez-y directement votre contenu, en dรฉfinissant le `status_code` que vous souhaitezย : -{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *} +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning | Attention +/// warning | Alertes Lorsque vous renvoyez une `Response` directement, comme dans l'exemple ci-dessus, elle sera renvoyรฉe directement. Elle ne sera pas sรฉrialisรฉe avec un modรจle. -Assurez-vous qu'il contient les donnรฉes souhaitรฉes et que les valeurs soient dans un format JSON valides (si vous utilisez une `JSONResponse`). +Assurez-vous qu'il contient les donnรฉes souhaitรฉes et que les valeurs sont dans un format JSON valide (si vous utilisez une `JSONResponse`). /// @@ -30,12 +30,12 @@ Assurez-vous qu'il contient les donnรฉes souhaitรฉes et que les valeurs soient d Vous pouvez รฉgalement utiliser `from starlette.responses import JSONResponse`. -Pour plus de commoditรฉs, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. Il en est de mรชme avec l'objet `statut`. +Pour plus de commoditรฉs, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. Il en est de mรชme avec `status`. /// -##ย Documents OpenAPI et API +## Documents OpenAPI et API { #openapi-and-api-docs } Si vous renvoyez directement des codes HTTP et des rรฉponses supplรฉmentaires, ils ne seront pas inclus dans le schรฉma OpenAPI (la documentation de l'API), car FastAPI n'a aucun moyen de savoir ร  l'avance ce que vous allez renvoyer. -Mais vous pouvez documenter cela dans votre code, en utilisantย : [Rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. +Mais vous pouvez documenter cela dans votre code, en utilisantย : [Rรฉponses supplรฉmentaires](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/advanced/index.md b/docs/fr/docs/advanced/index.md index d9d8ad8e60..a2f9d3b1bb 100644 --- a/docs/fr/docs/advanced/index.md +++ b/docs/fr/docs/advanced/index.md @@ -1,27 +1,21 @@ -# Guide de l'utilisateur avancรฉ +# Guide de l'utilisateur avancรฉ { #advanced-user-guide } -## Caractรฉristiques supplรฉmentaires +## Caractรฉristiques supplรฉmentaires { #additional-features } Le [Tutoriel - Guide de l'utilisateur](../tutorial/index.md){.internal-link target=_blank} devrait suffire ร  vous faire dรฉcouvrir toutes les fonctionnalitรฉs principales de **FastAPI**. Dans les sections suivantes, vous verrez des options, configurations et fonctionnalitรฉs supplรฉmentaires. -/// note | Remarque +/// tip | Astuce -Les sections de ce chapitre ne sont **pas nรฉcessairement "avancรฉes"**. +Les sections suivantes ne sont **pas nรฉcessairement ยซ avancรฉes ยป**. -Et il est possible que pour votre cas d'utilisation, la solution se trouve dans l'un d'entre eux. +Et il est possible que, pour votre cas d'utilisation, la solution se trouve dans l'une d'entre elles. /// -## Lisez d'abord le didacticiel +## Lire d'abord le tutoriel { #read-the-tutorial-first } Vous pouvez utiliser la plupart des fonctionnalitรฉs de **FastAPI** grรขce aux connaissances du [Tutoriel - Guide de l'utilisateur](../tutorial/index.md){.internal-link target=_blank}. Et les sections suivantes supposent que vous l'avez lu et que vous en connaissez les idรฉes principales. - -## Cours TestDriven.io - -Si vous souhaitez suivre un cours pour dรฉbutants avancรฉs pour complรฉter cette section de la documentation, vous pouvez consulterย : Dรฉveloppement pilotรฉ par les tests avec FastAPI et Docker par **TestDriven.io**. - -10ย % de tous les bรฉnรฉfices de ce cours sont reversรฉs au dรฉveloppement de **FastAPI**. ๐ŸŽ‰ ๐Ÿ˜„ diff --git a/docs/fr/docs/advanced/path-operation-advanced-configuration.md b/docs/fr/docs/advanced/path-operation-advanced-configuration.md index 7daf0fc65f..fc88f33633 100644 --- a/docs/fr/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/fr/docs/advanced/path-operation-advanced-configuration.md @@ -1,106 +1,108 @@ -# Configuration avancรฉe des paramรจtres de chemin +# Configuration avancรฉe des chemins d'accรจs { #path-operation-advanced-configuration } -## ID d'opรฉration OpenAPI +## ID dโ€™opรฉration OpenAPI { #openapi-operationid } -/// warning | Attention +/// warning | Alertes -Si vous n'รชtes pas un "expert" en OpenAPI, vous n'en avez probablement pas besoin. +Si vous nโ€™รชtes pas un ยซ expert ยป dโ€™OpenAPI, vous nโ€™en avez probablement pas besoin. /// -Dans OpenAPI, les chemins sont des ressources, tels que /users/ ou /items/, exposรฉes par votre API, et les opรฉrations sont les mรฉthodes HTTP utilisรฉes pour manipuler ces chemins, telles que GET, POST ou DELETE. Les operationId sont des chaรฎnes uniques facultatives utilisรฉes pour identifier une opรฉration d'un chemin. Vous pouvez dรฉfinir l'OpenAPI `operationId` ร  utiliser dans votre *opรฉration de chemin* avec le paramรจtre `operation_id`. +Vous pouvez dรฉfinir lโ€™OpenAPI `operationId` ร  utiliser dans votre chemin dโ€™accรจs avec le paramรจtre `operation_id`. -Vous devez vous assurer qu'il est unique pour chaque opรฉration. +Vous devez vous assurer quโ€™il est unique pour chaque opรฉration. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} -### Utilisation du nom *path operation function* comme operationId +### Utiliser le nom de la fonction de chemin dโ€™accรจs comme operationId { #using-the-path-operation-function-name-as-the-operationid } -Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer chaque `operation_id` de l'*opรฉration de chemin* en utilisant leur `APIRoute.name`. +Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer lโ€™`operation_id` de chaque chemin dโ€™accรจs en utilisant leur `APIRoute.name`. -Vous devriez le faire aprรจs avoir ajoutรฉ toutes vos *paramรจtres de chemin*. +Vous devez le faire aprรจs avoir ajoutรฉ tous vos chemins dโ€™accรจs. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} /// tip | Astuce -Si vous appelez manuellement `app.openapi()`, vous devez mettre ร  jour les `operationId` avant. +Si vous appelez manuellement `app.openapi()`, vous devez mettre ร  jour les `operationId` avant cela. /// -/// warning | Attention +/// warning | Alertes -Pour faire cela, vous devez vous assurer que chacun de vos *chemin* ait un nom unique. +Si vous faites cela, vous devez vous assurer que chacune de vos fonctions de chemin dโ€™accรจs a un nom unique. -Mรชme s'ils se trouvent dans des modules diffรฉrents (fichiers Python). +Mรชme si elles se trouvent dans des modules diffรฉrents (fichiers Python). /// -## Exclusion d'OpenAPI +## Exclusion dโ€™OpenAPI { #exclude-from-openapi } -Pour exclure un *chemin* du schรฉma OpenAPI gรฉnรฉrรฉ (et donc des systรจmes de documentation automatiques), utilisez le paramรจtre `include_in_schema` et assignez-lui la valeur `False`ย : +Pour exclure un chemin dโ€™accรจs du schรฉma OpenAPI gรฉnรฉrรฉ (et donc des systรจmes de documentation automatiques), utilisez le paramรจtre `include_in_schema` et dรฉfinissez-le ร  `False` : -{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} -## Description avancรฉe de docstring +## Description avancรฉe depuis la docstring { #advanced-description-from-docstring } -Vous pouvez limiter le texte utilisรฉ de la docstring d'une *fonction de chemin* qui sera affichรฉ sur OpenAPI. +Vous pouvez limiter les lignes utilisรฉes de la docstring dโ€™une fonction de chemin dโ€™accรจs pour OpenAPI. -L'ajout d'un `\f` (un caractรจre d'รฉchappement "form feed") va permettre ร  **FastAPI** de tronquer la sortie utilisรฉe pour OpenAPI ร  ce stade. +Lโ€™ajout dโ€™un `\f` (un caractรจre ยซ saut de page ยป รฉchappรฉ) amรจne **FastAPI** ร  tronquer la sortie utilisรฉe pour OpenAPI ร  cet endroit. -Il n'apparaรฎtra pas dans la documentation, mais d'autres outils (tel que Sphinx) pourront utiliser le reste. +Cela nโ€™apparaรฎtra pas dans la documentation, mais dโ€™autres outils (comme Sphinx) pourront utiliser le reste. -{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} -##ย Rรฉponses supplรฉmentaires +## Rรฉponses supplรฉmentaires { #additional-responses } -Vous avez probablement vu comment dรฉclarer le `response_model` et le `status_code` pour une *opรฉration de chemin*. +Vous avez probablement vu comment dรฉclarer le `response_model` et le `status_code` pour un chemin dโ€™accรจs. -Cela dรฉfinit les mรฉtadonnรฉes sur la rรฉponse principale d'une *opรฉration de chemin*. +Cela dรฉfinit les mรฉtadonnรฉes sur la rรฉponse principale dโ€™un chemin dโ€™accรจs. Vous pouvez รฉgalement dรฉclarer des rรฉponses supplรฉmentaires avec leurs modรจles, codes de statut, etc. -Il y a un chapitre entier ici dans la documentation ร  ce sujet, vous pouvez le lire sur [Rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. +Il y a un chapitre entier dans la documentation ร  ce sujet, vous pouvez le lire dans [Rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. -## OpenAPI supplรฉmentaire +## OpenAPI supplรฉmentaire { #openapi-extra } -Lorsque vous dรฉclarez un *chemin* dans votre application, **FastAPI** gรฉnรจre automatiquement les mรฉtadonnรฉes concernant ce *chemin* ร  inclure dans le schรฉma OpenAPI. +Lorsque vous dรฉclarez un chemin dโ€™accรจs dans votre application, **FastAPI** gรฉnรจre automatiquement les mรฉtadonnรฉes pertinentes ร  propos de ce chemin dโ€™accรจs ร  inclure dans le schรฉma OpenAPI. /// note | Dรฉtails techniques -La spรฉcification OpenAPI appelle ces mรฉtadonnรฉes des Objets d'opรฉration. +Dans la spรฉcification OpenAPI, cela sโ€™appelle lโ€™objet Operation. /// -Il contient toutes les informations sur le *chemin* et est utilisรฉ pour gรฉnรฉrer automatiquement la documentation. +Il contient toutes les informations sur le chemin dโ€™accรจs et est utilisรฉ pour gรฉnรฉrer la documentation automatique. Il inclut les `tags`, `parameters`, `requestBody`, `responses`, etc. -Ce schรฉma OpenAPI spรฉcifique aux *operations* est normalement gรฉnรฉrรฉ automatiquement par **FastAPI**, mais vous pouvez รฉgalement l'รฉtendre. +Ce schรฉma OpenAPI spรฉcifique ร  un chemin dโ€™accรจs est normalement gรฉnรฉrรฉ automatiquement par **FastAPI**, mais vous pouvez รฉgalement lโ€™รฉtendre. /// tip | Astuce -Si vous avez seulement besoin de dรฉclarer des rรฉponses supplรฉmentaires, un moyen plus pratique de le faire est d'utiliser les [rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. +Ceci est un point dโ€™extension de bas niveau. + +Si vous avez seulement besoin de dรฉclarer des rรฉponses supplรฉmentaires, un moyen plus pratique de le faire est dโ€™utiliser [Rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. /// -Vous pouvez รฉtendre le schรฉma OpenAPI pour une *opรฉration de chemin* en utilisant le paramรจtre `openapi_extra`. +Vous pouvez รฉtendre le schรฉma OpenAPI pour un chemin dโ€™accรจs en utilisant le paramรจtre `openapi_extra`. -### Extensions OpenAPI +### Extensions OpenAPI { #openapi-extensions } -Cet `openapi_extra` peut รชtre utile, par exemple, pour dรฉclarer [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)ย : +Cet `openapi_extra` peut รชtre utile, par exemple, pour dรฉclarer des [Extensions OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) : -{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} -Si vous ouvrez la documentation automatique de l'API, votre extension apparaรฎtra au bas du *chemin* spรฉcifique. +Si vous ouvrez la documentation automatique de lโ€™API, votre extension apparaรฎtra en bas du chemin dโ€™accรจs spรฉcifique. -Et dans le fichier openapi gรฉnรฉrรฉ (`/openapi.json`), vous verrez รฉgalement votre extension dans le cadre du *chemin* spรฉcifiqueย : +Et si vous consultez lโ€™OpenAPI rรฉsultant (ร  `/openapi.json` dans votre API), vous verrez รฉgalement votre extension comme partie du chemin dโ€™accรจs spรฉcifique : ```JSON hl_lines="22" { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" @@ -127,44 +129,44 @@ Et dans le fichier openapi gรฉnรฉrรฉ (`/openapi.json`), vous verrez รฉgalement v } ``` -### Personnalisation du Schรฉma OpenAPI pour un chemin +### Personnaliser le schรฉma OpenAPI dโ€™un chemin dโ€™accรจs { #custom-openapi-path-operation-schema } -Le dictionnaire contenu dans la variable `openapi_extra` sera fusionnรฉ avec le schรฉma OpenAPI gรฉnรฉrรฉ automatiquement pour l'*opรฉration de chemin*. +Le dictionnaire dans `openapi_extra` sera fusionnรฉ en profondeur avec le schรฉma OpenAPI gรฉnรฉrรฉ automatiquement pour le chemin dโ€™accรจs. Ainsi, vous pouvez ajouter des donnรฉes supplรฉmentaires au schรฉma gรฉnรฉrรฉ automatiquement. -Par exemple, vous pouvez dรฉcider de lire et de valider la requรชte avec votre propre code, sans utiliser les fonctionnalitรฉs automatiques de validation proposรฉe par Pydantic, mais vous pouvez toujours dรฉfinir la requรชte dans le schรฉma OpenAPI. +Par exemple, vous pourriez dรฉcider de lire et de valider la requรชte avec votre propre code, sans utiliser les fonctionnalitรฉs automatiques de FastAPI avec Pydantic, mais vous pourriez tout de mรชme vouloir dรฉfinir la requรชte dans le schรฉma OpenAPI. -Vous pouvez le faire avec `openapi_extra`ย : +Vous pourriez le faire avec `openapi_extra` : -{* ../../docs_src/path_operation_advanced_configuration/tutorial006.pyย hl[20:37,39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} -Dans cet exemple, nous n'avons dรฉclarรฉ aucun modรจle Pydantic. En fait, le corps de la requรชte n'est mรชme pas parsรฉ en tant que JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargรฉ de l'analyser d'une maniรจre ou d'une autre. +Dans cet exemple, nous nโ€™avons dรฉclarรฉ aucun modรจle Pydantic. En fait, le corps de la requรชte nโ€™est mรชme pas parsรฉ en JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargรฉe de lโ€™analyser dโ€™une maniรจre ou dโ€™une autre. Nรฉanmoins, nous pouvons dรฉclarer le schรฉma attendu pour le corps de la requรชte. -### Type de contenu OpenAPI personnalisรฉ +### Type de contenu OpenAPI personnalisรฉ { #custom-openapi-content-type } -En utilisant cette mรชme astuce, vous pouvez utiliser un modรจle Pydantic pour dรฉfinir le schรฉma JSON qui est ensuite inclus dans la section de schรฉma OpenAPI personnalisรฉe pour le *chemin* concernรฉ. +En utilisant cette mรชme astuce, vous pourriez utiliser un modรจle Pydantic pour dรฉfinir le JSON Schema qui est ensuite inclus dans la section de schรฉma OpenAPI personnalisรฉe pour le chemin dโ€™accรจs. -Et vous pouvez le faire mรชme si le type de donnรฉes dans la requรชte n'est pas au format JSON. +Et vous pourriez le faire mรชme si le type de donnรฉes dans la requรชte nโ€™est pas du JSON. -Dans cet exemple, nous n'utilisons pas les fonctionnalitรฉs de FastAPI pour extraire le schรฉma JSON des modรจles Pydantic ni la validation automatique pour JSON. En fait, nous dรฉclarons le type de contenu de la requรชte en tant que YAML, et non JSONย : +Par exemple, dans cette application nous nโ€™utilisons pas la fonctionnalitรฉ intรฉgrรฉe de FastAPI pour extraire le JSON Schema des modรจles Pydantic ni la validation automatique pour le JSON. En fait, nous dรฉclarons le type de contenu de la requรชte comme YAML, pas JSON : -{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} -Nรฉanmoins, bien que nous n'utilisions pas la fonctionnalitรฉ par dรฉfaut, nous utilisons toujours un modรจle Pydantic pour gรฉnรฉrer manuellement le schรฉma JSON pour les donnรฉes que nous souhaitons recevoir en YAML. +Nรฉanmoins, bien que nous nโ€™utilisions pas la fonctionnalitรฉ intรฉgrรฉe par dรฉfaut, nous utilisons toujours un modรจle Pydantic pour gรฉnรฉrer manuellement le JSON Schema pour les donnรฉes que nous souhaitons recevoir en YAML. -Ensuite, nous utilisons directement la requรชte et extrayons son contenu en tant qu'octets. Cela signifie que FastAPI n'essaiera mรชme pas d'analyser le payload de la requรชte en tant que JSON. +Ensuite, nous utilisons directement la requรชte et extrayons le corps en tant que `bytes`. Cela signifie que FastAPI nโ€™essaiera mรชme pas dโ€™analyser le payload de la requรชte en JSON. -Et nous analysons directement ce contenu YAML, puis nous utilisons ร  nouveau le mรชme modรจle Pydantic pour valider le contenu YAMLย : +Ensuite, dans notre code, nous analysons directement ce contenu YAML, puis nous utilisons ร  nouveau le mรชme modรจle Pydantic pour valider le contenu YAML : -{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} /// tip | Astuce Ici, nous rรฉutilisons le mรชme modรจle Pydantic. -Mais nous aurions pu tout aussi bien pu le valider d'une autre maniรจre. +Mais de la mรชme maniรจre, nous aurions pu le valider autrement. /// diff --git a/docs/fr/docs/advanced/response-directly.md b/docs/fr/docs/advanced/response-directly.md index 4ff883c770..f35c39c06f 100644 --- a/docs/fr/docs/advanced/response-directly.md +++ b/docs/fr/docs/advanced/response-directly.md @@ -1,20 +1,20 @@ -# Renvoyer directement une rรฉponse +# Renvoyer directement une rรฉponse { #return-a-response-directly } -Lorsque vous crรฉez une *opรฉration de chemins* **FastAPI**, vous pouvez normalement retourner n'importe quelle donnรฉe : un `dict`, une `list`, un modรจle Pydantic, un modรจle de base de donnรฉes, etc. +Lorsque vous crรฉez un *chemin d'accรจs* **FastAPI**, vous pouvez normalement retourner n'importe quelle donnรฉe : un `dict`, une `list`, un modรจle Pydantic, un modรจle de base de donnรฉes, etc. -Par dรฉfaut, **FastAPI** convertirait automatiquement cette valeur de retour en JSON en utilisant le `jsonable_encoder` expliquรฉ dans [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. +Par dรฉfaut, **FastAPI** convertirait automatiquement cette valeur de retour en JSON en utilisant le `jsonable_encoder` expliquรฉ dans [Encodeur compatible JSON](../tutorial/encoder.md){.internal-link target=_blank}. Ensuite, en arriรจre-plan, il mettra ces donnรฉes JSON-compatible (par exemple un `dict`) ร  l'intรฉrieur d'un `JSONResponse` qui sera utilisรฉ pour envoyer la rรฉponse au client. -Mais vous pouvez retourner une `JSONResponse` directement ร  partir de vos *opรฉrations de chemin*. +Mais vous pouvez retourner une `JSONResponse` directement ร  partir de vos *chemins d'accรจs*. Cela peut รชtre utile, par exemple, pour retourner des en-tรชtes personnalisรฉs ou des cookies. -## Renvoyer une `Response` +## Renvoyer une `Response` { #return-a-response } En fait, vous pouvez retourner n'importe quelle `Response` ou n'importe quelle sous-classe de celle-ci. -/// note | Remarque +/// tip | Astuce `JSONResponse` est elle-mรชme une sous-classe de `Response`. @@ -24,27 +24,27 @@ Et quand vous retournez une `Response`, **FastAPI** la transmet directement. Elle ne fera aucune conversion de donnรฉes avec les modรจles Pydantic, elle ne convertira pas le contenu en un type quelconque. -Cela vous donne beaucoup de flexibilitรฉ. Vous pouvez retourner n'importe quel type de donnรฉes, surcharger n'importe quelle dรฉclaration ou validation de donnรฉes. +Cela vous donne beaucoup de flexibilitรฉ. Vous pouvez retourner n'importe quel type de donnรฉes, surcharger n'importe quelle dรฉclaration ou validation de donnรฉes, etc. -## Utiliser le `jsonable_encoder` dans une `Response` +## Utiliser le `jsonable_encoder` dans une `Response` { #using-the-jsonable-encoder-in-a-response } -Parce que **FastAPI** n'apporte aucune modification ร  une `Response` que vous retournez, vous devez vous assurer que son contenu est prรชt ร  รชtre utilisรฉ (sรฉrialisable). +Parce que **FastAPI** n'apporte aucune modification ร  une `Response` que vous retournez, vous devez vous assurer que son contenu est prรชt pour cela. Par exemple, vous ne pouvez pas mettre un modรจle Pydantic dans une `JSONResponse` sans d'abord le convertir en un `dict` avec tous les types de donnรฉes (comme `datetime`, `UUID`, etc.) convertis en types compatibles avec JSON. -Pour ces cas, vous pouvez spรฉcifier un appel ร  `jsonable_encoder` pour convertir vos donnรฉes avant de les passer ร  une rรฉponse : +Pour ces cas, vous pouvez utiliser le `jsonable_encoder` pour convertir vos donnรฉes avant de les passer ร  une rรฉponse : -{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *} +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} /// note | Dรฉtails techniques Vous pouvez aussi utiliser `from starlette.responses import JSONResponse`. -**FastAPI** fournit le mรชme objet `starlette.responses` que `fastapi.responses` juste par commoditรฉ pour le dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. +**FastAPI** fournit le mรชme `starlette.responses` que `fastapi.responses` juste par commoditรฉ pour vous, le dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. /// -## Renvoyer une `Response` personnalisรฉe +## Renvoyer une `Response` personnalisรฉe { #returning-a-custom-response } L'exemple ci-dessus montre toutes les parties dont vous avez besoin, mais il n'est pas encore trรจs utile, car vous auriez pu retourner l'`item` directement, et **FastAPI** l'aurait mis dans une `JSONResponse` pour vous, en le convertissant en `dict`, etc. Tout cela par dรฉfaut. @@ -54,9 +54,9 @@ Disons que vous voulez retourner une rรฉponse รฉtant l'un des frameworks Python les plus rapides disponibles, seulement infรฉrieur ร  Starlette et Uvicorn (tous deux utilisรฉs au cล“ur de FastAPI). (*) +Les benchmarks indรฉpendants de TechEmpower montrent que les applications **FastAPI** sโ€™exรฉcutant avec Uvicorn sont parmi les frameworks Python les plus rapides disponibles, seulement en dessous de Starlette et Uvicorn euxโ€‘mรชmes (tous deux utilisรฉs en interne par FastAPI). -Mais en prรชtant attention aux tests de performance et aux comparaisons, il faut tenir compte de ce qu'il suit. +Mais en prรชtant attention aux tests de performance et aux comparaisons, vous devez tenir compte de ce qui suit. -## Tests de performance et rapiditรฉ +## Tests de performance et rapiditรฉ { #benchmarks-and-speed } Lorsque vous vรฉrifiez les tests de performance, il est commun de voir plusieurs outils de diffรฉrents types comparรฉs comme รฉquivalents. En particulier, on voit Uvicorn, Starlette et FastAPI comparรฉs (parmi de nombreux autres outils). -Plus le problรจme rรฉsolu par un outil est simple, mieux seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalitรฉs additionnelles fournies par les outils. +Plus le problรจme rรฉsolu par un outil est simple, meilleures seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalitรฉs additionnelles fournies par les outils. La hiรฉrarchie est la suivante : * **Uvicorn** : un serveur ASGI - * **Starlette** : (utilise Uvicorn) un micro-framework web - * **FastAPI**: (utilise Starlette) un micro-framework pour API disposant de fonctionnalitรฉs additionnelles pour la crรฉation d'API, avec la validation des donnรฉes, etc. + * **Starlette** : (utilise Uvicorn) un microframework web + * **FastAPI**: (utilise Starlette) un microframework pour API disposant de fonctionnalitรฉs additionnelles pour la crรฉation d'API, avec la validation des donnรฉes, etc. * **Uvicorn** : - * A les meilleures performances, รฉtant donnรฉ qu'il n'a pas beaucoup de code mis-ร -part le serveur en lui-mรชme. - * On n'รฉcrit pas une application avec uniquement Uvicorn. Cela signifie que le code devrait inclure plus ou moins, au minimum, tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale apportera les mรชmes complications que si on avait utilisรฉ un framework et que l'on avait minimisรฉ la quantitรฉ de code et de bugs. - * Si on compare Uvicorn, il faut le comparer ร  d'autre applications de serveurs comme Daphne, Hypercorn, uWSGI, etc. + * A les meilleures performances, รฉtant donnรฉ qu'il n'a pas beaucoup de code mis ร  part le serveur en luiโ€‘mรชme. + * On n'รฉcrit pas une application directement avec Uvicorn. Cela signifie que le code devrait inclure, au minimum, plus ou moins tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale aura la mรชme surcharge que si on avait utilisรฉ un framework, tout en minimisant la quantitรฉ de code et les bugs. + * Si on compare Uvicorn, il faut le comparer ร  d'autres serveurs d'applications comme Daphne, Hypercorn, uWSGI, etc. * **Starlette** : - * A les seconde meilleures performances aprรจs Uvicorn. Starlette utilise en rรฉalitรฉ Uvicorn. De ce fait, il ne peut quโ€™รชtre plus "lent" qu'Uvicorn car il requiert l'exรฉcution de plus de code. - * Cependant il nous apporte les outils pour construire une application web simple, avec un routage basรฉ sur des chemins, etc. - * Si on compare Starlette, il faut le comparer ร  d'autres frameworks web (ou micorframework) comme Sanic, Flask, Django, etc. + * A les secondes meilleures performances aprรจs Uvicorn. En rรฉalitรฉ, Starlette utilise Uvicorn. De ce fait, il ne peut quโ€™รชtre plus ยซ lent ยป qu'Uvicorn car il requiert l'exรฉcution de plus de code. + * Cependant, il apporte les outils pour construire une application web simple, avec un routage basรฉ sur des chemins, etc. + * Si on compare Starlette, il faut le comparer ร  d'autres frameworks web (ou microframeworks) comme Sanic, Flask, Django, etc. * **FastAPI** : - * Comme Starlette, FastAPI utilise Uvicorn et ne peut donc pas รชtre plus rapide que ce dernier. - * FastAPI apporte des fonctionnalitรฉs supplรฉmentaires ร  Starlette. Des fonctionnalitรฉs qui sont nรฉcessaires presque systรฉmatiquement lors de la crรฉation d'une API, comme la validation des donnรฉes, la sรฉrialisation. En utilisant FastAPI, on obtient une documentation automatiquement (qui ne requiert aucune manipulation pour รชtre mise en place). - * Si on n'utilisait pas FastAPI mais directement Starlette (ou un outil รฉquivalent comme Sanic, Flask, Responder, etc) il faudrait implรฉmenter la validation des donnรฉes et la sรฉrialisation par nous-mรชme. Le rรฉsultat serait donc le mรชme dans les deux cas mais du travail supplรฉmentaire serait ร  rรฉaliser avec Starlette, surtout en considรฉrant que la validation des donnรฉes et la sรฉrialisation reprรฉsentent la plus grande quantitรฉ de code ร  รฉcrire dans une application. - * De ce fait, en utilisant FastAPI on minimise le temps de dรฉveloppement, les bugs, le nombre de lignes de code, et on obtient les mรชmes performances (si ce n'est de meilleurs performances) que l'on aurait pu avoir sans ce framework (en ayant ร  implรฉmenter de nombreuses fonctionnalitรฉs importantes par nous-mรชmes). - * Si on compare FastAPI, il faut le comparer ร  d'autres frameworks web (ou ensemble d'outils) qui fournissent la validation des donnรฉes, la sรฉrialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc. + * Comme Starlette utilise Uvicorn et ne peut donc pas รชtre plus rapide que lui, **FastAPI** utilise Starlette et ne peut donc pas รชtre plus rapide que lui. + * FastAPI apporte des fonctionnalitรฉs supplรฉmentaires ร  Starlette. Des fonctionnalitรฉs dont vous avez presque toujours besoin lors de la crรฉation d'une API, comme la validation des donnรฉes et la sรฉrialisation. En l'utilisant, vous obtenez une documentation automatique ยซ gratuitement ยป (la documentation automatique n'ajoute mรชme pas de surcharge ร  lโ€™exรฉcution, elle est gรฉnรฉrรฉe au dรฉmarrage). + * Si on n'utilisait pas FastAPI mais directement Starlette (ou un autre outil comme Sanic, Flask, Responder, etc.), il faudrait implรฉmenter toute la validation des donnรฉes et la sรฉrialisation soiโ€‘mรชme. L'application finale aurait donc la mรชme surcharge que si elle avait รฉtรฉ construite avec FastAPI. Et dans de nombreux cas, cette validation des donnรฉes et cette sรฉrialisation reprรฉsentent la plus grande quantitรฉ de code รฉcrite dans les applications. + * De ce fait, en utilisant FastAPI on minimise le temps de dรฉveloppement, les bugs, le nombre de lignes de code, et on obtient probablement les mรชmes performances (voire de meilleures performances) que l'on aurait pu avoir sans ce framework (car il aurait fallu tout implรฉmenter dans votre code). + * Si on compare FastAPI, il faut le comparer ร  d'autres frameworks dโ€™application web (ou ensembles d'outils) qui fournissent la validation des donnรฉes, la sรฉrialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc. Des frameworks avec validation des donnรฉes, sรฉrialisation et documentation automatiques intรฉgrรฉes. diff --git a/docs/fr/docs/deployment/docker.md b/docs/fr/docs/deployment/docker.md index 05b597a2df..ec30f96079 100644 --- a/docs/fr/docs/deployment/docker.md +++ b/docs/fr/docs/deployment/docker.md @@ -1,75 +1,150 @@ -# Dรฉployer avec Docker +# FastAPI dans des conteneurs - Docker { #fastapi-in-containers-docker } -Dans cette section, vous verrez des instructions et des liens vers des guides pour savoir comment : +Lors du dรฉploiement d'applications FastAPI, une approche courante consiste ร  construire une **image de conteneur Linux**. C'est gรฉnรฉralement fait avec **Docker**. Vous pouvez ensuite dรฉployer cette image de conteneur de plusieurs faรงons possibles. -* Faire de votre application **FastAPI** une image/conteneur Docker avec une performance maximale. En environ **5 min**. -* (Optionnellement) comprendre ce que vous, en tant que dรฉveloppeur, devez savoir sur HTTPS. -* Configurer un cluster en mode Docker Swarm avec HTTPS automatique, mรชme sur un simple serveur ร  5 dollars US/mois. En environ **20 min**. -* Gรฉnรฉrer et dรฉployer une application **FastAPI** complรจte, en utilisant votre cluster Docker Swarm, avec HTTPS, etc. En environ **10 min**. +L'utilisation de conteneurs Linux prรฉsente plusieurs avantages, notamment la **sรฉcuritรฉ**, la **rรฉplicabilitรฉ**, la **simplicitรฉ**, entre autres. -Vous pouvez utiliser **Docker** pour le dรฉploiement. Il prรฉsente plusieurs avantages comme la sรฉcuritรฉ, la rรฉplicabilitรฉ, la simplicitรฉ de dรฉveloppement, etc. - -Si vous utilisez Docker, vous pouvez utiliser l'image Docker officielle : +/// tip | Astuce -## tiangolo/uvicorn-gunicorn-fastapi +Vous รชtes pressรฉ et vous connaissez dรฉjร  tout รงa ? Allez directement au [`Dockerfile` ci-dessous ๐Ÿ‘‡](#build-a-docker-image-for-fastapi). -Cette image est dotรฉe d'un mรฉcanisme d'"auto-tuning", de sorte qu'il vous suffit d'ajouter votre code pour obtenir automatiquement des performances trรจs รฉlevรฉes. Et sans faire de sacrifices. +/// -Mais vous pouvez toujours changer et mettre ร  jour toutes les configurations avec des variables d'environnement ou des fichiers de configuration. +
+Aperรงu du Dockerfile ๐Ÿ‘€ -/// tip | Astuce +```Dockerfile +FROM python:3.9 -Pour voir toutes les configurations et options, rendez-vous sur la page de l'image Docker : tiangolo/uvicorn-gunicorn-fastapi. +WORKDIR /code -/// +COPY ./requirements.txt /code/requirements.txt -## Crรฉer un `Dockerfile` +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -* Allez dans le rรฉpertoire de votre projet. -* Crรฉez un `Dockerfile` avec : +COPY ./app /code/app -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 +CMD ["fastapi", "run", "app/main.py", "--port", "80"] -COPY ./app /app +# Si vous exรฉcutez derriรจre un proxy comme Nginx ou Traefik, ajoutez --proxy-headers +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ``` -### Applications plus larges +
-Si vous avez suivi la section sur la crรฉation d' [Applications avec plusieurs fichiers](../tutorial/bigger-applications.md){.internal-link target=_blank}, votre `Dockerfile` pourrait ressembler ร  ceciย : +## Qu'est-ce qu'un conteneur { #what-is-a-container } -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 +Les conteneurs (principalement les conteneurs Linux) sont un moyen trรจs **lรฉger** d'empaqueter des applications, y compris toutes leurs dรฉpendances et les fichiers nรฉcessaires, tout en les isolant des autres conteneurs (autres applications ou composants) dans le mรชme systรจme. -COPY ./app /app/app -``` +Les conteneurs Linux s'exรฉcutent en utilisant le mรชme noyau Linux que l'hรดte (machine, machine virtuelle, serveur cloud, etc.). Cela signifie simplement qu'ils sont trรจs lรฉgers (comparรฉs ร  des machines virtuelles complรจtes รฉmulant un systรจme d'exploitation entier). -### Raspberry Pi et autres architectures +Ainsi, les conteneurs consomment **peu de ressources**, une quantitรฉ comparable ร  l'exรฉcution directe des processus (alors qu'une machine virtuelle consommerait beaucoup plus). -Si vous utilisez Docker sur un Raspberry Pi (qui a un processeur ARM) ou toute autre architecture, vous pouvez crรฉer un `Dockerfile` ร  partir de zรฉro, basรฉ sur une image de base Python (qui est multi-architecture) et utiliser Uvicorn seul. +Les conteneurs ont รฉgalement leurs propres processus d'exรฉcution **isolรฉs** (gรฉnรฉralement un seul processus), leur systรจme de fichiers et leur rรฉseau, ce qui simplifie le dรฉploiement, la sรฉcuritรฉ, le dรฉveloppement, etc. -Dans ce cas, votre `Dockerfile` pourrait ressembler ร  ceciย : +## Qu'est-ce qu'une image de conteneur { #what-is-a-container-image } -```Dockerfile -FROM python:3.7 +Un **conteneur** s'exรฉcute ร  partir d'une **image de conteneur**. + +Une image de conteneur est une version **statique** de tous les fichiers, des variables d'environnement et de la commande/le programme par dรฉfaut devant รชtre prรฉsents dans un conteneur. Ici, **statique** signifie que l'**image** du conteneur ne s'exรฉcute pas, elle n'est pas en cours d'exรฉcution, ce ne sont que les fichiers et mรฉtadonnรฉes empaquetรฉs. + +Par opposition ร  une ยซ **image de conteneur** ยป qui correspond aux contenus statiques stockรฉs, un ยซ **conteneur** ยป fait normalement rรฉfรฉrence ร  l'instance en cours d'exรฉcution, la chose qui est **exรฉcutรฉe**. + +Lorsque le **conteneur** est dรฉmarrรฉ et en cours d'exรฉcution (dรฉmarrรฉ ร  partir d'une **image de conteneur**), il peut crรฉer ou modifier des fichiers, des variables d'environnement, etc. Ces changements n'existeront que dans ce conteneur, mais ne persisteront pas dans l'image de conteneur sous-jacente (ils ne seront pas enregistrรฉs sur le disque). + +Une image de conteneur est comparable au **programme** et ร  ses contenus, par exemple `python` et un fichier `main.py`. + +Et le **conteneur** lui-mรชme (par opposition ร  l'**image de conteneur**) est l'instance en cours d'exรฉcution rรฉelle de l'image, comparable ร  un **processus**. En fait, un conteneur ne fonctionne que lorsqu'il a un **processus en cours d'exรฉcution** (et normalement, il s'agit d'un seul processus). Le conteneur s'arrรชte lorsqu'aucun processus n'y est en cours d'exรฉcution. + +## Images de conteneur { #container-images } + +Docker a รฉtรฉ l'un des principaux outils pour crรฉer et gรฉrer des **images de conteneur** et des **conteneurs**. + +Et il existe un Docker Hub public avec des **images de conteneur officielles** prรฉ-construites pour de nombreux outils, environnements, bases de donnรฉes et applications. + +Par exemple, il existe une image Python officielle. + +Et il existe beaucoup d'autres images pour diffรฉrentes choses comme des bases de donnรฉes, par exemple : + +* PostgreSQL +* MySQL +* MongoDB +* Redis, etc. + +En utilisant une image de conteneur prรฉ-construite, il est trรจs facile de **combiner** et d'utiliser diffรฉrents outils. Par exemple, pour essayer une nouvelle base de donnรฉes. Dans la plupart des cas, vous pouvez utiliser les **images officielles** et simplement les configurer avec des variables d'environnement. + +Ainsi, dans de nombreux cas, vous pouvez apprendre les conteneurs et Docker et rรฉutiliser ces connaissances avec de nombreux outils et composants diffรฉrents. + +Vous exรฉcuteriez donc **plusieurs conteneurs** avec des รฉlรฉments diffรฉrents, comme une base de donnรฉes, une application Python, un serveur web avec une application frontend React, et les connecter entre eux via leur rรฉseau interne. + +Tous les systรจmes de gestion de conteneurs (comme Docker ou Kubernetes) disposent de ces fonctionnalitรฉs rรฉseau intรฉgrรฉes. + +## Conteneurs et processus { #containers-and-processes } + +Une **image de conteneur** inclut normalement dans ses mรฉtadonnรฉes le programme/la commande par dรฉfaut ร  exรฉcuter lorsque le **conteneur** est dรฉmarrรฉ et les paramรจtres ร  transmettre ร  ce programme. Trรจs similaire ร  ce que vous utiliseriez en ligne de commande. + +Lorsqu'un **conteneur** est dรฉmarrรฉ, il exรฉcutera cette commande/ce programme (bien que vous puissiez la/le remplacer et faire exรฉcuter une autre commande/un autre programme). + +Un conteneur fonctionne tant que le **processus principal** (commande ou programme) est en cours d'exรฉcution. + +Un conteneur a normalement un **seul processus**, mais il est aussi possible de dรฉmarrer des sous-processus ร  partir du processus principal, et ainsi vous aurez **plusieurs processus** dans le mรชme conteneur. -RUN pip install fastapi uvicorn +Mais il n'est pas possible d'avoir un conteneur en cours d'exรฉcution sans **au moins un processus en cours**. Si le processus principal s'arrรชte, le conteneur s'arrรชte. -EXPOSE 80 +## Construire une image Docker pour FastAPI { #build-a-docker-image-for-fastapi } -COPY ./app /app +Trรจs bien, construisons quelque chose maintenant ! ๐Ÿš€ -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +Je vais vous montrer comment construire une **image Docker** pour FastAPI **ร  partir de zรฉro**, basรฉe sur l'image **officielle Python**. + +C'est ce que vous voudrez faire dans **la plupart des cas**, par exemple : + +* Utiliser **Kubernetes** ou des outils similaires +* Exรฉcuter sur un **Raspberry Pi** +* Utiliser un service cloud qui exรฉcuterait une image de conteneur pour vous, etc. + +### Dรฉpendances des paquets { #package-requirements } + +Vous aurez normalement les **dรฉpendances des paquets** de votre application dans un fichier. + +Cela dรฉpendra principalement de l'outil que vous utilisez pour **installer** ces dรฉpendances. + +La maniรจre la plus courante consiste ร  avoir un fichier `requirements.txt` avec les noms des paquets et leurs versions, un par ligne. + +Vous utiliserez bien sรปr les mรชmes idรฉes que vous avez lues dans [ร€ propos des versions de FastAPI](versions.md){.internal-link target=_blank} pour dรฉfinir les plages de versions. + +Par exemple, votre `requirements.txt` pourrait ressembler ร  : + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 ``` -## Crรฉer le code **FastAPI**. +Et vous installerez normalement ces dรฉpendances de paquets avec `pip`, par exemple : -* Crรฉer un rรฉpertoire `app` et y entrer. -* Crรฉez un fichier `main.py` avecย : +
-```Python -from typing import Optional +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` +
+ +/// info + +Il existe d'autres formats et outils pour dรฉfinir et installer des dรฉpendances de paquets. + +/// + +### Crรฉer le code **FastAPI** { #create-the-fastapi-code } + +* Crรฉez un rรฉpertoire `app` et entrez dedans. +* Crรฉez un fichier vide `__init__.py`. +* Crรฉez un fichier `main.py` avec : + +```Python from fastapi import FastAPI app = FastAPI() @@ -81,22 +156,168 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Optional[str] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -* Vous devriez maintenant avoir une structure de rรฉpertoire telle queย : +### Dockerfile { #dockerfile } + +Maintenant, dans le mรชme rรฉpertoire de projet, crรฉez un fichier `Dockerfile` avec : + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.9 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Dรฉmarrer ร  partir de l'image de base Python officielle. + +2. Dรฉfinir le rรฉpertoire de travail courant sur `/code`. + + C'est lร  que nous placerons le fichier `requirements.txt` et le rรฉpertoire `app`. + +3. Copier le fichier des dรฉpendances vers le rรฉpertoire `/code`. + + Copier **uniquement** le fichier des dรฉpendances en premier, pas le reste du code. + + Comme ce fichier **ne change pas souvent**, Docker le dรฉtectera et utilisera le **cache** pour cette รฉtape, ce qui activera le cache pour l'รฉtape suivante aussi. + +4. Installer les dรฉpendances listรฉes dans le fichier des dรฉpendances. + + L'option `--no-cache-dir` indique ร  `pip` de ne pas enregistrer localement les paquets tรฉlรฉchargรฉs, car cela ne sert que si `pip` devait รชtre relancรฉ pour installer les mรชmes paquets, mais ce n'est pas le cas lorsque l'on travaille avec des conteneurs. + + /// note | Remarque + + Le `--no-cache-dir` concerne uniquement `pip`, cela n'a rien ร  voir avec Docker ou les conteneurs. + + /// + + L'option `--upgrade` indique ร  `pip` de mettre ร  niveau les paquets s'ils sont dรฉjร  installรฉs. + + Comme l'รฉtape prรฉcรฉdente de copie du fichier peut รชtre dรฉtectรฉe par le **cache Docker**, cette รฉtape **utilisera รฉgalement le cache Docker** lorsqu'il est disponible. + + L'utilisation du cache ร  cette รฉtape vous **fera gagner** beaucoup de **temps** lors de la reconstruction de l'image encore et encore pendant le dรฉveloppement, au lieu de **tรฉlรฉcharger et installer** toutes les dรฉpendances **ร  chaque fois**. + +5. Copier le rรฉpertoire `./app` dans le rรฉpertoire `/code`. + + Comme cela contient tout le code qui est ce qui **change le plus frรฉquemment**, le **cache** Docker ne sera pas facilement utilisรฉ pour cette รฉtape ou pour les **รฉtapes suivantes**. + + Il est donc important de placer cela **vers la fin** du `Dockerfile`, pour optimiser les temps de construction de l'image de conteneur. + +6. Dรฉfinir la **commande** pour utiliser `fastapi run`, qui utilise Uvicorn sous le capot. + + `CMD` prend une liste de chaรฎnes, chacune de ces chaรฎnes correspond ร  ce que vous taperiez en ligne de commande sรฉparรฉ par des espaces. + + Cette commande sera exรฉcutรฉe ร  partir du **rรฉpertoire de travail courant**, le mรชme rรฉpertoire `/code` que vous avez dรฉfini plus haut avec `WORKDIR /code`. + +/// tip | Astuce + +Passez en revue ce que fait chaque ligne en cliquant sur chaque bulle numรฉrotรฉe dans le code. ๐Ÿ‘† + +/// + +/// warning | Alertes + +Vous devez vous assurer d'utiliser **toujours** la **forme exec** de l'instruction `CMD`, comme expliquรฉ ci-dessous. + +/// + +#### Utiliser `CMD` - Forme Exec { #use-cmd-exec-form } + +L'instruction Docker `CMD` peut รชtre รฉcrite sous deux formes : + +โœ… Forme **Exec** : + +```Dockerfile +# โœ… ร€ faire +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ Forme **Shell** : + +```Dockerfile +# โ›”๏ธ ร€ ne pas faire +CMD fastapi run app/main.py --port 80 +``` + +Assurez-vous d'utiliser toujours la forme **exec** pour garantir que FastAPI peut s'arrรชter proprement et que les [รฉvรฉnements de cycle de vie](../advanced/events.md){.internal-link target=_blank} sont dรฉclenchรฉs. + +Vous pouvez en lire davantage dans la documentation Docker sur les formes shell et exec. + +Cela peut รชtre trรจs visible lors de l'utilisation de `docker compose`. Voir cette section de la FAQ Docker Compose pour plus de dรฉtails techniques : Pourquoi mes services mettent-ils 10 secondes ร  se recrรฉer ou ร  s'arrรชter ?. + +#### Structure du rรฉpertoire { #directory-structure } + +Vous devriez maintenant avoir une structure de rรฉpertoire comme : ``` . โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py โ”‚ โ””โ”€โ”€ main.py -โ””โ”€โ”€ Dockerfile +โ”œโ”€โ”€ Dockerfile +โ””โ”€โ”€ requirements.txt +``` + +#### Derriรจre un proxy de terminaison TLS { #behind-a-tls-termination-proxy } + +Si vous exรฉcutez votre conteneur derriรจre un proxy de terminaison TLS (load balancer) comme Nginx ou Traefik, ajoutez l'option `--proxy-headers`, cela indiquera ร  Uvicorn (via la CLI FastAPI) de faire confiance aux en-tรชtes envoyรฉs par ce proxy lui indiquant que l'application s'exรฉcute derriรจre HTTPS, etc. + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Cache Docker { #docker-cache } + +Il y a une astuce importante dans ce `Dockerfile`, nous copions d'abord **le fichier des dรฉpendances seul**, pas le reste du code. Laissez-moi vous expliquer pourquoi. + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker et d'autres outils **construisent** ces images de conteneur **de maniรจre incrรฉmentale**, en ajoutant **une couche au-dessus de l'autre**, en commenรงant par le haut du `Dockerfile` et en ajoutant tous les fichiers crรฉรฉs par chacune des instructions du `Dockerfile`. + +Docker et des outils similaires utilisent รฉgalement un **cache interne** lors de la construction de l'image : si un fichier n'a pas changรฉ depuis la derniรจre construction de l'image de conteneur, alors il va **rรฉutiliser la mรชme couche** crรฉรฉe la derniรจre fois, au lieu de recopier le fichier et crรฉer une nouvelle couche ร  partir de zรฉro. + +ร‰viter simplement la copie des fichiers n'amรฉliore pas nรฉcessairement les choses de maniรจre significative, mais comme il a utilisรฉ le cache pour cette รฉtape, il peut **utiliser le cache pour l'รฉtape suivante**. Par exemple, il peut utiliser le cache pour l'instruction qui installe les dรฉpendances avec : + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt ``` -## Construire l'image Docker +Le fichier des dรฉpendances **ne changera pas frรฉquemment**. Ainsi, en copiant uniquement ce fichier, Docker pourra **utiliser le cache** pour cette รฉtape. + +Et ensuite, Docker pourra **utiliser le cache pour l'รฉtape suivante** qui tรฉlรฉcharge et installe ces dรฉpendances. Et c'est lร  que nous **gagnons beaucoup de temps**. โœจ ... et รฉvitons l'ennui en attendant. ๐Ÿ˜ช๐Ÿ˜† -* Allez dans le rรฉpertoire du projet (dans lequel se trouve votre `Dockerfile`, contenant votre rรฉpertoire `app`). +Tรฉlรฉcharger et installer les dรฉpendances de paquets **peut prendre des minutes**, mais utiliser le **cache** ne **prendra que quelques secondes** au plus. + +Et comme vous reconstruirez l'image de conteneur encore et encore pendant le dรฉveloppement pour vรฉrifier que vos modifications de code fonctionnent, cela vous fera gagner beaucoup de temps cumulรฉ. + +Ensuite, vers la fin du `Dockerfile`, nous copions tout le code. Comme c'est ce qui **change le plus frรฉquemment**, nous le plaรงons vers la fin, car presque toujours, tout ce qui suit cette รฉtape ne pourra pas utiliser le cache. + +```Dockerfile +COPY ./app /code/app +``` + +### Construire l'image Docker { #build-the-docker-image } + +Maintenant que tous les fichiers sont en place, construisons l'image de conteneur. + +* Allez dans le rรฉpertoire du projet (lร  oรน se trouve votre `Dockerfile`, contenant votre rรฉpertoire `app`). * Construisez votre image FastAPI :
@@ -109,9 +330,17 @@ $ docker build -t myimage .
-## Dรฉmarrer le conteneur Docker +/// tip | Astuce + +Remarquez le `.` ร  la fin, รฉquivalent ร  `./`, il indique ร  Docker le rรฉpertoire ร  utiliser pour construire l'image de conteneur. + +Dans ce cas, c'est le mรชme rรฉpertoire courant (`.`). -* Exรฉcutez un conteneur basรฉ sur votre imageย : +/// + +### Dรฉmarrer le conteneur Docker { #start-the-docker-container } + +* Exรฉcutez un conteneur basรฉ sur votre image :
@@ -121,65 +350,269 @@ $ docker run -d --name mycontainer -p 80:80 myimage
-Vous disposez maintenant d'un serveur FastAPI optimisรฉ dans un conteneur Docker. Configurรฉ automatiquement pour votre -serveur actuel (et le nombre de cล“urs du CPU). - -## Vรฉrifier +## Vรฉrifier { #check-it } -Vous devriez pouvoir accรฉder ร  votre application via l'URL de votre conteneur Docker, par exempleย : http://192.168.99.100/items/5?q=somequery ou http://127.0.0.1/items/5?q=somequery (ou รฉquivalent, en utilisant votre hรดte Docker). +Vous devriez pouvoir le vรฉrifier via l'URL de votre conteneur Docker, par exemple : http://192.168.99.100/items/5?q=somequery ou http://127.0.0.1/items/5?q=somequery (ou รฉquivalent, en utilisant votre hรดte Docker). -Vous verrez quelque chose commeย : +Vous verrez quelque chose comme : ```JSON {"item_id": 5, "q": "somequery"} ``` -## Documentation interactive de l'API +## Documentation interactive de l'API { #interactive-api-docs } -Vous pouvez maintenant visiter http://192.168.99.100/docs ou http://127.0.0.1/docs (ou รฉquivalent, en utilisant votre hรดte Docker). +Vous pouvez maintenant aller sur http://192.168.99.100/docs ou http://127.0.0.1/docs (ou รฉquivalent, en utilisant votre hรดte Docker). -Vous verrez la documentation interactive automatique de l'API (fournie par Swagger UI)ย : +Vous verrez la documentation interactive automatique de l'API (fournie par Swagger UI) : ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -## Documentation de l'API alternative +## Documentation alternative de l'API { #alternative-api-docs } -Et vous pouvez รฉgalement aller sur http://192.168.99.100/redoc ou http://127.0.0.1/redoc (ou รฉquivalent, en utilisant votre hรดte Docker). +Et vous pouvez aussi aller sur http://192.168.99.100/redoc ou http://127.0.0.1/redoc (ou รฉquivalent, en utilisant votre hรดte Docker). -Vous verrez la documentation automatique alternative (fournie par ReDoc)ย : +Vous verrez la documentation automatique alternative (fournie par ReDoc) : ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## Traefik +## Construire une image Docker avec un FastAPI mono-fichier { #build-a-docker-image-with-a-single-file-fastapi } + +Si votre FastAPI est un seul fichier, par exemple `main.py` sans rรฉpertoire `./app`, votre structure de fichiers pourrait ressembler ร  ceci : + +``` +. +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ main.py +โ””โ”€โ”€ requirements.txt +``` + +Vous n'auriez alors qu'ร  changer les chemins correspondants pour copier le fichier dans le `Dockerfile` : + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ -Traefik est un reverse proxy/load balancer -haute performance. Il peut faire office de "Proxy de terminaison TLS" (entre autres fonctionnalitรฉs). +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. Copier le fichier `main.py` directement dans le rรฉpertoire `/code` (sans rรฉpertoire `./app`). + +2. Utiliser `fastapi run` pour servir votre application dans le fichier unique `main.py`. + +Lorsque vous passez le fichier ร  `fastapi run`, il dรฉtectera automatiquement qu'il s'agit d'un fichier unique et non d'un package et saura comment l'importer et servir votre application FastAPI. ๐Ÿ˜Ž + +## Concepts de dรฉploiement { #deployment-concepts } + +Parlons ร  nouveau de certains des mรชmes [Concepts de dรฉploiement](concepts.md){.internal-link target=_blank} en termes de conteneurs. + +Les conteneurs sont principalement un outil pour simplifier le processus de **construction et de dรฉploiement** d'une application, mais ils n'imposent pas une approche particuliรจre pour gรฉrer ces **concepts de dรฉploiement**, et il existe plusieurs stratรฉgies possibles. + +La **bonne nouvelle**, c'est qu'avec chaque stratรฉgie diffรฉrente, il existe un moyen de couvrir tous les concepts de dรฉploiement. ๐ŸŽ‰ + +Passons en revue ces **concepts de dรฉploiement** en termes de conteneurs : + +* HTTPS +* Exรฉcution au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables au dรฉmarrage + +## HTTPS { #https } + +Si l'on se concentre uniquement sur l'**image de conteneur** pour une application FastAPI (et plus tard sur le **conteneur** en cours d'exรฉcution), HTTPS serait normalement gรฉrรฉ **ร  l'extรฉrieur** par un autre outil. + +Cela pourrait รชtre un autre conteneur, par exemple avec Traefik, gรฉrant **HTTPS** et l'acquisition **automatique** des **certificats**. + +/// tip | Astuce -Il est intรฉgrรฉ ร  Let's Encrypt. Ainsi, il peut gรฉrer toutes les parties HTTPS, y compris l'acquisition et le renouvellement des certificats. +Traefik s'intรจgre avec Docker, Kubernetes, et d'autres, donc il est trรจs facile de configurer HTTPS pour vos conteneurs avec lui. -Il est รฉgalement intรฉgrรฉ ร  Docker. Ainsi, vous pouvez dรฉclarer vos domaines dans les configurations de chaque application et faire en sorte qu'elles lisent ces configurations, gรฉnรจrent les certificats HTTPS et servent via HTTPS ร  votre application automatiquement, sans nรฉcessiter aucune modification de leurs configurations. +/// + +Alternativement, HTTPS pourrait รชtre gรฉrรฉ par un fournisseur cloud comme l'un de leurs services (tout en exรฉcutant l'application dans un conteneur). + +## Exรฉcution au dรฉmarrage et redรฉmarrages { #running-on-startup-and-restarts } + +Il y a normalement un autre outil chargรฉ de **dรฉmarrer et exรฉcuter** votre conteneur. + +Cela pourrait รชtre **Docker** directement, **Docker Compose**, **Kubernetes**, un **service cloud**, etc. + +Dans la plupart (ou toutes) des situations, il existe une option simple pour activer l'exรฉcution du conteneur au dรฉmarrage et activer les redรฉmarrages en cas d'รฉchec. Par exemple, dans Docker, c'est l'option de ligne de commande `--restart`. + +Sans utiliser de conteneurs, faire en sorte que les applications s'exรฉcutent au dรฉmarrage et avec redรฉmarrages peut รชtre fastidieux et difficile. Mais en **travaillant avec des conteneurs**, dans la plupart des cas, cette fonctionnalitรฉ est incluse par dรฉfaut. โœจ + +## Rรฉplication - Nombre de processus { #replication-number-of-processes } + +Si vous avez un cluster de machines avec **Kubernetes**, Docker Swarm Mode, Nomad, ou un autre systรจme complexe similaire pour gรฉrer des conteneurs distribuรฉs sur plusieurs machines, alors vous voudrez probablement **gรฉrer la rรฉplication** au **niveau du cluster** plutรดt que d'utiliser un **gestionnaire de processus** (comme Uvicorn avec workers) dans chaque conteneur. + +L'un de ces systรจmes de gestion de conteneurs distribuรฉs comme Kubernetes dispose normalement d'une maniรจre intรฉgrรฉe de gรฉrer la **rรฉplication des conteneurs** tout en supportant l'**รฉquilibrage de charge** des requรชtes entrantes. Le tout au **niveau du cluster**. + +Dans ces cas, vous voudrez probablement construire une **image Docker ร  partir de zรฉro** comme [expliquรฉ ci-dessus](#dockerfile), en installant vos dรฉpendances et en exรฉcutant **un seul processus Uvicorn** au lieu d'utiliser plusieurs workers Uvicorn. + +### ร‰quilibreur de charge { #load-balancer } + +Lors de l'utilisation de conteneurs, vous aurez normalement un composant **ร  l'รฉcoute sur le port principal**. Cela pourrait รชtre un autre conteneur qui est รฉgalement un **proxy de terminaison TLS** pour gรฉrer **HTTPS** ou un outil similaire. + +Comme ce composant prend la **charge** des requรชtes et la distribue entre les workers de faรงon (espรฉrons-le) **รฉquilibrรฉe**, on l'appelle รฉgalement communรฉment un **รฉquilibreur de charge**. + +/// tip | Astuce + +Le mรชme composant de **proxy de terminaison TLS** utilisรฉ pour HTTPS sera probablement aussi un **รฉquilibreur de charge**. + +/// + +Et en travaillant avec des conteneurs, le mรชme systรจme que vous utilisez pour les dรฉmarrer et les gรฉrer dispose dรฉjร  d'outils internes pour transmettre la **communication rรฉseau** (par ex. les requรชtes HTTP) depuis cet **รฉquilibreur de charge** (qui peut aussi รชtre un **proxy de terminaison TLS**) vers le ou les conteneurs avec votre application. + +### Un รฉquilibreur de charge - Plusieurs conteneurs worker { #one-load-balancer-multiple-worker-containers } + +Lorsque vous travaillez avec **Kubernetes** ou des systรจmes de gestion de conteneurs distribuรฉs similaires, l'utilisation de leurs mรฉcanismes rรฉseau internes permet au **seul รฉquilibreur de charge** ร  l'รฉcoute sur le **port** principal de transmettre la communication (les requรชtes) vers potentiellement **plusieurs conteneurs** exรฉcutant votre application. + +Chacun de ces conteneurs exรฉcutant votre application aura normalement **un seul processus** (par ex. un processus Uvicorn exรฉcutant votre application FastAPI). Ils seront tous des **conteneurs identiques**, exรฉcutant la mรชme chose, mais chacun avec son propre processus, sa mรฉmoire, etc. De cette faรงon, vous profiterez de la **parallรฉlisation** sur **diffรฉrents cล“urs** du CPU, voire sur **diffรฉrentes machines**. + +Et le systรจme de conteneurs distribuรฉs avec l'**รฉquilibreur de charge** **distribuera les requรชtes** ร  chacun des conteneurs exรฉcutant votre application **ร  tour de rรดle**. Ainsi, chaque requรชte pourrait รชtre traitรฉe par l'un des multiples **conteneurs rรฉpliquรฉs** exรฉcutant votre application. + +Et normalement cet **รฉquilibreur de charge** pourra gรฉrer des requรชtes qui vont vers *d'autres* applications dans votre cluster (par ex. vers un autre domaine, ou sous un autre prรฉfixe de chemin d'URL), et transmettra cette communication aux bons conteneurs pour *cette autre* application s'exรฉcutant dans votre cluster. + +### Un processus par conteneur { #one-process-per-container } + +Dans ce type de scรฉnario, vous voudrez probablement avoir **un seul processus (Uvicorn) par conteneur**, puisque vous gรฉrez dรฉjร  la rรฉplication au niveau du cluster. + +Donc, dans ce cas, vous **ne voudrez pas** avoir plusieurs workers dans le conteneur, par exemple avec l'option de ligne de commande `--workers`. Vous voudrez avoir **un seul processus Uvicorn** par conteneur (mais probablement plusieurs conteneurs). + +Avoir un autre gestionnaire de processus ร  l'intรฉrieur du conteneur (comme ce serait le cas avec plusieurs workers) n'ajouterait que de la **complexitรฉ inutile** que vous gรฉrez trรจs probablement dรฉjร  avec votre systรจme de cluster. + +### Conteneurs avec plusieurs processus et cas particuliers { #containers-with-multiple-processes-and-special-cases } + +Bien sรปr, il existe des **cas particuliers** oรน vous pourriez vouloir avoir **un conteneur** avec plusieurs **processus worker Uvicorn** ร  l'intรฉrieur. + +Dans ces cas, vous pouvez utiliser l'option de ligne de commande `--workers` pour dรฉfinir le nombre de workers que vous souhaitez exรฉcuter : + +```{ .dockerfile .annotate } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. Ici, nous utilisons l'option de ligne de commande `--workers` pour dรฉfinir le nombre de workers ร  4. + +Voici quelques exemples oรน cela pourrait avoir du sens : + +#### Une application simple { #a-simple-app } + +Vous pourriez vouloir un gestionnaire de processus dans le conteneur si votre application est **suffisamment simple** pour s'exรฉcuter sur un **seul serveur**, pas un cluster. + +#### Docker Compose { #docker-compose } + +Vous pourriez dรฉployer sur un **seul serveur** (pas un cluster) avec **Docker Compose**, donc vous n'auriez pas un moyen simple de gรฉrer la rรฉplication des conteneurs (avec Docker Compose) tout en prรฉservant le rรฉseau partagรฉ et l'**รฉquilibrage de charge**. + +Vous pourriez alors vouloir avoir **un seul conteneur** avec un **gestionnaire de processus** qui dรฉmarre **plusieurs processus worker** ร  l'intรฉrieur. --- -Avec ces informations et ces outils, passez ร  la section suivante pour tout combiner. +L'idรฉe principale est que **rien** de tout cela ne sont des **rรจgles gravรฉes dans la pierre** que vous devez suivre aveuglรฉment. Vous pouvez utiliser ces idรฉes pour **รฉvaluer votre propre cas d'usage** et dรฉcider de la meilleure approche pour votre systรจme, en vรฉrifiant comment gรฉrer les concepts suivants : + +* Sรฉcuritรฉ - HTTPS +* Exรฉcution au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables au dรฉmarrage + +## Mรฉmoire { #memory } + +Si vous exรฉcutez **un seul processus par conteneur**, vous aurez une quantitรฉ de mรฉmoire consommรฉe plus ou moins bien dรฉfinie, stable et limitรฉe par chacun de ces conteneurs (plus d'un s'ils sont rรฉpliquรฉs). + +Vous pouvez alors dรฉfinir ces mรชmes limites et exigences de mรฉmoire dans vos configurations pour votre systรจme de gestion de conteneurs (par exemple dans **Kubernetes**). De cette faรงon, il pourra **rรฉpliquer les conteneurs** sur les **machines disponibles** en tenant compte de la quantitรฉ de mรฉmoire dont ils ont besoin et de la quantitรฉ disponible sur les machines du cluster. + +Si votre application est **simple**, cela ne sera probablement **pas un problรจme**, et vous n'aurez peut-รชtre pas besoin de spรฉcifier des limites de mรฉmoire strictes. Mais si vous **utilisez beaucoup de mรฉmoire** (par exemple avec des modรจles de **machine learning**), vous devez vรฉrifier combien de mรฉmoire vous consommez et ajuster le **nombre de conteneurs** qui s'exรฉcutent sur **chaque machine** (et peut-รชtre ajouter plus de machines ร  votre cluster). + +Si vous exรฉcutez **plusieurs processus par conteneur**, vous devez vous assurer que le nombre de processus dรฉmarrรฉs ne **consomme pas plus de mรฉmoire** que ce qui est disponible. + +## ร‰tapes prรฉalables au dรฉmarrage et conteneurs { #previous-steps-before-starting-and-containers } + +Si vous utilisez des conteneurs (par ex. Docker, Kubernetes), alors il existe deux approches principales que vous pouvez utiliser. + +### Plusieurs conteneurs { #multiple-containers } + +Si vous avez **plusieurs conteneurs**, probablement chacun exรฉcutant un **seul processus** (par exemple, dans un cluster **Kubernetes**), alors vous voudrez probablement avoir un **conteneur sรฉparรฉ** effectuant le travail des **รฉtapes prรฉalables** dans un seul conteneur, exรฉcutant un seul processus, **avant** d'exรฉcuter les conteneurs worker rรฉpliquรฉs. + +/// info + +Si vous utilisez Kubernetes, ce sera probablement un Init Container. + +/// + +Si, dans votre cas d'usage, il n'y a pas de problรจme ร  exรฉcuter ces รฉtapes prรฉalables **plusieurs fois en parallรจle** (par exemple si vous n'exรฉcutez pas de migrations de base de donnรฉes, mais vรฉrifiez simplement si la base de donnรฉes est prรชte), alors vous pourriez aussi simplement les mettre dans chaque conteneur juste avant de dรฉmarrer le processus principal. + +### Un seul conteneur { #single-container } + +Si vous avez une configuration simple, avec **un seul conteneur** qui dรฉmarre ensuite plusieurs **processus worker** (ou un seul processus aussi), vous pouvez alors exรฉcuter ces รฉtapes prรฉalables dans le mรชme conteneur, juste avant de dรฉmarrer le processus avec l'application. + +### Image Docker de base { #base-docker-image } + +Il existait une image Docker officielle FastAPI : tiangolo/uvicorn-gunicorn-fastapi. Mais elle est dรฉsormais dรฉprรฉciรฉe. โ›”๏ธ + +Vous ne devriez probablement **pas** utiliser cette image Docker de base (ni aucune autre similaire). + +Si vous utilisez **Kubernetes** (ou autres) et que vous dรฉfinissez dรฉjร  la **rรฉplication** au niveau du cluster, avec plusieurs **conteneurs**. Dans ces cas, il est prรฉfรฉrable de **construire une image ร  partir de zรฉro** comme dรฉcrit ci-dessus : [Construire une image Docker pour FastAPI](#build-a-docker-image-for-fastapi). + +Et si vous devez avoir plusieurs workers, vous pouvez simplement utiliser l'option de ligne de commande `--workers`. + +/// note | Dรฉtails techniques + +L'image Docker a รฉtรฉ crรฉรฉe ร  une รฉpoque oรน Uvicorn ne supportait pas la gestion et le redรฉmarrage des workers morts, il fallait donc utiliser Gunicorn avec Uvicorn, ce qui ajoutait pas mal de complexitรฉ, uniquement pour que Gunicorn gรจre et redรฉmarre les processus worker Uvicorn. + +Mais maintenant qu'Uvicorn (et la commande `fastapi`) supporte l'usage de `--workers`, il n'y a plus de raison d'utiliser une image Docker de base au lieu de construire la vรดtre (c'est ร  peu prรจs la mรชme quantitรฉ de code ๐Ÿ˜…). + +/// + +## Dรฉployer l'image de conteneur { #deploy-the-container-image } -## Cluster en mode Docker Swarm avec Traefik et HTTPS +Aprรจs avoir une image de conteneur (Docker), il existe plusieurs faรงons de la dรฉployer. -Vous pouvez avoir un cluster en mode Docker Swarm configurรฉ en quelques minutes (environ 20 min) avec un processus Traefik principal gรฉrant HTTPS (y compris l'acquisition et le renouvellement des certificats). +Par exemple : -En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut mรชme s'agir -d'un serveur ร  5 USD/mois) et ensuite vous pouvez vous dรฉvelopper autant que vous le souhaitez en ajoutant d'autres serveurs. +* Avec **Docker Compose** sur un seul serveur +* Avec un cluster **Kubernetes** +* Avec un cluster Docker Swarm Mode +* Avec un autre outil comme Nomad +* Avec un service cloud qui prend votre image de conteneur et la dรฉploie -Pour configurer un cluster en mode Docker Swarm avec Traefik et la gestion de HTTPS, suivez ce guideย : +## Image Docker avec `uv` { #docker-image-with-uv } -### Docker Swarm Mode et Traefik pour un cluster HTTPS +Si vous utilisez uv pour installer et gรฉrer votre projet, vous pouvez suivre leur guide Docker pour uv. -### Dรฉployer une application FastAPI +## Rรฉcapitulatif { #recap } -La faรงon la plus simple de tout mettre en place, serait d'utiliser les [**Gรฉnรฉrateurs de projet FastAPI**](../project-generation.md){.internal-link target=_blank}. +Avec les systรจmes de conteneurs (par ex. avec **Docker** et **Kubernetes**), il devient assez simple de gรฉrer tous les **concepts de dรฉploiement** : -Le gรฉnerateur de projet adรฉquat est conรงu pour รชtre intรฉgrรฉ ร  ce cluster Docker Swarm avec Traefik et HTTPS dรฉcrit ci-dessus. +* HTTPS +* Exรฉcution au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables au dรฉmarrage -Vous pouvez gรฉnรฉrer un projet en 2 min environ. +Dans la plupart des cas, vous ne voudrez probablement pas utiliser d'image de base, et au contraire **construire une image de conteneur ร  partir de zรฉro** basรฉe sur l'image Docker Python officielle. -Le projet gรฉnรฉrรฉ a des instructions pour le dรฉployer et le faire prend 2 min de plus. +En prenant soin de l'**ordre** des instructions dans le `Dockerfile` et du **cache Docker**, vous pouvez **minimiser les temps de construction**, maximiser votre productivitรฉ (et รฉviter l'ennui). ๐Ÿ˜Ž diff --git a/docs/fr/docs/deployment/https.md b/docs/fr/docs/deployment/https.md index 3f7068ff03..74d38cdb9f 100644 --- a/docs/fr/docs/deployment/https.md +++ b/docs/fr/docs/deployment/https.md @@ -1,56 +1,231 @@ -# ร€ propos de HTTPS +# ร€ propos de HTTPS { #about-https } -Il est facile de penser que HTTPS peut simplement รชtre "activรฉ" ou non. +Il est facile de supposer que HTTPS est quelque chose qui est simplement ยซ activรฉ ยป ou non. Mais c'est beaucoup plus complexe que cela. -/// tip +/// tip | Astuce -Si vous รชtes pressรฉ ou si cela ne vous intรฉresse pas, passez aux sections suivantes pour obtenir des instructions รฉtape par รฉtape afin de tout configurer avec diffรฉrentes techniques. +Si vous รชtes pressรฉ ou si cela ne vous intรฉresse pas, continuez avec les sections suivantes pour obtenir des instructions รฉtape par รฉtape afin de tout configurer avec diffรฉrentes techniques. /// -Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez https://howhttps.works/. +Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez https://howhttps.works/. Maintenant, du point de vue d'un dรฉveloppeur, voici plusieurs choses ร  avoir en tรชte en pensant au HTTPSย : -* Pour le HTTPS, le serveur a besoin de "certificats" gรฉnรฉrรฉs par une tierce partie. - * Ces certificats sont en fait acquis auprรจs de la tierce partie, et non "gรฉnรฉrรฉs". -* Les certificats ont une durรฉe de vie. - * Ils expirent. - * Puis ils doivent รชtre renouvelรฉs et acquis ร  nouveau auprรจs de la tierce partie. -* Le cryptage de la connexion se fait au niveau du protocole TCP. - * C'est une couche en dessous de HTTP. - * Donc, le certificat et le traitement du cryptage sont faits avant HTTP. -* TCP ne connaรฎt pas les "domaines", seulement les adresses IP. - * L'information sur le domaine spรฉcifique demandรฉ se trouve dans les donnรฉes HTTP. -* Les certificats HTTPS "certifient" un certain domaine, mais le protocole et le cryptage se font au niveau TCP, avant de savoir quel domaine est traitรฉ. -* Par dรฉfaut, cela signifie que vous ne pouvez avoir qu'un seul certificat HTTPS par adresse IP. - * Quelle que soit la taille de votre serveur ou la taille de chacune des applications qu'il contient. - * Il existe cependant une solution ร  ce problรจme. -* Il existe une extension du protocole TLS (celui qui gรจre le cryptage au niveau TCP, avant HTTP) appelรฉe SNI (indication du nom du serveur). - * Cette extension SNI permet ร  un seul serveur (avec une seule adresse IP) d'avoir plusieurs certificats HTTPS et de servir plusieurs domaines/applications HTTPS. - * Pour que cela fonctionne, un seul composant (programme) fonctionnant sur le serveur, รฉcoutant sur l'adresse IP publique, doit avoir tous les certificats HTTPS du serveur. -* Aprรจs avoir obtenu une connexion sรฉcurisรฉe, le protocole de communication est toujours HTTP. - * Le contenu est cryptรฉ, mรชme s'il est envoyรฉ avec le protocole HTTP. - -Il est courant d'avoir un seul programme/serveur HTTP fonctionnant sur le serveur (la machine, l'hรดte, etc.) et -gรฉrant toutes les parties HTTPS : envoyer les requรชtes HTTP dรฉcryptรฉes ร  l'application HTTP rรฉelle fonctionnant sur -le mรชme serveur (dans ce cas, l'application **FastAPI**), prendre la rรฉponse HTTP de l'application, la crypter en utilisant le certificat appropriรฉ et la renvoyer au client en utilisant HTTPS. Ce serveur est souvent appelรฉ un Proxy de terminaison TLS. - -## Let's Encrypt - -Avant Let's Encrypt, ces certificats HTTPS รฉtaient vendus par des tiers de confiance. - -Le processus d'acquisition d'un de ces certificats รฉtait auparavant lourd, nรฉcessitait pas mal de paperasses et les certificats รฉtaient assez chers. - -Mais ensuite, Let's Encrypt a รฉtรฉ crรฉรฉ. - -Il s'agit d'un projet de la Fondation Linux. Il fournit des certificats HTTPS gratuitement. De maniรจre automatisรฉe. Ces certificats utilisent toutes les sรฉcuritรฉs cryptographiques standard et ont une durรฉe de vie courte (environ 3 mois), de sorte que la sรฉcuritรฉ est en fait meilleure en raison de leur durรฉe de vie rรฉduite. +* Pour le HTTPS, **le serveur** doit **disposer de ยซ certificats ยป** gรฉnรฉrรฉs par une **tierce partie**. + * Ces certificats sont en rรฉalitรฉ **acquis** auprรจs de la tierce partie, et non ยซ gรฉnรฉrรฉs ยป. +* Les certificats ont une **durรฉe de vie**. + * Ils **expirent**. + * Puis ils doivent รชtre **renouvelรฉs**, **acquis ร  nouveau** auprรจs de la tierce partie. +* Le cryptage de la connexion se fait au **niveau TCP**. + * C'est une couche **en dessous de HTTP**. + * Donc, la gestion du **certificat et du cryptage** est effectuรฉe **avant HTTP**. +* **TCP ne connaรฎt pas les ยซ domaines ยป**. Il ne connaรฎt que les adresses IP. + * L'information sur le **domaine spรฉcifique** demandรฉ se trouve dans les **donnรฉes HTTP**. +* Les **certificats HTTPS** ยซ certifient ยป un **certain domaine**, mais le protocole et le cryptage se font au niveau TCP, **avant de savoir** quel domaine est traitรฉ. +* **Par dรฉfaut**, cela signifie que vous ne pouvez avoir qu'**un seul certificat HTTPS par adresse IP**. + * Quelle que soit la taille de votre serveur ou la petitesse de chacune des applications qu'il contient. + * Il existe cependant une **solution** ร  ce problรจme. +* Il existe une **extension** du protocole **TLS** (celui qui gรจre le cryptage au niveau TCP, avant HTTP) appelรฉe **SNI**. + * Cette extension SNI permet ร  un seul serveur (avec une **seule adresse IP**) d'avoir **plusieurs certificats HTTPS** et de servir **plusieurs domaines/applications HTTPS**. + * Pour que cela fonctionne, un **seul** composant (programme) fonctionnant sur le serveur, รฉcoutant sur l'**adresse IP publique**, doit avoir **tous les certificats HTTPS** du serveur. +* **Aprรจs** l'รฉtablissement d'une connexion sรฉcurisรฉe, le protocole de communication est **toujours HTTP**. + * Le contenu est **cryptรฉ**, mรชme s'il est envoyรฉ avec le **protocole HTTP**. + +Il est courant d'avoir **un seul programme/serveur HTTP** fonctionnant sur le serveur (la machine, l'hรดte, etc.) et **gรฉrant toutes les parties HTTPS**ย : recevoir les **requรชtes HTTPS chiffrรฉes**, envoyer les **requรชtes HTTP dรฉchiffrรฉes** ร  l'application HTTP rรฉelle fonctionnant sur le mรชme serveur (l'application **FastAPI**, dans ce cas), prendre la **rรฉponse HTTP** de l'application, la **chiffrer** en utilisant le **certificat HTTPS** appropriรฉ et la renvoyer au client en utilisant **HTTPS**. Ce serveur est souvent appelรฉ un **Proxy de terminaison TLS**. + +Parmi les options que vous pourriez utiliser comme Proxy de terminaison TLSย : + +* Traefik (qui peut รฉgalement gรฉrer les renouvellements de certificats) +* Caddy (qui peut รฉgalement gรฉrer les renouvellements de certificats) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Avant Let's Encrypt, ces **certificats HTTPS** รฉtaient vendus par des tiers de confiance. + +Le processus d'acquisition de l'un de ces certificats รฉtait auparavant lourd, nรฉcessitait pas mal de paperasses et les certificats รฉtaient assez chers. + +Mais ensuite, **Let's Encrypt** a รฉtรฉ crรฉรฉ. + +Il s'agit d'un projet de la Fondation Linux. Il fournit **des certificats HTTPS gratuitement**, de maniรจre automatisรฉe. Ces certificats utilisent toutes les sรฉcuritรฉs cryptographiques standard et ont une durรฉe de vie courte (environ 3 mois), de sorte que la **sรฉcuritรฉ est en fait meilleure** en raison de leur durรฉe de vie rรฉduite. Les domaines sont vรฉrifiรฉs de maniรจre sรฉcurisรฉe et les certificats sont gรฉnรฉrรฉs automatiquement. Cela permet รฉgalement d'automatiser le renouvellement de ces certificats. -L'idรฉe est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un HTTPS sรฉcurisรฉ, gratuitement et pour toujours. +L'idรฉe est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un **HTTPS sรฉcurisรฉ, gratuitement et pour toujours**. + +## HTTPS pour les dรฉveloppeurs { #https-for-developers } + +Voici un exemple de ce ร  quoi pourrait ressembler une API HTTPS, รฉtape par รฉtape, en portant principalement attention aux idรฉes importantes pour les dรฉveloppeurs. + +### Nom de domaine { #domain-name } + +Tout commencerait probablement par le fait que vous **acquรฉriez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le mรชme que votre fournisseur cloud). + +Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP **publique** fixe. + +Dans le ou les serveurs DNS, vous configureriez un enregistrement (un ยซ `A record` ยป) pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**. + +Vous feriez probablement cela une seule fois, la premiรจre fois, lors de la mise en place de l'ensemble. + +/// tip | Astuce + +Cette partie relative au nom de domaine intervient bien avant HTTPS, mais comme tout dรฉpend du domaine et de l'adresse IP, il vaut la peine de la mentionner ici. + +/// + +### DNS { #dns } + +Concentrons-nous maintenant sur toutes les parties rรฉellement liรฉes ร  HTTPS. + +D'abord, le navigateur vรฉrifierait auprรจs des **serveurs DNS** quelle est l'**IP du domaine**, dans ce cas, `someapp.example.com`. + +Les serveurs DNS indiqueraient au navigateur d'utiliser une **adresse IP** spรฉcifique. Ce serait l'adresse IP publique utilisรฉe par votre serveur, celle que vous avez configurรฉe dans les serveurs DNS. + + + +### Dรฉbut de la nรฉgociation TLS (Handshake) { #tls-handshake-start } + +Le navigateur communiquerait ensuite avec cette adresse IP sur le **port 443** (le port HTTPS). + +La premiรจre partie de la communication consiste simplement ร  รฉtablir la connexion entre le client et le serveur et ร  dรฉcider des clรฉs cryptographiques qu'ils utiliseront, etc. + + + +Cette interaction entre le client et le serveur pour รฉtablir la connexion TLS s'appelle la **nรฉgociation TLS (TLS handshake)**. + +### TLS avec l'extension SNI { #tls-with-sni-extension } + +**Un seul processus** sur le serveur peut รฉcouter sur un **port** spรฉcifique d'une **adresse IP** spรฉcifique. Il pourrait y avoir d'autres processus รฉcoutant sur d'autres ports de la mรชme adresse IP, mais un seul pour chaque combinaison d'adresse IP et de port. + +TLS (HTTPS) utilise par dรฉfaut le port spรฉcifique `443`. C'est donc le port dont nous aurions besoin. + +Comme un seul processus peut รฉcouter sur ce port, le processus qui le ferait serait le **Proxy de terminaison TLS**. + +Le Proxy de terminaison TLS aurait accรจs ร  un ou plusieurs **certificats TLS** (certificats HTTPS). + +En utilisant l'**extension SNI** mentionnรฉe plus haut, le Proxy de terminaison TLS vรฉrifierait lequel des certificats TLS (HTTPS) disponibles il devrait utiliser pour cette connexion, en choisissant celui qui correspond au domaine attendu par le client. + +Dans ce cas, il utiliserait le certificat pour `someapp.example.com`. + + + +Le client **fait dรฉjร  confiance** ร  l'entitรฉ qui a gรฉnรฉrรฉ ce certificat TLS (dans ce cas Let's Encrypt, mais nous y reviendrons plus tard), il peut donc **vรฉrifier** que le certificat est valide. + +Ensuite, en utilisant le certificat, le client et le Proxy de terminaison TLS **dรฉcident comment chiffrer** le reste de la **communication TCP**. Cela termine la partie **nรฉgociation TLS**. + +Aprรจs cela, le client et le serveur disposent d'une **connexion TCP chiffrรฉe**, c'est ce que fournit TLS. Ils peuvent alors utiliser cette connexion pour dรฉmarrer la **communication HTTP** proprement dite. + +Et c'est ce qu'est **HTTPS**ย : c'est simplement du **HTTP** ร  l'intรฉrieur d'une **connexion TLS sรฉcurisรฉe** au lieu d'une connexion TCP pure (non chiffrรฉe). + +/// tip | Astuce + +Remarquez que le cryptage de la communication se produit au **niveau TCP**, pas au niveau HTTP. + +/// + +### Requรชte HTTPS { #https-request } + +Maintenant que le client et le serveur (spรฉcifiquement le navigateur et le Proxy de terminaison TLS) ont une **connexion TCP chiffrรฉe**, ils peuvent dรฉmarrer la **communication HTTP**. + +Ainsi, le client envoie une **requรชte HTTPS**. Ce n'est qu'une requรชte HTTP ร  travers une connexion TLS chiffrรฉe. + + + +### Dรฉchiffrer la requรชte { #decrypt-the-request } + +Le Proxy de terminaison TLS utiliserait le chiffrement convenu pour **dรฉchiffrer la requรชte**, et transmettrait la **requรชte HTTP en clair (dรฉchiffrรฉe)** au processus exรฉcutant l'application (par exemple un processus avec Uvicorn exรฉcutant l'application FastAPI). + + + +### Rรฉponse HTTP { #http-response } + +L'application traiterait la requรชte et enverrait une **rรฉponse HTTP en clair (non chiffrรฉe)** au Proxy de terminaison TLS. + + + +### Rรฉponse HTTPS { #https-response } + +Le Proxy de terminaison TLS **chiffrerait ensuite la rรฉponse** en utilisant la cryptographie convenue auparavant (qui a commencรฉ avec le certificat pour `someapp.example.com`), et la renverrait au navigateur. + +Ensuite, le navigateur vรฉrifierait que la rรฉponse est valide et chiffrรฉe avec la bonne clรฉ cryptographique, etc. Il **dรฉchiffrerait la rรฉponse** et la traiterait. + + + +Le client (navigateur) saura que la rรฉponse provient du bon serveur parce qu'elle utilise la cryptographie convenue auparavant ร  l'aide du **certificat HTTPS**. + +### Applications multiples { #multiple-applications } + +Sur le mรชme serveur (ou les mรชmes serveurs), il pourrait y avoir **plusieurs applications**, par exemple d'autres programmes d'API ou une base de donnรฉes. + +Un seul processus peut gรฉrer l'adresse IP et le port spรฉcifiques (le Proxy de terminaison TLS dans notre exemple), mais les autres applications/processus peuvent รฉgalement s'exรฉcuter sur le ou les serveurs, tant qu'ils n'essaient pas d'utiliser la mรชme **combinaison d'adresse IP publique et de port**. + + + +De cette faรงon, le Proxy de terminaison TLS pourrait gรฉrer HTTPS et les certificats pour **plusieurs domaines**, pour plusieurs applications, puis transmettre les requรชtes ร  la bonne application dans chaque cas. + +### Renouvellement des certificats { #certificate-renewal } + +ร€ un moment donnรฉ dans le futur, chaque certificat **expirerait** (environ 3 mois aprรจs son acquisition). + +Ensuite, il y aurait un autre programme (dans certains cas c'est un autre programme, dans d'autres cas cela pourrait รชtre le mรชme Proxy de terminaison TLS) qui communiquerait avec Let's Encrypt et renouvellerait le ou les certificats. + + + +Les **certificats TLS** sont **associรฉs ร  un nom de domaine**, pas ร  une adresse IP. + +Ainsi, pour renouveler les certificats, le programme de renouvellement doit **prouver** ร  l'autoritรฉ (Let's Encrypt) qu'il **ยซ possรจde ยป et contrรดle ce domaine**. + +Pour ce faire, et pour s'adapter aux diffรฉrents besoins des applications, il existe plusieurs faรงons de procรฉder. Parmi les plus courantesย : + +* **Modifier certains enregistrements DNS**. + * Pour cela, le programme de renouvellement doit prendre en charge les API du fournisseur DNSย ; ainsi, selon le fournisseur DNS que vous utilisez, cela peut รชtre ou non une option. +* **S'exรฉcuter comme un serveur** (au moins pendant le processus d'acquisition du certificat) sur l'adresse IP publique associรฉe au domaine. + * Comme nous l'avons dit plus haut, un seul processus peut รฉcouter sur une adresse IP et un port spรฉcifiques. + * C'est l'une des raisons pour lesquelles il est trรจs utile que le mรชme Proxy de terminaison TLS prenne รฉgalement en charge le processus de renouvellement des certificats. + * Sinon, vous pourriez avoir ร  arrรชter le Proxy de terminaison TLS momentanรฉment, dรฉmarrer le programme de renouvellement pour acquรฉrir les certificats, puis les configurer avec le Proxy de terminaison TLS, et ensuite redรฉmarrer le Proxy de terminaison TLS. Ce n'est pas idรฉal, car votre/vos application(s) ne seront pas disponibles pendant le temps oรน le Proxy de terminaison TLS est arrรชtรฉ. + +Tout ce processus de renouvellement, tout en continuant ร  servir l'application, est l'une des principales raisons pour lesquelles vous voudriez avoir un **systรจme sรฉparรฉ pour gรฉrer HTTPS** avec un Proxy de terminaison TLS, au lieu d'utiliser directement les certificats TLS avec le serveur d'application (par exemple Uvicorn). + +## En-tรชtes Proxy Forwarded { #proxy-forwarded-headers } + +Lorsque vous utilisez un proxy pour gรฉrer HTTPS, votre **serveur d'application** (par exemple Uvicorn via FastAPI CLI) ne connaรฎt rien du processus HTTPS, il communique en HTTP en clair avec le **Proxy de terminaison TLS**. + +Ce **proxy** dรฉfinirait normalement certains en-tรชtes HTTP ร  la volรฉe avant de transmettre la requรชte au **serveur d'application**, pour informer le serveur d'application que la requรชte est **transmise** par le proxy. + +/// note | Dรฉtails techniques + +Les en-tรชtes du proxy sontย : + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +Nรฉanmoins, comme le **serveur d'application** ne sait pas qu'il se trouve derriรจre un **proxy** de confiance, par dรฉfaut, il ne ferait pas confiance ร  ces en-tรชtes. + +Mais vous pouvez configurer le **serveur d'application** pour qu'il fasse confiance aux en-tรชtes transmis (*forwarded*) envoyรฉs par le **proxy**. Si vous utilisez FastAPI CLI, vous pouvez utiliser l'*option CLI* `--forwarded-allow-ips` pour lui indiquer ร  partir de quelles IP il doit faire confiance ร  ces en-tรชtes transmis. + +Par exemple, si le **serveur d'application** ne reรงoit des communications que du **proxy** de confiance, vous pouvez dรฉfinir `--forwarded-allow-ips="*"` pour lui faire faire confiance ร  toutes les IP entrantes, puisqu'il ne recevra des requรชtes que depuis l'IP utilisรฉe par le **proxy**. + +De cette faรงon, l'application sera en mesure de savoir quelle est sa propre URL publique, si elle utilise HTTPS, le domaine, etc. + +Cela serait utile, par exemple, pour gรฉrer correctement les redirections. + +/// tip | Astuce + +Vous pouvez en savoir plus dans la documentation [Derriรจre un proxy - Activer les en-tรชtes transmis par le proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} + +/// + +## Rรฉcapitulatif { #recap } + +Disposer de **HTTPS** est trรจs important, et assez **critique** dans la plupart des cas. La majeure partie de l'effort que vous, en tant que dรฉveloppeur, devez fournir autour de HTTPS consiste simplement ร  **comprendre ces concepts** et leur fonctionnement. + +Mais une fois que vous connaissez les informations de base sur **HTTPS pour les dรฉveloppeurs**, vous pouvez facilement combiner et configurer diffรฉrents outils pour vous aider ร  tout gรฉrer simplement. + +Dans certains des prochains chapitres, je vous montrerai plusieurs exemples concrets de configuration de **HTTPS** pour des applications **FastAPI**. ๐Ÿ”’ diff --git a/docs/fr/docs/deployment/index.md b/docs/fr/docs/deployment/index.md index e2014afe95..3b08e9af76 100644 --- a/docs/fr/docs/deployment/index.md +++ b/docs/fr/docs/deployment/index.md @@ -1,8 +1,8 @@ -# Dรฉploiement +# Dรฉploiement { #deployment } Le dรฉploiement d'une application **FastAPI** est relativement simple. -## Que signifie le dรฉploiement +## Que signifie le dรฉploiement { #what-does-deployment-mean } **Dรฉployer** une application signifie effectuer les รฉtapes nรฉcessaires pour la rendre **disponible pour les utilisateurs**. @@ -14,7 +14,7 @@ l'application efficacement et sans interruption ni problรจme. Ceci contraste avec les รฉtapes de **dรฉveloppement**, oรน vous รชtes constamment en train de modifier le code, de le casser et de le rรฉparer, d'arrรชter et de redรฉmarrer le serveur de dรฉveloppement, _etc._ -## Stratรฉgies de dรฉploiement +## Stratรฉgies de dรฉploiement { #deployment-strategies } Il existe plusieurs faรงons de procรฉder, en fonction de votre cas d'utilisation spรฉcifique et des outils que vous utilisez. @@ -22,6 +22,8 @@ utilisez. Vous pouvez **dรฉployer un serveur** vous-mรชme en utilisant une combinaison d'outils, vous pouvez utiliser un **service cloud** qui fait une partie du travail pour vous, ou encore d'autres options possibles. +Par exemple, nous, l'รฉquipe derriรจre FastAPI, avons crรฉรฉ **FastAPI Cloud**, pour rendre le dรฉploiement d'applications FastAPI dans le cloud aussi fluide que possible, avec la mรชme expรฉrience dรฉveloppeur que lorsque vous travaillez avec FastAPI. + Je vais vous montrer certains des principaux concepts que vous devriez probablement avoir ร  l'esprit lors du dรฉploiement d'une application **FastAPI** (bien que la plupart de ces concepts s'appliquent ร  tout autre type d'application web). diff --git a/docs/fr/docs/deployment/versions.md b/docs/fr/docs/deployment/versions.md index 9d84274e27..81794428fb 100644 --- a/docs/fr/docs/deployment/versions.md +++ b/docs/fr/docs/deployment/versions.md @@ -1,101 +1,93 @@ -# ร€ propos des versions de FastAPI +# ร€ propos des versions de FastAPI { #about-fastapi-versions } -**FastAPI** est dรฉjร  utilisรฉ en production dans de nombreuses applications et systรจmes. Et la couverture de test est maintenue ร  100 %. Mais son dรฉveloppement est toujours aussi rapide. +**FastAPI** est dรฉjร  utilisรฉ en production dans de nombreuses applications et de nombreux systรจmes. Et la couverture de tests est maintenue ร  100 %. Mais son dรฉveloppement avance toujours rapidement. -De nouvelles fonctionnalitรฉs sont ajoutรฉes frรฉquemment, des bogues sont corrigรฉs rรฉguliรจrement et le code est -amรฉliorรฉ continuellement. +De nouvelles fonctionnalitรฉs sont ajoutรฉes frรฉquemment, des bogues sont corrigรฉs rรฉguliรจrement et le code s'amรฉliore continuellement. -C'est pourquoi les versions actuelles sont toujours `0.x.x`, cela reflรจte que chaque version peut potentiellement -recevoir des changements non rรฉtrocompatibles. Cela suit les conventions de versionnage sรฉmantique. +C'est pourquoi les versions actuelles sont toujours `0.x.x`, cela reflรจte que chaque version pourrait potentiellement comporter des changements non rรฉtrocompatibles. Cela suit les conventions de versionnage sรฉmantique. Vous pouvez crรฉer des applications de production avec **FastAPI** dรจs maintenant (et vous le faites probablement depuis un certain temps), vous devez juste vous assurer que vous utilisez une version qui fonctionne correctement avec le reste de votre code. -## ร‰pinglez votre version de `fastapi` +## ร‰pingler votre version de `fastapi` { #pin-your-fastapi-version } -Tout d'abord il faut "รฉpingler" la version de **FastAPI** que vous utilisez ร  la derniรจre version dont vous savez -qu'elle fonctionne correctement pour votre application. +La premiรจre chose que vous devez faire est ยซ รฉpingler ยป la version de **FastAPI** que vous utilisez ร  la derniรจre version spรฉcifique dont vous savez quโ€™elle fonctionne correctement pour votre application. -Par exemple, disons que vous utilisez la version `0.45.0` dans votre application. +Par exemple, disons que vous utilisez la version `0.112.0` dans votre application. -Si vous utilisez un fichier `requirements.txt`, vous pouvez spรฉcifier la version avecย : +Si vous utilisez un fichier `requirements.txt`, vous pouvez spรฉcifier la version avec : ```txt -fastapi==0.45.0 +fastapi[standard]==0.112.0 ``` -ce qui signifierait que vous utiliseriez exactement la version `0.45.0`. +ce qui signifierait que vous utiliseriez exactement la version `0.112.0`. -Ou vous pourriez aussi l'รฉpingler avecย : +Ou vous pourriez aussi l'รฉpingler avec : ```txt -fastapi>=0.45.0,<0.46.0 +fastapi[standard]>=0.112.0,<0.113.0 ``` -cela signifierait que vous utiliseriez les versions `0.45.0` ou supรฉrieures, mais infรฉrieures ร  `0.46.0`, par exemple, une version `0.45.2` serait toujours acceptรฉe. +cela signifierait que vous utiliseriez les versions `0.112.0` ou supรฉrieures, mais infรฉrieures ร  `0.113.0`, par exemple, une version `0.112.2` serait toujours acceptรฉe. -Si vous utilisez un autre outil pour gรฉrer vos installations, comme Poetry, Pipenv, ou autres, ils ont tous un moyen que vous pouvez utiliser pour dรฉfinir des versions spรฉcifiques pour vos paquets. +Si vous utilisez un autre outil pour gรฉrer vos installations, comme `uv`, Poetry, Pipenv, ou autres, ils ont tous un moyen que vous pouvez utiliser pour dรฉfinir des versions spรฉcifiques pour vos paquets. -## Versions disponibles +## Versions disponibles { #available-versions } Vous pouvez consulter les versions disponibles (par exemple, pour vรฉrifier quelle est la derniรจre version en date) dans les [Notes de version](../release-notes.md){.internal-link target=_blank}. -## ร€ propos des versions +## ร€ propos des versions { #about-versions } -Suivant les conventions de versionnage sรฉmantique, toute version infรฉrieure ร  `1.0.0` peut potentiellement ajouter -des changements non rรฉtrocompatibles. +Suivant les conventions de versionnage sรฉmantique, toute version infรฉrieure ร  `1.0.0` peut potentiellement ajouter des changements non rรฉtrocompatibles. -FastAPI suit รฉgalement la convention que tout changement de version "PATCH" est pour des corrections de bogues et -des changements rรฉtrocompatibles. +FastAPI suit รฉgalement la convention selon laquelle tout changement de version ยซ PATCH ยป concerne des corrections de bogues et des changements rรฉtrocompatibles. /// tip | Astuce -Le "PATCH" est le dernier chiffre, par exemple, dans `0.2.3`, la version PATCH est `3`. +Le ยซ PATCH ยป est le dernier chiffre, par exemple, dans `0.2.3`, la version PATCH est `3`. /// -Donc, vous devriez รชtre capable d'รฉpingler une version comme suitย : +Donc, vous devriez รชtre en mesure d'รฉpingler une version comme suit : ```txt fastapi>=0.45.0,<0.46.0 ``` -Les changements non rรฉtrocompatibles et les nouvelles fonctionnalitรฉs sont ajoutรฉs dans les versions "MINOR". +Les changements non rรฉtrocompatibles et les nouvelles fonctionnalitรฉs sont ajoutรฉs dans les versions ยซ MINOR ยป. /// tip | Astuce -Le "MINOR" est le numรฉro au milieu, par exemple, dans `0.2.3`, la version MINOR est `2`. +Le ยซ MINOR ยป est le numรฉro au milieu, par exemple, dans `0.2.3`, la version MINOR est `2`. /// -## Mise ร  jour des versions FastAPI +## Mettre ร  niveau les versions de FastAPI { #upgrading-the-fastapi-versions } -Vous devriez tester votre application. +Vous devez ajouter des tests pour votre application. -Avec **FastAPI** c'est trรจs facile (merci ร  Starlette), consultez la documentation : [Testing](../tutorial/testing.md){.internal-link target=_blank} +Avec **FastAPI** c'est trรจs facile (merci ร  Starlette), consultez les documents : [Tests](../tutorial/testing.md){.internal-link target=_blank} -Aprรจs avoir effectuรฉ des tests, vous pouvez mettre ร  jour la version **FastAPI** vers une version plus rรฉcente, et vous assurer que tout votre code fonctionne correctement en exรฉcutant vos tests. +Aprรจs avoir des tests, vous pouvez mettre ร  niveau la version de **FastAPI** vers une version plus rรฉcente et vous assurer que tout votre code fonctionne correctement en exรฉcutant vos tests. -Si tout fonctionne, ou aprรจs avoir fait les changements nรฉcessaires, et que tous vos tests passent, vous pouvez -รฉpingler votre version de `fastapi` ร  cette nouvelle version rรฉcente. +Si tout fonctionne, ou aprรจs avoir effectuรฉ les changements nรฉcessaires, et que tous vos tests passent, vous pouvez alors รฉpingler votre `fastapi` ร  cette nouvelle version rรฉcente. -## ร€ propos de Starlette +## ร€ propos de Starlette { #about-starlette } -Vous ne devriez pas รฉpingler la version de `starlette`. +Vous ne devez pas รฉpingler la version de `starlette`. Diffรฉrentes versions de **FastAPI** utiliseront une version spรฉcifique plus rรฉcente de Starlette. Ainsi, vous pouvez simplement laisser **FastAPI** utiliser la bonne version de Starlette. -## ร€ propos de Pydantic +## ร€ propos de Pydantic { #about-pydantic } -Pydantic inclut des tests pour **FastAPI** avec ses propres tests, ainsi les nouvelles versions de Pydantic (au-dessus -de `1.0.0`) sont toujours compatibles avec **FastAPI**. +Pydantic inclut les tests pour **FastAPI** avec ses propres tests, ainsi les nouvelles versions de Pydantic (au-dessus de `1.0.0`) sont toujours compatibles avec FastAPI. -Vous pouvez รฉpingler Pydantic ร  toute version supรฉrieure ร  `1.0.0` qui fonctionne pour vous et infรฉrieure ร  `2.0.0`. +Vous pouvez รฉpingler Pydantic ร  toute version supรฉrieure ร  `1.0.0` qui fonctionne pour vous. -Par exempleย : +Par exemple : ```txt -pydantic>=1.2.0,<2.0.0 +pydantic>=2.7.0,<3.0.0 ``` diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 99ea8dda12..2aeaa1c692 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -1,11 +1,11 @@ -# FastAPI +# FastAPI { #fastapi }

- FastAPI + FastAPI

Framework FastAPI, haute performance, facile ร  apprendre, rapide ร  coder, prรชt pour la production @@ -27,7 +27,7 @@ --- -**Documentation** : https://fastapi.tiangolo.com +**Documentation** : https://fastapi.tiangolo.com/fr **Code Source** : https://github.com/fastapi/fastapi @@ -37,128 +37,130 @@ FastAPI est un framework web moderne et rapide (haute performance) pour la crรฉa Les principales fonctionnalitรฉs sont : -* **Rapiditรฉ** : De trรจs hautes performances, au niveau de **NodeJS** et **Go** (grรขce ร  Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). -* **Rapide ร  coder** : Augmente la vitesse de dรฉveloppement des fonctionnalitรฉs d'environ 200 % ร  300 %. * -* **Moins de bugs** : Rรฉduit d'environ 40 % les erreurs induites par le dรฉveloppeur. * -* **Intuitif** : Excellente compatibilitรฉ avec les IDE. Complรฉtion complรจte. Moins de temps passรฉ ร  dรฉboguer. -* **Facile** : Conรงu pour รชtre facile ร  utiliser et ร  apprendre. Moins de temps passรฉ ร  lire la documentation. -* **Concis** : Diminue la duplication de code. De nombreuses fonctionnalitรฉs liรฉes ร  la dรฉclaration de chaque paramรจtre. Moins de bugs. -* **Robuste** : Obtenez un code prรชt pour la production. Avec une documentation interactive automatique. -* **Basรฉ sur des normes** : Basรฉ sur (et entiรจrement compatible avec) les standards ouverts pour les APIs : OpenAPI (prรฉcรฉdemment connu sous le nom de Swagger) et JSON Schema. +* **Rapide** : trรจs hautes performances, au niveau de **NodeJS** et **Go** (grรขce ร  Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). +* **Rapide ร  coder** : augmente la vitesse de dรฉveloppement des fonctionnalitรฉs d'environ 200 % ร  300 %. * +* **Moins de bugs** : rรฉduit d'environ 40 % les erreurs induites par le dรฉveloppeur. * +* **Intuitif** : excellente compatibilitรฉ avec les รฉditeurs. Autocomplรฉtion partout. Moins de temps passรฉ ร  dรฉboguer. +* **Facile** : conรงu pour รชtre facile ร  utiliser et ร  apprendre. Moins de temps passรฉ ร  lire les documents. +* **Concis** : diminue la duplication de code. Plusieurs fonctionnalitรฉs ร  partir de chaque dรฉclaration de paramรจtre. Moins de bugs. +* **Robuste** : obtenez un code prรชt pour la production. Avec une documentation interactive automatique. +* **Basรฉ sur des normes** : basรฉ sur (et entiรจrement compatible avec) les standards ouverts pour les APIs : OpenAPI (prรฉcรฉdemment connu sous le nom de Swagger) et JSON Schema. * estimation basรฉe sur des tests d'une รฉquipe de dรฉveloppement interne, construisant des applications de production. -## Sponsors +## Sponsors { #sponsors } -{% if sponsors %} +### Sponsor clรฉ de voรปte { #keystone-sponsor } + +{% for sponsor in sponsors.keystone -%} + +{% endfor -%} + +### Sponsors Or et Argent { #gold-and-silver-sponsors } + {% for sponsor in sponsors.gold -%} {% endfor -%} {%- for sponsor in sponsors.silver -%} {% endfor %} -{% endif %} -Other sponsors +Autres sponsors -## Opinions +## Opinions { #opinions } -"_[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prรฉvois de l'utiliser dans mon รฉquipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux seront intรฉgrรฉs dans le coeur de **Windows** et dans certains produits **Office**._" +ยซ _[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prรฉvois de l'utiliser dans mon รฉquipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux sont intรฉgrรฉs au cล“ur de **Windows** et ร  certains produits **Office**._ ยป

Kabir Khan - Microsoft (ref)
--- -"_Nous avons adoptรฉ la bibliothรจque **FastAPI** pour crรฉer un serveur **REST** qui peut รชtre interrogรฉ pour obtenir des **prรฉdictions**. [pour Ludwig]_" +ยซ _Nous avons adoptรฉ la bibliothรจque **FastAPI** pour crรฉer un serveur **REST** qui peut รชtre interrogรฉ pour obtenir des **prรฉdictions**. [pour Ludwig]_ ยป -
Piero Molino, Yaroslav Dudin et Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, et Sai Sumanth Miryala - Uber (ref)
--- -"_**Netflix** a le plaisir d'annoncer la sortie en open-source de notre framework d'orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_" +ยซ _**Netflix** est heureux d'annoncer la publication en open source de notre framework d'orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_ ยป
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_Je suis trรจs enthousiaste ร  propos de **FastAPI**. C'est un bonheur !_" +ยซ _Je suis plus qu'enthousiaste ร  propos de **FastAPI**. C'est tellement fun !_ ยป -
Brian Okken - Auteur du podcast Python Bytes (ref)
+
Brian Okken - Animateur du podcast Python Bytes (ref)
--- -"_Honnรชtement, ce que vous avez construit a l'air super solide et รฉlรฉgant. A bien des รฉgards, c'est comme รงa que je voulais que **Hug** soit - c'est vraiment inspirant de voir quelqu'un construire รงa._" +ยซ _Honnรชtement, ce que vous avez construit a l'air super solide et soignรฉ. ร€ bien des รฉgards, c'est ce que je voulais que **Hug** soit โ€” c'est vraiment inspirant de voir quelqu'un construire รงa._ ยป -
Timothy Crosley - Crรฉateur de Hug (ref)
+
Timothy Crosley - Crรฉateur de Hug (ref)
--- -"_Si vous cherchez ร  apprendre un **framework moderne** pour crรฉer des APIs REST, regardez **FastAPI** [...] C'est rapide, facile ร  utiliser et ร  apprendre [...]_" +ยซ _Si vous cherchez ร  apprendre un **framework moderne** pour crรฉer des APIs REST, regardez **FastAPI** [...] C'est rapide, facile ร  utiliser et facile ร  apprendre [...]_ ยป -"_Nous sommes passรฉs ร  **FastAPI** pour nos **APIs** [...] Je pense que vous l'aimerez [...]_" +ยซ _Nous sommes passรฉs ร  **FastAPI** pour nos **APIs** [...] Je pense que vous l'aimerez [...]_ ยป
Ines Montani - Matthew Honnibal - Fondateurs de Explosion AI - Crรฉateurs de spaCy (ref) - (ref)
--- -"_Si quelqu'un cherche ร  construire une API Python de production, je recommande vivement **FastAPI**. Il est **bien conรงu**, **simple ร  utiliser** et **trรจs รฉvolutif**. Il est devenu un **composant clรฉ** dans notre stratรฉgie de dรฉveloppement API first et il est ร  l'origine de nombreux automatismes et services tels que notre ingรฉnieur virtuel TAC._" +ยซ _Si quelqu'un cherche ร  construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conรงu**, **simple ร  utiliser** et **hautement scalable**. Il est devenu un **composant clรฉ** de notre stratรฉgie de dรฉveloppement API-first et alimente de nombreuses automatisations et services tels que notre ingรฉnieur TAC virtuel._ ยป
Deon Pillsbury - Cisco (ref)
--- -## **Typer**, le FastAPI des CLI +## Mini documentaire FastAPI { #fastapi-mini-documentary } + +Un mini documentaire FastAPI est sorti fin 2025, vous pouvez le regarder en ligne : + +FastAPI Mini Documentary + +## **Typer**, le FastAPI des CLIs { #typer-the-fastapi-of-clis } -Si vous souhaitez construire une application CLI utilisable dans un terminal au lieu d'une API web, regardez **Typer**. +Si vous construisez une application CLI ร  utiliser dans un terminal au lieu d'une API web, regardez **Typer**. -**Typer** est le petit frรจre de FastAPI. Et il est destinรฉ ร  รชtre le **FastAPI des CLI**. โŒจ๏ธ ๐Ÿš€ +**Typer** est le petit frรจre de FastAPI. Et il est destinรฉ ร  รชtre le **FastAPI des CLIs**. โŒจ๏ธ ๐Ÿš€ -## Prรฉrequis +## Prรฉrequis { #requirements } FastAPI repose sur les รฉpaules de gรฉants : * Starlette pour les parties web. * Pydantic pour les parties donnรฉes. -## Installation - -
- -```console -$ pip install fastapi +## Installation { #installation } ----> 100% -``` - -
- -Vous aurez รฉgalement besoin d'un serveur ASGI pour la production tel que Uvicorn ou Hypercorn. +Crรฉez et activez un environnement virtuel puis installez FastAPI :
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
-## Exemple +**Remarque** : Vous devez vous assurer de mettre ยซ fastapi[standard] ยป entre guillemets pour garantir que cela fonctionne dans tous les terminaux. -### Crรฉez +## Exemple { #example } -* Crรฉez un fichier `main.py` avec : +### Crรฉer { #create-it } -```Python -from typing import Union +Crรฉez un fichier `main.py` avec : +```Python from fastapi import FastAPI app = FastAPI() @@ -170,18 +172,16 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ```
-Ou utilisez async def ... +Ou utilisez async def... Si votre code utilise `async` / `await`, utilisez `async def` : -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -193,28 +193,41 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -**Note** +**Remarque** : -Si vous n'รชtes pas familier avec cette notion, consultez la section _"Vous รชtes pressรฉs ?"_ ร  propos de `async` et `await` dans la documentation. +Si vous ne savez pas, consultez la section ยซ Vous รชtes pressรฉs ? ยป ร  propos de `async` et `await` dans la documentation.
-### Lancez +### Lancer { #run-it } Lancez le serveur avec :
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ + โ”‚ โ”‚ + โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ + โ”‚ โ”‚ + โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ + โ”‚ โ”‚ + โ”‚ Running in development mode, for production use: โ”‚ + โ”‚ โ”‚ + โ”‚ fastapi run โ”‚ + โ”‚ โ”‚ + โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -222,34 +235,34 @@ INFO: Application startup complete.
-ร€ propos de la commande uvicorn main:app --reload ... +ร€ propos de la commande fastapi dev main.py... -La commande `uvicorn main:app` fait rรฉfรฉrence ร  : +La commande `fastapi dev` lit votre fichier `main.py`, dรฉtecte l'application **FastAPI** qu'il contient et lance un serveur avec Uvicorn. -* `main` : le fichier `main.py` (le "module" Python). -* `app` : l'objet crรฉรฉ ร  l'intรฉrieur de `main.py` avec la ligne `app = FastAPI()`. -* `--reload` : fait redรฉmarrer le serveur aprรจs des changements de code. ร€ n'utiliser que pour le dรฉveloppement. +Par dรฉfaut, `fastapi dev` dรฉmarre avec le rechargement automatique activรฉ pour le dรฉveloppement local. + +Vous pouvez en savoir plus dans la documentation de la CLI FastAPI.
-### Vรฉrifiez +### Vรฉrifier { #check-it } Ouvrez votre navigateur ร  l'adresse http://127.0.0.1:8000/items/5?q=somequery. -Vous obtenez alors cette rรฉponse JSON : +Vous verrez la rรฉponse JSON : ```JSON {"item_id": 5, "q": "somequery"} ``` -Vous venez de crรฉer une API qui : +Vous avez dรฉjร  crรฉรฉ une API qui : -* Reรงoit les requรชtes HTTP pour les _chemins_ `/` et `/items/{item_id}`. -* Les deux _chemins_ acceptent des opรฉrations `GET` (รฉgalement connu sous le nom de _mรฉthodes_ HTTP). -* Le _chemin_ `/items/{item_id}` a un _paramรจtre_ `item_id` qui doit รชtre un `int`. -* Le _chemin_ `/items/{item_id}` a un _paramรจtre de requรชte_ optionnel `q` de type `str`. +* Reรงoit des requรชtes HTTP sur les _chemins_ `/` et `/items/{item_id}`. +* Les deux _chemins_ acceptent des opรฉrations `GET` (รฉgalement connues sous le nom de _mรฉthodes_ HTTP). +* Le _chemin_ `/items/{item_id}` a un _paramรจtre de chemin_ `item_id` qui doit รชtre un `int`. +* Le _chemin_ `/items/{item_id}` a un _paramรจtre de requรชte_ optionnel `q` de type `str`. -### Documentation API interactive +### Documentation API interactive { #interactive-api-docs } Maintenant, rendez-vous sur http://127.0.0.1:8000/docs. @@ -257,23 +270,21 @@ Vous verrez la documentation interactive automatique de l'API (fournie par http://127.0.0.1:8000/redoc. -Vous verrez la documentation interactive automatique de l'API (fournie par ReDoc) : +Vous verrez la documentation alternative automatique (fournie par ReDoc) : ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## Exemple plus poussรฉ - -Maintenant, modifiez le fichier `main.py` pour recevoir le corps d'une requรชte `PUT`. +## Mettre ร  niveau l'exemple { #example-upgrade } -Dรฉclarez ce corps en utilisant les types Python standards, grรขce ร  Pydantic. +Modifiez maintenant le fichier `main.py` pour recevoir un corps depuis une requรชte `PUT`. -```Python hl_lines="4 9-12 25-27" -from typing import Union +Dรฉclarez le corps en utilisant les types Python standard, grรขce ร  Pydantic. +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -283,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -292,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -301,35 +312,35 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -Le serveur se recharge normalement automatiquement (car vous avez pensรฉ ร  `--reload` dans la commande `uvicorn` ci-dessus). +Le serveur `fastapi dev` devrait se recharger automatiquement. -### Plus loin avec la documentation API interactive +### Mettre ร  niveau la documentation API interactive { #interactive-api-docs-upgrade } Maintenant, rendez-vous sur http://127.0.0.1:8000/docs. -* La documentation interactive de l'API sera automatiquement mise ร  jour, y compris le nouveau corps de la requรชte : +* La documentation interactive de l'API sera automatiquement mise ร  jour, y compris le nouveau corps : ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* Cliquez sur le bouton "Try it out", il vous permet de renseigner les paramรจtres et d'interagir directement avec l'API : +* Cliquez sur le bouton ยซ Try it out ยป, il vous permet de renseigner les paramรจtres et d'interagir directement avec l'API : ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -* Cliquez ensuite sur le bouton "Execute", l'interface utilisateur communiquera avec votre API, enverra les paramรจtres, obtiendra les rรฉsultats et les affichera ร  l'รฉcran : +* Cliquez ensuite sur le bouton ยซ Execute ยป, l'interface utilisateur communiquera avec votre API, enverra les paramรจtres, obtiendra les rรฉsultats et les affichera ร  l'รฉcran : ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) -### Plus loin avec la documentation API alternative +### Mettre ร  niveau la documentation API alternative { #alternative-api-docs-upgrade } Et maintenant, rendez-vous sur http://127.0.0.1:8000/redoc. -* La documentation alternative reflรฉtera รฉgalement le nouveau paramรจtre de requรชte et le nouveau corps : +* La documentation alternative reflรจtera รฉgalement le nouveau paramรจtre de requรชte et le nouveau corps : ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### En rรฉsumรฉ +### En rรฉsumรฉ { #recap } -En rรฉsumรฉ, vous dรฉclarez **une fois** les types de paramรจtres, le corps de la requรชte, etc. en tant que paramรจtres de fonction. +En rรฉsumรฉ, vous dรฉclarez **une fois** les types de paramรจtres, le corps, etc. en tant que paramรจtres de fonction. Vous faites cela avec les types Python standard modernes. @@ -337,7 +348,7 @@ Vous n'avez pas ร  apprendre une nouvelle syntaxe, les mรฉthodes ou les classes Juste du **Python** standard. -Par exemple, pour un `int`: +Par exemple, pour un `int` : ```Python item_id: int @@ -351,54 +362,54 @@ item: Item ... et avec cette dรฉclaration unique, vous obtenez : -* Une assistance dans votre IDE, notamment : - * la complรฉtion. +* Une assistance dans l'รฉditeur, notamment : + * l'autocomplรฉtion. * la vรฉrification des types. * La validation des donnรฉes : * des erreurs automatiques et claires lorsque les donnรฉes ne sont pas valides. - * une validation mรชme pour les objets JSON profondรฉment imbriquรฉs. -* Une conversion des donnรฉes d'entrรฉe : venant du rรฉseau et allant vers les donnรฉes et types de Python, permettant de lire : - * le JSON. - * les paramรจtres du chemin. - * les paramรจtres de la requรชte. - * les cookies. - * les en-tรชtes. - * les formulaires. - * les fichiers. -* La conversion des donnรฉes de sortie : conversion des donnรฉes et types Python en donnรฉes rรฉseau (au format JSON), permettant de convertir : - * les types Python (`str`, `int`, `float`, `bool`, `list`, etc). - * les objets `datetime`. - * les objets `UUID`. - * les modรจles de base de donnรฉes. - * ... et beaucoup plus. -* La documentation API interactive automatique, avec 2 interfaces utilisateur au choix : + * une validation mรชme pour les objets JSON profondรฉment imbriquรฉs. +* Conversion des donnรฉes d'entrรฉe : venant du rรฉseau vers les donnรฉes et types Python. Lecture depuis : + * JSON. + * Paramรจtres de chemin. + * Paramรจtres de requรชte. + * Cookies. + * En-tรชtes. + * Formulaires. + * Fichiers. +* Conversion des donnรฉes de sortie : conversion des donnรฉes et types Python en donnรฉes rรฉseau (au format JSON) : + * Conversion des types Python (`str`, `int`, `float`, `bool`, `list`, etc). + * Objets `datetime`. + * Objets `UUID`. + * Modรจles de base de donnรฉes. + * ... et bien plus. +* Documentation API interactive automatique, avec 2 interfaces utilisateur au choix : * Swagger UI. * ReDoc. --- -Pour revenir ร  l'exemple de code prรฉcรฉdent, **FastAPI** permet de : +Pour revenir ร  l'exemple de code prรฉcรฉdent, **FastAPI** va : -* Valider que `item_id` existe dans le chemin des requรชtes `GET` et `PUT`. +* Valider la prรฉsence d'un `item_id` dans le chemin pour les requรชtes `GET` et `PUT`. * Valider que `item_id` est de type `int` pour les requรชtes `GET` et `PUT`. - * Si ce n'est pas le cas, le client voit une erreur utile et claire. -* Vรฉrifier qu'il existe un paramรจtre de requรชte facultatif nommรฉ `q` (comme dans `http://127.0.0.1:8000/items/foo?q=somequery`) pour les requรชtes `GET`. - * Puisque le paramรจtre `q` est dรฉclarรฉ avec `= None`, il est facultatif. - * Sans le `None`, il serait nรฉcessaire (comme l'est le corps de la requรชte dans le cas du `PUT`). -* Pour les requรชtes `PUT` vers `/items/{item_id}`, de lire le corps en JSON : - * Vรฉrifier qu'il a un attribut obligatoire `name` qui devrait รชtre un `str`. - * Vรฉrifier qu'il a un attribut obligatoire `prix` qui doit รชtre un `float`. - * Vรฉrifier qu'il a un attribut facultatif `is_offer`, qui devrait รชtre un `bool`, s'il est prรฉsent. - * Tout cela fonctionnerait รฉgalement pour les objets JSON profondรฉment imbriquรฉs. -* Convertir de et vers JSON automatiquement. -* Documenter tout avec OpenAPI, qui peut รชtre utilisรฉ par : - * Les systรจmes de documentation interactifs. - * Les systรจmes de gรฉnรฉration automatique de code client, pour de nombreuses langues. + * Si ce n'est pas le cas, le client verra une erreur utile et claire. +* Vรฉrifier s'il existe un paramรจtre de requรชte optionnel nommรฉ `q` (comme dans `http://127.0.0.1:8000/items/foo?q=somequery`) pour les requรชtes `GET`. + * Comme le paramรจtre `q` est dรฉclarรฉ avec `= None`, il est optionnel. + * Sans le `None`, il serait requis (comme l'est le corps dans le cas de `PUT`). +* Pour les requรชtes `PUT` vers `/items/{item_id}`, lire le corps au format JSON : + * Vรฉrifier qu'il a un attribut obligatoire `name` qui doit รชtre un `str`. + * Vรฉrifier qu'il a un attribut obligatoire `price` qui doit รชtre un `float`. + * Vรฉrifier qu'il a un attribut optionnel `is_offer`, qui doit รชtre un `bool`, s'il est prรฉsent. + * Tout cela fonctionne รฉgalement pour les objets JSON profondรฉment imbriquรฉs. +* Convertir automatiquement depuis et vers JSON. +* Tout documenter avec OpenAPI, qui peut รชtre utilisรฉ par : + * des systรจmes de documentation interactive. + * des systรจmes de gรฉnรฉration automatique de clients, pour de nombreux langages. * Fournir directement 2 interfaces web de documentation interactive. --- -Nous n'avons fait qu'effleurer la surface, mais vous avez dรฉjร  une idรฉe de la faรงon dont tout cela fonctionne. +Nous n'avons fait qu'effleurer la surface, mais vous avez dรฉjร  une idรฉe de la faรงon dont tout fonctionne. Essayez de changer la ligne contenant : @@ -412,61 +423,137 @@ Essayez de changer la ligne contenant : ... "item_name": item.name ... ``` -... vers : +... ร  : ```Python ... "item_price": item.price ... ``` -... et voyez comment votre รฉditeur complรฉtera automatiquement les attributs et connaรฎtra leurs types : +... et voyez comment votre รฉditeur complรจte automatiquement les attributs et connaรฎt leurs types : -![compatibilitรฉ IDE](https://fastapi.tiangolo.com/img/vscode-completion.png) +![compatibilitรฉ รฉditeur](https://fastapi.tiangolo.com/img/vscode-completion.png) Pour un exemple plus complet comprenant plus de fonctionnalitรฉs, voir le Tutoriel - Guide utilisateur. -**Spoiler alert** : le tutoriel - guide utilisateur inclut : +**Alerte spoiler** : le tutoriel - guide utilisateur inclut : -* Dรฉclaration de **paramรจtres** provenant d'autres endroits diffรฉrents comme : **en-tรชtes.**, **cookies**, **champs de formulaire** et **fichiers**. -* L'utilisation de **contraintes de validation** comme `maximum_length` ou `regex`. -* Un **systรจme d'injection de dรฉpendance ** trรจs puissant et facile ร  utiliser . -* Sรฉcuritรฉ et authentification, y compris la prise en charge de **OAuth2** avec les **jetons JWT** et l'authentification **HTTP Basic**. -* Des techniques plus avancรฉes (mais tout aussi faciles) pour dรฉclarer les **modรจles JSON profondรฉment imbriquรฉs** (grรขce ร  Pydantic). -* Intรฉgration de **GraphQL** avec Strawberry et d'autres bibliothรจques. -* D'obtenir de nombreuses fonctionnalitรฉs supplรฉmentaires (grรขce ร  Starlette) comme : +* Dรฉclaration de **paramรจtres** provenant d'autres emplacements comme : **en-tรชtes**, **cookies**, **champs de formulaire** et **fichiers**. +* Comment dรฉfinir des **contraintes de validation** comme `maximum_length` ou `regex`. +* Un systรจme **d'injection de dรฉpendances** trรจs puissant et facile ร  utiliser. +* Sรฉcuritรฉ et authentification, y compris la prise en charge de **OAuth2** avec des **JWT tokens** et l'authentification **HTTP Basic**. +* Des techniques plus avancรฉes (mais tout aussi faciles) pour dรฉclarer des **modรจles JSON profondรฉment imbriquรฉs** (grรขce ร  Pydantic). +* Intรฉgration **GraphQL** avec Strawberry et d'autres bibliothรจques. +* De nombreuses fonctionnalitรฉs supplรฉmentaires (grรขce ร  Starlette) comme : * **WebSockets** - * de tester le code trรจs facilement avec `requests` et `pytest` - * **CORS** + * des tests extrรชmement faciles basรฉs sur HTTPX et `pytest` + * **CORS** * **Cookie Sessions** * ... et plus encore. -## Performance +### Dรฉployer votre application (optionnel) { #deploy-your-app-optional } -Les benchmarks TechEmpower indรฉpendants montrent que les applications **FastAPI** s'exรฉcutant sous Uvicorn sont parmi les frameworks existants en Python les plus rapides , juste derriรจre Starlette et Uvicorn (utilisรฉs en interne par FastAPI). (*) +Vous pouvez, si vous le souhaitez, dรฉployer votre application FastAPI sur FastAPI Cloud, allez vous inscrire sur la liste d'attente si ce n'est pas dรฉjร  fait. ๐Ÿš€ + +Si vous avez dรฉjร  un compte **FastAPI Cloud** (nous vous avons invitรฉ depuis la liste d'attente ๐Ÿ˜‰), vous pouvez dรฉployer votre application avec une seule commande. + +Avant de dรฉployer, assurez-vous d'รชtre connectรฉ : + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +Puis dรฉployez votre application : + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +C'est tout ! Vous pouvez maintenant accรฉder ร  votre application ร  cette URL. โœจ + +#### ร€ propos de FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** est construit par le mรชme auteur et la mรชme รฉquipe derriรจre **FastAPI**. + +Il simplifie le processus de **construction**, de **dรฉploiement** et **d'accรจs** ร  une API avec un effort minimal. + +Il apporte la mรชme **expรฉrience dรฉveloppeur** de la crรฉation d'applications avec FastAPI au **dรฉploiement** dans le cloud. ๐ŸŽ‰ + +FastAPI Cloud est le principal sponsor et financeur des projets open source *FastAPI and friends*. โœจ + +#### Dรฉployer sur d'autres fournisseurs cloud { #deploy-to-other-cloud-providers } + +FastAPI est open source et basรฉ sur des standards. Vous pouvez dรฉployer des applications FastAPI sur n'importe quel fournisseur cloud de votre choix. + +Suivez les guides de votre fournisseur cloud pour y dรฉployer des applications FastAPI. ๐Ÿค“ + +## Performance { #performance } + +Les benchmarks TechEmpower indรฉpendants montrent que les applications **FastAPI** s'exรฉcutant sous Uvicorn sont parmi les frameworks Python les plus rapides, juste derriรจre Starlette et Uvicorn eux-mรชmes (utilisรฉs en interne par FastAPI). (*) Pour en savoir plus, consultez la section Benchmarks. -## Dรฉpendances facultatives +## Dรฉpendances { #dependencies } + +FastAPI dรฉpend de Pydantic et Starlette. + +### Dรฉpendances `standard` { #standard-dependencies } -Utilisรฉes par Pydantic: +Lorsque vous installez FastAPI avec `pip install "fastapi[standard]"`, il inclut le groupe `standard` de dรฉpendances optionnelles : -* email-validator - pour la validation des adresses email. +Utilisรฉes par Pydantic : + +* email-validator - pour la validation des adresses e-mail. Utilisรฉes par Starlette : -* requests - Obligatoire si vous souhaitez utiliser `TestClient`. +* httpx - Obligatoire si vous souhaitez utiliser le `TestClient`. * jinja2 - Obligatoire si vous souhaitez utiliser la configuration de template par dรฉfaut. -* python-multipart - Obligatoire si vous souhaitez supporter le "dรฉcodage" de formulaire avec `request.form()`. -* itsdangerous - Obligatoire pour la prise en charge de `SessionMiddleware`. -* pyyaml - Obligatoire pour le support `SchemaGenerator` de Starlette (vous n'en avez probablement pas besoin avec FastAPI). +* python-multipart - Obligatoire si vous souhaitez prendre en charge lโ€™ยซ parsing ยป de formulaires avec `request.form()`. -Utilisรฉes par FastAPI / Starlette : +Utilisรฉes par FastAPI : -* uvicorn - Pour le serveur qui charge et sert votre application. -* orjson - Obligatoire si vous voulez utiliser `ORJSONResponse`. -* ujson - Obligatoire si vous souhaitez utiliser `UJSONResponse`. +* uvicorn - pour le serveur qui charge et sert votre application. Cela inclut `uvicorn[standard]`, qui comprend certaines dรฉpendances (par ex. `uvloop`) nรฉcessaires pour une haute performance. +* `fastapi-cli[standard]` - pour fournir la commande `fastapi`. + * Cela inclut `fastapi-cloud-cli`, qui vous permet de dรฉployer votre application FastAPI sur FastAPI Cloud. + +### Sans les dรฉpendances `standard` { #without-standard-dependencies } + +Si vous ne souhaitez pas inclure les dรฉpendances optionnelles `standard`, vous pouvez installer avec `pip install fastapi` au lieu de `pip install "fastapi[standard]"`. -Vous pouvez tout installer avec `pip install fastapi[all]`. +### Sans `fastapi-cloud-cli` { #without-fastapi-cloud-cli } + +Si vous souhaitez installer FastAPI avec les dรฉpendances standard mais sans `fastapi-cloud-cli`, vous pouvez installer avec `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + +### Dรฉpendances optionnelles supplรฉmentaires { #additional-optional-dependencies } + +Il existe des dรฉpendances supplรฉmentaires que vous pourriez vouloir installer. + +Dรฉpendances optionnelles supplรฉmentaires pour Pydantic : + +* pydantic-settings - pour la gestion des paramรจtres. +* pydantic-extra-types - pour des types supplรฉmentaires ร  utiliser avec Pydantic. + +Dรฉpendances optionnelles supplรฉmentaires pour FastAPI : + +* orjson - Obligatoire si vous souhaitez utiliser `ORJSONResponse`. +* ujson - Obligatoire si vous souhaitez utiliser `UJSONResponse`. -## Licence +## Licence { #license } Ce projet est soumis aux termes de la licence MIT. diff --git a/docs/fr/docs/learn/index.md b/docs/fr/docs/learn/index.md index 46fc095dce..5526877038 100644 --- a/docs/fr/docs/learn/index.md +++ b/docs/fr/docs/learn/index.md @@ -1,5 +1,5 @@ -# Apprendre +# Apprendre { #learn } Voici les sections introductives et les tutoriels pour apprendre **FastAPI**. -Vous pouvez considรฉrer ceci comme un **manuel**, un **cours**, la **mรฉthode officielle** et recommandรฉe pour apprรฉhender FastAPI. ๐Ÿ˜Ž +Vous pouvez considรฉrer ceci comme un **livre**, un **cours**, la **mรฉthode officielle** et recommandรฉe pour apprendre FastAPI. ๐Ÿ˜Ž diff --git a/docs/fr/docs/project-generation.md b/docs/fr/docs/project-generation.md index 4c04dc167d..f062ffecf5 100644 --- a/docs/fr/docs/project-generation.md +++ b/docs/fr/docs/project-generation.md @@ -1,84 +1,28 @@ -# Gรฉnรฉration de projets - Modรจle - -Vous pouvez utiliser un gรฉnรฉrateur de projet pour commencer, qui rรฉalisera pour vous la mise en place de bases cรดtรฉ architecture globale, sรฉcuritรฉ, base de donnรฉes et premiรจres routes d'API. - -Un gรฉnรฉrateur de projet fera toujours une mise en place trรจs subjective que vous devriez modifier et adapter suivant vos besoins, mais cela reste un bon point de dรฉpart pour vos projets. - -## Full Stack FastAPI PostgreSQL - -GitHub : https://github.com/tiangolo/full-stack-fastapi-postgresql - -### Full Stack FastAPI PostgreSQL - Fonctionnalitรฉs - -* Intรฉgration **Docker** complรจte (basรฉe sur Docker). -* Dรฉploiement Docker en mode Swarm -* Intรฉgration **Docker Compose** et optimisation pour dรฉveloppement local. -* Serveur web Python **prรชt au dรฉploiement** utilisant Uvicorn et Gunicorn. -* Backend Python **FastAPI** : - * **Rapide** : Trรจs hautes performances, comparables ร  **NodeJS** ou **Go** (grรขce ร  Starlette et Pydantic). - * **Intuitif** : Excellent support des รฉditeurs. Complรฉtion partout. Moins de temps passรฉ ร  dรฉboguer. - * **Facile** : Fait pour รชtre facile ร  utiliser et apprendre. Moins de temps passรฉ ร  lire de la documentation. - * **Concis** : Minimise la duplication de code. Plusieurs fonctionnalitรฉs ร  chaque dรฉclaration de paramรจtre. - * **Robuste** : Obtenez du code prรชt pour รชtre utilisรฉ en production. Avec de la documentation automatique interactive. - * **Basรฉ sur des normes** : Basรฉ sur (et totalement compatible avec) les normes ouvertes pour les APIs : OpenAPI et JSON Schema. - * **Et bien d'autres fonctionnalitรฉs** comme la validation automatique, la sรฉrialisation, l'authentification avec OAuth2 JWT tokens, etc. -* Hashage de **mots de passe sรฉcurisรฉ** par dรฉfaut. -* Authentification par **jetons JWT**. -* Modรจles **SQLAlchemy** (indรฉpendants des extensions Flask, afin qu'ils puissent รชtre utilisรฉs directement avec des *workers* Celery). -* Modรจle de dรฉmarrages basiques pour les utilisateurs (ร  modifier et supprimer au besoin). -* Migrations **Alembic**. -* **CORS** (partage des ressources entre origines multiples, ou *Cross Origin Resource Sharing*). -* *Worker* **Celery** pouvant importer et utiliser les modรจles et le code du reste du backend. -* Tests du backend REST basรฉs sur **Pytest**, intรฉgrรฉs dans Docker, pour que vous puissiez tester toutes les interactions de l'API indรฉpendamment de la base de donnรฉes. ร‰tant exรฉcutรฉs dans Docker, les tests peuvent utiliser un nouvel entrepรดt de donnรฉes crรฉรฉ de zรฉro ร  chaque fois (vous pouvez donc utiliser ElasticSearch, MongoDB, CouchDB, etc. et juste tester que l'API fonctionne). -* Intรฉgration Python facile avec **Jupyter Kernels** pour le dรฉveloppement ร  distance ou intra-Docker avec des extensions comme Atom Hydrogen ou Visual Studio Code Jupyter. -* Frontend **Vue** : - * Gรฉnรฉrรฉ avec Vue CLI. - * Gestion de l'**Authentification JWT**. - * Page de connexion. - * Aprรจs la connexion, page de tableau de bord principal. - * Tableau de bord principal avec crรฉation et modification d'utilisateurs. - * Modification de ses propres caractรฉristiques utilisateur. - * **Vuex**. - * **Vue-router**. - * **Vuetify** pour de magnifiques composants *material design*. - * **TypeScript**. - * Serveur Docker basรฉ sur **Nginx** (configurรฉ pour รชtre facilement manipulรฉ avec Vue-router). - * Utilisation de *Docker multi-stage building*, pour ne pas avoir besoin de sauvegarder ou *commit* du code compilรฉ. - * Tests frontend exรฉcutรฉs ร  la compilation (pouvant รชtre dรฉsactivรฉs). - * Fait aussi modulable que possible, pour pouvoir fonctionner comme tel, tout en pouvant รชtre utilisรฉ qu'en partie grรขce ร  Vue CLI. -* **PGAdmin** pour les bases de donnรฉes PostgreSQL, facilement modifiable pour utiliser PHPMYAdmin ou MySQL. -* **Flower** pour la surveillance de tรขches Celery. -* ร‰quilibrage de charge entre le frontend et le backend avec **Traefik**, afin de pouvoir avoir les deux sur le mรชme domaine, sรฉparรฉs par chemins, mais servis par diffรฉrents conteneurs. -* Intรฉgration Traefik, comprenant la gรฉnรฉration automatique de certificat **HTTPS** Let's Encrypt. -* GitLab **CI** (intรฉgration continue), comprenant des tests pour le frontend et le backend. - -## Full Stack FastAPI Couchbase - -GitHub : https://github.com/tiangolo/full-stack-fastapi-couchbase - -โš ๏ธ **ATTENTION** โš ๏ธ - -Si vous dรฉmarrez un nouveau projet de zรฉro, allez voir les alternatives au dรฉbut de cette page. - -Par exemple, le gรฉnรฉrateur de projet Full Stack FastAPI PostgreSQL peut รชtre une meilleure alternative, รฉtant activement maintenu et utilisรฉ et comprenant toutes les nouvelles fonctionnalitรฉs et amรฉliorations. - -Vous รชtes toujours libre d'utiliser le gรฉnรฉrateur basรฉ sur Couchbase si vous le voulez, cela devrait probablement fonctionner correctement, et si vous avez dรฉjร  un projet gรฉnรฉrรฉ en utilisant ce dernier, cela devrait fonctionner aussi (et vous l'avez dรฉjร  probablement mis ร  jour suivant vos besoins). - -Vous pouvez en apprendre plus dans la documentation du dรฉpรดt GithHub. - -## Full Stack FastAPI MongoDB - -...viendra surement plus tard, suivant le temps que j'ai. ๐Ÿ˜… ๐ŸŽ‰ - -## Modรจles d'apprentissage automatique avec spaCy et FastAPI - -GitHub : https://github.com/microsoft/cookiecutter-spacy-fastapi - -## Modรจles d'apprentissage automatique avec spaCy et FastAPI - Fonctionnalitรฉs - -* Intรฉgration d'un modรจle NER **spaCy**. -* Formatage de requรชte pour **Azure Cognitive Search**. -* Serveur Python web **prรชt ร  utiliser en production** utilisant Uvicorn et Gunicorn. -* Dรฉploiement CI/CD Kubernetes pour **Azure DevOps** (AKS). -* **Multilangues**. Choisissez facilement l'une des langues intรฉgrรฉes ร  spaCy durant la mise en place du projet. -* **Facilement gรฉnรฉralisable** ร  d'autres bibliothรจques similaires (Pytorch, Tensorflow), et non juste spaCy. +# Modรจle Full Stack FastAPI { #full-stack-fastapi-template } + +Les modรจles, bien qu'ils soient gรฉnรฉralement livrรฉs avec une configuration spรฉcifique, sont conรงus pour รชtre flexibles et personnalisables. Cela vous permet de les modifier et de les adapter aux exigences de votre projet, ce qui en fait un excellent point de dรฉpart. ๐Ÿ + +Vous pouvez utiliser ce modรจle pour dรฉmarrer, car il inclut une grande partie de la configuration initiale, la sรฉcuritรฉ, la base de donnรฉes et quelques endpoints d'API dรฉjร  prรชts pour vous. + +Dรฉpรดt GitHub : Modรจle Full Stack FastAPI + +## Modรจle Full Stack FastAPI - Pile technologique et fonctionnalitรฉs { #full-stack-fastapi-template-technology-stack-and-features } + +- โšก [**FastAPI**](https://fastapi.tiangolo.com/fr) pour l'API backend Python. + - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) pour les interactions avec la base de donnรฉes SQL en Python (ORM). + - ๐Ÿ” [Pydantic](https://docs.pydantic.dev), utilisรฉ par FastAPI, pour la validation des donnรฉes et la gestion des paramรจtres. + - ๐Ÿ’พ [PostgreSQL](https://www.postgresql.org) comme base de donnรฉes SQL. +- ๐Ÿš€ [React](https://react.dev) pour le frontend. + - ๐Ÿ’ƒ Utilisation de TypeScript, des hooks, de Vite et d'autres รฉlรฉments d'un stack frontend moderne. + - ๐ŸŽจ [Tailwind CSS](https://tailwindcss.com) et [shadcn/ui](https://ui.shadcn.com) pour les composants frontend. + - ๐Ÿค– Un client frontend gรฉnรฉrรฉ automatiquement. + - ๐Ÿงช [Playwright](https://playwright.dev) pour les tests de bout en bout. + - ๐Ÿฆ‡ Prise en charge du mode sombre. +- ๐Ÿ‹ [Docker Compose](https://www.docker.com) pour le dรฉveloppement et la production. +- ๐Ÿ”’ Hachage sรฉcurisรฉ des mots de passe par dรฉfaut. +- ๐Ÿ”‘ Authentification JWT (JSON Web Token). +- ๐Ÿ“ซ Rรฉcupรฉration de mot de passe par e-mail. +- โœ… Tests avec [Pytest](https://pytest.org). +- ๐Ÿ“ž [Traefik](https://traefik.io) comme proxy inverse / rรฉpartiteur de charge. +- ๐Ÿšข Instructions de dรฉploiement avec Docker Compose, y compris la configuration d'un proxy Traefik frontal pour gรฉrer les certificats HTTPS automatiques. +- ๐Ÿญ CI (intรฉgration continue) et CD (dรฉploiement continu) basรฉs sur GitHub Actions. diff --git a/docs/fr/docs/python-types.md b/docs/fr/docs/python-types.md index 99ca908277..f393b0f5c1 100644 --- a/docs/fr/docs/python-types.md +++ b/docs/fr/docs/python-types.md @@ -1,70 +1,68 @@ -# Introduction aux Types Python +# Introduction aux types Python { #python-types-intro } -Python supporte des annotations de type (ou *type hints*) optionnelles. +Python prend en charge des ยซ type hints ยป (aussi appelรฉes ยซ annotations de type ยป) facultatives. -Ces annotations de type constituent une syntaxe spรฉciale qui permet de dรฉclarer le type d'une variable. +Ces ยซ type hints ยป ou annotations sont une syntaxe spรฉciale qui permet de dรฉclarer le type d'une variable. -En dรฉclarant les types de vos variables, cela permet aux diffรฉrents outils comme les รฉditeurs de texte d'offrir un meilleur support. +En dรฉclarant les types de vos variables, les รฉditeurs et outils peuvent vous offrir un meilleur support. -Ce chapitre n'est qu'un **tutoriel rapide / rappel** sur les annotations de type Python. -Seulement le minimum nรฉcessaire pour les utiliser avec **FastAPI** sera couvert... ce qui est en rรฉalitรฉ trรจs peu. +Ceci est un **tutoriel rapide / rappel** ร  propos des annotations de type Python. Il couvre uniquement le minimum nรฉcessaire pour les utiliser avec **FastAPI** ... ce qui est en rรฉalitรฉ trรจs peu. -**FastAPI** est totalement basรฉ sur ces annotations de type, qui lui donnent de nombreux avantages. +**FastAPI** est totalement basรฉ sur ces annotations de type, elles lui donnent de nombreux avantages et bรฉnรฉfices. -Mais mรชme si vous n'utilisez pas ou n'utiliserez jamais **FastAPI**, vous pourriez bรฉnรฉficier d'apprendre quelques choses sur ces derniรจres. +Mais mรชme si vous n'utilisez jamais **FastAPI**, vous auriez intรฉrรชt ร  en apprendre un peu ร  leur sujet. -/// note +/// note | Remarque -Si vous รชtes un expert Python, et que vous savez dรฉjร  **tout** sur les annotations de type, passez au chapitre suivant. +Si vous รชtes un expert Python, et que vous savez dรฉjร  tout sur les annotations de type, passez au chapitre suivant. /// -## Motivations +## Motivation { #motivation } -Prenons un exemple simple : +Commenรงons par un exemple simple : -{*../../docs_src/python_types/tutorial001.py*} +{* ../../docs_src/python_types/tutorial001_py39.py *} -Exรฉcuter ce programe affiche : +Exรฉcuter ce programme affiche : ``` John Doe ``` -La fonction : +La fonction fait ce qui suit : * Prend un `first_name` et un `last_name`. -* Convertit la premiรจre lettre de chaque paramรจtre en majuscules grรขce ร  `title()`. -* Concatรจne les rรฉsultats avec un espace entre les deux. +* Convertit la premiรจre lettre de chacun en majuscule avec `title()`. +* Concatรจne ces deux valeurs avec un espace au milieu. -{*../../docs_src/python_types/tutorial001.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} -### Limitations +### Modifier le code { #edit-it } C'est un programme trรจs simple. Mais maintenant imaginez que vous l'รฉcriviez de zรฉro. -ร€ un certain point vous auriez commencรฉ la dรฉfinition de la fonction, vous aviez les paramรจtres prรชts. +ร€ un certain moment, vous auriez commencรฉ la dรฉfinition de la fonction, vous aviez les paramรจtres prรชts ... -Mais vous aviez besoin de "cette mรฉthode qui convertit la premiรจre lettre en majuscule". +Mais ensuite vous devez appeler ยซ cette mรฉthode qui convertit la premiรจre lettre en majuscule ยป. -ร‰tait-ce `upper` ? `uppercase` ? `first_uppercase` ? `capitalize` ? +ร‰tait-ce `upper` ? ร‰tait-ce `uppercase` ? `first_uppercase` ? `capitalize` ? -Vous essayez donc d'utiliser le vieil ami du programmeur, l'auto-complรฉtion de l'รฉditeur. +Vous essayez alors avec l'ami de toujours des programmeurs, l'autocomplรฉtion de l'รฉditeur. -Vous รฉcrivez le premier paramรจtre, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour dรฉclencher l'auto-complรฉtion. +Vous tapez le premier paramรจtre de la fonction, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour dรฉclencher l'autocomplรฉtion. -Mais malheureusement, rien d'utile n'en rรฉsulte : +Mais, malheureusement, vous n'obtenez rien d'utile : -### Ajouter des types +### Ajouter des types { #add-types } Modifions une seule ligne de la version prรฉcรฉdente. -Nous allons changer seulement cet extrait, les paramรจtres de la fonction, de : - +Nous allons changer exactement ce fragment, les paramรจtres de la fonction, de : ```Python first_name, last_name @@ -78,222 +76,389 @@ Nous allons changer seulement cet extrait, les paramรจtres de la fonction, de : C'est tout. -Ce sont des annotations de types : +Ce sont les ยซ annotations de type ยป : -{*../../docs_src/python_types/tutorial002.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} -ร€ ne pas confondre avec la dรฉclaration de valeurs par dรฉfaut comme ici : +Ce n'est pas la mรชme chose que de dรฉclarer des valeurs par dรฉfaut, ce qui serait : ```Python first_name="john", last_name="doe" ``` -C'est une chose diffรฉrente. +C'est diffรฉrent. -On utilise un deux-points (`:`), et pas un รฉgal (`=`). +Nous utilisons des deux-points (`:`), pas des signes รฉgal (`=`). -Et ajouter des annotations de types ne crรฉe normalement pas de diffรฉrence avec le comportement qui aurait eu lieu si elles n'รฉtaient pas lร . +Et ajouter des annotations de type ne change normalement pas ce qui se passe par rapport ร  ce qui se passerait sans elles. -Maintenant, imaginez que vous รชtes en train de crรฉer cette fonction, mais avec des annotations de type cette fois. +Mais maintenant, imaginez que vous รชtes ร  nouveau en train de crรฉer cette fonction, mais avec des annotations de type. -Au mรชme moment que durant l'exemple prรฉcรฉdent, vous essayez de dรฉclencher l'auto-complรฉtion et vous voyez : +Au mรชme moment, vous essayez de dรฉclencher l'autocomplรฉtion avec `Ctrl+Espace` et vous voyez : -Vous pouvez donc dรฉrouler les options jusqu'ร  trouver la mรฉthode ร  laquelle vous pensiez. +Avec cela, vous pouvez faire dรฉfiler en voyant les options, jusqu'ร  trouver celle qui ยซ vous dit quelque chose ยป : -## Plus de motivations +## Plus de motivation { #more-motivation } -Cette fonction possรจde dรฉjร  des annotations de type : +Regardez cette fonction, elle a dรฉjร  des annotations de type : -{*../../docs_src/python_types/tutorial003.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} -Comme l'รฉditeur connaรฎt le type des variables, vous n'avez pas seulement l'auto-complรฉtion, mais aussi de la dรฉtection d'erreurs : +Comme l'รฉditeur connaรฎt les types des variables, vous n'obtenez pas seulement l'autocomplรฉtion, vous obtenez aussi des vรฉrifications d'erreurs : -Maintenant que vous avez connaissance du problรจme, convertissez `age` en chaรฎne de caractรจres grรขce ร  `str(age)` : +Vous savez maintenant qu'il faut corriger, convertir `age` en chaรฎne avec `str(age)` : -{*../../docs_src/python_types/tutorial004.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} -## Dรฉclarer des types +## Dรฉclarer des types { #declaring-types } -Vous venez de voir lร  oรน les types sont gรฉnรฉralement dรฉclarรฉs : dans les paramรจtres de fonctions. +Vous venez de voir l'endroit principal pour dรฉclarer des annotations de type : dans les paramรจtres des fonctions. -C'est aussi ici que vous les utiliseriez avec **FastAPI**. +C'est aussi l'endroit principal oรน vous les utiliserez avec **FastAPI**. -### Types simples +### Types simples { #simple-types } -Vous pouvez dรฉclarer tous les types de Python, pas seulement `str`. +Vous pouvez dรฉclarer tous les types standards de Python, pas seulement `str`. -Comme par exemple : +Vous pouvez utiliser, par exemple : * `int` * `float` * `bool` * `bytes` -{*../../docs_src/python_types/tutorial005.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} -### Types gรฉnรฉriques avec des paramรจtres de types +### Types gรฉnรฉriques avec paramรจtres de type { #generic-types-with-type-parameters } -Il existe certaines structures de donnรฉes qui contiennent d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent elles aussi avoir leurs propres types. +Il existe certaines structures de donnรฉes qui peuvent contenir d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent aussi avoir leur propre type. -Pour dรฉclarer ces types et les types internes, on utilise le module standard de Python `typing`. +Ces types qui ont des types internes sont appelรฉs types ยซ gรฉnรฉriques ยป. Et il est possible de les dรฉclarer, mรชme avec leurs types internes. -Il existe spรฉcialement pour supporter ces annotations de types. +Pour dรฉclarer ces types et les types internes, vous pouvez utiliser le module standard Python `typing`. Il existe spรฉcifiquement pour prendre en charge ces annotations de type. -#### `List` +#### Versions plus rรฉcentes de Python { #newer-versions-of-python } -Par exemple, dรฉfinissons une variable comme `list` de `str`. +La syntaxe utilisant `typing` est compatible avec toutes les versions, de Python 3.6 aux plus rรฉcentes, y compris Python 3.9, Python 3.10, etc. -Importez `List` (avec un `L` majuscule) depuis `typing`. +Au fur et ร  mesure que Python รฉvolue, les versions plus rรฉcentes apportent un meilleur support pour ces annotations de type et dans de nombreux cas vous n'aurez mรชme pas besoin d'importer et d'utiliser le module `typing` pour les dรฉclarer. -{*../../docs_src/python_types/tutorial006.py hl[1] *} +Si vous pouvez choisir une version plus rรฉcente de Python pour votre projet, vous pourrez profiter de cette simplicitรฉ supplรฉmentaire. -Dรฉclarez la variable, en utilisant la syntaxe des deux-points (`:`). +Dans toute la documentation, il y a des exemples compatibles avec chaque version de Python (lorsqu'il y a une diffรฉrence). -Et comme type, mettez `List`. +Par exemple ยซ Python 3.6+ ยป signifie que c'est compatible avec Python 3.6 ou supรฉrieur (y compris 3.7, 3.8, 3.9, 3.10, etc.). Et ยซ Python 3.9+ ยป signifie que c'est compatible avec Python 3.9 ou supรฉrieur (y compris 3.10, etc). -Les listes รฉtant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) : +Si vous pouvez utiliser les derniรจres versions de Python, utilisez les exemples pour la derniรจre version, ils auront la meilleure et la plus simple syntaxe, par exemple, ยซ Python 3.10+ ยป. -{*../../docs_src/python_types/tutorial006.py hl[4] *} +#### Liste { #list } -/// tip | Astuce +Par exemple, dรฉfinissons une variable comme une `list` de `str`. + +Dรฉclarez la variable, en utilisant la mรชme syntaxe avec deux-points (`:`). + +Comme type, mettez `list`. + +Comme la liste est un type qui contient des types internes, mettez-les entre crochets : + +{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} -Ces types internes entre crochets sont appelรฉs des "paramรจtres de type". +/// info + +Ces types internes entre crochets sont appelรฉs ยซ paramรจtres de type ยป. -Ici, `str` est un paramรจtre de type passรฉ ร  `List`. +Dans ce cas, `str` est le paramรจtre de type passรฉ ร  `list`. /// -Ce qui signifie : "la variable `items` est une `list`, et chacun de ses รฉlรฉments a pour type `str`. +Cela signifie : ยซ la variable `items` est une `list`, et chacun des รฉlรฉments de cette liste est un `str` ยป. -En faisant cela, votre รฉditeur pourra vous aider, mรชme pendant que vous traitez des รฉlรฉments de la liste. +En faisant cela, votre รฉditeur peut vous fournir de l'aide mรชme pendant le traitement des รฉlรฉments de la liste : Sans types, c'est presque impossible ร  rรฉaliser. -Vous remarquerez que la variable `item` n'est qu'un des รฉlรฉments de la list `items`. +Remarquez que la variable `item` est l'un des รฉlรฉments de la liste `items`. -Et pourtant, l'รฉditeur sait qu'elle est de type `str` et pourra donc vous aider ร  l'utiliser. +Et pourtant, l'รฉditeur sait que c'est un `str` et fournit le support appropriรฉ. -#### `Tuple` et `Set` +#### Tuple et Set { #tuple-and-set } -C'est le mรชme fonctionnement pour dรฉclarer un `tuple` ou un `set` : +Vous feriez la mรชme chose pour dรฉclarer des `tuple` et des `set` : -{*../../docs_src/python_types/tutorial007.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} -Dans cet exemple : +Cela signifie : -* La variable `items_t` est un `tuple` avec 3 รฉlรฉments, un `int`, un deuxiรจme `int`, et un `str`. +* La variable `items_t` est un `tuple` avec 3 รฉlรฉments, un `int`, un autre `int`, et un `str`. * La variable `items_s` est un `set`, et chacun de ses รฉlรฉments est de type `bytes`. -#### `Dict` +#### Dict { #dict } + +Pour dรฉfinir un `dict`, vous passez 2 paramรจtres de type, sรฉparรฉs par des virgules. + +Le premier paramรจtre de type est pour les clรฉs du `dict`. + +Le second paramรจtre de type est pour les valeurs du `dict` : + +{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} + +Cela signifie : + +* La variable `prices` est un `dict` : + * Les clรฉs de ce `dict` sont de type `str` (disons, le nom de chaque article). + * Les valeurs de ce `dict` sont de type `float` (disons, le prix de chaque article). + +#### Union { #union } + +Vous pouvez dรฉclarer qu'une variable peut รชtre de plusieurs types, par exemple, un `int` ou un `str`. + +Dans Python 3.6 et supรฉrieur (y compris Python 3.10), vous pouvez utiliser le type `Union` de `typing` et mettre entre crochets les types possibles ร  accepter. + +Dans Python 3.10, il existe aussi une nouvelle syntaxe oรน vous pouvez mettre les types possibles sรฉparรฉs par une barre verticale (`|`). + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008b_py39.py!} +``` + +//// + +Dans les deux cas, cela signifie que `item` peut รชtre un `int` ou un `str`. + +#### Possiblement `None` { #possibly-none } + +Vous pouvez dรฉclarer qu'une valeur peut avoir un type, comme `str`, mais qu'elle peut aussi รชtre `None`. + +Dans Python 3.6 et supรฉrieur (y compris Python 3.10), vous pouvez le dรฉclarer en important et en utilisant `Optional` depuis le module `typing`. + +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009_py39.py!} +``` + +Utiliser `Optional[str]` au lieu de simplement `str` permettra ร  l'รฉditeur de vous aider ร  dรฉtecter des erreurs oรน vous supposeriez qu'une valeur est toujours un `str`, alors qu'elle pourrait en fait aussi รชtre `None`. + +`Optional[Something]` est en rรฉalitรฉ un raccourci pour `Union[Something, None]`, ils sont รฉquivalents. + +Cela signifie aussi que dans Python 3.10, vous pouvez utiliser `Something | None` : + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009_py39.py!} +``` + +//// + +//// tab | Python 3.9+ alternative + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009b_py39.py!} +``` + +//// + +#### Utiliser `Union` ou `Optional` { #using-union-or-optional } + +Si vous utilisez une version de Python infรฉrieure ร  3.10, voici un conseil de mon point de vue trรจs **subjectif** : + +* ๐Ÿšจ ร‰vitez d'utiliser `Optional[SomeType]` +* ร€ la place โœจ **utilisez `Union[SomeType, None]`** โœจ. + +Les deux sont รฉquivalents et sous le capot ce sont les mรชmes, mais je recommanderais `Union` plutรดt que `Optional` parce que le mot ยซ facultatif ยป semble impliquer que la valeur est optionnelle, alors que cela signifie en fait ยซ elle peut รชtre `None` ยป, mรชme si elle n'est pas facultative et est toujours requise. + +Je pense que `Union[SomeType, None]` est plus explicite sur ce que cela signifie. -Pour dรฉfinir un `dict`, il faut lui passer 2 paramรจtres, sรฉparรฉs par une virgule (`,`). +Il ne s'agit que des mots et des noms. Mais ces mots peuvent influencer la maniรจre dont vous et vos coรฉquipiers pensez au code. -Le premier paramรจtre de type est pour les clรฉs et le second pour les valeurs du dictionnaire (`dict`). +Par exemple, prenons cette fonction : -{*../../docs_src/python_types/tutorial008.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} -Dans cet exemple : +Le paramรจtre `name` est dรฉfini comme `Optional[str]`, mais il n'est pas facultatif, vous ne pouvez pas appeler la fonction sans le paramรจtre : -* La variable `prices` est de type `dict` : - * Les clรฉs de ce dictionnaire sont de type `str`. - * Les valeurs de ce dictionnaire sont de type `float`. +```Python +say_hi() # Oh non, cela lรจve une erreur ! ๐Ÿ˜ฑ +``` + +Le paramรจtre `name` est toujours requis (pas ยซ optionnel ยป) parce qu'il n'a pas de valeur par dรฉfaut. Nรฉanmoins, `name` accepte `None` comme valeur : + +```Python +say_hi(name=None) # Cela fonctionne, None est valide ๐ŸŽ‰ +``` -#### `Optional` +La bonne nouvelle est que, dรจs que vous รชtes sur Python 3.10, vous n'avez plus ร  vous en soucier, car vous pourrez simplement utiliser `|` pour dรฉfinir des unions de types : -Vous pouvez aussi utiliser `Optional` pour dรฉclarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi รชtre `None`. +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} -{*../../docs_src/python_types/tutorial009.py hl[1,4] *} +Et alors vous n'aurez plus ร  vous soucier de noms comme `Optional` et `Union`. ๐Ÿ˜Ž -Utiliser `Optional[str]` plutรดt que `str` permettra ร  l'รฉditeur de vous aider ร  dรฉtecter les erreurs oรน vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi รชtre `None`. +#### Types gรฉnรฉriques { #generic-types } -#### Types gรฉnรฉriques +Ces types qui prennent des paramรจtres de type entre crochets sont appelรฉs des **types gรฉnรฉriques** ou **Generics**, par exemple : -Les types qui peuvent contenir des paramรจtres de types entre crochets, comme : +//// tab | Python 3.10+ -* `List` -* `Tuple` -* `Set` -* `Dict` +Vous pouvez utiliser les mรชmes types intรฉgrรฉs comme gรฉnรฉriques (avec des crochets et des types ร  l'intรฉrieur) : + +* `list` +* `tuple` +* `set` +* `dict` + +Et, comme avec les versions prรฉcรฉdentes de Python, depuis le module `typing` : + +* `Union` * `Optional` -* ...et d'autres. +* ... et d'autres. -sont appelรฉs des **types gรฉnรฉriques** ou **Generics**. +Dans Python 3.10, comme alternative ร  l'utilisation des gรฉnรฉriques `Union` et `Optional`, vous pouvez utiliser la barre verticale (`|`) pour dรฉclarer des unions de types, c'est bien mieux et plus simple. -### Classes en tant que types +//// -Vous pouvez aussi dรฉclarer une classe comme type d'une variable. +//// tab | Python 3.9+ + +Vous pouvez utiliser les mรชmes types intรฉgrรฉs comme gรฉnรฉriques (avec des crochets et des types ร  l'intรฉrieur) : + +* `list` +* `tuple` +* `set` +* `dict` + +Et des gรฉnรฉriques depuis le module `typing` : + +* `Union` +* `Optional` +* ... et d'autres. + +//// + +### Classes en tant que types { #classes-as-types } -Disons que vous avez une classe `Person`, avec une variable `name` : +Vous pouvez aussi dรฉclarer une classe comme type d'une variable. -{*../../docs_src/python_types/tutorial010.py hl[1:3] *} +Disons que vous avez une classe `Person`, avec un nom : +{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} Vous pouvez ensuite dรฉclarer une variable de type `Person` : -{*../../docs_src/python_types/tutorial010.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} -Et vous aurez accรจs, encore une fois, au support complet offert par l'รฉditeur : +Et lร  encore, vous obtenez tout le support de l'รฉditeur : -## Les modรจles Pydantic +Remarquez que cela signifie ยซ `one_person` est une instance de la classe `Person` ยป. + +Cela ne signifie pas ยซ `one_person` est la classe appelรฉe `Person` ยป. + +## Modรจles Pydantic { #pydantic-models } Pydantic est une bibliothรจque Python pour effectuer de la validation de donnรฉes. -Vous dรฉclarez la forme de la donnรฉe avec des classes et des attributs. +Vous dรฉclarez la ยซ forme ยป de la donnรฉe sous forme de classes avec des attributs. -Chaque attribut possรจde un type. +Et chaque attribut a un type. -Puis vous crรฉez une instance de cette classe avec certaines valeurs et **Pydantic** validera les valeurs, les convertira dans le type adรฉquat (si c'est nรฉcessaire et possible) et vous donnera un objet avec toute la donnรฉe. +Ensuite, vous crรฉez une instance de cette classe avec certaines valeurs et elle validera les valeurs, les convertira dans le type appropriรฉ (le cas รฉchรฉant) et vous donnera un objet avec toutes les donnรฉes. -Ainsi, votre รฉditeur vous offrira un support adaptรฉ pour l'objet rรฉsultant. +Et vous obtenez tout le support de l'รฉditeur avec cet objet rรฉsultant. -Extrait de la documentation officielle de **Pydantic** : +Un exemple tirรฉ de la documentation officielle de Pydantic : -{*../../docs_src/python_types/tutorial011.py*} +{* ../../docs_src/python_types/tutorial011_py310.py *} /// info -Pour en savoir plus ร  propos de Pydantic, allez jeter un coup d'oeil ร  sa documentation. +Pour en savoir plus ร  propos de Pydantic, consultez sa documentation. + +/// + +**FastAPI** est entiรจrement basรฉ sur Pydantic. + +Vous verrez beaucoup plus de tout cela en pratique dans le [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}. + +/// tip | Astuce + +Pydantic a un comportement spรฉcial lorsque vous utilisez `Optional` ou `Union[Something, None]` sans valeur par dรฉfaut, vous pouvez en lire davantage dans la documentation de Pydantic ร  propos des champs Optionals requis. /// -**FastAPI** est basรฉ entiรจrement sur **Pydantic**. +## Annotations de type avec mรฉtadonnรฉes { #type-hints-with-metadata-annotations } + +Python dispose รฉgalement d'une fonctionnalitรฉ qui permet de mettre des **mรฉtadonnรฉes supplรฉmentaires** dans ces annotations de type en utilisant `Annotated`. + +Depuis Python 3.9, `Annotated` fait partie de la bibliothรจque standard, vous pouvez donc l'importer depuis `typing`. -Vous verrez bien plus d'exemples de son utilisation dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}. +{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} + +Python lui-mรชme ne fait rien avec ce `Annotated`. Et pour les รฉditeurs et autres outils, le type est toujours `str`. + +Mais vous pouvez utiliser cet espace dans `Annotated` pour fournir ร  **FastAPI** des mรฉtadonnรฉes supplรฉmentaires sur la faรงon dont vous voulez que votre application se comporte. + +L'important ร  retenir est que le premier paramรจtre de type que vous passez ร  `Annotated` est le type rรฉel. Le reste n'est que des mรฉtadonnรฉes pour d'autres outils. + +Pour l'instant, vous avez juste besoin de savoir que `Annotated` existe, et que c'est du Python standard. ๐Ÿ˜Ž + +Plus tard, vous verrez ร  quel point cela peut รชtre puissant. + +/// tip | Astuce + +Le fait que ce soit du Python standard signifie que vous bรฉnรฉficierez toujours de la meilleure expรฉrience dรฉveloppeur possible dans votre รฉditeur, avec les outils que vous utilisez pour analyser et refactoriser votre code, etc. โœจ + +Et aussi que votre code sera trรจs compatible avec de nombreux autres outils et bibliothรจques Python. ๐Ÿš€ + +/// -## Les annotations de type dans **FastAPI** +## Annotations de type dans **FastAPI** { #type-hints-in-fastapi } -**FastAPI** utilise ces annotations pour faire diffรฉrentes choses. +**FastAPI** tire parti de ces annotations de type pour faire plusieurs choses. -Avec **FastAPI**, vous dรฉclarez des paramรจtres grรขce aux annotations de types et vous obtenez : +Avec **FastAPI**, vous dรฉclarez des paramรจtres avec des annotations de type et vous obtenez : -* **du support de l'รฉditeur** -* **de la vรฉrification de types** +* **Du support de l'รฉditeur**. +* **Des vรฉrifications de types**. -...et **FastAPI** utilise ces mรชmes dรฉclarations pour : +... et **FastAPI** utilise les mรชmes dรฉclarations pour : -* **Dรฉfinir les prรฉrequis** : depuis les paramรจtres de chemins des requรชtes, les entรชtes, les corps, les dรฉpendances, etc. -* **Convertir des donnรฉes** : depuis la requรชte vers les types requis. -* **Valider des donnรฉes** : venant de chaque requรชte : - * Gรฉnรฉrant automatiquement des **erreurs** renvoyรฉes au client quand la donnรฉe est invalide. +* **Dรฉfinir des prรฉrequis** : ร  partir des paramรจtres de chemin de la requรชte, des paramรจtres de requรชte, des en-tรชtes, des corps, des dรฉpendances, etc. +* **Convertir des donnรฉes** : de la requรชte vers le type requis. +* **Valider des donnรฉes** : provenant de chaque requรชte : + * En gรฉnรฉrant des **erreurs automatiques** renvoyรฉes au client lorsque la donnรฉe est invalide. * **Documenter** l'API avec OpenAPI : - * ce qui ensuite utilisรฉ par les interfaces utilisateur automatiques de documentation interactive. + * ce qui est ensuite utilisรฉ par les interfaces utilisateur de documentation interactive automatiques. -Tout cela peut paraรฎtre bien abstrait, mais ne vous inquiรฉtez pas, vous verrez tout รงa en pratique dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}. +Tout cela peut sembler abstrait. Ne vous inquiรฉtez pas. Vous verrez tout cela en action dans le [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}. -Ce qu'il faut retenir c'est qu'en utilisant les types standard de Python, ร  un seul endroit (plutรดt que d'ajouter plus de classes, de dรฉcorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous. +L'important est qu'en utilisant les types standards de Python, en un seul endroit (au lieu d'ajouter plus de classes, de dรฉcorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous. /// info -Si vous avez dรฉjร  lu le tutoriel et รชtes revenus ici pour voir plus sur les types, une bonne ressource est la "cheat sheet" de `mypy`. +Si vous avez dรฉjร  parcouru tout le tutoriel et รชtes revenu pour en voir plus sur les types, une bonne ressource est l'ยซ aide-mรฉmoire ยป de `mypy`. /// diff --git a/docs/fr/docs/tutorial/background-tasks.md b/docs/fr/docs/tutorial/background-tasks.md index 6efd16e07d..ed7494669f 100644 --- a/docs/fr/docs/tutorial/background-tasks.md +++ b/docs/fr/docs/tutorial/background-tasks.md @@ -1,4 +1,4 @@ -# Tรขches d'arriรจre-plan +# Tรขches d'arriรจre-plan { #background-tasks } Vous pouvez dรฉfinir des tรขches d'arriรจre-plan qui seront exรฉcutรฉes aprรจs avoir retournรฉ une rรฉponse. @@ -7,20 +7,19 @@ Ceci est utile pour les opรฉrations qui doivent avoir lieu aprรจs une requรชte, Cela comprend, par exemple : * Les notifications par email envoyรฉes aprรจs l'exรฉcution d'une action : - * ร‰tant donnรฉ que se connecter ร  un serveur et envoyer un email a tendance ร  รชtre ยซlentยป (plusieurs secondes), vous pouvez retourner la rรฉponse directement et envoyer la notification en arriรจre-plan. + * ร‰tant donnรฉ que se connecter ร  un serveur et envoyer un email a tendance ร  รชtre ยซ lent ยป (plusieurs secondes), vous pouvez retourner la rรฉponse directement et envoyer la notification en arriรจre-plan. * Traiter des donnรฉes : - * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une rรฉponse ยซAcceptedยป (HTTP 202) puis faire le traitement en arriรจre-plan. + * Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une rรฉponse ยซ Accepted ยป (HTTP 202) puis faire le traitement en arriรจre-plan. +## Utiliser `BackgroundTasks` { #using-backgroundtasks } -## Utiliser `BackgroundTasks` +Pour commencer, importez `BackgroundTasks` et dรฉfinissez un paramรจtre dans votre *fonction de chemin d'accรจs* avec `BackgroundTasks` comme type dรฉclarรฉ. -Pour commencer, importez `BackgroundTasks` et dรฉfinissez un paramรจtre dans votre *fonction de chemin* avec `BackgroundTasks` comme type dรฉclarรฉ. - -{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} **FastAPI** crรฉera l'objet de type `BackgroundTasks` pour vous et le passera comme paramรจtre. -## Crรฉer une fonction de tรขche +## Crรฉer une fonction de tรขche { #create-a-task-function } Une fonction ร  exรฉcuter comme tรขche d'arriรจre-plan est juste une fonction standard qui peut recevoir des paramรจtres. @@ -30,14 +29,13 @@ Dans cet exemple, la fonction de tรขche รฉcrira dans un fichier (afin de simuler L'opรฉration d'รฉcriture n'utilisant ni `async` ni `await`, on dรฉfinit la fonction avec un `def` normal. -{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} - -## Ajouter une tรขche d'arriรจre-plan +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} -Dans votre *fonction de chemin*, passez votre fonction de tรขche ร  l'objet de type `BackgroundTasks` (`background_tasks` ici) grรขce ร  la mรฉthode `.add_task()` : +## Ajouter une tรขche d'arriรจre-plan { #add-the-background-task } +Dans votre *fonction de chemin d'accรจs*, passez votre fonction de tรขche ร  l'objet de type `BackgroundTasks` (`background_tasks` ici) grรขce ร  la mรฉthode `.add_task()` : -{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} `.add_task()` reรงoit comme arguments : @@ -45,40 +43,40 @@ Dans votre *fonction de chemin*, passez votre fonction de tรขche ร  l'objet de t * Les arguments positionnels ร  passer ร  la fonction de tรขche dans l'ordre (`email`). * Les arguments nommรฉs ร  passer ร  la fonction de tรขche (`message="some notification"`). -## Injection de dรฉpendances +## Injection de dรฉpendances { #dependency-injection } -Utiliser `BackgroundTasks` fonctionne aussi avec le systรจme d'injection de dรฉpendances. Vous pouvez dรฉclarer un paramรจtre de type `BackgroundTasks` ร  diffรฉrents niveaux : dans une *fonction de chemin*, dans une dรฉpendance, dans une sous-dรฉpendance... +Utiliser `BackgroundTasks` fonctionne aussi avec le systรจme d'injection de dรฉpendances. Vous pouvez dรฉclarer un paramรจtre de type `BackgroundTasks` ร  diffรฉrents niveaux : dans une *fonction de chemin d'accรจs*, dans une dรฉpendance (dependable), dans une sous-dรฉpendance, etc. -**FastAPI** sait quoi faire dans chaque cas et comment rรฉutiliser le mรชme objet, afin que tous les paramรจtres de type `BackgroundTasks` soient fusionnรฉs et que les tรขches soient exรฉcutรฉes en arriรจre-plan : +**FastAPI** sait quoi faire dans chaque cas et comment rรฉutiliser le mรชme objet, afin que toutes les tรขches d'arriรจre-plan soient fusionnรฉes et que les tรขches soient ensuite exรฉcutรฉes en arriรจre-plan : -{* ../../docs_src/background_tasks/tutorial002.py hl[13,15,22,25] *} +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} Dans cet exemple, les messages seront รฉcrits dans le fichier `log.txt` aprรจs que la rรฉponse soit envoyรฉe. -S'il y avait une `query` (paramรจtre nommรฉ `q`) dans la requรชte, alors elle sera รฉcrite dans `log.txt` via une tรขche d'arriรจre-plan. +S'il y avait un paramรจtre de requรชte dans la requรชte, alors il sera รฉcrit dans le journal via une tรขche d'arriรจre-plan. -Et ensuite une autre tรขche d'arriรจre-plan (gรฉnรฉrรฉe dans les paramรจtres de la *la fonction de chemin*) รฉcrira un message dans `log.txt` comprenant le paramรจtre de chemin `email`. +Et ensuite une autre tรขche d'arriรจre-plan (gรฉnรฉrรฉe dans la *fonction de chemin d'accรจs*) รฉcrira un message comprenant le paramรจtre de chemin `email`. -## Dรฉtails techniques +## Dรฉtails techniques { #technical-details } La classe `BackgroundTasks` provient directement de `starlette.background`. Elle est importรฉe/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et รฉviter d'importer accidentellement `BackgroundTask` (sans `s` ร  la fin) depuis `starlette.background`. -En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramรจtre de *fonction de chemin* et de laisser **FastAPI** gรฉrer le reste pour vous, comme en utilisant l'objet `Request` directement. +En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramรจtre de *fonction de chemin d'accรจs* et de laisser **FastAPI** gรฉrer le reste pour vous, comme en utilisant l'objet `Request` directement. Il est tout de mรชme possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut crรฉer l'objet dans le code et renvoyer une `Response` Starlette l'incluant. -Plus de dรฉtails sont disponibles dans la documentation officielle de Starlette sur les tรขches d'arriรจre-plan (via leurs classes `BackgroundTasks`et `BackgroundTask`). +Plus de dรฉtails sont disponibles dans la documentation officielle de Starlette sur les tรขches d'arriรจre-plan. -## Avertissement +## Avertissement { #caveat } Si vous avez besoin de rรฉaliser des traitements lourds en tรขche d'arriรจre-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le mรชme process (par exemple, pas besoin de partager la mรฉmoire, les variables, etc.), il peut s'avรฉrer profitable d'utiliser des outils plus importants tels que Celery. -Ces outils nรฉcessitent gรฉnรฉralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exรฉcuter des tรขches d'arriรจre-plan dans diffรฉrents process, et potentiellement, sur plusieurs serveurs. +Ces outils nรฉcessitent gรฉnรฉralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exรฉcuter des tรขches d'arriรจre-plan dans diffรฉrents process, et surtout, sur plusieurs serveurs. Mais si vous avez besoin d'accรฉder aux variables et objets de la mรชme application **FastAPI**, ou si vous avez besoin d'effectuer de petites tรขches d'arriรจre-plan (comme envoyer des notifications par email), vous pouvez simplement vous contenter d'utiliser `BackgroundTasks`. -## Rรฉsumรฉ +## Rรฉsumรฉ { #recap } -Importez et utilisez `BackgroundTasks` grรขce aux paramรจtres de *fonction de chemin* et les dรฉpendances pour ajouter des tรขches d'arriรจre-plan. +Importez et utilisez `BackgroundTasks` grรขce aux paramรจtres de *fonction de chemin d'accรจs* et les dรฉpendances pour ajouter des tรขches d'arriรจre-plan. diff --git a/docs/fr/docs/tutorial/body-multiple-params.md b/docs/fr/docs/tutorial/body-multiple-params.md index 0541acc74e..9aed24e989 100644 --- a/docs/fr/docs/tutorial/body-multiple-params.md +++ b/docs/fr/docs/tutorial/body-multiple-params.md @@ -1,24 +1,24 @@ -# Body - Paramรจtres multiples +# Body - Paramรจtres multiples { #body-multiple-parameters } -Maintenant que nous avons vu comment manipuler `Path` et `Query`, voyons comment faire pour le corps d'une requรชte, communรฉment dรฉsignรฉ par le terme anglais "body". +Maintenant que nous avons vu comment utiliser `Path` et `Query`, voyons des usages plus avancรฉs des dรฉclarations de paramรจtres du corps de la requรชte. -## Mรฉlanger les paramรจtres `Path`, `Query` et body +## Mรฉlanger les paramรจtres `Path`, `Query` et body { #mix-path-query-and-body-parameters } -Tout d'abord, sachez que vous pouvez mรฉlanger les dรฉclarations des paramรจtres `Path`, `Query` et body, **FastAPI** saura quoi faire. +Tout d'abord, sachez que vous pouvez mรฉlanger librement les dรฉclarations des paramรจtres `Path`, `Query` et du body, **FastAPI** saura quoi faire. -Vous pouvez รฉgalement dรฉclarer des paramรจtres body comme รฉtant optionnels, en leur assignant une valeur par dรฉfaut ร  `None` : +Et vous pouvez รฉgalement dรฉclarer des paramรจtres du body comme รฉtant optionnels, en leur assignant une valeur par dรฉfaut ร  `None` : {* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} -/// note +/// note | Remarque -Notez que, dans ce cas, le paramรจtre `item` provenant du `Body` est optionnel (sa valeur par dรฉfaut est `None`). +Notez que, dans ce cas, l'รฉlรฉment `item` rรฉcupรฉrรฉ depuis le body est optionnel. Comme sa valeur par dรฉfaut est `None`. /// -## Paramรจtres multiples du body +## Paramรจtres multiples du body { #multiple-body-parameters } -Dans l'exemple prรฉcรฉdent, les opรฉrations de routage attendaient un body JSON avec les attributs d'un `Item`, par exemple : +Dans l'exemple prรฉcรฉdent, les chemins d'accรจs attendraient un body JSON avec les attributs d'un `Item`, par exemple : ```JSON { @@ -29,13 +29,13 @@ Dans l'exemple prรฉcรฉdent, les opรฉrations de routage attendaient un body JSON } ``` -Mais vous pouvez รฉgalement dรฉclarer plusieurs paramรจtres provenant de body, par exemple `item` et `user` simultanรฉment : +Mais vous pouvez รฉgalement dรฉclarer plusieurs paramรจtres provenant du body, par exemple `item` et `user` : {* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} -Dans ce cas, **FastAPI** dรฉtectera qu'il y a plus d'un paramรจtre dans le body (chacun correspondant ร  un modรจle Pydantic). +Dans ce cas, **FastAPI** dรฉtectera qu'il y a plus d'un paramรจtre du body dans la fonction (il y a deux paramรจtres qui sont des modรจles Pydantic). -Il utilisera alors les noms des paramรจtres comme clรฉs, et s'attendra ร  recevoir quelque chose de semblable ร  : +Il utilisera alors les noms des paramรจtres comme clรฉs (noms de champs) dans le body, et s'attendra ร  recevoir un body semblable ร  : ```JSON { @@ -52,25 +52,25 @@ Il utilisera alors les noms des paramรจtres comme clรฉs, et s'attendra ร  recevo } ``` -/// note +/// note | Remarque -"Notez que, bien que nous ayons dรฉclarรฉ le paramรจtre `item` de la mรชme maniรจre que prรฉcรฉdemment, il est maintenant associรฉ ร  la clรฉ `item` dans le corps de la requรชte."`. +Notez que, bien que `item` ait รฉtรฉ dรฉclarรฉ de la mรชme maniรจre qu'auparavant, il est dรฉsormais attendu ร  l'intรฉrieur du body sous la clรฉ `item`. /// -**FastAPI** effectue la conversion de la requรชte de faรงon transparente, de sorte que les objets `item` et `user` se trouvent correctement dรฉfinis. +**FastAPI** effectuera la conversion automatique depuis la requรชte, de sorte que le paramรจtre `item` reรงoive son contenu spรฉcifique, et de mรชme pour `user`. -Il effectue รฉgalement la validation des donnรฉes (mรชme imbriquรฉes les unes dans les autres), et permet de les documenter correctement (schรฉma OpenAPI et documentation auto-gรฉnรฉrรฉe). +Il effectuera la validation des donnรฉes composรฉes, et les documentera ainsi pour le schรฉma OpenAPI et la documentation automatique. -## Valeurs scalaires dans le body +## Valeurs singuliรจres dans le body { #singular-values-in-body } -De la mรชme faรงon qu'il existe `Query` et `Path` pour dรฉfinir des donnรฉes supplรฉmentaires pour les paramรจtres query et path, **FastAPI** fournit un รฉquivalent `Body`. +De la mรชme faรงon qu'il existe `Query` et `Path` pour dรฉfinir des donnรฉes supplรฉmentaires pour les paramรจtres de requรชte et de chemin, **FastAPI** fournit un รฉquivalent `Body`. -Par exemple, en รฉtendant le modรจle prรฉcรฉdent, vous pouvez vouloir ajouter un paramรจtre `importance` dans le mรชme body, en plus des paramรจtres `item` et `user`. +Par exemple, en รฉtendant le modรจle prรฉcรฉdent, vous pourriez dรฉcider d'avoir une autre clรฉ `importance` dans le mรชme body, en plus de `item` et `user`. -Si vous le dรฉclarez tel quel, comme c'est une valeur [scalaire](https://docs.github.com/fr/graphql/reference/scalars), **FastAPI** supposera qu'il s'agit d'un paramรจtre de requรชte (`Query`). +Si vous le dรฉclarez tel quel, comme c'est une valeur singuliรจre, **FastAPI** supposera qu'il s'agit d'un paramรจtre de requรชte. -Mais vous pouvez indiquer ร  **FastAPI** de la traiter comme une variable de body en utilisant `Body` : +Mais vous pouvez indiquer ร  **FastAPI** de la traiter comme une autre clรฉ du body en utilisant `Body` : {* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} @@ -92,51 +92,51 @@ Dans ce cas, **FastAPI** s'attendra ร  un body semblable ร  : } ``` -Encore une fois, cela convertira les types de donnรฉes, les validera, permettra de gรฉnรฉrer la documentation, etc... +Encore une fois, il convertira les types de donnรฉes, validera, documentera, etc. -## Paramรจtres multiples body et query +## Paramรจtres multiples du body et paramรจtres de requรชte { #multiple-body-params-and-query } -Bien entendu, vous pouvez dรฉclarer autant de paramรจtres que vous le souhaitez, en plus des paramรจtres body dรฉjร  dรฉclarรฉs. +Bien entendu, vous pouvez รฉgalement dรฉclarer des paramรจtres de requรชte supplรฉmentaires quand vous en avez besoin, en plus de tout paramรจtre du body. -Par dรฉfaut, les valeurs [scalaires](https://docs.github.com/fr/graphql/reference/scalars) sont interprรฉtรฉes comme des paramรจtres query, donc inutile d'ajouter explicitement `Query`. Vous pouvez juste รฉcrire : +Comme, par dรฉfaut, les valeurs singuliรจres sont interprรฉtรฉes comme des paramรจtres de requรชte, vous n'avez pas besoin d'ajouter explicitement `Query`, vous pouvez simplement รฉcrire : ```Python -q: Union[str, None] = None +q: str | None = None ``` -Ou bien, en Python 3.10 et supรฉrieur : +Ou en Python 3.9 : ```Python -q: str | None = None +q: Union[str, None] = None ``` Par exemple : -{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[27] *} +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} /// info -`Body` possรจde les mรชmes paramรจtres de validation additionnels et de gestion des mรฉtadonnรฉes que `Query` et `Path`, ainsi que d'autres que nous verrons plus tard. +`Body` possรจde รฉgalement les mรชmes paramรจtres supplรฉmentaires de validation et de mรฉtadonnรฉes que `Query`, `Path` et d'autres que vous verrez plus tard. /// -## Inclure un paramรจtre imbriquรฉ dans le body +## Intรฉgrer un seul paramรจtre du body { #embed-a-single-body-parameter } -Disons que vous avez seulement un paramรจtre `item` dans le body, correspondant ร  un modรจle Pydantic `Item`. +Supposons que vous n'ayez qu'un seul paramรจtre `item` dans le body, provenant d'un modรจle Pydantic `Item`. -Par dรฉfaut, **FastAPI** attendra sa dรฉclaration directement dans le body. +Par dรฉfaut, **FastAPI** attendra alors son contenu directement. -Cependant, si vous souhaitez qu'il interprรชte correctement un JSON avec une clรฉ `item` associรฉe au contenu du modรจle, comme cela serait le cas si vous dรฉclariez des paramรจtres body additionnels, vous pouvez utiliser le paramรจtre spรฉcial `embed` de `Body` : +Mais si vous voulez qu'il attende un JSON avec une clรฉ `item` contenant le contenu du modรจle, comme lorsqu'on dรฉclare des paramรจtres supplรฉmentaires du body, vous pouvez utiliser le paramรจtre spรฉcial `embed` de `Body` : ```Python item: Item = Body(embed=True) ``` -Voici un exemple complet : +comme dans : {* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} -Dans ce cas **FastAPI** attendra un body semblable ร  : +Dans ce cas **FastAPI** s'attendra ร  un body semblable ร  : ```JSON hl_lines="2" { @@ -160,12 +160,12 @@ au lieu de : } ``` -## Pour rรฉsumer +## Rรฉcapitulatif { #recap } -Vous pouvez ajouter plusieurs paramรจtres body dans votre fonction de routage, mรชme si une requรชte ne peut avoir qu'un seul body. +Vous pouvez ajouter plusieurs paramรจtres du body ร  votre fonction de chemin d'accรจs, mรชme si une requรชte ne peut avoir qu'un seul body. -Cependant, **FastAPI** se chargera de faire opรฉrer sa magie, afin de toujours fournir ร  votre fonction des donnรฉes correctes, les validera et documentera le schรฉma associรฉ. +Mais **FastAPI** s'en chargera, vous fournira les bonnes donnรฉes dans votre fonction, et validera et documentera le schรฉma correct dans le chemin d'accรจs. -Vous pouvez รฉgalement dรฉclarer des valeurs [scalaires](https://docs.github.com/fr/graphql/reference/scalars) ร  recevoir dans le body. +Vous pouvez รฉgalement dรฉclarer des valeurs singuliรจres ร  recevoir dans le body. -Et vous pouvez indiquer ร  **FastAPI** d'inclure le body dans une autre variable, mรชme lorsqu'un seul paramรจtre est dรฉclarรฉ. +Et vous pouvez indiquer ร  **FastAPI** d'intรฉgrer le body sous une clรฉ mรชme lorsqu'un seul paramรจtre est dรฉclarรฉ. diff --git a/docs/fr/docs/tutorial/body.md b/docs/fr/docs/tutorial/body.md index 760b6d80ae..ca115fabc7 100644 --- a/docs/fr/docs/tutorial/body.md +++ b/docs/fr/docs/tutorial/body.md @@ -1,10 +1,10 @@ -# Corps de la requรชte +# Corps de la requรชte { #request-body } Quand vous avez besoin d'envoyer de la donnรฉe depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de requรชte**. Le corps d'une **requรชte** est de la donnรฉe envoyรฉe par le client ร  votre API. Le corps d'une **rรฉponse** est la donnรฉe envoyรฉe par votre API au client. -Votre API aura presque toujours ร  envoyer un corps de **rรฉponse**. Mais un client n'a pas toujours ร  envoyer un corps de **requรชte**. +Votre API aura presque toujours ร  envoyer un corps de **rรฉponse**. Mais un client n'a pas toujours ร  envoyer un **corps de requรชte**ย : parfois il demande seulement un chemin, peut-รชtre avec quelques paramรจtres de requรชte, mais n'envoie pas de corps. Pour dรฉclarer un corps de **requรชte**, on utilise les modรจles de Pydantic en profitant de tous leurs avantages et fonctionnalitรฉs. @@ -18,23 +18,23 @@ Ceci รฉtant dรฉcouragรฉ, la documentation interactive gรฉnรฉrรฉe par Swagger UI /// -## Importez le `BaseModel` de Pydantic +## Importer le `BaseModel` de Pydantic { #import-pydantics-basemodel } Commencez par importer la classe `BaseModel` du module `pydantic` : -{* ../../docs_src/body/tutorial001.py hl[4] *} +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} -## Crรฉez votre modรจle de donnรฉes +## Crรฉer votre modรจle de donnรฉes { #create-your-data-model } Dรฉclarez ensuite votre modรจle de donnรฉes en tant que classe qui hรฉrite de `BaseModel`. Utilisez les types Python standard pour tous les attributs : -{* ../../docs_src/body/tutorial001.py hl[7:11] *} +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} -Tout comme pour la dรฉclaration de paramรจtres de requรชte, quand un attribut de modรจle a une valeur par dรฉfaut, il n'est pas nรฉcessaire. Sinon, cet attribut doit รชtre renseignรฉ dans le corps de la requรชte. Pour rendre ce champ optionnel simplement, utilisez `None` comme valeur par dรฉfaut. +Tout comme pour la dรฉclaration de paramรจtres de requรชte, quand un attribut de modรจle a une valeur par dรฉfaut, il n'est pas nรฉcessaire. Sinon, cet attribut doit รชtre renseignรฉ dans le corps de la requรชte. Utilisez `None` pour le rendre simplement optionnel. -Par exemple, le modรจle ci-dessus dรฉclare un "objet" JSON (ou `dict` Python) tel que : +Par exemple, le modรจle ci-dessus dรฉclare un JSON ยซย `object`ย ยป (ou `dict` Python) tel que : ```JSON { @@ -45,7 +45,7 @@ Par exemple, le modรจle ci-dessus dรฉclare un "objet" JSON (ou `dict` Python) te } ``` -...`description` et `tax` รฉtant des attributs optionnels (avec `None` comme valeur par dรฉfaut), cet "objet" JSON serait aussi valide : +... `description` et `tax` รฉtant des attributs optionnels (avec `None` comme valeur par dรฉfaut), ce JSON ยซย `object`ย ยป serait aussi valide : ```JSON { @@ -54,28 +54,28 @@ Par exemple, le modรจle ci-dessus dรฉclare un "objet" JSON (ou `dict` Python) te } ``` -## Dรฉclarez-le comme paramรจtre +## Le dรฉclarer comme paramรจtre { #declare-it-as-a-parameter } Pour l'ajouter ร  votre *opรฉration de chemin*, dรฉclarez-le comme vous dรฉclareriez des paramรจtres de chemin ou de requรชte : -{* ../../docs_src/body/tutorial001.py hl[18] *} +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} -...et dรฉclarez que son type est le modรจle que vous avez crรฉรฉ : `Item`. +... et dรฉclarez que son type est le modรจle que vous avez crรฉรฉย : `Item`. -## Rรฉsultats +## Rรฉsultats { #results } En utilisant uniquement les dรฉclarations de type Python, **FastAPI** rรฉussit ร  : * Lire le contenu de la requรชte en tant que JSON. * Convertir les types correspondants (si nรฉcessaire). * Valider la donnรฉe. - * Si la donnรฉe est invalide, une erreur propre et claire sera renvoyรฉe, indiquant exactement oรน รฉtait la donnรฉe incorrecte. + * Si la donnรฉe est invalide, une erreur propre et claire sera renvoyรฉe, indiquant exactement oรน et quelle รฉtait la donnรฉe incorrecte. * Passer la donnรฉe reรงue dans le paramรจtre `item`. - * Ce paramรจtre ayant รฉtรฉ dรฉclarรฉ dans la fonction comme รฉtant de type `Item`, vous aurez aussi tout le support offert par l'รฉditeur (auto-complรฉtion, etc.) pour tous les attributs de ce paramรจtre et les types de ces attributs. -* Gรฉnรฉrer des dรฉfinitions JSON Schema pour votre modรจle, qui peuvent รชtre utilisรฉes oรน vous en avez besoin dans votre projet ensuite. -* Ces schรฉmas participeront ร  la constitution du schรฉma gรฉnรฉrรฉ OpenAPI, et seront donc utilisรฉs par les documentations automatiquement gรฉnรฉrรฉes. + * Ce paramรจtre ayant รฉtรฉ dรฉclarรฉ dans la fonction comme รฉtant de type `Item`, vous aurez aussi tout le support offert par l'รฉditeur (autocomplรฉtion, etc.) pour tous les attributs de ce paramรจtre et les types de ces attributs. +* Gรฉnรฉrer des dรฉfinitions JSON Schema pour votre modรจle ; vous pouvez รฉgalement les utiliser partout ailleurs si cela a du sens pour votre projet. +* Ces schรฉmas participeront ร  la constitution du schรฉma gรฉnรฉrรฉ OpenAPI, et seront utilisรฉs par les documentations automatiques UIs. -## Documentation automatique +## Documentation automatique { #automatic-docs } Les schรฉmas JSON de vos modรจles seront intรฉgrรฉs au schรฉma OpenAPI global de votre application, et seront donc affichรฉs dans la documentation interactive de l'API : @@ -85,63 +85,63 @@ Et seront aussi utilisรฉs dans chaque *opรฉration de chemin* de la documentation -## Support de l'รฉditeur +## Support de l'รฉditeur { #editor-support } -Dans votre รฉditeur, vous aurez des annotations de types et de l'auto-complรฉtion partout dans votre fonction (ce qui n'aurait pas รฉtรฉ le cas si vous aviez utilisรฉ un classique `dict` plutรดt qu'un modรจle Pydantic) : +Dans votre รฉditeur, vous aurez des annotations de type et de l'autocomplรฉtion partout dans votre fonction (ce qui n'aurait pas รฉtรฉ le cas si vous aviez reรงu un `dict` plutรดt qu'un modรจle Pydantic) : -Et vous obtenez aussi de la vรฉrification d'erreur pour les opรฉrations incorrectes de types : +Et vous obtenez aussi des vรฉrifications d'erreurs pour les opรฉrations de types incorrectes : Ce n'est pas un hasard, ce framework entier a รฉtรฉ bรขti avec ce design comme objectif. -Et cela a รฉtรฉ rigoureusement testรฉ durant la phase de design, avant toute implรฉmentation, pour s'assurer que cela fonctionnerait avec tous les รฉditeurs. +Et cela a รฉtรฉ rigoureusement testรฉ durant la phase de design, avant toute implรฉmentation, pour vous assurer que cela fonctionnerait avec tous les รฉditeurs. Des changements sur Pydantic ont mรชme รฉtรฉ faits pour supporter cela. -Les captures d'รฉcrans prรฉcรฉdentes ont รฉtรฉ prises sur Visual Studio Code. +Les captures d'รฉcran prรฉcรฉdentes ont รฉtรฉ prises sur Visual Studio Code. -Mais vous auriez le mรชme support de l'รฉditeur avec PyCharm et la majoritรฉ des autres รฉditeurs de code Python. +Mais vous auriez le mรชme support de l'รฉditeur avec PyCharm et la majoritรฉ des autres รฉditeurs de code Python : /// tip | Astuce -Si vous utilisez PyCharm comme รฉditeur, vous pouvez utiliser le Plugin Pydantic PyCharm Plugin. +Si vous utilisez PyCharm comme รฉditeur, vous pouvez utiliser le plug-in Pydantic PyCharm Plugin. Ce qui amรฉliore le support pour les modรจles Pydantic avec : -* de l'auto-complรฉtion +* de l'autocomplรฉtion * des vรฉrifications de type -* du "refactoring" (ou remaniement de code) +* du ยซย refactoringย ยป (ou remaniement de code) * de la recherche -* de l'inspection +* des inspections /// -## Utilisez le modรจle +## Utiliser le modรจle { #use-the-model } Dans la fonction, vous pouvez accรฉder ร  tous les attributs de l'objet du modรจle directement : -{* ../../docs_src/body/tutorial002.py hl[21] *} +{* ../../docs_src/body/tutorial002_py310.py *} -## Corps de la requรชte + paramรจtres de chemin +## Corps de la requรชte + paramรจtres de chemin { #request-body-path-parameters } Vous pouvez dรฉclarer des paramรจtres de chemin et un corps de requรชte pour la mรชme *opรฉration de chemin*. **FastAPI** est capable de reconnaรฎtre que les paramรจtres de la fonction qui correspondent aux paramรจtres de chemin doivent รชtre **rรฉcupรฉrรฉs depuis le chemin**, et que les paramรจtres de fonctions dรฉclarรฉs comme modรจles Pydantic devraient รชtre **rรฉcupรฉrรฉs depuis le corps de la requรชte**. -{* ../../docs_src/body/tutorial003.py hl[17:18] *} +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} -## Corps de la requรชte + paramรจtres de chemin et de requรชte +## Corps de la requรชte + paramรจtres de chemin et de requรชte { #request-body-path-query-parameters } Vous pouvez aussi dรฉclarer un **corps**, et des paramรจtres de **chemin** et de **requรชte** dans la mรชme *opรฉration de chemin*. **FastAPI** saura reconnaรฎtre chacun d'entre eux et rรฉcupรฉrer la bonne donnรฉe au bon endroit. -{* ../../docs_src/body/tutorial004.py hl[18] *} +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} Les paramรจtres de la fonction seront reconnus comme tel : @@ -149,14 +149,16 @@ Les paramรจtres de la fonction seront reconnus comme tel : * Si le paramรจtre est d'un **type singulier** (comme `int`, `float`, `str`, `bool`, etc.), il sera interprรฉtรฉ comme un paramรจtre de **requรชte**. * Si le paramรจtre est dรฉclarรฉ comme ayant pour type un **modรจle Pydantic**, il sera interprรฉtรฉ comme faisant partie du **corps** de la requรชte. -/// note +/// note | Remarque -**FastAPI** saura que la valeur de `q` n'est pas requise grรขce ร  la valeur par dรฉfaut `=None`. +**FastAPI** saura que la valeur de `q` n'est pas requise grรขce ร  la valeur par dรฉfaut `= None`. -Le type `Optional` dans `Optional[str]` n'est pas utilisรฉ par **FastAPI**, mais sera utile ร  votre รฉditeur pour amรฉliorer le support offert par ce dernier et dรฉtecter plus facilement des erreurs de type. +L'annotation de type `str | None` (Python 3.10+) ou `Union` dans `Union[str, None]` (Python 3.9+) n'est pas utilisรฉe par **FastAPI** pour dรฉterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par dรฉfaut `= None`. + +Mais ajouter ces annotations de type permettra ร  votre รฉditeur de vous offrir un meilleur support et de dรฉtecter des erreurs. /// -## Sans Pydantic +## Sans Pydantic { #without-pydantic } -Si vous ne voulez pas utiliser des modรจles Pydantic, vous pouvez aussi utiliser des paramรจtres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requรชte - Paramรจtres multiples](body-multiple-params.md){.internal-link target=_blank}. +Si vous ne voulez pas utiliser des modรจles Pydantic, vous pouvez aussi utiliser des paramรจtres de **Body**. Pour cela, allez voir la documentation sur [Corps de la requรชte - Paramรจtres multiples : Valeurs singuliรจres dans le corps](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/fr/docs/tutorial/debugging.md b/docs/fr/docs/tutorial/debugging.md index ab00fbdeb2..a88fa2b23f 100644 --- a/docs/fr/docs/tutorial/debugging.md +++ b/docs/fr/docs/tutorial/debugging.md @@ -1,14 +1,14 @@ -# Dรฉbogage +# Dรฉbogage { #debugging } Vous pouvez connecter le dรฉbogueur dans votre รฉditeur, par exemple avec Visual Studio Code ou PyCharm. -## Faites appel ร  `uvicorn` +## Appeler `uvicorn` { #call-uvicorn } Dans votre application FastAPI, importez et exรฉcutez directement `uvicorn` : -{* ../../docs_src/debugging/tutorial001.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} -### ร€ propos de `__name__ == "__main__"` +### ร€ propos de `__name__ == "__main__"` { #about-name-main } Le but principal de `__name__ == "__main__"` est d'avoir du code qui est exรฉcutรฉ lorsque votre fichier est appelรฉ avec : @@ -26,7 +26,7 @@ mais qui n'est pas appelรฉ lorsqu'un autre fichier l'importe, comme dans : from myapp import app ``` -#### Pour davantage de dรฉtails +#### Pour davantage de dรฉtails { #more-details } Imaginons que votre fichier s'appelle `myapp.py`. @@ -78,7 +78,7 @@ Pour plus d'informations, consultez dรฉbogueur +## Exรฉcuter votre code avec votre dรฉbogueur { #run-your-code-with-your-debugger } Parce que vous exรฉcutez le serveur Uvicorn directement depuis votre code, vous pouvez appeler votre programme Python (votre application FastAPI) directement depuis le dรฉbogueur. @@ -86,10 +86,10 @@ Parce que vous exรฉcutez le serveur Uvicorn directement depuis votre code, vous Par exemple, dans Visual Studio Code, vous pouvez : -- Cliquer sur l'onglet "Debug" de la barre d'activitรฉs de Visual Studio Code. -- "Add configuration...". -- Sรฉlectionnez "Python". -- Lancez le dรฉbogueur avec l'option "`Python: Current File (Integrated Terminal)`". +- Allez dans le panneau ยซ Debug ยป. +- ยซ Add configuration... ยป. +- Sรฉlectionnez ยซ Python ยป. +- Lancez le dรฉbogueur avec l'option ยซ Python: Current File (Integrated Terminal) ยป. Il dรฉmarrera alors le serveur avec votre code **FastAPI**, s'arrรชtera ร  vos points d'arrรชt, etc. @@ -101,8 +101,8 @@ Voici ร  quoi cela pourrait ressembler : Si vous utilisez Pycharm, vous pouvez : -- Ouvrir le menu "Run". -- Sรฉlectionnez l'option "Debug...". +- Ouvrez le menu ยซ Run ยป. +- Sรฉlectionnez l'option ยซ Debug... ยป. - Un menu contextuel s'affiche alors. - Sรฉlectionnez le fichier ร  dรฉboguer (dans ce cas, `main.py`). diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index 96ea56e622..b2693b3e5a 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -1,107 +1,122 @@ -# Dรฉmarrage +# Dรฉmarrage { #first-steps } -Le fichier **FastAPI** le plus simple possible pourrait ressembler ร  cela : +Le fichier **FastAPI** le plus simple possible pourrait ressembler ร  ceci : -{* ../../docs_src/first_steps/tutorial001.py *} +{* ../../docs_src/first_steps/tutorial001_py39.py *} -Copiez ce code dans un fichier nommรฉ `main.py`. +Copiez cela dans un fichier `main.py`. -Dรฉmarrez le serveur : +Dรฉmarrez le serveur en direct :
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. -``` + FastAPI Starting development server ๐Ÿš€ -
+ Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -/// note + module ๐Ÿ main.py -La commande `uvicorn main:app` fait rรฉfรฉrence ร  : + code Importing the FastAPI app object from the module with + the following code: -* `main` : le fichier `main.py` (le module Python). -* `app` : l'objet crรฉรฉ dans `main.py` via la ligne `app = FastAPI()`. -* `--reload` : l'option disant ร  uvicorn de redรฉmarrer le serveur ร  chaque changement du code. ร€ ne pas utiliser en production ! + from main import app -/// + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run -Vous devriez voir dans la console, une ligne semblable ร  la suivante : + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + + + +Dans la sortie, il y a une ligne semblable ร  : ```hl_lines="4" INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -Cette ligne montre l'URL par laquelle l'app est actuellement accessible, sur votre machine locale. +Cette ligne montre lโ€™URL oรน votre application est servie, sur votre machine locale. -### Allez voir le rรฉsultat +### Vรฉrifiez { #check-it } -Ouvrez votre navigateur ร  l'adresse
http://127.0.0.1:8000. +Ouvrez votre navigateur ร  lโ€™adresse http://127.0.0.1:8000. -Vous obtiendrez cette rรฉponse JSON : +Vous verrez la rรฉponse JSON suivante : ```JSON {"message": "Hello World"} ``` -### Documentation interactive de l'API +### Documentation interactive de lโ€™API { #interactive-api-docs } -Rendez-vous sur http://127.0.0.1:8000/docs. +Allez maintenant sur http://127.0.0.1:8000/docs. -Vous verrez la documentation interactive de l'API gรฉnรฉrรฉe automatiquement (via Swagger UI) : +Vous verrez la documentation interactive de lโ€™API gรฉnรฉrรฉe automatiquement (fournie par Swagger UI) : ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### Documentation alternative +### Documentation alternative de lโ€™API { #alternative-api-docs } -Ensuite, rendez-vous sur http://127.0.0.1:8000/redoc. +Et maintenant, allez sur http://127.0.0.1:8000/redoc. -Vous y verrez la documentation alternative (via ReDoc) : +Vous verrez la documentation automatique alternative (fournie par ReDoc) : ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } -**FastAPI** gรฉnรจre un "schรฉma" contenant toute votre API dans le standard de dรฉfinition d'API **OpenAPI**. +**FastAPI** gรฉnรจre un ยซ schรฉma ยป contenant toute votre API en utilisant le standard **OpenAPI** pour dรฉfinir des API. -#### "Schรฉma" +#### ยซ Schรฉma ยป { #schema } -Un "schรฉma" est une dรฉfinition ou une description de quelque chose. Pas le code qui l'implรฉmente, uniquement une description abstraite. +Un ยซ schรฉma ยป est une dรฉfinition ou une description de quelque chose. Pas le code qui lโ€™implรฉmente, mais uniquement une description abstraite. -#### "Schรฉma" d'API +#### ยซ Schรฉma ยป dโ€™API { #api-schema } Ici, OpenAPI est une spรฉcification qui dicte comment dรฉfinir le schรฉma de votre API. -Le schรฉma inclut les chemins de votre API, les paramรจtres potentiels de chaque chemin, etc. - -#### "Schรฉma" de donnรฉes +Cette dรฉfinition de schรฉma inclut les chemins de votre API, les paramรจtres possibles quโ€™ils prennent, etc. -Le terme "schรฉma" peut aussi faire rรฉfรฉrence ร  la forme de la donnรฉe, comme un contenu JSON. +#### ยซ Schรฉma ยป de donnรฉes { #data-schema } -Dans ce cas, cela signifierait les attributs JSON, ainsi que les types de ces attributs, etc. +Le terme ยซ schรฉma ยป peut รฉgalement faire rรฉfรฉrence ร  la forme dโ€™une donnรฉe, comme un contenu JSON. -#### OpenAPI et JSON Schema +Dans ce cas, cela dรฉsignerait les attributs JSON, ainsi que leurs types, etc. -**OpenAPI** dรฉfinit un schรฉma d'API pour votre API. Il inclut des dรฉfinitions (ou "schรฉmas") de la donnรฉe envoyรฉe et reรงue par votre API en utilisant **JSON Schema**, le standard des schรฉmas de donnรฉes JSON. +#### OpenAPI et JSON Schema { #openapi-and-json-schema } -#### Allez voir `openapi.json` +OpenAPI dรฉfinit un schรฉma dโ€™API pour votre API. Et ce schรฉma inclut des dรฉfinitions (ou ยซ schรฉmas ยป) des donnรฉes envoyรฉes et reรงues par votre API en utilisant **JSON Schema**, le standard pour les schรฉmas de donnรฉes JSON. -Si vous รชtes curieux d'ร  quoi ressemble le schรฉma brut **OpenAPI**, **FastAPI** gรฉnรจre automatiquement un (schรฉma) JSON avec les descriptions de toute votre API. +#### Voir le `openapi.json` { #check-the-openapi-json } -Vous pouvez le voir directement ร  cette adresse : http://127.0.0.1:8000/openapi.json. +Si vous รชtes curieux de voir ร  quoi ressemble le schรฉma OpenAPI brut, FastAPI gรฉnรจre automatiquement un JSON (schรฉma) avec les descriptions de toute votre API. -Le schรฉma devrait ressembler ร  ceci : +Vous pouvez le voir directement ร  lโ€™adresse : http://127.0.0.1:8000/openapi.json. +Il affichera un JSON commenรงant par quelque chose comme : ```JSON { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" @@ -120,79 +135,87 @@ Le schรฉma devrait ressembler ร  ceci : ... ``` -#### ร€ quoi sert OpenAPI +#### ร€ quoi sert OpenAPI { #what-is-openapi-for } -Le schรฉma **OpenAPI** est ce qui alimente les deux systรจmes de documentation interactive. +Le schรฉma OpenAPI est ce qui alimente les deux systรจmes de documentation interactive inclus. -Et il existe des dizaines d'alternatives, toutes basรฉes sur **OpenAPI**. Vous pourriez facilement ajouter n'importe laquelle de ces alternatives ร  votre application **FastAPI**. +Et il existe des dizaines dโ€™alternatives, toutes basรฉes sur OpenAPI. Vous pourriez facilement ajouter nโ€™importe laquelle de ces alternatives ร  votre application construite avec **FastAPI**. -Vous pourriez aussi l'utiliser pour gรฉnรฉrer du code automatiquement, pour les clients qui communiquent avec votre API. Comme par exemple, des applications frontend, mobiles ou IOT. +Vous pourriez รฉgalement lโ€™utiliser pour gรฉnรฉrer du code automatiquement, pour les clients qui communiquent avec votre API. Par exemple, des applications frontend, mobiles ou IoT. -## Rรฉcapitulatif, รฉtape par รฉtape +### Dรฉployer votre application (optionnel) { #deploy-your-app-optional } -### ร‰tape 1 : import `FastAPI` +Vous pouvez, si vous le souhaitez, dรฉployer votre application FastAPI sur FastAPI Cloud, allez rejoindre la liste dโ€™attente si ce nโ€™est pas dรฉjร  fait. ๐Ÿš€ -{* ../../docs_src/first_steps/tutorial001.py hl[1] *} +Si vous avez dรฉjร  un compte **FastAPI Cloud** (nous vous avons invitรฉ depuis la liste dโ€™attente ๐Ÿ˜‰), vous pouvez dรฉployer votre application avec une seule commande. -`FastAPI` est une classe Python qui fournit toutes les fonctionnalitรฉs nรฉcessaires au lancement de votre API. +Avant de dรฉployer, vous devez vous assurer que vous รชtes connectรฉ : -/// note | Dรฉtails techniques - -`FastAPI` est une classe hรฉritant directement de `Starlette`. - -Vous pouvez donc aussi utiliser toutes les fonctionnalitรฉs de Starlette depuis `FastAPI`. - -/// - -### ร‰tape 2 : crรฉer une "instance" `FastAPI` +
-{* ../../docs_src/first_steps/tutorial001.py hl[3] *} +```console +$ fastapi login -Ici la variable `app` sera une "instance" de la classe `FastAPI`. +You are logged in to FastAPI Cloud ๐Ÿš€ +``` -Ce sera le point principal d'interaction pour crรฉer toute votre API. +
-Cette `app` est la mรชme que celle ร  laquelle fait rรฉfรฉrence `uvicorn` dans la commande : +Puis dรฉployez votre application :
```console -$ uvicorn main:app --reload +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev ```
-Si vous crรฉez votre app avec : +Cโ€™est tout ! Vous pouvez maintenant accรฉder ร  votre application ร  cette URL. โœจ -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} +## Rรฉcapitulatif, รฉtape par รฉtape { #recap-step-by-step } -Et la mettez dans un fichier `main.py`, alors vous appelleriez `uvicorn` avec : +### ร‰tape 1 : importer `FastAPI` { #step-1-import-fastapi } -
+{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} -```console -$ uvicorn main:my_awesome_api --reload +`FastAPI` est une classe Python qui fournit toutes les fonctionnalitรฉs nรฉcessaires ร  votre API. -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` +/// note | Dรฉtails techniques -
+`FastAPI` est une classe qui hรฉrite directement de `Starlette`. + +Vous pouvez donc aussi utiliser toutes les fonctionnalitรฉs de Starlette avec `FastAPI`. + +/// + +### ร‰tape 2 : crรฉer une ยซ instance ยป `FastAPI` { #step-2-create-a-fastapi-instance } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} + +Ici, la variable `app` sera une ยซ instance ยป de la classe `FastAPI`. + +Ce sera le point principal dโ€™interaction pour crรฉer toute votre API. -### ร‰tape 3: crรฉer une *opรฉration de chemin* +### ร‰tape 3 : crรฉer un ยซ chemin dโ€™accรจs ยป { #step-3-create-a-path-operation } -#### Chemin +#### Chemin { #path } -Chemin, ou "path" fait rรฉfรฉrence ici ร  la derniรจre partie de l'URL dรฉmarrant au premier `/`. +ยซ Chemin ยป fait ici rรฉfรฉrence ร  la derniรจre partie de lโ€™URL ร  partir du premier `/`. -Donc, dans un URL tel que : +Donc, dans une URL telle que : ``` https://example.com/items/foo ``` -...le "path" serait : +... le chemin serait : ``` /items/foo @@ -200,66 +223,67 @@ https://example.com/items/foo /// info -Un chemin, ou "path" est aussi souvent appelรฉ route ou "endpoint". +Un ยซ chemin ยป est aussi couramment appelรฉ ยซ endpoint ยป ou ยซ route ยป. /// -#### Opรฉration +Lors de la crรฉation dโ€™une API, le ยซ chemin ยป est la maniรจre principale de sรฉparer les ยซ prรฉoccupations ยป et les ยซ ressources ยป. -"Opรฉration" fait rรฉfรฉrence ร  une des "mรฉthodes" HTTP. +#### Opรฉration { #operation } -Une de : +ยซ Opรฉration ยป fait ici rรฉfรฉrence ร  lโ€™une des ยซ mรฉthodes ยป HTTP. + +Lโ€™une de : * `POST` * `GET` * `PUT` * `DELETE` -...ou une des plus exotiques : +... et les plus exotiques : * `OPTIONS` * `HEAD` * `PATCH` * `TRACE` -Dans le protocol HTTP, vous pouvez communiquer avec chaque chemin en utilisant une (ou plus) de ces "mรฉthodes". +Dans le protocole HTTP, vous pouvez communiquer avec chaque chemin en utilisant une (ou plusieurs) de ces ยซ mรฉthodes ยป. --- -En construisant des APIs, vous utilisez gรฉnรฉralement ces mรฉthodes HTTP spรฉcifiques pour effectuer une action prรฉcise. - -Gรฉnรฉralement vous utilisez : +En construisant des APIs, vous utilisez normalement ces mรฉthodes HTTP spรฉcifiques pour effectuer une action prรฉcise. -* `POST` : pour crรฉer de la donnรฉe. -* `GET` : pour lire de la donnรฉe. -* `PUT` : pour mettre ร  jour de la donnรฉe. -* `DELETE` : pour supprimer de la donnรฉe. +En gรฉnรฉral, vous utilisez : -Donc, dans **OpenAPI**, chaque mรฉthode HTTP est appelรฉe une "opรฉration". +* `POST` : pour crรฉer des donnรฉes. +* `GET` : pour lire des donnรฉes. +* `PUT` : pour mettre ร  jour des donnรฉes. +* `DELETE` : pour supprimer des donnรฉes. -Nous allons donc aussi appeler ces derniรจres des "**opรฉrations**". +Donc, dans OpenAPI, chacune des mรฉthodes HTTP est appelรฉe une ยซ opรฉration ยป. +Nous allons donc aussi les appeler ยซ opรฉrations ยป. -#### Dรฉfinir un *dรฉcorateur d'opรฉration de chemin* +#### Dรฉfinir un ยซ dรฉcorateur de chemin dโ€™accรจs ยป { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} -Le `@app.get("/")` dit ร  **FastAPI** que la fonction en dessous est chargรฉe de gรฉrer les requรชtes qui vont sur : +Le `@app.get("/")` indique ร  **FastAPI** que la fonction juste en dessous est chargรฉe de gรฉrer les requรชtes qui vont versโ€ฏ: * le chemin `/` -* en utilisant une opรฉration get +* en utilisant une get opรฉration /// info | `@dรฉcorateur` Info -Cette syntaxe `@something` en Python est appelรฉe un "dรฉcorateur". +Cette syntaxe `@something` en Python est appelรฉe un ยซ dรฉcorateur ยป. -Vous la mettez au dessus d'une fonction. Comme un joli chapeau dรฉcoratif (j'imagine que ce terme vient de lร  ๐Ÿคท๐Ÿปโ€โ™‚). +Vous la mettez au-dessus dโ€™une fonction. Comme un joli chapeau dรฉcoratif (jโ€™imagine que cโ€™est de lร  que vient le terme ๐Ÿคท๐Ÿปโ€โ™‚). -Un "dรฉcorateur" prend la fonction en dessous et en fait quelque chose. +Un ยซ dรฉcorateur ยป prend la fonction en dessous et fait quelque chose avec. -Dans notre cas, ce dรฉcorateur dit ร  **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec l'**opรฉration** `get`. +Dans notre cas, ce dรฉcorateur indique ร  **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec une **opรฉration** `get`. -C'est le "**dรฉcorateur d'opรฉration de chemin**". +Cโ€™est le ยซ dรฉcorateur de chemin dโ€™accรจs ยป. /// @@ -269,7 +293,7 @@ Vous pouvez aussi utiliser les autres opรฉrations : * `@app.put()` * `@app.delete()` -Tout comme celles les plus exotiques : +Ainsi que les plus exotiques : * `@app.options()` * `@app.head()` @@ -278,58 +302,79 @@ Tout comme celles les plus exotiques : /// tip | Astuce -Vous รชtes libres d'utiliser chaque opรฉration (mรฉthode HTTP) comme vous le dรฉsirez. +Vous รชtes libre dโ€™utiliser chaque opรฉration (mรฉthode HTTP) comme vous le souhaitez. -**FastAPI** n'impose pas de sens spรฉcifique ร  chacune d'elle. +**FastAPI** nโ€™impose aucune signification spรฉcifique. -Les informations qui sont prรฉsentรฉes ici forment une directive gรฉnรฉrale, pas des obligations. +Les informations ici sont prรฉsentรฉes comme des lignes directrices, pas comme une obligation. -Par exemple, quand l'on utilise **GraphQL**, toutes les actions sont effectuรฉes en utilisant uniquement des opรฉrations `POST`. +Par exemple, lorsque vous utilisez GraphQL, vous effectuez normalement toutes les actions en utilisant uniquement des opรฉrations `POST`. /// -### ร‰tape 4 : dรฉfinir la **fonction de chemin**. +### ร‰tape 4 : dรฉfinir la **fonction de chemin dโ€™accรจs** { #step-4-define-the-path-operation-function } -Voici notre "**fonction de chemin**" (ou fonction d'opรฉration de chemin) : +Voici notre ยซ fonction de chemin dโ€™accรจs ยป : * **chemin** : `/`. * **opรฉration** : `get`. -* **fonction** : la fonction sous le "dรฉcorateur" (sous `@app.get("/")`). +* **fonction** : la fonction sous le ยซ dรฉcorateur ยป (sous `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} -C'est une fonction Python. +Cโ€™est une fonction Python. -Elle sera appelรฉe par **FastAPI** quand une requรชte sur l'URL `/` sera reรงue via une opรฉration `GET`. +Elle sera appelรฉe par **FastAPI** chaque fois quโ€™il recevra une requรชte vers lโ€™URL ยซ / ยป en utilisant une opรฉration `GET`. -Ici, c'est une fonction asynchrone (dรฉfinie avec `async def`). +Dans ce cas, cโ€™est une fonction `async`. --- -Vous pourriez aussi la dรฉfinir comme une fonction classique plutรดt qu'avec `async def` : +Vous pouvez aussi la dรฉfinir comme une fonction normale au lieu de `async def` : -{* ../../docs_src/first_steps/tutorial003.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} /// note -Si vous ne connaissez pas la diffรฉrence, allez voir la section [Concurrence : *"Vous รชtes pressรฉs ?"*](../async.md#vous-etes-presses){.internal-link target=_blank}. +Si vous ne connaissez pas la diffรฉrence, consultez [Asynchrone : ยซ Pressรฉ ? ยป](../async.md#in-a-hurry){.internal-link target=_blank}. /// -### ร‰tape 5 : retourner le contenu +### ร‰tape 5 : retourner le contenu { #step-5-return-the-content } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} + +Vous pouvez retourner un `dict`, une `list`, des valeurs uniques comme `str`, `int`, etc. + +Vous pouvez รฉgalement retourner des modรจles Pydantic (vous en verrez plus ร  ce sujet plus tard). + +Il existe de nombreux autres objets et modรจles qui seront automatiquement convertis en JSON (y compris des ORM, etc.). Essayez dโ€™utiliser vos favoris, il est fort probable quโ€™ils soient dรฉjร  pris en charge. + +### ร‰tape 6 : le dรฉployer { #step-6-deploy-it } + +Dรฉployez votre application sur **FastAPI Cloud** avec une seule commande : `fastapi deploy`. ๐ŸŽ‰ + +#### ร€ propos de FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** est construit par le mรชme auteur et lโ€™รฉquipe derriรจre **FastAPI**. + +Il simplifie le processus de **construction**, de **dรฉploiement** et dโ€™**accรจs** ร  une API avec un minimum dโ€™effort. + +Il apporte la mรชme **expรฉrience dรฉveloppeur** de crรฉation dโ€™applications avec FastAPI au **dรฉploiement** dans le cloud. ๐ŸŽ‰ -{* ../../docs_src/first_steps/tutorial001.py hl[8] *} +FastAPI Cloud est le sponsor principal et le financeur des projets open source *FastAPI and friends*. โœจ -Vous pouvez retourner un dictionnaire (`dict`), une liste (`list`), des valeurs seules comme des chaines de caractรจres (`str`) et des entiers (`int`), etc. +#### Dรฉployer sur dโ€™autres fournisseurs cloud { #deploy-to-other-cloud-providers } -Vous pouvez aussi retourner des models **Pydantic** (qui seront dรฉtaillรฉs plus tard). +FastAPI est open source et basรฉ sur des standards. Vous pouvez dรฉployer des applications FastAPI chez nโ€™importe quel fournisseur cloud de votre choix. -Il y a de nombreux autres objets et modรจles qui seront automatiquement convertis en JSON. Essayez d'utiliser vos favoris, il est fort probable qu'ils soient dรฉjร  supportรฉs. +Suivez les guides de votre fournisseur cloud pour y dรฉployer des applications FastAPI. ๐Ÿค“ -## Rรฉcapitulatif +## Rรฉcapitulatif { #recap } * Importez `FastAPI`. -* Crรฉez une instance d'`app`. -* Ajoutez une **dรฉcorateur d'opรฉration de chemin** (tel que `@app.get("/")`). -* Ajoutez une **fonction de chemin** (telle que `def root(): ...` comme ci-dessus). -* Lancez le serveur de dรฉveloppement (avec `uvicorn main:app --reload`). +* Crรฉez une instance `app`. +* ร‰crivez un **dรฉcorateur de chemin dโ€™accรจs** avec des dรฉcorateurs comme `@app.get("/")`. +* Dรฉfinissez une **fonction de chemin dโ€™accรจs** ; par exemple, `def root(): ...`. +* Exรฉcutez le serveur de dรฉveloppement avec la commande `fastapi dev`. +* Dรฉployez รฉventuellement votre application avec `fastapi deploy`. diff --git a/docs/fr/docs/tutorial/index.md b/docs/fr/docs/tutorial/index.md index 83cc5f9e88..0251b9b4b2 100644 --- a/docs/fr/docs/tutorial/index.md +++ b/docs/fr/docs/tutorial/index.md @@ -1,29 +1,53 @@ -# Tutoriel - Guide utilisateur - Introduction +# Tutoriel - Guide utilisateur { #tutorial-user-guide } Ce tutoriel vous montre comment utiliser **FastAPI** avec la plupart de ses fonctionnalitรฉs, รฉtape par รฉtape. -Chaque section s'appuie progressivement sur les prรฉcรฉdentes, mais elle est structurรฉe de maniรจre ร  sรฉparer les sujets, afin que vous puissiez aller directement ร  l'un d'entre eux pour rรฉsoudre vos besoins spรฉcifiques en matiรจre d'API. +Chaque section s'appuie progressivement sur les prรฉcรฉdentes, mais elle est structurรฉe de maniรจre ร  sรฉparer les sujets, afin que vous puissiez aller directement ร  l'un d'entre eux pour rรฉpondre ร  vos besoins spรฉcifiques d'API. -Il est รฉgalement conรงu pour fonctionner comme une rรฉfรฉrence future. +Il est รฉgalement conรงu pour servir de rรฉfรฉrence ultรฉrieure, afin que vous puissiez revenir voir exactement ce dont vous avez besoin. -Vous pouvez donc revenir et voir exactement ce dont vous avez besoin. - -## Exรฉcuter le code +## Exรฉcuter le code { #run-the-code } Tous les blocs de code peuvent รชtre copiรฉs et utilisรฉs directement (il s'agit en fait de fichiers Python testรฉs). -Pour exรฉcuter l'un de ces exemples, copiez le code dans un fichier `main.py`, et commencez `uvicorn` avec : +Pour exรฉcuter l'un de ces exemples, copiez le code dans un fichier `main.py`, et dรฉmarrez `fastapi dev` avec :
```console -$ uvicorn main:app --reload +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
@@ -34,45 +58,33 @@ L'utiliser dans votre รฉditeur est ce qui vous montre vraiment les avantages de --- -## Installer FastAPI +## Installer FastAPI { #install-fastapi } La premiรจre รฉtape consiste ร  installer FastAPI. -Pour le tutoriel, vous voudrez peut-รชtre l'installer avec toutes les dรฉpendances et fonctionnalitรฉs optionnelles : +Assurez-vous de crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis **d'installer FastAPI** :
```console -$ pip install fastapi[all] +$ pip install "fastapi[standard]" ---> 100% ```
-... qui comprend รฉgalement `uvicorn`, que vous pouvez utiliser comme serveur pour exรฉcuter votre code. - -/// note - -Vous pouvez รฉgalement l'installer piรจce par piรจce. +/// note | Remarque -C'est ce que vous feriez probablement une fois que vous voudrez dรฉployer votre application en production : +Lorsque vous installez avec `pip install "fastapi[standard]"` cela inclut des dรฉpendances standard optionnelles par dรฉfaut, y compris `fastapi-cloud-cli`, qui vous permet de dรฉployer sur FastAPI Cloud. -``` -pip install fastapi -``` - -Installez รฉgalement `uvicorn` pour qu'il fonctionne comme serveur : - -``` -pip install uvicorn -``` +Si vous ne souhaitez pas avoir ces dรฉpendances optionnelles, vous pouvez ร  la place installer `pip install fastapi`. -Et la mรชme chose pour chacune des dรฉpendances facultatives que vous voulez utiliser. +Si vous souhaitez installer les dรฉpendances standard mais sans `fastapi-cloud-cli`, vous pouvez installer avec `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. /// -## Guide utilisateur avancรฉ +## Guide d'utilisation avancรฉ { #advanced-user-guide } Il existe รฉgalement un **Guide d'utilisation avancรฉ** que vous pouvez lire plus tard aprรจs ce **Tutoriel - Guide d'utilisation**. diff --git a/docs/fr/docs/tutorial/path-params-numeric-validations.md b/docs/fr/docs/tutorial/path-params-numeric-validations.md index 3f3280e640..c80710777f 100644 --- a/docs/fr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/fr/docs/tutorial/path-params-numeric-validations.md @@ -1,8 +1,8 @@ -# Paramรจtres de chemin et validations numรฉriques +# Paramรจtres de chemin et validations numรฉriques { #path-parameters-and-numeric-validations } De la mรชme faรงon que vous pouvez dรฉclarer plus de validations et de mรฉtadonnรฉes pour les paramรจtres de requรชte avec `Query`, vous pouvez dรฉclarer le mรชme type de validations et de mรฉtadonnรฉes pour les paramรจtres de chemin avec `Path`. -## Importer Path +## Importer `Path` { #import-path } Tout d'abord, importez `Path` de `fastapi`, et importez `Annotated` : @@ -14,11 +14,11 @@ FastAPI a ajoutรฉ le support pour `Annotated` (et a commencรฉ ร  le recommander) Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant d'utiliser `Annotated`. -Assurez-vous de [Mettre ร  jour la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ร  la version 0.95.1 ร  minima avant d'utiliser `Annotated`. +Assurez-vous de [Mettre ร  niveau la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ร  la version 0.95.1 ร  minima avant d'utiliser `Annotated`. /// -## Dรฉclarer des mรฉtadonnรฉes +## Dรฉclarer des mรฉtadonnรฉes { #declare-metadata } Vous pouvez dรฉclarer les mรชmes paramรจtres que pour `Query`. @@ -26,15 +26,15 @@ Par exemple, pour dรฉclarer une valeur de mรฉtadonnรฉe `title` pour le paramรจtr {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} -/// note +/// note | Remarque Un paramรจtre de chemin est toujours requis car il doit faire partie du chemin. Mรชme si vous l'avez dรฉclarรฉ avec `None` ou dรฉfini une valeur par dรฉfaut, cela ne changerait rien, il serait toujours requis. /// -## Ordonnez les paramรจtres comme vous le souhaitez +## Ordonner les paramรจtres comme vous le souhaitez { #order-the-parameters-as-you-need } -/// tip +/// tip | Astuce Ce n'est probablement pas aussi important ou nรฉcessaire si vous utilisez `Annotated`. @@ -46,7 +46,7 @@ Et vous n'avez pas besoin de dรฉclarer autre chose pour ce paramรจtre, donc vous Mais vous avez toujours besoin d'utiliser `Path` pour le paramรจtre de chemin `item_id`. Et vous ne voulez pas utiliser `Annotated` pour une raison quelconque. -Python se plaindra si vous mettez une valeur avec une "dรฉfaut" avant une valeur qui n'a pas de "dรฉfaut". +Python se plaindra si vous mettez une valeur avec une ยซ valeur par dรฉfaut ยป avant une valeur qui n'a pas de ยซ valeur par dรฉfaut ยป. Mais vous pouvez les rรฉorganiser, et avoir la valeur sans dรฉfaut (le paramรจtre de requรชte `q`) en premier. @@ -54,15 +54,15 @@ Cela n'a pas d'importance pour **FastAPI**. Il dรฉtectera les paramรจtres par le Ainsi, vous pouvez dรฉclarer votre fonction comme suit : -{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} Mais gardez ร  l'esprit que si vous utilisez `Annotated`, vous n'aurez pas ce problรจme, cela n'aura pas d'importance car vous n'utilisez pas les valeurs par dรฉfaut des paramรจtres de fonction pour `Query()` ou `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} -## Ordonnez les paramรจtres comme vous le souhaitez (astuces) +## Ordonner les paramรจtres comme vous le souhaitez, astuces { #order-the-parameters-as-you-need-tricks } -/// tip +/// tip | Astuce Ce n'est probablement pas aussi important ou nรฉcessaire si vous utilisez `Annotated`. @@ -77,38 +77,29 @@ Si vous voulez : * les avoir dans un ordre diffรฉrent * ne pas utiliser `Annotated` -...Python a une petite syntaxe spรฉciale pour cela. +... Python a une petite syntaxe spรฉciale pour cela. Passez `*`, comme premier paramรจtre de la fonction. Python ne fera rien avec ce `*`, mais il saura que tous les paramรจtres suivants doivent รชtre appelรฉs comme arguments "mots-clรฉs" (paires clรฉ-valeur), รฉgalement connus sous le nom de kwargs. Mรชme s'ils n'ont pas de valeur par dรฉfaut. -{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} -# Avec `Annotated` +### Mieux avec `Annotated` { #better-with-annotated } Gardez ร  l'esprit que si vous utilisez `Annotated`, comme vous n'utilisez pas les valeurs par dรฉfaut des paramรจtres de fonction, vous n'aurez pas ce problรจme, et vous n'aurez probablement pas besoin d'utiliser `*`. {* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} -## Validations numรฉriques : supรฉrieur ou รฉgal +## Validations numรฉriques : supรฉrieur ou รฉgal { #number-validations-greater-than-or-equal } Avec `Query` et `Path` (et d'autres que vous verrez plus tard) vous pouvez dรฉclarer des contraintes numรฉriques. -Ici, avec `ge=1`, `item_id` devra รชtre un nombre entier "`g`reater than or `e`qual" ร  `1`. +Ici, avec `ge=1`, `item_id` devra รชtre un nombre entier ยซ `g`reater than or `e`qual ยป ร  `1`. {* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} -## Validations numรฉriques : supรฉrieur ou รฉgal et infรฉrieur ou รฉgal - -La mรชme chose s'applique pour : - -* `gt` : `g`reater `t`han -* `le` : `l`ess than or `e`qual - -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} - -## Validations numรฉriques : supรฉrieur et infรฉrieur ou รฉgal +## Validations numรฉriques : supรฉrieur et infรฉrieur ou รฉgal { #number-validations-greater-than-and-less-than-or-equal } La mรชme chose s'applique pour : @@ -117,7 +108,7 @@ La mรชme chose s'applique pour : {* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} -## Validations numรฉriques : flottants, supรฉrieur et infรฉrieur +## Validations numรฉriques : flottants, supรฉrieur et infรฉrieur { #number-validations-floats-greater-than-and-less-than } Les validations numรฉriques fonctionnent รฉgalement pour les valeurs `float`. @@ -129,7 +120,7 @@ Et la mรชme chose pour lt. {* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} -## Pour rรฉsumer +## Pour rรฉsumer { #recap } Avec `Query`, `Path` (et d'autres que vous verrez plus tard) vous pouvez dรฉclarer des mรฉtadonnรฉes et des validations de chaรฎnes de la mรชme maniรจre qu'avec les [Paramรจtres de requรชte et validations de chaรฎnes](query-params-str-validations.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/tutorial/path-params.md b/docs/fr/docs/tutorial/path-params.md index 71c96b18ee..3b2955a95d 100644 --- a/docs/fr/docs/tutorial/path-params.md +++ b/docs/fr/docs/tutorial/path-params.md @@ -1,205 +1,196 @@ -# Paramรจtres de chemin +# Paramรจtres de chemin { #path-parameters } -Vous pouvez dรฉclarer des "paramรจtres" ou "variables" de chemin avec la mรชme syntaxe que celle utilisรฉe par le -formatage de chaรฎne Python : +Vous pouvez dรฉclarer des ยซ paramรจtres ยป ou ยซ variables ยป de chemin avec la mรชme syntaxe utilisรฉe par les chaรฎnes de format Python : +{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} -{* ../../docs_src/path_params/tutorial001.py hl[6:7] *} +La valeur du paramรจtre de chemin `item_id` sera transmise ร  votre fonction dans l'argument `item_id`. -La valeur du paramรจtre `item_id` sera transmise ร  la fonction dans l'argument `item_id`. - -Donc, si vous exรฉcutez cet exemple et allez sur http://127.0.0.1:8000/items/foo, -vous verrez comme rรฉponse : +Donc, si vous exรฉcutez cet exemple et allez sur http://127.0.0.1:8000/items/foo, vous verrez comme rรฉponse : ```JSON {"item_id":"foo"} ``` -## Paramรจtres de chemin typรฉs - -Vous pouvez dรฉclarer le type d'un paramรจtre de chemin dans la fonction, en utilisant les annotations de type Python : +## Paramรจtres de chemin typรฉs { #path-parameters-with-types } +Vous pouvez dรฉclarer le type d'un paramรจtre de chemin dans la fonction, en utilisant les annotations de type Python standard : -{* ../../docs_src/path_params/tutorial002.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} Ici, `item_id` est dรฉclarรฉ comme `int`. -/// check | vรฉrifier +/// check | Vรฉrifications -Ceci vous permettra d'obtenir des fonctionnalitรฉs de l'รฉditeur dans votre fonction, telles -que des vรฉrifications d'erreur, de l'auto-complรฉtion, etc. +Cela vous apporte la prise en charge par l'รฉditeur dans votre fonction, avec vรฉrifications d'erreurs, autocomplรฉtion, etc. /// -## Conversion de donnรฉes +## Conversion de donnรฉes { #data-conversion } -Si vous exรฉcutez cet exemple et allez sur http://127.0.0.1:8000/items/3, vous aurez comme rรฉponse : +Si vous exรฉcutez cet exemple et ouvrez votre navigateur sur http://127.0.0.1:8000/items/3, vous verrez comme rรฉponse : ```JSON {"item_id":3} ``` -/// check | vรฉrifier +/// check | Vรฉrifications -Comme vous l'avez remarquรฉ, la valeur reรงue par la fonction (et renvoyรฉe ensuite) est `3`, -en tant qu'entier (`int`) Python, pas la chaรฎne de caractรจres (`string`) `"3"`. +Remarquez que la valeur reรงue par votre fonction (et renvoyรฉe) est `3`, en tant qu'entier (`int`) Python, pas la chaรฎne de caractรจres ยซ 3 ยป. -Grรขce aux dรฉclarations de types, **FastAPI** fournit du -"parsing" automatique. +Ainsi, avec cette dรฉclaration de type, **FastAPI** vous fournit automatiquement le ยซ parsing ยป de la requรชte. /// -## Validation de donnรฉes +## Validation de donnรฉes { #data-validation } -Si vous allez sur http://127.0.0.1:8000/items/foo, vous aurez une belle erreur HTTP : +Mais si vous allez dans le navigateur sur http://127.0.0.1:8000/items/foo, vous verrez une belle erreur HTTP : ```JSON { - "detail": [ - { - "loc": [ - "path", - "item_id" - ], - "msg": "value is not a valid integer", - "type": "type_error.integer" - } - ] + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] } ``` -car le paramรจtre de chemin `item_id` possรจde comme valeur `"foo"`, qui ne peut pas รชtre convertie en entier (`int`). - -La mรชme erreur se produira si vous passez un nombre flottant (`float`) et non un entier, comme ici -http://127.0.0.1:8000/items/4.2. +car le paramรจtre de chemin `item_id` a pour valeur ยซ foo ยป, qui n'est pas un `int`. +La mรชme erreur apparaรฎtrait si vous fournissiez un `float` au lieu d'un `int`, comme ici : http://127.0.0.1:8000/items/4.2 -/// check | vรฉrifier +/// check | Vรฉrifications -Donc, avec ces mรชmes dรฉclarations de type Python, **FastAPI** vous fournit de la validation de donnรฉes. +Ainsi, avec la mรชme dรฉclaration de type Python, **FastAPI** vous fournit la validation de donnรฉes. -Notez que l'erreur mentionne le point exact oรน la validation n'a pas rรฉussi. +Remarquez que l'erreur indique clairement l'endroit exact oรน la validation n'a pas rรฉussi. -Ce qui est incroyablement utile au moment de dรฉvelopper et dรฉbugger du code qui interagit avec votre API. +C'est incroyablement utile lors du dรฉveloppement et du dรฉbogage du code qui interagit avec votre API. /// -## Documentation +## Documentation { #documentation } -Et quand vous vous rendez sur http://127.0.0.1:8000/docs, vous verrez la -documentation gรฉnรฉrรฉe automatiquement et interactive : +Et lorsque vous ouvrez votre navigateur sur http://127.0.0.1:8000/docs, vous verrez une documentation d'API automatique et interactive comme : -/// info +/// check | Vรฉrifications -ร€ nouveau, en utilisant uniquement les dรฉclarations de type Python, **FastAPI** vous fournit automatiquement une documentation interactive (via Swagger UI). +ร€ nouveau, simplement avec cette mรชme dรฉclaration de type Python, **FastAPI** vous fournit une documentation interactive automatique (intรฉgrant Swagger UI). -On voit bien dans la documentation que `item_id` est dรฉclarรฉ comme entier. +Remarquez que le paramรจtre de chemin est dรฉclarรฉ comme entier. /// -## Les avantages d'avoir une documentation basรฉe sur une norme, et la documentation alternative. +## Les avantages d'une norme, documentation alternative { #standards-based-benefits-alternative-documentation } -Le schรฉma gรฉnรฉrรฉ suivant la norme OpenAPI, -il existe de nombreux outils compatibles. +Et comme le schรฉma gรฉnรฉrรฉ suit la norme OpenAPI, il existe de nombreux outils compatibles. -Grรขce ร  cela, **FastAPI** lui-mรชme fournit une documentation alternative (utilisant ReDoc), qui peut รชtre lue -sur http://127.0.0.1:8000/redoc : +Grรขce ร  cela, **FastAPI** fournit lui-mรชme une documentation d'API alternative (utilisant ReDoc), accessible sur http://127.0.0.1:8000/redoc : -De la mรชme faรงon, il existe bien d'autres outils compatibles, y compris des outils de gรฉnรฉration de code -pour de nombreux langages. +De la mรชme faรงon, il existe de nombreux outils compatibles, y compris des outils de gรฉnรฉration de code pour de nombreux langages. -## Pydantic +## Pydantic { #pydantic } -Toute la validation de donnรฉes est effectuรฉ en arriรจre-plan avec Pydantic, -dont vous bรฉnรฉficierez de tous les avantages. Vous savez donc que vous รชtes entre de bonnes mains. +Toute la validation de donnรฉes est effectuรฉe sous le capot par Pydantic, vous en bรฉnรฉficiez donc pleinement. Vous savez ainsi que vous รชtes entre de bonnes mains. -## L'ordre importe +Vous pouvez utiliser les mรชmes dรฉclarations de type avec `str`, `float`, `bool` et de nombreux autres types de donnรฉes complexes. -Quand vous crรฉez des *fonctions de chemins*, vous pouvez vous retrouver dans une situation oรน vous avez un chemin fixe. +Plusieurs d'entre eux sont explorรฉs dans les prochains chapitres du tutoriel. -Tel que `/users/me`, disons pour rรฉcupรฉrer les donnรฉes sur l'utilisateur actuel. +## L'ordre importe { #order-matters } -Et vous avez un second chemin : `/users/{user_id}` pour rรฉcupรฉrer de la donnรฉe sur un utilisateur spรฉcifique grรขce ร  son identifiant d'utilisateur +Quand vous crรฉez des *chemins d'accรจs*, vous pouvez vous retrouver dans une situation avec un chemin fixe. -Les *fonctions de chemin* รฉtant รฉvaluรฉes dans l'ordre, il faut s'assurer que la fonction correspondant ร  `/users/me` est dรฉclarรฉe avant celle de `/users/{user_id}` : +Par exemple `/users/me`, disons pour rรฉcupรฉrer les donnรฉes de l'utilisateur actuel. -{* ../../docs_src/path_params/tutorial003.py hl[6,11] *} +Et vous pouvez aussi avoir un chemin `/users/{user_id}` pour rรฉcupรฉrer des donnรฉes sur un utilisateur spรฉcifique grรขce ร  un identifiant d'utilisateur. -Sinon, le chemin `/users/{user_id}` correspondrait aussi ร  `/users/me`, la fonction "croyant" qu'elle a reรงu un paramรจtre `user_id` avec pour valeur `"me"`. +Comme les *chemins d'accรจs* sont รฉvaluรฉs dans l'ordre, vous devez vous assurer que le chemin `/users/me` est dรฉclarรฉ avant celui de `/users/{user_id}` : -## Valeurs prรฉdรฉfinies +{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} -Si vous avez une *fonction de chemin* qui reรงoit un *paramรจtre de chemin*, mais que vous voulez que les valeurs possibles des paramรจtres soient prรฉdรฉfinies, vous pouvez utiliser les `Enum` de Python. +Sinon, le chemin `/users/{user_id}` correspondrait aussi ร  `/users/me`, ยซ pensant ยป qu'il reรงoit un paramรจtre `user_id` avec la valeur ยซ me ยป. -### Crรฉation d'un `Enum` +De mรชme, vous ne pouvez pas redรฉfinir un chemin d'accรจs : -Importez `Enum` et crรฉez une sous-classe qui hรฉrite de `str` et `Enum`. +{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} -En hรฉritant de `str` la documentation sera capable de savoir que les valeurs doivent รชtre de type `string` et pourra donc afficher cette `Enum` correctement. +Le premier sera toujours utilisรฉ puisque le chemin correspond en premier. -Crรฉez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs autorisรฉes pour cette รฉnumรฉration. +## Valeurs prรฉdรฉfinies { #predefined-values } -{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *} +Si vous avez un *chemin d'accรจs* qui reรงoit un *paramรจtre de chemin*, mais que vous voulez que les valeurs possibles de ce *paramรจtre de chemin* soient prรฉdรฉfinies, vous pouvez utiliser une `Enum` Python standard. -/// info +### Crรฉer une classe `Enum` { #create-an-enum-class } -Les รฉnumรฉrations (ou enums) sont disponibles en Python depuis la version 3.4. +Importez `Enum` et crรฉez une sous-classe qui hรฉrite de `str` et de `Enum`. -/// +En hรฉritant de `str`, la documentation de l'API saura que les valeurs doivent รชtre de type `string` et pourra donc s'afficher correctement. + +Crรฉez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs valides disponibles : + +{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} /// tip | Astuce -Pour ceux qui se demandent, "AlexNet", "ResNet", et "LeNet" sont juste des noms de modรจles de Machine Learning. +Si vous vous demandez, ยซ AlexNet ยป, ยซ ResNet ยป et ยซ LeNet ยป sont juste des noms de modรจles de Machine Learning. /// -### Dรฉclarer un paramรจtre de chemin +### Dรฉclarer un paramรจtre de chemin { #declare-a-path-parameter } -Crรฉez ensuite un *paramรจtre de chemin* avec une annotation de type dรฉsignant l'รฉnumรฉration crรฉรฉe prรฉcรฉdemment (`ModelName`) : +Crรฉez ensuite un *paramรจtre de chemin* avec une annotation de type utilisant la classe d'รฉnumรฉration que vous avez crรฉรฉe (`ModelName`) : -{* ../../docs_src/path_params/tutorial005.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} -### Documentation +### Consulter la documentation { #check-the-docs } -Les valeurs disponibles pour le *paramรจtre de chemin* sont bien prรฉdรฉfinies, la documentation les affiche correctement : +Comme les valeurs disponibles pour le *paramรจtre de chemin* sont prรฉdรฉfinies, la documentation interactive peut les afficher clairement : -### Manipuler les *รฉnumรฉrations* Python +### Travailler avec les *รฉnumรฉrations* Python { #working-with-python-enumerations } -La valeur du *paramรจtre de chemin* sera un des "membres" de l'รฉnumรฉration. +La valeur du *paramรจtre de chemin* sera un *membre d'รฉnumรฉration*. -#### Comparer les *membres d'รฉnumรฉration* +#### Comparer des *membres d'รฉnumรฉration* { #compare-enumeration-members } -Vous pouvez comparer ce paramรจtre avec les membres de votre รฉnumรฉration `ModelName` : +Vous pouvez le comparer avec le *membre d'รฉnumรฉration* dans votre enum `ModelName` : -{* ../../docs_src/path_params/tutorial005.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} -#### Rรฉcupรฉrer la *valeur de l'รฉnumรฉration* +#### Obtenir la *valeur de l'รฉnumรฉration* { #get-the-enumeration-value } -Vous pouvez obtenir la valeur rรฉel d'un membre (une chaรฎne de caractรจres ici), avec `model_name.value`, ou en gรฉnรฉral, `votre_membre_d'enum.value` : +Vous pouvez obtenir la valeur rรฉelle (une `str` dans ce cas) avec `model_name.value`, ou en gรฉnรฉral, `votre_membre_d_enum.value` : -{* ../../docs_src/path_params/tutorial005.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} /// tip | Astuce -Vous pouvez aussi accรฉder la valeur `"lenet"` avec `ModelName.lenet.value`. +Vous pouvez aussi accรฉder ร  la valeur ยซ lenet ยป avec `ModelName.lenet.value`. /// -#### Retourner des *membres d'รฉnumรฉration* +#### Retourner des *membres d'รฉnumรฉration* { #return-enumeration-members } -Vous pouvez retourner des *membres d'รฉnumรฉration* dans vos *fonctions de chemin*, mรชme imbriquรฉe dans un JSON (e.g. un `dict`). +Vous pouvez retourner des *membres d'รฉnumรฉration* depuis votre *chemin d'accรจs*, mรชme imbriquรฉs dans un corps JSON (par ex. un `dict`). -Ils seront convertis vers leurs valeurs correspondantes (chaรฎnes de caractรจres ici) avant d'รชtre transmis au client : +Ils seront convertis vers leurs valeurs correspondantes (des chaรฎnes de caractรจres ici) avant d'รชtre renvoyรฉs au client : -{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} -Le client recevra une rรฉponse JSON comme celle-ci : +Dans votre client, vous recevrez une rรฉponse JSON comme : ```JSON { @@ -208,53 +199,53 @@ Le client recevra une rรฉponse JSON comme celle-ci : } ``` -## Paramรจtres de chemin contenant des chemins +## Paramรจtres de chemin contenant des chemins { #path-parameters-containing-paths } -Disons que vous avez une *fonction de chemin* liรฉe au chemin `/files/{file_path}`. +Disons que vous avez un *chemin d'accรจs* avec un chemin `/files/{file_path}`. -Mais que `file_path` lui-mรชme doit contenir un *chemin*, comme `home/johndoe/myfile.txt` par exemple. +Mais vous avez besoin que `file_path` lui-mรชme contienne un *chemin*, comme `home/johndoe/myfile.txt`. -Donc, l'URL pour ce fichier pourrait รชtre : `/files/home/johndoe/myfile.txt`. +Ainsi, l'URL pour ce fichier serait : `/files/home/johndoe/myfile.txt`. -### Support d'OpenAPI +### Support d'OpenAPI { #openapi-support } -OpenAPI ne supporte pas de maniรจre de dรฉclarer un paramรจtre de chemin contenant un *chemin*, cela pouvant causer des scรฉnarios difficiles ร  tester et dรฉfinir. +OpenAPI ne prend pas en charge une maniรจre de dรฉclarer un *paramรจtre de chemin* contenant un *chemin* ร  l'intรฉrieur, car cela peut conduire ร  des scรฉnarios difficiles ร  tester et ร  dรฉfinir. -Nรฉanmoins, cela reste faisable dans **FastAPI**, via les outils internes de Starlette. +Nรฉanmoins, vous pouvez toujours le faire dans **FastAPI**, en utilisant l'un des outils internes de Starlette. -Et la documentation fonctionne quand mรชme, bien qu'aucune section ne soit ajoutรฉe pour dire que la paramรจtre devrait contenir un *chemin*. +Et la documentation fonctionnera quand mรชme, mรชme si aucune indication supplรฉmentaire ne sera ajoutรฉe pour dire que le paramรจtre doit contenir un chemin. -### Convertisseur de *chemin* +### Convertisseur de chemin { #path-convertor } -En utilisant une option de Starlette directement, vous pouvez dรฉclarer un *paramรจtre de chemin* contenant un *chemin* avec une URL comme : +En utilisant une option directement depuis Starlette, vous pouvez dรฉclarer un *paramรจtre de chemin* contenant un *chemin* avec une URL comme : ``` /files/{file_path:path} ``` -Dans ce cas, le nom du paramรจtre est `file_path`, et la derniรจre partie, `:path`, indique ร  Starlette que le paramรจtre devrait correspondre ร  un *chemin*. +Dans ce cas, le nom du paramรจtre est `file_path`, et la derniรจre partie, `:path`, indique que le paramรจtre doit correspondre ร  n'importe quel *chemin*. -Vous pouvez donc l'utilisez comme tel : +Vous pouvez donc l'utiliser ainsi : -{* ../../docs_src/path_params/tutorial004.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} /// tip | Astuce -Vous pourriez avoir besoin que le paramรจtre contienne `/home/johndoe/myfile.txt`, avec un slash au dรฉbut (`/`). +Vous pourriez avoir besoin que le paramรจtre contienne `/home/johndoe/myfile.txt`, avec un slash initial (`/`). Dans ce cas, l'URL serait : `/files//home/johndoe/myfile.txt`, avec un double slash (`//`) entre `files` et `home`. /// -## Rรฉcapitulatif +## Rรฉcapitulatif { #recap } -Avec **FastAPI**, en utilisant les dรฉclarations de type rapides, intuitives et standards de Python, vous bรฉnรฉficiez de : +Avec **FastAPI**, en utilisant des dรฉclarations de type Python courtes, intuitives et standard, vous obtenez : -* Support de l'รฉditeur : vรฉrification d'erreurs, auto-complรฉtion, etc. -* "Parsing" de donnรฉes. -* Validation de donnรฉes. -* Annotations d'API et documentation automatique. +* Support de l'รฉditeur : vรฉrifications d'erreurs, autocomplรฉtion, etc. +* Donnรฉes ยซ parsing ยป +* Validation de donnรฉes +* Annotations d'API et documentation automatique -Et vous n'avez besoin de le dรฉclarer qu'une fois. +Et vous n'avez besoin de les dรฉclarer qu'une seule fois. -C'est probablement l'avantage visible principal de **FastAPI** comparรฉ aux autres *frameworks* (outre les performances pures). +C'est probablement l'avantage visible principal de **FastAPI** comparรฉ aux autres frameworks (outre les performances pures). diff --git a/docs/fr/docs/tutorial/query-params-str-validations.md b/docs/fr/docs/tutorial/query-params-str-validations.md index c54c0c7171..544d10328e 100644 --- a/docs/fr/docs/tutorial/query-params-str-validations.md +++ b/docs/fr/docs/tutorial/query-params-str-validations.md @@ -1,166 +1,273 @@ -# Paramรจtres de requรชte et validations de chaรฎnes de caractรจres +# Paramรจtres de requรชte et validations de chaรฎnes de caractรจres { #query-parameters-and-string-validations } -**FastAPI** vous permet de dรฉclarer des informations et des validateurs additionnels pour vos paramรจtres de requรชtes. +**FastAPI** vous permet de dรฉclarer des informations et des validations supplรฉmentaires pour vos paramรจtres. -Commenรงons avec cette application pour exemple : +Prenons cette application comme exemple : -{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -Le paramรจtre de requรชte `q` a pour type `Union[str, None]` (ou `str | None` en Python 3.10), signifiant qu'il est de type `str` mais pourrait aussi รชtre รฉgal ร  `None`, et bien sรปr, la valeur par dรฉfaut est `None`, donc **FastAPI** saura qu'il n'est pas requis. +Le paramรจtre de requรชte `q` est de type `str | None`, cela signifie quโ€™il est de type `str` mais peut aussi รชtre `None`, et en effet, la valeur par dรฉfaut est `None`, donc FastAPI saura quโ€™il nโ€™est pas requis. -/// note +/// note | Remarque -**FastAPI** saura que la valeur de `q` n'est pas requise grรขce ร  la valeur par dรฉfaut `= None`. +FastAPI saura que la valeur de `q` nโ€™est pas requise grรขce ร  la valeur par dรฉfaut `= None`. -Le `Union` dans `Union[str, None]` permettra ร  votre รฉditeur de vous offrir un meilleur support et de dรฉtecter les erreurs. +Avoir `str | None` permettra ร  votre รฉditeur de vous offrir un meilleur support et de dรฉtecter les erreurs. /// -## Validation additionnelle +## Validation additionnelle { #additional-validation } -Nous allons imposer que bien que `q` soit un paramรจtre optionnel, dรจs qu'il est fourni, **sa longueur n'excรจde pas 50 caractรจres**. +Nous allons imposer que, mรชme si `q` est optionnel, dรจs quโ€™il est fourni, **sa longueur nโ€™excรจde pas 50 caractรจres**. -## Importer `Query` +### Importer `Query` et `Annotated` { #import-query-and-annotated } -Pour cela, importez d'abord `Query` depuis `fastapi` : +Pour ce faire, importez dโ€™abord : -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *} +- `Query` depuis `fastapi` +- `Annotated` depuis `typing` -## Utiliser `Query` comme valeur par dรฉfaut +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -Construisez ensuite la valeur par dรฉfaut de votre paramรจtre avec `Query`, en choisissant 50 comme `max_length` : +/// info -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *} +FastAPI a ajoutรฉ la prise en charge de `Annotated` (et a commencรฉ ร  le recommander) dans la version 0.95.0. -Comme nous devons remplacer la valeur par dรฉfaut `None` dans la fonction par `Query()`, nous pouvons maintenant dรฉfinir la valeur par dรฉfaut avec le paramรจtre `Query(default=None)`, il sert le mรชme objectif qui est de dรฉfinir cette valeur par dรฉfaut. +Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant dโ€™utiliser `Annotated`. -Donc : +Assurez-vous de [mettre ร  niveau la version de FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} vers au moins 0.95.1 avant dโ€™utiliser `Annotated`. + +/// + +## Utiliser `Annotated` dans le type pour le paramรจtre `q` { #use-annotated-in-the-type-for-the-q-parameter } + +Vous vous souvenez que je vous ai dit plus tรดt que `Annotated` peut รชtre utilisรฉ pour ajouter des mรฉtadonnรฉes ร  vos paramรจtres dans lโ€™[Introduction aux types Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} ? + +Cโ€™est le moment de lโ€™utiliser avec FastAPI. ๐Ÿš€ + +Nous avions cette annotation de type : + +//// tab | Python 3.10+ ```Python -q: Union[str, None] = Query(default=None) +q: str | None = None ``` -... rend le paramรจtre optionnel, et est donc รฉquivalent ร  : +//// + +//// tab | Python 3.9+ ```Python q: Union[str, None] = None ``` -Mais dรฉclare explicitement `q` comme รฉtant un paramรจtre de requรชte. +//// -/// info +Ce que nous allons faire, cโ€™est lโ€™englober avec `Annotated`, de sorte que cela devienneย : -Gardez ร  l'esprit que la partie la plus importante pour rendre un paramรจtre optionnel est : +//// tab | Python 3.10+ ```Python -= None +q: Annotated[str | None] = None ``` -ou : +//// + +//// tab | Python 3.9+ ```Python -= Query(None) +q: Annotated[Union[str, None]] = None ``` -et utilisera ce `None` pour dรฉtecter que ce paramรจtre de requรชte **n'est pas requis**. +//// + +Les deux versions signifient la mรชme chose, `q` est un paramรจtre qui peut รชtre une `str` ou `None`, et par dรฉfaut, cโ€™est `None`. + +Passons maintenant aux choses amusantes. ๐ŸŽ‰ -Le `Union[str, None]` est uniquement lร  pour permettre ร  votre รฉditeur un meilleur support. +## Ajouter `Query` ร  `Annotated` dans le paramรจtre `q` { #add-query-to-annotated-in-the-q-parameter } + +Maintenant que nous avons cet `Annotated` dans lequel nous pouvons mettre plus dโ€™informations (dans ce cas une validation supplรฉmentaire), ajoutez `Query` ร  lโ€™intรฉrieur de `Annotated`, et dรฉfinissez le paramรจtre `max_length` ร  `50` : + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +Remarquez que la valeur par dรฉfaut est toujours `None`, donc le paramรจtre est toujours optionnel. + +Mais maintenant, avec `Query(max_length=50)` ร  lโ€™intรฉrieur de `Annotated`, nous indiquons ร  FastAPI que nous voulons **une validation supplรฉmentaire** pour cette valeur, nous voulons quโ€™elle ait au maximum 50 caractรจres. ๐Ÿ˜Ž + +/// tip | Astuce + +Ici nous utilisons `Query()` parce quโ€™il sโ€™agit dโ€™un **paramรจtre de requรชte**. Plus tard nous verrons dโ€™autres comme `Path()`, `Body()`, `Header()` et `Cookie()`, qui acceptent รฉgalement les mรชmes arguments que `Query()`. /// -Ensuite, nous pouvons passer d'autres paramรจtres ร  `Query`. Dans cet exemple, le paramรจtre `max_length` qui s'applique aux chaรฎnes de caractรจres : +FastAPI va maintenant : + +- **Valider** les donnรฉes en sโ€™assurant que la longueur maximale est de 50 caractรจres +- Afficher une **erreur claire** au client quand les donnรฉes ne sont pas valides +- **Documenter** le paramรจtre dans la *chemin d'accรจs* du schรฉma OpenAPI (il apparaรฎtra donc dans lโ€™**interface de documentation automatique**) + +## Alternative (ancienne) : `Query` comme valeur par dรฉfaut { #alternative-old-query-as-the-default-value } + +Les versions prรฉcรฉdentes de FastAPI (avant 0.95.0) exigeaient dโ€™utiliser `Query` comme valeur par dรฉfaut de votre paramรจtre, au lieu de le mettre dans `Annotated`. Il y a de fortes chances que vous voyiez du code qui lโ€™utilise encore, je vais donc vous lโ€™expliquer. + +/// tip | Astuce + +Pour du nouveau code et dรจs que possible, utilisez `Annotated` comme expliquรฉ ci-dessus. Il y a de multiples avantages (expliquรฉs ci-dessous) et aucun inconvรฉnient. ๐Ÿฐ + +/// + +Voici comment vous utiliseriez `Query()` comme valeur par dรฉfaut du paramรจtre de votre fonction, en dรฉfinissant le paramรจtre `max_length` ร  50 : + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +Comme, dans ce cas (sans utiliser `Annotated`), nous devons remplacer la valeur par dรฉfaut `None` dans la fonction par `Query()`, nous devons maintenant dรฉfinir la valeur par dรฉfaut avec le paramรจtre `Query(default=None)`, cela sert le mรชme objectif de dรฉfinir cette valeur par dรฉfaut (au moins pour FastAPI). + +Donc : + +```Python +q: str | None = Query(default=None) +``` + +... rend le paramรจtre optionnel, avec une valeur par dรฉfaut de `None`, comme : + +```Python +q: str | None = None +``` + +Mais la version avec `Query` le dรฉclare explicitement comme รฉtant un paramรจtre de requรชte. + +Ensuite, nous pouvons passer plus de paramรจtres ร  `Query`. Dans ce cas, le paramรจtre `max_length` qui sโ€™applique aux chaรฎnes de caractรจres : + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +Cela validera les donnรฉes, affichera une erreur claire lorsque les donnรฉes ne sont pas valides et documentera le paramรจtre dans la *chemin d'accรจs* du schรฉma OpenAPI. + +### `Query` comme valeur par dรฉfaut ou dans `Annotated` { #query-as-the-default-value-or-in-annotated } + +Gardez ร  lโ€™esprit quโ€™en utilisant `Query` ร  lโ€™intรฉrieur de `Annotated`, vous ne pouvez pas utiliser le paramรจtre `default` de `Query`. + +Utilisez ร  la place la valeur par dรฉfaut rรฉelle du paramรจtre de fonction. Sinon, ce serait incohรฉrent. + +Par exemple, ceci nโ€™est pas autorisรฉ : + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +... parce quโ€™il nโ€™est pas clair si la valeur par dรฉfaut doit รชtre ยซ rick ยป ou ยซ morty ยป. + +Donc, vous utiliseriez (de prรฉfรฉrence) : ```Python -q: Union[str, None] = Query(default=None, max_length=50) +q: Annotated[str, Query()] = "rick" ``` -Cela va valider les donnรฉes, montrer une erreur claire si ces derniรจres ne sont pas valides, et documenter le paramรจtre dans le schรฉma `OpenAPI` de cette *path operation*. +... ou dans des bases de code plus anciennes, vous trouverez : + +```Python +q: str = Query(default="rick") +``` + +### Avantages de `Annotated` { #advantages-of-annotated } + +**Lโ€™utilisation de `Annotated` est recommandรฉe** plutรดt que la valeur par dรฉfaut dans les paramรจtres de fonction, cโ€™est **mieux** pour plusieurs raisons. ๐Ÿค“ + +La valeur **par dรฉfaut** du **paramรจtre de fonction** est la **vraie valeur par dรฉfaut**, cโ€™est plus intuitif en Python en gรฉnรฉral. ๐Ÿ˜Œ -## Rajouter plus de validation +Vous pouvez **appeler** cette mรชme fonction dans **dโ€™autres endroits** sans FastAPI, et elle **fonctionnera comme prรฉvu**. Sโ€™il y a un paramรจtre **requis** (sans valeur par dรฉfaut), votre **รฉditeur** vous le signalera avec une erreur, **Python** se plaindra aussi si vous lโ€™exรฉcutez sans passer le paramรจtre requis. -Vous pouvez aussi rajouter un second paramรจtre `min_length` : +Quand vous nโ€™utilisez pas `Annotated` et utilisez ร  la place lโ€™**ancienne** mรฉthode avec la **valeur par dรฉfaut**, si vous appelez cette fonction sans FastAPI dans **dโ€™autres endroits**, vous devez **penser** ร  passer les arguments ร  la fonction pour quโ€™elle fonctionne correctement, sinon les valeurs seront diffรฉrentes de ce que vous attendez (par ex. `QueryInfo` ou quelque chose de similaire au lieu dโ€™une `str`). Et votre รฉditeur ne se plaindra pas, et Python ne se plaindra pas en exรฉcutant cette fonction, seulement quand les opรฉrations internes รฉchoueront. -{* ../../docs_src/query_params_str_validations/tutorial003.py hl[9] *} +Comme `Annotated` peut avoir plus dโ€™une annotation de mรฉtadonnรฉes, vous pouvez maintenant mรชme utiliser la mรชme fonction avec dโ€™autres outils, comme Typer. ๐Ÿš€ -## Ajouter des validations par expressions rรฉguliรจres +## Ajouter plus de validations { #add-more-validations } -On peut dรฉfinir une expression rรฉguliรจre ร  laquelle le paramรจtre doit correspondre : +Vous pouvez รฉgalement ajouter un paramรจtre `min_length` : -{* ../../docs_src/query_params_str_validations/tutorial004.py hl[10] *} +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} -Cette expression rรฉguliรจre vรฉrifie que la valeur passรฉe comme paramรจtre : +## Ajouter des expressions rรฉguliรจres { #add-regular-expressions } -* `^` : commence avec les caractรจres qui suivent, avec aucun caractรจre avant ceux-lร . -* `fixedquery` : a pour valeur exacte `fixedquery`. -* `$` : se termine directement ensuite, n'a pas d'autres caractรจres aprรจs `fixedquery`. +Vous pouvez dรฉfinir un `pattern` dโ€™expression rรฉguliรจre auquel le paramรจtre doit correspondre : -Si vous vous sentez perdu avec le concept d'**expression rรฉguliรจre**, pas d'inquiรฉtudes. Il s'agit d'une notion difficile pour beaucoup, et l'on peut dรฉjร  rรฉussir ร  faire beaucoup sans jamais avoir ร  les manipuler. +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} -Mais si vous dรฉcidez d'apprendre ร  les utiliser, sachez qu'ensuite vous pouvez les utiliser directement dans **FastAPI**. +Ce pattern dโ€™expression rรฉguliรจre spรฉcifique vรฉrifie que la valeur reรงue pour le paramรจtreย : -## Valeurs par dรฉfaut +- `^` : commence avec les caractรจres qui suivent, nโ€™a pas de caractรจres avant. +- `fixedquery` : a exactement la valeur `fixedquery`. +- `$` : se termine lร , nโ€™a pas dโ€™autres caractรจres aprรจs `fixedquery`. -De la mรชme faรงon que vous pouvez passer `None` comme premier argument pour l'utiliser comme valeur par dรฉfaut, vous pouvez passer d'autres valeurs. +Si vous vous sentez perdu avec toutes ces idรฉes dโ€™**ยซ expression rรฉguliรจre ยป**, pas dโ€™inquiรฉtude. Cโ€™est un sujet difficile pour beaucoup. Vous pouvez dรฉjร  faire beaucoup de choses sans avoir besoin dโ€™expressions rรฉguliรจres. -Disons que vous dรฉclarez le paramรจtre `q` comme ayant une longueur minimale de `3`, et une valeur par dรฉfaut รฉtant `"fixedquery"` : +Dรฉsormais, vous savez que, lorsque vous en aurez besoin, vous pourrez les utiliser dans **FastAPI**. -{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *} +## Valeurs par dรฉfaut { #default-values } -/// note | Rappel +Vous pouvez, bien sรปr, utiliser des valeurs par dรฉfaut autres que `None`. -Avoir une valeur par dรฉfaut rend le paramรจtre optionnel. +Disons que vous voulez dรฉclarer le paramรจtre de requรชte `q` avec un `min_length` de `3`, et avec une valeur par dรฉfaut de ยซ fixedquery ยป : + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} + +/// note | Remarque + +Avoir une valeur par dรฉfaut de nโ€™importe quel type, y compris `None`, rend le paramรจtre optionnel (non requis). /// -## Rendre ce paramรจtre requis +## Paramรจtres requis { #required-parameters } -Quand on ne dรฉclare ni validation, ni mรฉtadonnรฉe, on peut rendre le paramรจtre `q` requis en ne lui dรฉclarant juste aucune valeur par dรฉfaut : +Quand nous nโ€™avons pas besoin de dรฉclarer plus de validations ou de mรฉtadonnรฉes, nous pouvons rendre le paramรจtre de requรชte `q` requis en nโ€™indiquant simplement pas de valeur par dรฉfaut, commeย : ```Python q: str ``` -ร  la place de : +au lieu de : ```Python -q: Union[str, None] = None +q: str | None = None ``` -Mais maintenant, on dรฉclare `q` avec `Query`, comme ceci : +Mais maintenant nous le dรฉclarons avec `Query`, par exemple ainsi : ```Python -q: Union[str, None] = Query(default=None, min_length=3) +q: Annotated[str | None, Query(min_length=3)] = None ``` -Donc pour dรฉclarer une valeur comme requise tout en utilisant `Query`, il faut utiliser `...` comme premier argument : +Donc, lorsque vous avez besoin de dรฉclarer une valeur comme requise tout en utilisant `Query`, vous pouvez simplement ne pas dรฉclarer de valeur par dรฉfaut : -{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -/// info +### Requis, peut valoir `None` { #required-can-be-none } -Si vous n'avez jamais vu ce `...` auparavant : c'est une des constantes natives de Python appelรฉe "Ellipsis". +Vous pouvez dรฉclarer quโ€™un paramรจtre accepte `None`, mais quโ€™il est tout de mรชme requis. Cela obligerait les clients ร  envoyer une valeur, mรชme si la valeur est `None`. -/// +Pour ce faire, vous pouvez dรฉclarer que `None` est un type valide tout en ne dรฉclarant pas de valeur par dรฉfaut : -Cela indiquera ร  **FastAPI** que la prรฉsence de ce paramรจtre est obligatoire. +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -## Liste de paramรจtres / valeurs multiples via Query +## Liste de paramรจtres de requรชte / valeurs multiples { #query-parameter-list-multiple-values } -Quand on dรฉfinit un paramรจtre de requรชte explicitement avec `Query` on peut aussi dรฉclarer qu'il reรงoit une liste de valeur, ou des "valeurs multiples". +Quand vous dรฉfinissez un paramรจtre de requรชte explicitement avec `Query`, vous pouvez aussi dรฉclarer quโ€™il reรงoit une liste de valeurs, autrement dit, quโ€™il reรงoit des valeurs multiples. -Par exemple, pour dรฉclarer un paramรจtre de requรชte `q` qui peut apparaรฎtre plusieurs fois dans une URL, on รฉcrit : +Par exemple, pour dรฉclarer un paramรจtre de requรชte `q` qui peut apparaรฎtre plusieurs fois dans lโ€™URL, vous pouvez รฉcrire : -{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -Ce qui fait qu'avec une URL comme : +Ensuite, avec une URL comme : ``` http://localhost:8000/items/?q=foo&q=bar ``` -vous recevriez les valeurs des multiples paramรจtres de requรชte `q` (`foo` et `bar`) dans une `list` Python au sein de votre fonction de **path operation**, dans le paramรจtre de fonction `q`. +vous recevriez les valeurs des multiples paramรจtres de requรชte `q` (`foo` et `bar`) dans une `list` Python ร  lโ€™intรฉrieur de votre fonction de *chemin d'accรจs*, dans le *paramรจtre de fonction* `q`. -Donc la rรฉponse de cette URL serait : +Donc, la rรฉponse pour cette URL serait : ```JSON { @@ -173,19 +280,19 @@ Donc la rรฉponse de cette URL serait : /// tip | Astuce -Pour dรฉclarer un paramรจtre de requรชte de type `list`, comme dans l'exemple ci-dessus, il faut explicitement utiliser `Query`, sinon cela sera interprรฉtรฉ comme faisant partie du corps de la requรชte. +Pour dรฉclarer un paramรจtre de requรชte avec un type `list`, comme dans lโ€™exemple ci-dessus, vous devez explicitement utiliser `Query`, sinon il serait interprรฉtรฉ comme faisant partie du corps de la requรชte. /// -La documentation sera donc mise ร  jour automatiquement pour autoriser plusieurs valeurs : +Lโ€™interface de documentation interactive de lโ€™API sera mise ร  jour en consรฉquence, pour autoriser plusieurs valeurs : -### Combiner liste de paramรจtres et valeurs par dรฉfaut +### Liste de paramรจtres de requรชte / valeurs multiples avec valeurs par dรฉfaut { #query-parameter-list-multiple-values-with-defaults } -Et l'on peut aussi dรฉfinir une liste de valeurs par dรฉfaut si aucune n'est fournie : +Vous pouvez รฉgalement dรฉfinir une `list` de valeurs par dรฉfaut si aucune nโ€™est fournie : -{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} Si vous allez ร  : @@ -193,9 +300,7 @@ Si vous allez ร  : http://localhost:8000/items/ ``` -la valeur par dรฉfaut de `q` sera : `["foo", "bar"]` - -et la rรฉponse sera : +la valeur par dรฉfaut de `q` sera : `["foo", "bar"]` et votre rรฉponse sera : ```JSON { @@ -206,93 +311,163 @@ et la rรฉponse sera : } ``` -#### Utiliser `list` +#### Utiliser simplement `list` { #using-just-list } -Il est aussi possible d'utiliser directement `list` plutรดt que `List[str]` : +Vous pouvez aussi utiliser `list` directement au lieu de `list[str]` : -{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} -/// note +/// note | Remarque -Dans ce cas-lร , **FastAPI** ne vรฉrifiera pas le contenu de la liste. +Gardez ร  lโ€™esprit que dans ce cas, FastAPI ne vรฉrifiera pas le contenu de la liste. -Par exemple, `List[int]` vรฉrifiera (et documentera) que la liste est bien entiรจrement composรฉe d'entiers. Alors qu'un simple `list` ne ferait pas cette vรฉrification. +Par exemple, `list[int]` vรฉrifierait (et documenterait) que le contenu de la liste est composรฉ dโ€™entiers. Mais un simple `list` ne le ferait pas. /// -## Dรฉclarer des mรฉtadonnรฉes supplรฉmentaires +## Dรฉclarer plus de mรฉtadonnรฉes { #declare-more-metadata } -On peut aussi ajouter plus d'informations sur le paramรจtre. +Vous pouvez ajouter plus dโ€™informations ร  propos du paramรจtre. -Ces informations seront incluses dans le schรฉma `OpenAPI` gรฉnรฉrรฉ et utilisรฉes par la documentation interactive ou les outils externes utilisรฉs. +Ces informations seront incluses dans lโ€™OpenAPI gรฉnรฉrรฉ et utilisรฉes par les interfaces de documentation et les outils externes. -/// note +/// note | Remarque -Gardez en tรชte que les outils externes utilisรฉs ne supportent pas forcรฉment tous parfaitement OpenAPI. +Gardez ร  lโ€™esprit que diffรฉrents outils peuvent avoir des niveaux de prise en charge dโ€™OpenAPI diffรฉrents. -Il se peut donc que certains d'entre eux n'utilisent pas toutes les mรฉtadonnรฉes que vous avez dรฉclarรฉes pour le moment, bien que dans la plupart des cas, les fonctionnalitรฉs manquantes ont prรฉvu d'รชtre implรฉmentรฉes. +Certains dโ€™entre eux pourraient ne pas encore afficher toutes les informations supplรฉmentaires dรฉclarรฉes, bien que, dans la plupart des cas, la fonctionnalitรฉ manquante soit dรฉjร  prรฉvue au dรฉveloppement. /// Vous pouvez ajouter un `title` : -{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *} +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} Et une `description` : -{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *} +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} -## Alias de paramรจtres +## Paramรจtres avec alias { #alias-parameters } -Imaginez que vous vouliez que votre paramรจtre se nomme `item-query`. +Imaginez que vous vouliez que le paramรจtre soit `item-query`. -Comme dans la requรชte : +Comme dans : ``` http://127.0.0.1:8000/items/?item-query=foobaritems ``` -Mais `item-query` n'est pas un nom de variable valide en Python. +Mais `item-query` nโ€™est pas un nom de variable Python valide. -Le nom le plus proche serait `item_query`. +Le plus proche serait `item_query`. -Mais vous avez vraiment envie que ce soit exactement `item-query`... +Mais vous avez quand mรชme besoin que ce soit exactement `item-query` ... -Pour cela vous pouvez dรฉclarer un `alias`, et cet alias est ce qui sera utilisรฉ pour trouver la valeur du paramรจtre : +Vous pouvez alors dรฉclarer un `alias`, et cet alias sera utilisรฉ pour trouver la valeur du paramรจtre : -{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} -## Dรฉprรฉcier des paramรจtres +## Dรฉprรฉcier des paramรจtres { #deprecating-parameters } -Disons que vous ne vouliez plus utiliser ce paramรจtre dรฉsormais. +Disons que vous nโ€™aimez plus ce paramรจtre. -Il faut qu'il continue ร  exister pendant un certain temps car vos clients l'utilisent, mais vous voulez que la documentation mentionne clairement que ce paramรจtre est dรฉprรฉciรฉ. +Vous devez le laisser lร  quelque temps car des clients lโ€™utilisent, mais vous voulez que les documents lโ€™affichent clairement comme dรฉprรฉciรฉ. -On utilise alors l'argument `deprecated=True` de `Query` : +Passez alors le paramรจtre `deprecated=True` ร  `Query` : -{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *} +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} -La documentation le prรฉsentera comme il suit : +Les documents lโ€™afficheront ainsi : -## Pour rรฉsumer +## Exclure des paramรจtres dโ€™OpenAPI { #exclude-parameters-from-openapi } + +Pour exclure un paramรจtre de requรชte du schรฉma OpenAPI gรฉnรฉrรฉ (et donc, des systรจmes de documentation automatiques), dรฉfinissez le paramรจtre `include_in_schema` de `Query` ร  `False` : + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## Validation personnalisรฉe { #custom-validation } + +Il peut y avoir des cas oรน vous devez faire une **validation personnalisรฉe** qui ne peut pas รชtre rรฉalisรฉe avec les paramรจtres montrรฉs ci-dessus. + +Dans ces cas, vous pouvez utiliser une **fonction de validation personnalisรฉe** qui est appliquรฉe aprรจs la validation normale (par ex. aprรจs avoir validรฉ que la valeur est une `str`). + +Vous pouvez y parvenir en utilisant `AfterValidator` de Pydantic ร  lโ€™intรฉrieur de `Annotated`. + +/// tip | Astuce + +Pydantic a aussi `BeforeValidator` et dโ€™autres. ๐Ÿค“ + +/// + +Par exemple, ce validateur personnalisรฉ vรฉrifie que lโ€™ID dโ€™item commence par `isbn-` pour un numรฉro de livre ISBN ou par `imdb-` pour un ID dโ€™URL de film IMDB : + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info + +Cโ€™est disponible avec Pydantic version 2 ou supรฉrieure. ๐Ÿ˜Ž + +/// + +/// tip | Astuce + +Si vous devez faire un type de validation qui nรฉcessite de communiquer avec un **composant externe**, comme une base de donnรฉes ou une autre API, vous devez plutรดt utiliser les **Dรฉpendances de FastAPI**, vous en apprendrez davantage plus tard. + +Ces validateurs personnalisรฉs sont destinรฉs aux รฉlรฉments qui peuvent รชtre vรฉrifiรฉs **uniquement** avec les **mรชmes donnรฉes** fournies dans la requรชte. + +/// + +### Comprendre ce code { #understand-that-code } + +Le point important est simplement dโ€™utiliser **`AfterValidator` avec une fonction ร  lโ€™intรฉrieur de `Annotated`**. Nโ€™hรฉsitez pas ร  passer cette partie. ๐Ÿคธ + +--- + +Mais si vous รชtes curieux de cet exemple de code spรฉcifique et que vous รชtes toujours partant, voici quelques dรฉtails supplรฉmentaires. + +#### Chaรฎne avec `value.startswith()` { #string-with-value-startswith } + +Avez-vous remarquรฉ ? Une chaรฎne utilisant `value.startswith()` peut prendre un tuple, et elle vรฉrifiera chaque valeur du tuple : + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Un รฉlรฉment alรฉatoire { #a-random-item } + +Avec `data.items()` nous obtenons un objet itรฉrable avec des tuples contenant la clรฉ et la valeur pour chaque รฉlรฉment du dictionnaire. + +Nous convertissons cet objet itรฉrable en une `list` propre avec `list(data.items())`. + +Ensuite, avec `random.choice()` nous pouvons obtenir une **valeur alรฉatoire** depuis la liste, nous obtenons donc un tuple `(id, name)`. Ce sera quelque chose comme `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +Puis nous **affectons ces deux valeurs** du tuple aux variables `id` et `name`. + +Ainsi, si lโ€™utilisateur nโ€™a pas fourni dโ€™ID dโ€™item, il recevra quand mรชme une suggestion alรฉatoire. + +... nous faisons tout cela en **une seule ligne simple**. ๐Ÿคฏ Vous nโ€™adorez pas Python ? ๐Ÿ + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Rรฉcapitulatif { #recap } + +Vous pouvez dรฉclarer des validations et des mรฉtadonnรฉes supplรฉmentaires pour vos paramรจtres. -Il est possible d'ajouter des validateurs et mรฉtadonnรฉes pour vos paramรจtres. +Validations et mรฉtadonnรฉes gรฉnรฉriquesย : -Validateurs et mรฉtadonnรฉes gรฉnรฉriques: +- `alias` +- `title` +- `description` +- `deprecated` -* `alias` -* `title` -* `description` -* `deprecated` +Validations spรฉcifiques aux chaรฎnesย : -Validateurs spรฉcifiques aux chaรฎnes de caractรจres : +- `min_length` +- `max_length` +- `pattern` -* `min_length` -* `max_length` -* `regex` +Validations personnalisรฉes avec `AfterValidator`. -Parmi ces exemples, vous avez pu voir comment dรฉclarer des validateurs pour les chaรฎnes de caractรจres. +Dans ces exemples, vous avez vu comment dรฉclarer des validations pour des valeurs `str`. -Dans les prochains chapitres, vous verrez comment dรฉclarer des validateurs pour d'autres types, comme les nombres. +Voyez les prochains chapitres pour apprendre ร  dรฉclarer des validations pour dโ€™autres types, comme les nombres. diff --git a/docs/fr/docs/tutorial/query-params.md b/docs/fr/docs/tutorial/query-params.md index b87c26c782..1a4880ced3 100644 --- a/docs/fr/docs/tutorial/query-params.md +++ b/docs/fr/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ -# Paramรจtres de requรชte +# Paramรจtres de requรชte { #query-parameters } -Quand vous dรฉclarez des paramรจtres dans votre fonction de chemin qui ne font pas partie des paramรจtres indiquรฉs dans le chemin associรฉ, ces paramรจtres sont automatiquement considรฉrรฉs comme des paramรจtres de "requรชte". +Quand vous dรฉclarez d'autres paramรจtres de fonction qui ne font pas partie des paramรจtres de chemin, ils sont automatiquement interprรฉtรฉs comme des paramรจtres de ยซ query ยป. -{* ../../docs_src/query_params/tutorial001.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} -La partie appelรฉe requรชte (ou **query**) dans une URL est l'ensemble des paires clรฉs-valeurs placรฉes aprรจs le `?` , sรฉparรฉes par des `&`. +La query est l'ensemble des paires clรฉ-valeur placรฉes aprรจs le `?` dans une URL, sรฉparรฉes par des caractรจres `&`. Par exemple, dans l'URL : @@ -12,27 +12,27 @@ Par exemple, dans l'URL : http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...les paramรจtres de requรชte sont : +... les paramรจtres de requรชte sont : -* `skip` : avec une valeur de`0` +* `skip` : avec une valeur de `0` * `limit` : avec une valeur de `10` -Faisant partie de l'URL, ces valeurs sont des chaรฎnes de caractรจres (`str`). +Comme ils font partie de l'URL, ce sont ยซ naturellement ยป des chaรฎnes de caractรจres. -Mais quand on les dรฉclare avec des types Python (dans l'exemple prรฉcรฉdent, en tant qu'`int`), elles sont converties dans les types renseignรฉs. +Mais lorsque vous les dรฉclarez avec des types Python (dans l'exemple ci-dessus, en tant que `int`), ils sont convertis vers ce type et validรฉs par rapport ร  celui-ci. -Toutes les fonctionnalitรฉs qui s'appliquent aux paramรจtres de chemin s'appliquent aussi aux paramรจtres de requรชte : +Tous les mรชmes processus qui s'appliquaient aux paramรจtres de chemin s'appliquent aussi aux paramรจtres de requรชte : -* Support de l'รฉditeur : vรฉrification d'erreurs, auto-complรฉtion, etc. -* "Parsing" de donnรฉes. -* Validation de donnรฉes. -* Annotations d'API et documentation automatique. +* Prise en charge de l'รฉditeur (รฉvidemment) +* ยซ parsing ยป des donnรฉes +* Validation des donnรฉes +* Documentation automatique -## Valeurs par dรฉfaut +## Valeurs par dรฉfaut { #defaults } -Les paramรจtres de requรชte ne sont pas une partie fixe d'un chemin, ils peuvent รชtre optionnels et avoir des valeurs par dรฉfaut. +Comme les paramรจtres de requรชte ne sont pas une partie fixe d'un chemin, ils peuvent รชtre optionnels et avoir des valeurs par dรฉfaut. -Dans l'exemple ci-dessus, ils ont des valeurs par dรฉfaut qui sont `skip=0` et `limit=10`. +Dans l'exemple ci-dessus, ils ont des valeurs par dรฉfaut `skip=0` et `limit=10`. Donc, accรฉder ร  l'URL : @@ -40,52 +40,44 @@ Donc, accรฉder ร  l'URL : http://127.0.0.1:8000/items/ ``` -serait รฉquivalent ร  accรฉder ร  l'URL : +serait รฉquivalent ร  accรฉder ร  : ``` http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -Mais si vous accรฉdez ร , par exemple : +Mais si vous accรฉdez, par exemple, ร  : ``` http://127.0.0.1:8000/items/?skip=20 ``` -Les valeurs des paramรจtres de votre fonction seront : +Les valeurs des paramรจtres dans votre fonction seront : -* `skip=20` : car c'est la valeur dรฉclarรฉe dans l'URL. -* `limit=10` : car `limit` n'a pas รฉtรฉ dรฉclarรฉ dans l'URL, et que la valeur par dรฉfaut รฉtait `10`. +* `skip=20` : car vous l'avez dรฉfini dans l'URL +* `limit=10` : car c'รฉtait la valeur par dรฉfaut -## Paramรจtres optionnels +## Paramรจtres optionnels { #optional-parameters } -De la mรชme faรงon, vous pouvez dรฉfinir des paramรจtres de requรชte comme optionnels, en leur donnant comme valeur par dรฉfaut `None` : +De la mรชme faรงon, vous pouvez dรฉclarer des paramรจtres de requรชte optionnels, en dรฉfinissant leur valeur par dรฉfaut ร  `None` : -{* ../../docs_src/query_params/tutorial002.py hl[9] *} +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} -Ici, le paramรจtre `q` sera optionnel, et aura `None` comme valeur par dรฉfaut. +Dans ce cas, le paramรจtre de fonction `q` sera optionnel et vaudra `None` par dรฉfaut. -/// check | Remarque +/// check | Vรฉrifications -On peut voir que **FastAPI** est capable de dรฉtecter que le paramรจtre de chemin `item_id` est un paramรจtre de chemin et que `q` n'en est pas un, c'est donc un paramรจtre de requรชte. +Notez รฉgalement que FastAPI est suffisamment intelligent pour remarquer que le paramรจtre de chemin `item_id` est un paramรจtre de chemin et que `q` ne l'est pas, c'est donc un paramรจtre de requรชte. /// -/// note +## Conversion des types des paramรจtres de requรชte { #query-parameter-type-conversion } -**FastAPI** saura que `q` est optionnel grรขce au `=None`. +Vous pouvez aussi dรฉclarer des types `bool`, ils seront convertis : -Le `Optional` dans `Optional[str]` n'est pas utilisรฉ par **FastAPI** (**FastAPI** n'en utilisera que la partie `str`), mais il servira tout de mรชme ร  votre รฉditeur de texte pour dรฉtecter des erreurs dans votre code. +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -/// - -## Conversion des types des paramรจtres de requรชte - -Vous pouvez aussi dรฉclarer des paramรจtres de requรชte comme boolรฉens (`bool`), **FastAPI** les convertira : - -{* ../../docs_src/query_params/tutorial003.py hl[9] *} - -Avec ce code, en allant sur : +Dans ce cas, si vous allez sur : ``` http://127.0.0.1:8000/items/foo?short=1 @@ -115,60 +107,61 @@ ou http://127.0.0.1:8000/items/foo?short=yes ``` -ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la premiรจre lettre en majuscule, etc.), votre fonction considรฉrera le paramรจtre `short` comme ayant une valeur boolรฉenne ร  `True`. Sinon la valeur sera ร  `False`. +ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la premiรจre lettre en majuscule, etc.), votre fonction verra le paramรจtre `short` avec une valeur `bool` ร  `True`. Sinon la valeur sera ร  `False`. -## Multiples paramรจtres de chemin et de requรชte +## Multiples paramรจtres de chemin et de requรชte { #multiple-path-and-query-parameters } -Vous pouvez dรฉclarer plusieurs paramรจtres de chemin et paramรจtres de requรชte dans la mรชme fonction, **FastAPI** saura comment les gรฉrer. +Vous pouvez dรฉclarer plusieurs paramรจtres de chemin et paramรจtres de requรชte en mรชme temps, FastAPI sait lequel est lequel. Et vous n'avez pas besoin de les dรฉclarer dans un ordre spรฉcifique. -Ils seront dรฉtectรฉs par leurs noms : +Ils seront dรฉtectรฉs par leur nom : -{* ../../docs_src/query_params/tutorial004.py hl[8,10] *} +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## Paramรจtres de requรชte requis +## Paramรจtres de requรชte requis { #required-query-parameters } -Quand vous dรฉclarez une valeur par dรฉfaut pour un paramรจtre qui n'est pas un paramรจtre de chemin (actuellement, nous n'avons vu que les paramรจtres de requรชte), alors ce paramรจtre n'est pas requis. +Quand vous dรฉclarez une valeur par dรฉfaut pour des paramรจtres qui ne sont pas des paramรจtres de chemin (pour l'instant, nous n'avons vu que les paramรจtres de requรชte), alors ils ne sont pas requis. -Si vous ne voulez pas leur donner de valeur par dรฉfaut mais juste les rendre optionnels, utilisez `None` comme valeur par dรฉfaut. +Si vous ne voulez pas leur donner de valeur spรฉcifique mais simplement les rendre optionnels, dรฉfinissez la valeur par dรฉfaut ร  `None`. -Mais si vous voulez rendre un paramรจtre de requรชte obligatoire, vous pouvez juste ne pas y affecter de valeur par dรฉfaut : +Mais si vous voulez rendre un paramรจtre de requรชte obligatoire, vous pouvez simplement ne dรฉclarer aucune valeur par dรฉfaut : -{* ../../docs_src/query_params/tutorial005.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} -Ici le paramรจtre `needy` est un paramรจtre requis (ou obligatoire) de type `str`. +Ici, le paramรจtre de requรชte `needy` est un paramรจtre de requรชte requis de type `str`. -Si vous ouvrez une URL comme : +Si vous ouvrez dans votre navigateur une URL comme : ``` http://127.0.0.1:8000/items/foo-item ``` -...sans ajouter le paramรจtre requis `needy`, vous aurez une erreur : +... sans ajouter le paramรจtre requis `needy`, vous verrez une erreur comme : ```JSON { - "detail": [ - { - "loc": [ - "query", - "needy" - ], - "msg": "field required", - "type": "value_error.missing" - } - ] + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] } ``` -La prรฉsence de `needy` รฉtant nรฉcessaire, vous auriez besoin de l'insรฉrer dans l'URL : +Comme `needy` est un paramรจtre requis, vous devez le dรฉfinir dans l'URL : ``` http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ``` -...ce qui fonctionnerait : +... cela fonctionnerait : ```JSON { @@ -177,18 +170,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -Et bien sur, vous pouvez dรฉfinir certains paramรจtres comme requis, certains avec des valeurs par dรฉfaut et certains entiรจrement optionnels : +Et bien sรปr, vous pouvez dรฉfinir certains paramรจtres comme requis, certains avec une valeur par dรฉfaut et certains entiรจrement optionnels : -{* ../../docs_src/query_params/tutorial006.py hl[10] *} +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -Ici, on a donc 3 paramรจtres de requรชte : +Dans ce cas, il y a 3 paramรจtres de requรชte : -* `needy`, requis et de type `str`. -* `skip`, un `int` avec comme valeur par dรฉfaut `0`. +* `needy`, un `str` requis. +* `skip`, un `int` avec une valeur par dรฉfaut de `0`. * `limit`, un `int` optionnel. /// tip | Astuce -Vous pouvez utiliser les `Enum`s de la mรชme faรงon qu'avec les [Paramรจtres de chemin](path-params.md#valeurs-predefinies){.internal-link target=_blank}. +Vous pourriez aussi utiliser des `Enum`s de la mรชme faรงon qu'avec les [Paramรจtres de chemin](path-params.md#predefined-values){.internal-link target=_blank}. /// From 2c5a844c44c053251d557ce888811ea40dea0b01 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 15:34:47 +0000 Subject: [PATCH 113/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9f70eccb59..c54875f066 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). From b5d276bda8d8f61e6df6ffe3472de2600588774c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:43:38 -0800 Subject: [PATCH 114/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(add-missing)=20(#14790)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/tr/docs/_llm-test.md | 503 ++++++++++ docs/tr/docs/advanced/additional-responses.md | 247 +++++ .../docs/advanced/additional-status-codes.md | 41 + .../tr/docs/advanced/advanced-dependencies.md | 163 ++++ docs/tr/docs/advanced/async-tests.md | 99 ++ docs/tr/docs/advanced/behind-a-proxy.md | 466 ++++++++++ docs/tr/docs/advanced/custom-response.md | 312 +++++++ docs/tr/docs/advanced/dataclasses.md | 95 ++ docs/tr/docs/advanced/events.md | 165 ++++ docs/tr/docs/advanced/generate-clients.md | 208 +++++ docs/tr/docs/advanced/middleware.md | 97 ++ docs/tr/docs/advanced/openapi-callbacks.md | 186 ++++ docs/tr/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 172 ++++ .../advanced/response-change-status-code.md | 31 + docs/tr/docs/advanced/response-cookies.md | 51 ++ docs/tr/docs/advanced/response-directly.md | 65 ++ docs/tr/docs/advanced/response-headers.md | 41 + .../docs/advanced/security/http-basic-auth.md | 107 +++ .../docs/advanced/security/oauth2-scopes.md | 274 ++++++ docs/tr/docs/advanced/settings.md | 302 ++++++ docs/tr/docs/advanced/sub-applications.md | 67 ++ docs/tr/docs/advanced/templates.md | 126 +++ docs/tr/docs/advanced/testing-dependencies.md | 53 ++ docs/tr/docs/advanced/testing-events.md | 12 + .../docs/advanced/using-request-directly.md | 56 ++ docs/tr/docs/advanced/websockets.md | 186 ++++ docs/tr/docs/deployment/concepts.md | 321 +++++++ docs/tr/docs/deployment/docker.md | 620 +++++++++++++ docs/tr/docs/deployment/fastapicloud.md | 65 ++ docs/tr/docs/deployment/https.md | 231 +++++ docs/tr/docs/deployment/manually.md | 157 ++++ docs/tr/docs/deployment/server-workers.md | 139 +++ docs/tr/docs/deployment/versions.md | 93 ++ docs/tr/docs/environment-variables.md | 298 ++++++ docs/tr/docs/fastapi-cli.md | 75 ++ docs/tr/docs/help-fastapi.md | 256 ++++++ .../authentication-error-status-code.md | 17 + docs/tr/docs/how-to/conditional-openapi.md | 56 ++ docs/tr/docs/how-to/configure-swagger-ui.md | 70 ++ docs/tr/docs/how-to/custom-docs-ui-assets.md | 185 ++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/tr/docs/how-to/extending-openapi.md | 80 ++ docs/tr/docs/how-to/graphql.md | 60 ++ ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 +++ .../docs/how-to/separate-openapi-schemas.md | 102 +++ docs/tr/docs/how-to/testing-database.md | 7 + docs/tr/docs/tutorial/background-tasks.md | 84 ++ docs/tr/docs/tutorial/bigger-applications.md | 504 ++++++++++ docs/tr/docs/tutorial/body-fields.md | 60 ++ docs/tr/docs/tutorial/body-multiple-params.md | 175 ++++ docs/tr/docs/tutorial/body-nested-models.md | 220 +++++ docs/tr/docs/tutorial/body-updates.md | 100 ++ docs/tr/docs/tutorial/body.md | 166 ++++ docs/tr/docs/tutorial/cookie-param-models.md | 76 ++ docs/tr/docs/tutorial/cors.md | 89 ++ docs/tr/docs/tutorial/debugging.md | 113 +++ .../dependencies/classes-as-dependencies.md | 288 ++++++ ...pendencies-in-path-operation-decorators.md | 69 ++ .../dependencies/dependencies-with-yield.md | 289 ++++++ .../dependencies/global-dependencies.md | 16 + docs/tr/docs/tutorial/dependencies/index.md | 250 +++++ .../tutorial/dependencies/sub-dependencies.md | 105 +++ docs/tr/docs/tutorial/encoder.md | 35 + docs/tr/docs/tutorial/extra-data-types.md | 62 ++ docs/tr/docs/tutorial/extra-models.md | 211 +++++ docs/tr/docs/tutorial/handling-errors.md | 244 +++++ docs/tr/docs/tutorial/header-param-models.md | 72 ++ docs/tr/docs/tutorial/header-params.md | 91 ++ docs/tr/docs/tutorial/index.md | 95 ++ docs/tr/docs/tutorial/metadata.md | 120 +++ docs/tr/docs/tutorial/middleware.md | 95 ++ .../tutorial/path-operation-configuration.md | 107 +++ .../path-params-numeric-validations.md | 154 ++++ docs/tr/docs/tutorial/query-param-models.md | 68 ++ .../tutorial/query-params-str-validations.md | 473 ++++++++++ docs/tr/docs/tutorial/request-files.md | 176 ++++ docs/tr/docs/tutorial/request-form-models.md | 78 ++ .../docs/tutorial/request-forms-and-files.md | 41 + docs/tr/docs/tutorial/response-model.md | 343 +++++++ docs/tr/docs/tutorial/response-status-code.md | 101 ++ docs/tr/docs/tutorial/schema-extra-example.md | 202 ++++ docs/tr/docs/tutorial/security/first-steps.md | 203 +++++ .../tutorial/security/get-current-user.md | 105 +++ docs/tr/docs/tutorial/security/index.md | 106 +++ docs/tr/docs/tutorial/security/oauth2-jwt.md | 273 ++++++ .../docs/tutorial/security/simple-oauth2.md | 289 ++++++ docs/tr/docs/tutorial/sql-databases.md | 357 ++++++++ docs/tr/docs/tutorial/testing.md | 190 ++++ docs/tr/docs/virtual-environments.md | 862 ++++++++++++++++++ 90 files changed, 15013 insertions(+) create mode 100644 docs/tr/docs/_llm-test.md create mode 100644 docs/tr/docs/advanced/additional-responses.md create mode 100644 docs/tr/docs/advanced/additional-status-codes.md create mode 100644 docs/tr/docs/advanced/advanced-dependencies.md create mode 100644 docs/tr/docs/advanced/async-tests.md create mode 100644 docs/tr/docs/advanced/behind-a-proxy.md create mode 100644 docs/tr/docs/advanced/custom-response.md create mode 100644 docs/tr/docs/advanced/dataclasses.md create mode 100644 docs/tr/docs/advanced/events.md create mode 100644 docs/tr/docs/advanced/generate-clients.md create mode 100644 docs/tr/docs/advanced/middleware.md create mode 100644 docs/tr/docs/advanced/openapi-callbacks.md create mode 100644 docs/tr/docs/advanced/openapi-webhooks.md create mode 100644 docs/tr/docs/advanced/path-operation-advanced-configuration.md create mode 100644 docs/tr/docs/advanced/response-change-status-code.md create mode 100644 docs/tr/docs/advanced/response-cookies.md create mode 100644 docs/tr/docs/advanced/response-directly.md create mode 100644 docs/tr/docs/advanced/response-headers.md create mode 100644 docs/tr/docs/advanced/security/http-basic-auth.md create mode 100644 docs/tr/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/tr/docs/advanced/settings.md create mode 100644 docs/tr/docs/advanced/sub-applications.md create mode 100644 docs/tr/docs/advanced/templates.md create mode 100644 docs/tr/docs/advanced/testing-dependencies.md create mode 100644 docs/tr/docs/advanced/testing-events.md create mode 100644 docs/tr/docs/advanced/using-request-directly.md create mode 100644 docs/tr/docs/advanced/websockets.md create mode 100644 docs/tr/docs/deployment/concepts.md create mode 100644 docs/tr/docs/deployment/docker.md create mode 100644 docs/tr/docs/deployment/fastapicloud.md create mode 100644 docs/tr/docs/deployment/https.md create mode 100644 docs/tr/docs/deployment/manually.md create mode 100644 docs/tr/docs/deployment/server-workers.md create mode 100644 docs/tr/docs/deployment/versions.md create mode 100644 docs/tr/docs/environment-variables.md create mode 100644 docs/tr/docs/fastapi-cli.md create mode 100644 docs/tr/docs/help-fastapi.md create mode 100644 docs/tr/docs/how-to/authentication-error-status-code.md create mode 100644 docs/tr/docs/how-to/conditional-openapi.md create mode 100644 docs/tr/docs/how-to/configure-swagger-ui.md create mode 100644 docs/tr/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/tr/docs/how-to/custom-request-and-route.md create mode 100644 docs/tr/docs/how-to/extending-openapi.md create mode 100644 docs/tr/docs/how-to/graphql.md create mode 100644 docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/tr/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/tr/docs/how-to/testing-database.md create mode 100644 docs/tr/docs/tutorial/background-tasks.md create mode 100644 docs/tr/docs/tutorial/bigger-applications.md create mode 100644 docs/tr/docs/tutorial/body-fields.md create mode 100644 docs/tr/docs/tutorial/body-multiple-params.md create mode 100644 docs/tr/docs/tutorial/body-nested-models.md create mode 100644 docs/tr/docs/tutorial/body-updates.md create mode 100644 docs/tr/docs/tutorial/body.md create mode 100644 docs/tr/docs/tutorial/cookie-param-models.md create mode 100644 docs/tr/docs/tutorial/cors.md create mode 100644 docs/tr/docs/tutorial/debugging.md create mode 100644 docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md create mode 100644 docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md create mode 100644 docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md create mode 100644 docs/tr/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/tr/docs/tutorial/dependencies/index.md create mode 100644 docs/tr/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/tr/docs/tutorial/encoder.md create mode 100644 docs/tr/docs/tutorial/extra-data-types.md create mode 100644 docs/tr/docs/tutorial/extra-models.md create mode 100644 docs/tr/docs/tutorial/handling-errors.md create mode 100644 docs/tr/docs/tutorial/header-param-models.md create mode 100644 docs/tr/docs/tutorial/header-params.md create mode 100644 docs/tr/docs/tutorial/index.md create mode 100644 docs/tr/docs/tutorial/metadata.md create mode 100644 docs/tr/docs/tutorial/middleware.md create mode 100644 docs/tr/docs/tutorial/path-operation-configuration.md create mode 100644 docs/tr/docs/tutorial/path-params-numeric-validations.md create mode 100644 docs/tr/docs/tutorial/query-param-models.md create mode 100644 docs/tr/docs/tutorial/query-params-str-validations.md create mode 100644 docs/tr/docs/tutorial/request-files.md create mode 100644 docs/tr/docs/tutorial/request-form-models.md create mode 100644 docs/tr/docs/tutorial/request-forms-and-files.md create mode 100644 docs/tr/docs/tutorial/response-model.md create mode 100644 docs/tr/docs/tutorial/response-status-code.md create mode 100644 docs/tr/docs/tutorial/schema-extra-example.md create mode 100644 docs/tr/docs/tutorial/security/first-steps.md create mode 100644 docs/tr/docs/tutorial/security/get-current-user.md create mode 100644 docs/tr/docs/tutorial/security/index.md create mode 100644 docs/tr/docs/tutorial/security/oauth2-jwt.md create mode 100644 docs/tr/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/tr/docs/tutorial/sql-databases.md create mode 100644 docs/tr/docs/tutorial/testing.md create mode 100644 docs/tr/docs/virtual-environments.md diff --git a/docs/tr/docs/_llm-test.md b/docs/tr/docs/_llm-test.md new file mode 100644 index 0000000000..0ca218e6e9 --- /dev/null +++ b/docs/tr/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM test dosyasฤฑ { #llm-test-file } + +Bu dokรผman, dokรผmantasyonu รงeviren LLM'nin `scripts/translate.py` iรงindeki `general_prompt`'u ve `docs/{language code}/llm-prompt.md` iรงindeki dile รถzel prompt'u anlayฤฑp anlamadฤฑฤŸฤฑnฤฑ test eder. Dile รถzel prompt, `general_prompt`'a eklenir. + +Buraya eklenen testler, dile รถzel prompt'larฤฑ tasarlayan herkes tarafฤฑndan gรถrรผlecektir. + +ลžu ลŸekilde kullanฤฑn: + +* Dile รถzel bir prompt bulundurun: `docs/{language code}/llm-prompt.md`. +* Bu dokรผmanฤฑn hedeflediฤŸiniz dile sฤฑfฤฑrdan yeni bir รงevirisini yapฤฑn (รถrneฤŸin `translate.py` iรงindeki `translate-page` komutu). Bu, รงeviriyi `docs/{language code}/docs/_llm-test.md` altฤฑnda oluลŸturur. +* ร‡eviride her ลŸeyin yolunda olup olmadฤฑฤŸฤฑnฤฑ kontrol edin. +* Gerekirse dile รถzel prompt'u, genel prompt'u veya ฤฐngilizce dokรผmanฤฑ iyileลŸtirin. +* Ardฤฑndan รงeviride kalan sorunlarฤฑ elle dรผzeltin; bรถylece iyi bir รงeviri elde edin. +* ฤฐyi รงeviri yerindeyken yeniden รงeviri yapฤฑn. ฤฐdeal sonuรง, LLM'nin artฤฑk รงeviride hiรงbir deฤŸiลŸiklik yapmamasฤฑdฤฑr. Bu da genel prompt'un ve dile รถzel prompt'un olabilecek en iyi hรขle geldiฤŸi anlamฤฑna gelir (bazen rastgele gibi gรถrรผnen birkaรง deฤŸiลŸiklik yapabilir; รงรผnkรผ LLM'ler deterministik algoritmalar deฤŸildir). + +Testler: + +## Code snippets { #code-snippets } + +//// tab | Test + +Bu bir code snippet: `foo`. Bu da baลŸka bir code snippet: `bar`. Bir tane daha: `baz quux`. + +//// + +//// tab | Bilgi + +Code snippet'lerin iรงeriฤŸi olduฤŸu gibi bฤฑrakฤฑlmalฤฑdฤฑr. + +`script/translate.py` iรงindeki genel prompt'ta `### Content of code snippets` bรถlรผmรผne bakฤฑn. + +//// + +## Alฤฑntฤฑlar { #quotes } + +//// tab | Test + +Dรผn bir arkadaลŸฤฑm ลŸunu yazdฤฑ: "If you spell incorrectly correctly, you have spelled it incorrectly". Ben de ลŸunu yanฤฑtladฤฑm: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". + +/// note | Not + +LLM muhtemelen bunu yanlฤฑลŸ รงevirecektir. Yeniden รงeviri yapฤฑldฤฑฤŸฤฑnda dรผzeltilmiลŸ รงeviriyi koruyup korumadฤฑฤŸฤฑ รถnemlidir. + +/// + +//// + +//// tab | Bilgi + +Prompt tasarlayan kiลŸi, dรผz tฤฑrnaklarฤฑ tipografik tฤฑrnaklara dรถnรผลŸtรผrรผp dรถnรผลŸtรผrmemeyi seรงebilir. OlduฤŸu gibi bฤฑrakmak da uygundur. + +ร–rneฤŸin `docs/de/llm-prompt.md` iรงindeki `### Quotes` bรถlรผmรผne bakฤฑn. + +//// + +## Code snippet'lerde alฤฑntฤฑlar { #quotes-in-code-snippets } + +//// tab | Test + +`pip install "foo[bar]"` + +Code snippet'lerde string literal รถrnekleri: `"this"`, `'that'`. + +Code snippet'lerde string literal iรงin zor bir รถrnek: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Bilgi + +... Ancak code snippet'lerin iรงindeki tฤฑrnaklar olduฤŸu gibi kalmalฤฑdฤฑr. + +//// + +## Code block'lar { #code-blocks } + +//// tab | Test + +Bir Bash code รถrneฤŸi... + +```bash +# Evrene bir selam yazdฤฑr +echo "Hello universe" +``` + +...ve bir console code รถrneฤŸi... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...ve bir baลŸka console code รถrneฤŸi... + +```console +// "Code" adฤฑnda bir dizin oluลŸtur +$ mkdir code +// O dizine geรง +$ cd code +``` + +...ve bir Python code รถrneฤŸi... + +```Python +wont_work() # This won't work ๐Ÿ˜ฑ +works(foo="bar") # This works ๐ŸŽ‰ +``` + +...ve hepsi bu. + +//// + +//// tab | Bilgi + +Code block'larฤฑn iรงindeki code deฤŸiลŸtirilmemelidir; tek istisna yorumlardฤฑr (comments). + +`script/translate.py` iรงindeki genel prompt'ta `### Content of code blocks` bรถlรผmรผne bakฤฑn. + +//// + +## Sekmeler ve renkli kutular { #tabs-and-colored-boxes } + +//// tab | Test + +/// info | Bilgi +Some text +/// + +/// note | Not +Some text +/// + +/// note | Teknik Detaylar +Some text +/// + +/// check | Ek bilgi +Some text +/// + +/// tip | ฤฐpucu +Some text +/// + +/// warning | Uyarฤฑ +Some text +/// + +/// danger | Tehlike +Some text +/// + +//// + +//// tab | Bilgi + +Sekmelerin ve `Info`/`Note`/`Warning`/vb. bloklarฤฑn baลŸlฤฑฤŸฤฑ, dikey รงizgiden (`|`) sonra รงeviri olarak eklenmelidir. + +`script/translate.py` iรงindeki genel prompt'ta `### Special blocks` ve `### Tab blocks` bรถlรผmlerine bakฤฑn. + +//// + +## Web ve internal link'ler { #web-and-internal-links } + +//// tab | Test + +Link metni รงevrilmelidir, link adresi deฤŸiลŸmeden kalmalฤฑdฤฑr: + +* [Yukarฤฑdaki baลŸlฤฑฤŸa link](#code-snippets) +* [Internal link](index.md#installation){.internal-link target=_blank} +* External link +* Link to a style +* Link to a script +* Link to an image + +Link metni รงevrilmelidir, link adresi รงeviriye iลŸaret etmelidir: + +* FastAPI link + +//// + +//// tab | Bilgi + +Link'ler รงevrilmelidir, ancak adresleri deฤŸiลŸmeden kalmalฤฑdฤฑr. Bir istisna, FastAPI dokรผmantasyonunun sayfalarฤฑna verilen mutlak link'lerdir. Bu durumda link, รงeviriye iลŸaret etmelidir. + +`script/translate.py` iรงindeki genel prompt'ta `### Links` bรถlรผmรผne bakฤฑn. + +//// + +## HTML "abbr" รถฤŸeleri { #html-abbr-elements } + +//// tab | Test + +Burada HTML "abbr" รถฤŸeleriyle sarฤฑlmฤฑลŸ bazฤฑ ลŸeyler var (bazฤฑlarฤฑ uydurma): + +### abbr tam bir ifade verir { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr bir aรงฤฑklama verir { #the-abbr-gives-an-explanation } + +* cluster +* Deep Learning + +### abbr tam bir ifade ve bir aรงฤฑklama verir { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Bilgi + +"abbr" รถฤŸelerinin "title" attribute'larฤฑ belirli talimatlara gรถre รงevrilir. + +ร‡eviriler, LLM'nin kaldฤฑrmamasฤฑ gereken kendi "abbr" รถฤŸelerini ekleyebilir. ร–rneฤŸin ฤฐngilizce kelimeleri aรงฤฑklamak iรงin. + +`script/translate.py` iรงindeki genel prompt'ta `### HTML abbr elements` bรถlรผmรผne bakฤฑn. + +//// + +## BaลŸlฤฑklar { #headings } + +//// tab | Test + +### Bir web uygulamasฤฑ geliลŸtirin - bir รถฤŸretici { #develop-a-webapp-a-tutorial } + +Merhaba. + +### Type hint'ler ve -annotation'lar { #type-hints-and-annotations } + +Tekrar merhaba. + +### Super- ve subclass'lar { #super-and-subclasses } + +Tekrar merhaba. + +//// + +//// tab | Bilgi + +BaลŸlฤฑklarla ilgili tek katฤฑ kural, LLM'nin sรผslรผ parantezler iรงindeki hash kฤฑsmฤฑnฤฑ deฤŸiลŸtirmemesidir; bรถylece link'ler bozulmaz. + +`script/translate.py` iรงindeki genel prompt'ta `### Headings` bรถlรผmรผne bakฤฑn. + +Dile รถzel bazฤฑ talimatlar iรงin รถrneฤŸin `docs/de/llm-prompt.md` iรงindeki `### Headings` bรถlรผmรผne bakฤฑn. + +//// + +## Dokรผmanlarda kullanฤฑlan terimler { #terms-used-in-the-docs } + +//// tab | Test + +* siz +* sizin + +* รถrn. +* vb. + +* `foo` bir `int` olarak +* `bar` bir `str` olarak +* `baz` bir `list` olarak + +* Tutorial - Kullanฤฑcฤฑ kฤฑlavuzu +* ฤฐleri Dรผzey Kullanฤฑcฤฑ Kฤฑlavuzu +* SQLModel dokรผmanlarฤฑ +* API dokรผmanlarฤฑ +* otomatik dokรผmanlar + +* Veri Bilimi +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO formatฤฑ +* JSON Schema standardฤฑ +* JSON schema +* schema tanฤฑmฤฑ +* Password Flow +* Mobil + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* uygulamayฤฑ serve etmek +* sayfayฤฑ serve etmek + +* app +* application + +* request +* response +* error response + +* path operation +* path operation decorator +* path operation function + +* body +* request body +* response body +* JSON body +* form body +* file body +* function body + +* parameter +* body parameter +* path parameter +* query parameter +* cookie parameter +* header parameter +* form parameter +* function parameter + +* event +* startup event +* server'ฤฑn startup'ฤฑ +* shutdown event +* lifespan event + +* handler +* event handler +* exception handler +* handle etmek + +* model +* Pydantic model +* data model +* database model +* form model +* model object + +* class +* base class +* parent class +* subclass +* child class +* sibling class +* class method + +* header +* headers +* authorization header +* `Authorization` header +* forwarded header + +* dependency injection system +* dependency +* dependable +* dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* env var +* environment variable +* `PATH` +* `PATH` variable + +* authentication +* authentication provider +* authorization +* authorization form +* authorization provider +* kullanฤฑcฤฑ authenticate olur +* sistem kullanฤฑcฤฑyฤฑ authenticate eder + +* CLI +* command line interface + +* server +* client + +* cloud provider +* cloud service + +* geliลŸtirme +* geliลŸtirme aลŸamalarฤฑ + +* dict +* dictionary +* enumeration +* enum +* enum member + +* encoder +* decoder +* encode etmek +* decode etmek + +* exception +* raise etmek + +* expression +* statement + +* frontend +* backend + +* GitHub discussion +* GitHub issue + +* performance +* performance optimization + +* return type +* return value + +* security +* security scheme + +* task +* background task +* task function + +* template +* template engine + +* type annotation +* type hint + +* server worker +* Uvicorn worker +* Gunicorn Worker +* worker process +* worker class +* workload + +* deployment +* deploy etmek + +* SDK +* software development kit + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* breaking change +* bug +* button +* callable +* code +* commit +* context manager +* coroutine +* database session +* disk +* domain +* engine +* fake X +* HTTP GET method +* item +* library +* lifespan +* lock +* middleware +* mobile application +* module +* mounting +* network +* origin +* override +* payload +* processor +* property +* proxy +* pull request +* query +* RAM +* remote machine +* status code +* string +* tag +* web framework +* wildcard +* return etmek +* validate etmek + +//// + +//// tab | Bilgi + +Bu, dokรผmanlarda gรถrรผlen (รงoฤŸunlukla) teknik terimlerin eksiksiz ve normatif olmayan bir listesidir. Prompt tasarlayan kiลŸi iรงin, LLM'nin hangi terimlerde desteฤŸe ihtiyaรง duyduฤŸunu anlamada yardฤฑmcฤฑ olabilir. ร–rneฤŸin iyi bir รงeviriyi sรผrekli daha zayฤฑf bir รงeviriye geri alฤฑyorsa. Ya da sizin dilinizde bir terimi รงekimlemekte (conjugating/declinating) zorlanฤฑyorsa. + +ร–rneฤŸin `docs/de/llm-prompt.md` iรงindeki `### List of English terms and their preferred German translations` bรถlรผmรผne bakฤฑn. + +//// diff --git a/docs/tr/docs/advanced/additional-responses.md b/docs/tr/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..c8e372775c --- /dev/null +++ b/docs/tr/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI'de Ek Response'lar { #additional-responses-in-openapi } + +/// warning | Uyarฤฑ + +Bu konu oldukรงa ileri seviye bir konudur. + +**FastAPI**'ye yeni baลŸlฤฑyorsanฤฑz buna ihtiyaรง duymayabilirsiniz. + +/// + +Ek status code'lar, media type'lar, aรงฤฑklamalar vb. ile ek response'lar tanฤฑmlayabilirsiniz. + +Bu ek response'lar OpenAPI ลŸemasฤฑna dahil edilir; dolayฤฑsฤฑyla API dokรผmanlarฤฑnda da gรถrรผnรผrler. + +Ancak bu ek response'lar iรงin, status code'unuzu ve iรงeriฤŸinizi vererek `JSONResponse` gibi bir `Response`'u doฤŸrudan dรถndรผrdรผฤŸรผnรผzden emin olmanฤฑz gerekir. + +## `model` ile Ek Response { #additional-response-with-model } + +*Path operation decorator*'larฤฑnฤฑza `responses` adlฤฑ bir parametre geรงebilirsiniz. + +Bu parametre bir `dict` alฤฑr: anahtarlar her response iรงin status code'lardฤฑr (`200` gibi), deฤŸerler ise her birine ait bilgileri iรงeren baลŸka `dict`'lerdir. + +Bu response `dict`'lerinin her birinde, `response_model`'e benzer ลŸekilde bir Pydantic model iรงeren `model` anahtarฤฑ olabilir. + +**FastAPI** bu modeli alฤฑr, JSON Schema'sฤฑnฤฑ รผretir ve OpenAPI'de doฤŸru yere ekler. + +ร–rneฤŸin, `404` status code'u ve `Message` Pydantic model'i ile baลŸka bir response tanฤฑmlamak iรงin ลŸunu yazabilirsiniz: + +{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} + +/// note | Not + +`JSONResponse`'u doฤŸrudan dรถndรผrmeniz gerektiฤŸini unutmayฤฑn. + +/// + +/// info | Bilgi + +`model` anahtarฤฑ OpenAPI'nin bir parรงasฤฑ deฤŸildir. + +**FastAPI** buradaki Pydantic model'i alฤฑr, JSON Schema'yฤฑ รผretir ve doฤŸru yere yerleลŸtirir. + +DoฤŸru yer ลŸurasฤฑdฤฑr: + +* DeฤŸeri baลŸka bir JSON nesnesi (`dict`) olan `content` anahtarฤฑnฤฑn iรงinde: + * Media type anahtarฤฑ (รถrn. `application/json`) bulunur; bunun deฤŸeri baลŸka bir JSON nesnesidir ve onun iรงinde: + * DeฤŸeri model'den gelen JSON Schema olan `schema` anahtarฤฑ vardฤฑr; doฤŸru yer burasฤฑdฤฑr. + * **FastAPI** bunu doฤŸrudan gรถmmek yerine OpenAPI'deki baลŸka bir yerde bulunan global JSON Schema'lara bir referans ekler. Bรถylece diฤŸer uygulamalar ve client'lar bu JSON Schema'larฤฑ doฤŸrudan kullanabilir, daha iyi code generation araรงlarฤฑ saฤŸlayabilir, vb. + +/// + +Bu *path operation* iรงin OpenAPI'de รผretilen response'lar ลŸรถyle olur: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +Schema'lar OpenAPI ลŸemasฤฑnฤฑn iรงinde baลŸka bir yere referanslanฤฑr: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## Ana Response ฤฐรงin Ek Media Type'lar { #additional-media-types-for-the-main-response } + +Aynฤฑ `responses` parametresini, aynฤฑ ana response iรงin farklฤฑ media type'lar eklemek amacฤฑyla da kullanabilirsiniz. + +ร–rneฤŸin, `image/png` iรงin ek bir media type ekleyerek, *path operation*'ฤฑnฤฑzฤฑn bir JSON nesnesi (media type `application/json`) ya da bir PNG gรถrseli dรถndรผrebildiฤŸini belirtebilirsiniz: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | Not + +Gรถrseli `FileResponse` kullanarak doฤŸrudan dรถndรผrmeniz gerektiฤŸine dikkat edin. + +/// + +/// info | Bilgi + +`responses` parametrenizde aรงฤฑkรงa farklฤฑ bir media type belirtmediฤŸiniz sรผrece FastAPI, response'un ana response class'ฤฑ ile aynฤฑ media type'a sahip olduฤŸunu varsayar (varsayฤฑlan `application/json`). + +Ancak media type'ฤฑ `None` olan รถzel bir response class belirttiyseniz, FastAPI iliลŸkili bir model'i olan tรผm ek response'lar iรงin `application/json` kullanฤฑr. + +/// + +## Bilgileri BirleลŸtirme { #combining-information } + +`response_model`, `status_code` ve `responses` parametreleri dahil olmak รผzere, response bilgilerini birden fazla yerden birleลŸtirebilirsiniz. + +Varsayฤฑlan `200` status code'unu (ya da gerekiyorsa รถzel bir tane) kullanarak bir `response_model` tanฤฑmlayabilir, ardฤฑndan aynฤฑ response iรงin ek bilgileri `responses` iรงinde, doฤŸrudan OpenAPI ลŸemasฤฑna ekleyebilirsiniz. + +**FastAPI**, `responses` iรงindeki ek bilgileri korur ve model'inizin JSON Schema'sฤฑ ile birleลŸtirir. + +ร–rneฤŸin, Pydantic model kullanan ve รถzel bir `description` iรงeren `404` status code'lu bir response tanฤฑmlayabilirsiniz. + +Ayrฤฑca `response_model`'inizi kullanan, ancak รถzel bir `example` iรงeren `200` status code'lu bir response da tanฤฑmlayabilirsiniz: + +{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} + +Bunlarฤฑn hepsi OpenAPI'nize birleลŸtirilerek dahil edilir ve API dokรผmanlarฤฑnda gรถsterilir: + + + +## ร–n Tanฤฑmlฤฑ Response'larฤฑ ร–zel Olanlarla BirleลŸtirme { #combine-predefined-responses-and-custom-ones } + +Birรงok *path operation* iรงin geรงerli olacak bazฤฑ รถn tanฤฑmlฤฑ response'larฤฑnฤฑz olabilir; ancak bunlarฤฑ her *path operation*'ฤฑn ihtiyaรง duyduฤŸu รถzel response'larla birleลŸtirmek isteyebilirsiniz. + +Bu durumlarda, Python'daki bir `dict`'i `**dict_to_unpack` ile "unpacking" tekniฤŸini kullanabilirsiniz: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +Burada `new_dict`, `old_dict` iรงindeki tรผm key-value รงiftlerini ve buna ek olarak yeni key-value รงiftini iรงerir: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +Bu tekniฤŸi, *path operation*'larฤฑnฤฑzda bazฤฑ รถn tanฤฑmlฤฑ response'larฤฑ yeniden kullanmak ve bunlarฤฑ ek รถzel response'larla birleลŸtirmek iรงin kullanabilirsiniz. + +ร–rneฤŸin: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## OpenAPI Response'larฤฑ Hakkฤฑnda Daha Fazla Bilgi { #more-information-about-openapi-responses } + +Response'larฤฑn iรงine tam olarak neleri dahil edebileceฤŸinizi gรถrmek iรงin OpenAPI spesifikasyonundaki ลŸu bรถlรผmlere bakabilirsiniz: + +* OpenAPI Responses Object, `Response Object`'i iรงerir. +* OpenAPI Response Object, buradaki her ลŸeyi `responses` parametreniz iรงinde, her bir response'un iรงine doฤŸrudan ekleyebilirsiniz. Buna `description`, `headers`, `content` (bunun iรงinde farklฤฑ media type'lar ve JSON Schema'lar tanฤฑmlarsฤฑnฤฑz) ve `links` dahildir. diff --git a/docs/tr/docs/advanced/additional-status-codes.md b/docs/tr/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000..710a6459f3 --- /dev/null +++ b/docs/tr/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# Ek Status Code'larฤฑ { #additional-status-codes } + +Varsayฤฑlan olarak **FastAPI**, response'larฤฑ bir `JSONResponse` kullanarak dรถndรผrรผr; *path operation*'ฤฑnฤฑzdan dรถndรผrdรผฤŸรผnรผz iรงeriฤŸi bu `JSONResponse`'un iรงine yerleลŸtirir. + +Varsayฤฑlan status code'u veya *path operation* iรงinde sizin belirlediฤŸiniz status code'u kullanฤฑr. + +## Ek status code'larฤฑ { #additional-status-codes_1 } + +Ana status code'a ek olarak baลŸka status code'lar da dรถndรผrmek istiyorsanฤฑz, `JSONResponse` gibi bir `Response`'u doฤŸrudan dรถndรผrerek bunu yapabilirsiniz ve ek status code'u doฤŸrudan orada ayarlarsฤฑnฤฑz. + +ร–rneฤŸin, item'larฤฑ gรผncellemeye izin veren bir *path operation*'ฤฑnฤฑz olduฤŸunu dรผลŸรผnelim; baลŸarฤฑlฤฑ olduฤŸunda 200 "OK" HTTP status code'unu dรถndรผrรผyor olsun. + +Ancak yeni item'larฤฑ da kabul etmesini istiyorsunuz. Ve item daha รถnce yoksa, onu oluลŸturup 201 "Created" HTTP status code'unu dรถndรผrsรผn. + +Bunu yapmak iรงin `JSONResponse` import edin ve iรงeriฤŸinizi doฤŸrudan onunla dรถndรผrรผn; istediฤŸiniz `status_code`'u da ayarlayฤฑn: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | Uyarฤฑ + +Yukarฤฑdaki รถrnekte olduฤŸu gibi bir `Response`'u doฤŸrudan dรถndรผrdรผฤŸรผnรผzde, response aynen olduฤŸu gibi dรถndรผrรผlรผr. + +Bir model ile serialize edilmez, vb. + +ฤฐรงinde olmasฤฑnฤฑ istediฤŸiniz veriyi taลŸฤฑdฤฑฤŸฤฑndan emin olun ve deฤŸerlerin geรงerli JSON olduฤŸundan emin olun (eฤŸer `JSONResponse` kullanฤฑyorsanฤฑz). + +/// + +/// note | Teknik Detaylar + +`from starlette.responses import JSONResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.responses` iรงindekileri `fastapi.responses` altฤฑnda da sunar. Ancak mevcut response'larฤฑn รงoฤŸu doฤŸrudan Starlette'ten gelir. `status` iรงin de aynฤฑ durum geรงerlidir. + +/// + +## OpenAPI ve API docs { #openapi-and-api-docs } + +Ek status code'larฤฑ ve response'larฤฑ doฤŸrudan dรถndรผrรผrseniz, FastAPI sizin ne dรถndรผreceฤŸinizi รถnceden bilemeyeceฤŸi iรงin bunlar OpenAPI ลŸemasฤฑna (API docs) dahil edilmez. + +Ancak bunu kodunuzda ลŸu ลŸekilde dokรผmante edebilirsiniz: [Ek Response'lar](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/tr/docs/advanced/advanced-dependencies.md b/docs/tr/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000..48c0b62111 --- /dev/null +++ b/docs/tr/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# GeliลŸmiลŸ Dependency'ler { #advanced-dependencies } + +## Parametreli dependency'ler { #parameterized-dependencies } + +ลžimdiye kadar gรถrdรผฤŸรผmรผz tรผm dependency'ler sabit bir function ya da class idi. + +Ancak, birรงok farklฤฑ function veya class tanฤฑmlamak zorunda kalmadan, dependency รผzerinde bazฤฑ parametreler ayarlamak isteyebileceฤŸiniz durumlar olabilir. + +ร–rneฤŸin, query parametresi `q`'nun belirli bir sabit iรงeriฤŸi barฤฑndฤฑrฤฑp barฤฑndฤฑrmadฤฑฤŸฤฑnฤฑ kontrol eden bir dependency istediฤŸimizi dรผลŸรผnelim. + +Ama bu sabit iรงeriฤŸi parametreleลŸtirebilmek istiyoruz. + +## "Callable" bir instance { #a-callable-instance } + +Python'da bir class'ฤฑn instance'ฤฑnฤฑ "callable" yapmanฤฑn bir yolu vardฤฑr. + +Class'ฤฑn kendisini deฤŸil (zaten callable'dฤฑr), o class'ฤฑn bir instance'ฤฑnฤฑ. + +Bunu yapmak iรงin `__call__` adฤฑnda bir method tanฤฑmlarฤฑz: + +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} + +Bu durumda, ek parametreleri ve alt-dependency'leri kontrol etmek iรงin **FastAPI**'nin kullanacaฤŸฤฑ ลŸey bu `__call__` olacaktฤฑr; ayrฤฑca daha sonra *path operation function* iรงindeki parametreye bir deฤŸer geรงmek iรงin รงaฤŸrฤฑlacak olan da budur. + +## Instance'ฤฑ parametreleลŸtirme { #parameterize-the-instance } + +Ve ลŸimdi, dependency'yi "parametreleลŸtirmek" iรงin kullanacaฤŸฤฑmฤฑz instance parametrelerini tanฤฑmlamak รผzere `__init__` kullanabiliriz: + +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} + +Bu durumda **FastAPI**, `__init__` ile asla uฤŸraลŸmaz veya onu รถnemsemez; onu doฤŸrudan kendi kodumuzda kullanฤฑrฤฑz. + +## Bir instance oluลŸturma { #create-an-instance } + +Bu class'tan bir instance'ฤฑ ลŸรถyle oluลŸturabiliriz: + +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} + +Bรถylece dependency'mizi "parametreleลŸtirmiลŸ" oluruz; artฤฑk iรงinde `"bar"` vardฤฑr ve bu deฤŸer `checker.fixed_content` attribute'u olarak durur. + +## Instance'ฤฑ dependency olarak kullanma { #use-the-instance-as-a-dependency } + +Sonra `Depends(FixedContentQueryChecker)` yerine `Depends(checker)` iรงinde bu `checker`'ฤฑ kullanabiliriz. ร‡รผnkรผ dependency, class'ฤฑn kendisi deฤŸil, `checker` instance'ฤฑdฤฑr. + +Ve dependency รงรถzรผlรผrken **FastAPI** bu `checker`'ฤฑ ลŸรถyle รงaฤŸฤฑrฤฑr: + +```Python +checker(q="somequery") +``` + +...ve bunun dรถndรผrdรผฤŸรผ her ลŸeyi, *path operation function* iรงinde `fixed_content_included` parametresine dependency deฤŸeri olarak geรงirir: + +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} + +/// tip | ฤฐpucu + +Bunlarฤฑn tamamฤฑ biraz yapay gรถrรผnebilir. Ayrฤฑca bunun nasฤฑl faydalฤฑ olduฤŸu da henรผz รงok net olmayabilir. + +Bu รถrnekler bilerek basit tutuldu; ama mekanizmanฤฑn nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ gรถsteriyor. + +Security bรถlรผmlerinde, aynฤฑ ลŸekilde implement edilmiลŸ yardฤฑmcฤฑ function'lar bulunuyor. + +Buradaki her ลŸeyi anladฤฑysanฤฑz, security iรงin kullanฤฑlan bu yardฤฑmcฤฑ araรงlarฤฑn arka planda nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ da zaten biliyorsunuz demektir. + +/// + +## `yield`, `HTTPException`, `except` ve Background Tasks ile Dependency'ler { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | Uyarฤฑ + +Bรผyรผk ihtimalle bu teknik detaylara ihtiyacฤฑnฤฑz yok. + +Bu detaylar, รถzellikle 0.121.0'dan eski bir FastAPI uygulamanฤฑz varsa ve `yield` kullanan dependency'lerle ilgili sorunlar yaลŸฤฑyorsanฤฑz faydalฤฑdฤฑr. + +/// + +`yield` kullanan dependency'ler; farklฤฑ kullanฤฑm senaryolarฤฑnฤฑ kapsamak ve bazฤฑ sorunlarฤฑ dรผzeltmek iรงin zaman iรงinde evrildi. AลŸaฤŸฤฑda nelerin deฤŸiลŸtiฤŸinin bir รถzeti var. + +### `yield` ve `scope` ile dependency'ler { #dependencies-with-yield-and-scope } + +0.121.0 sรผrรผmรผnde FastAPI, `yield` kullanan dependency'ler iรงin `Depends(scope="function")` desteฤŸini ekledi. + +`Depends(scope="function")` kullanฤฑldฤฑฤŸฤฑnda, `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodu, *path operation function* biter bitmez, response client'a geri gรถnderilmeden รถnce รงalฤฑลŸtฤฑrฤฑlฤฑr. + +`Depends(scope="request")` (varsayฤฑlan) kullanฤฑldฤฑฤŸฤฑnda ise `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodu, response gรถnderildikten sonra รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Daha fazlasฤฑnฤฑ [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) dokรผmantasyonunda okuyabilirsiniz. + +### `yield` ve `StreamingResponse` ile dependency'ler, Teknik Detaylar { #dependencies-with-yield-and-streamingresponse-technical-details } + +FastAPI 0.118.0 รถncesinde, `yield` kullanan bir dependency kullanฤฑrsanฤฑz, *path operation function* dรถndรผkten sonra ama response gรถnderilmeden hemen รถnce `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodu รงalฤฑลŸtฤฑrฤฑlฤฑrdฤฑ. + +Amaรง, response'un aฤŸ รผzerinden taลŸฤฑnmasฤฑnฤฑ beklerken gereฤŸinden uzun sรผre resource tutmaktan kaรงฤฑnmaktฤฑ. + +Bu deฤŸiลŸiklik aynฤฑ zamanda ลŸunu da ifade ediyordu: `StreamingResponse` dรถndรผrรผrseniz, `yield` kullanan dependency'nin รงฤฑkฤฑลŸ kodu zaten รงalฤฑลŸmฤฑลŸ olurdu. + +ร–rneฤŸin, `yield` kullanan bir dependency iรงinde bir veritabanฤฑ session'ฤฑnฤฑz varsa, `StreamingResponse` veri stream ederken bu session'ฤฑ kullanamazdฤฑ; รงรผnkรผ `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodunda session zaten kapatฤฑlmฤฑลŸ olurdu. + +Bu davranฤฑลŸ 0.118.0'da geri alฤฑndฤฑ ve `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodunun, response gรถnderildikten sonra รงalฤฑลŸtฤฑrฤฑlmasฤฑ saฤŸlandฤฑ. + +/// info | Bilgi + +AลŸaฤŸฤฑda gรถreceฤŸiniz gibi, bu davranฤฑลŸ 0.106.0 sรผrรผmรผnden รถnceki davranฤฑลŸa oldukรงa benzer; ancak kรถลŸe durumlar iรงin รงeลŸitli iyileลŸtirmeler ve bug fix'ler iรงerir. + +/// + +#### Erken ร‡ฤฑkฤฑลŸ Kodu iรงin Kullanฤฑm Senaryolarฤฑ { #use-cases-with-early-exit-code } + +Bazฤฑ รถzel koลŸullardaki kullanฤฑm senaryolarฤฑ, response gรถnderilmeden รถnce `yield` kullanan dependency'lerin รงฤฑkฤฑลŸ kodunun รงalฤฑลŸtฤฑrฤฑldฤฑฤŸฤฑ eski davranฤฑลŸtan fayda gรถrebilir. + +ร–rneฤŸin, `yield` kullanan bir dependency iรงinde yalnฤฑzca bir kullanฤฑcฤฑyฤฑ doฤŸrulamak iรงin veritabanฤฑ session'ฤฑ kullanan bir kodunuz olduฤŸunu dรผลŸรผnรผn; ama bu session *path operation function* iรงinde bir daha hiรง kullanฤฑlmฤฑyor, yalnฤฑzca dependency iรงinde kullanฤฑlฤฑyor **ve** response'un gรถnderilmesi uzun sรผrรผyor. Mesela veriyi yavaลŸ gรถnderen bir `StreamingResponse` var, ama herhangi bir nedenle veritabanฤฑnฤฑ kullanmฤฑyor. + +Bu durumda veritabanฤฑ session'ฤฑ, response tamamen gรถnderilene kadar elde tutulur. Ancak session kullanฤฑlmฤฑyorsa, bunu elde tutmak gerekli deฤŸildir. + +ลžรถyle gรถrรผnebilir: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +`Session`'ฤฑn otomatik kapatฤฑlmasฤฑ olan รงฤฑkฤฑลŸ kodu ลŸurada: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...yavaลŸ veri gรถnderen response'un gรถnderimi bittikten sonra รงalฤฑลŸtฤฑrฤฑlฤฑr: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +Ama `generate_stream()` veritabanฤฑ session'ฤฑnฤฑ kullanmadฤฑฤŸฤฑ iรงin, response gรถnderilirken session'ฤฑ aรงฤฑk tutmak aslฤฑnda gerekli deฤŸildir. + +SQLModel (veya SQLAlchemy) kullanarak bu spesifik senaryoya sahipseniz, session'a artฤฑk ihtiyacฤฑnฤฑz kalmadฤฑktan sonra session'ฤฑ aรงฤฑkรงa kapatabilirsiniz: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +Bรถylece session veritabanฤฑ baฤŸlantฤฑsฤฑnฤฑ serbest bฤฑrakฤฑr ve diฤŸer request'ler bunu kullanabilir. + +`yield` kullanan bir dependency'den erken รงฤฑkฤฑลŸ gerektiren farklฤฑ bir kullanฤฑm senaryonuz varsa, lรผtfen kullanฤฑm senaryonuzla birlikte ve `yield` kullanan dependency'ler iรงin erken kapatmadan neden fayda gรถreceฤŸinizi aรงฤฑklayarak bir GitHub Discussion Question oluลŸturun. + +`yield` kullanan dependency'lerde erken kapatma iรงin ikna edici kullanฤฑm senaryolarฤฑ varsa, erken kapatmayฤฑ seรงmeli (opt-in) hale getiren yeni bir yรถntem eklemeyi dรผลŸรผnebilirim. + +### `yield` ve `except` ile dependency'ler, Teknik Detaylar { #dependencies-with-yield-and-except-technical-details } + +FastAPI 0.110.0 รถncesinde, `yield` kullanan bir dependency kullanฤฑr, sonra o dependency iรงinde `except` ile bir exception yakalar ve exception'ฤฑ tekrar raise etmezseniz; exception otomatik olarak herhangi bir exception handler'a veya internal server error handler'a raise/forward edilirdi. + +Bu davranฤฑลŸ 0.110.0 sรผrรผmรผnde deฤŸiลŸtirildi. Amaรง, handler olmayan (internal server errors) forward edilmiลŸ exception'larฤฑn yรถnetilmemesinden kaynaklanan bellek tรผketimini dรผzeltmek ve bunu normal Python kodunun davranฤฑลŸฤฑyla tutarlฤฑ hale getirmekti. + +### Background Tasks ve `yield` ile dependency'ler, Teknik Detaylar { #background-tasks-and-dependencies-with-yield-technical-details } + +FastAPI 0.106.0 รถncesinde, `yield` sonrasฤฑnda exception raise etmek mรผmkรผn deฤŸildi; รงรผnkรผ `yield` kullanan dependency'lerdeki รงฤฑkฤฑลŸ kodu response gรถnderildikten *sonra* รงalฤฑลŸtฤฑrฤฑlฤฑyordu. Bu nedenle [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} zaten รงalฤฑลŸmฤฑลŸ olurdu. + +Bu tasarฤฑmฤฑn ana sebeplerinden biri, background task'lerin iรงinde dependency'lerin "yield ettiฤŸi" aynฤฑ objeleri kullanmaya izin vermekti; รงรผnkรผ รงฤฑkฤฑลŸ kodu, background task'ler bittikten sonra รงalฤฑลŸtฤฑrฤฑlฤฑyordu. + +Bu davranฤฑลŸ FastAPI 0.106.0'da, response'un aฤŸ รผzerinde taลŸฤฑnmasฤฑnฤฑ beklerken resource tutmamak amacฤฑyla deฤŸiลŸtirildi. + +/// tip | ฤฐpucu + +Ek olarak, bir background task normalde ayrฤฑ ele alฤฑnmasฤฑ gereken baฤŸฤฑmsฤฑz bir mantฤฑk setidir ve kendi resource'larฤฑna sahip olmalฤฑdฤฑr (รถr. kendi veritabanฤฑ baฤŸlantฤฑsฤฑ). + +Bu ลŸekilde muhtemelen daha temiz bir kod elde edersiniz. + +/// + +Bu davranฤฑลŸa gรผvenerek kod yazdฤฑysanฤฑz, artฤฑk background task'ler iรงin resource'larฤฑ background task'in iรงinde oluลŸturmalฤฑ ve iรงeride yalnฤฑzca `yield` kullanan dependency'lerin resource'larฤฑna baฤŸlฤฑ olmayan verileri kullanmalฤฑsฤฑnฤฑz. + +ร–rneฤŸin, aynฤฑ veritabanฤฑ session'ฤฑnฤฑ kullanmak yerine background task iรงinde yeni bir veritabanฤฑ session'ฤฑ oluลŸturur ve veritabanฤฑndaki objeleri bu yeni session ile alฤฑrsฤฑnฤฑz. Ardฤฑndan, background task function'ฤฑna veritabanฤฑndan gelen objeyi parametre olarak geรงirmek yerine, o objenin ID'sini geรงirir ve objeyi background task function'ฤฑ iรงinde yeniden elde edersiniz. diff --git a/docs/tr/docs/advanced/async-tests.md b/docs/tr/docs/advanced/async-tests.md new file mode 100644 index 0000000000..82349bbec4 --- /dev/null +++ b/docs/tr/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Async Testler { #async-tests } + +SaฤŸlanan `TestClient` ile **FastAPI** uygulamalarฤฑnฤฑzฤฑ nasฤฑl test edeceฤŸinizi zaten gรถrdรผnรผz. ลžimdiye kadar yalnฤฑzca senkron testler yazdฤฑk, yani `async` fonksiyonlar kullanmadan. + +Testlerinizde asenkron fonksiyonlar kullanabilmek faydalฤฑ olabilir; รถrneฤŸin veritabanฤฑnฤฑzฤฑ asenkron olarak sorguluyorsanฤฑz. Diyelim ki FastAPI uygulamanฤฑza request gรถnderilmesini test etmek ve ardฤฑndan async bir veritabanฤฑ kรผtรผphanesi kullanฤฑrken backend'in doฤŸru veriyi veritabanฤฑna baลŸarฤฑyla yazdฤฑฤŸฤฑnฤฑ doฤŸrulamak istiyorsunuz. + +Bunu nasฤฑl รงalฤฑลŸtฤฑrabileceฤŸimize bir bakalฤฑm. + +## pytest.mark.anyio { #pytest-mark-anyio } + +Testlerimizde asenkron fonksiyonlar รงaฤŸฤฑrmak istiyorsak, test fonksiyonlarฤฑmฤฑzฤฑn da asenkron olmasฤฑ gerekir. AnyIO bunun iรงin gรผzel bir plugin saฤŸlar; bรถylece bazฤฑ test fonksiyonlarฤฑnฤฑn asenkron olarak รงaฤŸrฤฑlacaฤŸฤฑnฤฑ belirtebiliriz. + +## HTTPX { #httpx } + +**FastAPI** uygulamanฤฑz `async def` yerine normal `def` fonksiyonlarฤฑ kullanฤฑyor olsa bile, altta yatan yapฤฑ hรขlรข bir `async` uygulamadฤฑr. + +`TestClient`, standart pytest kullanarak normal `def` test fonksiyonlarฤฑnฤฑzฤฑn iรงinden asenkron FastAPI uygulamasฤฑnฤฑ รงaฤŸฤฑrmak iรงin iรงeride bazฤฑ โ€œsihirliโ€ iลŸlemler yapar. Ancak bu sihir, onu asenkron fonksiyonlarฤฑn iรงinde kullandฤฑฤŸฤฑmฤฑzda artฤฑk รงalฤฑลŸmaz. Testlerimizi asenkron รงalฤฑลŸtฤฑrdฤฑฤŸฤฑmฤฑzda, test fonksiyonlarฤฑmฤฑzฤฑn iรงinde `TestClient` kullanamayฤฑz. + +`TestClient`, HTTPX tabanlฤฑdฤฑr ve neyse ki API'yi test etmek iรงin HTTPX'i doฤŸrudan kullanabiliriz. + +## ร–rnek { #example } + +Basit bir รถrnek iรงin, [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} ve [Testing](../tutorial/testing.md){.internal-link target=_blank} bรถlรผmlerinde anlatฤฑlana benzer bir dosya yapฤฑsฤฑ dรผลŸรผnelim: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +`main.py` dosyasฤฑ ลŸรถyle olur: + +{* ../../docs_src/async_tests/app_a_py39/main.py *} + +`test_main.py` dosyasฤฑnda `main.py` iรงin testler yer alฤฑr, artฤฑk ลŸรถyle gรถrรผnebilir: + +{* ../../docs_src/async_tests/app_a_py39/test_main.py *} + +## ร‡alฤฑลŸtฤฑrma { #run-it } + +Testlerinizi her zamanki gibi ลŸu ลŸekilde รงalฤฑลŸtฤฑrabilirsiniz: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## Detaylฤฑ Anlatฤฑm { #in-detail } + +`@pytest.mark.anyio` marker'ฤฑ, pytest'e bu test fonksiyonunun asenkron olarak รงaฤŸrฤฑlmasฤฑ gerektiฤŸini sรถyler: + +{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} + +/// tip | ฤฐpucu + +Test fonksiyonu artฤฑk `TestClient` kullanฤฑrken eskiden olduฤŸu gibi sadece `def` deฤŸil, `async def`. + +/// + +Ardฤฑndan app ile bir `AsyncClient` oluลŸturup `await` kullanarak ona async request'ler gรถnderebiliriz. + +{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} + +Bu, ลŸu kullanฤฑma denktir: + +```Python +response = client.get('/') +``` + +...ki daha รถnce request'leri `TestClient` ile bu ลŸekilde gรถnderiyorduk. + +/// tip | ฤฐpucu + +Yeni `AsyncClient` ile async/await kullandฤฑฤŸฤฑmฤฑzฤฑ unutmayฤฑn; request asenkron รงalฤฑลŸฤฑr. + +/// + +/// warning | Uyarฤฑ + +Uygulamanฤฑz lifespan event'lerine dayanฤฑyorsa, `AsyncClient` bu event'leri tetiklemez. Tetiklendiklerinden emin olmak iรงin florimondmanca/asgi-lifespan paketindeki `LifespanManager`'ฤฑ kullanฤฑn. + +/// + +## DiฤŸer Asenkron Fonksiyon ร‡aฤŸrฤฑlarฤฑ { #other-asynchronous-function-calls } + +Test fonksiyonu artฤฑk asenkron olduฤŸundan, testlerinizde FastAPI uygulamanฤฑza request gรถndermenin yanฤฑnda baลŸka `async` fonksiyonlarฤฑ da (รงaฤŸฤฑrฤฑp `await` ederek) kodunuzun baลŸka yerlerinde yaptฤฑฤŸฤฑnฤฑz gibi aynฤฑ ลŸekilde kullanabilirsiniz. + +/// tip | ฤฐpucu + +Testlerinize asenkron fonksiyon รงaฤŸrฤฑlarฤฑ entegre ederken `RuntimeError: Task attached to a different loop` hatasฤฑyla karลŸฤฑlaลŸฤฑrsanฤฑz (รถr. MongoDB'nin MotorClient kullanฤฑmฤฑ), event loop gerektiren nesneleri yalnฤฑzca async fonksiyonlarฤฑn iรงinde oluลŸturmanฤฑz gerektiฤŸini unutmayฤฑn; รถrneฤŸin bir `@app.on_event("startup")` callback'i iรงinde. + +/// diff --git a/docs/tr/docs/advanced/behind-a-proxy.md b/docs/tr/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..e70b16960f --- /dev/null +++ b/docs/tr/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# Proxy Arkasฤฑnda ร‡alฤฑลŸtฤฑrma { #behind-a-proxy } + +Birรงok durumda, FastAPI uygulamanฤฑzฤฑn รถnรผnde Traefik veya Nginx gibi bir **proxy** kullanฤฑrsฤฑnฤฑz. + +Bu proxy'ler HTTPS sertifikalarฤฑnฤฑ ve diฤŸer bazฤฑ iลŸleri รผstlenebilir. + +## Proxy Forwarded Header'larฤฑ { #proxy-forwarded-headers } + +Uygulamanฤฑzฤฑn รถnรผndeki bir **proxy**, request'leri **server**'ฤฑnฤฑza gรถndermeden รถnce genelde bazฤฑ header'larฤฑ dinamik olarak ayarlar. Bรถylece server, request'in proxy tarafฤฑndan **forward** edildiฤŸini; domain dahil orijinal (public) URL'yi, HTTPS kullanฤฑldฤฑฤŸฤฑnฤฑ vb. bilgileri anlayabilir. + +**Server** programฤฑ (รถrneฤŸin **FastAPI CLI** รผzerinden **Uvicorn**) bu header'larฤฑ yorumlayabilir ve ardฤฑndan bu bilgiyi uygulamanฤฑza aktarabilir. + +Ancak gรผvenlik nedeniyle, server gรผvenilir bir proxy arkasฤฑnda olduฤŸunu bilmediฤŸi iรงin bu header'larฤฑ yorumlamaz. + +/// note | Teknik Detaylar + +Proxy header'larฤฑ ลŸunlardฤฑr: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### Proxy Forwarded Header'larฤฑnฤฑ EtkinleลŸtirme { #enable-proxy-forwarded-headers } + +FastAPI CLI'yi `--forwarded-allow-ips` *CLI Option*'ฤฑ ile baลŸlatฤฑp, bu forwarded header'larฤฑ okumada gรผvenilecek IP adreslerini verebilirsiniz. + +Bunu `--forwarded-allow-ips="*"` olarak ayarlarsanฤฑz, gelen tรผm IP'lere gรผvenir. + +**Server**'ฤฑnฤฑz gรผvenilir bir **proxy** arkasฤฑndaysa ve onunla sadece proxy konuลŸuyorsa, bu ayar server'ฤฑn o **proxy**'nin IP'si her neyse onu kabul etmesini saฤŸlar. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### HTTPS ile Redirect'ler { #redirects-with-https } + +ร–rneฤŸin `/items/` adฤฑnda bir *path operation* tanฤฑmladฤฑฤŸฤฑnฤฑzฤฑ dรผลŸรผnelim: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} + +Client `/items`'a gitmeye รงalฤฑลŸฤฑrsa, varsayฤฑlan olarak `/items/`'a redirect edilir. + +Ancak *CLI Option* `--forwarded-allow-ips` ayarlanmadan รถnce, `http://localhost:8000/items/`'a redirect edebilir. + +Oysa uygulamanฤฑz `https://mysuperapp.com` รผzerinde host ediliyor olabilir ve redirect'in `https://mysuperapp.com/items/` olmasฤฑ gerekir. + +Artฤฑk `--proxy-headers` ayarฤฑnฤฑ yaparak FastAPI'nin doฤŸru adrese redirect edebilmesini saฤŸlarsฤฑnฤฑz. ๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | ฤฐpucu + +HTTPS hakkฤฑnda daha fazla bilgi iรงin [HTTPS Hakkฤฑnda](../deployment/https.md){.internal-link target=_blank} rehberine bakฤฑn. + +/// + +### Proxy Forwarded Header'larฤฑ Nasฤฑl ร‡alฤฑลŸฤฑr { #how-proxy-forwarded-headers-work } + +**Proxy**'nin, client ile **application server** arasฤฑnda forwarded header'larฤฑ nasฤฑl eklediฤŸini gรถsteren gรถrsel bir temsil: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**Proxy**, orijinal client request'ini araya girerek (intercept) alฤฑr ve request'i **application server**'a iletmeden รถnce รถzel *forwarded* header'larฤฑ (`X-Forwarded-*`) ekler. + +Bu header'lar, aksi halde kaybolacak olan orijinal request bilgilerini korur: + +* **X-Forwarded-For**: Orijinal client'ฤฑn IP adresi +* **X-Forwarded-Proto**: Orijinal protokol (`https`) +* **X-Forwarded-Host**: Orijinal host (`mysuperapp.com`) + +**FastAPI CLI** `--forwarded-allow-ips` ile yapฤฑlandฤฑrฤฑldฤฑฤŸฤฑnda bu header'lara gรผvenir ve รถrneฤŸin redirect'lerde doฤŸru URL'leri รผretmek iรงin bunlarฤฑ kullanฤฑr. + +## Path Prefix'i Kฤฑrpฤฑlan (Stripped) Bir Proxy { #proxy-with-a-stripped-path-prefix } + +Uygulamanฤฑza bir path prefix ekleyen bir proxy'niz olabilir. + +Bu durumlarda uygulamanฤฑzฤฑ yapฤฑlandฤฑrmak iรงin `root_path` kullanabilirsiniz. + +`root_path`, FastAPI'nin (Starlette รผzerinden) รผzerine kurulduฤŸu ASGI spesifikasyonunun saฤŸladฤฑฤŸฤฑ bir mekanizmadฤฑr. + +`root_path` bu รถzel senaryolarฤฑ yรถnetmek iรงin kullanฤฑlฤฑr. + +Ayrฤฑca sub-application mount ederken de iรงeride kullanฤฑlฤฑr. + +Path prefix'i kฤฑrpฤฑlan bir proxy kullanmak, ลŸu anlama gelir: Kodunuzda `/app` altฤฑnda bir path tanฤฑmlarsฤฑnฤฑz; ancak รผstte bir katman (proxy) ekleyip **FastAPI** uygulamanฤฑzฤฑ `/api/v1` gibi bir path'in altฤฑna koyarsฤฑnฤฑz. + +Bu durumda, orijinal `/app` path'i aslฤฑnda `/api/v1/app` altฤฑnda servis edilir. + +Kodunuzun tamamฤฑ sadece `/app` varmฤฑลŸ gibi yazฤฑlmฤฑลŸ olsa bile. + +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} + +Proxy, request'i app server'a (muhtemelen FastAPI CLI รผzerinden Uvicorn) iletmeden รถnce **path prefix**'i anlฤฑk olarak **"kฤฑrpar"** (strip). Bรถylece uygulamanฤฑz hรขlรข `/app` altฤฑnda servis ediliyormuลŸ gibi davranฤฑr ve tรผm kodunuzu `/api/v1` prefix'ini iรงerecek ลŸekilde gรผncellemeniz gerekmez. + +Buraya kadar her ลŸey normal รงalฤฑลŸฤฑr. + +Ancak entegre dokรผman arayรผzรผnรผ (frontend) aรงtฤฑฤŸฤฑnฤฑzda, OpenAPI ลŸemasฤฑnฤฑ `/api/v1/openapi.json` yerine `/openapi.json` รผzerinden almayฤฑ bekler. + +Dolayฤฑsฤฑyla tarayฤฑcฤฑda รงalฤฑลŸan frontend `/openapi.json`'a eriลŸmeye รงalฤฑลŸฤฑr ve OpenAPI ลŸemasฤฑnฤฑ alamaz. + +ร‡รผnkรผ uygulamamฤฑz proxy arkasฤฑnda `/api/v1` path prefix'i ile รงalฤฑลŸmaktadฤฑr; frontend'in OpenAPI ลŸemasฤฑnฤฑ `/api/v1/openapi.json` รผzerinden รงekmesi gerekir. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | ฤฐpucu + +`0.0.0.0` IP'si, genelde programฤฑn ilgili makine/server รผzerindeki tรผm kullanฤฑlabilir IP'lerde dinlediฤŸi anlamฤฑna gelir. + +/// + +Docs UI'nin, bu API `server`'ฤฑnฤฑn (proxy arkasฤฑnda) `/api/v1` altฤฑnda bulunduฤŸunu belirtmek iรงin OpenAPI ลŸemasฤฑna da ihtiyacฤฑ olur. ร–rneฤŸin: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // More stuff here + } +} +``` + +Bu รถrnekte "Proxy", **Traefik** gibi bir ลŸey olabilir. Server da FastAPI uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran (Uvicorn'lu) FastAPI CLI olabilir. + +### `root_path` SaฤŸlama { #providing-the-root-path } + +Bunu yapmak iรงin `--root-path` komut satฤฑrฤฑ seรงeneฤŸini ลŸรถyle kullanabilirsiniz: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Hypercorn kullanฤฑyorsanฤฑz, onda da `--root-path` seรงeneฤŸi vardฤฑr. + +/// note | Teknik Detaylar + +ASGI spesifikasyonu bu kullanฤฑm senaryosu iรงin bir `root_path` tanฤฑmlar. + +`--root-path` komut satฤฑrฤฑ seรงeneฤŸi de bu `root_path`'i saฤŸlar. + +/// + +### Mevcut `root_path`'i Kontrol Etme { #checking-the-current-root-path } + +Uygulamanฤฑzฤฑn her request iรงin kullandฤฑฤŸฤฑ mevcut `root_path` deฤŸerini alabilirsiniz; bu deฤŸer ASGI spesifikasyonunun bir parรงasฤฑ olan `scope` dict'inin iรงindedir. + +Burada sadece gรถstermek iรงin bunu mesaja dahil ediyoruz. + +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} + +Ardฤฑndan Uvicorn'u ลŸu ลŸekilde baลŸlatฤฑrsanฤฑz: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Response ลŸรถyle bir ลŸey olur: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### FastAPI Uygulamasฤฑnda `root_path` Ayarlama { #setting-the-root-path-in-the-fastapi-app } + +Alternatif olarak, `--root-path` gibi bir komut satฤฑrฤฑ seรงeneฤŸi (veya muadili) saฤŸlayamฤฑyorsanฤฑz, FastAPI uygulamanฤฑzฤฑ oluลŸtururken `root_path` parametresini ayarlayabilirsiniz: + +{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} + +`FastAPI`'ye `root_path` vermek, Uvicorn veya Hypercorn'a `--root-path` komut satฤฑrฤฑ seรงeneฤŸini vermekle eลŸdeฤŸerdir. + +### `root_path` Hakkฤฑnda { #about-root-path } + +ลžunu unutmayฤฑn: Server (Uvicorn) bu `root_path`'i, uygulamaya iletmek dฤฑลŸฤฑnda baลŸka bir amaรงla kullanmaz. + +Ancak tarayฤฑcฤฑnฤฑzla http://127.0.0.1:8000/app adresine giderseniz normal response'u gรถrรผrsรผnรผz: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +Yani `http://127.0.0.1:8000/api/v1/app` รผzerinden eriลŸilmeyi beklemez. + +Uvicorn, proxy'nin Uvicorn'a `http://127.0.0.1:8000/app` รผzerinden eriลŸmesini bekler; bunun รผstรผne ekstra `/api/v1` prefix'ini eklemek proxy'nin sorumluluฤŸudur. + +## Stripped Path Prefix Kullanan Proxy'ler Hakkฤฑnda { #about-proxies-with-a-stripped-path-prefix } + +Stripped path prefix kullanan bir proxy, yapฤฑlandฤฑrma yรถntemlerinden yalnฤฑzca biridir. + +Birรงok durumda varsayฤฑlan davranฤฑลŸ, proxy'nin stripped path prefix kullanmamasฤฑ olacaktฤฑr. + +Bรถyle bir durumda (stripped path prefix olmadan), proxy `https://myawesomeapp.com` gibi bir yerde dinler; tarayฤฑcฤฑ `https://myawesomeapp.com/api/v1/app`'e giderse ve sizin server'ฤฑnฤฑz (รถr. Uvicorn) `http://127.0.0.1:8000` รผzerinde dinliyorsa, proxy (stripped path prefix olmadan) Uvicorn'a aynฤฑ path ile eriลŸir: `http://127.0.0.1:8000/api/v1/app`. + +## Traefik ile Local Olarak Test Etme { #testing-locally-with-traefik } + +Traefik kullanarak, stripped path prefix'li deneyi local'de kolayca รงalฤฑลŸtฤฑrabilirsiniz. + +Traefik'i indirin; tek bir binary'dir, sฤฑkฤฑลŸtฤฑrฤฑlmฤฑลŸ dosyayฤฑ รงฤฑkarฤฑp doฤŸrudan terminalden รงalฤฑลŸtฤฑrabilirsiniz. + +Ardฤฑndan `traefik.toml` adฤฑnda bir dosya oluลŸturup ลŸunu yazฤฑn: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +Bu, Traefik'e 9999 portunda dinlemesini ve `routes.toml` adlฤฑ baลŸka bir dosyayฤฑ kullanmasฤฑnฤฑ sรถyler. + +/// tip | ฤฐpucu + +Standart HTTP portu 80 yerine 9999 portunu kullanฤฑyoruz; bรถylece admin (`sudo`) yetkileriyle รงalฤฑลŸtฤฑrmanฤฑz gerekmez. + +/// + +ลžimdi diฤŸer dosyayฤฑ, `routes.toml`'u oluลŸturun: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +Bu dosya, Traefik'i `/api/v1` path prefix'ini kullanacak ลŸekilde yapฤฑlandฤฑrฤฑr. + +Ardฤฑndan Traefik, request'leri `http://127.0.0.1:8000` รผzerinde รงalฤฑลŸan Uvicorn'unuza yรถnlendirir. + +ลžimdi Traefik'i baลŸlatฤฑn: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +Ve ลŸimdi uygulamanฤฑzฤฑ `--root-path` seรงeneฤŸiyle baลŸlatฤฑn: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Response'larฤฑ Kontrol Edin { #check-the-responses } + +ลžimdi Uvicorn'un portundaki URL'ye giderseniz: http://127.0.0.1:8000/app, normal response'u gรถrรผrsรผnรผz: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | ฤฐpucu + +`http://127.0.0.1:8000/app` รผzerinden eriลŸiyor olsanฤฑz bile, `root_path` deฤŸerinin `--root-path` seรงeneฤŸinden alฤฑnฤฑp `/api/v1` olarak gรถsterildiฤŸine dikkat edin. + +/// + +ลžimdi de Traefik'in portundaki URL'yi, path prefix ile birlikte aรงฤฑn: http://127.0.0.1:9999/api/v1/app. + +Aynฤฑ response'u alฤฑrฤฑz: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ama bu sefer proxy'nin saฤŸladฤฑฤŸฤฑ prefix path olan `/api/v1` ile gelen URL'de. + +Elbette buradaki fikir, herkesin uygulamaya proxy รผzerinden eriลŸmesidir; dolayฤฑsฤฑyla `/api/v1` path prefix'li sรผrรผm "doฤŸru" olandฤฑr. + +Uvicorn'un doฤŸrudan sunduฤŸu, path prefix olmayan sรผrรผm (`http://127.0.0.1:8000/app`) ise sadece _proxy_'nin (Traefik) eriลŸmesi iรงin kullanฤฑlmalฤฑdฤฑr. + +Bu da Proxy'nin (Traefik) path prefix'i nasฤฑl kullandฤฑฤŸฤฑnฤฑ ve server'ฤฑn (Uvicorn) `--root-path` seรงeneฤŸinden gelen `root_path`'i nasฤฑl kullandฤฑฤŸฤฑnฤฑ gรถsterir. + +### Docs UI'yi Kontrol Edin { #check-the-docs-ui } + +ลžimdi iลŸin eฤŸlenceli kฤฑsmฤฑ. โœจ + +Uygulamaya eriลŸmenin "resmi" yolu, tanฤฑmladฤฑฤŸฤฑmฤฑz path prefix ile proxy รผzerinden eriลŸmektir. Bu yรผzden beklendiฤŸi gibi, Uvicorn'un doฤŸrudan servis ettiฤŸi docs UI'yi URL'de path prefix olmadan aรงarsanฤฑz รงalฤฑลŸmaz; รงรผnkรผ proxy รผzerinden eriลŸileceฤŸini varsayar. + +ลžuradan kontrol edebilirsiniz: http://127.0.0.1:8000/docs: + + + +Ancak docs UI'yi proxy รผzerinden, `9999` portuyla, `/api/v1/docs` altฤฑnda "resmi" URL'den aรงarsak doฤŸru รงalฤฑลŸฤฑr! ๐ŸŽ‰ + +ลžuradan kontrol edebilirsiniz: http://127.0.0.1:9999/api/v1/docs: + + + +Tam istediฤŸimiz gibi. โœ”๏ธ + +Bunun nedeni, FastAPI'nin OpenAPI iรงinde varsayฤฑlan `server`'ฤฑ, `root_path` tarafฤฑndan verilen URL ile oluลŸturmak iรงin bu `root_path`'i kullanmasฤฑdฤฑr. + +## Ek `server`'lar { #additional-servers } + +/// warning | Uyarฤฑ + +Bu daha ileri seviye bir kullanฤฑm senaryosudur. ฤฐsterseniz atlayabilirsiniz. + +/// + +Varsayฤฑlan olarak **FastAPI**, OpenAPI ลŸemasฤฑnda `root_path` iรงin bir `server` oluลŸturur. + +Ancak baลŸka alternatif `servers` da saฤŸlayabilirsiniz; รถrneฤŸin *aynฤฑ* docs UI'nin hem staging hem de production ortamฤฑyla etkileลŸime girmesini istiyorsanฤฑz. + +ร–zel bir `servers` listesi verirseniz ve bir `root_path` varsa (รงรผnkรผ API'niz proxy arkasฤฑndadฤฑr), **FastAPI** bu `root_path` ile bir "server"ฤฑ listenin baลŸฤฑna ekler. + +ร–rneฤŸin: + +{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} + +ลžรถyle bir OpenAPI ลŸemasฤฑ รผretir: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // More stuff here + } +} +``` + +/// tip | ฤฐpucu + +`url` deฤŸeri `/api/v1` olan, `root_path`'ten alฤฑnmฤฑลŸ otomatik รผretilen server'a dikkat edin. + +/// + +Docs UI'de, http://127.0.0.1:9999/api/v1/docs adresinde ลŸรถyle gรถrรผnรผr: + + + +/// tip | ฤฐpucu + +Docs UI, seรงtiฤŸiniz server ile etkileลŸime girer. + +/// + +/// note | Teknik Detaylar + +OpenAPI spesifikasyonunda `servers` รถzelliฤŸi opsiyoneldir. + +`servers` parametresini belirtmezseniz ve `root_path` `/` ile aynฤฑysa, รผretilen OpenAPI ลŸemasฤฑnda `servers` รถzelliฤŸi varsayฤฑlan olarak tamamen รงฤฑkarฤฑlฤฑr; bu da `url` deฤŸeri `/` olan tek bir server ile eลŸdeฤŸerdir. + +/// + +### `root_path`'ten Otomatik `server` Eklenmesini Kapatma { #disable-automatic-server-from-root-path } + +**FastAPI**'nin `root_path` kullanarak otomatik bir server eklemesini istemiyorsanฤฑz, `root_path_in_servers=False` parametresini kullanabilirsiniz: + +{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} + +Bรถylece OpenAPI ลŸemasฤฑna dahil etmez. + +## Bir Sub-Application Mount Etme { #mounting-a-sub-application } + +Bir sub-application'ฤฑ ( [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑldฤฑฤŸฤฑ gibi) mount etmeniz gerekiyorsa ve aynฤฑ zamanda `root_path` ile bir proxy kullanฤฑyorsanฤฑz, bunu beklendiฤŸi gibi normal ลŸekilde yapabilirsiniz. + +FastAPI iรงeride `root_path`'i akฤฑllฤฑca kullanฤฑr; dolayฤฑsฤฑyla doฤŸrudan รงalฤฑลŸฤฑr. โœจ diff --git a/docs/tr/docs/advanced/custom-response.md b/docs/tr/docs/advanced/custom-response.md new file mode 100644 index 0000000000..c5148f4287 --- /dev/null +++ b/docs/tr/docs/advanced/custom-response.md @@ -0,0 +1,312 @@ +# ร–zel Response - HTML, Stream, File ve DiฤŸerleri { #custom-response-html-stream-file-others } + +Varsayฤฑlan olarak **FastAPI**, response'larฤฑ `JSONResponse` kullanarak dรถndรผrรผr. + +Bunu, [DoฤŸrudan bir Response dรถndรผr](response-directly.md){.internal-link target=_blank} bรถlรผmรผnde gรถrdรผฤŸรผnรผz gibi doฤŸrudan bir `Response` dรถndรผrerek geรงersiz kฤฑlabilirsiniz. + +Ancak doฤŸrudan bir `Response` dรถndรผrรผrseniz (veya `JSONResponse` gibi herhangi bir alt sฤฑnฤฑfฤฑnฤฑ), veri otomatik olarak dรถnรผลŸtรผrรผlmez (bir `response_model` tanฤฑmlamฤฑลŸ olsanฤฑz bile) ve dokรผmantasyon da otomatik รผretilmez (รถrneฤŸin, รผretilen OpenAPIโ€™nin parรงasฤฑ olarak HTTP header `Content-Type` iรงindeki ilgili "media type" dahil edilmez). + +Bununla birlikte, *path operation decorator* iรงinde `response_class` parametresini kullanarak hangi `Response`โ€™un (รถrn. herhangi bir `Response` alt sฤฑnฤฑfฤฑ) kullanฤฑlacaฤŸฤฑnฤฑ da ilan edebilirsiniz. + +*path operation function*โ€™ฤฑnฤฑzdan dรถndรผrdรผฤŸรผnรผz iรงerik, o `Response`โ€™un iรงine yerleลŸtirilir. + +Ve eฤŸer bu `Response` ( `JSONResponse` ve `UJSONResponse`โ€™ta olduฤŸu gibi) bir JSON media typeโ€™a (`application/json`) sahipse, dรถndรผrdรผฤŸรผnรผz veri; *path operation decorator* iรงinde tanฤฑmladฤฑฤŸฤฑnฤฑz herhangi bir Pydantic `response_model` ile otomatik olarak dรถnรผลŸtรผrรผlรผr (ve filtrelenir). + +/// note | Not + +Media typeโ€™ฤฑ olmayan bir response class kullanฤฑrsanฤฑz, FastAPI responseโ€™unuzun content iรงermediฤŸini varsayar; bu yรผzden รผrettiฤŸi OpenAPI dokรผmanฤฑnda response formatฤฑnฤฑ dokรผmante etmez. + +/// + +## `ORJSONResponse` Kullan { #use-orjsonresponse } + +ร–rneฤŸin performansฤฑ sฤฑkฤฑลŸtฤฑrmaya รงalฤฑลŸฤฑyorsanฤฑz, `orjson` kurup kullanabilir ve responseโ€™u `ORJSONResponse` olarak ayarlayabilirsiniz. + +Kullanmak istediฤŸiniz `Response` classโ€™ฤฑnฤฑ (alt sฤฑnฤฑfฤฑnฤฑ) import edin ve *path operation decorator* iรงinde tanฤฑmlayฤฑn. + +Bรผyรผk response'larda, doฤŸrudan bir `Response` dรถndรผrmek bir dictionary dรถndรผrmekten รงok daha hฤฑzlฤฑdฤฑr. + +ร‡รผnkรผ varsayฤฑlan olarak FastAPI, iรงindeki her itemโ€™ฤฑ inceleyip JSON olarak serialize edilebilir olduฤŸundan emin olur; tutorialโ€™da anlatฤฑlan aynฤฑ [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} mekanizmasฤฑnฤฑ kullanฤฑr. Bu da รถrneฤŸin veritabanฤฑ modelleri gibi **keyfi objeleri** dรถndรผrebilmenizi saฤŸlar. + +Ancak dรถndรผrdรผฤŸรผnรผz iรงeriฤŸin **JSON ile serialize edilebilir** olduฤŸundan eminseniz, onu doฤŸrudan response classโ€™ฤฑna verebilir ve FastAPIโ€™nin response classโ€™ฤฑna vermeden รถnce dรถnรผลŸ iรงeriฤŸinizi `jsonable_encoder` iรงinden geรงirirken oluลŸturacaฤŸฤฑ ek yรผkten kaรงฤฑnabilirsiniz. + +{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} + +/// info | Bilgi + +`response_class` parametresi, responseโ€™un "media type"โ€™ฤฑnฤฑ tanฤฑmlamak iรงin de kullanฤฑlฤฑr. + +Bu durumda HTTP header `Content-Type`, `application/json` olarak ayarlanฤฑr. + +Ve OpenAPIโ€™de de bu ลŸekilde dokรผmante edilir. + +/// + +/// tip | ฤฐpucu + +`ORJSONResponse` yalnฤฑzca FastAPIโ€™de vardฤฑr, Starletteโ€™te yoktur. + +/// + +## HTML Response { #html-response } + +**FastAPI**โ€™den doฤŸrudan HTML iรงeren bir response dรถndรผrmek iรงin `HTMLResponse` kullanฤฑn. + +* `HTMLResponse` import edin. +* *path operation decorator*โ€™ฤฑnฤฑzฤฑn `response_class` parametresi olarak `HTMLResponse` verin. + +{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} + +/// info | Bilgi + +`response_class` parametresi, responseโ€™un "media type"โ€™ฤฑnฤฑ tanฤฑmlamak iรงin de kullanฤฑlฤฑr. + +Bu durumda HTTP header `Content-Type`, `text/html` olarak ayarlanฤฑr. + +Ve OpenAPIโ€™de de bu ลŸekilde dokรผmante edilir. + +/// + +### Bir `Response` Dรถndรผr { #return-a-response } + +[DoฤŸrudan bir Response dรถndรผr](response-directly.md){.internal-link target=_blank} bรถlรผmรผnde gรถrรผldรผฤŸรผ gibi, *path operation* iรงinde doฤŸrudan bir response dรถndรผrerek responseโ€™u override edebilirsiniz. + +Yukarฤฑdaki รถrneฤŸin aynฤฑsฤฑ, bu sefer bir `HTMLResponse` dรถndรผrerek, ลŸรถyle gรถrรผnebilir: + +{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} + +/// warning | Uyarฤฑ + +*path operation function*โ€™ฤฑnฤฑzฤฑn doฤŸrudan dรถndรผrdรผฤŸรผ bir `Response`, OpenAPIโ€™de dokรผmante edilmez (รถrneฤŸin `Content-Type` dokรผmante edilmez) ve otomatik interaktif dokรผmanlarda gรถrรผnmez. + +/// + +/// info | Bilgi + +Elbette gerรงek `Content-Type` headerโ€™ฤฑ, status code vb. deฤŸerler, dรถndรผrdรผฤŸรผnรผz `Response` objesinden gelir. + +/// + +### OpenAPIโ€™de Dokรผmante Et ve `Response`โ€™u Override Et { #document-in-openapi-and-override-response } + +Responseโ€™u fonksiyonun iรงinden override etmek ama aynฤฑ zamanda OpenAPIโ€™de "media type"โ€™ฤฑ dokรผmante etmek istiyorsanฤฑz, `response_class` parametresini kullanฤฑp ayrฤฑca bir `Response` objesi dรถndรผrebilirsiniz. + +Bu durumda `response_class` sadece OpenAPI *path operation*โ€™ฤฑnฤฑ dokรผmante etmek iรงin kullanฤฑlฤฑr; sizin `Response`โ€™unuz ise olduฤŸu gibi kullanฤฑlฤฑr. + +#### DoฤŸrudan bir `HTMLResponse` Dรถndรผr { #return-an-htmlresponse-directly } + +ร–rneฤŸin ลŸรถyle bir ลŸey olabilir: + +{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} + +Bu รถrnekte `generate_html_response()` fonksiyonu, HTMLโ€™i bir `str` olarak dรถndรผrmek yerine zaten bir `Response` รผretip dรถndรผrmektedir. + +`generate_html_response()` รงaฤŸrฤฑsฤฑnฤฑn sonucunu dรถndรผrerek, varsayฤฑlan **FastAPI** davranฤฑลŸฤฑnฤฑ override edecek bir `Response` dรถndรผrmรผลŸ olursunuz. + +Ama `response_class` iรงinde `HTMLResponse` da verdiฤŸiniz iรงin **FastAPI**, bunu OpenAPIโ€™de ve interaktif dokรผmanlarda `text/html` ile HTML olarak nasฤฑl dokรผmante edeceฤŸini bilir: + + + +## Mevcut Response'lar { #available-responses } + +Mevcut response'lardan bazฤฑlarฤฑ aลŸaฤŸฤฑdadฤฑr. + +Unutmayฤฑn: `Response` ile baลŸka herhangi bir ลŸeyi dรถndรผrebilir, hatta รถzel bir alt sฤฑnฤฑf da oluลŸturabilirsiniz. + +/// note | Teknik Detaylar + +`from starlette.responses import HTMLResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici iรงin kolaylฤฑk olsun diye `starlette.responses` iรงindekileri `fastapi.responses` olarak da saฤŸlar. Ancak mevcut response'larฤฑn รงoฤŸu doฤŸrudan Starletteโ€™ten gelir. + +/// + +### `Response` { #response } + +Ana `Response` classโ€™ฤฑdฤฑr; diฤŸer tรผm response'lar bundan tรผretilir. + +Bunu doฤŸrudan dรถndรผrebilirsiniz. + +ลžu parametreleri kabul eder: + +* `content` - Bir `str` veya `bytes`. +* `status_code` - Bir `int` HTTP status code. +* `headers` - Stringโ€™lerden oluลŸan bir `dict`. +* `media_type` - Media typeโ€™ฤฑ veren bir `str`. ร–rn. `"text/html"`. + +FastAPI (aslฤฑnda Starlette) otomatik olarak bir Content-Length headerโ€™ฤฑ ekler. Ayrฤฑca `media_type`โ€™a gรถre bir Content-Type headerโ€™ฤฑ ekler ve text tรผrleri iรงin sona bir charset ekler. + +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +Yukarฤฑda okuduฤŸunuz gibi, bir miktar text veya bytes alฤฑr ve HTML response dรถndรผrรผr. + +### `PlainTextResponse` { #plaintextresponse } + +Bir miktar text veya bytes alฤฑr ve dรผz metin response dรถndรผrรผr. + +{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +Bir miktar veri alฤฑr ve `application/json` olarak encode edilmiลŸ bir response dรถndรผrรผr. + +Yukarฤฑda okuduฤŸunuz gibi, **FastAPI**โ€™de varsayฤฑlan response budur. + +### `ORJSONResponse` { #orjsonresponse } + +Yukarฤฑda okuduฤŸunuz gibi `orjson` kullanan hฤฑzlฤฑ bir alternatif JSON response. + +/// info | Bilgi + +Bunun iรงin `orjson` kurulmalฤฑdฤฑr; รถrneฤŸin `pip install orjson`. + +/// + +### `UJSONResponse` { #ujsonresponse } + +`ujson` kullanan alternatif bir JSON response. + +/// info | Bilgi + +Bunun iรงin `ujson` kurulmalฤฑdฤฑr; รถrneฤŸin `pip install ujson`. + +/// + +/// warning | Uyarฤฑ + +`ujson`, bazฤฑ edge-caseโ€™leri ele alma konusunda Pythonโ€™un built-in implementasyonu kadar dikkatli deฤŸildir. + +/// + +{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} + +/// tip | ฤฐpucu + +`ORJSONResponse` daha hฤฑzlฤฑ bir alternatif olabilir. + +/// + +### `RedirectResponse` { #redirectresponse } + +HTTP redirect dรถndรผrรผr. Varsayฤฑlan olarak 307 status code (Temporary Redirect) kullanฤฑr. + +`RedirectResponse`โ€™u doฤŸrudan dรถndรผrebilirsiniz: + +{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} + +--- + +Veya `response_class` parametresi iรงinde kullanabilirsiniz: + +{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} + +Bunu yaparsanฤฑz, *path operation* functionโ€™ฤฑnฤฑzdan doฤŸrudan URL dรถndรผrebilirsiniz. + +Bu durumda kullanฤฑlan `status_code`, `RedirectResponse` iรงin varsayฤฑlan olan `307` olur. + +--- + +Ayrฤฑca `status_code` parametresini `response_class` parametresiyle birlikte kullanabilirsiniz: + +{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +Bir async generator veya normal generator/iterator alฤฑr ve response bodyโ€™yi stream eder. + +{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} + +#### `StreamingResponse`โ€™u file-like objelerle kullanma { #using-streamingresponse-with-file-like-objects } + +Bir file-like objeniz varsa (รถrn. `open()`โ€™ฤฑn dรถndรผrdรผฤŸรผ obje), o file-like obje รผzerinde iterate eden bir generator function oluลŸturabilirsiniz. + +Bรถylece รถnce hepsini memoryโ€™ye okumak zorunda kalmazsฤฑnฤฑz; bu generator functionโ€™ฤฑ `StreamingResponse`โ€™a verip dรถndรผrebilirsiniz. + +Buna cloud storage ile etkileลŸime giren, video iลŸleyen ve benzeri birรงok kรผtรผphane dahildir. + +{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} + +1. Bu generator functionโ€™dฤฑr. ฤฐรงinde `yield` ifadeleri olduฤŸu iรงin "generator function" denir. +2. Bir `with` bloฤŸu kullanarak, generator function bittiฤŸinde file-like objenin kapandฤฑฤŸฤฑndan emin oluruz. Yani response gรถndermeyi bitirdikten sonra kapanฤฑr. +3. Bu `yield from`, fonksiyona `file_like` isimli ลŸeyi iterate etmesini sรถyler. Ardฤฑndan iterate edilen her parรงa iรงin, o parรงayฤฑ bu generator functionโ€™dan (`iterfile`) geliyormuลŸ gibi yield eder. + + Yani, iรงerdeki "รผretme" (generating) iลŸini baลŸka bir ลŸeye devreden bir generator functionโ€™dฤฑr. + + Bunu bu ลŸekilde yaptฤฑฤŸฤฑmฤฑzda `with` bloฤŸu iรงinde tutabilir ve bรถylece iลŸ bitince file-like objenin kapanmasฤฑnฤฑ garanti edebiliriz. + +/// tip | ฤฐpucu + +Burada `async` ve `await` desteklemeyen standart `open()` kullandฤฑฤŸฤฑmฤฑz iรงin path operationโ€™ฤฑ normal `def` ile tanฤฑmlarฤฑz. + +/// + +### `FileResponse` { #fileresponse } + +Asenkron olarak bir dosyayฤฑ response olarak stream eder. + +DiฤŸer response tรผrlerine gรถre instantiate ederken farklฤฑ argรผmanlar alฤฑr: + +* `path` - Stream edilecek dosyanฤฑn dosya path'i. +* `headers` - Eklenecek รถzel headerโ€™lar; dictionary olarak. +* `media_type` - Media typeโ€™ฤฑ veren string. Ayarlanmazsa, dosya adฤฑ veya path kullanฤฑlarak media type tahmin edilir. +* `filename` - Ayarlanฤฑrsa response iรงindeki `Content-Disposition`โ€™a dahil edilir. + +File response'larฤฑ uygun `Content-Length`, `Last-Modified` ve `ETag` headerโ€™larฤฑnฤฑ iรงerir. + +{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} + +`response_class` parametresini de kullanabilirsiniz: + +{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} + +Bu durumda *path operation* functionโ€™ฤฑnฤฑzdan doฤŸrudan dosya path'ini dรถndรผrebilirsiniz. + +## ร–zel response class { #custom-response-class } + +`Response`โ€™dan tรผreterek kendi รถzel response classโ€™ฤฑnฤฑzฤฑ oluลŸturabilir ve kullanabilirsiniz. + +ร–rneฤŸin, dahil gelen `ORJSONResponse` classโ€™ฤฑnda kullanฤฑlmayan bazฤฑ รถzel ayarlarla `orjson` kullanmak istediฤŸinizi varsayalฤฑm. + +Diyelim ki girintili ve biรงimlendirilmiลŸ JSON dรถndรผrmek istiyorsunuz; bunun iรงin `orjson.OPT_INDENT_2` seรงeneฤŸini kullanmak istiyorsunuz. + +Bir `CustomORJSONResponse` oluลŸturabilirsiniz. Burada yapmanฤฑz gereken temel ลŸey, contentโ€™i `bytes` olarak dรถndรผren bir `Response.render(content)` metodu yazmaktฤฑr: + +{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} + +Artฤฑk ลŸunu dรถndรผrmek yerine: + +```json +{"message": "Hello World"} +``` + +...bu response ลŸunu dรถndรผrรผr: + +```json +{ + "message": "Hello World" +} +``` + +Elbette JSONโ€™u formatlamaktan รงok daha iyi ลŸekillerde bundan faydalanabilirsiniz. ๐Ÿ˜‰ + +## Varsayฤฑlan response class { #default-response-class } + +Bir **FastAPI** class instanceโ€™ฤฑ veya bir `APIRouter` oluลŸtururken, varsayฤฑlan olarak hangi response classโ€™ฤฑnฤฑn kullanฤฑlacaฤŸฤฑnฤฑ belirtebilirsiniz. + +Bunu tanฤฑmlayan parametre `default_response_class`โ€™tฤฑr. + +AลŸaฤŸฤฑdaki รถrnekte **FastAPI**, tรผm *path operations* iรงin varsayฤฑlan olarak `JSONResponse` yerine `ORJSONResponse` kullanฤฑr. + +{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} + +/// tip | ฤฐpucu + +Daha รถnce olduฤŸu gibi, *path operations* iรงinde `response_class`โ€™ฤฑ yine override edebilirsiniz. + +/// + +## Ek dokรผmantasyon { #additional-documentation } + +OpenAPIโ€™de media typeโ€™ฤฑ ve daha birรงok detayฤฑ `responses` kullanarak da tanฤฑmlayabilirsiniz: [OpenAPIโ€™de Ek Response'lar](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/tr/docs/advanced/dataclasses.md b/docs/tr/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..2639760070 --- /dev/null +++ b/docs/tr/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Dataclass Kullanฤฑmฤฑ { #using-dataclasses } + +FastAPI, **Pydantic** รผzerine inลŸa edilmiลŸtir ve request/response tanฤฑmlamak iรงin Pydantic model'lerini nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ gรถsteriyordum. + +Ancak FastAPI, `dataclasses` kullanmayฤฑ da aynฤฑ ลŸekilde destekler: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +Bu destek hรขlรข **Pydantic** sayesinde vardฤฑr; รงรผnkรผ Pydantic, `dataclasses` iรงin dahili destek sunar. + +Yani yukarฤฑdaki kod Pydantic'i doฤŸrudan kullanmasa bile, FastAPI bu standart dataclass'larฤฑ Pydantic'in kendi dataclass biรงimine dรถnรผลŸtรผrmek iรงin Pydantic'i kullanmaktadฤฑr. + +Ve elbette aynฤฑ รถzellikleri destekler: + +* veri doฤŸrulama (data validation) +* veri serileลŸtirme (data serialization) +* veri dokรผmantasyonu (data documentation), vb. + +Bu, Pydantic model'lerinde olduฤŸu gibi รงalฤฑลŸฤฑr. Aslฤฑnda arka planda da aynฤฑ ลŸekilde, Pydantic kullanฤฑlarak yapฤฑlฤฑr. + +/// info | Bilgi + +Dataclass'larฤฑn, Pydantic model'lerinin yapabildiฤŸi her ลŸeyi yapamadฤฑฤŸฤฑnฤฑ unutmayฤฑn. + +Bu yรผzden yine de Pydantic model'lerini kullanmanฤฑz gerekebilir. + +Ancak elinizde zaten bir sรผrรผ dataclass varsa, bunlarฤฑ FastAPI ile bir web API'yi beslemek iรงin kullanmak gรผzel bir numaradฤฑr. ๐Ÿค“ + +/// + +## `response_model` ฤฐรงinde Dataclass'lar { #dataclasses-in-response-model } + +`response_model` parametresinde `dataclasses` da kullanabilirsiniz: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +Dataclass otomatik olarak bir Pydantic dataclass'ฤฑna dรถnรผลŸtรผrรผlรผr. + +Bu sayede ลŸemasฤฑ API docs kullanฤฑcฤฑ arayรผzรผnde gรถrรผnรผr: + + + +## ฤฐรง ฤฐรงe Veri Yapฤฑlarฤฑnda Dataclass'lar { #dataclasses-in-nested-data-structures } + +ฤฐรง iรงe veri yapฤฑlarฤฑ oluลŸturmak iรงin `dataclasses` ile diฤŸer type annotation'larฤฑ da birleลŸtirebilirsiniz. + +Bazฤฑ durumlarda yine de Pydantic'in `dataclasses` sรผrรผmรผnรผ kullanmanฤฑz gerekebilir. ร–rneฤŸin, otomatik oluลŸturulan API dokรผmantasyonunda hata alฤฑyorsanฤฑz. + +Bu durumda standart `dataclasses` yerine, drop-in replacement olan `pydantic.dataclasses` kullanabilirsiniz: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. `field` hรขlรข standart `dataclasses` iรงinden import edilir. + +2. `pydantic.dataclasses`, `dataclasses` iรงin bir drop-in replacement'tฤฑr. + +3. `Author` dataclass'ฤฑ, `Item` dataclass'larฤฑndan oluลŸan bir liste iรงerir. + +4. `Author` dataclass'ฤฑ, `response_model` parametresi olarak kullanฤฑlฤฑr. + +5. Request body olarak dataclass'larla birlikte diฤŸer standart type annotation'larฤฑ da kullanabilirsiniz. + + Bu รถrnekte, `Item` dataclass'larฤฑndan oluลŸan bir listedir. + +6. Burada `items` iรงeren bir dictionary dรถndรผrรผyoruz; `items` bir dataclass listesi. + + FastAPI, veriyi JSON'a serializing etmeyi yine baลŸarฤฑr. + +7. Burada `response_model`, `Author` dataclass'larฤฑndan oluลŸan bir listenin type annotation'ฤฑnฤฑ kullanฤฑyor. + + Yine `dataclasses` ile standart type annotation'larฤฑ birleลŸtirebilirsiniz. + +8. Bu *path operation function*, `async def` yerine normal `def` kullanฤฑyor. + + Her zaman olduฤŸu gibi, FastAPI'de ihtiyaca gรถre `def` ve `async def`โ€™i birlikte kullanabilirsiniz. + + Hangisini ne zaman kullanmanฤฑz gerektiฤŸine dair hฤฑzlฤฑ bir hatฤฑrlatma isterseniz, [`async` ve `await`](../async.md#in-a-hurry){.internal-link target=_blank} dokรผmanฤฑndaki _"In a hurry?"_ bรถlรผmรผne bakฤฑn. + +9. Bu *path operation function* dataclass dรถndรผrmรผyor (isterse dรถndรผrebilir), onun yerine dahili verilerle bir dictionary listesi dรถndรผrรผyor. + + FastAPI, response'u dรถnรผลŸtรผrmek iรงin (dataclass'larฤฑ iรงeren) `response_model` parametresini kullanacaktฤฑr. + +KarmaลŸฤฑk veri yapฤฑlarฤฑ oluลŸturmak iรงin `dataclasses` ile diฤŸer type annotation'larฤฑ pek รงok farklฤฑ kombinasyonda birleลŸtirebilirsiniz. + +Daha spesifik ayrฤฑntฤฑlar iรงin yukarฤฑdaki kod iรงi annotation ipuรงlarฤฑna bakฤฑn. + +## Daha Fazla ร–ฤŸrenin { #learn-more } + +`dataclasses`'ฤฑ diฤŸer Pydantic model'leriyle de birleลŸtirebilir, onlardan kalฤฑtฤฑm alabilir, kendi model'lerinize dahil edebilirsiniz, vb. + +Daha fazlasฤฑ iรงin Pydantic'in dataclasses dokรผmantasyonuna bakฤฑn. + +## Sรผrรผm { #version } + +Bu รถzellik FastAPI `0.67.0` sรผrรผmรผnden beri mevcuttur. ๐Ÿ”– diff --git a/docs/tr/docs/advanced/events.md b/docs/tr/docs/advanced/events.md new file mode 100644 index 0000000000..257b952f95 --- /dev/null +++ b/docs/tr/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan Olaylarฤฑ { #lifespan-events } + +Uygulama **baลŸlamadan** รถnce รงalฤฑลŸtฤฑrฤฑlmasฤฑ gereken mantฤฑฤŸฤฑ (kodu) tanฤฑmlayabilirsiniz. Bu, bu kodun **bir kez**, uygulama **request almaya baลŸlamadan รถnce** รงalฤฑลŸtฤฑrฤฑlacaฤŸฤฑ anlamฤฑna gelir. + +Benzer ลŸekilde, uygulama **kapanฤฑrken** รงalฤฑลŸtฤฑrฤฑlmasฤฑ gereken mantฤฑฤŸฤฑ (kodu) da tanฤฑmlayabilirsiniz. Bu durumda bu kod, muhtemelen **รงok sayฤฑda request** iลŸlendi **sonra**, **bir kez** รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Bu kod, uygulama request almaya **baลŸlamadan** รถnce ve requestโ€™leri iลŸlemeyi **bitirdikten** hemen sonra รงalฤฑลŸtฤฑฤŸฤฑ iรงin, uygulamanฤฑn tรผm **lifespan**โ€™ฤฑnฤฑ (birazdan "lifespan" kelimesi รถnemli olacak ๐Ÿ˜‰) kapsar. + +Bu yaklaลŸฤฑm, tรผm uygulama boyunca kullanacaฤŸฤฑnฤฑz ve requestโ€™ler arasฤฑnda **paylaลŸฤฑlan** **resource**โ€™larฤฑ kurmak ve/veya sonrasฤฑnda bunlarฤฑ **temizlemek** iรงin รงok faydalฤฑdฤฑr. ร–rneฤŸin bir veritabanฤฑ connection poolโ€™u ya da paylaลŸฤฑlan bir machine learning modelini yรผklemek gibi. + +## Kullanฤฑm Senaryosu { #use-case } + +ร–nce bir **kullanฤฑm senaryosu** รถrneฤŸiyle baลŸlayalฤฑm, sonra bunu bununla nasฤฑl รงรถzeceฤŸimize bakalฤฑm. + +Requestโ€™leri iลŸlemek iรงin kullanmak istediฤŸiniz bazฤฑ **machine learning modelleriniz** olduฤŸunu hayal edelim. ๐Ÿค– + +Aynฤฑ modeller requestโ€™ler arasฤฑnda paylaลŸฤฑlฤฑr; yani request baลŸฤฑna bir model, kullanฤฑcฤฑ baลŸฤฑna bir model vb. gibi deฤŸil. + +Modeli yรผklemenin, diskten รงok fazla **data** okunmasฤฑ gerektiฤŸi iรงin **oldukรงa uzun sรผrebildiฤŸini** dรผลŸรผnelim. Dolayฤฑsฤฑyla bunu her request iรงin yapmak istemezsiniz. + +Modeli modรผlรผn/dosyanฤฑn en รผst seviyesinde yรผkleyebilirdiniz; ancak bu, basit bir otomatik test รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda bile **modelin yรผkleneceฤŸi** anlamฤฑna gelir. Bรถyle olunca test, kodun baฤŸฤฑmsฤฑz bir kฤฑsmฤฑnฤฑ รงalฤฑลŸtฤฑrabilmek iรงin รถnce modelin yรผklenmesini beklemek zorunda kalฤฑr ve **yavaลŸ** olur. + +Burada รงรถzeceฤŸimiz ลŸey bu: modeli requestโ€™ler iลŸlenmeden รถnce yรผkleyelim, ama kod yรผklenirken deฤŸil; yalnฤฑzca uygulama request almaya baลŸlamadan hemen รถnce. + +## Lifespan { #lifespan } + +Bu *startup* ve *shutdown* mantฤฑฤŸฤฑnฤฑ, `FastAPI` uygulamasฤฑnฤฑn `lifespan` parametresi ve bir "context manager" kullanarak tanฤฑmlayabilirsiniz (bunun ne olduฤŸunu birazdan gรถstereceฤŸim). + +ร–nce bir รถrnekle baลŸlayฤฑp sonra ayrฤฑntฤฑlarฤฑna bakalฤฑm. + +AลŸaฤŸฤฑdaki gibi `yield` kullanan async bir `lifespan()` fonksiyonu oluลŸturuyoruz: + +{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} + +Burada, `yield` รถncesinde (sahte) model fonksiyonunu machine learning modellerini iรงeren dictionaryโ€™e koyarak, modeli yรผkleme gibi maliyetli bir *startup* iลŸlemini simรผle ediyoruz. Bu kod, *startup* sฤฑrasฤฑnda, uygulama **request almaya baลŸlamadan รถnce** รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Ardฤฑndan `yield`โ€™den hemen sonra modeli bellekten kaldฤฑrฤฑyoruz (unload). Bu kod, uygulama **requestโ€™leri iลŸlemeyi bitirdikten sonra**, *shutdown*โ€™dan hemen รถnce รงalฤฑลŸtฤฑrฤฑlฤฑr. ร–rneฤŸin memory veya GPU gibi resourceโ€™larฤฑ serbest bฤฑrakabilir. + +/// tip | ฤฐpucu + +`shutdown`, uygulamayฤฑ **durdurduฤŸunuzda** gerรงekleลŸir. + +Belki yeni bir sรผrรผm baลŸlatmanฤฑz gerekiyordur, ya da รงalฤฑลŸtฤฑrmaktan sฤฑkฤฑlmฤฑลŸsฤฑnฤฑzdฤฑr. ๐Ÿคท + +/// + +### Lifespan fonksiyonu { #lifespan-function } + +Dikkat edilmesi gereken ilk ลŸey, `yield` iรงeren async bir fonksiyon tanฤฑmlฤฑyor olmamฤฑz. Bu, `yield` kullanan Dependenciesโ€™e oldukรงa benzer. + +{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} + +Fonksiyonun `yield`โ€™den รถnceki kฤฑsmฤฑ, uygulama baลŸlamadan **รถnce** รงalฤฑลŸฤฑr. + +`yield`โ€™den sonraki kฤฑsฤฑm ise, uygulama iลŸini bitirdikten **sonra** รงalฤฑลŸฤฑr. + +### Async Context Manager { #async-context-manager } + +Bakarsanฤฑz, fonksiyon `@asynccontextmanager` ile dekore edilmiลŸ. + +Bu da fonksiyonu "**async context manager**" denen ลŸeye dรถnรผลŸtรผrรผr. + +{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} + +Pythonโ€™da **context manager**, `with` ifadesi iรงinde kullanabildiฤŸiniz bir yapฤฑdฤฑr. ร–rneฤŸin `open()` bir context manager olarak kullanฤฑlabilir: + +```Python +with open("file.txt") as file: + file.read() +``` + +Pythonโ€™ฤฑn gรผncel sรผrรผmlerinde bir de **async context manager** vardฤฑr. Bunu `async with` ile kullanฤฑrsฤฑnฤฑz: + +```Python +async with lifespan(app): + await do_stuff() +``` + +Yukarฤฑdaki gibi bir context manager veya async context manager oluลŸturduฤŸunuzda, yaptฤฑฤŸฤฑ ลŸey ลŸudur: `with` bloฤŸuna girmeden รถnce `yield`โ€™den รถnceki kodu รงalฤฑลŸtฤฑrฤฑr, `with` bloฤŸundan รงฤฑktฤฑktan sonra da `yield`โ€™den sonraki kodu รงalฤฑลŸtฤฑrฤฑr. + +Yukarฤฑdaki kod รถrneฤŸimizde bunu doฤŸrudan kullanmฤฑyoruz; bunun yerine FastAPIโ€™ye veriyoruz ki o kullansฤฑn. + +`FastAPI` uygulamasฤฑnฤฑn `lifespan` parametresi bir **async context manager** alฤฑr; dolayฤฑsฤฑyla oluลŸturduฤŸumuz yeni `lifespan` async context managerโ€™ฤฑnฤฑ buraya geรงebiliriz. + +{* ../../docs_src/events/tutorial003_py39.py hl[22] *} + +## Alternatif Events (kullanฤฑmdan kaldฤฑrฤฑldฤฑ) { #alternative-events-deprecated } + +/// warning | Uyarฤฑ + +*startup* ve *shutdown* iลŸlemlerini yรถnetmenin รถnerilen yolu, yukarฤฑda anlatฤฑldฤฑฤŸฤฑ gibi `FastAPI` uygulamasฤฑnฤฑn `lifespan` parametresini kullanmaktฤฑr. Bir `lifespan` parametresi saฤŸlarsanฤฑz, `startup` ve `shutdown` event handlerโ€™larฤฑ artฤฑk รงaฤŸrฤฑlmaz. Ya tamamen `lifespan` ya da tamamen events; ikisi birden deฤŸil. + +Muhtemelen bu bรถlรผmรผ atlayabilirsiniz. + +/// + +*startup* ve *shutdown* sฤฑrasฤฑnda รงalฤฑลŸtฤฑrฤฑlacak bu mantฤฑฤŸฤฑ tanฤฑmlamanฤฑn alternatif bir yolu daha vardฤฑr. + +Uygulama baลŸlamadan รถnce veya uygulama kapanฤฑrken รงalฤฑลŸtฤฑrฤฑlmasฤฑ gereken event handlerโ€™larฤฑ (fonksiyonlarฤฑ) tanฤฑmlayabilirsiniz. + +Bu fonksiyonlar `async def` ile veya normal `def` ile tanฤฑmlanabilir. + +### `startup` eventi { #startup-event } + +Uygulama baลŸlamadan รถnce รงalฤฑลŸtฤฑrฤฑlacak bir fonksiyon eklemek iรงin, `"startup"` eventโ€™i ile tanฤฑmlayฤฑn: + +{* ../../docs_src/events/tutorial001_py39.py hl[8] *} + +Bu durumda `startup` event handler fonksiyonu, "database" รถฤŸesini (sadece bir `dict`) bazฤฑ deฤŸerlerle baลŸlatฤฑr. + +Birden fazla event handler fonksiyonu ekleyebilirsiniz. + +Ve tรผm `startup` event handlerโ€™larฤฑ tamamlanmadan uygulamanฤฑz request almaya baลŸlamaz. + +### `shutdown` eventi { #shutdown-event } + +Uygulama kapanฤฑrken รงalฤฑลŸtฤฑrฤฑlacak bir fonksiyon eklemek iรงin, `"shutdown"` eventโ€™i ile tanฤฑmlayฤฑn: + +{* ../../docs_src/events/tutorial002_py39.py hl[6] *} + +Burada `shutdown` event handler fonksiyonu, `log.txt` dosyasฤฑna `"Application shutdown"` satฤฑrฤฑnฤฑ yazar. + +/// info | Bilgi + +`open()` fonksiyonunda `mode="a"` "append" anlamฤฑna gelir; yani satฤฑr, รถnceki iรงeriฤŸi silmeden dosyada ne varsa onun sonuna eklenir. + +/// + +/// tip | ฤฐpucu + +Dikkat edin, bu รถrnekte bir dosyayla etkileลŸen standart Python `open()` fonksiyonunu kullanฤฑyoruz. + +Dolayฤฑsฤฑyla diskโ€™e yazฤฑlmasฤฑnฤฑ beklemeyi gerektiren I/O (input/output) sรถz konusu. + +Ancak `open()` `async` ve `await` kullanmaz. + +Bu yรผzden event handler fonksiyonunu `async def` yerine standart `def` ile tanฤฑmlarฤฑz. + +/// + +### `startup` ve `shutdown` birlikte { #startup-and-shutdown-together } + +*startup* ve *shutdown* mantฤฑฤŸฤฑnฤฑzฤฑn birbiriyle baฤŸlantฤฑlฤฑ olma ihtimali yรผksektir; bir ลŸeyi baลŸlatฤฑp sonra bitirmek, bir resource edinip sonra serbest bฤฑrakmak vb. isteyebilirsiniz. + +Bunu, ortak mantฤฑk veya deฤŸiลŸken paylaลŸmayan ayrฤฑ fonksiyonlarda yapmak daha zordur; รงรผnkรผ deฤŸerleri global deฤŸiลŸkenlerde tutmanฤฑz veya benzer numaralar yapmanฤฑz gerekir. + +Bu nedenle artฤฑk bunun yerine, yukarฤฑda aรงฤฑklandฤฑฤŸฤฑ gibi `lifespan` kullanmanฤฑz รถnerilmektedir. + +## Teknik Detaylar { #technical-details } + +Meraklฤฑ nerdโ€™ler iรงin kรผรงรผk bir teknik detay. ๐Ÿค“ + +Altta, ASGI teknik spesifikasyonunda bu, Lifespan Protocolโ€™รผn bir parรงasฤฑdฤฑr ve `startup` ile `shutdown` adฤฑnda eventโ€™ler tanฤฑmlar. + +/// info | Bilgi + +Starlette `lifespan` handlerโ€™larฤฑ hakkฤฑnda daha fazlasฤฑnฤฑ Starlette's Lifespan docs iรงinde okuyabilirsiniz. + +Ayrฤฑca kodunuzun baลŸka bรถlgelerinde de kullanฤฑlabilecek lifespan stateโ€™i nasฤฑl yรถneteceฤŸinizi de kapsar. + +/// + +## Alt Uygulamalar { #sub-applications } + +๐Ÿšจ Unutmayฤฑn: Bu lifespan eventโ€™leri (`startup` ve `shutdown`) yalnฤฑzca ana uygulama iรงin รงalฤฑลŸtฤฑrฤฑlฤฑr; [Alt Uygulamalar - Mounts](sub-applications.md){.internal-link target=_blank} iรงin รงalฤฑลŸtฤฑrฤฑlmaz. diff --git a/docs/tr/docs/advanced/generate-clients.md b/docs/tr/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..af278f2fef --- /dev/null +++ b/docs/tr/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# SDK รœretme { #generating-sdks } + +**FastAPI**, **OpenAPI** spesifikasyonunu temel aldฤฑฤŸฤฑ iรงin API'leri birรงok aracฤฑn anlayabildiฤŸi standart bir formatta tanฤฑmlanabilir. + +Bu sayede gรผncel **dokรผmantasyon**, birden fazla dilde istemci kรผtรผphaneleri (**SDKs**) ve kodunuzla senkron kalan **test** veya **otomasyon iลŸ akฤฑลŸlarฤฑ** รผretmek kolaylaลŸฤฑr. + +Bu rehberde, FastAPI backend'iniz iรงin bir **TypeScript SDK** รผretmeyi รถฤŸreneceksiniz. + +## Aรงฤฑk Kaynak SDK รœreteรงleri { #open-source-sdk-generators } + +Esnek bir seรงenek olan OpenAPI Generator, **birรงok programlama dilini** destekler ve OpenAPI spesifikasyonunuzdan SDK รผretebilir. + +**TypeScript client**'lar iรงin Hey API, TypeScript ekosistemi iรงin รถzel olarak tasarlanmฤฑลŸ, optimize bir deneyim sunan bir รงรถzรผmdรผr. + +Daha fazla SDK รผretecini OpenAPI.Tools รผzerinde keลŸfedebilirsiniz. + +/// tip | ฤฐpucu + +FastAPI otomatik olarak **OpenAPI 3.1** spesifikasyonlarฤฑ รผretir; bu yรผzden kullanacaฤŸฤฑnฤฑz aracฤฑn bu sรผrรผmรผ desteklemesi gerekir. + +/// + +## FastAPI Sponsorlarฤฑndan SDK รœreteรงleri { #sdk-generators-from-fastapi-sponsors } + +Bu bรถlรผm, FastAPI'yi sponsorlayan ลŸirketlerin sunduฤŸu **yatฤฑrฤฑm destekli** ve **ลŸirket destekli** รงรถzรผmleri รถne รงฤฑkarฤฑr. Bu รผrรผnler, yรผksek kaliteli รผretilen SDK'larฤฑn รผzerine **ek รถzellikler** ve **entegrasyonlar** saฤŸlar. + +โœจ [**FastAPI'ye sponsor olarak**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ bu ลŸirketler, framework'รผn ve **ekosisteminin** saฤŸlฤฑklฤฑ ve **sรผrdรผrรผlebilir** kalmasฤฑna yardฤฑmcฤฑ olur. + +Sponsor olmalarฤฑ aynฤฑ zamanda FastAPI **topluluฤŸuna** (size) gรผรงlรผ bir baฤŸlฤฑlฤฑฤŸฤฑ da gรถsterir; yalnฤฑzca **iyi bir hizmet** sunmayฤฑ deฤŸil, aynฤฑ zamanda **gรผรงlรผ ve geliลŸen bir framework** olan FastAPI'yi desteklemeyi de รถnemsediklerini gรถsterir. ๐Ÿ™‡ + +ร–rneฤŸin ลŸunlarฤฑ deneyebilirsiniz: + +* Speakeasy +* Stainless +* liblab + +Bu รงรถzรผmlerin bazฤฑlarฤฑ aรงฤฑk kaynak olabilir veya รผcretsiz katman sunabilir; yani finansal bir taahhรผt olmadan deneyebilirsiniz. BaลŸka ticari SDK รผreteรงleri de vardฤฑr ve internette bulunabilir. ๐Ÿค“ + +## TypeScript SDK OluลŸturma { #create-a-typescript-sdk } + +Basit bir FastAPI uygulamasฤฑyla baลŸlayalฤฑm: + +{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} + +*Path operation*'larฤฑn, request payload ve response payload iรงin kullandฤฑklarฤฑ modelleri `Item` ve `ResponseMessage` modelleriyle tanฤฑmladฤฑklarฤฑna dikkat edin. + +### API Dokรผmanlarฤฑ { #api-docs } + +`/docs` adresine giderseniz, request'lerde gรถnderilecek ve response'larda alฤฑnacak veriler iรงin **schema**'larฤฑ iรงerdiฤŸini gรถrรผrsรผnรผz: + + + +Bu schema'larฤฑ gรถrebilirsiniz, รงรผnkรผ uygulamada modellerle birlikte tanฤฑmlandฤฑlar. + +Bu bilgi uygulamanฤฑn **OpenAPI schema**'sฤฑnda bulunur ve sonrasฤฑnda API dokรผmanlarฤฑnda gรถsterilir. + +OpenAPI'ye dahil edilen, modellerden gelen bu bilginin aynฤฑsฤฑ **client code รผretmek** iรงin kullanฤฑlabilir. + +### Hey API { #hey-api } + +Modelleri olan bir FastAPI uygulamamฤฑz olduฤŸunda, Hey API ile bir TypeScript client รผretebiliriz. Bunu yapmanฤฑn en hฤฑzlฤฑ yolu npx kullanmaktฤฑr. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +Bu komut `./src/client` iรงine bir TypeScript SDK รผretecektir. + +Web sitelerinde `@hey-api/openapi-ts` kurulumunu รถฤŸrenebilir ve รผretilen รงฤฑktฤฑyฤฑ inceleyebilirsiniz. + +### SDK'yฤฑ Kullanma { #using-the-sdk } + +Artฤฑk client code'u import edip kullanabilirsiniz. ลžuna benzer gรถrรผnebilir; method'lar iรงin otomatik tamamlama aldฤฑฤŸฤฑnฤฑza dikkat edin: + + + +Ayrฤฑca gรถnderilecek payload iรงin de otomatik tamamlama alฤฑrsฤฑnฤฑz: + + + +/// tip | ฤฐpucu + +`name` ve `price` iรงin otomatik tamamlamaya dikkat edin; bunlar FastAPI uygulamasฤฑnda, `Item` modelinde tanฤฑmlanmฤฑลŸtฤฑ. + +/// + +GรถnderdiฤŸiniz veriler iรงin satฤฑr iรงi hatalar (inline errors) da alฤฑrsฤฑnฤฑz: + + + +Response objesi de otomatik tamamlama sunacaktฤฑr: + + + +## Tag'lerle FastAPI Uygulamasฤฑ { #fastapi-app-with-tags } + +Birรงok durumda FastAPI uygulamanฤฑz daha bรผyรผk olacaktฤฑr ve farklฤฑ *path operation* gruplarฤฑnฤฑ ayฤฑrmak iรงin muhtemelen tag'leri kullanacaksฤฑnฤฑz. + +ร–rneฤŸin **items** iรงin bir bรถlรผm, **users** iรงin baลŸka bir bรถlรผm olabilir ve bunlarฤฑ tag'lerle ayฤฑrabilirsiniz: + +{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} + +### Tag'lerle TypeScript Client รœretme { #generate-a-typescript-client-with-tags } + +Tag'leri kullanan bir FastAPI uygulamasฤฑ iรงin client รผrettiฤŸinizde, genelde client code da tag'lere gรถre ayrฤฑlฤฑr. + +Bu sayede client code tarafฤฑnda her ลŸey doฤŸru ลŸekilde sฤฑralanฤฑr ve gruplandฤฑrฤฑlฤฑr: + + + +Bu รถrnekte ลŸunlar var: + +* `ItemsService` +* `UsersService` + +### Client Method ฤฐsimleri { #client-method-names } + +ลžu an รผretilen `createItemItemsPost` gibi method isimleri รงok temiz gรถrรผnmรผyor: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...รงรผnkรผ client รผreteci, her *path operation* iรงin OpenAPI'nin dahili **operation ID** deฤŸerini kullanฤฑr. + +OpenAPI, her operation ID'nin tรผm *path operation*'lar arasฤฑnda benzersiz olmasฤฑnฤฑ ister. Bu yรผzden FastAPI; operation ID'yi benzersiz tutabilmek iรงin **function adฤฑ**, **path** ve **HTTP method/operation** bilgilerini birleลŸtirerek รผretir. + +Ancak bunu bir sonraki adฤฑmda nasฤฑl iyileลŸtirebileceฤŸinizi gรถstereceฤŸim. ๐Ÿค“ + +## ร–zel Operation ID'ler ve Daha ฤฐyi Method ฤฐsimleri { #custom-operation-ids-and-better-method-names } + +Bu operation ID'lerin **รผretilme** ลŸeklini **deฤŸiลŸtirerek**, client'larda daha basit **method isimleri** elde edebilirsiniz. + +Bu durumda, her operation ID'nin **benzersiz** olduฤŸundan baลŸka bir ลŸekilde emin olmanฤฑz gerekir. + +ร–rneฤŸin, her *path operation*'ฤฑn bir tag'i olmasฤฑnฤฑ saฤŸlayabilir ve operation ID'yi **tag** ve *path operation* **adฤฑ**na (function adฤฑ) gรถre รผretebilirsiniz. + +### Benzersiz ID รœreten ร–zel Fonksiyon { #custom-generate-unique-id-function } + +FastAPI, her *path operation* iรงin bir **unique ID** kullanฤฑr. Bu ID, **operation ID** iรงin ve ayrฤฑca request/response'lar iรงin gerekebilecek รถzel model isimleri iรงin de kullanฤฑlฤฑr. + +Bu fonksiyonu รถzelleลŸtirebilirsiniz. Bir `APIRoute` alฤฑr ve string dรถndรผrรผr. + +ร–rneฤŸin burada ilk tag'i (muhtemelen tek tag'iniz olur) ve *path operation* adฤฑnฤฑ (function adฤฑ) kullanฤฑyor. + +Sonrasฤฑnda bu รถzel fonksiyonu `generate_unique_id_function` parametresiyle **FastAPI**'ye geรงebilirsiniz: + +{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} + +### ร–zel Operation ID'lerle TypeScript Client รœretme { #generate-a-typescript-client-with-custom-operation-ids } + +Artฤฑk client'ฤฑ tekrar รผretirseniz, geliลŸtirilmiลŸ method isimlerini gรถreceksiniz: + + + +GรถrdรผฤŸรผnรผz gibi method isimleri artฤฑk รถnce tag'i, sonra function adฤฑnฤฑ iรงeriyor; URL path'i ve HTTP operation bilgisini artฤฑk taลŸฤฑmฤฑyor. + +### Client รœretecine Vermeden ร–nce OpenAPI Spesifikasyonunu ร–n ฤฐลŸlemek { #preprocess-the-openapi-specification-for-the-client-generator } + +รœretilen kodda hรขlรข bazฤฑ **tekrarlanan bilgiler** var. + +Bu method'un **items** ile iliลŸkili olduฤŸunu zaten biliyoruz; รงรผnkรผ bu kelime `ItemsService` iรงinde var (tag'den geliyor). Ama method adฤฑnda da tag adฤฑ รถnek olarak duruyor. ๐Ÿ˜• + +OpenAPI genelinde muhtemelen bunu korumak isteriz; รงรผnkรผ operation ID'lerin **benzersiz** olmasฤฑnฤฑ saฤŸlar. + +Ancak รผretilen client iรงin, client'larฤฑ รผretmeden hemen รถnce OpenAPI operation ID'lerini **deฤŸiลŸtirip**, method isimlerini daha hoลŸ ve **temiz** hale getirebiliriz. + +OpenAPI JSON'u `openapi.json` diye bir dosyaya indirip, ลŸu tarz bir script ile **รถndeki tag'i kaldฤฑrabiliriz**: + +{* ../../docs_src/generate_clients/tutorial004_py39.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +Bununla operation ID'ler `items-get_items` gibi deฤŸerlerden sadece `get_items` olacak ลŸekilde yeniden adlandฤฑrฤฑlฤฑr; bรถylece client รผreteci daha basit method isimleri รผretebilir. + +### ร–n ฤฐลŸlenmiลŸ OpenAPI ile TypeScript Client รœretme { #generate-a-typescript-client-with-the-preprocessed-openapi } + +Sonuรง artฤฑk bir `openapi.json` dosyasฤฑnda olduฤŸuna gรถre, input konumunu gรผncellemeniz gerekir: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +Yeni client'ฤฑ รผrettikten sonra, tรผm **otomatik tamamlama**, **satฤฑr iรงi hatalar**, vb. ile birlikte **temiz method isimleri** elde edersiniz: + + + +## Faydalar { #benefits } + +Otomatik รผretilen client'larฤฑ kullanฤฑnca ลŸu alanlarda **otomatik tamamlama** elde edersiniz: + +* Method'lar. +* Body'deki request payload'larฤฑ, query parametreleri, vb. +* Response payload'larฤฑ. + +Ayrฤฑca her ลŸey iรงin **satฤฑr iรงi hatalar** (inline errors) da olur. + +Backend kodunu her gรผncellediฤŸinizde ve frontend'i **yeniden รผrettiฤŸinizde**, yeni *path operation*'lar method olarak eklenir, eskileri kaldฤฑrฤฑlฤฑr ve diฤŸer deฤŸiลŸiklikler de รผretilen koda yansฤฑr. ๐Ÿค“ + +Bu, bir ลŸey deฤŸiลŸtiฤŸinde client code'a otomatik olarak **yansฤฑyacaฤŸฤฑ** anlamฤฑna gelir. Ayrฤฑca client'ฤฑ **build** ettiฤŸinizde, kullanฤฑlan verilerde bir **uyuลŸmazlฤฑk** (mismatch) varsa hata alฤฑrsฤฑnฤฑz. + +Bรถylece รผretimde son kullanฤฑcฤฑlara hata yansฤฑmasฤฑnฤฑ beklemek ve sonra sorunun nerede olduฤŸunu debug etmeye รงalฤฑลŸmak yerine, geliลŸtirme sรผrecinin รงok erken aลŸamalarฤฑnda **birรงok hatayฤฑ tespit edersiniz**. โœจ diff --git a/docs/tr/docs/advanced/middleware.md b/docs/tr/docs/advanced/middleware.md new file mode 100644 index 0000000000..a22644a090 --- /dev/null +++ b/docs/tr/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# ฤฐleri Seviye Middleware { #advanced-middleware } + +Ana tutorial'da uygulamanฤฑza [ร–zel Middleware](../tutorial/middleware.md){.internal-link target=_blank} eklemeyi gรถrdรผnรผz. + +Ardฤฑndan [`CORSMiddleware` ile CORS'u yรถnetmeyi](../tutorial/cors.md){.internal-link target=_blank} de okudunuz. + +Bu bรถlรผmde diฤŸer middleware'leri nasฤฑl kullanacaฤŸฤฑmฤฑza bakacaฤŸฤฑz. + +## ASGI middleware'leri ekleme { #adding-asgi-middlewares } + +**FastAPI**, Starlette รผzerine kurulu olduฤŸu ve ASGI spesifikasyonunu uyguladฤฑฤŸฤฑ iรงin, herhangi bir ASGI middleware'ini kullanabilirsiniz. + +Bir middleware'in รงalฤฑลŸmasฤฑ iรงin รถzellikle FastAPI ya da Starlette iรงin yazฤฑlmฤฑลŸ olmasฤฑ gerekmez; ASGI spec'ine uyduฤŸu sรผrece yeterlidir. + +Genel olarak ASGI middleware'leri, ilk argรผman olarak bir ASGI app almayฤฑ bekleyen class'lar olur. + +Dolayฤฑsฤฑyla รผรงรผncรผ taraf ASGI middleware'lerinin dokรผmantasyonunda muhtemelen ลŸรถyle bir ลŸey yapmanฤฑzฤฑ sรถylerler: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +Ancak FastAPI (aslฤฑnda Starlette) bunu yapmanฤฑn daha basit bir yolunu sunar; bรถylece dahili middleware'ler server hatalarฤฑnฤฑ doฤŸru ลŸekilde ele alฤฑr ve รถzel exception handler'lar dรผzgรผn รงalฤฑลŸฤฑr. + +Bunun iรงin `app.add_middleware()` kullanฤฑrsฤฑnฤฑz (CORS รถrneฤŸindeki gibi). + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` ilk argรผman olarak bir middleware class'ฤฑ alฤฑr ve middleware'e aktarฤฑlacak ek argรผmanlarฤฑ da kabul eder. + +## Entegre middleware'ler { #integrated-middlewares } + +**FastAPI**, yaygฤฑn kullanฤฑm senaryolarฤฑ iรงin birkaรง middleware iรงerir; ลŸimdi bunlarฤฑ nasฤฑl kullanacaฤŸฤฑmฤฑza bakacaฤŸฤฑz. + +/// note | Teknik Detaylar + +Bir sonraki รถrneklerde `from starlette.middleware.something import SomethingMiddleware` kullanmanฤฑz da mรผmkรผndรผr. + +**FastAPI**, size (geliลŸtirici olarak) kolaylฤฑk olsun diye `fastapi.middleware` iรงinde bazฤฑ middleware'leri saฤŸlar. Ancak mevcut middleware'lerin รงoฤŸu doฤŸrudan Starlette'ten gelir. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +Gelen tรผm request'lerin `https` veya `wss` olmasฤฑnฤฑ zorunlu kฤฑlar. + +`http` veya `ws` olarak gelen herhangi bir request, bunun yerine gรผvenli ลŸemaya redirect edilir. + +{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +HTTP Host Header saldฤฑrฤฑlarฤฑna karลŸฤฑ korunmak iรงin, gelen tรผm request'lerde `Host` header'ฤฑnฤฑn doฤŸru ayarlanmฤฑลŸ olmasฤฑnฤฑ zorunlu kฤฑlar. + +{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} + +AลŸaฤŸฤฑdaki argรผmanlar desteklenir: + +* `allowed_hosts` - Hostname olarak izin verilmesi gereken domain adlarฤฑnฤฑn listesi. `*.example.com` gibi wildcard domain'ler subdomain eลŸleลŸtirmesi iรงin desteklenir. Herhangi bir hostname'e izin vermek iรงin `allowed_hosts=["*"]` kullanฤฑn veya middleware'i hiรง eklemeyin. +* `www_redirect` - True olarak ayarlanฤฑrsa, izin verilen host'larฤฑn www olmayan sรผrรผmlerine gelen request'ler www sรผrรผmlerine redirect edilir. Varsayฤฑlanฤฑ `True`'dur. + +Gelen bir request doฤŸru ลŸekilde doฤŸrulanmazsa `400` response gรถnderilir. + +## `GZipMiddleware` { #gzipmiddleware } + +`Accept-Encoding` header'ฤฑnda `"gzip"` iรงeren herhangi bir request iรงin GZip response'larฤฑnฤฑ yรถnetir. + +Middleware hem standart hem de streaming response'larฤฑ ele alฤฑr. + +{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} + +AลŸaฤŸฤฑdaki argรผmanlar desteklenir: + +* `minimum_size` - Bayt cinsinden bu minimum boyuttan kรผรงรผk response'lara GZip uygulama. Varsayฤฑlanฤฑ `500`'dรผr. +* `compresslevel` - GZip sฤฑkฤฑลŸtฤฑrmasฤฑ sฤฑrasฤฑnda kullanฤฑlฤฑr. 1 ile 9 arasฤฑnda bir tamsayฤฑdฤฑr. Varsayฤฑlanฤฑ `9`'dur. Daha dรผลŸรผk deฤŸer daha hฤฑzlฤฑ sฤฑkฤฑลŸtฤฑrma ama daha bรผyรผk dosya boyutlarฤฑ รผretir; daha yรผksek deฤŸer daha yavaลŸ sฤฑkฤฑลŸtฤฑrma ama daha kรผรงรผk dosya boyutlarฤฑ รผretir. + +## DiฤŸer middleware'ler { #other-middlewares } + +BaลŸka birรงok ASGI middleware'i vardฤฑr. + +ร–rneฤŸin: + +* Uvicorn'un `ProxyHeadersMiddleware`'i +* MessagePack + +DiฤŸer mevcut middleware'leri gรถrmek iรงin Starlette'in Middleware dokรผmanlarฤฑna ve ASGI Awesome List listesine bakฤฑn. diff --git a/docs/tr/docs/advanced/openapi-callbacks.md b/docs/tr/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..61135b7e01 --- /dev/null +++ b/docs/tr/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI Callback'leri { #openapi-callbacks } + +BaลŸka biri tarafฤฑndan (muhtemelen API'nizi *kullanacak* olan aynฤฑ geliลŸtirici tarafฤฑndan) oluลŸturulmuลŸ bir *external API*'ye request tetikleyebilen bir *path operation* ile bir API oluลŸturabilirsiniz. + +API uygulamanฤฑzฤฑn *external API*'yi รงaฤŸฤฑrdฤฑฤŸฤฑ sฤฑrada gerรงekleลŸen sรผrece "callback" denir. ร‡รผnkรผ dฤฑลŸ geliลŸtiricinin yazdฤฑฤŸฤฑ yazฤฑlฤฑm API'nize bir request gรถnderir ve ardฤฑndan API'niz *geri รงaฤŸrฤฑ* yaparak (*call back*), bir *external API*'ye request gรถnderir (muhtemelen aynฤฑ geliลŸtiricinin oluลŸturduฤŸu). + +Bu durumda, o external API'nin nasฤฑl gรถrรผnmesi *gerektiฤŸini* dokรผmante etmek isteyebilirsiniz. Hangi *path operation*'a sahip olmalฤฑ, hangi body'yi beklemeli, hangi response'u dรถndรผrmeli, vb. + +## Callback'leri olan bir uygulama { #an-app-with-callbacks } + +Bunlarฤฑn hepsine bir รถrnekle bakalฤฑm. + +Fatura oluลŸturmayฤฑ saฤŸlayan bir uygulama geliลŸtirdiฤŸinizi dรผลŸรผnรผn. + +Bu faturalarฤฑn `id`, `title` (opsiyonel), `customer` ve `total` alanlarฤฑ olacak. + +API'nizin kullanฤฑcฤฑsฤฑ (external bir geliลŸtirici) API'nizde bir POST request ile fatura oluลŸturacak. + +Sonra API'niz (varsayalฤฑm ki): + +* Faturayฤฑ external geliลŸtiricinin bir mรผลŸterisine gรถnderir. +* Parayฤฑ tahsil eder. +* API kullanฤฑcฤฑsฤฑna (external geliลŸtiriciye) tekrar bir bildirim gรถnderir. + * Bu, external geliลŸtiricinin saฤŸladฤฑฤŸฤฑ bir *external API*'ye (*sizin API'nizden*) bir POST request gรถnderilerek yapฤฑlฤฑr (iลŸte bu "callback"tir). + +## Normal **FastAPI** uygulamasฤฑ { #the-normal-fastapi-app } + +ร–nce callback eklemeden รถnce normal API uygulamasฤฑnฤฑn nasฤฑl gรถrรผneceฤŸine bakalฤฑm. + +Bir `Invoice` body alacak bir *path operation*'ฤฑ ve callback iรงin URL'yi taลŸฤฑyacak `callback_url` adlฤฑ bir query parametresi olacak. + +Bu kฤฑsฤฑm oldukรงa standart; kodun รงoฤŸu muhtemelen size zaten tanฤฑdฤฑk gelecektir: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | ฤฐpucu + +`callback_url` query parametresi, Pydantic'in Url tipini kullanฤฑr. + +/// + +Tek yeni ลŸey, *path operation decorator*'ฤฑna argรผman olarak verilen `callbacks=invoices_callback_router.routes`. Bunun ne olduฤŸuna ลŸimdi bakacaฤŸฤฑz. + +## Callback'i dokรผmante etmek { #documenting-the-callback } + +Callback'in gerรงek kodu, bรผyรผk รถlรงรผde sizin API uygulamanฤฑza baฤŸlฤฑdฤฑr. + +Ve bir uygulamadan diฤŸerine oldukรงa deฤŸiลŸebilir. + +Sadece bir-iki satฤฑr kod bile olabilir, รถrneฤŸin: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +Ancak callback'in belki de en รถnemli kฤฑsmฤฑ, API'nizin kullanฤฑcฤฑsฤฑnฤฑn (external geliลŸtiricinin) *external API*'yi doฤŸru ลŸekilde uyguladฤฑฤŸฤฑndan emin olmaktฤฑr; รงรผnkรผ *sizin API'niz* callback'in request body'sinde belirli veriler gรถnderecektir, vb. + +Dolayฤฑsฤฑyla sฤฑradaki adฤฑm olarak, *sizin API'nizden* callback almak iรงin o *external API*'nin nasฤฑl gรถrรผnmesi gerektiฤŸini dokรผmante eden kodu ekleyeceฤŸiz. + +Bu dokรผmantasyon, API'nizde `/docs` altฤฑndaki Swagger UI'da gรถrรผnecek ve external geliลŸtiricilere *external API*'yi nasฤฑl inลŸa edeceklerini gรถsterecek. + +Bu รถrnek callback'in kendisini implemente etmiyor (o zaten tek satฤฑr kod olabilir), sadece dokรผmantasyon kฤฑsmฤฑnฤฑ ekliyor. + +/// tip | ฤฐpucu + +Gerรงek callback, sadece bir HTTP request'tir. + +Callback'i kendiniz implemente ederken HTTPX veya Requests gibi bir ลŸey kullanabilirsiniz. + +/// + +## Callback dokรผmantasyon kodunu yazฤฑn { #write-the-callback-documentation-code } + +Bu kod uygulamanฤฑzda รงalฤฑลŸtฤฑrฤฑlmayacak; sadece o *external API*'nin nasฤฑl gรถrรผnmesi gerektiฤŸini *dokรผmante etmek* iรงin gerekiyor. + +Ancak **FastAPI** ile bir API iรงin otomatik dokรผmantasyonu kolayca nasฤฑl รผreteceฤŸinizi zaten biliyorsunuz. + +O halde aynฤฑ bilgiyi kullanarak, *external API*'nin nasฤฑl gรถrรผnmesi gerektiฤŸini dokรผmante edeceฤŸiz... external API'nin implemente etmesi gereken *path operation*'larฤฑ oluลŸturarak (API'nizin รงaฤŸฤฑracaฤŸฤฑ olanlar). + +/// tip | ฤฐpucu + +Bir callback'i dokรผmante eden kodu yazarken, kendinizi *external geliลŸtirici* olarak hayal etmek faydalฤฑ olabilir. Ve ลŸu anda *sizin API'nizi* deฤŸil, *external API*'yi implemente ettiฤŸinizi dรผลŸรผnรผn. + +Bu bakฤฑลŸ aรงฤฑsฤฑnฤฑ (external geliลŸtiricinin bakฤฑลŸ aรงฤฑsฤฑnฤฑ) geรงici olarak benimsemek; parametreleri nereye koyacaฤŸฤฑnฤฑzฤฑ, body iรงin Pydantic modelini, response iรงin modelini vb. external API tarafฤฑnda nasฤฑl tasarlayacaฤŸฤฑnฤฑzฤฑ daha net hale getirebilir. + +/// + +### Bir callback `APIRouter` oluลŸturun { #create-a-callback-apirouter } + +ร–nce bir veya daha fazla callback iรงerecek yeni bir `APIRouter` oluลŸturun. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Callback *path operation*'ฤฑnฤฑ oluลŸturun { #create-the-callback-path-operation } + +Callback *path operation*'ฤฑnฤฑ oluลŸturmak iรงin, yukarฤฑda oluลŸturduฤŸunuz aynฤฑ `APIRouter`'ฤฑ kullanฤฑn. + +Normal bir FastAPI *path operation*'ฤฑ gibi gรถrรผnmelidir: + +* Muhtemelen almasฤฑ gereken body'nin bir deklarasyonu olmalฤฑ, รถrn. `body: InvoiceEvent`. +* Ayrฤฑca dรถndรผrmesi gereken response'un deklarasyonu da olabilir, รถrn. `response_model=InvoiceEventReceived`. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +Normal bir *path operation*'dan 2 temel farkฤฑ vardฤฑr: + +* Gerรงek bir koda ihtiyaรง duymaz; รงรผnkรผ uygulamanฤฑz bu kodu asla รงaฤŸฤฑrmayacak. Bu yalnฤฑzca *external API*'yi dokรผmante etmek iรงin kullanฤฑlฤฑr. Yani fonksiyon sadece `pass` iรงerebilir. +* *path*, bir OpenAPI 3 expression (aลŸaฤŸฤฑda daha fazlasฤฑ) iรงerebilir; bรถylece parametreler ve *sizin API'nize* gรถnderilen orijinal request'in bazฤฑ parรงalarฤฑyla deฤŸiลŸkenler kullanฤฑlabilir. + +### Callback path ifadesi { #the-callback-path-expression } + +Callback *path*'i, *sizin API'nize* gรถnderilen orijinal request'in bazฤฑ parรงalarฤฑnฤฑ iรงerebilen bir OpenAPI 3 expression barฤฑndฤฑrabilir. + +Bu รถrnekte, bu bir `str`: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +Yani API'nizin kullanฤฑcฤฑsฤฑ (external geliลŸtirici) *sizin API'nize* ลŸu adrese bir request gรถnderirse: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +ve JSON body ลŸu ลŸekilde olursa: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +o zaman *sizin API'niz* faturayฤฑ iลŸleyecek ve daha sonra bir noktada `callback_url`'ye (yani *external API*'ye) bir callback request gรถnderecek: + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +ve JSON body yaklaลŸฤฑk ลŸรถyle bir ลŸey iรงerecek: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +ve o *external API*'den ลŸu gibi bir JSON body iรงeren response bekleyecek: + +```JSON +{ + "ok": true +} +``` + +/// tip | ฤฐpucu + +Callback URL'sinin, `callback_url` iรงindeki query parametresi olarak alฤฑnan URL'yi (`https://www.external.org/events`) ve ayrฤฑca JSON body'nin iรงindeki fatura `id`'sini (`2expen51ve`) birlikte kullandฤฑฤŸฤฑna dikkat edin. + +/// + +### Callback router'ฤฑnฤฑ ekleyin { #add-the-callback-router } + +Bu noktada, yukarฤฑda oluลŸturduฤŸunuz callback router'ฤฑnda gerekli callback *path operation*'larฤฑ (external geliลŸtiricinin *external API*'de implemente etmesi gerekenler) hazฤฑr. + +ลžimdi *sizin API'nizin path operation decorator*'ฤฑnda `callbacks` parametresini kullanarak, callback router'ฤฑnฤฑn `.routes` attribute'unu (bu aslฤฑnda route/*path operation*'lardan oluลŸan bir `list`) geรงin: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | ฤฐpucu + +`callback=` iรงine router'ฤฑn kendisini (`invoices_callback_router`) deฤŸil, `invoices_callback_router.routes` ลŸeklinde `.routes` attribute'unu verdiฤŸinize dikkat edin. + +/// + +### Dokรผmanlarฤฑ kontrol edin { #check-the-docs } + +Artฤฑk uygulamanฤฑzฤฑ baลŸlatฤฑp http://127.0.0.1:8000/docs adresine gidebilirsiniz. + +*Path operation*'ฤฑnฤฑz iรงin, *external API*'nin nasฤฑl gรถrรผnmesi gerektiฤŸini gรถsteren bir "Callbacks" bรถlรผmรผnรผ iรงeren dokรผmanlarฤฑ gรถreceksiniz: + + diff --git a/docs/tr/docs/advanced/openapi-webhooks.md b/docs/tr/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..dd9e9bbe73 --- /dev/null +++ b/docs/tr/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhook'lar { #openapi-webhooks } + +Bazฤฑ durumlarda, API'nizi kullanan **kullanฤฑcฤฑlara** uygulamanฤฑzฤฑn *onlarฤฑn* uygulamasฤฑnฤฑ (request gรถndererek) bazฤฑ verilerle รงaฤŸฤฑrabileceฤŸini; genellikle bir tรผr **event** hakkฤฑnda **bildirim** yapmak iรงin kullanacaฤŸฤฑnฤฑ sรถylemek istersiniz. + +Bu da ลŸunu ifade eder: Kullanฤฑcฤฑlarฤฑnฤฑzฤฑn API'nize request gรถndermesi ลŸeklindeki normal akฤฑลŸ yerine, request'i **sizin API'niz** (veya uygulamanฤฑz) **onlarฤฑn sistemine** (onlarฤฑn API'sine, onlarฤฑn uygulamasฤฑna) **gรถnderebilir**. + +Buna genellikle **webhook** denir. + +## Webhook adฤฑmlarฤฑ { #webhooks-steps } + +Sรผreรง genellikle ลŸรถyledir: Kodunuzda gรถndereceฤŸiniz mesajฤฑn ne olduฤŸunu, yani request'in **body**'sini **siz tanฤฑmlarsฤฑnฤฑz**. + +Ayrฤฑca uygulamanฤฑzฤฑn bu request'leri veya event'leri hangi **anlarda** gรถndereceฤŸini de bir ลŸekilde tanฤฑmlarsฤฑnฤฑz. + +Ve **kullanฤฑcฤฑlarฤฑnฤฑz** da bir ลŸekilde (รถrneฤŸin bir web dashboard รผzerinden) uygulamanฤฑzฤฑn bu request'leri gรถndermesi gereken **URL**'yi tanฤฑmlar. + +Webhook'lar iรงin URL'lerin nasฤฑl kaydedileceฤŸine dair tรผm **mantฤฑk** ve bu request'leri gerรงekten gรถnderen kod tamamen size baฤŸlฤฑdฤฑr. Bunu **kendi kodunuzda** istediฤŸiniz gibi yazarsฤฑnฤฑz. + +## **FastAPI** ve OpenAPI ile webhook'larฤฑ dokรผmante etmek { #documenting-webhooks-with-fastapi-and-openapi } + +**FastAPI** ile OpenAPI kullanarak bu webhook'larฤฑn adlarฤฑnฤฑ, uygulamanฤฑzฤฑn gรถnderebileceฤŸi HTTP operation tรผrlerini (รถrn. `POST`, `PUT`, vb.) ve uygulamanฤฑzฤฑn gรถndereceฤŸi request **body**'lerini tanฤฑmlayabilirsiniz. + +Bu, kullanฤฑcฤฑlarฤฑnฤฑzฤฑn **webhook** request'lerinizi alacak ลŸekilde **API'lerini implement etmesini** รงok daha kolaylaลŸtฤฑrabilir; hatta kendi API kodlarฤฑnฤฑn bir kฤฑsmฤฑnฤฑ otomatik รผretebilirler. + +/// info | Bilgi + +Webhook'lar OpenAPI 3.1.0 ve รผzeri sรผrรผmlerde mevcuttur; FastAPI `0.99.0` ve รผzeri tarafฤฑndan desteklenir. + +/// + +## Webhook'larฤฑ olan bir uygulama { #an-app-with-webhooks } + +Bir **FastAPI** uygulamasฤฑ oluลŸturduฤŸunuzda, *webhook*'larฤฑ tanฤฑmlamak iรงin kullanabileceฤŸiniz bir `webhooks` attribute'u vardฤฑr; *path operation* tanฤฑmlar gibi, รถrneฤŸin `@app.webhooks.post()` ile. + +{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} + +TanฤฑmladฤฑฤŸฤฑnฤฑz webhook'lar **OpenAPI** ลŸemasฤฑnda ve otomatik **docs UI**'da yer alฤฑr. + +/// info | Bilgi + +`app.webhooks` nesnesi aslฤฑnda sadece bir `APIRouter`'dฤฑr; uygulamanฤฑzฤฑ birden fazla dosya ile yapฤฑlandฤฑrฤฑrken kullanacaฤŸฤฑnฤฑz tรผrรผn aynฤฑsฤฑdฤฑr. + +/// + +Dikkat edin: Webhook'larda aslฤฑnda bir *path* (รถr. `/items/`) deklare etmiyorsunuz; oraya verdiฤŸiniz metin sadece webhook'un bir **identifier**'ฤฑdฤฑr (event'in adฤฑ). ร–rneฤŸin `@app.webhooks.post("new-subscription")` iรงinde webhook adฤฑ `new-subscription`'dฤฑr. + +Bunun nedeni, webhook request'ini almak istedikleri gerรงek **URL path**'i **kullanฤฑcฤฑlarฤฑnฤฑzฤฑn** baลŸka bir ลŸekilde (รถrn. bir web dashboard รผzerinden) tanฤฑmlamasฤฑnฤฑn beklenmesidir. + +### Dokรผmanlarฤฑ kontrol edin { #check-the-docs } + +ลžimdi uygulamanฤฑzฤฑ baลŸlatฤฑp http://127.0.0.1:8000/docs adresine gidin. + +Dokรผmanlarฤฑnฤฑzda normal *path operation*'larฤฑ ve artฤฑk bazฤฑ **webhook**'larฤฑ da gรถreceksiniz: + + diff --git a/docs/tr/docs/advanced/path-operation-advanced-configuration.md b/docs/tr/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000..e326842d67 --- /dev/null +++ b/docs/tr/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,172 @@ +# Path Operation ฤฐleri Dรผzey Yapฤฑlandฤฑrma { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | Uyarฤฑ + +OpenAPI konusunda "uzman" deฤŸilseniz, muhtemelen buna ihtiyacฤฑnฤฑz yok. + +/// + +*path operation*โ€™ฤฑnฤฑzda kullanฤฑlacak OpenAPI `operationId` deฤŸerini `operation_id` parametresiyle ayarlayabilirsiniz. + +Bunun her operation iรงin benzersiz olduฤŸundan emin olmanฤฑz gerekir. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} + +### operationId olarak *path operation function* adฤฑnฤฑ kullanma { #using-the-path-operation-function-name-as-the-operationid } + +APIโ€™lerinizin function adlarฤฑnฤฑ `operationId` olarak kullanmak istiyorsanฤฑz, hepsini dolaลŸฤฑp her *path operation*โ€™ฤฑn `operation_id` deฤŸerini `APIRoute.name` ile override edebilirsiniz. + +Bunu, tรผm *path operation*โ€™larฤฑ ekledikten sonra yapmalฤฑsฤฑnฤฑz. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} + +/// tip | ฤฐpucu + +`app.openapi()` fonksiyonunu manuel olarak รงaฤŸฤฑrฤฑyorsanฤฑz, bunu yapmadan รถnce `operationId`โ€™leri gรผncellemelisiniz. + +/// + +/// warning | Uyarฤฑ + +Bunu yaparsanฤฑz, her bir *path operation function*โ€™ฤฑn adฤฑnฤฑn benzersiz olduฤŸundan emin olmanฤฑz gerekir. + +Farklฤฑ modรผllerde (Python dosyalarฤฑnda) olsalar bile. + +/// + +## OpenAPIโ€™den Hariรง Tutma { #exclude-from-openapi } + +Bir *path operation*โ€™ฤฑ รผretilen OpenAPI ลŸemasฤฑndan (dolayฤฑsฤฑyla otomatik dokรผmantasyon sistemlerinden) hariรง tutmak iรงin `include_in_schema` parametresini kullanฤฑn ve `False` yapฤฑn: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} + +## Docstringโ€™den ฤฐleri Dรผzey Aรงฤฑklama { #advanced-description-from-docstring } + +OpenAPI iรงin, bir *path operation function*โ€™ฤฑn docstringโ€™inden kullanฤฑlacak satฤฑrlarฤฑ sฤฑnฤฑrlandฤฑrabilirsiniz. + +Bir `\f` (escape edilmiลŸ "form feed" karakteri) eklerseniz, **FastAPI** OpenAPI iรงin kullanฤฑlan รงฤฑktฤฑyฤฑ bu noktada **keser**. + +Dokรผmantasyonda gรถrรผnmez, ancak diฤŸer araรงlar (Sphinx gibi) geri kalan kฤฑsmฤฑ kullanabilir. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## Ek Responses { #additional-responses } + +Muhtemelen bir *path operation* iรงin `response_model` ve `status_code` tanฤฑmlamayฤฑ gรถrmรผลŸsรผnรผzdรผr. + +Bu, bir *path operation*โ€™ฤฑn ana responseโ€™u ile ilgili metadataโ€™yฤฑ tanฤฑmlar. + +Ek responseโ€™larฤฑ; modelleri, status codeโ€™larฤฑ vb. ile birlikte ayrฤฑca da tanฤฑmlayabilirsiniz. + +Dokรผmantasyonda bununla ilgili ayrฤฑ bir bรถlรผm var; [OpenAPIโ€™de Ek Responses](additional-responses.md){.internal-link target=_blank} sayfasฤฑndan okuyabilirsiniz. + +## OpenAPI Extra { #openapi-extra } + +Uygulamanฤฑzda bir *path operation* tanฤฑmladฤฑฤŸฤฑnฤฑzda, **FastAPI** OpenAPI ลŸemasฤฑna dahil edilmek รผzere o *path operation* ile ilgili metadataโ€™yฤฑ otomatik olarak รผretir. + +/// note | Teknik Detaylar + +OpenAPI spesifikasyonunda buna Operation Object denir. + +/// + +Bu, *path operation* hakkฤฑnda tรผm bilgileri iรงerir ve otomatik dokรผmantasyonu รผretmek iรงin kullanฤฑlฤฑr. + +`tags`, `parameters`, `requestBody`, `responses` vb. alanlarฤฑ iรงerir. + +Bu *path operation*โ€™a รถzel OpenAPI ลŸemasฤฑ normalde **FastAPI** tarafฤฑndan otomatik รผretilir; ancak siz bunu geniลŸletebilirsiniz. + +/// tip | ฤฐpucu + +Bu, dรผลŸรผk seviyeli bir geniลŸletme noktasฤฑdฤฑr. + +Yalnฤฑzca ek responseโ€™lar tanฤฑmlamanฤฑz gerekiyorsa, bunu yapmanฤฑn daha pratik yolu [OpenAPIโ€™de Ek Responses](additional-responses.md){.internal-link target=_blank} kullanmaktฤฑr. + +/// + +Bir *path operation* iรงin OpenAPI ลŸemasฤฑnฤฑ `openapi_extra` parametresiyle geniลŸletebilirsiniz. + +### OpenAPI Extensions { #openapi-extensions } + +ร–rneฤŸin bu `openapi_extra`, [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) tanฤฑmlamak iรงin faydalฤฑ olabilir: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} + +Otomatik API dokรผmanlarฤฑnฤฑ aรงtฤฑฤŸฤฑnฤฑzda, extensionโ€™ฤฑnฤฑz ilgili *path operation*โ€™ฤฑn en altฤฑnda gรถrรผnรผr. + + + +Ayrฤฑca ortaya รงฤฑkan OpenAPIโ€™yi (APIโ€™nizde `/openapi.json`) gรถrรผntรผlerseniz, extensionโ€™ฤฑnฤฑzฤฑ ilgili *path operation*โ€™ฤฑn bir parรงasฤฑ olarak orada da gรถrรผrsรผnรผz: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ร–zel OpenAPI *path operation* ลŸemasฤฑ { #custom-openapi-path-operation-schema } + +`openapi_extra` iรงindeki dictionary, *path operation* iรงin otomatik รผretilen OpenAPI ลŸemasฤฑyla derinlemesine (deep) birleลŸtirilir. + +Bรถylece otomatik รผretilen ลŸemaya ek veri ekleyebilirsiniz. + +ร–rneฤŸin, Pydantic ile FastAPIโ€™nin otomatik รถzelliklerini kullanmadan requestโ€™i kendi kodunuzla okuyup doฤŸrulamaya karar verebilirsiniz; ancak yine de OpenAPI ลŸemasฤฑnda requestโ€™i tanฤฑmlamak isteyebilirsiniz. + +Bunu `openapi_extra` ile yapabilirsiniz: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} + +Bu รถrnekte herhangi bir Pydantic model tanฤฑmlamadฤฑk. Hatta request body JSON olarak parsed bile edilmiyor; doฤŸrudan `bytes` olarak okunuyor ve `magic_data_reader()` fonksiyonu bunu bir ลŸekilde parse etmekten sorumlu oluyor. + +Buna raฤŸmen, request body iรงin beklenen ลŸemayฤฑ tanฤฑmlayabiliriz. + +### ร–zel OpenAPI content type { #custom-openapi-content-type } + +Aynฤฑ yรถntemi kullanarak, Pydantic model ile JSON Schemaโ€™yฤฑ tanฤฑmlayฤฑp bunu *path operation* iรงin รถzel OpenAPI ลŸemasฤฑ bรถlรผmรผne dahil edebilirsiniz. + +Ve bunu, request iรงindeki veri tipi JSON olmasa bile yapabilirsiniz. + +ร–rneฤŸin bu uygulamada, FastAPIโ€™nin Pydantic modellerinden JSON Schema รงฤฑkarmaya yรถnelik entegre iลŸlevselliฤŸini ve JSON iรงin otomatik doฤŸrulamayฤฑ kullanmฤฑyoruz. Hatta request content typeโ€™ฤฑnฤฑ JSON deฤŸil, YAML olarak tanฤฑmlฤฑyoruz: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} + +Buna raฤŸmen, varsayฤฑlan entegre iลŸlevselliฤŸi kullanmasak da, YAML olarak almak istediฤŸimiz veri iรงin JSON Schemaโ€™yฤฑ manuel รผretmek รผzere bir Pydantic model kullanmaya devam ediyoruz. + +Ardฤฑndan requestโ€™i doฤŸrudan kullanฤฑp bodyโ€™yi `bytes` olarak รงฤฑkarฤฑyoruz. Bu da FastAPIโ€™nin request payloadโ€™ฤฑnฤฑ JSON olarak parse etmeye รงalฤฑลŸmayacaฤŸฤฑ anlamฤฑna gelir. + +Sonrasฤฑnda kodumuzda bu YAML iรงeriฤŸini doฤŸrudan parse ediyor, ardฤฑndan YAML iรงeriฤŸini doฤŸrulamak iรงin yine aynฤฑ Pydantic modeli kullanฤฑyoruz: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} + +/// tip | ฤฐpucu + +Burada aynฤฑ Pydantic modeli tekrar kullanฤฑyoruz. + +Aynฤฑ ลŸekilde, baลŸka bir yรถntemle de doฤŸrulama yapabilirdik. + +/// diff --git a/docs/tr/docs/advanced/response-change-status-code.md b/docs/tr/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000..239c0dddd4 --- /dev/null +++ b/docs/tr/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - Status Code DeฤŸiลŸtirme { #response-change-status-code } + +Muhtemelen daha รถnce varsayฤฑlan bir [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank} ayarlayabileceฤŸinizi okumuลŸsunuzdur. + +Ancak bazฤฑ durumlarda, varsayฤฑlandan farklฤฑ bir status code dรถndรผrmeniz gerekir. + +## Kullanฤฑm senaryosu { #use-case } + +ร–rneฤŸin, varsayฤฑlan olarak "OK" `200` HTTP status code'u dรถndรผrmek istediฤŸinizi dรผลŸรผnรผn. + +Ama veri mevcut deฤŸilse onu oluลŸturmak ve "CREATED" `201` HTTP status code'u dรถndรผrmek istiyorsunuz. + +Aynฤฑ zamanda, dรถndรผrdรผฤŸรผnรผz veriyi bir `response_model` ile filtreleyip dรถnรผลŸtรผrebilmeyi de sรผrdรผrmek istiyorsunuz. + +Bu tรผr durumlarda bir `Response` parametresi kullanabilirsiniz. + +## Bir `Response` parametresi kullanฤฑn { #use-a-response-parameter } + +*Path operation function* iรงinde `Response` tipinde bir parametre tanฤฑmlayabilirsiniz (cookie ve header'lar iรงin yapabildiฤŸiniz gibi). + +Ardฤฑndan bu *geรงici (temporal)* `Response` nesnesi รผzerinde `status_code` deฤŸerini ayarlayabilirsiniz. + +{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} + +Sonrasฤฑnda, normalde yaptฤฑฤŸฤฑnฤฑz gibi ihtiyacฤฑnฤฑz olan herhangi bir nesneyi dรถndรผrebilirsiniz (`dict`, bir veritabanฤฑ modeli, vb.). + +Ve eฤŸer bir `response_model` tanฤฑmladฤฑysanฤฑz, dรถndรผrdรผฤŸรผnรผz nesneyi filtrelemek ve dรถnรผลŸtรผrmek iรงin yine kullanฤฑlacaktฤฑr. + +**FastAPI**, status code'u (ayrฤฑca cookie ve header'larฤฑ) bu *geรงici (temporal)* response'tan alฤฑr ve `response_model` ile filtrelenmiลŸ, sizin dรถndรผrdรผฤŸรผnรผz deฤŸeri iรงeren nihai response'a yerleลŸtirir. + +Ayrฤฑca `Response` parametresini dependency'lerde de tanฤฑmlayฤฑp status code'u orada ayarlayabilirsiniz. Ancak unutmayฤฑn, en son ayarlanan deฤŸer geรงerli olur. diff --git a/docs/tr/docs/advanced/response-cookies.md b/docs/tr/docs/advanced/response-cookies.md new file mode 100644 index 0000000000..d00bfc4cd0 --- /dev/null +++ b/docs/tr/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# Response Cookie'leri { #response-cookies } + +## Bir `Response` parametresi kullanฤฑn { #use-a-response-parameter } + +*Path operation function* iรงinde `Response` tipinde bir parametre tanฤฑmlayabilirsiniz. + +Ardฤฑndan bu *geรงici* response nesnesi รผzerinde cookie'leri set edebilirsiniz. + +{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} + +Sonrasฤฑnda normalde yaptฤฑฤŸฤฑnฤฑz gibi ihtiyaรง duyduฤŸunuz herhangi bir nesneyi dรถndรผrebilirsiniz (bir `dict`, bir veritabanฤฑ modeli vb.). + +Ayrฤฑca bir `response_model` tanฤฑmladฤฑysanฤฑz, dรถndรผrdรผฤŸรผnรผz nesneyi filtrelemek ve dรถnรผลŸtรผrmek iรงin yine kullanฤฑlacaktฤฑr. + +**FastAPI**, bu *geรงici* response'u cookie'leri (ayrฤฑca header'larฤฑ ve status code'u) รงฤฑkarmak iรงin kullanฤฑr ve bunlarฤฑ, dรถndรผrdรผฤŸรผnรผz deฤŸeri iรงeren nihai response'a ekler. DรถndรผrdรผฤŸรผnรผz deฤŸer, varsa `response_model` ile filtrelenmiลŸ olur. + +`Response` parametresini dependency'lerde de tanฤฑmlayฤฑp, onlarฤฑn iรงinde cookie (ve header) set edebilirsiniz. + +## DoฤŸrudan bir `Response` dรถndรผrรผn { #return-a-response-directly } + +Kodunuzda doฤŸrudan bir `Response` dรถndรผrรผrken de cookie oluลŸturabilirsiniz. + +Bunu yapmak iรงin, [DoฤŸrudan Response Dรถndรผrme](response-directly.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑldฤฑฤŸฤฑ gibi bir response oluลŸturabilirsiniz. + +Sonra bunun iรงinde Cookie'leri set edin ve response'u dรถndรผrรผn: + +{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} + +/// tip | ฤฐpucu + +`Response` parametresini kullanmak yerine doฤŸrudan bir response dรถndรผrรผrseniz, FastAPI onu olduฤŸu gibi (doฤŸrudan) dรถndรผrรผr. + +Bu yรผzden, verinizin doฤŸru tipte olduฤŸundan emin olmanฤฑz gerekir. ร–rneฤŸin `JSONResponse` dรถndรผrรผyorsanฤฑz, verinin JSON ile uyumlu olmasฤฑ gerekir. + +Ayrฤฑca `response_model` tarafฤฑndan filtrelenmesi gereken bir veriyi gรถndermediฤŸinizden de emin olun. + +/// + +### Daha fazla bilgi { #more-info } + +/// note | Teknik Detaylar + +`from starlette.responses import Response` veya `from starlette.responses import JSONResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olmasฤฑ iรงin `fastapi.responses` iรงinde `starlette.responses` ile aynฤฑ response sฤฑnฤฑflarฤฑnฤฑ sunar. Ancak mevcut response'larฤฑn bรผyรผk kฤฑsmฤฑ doฤŸrudan Starlette'ten gelir. + +Ve `Response`, header ve cookie set etmek iรงin sฤฑk kullanฤฑldฤฑฤŸฤฑndan, **FastAPI** bunu `fastapi.Response` olarak da saฤŸlar. + +/// + +Mevcut tรผm parametreleri ve seรงenekleri gรถrmek iรงin Starlette dokรผmantasyonuna bakฤฑn. diff --git a/docs/tr/docs/advanced/response-directly.md b/docs/tr/docs/advanced/response-directly.md new file mode 100644 index 0000000000..332f1224fc --- /dev/null +++ b/docs/tr/docs/advanced/response-directly.md @@ -0,0 +1,65 @@ +# DoฤŸrudan Bir Response Dรถndรผrme { #return-a-response-directly } + +**FastAPI** ile bir *path operation* oluลŸturduฤŸunuzda, normalde ondan herhangi bir veri dรถndรผrebilirsiniz: bir `dict`, bir `list`, bir Pydantic model, bir veritabanฤฑ modeli vb. + +Varsayฤฑlan olarak **FastAPI**, dรถndรผrdรผฤŸรผnรผz bu deฤŸeri [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑlan `jsonable_encoder` ile otomatik olarak JSON'a รงevirir. + +Ardฤฑndan perde arkasฤฑnda, JSON-uyumlu bu veriyi (รถr. bir `dict`) client'a response gรถndermek iรงin kullanฤฑlacak bir `JSONResponse` iรงine yerleลŸtirir. + +Ancak *path operation*'larฤฑnฤฑzdan doฤŸrudan bir `JSONResponse` dรถndรผrebilirsiniz. + +Bu, รถrneฤŸin รถzel header'lar veya cookie'ler dรถndรผrmek istediฤŸinizde faydalฤฑ olabilir. + +## Bir `Response` Dรถndรผrme { #return-a-response } + +Aslฤฑnda herhangi bir `Response` veya onun herhangi bir alt sฤฑnฤฑfฤฑnฤฑ dรถndรผrebilirsiniz. + +/// tip | ฤฐpucu + +`JSONResponse` zaten `Response`'un bir alt sฤฑnฤฑfฤฑdฤฑr. + +/// + +Bir `Response` dรถndรผrdรผฤŸรผnรผzde, **FastAPI** bunu olduฤŸu gibi doฤŸrudan iletir. + +Pydantic model'leriyle herhangi bir veri dรถnรผลŸรผmรผ yapmaz, iรงeriฤŸi baลŸka bir tipe รงevirmez vb. + +Bu size ciddi bir esneklik saฤŸlar. Herhangi bir veri tรผrรผ dรถndรผrebilir, herhangi bir veri deklarasyonunu veya validasyonunu override edebilirsiniz. + +## Bir `Response` ฤฐรงinde `jsonable_encoder` Kullanma { #using-the-jsonable-encoder-in-a-response } + +**FastAPI**, sizin dรถndรผrdรผฤŸรผnรผz `Response` รผzerinde hiรงbir deฤŸiลŸiklik yapmadฤฑฤŸฤฑ iรงin, iรงeriฤŸinin gรถnderilmeye hazฤฑr olduฤŸundan emin olmanฤฑz gerekir. + +ร–rneฤŸin, bir Pydantic model'i, รถnce JSON-uyumlu tiplere รงevrilmeden (`datetime`, `UUID` vb.) doฤŸrudan bir `JSONResponse` iรงine koyamazsฤฑnฤฑz. ร–nce tรผm veri tipleri JSON-uyumlu hale gelecek ลŸekilde `dict`'e รงevrilmesi gerekir. + +Bu gibi durumlarda, response'a vermeden รถnce verinizi dรถnรผลŸtรผrmek iรงin `jsonable_encoder` kullanabilirsiniz: + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | Teknik Detaylar + +`from starlette.responses import JSONResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olmasฤฑ iรงin `starlette.responses` iรงeriฤŸini `fastapi.responses` รผzerinden de sunar. Ancak mevcut response'larฤฑn รงoฤŸu doฤŸrudan Starlette'tan gelir. + +/// + +## ร–zel Bir `Response` Dรถndรผrme { #returning-a-custom-response } + +Yukarฤฑdaki รถrnek ihtiyaรง duyduฤŸunuz tรผm parรงalarฤฑ gรถsteriyor, ancak henรผz รงok kullanฤฑลŸlฤฑ deฤŸil. ร‡รผnkรผ `item`'ฤฑ zaten doฤŸrudan dรถndรผrebilirdiniz ve **FastAPI** varsayฤฑlan olarak onu sizin iรงin bir `JSONResponse` iรงine koyup `dict`'e รงevirirdi vb. + +ลžimdi bunu kullanarak nasฤฑl รถzel bir response dรถndรผrebileceฤŸinize bakalฤฑm. + +Diyelim ki XML response dรถndรผrmek istiyorsunuz. + +XML iรงeriฤŸinizi bir string iรงine koyabilir, onu bir `Response` iรงine yerleลŸtirip dรถndรผrebilirsiniz: + +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} + +## Notlar { #notes } + +Bir `Response`'u doฤŸrudan dรถndรผrdรผฤŸรผnรผzde, verisi otomatik olarak validate edilmez, dรถnรผลŸtรผrรผlmez (serialize edilmez) veya dokรผmante edilmez. + +Ancak yine de [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑldฤฑฤŸฤฑ ลŸekilde dokรผmante edebilirsiniz. + +ฤฐlerleyen bรถlรผmlerde, otomatik veri dรถnรผลŸรผmรผ, dokรผmantasyon vb. รถzellikleri korurken bu รถzel `Response`'larฤฑ nasฤฑl kullanฤฑp declare edebileceฤŸinizi gรถreceksiniz. diff --git a/docs/tr/docs/advanced/response-headers.md b/docs/tr/docs/advanced/response-headers.md new file mode 100644 index 0000000000..85b0799d3f --- /dev/null +++ b/docs/tr/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# Response Header'larฤฑ { #response-headers } + +## Bir `Response` parametresi kullanฤฑn { #use-a-response-parameter } + +*Path operation function* iรงinde (cookie'lerde yapabildiฤŸiniz gibi) tipi `Response` olan bir parametre tanฤฑmlayabilirsiniz. + +Sonra da bu *geรงici* response nesnesi รผzerinde header'larฤฑ ayarlayabilirsiniz. + +{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} + +Ardฤฑndan normalde yaptฤฑฤŸฤฑnฤฑz gibi ihtiyacฤฑnฤฑz olan herhangi bir nesneyi dรถndรผrebilirsiniz (bir `dict`, bir veritabanฤฑ modeli vb.). + +EฤŸer bir `response_model` tanฤฑmladฤฑysanฤฑz, dรถndรผrdรผฤŸรผnรผz nesneyi filtrelemek ve dรถnรผลŸtรผrmek iรงin yine kullanฤฑlacaktฤฑr. + +**FastAPI**, header'larฤฑ (aynฤฑ ลŸekilde cookie'leri ve status code'u) bu *geรงici* response'dan alฤฑr ve dรถndรผrdรผฤŸรผnรผz deฤŸeri (varsa bir `response_model` ile filtrelenmiลŸ hรขliyle) iรงeren nihai response'a ekler. + +`Response` parametresini dependency'lerde de tanฤฑmlayฤฑp, onlarฤฑn iรงinde header (ve cookie) ayarlayabilirsiniz. + +## DoฤŸrudan bir `Response` dรถndรผrรผn { #return-a-response-directly } + +DoฤŸrudan bir `Response` dรถndรผrdรผฤŸรผnรผzde de header ekleyebilirsiniz. + +[Bir Response'u DoฤŸrudan Dรถndรผrรผn](response-directly.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑldฤฑฤŸฤฑ gibi bir response oluลŸturun ve header'larฤฑ ek bir parametre olarak geรงin: + +{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} + +/// note | Teknik Detaylar + +`from starlette.responses import Response` veya `from starlette.responses import JSONResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.responses` iรงeriฤŸini `fastapi.responses` olarak da sunar. Ancak mevcut response'larฤฑn รงoฤŸu doฤŸrudan Starlette'ten gelir. + +Ayrฤฑca `Response` header ve cookie ayarlamak iรงin sฤฑk kullanฤฑldฤฑฤŸฤฑndan, **FastAPI** bunu `fastapi.Response` altฤฑnda da saฤŸlar. + +/// + +## ร–zel Header'lar { #custom-headers } + +ร–zel/proprietary header'larฤฑn `X-` prefix'i kullanฤฑlarak eklenebileceฤŸini unutmayฤฑn. + +Ancak tarayฤฑcฤฑdaki bir client'ฤฑn gรถrebilmesini istediฤŸiniz รถzel header'larฤฑnฤฑz varsa, bunlarฤฑ CORS ayarlarฤฑnฤฑza eklemeniz gerekir ([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank} bรถlรผmรผnde daha fazla bilgi), bunun iรงin Starlette'in CORS dokรผmanฤฑnda aรงฤฑklanan `expose_headers` parametresini kullanฤฑn. diff --git a/docs/tr/docs/advanced/security/http-basic-auth.md b/docs/tr/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..b194c763e8 --- /dev/null +++ b/docs/tr/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +En basit senaryolarda HTTP Basic Auth kullanabilirsiniz. + +HTTP Basic Authโ€™ta uygulama, iรงinde kullanฤฑcฤฑ adฤฑ ve ลŸifre bulunan bir header bekler. + +EฤŸer bunu almazsa HTTP 401 "Unauthorized" hatasฤฑ dรถndรผrรผr. + +Ayrฤฑca deฤŸeri `Basic` olan ve isteฤŸe baฤŸlฤฑ `realm` parametresi iรงerebilen `WWW-Authenticate` headerโ€™ฤฑnฤฑ da dรถndรผrรผr. + +Bu da tarayฤฑcฤฑya, kullanฤฑcฤฑ adฤฑ ve ลŸifre iรงin entegre giriลŸ penceresini gรถstermesini sรถyler. + +Ardฤฑndan kullanฤฑcฤฑ adฤฑ ve ลŸifreyi yazdฤฑฤŸฤฑnฤฑzda tarayฤฑcฤฑ bunlarฤฑ otomatik olarak header iรงinde gรถnderir. + +## Basit HTTP Basic Auth { #simple-http-basic-auth } + +* `HTTPBasic` ve `HTTPBasicCredentials` import edin. +* `HTTPBasic` kullanarak bir "`security` scheme" oluลŸturun. +* *path operation*โ€™ฤฑnฤฑzda bir dependency ile bu `security`โ€™yi kullanฤฑn. +* Bu, `HTTPBasicCredentials` tipinde bir nesne dรถndรผrรผr: + * ฤฐรงinde gรถnderilen `username` ve `password` bulunur. + +{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} + +URLโ€™yi ilk kez aรงmaya รงalฤฑลŸtฤฑฤŸฤฑnฤฑzda (veya dokรผmanlardaki "Execute" butonuna tฤฑkladฤฑฤŸฤฑnฤฑzda) tarayฤฑcฤฑ sizden kullanฤฑcฤฑ adฤฑnฤฑzฤฑ ve ลŸifrenizi ister: + + + +## Kullanฤฑcฤฑ adฤฑnฤฑ kontrol edin { #check-the-username } + +Daha kapsamlฤฑ bir รถrneฤŸe bakalฤฑm. + +Kullanฤฑcฤฑ adฤฑ ve ลŸifrenin doฤŸru olup olmadฤฑฤŸฤฑnฤฑ kontrol etmek iรงin bir dependency kullanฤฑn. + +Bunun iรงin kullanฤฑcฤฑ adฤฑ ve ลŸifreyi kontrol ederken Python standart modรผlรผ olan `secrets`โ€™i kullanฤฑn. + +`secrets.compare_digest()`; `bytes` ya da yalnฤฑzca ASCII karakterleri (ฤฐngilizceโ€™deki karakterler) iรงeren bir `str` almalฤฑdฤฑr. Bu da `Sebastiรกn` iรงindeki `รก` gibi karakterlerle รงalฤฑลŸmayacaฤŸฤฑ anlamฤฑna gelir. + +Bunu yรถnetmek iรงin รถnce `username` ve `password` deฤŸerlerini UTF-8 ile encode ederek `bytes`โ€™a dรถnรผลŸtรผrรผrรผz. + +Sonra `secrets.compare_digest()` kullanarak `credentials.username`โ€™in `"stanleyjobson"` ve `credentials.password`โ€™รผn `"swordfish"` olduฤŸundan emin olabiliriz. + +{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} + +Bu, kabaca ลŸuna benzer olurdu: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Return some error + ... +``` + +Ancak `secrets.compare_digest()` kullanarak, "timing attacks" denilen bir saldฤฑrฤฑ tรผrรผne karลŸฤฑ gรผvenli olursunuz. + +### Timing Attacks { #timing-attacks } + +Peki "timing attack" nedir? + +Bazฤฑ saldฤฑrganlarฤฑn kullanฤฑcฤฑ adฤฑ ve ลŸifreyi tahmin etmeye รงalฤฑลŸtฤฑฤŸฤฑnฤฑ dรผลŸรผnelim. + +Ve `johndoe` kullanฤฑcฤฑ adฤฑ ve `love123` ลŸifresi ile bir request gรถnderiyorlar. + +Uygulamanฤฑzdaki Python kodu o zaman kabaca ลŸuna denk olur: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Ancak Python, `johndoe` iรงindeki ilk `j` ile `stanleyjobson` iรงindeki ilk `s`โ€™i karลŸฤฑlaลŸtฤฑrdฤฑฤŸฤฑ anda `False` dรถndรผrรผr; รงรผnkรผ iki stringโ€™in aynฤฑ olmadฤฑฤŸฤฑnฤฑ zaten anlar ve "kalan harfleri karลŸฤฑlaลŸtฤฑrmak iรงin daha fazla hesaplama yapmaya gerek yok" diye dรผลŸรผnรผr. Uygulamanฤฑz da "Incorrect username or password" der. + +Sonra saldฤฑrganlar bu sefer `stanleyjobsox` kullanฤฑcฤฑ adฤฑ ve `love123` ลŸifresi ile dener. + +Uygulama kodunuz da ลŸuna benzer bir ลŸey yapar: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Bu kez Python, iki stringโ€™in aynฤฑ olmadฤฑฤŸฤฑnฤฑ fark etmeden รถnce hem `stanleyjobsox` hem de `stanleyjobson` iรงinde `stanleyjobso` kฤฑsmฤฑnฤฑn tamamฤฑnฤฑ karลŸฤฑlaลŸtฤฑrmak zorunda kalฤฑr. Bu nedenle "Incorrect username or password" yanฤฑtฤฑnฤฑ vermesi birkaรง mikro saniye daha uzun sรผrer. + +#### Yanฤฑt sรผresi saldฤฑrganlara yardฤฑmcฤฑ olur { #the-time-to-answer-helps-the-attackers } + +Bu noktada saldฤฑrganlar, serverโ€™ฤฑn "Incorrect username or password" responseโ€™unu gรถndermesinin birkaรง mikro saniye daha uzun sรผrdรผฤŸรผnรผ fark ederek _bir ลŸeyleri_ doฤŸru yaptฤฑklarฤฑnฤฑ anlar; yani baลŸlangฤฑรงtaki bazฤฑ harfler doฤŸrudur. + +Sonra tekrar denerken, bunun `johndoe`โ€™dan ziyade `stanleyjobsox`โ€™a daha yakฤฑn bir ลŸey olmasฤฑ gerektiฤŸini bilerek devam edebilirler. + +#### "Profesyonel" bir saldฤฑrฤฑ { #a-professional-attack } + +Elbette saldฤฑrganlar bunu elle tek tek denemez; bunu yapan bir program yazarlar. Muhtemelen saniyede binlerce ya da milyonlarca test yaparlar ve her seferinde yalnฤฑzca bir doฤŸru harf daha elde ederler. + +Bรถylece birkaรง dakika ya da birkaรง saat iรงinde doฤŸru kullanฤฑcฤฑ adฤฑ ve ลŸifreyi, yanฤฑt sรผresini kullanarak ve uygulamamฤฑzฤฑn "yardฤฑmฤฑyla" tahmin etmiลŸ olurlar. + +#### `secrets.compare_digest()` ile dรผzeltin { #fix-it-with-secrets-compare-digest } + +Ancak bizim kodumuzda `secrets.compare_digest()` kullanฤฑyoruz. + +Kฤฑsacasฤฑ, `stanleyjobsox` ile `stanleyjobson`โ€™u karลŸฤฑlaลŸtฤฑrmak iรงin geรงen sรผre, `johndoe` ile `stanleyjobson`โ€™u karลŸฤฑlaลŸtฤฑrmak iรงin geรงen sรผreyle aynฤฑ olur. ลžifre iรงin de aynฤฑ ลŸekilde. + +Bu sayede uygulama kodunuzda `secrets.compare_digest()` kullanarak bu gรผvenlik saldฤฑrฤฑlarฤฑ ailesine karลŸฤฑ gรผvenli olursunuz. + +### Hatayฤฑ dรถndรผrรผn { #return-the-error } + +Credentialโ€™larฤฑn hatalฤฑ olduฤŸunu tespit ettikten sonra, 401 status code ile (credential verilmediฤŸinde dรถnenle aynฤฑ) bir `HTTPException` dรถndรผrรผn ve tarayฤฑcฤฑnฤฑn giriลŸ penceresini yeniden gรถstermesi iรงin `WWW-Authenticate` headerโ€™ฤฑnฤฑ ekleyin: + +{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} diff --git a/docs/tr/docs/advanced/security/oauth2-scopes.md b/docs/tr/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..ecba7851b0 --- /dev/null +++ b/docs/tr/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 scope'larฤฑ { #oauth2-scopes } + +OAuth2 scope'larฤฑnฤฑ **FastAPI** ile doฤŸrudan kullanabilirsiniz; sorunsuz รงalฤฑลŸacak ลŸekilde entegre edilmiลŸtir. + +Bu sayede OAuth2 standardฤฑnฤฑ takip eden, daha ince taneli bir izin sistemini OpenAPI uygulamanฤฑza (ve API dokรผmanlarฤฑnฤฑza) entegre edebilirsiniz. + +Scope'lu OAuth2; Facebook, Google, GitHub, Microsoft, X (Twitter) vb. birรงok bรผyรผk kimlik doฤŸrulama saฤŸlayฤฑcฤฑsฤฑnฤฑn kullandฤฑฤŸฤฑ mekanizmadฤฑr. Kullanฤฑcฤฑ ve uygulamalara belirli izinler vermek iรงin bunu kullanฤฑrlar. + +Facebook, Google, GitHub, Microsoft, X (Twitter) ile "giriลŸ yaptฤฑฤŸฤฑnฤฑzda", o uygulama scope'lu OAuth2 kullanฤฑyor demektir. + +Bu bรถlรผmde, **FastAPI** uygulamanฤฑzda aynฤฑ scope'lu OAuth2 ile authentication ve authorization'ฤฑ nasฤฑl yรถneteceฤŸinizi gรถreceksiniz. + +/// warning | Uyarฤฑ + +Bu bรถlรผm az รงok ileri seviye sayฤฑlฤฑr. Yeni baลŸlฤฑyorsanฤฑz atlayabilirsiniz. + +OAuth2 scope'larฤฑna mutlaka ihtiyacฤฑnฤฑz yok; authentication ve authorization'ฤฑ istediฤŸiniz ลŸekilde ele alabilirsiniz. + +Ancak scope'lu OAuth2, API'nize (OpenAPI ile) ve API dokรผmanlarฤฑnฤฑza gรผzel biรงimde entegre edilebilir. + +Buna raฤŸmen, bu scope'larฤฑ (veya baลŸka herhangi bir security/authorization gereksinimini) kodunuzda ihtiyaรง duyduฤŸunuz ลŸekilde yine siz zorunlu kฤฑlarsฤฑnฤฑz. + +Birรงok durumda scope'lu OAuth2 gereฤŸinden fazla (overkill) olabilir. + +Ama ihtiyacฤฑnฤฑz olduฤŸunu biliyorsanฤฑz ya da merak ediyorsanฤฑz okumaya devam edin. + +/// + +## OAuth2 scope'larฤฑ ve OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 spesifikasyonu, "scope"larฤฑ boลŸluklarla ayrฤฑlmฤฑลŸ string'lerden oluลŸan bir liste olarak tanฤฑmlar. + +Bu string'lerin her birinin iรงeriฤŸi herhangi bir formatta olabilir, ancak boลŸluk iรงermemelidir. + +Bu scope'lar "izinleri" temsil eder. + +OpenAPI'de (รถr. API dokรผmanlarฤฑnda) "security scheme" tanฤฑmlayabilirsiniz. + +Bu security scheme'lerden biri OAuth2 kullanฤฑyorsa, scope'larฤฑ da tanฤฑmlayฤฑp kullanabilirsiniz. + +Her bir "scope" sadece bir string'dir (boลŸluksuz). + +Genellikle belirli gรผvenlik izinlerini tanฤฑmlamak iรงin kullanฤฑlฤฑr, รถrneฤŸin: + +* `users:read` veya `users:write` sฤฑk gรถrรผlen รถrneklerdir. +* `instagram_basic` Facebook / Instagram tarafฤฑndan kullanฤฑlฤฑr. +* `https://www.googleapis.com/auth/drive` Google tarafฤฑndan kullanฤฑlฤฑr. + +/// info | Bilgi + +OAuth2'de "scope", gereken belirli bir izni bildiren bir string'den ibarettir. + +`:` gibi baลŸka karakterler iรงermesi ya da bir URL olmasฤฑ รถnemli deฤŸildir. + +Bu detaylar implementasyon'a baฤŸlฤฑdฤฑr. + +OAuth2 iรงin bunlar sadece string'dir. + +/// + +## Genel gรถrรผnรผm { #global-view } + +ร–nce, ana **Tutorial - User Guide** iรงindeki [Password (ve hashing) ile OAuth2, JWT token'lฤฑ Bearer](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} รถrneklerinden, OAuth2 scope'larฤฑna geรงince hangi kฤฑsฤฑmlarฤฑn deฤŸiลŸtiฤŸine hฤฑzlฤฑca bakalฤฑm: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +ลžimdi bu deฤŸiลŸiklikleri adฤฑm adฤฑm inceleyelim. + +## OAuth2 Security scheme { #oauth2-security-scheme } + +ฤฐlk deฤŸiลŸiklik, artฤฑk OAuth2 security scheme'ini iki adet kullanฤฑlabilir scope ile tanฤฑmlamamฤฑz: `me` ve `items`. + +`scopes` parametresi; her scope'un key, aรงฤฑklamasฤฑnฤฑn ise value olduฤŸu bir `dict` alฤฑr: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +Bu scope'larฤฑ tanฤฑmladฤฑฤŸฤฑmฤฑz iรงin, login/authorize yaptฤฑฤŸฤฑnฤฑzda API dokรผmanlarฤฑnda gรถrรผnecekler. + +Ve hangi scope'lara eriลŸim vermek istediฤŸinizi seรงebileceksiniz: `me` ve `items`. + +Bu, Facebook/Google/GitHub vb. ile giriลŸ yaparken izin verdiฤŸinizde kullanฤฑlan mekanizmanฤฑn aynฤฑsฤฑdฤฑr: + + + +## Scope'lu JWT token { #jwt-token-with-scopes } + +ลžimdi token *path operation*'ฤฑnฤฑ, istenen scope'larฤฑ dรถndรผrecek ลŸekilde deฤŸiลŸtirin. + +Hรขlรข aynฤฑ `OAuth2PasswordRequestForm` kullanฤฑlฤฑyor. Bu form, request'te aldฤฑฤŸฤฑ her scope iรงin `str`'lerden oluลŸan bir `list` iรงeren `scopes` รถzelliฤŸine sahiptir. + +Ve scope'larฤฑ JWT token'ฤฑn bir parรงasฤฑ olarak dรถndรผrรผyoruz. + +/// danger | Uyarฤฑ + +Basitlik iรงin burada, gelen scope'larฤฑ doฤŸrudan token'a ekliyoruz. + +Ama uygulamanฤฑzda gรผvenlik aรงฤฑsฤฑndan, yalnฤฑzca kullanฤฑcฤฑnฤฑn gerรงekten sahip olabileceฤŸi scope'larฤฑ (veya sizin รถnceden tanฤฑmladฤฑklarฤฑnฤฑzฤฑ) eklediฤŸinizden emin olmalฤฑsฤฑnฤฑz. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## *Path operation*'larda ve dependency'lerde scope tanฤฑmlama { #declare-scopes-in-path-operations-and-dependencies } + +Artฤฑk `/users/me/items/` iรงin olan *path operation*'ฤฑn `items` scope'unu gerektirdiฤŸini tanฤฑmlฤฑyoruz. + +Bunun iรงin `fastapi` iรงinden `Security` import edip kullanฤฑyoruz. + +Dependency'leri (`Depends` gibi) tanฤฑmlamak iรงin `Security` kullanabilirsiniz; fakat `Security`, ayrฤฑca string'lerden oluลŸan bir scope listesi alan `scopes` parametresini de alฤฑr. + +Bu durumda `Security`'ye dependency fonksiyonu olarak `get_current_active_user` veriyoruz (`Depends` ile yaptฤฑฤŸฤฑmฤฑz gibi). + +Ama ayrฤฑca bir `list` olarak scope'larฤฑ da veriyoruz; burada tek bir scope var: `items` (daha fazla da olabilir). + +Ve `get_current_active_user` dependency fonksiyonu, sadece `Depends` ile deฤŸil `Security` ile de alt-dependency'ler tanฤฑmlayabilir. Kendi alt-dependency fonksiyonunu (`get_current_user`) ve daha fazla scope gereksinimini tanฤฑmlar. + +Bu รถrnekte `me` scope'unu gerektiriyor (birden fazla scope da isteyebilirdi). + +/// note | Not + +Farklฤฑ yerlerde farklฤฑ scope'lar eklemek zorunda deฤŸilsiniz. + +Burada, **FastAPI**'nin farklฤฑ seviyelerde tanฤฑmlanan scope'larฤฑ nasฤฑl ele aldฤฑฤŸฤฑnฤฑ gรถstermek iรงin bรถyle yapฤฑyoruz. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | Teknik Detaylar + +`Security` aslฤฑnda `Depends`'in bir alt sฤฑnฤฑfฤฑdฤฑr ve sadece birazdan gรถreceฤŸimiz bir ek parametreye sahiptir. + +Ancak `Depends` yerine `Security` kullanฤฑnca **FastAPI**, security scope'larฤฑnฤฑn tanฤฑmlanabileceฤŸini bilir, bunlarฤฑ iรงeride kullanฤฑr ve API'yi OpenAPI ile dokรผmante eder. + +Fakat `fastapi` iรงinden `Query`, `Path`, `Depends`, `Security` vb. import ettiฤŸiniz ลŸeyler, aslฤฑnda รถzel sฤฑnฤฑflar dรถndรผren fonksiyonlardฤฑr. + +/// + +## `SecurityScopes` kullanฤฑmฤฑ { #use-securityscopes } + +ลžimdi `get_current_user` dependency'sini gรผncelleyelim. + +Bu fonksiyon, yukarฤฑdaki dependency'ler tarafฤฑndan kullanฤฑlฤฑyor. + +Burada, daha รถnce oluลŸturduฤŸumuz aynฤฑ OAuth2 scheme'i dependency olarak tanฤฑmlฤฑyoruz: `oauth2_scheme`. + +Bu dependency fonksiyonunun kendi iรงinde bir scope gereksinimi olmadฤฑฤŸฤฑ iรงin, `oauth2_scheme` ile `Depends` kullanabiliriz; security scope'larฤฑnฤฑ belirtmemiz gerekmiyorsa `Security` kullanmak zorunda deฤŸiliz. + +Ayrฤฑca `fastapi.security` iรงinden import edilen, `SecurityScopes` tipinde รถzel bir parametre tanฤฑmlฤฑyoruz. + +Bu `SecurityScopes` sฤฑnฤฑfฤฑ, `Request`'e benzer (`Request`, request nesnesini doฤŸrudan almak iรงin kullanฤฑlmฤฑลŸtฤฑ). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## `scopes`'larฤฑ kullanma { #use-the-scopes } + +`security_scopes` parametresi `SecurityScopes` tipinde olacaktฤฑr. + +Bu nesnenin `scopes` adlฤฑ bir รถzelliฤŸi vardฤฑr; bu liste, kendisinin ve bunu alt-dependency olarak kullanan tรผm dependency'lerin gerektirdiฤŸi tรผm scope'larฤฑ iรงerir. Yani tรผm "dependant"lar... kafa karฤฑลŸtฤฑrฤฑcฤฑ gelebilir; aลŸaฤŸฤฑda tekrar aรงฤฑklanฤฑyor. + +`security_scopes` nesnesi (`SecurityScopes` sฤฑnฤฑfฤฑndan) ayrฤฑca, bu scope'larฤฑ boลŸluklarla ayrฤฑlmฤฑลŸ tek bir string olarak veren `scope_str` attribute'una sahiptir (bunu kullanacaฤŸฤฑz). + +Sonrasฤฑnda birkaรง farklฤฑ noktada tekrar kullanabileceฤŸimiz (`raise` edebileceฤŸimiz) bir `HTTPException` oluลŸturuyoruz. + +Bu exception iรงinde, gerekiyorsa, gerekli scope'larฤฑ boลŸlukla ayrฤฑlmฤฑลŸ bir string olarak (`scope_str` ile) ekliyoruz. Bu scope'larฤฑ iรงeren string'i `WWW-Authenticate` header'ฤฑna koyuyoruz (spesifikasyonun bir parรงasฤฑ). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## `username` ve veri ลŸeklinin doฤŸrulanmasฤฑ { #verify-the-username-and-data-shape } + +Bir `username` aldฤฑฤŸฤฑmฤฑzฤฑ doฤŸruluyoruz ve scope'larฤฑ รงฤฑkarฤฑyoruz. + +Ardฤฑndan bu veriyi Pydantic model'i ile doฤŸruluyoruz (`ValidationError` exception'ฤฑnฤฑ yakalayarak). JWT token'ฤฑ okurken veya Pydantic ile veriyi doฤŸrularken bir hata olursa, daha รถnce oluลŸturduฤŸumuz `HTTPException`'ฤฑ fฤฑrlatฤฑyoruz. + +Bunun iรงin Pydantic model'i `TokenData`'yฤฑ, `scopes` adlฤฑ yeni bir รถzellik ekleyerek gรผncelliyoruz. + +Veriyi Pydantic ile doฤŸrulayarak รถrneฤŸin scope'larฤฑn tam olarak `str`'lerden oluลŸan bir `list` olduฤŸunu ve `username`'in bir `str` olduฤŸunu garanti edebiliriz. + +Aksi halde, รถrneฤŸin bir `dict` veya baลŸka bir ลŸey gelebilir; bu da daha sonra uygulamanฤฑn bir yerinde kฤฑrฤฑlmaya yol aรงฤฑp gรผvenlik riski oluลŸturabilir. + +Ayrฤฑca bu `username` ile bir kullanฤฑcฤฑ olduฤŸunu doฤŸruluyoruz; yoksa yine aynฤฑ exception'ฤฑ fฤฑrlatฤฑyoruz. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## `scopes`'larฤฑn doฤŸrulanmasฤฑ { #verify-the-scopes } + +ลžimdi bu dependency'nin ve tรผm dependant'larฤฑn ( *path operation*'lar dahil) gerektirdiฤŸi tรผm scope'larฤฑn, alฤฑnan token'da saฤŸlanan scope'lar iรงinde olup olmadฤฑฤŸฤฑnฤฑ doฤŸruluyoruz; deฤŸilse `HTTPException` fฤฑrlatฤฑyoruz. + +Bunun iรงin, tรผm bu scope'larฤฑ `str` olarak iรงeren bir `list` olan `security_scopes.scopes` kullanฤฑlฤฑr. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Dependency aฤŸacฤฑ ve scope'lar { #dependency-tree-and-scopes } + +Bu dependency aฤŸacฤฑnฤฑ ve scope'larฤฑ tekrar gรถzden geรงirelim. + +`get_current_active_user` dependency'si, alt-dependency olarak `get_current_user`'ฤฑ kullandฤฑฤŸฤฑ iรงin, `get_current_active_user` รผzerinde tanฤฑmlanan `"me"` scope'u, `get_current_user`'a geรงirilen `security_scopes.scopes` iรงindeki gerekli scope listesine dahil edilir. + +*Path operation*'ฤฑn kendisi de `"items"` scope'unu tanฤฑmlar; bu da `get_current_user`'a geรงirilen `security_scopes.scopes` listesinde yer alฤฑr. + +Dependency'lerin ve scope'larฤฑn hiyerarลŸisi ลŸรถyle gรถrรผnรผr: + +* *Path operation* `read_own_items` ลŸunlara sahiptir: + * Dependency ile gerekli scope'lar `["items"]`: + * `get_current_active_user`: + * `get_current_active_user` dependency fonksiyonu ลŸunlara sahiptir: + * Dependency ile gerekli scope'lar `["me"]`: + * `get_current_user`: + * `get_current_user` dependency fonksiyonu ลŸunlara sahiptir: + * Kendisinin gerektirdiฤŸi scope yok. + * `oauth2_scheme` kullanan bir dependency. + * `SecurityScopes` tipinde bir `security_scopes` parametresi: + * Bu `security_scopes` parametresinin `scopes` adlฤฑ bir รถzelliฤŸi vardฤฑr ve yukarฤฑda tanฤฑmlanan tรผm scope'larฤฑ iรงeren bir `list` taลŸฤฑr, yani: + * *Path operation* `read_own_items` iรงin `security_scopes.scopes` `["me", "items"]` iรงerir. + * *Path operation* `read_users_me` iรงin `security_scopes.scopes` `["me"]` iรงerir; รงรผnkรผ bu scope `get_current_active_user` dependency'sinde tanฤฑmlanmฤฑลŸtฤฑr. + * *Path operation* `read_system_status` iรงin `security_scopes.scopes` `[]` (boลŸ) olur; รงรผnkรผ herhangi bir `Security` ile `scopes` tanฤฑmlamamฤฑลŸtฤฑr ve dependency'si olan `get_current_user` da `scopes` tanฤฑmlamaz. + +/// tip | ฤฐpucu + +Buradaki รถnemli ve "sihirli" nokta ลŸu: `get_current_user`, her *path operation* iรงin kontrol etmesi gereken farklฤฑ bir `scopes` listesi alฤฑr. + +Bu, belirli bir *path operation* iรงin dependency aฤŸacฤฑndaki her *path operation* ve her dependency รผzerinde tanฤฑmlanan `scopes`'lara baฤŸlฤฑdฤฑr. + +/// + +## `SecurityScopes` hakkฤฑnda daha fazla detay { #more-details-about-securityscopes } + +`SecurityScopes`'u herhangi bir noktada ve birden fazla yerde kullanabilirsiniz; mutlaka "kรถk" dependency'de olmak zorunda deฤŸildir. + +Her zaman, **o spesifik** *path operation* ve **o spesifik** dependency aฤŸacฤฑ iรงin, mevcut `Security` dependency'lerinde ve tรผm dependant'larda tanฤฑmlanan security scope'larฤฑnฤฑ iรงerir. + +`SecurityScopes`, dependant'larฤฑn tanฤฑmladฤฑฤŸฤฑ tรผm scope'larฤฑ barฤฑndฤฑrdฤฑฤŸฤฑ iรงin, gereken scope'larฤฑn token'da olup olmadฤฑฤŸฤฑnฤฑ merkezi bir dependency fonksiyonunda doฤŸrulayฤฑp, farklฤฑ *path operation*'larda farklฤฑ scope gereksinimleri tanฤฑmlayabilirsiniz. + +Bu kontroller her *path operation* iรงin baฤŸฤฑmsฤฑz yapฤฑlฤฑr. + +## Deneyin { #check-it } + +API dokรผmanlarฤฑnฤฑ aรงarsanฤฑz, authenticate olup hangi scope'larฤฑ authorize etmek istediฤŸinizi seรงebilirsiniz. + + + +Hiรง scope seรงmezseniz "authenticated" olursunuz; ancak `/users/me/` veya `/users/me/items/`'e eriลŸmeye รงalฤฑลŸtฤฑฤŸฤฑnฤฑzda, yeterli izniniz olmadฤฑฤŸฤฑnฤฑ sรถyleyen bir hata alฤฑrsฤฑnฤฑz. Yine de `/status/`'a eriลŸebilirsiniz. + +`me` scope'unu seรงip `items` scope'unu seรงmezseniz `/users/me/`'a eriลŸebilirsiniz ama `/users/me/items/`'e eriลŸemezsiniz. + +Bu, bir รผรงรผncรผ taraf uygulamanฤฑn, bir kullanฤฑcฤฑ tarafฤฑndan saฤŸlanan token ile bu *path operation*'lardan birine eriลŸmeye รงalฤฑลŸtฤฑฤŸฤฑnda; kullanฤฑcฤฑnฤฑn uygulamaya kaรง izin verdiฤŸine baฤŸlฤฑ olarak yaลŸayacaฤŸฤฑ durumdur. + +## รœรงรผncรผ taraf entegrasyonlarฤฑ hakkฤฑnda { #about-third-party-integrations } + +Bu รถrnekte OAuth2 "password" flow'unu kullanฤฑyoruz. + +Bu, kendi uygulamamฤฑza giriลŸ yaptฤฑฤŸฤฑmฤฑz durumlar iรงin uygundur; muhtemelen kendi frontend'imiz vardฤฑr. + +ร‡รผnkรผ `username` ve `password` alacaฤŸฤฑnฤฑ bildiฤŸimiz frontend'i biz kontrol ediyoruz, dolayฤฑsฤฑyla gรผvenebiliriz. + +Ancak baลŸkalarฤฑnฤฑn baฤŸlanacaฤŸฤฑ bir OAuth2 uygulamasฤฑ geliลŸtiriyorsanฤฑz (yani Facebook, Google, GitHub vb. gibi bir authentication provider muadili geliลŸtiriyorsanฤฑz) diฤŸer flow'lardan birini kullanmalฤฑsฤฑnฤฑz. + +En yaygฤฑnฤฑ implicit flow'dur. + +En gรผvenlisi code flow'dur; ancak daha fazla adฤฑm gerektirdiฤŸi iรงin implementasyonu daha karmaลŸฤฑktฤฑr. Daha karmaลŸฤฑk olduฤŸundan, birรงok saฤŸlayฤฑcฤฑ implicit flow'yu รถnermeye yรถnelir. + +/// note | Not + +Her authentication provider'ฤฑn flow'larฤฑ markasฤฑnฤฑn bir parรงasฤฑ yapmak iรงin farklฤฑ ลŸekilde adlandฤฑrmasฤฑ yaygฤฑndฤฑr. + +Ama sonuรงta aynฤฑ OAuth2 standardฤฑnฤฑ implement ediyorlar. + +/// + +**FastAPI**, bu OAuth2 authentication flow'larฤฑnฤฑn tamamฤฑ iรงin `fastapi.security.oauth2` iรงinde yardฤฑmcฤฑ araรงlar sunar. + +## Decorator `dependencies` iรงinde `Security` { #security-in-decorator-dependencies } + +Decorator'ฤฑn `dependencies` parametresinde bir `list` `Depends` tanฤฑmlayabildiฤŸiniz gibi ( [Path operation decorator'larฤฑnda Dependencies](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} bรถlรผmรผnde aรงฤฑklandฤฑฤŸฤฑ รผzere), burada `scopes` ile birlikte `Security` de kullanabilirsiniz. diff --git a/docs/tr/docs/advanced/settings.md b/docs/tr/docs/advanced/settings.md new file mode 100644 index 0000000000..e3bcaac610 --- /dev/null +++ b/docs/tr/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Ayarlar ve Ortam DeฤŸiลŸkenleri { #settings-and-environment-variables } + +Birรงok durumda uygulamanฤฑzฤฑn bazฤฑ harici ayarlara veya konfigรผrasyonlara ihtiyacฤฑ olabilir; รถrneฤŸin secret key'ler, veritabanฤฑ kimlik bilgileri, e-posta servisleri iรงin kimlik bilgileri vb. + +Bu ayarlarฤฑn รงoฤŸu deฤŸiลŸkendir (deฤŸiลŸebilir); รถrneฤŸin veritabanฤฑ URL'leri. Ayrฤฑca birรงoฤŸu hassas olabilir; รถrneฤŸin secret'lar. + +Bu nedenle bunlarฤฑ, uygulama tarafฤฑndan okunan environment variable'lar ile saฤŸlamak yaygฤฑndฤฑr. + +/// tip | ฤฐpucu + +Environment variable'larฤฑ anlamak iรงin [Environment Variables](../environment-variables.md){.internal-link target=_blank} dokรผmanฤฑnฤฑ okuyabilirsiniz. + +/// + +## Tipler ve doฤŸrulama { #types-and-validation } + +Bu environment variable'lar yalnฤฑzca metin (string) taลŸฤฑyabilir; รงรผnkรผ Python'ฤฑn dฤฑลŸฤฑndadฤฑrlar ve diฤŸer programlarla ve sistemin geri kalanฤฑyla uyumlu olmalarฤฑ gerekir (hatta Linux, Windows, macOS gibi farklฤฑ iลŸletim sistemleriyle de). + +Bu da, Python iรงinde bir environment variable'dan okunan herhangi bir deฤŸerin `str` olacaฤŸฤฑ anlamฤฑna gelir; farklฤฑ bir tipe dรถnรผลŸtรผrme veya herhangi bir doฤŸrulama iลŸlemi kod iรงinde yapฤฑlmalฤฑdฤฑr. + +## Pydantic `Settings` { #pydantic-settings } + +Neyse ki Pydantic, environment variable'lardan gelen bu ayarlarฤฑ yรถnetmek iรงin Pydantic: Settings management ile รงok iyi bir yardฤฑmcฤฑ araรง sunar. + +### `pydantic-settings`'i kurun { #install-pydantic-settings } + +ร–nce, [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, aktive ettiฤŸinizden emin olun ve ardฤฑndan `pydantic-settings` paketini kurun: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +Ayrฤฑca `all` extras'ฤฑnฤฑ ลŸu ลŸekilde kurduฤŸunuzda da dahil gelir: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### `Settings` nesnesini oluลŸturun { #create-the-settings-object } + +Pydantic'ten `BaseSettings` import edin ve bir alt sฤฑnฤฑf (sub-class) oluลŸturun; tฤฑpkฤฑ bir Pydantic model'inde olduฤŸu gibi. + +Pydantic model'lerinde olduฤŸu gibi, type annotation'larla (ve gerekirse default deฤŸerlerle) class attribute'larฤฑ tanฤฑmlarsฤฑnฤฑz. + +Pydantic model'lerinde kullandฤฑฤŸฤฑnฤฑz aynฤฑ doฤŸrulama รถzelliklerini ve araรงlarฤฑnฤฑ burada da kullanabilirsiniz; รถrneฤŸin farklฤฑ veri tipleri ve `Field()` ile ek doฤŸrulamalar. + +{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} + +/// tip | ฤฐpucu + +Hฤฑzlฤฑca kopyalayฤฑp yapฤฑลŸtฤฑrmak istiyorsanฤฑz bu รถrneฤŸi kullanmayฤฑn; aลŸaฤŸฤฑdaki son รถrneฤŸi kullanฤฑn. + +/// + +Ardฤฑndan, bu `Settings` sฤฑnฤฑfฤฑnฤฑn bir instance'ฤฑnฤฑ oluลŸturduฤŸunuzda (bu รถrnekte `settings` nesnesi), Pydantic environment variable'larฤฑ bรผyรผk/kรผรงรผk harfe duyarsฤฑz ลŸekilde okur; yani bรผyรผk harfli `APP_NAME` deฤŸiลŸkeni, yine de `app_name` attribute'u iรงin okunur. + +Sonrasฤฑnda veriyi dรถnรผลŸtรผrรผr ve doฤŸrular. Bรถylece `settings` nesnesini kullandฤฑฤŸฤฑnฤฑzda, tanฤฑmladฤฑฤŸฤฑnฤฑz tiplerde verilere sahip olursunuz (รถrn. `items_per_user` bir `int` olur). + +### `settings`'i kullanฤฑn { #use-the-settings } + +Daha sonra uygulamanฤฑzda yeni `settings` nesnesini kullanabilirsiniz: + +{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} + +### Server'ฤฑ รงalฤฑลŸtฤฑrฤฑn { #run-the-server } + +Sonraki adฤฑmda server'ฤฑ รงalฤฑลŸtฤฑrฤฑrken konfigรผrasyonlarฤฑ environment variable olarak geรงersiniz; รถrneฤŸin `ADMIN_EMAIL` ve `APP_NAME` ลŸu ลŸekilde ayarlanabilir: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | ฤฐpucu + +Tek bir komut iรงin birden fazla env var ayarlamak istiyorsanฤฑz aralarฤฑna boลŸluk koyun ve hepsini komuttan รถnce yazฤฑn. + +/// + +Bรถylece `admin_email` ayarฤฑ `"deadpool@example.com"` olur. + +`app_name` `"ChimichangApp"` olur. + +`items_per_user` ise default deฤŸeri olan `50` olarak kalฤฑr. + +## Ayarlarฤฑ baลŸka bir module'de tutma { #settings-in-another-module } + +[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank} bรถlรผmรผnde gรถrdรผฤŸรผnรผz gibi, bu ayarlarฤฑ baลŸka bir module dosyasฤฑna koyabilirsiniz. + +ร–rneฤŸin `config.py` adฤฑnda bir dosyanฤฑz ลŸu ลŸekilde olabilir: + +{* ../../docs_src/settings/app01_py39/config.py *} + +Ve ardฤฑndan bunu `main.py` dosyasฤฑnda kullanabilirsiniz: + +{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} + +/// tip | ฤฐpucu + +[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank} bรถlรผmรผnde gรถrdรผฤŸรผnรผz gibi, ayrฤฑca bir `__init__.py` dosyasฤฑna da ihtiyacฤฑnฤฑz olacak. + +/// + +## Dependency iรงinde ayarlar { #settings-in-a-dependency } + +Bazฤฑ durumlarda, her yerde kullanฤฑlan global bir `settings` nesnesi yerine ayarlarฤฑ bir dependency รผzerinden saฤŸlamak faydalฤฑ olabilir. + +Bu รถzellikle test sฤฑrasฤฑnda รงok iลŸe yarar; รงรผnkรผ bir dependency'yi kendi รถzel ayarlarฤฑnฤฑzla override etmek รงok kolaydฤฑr. + +### Config dosyasฤฑ { #the-config-file } + +Bir รถnceki รถrnekten devam edersek, `config.py` dosyanฤฑz ลŸรถyle gรถrรผnebilir: + +{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} + +Dikkat edin, artฤฑk default bir instance `settings = Settings()` oluลŸturmuyoruz. + +### Ana uygulama dosyasฤฑ { #the-main-app-file } + +ลžimdi, yeni bir `config.Settings()` dรถndรผren bir dependency oluลŸturuyoruz. + +{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} + +/// tip | ฤฐpucu + +`@lru_cache` konusunu birazdan ele alacaฤŸฤฑz. + +ลžimdilik `get_settings()`'in normal bir fonksiyon olduฤŸunu varsayabilirsiniz. + +/// + +Sonra bunu dependency olarak *path operation function*'dan talep edebilir ve ihtiyaรง duyduฤŸumuz her yerde kullanabiliriz. + +{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} + +### Ayarlar ve test { #settings-and-testing } + +Ardฤฑndan, `get_settings` iรงin bir dependency override oluลŸturarak test sฤฑrasฤฑnda farklฤฑ bir settings nesnesi saฤŸlamak รงok kolay olur: + +{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} + +Dependency override iรงinde, yeni `Settings` nesnesini oluลŸtururken `admin_email` iรงin yeni bir deฤŸer ayarlarฤฑz ve sonra bu yeni nesneyi dรถndรผrรผrรผz. + +Sonrasฤฑnda bunun kullanฤฑldฤฑฤŸฤฑnฤฑ test edebiliriz. + +## `.env` dosyasฤฑ okuma { #reading-a-env-file } + +ร‡ok sayฤฑda ayarฤฑnฤฑz varsa ve bunlar farklฤฑ ortamlarda sฤฑk sฤฑk deฤŸiลŸiyorsa, bunlarฤฑ bir dosyaya koyup, sanki environment variable'mฤฑลŸ gibi o dosyadan okumak faydalฤฑ olabilir. + +Bu yaklaลŸฤฑm oldukรงa yaygฤฑndฤฑr ve bir adฤฑ vardฤฑr: Bu environment variable'lar genellikle `.env` adlฤฑ bir dosyaya konur ve bu dosyaya "dotenv" denir. + +/// tip | ฤฐpucu + +Nokta (`.`) ile baลŸlayan dosyalar, Linux ve macOS gibi Unix-benzeri sistemlerde gizli dosyadฤฑr. + +Ancak dotenv dosyasฤฑnฤฑn mutlaka bu dosya adฤฑna sahip olmasฤฑ gerekmez. + +/// + +Pydantic, harici bir kรผtรผphane kullanarak bu tรผr dosyalardan okuma desteฤŸine sahiptir. Daha fazlasฤฑ iรงin: Pydantic Settings: Dotenv (.env) support. + +/// tip | ฤฐpucu + +Bunun รงalฤฑลŸmasฤฑ iรงin `pip install python-dotenv` yapmanฤฑz gerekir. + +/// + +### `.env` dosyasฤฑ { #the-env-file } + +ลžรถyle bir `.env` dosyanฤฑz olabilir: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### Ayarlarฤฑ `.env`'den okuyun { #read-settings-from-env } + +Ardฤฑndan `config.py` dosyanฤฑzฤฑ ลŸรถyle gรผncelleyin: + +{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} + +/// tip | ฤฐpucu + +`model_config` attribute'u yalnฤฑzca Pydantic konfigรผrasyonu iรงindir. Daha fazlasฤฑ iรงin Pydantic: Concepts: Configuration. + +/// + +Burada, Pydantic `Settings` sฤฑnฤฑfฤฑnฤฑzฤฑn iรงinde `env_file` konfigรผrasyonunu tanฤฑmlar ve deฤŸer olarak kullanmak istediฤŸimiz dotenv dosyasฤฑnฤฑn dosya adฤฑnฤฑ veririz. + +### `lru_cache` ile `Settings`'i yalnฤฑzca bir kez oluลŸturma { #creating-the-settings-only-once-with-lru-cache } + +Diskten dosya okumak normalde maliyetli (yavaลŸ) bir iลŸlemdir; bu yรผzden muhtemelen bunu yalnฤฑzca bir kez yapฤฑp aynฤฑ settings nesnesini tekrar kullanmak istersiniz. Her request iรงin yeniden okumak istemezsiniz. + +Ancak her seferinde ลŸunu yaptฤฑฤŸฤฑmฤฑzda: + +```Python +Settings() +``` + +yeni bir `Settings` nesnesi oluลŸturulur ve oluลŸturulurken `.env` dosyasฤฑnฤฑ yeniden okur. + +Dependency fonksiyonu sadece ลŸรถyle olsaydฤฑ: + +```Python +def get_settings(): + return Settings() +``` + +bu nesneyi her request iรงin oluลŸtururduk ve `.env` dosyasฤฑnฤฑ her request'te okurduk. โš ๏ธ + +Fakat en รผstte `@lru_cache` decorator'รผnรผ kullandฤฑฤŸฤฑmฤฑz iรงin `Settings` nesnesi yalnฤฑzca bir kez, ilk รงaฤŸrฤฑldฤฑฤŸฤฑ anda oluลŸturulur. โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} + +Sonraki request'lerde dependency'ler iรงinden `get_settings()` รงaฤŸrฤฑldฤฑฤŸฤฑnda, `get_settings()`'in iรง kodu tekrar รงalฤฑลŸtฤฑrฤฑlฤฑp yeni bir `Settings` nesnesi yaratฤฑlmak yerine, ilk รงaฤŸrฤฑda dรถndรผrรผlen aynฤฑ nesne tekrar tekrar dรถndรผrรผlรผr. + +#### `lru_cache` Teknik Detaylarฤฑ { #lru-cache-technical-details } + +`@lru_cache`, decorator olarak uygulandฤฑฤŸฤฑ fonksiyonu, her seferinde tekrar hesaplamak yerine ilk seferde dรถndรผrdรผฤŸรผ deฤŸeri dรถndรผrecek ลŸekilde deฤŸiลŸtirir; yani fonksiyon kodunu her รงaฤŸrฤฑda yeniden รงalฤฑลŸtฤฑrmaz. + +Bu nedenle altฤฑndaki fonksiyon, argรผman kombinasyonlarฤฑnฤฑn her biri iรงin bir kez รงalฤฑลŸtฤฑrฤฑlฤฑr. Sonra bu argรผman kombinasyonlarฤฑnฤฑn her biri iรงin dรถndรผrรผlmรผลŸ deฤŸerler, fonksiyon aynฤฑ argรผman kombinasyonuyla รงaฤŸrฤฑldฤฑkรงa tekrar tekrar kullanฤฑlฤฑr. + +ร–rneฤŸin, ลŸรถyle bir fonksiyonunuz varsa: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +programฤฑnฤฑz ลŸu ลŸekilde รงalฤฑลŸabilir: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +Bizim `get_settings()` dependency'miz รถzelinde ise fonksiyon hiรง argรผman almaz; dolayฤฑsฤฑyla her zaman aynฤฑ deฤŸeri dรถndรผrรผr. + +Bu ลŸekilde, neredeyse global bir deฤŸiลŸken gibi davranฤฑr. Ancak bir dependency fonksiyonu kullandฤฑฤŸฤฑ iรงin testte kolayca override edebiliriz. + +`@lru_cache`, Python standart kรผtรผphanesinin bir parรงasฤฑ olan `functools` iรงindedir. Daha fazla bilgi iรงin: Python docs for `@lru_cache`. + +## ร–zet { #recap } + +Uygulamanฤฑzฤฑn ayarlarฤฑnฤฑ veya konfigรผrasyonlarฤฑnฤฑ yรถnetmek iรงin, Pydantic model'lerinin tรผm gรผcรผyle birlikte Pydantic Settings'i kullanabilirsiniz. + +* Dependency kullanarak test etmeyi basitleลŸtirebilirsiniz. +* Bununla `.env` dosyalarฤฑnฤฑ kullanabilirsiniz. +* `@lru_cache` kullanmak, dotenv dosyasฤฑnฤฑ her request iรงin tekrar tekrar okumayฤฑ engellerken, test sฤฑrasฤฑnda override etmenize de izin verir. diff --git a/docs/tr/docs/advanced/sub-applications.md b/docs/tr/docs/advanced/sub-applications.md new file mode 100644 index 0000000000..4773ba2004 --- /dev/null +++ b/docs/tr/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Alt Uygulamalar - Mount ฤฐลŸlemi { #sub-applications-mounts } + +Kendi baฤŸฤฑmsฤฑz OpenAPI ลŸemalarฤฑ ve kendi dokรผmantasyon arayรผzleri olan iki baฤŸฤฑmsฤฑz FastAPI uygulamasฤฑna ihtiyacฤฑnฤฑz varsa, bir ana uygulama oluลŸturup bir (veya daha fazla) alt uygulamayฤฑ "mount" edebilirsiniz. + +## Bir **FastAPI** uygulamasฤฑnฤฑ mount etmek { #mounting-a-fastapi-application } + +"Mount" etmek, belirli bir path altฤฑnda tamamen "baฤŸฤฑmsฤฑz" bir uygulamayฤฑ eklemek anlamฤฑna gelir. Ardฤฑndan o pathโ€™in altฤฑndaki her ลŸeyi, alt uygulamada tanฤฑmlanan _path operation_โ€™lar ile o alt uygulama yรถnetir. + +### รœst seviye uygulama { #top-level-application } + +ร–nce ana, รผst seviye **FastAPI** uygulamasฤฑnฤฑ ve onun *path operation*โ€™larฤฑnฤฑ oluลŸturun: + +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} + +### Alt uygulama { #sub-application } + +Sonra alt uygulamanฤฑzฤฑ ve onun *path operation*โ€™larฤฑnฤฑ oluลŸturun. + +Bu alt uygulama da standart bir FastAPI uygulamasฤฑdฤฑr; ancak "mount" edilecek olan budur: + +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} + +### Alt uygulamayฤฑ mount edin { #mount-the-sub-application } + +รœst seviye uygulamanฤฑzda (`app`), alt uygulama `subapi`โ€™yi mount edin. + +Bu รถrnekte `/subapi` pathโ€™ine mount edilecektir: + +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} + +### Otomatik API dokรผmanlarฤฑnฤฑ kontrol edin { #check-the-automatic-api-docs } + +ลžimdi dosyanฤฑzla birlikte `fastapi` komutunu รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ardฤฑndan http://127.0.0.1:8000/docs adresinden dokรผmanlarฤฑ aรงฤฑn. + +Ana uygulama iรงin otomatik API dokรผmanlarฤฑnฤฑ gรถreceksiniz; yalnฤฑzca onun kendi _path operation_โ€™larฤฑnฤฑ iรงerir: + + + +Sonra alt uygulamanฤฑn dokรผmanlarฤฑnฤฑ http://127.0.0.1:8000/subapi/docs adresinden aรงฤฑn. + +Alt uygulama iรงin otomatik API dokรผmanlarฤฑnฤฑ gรถreceksiniz; yalnฤฑzca onun kendi _path operation_โ€™larฤฑnฤฑ iรงerir ve hepsi doฤŸru alt-path รถneki `/subapi` altฤฑnda yer alฤฑr: + + + +ฤฐki arayรผzden herhangi biriyle etkileลŸime girmeyi denerseniz doฤŸru ลŸekilde รงalฤฑลŸtฤฑklarฤฑnฤฑ gรถrรผrsรผnรผz; รงรผnkรผ tarayฤฑcฤฑ her bir uygulama ya da alt uygulama ile ayrฤฑ ayrฤฑ iletiลŸim kurabilir. + +### Teknik Detaylar: `root_path` { #technical-details-root-path } + +Yukarฤฑda anlatฤฑldฤฑฤŸฤฑ gibi bir alt uygulamayฤฑ mount ettiฤŸinizde FastAPI, ASGI spesifikasyonundaki `root_path` adlฤฑ bir mekanizmayฤฑ kullanarak alt uygulamaya mount pathโ€™ini iletmeyi otomatik olarak yรถnetir. + +Bu sayede alt uygulama, dokรผmantasyon arayรผzรผ iรงin o path รถnekini kullanmasฤฑ gerektiฤŸini bilir. + +Ayrฤฑca alt uygulamanฤฑn kendi mount edilmiลŸ alt uygulamalarฤฑ da olabilir; FastAPI tรผm bu `root_path`โ€™leri otomatik olarak yรถnettiฤŸi iรงin her ลŸey doฤŸru ลŸekilde รงalฤฑลŸฤฑr. + +`root_path` hakkฤฑnda daha fazlasฤฑnฤฑ ve bunu aรงฤฑkรงa nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bรถlรผmรผnde รถฤŸreneceksiniz. diff --git a/docs/tr/docs/advanced/templates.md b/docs/tr/docs/advanced/templates.md new file mode 100644 index 0000000000..b91e0a2a84 --- /dev/null +++ b/docs/tr/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# ลžablonlar { #templates } + +**FastAPI** ile istediฤŸiniz herhangi bir template engine'i kullanabilirsiniz. + +Yaygฤฑn bir tercih, Flask ve diฤŸer araรงlarฤฑn da kullandฤฑฤŸฤฑ Jinja2'dir. + +Bunu kolayca yapฤฑlandฤฑrmak iรงin, doฤŸrudan **FastAPI** uygulamanฤฑzda kullanabileceฤŸiniz yardฤฑmcฤฑ araรงlar vardฤฑr (Starlette tarafฤฑndan saฤŸlanฤฑr). + +## BaฤŸฤฑmlฤฑlฤฑklarฤฑ Yรผkleme { #install-dependencies } + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, etkinleลŸtirdiฤŸinizden ve `jinja2`'yi yรผklediฤŸinizden emin olun: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## `Jinja2Templates` Kullanฤฑmฤฑ { #using-jinja2templates } + +* `Jinja2Templates`'ฤฑ iรงe aktarฤฑn. +* Daha sonra tekrar kullanabileceฤŸiniz bir `templates` nesnesi oluลŸturun. +* Template dรถndรผrecek *path operation* iรงinde bir `Request` parametresi tanฤฑmlayฤฑn. +* OluลŸturduฤŸunuz `templates` nesnesini kullanarak bir `TemplateResponse` render edip dรถndรผrรผn; template'in adฤฑnฤฑ, request nesnesini ve Jinja2 template'i iรงinde kullanฤฑlacak anahtar-deฤŸer รงiftlerini iรงeren bir "context" sรถzlรผฤŸรผnรผ (dict) iletin. + +{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} + +/// note | Not + +FastAPI 0.108.0 ve Starlette 0.29.0 รถncesinde, ilk parametre `name` idi. + +Ayrฤฑca, daha รถnceki sรผrรผmlerde `request` nesnesi, Jinja2 iรงin context iรงindeki anahtar-deฤŸer รงiftlerinin bir parรงasฤฑ olarak geรงirilirdi. + +/// + +/// tip | ฤฐpucu + +`response_class=HTMLResponse` olarak tanฤฑmlarsanฤฑz dokรผman arayรผzรผ (docs UI) response'un HTML olacaฤŸฤฑnฤฑ anlayabilir. + +/// + +/// note | Teknik Detaylar + +`from starlette.templating import Jinja2Templates` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici iรงin kolaylฤฑk olmasฤฑ adฤฑna `starlette.templating` iรงeriฤŸini `fastapi.templating` olarak da sunar. Ancak mevcut response'larฤฑn รงoฤŸu doฤŸrudan Starlette'ten gelir. `Request` ve `StaticFiles` iรงin de aynฤฑ durum geรงerlidir. + +/// + +## Template Yazma { #writing-templates } + +Ardฤฑndan รถrneฤŸin `templates/item.html` konumunda bir template yazabilirsiniz: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Template Context DeฤŸerleri { #template-context-values } + +ลžu HTML iรงeriฤŸinde: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...gรถsterilecek olan `id`, sizin "context" olarak ilettiฤŸiniz `dict` iรงinden alฤฑnฤฑr: + +```Python +{"id": id} +``` + +ร–rneฤŸin ID deฤŸeri `42` ise, ลŸu ลŸekilde render edilir: + +```html +Item ID: 42 +``` + +### Template `url_for` Argรผmanlarฤฑ { #template-url-for-arguments } + +Template iรงinde `url_for()` da kullanabilirsiniz; argรผman olarak, *path operation function*'ฤฑnฤฑzฤฑn kullandฤฑฤŸฤฑ argรผmanlarฤฑn aynฤฑsฤฑnฤฑ alฤฑr. + +Dolayฤฑsฤฑyla ลŸu bรถlรผm: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...*path operation function* olan `read_item(id=id)` tarafฤฑndan handle edilecek URL'nin aynฤฑsฤฑna bir link รผretir. + +ร–rneฤŸin ID deฤŸeri `42` ise, ลŸu ลŸekilde render edilir: + +```html + +``` + +## Template'ler ve statik dosyalar { #templates-and-static-files } + +Template iรงinde `url_for()` kullanabilir ve รถrneฤŸin `name="static"` ile mount ettiฤŸiniz `StaticFiles` ile birlikte kullanabilirsiniz. + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +Bu รถrnekte, ลŸu ลŸekilde `static/styles.css` konumundaki bir CSS dosyasฤฑna link verir: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +Ve `StaticFiles` kullandฤฑฤŸฤฑnฤฑz iรงin, bu CSS dosyasฤฑ **FastAPI** uygulamanฤฑz tarafฤฑndan `/static/styles.css` URL'sinde otomatik olarak servis edilir. + +## Daha fazla detay { #more-details } + +Template'leri nasฤฑl test edeceฤŸiniz dahil daha fazla detay iรงin Starlette'in template dokรผmantasyonuna bakฤฑn. diff --git a/docs/tr/docs/advanced/testing-dependencies.md b/docs/tr/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000..3cad637762 --- /dev/null +++ b/docs/tr/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# Override Kullanarak Dependency'leri Test Etme { #testing-dependencies-with-overrides } + +## Test Sฤฑrasฤฑnda Dependency Override Etme { #overriding-dependencies-during-testing } + +Test yazarken bazฤฑ durumlarda bir dependency'yi override etmek isteyebilirsiniz. + +Orijinal dependency'nin (ve varsa tรผm alt dependency'lerinin) รงalฤฑลŸmasฤฑnฤฑ istemezsiniz. + +Bunun yerine, yalnฤฑzca testler sฤฑrasฤฑnda (hatta belki sadece belirli bazฤฑ testlerde) kullanฤฑlacak farklฤฑ bir dependency saฤŸlarsฤฑnฤฑz; bรถylece orijinal dependency'nin รผrettiฤŸi deฤŸerin kullanฤฑldฤฑฤŸฤฑ yerde, test iรงin รผretilen deฤŸeri kullanabilirsiniz. + +### Kullanฤฑm Senaryolarฤฑ: Harici Servis { #use-cases-external-service } + +ร–rneฤŸin, รงaฤŸฤฑrmanฤฑz gereken harici bir authentication provider'ฤฑnฤฑz olabilir. + +Ona bir token gรถnderirsiniz ve o da authenticated bir user dรถndรผrรผr. + +Bu provider request baลŸฤฑna รผcret alฤฑyor olabilir ve onu รงaฤŸฤฑrmak, testlerde sabit bir mock user kullanmaya kฤฑyasla daha fazla zaman alabilir. + +Muhtemelen harici provider'ฤฑ bir kez test etmek istersiniz; ancak รงalฤฑลŸan her testte onu รงaฤŸฤฑrmanฤฑz ลŸart deฤŸildir. + +Bu durumda, o provider'ฤฑ รงaฤŸฤฑran dependency'yi override edebilir ve yalnฤฑzca testleriniz iรงin mock user dรถndรผren รถzel bir dependency kullanabilirsiniz. + +### `app.dependency_overrides` Attribute'รผnรผ Kullanฤฑn { #use-the-app-dependency-overrides-attribute } + +Bu tรผr durumlar iรงin **FastAPI** uygulamanฤฑzda `app.dependency_overrides` adฤฑnda bir attribute bulunur; bu basit bir `dict`'tir. + +Test iรงin bir dependency'yi override etmek istediฤŸinizde, key olarak orijinal dependency'yi (bir function), value olarak da override edecek dependency'nizi (baลŸka bir function) verirsiniz. + +Bรถylece **FastAPI**, orijinal dependency yerine bu override'ฤฑ รงaฤŸฤฑrฤฑr. + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | ฤฐpucu + +**FastAPI** uygulamanฤฑzฤฑn herhangi bir yerinde kullanฤฑlan bir dependency iรงin override tanฤฑmlayabilirsiniz. + +Orijinal dependency bir *path operation function* iรงinde, bir *path operation decorator* iรงinde (return value kullanmadฤฑฤŸฤฑnฤฑz durumlarda), bir `.include_router()` รงaฤŸrฤฑsฤฑnda, vb. kullanฤฑlฤฑyor olabilir. + +FastAPI yine de onu override edebilir. + +/// + +Sonrasฤฑnda override'larฤฑnฤฑzฤฑ (yani kaldฤฑrฤฑp sฤฑfฤฑrlamayฤฑ) `app.dependency_overrides` deฤŸerini boลŸ bir `dict` yaparak gerรงekleลŸtirebilirsiniz: + +```Python +app.dependency_overrides = {} +``` + +/// tip | ฤฐpucu + +Bir dependency'yi yalnฤฑzca bazฤฑ testler sฤฑrasฤฑnda override etmek istiyorsanฤฑz, override'ฤฑ testin baลŸฤฑnda (test function'ฤฑnฤฑn iรงinde) ayarlayฤฑp testin sonunda (yine test function'ฤฑnฤฑn sonunda) sฤฑfฤฑrlayabilirsiniz. + +/// diff --git a/docs/tr/docs/advanced/testing-events.md b/docs/tr/docs/advanced/testing-events.md new file mode 100644 index 0000000000..f12aef9888 --- /dev/null +++ b/docs/tr/docs/advanced/testing-events.md @@ -0,0 +1,12 @@ +# Event'leri Test Etme: lifespan ve startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +Test'lerinizde `lifespan`'ฤฑn รงalฤฑลŸmasฤฑ gerektiฤŸinde, `TestClient`'ฤฑ bir `with` ifadesiyle kullanabilirsiniz: + +{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} + + +Bu konuda daha fazla ayrฤฑntฤฑyฤฑ resmi Starlette dokรผmantasyon sitesindeki ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) bรถlรผmรผnde okuyabilirsiniz. + +Kullanฤฑmdan kaldฤฑrฤฑlmฤฑลŸ `startup` ve `shutdown` event'leri iรงin ise `TestClient`'ฤฑ aลŸaฤŸฤฑdaki gibi kullanabilirsiniz: + +{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} diff --git a/docs/tr/docs/advanced/using-request-directly.md b/docs/tr/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000..3efdafb032 --- /dev/null +++ b/docs/tr/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Request'i DoฤŸrudan Kullanmak { #using-the-request-directly } + +ลžu ana kadar, ihtiyacฤฑnฤฑz olan request parรงalarฤฑnฤฑ tipleriyle birlikte tanฤฑmlฤฑyordunuz. + +Verileri ลŸuradan alarak: + +* path'ten parameter olarak. +* Header'lardan. +* Cookie'lerden. +* vb. + +Bunu yaptฤฑฤŸฤฑnฤฑzda **FastAPI**, bu verileri doฤŸrular (validate eder), dรถnรผลŸtรผrรผr ve API'niz iรงin dokรผmantasyonu otomatik olarak รผretir. + +Ancak bazฤฑ durumlarda `Request` nesnesine doฤŸrudan eriลŸmeniz gerekebilir. + +## `Request` nesnesi hakkฤฑnda detaylar { #details-about-the-request-object } + +**FastAPI** aslฤฑnda altta **Starlette** รงalฤฑลŸtฤฑrฤฑr ve รผstรผne รงeลŸitli araรงlardan oluลŸan bir katman ekler. Bu yรผzden gerektiฤŸinde Starlette'in `Request` nesnesini doฤŸrudan kullanabilirsiniz. + +Bu ayrฤฑca ลŸu anlama gelir: `Request` nesnesinden veriyi doฤŸrudan alฤฑrsanฤฑz (รถrneฤŸin body'yi okursanฤฑz) FastAPI bu veriyi doฤŸrulamaz, dรถnรผลŸtรผrmez veya dokรผmante etmez (otomatik API arayรผzรผ iรงin OpenAPI ile). + +Buna raฤŸmen normal ลŸekilde tanฤฑmladฤฑฤŸฤฑnฤฑz diฤŸer herhangi bir parameter (รถrneฤŸin Pydantic model ile body) yine doฤŸrulanฤฑr, dรถnรผลŸtรผrรผlรผr, annotate edilir, vb. + +Ama bazฤฑ รถzel durumlarda `Request` nesnesini almak faydalฤฑdฤฑr. + +## `Request` nesnesini doฤŸrudan kullanฤฑn { #use-the-request-object-directly } + +*Path operation function* iรงinde client'ฤฑn IP adresini/host'unu almak istediฤŸinizi dรผลŸรผnelim. + +Bunun iรงin request'e doฤŸrudan eriลŸmeniz gerekir. + +{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} + +Tipi `Request` olan bir *path operation function* parameter'ฤฑ tanฤฑmladฤฑฤŸฤฑnฤฑzda **FastAPI**, o parameter'a `Request` nesnesini geรงmesi gerektiฤŸini anlar. + +/// tip | ฤฐpucu + +Bu รถrnekte, request parameter'ฤฑnฤฑn yanฤฑnda bir path parameter'ฤฑ da tanฤฑmladฤฑฤŸฤฑmฤฑza dikkat edin. + +Dolayฤฑsฤฑyla path parameter'ฤฑ รงฤฑkarฤฑlฤฑr, doฤŸrulanฤฑr, belirtilen tipe dรถnรผลŸtรผrรผlรผr ve OpenAPI ile annotate edilir. + +Aynฤฑ ลŸekilde, diฤŸer parameter'larฤฑ normal biรงimde tanฤฑmlamaya devam edip buna ek olarak `Request` de alabilirsiniz. + +/// + +## `Request` dokรผmantasyonu { #request-documentation } + +Resmi Starlette dokรผmantasyon sitesinde `Request` nesnesiyle ilgili daha fazla detayฤฑ okuyabilirsiniz. + +/// note | Teknik Detaylar + +`from starlette.requests import Request` de kullanabilirsiniz. + +**FastAPI** bunu size (geliลŸtiriciye) kolaylฤฑk olsun diye doฤŸrudan sunar. Ancak kendisi doฤŸrudan Starlette'ten gelir. + +/// diff --git a/docs/tr/docs/advanced/websockets.md b/docs/tr/docs/advanced/websockets.md new file mode 100644 index 0000000000..775d7cc25f --- /dev/null +++ b/docs/tr/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +**FastAPI** ile WebSockets kullanabilirsiniz. + +## `websockets` Kurulumu { #install-websockets } + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktive ettiฤŸinizden ve `websockets`'i ("WebSocket" protokolรผnรผ kullanmayฤฑ kolaylaลŸtฤฑran bir Python kรผtรผphanesi) kurduฤŸunuzdan emin olun: + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets client { #websockets-client } + +### Production'da { #in-production } + +Production sisteminizde muhtemelen React, Vue.js veya Angular gibi modern bir framework ile oluลŸturulmuลŸ bir frontend vardฤฑr. + +WebSockets kullanarak backend'inizle iletiลŸim kurmak iรงin de bรผyรผk ihtimalle frontend'inizin saฤŸladฤฑฤŸฤฑ yardฤฑmcฤฑ araรงlarฤฑ kullanฤฑrsฤฑnฤฑz. + +Ya da native kod ile doฤŸrudan WebSocket backend'inizle iletiลŸim kuran native bir mobil uygulamanฤฑz olabilir. + +Veya WebSocket endpoint'i ile iletiลŸim kurmak iรงin baลŸka herhangi bir yรถnteminizi de kullanฤฑyor olabilirsiniz. + +--- + +Ancak bu รถrnek iรงin, tamamฤฑ uzun bir string iรงinde olacak ลŸekilde biraz JavaScript iรงeren รงok basit bir HTML dokรผmanฤฑ kullanacaฤŸฤฑz. + +Elbette bu optimal deฤŸil ve production iรงin kullanmazsฤฑnฤฑz. + +Production'da yukarฤฑdaki seรงeneklerden birini kullanฤฑrsฤฑnฤฑz. + +Ama WebSockets'in server tarafฤฑna odaklanmak ve รงalฤฑลŸan bir รถrnek gรถrmek iรงin en basit yol bu: + +{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} + +## Bir `websocket` OluลŸturun { #create-a-websocket } + +**FastAPI** uygulamanฤฑzda bir `websocket` oluลŸturun: + +{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} + +/// note | Teknik Detaylar + +`from starlette.websockets import WebSocket` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak iลŸinizi kolaylaลŸtฤฑrmak iรงin aynฤฑ `WebSocket`'i doฤŸrudan saฤŸlar. Ancak aslฤฑnda doฤŸrudan Starlette'ten gelir. + +/// + +## Mesajlarฤฑ `await` Edin ve Mesaj Gรถnderin { #await-for-messages-and-send-messages } + +WebSocket route'unuzda mesajlarฤฑ `await` edebilir ve mesaj gรถnderebilirsiniz. + +{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} + +Binary, text ve JSON verisi alฤฑp gรถnderebilirsiniz. + +## Deneyin { #try-it } + +Dosyanฤฑzฤฑn adฤฑ `main.py` ise uygulamanฤฑzฤฑ ลŸu ลŸekilde รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000 adresini aรงฤฑn. + +ลžuna benzer basit bir sayfa gรถreceksiniz: + + + +Input kutusuna mesaj yazฤฑp gรถnderebilirsiniz: + + + +Ve WebSockets kullanan **FastAPI** uygulamanฤฑz yanฤฑt dรถndรผrecektir: + + + +Birรงok mesaj gรถnderebilir (ve alabilirsiniz): + + + +Ve hepsinde aynฤฑ WebSocket baฤŸlantฤฑsฤฑ kullanฤฑlacaktฤฑr. + +## `Depends` ve DiฤŸerlerini Kullanma { #using-depends-and-others } + +WebSocket endpoint'lerinde `fastapi` iรงinden import edip ลŸunlarฤฑ kullanabilirsiniz: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +DiฤŸer FastAPI endpoint'leri/*path operations* ile aynฤฑ ลŸekilde รงalฤฑลŸฤฑrlar: + +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} + +/// info | Bilgi + +Bu bir WebSocket olduฤŸu iรงin `HTTPException` raise etmek pek anlamlฤฑ deฤŸildir; bunun yerine `WebSocketException` raise ederiz. + +Spesifikasyonda tanฤฑmlanan geรงerli kodlar arasฤฑndan bir kapatma kodu kullanabilirsiniz. + +/// + +### Dependency'lerle WebSockets'i Deneyin { #try-the-websockets-with-dependencies } + +Dosyanฤฑzฤฑn adฤฑ `main.py` ise uygulamanฤฑzฤฑ ลŸu ลŸekilde รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000 adresini aรงฤฑn. + +Burada ลŸunlarฤฑ ayarlayabilirsiniz: + +* path'te kullanฤฑlan "Item ID". +* query parametresi olarak kullanฤฑlan "Token". + +/// tip | ฤฐpucu + +query'deki `token` deฤŸerinin bir dependency tarafฤฑndan ele alฤฑnacaฤŸฤฑna dikkat edin. + +/// + +Bununla WebSocket'e baฤŸlanabilir, ardฤฑndan mesaj gรถnderip alabilirsiniz: + + + +## BaฤŸlantฤฑ Kopmalarฤฑnฤฑ ve Birden Fazla Client'ฤฑ Yรถnetme { #handling-disconnections-and-multiple-clients } + +Bir WebSocket baฤŸlantฤฑsฤฑ kapandฤฑฤŸฤฑnda, `await websocket.receive_text()` bir `WebSocketDisconnect` exception'ฤฑ raise eder; ardฤฑndan bunu bu รถrnekteki gibi yakalayฤฑp (catch) yรถnetebilirsiniz. + +{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} + +Denemek iรงin: + +* Uygulamayฤฑ birden fazla tarayฤฑcฤฑ sekmesiyle aรงฤฑn. +* Bu sekmelerden mesaj yazฤฑn. +* Sonra sekmelerden birini kapatฤฑn. + +Bu, `WebSocketDisconnect` exception'ฤฑnฤฑ raise eder ve diฤŸer tรผm client'lar ลŸuna benzer bir mesaj alฤฑr: + +``` +Client #1596980209979 left the chat +``` + +/// tip | ฤฐpucu + +Yukarฤฑdaki uygulama, birden fazla WebSocket baฤŸlantฤฑsฤฑna mesajlarฤฑ nasฤฑl yรถnetip broadcast edeceฤŸinizi gรถstermek iรงin minimal ve basit bir รถrnektir. + +Ancak her ลŸey memory'de, tek bir list iรงinde yรถnetildiฤŸi iรงin yalnฤฑzca process รงalฤฑลŸtฤฑฤŸฤฑ sรผrece ve yalnฤฑzca tek bir process ile รงalฤฑลŸacaktฤฑr. + +FastAPI ile kolay entegre olan ama Redis, PostgreSQL vb. tarafฤฑndan desteklenen daha saฤŸlam bir ลŸeye ihtiyacฤฑnฤฑz varsa encode/broadcaster'a gรถz atฤฑn. + +/// + +## Daha Fazla Bilgi { #more-info } + +Seรงenekler hakkฤฑnda daha fazlasฤฑnฤฑ รถฤŸrenmek iรงin Starlette dokรผmantasyonunda ลŸunlara bakฤฑn: + +* `WebSocket` class'ฤฑ. +* Class tabanlฤฑ WebSocket yรถnetimi. diff --git a/docs/tr/docs/deployment/concepts.md b/docs/tr/docs/deployment/concepts.md new file mode 100644 index 0000000000..d0f5681469 --- /dev/null +++ b/docs/tr/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Deployment Kavramlarฤฑ { #deployments-concepts } + +Bir **FastAPI** uygulamasฤฑnฤฑ (hatta genel olarak herhangi bir web API'yi) deploy ederken, muhtemelen รถnemseyeceฤŸiniz bazฤฑ kavramlar vardฤฑr. Bu kavramlarฤฑ kullanarak, **uygulamanฤฑzฤฑ deploy etmek** iรงin **en uygun** yรถntemi bulabilirsiniz. + +ร–nemli kavramlardan bazฤฑlarฤฑ ลŸunlardฤฑr: + +* Gรผvenlik - HTTPS +* Startup'ta รงalฤฑลŸtฤฑrma +* Yeniden baลŸlatmalar +* Replikasyon (รงalฤฑลŸan process sayฤฑsฤฑ) +* Bellek +* BaลŸlatmadan รถnceki adฤฑmlar + +Bunlarฤฑn **deployment**'larฤฑ nasฤฑl etkilediฤŸine bakalฤฑm. + +Nihai hedef, **API client**'larฤฑnฤฑza **gรผvenli** bir ลŸekilde hizmet verebilmek, **kesintileri** รถnlemek ve **hesaplama kaynaklarฤฑnฤฑ** (รถr. uzak server'lar/sanal makineler) olabildiฤŸince verimli kullanmaktฤฑr. + +Burada bu **kavramlar** hakkฤฑnda biraz daha bilgi vereceฤŸim. Bรถylece, รงok farklฤฑ ortamlardaโ€”hatta bugรผn var olmayan **gelecekteki** ortamlarda bileโ€”API'nizi nasฤฑl deploy edeceฤŸinize karar verirken ihtiyaรง duyacaฤŸฤฑnฤฑz **sezgiyi** kazanmฤฑลŸ olursunuz. + +Bu kavramlarฤฑ dikkate alarak, **kendi API**'leriniz iรงin en iyi deployment yaklaลŸฤฑmฤฑnฤฑ **deฤŸerlendirebilir ve tasarlayabilirsiniz**. + +Sonraki bรถlรผmlerde, FastAPI uygulamalarฤฑnฤฑ deploy etmek iรงin daha **somut tarifler** (recipes) paylaลŸacaฤŸฤฑm. + +Ama ลŸimdilik, bu รถnemli **kavramsal fikirleri** inceleyelim. Bu kavramlar diฤŸer tรผm web API tรผrleri iรงin de geรงerlidir. + +## Gรผvenlik - HTTPS { #security-https } + +[HTTPS hakkฤฑndaki รถnceki bรถlรผmde](https.md){.internal-link target=_blank} HTTPS'in API'niz iรงin nasฤฑl ลŸifreleme saฤŸladฤฑฤŸฤฑnฤฑ รถฤŸrenmiลŸtik. + +Ayrฤฑca HTTPS'in genellikle uygulama server'ฤฑnฤฑzฤฑn **dฤฑลŸฤฑnda** yer alan bir bileลŸen tarafฤฑndan saฤŸlandฤฑฤŸฤฑnฤฑ, yani bir **TLS Termination Proxy** ile yapฤฑldฤฑฤŸฤฑnฤฑ da gรถrmรผลŸtรผk. + +Ve **HTTPS sertifikalarฤฑnฤฑ yenilemekten** sorumlu bir ลŸey olmalฤฑdฤฑr; bu aynฤฑ bileลŸen olabileceฤŸi gibi farklฤฑ bir bileลŸen de olabilir. + +### HTTPS iรงin ร–rnek Araรงlar { #example-tools-for-https } + +TLS Termination Proxy olarak kullanabileceฤŸiniz bazฤฑ araรงlar: + +* Traefik + * Sertifika yenilemelerini otomatik yรถnetir +* Caddy + * Sertifika yenilemelerini otomatik yรถnetir +* Nginx + * Sertifika yenilemeleri iรงin Certbot gibi harici bir bileลŸenle +* HAProxy + * Sertifika yenilemeleri iรงin Certbot gibi harici bir bileลŸenle +* Nginx gibi bir Ingress Controller ile Kubernetes + * Sertifika yenilemeleri iรงin cert-manager gibi harici bir bileลŸenle +* Bir cloud provider tarafฤฑndan servislerinin parรงasฤฑ olarak iรงeride yรถnetilmesi (aลŸaฤŸฤฑyฤฑ okuyun) + +Bir diฤŸer seรงenek de, HTTPS kurulumunu da dahil olmak รผzere iลŸin daha bรผyรผk kฤฑsmฤฑnฤฑ yapan bir **cloud service** kullanmaktฤฑr. Bunun bazฤฑ kฤฑsฤฑtlarฤฑ olabilir veya daha pahalฤฑ olabilir vb. Ancak bu durumda TLS Termination Proxy'yi kendiniz kurmak zorunda kalmazsฤฑnฤฑz. + +Sonraki bรถlรผmlerde bazฤฑ somut รถrnekler gรถstereceฤŸim. + +--- + +Sonraki kavramlar, gerรงek API'nizi รงalฤฑลŸtฤฑran programla (รถr. Uvicorn) ilgilidir. + +## Program ve Process { #program-and-process } + +ร‡alฤฑลŸan "**process**" hakkฤฑnda รงok konuลŸacaฤŸฤฑz. Bu yรผzden ne anlama geldiฤŸini ve "**program**" kelimesinden farkฤฑnฤฑn ne olduฤŸunu netleลŸtirmek faydalฤฑ. + +### Program Nedir { #what-is-a-program } + +**Program** kelimesi gรผnlรผk kullanฤฑmda birรงok ลŸeyi anlatmak iรงin kullanฤฑlฤฑr: + +* YazdฤฑฤŸฤฑnฤฑz **code**, yani **Python dosyalarฤฑ**. +* ฤฐลŸletim sistemi tarafฤฑndan **รงalฤฑลŸtฤฑrฤฑlabilen** **dosya**, รถrn: `python`, `python.exe` veya `uvicorn`. +* ฤฐลŸletim sistemi รผzerinde **รงalฤฑลŸฤฑr durumdayken** CPU kullanan ve bellekte veri tutan belirli bir program. Buna **process** de denir. + +### Process Nedir { #what-is-a-process } + +**Process** kelimesi genellikle daha spesifik kullanฤฑlฤฑr; yalnฤฑzca iลŸletim sistemi รผzerinde รงalฤฑลŸan ลŸeye (yukarฤฑdaki son madde gibi) iลŸaret eder: + +* ฤฐลŸletim sistemi รผzerinde **รงalฤฑลŸฤฑr durumda** olan belirli bir program. + * Bu; dosyayฤฑ ya da code'u deฤŸil, iลŸletim sistemi tarafฤฑndan **รงalฤฑลŸtฤฑrฤฑlan** ve yรถnetilen ลŸeyi ifade eder. +* Herhangi bir program, herhangi bir code, **yalnฤฑzca รงalฤฑลŸtฤฑrฤฑlฤฑrken** bir ลŸey yapabilir. Yani bir **process รงalฤฑลŸฤฑyorken**. +* Process siz tarafฤฑndan veya iลŸletim sistemi tarafฤฑndan **sonlandฤฑrฤฑlabilir** (ya da "killed" edilebilir). O anda รงalฤฑลŸmasฤฑ/รงalฤฑลŸtฤฑrฤฑlmasฤฑ durur ve artฤฑk **hiรงbir ลŸey yapamaz**. +* Bilgisayarฤฑnฤฑzda รงalฤฑลŸan her uygulamanฤฑn arkasฤฑnda bir process vardฤฑr; รงalฤฑลŸan her program, her pencere vb. Bilgisayar aรงฤฑkken normalde **aynฤฑ anda** birรงok process รงalฤฑลŸฤฑr. +* Aynฤฑ anda **aynฤฑ programฤฑn birden fazla process**'i รงalฤฑลŸabilir. + +ฤฐลŸletim sisteminizdeki "task manager" veya "system monitor" (ya da benzeri araรงlar) ile bu process'lerin birรงoฤŸunu รงalฤฑลŸฤฑr halde gรถrebilirsiniz. + +ร–rneฤŸin muhtemelen aynฤฑ browser programฤฑnฤฑ (Firefox, Chrome, Edge vb.) รงalฤฑลŸtฤฑran birden fazla process gรถreceksiniz. Genelde her tab iรงin bir process, รผstรผne bazฤฑ ek process'ler รงalฤฑลŸtฤฑrฤฑrlar. + + + +--- + +Artฤฑk **process** ve **program** arasฤฑndaki farkฤฑ bildiฤŸimize gรถre, deployment konusuna devam edelim. + +## Startup'ta ร‡alฤฑลŸtฤฑrma { #running-on-startup } + +ร‡oฤŸu durumda bir web API oluลŸturduฤŸunuzda, client'larฤฑnฤฑzฤฑn her zaman eriลŸebilmesi iรงin API'nizin kesintisiz ลŸekilde **sรผrekli รงalฤฑลŸฤฑyor** olmasฤฑnฤฑ istersiniz. Elbette sadece belirli durumlarda รงalฤฑลŸmasฤฑnฤฑ istemenizin รถzel bir sebebi olabilir; ancak รงoฤŸunlukla onu sรผrekli aรงฤฑk ve **kullanฤฑlabilir** halde tutarsฤฑnฤฑz. + +### Uzak Bir Server'da { #in-a-remote-server } + +Uzak bir server (cloud server, sanal makine vb.) kurduฤŸunuzda, yapabileceฤŸiniz en basit ลŸey; local geliลŸtirme sฤฑrasฤฑnda yaptฤฑฤŸฤฑnฤฑz gibi, manuel olarak `fastapi run` (Uvicorn'u kullanฤฑr) veya benzeri bir komutla รงalฤฑลŸtฤฑrmaktฤฑr. + +Bu yรถntem รงalฤฑลŸฤฑr ve **geliลŸtirme sฤฑrasฤฑnda** faydalฤฑdฤฑr. + +Ancak server'a olan baฤŸlantฤฑnฤฑz koparsa, **รงalฤฑลŸan process** muhtemelen รถlรผr. + +Ve server yeniden baลŸlatฤฑlฤฑrsa (รถrneฤŸin update'lerden sonra ya da cloud provider'ฤฑn migration'larฤฑndan sonra) bunu muhtemelen **fark etmezsiniz**. Dolayฤฑsฤฑyla process'i manuel yeniden baลŸlatmanฤฑz gerektiฤŸini de bilmezsiniz. Sonuรงta API'niz รถlรผ kalฤฑr. + +### Startup'ta Otomatik ร‡alฤฑลŸtฤฑrma { #run-automatically-on-startup } + +Genellikle server programฤฑnฤฑn (รถr. Uvicorn) server aรงฤฑlฤฑลŸฤฑnda otomatik baลŸlamasฤฑnฤฑ ve herhangi bir **insan mรผdahalesi** gerektirmeden API'nizi รงalฤฑลŸtฤฑran bir process'in sรผrekli ayakta olmasฤฑnฤฑ istersiniz (รถr. FastAPI uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran Uvicorn). + +### Ayrฤฑ Bir Program { #separate-program } + +Bunu saฤŸlamak iรงin genellikle startup'ta uygulamanฤฑzฤฑn รงalฤฑลŸtฤฑฤŸฤฑndan emin olacak **ayrฤฑ bir program** kullanฤฑrsฤฑnฤฑz. Pek รงok durumda bu program, รถrneฤŸin bir veritabanฤฑ gibi diฤŸer bileลŸenlerin/uygulamalarฤฑn da รงalฤฑลŸtฤฑฤŸฤฑndan emin olur. + +### Startup'ta ร‡alฤฑลŸtฤฑrmak iรงin ร–rnek Araรงlar { #example-tools-to-run-at-startup } + +Bu iลŸi yapabilen araรงlara รถrnekler: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Bir cloud provider tarafฤฑndan servislerinin parรงasฤฑ olarak iรงeride yรถnetilmesi +* DiฤŸerleri... + +Sonraki bรถlรผmlerde daha somut รถrnekler vereceฤŸim. + +## Yeniden BaลŸlatmalar { #restarts } + +Uygulamanฤฑzฤฑn startup'ta รงalฤฑลŸtฤฑฤŸฤฑndan emin olmaya benzer ลŸekilde, hatalardan sonra **yeniden baลŸlatฤฑldฤฑฤŸฤฑndan** da emin olmak istersiniz. + +### Hata Yaparฤฑz { #we-make-mistakes } + +Biz insanlar sรผrekli **hata** yaparฤฑz. Yazฤฑlฤฑmฤฑn neredeyse *her zaman* farklฤฑ yerlerinde gizli **bug**'lar vardฤฑr. + +Ve biz geliลŸtiriciler bu bug'larฤฑ buldukรงa ve yeni รถzellikler ekledikรงe code'u iyileลŸtiririz (muhtemelen yeni bug'lar da ekleyerek). + +### Kรผรงรผk Hatalar Otomatik Yรถnetilir { #small-errors-automatically-handled } + +FastAPI ile web API geliลŸtirirken, code'umuzda bir hata olursa FastAPI genellikle bunu hatayฤฑ tetikleyen tek request ile sฤฑnฤฑrlar. + +Client o request iรงin **500 Internal Server Error** alฤฑr; ancak uygulama tamamen รงรถkรผp durmak yerine sonraki request'ler iรงin รงalฤฑลŸmaya devam eder. + +### Daha Bรผyรผk Hatalar - ร‡รถkmeler { #bigger-errors-crashes } + +Yine de bazฤฑ durumlarda, yazdฤฑฤŸฤฑmฤฑz bir code **tรผm uygulamayฤฑ รงรถkertip** Uvicorn ve Python'ฤฑn crash olmasฤฑna neden olabilir. + +Bรถyle bir durumda, tek bir noktadaki hata yรผzรผnden uygulamanฤฑn รถlรผ kalmasฤฑnฤฑ istemezsiniz; bozuk olmayan *path operations* en azฤฑndan รงalฤฑลŸmaya devam etsin istersiniz. + +### Crash Sonrasฤฑ Yeniden BaลŸlatma { #restart-after-crash } + +Ancak รงalฤฑลŸan **process**'i รงรถkerten gerรงekten kรถtรผ hatalarda, process'i **yeniden baลŸlatmaktan** sorumlu harici bir bileลŸen istersiniz; en azฤฑndan birkaรง kez... + +/// tip | ฤฐpucu + +...Yine de uygulama **hemen crash oluyorsa**, onu sonsuza kadar yeniden baลŸlatmaya รงalฤฑลŸmanฤฑn pek anlamฤฑ yoktur. Bรถyle durumlarฤฑ bรผyรผk ihtimalle geliลŸtirme sฤฑrasฤฑnda ya da en geรง deploy'dan hemen sonra fark edersiniz. + +O yรผzden ana senaryoya odaklanalฤฑm: Gelecekte bazฤฑ รถzel durumlarda tamamen รงรถkebilir ve yine de yeniden baลŸlatmak mantฤฑklฤฑdฤฑr. + +/// + +Uygulamanฤฑzฤฑ yeniden baลŸlatmakla gรถrevli bileลŸenin **harici bir bileลŸen** olmasฤฑnฤฑ istersiniz. ร‡รผnkรผ o noktada Uvicorn ve Python ile birlikte aynฤฑ uygulama zaten crash olmuลŸtur; aynฤฑ app'in iรงindeki aynฤฑ code'un bunu dรผzeltmek iรงin yapabileceฤŸi bir ลŸey kalmaz. + +### Otomatik Yeniden BaลŸlatma iรงin ร–rnek Araรงlar { #example-tools-to-restart-automatically } + +ร‡oฤŸu durumda, **startup'ta programฤฑ รงalฤฑลŸtฤฑrmak** iรงin kullanฤฑlan aracฤฑn aynฤฑsฤฑ otomatik **restart**'larฤฑ yรถnetmek iรงin de kullanฤฑlฤฑr. + +ร–rneฤŸin bu ลŸunlarla yรถnetilebilir: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Bir cloud provider tarafฤฑndan servislerinin parรงasฤฑ olarak iรงeride yรถnetilmesi +* DiฤŸerleri... + +## Replikasyon - Process'ler ve Bellek { #replication-processes-and-memory } + +FastAPI uygulamasฤฑnda, Uvicorn'u รงalฤฑลŸtฤฑran `fastapi` komutu gibi bir server programฤฑ kullanฤฑrken, uygulamayฤฑ **tek bir process** iรงinde bir kez รงalฤฑลŸtฤฑrmak bile aynฤฑ anda birden fazla client'a hizmet verebilir. + +Ancak birรงok durumda, aynฤฑ anda birden fazla worker process รงalฤฑลŸtฤฑrmak istersiniz. + +### Birden Fazla Process - Worker'lar { #multiple-processes-workers } + +Tek bir process'in karลŸฤฑlayabileceฤŸinden daha fazla client'ฤฑnฤฑz varsa (รถrneฤŸin sanal makine รงok bรผyรผk deฤŸilse) ve server CPU'sunda **birden fazla core** varsa, aynฤฑ uygulamayla **birden fazla process** รงalฤฑลŸtฤฑrฤฑp tรผm request'leri bunlara daฤŸฤฑtabilirsiniz. + +Aynฤฑ API programฤฑnฤฑn **birden fazla process**'ini รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda, bunlara genellikle **worker** denir. + +### Worker Process'ler ve Port'lar { #worker-processes-and-ports } + +[HTTPS hakkฤฑndaki dokรผmanda](https.md){.internal-link target=_blank} bir server'da aynฤฑ port ve IP adresi kombinasyonunu yalnฤฑzca tek bir process'in dinleyebileceฤŸini hatฤฑrlฤฑyor musunuz? + +Bu hรขlรข geรงerli. + +Dolayฤฑsฤฑyla **aynฤฑ anda birden fazla process** รงalฤฑลŸtฤฑrabilmek iรงin, **port** รผzerinde dinleyen **tek bir process** olmalฤฑ ve bu process iletiลŸimi bir ลŸekilde worker process'lere aktarmalฤฑdฤฑr. + +### Process BaลŸฤฑna Bellek { #memory-per-process } + +Program belleฤŸe bir ลŸeyler yรผklediฤŸindeโ€”รถrneฤŸin bir deฤŸiลŸkende bir machine learning modelini veya bรผyรผk bir dosyanฤฑn iรงeriฤŸini tutmak gibiโ€”bunlarฤฑn hepsi server'ฤฑn **belleฤŸini (RAM)** tรผketir. + +Ve birden fazla process normalde **belleฤŸi paylaลŸmaz**. Yani her รงalฤฑลŸan process'in kendi verileri, deฤŸiลŸkenleri ve belleฤŸi vardฤฑr. Code'unuz รงok bellek tรผketiyorsa, **her process** buna denk bir miktar bellek tรผketir. + +### Server BelleฤŸi { #server-memory } + +ร–rneฤŸin code'unuz **1 GB** boyutunda bir Machine Learning modelini yรผklรผyorsa, API'niz tek process ile รงalฤฑลŸฤฑrken en az 1 GB RAM tรผketir. **4 process** (4 worker) baลŸlatฤฑrsanฤฑz her biri 1 GB RAM tรผketir. Yani toplamda API'niz **4 GB RAM** tรผketir. + +Uzak server'ฤฑnฤฑz veya sanal makineniz yalnฤฑzca 3 GB RAM'e sahipse, 4 GB'tan fazla RAM yรผklemeye รงalฤฑลŸmak sorun รงฤฑkarฤฑr. + +### Birden Fazla Process - Bir ร–rnek { #multiple-processes-an-example } + +Bu รถrnekte, iki adet **Worker Process** baลŸlatฤฑp kontrol eden bir **Manager Process** vardฤฑr. + +Bu Manager Process bรผyรผk ihtimalle IP รผzerindeki **port**'u dinleyen sรผreรงtir ve tรผm iletiลŸimi worker process'lere aktarฤฑr. + +Worker process'ler uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran process'lerdir; bir **request** alฤฑp bir **response** dรถndรผrmek iรงin asฤฑl hesaplamalarฤฑ yaparlar ve sizin RAM'de deฤŸiลŸkenlere koyduฤŸunuz her ลŸeyi yรผklerler. + + + +Elbette aynฤฑ makinede, uygulamanฤฑz dฤฑลŸฤฑnda da muhtemelen **baลŸka process**'ler รงalฤฑลŸฤฑr. + +ฤฐlginรง bir detay: Her process'in kullandฤฑฤŸฤฑ **CPU** yรผzdesi zaman iรงinde รงok **deฤŸiลŸken** olabilir; ancak **bellek (RAM)** genellikle az รงok **stabil** kalฤฑr. + +EฤŸer API'niz her seferinde benzer miktarda hesaplama yapฤฑyorsa ve รงok sayฤฑda client'ฤฑnฤฑz varsa, **CPU kullanฤฑmฤฑ** da muhtemelen *stabil olur* (hฤฑzlฤฑ hฤฑzlฤฑ sรผrekli yรผkselip alรงalmak yerine). + +### Replikasyon Araรงlarฤฑ ve Stratejileri ร–rnekleri { #examples-of-replication-tools-and-strategies } + +Bunu baลŸarmak iรงin farklฤฑ yaklaลŸฤฑmlar olabilir. Sonraki bรถlรผmlerde, รถrneฤŸin Docker ve container'lar konuลŸurken, belirli stratejileri daha detaylฤฑ anlatacaฤŸฤฑm. + +Dikkate almanฤฑz gereken ana kฤฑsฤฑt ลŸudur: **public IP** รผzerindeki **port**'u yรถneten **tek** bir bileลŸen olmalฤฑ. Sonrasฤฑnda bu bileลŸenin, replikasyonla รงoฤŸaltฤฑlmฤฑลŸ **process/worker**'lara iletiลŸimi **aktarmanฤฑn** bir yoluna sahip olmasฤฑ gerekir. + +Olasฤฑ kombinasyonlar ve stratejiler: + +* `--workers` ile **Uvicorn** + * Bir Uvicorn **process manager** **IP** ve **port** รผzerinde dinler ve **birden fazla Uvicorn worker process** baลŸlatฤฑr. +* **Kubernetes** ve diฤŸer daฤŸฤฑtฤฑk **container sistemleri** + * **Kubernetes** katmanฤฑnda bir ลŸey **IP** ve **port** รผzerinde dinler. Replikasyon, her birinde **tek bir Uvicorn process** รงalฤฑลŸan **birden fazla container** ile yapฤฑlฤฑr. +* Bunu sizin yerinize yapan **cloud service**'ler + * Cloud service muhtemelen **replikasyonu sizin yerinize yรถnetir**. Size รงalฤฑลŸtฤฑrฤฑlacak **bir process** veya kullanฤฑlacak bir **container image** tanฤฑmlama imkรขnฤฑ verebilir; her durumda bรผyรผk ihtimalle **tek bir Uvicorn process** olur ve bunu รงoฤŸaltmaktan cloud service sorumlu olur. + +/// tip | ฤฐpucu + +**Container**, Docker veya Kubernetes ile ilgili bazฤฑ maddeler ลŸimdilik รงok anlamlฤฑ gelmiyorsa dert etmeyin. + +Container image'larฤฑ, Docker, Kubernetes vb. konularฤฑ ilerideki bir bรถlรผmde daha detaylฤฑ anlatacaฤŸฤฑm: [Container'larda FastAPI - Docker](docker.md){.internal-link target=_blank}. + +/// + +## BaลŸlatmadan ร–nceki Adฤฑmlar { #previous-steps-before-starting } + +Uygulamanฤฑzฤฑ **baลŸlatmadan รถnce** bazฤฑ adฤฑmlar yapmak isteyeceฤŸiniz birรงok durum vardฤฑr. + +ร–rneฤŸin **database migrations** รงalฤฑลŸtฤฑrmak isteyebilirsiniz. + +Ancak รงoฤŸu durumda, bu adฤฑmlarฤฑ yalnฤฑzca **bir kez** รงalฤฑลŸtฤฑrmak istersiniz. + +Bu yรผzden, uygulamayฤฑ baลŸlatmadan รถnce bu **รถn adฤฑmlarฤฑ** รงalฤฑลŸtฤฑracak **tek bir process** olmasฤฑnฤฑ istersiniz. + +Ve daha sonra uygulamanฤฑn kendisi iรงin **birden fazla process** (birden fazla worker) baลŸlatsanฤฑz bile, bu รถn adฤฑmlarฤฑ รงalฤฑลŸtฤฑranฤฑn *yine* tek process olduฤŸundan emin olmalฤฑsฤฑnฤฑz. Bu adฤฑmlar **birden fazla process** tarafฤฑndan รงalฤฑลŸtฤฑrฤฑlsaydฤฑ, iลŸi **paralel** ลŸekilde tekrarlarlardฤฑ. Adฤฑmlar database migration gibi hassas bir ลŸeyse, birbirleriyle รงakฤฑลŸฤฑp รงatฤฑลŸma รงฤฑkarabilirler. + +Elbette bazฤฑ durumlarda รถn adฤฑmlarฤฑ birden fazla kez รงalฤฑลŸtฤฑrmak sorun deฤŸildir; bu durumda yรถnetmesi รงok daha kolay olur. + +/// tip | ฤฐpucu + +Ayrฤฑca, kurulumunuza baฤŸlฤฑ olarak bazฤฑ durumlarda uygulamanฤฑzฤฑ baลŸlatmadan รถnce **hiรง รถn adฤฑma ihtiyaรง duymayabilirsiniz**. + +Bu durumda bunlarฤฑn hiรงbirini dรผลŸรผnmeniz gerekmez. + +/// + +### ร–n Adฤฑmlar iรงin Strateji ร–rnekleri { #examples-of-previous-steps-strategies } + +Bu konu, **sisteminizi nasฤฑl deploy ettiฤŸinize** รงok baฤŸlฤฑdฤฑr ve muhtemelen programlarฤฑ nasฤฑl baลŸlattฤฑฤŸฤฑnฤฑz, restart'larฤฑ nasฤฑl yรถnettiฤŸiniz vb. ile baฤŸlantฤฑlฤฑdฤฑr. + +Bazฤฑ olasฤฑ fikirler: + +* Kubernetes'te, app container'ฤฑnฤฑzdan รถnce รงalฤฑลŸan bir "Init Container" +* ร–n adฤฑmlarฤฑ รงalฤฑลŸtฤฑrฤฑp sonra uygulamanฤฑzฤฑ baลŸlatan bir bash script + * Yine de o bash script'i baลŸlatmak/restart etmek, hatalarฤฑ tespit etmek vb. iรงin bir mekanizmaya ihtiyacฤฑnฤฑz olur. + +/// tip | ฤฐpucu + +Bunu container'larla nasฤฑl yapabileceฤŸinize dair daha somut รถrnekleri ilerideki bir bรถlรผmde anlatacaฤŸฤฑm: [Container'larda FastAPI - Docker](docker.md){.internal-link target=_blank}. + +/// + +## Kaynak Kullanฤฑmฤฑ { #resource-utilization } + +Server(lar)ฤฑnฤฑz bir **kaynaktฤฑr**. Programlarฤฑnฤฑzla CPU'lardaki hesaplama zamanฤฑnฤฑ ve mevcut RAM belleฤŸini tรผketebilir veya **kullanabilirsiniz**. + +Sistem kaynaklarฤฑnฤฑn ne kadarฤฑnฤฑ tรผketmek/kullanmak istersiniz? "Az" demek kolaydฤฑr; ancak pratikte hedef genellikle **รงรถkmeden mรผmkรผn olduฤŸunca fazla** kullanmaktฤฑr. + +3 server iรงin para รถdรผyor ama onlarฤฑn RAM ve CPU'sunun yalnฤฑzca kรผรงรผk bir kฤฑsmฤฑnฤฑ kullanฤฑyorsanฤฑz, muhtemelen **para israf ediyorsunuz** ve muhtemelen **elektrik tรผketimini** de gereksiz yere artฤฑrฤฑyorsunuz vb. + +Bu durumda 2 server ile devam edip onlarฤฑn kaynaklarฤฑnฤฑ (CPU, bellek, disk, aฤŸ bant geniลŸliฤŸi vb.) daha yรผksek oranlarda kullanmak daha iyi olabilir. + +ร–te yandan, 2 server'ฤฑnฤฑz var ve CPU ile RAM'in **%100**'รผnรผ kullanฤฑyorsanฤฑz, bir noktada bir process daha fazla bellek ister; server diski "bellek" gibi kullanmak zorunda kalฤฑr (binlerce kat daha yavaลŸ olabilir) ya da hatta **crash** edebilir. Ya da bir process bir hesaplama yapmak ister ve CPU tekrar boลŸalana kadar beklemek zorunda kalฤฑr. + +Bu senaryoda **bir server daha** eklemek ve bazฤฑ process'leri orada รงalฤฑลŸtฤฑrmak daha iyi olur; bรถylece hepsinin **yeterli RAM'i ve CPU zamanฤฑ** olur. + +Ayrฤฑca, herhangi bir sebeple API'nizde bir kullanฤฑm **spike**'ฤฑ olma ihtimali de vardฤฑr. Belki viral olur, belki baลŸka servisler veya bot'lar kullanmaya baลŸlar. Bu durumlarda gรผvende olmak iรงin ekstra kaynak isteyebilirsiniz. + +Hedef olarak **keyfi bir sayฤฑ** belirleyebilirsiniz; รถrneฤŸin kaynak kullanฤฑmฤฑnฤฑ **%50 ile %90 arasฤฑnda** tutmak gibi. ร–nemli olan, bunlarฤฑn muhtemelen รถlรงmek isteyeceฤŸiniz ve deployment'larฤฑnฤฑzฤฑ ayarlamak iรงin kullanacaฤŸฤฑnฤฑz ana metrikler olmasฤฑdฤฑr. + +Server'ฤฑnฤฑzda CPU ve RAM kullanฤฑmฤฑnฤฑ veya her process'in ne kadar kullandฤฑฤŸฤฑnฤฑ gรถrmek iรงin `htop` gibi basit araรงlarฤฑ kullanabilirsiniz. Ya da server'lar arasฤฑnda daฤŸฤฑtฤฑk รงalฤฑลŸan daha karmaลŸฤฑk monitoring araรงlarฤฑ kullanabilirsiniz. + +## ร–zet { #recap } + +Uygulamanฤฑzฤฑ nasฤฑl deploy edeceฤŸinize karar verirken aklฤฑnฤฑzda tutmanฤฑz gereken ana kavramlarฤฑn bazฤฑlarฤฑnฤฑ okudunuz: + +* Gรผvenlik - HTTPS +* Startup'ta รงalฤฑลŸtฤฑrma +* Yeniden baลŸlatmalar +* Replikasyon (รงalฤฑลŸan process sayฤฑsฤฑ) +* Bellek +* BaลŸlatmadan รถnceki adฤฑmlar + +Bu fikirleri ve nasฤฑl uygulayacaฤŸฤฑnฤฑzฤฑ anlamak, deployment'larฤฑnฤฑzฤฑ yapฤฑlandฤฑrฤฑrken ve ince ayar yaparken ihtiyaรง duyacaฤŸฤฑnฤฑz sezgiyi kazanmanฤฑzฤฑ saฤŸlamalฤฑdฤฑr. + +Sonraki bรถlรผmlerde, izleyebileceฤŸiniz stratejilere dair daha somut รถrnekler paylaลŸacaฤŸฤฑm. diff --git a/docs/tr/docs/deployment/docker.md b/docs/tr/docs/deployment/docker.md new file mode 100644 index 0000000000..b48d2ddf58 --- /dev/null +++ b/docs/tr/docs/deployment/docker.md @@ -0,0 +1,620 @@ +# Container'larda FastAPI - Docker { #fastapi-in-containers-docker } + +FastAPI uygulamalarฤฑnฤฑ deploy ederken yaygฤฑn bir yaklaลŸฤฑm, bir **Linux container image** oluลŸturmaktฤฑr. Bu genellikle **Docker** kullanฤฑlarak yapฤฑlฤฑr. Ardฤฑndan bu container image'ฤฑ birkaรง farklฤฑ yรถntemden biriyle deploy edebilirsiniz. + +Linux container'larฤฑ kullanmanฤฑn **gรผvenlik**, **tekrarlanabilirlik**, **basitlik** gibi birรงok avantajฤฑ vardฤฑr. + +/// tip | ฤฐpucu + +Aceleniz var ve bunlarฤฑ zaten biliyor musunuz? AลŸaฤŸฤฑdaki [`Dockerfile`'a atlayฤฑn ๐Ÿ‘‡](#build-a-docker-image-for-fastapi). + +/// + +
+Dockerfile ร–nizleme ๐Ÿ‘€ + +```Dockerfile +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# If running behind a proxy like Nginx or Traefik add --proxy-headers +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## Container Nedir { #what-is-a-container } + +Container'lar (รถzellikle Linux container'larฤฑ), bir uygulamayฤฑ tรผm baฤŸฤฑmlฤฑlฤฑklarฤฑ ve gerekli dosyalarฤฑyla birlikte paketlemenin, aynฤฑ sistemdeki diฤŸer container'lardan (diฤŸer uygulama ya da bileลŸenlerden) izole tutarken yapฤฑlan, รงok **hafif** bir yoludur. + +Linux container'larฤฑ, host'un (makine, sanal makine, cloud server vb.) aynฤฑ Linux kernel'ini kullanarak รงalฤฑลŸฤฑr. Bu da, tรผm bir iลŸletim sistemini emรผle eden tam sanal makinelere kฤฑyasla รงok daha hafif olduklarฤฑ anlamฤฑna gelir. + +Bu sayede container'lar **az kaynak** tรผketir; sรผreรงleri doฤŸrudan รงalฤฑลŸtฤฑrmaya benzer bir seviyede (bir sanal makine รงok daha fazla tรผketirdi). + +Container'larฤฑn ayrฤฑca kendi **izole** รงalฤฑลŸan process'leri (รงoฤŸunlukla tek bir process), dosya sistemi ve aฤŸฤฑ vardฤฑr. Bu da deployment, gรผvenlik, geliลŸtirme vb. sรผreรงleri kolaylaลŸtฤฑrฤฑr. + +## Container Image Nedir { #what-is-a-container-image } + +Bir **container**, bir **container image**'dan รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Container image; bir container iรงinde bulunmasฤฑ gereken tรผm dosyalarฤฑn, environment variable'larฤฑn ve varsayฤฑlan komut/programฤฑn **statik** bir sรผrรผmรผdรผr. Buradaki **statik**, container **image**'ฤฑnฤฑn รงalฤฑลŸmadฤฑฤŸฤฑ, execute edilmediฤŸi; sadece paketlenmiลŸ dosyalar ve metadata olduฤŸu anlamฤฑna gelir. + +DepolanmฤฑลŸ statik iรงerik olan "**container image**"ฤฑn aksine, "**container**" normalde รงalฤฑลŸan instance'ฤฑ, yani **execute edilen** ลŸeyi ifade eder. + +**Container** baลŸlatฤฑlฤฑp รงalฤฑลŸtฤฑฤŸฤฑnda (bir **container image**'dan baลŸlatฤฑlฤฑr), dosyalar oluลŸturabilir/deฤŸiลŸtirebilir, environment variable'larฤฑ deฤŸiลŸtirebilir vb. Bu deฤŸiลŸiklikler sadece o container iรงinde kalฤฑr; alttaki container image'da kalฤฑcฤฑ olmaz (diske kaydedilmez). + +Bir container image, **program** dosyasฤฑ ve iรงeriklerine benzetilebilir; รถrn. `python` ve `main.py` gibi bir dosya. + +Ve **container**'ฤฑn kendisi (container image'a karลŸฤฑt olarak) image'ฤฑn gerรงek รงalฤฑลŸan instance'ฤฑdฤฑr; bir **process**'e benzer. Hatta bir container, yalnฤฑzca iรงinde **รงalฤฑลŸan bir process** varken รงalฤฑลŸฤฑr (ve genelde tek process olur). ฤฐรงinde รงalฤฑลŸan process kalmayฤฑnca container durur. + +## Container Image'lar { #container-images } + +Docker, **container image** ve **container** oluลŸturup yรถnetmek iรงin kullanฤฑlan baลŸlฤฑca araรงlardan biri olmuลŸtur. + +Ayrฤฑca birรงok araรง, ortam, veritabanฤฑ ve uygulama iรงin รถnceden hazฤฑrlanmฤฑลŸ **resmi container image**'larฤฑn bulunduฤŸu herkese aรงฤฑk bir Docker Hub vardฤฑr. + +ร–rneฤŸin, resmi bir Python Image bulunur. + +Ve veritabanlarฤฑ gibi farklฤฑ ลŸeyler iรงin de birรงok image vardฤฑr; รถrneฤŸin: + +* PostgreSQL +* MySQL +* MongoDB +* Redis, vb. + +Hazฤฑr bir container image kullanarak farklฤฑ araรงlarฤฑ **birleลŸtirmek** ve birlikte kullanmak รงok kolaydฤฑr. ร–rneฤŸin yeni bir veritabanฤฑnฤฑ denemek iรงin. ร‡oฤŸu durumda **resmi image**'larฤฑ kullanฤฑp sadece environment variable'lar ile yapฤฑlandฤฑrmanฤฑz yeterlidir. + +Bu ลŸekilde, รงoฤŸu zaman container'lar ve Docker hakkฤฑnda รถฤŸrendiklerinizi farklฤฑ araรง ve bileลŸenlerde tekrar kullanabilirsiniz. + +Dolayฤฑsฤฑyla; veritabanฤฑ, Python uygulamasฤฑ, React frontend uygulamasฤฑ olan bir web server gibi farklฤฑ ลŸeyler iรงin **birden fazla container** รงalฤฑลŸtฤฑrฤฑr ve bunlarฤฑ internal network รผzerinden birbirine baฤŸlarsฤฑnฤฑz. + +Docker veya Kubernetes gibi tรผm container yรถnetim sistemlerinde bu aฤŸ รถzellikleri entegre olarak bulunur. + +## Container'lar ve Process'ler { #containers-and-processes } + +Bir **container image** normalde metadata iรงinde, **container** baลŸlatฤฑldฤฑฤŸฤฑnda รงalฤฑลŸtฤฑrฤฑlacak varsayฤฑlan program/komutu ve o programa geรงirilecek parametreleri iรงerir. Bu, komut satฤฑrฤฑnda yazacaฤŸฤฑnฤฑz ลŸeye รงok benzer. + +Bir **container** baลŸlatฤฑldฤฑฤŸฤฑnda bu komutu/programฤฑ รงalฤฑลŸtฤฑrฤฑr (ancak isterseniz bunu override edip baลŸka bir komut/program รงalฤฑลŸtฤฑrabilirsiniz). + +Bir container, **ana process** (komut/program) รงalฤฑลŸtฤฑฤŸฤฑ sรผrece รงalฤฑลŸฤฑr. + +Container'larda normalde **tek bir process** olur. Ancak ana process iรงinden subprocess'ler baลŸlatmak da mรผmkรผndรผr; bรถylece aynฤฑ container iรงinde **birden fazla process** olur. + +Ama **en az bir รงalฤฑลŸan process olmadan** รงalฤฑลŸan bir container olamaz. Ana process durursa container da durur. + +## FastAPI iรงin Docker Image OluลŸturalฤฑm { #build-a-docker-image-for-fastapi } + +Tamam, ลŸimdi bir ลŸeyler inลŸa edelim! ๐Ÿš€ + +Resmi **Python** image'ฤฑnฤฑ temel alarak, FastAPI iรงin **sฤฑfฤฑrdan** bir **Docker image** nasฤฑl oluลŸturulur gรถstereceฤŸim. + +Bu, รถrneฤŸin ลŸu durumlarda **รงoฤŸu zaman** yapmak isteyeceฤŸiniz ลŸeydir: + +* **Kubernetes** veya benzeri araรงlar kullanฤฑrken +* **Raspberry Pi** รผzerinde รงalฤฑลŸtฤฑrฤฑrken +* Container image'ฤฑnฤฑzฤฑ sizin iรงin รงalฤฑลŸtฤฑran bir cloud servisi kullanฤฑrken, vb. + +### Paket Gereksinimleri { #package-requirements } + +Uygulamanฤฑzฤฑn **paket gereksinimleri** genelde bir dosyada yer alฤฑr. + +Bu, gereksinimleri **yรผklemek** iรงin kullandฤฑฤŸฤฑnฤฑz araca gรถre deฤŸiลŸir. + +En yaygฤฑn yรถntem, paket adlarฤฑ ve versiyonlarฤฑnฤฑn satฤฑr satฤฑr yazฤฑldฤฑฤŸฤฑ bir `requirements.txt` dosyasฤฑna sahip olmaktฤฑr. + +Versiyon aralฤฑklarฤฑnฤฑ belirlemek iรงin elbette [FastAPI sรผrรผmleri hakkฤฑnda](versions.md){.internal-link target=_blank} bรถlรผmรผnde okuduฤŸunuz fikirleri kullanฤฑrsฤฑnฤฑz. + +ร–rneฤŸin `requirements.txt` ลŸรถyle gรถrรผnebilir: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +Ve bu baฤŸฤฑmlฤฑlฤฑklarฤฑ normalde `pip` ile yรผklersiniz, รถrneฤŸin: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// info | Bilgi + +Paket baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ tanฤฑmlamak ve yรผklemek iรงin baลŸka formatlar ve araรงlar da vardฤฑr. + +/// + +### **FastAPI** Kodunu OluลŸturun { #create-the-fastapi-code } + +* Bir `app` dizini oluลŸturun ve iรงine girin. +* BoลŸ bir `__init__.py` dosyasฤฑ oluลŸturun. +* AลŸaฤŸฤฑdakilerle bir `main.py` dosyasฤฑ oluลŸturun: + +```Python +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +ลžimdi aynฤฑ proje dizininde `Dockerfile` adlฤฑ bir dosya oluลŸturun ve iรงine ลŸunlarฤฑ yazฤฑn: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.9 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Resmi Python base image'ฤฑndan baลŸlayฤฑn. + +2. Geรงerli รงalฤฑลŸma dizinini `/code` olarak ayarlayฤฑn. + + `requirements.txt` dosyasฤฑnฤฑ ve `app` dizinini buraya koyacaฤŸฤฑz. + +3. Gereksinimleri iรงeren dosyayฤฑ `/code` dizinine kopyalayฤฑn. + + ร–nce kodun tamamฤฑnฤฑ deฤŸil, **sadece** gereksinim dosyasฤฑnฤฑ kopyalayฤฑn. + + Bu dosya **รงok sฤฑk deฤŸiลŸmediฤŸi** iรงin Docker bunu tespit eder ve bu adฤฑmda **cache** kullanฤฑr; bรถylece bir sonraki adฤฑm iรงin de cache devreye girer. + +4. Gereksinim dosyasฤฑndaki paket baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ yรผkleyin. + + `--no-cache-dir` seรงeneฤŸi, indirilen paketlerin yerel olarak kaydedilmemesini `pip`'e sรถyler. Bu kayฤฑt, `pip` aynฤฑ paketleri tekrar yรผklemek iรงin yeniden รงalฤฑลŸtฤฑrฤฑlacaksa iลŸe yarar; ancak container'larla รงalฤฑลŸฤฑrken genelde bu durum geรงerli deฤŸildir. + + /// note | Not + + `--no-cache-dir` yalnฤฑzca `pip` ile ilgilidir; Docker veya container'larla ilgili deฤŸildir. + + /// + + `--upgrade` seรงeneฤŸi, paketler zaten yรผklรผyse `pip`'e onlarฤฑ yรผkseltmesini sรถyler. + + Bir รถnceki adฤฑm (dosyayฤฑ kopyalama) **Docker cache** tarafฤฑndan tespit edilebildiฤŸi iรงin, bu adฤฑm da uygun olduฤŸunda **Docker cache'i kullanฤฑr**. + + Bu adฤฑmda cache kullanmak, geliลŸtirme sฤฑrasฤฑnda image'ฤฑ tekrar tekrar build ederken size รงok **zaman** kazandฤฑrฤฑr; her seferinde baฤŸฤฑmlฤฑlฤฑklarฤฑ **indirip yรผklemek** zorunda kalmazsฤฑnฤฑz. + +5. `./app` dizinini `/code` dizininin iรงine kopyalayฤฑn. + + Burada en sฤฑk deฤŸiลŸen ลŸey olan kodun tamamฤฑ bulunduฤŸundan, bu adฤฑm (ve genelde bundan sonraki adฤฑmlar) iรงin Docker **cache**'i kolay kolay kullanฤฑlamaz. + + Bu yรผzden, container image build sรผrelerini optimize etmek iรงin bunu `Dockerfile`'ฤฑn **sonlarฤฑna yakฤฑn** koymak รถnemlidir. + +6. Altta Uvicorn kullanan `fastapi run` komutunu **command** olarak ayarlayฤฑn. + + `CMD` bir string listesi alฤฑr; bu string'lerin her biri komut satฤฑrฤฑnda boลŸlukla ayrฤฑlmฤฑลŸ ลŸekilde yazacaฤŸฤฑnฤฑz parรงalarฤฑ temsil eder. + + Bu komut, yukarฤฑda `WORKDIR /code` ile ayarladฤฑฤŸฤฑnฤฑz `/code` dizininden รงalฤฑลŸtฤฑrฤฑlฤฑr. + +/// tip | ฤฐpucu + +Kod iรงindeki her numara balonuna tฤฑklayarak her satฤฑrฤฑn ne yaptฤฑฤŸฤฑnฤฑ gรถzden geรงirin. ๐Ÿ‘† + +/// + +/// warning | Uyarฤฑ + +AลŸaฤŸฤฑda aรงฤฑklandฤฑฤŸฤฑ gibi `CMD` talimatฤฑnฤฑn **her zaman** **exec form**'unu kullandฤฑฤŸฤฑnฤฑzdan emin olun. + +/// + +#### `CMD` Kullanฤฑmฤฑ - Exec Form { #use-cmd-exec-form } + +`CMD` Docker talimatฤฑ iki formda yazฤฑlabilir: + +โœ… **Exec** form: + +```Dockerfile +# โœ… Do this +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ **Shell** form: + +```Dockerfile +# โ›”๏ธ Don't do this +CMD fastapi run app/main.py --port 80 +``` + +FastAPI'nin dรผzgรผn ลŸekilde kapanabilmesi ve [lifespan event](../advanced/events.md){.internal-link target=_blank}'lerinin tetiklenmesi iรงin her zaman **exec** formunu kullanฤฑn. + +Detaylar iรงin shell ve exec form iรงin Docker dokรผmanlarฤฑna bakabilirsiniz. + +Bu durum `docker compose` kullanฤฑrken oldukรงa belirgin olabilir. Daha teknik detaylar iรงin ลŸu Docker Compose FAQ bรถlรผmรผne bakฤฑn: Why do my services take 10 seconds to recreate or stop?. + +#### Dizin Yapฤฑsฤฑ { #directory-structure } + +Artฤฑk dizin yapฤฑnฤฑz ลŸรถyle olmalฤฑ: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ โ””โ”€โ”€ main.py +โ”œโ”€โ”€ Dockerfile +โ””โ”€โ”€ requirements.txt +``` + +#### TLS Termination Proxy Arkasฤฑnda { #behind-a-tls-termination-proxy } + +Container'ฤฑnฤฑzฤฑ Nginx veya Traefik gibi bir TLS Termination Proxy (load balancer) arkasฤฑnda รงalฤฑลŸtฤฑrฤฑyorsanฤฑz `--proxy-headers` seรงeneฤŸini ekleyin. Bu, Uvicorn'a (FastAPI CLI รผzerinden) uygulamanฤฑn HTTPS arkasฤฑnda รงalฤฑลŸtฤฑฤŸฤฑnฤฑ sรถyleyen proxy header'larฤฑna gรผvenmesini sรถyler. + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker Cache { #docker-cache } + +Bu `Dockerfile` iรงinde รถnemli bir numara var: รถnce kodun geri kalanฤฑnฤฑ deฤŸil, **sadece baฤŸฤฑmlฤฑlฤฑk dosyasฤฑnฤฑ** kopyalฤฑyoruz. Nedenini anlatayฤฑm. + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker ve benzeri araรงlar bu container image'larฤฑnฤฑ **artฤฑmlฤฑ (incremental)** olarak **build** eder; `Dockerfile`'ฤฑn en รผstรผnden baลŸlayฤฑp her talimatฤฑn oluลŸturduฤŸu dosyalarฤฑ ekleyerek **katman katman (layer)** ilerler. + +Docker ve benzeri araรงlar image build ederken ayrฤฑca bir **internal cache** kullanฤฑr. Son build'den beri bir dosya deฤŸiลŸmediyse, dosyayฤฑ tekrar kopyalayฤฑp sฤฑfฤฑrdan yeni bir layer oluลŸturmak yerine, daha รถnce oluลŸturulan **aynฤฑ layer**'ฤฑ yeniden kullanฤฑr. + +Sadece dosya kopyalamayฤฑ azaltmak her zaman bรผyรผk fark yaratmaz. Ancak o adฤฑmda cache kullanฤฑldฤฑฤŸฤฑ iรงin, **bir sonraki adฤฑmda da cache kullanฤฑlabilir**. ร–rneฤŸin baฤŸฤฑmlฤฑlฤฑklarฤฑ yรผkleyen ลŸu talimat iรงin: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +Paket gereksinimleri dosyasฤฑ **sฤฑk sฤฑk deฤŸiลŸmez**. Bu yรผzden sadece bu dosyayฤฑ kopyalayฤฑnca, Docker bu adฤฑmda **cache** kullanabilir. + +Sonra Docker, baฤŸฤฑmlฤฑlฤฑklarฤฑ indirip yรผkleyen **bir sonraki adฤฑmda** da cache kullanabilir. Asฤฑl **รงok zaman kazandฤฑฤŸฤฑmฤฑz** yer de burasฤฑdฤฑr. โœจ ...ve beklerken sฤฑkฤฑlmayฤฑ engeller. ๐Ÿ˜ช๐Ÿ˜† + +BaฤŸฤฑmlฤฑlฤฑklarฤฑ indirip yรผklemek **dakikalar sรผrebilir**, fakat **cache** kullanmak en fazla **saniyeler** alฤฑr. + +GeliลŸtirme sฤฑrasฤฑnda kod deฤŸiลŸikliklerinizin รงalฤฑลŸtฤฑฤŸฤฑnฤฑ kontrol etmek iรงin container image'ฤฑ tekrar tekrar build edeceฤŸinizden, bu ciddi birikimli zaman kazancฤฑ saฤŸlar. + +Sonra `Dockerfile`'ฤฑn sonlarฤฑna doฤŸru tรผm kodu kopyalarฤฑz. En sฤฑk deฤŸiลŸen kฤฑsฤฑm bu olduฤŸu iรงin sona koyarฤฑz; รงรผnkรผ neredeyse her zaman bu adฤฑmdan sonra gelen adฤฑmlar cache kullanamaz. + +```Dockerfile +COPY ./app /code/app +``` + +### Docker Image'ฤฑnฤฑ Build Edin { #build-the-docker-image } + +Tรผm dosyalar hazฤฑr olduฤŸuna gรถre container image'ฤฑ build edelim. + +* Proje dizinine gidin (`Dockerfile`'ฤฑnฤฑzฤฑn olduฤŸu ve `app` dizininizi iรงeren dizin). +* FastAPI image'ฤฑnฤฑzฤฑ build edin: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | ฤฐpucu + +Sondaki `.` ifadesine dikkat edin; `./` ile aynฤฑ anlama gelir ve Docker'a container image build etmek iรงin hangi dizini kullanacaฤŸฤฑnฤฑ sรถyler. + +Bu รถrnekte, mevcut dizindir (`.`). + +/// + +### Docker Container'ฤฑnฤฑ BaลŸlatฤฑn { #start-the-docker-container } + +* Image'ฤฑnฤฑzdan bir container รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## Kontrol Edin { #check-it } + +Docker container'ฤฑnฤฑzฤฑn URL'inden kontrol edebilmelisiniz. ร–rneฤŸin: http://192.168.99.100/items/5?q=somequery veya http://127.0.0.1/items/5?q=somequery (ya da Docker host'unuzu kullanarak eลŸdeฤŸeri). + +ลžuna benzer bir ลŸey gรถrรผrsรผnรผz: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## EtkileลŸimli API Dokรผmanlarฤฑ { #interactive-api-docs } + +ลžimdi http://192.168.99.100/docs veya http://127.0.0.1/docs adresine gidebilirsiniz (ya da Docker host'unuzla eลŸdeฤŸeri). + +Otomatik etkileลŸimli API dokรผmantasyonunu gรถrรผrsรผnรผz ( Swagger UI tarafฤฑndan saฤŸlanฤฑr): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Alternatif API Dokรผmanlarฤฑ { #alternative-api-docs } + +Ayrฤฑca http://192.168.99.100/redoc veya http://127.0.0.1/redoc adresine de gidebilirsiniz (ya da Docker host'unuzla eลŸdeฤŸeri). + +Alternatif otomatik dokรผmantasyonu gรถrรผrsรผnรผz (ReDoc tarafฤฑndan saฤŸlanฤฑr): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Tek Dosyalฤฑk FastAPI ile Docker Image OluลŸturma { #build-a-docker-image-with-a-single-file-fastapi } + +FastAPI uygulamanฤฑz tek bir dosyaysa; รถrneฤŸin `./app` dizini olmadan sadece `main.py` varsa, dosya yapฤฑnฤฑz ลŸรถyle olabilir: + +``` +. +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ main.py +โ””โ”€โ”€ requirements.txt +``` + +Bu durumda `Dockerfile` iรงinde dosyayฤฑ kopyaladฤฑฤŸฤฑnฤฑz path'leri buna gรถre deฤŸiลŸtirmeniz yeterlidir: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. `main.py` dosyasฤฑnฤฑ doฤŸrudan `/code` dizinine kopyalayฤฑn (herhangi bir `./app` dizini olmadan). + +2. Tek dosya olan `main.py` iรงindeki uygulamanฤฑzฤฑ sunmak iรงin `fastapi run` kullanฤฑn. + +Dosyayฤฑ `fastapi run`'a verdiฤŸinizde, bunun bir package'ฤฑn parรงasฤฑ deฤŸil tek bir dosya olduฤŸunu otomatik olarak algฤฑlar; nasฤฑl import edip FastAPI uygulamanฤฑzฤฑ nasฤฑl serve edeceฤŸini bilir. ๐Ÿ˜Ž + +## Deployment Kavramlarฤฑ { #deployment-concepts } + +Aynฤฑ [Deployment Kavramlarฤฑ](concepts.md){.internal-link target=_blank}nฤฑ bu kez container'lar aรงฤฑsฤฑndan tekrar konuลŸalฤฑm. + +Container'lar, bir uygulamayฤฑ **build etme ve deploy etme** sรผrecini basitleลŸtiren bir araรงtฤฑr. Ancak bu **deployment kavramlarฤฑ**nฤฑ ele almak iรงin belirli bir yaklaลŸฤฑmฤฑ zorunlu kฤฑlmazlar; birkaรง farklฤฑ strateji mรผmkรผndรผr. + +**ฤฐyi haber** ลŸu: Hangi stratejiyi seรงerseniz seรงin, deployment kavramlarฤฑnฤฑn tamamฤฑnฤฑ kapsayacak bir yol vardฤฑr. ๐ŸŽ‰ + +Bu **deployment kavramlarฤฑ**nฤฑ container'lar aรงฤฑsฤฑndan gรถzden geรงirelim: + +* HTTPS +* Startup'ta รงalฤฑลŸtฤฑrma +* Restart'lar +* Replication (รงalฤฑลŸan process sayฤฑsฤฑ) +* Memory +* BaลŸlatmadan รถnceki adฤฑmlar + +## HTTPS { #https } + +Bir FastAPI uygulamasฤฑnฤฑn sadece **container image**'ฤฑna (ve sonra รงalฤฑลŸan **container**'a) odaklanฤฑrsak, HTTPS genellikle **haricen** baลŸka bir araรงla ele alฤฑnฤฑr. + +ร–rneฤŸin Traefik kullanan baลŸka bir container olabilir; **HTTPS** ve **sertifika**larฤฑn **otomatik** alฤฑnmasฤฑnฤฑ o yรถnetebilir. + +/// tip | ฤฐpucu + +Traefik; Docker, Kubernetes ve diฤŸerleriyle entegre รงalฤฑลŸฤฑr. Bu sayede container'larฤฑnฤฑz iรงin HTTPS'i kurup yapฤฑlandฤฑrmak oldukรงa kolaydฤฑr. + +/// + +Alternatif olarak HTTPS, bir cloud provider'ฤฑn sunduฤŸu servislerden biri tarafฤฑndan da yรถnetilebilir (uygulama yine container iรงinde รงalฤฑลŸฤฑrken). + +## Startup'ta ร‡alฤฑลŸtฤฑrma ve Restart'lar { #running-on-startup-and-restarts } + +Container'ฤฑnฤฑzฤฑ **baลŸlatฤฑp รงalฤฑลŸtฤฑrmaktan** sorumlu genellikle baลŸka bir araรง olur. + +Bu; doฤŸrudan **Docker**, **Docker Compose**, **Kubernetes**, bir **cloud service** vb. olabilir. + +ร‡oฤŸu (veya tรผm) durumda, container'ฤฑ startup'ta รงalฤฑลŸtฤฑrmayฤฑ ve hata durumlarฤฑnda restart'larฤฑ etkinleลŸtirmeyi saฤŸlayan basit bir seรงenek vardฤฑr. ร–rneฤŸin Docker'da bu, `--restart` komut satฤฑrฤฑ seรงeneฤŸidir. + +Container kullanmadan, uygulamalarฤฑ startup'ta รงalฤฑลŸtฤฑrmak ve restart mekanizmasฤฑ eklemek zahmetli ve zor olabilir. Ancak **container'larla รงalฤฑลŸฤฑrken** รงoฤŸu zaman bu iลŸlevler varsayฤฑlan olarak hazฤฑr gelir. โœจ + +## Replication - Process Sayฤฑsฤฑ { #replication-number-of-processes } + +Kubernetes, Docker Swarm Mode, Nomad veya benzeri, birden fazla makinede daฤŸฤฑtฤฑk container'larฤฑ yรถneten karmaลŸฤฑk bir sistemle kurulmuลŸ bir cluster'ฤฑnฤฑz varsa, replication'ฤฑ her container iรงinde bir **process manager** (รถr. worker'lฤฑ Uvicorn) kullanarak yรถnetmek yerine, muhtemelen **cluster seviyesinde** ele almak istersiniz. + +Kubernetes gibi daฤŸฤฑtฤฑk container yรถnetim sistemleri, gelen request'ler iรงin **load balancing** desteฤŸi sunarken aynฤฑ zamanda **container replication**'ฤฑnฤฑ yรถnetmek iรงin entegre mekanizmalara sahiptir. Hepsi **cluster seviyesinde**. + +Bu tรผr durumlarda, yukarฤฑda [anlatฤฑldฤฑฤŸฤฑ gibi](#dockerfile) baฤŸฤฑmlฤฑlฤฑklarฤฑ yรผkleyip **sฤฑfฤฑrdan bir Docker image** build etmek ve birden fazla Uvicorn worker kullanmak yerine **tek bir Uvicorn process** รงalฤฑลŸtฤฑrmak istersiniz. + +### Load Balancer { #load-balancer } + +Container'lar kullanฤฑrken, genellikle ana port'ta dinleyen bir bileลŸen olur. Bu, **HTTPS**'i ele almak iรงin bir **TLS Termination Proxy** olan baลŸka bir container da olabilir ya da benzeri bir araรง olabilir. + +Bu bileลŸen request'lerin **yรผkรผnรผ** alฤฑp worker'lar arasฤฑnda (umarฤฑm) **dengeli** ลŸekilde daฤŸฤฑttฤฑฤŸฤฑ iรงin yaygฤฑn olarak **Load Balancer** diye de adlandฤฑrฤฑlฤฑr. + +/// tip | ฤฐpucu + +HTTPS iรงin kullanฤฑlan aynฤฑ **TLS Termination Proxy** bileลŸeni muhtemelen bir **Load Balancer** olarak da รงalฤฑลŸฤฑr. + +/// + +Container'larla รงalฤฑลŸฤฑrken, onlarฤฑ baลŸlatฤฑp yรถnettiฤŸiniz sistem; bu **load balancer**'dan (aynฤฑ zamanda **TLS Termination Proxy** de olabilir) uygulamanฤฑzฤฑn bulunduฤŸu container(lar)a **network communication**'ฤฑ (รถr. HTTP request'leri) iletmek iรงin zaten dahili araรงlar sunar. + +### Tek Load Balancer - ร‡oklu Worker Container { #one-load-balancer-multiple-worker-containers } + +**Kubernetes** veya benzeri daฤŸฤฑtฤฑk container yรถnetim sistemleriyle รงalฤฑลŸฤฑrken, dahili aฤŸ mekanizmalarฤฑ sayesinde ana **port**'u dinleyen tek bir **load balancer**, uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran muhtemelen **birden fazla container**'a request'leri iletebilir. + +Uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran bu container'larฤฑn her birinde normalde **tek bir process** olur (รถr. FastAPI uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑran bir Uvicorn process). Hepsi aynฤฑ ลŸeyi รงalฤฑลŸtฤฑran **รถzdeลŸ container**'lardฤฑr; ancak her birinin kendi process'i, memory'si vb. vardฤฑr. Bรถylece CPU'nun **farklฤฑ core**'larฤฑnda, hatta **farklฤฑ makinelerde** paralelleลŸtirmeden yararlanฤฑrsฤฑnฤฑz. + +Load balancer'lฤฑ daฤŸฤฑtฤฑk sistem, request'leri uygulamanฤฑzฤฑn bulunduฤŸu container'larฤฑn her birine sฤฑrayla **daฤŸฤฑtฤฑr**. Bรถylece her request, uygulamanฤฑzฤฑn birden fazla **replicated container**'ฤฑndan biri tarafฤฑndan iลŸlenebilir. + +Ve bu **load balancer** normalde cluster'ฤฑnฤฑzdaki *diฤŸer* uygulamalara giden request'leri de (รถr. farklฤฑ bir domain ya da farklฤฑ bir URL path prefix altฤฑnda) yรถnetebilir ve iletiลŸimi o *diฤŸer* uygulamanฤฑn doฤŸru container'larฤฑna iletir. + +### Container BaลŸฤฑna Tek Process { #one-process-per-container } + +Bu senaryoda, replication'ฤฑ zaten cluster seviyesinde yaptฤฑฤŸฤฑnฤฑz iรงin, muhtemelen **container baลŸฤฑna tek bir (Uvicorn) process** istersiniz. + +Dolayฤฑsฤฑyla bu durumda container iรงinde `--workers` gibi bir komut satฤฑrฤฑ seรงeneฤŸiyle รงoklu worker istemezsiniz. Container baลŸฤฑna sadece **tek bir Uvicorn process** istersiniz (ama muhtemelen birden fazla container). + +Container iรงine ekstra bir process manager koymak (รงoklu worker gibi) รงoฤŸu zaman zaten cluster sisteminizle รงรถzdรผฤŸรผnรผz ลŸeye ek **gereksiz karmaลŸฤฑklฤฑk** katar. + +### Birden Fazla Process'li Container'lar ve ร–zel Durumlar { #containers-with-multiple-processes-and-special-cases } + +Elbette bazฤฑ **รถzel durumlarda** bir container iรงinde birden fazla **Uvicorn worker process** รงalฤฑลŸtฤฑrmak isteyebilirsiniz. + +Bu durumlarda รงalฤฑลŸtฤฑrmak istediฤŸiniz worker sayฤฑsฤฑnฤฑ `--workers` komut satฤฑrฤฑ seรงeneฤŸiyle ayarlayabilirsiniz: + +```{ .dockerfile .annotate } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. Burada worker sayฤฑsฤฑnฤฑ 4 yapmak iรงin `--workers` komut satฤฑrฤฑ seรงeneฤŸini kullanฤฑyoruz. + +Bunun mantฤฑklฤฑ olabileceฤŸi birkaรง รถrnek: + +#### Basit Bir Uygulama { #a-simple-app } + +Uygulamanฤฑz tek bir server รผzerinde (cluster deฤŸil) รงalฤฑลŸacak kadar **basitse**, container iรงinde bir process manager isteyebilirsiniz. + +#### Docker Compose { #docker-compose } + +**Docker Compose** ile **tek bir server**'a (cluster deฤŸil) deploy ediyor olabilirsiniz. Bu durumda, paylaลŸฤฑlan aฤŸฤฑ ve **load balancing**'i koruyarak container replication'ฤฑnฤฑ (Docker Compose ile) yรถnetmenin kolay bir yolu olmayabilir. + +Bu durumda, tek bir container iรงinde **bir process manager** ile **birden fazla worker process** baลŸlatmak isteyebilirsiniz. + +--- + +Ana fikir ลŸu: Bunlarฤฑn **hiรงbiri** kรถrรผ kรถrรผne uymanฤฑz gereken **deฤŸiลŸmez kurallar** deฤŸildir. Bu fikirleri, kendi kullanฤฑm senaryonuzu **deฤŸerlendirmek** ve sisteminiz iรงin en iyi yaklaลŸฤฑmฤฑ seรงmek iรงin kullanabilirsiniz. ลžu kavramlarฤฑ nasฤฑl yรถneteceฤŸinize bakarak karar verin: + +* Gรผvenlik - HTTPS +* Startup'ta รงalฤฑลŸtฤฑrma +* Restart'lar +* Replication (รงalฤฑลŸan process sayฤฑsฤฑ) +* Memory +* BaลŸlatmadan รถnceki adฤฑmlar + +## Memory { #memory } + +**Container baลŸฤฑna tek process** รงalฤฑลŸtฤฑrฤฑrsanฤฑz, her container'ฤฑn tรผketeceฤŸi memory miktarฤฑ aลŸaฤŸฤฑ yukarฤฑ tanฤฑmlฤฑ, stabil ve sฤฑnฤฑrlฤฑ olur (replication varsa birden fazla container iรงin). + +Sonra aynฤฑ memory limit ve gereksinimlerini container yรถnetim sisteminizin (รถr. **Kubernetes**) konfigรผrasyonlarฤฑnda belirleyebilirsiniz. Bรถylece sistem; ihtiyaรง duyulan memory miktarฤฑnฤฑ ve cluster'daki makinelerde mevcut memory'yi dikkate alarak **uygun makinelerde container'larฤฑ replicate edebilir**. + +Uygulamanฤฑz **basitse**, muhtemelen bu **bir sorun olmaz** ve katฤฑ memory limitleri belirlemeniz gerekmeyebilir. Ancak **รงok memory kullanฤฑyorsanฤฑz** (รถr. **machine learning** modelleriyle), ne kadar memory tรผkettiฤŸinizi kontrol edip **her makinede** รงalฤฑลŸacak **container sayฤฑsฤฑnฤฑ** ayarlamalฤฑsฤฑnฤฑz (ve gerekirse cluster'a daha fazla makine eklemelisiniz). + +**Container baลŸฤฑna birden fazla process** รงalฤฑลŸtฤฑrฤฑrsanฤฑz, baลŸlatฤฑlan process sayฤฑsฤฑnฤฑn mevcut olandan **fazla memory tรผketmediฤŸinden** emin olmanฤฑz gerekir. + +## BaลŸlatmadan ร–nceki Adฤฑmlar ve Container'lar { #previous-steps-before-starting-and-containers } + +Container kullanฤฑyorsanฤฑz (รถrn. Docker, Kubernetes), temelde iki yaklaลŸฤฑm vardฤฑr. + +### Birden Fazla Container { #multiple-containers } + +**Birden fazla container**'ฤฑnฤฑz varsa ve muhtemelen her biri **tek process** รงalฤฑลŸtฤฑrฤฑyorsa (รถr. bir **Kubernetes** cluster'ฤฑnda), replication yapฤฑlan worker container'lar รงalฤฑลŸmadan **รถnce**, **baลŸlatmadan รถnceki adฤฑmlar**ฤฑn iลŸini yapan **ayrฤฑ bir container** kullanmak isteyebilirsiniz (tek container, tek process). + +/// info | Bilgi + +Kubernetes kullanฤฑyorsanฤฑz, bu muhtemelen bir Init Container olur. + +/// + +Kullanฤฑm senaryonuzda bu adฤฑmlarฤฑ **paralel olarak birden fazla kez** รงalฤฑลŸtฤฑrmak sorun deฤŸilse (รถrneฤŸin veritabanฤฑ migration รงalฤฑลŸtฤฑrmฤฑyor, sadece veritabanฤฑ hazฤฑr mฤฑ diye kontrol ediyorsanฤฑz), o zaman her container'da ana process baลŸlamadan hemen รถnce de รงalฤฑลŸtฤฑrabilirsiniz. + +### Tek Container { #single-container } + +Basit bir kurulumda; **tek bir container** olup onun iรงinde birden fazla **worker process** (ya da sadece bir process) baลŸlatฤฑyorsanฤฑz, bu adฤฑmlarฤฑ aynฤฑ container iรงinde, uygulama process'ini baลŸlatmadan hemen รถnce รงalฤฑลŸtฤฑrabilirsiniz. + +### Base Docker Image { #base-docker-image } + +Eskiden resmi bir FastAPI Docker image'ฤฑ vardฤฑ: tiangolo/uvicorn-gunicorn-fastapi. Ancak artฤฑk kullanฤฑmdan kaldฤฑrฤฑldฤฑ (deprecated). โ›”๏ธ + +Muhtemelen bu base Docker image'ฤฑnฤฑ (veya benzeri baลŸka bir image'ฤฑ) kullanmamalฤฑsฤฑnฤฑz. + +**Kubernetes** (veya diฤŸerleri) kullanฤฑyor ve cluster seviyesinde birden fazla **container** ile **replication** ayarlฤฑyorsanฤฑz, bu durumda yukarฤฑda anlatฤฑldฤฑฤŸฤฑ gibi **sฤฑfฤฑrdan bir image build etmek** daha iyi olur: [FastAPI iรงin Docker Image OluลŸturalฤฑm](#build-a-docker-image-for-fastapi). + +Ve birden fazla worker gerekiyorsa, sadece `--workers` komut satฤฑrฤฑ seรงeneฤŸini kullanabilirsiniz. + +/// note | Teknik Detaylar + +Bu Docker image, Uvicorn dead worker'larฤฑ yรถnetmeyi ve yeniden baลŸlatmayฤฑ desteklemediฤŸi dรถnemde oluลŸturulmuลŸtu. Bu yรผzden Uvicorn ile birlikte Gunicorn kullanmak gerekiyordu; sฤฑrf Gunicorn, Uvicorn worker process'lerini yรถnetip yeniden baลŸlatsฤฑn diye oldukรงa fazla karmaลŸฤฑklฤฑk ekleniyordu. + +Ancak artฤฑk Uvicorn (ve `fastapi` komutu) `--workers` kullanฤฑmฤฑnฤฑ desteklediฤŸine gรถre, kendi image'ฤฑnฤฑzฤฑ build etmek yerine bir base Docker image kullanmanฤฑn bir nedeni kalmadฤฑ (kod miktarฤฑ da hemen hemen aynฤฑ ๐Ÿ˜…). + +/// + +## Container Image'ฤฑ Deploy Etme { #deploy-the-container-image } + +Bir Container (Docker) Image'ฤฑnฤฑz olduktan sonra bunu deploy etmenin birkaรง yolu vardฤฑr. + +ร–rneฤŸin: + +* Tek bir server'da **Docker Compose** ile +* Bir **Kubernetes** cluster'ฤฑ ile +* Docker Swarm Mode cluster'ฤฑ ile +* Nomad gibi baลŸka bir araรงla +* Container image'ฤฑnฤฑzฤฑ alฤฑp deploy eden bir cloud servisiyle + +## `uv` ile Docker Image { #docker-image-with-uv } + +Projenizi yรผklemek ve yรถnetmek iรงin uv kullanฤฑyorsanฤฑz, onlarฤฑn uv Docker rehberini takip edebilirsiniz. + +## ร–zet { #recap } + +Container sistemleri (รถrn. **Docker** ve **Kubernetes** ile) kullanฤฑnca tรผm **deployment kavramlarฤฑ**nฤฑ ele almak oldukรงa kolaylaลŸฤฑr: + +* HTTPS +* Startup'ta รงalฤฑลŸtฤฑrma +* Restart'lar +* Replication (รงalฤฑลŸan process sayฤฑsฤฑ) +* Memory +* BaลŸlatmadan รถnceki adฤฑmlar + +ร‡oฤŸu durumda bir base image kullanmak istemezsiniz; bunun yerine resmi Python Docker image'ฤฑnฤฑ temel alarak **sฤฑfฤฑrdan bir container image** build edersiniz. + +`Dockerfile` iรงindeki talimatlarฤฑn **sฤฑrasฤฑna** ve **Docker cache**'ine dikkat ederek **build sรผrelerini minimize edebilir**, รผretkenliฤŸinizi artฤฑrabilirsiniz (ve beklerken sฤฑkฤฑlmayฤฑ รถnlersiniz). ๐Ÿ˜Ž diff --git a/docs/tr/docs/deployment/fastapicloud.md b/docs/tr/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..bb861273be --- /dev/null +++ b/docs/tr/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +FastAPI uygulamanฤฑzฤฑ FastAPI Cloud'a **tek bir komutla** deploy edebilirsiniz. Henรผz yapmadฤฑysanฤฑz gidip bekleme listesine katฤฑlฤฑn. ๐Ÿš€ + +## GiriลŸ Yapma { #login } + +ร–nceden bir **FastAPI Cloud** hesabฤฑnฤฑz olduฤŸundan emin olun (sizi bekleme listesinden davet ettik ๐Ÿ˜‰). + +Ardฤฑndan giriลŸ yapฤฑn: + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## Deploy { #deploy } + +ลžimdi uygulamanฤฑzฤฑ **tek bir komutla** deploy edin: + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Hepsi bu! Artฤฑk uygulamanฤฑza o URL รผzerinden eriลŸebilirsiniz. โœจ + +## FastAPI Cloud Hakkฤฑnda { #about-fastapi-cloud } + +**FastAPI Cloud**, **FastAPI**'nin arkasฤฑndaki aynฤฑ yazar ve ekip tarafฤฑndan geliลŸtirilmiลŸtir. + +Bir API'yi minimum eforla **geliลŸtirme**, **deploy etme** ve **eriลŸilebilir kฤฑlma** sรผrecini sadeleลŸtirir. + +FastAPI ile uygulama geliลŸtirirken elde ettiฤŸiniz aynฤฑ **developer experience**'ฤฑ, onlarฤฑ buluta **deploy etmeye** de taลŸฤฑr. ๐ŸŽ‰ + +Ayrฤฑca bir uygulamayฤฑ deploy ederken ihtiyaรง duyacaฤŸฤฑnฤฑz pek รงok ลŸeyi de sizin iรงin halleder; รถrneฤŸin: + +* HTTPS +* Replication (รงoฤŸaltma), request'lere gรถre autoscaling ile +* vb. + +FastAPI Cloud, *FastAPI and friends* aรงฤฑk kaynak projelerinin birincil sponsoru ve finansman saฤŸlayฤฑcฤฑsฤฑdฤฑr. โœจ + +## DiฤŸer cloud saฤŸlayฤฑcฤฑlarฤฑna deploy etme { #deploy-to-other-cloud-providers } + +FastAPI aรงฤฑk kaynaklฤฑdฤฑr ve standartlara dayanฤฑr. FastAPI uygulamalarฤฑnฤฑ seรงtiฤŸiniz herhangi bir cloud saฤŸlayฤฑcฤฑsฤฑna deploy edebilirsiniz. + +FastAPI uygulamalarฤฑnฤฑ deploy etmek iรงin cloud saฤŸlayฤฑcฤฑnฤฑzฤฑn kendi kฤฑlavuzlarฤฑnฤฑ takip edin. ๐Ÿค“ + +## Kendi server'ฤฑnฤฑza deploy etme { #deploy-your-own-server } + +Bu **Deployment** kฤฑlavuzunun ilerleyen bรถlรผmlerinde tรผm detaylarฤฑ da ele alacaฤŸฤฑz; bรถylece neler olduฤŸunu, nelerin gerรงekleลŸmesi gerektiฤŸini ve FastAPI uygulamalarฤฑnฤฑ kendi baลŸฤฑnฤฑza (kendi server'larฤฑnฤฑzla da) nasฤฑl deploy edebileceฤŸinizi anlayacaksฤฑnฤฑz. ๐Ÿค“ diff --git a/docs/tr/docs/deployment/https.md b/docs/tr/docs/deployment/https.md new file mode 100644 index 0000000000..bb70883aa7 --- /dev/null +++ b/docs/tr/docs/deployment/https.md @@ -0,0 +1,231 @@ +# HTTPS Hakkฤฑnda { #about-https } + +HTTPSโ€™in sadece "aรงฤฑk" ya da "kapalฤฑ" olan bir ลŸey olduฤŸunu dรผลŸรผnmek kolaydฤฑr. + +Ancak bundan รงok daha karmaลŸฤฑktฤฑr. + +/// tip | ฤฐpucu + +Aceleniz varsa veya รงok da รถnemsemiyorsanฤฑz, her ลŸeyi farklฤฑ tekniklerle adฤฑm adฤฑm kurmak iรงin sonraki bรถlรผmlere geรงin. + +/// + +Bir kullanฤฑcฤฑ gรถzรผyle **HTTPSโ€™in temellerini รถฤŸrenmek** iรงin https://howhttps.works/ adresine bakฤฑn. + +ลžimdi de **geliลŸtirici perspektifinden**, HTTPS hakkฤฑnda dรผลŸรผnรผrken akฤฑlda tutulmasฤฑ gereken birkaรง nokta: + +* HTTPS iรงin **server**โ€™ฤฑn, **รผรงรผncรผ bir taraf** tarafฤฑndan verilen **"sertifikalara"** sahip olmasฤฑ gerekir. + * Bu sertifikalar aslฤฑnda รผรงรผncรผ tarafรงa "รผretilmez", รผรงรผncรผ taraftan **temin edilir**. +* Sertifikalarฤฑn bir **geรงerlilik sรผresi** vardฤฑr. + * Sรผresi **dolar**. + * Sonrasฤฑnda **yenilenmeleri**, รผรงรผncรผ taraftan **yeniden temin edilmeleri** gerekir. +* BaฤŸlantฤฑnฤฑn ลŸifrelenmesi **TCP seviyesinde** gerรงekleลŸir. + * Bu, **HTTPโ€™nin bir katman altฤฑdฤฑr**. + * Dolayฤฑsฤฑyla **sertifika ve ลŸifreleme** iลŸlemleri **HTTPโ€™den รถnce** yapฤฑlฤฑr. +* **TCP "domain"leri bilmez**. Yalnฤฑzca IP adreslerini bilir. + * ฤฐstenen **spesifik domain** bilgisi **HTTP verisinin** iรงindedir. +* **HTTPS sertifikalarฤฑ** belirli bir **domain**โ€™i "sertifikalandฤฑrฤฑr"; ancak protokol ve ลŸifreleme TCP seviyesinde, hangi domain ile รงalฤฑลŸฤฑldฤฑฤŸฤฑ **henรผz bilinmeden** gerรงekleลŸir. +* **Varsayฤฑlan olarak** bu, IP adresi baลŸฤฑna yalnฤฑzca **bir HTTPS sertifikasฤฑ** olabileceฤŸi anlamฤฑna gelir. + * Serverโ€™ฤฑnฤฑz ne kadar bรผyรผk olursa olsun ya da รผzerindeki her uygulama ne kadar kรผรงรผk olursa olsun. + * Ancak bunun bir **รงรถzรผmรผ** vardฤฑr. +* **TLS** protokolรผne (TCP seviyesinde, HTTPโ€™den รถnce ลŸifrelemeyi yapan) eklenen **SNI** adlฤฑ bir **extension** vardฤฑr. + * Bu SNI extensionโ€™ฤฑ, tek bir serverโ€™ฤฑn (tek bir **IP adresiyle**) **birden fazla HTTPS sertifikasฤฑ** kullanmasฤฑna ve **birden fazla HTTPS domain/uygulama** sunmasฤฑna izin verir. + * Bunun รงalฤฑลŸmasฤฑ iรงin server รผzerinde, **public IP adresini** dinleyen tek bir bileลŸenin (programฤฑn) serverโ€™daki **tรผm HTTPS sertifikalarฤฑna** sahip olmasฤฑ gerekir. +* Gรผvenli bir baฤŸlantฤฑ elde edildikten **sonra**, iletiลŸim protokolรผ **hรขlรข HTTP**โ€™dir. + * ฤฐรงerikler, **HTTP protokolรผ** ile gรถnderiliyor olsa bile **ลŸifrelenmiลŸtir**. + +Yaygฤฑn yaklaลŸฤฑm, serverโ€™da (makine, host vb.) รงalฤฑลŸan **tek bir program/HTTP server** bulundurup **HTTPS ile ilgili tรผm kฤฑsฤฑmlarฤฑ** yรถnetmektir: **ลŸifreli HTTPS request**โ€™leri almak, aynฤฑ serverโ€™da รงalฤฑลŸan gerรงek HTTP uygulamasฤฑna (bu รถrnekte **FastAPI** uygulamasฤฑ) **ลŸifresi รงรถzรผlmรผลŸ HTTP request**โ€™leri iletmek, uygulamadan gelen **HTTP response**โ€™u almak, uygun **HTTPS sertifikasฤฑ** ile **ลŸifrelemek** ve **HTTPS** ile clientโ€™a geri gรถndermek. Bu serverโ€™a รงoฤŸu zaman **TLS Termination Proxy** denir. + +TLS Termination Proxy olarak kullanabileceฤŸiniz seรงeneklerden bazฤฑlarฤฑ: + +* Traefik (sertifika yenilemelerini de yรถnetebilir) +* Caddy (sertifika yenilemelerini de yรถnetebilir) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Let's Encryptโ€™ten รถnce bu **HTTPS sertifikalarฤฑ**, gรผvenilen รผรงรผncรผ taraflar tarafฤฑndan satฤฑlฤฑrdฤฑ. + +Bu sertifikalardan birini temin etme sรผreci zahmetliydi, epey evrak iลŸi gerektirirdi ve sertifikalar oldukรงa pahalฤฑydฤฑ. + +Sonra **Let's Encrypt** ortaya รงฤฑktฤฑ. + +Linux Foundationโ€™ฤฑn bir projesidir. **HTTPS sertifikalarฤฑnฤฑ รผcretsiz** ve otomatik bir ลŸekilde saฤŸlar. Bu sertifikalar tรผm standart kriptografik gรผvenliฤŸi kullanฤฑr ve kฤฑsa รถmรผrlรผdรผr (yaklaลŸฤฑk 3 ay). Bu yรผzden, รถmรผrleri kฤฑsa olduฤŸu iรงin **gรผvenlik aslฤฑnda daha iyidir**. + +Domainโ€™ler gรผvenli ลŸekilde doฤŸrulanฤฑr ve sertifikalar otomatik รผretilir. Bu sayede sertifikalarฤฑn yenilenmesini otomatikleลŸtirmek de mรผmkรผn olur. + +Amaรง, bu sertifikalarฤฑn temin edilmesi ve yenilenmesini otomatikleลŸtirerek **รผcretsiz, kalฤฑcฤฑ olarak gรผvenli HTTPS** saฤŸlamaktฤฑr. + +## GeliลŸtiriciler ฤฐรงin HTTPS { #https-for-developers } + +Burada, bir HTTPS APIโ€™nin adฤฑm adฤฑm nasฤฑl gรถrรผnebileceฤŸine dair, รถzellikle geliลŸtiriciler iรงin รถnemli fikirlere odaklanan bir รถrnek var. + +### Domain Adฤฑ { #domain-name } + +Muhtemelen her ลŸey, bir **domain adฤฑ** **temin etmenizle** baลŸlar. Sonra bunu bir DNS serverโ€™ฤฑnda (muhtemelen aynฤฑ cloud providerโ€™ฤฑnฤฑzda) yapฤฑlandฤฑrฤฑrsฤฑnฤฑz. + +Muhtemelen bir cloud server (virtual machine) ya da benzeri bir ลŸey alฤฑrsฤฑnฤฑz ve bunun fixed bir **public IP adresi** olur. + +DNS server(lar)ฤฑnda, bir kaydฤฑ ("`A record`") **domain**โ€™inizi serverโ€™ฤฑnฤฑzฤฑn **public IP adresine** yรถnlendirecek ลŸekilde yapฤฑlandฤฑrฤฑrsฤฑnฤฑz. + +Bunu bรผyรผk olasฤฑlฤฑkla ilk kurulumda, sadece bir kez yaparsฤฑnฤฑz. + +/// tip | ฤฐpucu + +Bu Domain Adฤฑ kฤฑsmฤฑ HTTPSโ€™ten รงok daha รถnce gelir. Ancak her ลŸey domain ve IP adresine baฤŸlฤฑ olduฤŸu iรงin burada bahsetmeye deฤŸer. + +/// + +### DNS { #dns } + +ลžimdi gerรงek HTTPS parรงalarฤฑna odaklanalฤฑm. + +ร–nce tarayฤฑcฤฑ, bu รถrnekte `someapp.example.com` olan domain iรงin **IP**โ€™nin ne olduฤŸunu **DNS server**โ€™larฤฑna sorar. + +DNS serverโ€™larฤฑ tarayฤฑcฤฑya belirli bir **IP adresini** kullanmasฤฑnฤฑ sรถyler. Bu, DNS serverโ€™larฤฑnda yapฤฑlandฤฑrdฤฑฤŸฤฑnฤฑz ve serverโ€™ฤฑnฤฑzฤฑn kullandฤฑฤŸฤฑ public IP adresidir. + + + +### TLS Handshake BaลŸlangฤฑcฤฑ { #tls-handshake-start } + +Tarayฤฑcฤฑ daha sonra bu IP adresiyle **443 portu** (HTTPS portu) รผzerinden iletiลŸim kurar. + +ฤฐletiลŸimin ilk kฤฑsmฤฑ, client ile server arasฤฑnda baฤŸlantฤฑyฤฑ kurmak ve hangi kriptografik anahtarlarฤฑn kullanฤฑlacaฤŸฤฑna karar vermek vb. iรงindir. + + + +Client ile server arasฤฑndaki, TLS baฤŸlantฤฑsฤฑnฤฑ kurmaya yรถnelik bu etkileลŸime **TLS handshake** denir. + +### SNI Extensionโ€™ฤฑ ile TLS { #tls-with-sni-extension } + +Serverโ€™da, belirli bir **IP adresindeki** belirli bir **portu** dinleyen **yalnฤฑzca bir process** olabilir. Aynฤฑ IP adresinde baลŸka portlarฤฑ dinleyen baลŸka processโ€™ler olabilir, ancak IP+port kombinasyonu baลŸฤฑna yalnฤฑzca bir tane olur. + +TLS (HTTPS) varsayฤฑlan olarak `443` portunu kullanฤฑr. Yani ihtiyaรง duyacaฤŸฤฑmฤฑz port budur. + +Bu portu yalnฤฑzca bir process dinleyebileceฤŸi iรงin, bunu yapacak process **TLS Termination Proxy** olur. + +TLS Termination Proxy, bir ya da daha fazla **TLS sertifikasฤฑna** (HTTPS sertifikasฤฑ) eriลŸebilir. + +Yukarฤฑda bahsettiฤŸimiz **SNI extension**โ€™ฤฑnฤฑ kullanarak TLS Termination Proxy, bu baฤŸlantฤฑ iรงin elindeki TLS (HTTPS) sertifikalarฤฑndan hangisini kullanacaฤŸฤฑnฤฑ kontrol eder; clientโ€™ฤฑn beklediฤŸi domain ile eลŸleลŸen sertifikayฤฑ seรงer. + +Bu รถrnekte `someapp.example.com` sertifikasฤฑnฤฑ kullanฤฑr. + + + +Client, bu TLS sertifikasฤฑnฤฑ รผreten kuruluลŸa zaten **gรผvenir** (bu รถrnekte Let's Encrypt; birazdan ona da geleceฤŸiz). Bu sayede sertifikanฤฑn geรงerli olduฤŸunu **doฤŸrulayabilir**. + +Ardฤฑndan client ve TLS Termination Proxy, sertifikayฤฑ kullanarak **TCP iletiลŸiminin geri kalanฤฑnฤฑ nasฤฑl ลŸifreleyeceklerine** karar verir. Bรถylece **TLS Handshake** kฤฑsmฤฑ tamamlanฤฑr. + +Bundan sonra client ve server arasฤฑnda **ลŸifreli bir TCP baฤŸlantฤฑsฤฑ** vardฤฑr; TLSโ€™in saฤŸladฤฑฤŸฤฑ ลŸey budur. Sonra bu baฤŸlantฤฑyฤฑ kullanarak gerรงek **HTTP iletiลŸimini** baลŸlatabilirler. + +Ve **HTTPS** de tam olarak budur: ลŸifrelenmemiลŸ bir TCP baฤŸlantฤฑsฤฑ yerine, **gรผvenli bir TLS baฤŸlantฤฑsฤฑnฤฑn iรงinde** dรผz **HTTP**โ€™dir. + +/// tip | ฤฐpucu + +ลžifrelemenin HTTP seviyesinde deฤŸil, **TCP seviyesinde** gerรงekleลŸtiฤŸine dikkat edin. + +/// + +### HTTPS Request { #https-request } + +Artฤฑk client ile server (รถzellikle tarayฤฑcฤฑ ile TLS Termination Proxy) arasฤฑnda **ลŸifreli bir TCP baฤŸlantฤฑsฤฑ** olduฤŸuna gรถre, **HTTP iletiลŸimi** baลŸlayabilir. + +Dolayฤฑsฤฑyla client bir **HTTPS request** gรถnderir. Bu, ลŸifreli bir TLS baฤŸlantฤฑsฤฑ รผzerinden giden bir HTTP requestโ€™tir. + + + +### Requestโ€™in ลžifresini ร‡รถzme { #decrypt-the-request } + +TLS Termination Proxy, รผzerinde anlaลŸฤฑlan ลŸifrelemeyi kullanarak **requestโ€™in ลŸifresini รงรถzer** ve **dรผz (ลŸifresi รงรถzรผlmรผลŸ) HTTP request**โ€™i uygulamayฤฑ รงalฤฑลŸtฤฑran processโ€™e iletir (รถr. FastAPI uygulamasฤฑnฤฑ รงalฤฑลŸtฤฑran Uvicorn processโ€™i). + + + +### HTTP Response { #http-response } + +Uygulama requestโ€™i iลŸler ve TLS Termination Proxyโ€™ye **dรผz (ลŸifrelenmemiลŸ) bir HTTP response** gรถnderir. + + + +### HTTPS Response { #https-response } + +TLS Termination Proxy daha sonra responseโ€™u, daha รถnce รผzerinde anlaลŸฤฑlan kriptografi ile (baลŸlangฤฑcฤฑ `someapp.example.com` sertifikasฤฑna dayanan) **ลŸifreler** ve tarayฤฑcฤฑya geri gรถnderir. + +Sonrasฤฑnda tarayฤฑcฤฑ responseโ€™un geรงerli olduฤŸunu ve doฤŸru kriptografik anahtarla ลŸifrelendiฤŸini doฤŸrular vb. Ardฤฑndan **responseโ€™un ลŸifresini รงรถzer** ve iลŸler. + + + +Client (tarayฤฑcฤฑ), responseโ€™un doฤŸru serverโ€™dan geldiฤŸini bilir; รงรผnkรผ daha รถnce **HTTPS sertifikasฤฑ** ile รผzerinde anlaลŸtฤฑklarฤฑ kriptografiyi kullanmaktadฤฑr. + +### Birden Fazla Uygulama { #multiple-applications } + +Aynฤฑ serverโ€™da (veya serverโ€™larda) รถrneฤŸin baลŸka API programlarฤฑ ya da bir veritabanฤฑ gibi **birden fazla uygulama** olabilir. + +Belirli IP ve port kombinasyonunu yalnฤฑzca bir process yรถnetebilir (รถrneฤŸimizde TLS Termination Proxy). Ancak diฤŸer uygulamalar/processโ€™ler, aynฤฑ **public IP + port kombinasyonunu** kullanmaya รงalฤฑลŸmadฤฑklarฤฑ sรผrece server(lar)da รงalฤฑลŸabilir. + + + +Bu ลŸekilde TLS Termination Proxy, birden fazla uygulama iรงin **birden fazla domain**โ€™in HTTPS ve sertifika iลŸlerini yรถnetebilir ve her durumda requestโ€™leri doฤŸru uygulamaya iletebilir. + +### Sertifika Yenileme { #certificate-renewal } + +Gelecekte bir noktada, her sertifikanฤฑn sรผresi **dolar** (temin edildikten yaklaลŸฤฑk 3 ay sonra). + +Ardฤฑndan baลŸka bir program (bazฤฑ durumlarda ayrฤฑ bir programdฤฑr, bazฤฑ durumlarda aynฤฑ TLS Termination Proxy olabilir) Let's Encrypt ile konuลŸup sertifika(larฤฑ) yeniler. + + + +**TLS sertifikalarฤฑ** bir IP adresiyle deฤŸil, **domain adฤฑyla iliลŸkilidir**. + +Bu yรผzden sertifikalarฤฑ yenilemek iรงin, yenileme programฤฑ otoriteye (Let's Encrypt) gerรงekten o domainโ€™i **"sahiplendiฤŸini" ve kontrol ettiฤŸini** **kanฤฑtlamalฤฑdฤฑr**. + +Bunu yapmak ve farklฤฑ uygulama ihtiyaรงlarฤฑnฤฑ karลŸฤฑlamak iรงin birden fazla yรถntem vardฤฑr. Yaygฤฑn yรถntemlerden bazฤฑlarฤฑ: + +* Bazฤฑ **DNS kayฤฑtlarฤฑnฤฑ deฤŸiลŸtirmek**. + * Bunun iรงin yenileme programฤฑnฤฑn DNS provider APIโ€™lerini desteklemesi gerekir. Dolayฤฑsฤฑyla kullandฤฑฤŸฤฑnฤฑz DNS providerโ€™a baฤŸlฤฑ olarak bu seรงenek mรผmkรผn de olabilir, olmayabilir de. +* Domain ile iliลŸkili public IP adresinde **server olarak รงalฤฑลŸmak** (en azฤฑndan sertifika temin sรผrecinde). + * Yukarฤฑda sรถylediฤŸimiz gibi, belirli bir IP ve portu yalnฤฑzca bir process dinleyebilir. + * Bu, aynฤฑ TLS Termination Proxyโ€™nin sertifika yenileme sรผrecini de yรถnetmesinin neden รงok faydalฤฑ olduฤŸunun sebeplerinden biridir. + * Aksi halde TLS Termination Proxyโ€™yi kฤฑsa sรผreliฤŸine durdurmanฤฑz, sertifikalarฤฑ temin etmek iรงin yenileme programฤฑnฤฑ baลŸlatmanฤฑz, sonra bunlarฤฑ TLS Termination Proxy ile yapฤฑlandฤฑrmanฤฑz ve ardฤฑndan TLS Termination Proxyโ€™yi tekrar baลŸlatmanฤฑz gerekebilir. Bu ideal deฤŸildir; รงรผnkรผ TLS Termination Proxy kapalฤฑyken uygulama(lar)ฤฑnฤฑza eriลŸilemez. + +Uygulamayฤฑ servis etmeye devam ederken tรผm bu yenileme sรผrecini yรถnetebilmek, TLS sertifikalarฤฑnฤฑ doฤŸrudan uygulama serverโ€™ฤฑyla (รถrn. Uvicorn) kullanmak yerine, TLS Termination Proxy ile HTTPSโ€™i yรถnetecek **ayrฤฑ bir sistem** istemenizin baลŸlฤฑca nedenlerinden biridir. + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +HTTPSโ€™i bir proxy ile yรถnetirken, **application server**โ€™ฤฑnฤฑz (รถrneฤŸin FastAPI CLI รผzerinden Uvicorn) HTTPS sรผreci hakkฤฑnda hiรงbir ลŸey bilmez; **TLS Termination Proxy** ile dรผz HTTP รผzerinden iletiลŸim kurar. + +Bu **proxy** normalde requestโ€™i **application server**โ€™a iletmeden รถnce, requestโ€™in proxy tarafฤฑndan **forward** edildiฤŸini application serverโ€™a bildirmek iรงin bazฤฑ HTTP headerโ€™larฤฑnฤฑ anlฤฑk olarak ekler. + +/// note | Teknik Detaylar + +Proxy headerโ€™larฤฑ ลŸunlardฤฑr: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +Buna raฤŸmen **application server**, gรผvenilen bir **proxy** arkasฤฑnda olduฤŸunu bilmediฤŸi iรงin varsayฤฑlan olarak bu headerโ€™lara gรผvenmez. + +Ancak **application server**โ€™ฤฑ, **proxy**โ€™nin gรถnderdiฤŸi *forwarded* headerโ€™larฤฑna gรผvenecek ลŸekilde yapฤฑlandฤฑrabilirsiniz. FastAPI CLI kullanฤฑyorsanฤฑz, hangi IPโ€™lerden gelen *forwarded* headerโ€™lara gรผvenmesi gerektiฤŸini sรถylemek iรงin *CLI Option* `--forwarded-allow-ips` seรงeneฤŸini kullanabilirsiniz. + +ร–rneฤŸin **application server** yalnฤฑzca gรผvenilen **proxy**โ€™den iletiลŸim alฤฑyorsa, yalnฤฑzca **proxy**โ€™nin kullandฤฑฤŸฤฑ IPโ€™den request alacaฤŸฤฑ iรงin `--forwarded-allow-ips="*"` ayarlayฤฑp gelen tรผm IPโ€™lere gรผvenmesini saฤŸlayabilirsiniz. + +Bu sayede uygulama kendi public URLโ€™inin ne olduฤŸunu, HTTPS kullanฤฑp kullanmadฤฑฤŸฤฑnฤฑ, domainโ€™i vb. bilebilir. + +Bu, รถrneฤŸin redirectโ€™leri doฤŸru ลŸekilde yรถnetmek iรงin faydalฤฑdฤฑr. + +/// tip | ฤฐpucu + +Bununla ilgili daha fazlasฤฑnฤฑ [Behind a Proxy - Enable Proxy Forwarded Headers](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} dokรผmantasyonunda รถฤŸrenebilirsiniz. + +/// + +## ร–zet { #recap } + +**HTTPS** kullanmak รงok รถnemlidir ve รงoฤŸu durumda oldukรงa **kritiktir**. GeliลŸtirici olarak HTTPS etrafฤฑnda harcadฤฑฤŸฤฑnฤฑz รงabanฤฑn bรผyรผk kฤฑsmฤฑ, aslฤฑnda **bu kavramlarฤฑ** ve nasฤฑl รงalฤฑลŸtฤฑklarฤฑnฤฑ **anlamaktฤฑr**. + +Ancak **geliลŸtiriciler iรงin HTTPS**โ€™in temel bilgilerini รถฤŸrendikten sonra, her ลŸeyi basitรงe yรถnetmek iรงin farklฤฑ araรงlarฤฑ kolayca birleลŸtirip yapฤฑlandฤฑrabilirsiniz. + +Sonraki bรถlรผmlerin bazฤฑlarฤฑnda, **FastAPI** uygulamalarฤฑ iรงin **HTTPS**โ€™i nasฤฑl kuracaฤŸฤฑnฤฑza dair birkaรง somut รถrnek gรถstereceฤŸim. ๐Ÿ”’ diff --git a/docs/tr/docs/deployment/manually.md b/docs/tr/docs/deployment/manually.md new file mode 100644 index 0000000000..561ba86772 --- /dev/null +++ b/docs/tr/docs/deployment/manually.md @@ -0,0 +1,157 @@ +# Bir Sunucuyu Manuel Olarak ร‡alฤฑลŸtฤฑrฤฑn { #run-a-server-manually } + +## `fastapi run` Komutunu Kullanฤฑn { #use-the-fastapi-run-command } + +Kฤฑsacasฤฑ, FastAPI uygulamanฤฑzฤฑ sunmak iรงin `fastapi run` kullanฤฑn: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +Bu, รงoฤŸu durumda iลŸinizi gรถrรผr. ๐Ÿ˜Ž + +ร–rneฤŸin bu komutu, **FastAPI** app'inizi bir container iรงinde, bir sunucuda vb. baลŸlatmak iรงin kullanabilirsiniz. + +## ASGI Sunucularฤฑ { #asgi-servers } + +ลžimdi biraz daha detaya inelim. + +FastAPI, Python web framework'leri ve sunucularฤฑnฤฑ inลŸa etmek iรงin kullanฤฑlan ASGI adlฤฑ bir standardฤฑ kullanฤฑr. FastAPI bir ASGI web framework'รผdรผr. + +Uzak bir sunucu makinesinde **FastAPI** uygulamasฤฑnฤฑ (veya herhangi bir ASGI uygulamasฤฑnฤฑ) รงalฤฑลŸtฤฑrmak iรงin gereken ana ลŸey, **Uvicorn** gibi bir ASGI server programฤฑdฤฑr. `fastapi` komutuyla varsayฤฑlan olarak gelen de budur. + +Buna alternatif birkaรง seรงenek daha vardฤฑr, รถrneฤŸin: + +* Uvicorn: yรผksek performanslฤฑ bir ASGI server. +* Hypercorn: diฤŸer รถzelliklerin yanฤฑnda HTTP/2 ve Trio ile uyumlu bir ASGI server. +* Daphne: Django Channels iรงin geliลŸtirilmiลŸ ASGI server. +* Granian: Python uygulamalarฤฑ iรงin bir Rust HTTP server. +* NGINX Unit: NGINX Unit, hafif ve รงok yรถnlรผ bir web uygulamasฤฑ runtime'ฤฑdฤฑr. + +## Sunucu Makinesi ve Sunucu Programฤฑ { #server-machine-and-server-program } + +ฤฐsimlendirme konusunda akฤฑlda tutulmasฤฑ gereken kรผรงรผk bir detay var. ๐Ÿ’ก + +"**server**" kelimesi yaygฤฑn olarak hem uzak/bulut bilgisayarฤฑ (fiziksel veya sanal makine) hem de o makinede รงalฤฑลŸan programฤฑ (รถr. Uvicorn) ifade etmek iรงin kullanฤฑlฤฑr. + +Dolayฤฑsฤฑyla genel olarak "server" dendiฤŸinde, bu iki ลŸeyden birini kast ediyor olabilir. + +Uzak makineden bahsederken genelde **server** denir; ayrฤฑca **machine**, **VM** (virtual machine), **node** ifadeleri de kullanฤฑlฤฑr. Bunlarฤฑn hepsi, genellikle Linux รงalฤฑลŸtฤฑran ve รผzerinde programlarฤฑnฤฑzฤฑ รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑz bir tรผr uzak makineyi ifade eder. + +## Sunucu Programฤฑnฤฑ Yรผkleyin { #install-the-server-program } + +FastAPI'yi kurduฤŸunuzda, production sunucusu olarak Uvicorn da beraberinde gelir ve bunu `fastapi run` komutuyla baลŸlatabilirsiniz. + +Ancak bir ASGI server'ฤฑ manuel olarak da kurabilirsiniz. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, etkinleลŸtirdiฤŸinizden emin olun; ardฤฑndan server uygulamasฤฑnฤฑ kurabilirsiniz. + +ร–rneฤŸin Uvicorn'u kurmak iรงin: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +Benzer bir sรผreรง, diฤŸer ASGI server programlarฤฑnฤฑn tamamฤฑ iรงin de geรงerlidir. + +/// tip | ฤฐpucu + +`standard` eklediฤŸinizde Uvicorn, รถnerilen bazฤฑ ek baฤŸฤฑmlฤฑlฤฑklarฤฑ kurar ve kullanฤฑr. + +Bunlara, `asyncio` iรงin yรผksek performanslฤฑ bir drop-in replacement olan ve concurrency performansฤฑnฤฑ ciddi ลŸekilde artฤฑran `uvloop` da dahildir. + +FastAPI'yi `pip install "fastapi[standard]"` gibi bir ลŸekilde kurduฤŸunuzda `uvicorn[standard]` da zaten kurulmuลŸ olur. + +/// + +## Sunucu Programฤฑnฤฑ ร‡alฤฑลŸtฤฑrฤฑn { #run-the-server-program } + +Bir ASGI server'ฤฑ manuel olarak kurduysanฤฑz, FastAPI uygulamanฤฑzฤฑ import edebilmesi iรงin genellikle รถzel bir formatta bir import string geรงirmeniz gerekir: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | Not + +`uvicorn main:app` komutu ลŸunlarฤฑ ifade eder: + +* `main`: `main.py` dosyasฤฑ (Python "module"). +* `app`: `main.py` iรงinde `app = FastAPI()` satฤฑrฤฑyla oluลŸturulan nesne. + +ลžununla eลŸdeฤŸerdir: + +```Python +from main import app +``` + +/// + +Her alternatif ASGI server programฤฑ iรงin benzer bir komut bulunur; daha fazlasฤฑ iรงin ilgili dokรผmantasyonlarฤฑna bakabilirsiniz. + +/// warning | Uyarฤฑ + +Uvicorn ve diฤŸer sunucular, geliลŸtirme sฤฑrasฤฑnda faydalฤฑ olan `--reload` seรงeneฤŸini destekler. + +`--reload` seรงeneฤŸi รงok daha fazla kaynak tรผketir, daha kararsฤฑzdฤฑr vb. + +**GeliลŸtirme** sฤฑrasฤฑnda รงok yardฤฑmcฤฑ olur, ancak **production** ortamฤฑnda kullanmamalฤฑsฤฑnฤฑz. + +/// + +## Deployment Kavramlarฤฑ { #deployment-concepts } + +Bu รถrnekler server programฤฑnฤฑ (รถr. Uvicorn) รงalฤฑลŸtฤฑrฤฑr; **tek bir process** baลŸlatฤฑr, tรผm IP'lerde (`0.0.0.0`) ve รถnceden belirlenmiลŸ bir port'ta (รถr. `80`) dinler. + +Temel fikir budur. Ancak muhtemelen ลŸunlar gibi bazฤฑ ek konularla da ilgilenmek isteyeceksiniz: + +* Gรผvenlik - HTTPS +* AรงฤฑlฤฑลŸta รงalฤฑลŸtฤฑrma +* Yeniden baลŸlatmalar +* Replikasyon (รงalฤฑลŸan process sayฤฑsฤฑ) +* Bellek +* BaลŸlatmadan รถnceki adฤฑmlar + +Sonraki bรถlรผmlerde bu kavramlarฤฑn her birini nasฤฑl dรผลŸรผnmeniz gerektiฤŸini ve bunlarla baลŸa รงฤฑkmak iรงin kullanabileceฤŸiniz somut รถrnekleri/stratejileri anlatacaฤŸฤฑm. ๐Ÿš€ diff --git a/docs/tr/docs/deployment/server-workers.md b/docs/tr/docs/deployment/server-workers.md new file mode 100644 index 0000000000..faae4ef920 --- /dev/null +++ b/docs/tr/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Server Workers - Worker'larla Uvicorn { #server-workers-uvicorn-with-workers } + +ร–nceki bรถlรผmlerde bahsettiฤŸimiz deployment kavramlarฤฑna tekrar bakalฤฑm: + +* Gรผvenlik - HTTPS +* BaลŸlangฤฑรงta รงalฤฑลŸtฤฑrma +* Yeniden baลŸlatmalar +* **Replikasyon (รงalฤฑลŸan process sayฤฑsฤฑ)** +* Bellek +* BaลŸlatmadan รถnceki adฤฑmlar + +Bu noktaya kadar, dokรผmantasyondaki tรผm tutorial'larla muhtemelen bir **server programฤฑ** รงalฤฑลŸtฤฑrฤฑyordunuz; รถrneฤŸin Uvicorn'u รงalฤฑลŸtฤฑran `fastapi` komutunu kullanarak ve **tek bir process** ile. + +Uygulamalarฤฑ deploy ederken, **รงok รงekirdekten (multiple cores)** faydalanmak ve daha fazla request'i karลŸฤฑlayabilmek iรงin bรผyรผk olasฤฑlฤฑkla **process replikasyonu** (birden fazla process) isteyeceksiniz. + +[Daha รถnceki Deployment Concepts](concepts.md){.internal-link target=_blank} bรถlรผmรผnde gรถrdรผฤŸรผnรผz gibi, kullanabileceฤŸiniz birden fazla strateji var. + +Burada, `fastapi` komutunu kullanarak ya da `uvicorn` komutunu doฤŸrudan รงalฤฑลŸtฤฑrarak **worker process**'lerle **Uvicorn**'u nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ gรถstereceฤŸim. + +/// info | Bilgi + +Container kullanฤฑyorsanฤฑz (รถrneฤŸin Docker veya Kubernetes ile), bununla ilgili daha fazlasฤฑnฤฑ bir sonraki bรถlรผmde anlatacaฤŸฤฑm: [Container'larda FastAPI - Docker](docker.md){.internal-link target=_blank}. + +ร–zellikle **Kubernetes** รผzerinde รงalฤฑลŸtฤฑrฤฑrken, bรผyรผk olasฤฑlฤฑkla worker kullanmak **istemeyeceksiniz**; bunun yerine **container baลŸฤฑna tek bir Uvicorn process** รงalฤฑลŸtฤฑrmak daha uygundur. Ancak bunu da o bรถlรผmde detaylandฤฑracaฤŸฤฑm. + +/// + +## Birden Fazla Worker { #multiple-workers } + +Komut satฤฑrฤฑnda `--workers` seรงeneฤŸiyle birden fazla worker baลŸlatabilirsiniz: + +//// tab | `fastapi` + +`fastapi` komutunu kullanฤฑyorsanฤฑz: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +`uvicorn` komutunu doฤŸrudan kullanmayฤฑ tercih ederseniz: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +Buradaki tek yeni seรงenek `--workers`; bu seรงenek Uvicorn'a 4 adet worker process baลŸlatmasฤฑnฤฑ sรถyler. + +Ayrฤฑca her process'in **PID**'inin gรถsterildiฤŸini de gรถrebilirsiniz: parent process iรงin `27365` (bu **process manager**), her worker process iรงin de bir PID: `27368`, `27369`, `27370` ve `27367`. + +## Deployment Kavramlarฤฑ { #deployment-concepts } + +Burada, uygulamanฤฑn รงalฤฑลŸmasฤฑnฤฑ **paralelleลŸtirmek**, CPU'daki **รงok รงekirdekten** yararlanmak ve **daha fazla request** karลŸฤฑlayabilmek iรงin birden fazla **worker**'ฤฑ nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ gรถrdรผnรผz. + +Yukarฤฑdaki deployment kavramlarฤฑ listesinden, worker kullanฤฑmฤฑ aฤŸฤฑrlฤฑklฤฑ olarak **replikasyon** kฤฑsmฤฑna yardฤฑmcฤฑ olur, ayrฤฑca **yeniden baลŸlatmalar** konusunda da az da olsa katkฤฑ saฤŸlar. Ancak diฤŸerlerini yine sizin yรถnetmeniz gerekir: + +* **Gรผvenlik - HTTPS** +* **BaลŸlangฤฑรงta รงalฤฑลŸtฤฑrma** +* ***Yeniden baลŸlatmalar*** +* Replikasyon (รงalฤฑลŸan process sayฤฑsฤฑ) +* **Bellek** +* **BaลŸlatmadan รถnceki adฤฑmlar** + +## Container'lar ve Docker { #containers-and-docker } + +Bir sonraki bรถlรผmde, [Container'larda FastAPI - Docker](docker.md){.internal-link target=_blank} รผzerinden diฤŸer **deployment kavramlarฤฑnฤฑ** ele almak iรงin kullanabileceฤŸiniz bazฤฑ stratejileri anlatacaฤŸฤฑm. + +Tek bir Uvicorn process รงalฤฑลŸtฤฑracak ลŸekilde **sฤฑfฤฑrdan kendi image'ฤฑnฤฑzฤฑ oluลŸturmayฤฑ** gรถstereceฤŸim. Bu oldukรงa basit bir sรผreรงtir ve **Kubernetes** gibi daฤŸฤฑtฤฑk bir container yรถnetim sistemi kullanฤฑrken bรผyรผk olasฤฑlฤฑkla yapmak isteyeceฤŸiniz ลŸey de budur. + +## ร–zet { #recap } + +**ร‡ok รงekirdekli CPU**'lardan faydalanmak ve **birden fazla process'i paralel** รงalฤฑลŸtฤฑrmak iรงin `fastapi` veya `uvicorn` komutlarฤฑyla `--workers` CLI seรงeneฤŸini kullanarak birden fazla worker process รงalฤฑลŸtฤฑrabilirsiniz. + +DiฤŸer deployment kavramlarฤฑnฤฑ da kendiniz ele alarak **kendi deployment sisteminizi** kuruyorsanฤฑz, bu araรงlarฤฑ ve fikirleri kullanabilirsiniz. + +Container'larla (รถrn. Docker ve Kubernetes) **FastAPI**'yi รถฤŸrenmek iรงin bir sonraki bรถlรผme gรถz atฤฑn. Bu araรงlarฤฑn, diฤŸer **deployment kavramlarฤฑnฤฑ** รงรถzmek iรงin de basit yรถntemleri olduฤŸunu gรถreceksiniz. โœจ diff --git a/docs/tr/docs/deployment/versions.md b/docs/tr/docs/deployment/versions.md new file mode 100644 index 0000000000..c3fb5d9bd9 --- /dev/null +++ b/docs/tr/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# FastAPI Sรผrรผmleri Hakkฤฑnda { #about-fastapi-versions } + +**FastAPI** hรขlihazฤฑrda birรงok uygulama ve sistemde production ortamฤฑnda kullanฤฑlmaktadฤฑr. Ayrฤฑca test kapsamฤฑ %100 seviyesinde tutulmaktadฤฑr. Ancak geliลŸtirme sรผreci hรขlรข hฤฑzlฤฑ ลŸekilde ilerlemektedir. + +Yeni รถzellikler sฤฑk sฤฑk eklenir, bug'lar dรผzenli olarak dรผzeltilir ve kod sรผrekli iyileลŸtirilmektedir. + +Bu yรผzden mevcut sรผrรผmler hรขlรข `0.x.x` ลŸeklindedir; bu da her sรผrรผmde breaking change olma ihtimalini yansฤฑtฤฑr. Bu yaklaลŸฤฑm Semantic Versioning kurallarฤฑnฤฑ takip eder. + +ลžu anda **FastAPI** ile production uygulamalarฤฑ geliลŸtirebilirsiniz (muhtemelen bir sรผredir yapฤฑyorsunuz da); sadece kodunuzun geri kalanฤฑyla doฤŸru รงalฤฑลŸan bir sรผrรผm kullandฤฑฤŸฤฑnฤฑzdan emin olmanฤฑz gerekir. + +## `fastapi` sรผrรผmรผnรผ sabitleyin { #pin-your-fastapi-version } + +ฤฐlk yapmanฤฑz gereken, kullandฤฑฤŸฤฑnฤฑz **FastAPI** sรผrรผmรผnรผ uygulamanฤฑzla doฤŸru รงalฤฑลŸtฤฑฤŸฤฑnฤฑ bildiฤŸiniz belirli bir gรผncel sรผrรผme "sabitlemek" (pinlemek) olmalฤฑ. + +ร–rneฤŸin, uygulamanฤฑzda `0.112.0` sรผrรผmรผnรผ kullandฤฑฤŸฤฑnฤฑzฤฑ varsayalฤฑm. + +`requirements.txt` dosyasฤฑ kullanฤฑyorsanฤฑz sรผrรผmรผ ลŸรถyle belirtebilirsiniz: + +```txt +fastapi[standard]==0.112.0 +``` + +Bu, tam olarak `0.112.0` sรผrรผmรผnรผ kullanacaฤŸฤฑnฤฑz anlamฤฑna gelir. + +Ya da ลŸu ลŸekilde de sabitleyebilirsiniz: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +Bu da `0.112.0` ve รผzeri, ama `0.113.0` altฤฑndaki sรผrรผmleri kullanacaฤŸฤฑnฤฑz anlamฤฑna gelir; รถrneฤŸin `0.112.2` gibi bir sรผrรผm de kabul edilir. + +Kurulumlarฤฑ yรถnetmek iรงin `uv`, Poetry, Pipenv gibi baลŸka bir araรง (veya benzerleri) kullanฤฑyorsanฤฑz, bunlarฤฑn hepsinde paketler iรงin belirli sรผrรผmler tanฤฑmlamanฤฑn bir yolu vardฤฑr. + +## Mevcut sรผrรผmler { #available-versions } + +Mevcut sรผrรผmleri (รถr. en gรผncel son sรผrรผmรผn hangisi olduฤŸunu kontrol etmek iรงin) [Release Notes](../release-notes.md){.internal-link target=_blank} sayfasฤฑnda gรถrebilirsiniz. + +## Sรผrรผmler Hakkฤฑnda { #about-versions } + +Semantic Versioning kurallarฤฑna gรถre, `1.0.0` altฤฑndaki herhangi bir sรผrรผm breaking change iรงerebilir. + +FastAPI ayrฤฑca "PATCH" sรผrรผm deฤŸiลŸikliklerinin bug fix'ler ve breaking olmayan deฤŸiลŸiklikler iรงin kullanฤฑlmasฤฑ kuralฤฑnฤฑ da takip eder. + +/// tip | ฤฐpucu + +"PATCH" son sayฤฑdฤฑr. ร–rneฤŸin `0.2.3` iรงinde PATCH sรผrรผmรผ `3`'tรผr. + +/// + +Dolayฤฑsฤฑyla ลŸu ลŸekilde bir sรผrรผme sabitleyebilmelisiniz: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +Breaking change'ler ve yeni รถzellikler "MINOR" sรผrรผmlerde eklenir. + +/// tip | ฤฐpucu + +"MINOR" ortadaki sayฤฑdฤฑr. ร–rneฤŸin `0.2.3` iรงinde MINOR sรผrรผmรผ `2`'dir. + +/// + +## FastAPI Sรผrรผmlerini Yรผkseltme { #upgrading-the-fastapi-versions } + +Uygulamanฤฑz iรงin test'ler eklemelisiniz. + +**FastAPI** ile bu รงok kolaydฤฑr (Starlette sayesinde). Dokรผmantasyona bakฤฑn: [Testing](../tutorial/testing.md){.internal-link target=_blank} + +Test'leriniz olduktan sonra **FastAPI** sรผrรผmรผnรผ daha yeni bir sรผrรผme yรผkseltebilir ve test'lerinizi รงalฤฑลŸtฤฑrarak tรผm kodunuzun doฤŸru รงalฤฑลŸtฤฑฤŸฤฑndan emin olabilirsiniz. + +Her ลŸey รงalฤฑลŸฤฑyorsa (ya da gerekli deฤŸiลŸiklikleri yaptฤฑktan sonra) ve tรผm test'leriniz geรงiyorsa, `fastapi` sรผrรผmรผnรผ o yeni sรผrรผme sabitleyebilirsiniz. + +## Starlette Hakkฤฑnda { #about-starlette } + +`starlette` sรผrรผmรผnรผ sabitlememelisiniz. + +**FastAPI**'nin farklฤฑ sรผrรผmleri, Starlette'in belirli (daha yeni) bir sรผrรผmรผnรผ kullanฤฑr. + +Bu yรผzden **FastAPI**'nin doฤŸru Starlette sรผrรผmรผnรผ kullanmasฤฑna izin verebilirsiniz. + +## Pydantic Hakkฤฑnda { #about-pydantic } + +Pydantic, **FastAPI** iรงin olan test'leri kendi test'lerinin iรงine dahil eder; bu yรผzden Pydantic'in yeni sรผrรผmleri (`1.0.0` รผzeri) her zaman FastAPI ile uyumludur. + +Pydantic'i sizin iรงin รงalฤฑลŸan `1.0.0` รผzerindeki herhangi bir sรผrรผme sabitleyebilirsiniz. + +ร–rneฤŸin: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/tr/docs/environment-variables.md b/docs/tr/docs/environment-variables.md new file mode 100644 index 0000000000..e4f769a16e --- /dev/null +++ b/docs/tr/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Ortam DeฤŸiลŸkenleri { #environment-variables } + +/// tip | ฤฐpucu + +"Ortam deฤŸiลŸkenleri"nin ne olduฤŸunu ve nasฤฑl kullanฤฑlacaฤŸฤฑnฤฑ zaten biliyorsanฤฑz, bu bรถlรผmรผ atlayabilirsiniz. + +/// + +Ortam deฤŸiลŸkeni (genelde "**env var**" olarak da anฤฑlฤฑr), Python kodunun **dฤฑลŸฤฑnda**, **iลŸletim sistemi** seviyesinde bulunan ve Python kodunuz (veya diฤŸer programlar) tarafฤฑndan okunabilen bir deฤŸiลŸkendir. + +Ortam deฤŸiลŸkenleri; uygulama **ayarlarฤฑ**nฤฑ yรถnetmek, Pythonโ€™un **kurulumu**nun bir parรงasฤฑ olarak konfigรผrasyon yapmak vb. durumlarda iลŸe yarar. + +## Env Var OluลŸturma ve Kullanma { #create-and-use-env-vars } + +Pythonโ€™a ihtiyaรง duymadan, **shell (terminal)** iรงinde ortam deฤŸiลŸkenleri **oluลŸturabilir** ve kullanabilirsiniz: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// You could create an env var MY_NAME with +$ export MY_NAME="Wade Wilson" + +// Then you could use it with other programs, like +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Create an env var MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// Use it with other programs, like +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Pythonโ€™da env var Okuma { #read-env-vars-in-python } + +Ortam deฤŸiลŸkenlerini Pythonโ€™un **dฤฑลŸฤฑnda** (terminalde veya baลŸka bir yรถntemle) oluลŸturup daha sonra **Pythonโ€™da okuyabilirsiniz**. + +ร–rneฤŸin `main.py` adฤฑnda bir dosyanฤฑz ลŸรถyle olabilir: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | ฤฐpucu + +`os.getenv()` fonksiyonunun ikinci argรผmanฤฑ, bulunamadฤฑฤŸฤฑnda dรถndรผrรผlecek varsayฤฑlan (default) deฤŸerdir. + +Verilmezse varsayฤฑlan olarak `None` olur; burada varsayฤฑlan deฤŸer olarak `"World"` verdik. + +/// + +Sonrasฤฑnda bu Python programฤฑnฤฑ รงalฤฑลŸtฤฑrabilirsiniz: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Here we don't set the env var yet +$ python main.py + +// As we didn't set the env var, we get the default value + +Hello World from Python + +// But if we create an environment variable first +$ export MY_NAME="Wade Wilson" + +// And then call the program again +$ python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Here we don't set the env var yet +$ python main.py + +// As we didn't set the env var, we get the default value + +Hello World from Python + +// But if we create an environment variable first +$ $Env:MY_NAME = "Wade Wilson" + +// And then call the program again +$ python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python +``` + +
+ +//// + +Ortam deฤŸiลŸkenleri kodun dฤฑลŸฤฑnda ayarlanabildiฤŸi, ama kod tarafฤฑndan okunabildiฤŸi ve dosyalarla birlikte saklanmasฤฑnฤฑn (รถr. `git`โ€™e commit edilmesinin) gerekmediฤŸi iรงin, konfigรผrasyon veya **ayarlar** iรงin sฤฑkรงa kullanฤฑlฤฑr. + +Ayrฤฑca, bir ortam deฤŸiลŸkenini yalnฤฑzca **belirli bir program รงalฤฑลŸtฤฑrฤฑmฤฑ** iรงin oluลŸturabilirsiniz; bu deฤŸiลŸken sadece o program tarafฤฑndan, sadece o รงalฤฑลŸtฤฑrma sรผresince kullanฤฑlabilir. + +Bunu yapmak iรงin, program komutunun hemen รถncesinde ve aynฤฑ satฤฑrda tanฤฑmlayฤฑn: + +
+ +```console +// Create an env var MY_NAME in line for this program call +$ MY_NAME="Wade Wilson" python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python + +// The env var no longer exists afterwards +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | ฤฐpucu + +Bu konuyla ilgili daha fazlasฤฑnฤฑ The Twelve-Factor App: Config bรถlรผmรผnde okuyabilirsiniz. + +/// + +## Tipler ve DoฤŸrulama { #types-and-validation } + +Bu ortam deฤŸiลŸkenleri yalnฤฑzca **metin string**โ€™lerini taลŸฤฑyabilir. ร‡รผnkรผ Pythonโ€™un dฤฑลŸฤฑndadฤฑrlar ve diฤŸer programlarla, sistemin geri kalanฤฑyla (hatta Linux, Windows, macOS gibi farklฤฑ iลŸletim sistemleriyle) uyumlu olmak zorundadฤฑrlar. + +Bu, Pythonโ€™da bir ortam deฤŸiลŸkeninden okunan **her deฤŸerin `str` olacaฤŸฤฑ** anlamฤฑna gelir. Farklฤฑ bir tipe dรถnรผลŸtรผrme veya doฤŸrulama iลŸlemleri kod iรงinde yapฤฑlmalฤฑdฤฑr. + +Uygulama **ayarlarฤฑ**nฤฑ yรถnetmek iรงin ortam deฤŸiลŸkenlerini kullanmayฤฑ, [ฤฐleri Seviye Kullanฤฑcฤฑ Rehberi - Ayarlar ve Ortam DeฤŸiลŸkenleri](./advanced/settings.md){.internal-link target=_blank} bรถlรผmรผnde daha detaylฤฑ รถฤŸreneceksiniz. + +## `PATH` Ortam DeฤŸiลŸkeni { #path-environment-variable } + +ฤฐลŸletim sistemlerinin (Linux, macOS, Windows) รงalฤฑลŸtฤฑrฤฑlacak programlarฤฑ bulmak iรงin kullandฤฑฤŸฤฑ **รถzel** bir ortam deฤŸiลŸkeni vardฤฑr: **`PATH`**. + +`PATH` deฤŸiลŸkeninin deฤŸeri uzun bir stringโ€™dir; Linux ve macOSโ€™te dizinler iki nokta รผst รผste `:` ile, Windowsโ€™ta ise noktalฤฑ virgรผl `;` ile ayrฤฑlฤฑr. + +ร–rneฤŸin `PATH` ortam deฤŸiลŸkeni ลŸรถyle gรถrรผnebilir: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Bu, sistemin ลŸu dizinlerde program aramasฤฑ gerektiฤŸi anlamฤฑna gelir: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +Bu, sistemin ลŸu dizinlerde program aramasฤฑ gerektiฤŸi anlamฤฑna gelir: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +Terminalde bir **komut** yazdฤฑฤŸฤฑnฤฑzda, iลŸletim sistemi `PATH` ortam deฤŸiลŸkeninde listelenen **bu dizinlerin her birinde** programฤฑ **arar**. + +ร–rneฤŸin terminalde `python` yazdฤฑฤŸฤฑnฤฑzda, iลŸletim sistemi bu listedeki **ilk dizinde** `python` adlฤฑ bir program arar. + +Bulursa **onu kullanฤฑr**. Bulamazsa **diฤŸer dizinlerde** aramaya devam eder. + +### Python Kurulumu ve `PATH`โ€™in Gรผncellenmesi { #installing-python-and-updating-the-path } + +Pythonโ€™u kurarken, `PATH` ortam deฤŸiลŸkenini gรผncellemek isteyip istemediฤŸiniz sorulabilir. + +//// tab | Linux, macOS + +Diyelim ki Pythonโ€™u kurdunuz ve `/opt/custompython/bin` dizinine yรผklendi. + +`PATH` ortam deฤŸiลŸkenini gรผncellemeyi seรงerseniz, kurulum aracฤฑ `/opt/custompython/bin` yolunu `PATH` ortam deฤŸiลŸkenine ekler. + +ลžรถyle gรถrรผnebilir: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +Bรถylece terminalde `python` yazdฤฑฤŸฤฑnฤฑzda, sistem `/opt/custompython/bin` (son dizin) iรงindeki Python programฤฑnฤฑ bulur ve onu kullanฤฑr. + +//// + +//// tab | Windows + +Diyelim ki Pythonโ€™u kurdunuz ve `C:\opt\custompython\bin` dizinine yรผklendi. + +`PATH` ortam deฤŸiลŸkenini gรผncellemeyi seรงerseniz, kurulum aracฤฑ `C:\opt\custompython\bin` yolunu `PATH` ortam deฤŸiลŸkenine ekler. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +Bรถylece terminalde `python` yazdฤฑฤŸฤฑnฤฑzda, sistem `C:\opt\custompython\bin` (son dizin) iรงindeki Python programฤฑnฤฑ bulur ve onu kullanฤฑr. + +//// + +Yani ลŸunu yazarsanฤฑz: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +Sistem `python` programฤฑnฤฑ `/opt/custompython/bin` iรงinde **bulur** ve รงalฤฑลŸtฤฑrฤฑr. + +Bu, kabaca ลŸunu yazmaya denktir: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +Sistem `python` programฤฑnฤฑ `C:\opt\custompython\bin\python` iรงinde **bulur** ve รงalฤฑลŸtฤฑrฤฑr. + +Bu, kabaca ลŸunu yazmaya denktir: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Bu bilgiler, [Virtual Environments](virtual-environments.md){.internal-link target=_blank} konusunu รถฤŸrenirken iลŸinize yarayacak. + +## Sonuรง { #conclusion } + +Buraya kadar **ortam deฤŸiลŸkenleri**nin ne olduฤŸuna ve Pythonโ€™da nasฤฑl kullanฤฑlacaฤŸฤฑna dair temel bir fikir edinmiลŸ olmalฤฑsฤฑnฤฑz. + +Ayrฤฑca Wikipedia for Environment Variable sayfasฤฑndan daha fazlasฤฑnฤฑ da okuyabilirsiniz. + +ร‡oฤŸu zaman ortam deฤŸiลŸkenlerinin hemen nasฤฑl iลŸe yarayacaฤŸฤฑ ilk bakฤฑลŸta รงok net olmayabilir. Ancak geliลŸtirme yaparken birรงok farklฤฑ senaryoda tekrar tekrar karลŸฤฑnฤฑza รงฤฑkarlar; bu yรผzden bunlarฤฑ bilmek faydalฤฑdฤฑr. + +ร–rneฤŸin bir sonraki bรถlรผmde, [Virtual Environments](virtual-environments.md) konusunda bu bilgilere ihtiyaรง duyacaksฤฑnฤฑz. diff --git a/docs/tr/docs/fastapi-cli.md b/docs/tr/docs/fastapi-cli.md new file mode 100644 index 0000000000..4680d4bb6d --- /dev/null +++ b/docs/tr/docs/fastapi-cli.md @@ -0,0 +1,75 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI**, FastAPI uygulamanฤฑzฤฑ servis etmek, FastAPI projenizi yรถnetmek ve daha fazlasฤฑ iรงin kullanabileceฤŸiniz bir komut satฤฑrฤฑ programฤฑdฤฑr. + +FastAPI'yi kurduฤŸunuzda (รถr. `pip install "fastapi[standard]"`), beraberinde `fastapi-cli` adlฤฑ bir paket de gelir; bu paket terminalde `fastapi` komutunu saฤŸlar. + +FastAPI uygulamanฤฑzฤฑ geliลŸtirme iรงin รงalฤฑลŸtฤฑrmak รผzere `fastapi dev` komutunu kullanabilirsiniz: + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +`fastapi` adlฤฑ bu komut satฤฑrฤฑ programฤฑ, **FastAPI CLI**'dฤฑr. + +FastAPI CLI, Python programฤฑnฤฑzฤฑn path'ini (รถr. `main.py`) alฤฑr; `FastAPI` instance'ฤฑnฤฑ (genellikle `app` olarak adlandฤฑrฤฑlฤฑr) otomatik olarak tespit eder, doฤŸru import sรผrecini belirler ve ardฤฑndan uygulamayฤฑ servis eder. + +Production iรงin bunun yerine `fastapi run` kullanฤฑrsฤฑnฤฑz. ๐Ÿš€ + +ฤฐรงeride **FastAPI CLI**, yรผksek performanslฤฑ, production'a hazฤฑr bir ASGI server olan Uvicorn'u kullanฤฑr. ๐Ÿ˜Ž + +## `fastapi dev` { #fastapi-dev } + +`fastapi dev` รงalฤฑลŸtฤฑrmak, geliลŸtirme modunu baลŸlatฤฑr. + +Varsayฤฑlan olarak **auto-reload** etkindir; kodunuzda deฤŸiลŸiklik yaptฤฑฤŸฤฑnฤฑzda server'ฤฑ otomatik olarak yeniden yรผkler. Bu, kaynak tรผketimi yรผksek bir รถzelliktir ve kapalฤฑ olduฤŸuna kฤฑyasla daha az stabil olabilir. Sadece geliลŸtirme sฤฑrasฤฑnda kullanmalฤฑsฤฑnฤฑz. Ayrฤฑca yalnฤฑzca `127.0.0.1` IP adresini dinler; bu, makinenizin sadece kendisiyle iletiลŸim kurmasฤฑ iรงin kullanฤฑlan IP'dir (`localhost`). + +## `fastapi run` { #fastapi-run } + +`fastapi run` รงalฤฑลŸtฤฑrmak, varsayฤฑlan olarak FastAPI'yi production modunda baลŸlatฤฑr. + +Varsayฤฑlan olarak **auto-reload** kapalฤฑdฤฑr. Ayrฤฑca `0.0.0.0` IP adresini dinler; bu, kullanฤฑlabilir tรผm IP adresleri anlamฤฑna gelir. Bรถylece makineyle iletiลŸim kurabilen herkes tarafฤฑndan genel eriลŸime aรงฤฑk olur. Bu, normalde production'da รงalฤฑลŸtฤฑrma ลŸeklidir; รถrneฤŸin bir container iรงinde. + +ร‡oฤŸu durumda (ve genellikle yapmanฤฑz gereken ลŸekilde) รผst tarafta sizin yerinize HTTPS'i yรถneten bir "termination proxy" bulunur. Bu, uygulamanฤฑzฤฑ nasฤฑl deploy ettiฤŸinize baฤŸlฤฑdฤฑr; saฤŸlayฤฑcฤฑnฤฑz bunu sizin iรงin yapabilir ya da sizin ayrฤฑca kurmanฤฑz gerekebilir. + +/// tip | ฤฐpucu + +Bununla ilgili daha fazla bilgiyi [deployment dokรผmantasyonunda](deployment/index.md){.internal-link target=_blank} bulabilirsiniz. + +/// diff --git a/docs/tr/docs/help-fastapi.md b/docs/tr/docs/help-fastapi.md new file mode 100644 index 0000000000..785c0ae0d2 --- /dev/null +++ b/docs/tr/docs/help-fastapi.md @@ -0,0 +1,256 @@ +# FastAPI'ye Yardฤฑm Et - Yardฤฑm Al { #help-fastapi-get-help } + +**FastAPI**'yi seviyor musunuz? + +FastAPI'ye, diฤŸer kullanฤฑcฤฑlara ve yazara yardฤฑm etmek ister misiniz? + +Yoksa **FastAPI** ile ilgili yardฤฑm mฤฑ almak istiyorsunuz? + +Yardฤฑm etmenin รงok basit yollarฤฑ var (bazฤฑlarฤฑ sadece bir-iki tฤฑklama gerektirir). + +Yardฤฑm almanฤฑn da birkaรง yolu var. + +## Bรผltene abone olun { #subscribe-to-the-newsletter } + +ลžunlardan haberdar olmak iรงin (seyrek yayฤฑmlanan) [**FastAPI and friends** bรผltenine](newsletter.md){.internal-link target=_blank} abone olabilirsiniz: + +* FastAPI ve friends ile ilgili haberler ๐Ÿš€ +* Rehberler ๐Ÿ“ +* ร–zellikler โœจ +* Geriye dรถnรผk uyumsuz deฤŸiลŸiklikler ๐Ÿšจ +* ฤฐpuรงlarฤฑ ve pรผf noktalarฤฑ โœ… + +## X (Twitter) รผzerinden FastAPI'yi takip edin { #follow-fastapi-on-x-twitter } + +**FastAPI** ile ilgili en gรผncel haberleri almak iรงin @fastapi hesabฤฑnฤฑ **X (Twitter)** รผzerinde takip edin. ๐Ÿฆ + +## GitHub'da **FastAPI**'ye yฤฑldฤฑz verin { #star-fastapi-in-github } + +GitHub'da FastAPI'ye "star" verebilirsiniz (saฤŸ รผstteki yฤฑldฤฑz butonuna tฤฑklayarak): https://github.com/fastapi/fastapi. โญ๏ธ + +Yฤฑldฤฑz verince, diฤŸer kullanฤฑcฤฑlar projeyi daha kolay bulabilir ve baลŸkalarฤฑ iรงin de faydalฤฑ olduฤŸunu gรถrebilir. + +## GitHub repository'sini release'ler iรงin izleyin { #watch-the-github-repository-for-releases } + +GitHub'da FastAPI'yi "watch" edebilirsiniz (saฤŸ รผstteki "watch" butonuna tฤฑklayarak): https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +Orada "Releases only" seรงebilirsiniz. + +Bรถylece **FastAPI**'nin bug fix'ler ve yeni รถzelliklerle gelen her yeni release'inde (yeni versiyonunda) email ile bildirim alฤฑrsฤฑnฤฑz. + +## Yazarla baฤŸlantฤฑ kurun { #connect-with-the-author } + +Yazar olan benimle (Sebastiรกn Ramรญrez / `tiangolo`) baฤŸlantฤฑ kurabilirsiniz. + +ลžunlarฤฑ yapabilirsiniz: + +* Beni **GitHub**'da takip edin. + * Size yardฤฑmcฤฑ olabilecek oluลŸturduฤŸum diฤŸer Open Source projelere gรถz atฤฑn. + * Yeni bir Open Source proje oluลŸturduฤŸumda haberdar olmak iรงin beni takip edin. +* Beni **X (Twitter)** รผzerinde veya Mastodon'da takip edin. + * FastAPI'yi nasฤฑl kullandฤฑฤŸฤฑnฤฑzฤฑ anlatฤฑn (bunu duymayฤฑ seviyorum). + * Duyuru yaptฤฑฤŸฤฑmda veya yeni araรงlar yayฤฑnladฤฑฤŸฤฑmda haberdar olun. + * Ayrฤฑca (ayrฤฑ bir hesap olan) X (Twitter) รผzerinde @fastapi hesabฤฑnฤฑ da takip edebilirsiniz. +* Beni **LinkedIn**'de takip edin. + * Duyuru yaptฤฑฤŸฤฑmda veya yeni araรงlar yayฤฑnladฤฑฤŸฤฑmda haberdar olun (gerรงi X (Twitter)'ฤฑ daha sฤฑk kullanฤฑyorum ๐Ÿคทโ€โ™‚). +* **Dev.to** veya **Medium** รผzerinde yazdฤฑklarฤฑmฤฑ okuyun (ya da beni takip edin). + * DiฤŸer fikirleri, yazฤฑlarฤฑ ve oluลŸturduฤŸum araรงlarla ilgili iรงerikleri okuyun. + * Yeni bir ลŸey yayฤฑnladฤฑฤŸฤฑmda gรถrmek iรงin beni takip edin. + +## **FastAPI** hakkฤฑnda tweet atฤฑn { #tweet-about-fastapi } + +**FastAPI** hakkฤฑnda tweet atฤฑn ve neden sevdiฤŸinizi bana ve diฤŸerlerine sรถyleyin. ๐ŸŽ‰ + +**FastAPI**'nin nasฤฑl kullanฤฑldฤฑฤŸฤฑnฤฑ, nelerini sevdiฤŸinizi, hangi projede/ลŸirkette kullandฤฑฤŸฤฑnฤฑzฤฑ vb. duymayฤฑ seviyorum. + +## FastAPI iรงin oy verin { #vote-for-fastapi } + +* Slant'ta **FastAPI** iรงin oy verin. +* AlternativeTo'da **FastAPI** iรงin oy verin. +* StackShare'de **FastAPI** kullandฤฑฤŸฤฑnฤฑzฤฑ belirtin. + +## GitHub'da sorularla baลŸkalarฤฑna yardฤฑm edin { #help-others-with-questions-in-github } + +ลžuralarda insanlarฤฑn sorularฤฑna yardฤฑmcฤฑ olmayฤฑ deneyebilirsiniz: + +* GitHub Discussions +* GitHub Issues + +Birรงok durumda bu sorularฤฑn cevabฤฑnฤฑ zaten biliyor olabilirsiniz. ๐Ÿค“ + +EฤŸer insanlarฤฑn sorularฤฑna รงok yardฤฑm ederseniz, resmi bir [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank} olabilirsiniz. ๐ŸŽ‰ + +ลžunu unutmayฤฑn: en รถnemli nokta, nazik olmaya รงalฤฑลŸmak. ฤฐnsanlar รงoฤŸu zaman biriken stresle geliyor ve birรงok durumda soruyu en iyi ลŸekilde sormuyor; yine de elinizden geldiฤŸince nazik olmaya รงalฤฑลŸฤฑn. ๐Ÿค— + +Amaรง, **FastAPI** topluluฤŸunun nazik ve kapsayฤฑcฤฑ olmasฤฑ. Aynฤฑ zamanda baลŸkalarฤฑna zorbalฤฑk ya da saygฤฑsฤฑz davranฤฑลŸlarฤฑ da kabul etmeyin. Birbirimizi kollamalฤฑyฤฑz. + +--- + +Sorularda (discussions veya issues iรงinde) baลŸkalarฤฑna yardฤฑm etmek iรงin ลŸunlarฤฑ yapabilirsiniz: + +### Soruyu anlayฤฑn { #understand-the-question } + +* Soru soran kiลŸinin **amacฤฑnฤฑn** ve kullanฤฑm senaryosunun ne olduฤŸunu anlayabiliyor musunuz, kontrol edin. + +* Sonra sorunun (bรผyรผk รงoฤŸunluฤŸu soru olur) **net** olup olmadฤฑฤŸฤฑna bakฤฑn. + +* Birรงok durumda kullanฤฑcฤฑ kafasฤฑnda hayali bir รงรถzรผm kurup onu sorar; ancak **daha iyi** bir รงรถzรผm olabilir. Problemi ve kullanฤฑm senaryosunu daha iyi anladฤฑysanฤฑz daha iyi bir **alternatif รงรถzรผm** รถnerebilirsiniz. + +* Soruyu anlayamฤฑyorsanฤฑz daha fazla **detay** isteyin. + +### Problemi yeniden รผretin { #reproduce-the-problem } + +ร‡oฤŸu durumda ve รงoฤŸu soruda, kiลŸinin **orijinal kodu** ile ilgili bir ลŸey vardฤฑr. + +Birรงok kiลŸi sadece kodun bir parรงasฤฑnฤฑ kopyalar, ama bu **problemi yeniden รผretmek** iรงin yeterli olmaz. + +* ร‡alฤฑลŸtฤฑrฤฑp aynฤฑ hatayฤฑ/davranฤฑลŸฤฑ gรถrebileceฤŸiniz veya kullanฤฑm senaryosunu daha iyi anlayabileceฤŸiniz, yerelde **kopyala-yapฤฑลŸtฤฑr** yaparak รงalฤฑลŸtฤฑrฤฑlabilen bir minimal, reproducible, example paylaลŸmalarฤฑnฤฑ isteyebilirsiniz. + +* ร‡ok cรถmert hissediyorsanฤฑz, problemi anlatan aรงฤฑklamadan yola รงฤฑkarak kendiniz de bรถyle bir **รถrnek oluลŸturmayฤฑ** deneyebilirsiniz. Ancak bunun รงok zaman alabileceฤŸini unutmayฤฑn; รงoฤŸu zaman รถnce problemi netleลŸtirmelerini istemek daha iyidir. + +### ร‡รถzรผm รถnerin { #suggest-solutions } + +* Soruyu anlayabildikten sonra olasฤฑ bir **cevap** verebilirsiniz. + +* ร‡oฤŸu durumda, yapmak istediklerinden ziyade alttaki **asฤฑl problemi veya kullanฤฑm senaryosunu** anlamak daha iyidir; รงรผnkรผ denedikleri yรถntemden daha iyi bir รงรถzรผm yolu olabilir. + +### Kapatฤฑlmasฤฑnฤฑ isteyin { #ask-to-close } + +EฤŸer yanฤฑt verirlerse, bรผyรผk ihtimalle problemi รงรถzmรผลŸsรผnรผzdรผr, tebrikler, **kahramansฤฑnฤฑz**! ๐Ÿฆธ + +* EฤŸer รงรถzรผm iลŸe yaradฤฑysa ลŸunlarฤฑ yapmalarฤฑnฤฑ isteyebilirsiniz: + + * GitHub Discussions'ta: ilgili yorumu **answer** olarak iลŸaretlemeleri. + * GitHub Issues'ta: issue'yu **close** etmeleri. + +## GitHub repository'sini izleyin { #watch-the-github-repository } + +GitHub'da FastAPI'yi "watch" edebilirsiniz (saฤŸ รผstteki "watch" butonuna tฤฑklayarak): https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +"Releases only" yerine "Watching" seรงerseniz biri yeni bir issue veya soru oluลŸturduฤŸunda bildirim alฤฑrsฤฑnฤฑz. Ayrฤฑca sadece yeni issue'lar, ya da discussions, ya da PR'lar vb. iรงin bildirim almak istediฤŸinizi belirtebilirsiniz. + +Sonra da bu sorularฤฑ รงรถzmelerine yardฤฑmcฤฑ olmayฤฑ deneyebilirsiniz. + +## Soru Sorun { #ask-questions } + +GitHub repository'sinde รถrneฤŸin ลŸunlar iรงin yeni bir soru oluลŸturabilirsiniz: + +* Bir **soru** sorun veya bir **problem** hakkฤฑnda danฤฑลŸฤฑn. +* Yeni bir **feature** รถnerin. + +**Not**: Bunu yaparsanฤฑz, ben de sizden baลŸkalarฤฑna yardฤฑm etmenizi isteyeceฤŸim. ๐Ÿ˜‰ + +## Pull Request'leri ฤฐnceleyin { #review-pull-requests } + +BaลŸkalarฤฑnฤฑn gรถnderdiฤŸi pull request'leri incelememde bana yardฤฑmcฤฑ olabilirsiniz. + +Yine, lรผtfen elinizden geldiฤŸince nazik olmaya รงalฤฑลŸฤฑn. ๐Ÿค— + +--- + +Bir pull request'i incelerken akฤฑlda tutmanฤฑz gerekenler: + +### Problemi anlayฤฑn { #understand-the-problem } + +* ร–nce, pull request'in รงรถzmeye รงalฤฑลŸtฤฑฤŸฤฑ **problemi anladฤฑฤŸฤฑnฤฑzdan** emin olun. GitHub Discussion veya issue iรงinde daha uzun bir tartฤฑลŸmasฤฑ olabilir. + +* Pull request'in aslฤฑnda hiรง gerekmiyor olma ihtimali de yรผksektir; รงรผnkรผ problem **farklฤฑ bir ลŸekilde** รงรถzรผlebilir. Bu durumda bunu รถnerebilir veya bununla ilgili soru sorabilirsiniz. + +### Style konusunda รงok dert etmeyin { #dont-worry-about-style } + +* Commit message tarzฤฑ gibi ลŸeyleri รงok dert etmeyin; ben commit'leri manuel olarak dรผzenleyerek squash and merge yapacaฤŸฤฑm. + +* Style kurallarฤฑ iรงin de endiลŸelenmeyin; bunlarฤฑ kontrol eden otomatik araรงlar zaten var. + +Ek bir style veya tutarlฤฑlฤฑk ihtiyacฤฑ olursa, bunu doฤŸrudan isterim ya da gerekli deฤŸiลŸikliklerle รผstรผne commit eklerim. + +### Kodu kontrol edin { #check-the-code } + +* Kodu okuyup kontrol edin; mantฤฑklฤฑ mฤฑ bakฤฑn, **yerelde รงalฤฑลŸtฤฑrฤฑn** ve gerรงekten problemi รงรถzรผyor mu gรถrรผn. + +* Ardฤฑndan bunu yaptฤฑฤŸฤฑnฤฑzฤฑ belirten bir **yorum** yazฤฑn; bรถylece gerรงekten kontrol ettiฤŸinizi anlarฤฑm. + +/// info | Bilgi + +Ne yazฤฑk ki sadece birkaรง onayฤฑ olan PR'lara kรถrรผ kรถrรผne gรผvenemem. + +Defalarca, 3, 5 veya daha fazla onayฤฑ olan PR'lar oldu; muhtemelen aรงฤฑklamasฤฑ รงekici olduฤŸu iรงin onay aldฤฑlar. Ama PR'lara baktฤฑฤŸฤฑmda aslฤฑnda bozuk olduklarฤฑnฤฑ, bug iรงerdiฤŸini veya iddia ettikleri problemi รงรถzmediklerini gรถrdรผm. ๐Ÿ˜… + +Bu yรผzden kodu gerรงekten okuyup รงalฤฑลŸtฤฑrmanฤฑz ve bunu yorumlarda bana bildirmeniz รงok รถnemli. ๐Ÿค“ + +/// + +* PR bir ลŸekilde basitleลŸtirilebiliyorsa bunu isteyebilirsiniz. Ancak รงok didik didik etmeye gerek yok; konuya gรถre birรงok รถznel bakฤฑลŸ aรงฤฑsฤฑ olabilir (benim de olacaktฤฑr ๐Ÿ™ˆ). Bu yรผzden temel noktalara odaklanmak daha iyi. + +### Testler { #tests } + +* PR'da **testler** olduฤŸunu kontrol etmemde bana yardฤฑmcฤฑ olun. + +* PR'dan รถnce testlerin **fail** ettiฤŸini kontrol edin. ๐Ÿšจ + +* PR'dan sonra testlerin **pass** ettiฤŸini kontrol edin. โœ… + +* Birรงok PR test iรงermez; test eklemelerini **hatฤฑrlatabilirsiniz** veya hatta kendiniz bazฤฑ testler **รถnerebilirsiniz**. Bu, en รงok zaman alan iลŸlerden biridir ve burada รงok yardฤฑmcฤฑ olabilirsiniz. + +* Ayrฤฑca neleri denediฤŸinizi yorumlara yazฤฑn; bรถylece kontrol ettiฤŸinizi anlarฤฑm. ๐Ÿค“ + +## Pull Request OluลŸturun { #create-a-pull-request } + +ร–rneฤŸin ลŸunlar iรงin Pull Request'lerle kaynak koda [katkฤฑda bulunabilirsiniz](contributing.md){.internal-link target=_blank}: + +* Dokรผmantasyonda bulduฤŸunuz bir yazฤฑm hatasฤฑnฤฑ dรผzeltmek. +* FastAPI hakkฤฑnda oluลŸturduฤŸunuz veya bulduฤŸunuz bir makaleyi, videoyu ya da podcast'i bu dosyayฤฑ dรผzenleyerek paylaลŸmak. + * Link'inizi ilgili bรถlรผmรผn baลŸฤฑna eklediฤŸinizden emin olun. +* Dokรผmantasyonu kendi dilinize [รงevirmeye yardฤฑmcฤฑ olmak](contributing.md#translations){.internal-link target=_blank}. + * BaลŸkalarฤฑnฤฑn yaptฤฑฤŸฤฑ รงevirileri gรถzden geรงirmeye de yardฤฑmcฤฑ olabilirsiniz. +* Yeni dokรผmantasyon bรถlรผmleri รถnermek. +* Mevcut bir issue/bug'ฤฑ dรผzeltmek. + * Test eklediฤŸinizden emin olun. +* Yeni bir feature eklemek. + * Test eklediฤŸinizden emin olun. + * ฤฐlgiliyse dokรผmantasyon da eklediฤŸinizden emin olun. + +## FastAPI'nin Bakฤฑmฤฑna Yardฤฑm Edin { #help-maintain-fastapi } + +**FastAPI**'nin bakฤฑmฤฑnฤฑ yapmama yardฤฑmcฤฑ olun! ๐Ÿค“ + +Yapฤฑlacak รงok iลŸ var ve bunlarฤฑn รงoฤŸunu **SฤฐZ** yapabilirsiniz. + +ลžu anda yapabileceฤŸiniz ana iลŸler: + +* [GitHub'da sorularla baลŸkalarฤฑna yardฤฑm edin](#help-others-with-questions-in-github){.internal-link target=_blank} (yukarฤฑdaki bรถlรผme bakฤฑn). +* [Pull Request'leri inceleyin](#review-pull-requests){.internal-link target=_blank} (yukarฤฑdaki bรถlรผme bakฤฑn). + +Bu iki iลŸ, **en รงok zamanฤฑ alan** iลŸlerdir. FastAPI bakฤฑmฤฑnฤฑn ana yรผkรผ buradadฤฑr. + +Burada yardฤฑmcฤฑ olursanฤฑz, **FastAPI'nin bakฤฑmฤฑnฤฑ yapmama yardฤฑm etmiลŸ** ve daha **hฤฑzlฤฑ ve daha iyi ilerlemesini** saฤŸlamฤฑลŸ olursunuz. ๐Ÿš€ + +## Sohbete katฤฑlฤฑn { #join-the-chat } + +FastAPI topluluฤŸundan diฤŸer kiลŸilerle takฤฑlmak iรงin ๐Ÿ‘ฅ Discord chat server ๐Ÿ‘ฅ sohbetine katฤฑlฤฑn. + +/// tip | ฤฐpucu + +Sorular iรงin GitHub Discussions'a sorun; [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank} tarafฤฑndan yardฤฑm alma ihtimaliniz รงok daha yรผksektir. + +Chat'i sadece genel sohbetler iรงin kullanฤฑn. + +/// + +### Sorular iรงin chat'i kullanmayฤฑn { #dont-use-the-chat-for-questions } + +Chat sistemleri daha "serbest sohbet"e izin verdiฤŸi iรงin, รงok genel ve yanฤฑtlamasฤฑ daha zor sorular sormak kolaylaลŸฤฑr; bu nedenle cevap alamayabilirsiniz. + +GitHub'da ise ลŸablon (template) doฤŸru soruyu yazmanฤฑz iรงin sizi yรถnlendirir; bรถylece daha kolay iyi bir cevap alabilir, hatta bazen sormadan รถnce problemi kendiniz รงรถzebilirsiniz. Ayrฤฑca GitHub'da (zaman alsa bile) her ลŸeye mutlaka cevap verdiฤŸimden emin olabilirim. Chat sistemlerinde bunu kiลŸisel olarak yapamam. ๐Ÿ˜… + +Chat sistemlerindeki konuลŸmalar GitHub kadar kolay aranabilir deฤŸildir; bu yรผzden soru ve cevaplar sohbet iรงinde kaybolabilir. Ayrฤฑca [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank} olmak iรงin sadece GitHub'daki katkฤฑlar sayฤฑlฤฑr; dolayฤฑsฤฑyla bรผyรผk olasฤฑlฤฑkla GitHub'da daha fazla ilgi gรถrรผrsรผnรผz. + +ร–te yandan chat sistemlerinde binlerce kullanฤฑcฤฑ vardฤฑr; bu yรผzden neredeyse her zaman konuลŸacak birini bulma ihtimaliniz yรผksektir. ๐Ÿ˜„ + +## Yazara sponsor olun { #sponsor-the-author } + +EฤŸer **รผrรผnรผnรผz/ลŸirketiniz** **FastAPI**'ye baฤŸlฤฑysa veya onunla iliลŸkiliyse ve FastAPI kullanฤฑcฤฑlarฤฑna ulaลŸmak istiyorsanฤฑz, GitHub sponsors รผzerinden yazara (bana) sponsor olabilirsiniz. Tier'a gรถre dokรผmantasyonda bir rozet gibi ek faydalar elde edebilirsiniz. ๐ŸŽ + +--- + +TeลŸekkรผrler! ๐Ÿš€ diff --git a/docs/tr/docs/how-to/authentication-error-status-code.md b/docs/tr/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..579673624b --- /dev/null +++ b/docs/tr/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# Eski 403 Kimlik DoฤŸrulama Hata Durum Kodlarฤฑnฤฑ Kullanma { #use-old-403-authentication-error-status-codes } + +FastAPI `0.122.0` sรผrรผmรผnden รถnce, entegre security yardฤฑmcฤฑ araรงlarฤฑ baลŸarฤฑsฤฑz bir kimlik doฤŸrulama (authentication) sonrasฤฑnda client'a bir hata dรถndรผฤŸรผnde HTTP durum kodu olarak `403 Forbidden` kullanฤฑyordu. + +FastAPI `0.122.0` sรผrรผmรผnden itibaren ise daha uygun olan HTTP durum kodu `401 Unauthorized` kullanฤฑlmakta ve HTTP spesifikasyonlarฤฑna uygun olarak response iรงinde anlamlฤฑ bir `WWW-Authenticate` header'ฤฑ dรถndรผrรผlmektedir: RFC 7235, RFC 9110. + +Ancak herhangi bir nedenle client'larฤฑnฤฑz eski davranฤฑลŸa baฤŸlฤฑysa, security class'larฤฑnฤฑzda `make_not_authenticated_error` metodunu override ederek eski davranฤฑลŸa geri dรถnebilirsiniz. + +ร–rneฤŸin, varsayฤฑlan `401 Unauthorized` hatasฤฑ yerine `403 Forbidden` hatasฤฑ dรถndรผren bir `HTTPBearer` alt sฤฑnฤฑfฤฑ oluลŸturabilirsiniz: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} + +/// tip | ฤฐpucu + +Fonksiyonun exception instance'ฤฑnฤฑ dรถndรผrdรผฤŸรผne dikkat edin; exception'ฤฑ raise etmiyor. Raise iลŸlemi internal kodun geri kalan kฤฑsmฤฑnda yapฤฑlฤฑyor. + +/// diff --git a/docs/tr/docs/how-to/conditional-openapi.md b/docs/tr/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000..9562637c47 --- /dev/null +++ b/docs/tr/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# KoลŸullu OpenAPI { #conditional-openapi } + +Gerekirse, ayarlar ve environment variable'larฤฑ kullanarak OpenAPI'yi ortama gรถre koลŸullu ลŸekilde yapฤฑlandฤฑrabilir, hatta tamamen devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. + +## Gรผvenlik, API'ler ve dokรผmantasyon hakkฤฑnda { #about-security-apis-and-docs } + +Production ortamฤฑnda dokรผmantasyon arayรผzlerini gizlemek, API'nizi korumanฤฑn yolu *olmamalฤฑdฤฑr*. + +Bu, API'nize ekstra bir gรผvenlik katmanฤฑ eklemez; *path operation*'lar bulunduklarฤฑ yerde yine eriลŸilebilir olacaktฤฑr. + +Kodunuzda bir gรผvenlik aรงฤฑฤŸฤฑ varsa, o aรงฤฑk yine var olmaya devam eder. + +Dokรผmantasyonu gizlemek, API'nizle nasฤฑl etkileลŸime geรงileceฤŸini anlamayฤฑ zorlaลŸtฤฑrฤฑr ve production'da debug etmeyi de daha zor hale getirebilir. Bu yaklaลŸฤฑm, basitรงe Security through obscurity olarak deฤŸerlendirilebilir. + +API'nizi gรผvence altฤฑna almak istiyorsanฤฑz, yapabileceฤŸiniz daha iyi birรงok ลŸey var; รถrneฤŸin: + +* request body'leriniz ve response'larฤฑnฤฑz iรงin iyi tanฤฑmlanmฤฑลŸ Pydantic model'larฤฑna sahip olduฤŸunuzdan emin olun. +* dependencies kullanarak gerekli izinleri ve rolleri yapฤฑlandฤฑrฤฑn. +* Asla dรผz metin (plaintext) ลŸifre saklamayฤฑn, yalnฤฑzca password hash'leri saklayฤฑn. +* pwdlib ve JWT token'larฤฑ gibi, iyi bilinen kriptografik araรงlarฤฑ uygulayฤฑn ve kullanฤฑn. +* GerektiฤŸinde OAuth2 scope'larฤฑ ile daha ayrฤฑntฤฑlฤฑ izin kontrolleri ekleyin. +* ...vb. + +Yine de, bazฤฑ ortamlarda (รถrn. production) veya environment variable'lardan gelen konfigรผrasyonlara baฤŸlฤฑ olarak API docs'u gerรงekten devre dฤฑลŸฤฑ bฤฑrakmanฤฑz gereken รงok spesifik bir use case'iniz olabilir. + +## Ayarlar ve env var'lar ile koลŸullu OpenAPI { #conditional-openapi-from-settings-and-env-vars } + +รœretilen OpenAPI'yi ve docs UI'larฤฑnฤฑ yapฤฑlandฤฑrmak iรงin aynฤฑ Pydantic settings'i kolayca kullanabilirsiniz. + +ร–rneฤŸin: + +{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} + +Burada `openapi_url` ayarฤฑnฤฑ, varsayฤฑlanฤฑ `"/openapi.json"` olacak ลŸekilde tanฤฑmlฤฑyoruz. + +Ardฤฑndan `FastAPI` app'ini oluลŸtururken bunu kullanฤฑyoruz. + +Sonrasฤฑnda, environment variable `OPENAPI_URL`'i boลŸ string olarak ayarlayarak OpenAPI'yi (UI docs dahil) devre dฤฑลŸฤฑ bฤฑrakabilirsiniz; รถrneฤŸin: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Bรถylece `/openapi.json`, `/docs` veya `/redoc` URL'lerine giderseniz, aลŸaฤŸฤฑdaki gibi bir `404 Not Found` hatasฤฑ alฤฑrsฤฑnฤฑz: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/tr/docs/how-to/configure-swagger-ui.md b/docs/tr/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000..6c051a1215 --- /dev/null +++ b/docs/tr/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Swagger UI'yi Yapฤฑlandฤฑrฤฑn { #configure-swagger-ui } + +Bazฤฑ ek Swagger UI parametrelerini yapฤฑlandฤฑrabilirsiniz. + +Bunlarฤฑ yapฤฑlandฤฑrmak iรงin, `FastAPI()` uygulama nesnesini oluลŸtururken ya da `get_swagger_ui_html()` fonksiyonuna `swagger_ui_parameters` argรผmanฤฑnฤฑ verin. + +`swagger_ui_parameters`, Swagger UI'ye doฤŸrudan iletilecek yapฤฑlandฤฑrmalarฤฑ iรงeren bir `dict` alฤฑr. + +FastAPI, Swagger UI'nin ihtiyaรง duyduฤŸu ลŸekilde JavaScript ile uyumlu olsun diye bu yapฤฑlandฤฑrmalarฤฑ **JSON**'a dรถnรผลŸtรผrรผr. + +## Syntax Highlighting'i Devre DฤฑลŸฤฑ Bฤฑrakฤฑn { #disable-syntax-highlighting } + +ร–rneฤŸin, Swagger UI'de syntax highlighting'i devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. + +Ayarlarฤฑ deฤŸiลŸtirmeden bฤฑrakฤฑrsanฤฑz, syntax highlighting varsayฤฑlan olarak etkindir: + + + +Ancak `syntaxHighlight` deฤŸerini `False` yaparak devre dฤฑลŸฤฑ bฤฑrakabilirsiniz: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} + +...ve ardฤฑndan Swagger UI artฤฑk syntax highlighting'i gรถstermeyecektir: + + + +## Temayฤฑ DeฤŸiลŸtirin { #change-the-theme } + +Aynฤฑ ลŸekilde, `"syntaxHighlight.theme"` anahtarฤฑyla (ortasฤฑnda bir nokta olduฤŸuna dikkat edin) syntax highlighting temasฤฑnฤฑ ayarlayabilirsiniz: + +{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} + +Bu yapฤฑlandฤฑrma, syntax highlighting renk temasฤฑnฤฑ deฤŸiลŸtirir: + + + +## Varsayฤฑlan Swagger UI Parametrelerini DeฤŸiลŸtirin { #change-default-swagger-ui-parameters } + +FastAPI, รงoฤŸu kullanฤฑm senaryosu iรงin uygun bazฤฑ varsayฤฑlan yapฤฑlandฤฑrma parametreleriyle gelir. + +ลžu varsayฤฑlan yapฤฑlandฤฑrmalarฤฑ iรงerir: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +`swagger_ui_parameters` argรผmanฤฑnda farklฤฑ bir deฤŸer vererek bunlarฤฑn herhangi birini ezebilirsiniz (override). + +ร–rneฤŸin `deepLinking`'i devre dฤฑลŸฤฑ bฤฑrakmak iรงin `swagger_ui_parameters`'a ลŸu ayarlarฤฑ geรงebilirsiniz: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} + +## DiฤŸer Swagger UI Parametreleri { #other-swagger-ui-parameters } + +KullanabileceฤŸiniz diฤŸer tรผm olasฤฑ yapฤฑlandฤฑrmalarฤฑ gรถrmek iรงin, resmi Swagger UI parametreleri dokรผmantasyonunu okuyun. + +## Yalnฤฑzca JavaScript ayarlarฤฑ { #javascript-only-settings } + +Swagger UI ayrฤฑca bazฤฑ yapฤฑlandฤฑrmalarฤฑn **yalnฤฑzca JavaScript** nesneleri olmasฤฑna izin verir (รถrneฤŸin JavaScript fonksiyonlarฤฑ). + +FastAPI, bu yalnฤฑzca JavaScript olan `presets` ayarlarฤฑnฤฑ da iรงerir: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +Bunlar string deฤŸil, **JavaScript** nesneleridir; dolayฤฑsฤฑyla bunlarฤฑ Python kodundan doฤŸrudan geรงemezsiniz. + +Bรถyle yalnฤฑzca JavaScript yapฤฑlandฤฑrmalarฤฑna ihtiyacฤฑnฤฑz varsa, yukarฤฑdaki yรถntemlerden birini kullanabilirsiniz: Swagger UI'nin tรผm *path operation*'larฤฑnฤฑ override edin ve ihtiyaรง duyduฤŸunuz JavaScript'i elle yazฤฑn. diff --git a/docs/tr/docs/how-to/custom-docs-ui-assets.md b/docs/tr/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..bdd2d02440 --- /dev/null +++ b/docs/tr/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ร–zel Docs UI Statik Varlฤฑklarฤฑ (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } + +API dokรผmanlarฤฑ **Swagger UI** ve **ReDoc** kullanฤฑr ve bunlarฤฑn her biri bazฤฑ JavaScript ve CSS dosyalarฤฑna ihtiyaรง duyar. + +Varsayฤฑlan olarak bu dosyalar bir CDN รผzerinden servis edilir. + +Ancak bunu รถzelleลŸtirmek mรผmkรผndรผr; belirli bir CDN ayarlayabilir veya dosyalarฤฑ kendiniz servis edebilirsiniz. + +## JavaScript ve CSS iรงin ร–zel CDN { #custom-cdn-for-javascript-and-css } + +Diyelim ki farklฤฑ bir CDN kullanmak istiyorsunuz; รถrneฤŸin `https://unpkg.com/` kullanmak istiyorsunuz. + +Bu, รถrneฤŸin bazฤฑ URL'leri kฤฑsฤฑtlayan bir รผlkede yaลŸฤฑyorsanฤฑz faydalฤฑ olabilir. + +### Otomatik dokรผmanlarฤฑ devre dฤฑลŸฤฑ bฤฑrakฤฑn { #disable-the-automatic-docs } + +ฤฐlk adฤฑm, otomatik dokรผmanlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmaktฤฑr; รงรผnkรผ varsayฤฑlan olarak bunlar varsayฤฑlan CDN'i kullanฤฑr. + +Bunlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmak iรงin `FastAPI` uygulamanฤฑzฤฑ oluลŸtururken URL'lerini `None` olarak ayarlayฤฑn: + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} + +### ร–zel dokรผmanlarฤฑ ekleyin { #include-the-custom-docs } + +ลžimdi รถzel dokรผmanlar iรงin *path operation*'larฤฑ oluลŸturabilirsiniz. + +Dokรผmanlar iรงin HTML sayfalarฤฑnฤฑ รผretmek รผzere FastAPI'nin dahili fonksiyonlarฤฑnฤฑ yeniden kullanabilir ve gerekli argรผmanlarฤฑ iletebilirsiniz: + +* `openapi_url`: Dokรผmanlarฤฑn HTML sayfasฤฑnฤฑn API'niz iรงin OpenAPI ลŸemasฤฑnฤฑ alacaฤŸฤฑ URL. Burada `app.openapi_url` niteliฤŸini kullanabilirsiniz. +* `title`: API'nizin baลŸlฤฑฤŸฤฑ. +* `oauth2_redirect_url`: varsayฤฑlanฤฑ kullanmak iรงin burada `app.swagger_ui_oauth2_redirect_url` kullanabilirsiniz. +* `swagger_js_url`: Swagger UI dokรผmanlarฤฑnฤฑzฤฑn HTML'inin **JavaScript** dosyasฤฑnฤฑ alacaฤŸฤฑ URL. Bu, รถzel CDN URL'idir. +* `swagger_css_url`: Swagger UI dokรผmanlarฤฑnฤฑzฤฑn HTML'inin **CSS** dosyasฤฑnฤฑ alacaฤŸฤฑ URL. Bu, รถzel CDN URL'idir. + +ReDoc iรงin de benzer ลŸekilde... + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | ฤฐpucu + +`swagger_ui_redirect` iรงin olan *path operation*, OAuth2 kullandฤฑฤŸฤฑnฤฑzda yardฤฑmcฤฑ olmasฤฑ iรงin vardฤฑr. + +API'nizi bir OAuth2 saฤŸlayฤฑcฤฑsฤฑyla entegre ederseniz kimlik doฤŸrulamasฤฑ yapabilir, aldฤฑฤŸฤฑnฤฑz kimlik bilgileriyle API dokรผmanlarฤฑna geri dรถnebilir ve gerรงek OAuth2 kimlik doฤŸrulamasฤฑnฤฑ kullanarak onunla etkileลŸime geรงebilirsiniz. + +Swagger UI bunu arka planda sizin iรงin yรถnetir, ancak bu "redirect" yardฤฑmcฤฑsฤฑna ihtiyaรง duyar. + +/// + +### Test etmek iรงin bir *path operation* oluลŸturun { #create-a-path-operation-to-test-it } + +ลžimdi her ลŸeyin รงalฤฑลŸtฤฑฤŸฤฑnฤฑ test edebilmek iรงin bir *path operation* oluลŸturun: + +{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} + +### Test edin { #test-it } + +Artฤฑk http://127.0.0.1:8000/docs adresinden dokรผmanlarฤฑnฤฑza gidebilmeli ve sayfayฤฑ yenilediฤŸinizde bu varlฤฑklarฤฑn yeni CDN'den yรผklendiฤŸini gรถrebilmelisiniz. + +## Dokรผmanlar iรงin JavaScript ve CSS'i Self-Hosting ile barฤฑndฤฑrma { #self-hosting-javascript-and-css-for-docs } + +JavaScript ve CSS'i self-hosting ile barฤฑndฤฑrmak, รถrneฤŸin uygulamanฤฑzฤฑn ฤฐnternet eriลŸimi olmadan (offline), aรงฤฑk ฤฐnternet olmadan veya bir lokal aฤŸ iรงinde bile รงalฤฑลŸmaya devam etmesi gerekiyorsa faydalฤฑ olabilir. + +Burada bu dosyalarฤฑ aynฤฑ FastAPI uygulamasฤฑnda nasฤฑl kendiniz servis edeceฤŸinizi ve dokรผmanlarฤฑn bunlarฤฑ kullanacak ลŸekilde nasฤฑl yapฤฑlandฤฑrฤฑlacaฤŸฤฑnฤฑ gรถreceksiniz. + +### Proje dosya yapฤฑsฤฑ { #project-file-structure } + +Diyelim ki projenizin dosya yapฤฑsฤฑ ลŸรถyle: + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +ลžimdi bu statik dosyalarฤฑ saklamak iรงin bir dizin oluลŸturun. + +Yeni dosya yapฤฑnฤฑz ลŸรถyle olabilir: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### Dosyalarฤฑ indirin { #download-the-files } + +Dokรผmanlar iรงin gereken statik dosyalarฤฑ indirin ve `static/` dizinine koyun. + +Muhtemelen her bir linke saฤŸ tฤฑklayฤฑp "Save link as..." benzeri bir seรงenek seรงebilirsiniz. + +**Swagger UI** ลŸu dosyalarฤฑ kullanฤฑr: + +* `swagger-ui-bundle.js` +* `swagger-ui.css` + +**ReDoc** ise ลŸu dosyayฤฑ kullanฤฑr: + +* `redoc.standalone.js` + +Bundan sonra dosya yapฤฑnฤฑz ลŸรถyle gรถrรผnebilir: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### Statik dosyalarฤฑ servis edin { #serve-the-static-files } + +* `StaticFiles` iรงe aktarฤฑn. +* Belirli bir path'te bir `StaticFiles()` instance'ฤฑnฤฑ "mount" edin. + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} + +### Statik dosyalarฤฑ test edin { #test-the-static-files } + +Uygulamanฤฑzฤฑ baลŸlatฤฑn ve http://127.0.0.1:8000/static/redoc.standalone.js adresine gidin. + +**ReDoc** iรงin รงok uzun bir JavaScript dosyasฤฑ gรถrmelisiniz. + +ลžuna benzer bir ลŸekilde baลŸlayabilir: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +Bu, uygulamanฤฑzdan statik dosyalarฤฑ servis edebildiฤŸinizi ve dokรผmanlar iรงin statik dosyalarฤฑ doฤŸru yere koyduฤŸunuzu doฤŸrular. + +ลžimdi uygulamayฤฑ, dokรผmanlar iรงin bu statik dosyalarฤฑ kullanacak ลŸekilde yapฤฑlandฤฑrabiliriz. + +### Statik dosyalar iรงin otomatik dokรผmanlarฤฑ devre dฤฑลŸฤฑ bฤฑrakฤฑn { #disable-the-automatic-docs-for-static-files } + +ร–zel CDN kullanฤฑrken olduฤŸu gibi, ilk adฤฑm otomatik dokรผmanlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmaktฤฑr; รงรผnkรผ bunlar varsayฤฑlan olarak CDN kullanฤฑr. + +Bunlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmak iรงin `FastAPI` uygulamanฤฑzฤฑ oluลŸtururken URL'lerini `None` olarak ayarlayฤฑn: + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} + +### Statik dosyalar iรงin รถzel dokรผmanlarฤฑ ekleyin { #include-the-custom-docs-for-static-files } + +ร–zel CDN'de olduฤŸu gibi, artฤฑk รถzel dokรผmanlar iรงin *path operation*'larฤฑ oluลŸturabilirsiniz. + +Yine FastAPI'nin dahili fonksiyonlarฤฑnฤฑ kullanarak dokรผmanlar iรงin HTML sayfalarฤฑnฤฑ oluลŸturabilir ve gerekli argรผmanlarฤฑ geรงebilirsiniz: + +* `openapi_url`: Dokรผmanlarฤฑn HTML sayfasฤฑnฤฑn API'niz iรงin OpenAPI ลŸemasฤฑnฤฑ alacaฤŸฤฑ URL. Burada `app.openapi_url` niteliฤŸini kullanabilirsiniz. +* `title`: API'nizin baลŸlฤฑฤŸฤฑ. +* `oauth2_redirect_url`: varsayฤฑlanฤฑ kullanmak iรงin burada `app.swagger_ui_oauth2_redirect_url` kullanabilirsiniz. +* `swagger_js_url`: Swagger UI dokรผmanlarฤฑnฤฑzฤฑn HTML'inin **JavaScript** dosyasฤฑnฤฑ alacaฤŸฤฑ URL. **Artฤฑk bunu sizin kendi uygulamanฤฑz servis ediyor**. +* `swagger_css_url`: Swagger UI dokรผmanlarฤฑnฤฑzฤฑn HTML'inin **CSS** dosyasฤฑnฤฑ alacaฤŸฤฑ URL. **Artฤฑk bunu sizin kendi uygulamanฤฑz servis ediyor**. + +ReDoc iรงin de benzer ลŸekilde... + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | ฤฐpucu + +`swagger_ui_redirect` iรงin olan *path operation*, OAuth2 kullandฤฑฤŸฤฑnฤฑzda yardฤฑmcฤฑ olmasฤฑ iรงin vardฤฑr. + +API'nizi bir OAuth2 saฤŸlayฤฑcฤฑsฤฑyla entegre ederseniz kimlik doฤŸrulamasฤฑ yapabilir, aldฤฑฤŸฤฑnฤฑz kimlik bilgileriyle API dokรผmanlarฤฑna geri dรถnebilir ve gerรงek OAuth2 kimlik doฤŸrulamasฤฑnฤฑ kullanarak onunla etkileลŸime geรงebilirsiniz. + +Swagger UI bunu arka planda sizin iรงin yรถnetir, ancak bu "redirect" yardฤฑmcฤฑsฤฑna ihtiyaรง duyar. + +/// + +### Statik dosyalarฤฑ test etmek iรงin bir *path operation* oluลŸturun { #create-a-path-operation-to-test-static-files } + +ลžimdi her ลŸeyin รงalฤฑลŸtฤฑฤŸฤฑnฤฑ test edebilmek iรงin bir *path operation* oluลŸturun: + +{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} + +### Statik Dosyalar UI'ฤฑnฤฑ Test Edin { #test-static-files-ui } + +Artฤฑk WiFi baฤŸlantฤฑnฤฑzฤฑ kesip http://127.0.0.1:8000/docs adresindeki dokรผmanlarฤฑnฤฑza gidebilmeli ve sayfayฤฑ yenileyebilmelisiniz. + +Ve ฤฐnternet olmasa bile API dokรผmanlarฤฑnฤฑzฤฑ gรถrebilir ve onunla etkileลŸime geรงebilirsiniz. diff --git a/docs/tr/docs/how-to/custom-request-and-route.md b/docs/tr/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..a4419373f7 --- /dev/null +++ b/docs/tr/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ร–zel Request ve APIRoute sฤฑnฤฑfฤฑ { #custom-request-and-apiroute-class } + +Bazฤฑ durumlarda, `Request` ve `APIRoute` sฤฑnฤฑflarฤฑnฤฑn kullandฤฑฤŸฤฑ mantฤฑฤŸฤฑ override etmek isteyebilirsiniz. + +ร–zellikle bu yaklaลŸฤฑm, bir middleware iรงindeki mantฤฑฤŸa iyi bir alternatif olabilir. + +ร–rneฤŸin, request body uygulamanฤฑz tarafฤฑndan iลŸlenmeden รถnce okumak veya รผzerinde deฤŸiลŸiklik yapmak istiyorsanฤฑz. + +/// danger | Uyarฤฑ + +Bu "ileri seviye" bir รถzelliktir. + +**FastAPI**'ye yeni baลŸlฤฑyorsanฤฑz bu bรถlรผmรผ atlamak isteyebilirsiniz. + +/// + +## Kullanฤฑm senaryolarฤฑ { #use-cases } + +Bazฤฑ kullanฤฑm senaryolarฤฑ: + +* JSON olmayan request body'leri JSON'a dรถnรผลŸtรผrmek (รถrn. `msgpack`). +* gzip ile sฤฑkฤฑลŸtฤฑrฤฑlmฤฑลŸ request body'leri aรงmak (decompress). +* Tรผm request body'lerini otomatik olarak loglamak. + +## ร–zel request body encoding'lerini ele alma { #handling-custom-request-body-encodings } + +Gzip request'lerini aรงmak iรงin รถzel bir `Request` alt sฤฑnฤฑfฤฑnฤฑ nasฤฑl kullanabileceฤŸimize bakalฤฑm. + +Ayrฤฑca, o รถzel request sฤฑnฤฑfฤฑnฤฑ kullanmak iรงin bir `APIRoute` alt sฤฑnฤฑfฤฑ da oluลŸturacaฤŸฤฑz. + +### ร–zel bir `GzipRequest` sฤฑnฤฑfฤฑ oluลŸturun { #create-a-custom-gziprequest-class } + +/// tip | ฤฐpucu + +Bu, nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ gรถstermek iรงin hazฤฑrlanmฤฑลŸ basit bir รถrnektir; Gzip desteฤŸine ihtiyacฤฑnฤฑz varsa saฤŸlanan [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} bileลŸenini kullanabilirsiniz. + +/// + +ร–nce, uygun bir header mevcut olduฤŸunda body'yi aรงmak iรงin `Request.body()` metodunu overwrite edecek bir `GzipRequest` sฤฑnฤฑfฤฑ oluลŸturuyoruz. + +Header'da `gzip` yoksa body'yi aรงmayฤฑ denemez. + +Bรถylece aynฤฑ route sฤฑnฤฑfฤฑ, gzip ile sฤฑkฤฑลŸtฤฑrฤฑlmฤฑลŸ veya sฤฑkฤฑลŸtฤฑrฤฑlmamฤฑลŸ request'leri handle edebilir. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ร–zel bir `GzipRoute` sฤฑnฤฑfฤฑ oluลŸturun { #create-a-custom-gziproute-class } + +Sonra, `GzipRequest`'i kullanacak `fastapi.routing.APIRoute` iรงin รถzel bir alt sฤฑnฤฑf oluลŸturuyoruz. + +Bu kez `APIRoute.get_route_handler()` metodunu overwrite edeceฤŸiz. + +Bu metot bir fonksiyon dรถndรผrรผr. Bu fonksiyon da request'i alฤฑr ve response dรถndรผrรผr. + +Burada bu fonksiyonu, orijinal request'ten bir `GzipRequest` oluลŸturmak iรงin kullanฤฑyoruz. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | Teknik Detaylar + +Bir `Request`'in, request ile ilgili metadata'yฤฑ iรงeren bir Python `dict` olan `request.scope` attribute'u vardฤฑr. + +Bir `Request` ayrฤฑca `request.receive` iรงerir; bu, request'in body'sini "almak" (receive etmek) iรงin kullanฤฑlan bir fonksiyondur. + +`scope` `dict`'i ve `receive` fonksiyonu, ASGI spesifikasyonunun parรงalarฤฑdฤฑr. + +Ve bu iki ลŸey, `scope` ve `receive`, yeni bir `Request` instance'ฤฑ oluลŸturmak iรงin gerekenlerdir. + +`Request` hakkฤฑnda daha fazla bilgi iรงin Starlette'ฤฑn Request dokรผmantasyonuna bakฤฑn. + +/// + +`GzipRequest.get_route_handler` tarafฤฑndan dรถndรผrรผlen fonksiyonun farklฤฑ yaptฤฑฤŸฤฑ tek ลŸey, `Request`'i bir `GzipRequest`'e dรถnรผลŸtรผrmektir. + +Bunu yaptฤฑฤŸฤฑmฤฑzda `GzipRequest`, veriyi (gerekliyse) *path operations*'larฤฑmฤฑza geรงirmeden รถnce aรงma (decompress) iลŸini รผstlenir. + +Bundan sonra tรผm iลŸleme mantฤฑฤŸฤฑ aynฤฑdฤฑr. + +Ancak `GzipRequest.body` iรงindeki deฤŸiลŸikliklerimiz sayesinde, request body gerektiฤŸinde **FastAPI** tarafฤฑndan yรผklendiฤŸinde otomatik olarak decompress edilir. + +## Bir exception handler iรงinde request body'ye eriลŸme { #accessing-the-request-body-in-an-exception-handler } + +/// tip | ฤฐpucu + +Aynฤฑ problemi รงรถzmek iรงin, muhtemelen `RequestValidationError` iรงin รถzel bir handler iรงinde `body` kullanmak รงok daha kolaydฤฑr ([Hatalarฤฑ Ele Alma](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). + +Yine de bu รถrnek geรงerlidir ve dahili bileลŸenlerle nasฤฑl etkileลŸime geรงileceฤŸini gรถsterir. + +/// + +Aynฤฑ yaklaลŸฤฑmฤฑ bir exception handler iรงinde request body'ye eriลŸmek iรงin de kullanabiliriz. + +Tek yapmamฤฑz gereken, request'i bir `try`/`except` bloฤŸu iรงinde handle etmek: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +Bir exception oluลŸursa, `Request` instance'ฤฑ hรขlรข scope iรงinde olacaฤŸฤฑ iรงin, hatayฤฑ handle ederken request body'yi okuyup kullanabiliriz: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## Bir router iรงinde รถzel `APIRoute` sฤฑnฤฑfฤฑ { #custom-apiroute-class-in-a-router } + +Bir `APIRouter` iรงin `route_class` parametresini de ayarlayabilirsiniz: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +Bu รถrnekte, `router` altฤฑndaki *path operations*'lar รถzel `TimedRoute` sฤฑnฤฑfฤฑnฤฑ kullanฤฑr ve response'u รผretmek iรงin geรงen sรผreyi iรงeren ekstra bir `X-Response-Time` header'ฤฑ response'ta bulunur: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/tr/docs/how-to/extending-openapi.md b/docs/tr/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..99691946c2 --- /dev/null +++ b/docs/tr/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# OpenAPI'yi GeniลŸletme { #extending-openapi } + +OluลŸturulan OpenAPI ลŸemasฤฑnฤฑ deฤŸiลŸtirmeniz gereken bazฤฑ durumlar olabilir. + +Bu bรถlรผmde bunun nasฤฑl yapฤฑlacaฤŸฤฑnฤฑ gรถreceksiniz. + +## Normal sรผreรง { #the-normal-process } + +Normal (varsayฤฑlan) sรผreรง ลŸรถyledir. + +Bir `FastAPI` uygulamasฤฑnฤฑn (instance) OpenAPI ลŸemasฤฑnฤฑ dรถndรผrmesi beklenen bir `.openapi()` metodu vardฤฑr. + +Uygulama nesnesi oluลŸturulurken, `/openapi.json` (ya da `openapi_url` iรงin ne ayarladฤฑysanฤฑz o) iรงin bir *path operation* kaydedilir. + +Bu path operation, uygulamanฤฑn `.openapi()` metodunun sonucunu iรงeren bir JSON response dรถndรผrรผr. + +Varsayฤฑlan olarak `.openapi()` metodunun yaptฤฑฤŸฤฑ ลŸey, `.openapi_schema` รถzelliฤŸinde iรงerik olup olmadฤฑฤŸฤฑnฤฑ kontrol etmek ve varsa onu dรถndรผrmektir. + +EฤŸer yoksa, `fastapi.openapi.utils.get_openapi` konumundaki yardฤฑmcฤฑ (utility) fonksiyonu kullanarak ลŸemayฤฑ รผretir. + +Ve `get_openapi()` fonksiyonu ลŸu parametreleri alฤฑr: + +* `title`: Dokรผmanlarda gรถsterilen OpenAPI baลŸlฤฑฤŸฤฑ. +* `version`: API'nizin sรผrรผmรผ, รถrn. `2.5.0`. +* `openapi_version`: Kullanฤฑlan OpenAPI specification sรผrรผmรผ. Varsayฤฑlan olarak en gรผnceli: `3.1.0`. +* `summary`: API'nin kฤฑsa รถzeti. +* `description`: API'nizin aรงฤฑklamasฤฑ; markdown iรงerebilir ve dokรผmanlarda gรถsterilir. +* `routes`: route'larฤฑn listesi; bunlarฤฑn her biri kayฤฑtlฤฑ *path operations*'lardฤฑr. `app.routes` iรงinden alฤฑnฤฑrlar. + +/// info | Bilgi + +`summary` parametresi OpenAPI 3.1.0 ve รผzeri sรผrรผmlerde vardฤฑr; FastAPI 0.99.0 ve รผzeri tarafฤฑndan desteklenmektedir. + +/// + +## Varsayฤฑlanlarฤฑ ezme { #overriding-the-defaults } + +Yukarฤฑdaki bilgileri kullanarak aynฤฑ yardฤฑmcฤฑ fonksiyonla OpenAPI ลŸemasฤฑnฤฑ รผretebilir ve ihtiyacฤฑnฤฑz olan her parรงayฤฑ override edebilirsiniz. + +ร–rneฤŸin, รถzel bir logo eklemek iรงin ReDoc'un OpenAPI extension'ฤฑnฤฑ ekleyelim. + +### Normal **FastAPI** { #normal-fastapi } + +ร–nce, tรผm **FastAPI** uygulamanฤฑzฤฑ her zamanki gibi yazฤฑn: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} + +### OpenAPI ลŸemasฤฑnฤฑ รผretme { #generate-the-openapi-schema } + +Ardฤฑndan, bir `custom_openapi()` fonksiyonunun iรงinde aynฤฑ yardฤฑmcฤฑ fonksiyonu kullanarak OpenAPI ลŸemasฤฑnฤฑ รผretin: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} + +### OpenAPI ลŸemasฤฑnฤฑ deฤŸiลŸtirme { #modify-the-openapi-schema } + +Artฤฑk OpenAPI ลŸemasฤฑndaki `info` "object"'ine รถzel bir `x-logo` ekleyerek ReDoc extension'ฤฑnฤฑ ekleyebilirsiniz: + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} + +### OpenAPI ลŸemasฤฑnฤฑ cache'leme { #cache-the-openapi-schema } + +รœrettiฤŸiniz ลŸemayฤฑ saklamak iรงin `.openapi_schema` รถzelliฤŸini bir "cache" gibi kullanabilirsiniz. + +Bรถylece bir kullanฤฑcฤฑ API docs'larฤฑnฤฑzฤฑ her aรงtฤฑฤŸฤฑnda uygulamanฤฑz ลŸemayฤฑ tekrar tekrar รผretmek zorunda kalmaz. + +ลžema yalnฤฑzca bir kez รผretilecektir; sonraki request'ler iรงin de aynฤฑ cache'lenmiลŸ ลŸema kullanฤฑlacaktฤฑr. + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} + +### Metodu override etme { #override-the-method } + +ลžimdi `.openapi()` metodunu yeni fonksiyonunuzla deฤŸiลŸtirebilirsiniz. + +{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} + +### Kontrol edin { #check-it } + +http://127.0.0.1:8000/redoc adresine gittiฤŸinizde, รถzel logonuzu kullandฤฑฤŸฤฑnฤฑzฤฑ gรถreceksiniz (bu รถrnekte **FastAPI**'nin logosu): + + diff --git a/docs/tr/docs/how-to/graphql.md b/docs/tr/docs/how-to/graphql.md new file mode 100644 index 0000000000..fbf0188740 --- /dev/null +++ b/docs/tr/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +**FastAPI**, **ASGI** standardฤฑnฤฑ temel aldฤฑฤŸฤฑ iรงin ASGI ile uyumlu herhangi bir **GraphQL** kรผtรผphanesini entegre etmek oldukรงa kolaydฤฑr. + +Aynฤฑ uygulama iรงinde normal FastAPI *path operation*'larฤฑnฤฑ GraphQL ile birlikte kullanabilirsiniz. + +/// tip | ฤฐpucu + +**GraphQL** bazฤฑ รงok รถzel kullanฤฑm senaryolarฤฑnฤฑ รงรถzer. + +Yaygฤฑn **web API**'lerle karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnda **avantajlarฤฑ** ve **dezavantajlarฤฑ** vardฤฑr. + +Kendi senaryonuz iรงin **faydalarฤฑn**, **olumsuz yรถnleri** telafi edip etmediฤŸini mutlaka deฤŸerlendirin. ๐Ÿค“ + +/// + +## GraphQL Kรผtรผphaneleri { #graphql-libraries } + +AลŸaฤŸฤฑda **ASGI** desteฤŸi olan bazฤฑ **GraphQL** kรผtรผphaneleri var. Bunlarฤฑ **FastAPI** ile kullanabilirsiniz: + +* Strawberry ๐Ÿ“ + * FastAPI dokรผmantasyonu ile +* Ariadne + * FastAPI dokรผmantasyonu ile +* Tartiflette + * ASGI entegrasyonu saฤŸlamak iรงin Tartiflette ASGI ile +* Graphene + * starlette-graphene3 ile + +## Strawberry ile GraphQL { #graphql-with-strawberry } + +**GraphQL** ile รงalฤฑลŸmanฤฑz gerekiyorsa ya da bunu istiyorsanฤฑz, **Strawberry** รถnerilen kรผtรผphanedir; รงรผnkรผ tasarฤฑmฤฑ **FastAPI**'nin tasarฤฑmฤฑna en yakฤฑndฤฑr ve her ลŸey **type annotation**'lar รผzerine kuruludur. + +Kullanฤฑm senaryonuza gรถre farklฤฑ bir kรผtรผphaneyi tercih edebilirsiniz; ancak bana sorarsanฤฑz muhtemelen **Strawberry**'yi denemenizi รถnerirdim. + +Strawberry'yi FastAPI ile nasฤฑl entegre edebileceฤŸinize dair kรผรงรผk bir รถn izleme: + +{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} + +Strawberry hakkฤฑnda daha fazlasฤฑnฤฑ Strawberry dokรผmantasyonunda รถฤŸrenebilirsiniz. + +Ayrฤฑca FastAPI ile Strawberry dokรผmanlarฤฑna da gรถz atฤฑn. + +## Starlette'teki Eski `GraphQLApp` { #older-graphqlapp-from-starlette } + +Starlette'in รถnceki sรผrรผmlerinde Graphene ile entegrasyon iรงin bir `GraphQLApp` sฤฑnฤฑfฤฑ vardฤฑ. + +Bu sฤฑnฤฑf Starlette'te kullanฤฑmdan kaldฤฑrฤฑldฤฑ (deprecated). Ancak bunu kullanan bir kodunuz varsa, aynฤฑ kullanฤฑm senaryosunu kapsayan ve **neredeyse aynฤฑ bir interface** saฤŸlayan starlette-graphene3'e kolayca **migrate** edebilirsiniz. + +/// tip | ฤฐpucu + +GraphQL'e ihtiyacฤฑnฤฑz varsa, custom class ve type'lar yerine type annotation'lara dayandฤฑฤŸฤฑ iรงin yine de Strawberry'yi incelemenizi รถneririm. + +/// + +## Daha Fazlasฤฑnฤฑ ร–ฤŸrenin { #learn-more } + +**GraphQL** hakkฤฑnda daha fazlasฤฑnฤฑ resmi GraphQL dokรผmantasyonunda รถฤŸrenebilirsiniz. + +Ayrฤฑca yukarฤฑda bahsedilen kรผtรผphanelerin her biri hakkฤฑnda, kendi baฤŸlantฤฑlarฤฑndan daha fazla bilgi okuyabilirsiniz. diff --git a/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..275ac5fd17 --- /dev/null +++ b/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# Pydantic v1'den Pydantic v2'ye GeรงiลŸ { #migrate-from-pydantic-v1-to-pydantic-v2 } + +Eski bir FastAPI uygulamanฤฑz varsa, Pydantic'in 1. sรผrรผmรผnรผ kullanฤฑyor olabilirsiniz. + +FastAPI 0.100.0 sรผrรผmรผ, Pydantic v1 veya v2 ile รงalฤฑลŸmayฤฑ destekliyordu. Hangisi kuruluysa onu kullanฤฑyordu. + +FastAPI 0.119.0 sรผrรผmรผ, v2'ye geรงiลŸi kolaylaลŸtฤฑrmak iรงin, Pydantic v2โ€™nin iรงinden Pydantic v1โ€™e (`pydantic.v1` olarak) kฤฑsmi destek ekledi. + +FastAPI 0.126.0 sรผrรผmรผ Pydantic v1 desteฤŸini kaldฤฑrdฤฑ, ancak bir sรผre daha `pydantic.v1` desteฤŸini sรผrdรผrdรผ. + +/// warning | Uyarฤฑ + +Pydantic ekibi, **Python 3.14** ile baลŸlayarak Python'ฤฑn en yeni sรผrรผmleri iรงin Pydantic v1 desteฤŸini sonlandฤฑrdฤฑ. + +Buna `pydantic.v1` de dahildir; Python 3.14 ve รผzeri sรผrรผmlerde artฤฑk desteklenmemektedir. + +Python'ฤฑn en yeni รถzelliklerini kullanmak istiyorsanฤฑz, Pydantic v2 kullandฤฑฤŸฤฑnฤฑzdan emin olmanฤฑz gerekir. + +/// + +Pydantic v1 kullanan eski bir FastAPI uygulamanฤฑz varsa, burada onu Pydantic v2'ye nasฤฑl taลŸฤฑyacaฤŸฤฑnฤฑzฤฑ ve kademeli geรงiลŸi kolaylaลŸtฤฑran **FastAPI 0.119.0 รถzelliklerini** gรถstereceฤŸim. + +## Resmi Kฤฑlavuz { #official-guide } + +Pydantic'in v1'den v2'ye resmi bir Migration Guide'ฤฑ vardฤฑr. + +Ayrฤฑca nelerin deฤŸiลŸtiฤŸini, validasyonlarฤฑn artฤฑk nasฤฑl daha doฤŸru ve katฤฑ olduฤŸunu, olasฤฑ dikkat edilmesi gereken noktalarฤฑ (caveat) vb. de iรงerir. + +Nelerin deฤŸiลŸtiฤŸini daha iyi anlamak iรงin okuyabilirsiniz. + +## Testler { #tests } + +Uygulamanฤฑz iรงin [testlerinizin](../tutorial/testing.md){.internal-link target=_blank} olduฤŸundan ve bunlarฤฑ continuous integration (CI) รผzerinde รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzdan emin olun. + +Bu ลŸekilde yรผkseltmeyi yapabilir ve her ลŸeyin hรขlรข beklendiฤŸi gibi รงalฤฑลŸtฤฑฤŸฤฑnฤฑ doฤŸrulayabilirsiniz. + +## `bump-pydantic` { #bump-pydantic } + +Birรงok durumda, รถzel รถzelleลŸtirmeler olmadan standart Pydantic modelleri kullanฤฑyorsanฤฑz, Pydantic v1'den Pydantic v2'ye geรงiลŸ sรผrecinin bรผyรผk kฤฑsmฤฑnฤฑ otomatikleลŸtirebilirsiniz. + +Aynฤฑ Pydantic ekibinin geliลŸtirdiฤŸi `bump-pydantic` aracฤฑnฤฑ kullanabilirsiniz. + +Bu araรง, deฤŸiลŸmesi gereken kodun bรผyรผk bir kฤฑsmฤฑnฤฑ otomatik olarak dรถnรผลŸtรผrmenize yardฤฑmcฤฑ olur. + +Bundan sonra testleri รงalฤฑลŸtฤฑrฤฑp her ลŸeyin รงalฤฑลŸฤฑp รงalฤฑลŸmadฤฑฤŸฤฑnฤฑ kontrol edebilirsiniz. ร‡alฤฑลŸฤฑyorsa iลŸiniz biter. ๐Ÿ˜Ž + +## v2 ฤฐรงinde Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2, `pydantic.v1` adlฤฑ bir alt modรผl olarak Pydantic v1'in tamamฤฑnฤฑ iรงerir. Ancak bu yapฤฑ, Python 3.13'รผn รผzerindeki sรผrรผmlerde artฤฑk desteklenmemektedir. + +Bu da ลŸu anlama gelir: Pydantic v2'nin en gรผncel sรผrรผmรผnรผ kurup, bu alt modรผlden eski Pydantic v1 bileลŸenlerini import ederek, sanki eski Pydantic v1 kuruluymuลŸ gibi kullanabilirsiniz. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### v2 ฤฐรงinde Pydantic v1 iรงin FastAPI DesteฤŸi { #fastapi-support-for-pydantic-v1-in-v2 } + +FastAPI 0.119.0'dan itibaren, v2'ye geรงiลŸi kolaylaลŸtฤฑrmak iรงin Pydantic v2โ€™nin iรงinden Pydantic v1 kullanฤฑmฤฑna yรถnelik kฤฑsmi destek de vardฤฑr. + +Dolayฤฑsฤฑyla Pydantic'i en gรผncel 2 sรผrรผmรผne yรผkseltip import'larฤฑ `pydantic.v1` alt modรผlรผnรผ kullanacak ลŸekilde deฤŸiลŸtirebilirsiniz; รงoฤŸu durumda bu doฤŸrudan รงalฤฑลŸฤฑr. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | Uyarฤฑ + +Pydantic ekibi Python 3.14'ten itibaren yeni Python sรผrรผmlerinde Pydantic v1'i artฤฑk desteklemediฤŸi iรงin, `pydantic.v1` kullanฤฑmฤฑ da Python 3.14 ve รผzeri sรผrรผmlerde desteklenmez. + +/// + +### Aynฤฑ Uygulamada Pydantic v1 ve v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic aรงฤฑsฤฑndan, alanlarฤฑ (field) Pydantic v1 modelleriyle tanฤฑmlanmฤฑลŸ bir Pydantic v2 modeli (ya da tersi) kullanmak **desteklenmez**. + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...ancak aynฤฑ uygulamada Pydantic v1 ve v2 kullanarak **ayrฤฑ (separated)** modeller tanฤฑmlayabilirsiniz. + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +Bazฤฑ durumlarda, FastAPI uygulamanฤฑzda aynฤฑ **path operation** iรงinde hem Pydantic v1 hem de v2 modellerini kullanmak bile mรผmkรผndรผr: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +Yukarฤฑdaki รถrnekte input modeli bir Pydantic v1 modelidir; output modeli ( `response_model=ItemV2` ile tanฤฑmlanan) ise bir Pydantic v2 modelidir. + +### Pydantic v1 Parametreleri { #pydantic-v1-parameters } + +Pydantic v1 modelleriyle `Body`, `Query`, `Form` vb. parametreler iรงin FastAPI'ye รถzgรผ bazฤฑ araรงlarฤฑ kullanmanฤฑz gerekiyorsa, Pydantic v2'ye geรงiลŸi tamamlayana kadar bunlarฤฑ `fastapi.temp_pydantic_v1_params` iรงinden import edebilirsiniz: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### Adฤฑm Adฤฑm GeรงiลŸ { #migrate-in-steps } + +/// tip | ฤฐpucu + +ร–nce `bump-pydantic` ile deneyin; testleriniz geรงerse ve bu yol รงalฤฑลŸฤฑrsa tek komutla iลŸi bitirmiลŸ olursunuz. โœจ + +/// + +`bump-pydantic` sizin senaryonuz iรงin uygun deฤŸilse, aynฤฑ uygulamada hem Pydantic v1 hem de v2 modellerini birlikte kullanma desteฤŸinden yararlanarak Pydantic v2'ye kademeli ลŸekilde geรงebilirsiniz. + +ร–nce Pydantic'i en gรผncel 2 sรผrรผmรผne yรผkseltip tรผm modelleriniz iรงin import'larฤฑ `pydantic.v1` kullanacak ลŸekilde deฤŸiลŸtirebilirsiniz. + +Ardฤฑndan modellerinizi Pydantic v1'den v2'ye gruplar hรขlinde, adฤฑm adฤฑm taลŸฤฑmaya baลŸlayabilirsiniz. ๐Ÿšถ diff --git a/docs/tr/docs/how-to/separate-openapi-schemas.md b/docs/tr/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..c26411d292 --- /dev/null +++ b/docs/tr/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# Input ve Output iรงin Ayrฤฑ OpenAPI Schema'larฤฑ (Ya da DeฤŸil) { #separate-openapi-schemas-for-input-and-output-or-not } + +**Pydantic v2** yayฤฑnlandฤฑฤŸฤฑndan beri, รผretilen OpenAPI eskisine gรถre biraz daha net ve **doฤŸru**. ๐Ÿ˜Ž + +Hatta bazฤฑ durumlarda, aynฤฑ Pydantic model iรงin OpenAPI iรงinde input ve output tarafฤฑnda, **default deฤŸerler** olup olmamasฤฑna baฤŸlฤฑ olarak **iki farklฤฑ JSON Schema** bile gรถrebilirsiniz. + +Bunun nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna ve gerekirse nasฤฑl deฤŸiลŸtirebileceฤŸinize bir bakalฤฑm. + +## Input ve Output iรงin Pydantic Modelleri { #pydantic-models-for-input-and-output } + +Default deฤŸerleri olan bir Pydantic modeliniz olduฤŸunu varsayalฤฑm; รถrneฤŸin ลŸรถyle: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Input iรงin Model { #model-for-input } + +Bu modeli ลŸรถyle input olarak kullanฤฑrsanฤฑz: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...`description` alanฤฑ **zorunlu olmaz**. ร‡รผnkรผ `None` default deฤŸerine sahiptir. + +### Dokรผmanlarda Input Modeli { #input-model-in-docs } + +Bunu dokรผmanlarda da doฤŸrulayabilirsiniz; `description` alanฤฑnda **kฤฑrmฤฑzฤฑ yฤฑldฤฑz** yoktur, yani required olarak iลŸaretlenmemiลŸtir: + +
+ +
+ +### Output iรงin Model { #model-for-output } + +Ancak aynฤฑ modeli output olarak ลŸรถyle kullanฤฑrsanฤฑz: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...`description` default deฤŸere sahip olduฤŸu iรงin, o alan iรงin **hiรงbir ลŸey dรถndรผrmeseniz** bile yine de **o default deฤŸeri** alฤฑr. + +### Output Response Verisi iรงin Model { #model-for-output-response-data } + +Dokรผmanlarla etkileลŸip response'u kontrol ederseniz, kod `description` alanlarฤฑndan birine bir ลŸey eklememiลŸ olsa bile, JSON response default deฤŸeri (`null`) iรงerir: + +
+ +
+ +Bu, alanฤฑn **her zaman bir deฤŸeri olacaฤŸฤฑ** anlamฤฑna gelir; sadece bazen bu deฤŸer `None` olabilir (JSON'da `null`). + +Dolayฤฑsฤฑyla API'nizi kullanan client'larฤฑn bu deฤŸerin var olup olmadฤฑฤŸฤฑnฤฑ kontrol etmesine gerek yoktur; **alanฤฑn her zaman mevcut olacaฤŸฤฑnฤฑ varsayabilirler**, sadece bazฤฑ durumlarda default deฤŸer olan `None` gelecektir. + +Bunu OpenAPI'de ifade etmenin yolu, bu alanฤฑ **required** olarak iลŸaretlemektir; รงรผnkรผ her zaman yer alacaktฤฑr. + +Bu nedenle, bir modelin JSON Schema'sฤฑ **input mu output mu** kullanฤฑldฤฑฤŸฤฑna gรถre farklฤฑ olabilir: + +* **input** iรงin `description` **required olmaz** +* **output** iรงin **required olur** (ve `None` olabilir; JSON aรงฤฑsฤฑndan `null`) + +### Dokรผmanlarda Output Modeli { #model-for-output-in-docs } + +Dokรผmanlarda output modelini de kontrol edebilirsiniz; **hem** `name` **hem de** `description` alanlarฤฑ **kฤฑrmฤฑzฤฑ yฤฑldฤฑz** ile **required** olarak iลŸaretlenmiลŸtir: + +
+ +
+ +### Dokรผmanlarda Input ve Output Modelleri { #model-for-input-and-output-in-docs } + +OpenAPI iรงindeki tรผm kullanฤฑlabilir Schema'lara (JSON Schema'lara) bakarsanฤฑz, iki tane olduฤŸunu gรถreceksiniz: biri `Item-Input`, diฤŸeri `Item-Output`. + +`Item-Input` iรงin `description` **required deฤŸildir**, kฤฑrmฤฑzฤฑ yฤฑldฤฑz yoktur. + +Ama `Item-Output` iรงin `description` **required**'dฤฑr, kฤฑrmฤฑzฤฑ yฤฑldฤฑz vardฤฑr. + +
+ +
+ +**Pydantic v2**'nin bu รถzelliฤŸiyle API dokรผmantasyonunuz daha **hassas** olur; ayrฤฑca autogenerated client'lar ve SDK'lar kullanฤฑyorsanฤฑz, onlar da daha tutarlฤฑ ve daha iyi bir **developer experience** ile daha doฤŸru รผretilir. ๐ŸŽ‰ + +## Schema'larฤฑ Ayฤฑrma { #do-not-separate-schemas } + +Bazฤฑ durumlarda **input ve output iรงin aynฤฑ schema'yฤฑ** kullanmak isteyebilirsiniz. + +Bunun muhtemelen en yaygฤฑn nedeni, halihazฤฑrda autogenerated client kodlarฤฑnฤฑz/SDK'larฤฑnฤฑzฤฑn olmasฤฑ ve henรผz bunlarฤฑn hepsini gรผncellemek istememenizdir. Bรผyรผk ihtimalle bir noktada gรผncellemek isteyeceksiniz, ama belki ลŸu an deฤŸil. + +Bu durumda **FastAPI**'de bu รถzelliฤŸi `separate_input_output_schemas=False` parametresiyle kapatabilirsiniz. + +/// info | Bilgi + +`separate_input_output_schemas` desteฤŸi FastAPI `0.102.0` sรผrรผmรผnde eklendi. ๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Dokรผmanlarda Input ve Output Modelleri iรงin Aynฤฑ Schema { #same-schema-for-input-and-output-models-in-docs } + +Artฤฑk model iรงin input ve output tarafฤฑnda tek bir schema olur: sadece `Item`. Ayrฤฑca `description` alanฤฑ **required deฤŸildir**: + +
+ +
diff --git a/docs/tr/docs/how-to/testing-database.md b/docs/tr/docs/how-to/testing-database.md new file mode 100644 index 0000000000..a2062f6c26 --- /dev/null +++ b/docs/tr/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Bir Veritabanฤฑnฤฑ Test Etmek { #testing-a-database } + +Veritabanlarฤฑ, SQL ve SQLModel hakkฤฑnda SQLModel dokรผmantasyonundan รถฤŸrenebilirsiniz. ๐Ÿค“ + +Ayrฤฑca SQLModel'i FastAPI ile kullanmaya dair mini bir tutorial da var. โœจ + +Bu tutorial iรงinde SQL veritabanlarฤฑnฤฑ test etme hakkฤฑnda bir bรถlรผm de bulunuyor. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/background-tasks.md b/docs/tr/docs/tutorial/background-tasks.md new file mode 100644 index 0000000000..4cb67d8224 --- /dev/null +++ b/docs/tr/docs/tutorial/background-tasks.md @@ -0,0 +1,84 @@ +# Arka Plan Gรถrevleri { #background-tasks } + +Response dรถndรผrรผldรผkten *sonra* รงalฤฑลŸtฤฑrฤฑlacak arka plan gรถrevleri tanฤฑmlayabilirsiniz. + +Bu, requestโ€™ten sonra yapฤฑlmasฤฑ gereken; ancak clientโ€™ฤฑn responseโ€™u almadan รถnce tamamlanmasฤฑnฤฑ beklemesine gerek olmayan iลŸlemler iรงin kullanฤฑลŸlฤฑdฤฑr. + +ร–rneฤŸin: + +* Bir iลŸlem gerรงekleลŸtirdikten sonra gรถnderilen email bildirimleri: + * Bir email serverโ€™a baฤŸlanmak ve email gรถndermek genellikle "yavaลŸ" olduฤŸundan (birkaรง saniye), responseโ€™u hemen dรถndรผrรผp email bildirimini arka planda gรถnderebilirsiniz. +* Veri iลŸleme: + * ร–rneฤŸin, yavaลŸ bir sรผreรงten geรงmesi gereken bir dosya aldฤฑฤŸฤฑnฤฑzฤฑ dรผลŸรผnรผn; "Accepted" (HTTP 202) responseโ€™u dรถndรผrรผp dosyayฤฑ arka planda iลŸleyebilirsiniz. + +## `BackgroundTasks` Kullanฤฑmฤฑ { #using-backgroundtasks } + +ร–nce `BackgroundTasks`โ€™i import edin ve *path operation function*โ€™ฤฑnฤฑzda `BackgroundTasks` tip bildirimi olan bir parametre tanฤฑmlayฤฑn: + +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} + +**FastAPI**, sizin iรงin `BackgroundTasks` tipinde bir obje oluลŸturur ve onu ilgili parametre olarak geรงirir. + +## Bir Gรถrev Fonksiyonu OluลŸturun { #create-a-task-function } + +Arka plan gรถrevi olarak รงalฤฑลŸtฤฑrฤฑlacak bir fonksiyon oluลŸturun. + +Bu, parametre alabilen standart bir fonksiyondur. + +`async def` de olabilir, normal `def` de olabilir; **FastAPI** bunu doฤŸru ลŸekilde nasฤฑl ele alacaฤŸฤฑnฤฑ bilir. + +Bu รถrnekte gรถrev fonksiyonu bir dosyaya yazacaktฤฑr (email gรถndermeyi simรผle ediyor). + +Ve yazma iลŸlemi `async` ve `await` kullanmadฤฑฤŸฤฑ iรงin fonksiyonu normal `def` ile tanฤฑmlarฤฑz: + +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} + +## Arka Plan Gรถrevini Ekleyin { #add-the-background-task } + +*Path operation function*โ€™ฤฑnฤฑzฤฑn iรงinde, gรถrev fonksiyonunuzu `.add_task()` metodu ile *background tasks* objesine ekleyin: + +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} + +`.add_task()` ลŸu argรผmanlarฤฑ alฤฑr: + +* Arka planda รงalฤฑลŸtฤฑrฤฑlacak bir gรถrev fonksiyonu (`write_notification`). +* Gรถrev fonksiyonuna sฤฑrayla geรงirilecek argรผmanlar (`email`). +* Gรถrev fonksiyonuna geรงirilecek keyword argรผmanlar (`message="some notification"`). + +## Dependency Injection { #dependency-injection } + +`BackgroundTasks` kullanฤฑmฤฑ dependency injection sistemiyle de รงalฤฑลŸฤฑr; `BackgroundTasks` tipinde bir parametreyi birden fazla seviyede tanฤฑmlayabilirsiniz: bir *path operation function* iรงinde, bir dependencyโ€™de (dependable), bir sub-dependencyโ€™de, vb. + +**FastAPI** her durumda ne yapฤฑlacaฤŸฤฑnฤฑ ve aynฤฑ objenin nasฤฑl yeniden kullanฤฑlacaฤŸฤฑnฤฑ bilir; bรถylece tรผm arka plan gรถrevleri birleลŸtirilir ve sonrasฤฑnda arka planda รงalฤฑลŸtฤฑrฤฑlฤฑr: + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + +Bu รถrnekte, response gรถnderildikten *sonra* mesajlar `log.txt` dosyasฤฑna yazฤฑlacaktฤฑr. + +Requestโ€™te bir query varsa, logโ€™a bir arka plan gรถreviyle yazฤฑlฤฑr. + +Ardฤฑndan *path operation function* iรงinde oluลŸturulan baลŸka bir arka plan gรถrevi, `email` path parametresini kullanarak bir mesaj yazar. + +## Teknik Detaylar { #technical-details } + +`BackgroundTasks` sฤฑnฤฑfฤฑ doฤŸrudan `starlette.background`โ€™dan gelir. + +`fastapi` รผzerinden import edebilmeniz ve yanlฤฑลŸlฤฑkla `starlette.background` iรงindeki alternatif `BackgroundTask`โ€™i (sonunda `s` olmadan) import etmemeniz iรงin FastAPIโ€™nin iรงine doฤŸrudan import/eklenmiลŸtir. + +Sadece `BackgroundTasks` (ve `BackgroundTask` deฤŸil) kullanarak, bunu bir *path operation function* parametresi olarak kullanmak ve gerisini **FastAPI**โ€™nin sizin iรงin halletmesini saฤŸlamak mรผmkรผndรผr; tฤฑpkฤฑ `Request` objesini doฤŸrudan kullanฤฑrken olduฤŸu gibi. + +FastAPIโ€™de `BackgroundTask`โ€™i tek baลŸฤฑna kullanmak hรขlรข mรผmkรผndรผr; ancak bu durumda objeyi kendi kodunuzda oluลŸturmanฤฑz ve onu iรงeren bir Starlette `Response` dรถndรผrmeniz gerekir. + +Daha fazla detayฤฑ Starletteโ€™in Background Tasks iรงin resmi dokรผmantasyonunda gรถrebilirsiniz. + +## Dikkat Edilmesi Gerekenler { #caveat } + +YoฤŸun arka plan hesaplamalarฤฑ yapmanฤฑz gerekiyorsa ve bunun aynฤฑ process tarafฤฑndan รงalฤฑลŸtฤฑrฤฑlmasฤฑna ลŸart yoksa (รถrneฤŸin memory, deฤŸiลŸkenler vb. paylaลŸmanฤฑz gerekmiyorsa), Celery gibi daha bรผyรผk araรงlarฤฑ kullanmak size fayda saฤŸlayabilir. + +Bunlar genellikle daha karmaลŸฤฑk konfigurasyonlar ve RabbitMQ veya Redis gibi bir mesaj/iลŸ kuyruฤŸu yรถneticisi gerektirir; ancak arka plan gรถrevlerini birden fazla processโ€™te ve รถzellikle birden fazla serverโ€™da รงalฤฑลŸtฤฑrmanฤฑza olanak tanฤฑrlar. + +Ancak aynฤฑ **FastAPI** appโ€™i iรงindeki deฤŸiลŸkenlere ve objelere eriลŸmeniz gerekiyorsa veya kรผรงรผk arka plan gรถrevleri (email bildirimi gรถndermek gibi) yapacaksanฤฑz, doฤŸrudan `BackgroundTasks` kullanabilirsiniz. + +## ร–zet { #recap } + +Arka plan gรถrevleri eklemek iรงin *path operation function*โ€™larda ve dependencyโ€™lerde parametre olarak `BackgroundTasks`โ€™i import edip kullanฤฑn. diff --git a/docs/tr/docs/tutorial/bigger-applications.md b/docs/tr/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..d8a4b8208b --- /dev/null +++ b/docs/tr/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# Daha Bรผyรผk Uygulamalar - Birden Fazla Dosya { #bigger-applications-multiple-files } + +Bir uygulama veya web API geliลŸtirirken, her ลŸeyi tek bir dosyaya sฤฑฤŸdฤฑrabilmek nadirdir. + +**FastAPI**, tรผm esnekliฤŸi korurken uygulamanฤฑzฤฑ yapฤฑlandฤฑrmanฤฑza yardฤฑmcฤฑ olan pratik bir araรง sunar. + +/// info | Bilgi + +Flask'ten geliyorsanฤฑz, bu yapฤฑ Flask'in Blueprints'ine denk gelir. + +/// + +## ร–rnek Bir Dosya Yapฤฑsฤฑ { #an-example-file-structure } + +Diyelim ki ลŸรถyle bir dosya yapฤฑnฤฑz var: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | ฤฐpucu + +Birden fazla `__init__.py` dosyasฤฑ var: her dizinde veya alt dizinde bir tane. + +Bu sayede bir dosyadaki kodu diฤŸerine import edebilirsiniz. + +ร–rneฤŸin `app/main.py` iรงinde ลŸรถyle bir satฤฑrฤฑnฤฑz olabilir: + +``` +from app.routers import items +``` + +/// + +* `app` dizini her ลŸeyi iรงerir. Ayrฤฑca boลŸ bir `app/__init__.py` dosyasฤฑ olduฤŸu iรงin bir "Python package" (bir "Python module" koleksiyonu) olur: `app`. +* ฤฐรงinde bir `app/main.py` dosyasฤฑ vardฤฑr. Bir Python package'in (iรงinde `__init__.py` dosyasฤฑ olan bir dizinin) iรงinde olduฤŸundan, o package'in bir "module"โ€™รผdรผr: `app.main`. +* Benzer ลŸekilde `app/dependencies.py` dosyasฤฑ da bir "module"โ€™dรผr: `app.dependencies`. +* `app/routers/` adฤฑnda bir alt dizin vardฤฑr ve iรงinde baลŸka bir `__init__.py` dosyasฤฑ bulunur; dolayฤฑsฤฑyla bu bir "Python subpackage"โ€™dir: `app.routers`. +* `app/routers/items.py` dosyasฤฑ `app/routers/` packageโ€™i iรงinde olduฤŸundan bir submoduleโ€™dรผr: `app.routers.items`. +* `app/routers/users.py` iรงin de aynฤฑ ลŸekilde, baลŸka bir submoduleโ€™dรผr: `app.routers.users`. +* `app/internal/` adฤฑnda bir alt dizin daha vardฤฑr ve iรงinde baลŸka bir `__init__.py` dosyasฤฑ bulunur; dolayฤฑsฤฑyla bu da bir "Python subpackage"โ€™dir: `app.internal`. +* Ve `app/internal/admin.py` dosyasฤฑ baลŸka bir submoduleโ€™dรผr: `app.internal.admin`. + + + +Aynฤฑ dosya yapฤฑsฤฑ, yorumlarla birlikte: + +```bash +. +โ”œโ”€โ”€ app # "app" bir Python package'idir +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # bu dosya, "app"i bir "Python package" yapar +โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module'รผ, รถrn. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module'รผ, รถrn. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" bir "Python subpackage"idir +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # "routers"ฤฑ bir "Python subpackage" yapar +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule'รผ, รถrn. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule'รผ, รถrn. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" bir "Python subpackage"idir +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # "internal"ฤฑ bir "Python subpackage" yapar +โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule'รผ, รถrn. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +Diyelim ki sadece kullanฤฑcฤฑlarฤฑ yรถnetmeye ayrฤฑlmฤฑลŸ dosyanฤฑz `/app/routers/users.py` iรงindeki submodule olsun. + +Kullanฤฑcฤฑlarla ilgili *path operation*โ€™larฤฑ, kodun geri kalanฤฑndan ayrฤฑ tutmak istiyorsunuz; bรถylece dรผzenli kalฤฑr. + +Ancak bu hรขlรข aynฤฑ **FastAPI** uygulamasฤฑ/web APIโ€™sinin bir parรงasฤฑdฤฑr (aynฤฑ "Python Package" iรงinde). + +Bu module iรงin *path operation*โ€™larฤฑ `APIRouter` kullanarak oluลŸturabilirsiniz. + +### `APIRouter` Import Edin { #import-apirouter } + +`FastAPI` classโ€™ฤฑnda yaptฤฑฤŸฤฑnฤฑz gibi import edip bir "instance" oluลŸturursunuz: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### `APIRouter` ile *Path Operations* { #path-operations-with-apirouter } + +Sonra bunu kullanarak *path operation*โ€™larฤฑnฤฑzฤฑ tanฤฑmlarsฤฑnฤฑz. + +`FastAPI` classโ€™ฤฑnฤฑ nasฤฑl kullanฤฑyorsanฤฑz aynฤฑ ลŸekilde kullanฤฑn: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +`APIRouter`โ€™ฤฑ "mini bir `FastAPI`" classโ€™ฤฑ gibi dรผลŸรผnebilirsiniz. + +Aynฤฑ seรงeneklerin hepsi desteklenir. + +Aynฤฑ `parameters`, `responses`, `dependencies`, `tags`, vb. + +/// tip | ฤฐpucu + +Bu รถrnekte deฤŸiลŸkenin adฤฑ `router`. Ancak istediฤŸiniz gibi adlandฤฑrabilirsiniz. + +/// + +Bu `APIRouter`โ€™ฤฑ ana `FastAPI` uygulamasฤฑna ekleyeceฤŸiz; ama รถnce dependencyโ€™lere ve bir diฤŸer `APIRouter`โ€™a bakalฤฑm. + +## Dependencies { #dependencies } + +Uygulamanฤฑn birden fazla yerinde kullanฤฑlacak bazฤฑ dependencyโ€™lere ihtiyacฤฑmฤฑz olacaฤŸฤฑnฤฑ gรถrรผyoruz. + +Bu yรผzden onlarฤฑ ayrฤฑ bir `dependencies` moduleโ€™รผne koyuyoruz (`app/dependencies.py`). + +ลžimdi, รถzel bir `X-Token` header'ฤฑnฤฑ okumak iรงin basit bir dependency kullanalฤฑm: + +{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | ฤฐpucu + +ร–rneฤŸi basit tutmak iรงin uydurma bir header kullanฤฑyoruz. + +Ancak gerรงek senaryolarda, entegre [Security yardฤฑmcฤฑ araรงlarฤฑnฤฑ](security/index.md){.internal-link target=_blank} kullanarak daha iyi sonuรง alฤฑrsฤฑnฤฑz. + +/// + +## `APIRouter` ile BaลŸka Bir Module { #another-module-with-apirouter } + +Diyelim ki uygulamanฤฑzdaki "items" ile ilgili endpoint'ler de `app/routers/items.py` moduleโ€™รผnde olsun. + +ลžunlar iรงin *path operation*โ€™larฤฑnฤฑz var: + +* `/items/` +* `/items/{item_id}` + +Bu, `app/routers/users.py` ile aynฤฑ yapฤฑdadฤฑr. + +Ancak biraz daha akฤฑllฤฑ davranฤฑp kodu sadeleลŸtirmek istiyoruz. + +Bu moduleโ€™deki tรผm *path operation*โ€™larฤฑn ลŸu ortak รถzelliklere sahip olduฤŸunu biliyoruz: + +* Path `prefix`: `/items`. +* `tags`: (tek bir tag: `items`). +* Ek `responses`. +* `dependencies`: hepsinin, oluลŸturduฤŸumuz `X-Token` dependencyโ€™sine ihtiyacฤฑ var. + +Dolayฤฑsฤฑyla bunlarฤฑ her *path operation*โ€™a tek tek eklemek yerine `APIRouter`โ€™a ekleyebiliriz. + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +Her *path operation*โ€™ฤฑn pathโ€™i aลŸaฤŸฤฑdaki gibi `/` ile baลŸlamak zorunda olduฤŸundan: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...prefixโ€™in sonunda `/` olmamalฤฑdฤฑr. + +Yani bu รถrnekte prefix `/items` olur. + +Ayrฤฑca, bu router iรงindeki tรผm *path operation*โ€™lara uygulanacak bir `tags` listesi ve ek `responses` da ekleyebiliriz. + +Ve routerโ€™daki tรผm *path operation*โ€™lara eklenecek, her request iรงin รงalฤฑลŸtฤฑrฤฑlฤฑp รงรถzรผlecek bir `dependencies` listesi de ekleyebiliriz. + +/// tip | ฤฐpucu + +[ *path operation decorator*โ€™larฤฑndaki dependencyโ€™lerde](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} olduฤŸu gibi, *path operation function*โ€™ฤฑnฤฑza herhangi bir deฤŸer aktarฤฑlmayacaฤŸฤฑnฤฑ unutmayฤฑn. + +/// + +Sonuรง olarak item pathโ€™leri artฤฑk: + +* `/items/` +* `/items/{item_id}` + +...tam da istediฤŸimiz gibi olur. + +* Hepsi, iรงinde tek bir string `"items"` bulunan bir tag listesiyle iลŸaretlenir. + * Bu "tags", รถzellikle otomatik interaktif dokรผmantasyon sistemleri (OpenAPI) iรงin รงok faydalฤฑdฤฑr. +* Hepsi รถnceden tanฤฑmlฤฑ `responses`โ€™larฤฑ iรงerir. +* Bu *path operation*โ€™larฤฑn hepsinde, รถncesinde `dependencies` listesi deฤŸerlendirilip รงalฤฑลŸtฤฑrฤฑlฤฑr. + * Ayrฤฑca belirli bir *path operation* iรงinde dependency tanฤฑmlarsanฤฑz, **onlar da รงalฤฑลŸtฤฑrฤฑlฤฑr**. + * ร–nce router dependencyโ€™leri, sonra decoratorโ€™daki [`dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, sonra da normal parametre dependencyโ€™leri รงalฤฑลŸฤฑr. + * Ayrฤฑca [`scopes` ile `Security` dependencyโ€™leri](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} de ekleyebilirsiniz. + +/// tip | ฤฐpucu + +`APIRouter` iรงinde `dependencies` kullanmak, รถrneฤŸin bir grup *path operation* iรงin kimlik doฤŸrulamayฤฑ zorunlu kฤฑlmakta kullanฤฑlabilir. Dependencyโ€™leri tek tek her birine eklemeseniz bile. + +/// + +/// check | Ek bilgi + +`prefix`, `tags`, `responses` ve `dependencies` parametreleri (รงoฤŸu baลŸka รถrnekte olduฤŸu gibi) kod tekrarฤฑnฤฑ รถnlemenize yardฤฑmcฤฑ olan, **FastAPI**โ€™nin bir รถzelliฤŸidir. + +/// + +### Dependency'leri Import Edin { #import-the-dependencies } + +Bu kod `app.routers.items` moduleโ€™รผnde, yani `app/routers/items.py` dosyasฤฑnda duruyor. + +Dependency functionโ€™ฤฑnฤฑ ise `app.dependencies` moduleโ€™รผnden, yani `app/dependencies.py` dosyasฤฑndan almamฤฑz gerekiyor. + +Bu yรผzden dependencyโ€™ler iรงin `..` ile relative import kullanฤฑyoruz: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### Relative Import Nasฤฑl ร‡alฤฑลŸฤฑr { #how-relative-imports-work } + +/// tip | ฤฐpucu + +Importโ€™larฤฑn nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ รงok iyi biliyorsanฤฑz, bir sonraki bรถlรผme geรงin. + +/// + +Tek bir nokta `.`, รถrneฤŸin: + +```Python +from .dependencies import get_token_header +``` + +ลŸu anlama gelir: + +* Bu moduleโ€™รผn (yani `app/routers/items.py` dosyasฤฑnฤฑn) bulunduฤŸu package iรงinden baลŸla ( `app/routers/` dizini)... +* `dependencies` moduleโ€™รผnรผ bul (`app/routers/dependencies.py` gibi hayali bir dosya)... +* ve oradan `get_token_header` functionโ€™ฤฑnฤฑ import et. + +Ama o dosya yok; bizim dependencyโ€™lerimiz `app/dependencies.py` dosyasฤฑnda. + +Uygulama/dosya yapฤฑmฤฑzฤฑn nasฤฑl gรถrรผndรผฤŸรผnรผ hatฤฑrlayฤฑn: + + + +--- + +ฤฐki nokta `..`, รถrneฤŸin: + +```Python +from ..dependencies import get_token_header +``` + +ลŸu anlama gelir: + +* Bu moduleโ€™รผn bulunduฤŸu package iรงinden baลŸla (`app/routers/` dizini)... +* รผst (parent) packageโ€™e รงฤฑk (`app/` dizini)... +* burada `dependencies` moduleโ€™รผnรผ bul (`app/dependencies.py` dosyasฤฑ)... +* ve oradan `get_token_header` functionโ€™ฤฑnฤฑ import et. + +Bu doฤŸru ลŸekilde รงalฤฑลŸฤฑr! ๐ŸŽ‰ + +--- + +Aynฤฑ ลŸekilde, รผรง nokta `...` kullansaydฤฑk: + +```Python +from ...dependencies import get_token_header +``` + +ลŸu anlama gelirdi: + +* Bu moduleโ€™รผn bulunduฤŸu package iรงinden baลŸla (`app/routers/` dizini)... +* รผst packageโ€™e รงฤฑk (`app/` dizini)... +* sonra bir รผstรผne daha รงฤฑk (orada bir รผst package yok; `app` en รผst seviye ๐Ÿ˜ฑ)... +* ve orada `dependencies` moduleโ€™รผnรผ bul (`app/dependencies.py` dosyasฤฑ)... +* ve oradan `get_token_header` functionโ€™ฤฑnฤฑ import et. + +Bu, `app/` dizininin รผstรผnde, kendi `__init__.py` dosyasฤฑ olan baลŸka bir packageโ€™e iลŸaret ederdi. Ama bizde bรถyle bir ลŸey yok. Dolayฤฑsฤฑyla bu รถrnekte hata verirdi. ๐Ÿšจ + +Artฤฑk nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ bildiฤŸinize gรถre, uygulamalarฤฑnฤฑz ne kadar karmaลŸฤฑk olursa olsun relative importโ€™larฤฑ kullanabilirsiniz. ๐Ÿค“ + +### ร–zel `tags`, `responses` ve `dependencies` Ekleyin { #add-some-custom-tags-responses-and-dependencies } + +`/items` prefixโ€™ini ya da `tags=["items"]` deฤŸerini her *path operation*โ€™a tek tek eklemiyoruz; รงรผnkรผ bunlarฤฑ `APIRouter`โ€™a ekledik. + +Ama yine de belirli bir *path operation*โ€™a uygulanacak _ek_ `tags` tanฤฑmlayabilir, ayrฤฑca o *path operation*โ€™a รถzel `responses` ekleyebiliriz: + +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | ฤฐpucu + +Bu son *path operation*โ€™da tag kombinasyonu ลŸรถyle olur: `["items", "custom"]`. + +Ayrฤฑca dokรผmantasyonda iki response da gรถrรผnรผr: biri `404`, diฤŸeri `403`. + +/// + +## Ana `FastAPI` { #the-main-fastapi } + +ลžimdi `app/main.py` moduleโ€™รผne bakalฤฑm. + +Burada `FastAPI` classโ€™ฤฑnฤฑ import edip kullanฤฑrsฤฑnฤฑz. + +Bu dosya, uygulamanฤฑzda her ลŸeyi bir araya getiren ana dosya olacak. + +MantฤฑฤŸฤฑn bรผyรผk kฤฑsmฤฑ artฤฑk kendi moduleโ€™lerinde yaลŸayacaฤŸฤฑ iรงin ana dosya oldukรงa basit kalฤฑr. + +### `FastAPI` Import Edin { #import-fastapi } + +Normal ลŸekilde bir `FastAPI` classโ€™ฤฑ oluลŸturursunuz. + +Hatta her `APIRouter` iรงin olan dependencyโ€™lerle birleลŸtirilecek [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank} bile tanฤฑmlayabilirsiniz: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} + +### `APIRouter` Import Edin { #import-the-apirouter } + +ลžimdi `APIRouter` iรงeren diฤŸer submoduleโ€™leri import ediyoruz: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} + +`app/routers/users.py` ve `app/routers/items.py` dosyalarฤฑ aynฤฑ Python packageโ€™i olan `app`โ€™in parรงasฤฑ olan submoduleโ€™ler olduฤŸu iรงin, onlarฤฑ "relative import" ile tek bir nokta `.` kullanarak import edebiliriz. + +### Import Nasฤฑl ร‡alฤฑลŸฤฑr { #how-the-importing-works } + +ลžu bรถlรผm: + +```Python +from .routers import items, users +``` + +ลŸu anlama gelir: + +* Bu moduleโ€™รผn (yani `app/main.py` dosyasฤฑnฤฑn) bulunduฤŸu package iรงinden baลŸla (`app/` dizini)... +* `routers` subpackageโ€™ini bul (`app/routers/` dizini)... +* ve buradan `items` submoduleโ€™รผnรผ (`app/routers/items.py`) ve `users` submoduleโ€™รผnรผ (`app/routers/users.py`) import et... + +`items` moduleโ€™รผnรผn iรงinde `router` adฤฑnda bir deฤŸiลŸken vardฤฑr (`items.router`). Bu, `app/routers/items.py` dosyasฤฑnda oluลŸturduฤŸumuz aynฤฑ deฤŸiลŸkendir; bir `APIRouter` nesnesidir. + +Sonra aynฤฑ iลŸlemi `users` moduleโ€™รผ iรงin de yaparฤฑz. + +Ayrฤฑca ลŸรถyle de import edebilirdik: + +```Python +from app.routers import items, users +``` + +/// info | Bilgi + +ฤฐlk sรผrรผm "relative import"tur: + +```Python +from .routers import items, users +``` + +ฤฐkinci sรผrรผm "absolute import"tur: + +```Python +from app.routers import items, users +``` + +Python Packages ve Modules hakkฤฑnda daha fazlasฤฑ iรงin, Python'ฤฑn Modules ile ilgili resmi dokรผmantasyonunu okuyun. + +/// + +### ฤฐsim ร‡akฤฑลŸmalarฤฑnฤฑ ร–nleyin { #avoid-name-collisions } + +`items` submoduleโ€™รผnรผ doฤŸrudan import ediyoruz; sadece iรงindeki `router` deฤŸiลŸkenini import etmiyoruz. + +ร‡รผnkรผ `users` submoduleโ€™รผnde de `router` adlฤฑ baลŸka bir deฤŸiลŸken var. + +EฤŸer ลŸรถyle sฤฑrayla import etseydik: + +```Python +from .routers.items import router +from .routers.users import router +``` + +`users` iรงindeki `router`, `items` iรงindeki `router`โ€™ฤฑn รผstรผne yazardฤฑ ve ikisini aynฤฑ anda kullanamazdฤฑk. + +Bu yรผzden ikisini de aynฤฑ dosyada kullanabilmek iรงin submoduleโ€™leri doฤŸrudan import ediyoruz: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} + +### `users` ve `items` iรงin `APIRouter`โ€™larฤฑ Dahil Edin { #include-the-apirouters-for-users-and-items } + +ลžimdi `users` ve `items` submoduleโ€™lerindeki `router`โ€™larฤฑ dahil edelim: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} + +/// info | Bilgi + +`users.router`, `app/routers/users.py` dosyasฤฑnฤฑn iรงindeki `APIRouter`โ€™ฤฑ iรงerir. + +`items.router` ise `app/routers/items.py` dosyasฤฑnฤฑn iรงindeki `APIRouter`โ€™ฤฑ iรงerir. + +/// + +`app.include_router()` ile her bir `APIRouter`โ€™ฤฑ ana `FastAPI` uygulamasฤฑna ekleyebiliriz. + +Bรถylece o router iรงindeki tรผm routeโ€™lar uygulamanฤฑn bir parรงasฤฑ olarak dahil edilir. + +/// note | Teknik Detaylar + +Aslฤฑnda iรงeride, `APIRouter` iรงinde tanฤฑmlanan her *path operation* iรงin bir *path operation* oluลŸturur. + +Yani perde arkasฤฑnda, her ลŸey tek bir uygulamaymฤฑลŸ gibi รงalฤฑลŸฤฑr. + +/// + +/// check | Ek bilgi + +Routerโ€™larฤฑ dahil ederken performans konusunda endiลŸelenmeniz gerekmez. + +Bu iลŸlem mikrosaniyeler sรผrer ve sadece startup sฤฑrasฤฑnda olur. + +Dolayฤฑsฤฑyla performansฤฑ etkilemez. โšก + +/// + +### ร–zel `prefix`, `tags`, `responses` ve `dependencies` ile Bir `APIRouter` Dahil Edin { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +ลžimdi, kurumunuzun size `app/internal/admin.py` dosyasฤฑnฤฑ verdiฤŸini dรผลŸรผnelim. + +Bu dosyada, kurumunuzun birden fazla proje arasฤฑnda paylaลŸtฤฑฤŸฤฑ bazฤฑ admin *path operation*โ€™larฤฑnฤฑ iรงeren bir `APIRouter` var. + +Bu รถrnekte รงok basit olacak. Ancak kurum iรงinde baลŸka projelerle paylaลŸฤฑldฤฑฤŸฤฑ iรงin, bunu deฤŸiลŸtirip `prefix`, `dependencies`, `tags` vs. doฤŸrudan `APIRouter`โ€™a ekleyemediฤŸimizi varsayalฤฑm: + +{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +Yine de bu `APIRouter`โ€™ฤฑ dahil ederken รถzel bir `prefix` ayarlamak istiyoruz ki tรผm *path operation*โ€™larฤฑ `/admin` ile baลŸlasฤฑn; ayrฤฑca bu projede hรขlihazฤฑrda kullandฤฑฤŸฤฑmฤฑz `dependencies` ile gรผvene almak, `tags` ve `responses` eklemek istiyoruz. + +Orijinal `APIRouter`โ€™ฤฑ deฤŸiลŸtirmeden, bu parametreleri `app.include_router()`โ€™a vererek hepsini tanฤฑmlayabiliriz: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} + +Bรถylece orijinal `APIRouter` deฤŸiลŸmeden kalฤฑr; yani aynฤฑ `app/internal/admin.py` dosyasฤฑnฤฑ kurum iรงindeki diฤŸer projelerle de paylaลŸmaya devam edebiliriz. + +Sonuรง olarak, uygulamamฤฑzda `admin` moduleโ€™รผndeki her bir *path operation* ลŸunlara sahip olur: + +* `/admin` prefixโ€™i. +* `admin` tagโ€™i. +* `get_token_header` dependencyโ€™si. +* `418` responseโ€™u. ๐Ÿต + +Ancak bu sadece bizim uygulamamฤฑzdaki o `APIRouter` iรงin geรงerlidir; onu kullanan diฤŸer kodlar iรงin deฤŸil. + +Dolayฤฑsฤฑyla รถrneฤŸin diฤŸer projeler aynฤฑ `APIRouter`โ€™ฤฑ farklฤฑ bir authentication yรถntemiyle kullanabilir. + +### Bir *Path Operation* Dahil Edin { #include-a-path-operation } + +*Path operation*โ€™larฤฑ doฤŸrudan `FastAPI` uygulamasฤฑna da ekleyebiliriz. + +Burada bunu yapฤฑyoruz... sadece yapabildiฤŸimizi gรถstermek iรงin ๐Ÿคท: + +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} + +ve `app.include_router()` ile eklenen diฤŸer tรผm *path operation*โ€™larla birlikte doฤŸru ลŸekilde รงalฤฑลŸฤฑr. + +/// info | ร‡ok Teknik Detaylar + +**Not**: Bu oldukรงa teknik bir detay; bรผyรผk ihtimalle **direkt geรงebilirsiniz**. + +--- + +`APIRouter`โ€™lar "mount" edilmez; uygulamanฤฑn geri kalanฤฑndan izole deฤŸildir. + +ร‡รผnkรผ *path operation*โ€™larฤฑnฤฑ OpenAPI ลŸemasฤฑna ve kullanฤฑcฤฑ arayรผzlerine dahil etmek istiyoruz. + +Onlarฤฑ tamamen izole edip baฤŸฤฑmsฤฑz ลŸekilde "mount" edemediฤŸimiz iรงin, *path operation*โ€™lar doฤŸrudan eklenmek yerine "klonlanฤฑr" (yeniden oluลŸturulur). + +/// + +## Otomatik API Dokรผmanฤฑnฤฑ Kontrol Edin { #check-the-automatic-api-docs } + +ลžimdi uygulamanฤฑzฤฑ รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ve dokรผmanlarฤฑ http://127.0.0.1:8000/docs adresinde aรงฤฑn. + +Tรผm submoduleโ€™lerdeki pathโ€™leri, doฤŸru pathโ€™ler (ve prefixโ€™ler) ve doฤŸru tagโ€™lerle birlikte iรงeren otomatik API dokรผmanฤฑnฤฑ gรถreceksiniz: + + + +## Aynฤฑ Router'ฤฑ Farklฤฑ `prefix` ile Birden Fazla Kez Dahil Edin { #include-the-same-router-multiple-times-with-different-prefix } + +`.include_router()` ile aynฤฑ routerโ€™ฤฑ farklฤฑ prefixโ€™ler kullanarak birden fazla kez de dahil edebilirsiniz. + +ร–rneฤŸin aynฤฑ APIโ€™yi `/api/v1` ve `/api/latest` gibi farklฤฑ prefixโ€™ler altฤฑnda sunmak iรงin faydalฤฑ olabilir. + +Bu, muhtemelen ihtiyacฤฑnฤฑz olmayan ileri seviye bir kullanฤฑmdฤฑr; ancak gerekirse diye mevcut. + +## Bir `APIRouter`โ€™ฤฑ BaลŸka Birine Dahil Edin { #include-an-apirouter-in-another } + +Bir `APIRouter`โ€™ฤฑ `FastAPI` uygulamasฤฑna dahil ettiฤŸiniz gibi, bir `APIRouter`โ€™ฤฑ baลŸka bir `APIRouter`โ€™a da ลŸu ลŸekilde dahil edebilirsiniz: + +```Python +router.include_router(other_router) +``` + +`router`โ€™ฤฑ `FastAPI` uygulamasฤฑna dahil etmeden รถnce bunu yaptฤฑฤŸฤฑnฤฑzdan emin olun; bรถylece `other_router` iรงindeki *path operation*โ€™lar da dahil edilmiลŸ olur. diff --git a/docs/tr/docs/tutorial/body-fields.md b/docs/tr/docs/tutorial/body-fields.md new file mode 100644 index 0000000000..6a0f3314a1 --- /dev/null +++ b/docs/tr/docs/tutorial/body-fields.md @@ -0,0 +1,60 @@ +# Body - Alanlar { #body-fields } + +`Query`, `Path` ve `Body` ile *path operation function* parametrelerinde ek doฤŸrulama ve metadata tanฤฑmlayabildiฤŸiniz gibi, Pydantic modellerinin iรงinde de Pydantic'in `Field`'ฤฑnฤฑ kullanarak doฤŸrulama ve metadata tanฤฑmlayabilirsiniz. + +## `Field`'ฤฑ import edin { #import-field } + +ร–nce import etmeniz gerekir: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + +/// warning | Uyarฤฑ + +`Field`'ฤฑn, diฤŸerlerinin (`Query`, `Path`, `Body` vb.) aksine `fastapi`'den deฤŸil doฤŸrudan `pydantic`'den import edildiฤŸine dikkat edin. + +/// + +## Model attribute'larฤฑnฤฑ tanฤฑmlayฤฑn { #declare-model-attributes } + +Ardฤฑndan `Field`'ฤฑ model attribute'larฤฑyla birlikte kullanabilirsiniz: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} + +`Field`, `Query`, `Path` ve `Body` ile aynฤฑ ลŸekilde รงalฤฑลŸฤฑr; aynฤฑ parametrelerin tamamฤฑna sahiptir, vb. + +/// note | Teknik Detaylar + +Aslฤฑnda, `Query`, `Path` ve birazdan gรถreceฤŸiniz diฤŸerleri, ortak bir `Param` sฤฑnฤฑfฤฑnฤฑn alt sฤฑnฤฑflarฤฑndan nesneler oluลŸturur; `Param` sฤฑnฤฑfฤฑ da Pydantic'in `FieldInfo` sฤฑnฤฑfฤฑnฤฑn bir alt sฤฑnฤฑfฤฑdฤฑr. + +Pydantic'in `Field`'ฤฑ da `FieldInfo`'nun bir instance'ฤฑnฤฑ dรถndรผrรผr. + +`Body` ayrฤฑca doฤŸrudan `FieldInfo`'nun bir alt sฤฑnฤฑfฤฑndan nesneler dรถndรผrรผr. Daha sonra gรถreceฤŸiniz baลŸka bazฤฑlarฤฑ da `Body` sฤฑnฤฑfฤฑnฤฑn alt sฤฑnฤฑflarฤฑdฤฑr. + +`fastapi`'den `Query`, `Path` ve diฤŸerlerini import ettiฤŸinizde, bunlarฤฑn aslฤฑnda รถzel sฤฑnฤฑflar dรถndรผren fonksiyonlar olduฤŸunu unutmayฤฑn. + +/// + +/// tip | ฤฐpucu + +Type, varsayฤฑlan deฤŸer ve `Field` ile tanฤฑmlanan her model attribute'unun yapฤฑsฤฑnฤฑn, *path operation function* parametresiyle aynฤฑ olduฤŸuna dikkat edin; sadece `Path`, `Query` ve `Body` yerine `Field` kullanฤฑlmฤฑลŸtฤฑr. + +/// + +## Ek bilgi ekleyin { #add-extra-information } + +`Field`, `Query`, `Body` vb. iรงinde ek bilgi tanฤฑmlayabilirsiniz. Bu bilgiler oluลŸturulan JSON Schema'ya dahil edilir. + +ร–rnek (examples) tanฤฑmlamayฤฑ รถฤŸrenirken, dokรผmanlarฤฑn ilerleyen kฤฑsฤฑmlarฤฑnda ek bilgi ekleme konusunu daha ayrฤฑntฤฑlฤฑ gรถreceksiniz. + +/// warning | Uyarฤฑ + +`Field`'a geรงirilen ekstra key'ler, uygulamanฤฑz iรงin รผretilen OpenAPI schema'sฤฑnda da yer alฤฑr. +Bu key'ler OpenAPI spesifikasyonunun bir parรงasฤฑ olmak zorunda olmadฤฑฤŸฤฑndan, รถrneฤŸin [OpenAPI validator](https://validator.swagger.io/) gibi bazฤฑ OpenAPI araรงlarฤฑ รผretilen schema'nฤฑzla รงalฤฑลŸmayabilir. + +/// + +## ร–zet { #recap } + +Model attribute'larฤฑ iรงin ek doฤŸrulamalar ve metadata tanฤฑmlamak รผzere Pydantic'in `Field`'ฤฑnฤฑ kullanabilirsiniz. + +Ayrฤฑca, ek keyword argument'larฤฑ kullanarak JSON Schema'ya ekstra metadata da iletebilirsiniz. diff --git a/docs/tr/docs/tutorial/body-multiple-params.md b/docs/tr/docs/tutorial/body-multiple-params.md new file mode 100644 index 0000000000..3bac80d6a8 --- /dev/null +++ b/docs/tr/docs/tutorial/body-multiple-params.md @@ -0,0 +1,175 @@ +# Body - Birden Fazla Parametre { #body-multiple-parameters } + +Artฤฑk `Path` ve `Query` kullanmayฤฑ gรถrdรผฤŸรผmรผze gรถre, request body bildirimlerinin daha ileri kullanฤฑm senaryolarฤฑna bakalฤฑm. + +## `Path`, `Query` ve body parametrelerini karฤฑลŸtฤฑrma { #mix-path-query-and-body-parameters } + +ร–ncelikle, elbette `Path`, `Query` ve request body parametre bildirimlerini serbestรงe karฤฑลŸtฤฑrabilirsiniz ve **FastAPI** ne yapacaฤŸฤฑnฤฑ bilir. + +Ayrฤฑca, varsayฤฑlan deฤŸeri `None` yaparak body parametrelerini opsiyonel olarak da tanฤฑmlayabilirsiniz: + +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} + +/// note | Not + +Bu durumda body'den alฤฑnacak `item` opsiyoneldir. ร‡รผnkรผ varsayฤฑlan deฤŸeri `None` olarak ayarlanmฤฑลŸtฤฑr. + +/// + +## Birden fazla body parametresi { #multiple-body-parameters } + +ร–nceki รถrnekte, *path operation*'lar `Item`'ฤฑn รถzelliklerini iรงeren bir JSON body beklerdi, รถrneฤŸin: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +Ancak birden fazla body parametresi de tanฤฑmlayabilirsiniz; รถrneฤŸin `item` ve `user`: + +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} + + +Bu durumda **FastAPI**, fonksiyonda birden fazla body parametresi olduฤŸunu fark eder (iki parametre de Pydantic modelidir). + +Bunun รผzerine, body iรงinde anahtar (field name) olarak parametre adlarฤฑnฤฑ kullanฤฑr ve ลŸu ลŸekilde bir body bekler: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +/// note | Not + +`item` daha รถncekiyle aynฤฑ ลŸekilde tanฤฑmlanmฤฑลŸ olsa bile, artฤฑk body iรงinde `item` anahtarฤฑ altฤฑnda gelmesi beklenir. + +/// + +**FastAPI**, request'ten otomatik dรถnรผลŸรผmรผ yapar; bรถylece `item` parametresi kendi iรงeriฤŸini alฤฑr, `user` iรงin de aynฤฑ ลŸekilde olur. + +BirleลŸik verinin validasyonunu yapar ve OpenAPI ลŸemasฤฑ ile otomatik dokรผmantasyonda da bunu bu ลŸekilde dokรผmante eder. + +## Body iรงinde tekil deฤŸerler { #singular-values-in-body } + +Query ve path parametreleri iรงin ek veri tanฤฑmlamak รผzere `Query` ve `Path` olduฤŸu gibi, **FastAPI** bunlarฤฑn karลŸฤฑlฤฑฤŸฤฑ olarak `Body` de saฤŸlar. + +ร–rneฤŸin, รถnceki modeli geniลŸleterek, aynฤฑ body iรงinde `item` ve `user` dฤฑลŸฤฑnda bir de `importance` anahtarฤฑ olmasฤฑnฤฑ isteyebilirsiniz. + +Bunu olduฤŸu gibi tanฤฑmlarsanฤฑz, tekil bir deฤŸer olduฤŸu iรงin **FastAPI** bunun bir query parametresi olduฤŸunu varsayar. + +Ama `Body` kullanarak, **FastAPI**'ye bunu body iรงinde baลŸka bir anahtar olarak ele almasฤฑnฤฑ sรถyleyebilirsiniz: + +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} + + +Bu durumda **FastAPI** ลŸu ลŸekilde bir body bekler: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` + +Yine veri tiplerini dรถnรผลŸtรผrรผr, validate eder, dokรผmante eder, vb. + +## Birden fazla body parametresi ve query { #multiple-body-params-and-query } + +Elbette ihtiyaรง duyduฤŸunuzda, body parametrelerine ek olarak query parametreleri de tanฤฑmlayabilirsiniz. + +Varsayฤฑlan olarak tekil deฤŸerler query parametresi olarak yorumlandฤฑฤŸฤฑ iรงin, ayrฤฑca `Query` eklemeniz gerekmez; ลŸรถyle yazmanฤฑz yeterlidir: + +```Python +q: Union[str, None] = None +``` + +Ya da Python 3.10 ve รผzeri iรงin: + +```Python +q: str | None = None +``` + +ร–rneฤŸin: + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} + + +/// info | Bilgi + +`Body`, `Query`, `Path` ve daha sonra gรถreceฤŸiniz diฤŸerleriyle aynฤฑ ek validasyon ve metadata parametrelerine de sahiptir. + +/// + +## Tek bir body parametresini gรถmme { #embed-a-single-body-parameter } + +Diyelim ki Pydantic'teki `Item` modelinden gelen yalnฤฑzca tek bir `item` body parametreniz var. + +Varsayฤฑlan olarak **FastAPI**, body'nin doฤŸrudan bu modelin iรงeriฤŸi olmasฤฑnฤฑ bekler. + +Ancak, ek body parametreleri tanฤฑmladฤฑฤŸฤฑnฤฑzda olduฤŸu gibi, `item` anahtarฤฑ olan bir JSON ve onun iรงinde modelin iรงeriฤŸini beklemesini istiyorsanฤฑz, `Body`'nin รถzel parametresi olan `embed`'i kullanabilirsiniz: + +```Python +item: Item = Body(embed=True) +``` + +yani ลŸรถyle: + +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + + +Bu durumda **FastAPI** ลŸu ลŸekilde bir body bekler: + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +ลŸunun yerine: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## ร–zet { #recap } + +Bir request yalnฤฑzca tek bir body iรงerebilse de, *path operation function*'ฤฑnฤฑza birden fazla body parametresi ekleyebilirsiniz. + +Ancak **FastAPI** bunu yรถnetir; fonksiyonunuza doฤŸru veriyi verir ve *path operation* iรงinde doฤŸru ลŸemayฤฑ validate edip dokรผmante eder. + +Ayrฤฑca tekil deฤŸerlerin body'nin bir parรงasฤฑ olarak alฤฑnmasฤฑnฤฑ da tanฤฑmlayabilirsiniz. + +Ve yalnฤฑzca tek bir parametre tanฤฑmlanmฤฑลŸ olsa bile, **FastAPI**'ye body'yi bir anahtarฤฑn iรงine gรถmmesini sรถyleyebilirsiniz. diff --git a/docs/tr/docs/tutorial/body-nested-models.md b/docs/tr/docs/tutorial/body-nested-models.md new file mode 100644 index 0000000000..b4ffef3f15 --- /dev/null +++ b/docs/tr/docs/tutorial/body-nested-models.md @@ -0,0 +1,220 @@ +# Body - ฤฐรง ฤฐรงe Modeller { #body-nested-models } + +**FastAPI** ile (Pydantic sayesinde) istediฤŸiniz kadar derin iรง iรงe geรงmiลŸ modelleri tanฤฑmlayabilir, doฤŸrulayabilir, dokรผmante edebilir ve kullanabilirsiniz. + +## List alanlarฤฑ { #list-fields } + +Bir attributeโ€™u bir alt tipe sahip olacak ลŸekilde tanฤฑmlayabilirsiniz. ร–rneฤŸin, bir Python `list`: + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +Bu, `tags`โ€™in bir list olmasฤฑnฤฑ saฤŸlar; ancak listโ€™in elemanlarฤฑnฤฑn tipini belirtmez. + +## Tip parametresi olan list alanlarฤฑ { #list-fields-with-type-parameter } + +Ancak Pythonโ€™da, iรง tipleri olan listโ€™leri (ya da "type parameter" iรงeren tipleri) tanฤฑmlamanฤฑn belirli bir yolu vardฤฑr: + +### Tip parametresiyle bir `list` tanฤฑmlayฤฑn { #declare-a-list-with-a-type-parameter } + +`list`, `dict`, `tuple` gibi type parameter (iรง tip) alan tipleri tanฤฑmlamak iรงin, iรง tipi(leri) kรถลŸeli parantezlerle "type parameter" olarak verin: `[` ve `]` + +```Python +my_list: list[str] +``` + +Bu, tip tanฤฑmlarฤฑ iรงin standart Python sรถzdizimidir. + +ฤฐรง tipleri olan model attributeโ€™larฤฑ iรงin de aynฤฑ standart sรถzdizimini kullanฤฑn. + +Dolayฤฑsฤฑyla รถrneฤŸimizde, `tags`โ€™i รถzel olarak bir "string listโ€™i" yapabiliriz: + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## Set tipleri { #set-types } + +Sonra bunu dรผลŸรผnรผnce, tagโ€™lerin tekrar etmemesi gerektiฤŸini fark ederiz; bรผyรผk ihtimalle benzersiz stringโ€™ler olmalฤฑdฤฑr. + +Pythonโ€™da benzersiz รถฤŸelerden oluลŸan kรผmeler iรงin รถzel bir veri tipi vardฤฑr: `set`. + +O zaman `tags`โ€™i stringโ€™lerden oluลŸan bir set olarak tanฤฑmlayabiliriz: + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +Bรถylece duplicate veri iรงeren bir request alsanฤฑz bile, bu veri benzersiz รถฤŸelerden oluลŸan bir setโ€™e dรถnรผลŸtรผrรผlรผr. + +Ve bu veriyi ne zaman output etseniz, kaynakta duplicate olsa bile, benzersiz รถฤŸelerden oluลŸan bir set olarak output edilir. + +Ayrฤฑca buna gรถre annotate / dokรผmante edilir. + +## ฤฐรง ฤฐรงe Modeller { #nested-models } + +Bir Pydantic modelinin her attributeโ€™unun bir tipi vardฤฑr. + +Ancak bu tip, kendi baลŸฤฑna baลŸka bir Pydantic modeli de olabilir. + +Yani belirli attribute adlarฤฑ, tipleri ve validation kurallarฤฑyla derin iรง iรงe JSON "object"leri tanฤฑmlayabilirsiniz. + +Hem de istediฤŸiniz kadar iรง iรงe. + +### Bir alt model tanฤฑmlayฤฑn { #define-a-submodel } + +ร–rneฤŸin bir `Image` modeli tanฤฑmlayabiliriz: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### Alt modeli tip olarak kullanฤฑn { #use-the-submodel-as-a-type } + +Ardฤฑndan bunu bir attributeโ€™un tipi olarak kullanabiliriz: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +Bu da **FastAPI**โ€™nin aลŸaฤŸฤฑdakine benzer bir body bekleyeceฤŸi anlamฤฑna gelir: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Yine, sadece bu tanฤฑmฤฑ yaparak **FastAPI** ile ลŸunlarฤฑ elde edersiniz: + +* Editรถr desteฤŸi (tamamlama vb.), iรง iรงe modeller iรงin bile +* Veri dรถnรผลŸtรผrme +* Veri doฤŸrulama (validation) +* Otomatik dokรผmantasyon + +## ร–zel tipler ve doฤŸrulama { #special-types-and-validation } + +`str`, `int`, `float` vb. normal tekil tiplerin yanฤฑnda, `str`โ€™den tรผreyen daha karmaลŸฤฑk tekil tipleri de kullanabilirsiniz. + +Tรผm seรงenekleri gรถrmek iรงin Pydantic Type Overview sayfasฤฑna gรถz atฤฑn. Sonraki bรถlรผmde bazฤฑ รถrnekleri gรถreceksiniz. + +ร–rneฤŸin `Image` modelinde bir `url` alanฤฑmฤฑz olduฤŸuna gรถre, bunu `str` yerine Pydanticโ€™in `HttpUrl` tipinden bir instance olacak ลŸekilde tanฤฑmlayabiliriz: + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +Stringโ€™in geรงerli bir URL olup olmadฤฑฤŸฤฑ kontrol edilir ve JSON Schema / OpenAPIโ€™de de buna gรถre dokรผmante edilir. + +## Alt modellerden oluลŸan listโ€™lere sahip attributeโ€™lar { #attributes-with-lists-of-submodels } + +Pydantic modellerini `list`, `set` vb. tiplerin alt tipi olarak da kullanabilirsiniz: + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +Bu, aลŸaฤŸฤฑdaki gibi bir JSON body bekler (dรถnรผลŸtรผrรผr, doฤŸrular, dokรผmante eder vb.): + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// info | Bilgi + +`images` keyโ€™inin artฤฑk image objectโ€™lerinden oluลŸan bir list iรงerdiฤŸine dikkat edin. + +/// + +## ร‡ok derin iรง iรงe modeller { #deeply-nested-models } + +ฤฐstediฤŸiniz kadar derin iรง iรงe modeller tanฤฑmlayabilirsiniz: + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// info | Bilgi + +`Offer`โ€™ฤฑn bir `Item` listโ€™i olduฤŸuna, `Item`โ€™larฤฑn da opsiyonel bir `Image` listโ€™ine sahip olduฤŸuna dikkat edin. + +/// + +## Sadece list olan bodyโ€™ler { #bodies-of-pure-lists } + +BeklediฤŸiniz JSON bodyโ€™nin en รผst seviye deฤŸeri bir JSON `array` (Pythonโ€™da `list`) ise, tipi Pydantic modellerinde olduฤŸu gibi fonksiyonun parametresinde tanฤฑmlayabilirsiniz: + +```Python +images: list[Image] +``` + +ลŸu รถrnekte olduฤŸu gibi: + +{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} + +## Her yerde editรถr desteฤŸi { #editor-support-everywhere } + +Ve her yerde editรถr desteฤŸi alฤฑrsฤฑnฤฑz. + +List iรงindeki รถฤŸeler iรงin bile: + + + +Pydantic modelleri yerine doฤŸrudan `dict` ile รงalฤฑลŸsaydฤฑnฤฑz bu tรผr bir editรถr desteฤŸini alamazdฤฑnฤฑz. + +Ancak bunlarla uฤŸraลŸmanฤฑz da gerekmez; gelen dictโ€™ler otomatik olarak dรถnรผลŸtรผrรผlรผr ve outputโ€™unuz da otomatik olarak JSONโ€™a รงevrilir. + +## Rastgele `dict` bodyโ€™leri { #bodies-of-arbitrary-dicts } + +Bodyโ€™yi, keyโ€™leri bir tipte ve valueโ€™larฤฑ baลŸka bir tipte olan bir `dict` olarak da tanฤฑmlayabilirsiniz. + +Bu ลŸekilde (Pydantic modellerinde olduฤŸu gibi) geรงerli field/attribute adlarฤฑnฤฑn รถnceden ne olduฤŸunu bilmeniz gerekmez. + +Bu, รถnceden bilmediฤŸiniz keyโ€™leri almak istediฤŸiniz durumlarda faydalฤฑdฤฑr. + +--- + +Bir diฤŸer faydalฤฑ durum da keyโ€™lerin baลŸka bir tipte olmasฤฑnฤฑ istediฤŸiniz zamandฤฑr (รถr. `int`). + +Burada gรถreceฤŸimiz ลŸey de bu. + +Bu durumda, `int` keyโ€™lere ve `float` valueโ€™lara sahip olduฤŸu sรผrece herhangi bir `dict` kabul edersiniz: + +{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} + +/// tip | ฤฐpucu + +JSON key olarak yalnฤฑzca `str` destekler, bunu unutmayฤฑn. + +Ancak Pydantic otomatik veri dรถnรผลŸtรผrme yapar. + +Yani API clientโ€™larฤฑnฤฑz keyโ€™leri sadece string olarak gรถnderebilse bile, bu stringโ€™ler saf tamsayฤฑ iรงeriyorsa Pydantic bunlarฤฑ dรถnรผลŸtรผrรผr ve doฤŸrular. + +Ve `weights` olarak aldฤฑฤŸฤฑnฤฑz `dict`, gerรงekte `int` keyโ€™lere ve `float` valueโ€™lara sahip olur. + +/// + +## ร–zet { #recap } + +**FastAPI** ile Pydantic modellerinin saฤŸladฤฑฤŸฤฑ en yรผksek esnekliฤŸi elde ederken, kodunuzu da basit, kฤฑsa ve ลŸฤฑk tutarsฤฑnฤฑz. + +รœstelik tรผm avantajlarla birlikte: + +* Editรถr desteฤŸi (her yerde tamamlama!) +* Veri dรถnรผลŸtรผrme (diฤŸer adฤฑyla parsing / serialization) +* Veri doฤŸrulama (validation) +* Schema dokรผmantasyonu +* Otomatik dokรผmanlar diff --git a/docs/tr/docs/tutorial/body-updates.md b/docs/tr/docs/tutorial/body-updates.md new file mode 100644 index 0000000000..a9ad13d2ee --- /dev/null +++ b/docs/tr/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Body - Gรผncellemeler { #body-updates } + +## `PUT` ile deฤŸiลŸtirerek gรผncelleme { #update-replacing-with-put } + +Bir รถฤŸeyi gรผncellemek iรงin HTTP `PUT` operasyonunu kullanabilirsiniz. + +Girdi verisini JSON olarak saklanabilecek bir formata (รถr. bir NoSQL veritabanฤฑ ile) dรถnรผลŸtรผrmek iรงin `jsonable_encoder` kullanabilirsiniz. ร–rneฤŸin, `datetime` deฤŸerlerini `str`'ye รงevirmek gibi. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT`, mevcut verinin yerine geรงmesi gereken veriyi almak iรงin kullanฤฑlฤฑr. + +### DeฤŸiลŸtirerek gรผncelleme uyarฤฑsฤฑ { #warning-about-replacing } + +Bu, `bar` รถฤŸesini `PUT` ile, body iรงinde ลŸu verilerle gรผncellemek isterseniz: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +zaten kayฤฑtlฤฑ olan `"tax": 20.2` alanฤฑnฤฑ iรงermediฤŸi iรงin, input model `"tax": 10.5` varsayฤฑlan deฤŸerini kullanacaktฤฑr. + +Ve veri, bu "yeni" `tax` deฤŸeri olan `10.5` ile kaydedilecektir. + +## `PATCH` ile kฤฑsmi gรผncellemeler { #partial-updates-with-patch } + +Veriyi *kฤฑsmen* gรผncellemek iรงin HTTP `PATCH` operasyonunu da kullanabilirsiniz. + +Bu, yalnฤฑzca gรผncellemek istediฤŸiniz veriyi gรถnderip, geri kalanฤฑnฤฑ olduฤŸu gibi bฤฑrakabileceฤŸiniz anlamฤฑna gelir. + +/// note | Not + +`PATCH`, `PUT`'a gรถre daha az yaygฤฑn kullanฤฑlฤฑr ve daha az bilinir. + +Hatta birรงok ekip, kฤฑsmi gรผncellemeler iรงin bile yalnฤฑzca `PUT` kullanฤฑr. + +Bunlarฤฑ nasฤฑl isterseniz รถyle kullanmakta **รถzgรผrsรผnรผz**; **FastAPI** herhangi bir kฤฑsฤฑtlama dayatmaz. + +Ancak bu kฤฑlavuz, aลŸaฤŸฤฑ yukarฤฑ, bunlarฤฑn nasฤฑl kullanฤฑlmasฤฑ amaรงlandฤฑฤŸฤฑnฤฑ gรถsterir. + +/// + +### Pydantic'in `exclude_unset` parametresini kullanma { #using-pydantics-exclude-unset-parameter } + +Kฤฑsmi gรผncellemeler almak istiyorsanฤฑz, Pydantic modelinin `.model_dump()` metodundaki `exclude_unset` parametresini kullanmak รงok faydalฤฑdฤฑr. + +ร–rneฤŸin: `item.model_dump(exclude_unset=True)`. + +Bu, `item` modeli oluลŸturulurken set edilmiลŸ verileri iรงeren; varsayฤฑlan deฤŸerleri hariรง tutan bir `dict` รผretir. + +Sonrasฤฑnda bunu, yalnฤฑzca set edilmiลŸ (request'te gรถnderilmiลŸ) veriyi iรงeren; varsayฤฑlan deฤŸerleri atlayan bir `dict` รผretmek iรงin kullanabilirsiniz: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Pydantic'in `update` parametresini kullanma { #using-pydantics-update-parameter } + +Artฤฑk `.model_copy()` ile mevcut modelin bir kopyasฤฑnฤฑ oluลŸturup, gรผncellenecek verileri iรงeren bir `dict` ile `update` parametresini geรงebilirsiniz. + +ร–rneฤŸin: `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### Kฤฑsmi gรผncellemeler รถzeti { #partial-updates-recap } + +ร–zetle, kฤฑsmi gรผncelleme uygulamak iรงin ลŸunlarฤฑ yaparsฤฑnฤฑz: + +* (ฤฐsteฤŸe baฤŸlฤฑ olarak) `PUT` yerine `PATCH` kullanฤฑn. +* Kayฤฑtlฤฑ veriyi alฤฑn. +* Bu veriyi bir Pydantic modeline koyun. +* Input modelinden, varsayฤฑlan deฤŸerler olmadan bir `dict` รผretin (`exclude_unset` kullanarak). + * Bu ลŸekilde, modelinizdeki varsayฤฑlan deฤŸerlerle daha รถnce saklanmฤฑลŸ deฤŸerlerin รผzerine yazmak yerine, yalnฤฑzca kullanฤฑcฤฑnฤฑn gerรงekten set ettiฤŸi deฤŸerleri gรผncellersiniz. +* Kayฤฑtlฤฑ modelin bir kopyasฤฑnฤฑ oluลŸturun ve alฤฑnan kฤฑsmi gรผncellemeleri kullanarak attribute'larฤฑnฤฑ gรผncelleyin (`update` parametresini kullanarak). +* Kopyalanan modeli DB'nizde saklanabilecek bir ลŸeye dรถnรผลŸtรผrรผn (รถr. `jsonable_encoder` kullanarak). + * Bu, modelin `.model_dump()` metodunu yeniden kullanmaya benzer; ancak deฤŸerlerin JSON'a dรถnรผลŸtรผrรผlebilecek veri tiplerine รงevrilmesini garanti eder (รถr. `datetime` -> `str`). +* Veriyi DB'nize kaydedin. +* GรผncellenmiลŸ modeli dรถndรผrรผn. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | ฤฐpucu + +Aynฤฑ tekniฤŸi HTTP `PUT` operasyonu ile de kullanabilirsiniz. + +Ancak buradaki รถrnek `PATCH` kullanฤฑyor, รงรผnkรผ bu kullanฤฑm senaryolarฤฑ iรงin tasarlanmฤฑลŸtฤฑr. + +/// + +/// note | Not + +Input modelin yine de doฤŸrulandฤฑฤŸฤฑna dikkat edin. + +Dolayฤฑsฤฑyla, tรผm attribute'larฤฑn atlanabildiฤŸi kฤฑsmi gรผncellemeler almak istiyorsanฤฑz, tรผm attribute'larฤฑ optional olarak iลŸaretlenmiลŸ (varsayฤฑlan deฤŸerlerle veya `None` ile) bir modele ihtiyacฤฑnฤฑz vardฤฑr. + +**Gรผncelleme** iรงin tรผm deฤŸerleri optional olan modeller ile **oluลŸturma** iรงin zorunlu deฤŸerlere sahip modelleri ayฤฑrmak iรงin, [Extra Models](extra-models.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑlan fikirleri kullanabilirsiniz. + +/// diff --git a/docs/tr/docs/tutorial/body.md b/docs/tr/docs/tutorial/body.md new file mode 100644 index 0000000000..0557ef737a --- /dev/null +++ b/docs/tr/docs/tutorial/body.md @@ -0,0 +1,166 @@ +# Request Body { #request-body } + +Bir client'ten (รถrneฤŸin bir tarayฤฑcฤฑdan) API'nize veri gรถndermeniz gerektiฤŸinde, bunu **request body** olarak gรถnderirsiniz. + +Bir **request** body, client'in API'nize gรถnderdiฤŸi veridir. Bir **response** body ise API'nizin client'e gรถnderdiฤŸi veridir. + +API'niz neredeyse her zaman bir **response** body gรถndermek zorundadฤฑr. Ancak client'lerin her zaman **request body** gรถndermesi gerekmez; bazen sadece bir path isterler, belki birkaรง query parametresiyle birlikte, ama body gรถndermezler. + +Bir **request** body tanฤฑmlamak iรงin, tรผm gรผcรผ ve avantajlarฤฑyla Pydantic modellerini kullanฤฑrsฤฑnฤฑz. + +/// info | Bilgi + +Veri gรถndermek iรงin ลŸunlardan birini kullanmalฤฑsฤฑnฤฑz: `POST` (en yaygฤฑnฤฑ), `PUT`, `DELETE` veya `PATCH`. + +`GET` request'i ile body gรถndermek, spesifikasyonlarda tanฤฑmsฤฑz bir davranฤฑลŸtฤฑr; yine de FastAPI bunu yalnฤฑzca รงok karmaลŸฤฑk/uรง kullanฤฑm senaryolarฤฑ iรงin destekler. + +ร–nerilmediฤŸi iรงin Swagger UI ile etkileลŸimli dokรผmanlar, `GET` kullanฤฑrken body iรงin dokรผmantasyonu gรถstermez ve aradaki proxy'ler bunu desteklemeyebilir. + +/// + +## Pydantic'in `BaseModel`'ini import edin { #import-pydantics-basemodel } + +ร–nce, `pydantic` iรงinden `BaseModel`'i import etmeniz gerekir: + +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} + +## Veri modelinizi oluลŸturun { #create-your-data-model } + +Sonra veri modelinizi, `BaseModel`'den kalฤฑtฤฑm alan bir class olarak tanฤฑmlarsฤฑnฤฑz. + +Tรผm attribute'lar iรงin standart Python type'larฤฑnฤฑ kullanฤฑn: + +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + + +Query parametrelerini tanฤฑmlarken olduฤŸu gibi, bir model attribute'รผ default bir deฤŸere sahipse zorunlu deฤŸildir. Aksi halde zorunludur. Sadece opsiyonel yapmak iรงin `None` kullanฤฑn. + +ร–rneฤŸin, yukarฤฑdaki model ลŸu ลŸekilde bir JSON "`object`" (veya Python `dict`) tanฤฑmlar: + +```JSON +{ + "name": "Foo", + "description": "An optional description", + "price": 45.2, + "tax": 3.5 +} +``` + +...`description` ve `tax` opsiyonel olduฤŸu iรงin (default deฤŸerleri `None`), ลŸu JSON "`object`" da geรงerli olur: + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## Parametre olarak tanฤฑmlayฤฑn { #declare-it-as-a-parameter } + +Bunu *path operation*'ฤฑnฤฑza eklemek iรงin, path ve query parametrelerini tanฤฑmladฤฑฤŸฤฑnฤฑz ลŸekilde tanฤฑmlayฤฑn: + +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} + +...ve type'ฤฑnฤฑ, oluลŸturduฤŸunuz model olan `Item` olarak belirtin. + +## Sonuรงlar { #results } + +Sadece bu Python type tanฤฑmฤฑyla, **FastAPI** ลŸunlarฤฑ yapar: + +* Request'in body'sini JSON olarak okur. +* ฤฐlgili type'lara dรถnรผลŸtรผrรผr (gerekirse). +* Veriyi doฤŸrular (validate eder). + * Veri geรงersizse, tam olarak nerede ve hangi verinin hatalฤฑ olduฤŸunu sรถyleyen, anlaลŸฤฑlฤฑr bir hata dรถndรผrรผr. +* AldฤฑฤŸฤฑ veriyi `item` parametresi iรงinde size verir. + * Fonksiyonda bunun type'ฤฑnฤฑ `Item` olarak tanฤฑmladฤฑฤŸฤฑnฤฑz iรงin, tรผm attribute'lar ve type'larฤฑ iรงin editor desteฤŸini (tamamlama vb.) de alฤฑrsฤฑnฤฑz. +* Modeliniz iรงin JSON Schema tanฤฑmlarฤฑ รผretir; projeniz iรงin anlamlฤฑysa bunlarฤฑ baลŸka yerlerde de kullanabilirsiniz. +* Bu ลŸemalar รผretilen OpenAPI ลŸemasฤฑnฤฑn bir parรงasฤฑ olur ve otomatik dokรผmantasyon UIs tarafฤฑndan kullanฤฑlฤฑr. + +## Otomatik dokรผmanlar { #automatic-docs } + +Modellerinizin JSON Schema'larฤฑ, OpenAPI tarafฤฑndan รผretilen ลŸemanฤฑn bir parรงasฤฑ olur ve etkileลŸimli API dokรผmanlarฤฑnda gรถsterilir: + + + +Ayrฤฑca, ihtiyaรง duyan her *path operation* iรงindeki API dokรผmanlarฤฑnda da kullanฤฑlฤฑr: + + + +## Editor desteฤŸi { #editor-support } + +Editor'รผnรผzde, fonksiyonunuzun iรงinde her yerde type hint'leri ve tamamlama (completion) alฤฑrsฤฑnฤฑz (Pydantic modeli yerine `dict` alsaydฤฑnฤฑz bu olmazdฤฑ): + + + +YanlฤฑลŸ type iลŸlemleri iรงin hata kontrolleri de alฤฑrsฤฑnฤฑz: + + + +Bu bir tesadรผf deฤŸil; tรผm framework bu tasarฤฑmฤฑn etrafฤฑnda inลŸa edildi. + +Ayrฤฑca, bunun tรผm editor'lerle รงalฤฑลŸacaฤŸฤฑndan emin olmak iรงin herhangi bir implementasyon yapฤฑlmadan รถnce tasarฤฑm aลŸamasฤฑnda kapsamlฤฑ ลŸekilde test edildi. + +Hatta bunu desteklemek iรงin Pydantic'in kendisinde bile bazฤฑ deฤŸiลŸiklikler yapฤฑldฤฑ. + +ร–nceki ekran gรถrรผntรผleri Visual Studio Code ile alฤฑnmฤฑลŸtฤฑr. + +Ancak PyCharm ve diฤŸer Python editor'lerinin รงoฤŸunda da aynฤฑ editor desteฤŸini alฤฑrsฤฑnฤฑz: + + + +/// tip | ฤฐpucu + +Editor olarak PyCharm kullanฤฑyorsanฤฑz, Pydantic PyCharm Plugin kullanabilirsiniz. + +Pydantic modelleri iรงin editor desteฤŸini ลŸu aรงฤฑlardan iyileลŸtirir: + +* auto-completion +* type checks +* refactoring +* searching +* inspections + +/// + +## Modeli kullanฤฑn { #use-the-model } + +Fonksiyonun iรงinde model nesnesinin tรผm attribute'larฤฑna doฤŸrudan eriลŸebilirsiniz: + +{* ../../docs_src/body/tutorial002_py310.py *} + +## Request body + path parametreleri { #request-body-path-parameters } + +Path parametrelerini ve request body'yi aynฤฑ anda tanฤฑmlayabilirsiniz. + +**FastAPI**, path parametreleriyle eลŸleลŸen fonksiyon parametrelerinin **path'ten alฤฑnmasฤฑ** gerektiฤŸini ve Pydantic model olarak tanฤฑmlanan fonksiyon parametrelerinin **request body'den alฤฑnmasฤฑ** gerektiฤŸini anlayacaktฤฑr. + +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + + +## Request body + path + query parametreleri { #request-body-path-query-parameters } + +**body**, **path** ve **query** parametrelerini aynฤฑ anda da tanฤฑmlayabilirsiniz. + +**FastAPI** bunlarฤฑn her birini tanฤฑr ve veriyi doฤŸru yerden alฤฑr. + +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} + +Fonksiyon parametreleri ลŸu ลŸekilde tanฤฑnฤฑr: + +* Parametre, **path** iรงinde de tanฤฑmlฤฑysa path parametresi olarak kullanฤฑlฤฑr. +* Parametre **tekil bir type**'taysa (`int`, `float`, `str`, `bool` vb.), **query** parametresi olarak yorumlanฤฑr. +* Parametre bir **Pydantic model** type'ฤฑ olarak tanฤฑmlandฤฑysa, request **body** olarak yorumlanฤฑr. + +/// note | Not + +FastAPI, `q` deฤŸerinin zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` default deฤŸerinden anlayacaktฤฑr. + +`str | None` (Python 3.10+) veya `Union[str, None]` (Python 3.9+) iรงindeki `Union`, FastAPI tarafฤฑndan bu deฤŸerin zorunlu olmadฤฑฤŸฤฑnฤฑ belirlemek iรงin kullanฤฑlmaz; FastAPI bunun zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` default deฤŸeri olduฤŸu iรงin bilir. + +Ancak type annotation'larฤฑnฤฑ eklemek, editor'รผnรผzรผn size daha iyi destek vermesini ve hatalarฤฑ yakalamasฤฑnฤฑ saฤŸlar. + +/// + +## Pydantic olmadan { #without-pydantic } + +Pydantic modellerini kullanmak istemiyorsanฤฑz, **Body** parametrelerini de kullanabilirsiniz. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} dokรผmanฤฑna bakฤฑn. diff --git a/docs/tr/docs/tutorial/cookie-param-models.md b/docs/tr/docs/tutorial/cookie-param-models.md new file mode 100644 index 0000000000..a5bf515609 --- /dev/null +++ b/docs/tr/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Cookie Parameter Models { #cookie-parameter-models } + +Birbirleriyle iliลŸkili bir **cookie** grubunuz varsa, bunlarฤฑ tanฤฑmlamak iรงin bir **Pydantic model** oluลŸturabilirsiniz. + +Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tรผm parametreler iรงin validation ve metadata'yฤฑ tek seferde tanฤฑmlayabilirsiniz. + +/// note | Not + +Bu รถzellik FastAPI `0.115.0` sรผrรผmรผnden beri desteklenmektedir. + +/// + +/// tip | ฤฐpucu + +Aynฤฑ teknik `Query`, `Cookie` ve `Header` iรงin de geรงerlidir. + +/// + +## Pydantic Model ile Cookies { #cookies-with-a-pydantic-model } + +ฤฐhtiyacฤฑnฤฑz olan **cookie** parametrelerini bir **Pydantic model** iรงinde tanฤฑmlayฤฑn ve ardฤฑndan parametreyi `Cookie` olarak bildirin: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI**, request ile gelen **cookies** iรงinden **her bir field** iรงin veriyi **extract** eder ve size tanฤฑmladฤฑฤŸฤฑnฤฑz Pydantic model'i verir. + +## Dokรผmanlarฤฑ Kontrol Edin { #check-the-docs } + +Tanฤฑmlanan cookie'leri `/docs` altฤฑndaki docs UI'da gรถrebilirsiniz: + +
+ +
+ +/// info | Bilgi + +Tarayฤฑcฤฑlarฤฑn cookie'leri รถzel biรงimlerde ve arka planda yรถnetmesi nedeniyle, **JavaScript**'in cookie'lere eriลŸmesine kolayca izin vermediฤŸini aklฤฑnฤฑzda bulundurun. + +`/docs` altฤฑndaki **API docs UI**'a giderseniz, *path operation*'larฤฑnฤฑz iรงin cookie'lerin **dokรผmantasyonunu** gรถrebilirsiniz. + +Ancak verileri **doldurup** "Execute" dรผฤŸmesine tฤฑklasanฤฑz bile, docs UI **JavaScript** ile รงalฤฑลŸtฤฑฤŸฤฑ iรงin cookie'ler gรถnderilmez; dolayฤฑsฤฑyla hiรง deฤŸer girmemiลŸsiniz gibi bir **error** mesajฤฑ gรถrรผrsรผnรผz. + +/// + +## Fazladan Cookies'leri Yasaklayฤฑn { #forbid-extra-cookies } + +Bazฤฑ รถzel kullanฤฑm senaryolarฤฑnda (muhtemelen รงok yaygฤฑn deฤŸildir) almak istediฤŸiniz cookie'leri **kฤฑsฤฑtlamak** isteyebilirsiniz. + +API'niz artฤฑk kendi cookie consent'ฤฑnฤฑ kontrol etme gรผcรผne sahip. + +Pydantic'in model configuration'ฤฑnฤฑ kullanarak `extra` olan herhangi bir field'ฤฑ `forbid` edebilirsiniz: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} + +Bir client **fazladan cookie** gรถndermeye รงalฤฑลŸฤฑrsa, bir **error** response alฤฑr. + +Onayฤฑnฤฑzฤฑ almak iรงin bunca รงaba harcayan zavallฤฑ cookie banner'larฤฑ... API'nin bunu reddetmesi iรงin. + +ร–rneฤŸin client, deฤŸeri `good-list-please` olan bir `santa_tracker` cookie'si gรถndermeye รงalฤฑลŸฤฑrsa, client `santa_tracker` cookie is not allowed diyen bir **error** response alฤฑr: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## ร–zet { #summary } + +**FastAPI**'de **cookies** tanฤฑmlamak iรงin **Pydantic model**'lerini kullanabilirsiniz. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/cors.md b/docs/tr/docs/tutorial/cors.md new file mode 100644 index 0000000000..aae560022a --- /dev/null +++ b/docs/tr/docs/tutorial/cors.md @@ -0,0 +1,89 @@ +# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } + +CORS veya "Cross-Origin Resource Sharing", tarayฤฑcฤฑda รงalฤฑลŸan bir frontendโ€™in JavaScript kodunun bir backend ile iletiลŸim kurduฤŸu ve backendโ€™in frontendโ€™den farklฤฑ bir "origin"de olduฤŸu durumlarฤฑ ifade eder. + +## Origin { #origin } + +Origin; protocol (`http`, `https`), domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`) ve portโ€™un (`80`, `443`, `8080`) birleลŸimidir. + +Dolayฤฑsฤฑyla ลŸunlarฤฑn hepsi farklฤฑ originโ€™lerdir: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Hepsi `localhost` รผzerinde olsa bile, farklฤฑ protocol veya port kullandฤฑklarฤฑ iรงin farklฤฑ "origin" sayฤฑlฤฑrlar. + +## Adฤฑmlar { #steps } + +Diyelim ki tarayฤฑcฤฑnฤฑzda `http://localhost:8080` adresinde รงalฤฑลŸan bir frontendโ€™iniz var ve JavaScriptโ€™i, `http://localhost` adresinde รงalฤฑลŸan bir backend ile iletiลŸim kurmaya รงalฤฑลŸฤฑyor (port belirtmediฤŸimiz iรงin tarayฤฑcฤฑ varsayฤฑlan port olan `80`โ€™i kullanacaktฤฑr). + +Bu durumda tarayฤฑcฤฑ, `:80`-backendโ€™e bir HTTP `OPTIONS` requestโ€™i gรถnderir. EฤŸer backend, bu farklฤฑ originโ€™den (`http://localhost:8080`) gelen iletiลŸimi yetkilendiren uygun headerโ€™larฤฑ gรถnderirse, `:8080`-tarayฤฑcฤฑ frontendโ€™deki JavaScriptโ€™in `:80`-backendโ€™e request gรถndermesine izin verir. + +Bunu saฤŸlayabilmek iรงin `:80`-backendโ€™in bir "allowed origins" listesi olmalฤฑdฤฑr. + +Bu รถrnekte `:8080`-frontendโ€™in doฤŸru รงalฤฑลŸmasฤฑ iรงin listede `http://localhost:8080` bulunmalฤฑdฤฑr. + +## Wildcard'lar { #wildcards } + +Listeyi `"*"` (bir "wildcard") olarak tanฤฑmlayฤฑp, hepsine izin verildiฤŸini sรถylemek de mรผmkรผndรผr. + +Ancak bu, credentials iรงeren her ลŸeyi hariรง tutarak yalnฤฑzca belirli iletiลŸim tรผrlerine izin verir: Cookieโ€™ler, Bearer Tokenโ€™larla kullanฤฑlanlar gibi Authorization headerโ€™larฤฑ, vb. + +Bu yรผzden her ลŸeyin dรผzgรผn รงalฤฑลŸmasฤฑ iรงin, izin verilen originโ€™leri aรงฤฑkรงa belirtmek daha iyidir. + +## `CORSMiddleware` Kullanฤฑmฤฑ { #use-corsmiddleware } + +Bunu **FastAPI** uygulamanฤฑzda `CORSMiddleware` ile yapฤฑlandฤฑrabilirsiniz. + +* `CORSMiddleware`โ€™i import edin. +* ฤฐzin verilen originโ€™lerden (string) oluลŸan bir liste oluลŸturun. +* Bunu **FastAPI** uygulamanฤฑza bir "middleware" olarak ekleyin. + +Ayrฤฑca backendโ€™in ลŸunlara izin verip vermediฤŸini de belirtebilirsiniz: + +* Credentials (Authorization headerโ€™larฤฑ, Cookieโ€™ler, vb). +* Belirli HTTP methodโ€™larฤฑ (`POST`, `PUT`) veya wildcard `"*"` ile hepsini. +* Belirli HTTP headerโ€™larฤฑ veya wildcard `"*"` ile hepsini. + +{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} + + +`CORSMiddleware` implementasyonu tarafฤฑndan kullanฤฑlan varsayฤฑlan parametreler kฤฑsฤฑtlayฤฑcฤฑdฤฑr; bu nedenle tarayฤฑcฤฑlarฤฑn Cross-Domain baฤŸlamฤฑnda kullanmasฤฑna izin vermek iรงin belirli originโ€™leri, methodโ€™larฤฑ veya headerโ€™larฤฑ aรงฤฑkรงa etkinleลŸtirmeniz gerekir. + +AลŸaฤŸฤฑdaki argรผmanlar desteklenir: + +* `allow_origins` - Cross-origin request yapmasฤฑna izin verilmesi gereken originโ€™lerin listesi. ร–rn. `['https://example.org', 'https://www.example.org']`. Herhangi bir originโ€™e izin vermek iรงin `['*']` kullanabilirsiniz. +* `allow_origin_regex` - Cross-origin request yapmasฤฑna izin verilmesi gereken originโ€™lerle eลŸleลŸecek bir regex stringโ€™i. ร–rn. `'https://.*\.example\.org'`. +* `allow_methods` - Cross-origin requestโ€™lerde izin verilmesi gereken HTTP methodโ€™larฤฑnฤฑn listesi. Varsayฤฑlanฤฑ `['GET']`. Tรผm standart methodโ€™lara izin vermek iรงin `['*']` kullanabilirsiniz. +* `allow_headers` - Cross-origin requestโ€™lerde desteklenmesi gereken HTTP request headerโ€™larฤฑnฤฑn listesi. Varsayฤฑlanฤฑ `[]`. Tรผm headerโ€™lara izin vermek iรงin `['*']` kullanabilirsiniz. `Accept`, `Accept-Language`, `Content-Language` ve `Content-Type` headerโ€™larฤฑna basit CORS request'leri iรงin her zaman izin verilir. +* `allow_credentials` - Cross-origin requestโ€™ler iรงin cookie desteฤŸi olup olmayacaฤŸฤฑnฤฑ belirtir. Varsayฤฑlanฤฑ `False`. + + `allow_credentials` `True` olarak ayarlanmฤฑลŸsa, `allow_origins`, `allow_methods` ve `allow_headers` deฤŸerlerinin hiรงbiri `['*']` olamaz. Hepsinin aรงฤฑkรงa belirtilmesi gerekir. + +* `expose_headers` - Tarayฤฑcฤฑnฤฑn eriลŸebilmesi gereken response headerโ€™larฤฑnฤฑ belirtir. Varsayฤฑlanฤฑ `[]`. +* `max_age` - Tarayฤฑcฤฑlarฤฑn CORS responseโ€™larฤฑnฤฑ cacheโ€™lemesi iรงin saniye cinsinden azami sรผreyi ayarlar. Varsayฤฑlanฤฑ `600`. + +Middleware iki รถzel HTTP request tรผrรผne yanฤฑt verir... + +### CORS preflight request'leri { #cors-preflight-requests } + +Bunlar, `Origin` ve `Access-Control-Request-Method` headerโ€™larฤฑna sahip herhangi bir `OPTIONS` requestโ€™idir. + +Bu durumda middleware gelen requestโ€™i intercept eder ve uygun CORS headerโ€™larฤฑyla yanฤฑt verir; bilgilendirme amaรงlฤฑ olarak da `200` veya `400` response dรถndรผrรผr. + +### Basit request'ler { #simple-requests } + +`Origin` headerโ€™ฤฑ olan herhangi bir request. Bu durumda middleware requestโ€™i normal ลŸekilde geรงirir, ancak responseโ€™a uygun CORS headerโ€™larฤฑnฤฑ ekler. + +## Daha Fazla Bilgi { #more-info } + +CORS hakkฤฑnda daha fazla bilgi iรงin Mozilla CORS dokรผmantasyonuna bakฤฑn. + +/// note | Teknik Detaylar + +`from starlette.middleware.cors import CORSMiddleware` ลŸeklinde de kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olmasฤฑ iรงin `fastapi.middleware` iรงinde bazฤฑ middlewareโ€™ler saฤŸlar. Ancak mevcut middlewareโ€™lerin รงoฤŸu doฤŸrudan Starletteโ€™ten gelir. + +/// diff --git a/docs/tr/docs/tutorial/debugging.md b/docs/tr/docs/tutorial/debugging.md new file mode 100644 index 0000000000..54d5c9252a --- /dev/null +++ b/docs/tr/docs/tutorial/debugging.md @@ -0,0 +1,113 @@ +# Debugging { #debugging } + +Visual Studio Code veya PyCharm gibi editรถrรผnรผzde debugger'ฤฑ baฤŸlayabilirsiniz. + +## `uvicorn`'ฤฑ ร‡aฤŸฤฑrma { #call-uvicorn } + +FastAPI uygulamanฤฑzda `uvicorn`'ฤฑ import edip doฤŸrudan รงalฤฑลŸtฤฑrฤฑn: + +{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} + +### `__name__ == "__main__"` Hakkฤฑnda { #about-name-main } + +`__name__ == "__main__"` ifadesinin temel amacฤฑ, dosyanฤฑz ลŸu ลŸekilde รงaฤŸrฤฑldฤฑฤŸฤฑnda รงalฤฑลŸacak: + +
+ +```console +$ python myapp.py +``` + +
+ +ancak baลŸka bir dosya onu import ettiฤŸinde รงalฤฑลŸmayacak bir kod bรถlรผmรผne sahip olmaktฤฑr, รถrneฤŸin: + +```Python +from myapp import app +``` + +#### Daha fazla detay { #more-details } + +Dosyanฤฑzฤฑn adฤฑnฤฑn `myapp.py` olduฤŸunu varsayalฤฑm. + +ลžu ลŸekilde รงalฤฑลŸtฤฑrฤฑrsanฤฑz: + +
+ +```console +$ python myapp.py +``` + +
+ +Python tarafฤฑndan otomatik oluลŸturulan, dosyanฤฑzฤฑn iรงindeki `__name__` adlฤฑ dahili deฤŸiลŸkenin deฤŸeri `"__main__"` string'i olur. + +Dolayฤฑsฤฑyla ลŸu bรถlรผm: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +รงalฤฑลŸฤฑr. + +--- + +Ancak modรผlรผ (dosyayฤฑ) import ederseniz bu gerรงekleลŸmez. + +Yani รถrneฤŸin `importer.py` adฤฑnda baลŸka bir dosyanฤฑz var ve iรงinde ลŸunlar bulunuyorsa: + +```Python +from myapp import app + +# Some more code +``` + +bu durumda `myapp.py` iรงindeki otomatik oluลŸturulan `__name__` deฤŸiลŸkeni `"__main__"` deฤŸerine sahip olmaz. + +Bu yรผzden ลŸu satฤฑr: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +รงalฤฑลŸtฤฑrฤฑlmaz. + +/// info | Bilgi + +Daha fazla bilgi iรงin resmi Python dokรผmantasyonuna bakฤฑn. + +/// + +## Kodunuzu Debugger ile ร‡alฤฑลŸtฤฑrma { #run-your-code-with-your-debugger } + +Uvicorn server'ฤฑnฤฑ doฤŸrudan kodunuzdan รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑz iรงin, Python programฤฑnฤฑzฤฑ (FastAPI uygulamanฤฑzฤฑ) debugger'dan doฤŸrudan baลŸlatabilirsiniz. + +--- + +ร–rneฤŸin Visual Studio Code'da ลŸunlarฤฑ yapabilirsiniz: + +* "Debug" paneline gidin. +* "Add configuration..." seรงin. +* "Python" seรงin +* "`Python: Current File (Integrated Terminal)`" seรงeneฤŸiyle debugger'ฤฑ รงalฤฑลŸtฤฑrฤฑn. + +Bรถylece server, **FastAPI** kodunuzla baลŸlar; breakpoint'lerinizde durur vb. + +AลŸaฤŸฤฑdaki gibi gรถrรผnebilir: + + + +--- + +PyCharm kullanฤฑyorsanฤฑz ลŸunlarฤฑ yapabilirsiniz: + +* "Run" menรผsรผnรผ aรงฤฑn. +* "Debug..." seรงeneฤŸini seรงin. +* Bir context menรผ aรงฤฑlฤฑr. +* Debug edilecek dosyayฤฑ seรงin (bu รถrnekte `main.py`). + +Bรถylece server, **FastAPI** kodunuzla baลŸlar; breakpoint'lerinizde durur vb. + +AลŸaฤŸฤฑdaki gibi gรถrรผnebilir: + + diff --git a/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 0000000000..9ee57cb291 --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# Dependency Olarak Class'lar { #classes-as-dependencies } + +**Dependency Injection** sistemine daha derinlemesine geรงmeden รถnce, bir รถnceki รถrneฤŸi geliลŸtirelim. + +## ร–nceki ร–rnekten Bir `dict` { #a-dict-from-the-previous-example } + +ร–nceki รถrnekte, dependency'mizden ("dependable") bir `dict` dรถndรผrรผyorduk: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +Ama sonra *path operation function* iรงindeki `commons` parametresinde bir `dict` alฤฑyoruz. + +Ve biliyoruz ki editor'ler `dict`'ler iรงin รงok fazla destek (รถr. completion) veremez; รงรผnkรผ key'lerini ve value type'larฤฑnฤฑ bilemezler. + +Daha iyisini yapabiliriz... + +## Bir ลžeyi Dependency Yapan Nedir { #what-makes-a-dependency } + +ลžimdiye kadar dependency'leri function olarak tanฤฑmlanmฤฑลŸ ลŸekilde gรถrdรผnรผz. + +Ancak dependency tanฤฑmlamanฤฑn tek yolu bu deฤŸil (muhtemelen en yaygฤฑnฤฑ bu olsa da). + +Buradaki kritik nokta, bir dependency'nin "callable" olmasฤฑ gerektiฤŸidir. + +Python'da "**callable**", Python'ฤฑn bir function gibi "รงaฤŸฤฑrabildiฤŸi" her ลŸeydir. + +Yani elinizde `something` adlฤฑ bir nesne varsa (function _olmak zorunda deฤŸil_) ve onu ลŸรถyle "รงaฤŸฤฑrabiliyorsanฤฑz" (รงalฤฑลŸtฤฑrabiliyorsanฤฑz): + +```Python +something() +``` + +veya + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +o zaman bu bir "callable" demektir. + +## Dependency Olarak Class'lar { #classes-as-dependencies_1 } + +Python'da bir class'tan instance oluลŸtururken de aynฤฑ sรถz dizimini kullandฤฑฤŸฤฑnฤฑzฤฑ fark etmiลŸ olabilirsiniz. + +ร–rneฤŸin: + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +Bu durumda `fluffy`, `Cat` class'ฤฑnฤฑn bir instance'ฤฑdฤฑr. + +Ve `fluffy` oluลŸturmak iรงin `Cat`'i "รงaฤŸฤฑrmฤฑลŸ" olursunuz. + +Dolayฤฑsฤฑyla bir Python class'ฤฑ da bir **callable**'dฤฑr. + +O zaman **FastAPI** iรงinde bir Python class'ฤฑnฤฑ dependency olarak kullanabilirsiniz. + +FastAPI'nin aslฤฑnda kontrol ettiฤŸi ลŸey, bunun bir "callable" olmasฤฑ (function, class ya da baลŸka bir ลŸey) ve tanฤฑmlฤฑ parametreleridir. + +EฤŸer **FastAPI**'de bir dependency olarak bir "callable" verirseniz, FastAPI o "callable" iรงin parametreleri analiz eder ve bunlarฤฑ *path operation function* parametreleriyle aynฤฑ ลŸekilde iลŸler. Sub-dependency'ler dahil. + +Bu, hiรง parametresi olmayan callable'lar iรงin de geรงerlidir. Tฤฑpkฤฑ hiรง parametresi olmayan *path operation function*'larda olduฤŸu gibi. + +O zaman yukarฤฑdaki `common_parameters` adlฤฑ "dependable" dependency'sini `CommonQueryParams` class'ฤฑna รงevirebiliriz: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +Class instance'ฤฑnฤฑ oluลŸturmak iรงin kullanฤฑlan `__init__` metoduna dikkat edin: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +...bizim รถnceki `common_parameters` ile aynฤฑ parametrelere sahip: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +Bu parametreler, dependency'yi "รงรถzmek" iรงin **FastAPI**'nin kullanacaฤŸฤฑ ลŸeylerdir. + +Her iki durumda da ลŸunlar olacak: + +* `str` olan opsiyonel bir `q` query parametresi. +* Default deฤŸeri `0` olan `int` tipinde bir `skip` query parametresi. +* Default deฤŸeri `100` olan `int` tipinde bir `limit` query parametresi. + +Her iki durumda da veriler dรถnรผลŸtรผrรผlecek, doฤŸrulanacak, OpenAPI ลŸemasฤฑnda dokรผmante edilecek, vb. + +## Kullanalฤฑm { #use-it } + +Artฤฑk bu class'ฤฑ kullanarak dependency'nizi tanฤฑmlayabilirsiniz. + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI**, `CommonQueryParams` class'ฤฑnฤฑ รงaฤŸฤฑrฤฑr. Bu, o class'ฤฑn bir "instance"ฤฑnฤฑ oluลŸturur ve bu instance, sizin function'ฤฑnฤฑza `commons` parametresi olarak geรงirilir. + +## Type Annotation vs `Depends` { #type-annotation-vs-depends } + +Yukarฤฑdaki kodda `CommonQueryParams`'ฤฑ iki kez yazdฤฑฤŸฤฑmฤฑza dikkat edin: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +ลžuradaki son `CommonQueryParams`: + +```Python +... Depends(CommonQueryParams) +``` + +...FastAPI'nin dependency'nin ne olduฤŸunu anlamak iรงin gerรงekten kullandฤฑฤŸฤฑ ลŸeydir. + +FastAPI tanฤฑmlanan parametreleri buradan รงฤฑkarฤฑr ve aslฤฑnda รงaฤŸฤฑracaฤŸฤฑ ลŸey de budur. + +--- + +Bu durumda, ลŸuradaki ilk `CommonQueryParams`: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +...**FastAPI** iรงin รถzel bir anlam taลŸฤฑmaz. FastAPI bunu veri dรถnรผลŸtรผrme, doฤŸrulama vb. iรงin kullanmaz (รงรผnkรผ bunlar iรงin `Depends(CommonQueryParams)` kullanฤฑyor). + +Hatta ลŸunu bile yazabilirsiniz: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +...ลŸu รถrnekte olduฤŸu gibi: + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +Ancak type'ฤฑ belirtmeniz รถnerilir; bรถylece editor'รผnรผz `commons` parametresine ne geรงirileceฤŸini bilir ve size code completion, type check'leri vb. konularda yardฤฑmcฤฑ olur: + + + +## Kฤฑsayol { #shortcut } + +Ama burada bir miktar kod tekrarฤฑmฤฑz olduฤŸunu gรถrรผyorsunuz; `CommonQueryParams`'ฤฑ iki kez yazฤฑyoruz: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI**, bu durumlar iรงin bir kฤฑsayol saฤŸlar: dependency'nin *รถzellikle* FastAPI'nin bir instance oluลŸturmak iรงin "รงaฤŸฤฑracaฤŸฤฑ" bir class olduฤŸu durumlar. + +Bu รถzel durumlarda ลŸunu yapabilirsiniz: + +ลžunu yazmak yerine: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +...ลŸunu yazarsฤฑnฤฑz: + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.9+ Annotated Olmadan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ kullanmayฤฑ tercih edin. + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +Dependency'yi parametrenin type'ฤฑ olarak tanฤฑmlarsฤฑnฤฑz ve `Depends(CommonQueryParams)` iรงinde class'ฤฑ *yeniden* yazmak yerine, parametre vermeden `Depends()` kullanฤฑrsฤฑnฤฑz. + +Aynฤฑ รถrnek ลŸu hale gelir: + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +...ve **FastAPI** ne yapmasฤฑ gerektiฤŸini bilir. + +/// tip | ฤฐpucu + +Bu size faydalฤฑ olmaktan รงok kafa karฤฑลŸtฤฑrฤฑcฤฑ geliyorsa, kullanmayฤฑn; buna *ihtiyacฤฑnฤฑz* yok. + +Bu sadece bir kฤฑsayoldur. ร‡รผnkรผ **FastAPI** kod tekrarฤฑnฤฑ en aza indirmenize yardฤฑmcฤฑ olmayฤฑ รถnemser. + +/// diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 0000000000..4903aec4a4 --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# Path Operation Decorator'lerinde Dependency'ler { #dependencies-in-path-operation-decorators } + +Bazฤฑ durumlarda bir dependency'nin dรถndรผrdรผฤŸรผ deฤŸere *path operation function* iรงinde gerรงekten ihtiyacฤฑnฤฑz olmaz. + +Ya da dependency zaten bir deฤŸer dรถndรผrmรผyordur. + +Ancak yine de รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ/รงรถzรผlmesini istersiniz. + +Bu gibi durumlarda, `Depends` ile bir *path operation function* parametresi tanฤฑmlamak yerine, *path operation decorator*'รผne `dependencies` adฤฑnda bir `list` ekleyebilirsiniz. + +## *Path Operation Decorator*'รผne `dependencies` Ekleyin { #add-dependencies-to-the-path-operation-decorator } + +*Path operation decorator*, opsiyonel bir `dependencies` argรผmanฤฑ alฤฑr. + +Bu, `Depends()` รถฤŸelerinden oluลŸan bir `list` olmalฤฑdฤฑr: + +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} + +Bu dependency'ler normal dependency'lerle aynฤฑ ลŸekilde รงalฤฑลŸtฤฑrฤฑlฤฑr/รงรถzรผlรผr. Ancak (eฤŸer bir deฤŸer dรถndรผrรผyorlarsa) bu deฤŸer *path operation function*'ฤฑnฤฑza aktarฤฑlmaz. + +/// tip | ฤฐpucu + +Bazฤฑ editรถrler, kullanฤฑlmayan function parametrelerini kontrol eder ve bunlarฤฑ hata olarak gรถsterebilir. + +Bu `dependencies` yaklaลŸฤฑmฤฑyla, editรถr/araรง hatalarฤฑna takฤฑlmadan dependency'lerin รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ saฤŸlayabilirsiniz. + +Ayrฤฑca kodunuzda kullanฤฑlmayan bir parametreyi gรถren yeni geliลŸtiricilerin bunun gereksiz olduฤŸunu dรผลŸรผnmesi gibi bir kafa karฤฑลŸฤฑklฤฑฤŸฤฑnฤฑ da azaltabilir. + +/// + +/// info | Bilgi + +Bu รถrnekte uydurma รถzel header'lar olan `X-Key` ve `X-Token` kullanฤฑyoruz. + +Ancak gerรงek senaryolarda, security uygularken, entegre [Security yardฤฑmcฤฑ araรงlarฤฑnฤฑ (bir sonraki bรถlรผm)](../security/index.md){.internal-link target=_blank} kullanmak size daha fazla fayda saฤŸlar. + +/// + +## Dependency Hatalarฤฑ ve Return DeฤŸerleri { #dependencies-errors-and-return-values } + +Normalde kullandฤฑฤŸฤฑnฤฑz aynฤฑ dependency *function*'larฤฑnฤฑ burada da kullanabilirsiniz. + +### Dependency Gereksinimleri { #dependency-requirements } + +Request gereksinimleri (header'lar gibi) veya baลŸka alt dependency'ler tanฤฑmlayabilirler: + +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} + +### Exception Fฤฑrlatmak { #raise-exceptions } + +Bu dependency'ler, normal dependency'lerde olduฤŸu gibi `raise` ile exception fฤฑrlatabilir: + +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} + +### Return DeฤŸerleri { #return-values } + +Ayrฤฑca deฤŸer dรถndรผrebilirler ya da dรถndรผrmeyebilirler; dรถnen deฤŸer kullanฤฑlmayacaktฤฑr. + +Yani baลŸka bir yerde zaten kullandฤฑฤŸฤฑnฤฑz, deฤŸer dรถndรผren normal bir dependency'yi tekrar kullanabilirsiniz; deฤŸer kullanฤฑlmasa bile dependency รงalฤฑลŸtฤฑrฤฑlacaktฤฑr: + +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} + +## Bir *Path Operation* Grubu ฤฐรงin Dependency'ler { #dependencies-for-a-group-of-path-operations } + +Daha sonra, muhtemelen birden fazla dosya kullanarak daha bรผyรผk uygulamalarฤฑ nasฤฑl yapฤฑlandฤฑracaฤŸฤฑnฤฑzฤฑ okurken ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), bir *path operation* grubu iรงin tek bir `dependencies` parametresini nasฤฑl tanฤฑmlayacaฤŸฤฑnฤฑzฤฑ รถฤŸreneceksiniz. + +## Global Dependency'ler { #global-dependencies } + +Sฤฑrada, dependency'leri tรผm `FastAPI` uygulamasฤฑna nasฤฑl ekleyeceฤŸimizi gรถreceฤŸiz; bรถylece her *path operation* iรงin geรงerli olacaklar. diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 0000000000..bd025f799b --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,289 @@ +# `yield` ile Dependency'ler { #dependencies-with-yield } + +FastAPI, iลŸini bitirdikten sonra ek adฤฑmlar รงalฤฑลŸtฤฑran dependency'leri destekler. + +Bunu yapmak iรงin `return` yerine `yield` kullanฤฑn ve ek adฤฑmlarฤฑ (kodu) `yield` satฤฑrฤฑndan sonra yazฤฑn. + +/// tip | ฤฐpucu + +Her dependency iรงin yalnฤฑzca **bir kez** `yield` kullandฤฑฤŸฤฑnฤฑzdan emin olun. + +/// + +/// note | Teknik Detaylar + +ลžunlarla kullanฤฑlabilen herhangi bir fonksiyon: + +* `@contextlib.contextmanager` veya +* `@contextlib.asynccontextmanager` + +bir **FastAPI** dependency'si olarak kullanฤฑlabilir. + +Hatta FastAPI bu iki decorator'ฤฑ iรงeride (internally) kullanฤฑr. + +/// + +## `yield` ile Bir Veritabanฤฑ Dependency'si { #a-database-dependency-with-yield } + +ร–rneฤŸin bunu, bir veritabanฤฑ session'ฤฑ oluลŸturmak ve iลŸ bittikten sonra kapatmak iรงin kullanabilirsiniz. + +Response oluลŸturulmadan รถnce yalnฤฑzca `yield` satฤฑrฤฑna kadar olan (ve `yield` dahil) kod รงalฤฑลŸtฤฑrฤฑlฤฑr: + +{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} + +`yield` edilen deฤŸer, *path operation*'lara ve diฤŸer dependency'lere enjekte edilen (injected) deฤŸerdir: + +{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} + +Response'dan sonra `yield` satฤฑrฤฑnฤฑ takip eden kod รงalฤฑลŸtฤฑrฤฑlฤฑr: + +{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} + +/// tip | ฤฐpucu + +`async` ya da normal fonksiyonlar kullanabilirsiniz. + +**FastAPI**, normal dependency'lerde olduฤŸu gibi her ikisinde de doฤŸru ลŸekilde davranฤฑr. + +/// + +## `yield` ve `try` ile Bir Dependency { #a-dependency-with-yield-and-try } + +`yield` kullanan bir dependency iรงinde bir `try` bloฤŸu kullanฤฑrsanฤฑz, dependency kullanฤฑlฤฑrken fฤฑrlatฤฑlan (raised) herhangi bir exception'ฤฑ alฤฑrsฤฑnฤฑz. + +ร–rneฤŸin, baลŸka bir dependency'de veya bir *path operation* iรงinde รงalฤฑลŸan bir kod, bir veritabanฤฑ transaction'ฤฑnฤฑ "rollback" yaptฤฑysa ya da baลŸka bir exception oluลŸturduysa, o exception dependency'nizde size gelir. + +Dolayฤฑsฤฑyla `except SomeException` ile dependency iรงinde o spesifik exception'ฤฑ yakalayabilirsiniz. + +Aynฤฑ ลŸekilde, exception olsun ya da olmasฤฑn รงฤฑkฤฑลŸ (exit) adฤฑmlarฤฑnฤฑn รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ garanti etmek iรงin `finally` kullanabilirsiniz. + +{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} + +## `yield` ile Alt Dependency'ler { #sub-dependencies-with-yield } + +Her boyutta ve ลŸekilde alt dependency'ler ve alt dependency "aฤŸaรงlarฤฑ" (trees) oluลŸturabilirsiniz; bunlarฤฑn herhangi biri veya hepsi `yield` kullanabilir. + +**FastAPI**, `yield` kullanan her dependency'deki "exit code"'un doฤŸru sฤฑrayla รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ saฤŸlar. + +ร–rneฤŸin, `dependency_c`, `dependency_b`'ye; `dependency_b` de `dependency_a`'ya baฤŸlฤฑ olabilir: + +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} + +Ve hepsi `yield` kullanabilir. + +Bu durumda `dependency_c`, exit code'unu รงalฤฑลŸtฤฑrabilmek iรงin `dependency_b`'den gelen deฤŸerin (burada `dep_b`) hรขlรข eriลŸilebilir olmasฤฑna ihtiyaรง duyar. + +Aynฤฑ ลŸekilde `dependency_b` de exit code'u iรงin `dependency_a`'dan gelen deฤŸerin (burada `dep_a`) eriลŸilebilir olmasฤฑna ihtiyaรง duyar. + +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} + +Benzer ลŸekilde, bazฤฑ dependency'ler `yield`, bazฤฑlarฤฑ `return` kullanabilir ve bunlarฤฑn bazฤฑlarฤฑ diฤŸerlerine baฤŸlฤฑ olabilir. + +Ayrฤฑca birden fazla `yield` kullanan dependency gerektiren tek bir dependency'niz de olabilir, vb. + +ฤฐstediฤŸiniz herhangi bir dependency kombinasyonunu kullanabilirsiniz. + +**FastAPI** her ลŸeyin doฤŸru sฤฑrada รงalฤฑลŸmasฤฑnฤฑ saฤŸlar. + +/// note | Teknik Detaylar + +Bu, Python'un Context Managers yapฤฑsฤฑ sayesinde รงalฤฑลŸฤฑr. + +**FastAPI** bunu saฤŸlamak iรงin iรงeride onlarฤฑ kullanฤฑr. + +/// + +## `yield` ve `HTTPException` ile Dependency'ler { #dependencies-with-yield-and-httpexception } + +`yield` kullanan dependency'lerde `try` bloklarฤฑyla bazฤฑ kodlarฤฑ รงalฤฑลŸtฤฑrฤฑp ardฤฑndan `finally` sonrasฤฑnda exit code รงalฤฑลŸtฤฑrabileceฤŸinizi gรถrdรผnรผz. + +Ayrฤฑca `except` ile fฤฑrlatฤฑlan exception'ฤฑ yakalayฤฑp onunla bir ลŸey yapabilirsiniz. + +ร–rneฤŸin `HTTPException` gibi farklฤฑ bir exception fฤฑrlatabilirsiniz. + +/// tip | ฤฐpucu + +Bu biraz ileri seviye bir tekniktir ve รงoฤŸu durumda gerรงekten ihtiyaรง duymazsฤฑnฤฑz; รงรผnkรผ exception'larฤฑ (`HTTPException` dahil) uygulamanฤฑzฤฑn geri kalan kodundan, รถrneฤŸin *path operation function* iรงinden fฤฑrlatabilirsiniz. + +Ama ihtiyaรง duyarsanฤฑz diye burada. ๐Ÿค“ + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} + +Exception yakalayฤฑp buna gรถre รถzel bir response oluลŸturmak istiyorsanฤฑz bir [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} oluลŸturun. + +## `yield` ve `except` ile Dependency'ler { #dependencies-with-yield-and-except } + +`yield` kullanan bir dependency iรงinde `except` ile bir exception yakalar ve bunu tekrar fฤฑrlatmazsanฤฑz (ya da yeni bir exception fฤฑrlatmazsanฤฑz), FastAPI normal Python'da olduฤŸu gibi bir exception olduฤŸunu fark edemez: + +{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} + +Bu durumda client, biz `HTTPException` veya benzeri bir ลŸey fฤฑrlatmadฤฑฤŸฤฑmฤฑz iรงin olmasฤฑ gerektiฤŸi gibi *HTTP 500 Internal Server Error* response'u gรถrรผr; ancak server **hiรง log รผretmez** ve hatanฤฑn ne olduฤŸuna dair baลŸka bir iลŸaret de olmaz. ๐Ÿ˜ฑ + +### `yield` ve `except` Kullanan Dependency'lerde Her Zaman `raise` Edin { #always-raise-in-dependencies-with-yield-and-except } + +`yield` kullanan bir dependency iรงinde bir exception yakalarsanฤฑz, baลŸka bir `HTTPException` veya benzeri bir ลŸey fฤฑrlatmฤฑyorsanฤฑz, **orijinal exception'ฤฑ tekrar raise etmelisiniz**. + +Aynฤฑ exception'ฤฑ `raise` ile tekrar fฤฑrlatabilirsiniz: + +{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} + +Artฤฑk client yine aynฤฑ *HTTP 500 Internal Server Error* response'unu alฤฑr, ama server log'larda bizim รถzel `InternalError`'ฤฑmฤฑzฤฑ gรถrรผr. ๐Ÿ˜Ž + +## `yield` Kullanan Dependency'lerin ร‡alฤฑลŸtฤฑrฤฑlmasฤฑ { #execution-of-dependencies-with-yield } + +ร‡alฤฑลŸtฤฑrma sฤฑrasฤฑ kabaca aลŸaฤŸฤฑdaki diyagramdaki gibidir. Zaman yukarฤฑdan aลŸaฤŸฤฑ akar. Her sรผtun, etkileลŸime giren veya kod รงalฤฑลŸtฤฑran parรงalardan birini temsil eder. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// info | Bilgi + +Client'a yalnฤฑzca **tek bir response** gรถnderilir. Bu, error response'lardan biri olabilir ya da *path operation*'dan dรถnen response olabilir. + +Bu response'lardan biri gรถnderildikten sonra baลŸka bir response gรถnderilemez. + +/// + +/// tip | ฤฐpucu + +*Path operation function* iรงindeki koddan herhangi bir exception raise ederseniz, `HTTPException` dahil olmak รผzere bu exception `yield` kullanan dependency'lere aktarฤฑlฤฑr. ร‡oฤŸu durumda, doฤŸru ลŸekilde ele alฤฑndฤฑฤŸฤฑndan emin olmak iรงin `yield` kullanan dependency'den aynฤฑ exception'ฤฑ (veya yeni bir tanesini) yeniden raise etmek istersiniz. + +/// + +## Erken ร‡ฤฑkฤฑลŸ ve `scope` { #early-exit-and-scope } + +Normalde `yield` kullanan dependency'lerin exit code'u, client'a response gรถnderildikten **sonra** รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Ama *path operation function*'dan dรถndรผkten sonra dependency'yi kullanmayacaฤŸฤฑnฤฑzฤฑ biliyorsanฤฑz, `Depends(scope="function")` kullanarak FastAPI'ye dependency'yi *path operation function* dรถndรผkten sonra kapatmasฤฑnฤฑ, ancak **response gรถnderilmeden รถnce** kapatmasฤฑnฤฑ sรถyleyebilirsiniz. + +{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} + +`Depends()` ลŸu deฤŸerleri alabilen bir `scope` parametresi alฤฑr: + +* `"function"`: dependency'yi request'i iลŸleyen *path operation function* รงalฤฑลŸmadan รถnce baลŸlat, *path operation function* bittikten sonra bitir, ancak response client'a geri gรถnderilmeden **รถnce** sonlandฤฑr. Yani dependency fonksiyonu, *path operation **function***'ฤฑn **etrafฤฑnda** รงalฤฑลŸtฤฑrฤฑlฤฑr. +* `"request"`: dependency'yi request'i iลŸleyen *path operation function* รงalฤฑลŸmadan รถnce baลŸlat (`"function"` kullanฤฑmฤฑna benzer), ancak response client'a geri gรถnderildikten **sonra** sonlandฤฑr. Yani dependency fonksiyonu, **request** ve response dรถngรผsรผnรผn **etrafฤฑnda** รงalฤฑลŸtฤฑrฤฑlฤฑr. + +Belirtilmezse ve dependency `yield` kullanฤฑyorsa, varsayฤฑlan olarak `scope` `"request"` olur. + +### Alt dependency'ler iรงin `scope` { #scope-for-sub-dependencies } + +`scope="request"` (varsayฤฑlan) ile bir dependency tanฤฑmladฤฑฤŸฤฑnฤฑzda, herhangi bir alt dependency'nin `scope` deฤŸeri de `"request"` olmalฤฑdฤฑr. + +Ancak `scope` deฤŸeri `"function"` olan bir dependency, hem `"function"` hem de `"request"` scope'una sahip dependency'lere baฤŸlฤฑ olabilir. + +Bunun nedeni, bir dependency'nin exit code'unu alt dependency'lerden รถnce รงalฤฑลŸtฤฑrabilmesi gerekmesidir; รงรผnkรผ exit code sฤฑrasฤฑnda hรขlรข onlarฤฑ kullanmasฤฑ gerekebilir. + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` + +## `yield`, `HTTPException`, `except` ve Background Tasks ile Dependency'ler { #dependencies-with-yield-httpexception-except-and-background-tasks } + +`yield` kullanan dependency'ler, zaman iรงinde farklฤฑ kullanฤฑm senaryolarฤฑnฤฑ kapsamak ve bazฤฑ sorunlarฤฑ dรผzeltmek iรงin geliลŸti. + +FastAPI'nin farklฤฑ sรผrรผmlerinde nelerin deฤŸiลŸtiฤŸini gรถrmek isterseniz, advanced guide'da ลŸu bรถlรผmรผ okuyabilirsiniz: [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}. + +## Context Managers { #context-managers } + +### "Context Managers" Nedir? { #what-are-context-managers } + +"Context Managers", `with` ifadesiyle kullanabildiฤŸiniz Python nesneleridir. + +ร–rneฤŸin, bir dosyayฤฑ okumak iรงin `with` kullanabilirsiniz: + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +Temelde `open("./somefile.txt")`, "Context Manager" olarak adlandฤฑrฤฑlan bir nesne oluลŸturur. + +`with` bloฤŸu bittiฤŸinde, exception olsa bile dosyanฤฑn kapatฤฑlmasฤฑnฤฑ garanti eder. + +`yield` ile bir dependency oluลŸturduฤŸunuzda, **FastAPI** iรงeride bunun iรงin bir context manager oluลŸturur ve bazฤฑ ilgili baลŸka araรงlarla birleลŸtirir. + +### `yield` kullanan dependency'lerde context manager kullanma { #using-context-managers-in-dependencies-with-yield } + +/// warning | Uyarฤฑ + +Bu, az รงok "ileri seviye" bir fikirdir. + +**FastAPI**'ye yeni baลŸlฤฑyorsanฤฑz ลŸimdilik bunu atlamak isteyebilirsiniz. + +/// + +Python'da Context Manager'larฤฑ, iki method'a sahip bir class oluลŸturarak: `__enter__()` ve `__exit__()` yaratabilirsiniz. + +Ayrฤฑca dependency fonksiyonunun iรงinde `with` veya `async with` ifadeleri kullanarak **FastAPI**'de `yield` kullanan dependency'lerin iรงinde de kullanabilirsiniz: + +{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *} + +/// tip | ฤฐpucu + +Bir context manager oluลŸturmanฤฑn baลŸka bir yolu da ลŸunlardฤฑr: + +* `@contextlib.contextmanager` veya +* `@contextlib.asynccontextmanager` + +Bunlarฤฑ, tek bir `yield` iรงeren bir fonksiyonu decorate etmek iรงin kullanabilirsiniz. + +FastAPI, `yield` kullanan dependency'ler iรงin iรงeride bunu yapar. + +Ancak FastAPI dependency'leri iรงin bu decorator'larฤฑ kullanmak zorunda deฤŸilsiniz (hatta kullanmamalฤฑsฤฑnฤฑz). + +FastAPI bunu sizin yerinize iรงeride yapar. + +/// diff --git a/docs/tr/docs/tutorial/dependencies/global-dependencies.md b/docs/tr/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 0000000000..7f0025eaf2 --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,16 @@ +# Global Dependencies { #global-dependencies } + +Bazฤฑ uygulama tรผrlerinde, tรผm uygulama iรงin dependency eklemek isteyebilirsiniz. + +[`dependencies`'i *path operation decorator*'larฤฑna ekleyebildiฤŸiniz](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} gibi, `FastAPI` uygulamasฤฑna da ekleyebilirsiniz. + +Bu durumda, uygulamadaki tรผm *path operation*'lara uygulanฤฑrlar: + +{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *} + + +Ve [*path operation decorator*'larฤฑna `dependencies` ekleme](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} bรถlรผmรผndeki tรผm fikirler hรขlรข geรงerlidir; ancak bu sefer, uygulamadaki tรผm *path operation*'lar iรงin geรงerli olur. + +## *Path operations* gruplarฤฑ iรงin Dependencies { #dependencies-for-groups-of-path-operations } + +ฤฐleride, daha bรผyรผk uygulamalarฤฑ nasฤฑl yapฤฑlandฤฑracaฤŸฤฑnฤฑzฤฑ ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}) okurken, muhtemelen birden fazla dosyayla birlikte, bir *path operations* grubu iรงin tek bir `dependencies` parametresini nasฤฑl tanฤฑmlayacaฤŸฤฑnฤฑzฤฑ รถฤŸreneceksiniz. diff --git a/docs/tr/docs/tutorial/dependencies/index.md b/docs/tr/docs/tutorial/dependencies/index.md new file mode 100644 index 0000000000..f1e446d67d --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/index.md @@ -0,0 +1,250 @@ +# BaฤŸฤฑmlฤฑlฤฑklar { #dependencies } + +**FastAPI**, รงok gรผรงlรผ ama aynฤฑ zamanda sezgisel bir **Dependency Injection** sistemine sahiptir. + +Kullanฤฑmฤฑ รงok basit olacak ลŸekilde tasarlanmฤฑลŸtฤฑr ve herhangi bir geliลŸtiricinin diฤŸer bileลŸenleri **FastAPI** ile entegre etmesini kolaylaลŸtฤฑrฤฑr. + +## "Dependency Injection" Nedir? { #what-is-dependency-injection } + +Programlamada **"Dependency Injection"**, kodunuzun (bu รถrnekte *path operation function*'larฤฑnฤฑzฤฑn) รงalฤฑลŸmak ve kullanmak iรงin ihtiyaรง duyduฤŸu ลŸeyleri: "dependencies" (baฤŸฤฑmlฤฑlฤฑklar) olarak beyan edebilmesi anlamฤฑna gelir. + +Ardฤฑndan bu sistem (bu รถrnekte **FastAPI**), kodunuza gerekli baฤŸฤฑmlฤฑlฤฑklarฤฑ saฤŸlamak ("inject" etmek) iรงin gereken her ลŸeyi sizin yerinize halleder. + +Bu yaklaลŸฤฑm, ลŸunlara ihtiyaรง duyduฤŸunuzda รถzellikle faydalฤฑdฤฑr: + +* PaylaลŸฤฑlan bir mantฤฑฤŸa sahip olmak (aynฤฑ kod mantฤฑฤŸฤฑnฤฑ tekrar tekrar kullanmak). +* Veritabanฤฑ baฤŸlantฤฑlarฤฑnฤฑ paylaลŸmak. +* Gรผvenlik, authentication, rol gereksinimleri vb. kurallarฤฑ zorunlu kฤฑlmak. +* Ve daha birรงok ลŸey... + +Tรผm bunlarฤฑ, kod tekrarฤฑnฤฑ minimumda tutarak yaparsฤฑnฤฑz. + +## ฤฐlk Adฤฑmlar { #first-steps } + +ร‡ok basit bir รถrneฤŸe bakalฤฑm. ลžimdilik o kadar basit olacak ki pek iลŸe yaramayacak. + +Ama bu sayede **Dependency Injection** sisteminin nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna odaklanabiliriz. + +### Bir dependency (baฤŸฤฑmlฤฑlฤฑk) veya "dependable" OluลŸturun { #create-a-dependency-or-dependable } + +ร–nce dependency'e odaklanalฤฑm. + +Bu, bir *path operation function*'ฤฑn alabileceฤŸi parametrelerin aynฤฑsฤฑnฤฑ alabilen basit bir fonksiyondur: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +Bu kadar. + +**2 satฤฑr**. + +Ve tรผm *path operation function*'larฤฑnฤฑzla aynฤฑ ลŸekle ve yapฤฑya sahiptir. + +Bunu, "decorator" olmadan (yani `@app.get("/some-path")` olmadan) yazฤฑlmฤฑลŸ bir *path operation function* gibi dรผลŸรผnebilirsiniz. + +Ayrฤฑca istediฤŸiniz herhangi bir ลŸeyi dรถndรผrebilir. + +Bu รถrnekte, bu dependency ลŸunlarฤฑ bekler: + +* `str` olan, opsiyonel bir query parametresi `q`. +* `int` olan, opsiyonel bir query parametresi `skip` ve varsayฤฑlanฤฑ `0`. +* `int` olan, opsiyonel bir query parametresi `limit` ve varsayฤฑlanฤฑ `100`. + +Sonra da bu deฤŸerleri iรงeren bir `dict` dรถndรผrรผr. + +/// info | Bilgi + +FastAPI, `Annotated` desteฤŸini 0.95.0 sรผrรผmรผnde ekledi (ve รถnermeye baลŸladฤฑ). + +Daha eski bir sรผrรผm kullanฤฑyorsanฤฑz `Annotated` kullanmaya รงalฤฑลŸtฤฑฤŸฤฑnฤฑzda hata alฤฑrsฤฑnฤฑz. + +`Annotated` kullanmadan รถnce **FastAPI** sรผrรผmรผnรผ en az 0.95.1'e yรผkseltmek iรงin [FastAPI sรผrรผmรผnรผ yรผkseltin](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}. + +/// + +### `Depends`'i Import Edin { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### "Dependant" ฤฐรงinde Dependency'yi Tanฤฑmlayฤฑn { #declare-the-dependency-in-the-dependant } + +*Path operation function* parametrelerinizde `Body`, `Query` vb. kullandฤฑฤŸฤฑnฤฑz gibi, yeni bir parametreyle `Depends` kullanฤฑn: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +Fonksiyon parametrelerinde `Depends`'i `Body`, `Query` vb. ile aynฤฑ ลŸekilde kullansanฤฑz da `Depends` biraz farklฤฑ รงalฤฑลŸฤฑr. + +`Depends`'e yalnฤฑzca tek bir parametre verirsiniz. + +Bu parametre, bir fonksiyon gibi bir ลŸey olmalฤฑdฤฑr. + +Onu doฤŸrudan **รงaฤŸฤฑrmazsฤฑnฤฑz** (sonuna parantez eklemezsiniz), sadece `Depends()`'e parametre olarak verirsiniz. + +Ve bu fonksiyon da, *path operation function*'lar gibi parametre alฤฑr. + +/// tip | ฤฐpucu + +Fonksiyonlarฤฑn dฤฑลŸฤฑnda baลŸka hangi "ลŸeylerin" dependency olarak kullanฤฑlabildiฤŸini bir sonraki bรถlรผmde gรถreceksiniz. + +/// + +Yeni bir request geldiฤŸinde, **FastAPI** ลŸunlarฤฑ sizin yerinize yapar: + +* Dependency ("dependable") fonksiyonunuzu doฤŸru parametrelerle รงaฤŸฤฑrฤฑr. +* Fonksiyonunuzun sonucunu alฤฑr. +* Bu sonucu *path operation function*'ฤฑnฤฑzdaki parametreye atar. + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +Bu ลŸekilde paylaลŸฤฑlan kodu bir kez yazarsฤฑnฤฑz ve onu *path operation*'larda รงaฤŸฤฑrma iลŸini **FastAPI** halleder. + +/// check | Ek bilgi + +Dikkat edin: Bunu "register" etmek ya da benzeri bir ลŸey yapmak iรงin รถzel bir class oluลŸturup **FastAPI**'ye bir yere geรงirmeniz gerekmez. + +Sadece `Depends`'e verirsiniz ve gerisini **FastAPI** nasฤฑl yapacaฤŸฤฑnฤฑ bilir. + +/// + +## `Annotated` Dependency'lerini PaylaลŸฤฑn { #share-annotated-dependencies } + +Yukarฤฑdaki รถrneklerde, ufak bir **kod tekrarฤฑ** olduฤŸunu gรถrรผyorsunuz. + +`common_parameters()` dependency'sini kullanmanฤฑz gerektiฤŸinde, type annotation ve `Depends()` iรงeren parametrenin tamamฤฑnฤฑ yazmanฤฑz gerekir: + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +Ancak `Annotated` kullandฤฑฤŸฤฑmฤฑz iรงin bu `Annotated` deฤŸerini bir deฤŸiลŸkende saklayฤฑp birden fazla yerde kullanabiliriz: + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | ฤฐpucu + +Bu aslฤฑnda standart Python'dฤฑr; buna "type alias" denir ve **FastAPI**'ye รถzel bir ลŸey deฤŸildir. + +Ama **FastAPI**, `Annotated` dahil Python standartlarฤฑ รผzerine kurulu olduฤŸu iรงin bu tekniฤŸi kodunuzda kullanabilirsiniz. ๐Ÿ˜Ž + +/// + +Dependency'ler beklediฤŸiniz gibi รงalฤฑลŸmaya devam eder ve **en gรผzel kฤฑsmฤฑ** da ลŸudur: **type bilgisi korunur**. Bu da editรถrรผnรผzรผn size **autocompletion**, **inline errors** vb. saฤŸlamaya devam edeceฤŸi anlamฤฑna gelir. `mypy` gibi diฤŸer araรงlar iรงin de aynฤฑsฤฑ geรงerlidir. + +Bu รถzellikle, **bรผyรผk bir kod tabanฤฑnda**, aynฤฑ dependency'leri **birรงok *path operation*** iรงinde tekrar tekrar kullandฤฑฤŸฤฑnฤฑzda รงok faydalฤฑ olacaktฤฑr. + +## `async` Olsa da Olmasa da { #to-async-or-not-to-async } + +Dependency'ler de **FastAPI** tarafฤฑndan รงaฤŸrฤฑlacaฤŸฤฑ iรงin (tฤฑpkฤฑ *path operation function*'larฤฑnฤฑz gibi), fonksiyonlarฤฑ tanฤฑmlarken aynฤฑ kurallar geรงerlidir. + +`async def` ya da normal `def` kullanabilirsiniz. + +Ayrฤฑca normal `def` *path operation function*'larฤฑ iรงinde `async def` dependency tanฤฑmlayabilir veya `async def` *path operation function*'larฤฑ iรงinde `def` dependency kullanabilirsiniz vb. + +Fark etmez. **FastAPI** ne yapacaฤŸฤฑnฤฑ bilir. + +/// note | Not + +EฤŸer bilmiyorsanฤฑz, dokรผmanlarda `async` ve `await` iรงin [Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank} bรถlรผmรผne bakฤฑn. + +/// + +## OpenAPI ile Entegre { #integrated-with-openapi } + +Dependency'lerinizin (ve alt dependency'lerin) tรผm request tanฤฑmlarฤฑ, doฤŸrulamalarฤฑ ve gereksinimleri aynฤฑ OpenAPI ลŸemasฤฑna entegre edilir. + +Bu nedenle interaktif dokรผmanlar, bu dependency'lerden gelen tรผm bilgileri de iรงerir: + + + +## Basit Kullanฤฑm { #simple-usage } + +ลžรถyle dรผลŸรผnรผrseniz: *Path operation function*'lar, bir *path* ve *operation* eลŸleลŸtiฤŸinde kullanฤฑlacak ลŸekilde tanฤฑmlanฤฑr; ardฤฑndan **FastAPI** fonksiyonu doฤŸru parametrelerle รงaฤŸฤฑrฤฑr ve request'ten veriyi รงฤฑkarฤฑr. + +Aslฤฑnda tรผm (veya รงoฤŸu) web framework'รผ de aynฤฑ ลŸekilde รงalฤฑลŸฤฑr. + +Bu fonksiyonlarฤฑ hiรงbir zaman doฤŸrudan รงaฤŸฤฑrmazsฤฑnฤฑz. Onlarฤฑ framework'รผnรผz (bu รถrnekte **FastAPI**) รงaฤŸฤฑrฤฑr. + +Dependency Injection sistemiyle, *path operation function*'ฤฑnฤฑzฤฑn, ondan รถnce รงalฤฑลŸtฤฑrฤฑlmasฤฑ gereken baลŸka bir ลŸeye de "baฤŸlฤฑ" olduฤŸunu **FastAPI**'ye sรถyleyebilirsiniz; **FastAPI** bunu รงalฤฑลŸtฤฑrฤฑr ve sonuรงlarฤฑ "inject" eder. + +Aynฤฑ "dependency injection" fikri iรงin kullanฤฑlan diฤŸer yaygฤฑn terimler: + +* resources +* providers +* services +* injectables +* components + +## **FastAPI** Plug-in'leri { #fastapi-plug-ins } + +Entegrasyonlar ve "plug-in"ler **Dependency Injection** sistemi kullanฤฑlarak inลŸa edilebilir. Ancak aslฤฑnda **"plug-in" oluลŸturmanฤฑza gerek yoktur**; รงรผnkรผ dependency'leri kullanarak *path operation function*'larฤฑnฤฑza sunulabilecek sฤฑnฤฑrsฤฑz sayฤฑda entegrasyon ve etkileลŸim tanฤฑmlayabilirsiniz. + +Dependency'ler, รงok basit ve sezgisel bir ลŸekilde oluลŸturulabilir. Bรถylece ihtiyacฤฑnฤฑz olan Python package'larฤฑnฤฑ import edip, API fonksiyonlarฤฑnฤฑzla birkaรง satฤฑr kodla *kelimenin tam anlamฤฑyla* entegre edebilirsiniz. + +ฤฐlerleyen bรถlรผmlerde iliลŸkisel ve NoSQL veritabanlarฤฑ, gรผvenlik vb. konularda bunun รถrneklerini gรถreceksiniz. + +## **FastAPI** UyumluluฤŸu { #fastapi-compatibility } + +Dependency injection sisteminin sadeliฤŸi, **FastAPI**'yi ลŸunlarla uyumlu hale getirir: + +* tรผm iliลŸkisel veritabanlarฤฑ +* NoSQL veritabanlarฤฑ +* harici paketler +* harici API'ler +* authentication ve authorization sistemleri +* API kullanฤฑm izleme (monitoring) sistemleri +* response verisi injection sistemleri +* vb. + +## Basit ve Gรผรงlรผ { #simple-and-powerful } + +HiyerarลŸik dependency injection sistemi tanฤฑmlamak ve kullanmak รงok basit olsa da, hรขlรข oldukรงa gรผรงlรผdรผr. + +Kendileri de dependency tanฤฑmlayabilen dependency'ler tanฤฑmlayabilirsiniz. + +Sonuรงta hiyerarลŸik bir dependency aฤŸacฤฑ oluลŸur ve **Dependency Injection** sistemi tรผm bu dependency'leri (ve alt dependency'lerini) sizin iรงin รงรถzer ve her adฤฑmda sonuรงlarฤฑ saฤŸlar ("inject" eder). + +ร–rneฤŸin, 4 API endpoint'iniz (*path operation*) olduฤŸunu varsayalฤฑm: + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +O zaman her biri iรงin farklฤฑ izin gereksinimlerini yalnฤฑzca dependency'ler ve alt dependency'lerle ekleyebilirsiniz: + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## **OpenAPI** ile Entegre { #integrated-with-openapi_1 } + +Bu dependency'lerin tรผmรผ, gereksinimlerini beyan ederken aynฤฑ zamanda *path operation*'larฤฑnฤฑza parametreler, doฤŸrulamalar vb. da ekler. + +**FastAPI**, bunlarฤฑn hepsini OpenAPI ลŸemasฤฑna eklemekle ilgilenir; bรถylece interaktif dokรผmantasyon sistemlerinde gรถsterilir. diff --git a/docs/tr/docs/tutorial/dependencies/sub-dependencies.md b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000..184db839bc --- /dev/null +++ b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# Alt BaฤŸฤฑmlฤฑlฤฑklar { #sub-dependencies } + +**Alt baฤŸฤฑmlฤฑlฤฑklarฤฑ** olan baฤŸฤฑmlฤฑlฤฑklar oluลŸturabilirsiniz. + +ฤฐhtiyacฤฑnฤฑz olduฤŸu kadar **derine** gidebilirler. + +Bunlarฤฑ รงรถzme iลŸini **FastAPI** รผstlenir. + +## ฤฐlk baฤŸฤฑmlฤฑlฤฑk "dependable" { #first-dependency-dependable } + +ลžรถyle bir ilk baฤŸฤฑmlฤฑlฤฑk ("dependable") oluลŸturabilirsiniz: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +Burada `q` adฤฑnda opsiyonel bir query parametresi `str` olarak tanฤฑmlanฤฑr ve sonra doฤŸrudan geri dรถndรผrรผlรผr. + +Bu oldukรงa basit (pek faydalฤฑ deฤŸil), ama alt baฤŸฤฑmlฤฑlฤฑklarฤฑn nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna odaklanmamฤฑza yardฤฑmcฤฑ olacak. + +## ฤฐkinci baฤŸฤฑmlฤฑlฤฑk: "dependable" ve "dependant" { #second-dependency-dependable-and-dependant } + +Ardฤฑndan, aynฤฑ zamanda kendi iรงinde bir baฤŸฤฑmlฤฑlฤฑk da tanฤฑmlayan baลŸka bir baฤŸฤฑmlฤฑlฤฑk fonksiyonu (bir "dependable") oluลŸturabilirsiniz (yani o da bir "dependant" olur): + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +Tanฤฑmlanan parametrelere odaklanalฤฑm: + +* Bu fonksiyonun kendisi bir baฤŸฤฑmlฤฑlฤฑk ("dependable") olmasฤฑna raฤŸmen, ayrฤฑca baลŸka bir baฤŸฤฑmlฤฑlฤฑk daha tanฤฑmlar (baลŸka bir ลŸeye "depends" olur). + * `query_extractor`'a baฤŸlฤฑdฤฑr ve ondan dรถnen deฤŸeri `q` parametresine atar. +* Ayrฤฑca `last_query` adฤฑnda opsiyonel bir cookie'yi `str` olarak tanฤฑmlar. + * Kullanฤฑcฤฑ herhangi bir query `q` saฤŸlamadฤฑysa, daha รถnce cookie'ye kaydettiฤŸimiz en son kullanฤฑlan query'yi kullanฤฑrฤฑz. + +## BaฤŸฤฑmlฤฑlฤฑฤŸฤฑ Kullanma { #use-the-dependency } + +Sonra bu baฤŸฤฑmlฤฑlฤฑฤŸฤฑ ลŸรถyle kullanabiliriz: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// info | Bilgi + +Dikkat edin, *path operation function* iรงinde yalnฤฑzca tek bir baฤŸฤฑmlฤฑlฤฑk tanฤฑmlฤฑyoruz: `query_or_cookie_extractor`. + +Ancak **FastAPI**, `query_or_cookie_extractor`'ฤฑ รงaฤŸฤฑrmadan รถnce `query_extractor`'ฤฑ รถnce รงรถzmesi gerektiฤŸini bilir ve onun sonucunu `query_or_cookie_extractor`'a aktarฤฑr. + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## Aynฤฑ BaฤŸฤฑmlฤฑlฤฑฤŸฤฑ Birden Fazla Kez Kullanma { #using-the-same-dependency-multiple-times } + +BaฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑzdan biri aynฤฑ *path operation* iรงin birden fazla kez tanฤฑmlanฤฑrsa (รถrneฤŸin birden fazla baฤŸฤฑmlฤฑlฤฑฤŸฤฑn ortak bir alt baฤŸฤฑmlฤฑlฤฑฤŸฤฑ varsa), **FastAPI** o alt baฤŸฤฑmlฤฑlฤฑฤŸฤฑ request baลŸฤฑna yalnฤฑzca bir kez รงaฤŸฤฑracaฤŸฤฑnฤฑ bilir. + +Dรถnen deฤŸeri bir "cache" iรงinde saklar ve aynฤฑ request iรงinde buna ihtiyaรง duyan tรผm "dependant"lara aktarฤฑr; bรถylece aynฤฑ request iรงin baฤŸฤฑmlฤฑlฤฑฤŸฤฑ tekrar tekrar รงaฤŸฤฑrmaz. + +Daha ileri bir senaryoda, "cached" deฤŸeri kullanmak yerine aynฤฑ request iรงinde her adฤฑmda (muhtemelen birden fazla kez) baฤŸฤฑmlฤฑlฤฑฤŸฤฑn รงaฤŸrฤฑlmasฤฑ gerektiฤŸini biliyorsanฤฑz, `Depends` kullanฤฑrken `use_cache=False` parametresini ayarlayabilirsiniz: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.9+ Annotated olmayan + +/// tip | ฤฐpucu + +Mรผmkรผnse `Annotated` sรผrรผmรผnรผ tercih edin. + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## ร–zet { #recap } + +Burada kullanฤฑlan havalฤฑ terimlerin รถtesinde, **Dependency Injection** sistemi aslฤฑnda oldukรงa basittir. + +*Path operation function*'lara benzeyen fonksiyonlardan ibarettir. + +Yine de รงok gรผรงlรผdรผr ve keyfi derecede derin iรง iรงe geรงmiลŸ baฤŸฤฑmlฤฑlฤฑk "graph"larฤฑ (aฤŸaรงlarฤฑ) tanฤฑmlamanฤฑza izin verir. + +/// tip | ฤฐpucu + +Bu basit รถrneklerle รงok faydalฤฑ gรถrรผnmeyebilir. + +Ancak **security** ile ilgili bรถlรผmlerde bunun ne kadar iลŸe yaradฤฑฤŸฤฑnฤฑ gรถreceksiniz. + +Ayrฤฑca size ne kadar kod kazandฤฑrdฤฑฤŸฤฑnฤฑ da gรถreceksiniz. + +/// diff --git a/docs/tr/docs/tutorial/encoder.md b/docs/tr/docs/tutorial/encoder.md new file mode 100644 index 0000000000..e4790a032e --- /dev/null +++ b/docs/tr/docs/tutorial/encoder.md @@ -0,0 +1,35 @@ +# JSON Uyumlu Encoder { #json-compatible-encoder } + +Bazฤฑ durumlarda, bir veri tipini (รถrneฤŸin bir Pydantic model) JSON ile uyumlu bir ลŸeye (รถrneฤŸin `dict`, `list` vb.) dรถnรผลŸtรผrmeniz gerekebilir. + +ร–rneฤŸin, bunu bir veritabanฤฑnda saklamanฤฑz gerekiyorsa. + +Bunun iรงin **FastAPI**, `jsonable_encoder()` fonksiyonunu saฤŸlar. + +## `jsonable_encoder` Kullanฤฑmฤฑ { #using-the-jsonable-encoder } + +Yalnฤฑzca JSON ile uyumlu veri kabul eden bir veritabanฤฑnฤฑz olduฤŸunu dรผลŸรผnelim: `fake_db`. + +ร–rneฤŸin bu veritabanฤฑ, JSON ile uyumlu olmadฤฑklarฤฑ iรงin `datetime` objelerini kabul etmez. + +Dolayฤฑsฤฑyla bir `datetime` objesinin, ISO formatฤฑnda veriyi iรงeren bir `str`'e dรถnรผลŸtรผrรผlmesi gerekir. + +Aynฤฑ ลŸekilde bu veritabanฤฑ bir Pydantic model'i (attribute'lara sahip bir obje) de kabul etmez; yalnฤฑzca bir `dict` kabul eder. + +Bunun iรงin `jsonable_encoder` kullanabilirsiniz. + +Bir Pydantic model gibi bir obje alฤฑr ve JSON ile uyumlu bir versiyonunu dรถndรผrรผr: + +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} + +Bu รถrnekte, Pydantic model'i bir `dict`'e, `datetime`'ฤฑ da bir `str`'e dรถnรผลŸtรผrรผr. + +Bu fonksiyonun รงaฤŸrฤฑlmasฤฑyla elde edilen sonuรง, Python standardฤฑndaki `json.dumps()` ile encode edilebilecek bir ลŸeydir. + +JSON formatฤฑnda (string olarak) veriyi iรงeren bรผyรผk bir `str` dรถndรผrmez. Bunun yerine, tรผm deฤŸerleri ve alt deฤŸerleri JSON ile uyumlu olacak ลŸekilde, Pythonโ€™un standart bir veri yapฤฑsฤฑnฤฑ (รถrneฤŸin bir `dict`) dรถndรผrรผr. + +/// note | Not + +`jsonable_encoder`, aslฤฑnda **FastAPI** tarafฤฑndan veriyi dรถnรผลŸtรผrmek iรงin internal olarak kullanฤฑlฤฑr. Ancak birรงok farklฤฑ senaryoda da oldukรงa faydalฤฑdฤฑr. + +/// diff --git a/docs/tr/docs/tutorial/extra-data-types.md b/docs/tr/docs/tutorial/extra-data-types.md new file mode 100644 index 0000000000..464d3a82a9 --- /dev/null +++ b/docs/tr/docs/tutorial/extra-data-types.md @@ -0,0 +1,62 @@ +# Ek Veri Tipleri { #extra-data-types } + +ลžimdiye kadar ลŸunlar gibi yaygฤฑn veri tiplerini kullanฤฑyordunuz: + +* `int` +* `float` +* `str` +* `bool` + +Ancak daha karmaลŸฤฑk veri tiplerini de kullanabilirsiniz. + +Ve yine, ลŸimdiye kadar gรถrdรผฤŸรผnรผz รถzelliklerin aynฤฑsฤฑna sahip olursunuz: + +* Harika editรถr desteฤŸi. +* Gelen request'lerden veri dรถnรผลŸtรผrme. +* response verileri iรงin veri dรถnรผลŸtรผrme. +* Veri doฤŸrulama. +* Otomatik annotation ve dokรผmantasyon. + +## DiฤŸer veri tipleri { #other-data-types } + +KullanabileceฤŸiniz ek veri tiplerinden bazฤฑlarฤฑ ลŸunlardฤฑr: + +* `UUID`: + * Birรงok veritabanฤฑ ve sistemde ID olarak yaygฤฑn kullanฤฑlan, standart bir "Universally Unique Identifier". + * request ve response'larda `str` olarak temsil edilir. +* `datetime.datetime`: + * Python `datetime.datetime`. + * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15T15:53:00+05:00`. +* `datetime.date`: + * Python `datetime.date`. + * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15`. +* `datetime.time`: + * Python `datetime.time`. + * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `14:23:55.003`. +* `datetime.timedelta`: + * Python `datetime.timedelta`. + * request ve response'larda toplam saniye sayฤฑsฤฑnฤฑ ifade eden bir `float` olarak temsil edilir. + * Pydantic, bunu ayrฤฑca bir "ISO 8601 time diff encoding" olarak temsil etmeye de izin verir, daha fazla bilgi iรงin dokรผmanlara bakฤฑn. +* `frozenset`: + * request ve response'larda, `set` ile aynฤฑ ลŸekilde ele alฤฑnฤฑr: + * request'lerde bir list okunur, tekrarlar kaldฤฑrฤฑlฤฑr ve `set`'e dรถnรผลŸtรผrรผlรผr. + * response'larda `set`, `list`'e dรถnรผลŸtรผrรผlรผr. + * รœretilen schema, `set` deฤŸerlerinin benzersiz olduฤŸunu belirtir (JSON Schema'nฤฑn `uniqueItems` รถzelliฤŸini kullanarak). +* `bytes`: + * Standart Python `bytes`. + * request ve response'larda `str` gibi ele alฤฑnฤฑr. + * รœretilen schema, bunun `binary` "format"ฤฑna sahip bir `str` olduฤŸunu belirtir. +* `Decimal`: + * Standart Python `Decimal`. + * request ve response'larda `float` ile aynฤฑ ลŸekilde iลŸlenir. +* Geรงerli tรผm Pydantic veri tiplerini burada gรถrebilirsiniz: Pydantic data types. + +## ร–rnek { #example } + +Yukarฤฑdaki tiplerden bazฤฑlarฤฑnฤฑ kullanan parametrelere sahip bir รถrnek *path operation* ลŸรถyle: + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} + +Fonksiyonun iรงindeki parametrelerin doฤŸal veri tiplerinde olduฤŸunu unutmayฤฑn; รถrneฤŸin normal tarih iลŸlemleri yapabilirsiniz: + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/tr/docs/tutorial/extra-models.md b/docs/tr/docs/tutorial/extra-models.md new file mode 100644 index 0000000000..9aae28e05f --- /dev/null +++ b/docs/tr/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# Ek Modeller { #extra-models } + +ร–nceki รถrnekten devam edersek, birbiriyle iliลŸkili birden fazla modelin olmasฤฑ oldukรงa yaygฤฑndฤฑr. + +Bu durum รถzellikle kullanฤฑcฤฑ modellerinde sฤฑk gรถrรผlรผr, รงรผnkรผ: + +* **input modeli** bir `password` iรงerebilmelidir. +* **output modeli** `password` iรงermemelidir. +* **database modeli** bรผyรผk ihtimalle hash'lenmiลŸ bir `password` tutmalฤฑdฤฑr. + +/// danger + +Kullanฤฑcฤฑnฤฑn dรผz metin (plaintext) `password`'รผnรผ asla saklamayฤฑn. Her zaman sonradan doฤŸrulayabileceฤŸiniz "gรผvenli bir hash" saklayฤฑn. + +EฤŸer bilmiyorsanฤฑz, "password hash" nedir konusunu [gรผvenlik bรถlรผmlerinde](security/simple-oauth2.md#password-hashing){.internal-link target=_blank} รถฤŸreneceksiniz. + +/// + +## Birden ร‡ok Model { #multiple-models } + +`password` alanlarฤฑyla birlikte modellerin genel olarak nasฤฑl gรถrรผnebileceฤŸine ve nerelerde kullanฤฑlacaklarฤฑna dair bir fikir: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### `**user_in.model_dump()` Hakkฤฑnda { #about-user-in-model-dump } + +#### Pydantic'in `.model_dump()` Metodu { #pydantics-model-dump } + +`user_in`, `UserIn` sฤฑnฤฑfฤฑna ait bir Pydantic modelidir. + +Pydantic modellerinde, model verilerini iรงeren bir `dict` dรถndรผren `.model_dump()` metodu bulunur. + +Yani, ลŸรถyle bir Pydantic nesnesi `user_in` oluลŸturursak: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +ve sonra ลŸunu รงaฤŸฤฑrฤฑrsak: + +```Python +user_dict = user_in.model_dump() +``` + +artฤฑk `user_dict` deฤŸiลŸkeninde modelin verilerini iรงeren bir `dict` vardฤฑr (Pydantic model nesnesi yerine bir `dict` elde etmiลŸ oluruz). + +Ve eฤŸer ลŸunu รงaฤŸฤฑrฤฑrsak: + +```Python +print(user_dict) +``` + +ลŸรถyle bir Python `dict` elde ederiz: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### Bir `dict`'i Unpack Etmek { #unpacking-a-dict } + +`user_dict` gibi bir `dict` alฤฑp bunu bir fonksiyona (ya da sฤฑnฤฑfa) `**user_dict` ile gรถnderirsek, Python bunu "unpack" eder. Yani `user_dict` iรงindeki key ve value'larฤฑ doฤŸrudan key-value argรผmanlarฤฑ olarak geรงirir. + +Dolayฤฑsฤฑyla, yukarฤฑdaki `user_dict` ile devam edersek, ลŸunu yazmak: + +```Python +UserInDB(**user_dict) +``` + +ลŸuna eลŸdeฤŸer bir sonuรง รผretir: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +Ya da daha net ลŸekilde, `user_dict`'i doฤŸrudan kullanarak, gelecekte iรงeriฤŸi ne olursa olsun: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### Bir Pydantic Modelinden DiฤŸerinin ฤฐรงeriฤŸiyle Pydantic Model OluลŸturmak { #a-pydantic-model-from-the-contents-of-another } + +Yukarฤฑdaki รถrnekte `user_dict`'i `user_in.model_dump()` ile elde ettiฤŸimiz iรงin, ลŸu kod: + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +ลŸuna eลŸdeฤŸerdir: + +```Python +UserInDB(**user_in.model_dump()) +``` + +...รงรผnkรผ `user_in.model_dump()` bir `dict` dรถndรผrรผr ve biz de bunu `UserInDB`'ye `**` รถnekiyle vererek Python'ฤฑn "unpack" etmesini saฤŸlarฤฑz. + +Bรถylece, bir Pydantic modelindeki verilerden baลŸka bir Pydantic model รผretmiลŸ oluruz. + +#### Bir `dict`'i Unpack Etmek ve Ek Keyword'ler { #unpacking-a-dict-and-extra-keywords } + +Sonrasฤฑnda, aลŸaฤŸฤฑdaki gibi ek keyword argรผmanฤฑ `hashed_password=hashed_password` eklemek: + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +...ลŸuna benzer bir sonuca dรถnรผลŸรผr: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning + +Ek destek fonksiyonlarฤฑ olan `fake_password_hasher` ve `fake_save_user` sadece verinin olasฤฑ bir akฤฑลŸฤฑnฤฑ gรถstermek iรงindir; elbette gerรงek bir gรผvenlik saฤŸlamazlar. + +/// + +## Tekrarฤฑ Azaltma { #reduce-duplication } + +Kod tekrarฤฑnฤฑ azaltmak, **FastAPI**'nin temel fikirlerinden biridir. + +Kod tekrarฤฑ; bug, gรผvenlik problemi, kodun senkron dฤฑลŸฤฑna รงฤฑkmasฤฑ (bir yeri gรผncelleyip diฤŸerlerini gรผncellememek) gibi sorunlarฤฑn olasฤฑlฤฑฤŸฤฑnฤฑ artฤฑrฤฑr. + +Bu modellerin hepsi verinin bรผyรผk bir kฤฑsmฤฑnฤฑ paylaลŸฤฑyor ve attribute adlarฤฑnฤฑ ve type'larฤฑnฤฑ tekrar ediyor. + +Daha iyisini yapabiliriz. + +DiฤŸer modellerimiz iรงin temel olacak bir `UserBase` modeli tanฤฑmlayabiliriz. Sonra da bu modelden tรผreyen (subclass) modeller oluลŸturup onun attribute'larฤฑnฤฑ (type deklarasyonlarฤฑ, doฤŸrulama vb.) miras aldฤฑrabiliriz. + +Tรผm veri dรถnรผลŸtรผrme, doฤŸrulama, dokรผmantasyon vb. her zamanki gibi รงalฤฑลŸmaya devam eder. + +Bu sayede modeller arasฤฑndaki farklarฤฑ (plaintext `password` olan, `hashed_password` olan ve `password` olmayan) sadece o farklฤฑlฤฑklar olarak tanฤฑmlayabiliriz: + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` veya `anyOf` { #union-or-anyof } + +Bir response'u iki ya da daha fazla type'ฤฑn `Union`'ฤฑ olarak tanฤฑmlayabilirsiniz; bu, response'un bunlardan herhangi biri olabileceฤŸi anlamฤฑna gelir. + +OpenAPI'de bu `anyOf` ile tanฤฑmlanฤฑr. + +Bunu yapmak iรงin standart Python type hint'i olan `typing.Union`'ฤฑ kullanฤฑn: + +/// note + +Bir `Union` tanฤฑmlarken en spesifik type'ฤฑ รถnce, daha az spesifik olanฤฑ sonra ekleyin. AลŸaฤŸฤฑdaki รถrnekte daha spesifik olan `PlaneItem`, `Union[PlaneItem, CarItem]` iรงinde `CarItem`'dan รถnce gelir. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### Python 3.10'da `Union` { #union-in-python-3-10 } + +Bu รถrnekte `Union[PlaneItem, CarItem]` deฤŸerini `response_model` argรผmanฤฑna veriyoruz. + +Bunu bir **type annotation** iรงine koymak yerine bir **argรผmana deฤŸer** olarak geรงtiฤŸimiz iรงin, Python 3.10'da bile `Union` kullanmamฤฑz gerekiyor. + +EฤŸer bu bir type annotation iรงinde olsaydฤฑ, dikey รงizgiyi kullanabilirdik: + +```Python +some_variable: PlaneItem | CarItem +``` + +Ancak bunu `response_model=PlaneItem | CarItem` atamasฤฑna koyarsak hata alฤฑrฤฑz; รงรผnkรผ Python bunu bir type annotation olarak yorumlamak yerine `PlaneItem` ile `CarItem` arasฤฑnda **geรงersiz bir iลŸlem** yapmaya รงalฤฑลŸฤฑr. + +## Model Listesi { #list-of-models } + +Aynฤฑ ลŸekilde, nesne listesi dรถndรผren response'larฤฑ da tanฤฑmlayabilirsiniz. + +Bunun iรงin standart Python `typing.List`'i (ya da Python 3.9 ve รผzeri iรงin sadece `list`) kullanฤฑn: + +{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} + +## Rastgele `dict` ile Response { #response-with-arbitrary-dict } + +Bir Pydantic modeli kullanmadan, sadece key ve value type'larฤฑnฤฑ belirterek dรผz, rastgele bir `dict` ile de response tanฤฑmlayabilirsiniz. + +Bu, geรงerli field/attribute adlarฤฑnฤฑ (Pydantic modeli iรงin gerekli olurdu) รถnceden bilmiyorsanฤฑz kullanฤฑลŸlฤฑdฤฑr. + +Bu durumda `typing.Dict` (ya da Python 3.9 ve รผzeri iรงin sadece `dict`) kullanabilirsiniz: + +{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} + +## ร–zet { #recap } + +Her duruma gรถre birden fazla Pydantic modeli kullanฤฑn ve gerekirse รถzgรผrce inheritance uygulayฤฑn. + +Bir entity'nin farklฤฑ "state"lere sahip olmasฤฑ gerekiyorsa, o entity iรงin tek bir veri modeli kullanmak zorunda deฤŸilsiniz. ร–rneฤŸin `password` iรงeren, `password_hash` iรงeren ve `password` iรงermeyen state'lere sahip kullanฤฑcฤฑ "entity"si gibi. diff --git a/docs/tr/docs/tutorial/handling-errors.md b/docs/tr/docs/tutorial/handling-errors.md new file mode 100644 index 0000000000..a4d6937922 --- /dev/null +++ b/docs/tr/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# Hatalarฤฑ Yรถnetme { #handling-errors } + +APIโ€™nizi kullanan bir clientโ€™a hata bildirmek zorunda olduฤŸunuz pek รงok durum vardฤฑr. + +Bu client; frontendโ€™i olan bir tarayฤฑcฤฑ, baลŸka birinin yazdฤฑฤŸฤฑ bir kod, bir IoT cihazฤฑ vb. olabilir. + +Clientโ€™a ลŸunlarฤฑ sรถylemeniz gerekebilir: + +* Clientโ€™ฤฑn bu iลŸlem iรงin yeterli yetkisi yok. +* Clientโ€™ฤฑn bu kaynaฤŸa eriลŸimi yok. +* Clientโ€™ฤฑn eriลŸmeye รงalฤฑลŸtฤฑฤŸฤฑ รถฤŸe mevcut deฤŸil. +* vb. + +Bu durumlarda genellikle **400** aralฤฑฤŸฤฑnda (**400** ile **499** arasฤฑ) bir **HTTP status code** dรถndรผrรผrsรผnรผz. + +Bu, 200 HTTP status codeโ€™larฤฑna (200 ile 299 arasฤฑ) benzer. Bu "200" status codeโ€™larฤฑ, requestโ€™in bir ลŸekilde "baลŸarฤฑlฤฑ" olduฤŸunu ifade eder. + +400 aralฤฑฤŸฤฑndaki status codeโ€™lar ise hatanฤฑn client tarafฤฑndan kaynaklandฤฑฤŸฤฑnฤฑ gรถsterir. + +ลžu meลŸhur **"404 Not Found"** hatalarฤฑnฤฑ (ve ลŸakalarฤฑnฤฑ) hatฤฑrlฤฑyor musunuz? + +## `HTTPException` Kullanma { #use-httpexception } + +Clientโ€™a hata iรงeren HTTP responseโ€™larฤฑ dรถndรผrmek iรงin `HTTPException` kullanฤฑrsฤฑnฤฑz. + +### `HTTPException`โ€™ฤฑ Import Etme { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} + +### Kodunuzda Bir `HTTPException` Raise Etme { #raise-an-httpexception-in-your-code } + +`HTTPException`, APIโ€™lerle ilgili ek veriler iรงeren normal bir Python exceptionโ€™ฤฑdฤฑr. + +Python exceptionโ€™ฤฑ olduฤŸu iรงin `return` etmezsiniz, `raise` edersiniz. + +Bu aynฤฑ zamanda ลŸunu da ifade eder: *path operation function*โ€™ฤฑnฤฑzฤฑn iรงinde รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑz bir yardฤฑmcฤฑ (utility) fonksiyonun iรงindeyken `HTTPException` raise ederseniz, *path operation function* iรงindeki kodun geri kalanฤฑ รงalฤฑลŸmaz; requestโ€™i hemen sonlandฤฑrฤฑr ve `HTTPException` iรงindeki HTTP hatasฤฑnฤฑ clientโ€™a gรถnderir. + +Bir deฤŸer dรถndรผrmek yerine exception raise etmenin faydasฤฑ, Dependencies ve Security bรถlรผmรผnde daha da netleลŸecektir. + +Bu รถrnekte, client var olmayan bir ID ile bir item istediฤŸinde, `404` status codeโ€™u ile bir exception raise edelim: + +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} + +### Ortaya ร‡ฤฑkan Response { #the-resulting-response } + +Client `http://example.com/items/foo` (bir `item_id` `"foo"`) isterse, HTTP status code olarak 200 ve ลŸu JSON responseโ€™u alฤฑr: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +Ancak client `http://example.com/items/bar` (mevcut olmayan bir `item_id` `"bar"`) isterse, HTTP status code olarak 404 ("not found" hatasฤฑ) ve ลŸu JSON responseโ€™u alฤฑr: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | ฤฐpucu + +Bir `HTTPException` raise ederken, `detail` parametresine sadece `str` deฤŸil, JSONโ€™a dรถnรผลŸtรผrรผlebilen herhangi bir deฤŸer geรงebilirsiniz. + +ร–rneฤŸin `dict`, `list` vb. geรงebilirsiniz. + +Bunlar **FastAPI** tarafฤฑndan otomatik olarak iลŸlenir ve JSONโ€™a dรถnรผลŸtรผrรผlรผr. + +/// + +## ร–zel Headerโ€™lar Eklemek { #add-custom-headers } + +Bazฤฑ durumlarda HTTP hata responseโ€™una รถzel headerโ€™lar eklemek faydalฤฑdฤฑr. ร–rneฤŸin bazฤฑ gรผvenlik tรผrlerinde. + +Muhtemelen bunu doฤŸrudan kendi kodunuzda kullanmanฤฑz gerekmeyecek. + +Ama ileri seviye bir senaryo iรงin ihtiyaรง duyarsanฤฑz, รถzel headerโ€™lar ekleyebilirsiniz: + +{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} + +## ร–zel Exception Handlerโ€™larฤฑ Kurmak { #install-custom-exception-handlers } + +Starletteโ€™in aynฤฑ exception yardฤฑmcฤฑ araรงlarฤฑyla รถzel exception handlerโ€™lar ekleyebilirsiniz. + +Diyelim ki sizin (ya da kullandฤฑฤŸฤฑnฤฑz bir kรผtรผphanenin) `raise` edebileceฤŸi `UnicornException` adฤฑnda รถzel bir exceptionโ€™ฤฑnฤฑz var. + +Ve bu exceptionโ€™ฤฑ FastAPI ile global olarak handle etmek istiyorsunuz. + +`@app.exception_handler()` ile รถzel bir exception handler ekleyebilirsiniz: + +{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} + +Burada `/unicorns/yolo` iรงin request atarsanฤฑz, *path operation* bir `UnicornException` `raise` eder. + +Ancak bu, `unicorn_exception_handler` tarafฤฑndan handle edilir. + +Bรถylece HTTP status codeโ€™u `418` olan, JSON iรงeriฤŸi ลŸu ลŸekilde temiz bir hata responseโ€™u alฤฑrsฤฑnฤฑz: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Teknik Detaylar + +`from starlette.requests import Request` ve `from starlette.responses import JSONResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.responses` iรงeriฤŸini `fastapi.responses` olarak da sunar. Ancak mevcut responseโ€™larฤฑn รงoฤŸu doฤŸrudan Starletteโ€™ten gelir. `Request` iรงin de aynฤฑsฤฑ geรงerlidir. + +/// + +## Varsayฤฑlan Exception Handlerโ€™larฤฑ Override Etmek { #override-the-default-exception-handlers } + +**FastAPI** bazฤฑ varsayฤฑlan exception handlerโ€™lara sahiptir. + +Bu handlerโ€™lar, `HTTPException` `raise` ettiฤŸinizde ve request geรงersiz veri iรงerdiฤŸinde varsayฤฑlan JSON responseโ€™larฤฑ dรถndรผrmekten sorumludur. + +Bu exception handlerโ€™larฤฑ kendi handlerโ€™larฤฑnฤฑzla override edebilirsiniz. + +### Request Validation Exceptionโ€™larฤฑnฤฑ Override Etmek { #override-request-validation-exceptions } + +Bir request geรงersiz veri iรงerdiฤŸinde, **FastAPI** iรงeride `RequestValidationError` raise eder. + +Ve bunun iรงin varsayฤฑlan bir exception handler da iรงerir. + +Override etmek iรงin `RequestValidationError`โ€™ฤฑ import edin ve exception handlerโ€™ฤฑ `@app.exception_handler(RequestValidationError)` ile decorate edin. + +Exception handler, bir `Request` ve exceptionโ€™ฤฑ alฤฑr. + +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} + +Artฤฑk `/items/foo`โ€™ya giderseniz, ลŸu varsayฤฑlan JSON hatasฤฑ yerine: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +ลŸu ลŸekilde bir metin (text) versiyonu alฤฑrsฤฑnฤฑz: + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### `HTTPException` Hata Handlerโ€™ฤฑnฤฑ Override Etmek { #override-the-httpexception-error-handler } + +Benzer ลŸekilde `HTTPException` handlerโ€™ฤฑnฤฑ da override edebilirsiniz. + +ร–rneฤŸin bu hatalar iรงin JSON yerine plain text response dรถndรผrmek isteyebilirsiniz: + +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} + +/// note | Teknik Detaylar + +`from starlette.responses import PlainTextResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.responses` iรงeriฤŸini `fastapi.responses` olarak da sunar. Ancak mevcut responseโ€™larฤฑn รงoฤŸu doฤŸrudan Starletteโ€™ten gelir. + +/// + +/// warning | Uyarฤฑ + +`RequestValidationError`, validation hatasฤฑnฤฑn gerรงekleลŸtiฤŸi dosya adฤฑ ve satฤฑr bilgilerini iรงerir; isterseniz bunu logโ€™larฤฑnฤฑza ilgili bilgilerle birlikte yazdฤฑrabilirsiniz. + +Ancak bu, eฤŸer sadece stringโ€™e รงevirip bu bilgiyi doฤŸrudan response olarak dรถndรผrรผrseniz sisteminiz hakkฤฑnda bir miktar bilgi sฤฑzdฤฑrabileceฤŸiniz anlamฤฑna gelir. Bu yรผzden burada kod, her bir hatayฤฑ ayrฤฑ ayrฤฑ รงฤฑkarฤฑp gรถsterir. + +/// + +### `RequestValidationError` Bodyโ€™sini Kullanmak { #use-the-requestvalidationerror-body } + +`RequestValidationError`, geรงersiz veriyle aldฤฑฤŸฤฑ `body`โ€™yi iรงerir. + +Uygulamanฤฑzฤฑ geliลŸtirirken bodyโ€™yi logโ€™lamak, debug etmek, kullanฤฑcฤฑya dรถndรผrmek vb. iรงin bunu kullanabilirsiniz. + +{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} + +ลžimdi ลŸu gibi geรงersiz bir item gรถndermeyi deneyin: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +AldฤฑฤŸฤฑnฤฑz bodyโ€™yi de iรงeren, verinin geรงersiz olduฤŸunu sรถyleyen bir response alฤฑrsฤฑnฤฑz: + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### FastAPIโ€™nin `HTTPException`โ€™ฤฑ vs Starletteโ€™in `HTTPException`โ€™ฤฑ { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI**โ€™nin kendi `HTTPException`โ€™ฤฑ vardฤฑr. + +Ve **FastAPI**โ€™nin `HTTPException` hata sฤฑnฤฑfฤฑ, Starletteโ€™in `HTTPException` hata sฤฑnฤฑfฤฑndan kalฤฑtฤฑm alฤฑr (inherit). + +Tek fark ลŸudur: **FastAPI**โ€™nin `HTTPException`โ€™ฤฑ `detail` alanฤฑ iรงin JSONโ€™a รงevrilebilir herhangi bir veri kabul ederken, Starletteโ€™in `HTTPException`โ€™ฤฑ burada sadece string kabul eder. + +Bu yรผzden kodunuzda her zamanki gibi **FastAPI**โ€™nin `HTTPException`โ€™ฤฑnฤฑ raise etmeye devam edebilirsiniz. + +Ancak bir exception handler register ederken, bunu Starletteโ€™in `HTTPException`โ€™ฤฑ iรงin register etmelisiniz. + +Bรถylece Starletteโ€™in internal kodunun herhangi bir bรถlรผmรผ ya da bir Starlette extension/plug-inโ€™i Starlette `HTTPException` raise ederse, handlerโ€™ฤฑnฤฑz bunu yakalayฤฑp (catch) handle edebilir. + +Bu รถrnekte, iki `HTTPException`โ€™ฤฑ da aynฤฑ kodda kullanabilmek iรงin Starletteโ€™in exceptionโ€™ฤฑ `StarletteHTTPException` olarak yeniden adlandฤฑrฤฑlฤฑyor: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### **FastAPI**โ€™nin Exception Handlerโ€™larฤฑnฤฑ Yeniden Kullanmak { #reuse-fastapis-exception-handlers } + +Exceptionโ€™ฤฑ, **FastAPI**โ€™nin aynฤฑ varsayฤฑlan exception handlerโ€™larฤฑyla birlikte kullanmak isterseniz, varsayฤฑlan exception handlerโ€™larฤฑ `fastapi.exception_handlers` iรงinden import edip yeniden kullanabilirsiniz: + +{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} + +Bu รถrnekte sadece oldukรงa aรงฤฑklayฤฑcฤฑ bir mesajla hatayฤฑ yazdฤฑrฤฑyorsunuz; ama fikir anlaลŸฤฑlฤฑyor. Exceptionโ€™ฤฑ kullanฤฑp ardฤฑndan varsayฤฑlan exception handlerโ€™larฤฑ olduฤŸu gibi yeniden kullanabilirsiniz. diff --git a/docs/tr/docs/tutorial/header-param-models.md b/docs/tr/docs/tutorial/header-param-models.md new file mode 100644 index 0000000000..9170515dcf --- /dev/null +++ b/docs/tr/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Header Parametre Modelleri { #header-parameter-models } + +Birbiriyle iliลŸkili **header parametreleri**nden oluลŸan bir grubunuz varsa, bunlarฤฑ tanฤฑmlamak iรงin bir **Pydantic model** oluลŸturabilirsiniz. + +Bu sayede modeli **birden fazla yerde yeniden kullanabilir**, ayrฤฑca tรผm parametreler iรงin doฤŸrulamalarฤฑ ve metadata bilgilerini tek seferde tanฤฑmlayabilirsiniz. ๐Ÿ˜Ž + +/// note | Not + +Bu รถzellik FastAPI `0.115.0` sรผrรผmรผnden beri desteklenmektedir. ๐Ÿค“ + +/// + +## Pydantic Model ile Header Parametreleri { #header-parameters-with-a-pydantic-model } + +ฤฐhtiyacฤฑnฤฑz olan **header parametreleri**ni bir **Pydantic model** iรงinde tanฤฑmlayฤฑn, ardฤฑndan parametreyi `Header` olarak belirtin: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI**, request iรงindeki **headers** bรถlรผmรผnden **her alan** iรงin veriyi **รงฤฑkarฤฑr** ve size tanฤฑmladฤฑฤŸฤฑnฤฑz Pydantic model รถrneฤŸini verir. + +## Dokรผmanlarฤฑ Kontrol Edin { #check-the-docs } + +Gerekli header'larฤฑ `/docs` altฤฑndaki dokรผman arayรผzรผnde gรถrebilirsiniz: + +
+ +
+ +## Ek Header'larฤฑ Yasaklayฤฑn { #forbid-extra-headers } + +Bazฤฑ รถzel kullanฤฑm senaryolarฤฑnda (muhtemelen รงok yaygฤฑn deฤŸil), kabul etmek istediฤŸiniz header'larฤฑ **kฤฑsฤฑtlamak** isteyebilirsiniz. + +Pydantic'in model yapฤฑlandฤฑrmasฤฑnฤฑ kullanarak `extra` alanlarฤฑ `forbid` edebilirsiniz: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Bir client bazฤฑ **ek header'lar** gรถndermeye รงalฤฑลŸฤฑrsa, **hata** response'u alฤฑr. + +ร–rneฤŸin client, deฤŸeri `plumbus` olan bir `tool` header'ฤฑ gรถndermeye รงalฤฑลŸฤฑrsa, `tool` header parametresine izin verilmediฤŸini sรถyleyen bir **hata** response'u alฤฑr: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Alt ร‡izgileri DรถnรผลŸtรผrmeyi Kapatฤฑn { #disable-convert-underscores } + +Normal header parametrelerinde olduฤŸu gibi, parametre adlarฤฑnda alt รงizgi karakterleri olduฤŸunda bunlar **otomatik olarak tireye dรถnรผลŸtรผrรผlรผr**. + +ร–rneฤŸin kodda `save_data` adlฤฑ bir header parametreniz varsa, beklenen HTTP header `save-data` olur ve dokรผmanlarda da bu ลŸekilde gรถrรผnรผr. + +Herhangi bir sebeple bu otomatik dรถnรผลŸรผmรผ kapatmanฤฑz gerekiyorsa, header parametreleri iรงin kullandฤฑฤŸฤฑnฤฑz Pydantic model'lerde de bunu devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | Uyarฤฑ + +`convert_underscores` deฤŸerini `False` yapmadan รถnce, bazฤฑ HTTP proxy'lerinin ve server'larฤฑn alt รงizgi iรงeren header'larฤฑn kullanฤฑmฤฑna izin vermediฤŸini unutmayฤฑn. + +/// + +## ร–zet { #summary } + +**FastAPI**'de **headers** tanฤฑmlamak iรงin **Pydantic model** kullanabilirsiniz. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/header-params.md b/docs/tr/docs/tutorial/header-params.md new file mode 100644 index 0000000000..ca787f534c --- /dev/null +++ b/docs/tr/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Header Parametreleri { #header-parameters } + +`Query`, `Path` ve `Cookie` parametrelerini nasฤฑl tanฤฑmlฤฑyorsanฤฑz, Header parametrelerini de aynฤฑ ลŸekilde tanฤฑmlayabilirsiniz. + +## `Header`'ฤฑ Import Edin { #import-header } + +ร–nce `Header`'ฤฑ import edin: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## `Header` Parametrelerini Tanฤฑmlayฤฑn { #declare-header-parameters } + +Ardฤฑndan header parametrelerini, `Path`, `Query` ve `Cookie` ile kullandฤฑฤŸฤฑnฤฑz yapฤฑnฤฑn aynฤฑsฤฑyla tanฤฑmlayฤฑn. + +Default deฤŸeri ve ek validation ya da annotation parametrelerinin tamamฤฑnฤฑ belirleyebilirsiniz: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | Teknik Detaylar + +`Header`, `Path`, `Query` ve `Cookie`'nin "kardeลŸ" sฤฑnฤฑfฤฑdฤฑr. Ayrฤฑca aynฤฑ ortak `Param` sฤฑnฤฑfฤฑndan kalฤฑtฤฑm alฤฑr. + +Ancak ลŸunu unutmayฤฑn: `fastapi`'den `Query`, `Path`, `Header` ve diฤŸerlerini import ettiฤŸinizde, bunlar aslฤฑnda รถzel sฤฑnฤฑflarฤฑ dรถndรผren fonksiyonlardฤฑr. + +/// + +/// info | Bilgi + +Header'larฤฑ tanฤฑmlamak iรงin `Header` kullanmanฤฑz gerekir; aksi halde parametreler query parametreleri olarak yorumlanฤฑr. + +/// + +## Otomatik DรถnรผลŸtรผrme { #automatic-conversion } + +`Header`, `Path`, `Query` ve `Cookie`'nin saฤŸladฤฑklarฤฑna ek olarak kรผรงรผk bir ekstra iลŸlevsellik sunar. + +Standart header'larฤฑn รงoฤŸu, "hyphen" karakteri (diฤŸer adฤฑyla "minus symbol" (`-`)) ile ayrฤฑlฤฑr. + +Ancak `user-agent` gibi bir deฤŸiลŸken adฤฑ Python'da geรงersizdir. + +Bu yรผzden, default olarak `Header`, header'larฤฑ almak ve dokรผmante etmek iรงin parametre adlarฤฑndaki underscore (`_`) karakterlerini hyphen (`-`) ile dรถnรผลŸtรผrรผr. + +Ayrฤฑca HTTP header'larฤฑ bรผyรผk/kรผรงรผk harfe duyarlฤฑ deฤŸildir; dolayฤฑsฤฑyla onlarฤฑ standart Python stiliyle (diฤŸer adฤฑyla "snake_case") tanฤฑmlayabilirsiniz. + +Yani `User_Agent` gibi bir ลŸey yazฤฑp ilk harfleri bรผyรผtmeniz gerekmeden, Python kodunda normalde kullandฤฑฤŸฤฑnฤฑz gibi `user_agent` kullanabilirsiniz. + +Herhangi bir nedenle underscore'larฤฑn hyphen'lara otomatik dรถnรผลŸtรผrรผlmesini kapatmanฤฑz gerekirse, `Header`'ฤฑn `convert_underscores` parametresini `False` yapฤฑn: + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | Uyarฤฑ + +`convert_underscores`'u `False` yapmadan รถnce, bazฤฑ HTTP proxy'lerinin ve server'larฤฑn underscore iรงeren header'larฤฑn kullanฤฑmฤฑna izin vermediฤŸini unutmayฤฑn. + +/// + +## Yinelenen Header'lar { #duplicate-headers } + +Yinelenen header'lar almak mรผmkรผndรผr. Yani aynฤฑ header'ฤฑn birden fazla deฤŸeri olabilir. + +Bu tรผr durumlarฤฑ, type tanฤฑmฤฑnda bir list kullanarak belirtebilirsiniz. + +Yinelenen header'daki tรผm deฤŸerleri Python `list` olarak alฤฑrsฤฑnฤฑz. + +ร–rneฤŸin, birden fazla kez gelebilen `X-Token` header'ฤฑnฤฑ tanฤฑmlamak iรงin ลŸรถyle yazabilirsiniz: + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +EฤŸer bu *path operation* ile iki HTTP header gรถndererek iletiลŸim kurarsanฤฑz: + +``` +X-Token: foo +X-Token: bar +``` + +response ลŸรถyle olur: + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## ร–zet { #recap } + +Header'larฤฑ `Header` ile tanฤฑmlayฤฑn; `Query`, `Path` ve `Cookie` ile kullanฤฑlan ortak kalฤฑbฤฑ burada da kullanฤฑn. + +DeฤŸiลŸkenlerinizdeki underscore'lar konusunda endiลŸelenmeyin, **FastAPI** bunlarฤฑ dรถnรผลŸtรผrmeyi halleder. diff --git a/docs/tr/docs/tutorial/index.md b/docs/tr/docs/tutorial/index.md new file mode 100644 index 0000000000..f672c9e20b --- /dev/null +++ b/docs/tr/docs/tutorial/index.md @@ -0,0 +1,95 @@ +# EฤŸitim - Kullanฤฑcฤฑ Rehberi { #tutorial-user-guide } + +Bu eฤŸitim, **FastAPI**'yi รถzelliklerinin รงoฤŸuyla birlikte adฤฑm adฤฑm nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ gรถsterir. + +Her bรถlรผm bir รถncekilerin รผzerine kademeli olarak eklenir, ancak konular birbirinden ayrฤฑlacak ลŸekilde yapฤฑlandฤฑrฤฑlmฤฑลŸtฤฑr; bรถylece API ihtiyaรงlarฤฑnฤฑza gรถre doฤŸrudan belirli bir konuya gidip aradฤฑฤŸฤฑnฤฑzฤฑ bulabilirsiniz. + +Ayrฤฑca, ileride tekrar dรถnรผp tam olarak ihtiyaรง duyduฤŸunuz ลŸeyi gรถrebileceฤŸiniz bir referans olarak da tasarlanmฤฑลŸtฤฑr. + +## Kodu ร‡alฤฑลŸtฤฑrฤฑn { #run-the-code } + +Tรผm code block'lar kopyalanฤฑp doฤŸrudan kullanฤฑlabilir (zaten test edilmiลŸ Python dosyalarฤฑdฤฑr). + +ร–rneklerden herhangi birini รงalฤฑลŸtฤฑrmak iรงin, kodu `main.py` adlฤฑ bir dosyaya kopyalayฤฑn ve ลŸu komutla `fastapi dev`'i baลŸlatฤฑn: + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +Kodu yazmanฤฑz ya da kopyalayฤฑp dรผzenlemeniz ve yerelinizde รงalฤฑลŸtฤฑrmanฤฑz **ลŸiddetle รถnerilir**. + +Editรถrรผnรผzde kullanmak FastAPI'nin avantajlarฤฑnฤฑ gerรงekten gรถsterir: ne kadar az kod yazmanฤฑz gerektiฤŸini, type check'leri, autocompletion'ฤฑ vb. gรถrรผrsรผnรผz. + +--- + +## FastAPI'yi Kurun { #install-fastapi } + +ฤฐlk adฤฑm FastAPI'yi kurmaktฤฑr. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, etkinleลŸtirin ve ardฤฑndan **FastAPI'yi kurun**: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +/// note | Not + +`pip install "fastapi[standard]"` ile kurduฤŸunuzda, bazฤฑ varsayฤฑlan opsiyonel standard baฤŸฤฑmlฤฑlฤฑklarla birlikte gelir. Bunlara `fastapi-cloud-cli` da dahildir; bu sayede FastAPI Cloud'a deploy edebilirsiniz. + +Bu opsiyonel baฤŸฤฑmlฤฑlฤฑklarฤฑ istemiyorsanฤฑz bunun yerine `pip install fastapi` kurabilirsiniz. + +Standard baฤŸฤฑmlฤฑlฤฑklarฤฑ kurmak istiyor ama `fastapi-cloud-cli` olmasฤฑn diyorsanฤฑz, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile kurabilirsiniz. + +/// + +## ฤฐleri Dรผzey Kullanฤฑcฤฑ Rehberi { #advanced-user-guide } + +Bu **EฤŸitim - Kullanฤฑcฤฑ Rehberi**'ni bitirdikten sonra daha sonra okuyabileceฤŸiniz bir **ฤฐleri Dรผzey Kullanฤฑcฤฑ Rehberi** de var. + +**ฤฐleri Dรผzey Kullanฤฑcฤฑ Rehberi** bunun รผzerine inลŸa eder, aynฤฑ kavramlarฤฑ kullanฤฑr ve size bazฤฑ ek รถzellikler รถฤŸretir. + +Ancak รถnce **EฤŸitim - Kullanฤฑcฤฑ Rehberi**'ni (ลŸu anda okuduฤŸunuz bรถlรผmรผ) okumalฤฑsฤฑnฤฑz. + +Yalnฤฑzca **EฤŸitim - Kullanฤฑcฤฑ Rehberi** ile eksiksiz bir uygulama oluลŸturabilmeniz hedeflenmiลŸtir; ardฤฑndan ihtiyaรงlarฤฑnฤฑza gรถre, **ฤฐleri Dรผzey Kullanฤฑcฤฑ Rehberi**'ndeki ek fikirlerden bazฤฑlarฤฑnฤฑ kullanarak farklฤฑ ลŸekillerde geniลŸletebilirsiniz. diff --git a/docs/tr/docs/tutorial/metadata.md b/docs/tr/docs/tutorial/metadata.md new file mode 100644 index 0000000000..dacd68cf56 --- /dev/null +++ b/docs/tr/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# Metadata ve Dokรผman URL'leri { #metadata-and-docs-urls } + +**FastAPI** uygulamanฤฑzda รงeลŸitli metadata yapฤฑlandฤฑrmalarฤฑnฤฑ รถzelleลŸtirebilirsiniz. + +## API iรงin Metadata { #metadata-for-api } + +OpenAPI spesifikasyonunda ve otomatik API dokรผman arayรผzlerinde kullanฤฑlan ลŸu alanlarฤฑ ayarlayabilirsiniz: + +| Parametre | Tip | Aรงฤฑklama | +|------------|------|-------------| +| `title` | `str` | API'nin baลŸlฤฑฤŸฤฑ. | +| `summary` | `str` | API'nin kฤฑsa รถzeti. OpenAPI 3.1.0, FastAPI 0.99.0 sรผrรผmรผnden itibaren mevcut. | +| `description` | `str` | API'nin kฤฑsa aรงฤฑklamasฤฑ. Markdown kullanabilir. | +| `version` | `string` | API'nin sรผrรผmรผ. Bu, OpenAPI'nin deฤŸil, kendi uygulamanฤฑzฤฑn sรผrรผmรผdรผr. ร–rneฤŸin `2.5.0`. | +| `terms_of_service` | `str` | API'nin Kullanฤฑm KoลŸullarฤฑ (Terms of Service) iรงin bir URL. Verilirse, URL formatฤฑnda olmalฤฑdฤฑr. | +| `contact` | `dict` | Yayฤฑnlanan API iรงin iletiลŸim bilgileri. Birden fazla alan iรงerebilir.
contact alanlarฤฑ
ParametreTipAรงฤฑklama
namestrฤฐletiลŸim kiลŸisi/kuruluลŸunu tanฤฑmlayan ad.
urlstrฤฐletiลŸim bilgilerine iลŸaret eden URL. URL formatฤฑnda OLMALIDIR.
emailstrฤฐletiลŸim kiลŸisi/kuruluลŸunun e-posta adresi. E-posta adresi formatฤฑnda OLMALIDIR.
| +| `license_info` | `dict` | Yayฤฑnlanan API iรงin lisans bilgileri. Birden fazla alan iรงerebilir.
license_info alanlarฤฑ
ParametreTipAรงฤฑklama
namestrZORUNLU (license_info ayarlanmฤฑลŸsa). API iรงin kullanฤฑlan lisans adฤฑ.
identifierstrAPI iรงin bir SPDX lisans ifadesi. identifier alanฤฑ, url alanฤฑyla karลŸฤฑlฤฑklฤฑ olarak dฤฑลŸlayฤฑcฤฑdฤฑr (ikisi aynฤฑ anda kullanฤฑlamaz). OpenAPI 3.1.0, FastAPI 0.99.0 sรผrรผmรผnden itibaren mevcut.
urlstrAPI iรงin kullanฤฑlan lisansa ait URL. URL formatฤฑnda OLMALIDIR.
| + +ลžu ลŸekilde ayarlayabilirsiniz: + +{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} + +/// tip | ฤฐpucu + +`description` alanฤฑna Markdown yazabilirsiniz; รงฤฑktฤฑ tarafฤฑnda render edilir. + +/// + +Bu yapฤฑlandฤฑrmayla otomatik API dokรผmanlarฤฑ ลŸรถyle gรถrรผnรผr: + + + +## License identifier { #license-identifier } + +OpenAPI 3.1.0 ve FastAPI 0.99.0 sรผrรผmรผnden itibaren, `license_info` iรงinde `url` yerine bir `identifier` da ayarlayabilirsiniz. + +ร–rneฤŸin: + +{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} + +## Tag'ler iรงin Metadata { #metadata-for-tags } + +`openapi_tags` parametresiyle, path operation'larฤฑnฤฑzฤฑ gruplamak iรงin kullandฤฑฤŸฤฑnฤฑz farklฤฑ tag'ler adฤฑna ek metadata da ekleyebilirsiniz. + +Bu parametre, her tag iรงin bir sรถzlรผk (dictionary) iรงeren bir liste alฤฑr. + +Her sรถzlรผk ลŸunlarฤฑ iรงerebilir: + +* `name` (**zorunlu**): *path operation*'larda ve `APIRouter`'larda `tags` parametresinde kullandฤฑฤŸฤฑnฤฑz tag adฤฑyla aynฤฑ olan bir `str`. +* `description`: tag iรงin kฤฑsa bir aรงฤฑklama iรงeren `str`. Markdown iรงerebilir ve dokรผman arayรผzรผnde gรถsterilir. +* `externalDocs`: harici dokรผmanlarฤฑ tanฤฑmlayan bir `dict`: + * `description`: harici dokรผmanlar iรงin kฤฑsa aรงฤฑklama iรงeren `str`. + * `url` (**zorunlu**): harici dokรผmantasyonun URL'sini iรงeren `str`. + +### Tag'ler iรงin metadata oluลŸturun { #create-metadata-for-tags } + +`users` ve `items` tag'lerini iรงeren bir รถrnekle deneyelim. + +Tag'leriniz iรงin metadata oluลŸturup `openapi_tags` parametresine geรงin: + +{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} + +Aรงฤฑklamalarฤฑn iรงinde Markdown kullanabileceฤŸinizi unutmayฤฑn; รถrneฤŸin "login" kalฤฑn (**login**) ve "fancy" italik (_fancy_) olarak gรถsterilecektir. + +/// tip | ฤฐpucu + +KullandฤฑฤŸฤฑnฤฑz tรผm tag'ler iรงin metadata eklemek zorunda deฤŸilsiniz. + +/// + +### Tag'lerinizi kullanฤฑn { #use-your-tags } + +*path operation*'larฤฑnฤฑzฤฑ (ve `APIRouter`'larฤฑ) farklฤฑ tag'lere atamak iรงin `tags` parametresini kullanฤฑn: + +{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} + +/// info | Bilgi + +Tag'ler hakkฤฑnda daha fazlasฤฑ iรงin: [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank}. + +/// + +### Dokรผmanlarฤฑ kontrol edin { #check-the-docs } + +Artฤฑk dokรผmanlara baktฤฑฤŸฤฑnฤฑzda, eklediฤŸiniz tรผm metadata gรถsterilir: + + + +### Tag sฤฑrasฤฑ { #order-of-tags } + +Her tag metadata sรถzlรผฤŸรผnรผn listedeki sฤฑrasฤฑ, dokรผman arayรผzรผnde gรถsterilecek sฤฑrayฤฑ da belirler. + +ร–rneฤŸin alfabetik sฤฑralamada `users`, `items`'tan sonra gelirdi; ancak listedeki ilk sรถzlรผk olarak `users` metadata'sฤฑnฤฑ eklediฤŸimiz iรงin, dokรผmanlarda รถnce o gรถrรผnรผr. + +## OpenAPI URL'si { #openapi-url } + +Varsayฤฑlan olarak OpenAPI ลŸemasฤฑ `/openapi.json` adresinden sunulur. + +Ancak bunu `openapi_url` parametresiyle yapฤฑlandฤฑrabilirsiniz. + +ร–rneฤŸin `/api/v1/openapi.json` adresinden sunulacak ลŸekilde ayarlamak iรงin: + +{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} + +OpenAPI ลŸemasฤฑnฤฑ tamamen kapatmak isterseniz `openapi_url=None` ayarlayabilirsiniz; bu, onu kullanan dokรผmantasyon arayรผzlerini de devre dฤฑลŸฤฑ bฤฑrakฤฑr. + +## Dokรผman URL'leri { #docs-urls } + +Dahil gelen iki dokรผmantasyon arayรผzรผnรผ yapฤฑlandฤฑrabilirsiniz: + +* **Swagger UI**: `/docs` adresinden sunulur. + * URL'sini `docs_url` parametresiyle ayarlayabilirsiniz. + * `docs_url=None` ayarlayarak devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. +* **ReDoc**: `/redoc` adresinden sunulur. + * URL'sini `redoc_url` parametresiyle ayarlayabilirsiniz. + * `redoc_url=None` ayarlayarak devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. + +ร–rneฤŸin Swagger UI'yi `/documentation` adresinden sunup ReDoc'u kapatmak iรงin: + +{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} diff --git a/docs/tr/docs/tutorial/middleware.md b/docs/tr/docs/tutorial/middleware.md new file mode 100644 index 0000000000..68222265e7 --- /dev/null +++ b/docs/tr/docs/tutorial/middleware.md @@ -0,0 +1,95 @@ +# Middleware { #middleware } + +**FastAPI** uygulamalarฤฑna middleware ekleyebilirsiniz. + +"Middleware", herhangi bir รถzel *path operation* tarafฤฑndan iลŸlenmeden รถnce her **request** ile รงalฤฑลŸan bir fonksiyondur. Ayrฤฑca geri dรถndรผrmeden รถnce her **response** ile de รงalฤฑลŸฤฑr. + +* Uygulamanฤฑza gelen her **request**'i alฤฑr. +* Ardฤฑndan o **request** รผzerinde bir iลŸlem yapabilir veya gerekli herhangi bir kodu รงalฤฑลŸtฤฑrabilir. +* Sonra **request**'i uygulamanฤฑn geri kalanฤฑ tarafฤฑndan iลŸlenmesi iรงin iletir (bir *path operation* tarafฤฑndan). +* Ardฤฑndan uygulama tarafฤฑndan รผretilen **response**'u alฤฑr (bir *path operation* tarafฤฑndan). +* Sonra o **response** รผzerinde bir iลŸlem yapabilir veya gerekli herhangi bir kodu รงalฤฑลŸtฤฑrabilir. +* Son olarak **response**'u dรถndรผrรผr. + +/// note | Teknik Detaylar + +`yield` ile dependency'leriniz varsa, รงฤฑkฤฑลŸ (exit) kodu middleware'den *sonra* รงalฤฑลŸฤฑr. + +Herhangi bir background task varsa ([Background Tasks](background-tasks.md){.internal-link target=_blank} bรถlรผmรผnde ele alฤฑnฤฑyor, ileride gรถreceksiniz), bunlar tรผm middleware'ler *tamamlandฤฑktan sonra* รงalฤฑลŸฤฑr. + +/// + +## Middleware OluลŸturma { #create-a-middleware } + +Bir middleware oluลŸturmak iรงin bir fonksiyonun รผzerine `@app.middleware("http")` decorator'รผnรผ kullanฤฑrsฤฑnฤฑz. + +Middleware fonksiyonu ลŸunlarฤฑ alฤฑr: + +* `request`. +* Parametre olarak `request` alacak bir `call_next` fonksiyonu. + * Bu fonksiyon `request`'i ilgili *path operation*'a iletir. + * Ardฤฑndan ilgili *path operation* tarafฤฑndan รผretilen `response`'u dรถndรผrรผr. +* Sonrasฤฑnda `response`'u dรถndรผrmeden รถnce ayrฤฑca deฤŸiลŸtirebilirsiniz. + +{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} + +/// tip | ฤฐpucu + +ร–zel (proprietary) header'lar `X-` prefix'i kullanฤฑlarak eklenebilir, bunu aklฤฑnฤฑzda tutun. + +Ancak tarayฤฑcฤฑdaki bir client'ฤฑn gรถrebilmesini istediฤŸiniz รถzel header'larฤฑnฤฑz varsa, bunlarฤฑ CORS konfigรผrasyonlarฤฑnฤฑza ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) eklemeniz gerekir. Bunun iรงin, Starlette'ฤฑn CORS dokรผmanlarฤฑnda belgelenen `expose_headers` parametresini kullanฤฑn. + +/// + +/// note | Teknik Detaylar + +`from starlette.requests import Request` da kullanabilirdiniz. + +**FastAPI** bunu geliลŸtirici olarak size kolaylฤฑk olsun diye sunar. Ancak doฤŸrudan Starlette'tan gelir. + +/// + +### `response`'tan ร–nce ve Sonra { #before-and-after-the-response } + +Herhangi bir *path operation* `request`'i almadan รถnce, `request` ile birlikte รงalฤฑลŸacak kod ekleyebilirsiniz. + +Ayrฤฑca `response` รผretildikten sonra, geri dรถndรผrmeden รถnce de kod รงalฤฑลŸtฤฑrabilirsiniz. + +ร–rneฤŸin, request'i iลŸleyip response รผretmenin kaรง saniye sรผrdรผฤŸรผnรผ iรงeren `X-Process-Time` adlฤฑ รถzel bir header ekleyebilirsiniz: + +{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} + +/// tip | ฤฐpucu + +Burada `time.time()` yerine `time.perf_counter()` kullanฤฑyoruz, รงรผnkรผ bu kullanฤฑm senaryolarฤฑnda daha hassas olabilir. ๐Ÿค“ + +/// + +## Birden Fazla Middleware ร‡alฤฑลŸtฤฑrma Sฤฑrasฤฑ { #multiple-middleware-execution-order } + +`@app.middleware()` decorator'รผ veya `app.add_middleware()` metodu ile birden fazla middleware eklediฤŸinizde, eklenen her yeni middleware uygulamayฤฑ sarar ve bir stack oluลŸturur. En son eklenen middleware en *dฤฑลŸtaki* (outermost), ilk eklenen ise en *iรงteki* (innermost) olur. + +Request tarafฤฑnda รถnce en *dฤฑลŸtaki* middleware รงalฤฑลŸฤฑr. + +Response tarafฤฑnda ise en son o รงalฤฑลŸฤฑr. + +ร–rneฤŸin: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +Bu, aลŸaฤŸฤฑdaki รงalฤฑลŸtฤฑrma sฤฑrasฤฑnฤฑ oluลŸturur: + +* **Request**: MiddlewareB โ†’ MiddlewareA โ†’ route + +* **Response**: route โ†’ MiddlewareA โ†’ MiddlewareB + +Bu stack davranฤฑลŸฤฑ, middleware'lerin รถngรถrรผlebilir ve kontrol edilebilir bir sฤฑrayla รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ saฤŸlar. + +## DiฤŸer Middleware'ler { #other-middlewares } + +DiฤŸer middleware'ler hakkฤฑnda daha fazlasฤฑnฤฑ daha sonra [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank} bรถlรผmรผnde okuyabilirsiniz. + +Bir sonraki bรถlรผmde, middleware ile CORS'un nasฤฑl ele alฤฑnacaฤŸฤฑnฤฑ gรถreceksiniz. diff --git a/docs/tr/docs/tutorial/path-operation-configuration.md b/docs/tr/docs/tutorial/path-operation-configuration.md new file mode 100644 index 0000000000..610b863a4a --- /dev/null +++ b/docs/tr/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# Path Operation Yapฤฑlandฤฑrmasฤฑ { #path-operation-configuration } + +Onu yapฤฑlandฤฑrmak iรงin *path operation decorator*โ€™ฤฑnฤฑza geรงebileceฤŸiniz รงeลŸitli parametreler vardฤฑr. + +/// warning | Uyarฤฑ + +Bu parametrelerin *path operation function*โ€™ฤฑnฤฑza deฤŸil, doฤŸrudan *path operation decorator*โ€™ฤฑna verildiฤŸine dikkat edin. + +/// + +## Response Status Code { #response-status-code } + +*Path operation*โ€™ฤฑnฤฑzฤฑn responseโ€™unda kullanฤฑlacak (HTTP) `status_code`โ€™u tanฤฑmlayabilirsiniz. + +`404` gibi `int` kodu doฤŸrudan verebilirsiniz. + +Ancak her sayฤฑsal kodun ne iลŸe yaradฤฑฤŸฤฑnฤฑ hatฤฑrlamฤฑyorsanฤฑz, `status` iรงindeki kฤฑsayol sabitlerini kullanabilirsiniz: + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +Bu status code responseโ€™da kullanฤฑlacak ve OpenAPI ลŸemasฤฑna eklenecektir. + +/// note | Teknik Detaylar + +`from starlette import status` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak iลŸinizi kolaylaลŸtฤฑrmak iรงin `starlette.status`โ€™u `fastapi.status` olarak da sunar. Ancak kaynaฤŸฤฑ doฤŸrudan Starletteโ€™tir. + +/// + +## Tags { #tags } + +*Path operation*โ€™ฤฑnฤฑza tag ekleyebilirsiniz; `tags` parametresine `str` รถฤŸelerinden oluลŸan bir `list` verin (genellikle tek bir `str`): + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +Bunlar OpenAPI ลŸemasฤฑna eklenecek ve otomatik dokรผmantasyon arayรผzleri tarafฤฑndan kullanฤฑlacaktฤฑr: + + + +### Enum ile Tags { #tags-with-enums } + +Bรผyรผk bir uygulamanฤฑz varsa, zamanla **birden fazla tag** birikebilir ve iliลŸkili *path operation*โ€™lar iรงin her zaman **aynฤฑ tag**โ€™i kullandฤฑฤŸฤฑnฤฑzdan emin olmak isteyebilirsiniz. + +Bu durumlarda tagโ€™leri bir `Enum` iรงinde tutmak mantฤฑklฤฑ olabilir. + +**FastAPI** bunu dรผz stringโ€™lerde olduฤŸu gibi aynฤฑ ลŸekilde destekler: + +{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} + +## ร–zet ve aรงฤฑklama { #summary-and-description } + +Bir `summary` ve `description` ekleyebilirsiniz: + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} + +## Docstringโ€™den Description { #description-from-docstring } + +Aรงฤฑklamalar genelde uzun olur ve birden fazla satฤฑra yayฤฑlฤฑr; bu yรผzden *path operation* aรงฤฑklamasฤฑnฤฑ, fonksiyonun iรงinde docstring olarak tanฤฑmlayabilirsiniz; **FastAPI** de onu buradan okur. + +Docstring iรงinde Markdown yazabilirsiniz; doฤŸru ลŸekilde yorumlanฤฑr ve gรถsterilir (docstring girintisi dikkate alฤฑnarak). + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +Interactive docsโ€™ta ลŸรถyle kullanฤฑlacaktฤฑr: + + + +## Response description { #response-description } + +`response_description` parametresi ile response aรงฤฑklamasฤฑnฤฑ belirtebilirsiniz: + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} + +/// info | Bilgi + +`response_description` รถzellikle responseโ€™u ifade eder; `description` ise genel olarak *path operation*โ€™ฤฑ ifade eder. + +/// + +/// check | Ek bilgi + +OpenAPI, her *path operation* iรงin bir response description zorunlu kฤฑlar. + +Bu yรผzden siz saฤŸlamazsanฤฑz, **FastAPI** otomatik olarak "Successful response" รผretir. + +/// + + + +## Bir *path operation*โ€™ฤฑ Deprecate Etmek { #deprecate-a-path-operation } + +Bir *path operation*โ€™ฤฑ kaldฤฑrmadan, deprecated olarak iลŸaretlemeniz gerekiyorsa `deprecated` parametresini verin: + +{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} + +Interactive docsโ€™ta deprecated olduฤŸu net ลŸekilde iลŸaretlenecektir: + + + +Deprecated olan ve olmayan *path operation*โ€™larฤฑn nasฤฑl gรถrรผndรผฤŸรผne bakฤฑn: + + + +## ร–zet { #recap } + +*Path operation*โ€™larฤฑnฤฑzฤฑ, *path operation decorator*โ€™larฤฑna parametre geรงirerek kolayca yapฤฑlandฤฑrabilir ve metadata ekleyebilirsiniz. diff --git a/docs/tr/docs/tutorial/path-params-numeric-validations.md b/docs/tr/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 0000000000..e0118d71da --- /dev/null +++ b/docs/tr/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,154 @@ +# Path Parametreleri ve Sayฤฑsal DoฤŸrulamalar { #path-parameters-and-numeric-validations } + +`Query` ile query parametreleri iรงin daha fazla doฤŸrulama ve metadata tanฤฑmlayabildiฤŸiniz gibi, `Path` ile de path parametreleri iรงin aynฤฑ tรผr doฤŸrulama ve metadata tanฤฑmlayabilirsiniz. + +## `Path`'i ฤฐรงe Aktarฤฑn { #import-path } + +ร–nce `fastapi` iรงinden `Path`'i ve `Annotated`'ฤฑ iรงe aktarฤฑn: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// info | Bilgi + +FastAPI, 0.95.0 sรผrรผmรผnde `Annotated` desteฤŸini ekledi (ve bunu รถnermeye baลŸladฤฑ). + +Daha eski bir sรผrรผm kullanฤฑyorsanฤฑz, `Annotated` kullanmaya รงalฤฑลŸtฤฑฤŸฤฑnฤฑzda hata alฤฑrsฤฑnฤฑz. + +`Annotated` kullanmadan รถnce mutlaka FastAPI sรผrรผmรผnรผ en az 0.95.1 olacak ลŸekilde [FastAPI sรผrรผmรผnรผ yรผkseltin](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}. + +/// + +## Metadata Tanฤฑmlayฤฑn { #declare-metadata } + +`Query` iรงin geรงerli olan parametrelerin aynฤฑsฤฑnฤฑ tanฤฑmlayabilirsiniz. + +ร–rneฤŸin, `item_id` path parametresi iรงin bir `title` metadata deฤŸeri tanฤฑmlamak isterseniz ลŸunu yazabilirsiniz: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | Not + +Bir path parametresi her zaman zorunludur, รงรผnkรผ path'in bir parรงasฤฑ olmak zorundadฤฑr. `None` ile tanฤฑmlasanฤฑz veya bir varsayฤฑlan deฤŸer verseniz bile bu hiรงbir ลŸeyi deฤŸiลŸtirmez; yine her zaman zorunlu olur. + +/// + +## Parametreleri ฤฐhtiyacฤฑnฤฑza Gรถre Sฤฑralayฤฑn { #order-the-parameters-as-you-need } + +/// tip | ฤฐpucu + +`Annotated` kullanฤฑyorsanฤฑz, bu muhtemelen o kadar รถnemli ya da gerekli deฤŸildir. + +/// + +Diyelim ki query parametresi `q`'yu zorunlu bir `str` olarak tanฤฑmlamak istiyorsunuz. + +Ayrฤฑca bu parametre iรงin baลŸka bir ลŸey tanฤฑmlamanฤฑz gerekmiyor; dolayฤฑsฤฑyla `Query` kullanmanฤฑza da aslฤฑnda gerek yok. + +Ancak `item_id` path parametresi iรงin yine de `Path` kullanmanฤฑz gerekiyor. Ve bir sebepten `Annotated` kullanmak istemiyorsunuz. + +Python, "default" deฤŸeri olan bir parametreyi, "default" deฤŸeri olmayan bir parametreden รถnce yazarsanฤฑz ลŸikayet eder. + +Ama bunlarฤฑn sฤฑrasฤฑnฤฑ deฤŸiลŸtirebilir ve default deฤŸeri olmayan parametreyi (query parametresi `q`) en baลŸa koyabilirsiniz. + +Bu **FastAPI** iรงin รถnemli deฤŸildir. FastAPI parametreleri isimlerine, tiplerine ve default tanฤฑmlarฤฑna (`Query`, `Path`, vb.) gรถre tespit eder; sฤฑrayla ilgilenmez. + +Dolayฤฑsฤฑyla fonksiyonunuzu ลŸรถyle tanฤฑmlayabilirsiniz: + +{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} + +Ancak ลŸunu unutmayฤฑn: `Annotated` kullanฤฑrsanฤฑz bu problem olmaz; รงรผnkรผ `Query()` veya `Path()` iรงin fonksiyon parametresi default deฤŸerlerini kullanmฤฑyorsunuz. + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} + +## Parametreleri ฤฐhtiyacฤฑnฤฑza Gรถre Sฤฑralayฤฑn: Kรผรงรผk Hileler { #order-the-parameters-as-you-need-tricks } + +/// tip | ฤฐpucu + +`Annotated` kullanฤฑyorsanฤฑz, bu muhtemelen o kadar รถnemli ya da gerekli deฤŸildir. + +/// + +ฤฐลŸte bazen iลŸe yarayan **kรผรงรผk bir hile**; ama รงok sฤฑk ihtiyacฤฑnฤฑz olmayacak. + +ลžunlarฤฑ yapmak istiyorsanฤฑz: + +* `q` query parametresini `Query` kullanmadan ve herhangi bir default deฤŸer vermeden tanฤฑmlamak +* `item_id` path parametresini `Path` kullanarak tanฤฑmlamak +* bunlarฤฑ farklฤฑ bir sฤฑrada yazmak +* `Annotated` kullanmamak + +...Python bunun iรงin kรผรงรผk, รถzel bir sรถzdizimi sunar. + +Fonksiyonun ilk parametresi olarak `*` geรงin. + +Python bu `*` ile bir ลŸey yapmaz; ama bundan sonraki tรผm parametrelerin keyword argument (anahtar-deฤŸer รงiftleri) olarak รงaฤŸrฤฑlmasฤฑ gerektiฤŸini bilir; buna kwargs da denir. Default deฤŸerleri olmasa bile. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} + +### `Annotated` ile Daha ฤฐyi { #better-with-annotated } + +ลžunu da unutmayฤฑn: `Annotated` kullanฤฑrsanฤฑz, fonksiyon parametresi default deฤŸerlerini kullanmadฤฑฤŸฤฑnฤฑz iรงin bu sorun ortaya รงฤฑkmaz ve muhtemelen `*` kullanmanฤฑz da gerekmez. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} + +## Sayฤฑ DoฤŸrulamalarฤฑ: Bรผyรผk EลŸit { #number-validations-greater-than-or-equal } + +`Query` ve `Path` (ve ileride gรถreceฤŸiniz diฤŸerleri) ile sayฤฑ kฤฑsฤฑtlarฤฑ tanฤฑmlayabilirsiniz. + +Burada `ge=1` ile, `item_id` deฤŸerinin `1`'den "`g`reater than or `e`qual" olacak ลŸekilde bir tam sayฤฑ olmasฤฑ gerekir. + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} + +## Sayฤฑ DoฤŸrulamalarฤฑ: Bรผyรผk ve Kรผรงรผk EลŸit { #number-validations-greater-than-and-less-than-or-equal } + +Aynฤฑsฤฑ ลŸunlar iรงin de geรงerlidir: + +* `gt`: `g`reater `t`han +* `le`: `l`ess than or `e`qual + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} + +## Sayฤฑ DoฤŸrulamalarฤฑ: `float` DeฤŸerler, Bรผyรผk ve Kรผรงรผk { #number-validations-floats-greater-than-and-less-than } + +Sayฤฑ doฤŸrulamalarฤฑ `float` deฤŸerler iรงin de รงalฤฑลŸฤฑr. + +Burada gt tanฤฑmlayabilmek (sadece ge deฤŸil) รถnemli hale gelir. ร‡รผnkรผ รถrneฤŸin bir deฤŸerin `0`'dan bรผyรผk olmasฤฑnฤฑ isteyebilirsiniz; `1`'den kรผรงรผk olsa bile. + +Bu durumda `0.5` geรงerli bir deฤŸer olur. Ancak `0.0` veya `0` geรงerli olmaz. + +Aynฤฑsฤฑ lt iรงin de geรงerlidir. + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} + +## ร–zet { #recap } + +`Query`, `Path` (ve henรผz gรถrmedikleriniz) ile metadata ve string doฤŸrulamalarฤฑnฤฑ, [Query Parametreleri ve String DoฤŸrulamalar](query-params-str-validations.md){.internal-link target=_blank} bรถlรผmรผndekiyle aynฤฑ ลŸekilde tanฤฑmlayabilirsiniz. + +Ayrฤฑca sayฤฑsal doฤŸrulamalar da tanฤฑmlayabilirsiniz: + +* `gt`: `g`reater `t`han +* `ge`: `g`reater than or `e`qual +* `lt`: `l`ess `t`han +* `le`: `l`ess than or `e`qual + +/// info | Bilgi + +`Query`, `Path` ve ileride gรถreceฤŸiniz diฤŸer class'lar ortak bir `Param` class'ฤฑnฤฑn alt class'larฤฑdฤฑr. + +Hepsi, gรถrdรผฤŸรผnรผz ek doฤŸrulama ve metadata parametrelerini paylaลŸฤฑr. + +/// + +/// note | Teknik Detaylar + +`Query`, `Path` ve diฤŸerlerini `fastapi` iรงinden import ettiฤŸinizde, bunlar aslฤฑnda birer fonksiyondur. + +ร‡aฤŸrฤฑldฤฑklarฤฑnda, aynฤฑ isme sahip class'larฤฑn instance'larฤฑnฤฑ dรถndรผrรผrler. + +Yani `Query`'yi import edersiniz; bu bir fonksiyondur. Onu รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑzda, yine `Query` adlฤฑ bir class'ฤฑn instance'ฤฑnฤฑ dรถndรผrรผr. + +Bu fonksiyonlar (class'larฤฑ doฤŸrudan kullanmak yerine) editรถrรผnรผzรผn type'larฤฑyla ilgili hata iลŸaretlememesi iรงin vardฤฑr. + +Bu sayede, bu hatalarฤฑ yok saymak รผzere รถzel ayarlar eklemeden normal editรถrรผnรผzรผ ve coding araรงlarฤฑnฤฑzฤฑ kullanabilirsiniz. + +/// diff --git a/docs/tr/docs/tutorial/query-param-models.md b/docs/tr/docs/tutorial/query-param-models.md new file mode 100644 index 0000000000..75139a6777 --- /dev/null +++ b/docs/tr/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Query Parameter Modelleri { #query-parameter-models } + +Birbirleriyle iliลŸkili bir **query parameter** grubunuz varsa, bunlarฤฑ tanฤฑmlamak iรงin bir **Pydantic model** oluลŸturabilirsiniz. + +Bรถylece **modeli yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tรผm parametreler iรงin validation (doฤŸrulama) ile metadataโ€™yฤฑ tek seferde tanฤฑmlayabilirsiniz. ๐Ÿ˜Ž + +/// note | Not + +Bu รถzellik FastAPI `0.115.0` sรผrรผmรผnden beri desteklenmektedir. ๐Ÿค“ + +/// + +## Pydantic Model ile Query Parameters { #query-parameters-with-a-pydantic-model } + +ฤฐhtiyacฤฑnฤฑz olan **query parameter**โ€™larฤฑ bir **Pydantic model** iรงinde tanฤฑmlayฤฑn, ardฤฑndan parametreyi `Query` olarak belirtin: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI**, requestโ€™teki **query parameter**โ€™lardan **her field** iรงin veriyi **extract** eder ve tanฤฑmladฤฑฤŸฤฑnฤฑz Pydantic modelโ€™i size verir. + +## Dokรผmanlarฤฑ Kontrol Edin { #check-the-docs } + +Query parameterโ€™larฤฑ `/docs` altฤฑndaki dokรผmantasyon arayรผzรผnde gรถrebilirsiniz: + +
+ +
+ +## Ek Query Parameter'larฤฑ Yasaklayฤฑn { #forbid-extra-query-parameters } + +Bazฤฑ รถzel kullanฤฑm senaryolarฤฑnda (muhtemelen รงok yaygฤฑn deฤŸil), almak istediฤŸiniz query parameterโ€™larฤฑ **kฤฑsฤฑtlamak** isteyebilirsiniz. + +Pydanticโ€™in model konfigรผrasyonunu kullanarak `extra` fieldโ€™larฤฑ `forbid` edebilirsiniz: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Bir client, **query parameter**โ€™larda **ek (extra)** veri gรถndermeye รงalฤฑลŸฤฑrsa, **error** response alฤฑr. + +ร–rneฤŸin client, deฤŸeri `plumbus` olan bir `tool` query parameterโ€™ฤฑ gรถndermeye รงalฤฑลŸฤฑrsa: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +`tool` query parameterโ€™ฤฑna izin verilmediฤŸini sรถyleyen bir **error** response alฤฑr: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## ร–zet { #summary } + +**FastAPI** iรงinde **query parameter**โ€™larฤฑ tanฤฑmlamak iรงin **Pydantic model**โ€™leri kullanabilirsiniz. ๐Ÿ˜Ž + +/// tip | ฤฐpucu + +Spoiler: cookie ve headerโ€™larฤฑ tanฤฑmlamak iรงin de Pydantic modelโ€™leri kullanabilirsiniz; ancak bunu tutorialโ€™ฤฑn ilerleyen bรถlรผmlerinde gรถreceksiniz. ๐Ÿคซ + +/// diff --git a/docs/tr/docs/tutorial/query-params-str-validations.md b/docs/tr/docs/tutorial/query-params-str-validations.md new file mode 100644 index 0000000000..18f0249e54 --- /dev/null +++ b/docs/tr/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,473 @@ +# Query Parametreleri ve String DoฤŸrulamalarฤฑ { #query-parameters-and-string-validations } + +**FastAPI**, parametreleriniz iรงin ek bilgi ve doฤŸrulamalar (validation) tanฤฑmlamanฤฑza izin verir. + +ร–rnek olarak ลŸu uygulamayฤฑ ele alalฤฑm: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +Query parametresi `q`, `str | None` tipindedir. Yani tipi `str`โ€™dir ama `None` da olabilir. Nitekim varsayฤฑlan deฤŸer `None` olduฤŸu iรงin FastAPI bunun zorunlu olmadฤฑฤŸฤฑnฤฑ anlar. + +/// note | Not + +FastAPI, `q`โ€™nun zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` varsayฤฑlan deฤŸerinden anlar. + +`str | None` kullanmak, editรถrรผnรผzรผn daha iyi destek vermesini ve hatalarฤฑ yakalamasฤฑnฤฑ saฤŸlar. + +/// + +## Ek doฤŸrulama { #additional-validation } + +`q` opsiyonel olsa bile, verildiฤŸi durumda **uzunluฤŸunun 50 karakteri geรงmemesini** zorlayacaฤŸฤฑz. + +### `Query` ve `Annotated` import edin { #import-query-and-annotated } + +Bunu yapmak iรงin รถnce ลŸunlarฤฑ import edin: + +* `fastapi` iรงinden `Query` +* `typing` iรงinden `Annotated` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | Bilgi + +FastAPI, 0.95.0 sรผrรผmรผnde `Annotated` desteฤŸini ekledi (ve รถnermeye baลŸladฤฑ). + +Daha eski bir sรผrรผm kullanฤฑyorsanฤฑz `Annotated` kullanmaya รงalฤฑลŸฤฑrken hata alฤฑrsฤฑnฤฑz. + +`Annotated` kullanmadan รถnce FastAPI sรผrรผmรผnรผ en az 0.95.1โ€™e yรผkseltmek iรงin [FastAPI sรผrรผmรผnรผ yรผkseltin](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}. + +/// + +## `q` parametresinin tipinde `Annotated` kullanฤฑn { #use-annotated-in-the-type-for-the-q-parameter } + +[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} iรงinde `Annotated` ile parametrelerinize metadata ekleyebileceฤŸinizi sรถylemiลŸtim, hatฤฑrlฤฑyor musunuz? + +ลžimdi bunu FastAPI ile kullanmanฤฑn zamanฤฑ. ๐Ÿš€ + +ลžu tip anotasyonuna sahiptik: + +//// tab | Python 3.10+ + +```Python +q: str | None = None +``` + +//// + +//// tab | Python 3.9+ + +```Python +q: Union[str, None] = None +``` + +//// + +ลžimdi bunu `Annotated` ile saracaฤŸฤฑz; ลŸรถyle olacak: + +//// tab | Python 3.10+ + +```Python +q: Annotated[str | None] = None +``` + +//// + +//// tab | Python 3.9+ + +```Python +q: Annotated[Union[str, None]] = None +``` + +//// + +Bu iki sรผrรผm de aynฤฑ anlama gelir: `q`, `str` veya `None` olabilen bir parametredir ve varsayฤฑlan olarak `None`โ€™dฤฑr. + +ลžimdi iลŸin eฤŸlenceli kฤฑsmฤฑna geรงelim. ๐ŸŽ‰ + +## `q` parametresindeki `Annotated` iรงine `Query` ekleyin { #add-query-to-annotated-in-the-q-parameter } + +Artฤฑk ek bilgi (bu durumda ek doฤŸrulama) koyabildiฤŸimiz bir `Annotated`โ€™ฤฑmฤฑz olduฤŸuna gรถre, `Annotated` iรงine `Query` ekleyin ve `max_length` parametresini `50` olarak ayarlayฤฑn: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +Varsayฤฑlan deฤŸerin hรขlรข `None` olduฤŸuna dikkat edin; yani parametre hรขlรข opsiyonel. + +Ama ลŸimdi `Annotated` iรงinde `Query(max_length=50)` kullanarak FastAPIโ€™ye bu deฤŸer iรงin **ek doฤŸrulama** istediฤŸimizi sรถylรผyoruz: en fazla 50 karakter. ๐Ÿ˜Ž + +/// tip | ฤฐpucu + +Burada `Query()` kullanฤฑyoruz รงรผnkรผ bu bir **query parametresi**. ฤฐleride `Path()`, `Body()`, `Header()` ve `Cookie()` gibi, `Query()` ile aynฤฑ argรผmanlarฤฑ kabul eden diฤŸerlerini de gรถreceฤŸiz. + +/// + +FastAPI artฤฑk ลŸunlarฤฑ yapacak: + +* Verinin uzunluฤŸunun en fazla 50 karakter olduฤŸundan emin olacak ลŸekilde **doฤŸrulayacak** +* Veri geรงerli deฤŸilse client iรงin **net bir hata** gรถsterecek +* Parametreyi OpenAPI ลŸemasฤฑndaki *path operation* iรงinde **dokรผmante edecek** (dolayฤฑsฤฑyla **otomatik dokรผmantasyon arayรผzรผnde** gรถrรผnecek) + +## Alternatif (eski): Varsayฤฑlan deฤŸer olarak `Query` { #alternative-old-query-as-the-default-value } + +FastAPIโ€™nin รถnceki sรผrรผmlerinde (0.95.0 รถncesi) `Query`โ€™yi `Annotated` iรงine koymak yerine, parametrenizin varsayฤฑlan deฤŸeri olarak kullanmanฤฑz gerekiyordu. Etrafta bu ลŸekilde yazฤฑlmฤฑลŸ kod gรถrme ihtimaliniz yรผksek; bu yรผzden aรงฤฑklayalฤฑm. + +/// tip | ฤฐpucu + +Yeni kodlarda ve mรผmkรผn olduฤŸunda, yukarฤฑda anlatฤฑldฤฑฤŸฤฑ gibi `Annotated` kullanฤฑn. Birden fazla avantajฤฑ vardฤฑr (aลŸaฤŸฤฑda anlatฤฑlฤฑyor) ve dezavantajฤฑ yoktur. ๐Ÿฐ + +/// + +Fonksiyon parametresinin varsayฤฑlan deฤŸeri olarak `Query()` kullanฤฑp `max_length` parametresini 50 yapmak ลŸรถyle olurdu: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +Bu senaryoda (`Annotated` kullanmadฤฑฤŸฤฑmฤฑz iรงin) fonksiyondaki `None` varsayฤฑlan deฤŸerini `Query()` ile deฤŸiลŸtirmemiz gerekiyor. Bu durumda varsayฤฑlan deฤŸeri `Query(default=None)` ile vermeliyiz; bu, (en azฤฑndan FastAPI aรงฤฑsฤฑndan) aynฤฑ varsayฤฑlan deฤŸeri tanฤฑmlama amacฤฑna hizmet eder. + +Yani: + +```Python +q: str | None = Query(default=None) +``` + +...parametreyi `None` varsayฤฑlan deฤŸeriyle opsiyonel yapar; ลŸununla aynฤฑ: + +```Python +q: str | None = None +``` + +Ancak `Query` sรผrรผmรผ bunun bir query parametresi olduฤŸunu aรงฤฑkรงa belirtir. + +Sonrasฤฑnda `Query`โ€™ye daha fazla parametre geรงebiliriz. Bu รถrnekte stringโ€™ler iรงin geรงerli olan `max_length`: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +Bu, veriyi doฤŸrular, veri geรงerli deฤŸilse net bir hata gรถsterir ve parametreyi OpenAPI ลŸemasฤฑndaki *path operation* iรงinde dokรผmante eder. + +### Varsayฤฑlan deฤŸer olarak `Query` veya `Annotated` iรงinde `Query` { #query-as-the-default-value-or-in-annotated } + +`Annotated` iรงinde `Query` kullanฤฑrken `Query` iรงin `default` parametresini kullanamayacaฤŸฤฑnฤฑzฤฑ unutmayฤฑn. + +Bunun yerine fonksiyon parametresinin gerรงek varsayฤฑlan deฤŸerini kullanฤฑn. Aksi halde tutarsฤฑz olur. + +ร–rneฤŸin ลŸu kullanฤฑm izinli deฤŸildir: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...รงรผnkรผ varsayฤฑlan deฤŸerin `"rick"` mi `"morty"` mi olmasฤฑ gerektiฤŸi belli deฤŸildir. + +Bu nedenle (tercihen) ลŸรถyle kullanฤฑrsฤฑnฤฑz: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...veya eski kod tabanlarฤฑnda ลŸuna rastlarsฤฑnฤฑz: + +```Python +q: str = Query(default="rick") +``` + +### `Annotated`โ€™ฤฑn avantajlarฤฑ { #advantages-of-annotated } + +Fonksiyon parametrelerindeki varsayฤฑlan deฤŸer stiline gรถre **`Annotated` kullanmanฤฑz รถnerilir**; birden fazla nedenle **daha iyidir**. ๐Ÿค“ + +**Fonksiyon parametresinin** **varsayฤฑlan** deฤŸeri, **gerรงek varsayฤฑlan** deฤŸerdir; bu genel olarak Python aรงฤฑsฤฑndan daha sezgiseldir. ๐Ÿ˜Œ + +Aynฤฑ fonksiyonu FastAPI olmadan **baลŸka yerlerde** de **รงaฤŸฤฑrabilirsiniz** ve **beklendiฤŸi gibi รงalฤฑลŸฤฑr**. EฤŸer **zorunlu** bir parametre varsa (varsayฤฑlan deฤŸer yoksa) editรถrรผnรผz hata ile bunu belirtir; ayrฤฑca gerekli parametreyi vermeden รงalฤฑลŸtฤฑrฤฑrsanฤฑz **Python** da ลŸikayet eder. + +`Annotated` kullanmayฤฑp bunun yerine **(eski) varsayฤฑlan deฤŸer stilini** kullanฤฑrsanฤฑz, o fonksiyonu FastAPI olmadan **baลŸka yerlerde** รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑzda doฤŸru รงalฤฑลŸmasฤฑ iรงin argรผmanlarฤฑ geรงmeniz gerektiฤŸini **hatฤฑrlamak** zorunda kalฤฑrsฤฑnฤฑz; yoksa deฤŸerler beklediฤŸinizden farklฤฑ olur (รถr. `str` yerine `QueryInfo` veya benzeri). รœstelik editรถrรผnรผz de ลŸikayet etmez ve Python da fonksiyonu รงalฤฑลŸtฤฑrฤฑrken ลŸikayet etmez; ancak iรงerideki operasyonlar hata verince ortaya รงฤฑkar. + +`Annotated` birden fazla metadata anotasyonu alabildiฤŸi iรงin, artฤฑk aynฤฑ fonksiyonu Typer gibi baลŸka araรงlarla da kullanabilirsiniz. ๐Ÿš€ + +## Daha fazla doฤŸrulama ekleyin { #add-more-validations } + +`min_length` parametresini de ekleyebilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## Regular expression ekleyin { #add-regular-expressions } + +Parametrenin eลŸleลŸmesi gereken bir `pattern` regular expression tanฤฑmlayabilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +Bu รถzel regular expression patternโ€™i, gelen parametre deฤŸerinin ลŸunlarฤฑ saฤŸladฤฑฤŸฤฑnฤฑ kontrol eder: + +* `^`: AลŸaฤŸฤฑdaki karakterlerle baลŸlar; รถncesinde karakter yoktur. +* `fixedquery`: Tam olarak `fixedquery` deฤŸerine sahiptir. +* `$`: Orada biter; `fixedquery` sonrasฤฑnda baลŸka karakter yoktur. + +Bu **"regular expression"** konularฤฑ gรถzรผnรผzรผ korkutuyorsa sorun deฤŸil. Birรงok kiลŸi iรงin zor bir konudur. Regular expressionโ€™lara ihtiyaรง duymadan da pek รงok ลŸey yapabilirsiniz. + +Artฤฑk ihtiyaรง duyduฤŸunuzda **FastAPI** iรงinde kullanabileceฤŸinizi biliyorsunuz. + +## Varsayฤฑlan deฤŸerler { #default-values } + +Elbette `None` dฤฑลŸฤฑnda varsayฤฑlan deฤŸerler de kullanabilirsiniz. + +ร–rneฤŸin `q` query parametresi iรงin `min_length` deฤŸerini `3` yapmak ve varsayฤฑlan deฤŸer olarak `"fixedquery"` vermek istediฤŸinizi dรผลŸรผnelim: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} + +/// note | Not + +`None` dahil herhangi bir tipte varsayฤฑlan deฤŸere sahip olmak, parametreyi opsiyonel (zorunlu deฤŸil) yapar. + +/// + +## Zorunlu parametreler { #required-parameters } + +Daha fazla doฤŸrulama veya metadata tanฤฑmlamamฤฑz gerekmiyorsa, `q` query parametresini yalnฤฑzca varsayฤฑlan deฤŸer tanฤฑmlamayarak zorunlu yapabiliriz: + +```Python +q: str +``` + +ลŸunun yerine: + +```Python +q: str | None = None +``` + +Ancak biz artฤฑk `Query` ile tanฤฑmlฤฑyoruz; รถrneฤŸin ลŸรถyle: + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +Dolayฤฑsฤฑyla `Query` kullanฤฑrken bir deฤŸeri zorunlu yapmak istediฤŸinizde, varsayฤฑlan deฤŸer tanฤฑmlamamanฤฑz yeterlidir: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} + +### Zorunlu ama `None` olabilir { #required-can-be-none } + +Bir parametrenin `None` kabul edebileceฤŸini sรถyleyip yine de zorunlu olmasฤฑnฤฑ saฤŸlayabilirsiniz. Bu, clientโ€™larฤฑn deฤŸer gรถndermesini zorunlu kฤฑlar; deฤŸer `None` olsa bile. + +Bunu yapmak iรงin `None`โ€™ฤฑ geรงerli bir tip olarak tanฤฑmlayฤฑn ama varsayฤฑlan deฤŸer vermeyin: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## Query parametresi listesi / birden fazla deฤŸer { #query-parameter-list-multiple-values } + +Bir query parametresini `Query` ile aรงฤฑkรงa tanฤฑmladฤฑฤŸฤฑnฤฑzda, bir deฤŸer listesi alacak ลŸekilde (baลŸka bir deyiลŸle, birden fazla deฤŸer alacak ลŸekilde) de tanฤฑmlayabilirsiniz. + +ร–rneฤŸin URLโ€™de `q` query parametresinin birden fazla kez gรถrรผnebilmesini istiyorsanฤฑz ลŸรถyle yazabilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +Sonra ลŸu URL ile: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +*path operation function* iรงinde, *function parameter* olan `q` parametresinde, birden fazla `q` *query parameters* deฤŸerini (`foo` ve `bar`) bir Python `list`โ€™i olarak alฤฑrsฤฑnฤฑz. + +Dolayฤฑsฤฑyla bu URLโ€™ye response ลŸรถyle olur: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | ฤฐpucu + +Yukarฤฑdaki รถrnekte olduฤŸu gibi tipi `list` olan bir query parametresi tanฤฑmlamak iรงin `Query`โ€™yi aรงฤฑkรงa kullanmanฤฑz gerekir; aksi halde request body olarak yorumlanฤฑr. + +/// + +EtkileลŸimli API dokรผmanlarฤฑ da buna gรถre gรผncellenir ve birden fazla deฤŸere izin verir: + + + +### Varsayฤฑlanlarla query parametresi listesi / birden fazla deฤŸer { #query-parameter-list-multiple-values-with-defaults } + +Hiรง deฤŸer verilmezse varsayฤฑlan bir `list` de tanฤฑmlayabilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} + +ลžu adrese giderseniz: + +``` +http://localhost:8000/items/ +``` + +`q`โ€™nun varsayฤฑlanฤฑ `["foo", "bar"]` olur ve response ลŸรถyle olur: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### Sadece `list` kullanmak { #using-just-list } + +`list[str]` yerine doฤŸrudan `list` de kullanabilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} + +/// note | Not + +Bu durumda FastAPI, listenin iรงeriฤŸini kontrol etmez. + +ร–rneฤŸin `list[int]`, listenin iรงeriฤŸinin integer olduฤŸunu kontrol eder (ve dokรผmante eder). Ancak tek baลŸฤฑna `list` bunu yapmaz. + +/// + +## Daha fazla metadata tanฤฑmlayฤฑn { #declare-more-metadata } + +Parametre hakkฤฑnda daha fazla bilgi ekleyebilirsiniz. + +Bu bilgiler oluลŸturulan OpenAPIโ€™a dahil edilir ve dokรผmantasyon arayรผzleri ile harici araรงlar tarafฤฑndan kullanฤฑlฤฑr. + +/// note | Not + +Farklฤฑ araรงlarฤฑn OpenAPI desteฤŸi farklฤฑ seviyelerde olabilir. + +Bazฤฑlarฤฑ tanฤฑmladฤฑฤŸฤฑnฤฑz ek bilgilerin hepsini gรถstermeyebilir; ancak รงoฤŸu durumda eksik รถzellik geliลŸtirme planฤฑndadฤฑr. + +/// + +Bir `title` ekleyebilirsiniz: + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +Ve bir `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## Alias parametreleri { #alias-parameters } + +Parametrenin adฤฑnฤฑn `item-query` olmasฤฑnฤฑ istediฤŸinizi dรผลŸรผnรผn. + +ร–rneฤŸin: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +Ancak `item-query` geรงerli bir Python deฤŸiลŸken adฤฑ deฤŸildir. + +En yakฤฑn seรงenek `item_query` olur. + +Ama sizin hรขlรข tam olarak `item-query` olmasฤฑna ihtiyacฤฑnฤฑz var... + +O zaman bir `alias` tanฤฑmlayabilirsiniz; bu alias, parametre deฤŸerini bulmak iรงin kullanฤฑlacaktฤฑr: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## Parametreleri deprecated yapmak { #deprecating-parameters } + +Diyelim ki artฤฑk bu parametreyi istemiyorsunuz. + +Bazฤฑ clientโ€™lar hรขlรข kullandฤฑฤŸฤฑ iรงin bir sรผre tutmanฤฑz gerekiyor, ama dokรผmanlarฤฑn bunu aรงฤฑkรงa deprecated olarak gรถstermesini istiyorsunuz. + +O zaman `Query`โ€™ye `deprecated=True` parametresini geรงin: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +Dokรผmanlarda ลŸรถyle gรถrรผnรผr: + + + +## Parametreleri OpenAPIโ€™dan hariรง tutun { #exclude-parameters-from-openapi } + +OluลŸturulan OpenAPI ลŸemasฤฑndan (dolayฤฑsฤฑyla otomatik dokรผmantasyon sistemlerinden) bir query parametresini hariรง tutmak iรงin `Query`โ€™nin `include_in_schema` parametresini `False` yapฤฑn: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## ร–zel DoฤŸrulama { #custom-validation } + +Yukarฤฑdaki parametrelerle yapฤฑlamayan bazฤฑ **รถzel doฤŸrulama** ihtiyaรงlarฤฑnฤฑz olabilir. + +Bu durumlarda, normal doฤŸrulamadan sonra (รถr. deฤŸerin `str` olduฤŸunun doฤŸrulanmasฤฑndan sonra) uygulanacak bir **custom validator function** kullanabilirsiniz. + +Bunu, `Annotated` iรงinde Pydanticโ€™in `AfterValidator`โ€™ฤฑnฤฑ kullanarak yapabilirsiniz. + +/// tip | ฤฐpucu + +Pydanticโ€™te `BeforeValidator` ve baลŸka validatorโ€™lar da vardฤฑr. ๐Ÿค“ + +/// + +ร–rneฤŸin bu custom validator, bir item IDโ€™sinin ISBN kitap numarasฤฑ iรงin `isbn-` ile veya IMDB film URL IDโ€™si iรงin `imdb-` ile baลŸladฤฑฤŸฤฑnฤฑ kontrol eder: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | Bilgi + +Bu รถzellik Pydantic 2 ve รผzeri sรผrรผmlerde mevcuttur. ๐Ÿ˜Ž + +/// + +/// tip | ฤฐpucu + +Veritabanฤฑ veya baลŸka bir API gibi herhangi bir **harici bileลŸen** ile iletiลŸim gerektiren bir doฤŸrulama yapmanฤฑz gerekiyorsa, bunun yerine **FastAPI Dependencies** kullanmalฤฑsฤฑnฤฑz; onlarฤฑ ileride รถฤŸreneceksiniz. + +Bu custom validatorโ€™lar, requestโ€™te saฤŸlanan **yalnฤฑzca** **aynฤฑ veri** ile kontrol edilebilen ลŸeyler iรงindir. + +/// + +### O Kodu Anlamak { #understand-that-code } + +ร–nemli nokta, **`Annotated` iรงinde bir fonksiyonla birlikte `AfterValidator` kullanmak**. ฤฐsterseniz bu kฤฑsmฤฑ atlayabilirsiniz. ๐Ÿคธ + +--- + +Ama bu รถrnek kodun detaylarฤฑnฤฑ merak ediyorsanฤฑz, birkaรง ek bilgi: + +#### `value.startswith()` ile String { #string-with-value-startswith } + +Fark ettiniz mi? `value.startswith()` ile bir string, tuple alabilir ve tuple iรงindeki her deฤŸeri kontrol eder: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Rastgele Bir Item { #a-random-item } + +`data.items()` ile, her dictionary รถฤŸesi iรงin key ve value iรงeren tupleโ€™lardan oluลŸan bir iterable object elde ederiz. + +Bu iterable objectโ€™i `list(data.items())` ile dรผzgรผn bir `list`โ€™e รงeviririz. + +Ardฤฑndan `random.choice()` ile listโ€™ten **rastgele bir deฤŸer** alฤฑrฤฑz; yani `(id, name)` iรงeren bir tuple elde ederiz. ลžuna benzer: `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +Sonra tuple iรงindeki bu **iki deฤŸeri** `id` ve `name` deฤŸiลŸkenlerine **atarฤฑz**. + +Bรถylece kullanฤฑcฤฑ bir item IDโ€™si vermemiลŸ olsa bile yine de rastgele bir รถneri alฤฑr. + +...bรผtรผn bunlarฤฑ **tek bir basit satฤฑrda** yapฤฑyoruz. ๐Ÿคฏ Pythonโ€™u sevmemek elde mi? ๐Ÿ + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## ร–zet { #recap } + +Parametreleriniz iรงin ek doฤŸrulamalar ve metadata tanฤฑmlayabilirsiniz. + +Genel doฤŸrulamalar ve metadata: + +* `alias` +* `title` +* `description` +* `deprecated` + +Stringโ€™lere รถzel doฤŸrulamalar: + +* `min_length` +* `max_length` +* `pattern` + +`AfterValidator` ile custom doฤŸrulamalar. + +Bu รถrneklerde `str` deฤŸerleri iรงin doฤŸrulamanฤฑn nasฤฑl tanฤฑmlanacaฤŸฤฑnฤฑ gรถrdรผnรผz. + +Sayฤฑlar gibi diฤŸer tipler iรงin doฤŸrulamalarฤฑ nasฤฑl tanฤฑmlayacaฤŸฤฑnฤฑzฤฑ รถฤŸrenmek iรงin sonraki bรถlรผmlere geรงin. diff --git a/docs/tr/docs/tutorial/request-files.md b/docs/tr/docs/tutorial/request-files.md new file mode 100644 index 0000000000..0bbc557e01 --- /dev/null +++ b/docs/tr/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# Request Dosyalarฤฑ { #request-files } + +ฤฐstemcinin upload edeceฤŸi dosyalarฤฑ `File` kullanarak tanฤฑmlayabilirsiniz. + +/// info | Bilgi + +Upload edilen dosyalarฤฑ alabilmek iรงin รถnce `python-multipart` yรผkleyin. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, aktive ettiฤŸinizden ve ardฤฑndan paketi yรผklediฤŸinizden emin olun. ร–rneฤŸin: + +```console +$ pip install python-multipart +``` + +Bunun nedeni, upload edilen dosyalarฤฑn "form data" olarak gรถnderilmesidir. + +/// + +## `File` Import Edin { #import-file } + +`fastapi` iรงinden `File` ve `UploadFile` import edin: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} + +## `File` Parametrelerini Tanฤฑmlayฤฑn { #define-file-parameters } + +`Body` veya `Form` iรงin yaptฤฑฤŸฤฑnฤฑz gibi dosya parametreleri oluลŸturun: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} + +/// info | Bilgi + +`File`, doฤŸrudan `Form`โ€™dan tรผreyen bir sฤฑnฤฑftฤฑr. + +Ancak unutmayฤฑn: `fastapi` iรงinden `Query`, `Path`, `File` ve diฤŸerlerini import ettiฤŸinizde, bunlar aslฤฑnda รถzel sฤฑnฤฑflar dรถndรผren fonksiyonlardฤฑr. + +/// + +/// tip | ฤฐpucu + +File bodyโ€™leri tanฤฑmlamak iรงin `File` kullanmanฤฑz gerekir; aksi halde parametreler query parametreleri veya body (JSON) parametreleri olarak yorumlanฤฑr. + +/// + +Dosyalar "form data" olarak upload edilir. + +*path operation function* parametrenizin tipini `bytes` olarak tanฤฑmlarsanฤฑz, **FastAPI** dosyayฤฑ sizin iรงin okur ve iรงeriฤŸi `bytes` olarak alฤฑrsฤฑnฤฑz. + +Bunun, dosyanฤฑn tรผm iรงeriฤŸinin bellekte tutulacaฤŸฤฑ anlamฤฑna geldiฤŸini unutmayฤฑn. Kรผรงรผk dosyalar iรงin iyi รงalฤฑลŸฤฑr. + +Ancak bazฤฑ durumlarda `UploadFile` kullanmak size fayda saฤŸlayabilir. + +## `UploadFile` ile Dosya Parametreleri { #file-parameters-with-uploadfile } + +Tipi `UploadFile` olan bir dosya parametresi tanฤฑmlayฤฑn: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} + +`UploadFile` kullanmanฤฑn `bytes`โ€™a gรถre birkaรง avantajฤฑ vardฤฑr: + +* Parametrenin varsayฤฑlan deฤŸerinde `File()` kullanmak zorunda deฤŸilsiniz. +* "Spooled" bir dosya kullanฤฑr: + * Belirli bir maksimum boyuta kadar bellekte tutulan, bu limiti aลŸฤฑnca diske yazฤฑlan bir dosya. +* Bu sayede gรถrรผntรผler, videolar, bรผyรผk binaryโ€™ler vb. gibi bรผyรผk dosyalarda tรผm belleฤŸi tรผketmeden iyi รงalฤฑลŸฤฑr. +* Upload edilen dosyadan metadata alabilirsiniz. +* file-like bir `async` arayรผze sahiptir. +* `SpooledTemporaryFile` nesnesini dฤฑลŸa aรงar; bunu, file-like nesne bekleyen diฤŸer libraryโ€™lere doฤŸrudan geรงebilirsiniz. + +### `UploadFile` { #uploadfile } + +`UploadFile` ลŸu attributeโ€™lara sahiptir: + +* `filename`: Upload edilen orijinal dosya adฤฑnฤฑ iรงeren bir `str` (รถrn. `myimage.jpg`). +* `content_type`: Content typeโ€™ฤฑ (MIME type / media type) iรงeren bir `str` (รถrn. `image/jpeg`). +* `file`: Bir `SpooledTemporaryFile` (bir file-like nesne). Bu, "file-like" nesne bekleyen diฤŸer fonksiyonlara veya libraryโ€™lere doฤŸrudan verebileceฤŸiniz gerรงek Python file nesnesidir. + +`UploadFile` ลŸu `async` methodโ€™lara sahiptir. Bunlarฤฑn hepsi altta ilgili dosya methodโ€™larฤฑnฤฑ รงaฤŸฤฑrฤฑr (dahili `SpooledTemporaryFile` kullanarak). + +* `write(data)`: Dosyaya `data` (`str` veya `bytes`) yazar. +* `read(size)`: Dosyadan `size` (`int`) kadar byte/karakter okur. +* `seek(offset)`: Dosyada `offset` (`int`) byte pozisyonuna gider. + * ร–rn. `await myfile.seek(0)` dosyanฤฑn baลŸฤฑna gider. + * Bu, รถzellikle bir kez `await myfile.read()` รงalฤฑลŸtฤฑrdฤฑysanฤฑz ve sonra iรงeriฤŸi yeniden okumaya ihtiyaรง duyuyorsanฤฑz faydalฤฑdฤฑr. +* `close()`: Dosyayฤฑ kapatฤฑr. + +Bu methodโ€™larฤฑn hepsi `async` olduฤŸundan, bunlarฤฑ "await" etmeniz gerekir. + +ร–rneฤŸin, bir `async` *path operation function* iรงinde iรงeriฤŸi ลŸรถyle alabilirsiniz: + +```Python +contents = await myfile.read() +``` + +Normal bir `def` *path operation function* iรงindeyseniz `UploadFile.file`โ€™a doฤŸrudan eriลŸebilirsiniz, รถrneฤŸin: + +```Python +contents = myfile.file.read() +``` + +/// note | `async` Teknik Detaylar + +`async` methodโ€™larฤฑ kullandฤฑฤŸฤฑnฤฑzda, **FastAPI** dosya methodโ€™larฤฑnฤฑ bir threadpool iรงinde รงalฤฑลŸtฤฑrฤฑr ve bunlarฤฑ await eder. + +/// + +/// note | Starlette Teknik Detaylar + +**FastAPI**โ€™nin `UploadFile`โ€™ฤฑ doฤŸrudan **Starlette**โ€™in `UploadFile`โ€™ฤฑndan tรผretilmiลŸtir; ancak **Pydantic** ve FastAPIโ€™nin diฤŸer parรงalarฤฑyla uyumlu olmasฤฑ iรงin bazฤฑ gerekli eklemeler yapar. + +/// + +## "Form Data" Nedir { #what-is-form-data } + +HTML formlarฤฑ (`
`) veriyi serverโ€™a gรถnderirken normalde JSONโ€™dan farklฤฑ, veri iรงin "รถzel" bir encoding kullanฤฑr. + +**FastAPI**, JSON yerine bu veriyi doฤŸru yerden okuyacaฤŸฤฑndan emin olur. + +/// note | Teknik Detaylar + +Formlardan gelen veri, dosya iรงermiyorsa normalde "media type" olarak `application/x-www-form-urlencoded` ile encode edilir. + +Ancak form dosya iรงeriyorsa `multipart/form-data` olarak encode edilir. `File` kullanฤฑrsanฤฑz, **FastAPI** dosyalarฤฑ bodyโ€™nin doฤŸru kฤฑsmฤฑndan almasฤฑ gerektiฤŸini bilir. + +Bu encodingโ€™ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz MDN web dokรผmanlarฤฑndaki POST sayfasฤฑna bakฤฑn. + +/// + +/// warning | Uyarฤฑ + +Bir *path operation* iรงinde birden fazla `File` ve `Form` parametresi tanฤฑmlayabilirsiniz, ancak JSON olarak almayฤฑ beklediฤŸiniz `Body` alanlarฤฑnฤฑ ayrฤฑca tanฤฑmlayamazsฤฑnฤฑz; รงรผnkรผ request body `application/json` yerine `multipart/form-data` ile encode edilmiลŸ olur. + +Bu, **FastAPI**โ€™nin bir kฤฑsฤฑtฤฑ deฤŸildir; HTTP protocolโ€™รผnรผn bir parรงasฤฑdฤฑr. + +/// + +## Opsiyonel Dosya Upload { #optional-file-upload } + +Standart type annotationโ€™larฤฑ kullanฤฑp varsayฤฑlan deฤŸeri `None` yaparak bir dosyayฤฑ opsiyonel hale getirebilirsiniz: + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## Ek Metadata ile `UploadFile` { #uploadfile-with-additional-metadata } + +Ek metadata ayarlamak iรงin `UploadFile` ile birlikte `File()` da kullanabilirsiniz. ร–rneฤŸin: + +{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} + +## Birden Fazla Dosya Upload { #multiple-file-uploads } + +Aynฤฑ anda birden fazla dosya upload etmek mรผmkรผndรผr. + +Bu dosyalar, "form data" ile gรถnderilen aynฤฑ "form field" ile iliลŸkilendirilir. + +Bunu kullanmak iรงin `bytes` veya `UploadFile` listesini tanฤฑmlayฤฑn: + +{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} + +TanฤฑmladฤฑฤŸฤฑnฤฑz gibi, `bytes` veya `UploadFile`โ€™lardan oluลŸan bir `list` alฤฑrsฤฑnฤฑz. + +/// note | Teknik Detaylar + +`from starlette.responses import HTMLResponse` da kullanabilirsiniz. + +**FastAPI**, geliลŸtiriciye kolaylฤฑk olsun diye `starlette.responses` modรผlรผnรผ `fastapi.responses` olarak da saฤŸlar. Ancak mevcut responseโ€™larฤฑn รงoฤŸu doฤŸrudan Starletteโ€™ten gelir. + +/// + +### Ek Metadata ile Birden Fazla Dosya Upload { #multiple-file-uploads-with-additional-metadata } + +Daha รถnce olduฤŸu gibi, `UploadFile` iรงin bile ek parametreler ayarlamak amacฤฑyla `File()` kullanabilirsiniz: + +{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} + +## ร–zet { #recap } + +Requestโ€™te (form data olarak gรถnderilen) upload edilecek dosyalarฤฑ tanฤฑmlamak iรงin `File`, `bytes` ve `UploadFile` kullanฤฑn. diff --git a/docs/tr/docs/tutorial/request-form-models.md b/docs/tr/docs/tutorial/request-form-models.md new file mode 100644 index 0000000000..c35f956fce --- /dev/null +++ b/docs/tr/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Form Model'leri { #form-models } + +FastAPI'de **form field**'larฤฑnฤฑ tanฤฑmlamak iรงin **Pydantic model**'lerini kullanabilirsiniz. + +/// info | Bilgi + +Form'larฤฑ kullanmak iรงin รถnce `python-multipart`'ฤฑ yรผkleyin. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu etkinleลŸtirdiฤŸinizden ve ardฤฑndan paketi kurduฤŸunuzdan emin olun. ร–rneฤŸin: + +```console +$ pip install python-multipart +``` + +/// + +/// note | Not + +Bu รถzellik FastAPI `0.113.0` sรผrรผmรผnden itibaren desteklenmektedir. ๐Ÿค“ + +/// + +## Form'lar iรงin Pydantic Model'leri { #pydantic-models-for-forms } + +Sadece, **form field** olarak almak istediฤŸiniz alanlarla bir **Pydantic model** tanฤฑmlayฤฑn ve ardฤฑndan parametreyi `Form` olarak bildirin: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI**, request iรงindeki **form data**'dan **her bir field** iรงin veriyi **รงฤฑkarฤฑr** ve size tanฤฑmladฤฑฤŸฤฑnฤฑz Pydantic model'ini verir. + +## Dokรผmanlarฤฑ Kontrol Edin { #check-the-docs } + +Bunu `/docs` altฤฑndaki dokรผman arayรผzรผnde doฤŸrulayabilirsiniz: + +
+ +
+ +## Fazladan Form Field'larฤฑnฤฑ Yasaklayฤฑn { #forbid-extra-form-fields } + +Bazฤฑ รถzel kullanฤฑm senaryolarฤฑnda (muhtemelen รงok yaygฤฑn deฤŸildir), form field'larฤฑnฤฑ yalnฤฑzca Pydantic model'inde tanฤฑmlananlarla **sฤฑnฤฑrlamak** isteyebilirsiniz. Ve **fazladan** gelen field'larฤฑ **yasaklayabilirsiniz**. + +/// note | Not + +Bu รถzellik FastAPI `0.114.0` sรผrรผmรผnden itibaren desteklenmektedir. ๐Ÿค“ + +/// + +Herhangi bir `extra` field'ฤฑ `forbid` etmek iรงin Pydantic'in model konfigรผrasyonunu kullanabilirsiniz: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Bir client fazladan veri gรถndermeye รงalฤฑลŸฤฑrsa, bir **error** response alฤฑr. + +ร–rneฤŸin, client ลŸu form field'larฤฑnฤฑ gรถndermeye รงalฤฑลŸฤฑrsa: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +`extra` field'ฤฑnฤฑn izinli olmadฤฑฤŸฤฑnฤฑ sรถyleyen bir error response alฤฑr: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## ร–zet { #summary } + +FastAPI'de form field'larฤฑnฤฑ tanฤฑmlamak iรงin Pydantic model'lerini kullanabilirsiniz. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/request-forms-and-files.md b/docs/tr/docs/tutorial/request-forms-and-files.md new file mode 100644 index 0000000000..86d26b4989 --- /dev/null +++ b/docs/tr/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# Request Forms ve Files { #request-forms-and-files } + +`File` ve `Form` kullanarak aynฤฑ anda hem dosyalarฤฑ hem de form alanlarฤฑnฤฑ tanฤฑmlayabilirsiniz. + +/// info | Bilgi + +Yรผklenen dosyalarฤฑ ve/veya form verisini almak iรงin รถnce `python-multipart` paketini kurun. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktive ettiฤŸinizden ve ardฤฑndan paketi kurduฤŸunuzdan emin olun, รถrneฤŸin: + +```console +$ pip install python-multipart +``` + +/// + +## `File` ve `Form` Import Edin { #import-file-and-form } + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} + +## `File` ve `Form` Parametrelerini Tanฤฑmlayฤฑn { #define-file-and-form-parameters } + +Dosya ve form parametrelerini, `Body` veya `Query` iรงin yaptฤฑฤŸฤฑnฤฑz ลŸekilde oluลŸturun: + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} + +Dosyalar ve form alanlarฤฑ form data olarak upload edilir ve siz de dosyalarฤฑ ve form alanlarฤฑnฤฑ alฤฑrsฤฑnฤฑz. + +Ayrฤฑca bazฤฑ dosyalarฤฑ `bytes` olarak, bazฤฑlarฤฑnฤฑ da `UploadFile` olarak tanฤฑmlayabilirsiniz. + +/// warning | Uyarฤฑ + +Bir *path operation* iรงinde birden fazla `File` ve `Form` parametresi tanฤฑmlayabilirsiniz; ancak request'in body'si `application/json` yerine `multipart/form-data` ile encode edileceฤŸi iรงin, JSON olarak almayฤฑ beklediฤŸiniz `Body` alanlarฤฑnฤฑ aynฤฑ anda tanฤฑmlayamazsฤฑnฤฑz. + +Bu **FastAPI** kฤฑsฤฑtฤฑ deฤŸildir; HTTP protokolรผnรผn bir parรงasฤฑdฤฑr. + +/// + +## ร–zet { #recap } + +Aynฤฑ request iรงinde hem veri hem de dosya almanฤฑz gerektiฤŸinde `File` ve `Form`'u birlikte kullanฤฑn. diff --git a/docs/tr/docs/tutorial/response-model.md b/docs/tr/docs/tutorial/response-model.md new file mode 100644 index 0000000000..f1d1f7d15e --- /dev/null +++ b/docs/tr/docs/tutorial/response-model.md @@ -0,0 +1,343 @@ +# Response Model - DรถnรผลŸ Tipi { #response-model-return-type } + +*Path operation function* **dรถnรผลŸ tipini** (return type) type annotation ile belirtip response iรงin kullanฤฑlacak tipi tanฤฑmlayabilirsiniz. + +Fonksiyon **parametreleri** iรงin input dataโ€™da kullandฤฑฤŸฤฑnฤฑz **type annotations** yaklaลŸฤฑmฤฑnฤฑn aynฤฑsฤฑnฤฑ burada da kullanabilirsiniz; Pydantic modelโ€™leri, listโ€™ler, dictโ€™ler, integer, boolean gibi skaler deฤŸerler vb. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI bu dรถnรผลŸ tipini ลŸunlar iรงin kullanฤฑr: + +* Dรถnen veriyi **doฤŸrulamak** (validate). + * Veri geรงersizse (รถr. bir field eksikse), bu *sizin* uygulama kodunuzun bozuk olduฤŸu, olmasฤฑ gerekeni dรถndรผrmediฤŸi anlamฤฑna gelir; bu yรผzden yanlฤฑลŸ veri dรถndรผrmek yerine server error dรถner. Bรถylece siz ve clientโ€™larฤฑnฤฑz, beklenen veri ve veri ลŸeklinin geleceฤŸinden emin olabilirsiniz. +* OpenAPIโ€™deki *path operation* iรงine response iรงin bir **JSON Schema** eklemek. + * Bu, **otomatik dokรผmantasyon** tarafฤฑndan kullanฤฑlฤฑr. + * Ayrฤฑca otomatik client code generation araรงlarฤฑ tarafฤฑndan da kullanฤฑlฤฑr. + +Ama en รถnemlisi: + +* ร‡ฤฑktฤฑ verisini, dรถnรผลŸ tipinde tanฤฑmlฤฑ olana gรถre **sฤฑnฤฑrlar ve filtreler**. + * Bu, รถzellikle **gรผvenlik** aรงฤฑsฤฑndan รถnemlidir; aลŸaฤŸฤฑda daha fazlasฤฑnฤฑ gรถreceฤŸiz. + +## `response_model` Parametresi { #response-model-parameter } + +Bazฤฑ durumlarda, tam olarak dรถnรผลŸ tipinin sรถylediฤŸi gibi olmayan bir veriyi dรถndรผrmeniz gerekebilir ya da isteyebilirsiniz. + +ร–rneฤŸin, **bir dict** veya bir veritabanฤฑ objesi dรถndรผrmek isteyip, ama **onu bir Pydantic model olarak declare etmek** isteyebilirsiniz. Bรถylece Pydantic model, dรถndรผrdรผฤŸรผnรผz obje (รถr. dict veya veritabanฤฑ objesi) iรงin dokรผmantasyon, doฤŸrulama vb. iลŸlerin tamamฤฑnฤฑ yapar. + +EฤŸer dรถnรผลŸ tipi annotationโ€™ฤฑnฤฑ eklerseniz, araรงlar ve editรถrler (doฤŸru ลŸekilde) fonksiyonunuzun, declare ettiฤŸiniz tipten (รถr. Pydantic model) farklฤฑ bir tip (รถr. dict) dรถndรผrdรผฤŸรผnรผ sรถyleyip hata verir. + +Bu gibi durumlarda, dรถnรผลŸ tipi yerine *path operation decorator* parametresi olan `response_model`โ€™i kullanabilirsiniz. + +`response_model` parametresini herhangi bir *path operation* iรงinde kullanabilirsiniz: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* vb. + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | Not + +`response_model`โ€™in "decorator" metodunun (`get`, `post` vb.) bir parametresi olduฤŸuna dikkat edin. Body ve diฤŸer parametreler gibi, sizin *path operation function*โ€™ฤฑnฤฑzฤฑn parametresi deฤŸildir. + +/// + +`response_model`, Pydantic model fieldโ€™ฤฑ iรงin declare edeceฤŸiniz aynฤฑ tipi alฤฑr; yani bir Pydantic model olabilir ama รถrneฤŸin `List[Item]` gibi Pydantic modelโ€™lerden oluลŸan bir `list` de olabilir. + +FastAPI bu `response_model`โ€™i; dokรผmantasyon, doฤŸrulama vb. her ลŸey iรงin ve ayrฤฑca รงฤฑktฤฑ verisini **tip tanฤฑmฤฑna gรถre dรถnรผลŸtรผrmek ve filtrelemek** iรงin kullanฤฑr. + +/// tip | ฤฐpucu + +Editรถrรผnรผzde, mypy vb. ile sฤฑkฤฑ type kontrolรผ yapฤฑyorsanฤฑz, fonksiyon dรถnรผลŸ tipini `Any` olarak declare edebilirsiniz. + +Bรถylece editรถre bilerek her ลŸeyi dรถndรผrebileceฤŸinizi sรถylemiลŸ olursunuz. Ancak FastAPI, `response_model` ile dokรผmantasyon, doฤŸrulama, filtreleme vb. iลŸlemleri yine de yapar. + +/// + +### `response_model` ร–nceliฤŸi { #response-model-priority } + +Hem dรถnรผลŸ tipi hem de `response_model` declare ederseniz, FastAPIโ€™de `response_model` รถnceliklidir ve o kullanฤฑlฤฑr. + +Bรถylece, response modelโ€™den farklฤฑ bir tip dรถndรผrdรผฤŸรผnรผz durumlarda bile editรถr ve mypy gibi araรงlar iรงin fonksiyonlarฤฑnฤฑza doฤŸru type annotationโ€™lar ekleyebilir, aynฤฑ zamanda FastAPIโ€™nin `response_model` รผzerinden veri doฤŸrulama, dokรผmantasyon vb. yapmasฤฑnฤฑ saฤŸlayabilirsiniz. + +Ayrฤฑca `response_model=None` kullanarak, ilgili *path operation* iรงin response model oluลŸturulmasฤฑnฤฑ devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. Bu, Pydantic fieldโ€™ฤฑ olarak geรงerli olmayan ลŸeyler iรงin type annotation eklediฤŸinizde gerekebilir; aลŸaฤŸฤฑdaki bรถlรผmlerden birinde bunun รถrneฤŸini gรถreceksiniz. + +## Aynฤฑ input verisini geri dรถndรผrmek { #return-the-same-input-data } + +Burada `UserIn` adฤฑnda bir model declare ediyoruz; bu model plaintext bir password iรงerecek: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// info | Bilgi + +`EmailStr` kullanmak iรงin รถnce `email-validator` paketini kurun. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktive ettiฤŸinizden emin olun ve ardฤฑndan รถrneฤŸin ลŸรถyle kurun: + +```console +$ pip install email-validator +``` + +veya ลŸรถyle: + +```console +$ pip install "pydantic[email]" +``` + +/// + +Bu model ile hem inputโ€™u declare ediyoruz hem de outputโ€™u aynฤฑ model ile declare ediyoruz: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +Artฤฑk bir browser password ile user oluลŸturduฤŸunda, API response iรงinde aynฤฑ passwordโ€™รผ geri dรถndรผrecek. + +Bu รถrnekte sorun olmayabilir; รงรผnkรผ passwordโ€™รผ gรถnderen kullanฤฑcฤฑ zaten aynฤฑ kiลŸi. + +Ancak aynฤฑ modeli baลŸka bir *path operation* iรงin kullanฤฑrsak, kullanฤฑcฤฑnฤฑn passwordโ€™lerini her clientโ€™a gรถnderiyor olabiliriz. + +/// danger + +Tรผm riskleri bildiฤŸinizden ve ne yaptฤฑฤŸฤฑnฤฑzdan emin olmadฤฑฤŸฤฑnฤฑz sรผrece, bir kullanฤฑcฤฑnฤฑn plain passwordโ€™รผnรผ asla saklamayฤฑn ve bu ลŸekilde response iรงinde gรถndermeyin. + +/// + +## Bir output modeli ekleyin { #add-an-output-model } + +Bunun yerine, plaintext password iรงeren bir input modeli ve passwordโ€™รผ iรงermeyen bir output modeli oluลŸturabiliriz: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +Burada *path operation function* password iรงeren aynฤฑ input userโ€™ฤฑ dรถndรผrรผyor olsa bile: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...`response_model` olarak, passwordโ€™รผ iรงermeyen `UserOut` modelimizi declare ettik: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +Dolayฤฑsฤฑyla **FastAPI**, output modelโ€™de declare edilmemiลŸ tรผm verileri (Pydantic kullanarak) filtrelemekle ilgilenir. + +### `response_model` mi Return Type mฤฑ? { #response-model-or-return-type } + +Bu durumda iki model farklฤฑ olduฤŸu iรงin fonksiyon dรถnรผลŸ tipini `UserOut` olarak annotate etseydik, editรถr ve araรงlar farklฤฑ classโ€™lar olduฤŸu iรงin geรงersiz bir tip dรถndรผrdรผฤŸรผmรผzรผ sรถyleyip hata verecekti. + +Bu yรผzden bu รถrnekte `response_model` parametresinde declare etmek zorundayฤฑz. + +...ama bunu nasฤฑl aลŸabileceฤŸinizi gรถrmek iรงin aลŸaฤŸฤฑyฤฑ okumaya devam edin. + +## Return Type ve Veri Filtreleme { #return-type-and-data-filtering } + +ร–nceki รถrnekten devam edelim. Fonksiyonu **tek bir tip ile annotate etmek** istiyoruz; ama fonksiyondan gerรงekte **daha fazla veri** iรงeren bir ลŸey dรถndรผrebilmek istiyoruz. + +FastAPIโ€™nin response modelโ€™i kullanarak veriyi **filtrelemeye** devam etmesini istiyoruz. Yani fonksiyon daha fazla veri dรถndรผrse bile response, sadece response modelโ€™de declare edilmiลŸ fieldโ€™larฤฑ iรงersin. + +ร–nceki รถrnekte classโ€™lar farklฤฑ olduฤŸu iรงin `response_model` parametresini kullanmak zorundaydฤฑk. Ancak bu, editรถr ve araรงlarฤฑn fonksiyon dรถnรผลŸ tipi kontrolรผnden gelen desteฤŸini alamadฤฑฤŸฤฑmฤฑz anlamฤฑna da geliyor. + +Ama bu tarz durumlarฤฑn รงoฤŸunda modelin amacฤฑ, bu รถrnekteki gibi bazฤฑ verileri **filtrelemek/kaldฤฑrmak** olur. + +Bu gibi durumlarda classโ€™lar ve inheritance kullanarak, fonksiyon **type annotations** sayesinde editรถr ve araรงlarda daha iyi destek alabilir, aynฤฑ zamanda FastAPIโ€™nin **veri filtrelemesini** de koruyabiliriz. + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +Bununla birlikte, code typeโ€™lar aรงฤฑsฤฑndan doฤŸru olduฤŸu iรงin editรถrler ve mypy araรง desteฤŸi verir; ayrฤฑca FastAPIโ€™den veri filtrelemeyi de alฤฑrฤฑz. + +Bu nasฤฑl รงalฤฑลŸฤฑyor? Bir bakalฤฑm. ๐Ÿค“ + +### Type Annotations ve Araรง DesteฤŸi { #type-annotations-and-tooling } + +ร–nce editรถrler, mypy ve diฤŸer araรงlar bunu nasฤฑl gรถrรผr, ona bakalฤฑm. + +`BaseUser` temel fieldโ€™lara sahiptir. Ardฤฑndan `UserIn`, `BaseUser`โ€™dan miras alฤฑr ve `password` fieldโ€™ฤฑnฤฑ ekler; yani iki modelin fieldโ€™larฤฑnฤฑn tamamฤฑnฤฑ iรงerir. + +Fonksiyonun dรถnรผลŸ tipini `BaseUser` olarak annotate ediyoruz ama gerรงekte bir `UserIn` instanceโ€™ฤฑ dรถndรผrรผyoruz. + +Editรถr, mypy ve diฤŸer araรงlar buna itiraz etmez; รงรผnkรผ typing aรงฤฑsฤฑndan `UserIn`, `BaseUser`โ€™ฤฑn subclassโ€™ฤฑdฤฑr. Bu da, bir `BaseUser` bekleniyorken `UserIn`โ€™in *geรงerli* bir tip olduฤŸu anlamฤฑna gelir. + +### FastAPI Veri Filtreleme { #fastapi-data-filtering } + +FastAPI aรงฤฑsฤฑndan ise dรถnรผลŸ tipini gรถrรผr ve dรถndรผrdรผฤŸรผnรผz ลŸeyin **yalnฤฑzca** tipte declare edilen fieldโ€™larฤฑ iรงerdiฤŸinden emin olur. + +FastAPI, Pydantic ile iรงeride birkaรง iลŸlem yapar; bรถylece class inheritance kurallarฤฑnฤฑn dรถnen veri filtrelemede aynen kullanฤฑlmasฤฑna izin vermez. Aksi halde beklediฤŸinizden รงok daha fazla veriyi responseโ€™ta dรถndรผrebilirdiniz. + +Bu sayede iki dรผnyanฤฑn da en iyisini alฤฑrsฤฑnฤฑz: **araรง desteฤŸi** veren type annotations ve **veri filtreleme**. + +## Dokรผmanlarda gรถrรผn { #see-it-in-the-docs } + +Otomatik dokรผmanlarฤฑ gรถrdรผฤŸรผnรผzde, input model ve output modelโ€™in her birinin kendi JSON Schemaโ€™sฤฑna sahip olduฤŸunu kontrol edebilirsiniz: + + + +Ve her iki model de etkileลŸimli API dokรผmantasyonunda kullanฤฑlฤฑr: + + + +## DiฤŸer Return Type Annotationโ€™larฤฑ { #other-return-type-annotations } + +Bazฤฑ durumlarda Pydantic field olarak geรงerli olmayan bir ลŸey dรถndรผrebilir ve bunu fonksiyonda annotate edebilirsiniz; amaรง sadece araรงlarฤฑn (editรถr, mypy vb.) saฤŸladฤฑฤŸฤฑ desteฤŸi almaktฤฑr. + +### DoฤŸrudan Response Dรถndรผrmek { #return-a-response-directly } + +En yaygฤฑn durum, [ileri seviye dokรผmanlarda daha sonra anlatฤฑldฤฑฤŸฤฑ gibi doฤŸrudan bir Response dรถndรผrmektir](../advanced/response-directly.md){.internal-link target=_blank}. + +{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} + +Bu basit durum FastAPI tarafฤฑndan otomatik olarak ele alฤฑnฤฑr; รงรผnkรผ dรถnรผลŸ tipi annotationโ€™ฤฑ `Response` classโ€™ฤฑdฤฑr (veya onun bir subclassโ€™ฤฑ). + +Araรงlar da memnun olur; รงรผnkรผ hem `RedirectResponse` hem `JSONResponse`, `Response`โ€™un subclassโ€™ฤฑdฤฑr. Yani type annotation doฤŸrudur. + +### Bir Response Subclassโ€™ฤฑnฤฑ Annotate Etmek { #annotate-a-response-subclass } + +Type annotation iรงinde `Response`โ€™un bir subclassโ€™ฤฑnฤฑ da kullanabilirsiniz: + +{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} + +Bu da รงalฤฑลŸฤฑr; รงรผnkรผ `RedirectResponse`, `Response`โ€™un subclassโ€™ฤฑdฤฑr ve FastAPI bu basit durumu otomatik olarak yรถnetir. + +### Geรงersiz Return Type Annotationโ€™larฤฑ { #invalid-return-type-annotations } + +Ancak geรงerli bir Pydantic tipi olmayan baลŸka rastgele bir obje (รถr. bir veritabanฤฑ objesi) dรถndรผrรผr ve fonksiyonu da รถyle annotate ederseniz, FastAPI bu type annotationโ€™dan bir Pydantic response model oluลŸturmaya รงalฤฑลŸฤฑr ve baลŸarฤฑsฤฑz olur. + +Aynฤฑ ลŸey, farklฤฑ tipler arasฤฑnda bir union kullandฤฑฤŸฤฑnฤฑzda ve bu tiplerden biri veya birkaรงฤฑ geรงerli bir Pydantic tipi deฤŸilse de olur; รถrneฤŸin ลŸu kullanฤฑm patlar ๐Ÿ’ฅ: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...bu, type annotation Pydantic tipi olmadฤฑฤŸฤฑ ve tek bir `Response` classโ€™ฤฑ (veya subclassโ€™ฤฑ) olmadฤฑฤŸฤฑ iรงin baลŸarฤฑsฤฑz olur; bu, bir `Response` ile bir `dict` arasฤฑnda unionโ€™dฤฑr (ikiden herhangi biri). + +### Response Modelโ€™i Devre DฤฑลŸฤฑ Bฤฑrakmak { #disable-response-model } + +Yukarฤฑdaki รถrnekten devam edersek; FastAPIโ€™nin varsayฤฑlan olarak yaptฤฑฤŸฤฑ veri doฤŸrulama, dokรผmantasyon, filtreleme vb. iลŸlemleri istemiyor olabilirsiniz. + +Ancak yine de editรถrler ve type checkerโ€™lar (รถr. mypy) gibi araรงlarฤฑn desteฤŸini almak iรงin fonksiyonda dรถnรผลŸ tipi annotationโ€™ฤฑnฤฑ korumak isteyebilirsiniz. + +Bu durumda `response_model=None` ayarlayarak response model รผretimini devre dฤฑลŸฤฑ bฤฑrakabilirsiniz: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +Bu, FastAPIโ€™nin response model รผretimini atlamasฤฑnฤฑ saฤŸlar; bรถylece FastAPI uygulamanฤฑzฤฑ etkilemeden ihtiyacฤฑnฤฑz olan herhangi bir return type annotationโ€™ฤฑnฤฑ kullanabilirsiniz. ๐Ÿค“ + +## Response Model encoding parametreleri { #response-model-encoding-parameters } + +Response modelโ€™inizde ลŸu ลŸekilde default deฤŸerler olabilir: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (veya Python 3.10โ€™da `str | None = None`) iรงin default `None`โ€™dฤฑr. +* `tax: float = 10.5` iรงin default `10.5`โ€™tir. +* `tags: List[str] = []` iรงin default, boลŸ bir listโ€™tir: `[]`. + +Ancak gerรงekte kaydedilmedilerse, bunlarฤฑ sonuรงtan รงฤฑkarmak isteyebilirsiniz. + +ร–rneฤŸin NoSQL veritabanฤฑnda รงok sayฤฑda optional attribute iรงeren modelleriniz varsa, default deฤŸerlerle dolu รงok uzun JSON responseโ€™larฤฑ gรถndermek istemeyebilirsiniz. + +### `response_model_exclude_unset` parametresini kullanฤฑn { #use-the-response-model-exclude-unset-parameter } + +*Path operation decorator* parametresi olarak `response_model_exclude_unset=True` ayarlayabilirsiniz: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +bรถylece responseโ€™a default deฤŸerler dahil edilmez; yalnฤฑzca gerรงekten set edilmiลŸ deฤŸerler gelir. + +Dolayฤฑsฤฑyla IDโ€™si `foo` olan item iรงin bu *path operation*โ€™a request atarsanฤฑz, response (default deฤŸerler olmadan) ลŸรถyle olur: + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// info | Bilgi + +Ayrฤฑca ลŸunlarฤฑ da kullanabilirsiniz: + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +Bunlar, `exclude_defaults` ve `exclude_none` iรงin Pydantic dokรผmanlarฤฑnda anlatฤฑldฤฑฤŸฤฑ gibidir. + +/// + +#### Defaultโ€™u olan fieldโ€™lar iรงin deฤŸer iรงeren data { #data-with-values-for-fields-with-defaults } + +Ama dataโ€™nฤฑz modelde default deฤŸeri olan fieldโ€™lar iรงin deฤŸer iรงeriyorsa, รถrneฤŸin IDโ€™si `bar` olan item gibi: + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` + +bunlar responseโ€™a dahil edilir. + +#### Default deฤŸerlerle aynฤฑ deฤŸerlere sahip data { #data-with-the-same-values-as-the-defaults } + +EฤŸer data, default deฤŸerlerle aynฤฑ deฤŸerlere sahipse, รถrneฤŸin IDโ€™si `baz` olan item gibi: + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI yeterince akฤฑllฤฑdฤฑr (aslฤฑnda Pydantic yeterince akฤฑllฤฑdฤฑr) ve `description`, `tax`, `tags` default ile aynฤฑ olsa bile bunlarฤฑn explicit olarak set edildiฤŸini (defaultโ€™tan alฤฑnmadฤฑฤŸฤฑnฤฑ) anlar. + +Bu yรผzden JSON response iรงinde yer alฤฑrlar. + +/// tip | ฤฐpucu + +Default deฤŸerlerin yalnฤฑzca `None` olmak zorunda olmadฤฑฤŸฤฑnฤฑ unutmayฤฑn. + +Bir list (`[]`), `10.5` gibi bir `float` vb. olabilirler. + +/// + +### `response_model_include` ve `response_model_exclude` { #response-model-include-and-response-model-exclude } + +Ayrฤฑca *path operation decorator* parametreleri `response_model_include` ve `response_model_exclude`โ€™u da kullanabilirsiniz. + +Bunlar; dahil edilecek attribute isimlerini (geri kalanฤฑnฤฑ atlayarak) ya da hariรง tutulacak attribute isimlerini (geri kalanฤฑnฤฑ dahil ederek) belirten `str` deฤŸerlerinden oluลŸan bir `set` alฤฑr. + +Tek bir Pydantic modelโ€™iniz varsa ve outputโ€™tan bazฤฑ verileri hฤฑzlฤฑca รงฤฑkarmak istiyorsanฤฑz, bu yรถntem pratik bir kฤฑsayol olabilir. + +/// tip | ฤฐpucu + +Ancak yine de, bu parametreler yerine yukarฤฑdaki yaklaลŸฤฑmฤฑ (birden fazla class kullanmayฤฑ) tercih etmeniz รถnerilir. + +ร‡รผnkรผ `response_model_include` veya `response_model_exclude` ile bazฤฑ attributeโ€™larฤฑ atlฤฑyor olsanฤฑz bile, uygulamanฤฑzฤฑn OpenAPIโ€™sinde (ve dokรผmanlarda) รผretilen JSON Schema hรขlรข tam modelin JSON Schemaโ€™sฤฑ olacaktฤฑr. + +Bu durum, benzer ลŸekilde รงalฤฑลŸan `response_model_by_alias` iรงin de geรงerlidir. + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | ฤฐpucu + +`{"name", "description"}` sรถzdizimi, bu iki deฤŸere sahip bir `set` oluลŸturur. + +Bu, `set(["name", "description"])` ile eลŸdeฤŸerdir. + +/// + +#### `set` yerine `list` kullanmak { #using-lists-instead-of-sets } + +YanlฤฑลŸlฤฑkla `set` yerine `list` veya `tuple` kullanฤฑrsanฤฑz, FastAPI bunu yine `set`โ€™e รงevirir ve doฤŸru ลŸekilde รงalฤฑลŸฤฑr: + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## ร–zet { #recap } + +Response modelโ€™leri tanฤฑmlamak ve รถzellikle private dataโ€™nฤฑn filtrelendiฤŸinden emin olmak iรงin *path operation decorator* parametresi `response_model`โ€™i kullanฤฑn. + +Yalnฤฑzca explicit olarak set edilmiลŸ deฤŸerleri dรถndรผrmek iรงin `response_model_exclude_unset` kullanฤฑn. diff --git a/docs/tr/docs/tutorial/response-status-code.md b/docs/tr/docs/tutorial/response-status-code.md new file mode 100644 index 0000000000..57ae7bde34 --- /dev/null +++ b/docs/tr/docs/tutorial/response-status-code.md @@ -0,0 +1,101 @@ +# Response Status Code { #response-status-code } + +Bir response model tanฤฑmlayabildiฤŸiniz gibi, herhangi bir *path operation* iรงinde `status_code` parametresiyle response iรงin kullanฤฑlacak HTTP status code'u da belirtebilirsiniz: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* vb. + +{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} + +/// note | Not + +`status_code`'un, "decorator" metodunun (`get`, `post`, vb.) bir parametresi olduฤŸuna dikkat edin. Tรผm parametreler ve body gibi, sizin *path operation function*'ฤฑnฤฑzฤฑn bir parametresi deฤŸildir. + +/// + +`status_code` parametresi, HTTP status code'u iรงeren bir sayฤฑ alฤฑr. + +/// info | Bilgi + +Alternatif olarak `status_code`, Python'un `http.HTTPStatus`'ฤฑ gibi bir `IntEnum` da alabilir. + +/// + +Bu sayede: + +* Response'da o status code dรถner. +* OpenAPI ลŸemasฤฑnda (dolayฤฑsฤฑyla kullanฤฑcฤฑ arayรผzlerinde de) bu ลŸekilde dokรผmante edilir: + + + +/// note | Not + +Bazฤฑ response code'lar (bir sonraki bรถlรผmde gรถreceฤŸiz) response'un bir body'ye sahip olmadฤฑฤŸฤฑnฤฑ belirtir. + +FastAPI bunu bilir ve response body olmadฤฑฤŸฤฑnฤฑ sรถyleyen OpenAPI dokรผmantasyonunu รผretir. + +/// + +## HTTP status code'lar hakkฤฑnda { #about-http-status-codes } + +/// note | Not + +HTTP status code'larฤฑn ne olduฤŸunu zaten biliyorsanฤฑz, bir sonraki bรถlรผme geรงin. + +/// + +HTTP'de, response'un bir parรงasฤฑ olarak 3 basamaklฤฑ sayฤฑsal bir status code gรถnderirsiniz. + +Bu status code'larฤฑn tanฤฑnmalarฤฑnฤฑ saฤŸlayan bir isimleri de vardฤฑr; ancak รถnemli olan kฤฑsฤฑm sayฤฑdฤฑr. + +Kฤฑsaca: + +* `100 - 199` "Information" iรงindir. DoฤŸrudan nadiren kullanฤฑrsฤฑnฤฑz. Bu status code'lara sahip response'lar body iรงeremez. +* **`200 - 299`** "Successful" response'lar iรงindir. En sฤฑk kullanacaฤŸฤฑnฤฑz aralฤฑk budur. + * `200`, varsayฤฑlan status code'dur ve her ลŸeyin "OK" olduฤŸunu ifade eder. + * BaลŸka bir รถrnek `201` ("Created") olabilir. Genellikle veritabanฤฑnda yeni bir kayฤฑt oluลŸturduktan sonra kullanฤฑlฤฑr. + * ร–zel bir durum ise `204` ("No Content")'tรผr. Client'a dรถndรผrรผlecek iรงerik olmadฤฑฤŸฤฑnda kullanฤฑlฤฑr; bu nedenle response body olmamalฤฑdฤฑr. +* **`300 - 399`** "Redirection" iรงindir. Bu status code'lara sahip response'lar, `304` ("Not Modified") hariรง, body iรงerebilir de iรงermeyebilir de; `304` kesinlikle body iรงermemelidir. +* **`400 - 499`** "Client error" response'larฤฑ iรงindir. Muhtemelen en sฤฑk kullanacaฤŸฤฑnฤฑz ikinci aralฤฑk budur. + * ร–rneฤŸin `404`, "Not Found" response'u iรงindir. + * Client kaynaklฤฑ genel hatalar iรงin doฤŸrudan `400` kullanabilirsiniz. +* `500 - 599` server hatalarฤฑ iรงindir. Neredeyse hiรง doฤŸrudan kullanmazsฤฑnฤฑz. Uygulama kodunuzun bir bรถlรผmรผnde ya da server'da bir ลŸeyler ters giderse, otomatik olarak bu status code'lardan biri dรถner. + +/// tip | ฤฐpucu + +Her bir status code hakkฤฑnda daha fazla bilgi almak ve hangi kodun ne iรงin kullanฤฑldฤฑฤŸฤฑnฤฑ gรถrmek iรงin HTTP status code'lar hakkฤฑnda MDN dokรผmantasyonuna gรถz atฤฑn. + +/// + +## ฤฐsimleri hatฤฑrlamak iรงin kฤฑsayol { #shortcut-to-remember-the-names } + +ร–nceki รถrneฤŸe tekrar bakalฤฑm: + +{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} + +`201`, "Created" iรงin kullanฤฑlan status code'dur. + +Ancak bu kodlarฤฑn her birinin ne anlama geldiฤŸini ezberlemek zorunda deฤŸilsiniz. + +`fastapi.status` iรงindeki kolaylฤฑk deฤŸiลŸkenlerini (convenience variables) kullanabilirsiniz. + +{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} + +Bunlar sadece kolaylฤฑk saฤŸlar; aynฤฑ sayฤฑyฤฑ taลŸฤฑrlar. Ancak bu ลŸekilde editรถrรผn autocomplete รถzelliฤŸiyle kolayca bulabilirsiniz: + + + +/// note | Teknik Detaylar + +`from starlette import status` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.status`'u `fastapi.status` olarak da sunar. Ancak bu aslฤฑnda doฤŸrudan Starlette'den gelir. + +/// + +## Varsayฤฑlanฤฑ deฤŸiลŸtirmek { #changing-the-default } + +Daha sonra, [ฤฐleri Dรผzey Kullanฤฑcฤฑ Kฤฑlavuzu](../advanced/response-change-status-code.md){.internal-link target=_blank} iรงinde, burada tanฤฑmladฤฑฤŸฤฑnฤฑz varsayฤฑlanฤฑn dฤฑลŸฤฑnda farklฤฑ bir status code nasฤฑl dรถndรผreceฤŸinizi gรถreceksiniz. diff --git a/docs/tr/docs/tutorial/schema-extra-example.md b/docs/tr/docs/tutorial/schema-extra-example.md new file mode 100644 index 0000000000..a91dda8924 --- /dev/null +++ b/docs/tr/docs/tutorial/schema-extra-example.md @@ -0,0 +1,202 @@ +# Request ร–rnek Verilerini Tanฤฑmlama { #declare-request-example-data } + +Uygulamanฤฑzฤฑn alabileceฤŸi veriler iรงin รถrnekler (examples) tanฤฑmlayabilirsiniz. + +Bunu yapmanฤฑn birkaรง yolu var. + +## Pydantic modellerinde ek JSON Schema verisi { #extra-json-schema-data-in-pydantic-models } + +OluลŸturulan JSON Schemaโ€™ya eklenecek ลŸekilde bir Pydantic model iรงin `examples` tanฤฑmlayabilirsiniz. + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +Bu ek bilgi, o modelin รงฤฑktฤฑ **JSON Schema**โ€™sฤฑna olduฤŸu gibi eklenir ve API dokรผmanlarฤฑnda kullanฤฑlฤฑr. + +Pydantic dokรผmanlarฤฑ: Configuration bรถlรผmรผnde anlatฤฑldฤฑฤŸฤฑ gibi, bir `dict` alan `model_config` niteliฤŸini kullanabilirsiniz. + +รœretilen JSON Schemaโ€™da gรถrรผnmesini istediฤŸiniz (รถr. `examples` dahil) her tรผrlรผ ek veriyi iรงeren bir `dict` ile `"json_schema_extra"` ayarlayabilirsiniz. + +/// tip | ฤฐpucu + +Aynฤฑ tekniฤŸi JSON Schemaโ€™yฤฑ geniลŸletmek ve kendi รถzel ek bilgilerinizi eklemek iรงin de kullanabilirsiniz. + +ร–rneฤŸin, bir frontend kullanฤฑcฤฑ arayรผzรผ iรงin metadata eklemek vb. amaรงlarla kullanฤฑlabilir. + +/// + +/// info | Bilgi + +OpenAPI 3.1.0 (FastAPI 0.99.0โ€™dan beri kullanฤฑlฤฑyor), **JSON Schema** standardฤฑnฤฑn bir parรงasฤฑ olan `examples` iรงin destek ekledi. + +Bundan รถnce yalnฤฑzca tek bir รถrnek iรงin `example` anahtar kelimesini destekliyordu. Bu hรขlรข OpenAPI 3.1.0 tarafฤฑndan desteklenir; ancak artฤฑk deprecated durumdadฤฑr ve JSON Schema standardฤฑnฤฑn parรงasฤฑ deฤŸildir. Bu nedenle `example` kullanฤฑmฤฑnฤฑ `examples`โ€™a taลŸฤฑmanฤฑz รถnerilir. ๐Ÿค“ + +Daha fazlasฤฑnฤฑ sayfanฤฑn sonunda okuyabilirsiniz. + +/// + +## `Field` ek argรผmanlarฤฑ { #field-additional-arguments } + +Pydantic modelleriyle `Field()` kullanฤฑrken ek `examples` de tanฤฑmlayabilirsiniz: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## JSON Schema - OpenAPI iรงinde `examples` { #examples-in-json-schema-openapi } + +AลŸaฤŸฤฑdakilerden herhangi birini kullanฤฑrken: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +OpenAPI iรงindeki **JSON Schema**โ€™larฤฑna eklenecek ek bilgilerle birlikte bir `examples` grubu da tanฤฑmlayabilirsiniz. + +### `examples` ile `Body` { #body-with-examples } + +Burada `Body()` iรงinde beklenen veri iรงin tek bir รถrnek iรงeren `examples` geรงiriyoruz: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### Dokรผman arayรผzรผnde รถrnek { #example-in-the-docs-ui } + +Yukarฤฑdaki yรถntemlerden herhangi biriyle `/docs` iรงinde ลŸรถyle gรถrรผnรผr: + + + +### Birden fazla `examples` ile `Body` { #body-with-multiple-examples } + +Elbette birden fazla `examples` da geรงebilirsiniz: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +Bunu yaptฤฑฤŸฤฑnฤฑzda, รถrnekler bu body verisi iรงin dahili **JSON Schema**โ€™nฤฑn bir parรงasฤฑ olur. + +Buna raฤŸmen, time of writing this, dokรผman arayรผzรผnรผ gรถsteren araรง olan Swagger UI, **JSON Schema** iรงindeki veriler iรงin birden fazla รถrneฤŸi gรถstermeyi desteklemiyor. Ancak aลŸaฤŸฤฑda bir รงรถzรผm yolu var. + +### OpenAPIโ€™ye รถzel `examples` { #openapi-specific-examples } + +**JSON Schema** `examples`โ€™ฤฑ desteklemeden รถnce OpenAPI, yine `examples` adlฤฑ farklฤฑ bir alanฤฑ destekliyordu. + +Bu **OpenAPIโ€™ye รถzel** `examples`, OpenAPI spesifikasyonunda baลŸka bir bรถlรผmde yer alฤฑr. Her bir JSON Schemaโ€™nฤฑn iรงinde deฤŸil, **her bir *path operation* detaylarฤฑ** iรงinde bulunur. + +Swagger UI da bu รถzel `examples` alanฤฑnฤฑ bir sรผredir destekliyor. Dolayฤฑsฤฑyla bunu, **dokรผman arayรผzรผnde** farklฤฑ **รถrnekleri gรถstermek** iรงin kullanabilirsiniz. + +OpenAPIโ€™ye รถzel bu `examples` alanฤฑnฤฑn ลŸekli, (bir `list` yerine) **birden fazla รถrnek** iรงeren bir `dict`โ€™tir; her รถrnek ayrฤฑca **OpenAPI**โ€™ye eklenecek ekstra bilgiler iรงerir. + +Bu, OpenAPIโ€™nin iรงerdiฤŸi JSON Schemaโ€™larฤฑn iรงine girmez; bunun yerine doฤŸrudan *path operation* รผzerinde, dฤฑลŸarฤฑda yer alฤฑr. + +### `openapi_examples` Parametresini Kullanma { #using-the-openapi-examples-parameter } + +FastAPIโ€™de OpenAPIโ€™ye รถzel `examples`โ€™ฤฑ, ลŸu araรงlar iรงin `openapi_examples` parametresiyle tanฤฑmlayabilirsiniz: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +`dict`โ€™in anahtarlarฤฑ her bir รถrneฤŸi tanฤฑmlar; her bir deฤŸer ise baลŸka bir `dict`โ€™tir. + +`examples` iรงindeki her bir รถrnek `dict`โ€™i ลŸunlarฤฑ iรงerebilir: + +* `summary`: ร–rnek iรงin kฤฑsa aรงฤฑklama. +* `description`: Markdown metni iรงerebilen uzun aรงฤฑklama. +* `value`: Gรถsterilecek gerรงek รถrnek (รถr. bir `dict`). +* `externalValue`: `value`โ€™a alternatif; รถrneฤŸe iลŸaret eden bir URL. Ancak bu, `value` kadar รงok araรง tarafฤฑndan desteklenmiyor olabilir. + +ลžรถyle kullanabilirsiniz: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### Dokรผman Arayรผzรผnde OpenAPI ร–rnekleri { #openapi-examples-in-the-docs-ui } + +`Body()`โ€™ye `openapi_examples` eklendiฤŸinde `/docs` ลŸรถyle gรถrรผnรผr: + + + +## Teknik Detaylar { #technical-details } + +/// tip | ฤฐpucu + +Zaten **FastAPI** sรผrรผmรผ **0.99.0 veya รผzerini** kullanฤฑyorsanฤฑz, bรผyรผk olasฤฑlฤฑkla bu detaylarฤฑ **atlanabilirsiniz**. + +Bunlar daha รงok OpenAPI 3.1.0โ€™ฤฑn henรผz mevcut olmadฤฑฤŸฤฑ eski sรผrรผmler iรงin geรงerlidir. + +Bunu kฤฑsa bir OpenAPI ve JSON Schema **tarih dersi** gibi dรผลŸรผnebilirsiniz. ๐Ÿค“ + +/// + +/// warning | Uyarฤฑ + +Bunlar **JSON Schema** ve **OpenAPI** standartlarฤฑ hakkฤฑnda oldukรงa teknik detaylardฤฑr. + +Yukarฤฑdaki fikirler sizin iรงin zaten รงalฤฑลŸฤฑyorsa bu kadarฤฑ yeterli olabilir; muhtemelen bu detaylara ihtiyacฤฑnฤฑz yoktur, gรถnรผl rahatlฤฑฤŸฤฑyla atlayabilirsiniz. + +/// + +OpenAPI 3.1.0โ€™dan รถnce OpenAPI, **JSON Schema**โ€™nฤฑn daha eski ve deฤŸiลŸtirilmiลŸ bir sรผrรผmรผnรผ kullanฤฑyordu. + +JSON Schemaโ€™da `examples` yoktu; bu yรผzden OpenAPI, deฤŸiลŸtirilmiลŸ sรผrรผmรผne kendi `example` alanฤฑnฤฑ ekledi. + +OpenAPI ayrฤฑca spesifikasyonun diฤŸer bรถlรผmlerine de `example` ve `examples` alanlarฤฑnฤฑ ekledi: + +* `Parameter Object` (spesifikasyonda) โ€” FastAPIโ€™de ลŸunlar tarafฤฑndan kullanฤฑlฤฑyordu: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`; `content` alanฤฑnda, `Media Type Object` รผzerinde (spesifikasyonda) โ€” FastAPIโ€™de ลŸunlar tarafฤฑndan kullanฤฑlฤฑyordu: + * `Body()` + * `File()` + * `Form()` + +/// info | Bilgi + +Bu eski OpenAPIโ€™ye รถzel `examples` parametresi, FastAPI `0.103.0` sรผrรผmรผnden beri `openapi_examples` olarak kullanฤฑlฤฑyor. + +/// + +### JSON Schemaโ€™nฤฑn `examples` alanฤฑ { #json-schemas-examples-field } + +Sonrasฤฑnda JSON Schema, spesifikasyonun yeni bir sรผrรผmรผne `examples` alanฤฑnฤฑ ekledi. + +Ardฤฑndan yeni OpenAPI 3.1.0, bu yeni `examples` alanฤฑnฤฑ iรงeren en gรผncel sรผrรผmรผ (JSON Schema 2020-12) temel aldฤฑ. + +Ve artฤฑk, deprecated olan eski tekil (ve รถzel) `example` alanฤฑna kฤฑyasla bu yeni `examples` alanฤฑ รถnceliklidir. + +JSON Schemaโ€™daki bu yeni `examples` alanฤฑ, OpenAPIโ€™de baลŸka yerlerde kullanฤฑlan (yukarฤฑda anlatฤฑlan) metadataโ€™lฤฑ `dict` yapฤฑsฤฑndan farklฤฑ olarak **sadece รถrneklerden oluลŸan bir `list`**โ€™tir. + +/// info | Bilgi + +OpenAPI 3.1.0, JSON Schema ile bu yeni ve daha basit entegrasyonla yayฤฑmlandฤฑktan sonra bile bir sรผre, otomatik dokรผmantasyonu saฤŸlayan araรง Swagger UI OpenAPI 3.1.0โ€™ฤฑ desteklemiyordu (5.0.0 sรผrรผmรผnden beri destekliyor ๐ŸŽ‰). + +Bu nedenle, FastAPIโ€™nin 0.99.0 รถncesi sรผrรผmleri OpenAPI 3.1.0โ€™dan daha dรผลŸรผk sรผrรผmleri kullanmaya devam etti. + +/// + +### Pydantic ve FastAPI `examples` { #pydantic-and-fastapi-examples } + +Bir Pydantic modelinin iรงine `schema_extra` ya da `Field(examples=["something"])` kullanarak `examples` eklediฤŸinizde, bu รถrnek o Pydantic modelinin **JSON Schema**โ€™sฤฑna eklenir. + +Ve Pydantic modelinin bu **JSON Schema**โ€™sฤฑ, APIโ€™nizin **OpenAPI**โ€™sine dahil edilir; ardฤฑndan dokรผman arayรผzรผnde kullanฤฑlฤฑr. + +FastAPI 0.99.0โ€™dan รถnceki sรผrรผmlerde (0.99.0 ve รผzeri daha yeni OpenAPI 3.1.0โ€™ฤฑ kullanฤฑr) `Query()`, `Body()` vb. diฤŸer araรงlarla `example` veya `examples` kullandฤฑฤŸฤฑnฤฑzda, bu รถrnekler o veriyi tanฤฑmlayan JSON Schemaโ€™ya (OpenAPIโ€™nin kendi JSON Schema sรผrรผmรผne bile) eklenmiyordu; bunun yerine doฤŸrudan OpenAPIโ€™deki *path operation* tanฤฑmฤฑna ekleniyordu (JSON Schema kullanan OpenAPI bรถlรผmlerinin dฤฑลŸฤฑnda). + +Ancak artฤฑk FastAPI 0.99.0 ve รผzeri OpenAPI 3.1.0 kullandฤฑฤŸฤฑ (JSON Schema 2020-12) ve Swagger UI 5.0.0 ve รผzeriyle birlikte, her ลŸey daha tutarlฤฑ ve รถrnekler JSON Schemaโ€™ya dahil ediliyor. + +### Swagger UI ve OpenAPIโ€™ye รถzel `examples` { #swagger-ui-and-openapi-specific-examples } + +Swagger UI (2023-08-26 itibarฤฑyla) birden fazla JSON Schema รถrneฤŸini desteklemediฤŸi iรงin, kullanฤฑcฤฑlarฤฑn dokรผmanlarda birden fazla รถrnek gรถstermesi mรผmkรผn deฤŸildi. + +Bunu รงรถzmek iรงin FastAPI `0.103.0`, yeni `openapi_examples` parametresiyle aynฤฑ eski **OpenAPIโ€™ye รถzel** `examples` alanฤฑnฤฑ tanฤฑmlamayฤฑ **desteklemeye baลŸladฤฑ**. ๐Ÿค“ + +### ร–zet { #summary } + +Eskiden tarihten pek hoลŸlanmadฤฑฤŸฤฑmฤฑ sรถylerdim... ลŸimdi bakฤฑn, "teknoloji tarihi" dersi anlatฤฑyorum. ๐Ÿ˜… + +Kฤฑsacasฤฑ, **FastAPI 0.99.0 veya รผzerine yรผkseltin**; her ลŸey รงok daha **basit, tutarlฤฑ ve sezgisel** olur ve bu tarihsel detaylarฤฑn hiรงbirini bilmeniz gerekmez. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/security/first-steps.md b/docs/tr/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000..7e0a70a02c --- /dev/null +++ b/docs/tr/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# Gรผvenlik - ฤฐlk Adฤฑmlar { #security-first-steps } + +**backend** APIโ€™nizin bir domainโ€™de olduฤŸunu dรผลŸรผnelim. + +Ve baลŸka bir domainโ€™de ya da aynฤฑ domainโ€™in farklฤฑ bir pathโ€™inde (veya bir mobil uygulamada) bir **frontend**โ€™iniz var. + +Ve frontendโ€™in, **username** ve **password** kullanarak backend ile kimlik doฤŸrulamasฤฑ yapabilmesini istiyorsunuz. + +Bunu **FastAPI** ile **OAuth2** kullanarak oluลŸturabiliriz. + +Ama ihtiyacฤฑnฤฑz olan kรผรงรผk bilgi parรงalarฤฑnฤฑ bulmak iรงin uzun spesifikasyonun tamamฤฑnฤฑ okuma zahmetine girmeyelim. + +GรผvenliฤŸi yรถnetmek iรงin **FastAPI**โ€™nin sunduฤŸu araรงlarฤฑ kullanalฤฑm. + +## Nasฤฑl Gรถrรผnรผyor { #how-it-looks } + +ร–nce kodu kullanฤฑp nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna bakalฤฑm, sonra neler olup bittiฤŸini anlamak iรงin geri dรถneriz. + +## `main.py` OluลŸturun { #create-main-py } + +ร–rneฤŸi `main.py` adlฤฑ bir dosyaya kopyalayฤฑn: + +{* ../../docs_src/security/tutorial001_an_py39.py *} + +## ร‡alฤฑลŸtฤฑrฤฑn { #run-it } + +/// info | Bilgi + +`python-multipart` paketi, `pip install "fastapi[standard]"` komutunu รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda **FastAPI** ile birlikte otomatik olarak kurulur. + +Ancak `pip install fastapi` komutunu kullanฤฑrsanฤฑz, `python-multipart` paketi varsayฤฑlan olarak dahil edilmez. + +Elle kurmak iรงin bir [virtual environment](../../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktive ettiฤŸinizden emin olun ve ardฤฑndan ลŸununla kurun: + +```console +$ pip install python-multipart +``` + +Bunun nedeni, **OAuth2**โ€™nin `username` ve `password` gรถndermek iรงin "form data" kullanmasฤฑdฤฑr. + +/// + +ร–rneฤŸi ลŸu ลŸekilde รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## Kontrol Edin { #check-it } + +EtkileลŸimli dokรผmantasyona gidin: http://127.0.0.1:8000/docs. + +ลžuna benzer bir ลŸey gรถreceksiniz: + + + +/// check | Authorize butonu! + +Artฤฑk parฤฑl parฤฑl yeni bir "Authorize" butonunuz var. + +Ayrฤฑca *path operation*โ€™ฤฑnฤฑzฤฑn saฤŸ รผst kรถลŸesinde tฤฑklayabileceฤŸiniz kรผรงรผk bir kilit simgesi de bulunuyor. + +/// + +Ve ona tฤฑklarsanฤฑz, `username` ve `password` (ve diฤŸer opsiyonel alanlarฤฑ) girebileceฤŸiniz kรผรงรผk bir yetkilendirme formu gรถrรผrsรผnรผz: + + + +/// note | Not + +Formda ne yazdฤฑฤŸฤฑnฤฑzฤฑn รถnemi yok; ลŸimdilik รงalฤฑลŸmayacak. Ama birazdan oraya da geleceฤŸiz. + +/// + +Bu, elbette son kullanฤฑcฤฑlar iรงin bir frontend deฤŸil; ancak tรผm APIโ€™nizi etkileลŸimli ลŸekilde belgelemek iรงin harika bir otomatik araรงtฤฑr. + +Frontend ekibi tarafฤฑndan kullanฤฑlabilir (bu ekip siz de olabilirsiniz). + +รœรงรผncรผ taraf uygulamalar ve sistemler tarafฤฑndan kullanฤฑlabilir. + +Ve aynฤฑ uygulamayฤฑ debug etmek, kontrol etmek ve test etmek iรงin sizin tarafฤฑnฤฑzdan da kullanฤฑlabilir. + +## `password` Flow { #the-password-flow } + +ลžimdi biraz geri dรถnรผp bunlarฤฑn ne olduฤŸuna bakalฤฑm. + +`password` "flow"u, OAuth2โ€™de gรผvenlik ve authenticationโ€™ฤฑ yรถnetmek iรงin tanฤฑmlanmฤฑลŸ yรถntemlerden ("flow"lardan) biridir. + +OAuth2, backendโ€™in veya APIโ€™nin, kullanฤฑcฤฑyฤฑ authenticate eden serverโ€™dan baฤŸฤฑmsฤฑz olabilmesi iรงin tasarlanmฤฑลŸtฤฑr. + +Ancak bu รถrnekte, aynฤฑ **FastAPI** uygulamasฤฑ hem APIโ€™yi hem de authenticationโ€™ฤฑ yรถnetecek. + +O yรผzden basitleลŸtirilmiลŸ bu bakฤฑลŸ aรงฤฑsฤฑndan รผzerinden geรงelim: + +* Kullanฤฑcฤฑ frontendโ€™de `username` ve `password` yazar ve `Enter`โ€™a basar. +* Frontend (kullanฤฑcฤฑnฤฑn browserโ€™ฤฑnda รงalฤฑลŸฤฑr), bu `username` ve `password` deฤŸerlerini APIโ€™mizdeki belirli bir URLโ€™ye gรถnderir (`tokenUrl="token"` ile tanฤฑmlanan). +* API, `username` ve `password` deฤŸerlerini kontrol eder ve bir "token" ile response dรถner (henรผz bunlarฤฑn hiรงbirini implement etmedik). + * "Token", daha sonra bu kullanฤฑcฤฑyฤฑ doฤŸrulamak iรงin kullanabileceฤŸimiz iรงerik taลŸฤฑyan bir stringโ€™dir. + * Normalde tokenโ€™ฤฑn bir sรผre sonra sรผresi dolacak ลŸekilde ayarlanmasฤฑ beklenir. + * Bรถylece kullanฤฑcฤฑnฤฑn bir noktada tekrar giriลŸ yapmasฤฑ gerekir. + * Ayrฤฑca token รงalฤฑnฤฑrsa risk daha dรผลŸรผk olur. ร‡oฤŸu durumda, sonsuza kadar รงalฤฑลŸacak kalฤฑcฤฑ bir anahtar gibi deฤŸildir. +* Frontend bu tokenโ€™ฤฑ geรงici olarak bir yerde saklar. +* Kullanฤฑcฤฑ frontendโ€™de tฤฑklayarak web uygulamasฤฑnฤฑn baลŸka bir bรถlรผmรผne gider. +* Frontendโ€™in APIโ€™den daha fazla veri almasฤฑ gerekir. + * Ancak o endpoint iรงin authentication gereklidir. + * Bu yรผzden APIโ€™mizle authenticate olmak iรงin `Authorization` headerโ€™ฤฑnฤฑ, `Bearer ` + token deฤŸeriyle gรถnderir. + * Token `foobar` iรงeriyorsa `Authorization` headerโ€™ฤฑnฤฑn iรงeriฤŸi `Bearer foobar` olur. + +## **FastAPI**โ€™nin `OAuth2PasswordBearer`โ€™ฤฑ { #fastapis-oauth2passwordbearer } + +**FastAPI**, bu gรผvenlik รถzelliklerini implement etmek iรงin farklฤฑ soyutlama seviyelerinde รงeลŸitli araรงlar saฤŸlar. + +Bu รถrnekte **OAuth2**โ€™yi, **Password** flow ile, **Bearer** token kullanarak uygulayacaฤŸฤฑz. Bunu `OAuth2PasswordBearer` sฤฑnฤฑfฤฑ ile yaparฤฑz. + +/// info | Bilgi + +"Bearer" token tek seรงenek deฤŸildir. + +Ama bizim kullanฤฑm senaryomuz iรงin en iyi seรงenek odur. + +Ayrฤฑca bir OAuth2 uzmanฤฑ deฤŸilseniz ve ihtiyaรงlarฤฑnฤฑza daha uygun baลŸka bir seรงeneฤŸin neden gerekli olduฤŸunu net olarak bilmiyorsanฤฑz, รงoฤŸu kullanฤฑm senaryosu iรงin de en uygun seรงenek olacaktฤฑr. + +Bu durumda bile **FastAPI**, onu oluลŸturabilmeniz iรงin gereken araรงlarฤฑ sunar. + +/// + +`OAuth2PasswordBearer` sฤฑnฤฑfฤฑnฤฑn bir instanceโ€™ฤฑnฤฑ oluลŸtururken `tokenUrl` parametresini veririz. Bu parametre, clientโ€™ฤฑn (kullanฤฑcฤฑnฤฑn browserโ€™ฤฑnda รงalฤฑลŸan frontendโ€™in) token almak iรงin `username` ve `password` gรถndereceฤŸi URLโ€™yi iรงerir. + +{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} + +/// tip | ฤฐpucu + +Burada `tokenUrl="token"`, henรผz oluลŸturmadฤฑฤŸฤฑmฤฑz gรถreli bir URL olan `token`โ€™ฤฑ ifade eder. Gรถreli URL olduฤŸu iรงin `./token` ile eลŸdeฤŸerdir. + +Gรถreli URL kullandฤฑฤŸฤฑmฤฑz iรงin, APIโ€™niz `https://example.com/` adresinde olsaydฤฑ `https://example.com/token` anlamฤฑna gelirdi. Ama APIโ€™niz `https://example.com/api/v1/` adresinde olsaydฤฑ, bu kez `https://example.com/api/v1/token` anlamฤฑna gelirdi. + +Gรถreli URL kullanmak, [Behind a Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank} gibi daha ileri kullanฤฑm senaryolarฤฑnda bile uygulamanฤฑzฤฑn รงalฤฑลŸmaya devam etmesini garanti etmek aรงฤฑsฤฑndan รถnemlidir. + +/// + +Bu parametre o endpointโ€™i / *path operation*โ€™ฤฑ oluลŸturmaz; fakat `/token` URLโ€™sinin clientโ€™ฤฑn token almak iรงin kullanmasฤฑ gereken URL olduฤŸunu bildirir. Bu bilgi OpenAPIโ€™de, dolayฤฑsฤฑyla etkileลŸimli API dokรผmantasyon sistemlerinde kullanฤฑlฤฑr. + +Birazdan gerรงek path operationโ€™ฤฑ da oluลŸturacaฤŸฤฑz. + +/// info | Teknik Detaylar + +EฤŸer รงok katฤฑ bir "Pythonista" iseniz, `token_url` yerine `tokenUrl` ลŸeklindeki parametre adlandฤฑrma stilini sevmeyebilirsiniz. + +Bunun nedeni, OpenAPI spesifikasyonundaki isimle aynฤฑ adฤฑn kullanฤฑlmasฤฑdฤฑr. Bรถylece bu gรผvenlik ลŸemalarฤฑndan herhangi biri hakkฤฑnda daha fazla araลŸtฤฑrma yapmanฤฑz gerekirse, adฤฑ kopyalayฤฑp yapฤฑลŸtฤฑrarak kolayca daha fazla bilgi bulabilirsiniz. + +/// + +`oauth2_scheme` deฤŸiลŸkeni, `OAuth2PasswordBearer`โ€™ฤฑn bir instanceโ€™ฤฑdฤฑr; ama aynฤฑ zamanda "callable"dฤฑr. + +ลžu ลŸekilde รงaฤŸrฤฑlabilir: + +```Python +oauth2_scheme(some, parameters) +``` + +Dolayฤฑsฤฑyla `Depends` ile kullanฤฑlabilir. + +### Kullanฤฑn { #use-it } + +Artฤฑk `Depends` ile bir dependency olarak `oauth2_scheme`โ€™i geรงebilirsiniz. + +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} + +Bu dependency, *path operation function* iรงindeki `token` parametresine atanacak bir `str` saฤŸlar. + +**FastAPI**, bu dependencyโ€™yi OpenAPI ลŸemasฤฑnda (ve otomatik API dokรผmanlarฤฑnda) bir "security scheme" tanฤฑmlamak iรงin kullanabileceฤŸini bilir. + +/// info | Teknik Detaylar + +**FastAPI**, bir dependency iรงinde tanฤฑmlanan `OAuth2PasswordBearer` sฤฑnฤฑfฤฑnฤฑ OpenAPIโ€™de security scheme tanฤฑmlamak iรงin kullanabileceฤŸini bilir; รงรผnkรผ bu sฤฑnฤฑf `fastapi.security.oauth2.OAuth2`โ€™den kalฤฑtฤฑm alฤฑr, o da `fastapi.security.base.SecurityBase`โ€™den kalฤฑtฤฑm alฤฑr. + +OpenAPI (ve otomatik API dokรผmanlarฤฑ) ile entegre olan tรผm security araรงlarฤฑ `SecurityBase`โ€™den kalฤฑtฤฑm alฤฑr; **FastAPI** bu sayede onlarฤฑ OpenAPIโ€™ye nasฤฑl entegre edeceฤŸini anlayabilir. + +/// + +## Ne Yapar { #what-it-does } + +Request iรงinde `Authorization` headerโ€™ฤฑnฤฑ arar, deฤŸerin `Bearer ` + bir token olup olmadฤฑฤŸฤฑnฤฑ kontrol eder ve tokenโ€™ฤฑ `str` olarak dรถndรผrรผr. + +EฤŸer `Authorization` headerโ€™ฤฑnฤฑ gรถrmezse ya da deฤŸer `Bearer ` tokenโ€™ฤฑ iรงermiyorsa, doฤŸrudan 401 status code hatasฤฑyla (`UNAUTHORIZED`) response dรถner. + +Tokenโ€™ฤฑn var olup olmadฤฑฤŸฤฑnฤฑ kontrol edip ayrฤฑca hata dรถndรผrmenize bile gerek yoktur. Fonksiyonunuz รงalฤฑลŸฤฑyorsa, token iรงinde bir `str` olacaฤŸฤฑndan emin olabilirsiniz. + +Bunu ลŸimdiden etkileลŸimli dokรผmanlarda deneyebilirsiniz: + + + +Henรผz tokenโ€™ฤฑn geรงerliliฤŸini doฤŸrulamฤฑyoruz, ama baลŸlangฤฑรง iรงin bu bile yeterli. + +## ร–zet { #recap } + +Yani sadece 3 veya 4 ekstra satฤฑrla, ลŸimdiden ilkel de olsa bir gรผvenlik katmanฤฑ elde etmiลŸ oldunuz. diff --git a/docs/tr/docs/tutorial/security/get-current-user.md b/docs/tr/docs/tutorial/security/get-current-user.md new file mode 100644 index 0000000000..9f56c76289 --- /dev/null +++ b/docs/tr/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# Mevcut Kullanฤฑcฤฑyฤฑ Alma { #get-current-user } + +ร–nceki bรถlรผmde gรผvenlik sistemi (dependency injection sistemine dayanฤฑr) *path operation function*'a `str` olarak bir `token` veriyordu: + +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} + +Ancak bu hรขlรข pek kullanฤฑลŸlฤฑ deฤŸil. + +Bize mevcut kullanฤฑcฤฑyฤฑ verecek ลŸekilde dรผzenleyelim. + +## Bir kullanฤฑcฤฑ modeli oluลŸturun { #create-a-user-model } + +ร–nce bir Pydantic kullanฤฑcฤฑ modeli oluลŸturalฤฑm. + +Body'leri bildirmek iรงin Pydantic'i nasฤฑl kullanฤฑyorsak, aynฤฑ ลŸekilde onu baลŸka her yerde de kullanabiliriz: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} + +## `get_current_user` dependency'si oluลŸturun { #create-a-get-current-user-dependency } + +Bir `get_current_user` dependency'si oluลŸturalฤฑm. + +Dependency'lerin alt dependency'leri olabileceฤŸini hatฤฑrlฤฑyor musunuz? + +`get_current_user`, daha รถnce oluลŸturduฤŸumuz `oauth2_scheme` ile aynฤฑ dependency'yi kullanacak. + +Daha รถnce *path operation* iรงinde doฤŸrudan yaptฤฑฤŸฤฑmฤฑz gibi, yeni dependency'miz `get_current_user`, alt dependency olan `oauth2_scheme` รผzerinden `str` olarak bir `token` alacak: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## Kullanฤฑcฤฑyฤฑ alฤฑn { #get-the-user } + +`get_current_user`, oluลŸturduฤŸumuz (sahte) bir yardฤฑmcฤฑ (utility) fonksiyonu kullanacak; bu fonksiyon `str` olarak bir token alฤฑr ve Pydantic `User` modelimizi dรถndรผrรผr: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## Mevcut kullanฤฑcฤฑyฤฑ enjekte edin { #inject-the-current-user } + +Artฤฑk *path operation* iรงinde `get_current_user` ile aynฤฑ `Depends` yaklaลŸฤฑmฤฑnฤฑ kullanabiliriz: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +`current_user` tipini Pydantic `User` modeli olarak belirttiฤŸimize dikkat edin. + +Bu sayede fonksiyonun iรงinde otomatik tamamlama ve tip kontrollerinin tamamฤฑndan faydalanฤฑrฤฑz. + +/// tip | ฤฐpucu + +Request body'lerinin de Pydantic modelleri ile bildirildiฤŸini hatฤฑrlฤฑyor olabilirsiniz. + +Burada `Depends` kullandฤฑฤŸฤฑnฤฑz iรงin **FastAPI** karฤฑลŸฤฑklฤฑk yaลŸamaz. + +/// + +/// check | Ek bilgi + +Bu dependency sisteminin tasarฤฑmฤฑ, hepsi `User` modeli dรถndรผren farklฤฑ dependency'lere (farklฤฑ "dependable"lara) sahip olmamฤฑza izin verir. + +Bu tipte veri dรถndรผrebilen yalnฤฑzca tek bir dependency ile sฤฑnฤฑrlฤฑ deฤŸiliz. + +/// + +## DiฤŸer modeller { #other-models } + +Artฤฑk *path operation function* iรงinde mevcut kullanฤฑcฤฑyฤฑ doฤŸrudan alabilir ve gรผvenlik mekanizmalarฤฑnฤฑ `Depends` kullanarak **Dependency Injection** seviyesinde yรถnetebilirsiniz. + +Ayrฤฑca gรผvenlik gereksinimleri iรงin herhangi bir model veya veri kullanabilirsiniz (bu รถrnekte bir Pydantic `User` modeli). + +Ancak belirli bir data model, class ya da type kullanmak zorunda deฤŸilsiniz. + +Modelinizde bir `id` ve `email` olsun, ama `username` olmasฤฑn mฤฑ istiyorsunuz? Elbette. Aynฤฑ araรงlarฤฑ kullanabilirsiniz. + +Sadece bir `str` mฤฑ istiyorsunuz? Ya da sadece bir `dict`? Veya doฤŸrudan bir veritabanฤฑ class model instance'ฤฑ? Hepsi aynฤฑ ลŸekilde รงalฤฑลŸฤฑr. + +Uygulamanฤฑza giriลŸ yapan kullanฤฑcฤฑlar yok da robotlar, botlar veya yalnฤฑzca bir access token'a sahip baลŸka sistemler mi var? Yine, her ลŸey aynฤฑ ลŸekilde รงalฤฑลŸฤฑr. + +Uygulamanฤฑz iรงin neye ihtiyacฤฑnฤฑz varsa o tรผrden bir model, class ve veritabanฤฑ kullanฤฑn. **FastAPI**, dependency injection sistemiyle bunlarฤฑ destekler. + +## Kod boyutu { #code-size } + +Bu รถrnek biraz uzun gรถrรผnebilir. Gรผvenlik, data model'ler, utility fonksiyonlar ve *path operation*'larฤฑ aynฤฑ dosyada bir araya getirdiฤŸimizi unutmayฤฑn. + +Ama kritik nokta ลŸu: + +Gรผvenlik ve dependency injection tarafฤฑnฤฑ bir kez yazarsฤฑnฤฑz. + +ฤฐstediฤŸiniz kadar karmaลŸฤฑk hรขle getirebilirsiniz. Yine de hepsi tek bir yerde ve sadece bir kez yazฤฑlmฤฑลŸ olur. รœstelik tรผm esneklikle. + +Sonrasฤฑnda aynฤฑ gรผvenlik sistemini kullanan binlerce endpoint (*path operation*) olabilir. + +Ve bunlarฤฑn hepsi (ya da istediฤŸiniz bir kฤฑsmฤฑ) bu dependency'leri veya oluลŸturacaฤŸฤฑnฤฑz baลŸka dependency'leri yeniden kullanmaktan faydalanabilir. + +Hatta bu binlerce *path operation* 3 satฤฑr kadar kฤฑsa olabilir: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## ร–zet { #recap } + +Artฤฑk *path operation function* iรงinde mevcut kullanฤฑcฤฑyฤฑ doฤŸrudan alabilirsiniz. + +Yolun yarฤฑsฤฑna geldik. + +Kullanฤฑcฤฑnฤฑn/istemcinin gerรงekten `username` ve `password` gรถndermesini saฤŸlayacak bir *path operation* eklememiz gerekiyor. + +Sฤฑrada bu var. diff --git a/docs/tr/docs/tutorial/security/index.md b/docs/tr/docs/tutorial/security/index.md new file mode 100644 index 0000000000..a592db6df5 --- /dev/null +++ b/docs/tr/docs/tutorial/security/index.md @@ -0,0 +1,106 @@ +# Gรผvenlik { #security } + +Gรผvenlik, authentication ve authorizationโ€™ฤฑ ele almanฤฑn birรงok yolu vardฤฑr. + +Ve bu konu genellikle karmaลŸฤฑk ve "zor"dur. + +Birรงok framework ve sistemde yalnฤฑzca security ve authenticationโ€™ฤฑ yรถnetmek bile ciddi miktarda emek ve kod gerektirir (รงoฤŸu durumda yazฤฑlan toplam kodun %50โ€™si veya daha fazlasฤฑ olabilir). + +**FastAPI**, tรผm security spesifikasyonlarฤฑnฤฑ baลŸtan sona inceleyip รถฤŸrenmek zorunda kalmadan **Security** konusunu kolay, hฤฑzlฤฑ ve standart bir ลŸekilde ele almanฤฑza yardฤฑmcฤฑ olacak รงeลŸitli araรงlar sunar. + +Ama รถnce, kรผรงรผk birkaรง kavrama bakalฤฑm. + +## Acelem var? { #in-a-hurry } + +Bu terimlerin hiรงbirini umursamฤฑyorsanฤฑz ve sadece kullanฤฑcฤฑ adฤฑ ve parola tabanlฤฑ authentication ile securityโ€™yi *hemen ลŸimdi* eklemeniz gerekiyorsa, bir sonraki bรถlรผmlere geรงin. + +## OAuth2 { #oauth2 } + +OAuth2, authentication ve authorizationโ€™ฤฑ yรถnetmek iรงin รงeลŸitli yรถntemleri tanฤฑmlayan bir spesifikasyondur. + +Oldukรงa kapsamlฤฑ bir spesifikasyondur ve birkaรง karmaลŸฤฑk use caseโ€™i kapsar. + +"รœรงรผncรผ taraf" kullanarak authentication yapmanฤฑn yollarฤฑnฤฑ da iรงerir. + +"Facebook, Google, X (Twitter), GitHub ile giriลŸ yap" bulunan sistemlerin arka planda kullandฤฑฤŸฤฑ ลŸey de budur. + +### OAuth 1 { #oauth-1 } + +OAuth 1 de vardฤฑ; OAuth2โ€™den รงok farklฤฑdฤฑr ve daha karmaลŸฤฑktฤฑr, รงรผnkรผ iletiลŸimi nasฤฑl ลŸifreleyeceฤŸinize dair doฤŸrudan spesifikasyonlar iรงeriyordu. + +Gรผnรผmรผzde pek popรผler deฤŸildir veya pek kullanฤฑlmaz. + +OAuth2 ise iletiลŸimin nasฤฑl ลŸifreleneceฤŸini belirtmez; uygulamanฤฑzฤฑn HTTPS ile sunulmasฤฑnฤฑ bekler. + +/// tip | ฤฐpucu + +**deployment** bรถlรผmรผnde Traefik ve Let's Encrypt kullanarak รผcretsiz ลŸekilde HTTPSโ€™i nasฤฑl kuracaฤŸฤฑnฤฑzฤฑ gรถreceksiniz. + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect, **OAuth2** tabanlฤฑ baลŸka bir spesifikasyondur. + +OAuth2โ€™de nispeten belirsiz kalan bazฤฑ noktalarฤฑ tanฤฑmlayarak onu daha birlikte รงalฤฑลŸabilir (interoperable) hรขle getirmeye รงalฤฑลŸฤฑr. + +ร–rneฤŸin, Google ile giriลŸ OpenID Connect kullanฤฑr (arka planda OAuth2 kullanฤฑr). + +Ancak Facebook ile giriลŸ OpenID Connectโ€™i desteklemez. Kendine รถzgรผ bir OAuth2 รงeลŸidi vardฤฑr. + +### OpenID ("OpenID Connect" deฤŸil) { #openid-not-openid-connect } + +Bir de "OpenID" spesifikasyonu vardฤฑ. Bu da **OpenID Connect** ile aynฤฑ problemi รงรถzmeye รงalฤฑลŸฤฑyordu ama OAuth2 tabanlฤฑ deฤŸildi. + +Dolayฤฑsฤฑyla tamamen ayrฤฑ, ek bir sistemdi. + +Gรผnรผmรผzde pek popรผler deฤŸildir veya pek kullanฤฑlmaz. + +## OpenAPI { #openapi } + +OpenAPI (รถnceden Swagger olarak biliniyordu), APIโ€™ler inลŸa etmek iรงin aรงฤฑk spesifikasyondur (artฤฑk Linux Foundationโ€™ฤฑn bir parรงasฤฑ). + +**FastAPI**, **OpenAPI** tabanlฤฑdฤฑr. + +Bu sayede birden fazla otomatik etkileลŸimli dokรผmantasyon arayรผzรผ, code generation vb. mรผmkรผn olur. + +OpenAPI, birden fazla security "scheme" tanฤฑmlamanฤฑn bir yolunu sunar. + +Bunlarฤฑ kullanarak, etkileลŸimli dokรผmantasyon sistemleri de dahil olmak รผzere tรผm bu standart tabanlฤฑ araรงlardan faydalanabilirsiniz. + +OpenAPI ลŸu security schemeโ€™lerini tanฤฑmlar: + +* `apiKey`: uygulamaya รถzel bir anahtar; ลŸuradan gelebilir: + * Bir query parameter. + * Bir header. + * Bir cookie. +* `http`: standart HTTP authentication sistemleri, รถrneฤŸin: + * `bearer`: `Authorization` headerโ€™ฤฑ; deฤŸeri `Bearer ` + bir token olacak ลŸekilde. Bu, OAuth2โ€™den gelir. + * HTTP Basic authentication. + * HTTP Digest, vb. +* `oauth2`: OAuth2 ile securityโ€™yi yรถnetmenin tรผm yollarฤฑ ("flow" olarak adlandฤฑrฤฑlฤฑr). + * Bu flowโ€™larฤฑn birรงoฤŸu, bir OAuth 2.0 authentication provider (Google, Facebook, X (Twitter), GitHub vb.) oluลŸturmak iรงin uygundur: + * `implicit` + * `clientCredentials` + * `authorizationCode` + * Ancak, aynฤฑ uygulamanฤฑn iรงinde doฤŸrudan authentication yรถnetmek iรงin mรผkemmel ลŸekilde kullanฤฑlabilecek รถzel bir "flow" vardฤฑr: + * `password`: sonraki bazฤฑ bรถlรผmlerde bunun รถrnekleri ele alฤฑnacak. +* `openIdConnect`: OAuth2 authentication verisinin otomatik olarak nasฤฑl keลŸfedileceฤŸini tanฤฑmlamanฤฑn bir yolunu sunar. + * Bu otomatik keลŸif, OpenID Connect spesifikasyonunda tanฤฑmlanan ลŸeydir. + + +/// tip | ฤฐpucu + +Google, Facebook, X (Twitter), GitHub vb. gibi diฤŸer authentication/authorization providerโ€™larฤฑnฤฑ entegre etmek de mรผmkรผndรผr ve nispeten kolaydฤฑr. + +En karmaลŸฤฑk kฤฑsฤฑm, bu tรผr bir authentication/authorization providerโ€™ฤฑ inลŸa etmektir; ancak **FastAPI** aฤŸฤฑr iลŸleri sizin yerinize yaparken bunu kolayca yapabilmeniz iรงin araรงlar sunar. + +/// + +## **FastAPI** yardฤฑmcฤฑ araรงlarฤฑ { #fastapi-utilities } + +FastAPI, `fastapi.security` modรผlรผnde bu security schemeโ€™lerinin her biri iรงin, bu mekanizmalarฤฑ kullanmayฤฑ kolaylaลŸtฤฑran รงeลŸitli araรงlar saฤŸlar. + +Sonraki bรถlรผmlerde, **FastAPI**โ€™nin sunduฤŸu bu araรงlarฤฑ kullanarak APIโ€™nize nasฤฑl security ekleyeceฤŸinizi gรถreceksiniz. + +Ayrฤฑca bunun etkileลŸimli dokรผmantasyon sistemine nasฤฑl otomatik olarak entegre edildiฤŸini de gรถreceksiniz. diff --git a/docs/tr/docs/tutorial/security/oauth2-jwt.md b/docs/tr/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 0000000000..716761157c --- /dev/null +++ b/docs/tr/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,273 @@ +# Password ile OAuth2 (ve hashing), JWT token'larฤฑ ile Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +Artฤฑk tรผm security flow elimizde olduฤŸuna gรถre, uygulamayฤฑ gerรงekten gรผvenli hรขle getirelim: JWT token'larฤฑ ve gรผvenli password hashing kullanacaฤŸฤฑz. + +Bu kodu uygulamanฤฑzda gerรงekten kullanabilirsiniz; password hash'lerini veritabanฤฑnฤฑza kaydedebilirsiniz, vb. + +Bir รถnceki bรถlรผmde bฤฑraktฤฑฤŸฤฑmฤฑz yerden baลŸlayฤฑp รผzerine ekleyerek ilerleyeceฤŸiz. + +## JWT Hakkฤฑnda { #about-jwt } + +JWT, "JSON Web Tokens" anlamฤฑna gelir. + +Bir JSON nesnesini, boลŸluk iรงermeyen uzun ve yoฤŸun bir string'e kodlamak iรงin kullanฤฑlan bir standarttฤฑr. ลžuna benzer: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +ลžifrelenmiลŸ deฤŸildir; yani herkes iรงeriฤŸindeki bilgiyi geri รงฤฑkarabilir. + +Ancak imzalanmฤฑลŸtฤฑr. Bu yรผzden, sizin รผrettiฤŸiniz bir token'ฤฑ aldฤฑฤŸฤฑnฤฑzda, gerรงekten onu sizin รผrettiฤŸinizi doฤŸrulayabilirsiniz. + +Bu ลŸekilde, รถrneฤŸin 1 haftalฤฑk sรผre sonu (expiration) olan bir token oluลŸturabilirsiniz. Sonra kullanฤฑcฤฑ ertesi gรผn token ile geri geldiฤŸinde, kullanฤฑcฤฑnฤฑn hรขlรข sisteminizde oturum aรงmฤฑลŸ olduฤŸunu bilirsiniz. + +Bir hafta sonra token'ฤฑn sรผresi dolar; kullanฤฑcฤฑ yetkilendirilmez ve yeni bir token almak iรงin tekrar giriลŸ yapmak zorunda kalฤฑr. Ayrฤฑca kullanฤฑcฤฑ (veya รผรงรผncรผ bir taraf) token'ฤฑ deฤŸiลŸtirip sรผre sonunu farklฤฑ gรถstermek isterse bunu tespit edebilirsiniz; รงรผnkรผ imzalar eลŸleลŸmez. + +JWT token'larฤฑyla oynayฤฑp nasฤฑl รงalฤฑลŸtฤฑklarฤฑnฤฑ gรถrmek isterseniz https://jwt.io adresine bakฤฑn. + +## `PyJWT` Kurulumu { #install-pyjwt } + +Python'da JWT token'larฤฑnฤฑ รผretmek ve doฤŸrulamak iรงin `PyJWT` kurmamฤฑz gerekiyor. + +Bir [virtual environment](../../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, aktif edin ve ardฤฑndan `pyjwt` kurun: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info | Bilgi + +RSA veya ECDSA gibi dijital imza algoritmalarฤฑ kullanmayฤฑ planlฤฑyorsanฤฑz, `pyjwt[crypto]` baฤŸฤฑmlฤฑlฤฑฤŸฤฑ olan `cryptography` kรผtรผphanesini kurmalฤฑsฤฑnฤฑz. + +Daha fazla bilgi iรงin PyJWT Installation docs sayfasฤฑnฤฑ okuyabilirsiniz. + +/// + +## Password hashing { #password-hashing } + +"Hashing", bazฤฑ iรงerikleri (bu รถrnekte bir password) anlamsฤฑz gรถrรผnen bir bayt dizisine (pratikte bir string) dรถnรผลŸtรผrmek demektir. + +Aynฤฑ iรงeriฤŸi (aynฤฑ password'รผ) her seferinde verirseniz, her seferinde aynฤฑ anlamsฤฑz รงฤฑktฤฑyฤฑ elde edersiniz. + +Ancak bu anlamsฤฑz รงฤฑktฤฑdan geri password'e dรถnรผลŸtรผrme yapฤฑlamaz. + +### Neden password hashing kullanฤฑlฤฑr { #why-use-password-hashing } + +Veritabanฤฑnฤฑz รงalฤฑnฤฑrsa, hฤฑrsฤฑz kullanฤฑcฤฑlarฤฑnฤฑzฤฑn dรผz metin (plaintext) password'lerini deฤŸil, sadece hash'leri elde eder. + +Dolayฤฑsฤฑyla, o password'รผ baลŸka bir sistemde denemek kolay olmaz (pek รงok kullanฤฑcฤฑ her yerde aynฤฑ password'รผ kullandฤฑฤŸฤฑ iรงin bu tehlikeli olurdu). + +## `pwdlib` Kurulumu { #install-pwdlib } + +pwdlib, password hash'leriyle รงalฤฑลŸmak iรงin รงok iyi bir Python paketidir. + +Birรงok gรผvenli hashing algoritmasฤฑnฤฑ ve bunlarla รงalฤฑลŸmak iรงin yardฤฑmcฤฑ araรงlarฤฑ destekler. + +ร–nerilen algoritma "Argon2"dir. + +Bir [virtual environment](../../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, aktif edin ve sonra Argon2 ile birlikte pwdlib'i kurun: + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | ฤฐpucu + +`pwdlib` ile, **Django** tarafฤฑndan oluลŸturulmuลŸ password'leri, bir **Flask** security eklentisinin รผrettiklerini veya baลŸka birรงok kaynaktan gelen password'leri okuyabilecek ลŸekilde bile yapฤฑlandฤฑrabilirsiniz. + +Bรถylece รถrneฤŸin bir Django uygulamasฤฑndaki verileri aynฤฑ veritabanฤฑnda bir FastAPI uygulamasฤฑyla paylaลŸabilirsiniz. Ya da aynฤฑ veritabanฤฑnฤฑ kullanarak bir Django uygulamasฤฑnฤฑ kademeli ลŸekilde taลŸฤฑyabilirsiniz. + +Ayrฤฑca kullanฤฑcฤฑlarฤฑnฤฑz, aynฤฑ anda hem Django uygulamanฤฑzdan hem de **FastAPI** uygulamanฤฑzdan login olabilir. + +/// + +## Password'leri hash'leme ve doฤŸrulama { #hash-and-verify-the-passwords } + +Gerekli araรงlarฤฑ `pwdlib` iรงinden import edelim. + +ร–nerilen ayarlarla bir PasswordHash instance'ฤฑ oluลŸturalฤฑm; bunu password'leri hash'lemek ve doฤŸrulamak iรงin kullanacaฤŸฤฑz. + +/// tip | ฤฐpucu + +pwdlib, bcrypt hashing algoritmasฤฑnฤฑ da destekler; ancak legacy algoritmalarฤฑ iรงermez. Eski hash'lerle รงalฤฑลŸmak iรงin passlib kรผtรผphanesini kullanmanฤฑz รถnerilir. + +ร–rneฤŸin, baลŸka bir sistemin (Django gibi) รผrettiฤŸi password'leri okuyup doฤŸrulayabilir, ancak yeni password'leri Argon2 veya Bcrypt gibi farklฤฑ bir algoritmayla hash'leyebilirsiniz. + +Ve aynฤฑ anda hepsiyle uyumlu kalabilirsiniz. + +/// + +Kullanฤฑcฤฑdan gelen password'รผ hash'lemek iรงin bir yardฤฑmcฤฑ (utility) fonksiyon oluลŸturalฤฑm. + +Sonra, alฤฑnan password'รผn kayฤฑttaki hash ile eลŸleลŸip eลŸleลŸmediฤŸini doฤŸrulayan baลŸka bir yardฤฑmcฤฑ fonksiyon yazalฤฑm. + +Bir tane de kullanฤฑcฤฑyฤฑ authenticate edip geri dรถndรผren bir yardฤฑmcฤฑ fonksiyon ekleyelim. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} + +/// note | Not + +Yeni (sahte) veritabanฤฑ `fake_users_db`'ye bakarsanฤฑz, hash'lenmiลŸ password'รผn artฤฑk nasฤฑl gรถrรผndรผฤŸรผnรผ gรถrebilirsiniz: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + +/// + +## JWT token'larฤฑnฤฑ yรถnetme { #handle-jwt-tokens } + +Kurulu modรผlleri import edelim. + +JWT token'larฤฑnฤฑ imzalamak iรงin kullanฤฑlacak rastgele bir secret key oluลŸturalฤฑm. + +Gรผvenli, rastgele bir secret key รผretmek iรงin ลŸu komutu kullanฤฑn: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +ร‡ฤฑktฤฑyฤฑ `SECRET_KEY` deฤŸiลŸkenine kopyalayฤฑn (รถrnektekini kullanmayฤฑn). + +JWT token'ฤฑnฤฑ imzalamak iรงin kullanฤฑlan algoritmayฤฑ tutacak `ALGORITHM` adlฤฑ bir deฤŸiลŸken oluลŸturup deฤŸerini `"HS256"` yapฤฑn. + +Token'ฤฑn sรผre sonu (expiration) iรงin bir deฤŸiลŸken oluลŸturun. + +Response iรงin token endpoint'inde kullanฤฑlacak bir Pydantic Model tanฤฑmlayฤฑn. + +Yeni bir access token รผretmek iรงin bir yardฤฑmcฤฑ fonksiyon oluลŸturun. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} + +## Dependency'leri gรผncelleme { #update-the-dependencies } + +`get_current_user` fonksiyonunu, รถncekiyle aynฤฑ token'ฤฑ alacak ลŸekilde gรผncelleyelim; ancak bu sefer JWT token'larฤฑnฤฑ kullanacaฤŸฤฑz. + +Gelen token'ฤฑ decode edin, doฤŸrulayฤฑn ve mevcut kullanฤฑcฤฑyฤฑ dรถndรผrรผn. + +Token geรงersizse, hemen bir HTTP hatasฤฑ dรถndรผrรผn. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} + +## `/token` *path operation*'ฤฑnฤฑ gรผncelleme { #update-the-token-path-operation } + +Token'ฤฑn sรผre sonu iรงin bir `timedelta` oluลŸturun. + +Gerรงek bir JWT access token รผretip dรถndรผrรผn. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} + +### JWT "subject" `sub` Hakkฤฑnda Teknik Detaylar { #technical-details-about-the-jwt-subject-sub } + +JWT spesifikasyonu, token'ฤฑn konusu (subject) iรงin `sub` adlฤฑ bir anahtar olduฤŸunu sรถyler. + +Bunu kullanmak zorunlu deฤŸildir; ancak kullanฤฑcฤฑ kimliฤŸini koymak iรงin uygun yer burasฤฑdฤฑr, bu yรผzden burada onu kullanฤฑyoruz. + +JWT, sadece bir kullanฤฑcฤฑyฤฑ tanฤฑmlamak ve API'nizde doฤŸrudan iลŸlem yapmasฤฑna izin vermek dฤฑลŸฤฑnda baลŸka amaรงlarla da kullanฤฑlabilir. + +ร–rneฤŸin bir "araba"yฤฑ veya bir "blog post"u tanฤฑmlayabilirsiniz. + +Sonra o varlฤฑk iรงin izinler ekleyebilirsiniz; รถrneฤŸin (araba iรงin) "drive" ya da (blog iรงin) "edit". + +Ardฤฑndan bu JWT token'ฤฑnฤฑ bir kullanฤฑcฤฑya (veya bot'a) verebilirsiniz; onlar da, hesaplarฤฑ olmasฤฑna bile gerek kalmadan, sadece API'nizin bunun iรงin รผrettiฤŸi JWT token'ฤฑyla bu aksiyonlarฤฑ gerรงekleลŸtirebilir (arabayฤฑ sรผrmek veya blog post'u dรผzenlemek gibi). + +Bu fikirlerle JWT, รงok daha geliลŸmiลŸ senaryolarda kullanฤฑlabilir. + +Bu durumlarda, birden fazla varlฤฑฤŸฤฑn aynฤฑ ID'ye sahip olmasฤฑ mรผmkรผndรผr; รถrneฤŸin `foo` (kullanฤฑcฤฑ `foo`, araba `foo`, blog post `foo`). + +Dolayฤฑsฤฑyla ID รงakฤฑลŸmalarฤฑnฤฑ รถnlemek iรงin, kullanฤฑcฤฑ iรงin JWT token oluลŸtururken `sub` anahtarฤฑnฤฑn deฤŸerine bir รถnek ekleyebilirsiniz; รถrneฤŸin `username:`. Bu รถrnekte `sub` deฤŸeri ลŸรถyle olabilirdi: `username:johndoe`. + +Unutmamanฤฑz gereken รถnemli nokta ลŸudur: `sub` anahtarฤฑ, tรผm uygulama genelinde benzersiz bir tanฤฑmlayฤฑcฤฑ olmalฤฑ ve string olmalฤฑdฤฑr. + +## Kontrol Edelim { #check-it } + +Server'ฤฑ รงalฤฑลŸtฤฑrฤฑn ve docs'a gidin: http://127.0.0.1:8000/docs. + +ลžuna benzer bir arayรผz gรถreceksiniz: + + + +Uygulamayฤฑ, รถncekiyle aynฤฑ ลŸekilde authorize edin. + +ลžu kimlik bilgilerini kullanarak: + +Username: `johndoe` +Password: `secret` + +/// check | Ek bilgi + +Kodun hiรงbir yerinde dรผz metin password "`secret`" yok; sadece hash'lenmiลŸ hรขli var. + +/// + + + +`/users/me/` endpoint'ini รงaฤŸฤฑrฤฑn; response ลŸรถyle olacaktฤฑr: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +Developer tools'u aรงarsanฤฑz, gรถnderilen verinin sadece token'ฤฑ iรงerdiฤŸini gรถrebilirsiniz. Password sadece kullanฤฑcฤฑyฤฑ authenticate edip access token almak iรงin yapฤฑlan ilk request'te gรถnderilir, sonrasฤฑnda gรถnderilmez: + + + +/// note | Not + +`Authorization` header'ฤฑna dikkat edin; deฤŸeri `Bearer ` ile baลŸlฤฑyor. + +/// + +## `scopes` ile ฤฐleri Seviye Kullanฤฑm { #advanced-usage-with-scopes } + +OAuth2'nin "scopes" kavramฤฑ vardฤฑr. + +Bunlarฤฑ kullanarak bir JWT token'a belirli bir izin seti ekleyebilirsiniz. + +Sonra bu token'ฤฑ bir kullanฤฑcฤฑya doฤŸrudan veya bir รผรงรผncรผ tarafa verip, API'nizle belirli kฤฑsฤฑtlarla etkileลŸime girmesini saฤŸlayabilirsiniz. + +Nasฤฑl kullanฤฑldฤฑklarฤฑnฤฑ ve **FastAPI** ile nasฤฑl entegre olduklarฤฑnฤฑ, ileride **Advanced User Guide** iรงinde รถฤŸreneceksiniz. + +## ร–zet { #recap } + +ลžimdiye kadar gรถrdรผklerinizle, OAuth2 ve JWT gibi standartlarฤฑ kullanarak gรผvenli bir **FastAPI** uygulamasฤฑ kurabilirsiniz. + +Neredeyse her framework'te security'yi ele almak oldukรงa hฤฑzlฤฑ bir ลŸekilde karmaลŸฤฑk bir konu hรขline gelir. + +Bunu รงok basitleลŸtiren birรงok paket, veri modeli, veritabanฤฑ ve mevcut รถzelliklerle ilgili pek รงok รถdรผn vermek zorunda kalฤฑr. Hatta bazฤฑlarฤฑ iลŸi aลŸฤฑrฤฑ basitleลŸtirirken arka planda gรผvenlik aรงฤฑklarฤฑ da barฤฑndฤฑrฤฑr. + +--- + +**FastAPI**, hiรงbir veritabanฤฑ, veri modeli veya araรง konusunda รถdรผn vermez. + +Projenize en uygun olanlarฤฑ seรงebilmeniz iรงin size tam esneklik saฤŸlar. + +Ayrฤฑca `pwdlib` ve `PyJWT` gibi iyi bakฤฑmฤฑ yapฤฑlan ve yaygฤฑn kullanฤฑlan paketleri doฤŸrudan kullanabilirsiniz; รงรผnkรผ **FastAPI**, haricรฎ paketleri entegre etmek iรงin karmaลŸฤฑk mekanizmalara ihtiyaรง duymaz. + +Buna raฤŸmen, esneklikten, saฤŸlamlฤฑktan veya gรผvenlikten รถdรผn vermeden sรผreci mรผmkรผn olduฤŸunca basitleลŸtiren araรงlarฤฑ saฤŸlar. + +Ve OAuth2 gibi gรผvenli, standart protokolleri nispeten basit bir ลŸekilde kullanabilir ve uygulayabilirsiniz. + +Aynฤฑ standartlarฤฑ izleyerek, daha ince taneli (fine-grained) bir izin sistemi iรงin OAuth2 "scopes" kullanฤฑmฤฑnฤฑ **Advanced User Guide** iรงinde daha detaylฤฑ รถฤŸrenebilirsiniz. Scopes'lu OAuth2; Facebook, Google, GitHub, Microsoft, X (Twitter) vb. pek รงok bรผyรผk kimlik doฤŸrulama saฤŸlayฤฑcฤฑsฤฑnฤฑn, รผรงรผncรผ taraf uygulamalarฤฑn kullanฤฑcฤฑlarฤฑ adฤฑna API'leriyle etkileลŸebilmesine izin vermek iรงin kullandฤฑฤŸฤฑ mekanizmadฤฑr. diff --git a/docs/tr/docs/tutorial/security/simple-oauth2.md b/docs/tr/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000..88efd98e51 --- /dev/null +++ b/docs/tr/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# Password ve Bearer ile Basit OAuth2 { #simple-oauth2-with-password-and-bearer } + +ลžimdi รถnceki bรถlรผmรผn รผzerine inลŸa edip, eksik parรงalarฤฑ ekleyerek tam bir gรผvenlik akฤฑลŸฤฑ oluลŸturalฤฑm. + +## `username` ve `password`โ€™รผ Alma { #get-the-username-and-password } + +`username` ve `password`โ€™รผ almak iรงin **FastAPI** security yardฤฑmcฤฑ araรงlarฤฑnฤฑ kullanacaฤŸฤฑz. + +OAuth2, (bizim kullandฤฑฤŸฤฑmฤฑz) "password flow" kullanฤฑlฤฑrken client/kullanฤฑcฤฑnฤฑn form verisi olarak `username` ve `password` alanlarฤฑnฤฑ gรถndermesi gerektiฤŸini belirtir. + +Ayrฤฑca spesifikasyon, bu alanlarฤฑn adlarฤฑnฤฑn tam olarak bรถyle olmasฤฑ gerektiฤŸini sรถyler. Yani `user-name` veya `email` iลŸe yaramaz. + +Ancak merak etmeyin, frontendโ€™de son kullanฤฑcฤฑlarฤฑnฤฑza dilediฤŸiniz gibi gรถsterebilirsiniz. + +Veritabanฤฑ model(ler)inizde de istediฤŸiniz baลŸka isimleri kullanabilirsiniz. + +Fakat login *path operation*โ€™ฤฑ iรงin, spesifikasyonla uyumlu olmak (ve รถrneฤŸin entegre API dokรผmantasyon sistemini kullanabilmek) adฤฑna bu isimleri kullanmamฤฑz gerekiyor. + +Spesifikasyon ayrฤฑca `username` ve `password`โ€™รผn form verisi olarak gรถnderilmesi gerektiฤŸini de sรถyler (yani burada JSON yok). + +### `scope` { #scope } + +Spesifikasyon, clientโ€™ฤฑn "`scope`" adlฤฑ baลŸka bir form alanฤฑ da gรถnderebileceฤŸini sรถyler. + +Form alanฤฑnฤฑn adฤฑ `scope`โ€™tur (tekil), ama aslฤฑnda boลŸluklarla ayrฤฑlmฤฑลŸ "scope"โ€™lardan oluลŸan uzun bir stringโ€™dir. + +Her bir "scope" sadece bir stringโ€™dir (boลŸluk iรงermez). + +Genelde belirli gรผvenlik izinlerini (permission) belirtmek iรงin kullanฤฑlฤฑrlar, รถrneฤŸin: + +* `users:read` veya `users:write` yaygฤฑn รถrneklerdir. +* `instagram_basic` Facebook / Instagram tarafฤฑndan kullanฤฑlฤฑr. +* `https://www.googleapis.com/auth/drive` Google tarafฤฑndan kullanฤฑlฤฑr. + +/// info | Bilgi + +OAuth2โ€™de bir "scope", gerekli olan belirli bir izni ifade eden basit bir stringโ€™dir. + +`:` gibi baลŸka karakterler iรงermesi veya URL olmasฤฑ รถnemli deฤŸildir. + +Bu detaylar implementasyonโ€™a รถzeldir. + +OAuth2 aรงฤฑsฤฑndan bunlar sadece stringโ€™lerdir. + +/// + +## `username` ve `password`โ€™รผ Almak ฤฐรงin Kod { #code-to-get-the-username-and-password } + +ลžimdi bunu yรถnetmek iรงin **FastAPI**โ€™nin saฤŸladฤฑฤŸฤฑ araรงlarฤฑ kullanalฤฑm. + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +ร–nce `OAuth2PasswordRequestForm`โ€™u import edin ve `/token` iรงin *path operation* iรงinde `Depends` ile dependency olarak kullanฤฑn: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm`, ลŸu alanlarฤฑ iรงeren bir form body tanฤฑmlayan bir class dependencyโ€™sidir: + +* `username`. +* `password`. +* BoลŸlukla ayrฤฑlmฤฑลŸ stringโ€™lerden oluลŸan bรผyรผk bir string olarak opsiyonel `scope` alanฤฑ. +* Opsiyonel `grant_type`. + +/// tip | ฤฐpucu + +OAuth2 spesifikasyonu aslฤฑnda `grant_type` alanฤฑnฤฑ sabit bir `password` deฤŸeriyle *zorunlu kฤฑlar*, ancak `OAuth2PasswordRequestForm` bunu zorlamaz. + +Bunu zorlamak istiyorsanฤฑz, `OAuth2PasswordRequestForm` yerine `OAuth2PasswordRequestFormStrict` kullanฤฑn. + +/// + +* Opsiyonel `client_id` (bu รถrnekte ihtiyacฤฑmฤฑz yok). +* Opsiyonel `client_secret` (bu รถrnekte ihtiyacฤฑmฤฑz yok). + +/// info | Bilgi + +`OAuth2PasswordRequestForm`, `OAuth2PasswordBearer` gibi **FastAPI**โ€™ye รถzel โ€œรถzel bir sฤฑnฤฑfโ€ deฤŸildir. + +`OAuth2PasswordBearer`, bunun bir security scheme olduฤŸunu **FastAPI**โ€™ye bildirir. Bu yรผzden OpenAPIโ€™ye o ลŸekilde eklenir. + +Ama `OAuth2PasswordRequestForm` sadece bir class dependencyโ€™dir; bunu kendiniz de yazabilirdiniz ya da doฤŸrudan `Form` parametreleri tanฤฑmlayabilirdiniz. + +Fakat รงok yaygฤฑn bir kullanฤฑm olduฤŸu iรงin **FastAPI** bunu iลŸleri kolaylaลŸtฤฑrmak adฤฑna doฤŸrudan saฤŸlar. + +/// + +### Form Verisini Kullanma { #use-the-form-data } + +/// tip | ฤฐpucu + +`OAuth2PasswordRequestForm` dependency classโ€™ฤฑnฤฑn instanceโ€™ฤฑnda boลŸluklarla ayrฤฑlmฤฑลŸ uzun string olarak bir `scope` attributeโ€™u olmaz; bunun yerine gรถnderilen her scope iรงin gerรงek string listesini iรงeren `scopes` attributeโ€™u olur. + +Bu รถrnekte `scopes` kullanmฤฑyoruz, ama ihtiyacฤฑnฤฑz olursa bu รถzellik hazฤฑr. + +/// + +ลžimdi form alanฤฑndaki `username`โ€™i kullanarak (sahte) veritabanฤฑndan kullanฤฑcฤฑ verisini alฤฑn. + +Bรถyle bir kullanฤฑcฤฑ yoksa, "Incorrect username or password" diyerek bir hata dรถndรผrelim. + +Hata iรงin `HTTPException` exceptionโ€™ฤฑnฤฑ kullanฤฑyoruz: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### Passwordโ€™รผ Kontrol Etme { #check-the-password } + +Bu noktada veritabanฤฑndan kullanฤฑcฤฑ verisine sahibiz, ancak passwordโ€™รผ henรผz kontrol etmedik. + +ร–nce bu veriyi Pydantic `UserInDB` modeline koyalฤฑm. + +Asla dรผz metin (plaintext) password kaydetmemelisiniz; bu yรผzden (sahte) password hashing sistemini kullanacaฤŸฤฑz. + +Passwordโ€™ler eลŸleลŸmezse, aynฤฑ hatayฤฑ dรถndรผrรผrรผz. + +#### Password hashing { #password-hashing } + +"Hashing" ลŸudur: bir iรงeriฤŸi (bu รถrnekte password) anlaลŸฤฑlmaz gรถrรผnen bayt dizisine (yani bir stringโ€™e) dรถnรผลŸtรผrmek. + +Aynฤฑ iรงeriฤŸi (aynฤฑ passwordโ€™รผ) her verdiฤŸinizde, birebir aynฤฑ anlamsฤฑz gรถrรผnen รงฤฑktฤฑyฤฑ elde edersiniz. + +Ama bu anlamsฤฑz รงฤฑktฤฑyฤฑ tekrar passwordโ€™e geri รงeviremezsiniz. + +##### Neden password hashing kullanฤฑlฤฑr { #why-use-password-hashing } + +Veritabanฤฑnฤฑz รงalฤฑnฤฑrsa, hฤฑrsฤฑz kullanฤฑcฤฑlarฤฑnฤฑzฤฑn dรผz metin passwordโ€™lerine deฤŸil, sadece hashโ€™lere sahip olur. + +Dolayฤฑsฤฑyla hฤฑrsฤฑz, aynฤฑ passwordโ€™leri baลŸka bir sistemde denemeye รงalฤฑลŸamaz (birรงok kullanฤฑcฤฑ her yerde aynฤฑ passwordโ€™รผ kullandฤฑฤŸฤฑ iรงin bu tehlikeli olurdu). + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### `**user_dict` Hakkฤฑnda { #about-user-dict } + +`UserInDB(**user_dict)` ลŸu anlama gelir: + +*`user_dict` iรงindeki key ve valueโ€™larฤฑ doฤŸrudan key-value argรผmanlarฤฑ olarak geรงir; ลŸu ifadeyle eลŸdeฤŸerdir:* + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// info | Bilgi + +`**user_dict` iรงin daha kapsamlฤฑ bir aรงฤฑklama iรงin [**Extra Models** dokรผmantasyonundaki ilgili bรถlรผme](../extra-models.md#about-user-in-dict){.internal-link target=_blank} geri dรถnรผp bakฤฑn. + +/// + +## Tokenโ€™ฤฑ Dรถndรผrme { #return-the-token } + +`token` endpointโ€™inin responseโ€™u bir JSON object olmalฤฑdฤฑr. + +Bir `token_type` iรงermelidir. Biz "Bearer" tokenโ€™larฤฑ kullandฤฑฤŸฤฑmฤฑz iรงin token type "`bearer`" olmalฤฑdฤฑr. + +Ayrฤฑca `access_token` iรงermelidir; bunun deฤŸeri access tokenโ€™ฤฑmฤฑzฤฑ iรงeren bir string olmalฤฑdฤฑr. + +Bu basit รถrnekte tamamen gรผvensiz davranฤฑp token olarak aynฤฑ `username`โ€™i dรถndรผreceฤŸiz. + +/// tip | ฤฐpucu + +Bir sonraki bรถlรผmde, password hashing ve JWT tokenโ€™larฤฑ ile gerรงekten gรผvenli bir implementasyon gรถreceksiniz. + +Ama ลŸimdilik ihtiyacฤฑmฤฑz olan spesifik detaylara odaklanalฤฑm. + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | ฤฐpucu + +Spesifikasyona gรถre, bu รถrnekteki gibi `access_token` ve `token_type` iรงeren bir JSON dรถndรผrmelisiniz. + +Bunu kendi kodunuzda kendiniz yapmalฤฑ ve bu JSON keyโ€™lerini kullandฤฑฤŸฤฑnฤฑzdan emin olmalฤฑsฤฑnฤฑz. + +Spesifikasyonlara uyum iรงin, doฤŸru yapmanฤฑz gereken neredeyse tek ลŸey budur. + +Geri kalanฤฑnฤฑ **FastAPI** sizin yerinize yรถnetir. + +/// + +## Dependencyโ€™leri Gรผncelleme { #update-the-dependencies } + +ลžimdi dependencyโ€™lerimizi gรผncelleyeceฤŸiz. + +`current_user`โ€™ฤฑ *sadece* kullanฤฑcฤฑ aktifse almak istiyoruz. + +Bu yรผzden, `get_current_user`โ€™ฤฑ dependency olarak kullanan ek bir dependency olan `get_current_active_user`โ€™ฤฑ oluลŸturuyoruz. + +Bu iki dependency de kullanฤฑcฤฑ yoksa veya pasifse sadece HTTP hatasฤฑ dรถndรผrecek. + +Dolayฤฑsฤฑyla endpointโ€™imizde kullanฤฑcฤฑyฤฑ ancak kullanฤฑcฤฑ varsa, doฤŸru ลŸekilde authenticate edildiyse ve aktifse alacaฤŸฤฑz: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// info | Bilgi + +Burada `Bearer` deฤŸerine sahip ek `WWW-Authenticate` headerโ€™ฤฑnฤฑ dรถndรผrmemiz de spesifikasyonun bir parรงasฤฑdฤฑr. + +Herhangi bir HTTP (hata) durum kodu 401 "UNAUTHORIZED", ayrฤฑca `WWW-Authenticate` headerโ€™ฤฑ da dรถndรผrmelidir. + +Bearer tokenโ€™lar (bizim durumumuz) iรงin bu headerโ€™ฤฑn deฤŸeri `Bearer` olmalฤฑdฤฑr. + +Aslฤฑnda bu ekstra headerโ€™ฤฑ atlayabilirsiniz, yine de รงalฤฑลŸฤฑr. + +Ama spesifikasyonlara uyumlu olmasฤฑ iรงin burada eklenmiลŸtir. + +Ayrฤฑca, bunu bekleyen ve kullanan araรงlar olabilir (ลŸimdi veya ileride) ve bu da sizin ya da kullanฤฑcฤฑlarฤฑnฤฑz iรงin faydalฤฑ olabilir. + +Standartlarฤฑn faydasฤฑ da bu... + +/// + +## ร‡alฤฑลŸฤฑr Halini Gรถrรผn { #see-it-in-action } + +EtkileลŸimli dokรผmanlarฤฑ aรงฤฑn: http://127.0.0.1:8000/docs. + +### Authenticate Olma { #authenticate } + +"Authorize" butonuna tฤฑklayฤฑn. + +ลžu bilgileri kullanฤฑn: + +User: `johndoe` + +Password: `secret` + + + +Sistemde authenticate olduktan sonra ลŸรถyle gรถrรผrsรผnรผz: + + + +### Kendi Kullanฤฑcฤฑ Verinizi Alma { #get-your-own-user-data } + +ลžimdi `/users/me` pathโ€™inde `GET` operasyonunu kullanฤฑn. + +Kullanฤฑcฤฑnฤฑzฤฑn verisini ลŸรถyle alฤฑrsฤฑnฤฑz: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +Kilit ikonuna tฤฑklayฤฑp logout olursanฤฑz ve sonra aynฤฑ operasyonu tekrar denerseniz, ลŸu ลŸekilde bir HTTP 401 hatasฤฑ alฤฑrsฤฑnฤฑz: + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### Pasif Kullanฤฑcฤฑ { #inactive-user } + +ลžimdi pasif bir kullanฤฑcฤฑyla deneyin; ลŸu bilgilerle authenticate olun: + +User: `alice` + +Password: `secret2` + +Ve `/users/me` pathโ€™inde `GET` operasyonunu kullanmayฤฑ deneyin. + +ลžรถyle bir "Inactive user" hatasฤฑ alฤฑrsฤฑnฤฑz: + +```JSON +{ + "detail": "Inactive user" +} +``` + +## ร–zet { #recap } + +Artฤฑk APIโ€™niz iรงin `username` ve `password` tabanlฤฑ, eksiksiz bir gรผvenlik sistemi implement etmek iรงin gerekli araรงlara sahipsiniz. + +Bu araรงlarla gรผvenlik sistemini herhangi bir veritabanฤฑyla ve herhangi bir user veya veri modeliyle uyumlu hale getirebilirsiniz. + +Eksik kalan tek detay, bunun henรผz gerรงekten "gรผvenli" olmamasฤฑdฤฑr. + +Bir sonraki bรถlรผmde gรผvenli bir password hashing kรผtรผphanesini ve JWT tokenโ€™larฤฑnฤฑ nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ gรถreceksiniz. diff --git a/docs/tr/docs/tutorial/sql-databases.md b/docs/tr/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..e1638cb04f --- /dev/null +++ b/docs/tr/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL (ฤฐliลŸkisel) Veritabanlarฤฑ { #sql-relational-databases } + +**FastAPI**, SQL (iliลŸkisel) bir veritabanฤฑ kullanmanฤฑzฤฑ zorunlu kฤฑlmaz. Ancak isterseniz **istediฤŸiniz herhangi bir veritabanฤฑnฤฑ** kullanabilirsiniz. + +Burada SQLModel kullanarak bir รถrnek gรถreceฤŸiz. + +**SQLModel**, SQLAlchemy ve Pydanticโ€™in รผzerine inลŸa edilmiลŸtir. **FastAPI**โ€™nin yazarฤฑ tarafฤฑndan, **SQL veritabanlarฤฑ** kullanmasฤฑ gereken FastAPI uygulamalarฤฑyla mรผkemmel uyum saฤŸlamasฤฑ iรงin geliลŸtirilmiลŸtir. + +/// tip | ฤฐpucu + +ฤฐstediฤŸiniz baลŸka bir SQL veya NoSQL veritabanฤฑ kรผtรผphanesini kullanabilirsiniz (bazฤฑ durumlarda "ORMs" olarak adlandฤฑrฤฑlฤฑr). FastAPI sizi hiรงbir ลŸeye zorlamaz. + +/// + +SQLModel, SQLAlchemy tabanlฤฑ olduฤŸu iรงin SQLAlchemyโ€™nin **desteklediฤŸi herhangi bir veritabanฤฑnฤฑ** kolayca kullanabilirsiniz (bu da SQLModel tarafฤฑndan da desteklendikleri anlamฤฑna gelir), รถrneฤŸin: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server, vb. + +Bu รถrnekte **SQLite** kullanacaฤŸฤฑz; รงรผnkรผ tek bir dosya kullanฤฑr ve Pythonโ€™da yerleลŸik desteฤŸi vardฤฑr. Yani bu รถrneฤŸi kopyalayฤฑp olduฤŸu gibi รงalฤฑลŸtฤฑrabilirsiniz. + +Daha sonra, production uygulamanฤฑz iรงin **PostgreSQL** gibi bir veritabanฤฑ sunucusu kullanmak isteyebilirsiniz. + +/// tip | ฤฐpucu + +Frontend ve daha fazla araรงla birlikte **FastAPI** + **PostgreSQL** iรงeren resmi bir proje oluลŸturucu (project generator) var: https://github.com/fastapi/full-stack-fastapi-template + +/// + +Bu รงok basit ve kฤฑsa bir eฤŸitimdir. Veritabanlarฤฑ genelinde, SQL hakkฤฑnda veya daha ileri รถzellikler hakkฤฑnda รถฤŸrenmek isterseniz SQLModel dokรผmantasyonuna gidin. + +## `SQLModel` Kurulumu { #install-sqlmodel } + +ร–nce [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, aktive edin ve ardฤฑndan `sqlmodel`โ€™i yรผkleyin: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## Tek Model ile Uygulamayฤฑ OluลŸturma { #create-the-app-with-a-single-model } + +ร–nce, tek bir **SQLModel** modeliyle uygulamanฤฑn en basit ilk sรผrรผmรผnรผ oluลŸturacaฤŸฤฑz. + +AลŸaฤŸฤฑda, **birden fazla model** kullanarak gรผvenliฤŸi ve esnekliฤŸi artฤฑrฤฑp geliลŸtireceฤŸiz. + +### Modelleri OluลŸturma { #create-models } + +`SQLModel`โ€™i import edin ve bir veritabanฤฑ modeli oluลŸturun: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +`Hero` sฤฑnฤฑfฤฑ, bir Pydantic modeline รงok benzer (hatta altta aslฤฑnda *bir Pydantic modelidir*). + +Birkaรง fark var: + +* `table=True`, SQLModelโ€™e bunun bir *table model* olduฤŸunu sรถyler; SQL veritabanฤฑnda bir **table**โ€™ฤฑ temsil etmelidir, sadece bir *data model* deฤŸildir (diฤŸer normal Pydantic sฤฑnฤฑflarฤฑnda olduฤŸu gibi). + +* `Field(primary_key=True)`, SQLModelโ€™e `id`โ€™nin SQL veritabanฤฑndaki **primary key** olduฤŸunu sรถyler (SQL primary keyโ€™leri hakkฤฑnda daha fazlasฤฑnฤฑ SQLModel dokรผmantasyonunda รถฤŸrenebilirsiniz). + + **Not:** primary key alanฤฑ iรงin `int | None` kullanฤฑyoruz; bรถylece Python kodunda *`id` olmadan bir nesne oluลŸturabiliriz* (`id=None`) ve veritabanฤฑnฤฑn *kaydederken bunu รผreteceฤŸini* varsayarฤฑz. SQLModel, veritabanฤฑnฤฑn `id` saฤŸlayacaฤŸฤฑnฤฑ anlar ve *veritabanฤฑ ลŸemasฤฑnda sรผtunu null olamayan bir `INTEGER`* olarak tanฤฑmlar. Detaylar iรงin primary keyโ€™ler hakkฤฑnda SQLModel dokรผmantasyonuna bakฤฑn. + +* `Field(index=True)`, SQLModelโ€™e bu sรผtun iรงin bir **SQL index** oluลŸturmasฤฑnฤฑ sรถyler; bu da bu sรผtuna gรถre filtrelenmiลŸ verileri okurken veritabanฤฑnda daha hฤฑzlฤฑ arama yapฤฑlmasฤฑnฤฑ saฤŸlar. + + SQLModel, `str` olarak tanฤฑmlanan bir ลŸeyin SQL tarafฤฑnda `TEXT` (veya veritabanฤฑna baฤŸlฤฑ olarak `VARCHAR`) tipinde bir sรผtun olacaฤŸฤฑnฤฑ bilir. + +### Engine OluลŸturma { #create-an-engine } + +Bir SQLModel `engine`โ€™i (altta aslฤฑnda bir SQLAlchemy `engine`โ€™idir) veritabanฤฑna olan **baฤŸlantฤฑlarฤฑ tutan** yapฤฑdฤฑr. + +Tรผm kodunuzun aynฤฑ veritabanฤฑna baฤŸlanmasฤฑ iรงin **tek bir `engine` nesnesi** kullanฤฑrsฤฑnฤฑz. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +`check_same_thread=False` kullanmak, FastAPIโ€™nin aynฤฑ SQLite veritabanฤฑnฤฑ farklฤฑ threadโ€™lerde kullanmasฤฑna izin verir. Bu gereklidir; รงรผnkรผ **tek bir request** **birden fazla thread** kullanabilir (รถrneฤŸin dependencyโ€™lerde). + +Merak etmeyin; kodun yapฤฑsฤฑ gereฤŸi, ileride **her request iรงin tek bir SQLModel *session*** kullandฤฑฤŸฤฑmฤฑzdan emin olacaฤŸฤฑz. Zaten `check_same_thread` de temelde bunu mรผmkรผn kฤฑlmaya รงalฤฑลŸฤฑr. + +### Tableโ€™larฤฑ OluลŸturma { #create-the-tables } + +Sonra `SQLModel.metadata.create_all(engine)` kullanan bir fonksiyon ekleyerek tรผm *table model*โ€™ler iรงin **tableโ€™larฤฑ oluลŸtururuz**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### Session Dependencyโ€™si OluลŸturma { #create-a-session-dependency } + +Bir **`Session`**, **nesneleri memoryโ€™de** tutar ve verideki gerekli deฤŸiลŸiklikleri takip eder; ardฤฑndan veritabanฤฑyla iletiลŸim kurmak iรงin **`engine` kullanฤฑr**. + +`yield` ile, her request iรงin yeni bir `Session` saฤŸlayacak bir FastAPI **dependency** oluลŸturacaฤŸฤฑz. Bu da her requestโ€™te tek session kullanmamฤฑzฤฑ garanti eder. + +Ardฤฑndan bu dependencyโ€™yi kullanacak kodun geri kalanฤฑnฤฑ sadeleลŸtirmek iรงin `Annotated` ile `SessionDep` dependencyโ€™sini oluลŸtururuz. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### Startupโ€™ta Veritabanฤฑ Tableโ€™larฤฑnฤฑ OluลŸturma { #create-database-tables-on-startup } + +Uygulama baลŸlarken veritabanฤฑ tableโ€™larฤฑnฤฑ oluลŸturacaฤŸฤฑz. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +Burada bir uygulama startup eventโ€™inde tableโ€™larฤฑ oluลŸturuyoruz. + +Productionโ€™da bรผyรผk ihtimalle uygulamayฤฑ baลŸlatmadan รถnce รงalฤฑลŸan bir migration scriptโ€™i kullanฤฑrsฤฑnฤฑz. + +/// tip | ฤฐpucu + +SQLModel, Alembicโ€™i saran migration araรงlarฤฑna sahip olacak; ancak ลŸimdilik Alembicโ€™i doฤŸrudan kullanabilirsiniz. + +/// + +### Hero OluลŸturma { #create-a-hero } + +Her SQLModel modeli aynฤฑ zamanda bir Pydantic modeli olduฤŸu iรงin, Pydantic modelleriyle kullanabildiฤŸiniz **type annotation**โ€™larda aynฤฑ ลŸekilde kullanabilirsiniz. + +ร–rneฤŸin `Hero` tipinde bir parametre tanฤฑmlarsanฤฑz, bu parametre **JSON body**โ€™den okunur. + +Aynฤฑ ลŸekilde, bunu fonksiyonun **return type**โ€™ฤฑ olarak da tanฤฑmlayabilirsiniz; bรถylece verinin ลŸekli otomatik API docs arayรผzรผnde gรถrรผnรผr. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +Burada `SessionDep` dependencyโ€™sini (bir `Session`) kullanarak yeni `Hero`โ€™yu `Session` instanceโ€™ฤฑna ekliyoruz, deฤŸiลŸiklikleri veritabanฤฑna commit ediyoruz, `hero` iรงindeki veriyi refresh ediyoruz ve sonra geri dรถndรผrรผyoruz. + +### Heroโ€™larฤฑ Okuma { #read-heroes } + +`select()` kullanarak veritabanฤฑndan `Hero`โ€™larฤฑ **okuyabiliriz**. Sonuรงlarฤฑ sayfalama (pagination) yapmak iรงin `limit` ve `offset` ekleyebiliriz. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### Tek Bir Hero Okuma { #read-one-hero } + +Tek bir `Hero` **okuyabiliriz**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Hero Silme { #delete-a-hero } + +Bir `Hero`โ€™yu **silebiliriz**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### Uygulamayฤฑ ร‡alฤฑลŸtฤฑrma { #run-the-app } + +Uygulamayฤฑ รงalฤฑลŸtฤฑrabilirsiniz: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Sonra `/docs` arayรผzรผne gidin; **FastAPI**โ€™nin APIโ€™yi **dokรผmante etmek** iรงin bu **modelleri** kullandฤฑฤŸฤฑnฤฑ gรถreceksiniz. Ayrฤฑca veriyi **serialize** ve **validate** etmek iรงin de onlarฤฑ kullanacaktฤฑr. + +
+ +
+ +## Birden Fazla Model ile Uygulamayฤฑ Gรผncelleme { #update-the-app-with-multiple-models } + +ลžimdi bu uygulamayฤฑ biraz **refactor** edelim ve **gรผvenliฤŸi** ile **esnekliฤŸi** artฤฑralฤฑm. + +ร–nceki uygulamaya bakarsanฤฑz, UIโ€™da ลŸu ana kadar clientโ€™ฤฑn oluลŸturulacak `Hero`โ€™nun `id` deฤŸerini belirlemesine izin verdiฤŸini gรถrebilirsiniz. + +Buna izin vermemeliyiz; DBโ€™de zaten atanmฤฑลŸ bir `id`โ€™yi ezebilirler. `id` belirlemek **client** tarafฤฑndan deฤŸil, **backend** veya **veritabanฤฑ** tarafฤฑndan yapฤฑlmalฤฑdฤฑr. + +Ayrฤฑca hero iรงin bir `secret_name` oluลŸturuyoruz ama ลŸimdiye kadar her yerde geri dรถndรผrรผyoruz; bu pek de **secret** sayฤฑlmaz... + +Bunlarฤฑ birkaรง **ek model** ekleyerek dรผzelteceฤŸiz. SQLModelโ€™in parlayacaฤŸฤฑ yer de burasฤฑ. + +### Birden Fazla Model OluลŸturma { #create-multiple-models } + +**SQLModel**โ€™de, `table=True` olan herhangi bir model sฤฑnฤฑfฤฑ bir **table model**โ€™dir. + +`table=True` olmayan her model sฤฑnฤฑfฤฑ ise bir **data model**โ€™dir; bunlar aslฤฑnda sadece Pydantic modelleridir (bazฤฑ kรผรงรผk ek รถzelliklerle). + +SQLModel ile **inheritance** kullanarak her durumda tรผm alanlarฤฑ tekrar tekrar yazmaktan **kaรงฤฑnabiliriz**. + +#### `HeroBase` - temel sฤฑnฤฑf { #herobase-the-base-class } + +ร–nce tรผm modeller tarafฤฑndan **paylaลŸฤฑlan alanlarฤฑ** iรงeren bir `HeroBase` modeliyle baลŸlayalฤฑm: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - *table model* { #hero-the-table-model } + +Sonra gerรงek *table model* olan `Hero`โ€™yu, diฤŸer modellerde her zaman bulunmayan **ek alanlarla** oluลŸturalฤฑm: + +* `id` +* `secret_name` + +`Hero`, `HeroBase`โ€™ten miras aldฤฑฤŸฤฑ iรงin `HeroBase`โ€™te tanฤฑmlanan alanlara da sahiptir. Dolayฤฑsฤฑyla `Hero` iรงin tรผm alanlar: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - public *data model* { #heropublic-the-public-data-model } + +Sonraki adฤฑmda `HeroPublic` modelini oluลŸtururuz; bu model API clientโ€™larฤฑna **geri dรถndรผrรผlecek** modeldir. + +`HeroBase` ile aynฤฑ alanlara sahiptir; dolayฤฑsฤฑyla `secret_name` iรงermez. + +Sonunda kahramanlarฤฑmฤฑzฤฑn kimliฤŸi korunmuลŸ oldu! + +Ayrฤฑca `id: int` alanฤฑnฤฑ yeniden tanฤฑmlar. Bunu yaparak API clientโ€™larฤฑyla bir **contract** (sรถzleลŸme) oluลŸturmuลŸ oluruz; bรถylece `id` alanฤฑnฤฑn her zaman var olacaฤŸฤฑnฤฑ ve `int` olacaฤŸฤฑnฤฑ (asla `None` olmayacaฤŸฤฑnฤฑ) bilirler. + +/// tip | ฤฐpucu + +Return modelโ€™in bir deฤŸerin her zaman mevcut olduฤŸunu ve her zaman `int` olduฤŸunu (`None` deฤŸil) garanti etmesi API clientโ€™larฤฑ iรงin รงok faydalฤฑdฤฑr; bu kesinlik sayesinde daha basit kod yazabilirler. + +Ayrฤฑca **otomatik รผretilen client**โ€™larฤฑn arayรผzleri de daha basit olur; bรถylece APIโ€™nizle รงalฤฑลŸan geliลŸtiriciler iรงin sรผreรง รงok daha rahat olur. + +/// + +`HeroPublic` iรงindeki tรผm alanlar `HeroBase` ile aynฤฑdฤฑr; tek fark `id`โ€™nin `int` olarak tanฤฑmlanmasฤฑdฤฑr (`None` deฤŸil): + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - hero oluลŸturmak iรงin *data model* { #herocreate-the-data-model-to-create-a-hero } + +ลžimdi `HeroCreate` modelini oluลŸtururuz; bu model clientโ€™tan gelen veriyi **validate** etmek iรงin kullanฤฑlฤฑr. + +`HeroBase` ile aynฤฑ alanlara sahiptir ve ek olarak `secret_name` iรงerir. + +Artฤฑk clientโ€™lar **yeni bir hero oluลŸtururken** `secret_name` gรถnderecek; bu deฤŸer veritabanฤฑnda saklanacak, ancak API responseโ€™larฤฑnda clientโ€™a geri dรถndรผrรผlmeyecek. + +/// tip | ฤฐpucu + +**Password**โ€™larฤฑ bu ลŸekilde ele alฤฑrsฤฑnฤฑz: alฤฑrsฤฑnฤฑz ama APIโ€™de geri dรถndรผrmezsiniz. + +Ayrฤฑca password deฤŸerlerini saklamadan รถnce **hash** etmelisiniz; **asla plain text olarak saklamayฤฑn**. + +/// + +`HeroCreate` alanlarฤฑ: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - hero gรผncellemek iรงin *data model* { #heroupdate-the-data-model-to-update-a-hero } + +Uygulamanฤฑn รถnceki sรผrรผmรผnde bir heroโ€™yu **gรผncellemenin** bir yolu yoktu; ancak artฤฑk **birden fazla model** ile bunu yapabiliriz. + +`HeroUpdate` *data model* biraz รถzeldir: yeni bir hero oluลŸturmak iรงin gereken alanlarฤฑn **tamamฤฑna** sahiptir, ancak tรผm alanlar **opsiyoneldir** (hepsinin bir default deฤŸeri vardฤฑr). Bu sayede hero gรผncellerken sadece gรผncellemek istediฤŸiniz alanlarฤฑ gรถnderebilirsiniz. + +Tรผm **alanlar aslฤฑnda deฤŸiลŸtiฤŸi** iรงin (tip artฤฑk `None` iรงeriyor ve default deฤŸerleri `None` oluyor), onlarฤฑ **yeniden tanฤฑmlamamฤฑz** gerekir. + +Aslฤฑnda `HeroBase`โ€™ten miras almamฤฑz gerekmiyor; รงรผnkรผ tรผm alanlarฤฑ yeniden tanฤฑmlฤฑyoruz. Tutarlฤฑlฤฑk iรงin miras almayฤฑ bฤฑrakฤฑyorum ama bu gerekli deฤŸil. Daha รงok kiลŸisel tercih meselesi. + +`HeroUpdate` alanlarฤฑ: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### `HeroCreate` ile OluลŸturma ve `HeroPublic` Dรถndรผrme { #create-with-herocreate-and-return-a-heropublic } + +Artฤฑk **birden fazla model** olduฤŸuna gรถre, onlarฤฑ kullanan uygulama kฤฑsฤฑmlarฤฑnฤฑ gรผncelleyebiliriz. + +Requestโ€™te bir `HeroCreate` *data model* alฤฑrฤฑz ve bundan bir `Hero` *table model* oluลŸtururuz. + +Bu yeni *table model* `Hero`, clientโ€™ฤฑn gรถnderdiฤŸi alanlara sahip olur ve ayrฤฑca veritabanฤฑnฤฑn รผrettiฤŸi bir `id` alฤฑr. + +Sonra fonksiyondan bu *table model* `Hero`โ€™yu olduฤŸu gibi dรถndรผrรผrรผz. Ancak `response_model`โ€™i `HeroPublic` *data model* olarak belirlediฤŸimiz iรงin **FastAPI**, veriyi validate ve serialize etmek iรงin `HeroPublic` kullanฤฑr. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | ฤฐpucu + +Burada **return type annotation** `-> HeroPublic` yerine `response_model=HeroPublic` kullanฤฑyoruz; รงรผnkรผ gerรงekte dรถndรผrdรผฤŸรผmรผz deฤŸer *bir* `HeroPublic` deฤŸil. + +EฤŸer `-> HeroPublic` yazsaydฤฑk, editรถrรผnรผz ve linterโ€™ฤฑnฤฑz (haklฤฑ olarak) `HeroPublic` yerine `Hero` dรถndรผrdรผฤŸรผnรผz iรงin ลŸikayet edecekti. + +Bunu `response_model` iรงinde belirterek **FastAPI**โ€™ye iลŸini yapmasฤฑnฤฑ sรถylรผyoruz; type annotationโ€™lara ve editรถrรผnรผzรผn/diฤŸer araรงlarฤฑn saฤŸladฤฑฤŸฤฑ desteฤŸe karฤฑลŸmamฤฑลŸ oluyoruz. + +/// + +### `HeroPublic` ile Heroโ€™larฤฑ Okuma { #read-heroes-with-heropublic } + +Daha รถncekiyle aynฤฑ ลŸekilde `Hero`โ€™larฤฑ **okuyabiliriz**; yine `response_model=list[HeroPublic]` kullanarak verinin doฤŸru biรงimde validate ve serialize edilmesini garanti ederiz. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### `HeroPublic` ile Tek Bir Hero Okuma { #read-one-hero-with-heropublic } + +Tek bir heroโ€™yu **okuyabiliriz**: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### `HeroUpdate` ile Hero Gรผncelleme { #update-a-hero-with-heroupdate } + +Bir heroโ€™yu **gรผncelleyebiliriz**. Bunun iรงin HTTP `PATCH` operasyonu kullanฤฑrฤฑz. + +Kodda, clientโ€™ฤฑn gรถnderdiฤŸi tรผm verilerle bir `dict` alฤฑrฤฑz; **yalnฤฑzca clientโ€™ฤฑn gรถnderdiฤŸi veriler**, yani sadece default deฤŸer olduklarฤฑ iรงin orada bulunan deฤŸerler hariรง. Bunu yapmak iรงin `exclude_unset=True` kullanฤฑrฤฑz. Asฤฑl numara bu. + +Sonra `hero_db.sqlmodel_update(hero_data)` ile `hero_db`โ€™yi `hero_data` iรงindeki verilerle gรผncelleriz. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### Heroโ€™yu Tekrar Silme { #delete-a-hero-again } + +Bir heroโ€™yu **silmek** bรผyรผk รถlรงรผde aynฤฑ kalฤฑyor. + +Bu รถrnekte her ลŸeyi refactor etme isteฤŸimizi bastฤฑracaฤŸฤฑz. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### Uygulamayฤฑ Tekrar ร‡alฤฑลŸtฤฑrma { #run-the-app-again } + +Uygulamayฤฑ tekrar รงalฤฑลŸtฤฑrabilirsiniz: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +`/docs` API UIโ€™a giderseniz artฤฑk gรผncellendiฤŸini gรถreceksiniz; hero oluลŸtururken clientโ€™tan `id` beklemeyecek, vb. + +
+ +
+ +## ร–zet { #recap } + +Bir SQL veritabanฤฑyla etkileลŸim kurmak iรงin **SQLModel** kullanabilir ve *data model* ile *table model* yaklaลŸฤฑmฤฑyla kodu sadeleลŸtirebilirsiniz. + +**SQLModel** dokรผmantasyonunda รงok daha fazlasฤฑnฤฑ รถฤŸrenebilirsiniz; **FastAPI** ile SQLModel kullanฤฑmฤฑ iรงin daha uzun bir mini tutorial da bulunuyor. diff --git a/docs/tr/docs/tutorial/testing.md b/docs/tr/docs/tutorial/testing.md new file mode 100644 index 0000000000..8871566066 --- /dev/null +++ b/docs/tr/docs/tutorial/testing.md @@ -0,0 +1,190 @@ +# Test Etme { #testing } + +Starlette sayesinde **FastAPI** uygulamalarฤฑnฤฑ test etmek kolay ve keyiflidir. + +Temelde HTTPX รผzerine kuruludur; HTTPX de Requestsโ€™i temel alarak tasarlandฤฑฤŸฤฑ iรงin oldukรงa tanฤฑdฤฑk ve sezgiseldir. + +Bununla birlikte **FastAPI** ile pytest'i doฤŸrudan kullanabilirsiniz. + +## `TestClient` Kullanฤฑmฤฑ { #using-testclient } + +/// info | Bilgi + +`TestClient` kullanmak iรงin รถnce `httpx`'i kurun. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin: + +```console +$ pip install httpx +``` + +/// + +`TestClient`'ฤฑ import edin. + +**FastAPI** uygulamanฤฑzฤฑ ona vererek bir `TestClient` oluลŸturun. + +Adฤฑ `test_` ile baลŸlayan fonksiyonlar oluลŸturun (bu, `pytest`'in standart konvansiyonudur). + +`TestClient` nesnesini `httpx` ile kullandฤฑฤŸฤฑnฤฑz ลŸekilde kullanฤฑn. + +Kontrol etmeniz gereken ลŸeyler iรงin standart Python ifadeleriyle basit `assert` satฤฑrlarฤฑ yazฤฑn (bu da `pytest` standardฤฑdฤฑr). + +{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} + +/// tip | ฤฐpucu + +Test fonksiyonlarฤฑnฤฑn `async def` deฤŸil, normal `def` olduฤŸuna dikkat edin. + +Client'a yapฤฑlan รงaฤŸrฤฑlar da `await` kullanฤฑlmadan, normal รงaฤŸrฤฑlardฤฑr. + +Bu sayede `pytest`'i ek bir karmaลŸฤฑklฤฑk olmadan doฤŸrudan kullanabilirsiniz. + +/// + +/// note | Teknik Detaylar + +ฤฐsterseniz `from starlette.testclient import TestClient` da kullanabilirsiniz. + +**FastAPI**, geliลŸtirici olarak size kolaylฤฑk olsun diye `starlette.testclient`'ฤฑ `fastapi.testclient` รผzerinden de sunar. Ancak asฤฑl kaynak doฤŸrudan Starlette'tฤฑr. + +/// + +/// tip | ฤฐpucu + +FastAPI uygulamanฤฑza request gรถndermenin dฤฑลŸฤฑnda testlerinizde `async` fonksiyonlar รงaฤŸฤฑrmak istiyorsanฤฑz (รถrn. asenkron veritabanฤฑ fonksiyonlarฤฑ), ileri seviye bรถlรผmdeki [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} dokรผmanฤฑna gรถz atฤฑn. + +/// + +## Testleri Ayฤฑrma { #separating-tests } + +Gerรงek bir uygulamada testlerinizi bรผyรผk ihtimalle farklฤฑ bir dosyada tutarsฤฑnฤฑz. + +Ayrฤฑca **FastAPI** uygulamanฤฑz birden fazla dosya/modรผl vb. ile de oluลŸturulmuลŸ olabilir. + +### **FastAPI** Uygulama Dosyasฤฑ { #fastapi-app-file } + +[Bigger Applications](bigger-applications.md){.internal-link target=_blank}'te anlatฤฑlan ลŸekilde bir dosya yapฤฑnฤฑz olduฤŸunu varsayalฤฑm: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ main.py +``` + +`main.py` dosyasฤฑnda **FastAPI** uygulamanฤฑz bulunuyor olsun: + +{* ../../docs_src/app_testing/app_a_py39/main.py *} + +### Test Dosyasฤฑ { #testing-file } + +Sonra testlerinizin olduฤŸu bir `test_main.py` dosyanฤฑz olabilir. Bu dosya aynฤฑ Python package iรงinde (yani `__init__.py` dosyasฤฑ olan aynฤฑ dizinde) durabilir: + +``` hl_lines="5" +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +Bu dosya aynฤฑ package iรงinde olduฤŸu iรงin, `main` modรผlรผnden (`main.py`) `app` nesnesini import etmek รผzere relative import kullanabilirsiniz: + +{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} + +...ve test kodunu da รถncekiyle aynฤฑ ลŸekilde yazabilirsiniz. + +## Test Etme: GeniลŸletilmiลŸ ร–rnek { #testing-extended-example } + +ลžimdi bu รถrneฤŸi geniลŸletelim ve farklฤฑ parรงalarฤฑn nasฤฑl test edildiฤŸini gรถrmek iรงin daha fazla detay ekleyelim. + +### GeniลŸletilmiลŸ **FastAPI** Uygulama Dosyasฤฑ { #extended-fastapi-app-file } + +Aynฤฑ dosya yapฤฑsฤฑyla devam edelim: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +Diyelim ki **FastAPI** uygulamanฤฑzฤฑn bulunduฤŸu `main.py` dosyasฤฑnda artฤฑk baลŸka **path operations** da var. + +Hata dรถndรผrebilecek bir `GET` operation'ฤฑ var. + +Birden fazla farklฤฑ hata dรถndรผrebilecek bir `POST` operation'ฤฑ var. + +Her iki *path operation* da `X-Token` header'ฤฑnฤฑ gerektiriyor. + +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} + +### GeniลŸletilmiลŸ Test Dosyasฤฑ { #extended-testing-file } + +Sonrasฤฑnda `test_main.py` dosyanฤฑzฤฑ geniลŸletilmiลŸ testlerle gรผncelleyebilirsiniz: + +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + +Client'ฤฑn request iรงinde bir bilgi gรถndermesi gerektiฤŸinde ve bunu nasฤฑl yapacaฤŸฤฑnฤฑzฤฑ bilemediฤŸinizde, `httpx` ile nasฤฑl yapฤฑlacaฤŸฤฑnฤฑ aratabilirsiniz (Google) ya da HTTPXโ€™in tasarฤฑmฤฑ Requestsโ€™e dayandฤฑฤŸฤฑ iรงin `requests` ile nasฤฑl yapฤฑldฤฑฤŸฤฑnฤฑ da arayabilirsiniz. + +Sonra testlerinizde aynฤฑsฤฑnฤฑ uygularsฤฑnฤฑz. + +ร–rn.: + +* Bir *path* veya *query* parametresi geรงirmek iรงin, URLโ€™nin kendisine ekleyin. +* JSON body gรถndermek iรงin, `json` parametresine bir Python nesnesi (รถrn. bir `dict`) verin. +* JSON yerine *Form Data* gรถndermeniz gerekiyorsa, bunun yerine `data` parametresini kullanฤฑn. +* *headers* gรถndermek iรงin, `headers` parametresine bir `dict` verin. +* *cookies* iรงin, `cookies` parametresine bir `dict` verin. + +Backend'e veri geรงme hakkฤฑnda daha fazla bilgi iรงin (`httpx` veya `TestClient` kullanarak) HTTPX dokรผmantasyonu'na bakฤฑn. + +/// info | Bilgi + +`TestClient`'ฤฑn Pydantic model'lerini deฤŸil, JSON'a dรถnรผลŸtรผrรผlebilen verileri aldฤฑฤŸฤฑnฤฑ unutmayฤฑn. + +Testinizde bir Pydantic model'iniz varsa ve test sฤฑrasฤฑnda verisini uygulamaya gรถndermek istiyorsanฤฑz, [JSON Compatible Encoder](encoder.md){.internal-link target=_blank} iรงinde aรงฤฑklanan `jsonable_encoder`'ฤฑ kullanabilirsiniz. + +/// + +## ร‡alฤฑลŸtฤฑrma { #run-it } + +Bundan sonra yapmanฤฑz gereken tek ลŸey `pytest`'i kurmaktฤฑr. + +Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin: + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +Dosyalarฤฑ ve testleri otomatik olarak bulur, รงalฤฑลŸtฤฑrฤฑr ve sonuรงlarฤฑ size raporlar. + +Testleri ลŸu ลŸekilde รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/tr/docs/virtual-environments.md b/docs/tr/docs/virtual-environments.md new file mode 100644 index 0000000000..cf7fab778b --- /dev/null +++ b/docs/tr/docs/virtual-environments.md @@ -0,0 +1,862 @@ +# Virtual Environments { #virtual-environments } + +Python projeleriyle รงalฤฑลŸฤฑrken, her proje iรงin kurduฤŸunuz package'leri birbirinden izole etmek adฤฑna bรผyรผk ihtimalle bir **virtual environment** (veya benzer bir mekanizma) kullanmalฤฑsฤฑnฤฑz. + +/// info | Bilgi + +Virtual environment'leri, nasฤฑl oluลŸturulduklarฤฑnฤฑ ve nasฤฑl kullanฤฑldฤฑklarฤฑnฤฑ zaten biliyorsanฤฑz bu bรถlรผmรผ atlamak isteyebilirsiniz. ๐Ÿค“ + +/// + +/// tip | ฤฐpucu + +**Virtual environment**, **environment variable** ile aynฤฑ ลŸey deฤŸildir. + +**Environment variable**, sistemde bulunan ve programlarฤฑn kullanabildiฤŸi bir deฤŸiลŸkendir. + +**Virtual environment** ise iรงinde bazฤฑ dosyalar bulunan bir klasรถrdรผr. + +/// + +/// info | Bilgi + +Bu sayfada **virtual environment**'leri nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ ve nasฤฑl รงalฤฑลŸtฤฑklarฤฑnฤฑ รถฤŸreneceksiniz. + +EฤŸer Python'ฤฑ kurmak dahil her ลŸeyi sizin yerinize yรถneten bir **tool** kullanmaya hazฤฑrsanฤฑz, uv'yi deneyin. + +/// + +## Proje OluลŸturun { #create-a-project } + +ร–nce projeniz iรงin bir klasรถr oluลŸturun. + +Ben genelde home/user klasรถrรผmรผn iรงinde `code` adlฤฑ bir klasรถr oluลŸtururum. + +Sonra bunun iรงinde her proje iรงin ayrฤฑ bir klasรถr oluลŸtururum. + +
+ +```console +// Go to the home directory +$ cd +// Create a directory for all your code projects +$ mkdir code +// Enter into that code directory +$ cd code +// Create a directory for this project +$ mkdir awesome-project +// Enter into that project directory +$ cd awesome-project +``` + +
+ +## Virtual Environment OluลŸturun { #create-a-virtual-environment } + +Bir Python projesi รผzerinde **ilk kez** รงalฤฑลŸmaya baลŸladฤฑฤŸฤฑnฤฑzda, projenizin iรงinde **virtual environment** oluลŸturun. + +/// tip | ฤฐpucu + +Bunu her รงalฤฑลŸtฤฑฤŸฤฑnฤฑzda deฤŸil, **proje baลŸฤฑna sadece bir kez** yapmanฤฑz yeterlidir. + +/// + +//// tab | `venv` + +Bir virtual environment oluลŸturmak iรงin, Python ile birlikte gelen `venv` modรผlรผnรผ kullanabilirsiniz. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | Bu komut ne anlama geliyor + +* `python`: `python` adlฤฑ programฤฑ kullan +* `-m`: bir modรผlรผ script gibi รงalฤฑลŸtฤฑr; bir sonraki kฤฑsฤฑmda hangi modรผl olduฤŸunu sรถyleyeceฤŸiz +* `venv`: normalde Python ile birlikte kurulu gelen `venv` modรผlรผnรผ kullan +* `.venv`: virtual environment'i yeni `.venv` klasรถrรผnรผn iรงine oluลŸtur + +/// + +//// + +//// tab | `uv` + +EฤŸer `uv` kuruluysa, onunla da virtual environment oluลŸturabilirsiniz. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | ฤฐpucu + +Varsayฤฑlan olarak `uv`, `.venv` adlฤฑ bir klasรถrde virtual environment oluลŸturur. + +Ancak ek bir argรผmanla klasรถr adฤฑnฤฑ vererek bunu รถzelleลŸtirebilirsiniz. + +/// + +//// + +Bu komut `.venv` adlฤฑ bir klasรถrรผn iรงinde yeni bir virtual environment oluลŸturur. + +/// details | `.venv` veya baลŸka bir ad + +Virtual environment'i baลŸka bir klasรถrde de oluลŸturabilirsiniz; ancak buna `.venv` demek yaygฤฑn bir konvansiyondur. + +/// + +## Virtual Environment'i Aktif Edin { #activate-the-virtual-environment } + +OluลŸturduฤŸunuz virtual environment'i aktif edin; bรถylece รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑz her Python komutu veya kurduฤŸunuz her package onu kullanฤฑr. + +/// tip | ฤฐpucu + +Projede รงalฤฑลŸmak iรงin **yeni bir terminal oturumu** baลŸlattฤฑฤŸฤฑnฤฑz **her seferinde** bunu yapฤฑn. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Ya da Windows'ta Bash kullanฤฑyorsanฤฑz (รถrn. Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | ฤฐpucu + +Bu environment'e **yeni bir package** kurduฤŸunuz her seferinde environment'i yeniden **aktif edin**. + +Bรถylece, o package'in kurduฤŸu bir **terminal (CLI) programฤฑ** kullanฤฑyorsanฤฑz, global olarak kurulu (ve muhtemelen ihtiyacฤฑnฤฑz olandan farklฤฑ bir versiyona sahip) baลŸka bir program yerine, virtual environment'inizdeki programฤฑ kullanmฤฑลŸ olursunuz. + +/// + +## Virtual Environment'in Aktif OlduฤŸunu Kontrol Edin { #check-the-virtual-environment-is-active } + +Virtual environment'in aktif olduฤŸunu (bir รถnceki komutun รงalฤฑลŸtฤฑฤŸฤฑnฤฑ) kontrol edin. + +/// tip | ฤฐpucu + +Bu **opsiyoneldir**; ancak her ลŸeyin beklendiฤŸi gibi รงalฤฑลŸtฤฑฤŸฤฑnฤฑ ve hedeflediฤŸiniz virtual environment'i kullandฤฑฤŸฤฑnฤฑzฤฑ **kontrol etmek** iรงin iyi bir yรถntemdir. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +EฤŸer `python` binary'sini projenizin iรงinde (bu รถrnekte `awesome-project`) `.venv/bin/python` yolunda gรถsteriyorsa, tamamdฤฑr. ๐ŸŽ‰ + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +EฤŸer `python` binary'sini projenizin iรงinde (bu รถrnekte `awesome-project`) `.venv\Scripts\python` yolunda gรถsteriyorsa, tamamdฤฑr. ๐ŸŽ‰ + +//// + +## `pip`'i Yรผkseltin { #upgrade-pip } + +/// tip | ฤฐpucu + +`uv` kullanฤฑyorsanฤฑz, `pip` yerine onunla kurulum yaparsฤฑnฤฑz; dolayฤฑsฤฑyla `pip`'i yรผkseltmeniz gerekmez. ๐Ÿ˜Ž + +/// + +Package'leri kurmak iรงin `pip` kullanฤฑyorsanฤฑz (Python ile varsayฤฑlan olarak gelir), en gรผncel sรผrรผme **yรผkseltmeniz** gerekir. + +Bir package kurarken gรถrรผlen birรงok garip hata, รถnce `pip`'i yรผkseltince รงรถzรผlรผr. + +/// tip | ฤฐpucu + +Bunu genelde virtual environment'i oluลŸturduktan hemen sonra **bir kez** yaparsฤฑnฤฑz. + +/// + +Virtual environment'in aktif olduฤŸundan emin olun (yukarฤฑdaki komutla) ve sonra ลŸunu รงalฤฑลŸtฤฑrฤฑn: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +/// tip | ฤฐpucu + +Bazen pip'i yรผkseltmeye รงalฤฑลŸฤฑrken **`No module named pip`** hatasฤฑ alabilirsiniz. + +Bรถyle olursa, aลŸaฤŸฤฑdaki komutla pip'i kurup yรผkseltin: + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +Bu komut pip kurulu deฤŸilse kurar ve ayrฤฑca kurulu pip sรผrรผmรผnรผn `ensurepip` iรงinde bulunan sรผrรผm kadar gรผncel olmasฤฑnฤฑ garanti eder. + +/// + +## `.gitignore` Ekleyin { #add-gitignore } + +**Git** kullanฤฑyorsanฤฑz (kullanmalฤฑsฤฑnฤฑz), `.venv` iรงindeki her ลŸeyi Git'ten hariรง tutmak iรงin bir `.gitignore` dosyasฤฑ ekleyin. + +/// tip | ฤฐpucu + +Virtual environment'i `uv` ile oluลŸturduysanฤฑz, bunu zaten sizin iรงin yaptฤฑ; bu adฤฑmฤฑ atlayabilirsiniz. ๐Ÿ˜Ž + +/// + +/// tip | ฤฐpucu + +Bunu virtual environment'i oluลŸturduktan hemen sonra **bir kez** yapฤฑn. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | Bu komut ne anlama geliyor + +* `echo "*"`: terminale `*` metnini "yazar" (sonraki kฤฑsฤฑm bunu biraz deฤŸiลŸtiriyor) +* `>`: `>` iลŸaretinin solundaki komutun terminale yazdฤฑracaฤŸฤฑ รงฤฑktฤฑ, ekrana basฤฑlmak yerine saฤŸ taraftaki dosyaya yazฤฑlsฤฑn +* `.gitignore`: metnin yazฤฑlacaฤŸฤฑ dosyanฤฑn adฤฑ + +Git'te `*` "her ลŸey" demektir. Yani `.venv` klasรถrรผ iรงindeki her ลŸeyi ignore eder. + +Bu komut, iรงeriฤŸi ลŸu olan bir `.gitignore` dosyasฤฑ oluลŸturur: + +```gitignore +* +``` + +/// + +## Package'leri Kurun { #install-packages } + +Environment'i aktif ettikten sonra, iรงine package kurabilirsiniz. + +/// tip | ฤฐpucu + +Projede ihtiyaรง duyduฤŸunuz package'leri ilk kez kurarken veya yรผkseltirken bunu **bir kez** yapฤฑn. + +Bir sรผrรผmรผ yรผkseltmeniz veya yeni bir package eklemeniz gerekirse **tekrar** yaparsฤฑnฤฑz. + +/// + +### Package'leri DoฤŸrudan Kurun { #install-packages-directly } + +Acele ediyorsanฤฑz ve projenizin package gereksinimlerini bir dosyada belirtmek istemiyorsanฤฑz, doฤŸrudan kurabilirsiniz. + +/// tip | ฤฐpucu + +Programฤฑnฤฑzฤฑn ihtiyaรง duyduฤŸu package'leri ve versiyonlarฤฑnฤฑ bir dosyada tutmak (รถr. `requirements.txt` veya `pyproject.toml`) (รงok) iyi bir fikirdir. + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +EฤŸer `uv` varsa: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt`'ten Kurun { #install-from-requirements-txt } + +Bir `requirements.txt` dosyanฤฑz varsa, iรงindeki package'leri kurmak iรงin artฤฑk onu kullanabilirsiniz. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +EฤŸer `uv` varsa: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +Bazฤฑ package'ler iรงeren bir `requirements.txt` ลŸรถyle gรถrรผnebilir: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## Programฤฑnฤฑzฤฑ ร‡alฤฑลŸtฤฑrฤฑn { #run-your-program } + +Virtual environment'i aktif ettikten sonra programฤฑnฤฑzฤฑ รงalฤฑลŸtฤฑrabilirsiniz; program, virtual environment'in iรงindeki Python'ฤฑ ve oraya kurduฤŸunuz package'leri kullanฤฑr. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## Editรถrรผnรผzรผ Yapฤฑlandฤฑrฤฑn { #configure-your-editor } + +Muhtemelen bir editรถr kullanฤฑrsฤฑnฤฑz; otomatik tamamlamayฤฑ ve satฤฑr iรงi hatalarฤฑ alabilmek iรงin, editรถrรผnรผzรผ oluลŸturduฤŸunuz aynฤฑ virtual environment'i kullanacak ลŸekilde yapฤฑlandฤฑrdฤฑฤŸฤฑnฤฑzdan emin olun (muhtemelen otomatik algฤฑlar). + +ร–rneฤŸin: + +* VS Code +* PyCharm + +/// tip | ฤฐpucu + +Bunu genelde yalnฤฑzca **bir kez**, virtual environment'i oluลŸturduฤŸunuzda yapmanฤฑz gerekir. + +/// + +## Virtual Environment'i Devre DฤฑลŸฤฑ Bฤฑrakฤฑn { #deactivate-the-virtual-environment } + +Projeniz รผzerinde iลŸiniz bittiฤŸinde virtual environment'i **deactivate** edebilirsiniz. + +
+ +```console +$ deactivate +``` + +
+ +Bรถylece `python` รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda, o virtual environment iรงinden (ve oraya kurulu package'lerle) รงalฤฑลŸtฤฑrmaya รงalฤฑลŸmaz. + +## ร‡alฤฑลŸmaya Hazฤฑrsฤฑnฤฑz { #ready-to-work } + +Artฤฑk projeniz รผzerinde รงalฤฑลŸmaya baลŸlayabilirsiniz. + +/// tip | ฤฐpucu + +Yukarฤฑdaki her ลŸeyin aslฤฑnda ne olduฤŸunu anlamak ister misiniz? + +Okumaya devam edin. ๐Ÿ‘‡๐Ÿค“ + +/// + +## Neden Virtual Environment { #why-virtual-environments } + +FastAPI ile รงalฤฑลŸmak iรงin Python kurmanฤฑz gerekir. + +Sonrasฤฑnda FastAPI'yi ve kullanmak istediฤŸiniz diฤŸer tรผm **package**'leri **kurmanฤฑz** gerekir. + +Package kurmak iรงin genelde Python ile gelen `pip` komutunu (veya benzeri alternatifleri) kullanฤฑrsฤฑnฤฑz. + +Ancak `pip`'i doฤŸrudan kullanฤฑrsanฤฑz, package'ler **global Python environment**'ฤฑnฤฑza (Python'ฤฑn global kurulumuna) yรผklenir. + +### Problem { #the-problem } + +Peki package'leri global Python environment'a kurmanฤฑn sorunu ne? + +Bir noktada, muhtemelen **farklฤฑ package**'lere baฤŸฤฑmlฤฑ birรงok farklฤฑ program yazacaksฤฑnฤฑz. Ayrฤฑca รผzerinde รงalฤฑลŸtฤฑฤŸฤฑnฤฑz bazฤฑ projeler, aynฤฑ package'in **farklฤฑ versiyonlarฤฑna** ihtiyaรง duyacak. ๐Ÿ˜ฑ + +ร–rneฤŸin `philosophers-stone` adฤฑnda bir proje oluลŸturduฤŸunuzu dรผลŸรผnรผn; bu program, `harry` adlฤฑ baลŸka bir package'e **`1` versiyonu ile** baฤŸlฤฑ. Yani `harry`'yi kurmanฤฑz gerekir. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +Sonra daha ileri bir zamanda `prisoner-of-azkaban` adlฤฑ baลŸka bir proje oluลŸturuyorsunuz; bu proje de `harry`'ye baฤŸlฤฑ, fakat bu proje **`harry` versiyon `3`** istiyor. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +ลžimdi sorun ลŸu: package'leri local bir **virtual environment** yerine global (global environment) olarak kurarsanฤฑz, `harry`'nin hangi versiyonunu kuracaฤŸฤฑnฤฑza karar vermek zorunda kalฤฑrsฤฑnฤฑz. + +`philosophers-stone`'u รงalฤฑลŸtฤฑrmak istiyorsanฤฑz รถnce `harry` versiyon `1`'i kurmanฤฑz gerekir; รถrneฤŸin: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +Sonuรง olarak global Python environment'ฤฑnฤฑzda `harry` versiyon `1` kurulu olur. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +Fakat `prisoner-of-azkaban`'ฤฑ รงalฤฑลŸtฤฑrmak istiyorsanฤฑz, `harry` versiyon `1`'i kaldฤฑrฤฑp `harry` versiyon `3`'รผ kurmanฤฑz gerekir (ya da sadece `3`'รผ kurmak, otomatik olarak `1`'i kaldฤฑrabilir). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +Sonuรง olarak global Python environment'ฤฑnฤฑzda `harry` versiyon `3` kurulu olur. + +Ve `philosophers-stone`'u tekrar รงalฤฑลŸtฤฑrmaya kalkarsanฤฑz, `harry` versiyon `1`'e ihtiyaรง duyduฤŸu iรงin **รงalฤฑลŸmama** ihtimali vardฤฑr. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|โ›”๏ธ| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | ฤฐpucu + +Python package'lerinde **yeni versiyonlarda** **breaking change**'lerden kaรงฤฑnmak oldukรงa yaygฤฑndฤฑr; ancak yine de daha gรผvenlisi, yeni versiyonlarฤฑ bilinรงli ลŸekilde kurmak ve mรผmkรผnse test'leri รงalฤฑลŸtฤฑrฤฑp her ลŸeyin doฤŸru รงalฤฑลŸtฤฑฤŸฤฑnฤฑ doฤŸrulamaktฤฑr. + +/// + +ลžimdi bunu, **projelerinizin baฤŸฤฑmlฤฑ olduฤŸu** daha **birรงok** baลŸka **package** ile birlikte dรผลŸรผnรผn. Yรถnetmesi epey zorlaลŸฤฑr. Sonunda bazฤฑ projeleri package'lerin **uyumsuz versiyonlarฤฑyla** รงalฤฑลŸtฤฑrฤฑp, bir ลŸeylerin neden รงalฤฑลŸmadฤฑฤŸฤฑnฤฑ anlamamak gibi durumlara dรผลŸebilirsiniz. + +Ayrฤฑca iลŸletim sisteminize (รถrn. Linux, Windows, macOS) baฤŸlฤฑ olarak Python zaten kurulu gelmiลŸ olabilir. Bu durumda, sisteminizin **ihtiyaรง duyduฤŸu** bazฤฑ package'ler belirli versiyonlarla รถnceden kurulu olabilir. Global Python environment'a package kurarsanฤฑz, iลŸletim sistemiyle gelen bazฤฑ programlarฤฑ **bozma** ihtimaliniz olabilir. + +## Package'ler Nereye Kuruluyor { #where-are-packages-installed } + +Python'ฤฑ kurduฤŸunuzda, bilgisayarฤฑnฤฑzda bazฤฑ dosyalar iรงeren klasรถrler oluลŸturulur. + +Bu klasรถrlerin bir kฤฑsmฤฑ, kurduฤŸunuz tรผm package'leri barฤฑndฤฑrmaktan sorumludur. + +ลžunu รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda: + +
+ +```console +// Don't run this now, it's just an example ๐Ÿค“ +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +Bu, FastAPI kodunu iรงeren sฤฑkฤฑลŸtฤฑrฤฑlmฤฑลŸ bir dosyayฤฑ genellikle PyPI'dan indirir. + +Ayrฤฑca FastAPI'nin baฤŸฤฑmlฤฑ olduฤŸu diฤŸer package'ler iรงin de dosyalarฤฑ **indirir**. + +Sonra tรผm bu dosyalarฤฑ **aรงar (extract)** ve bilgisayarฤฑnฤฑzdaki bir klasรถre koyar. + +Varsayฤฑlan olarak bu indirilip รงฤฑkarฤฑlan dosyalarฤฑ, Python kurulumunuzla birlikte gelen klasรถre yerleลŸtirir; yani **global environment**'a. + +## Virtual Environment Nedir { #what-are-virtual-environments } + +Global environment'da tรผm package'leri bir arada tutmanฤฑn sorunlarฤฑna รงรถzรผm, รงalฤฑลŸtฤฑฤŸฤฑnฤฑz her proje iรงin ayrฤฑ bir **virtual environment** kullanmaktฤฑr. + +Virtual environment, global olana รงok benzeyen bir **klasรถrdรผr**; bir projenin ihtiyaรง duyduฤŸu package'leri buraya kurarsฤฑnฤฑz. + +Bรถylece her projenin kendi virtual environment'i (`.venv` klasรถrรผ) ve kendi package'leri olur. + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Virtual Environment'i Aktif Etmek Ne Demek { #what-does-activating-a-virtual-environment-mean } + +Bir virtual environment'i รถrneฤŸin ลŸununla aktif ettiฤŸinizde: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Ya da Windows'ta Bash kullanฤฑyorsanฤฑz (รถrn. Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +Bu komut, sonraki komutlarda kullanฤฑlabilecek bazฤฑ [environment variable](environment-variables.md){.internal-link target=_blank}'larฤฑ oluลŸturur veya deฤŸiลŸtirir. + +Bunlardan biri `PATH` deฤŸiลŸkenidir. + +/// tip | ฤฐpucu + +`PATH` environment variable hakkฤฑnda daha fazla bilgiyi [Environment Variables](environment-variables.md#path-environment-variable){.internal-link target=_blank} bรถlรผmรผnde bulabilirsiniz. + +/// + +Bir virtual environment'i aktive etmek, onun `.venv/bin` (Linux ve macOS'ta) veya `.venv\Scripts` (Windows'ta) yolunu `PATH` environment variable'ฤฑna ekler. + +Diyelim ki environment'i aktive etmeden รถnce `PATH` deฤŸiลŸkeni ลŸรถyleydi: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +Bu, sistemin programlarฤฑ ลŸu klasรถrlerde arayacaฤŸฤฑ anlamฤฑna gelir: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +Bu, sistemin programlarฤฑ ลŸurada arayacaฤŸฤฑ anlamฤฑna gelir: + +* `C:\Windows\System32` + +//// + +Virtual environment'i aktive ettikten sonra `PATH` deฤŸiลŸkeni ลŸuna benzer hale gelir: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Bu, sistemin artฤฑk programlarฤฑ รถnce ลŸurada aramaya baลŸlayacaฤŸฤฑ anlamฤฑna gelir: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +diฤŸer klasรถrlere bakmadan รถnce. + +Dolayฤฑsฤฑyla terminale `python` yazdฤฑฤŸฤฑnฤฑzda, sistem Python programฤฑnฤฑ ลŸurada bulur: + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +ve onu kullanฤฑr. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +Bu, sistemin artฤฑk programlarฤฑ รถnce ลŸurada aramaya baลŸlayacaฤŸฤฑ anlamฤฑna gelir: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +diฤŸer klasรถrlere bakmadan รถnce. + +Dolayฤฑsฤฑyla terminale `python` yazdฤฑฤŸฤฑnฤฑzda, sistem Python programฤฑnฤฑ ลŸurada bulur: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +ve onu kullanฤฑr. + +//// + +ร–nemli bir detay: virtual environment yolu `PATH` deฤŸiลŸkeninin **en baลŸฤฑna** eklenir. Sistem, mevcut baลŸka herhangi bir Python'ฤฑ bulmadan **รถnce** bunu bulur. Bรถylece `python` รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda, baลŸka bir `python` (รถrneฤŸin global environment'tan gelen `python`) yerine **virtual environment'taki** Python kullanฤฑlฤฑr. + +Virtual environment'i aktive etmek birkaรง ลŸeyi daha deฤŸiลŸtirir; ancak yaptฤฑฤŸฤฑ en รถnemli iลŸlerden biri budur. + +## Virtual Environment'i Kontrol Etmek { #checking-a-virtual-environment } + +Bir virtual environment'in aktif olup olmadฤฑฤŸฤฑnฤฑ รถrneฤŸin ลŸununla kontrol ettiฤŸinizde: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +Bu, kullanฤฑlacak `python` programฤฑnฤฑn **virtual environment'in iรงindeki** Python olduฤŸu anlamฤฑna gelir. + +Linux ve macOS'ta `which`, Windows PowerShell'de ise `Get-Command` kullanฤฑrsฤฑnฤฑz. + +Bu komutun รงalฤฑลŸma mantฤฑฤŸฤฑ ลŸudur: `PATH` environment variable iรงindeki **her yolu sฤฑrayla** dolaลŸฤฑr, `python` adlฤฑ programฤฑ arar. BulduฤŸunda, size o programฤฑn **dosya yolunu** gรถsterir. + +En รถnemli kฤฑsฤฑm ลŸu: `python` dediฤŸinizde รงalฤฑลŸacak olan "`python`" tam olarak budur. + +Yani doฤŸru virtual environment'da olup olmadฤฑฤŸฤฑnฤฑzฤฑ doฤŸrulayabilirsiniz. + +/// tip | ฤฐpucu + +Bir virtual environment'i aktive etmek kolaydฤฑr; sonra o Python ile kalฤฑp **baลŸka bir projeye geรงmek** de kolaydฤฑr. + +Bu durumda ikinci proje, baลŸka bir projenin virtual environment'ฤฑndan gelen **yanlฤฑลŸ Python**'ฤฑ kullandฤฑฤŸฤฑnฤฑz iรงin **รงalฤฑลŸmayabilir**. + +Hangi `python`'ฤฑn kullanฤฑldฤฑฤŸฤฑnฤฑ kontrol edebilmek bu yรผzden faydalฤฑdฤฑr. ๐Ÿค“ + +/// + +## Neden Virtual Environment'i Deactivate Edelim { #why-deactivate-a-virtual-environment } + +ร–rneฤŸin `philosophers-stone` projesi รผzerinde รงalฤฑลŸฤฑyor olabilirsiniz; **o virtual environment'i aktive eder**, package kurar ve o environment ile รงalฤฑลŸฤฑrsฤฑnฤฑz. + +Sonra **baลŸka bir proje** olan `prisoner-of-azkaban` รผzerinde รงalฤฑลŸmak istersiniz. + +O projeye gidersiniz: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +EฤŸer `philosophers-stone` iรงin olan virtual environment'i deactivate etmezseniz, terminalde `python` รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda `philosophers-stone`'dan gelen Python'ฤฑ kullanmaya รงalฤฑลŸฤฑr. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Error importing sirius, it's not installed ๐Ÿ˜ฑ +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +Ama virtual environment'i deactivate edip `prisoner-of-askaban` iรงin yeni olanฤฑ aktive ederseniz, `python` รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑzda `prisoner-of-azkaban` iรงindeki virtual environment'dan gelen Python kullanฤฑlฤฑr. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project ๐Ÿ˜Ž +$ deactivate + +// Activate the virtual environment in prisoner-of-azkaban/.venv ๐Ÿš€ +$ source .venv/bin/activate + +// Now when you run python, it will find the package sirius installed in this virtual environment โœจ +$ python main.py + +I solemnly swear ๐Ÿบ +``` + +
+ +## Alternatifler { #alternatives } + +Bu, baลŸlamanฤฑz iรงin basit bir rehber ve alttaki mekanizmalarฤฑn nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ รถฤŸretmeyi amaรงlฤฑyor. + +Virtual environment'leri, package baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ (requirements) ve projeleri yรถnetmek iรงin birรงok **alternatif** vardฤฑr. + +Hazฤฑr olduฤŸunuzda ve package baฤŸฤฑmlฤฑlฤฑklarฤฑ, virtual environment'ler vb. dahil **tรผm projeyi yรถnetmek** iรงin bir tool kullanmak istediฤŸinizde, uv'yi denemenizi รถneririm. + +`uv` birรงok ลŸey yapabilir, รถrneฤŸin: + +* Sizin iรงin **Python kurabilir**, farklฤฑ sรผrรผmler dahil +* Projelerinizin **virtual environment**'ini yรถnetebilir +* **Package** kurabilir +* Projeniz iรงin package **baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ ve versiyonlarฤฑnฤฑ** yรถnetebilir +* BaฤŸฤฑmlฤฑlฤฑklarฤฑ dahil, kurulacak package ve versiyonlarฤฑn **tam (exact)** bir setini garanti edebilir; bรถylece geliลŸtirirken bilgisayarฤฑnฤฑzda รงalฤฑลŸtฤฑrdฤฑฤŸฤฑnฤฑz projeyi production'da da birebir aynฤฑ ลŸekilde รงalฤฑลŸtฤฑrabileceฤŸinizden emin olursunuz; buna **locking** denir +* Ve daha birรงok ลŸey + +## Sonuรง { #conclusion } + +Buradaki her ลŸeyi okuduysanฤฑz ve anladฤฑysanฤฑz, artฤฑk birรงok geliลŸtiriciden **รงok daha fazla** virtual environment bilgisine sahipsiniz. ๐Ÿค“ + +Bu detaylarฤฑ bilmek, ileride karmaลŸฤฑk gรถrรผnen bir sorunu debug ederken bรผyรผk olasฤฑlฤฑkla iลŸinize yarayacak; รงรผnkรผ **altta nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ** biliyor olacaksฤฑnฤฑz. ๐Ÿ˜Ž From c7682a198a68455d0004dd0e8e829eef807065e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 15:44:05 +0000 Subject: [PATCH 115/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c54875f066..9304032108 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). From dcfd432c3645055ab6f23227c26f56aa182358ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:47:42 -0800 Subject: [PATCH 116/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20for=20tr?= =?UTF-8?q?anslations=20(#14830)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 5e6d821b31..af7944e75c 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -179,19 +179,23 @@ as Uvicorn by default will use the port `8000`, the documentation on port `8008` Help with translations is VERY MUCH appreciated! And it can't be done without the help from the community. ๐ŸŒŽ ๐Ÿš€ -Here are the steps to help with translations. +Translation pull requests are made by LLMs guided with prompts designed by the FastAPI team together with the community of native speakers for each supported language. -#### Translation PRs +#### LLM Prompt per Language -Translation pull requests are made by LLMs guided with prompts designed by the FastAPI team together with the community of native speakers for each supported language. +Each language has a directory: https://github.com/fastapi/fastapi/tree/master/docs, in it you can see a file `llm-prompt.md` with the prompt specific for that language. + +For example, for Spanish, the prompt is at: `docs/es/llm-prompt.md`. + +If you see mistakes in your language, you can make suggestions to the prompt in that file for your language, and request the specific pages you would like to re-generate after the changes. -These translations are normally still reviewed by native speakers, and here's where you can help! +#### Reviewing Translation PRs -* Check the currently existing pull requests for your language. You can filter the pull requests by the ones with the label for your language. For example, for Spanish, the label is `lang-es`. +You can also check the currently existing pull requests for your language. You can filter the pull requests by the ones with the label for your language. For example, for Spanish, the label is `lang-es`. -* When reviewing a pull request, it's better not to suggest changes in the same pull request, because it is LLM generated, and it won't be possible to make sure that small individual changes are replicated in other similar sections, or that they are preserved when translating the same content again. +When reviewing a pull request, it's better not to suggest changes in the same pull request, because it is LLM generated, and it won't be possible to make sure that small individual changes are replicated in other similar sections, or that they are preserved when translating the same content again. -* Instead of adding suggestions to the translation PR, make the suggestions to the LLM prompt file for that language, in a new PR. For example, for Spanish, the LLM prompt file is at: `docs/es/llm-prompt.md`. +Instead of adding suggestions to the translation PR, make the suggestions to the LLM prompt file for that language, in a new PR. For example, for Spanish, the LLM prompt file is at: `docs/es/llm-prompt.md`. /// tip @@ -201,9 +205,9 @@ Check the docs about GitHub Discussion to coordinate translations for your language. You can subscribe to it, and when there's a new pull request to review, an automatic comment will be added to the discussion. +Check if there's a GitHub Discussion to coordinate translations for your language. You can subscribe to it, and when there's a new pull request to review, an automatic comment will be added to the discussion. -* To check the 2-letter code for the language you want to translate, you can use the table List of ISO 639-1 codes. +To check the 2-letter code for the language you want to translate, you can use the table List of ISO 639-1 codes. #### Request a New Language From 8488d31aff7da56915f424d0b16e2b1cad70ec2d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 15:48:06 +0000 Subject: [PATCH 117/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9304032108..a91ea5a2b8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ๐Ÿ“ Update docs for translations. PR [#14830](https://github.com/fastapi/fastapi/pull/14830) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Fix duplicate word in `advanced-dependencies.md`. PR [#14815](https://github.com/fastapi/fastapi/pull/14815) by [@Rayyan-Oumlil](https://github.com/Rayyan-Oumlil). ### Translations From da9e101d5007dbb35bfe4fa695bbc2e22b42d568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 07:56:49 -0800 Subject: [PATCH 118/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-outdated)=20(#14831)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/tr/docs/advanced/wsgi.md | 22 +++++++++++++++++++--- docs/tr/docs/index.md | 18 ++++++------------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/tr/docs/advanced/wsgi.md b/docs/tr/docs/advanced/wsgi.md index 442f83a59a..6f6b10b68a 100644 --- a/docs/tr/docs/advanced/wsgi.md +++ b/docs/tr/docs/advanced/wsgi.md @@ -1,18 +1,34 @@ # WSGI'yi Dahil Etme - Flask, Django ve DiฤŸerleri { #including-wsgi-flask-django-others } -WSGI uygulamalarฤฑnฤฑ [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bรถlรผmlerinde gรถrdรผฤŸรผnรผz gibi mount edebilirsiniz. +WSGI uygulamalarฤฑnฤฑ [Alt Uygulamalar - Mount Etme](sub-applications.md){.internal-link target=_blank}, [Bir Proxy Arkasฤฑnda](behind-a-proxy.md){.internal-link target=_blank} bรถlรผmlerinde gรถrdรผฤŸรผnรผz gibi mount edebilirsiniz. Bunun iรงin `WSGIMiddleware`'ฤฑ kullanabilir ve bunu WSGI uygulamanฤฑzฤฑ (รถrneฤŸin Flask, Django vb.) sarmalamak iรงin kullanabilirsiniz. ## `WSGIMiddleware` Kullanฤฑmฤฑ { #using-wsgimiddleware } -`WSGIMiddleware`'ฤฑ import etmeniz gerekir. +/// info | Bilgi + +Bunun iรงin `a2wsgi` kurulmalฤฑdฤฑr; รถrneฤŸin `pip install a2wsgi` ile. + +/// + +`WSGIMiddleware`'ฤฑ `a2wsgi` paketinden import etmeniz gerekir. Ardฤฑndan WSGI (รถrn. Flask) uygulamasฤฑnฤฑ middleware ile sarmalayฤฑn. Ve sonra bunu bir path'in altฤฑna mount edin. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | Not + +ร–nceden, `fastapi.middleware.wsgi` iรงindeki `WSGIMiddleware`'ฤฑn kullanฤฑlmasฤฑ รถneriliyordu, ancak artฤฑk kullanฤฑmdan kaldฤฑrฤฑldฤฑ. + +Bunun yerine `a2wsgi` paketini kullanmanฤฑz รถnerilir. Kullanฤฑm aynฤฑdฤฑr. + +Sadece `a2wsgi` paketinin kurulu olduฤŸundan emin olun ve `WSGIMiddleware`'ฤฑ `a2wsgi` iรงinden doฤŸru ลŸekilde import edin. + +/// ## Kontrol Edelim { #check-it } diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index 9cffd4274f..16c425f5d7 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" ลžu iรงerikle `main.py` adฤฑnda bir dosya oluลŸturalฤฑm: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): EฤŸer kodunuz `async` / `await` kullanฤฑyorsa, `async def` kullanฤฑn: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ Alternatif otomatik dokรผmantasyonu gรถreceksiniz ( Date: Thu, 5 Feb 2026 15:57:15 +0000 Subject: [PATCH 119/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a91ea5a2b8..e85e3aa871 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo). From 4fe06cc24a9e502be2e2aeef9eeb236cc959dea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 08:02:22 -0800 Subject: [PATCH 120/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(update-outdated)=20(#14832)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/es/docs/advanced/wsgi.md | 22 ++++++++++++++++--- docs/es/docs/deployment/docker.md | 6 ++--- docs/es/docs/index.md | 18 +++++---------- docs/es/docs/tutorial/body-multiple-params.md | 6 ++--- .../tutorial/path-operation-configuration.md | 4 ++-- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/docs/es/docs/advanced/wsgi.md b/docs/es/docs/advanced/wsgi.md index d5113250ab..ae31185eef 100644 --- a/docs/es/docs/advanced/wsgi.md +++ b/docs/es/docs/advanced/wsgi.md @@ -2,17 +2,33 @@ Puedes montar aplicaciones WSGI como viste con [Sub Aplicaciones - Mounts](sub-applications.md){.internal-link target=_blank}, [Detrรกs de un Proxy](behind-a-proxy.md){.internal-link target=_blank}. -Para eso, puedes usar `WSGIMiddleware` y usarlo para envolver tu aplicaciรณn WSGI, por ejemplo, Flask, Django, etc. +Para eso, puedes usar el `WSGIMiddleware` y usarlo para envolver tu aplicaciรณn WSGI, por ejemplo, Flask, Django, etc. ## Usando `WSGIMiddleware` { #using-wsgimiddleware } -Necesitas importar `WSGIMiddleware`. +/// info | Informaciรณn + +Esto requiere instalar `a2wsgi`, por ejemplo con `pip install a2wsgi`. + +/// + +Necesitas importar `WSGIMiddleware` de `a2wsgi`. Luego envuelve la aplicaciรณn WSGI (p. ej., Flask) con el middleware. Y luego mรณntala bajo un path. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | Nota + +Anteriormente, se recomendaba usar `WSGIMiddleware` de `fastapi.middleware.wsgi`, pero ahora estรก deprecado. + +Se aconseja usar el paquete `a2wsgi` en su lugar. El uso sigue siendo el mismo. + +Solo asegรบrate de tener instalado el paquete `a2wsgi` e importar `WSGIMiddleware` correctamente desde `a2wsgi`. + +/// ## Revisa { #check-it } diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index 114a62ec35..9a0b889559 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -145,8 +145,6 @@ Existen otros formatos y herramientas para definir e instalar dependencias de pa * Crea un archivo `main.py` con: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -572,7 +570,7 @@ Si tienes una configuraciรณn simple, con un **contenedor รบnico** que luego inic ### Imagen Base de Docker { #base-docker-image } -Solรญa haber una imagen official de Docker de FastAPI: tiangolo/uvicorn-gunicorn-fastapi-docker. Pero ahora estรก obsoleta. โ›”๏ธ +Solรญa haber una imagen official de Docker de FastAPI: tiangolo/uvicorn-gunicorn-fastapi. Pero ahora estรก obsoleta. โ›”๏ธ Probablemente **no** deberรญas usar esta imagen base de Docker (o cualquier otra similar). diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 14fa07e413..ffea0ed546 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" Crea un archivo `main.py` con: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): Si tu cรณdigo usa `async` / `await`, usa `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ Ahora modifica el archivo `main.py` para recibir un body desde un request `PUT`. Declara el body usando tipos estรกndar de Python, gracias a Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} diff --git a/docs/es/docs/tutorial/body-multiple-params.md b/docs/es/docs/tutorial/body-multiple-params.md index 57cec16743..c52486f9b8 100644 --- a/docs/es/docs/tutorial/body-multiple-params.md +++ b/docs/es/docs/tutorial/body-multiple-params.md @@ -101,13 +101,13 @@ Por supuesto, tambiรฉn puedes declarar parรกmetros adicionales de query siempre Como, por defecto, los valores singulares se interpretan como parรกmetros de query, no tienes que aรฑadir explรญcitamente un `Query`, solo puedes hacer: ```Python -q: Union[str, None] = None +q: str | None = None ``` -O en Python 3.10 y superior: +O en Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` Por ejemplo: diff --git a/docs/es/docs/tutorial/path-operation-configuration.md b/docs/es/docs/tutorial/path-operation-configuration.md index 945574b9e8..f57b322fbb 100644 --- a/docs/es/docs/tutorial/path-operation-configuration.md +++ b/docs/es/docs/tutorial/path-operation-configuration.md @@ -52,7 +52,7 @@ En estos casos, podrรญa tener sentido almacenar las tags en un `Enum`. Puedes aรฑadir un `summary` y `description`: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## Descripciรณn desde docstring { #description-from-docstring } @@ -70,7 +70,7 @@ Serรก usado en la documentaciรณn interactiva: Puedes especificar la descripciรณn del response con el parรกmetro `response_description`: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | Informaciรณn From afb44f0ff83fef758144639a5e284e2f43d25eb9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 16:03:19 +0000 Subject: [PATCH 121/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e85e3aa871..c9470e138c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo). From 136d5f0a56493e289b58838abc82479d50b61df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 08:04:47 -0800 Subject: [PATCH 122/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update-outdated)=20(#14835)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .../ko/docs/advanced/advanced-dependencies.md | 8 ++--- docs/ko/docs/advanced/wsgi.md | 36 +++++++++++++------ docs/ko/docs/deployment/docker.md | 12 +++---- docs/ko/docs/index.md | 28 ++++++--------- docs/ko/docs/tutorial/body-multiple-params.md | 7 ++-- .../tutorial/path-operation-configuration.md | 8 ++--- 6 files changed, 54 insertions(+), 45 deletions(-) diff --git a/docs/ko/docs/advanced/advanced-dependencies.md b/docs/ko/docs/advanced/advanced-dependencies.md index 04e557d15b..fe16062586 100644 --- a/docs/ko/docs/advanced/advanced-dependencies.md +++ b/docs/ko/docs/advanced/advanced-dependencies.md @@ -79,13 +79,13 @@ checker(q="somequery") ### `yield`์™€ `scope`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ { #dependencies-with-yield-and-scope } -0.121.0 ๋ฒ„์ „์—์„œ FastAPI๋Š” `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์— ๋Œ€ํ•ด `Depends(scope="function")` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. +0.121.0 ๋ฒ„์ „์—์„œ FastAPI๋Š” `Depends(scope="function")` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. `Depends(scope="function")`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, `yield` ์ดํ›„์˜ ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๊ฐ€ ๋๋‚œ ์งํ›„(ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์ด ๋ฐ˜ํ™˜๋˜๊ธฐ ์ „)์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  `Depends(scope="request")`(๊ธฐ๋ณธ๊ฐ’)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, `yield` ์ดํ›„์˜ ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” ์‘๋‹ต์ด ์ „์†ก๋œ ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. -์ž์„ธํ•œ ๋‚ด์šฉ์€ [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. +์ž์„ธํ•œ ๋‚ด์šฉ์€ [`yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ - ์กฐ๊ธฐ ์ข…๋ฃŒ์™€ `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ### `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ๊ณผ `StreamingResponse`, ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ { #dependencies-with-yield-and-streamingresponse-technical-details } @@ -133,7 +133,7 @@ SQLModel(๋˜๋Š” SQLAlchemy)์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋Ÿฐ ํŠน์ • ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ๊ทธ๋Ÿฌ๋ฉด ์„ธ์…˜์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ํ•ด์ œํ•˜์—ฌ, ๋‹ค๋ฅธ ์š”์ฒญ๋“ค์ด ์ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -`yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์—์„œ ์กฐ๊ธฐ ์ข…๋ฃŒ๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ตฌ์ฒด์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์— ๋Œ€ํ•œ ์กฐ๊ธฐ ์ข…๋ฃŒ๊ฐ€ ์–ด๋–ค ์ ์—์„œ ์ด๋“์ด ๋˜๋Š”์ง€๋ฅผ ํฌํ•จํ•ด GitHub Discussion Question์„ ์ƒ์„ฑํ•ด ์ฃผ์„ธ์š”. +`yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์—์„œ ์กฐ๊ธฐ ์ข…๋ฃŒ๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ตฌ์ฒด์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์— ๋Œ€ํ•œ ์กฐ๊ธฐ ์ข…๋ฃŒ๊ฐ€ ์–ด๋–ค ์ ์—์„œ ์ด๋“์ด ๋˜๋Š”์ง€๋ฅผ ํฌํ•จํ•ด GitHub Discussions ์งˆ๋ฌธ์„ ์ƒ์„ฑํ•ด ์ฃผ์„ธ์š”. `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์—์„œ ์กฐ๊ธฐ ์ข…๋ฃŒ์— ๋Œ€ํ•œ ์„ค๋“๋ ฅ ์žˆ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋‹ค๋ฉด, ์กฐ๊ธฐ ์ข…๋ฃŒ๋ฅผ ์„ ํƒ์ ์œผ๋กœ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๋ฐฉ๋ฒ•์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. @@ -145,7 +145,7 @@ FastAPI 0.110.0 ์ด์ „์—๋Š” `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•œ ๋‹ค์Œ ๊ทธ ### ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํƒœ์Šคํฌ์™€ `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ, ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ { #background-tasks-and-dependencies-with-yield-technical-details } -FastAPI 0.106.0 ์ด์ „์—๋Š” `yield` ์ดํ›„์— ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค. `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์˜ ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” ์‘๋‹ต์ด ์ „์†ก๋œ *ํ›„์—* ์‹คํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}๊ฐ€ ์ด๋ฏธ ์‹คํ–‰๋œ ๋’ค์˜€์Šต๋‹ˆ๋‹ค. +FastAPI 0.106.0 ์ด์ „์—๋Š” `yield` ์ดํ›„์— ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค. `yield`๊ฐ€ ์žˆ๋Š” ์˜์กด์„ฑ์˜ ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” ์‘๋‹ต์ด ์ „์†ก๋œ *ํ›„์—* ์‹คํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, [์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}๊ฐ€ ์ด๋ฏธ ์‹คํ–‰๋œ ๋’ค์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ฃผ๋กœ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํƒœ์Šคํฌ ์•ˆ์—์„œ ์˜์กด์„ฑ์ด "yield"ํ•œ ๋™์ผํ•œ ๊ฐ์ฒด๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ ์„ค๊ณ„์˜€์Šต๋‹ˆ๋‹ค. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํƒœ์Šคํฌ๊ฐ€ ๋๋‚œ ๋’ค์— ์ข…๋ฃŒ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/wsgi.md b/docs/ko/docs/advanced/wsgi.md index 89cf57cfef..5e0e87c5e7 100644 --- a/docs/ko/docs/advanced/wsgi.md +++ b/docs/ko/docs/advanced/wsgi.md @@ -1,32 +1,48 @@ -# WSGI ํฌํ•จํ•˜๊ธฐ - Flask, Django ๊ทธ ์™ธ { #including-wsgi-flask-django-others } +# WSGI ํฌํ•จํ•˜๊ธฐ - Flask, Django ๋“ฑ { #including-wsgi-flask-django-others } -[์„œ๋ธŒ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ - ๋งˆ์šดํŠธ](sub-applications.md){.internal-link target=_blank}, [ํ”„๋ก์‹œ ๋’คํŽธ์—์„œ](behind-a-proxy.md){.internal-link target=_blank}์—์„œ ๋ณด์•˜๋“ฏ์ด WSGI ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ๋งˆ์šดํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +[์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ๋งˆ์šดํŠธ](sub-applications.md){.internal-link target=_blank}, [ํ”„๋ก์‹œ ๋’ค์—์„œ](behind-a-proxy.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ WSGI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งˆ์šดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์ด๋ฅผ ์œ„ํ•ด `WSGIMiddleware`๋ฅผ ์‚ฌ์šฉํ•ด WSGI ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Flask, Django ๋“ฑ)์„ ๊ฐ์Œ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋ฅผ ์œ„ํ•ด `WSGIMiddleware`๋ฅผ ์‚ฌ์šฉํ•ด WSGI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์˜ˆ: Flask, Django ๋“ฑ)์„ ๊ฐ์Œ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ## `WSGIMiddleware` ์‚ฌ์šฉํ•˜๊ธฐ { #using-wsgimiddleware } -`WSGIMiddleware`๋ฅผ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. +/// info | ์ •๋ณด -๊ทธ๋Ÿฐ ๋‹ค์Œ, WSGI(์˜ˆ: Flask) ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋ฏธ๋“ค์›จ์–ด๋กœ ํฌ์žฅํ•ฉ๋‹ˆ๋‹ค. +์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด `a2wsgi`๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: `pip install a2wsgi` -๊ทธ ํ›„, ํ•ด๋‹น ๊ฒฝ๋กœ์— ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค. +/// -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +`a2wsgi`์—์„œ `WSGIMiddleware`๋ฅผ import ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ ๋‹ค์Œ, WSGI(์˜ˆ: Flask) ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ์Œ‰๋‹ˆ๋‹ค. + +๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๊ฒฝ๋กœ์— ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค. + +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | ์ฐธ๊ณ  + +์ด์ „์— `fastapi.middleware.wsgi`์˜ `WSGIMiddleware` ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ–ˆ์ง€๋งŒ ์ด์ œ๋Š” ๋” ์ด์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + +๋Œ€์‹  `a2wsgi` ํŒจํ‚ค์ง€ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. + +๋‹จ, `a2wsgi` ํŒจํ‚ค์ง€๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ๊ณ  `a2wsgi`์—์„œ `WSGIMiddleware`๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ import ํ•˜๋Š”์ง€๋งŒ ํ™•์ธํ•˜์„ธ์š”. + +/// ## ํ™•์ธํ•˜๊ธฐ { #check-it } -์ด์ œ `/v1/` ๊ฒฝ๋กœ์— ์žˆ๋Š” ๋ชจ๋“  ์š”์ฒญ์€ Flask ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. +์ด์ œ `/v1/` ๊ฒฝ๋กœ์— ์žˆ๋Š” ๋ชจ๋“  ์š”์ฒญ์€ Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋จธ์ง€๋Š” **FastAPI**์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. -์‹คํ–‰ํ•˜๋ฉด http://localhost:8000/v1/์œผ๋กœ ์ด๋™ํ•ด์„œ Flask์˜ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +์‹คํ–‰ํ•˜๊ณ  http://localhost:8000/v1/๋กœ ์ด๋™ํ•˜๋ฉด Flask์˜ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```txt Hello, World from Flask! ``` -๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•˜๋ฉด http://localhost:8000/v2 **FastAPI**์˜ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +๊ทธ๋ฆฌ๊ณ  http://localhost:8000/v2๋กœ ์ด๋™ํ•˜๋ฉด **FastAPI**์˜ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```JSON { diff --git a/docs/ko/docs/deployment/docker.md b/docs/ko/docs/deployment/docker.md index be04c923a5..20e341c269 100644 --- a/docs/ko/docs/deployment/docker.md +++ b/docs/ko/docs/deployment/docker.md @@ -145,8 +145,6 @@ Successfully installed fastapi pydantic * ๋‹ค์Œ ๋‚ด์šฉ์œผ๋กœ `main.py` ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -245,14 +243,14 @@ Docker ์ง€์‹œ์–ด cluster๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—์„œ(**์›Œ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Uvicorn** ๊ฐ™์€) **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๋ฅผ ์“ฐ๋Š” ๋Œ€์‹ , **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ **๋ณต์ œ๋ฅผ ์ฒ˜๋ฆฌ**ํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. +**Kubernetes**, Docker Swarm Mode, Nomad ๋“ฑ์˜ ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์œผ๋กœ ์—ฌ๋Ÿฌ ๋จธ์‹ ์— ๋ถ„์‚ฐ๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—์„œ(**์›Œ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Uvicorn** ๊ฐ™์€) **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๋ฅผ ์“ฐ๋Š” ๋Œ€์‹ , **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ **๋ณต์ œ๋ฅผ ์ฒ˜๋ฆฌ**ํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. Kubernetes ๊ฐ™์€ ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์€ ๋ณดํ†ต ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ**์„ ์ง€์›ํ•˜๋ฉด์„œ๋„, **์ปจํ…Œ์ด๋„ˆ ๋ณต์ œ**๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ†ตํ•ฉ๋œ ๋ฐฉ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ์š”. @@ -580,7 +578,7 @@ Kubernetes๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ด๋Š” ์•„๋งˆ๋„ ์ž๋™์™„์„ฑ. ์ ์€ ๋””๋ฒ„๊น… ์‹œ๊ฐ„. +* **์ง๊ด€์ **: ํ›Œ๋ฅญํ•œ ํŽธ์ง‘๊ธฐ ์ง€์›. ๋ชจ๋“  ๊ณณ์—์„œ ์ž๋™์™„์„ฑ. ์ ์€ ๋””๋ฒ„๊น… ์‹œ๊ฐ„. * **์‰ฌ์›€**: ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ๋ฐฐ์šฐ๋„๋ก ์„ค๊ณ„. ์ ์€ ๋ฌธ์„œ ์ฝ๊ธฐ ์‹œ๊ฐ„. * **์งง์Œ**: ์ฝ”๋“œ ์ค‘๋ณต ์ตœ์†Œํ™”. ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ์˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ. ์ ์€ ๋ฒ„๊ทธ. * **๊ฒฌ๊ณ ํ•จ**: ์ค€๋น„๋œ ํ”„๋กœ๋•์…˜ ์šฉ ์ฝ”๋“œ๋ฅผ ์–ป์œผ์‹ญ์‹œ์˜ค. ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์™€ ํ•จ๊ป˜. @@ -127,7 +127,7 @@ FastAPI๋Š” ํ˜„๋Œ€์ ์ด๊ณ , ๋น ๋ฅด๋ฉฐ(๊ณ ์„ฑ๋Šฅ), ํŒŒ์ด์ฌ ํ‘œ์ค€ ํƒ€์ž… ํžŒํŠธ -์›น API ๋Œ€์‹  ํ„ฐ๋ฏธ๋„์—์„œ ์‚ฌ์šฉํ•  CLI ์•ฑ์„ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๋ฉด, **Typer**๋ฅผ ํ™•์ธํ•ด ๋ณด์‹ญ์‹œ์˜ค. +์›น API ๋Œ€์‹  ํ„ฐ๋ฏธ๋„์—์„œ ์‚ฌ์šฉํ•  CLI ์•ฑ์„ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๋ฉด, **Typer**๋ฅผ ํ™•์ธํ•ด ๋ณด์‹ญ์‹œ์˜ค. **Typer**๋Š” FastAPI์˜ ๋™์ƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  **CLI๋ฅผ ์œ„ํ•œ FastAPI**๊ฐ€ ๋˜๊ธฐ ์œ„ํ•ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. โŒจ๏ธ ๐Ÿš€ @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" ๋‹ค์Œ ๋‚ด์šฉ์œผ๋กœ `main.py` ํŒŒ์ผ์„ ๋งŒ๋“œ์‹ญ์‹œ์˜ค: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ๊ฐ€ `async` / `await`์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, `async def`๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ INFO: Application startup complete. Pydantic ๋•๋ถ„์— ํ‘œ์ค€ Python ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ๋ณธ๋ฌธ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -374,7 +368,7 @@ item: Item * ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ: * ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์„ ๋•Œ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ช…ํ™•ํ•œ ์—๋Ÿฌ. * ๊นŠ์ด ์ค‘์ฒฉ๋œ JSON ๊ฐ์ฒด์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ. -* ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ๋„คํŠธ์›Œํฌ์—์„œ ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์œผ๋กœ ์ „์†ก. ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค: +* ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ๋„คํŠธ์›Œํฌ์—์„œ ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์œผ๋กœ ์ „์†ก. ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค: * JSON. * ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜. * ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜. @@ -382,7 +376,7 @@ item: Item * ํ—ค๋”. * ํผ(Forms). * ํŒŒ์ผ. -* ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์„ ๋„คํŠธ์›Œํฌ ๋ฐ์ดํ„ฐ๋กœ ์ „ํ™˜(JSON ํ˜•์‹์œผ๋กœ): +* ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์„ ๋„คํŠธ์›Œํฌ ๋ฐ์ดํ„ฐ๋กœ ์ „ํ™˜(JSON ํ˜•์‹์œผ๋กœ): * ํŒŒ์ด์ฌ ํƒ€์ž… ๋ณ€ํ™˜ (`str`, `int`, `float`, `bool`, `list`, ๋“ฑ). * `datetime` ๊ฐ์ฒด. * `UUID` ๊ฐ์ฒด. @@ -445,7 +439,7 @@ item: Item * ์„œ๋กœ ๋‹ค๋ฅธ ์žฅ์†Œ์—์„œ **๋งค๊ฐœ๋ณ€์ˆ˜** ์„ ์–ธ: **ํ—ค๋”**, **์ฟ ํ‚ค**, **ํผ ํ•„๋“œ** ๊ทธ๋ฆฌ๊ณ  **ํŒŒ์ผ**. * `maximum_length` ๋˜๋Š” `regex`์ฒ˜๋Ÿผ **์œ ํšจ์„ฑ ์ œ์•ฝ**ํ•˜๋Š” ๋ฐฉ๋ฒ•. -* ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด **์˜์กด์„ฑ ์ฃผ์ž…** ์‹œ์Šคํ…œ. +* ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด **์˜์กด์„ฑ ์ฃผ์ž…** ์‹œ์Šคํ…œ. * **OAuth2** ์ง€์›์„ ํฌํ•จํ•œ **JWT tokens** ๋ฐ **HTTP Basic**์„ ๊ฐ–๋Š” ๋ณด์•ˆ๊ณผ ์ธ์ฆ. * (Pydantic ๋•๋ถ„์—) **๊นŠ์€ ์ค‘์ฒฉ JSON ๋ชจ๋ธ**์„ ์„ ์–ธํ•˜๋Š”๋ฐ ๋” ์ง„๋ณดํ•œ (ํ•˜์ง€๋งŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‰ฌ์šด) ๊ธฐ์ˆ . * Strawberry ๋ฐ ๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ **GraphQL** ํ†ตํ•ฉ. diff --git a/docs/ko/docs/tutorial/body-multiple-params.md b/docs/ko/docs/tutorial/body-multiple-params.md index 701351e637..bebdffed80 100644 --- a/docs/ko/docs/tutorial/body-multiple-params.md +++ b/docs/ko/docs/tutorial/body-multiple-params.md @@ -103,15 +103,16 @@ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ์ผ ๊ฐ’์€ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•ด์„๋˜๋ฏ€๋กœ, ๋ช…์‹œ์ ์œผ๋กœ `Query`๋ฅผ ์ถ”๊ฐ€ํ•  ํ•„์š” ์—†์ด ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: ```Python -q: Union[str, None] = None +q: str | None = None ``` -๋˜๋Š” Python 3.10 ์ด์ƒ์—์„œ๋Š”: +๋˜๋Š” Python 3.9์—์„œ๋Š”: ```Python -q: str | None = None +q: Union[str, None] = None ``` + ์˜ˆ๋ฅผ ๋“ค์–ด: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/ko/docs/tutorial/path-operation-configuration.md b/docs/ko/docs/tutorial/path-operation-configuration.md index b8a87667a0..baef3fb403 100644 --- a/docs/ko/docs/tutorial/path-operation-configuration.md +++ b/docs/ko/docs/tutorial/path-operation-configuration.md @@ -52,11 +52,11 @@ `summary`์™€ `description`์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## ๋…์ŠคํŠธ๋ง์œผ๋กœ ๋งŒ๋“  ์„ค๋ช… { #description-from-docstring } -์„ค๋ช…์€ ๋ณดํ†ต ๊ธธ์–ด์ง€๊ณ  ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์ณ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์„ค๋ช…์„ ํ•จ์ˆ˜ docstring์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ๊ทธ๊ณณ์—์„œ ์ด๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. +์„ค๋ช…์€ ๋ณดํ†ต ๊ธธ์–ด์ง€๊ณ  ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์ณ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์„ค๋ช…์„ ํ•จ์ˆ˜ docstring์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ๊ทธ๊ณณ์—์„œ ์ด๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ๋…์ŠคํŠธ๋ง์—๋Š” Markdown์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, (๋…์ŠคํŠธ๋ง์˜ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ) ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด์„๋˜๊ณ  ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. @@ -70,7 +70,7 @@ `response_description` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‘๋‹ต์— ๊ด€ํ•œ ์„ค๋ช…์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | ์ •๋ณด @@ -90,7 +90,7 @@ OpenAPI๋Š” ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์‘๋‹ต์— ๊ด€ํ•œ ์„ค๋ช…์„ ์š”๊ตฌํ•  ๊ฒƒ์„ ## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ง€์›์ค‘๋‹จํ•˜๊ธฐ { #deprecate-a-path-operation } -*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ  deprecated๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋ฉด, `deprecated` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ  deprecated๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋ฉด, `deprecated` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: {* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} From 2224b4e63b13a97a3132c7c1ff0cc2476d02527b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 08:05:03 -0800 Subject: [PATCH 123/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-outdated)=20(#14833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .../pt/docs/advanced/advanced-dependencies.md | 2 +- docs/pt/docs/advanced/wsgi.md | 20 ++++++++++++-- docs/pt/docs/deployment/docker.md | 6 ++--- docs/pt/docs/index.md | 26 +++++++------------ docs/pt/docs/tutorial/body-multiple-params.md | 6 ++--- .../tutorial/path-operation-configuration.md | 4 +-- 6 files changed, 36 insertions(+), 28 deletions(-) diff --git a/docs/pt/docs/advanced/advanced-dependencies.md b/docs/pt/docs/advanced/advanced-dependencies.md index 1ad9ea617f..959a7f3c2b 100644 --- a/docs/pt/docs/advanced/advanced-dependencies.md +++ b/docs/pt/docs/advanced/advanced-dependencies.md @@ -148,7 +148,7 @@ Antes do FastAPI 0.106.0, lanรงar exceรงรตes apรณs o `yield` nรฃo era possรญvel, Isso foi projetado assim principalmente para permitir o uso dos mesmos objetos "yielded" por dependรชncias dentro de tarefas em segundo plano, porque o cรณdigo de saรญda seria executado depois que as tarefas em segundo plano fossem concluรญdas. -Isso foi alterado no FastAPI 0.106.0 com a intenรงรฃo de nรฃo manter recursos enquanto se espera a resposta percorrer a rede. +Isso foi alterado no FastAPI 0.106.0 com a intenรงรฃo de nรฃo manter recursos enquanto se espera a response percorrer a rede. /// tip | Dica diff --git a/docs/pt/docs/advanced/wsgi.md b/docs/pt/docs/advanced/wsgi.md index c3c21d430a..99b783cdbe 100644 --- a/docs/pt/docs/advanced/wsgi.md +++ b/docs/pt/docs/advanced/wsgi.md @@ -6,13 +6,29 @@ Para isso, vocรช pode utilizar o `WSGIMiddleware` para encapsular a sua aplicaรง ## Usando `WSGIMiddleware` { #using-wsgimiddleware } -Vocรช precisa importar o `WSGIMiddleware`. +/// info | Informaรงรฃo + +Isso requer instalar `a2wsgi`, por exemplo com `pip install a2wsgi`. + +/// + +Vocรช precisa importar o `WSGIMiddleware` de `a2wsgi`. Em seguida, encapsule a aplicaรงรฃo WSGI (e.g. Flask) com o middleware. E entรฃo monte isso sob um path. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | Nota + +Anteriormente, recomendava-se usar `WSGIMiddleware` de `fastapi.middleware.wsgi`, mas agora estรก descontinuado. + +ร‰ aconselhรกvel usar o pacote `a2wsgi` em seu lugar. O uso permanece o mesmo. + +Apenas certifique-se de que o pacote `a2wsgi` estรก instalado e importe `WSGIMiddleware` corretamente de `a2wsgi`. + +/// ## Confira { #check-it } diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md index b26a69b54f..d47a153946 100644 --- a/docs/pt/docs/deployment/docker.md +++ b/docs/pt/docs/deployment/docker.md @@ -145,8 +145,6 @@ Hรก outros formatos e ferramentas para definir e instalar dependรชncias de pacot * Crie um arquivo `main.py` com: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -572,7 +570,7 @@ Se vocรช tiver uma configuraรงรฃo simples, com um **รบnico contรชiner** que ent ### Imagem Docker base { #base-docker-image } -Antes havia uma imagem oficial do FastAPI para Docker: tiangolo/uvicorn-gunicorn-fastapi. Mas agora ela estรก descontinuada. โ›”๏ธ +Antes havia uma imagem oficial do FastAPI para Docker: tiangolo/uvicorn-gunicorn-fastapi-docker. Mas agora ela estรก descontinuada. โ›”๏ธ Vocรช provavelmente **nรฃo** deve usar essa imagem base do Docker (ou qualquer outra semelhante). diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index 4e3be586da..e61cc2e2f4 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -33,7 +33,7 @@ --- -FastAPI รฉ um moderno e rรกpido (alta performance) _framework web_ para construรงรฃo de APIs com Python, baseado nos _type hints_ padrรตes do Python. +FastAPI รฉ um moderno e rรกpido (alta performance) framework web para construรงรฃo de APIs com Python, baseado nos type hints padrรตes do Python. Os recursos chave sรฃo: @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" Crie um arquivo `main.py` com: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): Se seu cรณdigo utiliza `async` / `await`, use `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ Agora modifique o arquivo `main.py` para receber um corpo de uma requisiรงรฃo `P Declare o corpo utilizando tipos padrรฃo Python, graรงas ao Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -411,7 +405,7 @@ Voltando ao cรณdigo do exemplo anterior, **FastAPI** irรก: * Documentar tudo com OpenAPI, que poderรก ser usado por: * Sistemas de documentaรงรฃo interativos. * Sistemas de clientes de geraรงรฃo de cรณdigo automรกticos, para muitas linguagens. -* Fornecer diretamente 2 interfaces _web_ de documentaรงรฃo interativa. +* Fornecer diretamente 2 interfaces web de documentaรงรฃo interativa. --- @@ -510,7 +504,7 @@ Siga os tutoriais do seu provedor de nuvem para implantar aplicaรงรตes FastAPI c ## Performance { #performance } -Testes de performance da _Independent TechEmpower_ mostram aplicaรงรตes **FastAPI** rodando sob Uvicorn como um dos _frameworks_ Python mais rรกpidos disponรญveis, somente atrรกs de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) +Testes de performance da Independent TechEmpower mostram aplicaรงรตes **FastAPI** rodando sob Uvicorn como um dos frameworks Python mais rรกpidos disponรญveis, somente atrรกs de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) Para entender mais sobre isso, veja a seรงรฃo Comparaรงรตes. @@ -530,7 +524,7 @@ Utilizado pelo Starlette: * httpx - Obrigatรณrio caso vocรช queira utilizar o `TestClient`. * jinja2 - Obrigatรณrio se vocรช quer utilizar a configuraรงรฃo padrรฃo de templates. -* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. +* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. Utilizado pelo FastAPI: diff --git a/docs/pt/docs/tutorial/body-multiple-params.md b/docs/pt/docs/tutorial/body-multiple-params.md index 3cba04912c..24f35b2105 100644 --- a/docs/pt/docs/tutorial/body-multiple-params.md +++ b/docs/pt/docs/tutorial/body-multiple-params.md @@ -101,13 +101,13 @@ Obviamente, vocรช tambรฉm pode declarar parรขmetros de consulta assim que vocรช Dado que, por padrรฃo, valores singulares sรฃo interpretados como parรขmetros de consulta, vocรช nรฃo precisa explicitamente adicionar uma `Query`, vocรช pode somente: ```Python -q: Union[str, None] = None +q: str | None = None ``` -Ou como em Python 3.10 e versรตes superiores: +Ou em Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` Por exemplo: diff --git a/docs/pt/docs/tutorial/path-operation-configuration.md b/docs/pt/docs/tutorial/path-operation-configuration.md index 84eebc1285..2527c28922 100644 --- a/docs/pt/docs/tutorial/path-operation-configuration.md +++ b/docs/pt/docs/tutorial/path-operation-configuration.md @@ -52,7 +52,7 @@ Nestes casos, pode fazer sentido armazenar as tags em um `Enum`. Vocรช pode adicionar um `summary` e uma `description`: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## Descriรงรฃo do docstring { #description-from-docstring } @@ -70,7 +70,7 @@ Ela serรก usada nas documentaรงรตes interativas: Vocรช pode especificar a descriรงรฃo da resposta com o parรขmetro `response_description`: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | Informaรงรฃo From 3578270af481d006bac53e1659640ce0bf257dba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 16:05:18 +0000 Subject: [PATCH 124/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c9470e138c..7da59e9f21 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo). From b892c3126c270d5f2b695034703bdae2a2f148ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 08:06:07 -0800 Subject: [PATCH 125/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-outdated)=20(#14836)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/de/docs/advanced/wsgi.md | 20 +++++++++++++++++-- docs/de/docs/deployment/docker.md | 4 +--- docs/de/docs/index.md | 18 ++++++----------- docs/de/docs/tutorial/body-multiple-params.md | 8 ++++---- .../tutorial/path-operation-configuration.md | 4 ++-- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md index 3cd776a6ab..0090883cea 100644 --- a/docs/de/docs/advanced/wsgi.md +++ b/docs/de/docs/advanced/wsgi.md @@ -6,13 +6,29 @@ Dazu kรถnnen Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wr ## `WSGIMiddleware` verwenden { #using-wsgimiddleware } -Sie mรผssen `WSGIMiddleware` importieren. +/// info | Info + +Dafรผr muss `a2wsgi` installiert sein, z. B. mit `pip install a2wsgi`. + +/// + +Sie mรผssen `WSGIMiddleware` aus `a2wsgi` importieren. Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware. Und dann mounten Sie das auf einem Pfad. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | Hinweis + +Frรผher wurde empfohlen, `WSGIMiddleware` aus `fastapi.middleware.wsgi` zu verwenden, dies ist jetzt deprecatet. + +Stattdessen wird empfohlen, das Paket `a2wsgi` zu verwenden. Die Nutzung bleibt gleich. + +Stellen Sie lediglich sicher, dass das Paket `a2wsgi` installiert ist und importieren Sie `WSGIMiddleware` korrekt aus `a2wsgi`. + +/// ## Es testen { #check-it } diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md index d4b74635d3..1e28efe521 100644 --- a/docs/de/docs/deployment/docker.md +++ b/docs/de/docs/deployment/docker.md @@ -145,8 +145,6 @@ Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhรคn * Erstellen Sie eine `main.py`-Datei mit: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index 11fb6c9832..3ce5cb27ff 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" Erstellen Sie eine Datei `main.py` mit: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): Wenn Ihr Code `async` / `await` verwendet, benutzen Sie `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ Sie sehen die alternative automatische Dokumentation (bereitgestellt von Requestbody-Deklarationen an. +Nun, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmรถglichkeiten von Requestbody-Deklarationen an. ## `Path`-, `Query`- und Body-Parameter vermischen { #mix-path-query-and-body-parameters } @@ -101,13 +101,13 @@ Natรผrlich kรถnnen Sie auch, wann immer Sie das brauchen, weitere Query-Paramete Da einfache Werte standardmรครŸig als Query-Parameter interpretiert werden, mรผssen Sie `Query` nicht explizit hinzufรผgen, Sie kรถnnen einfach schreiben: ```Python -q: Union[str, None] = None +q: str | None = None ``` -Oder in Python 3.10 und darรผber: +Oder in Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` Zum Beispiel: diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md index 3427b30528..a06c85e570 100644 --- a/docs/de/docs/tutorial/path-operation-configuration.md +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -52,7 +52,7 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern. Sie kรถnnen eine `summary` und eine `description` hinzufรผgen: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## Beschreibung mittels Docstring { #description-from-docstring } @@ -70,7 +70,7 @@ Es wird in der interaktiven Dokumentation verwendet: Sie kรถnnen die Response mit dem Parameter `response_description` beschreiben: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | Info From b82993643ecb709f3d732794c93f2562ae64731e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 16:06:09 +0000 Subject: [PATCH 126/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7da59e9f21..52aa38b8bc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo). From 2838dcb4a832ef65c3a98463593dda0aea0b982c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 16:06:44 +0000 Subject: [PATCH 127/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 52aa38b8bc..e4864ce0f1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo). From 457cd75c234bce2c1ec53abe9a6a1f6def0fcd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 08:11:07 -0800 Subject: [PATCH 128/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(translate-page)=20(#14837)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/fr/docs/deployment/manually.md | 182 +++++++++++++--------------- 1 file changed, 86 insertions(+), 96 deletions(-) diff --git a/docs/fr/docs/deployment/manually.md b/docs/fr/docs/deployment/manually.md index 3f99ccd9f6..c0c388b02c 100644 --- a/docs/fr/docs/deployment/manually.md +++ b/docs/fr/docs/deployment/manually.md @@ -1,167 +1,157 @@ -# Exรฉcuter un serveur manuellement - Uvicorn +# Exรฉcuter un serveur manuellement { #run-a-server-manually } -La principale chose dont vous avez besoin pour exรฉcuter une application **FastAPI** sur une machine serveur distante est un programme serveur ASGI tel que **Uvicorn**. +## Utiliser la commande `fastapi run` { #use-the-fastapi-run-command } -Il existe 3 principales alternativesย : +En bref, utilisez `fastapi run` pour servir votre application FastAPIย : -* Uvicornย : un serveur ASGI haute performance. -* Hypercornย : un serveur - ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalitรฉs. -* Daphneย : le serveur ASGI - conรงu pour Django Channels. - -## Machine serveur et programme serveur - -Il y a un petit dรฉtail sur les noms ร  garder ร  l'esprit. ๐Ÿ’ก - -Le mot "**serveur**" est couramment utilisรฉ pour dรฉsigner ร  la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et รฉgalement le programme qui s'exรฉcute sur cette machine (par exemple, Uvicorn). +
-Gardez cela ร  l'esprit lorsque vous lisez "serveur" en gรฉnรฉral, cela pourrait faire rรฉfรฉrence ร  l'une de ces deux choses. +```console +$ fastapi run main.py -Lorsqu'on se rรฉfรจre ร  la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nล“ud**. Tout cela fait rรฉfรฉrence ร  un type de machine distante, exรฉcutant Linux, en rรจgle gรฉnรฉrale, sur laquelle vous exรฉcutez des programmes. + FastAPI Starting production server ๐Ÿš€ + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -## Installer le programme serveur + module ๐Ÿ main.py -Vous pouvez installer un serveur compatible ASGI avecย : + code Importing the FastAPI app object from the module with + the following code: -//// tab | Uvicorn + from main import app -* Uvicorn, un serveur ASGI rapide comme l'รฉclair, basรฉ sur uvloop et httptools. + app Using import string: main:app -
+ server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs -```console -$ pip install "uvicorn[standard]" + Logs: ----> 100% + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) ```
-/// tip | Astuce +Cela fonctionnerait pour la plupart des cas. ๐Ÿ˜Ž -En ajoutant `standard`, Uvicorn va installer et utiliser quelques dรฉpendances supplรฉmentaires recommandรฉes. +Vous pourriez utiliser cette commande par exemple pour dรฉmarrer votre application **FastAPI** dans un conteneur, sur un serveur, etc. -Cela inclut `uvloop`, le remplaรงant performant de `asyncio`, qui fournit le gros gain de performance en matiรจre de concurrence. +## Serveurs ASGI { #asgi-servers } -/// +Allons un peu plus en dรฉtail. -//// +FastAPI utilise un standard pour construire des frameworks web Python et des serveurs appelรฉ ASGI. FastAPI est un framework web ASGI. -//// tab | Hypercorn +La principale chose dont vous avez besoin pour exรฉcuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui utilisรฉ par dรฉfaut par la commande `fastapi`. -* Hypercorn, un serveur ASGI รฉgalement compatible avec HTTP/2. +Il existe plusieurs alternatives, notammentย : -
+* Uvicornย : un serveur ASGI haute performance. +* Hypercornย : un serveur ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalitรฉs. +* Daphneย : le serveur ASGI conรงu pour Django Channels. +* Granianย : un serveur HTTP Rust pour les applications Python. +* NGINX Unitย : NGINX Unit est un environnement d'exรฉcution d'applications web lรฉger et polyvalent. -```console -$ pip install hypercorn +## Machine serveur et programme serveur { #server-machine-and-server-program } ----> 100% -``` - -
+Il y a un petit dรฉtail sur les noms ร  garder ร  l'esprit. ๐Ÿ’ก -...ou tout autre serveur ASGI. +Le mot ยซ serveur ยป est couramment utilisรฉ pour dรฉsigner ร  la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et รฉgalement le programme qui s'exรฉcute sur cette machine (par exemple, Uvicorn). -//// +Gardez cela ร  l'esprit lorsque vous lisez ยซ serveur ยป en gรฉnรฉral, cela pourrait faire rรฉfรฉrence ร  l'une de ces deux choses. -## Exรฉcutez le programme serveur +Lorsqu'on se rรฉfรจre ร  la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nล“ud**. Tout cela fait rรฉfรฉrence ร  un type de machine distante, exรฉcutant normalement Linux, sur laquelle vous exรฉcutez des programmes. -Vous pouvez ensuite exรฉcuter votre application de la mรชme maniรจre que vous l'avez fait dans les tutoriels, mais sans l'option `--reload`, par exempleย : +## Installer le programme serveur { #install-the-server-program } -//// tab | Uvicorn +Lorsque vous installez FastAPI, il est fourni avec un serveur de production, Uvicorn, et vous pouvez le dรฉmarrer avec la commande `fastapi run`. -
+Mais vous pouvez รฉgalement installer un serveur ASGI manuellement. -```console -$ uvicorn main:app --host 0.0.0.0 --port 80 +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, puis vous pouvez installer l'application serveur. -INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) -``` - -
- -//// - -//// tab | Hypercorn +Par exemple, pour installer Uvicornย :
```console -$ hypercorn main:app --bind 0.0.0.0:80 +$ pip install "uvicorn[standard]" -Running on 0.0.0.0:8080 over http (CTRL + C to quit) +---> 100% ```
-//// +Un processus similaire s'appliquerait ร  tout autre programme de serveur ASGI. -/// warning +/// tip | Astuce -N'oubliez pas de supprimer l'option `--reload` si vous l'utilisiez. +En ajoutant `standard`, Uvicorn va installer et utiliser quelques dรฉpendances supplรฉmentaires recommandรฉes. - L'option `--reload` consomme beaucoup plus de ressources, est plus instable, etc. +Cela inclut `uvloop`, le remplaรงant hautes performances de `asyncio`, qui fournit le gros gain de performance en matiรจre de concurrence. - Cela aide beaucoup pendant le **dรฉveloppement**, mais vous **ne devriez pas** l'utiliser en **production**. +Lorsque vous installez FastAPI avec quelque chose comme `pip install "fastapi[standard]"`, vous obtenez dรฉjร  `uvicorn[standard]` aussi. /// -## Hypercorn avec Trio - -Starlette et **FastAPI** sont basรฉs sur -AnyIO, qui les rend -compatibles avec asyncio, de la bibliothรจque standard Python et -Trio. - -Nรฉanmoins, Uvicorn n'est actuellement compatible qu'avec asyncio, et il utilise normalement `uvloop`, le remplaรงant hautes performances de `asyncio`. +## Exรฉcuter le programme serveur { #run-the-server-program } -Mais si vous souhaitez utiliser directement **Trio**, vous pouvez utiliser **Hypercorn** car il le prend en charge. โœจ - -### Installer Hypercorn avec Trio - -Vous devez d'abord installer Hypercorn avec le support Trioย : +Si vous avez installรฉ un serveur ASGI manuellement, vous devrez normalement passer une chaรฎne d'import dans un format spรฉcial pour qu'il importe votre application FastAPIย :
```console -$ pip install "hypercorn[trio]" ----> 100% +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) ```
-### Exรฉcuter avec Trio +/// note | Remarque -Ensuite, vous pouvez passer l'option de ligne de commande `--worker-class` avec la valeur `trio`ย : +La commande `uvicorn main:app` fait rรฉfรฉrence ร ย : -
+* `main`ย : le fichier `main.py` (le ยซ module ยป Python). +* `app`ย : l'objet crรฉรฉ dans `main.py` avec la ligne `app = FastAPI()`. -```console -$ hypercorn main:app --worker-class trio +C'est รฉquivalent ร ย : + +```Python +from main import app ``` -
+/// + +Chaque programme de serveur ASGI alternatif aurait une commande similaire, vous pouvez en lire plus dans leur documentation respective. + +/// warning | Alertes -Et cela dรฉmarrera Hypercorn avec votre application en utilisant Trio comme backend. +Uvicorn et d'autres serveurs prennent en charge une option `--reload` utile pendant le dรฉveloppement. -Vous pouvez dรฉsormais utiliser Trio en interne dans votre application. Ou mieux encore, vous pouvez utiliser AnyIO pour que votre code reste compatible avec Trio et asyncio. ๐ŸŽ‰ +L'option `--reload` consomme beaucoup plus de ressources, est plus instable, etc. + +Cela aide beaucoup pendant le **dรฉveloppement**, mais vous **ne devriez pas** l'utiliser en **production**. + +/// -## Concepts de dรฉploiement +## Concepts de dรฉploiement { #deployment-concepts } -Ces exemples lancent le programme serveur (e.g. Uvicorn), dรฉmarrant **un seul processus**, sur toutes les IPs (`0.0. -0.0`) sur un port prรฉdรฉfini (par example, `80`). +Ces exemples exรฉcutent le programme serveur (par exemple Uvicorn), en dรฉmarrant **un seul processus**, ร  l'รฉcoute sur toutes les IP (`0.0.0.0`) sur un port prรฉdรฉfini (par exemple `80`). -C'est l'idรฉe de base. Mais vous vous prรฉoccuperez probablement de certains concepts supplรฉmentaires, tels que ... : +C'est l'idรฉe de base. Mais vous voudrez probablement vous occuper de certaines choses supplรฉmentaires, commeย : -* la sรฉcuritรฉ - HTTPS -* l'exรฉcution au dรฉmarrage -* les redรฉmarrages -* la rรฉplication (le nombre de processus en cours d'exรฉcution) -* la mรฉmoire -* les รฉtapes prรฉcรฉdant le dรฉmarrage +* Sรฉcuritรฉ - HTTPS +* Exรฉcution au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉcรฉdant le dรฉmarrage -Je vous en dirai plus sur chacun de ces concepts, sur la faรงon de les aborder, et donnerai quelques exemples concrets avec des stratรฉgies pour les traiter dans les prochains chapitres. ๐Ÿš€ +Je vous en dirai plus sur chacun de ces concepts, sur la maniรจre d'y rรฉflรฉchir, et donnerai quelques exemples concrets avec des stratรฉgies pour les gรฉrer dans les prochains chapitres. ๐Ÿš€ From 464c359bb03f7ba72330198cc9f44df36194837d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 16:11:33 +0000 Subject: [PATCH 129/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e4864ce0f1..2fea9e79c2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for fr (translate-page). PR [#14837](https://github.com/fastapi/fastapi/pull/14837) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo). From b49435becdf53942be248fc2ffc7f53df5ac313c Mon Sep 17 00:00:00 2001 From: Jonathan Fulton Date: Thu, 5 Feb 2026 13:23:16 -0500 Subject: [PATCH 130/367] =?UTF-8?q?=E2=9C=A8=20Allow=20`Response`=20type?= =?UTF-8?q?=20hint=20as=20dependency=20annotation=20(#14794)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastiรกn Ramรญrez --- fastapi/dependencies/utils.py | 5 +- tests/test_response_dependency.py | 173 ++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 tests/test_response_dependency.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index fc5dfed85a..3037b233b9 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -449,7 +449,9 @@ def analyze_param( depends = dataclasses.replace(depends, dependency=type_annotation) # Handle non-param type annotations like Request - if lenient_issubclass( + # Only apply special handling when there's no explicit Depends - if there's a Depends, + # the dependency will be called and its return value used instead of the special injection + if depends is None and lenient_issubclass( type_annotation, ( Request, @@ -460,7 +462,6 @@ def analyze_param( SecurityScopes, ), ): - assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}" assert field_info is None, ( f"Cannot specify FastAPI annotation for type {type_annotation!r}" ) diff --git a/tests/test_response_dependency.py b/tests/test_response_dependency.py new file mode 100644 index 0000000000..38c3595948 --- /dev/null +++ b/tests/test_response_dependency.py @@ -0,0 +1,173 @@ +"""Test using special types (Response, Request, BackgroundTasks) as dependency annotations. + +These tests verify that special FastAPI types can be used with Depends() annotations +and that the dependency injection system properly handles them. +""" + +from typing import Annotated + +from fastapi import BackgroundTasks, Depends, FastAPI, Request, Response +from fastapi.responses import JSONResponse +from fastapi.testclient import TestClient + + +def test_response_with_depends_annotated(): + """Response type hint should work with Annotated[Response, Depends(...)].""" + app = FastAPI() + + def modify_response(response: Response) -> Response: + response.headers["X-Custom"] = "modified" + return response + + @app.get("/") + def endpoint(response: Annotated[Response, Depends(modify_response)]): + return {"status": "ok"} + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.json() == {"status": "ok"} + assert resp.headers.get("X-Custom") == "modified" + + +def test_response_with_depends_default(): + """Response type hint should work with Response = Depends(...).""" + app = FastAPI() + + def modify_response(response: Response) -> Response: + response.headers["X-Custom"] = "modified" + return response + + @app.get("/") + def endpoint(response: Response = Depends(modify_response)): + return {"status": "ok"} + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.json() == {"status": "ok"} + assert resp.headers.get("X-Custom") == "modified" + + +def test_response_without_depends(): + """Regular Response injection should still work.""" + app = FastAPI() + + @app.get("/") + def endpoint(response: Response): + response.headers["X-Direct"] = "set" + return {"status": "ok"} + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.json() == {"status": "ok"} + assert resp.headers.get("X-Direct") == "set" + + +def test_response_dependency_chain(): + """Response dependency should work in a chain of dependencies.""" + app = FastAPI() + + def first_modifier(response: Response) -> Response: + response.headers["X-First"] = "1" + return response + + def second_modifier( + response: Annotated[Response, Depends(first_modifier)], + ) -> Response: + response.headers["X-Second"] = "2" + return response + + @app.get("/") + def endpoint(response: Annotated[Response, Depends(second_modifier)]): + return {"status": "ok"} + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.headers.get("X-First") == "1" + assert resp.headers.get("X-Second") == "2" + + +def test_response_dependency_returns_different_response_instance(): + """Dependency that returns a different Response instance should work. + + When a dependency returns a new Response object (e.g., JSONResponse) instead + of modifying the injected one, the returned response should be used and any + modifications to it in the endpoint should be preserved. + """ + app = FastAPI() + + def default_response() -> Response: + response = JSONResponse(content={"status": "ok"}) + response.headers["X-Custom"] = "initial" + return response + + @app.get("/") + def endpoint(response: Annotated[Response, Depends(default_response)]): + response.headers["X-Custom"] = "modified" + return response + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.json() == {"status": "ok"} + assert resp.headers.get("X-Custom") == "modified" + + +# Tests for Request type hint with Depends +def test_request_with_depends_annotated(): + """Request type hint should work in dependency chain.""" + app = FastAPI() + + def extract_request_info(request: Request) -> dict: + return { + "path": request.url.path, + "user_agent": request.headers.get("user-agent", "unknown"), + } + + @app.get("/") + def endpoint( + info: Annotated[dict, Depends(extract_request_info)], + ): + return info + + client = TestClient(app) + resp = client.get("/", headers={"user-agent": "test-agent"}) + + assert resp.status_code == 200 + assert resp.json() == {"path": "/", "user_agent": "test-agent"} + + +# Tests for BackgroundTasks type hint with Depends +def test_background_tasks_with_depends_annotated(): + """BackgroundTasks type hint should work with Annotated[BackgroundTasks, Depends(...)].""" + app = FastAPI() + task_results = [] + + def background_task(message: str): + task_results.append(message) + + def add_background_task(background_tasks: BackgroundTasks) -> BackgroundTasks: + background_tasks.add_task(background_task, "from dependency") + return background_tasks + + @app.get("/") + def endpoint( + background_tasks: Annotated[BackgroundTasks, Depends(add_background_task)], + ): + background_tasks.add_task(background_task, "from endpoint") + return {"status": "ok"} + + client = TestClient(app) + resp = client.get("/") + + assert resp.status_code == 200 + assert "from dependency" in task_results + assert "from endpoint" in task_results From 0dd42b746e17d33a74ea267a62eace9ccdccf345 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 18:23:44 +0000 Subject: [PATCH 131/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2fea9e79c2..43600561b9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* โœจ Allow `Response` type hint as dependency annotation. PR [#14794](https://github.com/fastapi/fastapi/pull/14794) by [@jonathan-fulton](https://github.com/jonathan-fulton). + ### Docs * ๐Ÿ“ Update docs for translations. PR [#14830](https://github.com/fastapi/fastapi/pull/14830) by [@tiangolo](https://github.com/tiangolo). From 97145588f5442aa7c3830173813d5d1a2c893521 Mon Sep 17 00:00:00 2001 From: Albin Skott Date: Thu, 5 Feb 2026 19:34:34 +0100 Subject: [PATCH 132/367] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20PEP69?= =?UTF-8?q?5=20`TypeAliasType`=20(#13920)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: lokidev Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov Co-authored-by: Sebastiรกn Ramรญrez --- fastapi/dependencies/utils.py | 4 ++++ pyproject.toml | 1 + tests/test_dependency_pep695.py | 27 +++++++++++++++++++++++++++ uv.lock | 2 ++ 4 files changed, 34 insertions(+) create mode 100644 tests/test_dependency_pep695.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 3037b233b9..e5ac51d53c 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -66,6 +66,7 @@ from starlette.requests import HTTPConnection, Request from starlette.responses import Response from starlette.websockets import WebSocket from typing_extensions import Literal, get_args, get_origin +from typing_inspection.typing_objects import is_typealiastype multipart_not_installed_error = ( 'Form data requires "python-multipart" to be installed. \n' @@ -370,6 +371,9 @@ def analyze_param( depends = None type_annotation: Any = Any use_annotation: Any = Any + if is_typealiastype(annotation): + # unpack in case PEP 695 type syntax is used + annotation = annotation.__value__ if annotation is not inspect.Signature.empty: use_annotation = annotation type_annotation = annotation diff --git a/pyproject.toml b/pyproject.toml index 0f6bf1e4ac..e62baa5f85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,7 @@ dependencies = [ "starlette>=0.40.0,<0.51.0", "pydantic>=2.7.0", "typing-extensions>=4.8.0", + "typing-inspection>=0.4.2", "annotated-doc>=0.0.2", ] diff --git a/tests/test_dependency_pep695.py b/tests/test_dependency_pep695.py new file mode 100644 index 0000000000..ef5636638e --- /dev/null +++ b/tests/test_dependency_pep695.py @@ -0,0 +1,27 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI +from fastapi.testclient import TestClient +from typing_extensions import TypeAliasType + + +async def some_value() -> int: + return 123 + + +DependedValue = TypeAliasType( + "DependedValue", Annotated[int, Depends(some_value)], type_params=() +) + + +def test_pep695_type_dependencies(): + app = FastAPI() + + @app.get("/") + async def get_with_dep(value: DependedValue) -> str: # noqa + return f"value: {value}" + + client = TestClient(app) + response = client.get("/") + assert response.status_code == 200 + assert response.text == '"value: 123"' diff --git a/uv.lock b/uv.lock index 931a27021b..db5d2e9b1a 100644 --- a/uv.lock +++ b/uv.lock @@ -1021,6 +1021,7 @@ dependencies = [ { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions" }, + { name = "typing-inspection" }, ] [package.optional-dependencies] @@ -1202,6 +1203,7 @@ requires-dist = [ { name = "pyyaml", marker = "extra == 'all'", specifier = ">=5.3.1" }, { name = "starlette", specifier = ">=0.40.0,<0.51.0" }, { name = "typing-extensions", specifier = ">=4.8.0" }, + { name = "typing-inspection", specifier = ">=0.4.2" }, { name = "ujson", marker = "extra == 'all'", specifier = ">=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.12.0" }, From 54f8aeeb9a15e4d5a12401ec5549840966df0087 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 18:34:59 +0000 Subject: [PATCH 133/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 43600561b9..3280ad6994 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Features +* โœจ Add support for PEP695 `TypeAliasType`. PR [#13920](https://github.com/fastapi/fastapi/pull/13920) by [@cstruct](https://github.com/cstruct). * โœจ Allow `Response` type hint as dependency annotation. PR [#14794](https://github.com/fastapi/fastapi/pull/14794) by [@jonathan-fulton](https://github.com/jonathan-fulton). ### Docs From c5fd75a321496b1f8212744bde217ec8ea956154 Mon Sep 17 00:00:00 2001 From: Kanetsuna Masaya <156692516+mkanetsuna@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:41:43 +0900 Subject: [PATCH 134/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20using=20`Json[list?= =?UTF-8?q?[str]]`=20type=20(issue=20#10997)=20(#14616)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastiรกn Ramรญrez --- fastapi/dependencies/utils.py | 12 +++++-- tests/test_json_type.py | 63 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/test_json_type.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index e5ac51d53c..b8f7f948c6 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -51,7 +51,7 @@ from fastapi.logger import logger from fastapi.security.oauth2 import SecurityScopes from fastapi.types import DependencyCacheKey from fastapi.utils import create_model_field, get_path_param_names -from pydantic import BaseModel +from pydantic import BaseModel, Json from pydantic.fields import FieldInfo from starlette.background import BackgroundTasks as StarletteBackgroundTasks from starlette.concurrency import run_in_threadpool @@ -726,11 +726,19 @@ def _validate_value_with_model_field( return v_, [] +def _is_json_field(field: ModelField) -> bool: + return any(type(item) is Json for item in field.field_info.metadata) + + def _get_multidict_value( field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None ) -> Any: alias = alias or get_validation_alias(field) - if is_sequence_field(field) and isinstance(values, (ImmutableMultiDict, Headers)): + if ( + (not _is_json_field(field)) + and is_sequence_field(field) + and isinstance(values, (ImmutableMultiDict, Headers)) + ): value = values.getlist(alias) else: value = values.get(alias, None) diff --git a/tests/test_json_type.py b/tests/test_json_type.py new file mode 100644 index 0000000000..3e213eaca4 --- /dev/null +++ b/tests/test_json_type.py @@ -0,0 +1,63 @@ +import json +from typing import Annotated + +from fastapi import Cookie, FastAPI, Form, Header, Query +from fastapi.testclient import TestClient +from pydantic import Json + +app = FastAPI() + + +@app.post("/form-json-list") +def form_json_list(items: Annotated[Json[list[str]], Form()]) -> list[str]: + return items + + +@app.get("/query-json-list") +def query_json_list(items: Annotated[Json[list[str]], Query()]) -> list[str]: + return items + + +@app.get("/header-json-list") +def header_json_list(x_items: Annotated[Json[list[str]], Header()]) -> list[str]: + return x_items + + +@app.get("/cookie-json-list") +def cookie_json_list(items: Annotated[Json[list[str]], Cookie()]) -> list[str]: + return items + + +client = TestClient(app) + + +def test_form_json_list(): + response = client.post( + "/form-json-list", data={"items": json.dumps(["abc", "def"])} + ) + assert response.status_code == 200, response.text + assert response.json() == ["abc", "def"] + + +def test_query_json_list(): + response = client.get( + "/query-json-list", params={"items": json.dumps(["abc", "def"])} + ) + assert response.status_code == 200, response.text + assert response.json() == ["abc", "def"] + + +def test_header_json_list(): + response = client.get( + "/header-json-list", headers={"x-items": json.dumps(["abc", "def"])} + ) + assert response.status_code == 200, response.text + assert response.json() == ["abc", "def"] + + +def test_cookie_json_list(): + client.cookies.set("items", json.dumps(["abc", "def"])) + response = client.get("/cookie-json-list") + assert response.status_code == 200, response.text + assert response.json() == ["abc", "def"] + client.cookies.clear() From 6646e2b94f13fe4145560d02cef05cfd3a6bc925 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 18:42:10 +0000 Subject: [PATCH 135/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3280ad6994..6ec199a167 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -12,6 +12,10 @@ hide: * โœจ Add support for PEP695 `TypeAliasType`. PR [#13920](https://github.com/fastapi/fastapi/pull/13920) by [@cstruct](https://github.com/cstruct). * โœจ Allow `Response` type hint as dependency annotation. PR [#14794](https://github.com/fastapi/fastapi/pull/14794) by [@jonathan-fulton](https://github.com/jonathan-fulton). +### Fixes + +* ๐Ÿ› Fix using `Json[list[str]]` type (issue #10997). PR [#14616](https://github.com/fastapi/fastapi/pull/14616) by [@mkanetsuna](https://github.com/mkanetsuna). + ### Docs * ๐Ÿ“ Update docs for translations. PR [#14830](https://github.com/fastapi/fastapi/pull/14830) by [@tiangolo](https://github.com/tiangolo). From 23ddf09dd197ba099edc1b06eba61f7fc20a5ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 11:25:49 -0800 Subject: [PATCH 136/367] =?UTF-8?q?=F0=9F=94=A8=20Add=20max=20pages=20to?= =?UTF-8?q?=20translate=20to=20configs=20(#14840)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/translate.yml | 6 ++++++ scripts/translate.py | 23 ++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index 83518614b0..bb23fa32d9 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -35,6 +35,11 @@ on: type: boolean required: false default: false + max: + description: Maximum number of items to translate (e.g. 10) + type: number + required: false + default: 10 jobs: langs: @@ -115,3 +120,4 @@ jobs: EN_PATH: ${{ github.event.inputs.en_path }} COMMAND: ${{ matrix.command }} COMMIT_IN_PLACE: ${{ github.event.inputs.commit_in_place }} + MAX: ${{ github.event.inputs.max }} diff --git a/scripts/translate.py b/scripts/translate.py index 31c44583d1..ddcfa311d6 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -347,9 +347,12 @@ def list_outdated(language: str) -> list[Path]: @app.command() -def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: +def update_outdated( + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + max: Annotated[int, typer.Option(envvar="MAX")] = 10, +) -> None: outdated_paths = list_outdated(language) - for path in outdated_paths: + for path in outdated_paths[:max]: print(f"Updating lang: {language} path: {path}") translate_page(language=language, en_path=path) print(f"Done updating: {path}") @@ -357,9 +360,12 @@ def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) - @app.command() -def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: +def add_missing( + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + max: Annotated[int, typer.Option(envvar="MAX")] = 10, +) -> None: missing_paths = list_missing(language) - for path in missing_paths: + for path in missing_paths[:max]: print(f"Adding lang: {language} path: {path}") translate_page(language=language, en_path=path) print(f"Done adding: {path}") @@ -367,11 +373,14 @@ def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> No @app.command() -def update_and_add(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: +def update_and_add( + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + max: Annotated[int, typer.Option(envvar="MAX")] = 10, +) -> None: print(f"Updating outdated translations for {language}") - update_outdated(language=language) + update_outdated(language=language, max=max) print(f"Adding missing translations for {language}") - add_missing(language=language) + add_missing(language=language, max=max) print(f"Done updating and adding for {language}") From 8bdbd3725f7c88f3071ed9623da0945a269d3706 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 19:26:13 +0000 Subject: [PATCH 137/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6ec199a167..6a7fb926c6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -35,6 +35,10 @@ hide: * ๐ŸŒ Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* ๐Ÿ”จ Add max pages to translate to configs. PR [#14840](https://github.com/fastapi/fastapi/pull/14840) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.1 ### Features From 72325f698f7ab55e7df2f7fc40cc52693eadd687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 11:27:51 -0800 Subject: [PATCH 138/367] =?UTF-8?q?=F0=9F=8C=90=20Enable=20French=20docs?= =?UTF-8?q?=20translations=20(#14841)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 2 ++ scripts/docs.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index f713f2b122..38fe5f9cef 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -317,6 +317,8 @@ extra: name: de - Deutsch - link: /es/ name: es - espaรฑol + - link: /fr/ + name: fr - franรงais - link: /ja/ name: ja - ๆ—ฅๆœฌ่ชž - link: /ko/ diff --git a/scripts/docs.py b/scripts/docs.py index c1fb84bba7..4c065f9453 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -23,7 +23,7 @@ SUPPORTED_LANGS = { "de", "en", "es", - # "fr", + "fr", "ja", "ko", "pt", From 110b45d9b245d42a114a965bbd3039458afbf95e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 19:28:17 +0000 Subject: [PATCH 139/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6a7fb926c6..9e8760e99a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Translations +* ๐ŸŒ Enable French docs translations. PR [#14841](https://github.com/fastapi/fastapi/pull/14841) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for fr (translate-page). PR [#14837](https://github.com/fastapi/fastapi/pull/14837) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo). From 570e592a03c37c0436fea3727bd1be873417d9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 11:42:18 -0800 Subject: [PATCH 140/367] =?UTF-8?q?=F0=9F=8C=90=20Enable=20Traditional=20C?= =?UTF-8?q?hinese=20translations=20(#14842)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 2 ++ scripts/docs.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 38fe5f9cef..ccf5ffc7a0 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -331,6 +331,8 @@ extra: name: tr - Tรผrkรงe - link: /uk/ name: uk - ัƒะบั€ะฐั—ะฝััŒะบะฐ ะผะพะฒะฐ + - link: /zh-hant/ + name: zh-hant - ็น้ซ”ไธญๆ–‡ extra_css: - css/termynal.css - css/custom.css diff --git a/scripts/docs.py b/scripts/docs.py index 4c065f9453..2c7d6d5e4e 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -31,7 +31,7 @@ SUPPORTED_LANGS = { "tr", "uk", # "zh", - # "zh-hant", + "zh-hant", } From de56c96c640dddb224c0088ed6d949efbf86d853 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 19:42:42 +0000 Subject: [PATCH 141/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9e8760e99a..85a2157e0b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -38,6 +38,7 @@ hide: ### Internal +* ๐ŸŒ Enable Traditional Chinese translations. PR [#14842](https://github.com/fastapi/fastapi/pull/14842) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Add max pages to translate to configs. PR [#14840](https://github.com/fastapi/fastapi/pull/14840) by [@tiangolo](https://github.com/tiangolo). ## 0.128.1 From 79406a4b04078155ccc03e2d48ca0799836cfb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Feb 2026 20:46:37 +0100 Subject: [PATCH 142/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 4 +++- fastapi/__init__.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 85a2157e0b..c1a563f18b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.2 + ### Features * โœจ Add support for PEP695 `TypeAliasType`. PR [#13920](https://github.com/fastapi/fastapi/pull/13920) by [@cstruct](https://github.com/cstruct). @@ -23,6 +25,7 @@ hide: ### Translations +* ๐ŸŒ Enable Traditional Chinese translations. PR [#14842](https://github.com/fastapi/fastapi/pull/14842) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Enable French docs translations. PR [#14841](https://github.com/fastapi/fastapi/pull/14841) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for fr (translate-page). PR [#14837](https://github.com/fastapi/fastapi/pull/14837) by [@tiangolo](https://github.com/tiangolo). * ๐ŸŒ Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo). @@ -38,7 +41,6 @@ hide: ### Internal -* ๐ŸŒ Enable Traditional Chinese translations. PR [#14842](https://github.com/fastapi/fastapi/pull/14842) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”จ Add max pages to translate to configs. PR [#14840](https://github.com/fastapi/fastapi/pull/14840) by [@tiangolo](https://github.com/tiangolo). ## 0.128.1 diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 160e7235c3..99b9630d20 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.1" +__version__ = "0.128.2" from starlette import status as status From 3b8b310eda78d075ab8dd919bc17a9dce1c21f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 05:45:18 -0800 Subject: [PATCH 143/367] =?UTF-8?q?=F0=9F=91=B7=20Run=20tests=20with=20low?= =?UTF-8?q?er=20bound=20uv=20sync,=20upgrade=20`fastapi[all]`=20minimum=20?= =?UTF-8?q?dependencies:=20`ujson=20>=3D5.8.0`,=20`orjson=20>=3D3.9.3`=20(?= =?UTF-8?q?#14846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 11 +- pyproject.toml | 6 +- uv.lock | 1166 ++++++++++++++++++++---------------- 3 files changed, 664 insertions(+), 519 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5cbbde61fa..70710e3400 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,31 +49,40 @@ jobs: matrix: os: [ windows-latest, macos-latest ] python-version: [ "3.14" ] + uv-resolution: + - highest include: - os: ubuntu-latest python-version: "3.9" coverage: coverage + uv-resolution: lowest-direct - os: macos-latest python-version: "3.10" coverage: coverage + uv-resolution: highest - os: windows-latest python-version: "3.12" coverage: coverage + uv-resolution: lowest-direct - os: ubuntu-latest python-version: "3.13" coverage: coverage + uv-resolution: highest # Ubuntu with 3.13 needs coverage for CodSpeed benchmarks - os: ubuntu-latest python-version: "3.13" coverage: coverage + uv-resolution: highest codspeed: codspeed - os: ubuntu-latest python-version: "3.14" coverage: coverage + uv-resolution: highest fail-fast: false runs-on: ${{ matrix.os }} env: UV_PYTHON: ${{ matrix.python-version }} + UV_RESOLUTION: ${{ matrix.uv-resolution }} steps: - name: Dump GitHub context env: @@ -92,7 +101,7 @@ jobs: pyproject.toml uv.lock - name: Install Dependencies - run: uv sync --locked --no-dev --group tests --extra all + run: uv sync --no-dev --group tests --extra all - run: mkdir coverage - name: Test if: matrix.codspeed != 'codspeed' diff --git a/pyproject.toml b/pyproject.toml index e62baa5f85..ae9ae891e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,9 +108,9 @@ all = [ # For Starlette's schema generation, would not be used with FastAPI "pyyaml >=5.3.1", # For UJSONResponse - "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0", + "ujson >=5.8.0", # For ORJSONResponse - "orjson >=3.2.1", + "orjson >=3.9.3", # To validate email fields "email-validator >=2.0.0", # Uvicorn with uvloop @@ -167,7 +167,7 @@ tests = [ "anyio[trio]>=3.2.1,<5.0.0", "coverage[toml]>=6.5.0,<8.0", "dirty-equals==0.9.0", - "flask>=1.1.2,<4.0.0", + "flask>=3.0.0,<4.0.0", "inline-snapshot>=0.21.1", "mypy==1.14.1", "pwdlib[argon2]>=0.2.1", diff --git a/uv.lock b/uv.lock index db5d2e9b1a..435dddec5f 100644 --- a/uv.lock +++ b/uv.lock @@ -51,7 +51,7 @@ wheels = [ [[package]] name = "anthropic" -version = "0.75.0" +version = "0.78.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -63,9 +63,9 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/1f/08e95f4b7e2d35205ae5dcbb4ae97e7d477fc521c275c02609e2931ece2d/anthropic-0.75.0.tar.gz", hash = "sha256:e8607422f4ab616db2ea5baacc215dd5f028da99ce2f022e33c7c535b29f3dfb", size = 439565, upload-time = "2025-11-24T20:41:45.28Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/51/32849a48f9b1cfe80a508fd269b20bd8f0b1357c70ba092890fde5a6a10b/anthropic-0.78.0.tar.gz", hash = "sha256:55fd978ab9b049c61857463f4c4e9e092b24f892519c6d8078cee1713d8af06e", size = 509136, upload-time = "2026-02-05T17:52:04.986Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/1c/1cd02b7ae64302a6e06724bf80a96401d5313708651d277b1458504a1730/anthropic-0.75.0-py3-none-any.whl", hash = "sha256:ea8317271b6c15d80225a9f3c670152746e88805a7a61e14d4a374577164965b", size = 388164, upload-time = "2025-11-24T20:41:43.587Z" }, + { url = "https://files.pythonhosted.org/packages/3b/03/2f50931a942e5e13f80e24d83406714672c57964be593fc046d81369335b/anthropic-0.78.0-py3-none-any.whl", hash = "sha256:2a9887d2e99d1b0f9fe08857a1e9fe5d2d4030455dbf9ac65aab052e2efaeac4", size = 405485, upload-time = "2026-02-05T17:52:03.674Z" }, ] [[package]] @@ -184,11 +184,11 @@ wheels = [ [[package]] name = "babel" -version = "2.17.0" +version = "2.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] [[package]] @@ -256,21 +256,21 @@ wheels = [ [[package]] name = "boto3" -version = "1.42.24" +version = "1.42.43" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/21/8be0e3685c3a4868be48d8d2f6e5b4641727e1d8a5d396b8b401d2b5f06e/boto3-1.42.24.tar.gz", hash = "sha256:c47a2f40df933e3861fc66fd8d6b87ee36d4361663a7e7ba39a87f5a78b2eae1", size = 112788, upload-time = "2026-01-07T20:30:51.019Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/47/29afb754de7df0a0ebceaa9d83e209136ef7b62744259a6c09862fef4765/boto3-1.42.43.tar.gz", hash = "sha256:01fc5501209b23849fb30b01c6c086583ac91c40842a76083662fbfb84a82491", size = 112844, upload-time = "2026-02-05T20:31:44.974Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/75/bbfccb268f9faa4f59030888e859dca9797a980b77d6a074113af73bd4bf/boto3-1.42.24-py3-none-any.whl", hash = "sha256:8ed6ad670a5a2d7f66c1b0d3362791b48392c7a08f78479f5d8ab319a4d9118f", size = 140572, upload-time = "2026-01-07T20:30:49.431Z" }, + { url = "https://files.pythonhosted.org/packages/80/92/584447b14ae70f57f133a4bc64393902a72a3087486a7c09ce1bab25263c/boto3-1.42.43-py3-none-any.whl", hash = "sha256:44ddcaa37c350333c5a4799f533e786a595a97f1ee2fd7fc3e394cdebeb15e44", size = 140603, upload-time = "2026-02-05T20:31:43.698Z" }, ] [[package]] name = "botocore" -version = "1.42.24" +version = "1.42.43" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, @@ -278,9 +278,9 @@ dependencies = [ { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/12/d7/bb4a4e839b238ffb67b002d7326b328ebe5eb23ed5180f2ca10399a802de/botocore-1.42.24.tar.gz", hash = "sha256:be8d1bea64fb91eea08254a1e5fea057e4428d08e61f4e11083a02cafc1f8cc6", size = 14878455, upload-time = "2026-01-07T20:30:40.379Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/d6/def916ad1d13de5d511074afcde538a958e2e8a7c7020fb698d1f392f63b/botocore-1.42.43.tar.gz", hash = "sha256:41d04ead0b0862eec21f841811fb5764fe370a2df9b319e0d5297325c50fba1b", size = 14934077, upload-time = "2026-02-05T20:31:35.15Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/d4/f2655d777eed8b069ecab3761454cb83f830f8be8b5b0d292e4b3a980d00/botocore-1.42.24-py3-none-any.whl", hash = "sha256:8fca9781d7c84f7ad070fceffaff7179c4aa7a5ffb27b43df9d1d957801e0a8d", size = 14551806, upload-time = "2026-01-07T20:30:38.103Z" }, + { url = "https://files.pythonhosted.org/packages/4c/a8/95656f91b795eb47b73a00d36c51c7a5729eafa632c7348caa068ff63e50/botocore-1.42.43-py3-none-any.whl", hash = "sha256:1c0e30f62e274978ac3bcab253e3a859febea634b72b5e343589db7d17f83cd6", size = 14610179, upload-time = "2026-02-05T20:31:32.727Z" }, ] [[package]] @@ -326,7 +326,8 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, + { name = "pycparser", version = "2.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and implementation_name != 'PyPy'" }, + { name = "pycparser", version = "3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and implementation_name != 'PyPy'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ @@ -553,7 +554,7 @@ wheels = [ [[package]] name = "cohere" -version = "5.20.1" +version = "5.20.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastavro" }, @@ -566,9 +567,9 @@ dependencies = [ { name = "types-requests", version = "2.32.4.20260107", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/ed/bb02083654bdc089ae4ef1cd7691fd2233f1fd9f32bcbfacc80ff57d9775/cohere-5.20.1.tar.gz", hash = "sha256:50973f63d2c6138ff52ce37d8d6f78ccc539af4e8c43865e960d68e0bf835b6f", size = 180820, upload-time = "2025-12-18T16:39:50.975Z" } +sdist = { url = "https://files.pythonhosted.org/packages/35/37/65af9c50b5d5772a5528c6a949799f98ae286b8ebb924e0fac0619b3ae88/cohere-5.20.4.tar.gz", hash = "sha256:3b3017048ff5d5b4f113180947d538ca3d0f274de5875f0345be4c8cb3d5119a", size = 180737, upload-time = "2026-02-05T14:47:54.639Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/e3/94eb11ac3ebaaa3a6afb5d2ff23db95d58bc468ae538c388edf49f2f20b5/cohere-5.20.1-py3-none-any.whl", hash = "sha256:d230fd13d95ba92ae927fce3dd497599b169883afc7954fe29b39fb8d5df5fc7", size = 318973, upload-time = "2025-12-18T16:39:49.504Z" }, + { url = "https://files.pythonhosted.org/packages/6d/14/5c5077c6b01aed7a18dfc5ab775a35c7a6cb118e5bc1dafcfc06abdb9d9e/cohere-5.20.4-py3-none-any.whl", hash = "sha256:9cc6ebb0adac3d9f96ac0efffde6a2484534fb0aec3684a62c250d49da958f29", size = 318987, upload-time = "2026-02-05T14:47:53.505Z" }, ] [[package]] @@ -701,105 +702,105 @@ toml = [ [[package]] name = "coverage" -version = "7.13.1" +version = "7.13.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/9a/3742e58fd04b233df95c012ee9f3dfe04708a5e1d32613bd2d47d4e1be0d/coverage-7.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1fa280b3ad78eea5be86f94f461c04943d942697e0dac889fa18fff8f5f9147", size = 218633, upload-time = "2025-12-28T15:40:10.165Z" }, - { url = "https://files.pythonhosted.org/packages/7e/45/7e6bdc94d89cd7c8017ce735cf50478ddfe765d4fbf0c24d71d30ea33d7a/coverage-7.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c3d8c679607220979434f494b139dfb00131ebf70bb406553d69c1ff01a5c33d", size = 219147, upload-time = "2025-12-28T15:40:12.069Z" }, - { url = "https://files.pythonhosted.org/packages/f7/38/0d6a258625fd7f10773fe94097dc16937a5f0e3e0cdf3adef67d3ac6baef/coverage-7.13.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:339dc63b3eba969067b00f41f15ad161bf2946613156fb131266d8debc8e44d0", size = 245894, upload-time = "2025-12-28T15:40:13.556Z" }, - { url = "https://files.pythonhosted.org/packages/27/58/409d15ea487986994cbd4d06376e9860e9b157cfbfd402b1236770ab8dd2/coverage-7.13.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db622b999ffe49cb891f2fff3b340cdc2f9797d01a0a202a0973ba2562501d90", size = 247721, upload-time = "2025-12-28T15:40:15.37Z" }, - { url = "https://files.pythonhosted.org/packages/da/bf/6e8056a83fd7a96c93341f1ffe10df636dd89f26d5e7b9ca511ce3bcf0df/coverage-7.13.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1443ba9acbb593fa7c1c29e011d7c9761545fe35e7652e85ce7f51a16f7e08d", size = 249585, upload-time = "2025-12-28T15:40:17.226Z" }, - { url = "https://files.pythonhosted.org/packages/f4/15/e1daff723f9f5959acb63cbe35b11203a9df77ee4b95b45fffd38b318390/coverage-7.13.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c832ec92c4499ac463186af72f9ed4d8daec15499b16f0a879b0d1c8e5cf4a3b", size = 246597, upload-time = "2025-12-28T15:40:19.028Z" }, - { url = "https://files.pythonhosted.org/packages/74/a6/1efd31c5433743a6ddbc9d37ac30c196bb07c7eab3d74fbb99b924c93174/coverage-7.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:562ec27dfa3f311e0db1ba243ec6e5f6ab96b1edfcfc6cf86f28038bc4961ce6", size = 247626, upload-time = "2025-12-28T15:40:20.846Z" }, - { url = "https://files.pythonhosted.org/packages/6d/9f/1609267dd3e749f57fdd66ca6752567d1c13b58a20a809dc409b263d0b5f/coverage-7.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4de84e71173d4dada2897e5a0e1b7877e5eefbfe0d6a44edee6ce31d9b8ec09e", size = 245629, upload-time = "2025-12-28T15:40:22.397Z" }, - { url = "https://files.pythonhosted.org/packages/e2/f6/6815a220d5ec2466383d7cc36131b9fa6ecbe95c50ec52a631ba733f306a/coverage-7.13.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a5a68357f686f8c4d527a2dc04f52e669c2fc1cbde38f6f7eb6a0e58cbd17cae", size = 245901, upload-time = "2025-12-28T15:40:23.836Z" }, - { url = "https://files.pythonhosted.org/packages/ac/58/40576554cd12e0872faf6d2c0eb3bc85f71d78427946ddd19ad65201e2c0/coverage-7.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:77cc258aeb29a3417062758975521eae60af6f79e930d6993555eeac6a8eac29", size = 246505, upload-time = "2025-12-28T15:40:25.421Z" }, - { url = "https://files.pythonhosted.org/packages/3b/77/9233a90253fba576b0eee81707b5781d0e21d97478e5377b226c5b096c0f/coverage-7.13.1-cp310-cp310-win32.whl", hash = "sha256:bb4f8c3c9a9f34423dba193f241f617b08ffc63e27f67159f60ae6baf2dcfe0f", size = 221257, upload-time = "2025-12-28T15:40:27.217Z" }, - { url = "https://files.pythonhosted.org/packages/e0/43/e842ff30c1a0a623ec80db89befb84a3a7aad7bfe44a6ea77d5a3e61fedd/coverage-7.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:c8e2706ceb622bc63bac98ebb10ef5da80ed70fbd8a7999a5076de3afaef0fb1", size = 222191, upload-time = "2025-12-28T15:40:28.916Z" }, - { url = "https://files.pythonhosted.org/packages/b4/9b/77baf488516e9ced25fc215a6f75d803493fc3f6a1a1227ac35697910c2a/coverage-7.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a55d509a1dc5a5b708b5dad3b5334e07a16ad4c2185e27b40e4dba796ab7f88", size = 218755, upload-time = "2025-12-28T15:40:30.812Z" }, - { url = "https://files.pythonhosted.org/packages/d7/cd/7ab01154e6eb79ee2fab76bf4d89e94c6648116557307ee4ebbb85e5c1bf/coverage-7.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d010d080c4888371033baab27e47c9df7d6fb28d0b7b7adf85a4a49be9298b3", size = 219257, upload-time = "2025-12-28T15:40:32.333Z" }, - { url = "https://files.pythonhosted.org/packages/01/d5/b11ef7863ffbbdb509da0023fad1e9eda1c0eaea61a6d2ea5b17d4ac706e/coverage-7.13.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d938b4a840fb1523b9dfbbb454f652967f18e197569c32266d4d13f37244c3d9", size = 249657, upload-time = "2025-12-28T15:40:34.1Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7c/347280982982383621d29b8c544cf497ae07ac41e44b1ca4903024131f55/coverage-7.13.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf100a3288f9bb7f919b87eb84f87101e197535b9bd0e2c2b5b3179633324fee", size = 251581, upload-time = "2025-12-28T15:40:36.131Z" }, - { url = "https://files.pythonhosted.org/packages/82/f6/ebcfed11036ade4c0d75fa4453a6282bdd225bc073862766eec184a4c643/coverage-7.13.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef6688db9bf91ba111ae734ba6ef1a063304a881749726e0d3575f5c10a9facf", size = 253691, upload-time = "2025-12-28T15:40:37.626Z" }, - { url = "https://files.pythonhosted.org/packages/02/92/af8f5582787f5d1a8b130b2dcba785fa5e9a7a8e121a0bb2220a6fdbdb8a/coverage-7.13.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0b609fc9cdbd1f02e51f67f51e5aee60a841ef58a68d00d5ee2c0faf357481a3", size = 249799, upload-time = "2025-12-28T15:40:39.47Z" }, - { url = "https://files.pythonhosted.org/packages/24/aa/0e39a2a3b16eebf7f193863323edbff38b6daba711abaaf807d4290cf61a/coverage-7.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c43257717611ff5e9a1d79dce8e47566235ebda63328718d9b65dd640bc832ef", size = 251389, upload-time = "2025-12-28T15:40:40.954Z" }, - { url = "https://files.pythonhosted.org/packages/73/46/7f0c13111154dc5b978900c0ccee2e2ca239b910890e674a77f1363d483e/coverage-7.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e09fbecc007f7b6afdfb3b07ce5bd9f8494b6856dd4f577d26c66c391b829851", size = 249450, upload-time = "2025-12-28T15:40:42.489Z" }, - { url = "https://files.pythonhosted.org/packages/ac/ca/e80da6769e8b669ec3695598c58eef7ad98b0e26e66333996aee6316db23/coverage-7.13.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a03a4f3a19a189919c7055098790285cc5c5b0b3976f8d227aea39dbf9f8bfdb", size = 249170, upload-time = "2025-12-28T15:40:44.279Z" }, - { url = "https://files.pythonhosted.org/packages/af/18/9e29baabdec1a8644157f572541079b4658199cfd372a578f84228e860de/coverage-7.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3820778ea1387c2b6a818caec01c63adc5b3750211af6447e8dcfb9b6f08dbba", size = 250081, upload-time = "2025-12-28T15:40:45.748Z" }, - { url = "https://files.pythonhosted.org/packages/00/f8/c3021625a71c3b2f516464d322e41636aea381018319050a8114105872ee/coverage-7.13.1-cp311-cp311-win32.whl", hash = "sha256:ff10896fa55167371960c5908150b434b71c876dfab97b69478f22c8b445ea19", size = 221281, upload-time = "2025-12-28T15:40:47.232Z" }, - { url = "https://files.pythonhosted.org/packages/27/56/c216625f453df6e0559ed666d246fcbaaa93f3aa99eaa5080cea1229aa3d/coverage-7.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:a998cc0aeeea4c6d5622a3754da5a493055d2d95186bad877b0a34ea6e6dbe0a", size = 222215, upload-time = "2025-12-28T15:40:49.19Z" }, - { url = "https://files.pythonhosted.org/packages/5c/9a/be342e76f6e531cae6406dc46af0d350586f24d9b67fdfa6daee02df71af/coverage-7.13.1-cp311-cp311-win_arm64.whl", hash = "sha256:fea07c1a39a22614acb762e3fbbb4011f65eedafcb2948feeef641ac78b4ee5c", size = 220886, upload-time = "2025-12-28T15:40:51.067Z" }, - { url = "https://files.pythonhosted.org/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", size = 218927, upload-time = "2025-12-28T15:40:52.814Z" }, - { url = "https://files.pythonhosted.org/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", size = 219288, upload-time = "2025-12-28T15:40:54.262Z" }, - { url = "https://files.pythonhosted.org/packages/d0/0a/853a76e03b0f7c4375e2ca025df45c918beb367f3e20a0a8e91967f6e96c/coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", size = 250786, upload-time = "2025-12-28T15:40:56.059Z" }, - { url = "https://files.pythonhosted.org/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", size = 253543, upload-time = "2025-12-28T15:40:57.585Z" }, - { url = "https://files.pythonhosted.org/packages/96/b2/7f1f0437a5c855f87e17cf5d0dc35920b6440ff2b58b1ba9788c059c26c8/coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", size = 254635, upload-time = "2025-12-28T15:40:59.443Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d1/73c3fdb8d7d3bddd9473c9c6a2e0682f09fc3dfbcb9c3f36412a7368bcab/coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", size = 251202, upload-time = "2025-12-28T15:41:01.328Z" }, - { url = "https://files.pythonhosted.org/packages/66/3c/f0edf75dcc152f145d5598329e864bbbe04ab78660fe3e8e395f9fff010f/coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", size = 252566, upload-time = "2025-12-28T15:41:03.319Z" }, - { url = "https://files.pythonhosted.org/packages/17/b3/e64206d3c5f7dcbceafd14941345a754d3dbc78a823a6ed526e23b9cdaab/coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", size = 250711, upload-time = "2025-12-28T15:41:06.411Z" }, - { url = "https://files.pythonhosted.org/packages/dc/ad/28a3eb970a8ef5b479ee7f0c484a19c34e277479a5b70269dc652b730733/coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", size = 250278, upload-time = "2025-12-28T15:41:08.285Z" }, - { url = "https://files.pythonhosted.org/packages/54/e3/c8f0f1a93133e3e1291ca76cbb63565bd4b5c5df63b141f539d747fff348/coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", size = 252154, upload-time = "2025-12-28T15:41:09.969Z" }, - { url = "https://files.pythonhosted.org/packages/d0/bf/9939c5d6859c380e405b19e736321f1c7d402728792f4c752ad1adcce005/coverage-7.13.1-cp312-cp312-win32.whl", hash = "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7", size = 221487, upload-time = "2025-12-28T15:41:11.468Z" }, - { url = "https://files.pythonhosted.org/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6", size = 222299, upload-time = "2025-12-28T15:41:13.386Z" }, - { url = "https://files.pythonhosted.org/packages/10/79/176a11203412c350b3e9578620013af35bcdb79b651eb976f4a4b32044fa/coverage-7.13.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c", size = 220941, upload-time = "2025-12-28T15:41:14.975Z" }, - { url = "https://files.pythonhosted.org/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, - { url = "https://files.pythonhosted.org/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, - { url = "https://files.pythonhosted.org/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, - { url = "https://files.pythonhosted.org/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, - { url = "https://files.pythonhosted.org/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, - { url = "https://files.pythonhosted.org/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, - { url = "https://files.pythonhosted.org/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, - { url = "https://files.pythonhosted.org/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f7/91fa73c4b80305c86598a2d4e54ba22df6bf7d0d97500944af7ef155d9f7/coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", size = 221512, upload-time = "2025-12-28T15:41:35.519Z" }, - { url = "https://files.pythonhosted.org/packages/45/0b/0768b4231d5a044da8f75e097a8714ae1041246bb765d6b5563bab456735/coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", size = 222321, upload-time = "2025-12-28T15:41:37.371Z" }, - { url = "https://files.pythonhosted.org/packages/9b/b8/bdcb7253b7e85157282450262008f1366aa04663f3e3e4c30436f596c3e2/coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", size = 220949, upload-time = "2025-12-28T15:41:39.553Z" }, - { url = "https://files.pythonhosted.org/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, - { url = "https://files.pythonhosted.org/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, - { url = "https://files.pythonhosted.org/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, - { url = "https://files.pythonhosted.org/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, - { url = "https://files.pythonhosted.org/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, - { url = "https://files.pythonhosted.org/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, - { url = "https://files.pythonhosted.org/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, - { url = "https://files.pythonhosted.org/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, - { url = "https://files.pythonhosted.org/packages/88/4f/3c159b7953db37a7b44c0eab8a95c37d1aa4257c47b4602c04022d5cb975/coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", size = 222184, upload-time = "2025-12-28T15:41:59.763Z" }, - { url = "https://files.pythonhosted.org/packages/58/a5/6b57d28f81417f9335774f20679d9d13b9a8fb90cd6160957aa3b54a2379/coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", size = 223250, upload-time = "2025-12-28T15:42:01.52Z" }, - { url = "https://files.pythonhosted.org/packages/81/7c/160796f3b035acfbb58be80e02e484548595aa67e16a6345e7910ace0a38/coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", size = 221521, upload-time = "2025-12-28T15:42:03.275Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8e/ba0e597560c6563fc0adb902fda6526df5d4aa73bb10adf0574d03bd2206/coverage-7.13.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:97ab3647280d458a1f9adb85244e81587505a43c0c7cff851f5116cd2814b894", size = 218996, upload-time = "2025-12-28T15:42:04.978Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8e/764c6e116f4221dc7aa26c4061181ff92edb9c799adae6433d18eeba7a14/coverage-7.13.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8f572d989142e0908e6acf57ad1b9b86989ff057c006d13b76c146ec6a20216a", size = 219326, upload-time = "2025-12-28T15:42:06.691Z" }, - { url = "https://files.pythonhosted.org/packages/4f/a6/6130dc6d8da28cdcbb0f2bf8865aeca9b157622f7c0031e48c6cf9a0e591/coverage-7.13.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d72140ccf8a147e94274024ff6fd8fb7811354cf7ef88b1f0a988ebaa5bc774f", size = 250374, upload-time = "2025-12-28T15:42:08.786Z" }, - { url = "https://files.pythonhosted.org/packages/82/2b/783ded568f7cd6b677762f780ad338bf4b4750205860c17c25f7c708995e/coverage-7.13.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3c9f051b028810f5a87c88e5d6e9af3c0ff32ef62763bf15d29f740453ca909", size = 252882, upload-time = "2025-12-28T15:42:10.515Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b2/9808766d082e6a4d59eb0cc881a57fc1600eb2c5882813eefff8254f71b5/coverage-7.13.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f398ba4df52d30b1763f62eed9de5620dcde96e6f491f4c62686736b155aa6e4", size = 254218, upload-time = "2025-12-28T15:42:12.208Z" }, - { url = "https://files.pythonhosted.org/packages/44/ea/52a985bb447c871cb4d2e376e401116520991b597c85afdde1ea9ef54f2c/coverage-7.13.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:132718176cc723026d201e347f800cd1a9e4b62ccd3f82476950834dad501c75", size = 250391, upload-time = "2025-12-28T15:42:14.21Z" }, - { url = "https://files.pythonhosted.org/packages/7f/1d/125b36cc12310718873cfc8209ecfbc1008f14f4f5fa0662aa608e579353/coverage-7.13.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e549d642426e3579b3f4b92d0431543b012dcb6e825c91619d4e93b7363c3f9", size = 252239, upload-time = "2025-12-28T15:42:16.292Z" }, - { url = "https://files.pythonhosted.org/packages/6a/16/10c1c164950cade470107f9f14bbac8485f8fb8515f515fca53d337e4a7f/coverage-7.13.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:90480b2134999301eea795b3a9dbf606c6fbab1b489150c501da84a959442465", size = 250196, upload-time = "2025-12-28T15:42:18.54Z" }, - { url = "https://files.pythonhosted.org/packages/2a/c6/cd860fac08780c6fd659732f6ced1b40b79c35977c1356344e44d72ba6c4/coverage-7.13.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e825dbb7f84dfa24663dd75835e7257f8882629fc11f03ecf77d84a75134b864", size = 250008, upload-time = "2025-12-28T15:42:20.365Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/a8c58d3d38f82a5711e1e0a67268362af48e1a03df27c03072ac30feefcf/coverage-7.13.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:623dcc6d7a7ba450bbdbeedbaa0c42b329bdae16491af2282f12a7e809be7eb9", size = 251671, upload-time = "2025-12-28T15:42:22.114Z" }, - { url = "https://files.pythonhosted.org/packages/f0/bc/fd4c1da651d037a1e3d53e8cb3f8182f4b53271ffa9a95a2e211bacc0349/coverage-7.13.1-cp314-cp314-win32.whl", hash = "sha256:6e73ebb44dca5f708dc871fe0b90cf4cff1a13f9956f747cc87b535a840386f5", size = 221777, upload-time = "2025-12-28T15:42:23.919Z" }, - { url = "https://files.pythonhosted.org/packages/4b/50/71acabdc8948464c17e90b5ffd92358579bd0910732c2a1c9537d7536aa6/coverage-7.13.1-cp314-cp314-win_amd64.whl", hash = "sha256:be753b225d159feb397bd0bf91ae86f689bad0da09d3b301478cd39b878ab31a", size = 222592, upload-time = "2025-12-28T15:42:25.619Z" }, - { url = "https://files.pythonhosted.org/packages/f7/c8/a6fb943081bb0cc926499c7907731a6dc9efc2cbdc76d738c0ab752f1a32/coverage-7.13.1-cp314-cp314-win_arm64.whl", hash = "sha256:228b90f613b25ba0019361e4ab81520b343b622fc657daf7e501c4ed6a2366c0", size = 221169, upload-time = "2025-12-28T15:42:27.629Z" }, - { url = "https://files.pythonhosted.org/packages/16/61/d5b7a0a0e0e40d62e59bc8c7aa1afbd86280d82728ba97f0673b746b78e2/coverage-7.13.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:60cfb538fe9ef86e5b2ab0ca8fc8d62524777f6c611dcaf76dc16fbe9b8e698a", size = 219730, upload-time = "2025-12-28T15:42:29.306Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2c/8881326445fd071bb49514d1ce97d18a46a980712b51fee84f9ab42845b4/coverage-7.13.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:57dfc8048c72ba48a8c45e188d811e5efd7e49b387effc8fb17e97936dde5bf6", size = 220001, upload-time = "2025-12-28T15:42:31.319Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d7/50de63af51dfa3a7f91cc37ad8fcc1e244b734232fbc8b9ab0f3c834a5cd/coverage-7.13.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f2f725aa3e909b3c5fdb8192490bdd8e1495e85906af74fe6e34a2a77ba0673", size = 261370, upload-time = "2025-12-28T15:42:32.992Z" }, - { url = "https://files.pythonhosted.org/packages/e1/2c/d31722f0ec918fd7453b2758312729f645978d212b410cd0f7c2aed88a94/coverage-7.13.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ee68b21909686eeb21dfcba2c3b81fee70dcf38b140dcd5aa70680995fa3aa5", size = 263485, upload-time = "2025-12-28T15:42:34.759Z" }, - { url = "https://files.pythonhosted.org/packages/fa/7a/2c114fa5c5fc08ba0777e4aec4c97e0b4a1afcb69c75f1f54cff78b073ab/coverage-7.13.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724b1b270cb13ea2e6503476e34541a0b1f62280bc997eab443f87790202033d", size = 265890, upload-time = "2025-12-28T15:42:36.517Z" }, - { url = "https://files.pythonhosted.org/packages/65/d9/f0794aa1c74ceabc780fe17f6c338456bbc4e96bd950f2e969f48ac6fb20/coverage-7.13.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:916abf1ac5cf7eb16bc540a5bf75c71c43a676f5c52fcb9fe75a2bd75fb944e8", size = 260445, upload-time = "2025-12-28T15:42:38.646Z" }, - { url = "https://files.pythonhosted.org/packages/49/23/184b22a00d9bb97488863ced9454068c79e413cb23f472da6cbddc6cfc52/coverage-7.13.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:776483fd35b58d8afe3acbd9988d5de592ab6da2d2a865edfdbc9fdb43e7c486", size = 263357, upload-time = "2025-12-28T15:42:40.788Z" }, - { url = "https://files.pythonhosted.org/packages/7d/bd/58af54c0c9199ea4190284f389005779d7daf7bf3ce40dcd2d2b2f96da69/coverage-7.13.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b6f3b96617e9852703f5b633ea01315ca45c77e879584f283c44127f0f1ec564", size = 260959, upload-time = "2025-12-28T15:42:42.808Z" }, - { url = "https://files.pythonhosted.org/packages/4b/2a/6839294e8f78a4891bf1df79d69c536880ba2f970d0ff09e7513d6e352e9/coverage-7.13.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd63e7b74661fed317212fab774e2a648bc4bb09b35f25474f8e3325d2945cd7", size = 259792, upload-time = "2025-12-28T15:42:44.818Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c3/528674d4623283310ad676c5af7414b9850ab6d55c2300e8aa4b945ec554/coverage-7.13.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:933082f161bbb3e9f90d00990dc956120f608cdbcaeea15c4d897f56ef4fe416", size = 262123, upload-time = "2025-12-28T15:42:47.108Z" }, - { url = "https://files.pythonhosted.org/packages/06/c5/8c0515692fb4c73ac379d8dc09b18eaf0214ecb76ea6e62467ba7a1556ff/coverage-7.13.1-cp314-cp314t-win32.whl", hash = "sha256:18be793c4c87de2965e1c0f060f03d9e5aff66cfeae8e1dbe6e5b88056ec153f", size = 222562, upload-time = "2025-12-28T15:42:49.144Z" }, - { url = "https://files.pythonhosted.org/packages/05/0e/c0a0c4678cb30dac735811db529b321d7e1c9120b79bd728d4f4d6b010e9/coverage-7.13.1-cp314-cp314t-win_amd64.whl", hash = "sha256:0e42e0ec0cd3e0d851cb3c91f770c9301f48647cb2877cb78f74bdaa07639a79", size = 223670, upload-time = "2025-12-28T15:42:51.218Z" }, - { url = "https://files.pythonhosted.org/packages/f5/5f/b177aa0011f354abf03a8f30a85032686d290fdeed4222b27d36b4372a50/coverage-7.13.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eaecf47ef10c72ece9a2a92118257da87e460e113b83cc0d2905cbbe931792b4", size = 221707, upload-time = "2025-12-28T15:42:53.034Z" }, - { url = "https://files.pythonhosted.org/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/11/43/3e4ac666cc35f231fa70c94e9f38459299de1a152813f9d2f60fc5f3ecaf/coverage-7.13.3.tar.gz", hash = "sha256:f7f6182d3dfb8802c1747eacbfe611b669455b69b7c037484bb1efbbb56711ac", size = 826832, upload-time = "2026-02-03T14:02:30.944Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/07/1c8099563a8a6c389a31c2d0aa1497cee86d6248bb4b9ba5e779215db9f9/coverage-7.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b4f345f7265cdbdb5ec2521ffff15fa49de6d6c39abf89fc7ad68aa9e3a55f0", size = 219143, upload-time = "2026-02-03T13:59:40.459Z" }, + { url = "https://files.pythonhosted.org/packages/69/39/a892d44af7aa092cab70e0cc5cdbba18eeccfe1d6930695dab1742eef9e9/coverage-7.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96c3be8bae9d0333e403cc1a8eb078a7f928b5650bae94a18fb4820cc993fb9b", size = 219663, upload-time = "2026-02-03T13:59:41.951Z" }, + { url = "https://files.pythonhosted.org/packages/9a/25/9669dcf4c2bb4c3861469e6db20e52e8c11908cf53c14ec9b12e9fd4d602/coverage-7.13.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d6f4a21328ea49d38565b55599e1c02834e76583a6953e5586d65cb1efebd8f8", size = 246424, upload-time = "2026-02-03T13:59:43.418Z" }, + { url = "https://files.pythonhosted.org/packages/f3/68/d9766c4e298aca62ea5d9543e1dd1e4e1439d7284815244d8b7db1840bfb/coverage-7.13.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fc970575799a9d17d5c3fafd83a0f6ccf5d5117cdc9ad6fbd791e9ead82418b0", size = 248228, upload-time = "2026-02-03T13:59:44.816Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e2/eea6cb4a4bd443741adf008d4cccec83a1f75401df59b6559aca2bdd9710/coverage-7.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ff33b652b3556b05e204ae20793d1f872161b0fa5ec8a9ac76f8430e152ed6", size = 250103, upload-time = "2026-02-03T13:59:46.271Z" }, + { url = "https://files.pythonhosted.org/packages/db/77/664280ecd666c2191610842177e2fab9e5dbdeef97178e2078fed46a3d2c/coverage-7.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7df8759ee57b9f3f7b66799b7660c282f4375bef620ade1686d6a7b03699e75f", size = 247107, upload-time = "2026-02-03T13:59:48.53Z" }, + { url = "https://files.pythonhosted.org/packages/2b/df/2a672eab99e0d0eba52d8a63e47dc92245eee26954d1b2d3c8f7d372151f/coverage-7.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f45c9bcb16bee25a798ccba8a2f6a1251b19de6a0d617bb365d7d2f386c4e20e", size = 248143, upload-time = "2026-02-03T13:59:50.027Z" }, + { url = "https://files.pythonhosted.org/packages/a5/dc/a104e7a87c13e57a358b8b9199a8955676e1703bb372d79722b54978ae45/coverage-7.13.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:318b2e4753cbf611061e01b6cc81477e1cdfeb69c36c4a14e6595e674caadb56", size = 246148, upload-time = "2026-02-03T13:59:52.025Z" }, + { url = "https://files.pythonhosted.org/packages/2b/89/e113d3a58dc20b03b7e59aed1e53ebc9ca6167f961876443e002b10e3ae9/coverage-7.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:24db3959de8ee394eeeca89ccb8ba25305c2da9a668dd44173394cbd5aa0777f", size = 246414, upload-time = "2026-02-03T13:59:53.859Z" }, + { url = "https://files.pythonhosted.org/packages/3f/60/a3fd0a6e8d89b488396019a2268b6a1f25ab56d6d18f3be50f35d77b47dc/coverage-7.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be14d0622125edef21b3a4d8cd2d138c4872bf6e38adc90fd92385e3312f406a", size = 247023, upload-time = "2026-02-03T13:59:55.454Z" }, + { url = "https://files.pythonhosted.org/packages/19/fa/de4840bb939dbb22ba0648a6d8069fa91c9cf3b3fca8b0d1df461e885b3d/coverage-7.13.3-cp310-cp310-win32.whl", hash = "sha256:53be4aab8ddef18beb6188f3a3fdbf4d1af2277d098d4e618be3a8e6c88e74be", size = 221751, upload-time = "2026-02-03T13:59:57.383Z" }, + { url = "https://files.pythonhosted.org/packages/de/87/233ff8b7ef62fb63f58c78623b50bef69681111e0c4d43504f422d88cda4/coverage-7.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:bfeee64ad8b4aae3233abb77eb6b52b51b05fa89da9645518671b9939a78732b", size = 222686, upload-time = "2026-02-03T13:59:58.825Z" }, + { url = "https://files.pythonhosted.org/packages/ec/09/1ac74e37cf45f17eb41e11a21854f7f92a4c2d6c6098ef4a1becb0c6d8d3/coverage-7.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5907605ee20e126eeee2abe14aae137043c2c8af2fa9b38d2ab3b7a6b8137f73", size = 219276, upload-time = "2026-02-03T14:00:00.296Z" }, + { url = "https://files.pythonhosted.org/packages/2e/cb/71908b08b21beb2c437d0d5870c4ec129c570ca1b386a8427fcdb11cf89c/coverage-7.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a88705500988c8acad8b8fd86c2a933d3aa96bec1ddc4bc5cb256360db7bbd00", size = 219776, upload-time = "2026-02-03T14:00:02.414Z" }, + { url = "https://files.pythonhosted.org/packages/09/85/c4f3dd69232887666a2c0394d4be21c60ea934d404db068e6c96aa59cd87/coverage-7.13.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bbb5aa9016c4c29e3432e087aa29ebee3f8fda089cfbfb4e6d64bd292dcd1c2", size = 250196, upload-time = "2026-02-03T14:00:04.197Z" }, + { url = "https://files.pythonhosted.org/packages/9c/cc/560ad6f12010344d0778e268df5ba9aa990aacccc310d478bf82bf3d302c/coverage-7.13.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c2be202a83dde768937a61cdc5d06bf9fb204048ca199d93479488e6247656c", size = 252111, upload-time = "2026-02-03T14:00:05.639Z" }, + { url = "https://files.pythonhosted.org/packages/f0/66/3193985fb2c58e91f94cfbe9e21a6fdf941e9301fe2be9e92c072e9c8f8c/coverage-7.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f45e32ef383ce56e0ca099b2e02fcdf7950be4b1b56afaab27b4ad790befe5b", size = 254217, upload-time = "2026-02-03T14:00:07.738Z" }, + { url = "https://files.pythonhosted.org/packages/c5/78/f0f91556bf1faa416792e537c523c5ef9db9b1d32a50572c102b3d7c45b3/coverage-7.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ed2e787249b922a93cd95c671cc9f4c9797a106e81b455c83a9ddb9d34590c0", size = 250318, upload-time = "2026-02-03T14:00:09.224Z" }, + { url = "https://files.pythonhosted.org/packages/6f/aa/fc654e45e837d137b2c1f3a2cc09b4aea1e8b015acd2f774fa0f3d2ddeba/coverage-7.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:05dd25b21afffe545e808265897c35f32d3e4437663923e0d256d9ab5031fb14", size = 251909, upload-time = "2026-02-03T14:00:10.712Z" }, + { url = "https://files.pythonhosted.org/packages/73/4d/ab53063992add8a9ca0463c9d92cce5994a29e17affd1c2daa091b922a93/coverage-7.13.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46d29926349b5c4f1ea4fca95e8c892835515f3600995a383fa9a923b5739ea4", size = 249971, upload-time = "2026-02-03T14:00:12.402Z" }, + { url = "https://files.pythonhosted.org/packages/29/25/83694b81e46fcff9899694a1b6f57573429cdd82b57932f09a698f03eea5/coverage-7.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fae6a21537519c2af00245e834e5bf2884699cc7c1055738fd0f9dc37a3644ad", size = 249692, upload-time = "2026-02-03T14:00:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ef/d68fc304301f4cb4bf6aefa0045310520789ca38dabdfba9dbecd3f37919/coverage-7.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c672d4e2f0575a4ca2bf2aa0c5ced5188220ab806c1bb6d7179f70a11a017222", size = 250597, upload-time = "2026-02-03T14:00:15.461Z" }, + { url = "https://files.pythonhosted.org/packages/8d/85/240ad396f914df361d0f71e912ddcedb48130c71b88dc4193fe3c0306f00/coverage-7.13.3-cp311-cp311-win32.whl", hash = "sha256:fcda51c918c7a13ad93b5f89a58d56e3a072c9e0ba5c231b0ed81404bf2648fb", size = 221773, upload-time = "2026-02-03T14:00:17.462Z" }, + { url = "https://files.pythonhosted.org/packages/2f/71/165b3a6d3d052704a9ab52d11ea64ef3426745de517dda44d872716213a7/coverage-7.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:d1a049b5c51b3b679928dd35e47c4a2235e0b6128b479a7596d0ef5b42fa6301", size = 222711, upload-time = "2026-02-03T14:00:19.449Z" }, + { url = "https://files.pythonhosted.org/packages/51/d0/0ddc9c5934cdd52639c5df1f1eb0fdab51bb52348f3a8d1c7db9c600d93a/coverage-7.13.3-cp311-cp311-win_arm64.whl", hash = "sha256:79f2670c7e772f4917895c3d89aad59e01f3dbe68a4ed2d0373b431fad1dcfba", size = 221377, upload-time = "2026-02-03T14:00:20.968Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/330f8e83b143f6668778ed61d17ece9dc48459e9e74669177de02f45fec5/coverage-7.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ed48b4170caa2c4420e0cd27dc977caaffc7eecc317355751df8373dddcef595", size = 219441, upload-time = "2026-02-03T14:00:22.585Z" }, + { url = "https://files.pythonhosted.org/packages/08/e7/29db05693562c2e65bdf6910c0af2fd6f9325b8f43caf7a258413f369e30/coverage-7.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8f2adf4bcffbbec41f366f2e6dffb9d24e8172d16e91da5799c9b7ed6b5716e6", size = 219801, upload-time = "2026-02-03T14:00:24.186Z" }, + { url = "https://files.pythonhosted.org/packages/90/ae/7f8a78249b02b0818db46220795f8ac8312ea4abd1d37d79ea81db5cae81/coverage-7.13.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01119735c690786b6966a1e9f098da4cd7ca9174c4cfe076d04e653105488395", size = 251306, upload-time = "2026-02-03T14:00:25.798Z" }, + { url = "https://files.pythonhosted.org/packages/62/71/a18a53d1808e09b2e9ebd6b47dad5e92daf4c38b0686b4c4d1b2f3e42b7f/coverage-7.13.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8bb09e83c603f152d855f666d70a71765ca8e67332e5829e62cb9466c176af23", size = 254051, upload-time = "2026-02-03T14:00:27.474Z" }, + { url = "https://files.pythonhosted.org/packages/4a/0a/eb30f6455d04c5a3396d0696cad2df0269ae7444bb322f86ffe3376f7bf9/coverage-7.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b607a40cba795cfac6d130220d25962931ce101f2f478a29822b19755377fb34", size = 255160, upload-time = "2026-02-03T14:00:29.024Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7e/a45baac86274ce3ed842dbb84f14560c673ad30535f397d89164ec56c5df/coverage-7.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:44f14a62f5da2e9aedf9080e01d2cda61df39197d48e323538ec037336d68da8", size = 251709, upload-time = "2026-02-03T14:00:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/c0/df/dd0dc12f30da11349993f3e218901fdf82f45ee44773596050c8f5a1fb25/coverage-7.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:debf29e0b157769843dff0981cc76f79e0ed04e36bb773c6cac5f6029054bd8a", size = 253083, upload-time = "2026-02-03T14:00:32.14Z" }, + { url = "https://files.pythonhosted.org/packages/ab/32/fc764c8389a8ce95cb90eb97af4c32f392ab0ac23ec57cadeefb887188d3/coverage-7.13.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:824bb95cd71604031ae9a48edb91fd6effde669522f960375668ed21b36e3ec4", size = 251227, upload-time = "2026-02-03T14:00:34.721Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ca/d025e9da8f06f24c34d2da9873957cfc5f7e0d67802c3e34d0caa8452130/coverage-7.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8f1010029a5b52dc427c8e2a8dbddb2303ddd180b806687d1acd1bb1d06649e7", size = 250794, upload-time = "2026-02-03T14:00:36.278Z" }, + { url = "https://files.pythonhosted.org/packages/45/c7/76bf35d5d488ec8f68682eb8e7671acc50a6d2d1c1182de1d2b6d4ffad3b/coverage-7.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cd5dee4fd7659d8306ffa79eeaaafd91fa30a302dac3af723b9b469e549247e0", size = 252671, upload-time = "2026-02-03T14:00:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/bf/10/1921f1a03a7c209e1cb374f81a6b9b68b03cdb3ecc3433c189bc90e2a3d5/coverage-7.13.3-cp312-cp312-win32.whl", hash = "sha256:f7f153d0184d45f3873b3ad3ad22694fd73aadcb8cdbc4337ab4b41ea6b4dff1", size = 221986, upload-time = "2026-02-03T14:00:40.442Z" }, + { url = "https://files.pythonhosted.org/packages/3c/7c/f5d93297f8e125a80c15545edc754d93e0ed8ba255b65e609b185296af01/coverage-7.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:03a6e5e1e50819d6d7436f5bc40c92ded7e484e400716886ac921e35c133149d", size = 222793, upload-time = "2026-02-03T14:00:42.106Z" }, + { url = "https://files.pythonhosted.org/packages/43/59/c86b84170015b4555ebabca8649bdf9f4a1f737a73168088385ed0f947c4/coverage-7.13.3-cp312-cp312-win_arm64.whl", hash = "sha256:51c4c42c0e7d09a822b08b6cf79b3c4db8333fffde7450da946719ba0d45730f", size = 221410, upload-time = "2026-02-03T14:00:43.726Z" }, + { url = "https://files.pythonhosted.org/packages/81/f3/4c333da7b373e8c8bfb62517e8174a01dcc373d7a9083698e3b39d50d59c/coverage-7.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:853c3d3c79ff0db65797aad79dee6be020efd218ac4510f15a205f1e8d13ce25", size = 219468, upload-time = "2026-02-03T14:00:45.829Z" }, + { url = "https://files.pythonhosted.org/packages/d6/31/0714337b7d23630c8de2f4d56acf43c65f8728a45ed529b34410683f7217/coverage-7.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f75695e157c83d374f88dcc646a60cb94173304a9258b2e74ba5a66b7614a51a", size = 219839, upload-time = "2026-02-03T14:00:47.407Z" }, + { url = "https://files.pythonhosted.org/packages/12/99/bd6f2a2738144c98945666f90cae446ed870cecf0421c767475fcf42cdbe/coverage-7.13.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d098709621d0819039f3f1e471ee554f55a0b2ac0d816883c765b14129b5627", size = 250828, upload-time = "2026-02-03T14:00:49.029Z" }, + { url = "https://files.pythonhosted.org/packages/6f/99/97b600225fbf631e6f5bfd3ad5bcaf87fbb9e34ff87492e5a572ff01bbe2/coverage-7.13.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:16d23d6579cf80a474ad160ca14d8b319abaa6db62759d6eef53b2fc979b58c8", size = 253432, upload-time = "2026-02-03T14:00:50.655Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5c/abe2b3490bda26bd4f5e3e799be0bdf00bd81edebedc2c9da8d3ef288fa8/coverage-7.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00d34b29a59d2076e6f318b30a00a69bf63687e30cd882984ed444e753990cc1", size = 254672, upload-time = "2026-02-03T14:00:52.757Z" }, + { url = "https://files.pythonhosted.org/packages/31/ba/5d1957c76b40daff53971fe0adb84d9c2162b614280031d1d0653dd010c1/coverage-7.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ab6d72bffac9deb6e6cb0f61042e748de3f9f8e98afb0375a8e64b0b6e11746b", size = 251050, upload-time = "2026-02-03T14:00:54.332Z" }, + { url = "https://files.pythonhosted.org/packages/69/dc/dffdf3bfe9d32090f047d3c3085378558cb4eb6778cda7de414ad74581ed/coverage-7.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e129328ad1258e49cae0123a3b5fcb93d6c2fa90d540f0b4c7cdcdc019aaa3dc", size = 252801, upload-time = "2026-02-03T14:00:56.121Z" }, + { url = "https://files.pythonhosted.org/packages/87/51/cdf6198b0f2746e04511a30dc9185d7b8cdd895276c07bdb538e37f1cd50/coverage-7.13.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2213a8d88ed35459bda71597599d4eec7c2ebad201c88f0bfc2c26fd9b0dd2ea", size = 250763, upload-time = "2026-02-03T14:00:58.719Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1a/596b7d62218c1d69f2475b69cc6b211e33c83c902f38ee6ae9766dd422da/coverage-7.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:00dd3f02de6d5f5c9c3d95e3e036c3c2e2a669f8bf2d3ceb92505c4ce7838f67", size = 250587, upload-time = "2026-02-03T14:01:01.197Z" }, + { url = "https://files.pythonhosted.org/packages/f7/46/52330d5841ff660f22c130b75f5e1dd3e352c8e7baef5e5fef6b14e3e991/coverage-7.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9bada7bc660d20b23d7d312ebe29e927b655cf414dadcdb6335a2075695bd86", size = 252358, upload-time = "2026-02-03T14:01:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/36/8a/e69a5be51923097ba7d5cff9724466e74fe486e9232020ba97c809a8b42b/coverage-7.13.3-cp313-cp313-win32.whl", hash = "sha256:75b3c0300f3fa15809bd62d9ca8b170eb21fcf0100eb4b4154d6dc8b3a5bbd43", size = 222007, upload-time = "2026-02-03T14:01:04.876Z" }, + { url = "https://files.pythonhosted.org/packages/0a/09/a5a069bcee0d613bdd48ee7637fa73bc09e7ed4342b26890f2df97cc9682/coverage-7.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:a2f7589c6132c44c53f6e705e1a6677e2b7821378c22f7703b2cf5388d0d4587", size = 222812, upload-time = "2026-02-03T14:01:07.296Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4f/d62ad7dfe32f9e3d4a10c178bb6f98b10b083d6e0530ca202b399371f6c1/coverage-7.13.3-cp313-cp313-win_arm64.whl", hash = "sha256:123ceaf2b9d8c614f01110f908a341e05b1b305d6b2ada98763b9a5a59756051", size = 221433, upload-time = "2026-02-03T14:01:09.156Z" }, + { url = "https://files.pythonhosted.org/packages/04/b2/4876c46d723d80b9c5b695f1a11bf5f7c3dabf540ec00d6edc076ff025e6/coverage-7.13.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:cc7fd0f726795420f3678ac82ff882c7fc33770bd0074463b5aef7293285ace9", size = 220162, upload-time = "2026-02-03T14:01:11.409Z" }, + { url = "https://files.pythonhosted.org/packages/fc/04/9942b64a0e0bdda2c109f56bda42b2a59d9d3df4c94b85a323c1cae9fc77/coverage-7.13.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d358dc408edc28730aed5477a69338e444e62fba0b7e9e4a131c505fadad691e", size = 220510, upload-time = "2026-02-03T14:01:13.038Z" }, + { url = "https://files.pythonhosted.org/packages/5a/82/5cfe1e81eae525b74669f9795f37eb3edd4679b873d79d1e6c1c14ee6c1c/coverage-7.13.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5d67b9ed6f7b5527b209b24b3df9f2e5bf0198c1bbf99c6971b0e2dcb7e2a107", size = 261801, upload-time = "2026-02-03T14:01:14.674Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ec/a553d7f742fd2cd12e36a16a7b4b3582d5934b496ef2b5ea8abeb10903d4/coverage-7.13.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59224bfb2e9b37c1335ae35d00daa3a5b4e0b1a20f530be208fff1ecfa436f43", size = 263882, upload-time = "2026-02-03T14:01:16.343Z" }, + { url = "https://files.pythonhosted.org/packages/e1/58/8f54a2a93e3d675635bc406de1c9ac8d551312142ff52c9d71b5e533ad45/coverage-7.13.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9306b5299e31e31e0d3b908c66bcb6e7e3ddca143dea0266e9ce6c667346d3", size = 266306, upload-time = "2026-02-03T14:01:18.02Z" }, + { url = "https://files.pythonhosted.org/packages/1a/be/e593399fd6ea1f00aee79ebd7cc401021f218d34e96682a92e1bae092ff6/coverage-7.13.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:343aaeb5f8bb7bcd38620fd7bc56e6ee8207847d8c6103a1e7b72322d381ba4a", size = 261051, upload-time = "2026-02-03T14:01:19.757Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e5/e9e0f6138b21bcdebccac36fbfde9cf15eb1bbcea9f5b1f35cd1f465fb91/coverage-7.13.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2182129f4c101272ff5f2f18038d7b698db1bf8e7aa9e615cb48440899ad32e", size = 263868, upload-time = "2026-02-03T14:01:21.487Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bf/de72cfebb69756f2d4a2dde35efcc33c47d85cd3ebdf844b3914aac2ef28/coverage-7.13.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:94d2ac94bd0cc57c5626f52f8c2fffed1444b5ae8c9fc68320306cc2b255e155", size = 261498, upload-time = "2026-02-03T14:01:23.097Z" }, + { url = "https://files.pythonhosted.org/packages/f2/91/4a2d313a70fc2e98ca53afd1c8ce67a89b1944cd996589a5b1fe7fbb3e5c/coverage-7.13.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:65436cde5ecabe26fb2f0bf598962f0a054d3f23ad529361326ac002c61a2a1e", size = 260394, upload-time = "2026-02-03T14:01:24.949Z" }, + { url = "https://files.pythonhosted.org/packages/40/83/25113af7cf6941e779eb7ed8de2a677865b859a07ccee9146d4cc06a03e3/coverage-7.13.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db83b77f97129813dbd463a67e5335adc6a6a91db652cc085d60c2d512746f96", size = 262579, upload-time = "2026-02-03T14:01:26.703Z" }, + { url = "https://files.pythonhosted.org/packages/1e/19/a5f2b96262977e82fb9aabbe19b4d83561f5d063f18dde3e72f34ffc3b2f/coverage-7.13.3-cp313-cp313t-win32.whl", hash = "sha256:dfb428e41377e6b9ba1b0a32df6db5409cb089a0ed1d0a672dc4953ec110d84f", size = 222679, upload-time = "2026-02-03T14:01:28.553Z" }, + { url = "https://files.pythonhosted.org/packages/81/82/ef1747b88c87a5c7d7edc3704799ebd650189a9158e680a063308b6125ef/coverage-7.13.3-cp313-cp313t-win_amd64.whl", hash = "sha256:5badd7e596e6b0c89aa8ec6d37f4473e4357f982ce57f9a2942b0221cd9cf60c", size = 223740, upload-time = "2026-02-03T14:01:30.776Z" }, + { url = "https://files.pythonhosted.org/packages/1c/4c/a67c7bb5b560241c22736a9cb2f14c5034149ffae18630323fde787339e4/coverage-7.13.3-cp313-cp313t-win_arm64.whl", hash = "sha256:989aa158c0eb19d83c76c26f4ba00dbb272485c56e452010a3450bdbc9daafd9", size = 221996, upload-time = "2026-02-03T14:01:32.495Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b3/677bb43427fed9298905106f39c6520ac75f746f81b8f01104526a8026e4/coverage-7.13.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c6f6169bbdbdb85aab8ac0392d776948907267fcc91deeacf6f9d55f7a83ae3b", size = 219513, upload-time = "2026-02-03T14:01:34.29Z" }, + { url = "https://files.pythonhosted.org/packages/42/53/290046e3bbf8986cdb7366a42dab3440b9983711eaff044a51b11006c67b/coverage-7.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2f5e731627a3d5ef11a2a35aa0c6f7c435867c7ccbc391268eb4f2ca5dbdcc10", size = 219850, upload-time = "2026-02-03T14:01:35.984Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2b/ab41f10345ba2e49d5e299be8663be2b7db33e77ac1b85cd0af985ea6406/coverage-7.13.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9db3a3285d91c0b70fab9f39f0a4aa37d375873677efe4e71e58d8321e8c5d39", size = 250886, upload-time = "2026-02-03T14:01:38.287Z" }, + { url = "https://files.pythonhosted.org/packages/72/2d/b3f6913ee5a1d5cdd04106f257e5fac5d048992ffc2d9995d07b0f17739f/coverage-7.13.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06e49c5897cb12e3f7ecdc111d44e97c4f6d0557b81a7a0204ed70a8b038f86f", size = 253393, upload-time = "2026-02-03T14:01:40.118Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f6/b1f48810ffc6accf49a35b9943636560768f0812330f7456aa87dc39aff5/coverage-7.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb25061a66802df9fc13a9ba1967d25faa4dae0418db469264fd9860a921dde4", size = 254740, upload-time = "2026-02-03T14:01:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/57/d0/e59c54f9be0b61808f6bc4c8c4346bd79f02dd6bbc3f476ef26124661f20/coverage-7.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:99fee45adbb1caeb914da16f70e557fb7ff6ddc9e4b14de665bd41af631367ef", size = 250905, upload-time = "2026-02-03T14:01:44.163Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f7/5291bcdf498bafbee3796bb32ef6966e9915aebd4d0954123c8eae921c32/coverage-7.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:318002f1fd819bdc1651c619268aa5bc853c35fa5cc6d1e8c96bd9cd6c828b75", size = 252753, upload-time = "2026-02-03T14:01:45.974Z" }, + { url = "https://files.pythonhosted.org/packages/a0/a9/1dcafa918c281554dae6e10ece88c1add82db685be123e1b05c2056ff3fb/coverage-7.13.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:71295f2d1d170b9977dc386d46a7a1b7cbb30e5405492529b4c930113a33f895", size = 250716, upload-time = "2026-02-03T14:01:48.844Z" }, + { url = "https://files.pythonhosted.org/packages/44/bb/4ea4eabcce8c4f6235df6e059fbc5db49107b24c4bdffc44aee81aeca5a8/coverage-7.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5b1ad2e0dc672625c44bc4fe34514602a9fd8b10d52ddc414dc585f74453516c", size = 250530, upload-time = "2026-02-03T14:01:50.793Z" }, + { url = "https://files.pythonhosted.org/packages/6d/31/4a6c9e6a71367e6f923b27b528448c37f4e959b7e4029330523014691007/coverage-7.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b2beb64c145593a50d90db5c7178f55daeae129123b0d265bdb3cbec83e5194a", size = 252186, upload-time = "2026-02-03T14:01:52.607Z" }, + { url = "https://files.pythonhosted.org/packages/27/92/e1451ef6390a4f655dc42da35d9971212f7abbbcad0bdb7af4407897eb76/coverage-7.13.3-cp314-cp314-win32.whl", hash = "sha256:3d1aed4f4e837a832df2f3b4f68a690eede0de4560a2dbc214ea0bc55aabcdb4", size = 222253, upload-time = "2026-02-03T14:01:55.071Z" }, + { url = "https://files.pythonhosted.org/packages/8a/98/78885a861a88de020c32a2693487c37d15a9873372953f0c3c159d575a43/coverage-7.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9f9efbbaf79f935d5fbe3ad814825cbce4f6cdb3054384cb49f0c0f496125fa0", size = 223069, upload-time = "2026-02-03T14:01:56.95Z" }, + { url = "https://files.pythonhosted.org/packages/eb/fb/3784753a48da58a5337972abf7ca58b1fb0f1bda21bc7b4fae992fd28e47/coverage-7.13.3-cp314-cp314-win_arm64.whl", hash = "sha256:31b6e889c53d4e6687ca63706148049494aace140cffece1c4dc6acadb70a7b3", size = 221633, upload-time = "2026-02-03T14:01:58.758Z" }, + { url = "https://files.pythonhosted.org/packages/40/f9/75b732d9674d32cdbffe801ed5f770786dd1c97eecedef2125b0d25102dc/coverage-7.13.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c5e9787cec750793a19a28df7edd85ac4e49d3fb91721afcdc3b86f6c08d9aa8", size = 220243, upload-time = "2026-02-03T14:02:01.109Z" }, + { url = "https://files.pythonhosted.org/packages/cf/7e/2868ec95de5a65703e6f0c87407ea822d1feb3619600fbc3c1c4fa986090/coverage-7.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5b86db331c682fd0e4be7098e6acee5e8a293f824d41487c667a93705d415ca", size = 220515, upload-time = "2026-02-03T14:02:02.862Z" }, + { url = "https://files.pythonhosted.org/packages/7d/eb/9f0d349652fced20bcaea0f67fc5777bd097c92369f267975732f3dc5f45/coverage-7.13.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:edc7754932682d52cf6e7a71806e529ecd5ce660e630e8bd1d37109a2e5f63ba", size = 261874, upload-time = "2026-02-03T14:02:04.727Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a5/6619bc4a6c7b139b16818149a3e74ab2e21599ff9a7b6811b6afde99f8ec/coverage-7.13.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3a16d6398666510a6886f67f43d9537bfd0e13aca299688a19daa84f543122f", size = 264004, upload-time = "2026-02-03T14:02:06.634Z" }, + { url = "https://files.pythonhosted.org/packages/29/b7/90aa3fc645a50c6f07881fca4fd0ba21e3bfb6ce3a7078424ea3a35c74c9/coverage-7.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:303d38b19626c1981e1bb067a9928236d88eb0e4479b18a74812f05a82071508", size = 266408, upload-time = "2026-02-03T14:02:09.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/55/08bb2a1e4dcbae384e638f0effef486ba5987b06700e481691891427d879/coverage-7.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:284e06eadfe15ddfee2f4ee56631f164ef897a7d7d5a15bca5f0bb88889fc5ba", size = 260977, upload-time = "2026-02-03T14:02:11.755Z" }, + { url = "https://files.pythonhosted.org/packages/9b/76/8bd4ae055a42d8fb5dd2230e5cf36ff2e05f85f2427e91b11a27fea52ed7/coverage-7.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d401f0864a1d3198422816878e4e84ca89ec1c1bf166ecc0ae01380a39b888cd", size = 263868, upload-time = "2026-02-03T14:02:13.565Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f9/ba000560f11e9e32ec03df5aa8477242c2d95b379c99ac9a7b2e7fbacb1a/coverage-7.13.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3f379b02c18a64de78c4ccdddf1c81c2c5ae1956c72dacb9133d7dd7809794ab", size = 261474, upload-time = "2026-02-03T14:02:16.069Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/4de4de8f9ca7af4733bfcf4baa440121b7dbb3856daf8428ce91481ff63b/coverage-7.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:7a482f2da9086971efb12daca1d6547007ede3674ea06e16d7663414445c683e", size = 260317, upload-time = "2026-02-03T14:02:17.996Z" }, + { url = "https://files.pythonhosted.org/packages/05/71/5cd8436e2c21410ff70be81f738c0dddea91bcc3189b1517d26e0102ccb3/coverage-7.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:562136b0d401992118d9b49fbee5454e16f95f85b120a4226a04d816e33fe024", size = 262635, upload-time = "2026-02-03T14:02:20.405Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f8/2834bb45bdd70b55a33ec354b8b5f6062fc90e5bb787e14385903a979503/coverage-7.13.3-cp314-cp314t-win32.whl", hash = "sha256:ca46e5c3be3b195098dd88711890b8011a9fa4feca942292bb84714ce5eab5d3", size = 223035, upload-time = "2026-02-03T14:02:22.323Z" }, + { url = "https://files.pythonhosted.org/packages/26/75/f8290f0073c00d9ae14056d2b84ab92dff21d5370e464cb6cb06f52bf580/coverage-7.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:06d316dbb3d9fd44cca05b2dbcfbef22948493d63a1f28e828d43e6cc505fed8", size = 224142, upload-time = "2026-02-03T14:02:24.143Z" }, + { url = "https://files.pythonhosted.org/packages/03/01/43ac78dfea8946c4a9161bbc034b5549115cb2b56781a4b574927f0d141a/coverage-7.13.3-cp314-cp314t-win_arm64.whl", hash = "sha256:299d66e9218193f9dc6e4880629ed7c4cd23486005166247c283fb98531656c3", size = 222166, upload-time = "2026-02-03T14:02:26.005Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fb/70af542d2d938c778c9373ce253aa4116dbe7c0a5672f78b2b2ae0e1b94b/coverage-7.13.3-py3-none-any.whl", hash = "sha256:90a8af9dba6429b2573199622d72e0ebf024d6276f16abce394ad4d181bb0910", size = 211237, upload-time = "2026-02-03T14:02:27.986Z" }, ] [package.optional-dependencies] @@ -809,79 +810,74 @@ toml = [ [[package]] name = "cross-web" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/4f/bdb62e969649ee76d4741ef8eee34384ec2bc21cc66eb7fd244e6ad62be8/cross_web-0.4.0.tar.gz", hash = "sha256:4ae65619ddfcd06d6803432c0366342d7e8aeba10194b4e144d73a662e75370c", size = 157111, upload-time = "2025-12-25T20:45:21.989Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/58/e688e99d1493c565d1587e64b499268d0a3129ae59f4efe440aac395f803/cross_web-0.4.1.tar.gz", hash = "sha256:0466295028dcae98c9ab3d18757f90b0e74fac2ff90efbe87e74657546d9993d", size = 157385, upload-time = "2026-01-09T18:17:41.534Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/d6/6c6a036655e5091b26b9f350dcf43821895325aa4727396b14c67679a957/cross_web-0.4.0-py3-none-any.whl", hash = "sha256:0c675bd26e91428cab31e3e927929b42da94aa96da92974e57c78f9a732d0e9b", size = 14200, upload-time = "2025-12-25T20:45:23.075Z" }, + { url = "https://files.pythonhosted.org/packages/67/49/92b46b6e65f09b717a66c4e5a9bc47a45ebc83dd0e0ed126f8258363479d/cross_web-0.4.1-py3-none-any.whl", hash = "sha256:41b07c3a38253c517ec0603c1a366353aff77538946092b0f9a2235033f192c2", size = 14320, upload-time = "2026-01-09T18:17:40.325Z" }, ] [[package]] name = "cryptography" -version = "46.0.3" +version = "46.0.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, - { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, - { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, - { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, - { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, - { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, - { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, - { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, - { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, - { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, - { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, - { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, - { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, - { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" }, - { url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" }, - { url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" }, - { url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" }, - { url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" }, - { url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" }, - { url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" }, - { url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" }, - { url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" }, - { url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" }, - { url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" }, - { url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" }, - { url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" }, - { url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" }, - { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, - { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, - { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, - { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, - { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, - { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, - { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, - { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, - { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, - { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, - { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, - { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, - { url = "https://files.pythonhosted.org/packages/d9/cd/1a8633802d766a0fa46f382a77e096d7e209e0817892929655fe0586ae32/cryptography-46.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a23582810fedb8c0bc47524558fb6c56aac3fc252cb306072fd2815da2a47c32", size = 3689163, upload-time = "2025-10-15T23:18:13.821Z" }, - { url = "https://files.pythonhosted.org/packages/4c/59/6b26512964ace6480c3e54681a9859c974172fb141c38df11eadd8416947/cryptography-46.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e7aec276d68421f9574040c26e2a7c3771060bc0cff408bae1dcb19d3ab1e63c", size = 3429474, upload-time = "2025-10-15T23:18:15.477Z" }, - { url = "https://files.pythonhosted.org/packages/06/8a/e60e46adab4362a682cf142c7dcb5bf79b782ab2199b0dcb81f55970807f/cryptography-46.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7ce938a99998ed3c8aa7e7272dca1a610401ede816d36d0693907d863b10d9ea", size = 3698132, upload-time = "2025-10-15T23:18:17.056Z" }, - { url = "https://files.pythonhosted.org/packages/da/38/f59940ec4ee91e93d3311f7532671a5cef5570eb04a144bf203b58552d11/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:191bb60a7be5e6f54e30ba16fdfae78ad3a342a0599eb4193ba88e3f3d6e185b", size = 4243992, upload-time = "2025-10-15T23:18:18.695Z" }, - { url = "https://files.pythonhosted.org/packages/b0/0c/35b3d92ddebfdfda76bb485738306545817253d0a3ded0bfe80ef8e67aa5/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c70cc23f12726be8f8bc72e41d5065d77e4515efae3690326764ea1b07845cfb", size = 4409944, upload-time = "2025-10-15T23:18:20.597Z" }, - { url = "https://files.pythonhosted.org/packages/99/55/181022996c4063fc0e7666a47049a1ca705abb9c8a13830f074edb347495/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:9394673a9f4de09e28b5356e7fff97d778f8abad85c9d5ac4a4b7e25a0de7717", size = 4242957, upload-time = "2025-10-15T23:18:22.18Z" }, - { url = "https://files.pythonhosted.org/packages/ba/af/72cd6ef29f9c5f731251acadaeb821559fe25f10852f44a63374c9ca08c1/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94cd0549accc38d1494e1f8de71eca837d0509d0d44bf11d158524b0e12cebf9", size = 4409447, upload-time = "2025-10-15T23:18:24.209Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c3/e90f4a4feae6410f914f8ebac129b9ae7a8c92eb60a638012dde42030a9d/cryptography-46.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6b5063083824e5509fdba180721d55909ffacccc8adbec85268b48439423d78c", size = 3438528, upload-time = "2025-10-15T23:18:26.227Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/78/19/f748958276519adf6a0c1e79e7b8860b4830dda55ccdf29f2719b5fc499c/cryptography-46.0.4.tar.gz", hash = "sha256:bfd019f60f8abc2ed1b9be4ddc21cfef059c841d86d710bb69909a688cbb8f59", size = 749301, upload-time = "2026-01-28T00:24:37.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/99/157aae7949a5f30d51fcb1a9851e8ebd5c74bf99b5285d8bb4b8b9ee641e/cryptography-46.0.4-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:281526e865ed4166009e235afadf3a4c4cba6056f99336a99efba65336fd5485", size = 7173686, upload-time = "2026-01-28T00:23:07.515Z" }, + { url = "https://files.pythonhosted.org/packages/87/91/874b8910903159043b5c6a123b7e79c4559ddd1896e38967567942635778/cryptography-46.0.4-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f14fba5bf6f4390d7ff8f086c566454bff0411f6d8aa7af79c88b6f9267aecc", size = 4275871, upload-time = "2026-01-28T00:23:09.439Z" }, + { url = "https://files.pythonhosted.org/packages/c0/35/690e809be77896111f5b195ede56e4b4ed0435b428c2f2b6d35046fbb5e8/cryptography-46.0.4-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:47bcd19517e6389132f76e2d5303ded6cf3f78903da2158a671be8de024f4cd0", size = 4423124, upload-time = "2026-01-28T00:23:11.529Z" }, + { url = "https://files.pythonhosted.org/packages/1a/5b/a26407d4f79d61ca4bebaa9213feafdd8806dc69d3d290ce24996d3cfe43/cryptography-46.0.4-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:01df4f50f314fbe7009f54046e908d1754f19d0c6d3070df1e6268c5a4af09fa", size = 4277090, upload-time = "2026-01-28T00:23:13.123Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d8/4bb7aec442a9049827aa34cee1aa83803e528fa55da9a9d45d01d1bb933e/cryptography-46.0.4-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5aa3e463596b0087b3da0dbe2b2487e9fc261d25da85754e30e3b40637d61f81", size = 4947652, upload-time = "2026-01-28T00:23:14.554Z" }, + { url = "https://files.pythonhosted.org/packages/2b/08/f83e2e0814248b844265802d081f2fac2f1cbe6cd258e72ba14ff006823a/cryptography-46.0.4-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0a9ad24359fee86f131836a9ac3bffc9329e956624a2d379b613f8f8abaf5255", size = 4455157, upload-time = "2026-01-28T00:23:16.443Z" }, + { url = "https://files.pythonhosted.org/packages/0a/05/19d849cf4096448779d2dcc9bb27d097457dac36f7273ffa875a93b5884c/cryptography-46.0.4-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:dc1272e25ef673efe72f2096e92ae39dea1a1a450dd44918b15351f72c5a168e", size = 3981078, upload-time = "2026-01-28T00:23:17.838Z" }, + { url = "https://files.pythonhosted.org/packages/e6/89/f7bac81d66ba7cde867a743ea5b37537b32b5c633c473002b26a226f703f/cryptography-46.0.4-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:de0f5f4ec8711ebc555f54735d4c673fc34b65c44283895f1a08c2b49d2fd99c", size = 4276213, upload-time = "2026-01-28T00:23:19.257Z" }, + { url = "https://files.pythonhosted.org/packages/da/9f/7133e41f24edd827020ad21b068736e792bc68eecf66d93c924ad4719fb3/cryptography-46.0.4-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:eeeb2e33d8dbcccc34d64651f00a98cb41b2dc69cef866771a5717e6734dfa32", size = 4912190, upload-time = "2026-01-28T00:23:21.244Z" }, + { url = "https://files.pythonhosted.org/packages/a6/f7/6d43cbaddf6f65b24816e4af187d211f0bc536a29961f69faedc48501d8e/cryptography-46.0.4-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3d425eacbc9aceafd2cb429e42f4e5d5633c6f873f5e567077043ef1b9bbf616", size = 4454641, upload-time = "2026-01-28T00:23:22.866Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4f/ebd0473ad656a0ac912a16bd07db0f5d85184924e14fc88feecae2492834/cryptography-46.0.4-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91627ebf691d1ea3976a031b61fb7bac1ccd745afa03602275dda443e11c8de0", size = 4405159, upload-time = "2026-01-28T00:23:25.278Z" }, + { url = "https://files.pythonhosted.org/packages/d1/f7/7923886f32dc47e27adeff8246e976d77258fd2aa3efdd1754e4e323bf49/cryptography-46.0.4-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2d08bc22efd73e8854b0b7caff402d735b354862f1145d7be3b9c0f740fef6a0", size = 4666059, upload-time = "2026-01-28T00:23:26.766Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a7/0fca0fd3591dffc297278a61813d7f661a14243dd60f499a7a5b48acb52a/cryptography-46.0.4-cp311-abi3-win32.whl", hash = "sha256:82a62483daf20b8134f6e92898da70d04d0ef9a75829d732ea1018678185f4f5", size = 3026378, upload-time = "2026-01-28T00:23:28.317Z" }, + { url = "https://files.pythonhosted.org/packages/2d/12/652c84b6f9873f0909374864a57b003686c642ea48c84d6c7e2c515e6da5/cryptography-46.0.4-cp311-abi3-win_amd64.whl", hash = "sha256:6225d3ebe26a55dbc8ead5ad1265c0403552a63336499564675b29eb3184c09b", size = 3478614, upload-time = "2026-01-28T00:23:30.275Z" }, + { url = "https://files.pythonhosted.org/packages/b9/27/542b029f293a5cce59349d799d4d8484b3b1654a7b9a0585c266e974a488/cryptography-46.0.4-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:485e2b65d25ec0d901bca7bcae0f53b00133bf3173916d8e421f6fddde103908", size = 7116417, upload-time = "2026-01-28T00:23:31.958Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f5/559c25b77f40b6bf828eabaf988efb8b0e17b573545edb503368ca0a2a03/cryptography-46.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:078e5f06bd2fa5aea5a324f2a09f914b1484f1d0c2a4d6a8a28c74e72f65f2da", size = 4264508, upload-time = "2026-01-28T00:23:34.264Z" }, + { url = "https://files.pythonhosted.org/packages/49/a1/551fa162d33074b660dc35c9bc3616fefa21a0e8c1edd27b92559902e408/cryptography-46.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dce1e4f068f03008da7fa51cc7abc6ddc5e5de3e3d1550334eaf8393982a5829", size = 4409080, upload-time = "2026-01-28T00:23:35.793Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/4d8d129a755f5d6df1bbee69ea2f35ebfa954fa1847690d1db2e8bca46a5/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2067461c80271f422ee7bdbe79b9b4be54a5162e90345f86a23445a0cf3fd8a2", size = 4270039, upload-time = "2026-01-28T00:23:37.263Z" }, + { url = "https://files.pythonhosted.org/packages/4c/f5/ed3fcddd0a5e39321e595e144615399e47e7c153a1fb8c4862aec3151ff9/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:c92010b58a51196a5f41c3795190203ac52edfd5dc3ff99149b4659eba9d2085", size = 4926748, upload-time = "2026-01-28T00:23:38.884Z" }, + { url = "https://files.pythonhosted.org/packages/43/ae/9f03d5f0c0c00e85ecb34f06d3b79599f20630e4db91b8a6e56e8f83d410/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:829c2b12bbc5428ab02d6b7f7e9bbfd53e33efd6672d21341f2177470171ad8b", size = 4442307, upload-time = "2026-01-28T00:23:40.56Z" }, + { url = "https://files.pythonhosted.org/packages/8b/22/e0f9f2dae8040695103369cf2283ef9ac8abe4d51f68710bec2afd232609/cryptography-46.0.4-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:62217ba44bf81b30abaeda1488686a04a702a261e26f87db51ff61d9d3510abd", size = 3959253, upload-time = "2026-01-28T00:23:42.827Z" }, + { url = "https://files.pythonhosted.org/packages/01/5b/6a43fcccc51dae4d101ac7d378a8724d1ba3de628a24e11bf2f4f43cba4d/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:9c2da296c8d3415b93e6053f5a728649a87a48ce084a9aaf51d6e46c87c7f2d2", size = 4269372, upload-time = "2026-01-28T00:23:44.655Z" }, + { url = "https://files.pythonhosted.org/packages/17/b7/0f6b8c1dd0779df2b526e78978ff00462355e31c0a6f6cff8a3e99889c90/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9b34d8ba84454641a6bf4d6762d15847ecbd85c1316c0a7984e6e4e9f748ec2e", size = 4891908, upload-time = "2026-01-28T00:23:46.48Z" }, + { url = "https://files.pythonhosted.org/packages/83/17/259409b8349aa10535358807a472c6a695cf84f106022268d31cea2b6c97/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:df4a817fa7138dd0c96c8c8c20f04b8aaa1fac3bbf610913dcad8ea82e1bfd3f", size = 4441254, upload-time = "2026-01-28T00:23:48.403Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fe/e4a1b0c989b00cee5ffa0764401767e2d1cf59f45530963b894129fd5dce/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b1de0ebf7587f28f9190b9cb526e901bf448c9e6a99655d2b07fff60e8212a82", size = 4396520, upload-time = "2026-01-28T00:23:50.26Z" }, + { url = "https://files.pythonhosted.org/packages/b3/81/ba8fd9657d27076eb40d6a2f941b23429a3c3d2f56f5a921d6b936a27bc9/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9b4d17bc7bd7cdd98e3af40b441feaea4c68225e2eb2341026c84511ad246c0c", size = 4651479, upload-time = "2026-01-28T00:23:51.674Z" }, + { url = "https://files.pythonhosted.org/packages/00/03/0de4ed43c71c31e4fe954edd50b9d28d658fef56555eba7641696370a8e2/cryptography-46.0.4-cp314-cp314t-win32.whl", hash = "sha256:c411f16275b0dea722d76544a61d6421e2cc829ad76eec79280dbdc9ddf50061", size = 3001986, upload-time = "2026-01-28T00:23:53.485Z" }, + { url = "https://files.pythonhosted.org/packages/5c/70/81830b59df7682917d7a10f833c4dab2a5574cd664e86d18139f2b421329/cryptography-46.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:728fedc529efc1439eb6107b677f7f7558adab4553ef8669f0d02d42d7b959a7", size = 3468288, upload-time = "2026-01-28T00:23:55.09Z" }, + { url = "https://files.pythonhosted.org/packages/56/f7/f648fdbb61d0d45902d3f374217451385edc7e7768d1b03ff1d0e5ffc17b/cryptography-46.0.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a9556ba711f7c23f77b151d5798f3ac44a13455cc68db7697a1096e6d0563cab", size = 7169583, upload-time = "2026-01-28T00:23:56.558Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cc/8f3224cbb2a928de7298d6ed4790f5ebc48114e02bdc9559196bfb12435d/cryptography-46.0.4-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bf75b0259e87fa70bddc0b8b4078b76e7fd512fd9afae6c1193bcf440a4dbef", size = 4275419, upload-time = "2026-01-28T00:23:58.364Z" }, + { url = "https://files.pythonhosted.org/packages/17/43/4a18faa7a872d00e4264855134ba82d23546c850a70ff209e04ee200e76f/cryptography-46.0.4-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3c268a3490df22270955966ba236d6bc4a8f9b6e4ffddb78aac535f1a5ea471d", size = 4419058, upload-time = "2026-01-28T00:23:59.867Z" }, + { url = "https://files.pythonhosted.org/packages/ee/64/6651969409821d791ba12346a124f55e1b76f66a819254ae840a965d4b9c/cryptography-46.0.4-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:812815182f6a0c1d49a37893a303b44eaac827d7f0d582cecfc81b6427f22973", size = 4278151, upload-time = "2026-01-28T00:24:01.731Z" }, + { url = "https://files.pythonhosted.org/packages/20/0b/a7fce65ee08c3c02f7a8310cc090a732344066b990ac63a9dfd0a655d321/cryptography-46.0.4-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:a90e43e3ef65e6dcf969dfe3bb40cbf5aef0d523dff95bfa24256be172a845f4", size = 4939441, upload-time = "2026-01-28T00:24:03.175Z" }, + { url = "https://files.pythonhosted.org/packages/db/a7/20c5701e2cd3e1dfd7a19d2290c522a5f435dd30957d431dcb531d0f1413/cryptography-46.0.4-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a05177ff6296644ef2876fce50518dffb5bcdf903c85250974fc8bc85d54c0af", size = 4451617, upload-time = "2026-01-28T00:24:05.403Z" }, + { url = "https://files.pythonhosted.org/packages/00/dc/3e16030ea9aa47b63af6524c354933b4fb0e352257c792c4deeb0edae367/cryptography-46.0.4-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:daa392191f626d50f1b136c9b4cf08af69ca8279d110ea24f5c2700054d2e263", size = 3977774, upload-time = "2026-01-28T00:24:06.851Z" }, + { url = "https://files.pythonhosted.org/packages/42/c8/ad93f14118252717b465880368721c963975ac4b941b7ef88f3c56bf2897/cryptography-46.0.4-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e07ea39c5b048e085f15923511d8121e4a9dc45cee4e3b970ca4f0d338f23095", size = 4277008, upload-time = "2026-01-28T00:24:08.926Z" }, + { url = "https://files.pythonhosted.org/packages/00/cf/89c99698151c00a4631fbfcfcf459d308213ac29e321b0ff44ceeeac82f1/cryptography-46.0.4-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d5a45ddc256f492ce42a4e35879c5e5528c09cd9ad12420828c972951d8e016b", size = 4903339, upload-time = "2026-01-28T00:24:12.009Z" }, + { url = "https://files.pythonhosted.org/packages/03/c3/c90a2cb358de4ac9309b26acf49b2a100957e1ff5cc1e98e6c4996576710/cryptography-46.0.4-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:6bb5157bf6a350e5b28aee23beb2d84ae6f5be390b2f8ee7ea179cda077e1019", size = 4451216, upload-time = "2026-01-28T00:24:13.975Z" }, + { url = "https://files.pythonhosted.org/packages/96/2c/8d7f4171388a10208671e181ca43cdc0e596d8259ebacbbcfbd16de593da/cryptography-46.0.4-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:dd5aba870a2c40f87a3af043e0dee7d9eb02d4aff88a797b48f2b43eff8c3ab4", size = 4404299, upload-time = "2026-01-28T00:24:16.169Z" }, + { url = "https://files.pythonhosted.org/packages/e9/23/cbb2036e450980f65c6e0a173b73a56ff3bccd8998965dea5cc9ddd424a5/cryptography-46.0.4-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:93d8291da8d71024379ab2cb0b5c57915300155ad42e07f76bea6ad838d7e59b", size = 4664837, upload-time = "2026-01-28T00:24:17.629Z" }, + { url = "https://files.pythonhosted.org/packages/0a/21/f7433d18fe6d5845329cbdc597e30caf983229c7a245bcf54afecc555938/cryptography-46.0.4-cp38-abi3-win32.whl", hash = "sha256:0563655cb3c6d05fb2afe693340bc050c30f9f34e15763361cf08e94749401fc", size = 3009779, upload-time = "2026-01-28T00:24:20.198Z" }, + { url = "https://files.pythonhosted.org/packages/3a/6a/bd2e7caa2facffedf172a45c1a02e551e6d7d4828658c9a245516a598d94/cryptography-46.0.4-cp38-abi3-win_amd64.whl", hash = "sha256:fa0900b9ef9c49728887d1576fd8d9e7e3ea872fa9b25ef9b64888adc434e976", size = 3466633, upload-time = "2026-01-28T00:24:21.851Z" }, + { url = "https://files.pythonhosted.org/packages/59/e0/f9c6c53e1f2a1c2507f00f2faba00f01d2f334b35b0fbfe5286715da2184/cryptography-46.0.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:766330cce7416c92b5e90c3bb71b1b79521760cdcfc3a6a1a182d4c9fab23d2b", size = 3476316, upload-time = "2026-01-28T00:24:24.144Z" }, + { url = "https://files.pythonhosted.org/packages/27/7a/f8d2d13227a9a1a9fe9c7442b057efecffa41f1e3c51d8622f26b9edbe8f/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c236a44acfb610e70f6b3e1c3ca20ff24459659231ef2f8c48e879e2d32b73da", size = 4216693, upload-time = "2026-01-28T00:24:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/c5/de/3787054e8f7972658370198753835d9d680f6cd4a39df9f877b57f0dd69c/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8a15fb869670efa8f83cbffbc8753c1abf236883225aed74cd179b720ac9ec80", size = 4382765, upload-time = "2026-01-28T00:24:27.577Z" }, + { url = "https://files.pythonhosted.org/packages/8a/5f/60e0afb019973ba6a0b322e86b3d61edf487a4f5597618a430a2a15f2d22/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:fdc3daab53b212472f1524d070735b2f0c214239df131903bae1d598016fa822", size = 4216066, upload-time = "2026-01-28T00:24:29.056Z" }, + { url = "https://files.pythonhosted.org/packages/81/8e/bf4a0de294f147fee66f879d9bae6f8e8d61515558e3d12785dd90eca0be/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:44cc0675b27cadb71bdbb96099cca1fa051cd11d2ade09e5cd3a2edb929ed947", size = 4382025, upload-time = "2026-01-28T00:24:30.681Z" }, + { url = "https://files.pythonhosted.org/packages/79/f4/9ceb90cfd6a3847069b0b0b353fd3075dc69b49defc70182d8af0c4ca390/cryptography-46.0.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be8c01a7d5a55f9a47d1888162b76c8f49d62b234d88f0ff91a9fbebe32ffbc3", size = 3406043, upload-time = "2026-01-28T00:24:32.236Z" }, ] [[package]] @@ -1031,12 +1027,13 @@ all = [ { name = "httpx" }, { name = "itsdangerous" }, { name = "jinja2" }, - { name = "orjson" }, + { name = "orjson", version = "3.11.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "orjson", version = "3.11.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pydantic-extra-types" }, { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.21", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pyyaml" }, { name = "ujson" }, { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, @@ -1051,7 +1048,7 @@ standard = [ { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.21", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, ] @@ -1064,7 +1061,7 @@ standard-no-fastapi-cloud-cli = [ { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.21", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, ] @@ -1076,7 +1073,7 @@ dev = [ { name = "black" }, { name = "cairosvg" }, { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, { name = "dirty-equals" }, { name = "flask" }, { name = "gitpython" }, @@ -1107,7 +1104,7 @@ dev = [ { name = "ruff" }, { name = "sqlmodel" }, { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.288.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql", version = "0.291.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typer" }, { name = "types-orjson" }, { name = "types-ujson" }, @@ -1148,7 +1145,7 @@ tests = [ { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, { name = "dirty-equals" }, { name = "flask" }, { name = "httpx" }, @@ -1163,7 +1160,7 @@ tests = [ { name = "ruff" }, { name = "sqlmodel" }, { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.288.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql", version = "0.291.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "types-orjson" }, { name = "types-ujson" }, ] @@ -1189,7 +1186,7 @@ requires-dist = [ { name = "jinja2", marker = "extra == 'all'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=3.1.5" }, - { name = "orjson", marker = "extra == 'all'", specifier = ">=3.2.1" }, + { name = "orjson", marker = "extra == 'all'", specifier = ">=3.9.3" }, { name = "pydantic", specifier = ">=2.7.0" }, { name = "pydantic-extra-types", marker = "extra == 'all'", specifier = ">=2.0.0" }, { name = "pydantic-extra-types", marker = "extra == 'standard'", specifier = ">=2.0.0" }, @@ -1204,7 +1201,7 @@ requires-dist = [ { name = "starlette", specifier = ">=0.40.0,<0.51.0" }, { name = "typing-extensions", specifier = ">=4.8.0" }, { name = "typing-inspection", specifier = ">=0.4.2" }, - { name = "ujson", marker = "extra == 'all'", specifier = ">=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0" }, + { name = "ujson", marker = "extra == 'all'", specifier = ">=5.8.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=0.12.0" }, @@ -1219,7 +1216,7 @@ dev = [ { name = "cairosvg", specifier = "==2.8.2" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, { name = "dirty-equals", specifier = "==0.9.0" }, - { name = "flask", specifier = ">=1.1.2,<4.0.0" }, + { name = "flask", specifier = ">=3.0.0,<4.0.0" }, { name = "gitpython", specifier = "==3.1.46" }, { name = "griffe-typingdoc", specifier = "==0.3.0" }, { name = "griffe-warnings-deprecated", specifier = "==1.1.0" }, @@ -1287,7 +1284,7 @@ tests = [ { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, { name = "dirty-equals", specifier = "==0.9.0" }, - { name = "flask", specifier = ">=1.1.2,<4.0.0" }, + { name = "flask", specifier = ">=3.0.0,<4.0.0" }, { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, { name = "inline-snapshot", specifier = ">=0.21.1" }, { name = "mypy", specifier = "==1.14.1" }, @@ -1337,7 +1334,7 @@ standard-no-fastapi-cloud-cli = [ [[package]] name = "fastapi-cloud-cli" -version = "0.8.0" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastar" }, @@ -1350,9 +1347,9 @@ dependencies = [ { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/5d/3b33438de35521fab4968b232caa9a4bd568a5078f2b2dfb7bb8a4528603/fastapi_cloud_cli-0.8.0.tar.gz", hash = "sha256:cf07c502528bfd9e6b184776659f05d9212811d76bbec9fbb6bf34bed4c7456f", size = 30257, upload-time = "2025-12-23T12:08:33.904Z" } +sdist = { url = "https://files.pythonhosted.org/packages/11/15/6c3d85d63964340fde6f36cc80f3f365d35f371e6a918d68ff3a3d588ef2/fastapi_cloud_cli-0.11.0.tar.gz", hash = "sha256:ecc83a5db106be35af528eccb01aa9bced1d29783efd48c8c1c831cf111eea99", size = 36170, upload-time = "2026-01-15T09:51:33.681Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/8e/abb95ef59e91bb5adaa2d18fbf9ea70fd524010bb03f406a2dd2a4775ef9/fastapi_cloud_cli-0.8.0-py3-none-any.whl", hash = "sha256:e9f40bee671d985fd25d7a5409b56d4f103777bf8a0c6d746ea5fbf97a8186d9", size = 22306, upload-time = "2025-12-23T12:08:32.68Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/60f79270a3320780be7e2ae8a1740cb98a692920b569ba420b97bcc6e175/fastapi_cloud_cli-0.11.0-py3-none-any.whl", hash = "sha256:76857b0f09d918acfcb50ade34682ba3b2079ca0c43fda10215de301f185a7f8", size = 26884, upload-time = "2026-01-15T09:51:34.471Z" }, ] [[package]] @@ -1569,15 +1566,15 @@ wheels = [ [[package]] name = "filelock" -version = "3.20.2" +version = "3.20.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/e0/a75dbe4bca1e7d41307323dad5ea2efdd95408f74ab2de8bd7dba9b51a1a/filelock-3.20.2.tar.gz", hash = "sha256:a2241ff4ddde2a7cebddf78e39832509cb045d18ec1a09d7248d6bfc6bfbbe64", size = 19510, upload-time = "2026-01-02T15:33:32.582Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/30/ab407e2ec752aa541704ed8f93c11e2a5d92c168b8a755d818b74a3c5c2d/filelock-3.20.2-py3-none-any.whl", hash = "sha256:fbba7237d6ea277175a32c54bb71ef814a8546d8601269e1bfc388de333974e8", size = 16697, upload-time = "2026-01-02T15:33:31.133Z" }, + { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] [[package]] @@ -1613,15 +1610,15 @@ wheels = [ [[package]] name = "fsspec" -version = "2025.12.0" +version = "2026.2.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/b6/27/954057b0d1f53f086f681755207dda6de6c660ce133c829158e8e8fe7895/fsspec-2025.12.0.tar.gz", hash = "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973", size = 309748, upload-time = "2025-12-03T15:23:42.687Z" } +sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/c7/b64cae5dba3a1b138d7123ec36bb5ccd39d39939f18454407e5468f4763f/fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b", size = 201422, upload-time = "2025-12-03T15:23:41.434Z" }, + { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, ] [[package]] @@ -1663,15 +1660,16 @@ wheels = [ [[package]] name = "google-auth" -version = "2.47.0" +version = "2.48.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "cryptography" }, { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/3c/ec64b9a275ca22fa1cd3b6e77fefcf837b0732c890aa32d2bd21313d9b33/google_auth-2.47.0.tar.gz", hash = "sha256:833229070a9dfee1a353ae9877dcd2dec069a8281a4e72e72f77d4a70ff945da", size = 323719, upload-time = "2026-01-06T21:55:31.045Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/41/242044323fbd746615884b1c16639749e73665b718209946ebad7ba8a813/google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce", size = 326522, upload-time = "2026-01-26T19:22:47.157Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/18/79e9008530b79527e0d5f79e7eef08d3b179b7f851cfd3a2f27822fbdfa9/google_auth-2.47.0-py3-none-any.whl", hash = "sha256:c516d68336bfde7cf0da26aab674a36fedcf04b37ac4edd59c597178760c3498", size = 234867, upload-time = "2026-01-06T21:55:28.6Z" }, + { url = "https://files.pythonhosted.org/packages/83/1d/d6466de3a5249d35e832a52834115ca9d1d0de6abc22065f049707516d47/google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f", size = 236499, upload-time = "2026-01-26T19:22:45.099Z" }, ] [package.optional-dependencies] @@ -1692,7 +1690,7 @@ dependencies = [ { name = "httpx", marker = "python_full_version < '3.10'" }, { name = "pydantic", marker = "python_full_version < '3.10'" }, { name = "requests", marker = "python_full_version < '3.10'" }, - { name = "tenacity", marker = "python_full_version < '3.10'" }, + { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, { name = "websockets", marker = "python_full_version < '3.10'" }, ] @@ -1703,7 +1701,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.57.0" +version = "1.62.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", @@ -1717,13 +1715,13 @@ dependencies = [ { name = "pydantic", marker = "python_full_version >= '3.10'" }, { name = "requests", marker = "python_full_version >= '3.10'" }, { name = "sniffio", marker = "python_full_version >= '3.10'" }, - { name = "tenacity", marker = "python_full_version >= '3.10'" }, + { name = "tenacity", version = "9.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, { name = "websockets", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2b/b4/8251c2d2576224a4b51a8ab6159820f9200b8da28ff555c78ee15607096e/google_genai-1.57.0.tar.gz", hash = "sha256:0ff9c36b8d68abfbdbd13b703ece926de5f3e67955666b36315ecf669b94a826", size = 485648, upload-time = "2026-01-07T20:38:20.271Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/4c/71b32b5c8db420cf2fd0d5ef8a672adbde97d85e5d44a0b4fca712264ef1/google_genai-1.62.0.tar.gz", hash = "sha256:709468a14c739a080bc240a4f3191df597bf64485b1ca3728e0fb67517774c18", size = 490888, upload-time = "2026-02-04T22:48:41.989Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/02/858bdae08e2184b6afe0b18bc3113318522c9cf326a5a1698055edd31f88/google_genai-1.57.0-py3-none-any.whl", hash = "sha256:d63c7a89a1f549c4d14032f41a0cdb4b6fe3f565e2eee6b5e0907a0aeceabefd", size = 713323, upload-time = "2026-01-07T20:38:18.051Z" }, + { url = "https://files.pythonhosted.org/packages/09/5f/4645d8a28c6e431d0dd6011003a852563f3da7037d36af53154925b099fd/google_genai-1.62.0-py3-none-any.whl", hash = "sha256:4c3daeff3d05fafee4b9a1a31f9c07f01bc22051081aa58b4d61f58d16d1bcc0", size = 724166, upload-time = "2026-02-04T22:48:39.956Z" }, ] [[package]] @@ -1816,61 +1814,66 @@ wheels = [ [[package]] name = "greenlet" -version = "3.3.0" +version = "3.3.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/6a/33d1702184d94106d3cdd7bfb788e19723206fce152e303473ca3b946c7b/greenlet-3.3.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6f8496d434d5cb2dce025773ba5597f71f5410ae499d5dd9533e0653258cdb3d", size = 273658, upload-time = "2025-12-04T14:23:37.494Z" }, - { url = "https://files.pythonhosted.org/packages/d6/b7/2b5805bbf1907c26e434f4e448cd8b696a0b71725204fa21a211ff0c04a7/greenlet-3.3.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b96dc7eef78fd404e022e165ec55327f935b9b52ff355b067eb4a0267fc1cffb", size = 574810, upload-time = "2025-12-04T14:50:04.154Z" }, - { url = "https://files.pythonhosted.org/packages/94/38/343242ec12eddf3d8458c73f555c084359883d4ddc674240d9e61ec51fd6/greenlet-3.3.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73631cd5cccbcfe63e3f9492aaa664d278fda0ce5c3d43aeda8e77317e38efbd", size = 586248, upload-time = "2025-12-04T14:57:39.35Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d0/0ae86792fb212e4384041e0ef8e7bc66f59a54912ce407d26a966ed2914d/greenlet-3.3.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b299a0cb979f5d7197442dccc3aee67fce53500cd88951b7e6c35575701c980b", size = 597403, upload-time = "2025-12-04T15:07:10.831Z" }, - { url = "https://files.pythonhosted.org/packages/b6/a8/15d0aa26c0036a15d2659175af00954aaaa5d0d66ba538345bd88013b4d7/greenlet-3.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7dee147740789a4632cace364816046e43310b59ff8fb79833ab043aefa72fd5", size = 586910, upload-time = "2025-12-04T14:25:59.705Z" }, - { url = "https://files.pythonhosted.org/packages/e1/9b/68d5e3b7ccaba3907e5532cf8b9bf16f9ef5056a008f195a367db0ff32db/greenlet-3.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:39b28e339fc3c348427560494e28d8a6f3561c8d2bcf7d706e1c624ed8d822b9", size = 1547206, upload-time = "2025-12-04T15:04:21.027Z" }, - { url = "https://files.pythonhosted.org/packages/66/bd/e3086ccedc61e49f91e2cfb5ffad9d8d62e5dc85e512a6200f096875b60c/greenlet-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3c374782c2935cc63b2a27ba8708471de4ad1abaa862ffdb1ef45a643ddbb7d", size = 1613359, upload-time = "2025-12-04T14:27:26.548Z" }, - { url = "https://files.pythonhosted.org/packages/f4/6b/d4e73f5dfa888364bbf02efa85616c6714ae7c631c201349782e5b428925/greenlet-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:b49e7ed51876b459bd645d83db257f0180e345d3f768a35a85437a24d5a49082", size = 300740, upload-time = "2025-12-04T14:47:52.773Z" }, - { url = "https://files.pythonhosted.org/packages/1f/cb/48e964c452ca2b92175a9b2dca037a553036cb053ba69e284650ce755f13/greenlet-3.3.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e29f3018580e8412d6aaf5641bb7745d38c85228dacf51a73bd4e26ddf2a6a8e", size = 274908, upload-time = "2025-12-04T14:23:26.435Z" }, - { url = "https://files.pythonhosted.org/packages/28/da/38d7bff4d0277b594ec557f479d65272a893f1f2a716cad91efeb8680953/greenlet-3.3.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a687205fb22794e838f947e2194c0566d3812966b41c78709554aa883183fb62", size = 577113, upload-time = "2025-12-04T14:50:05.493Z" }, - { url = "https://files.pythonhosted.org/packages/3c/f2/89c5eb0faddc3ff014f1c04467d67dee0d1d334ab81fadbf3744847f8a8a/greenlet-3.3.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4243050a88ba61842186cb9e63c7dfa677ec146160b0efd73b855a3d9c7fcf32", size = 590338, upload-time = "2025-12-04T14:57:41.136Z" }, - { url = "https://files.pythonhosted.org/packages/80/d7/db0a5085035d05134f8c089643da2b44cc9b80647c39e93129c5ef170d8f/greenlet-3.3.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:670d0f94cd302d81796e37299bcd04b95d62403883b24225c6b5271466612f45", size = 601098, upload-time = "2025-12-04T15:07:11.898Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/e959a127b630a58e23529972dbc868c107f9d583b5a9f878fb858c46bc1a/greenlet-3.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb3a8ec3db4a3b0eb8a3c25436c2d49e3505821802074969db017b87bc6a948", size = 590206, upload-time = "2025-12-04T14:26:01.254Z" }, - { url = "https://files.pythonhosted.org/packages/48/60/29035719feb91798693023608447283b266b12efc576ed013dd9442364bb/greenlet-3.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2de5a0b09eab81fc6a382791b995b1ccf2b172a9fec934747a7a23d2ff291794", size = 1550668, upload-time = "2025-12-04T15:04:22.439Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5f/783a23754b691bfa86bd72c3033aa107490deac9b2ef190837b860996c9f/greenlet-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4449a736606bd30f27f8e1ff4678ee193bc47f6ca810d705981cfffd6ce0d8c5", size = 1615483, upload-time = "2025-12-04T14:27:28.083Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d5/c339b3b4bc8198b7caa4f2bd9fd685ac9f29795816d8db112da3d04175bb/greenlet-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:7652ee180d16d447a683c04e4c5f6441bae7ba7b17ffd9f6b3aff4605e9e6f71", size = 301164, upload-time = "2025-12-04T14:42:51.577Z" }, - { url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" }, - { url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" }, - { url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" }, - { url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" }, - { url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" }, - { url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" }, - { url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" }, - { url = "https://files.pythonhosted.org/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" }, - { url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" }, - { url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" }, - { url = "https://files.pythonhosted.org/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311, upload-time = "2025-12-04T15:07:14.697Z" }, - { url = "https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833, upload-time = "2025-12-04T14:26:03.669Z" }, - { url = "https://files.pythonhosted.org/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256, upload-time = "2025-12-04T15:04:25.276Z" }, - { url = "https://files.pythonhosted.org/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483, upload-time = "2025-12-04T14:27:30.804Z" }, - { url = "https://files.pythonhosted.org/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833, upload-time = "2025-12-04T14:32:23.929Z" }, - { url = "https://files.pythonhosted.org/packages/d7/7c/f0a6d0ede2c7bf092d00bc83ad5bafb7e6ec9b4aab2fbdfa6f134dc73327/greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f", size = 275671, upload-time = "2025-12-04T14:23:05.267Z" }, - { url = "https://files.pythonhosted.org/packages/44/06/dac639ae1a50f5969d82d2e3dd9767d30d6dbdbab0e1a54010c8fe90263c/greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365", size = 646360, upload-time = "2025-12-04T14:50:10.026Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/0fb76fe6c5369fba9bf98529ada6f4c3a1adf19e406a47332245ef0eb357/greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3", size = 658160, upload-time = "2025-12-04T14:57:45.41Z" }, - { url = "https://files.pythonhosted.org/packages/93/79/d2c70cae6e823fac36c3bbc9077962105052b7ef81db2f01ec3b9bf17e2b/greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45", size = 671388, upload-time = "2025-12-04T15:07:15.789Z" }, - { url = "https://files.pythonhosted.org/packages/b8/14/bab308fc2c1b5228c3224ec2bf928ce2e4d21d8046c161e44a2012b5203e/greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955", size = 660166, upload-time = "2025-12-04T14:26:05.099Z" }, - { url = "https://files.pythonhosted.org/packages/4b/d2/91465d39164eaa0085177f61983d80ffe746c5a1860f009811d498e7259c/greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55", size = 1615193, upload-time = "2025-12-04T15:04:27.041Z" }, - { url = "https://files.pythonhosted.org/packages/42/1b/83d110a37044b92423084d52d5d5a3b3a73cafb51b547e6d7366ff62eff1/greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc", size = 1683653, upload-time = "2025-12-04T14:27:32.366Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/9030e6f9aa8fd7808e9c31ba4c38f87c4f8ec324ee67431d181fe396d705/greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170", size = 305387, upload-time = "2025-12-04T14:26:51.063Z" }, - { url = "https://files.pythonhosted.org/packages/a0/66/bd6317bc5932accf351fc19f177ffba53712a202f9df10587da8df257c7e/greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931", size = 282638, upload-time = "2025-12-04T14:25:20.941Z" }, - { url = "https://files.pythonhosted.org/packages/30/cf/cc81cb030b40e738d6e69502ccbd0dd1bced0588e958f9e757945de24404/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388", size = 651145, upload-time = "2025-12-04T14:50:11.039Z" }, - { url = "https://files.pythonhosted.org/packages/9c/ea/1020037b5ecfe95ca7df8d8549959baceb8186031da83d5ecceff8b08cd2/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3", size = 654236, upload-time = "2025-12-04T14:57:47.007Z" }, - { url = "https://files.pythonhosted.org/packages/69/cc/1e4bae2e45ca2fa55299f4e85854606a78ecc37fead20d69322f96000504/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221", size = 662506, upload-time = "2025-12-04T15:07:16.906Z" }, - { url = "https://files.pythonhosted.org/packages/57/b9/f8025d71a6085c441a7eaff0fd928bbb275a6633773667023d19179fe815/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b", size = 653783, upload-time = "2025-12-04T14:26:06.225Z" }, - { url = "https://files.pythonhosted.org/packages/f6/c7/876a8c7a7485d5d6b5c6821201d542ef28be645aa024cfe1145b35c120c1/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd", size = 1614857, upload-time = "2025-12-04T15:04:28.484Z" }, - { url = "https://files.pythonhosted.org/packages/4f/dc/041be1dff9f23dac5f48a43323cd0789cb798342011c19a248d9c9335536/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9", size = 1676034, upload-time = "2025-12-04T14:27:33.531Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/8a/99/1cd3411c56a410994669062bd73dd58270c00cc074cac15f385a1fd91f8a/greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98", size = 184690, upload-time = "2026-01-23T15:31:02.076Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/65/5b235b40581ad75ab97dcd8b4218022ae8e3ab77c13c919f1a1dfe9171fd/greenlet-3.3.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13", size = 273723, upload-time = "2026-01-23T15:30:37.521Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ad/eb4729b85cba2d29499e0a04ca6fbdd8f540afd7be142fd571eea43d712f/greenlet-3.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4", size = 574874, upload-time = "2026-01-23T16:00:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/87/32/57cad7fe4c8b82fdaa098c89498ef85ad92dfbb09d5eb713adedfc2ae1f5/greenlet-3.3.1-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5", size = 586309, upload-time = "2026-01-23T16:05:25.18Z" }, + { url = "https://files.pythonhosted.org/packages/66/66/f041005cb87055e62b0d68680e88ec1a57f4688523d5e2fb305841bc8307/greenlet-3.3.1-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5", size = 597461, upload-time = "2026-01-23T16:15:51.943Z" }, + { url = "https://files.pythonhosted.org/packages/87/eb/8a1ec2da4d55824f160594a75a9d8354a5fe0a300fb1c48e7944265217e1/greenlet-3.3.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe", size = 586985, upload-time = "2026-01-23T15:32:47.968Z" }, + { url = "https://files.pythonhosted.org/packages/15/1c/0621dd4321dd8c351372ee8f9308136acb628600658a49be1b7504208738/greenlet-3.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729", size = 1547271, upload-time = "2026-01-23T16:04:18.977Z" }, + { url = "https://files.pythonhosted.org/packages/9d/53/24047f8924c83bea7a59c8678d9571209c6bfe5f4c17c94a78c06024e9f2/greenlet-3.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4", size = 1613427, upload-time = "2026-01-23T15:33:44.428Z" }, + { url = "https://files.pythonhosted.org/packages/ff/07/ac9bf1ec008916d1a3373cae212884c1dcff4a4ba0d41127ce81a8deb4e9/greenlet-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8", size = 226100, upload-time = "2026-01-23T15:30:56.957Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e8/2e1462c8fdbe0f210feb5ac7ad2d9029af8be3bf45bd9fa39765f821642f/greenlet-3.3.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c", size = 274974, upload-time = "2026-01-23T15:31:02.891Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a8/530a401419a6b302af59f67aaf0b9ba1015855ea7e56c036b5928793c5bd/greenlet-3.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd", size = 577175, upload-time = "2026-01-23T16:00:56.213Z" }, + { url = "https://files.pythonhosted.org/packages/8e/89/7e812bb9c05e1aaef9b597ac1d0962b9021d2c6269354966451e885c4e6b/greenlet-3.3.1-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5", size = 590401, upload-time = "2026-01-23T16:05:26.365Z" }, + { url = "https://files.pythonhosted.org/packages/70/ae/e2d5f0e59b94a2269b68a629173263fa40b63da32f5c231307c349315871/greenlet-3.3.1-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f", size = 601161, upload-time = "2026-01-23T16:15:53.456Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ae/8d472e1f5ac5efe55c563f3eabb38c98a44b832602e12910750a7c025802/greenlet-3.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2", size = 590272, upload-time = "2026-01-23T15:32:49.411Z" }, + { url = "https://files.pythonhosted.org/packages/a8/51/0fde34bebfcadc833550717eade64e35ec8738e6b097d5d248274a01258b/greenlet-3.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9", size = 1550729, upload-time = "2026-01-23T16:04:20.867Z" }, + { url = "https://files.pythonhosted.org/packages/16/c9/2fb47bee83b25b119d5a35d580807bb8b92480a54b68fef009a02945629f/greenlet-3.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f", size = 1615552, upload-time = "2026-01-23T15:33:45.743Z" }, + { url = "https://files.pythonhosted.org/packages/1f/54/dcf9f737b96606f82f8dd05becfb8d238db0633dd7397d542a296fe9cad3/greenlet-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b", size = 226462, upload-time = "2026-01-23T15:36:50.422Z" }, + { url = "https://files.pythonhosted.org/packages/91/37/61e1015cf944ddd2337447d8e97fb423ac9bc21f9963fb5f206b53d65649/greenlet-3.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4", size = 225715, upload-time = "2026-01-23T15:33:17.298Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/9d76a66421d1ae24340dfae7e79c313957f6e3195c144d2c73333b5bfe34/greenlet-3.3.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975", size = 276443, upload-time = "2026-01-23T15:30:10.066Z" }, + { url = "https://files.pythonhosted.org/packages/81/99/401ff34bb3c032d1f10477d199724f5e5f6fbfb59816ad1455c79c1eb8e7/greenlet-3.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36", size = 597359, upload-time = "2026-01-23T16:00:57.394Z" }, + { url = "https://files.pythonhosted.org/packages/2b/bc/4dcc0871ed557792d304f50be0f7487a14e017952ec689effe2180a6ff35/greenlet-3.3.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba", size = 607805, upload-time = "2026-01-23T16:05:28.068Z" }, + { url = "https://files.pythonhosted.org/packages/3b/cd/7a7ca57588dac3389e97f7c9521cb6641fd8b6602faf1eaa4188384757df/greenlet-3.3.1-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca", size = 622363, upload-time = "2026-01-23T16:15:54.754Z" }, + { url = "https://files.pythonhosted.org/packages/cf/05/821587cf19e2ce1f2b24945d890b164401e5085f9d09cbd969b0c193cd20/greenlet-3.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336", size = 609947, upload-time = "2026-01-23T15:32:51.004Z" }, + { url = "https://files.pythonhosted.org/packages/a4/52/ee8c46ed9f8babaa93a19e577f26e3d28a519feac6350ed6f25f1afee7e9/greenlet-3.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1", size = 1567487, upload-time = "2026-01-23T16:04:22.125Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7c/456a74f07029597626f3a6db71b273a3632aecb9afafeeca452cfa633197/greenlet-3.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149", size = 1636087, upload-time = "2026-01-23T15:33:47.486Z" }, + { url = "https://files.pythonhosted.org/packages/34/2f/5e0e41f33c69655300a5e54aeb637cf8ff57f1786a3aba374eacc0228c1d/greenlet-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a", size = 227156, upload-time = "2026-01-23T15:34:34.808Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ab/717c58343cf02c5265b531384b248787e04d8160b8afe53d9eec053d7b44/greenlet-3.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1", size = 226403, upload-time = "2026-01-23T15:31:39.372Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ab/d26750f2b7242c2b90ea2ad71de70cfcd73a948a49513188a0fc0d6fc15a/greenlet-3.3.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3", size = 275205, upload-time = "2026-01-23T15:30:24.556Z" }, + { url = "https://files.pythonhosted.org/packages/10/d3/be7d19e8fad7c5a78eeefb2d896a08cd4643e1e90c605c4be3b46264998f/greenlet-3.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac", size = 599284, upload-time = "2026-01-23T16:00:58.584Z" }, + { url = "https://files.pythonhosted.org/packages/ae/21/fe703aaa056fdb0f17e5afd4b5c80195bbdab701208918938bd15b00d39b/greenlet-3.3.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd", size = 610274, upload-time = "2026-01-23T16:05:29.312Z" }, + { url = "https://files.pythonhosted.org/packages/06/00/95df0b6a935103c0452dad2203f5be8377e551b8466a29650c4c5a5af6cc/greenlet-3.3.1-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e", size = 624375, upload-time = "2026-01-23T16:15:55.915Z" }, + { url = "https://files.pythonhosted.org/packages/cb/86/5c6ab23bb3c28c21ed6bebad006515cfe08b04613eb105ca0041fecca852/greenlet-3.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3", size = 612904, upload-time = "2026-01-23T15:32:52.317Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f3/7949994264e22639e40718c2daf6f6df5169bf48fb038c008a489ec53a50/greenlet-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951", size = 1567316, upload-time = "2026-01-23T16:04:23.316Z" }, + { url = "https://files.pythonhosted.org/packages/8d/6e/d73c94d13b6465e9f7cd6231c68abde838bb22408596c05d9059830b7872/greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2", size = 1636549, upload-time = "2026-01-23T15:33:48.643Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b3/c9c23a6478b3bcc91f979ce4ca50879e4d0b2bd7b9a53d8ecded719b92e2/greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946", size = 227042, upload-time = "2026-01-23T15:33:58.216Z" }, + { url = "https://files.pythonhosted.org/packages/90/e7/824beda656097edee36ab15809fd063447b200cc03a7f6a24c34d520bc88/greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d", size = 226294, upload-time = "2026-01-23T15:30:52.73Z" }, + { url = "https://files.pythonhosted.org/packages/ae/fb/011c7c717213182caf78084a9bea51c8590b0afda98001f69d9f853a495b/greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5", size = 275737, upload-time = "2026-01-23T15:32:16.889Z" }, + { url = "https://files.pythonhosted.org/packages/41/2e/a3a417d620363fdbb08a48b1dd582956a46a61bf8fd27ee8164f9dfe87c2/greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b", size = 646422, upload-time = "2026-01-23T16:01:00.354Z" }, + { url = "https://files.pythonhosted.org/packages/b4/09/c6c4a0db47defafd2d6bab8ddfe47ad19963b4e30f5bed84d75328059f8c/greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e", size = 658219, upload-time = "2026-01-23T16:05:30.956Z" }, + { url = "https://files.pythonhosted.org/packages/e2/89/b95f2ddcc5f3c2bc09c8ee8d77be312df7f9e7175703ab780f2014a0e781/greenlet-3.3.1-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d", size = 671455, upload-time = "2026-01-23T16:15:57.232Z" }, + { url = "https://files.pythonhosted.org/packages/80/38/9d42d60dffb04b45f03dbab9430898352dba277758640751dc5cc316c521/greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f", size = 660237, upload-time = "2026-01-23T15:32:53.967Z" }, + { url = "https://files.pythonhosted.org/packages/96/61/373c30b7197f9e756e4c81ae90a8d55dc3598c17673f91f4d31c3c689c3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683", size = 1615261, upload-time = "2026-01-23T16:04:25.066Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d3/ca534310343f5945316f9451e953dcd89b36fe7a19de652a1dc5a0eeef3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1", size = 1683719, upload-time = "2026-01-23T15:33:50.61Z" }, + { url = "https://files.pythonhosted.org/packages/52/cb/c21a3fd5d2c9c8b622e7bede6d6d00e00551a5ee474ea6d831b5f567a8b4/greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a", size = 228125, upload-time = "2026-01-23T15:32:45.265Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8e/8a2db6d11491837af1de64b8aff23707c6e85241be13c60ed399a72e2ef8/greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79", size = 227519, upload-time = "2026-01-23T15:31:47.284Z" }, + { url = "https://files.pythonhosted.org/packages/28/24/cbbec49bacdcc9ec652a81d3efef7b59f326697e7edf6ed775a5e08e54c2/greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242", size = 282706, upload-time = "2026-01-23T15:33:05.525Z" }, + { url = "https://files.pythonhosted.org/packages/86/2e/4f2b9323c144c4fe8842a4e0d92121465485c3c2c5b9e9b30a52e80f523f/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774", size = 651209, upload-time = "2026-01-23T16:01:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/d9/87/50ca60e515f5bb55a2fbc5f0c9b5b156de7d2fc51a0a69abc9d23914a237/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97", size = 654300, upload-time = "2026-01-23T16:05:32.199Z" }, + { url = "https://files.pythonhosted.org/packages/7c/25/c51a63f3f463171e09cb586eb64db0861eb06667ab01a7968371a24c4f3b/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab", size = 662574, upload-time = "2026-01-23T16:15:58.364Z" }, + { url = "https://files.pythonhosted.org/packages/1d/94/74310866dfa2b73dd08659a3d18762f83985ad3281901ba0ee9a815194fb/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2", size = 653842, upload-time = "2026-01-23T15:32:55.671Z" }, + { url = "https://files.pythonhosted.org/packages/97/43/8bf0ffa3d498eeee4c58c212a3905dd6146c01c8dc0b0a046481ca29b18c/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53", size = 1614917, upload-time = "2026-01-23T16:04:26.276Z" }, + { url = "https://files.pythonhosted.org/packages/89/90/a3be7a5f378fc6e84abe4dcfb2ba32b07786861172e502388b4c90000d1b/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249", size = 1676092, upload-time = "2026-01-23T15:33:52.176Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2b/98c7f93e6db9977aaee07eb1e51ca63bd5f779b900d362791d3252e60558/greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451", size = 233181, upload-time = "2026-01-23T15:33:00.29Z" }, ] [[package]] @@ -2084,13 +2087,13 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.3.0" +version = "1.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "filelock", version = "3.20.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "filelock", version = "3.20.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "fsspec", version = "2025.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "fsspec", version = "2025.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "fsspec", version = "2026.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, { name = "httpx" }, { name = "packaging" }, @@ -2100,9 +2103,9 @@ dependencies = [ { name = "typer-slim" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/c9/d42b5cfa0a50b77cf9165e13edfaf2e3bd4e0def9cb67b6b8a07224a52ab/huggingface_hub-1.3.0.tar.gz", hash = "sha256:289e2a3586fdf01e35882944eaa06fbd57436de24b6e653d1fab248584acd66b", size = 622092, upload-time = "2026-01-09T09:54:44.663Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/fc/eb9bc06130e8bbda6a616e1b80a7aa127681c448d6b49806f61db2670b61/huggingface_hub-1.4.1.tar.gz", hash = "sha256:b41131ec35e631e7383ab26d6146b8d8972abc8b6309b963b306fbcca87f5ed5", size = 642156, upload-time = "2026-02-06T09:20:03.013Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/5b/c5fde1f56b1f072b3028ec5413f3f5bf472c5891ebb34589cddb1689609f/huggingface_hub-1.3.0-py3-none-any.whl", hash = "sha256:763f450169bb05ea3867990e9d3ba9464eb617b874791301dc81be2c6ffb0bf5", size = 533092, upload-time = "2026-01-09T09:54:43.228Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, ] [[package]] @@ -2205,120 +2208,120 @@ wheels = [ [[package]] name = "jiter" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/45/9d/e0660989c1370e25848bb4c52d061c71837239738ad937e83edca174c273/jiter-0.12.0.tar.gz", hash = "sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b", size = 168294, upload-time = "2025-11-09T20:49:23.302Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/91/13cb9505f7be74a933f37da3af22e029f6ba64f5669416cb8b2774bc9682/jiter-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:e7acbaba9703d5de82a2c98ae6a0f59ab9770ab5af5fa35e43a303aee962cf65", size = 316652, upload-time = "2025-11-09T20:46:41.021Z" }, - { url = "https://files.pythonhosted.org/packages/4e/76/4e9185e5d9bb4e482cf6dec6410d5f78dfeb374cfcecbbe9888d07c52daa/jiter-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:364f1a7294c91281260364222f535bc427f56d4de1d8ffd718162d21fbbd602e", size = 319829, upload-time = "2025-11-09T20:46:43.281Z" }, - { url = "https://files.pythonhosted.org/packages/86/af/727de50995d3a153138139f259baae2379d8cb0522c0c00419957bc478a6/jiter-0.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85ee4d25805d4fb23f0a5167a962ef8e002dbfb29c0989378488e32cf2744b62", size = 350568, upload-time = "2025-11-09T20:46:45.075Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c1/d6e9f4b7a3d5ac63bcbdfddeb50b2dcfbdc512c86cffc008584fdc350233/jiter-0.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:796f466b7942107eb889c08433b6e31b9a7ed31daceaecf8af1be26fb26c0ca8", size = 369052, upload-time = "2025-11-09T20:46:46.818Z" }, - { url = "https://files.pythonhosted.org/packages/eb/be/00824cd530f30ed73fa8a4f9f3890a705519e31ccb9e929f1e22062e7c76/jiter-0.12.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35506cb71f47dba416694e67af996bbdefb8e3608f1f78799c2e1f9058b01ceb", size = 481585, upload-time = "2025-11-09T20:46:48.319Z" }, - { url = "https://files.pythonhosted.org/packages/74/b6/2ad7990dff9504d4b5052eef64aa9574bd03d722dc7edced97aad0d47be7/jiter-0.12.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:726c764a90c9218ec9e4f99a33d6bf5ec169163f2ca0fc21b654e88c2abc0abc", size = 380541, upload-time = "2025-11-09T20:46:49.643Z" }, - { url = "https://files.pythonhosted.org/packages/b5/c7/f3c26ecbc1adbf1db0d6bba99192143d8fe8504729d9594542ecc4445784/jiter-0.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa47810c5565274810b726b0dc86d18dce5fd17b190ebdc3890851d7b2a0e74", size = 364423, upload-time = "2025-11-09T20:46:51.731Z" }, - { url = "https://files.pythonhosted.org/packages/18/51/eac547bf3a2d7f7e556927278e14c56a0604b8cddae75815d5739f65f81d/jiter-0.12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8ec0259d3f26c62aed4d73b198c53e316ae11f0f69c8fbe6682c6dcfa0fcce2", size = 389958, upload-time = "2025-11-09T20:46:53.432Z" }, - { url = "https://files.pythonhosted.org/packages/2c/1f/9ca592e67175f2db156cff035e0d817d6004e293ee0c1d73692d38fcb596/jiter-0.12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:79307d74ea83465b0152fa23e5e297149506435535282f979f18b9033c0bb025", size = 522084, upload-time = "2025-11-09T20:46:54.848Z" }, - { url = "https://files.pythonhosted.org/packages/83/ff/597d9cdc3028f28224f53e1a9d063628e28b7a5601433e3196edda578cdd/jiter-0.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cf6e6dd18927121fec86739f1a8906944703941d000f0639f3eb6281cc601dca", size = 513054, upload-time = "2025-11-09T20:46:56.487Z" }, - { url = "https://files.pythonhosted.org/packages/24/6d/1970bce1351bd02e3afcc5f49e4f7ef3dabd7fb688f42be7e8091a5b809a/jiter-0.12.0-cp310-cp310-win32.whl", hash = "sha256:b6ae2aec8217327d872cbfb2c1694489057b9433afce447955763e6ab015b4c4", size = 206368, upload-time = "2025-11-09T20:46:58.638Z" }, - { url = "https://files.pythonhosted.org/packages/e3/6b/eb1eb505b2d86709b59ec06681a2b14a94d0941db091f044b9f0e16badc0/jiter-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:c7f49ce90a71e44f7e1aa9e7ec415b9686bbc6a5961e57eab511015e6759bc11", size = 204847, upload-time = "2025-11-09T20:47:00.295Z" }, - { url = "https://files.pythonhosted.org/packages/32/f9/eaca4633486b527ebe7e681c431f529b63fe2709e7c5242fc0f43f77ce63/jiter-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8f8a7e317190b2c2d60eb2e8aa835270b008139562d70fe732e1c0020ec53c9", size = 316435, upload-time = "2025-11-09T20:47:02.087Z" }, - { url = "https://files.pythonhosted.org/packages/10/c1/40c9f7c22f5e6ff715f28113ebaba27ab85f9af2660ad6e1dd6425d14c19/jiter-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2218228a077e784c6c8f1a8e5d6b8cb1dea62ce25811c356364848554b2056cd", size = 320548, upload-time = "2025-11-09T20:47:03.409Z" }, - { url = "https://files.pythonhosted.org/packages/6b/1b/efbb68fe87e7711b00d2cfd1f26bb4bfc25a10539aefeaa7727329ffb9cb/jiter-0.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9354ccaa2982bf2188fd5f57f79f800ef622ec67beb8329903abf6b10da7d423", size = 351915, upload-time = "2025-11-09T20:47:05.171Z" }, - { url = "https://files.pythonhosted.org/packages/15/2d/c06e659888c128ad1e838123d0638f0efad90cc30860cb5f74dd3f2fc0b3/jiter-0.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2607185ea89b4af9a604d4c7ec40e45d3ad03ee66998b031134bc510232bb7", size = 368966, upload-time = "2025-11-09T20:47:06.508Z" }, - { url = "https://files.pythonhosted.org/packages/6b/20/058db4ae5fb07cf6a4ab2e9b9294416f606d8e467fb74c2184b2a1eeacba/jiter-0.12.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a585a5e42d25f2e71db5f10b171f5e5ea641d3aa44f7df745aa965606111cc2", size = 482047, upload-time = "2025-11-09T20:47:08.382Z" }, - { url = "https://files.pythonhosted.org/packages/49/bb/dc2b1c122275e1de2eb12905015d61e8316b2f888bdaac34221c301495d6/jiter-0.12.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd9e21d34edff5a663c631f850edcb786719c960ce887a5661e9c828a53a95d9", size = 380835, upload-time = "2025-11-09T20:47:09.81Z" }, - { url = "https://files.pythonhosted.org/packages/23/7d/38f9cd337575349de16da575ee57ddb2d5a64d425c9367f5ef9e4612e32e/jiter-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a612534770470686cd5431478dc5a1b660eceb410abade6b1b74e320ca98de6", size = 364587, upload-time = "2025-11-09T20:47:11.529Z" }, - { url = "https://files.pythonhosted.org/packages/f0/a3/b13e8e61e70f0bb06085099c4e2462647f53cc2ca97614f7fedcaa2bb9f3/jiter-0.12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3985aea37d40a908f887b34d05111e0aae822943796ebf8338877fee2ab67725", size = 390492, upload-time = "2025-11-09T20:47:12.993Z" }, - { url = "https://files.pythonhosted.org/packages/07/71/e0d11422ed027e21422f7bc1883c61deba2d9752b720538430c1deadfbca/jiter-0.12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b1207af186495f48f72529f8d86671903c8c10127cac6381b11dddc4aaa52df6", size = 522046, upload-time = "2025-11-09T20:47:14.6Z" }, - { url = "https://files.pythonhosted.org/packages/9f/59/b968a9aa7102a8375dbbdfbd2aeebe563c7e5dddf0f47c9ef1588a97e224/jiter-0.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef2fb241de583934c9915a33120ecc06d94aa3381a134570f59eed784e87001e", size = 513392, upload-time = "2025-11-09T20:47:16.011Z" }, - { url = "https://files.pythonhosted.org/packages/ca/e4/7df62002499080dbd61b505c5cb351aa09e9959d176cac2aa8da6f93b13b/jiter-0.12.0-cp311-cp311-win32.whl", hash = "sha256:453b6035672fecce8007465896a25b28a6b59cfe8fbc974b2563a92f5a92a67c", size = 206096, upload-time = "2025-11-09T20:47:17.344Z" }, - { url = "https://files.pythonhosted.org/packages/bb/60/1032b30ae0572196b0de0e87dce3b6c26a1eff71aad5fe43dee3082d32e0/jiter-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:ca264b9603973c2ad9435c71a8ec8b49f8f715ab5ba421c85a51cde9887e421f", size = 204899, upload-time = "2025-11-09T20:47:19.365Z" }, - { url = "https://files.pythonhosted.org/packages/49/d5/c145e526fccdb834063fb45c071df78b0cc426bbaf6de38b0781f45d956f/jiter-0.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:cb00ef392e7d684f2754598c02c409f376ddcef857aae796d559e6cacc2d78a5", size = 188070, upload-time = "2025-11-09T20:47:20.75Z" }, - { url = "https://files.pythonhosted.org/packages/92/c9/5b9f7b4983f1b542c64e84165075335e8a236fa9e2ea03a0c79780062be8/jiter-0.12.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:305e061fa82f4680607a775b2e8e0bcb071cd2205ac38e6ef48c8dd5ebe1cf37", size = 314449, upload-time = "2025-11-09T20:47:22.999Z" }, - { url = "https://files.pythonhosted.org/packages/98/6e/e8efa0e78de00db0aee82c0cf9e8b3f2027efd7f8a71f859d8f4be8e98ef/jiter-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c1860627048e302a528333c9307c818c547f214d8659b0705d2195e1a94b274", size = 319855, upload-time = "2025-11-09T20:47:24.779Z" }, - { url = "https://files.pythonhosted.org/packages/20/26/894cd88e60b5d58af53bec5c6759d1292bd0b37a8b5f60f07abf7a63ae5f/jiter-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df37577a4f8408f7e0ec3205d2a8f87672af8f17008358063a4d6425b6081ce3", size = 350171, upload-time = "2025-11-09T20:47:26.469Z" }, - { url = "https://files.pythonhosted.org/packages/f5/27/a7b818b9979ac31b3763d25f3653ec3a954044d5e9f5d87f2f247d679fd1/jiter-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fdd787356c1c13a4f40b43c2156276ef7a71eb487d98472476476d803fb2cf", size = 365590, upload-time = "2025-11-09T20:47:27.918Z" }, - { url = "https://files.pythonhosted.org/packages/ba/7e/e46195801a97673a83746170b17984aa8ac4a455746354516d02ca5541b4/jiter-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1eb5db8d9c65b112aacf14fcd0faae9913d07a8afea5ed06ccdd12b724e966a1", size = 479462, upload-time = "2025-11-09T20:47:29.654Z" }, - { url = "https://files.pythonhosted.org/packages/ca/75/f833bfb009ab4bd11b1c9406d333e3b4357709ed0570bb48c7c06d78c7dd/jiter-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73c568cc27c473f82480abc15d1301adf333a7ea4f2e813d6a2c7d8b6ba8d0df", size = 378983, upload-time = "2025-11-09T20:47:31.026Z" }, - { url = "https://files.pythonhosted.org/packages/71/b3/7a69d77943cc837d30165643db753471aff5df39692d598da880a6e51c24/jiter-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4321e8a3d868919bcb1abb1db550d41f2b5b326f72df29e53b2df8b006eb9403", size = 361328, upload-time = "2025-11-09T20:47:33.286Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ac/a78f90caf48d65ba70d8c6efc6f23150bc39dc3389d65bbec2a95c7bc628/jiter-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a51bad79f8cc9cac2b4b705039f814049142e0050f30d91695a2d9a6611f126", size = 386740, upload-time = "2025-11-09T20:47:34.703Z" }, - { url = "https://files.pythonhosted.org/packages/39/b6/5d31c2cc8e1b6a6bcf3c5721e4ca0a3633d1ab4754b09bc7084f6c4f5327/jiter-0.12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2a67b678f6a5f1dd6c36d642d7db83e456bc8b104788262aaefc11a22339f5a9", size = 520875, upload-time = "2025-11-09T20:47:36.058Z" }, - { url = "https://files.pythonhosted.org/packages/30/b5/4df540fae4e9f68c54b8dab004bd8c943a752f0b00efd6e7d64aa3850339/jiter-0.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efe1a211fe1fd14762adea941e3cfd6c611a136e28da6c39272dbb7a1bbe6a86", size = 511457, upload-time = "2025-11-09T20:47:37.932Z" }, - { url = "https://files.pythonhosted.org/packages/07/65/86b74010e450a1a77b2c1aabb91d4a91dd3cd5afce99f34d75fd1ac64b19/jiter-0.12.0-cp312-cp312-win32.whl", hash = "sha256:d779d97c834b4278276ec703dc3fc1735fca50af63eb7262f05bdb4e62203d44", size = 204546, upload-time = "2025-11-09T20:47:40.47Z" }, - { url = "https://files.pythonhosted.org/packages/1c/c7/6659f537f9562d963488e3e55573498a442503ced01f7e169e96a6110383/jiter-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e8269062060212b373316fe69236096aaf4c49022d267c6736eebd66bbbc60bb", size = 205196, upload-time = "2025-11-09T20:47:41.794Z" }, - { url = "https://files.pythonhosted.org/packages/21/f4/935304f5169edadfec7f9c01eacbce4c90bb9a82035ac1de1f3bd2d40be6/jiter-0.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:06cb970936c65de926d648af0ed3d21857f026b1cf5525cb2947aa5e01e05789", size = 186100, upload-time = "2025-11-09T20:47:43.007Z" }, - { url = "https://files.pythonhosted.org/packages/3d/a6/97209693b177716e22576ee1161674d1d58029eb178e01866a0422b69224/jiter-0.12.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e", size = 313658, upload-time = "2025-11-09T20:47:44.424Z" }, - { url = "https://files.pythonhosted.org/packages/06/4d/125c5c1537c7d8ee73ad3d530a442d6c619714b95027143f1b61c0b4dfe0/jiter-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1", size = 318605, upload-time = "2025-11-09T20:47:45.973Z" }, - { url = "https://files.pythonhosted.org/packages/99/bf/a840b89847885064c41a5f52de6e312e91fa84a520848ee56c97e4fa0205/jiter-0.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf", size = 349803, upload-time = "2025-11-09T20:47:47.535Z" }, - { url = "https://files.pythonhosted.org/packages/8a/88/e63441c28e0db50e305ae23e19c1d8fae012d78ed55365da392c1f34b09c/jiter-0.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44", size = 365120, upload-time = "2025-11-09T20:47:49.284Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7c/49b02714af4343970eb8aca63396bc1c82fa01197dbb1e9b0d274b550d4e/jiter-0.12.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45", size = 479918, upload-time = "2025-11-09T20:47:50.807Z" }, - { url = "https://files.pythonhosted.org/packages/69/ba/0a809817fdd5a1db80490b9150645f3aae16afad166960bcd562be194f3b/jiter-0.12.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87", size = 379008, upload-time = "2025-11-09T20:47:52.211Z" }, - { url = "https://files.pythonhosted.org/packages/5f/c3/c9fc0232e736c8877d9e6d83d6eeb0ba4e90c6c073835cc2e8f73fdeef51/jiter-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed", size = 361785, upload-time = "2025-11-09T20:47:53.512Z" }, - { url = "https://files.pythonhosted.org/packages/96/61/61f69b7e442e97ca6cd53086ddc1cf59fb830549bc72c0a293713a60c525/jiter-0.12.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9", size = 386108, upload-time = "2025-11-09T20:47:54.893Z" }, - { url = "https://files.pythonhosted.org/packages/e9/2e/76bb3332f28550c8f1eba3bf6e5efe211efda0ddbbaf24976bc7078d42a5/jiter-0.12.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626", size = 519937, upload-time = "2025-11-09T20:47:56.253Z" }, - { url = "https://files.pythonhosted.org/packages/84/d6/fa96efa87dc8bff2094fb947f51f66368fa56d8d4fc9e77b25d7fbb23375/jiter-0.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c", size = 510853, upload-time = "2025-11-09T20:47:58.32Z" }, - { url = "https://files.pythonhosted.org/packages/8a/28/93f67fdb4d5904a708119a6ab58a8f1ec226ff10a94a282e0215402a8462/jiter-0.12.0-cp313-cp313-win32.whl", hash = "sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de", size = 204699, upload-time = "2025-11-09T20:47:59.686Z" }, - { url = "https://files.pythonhosted.org/packages/c4/1f/30b0eb087045a0abe2a5c9c0c0c8da110875a1d3be83afd4a9a4e548be3c/jiter-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a", size = 204258, upload-time = "2025-11-09T20:48:01.01Z" }, - { url = "https://files.pythonhosted.org/packages/2c/f4/2b4daf99b96bce6fc47971890b14b2a36aef88d7beb9f057fafa032c6141/jiter-0.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60", size = 185503, upload-time = "2025-11-09T20:48:02.35Z" }, - { url = "https://files.pythonhosted.org/packages/39/ca/67bb15a7061d6fe20b9b2a2fd783e296a1e0f93468252c093481a2f00efa/jiter-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6", size = 317965, upload-time = "2025-11-09T20:48:03.783Z" }, - { url = "https://files.pythonhosted.org/packages/18/af/1788031cd22e29c3b14bc6ca80b16a39a0b10e611367ffd480c06a259831/jiter-0.12.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4", size = 345831, upload-time = "2025-11-09T20:48:05.55Z" }, - { url = "https://files.pythonhosted.org/packages/05/17/710bf8472d1dff0d3caf4ced6031060091c1320f84ee7d5dcbed1f352417/jiter-0.12.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb", size = 361272, upload-time = "2025-11-09T20:48:06.951Z" }, - { url = "https://files.pythonhosted.org/packages/fb/f1/1dcc4618b59761fef92d10bcbb0b038b5160be653b003651566a185f1a5c/jiter-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7", size = 204604, upload-time = "2025-11-09T20:48:08.328Z" }, - { url = "https://files.pythonhosted.org/packages/d9/32/63cb1d9f1c5c6632a783c0052cde9ef7ba82688f7065e2f0d5f10a7e3edb/jiter-0.12.0-cp313-cp313t-win_arm64.whl", hash = "sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3", size = 185628, upload-time = "2025-11-09T20:48:09.572Z" }, - { url = "https://files.pythonhosted.org/packages/a8/99/45c9f0dbe4a1416b2b9a8a6d1236459540f43d7fb8883cff769a8db0612d/jiter-0.12.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c46d927acd09c67a9fb1416df45c5a04c27e83aae969267e98fba35b74e99525", size = 312478, upload-time = "2025-11-09T20:48:10.898Z" }, - { url = "https://files.pythonhosted.org/packages/4c/a7/54ae75613ba9e0f55fcb0bc5d1f807823b5167cc944e9333ff322e9f07dd/jiter-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:774ff60b27a84a85b27b88cd5583899c59940bcc126caca97eb2a9df6aa00c49", size = 318706, upload-time = "2025-11-09T20:48:12.266Z" }, - { url = "https://files.pythonhosted.org/packages/59/31/2aa241ad2c10774baf6c37f8b8e1f39c07db358f1329f4eb40eba179c2a2/jiter-0.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5433fab222fb072237df3f637d01b81f040a07dcac1cb4a5c75c7aa9ed0bef1", size = 351894, upload-time = "2025-11-09T20:48:13.673Z" }, - { url = "https://files.pythonhosted.org/packages/54/4f/0f2759522719133a9042781b18cc94e335b6d290f5e2d3e6899d6af933e3/jiter-0.12.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8c593c6e71c07866ec6bfb790e202a833eeec885022296aff6b9e0b92d6a70e", size = 365714, upload-time = "2025-11-09T20:48:15.083Z" }, - { url = "https://files.pythonhosted.org/packages/dc/6f/806b895f476582c62a2f52c453151edd8a0fde5411b0497baaa41018e878/jiter-0.12.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90d32894d4c6877a87ae00c6b915b609406819dce8bc0d4e962e4de2784e567e", size = 478989, upload-time = "2025-11-09T20:48:16.706Z" }, - { url = "https://files.pythonhosted.org/packages/86/6c/012d894dc6e1033acd8db2b8346add33e413ec1c7c002598915278a37f79/jiter-0.12.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:798e46eed9eb10c3adbbacbd3bdb5ecd4cf7064e453d00dbef08802dae6937ff", size = 378615, upload-time = "2025-11-09T20:48:18.614Z" }, - { url = "https://files.pythonhosted.org/packages/87/30/d718d599f6700163e28e2c71c0bbaf6dace692e7df2592fd793ac9276717/jiter-0.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3f1368f0a6719ea80013a4eb90ba72e75d7ea67cfc7846db2ca504f3df0169a", size = 364745, upload-time = "2025-11-09T20:48:20.117Z" }, - { url = "https://files.pythonhosted.org/packages/8f/85/315b45ce4b6ddc7d7fceca24068543b02bdc8782942f4ee49d652e2cc89f/jiter-0.12.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65f04a9d0b4406f7e51279710b27484af411896246200e461d80d3ba0caa901a", size = 386502, upload-time = "2025-11-09T20:48:21.543Z" }, - { url = "https://files.pythonhosted.org/packages/74/0b/ce0434fb40c5b24b368fe81b17074d2840748b4952256bab451b72290a49/jiter-0.12.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:fd990541982a24281d12b67a335e44f117e4c6cbad3c3b75c7dea68bf4ce3a67", size = 519845, upload-time = "2025-11-09T20:48:22.964Z" }, - { url = "https://files.pythonhosted.org/packages/e8/a3/7a7a4488ba052767846b9c916d208b3ed114e3eb670ee984e4c565b9cf0d/jiter-0.12.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:b111b0e9152fa7df870ecaebb0bd30240d9f7fff1f2003bcb4ed0f519941820b", size = 510701, upload-time = "2025-11-09T20:48:24.483Z" }, - { url = "https://files.pythonhosted.org/packages/c3/16/052ffbf9d0467b70af24e30f91e0579e13ded0c17bb4a8eb2aed3cb60131/jiter-0.12.0-cp314-cp314-win32.whl", hash = "sha256:a78befb9cc0a45b5a5a0d537b06f8544c2ebb60d19d02c41ff15da28a9e22d42", size = 205029, upload-time = "2025-11-09T20:48:25.749Z" }, - { url = "https://files.pythonhosted.org/packages/e4/18/3cf1f3f0ccc789f76b9a754bdb7a6977e5d1d671ee97a9e14f7eb728d80e/jiter-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:e1fe01c082f6aafbe5c8faf0ff074f38dfb911d53f07ec333ca03f8f6226debf", size = 204960, upload-time = "2025-11-09T20:48:27.415Z" }, - { url = "https://files.pythonhosted.org/packages/02/68/736821e52ecfdeeb0f024b8ab01b5a229f6b9293bbdb444c27efade50b0f/jiter-0.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:d72f3b5a432a4c546ea4bedc84cce0c3404874f1d1676260b9c7f048a9855451", size = 185529, upload-time = "2025-11-09T20:48:29.125Z" }, - { url = "https://files.pythonhosted.org/packages/30/61/12ed8ee7a643cce29ac97c2281f9ce3956eb76b037e88d290f4ed0d41480/jiter-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e6ded41aeba3603f9728ed2b6196e4df875348ab97b28fc8afff115ed42ba7a7", size = 318974, upload-time = "2025-11-09T20:48:30.87Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c6/f3041ede6d0ed5e0e79ff0de4c8f14f401bbf196f2ef3971cdbe5fd08d1d/jiter-0.12.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a947920902420a6ada6ad51892082521978e9dd44a802663b001436e4b771684", size = 345932, upload-time = "2025-11-09T20:48:32.658Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5d/4d94835889edd01ad0e2dbfc05f7bdfaed46292e7b504a6ac7839aa00edb/jiter-0.12.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:add5e227e0554d3a52cf390a7635edaffdf4f8fce4fdbcef3cc2055bb396a30c", size = 367243, upload-time = "2025-11-09T20:48:34.093Z" }, - { url = "https://files.pythonhosted.org/packages/fd/76/0051b0ac2816253a99d27baf3dda198663aff882fa6ea7deeb94046da24e/jiter-0.12.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f9b1cda8fcb736250d7e8711d4580ebf004a46771432be0ae4796944b5dfa5d", size = 479315, upload-time = "2025-11-09T20:48:35.507Z" }, - { url = "https://files.pythonhosted.org/packages/70/ae/83f793acd68e5cb24e483f44f482a1a15601848b9b6f199dacb970098f77/jiter-0.12.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deeb12a2223fe0135c7ff1356a143d57f95bbf1f4a66584f1fc74df21d86b993", size = 380714, upload-time = "2025-11-09T20:48:40.014Z" }, - { url = "https://files.pythonhosted.org/packages/b1/5e/4808a88338ad2c228b1126b93fcd8ba145e919e886fe910d578230dabe3b/jiter-0.12.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c596cc0f4cb574877550ce4ecd51f8037469146addd676d7c1a30ebe6391923f", size = 365168, upload-time = "2025-11-09T20:48:41.462Z" }, - { url = "https://files.pythonhosted.org/packages/0c/d4/04619a9e8095b42aef436b5aeb4c0282b4ff1b27d1db1508df9f5dc82750/jiter-0.12.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ab4c823b216a4aeab3fdbf579c5843165756bd9ad87cc6b1c65919c4715f783", size = 387893, upload-time = "2025-11-09T20:48:42.921Z" }, - { url = "https://files.pythonhosted.org/packages/17/ea/d3c7e62e4546fdc39197fa4a4315a563a89b95b6d54c0d25373842a59cbe/jiter-0.12.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e427eee51149edf962203ff8db75a7514ab89be5cb623fb9cea1f20b54f1107b", size = 520828, upload-time = "2025-11-09T20:48:44.278Z" }, - { url = "https://files.pythonhosted.org/packages/cc/0b/c6d3562a03fd767e31cb119d9041ea7958c3c80cb3d753eafb19b3b18349/jiter-0.12.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:edb868841f84c111255ba5e80339d386d937ec1fdce419518ce1bd9370fac5b6", size = 511009, upload-time = "2025-11-09T20:48:45.726Z" }, - { url = "https://files.pythonhosted.org/packages/aa/51/2cb4468b3448a8385ebcd15059d325c9ce67df4e2758d133ab9442b19834/jiter-0.12.0-cp314-cp314t-win32.whl", hash = "sha256:8bbcfe2791dfdb7c5e48baf646d37a6a3dcb5a97a032017741dea9f817dca183", size = 205110, upload-time = "2025-11-09T20:48:47.033Z" }, - { url = "https://files.pythonhosted.org/packages/b2/c5/ae5ec83dec9c2d1af805fd5fe8f74ebded9c8670c5210ec7820ce0dbeb1e/jiter-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2fa940963bf02e1d8226027ef461e36af472dea85d36054ff835aeed944dd873", size = 205223, upload-time = "2025-11-09T20:48:49.076Z" }, - { url = "https://files.pythonhosted.org/packages/97/9a/3c5391907277f0e55195550cf3fa8e293ae9ee0c00fb402fec1e38c0c82f/jiter-0.12.0-cp314-cp314t-win_arm64.whl", hash = "sha256:506c9708dd29b27288f9f8f1140c3cb0e3d8ddb045956d7757b1fa0e0f39a473", size = 185564, upload-time = "2025-11-09T20:48:50.376Z" }, - { url = "https://files.pythonhosted.org/packages/7d/da/3e1fbd1f03f89ff0b4469d481be0b5cf2880c8e7b56fd80303b3ab5ae52d/jiter-0.12.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c9d28b218d5f9e5f69a0787a196322a5056540cb378cac8ff542b4fa7219966c", size = 319378, upload-time = "2025-11-09T20:48:51.761Z" }, - { url = "https://files.pythonhosted.org/packages/c7/4e/e07d69285e9e19a153050a6d281d2f0968600753a8fed8a3a141d6ffc140/jiter-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0ee12028daf8cfcf880dd492349a122a64f42c059b6c62a2b0c96a83a8da820", size = 312195, upload-time = "2025-11-09T20:48:53.547Z" }, - { url = "https://files.pythonhosted.org/packages/2d/82/1f1cb5231b36af9f3d6d5b6030e70110faf14fd143419fc5fe7d852e691a/jiter-0.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b135ebe757a82d67ed2821526e72d0acf87dd61f6013e20d3c45b8048af927b", size = 352777, upload-time = "2025-11-09T20:48:55.058Z" }, - { url = "https://files.pythonhosted.org/packages/6a/5e/728393bbbc99b31e8f7a4fdd8fa55e455a0a9648f79097d9088baf1f676f/jiter-0.12.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15d7fafb81af8a9e3039fc305529a61cd933eecee33b4251878a1c89859552a3", size = 370738, upload-time = "2025-11-09T20:48:56.632Z" }, - { url = "https://files.pythonhosted.org/packages/30/08/ac92f0df7b14ac82f2fe0a382a8000e600ab90af95798d4a7db0c1bd0736/jiter-0.12.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92d1f41211d8a8fe412faad962d424d334764c01dac6691c44691c2e4d3eedaf", size = 483744, upload-time = "2025-11-09T20:48:58.006Z" }, - { url = "https://files.pythonhosted.org/packages/7e/f4/dbfa4e759a2b82e969a14c3d0a91b176f1ed94717183a2f495cf94a651b9/jiter-0.12.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a64a48d7c917b8f32f25c176df8749ecf08cec17c466114727efe7441e17f6d", size = 382888, upload-time = "2025-11-09T20:48:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/6c/d9/b86fff7f748b0bb54222a8f132ffaf4d1be56b4591fa76d3cfdd701a33e5/jiter-0.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:122046f3b3710b85de99d9aa2f3f0492a8233a2f54a64902b096efc27ea747b5", size = 366465, upload-time = "2025-11-09T20:49:01.408Z" }, - { url = "https://files.pythonhosted.org/packages/93/3c/1152d8b433317a568927e13c1b125c680e6c058ff5d304833be8469bd4f2/jiter-0.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:27ec39225e03c32c6b863ba879deb427882f243ae46f0d82d68b695fa5b48b40", size = 392603, upload-time = "2025-11-09T20:49:02.784Z" }, - { url = "https://files.pythonhosted.org/packages/6e/92/ff19d8fb87f3f9438eb7464862c8d0126455bc046b345d59b21443640c62/jiter-0.12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26b9e155ddc132225a39b1995b3b9f0fe0f79a6d5cbbeacf103271e7d309b404", size = 523780, upload-time = "2025-11-09T20:49:04.42Z" }, - { url = "https://files.pythonhosted.org/packages/87/3a/4260e2d84e4a293c36d2a8e8b8dcd69609c671f3bd310e4625359217c517/jiter-0.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9ab05b7c58e29bb9e60b70c2e0094c98df79a1e42e397b9bb6eaa989b7a66dd0", size = 514874, upload-time = "2025-11-09T20:49:05.844Z" }, - { url = "https://files.pythonhosted.org/packages/2e/f7/574d2cb79e86feb035ade18c2254da71d04417555907c9df51dd6b183426/jiter-0.12.0-cp39-cp39-win32.whl", hash = "sha256:59f9f9df87ed499136db1c2b6c9efb902f964bed42a582ab7af413b6a293e7b0", size = 208329, upload-time = "2025-11-09T20:49:07.444Z" }, - { url = "https://files.pythonhosted.org/packages/05/ce/50725ec39782d8c973f19ae2d7dd3d192d01332c7cbde48c75e16a3e85a9/jiter-0.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3719596a1ebe7a48a498e8d5d0c4bf7553321d4c3eee1d620628d51351a3928", size = 206557, upload-time = "2025-11-09T20:49:08.888Z" }, - { url = "https://files.pythonhosted.org/packages/fe/54/5339ef1ecaa881c6948669956567a64d2670941925f245c434f494ffb0e5/jiter-0.12.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:4739a4657179ebf08f85914ce50332495811004cc1747852e8b2041ed2aab9b8", size = 311144, upload-time = "2025-11-09T20:49:10.503Z" }, - { url = "https://files.pythonhosted.org/packages/27/74/3446c652bffbd5e81ab354e388b1b5fc1d20daac34ee0ed11ff096b1b01a/jiter-0.12.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:41da8def934bf7bec16cb24bd33c0ca62126d2d45d81d17b864bd5ad721393c3", size = 305877, upload-time = "2025-11-09T20:49:12.269Z" }, - { url = "https://files.pythonhosted.org/packages/a1/f4/ed76ef9043450f57aac2d4fbeb27175aa0eb9c38f833be6ef6379b3b9a86/jiter-0.12.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c44ee814f499c082e69872d426b624987dbc5943ab06e9bbaa4f81989fdb79e", size = 340419, upload-time = "2025-11-09T20:49:13.803Z" }, - { url = "https://files.pythonhosted.org/packages/21/01/857d4608f5edb0664aa791a3d45702e1a5bcfff9934da74035e7b9803846/jiter-0.12.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd2097de91cf03eaa27b3cbdb969addf83f0179c6afc41bbc4513705e013c65d", size = 347212, upload-time = "2025-11-09T20:49:15.643Z" }, - { url = "https://files.pythonhosted.org/packages/cb/f5/12efb8ada5f5c9edc1d4555fe383c1fb2eac05ac5859258a72d61981d999/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e8547883d7b96ef2e5fe22b88f8a4c8725a56e7f4abafff20fd5272d634c7ecb", size = 309974, upload-time = "2025-11-09T20:49:17.187Z" }, - { url = "https://files.pythonhosted.org/packages/85/15/d6eb3b770f6a0d332675141ab3962fd4a7c270ede3515d9f3583e1d28276/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:89163163c0934854a668ed783a2546a0617f71706a2551a4a0666d91ab365d6b", size = 304233, upload-time = "2025-11-09T20:49:18.734Z" }, - { url = "https://files.pythonhosted.org/packages/8c/3e/e7e06743294eea2cf02ced6aa0ff2ad237367394e37a0e2b4a1108c67a36/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d96b264ab7d34bbb2312dedc47ce07cd53f06835eacbc16dde3761f47c3a9e7f", size = 338537, upload-time = "2025-11-09T20:49:20.317Z" }, - { url = "https://files.pythonhosted.org/packages/2f/9c/6753e6522b8d0ef07d3a3d239426669e984fb0eba15a315cdbc1253904e4/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c", size = 346110, upload-time = "2025-11-09T20:49:21.817Z" }, +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/5a/41da76c5ea07bec1b0472b6b2fdb1b651074d504b19374d7e130e0cdfb25/jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e", size = 311164, upload-time = "2026-02-02T12:35:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/40/cb/4a1bf994a3e869f0d39d10e11efb471b76d0ad70ecbfb591427a46c880c2/jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a", size = 320296, upload-time = "2026-02-02T12:35:19.828Z" }, + { url = "https://files.pythonhosted.org/packages/09/82/acd71ca9b50ecebadc3979c541cd717cce2fe2bc86236f4fa597565d8f1a/jiter-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19928b5d1ce0ff8c1ee1b9bdef3b5bfc19e8304f1b904e436caf30bc15dc6cf5", size = 352742, upload-time = "2026-02-02T12:35:21.258Z" }, + { url = "https://files.pythonhosted.org/packages/71/03/d1fc996f3aecfd42eb70922edecfb6dd26421c874503e241153ad41df94f/jiter-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:309549b778b949d731a2f0e1594a3f805716be704a73bf3ad9a807eed5eb5721", size = 363145, upload-time = "2026-02-02T12:35:24.653Z" }, + { url = "https://files.pythonhosted.org/packages/f1/61/a30492366378cc7a93088858f8991acd7d959759fe6138c12a4644e58e81/jiter-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcdabaea26cb04e25df3103ce47f97466627999260290349a88c8136ecae0060", size = 487683, upload-time = "2026-02-02T12:35:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/4223cffa9dbbbc96ed821c5aeb6bca510848c72c02086d1ed3f1da3d58a7/jiter-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a377af27b236abbf665a69b2bdd680e3b5a0bd2af825cd3b81245279a7606c", size = 373579, upload-time = "2026-02-02T12:35:27.582Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c9/b0489a01329ab07a83812d9ebcffe7820a38163c6d9e7da644f926ff877c/jiter-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe49d3ff6db74321f144dff9addd4a5874d3105ac5ba7c5b77fac099cfae31ae", size = 362904, upload-time = "2026-02-02T12:35:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/05/af/53e561352a44afcba9a9bc67ee1d320b05a370aed8df54eafe714c4e454d/jiter-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2113c17c9a67071b0f820733c0893ed1d467b5fcf4414068169e5c2cabddb1e2", size = 392380, upload-time = "2026-02-02T12:35:30.385Z" }, + { url = "https://files.pythonhosted.org/packages/76/2a/dd805c3afb8ed5b326c5ae49e725d1b1255b9754b1b77dbecdc621b20773/jiter-0.13.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ab1185ca5c8b9491b55ebf6c1e8866b8f68258612899693e24a92c5fdb9455d5", size = 517939, upload-time = "2026-02-02T12:35:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/7b67d76f55b8fe14c937e7640389612f05f9a4145fc28ae128aaa5e62257/jiter-0.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9621ca242547edc16400981ca3231e0c91c0c4c1ab8573a596cd9bb3575d5c2b", size = 551696, upload-time = "2026-02-02T12:35:33.306Z" }, + { url = "https://files.pythonhosted.org/packages/85/9c/57cdd64dac8f4c6ab8f994fe0eb04dc9fd1db102856a4458fcf8a99dfa62/jiter-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a7637d92b1c9d7a771e8c56f445c7f84396d48f2e756e5978840ecba2fac0894", size = 204592, upload-time = "2026-02-02T12:35:34.58Z" }, + { url = "https://files.pythonhosted.org/packages/a7/38/f4f3ea5788b8a5bae7510a678cdc747eda0c45ffe534f9878ff37e7cf3b3/jiter-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c1b609e5cbd2f52bb74fb721515745b407df26d7b800458bd97cb3b972c29e7d", size = 206016, upload-time = "2026-02-02T12:35:36.435Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, + { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, + { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, + { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, + { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, + { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, + { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, + { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, + { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, + { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" }, + { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" }, + { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" }, + { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" }, + { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" }, + { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" }, + { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" }, + { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" }, + { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" }, + { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" }, + { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, + { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, + { url = "https://files.pythonhosted.org/packages/41/95/8e6611379c9ce8534ff94dd800c50d6d0061b2c9ae6386fbcd86c7386f0a/jiter-0.13.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:4397ee562b9f69d283e5674445551b47a5e8076fdde75e71bfac5891113dc543", size = 313635, upload-time = "2026-02-02T12:37:23.545Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/17db64dcaf84bbb187874232222030ea4d689e6008f93bda6e7c691bc4c7/jiter-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f90023f8f672e13ea1819507d2d21b9d2d1c18920a3b3a5f1541955a85b5504", size = 309761, upload-time = "2026-02-02T12:37:25.075Z" }, + { url = "https://files.pythonhosted.org/packages/a3/36/b2e2a7b12b94ecc7248acf2a8fe6288be893d1ebb9728655ceada22f00ad/jiter-0.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed0240dd1536a98c3ab55e929c60dfff7c899fecafcb7d01161b21a99fc8c363", size = 355245, upload-time = "2026-02-02T12:37:26.646Z" }, + { url = "https://files.pythonhosted.org/packages/77/3f/5b159663c5be622daec20074c997bb66bc1fac63c167c02aef3df476fb32/jiter-0.13.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6207fc61c395b26fffdcf637a0b06b4326f35bfa93c6e92fe1a166a21aeb6731", size = 365842, upload-time = "2026-02-02T12:37:28.207Z" }, + { url = "https://files.pythonhosted.org/packages/98/30/76a68fa2c9c815c6b7802a92fc354080d66ffba9acc4690fd85622f77ad4/jiter-0.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00203f47c214156df427b5989de74cb340c65c8180d09be1bf9de81d0abad599", size = 489223, upload-time = "2026-02-02T12:37:29.571Z" }, + { url = "https://files.pythonhosted.org/packages/a3/39/7c5cb85ccd71241513c878054c26a55828ccded6567d931a23ea4be73787/jiter-0.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c26ad6967c9dcedf10c995a21539c3aa57d4abad7001b7a84f621a263a6b605", size = 375762, upload-time = "2026-02-02T12:37:31.186Z" }, + { url = "https://files.pythonhosted.org/packages/a8/6a/381cd18d050b0102e60324e8d3f51f37ef02c56e9f4e5f0b7d26ba18958d/jiter-0.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a576f5dce9ac7de5d350b8e2f552cf364f32975ed84717c35379a51c7cb198bd", size = 364996, upload-time = "2026-02-02T12:37:32.931Z" }, + { url = "https://files.pythonhosted.org/packages/37/1e/d66310f1f7085c13ea6f1119c9566ec5d2cfd1dc90df963118a6869247bb/jiter-0.13.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b22945be8425d161f2e536cdae66da300b6b000f1c0ba3ddf237d1bfd45d21b8", size = 395463, upload-time = "2026-02-02T12:37:34.446Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ab/06ae77cb293f860b152c356c635c15aaa800ce48772865a41704d9fac80d/jiter-0.13.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6eeb7db8bc77dc20476bc2f7407a23dbe3d46d9cc664b166e3d474e1c1de4baa", size = 520944, upload-time = "2026-02-02T12:37:35.987Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8e/57b49b20361c42a80d455a6d83cb38626204508cab4298d6a22880205319/jiter-0.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:19cd6f85e1dc090277c3ce90a5b7d96f32127681d825e71c9dce28788e39fc0c", size = 554955, upload-time = "2026-02-02T12:37:37.656Z" }, + { url = "https://files.pythonhosted.org/packages/79/dd/113489973c3b4256e383321aea11bd57389e401912fa48eb145a99b38767/jiter-0.13.0-cp39-cp39-win32.whl", hash = "sha256:dc3ce84cfd4fa9628fe62c4f85d0d597a4627d4242cfafac32a12cc1455d00f7", size = 206876, upload-time = "2026-02-02T12:37:39.225Z" }, + { url = "https://files.pythonhosted.org/packages/6e/73/2bdfc7133c5ee0c8f18cfe4a7582f3cfbbf3ff672cec1b5f4ca67ff9d041/jiter-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:9ffda299e417dc83362963966c50cb76d42da673ee140de8a8ac762d4bb2378b", size = 206404, upload-time = "2026-02-02T12:37:40.632Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, ] [[package]] name = "jmespath" -version = "1.0.1" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, ] [[package]] @@ -2362,11 +2365,11 @@ wheels = [ [[package]] name = "logfire-api" -version = "4.17.0" +version = "4.22.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/2a/76d8fbafa881cb03d5ad6e1d67d537e8c308ae7145812b8891f7b8751224/logfire_api-4.17.0.tar.gz", hash = "sha256:4647dad05146a68af441d59a7746a966df4c2581b316616f1210f8cf74931353", size = 58305, upload-time = "2026-01-07T10:52:17.768Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/c2/38871722347486f59f48dbe407541ff1e02398637b800778a2602f2353a7/logfire_api-4.22.0.tar.gz", hash = "sha256:b22a038e76c58cba1ab2ce7ce1a26aa5f3df8c63e84d6ad01fb22f75273ca830", size = 59723, upload-time = "2026-02-04T12:17:59.07Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/bc/3844e103dca998dcc195d6ef09e0f29d9000bac870117db1dd59a29bfeef/logfire_api-4.17.0-py3-none-any.whl", hash = "sha256:80a4b79cd9918934cdf2043d944cfb04182708178d846273484d47f3619a5a39", size = 96146, upload-time = "2026-01-07T10:52:15.088Z" }, + { url = "https://files.pythonhosted.org/packages/1e/93/4e8395f3e4b1951b1de8d06cb7d7ef1105efd294ea3443bf39b3594390af/logfire_api-4.22.0-py3-none-any.whl", hash = "sha256:9fd2a2dac9cc3adf71ad4dac7bc9d26af326a5aa87445be90026048d22b92a8e", size = 98543, upload-time = "2026-02-04T12:17:56.365Z" }, ] [[package]] @@ -2386,15 +2389,15 @@ wheels = [ [[package]] name = "markdown" -version = "3.10" +version = "3.10.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/7dd27d9d863b3376fcf23a5a13cb5d024aed1db46f963f1b5735ae43b3be/markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e", size = 364931, upload-time = "2025-11-03T19:51:15.007Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/b1/af95bcae8549f1f3fd70faacb29075826a0d689a27f232e8cee315efa053/markdown-3.10.1.tar.gz", hash = "sha256:1c19c10bd5c14ac948c53d0d762a04e2fa35a6d58a6b7b1e6bfcbe6fefc0001a", size = 365402, upload-time = "2026-01-21T18:09:28.206Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c", size = 107678, upload-time = "2025-11-03T19:51:13.887Z" }, + { url = "https://files.pythonhosted.org/packages/59/1b/6ef961f543593969d25b2afe57a3564200280528caa9bd1082eecdd7b3bc/markdown-3.10.1-py3-none-any.whl", hash = "sha256:867d788939fe33e4b736426f5b9f651ad0c0ae0ecf89df0ca5d1176c70812fe3", size = 107684, upload-time = "2026-01-21T18:09:27.203Z" }, ] [[package]] @@ -2403,7 +2406,7 @@ version = "0.0.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c5/47/ec9eae4a6d2f336d95681df43720e2b25b045dc3ed44ae6d30a5ce2f5dff/markdown_include_variants-0.0.8.tar.gz", hash = "sha256:46d812340c64dcd3646b1eaa356bafb31626dd7b4955d15c44ff8c48c6357227", size = 46882, upload-time = "2025-12-12T16:11:04.254Z" } wheels = [ @@ -2548,7 +2551,7 @@ dependencies = [ { name = "jsonschema", marker = "python_full_version >= '3.10'" }, { name = "pydantic", marker = "python_full_version >= '3.10'" }, { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-multipart", version = "0.0.21", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pywin32", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, { name = "sse-starlette", marker = "python_full_version >= '3.10'" }, { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, @@ -2575,7 +2578,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cyclic" }, { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "rcslice" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bf/f0/f395a9cf164471d3c7bbe58cbd64d74289575a8b85a962b49a804ab7ed34/mdx_include-1.4.2.tar.gz", hash = "sha256:992f9fbc492b5cf43f7d8cb4b90b52a4e4c5fdd7fd04570290a83eea5c84f297", size = 15051, upload-time = "2022-07-26T05:46:14.129Z" } @@ -2622,7 +2625,7 @@ dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "markupsafe" }, { name = "mergedeep" }, { name = "mkdocs-get-deps" }, @@ -2643,7 +2646,7 @@ version = "1.4.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "markupsafe" }, { name = "mkdocs" }, ] @@ -2700,7 +2703,7 @@ dependencies = [ { name = "colorama" }, { name = "jinja2" }, { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "mkdocs" }, { name = "mkdocs-material-extensions" }, { name = "paginate" }, @@ -2742,7 +2745,7 @@ dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "markupsafe" }, { name = "mkdocs" }, { name = "mkdocs-autorefs" }, @@ -2851,7 +2854,7 @@ wheels = [ [[package]] name = "openai" -version = "2.14.0" +version = "2.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2863,9 +2866,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/b1/12fe1c196bea326261718eb037307c1c1fe1dedc2d2d4de777df822e6238/openai-2.14.0.tar.gz", hash = "sha256:419357bedde9402d23bf8f2ee372fca1985a73348debba94bddff06f19459952", size = 626938, upload-time = "2025-12-19T03:28:45.742Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/a2/677f22c4b487effb8a09439fb6134034b5f0a39ca27df8b95fac23a93720/openai-2.17.0.tar.gz", hash = "sha256:47224b74bd20f30c6b0a6a329505243cb2f26d5cf84d9f8d0825ff8b35e9c999", size = 631445, upload-time = "2026-02-05T16:27:40.953Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/4b/7c1a00c2c3fbd004253937f7520f692a9650767aa73894d7a34f0d65d3f4/openai-2.14.0-py3-none-any.whl", hash = "sha256:7ea40aca4ffc4c4a776e77679021b47eec1160e341f42ae086ba949c9dcc9183", size = 1067558, upload-time = "2025-12-19T03:28:43.727Z" }, + { url = "https://files.pythonhosted.org/packages/44/97/284535aa75e6e84ab388248b5a323fc296b1f70530130dee37f7f4fbe856/openai-2.17.0-py3-none-any.whl", hash = "sha256:4f393fd886ca35e113aac7ff239bcd578b81d8f104f5aedc7d3693eb2af1d338", size = 1069524, upload-time = "2026-02-05T16:27:38.941Z" }, ] [[package]] @@ -2885,6 +2888,9 @@ wheels = [ name = "orjson" version = "3.11.5" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] sdist = { url = "https://files.pythonhosted.org/packages/04/b8/333fdb27840f3bf04022d21b654a35f58e15407183aeb16f3b41aa053446/orjson-3.11.5.tar.gz", hash = "sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5", size = 5972347, upload-time = "2025-12-06T15:55:39.458Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/79/19/b22cf9dad4db20c8737041046054cbd4f38bb5a2d0e4bb60487832ce3d76/orjson-3.11.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:df9eadb2a6386d5ea2bfd81309c505e125cfc9ba2b1b99a97e60985b0b3665d1", size = 245719, upload-time = "2025-12-06T15:53:43.877Z" }, @@ -2975,6 +2981,91 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/e6/babf31154e047e465bc194eb72d1326d7c52ad4d7f50bf92b02b3cacda5c/orjson-3.11.5-cp39-cp39-win_amd64.whl", hash = "sha256:09b94b947ac08586af635ef922d69dc9bc63321527a3a04647f4986a73f4bd30", size = 133189, upload-time = "2025-12-06T15:55:38.143Z" }, ] +[[package]] +name = "orjson" +version = "3.11.7" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1a/a373746fa6d0e116dd9e54371a7b54622c44d12296d5d0f3ad5e3ff33490/orjson-3.11.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174", size = 229140, upload-time = "2026-02-02T15:37:06.082Z" }, + { url = "https://files.pythonhosted.org/packages/52/a2/fa129e749d500f9b183e8a3446a193818a25f60261e9ce143ad61e975208/orjson-3.11.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67", size = 128670, upload-time = "2026-02-02T15:37:08.002Z" }, + { url = "https://files.pythonhosted.org/packages/08/93/1e82011cd1e0bd051ef9d35bed1aa7fb4ea1f0a055dc2c841b46b43a9ebd/orjson-3.11.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11", size = 123832, upload-time = "2026-02-02T15:37:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d8/a26b431ef962c7d55736674dddade876822f3e33223c1f47a36879350d04/orjson-3.11.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc", size = 129171, upload-time = "2026-02-02T15:37:11.112Z" }, + { url = "https://files.pythonhosted.org/packages/a7/19/f47819b84a580f490da260c3ee9ade214cf4cf78ac9ce8c1c758f80fdfc9/orjson-3.11.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16", size = 141967, upload-time = "2026-02-02T15:37:12.282Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cd/37ece39a0777ba077fdcdbe4cccae3be8ed00290c14bf8afdc548befc260/orjson-3.11.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222", size = 130991, upload-time = "2026-02-02T15:37:13.465Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ed/f2b5d66aa9b6b5c02ff5f120efc7b38c7c4962b21e6be0f00fd99a5c348e/orjson-3.11.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa", size = 133674, upload-time = "2026-02-02T15:37:14.694Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6e/baa83e68d1aa09fa8c3e5b2c087d01d0a0bd45256de719ed7bc22c07052d/orjson-3.11.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e", size = 138722, upload-time = "2026-02-02T15:37:16.501Z" }, + { url = "https://files.pythonhosted.org/packages/0c/47/7f8ef4963b772cd56999b535e553f7eb5cd27e9dd6c049baee6f18bfa05d/orjson-3.11.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2", size = 409056, upload-time = "2026-02-02T15:37:17.895Z" }, + { url = "https://files.pythonhosted.org/packages/38/eb/2df104dd2244b3618f25325a656f85cc3277f74bbd91224752410a78f3c7/orjson-3.11.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c", size = 144196, upload-time = "2026-02-02T15:37:19.349Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2a/ee41de0aa3a6686598661eae2b4ebdff1340c65bfb17fcff8b87138aab21/orjson-3.11.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f", size = 134979, upload-time = "2026-02-02T15:37:20.906Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fa/92fc5d3d402b87a8b28277a9ed35386218a6a5287c7fe5ee9b9f02c53fb2/orjson-3.11.7-cp310-cp310-win32.whl", hash = "sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de", size = 127968, upload-time = "2026-02-02T15:37:23.178Z" }, + { url = "https://files.pythonhosted.org/packages/07/29/a576bf36d73d60df06904d3844a9df08e25d59eba64363aaf8ec2f9bff41/orjson-3.11.7-cp310-cp310-win_amd64.whl", hash = "sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993", size = 125128, upload-time = "2026-02-02T15:37:24.329Z" }, + { url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" }, + { url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" }, + { url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" }, + { url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" }, + { url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" }, + { url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" }, + { url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" }, + { url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" }, + { url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" }, + { url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" }, + { url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" }, + { url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" }, + { url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" }, + { url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" }, + { url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" }, + { url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" }, + { url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" }, + { url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" }, + { url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" }, + { url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" }, + { url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" }, + { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" }, + { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" }, + { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" }, + { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" }, + { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" }, + { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" }, + { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" }, + { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" }, + { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" }, + { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" }, + { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" }, + { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" }, + { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" }, + { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" }, + { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" }, + { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" }, + { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" }, +] + [[package]] name = "outcome" version = "1.3.0.post0" @@ -2989,11 +3080,11 @@ wheels = [ [[package]] name = "packaging" -version = "25.0" +version = "26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] [[package]] @@ -3007,11 +3098,11 @@ wheels = [ [[package]] name = "pathspec" -version = "1.0.2" +version = "1.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/b9/6eb731b52f132181a9144bbe77ff82117f6b2d2fbfba49aaab2c014c4760/pathspec-1.0.2.tar.gz", hash = "sha256:fa32b1eb775ed9ba8d599b22c5f906dc098113989da2c00bf8b210078ca7fb92", size = 130502, upload-time = "2026-01-08T04:33:27.613Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/6b/14fc9049d78435fd29e82846c777bd7ed9c470013dc8d0260fff3ff1c11e/pathspec-1.0.2-py3-none-any.whl", hash = "sha256:62f8558917908d237d399b9b338ef455a814801a4688bc41074b25feefd93472", size = 54844, upload-time = "2026-01-08T04:33:26.4Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] [[package]] @@ -3154,22 +3245,22 @@ wheels = [ [[package]] name = "playwright" -version = "1.57.0" +version = "1.58.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "greenlet", version = "3.2.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "greenlet", version = "3.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "greenlet", version = "3.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pyee" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/b6/e17543cea8290ae4dced10be21d5a43c360096aa2cce0aa7039e60c50df3/playwright-1.57.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:9351c1ac3dfd9b3820fe7fc4340d96c0d3736bb68097b9b7a69bd45d25e9370c", size = 41985039, upload-time = "2025-12-09T08:06:18.408Z" }, - { url = "https://files.pythonhosted.org/packages/8b/04/ef95b67e1ff59c080b2effd1a9a96984d6953f667c91dfe9d77c838fc956/playwright-1.57.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4a9d65027bce48eeba842408bcc1421502dfd7e41e28d207e94260fa93ca67e", size = 40775575, upload-time = "2025-12-09T08:06:22.105Z" }, - { url = "https://files.pythonhosted.org/packages/60/bd/5563850322a663956c927eefcf1457d12917e8f118c214410e815f2147d1/playwright-1.57.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:99104771abc4eafee48f47dac2369e0015516dc1ce8c409807d2dd440828b9a4", size = 41985042, upload-time = "2025-12-09T08:06:25.357Z" }, - { url = "https://files.pythonhosted.org/packages/56/61/3a803cb5ae0321715bfd5247ea871d25b32c8f372aeb70550a90c5f586df/playwright-1.57.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:284ed5a706b7c389a06caa431b2f0ba9ac4130113c3a779767dda758c2497bb1", size = 45975252, upload-time = "2025-12-09T08:06:29.186Z" }, - { url = "https://files.pythonhosted.org/packages/83/d7/b72eb59dfbea0013a7f9731878df8c670f5f35318cedb010c8a30292c118/playwright-1.57.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a1bae6c0a07839cdeaddbc0756b3b2b85e476c07945f64ece08f1f956a86f1", size = 45706917, upload-time = "2025-12-09T08:06:32.549Z" }, - { url = "https://files.pythonhosted.org/packages/e4/09/3fc9ebd7c95ee54ba6a68d5c0bc23e449f7235f4603fc60534a364934c16/playwright-1.57.0-py3-none-win32.whl", hash = "sha256:1dd93b265688da46e91ecb0606d36f777f8eadcf7fbef12f6426b20bf0c9137c", size = 36553860, upload-time = "2025-12-09T08:06:35.864Z" }, - { url = "https://files.pythonhosted.org/packages/58/d4/dcdfd2a33096aeda6ca0d15584800443dd2be64becca8f315634044b135b/playwright-1.57.0-py3-none-win_amd64.whl", hash = "sha256:6caefb08ed2c6f29d33b8088d05d09376946e49a73be19271c8cd5384b82b14c", size = 36553864, upload-time = "2025-12-09T08:06:38.915Z" }, - { url = "https://files.pythonhosted.org/packages/6a/60/fe31d7e6b8907789dcb0584f88be741ba388413e4fbce35f1eba4e3073de/playwright-1.57.0-py3-none-win_arm64.whl", hash = "sha256:5f065f5a133dbc15e6e7c71e7bc04f258195755b1c32a432b792e28338c8335e", size = 32837940, upload-time = "2025-12-09T08:06:42.268Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c9/9c6061d5703267f1baae6a4647bfd1862e386fbfdb97d889f6f6ae9e3f64/playwright-1.58.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:96e3204aac292ee639edbfdef6298b4be2ea0a55a16b7068df91adac077cc606", size = 42251098, upload-time = "2026-01-30T15:09:24.028Z" }, + { url = "https://files.pythonhosted.org/packages/e0/40/59d34a756e02f8c670f0fee987d46f7ee53d05447d43cd114ca015cb168c/playwright-1.58.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:70c763694739d28df71ed578b9c8202bb83e8fe8fb9268c04dd13afe36301f71", size = 41039625, upload-time = "2026-01-30T15:09:27.558Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ee/3ce6209c9c74a650aac9028c621f357a34ea5cd4d950700f8e2c4b7fe2c4/playwright-1.58.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:185e0132578733d02802dfddfbbc35f42be23a45ff49ccae5081f25952238117", size = 42251098, upload-time = "2026-01-30T15:09:30.461Z" }, + { url = "https://files.pythonhosted.org/packages/f1/af/009958cbf23fac551a940d34e3206e6c7eed2b8c940d0c3afd1feb0b0589/playwright-1.58.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:c95568ba1eda83812598c1dc9be60b4406dffd60b149bc1536180ad108723d6b", size = 46235268, upload-time = "2026-01-30T15:09:33.787Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a6/0e66ad04b6d3440dae73efb39540c5685c5fc95b17c8b29340b62abbd952/playwright-1.58.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f9999948f1ab541d98812de25e3a8c410776aa516d948807140aff797b4bffa", size = 45964214, upload-time = "2026-01-30T15:09:36.751Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4b/236e60ab9f6d62ed0fd32150d61f1f494cefbf02304c0061e78ed80c1c32/playwright-1.58.0-py3-none-win32.whl", hash = "sha256:1e03be090e75a0fabbdaeab65ce17c308c425d879fa48bb1d7986f96bfad0b99", size = 36815998, upload-time = "2026-01-30T15:09:39.627Z" }, + { url = "https://files.pythonhosted.org/packages/41/f8/5ec599c5e59d2f2f336a05b4f318e733077cd5044f24adb6f86900c3e6a7/playwright-1.58.0-py3-none-win_amd64.whl", hash = "sha256:a2bf639d0ce33b3ba38de777e08697b0d8f3dc07ab6802e4ac53fb65e3907af8", size = 36816005, upload-time = "2026-01-30T15:09:42.449Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c4/cc0229fea55c87d6c9c67fe44a21e2cd28d1d558a5478ed4d617e9fb0c93/playwright-1.58.0-py3-none-win_arm64.whl", hash = "sha256:32ffe5c303901a13a0ecab91d1c3f74baf73b84f4bedbb6b935f5bc11cc98e1b", size = 33085919, upload-time = "2026-01-30T15:09:45.71Z" }, ] [[package]] @@ -3279,11 +3370,27 @@ wheels = [ name = "pycparser" version = "2.23" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, ] +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + [[package]] name = "pydantic" version = "2.12.5" @@ -3361,7 +3468,7 @@ evals = [ ] google = [ { name = "google-genai", version = "1.47.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "google-genai", version = "1.57.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "google-genai", version = "1.62.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] groq = [ { name = "groq" }, @@ -3379,7 +3486,8 @@ openai = [ { name = "openai" }, ] retries = [ - { name = "tenacity" }, + { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "tenacity", version = "9.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] vertexai = [ { name = "google-auth" }, @@ -3652,16 +3760,16 @@ crypto = [ [[package]] name = "pymdown-extensions" -version = "10.20" +version = "10.20.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/35/e3814a5b7df295df69d035cfb8aab78b2967cdf11fcfae7faed726b66664/pymdown_extensions-10.20.tar.gz", hash = "sha256:5c73566ab0cf38c6ba084cb7c5ea64a119ae0500cce754ccb682761dfea13a52", size = 852774, upload-time = "2025-12-31T19:59:42.211Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/6c/9e370934bfa30e889d12e61d0dae009991294f40055c238980066a7fbd83/pymdown_extensions-10.20.1.tar.gz", hash = "sha256:e7e39c865727338d434b55f1dd8da51febcffcaebd6e1a0b9c836243f660740a", size = 852860, upload-time = "2026-01-24T05:56:56.758Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ea/10/47caf89cbb52e5bb764696fd52a8c591a2f0e851a93270c05a17f36000b5/pymdown_extensions-10.20-py3-none-any.whl", hash = "sha256:ea9e62add865da80a271d00bfa1c0fa085b20d133fb3fc97afdc88e682f60b2f", size = 268733, upload-time = "2025-12-31T19:59:40.652Z" }, + { url = "https://files.pythonhosted.org/packages/40/6d/b6ee155462a0156b94312bdd82d2b92ea56e909740045a87ccb98bf52405/pymdown_extensions-10.20.1-py3-none-any.whl", hash = "sha256:24af7feacbca56504b313b7b418c4f5e1317bb5fea60f03d57be7fcc40912aa0", size = 268768, upload-time = "2026-01-24T05:56:54.537Z" }, ] [[package]] @@ -3782,15 +3890,15 @@ wheels = [ [[package]] name = "python-multipart" -version = "0.0.21" +version = "0.0.22" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version >= '3.10' and python_full_version < '3.14'", ] -sdist = { url = "https://files.pythonhosted.org/packages/78/96/804520d0850c7db98e5ccb70282e29208723f0964e88ffd9d0da2f52ea09/python_multipart-0.0.21.tar.gz", hash = "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92", size = 37196, upload-time = "2025-12-17T09:24:22.446Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/76/03af049af4dcee5d27442f71b6924f01f3efb5d2bd34f23fcd563f2cc5f5/python_multipart-0.0.21-py3-none-any.whl", hash = "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090", size = 24541, upload-time = "2025-12-17T09:24:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, ] [[package]] @@ -3956,21 +4064,21 @@ wheels = [ [[package]] name = "rich" -version = "14.2.0" +version = "14.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/99/a4cab2acbb884f80e558b0771e97e21e939c5dfb460f488d19df485e8298/rich-14.3.2.tar.gz", hash = "sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8", size = 230143, upload-time = "2026-02-01T16:20:47.908Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, + { url = "https://files.pythonhosted.org/packages/ef/45/615f5babd880b4bd7d405cc0dc348234c5ffb6ed1ea33e152ede08b2072d/rich-14.3.2-py3-none-any.whl", hash = "sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69", size = 309963, upload-time = "2026-02-01T16:20:46.078Z" }, ] [[package]] name = "rich-toolkit" -version = "0.17.1" +version = "0.18.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -3978,9 +4086,9 @@ dependencies = [ { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/97/09/3f9b8d9daaf235195c626f21e03604c05b987404ee3bcacee0c1f67f2a8e/rich_toolkit-0.17.1.tar.gz", hash = "sha256:5af54df8d1dd9c8530e462e1bdcaed625c9b49f5a55b035aa0ba1c17bdb87c9a", size = 187925, upload-time = "2025-12-17T10:49:22.583Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/f1/bcfbde3ca38db54b5dcf7ee3d0caf3ed9133a169aec5a58ad9ec50ba12e8/rich_toolkit-0.18.1.tar.gz", hash = "sha256:bf104f1945a7252debeda7d7138118eaf848fff5ea81d9eda556cbc5f911122c", size = 192514, upload-time = "2026-02-01T10:56:31.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/7b/15e55fa8a76d0d41bf34d965af78acdaf80a315907adb30de8b63c272694/rich_toolkit-0.17.1-py3-none-any.whl", hash = "sha256:96d24bb921ecd225ffce7c526a9149e74006410c05e6d405bd74ffd54d5631ed", size = 31412, upload-time = "2025-12-17T10:49:21.793Z" }, + { url = "https://files.pythonhosted.org/packages/da/43/6f9860c4bfb1f181c347941542a8955ce24b228f84550253765aa1854d53/rich_toolkit-0.18.1-py3-none-any.whl", hash = "sha256:04011a9751f4c2becdf44bd1aaff8562d4b00caf04f14e483a9873c15fbe3154", size = 32255, upload-time = "2026-02-01T10:56:33.071Z" }, ] [[package]] @@ -4304,16 +4412,16 @@ wheels = [ [[package]] name = "sentry-sdk" -version = "2.49.0" +version = "2.52.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/94/23ac26616a883f492428d9ee9ad6eee391612125326b784dbfc30e1e7bab/sentry_sdk-2.49.0.tar.gz", hash = "sha256:c1878599cde410d481c04ef50ee3aedd4f600e4d0d253f4763041e468b332c30", size = 387228, upload-time = "2026-01-08T09:56:25.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/59/eb/1b497650eb564701f9a7b8a95c51b2abe9347ed2c0b290ba78f027ebe4ea/sentry_sdk-2.52.0.tar.gz", hash = "sha256:fa0bec872cfec0302970b2996825723d67390cdd5f0229fb9efed93bd5384899", size = 410273, upload-time = "2026-02-04T15:03:54.706Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/43/1c586f9f413765201234541857cb82fda076f4b0f7bad4a0ec248da39cf3/sentry_sdk-2.49.0-py2.py3-none-any.whl", hash = "sha256:6ea78499133874445a20fe9c826c9e960070abeb7ae0cdf930314ab16bb97aa0", size = 415693, upload-time = "2026-01-08T09:56:21.872Z" }, + { url = "https://files.pythonhosted.org/packages/ca/63/2c6daf59d86b1c30600bff679d039f57fd1932af82c43c0bde1cbc55e8d4/sentry_sdk-2.52.0-py2.py3-none-any.whl", hash = "sha256:931c8f86169fc6f2752cb5c4e6480f0d516112e78750c312e081ababecbaf2ed", size = 435547, upload-time = "2026-02-04T15:03:51.567Z" }, ] [[package]] @@ -4376,59 +4484,66 @@ wheels = [ [[package]] name = "sqlalchemy" -version = "2.0.45" +version = "2.0.46" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "greenlet", version = "3.2.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.10' and platform_machine == 'AMD64') or (python_full_version < '3.10' and platform_machine == 'WIN32') or (python_full_version < '3.10' and platform_machine == 'aarch64') or (python_full_version < '3.10' and platform_machine == 'amd64') or (python_full_version < '3.10' and platform_machine == 'ppc64le') or (python_full_version < '3.10' and platform_machine == 'win32') or (python_full_version < '3.10' and platform_machine == 'x86_64')" }, - { name = "greenlet", version = "3.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and platform_machine == 'AMD64') or (python_full_version >= '3.10' and platform_machine == 'WIN32') or (python_full_version >= '3.10' and platform_machine == 'aarch64') or (python_full_version >= '3.10' and platform_machine == 'amd64') or (python_full_version >= '3.10' and platform_machine == 'ppc64le') or (python_full_version >= '3.10' and platform_machine == 'win32') or (python_full_version >= '3.10' and platform_machine == 'x86_64')" }, + { name = "greenlet", version = "3.3.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and platform_machine == 'AMD64') or (python_full_version >= '3.10' and platform_machine == 'WIN32') or (python_full_version >= '3.10' and platform_machine == 'aarch64') or (python_full_version >= '3.10' and platform_machine == 'amd64') or (python_full_version >= '3.10' and platform_machine == 'ppc64le') or (python_full_version >= '3.10' and platform_machine == 'win32') or (python_full_version >= '3.10' and platform_machine == 'x86_64')" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/f9/5e4491e5ccf42f5d9cfc663741d261b3e6e1683ae7812114e7636409fcc6/sqlalchemy-2.0.45.tar.gz", hash = "sha256:1632a4bda8d2d25703fdad6363058d882541bdaaee0e5e3ddfa0cd3229efce88", size = 9869912, upload-time = "2025-12-09T21:05:16.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/70/75b1387d72e2847220441166c5eb4e9846dd753895208c13e6d66523b2d9/sqlalchemy-2.0.45-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c64772786d9eee72d4d3784c28f0a636af5b0a29f3fe26ff11f55efe90c0bd85", size = 2154148, upload-time = "2025-12-10T20:03:21.023Z" }, - { url = "https://files.pythonhosted.org/packages/d8/a4/7805e02323c49cb9d1ae5cd4913b28c97103079765f520043f914fca4cb3/sqlalchemy-2.0.45-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7ae64ebf7657395824a19bca98ab10eb9a3ecb026bf09524014f1bb81cb598d4", size = 3233051, upload-time = "2025-12-09T22:06:04.768Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ec/32ae09139f61bef3de3142e85c47abdee8db9a55af2bb438da54a4549263/sqlalchemy-2.0.45-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f02325709d1b1a1489f23a39b318e175a171497374149eae74d612634b234c0", size = 3232781, upload-time = "2025-12-09T22:09:54.435Z" }, - { url = "https://files.pythonhosted.org/packages/ad/bd/bf7b869b6f5585eac34222e1cf4405f4ba8c3b85dd6b1af5d4ce8bca695f/sqlalchemy-2.0.45-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2c3684fca8a05f0ac1d9a21c1f4a266983a7ea9180efb80ffeb03861ecd01a0", size = 3182096, upload-time = "2025-12-09T22:06:06.169Z" }, - { url = "https://files.pythonhosted.org/packages/21/6a/c219720a241bb8f35c88815ccc27761f5af7fdef04b987b0e8a2c1a6dcaa/sqlalchemy-2.0.45-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040f6f0545b3b7da6b9317fc3e922c9a98fc7243b2a1b39f78390fc0942f7826", size = 3205109, upload-time = "2025-12-09T22:09:55.969Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c4/6ccf31b2bc925d5d95fab403ffd50d20d7c82b858cf1a4855664ca054dce/sqlalchemy-2.0.45-cp310-cp310-win32.whl", hash = "sha256:830d434d609fe7bfa47c425c445a8b37929f140a7a44cdaf77f6d34df3a7296a", size = 2114240, upload-time = "2025-12-09T21:29:54.007Z" }, - { url = "https://files.pythonhosted.org/packages/de/29/a27a31fca07316def418db6f7c70ab14010506616a2decef1906050a0587/sqlalchemy-2.0.45-cp310-cp310-win_amd64.whl", hash = "sha256:0209d9753671b0da74da2cfbb9ecf9c02f72a759e4b018b3ab35f244c91842c7", size = 2137615, upload-time = "2025-12-09T21:29:55.85Z" }, - { url = "https://files.pythonhosted.org/packages/a2/1c/769552a9d840065137272ebe86ffbb0bc92b0f1e0a68ee5266a225f8cd7b/sqlalchemy-2.0.45-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e90a344c644a4fa871eb01809c32096487928bd2038bf10f3e4515cb688cc56", size = 2153860, upload-time = "2025-12-10T20:03:23.843Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f8/9be54ff620e5b796ca7b44670ef58bc678095d51b0e89d6e3102ea468216/sqlalchemy-2.0.45-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8c8b41b97fba5f62349aa285654230296829672fc9939cd7f35aab246d1c08b", size = 3309379, upload-time = "2025-12-09T22:06:07.461Z" }, - { url = "https://files.pythonhosted.org/packages/f6/2b/60ce3ee7a5ae172bfcd419ce23259bb874d2cddd44f67c5df3760a1e22f9/sqlalchemy-2.0.45-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:12c694ed6468333a090d2f60950e4250b928f457e4962389553d6ba5fe9951ac", size = 3309948, upload-time = "2025-12-09T22:09:57.643Z" }, - { url = "https://files.pythonhosted.org/packages/a3/42/bac8d393f5db550e4e466d03d16daaafd2bad1f74e48c12673fb499a7fc1/sqlalchemy-2.0.45-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f7d27a1d977a1cfef38a0e2e1ca86f09c4212666ce34e6ae542f3ed0a33bc606", size = 3261239, upload-time = "2025-12-09T22:06:08.879Z" }, - { url = "https://files.pythonhosted.org/packages/6f/12/43dc70a0528c59842b04ea1c1ed176f072a9b383190eb015384dd102fb19/sqlalchemy-2.0.45-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d62e47f5d8a50099b17e2bfc1b0c7d7ecd8ba6b46b1507b58cc4f05eefc3bb1c", size = 3284065, upload-time = "2025-12-09T22:09:59.454Z" }, - { url = "https://files.pythonhosted.org/packages/cf/9c/563049cf761d9a2ec7bc489f7879e9d94e7b590496bea5bbee9ed7b4cc32/sqlalchemy-2.0.45-cp311-cp311-win32.whl", hash = "sha256:3c5f76216e7b85770d5bb5130ddd11ee89f4d52b11783674a662c7dd57018177", size = 2113480, upload-time = "2025-12-09T21:29:57.03Z" }, - { url = "https://files.pythonhosted.org/packages/bc/fa/09d0a11fe9f15c7fa5c7f0dd26be3d235b0c0cbf2f9544f43bc42efc8a24/sqlalchemy-2.0.45-cp311-cp311-win_amd64.whl", hash = "sha256:a15b98adb7f277316f2c276c090259129ee4afca783495e212048daf846654b2", size = 2138407, upload-time = "2025-12-09T21:29:58.556Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c7/1900b56ce19bff1c26f39a4ce427faec7716c81ac792bfac8b6a9f3dca93/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3ee2aac15169fb0d45822983631466d60b762085bc4535cd39e66bea362df5f", size = 3333760, upload-time = "2025-12-09T22:11:02.66Z" }, - { url = "https://files.pythonhosted.org/packages/0a/93/3be94d96bb442d0d9a60e55a6bb6e0958dd3457751c6f8502e56ef95fed0/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba547ac0b361ab4f1608afbc8432db669bd0819b3e12e29fb5fa9529a8bba81d", size = 3348268, upload-time = "2025-12-09T22:13:49.054Z" }, - { url = "https://files.pythonhosted.org/packages/48/4b/f88ded696e61513595e4a9778f9d3f2bf7332cce4eb0c7cedaabddd6687b/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215f0528b914e5c75ef2559f69dca86878a3beeb0c1be7279d77f18e8d180ed4", size = 3278144, upload-time = "2025-12-09T22:11:04.14Z" }, - { url = "https://files.pythonhosted.org/packages/ed/6a/310ecb5657221f3e1bd5288ed83aa554923fb5da48d760a9f7622afeb065/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:107029bf4f43d076d4011f1afb74f7c3e2ea029ec82eb23d8527d5e909e97aa6", size = 3313907, upload-time = "2025-12-09T22:13:50.598Z" }, - { url = "https://files.pythonhosted.org/packages/5c/39/69c0b4051079addd57c84a5bfb34920d87456dd4c90cf7ee0df6efafc8ff/sqlalchemy-2.0.45-cp312-cp312-win32.whl", hash = "sha256:0c9f6ada57b58420a2c0277ff853abe40b9e9449f8d7d231763c6bc30f5c4953", size = 2112182, upload-time = "2025-12-09T21:39:30.824Z" }, - { url = "https://files.pythonhosted.org/packages/f7/4e/510db49dd89fc3a6e994bee51848c94c48c4a00dc905e8d0133c251f41a7/sqlalchemy-2.0.45-cp312-cp312-win_amd64.whl", hash = "sha256:8defe5737c6d2179c7997242d6473587c3beb52e557f5ef0187277009f73e5e1", size = 2139200, upload-time = "2025-12-09T21:39:32.321Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf", size = 3277082, upload-time = "2025-12-09T22:11:06.167Z" }, - { url = "https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e", size = 3293131, upload-time = "2025-12-09T22:13:52.626Z" }, - { url = "https://files.pythonhosted.org/packages/da/4c/13dab31266fc9904f7609a5dc308a2432a066141d65b857760c3bef97e69/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:470daea2c1ce73910f08caf10575676a37159a6d16c4da33d0033546bddebc9b", size = 3225389, upload-time = "2025-12-09T22:11:08.093Z" }, - { url = "https://files.pythonhosted.org/packages/74/04/891b5c2e9f83589de202e7abaf24cd4e4fa59e1837d64d528829ad6cc107/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9c6378449e0940476577047150fd09e242529b761dc887c9808a9a937fe990c8", size = 3266054, upload-time = "2025-12-09T22:13:54.262Z" }, - { url = "https://files.pythonhosted.org/packages/f1/24/fc59e7f71b0948cdd4cff7a286210e86b0443ef1d18a23b0d83b87e4b1f7/sqlalchemy-2.0.45-cp313-cp313-win32.whl", hash = "sha256:4b6bec67ca45bc166c8729910bd2a87f1c0407ee955df110d78948f5b5827e8a", size = 2110299, upload-time = "2025-12-09T21:39:33.486Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c5/d17113020b2d43073412aeca09b60d2009442420372123b8d49cc253f8b8/sqlalchemy-2.0.45-cp313-cp313-win_amd64.whl", hash = "sha256:afbf47dc4de31fa38fd491f3705cac5307d21d4bb828a4f020ee59af412744ee", size = 2136264, upload-time = "2025-12-09T21:39:36.801Z" }, - { url = "https://files.pythonhosted.org/packages/3d/8d/bb40a5d10e7a5f2195f235c0b2f2c79b0bf6e8f00c0c223130a4fbd2db09/sqlalchemy-2.0.45-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83d7009f40ce619d483d26ac1b757dfe3167b39921379a8bd1b596cf02dab4a6", size = 3521998, upload-time = "2025-12-09T22:13:28.622Z" }, - { url = "https://files.pythonhosted.org/packages/75/a5/346128b0464886f036c039ea287b7332a410aa2d3fb0bb5d404cb8861635/sqlalchemy-2.0.45-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d8a2ca754e5415cde2b656c27900b19d50ba076aa05ce66e2207623d3fe41f5a", size = 3473434, upload-time = "2025-12-09T22:13:30.188Z" }, - { url = "https://files.pythonhosted.org/packages/cc/64/4e1913772646b060b025d3fc52ce91a58967fe58957df32b455de5a12b4f/sqlalchemy-2.0.45-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f46ec744e7f51275582e6a24326e10c49fbdd3fc99103e01376841213028774", size = 3272404, upload-time = "2025-12-09T22:11:09.662Z" }, - { url = "https://files.pythonhosted.org/packages/b3/27/caf606ee924282fe4747ee4fd454b335a72a6e018f97eab5ff7f28199e16/sqlalchemy-2.0.45-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:883c600c345123c033c2f6caca18def08f1f7f4c3ebeb591a63b6fceffc95cce", size = 3277057, upload-time = "2025-12-09T22:13:56.213Z" }, - { url = "https://files.pythonhosted.org/packages/85/d0/3d64218c9724e91f3d1574d12eb7ff8f19f937643815d8daf792046d88ab/sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2c0b74aa79e2deade948fe8593654c8ef4228c44ba862bb7c9585c8e0db90f33", size = 3222279, upload-time = "2025-12-09T22:11:11.1Z" }, - { url = "https://files.pythonhosted.org/packages/24/10/dd7688a81c5bc7690c2a3764d55a238c524cd1a5a19487928844cb247695/sqlalchemy-2.0.45-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a420169cef179d4c9064365f42d779f1e5895ad26ca0c8b4c0233920973db74", size = 3244508, upload-time = "2025-12-09T22:13:57.932Z" }, - { url = "https://files.pythonhosted.org/packages/aa/41/db75756ca49f777e029968d9c9fee338c7907c563267740c6d310a8e3f60/sqlalchemy-2.0.45-cp314-cp314-win32.whl", hash = "sha256:e50dcb81a5dfe4b7b4a4aa8f338116d127cb209559124f3694c70d6cd072b68f", size = 2113204, upload-time = "2025-12-09T21:39:38.365Z" }, - { url = "https://files.pythonhosted.org/packages/89/a2/0e1590e9adb292b1d576dbcf67ff7df8cf55e56e78d2c927686d01080f4b/sqlalchemy-2.0.45-cp314-cp314-win_amd64.whl", hash = "sha256:4748601c8ea959e37e03d13dcda4a44837afcd1b21338e637f7c935b8da06177", size = 2138785, upload-time = "2025-12-09T21:39:39.503Z" }, - { url = "https://files.pythonhosted.org/packages/42/39/f05f0ed54d451156bbed0e23eb0516bcad7cbb9f18b3bf219c786371b3f0/sqlalchemy-2.0.45-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd337d3526ec5298f67d6a30bbbe4ed7e5e68862f0bf6dd21d289f8d37b7d60b", size = 3522029, upload-time = "2025-12-09T22:13:32.09Z" }, - { url = "https://files.pythonhosted.org/packages/54/0f/d15398b98b65c2bce288d5ee3f7d0a81f77ab89d9456994d5c7cc8b2a9db/sqlalchemy-2.0.45-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9a62b446b7d86a3909abbcd1cd3cc550a832f99c2bc37c5b22e1925438b9367b", size = 3475142, upload-time = "2025-12-09T22:13:33.739Z" }, - { url = "https://files.pythonhosted.org/packages/53/01/a01b9829d146ba59972e6dfc88138142f5ffa4110e492c83326e7d765a17/sqlalchemy-2.0.45-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d29b2b99d527dbc66dd87c3c3248a5dd789d974a507f4653c969999fc7c1191b", size = 2157179, upload-time = "2025-12-10T20:05:13.998Z" }, - { url = "https://files.pythonhosted.org/packages/1f/78/ed43ed8ac27844f129adfc45a8735bab5dcad3e5211f4dc1bd7e676bc3ed/sqlalchemy-2.0.45-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:59a8b8bd9c6bedf81ad07c8bd5543eedca55fe9b8780b2b628d495ba55f8db1e", size = 3233038, upload-time = "2025-12-09T22:06:55.42Z" }, - { url = "https://files.pythonhosted.org/packages/24/1c/721ec797f21431c905ad98cbce66430d72a340935e3b7e3232cf05e015cc/sqlalchemy-2.0.45-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd93c6f5d65f254ceabe97548c709e073d6da9883343adaa51bf1a913ce93f8e", size = 3233117, upload-time = "2025-12-09T22:10:03.143Z" }, - { url = "https://files.pythonhosted.org/packages/52/33/dcfb8dffb2ccd7c6803d63454dc1917ef5ec5b5e281fecbbc0ed1de1f125/sqlalchemy-2.0.45-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d0beadc2535157070c9c17ecf25ecec31e13c229a8f69196d7590bde8082bf1", size = 3182306, upload-time = "2025-12-09T22:06:56.894Z" }, - { url = "https://files.pythonhosted.org/packages/53/76/7cf8ce9e6dcac1d37125425aadec406d8a839dffc1b8763f6e7a56b0bf33/sqlalchemy-2.0.45-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e057f928ffe9c9b246a55b469c133b98a426297e1772ad24ce9f0c47d123bd5b", size = 3205587, upload-time = "2025-12-09T22:10:04.812Z" }, - { url = "https://files.pythonhosted.org/packages/d2/ac/5cd0d14f7830981c06f468507237b0a8205691d626492b5551a67535eb30/sqlalchemy-2.0.45-cp39-cp39-win32.whl", hash = "sha256:c1c2091b1489435ff85728fafeb990f073e64f6f5e81d5cd53059773e8521eb6", size = 2115932, upload-time = "2025-12-09T22:09:17.012Z" }, - { url = "https://files.pythonhosted.org/packages/b9/eb/76f6db8828c6e0cfac89820a07a40a2bab25e82e69827177b942a9bff42a/sqlalchemy-2.0.45-cp39-cp39-win_amd64.whl", hash = "sha256:56ead1f8dfb91a54a28cd1d072c74b3d635bcffbd25e50786533b822d4f2cde2", size = 2139570, upload-time = "2025-12-09T22:09:18.545Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl", hash = "sha256:5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0", size = 1936672, upload-time = "2025-12-09T21:54:52.608Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/26/66ba59328dc25e523bfcb0f8db48bdebe2035e0159d600e1f01c0fc93967/sqlalchemy-2.0.46-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735", size = 2155051, upload-time = "2026-01-21T18:27:28.965Z" }, + { url = "https://files.pythonhosted.org/packages/21/cd/9336732941df972fbbfa394db9caa8bb0cf9fe03656ec728d12e9cbd6edc/sqlalchemy-2.0.46-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39", size = 3234666, upload-time = "2026-01-21T18:32:28.72Z" }, + { url = "https://files.pythonhosted.org/packages/38/62/865ae8b739930ec433cd4123760bee7f8dafdc10abefd725a025604fb0de/sqlalchemy-2.0.46-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f", size = 3232917, upload-time = "2026-01-21T18:44:54.064Z" }, + { url = "https://files.pythonhosted.org/packages/24/38/805904b911857f2b5e00fdea44e9570df62110f834378706939825579296/sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5", size = 3185790, upload-time = "2026-01-21T18:32:30.581Z" }, + { url = "https://files.pythonhosted.org/packages/69/4f/3260bb53aabd2d274856337456ea52f6a7eccf6cce208e558f870cec766b/sqlalchemy-2.0.46-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e", size = 3207206, upload-time = "2026-01-21T18:44:55.93Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b3/67c432d7f9d88bb1a61909b67e29f6354d59186c168fb5d381cf438d3b73/sqlalchemy-2.0.46-cp310-cp310-win32.whl", hash = "sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047", size = 2115296, upload-time = "2026-01-21T18:33:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/4a/8c/25fb284f570f9d48e6c240f0269a50cec9cf009a7e08be4c0aaaf0654972/sqlalchemy-2.0.46-cp310-cp310-win_amd64.whl", hash = "sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061", size = 2138540, upload-time = "2026-01-21T18:33:14.22Z" }, + { url = "https://files.pythonhosted.org/packages/69/ac/b42ad16800d0885105b59380ad69aad0cce5a65276e269ce2729a2343b6a/sqlalchemy-2.0.46-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684", size = 2154851, upload-time = "2026-01-21T18:27:30.54Z" }, + { url = "https://files.pythonhosted.org/packages/a0/60/d8710068cb79f64d002ebed62a7263c00c8fd95f4ebd4b5be8f7ca93f2bc/sqlalchemy-2.0.46-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62", size = 3311241, upload-time = "2026-01-21T18:32:33.45Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/20c71487c7219ab3aa7421c7c62d93824c97c1460f2e8bb72404b0192d13/sqlalchemy-2.0.46-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f", size = 3310741, upload-time = "2026-01-21T18:44:57.887Z" }, + { url = "https://files.pythonhosted.org/packages/65/80/d26d00b3b249ae000eee4db206fcfc564bf6ca5030e4747adf451f4b5108/sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01", size = 3263116, upload-time = "2026-01-21T18:32:35.044Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/74dda7506640923821340541e8e45bd3edd8df78664f1f2e0aae8077192b/sqlalchemy-2.0.46-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999", size = 3285327, upload-time = "2026-01-21T18:44:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/9f/25/6dcf8abafff1389a21c7185364de145107b7394ecdcb05233815b236330d/sqlalchemy-2.0.46-cp311-cp311-win32.whl", hash = "sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d", size = 2114564, upload-time = "2026-01-21T18:33:15.85Z" }, + { url = "https://files.pythonhosted.org/packages/93/5f/e081490f8523adc0088f777e4ebad3cac21e498ec8a3d4067074e21447a1/sqlalchemy-2.0.46-cp311-cp311-win_amd64.whl", hash = "sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597", size = 2139233, upload-time = "2026-01-21T18:33:17.528Z" }, + { url = "https://files.pythonhosted.org/packages/b6/35/d16bfa235c8b7caba3730bba43e20b1e376d2224f407c178fbf59559f23e/sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c", size = 2153405, upload-time = "2026-01-21T19:05:54.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/6c/3192e24486749862f495ddc6584ed730c0c994a67550ec395d872a2ad650/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9", size = 3334702, upload-time = "2026-01-21T18:46:45.384Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a2/b9f33c8d68a3747d972a0bb758c6b63691f8fb8a49014bc3379ba15d4274/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b", size = 3347664, upload-time = "2026-01-21T18:40:09.979Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d2/3e59e2a91eaec9db7e8dc6b37b91489b5caeb054f670f32c95bcba98940f/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53", size = 3277372, upload-time = "2026-01-21T18:46:47.168Z" }, + { url = "https://files.pythonhosted.org/packages/dd/dd/67bc2e368b524e2192c3927b423798deda72c003e73a1e94c21e74b20a85/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e", size = 3312425, upload-time = "2026-01-21T18:40:11.548Z" }, + { url = "https://files.pythonhosted.org/packages/43/82/0ecd68e172bfe62247e96cb47867c2d68752566811a4e8c9d8f6e7c38a65/sqlalchemy-2.0.46-cp312-cp312-win32.whl", hash = "sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb", size = 2113155, upload-time = "2026-01-21T18:42:49.748Z" }, + { url = "https://files.pythonhosted.org/packages/bc/2a/2821a45742073fc0331dc132552b30de68ba9563230853437cac54b2b53e/sqlalchemy-2.0.46-cp312-cp312-win_amd64.whl", hash = "sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff", size = 2140078, upload-time = "2026-01-21T18:42:51.197Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4b/fa7838fe20bb752810feed60e45625a9a8b0102c0c09971e2d1d95362992/sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00", size = 2150268, upload-time = "2026-01-21T19:05:56.621Z" }, + { url = "https://files.pythonhosted.org/packages/46/c1/b34dccd712e8ea846edf396e00973dda82d598cb93762e55e43e6835eba9/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2", size = 3276511, upload-time = "2026-01-21T18:46:49.022Z" }, + { url = "https://files.pythonhosted.org/packages/96/48/a04d9c94753e5d5d096c628c82a98c4793b9c08ca0e7155c3eb7d7db9f24/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee", size = 3292881, upload-time = "2026-01-21T18:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/be/f4/06eda6e91476f90a7d8058f74311cb65a2fb68d988171aced81707189131/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad", size = 3224559, upload-time = "2026-01-21T18:46:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a2/d2af04095412ca6345ac22b33b89fe8d6f32a481e613ffcb2377d931d8d0/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e", size = 3262728, upload-time = "2026-01-21T18:40:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/31/48/1980c7caa5978a3b8225b4d230e69a2a6538a3562b8b31cea679b6933c83/sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f", size = 2111295, upload-time = "2026-01-21T18:42:52.366Z" }, + { url = "https://files.pythonhosted.org/packages/2d/54/f8d65bbde3d877617c4720f3c9f60e99bb7266df0d5d78b6e25e7c149f35/sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef", size = 2137076, upload-time = "2026-01-21T18:42:53.924Z" }, + { url = "https://files.pythonhosted.org/packages/56/ba/9be4f97c7eb2b9d5544f2624adfc2853e796ed51d2bb8aec90bc94b7137e/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10", size = 3556533, upload-time = "2026-01-21T18:33:06.636Z" }, + { url = "https://files.pythonhosted.org/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764", size = 3523208, upload-time = "2026-01-21T18:45:08.436Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b", size = 3464292, upload-time = "2026-01-21T18:33:08.208Z" }, + { url = "https://files.pythonhosted.org/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447", size = 3473497, upload-time = "2026-01-21T18:45:10.552Z" }, + { url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" }, + { url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" }, + { url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" }, + { url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" }, + { url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" }, + { url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" }, + { url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" }, + { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" }, + { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" }, + { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/9a/06/a29b51a577cc5746712ed8a2870794659a6bf405264b32dd5ccc380844d1/sqlalchemy-2.0.46-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3", size = 2158097, upload-time = "2026-01-21T18:24:45.892Z" }, + { url = "https://files.pythonhosted.org/packages/be/55/44689ed21b5a82708502243310878cfc76e0f326ed16103f4336f605055b/sqlalchemy-2.0.46-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a", size = 3233722, upload-time = "2026-01-21T18:30:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/be/11/1d6024d9cdd2108d500b399bdc77a1738119789aa70c83d68e1012d32596/sqlalchemy-2.0.46-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce", size = 3233038, upload-time = "2026-01-21T18:32:26.945Z" }, + { url = "https://files.pythonhosted.org/packages/38/6d/f813e3204baea710f2d82a61821bdf7b39cebda6dbba7cdeb976b0552239/sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5", size = 3183163, upload-time = "2026-01-21T18:30:58.647Z" }, + { url = "https://files.pythonhosted.org/packages/8d/5d/32b70643ef73c1bb3723a98316b89182cad2b9a6744d5335f1d69fcdb3f2/sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc", size = 3205174, upload-time = "2026-01-21T18:32:28.684Z" }, + { url = "https://files.pythonhosted.org/packages/99/a9/b9f7bd299b7550925e1e7d71d634e1eee23c035abed7de125fda7c74b0c8/sqlalchemy-2.0.46-cp39-cp39-win32.whl", hash = "sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d", size = 2117095, upload-time = "2026-01-21T18:34:02.596Z" }, + { url = "https://files.pythonhosted.org/packages/04/0b/2e376b34a7c2f3d9d40811c3412fdc65cd35c6da2d660c283ad24bd9bab1/sqlalchemy-2.0.46-cp39-cp39-win_amd64.whl", hash = "sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be", size = 2140517, upload-time = "2026-01-21T18:34:03.958Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" }, ] [[package]] @@ -4446,15 +4561,15 @@ wheels = [ [[package]] name = "sse-starlette" -version = "3.1.2" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "python_full_version >= '3.10'" }, { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/34/f5df66cb383efdbf4f2db23cabb27f51b1dcb737efaf8a558f6f1d195134/sse_starlette-3.1.2.tar.gz", hash = "sha256:55eff034207a83a0eb86de9a68099bd0157838f0b8b999a1b742005c71e33618", size = 26303, upload-time = "2025-12-31T08:02:20.023Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/8d/00d280c03ffd39aaee0e86ec81e2d3b9253036a0f93f51d10503adef0e65/sse_starlette-3.2.0.tar.gz", hash = "sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422", size = 27253, upload-time = "2026-01-17T13:11:05.62Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/95/8c4b76eec9ae574474e5d2997557cebf764bcd3586458956c30631ae08f4/sse_starlette-3.1.2-py3-none-any.whl", hash = "sha256:cd800dd349f4521b317b9391d3796fa97b71748a4da9b9e00aafab32dda375c8", size = 12484, upload-time = "2025-12-31T08:02:18.894Z" }, + { url = "https://files.pythonhosted.org/packages/96/7f/832f015020844a8b8f7a9cbc103dd76ba8e3875004c41e08440ea3a2b41a/sse_starlette-3.2.0-py3-none-any.whl", hash = "sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf", size = 12763, upload-time = "2026-01-17T13:11:03.775Z" }, ] [[package]] @@ -4511,7 +4626,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.288.2" +version = "0.291.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", @@ -4524,9 +4639,9 @@ dependencies = [ { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d9/13/306dd2edb5f0c4aa51e2d071994a91ed1a0304e9feafa79ea0f04da51298/strawberry_graphql-0.288.2.tar.gz", hash = "sha256:853dbab407e3f5099f3a27dbf37786535894a0fbf150df5dde145fc290db607e", size = 215182, upload-time = "2026-01-01T20:01:19.277Z" } +sdist = { url = "https://files.pythonhosted.org/packages/61/18/5a07bc95bdf1cb73e93cd1f1d5b11750ded6f5e4d9407e7d500abc635b36/strawberry_graphql-0.291.1.tar.gz", hash = "sha256:13463d09e042857e4c12eee0eafc2bbdef963e4a30e20ed9a9c9fb0d487d4aac", size = 217765, upload-time = "2026-02-06T10:07:15.861Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/14/15abfa6d289048eeb1b1cca4a582db08a3c1f42784b485c21ef54617e2c7/strawberry_graphql-0.288.2-py3-none-any.whl", hash = "sha256:ad72d7904582db333158568751bb6186a872380a8cc6671159d011d279382542", size = 313137, upload-time = "2026-01-01T20:01:17.32Z" }, + { url = "https://files.pythonhosted.org/packages/0e/7b/47ec56118decc90b9ae85a98180dc326fdad2ee031cba0e05c6c62349b88/strawberry_graphql-0.291.1-py3-none-any.whl", hash = "sha256:09798d3172b42be4d5526771ec581e1b1f93c7020b82a8b07b4c507676f75aa0", size = 316439, upload-time = "2026-02-06T10:07:18.247Z" }, ] [[package]] @@ -4545,11 +4660,27 @@ wheels = [ name = "tenacity" version = "9.1.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] +[[package]] +name = "tenacity" +version = "9.1.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/4a/c3357c8742f361785e3702bb4c9c68c4cb37a80aa657640b820669be5af1/tenacity-9.1.3.tar.gz", hash = "sha256:a6724c947aa717087e2531f883bde5c9188f603f6669a9b8d54eb998e604c12a", size = 49002, upload-time = "2026-02-05T06:33:12.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/6b/cdc85edb15e384d8e934aad89638cc8646e118c80de94c60125d0fc0a185/tenacity-9.1.3-py3-none-any.whl", hash = "sha256:51171cfc6b8a7826551e2f029426b10a6af189c5ac6986adcd7eb36d42f17954", size = 28858, upload-time = "2026-02-05T06:33:11.219Z" }, +] + [[package]] name = "termcolor" version = "3.1.0" @@ -4651,63 +4782,68 @@ wheels = [ [[package]] name = "tomli" -version = "2.3.0" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, - { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, - { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, - { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, - { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, - { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, - { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, - { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, - { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, - { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, - { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, - { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, - { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, - { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, - { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, - { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, - { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, - { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, - { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, - { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, - { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, - { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, - { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, - { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, - { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, - { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, - { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, - { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, - { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, - { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, - { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, - { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, - { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, - { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, - { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, - { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, - { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, + { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, + { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, + { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, + { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, + { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, + { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, + { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, + { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, + { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, + { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, + { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, + { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, + { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, + { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, + { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, + { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, + { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, ] [[package]] name = "tqdm" -version = "4.67.1" +version = "4.67.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] [[package]] @@ -5243,11 +5379,11 @@ wheels = [ [[package]] name = "wcwidth" -version = "0.2.14" +version = "0.5.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/62/a7c072fbfefb2980a00f99ca994279cb9ecf310cb2e6b2a4d2a28fe192b3/wcwidth-0.5.3.tar.gz", hash = "sha256:53123b7af053c74e9fe2e92ac810301f6139e64379031f7124574212fb3b4091", size = 157587, upload-time = "2026-01-31T03:52:10.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/3c/c1/d73f12f8cdb1891334a2ccf7389eed244d3941e74d80dd220badb937f3fb/wcwidth-0.5.3-py3-none-any.whl", hash = "sha256:d584eff31cd4753e1e5ff6c12e1edfdb324c995713f75d26c29807bb84bf649e", size = 92981, upload-time = "2026-01-31T03:52:09.14Z" }, ] [[package]] From 8e50c55fd90c4433ddc9096ff439da9498a8314a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 13:45:47 +0000 Subject: [PATCH 144/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c1a563f18b..bd62fc063e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ๐Ÿ‘ท Run tests with lower bound uv sync, upgrade `fastapi[all]` minimum dependencies: `ujson >=5.8.0`, `orjson >=3.9.3`. PR [#14846](https://github.com/fastapi/fastapi/pull/14846) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.2 ### Features From f9f79926047d7f5d8e0127dd585e7683ee57e9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 07:18:30 -0800 Subject: [PATCH 145/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Re-implement=20`on?= =?UTF-8?q?=5Fevent`=20in=20FastAPI=20for=20compatibility=20with=20the=20n?= =?UTF-8?q?ext=20Starlette,=20while=20keeping=20backwards=20compatibility?= =?UTF-8?q?=20(#14851)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/routing.py | 157 +++++++++++++++++++++++++++++++++++- tests/test_router_events.py | 76 +++++++++++++++++ 2 files changed, 229 insertions(+), 4 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index 9ca2f46732..c95f624bdf 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1,22 +1,31 @@ +import contextlib import email.message import functools import inspect import json +import types from collections.abc import ( AsyncIterator, Awaitable, Collection, Coroutine, + Generator, Mapping, Sequence, ) -from contextlib import AsyncExitStack, asynccontextmanager +from contextlib import ( + AbstractAsyncContextManager, + AbstractContextManager, + AsyncExitStack, + asynccontextmanager, +) from enum import Enum, IntEnum from typing import ( Annotated, Any, Callable, Optional, + TypeVar, Union, ) @@ -143,6 +152,50 @@ def websocket_session( return app +_T = TypeVar("_T") + + +# Vendored from starlette.routing to avoid importing private symbols +class _AsyncLiftContextManager(AbstractAsyncContextManager[_T]): + """ + Wraps a synchronous context manager to make it async. + + This is vendored from Starlette to avoid importing private symbols. + """ + + def __init__(self, cm: AbstractContextManager[_T]) -> None: + self._cm = cm + + async def __aenter__(self) -> _T: + return self._cm.__enter__() + + async def __aexit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[types.TracebackType], + ) -> Optional[bool]: + return self._cm.__exit__(exc_type, exc_value, traceback) + + +# Vendored from starlette.routing to avoid importing private symbols +def _wrap_gen_lifespan_context( + lifespan_context: Callable[[Any], Generator[Any, Any, Any]], +) -> Callable[[Any], AbstractAsyncContextManager[Any]]: + """ + Wrap a generator-based lifespan context into an async context manager. + + This is vendored from Starlette to avoid importing private symbols. + """ + cmgr = contextlib.contextmanager(lifespan_context) + + @functools.wraps(cmgr) + def wrapper(app: Any) -> _AsyncLiftContextManager[Any]: + return _AsyncLiftContextManager(cmgr(app)) + + return wrapper + + def _merge_lifespan_context( original_context: Lifespan[Any], nested_context: Lifespan[Any] ) -> Lifespan[Any]: @@ -160,6 +213,30 @@ def _merge_lifespan_context( return merged_lifespan # type: ignore[return-value] +class _DefaultLifespan: + """ + Default lifespan context manager that runs on_startup and on_shutdown handlers. + + This is a copy of the Starlette _DefaultLifespan class that was removed + in Starlette. FastAPI keeps it to maintain backward compatibility with + on_startup and on_shutdown event handlers. + + Ref: https://github.com/Kludex/starlette/pull/3117 + """ + + def __init__(self, router: "APIRouter") -> None: + self._router = router + + async def __aenter__(self) -> None: + await self._router._startup() + + async def __aexit__(self, *exc_info: object) -> None: + await self._router._shutdown() + + def __call__(self: _T, app: object) -> _T: + return self + + # Cache for endpoint context to avoid re-extracting on every request _endpoint_context_cache: dict[int, EndpointContext] = {} @@ -903,13 +980,33 @@ class APIRouter(routing.Router): ), ] = Default(generate_unique_id), ) -> None: + # Handle on_startup/on_shutdown locally since Starlette removed support + # Ref: https://github.com/Kludex/starlette/pull/3117 + # TODO: deprecate this once the lifespan (or alternative) interface is improved + self.on_startup: list[Callable[[], Any]] = ( + [] if on_startup is None else list(on_startup) + ) + self.on_shutdown: list[Callable[[], Any]] = ( + [] if on_shutdown is None else list(on_shutdown) + ) + + # Determine the lifespan context to use + if lifespan is None: + # Use the default lifespan that runs on_startup/on_shutdown handlers + lifespan_context: Lifespan[Any] = _DefaultLifespan(self) + elif inspect.isasyncgenfunction(lifespan): + lifespan_context = asynccontextmanager(lifespan) + elif inspect.isgeneratorfunction(lifespan): + lifespan_context = _wrap_gen_lifespan_context(lifespan) + else: + lifespan_context = lifespan + self.lifespan_context = lifespan_context + super().__init__( routes=routes, redirect_slashes=redirect_slashes, default=default, - on_startup=on_startup, - on_shutdown=on_shutdown, - lifespan=lifespan, + lifespan=lifespan_context, ) if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" @@ -4473,6 +4570,58 @@ class APIRouter(routing.Router): generate_unique_id_function=generate_unique_id_function, ) + # TODO: remove this once the lifespan (or alternative) interface is improved + async def _startup(self) -> None: + """ + Run any `.on_startup` event handlers. + + This method is kept for backward compatibility after Starlette removed + support for on_startup/on_shutdown handlers. + + Ref: https://github.com/Kludex/starlette/pull/3117 + """ + for handler in self.on_startup: + if is_async_callable(handler): + await handler() + else: + handler() + + # TODO: remove this once the lifespan (or alternative) interface is improved + async def _shutdown(self) -> None: + """ + Run any `.on_shutdown` event handlers. + + This method is kept for backward compatibility after Starlette removed + support for on_startup/on_shutdown handlers. + + Ref: https://github.com/Kludex/starlette/pull/3117 + """ + for handler in self.on_shutdown: + if is_async_callable(handler): + await handler() + else: + handler() + + # TODO: remove this once the lifespan (or alternative) interface is improved + def add_event_handler( + self, + event_type: str, + func: Callable[[], Any], + ) -> None: + """ + Add an event handler function for startup or shutdown. + + This method is kept for backward compatibility after Starlette removed + support for on_startup/on_shutdown handlers. + + Ref: https://github.com/Kludex/starlette/pull/3117 + """ + assert event_type in ("startup", "shutdown") + if event_type == "startup": + self.on_startup.append(func) + else: + self.on_shutdown.append(func) + @deprecated( """ on_event is deprecated, use lifespan event handlers instead. diff --git a/tests/test_router_events.py b/tests/test_router_events.py index 9df299cdaa..65f2f521c1 100644 --- a/tests/test_router_events.py +++ b/tests/test_router_events.py @@ -241,3 +241,79 @@ def test_merged_mixed_state_lifespans() -> None: with TestClient(app) as client: assert client.app_state == {"router": True} + + +@pytest.mark.filterwarnings( + r"ignore:\s*on_event is deprecated, use lifespan event handlers instead.*:DeprecationWarning" +) +def test_router_async_shutdown_handler(state: State) -> None: + """Test that async on_shutdown event handlers are called correctly, for coverage.""" + app = FastAPI() + + @app.get("/") + def main() -> dict[str, str]: + return {"message": "Hello World"} + + @app.on_event("shutdown") + async def app_shutdown() -> None: + state.app_shutdown = True + + assert state.app_shutdown is False + with TestClient(app) as client: + assert state.app_shutdown is False + response = client.get("/") + assert response.status_code == 200, response.text + assert state.app_shutdown is True + + +def test_router_sync_generator_lifespan(state: State) -> None: + """Test that a sync generator lifespan works via _wrap_gen_lifespan_context.""" + from collections.abc import Generator + + def lifespan(app: FastAPI) -> Generator[None, None, None]: + state.app_startup = True + yield + state.app_shutdown = True + + app = FastAPI(lifespan=lifespan) # type: ignore[arg-type] + + @app.get("/") + def main() -> dict[str, str]: + return {"message": "Hello World"} + + assert state.app_startup is False + assert state.app_shutdown is False + with TestClient(app) as client: + assert state.app_startup is True + assert state.app_shutdown is False + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {"message": "Hello World"} + assert state.app_startup is True + assert state.app_shutdown is True + + +def test_router_async_generator_lifespan(state: State) -> None: + """Test that an async generator lifespan (not wrapped) works.""" + + async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: + state.app_startup = True + yield + state.app_shutdown = True + + app = FastAPI(lifespan=lifespan) # type: ignore[arg-type] + + @app.get("/") + def main() -> dict[str, str]: + return {"message": "Hello World"} + + assert state.app_startup is False + assert state.app_shutdown is False + with TestClient(app) as client: + assert state.app_startup is True + assert state.app_shutdown is False + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {"message": "Hello World"} + assert state.app_startup is True + assert state.app_shutdown is True From fe8c33ea64f797ae544e25e7ddb82c8342fd8880 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 15:18:55 +0000 Subject: [PATCH 146/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bd62fc063e..823465ddfe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* โ™ป๏ธ Re-implement `on_event` in FastAPI for compatibility with the next Starlette, while keeping backwards compatibility. PR [#14851](https://github.com/fastapi/fastapi/pull/14851) by [@tiangolo](https://github.com/tiangolo). + ### Internal * ๐Ÿ‘ท Run tests with lower bound uv sync, upgrade `fastapi[all]` minimum dependencies: `ujson >=5.8.0`, `orjson >=3.9.3`. PR [#14846](https://github.com/fastapi/fastapi/pull/14846) by [@tiangolo](https://github.com/tiangolo). From 08233d7ffca5b967489910f8bb57161c9b52090c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 07:28:59 -0800 Subject: [PATCH 147/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#14834)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .../ru/docs/advanced/advanced-dependencies.md | 2 +- docs/ru/docs/advanced/wsgi.md | 20 +++++++++++++++++-- docs/ru/docs/deployment/docker.md | 4 +--- docs/ru/docs/index.md | 18 ++++++----------- docs/ru/docs/tutorial/body-multiple-params.md | 8 ++++---- .../tutorial/path-operation-configuration.md | 6 +++--- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index cc6691b300..fb2643cd5c 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -48,7 +48,7 @@ checker(q="somequery") ``` -โ€ฆะธ ะฟะตั€ะตะดะฐัั‚ ะฒะพะทะฒั€ะฐั‰ั‘ะฝะฝะพะต ะทะฝะฐั‡ะตะฝะธะต ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะฝะฐัˆัƒ *ั„ัƒะฝะบั†ะธัŽ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ* ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `fixed_content_included`: +โ€ฆะธ ะฟะตั€ะตะดะฐัั‚ ะฒะพะทะฒั€ะฐั‰ั‘ะฝะฝะพะต ะทะฝะฐั‡ะตะฝะธะต ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `fixed_content_included` ะฝะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*: {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index 64d7c7a289..41d3a169c7 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -6,13 +6,29 @@ ## ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `WSGIMiddleware` { #using-wsgimiddleware } -ะัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ `WSGIMiddleware`. +/// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั + +ะ”ะปั ัั‚ะพะณะพ ั‚ั€ะตะฑัƒะตั‚ัั ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ `a2wsgi`, ะฝะฐะฟั€ะธะผะตั€ ั ะฟะพะผะพั‰ัŒัŽ `pip install a2wsgi`. + +/// + +ะัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ `WSGIMiddleware` ะธะท `a2wsgi`. ะ—ะฐั‚ะตะผ ะพะฑะตั€ะฝะธั‚ะต WSGIโ€‘ะฟั€ะธะปะพะถะตะฝะธะต (ะฝะฐะฟั€ะธะผะตั€, Flask) ะฒ middleware (ะŸั€ะพะผะตะถัƒั‚ะพั‡ะฝั‹ะน ัะปะพะน). ะŸะพัะปะต ัั‚ะพะณะพ ัะผะพะฝั‚ะธั€ัƒะนั‚ะต ะตะณะพ ะฝะฐ ะฟัƒั‚ัŒ. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต + +ะ ะฐะฝะตะต ั€ะตะบะพะผะตะฝะดะพะฒะฐะปะพััŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `WSGIMiddleware` ะธะท `fastapi.middleware.wsgi`, ะฝะพ ั‚ะตะฟะตั€ัŒ ะพะฝ ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน. + +ะ’ะผะตัั‚ะพ ะฝะตะณะพ ั€ะตะบะพะผะตะฝะดัƒะตั‚ัั ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐะบะตั‚ `a2wsgi`. ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะพัั‚ะฐั‘ั‚ัั ั‚ะฐะบะธะผ ะถะต. + +ะŸั€ะพัั‚ะพ ัƒะฑะตะดะธั‚ะตััŒ, ั‡ั‚ะพ ะฟะฐะบะตั‚ `a2wsgi` ัƒัั‚ะฐะฝะพะฒะปะตะฝ, ะธ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `WSGIMiddleware` ะธะท `a2wsgi`. + +/// ## ะŸั€ะพะฒะตั€ัŒั‚ะต { #check-it } diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 3937b01654..9e8562be70 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -145,8 +145,6 @@ Successfully installed fastapi pydantic * ะกะพะทะดะฐะนั‚ะต ั„ะฐะนะป `main.py` ัะพ ัะปะตะดัƒัŽั‰ะธะผ ัะพะดะตั€ะถะธะผั‹ะผ: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 02b1c9a286..b1a0c9a2e9 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -161,8 +161,6 @@ $ pip install "fastapi[standard]" ะกะพะทะดะฐะนั‚ะต ั„ะฐะนะป `main.py` ัะพ ัะปะตะดัƒัŽั‰ะธะผ ัะพะดะตั€ะถะธะผั‹ะผ: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -174,7 +172,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None): ะ•ัะปะธ ะฒะฐัˆ ะบะพะด ะธัะฟะพะปัŒะทัƒะตั‚ `async` / `await`, ะธัะฟะพะปัŒะทัƒะนั‚ะต `async def`: -```Python hl_lines="9 14" -from typing import Union - +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -197,7 +193,7 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -288,9 +284,7 @@ INFO: Application startup complete. ะžะฑัŠัะฒะธั‚ะต ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ, ะธัะฟะพะปัŒะทัƒั ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ั‚ะธะฟั‹ Python, ัะฟะฐัะธะฑะพ Pydantic. -```Python hl_lines="4 9-12 25-27" -from typing import Union - +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -300,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -309,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} diff --git a/docs/ru/docs/tutorial/body-multiple-params.md b/docs/ru/docs/tutorial/body-multiple-params.md index 9ae57a3113..9d94004947 100644 --- a/docs/ru/docs/tutorial/body-multiple-params.md +++ b/docs/ru/docs/tutorial/body-multiple-params.md @@ -101,13 +101,13 @@ ะŸะพัะบะพะปัŒะบัƒ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะพั‚ะดะตะปัŒะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ัƒัŽั‚ัั ะบะฐะบ query-ะฟะฐั€ะฐะผะตั‚ั€ั‹, ะฒะฐะผ ะฝะต ะฝัƒะถะฝะพ ัะฒะฝะพ ะดะพะฑะฐะฒะปัั‚ัŒ `Query`, ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ัะดะตะปะฐั‚ัŒ ั‚ะฐะบ: ```Python -q: Union[str, None] = None +q: str | None = None ``` -ะ˜ะปะธ ะฒ Python 3.10 ะธ ะฒั‹ัˆะต: +ะ˜ะปะธ ะฒ Python 3.9: ```Python -q: str | None = None +q: Union[str, None] = None ``` ะะฐะฟั€ะธะผะตั€: @@ -116,7 +116,7 @@ q: str | None = None /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั -`Body` ั‚ะฐะบะถะต ะธะผะตะตั‚ ะฒัะต ั‚ะต ะถะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฒะฐะปะธะดะฐั†ะธะธ ะธ ะผะตั‚ะฐะดะฐะฝะฝั‹ั…, ะบะฐะบ ัƒ `Query`,`Path` ะธ ะดั€ัƒะณะธั…, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ัƒะฒะธะดะธั‚ะต ะฟะพะทะถะต. +`Body` ั‚ะฐะบะถะต ะธะผะตะตั‚ ะฒัะต ั‚ะต ะถะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฒะฐะปะธะดะฐั†ะธะธ ะธ ะผะตั‚ะฐะดะฐะฝะฝั‹ั…, ะบะฐะบ ัƒ `Query`, `Path` ะธ ะดั€ัƒะณะธั…, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ัƒะฒะธะดะธั‚ะต ะฟะพะทะถะต. /// diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md index 96a54ffea0..112a1efca5 100644 --- a/docs/ru/docs/tutorial/path-operation-configuration.md +++ b/docs/ru/docs/tutorial/path-operation-configuration.md @@ -52,7 +52,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ `summary` ะธ `description`: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## ะžะฟะธัะฐะฝะธะต ะธะท ัั‚ั€ะพะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #description-from-docstring } @@ -70,7 +70,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ัƒะบะฐะทะฐั‚ัŒ ะพะฟะธัะฐะฝะธะต ะพั‚ะฒะตั‚ะฐ ั ะฟะพะผะพั‰ัŒัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `response_description`: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั @@ -78,7 +78,7 @@ /// -/// check +/// check | ะŸั€ะพะฒะตั€ะบะฐ OpenAPI ัƒะบะฐะทั‹ะฒะฐะตั‚, ั‡ั‚ะพ ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฝะตะพะฑั…ะพะดะธะผะพ ะพะฟะธัะฐะฝะธะต ะพั‚ะฒะตั‚ะฐ. From 01e85c03bd992ef933fb1203879cd5a234796f78 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 15:29:27 +0000 Subject: [PATCH 148/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 823465ddfe..bca40fa324 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * โ™ป๏ธ Re-implement `on_event` in FastAPI for compatibility with the next Starlette, while keeping backwards compatibility. PR [#14851](https://github.com/fastapi/fastapi/pull/14851) by [@tiangolo](https://github.com/tiangolo). +### Translations + +* ๐ŸŒ Update translations for ru (update-outdated). PR [#14834](https://github.com/fastapi/fastapi/pull/14834) by [@tiangolo](https://github.com/tiangolo). + ### Internal * ๐Ÿ‘ท Run tests with lower bound uv sync, upgrade `fastapi[all]` minimum dependencies: `ujson >=5.8.0`, `orjson >=3.9.3`. PR [#14846](https://github.com/fastapi/fastapi/pull/14846) by [@tiangolo](https://github.com/tiangolo). From 19f13ead4cf61376e5bc615ebc8253e2ee4104b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 07:30:48 -0800 Subject: [PATCH 149/367] =?UTF-8?q?=F0=9F=91=B7=20Run=20tests=20with=20Sta?= =?UTF-8?q?rlette=20from=20git=20(#14849)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 70710e3400..e314b6a041 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,6 +51,9 @@ jobs: python-version: [ "3.14" ] uv-resolution: - highest + starlette-src: + - starlette-pypi + - starlette-git include: - os: ubuntu-latest python-version: "3.9" @@ -78,11 +81,13 @@ jobs: python-version: "3.14" coverage: coverage uv-resolution: highest + starlette-src: starlette-git fail-fast: false runs-on: ${{ matrix.os }} env: UV_PYTHON: ${{ matrix.python-version }} UV_RESOLUTION: ${{ matrix.uv-resolution }} + STARLETTE_SRC: ${{ matrix.starlette-src }} steps: - name: Dump GitHub context env: @@ -102,10 +107,13 @@ jobs: uv.lock - name: Install Dependencies run: uv sync --no-dev --group tests --extra all + - name: Install Starlette from source + if: matrix.starlette-src == 'starlette-git' + run: uv pip install "git+https://github.com/Kludex/starlette@main" - run: mkdir coverage - name: Test if: matrix.codspeed != 'codspeed' - run: uv run bash scripts/test.sh + run: uv run --no-sync bash scripts/test.sh env: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} @@ -117,7 +125,7 @@ jobs: CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} with: mode: simulation - run: uv run coverage run -m pytest tests/ --codspeed + run: uv run --no-sync coverage run -m pytest tests/ --codspeed # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow - name: Store coverage files if: matrix.coverage == 'coverage' From 201feedd681a26e3ed82628f963ad3a9af72d612 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 15:31:16 +0000 Subject: [PATCH 150/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bca40fa324..2dc6c908d8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* ๐Ÿ‘ท Run tests with Starlette from git. PR [#14849](https://github.com/fastapi/fastapi/pull/14849) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Run tests with lower bound uv sync, upgrade `fastapi[all]` minimum dependencies: `ujson >=5.8.0`, `orjson >=3.9.3`. PR [#14846](https://github.com/fastapi/fastapi/pull/14846) by [@tiangolo](https://github.com/tiangolo). ## 0.128.2 From f6cc650a127070ff427ef4d7b4666d304b1cc27e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 08:37:37 -0800 Subject: [PATCH 151/367] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20Starlett?= =?UTF-8?q?e=20supported=20version=20range=20to=20`starlette>=3D0.40.0,<1.?= =?UTF-8?q?0.0`=20(#14853)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ae9ae891e8..519f45e315 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.51.0", + "starlette>=0.40.0,<1.0.0", "pydantic>=2.7.0", "typing-extensions>=4.8.0", "typing-inspection>=0.4.2", diff --git a/uv.lock b/uv.lock index 435dddec5f..88b9f28df7 100644 --- a/uv.lock +++ b/uv.lock @@ -1198,7 +1198,7 @@ requires-dist = [ { name = "python-multipart", marker = "extra == 'standard'", specifier = ">=0.0.18" }, { name = "python-multipart", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=0.0.18" }, { name = "pyyaml", marker = "extra == 'all'", specifier = ">=5.3.1" }, - { name = "starlette", specifier = ">=0.40.0,<0.51.0" }, + { name = "starlette", specifier = ">=0.40.0,<1.0.0" }, { name = "typing-extensions", specifier = ">=4.8.0" }, { name = "typing-inspection", specifier = ">=0.4.2" }, { name = "ujson", marker = "extra == 'all'", specifier = ">=5.8.0" }, From 661cdfb8a465ae8f629b2605fc4a9171f19200fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 16:38:15 +0000 Subject: [PATCH 152/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2dc6c908d8..c782655129 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * โ™ป๏ธ Re-implement `on_event` in FastAPI for compatibility with the next Starlette, while keeping backwards compatibility. PR [#14851](https://github.com/fastapi/fastapi/pull/14851) by [@tiangolo](https://github.com/tiangolo). +### Upgrades + +* โฌ†๏ธ Upgrade Starlette supported version range to `starlette>=0.40.0,<1.0.0`. PR [#14853](https://github.com/fastapi/fastapi/pull/14853) by [@tiangolo](https://github.com/tiangolo). + ### Translations * ๐ŸŒ Update translations for ru (update-outdated). PR [#14834](https://github.com/fastapi/fastapi/pull/14834) by [@tiangolo](https://github.com/tiangolo). From 36985f5f25a5a706e5c9bd4630a3c74f45f6bfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 17:44:11 +0100 Subject: [PATCH 153/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c782655129..a55a15abd7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.3 + ### Refactors * โ™ป๏ธ Re-implement `on_event` in FastAPI for compatibility with the next Starlette, while keeping backwards compatibility. PR [#14851](https://github.com/fastapi/fastapi/pull/14851) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 99b9630d20..b23e3c42fb 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.2" +__version__ = "0.128.3" from starlette import status as status From 5a31b37cc7f12d006d7daebdc82b623e25b3ed2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 09:18:30 -0800 Subject: [PATCH 154/367] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20developm?= =?UTF-8?q?ent=20dependencies=20(#14854)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 88 +- uv.lock | 2955 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 2712 insertions(+), 331 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 519f45e315..4895c2d34e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,62 +129,62 @@ dev = [ { include-group = "tests" }, { include-group = "docs" }, { include-group = "translations" }, - "playwright>=1.57.0", - "prek==0.2.22", + "playwright >=1.57.0", + "prek >=0.2.22", ] docs = [ { include-group = "docs-tests" }, - "black==25.1.0", - "cairosvg==2.8.2", - "griffe-typingdoc==0.3.0", - "griffe-warnings-deprecated==1.1.0", - "jieba==0.42.1", - "markdown-include-variants==0.0.8", - "mdx-include>=1.4.1,<2.0.0", - "mkdocs-macros-plugin==1.5.0", - "mkdocs-material==9.7.0", - "mkdocs-redirects>=1.2.1,<1.3.0", - "mkdocstrings[python]==0.30.1", - "pillow==11.3.0", - "python-slugify==8.0.4", - "pyyaml>=5.3.1,<7.0.0", - "typer==0.21.1", + "black >=25.1.0", + "cairosvg >=2.8.2", + "griffe-typingdoc >=0.3.0", + "griffe-warnings-deprecated >=1.1.0", + "jieba >=0.42.1", + "markdown-include-variants >=0.0.8", + "mdx-include >=1.4.1,<2.0.0", + "mkdocs-macros-plugin >=1.5.0", + "mkdocs-material >=9.7.0", + "mkdocs-redirects >=1.2.1,<1.3.0", + "mkdocstrings[python] >=0.30.1", + "pillow >=11.3.0", + "python-slugify >=8.0.4", + "pyyaml >=5.3.1,<7.0.0", + "typer >=0.21.1", ] docs-tests = [ - "httpx>=0.23.0,<1.0.0", - "ruff==0.14.14", + "httpx >=0.23.0,<1.0.0", + "ruff >=0.14.14", ] github-actions = [ - "httpx>=0.27.0,<1.0.0", - "pydantic>=2.5.3,<3.0.0", - "pydantic-settings>=2.1.0,<3.0.0", - "pygithub>=2.3.0,<3.0.0", - "pyyaml>=5.3.1,<7.0.0", - "smokeshow>=0.5.0", + "httpx >=0.27.0,<1.0.0", + "pydantic >=2.5.3,<3.0.0", + "pydantic-settings >=2.1.0,<3.0.0", + "pygithub >=2.3.0,<3.0.0", + "pyyaml >=5.3.1,<7.0.0", + "smokeshow >=0.5.0", ] tests = [ { include-group = "docs-tests" }, - "anyio[trio]>=3.2.1,<5.0.0", - "coverage[toml]>=6.5.0,<8.0", - "dirty-equals==0.9.0", - "flask>=3.0.0,<4.0.0", - "inline-snapshot>=0.21.1", - "mypy==1.14.1", - "pwdlib[argon2]>=0.2.1", - "pyjwt==2.9.0", - "pytest>=7.1.3,<9.0.0", - "pytest-codspeed==4.2.0", - "pyyaml>=5.3.1,<7.0.0", - "sqlmodel==0.0.31", - "strawberry-graphql>=0.200.0,<1.0.0", - "types-orjson==3.6.2", - "types-ujson==5.10.0.20240515", - "a2wsgi>=1.9.0,<=2.0.0", + "anyio[trio] >=3.2.1,<5.0.0", + "coverage[toml] >=6.5.0,<8.0", + "dirty-equals >=0.9.0", + "flask >=3.0.0,<4.0.0", + "inline-snapshot >=0.21.1", + "mypy >=1.14.1", + "pwdlib[argon2] >=0.2.1", + "pyjwt >=2.9.0", + "pytest >=7.1.3,<9.0.0", + "pytest-codspeed >=4.2.0", + "pyyaml >=5.3.1,<7.0.0", + "sqlmodel >=0.0.31", + "strawberry-graphql >=0.200.0,<1.0.0", + "types-orjson >=3.6.2", + "types-ujson >=5.10.0.20240515", + "a2wsgi >=1.9.0,<=2.0.0", ] translations = [ - "gitpython==3.1.46", - "pydantic-ai==0.4.10", - "pygithub==2.8.1", + "gitpython >=3.1.46", + "pydantic-ai >=0.4.10", + "pygithub >=2.8.1", ] [tool.pdm] diff --git a/uv.lock b/uv.lock index 88b9f28df7..9a807f8b4d 100644 --- a/uv.lock +++ b/uv.lock @@ -31,6 +31,165 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/78/eb55fabaab41abc53f52c0918a9a8c0f747807e5306273f51120fd695957/ag_ui_protocol-0.1.10-py3-none-any.whl", hash = "sha256:c81e6981f30aabdf97a7ee312bfd4df0cd38e718d9fc10019c7d438128b93ab5", size = 7889, upload-time = "2025-11-06T15:17:15.325Z" }, ] +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, + { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, + { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, + { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, + { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, + { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, + { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, + { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, + { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, + { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, + { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, + { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, + { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, + { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, + { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, + { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, + { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, + { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, + { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, + { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, + { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, + { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, + { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, + { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, + { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, + { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, + { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, + { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, + { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, + { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, + { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, + { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, + { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, + { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, + { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, + { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, + { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, + { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, + { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, + { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, + { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, + { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, + { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, + { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, + { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, + { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, + { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, + { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, + { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, + { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, + { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, + { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, + { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, + { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, + { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, + { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, + { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, + { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, + { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, + { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, + { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, + { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, + { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, + { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, + { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, + { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, + { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, + { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, + { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + [[package]] name = "annotated-doc" version = "0.0.4" @@ -173,6 +332,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, ] +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, +] + [[package]] name = "attrs" version = "25.4.0" @@ -182,6 +350,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] +[[package]] +name = "authlib" +version = "1.6.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/dc/ed1681bf1339dd6ea1ce56136bad4baabc6f7ad466e375810702b0237047/authlib-1.6.7.tar.gz", hash = "sha256:dbf10100011d1e1b34048c9d120e83f13b35d69a826ae762b93d2fb5aafc337b", size = 164950, upload-time = "2026-02-06T14:04:14.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/00/3ed12264094ec91f534fae429945efbaa9f8c666f3aa7061cc3b2a26a0cd/authlib-1.6.7-py2.py3-none-any.whl", hash = "sha256:c637340d9a02789d2efa1d003a7437d10d3e565237bcb5fcbc6c134c7b95bab0", size = 244115, upload-time = "2026-02-06T14:04:12.141Z" }, +] + [[package]] name = "babel" version = "2.18.0" @@ -191,6 +371,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + [[package]] name = "backrefs" version = "6.1" @@ -205,44 +394,107 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/e3/a4fa1946722c4c7b063cc25043a12d9ce9b4323777f89643be74cef2993c/backrefs-6.1-py39-none-any.whl", hash = "sha256:a9e99b8a4867852cad177a6430e31b0f6e495d65f8c6c134b68c14c3c95bf4b0", size = 381058, upload-time = "2025-11-15T14:52:06.698Z" }, ] +[[package]] +name = "beartype" +version = "0.22.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, +] + [[package]] name = "black" -version = "25.1.0" +version = "25.11.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, + { name = "mypy-extensions", marker = "python_full_version < '3.10'" }, + { name = "packaging", marker = "python_full_version < '3.10'" }, + { name = "pathspec", marker = "python_full_version < '3.10'" }, { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pytokens", marker = "python_full_version < '3.10'" }, + { name = "tomli", marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/ad/33adf4708633d047950ff2dfdea2e215d84ac50ef95aff14a614e4b6e9b2/black-25.11.0.tar.gz", hash = "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", size = 655669, upload-time = "2025-11-10T01:53:50.558Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/d2/6caccbc96f9311e8ec3378c296d4f4809429c43a6cd2394e3c390e86816d/black-25.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e", size = 1743501, upload-time = "2025-11-10T01:59:06.202Z" }, + { url = "https://files.pythonhosted.org/packages/69/35/b986d57828b3f3dccbf922e2864223197ba32e74c5004264b1c62bc9f04d/black-25.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0", size = 1597308, upload-time = "2025-11-10T01:57:58.633Z" }, + { url = "https://files.pythonhosted.org/packages/39/8e/8b58ef4b37073f52b64a7b2dd8c9a96c84f45d6f47d878d0aa557e9a2d35/black-25.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37", size = 1656194, upload-time = "2025-11-10T01:57:10.909Z" }, + { url = "https://files.pythonhosted.org/packages/8d/30/9c2267a7955ecc545306534ab88923769a979ac20a27cf618d370091e5dd/black-25.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03", size = 1347996, upload-time = "2025-11-10T01:57:22.391Z" }, + { url = "https://files.pythonhosted.org/packages/c4/62/d304786b75ab0c530b833a89ce7d997924579fb7484ecd9266394903e394/black-25.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a", size = 1727891, upload-time = "2025-11-10T02:01:40.507Z" }, + { url = "https://files.pythonhosted.org/packages/82/5d/ffe8a006aa522c9e3f430e7b93568a7b2163f4b3f16e8feb6d8c3552761a/black-25.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170", size = 1581875, upload-time = "2025-11-10T01:57:51.192Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c8/7c8bda3108d0bb57387ac41b4abb5c08782b26da9f9c4421ef6694dac01a/black-25.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc", size = 1642716, upload-time = "2025-11-10T01:56:51.589Z" }, + { url = "https://files.pythonhosted.org/packages/34/b9/f17dea34eecb7cc2609a89627d480fb6caea7b86190708eaa7eb15ed25e7/black-25.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e", size = 1352904, upload-time = "2025-11-10T01:59:26.252Z" }, + { url = "https://files.pythonhosted.org/packages/7f/12/5c35e600b515f35ffd737da7febdb2ab66bb8c24d88560d5e3ef3d28c3fd/black-25.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", size = 1772831, upload-time = "2025-11-10T02:03:47Z" }, + { url = "https://files.pythonhosted.org/packages/1a/75/b3896bec5a2bb9ed2f989a970ea40e7062f8936f95425879bbe162746fe5/black-25.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", size = 1608520, upload-time = "2025-11-10T01:58:46.895Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", size = 1682719, upload-time = "2025-11-10T01:56:55.24Z" }, + { url = "https://files.pythonhosted.org/packages/96/fb/f7dc2793a22cdf74a72114b5ed77fe3349a2e09ef34565857a2f917abdf2/black-25.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", size = 1362684, upload-time = "2025-11-10T01:57:07.639Z" }, + { url = "https://files.pythonhosted.org/packages/ad/47/3378d6a2ddefe18553d1115e36aea98f4a90de53b6a3017ed861ba1bd3bc/black-25.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", size = 1772446, upload-time = "2025-11-10T02:02:16.181Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4b/0f00bfb3d1f7e05e25bfc7c363f54dc523bb6ba502f98f4ad3acf01ab2e4/black-25.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", size = 1607983, upload-time = "2025-11-10T02:02:52.502Z" }, + { url = "https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", size = 1682481, upload-time = "2025-11-10T01:57:12.35Z" }, + { url = "https://files.pythonhosted.org/packages/55/17/7e10ff1267bfa950cc16f0a411d457cdff79678fbb77a6c73b73a5317904/black-25.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", size = 1363869, upload-time = "2025-11-10T01:58:24.608Z" }, + { url = "https://files.pythonhosted.org/packages/67/c0/cc865ce594d09e4cd4dfca5e11994ebb51604328489f3ca3ae7bb38a7db5/black-25.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", size = 1771358, upload-time = "2025-11-10T02:03:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/37/77/4297114d9e2fd2fc8ab0ab87192643cd49409eb059e2940391e7d2340e57/black-25.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", size = 1612902, upload-time = "2025-11-10T01:59:33.382Z" }, + { url = "https://files.pythonhosted.org/packages/de/63/d45ef97ada84111e330b2b2d45e1dd163e90bd116f00ac55927fb6bf8adb/black-25.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", size = 1680571, upload-time = "2025-11-10T01:57:04.239Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4b/5604710d61cdff613584028b4cb4607e56e148801ed9b38ee7970799dab6/black-25.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", size = 1382599, upload-time = "2025-11-10T01:57:57.427Z" }, + { url = "https://files.pythonhosted.org/packages/d5/9a/5b2c0e3215fe748fcf515c2dd34658973a1210bf610e24de5ba887e4f1c8/black-25.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06", size = 1743063, upload-time = "2025-11-10T02:02:43.175Z" }, + { url = "https://files.pythonhosted.org/packages/a1/20/245164c6efc27333409c62ba54dcbfbe866c6d1957c9a6c0647786e950da/black-25.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2", size = 1596867, upload-time = "2025-11-10T02:00:17.157Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6f/1a3859a7da205f3d50cf3a8bec6bdc551a91c33ae77a045bb24c1f46ab54/black-25.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc", size = 1655678, upload-time = "2025-11-10T01:57:09.028Z" }, + { url = "https://files.pythonhosted.org/packages/56/1a/6dec1aeb7be90753d4fcc273e69bc18bfd34b353223ed191da33f7519410/black-25.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc", size = 1347452, upload-time = "2025-11-10T01:57:01.871Z" }, + { url = "https://files.pythonhosted.org/packages/00/5d/aed32636ed30a6e7f9efd6ad14e2a0b0d687ae7c8c7ec4e4a557174b895c/black-25.11.0-py3-none-any.whl", hash = "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", size = 204918, upload-time = "2025-11-10T01:53:48.917Z" }, +] + +[[package]] +name = "black" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +dependencies = [ + { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "mypy-extensions", marker = "python_full_version >= '3.10'" }, + { name = "packaging", marker = "python_full_version >= '3.10'" }, + { name = "pathspec", marker = "python_full_version >= '3.10'" }, { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "pytokens", marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version == '3.10.*'" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419, upload-time = "2025-01-29T05:37:06.642Z" }, - { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080, upload-time = "2025-01-29T05:37:09.321Z" }, - { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886, upload-time = "2025-01-29T04:18:24.432Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404, upload-time = "2025-01-29T04:19:04.296Z" }, - { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload-time = "2025-01-29T05:37:11.71Z" }, - { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload-time = "2025-01-29T05:37:14.309Z" }, - { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload-time = "2025-01-29T04:18:17.688Z" }, - { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload-time = "2025-01-29T04:18:51.711Z" }, - { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload-time = "2025-01-29T05:37:16.707Z" }, - { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload-time = "2025-01-29T05:37:18.273Z" }, - { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload-time = "2025-01-29T04:18:33.823Z" }, - { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload-time = "2025-01-29T04:19:12.944Z" }, - { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673, upload-time = "2025-01-29T05:37:20.574Z" }, - { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190, upload-time = "2025-01-29T05:37:22.106Z" }, - { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926, upload-time = "2025-01-29T04:18:58.564Z" }, - { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613, upload-time = "2025-01-29T04:19:27.63Z" }, - { url = "https://files.pythonhosted.org/packages/d3/b6/ae7507470a4830dbbfe875c701e84a4a5fb9183d1497834871a715716a92/black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0", size = 1628593, upload-time = "2025-01-29T05:37:23.672Z" }, - { url = "https://files.pythonhosted.org/packages/24/c1/ae36fa59a59f9363017ed397750a0cd79a470490860bc7713967d89cdd31/black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f", size = 1460000, upload-time = "2025-01-29T05:37:25.829Z" }, - { url = "https://files.pythonhosted.org/packages/ac/b6/98f832e7a6c49aa3a464760c67c7856363aa644f2f3c74cf7d624168607e/black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e", size = 1765963, upload-time = "2025-01-29T04:18:38.116Z" }, - { url = "https://files.pythonhosted.org/packages/ce/e9/2cb0a017eb7024f70e0d2e9bdb8c5a5b078c5740c7f8816065d06f04c557/black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355", size = 1419419, upload-time = "2025-01-29T04:18:30.191Z" }, - { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/13/88/560b11e521c522440af991d46848a2bde64b5f7202ec14e1f46f9509d328/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58", size = 658785, upload-time = "2026-01-18T04:50:11.993Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/1b/523329e713f965ad0ea2b7a047eeb003007792a0353622ac7a8cb2ee6fef/black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168", size = 1849661, upload-time = "2026-01-18T04:59:12.425Z" }, + { url = "https://files.pythonhosted.org/packages/14/82/94c0640f7285fa71c2f32879f23e609dd2aa39ba2641f395487f24a578e7/black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d", size = 1689065, upload-time = "2026-01-18T04:59:13.993Z" }, + { url = "https://files.pythonhosted.org/packages/f0/78/474373cbd798f9291ed8f7107056e343fd39fef42de4a51c7fd0d360840c/black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0", size = 1751502, upload-time = "2026-01-18T04:59:15.971Z" }, + { url = "https://files.pythonhosted.org/packages/29/89/59d0e350123f97bc32c27c4d79563432d7f3530dca2bff64d855c178af8b/black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24", size = 1400102, upload-time = "2026-01-18T04:59:17.8Z" }, + { url = "https://files.pythonhosted.org/packages/e1/bc/5d866c7ae1c9d67d308f83af5462ca7046760158bbf142502bad8f22b3a1/black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89", size = 1207038, upload-time = "2026-01-18T04:59:19.543Z" }, + { url = "https://files.pythonhosted.org/packages/30/83/f05f22ff13756e1a8ce7891db517dbc06200796a16326258268f4658a745/black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5", size = 1831956, upload-time = "2026-01-18T04:59:21.38Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f2/b2c570550e39bedc157715e43927360312d6dd677eed2cc149a802577491/black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68", size = 1672499, upload-time = "2026-01-18T04:59:23.257Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d7/990d6a94dc9e169f61374b1c3d4f4dd3037e93c2cc12b6f3b12bc663aa7b/black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14", size = 1735431, upload-time = "2026-01-18T04:59:24.729Z" }, + { url = "https://files.pythonhosted.org/packages/36/1c/cbd7bae7dd3cb315dfe6eeca802bb56662cc92b89af272e014d98c1f2286/black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c", size = 1400468, upload-time = "2026-01-18T04:59:27.381Z" }, + { url = "https://files.pythonhosted.org/packages/59/b1/9fe6132bb2d0d1f7094613320b56297a108ae19ecf3041d9678aec381b37/black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4", size = 1207332, upload-time = "2026-01-18T04:59:28.711Z" }, + { url = "https://files.pythonhosted.org/packages/f5/13/710298938a61f0f54cdb4d1c0baeb672c01ff0358712eddaf29f76d32a0b/black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f", size = 1878189, upload-time = "2026-01-18T04:59:30.682Z" }, + { url = "https://files.pythonhosted.org/packages/79/a6/5179beaa57e5dbd2ec9f1c64016214057b4265647c62125aa6aeffb05392/black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6", size = 1700178, upload-time = "2026-01-18T04:59:32.387Z" }, + { url = "https://files.pythonhosted.org/packages/8c/04/c96f79d7b93e8f09d9298b333ca0d31cd9b2ee6c46c274fd0f531de9dc61/black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a", size = 1777029, upload-time = "2026-01-18T04:59:33.767Z" }, + { url = "https://files.pythonhosted.org/packages/49/f9/71c161c4c7aa18bdda3776b66ac2dc07aed62053c7c0ff8bbda8c2624fe2/black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791", size = 1406466, upload-time = "2026-01-18T04:59:35.177Z" }, + { url = "https://files.pythonhosted.org/packages/4a/8b/a7b0f974e473b159d0ac1b6bcefffeb6bec465898a516ee5cc989503cbc7/black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954", size = 1216393, upload-time = "2026-01-18T04:59:37.18Z" }, + { url = "https://files.pythonhosted.org/packages/79/04/fa2f4784f7237279332aa735cdfd5ae2e7730db0072fb2041dadda9ae551/black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304", size = 1877781, upload-time = "2026-01-18T04:59:39.054Z" }, + { url = "https://files.pythonhosted.org/packages/cf/ad/5a131b01acc0e5336740a039628c0ab69d60cf09a2c87a4ec49f5826acda/black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9", size = 1699670, upload-time = "2026-01-18T04:59:41.005Z" }, + { url = "https://files.pythonhosted.org/packages/da/7c/b05f22964316a52ab6b4265bcd52c0ad2c30d7ca6bd3d0637e438fc32d6e/black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b", size = 1775212, upload-time = "2026-01-18T04:59:42.545Z" }, + { url = "https://files.pythonhosted.org/packages/a6/a3/e8d1526bea0446e040193185353920a9506eab60a7d8beb062029129c7d2/black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b", size = 1409953, upload-time = "2026-01-18T04:59:44.357Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5a/d62ebf4d8f5e3a1daa54adaab94c107b57be1b1a2f115a0249b41931e188/black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca", size = 1217707, upload-time = "2026-01-18T04:59:45.719Z" }, + { url = "https://files.pythonhosted.org/packages/6a/83/be35a175aacfce4b05584ac415fd317dd6c24e93a0af2dcedce0f686f5d8/black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115", size = 1871864, upload-time = "2026-01-18T04:59:47.586Z" }, + { url = "https://files.pythonhosted.org/packages/a5/f5/d33696c099450b1274d925a42b7a030cd3ea1f56d72e5ca8bbed5f52759c/black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79", size = 1701009, upload-time = "2026-01-18T04:59:49.443Z" }, + { url = "https://files.pythonhosted.org/packages/1b/87/670dd888c537acb53a863bc15abbd85b22b429237d9de1b77c0ed6b79c42/black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af", size = 1767806, upload-time = "2026-01-18T04:59:50.769Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9c/cd3deb79bfec5bcf30f9d2100ffeec63eecce826eb63e3961708b9431ff1/black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f", size = 1433217, upload-time = "2026-01-18T04:59:52.218Z" }, + { url = "https://files.pythonhosted.org/packages/4e/29/f3be41a1cf502a283506f40f5d27203249d181f7a1a2abce1c6ce188035a/black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0", size = 1245773, upload-time = "2026-01-18T04:59:54.457Z" }, + { url = "https://files.pythonhosted.org/packages/e4/3d/51bdb3ecbfadfaf825ec0c75e1de6077422b4afa2091c6c9ba34fbfc0c2d/black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede", size = 204010, upload-time = "2026-01-18T04:50:09.978Z" }, ] [[package]] @@ -283,6 +535,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/a8/95656f91b795eb47b73a00d36c51c7a5729eafa632c7348caa068ff63e50/botocore-1.42.43-py3-none-any.whl", hash = "sha256:1c0e30f62e274978ac3bcab253e3a859febea634b72b5e343589db7d17f83cd6", size = 14610179, upload-time = "2026-02-05T20:31:32.727Z" }, ] +[[package]] +name = "cachetools" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/af/df70e9b65bc77a1cbe0768c0aa4617147f30f8306ded98c1744bcdc0ae1e/cachetools-7.0.0.tar.gz", hash = "sha256:a9abf18ff3b86c7d05b27ead412e235e16ae045925e531fae38d5fada5ed5b08", size = 35796, upload-time = "2026-02-01T18:59:47.411Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/df/2dd32cce20cbcf6f2ec456b58d44368161ad28320729f64e5e1d5d7bd0ae/cachetools-7.0.0-py3-none-any.whl", hash = "sha256:d52fef60e6e964a1969cfb61ccf6242a801b432790fe520d78720d757c81cbd2", size = 13487, upload-time = "2026-02-01T18:59:45.981Z" }, +] + [[package]] name = "cairocffi" version = "1.7.1" @@ -303,7 +564,8 @@ dependencies = [ { name = "cairocffi" }, { name = "cssselect2" }, { name = "defusedxml" }, - { name = "pillow" }, + { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "tinycss2", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "tinycss2", version = "1.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] @@ -552,6 +814,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, ] +[[package]] +name = "cloudpickle" +version = "3.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, +] + [[package]] name = "cohere" version = "5.20.4" @@ -808,6 +1079,19 @@ toml = [ { name = "tomli", marker = "python_full_version >= '3.10' and python_full_version <= '3.11'" }, ] +[[package]] +name = "croniter" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, + { name = "pytz", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/2f/44d1ae153a0e27be56be43465e5cb39b9650c781e001e7864389deb25090/croniter-6.0.0.tar.gz", hash = "sha256:37c504b313956114a983ece2c2b07790b1f1094fe9d81cc94739214748255577", size = 64481, upload-time = "2024-12-17T17:17:47.32Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/4b/290b4c3efd6417a8b0c284896de19b1d5855e6dbdb97d2a35e68fa42de85/croniter-6.0.0-py2.py3-none-any.whl", hash = "sha256:2f878c3856f17896979b2a4379ba1f09c83e374931ea15cc835c5dd2eee9b368", size = 25468, upload-time = "2024-12-17T17:17:45.359Z" }, +] + [[package]] name = "cross-web" version = "0.4.1" @@ -903,6 +1187,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/c0/9f59d2ebd9d585e1681c51767eb138bcd9d0ea770f6fc003cd875c7f5e62/cyclic-1.0.0-py3-none-any.whl", hash = "sha256:32d8181d7698f426bce6f14f4c3921ef95b6a84af9f96192b59beb05bc00c3ed", size = 2547, upload-time = "2018-09-26T16:47:05.609Z" }, ] +[[package]] +name = "cyclopts" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs", marker = "python_full_version >= '3.10'" }, + { name = "docstring-parser", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "rich-rst", marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version == '3.10.*'" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/93/6085aa89c3fff78a5180987354538d72e43b0db27e66a959302d0c07821a/cyclopts-4.5.1.tar.gz", hash = "sha256:fadc45304763fd9f5d6033727f176898d17a1778e194436964661a005078a3dd", size = 162075, upload-time = "2026-01-25T15:23:54.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/7c/996760c30f1302704af57c66ff2d723f7d656d0d0b93563b5528a51484bb/cyclopts-4.5.1-py3-none-any.whl", hash = "sha256:0642c93601e554ca6b7b9abd81093847ea4448b2616280f2a0952416574e8c7a", size = 199807, upload-time = "2026-01-25T15:23:55.219Z" }, +] + [[package]] name = "defusedxml" version = "0.7.1" @@ -914,11 +1215,20 @@ wheels = [ [[package]] name = "dirty-equals" -version = "0.9.0" +version = "0.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/1d/c5913ac9d6615515a00f4bdc71356d302437cb74ff2e9aaccd3c14493b78/dirty_equals-0.11.tar.gz", hash = "sha256:f4ac74ee88f2d11e2fa0f65eb30ee4f07105c5f86f4dc92b09eb1138775027c3", size = 128067, upload-time = "2025-11-17T01:51:24.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/8d/dbff05239043271dbeace563a7686212a3dd517864a35623fe4d4a64ca19/dirty_equals-0.11-py3-none-any.whl", hash = "sha256:b1d7093273fc2f9be12f443a8ead954ef6daaf6746fd42ef3a5616433ee85286", size = 28051, upload-time = "2025-11-17T01:51:22.849Z" }, +] + +[[package]] +name = "diskcache" +version = "5.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/99/133892f401ced5a27e641a473c547d5fbdb39af8f85dac8a9d633ea3e7a7/dirty_equals-0.9.0.tar.gz", hash = "sha256:17f515970b04ed7900b733c95fd8091f4f85e52f1fb5f268757f25c858eb1f7b", size = 50412, upload-time = "2025-01-11T23:23:40.491Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916, upload-time = "2023-08-31T06:12:00.316Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/0c/03cc99bf3b6328604b10829de3460f2b2ad3373200c45665c38508e550c6/dirty_equals-0.9.0-py3-none-any.whl", hash = "sha256:ff4d027f5cfa1b69573af00f7ba9043ea652dbdce3fe5cbe828e478c7346db9c", size = 28226, upload-time = "2025-01-11T23:23:37.489Z" }, + { url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550, upload-time = "2023-08-31T06:11:58.822Z" }, ] [[package]] @@ -964,6 +1274,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, ] +[[package]] +name = "docutils" +version = "0.22.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, +] + [[package]] name = "email-validator" version = "2.3.0" @@ -1008,6 +1327,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, ] +[[package]] +name = "fakeredis" +version = "2.33.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "redis", marker = "python_full_version >= '3.10'" }, + { name = "sortedcontainers", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/78/a850fed8aeef96d4a99043c90b818b2ed5419cd5b24a4049fd7cfb9f1471/fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965", size = 119605, upload-time = "2025-12-16T19:45:51.08Z" }, +] + +[package.optional-dependencies] +lua = [ + { name = "lupa", marker = "python_full_version >= '3.10'" }, +] + [[package]] name = "fastapi" source = { editable = "." } @@ -1015,7 +1353,7 @@ dependencies = [ { name = "annotated-doc" }, { name = "pydantic" }, { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions" }, { name = "typing-inspection" }, ] @@ -1070,7 +1408,8 @@ standard-no-fastapi-cloud-cli = [ dev = [ { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, - { name = "black" }, + { name = "black", version = "25.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "black", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "cairosvg" }, { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, @@ -1087,14 +1426,17 @@ dev = [ { name = "mkdocs-macros-plugin" }, { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, - { name = "mkdocstrings", extra = ["python"] }, + { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version < '3.10'" }, + { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version >= '3.10'" }, { name = "mypy" }, - { name = "pillow" }, + { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "playwright" }, { name = "prek" }, { name = "pwdlib", version = "0.2.1", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version < '3.10'" }, { name = "pwdlib", version = "0.3.0", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version >= '3.10'" }, - { name = "pydantic-ai" }, + { name = "pydantic-ai", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pydantic-ai", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pygithub" }, { name = "pyjwt" }, { name = "pytest" }, @@ -1104,13 +1446,14 @@ dev = [ { name = "ruff" }, { name = "sqlmodel" }, { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.291.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql", version = "0.291.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typer" }, { name = "types-orjson" }, { name = "types-ujson" }, ] docs = [ - { name = "black" }, + { name = "black", version = "25.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "black", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "cairosvg" }, { name = "griffe-typingdoc" }, { name = "griffe-warnings-deprecated" }, @@ -1121,8 +1464,10 @@ docs = [ { name = "mkdocs-macros-plugin" }, { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, - { name = "mkdocstrings", extra = ["python"] }, - { name = "pillow" }, + { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version < '3.10'" }, + { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version >= '3.10'" }, + { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "python-slugify" }, { name = "pyyaml" }, { name = "ruff" }, @@ -1160,13 +1505,14 @@ tests = [ { name = "ruff" }, { name = "sqlmodel" }, { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.291.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql", version = "0.291.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "types-orjson" }, { name = "types-ujson" }, ] translations = [ { name = "gitpython" }, - { name = "pydantic-ai" }, + { name = "pydantic-ai", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pydantic-ai", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pygithub" }, ] @@ -1212,64 +1558,64 @@ provides-extras = ["standard", "standard-no-fastapi-cloud-cli", "all"] dev = [ { name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, - { name = "black", specifier = "==25.1.0" }, - { name = "cairosvg", specifier = "==2.8.2" }, + { name = "black", specifier = ">=25.1.0" }, + { name = "cairosvg", specifier = ">=2.8.2" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, - { name = "dirty-equals", specifier = "==0.9.0" }, + { name = "dirty-equals", specifier = ">=0.9.0" }, { name = "flask", specifier = ">=3.0.0,<4.0.0" }, - { name = "gitpython", specifier = "==3.1.46" }, - { name = "griffe-typingdoc", specifier = "==0.3.0" }, - { name = "griffe-warnings-deprecated", specifier = "==1.1.0" }, + { name = "gitpython", specifier = ">=3.1.46" }, + { name = "griffe-typingdoc", specifier = ">=0.3.0" }, + { name = "griffe-warnings-deprecated", specifier = ">=1.1.0" }, { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, { name = "inline-snapshot", specifier = ">=0.21.1" }, - { name = "jieba", specifier = "==0.42.1" }, - { name = "markdown-include-variants", specifier = "==0.0.8" }, + { name = "jieba", specifier = ">=0.42.1" }, + { name = "markdown-include-variants", specifier = ">=0.0.8" }, { name = "mdx-include", specifier = ">=1.4.1,<2.0.0" }, - { name = "mkdocs-macros-plugin", specifier = "==1.5.0" }, - { name = "mkdocs-material", specifier = "==9.7.0" }, + { name = "mkdocs-macros-plugin", specifier = ">=1.5.0" }, + { name = "mkdocs-material", specifier = ">=9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, - { name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" }, - { name = "mypy", specifier = "==1.14.1" }, - { name = "pillow", specifier = "==11.3.0" }, + { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, + { name = "mypy", specifier = ">=1.14.1" }, + { name = "pillow", specifier = ">=11.3.0" }, { name = "playwright", specifier = ">=1.57.0" }, - { name = "prek", specifier = "==0.2.22" }, + { name = "prek", specifier = ">=0.2.22" }, { name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" }, - { name = "pydantic-ai", specifier = "==0.4.10" }, - { name = "pygithub", specifier = "==2.8.1" }, - { name = "pyjwt", specifier = "==2.9.0" }, + { name = "pydantic-ai", specifier = ">=0.4.10" }, + { name = "pygithub", specifier = ">=2.8.1" }, + { name = "pyjwt", specifier = ">=2.9.0" }, { name = "pytest", specifier = ">=7.1.3,<9.0.0" }, - { name = "pytest-codspeed", specifier = "==4.2.0" }, - { name = "python-slugify", specifier = "==8.0.4" }, + { name = "pytest-codspeed", specifier = ">=4.2.0" }, + { name = "python-slugify", specifier = ">=8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.14" }, - { name = "sqlmodel", specifier = "==0.0.31" }, + { name = "ruff", specifier = ">=0.14.14" }, + { name = "sqlmodel", specifier = ">=0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, - { name = "typer", specifier = "==0.21.1" }, - { name = "types-orjson", specifier = "==3.6.2" }, - { name = "types-ujson", specifier = "==5.10.0.20240515" }, + { name = "typer", specifier = ">=0.21.1" }, + { name = "types-orjson", specifier = ">=3.6.2" }, + { name = "types-ujson", specifier = ">=5.10.0.20240515" }, ] docs = [ - { name = "black", specifier = "==25.1.0" }, - { name = "cairosvg", specifier = "==2.8.2" }, - { name = "griffe-typingdoc", specifier = "==0.3.0" }, - { name = "griffe-warnings-deprecated", specifier = "==1.1.0" }, + { name = "black", specifier = ">=25.1.0" }, + { name = "cairosvg", specifier = ">=2.8.2" }, + { name = "griffe-typingdoc", specifier = ">=0.3.0" }, + { name = "griffe-warnings-deprecated", specifier = ">=1.1.0" }, { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, - { name = "jieba", specifier = "==0.42.1" }, - { name = "markdown-include-variants", specifier = "==0.0.8" }, + { name = "jieba", specifier = ">=0.42.1" }, + { name = "markdown-include-variants", specifier = ">=0.0.8" }, { name = "mdx-include", specifier = ">=1.4.1,<2.0.0" }, - { name = "mkdocs-macros-plugin", specifier = "==1.5.0" }, - { name = "mkdocs-material", specifier = "==9.7.0" }, + { name = "mkdocs-macros-plugin", specifier = ">=1.5.0" }, + { name = "mkdocs-material", specifier = ">=9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, - { name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" }, - { name = "pillow", specifier = "==11.3.0" }, - { name = "python-slugify", specifier = "==8.0.4" }, + { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, + { name = "pillow", specifier = ">=11.3.0" }, + { name = "python-slugify", specifier = ">=8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.14" }, - { name = "typer", specifier = "==0.21.1" }, + { name = "ruff", specifier = ">=0.14.14" }, + { name = "typer", specifier = ">=0.21.1" }, ] docs-tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, - { name = "ruff", specifier = "==0.14.14" }, + { name = "ruff", specifier = ">=0.14.14" }, ] github-actions = [ { name = "httpx", specifier = ">=0.27.0,<1.0.0" }, @@ -1283,26 +1629,26 @@ tests = [ { name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, - { name = "dirty-equals", specifier = "==0.9.0" }, + { name = "dirty-equals", specifier = ">=0.9.0" }, { name = "flask", specifier = ">=3.0.0,<4.0.0" }, { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, { name = "inline-snapshot", specifier = ">=0.21.1" }, - { name = "mypy", specifier = "==1.14.1" }, + { name = "mypy", specifier = ">=1.14.1" }, { name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" }, - { name = "pyjwt", specifier = "==2.9.0" }, + { name = "pyjwt", specifier = ">=2.9.0" }, { name = "pytest", specifier = ">=7.1.3,<9.0.0" }, - { name = "pytest-codspeed", specifier = "==4.2.0" }, + { name = "pytest-codspeed", specifier = ">=4.2.0" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, - { name = "ruff", specifier = "==0.14.14" }, - { name = "sqlmodel", specifier = "==0.0.31" }, + { name = "ruff", specifier = ">=0.14.14" }, + { name = "sqlmodel", specifier = ">=0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, - { name = "types-orjson", specifier = "==3.6.2" }, - { name = "types-ujson", specifier = "==5.10.0.20240515" }, + { name = "types-orjson", specifier = ">=3.6.2" }, + { name = "types-ujson", specifier = ">=5.10.0.20240515" }, ] translations = [ - { name = "gitpython", specifier = "==3.1.46" }, - { name = "pydantic-ai", specifier = "==0.4.10" }, - { name = "pygithub", specifier = "==2.8.1" }, + { name = "gitpython", specifier = ">=3.1.46" }, + { name = "pydantic-ai", specifier = ">=0.4.10" }, + { name = "pygithub", specifier = ">=2.8.1" }, ] [[package]] @@ -1552,6 +1898,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/ba/b814fb09b32c8f3059451c33bb11d55eb23188e6a499f5dde628d13bc076/fastavro-1.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:a38607444281619eda3a9c1be9f5397634012d1b237142eee1540e810b30ac8b", size = 510328, upload-time = "2025-10-10T15:42:32.415Z" }, ] +[[package]] +name = "fastmcp" +version = "2.14.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "authlib", marker = "python_full_version >= '3.10'" }, + { name = "cyclopts", marker = "python_full_version >= '3.10'" }, + { name = "exceptiongroup", marker = "python_full_version >= '3.10'" }, + { name = "httpx", marker = "python_full_version >= '3.10'" }, + { name = "jsonref", marker = "python_full_version >= '3.10'" }, + { name = "jsonschema-path", marker = "python_full_version >= '3.10'" }, + { name = "mcp", marker = "python_full_version >= '3.10'" }, + { name = "openapi-pydantic", marker = "python_full_version >= '3.10'" }, + { name = "packaging", marker = "python_full_version >= '3.10'" }, + { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "py-key-value-aio", extra = ["disk", "keyring", "memory"], marker = "python_full_version >= '3.10'" }, + { name = "pydantic", extra = ["email"], marker = "python_full_version >= '3.10'" }, + { name = "pydocket", marker = "python_full_version >= '3.10'" }, + { name = "pyperclip", marker = "python_full_version >= '3.10'" }, + { name = "python-dotenv", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "websockets", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/32/982678d44f13849530a74ab101ed80e060c2ee6cf87471f062dcf61705fd/fastmcp-2.14.5.tar.gz", hash = "sha256:38944dc582c541d55357082bda2241cedb42cd3a78faea8a9d6a2662c62a42d7", size = 8296329, upload-time = "2026-02-03T15:35:21.005Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/c1/1a35ec68ff76ea8443aa115b18bcdee748a4ada2124537ee90522899ff9f/fastmcp-2.14.5-py3-none-any.whl", hash = "sha256:d81e8ec813f5089d3624bec93944beaefa86c0c3a4ef1111cbef676a761ebccf", size = 417784, upload-time = "2026-02-03T15:35:18.489Z" }, +] + [[package]] name = "filelock" version = "3.19.1" @@ -1596,6 +1971,143 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" }, ] +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, + { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, + { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, + { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, + { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, + { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, + { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, + { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, + { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, + { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, + { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, + { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, + { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, + { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, + { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, + { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, + { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/c2/59/ae5cdac87a00962122ea37bb346d41b66aec05f9ce328fa2b9e216f8967b/frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47", size = 86967, upload-time = "2025-10-06T05:37:55.607Z" }, + { url = "https://files.pythonhosted.org/packages/8a/10/17059b2db5a032fd9323c41c39e9d1f5f9d0c8f04d1e4e3e788573086e61/frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca", size = 49984, upload-time = "2025-10-06T05:37:57.049Z" }, + { url = "https://files.pythonhosted.org/packages/4b/de/ad9d82ca8e5fa8f0c636e64606553c79e2b859ad253030b62a21fe9986f5/frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068", size = 50240, upload-time = "2025-10-06T05:37:58.145Z" }, + { url = "https://files.pythonhosted.org/packages/4e/45/3dfb7767c2a67d123650122b62ce13c731b6c745bc14424eea67678b508c/frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95", size = 219472, upload-time = "2025-10-06T05:37:59.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/bf/5bf23d913a741b960d5c1dac7c1985d8a2a1d015772b2d18ea168b08e7ff/frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459", size = 221531, upload-time = "2025-10-06T05:38:00.521Z" }, + { url = "https://files.pythonhosted.org/packages/d0/03/27ec393f3b55860859f4b74cdc8c2a4af3dbf3533305e8eacf48a4fd9a54/frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675", size = 219211, upload-time = "2025-10-06T05:38:01.842Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ad/0fd00c404fa73fe9b169429e9a972d5ed807973c40ab6b3cf9365a33d360/frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61", size = 231775, upload-time = "2025-10-06T05:38:03.384Z" }, + { url = "https://files.pythonhosted.org/packages/8a/c3/86962566154cb4d2995358bc8331bfc4ea19d07db1a96f64935a1607f2b6/frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6", size = 236631, upload-time = "2025-10-06T05:38:04.609Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/6ffad161dbd83782d2c66dc4d378a9103b31770cb1e67febf43aea42d202/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5", size = 218632, upload-time = "2025-10-06T05:38:05.917Z" }, + { url = "https://files.pythonhosted.org/packages/58/b2/4677eee46e0a97f9b30735e6ad0bf6aba3e497986066eb68807ac85cf60f/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3", size = 235967, upload-time = "2025-10-06T05:38:07.614Z" }, + { url = "https://files.pythonhosted.org/packages/05/f3/86e75f8639c5a93745ca7addbbc9de6af56aebb930d233512b17e46f6493/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1", size = 228799, upload-time = "2025-10-06T05:38:08.845Z" }, + { url = "https://files.pythonhosted.org/packages/30/00/39aad3a7f0d98f5eb1d99a3c311215674ed87061aecee7851974b335c050/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178", size = 230566, upload-time = "2025-10-06T05:38:10.52Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4d/aa144cac44568d137846ddc4d5210fb5d9719eb1d7ec6fa2728a54b5b94a/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda", size = 217715, upload-time = "2025-10-06T05:38:11.832Z" }, + { url = "https://files.pythonhosted.org/packages/64/4c/8f665921667509d25a0dd72540513bc86b356c95541686f6442a3283019f/frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087", size = 39933, upload-time = "2025-10-06T05:38:13.061Z" }, + { url = "https://files.pythonhosted.org/packages/79/bd/bcc926f87027fad5e59926ff12d136e1082a115025d33c032d1cd69ab377/frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a", size = 44121, upload-time = "2025-10-06T05:38:14.572Z" }, + { url = "https://files.pythonhosted.org/packages/4c/07/9c2e4eb7584af4b705237b971b89a4155a8e57599c4483a131a39256a9a0/frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103", size = 40312, upload-time = "2025-10-06T05:38:15.699Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + [[package]] name = "fsspec" version = "2025.10.0" @@ -1621,6 +2133,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, ] +[[package]] +name = "genai-prices" +version = "0.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, + { name = "httpx" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/87/bdc11c1671e3a3fe701c3c4aaae4aa2bb7a84a6bb1812dfb5693c87d3872/genai_prices-0.0.52.tar.gz", hash = "sha256:0df7420b555fa3a48d09e5c7802ba35b5dfa9fd49b0c3bb2c150c59060d83f52", size = 58364, upload-time = "2026-01-28T12:07:49.386Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/33/6316b4907a0bffc1bcc99074c7e2d01184fdfeee401c864146a40d55ad10/genai_prices-0.0.52-py3-none-any.whl", hash = "sha256:639e7a2ae7eddf5710febb9779b9c9e31ff5acf464b4eb1f6018798ea642e6d3", size = 60937, upload-time = "2026-01-28T12:07:47.921Z" }, +] + [[package]] name = "ghp-import" version = "2.1.0" @@ -1724,6 +2250,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/09/5f/4645d8a28c6e431d0dd6011003a852563f3da7037d36af53154925b099fd/google_genai-1.62.0-py3-none-any.whl", hash = "sha256:4c3daeff3d05fafee4b9a1a31f9c07f01bc22051081aa58b4d61f58d16d1bcc0", size = 724166, upload-time = "2026-02-04T22:48:39.956Z" }, ] +[[package]] +name = "googleapis-common-protos" +version = "1.72.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload-time = "2025-11-06T18:29:13.14Z" }, +] + [[package]] name = "graphql-core" version = "3.2.7" @@ -1951,6 +2489,77 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/88/3175759d2ef30406ea721f4d837bfa1ba4339fde3b81ba8c5640a96ed231/groq-1.0.0-py3-none-any.whl", hash = "sha256:6e22bf92ffad988f01d2d4df7729add66b8fd5dbfb2154b5bbf3af245b72c731", size = 138292, upload-time = "2025-12-17T23:34:21.957Z" }, ] +[[package]] +name = "grpcio" +version = "1.78.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/8a/3d098f35c143a89520e568e6539cc098fcd294495910e359889ce8741c84/grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5", size = 12852416, upload-time = "2026-02-06T09:57:18.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/a8/690a085b4d1fe066130de97a87de32c45062cf2ecd218df9675add895550/grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5", size = 5946986, upload-time = "2026-02-06T09:54:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/c7/1b/e5213c5c0ced9d2d92778d30529ad5bb2dcfb6c48c4e2d01b1f302d33d64/grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2", size = 11816533, upload-time = "2026-02-06T09:54:37.04Z" }, + { url = "https://files.pythonhosted.org/packages/18/37/1ba32dccf0a324cc5ace744c44331e300b000a924bf14840f948c559ede7/grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d", size = 6519964, upload-time = "2026-02-06T09:54:40.268Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f5/c0e178721b818072f2e8b6fde13faaba942406c634009caf065121ce246b/grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb", size = 7198058, upload-time = "2026-02-06T09:54:42.389Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b2/40d43c91ae9cd667edc960135f9f08e58faa1576dc95af29f66ec912985f/grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7", size = 6727212, upload-time = "2026-02-06T09:54:44.91Z" }, + { url = "https://files.pythonhosted.org/packages/ed/88/9da42eed498f0efcfcd9156e48ae63c0cde3bea398a16c99fb5198c885b6/grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec", size = 7300845, upload-time = "2026-02-06T09:54:47.562Z" }, + { url = "https://files.pythonhosted.org/packages/23/3f/1c66b7b1b19a8828890e37868411a6e6925df5a9030bfa87ab318f34095d/grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a", size = 8284605, upload-time = "2026-02-06T09:54:50.475Z" }, + { url = "https://files.pythonhosted.org/packages/94/c4/ca1bd87394f7b033e88525384b4d1e269e8424ab441ea2fba1a0c5b50986/grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813", size = 7726672, upload-time = "2026-02-06T09:54:53.11Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/f16e487d4cc65ccaf670f6ebdd1a17566b965c74fc3d93999d3b2821e052/grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de", size = 4076715, upload-time = "2026-02-06T09:54:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/2a/32/4ce60d94e242725fd3bcc5673c04502c82a8e87b21ea411a63992dc39f8f/grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf", size = 4799157, upload-time = "2026-02-06T09:54:59.838Z" }, + { url = "https://files.pythonhosted.org/packages/86/c7/d0b780a29b0837bf4ca9580904dfb275c1fc321ded7897d620af7047ec57/grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6", size = 5951525, upload-time = "2026-02-06T09:55:01.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b1/96920bf2ee61df85a9503cb6f733fe711c0ff321a5a697d791b075673281/grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e", size = 11830418, upload-time = "2026-02-06T09:55:04.462Z" }, + { url = "https://files.pythonhosted.org/packages/83/0c/7c1528f098aeb75a97de2bae18c530f56959fb7ad6c882db45d9884d6edc/grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911", size = 6524477, upload-time = "2026-02-06T09:55:07.111Z" }, + { url = "https://files.pythonhosted.org/packages/8d/52/e7c1f3688f949058e19a011c4e0dec973da3d0ae5e033909677f967ae1f4/grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e", size = 7198266, upload-time = "2026-02-06T09:55:10.016Z" }, + { url = "https://files.pythonhosted.org/packages/e5/61/8ac32517c1e856677282c34f2e7812d6c328fa02b8f4067ab80e77fdc9c9/grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303", size = 6730552, upload-time = "2026-02-06T09:55:12.207Z" }, + { url = "https://files.pythonhosted.org/packages/bd/98/b8ee0158199250220734f620b12e4a345955ac7329cfd908d0bf0fda77f0/grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04", size = 7304296, upload-time = "2026-02-06T09:55:15.044Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0f/7b72762e0d8840b58032a56fdbd02b78fc645b9fa993d71abf04edbc54f4/grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec", size = 8288298, upload-time = "2026-02-06T09:55:17.276Z" }, + { url = "https://files.pythonhosted.org/packages/24/ae/ae4ce56bc5bb5caa3a486d60f5f6083ac3469228faa734362487176c15c5/grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074", size = 7730953, upload-time = "2026-02-06T09:55:19.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6e/8052e3a28eb6a820c372b2eb4b5e32d195c661e137d3eca94d534a4cfd8a/grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856", size = 4076503, upload-time = "2026-02-06T09:55:21.521Z" }, + { url = "https://files.pythonhosted.org/packages/08/62/f22c98c5265dfad327251fa2f840b591b1df5f5e15d88b19c18c86965b27/grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558", size = 4799767, upload-time = "2026-02-06T09:55:24.107Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f4/7384ed0178203d6074446b3c4f46c90a22ddf7ae0b3aee521627f54cfc2a/grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97", size = 5913985, upload-time = "2026-02-06T09:55:26.832Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/be1caa25f06594463f685b3790b320f18aea49b33166f4141bfdc2bfb236/grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e", size = 11811853, upload-time = "2026-02-06T09:55:29.224Z" }, + { url = "https://files.pythonhosted.org/packages/24/a7/f06d151afc4e64b7e3cc3e872d331d011c279aaab02831e40a81c691fb65/grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996", size = 6475766, upload-time = "2026-02-06T09:55:31.825Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a8/4482922da832ec0082d0f2cc3a10976d84a7424707f25780b82814aafc0a/grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7", size = 7170027, upload-time = "2026-02-06T09:55:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/54/bf/f4a3b9693e35d25b24b0b39fa46d7d8a3c439e0a3036c3451764678fec20/grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9", size = 6690766, upload-time = "2026-02-06T09:55:36.902Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/521875265cc99fe5ad4c5a17010018085cae2810a928bf15ebe7d8bcd9cc/grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383", size = 7266161, upload-time = "2026-02-06T09:55:39.824Z" }, + { url = "https://files.pythonhosted.org/packages/05/86/296a82844fd40a4ad4a95f100b55044b4f817dece732bf686aea1a284147/grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6", size = 8253303, upload-time = "2026-02-06T09:55:42.353Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e4/ea3c0caf5468537f27ad5aab92b681ed7cc0ef5f8c9196d3fd42c8c2286b/grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce", size = 7698222, upload-time = "2026-02-06T09:55:44.629Z" }, + { url = "https://files.pythonhosted.org/packages/d7/47/7f05f81e4bb6b831e93271fb12fd52ba7b319b5402cbc101d588f435df00/grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68", size = 4066123, upload-time = "2026-02-06T09:55:47.644Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e7/d6914822c88aa2974dbbd10903d801a28a19ce9cd8bad7e694cbbcf61528/grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e", size = 4797657, upload-time = "2026-02-06T09:55:49.86Z" }, + { url = "https://files.pythonhosted.org/packages/05/a9/8f75894993895f361ed8636cd9237f4ab39ef87fd30db17467235ed1c045/grpcio-1.78.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:ce3a90455492bf8bfa38e56fbbe1dbd4f872a3d8eeaf7337dc3b1c8aa28c271b", size = 5920143, upload-time = "2026-02-06T09:55:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/55/06/0b78408e938ac424100100fd081189451b472236e8a3a1f6500390dc4954/grpcio-1.78.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:2bf5e2e163b356978b23652c4818ce4759d40f4712ee9ec5a83c4be6f8c23a3a", size = 11803926, upload-time = "2026-02-06T09:55:55.494Z" }, + { url = "https://files.pythonhosted.org/packages/88/93/b59fe7832ff6ae3c78b813ea43dac60e295fa03606d14d89d2e0ec29f4f3/grpcio-1.78.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f2ac84905d12918e4e55a16da17939eb63e433dc11b677267c35568aa63fc84", size = 6478628, upload-time = "2026-02-06T09:55:58.533Z" }, + { url = "https://files.pythonhosted.org/packages/ed/df/e67e3734527f9926b7d9c0dde6cd998d1d26850c3ed8eeec81297967ac67/grpcio-1.78.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b58f37edab4a3881bc6c9bca52670610e0c9ca14e2ea3cf9debf185b870457fb", size = 7173574, upload-time = "2026-02-06T09:56:01.786Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/cc03fffb07bfba982a9ec097b164e8835546980aec25ecfa5f9c1a47e022/grpcio-1.78.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:735e38e176a88ce41840c21bb49098ab66177c64c82426e24e0082500cc68af5", size = 6692639, upload-time = "2026-02-06T09:56:04.529Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/289c32e301b85bdb67d7ec68b752155e674ee3ba2173a1858f118e399ef3/grpcio-1.78.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2045397e63a7a0ee7957c25f7dbb36ddc110e0cfb418403d110c0a7a68a844e9", size = 7268838, upload-time = "2026-02-06T09:56:08.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/79/1be93f32add280461fa4773880196572563e9c8510861ac2da0ea0f892b6/grpcio-1.78.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9f136fbafe7ccf4ac7e8e0c28b31066e810be52d6e344ef954a3a70234e1702", size = 8251878, upload-time = "2026-02-06T09:56:10.914Z" }, + { url = "https://files.pythonhosted.org/packages/65/65/793f8e95296ab92e4164593674ae6291b204bb5f67f9d4a711489cd30ffa/grpcio-1.78.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:748b6138585379c737adc08aeffd21222abbda1a86a0dca2a39682feb9196c20", size = 7695412, upload-time = "2026-02-06T09:56:13.593Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/1e233fe697ecc82845942c2822ed06bb522e70d6771c28d5528e4c50f6a4/grpcio-1.78.0-cp313-cp313-win32.whl", hash = "sha256:271c73e6e5676afe4fc52907686670c7cea22ab2310b76a59b678403ed40d670", size = 4064899, upload-time = "2026-02-06T09:56:15.601Z" }, + { url = "https://files.pythonhosted.org/packages/4d/27/d86b89e36de8a951501fb06a0f38df19853210f341d0b28f83f4aa0ffa08/grpcio-1.78.0-cp313-cp313-win_amd64.whl", hash = "sha256:f2d4e43ee362adfc05994ed479334d5a451ab7bc3f3fee1b796b8ca66895acb4", size = 4797393, upload-time = "2026-02-06T09:56:17.882Z" }, + { url = "https://files.pythonhosted.org/packages/29/f2/b56e43e3c968bfe822fa6ce5bca10d5c723aa40875b48791ce1029bb78c7/grpcio-1.78.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:e87cbc002b6f440482b3519e36e1313eb5443e9e9e73d6a52d43bd2004fcfd8e", size = 5920591, upload-time = "2026-02-06T09:56:20.758Z" }, + { url = "https://files.pythonhosted.org/packages/5d/81/1f3b65bd30c334167bfa8b0d23300a44e2725ce39bba5b76a2460d85f745/grpcio-1.78.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:c41bc64626db62e72afec66b0c8a0da76491510015417c127bfc53b2fe6d7f7f", size = 11813685, upload-time = "2026-02-06T09:56:24.315Z" }, + { url = "https://files.pythonhosted.org/packages/0e/1c/bbe2f8216a5bd3036119c544d63c2e592bdf4a8ec6e4a1867592f4586b26/grpcio-1.78.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8dfffba826efcf366b1e3ccc37e67afe676f290e13a3b48d31a46739f80a8724", size = 6487803, upload-time = "2026-02-06T09:56:27.367Z" }, + { url = "https://files.pythonhosted.org/packages/16/5c/a6b2419723ea7ddce6308259a55e8e7593d88464ce8db9f4aa857aba96fa/grpcio-1.78.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74be1268d1439eaaf552c698cdb11cd594f0c49295ae6bb72c34ee31abbe611b", size = 7173206, upload-time = "2026-02-06T09:56:29.876Z" }, + { url = "https://files.pythonhosted.org/packages/df/1e/b8801345629a415ea7e26c83d75eb5dbe91b07ffe5210cc517348a8d4218/grpcio-1.78.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be63c88b32e6c0f1429f1398ca5c09bc64b0d80950c8bb7807d7d7fb36fb84c7", size = 6693826, upload-time = "2026-02-06T09:56:32.305Z" }, + { url = "https://files.pythonhosted.org/packages/34/84/0de28eac0377742679a510784f049738a80424b17287739fc47d63c2439e/grpcio-1.78.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3c586ac70e855c721bda8f548d38c3ca66ac791dc49b66a8281a1f99db85e452", size = 7277897, upload-time = "2026-02-06T09:56:34.915Z" }, + { url = "https://files.pythonhosted.org/packages/ca/9c/ad8685cfe20559a9edb66f735afdcb2b7d3de69b13666fdfc542e1916ebd/grpcio-1.78.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:35eb275bf1751d2ffbd8f57cdbc46058e857cf3971041521b78b7db94bdaf127", size = 8252404, upload-time = "2026-02-06T09:56:37.553Z" }, + { url = "https://files.pythonhosted.org/packages/3c/05/33a7a4985586f27e1de4803887c417ec7ced145ebd069bc38a9607059e2b/grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65", size = 7696837, upload-time = "2026-02-06T09:56:40.173Z" }, + { url = "https://files.pythonhosted.org/packages/73/77/7382241caf88729b106e49e7d18e3116216c778e6a7e833826eb96de22f7/grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c", size = 4142439, upload-time = "2026-02-06T09:56:43.258Z" }, + { url = "https://files.pythonhosted.org/packages/48/b2/b096ccce418882fbfda4f7496f9357aaa9a5af1896a9a7f60d9f2b275a06/grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb", size = 4929852, upload-time = "2026-02-06T09:56:45.885Z" }, + { url = "https://files.pythonhosted.org/packages/58/6c/40a4bba2c753ea8eeb8d776a31e9c54f4e506edf36db93a3db5456725294/grpcio-1.78.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:86f85dd7c947baa707078a236288a289044836d4b640962018ceb9cd1f899af5", size = 5947902, upload-time = "2026-02-06T09:56:48.469Z" }, + { url = "https://files.pythonhosted.org/packages/c0/4c/ed7664a37a7008be41204c77e0d88bbc4ac531bcf0c27668cd066f9ff6e2/grpcio-1.78.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:de8cb00d1483a412a06394b8303feec5dcb3b55f81d83aa216dbb6a0b86a94f5", size = 11824772, upload-time = "2026-02-06T09:56:51.264Z" }, + { url = "https://files.pythonhosted.org/packages/9a/5b/45a5c23ba3c4a0f51352366d9b25369a2a51163ab1c93482cb8408726617/grpcio-1.78.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e888474dee2f59ff68130f8a397792d8cb8e17e6b3434339657ba4ee90845a8c", size = 6521579, upload-time = "2026-02-06T09:56:54.967Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/392e647d918004231e3d1c780ed125c48939bfc8f845adb8b5820410da3e/grpcio-1.78.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:86ce2371bfd7f212cf60d8517e5e854475c2c43ce14aa910e136ace72c6db6c1", size = 7199330, upload-time = "2026-02-06T09:56:57.611Z" }, + { url = "https://files.pythonhosted.org/packages/68/2f/42a52d78bdbdb3f1310ed690a3511cd004740281ca75d300b7bd6d9d3de3/grpcio-1.78.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0c689c02947d636bc7fab3e30cc3a3445cca99c834dfb77cd4a6cabfc1c5597", size = 6726696, upload-time = "2026-02-06T09:57:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/0f/83/b3d932a4fbb2dce3056f6df2926fc2d3ddc5d5acbafbec32c84033cf3f23/grpcio-1.78.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ce7599575eeb25c0f4dc1be59cada6219f3b56176f799627f44088b21381a28a", size = 7299076, upload-time = "2026-02-06T09:57:04.124Z" }, + { url = "https://files.pythonhosted.org/packages/ba/d9/70ea1be55efaf91fd19f7258b1292772a8226cf1b0e237717fba671073cb/grpcio-1.78.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:684083fd383e9dc04c794adb838d4faea08b291ce81f64ecd08e4577c7398adf", size = 8284493, upload-time = "2026-02-06T09:57:06.746Z" }, + { url = "https://files.pythonhosted.org/packages/d0/2f/3dddccf49e3e75564655b84175fca092d3efd81d2979fc89c4b1c1d879dc/grpcio-1.78.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab399ef5e3cd2a721b1038a0f3021001f19c5ab279f145e1146bb0b9f1b2b12c", size = 7724340, upload-time = "2026-02-06T09:57:09.453Z" }, + { url = "https://files.pythonhosted.org/packages/79/ae/dfdb3183141db787a9363078a98764675996a7c2448883153091fd7c8527/grpcio-1.78.0-cp39-cp39-win32.whl", hash = "sha256:f3d6379493e18ad4d39537a82371c5281e153e963cecb13f953ebac155756525", size = 4077641, upload-time = "2026-02-06T09:57:11.881Z" }, + { url = "https://files.pythonhosted.org/packages/aa/aa/694b2f505345cfdd234cffb2525aa379a81695e6c02fd40d7e9193e871c6/grpcio-1.78.0-cp39-cp39-win_amd64.whl", hash = "sha256:5361a0630a7fdb58a6a97638ab70e1dae2893c4d08d7aba64ded28bb9e7a29df", size = 4799428, upload-time = "2026-02-06T09:57:14.493Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -2087,25 +2696,28 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.4.1" +version = "0.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "filelock", version = "3.20.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "fsspec", version = "2025.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "fsspec", version = "2026.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, - { name = "httpx" }, + { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, { name = "packaging" }, { name = "pyyaml" }, - { name = "shellingham" }, + { name = "requests" }, { name = "tqdm" }, - { name = "typer-slim" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c4/fc/eb9bc06130e8bbda6a616e1b80a7aa127681c448d6b49806f61db2670b61/huggingface_hub-1.4.1.tar.gz", hash = "sha256:b41131ec35e631e7383ab26d6146b8d8972abc8b6309b963b306fbcca87f5ed5", size = 642156, upload-time = "2026-02-06T09:20:03.013Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/b7/8cb61d2eece5fb05a83271da168186721c450eb74e3c31f7ef3169fa475b/huggingface_hub-0.36.2.tar.gz", hash = "sha256:1934304d2fb224f8afa3b87007d58501acfda9215b334eed53072dd5e815ff7a", size = 649782, upload-time = "2026-02-06T09:24:13.098Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, + { url = "https://files.pythonhosted.org/packages/a8/af/48ac8483240de756d2438c380746e7130d1c6f75802ef22f3c6d49982787/huggingface_hub-0.36.2-py3-none-any.whl", hash = "sha256:48f0c8eac16145dfce371e9d2d7772854a4f591bcb56c9cf548accf531d54270", size = 566395, upload-time = "2026-02-06T09:24:11.133Z" }, +] + +[package.optional-dependencies] +inference = [ + { name = "aiohttp" }, ] [[package]] @@ -2188,6 +2800,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, ] +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version >= '3.10' and python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/48/aa685dbf1024c7bd82bede569e3a85f82c32fd3d79ba5fea578f0159571a/jaraco_context-6.1.0-py3-none-any.whl", hash = "sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda", size = 7065, upload-time = "2026-01-13T02:53:53.031Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, +] + +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + [[package]] name = "jieba" version = "0.42.1" @@ -2324,6 +2981,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, ] +[[package]] +name = "jsonref" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -2339,6 +3005,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, ] +[[package]] +name = "jsonschema-path" +version = "0.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pathable", marker = "python_full_version >= '3.10'" }, + { name = "pyyaml", marker = "python_full_version >= '3.10'" }, + { name = "referencing", marker = "python_full_version >= '3.10'" }, + { name = "requests", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/58/3485da8cb93d2f393bce453adeef16896751f14ba3e2024bc21dc9597646/jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8", size = 14810, upload-time = "2025-01-24T14:33:14.652Z" }, +] + [[package]] name = "jsonschema-specifications" version = "2025.9.1" @@ -2351,6 +3032,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] +[[package]] +name = "keyring" +version = "25.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version >= '3.10' and python_full_version < '3.12'" }, + { name = "jaraco-classes", marker = "python_full_version >= '3.10'" }, + { name = "jaraco-context", marker = "python_full_version >= '3.10'" }, + { name = "jaraco-functools", marker = "python_full_version >= '3.10'" }, + { name = "jeepney", marker = "python_full_version >= '3.10' and sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, + { name = "secretstorage", marker = "python_full_version >= '3.10' and sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, +] + [[package]] name = "lia-web" version = "0.3.1" @@ -2363,6 +3062,113 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/8b/b628fc18658f94b3d094708a18b71083cf47628e85cbc6b9edba54d5b2d7/lia_web-0.3.1-py3-none-any.whl", hash = "sha256:e4e6e7a9381e228aca60a6f3d67dbae9a5f4638eced242d931f95797ddba3f8b", size = 5933, upload-time = "2025-12-25T20:41:52.289Z" }, ] +[[package]] +name = "librt" +version = "0.7.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/24/5f3646ff414285e0f7708fa4e946b9bf538345a41d1c375c439467721a5e/librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862", size = 148323, upload-time = "2026-01-14T12:56:16.876Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/13/57b06758a13550c5f09563893b004f98e9537ee6ec67b7df85c3571c8832/librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d", size = 56521, upload-time = "2026-01-14T12:54:40.066Z" }, + { url = "https://files.pythonhosted.org/packages/c2/24/bbea34d1452a10612fb45ac8356f95351ba40c2517e429602160a49d1fd0/librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b", size = 58456, upload-time = "2026-01-14T12:54:41.471Z" }, + { url = "https://files.pythonhosted.org/packages/04/72/a168808f92253ec3a810beb1eceebc465701197dbc7e865a1c9ceb3c22c7/librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d", size = 164392, upload-time = "2026-01-14T12:54:42.843Z" }, + { url = "https://files.pythonhosted.org/packages/14/5c/4c0d406f1b02735c2e7af8ff1ff03a6577b1369b91aa934a9fa2cc42c7ce/librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d", size = 172959, upload-time = "2026-01-14T12:54:44.602Z" }, + { url = "https://files.pythonhosted.org/packages/82/5f/3e85351c523f73ad8d938989e9a58c7f59fb9c17f761b9981b43f0025ce7/librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c", size = 186717, upload-time = "2026-01-14T12:54:45.986Z" }, + { url = "https://files.pythonhosted.org/packages/08/f8/18bfe092e402d00fe00d33aa1e01dda1bd583ca100b393b4373847eade6d/librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c", size = 184585, upload-time = "2026-01-14T12:54:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/4e/fc/f43972ff56fd790a9fa55028a52ccea1875100edbb856b705bd393b601e3/librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d", size = 180497, upload-time = "2026-01-14T12:54:48.946Z" }, + { url = "https://files.pythonhosted.org/packages/e1/3a/25e36030315a410d3ad0b7d0f19f5f188e88d1613d7d3fd8150523ea1093/librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0", size = 200052, upload-time = "2026-01-14T12:54:50.382Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b8/f3a5a1931ae2a6ad92bf6893b9ef44325b88641d58723529e2c2935e8abe/librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85", size = 43477, upload-time = "2026-01-14T12:54:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/fe/91/c4202779366bc19f871b4ad25db10fcfa1e313c7893feb942f32668e8597/librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c", size = 49806, upload-time = "2026-01-14T12:54:53.149Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a3/87ea9c1049f2c781177496ebee29430e4631f439b8553a4969c88747d5d8/librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f", size = 56507, upload-time = "2026-01-14T12:54:54.156Z" }, + { url = "https://files.pythonhosted.org/packages/5e/4a/23bcef149f37f771ad30203d561fcfd45b02bc54947b91f7a9ac34815747/librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac", size = 58455, upload-time = "2026-01-14T12:54:55.978Z" }, + { url = "https://files.pythonhosted.org/packages/22/6e/46eb9b85c1b9761e0f42b6e6311e1cc544843ac897457062b9d5d0b21df4/librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c", size = 164956, upload-time = "2026-01-14T12:54:57.311Z" }, + { url = "https://files.pythonhosted.org/packages/7a/3f/aa7c7f6829fb83989feb7ba9aa11c662b34b4bd4bd5b262f2876ba3db58d/librt-0.7.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:631599598e2c76ded400c0a8722dec09217c89ff64dc54b060f598ed68e7d2a8", size = 174364, upload-time = "2026-01-14T12:54:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/3f/2d/d57d154b40b11f2cb851c4df0d4c4456bacd9b1ccc4ecb593ddec56c1a8b/librt-0.7.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c1ba843ae20db09b9d5c80475376168feb2640ce91cd9906414f23cc267a1ff", size = 188034, upload-time = "2026-01-14T12:55:00.141Z" }, + { url = "https://files.pythonhosted.org/packages/59/f9/36c4dad00925c16cd69d744b87f7001792691857d3b79187e7a673e812fb/librt-0.7.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b5b007bb22ea4b255d3ee39dfd06d12534de2fcc3438567d9f48cdaf67ae1ae3", size = 186295, upload-time = "2026-01-14T12:55:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/23/9b/8a9889d3df5efb67695a67785028ccd58e661c3018237b73ad081691d0cb/librt-0.7.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbd79caaf77a3f590cbe32dc2447f718772d6eea59656a7dcb9311161b10fa75", size = 181470, upload-time = "2026-01-14T12:55:02.492Z" }, + { url = "https://files.pythonhosted.org/packages/43/64/54d6ef11afca01fef8af78c230726a9394759f2addfbf7afc5e3cc032a45/librt-0.7.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87808a8d1e0bd62a01cafc41f0fd6818b5a5d0ca0d8a55326a81643cdda8f873", size = 201713, upload-time = "2026-01-14T12:55:03.919Z" }, + { url = "https://files.pythonhosted.org/packages/2d/29/73e7ed2991330b28919387656f54109139b49e19cd72902f466bd44415fd/librt-0.7.8-cp311-cp311-win32.whl", hash = "sha256:31724b93baa91512bd0a376e7cf0b59d8b631ee17923b1218a65456fa9bda2e7", size = 43803, upload-time = "2026-01-14T12:55:04.996Z" }, + { url = "https://files.pythonhosted.org/packages/3f/de/66766ff48ed02b4d78deea30392ae200bcbd99ae61ba2418b49fd50a4831/librt-0.7.8-cp311-cp311-win_amd64.whl", hash = "sha256:978e8b5f13e52cf23a9e80f3286d7546baa70bc4ef35b51d97a709d0b28e537c", size = 50080, upload-time = "2026-01-14T12:55:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e3/33450438ff3a8c581d4ed7f798a70b07c3206d298cf0b87d3806e72e3ed8/librt-0.7.8-cp311-cp311-win_arm64.whl", hash = "sha256:20e3946863d872f7cabf7f77c6c9d370b8b3d74333d3a32471c50d3a86c0a232", size = 43383, upload-time = "2026-01-14T12:55:07.49Z" }, + { url = "https://files.pythonhosted.org/packages/56/04/79d8fcb43cae376c7adbab7b2b9f65e48432c9eced62ac96703bcc16e09b/librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63", size = 57472, upload-time = "2026-01-14T12:55:08.528Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ba/60b96e93043d3d659da91752689023a73981336446ae82078cddf706249e/librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93", size = 58986, upload-time = "2026-01-14T12:55:09.466Z" }, + { url = "https://files.pythonhosted.org/packages/7c/26/5215e4cdcc26e7be7eee21955a7e13cbf1f6d7d7311461a6014544596fac/librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592", size = 168422, upload-time = "2026-01-14T12:55:10.499Z" }, + { url = "https://files.pythonhosted.org/packages/0f/84/e8d1bc86fa0159bfc24f3d798d92cafd3897e84c7fea7fe61b3220915d76/librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850", size = 177478, upload-time = "2026-01-14T12:55:11.577Z" }, + { url = "https://files.pythonhosted.org/packages/57/11/d0268c4b94717a18aa91df1100e767b010f87b7ae444dafaa5a2d80f33a6/librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62", size = 192439, upload-time = "2026-01-14T12:55:12.7Z" }, + { url = "https://files.pythonhosted.org/packages/8d/56/1e8e833b95fe684f80f8894ae4d8b7d36acc9203e60478fcae599120a975/librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b", size = 191483, upload-time = "2026-01-14T12:55:13.838Z" }, + { url = "https://files.pythonhosted.org/packages/17/48/f11cf28a2cb6c31f282009e2208312aa84a5ee2732859f7856ee306176d5/librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714", size = 185376, upload-time = "2026-01-14T12:55:15.017Z" }, + { url = "https://files.pythonhosted.org/packages/b8/6a/d7c116c6da561b9155b184354a60a3d5cdbf08fc7f3678d09c95679d13d9/librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449", size = 206234, upload-time = "2026-01-14T12:55:16.571Z" }, + { url = "https://files.pythonhosted.org/packages/61/de/1975200bb0285fc921c5981d9978ce6ce11ae6d797df815add94a5a848a3/librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac", size = 44057, upload-time = "2026-01-14T12:55:18.077Z" }, + { url = "https://files.pythonhosted.org/packages/8e/cd/724f2d0b3461426730d4877754b65d39f06a41ac9d0a92d5c6840f72b9ae/librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708", size = 50293, upload-time = "2026-01-14T12:55:19.179Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cf/7e899acd9ee5727ad8160fdcc9994954e79fab371c66535c60e13b968ffc/librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0", size = 43574, upload-time = "2026-01-14T12:55:20.185Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fe/b1f9de2829cf7fc7649c1dcd202cfd873837c5cc2fc9e526b0e7f716c3d2/librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc", size = 57500, upload-time = "2026-01-14T12:55:21.219Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d4/4a60fbe2e53b825f5d9a77325071d61cd8af8506255067bf0c8527530745/librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2", size = 59019, upload-time = "2026-01-14T12:55:22.256Z" }, + { url = "https://files.pythonhosted.org/packages/6a/37/61ff80341ba5159afa524445f2d984c30e2821f31f7c73cf166dcafa5564/librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3", size = 169015, upload-time = "2026-01-14T12:55:23.24Z" }, + { url = "https://files.pythonhosted.org/packages/1c/86/13d4f2d6a93f181ebf2fc953868826653ede494559da8268023fe567fca3/librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6", size = 178161, upload-time = "2026-01-14T12:55:24.826Z" }, + { url = "https://files.pythonhosted.org/packages/88/26/e24ef01305954fc4d771f1f09f3dd682f9eb610e1bec188ffb719374d26e/librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d", size = 193015, upload-time = "2026-01-14T12:55:26.04Z" }, + { url = "https://files.pythonhosted.org/packages/88/a0/92b6bd060e720d7a31ed474d046a69bd55334ec05e9c446d228c4b806ae3/librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e", size = 192038, upload-time = "2026-01-14T12:55:27.208Z" }, + { url = "https://files.pythonhosted.org/packages/06/bb/6f4c650253704279c3a214dad188101d1b5ea23be0606628bc6739456624/librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca", size = 186006, upload-time = "2026-01-14T12:55:28.594Z" }, + { url = "https://files.pythonhosted.org/packages/dc/00/1c409618248d43240cadf45f3efb866837fa77e9a12a71481912135eb481/librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93", size = 206888, upload-time = "2026-01-14T12:55:30.214Z" }, + { url = "https://files.pythonhosted.org/packages/d9/83/b2cfe8e76ff5c1c77f8a53da3d5de62d04b5ebf7cf913e37f8bca43b5d07/librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951", size = 44126, upload-time = "2026-01-14T12:55:31.44Z" }, + { url = "https://files.pythonhosted.org/packages/a9/0b/c59d45de56a51bd2d3a401fc63449c0ac163e4ef7f523ea8b0c0dee86ec5/librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34", size = 50262, upload-time = "2026-01-14T12:55:33.01Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b9/973455cec0a1ec592395250c474164c4a58ebf3e0651ee920fef1a2623f1/librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09", size = 43600, upload-time = "2026-01-14T12:55:34.054Z" }, + { url = "https://files.pythonhosted.org/packages/1a/73/fa8814c6ce2d49c3827829cadaa1589b0bf4391660bd4510899393a23ebc/librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418", size = 57049, upload-time = "2026-01-14T12:55:35.056Z" }, + { url = "https://files.pythonhosted.org/packages/53/fe/f6c70956da23ea235fd2e3cc16f4f0b4ebdfd72252b02d1164dd58b4e6c3/librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611", size = 58689, upload-time = "2026-01-14T12:55:36.078Z" }, + { url = "https://files.pythonhosted.org/packages/1f/4d/7a2481444ac5fba63050d9abe823e6bc16896f575bfc9c1e5068d516cdce/librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758", size = 166808, upload-time = "2026-01-14T12:55:37.595Z" }, + { url = "https://files.pythonhosted.org/packages/ac/3c/10901d9e18639f8953f57c8986796cfbf4c1c514844a41c9197cf87cb707/librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea", size = 175614, upload-time = "2026-01-14T12:55:38.756Z" }, + { url = "https://files.pythonhosted.org/packages/db/01/5cbdde0951a5090a80e5ba44e6357d375048123c572a23eecfb9326993a7/librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac", size = 189955, upload-time = "2026-01-14T12:55:39.939Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b4/e80528d2f4b7eaf1d437fcbd6fc6ba4cbeb3e2a0cb9ed5a79f47c7318706/librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398", size = 189370, upload-time = "2026-01-14T12:55:41.057Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ab/938368f8ce31a9787ecd4becb1e795954782e4312095daf8fd22420227c8/librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81", size = 183224, upload-time = "2026-01-14T12:55:42.328Z" }, + { url = "https://files.pythonhosted.org/packages/3c/10/559c310e7a6e4014ac44867d359ef8238465fb499e7eb31b6bfe3e3f86f5/librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83", size = 203541, upload-time = "2026-01-14T12:55:43.501Z" }, + { url = "https://files.pythonhosted.org/packages/f8/db/a0db7acdb6290c215f343835c6efda5b491bb05c3ddc675af558f50fdba3/librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d", size = 40657, upload-time = "2026-01-14T12:55:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/72/e0/4f9bdc2a98a798511e81edcd6b54fe82767a715e05d1921115ac70717f6f/librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44", size = 46835, upload-time = "2026-01-14T12:55:45.655Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3d/59c6402e3dec2719655a41ad027a7371f8e2334aa794ed11533ad5f34969/librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce", size = 39885, upload-time = "2026-01-14T12:55:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9c/2481d80950b83085fb14ba3c595db56330d21bbc7d88a19f20165f3538db/librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f", size = 59161, upload-time = "2026-01-14T12:55:48.45Z" }, + { url = "https://files.pythonhosted.org/packages/96/79/108df2cfc4e672336765d54e3ff887294c1cc36ea4335c73588875775527/librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde", size = 61008, upload-time = "2026-01-14T12:55:49.527Z" }, + { url = "https://files.pythonhosted.org/packages/46/f2/30179898f9994a5637459d6e169b6abdc982012c0a4b2d4c26f50c06f911/librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e", size = 187199, upload-time = "2026-01-14T12:55:50.587Z" }, + { url = "https://files.pythonhosted.org/packages/b4/da/f7563db55cebdc884f518ba3791ad033becc25ff68eb70902b1747dc0d70/librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b", size = 198317, upload-time = "2026-01-14T12:55:51.991Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6c/4289acf076ad371471fa86718c30ae353e690d3de6167f7db36f429272f1/librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666", size = 210334, upload-time = "2026-01-14T12:55:53.682Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7f/377521ac25b78ac0a5ff44127a0360ee6d5ddd3ce7327949876a30533daa/librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581", size = 211031, upload-time = "2026-01-14T12:55:54.827Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b1/e1e96c3e20b23d00cf90f4aad48f0deb4cdfec2f0ed8380d0d85acf98bbf/librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a", size = 204581, upload-time = "2026-01-14T12:55:56.811Z" }, + { url = "https://files.pythonhosted.org/packages/43/71/0f5d010e92ed9747e14bef35e91b6580533510f1e36a8a09eb79ee70b2f0/librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca", size = 224731, upload-time = "2026-01-14T12:55:58.175Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365", size = 41173, upload-time = "2026-01-14T12:55:59.315Z" }, + { url = "https://files.pythonhosted.org/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32", size = 47668, upload-time = "2026-01-14T12:56:00.261Z" }, + { url = "https://files.pythonhosted.org/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06", size = 40550, upload-time = "2026-01-14T12:56:01.542Z" }, + { url = "https://files.pythonhosted.org/packages/3b/9b/2668bb01f568bc89ace53736df950845f8adfcacdf6da087d5cef12110cb/librt-0.7.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c7e8f88f79308d86d8f39c491773cbb533d6cb7fa6476f35d711076ee04fceb6", size = 56680, upload-time = "2026-01-14T12:56:02.602Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d4/dbb3edf2d0ec4ba08dcaf1865833d32737ad208962d4463c022cea6e9d3c/librt-0.7.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:389bd25a0db916e1d6bcb014f11aa9676cedaa485e9ec3752dfe19f196fd377b", size = 58612, upload-time = "2026-01-14T12:56:03.616Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c9/64b029de4ac9901fcd47832c650a0fd050555a452bd455ce8deddddfbb9f/librt-0.7.8-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73fd300f501a052f2ba52ede721232212f3b06503fa12665408ecfc9d8fd149c", size = 163654, upload-time = "2026-01-14T12:56:04.975Z" }, + { url = "https://files.pythonhosted.org/packages/81/5c/95e2abb1b48eb8f8c7fc2ae945321a6b82777947eb544cc785c3f37165b2/librt-0.7.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d772edc6a5f7835635c7562f6688e031f0b97e31d538412a852c49c9a6c92d5", size = 172477, upload-time = "2026-01-14T12:56:06.103Z" }, + { url = "https://files.pythonhosted.org/packages/7e/27/9bdf12e05b0eb089dd008d9c8aabc05748aad9d40458ade5e627c9538158/librt-0.7.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde8a130bd0f239e45503ab39fab239ace094d63ee1d6b67c25a63d741c0f71", size = 186220, upload-time = "2026-01-14T12:56:09.958Z" }, + { url = "https://files.pythonhosted.org/packages/53/6a/c3774f4cc95e68ed444a39f2c8bd383fd18673db7d6b98cfa709f6634b93/librt-0.7.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fdec6e2368ae4f796fc72fad7fd4bd1753715187e6d870932b0904609e7c878e", size = 183841, upload-time = "2026-01-14T12:56:11.109Z" }, + { url = "https://files.pythonhosted.org/packages/58/6b/48702c61cf83e9c04ad5cec8cad7e5e22a2cde23a13db8ef341598897ddd/librt-0.7.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00105e7d541a8f2ee5be52caacea98a005e0478cfe78c8080fbb7b5d2b340c63", size = 179751, upload-time = "2026-01-14T12:56:12.278Z" }, + { url = "https://files.pythonhosted.org/packages/35/87/5f607fc73a131d4753f4db948833063c6aad18e18a4e6fbf64316c37ae65/librt-0.7.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c6f8947d3dfd7f91066c5b4385812c18be26c9d5a99ca56667547f2c39149d94", size = 199319, upload-time = "2026-01-14T12:56:13.425Z" }, + { url = "https://files.pythonhosted.org/packages/6e/cc/b7c5ac28ae0f0645a9681248bae4ede665bba15d6f761c291853c5c5b78e/librt-0.7.8-cp39-cp39-win32.whl", hash = "sha256:41d7bb1e07916aeb12ae4a44e3025db3691c4149ab788d0315781b4d29b86afb", size = 43434, upload-time = "2026-01-14T12:56:14.781Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5d/dce0c92f786495adf2c1e6784d9c50a52fb7feb1cfb17af97a08281a6e82/librt-0.7.8-cp39-cp39-win_amd64.whl", hash = "sha256:e90a8e237753c83b8e484d478d9a996dc5e39fd5bd4c6ce32563bc8123f132be", size = 49801, upload-time = "2026-01-14T12:56:15.827Z" }, +] + +[[package]] +name = "logfire" +version = "4.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-instrumentation", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, + { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version == '3.10.*'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/29/4386b331b8aecad429c043bbd1b7684cdb56ff9e11a5bd96845483dc0968/logfire-4.22.0.tar.gz", hash = "sha256:284b3b955c7515d4428dbc1e04784c3e652e62acf7597bd64a0aa9ecb6a7dedd", size = 654771, upload-time = "2026-02-04T12:17:57.635Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/ce/24a598c271d9631b09fb42f86f1e6d63b50647ecf0ce438d368a1e1af66b/logfire-4.22.0-py3-none-any.whl", hash = "sha256:9a0d20885613efe4bc9efcfa19a7943a6c642bc21339d926c51fcc74c0d083d6", size = 242637, upload-time = "2026-02-04T12:17:54.787Z" }, +] + +[package.optional-dependencies] +httpx = [ + { name = "opentelemetry-instrumentation-httpx", marker = "python_full_version >= '3.10'" }, +] + [[package]] name = "logfire-api" version = "4.22.0" @@ -2372,6 +3178,91 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/93/4e8395f3e4b1951b1de8d06cb7d7ef1105efd294ea3443bf39b3594390af/logfire_api-4.22.0-py3-none-any.whl", hash = "sha256:9fd2a2dac9cc3adf71ad4dac7bc9d26af326a5aa87445be90026048d22b92a8e", size = 98543, upload-time = "2026-02-04T12:17:56.365Z" }, ] +[[package]] +name = "lupa" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/15/713cab5d0dfa4858f83b99b3e0329072df33dc14fc3ebbaa017e0f9755c4/lupa-2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b3dabda836317e63c5ad052826e156610f356a04b3003dfa0dbe66b5d54d671", size = 954828, upload-time = "2025-10-24T07:17:15.726Z" }, + { url = "https://files.pythonhosted.org/packages/2e/71/704740cbc6e587dd6cc8dabf2f04820ac6a671784e57cc3c29db795476db/lupa-2.6-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8726d1c123bbe9fbb974ce29825e94121824e66003038ff4532c14cc2ed0c51c", size = 1919259, upload-time = "2025-10-24T07:17:18.586Z" }, + { url = "https://files.pythonhosted.org/packages/eb/18/f248341c423c5d48837e35584c6c3eb4acab7e722b6057d7b3e28e42dae8/lupa-2.6-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:f4e159e7d814171199b246f9235ca8961f6461ea8c1165ab428afa13c9289a94", size = 984998, upload-time = "2025-10-24T07:17:20.428Z" }, + { url = "https://files.pythonhosted.org/packages/44/1e/8a4bd471e018aad76bcb9455d298c2c96d82eced20f2ae8fcec8cd800948/lupa-2.6-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:202160e80dbfddfb79316692a563d843b767e0f6787bbd1c455f9d54052efa6c", size = 1174871, upload-time = "2025-10-24T07:17:22.755Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5c/3a3f23fd6a91b0986eea1ceaf82ad3f9b958fe3515a9981fb9c4eb046c8b/lupa-2.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5deede7c5b36ab64f869dae4831720428b67955b0bb186c8349cf6ea121c852b", size = 1057471, upload-time = "2025-10-24T07:17:24.908Z" }, + { url = "https://files.pythonhosted.org/packages/45/ac/01be1fed778fb0c8f46ee8cbe344e4d782f6806fac12717f08af87aa4355/lupa-2.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86f04901f920bbf7c0cac56807dc9597e42347123e6f1f3ca920f15f54188ce5", size = 2100592, upload-time = "2025-10-24T07:17:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/3f/6c/1a05bb873e30830f8574e10cd0b4cdbc72e9dbad2a09e25810b5e3b1f75d/lupa-2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6deef8f851d6afb965c84849aa5b8c38856942df54597a811ce0369ced678610", size = 1081396, upload-time = "2025-10-24T07:17:29.064Z" }, + { url = "https://files.pythonhosted.org/packages/a2/c2/a19dd80d6dc98b39bbf8135b8198e38aa7ca3360b720eac68d1d7e9286b5/lupa-2.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:21f2b5549681c2a13b1170a26159d30875d367d28f0247b81ca347222c755038", size = 1192007, upload-time = "2025-10-24T07:17:31.362Z" }, + { url = "https://files.pythonhosted.org/packages/4f/43/e1b297225c827f55752e46fdbfb021c8982081b0f24490e42776ea69ae3b/lupa-2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:66eea57630eab5e6f49fdc5d7811c0a2a41f2011be4ea56a087ea76112011eb7", size = 2196661, upload-time = "2025-10-24T07:17:33.484Z" }, + { url = "https://files.pythonhosted.org/packages/2e/8f/2272d429a7fa9dc8dbd6e9c5c9073a03af6007eb22a4c78829fec6a34b80/lupa-2.6-cp310-cp310-win32.whl", hash = "sha256:60a403de8cab262a4fe813085dd77010effa6e2eb1886db2181df803140533b1", size = 1412738, upload-time = "2025-10-24T07:17:35.11Z" }, + { url = "https://files.pythonhosted.org/packages/35/2a/1708911271dd49ad87b4b373b5a4b0e0a0516d3d2af7b76355946c7ee171/lupa-2.6-cp310-cp310-win_amd64.whl", hash = "sha256:e4656a39d93dfa947cf3db56dc16c7916cb0cc8024acd3a952071263f675df64", size = 1656898, upload-time = "2025-10-24T07:17:36.949Z" }, + { url = "https://files.pythonhosted.org/packages/ca/29/1f66907c1ebf1881735afa695e646762c674f00738ebf66d795d59fc0665/lupa-2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d988c0f9331b9f2a5a55186701a25444ab10a1432a1021ee58011499ecbbdd5", size = 962875, upload-time = "2025-10-24T07:17:39.107Z" }, + { url = "https://files.pythonhosted.org/packages/e6/67/4a748604be360eb9c1c215f6a0da921cd1a2b44b2c5951aae6fb83019d3a/lupa-2.6-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ebe1bbf48259382c72a6fe363dea61a0fd6fe19eab95e2ae881e20f3654587bf", size = 1935390, upload-time = "2025-10-24T07:17:41.427Z" }, + { url = "https://files.pythonhosted.org/packages/ac/0c/8ef9ee933a350428b7bdb8335a37ef170ab0bb008bbf9ca8f4f4310116b6/lupa-2.6-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:a8fcee258487cf77cdd41560046843bb38c2e18989cd19671dd1e2596f798306", size = 992193, upload-time = "2025-10-24T07:17:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/65/46/e6c7facebdb438db8a65ed247e56908818389c1a5abbf6a36aab14f1057d/lupa-2.6-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:561a8e3be800827884e767a694727ed8482d066e0d6edfcbf423b05e63b05535", size = 1165844, upload-time = "2025-10-24T07:17:45.437Z" }, + { url = "https://files.pythonhosted.org/packages/1c/26/9f1154c6c95f175ccbf96aa96c8f569c87f64f463b32473e839137601a8b/lupa-2.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af880a62d47991cae78b8e9905c008cbfdc4a3a9723a66310c2634fc7644578c", size = 1048069, upload-time = "2025-10-24T07:17:47.181Z" }, + { url = "https://files.pythonhosted.org/packages/68/67/2cc52ab73d6af81612b2ea24c870d3fa398443af8e2875e5befe142398b1/lupa-2.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80b22923aa4023c86c0097b235615f89d469a0c4eee0489699c494d3367c4c85", size = 2079079, upload-time = "2025-10-24T07:17:49.755Z" }, + { url = "https://files.pythonhosted.org/packages/2e/dc/f843f09bbf325f6e5ee61730cf6c3409fc78c010d968c7c78acba3019ca7/lupa-2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:153d2cc6b643f7efb9cfc0c6bb55ec784d5bac1a3660cfc5b958a7b8f38f4a75", size = 1071428, upload-time = "2025-10-24T07:17:51.991Z" }, + { url = "https://files.pythonhosted.org/packages/2e/60/37533a8d85bf004697449acb97ecdacea851acad28f2ad3803662487dd2a/lupa-2.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3fa8777e16f3ded50b72967dc17e23f5a08e4f1e2c9456aff2ebdb57f5b2869f", size = 1181756, upload-time = "2025-10-24T07:17:53.752Z" }, + { url = "https://files.pythonhosted.org/packages/e4/f2/cf29b20dbb4927b6a3d27c339ac5d73e74306ecc28c8e2c900b2794142ba/lupa-2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8dbdcbe818c02a2f56f5ab5ce2de374dab03e84b25266cfbaef237829bc09b3f", size = 2175687, upload-time = "2025-10-24T07:17:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/94/7c/050e02f80c7131b63db1474bff511e63c545b5a8636a24cbef3fc4da20b6/lupa-2.6-cp311-cp311-win32.whl", hash = "sha256:defaf188fde8f7a1e5ce3a5e6d945e533b8b8d547c11e43b96c9b7fe527f56dc", size = 1412592, upload-time = "2025-10-24T07:17:59.062Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/6f2af98aa5d771cea661f66c8eb8f53772ec1ab1dfbce24126cfcd189436/lupa-2.6-cp311-cp311-win_amd64.whl", hash = "sha256:9505ae600b5c14f3e17e70f87f88d333717f60411faca1ddc6f3e61dce85fa9e", size = 1669194, upload-time = "2025-10-24T07:18:01.647Z" }, + { url = "https://files.pythonhosted.org/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" }, + { url = "https://files.pythonhosted.org/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" }, + { url = "https://files.pythonhosted.org/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" }, + { url = "https://files.pythonhosted.org/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" }, + { url = "https://files.pythonhosted.org/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" }, + { url = "https://files.pythonhosted.org/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" }, + { url = "https://files.pythonhosted.org/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" }, + { url = "https://files.pythonhosted.org/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" }, + { url = "https://files.pythonhosted.org/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" }, + { url = "https://files.pythonhosted.org/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" }, + { url = "https://files.pythonhosted.org/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" }, + { url = "https://files.pythonhosted.org/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" }, + { url = "https://files.pythonhosted.org/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" }, + { url = "https://files.pythonhosted.org/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" }, + { url = "https://files.pythonhosted.org/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" }, + { url = "https://files.pythonhosted.org/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" }, + { url = "https://files.pythonhosted.org/packages/66/9d/d9427394e54d22a35d1139ef12e845fd700d4872a67a34db32516170b746/lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1", size = 953818, upload-time = "2025-10-24T07:18:53.378Z" }, + { url = "https://files.pythonhosted.org/packages/10/41/27bbe81953fb2f9ecfced5d9c99f85b37964cfaf6aa8453bb11283983721/lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18", size = 1915850, upload-time = "2025-10-24T07:18:55.259Z" }, + { url = "https://files.pythonhosted.org/packages/a3/98/f9ff60db84a75ba8725506bbf448fb085bc77868a021998ed2a66d920568/lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe", size = 982344, upload-time = "2025-10-24T07:18:57.05Z" }, + { url = "https://files.pythonhosted.org/packages/41/f7/f39e0f1c055c3b887d86b404aaf0ca197b5edfd235a8b81b45b25bac7fc3/lupa-2.6-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad", size = 1156543, upload-time = "2025-10-24T07:18:59.251Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9c/59e6cffa0d672d662ae17bd7ac8ecd2c89c9449dee499e3eb13ca9cd10d9/lupa-2.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8", size = 1047974, upload-time = "2025-10-24T07:19:01.449Z" }, + { url = "https://files.pythonhosted.org/packages/23/c6/a04e9cef7c052717fcb28fb63b3824802488f688391895b618e39be0f684/lupa-2.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6", size = 2073458, upload-time = "2025-10-24T07:19:03.369Z" }, + { url = "https://files.pythonhosted.org/packages/e6/10/824173d10f38b51fc77785228f01411b6ca28826ce27404c7c912e0e442c/lupa-2.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134", size = 1067683, upload-time = "2025-10-24T07:19:06.2Z" }, + { url = "https://files.pythonhosted.org/packages/b6/dc/9692fbcf3c924d9c4ece2d8d2f724451ac2e09af0bd2a782db1cef34e799/lupa-2.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3", size = 1171892, upload-time = "2025-10-24T07:19:08.544Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/e318b628d4643c278c96ab3ddea07fc36b075a57383c837f5b11e537ba9d/lupa-2.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9", size = 2166641, upload-time = "2025-10-24T07:19:10.485Z" }, + { url = "https://files.pythonhosted.org/packages/12/f7/a6f9ec2806cf2d50826980cdb4b3cffc7691dc6f95e13cc728846d5cb793/lupa-2.6-cp314-cp314-win32.whl", hash = "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f", size = 1456857, upload-time = "2025-10-24T07:19:37.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/de/df71896f25bdc18360fdfa3b802cd7d57d7fede41a0e9724a4625b412c85/lupa-2.6-cp314-cp314-win_amd64.whl", hash = "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67", size = 1731191, upload-time = "2025-10-24T07:19:40.281Z" }, + { url = "https://files.pythonhosted.org/packages/47/3c/a1f23b01c54669465f5f4c4083107d496fbe6fb45998771420e9aadcf145/lupa-2.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf", size = 999343, upload-time = "2025-10-24T07:19:12.519Z" }, + { url = "https://files.pythonhosted.org/packages/c5/6d/501994291cb640bfa2ccf7f554be4e6914afa21c4026bd01bff9ca8aac57/lupa-2.6-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142", size = 2000730, upload-time = "2025-10-24T07:19:14.869Z" }, + { url = "https://files.pythonhosted.org/packages/53/a5/457ffb4f3f20469956c2d4c4842a7675e884efc895b2f23d126d23e126cc/lupa-2.6-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953", size = 1021553, upload-time = "2025-10-24T07:19:17.123Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/36bb5a5d0960f2a5c7c700e0819abb76fd9bf9c1d8a66e5106416d6e9b14/lupa-2.6-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983", size = 1133275, upload-time = "2025-10-24T07:19:20.51Z" }, + { url = "https://files.pythonhosted.org/packages/19/86/202ff4429f663013f37d2229f6176ca9f83678a50257d70f61a0a97281bf/lupa-2.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa", size = 1038441, upload-time = "2025-10-24T07:19:22.509Z" }, + { url = "https://files.pythonhosted.org/packages/a7/42/d8125f8e420714e5b52e9c08d88b5329dfb02dcca731b4f21faaee6cc5b5/lupa-2.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7", size = 2058324, upload-time = "2025-10-24T07:19:24.979Z" }, + { url = "https://files.pythonhosted.org/packages/2b/2c/47bf8b84059876e877a339717ddb595a4a7b0e8740bacae78ba527562e1c/lupa-2.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f", size = 1060250, upload-time = "2025-10-24T07:19:27.262Z" }, + { url = "https://files.pythonhosted.org/packages/c2/06/d88add2b6406ca1bdec99d11a429222837ca6d03bea42ca75afa169a78cb/lupa-2.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c", size = 1151126, upload-time = "2025-10-24T07:19:29.522Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a0/89e6a024c3b4485b89ef86881c9d55e097e7cb0bdb74efb746f2fa6a9a76/lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80", size = 2153693, upload-time = "2025-10-24T07:19:31.379Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/a0f007dc58fc1bbf51fb85dcc82fcb1f21b8c4261361de7dab0e3d8521ef/lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291", size = 1590104, upload-time = "2025-10-24T07:19:33.514Z" }, + { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818, upload-time = "2025-10-24T07:19:36.039Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c5/918ed6c3af793764bae155d68df47bab2635ab7c94dee3dbb5d9c6d5ba38/lupa-2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8897dc6c3249786b2cdf2f83324febb436193d4581b6a71dea49f77bf8b19bb0", size = 956718, upload-time = "2025-10-24T07:20:03.086Z" }, + { url = "https://files.pythonhosted.org/packages/da/91/0ca797da854478225c0f6a8fc3c500a2f5c11826d732735beb5dffff9e85/lupa-2.6-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:4446396ca3830be0c106c70db4b4f622c37b2d447874c07952cafb9c57949a4a", size = 1923934, upload-time = "2025-10-24T07:20:05.428Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7f/98a6a2535285d43457eb665822ab08447e2196b614db3152772d457ca426/lupa-2.6-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:5826e687c89995a6eaafeae242071ba16448eec1a9ee8e17ed48551b5d1e21c2", size = 987286, upload-time = "2025-10-24T07:20:07.338Z" }, + { url = "https://files.pythonhosted.org/packages/5f/50/edad7c180ab28aa543e6c3895e56a2c7a6ff92140a283316e6086f118552/lupa-2.6-cp39-cp39-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:5871935cb36d1d22f9c04ac0db75c06751bd95edcfa0d9309f732de908e297a9", size = 1176541, upload-time = "2025-10-24T07:20:09.305Z" }, + { url = "https://files.pythonhosted.org/packages/24/b3/27a0ec4c73011e86f9bd2eada010062308a4ed32921898d066ae54e064e1/lupa-2.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:43eb6e43ea8512d0d65b995d36dd9d77aa02598035e25b84c23a1b58700c9fb2", size = 1058981, upload-time = "2025-10-24T07:20:11.7Z" }, + { url = "https://files.pythonhosted.org/packages/a4/12/d55d45a8c253e7981f59ae920bac49dbd49888954b25fd1eb3a7be1321db/lupa-2.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:559714053018d9885cc8c36a33c5b7eb9aad30fb6357719cac3ce4dc6b39157e", size = 2103336, upload-time = "2025-10-24T07:20:13.71Z" }, + { url = "https://files.pythonhosted.org/packages/ab/17/058cc212c22d6a25990226afd02c741b2813b5f325396a9180b4accb70ac/lupa-2.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:57ac88a00ce59bd9d4ddcd4fca8e02564765725f5068786b011c9d1be3de20c5", size = 1083209, upload-time = "2025-10-24T07:20:15.587Z" }, + { url = "https://files.pythonhosted.org/packages/e6/01/8ca3a56a4e127784a15f0c7ec1f67e9894c2e9d4bf402389ddda4ea8081b/lupa-2.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:b683fbd867c2e54c44a686361b75eee7e7a790da55afdbe89f1f23b106de0274", size = 1193077, upload-time = "2025-10-24T07:20:17.857Z" }, + { url = "https://files.pythonhosted.org/packages/07/1b/c7fe79bcda6d489306bb7c1a9b4d545b7f0930b9ce80080643fc39b3fdc9/lupa-2.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d2f656903a2ed2e074bf2b7d300968028dfa327a45b055be8e3b51ef0b82f9bf", size = 2198584, upload-time = "2025-10-24T07:20:20.468Z" }, + { url = "https://files.pythonhosted.org/packages/9e/df/3f7631eea3478ac3868cbcb2763c1a4e2f7b875fcb2683f956bf7aabf65f/lupa-2.6-cp39-cp39-win32.whl", hash = "sha256:bf28f68ae231b72008523ab5ac23835ba0f76e0e99ec38b59766080a84eb596a", size = 1414693, upload-time = "2025-10-24T07:20:23.477Z" }, + { url = "https://files.pythonhosted.org/packages/08/e0/3fd9617814663129fa4a9b33a980c3fe344297337cb550c738f87f730f6b/lupa-2.6-cp39-cp39-win_amd64.whl", hash = "sha256:b4b2e9b3795a9897cf6cfcc58d08210fdc0d13ab47c9a0e13858c68932d8353c", size = 1658877, upload-time = "2025-10-24T07:20:27.086Z" }, +] + [[package]] name = "markdown" version = "3.9" @@ -2542,7 +3433,7 @@ wheels = [ [[package]] name = "mcp" -version = "1.19.0" +version = "1.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "python_full_version >= '3.10'" }, @@ -2551,15 +3442,18 @@ dependencies = [ { name = "jsonschema", marker = "python_full_version >= '3.10'" }, { name = "pydantic", marker = "python_full_version >= '3.10'" }, { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pyjwt", extra = ["crypto"], marker = "python_full_version >= '3.10'" }, { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pywin32", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, { name = "sse-starlette", marker = "python_full_version >= '3.10'" }, - { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/2b/916852a5668f45d8787378461eaa1244876d77575ffef024483c94c0649c/mcp-1.19.0.tar.gz", hash = "sha256:213de0d3cd63f71bc08ffe9cc8d4409cc87acffd383f6195d2ce0457c021b5c1", size = 444163, upload-time = "2025-10-24T01:11:15.839Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/a3/3e71a875a08b6a830b88c40bc413bff01f1650f1efe8a054b5e90a9d4f56/mcp-1.19.0-py3-none-any.whl", hash = "sha256:f5907fe1c0167255f916718f376d05f09a830a215327a3ccdd5ec8a519f2e572", size = 170105, upload-time = "2025-10-24T01:11:14.151Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d9/eaa1f80170d2b7c5ba23f3b59f766f3a0bb41155fbc32a69adfa1adaaef9/mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca", size = 233615, upload-time = "2026-01-24T19:40:30.652Z" }, ] [[package]] @@ -2695,7 +3589,7 @@ wheels = [ [[package]] name = "mkdocs-material" -version = "9.7.0" +version = "9.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "babel" }, @@ -2711,9 +3605,9 @@ dependencies = [ { name = "pymdown-extensions" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9c/3b/111b84cd6ff28d9e955b5f799ef217a17bc1684ac346af333e6100e413cb/mkdocs_material-9.7.0.tar.gz", hash = "sha256:602b359844e906ee402b7ed9640340cf8a474420d02d8891451733b6b02314ec", size = 4094546, upload-time = "2025-11-11T08:49:09.73Z" } +sdist = { url = "https://files.pythonhosted.org/packages/27/e2/2ffc356cd72f1473d07c7719d82a8f2cbd261666828614ecb95b12169f41/mkdocs_material-9.7.1.tar.gz", hash = "sha256:89601b8f2c3e6c6ee0a918cc3566cb201d40bf37c3cd3c2067e26fadb8cce2b8", size = 4094392, upload-time = "2025-12-18T09:49:00.308Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/87/eefe8d5e764f4cf50ed91b943f8e8f96b5efd65489d8303b7a36e2e79834/mkdocs_material-9.7.0-py3-none-any.whl", hash = "sha256:da2866ea53601125ff5baa8aa06404c6e07af3c5ce3d5de95e3b52b80b442887", size = 9283770, upload-time = "2025-11-11T08:49:06.26Z" }, + { url = "https://files.pythonhosted.org/packages/3e/32/ed071cb721aca8c227718cffcf7bd539620e9799bbf2619e90c757bfd030/mkdocs_material-9.7.1-py3-none-any.whl", hash = "sha256:3f6100937d7d731f87f1e3e3b021c97f7239666b9ba1151ab476cabb96c60d5c", size = 9297166, upload-time = "2025-12-18T09:48:56.664Z" }, ] [[package]] @@ -2741,15 +3635,17 @@ wheels = [ name = "mkdocstrings" version = "0.30.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, - { name = "jinja2" }, + { name = "jinja2", marker = "python_full_version < '3.10'" }, { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "markupsafe" }, - { name = "mkdocs" }, - { name = "mkdocs-autorefs" }, - { name = "pymdown-extensions" }, + { name = "markupsafe", marker = "python_full_version < '3.10'" }, + { name = "mkdocs", marker = "python_full_version < '3.10'" }, + { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, + { name = "pymdown-extensions", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c5/33/2fa3243439f794e685d3e694590d28469a9b8ea733af4b48c250a3ffc9a0/mkdocstrings-0.30.1.tar.gz", hash = "sha256:84a007aae9b707fb0aebfc9da23db4b26fc9ab562eb56e335e9ec480cb19744f", size = 106350, upload-time = "2025-09-19T10:49:26.446Z" } wheels = [ @@ -2759,25 +3655,50 @@ wheels = [ [package.optional-dependencies] python = [ { name = "mkdocstrings-python", version = "1.18.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings-python", version = "2.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] [[package]] -name = "mkdocstrings-python" -version = "1.18.2" +name = "mkdocstrings" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.10'", + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", ] dependencies = [ - { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, + { name = "jinja2", marker = "python_full_version >= '3.10'" }, + { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markupsafe", marker = "python_full_version >= '3.10'" }, + { name = "mkdocs", marker = "python_full_version >= '3.10'" }, + { name = "mkdocs-autorefs", marker = "python_full_version >= '3.10'" }, + { name = "pymdown-extensions", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" } +sdist = { url = "https://files.pythonhosted.org/packages/63/4d/1ca8a9432579184599714aaeb36591414cc3d3bfd9d494f6db540c995ae4/mkdocstrings-1.0.2.tar.gz", hash = "sha256:48edd0ccbcb9e30a3121684e165261a9d6af4d63385fc4f39a54a49ac3b32ea8", size = 101048, upload-time = "2026-01-24T15:57:25.735Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" }, + { url = "https://files.pythonhosted.org/packages/57/32/407a9a5fdd7d8ecb4af8d830b9bcdf47ea68f916869b3f44bac31f081250/mkdocstrings-1.0.2-py3-none-any.whl", hash = "sha256:41897815a8026c3634fe5d51472c3a569f92ded0ad8c7a640550873eea3b6817", size = 35443, upload-time = "2026-01-24T15:57:23.933Z" }, +] + +[package.optional-dependencies] +python = [ + { name = "mkdocstrings-python", version = "2.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] + +[[package]] +name = "mkdocstrings-python" +version = "1.18.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, + { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" }, ] [[package]] @@ -2791,7 +3712,7 @@ resolution-markers = [ dependencies = [ { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "mkdocs-autorefs", marker = "python_full_version >= '3.10'" }, - { name = "mkdocstrings", marker = "python_full_version >= '3.10'" }, + { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/24/75/d30af27a2906f00eb90143470272376d728521997800f5dce5b340ba35bc/mkdocstrings_python-2.0.1.tar.gz", hash = "sha256:843a562221e6a471fefdd4b45cc6c22d2607ccbad632879234fa9692e9cf7732", size = 199345, upload-time = "2025-12-03T14:26:11.755Z" } @@ -2799,48 +3720,221 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/06/c5f8deba7d2cbdfa7967a716ae801aa9ca5f734b8f54fd473ef77a088dbe/mkdocstrings_python-2.0.1-py3-none-any.whl", hash = "sha256:66ecff45c5f8b71bf174e11d49afc845c2dfc7fc0ab17a86b6b337e0f24d8d90", size = 105055, upload-time = "2025-12-03T14:26:10.184Z" }, ] +[[package]] +name = "more-itertools" +version = "10.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, + { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, + { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, + { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, + { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, + { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, + { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, + { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, + { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, + { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, + { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, + { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, + { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, + { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, + { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, + { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, + { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, + { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, + { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, + { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, + { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, + { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, + { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, + { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, + { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, + { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, + { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, + { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, + { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, + { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, + { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" }, + { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" }, + { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" }, + { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" }, + { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" }, + { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" }, + { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" }, + { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" }, + { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ee/74525ebe3eb5fddcd6735fc03cbea3feeed4122b53bc798ac32d297ac9ae/multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f", size = 77107, upload-time = "2026-01-26T02:46:12.608Z" }, + { url = "https://files.pythonhosted.org/packages/f0/9a/ce8744e777a74b3050b1bf56be3eed1053b3457302ea055f1ea437200a23/multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358", size = 44943, upload-time = "2026-01-26T02:46:14.016Z" }, + { url = "https://files.pythonhosted.org/packages/83/9c/1d2a283d9c6f31e260cb6c2fccadc3edcf6c4c14ee0929cd2af4d2606dd7/multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5", size = 44603, upload-time = "2026-01-26T02:46:15.391Z" }, + { url = "https://files.pythonhosted.org/packages/87/9d/3b186201671583d8e8d6d79c07481a5aafd0ba7575e3d8566baec80c1e82/multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0", size = 240573, upload-time = "2026-01-26T02:46:16.783Z" }, + { url = "https://files.pythonhosted.org/packages/42/7d/a52f5d4d0754311d1ac78478e34dff88de71259a8585e05ee14e5f877caf/multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8", size = 240106, upload-time = "2026-01-26T02:46:18.432Z" }, + { url = "https://files.pythonhosted.org/packages/84/9f/d80118e6c30ff55b7d171bdc5520aad4b9626e657520b8d7c8ca8c2fad12/multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0", size = 219418, upload-time = "2026-01-26T02:46:20.526Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bd/896e60b3457f194de77c7de64f9acce9f75da0518a5230ce1df534f6747b/multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f", size = 252124, upload-time = "2026-01-26T02:46:22.157Z" }, + { url = "https://files.pythonhosted.org/packages/f4/de/ba6b30447c36a37078d0ba604aa12c1a52887af0c355236ca6e0a9d5286f/multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f", size = 249402, upload-time = "2026-01-26T02:46:23.718Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b2/50a383c96230e432895a2fd3bcfe1b65785899598259d871d5de6b93180c/multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e", size = 240346, upload-time = "2026-01-26T02:46:25.393Z" }, + { url = "https://files.pythonhosted.org/packages/89/37/16d391fd8da544b1489306e38a46785fa41dd0f0ef766837ed7d4676dde0/multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2", size = 237010, upload-time = "2026-01-26T02:46:27.408Z" }, + { url = "https://files.pythonhosted.org/packages/b0/24/3152ee026eda86d5d3e3685182911e6951af7a016579da931080ce6ac9ad/multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8", size = 232018, upload-time = "2026-01-26T02:46:29.941Z" }, + { url = "https://files.pythonhosted.org/packages/9c/1f/48d3c27a72be7fd23a55d8847193c459959bf35a5bb5844530dab00b739b/multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941", size = 241498, upload-time = "2026-01-26T02:46:32.052Z" }, + { url = "https://files.pythonhosted.org/packages/1a/45/413643ae2952d0decdf6c1250f86d08a43e143271441e81027e38d598bd7/multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a", size = 247957, upload-time = "2026-01-26T02:46:33.666Z" }, + { url = "https://files.pythonhosted.org/packages/50/f8/f1d0ac23df15e0470776388bdb261506f63af1f81d28bacb5e262d6e12b6/multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de", size = 241651, upload-time = "2026-01-26T02:46:35.7Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c9/1a2a18f383cf129add66b6c36b75c3911a7ba95cf26cb141482de085cc12/multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5", size = 236371, upload-time = "2026-01-26T02:46:37.37Z" }, + { url = "https://files.pythonhosted.org/packages/bb/aa/77d87e3fca31325b87e0eb72d5fe9a7472dcb51391a42df7ac1f3842f6c0/multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0", size = 41426, upload-time = "2026-01-26T02:46:39.026Z" }, + { url = "https://files.pythonhosted.org/packages/e3/b3/e8863e6a2da15a9d7e98976ff402e871b7352c76566df6c18d0378e0d9cf/multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4", size = 46180, upload-time = "2026-01-26T02:46:40.422Z" }, + { url = "https://files.pythonhosted.org/packages/93/d3/dd4fa951ad5b5fa216bf30054d705683d13405eea7459833d78f31b74c9c/multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9", size = 43231, upload-time = "2026-01-26T02:46:41.945Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + [[package]] name = "mypy" -version = "1.14.1" +version = "1.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051, upload-time = "2024-12-30T16:39:07.335Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002, upload-time = "2024-12-30T16:37:22.435Z" }, - { url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400, upload-time = "2024-12-30T16:37:53.526Z" }, - { url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172, upload-time = "2024-12-30T16:37:50.332Z" }, - { url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732, upload-time = "2024-12-30T16:37:29.96Z" }, - { url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197, upload-time = "2024-12-30T16:38:05.037Z" }, - { url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836, upload-time = "2024-12-30T16:37:19.726Z" }, - { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432, upload-time = "2024-12-30T16:37:11.533Z" }, - { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515, upload-time = "2024-12-30T16:37:40.724Z" }, - { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791, upload-time = "2024-12-30T16:36:58.73Z" }, - { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203, upload-time = "2024-12-30T16:37:03.741Z" }, - { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900, upload-time = "2024-12-30T16:37:57.948Z" }, - { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869, upload-time = "2024-12-30T16:37:33.428Z" }, - { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668, upload-time = "2024-12-30T16:38:02.211Z" }, - { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060, upload-time = "2024-12-30T16:37:46.131Z" }, - { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167, upload-time = "2024-12-30T16:37:43.534Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341, upload-time = "2024-12-30T16:37:36.249Z" }, - { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991, upload-time = "2024-12-30T16:37:06.743Z" }, - { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016, upload-time = "2024-12-30T16:37:15.02Z" }, - { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097, upload-time = "2024-12-30T16:37:25.144Z" }, - { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728, upload-time = "2024-12-30T16:38:08.634Z" }, - { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965, upload-time = "2024-12-30T16:38:12.132Z" }, - { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660, upload-time = "2024-12-30T16:38:17.342Z" }, - { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198, upload-time = "2024-12-30T16:38:32.839Z" }, - { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276, upload-time = "2024-12-30T16:38:20.828Z" }, - { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493, upload-time = "2024-12-30T16:38:26.935Z" }, - { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702, upload-time = "2024-12-30T16:38:50.623Z" }, - { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104, upload-time = "2024-12-30T16:38:53.735Z" }, - { url = "https://files.pythonhosted.org/packages/f1/bf/76a569158db678fee59f4fd30b8e7a0d75bcbaeef49edd882a0d63af6d66/mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", size = 12830167, upload-time = "2024-12-30T16:38:56.437Z" }, - { url = "https://files.pythonhosted.org/packages/43/bc/0bc6b694b3103de9fed61867f1c8bd33336b913d16831431e7cb48ef1c92/mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", size = 13013834, upload-time = "2024-12-30T16:38:59.204Z" }, - { url = "https://files.pythonhosted.org/packages/b0/79/5f5ec47849b6df1e6943d5fd8e6632fbfc04b4fd4acfa5a5a9535d11b4e2/mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", size = 9781231, upload-time = "2024-12-30T16:39:05.124Z" }, - { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905, upload-time = "2024-12-30T16:38:42.021Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, + { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, + { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, + { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, + { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, + { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, + { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, + { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, + { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, + { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, + { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, + { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, + { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, + { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, + { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, + { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, + { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, + { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f7/88436084550ca9af5e610fa45286be04c3b63374df3e021c762fe8c4369f/mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3", size = 13102606, upload-time = "2025-12-15T05:02:46.833Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a5/43dfad311a734b48a752790571fd9e12d61893849a01bff346a54011957f/mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a", size = 12164496, upload-time = "2025-12-15T05:03:41.947Z" }, + { url = "https://files.pythonhosted.org/packages/88/f0/efbfa391395cce2f2771f937e0620cfd185ec88f2b9cd88711028a768e96/mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67", size = 12772068, upload-time = "2025-12-15T05:02:53.689Z" }, + { url = "https://files.pythonhosted.org/packages/25/05/58b3ba28f5aed10479e899a12d2120d582ba9fa6288851b20bf1c32cbb4f/mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e", size = 13520385, upload-time = "2025-12-15T05:02:38.328Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a0/c006ccaff50b31e542ae69b92fe7e2f55d99fba3a55e01067dd564325f85/mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376", size = 13796221, upload-time = "2025-12-15T05:03:22.147Z" }, + { url = "https://files.pythonhosted.org/packages/b2/ff/8bdb051cd710f01b880472241bd36b3f817a8e1c5d5540d0b761675b6de2/mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24", size = 10055456, upload-time = "2025-12-15T05:03:35.169Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, ] [[package]] @@ -2852,6 +3946,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "nexus-rpc" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, +] + +[[package]] +name = "nexus-rpc" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +dependencies = [ + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/50/95d7bc91f900da5e22662c82d9bf0f72a4b01f2a552708bf2f43807707a1/nexus_rpc-1.2.0.tar.gz", hash = "sha256:b4ddaffa4d3996aaeadf49b80dfcdfbca48fe4cb616defaf3b3c5c2c8fc61890", size = 74142, upload-time = "2025-11-17T19:17:06.798Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/04/eaac430d0e6bf21265ae989427d37e94be5e41dc216879f1fbb6c5339942/nexus_rpc-1.2.0-py3-none-any.whl", hash = "sha256:977876f3af811ad1a09b2961d3d1ac9233bda43ff0febbb0c9906483b9d9f8a3", size = 28166, upload-time = "2025-11-17T19:17:05.64Z" }, +] + [[package]] name = "openai" version = "2.17.0" @@ -2871,6 +3996,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/97/284535aa75e6e84ab388248b5a323fc296b1f70530130dee37f7f4fbe856/openai-2.17.0-py3-none-any.whl", hash = "sha256:4f393fd886ca35e113aac7ff239bcd578b81d8f104f5aedc7d3693eb2af1d338", size = 1069524, upload-time = "2026-02-05T16:27:38.941Z" }, ] +[[package]] +name = "openapi-pydantic" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, +] + [[package]] name = "opentelemetry-api" version = "1.39.1" @@ -2884,6 +4021,115 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356, upload-time = "2025-12-11T13:32:17.304Z" }, ] +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/02/ffc3e143d89a27ac21fd557365b98bd0653b98de8a101151d5805b5d4c33/opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", size = 18366, upload-time = "2025-12-11T13:32:20.2Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-exporter-otlp-proto-common", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-proto", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, + { name = "requests", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/f1/b27d3e2e003cd9a3592c43d099d2ed8d0a947c15281bf8463a256db0b46c/opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985", size = 19641, upload-time = "2025-12-11T13:32:22.248Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, + { name = "packaging", marker = "python_full_version >= '3.10'" }, + { name = "wrapt", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/0f/7e6b713ac117c1f5e4e3300748af699b9902a2e5e34c9cf443dde25a01fa/opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a", size = 31706, upload-time = "2025-12-11T13:36:42.515Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/d2/6788e83c5c86a2690101681aeef27eeb2a6bf22df52d3f263a22cee20915/opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", size = 33096, upload-time = "2025-12-11T13:35:33.067Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-instrumentation", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-util-http", marker = "python_full_version >= '3.10'" }, + { name = "wrapt", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/08/11208bcfcab4fc2023252c3f322aa397fd9ad948355fea60f5fc98648603/opentelemetry_instrumentation_httpx-0.60b1.tar.gz", hash = "sha256:a506ebaf28c60112cbe70ad4f0338f8603f148938cb7b6794ce1051cd2b270ae", size = 20611, upload-time = "2025-12-11T13:37:01.661Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/59/b98e84eebf745ffc75397eaad4763795bff8a30cbf2373a50ed4e70646c5/opentelemetry_instrumentation_httpx-0.60b1-py3-none-any.whl", hash = "sha256:f37636dd742ad2af83d896ba69601ed28da51fa4e25d1ab62fde89ce413e275b", size = 15701, upload-time = "2025-12-11T13:36:04.56Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/95/b40c96a7b5203005a0b03d8ce8cd212ff23f1793d5ba289c87a097571b18/opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", size = 72535, upload-time = "2025-12-11T13:32:33.866Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.39.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/98/e91cf858f203d86f4eccdf763dcf01cf03f1dae80c3750f7e635bfa206b6/opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c", size = 132565, upload-time = "2025-12-11T13:32:35.069Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/5e/5958555e09635d09b75de3c4f8b9cae7335ca545d77392ffe7331534c402/opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb", size = 219982, upload-time = "2025-12-11T13:32:36.955Z" }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.60b1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/50/fc/c47bb04a1d8a941a4061307e1eddfa331ed4d0ab13d8a9781e6db256940a/opentelemetry_util_http-0.60b1.tar.gz", hash = "sha256:0d97152ca8c8a41ced7172d29d3622a219317f74ae6bb3027cfbdcf22c3cc0d6", size = 11053, upload-time = "2025-12-11T13:37:25.115Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/5c/d3f1733665f7cd582ef0842fb1d2ed0bc1fba10875160593342d22bba375/opentelemetry_util_http-0.60b1-py3-none-any.whl", hash = "sha256:66381ba28550c91bee14dcba8979ace443444af1ed609226634596b4b0faf199", size = 8947, upload-time = "2025-12-11T13:36:37.151Z" }, +] + [[package]] name = "orjson" version = "3.11.5" @@ -3080,11 +4326,11 @@ wheels = [ [[package]] name = "packaging" -version = "26.0" +version = "25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] [[package]] @@ -3096,6 +4342,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, ] +[[package]] +name = "pathable" +version = "0.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124, upload-time = "2025-01-10T18:43:13.247Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, +] + [[package]] name = "pathspec" version = "1.0.4" @@ -3105,10 +4360,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] +[[package]] +name = "pathvalidate" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/2a/52a8da6fe965dea6192eb716b357558e103aea0a1e9a8352ad575a8406ca/pathvalidate-3.3.1.tar.gz", hash = "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177", size = 63262, upload-time = "2025-06-15T09:07:20.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" }, +] + [[package]] name = "pillow" version = "11.3.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4c/5d/45a3553a253ac8763f3561371432a90bdbe6000fbdcf1397ffe502aa206c/pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860", size = 5316554, upload-time = "2025-07-01T09:13:39.342Z" }, @@ -3218,6 +4485,108 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" }, ] +[[package]] +name = "pillow" +version = "12.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/41/f73d92b6b883a579e79600d391f2e21cb0df767b2714ecbd2952315dfeef/pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd", size = 5304089, upload-time = "2026-01-02T09:10:24.953Z" }, + { url = "https://files.pythonhosted.org/packages/94/55/7aca2891560188656e4a91ed9adba305e914a4496800da6b5c0a15f09edf/pillow-12.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cad302dc10fac357d3467a74a9561c90609768a6f73a1923b0fd851b6486f8b0", size = 4657815, upload-time = "2026-01-02T09:10:27.063Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d2/b28221abaa7b4c40b7dba948f0f6a708bd7342c4d47ce342f0ea39643974/pillow-12.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a40905599d8079e09f25027423aed94f2823adaf2868940de991e53a449e14a8", size = 6222593, upload-time = "2026-01-02T09:10:29.115Z" }, + { url = "https://files.pythonhosted.org/packages/71/b8/7a61fb234df6a9b0b479f69e66901209d89ff72a435b49933f9122f94cac/pillow-12.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92a7fe4225365c5e3a8e598982269c6d6698d3e783b3b1ae979e7819f9cd55c1", size = 8027579, upload-time = "2026-01-02T09:10:31.182Z" }, + { url = "https://files.pythonhosted.org/packages/ea/51/55c751a57cc524a15a0e3db20e5cde517582359508d62305a627e77fd295/pillow-12.1.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f10c98f49227ed8383d28174ee95155a675c4ed7f85e2e573b04414f7e371bda", size = 6335760, upload-time = "2026-01-02T09:10:33.02Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7c/60e3e6f5e5891a1a06b4c910f742ac862377a6fe842f7184df4a274ce7bf/pillow-12.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8637e29d13f478bc4f153d8daa9ffb16455f0a6cb287da1b432fdad2bfbd66c7", size = 7027127, upload-time = "2026-01-02T09:10:35.009Z" }, + { url = "https://files.pythonhosted.org/packages/06/37/49d47266ba50b00c27ba63a7c898f1bb41a29627ced8c09e25f19ebec0ff/pillow-12.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:21e686a21078b0f9cb8c8a961d99e6a4ddb88e0fc5ea6e130172ddddc2e5221a", size = 6449896, upload-time = "2026-01-02T09:10:36.793Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/67fd87d2913902462cd9b79c6211c25bfe95fcf5783d06e1367d6d9a741f/pillow-12.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2415373395a831f53933c23ce051021e79c8cd7979822d8cc478547a3f4da8ef", size = 7151345, upload-time = "2026-01-02T09:10:39.064Z" }, + { url = "https://files.pythonhosted.org/packages/bd/15/f8c7abf82af68b29f50d77c227e7a1f87ce02fdc66ded9bf603bc3b41180/pillow-12.1.0-cp310-cp310-win32.whl", hash = "sha256:e75d3dba8fc1ddfec0cd752108f93b83b4f8d6ab40e524a95d35f016b9683b09", size = 6325568, upload-time = "2026-01-02T09:10:41.035Z" }, + { url = "https://files.pythonhosted.org/packages/d4/24/7d1c0e160b6b5ac2605ef7d8be537e28753c0db5363d035948073f5513d7/pillow-12.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:64efdf00c09e31efd754448a383ea241f55a994fd079866b92d2bbff598aad91", size = 7032367, upload-time = "2026-01-02T09:10:43.09Z" }, + { url = "https://files.pythonhosted.org/packages/f4/03/41c038f0d7a06099254c60f618d0ec7be11e79620fc23b8e85e5b31d9a44/pillow-12.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f188028b5af6b8fb2e9a76ac0f841a575bd1bd396e46ef0840d9b88a48fdbcea", size = 2452345, upload-time = "2026-01-02T09:10:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/43/c4/bf8328039de6cc22182c3ef007a2abfbbdab153661c0a9aa78af8d706391/pillow-12.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:a83e0850cb8f5ac975291ebfc4170ba481f41a28065277f7f735c202cd8e0af3", size = 5304057, upload-time = "2026-01-02T09:10:46.627Z" }, + { url = "https://files.pythonhosted.org/packages/43/06/7264c0597e676104cc22ca73ee48f752767cd4b1fe084662620b17e10120/pillow-12.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b6e53e82ec2db0717eabb276aa56cf4e500c9a7cec2c2e189b55c24f65a3e8c0", size = 4657811, upload-time = "2026-01-02T09:10:49.548Z" }, + { url = "https://files.pythonhosted.org/packages/72/64/f9189e44474610daf83da31145fa56710b627b5c4c0b9c235e34058f6b31/pillow-12.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40a8e3b9e8773876d6e30daed22f016509e3987bab61b3b7fe309d7019a87451", size = 6232243, upload-time = "2026-01-02T09:10:51.62Z" }, + { url = "https://files.pythonhosted.org/packages/ef/30/0df458009be6a4caca4ca2c52975e6275c387d4e5c95544e34138b41dc86/pillow-12.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800429ac32c9b72909c671aaf17ecd13110f823ddb7db4dfef412a5587c2c24e", size = 8037872, upload-time = "2026-01-02T09:10:53.446Z" }, + { url = "https://files.pythonhosted.org/packages/e4/86/95845d4eda4f4f9557e25381d70876aa213560243ac1a6d619c46caaedd9/pillow-12.1.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b022eaaf709541b391ee069f0022ee5b36c709df71986e3f7be312e46f42c84", size = 6345398, upload-time = "2026-01-02T09:10:55.426Z" }, + { url = "https://files.pythonhosted.org/packages/5c/1f/8e66ab9be3aaf1435bc03edd1ebdf58ffcd17f7349c1d970cafe87af27d9/pillow-12.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f345e7bc9d7f368887c712aa5054558bad44d2a301ddf9248599f4161abc7c0", size = 7034667, upload-time = "2026-01-02T09:10:57.11Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f6/683b83cb9b1db1fb52b87951b1c0b99bdcfceaa75febf11406c19f82cb5e/pillow-12.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d70347c8a5b7ccd803ec0c85c8709f036e6348f1e6a5bf048ecd9c64d3550b8b", size = 6458743, upload-time = "2026-01-02T09:10:59.331Z" }, + { url = "https://files.pythonhosted.org/packages/9a/7d/de833d63622538c1d58ce5395e7c6cb7e7dce80decdd8bde4a484e095d9f/pillow-12.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fcc52d86ce7a34fd17cb04e87cfdb164648a3662a6f20565910a99653d66c18", size = 7159342, upload-time = "2026-01-02T09:11:01.82Z" }, + { url = "https://files.pythonhosted.org/packages/8c/40/50d86571c9e5868c42b81fe7da0c76ca26373f3b95a8dd675425f4a92ec1/pillow-12.1.0-cp311-cp311-win32.whl", hash = "sha256:3ffaa2f0659e2f740473bcf03c702c39a8d4b2b7ffc629052028764324842c64", size = 6328655, upload-time = "2026-01-02T09:11:04.556Z" }, + { url = "https://files.pythonhosted.org/packages/6c/af/b1d7e301c4cd26cd45d4af884d9ee9b6fab893b0ad2450d4746d74a6968c/pillow-12.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:806f3987ffe10e867bab0ddad45df1148a2b98221798457fa097ad85d6e8bc75", size = 7031469, upload-time = "2026-01-02T09:11:06.538Z" }, + { url = "https://files.pythonhosted.org/packages/48/36/d5716586d887fb2a810a4a61518a327a1e21c8b7134c89283af272efe84b/pillow-12.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9f5fefaca968e700ad1a4a9de98bf0869a94e397fe3524c4c9450c1445252304", size = 2452515, upload-time = "2026-01-02T09:11:08.226Z" }, + { url = "https://files.pythonhosted.org/packages/20/31/dc53fe21a2f2996e1b7d92bf671cdb157079385183ef7c1ae08b485db510/pillow-12.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a332ac4ccb84b6dde65dbace8431f3af08874bf9770719d32a635c4ef411b18b", size = 5262642, upload-time = "2026-01-02T09:11:10.138Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c1/10e45ac9cc79419cedf5121b42dcca5a50ad2b601fa080f58c22fb27626e/pillow-12.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:907bfa8a9cb790748a9aa4513e37c88c59660da3bcfffbd24a7d9e6abf224551", size = 4657464, upload-time = "2026-01-02T09:11:12.319Z" }, + { url = "https://files.pythonhosted.org/packages/ad/26/7b82c0ab7ef40ebede7a97c72d473bda5950f609f8e0c77b04af574a0ddb/pillow-12.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efdc140e7b63b8f739d09a99033aa430accce485ff78e6d311973a67b6bf3208", size = 6234878, upload-time = "2026-01-02T09:11:14.096Z" }, + { url = "https://files.pythonhosted.org/packages/76/25/27abc9792615b5e886ca9411ba6637b675f1b77af3104710ac7353fe5605/pillow-12.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bef9768cab184e7ae6e559c032e95ba8d07b3023c289f79a2bd36e8bf85605a5", size = 8044868, upload-time = "2026-01-02T09:11:15.903Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ea/f200a4c36d836100e7bc738fc48cd963d3ba6372ebc8298a889e0cfc3359/pillow-12.1.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:742aea052cf5ab5034a53c3846165bc3ce88d7c38e954120db0ab867ca242661", size = 6349468, upload-time = "2026-01-02T09:11:17.631Z" }, + { url = "https://files.pythonhosted.org/packages/11/8f/48d0b77ab2200374c66d344459b8958c86693be99526450e7aee714e03e4/pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6dfc2af5b082b635af6e08e0d1f9f1c4e04d17d4e2ca0ef96131e85eda6eb17", size = 7041518, upload-time = "2026-01-02T09:11:19.389Z" }, + { url = "https://files.pythonhosted.org/packages/1d/23/c281182eb986b5d31f0a76d2a2c8cd41722d6fb8ed07521e802f9bba52de/pillow-12.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:609e89d9f90b581c8d16358c9087df76024cf058fa693dd3e1e1620823f39670", size = 6462829, upload-time = "2026-01-02T09:11:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/25/ef/7018273e0faac099d7b00982abdcc39142ae6f3bd9ceb06de09779c4a9d6/pillow-12.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43b4899cfd091a9693a1278c4982f3e50f7fb7cff5153b05174b4afc9593b616", size = 7166756, upload-time = "2026-01-02T09:11:23.559Z" }, + { url = "https://files.pythonhosted.org/packages/8f/c8/993d4b7ab2e341fe02ceef9576afcf5830cdec640be2ac5bee1820d693d4/pillow-12.1.0-cp312-cp312-win32.whl", hash = "sha256:aa0c9cc0b82b14766a99fbe6084409972266e82f459821cd26997a488a7261a7", size = 6328770, upload-time = "2026-01-02T09:11:25.661Z" }, + { url = "https://files.pythonhosted.org/packages/a7/87/90b358775a3f02765d87655237229ba64a997b87efa8ccaca7dd3e36e7a7/pillow-12.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d70534cea9e7966169ad29a903b99fc507e932069a881d0965a1a84bb57f6c6d", size = 7033406, upload-time = "2026-01-02T09:11:27.474Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cf/881b457eccacac9e5b2ddd97d5071fb6d668307c57cbf4e3b5278e06e536/pillow-12.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:65b80c1ee7e14a87d6a068dd3b0aea268ffcabfe0498d38661b00c5b4b22e74c", size = 2452612, upload-time = "2026-01-02T09:11:29.309Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" }, + { url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" }, + { url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" }, + { url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" }, + { url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" }, + { url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" }, + { url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" }, + { url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" }, + { url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" }, + { url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" }, + { url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" }, + { url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" }, + { url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" }, + { url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" }, + { url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" }, + { url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" }, + { url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" }, + { url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" }, + { url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" }, + { url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" }, + { url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" }, + { url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" }, + { url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" }, + { url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" }, + { url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" }, + { url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" }, + { url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" }, + { url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" }, + { url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" }, + { url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" }, + { url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" }, + { url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" }, + { url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" }, + { url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" }, + { url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/8b/bc/224b1d98cffd7164b14707c91aac83c07b047fbd8f58eba4066a3e53746a/pillow-12.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ca94b6aac0d7af2a10ba08c0f888b3d5114439b6b3ef39968378723622fed377", size = 5228605, upload-time = "2026-01-02T09:13:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ca/49ca7769c4550107de049ed85208240ba0f330b3f2e316f24534795702ce/pillow-12.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:351889afef0f485b84078ea40fe33727a0492b9af3904661b0abbafee0355b72", size = 4622245, upload-time = "2026-01-02T09:13:15.964Z" }, + { url = "https://files.pythonhosted.org/packages/73/48/fac807ce82e5955bcc2718642b94b1bd22a82a6d452aea31cbb678cddf12/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb0984b30e973f7e2884362b7d23d0a348c7143ee559f38ef3eaab640144204c", size = 5247593, upload-time = "2026-01-02T09:13:17.913Z" }, + { url = "https://files.pythonhosted.org/packages/d2/95/3e0742fe358c4664aed4fd05d5f5373dcdad0b27af52aa0972568541e3f4/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84cabc7095dd535ca934d57e9ce2a72ffd216e435a84acb06b2277b1de2689bd", size = 6989008, upload-time = "2026-01-02T09:13:20.083Z" }, + { url = "https://files.pythonhosted.org/packages/5a/74/fe2ac378e4e202e56d50540d92e1ef4ff34ed687f3c60f6a121bcf99437e/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53d8b764726d3af1a138dd353116f774e3862ec7e3794e0c8781e30db0f35dfc", size = 5313824, upload-time = "2026-01-02T09:13:22.405Z" }, + { url = "https://files.pythonhosted.org/packages/f3/77/2a60dee1adee4e2655ac328dd05c02a955c1cd683b9f1b82ec3feb44727c/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5da841d81b1a05ef940a8567da92decaa15bc4d7dedb540a8c219ad83d91808a", size = 5963278, upload-time = "2026-01-02T09:13:24.706Z" }, + { url = "https://files.pythonhosted.org/packages/2d/71/64e9b1c7f04ae0027f788a248e6297d7fcc29571371fe7d45495a78172c0/pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19", size = 7029809, upload-time = "2026-01-02T09:13:26.541Z" }, +] + [[package]] name = "platformdirs" version = "4.4.0" @@ -3274,28 +4643,35 @@ wheels = [ [[package]] name = "prek" -version = "0.2.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/a7/1e07536315f77d7b233cbf3dd916dc3424239c435ee0a0110c9b2cbcf6b0/prek-0.2.22.tar.gz", hash = "sha256:5abbda8bae0a63a18d3fe573162e8504a7b100e3603169cc2d06053891a02d7c", size = 267212, upload-time = "2025-12-13T12:57:51.797Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/fe/ba9a940adc55d78b96b58376a8752e95261402c1e5812acce6ea1a000fb8/prek-0.2.22-py3-none-linux_armv6l.whl", hash = "sha256:d026b2d75529a743466000e8dd058d3d5e7c597c34905b333f2ede3d24cb23f1", size = 4798026, upload-time = "2025-12-13T12:57:45.286Z" }, - { url = "https://files.pythonhosted.org/packages/12/40/459cf510491271b08d19b4ef34f8293440eb472e633f4ffaf34179f39a12/prek-0.2.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:60b5bec94fa9f59fe5a9e90554c7346ceef81ea33d01bb18172d2576b07ac449", size = 4894023, upload-time = "2025-12-13T12:57:40.102Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0b/59e0438b1e7d1b6fa3f14174a916d369e27c421f8876f7ec7c7a52fbfae7/prek-0.2.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a0c7c6ceee536122916d32d26b6fa4fac9e95ba28631901164ffc0b0fed28a9e", size = 4615858, upload-time = "2025-12-13T12:57:57.471Z" }, - { url = "https://files.pythonhosted.org/packages/e9/27/ea40cf715717298fdf802da2b15a2c4445b8c114aae28cab6bf794d65670/prek-0.2.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c90273bef7b638dfc36dede62c494f958456330375ffce891c68321b2a7b46ba", size = 4810206, upload-time = "2025-12-13T12:57:46.534Z" }, - { url = "https://files.pythonhosted.org/packages/b5/12/d1c3db35839492236afb8642a2818d5b413e5fce4ea909bc7ddfb3d4591a/prek-0.2.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d8ecf202073433b87df2671a98bc44d3b68bb5711f7119b50b7bd65c2a67f13", size = 4722439, upload-time = "2025-12-13T12:57:48.106Z" }, - { url = "https://files.pythonhosted.org/packages/64/a0/0f24a9cacd5d78119f47063d860e03fa42b4d7dcf6803a49b0bef51b771b/prek-0.2.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4f26d76247ce7671cf5d9786e7fc86fdb43c065fd5507e8d64b3de7fd5e4447", size = 5037705, upload-time = "2025-12-13T12:57:50.596Z" }, - { url = "https://files.pythonhosted.org/packages/ca/6e/7616f84141755f1d9fe232f0bd06589421ae0dabd99180fdae2840d22ae8/prek-0.2.22-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ac1f0ea2c82e35eb0ffc98dfbcd9ee34cfd7350b64f97198da4c311a271cdb8f", size = 5453199, upload-time = "2025-12-13T12:57:38.458Z" }, - { url = "https://files.pythonhosted.org/packages/51/80/542a583db9b27bfd34954243666e451b266513bc742e0491cd61ff1b390e/prek-0.2.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f5d5131b9e57548f64d74665fd4414a8deb603a67d52ee18b3e6540cdb77733", size = 5399635, upload-time = "2025-12-13T12:57:43.359Z" }, - { url = "https://files.pythonhosted.org/packages/49/06/ca4e6fee73e14e1aced90f5c83b9cdf9a8e1c3b1aa1e4f45a2a65de05a28/prek-0.2.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a768484e1c94a33228765f63701261316b64e11c482abe2a35c54045d3f81feb", size = 5498340, upload-time = "2025-12-13T12:57:41.827Z" }, - { url = "https://files.pythonhosted.org/packages/85/a8/9636fc782db9c22d1740a8e5dc4e1ffc3a28099d074f812da46332e7c7a7/prek-0.2.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c941c8503ea537a84ea97074dc97b0f0dfd9861864883eb8b90586ed321847e", size = 5078431, upload-time = "2025-12-13T12:57:31.664Z" }, - { url = "https://files.pythonhosted.org/packages/4f/29/e78d2f444cf1f097aaaefee8910d7b9fe34195f06b086e0d2153b6c66e07/prek-0.2.22-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:946c6cfe18b17a7b53c49a389bf65f1e8e45a1b96bfdaeeacde21f5b5ca2d149", size = 4820871, upload-time = "2025-12-13T12:57:33.074Z" }, - { url = "https://files.pythonhosted.org/packages/fb/ec/779db6c35663e949b3f9989c584297aa115d3cc44822c149dbe40d51cd14/prek-0.2.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2cffd5809cf678b4300378d612b5da12cd2183ddc7aee78178db0b1ea48f0069", size = 4834431, upload-time = "2025-12-13T12:57:34.65Z" }, - { url = "https://files.pythonhosted.org/packages/1d/18/12bb4fece680457f4d4f13d21c5784675ce8b1db5c968261348c52087232/prek-0.2.22-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:f91df793cbc28647863eb54d578f37782736726671838ca92c9d0601329cb928", size = 4709742, upload-time = "2025-12-13T12:57:52.706Z" }, - { url = "https://files.pythonhosted.org/packages/3f/27/de1d9d037f59393568713121f4bfcea11cd546dcf96f214827983b8beccf/prek-0.2.22-py3-none-musllinux_1_1_i686.whl", hash = "sha256:3c40ba36b3e89817b20efe6163fd15387b81caf1f489060265d84103ae6e5184", size = 4925048, upload-time = "2025-12-13T12:57:49.348Z" }, - { url = "https://files.pythonhosted.org/packages/49/bf/d40eef2e5ccbc520da94c2463450d0ecab598c092684002b463fd5491ff6/prek-0.2.22-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a4154a419581723d12eccaa5b1d27686283c5c78b753c1984270d7e144a15fa7", size = 5192083, upload-time = "2025-12-13T12:57:35.957Z" }, - { url = "https://files.pythonhosted.org/packages/41/ba/11ea837a876dcc7f5df85962bc560c8627a962261f046a1615b0a6016b01/prek-0.2.22-py3-none-win32.whl", hash = "sha256:9fd3d629a256ce3171bebc3183f9c608022fff0db19a511307ab0f4c7682d5e3", size = 4586129, upload-time = "2025-12-13T12:57:54.438Z" }, - { url = "https://files.pythonhosted.org/packages/2f/8c/05ab6d11ac670664c99944e4819a77a63360aab253d8daf4ae411c705bcd/prek-0.2.22-py3-none-win_amd64.whl", hash = "sha256:ad7997ae4bef4fccc0a6761c00479bdd44f2a5bb7eb97aebda3b42fe785e10a1", size = 5273787, upload-time = "2025-12-13T12:57:37.205Z" }, - { url = "https://files.pythonhosted.org/packages/38/7a/53e8a550df705b5bf78a589c4e11d21485ac38c1a65e9c98fc3169a5eb25/prek-0.2.22-py3-none-win_arm64.whl", hash = "sha256:2442c0f12bd57675124542a92f5c799e7ffe52dc7cd98301c43c361849a3aef6", size = 4941186, upload-time = "2025-12-13T12:57:56.214Z" }, +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/f5/ee52def928dd1355c20bcfcf765e1e61434635c33f3075e848e7b83a157b/prek-0.3.2.tar.gz", hash = "sha256:dce0074ff1a21290748ca567b4bda7553ee305a8c7b14d737e6c58364a499364", size = 334229, upload-time = "2026-02-06T13:49:47.539Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/69/70a5fc881290a63910494df2677c0fb241d27cfaa435bbcd0de5cd2e2443/prek-0.3.2-py3-none-linux_armv6l.whl", hash = "sha256:4f352f9c3fc98aeed4c8b2ec4dbf16fc386e45eea163c44d67e5571489bd8e6f", size = 4614960, upload-time = "2026-02-06T13:50:05.818Z" }, + { url = "https://files.pythonhosted.org/packages/c0/15/a82d5d32a2207ccae5d86ea9e44f2b93531ed000faf83a253e8d1108e026/prek-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4a000cfbc3a6ec7d424f8be3c3e69ccd595448197f92daac8652382d0acc2593", size = 4622889, upload-time = "2026-02-06T13:49:53.662Z" }, + { url = "https://files.pythonhosted.org/packages/89/75/ea833b58a12741397017baef9b66a6e443bfa8286ecbd645d14111446280/prek-0.3.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5436bdc2702cbd7bcf9e355564ae66f8131211e65fefae54665a94a07c3d450a", size = 4239653, upload-time = "2026-02-06T13:50:02.88Z" }, + { url = "https://files.pythonhosted.org/packages/10/b4/d9c3885987afac6e20df4cb7db14e3b0d5a08a77ae4916488254ebac4d0b/prek-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0161b5f584f9e7f416d6cf40a17b98f17953050ff8d8350ec60f20fe966b86b6", size = 4595101, upload-time = "2026-02-06T13:49:49.813Z" }, + { url = "https://files.pythonhosted.org/packages/21/a6/1a06473ed83dbc898de22838abdb13954e2583ce229f857f61828384634c/prek-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e641e8533bca38797eebb49aa89ed0e8db0e61225943b27008c257e3af4d631", size = 4521978, upload-time = "2026-02-06T13:49:41.266Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5e/c38390d5612e6d86b32151c1d2fdab74a57913473193591f0eb00c894c21/prek-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfca1810d49d3f9ef37599c958c4e716bc19a1d78a7e88cbdcb332e0b008994f", size = 4829108, upload-time = "2026-02-06T13:49:44.598Z" }, + { url = "https://files.pythonhosted.org/packages/80/a6/cecce2ab623747ff65ed990bb0d95fa38449ee19b348234862acf9392fff/prek-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d69d754299a95a85dc20196f633232f306bee7e7c8cba61791f49ce70404ec", size = 5357520, upload-time = "2026-02-06T13:49:48.512Z" }, + { url = "https://files.pythonhosted.org/packages/a5/18/d6bcb29501514023c76d55d5cd03bdbc037737c8de8b6bc41cdebfb1682c/prek-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:539dcb90ad9b20837968539855df6a29493b328a1ae87641560768eed4f313b0", size = 4852635, upload-time = "2026-02-06T13:49:58.347Z" }, + { url = "https://files.pythonhosted.org/packages/1b/0a/ae46f34ba27ba87aea5c9ad4ac9cd3e07e014fd5079ae079c84198f62118/prek-0.3.2-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:1998db3d0cbe243984736c82232be51318f9192e2433919a6b1c5790f600b5fd", size = 4599484, upload-time = "2026-02-06T13:49:43.296Z" }, + { url = "https://files.pythonhosted.org/packages/1a/a9/73bfb5b3f7c3583f9b0d431924873928705cdef6abb3d0461c37254a681b/prek-0.3.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:07ab237a5415a3e8c0db54de9d63899bcd947624bdd8820d26f12e65f8d19eb7", size = 4657694, upload-time = "2026-02-06T13:50:01.074Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bc/0994bc176e1a80110fad3babce2c98b0ac4007630774c9e18fc200a34781/prek-0.3.2-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:0ced19701d69c14a08125f14a5dd03945982edf59e793c73a95caf4697a7ac30", size = 4509337, upload-time = "2026-02-06T13:49:54.891Z" }, + { url = "https://files.pythonhosted.org/packages/f9/13/e73f85f65ba8f626468e5d1694ab3763111513da08e0074517f40238c061/prek-0.3.2-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ffb28189f976fa111e770ee94e4f298add307714568fb7d610c8a7095cb1ce59", size = 4697350, upload-time = "2026-02-06T13:50:04.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/47/98c46dcd580305b9960252a4eb966f1a7b1035c55c363f378d85662ba400/prek-0.3.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:f63134b3eea14421789a7335d86f99aee277cb520427196f2923b9260c60e5c5", size = 4955860, upload-time = "2026-02-06T13:49:56.581Z" }, + { url = "https://files.pythonhosted.org/packages/73/42/1bb4bba3ff47897df11e9dfd774027cdfa135482c961a54e079af0faf45a/prek-0.3.2-py3-none-win32.whl", hash = "sha256:58c806bd1344becd480ef5a5ba348846cc000af0e1fbe854fef91181a2e06461", size = 4267619, upload-time = "2026-02-06T13:49:39.503Z" }, + { url = "https://files.pythonhosted.org/packages/97/11/6665f47a7c350d83de17403c90bbf7a762ef50876ece456a86f64f46fbfb/prek-0.3.2-py3-none-win_amd64.whl", hash = "sha256:70114b48e9eb8048b2c11b4c7715ce618529c6af71acc84dd8877871a2ef71a6", size = 4624324, upload-time = "2026-02-06T13:49:45.922Z" }, + { url = "https://files.pythonhosted.org/packages/22/e7/740997ca82574d03426f897fd88afe3fc8a7306b8c7ea342a8bc1c538488/prek-0.3.2-py3-none-win_arm64.whl", hash = "sha256:9144d176d0daa2469a25c303ef6f6fa95a8df015eb275232f5cb53551ecefef0", size = 4336008, upload-time = "2026-02-06T13:49:52.27Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, ] [[package]] @@ -3310,6 +4686,175 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] +[[package]] +name = "propcache" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, + { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, + { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, + { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, + { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, + { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, + { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, + { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, + { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, + { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, + { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, + { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, + { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, + { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, + { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, + { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, + { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, + { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, + { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, + { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, + { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, + { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, + { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, + { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, + { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, + { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, + { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, + { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, + { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, + { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, + { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, + { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, + { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, + { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, + { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, + { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, + { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, + { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, + { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, + { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, + { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, + { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, + { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, + { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, + { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, + { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, + { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, + { url = "https://files.pythonhosted.org/packages/9b/01/0ebaec9003f5d619a7475165961f8e3083cf8644d704b60395df3601632d/propcache-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", size = 80277, upload-time = "2025-10-08T19:48:36.647Z" }, + { url = "https://files.pythonhosted.org/packages/34/58/04af97ac586b4ef6b9026c3fd36ee7798b737a832f5d3440a4280dcebd3a/propcache-0.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", size = 45865, upload-time = "2025-10-08T19:48:37.859Z" }, + { url = "https://files.pythonhosted.org/packages/7c/19/b65d98ae21384518b291d9939e24a8aeac4fdb5101b732576f8f7540e834/propcache-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", size = 47636, upload-time = "2025-10-08T19:48:39.038Z" }, + { url = "https://files.pythonhosted.org/packages/b3/0f/317048c6d91c356c7154dca5af019e6effeb7ee15fa6a6db327cc19e12b4/propcache-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", size = 201126, upload-time = "2025-10-08T19:48:40.774Z" }, + { url = "https://files.pythonhosted.org/packages/71/69/0b2a7a5a6ee83292b4b997dbd80549d8ce7d40b6397c1646c0d9495f5a85/propcache-0.4.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", size = 209837, upload-time = "2025-10-08T19:48:42.167Z" }, + { url = "https://files.pythonhosted.org/packages/a5/92/c699ac495a6698df6e497fc2de27af4b6ace10d8e76528357ce153722e45/propcache-0.4.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", size = 215578, upload-time = "2025-10-08T19:48:43.56Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ee/14de81c5eb02c0ee4f500b4e39c4e1bd0677c06e72379e6ab18923c773fc/propcache-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", size = 197187, upload-time = "2025-10-08T19:48:45.309Z" }, + { url = "https://files.pythonhosted.org/packages/1d/94/48dce9aaa6d8dd5a0859bad75158ec522546d4ac23f8e2f05fac469477dd/propcache-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", size = 193478, upload-time = "2025-10-08T19:48:47.743Z" }, + { url = "https://files.pythonhosted.org/packages/60/b5/0516b563e801e1ace212afde869a0596a0d7115eec0b12d296d75633fb29/propcache-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", size = 190650, upload-time = "2025-10-08T19:48:49.373Z" }, + { url = "https://files.pythonhosted.org/packages/24/89/e0f7d4a5978cd56f8cd67735f74052f257dc471ec901694e430f0d1572fe/propcache-0.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", size = 200251, upload-time = "2025-10-08T19:48:51.4Z" }, + { url = "https://files.pythonhosted.org/packages/06/7d/a1fac863d473876ed4406c914f2e14aa82d2f10dd207c9e16fc383cc5a24/propcache-0.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781", size = 200919, upload-time = "2025-10-08T19:48:53.227Z" }, + { url = "https://files.pythonhosted.org/packages/c3/4e/f86a256ff24944cf5743e4e6c6994e3526f6acfcfb55e21694c2424f758c/propcache-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", size = 193211, upload-time = "2025-10-08T19:48:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/6e/3f/3fbad5f4356b068f1b047d300a6ff2c66614d7030f078cd50be3fec04228/propcache-0.4.1-cp39-cp39-win32.whl", hash = "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", size = 38314, upload-time = "2025-10-08T19:48:56.792Z" }, + { url = "https://files.pythonhosted.org/packages/a4/45/d78d136c3a3d215677abb886785aae744da2c3005bcb99e58640c56529b1/propcache-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", size = 41912, upload-time = "2025-10-08T19:48:57.995Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2a/b0632941f25139f4e58450b307242951f7c2717a5704977c6d5323a800af/propcache-0.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", size = 38450, upload-time = "2025-10-08T19:48:59.349Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +] + +[[package]] +name = "protobuf" +version = "5.29.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/57/394a763c103e0edf87f0938dafcd918d53b4c011dfc5c8ae80f3b0452dbb/protobuf-5.29.6.tar.gz", hash = "sha256:da9ee6a5424b6b30fd5e45c5ea663aef540ca95f9ad99d1e887e819cdf9b8723", size = 425623, upload-time = "2026-02-04T22:54:40.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/88/9ee58ff7863c479d6f8346686d4636dd4c415b0cbeed7a6a7d0617639c2a/protobuf-5.29.6-cp310-abi3-win32.whl", hash = "sha256:62e8a3114992c7c647bce37dcc93647575fc52d50e48de30c6fcb28a6a291eb1", size = 423357, upload-time = "2026-02-04T22:54:25.805Z" }, + { url = "https://files.pythonhosted.org/packages/1c/66/2dc736a4d576847134fb6d80bd995c569b13cdc7b815d669050bf0ce2d2c/protobuf-5.29.6-cp310-abi3-win_amd64.whl", hash = "sha256:7e6ad413275be172f67fdee0f43484b6de5a904cc1c3ea9804cb6fe2ff366eda", size = 435175, upload-time = "2026-02-04T22:54:28.592Z" }, + { url = "https://files.pythonhosted.org/packages/06/db/49b05966fd208ae3f44dcd33837b6243b4915c57561d730a43f881f24dea/protobuf-5.29.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:b5a169e664b4057183a34bdc424540e86eea47560f3c123a0d64de4e137f9269", size = 418619, upload-time = "2026-02-04T22:54:30.266Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d7/48cbf6b0c3c39761e47a99cb483405f0fde2be22cf00d71ef316ce52b458/protobuf-5.29.6-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:a8866b2cff111f0f863c1b3b9e7572dc7eaea23a7fae27f6fc613304046483e6", size = 320284, upload-time = "2026-02-04T22:54:31.782Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dd/cadd6ec43069247d91f6345fa7a0d2858bef6af366dbd7ba8f05d2c77d3b/protobuf-5.29.6-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3387f44798ac1106af0233c04fb8abf543772ff241169946f698b3a9a3d3ab9", size = 320478, upload-time = "2026-02-04T22:54:32.909Z" }, + { url = "https://files.pythonhosted.org/packages/30/a4/ff263f5687815e1a10a9243a3a6463af42ca251224bf4b8fc4c93b9f5b80/protobuf-5.29.6-cp39-cp39-win32.whl", hash = "sha256:cb4c86de9cd8a7f3a256b9744220d87b847371c6b2f10bde87768918ef33ba49", size = 423352, upload-time = "2026-02-04T22:54:37.375Z" }, + { url = "https://files.pythonhosted.org/packages/5c/64/e943206d3b5069050d570a2c53a90631240d99adcc9a91c6ff7b41876f4d/protobuf-5.29.6-cp39-cp39-win_amd64.whl", hash = "sha256:76e07e6567f8baf827137e8d5b8204b6c7b6488bbbff1bf0a72b383f77999c18", size = 435222, upload-time = "2026-02-04T22:54:38.418Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cb/e3065b447186cb70aa65acc70c86baf482d82bf75625bf5a2c4f6919c6a3/protobuf-5.29.6-py3-none-any.whl", hash = "sha256:6b9edb641441b2da9fa8f428760fc136a49cf97a52076010cf22a2ff73438a86", size = 173126, upload-time = "2026-02-04T22:54:39.462Z" }, +] + +[[package]] +name = "protobuf" +version = "6.33.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, + { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, + { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, + { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/08/60/84d5f6dcda9165e4d6a56ac8433c9f40a8906bf2966150b8a0cfde097d78/protobuf-6.33.5-cp39-cp39-win32.whl", hash = "sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c", size = 425892, upload-time = "2026-01-29T21:51:30.382Z" }, + { url = "https://files.pythonhosted.org/packages/68/19/33d7dc2dc84439587fa1e21e1c0026c01ad2af0a62f58fd54002a7546307/protobuf-6.33.5-cp39-cp39-win_amd64.whl", hash = "sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a", size = 437137, upload-time = "2026-01-29T21:51:31.456Z" }, + { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, +] + [[package]] name = "pwdlib" version = "0.2.1" @@ -3345,6 +4890,47 @@ argon2 = [ { name = "argon2-cffi", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] +[[package]] +name = "py-key-value-aio" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype", marker = "python_full_version >= '3.10'" }, + { name = "py-key-value-shared", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/10/72f6f213b8f0bce36eff21fda0a13271834e9eeff7f9609b01afdc253c79/py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64", size = 96342, upload-time = "2025-11-17T16:50:03.801Z" }, +] + +[package.optional-dependencies] +disk = [ + { name = "diskcache", marker = "python_full_version >= '3.10'" }, + { name = "pathvalidate", marker = "python_full_version >= '3.10'" }, +] +keyring = [ + { name = "keyring", marker = "python_full_version >= '3.10'" }, +] +memory = [ + { name = "cachetools", marker = "python_full_version >= '3.10'" }, +] +redis = [ + { name = "redis", marker = "python_full_version >= '3.10'" }, +] + +[[package]] +name = "py-key-value-shared" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560, upload-time = "2025-11-17T16:50:05.954Z" }, +] + [[package]] name = "pyasn1" version = "0.6.2" @@ -3413,85 +4999,193 @@ email = [ [[package]] name = "pydantic-ai" -version = "0.4.10" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "pydantic-ai-slim", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "google", "groq", "huggingface", "mistral", "openai", "retries", "temporal", "vertexai"], marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/d7/fcc18ce80008e888404a3615f973aa3f39b98384d61b03621144c9f4c2d4/pydantic_ai-0.8.1.tar.gz", hash = "sha256:05974382082ee4f3706909d06bdfcc5e95f39e29230cc4d00e47429080099844", size = 43772581, upload-time = "2025-08-29T14:46:23.201Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/04/802b8cf834dffcda8baabb3b76c549243694a83346c3f54e47a3a4d519fb/pydantic_ai-0.8.1-py3-none-any.whl", hash = "sha256:5fa923097132aa69b4d6a310b462dc091009c7b87705edf4443d37b887d5ef9a", size = 10188, upload-time = "2025-08-29T14:46:11.137Z" }, +] + +[[package]] +name = "pydantic-ai" +version = "1.56.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] dependencies = [ - { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "google", "groq", "huggingface", "mcp", "mistral", "openai", "retries", "vertexai"] }, + { name = "pydantic-ai-slim", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"], marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dd/67/eef2d1d64579c20ff732244c8f46f5b10401a47122b2404fd1a786860e0e/pydantic_ai-0.4.10.tar.gz", hash = "sha256:21cda3b62706dfdd5b9d662bb9a2ead50d51951f6ee0bbee45320b8752a95055", size = 43555371, upload-time = "2025-07-30T23:03:50.744Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/1a/800a1e02b259152a49d4c11d9103784a7482c7e9b067eeea23e949d3d80f/pydantic_ai-1.56.0.tar.gz", hash = "sha256:643ff71612df52315b3b4c4b41543657f603f567223eb33245dc8098f005bdc4", size = 11795, upload-time = "2026-02-06T01:13:21.122Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/12/9c/3ea9ce322448e963fd84abb61985fa2d2ea0cb3f09bf0634cf43b2f49de6/pydantic_ai-0.4.10-py3-none-any.whl", hash = "sha256:4822325c92a57c9b45bdfd993106558e2397362b98ec211670d106c4b073ddd8", size = 10194, upload-time = "2025-07-30T23:03:42.435Z" }, + { url = "https://files.pythonhosted.org/packages/5c/35/f4a7fd2b9962ddb9b021f76f293e74fda71da190bb74b57ed5b343c93022/pydantic_ai-1.56.0-py3-none-any.whl", hash = "sha256:b6b3ac74bdc004693834750da4420ea2cde0d3cbc3f134c0b7544f98f1c00859", size = 7222, upload-time = "2026-02-06T01:13:11.755Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "0.4.10" +version = "0.8.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "eval-type-backport" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, + { name = "genai-prices", marker = "python_full_version < '3.10'" }, { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "httpx" }, - { name = "opentelemetry-api" }, - { name = "pydantic" }, - { name = "pydantic-graph" }, - { name = "typing-inspection" }, + { name = "httpx", marker = "python_full_version < '3.10'" }, + { name = "opentelemetry-api", marker = "python_full_version < '3.10'" }, + { name = "pydantic", marker = "python_full_version < '3.10'" }, + { name = "pydantic-graph", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "typing-inspection", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/fc/4123faf9372807e487c83acc858482f6d5a2f39ee6c1e25a895f23f700b6/pydantic_ai_slim-0.4.10.tar.gz", hash = "sha256:c9f6904aaa91c0309f91cc3a5617c570e153afbbb9888ee52190f58f029640f0", size = 189595, upload-time = "2025-07-30T23:03:55.44Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/91/08137459b3745900501b3bd11852ced6c81b7ce6e628696d75b09bb786c5/pydantic_ai_slim-0.8.1.tar.gz", hash = "sha256:12ef3dcbe5e1dad195d5e256746ef960f6e59aeddda1a55bdd553ee375ff53ae", size = 218906, upload-time = "2025-08-29T14:46:27.517Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/d7/b1f6cf2eb9d24086de8a7f9e08956421fde514bcb7a4a3594b108e12636e/pydantic_ai_slim-0.4.10-py3-none-any.whl", hash = "sha256:49a386d6a900b4c1a81bca3469522a4c0eaab5a46a3953d1ffda8f0f2865ed97", size = 254994, upload-time = "2025-07-30T23:03:45.03Z" }, + { url = "https://files.pythonhosted.org/packages/11/ce/8dbadd04f578d02a9825a46e931005743fe223736296f30b55846c084fab/pydantic_ai_slim-0.8.1-py3-none-any.whl", hash = "sha256:fc7edc141b21fe42bc54a2d92c1127f8a75160c5e57a168dba154d3f4adb963f", size = 297821, upload-time = "2025-08-29T14:46:14.647Z" }, ] [package.optional-dependencies] ag-ui = [ - { name = "ag-ui-protocol" }, + { name = "ag-ui-protocol", marker = "python_full_version < '3.10'" }, { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] anthropic = [ - { name = "anthropic" }, + { name = "anthropic", marker = "python_full_version < '3.10'" }, ] bedrock = [ - { name = "boto3" }, + { name = "boto3", marker = "python_full_version < '3.10'" }, ] cli = [ - { name = "argcomplete" }, - { name = "prompt-toolkit" }, - { name = "rich" }, + { name = "argcomplete", marker = "python_full_version < '3.10'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.10'" }, + { name = "pyperclip", marker = "python_full_version < '3.10'" }, + { name = "rich", marker = "python_full_version < '3.10'" }, ] cohere = [ - { name = "cohere", marker = "sys_platform != 'emscripten'" }, + { name = "cohere", marker = "python_full_version < '3.10' and sys_platform != 'emscripten'" }, ] evals = [ - { name = "pydantic-evals" }, + { name = "pydantic-evals", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, ] google = [ { name = "google-genai", version = "1.47.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +groq = [ + { name = "groq", marker = "python_full_version < '3.10'" }, +] +huggingface = [ + { name = "huggingface-hub", extra = ["inference"], marker = "python_full_version < '3.10'" }, +] +mistral = [ + { name = "mistralai", marker = "python_full_version < '3.10'" }, +] +openai = [ + { name = "openai", marker = "python_full_version < '3.10'" }, +] +retries = [ + { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +temporal = [ + { name = "temporalio", version = "1.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +vertexai = [ + { name = "google-auth", marker = "python_full_version < '3.10'" }, + { name = "requests", marker = "python_full_version < '3.10'" }, +] + +[[package]] +name = "pydantic-ai-slim" +version = "1.56.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, + { name = "genai-prices", marker = "python_full_version >= '3.10'" }, + { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "httpx", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "pydantic", marker = "python_full_version >= '3.10'" }, + { name = "pydantic-graph", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/5c/3a577825b9c1da8f287be7f2ee6fe9aab48bc8a80e65c8518052c589f51c/pydantic_ai_slim-1.56.0.tar.gz", hash = "sha256:9f9f9c56b1c735837880a515ae5661b465b40207b25f3a3434178098b2137f05", size = 415265, upload-time = "2026-02-06T01:13:23.58Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/4b/34682036528eeb9aaf093c2073540ddf399ab37b99d282a69ca41356f1aa/pydantic_ai_slim-1.56.0-py3-none-any.whl", hash = "sha256:d657e4113485020500b23b7390b0066e2a0277edc7577eaad2290735ca5dd7d5", size = 542270, upload-time = "2026-02-06T01:13:14.918Z" }, +] + +[package.optional-dependencies] +ag-ui = [ + { name = "ag-ui-protocol", marker = "python_full_version >= '3.10'" }, + { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +anthropic = [ + { name = "anthropic", marker = "python_full_version >= '3.10'" }, +] +bedrock = [ + { name = "boto3", marker = "python_full_version >= '3.10'" }, +] +cli = [ + { name = "argcomplete", marker = "python_full_version >= '3.10'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.10'" }, + { name = "pyperclip", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, +] +cohere = [ + { name = "cohere", marker = "python_full_version >= '3.10' and sys_platform != 'emscripten'" }, +] +evals = [ + { name = "pydantic-evals", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +fastmcp = [ + { name = "fastmcp", marker = "python_full_version >= '3.10'" }, +] +google = [ { name = "google-genai", version = "1.62.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] groq = [ - { name = "groq" }, + { name = "groq", marker = "python_full_version >= '3.10'" }, ] huggingface = [ - { name = "huggingface-hub" }, + { name = "huggingface-hub", extra = ["inference"], marker = "python_full_version >= '3.10'" }, +] +logfire = [ + { name = "logfire", extra = ["httpx"], marker = "python_full_version >= '3.10'" }, ] mcp = [ { name = "mcp", marker = "python_full_version >= '3.10'" }, ] mistral = [ - { name = "mistralai" }, + { name = "mistralai", marker = "python_full_version >= '3.10'" }, ] openai = [ - { name = "openai" }, + { name = "openai", marker = "python_full_version >= '3.10'" }, + { name = "tiktoken", marker = "python_full_version >= '3.10'" }, ] retries = [ - { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "tenacity", version = "9.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] +temporal = [ + { name = "temporalio", version = "1.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +ui = [ + { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] vertexai = [ - { name = "google-auth" }, - { name = "requests" }, + { name = "google-auth", marker = "python_full_version >= '3.10'" }, + { name = "requests", marker = "python_full_version >= '3.10'" }, +] +xai = [ + { name = "xai-sdk", marker = "python_full_version >= '3.10'" }, ] [[package]] @@ -3627,20 +5321,44 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "0.4.10" +version = "0.8.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "anyio" }, - { name = "eval-type-backport", marker = "python_full_version < '3.11'" }, - { name = "logfire-api" }, - { name = "pydantic" }, - { name = "pydantic-ai-slim" }, - { name = "pyyaml" }, - { name = "rich" }, + { name = "anyio", marker = "python_full_version < '3.10'" }, + { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, + { name = "logfire-api", marker = "python_full_version < '3.10'" }, + { name = "pydantic", marker = "python_full_version < '3.10'" }, + { name = "pydantic-ai-slim", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pyyaml", marker = "python_full_version < '3.10'" }, + { name = "rich", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/98/b7/3f925d6ec9a2627e3310e87c2131514c3b44427c8975fafe83453825cfca/pydantic_evals-0.4.10.tar.gz", hash = "sha256:310acc7559d601743a101c606e50c0c5a9592bfc53cb733c7e54143b39e0fc97", size = 43729, upload-time = "2025-07-30T23:03:56.943Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/9d/460a1f2c9f5f263e9d8e9661acbd654ccc81ad3373ea43048d914091a817/pydantic_evals-0.8.1.tar.gz", hash = "sha256:c398a623c31c19ce70e346ad75654fcb1517c3f6a821461f64fe5cbbe0813023", size = 43933, upload-time = "2025-08-29T14:46:28.903Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/9f/7972c450d74c2b0f6d9f9de644ac33c4c63f0f2156f8acd37a274b1f43a3/pydantic_evals-0.4.10-py3-none-any.whl", hash = "sha256:5fda10c5ced2c99f03b407bd56645574598e6daab0e5be2ed7056e815e6037f6", size = 52511, upload-time = "2025-07-30T23:03:46.717Z" }, + { url = "https://files.pythonhosted.org/packages/6f/f9/1d21c4687167c4fa76fd3b1ed47f9bc2d38fd94cbacd9aa3f19e82e59830/pydantic_evals-0.8.1-py3-none-any.whl", hash = "sha256:6c76333b1d79632f619eb58a24ac656e9f402c47c75ad750ba0230d7f5514344", size = 52602, upload-time = "2025-08-29T14:46:16.602Z" }, +] + +[[package]] +name = "pydantic-evals" +version = "1.56.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +dependencies = [ + { name = "anyio", marker = "python_full_version >= '3.10'" }, + { name = "logfire-api", marker = "python_full_version >= '3.10'" }, + { name = "pydantic", marker = "python_full_version >= '3.10'" }, + { name = "pydantic-ai-slim", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pyyaml", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/f2/8c59284a2978af3fbda45ae3217218eaf8b071207a9290b54b7613983e5d/pydantic_evals-1.56.0.tar.gz", hash = "sha256:206635107127af6a3ee4b1fc8f77af6afb14683615a2d6b3609f79467c1c0d28", size = 47210, upload-time = "2026-02-06T01:13:25.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/51/9875d19ff6d584aaeb574aba76b49d931b822546fc60b29c4fc0da98170d/pydantic_evals-1.56.0-py3-none-any.whl", hash = "sha256:d1efb410c97135aabd2a22453b10c981b2b9851985e9354713af67ae0973b7a9", size = 56407, upload-time = "2026-02-06T01:13:17.098Z" }, ] [[package]] @@ -3658,17 +5376,39 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "0.4.10" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "httpx", marker = "python_full_version < '3.10'" }, + { name = "logfire-api", marker = "python_full_version < '3.10'" }, + { name = "pydantic", marker = "python_full_version < '3.10'" }, + { name = "typing-inspection", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/97/b35b7cb82d9f1bb6d5c6d21bba54f6196a3a5f593373f3a9c163a3821fd7/pydantic_graph-0.8.1.tar.gz", hash = "sha256:c61675a05c74f661d4ff38d04b74bd652c1e0959467801986f2f85dc7585410d", size = 21675, upload-time = "2025-08-29T14:46:29.839Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/e3/5908643b049bb2384d143885725cbeb0f53707d418357d4d1ac8d2c82629/pydantic_graph-0.8.1-py3-none-any.whl", hash = "sha256:f1dd5db0fe22f4e3323c04c65e2f0013846decc312b3efc3196666764556b765", size = 27239, upload-time = "2025-08-29T14:46:18.317Z" }, +] + +[[package]] +name = "pydantic-graph" +version = "1.56.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] dependencies = [ - { name = "httpx" }, - { name = "logfire-api" }, - { name = "pydantic" }, - { name = "typing-inspection" }, + { name = "httpx", marker = "python_full_version >= '3.10'" }, + { name = "logfire-api", marker = "python_full_version >= '3.10'" }, + { name = "pydantic", marker = "python_full_version >= '3.10'" }, + { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/46/62b83bd471a8743c41aba6693f55b746b8ee1294f64b7e9f42db7c3fd4b5/pydantic_graph-0.4.10.tar.gz", hash = "sha256:034063ac0ce2143a877a4fac563520492e70dde42d262b22c928f081d7759c5b", size = 21978, upload-time = "2025-07-30T23:03:57.986Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/03/f92881cdb12d6f43e60e9bfd602e41c95408f06e2324d3729f7a194e2bcd/pydantic_graph-1.56.0.tar.gz", hash = "sha256:5e22972dbb43dbc379ab9944252ff864019abf3c7d465dcdf572fc8aec9a44a1", size = 58460, upload-time = "2026-02-06T01:13:26.708Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/55/0026897b1cd6ab6b179b25c06b1dff496a3ebb83e30c6acb1a5a40e80cd1/pydantic_graph-0.4.10-py3-none-any.whl", hash = "sha256:e5128d5e370a6391aa6441eaefff6b3a139e583e0ac6755d83b88c9df9c6c6a7", size = 27578, upload-time = "2025-07-30T23:03:47.925Z" }, + { url = "https://files.pythonhosted.org/packages/08/07/8c823eb4d196137c123d4d67434e185901d3cbaea3b0c2b7667da84e72c1/pydantic_graph-1.56.0-py3-none-any.whl", hash = "sha256:ec3f0a1d6fcedd4eb9c59fef45079c2ee4d4185878d70dae26440a9c974c6bb3", size = 72346, upload-time = "2026-02-06T01:13:18.792Z" }, ] [[package]] @@ -3706,6 +5446,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" }, ] +[[package]] +name = "pydocket" +version = "0.17.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cloudpickle", marker = "python_full_version >= '3.10'" }, + { name = "croniter", marker = "python_full_version >= '3.10'" }, + { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, + { name = "fakeredis", extra = ["lua"], marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, + { name = "prometheus-client", marker = "python_full_version >= '3.10'" }, + { name = "py-key-value-aio", extra = ["memory", "redis"], marker = "python_full_version >= '3.10'" }, + { name = "python-json-logger", marker = "python_full_version >= '3.10'" }, + { name = "redis", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "taskgroup", marker = "python_full_version == '3.10.*'" }, + { name = "typer", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/26/ac23ead3725475468b50b486939bf5feda27180050a614a7407344a0af0e/pydocket-0.17.5.tar.gz", hash = "sha256:19a6976d8fd11c1acf62feb0291a339e06beaefa100f73dd38c6499760ad3e62", size = 334829, upload-time = "2026-01-30T18:44:39.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/98/73427d065c067a99de6afbe24df3d90cf20d63152ceb42edff2b6e829d4c/pydocket-0.17.5-py3-none-any.whl", hash = "sha256:544d7c2625a33e52528ac24db25794841427dfc2cf30b9c558ac387c77746241", size = 93355, upload-time = "2026-01-30T18:44:37.972Z" }, +] + [[package]] name = "pyee" version = "13.0.0" @@ -3746,11 +5510,11 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.9.0" +version = "2.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fb/68/ce067f09fca4abeca8771fe667d89cc347d1e99da3e093112ac329c6020e/pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c", size = 78825, upload-time = "2024-08-01T15:01:08.445Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/79/84/0fdf9b18ba31d69877bd39c9cd6052b47f3761e9910c15de788e519f079f/PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", size = 22344, upload-time = "2024-08-01T15:01:06.481Z" }, + { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, ] [package.optional-dependencies] @@ -3807,6 +5571,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/29/7d/5945b5af29534641820d3bd7b00962abbbdfee84ec7e19f0d5b3175f9a31/pynacl-1.6.2-cp38-abi3-win_arm64.whl", hash = "sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c", size = 184801, upload-time = "2026-01-01T17:32:36.309Z" }, ] +[[package]] +name = "pyperclip" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, +] + [[package]] name = "pytest" version = "8.4.2" @@ -3876,6 +5649,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, ] +[[package]] +name = "python-json-logger" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, +] + [[package]] name = "python-multipart" version = "0.0.20" @@ -3913,6 +5695,59 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" }, ] +[[package]] +name = "pytokens" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" }, + { url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, + { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, + { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, + { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, + { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, + { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, + { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, + { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, + { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, + { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, + { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/51/2a/f125667ce48105bf1f4e50e03cfa7b24b8c4f47684d7f1cf4dcb6f6b1c15/pytokens-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3", size = 161464, upload-time = "2026-01-30T01:03:39.11Z" }, + { url = "https://files.pythonhosted.org/packages/40/df/065a30790a7ca6bb48ad9018dd44668ed9135610ebf56a2a4cb8e513fd5c/pytokens-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1", size = 246159, upload-time = "2026-01-30T01:03:40.131Z" }, + { url = "https://files.pythonhosted.org/packages/a5/1c/fd09976a7e04960dabc07ab0e0072c7813d566ec67d5490a4c600683c158/pytokens-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db", size = 259120, upload-time = "2026-01-30T01:03:41.233Z" }, + { url = "https://files.pythonhosted.org/packages/52/49/59fdc6fc5a390ae9f308eadeb97dfc70fc2d804ffc49dd39fc97604622ec/pytokens-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1", size = 262196, upload-time = "2026-01-30T01:03:42.696Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/d6734dccf0080e3dc00a55b0827ab5af30c886f8bc127bbc04bc3445daec/pytokens-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a", size = 103510, upload-time = "2026-01-30T01:03:43.915Z" }, + { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + [[package]] name = "pywin32" version = "311" @@ -3938,6 +5773,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/60/22/e0e8d802f124772cec9c75430b01a212f86f9de7546bda715e54140d5aeb/pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d", size = 8778162, upload-time = "2025-07-14T20:13:03.544Z" }, ] +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + [[package]] name = "pyyaml" version = "6.0.3" @@ -4032,18 +5876,168 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/96/7935186fba032312eb8a75e6503440b0e6de76c901421f791408e4debd93/rcslice-1.1.0-py3-none-any.whl", hash = "sha256:1b12fc0c0ca452e8a9fd2b56ac008162f19e250906a4290a7e7a98be3200c2a6", size = 5180, upload-time = "2018-09-27T12:44:05.197Z" }, ] +[[package]] +name = "redis" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-timeout", marker = "python_full_version >= '3.10' and python_full_version < '3.11.3'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, +] + [[package]] name = "referencing" -version = "0.37.0" +version = "0.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs", marker = "python_full_version >= '3.10'" }, { name = "rpds-py", marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, +] + +[[package]] +name = "regex" +version = "2026.1.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/86/07d5056945f9ec4590b518171c4254a5925832eb727b56d3c38a7476f316/regex-2026.1.15.tar.gz", hash = "sha256:164759aa25575cbc0651bef59a0b18353e54300d79ace8084c818ad8ac72b7d5", size = 414811, upload-time = "2026-01-14T23:18:02.775Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/d2/e6ee96b7dff201a83f650241c52db8e5bd080967cb93211f57aa448dc9d6/regex-2026.1.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e3dd93c8f9abe8aa4b6c652016da9a3afa190df5ad822907efe6b206c09896e", size = 488166, upload-time = "2026-01-14T23:13:46.408Z" }, + { url = "https://files.pythonhosted.org/packages/23/8a/819e9ce14c9f87af026d0690901b3931f3101160833e5d4c8061fa3a1b67/regex-2026.1.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:97499ff7862e868b1977107873dd1a06e151467129159a6ffd07b66706ba3a9f", size = 290632, upload-time = "2026-01-14T23:13:48.688Z" }, + { url = "https://files.pythonhosted.org/packages/d5/c3/23dfe15af25d1d45b07dfd4caa6003ad710dcdcb4c4b279909bdfe7a2de8/regex-2026.1.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0bda75ebcac38d884240914c6c43d8ab5fb82e74cde6da94b43b17c411aa4c2b", size = 288500, upload-time = "2026-01-14T23:13:50.503Z" }, + { url = "https://files.pythonhosted.org/packages/c6/31/1adc33e2f717df30d2f4d973f8776d2ba6ecf939301efab29fca57505c95/regex-2026.1.15-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7dcc02368585334f5bc81fc73a2a6a0bbade60e7d83da21cead622faf408f32c", size = 781670, upload-time = "2026-01-14T23:13:52.453Z" }, + { url = "https://files.pythonhosted.org/packages/23/ce/21a8a22d13bc4adcb927c27b840c948f15fc973e21ed2346c1bd0eae22dc/regex-2026.1.15-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:693b465171707bbe882a7a05de5e866f33c76aa449750bee94a8d90463533cc9", size = 850820, upload-time = "2026-01-14T23:13:54.894Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/3eeacdf587a4705a44484cd0b30e9230a0e602811fb3e2cc32268c70d509/regex-2026.1.15-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b0d190e6f013ea938623a58706d1469a62103fb2a241ce2873a9906e0386582c", size = 898777, upload-time = "2026-01-14T23:13:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/79/a9/1898a077e2965c35fc22796488141a22676eed2d73701e37c73ad7c0b459/regex-2026.1.15-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ff818702440a5878a81886f127b80127f5d50563753a28211482867f8318106", size = 791750, upload-time = "2026-01-14T23:13:58.527Z" }, + { url = "https://files.pythonhosted.org/packages/4c/84/e31f9d149a178889b3817212827f5e0e8c827a049ff31b4b381e76b26e2d/regex-2026.1.15-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f052d1be37ef35a54e394de66136e30fa1191fab64f71fc06ac7bc98c9a84618", size = 782674, upload-time = "2026-01-14T23:13:59.874Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ff/adf60063db24532add6a1676943754a5654dcac8237af024ede38244fd12/regex-2026.1.15-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6bfc31a37fd1592f0c4fc4bfc674b5c42e52efe45b4b7a6a14f334cca4bcebe4", size = 767906, upload-time = "2026-01-14T23:14:01.298Z" }, + { url = "https://files.pythonhosted.org/packages/af/3e/e6a216cee1e2780fec11afe7fc47b6f3925d7264e8149c607ac389fd9b1a/regex-2026.1.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d6ce5ae80066b319ae3bc62fd55a557c9491baa5efd0d355f0de08c4ba54e79", size = 774798, upload-time = "2026-01-14T23:14:02.715Z" }, + { url = "https://files.pythonhosted.org/packages/0f/98/23a4a8378a9208514ed3efc7e7850c27fa01e00ed8557c958df0335edc4a/regex-2026.1.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1704d204bd42b6bb80167df0e4554f35c255b579ba99616def38f69e14a5ccb9", size = 845861, upload-time = "2026-01-14T23:14:04.824Z" }, + { url = "https://files.pythonhosted.org/packages/f8/57/d7605a9d53bd07421a8785d349cd29677fe660e13674fa4c6cbd624ae354/regex-2026.1.15-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e3174a5ed4171570dc8318afada56373aa9289eb6dc0d96cceb48e7358b0e220", size = 755648, upload-time = "2026-01-14T23:14:06.371Z" }, + { url = "https://files.pythonhosted.org/packages/6f/76/6f2e24aa192da1e299cc1101674a60579d3912391867ce0b946ba83e2194/regex-2026.1.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:87adf5bd6d72e3e17c9cb59ac4096b1faaf84b7eb3037a5ffa61c4b4370f0f13", size = 836250, upload-time = "2026-01-14T23:14:08.343Z" }, + { url = "https://files.pythonhosted.org/packages/11/3a/1f2a1d29453299a7858eab7759045fc3d9d1b429b088dec2dc85b6fa16a2/regex-2026.1.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e85dc94595f4d766bd7d872a9de5ede1ca8d3063f3bdf1e2c725f5eb411159e3", size = 779919, upload-time = "2026-01-14T23:14:09.954Z" }, + { url = "https://files.pythonhosted.org/packages/c0/67/eab9bc955c9dcc58e9b222c801e39cff7ca0b04261792a2149166ce7e792/regex-2026.1.15-cp310-cp310-win32.whl", hash = "sha256:21ca32c28c30d5d65fc9886ff576fc9b59bbca08933e844fa2363e530f4c8218", size = 265888, upload-time = "2026-01-14T23:14:11.35Z" }, + { url = "https://files.pythonhosted.org/packages/1d/62/31d16ae24e1f8803bddb0885508acecaec997fcdcde9c243787103119ae4/regex-2026.1.15-cp310-cp310-win_amd64.whl", hash = "sha256:3038a62fc7d6e5547b8915a3d927a0fbeef84cdbe0b1deb8c99bbd4a8961b52a", size = 277830, upload-time = "2026-01-14T23:14:12.908Z" }, + { url = "https://files.pythonhosted.org/packages/e5/36/5d9972bccd6417ecd5a8be319cebfd80b296875e7f116c37fb2a2deecebf/regex-2026.1.15-cp310-cp310-win_arm64.whl", hash = "sha256:505831646c945e3e63552cc1b1b9b514f0e93232972a2d5bedbcc32f15bc82e3", size = 270376, upload-time = "2026-01-14T23:14:14.782Z" }, + { url = "https://files.pythonhosted.org/packages/d0/c9/0c80c96eab96948363d270143138d671d5731c3a692b417629bf3492a9d6/regex-2026.1.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ae6020fb311f68d753b7efa9d4b9a5d47a5d6466ea0d5e3b5a471a960ea6e4a", size = 488168, upload-time = "2026-01-14T23:14:16.129Z" }, + { url = "https://files.pythonhosted.org/packages/17/f0/271c92f5389a552494c429e5cc38d76d1322eb142fb5db3c8ccc47751468/regex-2026.1.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eddf73f41225942c1f994914742afa53dc0d01a6e20fe14b878a1b1edc74151f", size = 290636, upload-time = "2026-01-14T23:14:17.715Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f9/5f1fd077d106ca5655a0f9ff8f25a1ab55b92128b5713a91ed7134ff688e/regex-2026.1.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e8cd52557603f5c66a548f69421310886b28b7066853089e1a71ee710e1cdc1", size = 288496, upload-time = "2026-01-14T23:14:19.326Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e1/8f43b03a4968c748858ec77f746c286d81f896c2e437ccf050ebc5d3128c/regex-2026.1.15-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5170907244b14303edc5978f522f16c974f32d3aa92109fabc2af52411c9433b", size = 793503, upload-time = "2026-01-14T23:14:20.922Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4e/a39a5e8edc5377a46a7c875c2f9a626ed3338cb3bb06931be461c3e1a34a/regex-2026.1.15-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2748c1ec0663580b4510bd89941a31560b4b439a0b428b49472a3d9944d11cd8", size = 860535, upload-time = "2026-01-14T23:14:22.405Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1c/9dce667a32a9477f7a2869c1c767dc00727284a9fa3ff5c09a5c6c03575e/regex-2026.1.15-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2f2775843ca49360508d080eaa87f94fa248e2c946bbcd963bb3aae14f333413", size = 907225, upload-time = "2026-01-14T23:14:23.897Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3c/87ca0a02736d16b6262921425e84b48984e77d8e4e572c9072ce96e66c30/regex-2026.1.15-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9ea2604370efc9a174c1b5dcc81784fb040044232150f7f33756049edfc9026", size = 800526, upload-time = "2026-01-14T23:14:26.039Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/647d5715aeea7c87bdcbd2f578f47b415f55c24e361e639fe8c0cc88878f/regex-2026.1.15-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dcd31594264029b57bf16f37fd7248a70b3b764ed9e0839a8f271b2d22c0785", size = 773446, upload-time = "2026-01-14T23:14:28.109Z" }, + { url = "https://files.pythonhosted.org/packages/af/89/bf22cac25cb4ba0fe6bff52ebedbb65b77a179052a9d6037136ae93f42f4/regex-2026.1.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c08c1f3e34338256732bd6938747daa3c0d5b251e04b6e43b5813e94d503076e", size = 783051, upload-time = "2026-01-14T23:14:29.929Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f4/6ed03e71dca6348a5188363a34f5e26ffd5db1404780288ff0d79513bce4/regex-2026.1.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e43a55f378df1e7a4fa3547c88d9a5a9b7113f653a66821bcea4718fe6c58763", size = 854485, upload-time = "2026-01-14T23:14:31.366Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9a/8e8560bd78caded8eb137e3e47612430a05b9a772caf60876435192d670a/regex-2026.1.15-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f82110ab962a541737bd0ce87978d4c658f06e7591ba899192e2712a517badbb", size = 762195, upload-time = "2026-01-14T23:14:32.802Z" }, + { url = "https://files.pythonhosted.org/packages/38/6b/61fc710f9aa8dfcd764fe27d37edfaa023b1a23305a0d84fccd5adb346ea/regex-2026.1.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:27618391db7bdaf87ac6c92b31e8f0dfb83a9de0075855152b720140bda177a2", size = 845986, upload-time = "2026-01-14T23:14:34.898Z" }, + { url = "https://files.pythonhosted.org/packages/fd/2e/fbee4cb93f9d686901a7ca8d94285b80405e8c34fe4107f63ffcbfb56379/regex-2026.1.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bfb0d6be01fbae8d6655c8ca21b3b72458606c4aec9bbc932db758d47aba6db1", size = 788992, upload-time = "2026-01-14T23:14:37.116Z" }, + { url = "https://files.pythonhosted.org/packages/ed/14/3076348f3f586de64b1ab75a3fbabdaab7684af7f308ad43be7ef1849e55/regex-2026.1.15-cp311-cp311-win32.whl", hash = "sha256:b10e42a6de0e32559a92f2f8dc908478cc0fa02838d7dbe764c44dca3fa13569", size = 265893, upload-time = "2026-01-14T23:14:38.426Z" }, + { url = "https://files.pythonhosted.org/packages/0f/19/772cf8b5fc803f5c89ba85d8b1870a1ca580dc482aa030383a9289c82e44/regex-2026.1.15-cp311-cp311-win_amd64.whl", hash = "sha256:e9bf3f0bbdb56633c07d7116ae60a576f846efdd86a8848f8d62b749e1209ca7", size = 277840, upload-time = "2026-01-14T23:14:39.785Z" }, + { url = "https://files.pythonhosted.org/packages/78/84/d05f61142709474da3c0853222d91086d3e1372bcdab516c6fd8d80f3297/regex-2026.1.15-cp311-cp311-win_arm64.whl", hash = "sha256:41aef6f953283291c4e4e6850607bd71502be67779586a61472beacb315c97ec", size = 270374, upload-time = "2026-01-14T23:14:41.592Z" }, + { url = "https://files.pythonhosted.org/packages/92/81/10d8cf43c807d0326efe874c1b79f22bfb0fb226027b0b19ebc26d301408/regex-2026.1.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4c8fcc5793dde01641a35905d6731ee1548f02b956815f8f1cab89e515a5bdf1", size = 489398, upload-time = "2026-01-14T23:14:43.741Z" }, + { url = "https://files.pythonhosted.org/packages/90/b0/7c2a74e74ef2a7c32de724658a69a862880e3e4155cba992ba04d1c70400/regex-2026.1.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bfd876041a956e6a90ad7cdb3f6a630c07d491280bfeed4544053cd434901681", size = 291339, upload-time = "2026-01-14T23:14:45.183Z" }, + { url = "https://files.pythonhosted.org/packages/19/4d/16d0773d0c818417f4cc20aa0da90064b966d22cd62a8c46765b5bd2d643/regex-2026.1.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9250d087bc92b7d4899ccd5539a1b2334e44eee85d848c4c1aef8e221d3f8c8f", size = 289003, upload-time = "2026-01-14T23:14:47.25Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e4/1fc4599450c9f0863d9406e944592d968b8d6dfd0d552a7d569e43bceada/regex-2026.1.15-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8a154cf6537ebbc110e24dabe53095e714245c272da9c1be05734bdad4a61aa", size = 798656, upload-time = "2026-01-14T23:14:48.77Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e6/59650d73a73fa8a60b3a590545bfcf1172b4384a7df2e7fe7b9aab4e2da9/regex-2026.1.15-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8050ba2e3ea1d8731a549e83c18d2f0999fbc99a5f6bd06b4c91449f55291804", size = 864252, upload-time = "2026-01-14T23:14:50.528Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ab/1d0f4d50a1638849a97d731364c9a80fa304fec46325e48330c170ee8e80/regex-2026.1.15-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf065240704cb8951cc04972cf107063917022511273e0969bdb34fc173456c", size = 912268, upload-time = "2026-01-14T23:14:52.952Z" }, + { url = "https://files.pythonhosted.org/packages/dd/df/0d722c030c82faa1d331d1921ee268a4e8fb55ca8b9042c9341c352f17fa/regex-2026.1.15-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c32bef3e7aeee75746748643667668ef941d28b003bfc89994ecf09a10f7a1b5", size = 803589, upload-time = "2026-01-14T23:14:55.182Z" }, + { url = "https://files.pythonhosted.org/packages/66/23/33289beba7ccb8b805c6610a8913d0131f834928afc555b241caabd422a9/regex-2026.1.15-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5eaa4a4c5b1906bd0d2508d68927f15b81821f85092e06f1a34a4254b0e1af3", size = 775700, upload-time = "2026-01-14T23:14:56.707Z" }, + { url = "https://files.pythonhosted.org/packages/e7/65/bf3a42fa6897a0d3afa81acb25c42f4b71c274f698ceabd75523259f6688/regex-2026.1.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:86c1077a3cc60d453d4084d5b9649065f3bf1184e22992bd322e1f081d3117fb", size = 787928, upload-time = "2026-01-14T23:14:58.312Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f5/13bf65864fc314f68cdd6d8ca94adcab064d4d39dbd0b10fef29a9da48fc/regex-2026.1.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2b091aefc05c78d286657cd4db95f2e6313375ff65dcf085e42e4c04d9c8d410", size = 858607, upload-time = "2026-01-14T23:15:00.657Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/040e589834d7a439ee43fb0e1e902bc81bd58a5ba81acffe586bb3321d35/regex-2026.1.15-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:57e7d17f59f9ebfa9667e6e5a1c0127b96b87cb9cede8335482451ed00788ba4", size = 763729, upload-time = "2026-01-14T23:15:02.248Z" }, + { url = "https://files.pythonhosted.org/packages/9b/84/6921e8129687a427edf25a34a5594b588b6d88f491320b9de5b6339a4fcb/regex-2026.1.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:c6c4dcdfff2c08509faa15d36ba7e5ef5fcfab25f1e8f85a0c8f45bc3a30725d", size = 850697, upload-time = "2026-01-14T23:15:03.878Z" }, + { url = "https://files.pythonhosted.org/packages/8a/87/3d06143d4b128f4229158f2de5de6c8f2485170c7221e61bf381313314b2/regex-2026.1.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf8ff04c642716a7f2048713ddc6278c5fd41faa3b9cab12607c7abecd012c22", size = 789849, upload-time = "2026-01-14T23:15:06.102Z" }, + { url = "https://files.pythonhosted.org/packages/77/69/c50a63842b6bd48850ebc7ab22d46e7a2a32d824ad6c605b218441814639/regex-2026.1.15-cp312-cp312-win32.whl", hash = "sha256:82345326b1d8d56afbe41d881fdf62f1926d7264b2fc1537f99ae5da9aad7913", size = 266279, upload-time = "2026-01-14T23:15:07.678Z" }, + { url = "https://files.pythonhosted.org/packages/f2/36/39d0b29d087e2b11fd8191e15e81cce1b635fcc845297c67f11d0d19274d/regex-2026.1.15-cp312-cp312-win_amd64.whl", hash = "sha256:4def140aa6156bc64ee9912383d4038f3fdd18fee03a6f222abd4de6357ce42a", size = 277166, upload-time = "2026-01-14T23:15:09.257Z" }, + { url = "https://files.pythonhosted.org/packages/28/32/5b8e476a12262748851fa8ab1b0be540360692325975b094e594dfebbb52/regex-2026.1.15-cp312-cp312-win_arm64.whl", hash = "sha256:c6c565d9a6e1a8d783c1948937ffc377dd5771e83bd56de8317c450a954d2056", size = 270415, upload-time = "2026-01-14T23:15:10.743Z" }, + { url = "https://files.pythonhosted.org/packages/f8/2e/6870bb16e982669b674cce3ee9ff2d1d46ab80528ee6bcc20fb2292efb60/regex-2026.1.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e69d0deeb977ffe7ed3d2e4439360089f9c3f217ada608f0f88ebd67afb6385e", size = 489164, upload-time = "2026-01-14T23:15:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/9774542e203849b0286badf67199970a44ebdb0cc5fb739f06e47ada72f8/regex-2026.1.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3601ffb5375de85a16f407854d11cca8fe3f5febbe3ac78fb2866bb220c74d10", size = 291218, upload-time = "2026-01-14T23:15:15.647Z" }, + { url = "https://files.pythonhosted.org/packages/b2/87/b0cda79f22b8dee05f774922a214da109f9a4c0eca5da2c9d72d77ea062c/regex-2026.1.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4c5ef43b5c2d4114eb8ea424bb8c9cec01d5d17f242af88b2448f5ee81caadbc", size = 288895, upload-time = "2026-01-14T23:15:17.788Z" }, + { url = "https://files.pythonhosted.org/packages/3b/6a/0041f0a2170d32be01ab981d6346c83a8934277d82c780d60b127331f264/regex-2026.1.15-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:968c14d4f03e10b2fd960f1d5168c1f0ac969381d3c1fcc973bc45fb06346599", size = 798680, upload-time = "2026-01-14T23:15:19.342Z" }, + { url = "https://files.pythonhosted.org/packages/58/de/30e1cfcdbe3e891324aa7568b7c968771f82190df5524fabc1138cb2d45a/regex-2026.1.15-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56a5595d0f892f214609c9f76b41b7428bed439d98dc961efafdd1354d42baae", size = 864210, upload-time = "2026-01-14T23:15:22.005Z" }, + { url = "https://files.pythonhosted.org/packages/64/44/4db2f5c5ca0ccd40ff052ae7b1e9731352fcdad946c2b812285a7505ca75/regex-2026.1.15-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf650f26087363434c4e560011f8e4e738f6f3e029b85d4904c50135b86cfa5", size = 912358, upload-time = "2026-01-14T23:15:24.569Z" }, + { url = "https://files.pythonhosted.org/packages/79/b6/e6a5665d43a7c42467138c8a2549be432bad22cbd206f5ec87162de74bd7/regex-2026.1.15-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18388a62989c72ac24de75f1449d0fb0b04dfccd0a1a7c1c43af5eb503d890f6", size = 803583, upload-time = "2026-01-14T23:15:26.526Z" }, + { url = "https://files.pythonhosted.org/packages/e7/53/7cd478222169d85d74d7437e74750005e993f52f335f7c04ff7adfda3310/regex-2026.1.15-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d220a2517f5893f55daac983bfa9fe998a7dbcaee4f5d27a88500f8b7873788", size = 775782, upload-time = "2026-01-14T23:15:29.352Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b5/75f9a9ee4b03a7c009fe60500fe550b45df94f0955ca29af16333ef557c5/regex-2026.1.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9c08c2fbc6120e70abff5d7f28ffb4d969e14294fb2143b4b5c7d20e46d1714", size = 787978, upload-time = "2026-01-14T23:15:31.295Z" }, + { url = "https://files.pythonhosted.org/packages/72/b3/79821c826245bbe9ccbb54f6eadb7879c722fd3e0248c17bfc90bf54e123/regex-2026.1.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7ef7d5d4bd49ec7364315167a4134a015f61e8266c6d446fc116a9ac4456e10d", size = 858550, upload-time = "2026-01-14T23:15:33.558Z" }, + { url = "https://files.pythonhosted.org/packages/4a/85/2ab5f77a1c465745bfbfcb3ad63178a58337ae8d5274315e2cc623a822fa/regex-2026.1.15-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6e42844ad64194fa08d5ccb75fe6a459b9b08e6d7296bd704460168d58a388f3", size = 763747, upload-time = "2026-01-14T23:15:35.206Z" }, + { url = "https://files.pythonhosted.org/packages/6d/84/c27df502d4bfe2873a3e3a7cf1bdb2b9cc10284d1a44797cf38bed790470/regex-2026.1.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cfecdaa4b19f9ca534746eb3b55a5195d5c95b88cac32a205e981ec0a22b7d31", size = 850615, upload-time = "2026-01-14T23:15:37.523Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b7/658a9782fb253680aa8ecb5ccbb51f69e088ed48142c46d9f0c99b46c575/regex-2026.1.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:08df9722d9b87834a3d701f3fca570b2be115654dbfd30179f30ab2f39d606d3", size = 789951, upload-time = "2026-01-14T23:15:39.582Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2a/5928af114441e059f15b2f63e188bd00c6529b3051c974ade7444b85fcda/regex-2026.1.15-cp313-cp313-win32.whl", hash = "sha256:d426616dae0967ca225ab12c22274eb816558f2f99ccb4a1d52ca92e8baf180f", size = 266275, upload-time = "2026-01-14T23:15:42.108Z" }, + { url = "https://files.pythonhosted.org/packages/4f/16/5bfbb89e435897bff28cf0352a992ca719d9e55ebf8b629203c96b6ce4f7/regex-2026.1.15-cp313-cp313-win_amd64.whl", hash = "sha256:febd38857b09867d3ed3f4f1af7d241c5c50362e25ef43034995b77a50df494e", size = 277145, upload-time = "2026-01-14T23:15:44.244Z" }, + { url = "https://files.pythonhosted.org/packages/56/c1/a09ff7392ef4233296e821aec5f78c51be5e91ffde0d163059e50fd75835/regex-2026.1.15-cp313-cp313-win_arm64.whl", hash = "sha256:8e32f7896f83774f91499d239e24cebfadbc07639c1494bb7213983842348337", size = 270411, upload-time = "2026-01-14T23:15:45.858Z" }, + { url = "https://files.pythonhosted.org/packages/3c/38/0cfd5a78e5c6db00e6782fdae70458f89850ce95baa5e8694ab91d89744f/regex-2026.1.15-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ec94c04149b6a7b8120f9f44565722c7ae31b7a6d2275569d2eefa76b83da3be", size = 492068, upload-time = "2026-01-14T23:15:47.616Z" }, + { url = "https://files.pythonhosted.org/packages/50/72/6c86acff16cb7c959c4355826bbf06aad670682d07c8f3998d9ef4fee7cd/regex-2026.1.15-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40c86d8046915bb9aeb15d3f3f15b6fd500b8ea4485b30e1bbc799dab3fe29f8", size = 292756, upload-time = "2026-01-14T23:15:49.307Z" }, + { url = "https://files.pythonhosted.org/packages/4e/58/df7fb69eadfe76526ddfce28abdc0af09ffe65f20c2c90932e89d705153f/regex-2026.1.15-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:726ea4e727aba21643205edad8f2187ec682d3305d790f73b7a51c7587b64bdd", size = 291114, upload-time = "2026-01-14T23:15:51.484Z" }, + { url = "https://files.pythonhosted.org/packages/ed/6c/a4011cd1cf96b90d2cdc7e156f91efbd26531e822a7fbb82a43c1016678e/regex-2026.1.15-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cb740d044aff31898804e7bf1181cc72c03d11dfd19932b9911ffc19a79070a", size = 807524, upload-time = "2026-01-14T23:15:53.102Z" }, + { url = "https://files.pythonhosted.org/packages/1d/25/a53ffb73183f69c3e9f4355c4922b76d2840aee160af6af5fac229b6201d/regex-2026.1.15-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05d75a668e9ea16f832390d22131fe1e8acc8389a694c8febc3e340b0f810b93", size = 873455, upload-time = "2026-01-14T23:15:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/66/0b/8b47fc2e8f97d9b4a851736f3890a5f786443aa8901061c55f24c955f45b/regex-2026.1.15-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d991483606f3dbec93287b9f35596f41aa2e92b7c2ebbb935b63f409e243c9af", size = 915007, upload-time = "2026-01-14T23:15:57.041Z" }, + { url = "https://files.pythonhosted.org/packages/c2/fa/97de0d681e6d26fabe71968dbee06dd52819e9a22fdce5dac7256c31ed84/regex-2026.1.15-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:194312a14819d3e44628a44ed6fea6898fdbecb0550089d84c403475138d0a09", size = 812794, upload-time = "2026-01-14T23:15:58.916Z" }, + { url = "https://files.pythonhosted.org/packages/22/38/e752f94e860d429654aa2b1c51880bff8dfe8f084268258adf9151cf1f53/regex-2026.1.15-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe2fda4110a3d0bc163c2e0664be44657431440722c5c5315c65155cab92f9e5", size = 781159, upload-time = "2026-01-14T23:16:00.817Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a7/d739ffaef33c378fc888302a018d7f81080393d96c476b058b8c64fd2b0d/regex-2026.1.15-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:124dc36c85d34ef2d9164da41a53c1c8c122cfb1f6e1ec377a1f27ee81deb794", size = 795558, upload-time = "2026-01-14T23:16:03.267Z" }, + { url = "https://files.pythonhosted.org/packages/3e/c4/542876f9a0ac576100fc73e9c75b779f5c31e3527576cfc9cb3009dcc58a/regex-2026.1.15-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1774cd1981cd212506a23a14dba7fdeaee259f5deba2df6229966d9911e767a", size = 868427, upload-time = "2026-01-14T23:16:05.646Z" }, + { url = "https://files.pythonhosted.org/packages/fc/0f/d5655bea5b22069e32ae85a947aa564912f23758e112cdb74212848a1a1b/regex-2026.1.15-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b5f7d8d2867152cdb625e72a530d2ccb48a3d199159144cbdd63870882fb6f80", size = 769939, upload-time = "2026-01-14T23:16:07.542Z" }, + { url = "https://files.pythonhosted.org/packages/20/06/7e18a4fa9d326daeda46d471a44ef94201c46eaa26dbbb780b5d92cbfdda/regex-2026.1.15-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:492534a0ab925d1db998defc3c302dae3616a2fc3fe2e08db1472348f096ddf2", size = 854753, upload-time = "2026-01-14T23:16:10.395Z" }, + { url = "https://files.pythonhosted.org/packages/3b/67/dc8946ef3965e166f558ef3b47f492bc364e96a265eb4a2bb3ca765c8e46/regex-2026.1.15-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c661fc820cfb33e166bf2450d3dadbda47c8d8981898adb9b6fe24e5e582ba60", size = 799559, upload-time = "2026-01-14T23:16:12.347Z" }, + { url = "https://files.pythonhosted.org/packages/a5/61/1bba81ff6d50c86c65d9fd84ce9699dd106438ee4cdb105bf60374ee8412/regex-2026.1.15-cp313-cp313t-win32.whl", hash = "sha256:99ad739c3686085e614bf77a508e26954ff1b8f14da0e3765ff7abbf7799f952", size = 268879, upload-time = "2026-01-14T23:16:14.049Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5e/cef7d4c5fb0ea3ac5c775fd37db5747f7378b29526cc83f572198924ff47/regex-2026.1.15-cp313-cp313t-win_amd64.whl", hash = "sha256:32655d17905e7ff8ba5c764c43cb124e34a9245e45b83c22e81041e1071aee10", size = 280317, upload-time = "2026-01-14T23:16:15.718Z" }, + { url = "https://files.pythonhosted.org/packages/b4/52/4317f7a5988544e34ab57b4bde0f04944c4786128c933fb09825924d3e82/regex-2026.1.15-cp313-cp313t-win_arm64.whl", hash = "sha256:b2a13dd6a95e95a489ca242319d18fc02e07ceb28fa9ad146385194d95b3c829", size = 271551, upload-time = "2026-01-14T23:16:17.533Z" }, + { url = "https://files.pythonhosted.org/packages/52/0a/47fa888ec7cbbc7d62c5f2a6a888878e76169170ead271a35239edd8f0e8/regex-2026.1.15-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:d920392a6b1f353f4aa54328c867fec3320fa50657e25f64abf17af054fc97ac", size = 489170, upload-time = "2026-01-14T23:16:19.835Z" }, + { url = "https://files.pythonhosted.org/packages/ac/c4/d000e9b7296c15737c9301708e9e7fbdea009f8e93541b6b43bdb8219646/regex-2026.1.15-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b5a28980a926fa810dbbed059547b02783952e2efd9c636412345232ddb87ff6", size = 291146, upload-time = "2026-01-14T23:16:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b6/921cc61982e538682bdf3bdf5b2c6ab6b34368da1f8e98a6c1ddc503c9cf/regex-2026.1.15-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:621f73a07595d83f28952d7bd1e91e9d1ed7625fb7af0064d3516674ec93a2a2", size = 288986, upload-time = "2026-01-14T23:16:23.381Z" }, + { url = "https://files.pythonhosted.org/packages/ca/33/eb7383dde0bbc93f4fb9d03453aab97e18ad4024ac7e26cef8d1f0a2cff0/regex-2026.1.15-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d7d92495f47567a9b1669c51fc8d6d809821849063d168121ef801bbc213846", size = 799098, upload-time = "2026-01-14T23:16:25.088Z" }, + { url = "https://files.pythonhosted.org/packages/27/56/b664dccae898fc8d8b4c23accd853f723bde0f026c747b6f6262b688029c/regex-2026.1.15-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8dd16fba2758db7a3780a051f245539c4451ca20910f5a5e6ea1c08d06d4a76b", size = 864980, upload-time = "2026-01-14T23:16:27.297Z" }, + { url = "https://files.pythonhosted.org/packages/16/40/0999e064a170eddd237bae9ccfcd8f28b3aa98a38bf727a086425542a4fc/regex-2026.1.15-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1e1808471fbe44c1a63e5f577a1d5f02fe5d66031dcbdf12f093ffc1305a858e", size = 911607, upload-time = "2026-01-14T23:16:29.235Z" }, + { url = "https://files.pythonhosted.org/packages/07/78/c77f644b68ab054e5a674fb4da40ff7bffb2c88df58afa82dbf86573092d/regex-2026.1.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0751a26ad39d4f2ade8fe16c59b2bf5cb19eb3d2cd543e709e583d559bd9efde", size = 803358, upload-time = "2026-01-14T23:16:31.369Z" }, + { url = "https://files.pythonhosted.org/packages/27/31/d4292ea8566eaa551fafc07797961c5963cf5235c797cc2ae19b85dfd04d/regex-2026.1.15-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0f0c7684c7f9ca241344ff95a1de964f257a5251968484270e91c25a755532c5", size = 775833, upload-time = "2026-01-14T23:16:33.141Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b2/cff3bf2fea4133aa6fb0d1e370b37544d18c8350a2fa118c7e11d1db0e14/regex-2026.1.15-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74f45d170a21df41508cb67165456538425185baaf686281fa210d7e729abc34", size = 788045, upload-time = "2026-01-14T23:16:35.005Z" }, + { url = "https://files.pythonhosted.org/packages/8d/99/2cb9b69045372ec877b6f5124bda4eb4253bc58b8fe5848c973f752bc52c/regex-2026.1.15-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f1862739a1ffb50615c0fde6bae6569b5efbe08d98e59ce009f68a336f64da75", size = 859374, upload-time = "2026-01-14T23:16:36.919Z" }, + { url = "https://files.pythonhosted.org/packages/09/16/710b0a5abe8e077b1729a562d2f297224ad079f3a66dce46844c193416c8/regex-2026.1.15-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:453078802f1b9e2b7303fb79222c054cb18e76f7bdc220f7530fdc85d319f99e", size = 763940, upload-time = "2026-01-14T23:16:38.685Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/7585c8e744e40eb3d32f119191969b91de04c073fca98ec14299041f6e7e/regex-2026.1.15-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:a30a68e89e5a218b8b23a52292924c1f4b245cb0c68d1cce9aec9bbda6e2c160", size = 850112, upload-time = "2026-01-14T23:16:40.646Z" }, + { url = "https://files.pythonhosted.org/packages/af/d6/43e1dd85df86c49a347aa57c1f69d12c652c7b60e37ec162e3096194a278/regex-2026.1.15-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9479cae874c81bf610d72b85bb681a94c95722c127b55445285fb0e2c82db8e1", size = 789586, upload-time = "2026-01-14T23:16:42.799Z" }, + { url = "https://files.pythonhosted.org/packages/93/38/77142422f631e013f316aaae83234c629555729a9fbc952b8a63ac91462a/regex-2026.1.15-cp314-cp314-win32.whl", hash = "sha256:d639a750223132afbfb8f429c60d9d318aeba03281a5f1ab49f877456448dcf1", size = 271691, upload-time = "2026-01-14T23:16:44.671Z" }, + { url = "https://files.pythonhosted.org/packages/4a/a9/ab16b4649524ca9e05213c1cdbb7faa85cc2aa90a0230d2f796cbaf22736/regex-2026.1.15-cp314-cp314-win_amd64.whl", hash = "sha256:4161d87f85fa831e31469bfd82c186923070fc970b9de75339b68f0c75b51903", size = 280422, upload-time = "2026-01-14T23:16:46.607Z" }, + { url = "https://files.pythonhosted.org/packages/be/2a/20fd057bf3521cb4791f69f869635f73e0aaf2b9ad2d260f728144f9047c/regex-2026.1.15-cp314-cp314-win_arm64.whl", hash = "sha256:91c5036ebb62663a6b3999bdd2e559fd8456d17e2b485bf509784cd31a8b1705", size = 273467, upload-time = "2026-01-14T23:16:48.967Z" }, + { url = "https://files.pythonhosted.org/packages/ad/77/0b1e81857060b92b9cad239104c46507dd481b3ff1fa79f8e7f865aae38a/regex-2026.1.15-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ee6854c9000a10938c79238de2379bea30c82e4925a371711af45387df35cab8", size = 492073, upload-time = "2026-01-14T23:16:51.154Z" }, + { url = "https://files.pythonhosted.org/packages/70/f3/f8302b0c208b22c1e4f423147e1913fd475ddd6230565b299925353de644/regex-2026.1.15-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c2b80399a422348ce5de4fe40c418d6299a0fa2803dd61dc0b1a2f28e280fcf", size = 292757, upload-time = "2026-01-14T23:16:53.08Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f0/ef55de2460f3b4a6da9d9e7daacd0cb79d4ef75c64a2af316e68447f0df0/regex-2026.1.15-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:dca3582bca82596609959ac39e12b7dad98385b4fefccb1151b937383cec547d", size = 291122, upload-time = "2026-01-14T23:16:55.383Z" }, + { url = "https://files.pythonhosted.org/packages/cf/55/bb8ccbacabbc3a11d863ee62a9f18b160a83084ea95cdfc5d207bfc3dd75/regex-2026.1.15-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef71d476caa6692eea743ae5ea23cde3260677f70122c4d258ca952e5c2d4e84", size = 807761, upload-time = "2026-01-14T23:16:57.251Z" }, + { url = "https://files.pythonhosted.org/packages/8f/84/f75d937f17f81e55679a0509e86176e29caa7298c38bd1db7ce9c0bf6075/regex-2026.1.15-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c243da3436354f4af6c3058a3f81a97d47ea52c9bd874b52fd30274853a1d5df", size = 873538, upload-time = "2026-01-14T23:16:59.349Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d9/0da86327df70349aa8d86390da91171bd3ca4f0e7c1d1d453a9c10344da3/regex-2026.1.15-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8355ad842a7c7e9e5e55653eade3b7d1885ba86f124dd8ab1f722f9be6627434", size = 915066, upload-time = "2026-01-14T23:17:01.607Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5e/f660fb23fc77baa2a61aa1f1fe3a4eea2bbb8a286ddec148030672e18834/regex-2026.1.15-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f192a831d9575271a22d804ff1a5355355723f94f31d9eef25f0d45a152fdc1a", size = 812938, upload-time = "2026-01-14T23:17:04.366Z" }, + { url = "https://files.pythonhosted.org/packages/69/33/a47a29bfecebbbfd1e5cd3f26b28020a97e4820f1c5148e66e3b7d4b4992/regex-2026.1.15-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:166551807ec20d47ceaeec380081f843e88c8949780cd42c40f18d16168bed10", size = 781314, upload-time = "2026-01-14T23:17:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/65/ec/7ec2bbfd4c3f4e494a24dec4c6943a668e2030426b1b8b949a6462d2c17b/regex-2026.1.15-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9ca1cbdc0fbfe5e6e6f8221ef2309988db5bcede52443aeaee9a4ad555e0dac", size = 795652, upload-time = "2026-01-14T23:17:08.521Z" }, + { url = "https://files.pythonhosted.org/packages/46/79/a5d8651ae131fe27d7c521ad300aa7f1c7be1dbeee4d446498af5411b8a9/regex-2026.1.15-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b30bcbd1e1221783c721483953d9e4f3ab9c5d165aa709693d3f3946747b1aea", size = 868550, upload-time = "2026-01-14T23:17:10.573Z" }, + { url = "https://files.pythonhosted.org/packages/06/b7/25635d2809664b79f183070786a5552dd4e627e5aedb0065f4e3cf8ee37d/regex-2026.1.15-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2a8d7b50c34578d0d3bf7ad58cde9652b7d683691876f83aedc002862a35dc5e", size = 769981, upload-time = "2026-01-14T23:17:12.871Z" }, + { url = "https://files.pythonhosted.org/packages/16/8b/fc3fcbb2393dcfa4a6c5ffad92dc498e842df4581ea9d14309fcd3c55fb9/regex-2026.1.15-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9d787e3310c6a6425eb346be4ff2ccf6eece63017916fd77fe8328c57be83521", size = 854780, upload-time = "2026-01-14T23:17:14.837Z" }, + { url = "https://files.pythonhosted.org/packages/d0/38/dde117c76c624713c8a2842530be9c93ca8b606c0f6102d86e8cd1ce8bea/regex-2026.1.15-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:619843841e220adca114118533a574a9cd183ed8a28b85627d2844c500a2b0db", size = 799778, upload-time = "2026-01-14T23:17:17.369Z" }, + { url = "https://files.pythonhosted.org/packages/e3/0d/3a6cfa9ae99606afb612d8fb7a66b245a9d5ff0f29bb347c8a30b6ad561b/regex-2026.1.15-cp314-cp314t-win32.whl", hash = "sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e", size = 274667, upload-time = "2026-01-14T23:17:19.301Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b2/297293bb0742fd06b8d8e2572db41a855cdf1cae0bf009b1cb74fe07e196/regex-2026.1.15-cp314-cp314t-win_amd64.whl", hash = "sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf", size = 284386, upload-time = "2026-01-14T23:17:21.231Z" }, + { url = "https://files.pythonhosted.org/packages/95/e4/a3b9480c78cf8ee86626cb06f8d931d74d775897d44201ccb813097ae697/regex-2026.1.15-cp314-cp314t-win_arm64.whl", hash = "sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70", size = 274837, upload-time = "2026-01-14T23:17:23.146Z" }, + { url = "https://files.pythonhosted.org/packages/a2/e7/0e1913dc52eee9c5cf8417c9813c4c55972a3f37d27cfa2e623b79b63dbc/regex-2026.1.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:55b4ea996a8e4458dd7b584a2f89863b1655dd3d17b88b46cbb9becc495a0ec5", size = 488185, upload-time = "2026-01-14T23:17:25.2Z" }, + { url = "https://files.pythonhosted.org/packages/78/df/c52c1ff4221529faad0953e197982fe9508c6dbb42327e31bf98ea07472a/regex-2026.1.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e1e28be779884189cdd57735e997f282b64fd7ccf6e2eef3e16e57d7a34a815", size = 290628, upload-time = "2026-01-14T23:17:27.125Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d2/a2fef3717deaff647d7de2bccf899a576c7eaf042b6b271fc4474515fe97/regex-2026.1.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0057de9eaef45783ff69fa94ae9f0fd906d629d0bd4c3217048f46d1daa32e9b", size = 288509, upload-time = "2026-01-14T23:17:29.017Z" }, + { url = "https://files.pythonhosted.org/packages/70/89/faf5ee5c69168753c845a3d58b4683f61c899d162bfe1264fca88d5b3924/regex-2026.1.15-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7cd0b2be0f0269283a45c0d8b2c35e149d1319dcb4a43c9c3689fa935c1ee6", size = 781088, upload-time = "2026-01-14T23:17:30.961Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2c/707e5c380ad547c93686e21144e7e24dc2064dd84ec5b751b6dbdfc9be2b/regex-2026.1.15-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8db052bbd981e1666f09e957f3790ed74080c2229007c1dd67afdbf0b469c48b", size = 850516, upload-time = "2026-01-14T23:17:32.946Z" }, + { url = "https://files.pythonhosted.org/packages/5d/3b/baa816cdcad1c0f8195f9f40ab2b2a2246c8a2989dcd90641c0c6559e3fd/regex-2026.1.15-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:343db82cb3712c31ddf720f097ef17c11dab2f67f7a3e7be976c4f82eba4e6df", size = 898124, upload-time = "2026-01-14T23:17:36.019Z" }, + { url = "https://files.pythonhosted.org/packages/e7/74/1eb46bde30899825ed9fdf645eba16b7b97c49d12d300f5177989b9a09a4/regex-2026.1.15-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:55e9d0118d97794367309635df398bdfd7c33b93e2fdfa0b239661cd74b4c14e", size = 791290, upload-time = "2026-01-14T23:17:38.097Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5d/b72e176fb21e2ec248baed01151a342d1f44dd43c2b6bb6a41ad183b274e/regex-2026.1.15-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:008b185f235acd1e53787333e5690082e4f156c44c87d894f880056089e9bc7c", size = 781996, upload-time = "2026-01-14T23:17:40.109Z" }, + { url = "https://files.pythonhosted.org/packages/61/0e/d3b3710eaafd994a4a71205d114abc38cda8691692a2ce2313abe68e7eb7/regex-2026.1.15-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fd65af65e2aaf9474e468f9e571bd7b189e1df3a61caa59dcbabd0000e4ea839", size = 767578, upload-time = "2026-01-14T23:17:42.134Z" }, + { url = "https://files.pythonhosted.org/packages/09/51/c6a6311833e040f95d229a34d82ac1cec2af8a5c00d58b244f2fceecef87/regex-2026.1.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f42e68301ff4afee63e365a5fc302b81bb8ba31af625a671d7acb19d10168a8c", size = 774354, upload-time = "2026-01-14T23:17:44.392Z" }, + { url = "https://files.pythonhosted.org/packages/cc/97/c522d1f19fb2c549aaf680b115c110cd124c02062bc8c95f33db8583b4bb/regex-2026.1.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f7792f27d3ee6e0244ea4697d92b825f9a329ab5230a78c1a68bd274e64b5077", size = 845297, upload-time = "2026-01-14T23:17:47.145Z" }, + { url = "https://files.pythonhosted.org/packages/99/a0/99468c386ab68a5e24c946c5c353c29c33a95523e275c17839f2446db15d/regex-2026.1.15-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:dbaf3c3c37ef190439981648ccbf0c02ed99ae066087dd117fcb616d80b010a4", size = 755132, upload-time = "2026-01-14T23:17:49.796Z" }, + { url = "https://files.pythonhosted.org/packages/70/33/d5748c7b6c9d3621f12570583561ba529e2d1b12e4f70b8f17979b133e65/regex-2026.1.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:adc97a9077c2696501443d8ad3fa1b4fc6d131fc8fd7dfefd1a723f89071cf0a", size = 835662, upload-time = "2026-01-14T23:17:52.559Z" }, + { url = "https://files.pythonhosted.org/packages/ad/15/1986972c276672505437f1ba3c9706c2d91f321cfb9b2f4d06e8bff1b999/regex-2026.1.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:069f56a7bf71d286a6ff932a9e6fb878f151c998ebb2519a9f6d1cee4bffdba3", size = 779513, upload-time = "2026-01-14T23:17:54.711Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f9/124f6a5cb3969d8e30471ed4f46cfc17c47aef1a9863ee8b4ba1d98b1bc4/regex-2026.1.15-cp39-cp39-win32.whl", hash = "sha256:ea4e6b3566127fda5e007e90a8fd5a4169f0cf0619506ed426db647f19c8454a", size = 265923, upload-time = "2026-01-14T23:17:56.69Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c2/bb8fad7d27f1d71fc9772befd544bccd22eddc62a6735f57b003b4aff005/regex-2026.1.15-cp39-cp39-win_amd64.whl", hash = "sha256:cda1ed70d2b264952e88adaa52eea653a33a1b98ac907ae2f86508eb44f65cdc", size = 277900, upload-time = "2026-01-14T23:17:58.72Z" }, + { url = "https://files.pythonhosted.org/packages/f7/fa/4e033327c1d8350bc812cac906d873984d3d4b39529252f392a47ccc356d/regex-2026.1.15-cp39-cp39-win_arm64.whl", hash = "sha256:b325d4714c3c48277bfea1accd94e193ad6ed42b4bad79ad64f3b8f8a31260a5", size = 270413, upload-time = "2026-01-14T23:18:00.764Z" }, ] [[package]] @@ -4076,6 +6070,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/45/615f5babd880b4bd7d405cc0dc348234c5ffb6ed1ea33e152ede08b2072d/rich-14.3.2-py3-none-any.whl", hash = "sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69", size = 309963, upload-time = "2026-02-01T16:20:46.078Z" }, ] +[[package]] +name = "rich-rst" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" }, +] + [[package]] name = "rich-toolkit" version = "0.18.1" @@ -4374,28 +6381,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.14.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" }, - { url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" }, - { url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" }, - { url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" }, - { url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" }, - { url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" }, - { url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" }, - { url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" }, - { url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" }, - { url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" }, - { url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" }, - { url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" }, - { url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" }, - { url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" }, - { url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" }, - { url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" }, +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/39/5cee96809fbca590abea6b46c6d1c586b49663d1d2830a751cc8fc42c666/ruff-0.15.0.tar.gz", hash = "sha256:6bdea47cdbea30d40f8f8d7d69c0854ba7c15420ec75a26f463290949d7f7e9a", size = 4524893, upload-time = "2026-02-03T17:53:35.357Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/88/3fd1b0aa4b6330d6aaa63a285bc96c9f71970351579152d231ed90914586/ruff-0.15.0-py3-none-linux_armv6l.whl", hash = "sha256:aac4ebaa612a82b23d45964586f24ae9bc23ca101919f5590bdb368d74ad5455", size = 10354332, upload-time = "2026-02-03T17:52:54.892Z" }, + { url = "https://files.pythonhosted.org/packages/72/f6/62e173fbb7eb75cc29fe2576a1e20f0a46f671a2587b5f604bfb0eaf5f6f/ruff-0.15.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dcd4be7cc75cfbbca24a98d04d0b9b36a270d0833241f776b788d59f4142b14d", size = 10767189, upload-time = "2026-02-03T17:53:19.778Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/968ae17b676d1d2ff101d56dc69cf333e3a4c985e1ec23803df84fc7bf9e/ruff-0.15.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d747e3319b2bce179c7c1eaad3d884dc0a199b5f4d5187620530adf9105268ce", size = 10075384, upload-time = "2026-02-03T17:53:29.241Z" }, + { url = "https://files.pythonhosted.org/packages/a2/bf/9843c6044ab9e20af879c751487e61333ca79a2c8c3058b15722386b8cae/ruff-0.15.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:650bd9c56ae03102c51a5e4b554d74d825ff3abe4db22b90fd32d816c2e90621", size = 10481363, upload-time = "2026-02-03T17:52:43.332Z" }, + { url = "https://files.pythonhosted.org/packages/55/d9/4ada5ccf4cd1f532db1c8d44b6f664f2208d3d93acbeec18f82315e15193/ruff-0.15.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6664b7eac559e3048223a2da77769c2f92b43a6dfd4720cef42654299a599c9", size = 10187736, upload-time = "2026-02-03T17:53:00.522Z" }, + { url = "https://files.pythonhosted.org/packages/86/e2/f25eaecd446af7bb132af0a1d5b135a62971a41f5366ff41d06d25e77a91/ruff-0.15.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f811f97b0f092b35320d1556f3353bf238763420ade5d9e62ebd2b73f2ff179", size = 10968415, upload-time = "2026-02-03T17:53:15.705Z" }, + { url = "https://files.pythonhosted.org/packages/e7/dc/f06a8558d06333bf79b497d29a50c3a673d9251214e0d7ec78f90b30aa79/ruff-0.15.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:761ec0a66680fab6454236635a39abaf14198818c8cdf691e036f4bc0f406b2d", size = 11809643, upload-time = "2026-02-03T17:53:23.031Z" }, + { url = "https://files.pythonhosted.org/packages/dd/45/0ece8db2c474ad7df13af3a6d50f76e22a09d078af63078f005057ca59eb/ruff-0.15.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:940f11c2604d317e797b289f4f9f3fa5555ffe4fb574b55ed006c3d9b6f0eb78", size = 11234787, upload-time = "2026-02-03T17:52:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d9/0e3a81467a120fd265658d127db648e4d3acfe3e4f6f5d4ea79fac47e587/ruff-0.15.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcbca3d40558789126da91d7ef9a7c87772ee107033db7191edefa34e2c7f1b4", size = 11112797, upload-time = "2026-02-03T17:52:49.274Z" }, + { url = "https://files.pythonhosted.org/packages/b2/cb/8c0b3b0c692683f8ff31351dfb6241047fa873a4481a76df4335a8bff716/ruff-0.15.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9a121a96db1d75fa3eb39c4539e607f628920dd72ff1f7c5ee4f1b768ac62d6e", size = 11033133, upload-time = "2026-02-03T17:53:33.105Z" }, + { url = "https://files.pythonhosted.org/packages/f8/5e/23b87370cf0f9081a8c89a753e69a4e8778805b8802ccfe175cc410e50b9/ruff-0.15.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5298d518e493061f2eabd4abd067c7e4fb89e2f63291c94332e35631c07c3662", size = 10442646, upload-time = "2026-02-03T17:53:06.278Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9a/3c94de5ce642830167e6d00b5c75aacd73e6347b4c7fc6828699b150a5ee/ruff-0.15.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afb6e603d6375ff0d6b0cee563fa21ab570fd15e65c852cb24922cef25050cf1", size = 10195750, upload-time = "2026-02-03T17:53:26.084Z" }, + { url = "https://files.pythonhosted.org/packages/30/15/e396325080d600b436acc970848d69df9c13977942fb62bb8722d729bee8/ruff-0.15.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:77e515f6b15f828b94dc17d2b4ace334c9ddb7d9468c54b2f9ed2b9c1593ef16", size = 10676120, upload-time = "2026-02-03T17:53:09.363Z" }, + { url = "https://files.pythonhosted.org/packages/8d/c9/229a23d52a2983de1ad0fb0ee37d36e0257e6f28bfd6b498ee2c76361874/ruff-0.15.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6f6e80850a01eb13b3e42ee0ebdf6e4497151b48c35051aab51c101266d187a3", size = 11201636, upload-time = "2026-02-03T17:52:57.281Z" }, + { url = "https://files.pythonhosted.org/packages/6f/b0/69adf22f4e24f3677208adb715c578266842e6e6a3cc77483f48dd999ede/ruff-0.15.0-py3-none-win32.whl", hash = "sha256:238a717ef803e501b6d51e0bdd0d2c6e8513fe9eec14002445134d3907cd46c3", size = 10465945, upload-time = "2026-02-03T17:53:12.591Z" }, + { url = "https://files.pythonhosted.org/packages/51/ad/f813b6e2c97e9b4598be25e94a9147b9af7e60523b0cb5d94d307c15229d/ruff-0.15.0-py3-none-win_amd64.whl", hash = "sha256:dd5e4d3301dc01de614da3cdffc33d4b1b96fb89e45721f1598e5532ccf78b18", size = 11564657, upload-time = "2026-02-03T17:52:51.893Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b0/2d823f6e77ebe560f4e397d078487e8d52c1516b331e3521bc75db4272ca/ruff-0.15.0-py3-none-win_arm64.whl", hash = "sha256:c480d632cc0ca3f0727acac8b7d053542d9e114a462a145d0b00e7cd658c515a", size = 10865753, upload-time = "2026-02-03T17:53:03.014Z" }, ] [[package]] @@ -4410,6 +6416,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/51/727abb13f44c1fcf6d145979e1535a35794db0f6e450a0cb46aa24732fe2/s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe", size = 86830, upload-time = "2025-12-01T02:30:57.729Z" }, ] +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography", marker = "python_full_version >= '3.10'" }, + { name = "jeepney", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, +] + [[package]] name = "sentry-sdk" version = "2.52.0" @@ -4548,15 +6567,15 @@ wheels = [ [[package]] name = "sqlmodel" -version = "0.0.31" +version = "0.0.32" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "sqlalchemy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/56/b8/e7cd6def4a773f25d6e29ffce63ccbfd6cf9488b804ab6fb9b80d334b39d/sqlmodel-0.0.31.tar.gz", hash = "sha256:2d41a8a9ee05e40736e2f9db8ea28cbfe9b5d4e5a18dd139e80605025e0c516c", size = 94952, upload-time = "2025-12-28T12:35:01.436Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/89/67f8964f3b2ed073fa4e95201e708291935d00e3600f36f09c1be3e279fe/sqlmodel-0.0.32.tar.gz", hash = "sha256:48e8fe4c8c3d7d8bf8468db17fa92ca680421e86cfec8b352217ef40736767be", size = 94140, upload-time = "2026-02-01T18:19:14.752Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/72/5aa5be921800f6418a949a73c9bb7054890881143e6bc604a93d228a95a3/sqlmodel-0.0.31-py3-none-any.whl", hash = "sha256:6d946d56cac4c2db296ba1541357cee2e795d68174e2043cd138b916794b1513", size = 27093, upload-time = "2025-12-28T12:35:00.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/de/d9b40ed2c570fd612c2abd57e4d9084a9d8eb1797447e2ce897b77b1c4b2/sqlmodel-0.0.32-py3-none-any.whl", hash = "sha256:d62f0702599592046c1a136d3512feab3d5a80e2988642ef0ed2c89b9b8b297b", size = 27416, upload-time = "2026-02-01T18:19:15.992Z" }, ] [[package]] @@ -4565,7 +6584,7 @@ version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "starlette", version = "0.50.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8b/8d/00d280c03ffd39aaee0e86ec81e2d3b9253036a0f93f51d10503adef0e65/sse_starlette-3.2.0.tar.gz", hash = "sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422", size = 27253, upload-time = "2026-01-17T13:11:05.62Z" } wheels = [ @@ -4590,7 +6609,7 @@ wheels = [ [[package]] name = "starlette" -version = "0.50.0" +version = "0.52.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", @@ -4600,9 +6619,9 @@ dependencies = [ { name = "anyio", marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" }, + { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, ] [[package]] @@ -4626,7 +6645,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.291.1" +version = "0.291.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", @@ -4639,9 +6658,9 @@ dependencies = [ { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/61/18/5a07bc95bdf1cb73e93cd1f1d5b11750ded6f5e4d9407e7d500abc635b36/strawberry_graphql-0.291.1.tar.gz", hash = "sha256:13463d09e042857e4c12eee0eafc2bbdef963e4a30e20ed9a9c9fb0d487d4aac", size = 217765, upload-time = "2026-02-06T10:07:15.861Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/dd/e0e68f4b17da6ff5773fcd4bebf86fc4ff8620c854be816d047e9af8c4aa/strawberry_graphql-0.291.2.tar.gz", hash = "sha256:e6076604a786e8437bc64a27348584c082113442f072daf757b56e4863543a97", size = 217730, upload-time = "2026-02-06T14:40:51.173Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/7b/47ec56118decc90b9ae85a98180dc326fdad2ee031cba0e05c6c62349b88/strawberry_graphql-0.291.1-py3-none-any.whl", hash = "sha256:09798d3172b42be4d5526771ec581e1b1f93c7020b82a8b07b4c507676f75aa0", size = 316439, upload-time = "2026-02-06T10:07:18.247Z" }, + { url = "https://files.pythonhosted.org/packages/6f/14/93908a029605955e3411cdb0f2e8cfe170e5331da23357ed71d5c51b15bc/strawberry_graphql-0.291.2-py3-none-any.whl", hash = "sha256:f71d3669086c6747fd4760e6fafe3605d9a33f7d168886e5edd2b61a04972e56", size = 316389, upload-time = "2026-02-06T14:40:53.482Z" }, ] [[package]] @@ -4656,6 +6675,65 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/17/43/47c7cf84b3bd74a8631b02d47db356656bb8dff6f2e61a4c749963814d0d/super_collections-0.6.2-py3-none-any.whl", hash = "sha256:291b74d26299e9051d69ad9d89e61b07b6646f86a57a2f5ab3063d206eee9c56", size = 16173, upload-time = "2025-09-30T00:37:07.104Z" }, ] +[[package]] +name = "taskgroup" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version >= '3.10' and python_full_version < '3.14'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.14'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f0/8d/e218e0160cc1b692e6e0e5ba34e8865dbb171efeb5fc9a704544b3020605/taskgroup-0.2.2.tar.gz", hash = "sha256:078483ac3e78f2e3f973e2edbf6941374fbea81b9c5d0a96f51d297717f4752d", size = 11504, upload-time = "2025-01-03T09:24:13.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/b1/74babcc824a57904e919f3af16d86c08b524c0691504baf038ef2d7f655c/taskgroup-0.2.2-py2.py3-none-any.whl", hash = "sha256:e2c53121609f4ae97303e9ea1524304b4de6faf9eb2c9280c7f87976479a52fb", size = 14237, upload-time = "2025-01-03T09:24:11.41Z" }, +] + +[[package]] +name = "temporalio" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "nexus-rpc", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "protobuf", version = "5.29.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "python-dateutil", marker = "python_full_version < '3.10'" }, + { name = "types-protobuf", marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/32/375ab75d0ebb468cf9c8abbc450a03d3a8c66401fc320b338bd8c00d36b4/temporalio-1.16.0.tar.gz", hash = "sha256:dd926f3e30626fd4edf5e0ce596b75ecb5bbe0e4a0281e545ac91b5577967c91", size = 1733873, upload-time = "2025-08-21T22:12:50.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/36/12bb7234c83ddca4b8b032c8f1a9e07a03067c6ed6d2ddb39c770a4c87c6/temporalio-1.16.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:547c0853310350d3e5b5b9c806246cbf2feb523f685b05bf14ec1b0ece8a7bb6", size = 12540769, upload-time = "2025-08-21T22:11:24.551Z" }, + { url = "https://files.pythonhosted.org/packages/3c/16/a7d402435b8f994979abfeffd3f5ffcaaeada467ac16438e61c51c9f7abe/temporalio-1.16.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b05bb0d06025645aed6f936615311a6774eb8dc66280f32a810aac2283e1258", size = 12968631, upload-time = "2025-08-21T22:11:48.375Z" }, + { url = "https://files.pythonhosted.org/packages/11/6f/16663eef877b61faa5fd917b3a63497416ec4319195af75f6169a1594479/temporalio-1.16.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a08aed4e0f6c2b6bfc779b714e91dfe8c8491a0ddb4c4370627bb07f9bddcfd", size = 13164612, upload-time = "2025-08-21T22:12:16.366Z" }, + { url = "https://files.pythonhosted.org/packages/af/0e/8c6704ca7033aa09dc084f285d70481d758972cc341adc3c84d5f82f7b01/temporalio-1.16.0-cp39-abi3-win_amd64.whl", hash = "sha256:7c190362b0d7254f1f93fb71456063e7b299ac85a89f6227758af82c6a5aa65b", size = 13177058, upload-time = "2025-08-21T22:12:44.239Z" }, +] + +[[package]] +name = "temporalio" +version = "1.20.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version >= '3.10' and python_full_version < '3.14'", +] +dependencies = [ + { name = "nexus-rpc", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "python-dateutil", marker = "python_full_version == '3.10.*'" }, + { name = "types-protobuf", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/db/7d5118d28b0918888e1ec98f56f659fdb006351e06d95f30f4274962a76f/temporalio-1.20.0.tar.gz", hash = "sha256:5a6a85b7d298b7359bffa30025f7deac83c74ac095a4c6952fbf06c249a2a67c", size = 1850498, upload-time = "2025-11-25T21:25:20.225Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/1b/e69052aa6003eafe595529485d9c62d1382dd5e671108f1bddf544fb6032/temporalio-1.20.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:fba70314b4068f8b1994bddfa0e2ad742483f0ae714d2ef52e63013ccfd7042e", size = 12061638, upload-time = "2025-11-25T21:24:57.918Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3b/3e8c67ed7f23bedfa231c6ac29a7a9c12b89881da7694732270f3ecd6b0c/temporalio-1.20.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffc5bb6cabc6ae67f0bfba44de6a9c121603134ae18784a2ff3a7f230ad99080", size = 11562603, upload-time = "2025-11-25T21:25:01.721Z" }, + { url = "https://files.pythonhosted.org/packages/6d/be/ed0cc11702210522a79e09703267ebeca06eb45832b873a58de3ca76b9d0/temporalio-1.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1e80c1e4cdf88fa8277177f563edc91466fe4dc13c0322f26e55c76b6a219e6", size = 11824016, upload-time = "2025-11-25T21:25:06.771Z" }, + { url = "https://files.pythonhosted.org/packages/9d/97/09c5cafabc80139d97338a2bdd8ec22e08817dfd2949ab3e5b73565006eb/temporalio-1.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba92d909188930860c9d89ca6d7a753bc5a67e4e9eac6cea351477c967355eed", size = 12189521, upload-time = "2025-11-25T21:25:12.091Z" }, + { url = "https://files.pythonhosted.org/packages/11/23/5689c014a76aff3b744b3ee0d80815f63b1362637814f5fbb105244df09b/temporalio-1.20.0-cp310-abi3-win_amd64.whl", hash = "sha256:eacfd571b653e0a0f4aa6593f4d06fc628797898f0900d400e833a1f40cad03a", size = 12745027, upload-time = "2025-11-25T21:25:16.827Z" }, +] + [[package]] name = "tenacity" version = "9.1.2" @@ -4715,6 +6793,74 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, ] +[[package]] +name = "tiktoken" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "regex", marker = "python_full_version >= '3.10'" }, + { name = "requests", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/b3/2cb7c17b6c4cf8ca983204255d3f1d95eda7213e247e6947a0ee2c747a2c/tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970", size = 1051991, upload-time = "2025-10-06T20:21:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/27/0f/df139f1df5f6167194ee5ab24634582ba9a1b62c6b996472b0277ec80f66/tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16", size = 995798, upload-time = "2025-10-06T20:21:35.579Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5d/26a691f28ab220d5edc09b9b787399b130f24327ef824de15e5d85ef21aa/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:cde24cdb1b8a08368f709124f15b36ab5524aac5fa830cc3fdce9c03d4fb8030", size = 1129865, upload-time = "2025-10-06T20:21:36.675Z" }, + { url = "https://files.pythonhosted.org/packages/b2/94/443fab3d4e5ebecac895712abd3849b8da93b7b7dec61c7db5c9c7ebe40c/tiktoken-0.12.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6de0da39f605992649b9cfa6f84071e3f9ef2cec458d08c5feb1b6f0ff62e134", size = 1152856, upload-time = "2025-10-06T20:21:37.873Z" }, + { url = "https://files.pythonhosted.org/packages/54/35/388f941251b2521c70dd4c5958e598ea6d2c88e28445d2fb8189eecc1dfc/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6faa0534e0eefbcafaccb75927a4a380463a2eaa7e26000f0173b920e98b720a", size = 1195308, upload-time = "2025-10-06T20:21:39.577Z" }, + { url = "https://files.pythonhosted.org/packages/f8/00/c6681c7f833dd410576183715a530437a9873fa910265817081f65f9105f/tiktoken-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82991e04fc860afb933efb63957affc7ad54f83e2216fe7d319007dab1ba5892", size = 1255697, upload-time = "2025-10-06T20:21:41.154Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d2/82e795a6a9bafa034bf26a58e68fe9a89eeaaa610d51dbeb22106ba04f0a/tiktoken-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:6fb2995b487c2e31acf0a9e17647e3b242235a20832642bb7a9d1a181c0c1bb1", size = 879375, upload-time = "2025-10-06T20:21:43.201Z" }, + { url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" }, + { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" }, + { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" }, + { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" }, + { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, + { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, + { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, + { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, + { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, + { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, + { url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, + { url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, + { url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, + { url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, + { url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, + { url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, + { url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, + { url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, + { url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, + { url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, + { url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188, upload-time = "2025-10-06T20:22:19.563Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978, upload-time = "2025-10-06T20:22:20.702Z" }, + { url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271, upload-time = "2025-10-06T20:22:22.06Z" }, + { url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216, upload-time = "2025-10-06T20:22:23.085Z" }, + { url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860, upload-time = "2025-10-06T20:22:24.602Z" }, + { url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567, upload-time = "2025-10-06T20:22:25.671Z" }, + { url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067, upload-time = "2025-10-06T20:22:26.753Z" }, + { url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473, upload-time = "2025-10-06T20:22:27.775Z" }, + { url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855, upload-time = "2025-10-06T20:22:28.799Z" }, + { url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022, upload-time = "2025-10-06T20:22:29.981Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736, upload-time = "2025-10-06T20:22:30.996Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" }, + { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" }, + { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d1/7507bfb9c2ceef52ae3ae813013215c185648e21127538aae66dedd3af9c/tiktoken-0.12.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:d51d75a5bffbf26f86554d28e78bfb921eae998edc2675650fd04c7e1f0cdc1e", size = 1053407, upload-time = "2025-10-06T20:22:35.492Z" }, + { url = "https://files.pythonhosted.org/packages/ee/4a/8ea1da602ac39dee4356b4cd6040a2325507482c36043044b6f581597b4f/tiktoken-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:09eb4eae62ae7e4c62364d9ec3a57c62eea707ac9a2b2c5d6bd05de6724ea179", size = 997150, upload-time = "2025-10-06T20:22:37.286Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1a/62d1d36b167eccd441aff2f0091551ca834295541b949d161021aa658167/tiktoken-0.12.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:df37684ace87d10895acb44b7f447d4700349b12197a526da0d4a4149fde074c", size = 1131575, upload-time = "2025-10-06T20:22:39.023Z" }, + { url = "https://files.pythonhosted.org/packages/f7/16/544207d63c8c50edd2321228f21d236e4e49d235128bb7e3e0f69eed0807/tiktoken-0.12.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:4c9614597ac94bb294544345ad8cf30dac2129c05e2db8dc53e082f355857af7", size = 1154920, upload-time = "2025-10-06T20:22:40.175Z" }, + { url = "https://files.pythonhosted.org/packages/99/4c/0a3504157c81364fc0c64cada54efef0567961357e786706ea63bc8946e1/tiktoken-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:20cf97135c9a50de0b157879c3c4accbb29116bcf001283d26e073ff3b345946", size = 1196766, upload-time = "2025-10-06T20:22:41.365Z" }, + { url = "https://files.pythonhosted.org/packages/d4/46/8e6a258ae65447c75770fe5ea8968acab369e8c9f537f727c91f83772325/tiktoken-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:15d875454bbaa3728be39880ddd11a5a2a9e548c29418b41e8fd8a767172b5ec", size = 1258278, upload-time = "2025-10-06T20:22:42.846Z" }, + { url = "https://files.pythonhosted.org/packages/35/43/3b95de4f5e76f3cafc70dac9b1b9cfe759ff3bfd494ac91a280e93772e90/tiktoken-0.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cff3688ba3c639ebe816f8d58ffbbb0aa7433e23e08ab1cade5d175fc973fb3", size = 881888, upload-time = "2025-10-06T20:22:44.059Z" }, +] + [[package]] name = "tinycss2" version = "1.4.0" @@ -4906,26 +7052,21 @@ wheels = [ ] [[package]] -name = "typer-slim" -version = "0.21.1" +name = "types-orjson" +version = "3.6.2" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/17/d4/064570dec6358aa9049d4708e4a10407d74c99258f8b2136bb8702303f1a/typer_slim-0.21.1.tar.gz", hash = "sha256:73495dd08c2d0940d611c5a8c04e91c2a0a98600cbd4ee19192255a233b6dbfd", size = 110478, upload-time = "2026-01-06T11:21:11.176Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/97/3f78cfdf663e5668e8b490d8c84d6de089d2d8dbad935f0dc43555d52a90/types-orjson-3.6.2.tar.gz", hash = "sha256:cf9afcc79a86325c7aff251790338109ed6f6b1bab09d2d4262dd18c85a3c638", size = 1999, upload-time = "2022-01-07T11:31:10.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/0a/4aca634faf693e33004796b6cee0ae2e1dba375a800c16ab8d3eff4bb800/typer_slim-0.21.1-py3-none-any.whl", hash = "sha256:6e6c31047f171ac93cc5a973c9e617dbc5ab2bddc4d0a3135dc161b4e2020e0d", size = 47444, upload-time = "2026-01-06T11:21:12.441Z" }, + { url = "https://files.pythonhosted.org/packages/55/84/b34abd2d08381c5113e475908a1d79d27dc9a15f669213cee4ca03d1a891/types_orjson-3.6.2-py3-none-any.whl", hash = "sha256:22ee9a79236b6b0bfb35a0684eded62ad930a88a56797fa3c449b026cf7dbfe4", size = 2224, upload-time = "2022-01-07T11:31:09.271Z" }, ] [[package]] -name = "types-orjson" -version = "3.6.2" +name = "types-protobuf" +version = "6.32.1.20251210" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/97/3f78cfdf663e5668e8b490d8c84d6de089d2d8dbad935f0dc43555d52a90/types-orjson-3.6.2.tar.gz", hash = "sha256:cf9afcc79a86325c7aff251790338109ed6f6b1bab09d2d4262dd18c85a3c638", size = 1999, upload-time = "2022-01-07T11:31:10.518Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/59/c743a842911887cd96d56aa8936522b0cd5f7a7f228c96e81b59fced45be/types_protobuf-6.32.1.20251210.tar.gz", hash = "sha256:c698bb3f020274b1a2798ae09dc773728ce3f75209a35187bd11916ebfde6763", size = 63900, upload-time = "2025-12-10T03:14:25.451Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/84/b34abd2d08381c5113e475908a1d79d27dc9a15f669213cee4ca03d1a891/types_orjson-3.6.2-py3-none-any.whl", hash = "sha256:22ee9a79236b6b0bfb35a0684eded62ad930a88a56797fa3c449b026cf7dbfe4", size = 2224, upload-time = "2022-01-07T11:31:09.271Z" }, + { url = "https://files.pythonhosted.org/packages/aa/43/58e75bac4219cbafee83179505ff44cae3153ec279be0e30583a73b8f108/types_protobuf-6.32.1.20251210-py3-none-any.whl", hash = "sha256:2641f78f3696822a048cfb8d0ff42ccd85c25f12f871fbebe86da63793692140", size = 77921, upload-time = "2025-12-10T03:14:24.477Z" }, ] [[package]] @@ -4961,11 +7102,11 @@ wheels = [ [[package]] name = "types-ujson" -version = "5.10.0.20240515" +version = "5.10.0.20250822" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/49/abb4bcb9f2258f785edbf236b517c3e7ba8a503a8cbce6b5895930586cc0/types-ujson-5.10.0.20240515.tar.gz", hash = "sha256:ceae7127f0dafe4af5dd0ecf98ee13e9d75951ef963b5c5a9b7ea92e0d71f0d7", size = 3571, upload-time = "2024-05-15T02:24:43.704Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/bd/d372d44534f84864a96c19a7059d9b4d29db8541828b8b9dc3040f7a46d0/types_ujson-5.10.0.20250822.tar.gz", hash = "sha256:0a795558e1f78532373cf3f03f35b1f08bc60d52d924187b97995ee3597ba006", size = 8437, upload-time = "2025-08-22T03:02:19.433Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/1f/9d018cee3d09ab44a5211f0b5ed9b0422ad9a8c226bf3967f5884498d8f0/types_ujson-5.10.0.20240515-py3-none-any.whl", hash = "sha256:02bafc36b3a93d2511757a64ff88bd505e0a57fba08183a9150fbcfcb2015310", size = 2757, upload-time = "2024-05-15T02:24:42.315Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f2/d812543c350674d8b3f6e17c8922248ee3bb752c2a76f64beb8c538b40cf/types_ujson-5.10.0.20250822-py3-none-any.whl", hash = "sha256:3e9e73a6dc62ccc03449d9ac2c580cd1b7a8e4873220db498f7dd056754be080", size = 7657, upload-time = "2025-08-22T03:02:18.699Z" }, ] [[package]] @@ -5483,6 +7624,246 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ad/e4/8d97cca767bcc1be76d16fb76951608305561c6e056811587f36cb1316a8/werkzeug-3.1.5-py3-none-any.whl", hash = "sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc", size = 225025, upload-time = "2026-01-08T17:49:21.859Z" }, ] +[[package]] +name = "wrapt" +version = "1.17.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/23/bb82321b86411eb51e5a5db3fb8f8032fd30bd7c2d74bfe936136b2fa1d6/wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04", size = 53482, upload-time = "2025-08-12T05:51:44.467Z" }, + { url = "https://files.pythonhosted.org/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2", size = 38676, upload-time = "2025-08-12T05:51:32.636Z" }, + { url = "https://files.pythonhosted.org/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c", size = 38957, upload-time = "2025-08-12T05:51:54.655Z" }, + { url = "https://files.pythonhosted.org/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775", size = 81975, upload-time = "2025-08-12T05:52:30.109Z" }, + { url = "https://files.pythonhosted.org/packages/f2/15/dd576273491f9f43dd09fce517f6c2ce6eb4fe21681726068db0d0467096/wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd", size = 83149, upload-time = "2025-08-12T05:52:09.316Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c4/5eb4ce0d4814521fee7aa806264bf7a114e748ad05110441cd5b8a5c744b/wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05", size = 82209, upload-time = "2025-08-12T05:52:10.331Z" }, + { url = "https://files.pythonhosted.org/packages/31/4b/819e9e0eb5c8dc86f60dfc42aa4e2c0d6c3db8732bce93cc752e604bb5f5/wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418", size = 81551, upload-time = "2025-08-12T05:52:31.137Z" }, + { url = "https://files.pythonhosted.org/packages/f8/83/ed6baf89ba3a56694700139698cf703aac9f0f9eb03dab92f57551bd5385/wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390", size = 36464, upload-time = "2025-08-12T05:53:01.204Z" }, + { url = "https://files.pythonhosted.org/packages/2f/90/ee61d36862340ad7e9d15a02529df6b948676b9a5829fd5e16640156627d/wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6", size = 38748, upload-time = "2025-08-12T05:53:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c3/cefe0bd330d389c9983ced15d326f45373f4073c9f4a8c2f99b50bfea329/wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18", size = 36810, upload-time = "2025-08-12T05:52:51.906Z" }, + { url = "https://files.pythonhosted.org/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7", size = 53482, upload-time = "2025-08-12T05:51:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85", size = 38674, upload-time = "2025-08-12T05:51:34.629Z" }, + { url = "https://files.pythonhosted.org/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f", size = 38959, upload-time = "2025-08-12T05:51:56.074Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311", size = 82376, upload-time = "2025-08-12T05:52:32.134Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1", size = 83604, upload-time = "2025-08-12T05:52:11.663Z" }, + { url = "https://files.pythonhosted.org/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5", size = 82782, upload-time = "2025-08-12T05:52:12.626Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2", size = 82076, upload-time = "2025-08-12T05:52:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89", size = 36457, upload-time = "2025-08-12T05:53:03.936Z" }, + { url = "https://files.pythonhosted.org/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77", size = 38745, upload-time = "2025-08-12T05:53:02.885Z" }, + { url = "https://files.pythonhosted.org/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a", size = 36806, upload-time = "2025-08-12T05:52:53.368Z" }, + { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, + { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, + { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, + { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, + { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, + { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, + { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, + { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, + { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, + { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, + { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, + { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, + { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, + { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, + { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, + { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, + { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/41/be/be9b3b0a461ee3e30278706f3f3759b9b69afeedef7fe686036286c04ac6/wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc", size = 53485, upload-time = "2025-08-12T05:51:53.11Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a8/8f61d6b8f526efc8c10e12bf80b4206099fea78ade70427846a37bc9cbea/wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9", size = 38675, upload-time = "2025-08-12T05:51:42.885Z" }, + { url = "https://files.pythonhosted.org/packages/48/f1/23950c29a25637b74b322f9e425a17cc01a478f6afb35138ecb697f9558d/wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d", size = 38956, upload-time = "2025-08-12T05:52:03.149Z" }, + { url = "https://files.pythonhosted.org/packages/43/46/dd0791943613885f62619f18ee6107e6133237a6b6ed8a9ecfac339d0b4f/wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a", size = 81745, upload-time = "2025-08-12T05:52:49.62Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ec/bb2d19bd1a614cc4f438abac13ae26c57186197920432d2a915183b15a8b/wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139", size = 82833, upload-time = "2025-08-12T05:52:27.738Z" }, + { url = "https://files.pythonhosted.org/packages/8d/eb/66579aea6ad36f07617fedca8e282e49c7c9bab64c63b446cfe4f7f47a49/wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df", size = 81889, upload-time = "2025-08-12T05:52:29.023Z" }, + { url = "https://files.pythonhosted.org/packages/04/9c/a56b5ac0e2473bdc3fb11b22dd69ff423154d63861cf77911cdde5e38fd2/wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b", size = 81344, upload-time = "2025-08-12T05:52:50.869Z" }, + { url = "https://files.pythonhosted.org/packages/93/4c/9bd735c42641d81cb58d7bfb142c58f95c833962d15113026705add41a07/wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81", size = 36462, upload-time = "2025-08-12T05:53:19.623Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ea/0b72f29cb5ebc16eb55c57dc0c98e5de76fc97f435fd407f7d409459c0a6/wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f", size = 38740, upload-time = "2025-08-12T05:53:18.271Z" }, + { url = "https://files.pythonhosted.org/packages/c3/8b/9eae65fb92321e38dbfec7719b87d840a4b92fde83fd1bbf238c5488d055/wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f", size = 36806, upload-time = "2025-08-12T05:52:58.765Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +] + +[[package]] +name = "xai-sdk" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp", marker = "python_full_version >= '3.10'" }, + { name = "googleapis-common-protos", marker = "python_full_version >= '3.10'" }, + { name = "grpcio", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, + { name = "packaging", marker = "python_full_version >= '3.10'" }, + { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic", marker = "python_full_version >= '3.10'" }, + { name = "requests", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/66/1e0163eac090733d0ed0836a0cd3c14f5b59abeaa6fdba71c7b56b1916e4/xai_sdk-1.6.1.tar.gz", hash = "sha256:b55528df188f8c8448484021d735f75b0e7d71719ddeb432c5f187ac67e3c983", size = 388223, upload-time = "2026-01-29T03:13:07.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/98/8b4019b35f2200295c5eec8176da4b779ec3a0fd60eba7196b618f437e1f/xai_sdk-1.6.1-py3-none-any.whl", hash = "sha256:f478dee9bd8839b8d341bd075277d0432aff5cd7120a4284547d25c6c9e7ab3b", size = 240917, upload-time = "2026-01-29T03:13:05.626Z" }, +] + +[[package]] +name = "yarl" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, + { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, + { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, + { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, + { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, + { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, + { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, + { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, + { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, + { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, + { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, + { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, + { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, + { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, + { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, + { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, + { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, + { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, + { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, + { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, + { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, + { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, + { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, + { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, + { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, + { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, + { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, + { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, + { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, + { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, + { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, + { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, + { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, + { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, + { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, + { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, + { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, + { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, + { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, + { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, + { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, + { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, + { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, + { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, + { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, + { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, + { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, + { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, + { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, + { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, + { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, + { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, + { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, + { url = "https://files.pythonhosted.org/packages/94/fd/6480106702a79bcceda5fd9c63cb19a04a6506bd5ce7fd8d9b63742f0021/yarl-1.22.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748", size = 141301, upload-time = "2025-10-06T14:12:19.01Z" }, + { url = "https://files.pythonhosted.org/packages/42/e1/6d95d21b17a93e793e4ec420a925fe1f6a9342338ca7a563ed21129c0990/yarl-1.22.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859", size = 93864, upload-time = "2025-10-06T14:12:21.05Z" }, + { url = "https://files.pythonhosted.org/packages/32/58/b8055273c203968e89808413ea4c984988b6649baabf10f4522e67c22d2f/yarl-1.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9", size = 94706, upload-time = "2025-10-06T14:12:23.287Z" }, + { url = "https://files.pythonhosted.org/packages/18/91/d7bfbc28a88c2895ecd0da6a874def0c147de78afc52c773c28e1aa233a3/yarl-1.22.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054", size = 347100, upload-time = "2025-10-06T14:12:28.527Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e8/37a1e7b99721c0564b1fc7b0a4d1f595ef6fb8060d82ca61775b644185f7/yarl-1.22.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b", size = 318902, upload-time = "2025-10-06T14:12:30.528Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ef/34724449d7ef2db4f22df644f2dac0b8a275d20f585e526937b3ae47b02d/yarl-1.22.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60", size = 363302, upload-time = "2025-10-06T14:12:32.295Z" }, + { url = "https://files.pythonhosted.org/packages/8a/04/88a39a5dad39889f192cce8d66cc4c58dbeca983e83f9b6bf23822a7ed91/yarl-1.22.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890", size = 370816, upload-time = "2025-10-06T14:12:34.01Z" }, + { url = "https://files.pythonhosted.org/packages/6b/1f/5e895e547129413f56c76be2c3ce4b96c797d2d0ff3e16a817d9269b12e6/yarl-1.22.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba", size = 346465, upload-time = "2025-10-06T14:12:35.977Z" }, + { url = "https://files.pythonhosted.org/packages/11/13/a750e9fd6f9cc9ed3a52a70fe58ffe505322f0efe0d48e1fd9ffe53281f5/yarl-1.22.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca", size = 341506, upload-time = "2025-10-06T14:12:37.788Z" }, + { url = "https://files.pythonhosted.org/packages/3c/67/bb6024de76e7186611ebe626aec5b71a2d2ecf9453e795f2dbd80614784c/yarl-1.22.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba", size = 335030, upload-time = "2025-10-06T14:12:39.775Z" }, + { url = "https://files.pythonhosted.org/packages/a2/be/50b38447fd94a7992996a62b8b463d0579323fcfc08c61bdba949eef8a5d/yarl-1.22.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b", size = 358560, upload-time = "2025-10-06T14:12:41.547Z" }, + { url = "https://files.pythonhosted.org/packages/e2/89/c020b6f547578c4e3dbb6335bf918f26e2f34ad0d1e515d72fd33ac0c635/yarl-1.22.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e", size = 357290, upload-time = "2025-10-06T14:12:43.861Z" }, + { url = "https://files.pythonhosted.org/packages/8c/52/c49a619ee35a402fa3a7019a4fa8d26878fec0d1243f6968bbf516789578/yarl-1.22.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8", size = 350700, upload-time = "2025-10-06T14:12:46.868Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c9/f5042d87777bf6968435f04a2bbb15466b2f142e6e47fa4f34d1a3f32f0c/yarl-1.22.0-cp39-cp39-win32.whl", hash = "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b", size = 82323, upload-time = "2025-10-06T14:12:48.633Z" }, + { url = "https://files.pythonhosted.org/packages/fd/58/d00f7cad9eba20c4eefac2682f34661d1d1b3a942fc0092eb60e78cfb733/yarl-1.22.0-cp39-cp39-win_amd64.whl", hash = "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed", size = 87145, upload-time = "2025-10-06T14:12:50.241Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a3/70904f365080780d38b919edd42d224b8c4ce224a86950d2eaa2a24366ad/yarl-1.22.0-cp39-cp39-win_arm64.whl", hash = "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2", size = 82173, upload-time = "2025-10-06T14:12:51.869Z" }, + { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +] + [[package]] name = "zipp" version = "3.23.0" From 266a3138b5332de819606d339db2392f1595fe68 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 17:18:53 +0000 Subject: [PATCH 155/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a55a15abd7..6896100495 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* โฌ†๏ธ Upgrade development dependencies. PR [#14854](https://github.com/fastapi/fastapi/pull/14854) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.3 ### Refactors From 0f5987b560fbf8fac9ed30ed3477f2acc97d9ae9 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:23:48 +0300 Subject: [PATCH 156/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(outdated=20and=20missing)=20(#14838)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tr/docs/advanced/advanced-dependencies.md | 8 +- docs/tr/docs/alternatives.md | 412 +++++++++--------- docs/tr/docs/deployment/docker.md | 8 +- docs/tr/docs/history-design-future.md | 14 +- docs/tr/docs/translation-banner.md | 11 + docs/tr/docs/tutorial/body-multiple-params.md | 6 +- .../tutorial/path-operation-configuration.md | 8 +- 7 files changed, 238 insertions(+), 229 deletions(-) create mode 100644 docs/tr/docs/translation-banner.md diff --git a/docs/tr/docs/advanced/advanced-dependencies.md b/docs/tr/docs/advanced/advanced-dependencies.md index 48c0b62111..8afb544bdd 100644 --- a/docs/tr/docs/advanced/advanced-dependencies.md +++ b/docs/tr/docs/advanced/advanced-dependencies.md @@ -78,13 +78,13 @@ Bu detaylar, รถzellikle 0.121.0'dan eski bir FastAPI uygulamanฤฑz varsa ve `yiel ### `yield` ve `scope` ile dependency'ler { #dependencies-with-yield-and-scope } -0.121.0 sรผrรผmรผnde FastAPI, `yield` kullanan dependency'ler iรงin `Depends(scope="function")` desteฤŸini ekledi. +0.121.0 sรผrรผmรผnde FastAPI, `Depends(scope="function")` desteฤŸini ekledi. `Depends(scope="function")` kullanฤฑldฤฑฤŸฤฑnda, `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodu, *path operation function* biter bitmez, response client'a geri gรถnderilmeden รถnce รงalฤฑลŸtฤฑrฤฑlฤฑr. `Depends(scope="request")` (varsayฤฑlan) kullanฤฑldฤฑฤŸฤฑnda ise `yield` sonrasฤฑndaki รงฤฑkฤฑลŸ kodu, response gรถnderildikten sonra รงalฤฑลŸtฤฑrฤฑlฤฑr. -Daha fazlasฤฑnฤฑ [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) dokรผmantasyonunda okuyabilirsiniz. +Daha fazlasฤฑnฤฑ [`yield` ile Dependency'ler - Erken รงฤฑkฤฑลŸ ve `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) dokรผmantasyonunda okuyabilirsiniz. ### `yield` ve `StreamingResponse` ile dependency'ler, Teknik Detaylar { #dependencies-with-yield-and-streamingresponse-technical-details } @@ -132,7 +132,7 @@ SQLModel (veya SQLAlchemy) kullanarak bu spesifik senaryoya sahipseniz, session' Bรถylece session veritabanฤฑ baฤŸlantฤฑsฤฑnฤฑ serbest bฤฑrakฤฑr ve diฤŸer request'ler bunu kullanabilir. -`yield` kullanan bir dependency'den erken รงฤฑkฤฑลŸ gerektiren farklฤฑ bir kullanฤฑm senaryonuz varsa, lรผtfen kullanฤฑm senaryonuzla birlikte ve `yield` kullanan dependency'ler iรงin erken kapatmadan neden fayda gรถreceฤŸinizi aรงฤฑklayarak bir GitHub Discussion Question oluลŸturun. +`yield` kullanan bir dependency'den erken รงฤฑkฤฑลŸ gerektiren farklฤฑ bir kullanฤฑm senaryonuz varsa, lรผtfen kullanฤฑm senaryonuzla birlikte ve `yield` kullanan dependency'ler iรงin erken kapatmadan neden fayda gรถreceฤŸinizi aรงฤฑklayarak bir GitHub Discussion Sorusu oluลŸturun. `yield` kullanan dependency'lerde erken kapatma iรงin ikna edici kullanฤฑm senaryolarฤฑ varsa, erken kapatmayฤฑ seรงmeli (opt-in) hale getiren yeni bir yรถntem eklemeyi dรผลŸรผnebilirim. @@ -144,7 +144,7 @@ Bu davranฤฑลŸ 0.110.0 sรผrรผmรผnde deฤŸiลŸtirildi. Amaรง, handler olmayan (inter ### Background Tasks ve `yield` ile dependency'ler, Teknik Detaylar { #background-tasks-and-dependencies-with-yield-technical-details } -FastAPI 0.106.0 รถncesinde, `yield` sonrasฤฑnda exception raise etmek mรผmkรผn deฤŸildi; รงรผnkรผ `yield` kullanan dependency'lerdeki รงฤฑkฤฑลŸ kodu response gรถnderildikten *sonra* รงalฤฑลŸtฤฑrฤฑlฤฑyordu. Bu nedenle [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} zaten รงalฤฑลŸmฤฑลŸ olurdu. +FastAPI 0.106.0 รถncesinde, `yield` sonrasฤฑnda exception raise etmek mรผmkรผn deฤŸildi; รงรผnkรผ `yield` kullanan dependency'lerdeki รงฤฑkฤฑลŸ kodu response gรถnderildikten *sonra* รงalฤฑลŸtฤฑrฤฑlฤฑyordu. Bu nedenle [Exception Handler'larฤฑ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} zaten รงalฤฑลŸmฤฑลŸ olurdu. Bu tasarฤฑmฤฑn ana sebeplerinden biri, background task'lerin iรงinde dependency'lerin "yield ettiฤŸi" aynฤฑ objeleri kullanmaya izin vermekti; รงรผnkรผ รงฤฑkฤฑลŸ kodu, background task'ler bittikten sonra รงalฤฑลŸtฤฑrฤฑlฤฑyordu. diff --git a/docs/tr/docs/alternatives.md b/docs/tr/docs/alternatives.md index 9b603ea817..afc1a45ef5 100644 --- a/docs/tr/docs/alternatives.md +++ b/docs/tr/docs/alternatives.md @@ -1,483 +1,483 @@ -# Alternatifler, ฤฐlham Kaynaklarฤฑ ve KarลŸฤฑlaลŸtฤฑrmalar +# Alternatifler, ฤฐlham Kaynaklarฤฑ ve KarลŸฤฑlaลŸtฤฑrmalar { #alternatives-inspiration-and-comparisons } -**FastAPI**'ya neler ilham verdi? DiฤŸer alternatiflerle karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑnda farklarฤฑ neler? **FastAPI** diฤŸer alternatiflerinden neler รถฤŸrendi? +**FastAPI**'a nelerin ilham verdiฤŸi, alternatiflerle nasฤฑl karลŸฤฑlaลŸtฤฑrฤฑldฤฑฤŸฤฑ ve onlardan neler รถฤŸrendiฤŸi. -## GiriลŸ +## GiriลŸ { #intro } BaลŸkalarฤฑnฤฑn daha รถnceki รงalฤฑลŸmalarฤฑ olmasaydฤฑ, **FastAPI** var olmazdฤฑ. -GeรงmiลŸte oluลŸturulan pek รงok araรง **FastAPI**'a ilham kaynaฤŸฤฑ olmuลŸtur. +ร–nceden oluลŸturulan birรงok araรง, ortaya รงฤฑkฤฑลŸฤฑna ilham verdi. -Yฤฑllardฤฑr yeni bir framework oluลŸturmaktan kaรงฤฑnฤฑyordum. BaลŸlangฤฑรงta **FastAPI**'ฤฑn รงรถzdรผฤŸรผ sorunlarฤฑ รงรถzebilmek iรงin pek รงok farklฤฑ framework, eklenti ve araรง kullanmayฤฑ denedim. +Yฤฑllarca yeni bir framework oluลŸturmaktan kaรงฤฑndฤฑm. ร–nce **FastAPI**โ€™ฤฑn bugรผn kapsadฤฑฤŸฤฑ รถzelliklerin tamamฤฑnฤฑ, birรงok farklฤฑ framework, eklenti ve araรงla รงรถzmeyi denedim. -Ancak bir noktada, geรงmiลŸteki diฤŸer araรงlardan en iyi fikirleri alarak bรผtรผn bu รงรถzรผmleri kapsayan, ayrฤฑca bรผtรผn bunlarฤฑ Python'ฤฑn daha รถnce mevcut olmayan รถzelliklerini (Python 3.6+ ile gelen tip belirteรงleri) kullanarak yapan bir ลŸey รผretmekten baลŸka seรงenek kalmamฤฑลŸtฤฑ. +Ancak bir noktada, geรงmiลŸteki araรงlardan en iyi fikirleri alฤฑp, mรผmkรผn olan en iyi ลŸekilde birleลŸtiren ve daha รถnce mevcut olmayan dil รถzelliklerini (Python 3.6+ tip belirteรงleri) kullanarak tรผm bu รถzellikleri saฤŸlayan bir ลŸey geliลŸtirmekten baลŸka seรงenek kalmadฤฑ. -## Daha ร–nce GeliลŸtirilen Araรงlar +## Daha ร–nce GeliลŸtirilen Araรงlar { #previous-tools } -### Django +### Django { #django } -Django geniลŸ รงapta gรผvenilen, Python ekosistemindeki en popรผler web framework'รผdรผr. Instagram gibi sistemleri geliลŸtirmede kullanฤฑlmฤฑลŸtฤฑr. +Python ekosistemindeki en popรผler ve yaygฤฑn olarak gรผvenilen web frameworkโ€™รผdรผr. Instagram gibi sistemleri geliลŸtirmede kullanฤฑlmฤฑลŸtฤฑr. -MySQL ve PostgreSQL gibi iliลŸkisel veritabanlarฤฑyla nispeten sฤฑkฤฑ bir ลŸekilde baฤŸlantฤฑlฤฑdฤฑr. Bu nedenle Couchbase, MongoDB ve Cassandra gibi NoSQL veritabanlarฤฑnฤฑ ana veritabanฤฑ motoru olarak kullanmak pek de kolay deฤŸil. +MySQL veya PostgreSQL gibi iliลŸkisel veritabanlarฤฑyla nispeten sฤฑkฤฑ baฤŸlฤฑdฤฑr, bu nedenle Couchbase, MongoDB, Cassandra vb. gibi bir NoSQL veritabanฤฑnฤฑ ana depolama motoru olarak kullanmak pek kolay deฤŸildir. -Modern รถn uรงlarda (React, Vue.js ve Angular gibi) veya diฤŸer sistemler (รถrneฤŸin nesnelerin interneti cihazlarฤฑ) tarafฤฑndan kullanฤฑlan API'lar yerine arka uรงta HTML รผretmek iรงin oluลŸturuldu. +Modern bir รถn uรง (React, Vue.js, Angular gibi) veya onunla haberleลŸen diฤŸer sistemler (รถr. IoT cihazlarฤฑ) tarafฤฑndan tรผketilen APIโ€™lar รผretmekten ziyade, arka uรงta HTML รผretmek iรงin oluลŸturulmuลŸtur. -### Django REST Framework +### Django REST Framework { #django-rest-framework } -Django REST framework'รผ, Django'nun API kabiliyetlerini arttฤฑrmak iรงin arka planda Django kullanan esnek bir araรง grubu olarak oluลŸturuldu. +Django REST Framework, Django รผzerine kurulu esnek bir araรง takฤฑmฤฑ olarak, Web APIโ€™lar geliลŸtirmeyi ve Djangoโ€™nun API kabiliyetlerini artฤฑrmayฤฑ hedefler. -รœstelik Mozilla, Red Hat ve Eventbrite gibi pek รงok ลŸirket tarafฤฑndan kullanฤฑlฤฑyor. +Mozilla, Red Hat ve Eventbrite gibi birรงok ลŸirket tarafฤฑndan kullanฤฑlmaktadฤฑr. -**Otomatik API dรถkรผmantasyonu**nun ilk รถrneklerinden biri olduฤŸu iรงin, **FastAPI** arayฤฑลŸฤฑna ilham veren ilk fikirlerden biri oldu. +**Otomatik API dรถkรผmantasyonu**nun ilk รถrneklerinden biriydi ve bu, โ€œ**FastAPI** arayฤฑลŸฤฑnaโ€ ilham veren ilk fikirlerden biriydi. /// note | Not -Django REST Framework'รผ, aynฤฑ zamanda **FastAPI**'ฤฑn dayandฤฑฤŸฤฑ Starlette ve Uvicorn'un da yaratฤฑcฤฑsฤฑ olan Tom Christie tarafฤฑndan geliลŸtirildi. +Django REST Framework, **FastAPI**'ฤฑn รผzerine inลŸa edildiฤŸi Starlette ve Uvicorn'un da yaratฤฑcฤฑsฤฑ olan Tom Christie tarafฤฑndan geliลŸtirildi. /// -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -Kullanฤฑcฤฑlar iรงin otomatik API dรถkรผmantasyonu sunan bir web arayรผzรผne sahip olmalฤฑ. +Otomatik API dรถkรผmantasyonu saฤŸlayan bir web arayรผzรผ sunmak. /// -### Flask +### Flask { #flask } -Flask bir mikro framework olduฤŸundan Django gibi framework'lerin aksine veritabanฤฑ entegrasyonu gibi Django ile gelen pek รงok รถzelliฤŸi direkt barฤฑndฤฑrmaz. +Flask bir โ€œmikroframeworkโ€tรผr, Djangoโ€™da varsayฤฑlan gelen pek รงok รถzelliฤŸi (veritabanฤฑ entegrasyonlarฤฑ vb.) iรงermez. -SaฤŸladฤฑฤŸฤฑ basitlik ve esneklik NoSQL veritabanlarฤฑnฤฑ ana veritabanฤฑ sistemi olarak kullanmak gibi ลŸeyler yapmaya olanak saฤŸlar. +Bu basitlik ve esneklik, NoSQL veritabanlarฤฑnฤฑ ana veri depolama sistemi olarak kullanmak gibi ลŸeyleri mรผmkรผn kฤฑlar. -Yapฤฑsฤฑ oldukรงa basit olduฤŸundan รถฤŸrenmesi de nispeten basittir, tabii dรถkรผmantasyonu bazฤฑ noktalarda biraz teknik hale geliyor. +ร‡ok basit olduฤŸu iรงin รถฤŸrenmesi nispeten sezgiseldir, ancak dรถkรผmantasyon bazฤฑ noktalarda biraz teknikleลŸebilir. -Ayrฤฑca Django ile birlikte gelen veritabanฤฑ, kullanฤฑcฤฑ yรถnetimi ve diฤŸer pek รงok รถzelliฤŸe ihtiyaรง duymayan uygulamalarda da yaygฤฑn olarak kullanฤฑlฤฑyor. Ancak bu tรผr รถzelliklerin pek รงoฤŸu eklentiler ile eklenebiliyor. +Ayrฤฑca veritabanฤฑ, kullanฤฑcฤฑ yรถnetimi veya Djangoโ€™da รถnceden gelen pek รงok รถzelliฤŸe ihtiyaรง duymayan uygulamalar iรงin de yaygฤฑn olarak kullanฤฑlฤฑr. Yine de bu รถzelliklerin รงoฤŸu eklentilerle eklenebilir. -Uygulama parรงalarฤฑnฤฑn bรถyle ayrฤฑlฤฑyor oluลŸu ve istenilen รถzelliklerle geniลŸletilebilecek bir mikro framework olmak tam da benim istediฤŸim bir รถzellikti. +BileลŸenlerin ayrฤฑk olmasฤฑ ve gerekeni tam olarak kapsayacak ลŸekilde geniลŸletilebilen bir โ€œmikroframeworkโ€ olmasฤฑ, รถzellikle korumak istediฤŸim bir รถzelliktir. -Flask'ฤฑn basitliฤŸi gรถz รถnรผnde bulundurulduฤŸu zaman, API geliลŸtirmek iรงin iyi bir seรงim gibi gรถrรผnรผyordu. Sฤฑradaki ลŸey ise Flask iรงin bir "Django REST Framework"! +Flaskโ€™ฤฑn sadeliฤŸi gรถz รถnรผne alฤฑndฤฑฤŸฤฑnda, API geliลŸtirmek iรงin iyi bir aday gibi gรถrรผnรผyordu. Sฤฑrada, Flask iรงin bir โ€œDjango REST Frameworkโ€ bulmak vardฤฑ. -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -Gereken araรงlarฤฑ ve parรงalarฤฑ birleลŸtirip eลŸleลŸtirmeyi kolaylaลŸtฤฑracak bir mikro framework olmalฤฑ. +Gereken araรง ve parรงalarฤฑ kolayca eลŸleลŸtirip birleลŸtirmeyi saฤŸlayan bir mikroframework olmak. -Basit ve kullanmasฤฑ kolay bir yรถnlendirme sistemine sahip olmalฤฑ. +Basit ve kullanฤฑmฤฑ kolay bir yรถnlendirme (routing) sistemine sahip olmak. /// -### Requests +### Requests { #requests } -**FastAPI** aslฤฑnda **Requests**'in bir alternatifi deฤŸil. ฤฐkisininde kapsamฤฑ oldukรงa farklฤฑ. +**FastAPI** aslฤฑnda **Requests**โ€™in bir alternatifi deฤŸildir. Kapsamlarฤฑ รงok farklฤฑdฤฑr. -Aslฤฑnda Requests'i bir FastAPI uygulamasฤฑnฤฑn *iรงinde* kullanmak daha olaฤŸan olurdu. +Hatta bir FastAPI uygulamasฤฑnฤฑn iรงinde Requests kullanmak yaygฤฑndฤฑr. -Ama yine de, FastAPI, Requests'ten oldukรงa ilham aldฤฑ. +Yine de FastAPI, Requestsโ€™ten epey ilham almฤฑลŸtฤฑr. -**Requests**, API'lar ile bir istemci olarak *etkileลŸime geรงmeyi* saฤŸlayan bir kรผtรผphaneyken **FastAPI** bir sunucu olarak API'lar oluลŸturmaya yarar. +**Requests** bir kรผtรผphane olarak APIโ€™larla (istemci olarak) etkileลŸime geรงmeye yararken, **FastAPI** APIโ€™lar (sunucu olarak) geliลŸtirmeye yarar. -ร–yle ya da bรถyle zฤฑt uรงlarda olmalarฤฑna raฤŸmen birbirlerini tamamlฤฑyorlar. +Yani daha รงok zฤฑt uรงlardadฤฑrlar ama birbirlerini tamamlarlar. -Requests oldukรงa basit ve sezgisel bir tasarฤฑma sahip, kullanmasฤฑ da mantฤฑklฤฑ varsayฤฑlan deฤŸerlerle oldukรงa kolay. Ama aynฤฑ zamanda รงok gรผรงlรผ ve gayet รถzelleลŸtirilebilir. +Requests รงok basit ve sezgisel bir tasarฤฑma sahiptir, mantฤฑklฤฑ varsayฤฑlanlarla kullanฤฑmฤฑ รงok kolaydฤฑr. Aynฤฑ zamanda รงok gรผรงlรผ ve รถzelleลŸtirilebilirdir. -Bu yรผzden resmi web sitede de sรถylendiฤŸi gibi: +Bu yรผzden resmi web sitesinde de sรถylendiฤŸi gibi: -> Requests, tรผm zamanlarฤฑn en รงok indirilen Python paketlerinden biridir. +> Requests, tรผm zamanlarฤฑn en รงok indirilen Python paketlerinden biridir -Kullanฤฑm ลŸekli oldukรงa basit. ร–rneฤŸin bir `GET` isteฤŸi yapmak iรงin aลŸaฤŸฤฑdaki yeterli: +Kullanฤฑmฤฑ รงok basittir. ร–rneฤŸin bir `GET` isteฤŸi yapmak iรงin: ```Python response = requests.get("http://example.com/some/url") ``` -Bunun FastAPI'deki API *yol iลŸlemi* ลŸรถyle gรถrรผnรผr: +Buna karลŸฤฑlฤฑk bir FastAPI API *path operation*โ€™ฤฑ ลŸรถyle olabilir: ```Python hl_lines="1" @app.get("/some/url") def read_url(): - return {"message": "Hello World!"} + return {"message": "Hello World"} ``` `requests.get(...)` ile `@app.get(...)` arasฤฑndaki benzerliklere bakฤฑn. -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -* Basit ve sezgisel bir API'ya sahip olmalฤฑ. -* HTTP metot isimlerini (iลŸlemlerini) anlaลŸฤฑlฤฑr olacak bir ลŸekilde, direkt kullanmalฤฑ. -* Mantฤฑklฤฑ varsayฤฑlan deฤŸerlere ve buna raฤŸmen gรผรงlรผ bir รถzelleลŸtirme desteฤŸine sahip olmalฤฑ. +* Basit ve sezgisel bir APIโ€™ya sahip olmak. +* HTTP metot isimlerini (iลŸlemlerini) doฤŸrudan, anlaลŸฤฑlฤฑr ve sezgisel bir ลŸekilde kullanmak. +* Mantฤฑklฤฑ varsayฤฑlanlara sahip olmak ama gรผรงlรผ รถzelleลŸtirmeler de sunmak. /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } -Benim Django REST Framework'รผnden istediฤŸim ana รถzellik otomatik API dรถkรผmantasyonuydu. +Django REST Frameworkโ€™รผnden istediฤŸim ana รถzellik otomatik API dรถkรผmantasyonuydu. -Daha sonra API'larฤฑ dรถkรผmanlamak iรงin Swagger adฤฑnda JSON (veya JSON'un bir uzantฤฑsฤฑ olan YAML'ฤฑ) kullanan bir standart olduฤŸunu buldum. +Sonra APIโ€™larฤฑ JSON (veya JSONโ€™un bir uzantฤฑsฤฑ olan YAML) kullanarak dรถkรผmante etmek iรงin Swagger adlฤฑ bir standart olduฤŸunu gรถrdรผm. -รœstelik Swagger API'larฤฑ iรงin zaten halihazฤฑrda oluลŸturulmuลŸ bir web arayรผzรผ vardฤฑ. Yani, bir API iรงin Swagger dรถkรผmantasyonu oluลŸturmak bu arayรผzรผ otomatik olarak kullanabilmek demekti. +Ve Swagger APIโ€™larฤฑ iรงin zaten oluลŸturulmuลŸ bir web arayรผzรผ vardฤฑ. Yani bir API iรงin Swagger dรถkรผmantasyonu รผretebilmek, bu web arayรผzรผnรผ otomatik kullanabilmek demekti. -Swagger bir noktada Linux Foundation'a verildi ve adฤฑ OpenAPI olarak deฤŸiลŸtirildi. +Bir noktada Swagger, Linux Foundationโ€™a devredildi ve OpenAPI olarak yeniden adlandฤฑrฤฑldฤฑ. -ฤฐลŸte bu yรผzden versiyon 2.0 hakkฤฑnda konuลŸurken "Swagger", versiyon 3 ve รผzeri iรงin ise "OpenAPI" adฤฑnฤฑ kullanmak daha yaygฤฑn. +Bu yรผzden, 2.0 sรผrรผmรผ sรถz konusu olduฤŸunda โ€œSwaggerโ€, 3+ sรผrรผmler iรงin ise โ€œOpenAPIโ€ denmesi yaygฤฑndฤฑr. -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -API spesifikasyonlarฤฑ iรงin รถzel bir ลŸema yerine bir aรงฤฑk standart benimseyip kullanmalฤฑ. +API spesifikasyonlarฤฑ iรงin รถzel bir ลŸema yerine aรงฤฑk bir standart benimsemek ve kullanmak. -Ayrฤฑca standarda baฤŸlฤฑ kullanฤฑcฤฑ arayรผzรผ araรงlarฤฑnฤฑ entegre etmeli: +Ve standartlara dayalฤฑ kullanฤฑcฤฑ arayรผzรผ araรงlarฤฑnฤฑ entegre etmek: * Swagger UI * ReDoc -Yukarฤฑdaki ikisi oldukรงa popรผler ve istikrarlฤฑ olduฤŸu iรงin seรงildi, ancak hฤฑzlฤฑ bir araลŸtฤฑrma yaparak **FastAPI** ile kullanabileceฤŸiniz pek รงok OpenAPI alternatifi arayรผz bulabilirsiniz. +Bu ikisi oldukรงa popรผler ve istikrarlฤฑ olduklarฤฑ iรงin seรงildi; hฤฑzlฤฑ bir aramayla OpenAPI iรงin onlarca alternatif kullanฤฑcฤฑ arayรผzรผ bulabilirsiniz (**FastAPI** ile de kullanabilirsiniz). /// -### Flask REST framework'leri +### Flask REST frameworkโ€™leri { #flask-rest-frameworks } -Pek รงok Flask REST framework'รผ var, fakat bunlarฤฑ biraz araลŸtฤฑrdฤฑktan sonra pek รงoฤŸunun artฤฑk geliลŸtirilmediฤŸini ve gรถze batan bazฤฑ sorunlarฤฑnฤฑn olduฤŸunu gรถrdรผm. +Birรงok Flask REST frameworkโ€™รผ var; ancak zaman ayฤฑrฤฑp inceledikten sonra รงoฤŸunun artฤฑk sรผrdรผrรผlmediฤŸini veya bazฤฑ kritik sorunlar nedeniyle uygun olmadฤฑklarฤฑnฤฑ gรถrdรผm. -### Marshmallow +### Marshmallow { #marshmallow } -API sistemlerine gereken ana รถzelliklerden biri de koddan veriyi alฤฑp aฤŸ รผzerinde gรถnderilebilecek bir ลŸeye รงevirmek, yani veri dรถnรผลŸรผmรผ. Bu iลŸleme veritabanฤฑndaki veriyi iรงeren bir objeyi JSON objesine รงevirmek, `datetime` objelerini metinlere รงevirmek gibi รถrnekler verilebilir. +API sistemlerinin ihtiyaรง duyduฤŸu temel รถzelliklerden biri, koddan (Python) veriyi alฤฑp aฤŸ รผzerinden gรถnderilebilecek bir ลŸeye dรถnรผลŸtรผrmek, yani veri โ€œdรถnรผลŸรผmโ€รผdรผr. ร–rneฤŸin, bir veritabanฤฑndan gelen verileri iรงeren bir objeyi JSON objesine dรถnรผลŸtรผrmek, `datetime` objelerini stringโ€™e รงevirmek vb. -API'lara gereken bir diฤŸer bรผyรผk รถzellik ise veri doฤŸrulamadฤฑr, yani verinin รงeลŸitli parametrelere baฤŸlฤฑ olarak doฤŸru ve tutarlฤฑ olduฤŸundan emin olmaktฤฑr. ร–rneฤŸin bir alanฤฑn `int` olmasฤฑna karar verdiniz, daha sonra rastgele bir metin deฤŸeri almasฤฑnฤฑ istemezsiniz. Bu รถzellikle sisteme dฤฑลŸarฤฑdan gelen veri iรงin kullanฤฑลŸlฤฑ bir รถzellik oluyor. +APIโ€™larฤฑn ihtiyaรง duyduฤŸu bir diฤŸer รถnemli รถzellik, veri doฤŸrulamadฤฑr; belirli parametreler gรถz รถnรผne alฤฑndฤฑฤŸฤฑnda verinin geรงerli olduฤŸundan emin olmak. ร–rneฤŸin, bir alanฤฑn `int` olmasฤฑ ve rastgele bir metin olmamasฤฑ. Bu รถzellikle dฤฑลŸarฤฑdan gelen veriler iรงin kullanฤฑลŸlฤฑdฤฑr. -Bir veri doฤŸrulama sistemi olmazsa bรผtรผn bu kontrolleri koda dรถkerek kendiniz yapmak zorunda kalฤฑrdฤฑnฤฑz. +Bir veri doฤŸrulama sistemi olmadan, tรผm bu kontrolleri kod iรงinde el ile yapmanฤฑz gerekir. -Marshmallow bu รถzellikleri saฤŸlamak iรงin geliลŸtirilmiลŸti. Benim de geรงmiลŸte oldukรงa sฤฑk kullandฤฑฤŸฤฑm harika bir kรผtรผphanedir. +Marshmallow, bu รถzellikleri saฤŸlamak iรงin inลŸa edildi. Harika bir kรผtรผphanedir ve geรงmiลŸte รงok kullandฤฑm. -Ama... Python'un tip belirteรงleri gelmeden รถnce oluลŸturulmuลŸtu. Yani her ลŸemayฤฑ tanฤฑmlamak iรงin Marshmallow'un sunduฤŸu spesifik araรงlarฤฑ ve sฤฑnฤฑflarฤฑ kullanmanฤฑz gerekiyordu. +Ancak Python tip belirteรงlerinden รถnce yazฤฑlmฤฑลŸtฤฑr. Dolayฤฑsฤฑyla her ลŸemayฤฑ tanฤฑmlamak iรงin Marshmallowโ€™un saฤŸladฤฑฤŸฤฑ belirli yardฤฑmcฤฑlar ve sฤฑnฤฑflar kullanฤฑlฤฑr. -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -Kod kullanarak otomatik olarak veri tipini ve veri doฤŸrulamayฤฑ belirten "ลŸemalar" tanฤฑmlamalฤฑ. +Kodla, veri tiplerini ve doฤŸrulamayฤฑ otomatik saฤŸlayan โ€œลŸemalarโ€ tanฤฑmlamak. /// -### Webargs +### Webargs { #webargs } -API'larฤฑn ihtiyacฤฑ olan bir diฤŸer รถnemli รถzellik ise gelen isteklerdeki verileri Python objelerine ayrฤฑลŸtฤฑrabilmektir. +APIโ€™larฤฑn ihtiyaรง duyduฤŸu bir diฤŸer bรผyรผk รถzellik, gelen isteklerden veriyi ayrฤฑลŸtฤฑrmadฤฑr. -Webargs, Flask gibi bir kaรง framework'รผn รผzerinde bunu saฤŸlamak iรงin geliลŸtirilen bir araรงtฤฑr. +Webargs, Flask dahil birkaรง frameworkโ€™รผn รผzerinde bunu saฤŸlamak iรงin geliลŸtirilmiลŸ bir araรงtฤฑr. -Veri doฤŸrulama iรงin arka planda Marshmallow kullanฤฑyor, hatta aynฤฑ geliลŸtiriciler tarafฤฑndan oluลŸturuldu. +Veri doฤŸrulama iรงin arka planda Marshmallowโ€™u kullanฤฑr. Aynฤฑ geliลŸtiriciler tarafฤฑndan yazฤฑlmฤฑลŸtฤฑr. -Webargs da harika bir araรง ve onu da geรงmiลŸte henรผz **FastAPI** yokken รงok kullandฤฑm. +**FastAPI**โ€™dan รถnce benim de รงok kullandฤฑฤŸฤฑm harika bir araรงtฤฑr. /// info | Bilgi -Webargs aynฤฑ Marshmallow geliลŸtirileri tarafฤฑndan oluลŸturuldu. +Webargs, Marshmallow geliลŸtiricileri tarafฤฑndan oluลŸturuldu. /// -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -Gelen istek verisi iรงin otomatik veri doฤŸrulamaya sahip olmalฤฑ. +Gelen istek verisini otomatik doฤŸrulamak. /// -### APISpec +### APISpec { #apispec } -Marshmallow ve Webargs eklentiler olarak; veri doฤŸrulama, ayrฤฑลŸtฤฑrma ve dรถnรผลŸtรผrmeyi saฤŸlฤฑyor. +Marshmallow ve Webargs; doฤŸrulama, ayrฤฑลŸtฤฑrma ve dรถnรผลŸรผmรผ eklenti olarak saฤŸlar. -Ancak dรถkรผmantasyondan hala ses seda yok. Daha sonrasฤฑnda ise APISpec geldi. +Ama dรถkรผmantasyon eksikti. Sonra APISpec geliลŸtirildi. -APISpec pek รงok framework iรงin bir eklenti olarak kullanฤฑlฤฑyor (Starlette iรงin de bir eklentisi var). +Birรงok framework iรงin bir eklentidir (Starlette iรงin de bir eklenti vardฤฑr). -ลžemanฤฑn tanฤฑmฤฑnฤฑ yol'a istek geldiฤŸinde รงalฤฑลŸan her bir fonksiyonun dรถkรผman dizesinin iรงine YAML formatฤฑnda olacak ลŸekilde yazฤฑyorsunuz o da OpenAPI ลŸemalarฤฑ รผretiyor. +ร‡alฤฑลŸma ลŸekli: Her bir routeโ€™u iลŸleyen fonksiyonun docstringโ€™i iรงine YAML formatฤฑnda ลŸema tanฤฑmฤฑ yazarsฤฑnฤฑz. -Flask, Starlette, Responder ve benzerlerinde bu ลŸekilde รงalฤฑลŸฤฑyor. +Ve OpenAPI ลŸemalarฤฑ รผretir. -Fakat sonrasฤฑnda yine mikro sรถzdizimi problemiyle karลŸฤฑlaลŸฤฑyoruz. Python metinlerinin iรงinde koskoca bir YAML oluyor. +Flask, Starlette, Responder vb. iรงin รงalฤฑลŸma ลŸekli bรถyledir. -Editรถr bu konuda pek yardฤฑmcฤฑ olamaz. รœstelik eฤŸer parametreleri ya da Marshmallow ลŸemalarฤฑnฤฑ deฤŸiลŸtirip YAML kodunu gรผncellemeyi unutursak artฤฑk dรถkรผman geรงerliliฤŸini yitiriyor. +Ancak yine, Python metni iรงinde (kocaman bir YAML) mikro bir sรถz dizimi sorunu ortaya รงฤฑkar. + +Editรถr bu konuda pek yardฤฑmcฤฑ olamaz. Parametreleri veya Marshmallow ลŸemalarฤฑnฤฑ deฤŸiลŸtirip docstringโ€™teki YAMLโ€™ฤฑ gรผncellemeyi unutursak, รผretilen ลŸema geรงerliliฤŸini yitirir. /// info | Bilgi -APISpec de aynฤฑ Marshmallow geliลŸtiricileri tarafฤฑndan oluลŸturuldu. +APISpec, Marshmallow geliลŸtiricileri tarafฤฑndan oluลŸturuldu. /// -/// check | **FastAPI**'a nasฤฑl ilham verdi? +/// check | **FastAPI**'a ilham olan -API'lar iรงin aรงฤฑk standart desteฤŸi olmalฤฑ (OpenAPI gibi). +APIโ€™lar iรงin aรงฤฑk standart olan OpenAPIโ€™ฤฑ desteklemek. /// -### Flask-apispec +### Flask-apispec { #flask-apispec } -Flask-apispec ise Webargs, Marshmallow ve APISpec'i birbirine baฤŸlayan bir Flask eklentisi. +Webargs, Marshmallow ve APISpecโ€™i bir araya getiren bir Flask eklentisidir. -Webargs ve Marshmallow'daki bilgiyi APISpec ile otomatik OpenAPI ลŸemalarฤฑ รผretmek iรงin kullanฤฑyor. +Webargs ve Marshmallowโ€™dan aldฤฑฤŸฤฑ bilgiyi kullanarak, APISpec ile otomatik OpenAPI ลŸemalarฤฑ รผretir. -Hak ettiฤŸi deฤŸeri gรถrmeyen, harika bir araรง. Piyasadaki รงoฤŸu Flask eklentisinden รงok daha popรผler olmalฤฑ. Hak ettiฤŸi deฤŸeri gรถrmรผyor oluลŸunun sebebi ise dรถkรผmantasyonun รงok kฤฑsa ve soyut olmasฤฑ olabilir. +Harika ama yeterince deฤŸer gรถrmeyen bir araรงtฤฑr. Mevcut birรงok Flask eklentisinden รงok daha popรผler olmalฤฑydฤฑ. Muhtemelen dรถkรผmantasyonunun fazla kฤฑsa ve soyut olmasฤฑndan kaynaklanฤฑyor olabilir. -Bรถylece Flask-apispec, Python dรถkรผman dizilerine YAML gibi farklฤฑ bir syntax yazma sorununu รงรถzmรผลŸ oldu. +Python docstringโ€™leri iรงine YAML (farklฤฑ bir sรถz dizimi) yazma ihtiyacฤฑnฤฑ ortadan kaldฤฑrdฤฑ. -**FastAPI**'ฤฑ geliลŸtirene dek benim favori arka uรง kombinasyonum Flask'in yanฤฑnda Marshmallow ve Webargs ile birlikte Flask-apispec idi. +**FastAPI**โ€™yฤฑ inลŸa edene kadar, Flask + Flask-apispec + Marshmallow + Webargs kombinasyonu benim favori arka uรง stackโ€™imdi. -Bunu kullanmak, bir kaรง full-stack Flask projesi oluลŸturucusunun yaratฤฑlmasฤฑna yol aรงtฤฑ. Bunlar benim (ve bir kaรง harici ekibin de) ลŸimdiye kadar kullandฤฑฤŸฤฑ asฤฑl stackler: +Bunu kullanmak, birkaรง Flask fullโ€‘stack รผreticisinin ortaya รงฤฑkmasฤฑna yol aรงtฤฑ. ลžu ana kadar benim (ve birkaรง harici ekibin) kullandฤฑฤŸฤฑ ana stackโ€™ler: * https://github.com/tiangolo/full-stack * https://github.com/tiangolo/full-stack-flask-couchbase * https://github.com/tiangolo/full-stack-flask-couchdb -Aynฤฑ full-stack รผreticiler [**FastAPI** Proje รœreticileri](project-generation.md){.internal-link target=_blank}'nin de temelini oluลŸturdu. +Aynฤฑ fullโ€‘stack รผreticiler, [**FastAPI** Proje รœreticileri](project-generation.md){.internal-link target=_blank}โ€™nin de temelini oluลŸturdu. /// info | Bilgi -Flask-apispec de aynฤฑ Marshmallow geliลŸtiricileri tarafฤฑndan รผretildi. +Flask-apispec, Marshmallow geliลŸtiricileri tarafฤฑndan oluลŸturuldu. /// -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan -Veri dรถnรผลŸรผmรผ ve veri doฤŸrulamayฤฑ tanฤฑmlayan kodu kullanarak otomatik olarak OpenAPI ลŸemasฤฑ oluลŸturmalฤฑ. +Veri dรถnรผลŸรผmรผ ve doฤŸrulamayฤฑ tanฤฑmlayan aynฤฑ koddan, OpenAPI ลŸemasฤฑnฤฑ otomatik รผretmek. /// -### NestJS (and Angular) +### NestJS (ve Angular) { #nestjs-and-angular } -Bu Python teknolojisi bile deฤŸil. NestJS, Angulardan ilham almฤฑลŸ olan bir JavaScript (TypeScript) NodeJS framework'รผ. +Bu Python bile deฤŸil; NestJS, Angularโ€™dan ilham alan bir JavaScript (TypeScript) NodeJS frameworkโ€™รผdรผr. -Flask-apispec ile yapฤฑlabileceklere nispeten benzeyen bir ลŸey elde ediyor. +Flask-apispec ile yapฤฑlabilene kฤฑsmen benzer bir ลŸey baลŸarฤฑr. -Angular 2'den ilham alan, iรงine gรถmรผlรผ bir baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi var. BildiฤŸim diฤŸer tรผm baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemlerinde olduฤŸu gibi"baฤŸฤฑmlฤฑlฤฑk"larฤฑ รถnceden kaydetmenizi gerektiriyor. Bรถylece projeyi daha detaylฤฑ hale getiriyor ve kod tekrarฤฑnฤฑ da arttฤฑrฤฑyor. +Angular 2โ€™den esinlenen, entegre bir baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi vardฤฑr. โ€œInjectableโ€larฤฑ รถnceden kaydetmeyi gerektirir (bildiฤŸim diฤŸer baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemlerinde olduฤŸu gibi), bu da ayrฤฑntฤฑyฤฑ ve kod tekrarฤฑnฤฑ artฤฑrฤฑr. -Parametreler TypeScript tipleri (Python tip belirteรงlerine benzer) ile aรงฤฑklandฤฑฤŸฤฑndan editรถr desteฤŸi oldukรงa iyi. +Parametreler TypeScript tipleriyle (Python tip belirteรงlerine benzer) aรงฤฑklandฤฑฤŸฤฑndan, editรถr desteฤŸi oldukรงa iyidir. -Ama TypeScript verileri kod JavaScript'e derlendikten sonra korunmadฤฑฤŸฤฑndan, bunlara dayanarak aynฤฑ anda veri doฤŸrulamasฤฑ, veri dรถnรผลŸรผmรผ ve dรถkรผmantasyon tanฤฑmlanamฤฑyor. Bundan ve bazฤฑ tasarฤฑm tercihlerinden dolayฤฑ veri doฤŸrulamasฤฑ, dรถnรผลŸรผmรผ ve otomatik ลŸema รผretimi iรงin pek รงok yere dekorator eklemek gerekiyor. Bu da projeyi oldukรงa detaylandฤฑrฤฑyor. +Ancak TypeScript tip bilgisi JavaScriptโ€™e derlemeden sonra korunmadฤฑฤŸฤฑndan, aynฤฑ anda tiplere dayanarak doฤŸrulama, dรถnรผลŸรผm ve dรถkรผmantasyon tanฤฑmlanamaz. Bu ve bazฤฑ tasarฤฑm kararlarฤฑ nedeniyle doฤŸrulama, dรถnรผลŸรผm ve otomatik ลŸema รผretimi iรงin birรงok yere dekoratรถr eklemek gerekir; proje oldukรงa ayrฤฑntฤฑlฤฑ hรขle gelir. -ฤฐรง iรงe geรงen derin modelleri pek iyi iลŸleyemiyor. Yani eฤŸer istekteki JSON gรถvdesi derin bir JSON objesiyse dรผzgรผn bir ลŸekilde dรถkรผmante edilip doฤŸrulanamฤฑyor. +ฤฐรงiรงe modelleri รงok iyi iลŸleyemez. Yani istek gรถvdesindeki JSON, iรงinde baลŸka alanlarฤฑ ve onlar da iรงiรงe JSON objelerini iรงeriyorsa, doฤŸru ลŸekilde dรถkรผmante edilip doฤŸrulanamaz. -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan -Gรผzel bir editรถr desteฤŸi iรงin Python tiplerini kullanmalฤฑ. +Harika editรถr desteฤŸi iรงin Python tiplerini kullanmak. -Gรผรงlรผ bir baฤŸฤฑmlฤฑlฤฑk enjeksiyon sistemine sahip olmalฤฑ. Kod tekrarฤฑnฤฑ minimuma indirecek bir yol bulmalฤฑ. +Gรผรงlรผ bir baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemine sahip olmak. Kod tekrarฤฑnฤฑ en aza indirmenin bir yolunu bulmak. /// -### Sanic +### Sanic { #sanic } -Sanic, `asyncio`'ya dayanan son derece hฤฑzlฤฑ Python kรผtรผphanelerinden biriydi. Flask'a epey benzeyecek ลŸekilde geliลŸtirilmiลŸti. +`asyncio` tabanlฤฑ, son derece hฤฑzlฤฑ ilk Python frameworkโ€™lerinden biriydi. Flaskโ€™a oldukรงa benzer olacak ลŸekilde geliลŸtirilmiลŸti. -/// note | Teknik detaylar +/// note | Teknik Detaylar -ฤฐรงerisinde standart Python `asyncio` dรถngรผsรผ yerine `uvloop` kullanฤฑldฤฑ. Hฤฑzฤฑnฤฑn asฤฑl kaynaฤŸฤฑ buydu. +Varsayฤฑlan Python `asyncio` dรถngรผsรผ yerine `uvloop` kullanฤฑr; hฤฑzฤฑnฤฑ esasen bu saฤŸlar. -Uvicorn ve Starlette'e ilham kaynaฤŸฤฑ olduฤŸu oldukรงa aรงฤฑk, ลŸu anda ikisi de aรงฤฑk karลŸฤฑlaลŸtฤฑrmalarda Sanicten daha hฤฑzlฤฑ gรถzรผkรผyor. +Aรงฤฑk kฤฑyaslamalarda, bugรผn Uvicorn ve Starletteโ€™in Sanicโ€™ten daha hฤฑzlฤฑ olduฤŸu gรถrรผlรผr; Sanic bu ikisine ilham vermiลŸtir. /// -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan -Uรงuk performans saฤŸlayacak bir yol bulmalฤฑ. +ร‡ok yรผksek performans elde etmenin bir yolunu bulmak. -Tam da bu yรผzden **FastAPI** Starlette'e dayanฤฑyor, รงรผnkรผ Starlette ลŸu anda kullanฤฑlabilir en hฤฑzlฤฑ framework. (รผรงรผncรผ parti karลŸฤฑlaลŸtฤฑrmalฤฑ testlerine gรถre) +Bu yรผzden **FastAPI**, en hฤฑzlฤฑ framework olduฤŸu iรงin (รผรงรผncรผ parti kฤฑyaslamalara gรถre) Starlette รผzerine kuruludur. /// -### Falcon - -Falcon ise bir diฤŸer yรผksek performanslฤฑ Python framework'รผ. Minimal olacak ลŸekilde Hug gibi diฤŸer framework'lerin temeli olabilmek iรงin tasarlandฤฑ. +### Falcon { #falcon } -ฤฐki parametre kabul eden fonksiyonlar ลŸeklinde tasarlandฤฑ, biri "istek" ve diฤŸeri ise "cevap". Sonra isteฤŸin รงeลŸitli kฤฑsฤฑmlarฤฑnฤฑ **okuyor**, cevaba ise bir ลŸeyler **yazฤฑyorsunuz**. Bu tasarฤฑmdan dolayฤฑ istek parametrelerini ve gรถvdelerini standart Python tip belirteรงlerini kullanarak fonksiyon parametreleriyle belirtmek mรผmkรผn deฤŸil. +Falcon, baลŸka bir yรผksek performanslฤฑ Python frameworkโ€™รผdรผr; minimal olacak ลŸekilde tasarlanmฤฑลŸ ve Hug gibi diฤŸer frameworkโ€™lere temel olmuลŸtur. -Yani veri doฤŸrulama, veri dรถnรผลŸtรผrme ve dรถkรผmantasyonun hepsi kodda yer almalฤฑ, otomatik halledemiyoruz. Ya da Falcon รผzerine bir framework olarak uygulanmalarฤฑ gerekiyor, aynฤฑ Hug'da olduฤŸu gibi. Bu ayrฤฑm Falcon'un tasarฤฑmฤฑndan esinlenen, istek ve cevap objelerini parametre olarak iลŸleyen diฤŸer kรผtรผphanelerde de yer alฤฑyor. +ฤฐki parametre alan fonksiyonlar etrafฤฑnda tasarlanmฤฑลŸtฤฑr: โ€œrequestโ€ ve โ€œresponseโ€. ฤฐstekten parรงalar โ€œokurโ€, cevaba parรงalar โ€œyazarsฤฑnฤฑzโ€. Bu tasarฤฑm nedeniyle, fonksiyon parametreleriyle standart Python tip belirteรงlerini kullanarak istek parametrelerini ve gรถvdelerini ilan etmek mรผmkรผn deฤŸildir. -/// check | **FastAPI**'a nasฤฑl ilham oldu? +Dolayฤฑsฤฑyla veri doฤŸrulama, dรถnรผลŸรผm ve dรถkรผmantasyon kodda yapฤฑlmalฤฑ; otomatik olmaz. Ya da Hugโ€™da olduฤŸu gibi Falconโ€™un รผzerine bir framework olarak uygulanmalฤฑdฤฑr. Falconโ€™un tasarฤฑmฤฑndan etkilenen ve tek bir request objesi ile response objesini parametre olarak alan diฤŸer frameworkโ€™lerde de aynฤฑ ayrฤฑm vardฤฑr. -Harika bir performans'a sahip olmanฤฑn yollarฤฑnฤฑ bulmalฤฑ. +/// check | **FastAPI**'a ilham olan -Hug ile birlikte (Hug zaten Falcon'a dayandฤฑฤŸฤฑndan) **FastAPI**'ฤฑn fonksiyonlarda `cevap` parametresi belirtmesinde ilham kaynaฤŸฤฑ oldu. +Harika performans elde etmenin yollarฤฑnฤฑ bulmak. -FastAPI'da opsiyonel olmasฤฑna raฤŸmen, daha รงok header'lar, รงerezler ve alternatif durum kodlarฤฑ belirlemede kullanฤฑlฤฑyor. +Hug ile birlikte (Hug, Falconโ€™a dayanฤฑr) **FastAPI**โ€™da fonksiyonlarda opsiyonel bir `response` parametresi ilan edilmesi fikrine ilham vermek. FastAPIโ€™da bu parametre รงoฤŸunlukla header, cookie ve alternatif durum kodlarฤฑnฤฑ ayarlamak iรงin kullanฤฑlฤฑr. /// -### Molten +### Molten { #molten } -**FastAPI**'ฤฑ geliลŸtirmenin ilk aลŸamalarฤฑnda Molten'ฤฑ keลŸfettim. Pek รงok ortak fikrimiz vardฤฑ: +**FastAPI**โ€™ฤฑ geliลŸtirmenin ilk aลŸamalarฤฑnda Moltenโ€™ฤฑ keลŸfettim. Oldukรงa benzer fikirleri vardฤฑ: -* Python'daki tip belirteรงlerini baz alฤฑyordu. -* Bunlara baฤŸlฤฑ olarak veri doฤŸrulamasฤฑ ve dรถkรผmantasyon saฤŸlฤฑyordu. -* Bir baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi vardฤฑ. +* Python tip belirteรงlerine dayanฤฑr. +* Bu tiplere baฤŸlฤฑ doฤŸrulama ve dรถkรผmantasyon saฤŸlar. +* BaฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi vardฤฑr. -Veri doฤŸrulama, veri dรถnรผลŸtรผrme ve dรถkรผmantasyon iรงin Pydantic gibi bir รผรงรผncรผ parti kรผtรผphane kullanmฤฑyor, kendi iรงerisinde bunlara sahip. Yani bu veri tipi tanฤฑmlarฤฑnฤฑ tekrar kullanmak pek de kolay deฤŸil. +Pydantic gibi doฤŸrulama, dรถnรผลŸรผm ve dรถkรผmantasyon iรงin รผรงรผncรผ parti bir kรผtรผphane kullanmaz; kendi iรงinde saฤŸlar. Bu yรผzden bu veri tipi tanฤฑmlarฤฑnฤฑ tekrar kullanmak o kadar kolay olmaz. -Biraz daha detaylฤฑ ayarlamalara gerek duyuyor. Ayrฤฑca ASGI yerine WSGI'a dayanฤฑyor. Yani Uvicorn, Starlette ve Sanic gibi araรงlarฤฑn yรผksek performansฤฑndan faydalanacak ลŸekilde tasarlanmamฤฑลŸ. +Biraz daha ayrฤฑntฤฑlฤฑ yapฤฑlandฤฑrma ister. Ve ASGI yerine WSGI tabanlฤฑ olduฤŸundan, Uvicorn, Starlette ve Sanic gibi araรงlarฤฑn yรผksek performansฤฑndan faydalanmaya yรถnelik tasarlanmamฤฑลŸtฤฑr. -BaฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi baฤŸฤฑmlฤฑlฤฑklarฤฑn รถnceden kaydedilmesini ve sonrasฤฑnda belirlenen veri tiplerine gรถre รงรถzรผlmesini gerektiriyor. Yani spesifik bir tip, birden fazla bileลŸen ile belirlenemiyor. +BaฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi, baฤŸฤฑmlฤฑlฤฑklarฤฑn รถnceden kaydedilmesini ve tiplerine gรถre รงรถzรผlmesini gerektirir. Yani belirli bir tipi saฤŸlayan birden fazla โ€œbileลŸenโ€ tanฤฑmlanamaz. -Yol'lar fonksiyonun รผstรผnde endpoint'i iลŸleyen dekoratรถrler yerine farklฤฑ yerlerde tanฤฑmlanan fonksiyonlarla belirlenir. Bu Flask (ve Starlette) yerine daha รงok Django'nun yaklaลŸฤฑmฤฑna daha yakฤฑn bir metot. Bu, kodda nispeten birbiriyle sฤฑkฤฑ iliลŸkili olan ลŸeyleri ayฤฑrmaya sebep oluyor. +Routeโ€™lar, endpointโ€™i iลŸleyen fonksiyonun รผstรผne konan dekoratรถrlerle deฤŸil, tek bir yerde, farklฤฑ yerlerde tanฤฑmlanmฤฑลŸ fonksiyonlar kullanฤฑlarak ilan edilir. Bu yaklaลŸฤฑm, Flask (ve Starlette) yerine Djangoโ€™ya daha yakฤฑndฤฑr; kodda aslฤฑnda birbirine sฤฑkฤฑ baฤŸlฤฑ olan ลŸeyleri ayฤฑrฤฑr. -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan -Model รถzelliklerinin "standart" deฤŸerlerini kullanarak veri tipleri iรงin ekstra veri doฤŸrulama koลŸullarฤฑ tanฤฑmlamalฤฑ. Bu editรถr desteฤŸini geliลŸtiriyor ve daha รถnceden Pydantic'te yoktu. +Model รถzelliklerinin โ€œvarsayฤฑlanโ€ deฤŸerlerini kullanarak veri tiplerine ekstra doฤŸrulamalar tanฤฑmlamak. Bu, editรถr desteฤŸini iyileลŸtirir ve Pydanticโ€™te daha รถnce yoktu. -Bu aslฤฑnda Pydantic'in de aynฤฑ doฤŸrulama stiline geรงmesinde ilham kaynaฤŸฤฑ oldu. ลžu anda bรผtรผn bu รถzellikler Pydantic'in yapฤฑsฤฑnda yer alฤฑyor. +Bu yaklaลŸฤฑm, Pydanticโ€™te de aynฤฑ doฤŸrulama beyan stilinin desteklenmesine ilham verdi (bu iลŸlevselliklerin tamamฤฑ artฤฑk Pydanticโ€™te mevcut). /// -### Hug +### Hug { #hug } -Hug, Python tip belirteรงlerini kullanarak API parametrelerinin tipini belirlemeyi uygulayan ilk framework'lerdendi. Bu, diฤŸer araรงlara da ilham kaynaฤŸฤฑ olan harika bir fikirdi. +Hug, Python tip belirteรงlerini kullanarak API parametre tiplerini ilan etmeyi uygulayan ilk frameworkโ€™lerden biriydi. DiฤŸer araรงlara da ilham veren harika bir fikirdi. -Tip belirlerken standart Python veri tipleri yerine kendi รถzel tiplerini kullandฤฑ, yine de bu ileriye dรถnรผk devasa bir adฤฑmdฤฑ. +Standart Python tipleri yerine kendi รถzel tiplerini kullansa da bรผyรผk bir adฤฑmdฤฑ. -Hug ayrฤฑca tรผm API'ฤฑ JSON ile ifade eden รถzel bir ลŸema oluลŸturan ilk framework'lerdendir. +JSON ile tรผm APIโ€™ฤฑ beyan eden รถzel bir ลŸema รผreten ilk frameworkโ€™lerden biriydi. -OpenAPI veya JSON ลžemasฤฑ gibi bir standarda baฤŸlฤฑ deฤŸildi. Yani Swagger UI gibi diฤŸer araรงlarla entegre etmek kolay olmazdฤฑ. Ama yine de, bu oldukรงa yenilikรงi bir fikirdi. +OpenAPI veya JSON Schema gibi bir standarda dayanmadฤฑฤŸฤฑ iรงin Swagger UI gibi diฤŸer araรงlarla doฤŸrudan entegre edilemezdi. Yine de oldukรงa yenilikรงiydi. -Ayrฤฑca ilginรง ve รงok rastlanmayan bir รถzelliฤŸi vardฤฑ: aynฤฑ framework'รผ kullanarak hem API'lar hem de CLI'lar oluลŸturmak mรผmkรผndรผ. +Nadir bir รถzelliฤŸi daha vardฤฑ: aynฤฑ framework ile hem APIโ€™lar hem de CLIโ€™lar oluลŸturmak mรผmkรผndรผ. -Senkron รงalฤฑลŸan Python web framework'lerinin standardฤฑna (WSGI) dayandฤฑฤŸฤฑndan dolayฤฑ Websocket'leri ve diฤŸer ลŸeyleri iลŸleyemiyor, ancak yine de yรผksek performansa sahip. +Senkron Python web frameworkโ€™leri iรงin รถnceki standart olan WSGIโ€™ye dayandฤฑฤŸฤฑndan, WebSocket vb. ลŸeyleri iลŸleyemez, ancak yine de yรผksek performansa sahiptir. /// info | Bilgi -Hug, Python dosyalarฤฑnda bulunan dahil etme satฤฑrlarฤฑnฤฑ otomatik olarak sฤฑralayan harika bir araรง olan `isort`'un geliลŸtiricisi Timothy Crosley tarafฤฑndan geliลŸtirildi. +Hug, Python dosyalarฤฑndaki importโ€™larฤฑ otomatik sฤฑralayan harika bir araรง olan `isort`โ€™un geliลŸtiricisi Timothy Crosley tarafฤฑndan geliลŸtirildi. /// -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan fikirler -Hug, APIStar'ฤฑn รงeลŸitli kฤฑsฤฑmlarฤฑnda esin kaynaฤŸฤฑ oldu ve APIStar'la birlikte en umut verici bulduฤŸum araรงlardan biriydi. +Hug, APIStarโ€™ฤฑn bazฤฑ kฤฑsฤฑmlarฤฑna ilham verdi ve APIStar ile birlikte en umut verici bulduฤŸum araรงlardandฤฑ. -**FastAPI**, Python tip belirteรงlerini kullanarak parametre belirlemede ve API'ฤฑ otomatฤฑk tanฤฑmlayan bir ลŸema รผretmede de Hug'a esinlendi. +**FastAPI**, parametreleri ilan etmek ve APIโ€™ฤฑ otomatik tanฤฑmlayan bir ลŸema รผretmek iรงin Python tip belirteรงlerini kullanma fikrini Hugโ€™dan ilhamla benimsedi. -**FastAPI**'ฤฑn header ve รงerez tanฤฑmlamak iรงin fonksiyonlarda `response` parametresini belirtmesinde de Hug'dan ilham alฤฑndฤฑ. +Ayrฤฑca header ve cookie ayarlamak iรงin fonksiyonlarda `response` parametresi ilan etme fikrine de Hug ilham verdi. /// -### APIStar (<= 0.5) +### APIStar (<= 0.5) { #apistar-0-5 } -**FastAPI**'ฤฑ geliลŸtirmeye baลŸlamadan hemen รถnce **APIStar** sunucusunu buldum. Benim aradฤฑฤŸฤฑm ลŸeylerin neredeyse hepsine sahipti ve harika bir tasarฤฑmฤฑ vardฤฑ. +**FastAPI**โ€™yi inลŸa etmeye karar vermeden hemen รถnce **APIStar** sunucusunu buldum. AradฤฑฤŸฤฑm ลŸeylerin neredeyse hepsine sahipti ve harika bir tasarฤฑmฤฑ vardฤฑ. -Benim ลŸimdiye kadar gรถrdรผฤŸรผm Python tip belirteรงlerini kullanarak parametre ve istekler belirlemeyi uygulayan ilk framework'lerdendi (Molten ve NestJS'den รถnce). APIStar'ฤฑ da aลŸaฤŸฤฑ yukarฤฑ Hug ile aynฤฑ zamanlarda buldum. Fakat APIStar OpenAPI standardฤฑnฤฑ kullanฤฑyordu. +Python tip belirteรงleriyle parametreleri ve istekleri ilan eden bir frameworkโ€™รผn gรถrdรผฤŸรผm ilk รถrneklerindendi (NestJS ve Moltenโ€™dan รถnce). AลŸaฤŸฤฑ yukarฤฑ Hug ile aynฤฑ zamanlarda buldum; ancak APIStar, OpenAPI standardฤฑnฤฑ kullanฤฑyordu. -Farklฤฑ yerlerdeki tip belirteรงlerine baฤŸlฤฑ olarak otomatik veri doฤŸrulama, veri dรถnรผลŸtรผrme ve OpenAPI ลŸemasฤฑ oluลŸturma desteฤŸi sunuyordu. +Farklฤฑ yerlerdeki aynฤฑ tip belirteรงlerine dayanarak otomatik veri doฤŸrulama, veri dรถnรผลŸรผmรผ ve OpenAPI ลŸemasฤฑ รผretimi vardฤฑ. -Gรถvde ลŸema tanฤฑmlarฤฑ Pydantic ile aynฤฑ Python tip belirteรงlerini kullanmฤฑyordu, biraz daha Marsmallow'a benziyordu. Dolayฤฑsฤฑyla editรถr desteฤŸi de o kadar iyi olmazdฤฑ ama APIStar eldeki en iyi seรงenekti. +Gรถvde ลŸema tanฤฑmlarฤฑ Pydanticโ€™tekiyle aynฤฑ Python tip belirteรงlerini kullanmฤฑyordu; biraz daha Marshmallowโ€™a benziyordu. Bu yรผzden editรถr desteฤŸi o kadar iyi olmazdฤฑ; yine de APIStar mevcut en iyi seรงenekti. -O dรถnemlerde karลŸฤฑlaลŸtฤฑrmalarda en iyi performansa sahipti (yalnฤฑzca Starlette'e kaybediyordu). +O dรถnem kฤฑyaslamalarda en iyi performansa sahipti (sadece Starlette tarafฤฑndan geรงiliyordu). -BaลŸlangฤฑรงta otomatik API dรถkรผmantasyonu sunan bir web arayรผzรผ yoktu, ama ben ona Swagger UI ekleyebileceฤŸimi biliyordum. +BaลŸta otomatik API dรถkรผmantasyonu sunan bir web arayรผzรผ yoktu ama Swagger UI ekleyebileceฤŸimi biliyordum. -BaฤŸฤฑmlฤฑlฤฑk enjeksiyon sistemi vardฤฑ. Yukarฤฑda bahsettiฤŸim diฤŸer araรงlar gibi bundaki sistem de bileลŸenlerin รถnceden kaydedilmesini gerektiriyordu. Yine de harika bir รถzellikti. +BaฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi vardฤฑ. DiฤŸer araรงlarda olduฤŸu gibi bileลŸenlerin รถnceden kaydedilmesini gerektiriyordu. Yine de harika bir รถzellikti. -Gรผvenlik entegrasyonu olmadฤฑฤŸฤฑndan dolayฤฑ APIStar'ฤฑ hiรง bir zaman tam bir projede kullanamadฤฑm. Bu yรผzden Flask-apispec'e baฤŸlฤฑ full-stack proje รผreticilerde sahip olduฤŸum รถzellikleri tamamen deฤŸiลŸtiremedim. Bu gรผvenlik entegrasyonunu ekleyen bir PR oluลŸturmak da projelerim arasฤฑnda yer alฤฑyordu. +Gรผvenlik entegrasyonu olmadฤฑฤŸฤฑndan tam bir projede kullanamadฤฑm; bu yรผzden Flask-apispec tabanlฤฑ fullโ€‘stack รผreticilerle sahip olduฤŸum รถzelliklerin tamamฤฑnฤฑ ikame edemedim. Bu iลŸlevi ekleyen bir pull requestโ€™i yapฤฑlacaklar listeme almฤฑลŸtฤฑm. -Sonrasฤฑnda ise projenin odaฤŸฤฑ deฤŸiลŸti. +Sonra projenin odaฤŸฤฑ deฤŸiลŸti. -GeliลŸtiricinin Starlette'e odaklanmasฤฑ gerekince proje de artฤฑk bir API web framework'รผ olmayฤฑ bฤฑraktฤฑ. +Artฤฑk bir API web frameworkโ€™รผ deฤŸildi; geliลŸtirici Starletteโ€™e odaklanmak zorundaydฤฑ. -Artฤฑk APIStar, OpenAPI รถzelliklerini doฤŸrulamak iรงin bir dizi araรง sunan bir proje haline geldi. +ลžimdi APIStar, bir web frameworkโ€™รผ deฤŸil, OpenAPI spesifikasyonlarฤฑnฤฑ doฤŸrulamak iรงin araรงlar takฤฑmฤฑndan ibaret. /// info | Bilgi -APIStar, aลŸaฤŸฤฑdaki projeleri de รผreten Tom Christie tarafฤฑndan geliลŸtirildi: +APIStar, aลŸaฤŸฤฑdakilerin de yaratฤฑcฤฑsฤฑ olan Tom Christie tarafฤฑndan geliลŸtirildi: * Django REST Framework -* **FastAPI**'ฤฑn da dayandฤฑฤŸฤฑ Starlette -* Starlette ve **FastAPI** tarafฤฑndan da kullanฤฑlan Uvicorn +* **FastAPI**โ€™ฤฑn รผzerine kurulu Starlette +* Starlette ve **FastAPI** tarafฤฑndan kullanฤฑlan Uvicorn /// -/// check | **FastAPI**'a nasฤฑl ilham oldu? +/// check | **FastAPI**'a ilham olan -Var oldu. +Var olmak. -Aynฤฑ Python veri tipleriyle birden fazla ลŸeyi belirleme (veri doฤŸrulama, veri dรถnรผลŸtรผrme ve dรถkรผmantasyon), bir yandan da harika bir editรถr desteฤŸi sunma, benim muhteลŸem bulduฤŸum bir fikirdi. +Aynฤฑ Python tipleriyle (hem veri doฤŸrulama, dรถnรผลŸรผm ve dรถkรผmantasyon) birden รงok ลŸeyi ilan etmek ve aynฤฑ anda harika editรถr desteฤŸi saฤŸlamak, bence dahiyane bir fikirdi. -Uzunca bir sรผre boyunca benzer bir framework arayฤฑp pek รงok farklฤฑ alternatifi denedikten sonra, APIStar en iyi seรงenekti. +Uzun sรผre benzer bir framework arayฤฑp birรงok alternatifi denedikten sonra, APIStar mevcut en iyi seรงenekti. -Sonra APIStar bir sunucu olmayฤฑ bฤฑraktฤฑ ve Starlette oluลŸturuldu. Starlette, bรถyle bir sunucu sistemi iรงin daha iyi bir temel sunuyordu. Bu da **FastAPI**'ฤฑn son esin kaynaฤŸฤฑydฤฑ. +Sonra APIStar bir sunucu olarak var olmaktan รงฤฑktฤฑ ve Starlette oluลŸturuldu; bรถyle bir sistem iรงin daha iyi bir temel oldu. Bu, **FastAPI**โ€™yi inลŸa etmek iรงin son ilhamdฤฑ. -Ben bu รถnceki araรงlardan รถฤŸrendiklerime dayanarak **FastAPI**'ฤฑn รถzelliklerini arttฤฑrฤฑp geliลŸtiriyor, tip desteฤŸi sistemi ve diฤŸer kฤฑsฤฑmlarฤฑ iyileลŸtiriyorum ancak yine de **FastAPI**'ฤฑ APIStar'ฤฑn "ruhani varisi" olarak gรถrรผyorum. +ร–nceki bu araรงlardan edinilen deneyimler รผzerine รถzellikleri, tip sistemi ve diฤŸer kฤฑsฤฑmlarฤฑ geliลŸtirip artฤฑrฤฑrken, **FastAPI**โ€™yi APIStarโ€™ฤฑn โ€œruhani varisiโ€ olarak gรถrรผyorum. /// -## **FastAPI** Tarafฤฑndan Kullanฤฑlanlar +## **FastAPI** Tarafฤฑndan Kullanฤฑlanlar { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } -Pydantic Python tip belirteรงlerine dayanan; veri doฤŸrulama, veri dรถnรผลŸtรผrme ve dรถkรผmantasyon tanฤฑmlamak (JSON ลžema kullanarak) iรงin bir kรผtรผphanedir. +Pydantic, Python tip belirteรงlerine dayalฤฑ olarak veri doฤŸrulama, dรถnรผลŸรผm ve dรถkรผmantasyon (JSON Schema kullanarak) tanฤฑmlamak iรงin bir kรผtรผphanedir. -Tip belirteรงleri kullanฤฑyor olmasฤฑ onu aลŸฤฑrฤฑ sezgisel yapฤฑyor. +Bu onu aลŸฤฑrฤฑ sezgisel kฤฑlar. -Marshmallow ile karลŸฤฑlaลŸtฤฑrฤฑlabilir. Ancak karลŸฤฑlaลŸtฤฑrmalarda Marshmallowdan daha hฤฑzlฤฑ gรถrรผnรผyor. Aynฤฑ Python tip belirteรงlerine dayanฤฑyor ve editรถr desteฤŸi de harika. +Marshmallow ile karลŸฤฑlaลŸtฤฑrฤฑlabilir. Kฤฑyaslamalarda Marshmallowโ€™dan daha hฤฑzlฤฑdฤฑr. Aynฤฑ Python tip belirteรงlerine dayandฤฑฤŸฤฑ iรงin editรถr desteฤŸi harikadฤฑr. -/// check | **FastAPI** nerede kullanฤฑyor? +/// check | **FastAPI** bunu ลŸurada kullanฤฑr -Bรผtรผn veri doฤŸrulama, veri dรถnรผลŸtรผrme ve JSON ลžemasฤฑna baฤŸlฤฑ otomatik model dรถkรผmantasyonunu halletmek iรงin! +Tรผm veri doฤŸrulama, veri dรถnรผลŸรผmรผ ve JSON Schema tabanlฤฑ otomatik model dรถkรผmantasyonunu halletmekte. -**FastAPI** yaptฤฑฤŸฤฑ her ลŸeyin yanฤฑ sฤฑra bu JSON ลžema verisini alฤฑp daha sonra OpenAPI'ya yerleลŸtiriyor. +**FastAPI** daha sonra bu JSON Schema verisini alฤฑr ve (yaptฤฑฤŸฤฑ diฤŸer ลŸeylerin yanฤฑ sฤฑra) OpenAPI iรงine yerleลŸtirir. /// -### Starlette +### Starlette { #starlette } -Starlette hafif bir ASGI framework'รผ ve yรผksek performanslฤฑ asyncio servisleri oluลŸturmak iรงin ideal. +Starlette, yรผksek performanslฤฑ asyncio servisleri oluลŸturmak iรงin ideal, hafif bir ASGI frameworkโ€™รผ/araรง takฤฑmฤฑdฤฑr. -Kullanฤฑmฤฑ รงok kolay ve sezgisel, kolaylฤฑkla geniลŸletilebilecek ve modรผler bileลŸenlere sahip olacak ลŸekilde tasarlandฤฑ. +ร‡ok basit ve sezgiseldir. Kolayca geniลŸletilebilir ve modรผler bileลŸenlere sahip olacak ลŸekilde tasarlanmฤฑลŸtฤฑr. -Sahip olduฤŸu bir kaรง รถzellik: +ลžunlara sahiptir: -* Cidden etkileyici bir performans. +* Cidden etkileyici performans. * WebSocket desteฤŸi. -* ฤฐลŸlem-iรงi arka plan gรถrevleri. +* Sรผreรง iรงi arka plan gรถrevleri. * BaลŸlatma ve kapatma olaylarฤฑ. -* HTTPX ile geliลŸtirilmiลŸ bir test istemcisi. -* CORS, GZip, Static Files ve Streaming cevaplarฤฑ desteฤŸi. -* Session ve รงerez desteฤŸi. -* Kodun %100'รผ test kapsamฤฑnda. -* Kodun %100'รผ tip belirteรงleriyle desteklenmiลŸtir. -* Yalnฤฑzca bir kaรง zorunlu baฤŸฤฑmlฤฑlฤฑฤŸa sahip. +* HTTPX รผzerinde geliลŸtirilmiลŸ test istemcisi. +* CORS, GZip, Statik Dosyalar, Streaming cevaplar. +* Oturum (Session) ve Cookie desteฤŸi. +* %100 test kapsamฤฑ. +* %100 tip anotasyonlu kod tabanฤฑ. +* Az sayฤฑda zorunlu baฤŸฤฑmlฤฑlฤฑk. -Starlette ลŸu anda test edilen en hฤฑzlฤฑ Python framework'รผ. Yalnฤฑzca bir sunucu olan Uvicorn'a yeniliyor, o da zaten bir framework deฤŸil. +Starlette, ลŸu anda test edilen en hฤฑzlฤฑ Python frameworkโ€™รผdรผr. Yalnฤฑzca bir framework deฤŸil, bir sunucu olan Uvicorn tarafฤฑndan geรงilir. -Starlette bรผtรผn temel web mikro framework iลŸlevselliฤŸini saฤŸlฤฑyor. +Starlette, temel web mikroframework iลŸlevselliฤŸinin tamamฤฑnฤฑ saฤŸlar. -Ancak otomatik veri doฤŸrulama, veri dรถnรผลŸtรผrme ve dรถkรผmantasyon saฤŸlamyor. +Ancak otomatik veri doฤŸrulama, dรถnรผลŸรผm veya dรถkรผmantasyon saฤŸlamaz. -Bu, **FastAPI**'ฤฑn onun รผzerine tamamen Python tip belirteรงlerine baฤŸlฤฑ olarak eklediฤŸi (Pydantic ile) ana ลŸeylerden biri. **FastAPI** bunun yanฤฑnda artฤฑ olarak baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi, gรผvenlik araรงlarฤฑ, OpenAPI ลŸema รผretimi ve benzeri รถzellikler de ekliyor. +**FastAPI**โ€™nin bunun รผzerine eklediฤŸi ana ลŸeylerden biri, Pydantic kullanarak, bรผtรผnรผyle Python tip belirteรงlerine dayalฤฑ bu รถzelliklerdir. Buna ek olarak baฤŸฤฑmlฤฑlฤฑk enjeksiyonu sistemi, gรผvenlik yardฤฑmcฤฑlarฤฑ, OpenAPI ลŸema รผretimi vb. gelir. /// note | Teknik Detaylar -ASGI, Django'nun ana ekibi tarafฤฑndan geliลŸtirilen yeni bir "standart". Bir "Python standardฤฑ" (PEP) olma sรผrecinde fakat henรผz bir standart deฤŸil. +ASGI, Django รงekirdek ekip รผyeleri tarafฤฑndan geliลŸtirilen yeni bir โ€œstandartโ€tฤฑr. Hรขlรข resmi bir โ€œPython standardฤฑโ€ (PEP) deฤŸildir, ancak bu sรผreรง รผzerindedirler. -Bununla birlikte, halihazฤฑrda birรงok araรง tarafฤฑndan bir "standart" olarak kullanฤฑlmakta. Bu, Uvicorn'u farklฤฑ ASGI sunucularฤฑyla (Daphne veya Hypercorn gibi) deฤŸiลŸtirebileceฤŸiniz veya `python-socketio` gibi ASGI ile uyumlu araรงlarฤฑ ekleyebileciฤŸiniz iรงin birlikte รงalฤฑลŸฤฑlabilirliฤŸi bรผyรผk รถlรงรผde arttฤฑrฤฑyor. +Buna raฤŸmen, ลŸimdiden birรงok araรง tarafฤฑndan bir โ€œstandartโ€ olarak kullanฤฑlmaktadฤฑr. Bu, birlikte รงalฤฑลŸabilirliฤŸi bรผyรผk รถlรงรผde artฤฑrฤฑr; รถrneฤŸin Uvicornโ€™u baลŸka bir ASGI sunucusuyla (Daphne veya Hypercorn gibi) deฤŸiลŸtirebilir ya da `python-socketio` gibi ASGI uyumlu araรงlar ekleyebilirsiniz. /// -/// check | **FastAPI** nerede kullanฤฑyor? +/// check | **FastAPI** bunu ลŸurada kullanฤฑr -Tรผm temel web kฤฑsฤฑmlarฤฑnda รผzerine รถzellikler eklenerek kullanฤฑlmakta. +Tรผm temel web kฤฑsฤฑmlarฤฑnฤฑ ele almak; รผzerine รถzellikler eklemek. -`FastAPI` sฤฑnฤฑfฤฑnฤฑn kendisi direkt olarak `Starlette` sฤฑnฤฑfฤฑnฤฑ miras alฤฑyor! +`FastAPI` sฤฑnฤฑfฤฑ, doฤŸrudan `Starlette` sฤฑnฤฑfฤฑndan miras alฤฑr. -Yani, Starlette ile yapabileceฤŸiniz her ลŸeyi, Starlette'in bir nevi gรผรงlendirilmiลŸ hali olan **FastAPI** ile doฤŸrudan yapabilirsiniz. +Dolayฤฑsฤฑyla Starlette ile yapabildiฤŸiniz her ลŸeyi, adeta โ€œturbo ลŸarjlฤฑ Starletteโ€ olan **FastAPI** ile de doฤŸrudan yapabilirsiniz. /// -### Uvicorn +### Uvicorn { #uvicorn } -Uvicorn, uvlook ile httptools รผzerine kurulu ฤฑลŸฤฑk hzฤฑnda bir ASGI sunucusudur. +Uvicorn, uvloop ve httptools รผzerinde inลŸa edilmiลŸ, ฤฑลŸฤฑk hฤฑzฤฑnda bir ASGI sunucusudur. -Bir web framework'รผnden ziyade bir sunucudur, yani yollara baฤŸlฤฑ yรถnlendirme yapmanฤฑzฤฑ saฤŸlayan araรงlarฤฑ yoktur. Bu daha รงok Starlette (ya da **FastAPI**) gibi bir framework'รผn sunucuya ek olarak saฤŸladฤฑฤŸฤฑ bir ลŸeydir. +Bir web frameworkโ€™รผ deฤŸil, bir sunucudur. ร–rneฤŸin pathโ€™lere gรถre yรถnlendirme araรงlarฤฑ saฤŸlamaz; bunu Starlette (veya **FastAPI**) gibi bir framework รผstte saฤŸlar. -Starlette ve **FastAPI** iรงin tavsiye edilen sunucu Uvicorndur. +Starlette ve **FastAPI** iรงin รถnerilen sunucudur. -/// check | **FastAPI** neden tavsiye ediyor? +/// check | **FastAPI** bunu ลŸรถyle รถnerir -**FastAPI** uygulamalarฤฑnฤฑ รงalฤฑลŸtฤฑrmak iรงin ana web sunucusu Uvicorn! +**FastAPI** uygulamalarฤฑnฤฑ รงalฤฑลŸtฤฑrmak iรงin ana web sunucusu. -Gunicorn ile birleลŸtirdiฤŸinizde asenkron ve รงoklu iลŸlem destekleyen bir sunucu elde ediyorsunuz! +Komut satฤฑrฤฑnda `--workers` seรงeneฤŸini kullanarak asenkron รงok sรผreรงli (multiโ€‘process) bir sunucu da elde edebilirsiniz. -Daha fazla detay iรงin [Deployment](deployment/index.md){.internal-link target=_blank} bรถlรผmรผnรผ inceleyebilirsiniz. +Daha fazla detay iรงin [DaฤŸฤฑtฤฑm](deployment/index.md){.internal-link target=_blank} bรถlรผmรผne bakฤฑn. /// -## KarลŸฤฑlaลŸtฤฑrma ve Hฤฑz +## Kฤฑyaslamalar ve Hฤฑz { #benchmarks-and-speed } -Uvicorn, Starlette ve FastAPI arasฤฑndakฤฑ farkฤฑ daha iyi anlamak ve karลŸฤฑlaลŸtฤฑrma yapmak iรงin [Kฤฑyaslamalar](benchmarks.md){.internal-link target=_blank} bรถlรผmรผne bakฤฑn! +Uvicorn, Starlette ve FastAPI arasฤฑndaki farkฤฑ anlamak ve karลŸฤฑlaลŸtฤฑrmak iรงin [Kฤฑyaslamalar](benchmarks.md){.internal-link target=_blank} bรถlรผmรผne gรถz atฤฑn. diff --git a/docs/tr/docs/deployment/docker.md b/docs/tr/docs/deployment/docker.md index b48d2ddf58..6c8f74c778 100644 --- a/docs/tr/docs/deployment/docker.md +++ b/docs/tr/docs/deployment/docker.md @@ -145,8 +145,6 @@ Paket baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ tanฤฑmlamak ve yรผklemek iรงin baลŸka formatlar ve * AลŸaฤŸฤฑdakilerle bir `main.py` dosyasฤฑ oluลŸturun: ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -158,7 +156,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` @@ -260,7 +258,7 @@ FastAPI'nin dรผzgรผn ลŸekilde kapanabilmesi ve [lifespan event](../advanced/even Detaylar iรงin shell ve exec form iรงin Docker dokรผmanlarฤฑna bakabilirsiniz. -Bu durum `docker compose` kullanฤฑrken oldukรงa belirgin olabilir. Daha teknik detaylar iรงin ลŸu Docker Compose FAQ bรถlรผmรผne bakฤฑn: Why do my services take 10 seconds to recreate or stop?. +Bu durum `docker compose` kullanฤฑrken oldukรงa belirgin olabilir. Daha teknik detaylar iรงin ลŸu Docker Compose FAQ bรถlรผmรผne bakฤฑn: Hizmetlerimin yeniden oluลŸturulmasฤฑ veya durmasฤฑ neden 10 saniye sรผrรผyor?. #### Dizin Yapฤฑsฤฑ { #directory-structure } @@ -456,7 +454,7 @@ Container kullanmadan, uygulamalarฤฑ startup'ta รงalฤฑลŸtฤฑrmak ve restart mekan ## Replication - Process Sayฤฑsฤฑ { #replication-number-of-processes } -Kubernetes, Docker Swarm Mode, Nomad veya benzeri, birden fazla makinede daฤŸฤฑtฤฑk container'larฤฑ yรถneten karmaลŸฤฑk bir sistemle kurulmuลŸ bir cluster'ฤฑnฤฑz varsa, replication'ฤฑ her container iรงinde bir **process manager** (รถr. worker'lฤฑ Uvicorn) kullanarak yรถnetmek yerine, muhtemelen **cluster seviyesinde** ele almak istersiniz. +Kubernetes, Docker Swarm Mode, Nomad veya benzeri, birden fazla makinede daฤŸฤฑtฤฑk container'larฤฑ yรถneten karmaลŸฤฑk bir sistemle kurulmuลŸ bir cluster'ฤฑnฤฑz varsa, replication'ฤฑ her container iรงinde bir **process manager** (รถr. worker'lฤฑ Uvicorn) kullanarak yรถnetmek yerine, muhtemelen **cluster seviyesinde** ele almak istersiniz. Kubernetes gibi daฤŸฤฑtฤฑk container yรถnetim sistemleri, gelen request'ler iรงin **load balancing** desteฤŸi sunarken aynฤฑ zamanda **container replication**'ฤฑnฤฑ yรถnetmek iรงin entegre mekanizmalara sahiptir. Hepsi **cluster seviyesinde**. diff --git a/docs/tr/docs/history-design-future.md b/docs/tr/docs/history-design-future.md index cad290828b..764a519571 100644 --- a/docs/tr/docs/history-design-future.md +++ b/docs/tr/docs/history-design-future.md @@ -1,4 +1,4 @@ -# GeรงmiลŸi, Tasarฤฑmฤฑ ve GeleceฤŸi +# GeรงmiลŸi, Tasarฤฑmฤฑ ve GeleceฤŸi { #history-design-and-future } Bir sรผre รถnce, bir **FastAPI** kullanฤฑcฤฑsฤฑ sordu: @@ -6,7 +6,7 @@ Bir sรผre รถnce, **Pydantic**'i kullanmaya karar verdim. @@ -60,11 +60,11 @@ Sonra, JSON Schema ile tamamen uyumlu olmasฤฑnฤฑ saฤŸlamak, kฤฑsฤฑtlama bildirim GeliลŸtirme sฤฑrasฤฑnda, diฤŸer ana gereksinim olan **Starlette**'e de katkฤฑda bulundum. -## GeliลŸtirme +## GeliลŸtirme { #development } **FastAPI**'ฤฑ oluลŸturmaya baลŸladฤฑฤŸฤฑmda, parรงalarฤฑn รงoฤŸu zaten yerindeydi, tasarฤฑm tanฤฑmlanmฤฑลŸtฤฑ, gereksinimler ve araรงlar hazฤฑrdฤฑ, standartlar ve tanฤฑmlamalar hakkฤฑndaki bilgi net ve tazeydi. -## Gelecek +## Gelecek { #future } ลžimdiye kadar, **FastAPI**'ฤฑn fikirleriyle birรงok kiลŸiye faydalฤฑ olduฤŸu apaรงฤฑk ortada. diff --git a/docs/tr/docs/translation-banner.md b/docs/tr/docs/translation-banner.md new file mode 100644 index 0000000000..b52578f71d --- /dev/null +++ b/docs/tr/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ Yapay Zekรข ve ฤฐnsanlar Tarafฤฑndan ร‡eviri + +Bu รงeviri, insanlar tarafฤฑndan yรถnlendirilen bir yapay zekรข ile oluลŸturuldu. ๐Ÿค + +Orijinal anlamฤฑn yanlฤฑลŸ anlaลŸฤฑlmasฤฑ ya da kulaฤŸa doฤŸal gelmeme gibi hatalar iรงerebilir. ๐Ÿค– + +[Yapay zekรขyฤฑ daha iyi yรถnlendirmemize yardฤฑmcฤฑ olarak](https://fastapi.tiangolo.com/tr/contributing/#translations) bu รงeviriyi iyileลŸtirebilirsiniz. + +[ฤฐngilizce sรผrรผm](ENGLISH_VERSION_URL) + +/// diff --git a/docs/tr/docs/tutorial/body-multiple-params.md b/docs/tr/docs/tutorial/body-multiple-params.md index 3bac80d6a8..29970ca40e 100644 --- a/docs/tr/docs/tutorial/body-multiple-params.md +++ b/docs/tr/docs/tutorial/body-multiple-params.md @@ -103,13 +103,13 @@ Elbette ihtiyaรง duyduฤŸunuzda, body parametrelerine ek olarak query parametrele Varsayฤฑlan olarak tekil deฤŸerler query parametresi olarak yorumlandฤฑฤŸฤฑ iรงin, ayrฤฑca `Query` eklemeniz gerekmez; ลŸรถyle yazmanฤฑz yeterlidir: ```Python -q: Union[str, None] = None +q: str | None = None ``` -Ya da Python 3.10 ve รผzeri iรงin: +Ya da Python 3.9'da: ```Python -q: str | None = None +q: Union[str, None] = None ``` ร–rneฤŸin: diff --git a/docs/tr/docs/tutorial/path-operation-configuration.md b/docs/tr/docs/tutorial/path-operation-configuration.md index 610b863a4a..3fe24dc0a4 100644 --- a/docs/tr/docs/tutorial/path-operation-configuration.md +++ b/docs/tr/docs/tutorial/path-operation-configuration.md @@ -52,11 +52,11 @@ Bu durumlarda tagโ€™leri bir `Enum` iรงinde tutmak mantฤฑklฤฑ olabilir. Bir `summary` ve `description` ekleyebilirsiniz: -{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} ## Docstringโ€™den Description { #description-from-docstring } -Aรงฤฑklamalar genelde uzun olur ve birden fazla satฤฑra yayฤฑlฤฑr; bu yรผzden *path operation* aรงฤฑklamasฤฑnฤฑ, fonksiyonun iรงinde docstring olarak tanฤฑmlayabilirsiniz; **FastAPI** de onu buradan okur. +Aรงฤฑklamalar genelde uzun olur ve birden fazla satฤฑra yayฤฑlฤฑr; bu yรผzden *path operation* aรงฤฑklamasฤฑnฤฑ, fonksiyonun iรงinde docstring olarak tanฤฑmlayabilirsiniz; **FastAPI** de onu buradan okur. Docstring iรงinde Markdown yazabilirsiniz; doฤŸru ลŸekilde yorumlanฤฑr ve gรถsterilir (docstring girintisi dikkate alฤฑnarak). @@ -70,7 +70,7 @@ Interactive docsโ€™ta ลŸรถyle kullanฤฑlacaktฤฑr: `response_description` parametresi ile response aรงฤฑklamasฤฑnฤฑ belirtebilirsiniz: -{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | Bilgi @@ -90,7 +90,7 @@ Bu yรผzden siz saฤŸlamazsanฤฑz, **FastAPI** otomatik olarak "Successful response ## Bir *path operation*โ€™ฤฑ Deprecate Etmek { #deprecate-a-path-operation } -Bir *path operation*โ€™ฤฑ kaldฤฑrmadan, deprecated olarak iลŸaretlemeniz gerekiyorsa `deprecated` parametresini verin: +Bir *path operation*โ€™ฤฑ kaldฤฑrmadan, deprecated olarak iลŸaretlemeniz gerekiyorsa `deprecated` parametresini verin: {* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} From 2eb454ab04e81325ed430a036103e4aede299d61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 17:24:15 +0000 Subject: [PATCH 157/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6896100495..4ba0491a53 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* ๐ŸŒ Update translations for tr (outdated and missing). PR [#14838](https://github.com/fastapi/fastapi/pull/14838) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Internal * โฌ†๏ธ Upgrade development dependencies. PR [#14854](https://github.com/fastapi/fastapi/pull/14854) by [@tiangolo](https://github.com/tiangolo). From cba537ab717ff205857a0eb877c69e79cfd06a51 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:24:25 +0300 Subject: [PATCH 158/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(outdated=20pages)=20(#14839)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/fr/docs/tutorial/body-multiple-params.md | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/fr/docs/tutorial/body-multiple-params.md b/docs/fr/docs/tutorial/body-multiple-params.md index 9aed24e989..92ca2afc36 100644 --- a/docs/fr/docs/tutorial/body-multiple-params.md +++ b/docs/fr/docs/tutorial/body-multiple-params.md @@ -2,23 +2,23 @@ Maintenant que nous avons vu comment utiliser `Path` et `Query`, voyons des usages plus avancรฉs des dรฉclarations de paramรจtres du corps de la requรชte. -## Mรฉlanger les paramรจtres `Path`, `Query` et body { #mix-path-query-and-body-parameters } +## Mรฉlanger les paramรจtres `Path`, `Query` et du corps de la requรชte { #mix-path-query-and-body-parameters } -Tout d'abord, sachez que vous pouvez mรฉlanger librement les dรฉclarations des paramรจtres `Path`, `Query` et du body, **FastAPI** saura quoi faire. +Tout d'abord, sachez que vous pouvez mรฉlanger librement les dรฉclarations des paramรจtres `Path`, `Query` et du corps de la requรชte, **FastAPI** saura quoi faire. -Et vous pouvez รฉgalement dรฉclarer des paramรจtres du body comme รฉtant optionnels, en leur assignant une valeur par dรฉfaut ร  `None` : +Et vous pouvez รฉgalement dรฉclarer des paramรจtres du corps de la requรชte comme รฉtant optionnels, en leur assignant une valeur par dรฉfaut ร  `None` : {* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} /// note | Remarque -Notez que, dans ce cas, l'รฉlรฉment `item` rรฉcupรฉrรฉ depuis le body est optionnel. Comme sa valeur par dรฉfaut est `None`. +Notez que, dans ce cas, l'รฉlรฉment `item` rรฉcupรฉrรฉ depuis le corps de la requรชte est optionnel. Comme sa valeur par dรฉfaut est `None`. /// -## Paramรจtres multiples du body { #multiple-body-parameters } +## Paramรจtres multiples du corps de la requรชte { #multiple-body-parameters } -Dans l'exemple prรฉcรฉdent, les chemins d'accรจs attendraient un body JSON avec les attributs d'un `Item`, par exemple : +Dans l'exemple prรฉcรฉdent, les chemins d'accรจs attendraient un corps de la requรชte JSON avec les attributs d'un `Item`, par exemple : ```JSON { @@ -29,13 +29,13 @@ Dans l'exemple prรฉcรฉdent, les chemins d'accรจs attendraient un body JSON avec } ``` -Mais vous pouvez รฉgalement dรฉclarer plusieurs paramรจtres provenant du body, par exemple `item` et `user` : +Mais vous pouvez รฉgalement dรฉclarer plusieurs paramรจtres provenant du corps de la requรชte, par exemple `item` et `user` : {* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} -Dans ce cas, **FastAPI** dรฉtectera qu'il y a plus d'un paramรจtre du body dans la fonction (il y a deux paramรจtres qui sont des modรจles Pydantic). +Dans ce cas, **FastAPI** dรฉtectera qu'il y a plus d'un paramรจtre du corps de la requรชte dans la fonction (il y a deux paramรจtres qui sont des modรจles Pydantic). -Il utilisera alors les noms des paramรจtres comme clรฉs (noms de champs) dans le body, et s'attendra ร  recevoir un body semblable ร  : +Il utilisera alors les noms des paramรจtres comme clรฉs (noms de champs) dans le corps de la requรชte, et s'attendra ร  recevoir un corps de la requรชte semblable ร  : ```JSON { @@ -54,7 +54,7 @@ Il utilisera alors les noms des paramรจtres comme clรฉs (noms de champs) dans le /// note | Remarque -Notez que, bien que `item` ait รฉtรฉ dรฉclarรฉ de la mรชme maniรจre qu'auparavant, il est dรฉsormais attendu ร  l'intรฉrieur du body sous la clรฉ `item`. +Notez que, bien que `item` ait รฉtรฉ dรฉclarรฉ de la mรชme maniรจre qu'auparavant, il est dรฉsormais attendu ร  l'intรฉrieur du corps de la requรชte sous la clรฉ `item`. /// @@ -62,19 +62,19 @@ Notez que, bien que `item` ait รฉtรฉ dรฉclarรฉ de la mรชme maniรจre qu'auparavan Il effectuera la validation des donnรฉes composรฉes, et les documentera ainsi pour le schรฉma OpenAPI et la documentation automatique. -## Valeurs singuliรจres dans le body { #singular-values-in-body } +## Valeurs singuliรจres dans le corps de la requรชte { #singular-values-in-body } De la mรชme faรงon qu'il existe `Query` et `Path` pour dรฉfinir des donnรฉes supplรฉmentaires pour les paramรจtres de requรชte et de chemin, **FastAPI** fournit un รฉquivalent `Body`. -Par exemple, en รฉtendant le modรจle prรฉcรฉdent, vous pourriez dรฉcider d'avoir une autre clรฉ `importance` dans le mรชme body, en plus de `item` et `user`. +Par exemple, en รฉtendant le modรจle prรฉcรฉdent, vous pourriez dรฉcider d'avoir une autre clรฉ `importance` dans le mรชme corps de la requรชte, en plus de `item` et `user`. Si vous le dรฉclarez tel quel, comme c'est une valeur singuliรจre, **FastAPI** supposera qu'il s'agit d'un paramรจtre de requรชte. -Mais vous pouvez indiquer ร  **FastAPI** de la traiter comme une autre clรฉ du body en utilisant `Body` : +Mais vous pouvez indiquer ร  **FastAPI** de la traiter comme une autre clรฉ du corps de la requรชte en utilisant `Body` : {* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} -Dans ce cas, **FastAPI** s'attendra ร  un body semblable ร  : +Dans ce cas, **FastAPI** s'attendra ร  un corps de la requรชte semblable ร  : ```JSON { @@ -94,9 +94,9 @@ Dans ce cas, **FastAPI** s'attendra ร  un body semblable ร  : Encore une fois, il convertira les types de donnรฉes, validera, documentera, etc. -## Paramรจtres multiples du body et paramรจtres de requรชte { #multiple-body-params-and-query } +## Paramรจtres multiples du corps de la requรชte et paramรจtres de requรชte { #multiple-body-params-and-query } -Bien entendu, vous pouvez รฉgalement dรฉclarer des paramรจtres de requรชte supplรฉmentaires quand vous en avez besoin, en plus de tout paramรจtre du body. +Bien entendu, vous pouvez รฉgalement dรฉclarer des paramรจtres de requรชte supplรฉmentaires quand vous en avez besoin, en plus de tout paramรจtre du corps de la requรชte. Comme, par dรฉfaut, les valeurs singuliรจres sont interprรฉtรฉes comme des paramรจtres de requรชte, vous n'avez pas besoin d'ajouter explicitement `Query`, vous pouvez simplement รฉcrire : @@ -120,13 +120,13 @@ Par exemple : /// -## Intรฉgrer un seul paramรจtre du body { #embed-a-single-body-parameter } +## Intรฉgrer un seul paramรจtre du corps de la requรชte { #embed-a-single-body-parameter } -Supposons que vous n'ayez qu'un seul paramรจtre `item` dans le body, provenant d'un modรจle Pydantic `Item`. +Supposons que vous n'ayez qu'un seul paramรจtre `item` dans le corps de la requรชte, provenant d'un modรจle Pydantic `Item`. Par dรฉfaut, **FastAPI** attendra alors son contenu directement. -Mais si vous voulez qu'il attende un JSON avec une clรฉ `item` contenant le contenu du modรจle, comme lorsqu'on dรฉclare des paramรจtres supplรฉmentaires du body, vous pouvez utiliser le paramรจtre spรฉcial `embed` de `Body` : +Mais si vous voulez qu'il attende un JSON avec une clรฉ `item` contenant le contenu du modรจle, comme lorsqu'on dรฉclare des paramรจtres supplรฉmentaires du corps de la requรชte, vous pouvez utiliser le paramรจtre spรฉcial `embed` de `Body` : ```Python item: Item = Body(embed=True) @@ -136,7 +136,7 @@ comme dans : {* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} -Dans ce cas **FastAPI** s'attendra ร  un body semblable ร  : +Dans ce cas **FastAPI** s'attendra ร  un corps de la requรชte semblable ร  : ```JSON hl_lines="2" { @@ -162,10 +162,10 @@ au lieu de : ## Rรฉcapitulatif { #recap } -Vous pouvez ajouter plusieurs paramรจtres du body ร  votre fonction de chemin d'accรจs, mรชme si une requรชte ne peut avoir qu'un seul body. +Vous pouvez ajouter plusieurs paramรจtres du corps de la requรชte ร  votre fonction de chemin d'accรจs, mรชme si une requรชte ne peut avoir qu'un seul corps de la requรชte. Mais **FastAPI** s'en chargera, vous fournira les bonnes donnรฉes dans votre fonction, et validera et documentera le schรฉma correct dans le chemin d'accรจs. -Vous pouvez รฉgalement dรฉclarer des valeurs singuliรจres ร  recevoir dans le body. +Vous pouvez รฉgalement dรฉclarer des valeurs singuliรจres ร  recevoir dans le corps de la requรชte. -Et vous pouvez indiquer ร  **FastAPI** d'intรฉgrer le body sous une clรฉ mรชme lorsqu'un seul paramรจtre est dรฉclarรฉ. +Et vous pouvez indiquer ร  **FastAPI** d'intรฉgrer le corps de la requรชte sous une clรฉ mรชme lorsqu'un seul paramรจtre est dรฉclarรฉ. From 512c3ad88c8f03a03154df317c65aa0ca4f1f78d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 17:24:56 +0000 Subject: [PATCH 159/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4ba0491a53..75e0a5f562 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for fr (outdated pages). PR [#14839](https://github.com/fastapi/fastapi/pull/14839) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (outdated and missing). PR [#14838](https://github.com/fastapi/fastapi/pull/14838) by [@YuriiMotov](https://github.com/YuriiMotov). ### Internal From 3c49346238643287780d9f0d673f88b0d02df109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 10:01:05 -0800 Subject: [PATCH 160/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20interna?= =?UTF-8?q?ls,=20cleanup=20unneeded=20Pydantic=20v1=20specific=20logic=20(?= =?UTF-8?q?#14856)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/__init__.py | 1 - fastapi/_compat/shared.py | 1 - fastapi/_compat/v2.py | 10 ++-------- fastapi/routing.py | 15 +-------------- fastapi/utils.py | 16 ---------------- 5 files changed, 3 insertions(+), 40 deletions(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 3dfaf9b712..b7701bd1a1 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -1,4 +1,3 @@ -from .shared import PYDANTIC_V2 as PYDANTIC_V2 from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1 from .shared import field_annotation_is_scalar as field_annotation_is_scalar diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py index 68b9bbdf1e..fdda481b86 100644 --- a/fastapi/_compat/shared.py +++ b/fastapi/_compat/shared.py @@ -28,7 +28,6 @@ else: ) # pyright: ignore[reportAttributeAccessIssue] PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2]) -PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2 sequence_annotation_to_type = { diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index dae78a32e0..6c2eec58b5 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -500,14 +500,8 @@ def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap: - all_flat_models: TypeModelSet = set() - - v2_model_fields = [field for field in fields if isinstance(field, ModelField)] - v2_flat_models = get_flat_models_from_fields(v2_model_fields, known_models=set()) - all_flat_models = all_flat_models.union(v2_flat_models) - - model_name_map = get_model_name_map(all_flat_models) - return model_name_map + flat_models = get_flat_models_from_fields(fields, known_models=set()) + return get_model_name_map(flat_models) def get_flat_models_from_model( diff --git a/fastapi/routing.py b/fastapi/routing.py index c95f624bdf..b8d1f76248 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -59,7 +59,6 @@ from fastapi.exceptions import ( ) from fastapi.types import DecoratedCallable, IncEx from fastapi.utils import ( - create_cloned_field, create_model_field, generate_unique_id, get_value_or_default, @@ -652,20 +651,8 @@ class APIRoute(routing.Route): type_=self.response_model, mode="serialization", ) - # Create a clone of the field, so that a Pydantic submodel is not returned - # as is just because it's an instance of a subclass of a more limited class - # e.g. UserInDB (containing hashed_password) could be a subclass of User - # that doesn't have the hashed_password. But because it's a subclass, it - # would pass the validation and be returned as is. - # By being a new field, no inheritance will be passed as is. A new model - # will always be created. - # TODO: remove when deprecating Pydantic v1 - self.secure_cloned_response_field: Optional[ModelField] = ( - create_cloned_field(self.response_field) - ) else: self.response_field = None # type: ignore - self.secure_cloned_response_field = None self.dependencies = list(dependencies or []) self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") # if a "form feed" character (page break) is found in the description text, @@ -720,7 +707,7 @@ class APIRoute(routing.Route): body_field=self.body_field, status_code=self.status_code, response_class=self.response_class, - response_field=self.secure_cloned_response_field, + response_field=self.response_field, response_model_include=self.response_model_include, response_model_exclude=self.response_model_exclude, response_model_by_alias=self.response_model_by_alias, diff --git a/fastapi/utils.py b/fastapi/utils.py index 1c3a0881f7..da11fe2c77 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -1,13 +1,11 @@ import re import warnings -from collections.abc import MutableMapping from typing import ( TYPE_CHECKING, Any, Optional, Union, ) -from weakref import WeakKeyDictionary import fastapi from fastapi._compat import ( @@ -21,7 +19,6 @@ from fastapi._compat import ( ) from fastapi.datastructures import DefaultPlaceholder, DefaultType from fastapi.exceptions import FastAPIDeprecationWarning, PydanticV1NotSupportedError -from pydantic import BaseModel from pydantic.fields import FieldInfo from typing_extensions import Literal @@ -30,11 +27,6 @@ from ._compat import v2 if TYPE_CHECKING: # pragma: nocover from .routing import APIRoute -# Cache for `create_cloned_field` -_CLONED_TYPES_CACHE: MutableMapping[type[BaseModel], type[BaseModel]] = ( - WeakKeyDictionary() -) - def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: if status_code is None: @@ -97,14 +89,6 @@ def create_model_field( ) from None -def create_cloned_field( - field: ModelField, - *, - cloned_types: Optional[MutableMapping[type[BaseModel], type[BaseModel]]] = None, -) -> ModelField: - return field - - def generate_operation_id_for_path( *, name: str, path: str, method: str ) -> str: # pragma: nocover From ac8362c447b94247e9f7268c3d1e2807818647ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 18:01:30 +0000 Subject: [PATCH 161/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 75e0a5f562..d442ef9a19 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* โ™ป๏ธ Refactor internals, cleanup unneeded Pydantic v1 specific logic. PR [#14856](https://github.com/fastapi/fastapi/pull/14856) by [@tiangolo](https://github.com/tiangolo). + ### Translations * ๐ŸŒ Update translations for fr (outdated pages). PR [#14839](https://github.com/fastapi/fastapi/pull/14839) by [@YuriiMotov](https://github.com/YuriiMotov). From cf55bade7ea6e4bf85a167e8aed1c6167e7a4196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 6 Feb 2026 11:04:24 -0800 Subject: [PATCH 162/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20interna?= =?UTF-8?q?ls,=20remove=20Pydantic=20v1=20only=20logic,=20no=20longer=20ne?= =?UTF-8?q?eded=20(#14857)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/__init__.py | 1 - fastapi/_compat/v2.py | 107 ++++------------------------------ fastapi/dependencies/utils.py | 8 +-- fastapi/openapi/utils.py | 8 ++- fastapi/routing.py | 7 +-- 5 files changed, 19 insertions(+), 112 deletions(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index b7701bd1a1..22bc28dec3 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -25,7 +25,6 @@ from .v2 import copy_field_info as copy_field_info from .v2 import create_body_model as create_body_model from .v2 import evaluate_forwardref as evaluate_forwardref from .v2 import get_cached_model_fields as get_cached_model_fields -from .v2 import get_compat_model_name_map as get_compat_model_name_map from .v2 import get_definitions as get_definitions from .v2 import get_missing_field_error as get_missing_field_error from .v2 import get_schema_from_model_field as get_schema_from_model_field diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 6c2eec58b5..57b3d94ffc 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -1,7 +1,7 @@ import re import warnings from collections.abc import Sequence -from copy import copy, deepcopy +from copy import copy from dataclasses import dataclass, is_dataclass from enum import Enum from functools import lru_cache @@ -169,11 +169,11 @@ class ModelField: values: dict[str, Any] = {}, # noqa: B006 *, loc: tuple[Union[int, str], ...] = (), - ) -> tuple[Any, Union[list[dict[str, Any]], None]]: + ) -> tuple[Any, list[dict[str, Any]]]: try: return ( self._type_adapter.validate_python(value, from_attributes=True), - None, + [], ) except ValidationError as exc: return None, _regenerate_error_with_loc( @@ -305,94 +305,12 @@ def get_definitions( if "description" in item_def: item_description = cast(str, item_def["description"]).split("\f")[0] item_def["description"] = item_description - new_mapping, new_definitions = _remap_definitions_and_field_mappings( - model_name_map=model_name_map, - definitions=definitions, # type: ignore[arg-type] - field_mapping=field_mapping, - ) - return new_mapping, new_definitions - - -def _replace_refs( - *, - schema: dict[str, Any], - old_name_to_new_name_map: dict[str, str], -) -> dict[str, Any]: - new_schema = deepcopy(schema) - for key, value in new_schema.items(): - if key == "$ref": - value = schema["$ref"] - if isinstance(value, str): - ref_name = schema["$ref"].split("/")[-1] - if ref_name in old_name_to_new_name_map: - new_name = old_name_to_new_name_map[ref_name] - new_schema["$ref"] = REF_TEMPLATE.format(model=new_name) - continue - if isinstance(value, dict): - new_schema[key] = _replace_refs( - schema=value, - old_name_to_new_name_map=old_name_to_new_name_map, - ) - elif isinstance(value, list): - new_value = [] - for item in value: - if isinstance(item, dict): - new_item = _replace_refs( - schema=item, - old_name_to_new_name_map=old_name_to_new_name_map, - ) - new_value.append(new_item) - - else: - new_value.append(item) - new_schema[key] = new_value - return new_schema - - -def _remap_definitions_and_field_mappings( - *, - model_name_map: ModelNameMap, - definitions: dict[str, Any], - field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue - ], -) -> tuple[ - dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - dict[str, Any], -]: - old_name_to_new_name_map = {} - for field_key, schema in field_mapping.items(): - model = field_key[0].type_ - if model not in model_name_map or "$ref" not in schema: - continue - new_name = model_name_map[model] - old_name = schema["$ref"].split("/")[-1] - if old_name in {f"{new_name}-Input", f"{new_name}-Output"}: - continue - old_name_to_new_name_map[old_name] = new_name - - new_field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue - ] = {} - for field_key, schema in field_mapping.items(): - new_schema = _replace_refs( - schema=schema, - old_name_to_new_name_map=old_name_to_new_name_map, - ) - new_field_mapping[field_key] = new_schema - - new_definitions = {} - for key, value in definitions.items(): - if key in old_name_to_new_name_map: - new_key = old_name_to_new_name_map[key] - else: - new_key = key - new_value = _replace_refs( - schema=value, - old_name_to_new_name_map=old_name_to_new_name_map, - ) - new_definitions[new_key] = new_value - return new_field_mapping, new_definitions + # definitions: dict[DefsRef, dict[str, Any]] + # but mypy complains about general str in other places that are not declared as + # DefsRef, although DefsRef is just str: + # DefsRef = NewType('DefsRef', str) + # So, a cast to simplify the types here + return field_mapping, cast(dict[str, dict[str, Any]], definitions) def is_scalar_field(field: ModelField) -> bool: @@ -441,7 +359,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index] -def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]: +def get_missing_field_error(loc: tuple[Union[int, str], ...]) -> dict[str, Any]: error = ValidationError.from_exception_data( "Field required", [{"type": "missing", "loc": loc, "input": {}}] ).errors(include_url=False)[0] @@ -499,11 +417,6 @@ def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str return {v: k for k, v in name_model_map.items()} -def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap: - flat_models = get_flat_models_from_fields(fields, known_models=set()) - return get_model_name_map(flat_models) - - def get_flat_models_from_model( model: type["BaseModel"], known_models: Union[TypeModelSet, None] = None ) -> TypeModelSet: diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index b8f7f948c6..dd42371ecc 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -21,7 +21,6 @@ from fastapi._compat import ( ModelField, RequiredParam, Undefined, - _regenerate_error_with_loc, copy_field_info, create_body_model, evaluate_forwardref, @@ -718,12 +717,7 @@ def _validate_value_with_model_field( return None, [get_missing_field_error(loc=loc)] else: return deepcopy(field.default), [] - v_, errors_ = field.validate(value, values, loc=loc) - if isinstance(errors_, list): - new_errors = _regenerate_error_with_loc(errors=errors_, loc_prefix=()) - return None, new_errors - else: - return v_, [] + return field.validate(value, values, loc=loc) def _is_json_field(field: ModelField) -> bool: diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 5736af3b78..c9b006a718 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -9,11 +9,14 @@ from fastapi import routing from fastapi._compat import ( ModelField, Undefined, - get_compat_model_name_map, get_definitions, get_schema_from_model_field, lenient_issubclass, ) +from fastapi._compat.v2 import ( + get_flat_models_from_fields, + get_model_name_map, +) from fastapi.datastructures import DefaultPlaceholder from fastapi.dependencies.models import Dependant from fastapi.dependencies.utils import ( @@ -512,7 +515,8 @@ def get_openapi( webhook_paths: dict[str, dict[str, Any]] = {} operation_ids: set[str] = set() all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or [])) - model_name_map = get_compat_model_name_map(all_fields) + flat_models = get_flat_models_from_fields(all_fields, known_models=set()) + model_name_map = get_model_name_map(flat_models) field_mapping, definitions = get_definitions( fields=all_fields, model_name_map=model_name_map, diff --git a/fastapi/routing.py b/fastapi/routing.py index b8d1f76248..fe8d886093 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -277,15 +277,12 @@ async def serialize_response( endpoint_ctx: Optional[EndpointContext] = None, ) -> Any: if field: - errors = [] if is_coroutine: - value, errors_ = field.validate(response_content, {}, loc=("response",)) + value, errors = field.validate(response_content, {}, loc=("response",)) else: - value, errors_ = await run_in_threadpool( + value, errors = await run_in_threadpool( field.validate, response_content, {}, loc=("response",) ) - if isinstance(errors_, list): - errors.extend(errors_) if errors: ctx = endpoint_ctx or EndpointContext() raise ResponseValidationError( From cc6ced6345f6be18038437b73866294697294f3e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Feb 2026 19:04:48 +0000 Subject: [PATCH 163/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d442ef9a19..b9982e8c9c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Refactors +* โ™ป๏ธ Simplify internals, remove Pydantic v1 only logic, no longer needed. PR [#14857](https://github.com/fastapi/fastapi/pull/14857) by [@tiangolo](https://github.com/tiangolo). * โ™ป๏ธ Refactor internals, cleanup unneeded Pydantic v1 specific logic. PR [#14856](https://github.com/fastapi/fastapi/pull/14856) by [@tiangolo](https://github.com/tiangolo). ### Translations From d59fbc3494940c9afe675cc89271bd0fa744574f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Feb 2026 00:08:07 -0800 Subject: [PATCH 164/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20interna?= =?UTF-8?q?ls,=20simplify=20Pydantic=20v2/v1=20utils,=20`create=5Fmodel=5F?= =?UTF-8?q?field`,=20better=20types=20for=20`lenient=5Fissubclass`=20(#148?= =?UTF-8?q?60)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/__init__.py | 7 ++---- fastapi/_compat/shared.py | 37 ++++++++++++++++++++------------ fastapi/_compat/v2.py | 40 +++++++++++------------------------ fastapi/dependencies/utils.py | 8 +------ fastapi/openapi/models.py | 5 +---- fastapi/openapi/utils.py | 6 ++---- fastapi/routing.py | 12 ----------- fastapi/utils.py | 12 +---------- 8 files changed, 43 insertions(+), 84 deletions(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 22bc28dec3..62681696ed 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -1,7 +1,6 @@ from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1 from .shared import field_annotation_is_scalar as field_annotation_is_scalar -from .shared import is_pydantic_v1_model_class as is_pydantic_v1_model_class from .shared import is_pydantic_v1_model_instance as is_pydantic_v1_model_instance from .shared import ( is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation, @@ -12,21 +11,19 @@ from .shared import ( from .shared import lenient_issubclass as lenient_issubclass from .shared import sequence_types as sequence_types from .shared import value_is_sequence as value_is_sequence -from .v2 import BaseConfig as BaseConfig from .v2 import ModelField as ModelField from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError from .v2 import RequiredParam as RequiredParam from .v2 import Undefined as Undefined -from .v2 import UndefinedType as UndefinedType from .v2 import Url as Url -from .v2 import Validator as Validator -from .v2 import _regenerate_error_with_loc as _regenerate_error_with_loc from .v2 import copy_field_info as copy_field_info from .v2 import create_body_model as create_body_model from .v2 import evaluate_forwardref as evaluate_forwardref from .v2 import get_cached_model_fields as get_cached_model_fields from .v2 import get_definitions as get_definitions +from .v2 import get_flat_models_from_fields as get_flat_models_from_fields from .v2 import get_missing_field_error as get_missing_field_error +from .v2 import get_model_name_map as get_model_name_map from .v2 import get_schema_from_model_field as get_schema_from_model_field from .v2 import is_bytes_field as is_bytes_field from .v2 import is_bytes_sequence_field as is_bytes_sequence_field diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py index fdda481b86..c009da8fdc 100644 --- a/fastapi/_compat/shared.py +++ b/fastapi/_compat/shared.py @@ -8,6 +8,7 @@ from dataclasses import is_dataclass from typing import ( Annotated, Any, + TypeVar, Union, ) @@ -15,7 +16,9 @@ from fastapi.types import UnionType from pydantic import BaseModel from pydantic.version import VERSION as PYDANTIC_VERSION from starlette.datastructures import UploadFile -from typing_extensions import get_args, get_origin +from typing_extensions import TypeGuard, get_args, get_origin + +_T = TypeVar("_T") # Copy from Pydantic: pydantic/_internal/_typing_extra.py if sys.version_info < (3, 10): @@ -39,15 +42,13 @@ sequence_annotation_to_type = { deque: deque, } -sequence_types = tuple(sequence_annotation_to_type.keys()) - -Url: type[Any] +sequence_types: tuple[type[Any], ...] = tuple(sequence_annotation_to_type.keys()) -# Copy of Pydantic: pydantic/_internal/_utils.py +# Copy of Pydantic: pydantic/_internal/_utils.py with added TypeGuard def lenient_issubclass( - cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None] -) -> bool: + cls: Any, class_or_tuple: Union[type[_T], tuple[type[_T], ...], None] +) -> TypeGuard[type[_T]]: try: return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] except TypeError: # pragma: no cover @@ -177,16 +178,26 @@ def is_uploadfile_sequence_annotation(annotation: Any) -> bool: def is_pydantic_v1_model_instance(obj: Any) -> bool: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - from pydantic import v1 + # TODO: remove this function once the required version of Pydantic fully + # removes pydantic.v1 + try: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + from pydantic import v1 + except ImportError: # pragma: no cover + return False return isinstance(obj, v1.BaseModel) def is_pydantic_v1_model_class(cls: Any) -> bool: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - from pydantic import v1 + # TODO: remove this function once the required version of Pydantic fully + # removes pydantic.v1 + try: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + from pydantic import v1 + except ImportError: # pragma: no cover + return False return lenient_issubclass(cls, v1.BaseModel) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 57b3d94ffc..efc20fa58b 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -12,7 +12,7 @@ from typing import ( cast, ) -from fastapi._compat import shared +from fastapi._compat import lenient_issubclass, shared from fastapi.openapi.constants import REF_TEMPLATE from fastapi.types import IncEx, ModelNameMap, UnionType from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model @@ -23,29 +23,20 @@ from pydantic._internal._schema_generation_shared import ( # type: ignore[attr- GetJsonSchemaHandler as GetJsonSchemaHandler, ) from pydantic._internal._typing_extra import eval_type_lenient -from pydantic._internal._utils import lenient_issubclass as lenient_issubclass from pydantic.fields import FieldInfo as FieldInfo from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue from pydantic_core import CoreSchema as CoreSchema -from pydantic_core import PydanticUndefined, PydanticUndefinedType +from pydantic_core import PydanticUndefined from pydantic_core import Url as Url +from pydantic_core.core_schema import ( + with_info_plain_validator_function as with_info_plain_validator_function, +) from typing_extensions import Literal, get_args, get_origin -try: - from pydantic_core.core_schema import ( - with_info_plain_validator_function as with_info_plain_validator_function, - ) -except ImportError: # pragma: no cover - from pydantic_core.core_schema import ( - general_plain_validator_function as with_info_plain_validator_function, # noqa: F401 - ) - RequiredParam = PydanticUndefined Undefined = PydanticUndefined -UndefinedType = PydanticUndefinedType evaluate_forwardref = eval_type_lenient -Validator = Any # TODO: remove when dropping support for Pydantic < v2.12.3 _Attrs = { @@ -87,14 +78,6 @@ def asdict(field_info: FieldInfo) -> dict[str, Any]: } -class BaseConfig: - pass - - -class ErrorWrapper(Exception): - pass - - @dataclass class ModelField: field_info: FieldInfo @@ -143,8 +126,8 @@ class ModelField: warnings.simplefilter( "ignore", category=UnsupportedFieldAttributeWarning ) - # TODO: remove after dropping support for Python 3.8 and - # setting the min Pydantic to v2.12.3 that adds asdict() + # TODO: remove after setting the min Pydantic to v2.12.3 + # that adds asdict(), and use self.field_info.asdict() instead field_dict = asdict(self.field_info) annotated_args = ( field_dict["annotation"], @@ -432,10 +415,11 @@ def get_flat_models_from_annotation( origin = get_origin(annotation) if origin is not None: for arg in get_args(annotation): - if lenient_issubclass(arg, (BaseModel, Enum)) and arg not in known_models: - known_models.add(arg) - if lenient_issubclass(arg, BaseModel): - get_flat_models_from_model(arg, known_models=known_models) + if lenient_issubclass(arg, (BaseModel, Enum)): + if arg not in known_models: + known_models.add(arg) # type: ignore[arg-type] + if lenient_issubclass(arg, BaseModel): + get_flat_models_from_model(arg, known_models=known_models) else: get_flat_models_from_annotation(arg, known_models=known_models) return known_models diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index dd42371ecc..1e334c4296 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -512,7 +512,6 @@ def analyze_param( type_=use_annotation_from_field_info, default=field_info.default, alias=alias, - required=field_info.default in (RequiredParam, Undefined), field_info=field_info, ) if is_path_param: @@ -523,11 +522,7 @@ def analyze_param( assert ( is_scalar_field(field) or is_scalar_sequence_field(field) - or ( - lenient_issubclass(field.type_, BaseModel) - # For Pydantic v1 - and getattr(field, "shape", 1) == 1 - ) + or lenient_issubclass(field.type_, BaseModel) ), f"Query parameter {param_name!r} must be one of the supported types" return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) @@ -1021,7 +1016,6 @@ def get_body_field( final_field = create_model_field( name="body", type_=BodyModel, - required=required, alias="body", field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), ) diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index ac6a6d52c3..0959906390 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -143,10 +143,7 @@ class Schema(BaseModelWithConfig): else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") dependentSchemas: Optional[dict[str, "SchemaOrBool"]] = None prefixItems: Optional[list["SchemaOrBool"]] = None - # TODO: uncomment and remove below when deprecating Pydantic v1 - # It generates a list of schemas for tuples, before prefixItems was available - # items: Optional["SchemaOrBool"] = None - items: Optional[Union["SchemaOrBool", list["SchemaOrBool"]]] = None + items: Optional["SchemaOrBool"] = None contains: Optional["SchemaOrBool"] = None properties: Optional[dict[str, "SchemaOrBool"]] = None patternProperties: Optional[dict[str, "SchemaOrBool"]] = None diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index c9b006a718..9cff359816 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -10,12 +10,10 @@ from fastapi._compat import ( ModelField, Undefined, get_definitions, - get_schema_from_model_field, - lenient_issubclass, -) -from fastapi._compat.v2 import ( get_flat_models_from_fields, get_model_name_map, + get_schema_from_model_field, + lenient_issubclass, ) from fastapi.datastructures import DefaultPlaceholder from fastapi.dependencies.models import Dependant diff --git a/fastapi/routing.py b/fastapi/routing.py index fe8d886093..0b4d28873c 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -34,7 +34,6 @@ from fastapi import params from fastapi._compat import ( ModelField, Undefined, - annotation_is_pydantic_v1, lenient_issubclass, ) from fastapi.datastructures import Default, DefaultPlaceholder @@ -52,7 +51,6 @@ from fastapi.encoders import jsonable_encoder from fastapi.exceptions import ( EndpointContext, FastAPIError, - PydanticV1NotSupportedError, RequestValidationError, ResponseValidationError, WebSocketRequestValidationError, @@ -638,11 +636,6 @@ class APIRoute(routing.Route): f"Status code {status_code} must not have a response body" ) response_name = "Response_" + self.unique_id - if annotation_is_pydantic_v1(self.response_model): - raise PydanticV1NotSupportedError( - "pydantic.v1 models are no longer supported by FastAPI." - f" Please update the response model {self.response_model!r}." - ) self.response_field = create_model_field( name=response_name, type_=self.response_model, @@ -664,11 +657,6 @@ class APIRoute(routing.Route): f"Status code {additional_status_code} must not have a response body" ) response_name = f"Response_{additional_status_code}_{self.unique_id}" - if annotation_is_pydantic_v1(model): - raise PydanticV1NotSupportedError( - "pydantic.v1 models are no longer supported by FastAPI." - f" In responses={{}}, please update {model}." - ) response_field = create_model_field( name=response_name, type_=model, mode="serialization" ) diff --git a/fastapi/utils.py b/fastapi/utils.py index da11fe2c77..28c7cdfccb 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -9,12 +9,9 @@ from typing import ( import fastapi from fastapi._compat import ( - BaseConfig, ModelField, PydanticSchemaGenerationError, Undefined, - UndefinedType, - Validator, annotation_is_pydantic_v1, ) from fastapi.datastructures import DefaultPlaceholder, DefaultType @@ -63,26 +60,19 @@ _invalid_args_message = ( def create_model_field( name: str, type_: Any, - class_validators: Optional[dict[str, Validator]] = None, default: Optional[Any] = Undefined, - required: Union[bool, UndefinedType] = Undefined, - model_config: Union[type[BaseConfig], None] = None, field_info: Optional[FieldInfo] = None, alias: Optional[str] = None, mode: Literal["validation", "serialization"] = "validation", - version: Literal["1", "auto"] = "auto", ) -> ModelField: if annotation_is_pydantic_v1(type_): raise PydanticV1NotSupportedError( "pydantic.v1 models are no longer supported by FastAPI." f" Please update the response model {type_!r}." ) - class_validators = class_validators or {} - field_info = field_info or FieldInfo(annotation=type_, default=default, alias=alias) - kwargs = {"mode": mode, "name": name, "field_info": field_info} try: - return v2.ModelField(**kwargs) # type: ignore[arg-type] + return v2.ModelField(mode=mode, name=name, field_info=field_info) except PydanticSchemaGenerationError: raise fastapi.exceptions.FastAPIError( _invalid_args_message.format(type_=type_) From 58cdfc7f4b1ad22a4e6450319affb42d185775d9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 7 Feb 2026 08:08:31 +0000 Subject: [PATCH 165/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b9982e8c9c..1c640aba8d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Refactors +* โ™ป๏ธ Refactor internals, simplify Pydantic v2/v1 utils, `create_model_field`, better types for `lenient_issubclass`. PR [#14860](https://github.com/fastapi/fastapi/pull/14860) by [@tiangolo](https://github.com/tiangolo). * โ™ป๏ธ Simplify internals, remove Pydantic v1 only logic, no longer needed. PR [#14857](https://github.com/fastapi/fastapi/pull/14857) by [@tiangolo](https://github.com/tiangolo). * โ™ป๏ธ Refactor internals, cleanup unneeded Pydantic v1 specific logic. PR [#14856](https://github.com/fastapi/fastapi/pull/14856) by [@tiangolo](https://github.com/tiangolo). From 8eac94bd91c212a2aab676acd7f8e94cd3097dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Feb 2026 09:12:54 +0100 Subject: [PATCH 166/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1c640aba8d..08cd77aeba 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.4 + ### Refactors * โ™ป๏ธ Refactor internals, simplify Pydantic v2/v1 utils, `create_model_field`, better types for `lenient_issubclass`. PR [#14860](https://github.com/fastapi/fastapi/pull/14860) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index b23e3c42fb..580919a81c 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.3" +__version__ = "0.128.4" from starlette import status as status From 2e7d3754cd1c85feb4dfa14ee29a509133cfc203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 7 Feb 2026 00:34:32 -0800 Subject: [PATCH 167/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20and=20s?= =?UTF-8?q?implify=20Pydantic=20v2=20(and=20v1)=20compatibility=20internal?= =?UTF-8?q?=20utils=20(#14862)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/__init__.py | 12 ++++++--- fastapi/_compat/v2.py | 30 +++------------------ fastapi/dependencies/utils.py | 51 ++++++++++++++++++++--------------- fastapi/openapi/utils.py | 6 ++--- 4 files changed, 44 insertions(+), 55 deletions(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 62681696ed..4581c38c88 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -1,6 +1,14 @@ from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1 from .shared import field_annotation_is_scalar as field_annotation_is_scalar +from .shared import ( + field_annotation_is_scalar_sequence as field_annotation_is_scalar_sequence, +) +from .shared import field_annotation_is_sequence as field_annotation_is_sequence +from .shared import ( + is_bytes_or_nonable_bytes_annotation as is_bytes_or_nonable_bytes_annotation, +) +from .shared import is_bytes_sequence_annotation as is_bytes_sequence_annotation from .shared import is_pydantic_v1_model_instance as is_pydantic_v1_model_instance from .shared import ( is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation, @@ -25,11 +33,7 @@ from .v2 import get_flat_models_from_fields as get_flat_models_from_fields from .v2 import get_missing_field_error as get_missing_field_error from .v2 import get_model_name_map as get_model_name_map from .v2 import get_schema_from_model_field as get_schema_from_model_field -from .v2 import is_bytes_field as is_bytes_field -from .v2 import is_bytes_sequence_field as is_bytes_sequence_field from .v2 import is_scalar_field as is_scalar_field -from .v2 import is_scalar_sequence_field as is_scalar_sequence_field -from .v2 import is_sequence_field as is_sequence_field from .v2 import serialize_sequence_value as serialize_sequence_value from .v2 import ( with_info_plain_validator_function as with_info_plain_validator_function, diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index efc20fa58b..87b9fb47fa 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -102,18 +102,10 @@ class ModelField: sa = self.field_info.serialization_alias return sa or None - @property - def required(self) -> bool: - return self.field_info.is_required() - @property def default(self) -> Any: return self.get_default() - @property - def type_(self) -> Any: - return self.field_info.annotation - def __post_init__(self) -> None: with warnings.catch_warnings(): # Pydantic >= 2.12.0 warns about field specific metadata that is unused @@ -267,9 +259,9 @@ def get_definitions( for model in flat_serialization_models ] flat_model_fields = flat_validation_model_fields + flat_serialization_model_fields - input_types = {f.type_ for f in fields} + input_types = {f.field_info.annotation for f in fields} unique_flat_model_fields = { - f for f in flat_model_fields if f.type_ not in input_types + f for f in flat_model_fields if f.field_info.annotation not in input_types } inputs = [ ( @@ -304,22 +296,6 @@ def is_scalar_field(field: ModelField) -> bool: ) and not isinstance(field.field_info, params.Body) -def is_sequence_field(field: ModelField) -> bool: - return shared.field_annotation_is_sequence(field.field_info.annotation) - - -def is_scalar_sequence_field(field: ModelField) -> bool: - return shared.field_annotation_is_scalar_sequence(field.field_info.annotation) - - -def is_bytes_field(field: ModelField) -> bool: - return shared.is_bytes_or_nonable_bytes_annotation(field.type_) - - -def is_bytes_sequence_field(field: ModelField) -> bool: - return shared.is_bytes_sequence_annotation(field.type_) - - def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: cls = type(field_info) merged_field_info = cls.from_annotation(annotation) @@ -428,7 +404,7 @@ def get_flat_models_from_annotation( def get_flat_models_from_field( field: ModelField, known_models: TypeModelSet ) -> TypeModelSet: - field_type = field.type_ + field_type = field.field_info.annotation if lenient_issubclass(field_type, BaseModel): if field_type in known_models: return known_models diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 1e334c4296..80f9c76e90 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -25,13 +25,13 @@ from fastapi._compat import ( create_body_model, evaluate_forwardref, field_annotation_is_scalar, + field_annotation_is_scalar_sequence, + field_annotation_is_sequence, get_cached_model_fields, get_missing_field_error, - is_bytes_field, - is_bytes_sequence_field, + is_bytes_or_nonable_bytes_annotation, + is_bytes_sequence_annotation, is_scalar_field, - is_scalar_sequence_field, - is_sequence_field, is_uploadfile_or_nonable_uploadfile_annotation, is_uploadfile_sequence_annotation, lenient_issubclass, @@ -182,8 +182,10 @@ def _get_flat_fields_from_params(fields: list[ModelField]) -> list[ModelField]: if not fields: return fields first_field = fields[0] - if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel): - fields_to_extract = get_cached_model_fields(first_field.type_) + if len(fields) == 1 and lenient_issubclass( + first_field.field_info.annotation, BaseModel + ): + fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) return fields_to_extract return fields @@ -521,8 +523,8 @@ def analyze_param( elif isinstance(field_info, params.Query): assert ( is_scalar_field(field) - or is_scalar_sequence_field(field) - or lenient_issubclass(field.type_, BaseModel) + or field_annotation_is_scalar_sequence(field.field_info.annotation) + or lenient_issubclass(field.field_info.annotation, BaseModel) ), f"Query parameter {param_name!r} must be one of the supported types" return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) @@ -708,7 +710,7 @@ def _validate_value_with_model_field( *, field: ModelField, value: Any, values: dict[str, Any], loc: tuple[str, ...] ) -> tuple[Any, list[Any]]: if value is None: - if field.required: + if field.field_info.is_required(): return None, [get_missing_field_error(loc=loc)] else: return deepcopy(field.default), [] @@ -725,7 +727,7 @@ def _get_multidict_value( alias = alias or get_validation_alias(field) if ( (not _is_json_field(field)) - and is_sequence_field(field) + and field_annotation_is_sequence(field.field_info.annotation) and isinstance(values, (ImmutableMultiDict, Headers)) ): value = values.getlist(alias) @@ -738,9 +740,12 @@ def _get_multidict_value( and isinstance(value, str) # For type checks and value == "" ) - or (is_sequence_field(field) and len(value) == 0) + or ( + field_annotation_is_sequence(field.field_info.annotation) + and len(value) == 0 + ) ): - if field.required: + if field.field_info.is_required(): return else: return deepcopy(field.default) @@ -761,8 +766,10 @@ def request_params_to_args( fields_to_extract = fields single_not_embedded_field = False default_convert_underscores = True - if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel): - fields_to_extract = get_cached_model_fields(first_field.type_) + if len(fields) == 1 and lenient_issubclass( + first_field.field_info.annotation, BaseModel + ): + fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) single_not_embedded_field = True # If headers are in a Pydantic model, the way to disable convert_underscores # would be with Header(convert_underscores=False) at the Pydantic model level @@ -866,8 +873,8 @@ def _should_embed_body_fields(fields: list[ModelField]) -> bool: # otherwise it has to be embedded, so that the key value pair can be extracted if ( isinstance(first_field.field_info, params.Form) - and not lenient_issubclass(first_field.type_, BaseModel) - and not is_union_of_base_models(first_field.type_) + and not lenient_issubclass(first_field.field_info.annotation, BaseModel) + and not is_union_of_base_models(first_field.field_info.annotation) ): return True return False @@ -884,12 +891,12 @@ async def _extract_form_body( field_info = field.field_info if ( isinstance(field_info, params.File) - and is_bytes_field(field) + and is_bytes_or_nonable_bytes_annotation(field.field_info.annotation) and isinstance(value, UploadFile) ): value = await value.read() elif ( - is_bytes_sequence_field(field) + is_bytes_sequence_annotation(field.field_info.annotation) and isinstance(field_info, params.File) and value_is_sequence(value) ): @@ -936,10 +943,10 @@ async def request_body_to_args( if ( single_not_embedded_field - and lenient_issubclass(first_field.type_, BaseModel) + and lenient_issubclass(first_field.field_info.annotation, BaseModel) and isinstance(received_body, FormData) ): - fields_to_extract = get_cached_model_fields(first_field.type_) + fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) if isinstance(received_body, FormData): body_to_process = await _extract_form_body(fields_to_extract, received_body) @@ -992,7 +999,9 @@ def get_body_field( BodyModel = create_body_model( fields=flat_dependant.body_params, model_name=model_name ) - required = any(True for f in flat_dependant.body_params if f.required) + required = any( + True for f in flat_dependant.body_params if f.field_info.is_required() + ) BodyFieldInfo_kwargs: dict[str, Any] = { "annotation": BodyModel, "alias": "body", diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 9cff359816..bcad0be75d 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -129,7 +129,7 @@ def _get_openapi_operation_parameters( default_convert_underscores = True if len(flat_dependant.header_params) == 1: first_field = flat_dependant.header_params[0] - if lenient_issubclass(first_field.type_, BaseModel): + if lenient_issubclass(first_field.field_info.annotation, BaseModel): default_convert_underscores = getattr( first_field.field_info, "convert_underscores", True ) @@ -161,7 +161,7 @@ def _get_openapi_operation_parameters( parameter = { "name": name, "in": param_type.value, - "required": param.required, + "required": param.field_info.is_required(), "schema": param_schema, } if field_info.description: @@ -198,7 +198,7 @@ def get_openapi_operation_request_body( ) field_info = cast(Body, body_field.field_info) request_media_type = field_info.media_type - required = body_field.required + required = body_field.field_info.is_required() request_body_oai: dict[str, Any] = {} if required: request_body_oai["required"] = required From c48539f4c60e3e63af34fded4d9eb0d27ac34eeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 7 Feb 2026 08:34:59 +0000 Subject: [PATCH 168/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 08cd77aeba..5d93b684af 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* โ™ป๏ธ Refactor and simplify Pydantic v2 (and v1) compatibility internal utils. PR [#14862](https://github.com/fastapi/fastapi/pull/14862) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.4 ### Refactors From 9f4ecf562cffd79a2d6bff0eb333df5669bd70e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 8 Feb 2026 02:18:38 -0800 Subject: [PATCH 169/367] =?UTF-8?q?=E2=9C=85=20Add=20inline=20snapshot=20t?= =?UTF-8?q?ests=20for=20OpenAPI=20before=20changes=20from=20Pydantic=20v2?= =?UTF-8?q?=20(#14864)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_additional_properties.py | 141 +- tests/test_additional_properties_bool.py | 141 +- tests/test_additional_response_extra.py | 37 +- ...tional_responses_custom_validationerror.py | 113 +- ...ional_responses_default_validationerror.py | 127 +- ...est_additional_responses_response_class.py | 129 +- tests/test_additional_responses_router.py | 167 +- ...itional_responses_union_duplicate_anyof.py | 141 +- tests/test_annotated.py | 307 +- tests/test_application.py | 2227 +-- tests/test_computed_fields.py | 107 +- tests/test_custom_route_class.py | 85 +- tests/test_dependency_duplicates.py | 247 +- tests/test_deprecated_openapi_prefix.py | 39 +- tests/test_duplicate_models_openapi.py | 85 +- tests/test_enforce_once_required_parameter.py | 156 +- tests/test_extra_routes.py | 453 +- tests/test_forms_single_param.py | 139 +- tests/test_generate_unique_id_function.py | 2490 +-- tests/test_generic_parameterless_depends.py | 61 +- tests/test_get_request_body.py | 141 +- .../test_include_router_defaults_overrides.py | 12753 ++++++++-------- tests/test_infer_param_optionality.py | 405 +- .../test_modules_same_name_body/test_main.py | 201 +- tests/test_multi_body_errors.py | 166 +- tests/test_multi_query_errors.py | 135 +- tests/test_openapi_examples.py | 485 +- .../test_openapi_query_parameter_extension.py | 157 +- tests/test_openapi_route_extensions.py | 39 +- ...t_openapi_separate_input_output_schemas.py | 366 +- tests/test_param_in_path_and_dependency.py | 128 +- tests/test_param_include_in_schema.py | 272 +- tests/test_put_no_body.py | 127 +- tests/test_regex_deprecated_params.py | 138 +- tests/test_repeated_dependency_schema.py | 155 +- tests/test_repeated_parameter_alias.py | 140 +- tests/test_reponse_set_reponse_code_empty.py | 121 +- ...test_request_body_parameters_media_type.py | 239 +- .../test_cookie/test_optional_str.py | 97 +- .../test_cookie/test_required_str.py | 73 +- .../test_header/test_list.py | 105 +- .../test_header/test_optional_list.py | 121 +- .../test_header/test_optional_str.py | 97 +- .../test_header/test_required_str.py | 73 +- .../test_path/test_required_str.py | 19 +- .../test_query/test_list.py | 105 +- .../test_query/test_optional_list.py | 121 +- .../test_query/test_optional_str.py | 97 +- .../test_query/test_required_str.py | 73 +- tests/test_response_by_alias.py | 359 +- tests/test_response_class_no_mediatype.py | 125 +- tests/test_response_code_no_body.py | 113 +- ...est_response_model_as_return_annotation.py | 1185 +- tests/test_response_model_sub_types.py | 193 +- tests/test_schema_extra_examples.py | 1041 +- tests/test_security_api_key_cookie.py | 49 +- ...est_security_api_key_cookie_description.py | 57 +- .../test_security_api_key_cookie_optional.py | 49 +- tests/test_security_api_key_header.py | 49 +- ...est_security_api_key_header_description.py | 57 +- .../test_security_api_key_header_optional.py | 49 +- tests/test_security_api_key_query.py | 49 +- ...test_security_api_key_query_description.py | 57 +- tests/test_security_api_key_query_optional.py | 49 +- tests/test_security_http_base.py | 45 +- tests/test_security_http_base_description.py | 55 +- tests/test_security_http_base_optional.py | 45 +- tests/test_security_http_basic_optional.py | 45 +- tests/test_security_http_basic_realm.py | 45 +- ...t_security_http_basic_realm_description.py | 55 +- tests/test_security_http_bearer.py | 45 +- .../test_security_http_bearer_description.py | 55 +- tests/test_security_http_bearer_optional.py | 45 +- tests/test_security_http_digest.py | 45 +- .../test_security_http_digest_description.py | 55 +- tests/test_security_http_digest_optional.py | 45 +- tests/test_security_oauth2.py | 215 +- ...curity_oauth2_authorization_code_bearer.py | 65 +- ...2_authorization_code_bearer_description.py | 67 +- tests/test_security_oauth2_optional.py | 215 +- ...st_security_oauth2_optional_description.py | 217 +- ...ecurity_oauth2_password_bearer_optional.py | 53 +- ...h2_password_bearer_optional_description.py | 55 +- tests/test_security_openid_connect.py | 53 +- ...est_security_openid_connect_description.py | 55 +- .../test_security_openid_connect_optional.py | 53 +- tests/test_starlette_exception.py | 227 +- tests/test_sub_callbacks.py | 351 +- tests/test_tuples.py | 315 +- .../test_tutorial001.py | 179 +- .../test_tutorial002.py | 165 +- .../test_tutorial003.py | 187 +- .../test_tutorial004.py | 171 +- .../test_behind_a_proxy/test_tutorial001.py | 39 +- .../test_behind_a_proxy/test_tutorial002.py | 39 +- .../test_bigger_applications/test_main.py | 601 +- .../test_body/test_tutorial001.py | 151 +- .../test_body/test_tutorial002.py | 151 +- .../test_body/test_tutorial003.py | 171 +- .../test_body/test_tutorial004.py | 187 +- .../test_body_fields/test_tutorial001.py | 193 +- .../test_tutorial001.py | 201 +- .../test_tutorial002.py | 273 +- .../test_tutorial003.py | 203 +- .../test_tutorial004.py | 225 +- .../test_tutorial005.py | 231 +- ...est_tutorial001_tutorial002_tutorial003.py | 191 +- .../test_tutorial004.py | 241 +- .../test_tutorial005.py | 247 +- .../test_tutorial006.py | 261 +- .../test_tutorial007.py | 285 +- .../test_tutorial008.py | 157 +- .../test_tutorial009.py | 125 +- .../test_body_updates/test_tutorial001.py | 241 +- .../test_body_updates/test_tutorial002.py | 241 +- .../test_tutorial001.py | 37 +- .../test_cookie_params/test_tutorial001.py | 133 +- .../test_custom_response/test_tutorial001.py | 37 +- .../test_custom_response/test_tutorial001b.py | 37 +- ...est_tutorial002_tutorial003_tutorial004.py | 37 +- .../test_custom_response/test_tutorial005.py | 39 +- .../test_custom_response/test_tutorial006.py | 37 +- .../test_custom_response/test_tutorial006b.py | 27 +- .../test_custom_response/test_tutorial006c.py | 27 +- .../test_dataclasses/test_tutorial001.py | 153 +- .../test_dataclasses/test_tutorial003.py | 231 +- .../test_debugging/test_tutorial001.py | 35 +- .../test_tutorial001_tutorial001_02.py | 261 +- ...est_tutorial002_tutorial003_tutorial004.py | 167 +- .../test_dependencies/test_tutorial005.py | 147 +- .../test_dependencies/test_tutorial006.py | 139 +- .../test_dependencies/test_tutorial011.py | 133 +- .../test_dependencies/test_tutorial012.py | 205 +- .../test_encoder/test_tutorial001.py | 211 +- .../test_events/test_tutorial001.py | 132 +- .../test_events/test_tutorial002.py | 37 +- .../test_events/test_tutorial003.py | 132 +- .../test_tutorial001.py | 51 +- .../test_tutorial001_tutorial002.py | 195 +- .../test_extra_models/test_tutorial004.py | 77 +- .../test_extra_models/test_tutorial005.py | 51 +- ...est_tutorial001_tutorial002_tutorial003.py | 37 +- .../test_generate_clients/test_tutorial001.py | 185 +- .../test_generate_clients/test_tutorial002.py | 263 +- .../test_generate_clients/test_tutorial003.py | 263 +- .../test_generate_clients/test_tutorial004.py | 344 +- .../test_graphql/test_tutorial001.py | 67 +- .../test_handling_errors/test_tutorial001.py | 127 +- .../test_handling_errors/test_tutorial002.py | 127 +- .../test_handling_errors/test_tutorial003.py | 127 +- .../test_handling_errors/test_tutorial004.py | 127 +- .../test_handling_errors/test_tutorial005.py | 139 +- .../test_handling_errors/test_tutorial006.py | 127 +- .../test_header_params/test_tutorial001.py | 133 +- .../test_header_params/test_tutorial002.py | 133 +- .../test_header_params/test_tutorial003.py | 137 +- .../test_metadata/test_tutorial001.py | 65 +- .../test_metadata/test_tutorial001_1.py | 65 +- .../test_metadata/test_tutorial002.py | 43 +- .../test_metadata/test_tutorial003.py | 43 +- .../test_metadata/test_tutorial004.py | 89 +- .../test_middleware/test_tutorial001.py | 19 +- .../test_tutorial001.py | 273 +- .../test_openapi_webhooks/test_tutorial001.py | 171 +- .../test_tutorial001.py | 37 +- .../test_tutorial002.py | 37 +- .../test_tutorial003.py | 13 +- .../test_tutorial004.py | 173 +- .../test_tutorial005.py | 39 +- .../test_tutorial006.py | 63 +- .../test_tutorial007.py | 69 +- .../test_tutorial001.py | 225 +- .../test_tutorial002.py | 269 +- .../test_tutorial002b.py | 65 +- .../test_tutorial003_tutorial004.py | 227 +- .../test_tutorial005.py | 173 +- .../test_tutorial006.py | 93 +- .../test_path_params/test_tutorial001.py | 155 +- .../test_path_params/test_tutorial002.py | 157 +- .../test_path_params/test_tutorial003.py | 179 +- .../test_path_params/test_tutorial003b.py | 35 +- .../test_path_params/test_tutorial004.py | 127 +- .../test_path_params/test_tutorial005.py | 138 +- .../test_tutorial001.py | 193 +- .../test_tutorial002_tutorial003.py | 179 +- .../test_tutorial004.py | 181 +- .../test_tutorial005.py | 183 +- .../test_tutorial006.py | 203 +- .../test_query_params/test_tutorial001.py | 149 +- .../test_query_params/test_tutorial002.py | 155 +- .../test_query_params/test_tutorial003.py | 173 +- .../test_query_params/test_tutorial004.py | 185 +- .../test_query_params/test_tutorial005.py | 139 +- .../test_query_params/test_tutorial006.py | 173 +- .../test_tutorial001.py | 139 +- .../test_tutorial002.py | 145 +- .../test_tutorial003.py | 147 +- .../test_tutorial004.py | 149 +- .../test_tutorial005.py | 137 +- .../test_tutorial006.py | 135 +- .../test_tutorial006c.py | 139 +- .../test_tutorial007.py | 145 +- .../test_tutorial008.py | 147 +- .../test_tutorial009.py | 139 +- .../test_tutorial010.py | 165 +- .../test_tutorial011.py | 139 +- .../test_tutorial012.py | 137 +- .../test_tutorial013.py | 137 +- .../test_tutorial014.py | 111 +- .../test_request_files/test_tutorial001.py | 207 +- .../test_request_files/test_tutorial001_03.py | 223 +- .../test_request_files/test_tutorial002.py | 237 +- .../test_request_files/test_tutorial003.py | 247 +- .../test_tutorial001.py | 139 +- .../test_tutorial002.py | 141 +- .../test_request_forms/test_tutorial001.py | 139 +- .../test_tutorial001.py | 151 +- .../test_tutorial001.py | 183 +- .../test_tutorial002.py | 41 +- .../test_tutorial001_tutorial001_01.py | 201 +- .../test_response_model/test_tutorial002.py | 161 +- .../test_tutorial003_02.py | 133 +- .../test_tutorial003_03.py | 37 +- .../test_tutorial003_05.py | 133 +- .../test_tutorial001_tutorial002.py | 127 +- .../test_tutorial001.py | 184 +- .../test_tutorial002.py | 188 +- .../test_tutorial003.py | 186 +- .../test_tutorial004.py | 193 +- .../test_tutorial005.py | 213 +- .../test_security/test_tutorial001.py | 53 +- .../test_security/test_tutorial002.py | 53 +- .../test_security/test_tutorial003.py | 213 +- .../test_security/test_tutorial004.py | 313 +- .../test_security/test_tutorial006.py | 45 +- .../test_security/test_tutorial007.py | 45 +- .../test_tutorial001.py | 173 +- .../test_tutorial002.py | 173 +- .../test_tutorial/test_settings/test_app01.py | 37 +- .../test_static_files/test_tutorial001.py | 13 +- .../test_sub_applications/test_tutorial001.py | 102 +- .../test_tutorial/test_testing/test_main_a.py | 38 +- .../test_testing/test_tutorial001.py | 38 +- .../test_tutorial001.py | 163 +- tests/test_union_body.py | 155 +- tests/test_union_forms.py | 168 +- tests/test_union_inherited_body.py | 167 +- tests/test_webhooks_security.py | 150 +- 248 files changed, 27426 insertions(+), 26206 deletions(-) diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py index 935acca42e..130a6662a1 100644 --- a/tests/test_additional_properties.py +++ b/tests/test_additional_properties.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -26,84 +27,88 @@ def test_additional_properties_post(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/foo": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/foo": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Foo", + "operationId": "foo_foo_post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Items"} } }, + "required": True, }, - }, - "summary": "Foo", - "operationId": "foo_foo_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Items"} + } + } + }, + "components": { + "schemas": { + "Items": { + "title": "Items", + "required": ["items"], + "type": "object", + "properties": { + "items": { + "title": "Items", + "type": "object", + "additionalProperties": {"type": "integer"}, } }, - "required": True, }, - } - } - }, - "components": { - "schemas": { - "Items": { - "title": "Items", - "required": ["items"], - "type": "object", - "properties": { - "items": { - "title": "Items", - "type": "object", - "additionalProperties": {"type": "integer"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_additional_properties_bool.py b/tests/test_additional_properties_bool.py index 3b323ad463..c02841cde1 100644 --- a/tests/test_additional_properties_bool.py +++ b/tests/test_additional_properties_bool.py @@ -2,6 +2,7 @@ from typing import Union from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, ConfigDict @@ -40,83 +41,87 @@ def test_call_valid(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post", - "operationId": "post__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - {"$ref": "#/components/schemas/Foo"}, - {"type": "null"}, - ], - "title": "Foo", - } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post", + "operationId": "post__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "anyOf": [ + {"$ref": "#/components/schemas/Foo"}, + {"type": "null"}, + ], + "title": "Foo", } } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "Foo": { - "properties": {}, - "additionalProperties": False, - "type": "object", - "title": "Foo", - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + }, + "components": { + "schemas": { + "Foo": { + "properties": {}, + "additionalProperties": False, + "type": "object", + "title": "Foo", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_additional_response_extra.py b/tests/test_additional_response_extra.py index 55be19bad2..70a9a73312 100644 --- a/tests/test_additional_response_extra.py +++ b/tests/test_additional_response_extra.py @@ -1,5 +1,6 @@ from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot router = APIRouter() @@ -29,21 +30,23 @@ def test_path_operation(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Item", - "operationId": "read_item_items__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Item", + "operationId": "read_item_items__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_additional_responses_custom_validationerror.py b/tests/test_additional_responses_custom_validationerror.py index 8724e5ecb8..9b468c6217 100644 --- a/tests/test_additional_responses_custom_validationerror.py +++ b/tests/test_additional_responses_custom_validationerror.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -34,64 +35,66 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/{id}": { - "get": { - "responses": { - "422": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": { - "$ref": "#/components/schemas/JsonApiError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/{id}": { + "get": { + "responses": { + "422": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } } - } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/vnd.api+json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/vnd.api+json": {"schema": {}}}, - }, - }, - "summary": "A", - "operationId": "a_a__id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Id"}, - "name": "id", - "in": "path", - } - ], + "summary": "A", + "operationId": "a_a__id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Id"}, + "name": "id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, + }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_additional_responses_default_validationerror.py b/tests/test_additional_responses_default_validationerror.py index acc081fb16..09e03959e5 100644 --- a/tests/test_additional_responses_default_validationerror.py +++ b/tests/test_additional_responses_default_validationerror.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -15,72 +16,76 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/{id}": { - "get": { - "responses": { - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/{id}": { + "get": { + "responses": { + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "A", - "operationId": "a_a__id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Id"}, - "name": "id", - "in": "path", - } - ], + "summary": "A", + "operationId": "a_a__id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Id"}, + "name": "id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_additional_responses_response_class.py b/tests/test_additional_responses_response_class.py index fecc3ee16b..3faab27978 100644 --- a/tests/test_additional_responses_response_class.py +++ b/tests/test_additional_responses_response_class.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -39,76 +40,78 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": { - "$ref": "#/components/schemas/JsonApiError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } } - } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/vnd.api+json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/vnd.api+json": {"schema": {}}}, + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Error"} + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, - "summary": "A", - "operationId": "a_a_get", - } + "summary": "B", + "operationId": "b_b_get", + } + }, }, - "/b": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Error"} - } - }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } }, }, - "summary": "B", - "operationId": "b_b_get", } }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, - } + } + ) diff --git a/tests/test_additional_responses_router.py b/tests/test_additional_responses_router.py index 71cabc7c3d..b6c359ba8b 100644 --- a/tests/test_additional_responses_router.py +++ b/tests/test_additional_responses_router.py @@ -1,5 +1,6 @@ from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel @@ -84,94 +85,98 @@ def test_d(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "501": {"description": "Error 1"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "501": {"description": "Error 1"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, - "summary": "A", - "operationId": "a_a_get", - } - }, - "/b": { - "get": { - "responses": { - "502": {"description": "Error 2"}, - "4XX": {"description": "Error with range, upper"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "502": {"description": "Error 2"}, + "4XX": {"description": "Error with range, upper"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, - "summary": "B", - "operationId": "b_b_get", - } - }, - "/c": { - "get": { - "responses": { - "400": {"description": "Error with str"}, - "5XX": {"description": "Error with range, lower"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "B", + "operationId": "b_b_get", + } + }, + "/c": { + "get": { + "responses": { + "400": {"description": "Error with str"}, + "5XX": {"description": "Error with range, lower"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "default": {"description": "A default response"}, }, - "default": {"description": "A default response"}, - }, - "summary": "C", - "operationId": "c_c_get", - } - }, - "/d": { - "get": { - "responses": { - "400": {"description": "Error with str"}, - "5XX": { - "description": "Server Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseModel" + "summary": "C", + "operationId": "c_c_get", + } + }, + "/d": { + "get": { + "responses": { + "400": {"description": "Error with str"}, + "5XX": { + "description": "Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseModel" + } } - } + }, }, - }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "default": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseModel" + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "default": { + "description": "Default Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseModel" + } } - } + }, }, }, - }, - "summary": "D", - "operationId": "d_d_get", - } + "summary": "D", + "operationId": "d_d_get", + } + }, }, - }, - "components": { - "schemas": { - "ResponseModel": { - "title": "ResponseModel", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, + "components": { + "schemas": { + "ResponseModel": { + "title": "ResponseModel", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_additional_responses_union_duplicate_anyof.py b/tests/test_additional_responses_union_duplicate_anyof.py index f5d987ca31..5d833fce4a 100644 --- a/tests/test_additional_responses_union_duplicate_anyof.py +++ b/tests/test_additional_responses_union_duplicate_anyof.py @@ -8,6 +8,7 @@ from typing import Union from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel @@ -45,79 +46,81 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/route1": { - "get": { - "summary": "Route1", - "operationId": "route1_route1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "anyOf": [ - {"$ref": "#/components/schemas/ModelA"}, - {"$ref": "#/components/schemas/ModelB"}, - ], - "title": "Response 500 Route1 Route1 Get", - }, - "examples": {"Case A": {"value": "a"}}, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/route1": { + "get": { + "summary": "Route1", + "operationId": "route1_route1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/ModelA"}, + {"$ref": "#/components/schemas/ModelB"}, + ], + "title": "Response 500 Route1 Route1 Get", + }, + "examples": {"Case A": {"value": "a"}}, + } + }, }, }, - }, - } - }, - "/route2": { - "get": { - "summary": "Route2", - "operationId": "route2_route2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "anyOf": [ - {"$ref": "#/components/schemas/ModelA"}, - {"$ref": "#/components/schemas/ModelB"}, - ], - "title": "Response 500 Route2 Route2 Get", - }, - "examples": {"Case A": {"value": "a"}}, - } + } + }, + "/route2": { + "get": { + "summary": "Route2", + "operationId": "route2_route2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/ModelA"}, + {"$ref": "#/components/schemas/ModelB"}, + ], + "title": "Response 500 Route2 Route2 Get", + }, + "examples": {"Case A": {"value": "a"}}, + } + }, }, }, + } + }, + }, + "components": { + "schemas": { + "ModelA": { + "properties": {"a": {"type": "string", "title": "A"}}, + "type": "object", + "required": ["a"], + "title": "ModelA", + }, + "ModelB": { + "properties": {"b": {"type": "string", "title": "B"}}, + "type": "object", + "required": ["b"], + "title": "ModelB", }, } }, - }, - "components": { - "schemas": { - "ModelA": { - "properties": {"a": {"type": "string", "title": "A"}}, - "type": "object", - "required": ["a"], - "title": "ModelA", - }, - "ModelB": { - "properties": {"b": {"type": "string", "title": "B"}}, - "type": "object", - "required": ["b"], - "title": "ModelB", - }, - } - }, - } + } + ) diff --git a/tests/test_annotated.py b/tests/test_annotated.py index 99bd03ae6f..68e2ea884c 100644 --- a/tests/test_annotated.py +++ b/tests/test_annotated.py @@ -3,6 +3,7 @@ from typing import Annotated import pytest from fastapi import APIRouter, FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -120,174 +121,178 @@ def test_nested_router(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/default": { - "get": { - "summary": "Default", - "operationId": "default_default_get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Foo", - "type": "string", - "default": "foo", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/default": { + "get": { + "summary": "Default", + "operationId": "default_default_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Foo", + "type": "string", + "default": "foo", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/required": { - "get": { - "summary": "Required", - "operationId": "required_required_get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Foo", - "minLength": 1, - "type": "string", + } + }, + "/required": { + "get": { + "summary": "Required", + "operationId": "required_required_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Foo", + "minLength": 1, + "type": "string", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/multiple": { - "get": { - "summary": "Multiple", - "operationId": "multiple_multiple_get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Foo", - "minLength": 1, - "type": "string", + } + }, + "/multiple": { + "get": { + "summary": "Multiple", + "operationId": "multiple_multiple_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Foo", + "minLength": 1, + "type": "string", + }, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/unrelated": { - "get": { - "summary": "Unrelated", - "operationId": "unrelated_unrelated_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Foo", "type": "string"}, - "name": "foo", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/unrelated": { + "get": { + "summary": "Unrelated", + "operationId": "unrelated_unrelated_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Foo", "type": "string"}, + "name": "foo", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_application.py b/tests/test_application.py index fe97e674c0..6758662980 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1,5 +1,6 @@ import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from .main import app @@ -54,1227 +55,1231 @@ def test_enum_status_code_response(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "externalDocs": { - "description": "External API documentation.", - "url": "https://docs.example.com/api-general", - }, - "paths": { - "/api_route": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Non Operation", - "operationId": "non_operation_api_route_get", - } - }, - "/non_decorated_route": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Non Decorated Route", - "operationId": "non_decorated_route_non_decorated_route_get", - } - }, - "/text": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get Text", - "operationId": "get_text_text_get", - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "externalDocs": { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general", }, - "/path/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "paths": { + "/api_route": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Non Operation", + "operationId": "non_operation_api_route_get", + } + }, + "/non_decorated_route": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Non Decorated Route", + "operationId": "non_decorated_route_non_decorated_route_get", + } + }, + "/text": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get Text", + "operationId": "get_text_text_get", + } + }, + "/path/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Id", - "operationId": "get_id_path__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/str/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Id", + "operationId": "get_id_path__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/str/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Str Id", - "operationId": "get_str_id_path_str__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Str Id", + "operationId": "get_str_id_path_str__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Int Id", - "operationId": "get_int_id_path_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/float/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Int Id", + "operationId": "get_int_id_path_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/float/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Float Id", - "operationId": "get_float_id_path_float__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "number"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/bool/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Float Id", + "operationId": "get_float_id_path_float__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "number"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/bool/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Bool Id", - "operationId": "get_bool_id_path_bool__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "boolean"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Bool Id", + "operationId": "get_bool_id_path_bool__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "boolean"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Id", - "operationId": "get_path_param_id_path_param__item_id__get", - "parameters": [ - { - "name": "item_id", - "in": "path", - "required": True, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Item Id", - }, - } - ], - } - }, - "/path/param-minlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Id", + "operationId": "get_path_param_id_path_param__item_id__get", + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": True, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Item Id", + }, + } + ], + } + }, + "/path/param-minlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Min Length", - "operationId": "get_path_param_min_length_path_param_minlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minLength": 3, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-maxlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Min Length", + "operationId": "get_path_param_min_length_path_param_minlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minLength": 3, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-maxlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Max Length", - "operationId": "get_path_param_max_length_path_param_maxlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maxLength": 3, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-min_maxlength/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Max Length", + "operationId": "get_path_param_max_length_path_param_maxlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maxLength": 3, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-min_maxlength/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Min Max Length", - "operationId": "get_path_param_min_max_length_path_param_min_maxlength__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maxLength": 3, - "minLength": 2, - "type": "string", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Min Max Length", + "operationId": "get_path_param_min_max_length_path_param_min_maxlength__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maxLength": 3, + "minLength": 2, + "type": "string", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt", - "operationId": "get_path_param_gt_path_param_gt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt0/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt", + "operationId": "get_path_param_gt_path_param_gt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt0/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt0", - "operationId": "get_path_param_gt0_path_param_gt0__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 0.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-ge/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt0", + "operationId": "get_path_param_gt0_path_param_gt0__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 0.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-ge/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Ge", - "operationId": "get_path_param_ge_path_param_ge__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minimum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Ge", + "operationId": "get_path_param_ge_path_param_ge__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minimum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt", - "operationId": "get_path_param_lt_path_param_lt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt0/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt", + "operationId": "get_path_param_lt_path_param_lt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt0/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt0", - "operationId": "get_path_param_lt0_path_param_lt0__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 0.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt0", + "operationId": "get_path_param_lt0_path_param_lt0__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 0.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le", - "operationId": "get_path_param_le_path_param_le__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-gt/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le", + "operationId": "get_path_param_le_path_param_le__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-gt/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Gt", - "operationId": "get_path_param_lt_gt_path_param_lt_gt__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "exclusiveMinimum": 1.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-ge/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Gt", + "operationId": "get_path_param_lt_gt_path_param_lt_gt__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "exclusiveMinimum": 1.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-ge/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Ge", - "operationId": "get_path_param_le_ge_path_param_le_ge__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "minimum": 1.0, - "type": "number", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Ge", + "operationId": "get_path_param_le_ge_path_param_le_ge__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "minimum": 1.0, + "type": "number", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Int", - "operationId": "get_path_param_lt_int_path_param_lt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-gt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Int", + "operationId": "get_path_param_lt_int_path_param_lt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-gt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Gt Int", - "operationId": "get_path_param_gt_int_path_param_gt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMinimum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Gt Int", + "operationId": "get_path_param_gt_int_path_param_gt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMinimum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Int", - "operationId": "get_path_param_le_int_path_param_le_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-ge-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Int", + "operationId": "get_path_param_le_int_path_param_le_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-ge-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Ge Int", - "operationId": "get_path_param_ge_int_path_param_ge_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "minimum": 3.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-lt-gt-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Ge Int", + "operationId": "get_path_param_ge_int_path_param_ge_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "minimum": 3.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-lt-gt-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Lt Gt Int", - "operationId": "get_path_param_lt_gt_int_path_param_lt_gt_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "exclusiveMaximum": 3.0, - "exclusiveMinimum": 1.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/path/param-le-ge-int/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Lt Gt Int", + "operationId": "get_path_param_lt_gt_int_path_param_lt_gt_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "exclusiveMaximum": 3.0, + "exclusiveMinimum": 1.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/path/param-le-ge-int/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Path Param Le Ge Int", - "operationId": "get_path_param_le_ge_int_path_param_le_ge_int__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "maximum": 3.0, - "minimum": 1.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/query": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Path Param Le Ge Int", + "operationId": "get_path_param_le_ge_int_path_param_le_ge_int__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "maximum": 3.0, + "minimum": 1.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/query": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query", - "operationId": "get_query_query_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/optional": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query", + "operationId": "get_query_query_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/optional": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Optional", - "operationId": "get_query_optional_query_optional_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/int": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Optional", + "operationId": "get_query_optional_query_optional_get", + "parameters": [ + { + "required": False, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/int": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type", - "operationId": "get_query_type_query_int_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query", "type": "integer"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/int/optional": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type", + "operationId": "get_query_type_query_int_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query", "type": "integer"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/int/optional": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type Optional", - "operationId": "get_query_type_optional_query_int_optional_get", - "parameters": [ - { - "name": "query", - "in": "query", - "required": False, - "schema": { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Query", - }, - } - ], - } - }, - "/query/int/default": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type Optional", + "operationId": "get_query_type_optional_query_int_optional_get", + "parameters": [ + { + "name": "query", + "in": "query", + "required": False, + "schema": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "title": "Query", + }, + } + ], + } + }, + "/query/int/default": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Type Int Default", - "operationId": "get_query_type_int_default_query_int_default_get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Query", - "type": "integer", - "default": 10, - }, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Type Int Default", + "operationId": "get_query_type_int_default_query_int_default_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Query", + "type": "integer", + "default": 10, + }, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param", - "operationId": "get_query_param_query_param_get", - "parameters": [ - { - "required": False, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param-required": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Param", + "operationId": "get_query_param_query_param_get", + "parameters": [ + { + "required": False, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param-required": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param Required", - "operationId": "get_query_param_required_query_param_required_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/query/param-required/int": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Query Param Required", + "operationId": "get_query_param_required_query_param_required_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/query/param-required/int": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Query Param Required Type", - "operationId": "get_query_param_required_type_query_param_required_int_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Query", "type": "integer"}, - "name": "query", - "in": "query", - } - ], - } - }, - "/enum-status-code": { - "get": { - "responses": { - "201": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - }, - "summary": "Get Enum Status Code", - "operationId": "get_enum_status_code_enum_status_code_get", - } - }, - "/query/frozenset": { - "get": { - "summary": "Get Query Type Frozenset", - "operationId": "get_query_type_frozenset_query_frozenset_get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Query", - "uniqueItems": True, - "type": "array", - "items": {"type": "integer"}, - }, - "name": "query", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "Get Query Param Required Type", + "operationId": "get_query_param_required_type_query_param_required_int_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Query", "type": "integer"}, + "name": "query", + "in": "query", + } + ], + } + }, + "/enum-status-code": { + "get": { + "responses": { + "201": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Get Enum Status Code", + "operationId": "get_enum_status_code_enum_status_code_get", + } + }, + "/query/frozenset": { + "get": { + "summary": "Get Query Type Frozenset", + "operationId": "get_query_type_frozenset_query_frozenset_get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Query", + "uniqueItems": True, + "type": "array", + "items": {"type": "integer"}, + }, + "name": "query", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query/list": { - "get": { - "summary": "Get Query List", - "operationId": "get_query_list_query_list_get", - "parameters": [ - { - "name": "device_ids", - "in": "query", - "required": True, - "schema": { - "type": "array", - "items": {"type": "integer"}, - "title": "Device Ids", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": {"type": "integer"}, - "title": "Response Get Query List Query List Get", + } + }, + "/query/list": { + "get": { + "summary": "Get Query List", + "operationId": "get_query_list_query_list_get", + "parameters": [ + { + "name": "device_ids", + "in": "query", + "required": True, + "schema": { + "type": "array", + "items": {"type": "integer"}, + "title": "Device Ids", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": {"type": "integer"}, + "title": "Response Get Query List Query List Get", + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query/list-default": { - "get": { - "summary": "Get Query List Default", - "operationId": "get_query_list_default_query_list_default_get", - "parameters": [ - { - "name": "device_ids", - "in": "query", - "required": False, - "schema": { - "type": "array", - "items": {"type": "integer"}, - "default": [], - "title": "Device Ids", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": {"type": "integer"}, - "title": "Response Get Query List Default Query List Default Get", + } + }, + "/query/list-default": { + "get": { + "summary": "Get Query List Default", + "operationId": "get_query_list_default_query_list_default_get", + "parameters": [ + { + "name": "device_ids", + "in": "query", + "required": False, + "schema": { + "type": "array", + "items": {"type": "integer"}, + "default": [], + "title": "Device Ids", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": {"type": "integer"}, + "title": "Response Get Query List Default Query List Default Get", + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_computed_fields.py b/tests/test_computed_fields.py index e7f969f7cf..af6654a639 100644 --- a/tests/test_computed_fields.py +++ b/tests/test_computed_fields.py @@ -1,6 +1,7 @@ import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture(name="client") @@ -43,55 +44,65 @@ def test_get(client: TestClient, path: str): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Read Root", - "operationId": "read_root__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Rectangle"} - } - }, - } - }, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Read Root", + "operationId": "read_root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Rectangle" + } + } + }, + } + }, + } + }, + "/responses": { + "get": { + "summary": "Read Responses", + "operationId": "read_responses_responses_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Rectangle" + } + } + }, + } + }, + } + }, }, - "/responses": { - "get": { - "summary": "Read Responses", - "operationId": "read_responses_responses_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Rectangle"} - } + "components": { + "schemas": { + "Rectangle": { + "properties": { + "width": {"type": "integer", "title": "Width"}, + "length": {"type": "integer", "title": "Length"}, + "area": { + "type": "integer", + "title": "Area", + "readOnly": True, }, - } - }, + }, + "type": "object", + "required": ["width", "length", "area"], + "title": "Rectangle", + } } }, - }, - "components": { - "schemas": { - "Rectangle": { - "properties": { - "width": {"type": "integer", "title": "Width"}, - "length": {"type": "integer", "title": "Length"}, - "area": {"type": "integer", "title": "Area", "readOnly": True}, - }, - "type": "object", - "required": ["width", "length", "area"], - "title": "Rectangle", - } - } - }, - } + } + ) diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py index 55374584b0..786c1efc31 100644 --- a/tests/test_custom_route_class.py +++ b/tests/test_custom_route_class.py @@ -2,6 +2,7 @@ import pytest from fastapi import APIRouter, FastAPI from fastapi.routing import APIRoute from fastapi.testclient import TestClient +from inline_snapshot import snapshot from starlette.routing import Route app = FastAPI() @@ -74,45 +75,47 @@ def test_route_classes(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get A", - "operationId": "get_a_a__get", - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get A", + "operationId": "get_a_a__get", + } + }, + "/a/b/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get B", + "operationId": "get_b_a_b__get", + } + }, + "/a/b/c/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Get C", + "operationId": "get_c_a_b_c__get", + } + }, }, - "/a/b/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get B", - "operationId": "get_b_a_b__get", - } - }, - "/a/b/c/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Get C", - "operationId": "get_c_a_b_c__get", - } - }, - }, - } + } + ) diff --git a/tests/test_dependency_duplicates.py b/tests/test_dependency_duplicates.py index 3ca6a3e891..81490e68b6 100644 --- a/tests/test_dependency_duplicates.py +++ b/tests/test_dependency_duplicates.py @@ -1,5 +1,6 @@ from fastapi import Depends, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -84,149 +85,153 @@ def test_sub_duplicates(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/with-duplicates": { - "post": { - "summary": "With Duplicates", - "operationId": "with_duplicates_with_duplicates_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/with-duplicates": { + "post": { + "summary": "With Duplicates", + "operationId": "with_duplicates_with_duplicates_post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - } - }, - "/no-duplicates": { - "post": { - "summary": "No Duplicates", - "operationId": "no_duplicates_no_duplicates_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_no_duplicates_no_duplicates_post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/no-duplicates": { + "post": { + "summary": "No Duplicates", + "operationId": "no_duplicates_no_duplicates_post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_no_duplicates_no_duplicates_post" } } }, + "required": True, }, - }, - } - }, - "/with-duplicates-sub": { - "post": { - "summary": "No Duplicates Sub", - "operationId": "no_duplicates_sub_with_duplicates_sub_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/with-duplicates-sub": { + "post": { + "summary": "No Duplicates Sub", + "operationId": "no_duplicates_sub_with_duplicates_sub_post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, }, - }, - "components": { - "schemas": { - "Body_no_duplicates_no_duplicates_post": { - "title": "Body_no_duplicates_no_duplicates_post", - "required": ["item", "item2"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, + "components": { + "schemas": { + "Body_no_duplicates_no_duplicates_post": { + "title": "Body_no_duplicates_no_duplicates_post", + "required": ["item", "item2"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["data"], - "type": "object", - "properties": {"data": {"title": "Data", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "Item": { + "title": "Item", + "required": ["data"], + "type": "object", + "properties": {"data": {"title": "Data", "type": "string"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_deprecated_openapi_prefix.py b/tests/test_deprecated_openapi_prefix.py index ec7366d2af..24198af346 100644 --- a/tests/test_deprecated_openapi_prefix.py +++ b/tests/test_deprecated_openapi_prefix.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, Request from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI(openapi_prefix="/api/v1") @@ -21,22 +22,24 @@ def test_main(): def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - "servers": [{"url": "/api/v1"}], - } + }, + "servers": [{"url": "/api/v1"}], + } + ) diff --git a/tests/test_duplicate_models_openapi.py b/tests/test_duplicate_models_openapi.py index 83e86d231a..d5a6d1fec5 100644 --- a/tests/test_duplicate_models_openapi.py +++ b/tests/test_duplicate_models_openapi.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -35,45 +36,49 @@ def test_get_api_route(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "F", - "operationId": "f__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model3"} - } - }, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "F", + "operationId": "f__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Model3" + } + } + }, + } + }, + } } - } - }, - "components": { - "schemas": { - "Model": {"title": "Model", "type": "object", "properties": {}}, - "Model2": { - "title": "Model2", - "required": ["a"], - "type": "object", - "properties": {"a": {"$ref": "#/components/schemas/Model"}}, - }, - "Model3": { - "title": "Model3", - "required": ["c", "d"], - "type": "object", - "properties": { - "c": {"$ref": "#/components/schemas/Model"}, - "d": {"$ref": "#/components/schemas/Model2"}, + }, + "components": { + "schemas": { + "Model": {"title": "Model", "type": "object", "properties": {}}, + "Model2": { + "title": "Model2", + "required": ["a"], + "type": "object", + "properties": {"a": {"$ref": "#/components/schemas/Model"}}, + }, + "Model3": { + "title": "Model3", + "required": ["c", "d"], + "type": "object", + "properties": { + "c": {"$ref": "#/components/schemas/Model"}, + "d": {"$ref": "#/components/schemas/Model2"}, + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index c46a543576..0dee15c25d 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -1,7 +1,8 @@ from typing import Optional -from fastapi import Depends, FastAPI, Query, status +from fastapi import Depends, FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -26,81 +27,6 @@ def foo_handler( client = TestClient(app) -expected_schema = { - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "title": "Detail", - "type": "array", - } - }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - "title": "Location", - "type": "array", - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - "required": ["loc", "msg", "type"], - "title": "ValidationError", - "type": "object", - }, - } - }, - "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.1.0", - "paths": { - "/foo": { - "get": { - "operationId": "foo_handler_foo_get", - "parameters": [ - { - "in": "query", - "name": "client_id", - "required": True, - "schema": {"title": "Client Id", "type": "string"}, - }, - ], - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - "description": "Validation Error", - }, - }, - "summary": "Foo Handler", - } - } - }, -} - - -def test_schema(): - response = client.get("/openapi.json") - assert response.status_code == status.HTTP_200_OK - actual_schema = response.json() - assert actual_schema == expected_schema - def test_get_invalid(): response = client.get("/foo") @@ -111,3 +37,81 @@ def test_get_valid(): response = client.get("/foo", params={"client_id": "bar"}) assert response.status_code == 200 assert response.json() == {"client_id": "bar_key", "client_tag": "bar_tag"} + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array", + } + }, + "title": "HTTPValidationError", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "title": "Location", + "type": "array", + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", + }, + } + }, + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.1.0", + "paths": { + "/foo": { + "get": { + "operationId": "foo_handler_foo_get", + "parameters": [ + { + "in": "query", + "name": "client_id", + "required": True, + "schema": {"title": "Client Id", "type": "string"}, + }, + ], + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error", + }, + }, + "summary": "Foo Handler", + } + } + }, + } + ) diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index 251af4a59e..96f85b4465 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -98,270 +99,274 @@ def test_trace(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Get Items", + "operationId": "get_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Get Items", - "operationId": "get_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "delete": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "delete": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Delete Item", + "operationId": "delete_item_items__item_id__delete", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, - }, - }, - "summary": "Delete Item", - "operationId": "delete_item_items__item_id__delete", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } }, - "required": True, }, - }, - "options": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "options": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Options Item", + "operationId": "options_item_items__item_id__options", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Options Item", - "operationId": "options_item_items__item_id__options", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "head": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "head": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Head Item", + "operationId": "head_item_items__item_id__head", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Head Item", - "operationId": "head_item_items__item_id__head", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "patch": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "patch": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Patch Item", + "operationId": "patch_item_items__item_id__patch", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, - }, - }, - "summary": "Patch Item", - "operationId": "patch_item_items__item_id__patch", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } }, - "required": True, }, - }, - "trace": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "trace": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Trace Item", + "operationId": "trace_item_items__item_id__trace", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Trace Item", - "operationId": "trace_item_items__item_id__trace", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], }, - }, - "/items-not-decorated/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "/items-not-decorated/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Get Not Decorated", - "operationId": "get_not_decorated_items_not_decorated__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } + "summary": "Get Not Decorated", + "operationId": "get_not_decorated_items_not_decorated__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, }, - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": { - "title": "Price", - "anyOf": [{"type": "number"}, {"type": "null"}], + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": { + "title": "Price", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_forms_single_param.py b/tests/test_forms_single_param.py index fc163cb1ef..e759b006a6 100644 --- a/tests/test_forms_single_param.py +++ b/tests/test_forms_single_param.py @@ -2,6 +2,7 @@ from typing import Annotated from fastapi import FastAPI, Form from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -23,80 +24,86 @@ def test_single_form_field(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/form/": { - "post": { - "summary": "Post Form", - "operationId": "post_form_form__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_post_form_form__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/form/": { + "post": { + "summary": "Post Form", + "operationId": "post_form_form__post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_post_form_form__post" } } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "Body_post_form_form__post": { - "properties": {"username": {"type": "string", "title": "Username"}}, - "type": "object", - "required": ["username"], - "title": "Body_post_form_form__post", - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + }, + "components": { + "schemas": { + "Body_post_form_form__post": { + "properties": { + "username": {"type": "string", "title": "Username"} + }, + "type": "object", + "required": ["username"], + "title": "Body_post_form_form__post", }, - "type": "object", - "title": "HTTPValidationError", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_generate_unique_id_function.py b/tests/test_generate_unique_id_function.py index 49510d08a9..c56e6d5794 100644 --- a/tests/test_generate_unique_id_function.py +++ b/tests/test_generate_unique_id_function.py @@ -3,6 +3,7 @@ import warnings from fastapi import APIRouter, FastAPI from fastapi.routing import APIRoute from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel @@ -45,190 +46,197 @@ def test_top_level_generate_unique_id(): app.include_router(router) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "foo_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "foo_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "foo_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Foo Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "foo_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Foo Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_foo_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_foo_post_root": { - "title": "Body_foo_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_router": { - "title": "Body_foo_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, + } }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_foo_post_root": { + "title": "Body_foo_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_router": { + "title": "Body_foo_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_router_overrides_generate_unique_id(): @@ -248,190 +256,197 @@ def test_router_overrides_generate_unique_id(): app.include_router(router) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "foo_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "foo_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "bar_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_bar_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Bar Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "bar_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Bar Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_bar_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_bar_post_router": { - "title": "Body_bar_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_root": { - "title": "Body_foo_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, + } }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_bar_post_router": { + "title": "Body_bar_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_root": { + "title": "Body_foo_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_router_include_overrides_generate_unique_id(): @@ -451,190 +466,197 @@ def test_router_include_overrides_generate_unique_id(): app.include_router(router, generate_unique_id_function=custom_generate_unique_id3) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "foo_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "foo_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "bar_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_bar_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Bar Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "bar_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Bar Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_bar_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_bar_post_router": { - "title": "Body_bar_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_root": { - "title": "Body_foo_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, + } }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_bar_post_router": { + "title": "Body_bar_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_root": { + "title": "Body_foo_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_subrouter_top_level_include_overrides_generate_unique_id(): @@ -664,253 +686,262 @@ def test_subrouter_top_level_include_overrides_generate_unique_id(): app.include_router(router, generate_unique_id_function=custom_generate_unique_id3) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "foo_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "foo_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "baz_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_baz_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Baz Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "baz_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Baz Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_baz_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Baz Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - }, - } - }, - "/subrouter": { - "post": { - "summary": "Post Subrouter", - "operationId": "bar_post_subrouter", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_bar_post_subrouter" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Bar Post Subrouter", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Baz Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Bar Post Subrouter", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "422": { - "description": "Validation Error", + } + }, + "/subrouter": { + "post": { + "summary": "Post Subrouter", + "operationId": "bar_post_subrouter", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_bar_post_subrouter" } } }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Bar Post Subrouter", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } + } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Bar Post Subrouter", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_bar_post_subrouter": { - "title": "Body_bar_post_subrouter", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_baz_post_router": { - "title": "Body_baz_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_root": { - "title": "Body_foo_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, + } }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_bar_post_subrouter": { + "title": "Body_bar_post_subrouter", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_baz_post_router": { + "title": "Body_baz_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_root": { + "title": "Body_foo_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_router_path_operation_overrides_generate_unique_id(): @@ -933,190 +964,197 @@ def test_router_path_operation_overrides_generate_unique_id(): app.include_router(router) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "foo_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "foo_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "baz_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_baz_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Baz Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "baz_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Baz Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_baz_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Baz Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Baz Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_baz_post_router": { - "title": "Body_baz_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_root": { - "title": "Body_foo_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, + } }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_baz_post_router": { + "title": "Body_baz_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_root": { + "title": "Body_foo_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_app_path_operation_overrides_generate_unique_id(): @@ -1143,190 +1181,197 @@ def test_app_path_operation_overrides_generate_unique_id(): app.include_router(router) client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "baz_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_baz_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "baz_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Baz Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_baz_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Baz Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Baz Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Baz Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, }, - }, - }, - } - }, - "/router": { - "post": { - "summary": "Post Router", - "operationId": "bar_post_router", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_bar_post_router" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Bar Post Router", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - "404": { - "description": "Not Found", + } + }, + "/router": { + "post": { + "summary": "Post Router", + "operationId": "bar_post_router", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response 404 Bar Post Router", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "$ref": "#/components/schemas/Body_bar_post_router" } } }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Bar Post Router", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_bar_post_router": { - "title": "Body_bar_post_router", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_baz_post_root": { - "title": "Body_baz_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, + } }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_bar_post_router": { + "title": "Body_bar_post_router", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_baz_post_root": { + "title": "Body_baz_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_callback_override_generate_unique_id(): @@ -1362,259 +1407,266 @@ def test_callback_override_generate_unique_id(): client = TestClient(app) response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "post": { - "summary": "Post Root", - "operationId": "baz_post_root", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_baz_post_root" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "post": { + "summary": "Post Root", + "operationId": "baz_post_root", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Baz Post Root", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_baz_post_root" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Baz Post Root", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Baz Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Baz Post Root", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - "callbacks": { - "post_callback": { - "/post-callback": { - "post": { - "summary": "Post Callback", - "operationId": "baz_post_callback", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_baz_post_callback" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + "callbacks": { + "post_callback": { + "/post-callback": { + "post": { + "summary": "Post Callback", + "operationId": "baz_post_callback", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Baz Post Callback", - "type": "array", - "items": { - "$ref": "#/components/schemas/Item" - }, + "$ref": "#/components/schemas/Body_baz_post_callback" } } }, + "required": True, }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Baz Post Callback", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Baz Post Callback", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Baz Post Callback", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - } - }, - } - }, - "/tocallback": { - "post": { - "summary": "Post With Callback", - "operationId": "foo_post_with_callback", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_foo_post_with_callback" + } } } }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + } + }, + "/tocallback": { + "post": { + "summary": "Post With Callback", + "operationId": "foo_post_with_callback", + "requestBody": { "content": { "application/json": { "schema": { - "title": "Response Foo Post With Callback", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "$ref": "#/components/schemas/Body_foo_post_with_callback" } } }, - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "title": "Response 404 Foo Post With Callback", - "type": "array", - "items": { - "$ref": "#/components/schemas/Message" - }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Foo Post With Callback", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "title": "Response 404 Foo Post With Callback", + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_baz_post_callback": { - "title": "Body_baz_post_callback", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_baz_post_root": { - "title": "Body_baz_post_root", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, - }, - "Body_foo_post_with_callback": { - "title": "Body_foo_post_with_callback", - "required": ["item1", "item2"], - "type": "object", - "properties": { - "item1": {"$ref": "#/components/schemas/Item"}, - "item2": {"$ref": "#/components/schemas/Item"}, - }, + } }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "Message": { - "title": "Message", - "required": ["title", "description"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "description": {"title": "Description", "type": "string"}, + }, + "components": { + "schemas": { + "Body_baz_post_callback": { + "title": "Body_baz_post_callback", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_baz_post_root": { + "title": "Body_baz_post_root", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "Body_foo_post_with_callback": { + "title": "Body_foo_post_with_callback", + "required": ["item1", "item2"], + "type": "object", + "properties": { + "item1": {"$ref": "#/components/schemas/Item"}, + "item2": {"$ref": "#/components/schemas/Item"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, + }, + "Message": { + "title": "Message", + "required": ["title", "description"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, }, - }, - } - }, - } + } + }, + } + ) def test_warn_duplicate_operation_id(): diff --git a/tests/test_generic_parameterless_depends.py b/tests/test_generic_parameterless_depends.py index 93b72ad243..96c7a71265 100644 --- a/tests/test_generic_parameterless_depends.py +++ b/tests/test_generic_parameterless_depends.py @@ -2,6 +2,7 @@ from typing import Annotated, TypeVar from fastapi import Depends, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -44,33 +45,35 @@ def test_generic_parameterless_depends(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.1.0", - "paths": { - "/a": { - "get": { - "operationId": "a_a_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "A", - } + assert response.json() == snapshot( + { + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.1.0", + "paths": { + "/a": { + "get": { + "operationId": "a_a_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } + }, + "summary": "A", + } + }, + "/b": { + "get": { + "operationId": "b_b_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } + }, + "summary": "B", + } + }, }, - "/b": { - "get": { - "operationId": "b_b_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "B", - } - }, - }, - } + } + ) diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index b21889e30f..1b0f4970b7 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -28,82 +29,86 @@ def test_get_with_body(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/product": { - "get": { - "summary": "Create Item", - "operationId": "create_item_product_get", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Product"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/product": { + "get": { + "summary": "Create Item", + "operationId": "create_item_product_get", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Product"} } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Product": { - "title": "Product", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Product": { + "title": "Product", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_include_router_defaults_overrides.py b/tests/test_include_router_defaults_overrides.py index 6d2ffc44a5..e8303c8218 100644 --- a/tests/test_include_router_defaults_overrides.py +++ b/tests/test_include_router_defaults_overrides.py @@ -4,6 +4,7 @@ import pytest from fastapi import APIRouter, Depends, FastAPI, Response from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot class ResponseLevel0(JSONResponse): @@ -442,6858 +443,6862 @@ def test_openapi(): response = client.get("/openapi.json") assert issubclass(w[-1].category, UserWarning) assert "Duplicate Operation ID" in str(w[-1].message) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/override1": { - "get": { - "tags": ["path1a", "path1b"], - "summary": "Path1 Override", - "operationId": "path1_override_override1_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level1", "type": "string"}, - "name": "level1", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/override1": { + "get": { + "tags": ["path1a", "path1b"], + "summary": "Path1 Override", + "operationId": "path1_override_override1_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level1", "type": "string"}, + "name": "level1", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, + "deprecated": True, + } + }, + "/default1": { + "get": { + "summary": "Path1 Default", + "operationId": "path1_default_default1_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level1", "type": "string"}, + "name": "level1", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } }, - }, - "deprecated": True, - } - }, - "/default1": { - "get": { - "summary": "Path1 Default", - "operationId": "path1_default_default1_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level1", "type": "string"}, - "name": "level1", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + "/level1/level2/override3": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "path3a", + "path3b", + ], + "summary": "Path3 Override Router2 Override", + "operationId": "path3_override_router2_override_level1_level2_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, }, - }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - } - }, - } - }, - "/level1/level2/override3": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "path3a", - "path3b", - ], - "summary": "Path3 Override Router2 Override", - "operationId": "path3_override_router2_override_level1_level2_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/default3": { + "get": { + "tags": ["level1a", "level1b", "level2a", "level2b"], + "summary": "Path3 Default Router2 Override", + "operationId": "path3_default_router2_override_level1_level2_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level3/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level2_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/default3": { - "get": { - "tags": ["level1a", "level1b", "level2a", "level2b"], - "summary": "Path3 Default Router2 Override", - "operationId": "path3_default_router2_override_level1_level2_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level3/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level2_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level2_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level3/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level2_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level3/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level3a", + "level3b", + ], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level2_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level2_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level2_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level2_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level2a", + "level2b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level2_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level2_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level3/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level3a", - "level3b", - ], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level2_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level2_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level2_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level2a", - "level2b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level2_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level2/default5": { - "get": { - "tags": ["level1a", "level1b", "level2a", "level2b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level2_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/override3": { - "get": { - "tags": ["level1a", "level1b", "path3a", "path3b"], - "summary": "Path3 Override Router2 Default", - "operationId": "path3_override_router2_default_level1_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/default3": { - "get": { - "tags": ["level1a", "level1b"], - "summary": "Path3 Default Router2 Default", - "operationId": "path3_default_router2_default_level1_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - } - }, - "/level1/level3/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/level4/default5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level3/default5": { - "get": { - "tags": ["level1a", "level1b", "level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - } - }, - "/level1/level4/override5": { - "get": { - "tags": [ - "level1a", - "level1b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level1_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/level4/default5": { - "get": { - "tags": ["level1a", "level1b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level1_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/override5": { - "get": { - "tags": ["level1a", "level1b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level1_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level1/default5": { - "get": { - "tags": ["level1a", "level1b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level1_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-1": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "401": {"description": "Client error level 1"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "501": {"description": "Server error level 1"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "callback1": { - "/": { - "get": { - "summary": "Callback1", - "operationId": "callback1__get", - "parameters": [ - { - "name": "level1", - "in": "query", - "required": True, - "schema": { - "title": "Level1", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - }, - } - }, - "/level2/override3": { - "get": { - "tags": ["level2a", "level2b", "path3a", "path3b"], - "summary": "Path3 Override Router2 Override", - "operationId": "path3_override_router2_override_level2_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level2/default5": { + "get": { + "tags": ["level1a", "level1b", "level2a", "level2b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level2_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/default3": { - "get": { - "tags": ["level2a", "level2b"], - "summary": "Path3 Default Router2 Override", - "operationId": "path3_default_router2_override_level2_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/override3": { + "get": { + "tags": ["level1a", "level1b", "path3a", "path3b"], + "summary": "Path3 Override Router2 Default", + "operationId": "path3_override_router2_default_level1_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/level4/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level2_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/default3": { + "get": { + "tags": ["level1a", "level1b"], + "summary": "Path3 Default Router2 Default", + "operationId": "path3_default_router2_default_level1_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + } + }, + "/level1/level3/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/level4/default5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "level4a", - "level4b", - ], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level2_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level3/level4/default5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level3a", - "level3b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level2_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level3/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level3/default5": { - "get": { - "tags": ["level2a", "level2b", "level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level2_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level3/default5": { + "get": { + "tags": ["level1a", "level1b", "level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level4/override5": { - "get": { - "tags": [ - "level2a", - "level2b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level2_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, + } + }, + "/level1/level4/override5": { + "get": { + "tags": [ + "level1a", + "level1b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level1_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/level4/default5": { + "get": { + "tags": ["level1a", "level1b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level1_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/level4/default5": { - "get": { - "tags": ["level2a", "level2b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level2_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level1/override5": { + "get": { + "tags": ["level1a", "level1b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level1_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, + }, + } + } + }, + }, + "deprecated": True, + } + }, + "/level1/default5": { + "get": { + "tags": ["level1a", "level1b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level1_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-1": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "401": {"description": "Client error level 1"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "501": {"description": "Server error level 1"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback1": { + "/": { + "get": { + "summary": "Callback1", + "operationId": "callback1__get", + "parameters": [ + { + "name": "level1", + "in": "query", + "required": True, + "schema": { + "title": "Level1", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + } + }, + "/level2/override3": { + "get": { + "tags": ["level2a", "level2b", "path3a", "path3b"], + "summary": "Path3 Override Router2 Override", + "operationId": "path3_override_router2_override_level2_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/override5": { - "get": { - "tags": ["level2a", "level2b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level2_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/default3": { + "get": { + "tags": ["level2a", "level2b"], + "summary": "Path3 Default Router2 Override", + "operationId": "path3_default_router2_override_level2_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level3/level4/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level2_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level2/default5": { - "get": { - "tags": ["level2a", "level2b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level2_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-2": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "402": {"description": "Client error level 2"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "502": {"description": "Server error level 2"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level3/level4/default5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "level4a", + "level4b", + ], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level2_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback2": { - "/": { - "get": { - "summary": "Callback2", - "operationId": "callback2__get", - "parameters": [ - { - "name": "level2", - "in": "query", - "required": True, - "schema": { - "title": "Level2", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/override3": { - "get": { - "tags": ["path3a", "path3b"], - "summary": "Path3 Override Router2 Default", - "operationId": "path3_override_router2_default_override3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level3/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level3a", + "level3b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level2_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/default3": { - "get": { - "summary": "Path3 Default Router2 Default", - "operationId": "path3_default_router2_default_default3_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level3", "type": "string"}, - "name": "level3", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level3/default5": { + "get": { + "tags": ["level2a", "level2b", "level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level2_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - } - }, - } - }, - "/level3/level4/override5": { - "get": { - "tags": [ - "level3a", - "level3b", - "level4a", - "level4b", - "path5a", - "path5b", - ], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level3_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level4/override5": { + "get": { + "tags": [ + "level2a", + "level2b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level2_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/level4/default5": { + "get": { + "tags": ["level2a", "level2b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level2_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/level3/level4/default5": { - "get": { - "tags": ["level3a", "level3b", "level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level3_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/override5": { + "get": { + "tags": ["level2a", "level2b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level2_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + "deprecated": True, + } + }, + "/level2/default5": { + "get": { + "tags": ["level2a", "level2b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level2_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-2": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "402": {"description": "Client error level 2"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "502": {"description": "Server error level 2"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback2": { + "/": { + "get": { + "summary": "Callback2", + "operationId": "callback2__get", + "parameters": [ + { + "name": "level2", + "in": "query", + "required": True, + "schema": { + "title": "Level2", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level3/override5": { - "get": { - "tags": ["level3a", "level3b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_level3_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/override3": { + "get": { + "tags": ["path3a", "path3b"], + "summary": "Path3 Override Router2 Default", + "operationId": "path3_override_router2_default_override3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/default3": { + "get": { + "summary": "Path3 Default Router2 Default", + "operationId": "path3_default_router2_default_default3_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level3", "type": "string"}, + "name": "level3", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + } + }, + "/level3/level4/override5": { + "get": { + "tags": [ + "level3a", + "level3b", + "level4a", + "level4b", + "path5a", + "path5b", + ], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level3_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level3/default5": { - "get": { - "tags": ["level3a", "level3b"], - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_level3_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-3": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "403": {"description": "Client error level 3"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "503": {"description": "Server error level 3"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback3": { - "/": { - "get": { - "summary": "Callback3", - "operationId": "callback3__get", - "parameters": [ - { - "name": "level3", - "in": "query", - "required": True, - "schema": { - "title": "Level3", - "type": "string", - }, + "deprecated": True, + } + }, + "/level3/level4/default5": { + "get": { + "tags": ["level3a", "level3b", "level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level3_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - } - }, - "/level4/override5": { - "get": { - "tags": ["level4a", "level4b", "path5a", "path5b"], - "summary": "Path5 Override Router4 Override", - "operationId": "path5_override_router4_override_level4_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "404": {"description": "Client error level 4"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, - }, - "500": {"description": "Server error level 0"}, - "504": {"description": "Server error level 4"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + "deprecated": True, + } + }, + "/level3/override5": { + "get": { + "tags": ["level3a", "level3b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_level3_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/level4/default5": { - "get": { - "tags": ["level4a", "level4b"], - "summary": "Path5 Default Router4 Override", - "operationId": "path5_default_router4_override_level4_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-4": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "404": {"description": "Client error level 4"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - "504": {"description": "Server error level 4"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level3/default5": { + "get": { + "tags": ["level3a", "level3b"], + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_level3_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-3": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "403": {"description": "Client error level 3"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "503": {"description": "Server error level 3"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback3": { + "/": { + "get": { + "summary": "Callback3", + "operationId": "callback3__get", + "parameters": [ + { + "name": "level3", + "in": "query", + "required": True, + "schema": { + "title": "Level3", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback4": { - "/": { - "get": { - "summary": "Callback4", - "operationId": "callback4__get", - "parameters": [ - { - "name": "level4", - "in": "query", - "required": True, - "schema": { - "title": "Level4", - "type": "string", - }, + } + }, + "/level4/override5": { + "get": { + "tags": ["level4a", "level4b", "path5a", "path5b"], + "summary": "Path5 Override Router4 Override", + "operationId": "path5_override_router4_override_level4_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "404": {"description": "Client error level 4"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "504": {"description": "Server error level 4"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } - }, - }, - "deprecated": True, - } - }, - "/override5": { - "get": { - "tags": ["path5a", "path5b"], - "summary": "Path5 Override Router4 Default", - "operationId": "path5_override_router4_default_override5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-5": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "405": {"description": "Client error level 5"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, } } }, }, - "500": {"description": "Server error level 0"}, - "505": {"description": "Server error level 5"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/level4/default5": { + "get": { + "tags": ["level4a", "level4b"], + "summary": "Path5 Default Router4 Override", + "operationId": "path5_default_router4_override_level4_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-4": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "404": {"description": "Client error level 4"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "504": {"description": "Server error level 4"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback4": { + "/": { + "get": { + "summary": "Callback4", + "operationId": "callback4__get", + "parameters": [ + { + "name": "level4", + "in": "query", + "required": True, + "schema": { + "title": "Level4", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - "callback5": { - "/": { - "get": { - "summary": "Callback5", - "operationId": "callback5__get", - "parameters": [ - { - "name": "level5", - "in": "query", - "required": True, - "schema": { - "title": "Level5", - "type": "string", - }, + "deprecated": True, + } + }, + "/override5": { + "get": { + "tags": ["path5a", "path5b"], + "summary": "Path5 Override Router4 Default", + "operationId": "path5_override_router4_default_override5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-5": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "405": {"description": "Client error level 5"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} + } + }, + }, + "500": {"description": "Server error level 0"}, + "505": {"description": "Server error level 5"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + } + }, + "callback5": { + "/": { + "get": { + "summary": "Callback5", + "operationId": "callback5__get", + "parameters": [ + { + "name": "level5", + "in": "query", + "required": True, + "schema": { + "title": "Level5", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } - } - }, - }, - "deprecated": True, - } - }, - "/default5": { - "get": { - "summary": "Path5 Default Router4 Default", - "operationId": "path5_default_router4_default_default5_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Level5", "type": "string"}, - "name": "level5", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/x-level-0": {"schema": {}}}, - }, - "400": {"description": "Client error level 0"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" } } }, }, - "500": {"description": "Server error level 0"}, - }, - "callbacks": { - "callback0": { - "/": { - "get": { - "summary": "Callback0", - "operationId": "callback0__get", - "parameters": [ - { - "name": "level0", - "in": "query", - "required": True, - "schema": { - "title": "Level0", - "type": "string", - }, + "deprecated": True, + } + }, + "/default5": { + "get": { + "summary": "Path5 Default Router4 Default", + "operationId": "path5_default_router4_default_default5_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Level5", "type": "string"}, + "name": "level5", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/x-level-0": {"schema": {}}}, + }, + "400": {"description": "Client error level 0"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + } + }, + }, + "500": {"description": "Server error level 0"}, + }, + "callbacks": { + "callback0": { + "/": { + "get": { + "summary": "Callback0", + "operationId": "callback0__get", + "parameters": [ + { + "name": "level0", + "in": "query", + "required": True, + "schema": { + "title": "Level0", + "type": "string", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": {"schema": {}} + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } - } - }, - } + }, + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_infer_param_optionality.py b/tests/test_infer_param_optionality.py index b11a1ca433..bb20a4a1aa 100644 --- a/tests/test_infer_param_optionality.py +++ b/tests/test_infer_param_optionality.py @@ -2,6 +2,7 @@ from typing import Optional from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -107,228 +108,232 @@ def test_get_users_item(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "summary": "Get Users", - "operationId": "get_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/users/{user_id}": { - "get": { - "summary": "Get User", - "operationId": "get_user_users__user_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "User Id", "type": "string"}, - "name": "user_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "summary": "Get Users", + "operationId": "get_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/users/{user_id}": { + "get": { + "summary": "Get User", + "operationId": "get_user_users__user_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "User Id", "type": "string"}, + "name": "user_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/items/": { - "get": { - "summary": "Get Items", - "operationId": "get_items_items__get", - "parameters": [ - { - "required": False, - "name": "user_id", - "in": "query", - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "User Id", + } + }, + "/items/": { + "get": { + "summary": "Get Items", + "operationId": "get_items_items__get", + "parameters": [ + { + "required": False, + "name": "user_id", + "in": "query", + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "User Id", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/items/{item_id}": { - "get": { - "summary": "Get Item", - "operationId": "get_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "name": "user_id", - "in": "query", - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "User Id", + } + }, + "/items/{item_id}": { + "get": { + "summary": "Get Item", + "operationId": "get_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + { + "required": False, + "name": "user_id", + "in": "query", + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "User Id", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/users/{user_id}/items/": { - "get": { - "summary": "Get Items", - "operationId": "get_items_users__user_id__items__get", - "parameters": [ - { - "required": True, - "name": "user_id", - "in": "path", - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "User Id", + } + }, + "/users/{user_id}/items/": { + "get": { + "summary": "Get Items", + "operationId": "get_items_users__user_id__items__get", + "parameters": [ + { + "required": True, + "name": "user_id", + "in": "path", + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "User Id", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/users/{user_id}/items/{item_id}": { - "get": { - "summary": "Get Item", - "operationId": "get_item_users__user_id__items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "name": "user_id", - "in": "path", - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "User Id", + } + }, + "/users/{user_id}/items/{item_id}": { + "get": { + "summary": "Get Item", + "operationId": "get_item_users__user_id__items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + { + "required": True, + "name": "user_id", + "in": "path", + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "User Id", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index 276de539db..72707993e0 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -1,5 +1,6 @@ import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from .app.main import app @@ -28,124 +29,128 @@ def test_post_invalid(path): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a/compute": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a/compute": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Compute", + "operationId": "compute_a_compute_post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_compute_a_compute_post" } } }, + "required": True, }, - }, - "summary": "Compute", - "operationId": "compute_a_compute_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_compute_a_compute_post" - } - } - }, - "required": True, - }, - } - }, - "/b/compute/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/b/compute/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Compute", + "operationId": "compute_b_compute__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_compute_b_compute__post" } } }, + "required": True, }, - }, - "summary": "Compute", - "operationId": "compute_b_compute__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_compute_b_compute__post" - } - } - }, - "required": True, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "Body_compute_b_compute__post": { - "title": "Body_compute_b_compute__post", - "required": ["a", "b"], - "type": "object", - "properties": { - "a": {"title": "A", "type": "integer"}, - "b": {"title": "B", "type": "string"}, + "components": { + "schemas": { + "Body_compute_b_compute__post": { + "title": "Body_compute_b_compute__post", + "required": ["a", "b"], + "type": "object", + "properties": { + "a": {"title": "A", "type": "integer"}, + "b": {"title": "B", "type": "string"}, + }, }, - }, - "Body_compute_a_compute_post": { - "title": "Body_compute_a_compute_post", - "required": ["a", "b"], - "type": "object", - "properties": { - "a": {"title": "A", "type": "integer"}, - "b": {"title": "B", "type": "string"}, + "Body_compute_a_compute_post": { + "title": "Body_compute_a_compute_post", + "required": ["a", "b"], + "type": "object", + "properties": { + "a": {"title": "A", "type": "integer"}, + "b": {"title": "B", "type": "string"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index fa3e0c6359..792471b5c1 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -89,99 +89,103 @@ def test_put_incorrect_body_multiple(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Save Item No Body", + "operationId": "save_item_no_body_items__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Item", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, } } }, + "required": True, }, - }, - "summary": "Save Item No Body", - "operationId": "save_item_no_body_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Item", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "age"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "age": { - "title": "Age", - "anyOf": [ - {"exclusiveMinimum": 0.0, "type": "number"}, - IsOneOf( - # pydantic < 2.12.0 - {"type": "string"}, - # pydantic >= 2.12.0 - { - "type": "string", - "pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$", - }, - ), - ], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "age"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "age": { + "title": "Age", + "anyOf": [ + {"exclusiveMinimum": 0.0, "type": "number"}, + IsOneOf( + # pydantic < 2.12.0 + {"type": "string"}, + # pydantic >= 2.12.0 + { + "type": "string", + "pattern": r"^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$", + }, + ), + ], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_multi_query_errors.py b/tests/test_multi_query_errors.py index 7540367a6f..060951efa4 100644 --- a/tests/test_multi_query_errors.py +++ b/tests/test_multi_query_errors.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -42,76 +43,80 @@ def test_multi_query_incorrect(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "integer"}, - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "integer"}, + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index 93e5b366f1..deb74d8a0f 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -2,6 +2,7 @@ from typing import Union from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -143,277 +144,281 @@ def test_call_api(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/examples/": { - "post": { - "summary": "Examples", - "operationId": "examples_examples__post", - "requestBody": { - "content": { - "application/json": { + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/examples/": { + "post": { + "summary": "Examples", + "operationId": "examples_examples__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item", + "examples": [ + {"data": "Data in Body examples, example1"} + ], + }, + "examples": { + "Example One": { + "summary": "Example One Summary", + "description": "Example One Description", + "value": { + "data": "Data in Body examples, example1" + }, + }, + "Example Two": { + "value": { + "data": "Data in Body examples, example2" + } + }, + }, + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/path_examples/{item_id}": { + "get": { + "summary": "Path Examples", + "operationId": "path_examples_path_examples__item_id__get", + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": True, "schema": { - "$ref": "#/components/schemas/Item", + "type": "string", "examples": [ - {"data": "Data in Body examples, example1"} + "json_schema_item_1", + "json_schema_item_2", ], + "title": "Item Id", }, "examples": { - "Example One": { - "summary": "Example One Summary", - "description": "Example One Description", - "value": { - "data": "Data in Body examples, example1" - }, - }, - "Example Two": { - "value": { - "data": "Data in Body examples, example2" - } + "Path One": { + "summary": "Path One Summary", + "description": "Path One Description", + "value": "item_1", }, + "Path Two": {"value": "item_2"}, }, } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/path_examples/{item_id}": { - "get": { - "summary": "Path Examples", - "operationId": "path_examples_path_examples__item_id__get", - "parameters": [ - { - "name": "item_id", - "in": "path", - "required": True, - "schema": { - "type": "string", - "examples": [ - "json_schema_item_1", - "json_schema_item_2", - ], - "title": "Item Id", - }, - "examples": { - "Path One": { - "summary": "Path One Summary", - "description": "Path One Description", - "value": "item_1", + } + }, + "/query_examples/": { + "get": { + "summary": "Query Examples", + "operationId": "query_examples_query_examples__get", + "parameters": [ + { + "name": "data", + "in": "query", + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "examples": [ + "json_schema_query1", + "json_schema_query2", + ], + "title": "Data", + }, + "examples": { + "Query One": { + "summary": "Query One Summary", + "description": "Query One Description", + "value": "query1", + }, + "Query Two": {"value": "query2"}, }, - "Path Two": {"value": "item_2"}, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_examples/": { - "get": { - "summary": "Query Examples", - "operationId": "query_examples_query_examples__get", - "parameters": [ - { - "name": "data", - "in": "query", - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "examples": [ - "json_schema_query1", - "json_schema_query2", - ], - "title": "Data", - }, - "examples": { - "Query One": { - "summary": "Query One Summary", - "description": "Query One Description", - "value": "query1", + } + }, + "/header_examples/": { + "get": { + "summary": "Header Examples", + "operationId": "header_examples_header_examples__get", + "parameters": [ + { + "name": "data", + "in": "header", + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "examples": [ + "json_schema_header1", + "json_schema_header2", + ], + "title": "Data", }, - "Query Two": {"value": "query2"}, + "examples": { + "Header One": { + "summary": "Header One Summary", + "description": "Header One Description", + "value": "header1", + }, + "Header Two": {"value": "header2"}, + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_examples/": { - "get": { - "summary": "Header Examples", - "operationId": "header_examples_header_examples__get", - "parameters": [ - { - "name": "data", - "in": "header", - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "examples": [ - "json_schema_header1", - "json_schema_header2", - ], - "title": "Data", - }, - "examples": { - "Header One": { - "summary": "Header One Summary", - "description": "Header One Description", - "value": "header1", + } + }, + "/cookie_examples/": { + "get": { + "summary": "Cookie Examples", + "operationId": "cookie_examples_cookie_examples__get", + "parameters": [ + { + "name": "data", + "in": "cookie", + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "examples": [ + "json_schema_cookie1", + "json_schema_cookie2", + ], + "title": "Data", + }, + "examples": { + "Cookie One": { + "summary": "Cookie One Summary", + "description": "Cookie One Description", + "value": "cookie1", + }, + "Cookie Two": {"value": "cookie2"}, }, - "Header Two": {"value": "header2"}, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - "/cookie_examples/": { - "get": { - "summary": "Cookie Examples", - "operationId": "cookie_examples_cookie_examples__get", - "parameters": [ - { - "name": "data", - "in": "cookie", - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "examples": [ - "json_schema_cookie1", - "json_schema_cookie2", - ], - "title": "Data", - }, - "examples": { - "Cookie One": { - "summary": "Cookie One Summary", - "description": "Cookie One Description", - "value": "cookie1", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" }, - "Cookie Two": {"value": "cookie2"}, - }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, + "type": "array", + "title": "Detail", + } }, + "type": "object", + "title": "HTTPValidationError", }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + "Item": { + "properties": {"data": {"type": "string", "title": "Data"}}, + "type": "object", + "required": ["data"], + "title": "Item", }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": {"data": {"type": "string", "title": "Data"}}, - "type": "object", - "required": ["data"], - "title": "Item", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_openapi_query_parameter_extension.py b/tests/test_openapi_query_parameter_extension.py index b6c3c3d8da..836a0a7ee5 100644 --- a/tests/test_openapi_query_parameter_extension.py +++ b/tests/test_openapi_query_parameter_extension.py @@ -2,6 +2,7 @@ from typing import Optional from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -41,88 +42,92 @@ def test_get_route(): def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Route With Extra Query Parameters", - "operationId": "route_with_extra_query_parameters__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "default": 50, - "title": "Standard Query Param", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Route With Extra Query Parameters", + "operationId": "route_with_extra_query_parameters__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "default": 50, + "title": "Standard Query Param", + }, + "name": "standard_query_param", + "in": "query", }, - "name": "standard_query_param", - "in": "query", - }, - { - "required": False, - "schema": {"title": "Extra Param 1"}, - "name": "extra_param_1", - "in": "query", - }, - { - "required": True, - "schema": {"title": "Extra Param 2"}, - "name": "extra_param_2", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + { + "required": False, + "schema": {"title": "Extra Param 1"}, + "name": "extra_param_1", + "in": "query", + }, + { + "required": True, + "schema": {"title": "Extra Param 2"}, + "name": "extra_param_2", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_openapi_route_extensions.py b/tests/test_openapi_route_extensions.py index 3a30994367..fc11b69c81 100644 --- a/tests/test_openapi_route_extensions.py +++ b/tests/test_openapi_route_extensions.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -18,25 +19,27 @@ def test_get_route(): assert response.json() == {} -def test_openapi(): +def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, - "summary": "Route With Extras", - "operationId": "route_with_extras__get", - "x-custom-extension": "value", - } + "summary": "Route With Extras", + "operationId": "route_with_extras__get", + "x-custom-extension": "value", + } + }, }, - }, - } + } + ) diff --git a/tests/test_openapi_separate_input_output_schemas.py b/tests/test_openapi_separate_input_output_schemas.py index f941e323bf..0efeece017 100644 --- a/tests/test_openapi_separate_input_output_schemas.py +++ b/tests/test_openapi_separate_input_output_schemas.py @@ -444,229 +444,235 @@ def test_openapi_schema_no_separate(): client = get_app_client(separate_input_output_schemas=False) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": {"$ref": "#/components/schemas/Item"}, - "type": "array", - "title": "Response Read Items Items Get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/Item" + }, + "type": "array", + "title": "Response Read Items Items Get", + } } - } - }, - } - }, - }, - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "402": { - "description": "Payment Required", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "402": { + "description": "Payment Required", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, - }, - "/items-list/": { - "post": { - "summary": "Create Item List", - "operationId": "create_item_list_items_list__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "items": {"$ref": "#/components/schemas/Item"}, - "type": "array", - "title": "Item", - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "/items-list/": { + "post": { + "summary": "Create Item List", + "operationId": "create_item_list_items_list__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "items": {"$ref": "#/components/schemas/Item"}, + "type": "array", + "title": "Item", } } }, + "required": True, }, - }, - } - }, - "/with-computed-field/": { - "post": { - "summary": "Create With Computed Field", - "operationId": "create_with_computed_field_with_computed_field__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WithComputedField-Input" - } - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + } + }, + "/with-computed-field/": { + "post": { + "summary": "Create With Computed Field", + "operationId": "create_with_computed_field_with_computed_field__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithComputedField-Output" + "$ref": "#/components/schemas/WithComputedField-Input" } } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithComputedField-Output" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } - }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", - }, - "sub": { - "anyOf": [ - {"$ref": "#/components/schemas/SubItem"}, - {"type": "null"}, - ] + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "required": ["name"], - "title": "Item", - }, - "SubItem": { - "properties": { - "subname": {"type": "string", "title": "Subname"}, - "sub_description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Sub Description", + "Item": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "sub": { + "anyOf": [ + {"$ref": "#/components/schemas/SubItem"}, + {"type": "null"}, + ] + }, }, - "tags": { - "items": {"type": "string"}, - "type": "array", - "title": "Tags", - "default": [], + "type": "object", + "required": ["name"], + "title": "Item", + }, + "SubItem": { + "properties": { + "subname": {"type": "string", "title": "Subname"}, + "sub_description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Sub Description", + }, + "tags": { + "items": {"type": "string"}, + "type": "array", + "title": "Tags", + "default": [], + }, }, + "type": "object", + "required": ["subname"], + "title": "SubItem", }, - "type": "object", - "required": ["subname"], - "title": "SubItem", - }, - "WithComputedField-Input": { - "properties": {"name": {"type": "string", "title": "Name"}}, - "type": "object", - "required": ["name"], - "title": "WithComputedField", - }, - "WithComputedField-Output": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "computed_field": { - "type": "string", - "title": "Computed Field", - "readOnly": True, + "WithComputedField-Input": { + "properties": {"name": {"type": "string", "title": "Name"}}, + "type": "object", + "required": ["name"], + "title": "WithComputedField", + }, + "WithComputedField-Output": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "computed_field": { + "type": "string", + "title": "Computed Field", + "readOnly": True, + }, }, + "type": "object", + "required": ["name", "computed_field"], + "title": "WithComputedField", }, - "type": "object", - "required": ["name", "computed_field"], - "title": "WithComputedField", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - "type": "array", - "title": "Location", + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_param_in_path_and_dependency.py b/tests/test_param_in_path_and_dependency.py index 6b1f660cb7..81178924bf 100644 --- a/tests/test_param_in_path_and_dependency.py +++ b/tests/test_param_in_path_and_dependency.py @@ -1,5 +1,6 @@ from fastapi import Depends, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -23,73 +24,76 @@ def test_read_users(): def test_openapi_schema(): response = client.get("/openapi.json") - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/{user_id}": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__user_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "User Id", "type": "integer"}, - "name": "user_id", - "in": "path", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/{user_id}": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__user_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "User Id", "type": "integer"}, + "name": "user_id", + "in": "path", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index 5060920f14..463fb51b10 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -3,6 +3,7 @@ from typing import Optional import pytest from fastapi import Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -33,140 +34,6 @@ async def hidden_query( return {"hidden_query": hidden_query} -openapi_schema = { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/hidden_cookie": { - "get": { - "summary": "Hidden Cookie", - "operationId": "hidden_cookie_hidden_cookie_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/hidden_header": { - "get": { - "summary": "Hidden Header", - "operationId": "hidden_header_hidden_header_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/hidden_path/{hidden_path}": { - "get": { - "summary": "Hidden Path", - "operationId": "hidden_path_hidden_path__hidden_path__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/hidden_query": { - "get": { - "summary": "Hidden Query", - "operationId": "hidden_query_hidden_query_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, - }, - }, - } - }, -} - - -def test_openapi_schema(): - client = TestClient(app) - response = client.get("/openapi.json") - assert response.status_code == 200 - assert response.json() == openapi_schema - - @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", [ @@ -242,3 +109,140 @@ def test_hidden_query(path, expected_status, expected_response): response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response + + +def test_openapi_schema(): + client = TestClient(app) + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/hidden_cookie": { + "get": { + "summary": "Hidden Cookie", + "operationId": "hidden_cookie_hidden_cookie_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/hidden_header": { + "get": { + "summary": "Hidden Header", + "operationId": "hidden_header_hidden_header_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/hidden_path/{hidden_path}": { + "get": { + "summary": "Hidden Path", + "operationId": "hidden_path_hidden_path__hidden_path__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/hidden_query": { + "get": { + "summary": "Hidden Query", + "operationId": "hidden_query_hidden_query_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, + }, + }, + } + }, + } + ) diff --git a/tests/test_put_no_body.py b/tests/test_put_no_body.py index 2b9299bc58..5759a3f9f6 100644 --- a/tests/test_put_no_body.py +++ b/tests/test_put_no_body.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -27,72 +28,76 @@ def test_put_no_body_with_body(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Save Item No Body", - "operationId": "save_item_no_body_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Save Item No Body", + "operationId": "save_item_no_body_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_regex_deprecated_params.py b/tests/test_regex_deprecated_params.py index 6074b62828..2069004f3c 100644 --- a/tests/test_regex_deprecated_params.py +++ b/tests/test_regex_deprecated_params.py @@ -4,6 +4,7 @@ import pytest from fastapi import FastAPI, Query from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.testclient import TestClient +from inline_snapshot import snapshot from .utils import needs_py310 @@ -64,79 +65,82 @@ def test_openapi_schema(): client = get_client() response = client.get("/openapi.json") assert response.status_code == 200, response.text - # insert_assert(response.json()) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "name": "q", - "in": "query", - "required": False, - "schema": { - "anyOf": [ - {"type": "string", "pattern": "^fixedquery$"}, - {"type": "null"}, - ], - "title": "Q", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "name": "q", + "in": "query", + "required": False, + "schema": { + "anyOf": [ + {"type": "string", "pattern": "^fixedquery$"}, + {"type": "null"}, + ], + "title": "Q", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index 0fc7e3d3ef..304052dd11 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -1,5 +1,6 @@ from fastapi import Depends, FastAPI, Header, status from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -19,86 +20,90 @@ def get_deps(dep1: str = Depends(get_header), dep2: str = Depends(get_something_ client = TestClient(app) -schema = { - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "title": "Detail", - "type": "array", - } - }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - "title": "Location", - "type": "array", - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - "required": ["loc", "msg", "type"], - "title": "ValidationError", - "type": "object", - }, - } - }, - "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.1.0", - "paths": { - "/": { - "get": { - "operationId": "get_deps__get", - "parameters": [ - { - "in": "header", - "name": "someheader", - "required": True, - "schema": {"title": "Someheader", "type": "string"}, - } - ], - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - "description": "Validation Error", - }, - }, - "summary": "Get Deps", - } - } - }, -} + +def test_response(): + response = client.get("/", headers={"someheader": "hello"}) + assert response.status_code == status.HTTP_200_OK + assert response.json() == {"dep1": "hello", "dep2": "hello123"} -def test_schema(): +def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == status.HTTP_200_OK actual_schema = response.json() - assert actual_schema == schema assert ( len(actual_schema["paths"]["/"]["get"]["parameters"]) == 1 ) # primary goal of this test - - -def test_response(): - response = client.get("/", headers={"someheader": "hello"}) - assert response.status_code == status.HTTP_200_OK - assert response.json() == {"dep1": "hello", "dep2": "hello123"} + assert actual_schema == snapshot( + { + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array", + } + }, + "title": "HTTPValidationError", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "title": "Location", + "type": "array", + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", + }, + } + }, + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.1.0", + "paths": { + "/": { + "get": { + "operationId": "get_deps__get", + "parameters": [ + { + "in": "header", + "name": "someheader", + "required": True, + "schema": {"title": "Someheader", "type": "string"}, + } + ], + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error", + }, + }, + "summary": "Get Deps", + } + } + }, + } + ) diff --git a/tests/test_repeated_parameter_alias.py b/tests/test_repeated_parameter_alias.py index 49e4ad4a2e..32cd55ec31 100644 --- a/tests/test_repeated_parameter_alias.py +++ b/tests/test_repeated_parameter_alias.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, Path, Query, status from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -24,79 +25,82 @@ def test_get_parameters(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == status.HTTP_200_OK - actual_schema = response.json() - assert actual_schema == { - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "title": "Detail", - "type": "array", - } + assert response.json() == snapshot( + { + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array", + } + }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "title": "Location", + "type": "array", }, - "title": "Location", - "type": "array", + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", }, - "required": ["loc", "msg", "type"], - "title": "ValidationError", - "type": "object", - }, - } - }, - "info": {"title": "FastAPI", "version": "0.1.0"}, - "openapi": "3.1.0", - "paths": { - "/{repeated_alias}": { - "get": { - "operationId": "get_parameters_with_repeated_aliases__repeated_alias__get", - "parameters": [ - { - "in": "path", - "name": "repeated_alias", - "required": True, - "schema": {"title": "Repeated Alias", "type": "string"}, - }, - { - "in": "query", - "name": "repeated_alias", - "required": True, - "schema": {"title": "Repeated Alias", "type": "string"}, - }, - ], - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.1.0", + "paths": { + "/{repeated_alias}": { + "get": { + "operationId": "get_parameters_with_repeated_aliases__repeated_alias__get", + "parameters": [ + { + "in": "path", + "name": "repeated_alias", + "required": True, + "schema": {"title": "Repeated Alias", "type": "string"}, + }, + { + "in": "query", + "name": "repeated_alias", + "required": True, + "schema": {"title": "Repeated Alias", "type": "string"}, + }, + ], + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, - "summary": "Get Parameters With Repeated Aliases", + "summary": "Get Parameters With Repeated Aliases", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_reponse_set_reponse_code_empty.py index b31aefa479..77da6aafcb 100644 --- a/tests/test_reponse_set_reponse_code_empty.py +++ b/tests/test_reponse_set_reponse_code_empty.py @@ -2,6 +2,7 @@ from typing import Any from fastapi import FastAPI, Response from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -31,69 +32,73 @@ def test_dependency_set_status_code(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/{id}": { - "delete": { - "summary": "Delete Deployment", - "operationId": "delete_deployment__id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Id", "type": "integer"}, - "name": "id", - "in": "path", - } - ], - "responses": { - "204": {"description": "Successful Response"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/{id}": { + "delete": { + "summary": "Delete Deployment", + "operationId": "delete_deployment__id__delete", + "parameters": [ + { + "required": True, + "schema": {"title": "Id", "type": "integer"}, + "name": "id", + "in": "path", + } + ], + "responses": { + "204": {"description": "Successful Response"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_request_body_parameters_media_type.py b/tests/test_request_body_parameters_media_type.py index 8731c3e5d3..10e7be50cb 100644 --- a/tests/test_request_body_parameters_media_type.py +++ b/tests/test_request_body_parameters_media_type.py @@ -1,5 +1,6 @@ from fastapi import Body, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -37,141 +38,147 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/products": { - "post": { - "summary": "Create Product", - "operationId": "create_product_products_post", - "requestBody": { - "content": { - "application/vnd.api+json": { - "schema": { - "$ref": "#/components/schemas/Body_create_product_products_post" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/products": { + "post": { + "summary": "Create Product", + "operationId": "create_product_products_post", + "requestBody": { + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Body_create_product_products_post" + } } - } + }, + "required": True, }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/shops": { + "post": { + "summary": "Create Shop", + "operationId": "create_shop_shops_post", + "requestBody": { "content": { - "application/json": { + "application/vnd.api+json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_shop_shops_post" } } }, + "required": True, }, - }, - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, }, - "/shops": { - "post": { - "summary": "Create Shop", - "operationId": "create_shop_shops_post", - "requestBody": { - "content": { - "application/vnd.api+json": { - "schema": { - "$ref": "#/components/schemas/Body_create_shop_shops_post" - } - } + "components": { + "schemas": { + "Body_create_product_products_post": { + "title": "Body_create_product_products_post", + "required": ["data"], + "type": "object", + "properties": { + "data": {"$ref": "#/components/schemas/Product"} }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + "Body_create_shop_shops_post": { + "title": "Body_create_shop_shops_post", + "required": ["data"], + "type": "object", + "properties": { + "data": {"$ref": "#/components/schemas/Shop"}, + "included": { + "title": "Included", + "type": "array", + "items": {"$ref": "#/components/schemas/Product"}, + "default": [], }, }, }, - } - }, - }, - "components": { - "schemas": { - "Body_create_product_products_post": { - "title": "Body_create_product_products_post", - "required": ["data"], - "type": "object", - "properties": {"data": {"$ref": "#/components/schemas/Product"}}, - }, - "Body_create_shop_shops_post": { - "title": "Body_create_shop_shops_post", - "required": ["data"], - "type": "object", - "properties": { - "data": {"$ref": "#/components/schemas/Shop"}, - "included": { - "title": "Included", - "type": "array", - "items": {"$ref": "#/components/schemas/Product"}, - "default": [], + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "Product": { + "title": "Product", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "Product": { - "title": "Product", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Shop": { + "title": "Shop", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, }, - }, - "Shop": { - "title": "Shop", - "required": ["name"], - "type": "object", - "properties": {"name": {"title": "Name", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_request_params/test_cookie/test_optional_str.py b/tests/test_request_params/test_cookie/test_optional_str.py index 6f381c8b86..1b2a18b072 100644 --- a/tests/test_request_params/test_cookie/test_optional_str.py +++ b/tests/test_request_params/test_cookie/test_optional_str.py @@ -3,6 +3,7 @@ from typing import Annotated, Optional import pytest from fastapi import Cookie, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -30,17 +31,19 @@ async def read_model_optional_str(p: Annotated[CookieModelOptionalStr, Cookie()] ["/optional-str", "/model-optional-str"], ) def test_optional_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P", - }, - "name": "p", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P", + }, + "name": "p", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -91,17 +94,19 @@ async def read_model_optional_alias(p: Annotated[CookieModelOptionalAlias, Cooki ["/optional-alias", "/model-optional-alias"], ) def test_optional_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Alias", - }, - "name": "p_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Alias", + }, + "name": "p_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -169,17 +174,19 @@ def read_model_optional_validation_alias( ["/optional-validation-alias", "/model-optional-validation-alias"], ) def test_optional_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -255,17 +262,19 @@ def read_model_optional_alias_and_validation_alias( ], ) def test_optional_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_cookie/test_required_str.py b/tests/test_request_params/test_cookie/test_required_str.py index 3e877b3e3d..25f93bba66 100644 --- a/tests/test_request_params/test_cookie/test_required_str.py +++ b/tests/test_request_params/test_cookie/test_required_str.py @@ -4,6 +4,7 @@ import pytest from dirty_equals import IsOneOf from fastapi import Cookie, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -31,14 +32,16 @@ async def read_model_required_str(p: Annotated[CookieModelRequiredStr, Cookie()] ["/required-str", "/model-required-str"], ) def test_required_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P", "type": "string"}, - "name": "p", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P", "type": "string"}, + "name": "p", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -96,14 +99,16 @@ async def read_model_required_alias(p: Annotated[CookieModelRequiredAlias, Cooki ["/required-alias", "/model-required-alias"], ) def test_required_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Alias", "type": "string"}, - "name": "p_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Alias", "type": "string"}, + "name": "p_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -195,14 +200,16 @@ def read_model_required_validation_alias( ["/required-validation-alias", "/model-required-validation-alias"], ) def test_required_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( @@ -302,14 +309,16 @@ def read_model_required_alias_and_validation_alias( ], ) def test_required_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "cookie", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "cookie", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_header/test_list.py b/tests/test_request_params/test_header/test_list.py index 489a6b3e7d..4b8e2adb4a 100644 --- a/tests/test_request_params/test_header/test_list.py +++ b/tests/test_request_params/test_header/test_list.py @@ -4,6 +4,7 @@ import pytest from dirty_equals import AnyThing, IsOneOf, IsPartialDict from fastapi import FastAPI, Header from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -31,18 +32,20 @@ def read_model_required_list_str(p: Annotated[HeaderModelRequiredListStr, Header ["/required-list-str", "/model-required-list-str"], ) def test_required_list_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -101,18 +104,20 @@ async def read_model_required_list_alias( ["/required-list-alias", "/model-required-list-alias"], ) def test_required_list_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -199,18 +204,20 @@ async def read_model_required_list_validation_alias( ["/required-list-validation-alias", "/model-required-list-validation-alias"], ) def test_required_list_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Val Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Val Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -307,18 +314,20 @@ def read_model_required_list_alias_and_validation_alias( ], ) def test_required_list_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Val Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Val Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_header/test_optional_list.py b/tests/test_request_params/test_header/test_optional_list.py index 5dd4ea9ade..3bbb73d544 100644 --- a/tests/test_request_params/test_header/test_optional_list.py +++ b/tests/test_request_params/test_header/test_optional_list.py @@ -3,6 +3,7 @@ from typing import Annotated, Optional import pytest from fastapi import FastAPI, Header from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -34,20 +35,22 @@ async def read_model_optional_list_str( ["/optional-list-str", "/model-optional-list-str"], ) def test_optional_list_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P", - }, - "name": "p", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P", + }, + "name": "p", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -99,20 +102,22 @@ async def read_model_optional_list_alias( ["/optional-list-alias", "/model-optional-list-alias"], ) def test_optional_list_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Alias", - }, - "name": "p_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Alias", + }, + "name": "p_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -178,20 +183,22 @@ def read_model_optional_list_validation_alias( ["/optional-list-validation-alias", "/model-optional-list-validation-alias"], ) def test_optional_list_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -266,20 +273,22 @@ def read_model_optional_list_alias_and_validation_alias( ], ) def test_optional_list_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_header/test_optional_str.py b/tests/test_request_params/test_header/test_optional_str.py index 0bd0eddc1b..a5174e59af 100644 --- a/tests/test_request_params/test_header/test_optional_str.py +++ b/tests/test_request_params/test_header/test_optional_str.py @@ -3,6 +3,7 @@ from typing import Annotated, Optional import pytest from fastapi import FastAPI, Header from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -30,17 +31,19 @@ async def read_model_optional_str(p: Annotated[HeaderModelOptionalStr, Header()] ["/optional-str", "/model-optional-str"], ) def test_optional_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P", - }, - "name": "p", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P", + }, + "name": "p", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -90,17 +93,19 @@ async def read_model_optional_alias(p: Annotated[HeaderModelOptionalAlias, Heade ["/optional-alias", "/model-optional-alias"], ) def test_optional_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Alias", - }, - "name": "p_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Alias", + }, + "name": "p_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -166,17 +171,19 @@ def read_model_optional_validation_alias( ["/optional-validation-alias", "/model-optional-validation-alias"], ) def test_optional_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -250,17 +257,19 @@ def read_model_optional_alias_and_validation_alias( ], ) def test_optional_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_header/test_required_str.py b/tests/test_request_params/test_header/test_required_str.py index 20dd296570..2df9b5f2ff 100644 --- a/tests/test_request_params/test_header/test_required_str.py +++ b/tests/test_request_params/test_header/test_required_str.py @@ -4,6 +4,7 @@ import pytest from dirty_equals import AnyThing, IsOneOf, IsPartialDict from fastapi import FastAPI, Header from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -31,14 +32,16 @@ async def read_model_required_str(p: Annotated[HeaderModelRequiredStr, Header()] ["/required-str", "/model-required-str"], ) def test_required_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P", "type": "string"}, - "name": "p", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P", "type": "string"}, + "name": "p", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -95,14 +98,16 @@ async def read_model_required_alias(p: Annotated[HeaderModelRequiredAlias, Heade ["/required-alias", "/model-required-alias"], ) def test_required_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Alias", "type": "string"}, - "name": "p_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Alias", "type": "string"}, + "name": "p_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -189,14 +194,16 @@ def read_model_required_validation_alias( ["/required-validation-alias", "/model-required-validation-alias"], ) def test_required_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( @@ -294,14 +301,16 @@ def read_model_required_alias_and_validation_alias( ], ) def test_required_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "header", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "header", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_path/test_required_str.py b/tests/test_request_params/test_path/test_required_str.py index b2d63667e2..5add058c2b 100644 --- a/tests/test_request_params/test_path/test_required_str.py +++ b/tests/test_request_params/test_path/test_required_str.py @@ -3,6 +3,7 @@ from typing import Annotated import pytest from fastapi import FastAPI, Path from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -53,14 +54,16 @@ def read_required_alias_and_validation_alias( ], ) def test_schema(path: str, expected_name: str, expected_title: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": expected_title, "type": "string"}, - "name": expected_name, - "in": "path", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": expected_title, "type": "string"}, + "name": expected_name, + "in": "path", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_query/test_list.py b/tests/test_request_params/test_query/test_list.py index e933da214d..a5cd030218 100644 --- a/tests/test_request_params/test_query/test_list.py +++ b/tests/test_request_params/test_query/test_list.py @@ -4,6 +4,7 @@ import pytest from dirty_equals import IsOneOf from fastapi import FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -31,18 +32,20 @@ def read_model_required_list_str(p: Annotated[QueryModelRequiredListStr, Query() ["/required-list-str", "/model-required-list-str"], ) def test_required_list_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -101,18 +104,20 @@ async def read_model_required_list_alias( ["/required-list-alias", "/model-required-list-alias"], ) def test_required_list_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -199,18 +204,20 @@ async def read_model_required_list_validation_alias( ["/required-list-validation-alias", "/model-required-list-validation-alias"], ) def test_required_list_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Val Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Val Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -305,18 +312,20 @@ def read_model_required_list_alias_and_validation_alias( ], ) def test_required_list_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": { - "title": "P Val Alias", - "type": "array", - "items": {"type": "string"}, - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": { + "title": "P Val Alias", + "type": "array", + "items": {"type": "string"}, + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_query/test_optional_list.py b/tests/test_request_params/test_query/test_optional_list.py index 351e03a713..5608c6499b 100644 --- a/tests/test_request_params/test_query/test_optional_list.py +++ b/tests/test_request_params/test_query/test_optional_list.py @@ -3,6 +3,7 @@ from typing import Annotated, Optional import pytest from fastapi import FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -34,20 +35,22 @@ async def read_model_optional_list_str( ["/optional-list-str", "/model-optional-list-str"], ) def test_optional_list_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P", - }, - "name": "p", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P", + }, + "name": "p", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -99,20 +102,22 @@ async def read_model_optional_list_alias( ["/optional-list-alias", "/model-optional-list-alias"], ) def test_optional_list_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Alias", - }, - "name": "p_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Alias", + }, + "name": "p_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -178,20 +183,22 @@ def read_model_optional_list_validation_alias( ["/optional-list-validation-alias", "/model-optional-list-validation-alias"], ) def test_optional_list_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -264,20 +271,22 @@ def read_model_optional_list_alias_and_validation_alias( ], ) def test_optional_list_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_query/test_optional_str.py b/tests/test_request_params/test_query/test_optional_str.py index 12e1b465a7..b181686b05 100644 --- a/tests/test_request_params/test_query/test_optional_str.py +++ b/tests/test_request_params/test_query/test_optional_str.py @@ -3,6 +3,7 @@ from typing import Annotated, Optional import pytest from fastapi import FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -30,17 +31,19 @@ async def read_model_optional_str(p: Annotated[QueryModelOptionalStr, Query()]): ["/optional-str", "/model-optional-str"], ) def test_optional_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P", - }, - "name": "p", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P", + }, + "name": "p", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -90,17 +93,19 @@ async def read_model_optional_alias(p: Annotated[QueryModelOptionalAlias, Query( ["/optional-alias", "/model-optional-alias"], ) def test_optional_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Alias", - }, - "name": "p_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Alias", + }, + "name": "p_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -166,17 +171,19 @@ def read_model_optional_validation_alias( ["/optional-validation-alias", "/model-optional-validation-alias"], ) def test_optional_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -250,17 +257,19 @@ def read_model_optional_alias_and_validation_alias( ], ) def test_optional_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "P Val Alias", - }, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "P Val Alias", + }, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_request_params/test_query/test_required_str.py b/tests/test_request_params/test_query/test_required_str.py index 9e7b961453..c60e5ca02a 100644 --- a/tests/test_request_params/test_query/test_required_str.py +++ b/tests/test_request_params/test_query/test_required_str.py @@ -4,6 +4,7 @@ import pytest from dirty_equals import IsOneOf from fastapi import FastAPI, Query from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, Field app = FastAPI() @@ -31,14 +32,16 @@ async def read_model_required_str(p: Annotated[QueryModelRequiredStr, Query()]): ["/required-str", "/model-required-str"], ) def test_required_str_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P", "type": "string"}, - "name": "p", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P", "type": "string"}, + "name": "p", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -95,14 +98,16 @@ async def read_model_required_alias(p: Annotated[QueryModelRequiredAlias, Query( ["/required-alias", "/model-required-alias"], ) def test_required_str_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Alias", "type": "string"}, - "name": "p_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Alias", "type": "string"}, + "name": "p_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -192,14 +197,16 @@ def read_model_required_validation_alias( ["/required-validation-alias", "/model-required-validation-alias"], ) def test_required_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( @@ -297,14 +304,16 @@ def read_model_required_alias_and_validation_alias( ], ) def test_required_alias_and_validation_alias_schema(path: str): - assert app.openapi()["paths"][path]["get"]["parameters"] == [ - { - "required": True, - "schema": {"title": "P Val Alias", "type": "string"}, - "name": "p_val_alias", - "in": "query", - } - ] + assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( + [ + { + "required": True, + "schema": {"title": "P Val Alias", "type": "string"}, + "name": "p_val_alias", + "in": "query", + } + ] + ) @pytest.mark.parametrize( diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py index 807d2600b9..cf97934a9b 100644 --- a/tests/test_response_by_alias.py +++ b/tests/test_response_by_alias.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, ConfigDict, Field app = FastAPI() @@ -136,188 +137,194 @@ def test_read_list_no_alias(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/dict": { - "get": { - "summary": "Read Dict", - "operationId": "read_dict_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/model": { - "get": { - "summary": "Read Model", - "operationId": "read_model_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/list": { - "get": { - "summary": "Read List", - "operationId": "read_list_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read List List Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/dict": { + "get": { + "summary": "Read Dict", + "operationId": "read_dict_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} } - } - }, - } - }, - } - }, - "/by-alias/dict": { - "get": { - "summary": "By Alias Dict", - "operationId": "by_alias_dict_by_alias_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/by-alias/model": { - "get": { - "summary": "By Alias Model", - "operationId": "by_alias_model_by_alias_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } - }, - } - }, - } - }, - "/by-alias/list": { - "get": { - "summary": "By Alias List", - "operationId": "by_alias_list_by_alias_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response By Alias List By Alias List Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, + }, + } + }, + } + }, + "/model": { + "get": { + "summary": "Read Model", + "operationId": "read_model_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} } - } - }, - } - }, - } - }, - "/no-alias/dict": { - "get": { - "summary": "No Alias Dict", - "operationId": "no_alias_dict_no_alias_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelNoAlias" + }, + } + }, + } + }, + "/list": { + "get": { + "summary": "Read List", + "operationId": "read_list_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read List List Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Model" + }, + } } - } - }, - } - }, - } - }, - "/no-alias/model": { - "get": { - "summary": "No Alias Model", - "operationId": "no_alias_model_no_alias_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelNoAlias" + }, + } + }, + } + }, + "/by-alias/dict": { + "get": { + "summary": "By Alias Dict", + "operationId": "by_alias_dict_by_alias_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} } - } - }, - } - }, - } - }, - "/no-alias/list": { - "get": { - "summary": "No Alias List", - "operationId": "no_alias_list_no_alias_list_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Alias List No Alias List Get", - "type": "array", - "items": { + }, + } + }, + } + }, + "/by-alias/model": { + "get": { + "summary": "By Alias Model", + "operationId": "by_alias_model_by_alias_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, + } + }, + } + }, + "/by-alias/list": { + "get": { + "summary": "By Alias List", + "operationId": "by_alias_list_by_alias_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response By Alias List By Alias List Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Model" + }, + } + } + }, + } + }, + } + }, + "/no-alias/dict": { + "get": { + "summary": "No Alias Dict", + "operationId": "no_alias_dict_no_alias_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelNoAlias" + } + } + }, + } + }, + } + }, + "/no-alias/model": { + "get": { + "summary": "No Alias Model", + "operationId": "no_alias_model_no_alias_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ModelNoAlias" - }, + } + } + }, + } + }, + } + }, + "/no-alias/list": { + "get": { + "summary": "No Alias List", + "operationId": "no_alias_list_no_alias_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Alias List No Alias List Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/ModelNoAlias" + }, + } } - } - }, - } + }, + } + }, + } + }, + }, + "components": { + "schemas": { + "Model": { + "title": "Model", + "required": ["alias"], + "type": "object", + "properties": {"alias": {"title": "Alias", "type": "string"}}, + }, + "ModelNoAlias": { + "title": "ModelNoAlias", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, + "description": "response_model_by_alias=False is basically a quick hack, to support proper OpenAPI use another model with the correct field names", }, } }, - }, - "components": { - "schemas": { - "Model": { - "title": "Model", - "required": ["alias"], - "type": "object", - "properties": {"alias": {"title": "Alias", "type": "string"}}, - }, - "ModelNoAlias": { - "title": "ModelNoAlias", - "required": ["name"], - "type": "object", - "properties": {"name": {"title": "Name", "type": "string"}}, - "description": "response_model_by_alias=False is basically a quick hack, to support proper OpenAPI use another model with the correct field names", - }, - } - }, - } + } + ) diff --git a/tests/test_response_class_no_mediatype.py b/tests/test_response_class_no_mediatype.py index 4dc164bf92..75582cd607 100644 --- a/tests/test_response_class_no_mediatype.py +++ b/tests/test_response_class_no_mediatype.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Response from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -39,73 +40,75 @@ client = TestClient(app) def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JsonApiError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } } - } + }, }, + "200": {"description": "Successful Response"}, }, - "200": {"description": "Successful Response"}, - }, - "summary": "A", - "operationId": "a_a_get", - } - }, - "/b": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Error"} - } + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Error"} + } + }, + }, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, }, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "summary": "B", + "operationId": "b_b_get", + } + }, + }, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } }, }, - "summary": "B", - "operationId": "b_b_get", } }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, - } + } + ) diff --git a/tests/test_response_code_no_body.py b/tests/test_response_code_no_body.py index 70456a7462..2156210650 100644 --- a/tests/test_response_code_no_body.py +++ b/tests/test_response_code_no_body.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from fastapi.responses import JSONResponse from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -47,66 +48,68 @@ def test_get_response(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/a": { - "get": { - "responses": { - "500": { - "description": "Error", - "content": { - "application/vnd.api+json": { - "schema": { - "$ref": "#/components/schemas/JsonApiError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/a": { + "get": { + "responses": { + "500": { + "description": "Error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/JsonApiError" + } } - } + }, }, + "204": {"description": "Successful Response"}, }, - "204": {"description": "Successful Response"}, - }, - "summary": "A", - "operationId": "a_a_get", - } + "summary": "A", + "operationId": "a_a_get", + } + }, + "/b": { + "get": { + "responses": { + "204": {"description": "No Content"}, + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + }, + "summary": "B", + "operationId": "b_b_get", + } + }, }, - "/b": { - "get": { - "responses": { - "204": {"description": "No Content"}, - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "components": { + "schemas": { + "Error": { + "title": "Error", + "required": ["status", "title"], + "type": "object", + "properties": { + "status": {"title": "Status", "type": "string"}, + "title": {"title": "Title", "type": "string"}, + }, + }, + "JsonApiError": { + "title": "JsonApiError", + "required": ["errors"], + "type": "object", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "items": {"$ref": "#/components/schemas/Error"}, + } }, }, - "summary": "B", - "operationId": "b_b_get", } }, - }, - "components": { - "schemas": { - "Error": { - "title": "Error", - "required": ["status", "title"], - "type": "object", - "properties": { - "status": {"title": "Status", "type": "string"}, - "title": {"title": "Title", "type": "string"}, - }, - }, - "JsonApiError": { - "title": "JsonApiError", - "required": ["errors"], - "type": "object", - "properties": { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "#/components/schemas/Error"}, - } - }, - }, - } - }, - } + } + ) diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index 58fba89f1a..ded5971027 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -5,6 +5,7 @@ from fastapi import FastAPI from fastapi.exceptions import FastAPIError, ResponseValidationError from fastapi.responses import JSONResponse, Response from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel @@ -512,603 +513,611 @@ def test_invalid_response_model_field(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/no_response_model-no_annotation-return_model": { - "get": { - "summary": "No Response Model No Annotation Return Model", - "operationId": "no_response_model_no_annotation_return_model_no_response_model_no_annotation_return_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/no_response_model-no_annotation-return_dict": { - "get": { - "summary": "No Response Model No Annotation Return Dict", - "operationId": "no_response_model_no_annotation_return_dict_no_response_model_no_annotation_return_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model-no_annotation-return_same_model": { - "get": { - "summary": "Response Model No Annotation Return Same Model", - "operationId": "response_model_no_annotation_return_same_model_response_model_no_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_exact_dict": { - "get": { - "summary": "Response Model No Annotation Return Exact Dict", - "operationId": "response_model_no_annotation_return_exact_dict_response_model_no_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_invalid_dict": { - "get": { - "summary": "Response Model No Annotation Return Invalid Dict", - "operationId": "response_model_no_annotation_return_invalid_dict_response_model_no_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_invalid_model": { - "get": { - "summary": "Response Model No Annotation Return Invalid Model", - "operationId": "response_model_no_annotation_return_invalid_model_response_model_no_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_dict_with_extra_data": { - "get": { - "summary": "Response Model No Annotation Return Dict With Extra Data", - "operationId": "response_model_no_annotation_return_dict_with_extra_data_response_model_no_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model-no_annotation-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model No Annotation Return Submodel With Extra Data", - "operationId": "response_model_no_annotation_return_submodel_with_extra_data_response_model_no_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_same_model": { - "get": { - "summary": "No Response Model Annotation Return Same Model", - "operationId": "no_response_model_annotation_return_same_model_no_response_model_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_exact_dict": { - "get": { - "summary": "No Response Model Annotation Return Exact Dict", - "operationId": "no_response_model_annotation_return_exact_dict_no_response_model_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_invalid_dict": { - "get": { - "summary": "No Response Model Annotation Return Invalid Dict", - "operationId": "no_response_model_annotation_return_invalid_dict_no_response_model_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_invalid_model": { - "get": { - "summary": "No Response Model Annotation Return Invalid Model", - "operationId": "no_response_model_annotation_return_invalid_model_no_response_model_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_dict_with_extra_data": { - "get": { - "summary": "No Response Model Annotation Return Dict With Extra Data", - "operationId": "no_response_model_annotation_return_dict_with_extra_data_no_response_model_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/no_response_model-annotation-return_submodel_with_extra_data": { - "get": { - "summary": "No Response Model Annotation Return Submodel With Extra Data", - "operationId": "no_response_model_annotation_return_submodel_with_extra_data_no_response_model_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_none-annotation-return_same_model": { - "get": { - "summary": "Response Model None Annotation Return Same Model", - "operationId": "response_model_none_annotation_return_same_model_response_model_none_annotation_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_exact_dict": { - "get": { - "summary": "Response Model None Annotation Return Exact Dict", - "operationId": "response_model_none_annotation_return_exact_dict_response_model_none_annotation_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_invalid_dict": { - "get": { - "summary": "Response Model None Annotation Return Invalid Dict", - "operationId": "response_model_none_annotation_return_invalid_dict_response_model_none_annotation_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_invalid_model": { - "get": { - "summary": "Response Model None Annotation Return Invalid Model", - "operationId": "response_model_none_annotation_return_invalid_model_response_model_none_annotation_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_dict_with_extra_data": { - "get": { - "summary": "Response Model None Annotation Return Dict With Extra Data", - "operationId": "response_model_none_annotation_return_dict_with_extra_data_response_model_none_annotation_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_none-annotation-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model None Annotation Return Submodel With Extra Data", - "operationId": "response_model_none_annotation_return_submodel_with_extra_data_response_model_none_annotation_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_same_model": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Same Model", - "operationId": "response_model_model1_annotation_model2_return_same_model_response_model_model1_annotation_model2_return_same_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_exact_dict": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Exact Dict", - "operationId": "response_model_model1_annotation_model2_return_exact_dict_response_model_model1_annotation_model2_return_exact_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_invalid_dict": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Invalid Dict", - "operationId": "response_model_model1_annotation_model2_return_invalid_dict_response_model_model1_annotation_model2_return_invalid_dict_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_invalid_model": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Invalid Model", - "operationId": "response_model_model1_annotation_model2_return_invalid_model_response_model_model1_annotation_model2_return_invalid_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_dict_with_extra_data": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Dict With Extra Data", - "operationId": "response_model_model1_annotation_model2_return_dict_with_extra_data_response_model_model1_annotation_model2_return_dict_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_model1-annotation_model2-return_submodel_with_extra_data": { - "get": { - "summary": "Response Model Model1 Annotation Model2 Return Submodel With Extra Data", - "operationId": "response_model_model1_annotation_model2_return_submodel_with_extra_data_response_model_model1_annotation_model2_return_submodel_with_extra_data_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_filtering_model-annotation_submodel-return_submodel": { - "get": { - "summary": "Response Model Filtering Model Annotation Submodel Return Submodel", - "operationId": "response_model_filtering_model_annotation_submodel_return_submodel_response_model_filtering_model_annotation_submodel_return_submodel_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - } - }, - } - }, - "/response_model_list_of_model-no_annotation": { - "get": { - "summary": "Response Model List Of Model No Annotation", - "operationId": "response_model_list_of_model_no_annotation_response_model_list_of_model_no_annotation_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model List Of Model No Annotation Response Model List Of Model No Annotation Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/no_response_model-no_annotation-return_model": { + "get": { + "summary": "No Response Model No Annotation Return Model", + "operationId": "no_response_model_no_annotation_return_model_no_response_model_no_annotation_return_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/no_response_model-no_annotation-return_dict": { + "get": { + "summary": "No Response Model No Annotation Return Dict", + "operationId": "no_response_model_no_annotation_return_dict_no_response_model_no_annotation_return_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model-no_annotation-return_same_model": { + "get": { + "summary": "Response Model No Annotation Return Same Model", + "operationId": "response_model_no_annotation_return_same_model_response_model_no_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/no_response_model-annotation_list_of_model": { - "get": { - "summary": "No Response Model Annotation List Of Model", - "operationId": "no_response_model_annotation_list_of_model_no_response_model_annotation_list_of_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation List Of Model No Response Model Annotation List Of Model Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, + }, + } + }, + } + }, + "/response_model-no_annotation-return_exact_dict": { + "get": { + "summary": "Response Model No Annotation Return Exact Dict", + "operationId": "response_model_no_annotation_return_exact_dict_response_model_no_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/no_response_model-annotation_forward_ref_list_of_model": { - "get": { - "summary": "No Response Model Annotation Forward Ref List Of Model", - "operationId": "no_response_model_annotation_forward_ref_list_of_model_no_response_model_annotation_forward_ref_list_of_model_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Forward Ref List Of Model No Response Model Annotation Forward Ref List Of Model Get", - "type": "array", - "items": {"$ref": "#/components/schemas/User"}, + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_dict": { + "get": { + "summary": "Response Model No Annotation Return Invalid Dict", + "operationId": "response_model_no_annotation_return_invalid_dict_response_model_no_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/response_model_union-no_annotation-return_model1": { - "get": { - "summary": "Response Model Union No Annotation Return Model1", - "operationId": "response_model_union_no_annotation_return_model1_response_model_union_no_annotation_return_model1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model Union No Annotation Return Model1 Response Model Union No Annotation Return Model1 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], + }, + } + }, + } + }, + "/response_model-no_annotation-return_invalid_model": { + "get": { + "summary": "Response Model No Annotation Return Invalid Model", + "operationId": "response_model_no_annotation_return_invalid_model_response_model_no_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/response_model_union-no_annotation-return_model2": { - "get": { - "summary": "Response Model Union No Annotation Return Model2", - "operationId": "response_model_union_no_annotation_return_model2_response_model_union_no_annotation_return_model2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Response Model Union No Annotation Return Model2 Response Model Union No Annotation Return Model2 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], + }, + } + }, + } + }, + "/response_model-no_annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Dict With Extra Data", + "operationId": "response_model_no_annotation_return_dict_with_extra_data_response_model_no_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/no_response_model-annotation_union-return_model1": { - "get": { - "summary": "No Response Model Annotation Union Return Model1", - "operationId": "no_response_model_annotation_union_return_model1_no_response_model_annotation_union_return_model1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Union Return Model1 No Response Model Annotation Union Return Model1 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], + }, + } + }, + } + }, + "/response_model-no_annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model No Annotation Return Submodel With Extra Data", + "operationId": "response_model_no_annotation_return_submodel_with_extra_data_response_model_no_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } - }, - "/no_response_model-annotation_union-return_model2": { - "get": { - "summary": "No Response Model Annotation Union Return Model2", - "operationId": "no_response_model_annotation_union_return_model2_no_response_model_annotation_union_return_model2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response No Response Model Annotation Union Return Model2 No Response Model Annotation Union Return Model2 Get", - "anyOf": [ - {"$ref": "#/components/schemas/User"}, - {"$ref": "#/components/schemas/Item"}, - ], + }, + } + }, + } + }, + "/no_response_model-annotation-return_same_model": { + "get": { + "summary": "No Response Model Annotation Return Same Model", + "operationId": "no_response_model_annotation_return_same_model_no_response_model_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} } - } - }, - } - }, - } + }, + } + }, + } + }, + "/no_response_model-annotation-return_exact_dict": { + "get": { + "summary": "No Response Model Annotation Return Exact Dict", + "operationId": "no_response_model_annotation_return_exact_dict_no_response_model_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_dict": { + "get": { + "summary": "No Response Model Annotation Return Invalid Dict", + "operationId": "no_response_model_annotation_return_invalid_dict_no_response_model_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_invalid_model": { + "get": { + "summary": "No Response Model Annotation Return Invalid Model", + "operationId": "no_response_model_annotation_return_invalid_model_no_response_model_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_dict_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Dict With Extra Data", + "operationId": "no_response_model_annotation_return_dict_with_extra_data_no_response_model_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/no_response_model-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "No Response Model Annotation Return Submodel With Extra Data", + "operationId": "no_response_model_annotation_return_submodel_with_extra_data_no_response_model_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_none-annotation-return_same_model": { + "get": { + "summary": "Response Model None Annotation Return Same Model", + "operationId": "response_model_none_annotation_return_same_model_response_model_none_annotation_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_exact_dict": { + "get": { + "summary": "Response Model None Annotation Return Exact Dict", + "operationId": "response_model_none_annotation_return_exact_dict_response_model_none_annotation_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_dict": { + "get": { + "summary": "Response Model None Annotation Return Invalid Dict", + "operationId": "response_model_none_annotation_return_invalid_dict_response_model_none_annotation_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_invalid_model": { + "get": { + "summary": "Response Model None Annotation Return Invalid Model", + "operationId": "response_model_none_annotation_return_invalid_model_response_model_none_annotation_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_dict_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Dict With Extra Data", + "operationId": "response_model_none_annotation_return_dict_with_extra_data_response_model_none_annotation_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_none-annotation-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model None Annotation Return Submodel With Extra Data", + "operationId": "response_model_none_annotation_return_submodel_with_extra_data_response_model_none_annotation_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_same_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Same Model", + "operationId": "response_model_model1_annotation_model2_return_same_model_response_model_model1_annotation_model2_return_same_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_exact_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Exact Dict", + "operationId": "response_model_model1_annotation_model2_return_exact_dict_response_model_model1_annotation_model2_return_exact_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_dict": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Dict", + "operationId": "response_model_model1_annotation_model2_return_invalid_dict_response_model_model1_annotation_model2_return_invalid_dict_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_invalid_model": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Invalid Model", + "operationId": "response_model_model1_annotation_model2_return_invalid_model_response_model_model1_annotation_model2_return_invalid_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_dict_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Dict With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_dict_with_extra_data_response_model_model1_annotation_model2_return_dict_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_model1-annotation_model2-return_submodel_with_extra_data": { + "get": { + "summary": "Response Model Model1 Annotation Model2 Return Submodel With Extra Data", + "operationId": "response_model_model1_annotation_model2_return_submodel_with_extra_data_response_model_model1_annotation_model2_return_submodel_with_extra_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_filtering_model-annotation_submodel-return_submodel": { + "get": { + "summary": "Response Model Filtering Model Annotation Submodel Return Submodel", + "operationId": "response_model_filtering_model_annotation_submodel_return_submodel_response_model_filtering_model_annotation_submodel_return_submodel_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, + } + }, + } + }, + "/response_model_list_of_model-no_annotation": { + "get": { + "summary": "Response Model List Of Model No Annotation", + "operationId": "response_model_list_of_model_no_annotation_response_model_list_of_model_no_annotation_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model List Of Model No Annotation Response Model List Of Model No Annotation Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + }, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_list_of_model": { + "get": { + "summary": "No Response Model Annotation List Of Model", + "operationId": "no_response_model_annotation_list_of_model_no_response_model_annotation_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation List Of Model No Response Model Annotation List Of Model Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + }, + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_forward_ref_list_of_model": { + "get": { + "summary": "No Response Model Annotation Forward Ref List Of Model", + "operationId": "no_response_model_annotation_forward_ref_list_of_model_no_response_model_annotation_forward_ref_list_of_model_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Forward Ref List Of Model No Response Model Annotation Forward Ref List Of Model Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + }, + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model1": { + "get": { + "summary": "Response Model Union No Annotation Return Model1", + "operationId": "response_model_union_no_annotation_return_model1_response_model_union_no_annotation_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model1 Response Model Union No Annotation Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/response_model_union-no_annotation-return_model2": { + "get": { + "summary": "Response Model Union No Annotation Return Model2", + "operationId": "response_model_union_no_annotation_return_model2_response_model_union_no_annotation_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Response Model Union No Annotation Return Model2 Response Model Union No Annotation Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model1": { + "get": { + "summary": "No Response Model Annotation Union Return Model1", + "operationId": "no_response_model_annotation_union_return_model1_no_response_model_annotation_union_return_model1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model1 No Response Model Annotation Union Return Model1 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_union-return_model2": { + "get": { + "summary": "No Response Model Annotation Union Return Model2", + "operationId": "no_response_model_annotation_union_return_model2_no_response_model_annotation_union_return_model2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response No Response Model Annotation Union Return Model2 No Response Model Annotation Union Return Model2 Get", + "anyOf": [ + {"$ref": "#/components/schemas/User"}, + {"$ref": "#/components/schemas/Item"}, + ], + } + } + }, + } + }, + } + }, + "/no_response_model-annotation_response_class": { + "get": { + "summary": "No Response Model Annotation Response Class", + "operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/no_response_model-annotation_json_response_class": { + "get": { + "summary": "No Response Model Annotation Json Response Class", + "operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, }, - "/no_response_model-annotation_response_class": { - "get": { - "summary": "No Response Model Annotation Response Class", - "operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - } - }, - "/no_response_model-annotation_json_response_class": { - "get": { - "summary": "No Response Model Annotation Json Response Class", - "operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } + "User": { + "title": "User", + "required": ["name", "surname"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "surname": {"title": "Surname", "type": "string"}, + }, }, } }, - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - }, - }, - "User": { - "title": "User", - "required": ["name", "surname"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "surname": {"title": "Surname", "type": "string"}, - }, - }, - } - }, - } + } + ) diff --git a/tests/test_response_model_sub_types.py b/tests/test_response_model_sub_types.py index 8036bcb07d..9c7096c5f0 100644 --- a/tests/test_response_model_sub_types.py +++ b/tests/test_response_model_sub_types.py @@ -1,5 +1,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel @@ -47,110 +48,114 @@ def test_path_operations(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/valid1": { - "get": { - "summary": "Valid1", - "operationId": "valid1_valid1_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid1 Valid1 Get", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/valid1": { + "get": { + "summary": "Valid1", + "operationId": "valid1_valid1_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid1 Valid1 Get", + "type": "integer", + } } - } + }, }, }, - }, - } - }, - "/valid2": { - "get": { - "summary": "Valid2", - "operationId": "valid2_valid2_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid2 Valid2 Get", - "type": "array", - "items": {"type": "integer"}, + } + }, + "/valid2": { + "get": { + "summary": "Valid2", + "operationId": "valid2_valid2_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid2 Valid2 Get", + "type": "array", + "items": {"type": "integer"}, + } } - } + }, }, }, - }, - } - }, - "/valid3": { - "get": { - "summary": "Valid3", - "operationId": "valid3_valid3_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Model"} - } + } + }, + "/valid3": { + "get": { + "summary": "Valid3", + "operationId": "valid3_valid3_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Model"} + } + }, }, }, - }, - } - }, - "/valid4": { - "get": { - "summary": "Valid4", - "operationId": "valid4_valid4_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "title": "Response 500 Valid4 Valid4 Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Model"}, + } + }, + "/valid4": { + "get": { + "summary": "Valid4", + "operationId": "valid4_valid4_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "title": "Response 500 Valid4 Valid4 Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Model" + }, + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "Model": { - "title": "Model", - "required": ["name"], - "type": "object", - "properties": {"name": {"title": "Name", "type": "string"}}, + "components": { + "schemas": { + "Model": { + "title": "Model", + "required": ["name"], + "type": "object", + "properties": {"name": {"title": "Name", "type": "string"}}, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index 8caf6ce7af..9ec41e7e84 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -4,6 +4,7 @@ import pytest from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, ConfigDict @@ -263,592 +264,596 @@ def test_openapi_schema(): client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/schema_extra/": { - "post": { - "summary": "Schema Extra", - "operationId": "schema_extra_schema_extra__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/schema_extra/": { + "post": { + "summary": "Schema Extra", + "operationId": "schema_extra_schema_extra__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - } - }, - "/example/": { - "post": { - "summary": "Example", - "operationId": "example_example__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "example": {"data": "Data in Body example"}, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/examples/": { - "post": { - "summary": "Examples", - "operationId": "examples_examples__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - "examples": [ - {"data": "Data in Body examples, example1"}, - {"data": "Data in Body examples, example2"}, - ], - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + } + }, + "/example/": { + "post": { + "summary": "Example", + "operationId": "example_example__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"}, + "example": {"data": "Data in Body example"}, } }, + "required": True, }, - }, - } - }, - "/example_examples/": { - "post": { - "summary": "Example Examples", - "operationId": "example_examples_example_examples__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - "examples": [ - {"data": "examples example_examples 1"}, - {"data": "examples example_examples 2"}, - ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "example": {"data": "Overridden example"}, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/examples/": { + "post": { + "summary": "Examples", + "operationId": "examples_examples__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", + "examples": [ + {"data": "Data in Body examples, example1"}, + {"data": "Data in Body examples, example2"}, + ], } } }, - }, - }, - } - }, - "/path_example/{item_id}": { - "get": { - "summary": "Path Example", - "operationId": "path_example_path_example__item_id__get", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "example": "item_1", - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/path_examples/{item_id}": { - "get": { - "summary": "Path Examples", - "operationId": "path_examples_path_examples__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "examples": ["item_1", "item_2"], - }, - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + } + }, + "/example_examples/": { + "post": { + "summary": "Example Examples", + "operationId": "example_examples_example_examples__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "$ref": "#/components/schemas/Item", + "examples": [ + {"data": "examples example_examples 1"}, + {"data": "examples example_examples 2"}, + ], + }, + "example": {"data": "Overridden example"}, } }, - }, - }, - } - }, - "/path_example_examples/{item_id}": { - "get": { - "summary": "Path Example Examples", - "operationId": "path_example_examples_path_example_examples__item_id__get", - "parameters": [ - { "required": True, - "schema": { - "title": "Item Id", - "type": "string", - "examples": ["item_1", "item_2"], - }, - "example": "item_overridden", - "name": "item_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_example/": { - "get": { - "summary": "Query Example", - "operationId": "query_example_query_example__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - }, - "example": "query1", - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/path_example/{item_id}": { + "get": { + "summary": "Path Example", + "operationId": "path_example_path_example__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "example": "item_1", + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_examples/": { - "get": { - "summary": "Query Examples", - "operationId": "query_examples_query_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["query1", "query2"], - }, - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/path_examples/{item_id}": { + "get": { + "summary": "Path Examples", + "operationId": "path_examples_path_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "examples": ["item_1", "item_2"], + }, + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/query_example_examples/": { - "get": { - "summary": "Query Example Examples", - "operationId": "query_example_examples_query_example_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["query1", "query2"], - }, - "example": "query_overridden", - "name": "data", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/path_example_examples/{item_id}": { + "get": { + "summary": "Path Example Examples", + "operationId": "path_example_examples_path_example_examples__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + "examples": ["item_1", "item_2"], + }, + "example": "item_overridden", + "name": "item_id", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_example/": { - "get": { - "summary": "Header Example", - "operationId": "header_example_header_example__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - }, - "example": "header1", - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/query_example/": { + "get": { + "summary": "Query Example", + "operationId": "query_example_query_example__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + }, + "example": "query1", + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_examples/": { - "get": { - "summary": "Header Examples", - "operationId": "header_examples_header_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["header1", "header2"], - }, - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/query_examples/": { + "get": { + "summary": "Query Examples", + "operationId": "query_examples_query_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["query1", "query2"], + }, + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/header_example_examples/": { - "get": { - "summary": "Header Example Examples", - "operationId": "header_example_examples_header_example_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["header1", "header2"], - }, - "example": "header_overridden", - "name": "data", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/query_example_examples/": { + "get": { + "summary": "Query Example Examples", + "operationId": "query_example_examples_query_example_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["query1", "query2"], + }, + "example": "query_overridden", + "name": "data", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_example/": { - "get": { - "summary": "Cookie Example", - "operationId": "cookie_example_cookie_example__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - }, - "example": "cookie1", - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/header_example/": { + "get": { + "summary": "Header Example", + "operationId": "header_example_header_example__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + }, + "example": "header1", + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/header_examples/": { + "get": { + "summary": "Header Examples", + "operationId": "header_examples_header_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["header1", "header2"], + }, + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_examples/": { - "get": { - "summary": "Cookie Examples", - "operationId": "cookie_examples_cookie_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["cookie1", "cookie2"], - }, - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/header_example_examples/": { + "get": { + "summary": "Header Example Examples", + "operationId": "header_example_examples_header_example_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["header1", "header2"], + }, + "example": "header_overridden", + "name": "data", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/cookie_example/": { + "get": { + "summary": "Cookie Example", + "operationId": "cookie_example_cookie_example__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + }, + "example": "cookie1", + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/cookie_example_examples/": { - "get": { - "summary": "Cookie Example Examples", - "operationId": "cookie_example_examples_cookie_example_examples__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Data", - "examples": ["cookie1", "cookie2"], - }, - "example": "cookie_overridden", - "name": "data", - "in": "cookie", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/cookie_examples/": { + "get": { + "summary": "Cookie Examples", + "operationId": "cookie_examples_cookie_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["cookie1", "cookie2"], + }, + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/cookie_example_examples/": { + "get": { + "summary": "Cookie Example Examples", + "operationId": "cookie_example_examples_cookie_example_examples__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Data", + "examples": ["cookie1", "cookie2"], + }, + "example": "cookie_overridden", + "name": "data", + "in": "cookie", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["data"], - "type": "object", - "properties": {"data": {"title": "Data", "type": "string"}}, - "example": {"data": "Data in schema_extra"}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "Item": { + "title": "Item", + "required": ["data"], + "type": "object", + "properties": {"data": {"title": "Data", "type": "string"}}, + "example": {"data": "Data in schema_extra"}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_security_api_key_cookie.py b/tests/test_security_api_key_cookie.py index 9bacfc56ec..e37e113b8e 100644 --- a/tests/test_security_api_key_cookie.py +++ b/tests/test_security_api_key_cookie.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyCookie from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,27 +42,29 @@ def test_openapi_schema(): client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} + } + }, + } + ) diff --git a/tests/test_security_api_key_cookie_description.py b/tests/test_security_api_key_cookie_description.py index d0cab324eb..b12dce4bf5 100644 --- a/tests/test_security_api_key_cookie_description.py +++ b/tests/test_security_api_key_cookie_description.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyCookie from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,32 +42,34 @@ def test_openapi_schema(): client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": { - "type": "apiKey", - "name": "key", - "in": "cookie", - "description": "An API Cookie Key", + }, + "components": { + "securitySchemes": { + "APIKeyCookie": { + "type": "apiKey", + "name": "key", + "in": "cookie", + "description": "An API Cookie Key", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_api_key_cookie_optional.py b/tests/test_security_api_key_cookie_optional.py index cb5590168d..7988d80443 100644 --- a/tests/test_security_api_key_cookie_optional.py +++ b/tests/test_security_api_key_cookie_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyCookie from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -47,27 +48,29 @@ def test_openapi_schema(): client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyCookie": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyCookie": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyCookie": {"type": "apiKey", "name": "key", "in": "cookie"} + } + }, + } + ) diff --git a/tests/test_security_api_key_header.py b/tests/test_security_api_key_header.py index 3e761b150b..a53a2a2279 100644 --- a/tests/test_security_api_key_header.py +++ b/tests/test_security_api_key_header.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyHeader from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,27 +42,29 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} + } + }, + } + ) diff --git a/tests/test_security_api_key_header_description.py b/tests/test_security_api_key_header_description.py index 38a1a88814..0052dbcfc4 100644 --- a/tests/test_security_api_key_header_description.py +++ b/tests/test_security_api_key_header_description.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyHeader from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,32 +42,34 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": { - "type": "apiKey", - "name": "key", - "in": "header", - "description": "An API Key Header", + }, + "components": { + "securitySchemes": { + "APIKeyHeader": { + "type": "apiKey", + "name": "key", + "in": "header", + "description": "An API Key Header", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_api_key_header_optional.py b/tests/test_security_api_key_header_optional.py index 6f9682a64f..51abd0bb96 100644 --- a/tests/test_security_api_key_header_optional.py +++ b/tests/test_security_api_key_header_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyHeader from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -46,27 +47,29 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyHeader": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyHeader": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyHeader": {"type": "apiKey", "name": "key", "in": "header"} + } + }, + } + ) diff --git a/tests/test_security_api_key_query.py b/tests/test_security_api_key_query.py index 11ed194689..c3cb855fc7 100644 --- a/tests/test_security_api_key_query.py +++ b/tests/test_security_api_key_query.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyQuery from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,27 +42,29 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} + } + }, + } + ) diff --git a/tests/test_security_api_key_query_description.py b/tests/test_security_api_key_query_description.py index 6587983261..f775a4feaa 100644 --- a/tests/test_security_api_key_query_description.py +++ b/tests/test_security_api_key_query_description.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyQuery from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -41,32 +42,34 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": { - "type": "apiKey", - "name": "key", - "in": "query", - "description": "API Key Query", + }, + "components": { + "securitySchemes": { + "APIKeyQuery": { + "type": "apiKey", + "name": "key", + "in": "query", + "description": "API Key Query", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_api_key_query_optional.py b/tests/test_security_api_key_query_optional.py index 4cc134bd49..26fbb9ee4f 100644 --- a/tests/test_security_api_key_query_optional.py +++ b/tests/test_security_api_key_query_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyQuery from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -46,27 +47,29 @@ def test_security_api_key_no_key(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"APIKeyQuery": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"APIKeyQuery": []}], + } } - } - }, - "components": { - "securitySchemes": { - "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} - } - }, - } + }, + "components": { + "securitySchemes": { + "APIKeyQuery": {"type": "apiKey", "name": "key", "in": "query"} + } + }, + } + ) diff --git a/tests/test_security_http_base.py b/tests/test_security_http_base.py index ac38ee718e..fff6f0ee54 100644 --- a/tests/test_security_http_base.py +++ b/tests/test_security_http_base.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -37,25 +38,27 @@ def test_security_http_base_no_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} + }, + } + ) diff --git a/tests/test_security_http_base_description.py b/tests/test_security_http_base_description.py index 791ea59f4d..b03636a619 100644 --- a/tests/test_security_http_base_description.py +++ b/tests/test_security_http_base_description.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -31,31 +32,33 @@ def test_security_http_base_no_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } } - } - }, - "components": { - "securitySchemes": { - "HTTPBase": { - "type": "http", - "scheme": "Other", - "description": "Other Security Scheme", + }, + "components": { + "securitySchemes": { + "HTTPBase": { + "type": "http", + "scheme": "Other", + "description": "Other Security Scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_http_base_optional.py b/tests/test_security_http_base_optional.py index dd4d76843a..612a7909fe 100644 --- a/tests/test_security_http_base_optional.py +++ b/tests/test_security_http_base_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -36,25 +37,27 @@ def test_security_http_base_no_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBase": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBase": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBase": {"type": "http", "scheme": "Other"}} + }, + } + ) diff --git a/tests/test_security_http_basic_optional.py b/tests/test_security_http_basic_optional.py index 7071f381a1..e94565c7bb 100644 --- a/tests/test_security_http_basic_optional.py +++ b/tests/test_security_http_basic_optional.py @@ -4,6 +4,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -53,25 +54,27 @@ def test_security_http_basic_non_basic_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } + ) diff --git a/tests/test_security_http_basic_realm.py b/tests/test_security_http_basic_realm.py index ec7371f90f..0e328cdd95 100644 --- a/tests/test_security_http_basic_realm.py +++ b/tests/test_security_http_basic_realm.py @@ -3,6 +3,7 @@ from base64 import b64encode from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -51,25 +52,27 @@ def test_security_http_basic_non_basic_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } + ) diff --git a/tests/test_security_http_basic_realm_description.py b/tests/test_security_http_basic_realm_description.py index a93d5fc86b..5423d9b8d0 100644 --- a/tests/test_security_http_basic_realm_description.py +++ b/tests/test_security_http_basic_realm_description.py @@ -3,6 +3,7 @@ from base64 import b64encode from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -51,31 +52,33 @@ def test_security_http_basic_non_basic_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } } - } - }, - "components": { - "securitySchemes": { - "HTTPBasic": { - "type": "http", - "scheme": "basic", - "description": "HTTPBasic scheme", + }, + "components": { + "securitySchemes": { + "HTTPBasic": { + "type": "http", + "scheme": "basic", + "description": "HTTPBasic scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_http_bearer.py b/tests/test_security_http_bearer.py index 961b42f4db..eb94ddc3d9 100644 --- a/tests/test_security_http_bearer.py +++ b/tests/test_security_http_bearer.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -38,25 +39,27 @@ def test_security_http_bearer_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} + }, + } + ) diff --git a/tests/test_security_http_bearer_description.py b/tests/test_security_http_bearer_description.py index e16994abce..47fc141079 100644 --- a/tests/test_security_http_bearer_description.py +++ b/tests/test_security_http_bearer_description.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -38,31 +39,33 @@ def test_security_http_bearer_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "HTTPBearer": { - "type": "http", - "scheme": "bearer", - "description": "HTTP Bearer token scheme", + }, + "components": { + "securitySchemes": { + "HTTPBearer": { + "type": "http", + "scheme": "bearer", + "description": "HTTP Bearer token scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_http_bearer_optional.py b/tests/test_security_http_bearer_optional.py index 943da2ee2e..b49a6593ec 100644 --- a/tests/test_security_http_bearer_optional.py +++ b/tests/test_security_http_bearer_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -42,25 +43,27 @@ def test_security_http_bearer_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBearer": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}} + }, + } + ) diff --git a/tests/test_security_http_digest.py b/tests/test_security_http_digest.py index 3fad4c7a56..345ae9c171 100644 --- a/tests/test_security_http_digest.py +++ b/tests/test_security_http_digest.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -40,25 +41,27 @@ def test_security_http_digest_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} + }, + } + ) diff --git a/tests/test_security_http_digest_description.py b/tests/test_security_http_digest_description.py index 319416a071..1219bd40e3 100644 --- a/tests/test_security_http_digest_description.py +++ b/tests/test_security_http_digest_description.py @@ -1,6 +1,7 @@ from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -40,31 +41,33 @@ def test_security_http_digest_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } } - } - }, - "components": { - "securitySchemes": { - "HTTPDigest": { - "type": "http", - "scheme": "digest", - "description": "HTTPDigest scheme", + }, + "components": { + "securitySchemes": { + "HTTPDigest": { + "type": "http", + "scheme": "digest", + "description": "HTTPDigest scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_http_digest_optional.py b/tests/test_security_http_digest_optional.py index 0d66f9c72e..97e62634d8 100644 --- a/tests/test_security_http_digest_optional.py +++ b/tests/test_security_http_digest_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -44,25 +45,27 @@ def test_security_http_digest_incorrect_scheme_credentials(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPDigest": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPDigest": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPDigest": {"type": "http", "scheme": "digest"}} + }, + } + ) diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index bff1226ad9..1c216e95d8 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -2,6 +2,7 @@ import pytest from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -148,124 +149,132 @@ def test_strict_login_correct_grant_type(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_login_post" } } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OAuth2": []}], - } + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OAuth2": []}], + } + }, }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "^password$", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": { - "title": "Client Id", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "client_secret": { - "title": "Client Secret", - "anyOf": [{"type": "string"}, {"type": "null"}], + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "^password$", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": { + "title": "Scope", + "type": "string", + "default": "", + }, + "client_id": { + "title": "Client Id", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "client_secret": { + "title": "Client Secret", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + } + }, }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - } - }, - }, - } + } + ) diff --git a/tests/test_security_oauth2_authorization_code_bearer.py b/tests/test_security_oauth2_authorization_code_bearer.py index 66f53ab00d..1ba577e9ff 100644 --- a/tests/test_security_oauth2_authorization_code_bearer.py +++ b/tests/test_security_oauth2_authorization_code_bearer.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import OAuth2AuthorizationCodeBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -46,36 +47,38 @@ def test_token_with_whitespaces(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2AuthorizationCodeBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2AuthorizationCodeBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OAuth2AuthorizationCodeBearer": { - "type": "oauth2", - "flows": { - "authorizationCode": { - "authorizationUrl": "authorize", - "tokenUrl": "token", - "scopes": {}, - } - }, + }, + "components": { + "securitySchemes": { + "OAuth2AuthorizationCodeBearer": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "authorize", + "tokenUrl": "token", + "scopes": {}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_oauth2_authorization_code_bearer_description.py b/tests/test_security_oauth2_authorization_code_bearer_description.py index 5386fbbd9d..73807c31a3 100644 --- a/tests/test_security_oauth2_authorization_code_bearer_description.py +++ b/tests/test_security_oauth2_authorization_code_bearer_description.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import OAuth2AuthorizationCodeBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -43,37 +44,39 @@ def test_token(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2AuthorizationCodeBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2AuthorizationCodeBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OAuth2AuthorizationCodeBearer": { - "type": "oauth2", - "flows": { - "authorizationCode": { - "authorizationUrl": "authorize", - "tokenUrl": "token", - "scopes": {}, - } - }, - "description": "OAuth2 Code Bearer", + }, + "components": { + "securitySchemes": { + "OAuth2AuthorizationCodeBearer": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "authorize", + "tokenUrl": "token", + "scopes": {}, + } + }, + "description": "OAuth2 Code Bearer", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index 5bcd5040fd..cb79afdb86 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -4,6 +4,7 @@ import pytest from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -151,124 +152,132 @@ def test_strict_login_correct_data(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_login_post" } } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2": []}], - } + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2": []}], + } + }, }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "^password$", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": { - "title": "Client Id", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "client_secret": { - "title": "Client Secret", - "anyOf": [{"type": "string"}, {"type": "null"}], + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "^password$", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": { + "title": "Scope", + "type": "string", + "default": "", + }, + "client_id": { + "title": "Client Id", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "client_secret": { + "title": "Client Secret", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + } + }, }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - } - }, - }, - } + } + ) diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index 0353ba4c27..b3fae37a17 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -4,6 +4,7 @@ import pytest from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -152,125 +153,133 @@ def test_strict_login_correct_correct_grant_type(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login_post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_login_post" } } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login_post" - } + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2": []}], - } + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2": []}], + } + }, }, - }, - "components": { - "schemas": { - "Body_login_login_post": { - "title": "Body_login_login_post", - "required": ["grant_type", "username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "pattern": "^password$", - "type": "string", - }, - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": { - "title": "Client Id", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "client_secret": { - "title": "Client Secret", - "anyOf": [{"type": "string"}, {"type": "null"}], + "components": { + "schemas": { + "Body_login_login_post": { + "title": "Body_login_login_post", + "required": ["grant_type", "username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "pattern": "^password$", + "type": "string", + }, + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "scope": { + "title": "Scope", + "type": "string", + "default": "", + }, + "client_id": { + "title": "Client Id", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "client_secret": { + "title": "Client Secret", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "password": { + "scopes": { + "read:users": "Read the users", + "write:users": "Create users", + }, + "tokenUrl": "token", + } + }, + "description": "OAuth2 security scheme", + } + }, }, - "securitySchemes": { - "OAuth2": { - "type": "oauth2", - "flows": { - "password": { - "scopes": { - "read:users": "Read the users", - "write:users": "Create users", - }, - "tokenUrl": "token", - } - }, - "description": "OAuth2 security scheme", - } - }, - }, - } + } + ) diff --git a/tests/test_security_oauth2_password_bearer_optional.py b/tests/test_security_oauth2_password_bearer_optional.py index 4c9362c3eb..01e2f65ed9 100644 --- a/tests/test_security_oauth2_password_bearer_optional.py +++ b/tests/test_security_oauth2_password_bearer_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import OAuth2PasswordBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -40,30 +41,32 @@ def test_incorrect_token(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2PasswordBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, + }, + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_oauth2_password_bearer_optional_description.py b/tests/test_security_oauth2_password_bearer_optional_description.py index 6e6ea846cd..fec8d03a7a 100644 --- a/tests/test_security_oauth2_password_bearer_optional_description.py +++ b/tests/test_security_oauth2_password_bearer_optional_description.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import OAuth2PasswordBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot app = FastAPI() @@ -44,31 +45,33 @@ def test_incorrect_token(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2PasswordBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, - "description": "OAuth2PasswordBearer security scheme", + }, + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "/token"}}, + "description": "OAuth2PasswordBearer security scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_openid_connect.py b/tests/test_security_openid_connect.py index c9a0a8db76..2c8bcd494e 100644 --- a/tests/test_security_openid_connect.py +++ b/tests/test_security_openid_connect.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -47,30 +48,32 @@ def test_security_oauth2_password_bearer_no_header(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": { - "type": "openIdConnect", - "openIdConnectUrl": "/openid", + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_openid_connect_description.py b/tests/test_security_openid_connect_description.py index d008cbc630..4f69c82ff9 100644 --- a/tests/test_security_openid_connect_description.py +++ b/tests/test_security_openid_connect_description.py @@ -1,6 +1,7 @@ from fastapi import Depends, FastAPI, Security from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -49,31 +50,33 @@ def test_security_oauth2_password_bearer_no_header(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": { - "type": "openIdConnect", - "openIdConnectUrl": "/openid", - "description": "OpenIdConnect security scheme", + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + "description": "OpenIdConnect security scheme", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_security_openid_connect_optional.py b/tests/test_security_openid_connect_optional.py index e817434b0d..ebaf394dc9 100644 --- a/tests/test_security_openid_connect_optional.py +++ b/tests/test_security_openid_connect_optional.py @@ -3,6 +3,7 @@ from typing import Optional from fastapi import Depends, FastAPI, Security from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -52,30 +53,32 @@ def test_security_oauth2_password_bearer_no_header(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"OpenIdConnect": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"OpenIdConnect": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OpenIdConnect": { - "type": "openIdConnect", - "openIdConnectUrl": "/openid", + }, + "components": { + "securitySchemes": { + "OpenIdConnect": { + "type": "openIdConnect", + "openIdConnectUrl": "/openid", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 2be37b8bb8..95c780c0d4 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, HTTPException from fastapi.testclient import TestClient +from inline_snapshot import snapshot from starlette.exceptions import HTTPException as StarletteHTTPException app = FastAPI() @@ -79,126 +80,130 @@ def test_no_body_status_code_with_detail_exception_handlers(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/http-no-body-statuscode-exception": { - "get": { - "operationId": "no_body_status_code_exception_http_no_body_statuscode_exception_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "No Body Status Code Exception", - } - }, - "/http-no-body-statuscode-with-detail-exception": { - "get": { - "operationId": "no_body_status_code_with_detail_exception_http_no_body_statuscode_with_detail_exception_get", - "responses": { - "200": { - "content": {"application/json": {"schema": {}}}, - "description": "Successful Response", - } - }, - "summary": "No Body Status Code With Detail Exception", - } - }, - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/http-no-body-statuscode-exception": { + "get": { + "operationId": "no_body_status_code_exception_http_no_body_statuscode_exception_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "No Body Status Code Exception", + } + }, + "/http-no-body-statuscode-with-detail-exception": { + "get": { + "operationId": "no_body_status_code_with_detail_exception_http_no_body_statuscode_with_detail_exception_get", + "responses": { + "200": { + "content": {"application/json": {"schema": {}}}, + "description": "Successful Response", + } + }, + "summary": "No Body Status Code With Detail Exception", + } + }, + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } - }, - "/starlette-items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, + "/starlette-items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Starlette Item", - "operationId": "read_starlette_item_starlette_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - } + "summary": "Read Starlette Item", + "operationId": "read_starlette_item_starlette_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } + }, }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index 442e709fb1..86dc4d00e2 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -2,6 +2,7 @@ from typing import Optional from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel, HttpUrl app = FastAPI() @@ -86,210 +87,222 @@ def test_get(): def test_openapi_schema(): with client: response = client.get("/openapi.json") - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/invoices/": { - "post": { - "summary": "Create Invoice", - "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', - "operationId": "create_invoice_invoices__post", - "parameters": [ - { - "required": False, - "schema": { - "title": "Callback Url", - "anyOf": [ - { - "type": "string", - "format": "uri", - "minLength": 1, - "maxLength": 2083, - }, - {"type": "null"}, - ], - }, - "name": "callback_url", - "in": "query", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Invoice"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/invoices/": { + "post": { + "summary": "Create Invoice", + "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', + "operationId": "create_invoice_invoices__post", + "parameters": [ + { + "required": False, + "schema": { + "title": "Callback Url", + "anyOf": [ + { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2083, + }, + {"type": "null"}, + ], + }, + "name": "callback_url", + "in": "query", } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Invoice" } } }, + "required": True, }, - }, - "callbacks": { - "event_callback": { - "{$callback_url}/events/{$request.body.title}": { - "get": { - "summary": "Event Callback", - "operationId": "event_callback__callback_url__events___request_body_title__get", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Event" - } - } - }, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": {"schema": {}} - }, - }, - "422": { - "description": "Validation Error", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "callbacks": { + "event_callback": { + "{$callback_url}/events/{$request.body.title}": { + "get": { + "summary": "Event Callback", + "operationId": "event_callback__callback_url__events___request_body_title__get", + "requestBody": { + "required": True, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Event" } } }, }, - }, - } - } - }, - "invoice_notification": { - "{$callback_url}/invoices/{$request.body.id}": { - "post": { - "summary": "Invoice Notification", - "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InvoiceEvent" - } - } + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - }, - "responses": { - "200": { - "description": "Successful Response", + } + } + }, + "invoice_notification": { + "{$callback_url}/invoices/{$request.body.id}": { + "post": { + "summary": "Invoice Notification", + "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", + "requestBody": { + "required": True, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InvoiceEventReceived" + "$ref": "#/components/schemas/InvoiceEvent" } } }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEventReceived" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } - } + }, }, - }, + } } - } - }, - "components": { - "schemas": { - "Event": { - "title": "Event", - "required": ["name", "total"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "total": {"title": "Total", "type": "number"}, + }, + "components": { + "schemas": { + "Event": { + "title": "Event", + "required": ["name", "total"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" + "Invoice": { + "title": "Invoice", + "required": ["id", "customer", "total"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "title": { + "title": "Title", + "anyOf": [{"type": "string"}, {"type": "null"}], }, - } + "customer": {"title": "Customer", "type": "string"}, + "total": {"title": "Total", "type": "number"}, + }, }, - }, - "Invoice": { - "title": "Invoice", - "required": ["id", "customer", "total"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "title": { - "title": "Title", - "anyOf": [{"type": "string"}, {"type": "null"}], + "InvoiceEvent": { + "title": "InvoiceEvent", + "required": ["description", "paid"], + "type": "object", + "properties": { + "description": { + "title": "Description", + "type": "string", + }, + "paid": {"title": "Paid", "type": "boolean"}, }, - "customer": {"title": "Customer", "type": "string"}, - "total": {"title": "Total", "type": "number"}, }, - }, - "InvoiceEvent": { - "title": "InvoiceEvent", - "required": ["description", "paid"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "paid": {"title": "Paid", "type": "boolean"}, + "InvoiceEventReceived": { + "title": "InvoiceEventReceived", + "required": ["ok"], + "type": "object", + "properties": {"ok": {"title": "Ok", "type": "boolean"}}, }, - }, - "InvoiceEventReceived": { - "title": "InvoiceEventReceived", - "required": ["ok"], - "type": "object", - "properties": {"ok": {"title": "Ok", "type": "boolean"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tuples.py b/tests/test_tuples.py index de9487df2a..265388587b 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -1,5 +1,6 @@ from fastapi import FastAPI, Form from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -83,189 +84,193 @@ def test_tuple_form_invalid(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/model-with-tuple/": { - "post": { - "summary": "Post Model With Tuple", - "operationId": "post_model_with_tuple_model_with_tuple__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/ItemGroup"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/model-with-tuple/": { + "post": { + "summary": "Post Model With Tuple", + "operationId": "post_model_with_tuple_model_with_tuple__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/ItemGroup"} } }, + "required": True, }, - }, - } - }, - "/tuple-of-models/": { - "post": { - "summary": "Post Tuple Of Models", - "operationId": "post_tuple_of_models_tuple_of_models__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Square", - "maxItems": 2, - "minItems": 2, - "type": "array", - "prefixItems": [ - {"$ref": "#/components/schemas/Coordinate"}, - {"$ref": "#/components/schemas/Coordinate"}, - ], - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/tuple-of-models/": { + "post": { + "summary": "Post Tuple Of Models", + "operationId": "post_tuple_of_models_tuple_of_models__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Square", + "maxItems": 2, + "minItems": 2, + "type": "array", + "prefixItems": [ + {"$ref": "#/components/schemas/Coordinate"}, + {"$ref": "#/components/schemas/Coordinate"}, + ], } } }, + "required": True, }, - }, - } - }, - "/tuple-form/": { - "post": { - "summary": "Hello", - "operationId": "hello_tuple_form__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_hello_tuple_form__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/tuple-form/": { + "post": { + "summary": "Hello", + "operationId": "hello_tuple_form__post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_hello_tuple_form__post" } } }, + "required": True, }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_hello_tuple_form__post": { - "title": "Body_hello_tuple_form__post", - "required": ["values"], - "type": "object", - "properties": { - "values": { - "title": "Values", - "maxItems": 2, - "minItems": 2, - "type": "array", - "prefixItems": [ - {"type": "integer"}, - {"type": "integer"}, - ], - } - }, - }, - "Coordinate": { - "title": "Coordinate", - "required": ["x", "y"], - "type": "object", - "properties": { - "x": {"title": "X", "type": "number"}, - "y": {"title": "Y", "type": "number"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } }, - "ItemGroup": { - "title": "ItemGroup", - "required": ["items"], - "type": "object", - "properties": { - "items": { - "title": "Items", - "type": "array", - "items": { + }, + "components": { + "schemas": { + "Body_hello_tuple_form__post": { + "title": "Body_hello_tuple_form__post", + "required": ["values"], + "type": "object", + "properties": { + "values": { + "title": "Values", "maxItems": 2, "minItems": 2, "type": "array", "prefixItems": [ - {"type": "string"}, - {"type": "string"}, + {"type": "integer"}, + {"type": "integer"}, ], - }, - } + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", + "Coordinate": { + "title": "Coordinate", + "required": ["x", "y"], + "type": "object", + "properties": { + "x": {"title": "X", "type": "number"}, + "y": {"title": "Y", "type": "number"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, + }, + "ItemGroup": { + "title": "ItemGroup", + "required": ["items"], + "type": "object", + "properties": { "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "title": "Items", + "type": "array", + "items": { + "maxItems": 2, + "minItems": 2, + "type": "array", + "prefixItems": [ + {"type": "string"}, + {"type": "string"}, + ], + }, + } + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index 78ccb84426..d8d9d4130b 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.additional_responses.tutorial001_py39 import app @@ -20,99 +21,107 @@ def test_path_operation_not_found(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Message"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + }, }, - }, - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "Message": { + "title": "Message", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, }, - }, - "Message": { - "title": "Message", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index cdab56d7a6..4fae59d222 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -4,6 +4,7 @@ import shutil import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from tests.utils import needs_py310 @@ -41,95 +42,99 @@ def test_path_operation_img(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Return the JSON item or an image.", - "content": { - "image/png": {}, - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Return the JSON item or an image.", + "content": { + "image/png": {}, + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + }, }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "anyOf": [{"type": "boolean"}, {"type": "null"}], - "title": "Img", + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "img", - "in": "query", - }, - ], + { + "required": False, + "schema": { + "anyOf": [{"type": "boolean"}, {"type": "null"}], + "title": "Img", + }, + "name": "img", + "in": "query", + }, + ], + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index fda786b398..e888819dfe 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.additional_responses.tutorial003_py39 import app @@ -20,103 +21,111 @@ def test_path_operation_not_found(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": { - "description": "The item was not found", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Message"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": { + "description": "The item was not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + }, }, - }, - "200": { - "description": "Item requested by ID", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "example": { - "id": "bar", - "value": "The bar tenders", - }, - } + "200": { + "description": "Item requested by ID", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "example": { + "id": "bar", + "value": "The bar tenders", + }, + } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, + }, + "Message": { + "title": "Message", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, }, - }, - "Message": { - "title": "Message", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index f36d3d79c2..9df326a5ce 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -4,6 +4,7 @@ import shutil import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from tests.utils import needs_py310 @@ -41,98 +42,102 @@ def test_path_operation_img(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "404": {"description": "Item not found"}, - "302": {"description": "The item was moved"}, - "403": {"description": "Not enough privileges"}, - "200": { - "description": "Successful Response", - "content": { - "image/png": {}, - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "404": {"description": "Item not found"}, + "302": {"description": "The item was moved"}, + "403": {"description": "Not enough privileges"}, + "200": { + "description": "Successful Response", + "content": { + "image/png": {}, + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + }, }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "anyOf": [{"type": "boolean"}, {"type": "null"}], - "title": "Img", + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "img", - "in": "query", - }, - ], + { + "required": False, + "schema": { + "anyOf": [{"type": "boolean"}, {"type": "null"}], + "title": "Img", + }, + "name": "img", + "in": "query", + }, + ], + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["id", "value"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "value": {"title": "Value", "type": "string"}, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["id", "value"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "value": {"title": "Value", "type": "string"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py index 00574b5b0f..31adaa56a6 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.behind_a_proxy.tutorial001_py39 import app @@ -14,22 +15,24 @@ def test_main(): def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - "servers": [{"url": "/api/v1"}], - } + }, + "servers": [{"url": "/api/v1"}], + } + ) diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py index 1a49c0dfeb..56e6f2f9d2 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.behind_a_proxy.tutorial002_py39 import app @@ -14,22 +15,24 @@ def test_main(): def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "summary": "Read Main", - "operationId": "read_main_app_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "summary": "Read Main", + "operationId": "read_main_app_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - "servers": [{"url": "/api/v1"}], - } + }, + "servers": [{"url": "/api/v1"}], + } + ) diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index f80563d142..18845e4702 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -269,334 +270,338 @@ def test_admin_invalid_header(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/users/me": { - "get": { - "tags": ["users"], - "summary": "Read User Me", - "operationId": "read_user_me_users_me_get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/users/me": { + "get": { + "tags": ["users"], + "summary": "Read User Me", + "operationId": "read_user_me_users_me_get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/users/{username}": { - "get": { - "tags": ["users"], - "summary": "Read User", - "operationId": "read_user_users__username__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Username", "type": "string"}, - "name": "username", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/users/{username}": { + "get": { + "tags": ["users"], + "summary": "Read User", + "operationId": "read_user_users__username__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Username", "type": "string"}, + "name": "username", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/items/{item_id}": { + "get": { + "tags": ["items"], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, }, - } - }, - "/items/{item_id}": { - "get": { - "tags": ["items"], - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "put": { + "tags": ["items", "custom"], + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "404": {"description": "Not found"}, + "403": {"description": "Operation forbidden"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, }, }, - "put": { - "tags": ["items", "custom"], - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "404": {"description": "Not found"}, - "403": {"description": "Operation forbidden"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "/admin/": { + "post": { + "tags": ["admin"], + "summary": "Update Admin", + "operationId": "update_admin_admin__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + }, + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "418": {"description": "I'm a teapot"}, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } }, - }, - "/admin/": { - "post": { - "tags": ["admin"], - "summary": "Update Admin", - "operationId": "update_admin_admin__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - }, - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "418": {"description": "I'm a teapot"}, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Token", "type": "string"}, + "name": "token", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Token", "type": "string"}, - "name": "token", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, }, } }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, - }, - }, - } - }, - } + } + ) diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 9a837483f2..c1877a72ef 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -3,6 +3,7 @@ from unittest.mock import patch import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -260,89 +261,93 @@ def test_other_exceptions(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body/test_tutorial002.py b/tests/test_tutorial/test_body/test_tutorial002.py index e8b23e8f61..94bf213e3f 100644 --- a/tests/test_tutorial/test_body/test_tutorial002.py +++ b/tests/test_tutorial/test_body/test_tutorial002.py @@ -3,6 +3,7 @@ from typing import Union import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -75,89 +76,93 @@ def test_post_with_no_data(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body/test_tutorial003.py b/tests/test_tutorial/test_body/test_tutorial003.py index 7b8b7ea89f..832c211f66 100644 --- a/tests/test_tutorial/test_body/test_tutorial003.py +++ b/tests/test_tutorial/test_body/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -74,100 +75,104 @@ def test_put_with_no_data(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body/test_tutorial004.py b/tests/test_tutorial/test_body/test_tutorial004.py index d78c760f5d..1019a168cf 100644 --- a/tests/test_tutorial/test_body/test_tutorial004.py +++ b/tests/test_tutorial/test_body/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -76,109 +77,113 @@ def test_put_with_no_data(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, }, - }, - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, - "name": "q", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index cb6da29085..0116dcb09c 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -74,113 +75,117 @@ def test_invalid_price(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" } } }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "The description of the item", - "anyOf": [ - {"maxLength": 300, "type": "string"}, - {"type": "null"}, - ], - }, - "price": { - "title": "Price", - "exclusiveMinimum": 0.0, - "type": "number", - "description": "The price must be greater than zero", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "The description of the item", + "anyOf": [ + {"maxLength": 300, "type": "string"}, + {"type": "null"}, + ], + }, + "price": { + "title": "Price", + "exclusiveMinimum": 0.0, + "type": "number", + "description": "The price must be greater than zero", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item"], - "type": "object", - "properties": {"item": {"$ref": "#/components/schemas/Item"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item"], + "type": "object", + "properties": {"item": {"$ref": "#/components/schemas/Item"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index a4f24627b0..2e8ba457be 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -67,116 +68,120 @@ def test_post_id_foo(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "maximum": 1000.0, + "minimum": 0.0, + "type": "integer", + }, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", + }, + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "anyOf": [ + {"$ref": "#/components/schemas/Item"}, + {"type": "null"}, + ], + "title": "Item", } } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "maximum": 1000.0, - "minimum": 0.0, - "type": "integer", - }, - "name": "item_id", - "in": "path", + } }, - { - "required": False, - "schema": { + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", }, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - {"$ref": "#/components/schemas/Item"}, - {"type": "null"}, - ], - "title": "Item", - } - } - } - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py index 155bda0c99..0c94e9dd1e 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -197,167 +198,169 @@ def test_post_id_foo(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/items/{item_id}": { - "put": { - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", - }, - }, - ], - "requestBody": { - "content": { - "application/json": { + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/items/{item_id}": { + "put": { + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put", + "title": "Item Id", + "type": "integer", }, }, - }, - "required": True, - }, - "responses": { - "200": { + ], + "requestBody": { "content": { "application/json": { - "schema": {}, + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put", + }, }, }, - "description": "Successful Response", + "required": True, }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, + }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Update Item", }, - "summary": "Update Item", }, }, - }, - "components": { - "schemas": { - "Body_update_item_items__item_id__put": { - "properties": { - "item": { - "$ref": "#/components/schemas/Item", - }, - "user": { - "$ref": "#/components/schemas/User", + "components": { + "schemas": { + "Body_update_item_items__item_id__put": { + "properties": { + "item": { + "$ref": "#/components/schemas/Item", + }, + "user": { + "$ref": "#/components/schemas/User", + }, }, + "required": [ + "item", + "user", + ], + "title": "Body_update_item_items__item_id__put", + "type": "object", }, - "required": [ - "item", - "user", - ], - "title": "Body_update_item_items__item_id__put", - "type": "object", - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "User": { - "properties": { - "username": { - "title": "Username", - "type": "string", - }, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + "User": { + "properties": { + "username": { + "title": "Username", + "type": "string", + }, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, + "required": [ + "username", + ], + "title": "User", + "type": "object", }, - "required": [ - "username", - ], - "title": "User", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index 2f403797fe..c27f3d5ba8 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -102,121 +103,125 @@ def test_post_body_empty_list(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" } } }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": {"title": "Importance", "type": "integer"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py index 506e55eebc..2a39f3d713 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -159,134 +160,138 @@ def test_put_invalid_importance(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + }, + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", + }, + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_update_item_items__item_id__put" } } }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", }, - { - "required": False, - "schema": { + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", }, - "name": "q", - "in": "query", - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": { - "title": "Importance", - "type": "integer", - "exclusiveMinimum": 0.0, + "Body_update_item_items__item_id__put": { + "title": "Body_update_item_items__item_id__put", + "required": ["item", "user", "importance"], + "type": "object", + "properties": { + "item": {"$ref": "#/components/schemas/Item"}, + "user": {"$ref": "#/components/schemas/User"}, + "importance": { + "title": "Importance", + "type": "integer", + "exclusiveMinimum": 0.0, + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py index 20859d12c8..d600e0767d 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -131,144 +132,146 @@ def test_post_missing_required_field_in_item(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/items/{item_id}": { - "put": { - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", - }, - }, - ], - "requestBody": { - "content": { - "application/json": { + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/items/{item_id}": { + "put": { + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put", + "title": "Item Id", + "type": "integer", }, }, - }, - "required": True, - }, - "responses": { - "200": { + ], + "requestBody": { "content": { "application/json": { - "schema": {}, + "schema": { + "$ref": "#/components/schemas/Body_update_item_items__item_id__put", + }, }, }, - "description": "Successful Response", + "required": True, }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, }, }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, + }, + }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Update Item", }, - "summary": "Update Item", }, }, - }, - "components": { - "schemas": { - "Body_update_item_items__item_id__put": { - "properties": { - "item": { - "$ref": "#/components/schemas/Item", + "components": { + "schemas": { + "Body_update_item_items__item_id__put": { + "properties": { + "item": { + "$ref": "#/components/schemas/Item", + }, }, + "required": ["item"], + "title": "Body_update_item_items__item_id__put", + "type": "object", }, - "required": ["item"], - "title": "Body_update_item_items__item_id__put", - "type": "object", - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py index ae494350b3..78e5e53a20 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -142,112 +143,116 @@ def test_openapi_schema(client: TestClient, mod_name: str): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", } } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "components": { + "schemas": { + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": tags_schema, }, - "tags": tags_schema, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py index c1410330c4..6a70779b68 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -139,139 +140,143 @@ def test_put_missing_required_in_image(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", } } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Image": { - "properties": { - "url": { - "title": "Url", - "type": "string", - }, - "name": { - "title": "Name", - "type": "string", + }, + "components": { + "schemas": { + "Image": { + "properties": { + "url": { + "title": "Url", + "type": "string", + }, + "name": { + "title": "Name", + "type": "string", + }, }, + "required": ["url", "name"], + "title": "Image", + "type": "object", }, - "required": ["url", "name"], - "title": "Image", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "default": [], - "type": "array", - "items": {"type": "string"}, - "uniqueItems": True, - }, - "image": { - "anyOf": [ - {"$ref": "#/components/schemas/Image"}, - {"type": "null"}, - ], + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "default": [], + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + }, + "image": { + "anyOf": [ + {"$ref": "#/components/schemas/Image"}, + {"type": "null"}, + ], + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py index c09e0c1b10..2ff3d4f220 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -162,142 +163,146 @@ def test_put_wrong_url(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", } } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Image": { - "properties": { - "url": { - "title": "Url", - "type": "string", - "format": "uri", - "maxLength": 2083, - "minLength": 1, - }, - "name": { - "title": "Name", - "type": "string", + }, + "components": { + "schemas": { + "Image": { + "properties": { + "url": { + "title": "Url", + "type": "string", + "format": "uri", + "maxLength": 2083, + "minLength": 1, + }, + "name": { + "title": "Name", + "type": "string", + }, }, + "required": ["url", "name"], + "title": "Image", + "type": "object", }, - "required": ["url", "name"], - "title": "Image", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "default": [], - "type": "array", - "items": {"type": "string"}, - "uniqueItems": True, - }, - "image": { - "anyOf": [ - {"$ref": "#/components/schemas/Image"}, - {"type": "null"}, - ], + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "default": [], + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + }, + "image": { + "anyOf": [ + {"$ref": "#/components/schemas/Image"}, + {"type": "null"}, + ], + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py index f26c50167b..229216fc58 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -122,150 +123,154 @@ def test_put_images_not_list(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", } } }, + "required": True, }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Image": { - "properties": { - "url": { - "title": "Url", - "type": "string", - "format": "uri", - "maxLength": 2083, - "minLength": 1, - }, - "name": { - "title": "Name", - "type": "string", + }, + "components": { + "schemas": { + "Image": { + "properties": { + "url": { + "title": "Url", + "type": "string", + "format": "uri", + "maxLength": 2083, + "minLength": 1, + }, + "name": { + "title": "Name", + "type": "string", + }, }, + "required": ["url", "name"], + "title": "Image", + "type": "object", }, - "required": ["url", "name"], - "title": "Image", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "default": [], - "type": "array", - "items": {"type": "string"}, - "uniqueItems": True, - }, - "images": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/Image", + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "default": [], + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + }, + "images": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/Image", + }, + "type": "array", }, - "type": "array", - }, - { - "type": "null", - }, - ], - "title": "Images", + { + "type": "null", + }, + ], + "title": "Images", + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py index dac168e242..5a7763f598 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -184,163 +185,167 @@ def test_put_missing_required_in_images(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/offers/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/offers/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Offer", + "operationId": "create_offer_offers__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Offer", } } }, + "required": True, }, - }, - "summary": "Create Offer", - "operationId": "create_offer_offers__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Offer", - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Image": { - "properties": { - "url": { - "title": "Url", - "type": "string", - "format": "uri", - "maxLength": 2083, - "minLength": 1, - }, - "name": { - "title": "Name", - "type": "string", + }, + "components": { + "schemas": { + "Image": { + "properties": { + "url": { + "title": "Url", + "type": "string", + "format": "uri", + "maxLength": 2083, + "minLength": 1, + }, + "name": { + "title": "Name", + "type": "string", + }, }, + "required": ["url", "name"], + "title": "Image", + "type": "object", }, - "required": ["url", "name"], - "title": "Image", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "default": [], - "type": "array", - "items": {"type": "string"}, - "uniqueItems": True, - }, - "images": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/Image", + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "default": [], + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + }, + "images": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/Image", + }, + "type": "array", }, - "type": "array", - }, - { - "type": "null", - }, - ], - "title": "Images", + { + "type": "null", + }, + ], + "title": "Images", + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "Offer": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": { - "title": "Price", - "type": "number", - }, - "items": { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "Offer": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "type": "number", + }, + "items": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + }, }, + "required": ["name", "price", "items"], + "title": "Offer", + "type": "object", }, - "required": ["name", "price", "items"], - "title": "Offer", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py index 2101b7bbe5..26f48f1d5f 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -66,94 +67,98 @@ def test_post_not_a_list(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/images/multiple/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/images/multiple/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Multiple Images", + "operationId": "create_multiple_images_images_multiple__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Images", + "type": "array", + "items": {"$ref": "#/components/schemas/Image"}, } } }, + "required": True, }, - }, - "summary": "Create Multiple Images", - "operationId": "create_multiple_images_images_multiple__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Images", - "type": "array", - "items": {"$ref": "#/components/schemas/Image"}, - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Image": { - "properties": { - "url": { - "title": "Url", - "type": "string", - "format": "uri", - "maxLength": 2083, - "minLength": 1, - }, - "name": { - "title": "Name", - "type": "string", + }, + "components": { + "schemas": { + "Image": { + "properties": { + "url": { + "title": "Url", + "type": "string", + "format": "uri", + "maxLength": 2083, + "minLength": 1, + }, + "name": { + "title": "Name", + "type": "string", + }, }, + "required": ["url", "name"], + "title": "Image", + "type": "object", }, - "required": ["url", "name"], - "title": "Image", - "type": "object", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index f7481a5f7f..492dcecd2b 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -43,76 +44,80 @@ def test_post_invalid_body(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/index-weights/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/index-weights/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Index Weights", + "operationId": "create_index_weights_index_weights__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Weights", + "type": "object", + "additionalProperties": {"type": "number"}, } } }, + "required": True, }, - }, - "summary": "Create Index Weights", - "operationId": "create_index_weights_index_weights__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Weights", - "type": "object", - "additionalProperties": {"type": "number"}, - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index 9c6a90576c..feb07b8595 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -48,141 +49,145 @@ def test_put(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } }, - "required": True, }, - }, - } - }, - "components": { - "schemas": { - "Item": { - "type": "object", - "title": "Item", - "properties": { - "name": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Name", - }, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", - }, - "price": { - "anyOf": [{"type": "number"}, {"type": "null"}], - "title": "Price", - }, - "tax": {"title": "Tax", "type": "number", "default": 10.5}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], + } + }, + "components": { + "schemas": { + "Item": { + "type": "object", + "title": "Item", + "properties": { + "name": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Name", + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Price", + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_body_updates/test_tutorial002.py b/tests/test_tutorial/test_body_updates/test_tutorial002.py index 7d79cf5e63..a34d08b52b 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial002.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -69,141 +70,145 @@ def test_patch_name(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - }, - "patch": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + "patch": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Update Item", + "operationId": "update_item_items__item_id__patch", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__patch", - "parameters": [ - { "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } }, - "required": True, }, - }, - } - }, - "components": { - "schemas": { - "Item": { - "type": "object", - "title": "Item", - "properties": { - "name": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Name", - }, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", - }, - "price": { - "anyOf": [{"type": "number"}, {"type": "null"}], - "title": "Price", - }, - "tax": {"title": "Tax", "type": "number", "default": 10.5}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], + } + }, + "components": { + "schemas": { + "Item": { + "type": "object", + "title": "Item", + "properties": { + "name": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Name", + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Price", + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py index ddc282d85e..644b82ad9a 100644 --- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py @@ -1,6 +1,7 @@ import importlib from fastapi.testclient import TestClient +from inline_snapshot import snapshot def get_client() -> TestClient: @@ -38,21 +39,23 @@ def test_default_openapi(): response = client.get("/redoc") assert response.status_code == 200, response.text response = client.get("/openapi.json") - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index ab71148764..4d7adf0d60 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -3,6 +3,7 @@ from types import ModuleType import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -47,75 +48,79 @@ def test_openapi_schema(mod: ModuleType): client = TestClient(mod.app) response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Ads Id", - }, - "name": "ads_id", - "in": "cookie", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Ads Id", + }, + "name": "ads_id", + "in": "cookie", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index f1d2accef2..20244bef45 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -26,21 +27,23 @@ def test_get_custom_response(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index 3337f47d5f..746801df16 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.custom_response.tutorial001b_py39 import app @@ -14,21 +15,23 @@ def test_get_custom_response(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py index 22e2e02540..f79d38b831 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -48,21 +49,23 @@ def test_openapi_schema(client: TestClient, mod_name: str): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": response_content, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": response_content, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py index fea105c28e..b4919af6c3 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial005.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial005.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.custom_response.tutorial005_py39 import app @@ -14,21 +15,25 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Main", - "operationId": "main__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"text/plain": {"schema": {"type": "string"}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Main", + "operationId": "main__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": {"schema": {"type": "string"}} + }, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py index e9e6ca1086..ea2d366aa0 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.custom_response.tutorial006_py39 import app @@ -14,21 +15,23 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/typer": { - "get": { - "summary": "Redirect Typer", - "operationId": "redirect_typer_typer_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/typer": { + "get": { + "summary": "Redirect Typer", + "operationId": "redirect_typer_typer_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py index 7ca727d2cd..133a591b16 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.custom_response.tutorial006b_py39 import app @@ -14,16 +15,18 @@ def test_redirect_response_class(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/fastapi": { - "get": { - "summary": "Redirect Fastapi", - "operationId": "redirect_fastapi_fastapi_get", - "responses": {"307": {"description": "Successful Response"}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/fastapi": { + "get": { + "summary": "Redirect Fastapi", + "operationId": "redirect_fastapi_fastapi_get", + "responses": {"307": {"description": "Successful Response"}}, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py index e3f76c8403..5b17d815d0 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.custom_response.tutorial006c_py39 import app @@ -14,16 +15,18 @@ def test_redirect_status_code(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/pydantic": { - "get": { - "summary": "Redirect Pydantic", - "operationId": "redirect_pydantic_pydantic_get", - "responses": {"302": {"description": "Successful Response"}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/pydantic": { + "get": { + "summary": "Redirect Pydantic", + "operationId": "redirect_pydantic_pydantic_get", + "responses": {"302": {"description": "Successful Response"}}, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index 756eacf233..a3d2cf5152 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from tests.utils import needs_py310 @@ -50,89 +51,93 @@ def test_post_invalid_item(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index de63a94766..e023271bc3 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -70,135 +71,141 @@ def test_get_authors(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/authors/{author_id}/items/": { - "post": { - "summary": "Create Author Items", - "operationId": "create_author_items_authors__author_id__items__post", - "parameters": [ - { - "required": True, - "schema": {"title": "Author Id", "type": "string"}, - "name": "author_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/authors/{author_id}/items/": { + "post": { + "summary": "Create Author Items", + "operationId": "create_author_items_authors__author_id__items__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Author Id", "type": "string"}, + "name": "author_id", + "in": "path", } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Author"} - } - }, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, } } }, + "required": True, }, - }, - } - }, - "/authors/": { - "get": { - "summary": "Get Authors", - "operationId": "get_authors_authors__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Get Authors Authors Get", - "type": "array", - "items": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/Author" - }, + } } - } + }, }, - } - }, - } + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/authors/": { + "get": { + "summary": "Get Authors", + "operationId": "get_authors_authors__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Get Authors Authors Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Author" + }, + } + } + }, + } + }, + } + }, }, - }, - "components": { - "schemas": { - "Author": { - "title": "Author", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "items": { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "components": { + "schemas": { + "Author": { + "title": "Author", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "items": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + }, }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", + "Item": { + "title": "Item", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_debugging/test_tutorial001.py b/tests/test_tutorial/test_debugging/test_tutorial001.py index cf62c3b194..1a0ca6cad7 100644 --- a/tests/test_tutorial/test_debugging/test_tutorial001.py +++ b/tests/test_tutorial/test_debugging/test_tutorial001.py @@ -5,6 +5,7 @@ import unittest import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot MOD_NAME = "docs_src.debugging.tutorial001_py39" @@ -44,21 +45,23 @@ def test_uvicorn_run_called_when_run_as_main(): # Just for coverage def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "summary": "Root", - "operationId": "root__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Root", + "operationId": "root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, }, - }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py index 15919c63f7..74f4a8f3a2 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -43,148 +44,152 @@ def test_get(path, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Skip", - "type": "integer", - "default": 0, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", }, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "type": "integer", - "default": 100, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", }, - "name": "limit", - "in": "query", - }, - ], - } - }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + ], + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Skip", - "type": "integer", - "default": 0, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", }, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "type": "integer", - "default": 100, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", }, - "name": "limit", - "in": "query", - }, - ], - } + ], + } + }, }, - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py index 96300a2599..6e1cea5a08 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -87,95 +88,99 @@ def test_get(path, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Skip", - "type": "integer", - "default": 0, + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", }, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "type": "integer", - "default": 100, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 100, + }, + "name": "limit", + "in": "query", }, - "name": "limit", - "in": "query", - }, - ], + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial005.py b/tests/test_tutorial/test_dependencies/test_tutorial005.py index e595859cb8..31054744a1 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial005.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -58,84 +59,88 @@ def test_get(path, cookie, expected_status, expected_response, client: TestClien def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Query", - "operationId": "read_query_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Q", + "summary": "Read Query", + "operationId": "read_query_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Last Query", + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Last Query", + }, + "name": "last_query", + "in": "cookie", }, - "name": "last_query", - "in": "cookie", - }, - ], + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index cdea27b7c0..8d6cfa2d65 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -68,78 +69,82 @@ def test_get_valid_headers(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial011.py b/tests/test_tutorial/test_dependencies/test_tutorial011.py index 3374c54b5e..383422a7e6 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial011.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial011.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -47,76 +48,80 @@ def test_get(path, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/query-checker/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/query-checker/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Query Check", - "operationId": "read_query_check_query_checker__get", - "parameters": [ - { - "required": False, - "schema": { - "type": "string", - "default": "", - "title": "Q", + "summary": "Read Query Check", + "operationId": "read_query_check_query_checker__get", + "parameters": [ + { + "required": False, + "schema": { + "type": "string", + "default": "", + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - ], + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index f342ff842e..a156889245 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -115,114 +116,118 @@ def test_get_valid_headers_users(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } - }, - "/users/": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__get", - "parameters": [ - { - "required": True, - "schema": {"title": "X-Token", "type": "string"}, - "name": "x-token", - "in": "header", - }, - { - "required": True, - "schema": {"title": "X-Key", "type": "string"}, - "name": "x-key", - "in": "header", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + } + }, + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "parameters": [ + { + "required": True, + "schema": {"title": "X-Token", "type": "string"}, + "name": "x-token", + "in": "header", + }, + { + "required": True, + "schema": {"title": "X-Key", "type": "string"}, + "name": "x-key", + "in": "header", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_encoder/test_tutorial001.py b/tests/test_tutorial/test_encoder/test_tutorial001.py index 5a4edbc66e..a3d6723336 100644 --- a/tests/test_tutorial/test_encoder/test_tutorial001.py +++ b/tests/test_tutorial/test_encoder/test_tutorial001.py @@ -3,6 +3,7 @@ from types import ModuleType import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -73,138 +74,140 @@ def test_put_invalid_data(client: TestClient, mod: ModuleType): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{id}": { - "put": { - "operationId": "update_item_items__id__put", - "parameters": [ - { - "in": "path", - "name": "id", - "required": True, - "schema": { - "title": "Id", - "type": "string", - }, - }, - ], - "requestBody": { - "content": { - "application/json": { + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{id}": { + "put": { + "operationId": "update_item_items__id__put", + "parameters": [ + { + "in": "path", + "name": "id", + "required": True, "schema": { - "$ref": "#/components/schemas/Item", + "title": "Id", + "type": "string", }, }, - }, - "required": True, - }, - "responses": { - "200": { + ], + "requestBody": { "content": { "application/json": { - "schema": {}, + "schema": { + "$ref": "#/components/schemas/Item", + }, }, }, - "description": "Successful Response", + "required": True, }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, }, }, + "description": "Successful Response", }, - "description": "Validation Error", - }, - }, - "summary": "Update Item", - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, + }, + }, + "description": "Validation Error", }, - "title": "Detail", - "type": "array", }, + "summary": "Update Item", }, - "title": "HTTPValidationError", - "type": "object", }, - "Item": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", }, - ], - "title": "Description", - }, - "timestamp": { - "format": "date-time", - "title": "Timestamp", - "type": "string", - }, - "title": { - "title": "Title", - "type": "string", + "title": "Detail", + "type": "array", + }, }, + "title": "HTTPValidationError", + "type": "object", }, - "required": [ - "title", - "timestamp", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { + "Item": { + "properties": { + "description": { "anyOf": [ { "type": "string", }, { - "type": "integer", + "type": "null", }, ], + "title": "Description", + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string", + }, + "title": { + "title": "Title", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", }, - "type": { - "title": "Error Type", - "type": "string", + "required": [ + "title", + "timestamp", + ], + "title": "Item", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", + }, }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index 48b838d5a0..63215c00db 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -1,6 +1,7 @@ import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture(name="app", scope="module") @@ -21,74 +22,79 @@ def test_openapi_schema(app: FastAPI): with TestClient(app) as client: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_events/test_tutorial002.py b/tests/test_tutorial/test_events/test_tutorial002.py index 0612899b55..f98d8921f7 100644 --- a/tests/test_tutorial/test_events/test_tutorial002.py +++ b/tests/test_tutorial/test_events/test_tutorial002.py @@ -1,6 +1,7 @@ import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture(name="app", scope="module") @@ -23,21 +24,23 @@ def test_openapi_schema(app: FastAPI): with TestClient(app) as client: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py index aed9def7ae..4fc848e116 100644 --- a/tests/test_tutorial/test_events/test_tutorial003.py +++ b/tests/test_tutorial/test_events/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.events.tutorial003_py39 import ( app, @@ -21,74 +22,79 @@ def test_openapi_schema(): with TestClient(app) as client: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/predict": { - "get": { - "summary": "Predict", - "operationId": "predict_predict_get", - "parameters": [ - { - "required": True, - "schema": {"title": "X", "type": "number"}, - "name": "x", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/predict": { + "get": { + "summary": "Predict", + "operationId": "predict_predict_get", + "parameters": [ + { + "required": True, + "schema": {"title": "X", "type": "number"}, + "name": "x", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py index 83ecb300ee..bc10c888c1 100644 --- a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.extending_openapi.tutorial001_py39 import app @@ -14,32 +15,34 @@ def test(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "Custom title", - "summary": "This is a very custom OpenAPI schema", - "description": "Here's a longer description of the custom **OpenAPI** schema", - "version": "2.5.0", - "x-logo": { - "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "Custom title", + "summary": "This is a very custom OpenAPI schema", + "description": "Here's a longer description of the custom **OpenAPI** schema", + "version": "2.5.0", + "x-logo": { + "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" + }, }, - }, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - } + }, + } + ) openapi_schema = response.json() # Request again to test the custom cache response = client.get("/openapi.json") diff --git a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py index 9981699862..4248878b5a 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -44,115 +45,119 @@ def test_post(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/user/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserOut", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/user/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserOut", + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create User", + "operationId": "create_user_user__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/UserIn"} } }, + "required": True, }, - }, - "summary": "Create User", - "operationId": "create_user_user__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/UserIn"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "UserIn": { - "title": "UserIn", - "required": IsList( - "username", "password", "email", check_order=False - ), - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "email": { - "title": "Email", - "type": "string", - "format": "email", - }, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "components": { + "schemas": { + "UserIn": { + "title": "UserIn", + "required": IsList( + "username", "password", "email", check_order=False + ), + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "email": { + "title": "Email", + "type": "string", + "format": "email", + }, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "UserOut": { - "title": "UserOut", - "required": ["username", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": { - "title": "Email", - "type": "string", - "format": "email", - }, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + "UserOut": { + "title": "UserOut", + "required": ["username", "email"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "email": { + "title": "Email", + "type": "string", + "format": "email", + }, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004.py b/tests/test_tutorial/test_extra_models/test_tutorial004.py index 073375ccc9..c64371e3be 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -29,42 +30,46 @@ def test_get_items(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Items Items Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Items Items Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } - }, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", + }, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "description"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": {"title": "Description", "type": "string"}, - }, + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "description"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py index 8e52d8d4ba..43b8bae8e5 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -26,29 +27,31 @@ def test_get_items(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/keyword-weights/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Keyword Weights Keyword Weights Get", - "type": "object", - "additionalProperties": {"type": "number"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/keyword-weights/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Read Keyword Weights Keyword Weights Get", + "type": "object", + "additionalProperties": {"type": "number"}, + } } - } - }, - } - }, - "summary": "Read Keyword Weights", - "operationId": "read_keyword_weights_keyword_weights__get", + }, + } + }, + "summary": "Read Keyword Weights", + "operationId": "read_keyword_weights_keyword_weights__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py index aa65218cde..5457ad132a 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -33,21 +34,23 @@ def test_get_path(client: TestClient, path, expected_status, expected_response): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Root", - "operationId": "root__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Root", + "operationId": "root__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial001.py b/tests/test_tutorial/test_generate_clients/test_tutorial001.py index 83ae38c5b5..62799d259b 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial001.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -34,111 +35,119 @@ def test_get_items(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Get Items Items Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Get Items Items Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } - }, - } - }, - }, - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ResponseMessage": { - "title": "ResponseMessage", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ResponseMessage": { + "title": "ResponseMessage", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial002.py b/tests/test_tutorial/test_generate_clients/test_tutorial002.py index b9255325aa..f64f5f8666 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial002.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.generate_clients.tutorial002_py39 import app @@ -31,159 +32,167 @@ def test_get_items(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Get Items Items Get", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Get Items Items Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } - }, - } - }, - }, - "post": { - "tags": ["items"], - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "tags": ["items"], + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, - }, - "/users/": { - "post": { - "tags": ["users"], - "summary": "Create User", - "operationId": "create_user_users__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + "/users/": { + "post": { + "tags": ["users"], + "summary": "Create User", + "operationId": "create_user_users__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/User"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ResponseMessage": { - "title": "ResponseMessage", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "User": { - "title": "User", - "required": ["username", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": {"title": "Email", "type": "string"}, + "ResponseMessage": { + "title": "ResponseMessage", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "User": { + "title": "User", + "required": ["username", "email"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "email": {"title": "Email", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index d054845879..34ede61946 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.generate_clients.tutorial003_py39 import app @@ -31,159 +32,167 @@ def test_get_items(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "items-get_items", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Items-Get Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "items-get_items", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Items-Get Items", + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + } } - } - }, - } - }, - }, - "post": { - "tags": ["items"], - "summary": "Create Item", - "operationId": "items-create_item", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "tags": ["items"], + "summary": "Create Item", + "operationId": "items-create_item", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, - }, - "/users/": { - "post": { - "tags": ["users"], - "summary": "Create User", - "operationId": "users-create_user", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + "/users/": { + "post": { + "tags": ["users"], + "summary": "Create User", + "operationId": "users-create_user", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ResponseMessage" - } + "schema": {"$ref": "#/components/schemas/User"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, - } + } + }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + }, }, - }, - "ResponseMessage": { - "title": "ResponseMessage", - "required": ["message"], - "type": "object", - "properties": {"message": {"title": "Message", "type": "string"}}, - }, - "User": { - "title": "User", - "required": ["username", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": {"title": "Email", "type": "string"}, + "ResponseMessage": { + "title": "ResponseMessage", + "required": ["message"], + "type": "object", + "properties": { + "message": {"title": "Message", "type": "string"} + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "User": { + "title": "User", + "required": ["username", "email"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "email": {"title": "Email", "type": "string"}, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial004.py b/tests/test_tutorial/test_generate_clients/test_tutorial004.py index eea60e3428..d04bfbfe87 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial004.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial004.py @@ -3,6 +3,8 @@ import json import pathlib from unittest.mock import patch +from inline_snapshot import snapshot + from docs_src.generate_clients import tutorial003_py39 @@ -15,218 +17,220 @@ def test_remove_tags(tmp_path: pathlib.Path): importlib.import_module("docs_src.generate_clients.tutorial004_py39") modified_openapi = json.loads(tmp_file.read_text()) - assert modified_openapi == { - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", - }, - "title": "Detail", - "type": "array", - }, - }, - "title": "HTTPValidationError", - "type": "object", - }, - "Item": { - "properties": { - "name": { - "title": "Name", - "type": "string", - }, - "price": { - "title": "Price", - "type": "number", + assert modified_openapi == snapshot( + { + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", + }, }, + "title": "HTTPValidationError", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ResponseMessage": { - "properties": { - "message": { - "title": "Message", - "type": "string", + "Item": { + "properties": { + "name": { + "title": "Name", + "type": "string", + }, + "price": { + "title": "Price", + "type": "number", + }, }, + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", }, - "required": [ - "message", - ], - "title": "ResponseMessage", - "type": "object", - }, - "User": { - "properties": { - "email": { - "title": "Email", - "type": "string", - }, - "username": { - "title": "Username", - "type": "string", + "ResponseMessage": { + "properties": { + "message": { + "title": "Message", + "type": "string", + }, }, + "required": [ + "message", + ], + "title": "ResponseMessage", + "type": "object", }, - "required": [ - "username", - "email", - ], - "title": "User", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "User": { + "properties": { + "email": { + "title": "Email", + "type": "string", + }, + "username": { + "title": "Username", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "username", + "email", + ], + "title": "User", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", - }, - }, - }, - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/items/": { - "get": { - "operationId": "get_items", - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/Item", + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", }, - "title": "Response Items-Get Items", - "type": "array", - }, + { + "type": "integer", + }, + ], }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "description": "Successful Response", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "summary": "Get Items", - "tags": [ - "items", - ], }, - "post": { - "operationId": "create_item", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", + }, + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/items/": { + "get": { + "operationId": "get_items", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/Item", + }, + "title": "Response Items-Get Items", + "type": "array", + }, + }, }, + "description": "Successful Response", }, }, - "required": True, + "summary": "Get Items", + "tags": [ + "items", + ], }, - "responses": { - "200": { + "post": { + "operationId": "create_item", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResponseMessage", + "$ref": "#/components/schemas/Item", }, }, }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "required": True, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage", + }, }, }, + "description": "Successful Response", }, - "description": "Validation Error", - }, - }, - "summary": "Create Item", - "tags": [ - "items", - ], - }, - }, - "/users/": { - "post": { - "operationId": "create_user", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, + }, }, + "description": "Validation Error", }, }, - "required": True, + "summary": "Create Item", + "tags": [ + "items", + ], }, - "responses": { - "200": { + }, + "/users/": { + "post": { + "operationId": "create_user", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResponseMessage", + "$ref": "#/components/schemas/User", }, }, }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "required": True, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResponseMessage", + }, + }, + }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Create User", + "tags": [ + "users", + ], }, - "summary": "Create User", - "tags": [ - "users", - ], }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_graphql/test_tutorial001.py b/tests/test_tutorial/test_graphql/test_tutorial001.py index 9ba7147b55..cc3be6a190 100644 --- a/tests/test_tutorial/test_graphql/test_tutorial001.py +++ b/tests/test_tutorial/test_graphql/test_tutorial001.py @@ -1,6 +1,7 @@ import warnings import pytest +from inline_snapshot import snapshot from starlette.testclient import TestClient warnings.filterwarnings( @@ -26,45 +27,47 @@ def test_query(client: TestClient): def test_openapi(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/graphql": { - "get": { - "operationId": "handle_http_get_graphql_get", - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/graphql": { + "get": { + "operationId": "handle_http_get_graphql_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "The GraphiQL integrated development environment.", + }, + "404": { + "description": "Not found if GraphiQL or query via GET are not enabled.", }, - "description": "The GraphiQL integrated development environment.", - }, - "404": { - "description": "Not found if GraphiQL or query via GET are not enabled.", }, + "summary": "Handle Http Get", }, - "summary": "Handle Http Get", - }, - "post": { - "operationId": "handle_http_post_graphql_post", - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + "post": { + "operationId": "handle_http_post_graphql_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", }, + "summary": "Handle Http Post", }, - "summary": "Handle Http Post", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index e22f1dafd4..8283cdc73e 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial001_py39 import app @@ -21,72 +22,76 @@ def test_get_item_not_found(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index 991478a0fe..c437693d3d 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial002_py39 import app @@ -21,72 +22,76 @@ def test_get_item_not_found_header(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items-header/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items-header/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item Header", - "operationId": "read_item_header_items_header__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item Header", + "operationId": "read_item_header_items_header__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index c303960bde..959729e53f 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial003_py39 import app @@ -22,72 +23,76 @@ def test_get_exception(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/unicorns/{name}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/unicorns/{name}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Unicorn", - "operationId": "read_unicorn_unicorns__name__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Name", "type": "string"}, - "name": "name", - "in": "path", - } - ], + "summary": "Read Unicorn", + "operationId": "read_unicorn_unicorns__name__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Name", "type": "string"}, + "name": "name", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index f6ec59b4d0..16165bb3d3 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial004_py39 import app @@ -27,72 +28,76 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index a7fa4f0b64..af924a9f76 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial005_py39 import app @@ -31,81 +32,85 @@ def test_post(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Item": { - "title": "Item", - "required": ["title", "size"], - "type": "object", - "properties": { - "title": {"title": "Title", "type": "string"}, - "size": {"title": "Size", "type": "integer"}, + "Item": { + "title": "Item", + "required": ["title", "size"], + "type": "object", + "properties": { + "title": {"title": "Title", "type": "string"}, + "size": {"title": "Size", "type": "integer"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index 9cb57d857d..4c069d81e2 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.handling_errors.tutorial006_py39 import app @@ -35,72 +36,76 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 60342f70a4..2e97a83221 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -39,75 +40,79 @@ def test(path, headers, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "User-Agent", - }, - "name": "user-agent", - "in": "header", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "User-Agent", + }, + "name": "user-agent", + "in": "header", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py index f1ced99b1b..ba86c55bf6 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -50,75 +51,79 @@ def test(path, headers, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Strange Header", - }, - "name": "strange_header", - "in": "header", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Strange Header", + }, + "name": "strange_header", + "in": "header", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py index 382c3ae191..30e5133c01 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -44,78 +45,82 @@ def test(path, headers, expected_status, expected_response, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "X-Token", - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "X-Token", + "anyOf": [ + {"type": "array", "items": {"type": "string"}}, + {"type": "null"}, + ], + }, + "name": "x-token", + "in": "header", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "x-token", - "in": "header", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial001.py b/tests/test_tutorial/test_metadata/test_tutorial001.py index ead48577d0..ba3c09ce4c 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.metadata.tutorial001_py39 import app @@ -14,36 +15,38 @@ def test_items(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "ChimichangApp", - "summary": "Deadpool's favorite app. Nuff said.", - "description": "\nChimichangApp API helps you do awesome stuff. ๐Ÿš€\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", - "termsOfService": "http://example.com/terms/", - "contact": { - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "ChimichangApp", + "summary": "Deadpool's favorite app. Nuff said.", + "description": "\nChimichangApp API helps you do awesome stuff. ๐Ÿš€\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", + "termsOfService": "http://example.com/terms/", + "contact": { + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, + "version": "0.0.1", }, - "license": { - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html", - }, - "version": "0.0.1", - }, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial001_1.py b/tests/test_tutorial/test_metadata/test_tutorial001_1.py index 10cb35c546..9339549731 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001_1.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001_1.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.metadata.tutorial001_1_py39 import app @@ -14,36 +15,38 @@ def test_items(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "ChimichangApp", - "summary": "Deadpool's favorite app. Nuff said.", - "description": "\nChimichangApp API helps you do awesome stuff. ๐Ÿš€\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", - "termsOfService": "http://example.com/terms/", - "contact": { - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "ChimichangApp", + "summary": "Deadpool's favorite app. Nuff said.", + "description": "\nChimichangApp API helps you do awesome stuff. ๐Ÿš€\n\n## Items\n\nYou can **read items**.\n\n## Users\n\nYou will be able to:\n\n* **Create users** (_not implemented_).\n* **Read users** (_not implemented_).\n", + "termsOfService": "http://example.com/terms/", + "contact": { + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + "license": { + "name": "Apache 2.0", + "identifier": "Apache-2.0", + }, + "version": "0.0.1", }, - "license": { - "name": "Apache 2.0", - "identifier": "Apache-2.0", - }, - "version": "0.0.1", - }, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial002.py b/tests/test_tutorial/test_metadata/test_tutorial002.py index e2814c88f9..5a252475eb 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial002.py +++ b/tests/test_tutorial/test_metadata/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.metadata.tutorial002_py39 import app @@ -19,24 +20,26 @@ def test_get_openapi_json_default_url(): def test_openapi_schema(): response = client.get("/api/v1/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial003.py b/tests/test_tutorial/test_metadata/test_tutorial003.py index 085c271cdb..778781e665 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial003.py +++ b/tests/test_tutorial/test_metadata/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.metadata.tutorial003_py39 import app @@ -14,27 +15,29 @@ def test_items(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) def test_swagger_ui_default_url(): diff --git a/tests/test_tutorial/test_metadata/test_tutorial004.py b/tests/test_tutorial/test_metadata/test_tutorial004.py index 4ef93fd5e3..5c309a830e 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial004.py +++ b/tests/test_tutorial/test_metadata/test_tutorial004.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.metadata.tutorial004_py39 import app @@ -15,49 +16,51 @@ def test_path_operations(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "tags": ["users"], - "summary": "Get Users", - "operationId": "get_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "tags": ["users"], + "summary": "Get Users", + "operationId": "get_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, }, - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } + "tags": [ + { + "name": "users", + "description": "Operations with users. The **login** logic is also here.", + }, + { + "name": "items", + "description": "Manage items. So _fancy_ they have their own docs.", + "externalDocs": { + "description": "Items external docs", + "url": "https://fastapi.tiangolo.com/", }, - } - }, - }, - "tags": [ - { - "name": "users", - "description": "Operations with users. The **login** logic is also here.", - }, - { - "name": "items", - "description": "Manage items. So _fancy_ they have their own docs.", - "externalDocs": { - "description": "Items external docs", - "url": "https://fastapi.tiangolo.com/", }, - }, - ], - } + ], + } + ) diff --git a/tests/test_tutorial/test_middleware/test_tutorial001.py b/tests/test_tutorial/test_middleware/test_tutorial001.py index cbcfd4146f..18047f3430 100644 --- a/tests/test_tutorial/test_middleware/test_tutorial001.py +++ b/tests/test_tutorial/test_middleware/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.middleware.tutorial001_py39 import app @@ -14,11 +15,13 @@ def test_response_headers(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "paths": {}, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "paths": {}, + } + ) diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index e8c98e8063..1e937d0c90 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -3,6 +3,7 @@ from types import ModuleType import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from tests.utils import needs_py310 @@ -42,163 +43,167 @@ def test_dummy_callback(mod: ModuleType): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/invoices/": { - "post": { - "summary": "Create Invoice", - "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', - "operationId": "create_invoice_invoices__post", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "uri", - "minLength": 1, - "maxLength": 2083, - }, - {"type": "null"}, - ], - "title": "Callback Url", - }, - "name": "callback_url", - "in": "query", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Invoice"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/invoices/": { + "post": { + "summary": "Create Invoice", + "description": 'Create an invoice.\n\nThis will (let\'s imagine) let the API user (some external developer) create an\ninvoice.\n\nAnd this path operation will:\n\n* Send the invoice to the client.\n* Collect the money from the client.\n* Send a notification back to the API user (the external developer), as a callback.\n * At this point is that the API will somehow send a POST request to the\n external API with the notification of the invoice event\n (e.g. "payment successful").', + "operationId": "create_invoice_invoices__post", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2083, + }, + {"type": "null"}, + ], + "title": "Callback Url", + }, + "name": "callback_url", + "in": "query", } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Invoice"} } }, + "required": True, }, - }, - "callbacks": { - "invoice_notification": { - "{$callback_url}/invoices/{$request.body.id}": { - "post": { - "summary": "Invoice Notification", - "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InvoiceEvent" - } - } - }, - }, - "responses": { - "200": { - "description": "Successful Response", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "callbacks": { + "invoice_notification": { + "{$callback_url}/invoices/{$request.body.id}": { + "post": { + "summary": "Invoice Notification", + "operationId": "invoice_notification__callback_url__invoices___request_body_id__post", + "requestBody": { + "required": True, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InvoiceEventReceived" + "$ref": "#/components/schemas/InvoiceEvent" } } }, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvoiceEventReceived" + } } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - }, + } } } - } - }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "Invoice": { - "title": "Invoice", - "required": ["id", "customer", "total"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "string"}, - "title": { - "title": "Title", - "anyOf": [{"type": "string"}, {"type": "null"}], + "Invoice": { + "title": "Invoice", + "required": ["id", "customer", "total"], + "type": "object", + "properties": { + "id": {"title": "Id", "type": "string"}, + "title": { + "title": "Title", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "customer": {"title": "Customer", "type": "string"}, + "total": {"title": "Total", "type": "number"}, }, - "customer": {"title": "Customer", "type": "string"}, - "total": {"title": "Total", "type": "number"}, }, - }, - "InvoiceEvent": { - "title": "InvoiceEvent", - "required": ["description", "paid"], - "type": "object", - "properties": { - "description": {"title": "Description", "type": "string"}, - "paid": {"title": "Paid", "type": "boolean"}, + "InvoiceEvent": { + "title": "InvoiceEvent", + "required": ["description", "paid"], + "type": "object", + "properties": { + "description": {"title": "Description", "type": "string"}, + "paid": {"title": "Paid", "type": "boolean"}, + }, }, - }, - "InvoiceEventReceived": { - "title": "InvoiceEventReceived", - "required": ["ok"], - "type": "object", - "properties": {"ok": {"title": "Ok", "type": "boolean"}}, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "InvoiceEventReceived": { + "title": "InvoiceEventReceived", + "required": ["ok"], + "type": "object", + "properties": {"ok": {"title": "Ok", "type": "boolean"}}, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py index c58e0fd02c..0482c94bf9 100644 --- a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.openapi_webhooks.tutorial001_py39 import app @@ -19,101 +20,107 @@ def test_dummy_webhook(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/": { - "get": { - "summary": "Read Users", - "operationId": "read_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - } - }, - "webhooks": { - "new-subscription": { - "post": { - "summary": "New Subscription", - "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", - "operationId": "new_subscriptionnew_subscription_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Subscription"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/": { + "get": { + "summary": "Read Users", + "operationId": "read_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + } + } + }, + "webhooks": { + "new-subscription": { + "post": { + "summary": "New Subscription", + "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", + "operationId": "new_subscriptionnew_subscription_post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Subscription" } } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "Subscription": { - "properties": { - "username": {"type": "string", "title": "Username"}, - "monthly_fee": {"type": "number", "title": "Monthly Fee"}, - "start_date": { - "type": "string", - "format": "date-time", - "title": "Start Date", + "Subscription": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "monthly_fee": {"type": "number", "title": "Monthly Fee"}, + "start_date": { + "type": "string", + "format": "date-time", + "title": "Start Date", + }, }, + "type": "object", + "required": ["username", "monthly_fee", "start_date"], + "title": "Subscription", }, - "type": "object", - "required": ["username", "monthly_fee", "start_date"], - "title": "Subscription", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py index ee0b707108..3a4f648241 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_advanced_configuration.tutorial001_py39 import app @@ -14,21 +15,23 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "some_specific_id_you_define", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "some_specific_id_you_define", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py index f6580d72e3..c26c36030b 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_advanced_configuration.tutorial002_py39 import app @@ -14,21 +15,23 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py index 104554fce3..f060647b29 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_advanced_configuration.tutorial003_py39 import app @@ -14,8 +15,10 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": {}, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": {}, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index 75b08a4e75..bf79345449 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -38,101 +39,105 @@ def test_query_params_str_validations(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py index e2a71236ff..779e54f9e7 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_advanced_configuration.tutorial005_py39 import app @@ -13,22 +14,24 @@ def test_get(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "x-aperture-labs-portal": "blue", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "x-aperture-labs-portal": "blue", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py index 9484f7f573..d63b5f912d 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_advanced_configuration.tutorial006_py39 import app @@ -21,37 +22,39 @@ def test_post(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"type": "string"}, - "price": {"type": "number"}, - "description": {"type": "string"}, - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"type": "string"}, + "price": {"type": "number"}, + "description": {"type": "string"}, + }, + } } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index d5f284e3bd..ec0c91bdad 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -75,41 +76,43 @@ def test_post_invalid(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/x-yaml": { - "schema": { - "title": "Item", - "required": ["name", "tags"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/x-yaml": { + "schema": { + "title": "Item", + "required": ["name", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + }, }, - }, + } } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py index de81251d04..500cb057c5 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -45,144 +46,146 @@ def test_post_items(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "201": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "Item": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], - "title": "Description", - }, - "name": { - "title": "Name", - "type": "string", - }, - "price": { - "title": "Price", - "type": "number", - }, - "tags": { - "default": [], - "items": { + "Item": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + "title": "Description", + }, + "name": { + "title": "Name", "type": "string", }, - "title": "Tags", - "type": "array", - "uniqueItems": True, - }, - "tax": { - "anyOf": [ - { - "type": "number", - }, - { - "type": "null", + "price": { + "title": "Price", + "type": "number", + }, + "tags": { + "default": [], + "items": { + "type": "string", }, - ], - "title": "Tax", - }, - }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { + "title": "Tags", + "type": "array", + "uniqueItems": True, + }, + "tax": { "anyOf": [ { - "type": "string", + "type": "number", }, { - "type": "integer", + "type": "null", }, ], + "title": "Tax", }, - "title": "Location", - "type": "array", }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", + }, }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py index 28e5e7d8d1..1cc560cb9a 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py @@ -3,6 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -57,169 +58,171 @@ def test_get_users(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - }, - "post": { - "tags": ["items"], - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "tags": ["items"], + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, - }, - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", - }, - "title": "Detail", - "type": "array", + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } }, - }, - "title": "HTTPValidationError", - "type": "object", + } }, - "Item": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", }, - ], - "title": "Description", - }, - "name": { - "title": "Name", - "type": "string", - }, - "price": { - "title": "Price", - "type": "number", - }, - "tags": { - "default": [], - "items": { - "type": "string", + "title": "Detail", + "type": "array", }, - "title": "Tags", - "type": "array", - "uniqueItems": True, - }, - "tax": { - "anyOf": [ - { - "type": "number", - }, - { - "type": "null", - }, - ], - "title": "Tax", }, + "title": "HTTPValidationError", + "type": "object", }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { + "Item": { + "properties": { + "description": { "anyOf": [ { "type": "string", }, { - "type": "integer", + "type": "null", }, ], + "title": "Description", + }, + "name": { + "title": "Name", + "type": "string", + }, + "price": { + "title": "Price", + "type": "number", + }, + "tags": { + "default": [], + "items": { + "type": "string", + }, + "title": "Tags", + "type": "array", + "uniqueItems": True, + }, + "tax": { + "anyOf": [ + { + "type": "number", + }, + { + "type": "null", + }, + ], + "title": "Tax", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", }, - "type": { - "title": "Error Type", - "type": "string", + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", + }, }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py index 5a0193adfa..98319645c2 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_configuration.tutorial002b_py39 import app @@ -20,35 +21,37 @@ def test_get_users(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "tags": ["items"], - "summary": "Get Items", - "operationId": "get_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "tags": ["items"], + "summary": "Get Items", + "operationId": "get_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, + "/users/": { + "get": { + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, }, - "/users/": { - "get": { - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } - }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py index e42c3e2b73..8e86cd8a51 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py @@ -4,6 +4,7 @@ from textwrap import dedent import pytest from dirty_equals import IsList from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -66,145 +67,147 @@ def test_openapi_schema(client: TestClient, mod_name: str): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "summary": "Create an item", - "description": DESCRIPTIONS[mod_name], - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "summary": "Create an item", + "description": DESCRIPTIONS[mod_name], + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, }, }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "Item": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], - "title": "Description", - }, - "name": { - "title": "Name", - "type": "string", - }, - "price": { - "title": "Price", - "type": "number", - }, - "tags": { - "default": [], - "items": { + "Item": { + "properties": { + "description": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + "title": "Description", + }, + "name": { + "title": "Name", "type": "string", }, - "title": "Tags", - "type": "array", - "uniqueItems": True, - }, - "tax": { - "anyOf": [ - { - "type": "number", - }, - { - "type": "null", + "price": { + "title": "Price", + "type": "number", + }, + "tags": { + "default": [], + "items": { + "type": "string", }, - ], - "title": "Tax", - }, - }, - "required": [ - "name", - "price", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { + "title": "Tags", + "type": "array", + "uniqueItems": True, + }, + "tax": { "anyOf": [ { - "type": "string", + "type": "number", }, { - "type": "integer", + "type": "null", }, ], + "title": "Tax", }, - "title": "Location", - "type": "array", }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", + "required": [ + "name", + "price", + ], + "title": "Item", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", + }, }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index b684c9f5c2..07152755f5 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -37,101 +38,105 @@ def test_query_params_str_validations(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "The created item", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, }, - }, - "summary": "Create an item", - "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "uniqueItems": True, - "type": "array", - "items": {"type": "string"}, - "default": [], + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py index 5d9c55675f..5f56ab929e 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py @@ -1,5 +1,6 @@ import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_operation_configuration.tutorial006_py39 import app @@ -23,49 +24,51 @@ def test_query_params_str_validations(path, expected_status, expected_response): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["items"], - "summary": "Read Items", - "operationId": "read_items_items__get", - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["items"], + "summary": "Read Items", + "operationId": "read_items_items__get", + } + }, + "/users/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["users"], + "summary": "Read Users", + "operationId": "read_users_users__get", + } + }, + "/elements/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "tags": ["items"], + "summary": "Read Elements", + "operationId": "read_elements_elements__get", + "deprecated": True, + } + }, }, - "/users/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["users"], - "summary": "Read Users", - "operationId": "read_users_users__get", - } - }, - "/elements/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "tags": ["items"], - "summary": "Read Elements", - "operationId": "read_elements_elements__get", - "deprecated": True, - } - }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial001.py b/tests/test_tutorial/test_path_params/test_tutorial001.py index f54626f339..ec598832b0 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params/test_tutorial001.py @@ -1,5 +1,6 @@ import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial001_py39 import app @@ -22,97 +23,99 @@ def test_get_items(item_id, expected_response): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + }, }, - }, - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Read Item", }, - "summary": "Read Item", }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial002.py b/tests/test_tutorial/test_path_params/test_tutorial002.py index 46da41b481..8384ec8eff 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial002.py +++ b/tests/test_tutorial/test_path_params/test_tutorial002.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial002_py39 import app @@ -29,98 +30,100 @@ def test_get_items_invalid_id(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "integer", + }, }, - }, - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Read Item", }, - "summary": "Read Item", }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial003.py b/tests/test_tutorial/test_path_params/test_tutorial003.py index 6ac92c87e3..432ccde49d 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial003.py +++ b/tests/test_tutorial/test_path_params/test_tutorial003.py @@ -1,5 +1,6 @@ import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial003_py39 import app @@ -22,114 +23,116 @@ def test_get_users(user_id: str, expected_response: dict): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "operationId": "read_user_me_users_me_get", - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "operationId": "read_user_me_users_me_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", }, + "summary": "Read User Me", }, - "summary": "Read User Me", }, - }, - "/users/{user_id}": { - "get": { - "operationId": "read_user_users__user_id__get", - "parameters": [ - { - "in": "path", - "name": "user_id", - "required": True, - "schema": { - "title": "User Id", - "type": "string", + "/users/{user_id}": { + "get": { + "operationId": "read_user_users__user_id__get", + "parameters": [ + { + "in": "path", + "name": "user_id", + "required": True, + "schema": { + "title": "User Id", + "type": "string", + }, }, - }, - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Read User", }, - "summary": "Read User", }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial003b.py b/tests/test_tutorial/test_path_params/test_tutorial003b.py index 8e4a26a1ca..1cf39eca9a 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial003b.py +++ b/tests/test_tutorial/test_path_params/test_tutorial003b.py @@ -1,6 +1,7 @@ import asyncio from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial003b_py39 import app, read_users2 @@ -20,25 +21,27 @@ def test_read_users2(): # Just for coverage def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users": { - "get": { - "operationId": "read_users2_users_get", - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users": { + "get": { + "operationId": "read_users2_users_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", }, + "summary": "Read Users2", }, - "summary": "Read Users2", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index 8f460fb695..b691e821df 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial004_py39 import app @@ -22,72 +23,76 @@ def test_root_file_path(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/{file_path}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/{file_path}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read File", - "operationId": "read_file_files__file_path__get", - "parameters": [ - { - "required": True, - "schema": {"title": "File Path", "type": "string"}, - "name": "file_path", - "in": "path", - } - ], + "summary": "Read File", + "operationId": "read_file_files__file_path__get", + "parameters": [ + { + "required": True, + "schema": {"title": "File Path", "type": "string"}, + "name": "file_path", + "in": "path", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index 3e3766e845..c60fee3f0c 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.path_params.tutorial005_py39 import app @@ -42,78 +43,81 @@ def test_get_enums_invalid(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - data = response.json() - assert data == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/models/{model_name}": { - "get": { - "summary": "Get Model", - "operationId": "get_model_models__model_name__get", - "parameters": [ - { - "required": True, - "schema": {"$ref": "#/components/schemas/ModelName"}, - "name": "model_name", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/models/{model_name}": { + "get": { + "summary": "Get Model", + "operationId": "get_model_models__model_name__get", + "parameters": [ + { + "required": True, + "schema": {"$ref": "#/components/schemas/ModelName"}, + "name": "model_name", + "in": "path", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ModelName": { - "title": "ModelName", - "enum": ["alexnet", "resnet", "lenet"], - "type": "string", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ModelName": { + "title": "ModelName", + "enum": ["alexnet", "resnet", "lenet"], + "type": "string", + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py index a4d68d01b4..b43de70325 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -53,114 +54,116 @@ def test_read_items_invalid_item_id(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "type": "integer", + }, + "name": "item_id", + "in": "path", }, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], - "title": "Item-Query", + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + "title": "Item-Query", + }, + "name": "item-query", + "in": "query", }, - "name": "item-query", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {}, - } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {}, + } + }, }, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py index 37533bd228..1bb2a3ea8e 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -66,107 +67,109 @@ def test_read_items_missing_q(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "type": "integer", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "type": "integer", + }, + "name": "item_id", + "in": "path", }, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": { - "type": "string", - "title": "Q", + { + "required": True, + "schema": { + "type": "string", + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {}, - } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {}, + } + }, }, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py index a9c111a594..37c16d2954 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -80,108 +81,110 @@ def test_read_items_missing_q(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "type": "integer", - "minimum": 1, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "type": "integer", + "minimum": 1, + }, + "name": "item_id", + "in": "path", }, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": { - "type": "string", - "title": "Q", + { + "required": True, + "schema": { + "type": "string", + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {}, - } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {}, + } + }, }, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py index e0e976d6f3..0afc9dcbc9 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -96,109 +97,111 @@ def test_read_items_missing_q(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "type": "integer", - "exclusiveMinimum": 0, - "maximum": 1000, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 1000, + }, + "name": "item_id", + "in": "path", }, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": { - "type": "string", - "title": "Q", + { + "required": True, + "schema": { + "type": "string", + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {}, - } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {}, + } + }, }, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py index 2004ad1d2b..e0a9694c12 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -104,120 +105,122 @@ def test_read_items_size_too_large(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": { - "title": "The ID of the item to get", - "type": "integer", - "minimum": 0, - "maximum": 1000, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": { + "title": "The ID of the item to get", + "type": "integer", + "minimum": 0, + "maximum": 1000, + }, + "name": "item_id", + "in": "path", }, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": { - "type": "string", - "title": "Q", + { + "required": True, + "schema": { + "type": "string", + "title": "Q", + }, + "name": "q", + "in": "query", }, - "name": "q", - "in": "query", - }, - { - "in": "query", - "name": "size", - "required": True, - "schema": { - "exclusiveMaximum": 10.5, - "exclusiveMinimum": 0, - "title": "Size", - "type": "number", + { + "in": "query", + "name": "size", + "required": True, + "schema": { + "exclusiveMaximum": 10.5, + "exclusiveMinimum": 0, + "title": "Size", + "type": "number", + }, }, - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {}, - } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {}, + } + }, }, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial001.py b/tests/test_tutorial/test_query_params/test_tutorial001.py index 84e4557272..40ada0e8e4 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -43,86 +44,90 @@ def test_read_user_item(client: TestClient, path, expected_json): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Item", - "operationId": "read_item_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Skip", - "type": "integer", - "default": 0, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Item", + "operationId": "read_item_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", }, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "type": "integer", - "default": 10, + { + "required": False, + "schema": { + "title": "Limit", + "type": "integer", + "default": 10, + }, + "name": "limit", + "in": "query", }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial002.py b/tests/test_tutorial/test_query_params/test_tutorial002.py index f725c80b32..1da308a7e2 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -42,88 +43,92 @@ def test_read_user_item(client: TestClient, path, expected_json): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "title": "Q", - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "q", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + { + "required": False, + "schema": { + "title": "Q", + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + }, + "name": "q", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial003.py b/tests/test_tutorial/test_query_params/test_tutorial003.py index 9f1f2e6e4c..9bb58ff9fe 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -53,98 +54,102 @@ def test_read_user_item(client: TestClient, path, expected_json): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "summary": "Read Item", - "operationId": "read_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "title": "Q", - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Short", - "type": "boolean", - "default": False, + { + "required": False, + "schema": { + "title": "Q", + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + }, + "name": "q", + "in": "query", }, - "name": "short", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + { + "required": False, + "schema": { + "title": "Short", + "type": "boolean", + "default": False, + }, + "name": "short", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial004.py b/tests/test_tutorial/test_query_params/test_tutorial004.py index e834f973a9..20aadb3acd 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -55,104 +56,108 @@ def test_read_user_item(client: TestClient, path, expected_json): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/{user_id}/items/{item_id}": { - "get": { - "summary": "Read User Item", - "operationId": "read_user_item_users__user_id__items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "User Id", "type": "integer"}, - "name": "user_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": False, - "schema": { - "title": "Q", - "anyOf": [ - { - "type": "string", - }, - { - "type": "null", - }, - ], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/{user_id}/items/{item_id}": { + "get": { + "summary": "Read User Item", + "operationId": "read_user_item_users__user_id__items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "User Id", "type": "integer"}, + "name": "user_id", + "in": "path", }, - "name": "q", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Short", - "type": "boolean", - "default": False, + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "short", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + { + "required": False, + "schema": { + "title": "Q", + "anyOf": [ + { + "type": "string", + }, + { + "type": "null", + }, + ], + }, + "name": "q", + "in": "query", + }, + { + "required": False, + "schema": { + "title": "Short", + "type": "boolean", + "default": False, + }, + "name": "short", + "in": "query", + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index 36129dbc96..e023fe6d80 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.query_params.tutorial005_py39 import app @@ -29,78 +30,82 @@ def test_foo_no_needy(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read User Item", - "operationId": "read_user_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Needy", "type": "string"}, - "name": "needy", - "in": "query", - }, - ], + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + }, + { + "required": True, + "schema": {"title": "Needy", "type": "string"}, + "name": "needy", + "in": "query", + }, + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index 473dc33661..b28e126556 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -61,97 +62,101 @@ def test_foo_no_needy(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read User Item", - "operationId": "read_user_item_items__item_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "string"}, - "name": "item_id", - "in": "path", - }, - { - "required": True, - "schema": {"title": "Needy", "type": "string"}, - "name": "needy", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Skip", - "type": "integer", - "default": 0, + "summary": "Read User Item", + "operationId": "read_user_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", }, - "name": "skip", - "in": "query", - }, - { - "required": False, - "schema": { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Limit", + { + "required": True, + "schema": {"title": "Needy", "type": "string"}, + "name": "needy", + "in": "query", }, - "name": "limit", - "in": "query", - }, - ], + { + "required": False, + "schema": { + "title": "Skip", + "type": "integer", + "default": 0, + }, + "name": "skip", + "in": "query", + }, + { + "required": False, + "schema": { + "anyOf": [{"type": "integer"}, {"type": "null"}], + "title": "Limit", + }, + "name": "limit", + "in": "query", + }, + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py index 069921629e..ed73b7329e 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -46,78 +47,82 @@ def test_query_params_str_validations_q_query(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - {"type": "string"}, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + {"type": "string"}, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py index a043b5b2e7..3eac1f2b36 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -64,81 +65,85 @@ def test_query_params_str_validations_q_too_long(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "maxLength": 50, - }, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "maxLength": 50, + }, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py index 68c6e6174f..59d5160acb 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -74,82 +75,86 @@ def test_query_params_str_validations_q_too_long(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - }, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "minLength": 3, + "maxLength": 50, + }, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py index 79538f952b..abf08c9328 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -67,83 +68,87 @@ def test_query_params_str_validations_q_nonregexquery(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "minLength": 3, + "maxLength": 50, + "pattern": "^fixedquery$", + }, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py index fafbd0a7d0..7b5368abc4 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -57,77 +58,81 @@ def test_query_params_str_validations_q_short(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "type": "string", - "default": "fixedquery", - "minLength": 3, - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "type": "string", + "default": "fixedquery", + "minLength": 3, + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py index 1d01492c66..2c1df2c08f 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -63,76 +64,80 @@ def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient) def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": { - "type": "string", - "minLength": 3, - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": { + "type": "string", + "minLength": 3, + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py index d31cb5036a..3df9efa839 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -73,78 +74,82 @@ def test_query_params_str_validations_q_short(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": True, - "schema": { - "anyOf": [ - {"type": "string", "minLength": 3}, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": True, + "schema": { + "anyOf": [ + {"type": "string", "minLength": 3}, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py index e030902451..874002b173 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -58,81 +59,85 @@ def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient) def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - }, - {"type": "null"}, - ], - "title": "Query string", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "minLength": 3, + }, + {"type": "null"}, + ], + "title": "Query string", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py index 186de5e062..b9613a17b8 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -58,83 +59,87 @@ def test_query_params_str_validations_q_fixedquery_too_short(client: TestClient) def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - }, - {"type": "null"}, - ], - "title": "Query string", + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { "description": "Query string for the items to search in the database that have a good match", - }, - "name": "q", - "in": "query", - } - ], + "required": False, + "schema": { + "anyOf": [ + { + "type": "string", + "minLength": 3, + }, + {"type": "null"}, + ], + "title": "Query string", + "description": "Query string for the items to search in the database that have a good match", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py index b242a75c90..d749d85f7a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -48,78 +49,82 @@ def test_query_params_str_validations_q_fixedquery(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "schema": { - "anyOf": [ - {"type": "string"}, - {"type": "null"}, - ], - "title": "Item-Query", - }, - "required": False, - "name": "item-query", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "schema": { + "anyOf": [ + {"type": "string"}, + {"type": "null"}, + ], + "title": "Item-Query", + }, + "required": False, + "name": "item-query", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index 6a39130af2..395f795184 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -3,6 +3,7 @@ import importlib import pytest from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -65,92 +66,96 @@ def test_query_params_str_validations_item_query_nonregexquery(client: TestClien def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - }, - "name": "item-query", - "in": "query", - } - ], + "required": False, + "deprecated": True, + "schema": { + "anyOf": [ + { + "type": "string", + "minLength": 3, + "maxLength": 50, + "pattern": "^fixedquery$", + }, + {"type": "null"}, + ], + "title": "Query string", + "description": "Query string for the items to search in the database that have a good match", + # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. + **( + {"deprecated": True} + if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) + else {} + ), + }, + "name": "item-query", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index 6ab279bf3e..c25357fdd1 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -41,78 +42,82 @@ def test_query_no_values(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "anyOf": [ + {"type": "array", "items": {"type": "string"}}, + {"type": "null"}, + ], + "title": "Q", + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index 41bfeb3a7a..c3d01e90ea 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -37,77 +38,81 @@ def test_multi_query_values(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {"type": "string"}, + "default": ["foo", "bar"], + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 52c8147ffb..74efa46958 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -37,77 +38,81 @@ def test_query_no_values(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Q", + "type": "array", + "items": {}, + "default": [], + }, + "name": "q", + "in": "query", + } + ], + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index bb168f0fc3..6dff18b787 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -39,64 +40,68 @@ def test_no_hidden_query(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index db9b83b31a..fd5c3b0559 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -82,122 +83,134 @@ def test_post_upload_file(tmp_path, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_file_files__post" } } }, + "required": True, }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/uploadfile/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" } } }, + "required": True, }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } + } + }, + }, + "components": { + "schemas": { + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "format": "binary", } }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "format": "binary", + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index 903452ac76..5ef8df178c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -41,132 +42,136 @@ def test_post_upload_file(tmp_path, client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_file_files__post" } } }, + "required": True, }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/uploadfile/": { + "post": { + "summary": "Create Upload File", + "operationId": "create_upload_file_uploadfile__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" } } }, + "required": True, }, - }, - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as bytes", + "format": "binary", + } + }, }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } + "Body_create_upload_file_uploadfile__post": { + "title": "Body_create_upload_file_uploadfile__post", + "required": ["file"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "description": "A file read as UploadFile", + "format": "binary", + } + }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 4d9ff0e93d..52655fd63b 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -3,6 +3,7 @@ import importlib import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -102,142 +103,146 @@ def test_get_root(app: FastAPI): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Files", + "operationId": "create_files_files__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_files_files__post" } } }, + "required": True, }, - }, - "summary": "Create Files", - "operationId": "create_files_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_files_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfiles/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "/uploadfiles/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create Upload Files", + "operationId": "create_upload_files_uploadfiles__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" } } }, + "required": True, }, - }, - "summary": "Create Upload Files", - "operationId": "create_upload_files_uploadfiles__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" - } + } + }, + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - } - }, - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Main", - "operationId": "main__get", - } + "summary": "Main", + "operationId": "main__get", + } + }, }, - }, - "components": { - "schemas": { - "Body_create_upload_files_uploadfiles__post": { - "title": "Body_create_upload_files_uploadfiles__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - } + "components": { + "schemas": { + "Body_create_upload_files_uploadfiles__post": { + "title": "Body_create_upload_files_uploadfiles__post", + "required": ["files"], + "type": "object", + "properties": { + "files": { + "title": "Files", + "type": "array", + "items": {"type": "string", "format": "binary"}, + } + }, }, - }, - "Body_create_files_files__post": { - "title": "Body_create_files_files__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - } + "Body_create_files_files__post": { + "title": "Body_create_files_files__post", + "required": ["files"], + "type": "object", + "properties": { + "files": { + "title": "Files", + "type": "array", + "items": {"type": "string", "format": "binary"}, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index c9f7f09940..a1425ba330 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -3,6 +3,7 @@ import importlib import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -72,144 +73,148 @@ def test_get_root(app: FastAPI): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create Files", - "operationId": "create_files_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_files_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "summary": "Create Files", + "operationId": "create_files_files__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_files_files__post" } } }, + "required": True, }, - }, - } - }, - "/uploadfiles/": { - "post": { - "summary": "Create Upload Files", - "operationId": "create_upload_files_uploadfiles__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + } + }, + "/uploadfiles/": { + "post": { + "summary": "Create Upload Files", + "operationId": "create_upload_files_uploadfiles__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" } } }, + "required": True, }, - }, - } - }, - "/": { - "get": { - "summary": "Main", - "operationId": "main__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - } + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/": { + "get": { + "summary": "Main", + "operationId": "main__get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + }, }, - }, - "components": { - "schemas": { - "Body_create_files_files__post": { - "title": "Body_create_files_files__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - "description": "Multiple files as bytes", - } + "components": { + "schemas": { + "Body_create_files_files__post": { + "title": "Body_create_files_files__post", + "required": ["files"], + "type": "object", + "properties": { + "files": { + "title": "Files", + "type": "array", + "items": {"type": "string", "format": "binary"}, + "description": "Multiple files as bytes", + } + }, }, - }, - "Body_create_upload_files_uploadfiles__post": { - "title": "Body_create_upload_files_uploadfiles__post", - "required": ["files"], - "type": "object", - "properties": { - "files": { - "title": "Files", - "type": "array", - "items": {"type": "string", "format": "binary"}, - "description": "Multiple files as UploadFile", - } + "Body_create_upload_files_uploadfiles__post": { + "title": "Body_create_upload_files_uploadfiles__post", + "required": ["files"], + "type": "object", + "properties": { + "files": { + "title": "Files", + "type": "array", + "items": {"type": "string", "format": "binary"}, + "description": "Multiple files as UploadFile", + } + }, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial001.py b/tests/test_tutorial/test_request_form_models/test_tutorial001.py index c4740ee72d..68fa074dc3 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial001.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -99,81 +100,85 @@ def test_post_body_json(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login__post", + "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "application/x-www-form-urlencoded": { + "schema": {"$ref": "#/components/schemas/FormData"} } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": {"$ref": "#/components/schemas/FormData"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "FormData": { - "properties": { - "username": {"type": "string", "title": "Username"}, - "password": {"type": "string", "title": "Password"}, + }, + "components": { + "schemas": { + "FormData": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "password": {"type": "string", "title": "Password"}, + }, + "type": "object", + "required": ["username", "password"], + "title": "FormData", }, - "type": "object", - "required": ["username", "password"], - "title": "FormData", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002.py b/tests/test_tutorial/test_request_form_models/test_tutorial002.py index b07fce432a..ed5ae109a0 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial002.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -116,82 +117,86 @@ def test_post_body_json(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login__post", + "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "application/x-www-form-urlencoded": { + "schema": {"$ref": "#/components/schemas/FormData"} } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": {"$ref": "#/components/schemas/FormData"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "FormData": { - "properties": { - "username": {"type": "string", "title": "Username"}, - "password": {"type": "string", "title": "Password"}, + }, + "components": { + "schemas": { + "FormData": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "password": {"type": "string", "title": "Password"}, + }, + "additionalProperties": False, + "type": "object", + "required": ["username", "password"], + "title": "FormData", }, - "additionalProperties": False, - "type": "object", - "required": ["username", "password"], - "title": "FormData", - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py index f5f76306e9..d1596f137e 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -99,83 +100,87 @@ def test_post_body_json(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/login/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/login/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_login__post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_login__post" } } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_login__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_login__post" - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Body_login_login__post": { - "title": "Body_login_login__post", - "required": ["username", "password"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, + }, + "components": { + "schemas": { + "Body_login_login__post": { + "title": "Body_login_login__post", + "required": ["username", "password"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index cd05a1ccf1..6e9165c425 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -3,6 +3,7 @@ import importlib import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -149,88 +150,96 @@ def test_post_files_and_token(tmp_path, app: FastAPI): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/files/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Create File", + "operationId": "create_file_files__post", + "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_create_file_files__post" } } }, + "required": True, }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file", "fileb", "token"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"}, - "fileb": { - "title": "Fileb", - "type": "string", - "format": "binary", + }, + "components": { + "schemas": { + "Body_create_file_files__post": { + "title": "Body_create_file_files__post", + "required": ["file", "fileb", "token"], + "type": "object", + "properties": { + "file": { + "title": "File", + "type": "string", + "format": "binary", + }, + "fileb": { + "title": "Fileb", + "type": "string", + "format": "binary", + }, + "token": {"title": "Token", "type": "string"}, }, - "token": {"title": "Token", "type": "string"}, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_response_directly/test_tutorial001.py b/tests/test_tutorial/test_response_directly/test_tutorial001.py index 76e7143bda..2b034f1c98 100644 --- a/tests/test_tutorial/test_response_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_response_directly/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -40,115 +41,117 @@ def test_path_operation(client: TestClient): def test_openapi_schema_pv2(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/items/{id}": { - "put": { - "operationId": "update_item_items__id__put", - "parameters": [ - { - "in": "path", - "name": "id", - "required": True, - "schema": {"title": "Id", "type": "string"}, - }, - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - }, - }, - }, - "required": True, - }, - "responses": { - "200": { - "content": { - "application/json": {"schema": {}}, + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/items/{id}": { + "put": { + "operationId": "update_item_items__id__put", + "parameters": [ + { + "in": "path", + "name": "id", + "required": True, + "schema": {"title": "Id", "type": "string"}, }, - "description": "Successful Response", - }, - "422": { + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "$ref": "#/components/schemas/Item", }, }, }, - "description": "Validation Error", + "required": True, }, - }, - "summary": "Update Item", - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "responses": { + "200": { + "content": { + "application/json": {"schema": {}}, + }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, + }, + }, + "description": "Validation Error", }, - "title": "Detail", - "type": "array", }, + "summary": "Update Item", }, - "title": "HTTPValidationError", - "type": "object", }, - "Item": { - "properties": { - "description": { - "anyOf": [ - {"type": "string"}, - {"type": "null"}, - ], - "title": "Description", - }, - "timestamp": { - "format": "date-time", - "title": "Timestamp", - "type": "string", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", + }, }, - "title": {"title": "Title", "type": "string"}, + "title": "HTTPValidationError", + "type": "object", }, - "required": [ - "title", - "timestamp", - ], - "title": "Item", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { + "Item": { + "properties": { + "description": { "anyOf": [ {"type": "string"}, - {"type": "integer"}, + {"type": "null"}, ], + "title": "Description", }, - "title": "Location", - "type": "array", + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string", + }, + "title": {"title": "Title", "type": "string"}, + }, + "required": [ + "title", + "timestamp", + ], + "title": "Item", + "type": "object", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", }, - "required": ["loc", "msg", "type"], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_response_directly/test_tutorial002.py b/tests/test_tutorial/test_response_directly/test_tutorial002.py index ef84575723..047e82c148 100644 --- a/tests/test_tutorial/test_response_directly/test_tutorial002.py +++ b/tests/test_tutorial/test_response_directly/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -38,28 +39,30 @@ def test_path_operation(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/legacy/": { - "get": { - "operationId": "get_legacy_data_legacy__get", - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/legacy/": { + "get": { + "operationId": "get_legacy_data_legacy__get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", }, + "summary": "Get Legacy Data", }, - "summary": "Get Legacy Data", }, }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py index 265162f15f..914f53783c 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -77,119 +78,125 @@ def test_create_item_only_required(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - "title": "Response Read Items Items Get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Item" + }, + "title": "Response Read Items Items Get", + } } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - }, - "post": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", }, }, }, - "required": True, + "summary": "Read Items", + "operationId": "read_items_items__get", }, - "responses": { - "200": { - "description": "Successful Response", + "post": { + "requestBody": { "content": { "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - } + "schema": { + "$ref": "#/components/schemas/Item", + }, + }, }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, } - } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, + "summary": "Create Item", + "operationId": "create_item_items__post", }, - "summary": "Create Item", - "operationId": "create_item_items__post", - }, - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "price": {"title": "Price", "type": "number"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - }, - "tags": { - "title": "Tags", - "type": "array", - "items": {"type": "string"}, - "default": [], + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "price": {"title": "Price", "type": "number"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial002.py b/tests/test_tutorial/test_response_model/test_tutorial002.py index 17027d3c10..10a4e37cd3 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial002.py +++ b/tests/test_tutorial/test_response_model/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -38,94 +39,100 @@ def test_post_user(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/user/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/UserIn"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/user/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserIn" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Create User", + "operationId": "create_user_user__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/UserIn"} } }, + "required": True, }, - }, - "summary": "Create User", - "operationId": "create_user_user__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/UserIn"} - } - }, - "required": True, - }, + } } - } - }, - "components": { - "schemas": { - "UserIn": { - "title": "UserIn", - "required": ["username", "password", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "email": { - "title": "Email", - "type": "string", - "format": "email", - }, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "components": { + "schemas": { + "UserIn": { + "title": "UserIn", + "required": ["username", "password", "email"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "password": {"title": "Password", "type": "string"}, + "email": { + "title": "Email", + "type": "string", + "format": "email", + }, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_02.py b/tests/test_tutorial/test_response_model/test_tutorial003_02.py index fcd5f9a1d4..460c882516 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_02.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_02.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.response_model.tutorial003_02_py39 import app @@ -20,76 +21,80 @@ def test_get_redirect(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/portal": { - "get": { - "summary": "Get Portal", - "operationId": "get_portal_portal_get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Teleport", - "type": "boolean", - "default": False, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/portal": { + "get": { + "summary": "Get Portal", + "operationId": "get_portal_portal_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Teleport", + "type": "boolean", + "default": False, + }, + "name": "teleport", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "teleport", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_03.py b/tests/test_tutorial/test_response_model/test_tutorial003_03.py index ea3c733b24..c83d78c4fa 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_03.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_03.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.response_model.tutorial003_03_py39 import app @@ -14,21 +15,23 @@ def test_get_portal(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/teleport": { - "get": { - "summary": "Get Teleport", - "operationId": "get_teleport_teleport_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/teleport": { + "get": { + "summary": "Get Teleport", + "operationId": "get_teleport_teleport_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05.py b/tests/test_tutorial/test_response_model/test_tutorial003_05.py index e64ed1a804..187b6491fc 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_05.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_05.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -35,76 +36,80 @@ def test_get_redirect(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/portal": { - "get": { - "summary": "Get Portal", - "operationId": "get_portal_portal_get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Teleport", - "type": "boolean", - "default": False, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/portal": { + "get": { + "summary": "Get Portal", + "operationId": "get_portal_portal_get", + "parameters": [ + { + "required": False, + "schema": { + "title": "Teleport", + "type": "boolean", + "default": False, + }, + "name": "teleport", + "in": "query", + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, }, - "name": "teleport", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py index 8b6213e33d..7199ceed65 100644 --- a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -27,72 +28,76 @@ def test_create_item(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "parameters": [ - { - "name": "name", - "in": "query", - "required": True, - "schema": {"title": "Name", "type": "string"}, - } - ], - "summary": "Create Item", - "operationId": "create_item_items__post", - "responses": { - "201": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "parameters": [ + { + "name": "name", + "in": "query", + "required": True, + "schema": {"title": "Name", "type": "string"}, + } + ], + "summary": "Create Item", + "operationId": "create_item_items__post", + "responses": { + "201": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "components": { + "schemas": { + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py index 7f0105a26d..f19346a3a4 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -36,106 +37,109 @@ def test_post_body_example(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - # insert_assert(response.json()) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "name": "item_id", - "in": "path", - "required": True, - "schema": {"type": "integer", "title": "Item Id"}, - } - ], - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": True, + "schema": {"type": "integer", "title": "Item Id"}, } - }, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { + "required": True, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } - }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } }, - "price": {"type": "number", "title": "Price"}, - "tax": { - "anyOf": [{"type": "number"}, {"type": "null"}], - "title": "Tax", + "type": "object", + "title": "HTTPValidationError", + }, + "Item": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": {"type": "number", "title": "Price"}, + "tax": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Tax", + }, }, + "type": "object", + "required": ["name", "price"], + "title": "Item", + "examples": [ + { + "description": "A very nice Item", + "name": "Foo", + "price": 35.4, + "tax": 3.2, + } + ], }, - "type": "object", - "required": ["name", "price"], - "title": "Item", - "examples": [ - { - "description": "A very nice Item", - "name": "Foo", - "price": 35.4, - "tax": 3.2, - } - ], - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py index 32707c2993..8313cb14f6 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -36,108 +37,111 @@ def test_post_body_example(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - # insert_assert(response.json()) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "name": "item_id", - "in": "path", - "required": True, - "schema": {"type": "integer", "title": "Item Id"}, - } - ], - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": True, + "schema": {"type": "integer", "title": "Item Id"}, } - }, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { + "required": True, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } - }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "examples": ["Foo"], - }, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", - "examples": ["A very nice Item"], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "price": { - "type": "number", - "title": "Price", - "examples": [35.4], + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } }, - "tax": { - "anyOf": [{"type": "number"}, {"type": "null"}], - "title": "Tax", - "examples": [3.2], + "type": "object", + "title": "HTTPValidationError", + }, + "Item": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "examples": ["Foo"], + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + "examples": ["A very nice Item"], + }, + "price": { + "type": "number", + "title": "Price", + "examples": [35.4], + }, + "tax": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Tax", + "examples": [3.2], + }, }, + "type": "object", + "required": ["name", "price"], + "title": "Item", }, - "type": "object", - "required": ["name", "price"], - "title": "Item", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py index 4f8f1394c1..3c45a64bcf 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -38,108 +39,111 @@ def test_post_body_example(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - # insert_assert(response.json()) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "name": "item_id", - "in": "path", - "required": True, - "schema": {"type": "integer", "title": "Item Id"}, - } - ], - "requestBody": { - "required": True, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - "examples": [ - { - "description": "A very nice Item", - "name": "Foo", - "price": 35.4, - "tax": 3.2, - } - ], - }, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "name": "item_id", + "in": "path", + "required": True, + "schema": {"type": "integer", "title": "Item Id"}, } - }, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { + "required": True, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "$ref": "#/components/schemas/Item", + "examples": [ + { + "description": "A very nice Item", + "name": "Foo", + "price": 35.4, + "tax": 3.2, + } + ], + }, } }, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } - }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } }, - "price": {"type": "number", "title": "Price"}, - "tax": { - "anyOf": [{"type": "number"}, {"type": "null"}], - "title": "Tax", + "type": "object", + "title": "HTTPValidationError", + }, + "Item": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": {"type": "number", "title": "Price"}, + "tax": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Tax", + }, }, + "type": "object", + "required": ["name", "price"], + "title": "Item", }, - "type": "object", - "required": ["name", "price"], - "title": "Item", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py index 3a0a7704bf..4b8e15fa19 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -38,112 +39,116 @@ def test_post_body_example(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Item", - "examples": [ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, - {"name": "Bar", "price": "35.4"}, - { - "name": "Baz", - "price": "thirty five point four", - }, - ], - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + ], + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Item", + "examples": [ + { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, + {"name": "Bar", "price": "35.4"}, + { + "name": "Baz", + "price": "thirty five point four", + }, + ], } } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py index b10f25e262..7f8e36df21 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -38,121 +39,125 @@ def test_post_body_example(client: TestClient): def test_openapi_schema(client: TestClient) -> None: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"}, - "examples": { - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "put": { + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "integer"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Item"}, + "examples": { + "normal": { + "summary": "A normal example", + "description": "A **normal** item works correctly.", + "value": { + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": {"name": "Bar", "price": "35.4"}, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", + "converted": { + "summary": "An example with converted data", + "description": "FastAPI can convert price `strings` to actual `numbers` automatically", + "value": {"name": "Bar", "price": "35.4"}, + }, + "invalid": { + "summary": "Invalid data is rejected with an error", + "value": { + "name": "Baz", + "price": "thirty five point four", + }, }, }, - }, - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + } + }, + "required": True, }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - } + }, }, }, - }, + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "components": { + "schemas": { + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } }, - "price": {"title": "Price", "type": "number"}, - "tax": { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "Item": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial001.py b/tests/test_tutorial/test_security/test_tutorial001.py index cdaa50b191..5742b51bf0 100644 --- a/tests/test_tutorial/test_security/test_tutorial001.py +++ b/tests/test_tutorial/test_security/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -41,30 +42,32 @@ def test_incorrect_token(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "security": [{"OAuth2PasswordBearer": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, + }, + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial002.py b/tests/test_tutorial/test_security/test_tutorial002.py index 85c076b1d2..1e8c6e0180 100644 --- a/tests/test_tutorial/test_security/test_tutorial002.py +++ b/tests/test_tutorial/test_security/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -42,30 +43,32 @@ def test_token(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2PasswordBearer": []}], - } - } - }, - "components": { - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2PasswordBearer": []}], + } } }, - }, - } + "components": { + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, + } + }, + }, + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index 924b36b3ab..acd910c71f 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -86,123 +87,131 @@ def test_inactive_user(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/token": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/token": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Login", + "operationId": "login_token_post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_token_post" } } }, + "required": True, }, - }, - "summary": "Login", - "operationId": "login_token_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_token_post" - } + } + }, + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, } }, - "required": True, - }, - } - }, - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me_get", - "security": [{"OAuth2PasswordBearer": []}], - } + "summary": "Read Users Me", + "operationId": "read_users_me_users_me_get", + "security": [{"OAuth2PasswordBearer": []}], + } + }, }, - }, - "components": { - "schemas": { - "Body_login_token_post": { - "title": "Body_login_token_post", - "required": ["username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "anyOf": [ - {"pattern": "^password$", "type": "string"}, - {"type": "null"}, - ], - }, - "username": {"title": "Username", "type": "string"}, - "password": { - "title": "Password", - "type": "string", - "format": "password", - }, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": { - "title": "Client Id", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "client_secret": { - "title": "Client Secret", - "anyOf": [{"type": "string"}, {"type": "null"}], - "format": "password", + "components": { + "schemas": { + "Body_login_token_post": { + "title": "Body_login_token_post", + "required": ["username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "anyOf": [ + {"pattern": "^password$", "type": "string"}, + {"type": "null"}, + ], + }, + "username": {"title": "Username", "type": "string"}, + "password": { + "title": "Password", + "type": "string", + "format": "password", + }, + "scope": { + "title": "Scope", + "type": "string", + "default": "", + }, + "client_id": { + "title": "Client Id", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "client_secret": { + "title": "Client Secret", + "anyOf": [{"type": "string"}, {"type": "null"}], + "format": "password", + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, }, + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, + } + }, }, - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": {"password": {"scopes": {}, "tokenUrl": "token"}}, - } - }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial004.py b/tests/test_tutorial/test_security/test_tutorial004.py index 2b0df66a2e..e842c92a13 100644 --- a/tests/test_tutorial/test_security/test_tutorial004.py +++ b/tests/test_tutorial/test_security/test_tutorial004.py @@ -4,6 +4,7 @@ from unittest.mock import patch import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -188,178 +189,186 @@ def test_openapi_schema(mod: ModuleType): client = TestClient(mod.app) response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/token": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Token"} - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/token": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Token"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, }, }, - "422": { - "description": "Validation Error", + "summary": "Login For Access Token", + "operationId": "login_for_access_token_token_post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Body_login_for_access_token_token_post" } } }, + "required": True, }, - }, - "summary": "Login For Access Token", - "operationId": "login_for_access_token_token_post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Body_login_for_access_token_token_post" - } + } + }, + "/users/me/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/User"} + } + }, } }, - "required": True, - }, - } + "summary": "Read Users Me", + "operationId": "read_users_me_users_me__get", + "security": [{"OAuth2PasswordBearer": []}], + } + }, + "/users/me/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Own Items", + "operationId": "read_own_items_users_me_items__get", + "security": [{"OAuth2PasswordBearer": []}], + } + }, }, - "/users/me/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/User"} - } + "components": { + "schemas": { + "User": { + "title": "User", + "required": ["username"], + "type": "object", + "properties": { + "username": {"title": "Username", "type": "string"}, + "email": { + "title": "Email", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "full_name": { + "title": "Full Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "disabled": { + "title": "Disabled", + "anyOf": [{"type": "boolean"}, {"type": "null"}], }, - } - }, - "summary": "Read Users Me", - "operationId": "read_users_me_users_me__get", - "security": [{"OAuth2PasswordBearer": []}], - } - }, - "/users/me/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Own Items", - "operationId": "read_own_items_users_me_items__get", - "security": [{"OAuth2PasswordBearer": []}], - } - }, - }, - "components": { - "schemas": { - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": { - "title": "Email", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "full_name": { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - }, - "disabled": { - "title": "Disabled", - "anyOf": [{"type": "boolean"}, {"type": "null"}], }, }, - }, - "Token": { - "title": "Token", - "required": ["access_token", "token_type"], - "type": "object", - "properties": { - "access_token": {"title": "Access Token", "type": "string"}, - "token_type": {"title": "Token Type", "type": "string"}, - }, - }, - "Body_login_for_access_token_token_post": { - "title": "Body_login_for_access_token_token_post", - "required": ["username", "password"], - "type": "object", - "properties": { - "grant_type": { - "title": "Grant Type", - "anyOf": [ - {"pattern": "^password$", "type": "string"}, - {"type": "null"}, - ], - }, - "username": {"title": "Username", "type": "string"}, - "password": { - "title": "Password", - "type": "string", - "format": "password", - }, - "scope": {"title": "Scope", "type": "string", "default": ""}, - "client_id": { - "title": "Client Id", - "anyOf": [{"type": "string"}, {"type": "null"}], + "Token": { + "title": "Token", + "required": ["access_token", "token_type"], + "type": "object", + "properties": { + "access_token": {"title": "Access Token", "type": "string"}, + "token_type": {"title": "Token Type", "type": "string"}, }, - "client_secret": { - "title": "Client Secret", - "anyOf": [{"type": "string"}, {"type": "null"}], - "format": "password", + }, + "Body_login_for_access_token_token_post": { + "title": "Body_login_for_access_token_token_post", + "required": ["username", "password"], + "type": "object", + "properties": { + "grant_type": { + "title": "Grant Type", + "anyOf": [ + {"pattern": "^password$", "type": "string"}, + {"type": "null"}, + ], + }, + "username": {"title": "Username", "type": "string"}, + "password": { + "title": "Password", + "type": "string", + "format": "password", + }, + "scope": { + "title": "Scope", + "type": "string", + "default": "", + }, + "client_id": { + "title": "Client Id", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "client_secret": { + "title": "Client Secret", + "anyOf": [{"type": "string"}, {"type": "null"}], + "format": "password", + }, }, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, }, + "securitySchemes": { + "OAuth2PasswordBearer": { + "type": "oauth2", + "flows": { + "password": { + "scopes": {}, + "tokenUrl": "token", + } + }, + } + }, }, - "securitySchemes": { - "OAuth2PasswordBearer": { - "type": "oauth2", - "flows": { - "password": { - "scopes": {}, - "tokenUrl": "token", - } - }, - } - }, - }, - } + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial006.py b/tests/test_tutorial/test_security/test_tutorial006.py index a4b3104bbc..1c96f62ae3 100644 --- a/tests/test_tutorial/test_security/test_tutorial006.py +++ b/tests/test_tutorial/test_security/test_tutorial006.py @@ -3,6 +3,7 @@ from base64 import b64encode import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -53,25 +54,27 @@ def test_security_http_basic_non_basic_credentials(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } + ) diff --git a/tests/test_tutorial/test_security/test_tutorial007.py b/tests/test_tutorial/test_security/test_tutorial007.py index 28b70a2d43..24667422fe 100644 --- a/tests/test_tutorial/test_security/test_tutorial007.py +++ b/tests/test_tutorial/test_security/test_tutorial007.py @@ -3,6 +3,7 @@ from base64 import b64encode import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture( @@ -65,25 +66,27 @@ def test_security_http_basic_invalid_password(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/users/me": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Current User", - "operationId": "read_current_user_users_me_get", - "security": [{"HTTPBasic": []}], + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/users/me": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Current User", + "operationId": "read_current_user_users_me_get", + "security": [{"HTTPBasic": []}], + } } - } - }, - "components": { - "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} - }, - } + }, + "components": { + "securitySchemes": {"HTTPBasic": {"type": "http", "scheme": "basic"}} + }, + } + ) diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py index d0a0d5d388..0be3b59f99 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -41,102 +42,108 @@ def test_read_items(client: TestClient) -> None: def test_openapi_schema(client: TestClient) -> None: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": {"$ref": "#/components/schemas/Item"}, - "type": "array", - "title": "Response Read Items Items Get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/Item" + }, + "type": "array", + "title": "Response Read Items Items Get", + } } - } - }, - } - }, - }, - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", + "Item": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, }, + "type": "object", + "required": ["name"], + "title": "Item", }, - "type": "object", - "required": ["name"], - "title": "Item", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py index a2fa56f932..87c63f69e0 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py @@ -2,6 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot from ...utils import needs_py310 @@ -41,102 +42,108 @@ def test_read_items(client: TestClient) -> None: def test_openapi_schema(client: TestClient) -> None: response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": {"$ref": "#/components/schemas/Item"}, - "type": "array", - "title": "Response Read Items Items Get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/Item" + }, + "type": "array", + "title": "Response Read Items Items Get", + } } - } - }, - } - }, - }, - "post": { - "summary": "Create Item", - "operationId": "create_item_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Item"} + }, } }, - "required": True, }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + "post": { + "summary": "Create Item", + "operationId": "create_item_items__post", + "requestBody": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "schema": {"$ref": "#/components/schemas/Item"} } }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "Item": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "description": { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Description", + "Item": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, }, + "type": "object", + "required": ["name"], + "title": "Item", }, - "type": "object", - "required": ["name"], - "title": "Item", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_tutorial/test_settings/test_app01.py b/tests/test_tutorial/test_settings/test_app01.py index 0c5e440f1a..52b9b1e629 100644 --- a/tests/test_tutorial/test_settings/test_app01.py +++ b/tests/test_tutorial/test_settings/test_app01.py @@ -4,6 +4,7 @@ import sys import pytest from dirty_equals import IsAnyStr from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import ValidationError from pytest import MonkeyPatch @@ -58,21 +59,23 @@ def test_app(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/info": { - "get": { - "operationId": "info_info_get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Info", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/info": { + "get": { + "operationId": "info_info_get", + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Info", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_static_files/test_tutorial001.py b/tests/test_tutorial/test_static_files/test_tutorial001.py index 4fbf19ae82..dd93fee790 100644 --- a/tests/test_tutorial/test_static_files/test_tutorial001.py +++ b/tests/test_tutorial/test_static_files/test_tutorial001.py @@ -3,6 +3,7 @@ from pathlib import Path import pytest from fastapi.testclient import TestClient +from inline_snapshot import snapshot @pytest.fixture(scope="module") @@ -33,8 +34,10 @@ def test_static_files_not_found(client: TestClient): def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": {}, - } + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": {}, + } + ) diff --git a/tests/test_tutorial/test_sub_applications/test_tutorial001.py b/tests/test_tutorial/test_sub_applications/test_tutorial001.py index ef1f80164b..a8fb3dc36f 100644 --- a/tests/test_tutorial/test_sub_applications/test_tutorial001.py +++ b/tests/test_tutorial/test_sub_applications/test_tutorial001.py @@ -1,53 +1,10 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.sub_applications.tutorial001_py39 import app client = TestClient(app) -openapi_schema_main = { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/app": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Main", - "operationId": "read_main_app_get", - } - } - }, -} -openapi_schema_sub = { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/sub": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Sub", - "operationId": "read_sub_sub_get", - } - } - }, - "servers": [{"url": "/subapi"}], -} - - -def test_openapi_schema_main(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema_main - def test_main(): response = client.get("/app") @@ -55,13 +12,58 @@ def test_main(): assert response.json() == {"message": "Hello World from main app"} -def test_openapi_schema_sub(): - response = client.get("/subapi/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == openapi_schema_sub - - def test_sub(): response = client.get("/subapi/sub") assert response.status_code == 200, response.text assert response.json() == {"message": "Hello World from sub API"} + + +def test_openapi_schema_main(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/app": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Main", + "operationId": "read_main_app_get", + } + } + }, + } + ) + + +def test_openapi_schema_sub(): + response = client.get("/subapi/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/sub": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Sub", + "operationId": "read_sub_sub_get", + } + } + }, + "servers": [{"url": "/subapi"}], + } + ) diff --git a/tests/test_tutorial/test_testing/test_main_a.py b/tests/test_tutorial/test_testing/test_main_a.py index 9b3c796bdc..5284888053 100644 --- a/tests/test_tutorial/test_testing/test_main_a.py +++ b/tests/test_tutorial/test_testing/test_main_a.py @@ -1,3 +1,5 @@ +from inline_snapshot import snapshot + from docs_src.app_testing.app_a_py39.test_main import client, test_read_main @@ -8,21 +10,23 @@ def test_main(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Main", - "operationId": "read_main__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Main", + "operationId": "read_main__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_testing/test_tutorial001.py b/tests/test_tutorial/test_testing/test_tutorial001.py index 5f6533306e..2b501d36a7 100644 --- a/tests/test_tutorial/test_testing/test_tutorial001.py +++ b/tests/test_tutorial/test_testing/test_tutorial001.py @@ -1,3 +1,5 @@ +from inline_snapshot import snapshot + from docs_src.app_testing.tutorial001_py39 import client, test_read_main @@ -8,21 +10,23 @@ def test_main(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - "summary": "Read Main", - "operationId": "read_main__get", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + "summary": "Read Main", + "operationId": "read_main__get", + } } - } - }, - } + }, + } + ) diff --git a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py index b55bfb4567..cb8ae8b050 100644 --- a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py @@ -1,4 +1,5 @@ from fastapi.testclient import TestClient +from inline_snapshot import snapshot from docs_src.using_request_directly.tutorial001_py39 import app @@ -14,101 +15,103 @@ def test_path_operation(): def test_openapi(): response = client.get("/openapi.json") assert response.status_code == 200 - assert response.json() == { - "info": { - "title": "FastAPI", - "version": "0.1.0", - }, - "openapi": "3.1.0", - "paths": { - "/items/{item_id}": { - "get": { - "operationId": "read_root_items__item_id__get", - "parameters": [ - { - "in": "path", - "name": "item_id", - "required": True, - "schema": { - "title": "Item Id", - "type": "string", + assert response.json() == snapshot( + { + "info": { + "title": "FastAPI", + "version": "0.1.0", + }, + "openapi": "3.1.0", + "paths": { + "/items/{item_id}": { + "get": { + "operationId": "read_root_items__item_id__get", + "parameters": [ + { + "in": "path", + "name": "item_id", + "required": True, + "schema": { + "title": "Item Id", + "type": "string", + }, }, - }, - ], - "responses": { - "200": { - "content": { - "application/json": { - "schema": {}, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {}, + }, }, + "description": "Successful Response", }, - "description": "Successful Response", - }, - "422": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError", + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError", + }, }, }, + "description": "Validation Error", }, - "description": "Validation Error", }, + "summary": "Read Root", }, - "summary": "Read Root", }, }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError", + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError", + }, + "title": "Detail", + "type": "array", }, - "title": "Detail", - "type": "array", }, + "title": "HTTPValidationError", + "type": "object", }, - "title": "HTTPValidationError", - "type": "object", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "integer", - }, - ], + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + ], + }, + "title": "Location", + "type": "array", + }, + "msg": { + "title": "Message", + "type": "string", + }, + "type": { + "title": "Error Type", + "type": "string", }, - "title": "Location", - "type": "array", - }, - "msg": { - "title": "Message", - "type": "string", - }, - "type": { - "title": "Error Type", - "type": "string", }, + "required": [ + "loc", + "msg", + "type", + ], + "title": "ValidationError", + "type": "object", }, - "required": [ - "loc", - "msg", - "type", - ], - "title": "ValidationError", - "type": "object", }, }, - }, - } + } + ) diff --git a/tests/test_union_body.py b/tests/test_union_body.py index ee56bb6eb1..e333e2499f 100644 --- a/tests/test_union_body.py +++ b/tests/test_union_body.py @@ -2,6 +2,7 @@ from typing import Optional, Union from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -38,94 +39,98 @@ def test_post_item(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Save Union Body", + "operationId": "save_union_body_items__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Item", + "anyOf": [ + {"$ref": "#/components/schemas/OtherItem"}, + {"$ref": "#/components/schemas/Item"}, + ], } } }, + "required": True, }, + } + } + }, + "components": { + "schemas": { + "OtherItem": { + "title": "OtherItem", + "required": ["price"], + "type": "object", + "properties": {"price": {"title": "Price", "type": "integer"}}, }, - "summary": "Save Union Body", - "operationId": "save_union_body_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Item", - "anyOf": [ - {"$ref": "#/components/schemas/OtherItem"}, - {"$ref": "#/components/schemas/Item"}, - ], - } + "Item": { + "title": "Item", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], } }, - "required": True, }, - } - } - }, - "components": { - "schemas": { - "OtherItem": { - "title": "OtherItem", - "required": ["price"], - "type": "object", - "properties": {"price": {"title": "Price", "type": "integer"}}, - }, - "Item": { - "title": "Item", - "type": "object", - "properties": { - "name": { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py index d90d0753a9..f6c2658f96 100644 --- a/tests/test_union_forms.py +++ b/tests/test_union_forms.py @@ -2,6 +2,7 @@ from typing import Annotated, Union from fastapi import FastAPI, Form from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -61,97 +62,102 @@ def test_empty_form(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/form-union/": { - "post": { - "summary": "Post Union Form", - "operationId": "post_union_form_form_union__post", - "requestBody": { - "content": { - "application/x-www-form-urlencoded": { - "schema": { - "anyOf": [ - {"$ref": "#/components/schemas/UserForm"}, - {"$ref": "#/components/schemas/CompanyForm"}, - ], - "title": "Data", - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/form-union/": { + "post": { + "summary": "Post Union Form", + "operationId": "post_union_form_form_union__post", + "requestBody": { "content": { - "application/json": { + "application/x-www-form-urlencoded": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "anyOf": [ + {"$ref": "#/components/schemas/UserForm"}, + { + "$ref": "#/components/schemas/CompanyForm" + }, + ], + "title": "Data", } } }, + "required": True, }, - }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } } - } - }, - "components": { - "schemas": { - "CompanyForm": { - "properties": { - "company_name": {"type": "string", "title": "Company Name"}, - "industry": {"type": "string", "title": "Industry"}, + }, + "components": { + "schemas": { + "CompanyForm": { + "properties": { + "company_name": {"type": "string", "title": "Company Name"}, + "industry": {"type": "string", "title": "Industry"}, + }, + "type": "object", + "required": ["company_name", "industry"], + "title": "CompanyForm", }, - "type": "object", - "required": ["company_name", "industry"], - "title": "CompanyForm", - }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "UserForm": { - "properties": { - "name": {"type": "string", "title": "Name"}, - "email": {"type": "string", "title": "Email"}, + "UserForm": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "email": {"type": "string", "title": "Email"}, + }, + "type": "object", + "required": ["name", "email"], + "title": "UserForm", }, - "type": "object", - "required": ["name", "email"], - "title": "UserForm", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_union_inherited_body.py b/tests/test_union_inherited_body.py index 6b284c68c3..5378880a47 100644 --- a/tests/test_union_inherited_body.py +++ b/tests/test_union_inherited_body.py @@ -2,6 +2,7 @@ from typing import Optional, Union from fastapi import FastAPI from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -38,100 +39,106 @@ def test_post_item(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, }, - "422": { - "description": "Validation Error", + "summary": "Save Union Different Body", + "operationId": "save_union_different_body_items__post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "title": "Item", + "anyOf": [ + { + "$ref": "#/components/schemas/ExtendedItem" + }, + {"$ref": "#/components/schemas/Item"}, + ], } } }, + "required": True, }, - }, - "summary": "Save Union Different Body", - "operationId": "save_union_different_body_items__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "Item", - "anyOf": [ - {"$ref": "#/components/schemas/ExtendedItem"}, - {"$ref": "#/components/schemas/Item"}, - ], - } + } + } + }, + "components": { + "schemas": { + "Item": { + "title": "Item", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], } }, - "required": True, }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "type": "object", - "properties": { - "name": { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - }, - }, - "ExtendedItem": { - "title": "ExtendedItem", - "required": ["age"], - "type": "object", - "properties": { - "name": { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], + "ExtendedItem": { + "title": "ExtendedItem", + "required": ["age"], + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "age": {"title": "Age", "type": "integer"}, }, - "age": {"title": "Age", "type": "integer"}, }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + "input": {"title": "Input"}, + "ctx": {"title": "Context", "type": "object"}, }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + } + }, }, - }, - } - }, - } + } + }, + } + ) diff --git a/tests/test_webhooks_security.py b/tests/test_webhooks_security.py index c2c2809b2f..267e450d12 100644 --- a/tests/test_webhooks_security.py +++ b/tests/test_webhooks_security.py @@ -4,6 +4,7 @@ from typing import Annotated from fastapi import FastAPI, Security from fastapi.security import HTTPBearer from fastapi.testclient import TestClient +from inline_snapshot import snapshot from pydantic import BaseModel app = FastAPI() @@ -38,91 +39,96 @@ def test_dummy_webhook(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - # insert_assert(response.json()) - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": {}, - "webhooks": { - "new-subscription": { - "post": { - "summary": "New Subscription", - "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", - "operationId": "new_subscriptionnew_subscription_post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Subscription"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": {}, + "webhooks": { + "new-subscription": { + "post": { + "summary": "New Subscription", + "description": "When a new user subscribes to your service we'll send you a POST request with this\ndata to the URL that you register for the event `new-subscription` in the dashboard.", + "operationId": "new_subscriptionnew_subscription_post", + "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/Subscription" } } }, + "required": True, }, - }, - "security": [{"HTTPBearer": []}], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "security": [{"HTTPBearer": []}], + } } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "properties": { - "detail": { - "items": {"$ref": "#/components/schemas/ValidationError"}, - "type": "array", - "title": "Detail", - } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", }, - "type": "object", - "title": "HTTPValidationError", - }, - "Subscription": { - "properties": { - "username": {"type": "string", "title": "Username"}, - "monthly_fee": {"type": "number", "title": "Monthly Fee"}, - "start_date": { - "type": "string", - "format": "date-time", - "title": "Start Date", + "Subscription": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "monthly_fee": {"type": "number", "title": "Monthly Fee"}, + "start_date": { + "type": "string", + "format": "date-time", + "title": "Start Date", + }, }, + "type": "object", + "required": ["username", "monthly_fee", "start_date"], + "title": "Subscription", }, - "type": "object", - "required": ["username", "monthly_fee", "start_date"], - "title": "Subscription", - }, - "ValidationError": { - "properties": { - "ctx": {"title": "Context", "type": "object"}, - "input": {"title": "Input"}, - "loc": { - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", }, - "type": "array", - "title": "Location", + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, }, - "msg": {"type": "string", "title": "Message"}, - "type": {"type": "string", "title": "Error Type"}, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", }, - "type": "object", - "required": ["loc", "msg", "type"], - "title": "ValidationError", }, + "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}}, }, - "securitySchemes": {"HTTPBearer": {"type": "http", "scheme": "bearer"}}, - }, - } + } + ) From 79d4dfb37fd2e67090b29ed770bd096fd861f3cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Feb 2026 10:19:07 +0000 Subject: [PATCH 170/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5d93b684af..a0234366e7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * โ™ป๏ธ Refactor and simplify Pydantic v2 (and v1) compatibility internal utils. PR [#14862](https://github.com/fastapi/fastapi/pull/14862) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* โœ… Add inline snapshot tests for OpenAPI before changes from Pydantic v2. PR [#14864](https://github.com/fastapi/fastapi/pull/14864) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.4 ### Refactors From dedf1409fe8c095b8881ab732e132e66e9eae997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 8 Feb 2026 11:20:22 +0100 Subject: [PATCH 171/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a0234366e7..5a714d1a03 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.5 + ### Refactors * โ™ป๏ธ Refactor and simplify Pydantic v2 (and v1) compatibility internal utils. PR [#14862](https://github.com/fastapi/fastapi/pull/14862) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 580919a81c..1176856891 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.4" +__version__ = "0.128.5" from starlette import status as status From 376e1085807ddf6f899189340eb0d0217dbb74f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 8 Feb 2026 02:39:41 -0800 Subject: [PATCH 172/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(update-outdated)=20(#14843)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/en/mkdocs.yml | 2 + docs/zh/docs/advanced/additional-responses.md | 140 ++-- .../docs/advanced/additional-status-codes.md | 14 +- .../zh/docs/advanced/advanced-dependencies.md | 156 ++++- docs/zh/docs/advanced/async-tests.md | 32 +- docs/zh/docs/advanced/behind-a-proxy.md | 287 +++++--- docs/zh/docs/advanced/custom-response.md | 194 ++++-- docs/zh/docs/advanced/dataclasses.md | 98 ++- docs/zh/docs/advanced/events.md | 104 ++- docs/zh/docs/advanced/generate-clients.md | 223 +++--- docs/zh/docs/advanced/index.md | 20 +- docs/zh/docs/advanced/middleware.md | 36 +- docs/zh/docs/advanced/openapi-callbacks.md | 56 +- docs/zh/docs/advanced/openapi-webhooks.md | 16 +- .../path-operation-advanced-configuration.md | 148 +++- .../advanced/response-change-status-code.md | 10 +- docs/zh/docs/advanced/response-cookies.md | 18 +- docs/zh/docs/advanced/response-directly.md | 29 +- docs/zh/docs/advanced/response-headers.md | 36 +- .../docs/advanced/security/http-basic-auth.md | 26 +- docs/zh/docs/advanced/security/index.md | 16 +- .../docs/advanced/security/oauth2-scopes.md | 258 +++---- docs/zh/docs/advanced/settings.md | 289 +++----- docs/zh/docs/advanced/sub-applications.md | 28 +- docs/zh/docs/advanced/templates.md | 48 +- docs/zh/docs/advanced/testing-dependencies.md | 9 +- docs/zh/docs/advanced/testing-events.md | 12 +- docs/zh/docs/advanced/testing-websockets.md | 12 +- .../docs/advanced/using-request-directly.md | 14 +- docs/zh/docs/advanced/websockets.md | 64 +- docs/zh/docs/advanced/wsgi.md | 32 +- docs/zh/docs/async.md | 74 +- docs/zh/docs/benchmarks.md | 22 +- docs/zh/docs/deployment/cloud.md | 25 +- docs/zh/docs/deployment/concepts.md | 115 ++-- docs/zh/docs/deployment/docker.md | 648 +++++++----------- docs/zh/docs/deployment/https.md | 99 ++- docs/zh/docs/deployment/index.md | 12 +- docs/zh/docs/deployment/manually.md | 17 +- docs/zh/docs/deployment/server-workers.md | 12 +- docs/zh/docs/deployment/versions.md | 48 +- docs/zh/docs/environment-variables.md | 32 +- docs/zh/docs/fastapi-cli.md | 20 +- docs/zh/docs/features.md | 110 ++- docs/zh/docs/help-fastapi.md | 267 +++++--- docs/zh/docs/history-design-future.md | 19 +- docs/zh/docs/how-to/configure-swagger-ui.md | 24 +- docs/zh/docs/how-to/general.md | 24 +- docs/zh/docs/how-to/index.md | 4 +- docs/zh/docs/index.md | 443 +++++++----- docs/zh/docs/learn/index.md | 2 +- docs/zh/docs/project-generation.md | 44 +- docs/zh/docs/python-types.md | 418 +++++++---- docs/zh/docs/tutorial/background-tasks.md | 64 +- docs/zh/docs/tutorial/bigger-applications.md | 134 ++-- docs/zh/docs/tutorial/body-fields.md | 19 +- docs/zh/docs/tutorial/body-multiple-params.md | 34 +- docs/zh/docs/tutorial/body-nested-models.md | 67 +- docs/zh/docs/tutorial/body-updates.md | 87 +-- docs/zh/docs/tutorial/body.md | 114 +-- docs/zh/docs/tutorial/cookie-param-models.md | 18 +- docs/zh/docs/tutorial/cookie-params.md | 23 +- docs/zh/docs/tutorial/cors.md | 39 +- docs/zh/docs/tutorial/debugging.md | 14 +- .../dependencies/classes-as-dependencies.md | 158 ++++- ...pendencies-in-path-operation-decorators.md | 30 +- .../dependencies/dependencies-with-yield.md | 200 +++--- .../dependencies/global-dependencies.md | 10 +- docs/zh/docs/tutorial/dependencies/index.md | 200 +++--- .../tutorial/dependencies/sub-dependencies.md | 45 +- docs/zh/docs/tutorial/encoder.md | 6 +- docs/zh/docs/tutorial/extra-data-types.md | 14 +- docs/zh/docs/tutorial/extra-models.md | 104 +-- docs/zh/docs/tutorial/first-steps.md | 117 +++- docs/zh/docs/tutorial/handling-errors.md | 171 ++--- docs/zh/docs/tutorial/header-param-models.md | 28 +- docs/zh/docs/tutorial/header-params.md | 14 +- docs/zh/docs/tutorial/index.md | 16 +- docs/zh/docs/tutorial/metadata.md | 74 +- docs/zh/docs/tutorial/middleware.md | 93 ++- .../tutorial/path-operation-configuration.md | 58 +- .../path-params-numeric-validations.md | 127 ++-- docs/zh/docs/tutorial/path-params.md | 147 ++-- docs/zh/docs/tutorial/query-param-models.md | 16 +- .../tutorial/query-params-str-validations.md | 403 ++++++++--- docs/zh/docs/tutorial/query-params.md | 51 +- docs/zh/docs/tutorial/request-files.md | 142 ++-- docs/zh/docs/tutorial/request-form-models.md | 38 +- .../docs/tutorial/request-forms-and-files.md | 22 +- docs/zh/docs/tutorial/request-forms.md | 58 +- docs/zh/docs/tutorial/response-model.md | 284 +++++--- docs/zh/docs/tutorial/response-status-code.md | 48 +- docs/zh/docs/tutorial/schema-extra-example.md | 199 +++++- docs/zh/docs/tutorial/security/first-steps.md | 174 ++--- .../tutorial/security/get-current-user.md | 28 +- docs/zh/docs/tutorial/security/index.md | 26 +- docs/zh/docs/tutorial/security/oauth2-jwt.md | 207 +++--- .../docs/tutorial/security/simple-oauth2.md | 66 +- docs/zh/docs/tutorial/sql-databases.md | 195 +++--- docs/zh/docs/tutorial/static-files.md | 38 +- docs/zh/docs/tutorial/testing.md | 92 +-- docs/zh/docs/virtual-environments.md | 106 +-- scripts/docs.py | 2 +- 103 files changed, 5330 insertions(+), 3996 deletions(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index ccf5ffc7a0..60d2f977e5 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -331,6 +331,8 @@ extra: name: tr - Tรผrkรงe - link: /uk/ name: uk - ัƒะบั€ะฐั—ะฝััŒะบะฐ ะผะพะฒะฐ + - link: /zh/ + name: zh - ็ฎ€ไฝ“ไธญๆ–‡ - link: /zh-hant/ name: zh-hant - ็น้ซ”ไธญๆ–‡ extra_css: diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md index 362ef9460a..bc197280ab 100644 --- a/docs/zh/docs/advanced/additional-responses.md +++ b/docs/zh/docs/advanced/additional-responses.md @@ -1,44 +1,57 @@ -# OPENAPI ไธญ็š„ๅ…ถไป–ๅ“ๅบ” +# OpenAPI ไธญ็š„้™„ๅŠ ๅ“ๅบ” { #additional-responses-in-openapi } -ๆ‚จๅฏไปฅๅฃฐๆ˜Ž้™„ๅŠ ๅ“ๅบ”๏ผŒๅŒ…ๆ‹ฌ้™„ๅŠ ็Šถๆ€ไปฃ็ ใ€ๅช’ไฝ“็ฑปๅž‹ใ€ๆ่ฟฐ็ญ‰ใ€‚ +/// warning | ่ญฆๅ‘Š -่ฟ™ไบ›้ขๅค–็š„ๅ“ๅบ”ๅฐ†ๅŒ…ๅซๅœจOpenAPIๆจกๅผไธญ๏ผŒๅ› ๆญคๅฎƒไปฌไนŸๅฐ†ๅ‡บ็ŽฐๅœจAPIๆ–‡ๆกฃไธญใ€‚ +่ฟ™ๆ˜ฏไธ€ไธช็›ธๅฏน้ซ˜็บง็š„่ฏ้ข˜ใ€‚ -ไฝ†ๆ˜ฏๅฏนไบŽ้‚ฃไบ›้ขๅค–็š„ๅ“ๅบ”๏ผŒไฝ ๅฟ…้กป็กฎไฟไฝ ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธชๅƒ `JSONResponse` ไธ€ๆ ท็š„ `Response` ๏ผŒๅนถๅŒ…ๅซไฝ ็š„็Šถๆ€ไปฃ็ ๅ’Œๅ†…ๅฎนใ€‚ +ๅฆ‚ๆžœไฝ ๅˆšๅผ€ๅง‹ไฝฟ็”จ **FastAPI**๏ผŒๅฏ่ƒฝๆš‚ๆ—ถ็”จไธๅˆฐใ€‚ -## `model`้™„ๅŠ ๅ“ๅบ” -ๆ‚จๅฏไปฅๅ‘่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไผ ้€’ๅ‚ๆ•ฐ `responses` ใ€‚ +/// + +ไฝ ๅฏไปฅๅฃฐๆ˜Ž้™„ๅŠ ๅ“ๅบ”๏ผŒๅŒ…ๆ‹ฌ้ขๅค–็š„็Šถๆ€็ ใ€ๅช’ไฝ“็ฑปๅž‹ใ€ๆ่ฟฐ็ญ‰ใ€‚ + +่ฟ™ไบ›้™„ๅŠ ๅ“ๅบ”ไผš่ขซๅŒ…ๅซๅœจ OpenAPI ๆจกๅผไธญ๏ผŒๅ› ๆญคๅฎƒไปฌไนŸไผšๅ‡บ็Žฐๅœจ API ๆ–‡ๆกฃไธญใ€‚ + +ไฝ†ๆ˜ฏๅฏนไบŽ่ฟ™ไบ›้™„ๅŠ ๅ“ๅบ”๏ผŒไฝ ๅฟ…้กป็กฎไฟ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `Response`๏ผˆไพ‹ๅฆ‚ `JSONResponse`๏ผ‰๏ผŒๅนถๆบๅธฆไฝ ็š„็Šถๆ€็ ๅ’Œๅ†…ๅฎนใ€‚ + +## ๅธฆๆœ‰ `model` ็š„้™„ๅŠ ๅ“ๅบ” { #additional-response-with-model } + +ไฝ ๅฏไปฅๅ‘ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไผ ๅ…ฅๅ‚ๆ•ฐ `responses`ใ€‚ + +ๅฎƒๆŽฅๆ”ถไธ€ไธช `dict`๏ผš้”ฎๆ˜ฏๆฏไธชๅ“ๅบ”็š„็Šถๆ€็ ๏ผˆไพ‹ๅฆ‚ `200`๏ผ‰๏ผŒๅ€ผๆ˜ฏๅŒ…ๅซ่ฏฅๅ“ๅบ”ไฟกๆฏ็š„ๅฆไธ€ไธช `dict`ใ€‚ -ๅฎƒๆŽฅๆ”ถไธ€ไธช `dict`๏ผŒ้”ฎๆ˜ฏๆฏไธชๅ“ๅบ”็š„็Šถๆ€ไปฃ็ ๏ผˆๅฆ‚`200`๏ผ‰๏ผŒๅ€ผๆ˜ฏๅŒ…ๅซๆฏไธชๅ“ๅบ”ไฟกๆฏ็š„ๅ…ถไป– `dict`ใ€‚ +่ฟ™ไบ›ๅ“ๅบ”็š„ๆฏไธช `dict` ้ƒฝๅฏไปฅๆœ‰ไธ€ไธช้”ฎ `model`๏ผŒๅŒ…ๅซไธ€ไธช Pydantic ๆจกๅž‹๏ผŒๅฐฑๅƒ `response_model` ไธ€ๆ ทใ€‚ -ๆฏไธชๅ“ๅบ”ๅญ—ๅ…ธ้ƒฝๅฏไปฅๆœ‰ไธ€ไธชๅ…ณ้”ฎๆจกๅž‹๏ผŒๅ…ถไธญๅŒ…ๅซไธ€ไธช `Pydantic` ๆจกๅž‹๏ผŒๅฐฑๅƒ `response_model` ไธ€ๆ ทใ€‚ +**FastAPI** ไผš่Žทๅ–่ฏฅๆจกๅž‹๏ผŒ็”Ÿๆˆๅฎƒ็š„ JSON Schema๏ผŒๅนถๅฐ†ๅ…ถๆ”พๅœจ OpenAPI ไธญ็š„ๆญฃ็กฎไฝ็ฝฎใ€‚ -**FastAPI**ๅฐ†้‡‡็”จ่ฏฅๆจกๅž‹๏ผŒ็”Ÿๆˆๅ…ถ`JSON Schema`ๅนถๅฐ†ๅ…ถๅŒ…ๅซๅœจ`OpenAPI`ไธญ็š„ๆญฃ็กฎไฝ็ฝฎใ€‚ +ไพ‹ๅฆ‚๏ผŒ่ฆๅฃฐๆ˜Žๅฆไธ€ไธช็Šถๆ€็ ไธบ `404` ไธ”ๅ…ทๆœ‰ Pydantic ๆจกๅž‹ `Message` ็š„ๅ“ๅบ”๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ทๅ†™๏ผš -ไพ‹ๅฆ‚๏ผŒ่ฆๅฃฐๆ˜Žๅฆไธ€ไธชๅ…ทๆœ‰็Šถๆ€็  `404` ๅ’Œ`Pydantic`ๆจกๅž‹ `Message` ็š„ๅ“ๅบ”๏ผŒๅฏไปฅๅ†™๏ผš -{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} -/// note +/// note | ๆณจๆ„ -่ฏท่ฎฐไฝ๏ผŒๆ‚จๅฟ…้กป็›ดๆŽฅ่ฟ”ๅ›ž `JSONResponse` ใ€‚ +่ฎฐไฝไฝ ้œ€่ฆ็›ดๆŽฅ่ฟ”ๅ›ž `JSONResponse`ใ€‚ /// -/// info +/// info | ไฟกๆฏ -`model` ๅฏ†้’ฅไธๆ˜ฏOpenAPI็š„ไธ€้ƒจๅˆ†ใ€‚ -**FastAPI**ๅฐ†ไปŽ้‚ฃ้‡Œ่Žทๅ–`Pydantic`ๆจกๅž‹๏ผŒ็”Ÿๆˆ` JSON Schema` ๏ผŒๅนถๅฐ†ๅ…ถๆ”พๅœจๆญฃ็กฎ็š„ไฝ็ฝฎใ€‚ -- ๆญฃ็กฎ็š„ไฝ็ฝฎๆ˜ฏ๏ผš - - ๅœจ้”ฎ `content` ไธญ๏ผŒๅ…ถๅ…ทๆœ‰ๅฆไธ€ไธช`JSON`ๅฏน่ฑก๏ผˆ `dict` ๏ผ‰ไฝœไธบๅ€ผ๏ผŒ่ฏฅ`JSON`ๅฏน่ฑกๅŒ…ๅซ๏ผš - - ๅช’ไฝ“็ฑปๅž‹็š„ๅฏ†้’ฅ๏ผŒไพ‹ๅฆ‚ `application/json` ๏ผŒๅฎƒๅŒ…ๅซๅฆไธ€ไธช`JSON`ๅฏน่ฑกไฝœไธบๅ€ผ๏ผŒ่ฏฅๅฏน่ฑกๅŒ…ๅซ๏ผš - - ไธ€ไธช้”ฎ` schema` ๏ผŒๅฎƒ็š„ๅ€ผๆ˜ฏๆฅ่‡ชๆจกๅž‹็š„`JSON Schema`๏ผŒๆญฃ็กฎ็š„ไฝ็ฝฎๅœจ่ฟ™้‡Œใ€‚ - - **FastAPI**ๅœจ่ฟ™้‡ŒๆทปๅŠ ไบ†ๅฏนOpenAPIไธญๅฆไธ€ไธชๅœฐๆ–น็š„ๅ…จๅฑ€JSONๆจกๅผ็š„ๅผ•็”จ๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๅŒ…ๅซๅฎƒใ€‚่ฟ™ๆ ท๏ผŒๅ…ถไป–ๅบ”็”จ็จ‹ๅบๅ’Œๅฎขๆˆท็ซฏๅฏไปฅ็›ดๆŽฅไฝฟ็”จ่ฟ™ไบ›JSONๆจกๅผ๏ผŒๆไพ›ๆ›ดๅฅฝ็š„ไปฃ็ ็”Ÿๆˆๅทฅๅ…ท็ญ‰ใ€‚ +`model` ้”ฎไธๆ˜ฏ OpenAPI ็š„ไธ€้ƒจๅˆ†ใ€‚ + +**FastAPI** ไผšไปŽ่ฟ™้‡Œ่Žทๅ– Pydantic ๆจกๅž‹๏ผŒ็”Ÿๆˆ JSON Schema๏ผŒๅนถๆŠŠๅฎƒๆ”พๅˆฐๆญฃ็กฎ็š„ไฝ็ฝฎใ€‚ + +ๆญฃ็กฎ็š„ไฝ็ฝฎๆ˜ฏ๏ผš + +* ๅœจ้”ฎ `content` ไธญ๏ผŒๅฎƒ็š„ๅ€ผๆ˜ฏๅฆไธ€ไธช JSON ๅฏน่ฑก๏ผˆ`dict`๏ผ‰๏ผŒ่ฏฅๅฏน่ฑกๅŒ…ๅซ๏ผš + * ไธ€ไธชๅช’ไฝ“็ฑปๅž‹ไฝœไธบ้”ฎ๏ผŒไพ‹ๅฆ‚ `application/json`๏ผŒๅฎƒ็š„ๅ€ผๆ˜ฏๅฆไธ€ไธช JSON ๅฏน่ฑก๏ผŒ่ฏฅๅฏน่ฑกๅŒ…ๅซ๏ผš + * ไธ€ไธช้”ฎ `schema`๏ผŒๅฎƒ็š„ๅ€ผๆ˜ฏๆฅ่‡ช่ฏฅๆจกๅž‹็š„ JSON Schema๏ผŒ่ฟ™้‡Œๅฐฑๆ˜ฏๆญฃ็กฎ็š„ไฝ็ฝฎใ€‚ + * **FastAPI** ไผšๅœจ่ฟ™้‡ŒๆทปๅŠ ไธ€ไธชๅผ•็”จ๏ผŒๆŒ‡ๅ‘ไฝ  OpenAPI ไธญๅฆไธ€ไธชไฝ็ฝฎ็š„ๅ…จๅฑ€ JSON Schemas๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๅ†…่”ใ€‚่ฟ™ๆ ท๏ผŒๅ…ถไป–ๅบ”็”จๅ’Œๅฎขๆˆท็ซฏๅฏไปฅ็›ดๆŽฅไฝฟ็”จ่ฟ™ไบ› JSON Schemas๏ผŒๆไพ›ๆ›ดๅฅฝ็š„ไปฃ็ ็”Ÿๆˆๅทฅๅ…ท็ญ‰ใ€‚ /// -**ๅœจOpenAPIไธญไธบ่ฏฅ่ทฏๅพ„ๆ“ไฝœ็”Ÿๆˆ็š„ๅ“ๅบ”ๅฐ†ๆ˜ฏ๏ผš** +ไธบ่ฏฅ*่ทฏๅพ„ๆ“ไฝœ*ๅœจ OpenAPI ไธญ็”Ÿๆˆ็š„ๅ“ๅบ”ๅฐ†ๆ˜ฏ๏ผš -```json hl_lines="3-12" +```JSON hl_lines="3-12" { "responses": { "404": { @@ -73,10 +86,11 @@ } } } - ``` -**ๆจกๅผ่ขซๅผ•็”จๅˆฐOpenAPIๆจกๅผไธญ็š„ๅฆไธ€ไธชไฝ็ฝฎ๏ผš** -```json hl_lines="4-16" + +่ฟ™ไบ›ๆจกๅผๅœจ OpenAPI ๆจกๅผไธญ่ขซๅผ•็”จๅˆฐๅฆไธ€ไธชไฝ็ฝฎ๏ผš + +```JSON hl_lines="4-16" { "components": { "schemas": { @@ -153,48 +167,54 @@ } } } - ``` -## ไธปๅ“ๅบ”็š„ๅ…ถไป–ๅช’ไฝ“็ฑปๅž‹ -ๆ‚จๅฏไปฅไฝฟ็”จ็›ธๅŒ็š„ `responses` ๅ‚ๆ•ฐไธบ็›ธๅŒ็š„ไธปๅ“ๅบ”ๆทปๅŠ ไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹ใ€‚ +## ไธปๅ“ๅบ”็š„ๅ…ถไป–ๅช’ไฝ“็ฑปๅž‹ { #additional-media-types-for-the-main-response } -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅๆทปๅŠ ไธ€ไธช้ขๅค–็š„ๅช’ไฝ“็ฑปๅž‹` image/png` ๏ผŒๅฃฐๆ˜Žๆ‚จ็š„่ทฏๅพ„ๆ“ไฝœๅฏไปฅ่ฟ”ๅ›žJSONๅฏน่ฑก๏ผˆๅช’ไฝ“็ฑปๅž‹ `application/json` ๏ผ‰ๆˆ–PNGๅ›พๅƒ๏ผš +ไฝ ๅฏไปฅไฝฟ็”จๅŒไธ€ไธช `responses` ๅ‚ๆ•ฐไธบๅŒไธ€ไธชไธปๅ“ๅบ”ๆทปๅŠ ไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹ใ€‚ -{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *} +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆทปๅŠ ไธ€ไธช้ขๅค–็š„ๅช’ไฝ“็ฑปๅž‹ `image/png`๏ผŒๅฃฐๆ˜Žไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅฏไปฅ่ฟ”ๅ›ž JSON ๅฏน่ฑก๏ผˆๅช’ไฝ“็ฑปๅž‹ไธบ `application/json`๏ผ‰ๆˆ– PNG ๅ›พ็‰‡๏ผš -/// note +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} -- ่ฏทๆณจๆ„๏ผŒๆ‚จๅฟ…้กป็›ดๆŽฅไฝฟ็”จ `FileResponse` ่ฟ”ๅ›žๅ›พๅƒใ€‚ +/// note | ๆณจๆ„ + +่ฏทๆณจๆ„๏ผŒไฝ ๅฟ…้กป็›ดๆŽฅไฝฟ็”จ `FileResponse` ่ฟ”ๅ›žๅ›พ็‰‡ใ€‚ /// -/// info +/// info | ไฟกๆฏ + +้™ค้žไฝ ๅœจ `responses` ๅ‚ๆ•ฐไธญๆ˜Ž็กฎๆŒ‡ๅฎšไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹๏ผŒๅฆๅˆ™ FastAPI ไผšๅ‡่ฎพๅ“ๅบ”ไธŽไธปๅ“ๅบ”็ฑปๅ…ทๆœ‰็›ธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹๏ผˆ้ป˜่ฎคๆ˜ฏ `application/json`๏ผ‰ใ€‚ -- ้™ค้žๅœจ `responses` ๅ‚ๆ•ฐไธญๆ˜Ž็กฎๆŒ‡ๅฎšไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹๏ผŒๅฆๅˆ™**FastAPI**ๅฐ†ๅ‡ๅฎšๅ“ๅบ”ไธŽไธปๅ“ๅบ”็ฑปๅ…ทๆœ‰็›ธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹๏ผˆ้ป˜่ฎคไธบ` application/json` ๏ผ‰ใ€‚ -- ไฝ†ๆ˜ฏๅฆ‚ๆžœๆ‚จๆŒ‡ๅฎšไบ†ไธ€ไธช่‡ชๅฎšไน‰ๅ“ๅบ”็ฑป๏ผŒๅนถๅฐ† `None `ไฝœไธบๅ…ถๅช’ไฝ“็ฑปๅž‹๏ผŒ**FastAPI**ๅฐ†ไฝฟ็”จ `application/json` ไฝœไธบๅ…ทๆœ‰ๅ…ณ่”ๆจกๅž‹็š„ไปปไฝ•ๅ…ถไป–ๅ“ๅบ”ใ€‚ +ไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ๆŒ‡ๅฎšไบ†ไธ€ไธชๅช’ไฝ“็ฑปๅž‹ไธบ `None` ็š„่‡ชๅฎšไน‰ๅ“ๅบ”็ฑป๏ผŒFastAPI ไผšๅฏนไปปไฝ•ๅ…ทๆœ‰ๅ…ณ่”ๆจกๅž‹็š„้™„ๅŠ ๅ“ๅบ”ไฝฟ็”จ `application/json`ใ€‚ /// -## ็ป„ๅˆไฟกๆฏ -ๆ‚จ่ฟ˜ๅฏไปฅ่”ๅˆๆŽฅๆ”ถๆฅ่‡ชๅคšไธชไฝ็ฝฎ็š„ๅ“ๅบ”ไฟกๆฏ๏ผŒๅŒ…ๆ‹ฌ `response_model `ใ€ `status_code` ๅ’Œ `responses `ๅ‚ๆ•ฐใ€‚ +## ็ป„ๅˆไฟกๆฏ { #combining-information } + +ไฝ ไนŸๅฏไปฅๆŠŠๆฅ่‡ชๅคšไธชไฝ็ฝฎ็š„ๅ“ๅบ”ไฟกๆฏ็ป„ๅˆๅœจไธ€่ตท๏ผŒๅŒ…ๆ‹ฌ `response_model`ใ€`status_code` ๅ’Œ `responses` ๅ‚ๆ•ฐใ€‚ + +ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธช `response_model`๏ผŒไฝฟ็”จ้ป˜่ฎค็Šถๆ€็  `200`๏ผˆๆˆ–ๆ นๆฎ้œ€่ฆไฝฟ็”จ่‡ชๅฎšไน‰็Šถๆ€็ ๏ผ‰๏ผŒ็„ถๅŽๅœจ `responses` ไธญ็›ดๆŽฅๅœจ OpenAPI ๆจกๅผ้‡ŒไธบๅŒไธ€ไธชๅ“ๅบ”ๅฃฐๆ˜Ž้™„ๅŠ ไฟกๆฏใ€‚ -ๆ‚จๅฏไปฅไฝฟ็”จ้ป˜่ฎค็š„็Šถๆ€็  `200` ๏ผˆๆˆ–่€…ๆ‚จ้œ€่ฆ็š„่‡ชๅฎšไน‰็Šถๆ€็ ๏ผ‰ๅฃฐๆ˜Žไธ€ไธช `response_model `๏ผŒ็„ถๅŽ็›ดๆŽฅๅœจOpenAPIๆจกๅผไธญๅœจ `responses` ไธญๅฃฐๆ˜Ž็›ธๅŒๅ“ๅบ”็š„ๅ…ถไป–ไฟกๆฏใ€‚ +**FastAPI** ไผšไฟ็•™ๆฅ่‡ช `responses` ็š„้™„ๅŠ ไฟกๆฏ๏ผŒๅนถๆŠŠๅฎƒไธŽไฝ ็š„ๆจกๅž‹็”Ÿๆˆ็š„ JSON Schema ๅˆๅนถใ€‚ -**FastAPI**ๅฐ†ไฟ็•™ๆฅ่‡ช `responses` ็š„้™„ๅŠ ไฟกๆฏ๏ผŒๅนถๅฐ†ๅ…ถไธŽๆจกๅž‹ไธญ็š„JSON Schema็ป“ๅˆ่ตทๆฅใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธช็Šถๆ€็ ไธบ `404` ็š„ๅ“ๅบ”๏ผŒๅฎƒไฝฟ็”จไธ€ไธช Pydantic ๆจกๅž‹ๅนถๅธฆๆœ‰่‡ชๅฎšไน‰็š„ `description`ใ€‚ -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ็Šถๆ€็  `404` ๅฃฐๆ˜Žๅ“ๅบ”๏ผŒ่ฏฅๅ“ๅบ”ไฝฟ็”จ`Pydantic`ๆจกๅž‹ๅนถๅ…ทๆœ‰่‡ชๅฎšไน‰็š„` description` ใ€‚ +ไปฅๅŠไธ€ไธช็Šถๆ€็ ไธบ `200` ็š„ๅ“ๅบ”๏ผŒๅฎƒไฝฟ็”จไฝ ็š„ `response_model`๏ผŒไฝ†ๅŒ…ๅซ่‡ชๅฎšไน‰็š„ `example`๏ผš -ไปฅๅŠไธ€ไธช็Šถๆ€็ ไธบ `200` ็š„ๅ“ๅบ”๏ผŒๅฎƒไฝฟ็”จๆ‚จ็š„ `response_model` ๏ผŒไฝ†ๅŒ…ๅซ่‡ชๅฎšไน‰็š„ `example` ๏ผš +{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} -{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *} +ๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝไผš่ขซๅˆๅนถๅนถๅŒ…ๅซๅˆฐไฝ ็š„ OpenAPI ไธญ๏ผŒๅนถๆ˜พ็คบๅœจ API ๆ–‡ๆกฃ้‡Œ๏ผš -ๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝๅฐ†่ขซๅˆๅนถๅนถๅŒ…ๅซๅœจๆ‚จ็š„OpenAPIไธญ๏ผŒๅนถๅœจAPIๆ–‡ๆกฃไธญๆ˜พ็คบ๏ผš + -## ่”ๅˆ้ข„ๅฎšไน‰ๅ“ๅบ”ๅ’Œ่‡ชๅฎšไน‰ๅ“ๅบ” +## ็ป„ๅˆ้ข„ๅฎšไน‰ๅ“ๅบ”ๅ’Œ่‡ชๅฎšไน‰ๅ“ๅบ” { #combine-predefined-responses-and-custom-ones } + +ไฝ ๅฏ่ƒฝๅธŒๆœ›ๆœ‰ไธ€ไบ›้€‚็”จไบŽ่ฎธๅคš*่ทฏๅพ„ๆ“ไฝœ*็š„้ข„ๅฎšไน‰ๅ“ๅบ”๏ผŒไฝ†ๅŒๆ—ถๅˆๆƒณๆŠŠๅฎƒไปฌไธŽๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ๆ‰€้œ€็š„่‡ชๅฎšไน‰ๅ“ๅบ”็ป„ๅˆๅœจไธ€่ตทใ€‚ + +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Python ็š„โ€œ่งฃๅŒ…โ€`dict` ็š„ๆŠ€ๅทง `**dict_to_unpack`๏ผš -ๆ‚จๅฏ่ƒฝๅธŒๆœ›ๆœ‰ไธ€ไบ›ๅบ”็”จไบŽ่ฎธๅคš่ทฏๅพ„ๆ“ไฝœ็š„้ข„ๅฎšไน‰ๅ“ๅบ”๏ผŒไฝ†ๆ˜ฏไฝ ๆƒณๅฐ†ไธๅŒ็š„่ทฏๅพ„ๅ’Œ่‡ชๅฎšไน‰็š„็›ธๅบ”็ป„ๅˆๅœจไธ€ๅ—ใ€‚ -ๅฏนไบŽ่ฟ™ไบ›ๆƒ…ๅ†ต๏ผŒไฝ ๅฏไปฅไฝฟ็”จPython็š„ๆŠ€ๆœฏ๏ผŒๅฐ† `dict` ไธŽ `**dict_to_unpack` ่งฃๅŒ…๏ผš ```Python old_dict = { "old key": "old value", @@ -203,19 +223,25 @@ old_dict = { new_dict = {**old_dict, "new key": "new value"} ``` -่ฟ™้‡Œ๏ผŒ new_dict ๅฐ†ๅŒ…ๅซๆฅ่‡ช old_dict ็š„ๆ‰€ๆœ‰้”ฎๅ€ผๅฏนๅŠ ไธŠๆ–ฐ็š„้”ฎๅ€ผๅฏน๏ผš -```python +่ฟ™้‡Œ๏ผŒ`new_dict` ๅฐ†ๅŒ…ๅซๆฅ่‡ช `old_dict` ็š„ๆ‰€ๆœ‰้”ฎๅ€ผๅฏน๏ผŒๅ†ๅŠ ไธŠๆ–ฐ็š„้”ฎๅ€ผๅฏน๏ผš + +```Python { "old key": "old value", "second old key": "second old value", "new key": "new value", } ``` -ๆ‚จๅฏไปฅไฝฟ็”จ่ฏฅๆŠ€ๆœฏๅœจ่ทฏๅพ„ๆ“ไฝœไธญ้‡็”จไธ€ไบ›้ข„ๅฎšไน‰็š„ๅ“ๅบ”๏ผŒๅนถๅฐ†ๅฎƒไปฌไธŽๅ…ถไป–่‡ชๅฎšไน‰ๅ“ๅบ”็›ธ็ป“ๅˆใ€‚ -**ไพ‹ๅฆ‚๏ผš** -{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} -## ๆœ‰ๅ…ณOpenAPIๅ“ๅบ”็š„ๆ›ดๅคšไฟกๆฏ - -่ฆไบ†่งฃๆ‚จๅฏไปฅๅœจๅ“ๅบ”ไธญๅŒ…ๅซๅ“ชไบ›ๅ†…ๅฎน๏ผŒๆ‚จๅฏไปฅๆŸฅ็œ‹OpenAPI่ง„่Œƒไธญ็š„ไปฅไธ‹้ƒจๅˆ†๏ผš - + [OpenAPIๅ“ๅบ”ๅฏน่ฑก](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject)๏ผŒๅฎƒๅŒ…ๆ‹ฌ Response Object ใ€‚ - + [OpenAPIๅ“ๅบ”ๅฏน่ฑก](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject)๏ผŒๆ‚จๅฏไปฅ็›ดๆŽฅๅœจ `responses` ๅ‚ๆ•ฐไธญ็š„ๆฏไธชๅ“ๅบ”ไธญๅŒ…ๅซไปปไฝ•ๅ†…ๅฎนใ€‚ๅŒ…ๆ‹ฌ `description` ใ€ `headers` ใ€ `content` ๏ผˆๅ…ถไธญๆ˜ฏๅฃฐๆ˜ŽไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹ๅ’ŒJSON Schemas๏ผ‰ๅ’Œ `links` ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ่ฏฅๆŠ€ๅทงๅœจ*่ทฏๅพ„ๆ“ไฝœ*ไธญ้‡็”จไธ€ไบ›้ข„ๅฎšไน‰ๅ“ๅบ”๏ผŒๅนถๆŠŠๅฎƒไปฌไธŽ้ขๅค–็š„่‡ชๅฎšไน‰ๅ“ๅบ”็ป„ๅˆๅœจไธ€่ตทใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## ๅ…ณไบŽ OpenAPI ๅ“ๅบ”็š„ๆ›ดๅคšไฟกๆฏ { #more-information-about-openapi-responses } + +่ฆๆŸฅ็œ‹ๅ“ๅบ”ไธญ็ฉถ็ซŸๅฏไปฅๅŒ…ๅซไป€ไนˆ๏ผŒไฝ ๅฏไปฅๆŸฅ็œ‹ OpenAPI ่ง„่Œƒไธญ็š„ไปฅไธ‹้ƒจๅˆ†๏ผš + +* OpenAPI Responses ๅฏน่ฑก๏ผŒๅฎƒๅŒ…ๅซ `Response Object`ใ€‚ +* OpenAPI Response ๅฏน่ฑก๏ผŒไฝ ๅฏไปฅๆŠŠ่ฟ™้‡Œ็š„ไปปไฝ•ๅ†…ๅฎน็›ดๆŽฅๅŒ…ๅซๅˆฐ `responses` ๅ‚ๆ•ฐไธญ็š„ๆฏไธชๅ“ๅบ”้‡Œใ€‚ๅŒ…ๆ‹ฌ `description`ใ€`headers`ใ€`content`๏ผˆๅœจ่ฟ™้‡Œๅฃฐๆ˜ŽไธๅŒ็š„ๅช’ไฝ“็ฑปๅž‹ๅ’Œ JSON Schemas๏ผ‰๏ผŒไปฅๅŠ `links`ใ€‚ diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index b048a2a170..23ceab4e87 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -1,10 +1,10 @@ -# ้ขๅค–็š„็Šถๆ€็  +# ้ขๅค–็š„็Šถๆ€็  { #additional-status-codes } **FastAPI** ้ป˜่ฎคไฝฟ็”จ `JSONResponse` ่ฟ”ๅ›žไธ€ไธชๅ“ๅบ”๏ผŒๅฐ†ไฝ ็š„ *่ทฏๅพ„ๆ“ไฝœ* ไธญ็š„่ฟ”ๅ›žๅ†…ๅฎนๆ”พๅˆฐ่ฏฅ `JSONResponse` ไธญใ€‚ **FastAPI** ไผš่‡ชๅŠจไฝฟ็”จ้ป˜่ฎค็š„็Šถๆ€็ ๆˆ–่€…ไฝฟ็”จไฝ ๅœจ *่ทฏๅพ„ๆ“ไฝœ* ไธญ่ฎพ็ฝฎ็š„็Šถๆ€็ ใ€‚ -## ้ขๅค–็š„็Šถๆ€็  +## ้ขๅค–็š„็Šถๆ€็  { #additional-status-codes_1 } ๅฆ‚ๆžœไฝ ๆƒณ่ฆ่ฟ”ๅ›žไธป่ฆ็Šถๆ€็ ไน‹ๅค–็š„็Šถๆ€็ ๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `Response` ๆฅๅฎž็Žฐ๏ผŒๆฏ”ๅฆ‚ `JSONResponse`๏ผŒ็„ถๅŽ็›ดๆŽฅ่ฎพ็ฝฎ้ขๅค–็š„็Šถๆ€็ ใ€‚ @@ -12,15 +12,15 @@ ไฝ†ๆ˜ฏไฝ ไนŸๅธŒๆœ›ๅฎƒ่ƒฝๅคŸๆŽฅๅ—ๆ–ฐ็š„ๆก็›ฎใ€‚ๅนถไธ”ๅฝ“่ฟ™ไบ›ๆก็›ฎไธๅญ˜ๅœจๆ—ถ๏ผŒไผš่‡ชๅŠจๅˆ›ๅปบๅนถ่ฟ”ๅ›ž 201 ใ€Œๅˆ›ๅปบใ€็š„ HTTP ็Šถๆ€็ ใ€‚ -่ฆๅฎž็Žฐๅฎƒ๏ผŒๅฏผๅ…ฅ `JSONResponse`๏ผŒ็„ถๅŽๅœจๅ…ถไธญ็›ดๆŽฅ่ฟ”ๅ›žไฝ ็š„ๅ†…ๅฎน๏ผŒๅนถๅฐ† `status_code` ่ฎพ็ฝฎไธบไธบไฝ ่ฆ็š„ๅ€ผใ€‚ +่ฆๅฎž็Žฐๅฎƒ๏ผŒๅฏผๅ…ฅ `JSONResponse`๏ผŒ็„ถๅŽๅœจๅ…ถไธญ็›ดๆŽฅ่ฟ”ๅ›žไฝ ็š„ๅ†…ๅฎน๏ผŒๅนถๅฐ† `status_code` ่ฎพ็ฝฎไธบไฝ ่ฆ็š„ๅ€ผใ€‚ -{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *} +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning | ่ญฆๅ‘Š +/// warning ๅฝ“ไฝ ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธชๅƒไธŠ้ขไพ‹ๅญไธญ็š„ `Response` ๅฏน่ฑกๆ—ถ๏ผŒๅฎƒไผš็›ดๆŽฅ่ฟ”ๅ›žใ€‚ -FastAPI ไธไผš็”จๆจกๅž‹็ญ‰ๅฏน่ฏฅๅ“ๅบ”่ฟ›่กŒๅบๅˆ—ๅŒ–ใ€‚ +ๅฎƒไธไผš็”จๆจกๅž‹็ญ‰่ฟ›่กŒๅบๅˆ—ๅŒ–ใ€‚ ็กฎไฟๅ…ถไธญๆœ‰ไฝ ๆƒณ่ฆ็š„ๆ•ฐๆฎ๏ผŒไธ”่ฟ”ๅ›ž็š„ๅ€ผไธบๅˆๆณ•็š„ JSON๏ผˆๅฆ‚ๆžœไฝ ไฝฟ็”จ `JSONResponse` ็š„่ฏ๏ผ‰ใ€‚ @@ -34,7 +34,7 @@ FastAPI ไธไผš็”จๆจกๅž‹็ญ‰ๅฏน่ฏฅๅ“ๅบ”่ฟ›่กŒๅบๅˆ—ๅŒ–ใ€‚ /// -## OpenAPI ๅ’Œ API ๆ–‡ๆกฃ +## OpenAPI ๅ’Œ API ๆ–‡ๆกฃ { #openapi-and-api-docs } ๅฆ‚ๆžœไฝ ็›ดๆŽฅ่ฟ”ๅ›ž้ขๅค–็š„็Šถๆ€็ ๅ’Œๅ“ๅบ”๏ผŒๅฎƒไปฌไธไผšๅŒ…ๅซๅœจ OpenAPI ๆ–นๆกˆ๏ผˆAPI ๆ–‡ๆกฃ๏ผ‰ไธญ๏ผŒๅ› ไธบ FastAPI ๆฒกๅŠžๆณ•้ข„ๅ…ˆ็Ÿฅ้“ไฝ ่ฆ่ฟ”ๅ›žไป€ไนˆใ€‚ diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md index 8375bd48ea..3efca89442 100644 --- a/docs/zh/docs/advanced/advanced-dependencies.md +++ b/docs/zh/docs/advanced/advanced-dependencies.md @@ -1,65 +1,163 @@ -# ้ซ˜็บงไพ่ต–้กน +# ้ซ˜็บงไพ่ต–้กน { #advanced-dependencies } -## ๅ‚ๆ•ฐๅŒ–็š„ไพ่ต–้กน +## ๅ‚ๆ•ฐๅŒ–็š„ไพ่ต–้กน { #parameterized-dependencies } -ๆˆ‘ไปฌไน‹ๅ‰็œ‹ๅˆฐ็š„ๆ‰€ๆœ‰ไพ่ต–้กน้ƒฝๆ˜ฏๅ†™ๆญป็š„ๅ‡ฝๆ•ฐๆˆ–็ฑปใ€‚ +็›ฎๅ‰ๆˆ‘ไปฌ็œ‹ๅˆฐ็š„ไพ่ต–้กน้ƒฝๆ˜ฏๅ›บๅฎš็š„ๅ‡ฝๆ•ฐๆˆ–็ฑปใ€‚ -ไฝ†ไนŸๅฏไปฅไธบไพ่ต–้กน่ฎพ็ฝฎๅ‚ๆ•ฐ๏ผŒ้ฟๅ…ๅฃฐๆ˜ŽๅคšไธชไธๅŒ็š„ๅ‡ฝๆ•ฐๆˆ–็ฑปใ€‚ +ไฝ†ๆœ‰ๆ—ถไฝ ๅฏ่ƒฝๅธŒๆœ›ไธบไพ่ต–้กน่ฎพ็ฝฎๅ‚ๆ•ฐ๏ผŒ่€Œไธๅฟ…ๅฃฐๆ˜Ž่ฎธๅคšไธๅŒ็š„ๅ‡ฝๆ•ฐๆˆ–็ฑปใ€‚ -ๅ‡่ฎพ่ฆๅˆ›ๅปบๆ ก้ชŒๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ๆ˜ฏๅฆๅŒ…ๅซๅ›บๅฎšๅ†…ๅฎน็š„ไพ่ต–้กนใ€‚ +ๅ‡่ฎพๆˆ‘ไปฌ่ฆๆœ‰ไธ€ไธชไพ่ต–้กน๏ผŒ็”จๆฅๆฃ€ๆŸฅๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ๆ˜ฏๅฆๅŒ…ๅซๆŸไธชๅ›บๅฎšๅ†…ๅฎนใ€‚ -ไฝ†ๆญคๅค„่ฆๆŠŠๅพ…ๆฃ€้ชŒ็š„ๅ›บๅฎšๅ†…ๅฎนๅฎšไน‰ไธบๅ‚ๆ•ฐใ€‚ +ไฝ†ๆˆ‘ไปฌๅธŒๆœ›่ƒฝๅคŸๆŠŠ่ฟ™ไธชๅ›บๅฎšๅ†…ๅฎนๅ‚ๆ•ฐๅŒ–ใ€‚ -## **ๅฏ่ฐƒ็”จ**ๅฎžไพ‹ +## โ€œๅฏ่ฐƒ็”จโ€็š„ๅฎžไพ‹ { #a-callable-instance } -Python ๅฏไปฅๆŠŠ็ฑปๅฎžไพ‹ๅ˜ไธบ**ๅฏ่ฐƒ็”จ้กน**ใ€‚ +ๅœจ Python ไธญ๏ผŒๅฏไปฅ่ฎฉๆŸไธช็ฑป็š„ๅฎžไพ‹ๅ˜ๆˆโ€œๅฏ่ฐƒ็”จๅฏน่ฑกโ€๏ผˆcallable๏ผ‰ใ€‚ -่ฟ™้‡Œ่ฏด็š„ไธๆ˜ฏ็ฑปๆœฌ่บซ๏ผˆ็ฑปๆœฌๅฐฑๆ˜ฏๅฏ่ฐƒ็”จ้กน๏ผ‰๏ผŒ่€Œๆ˜ฏ็ฑปๅฎžไพ‹ใ€‚ +่ฟ™้‡ŒๆŒ‡็š„ๆ˜ฏ็ฑป็š„ๅฎžไพ‹๏ผˆ็ฑปๆœฌ่บซๅทฒ็ปๆ˜ฏๅฏ่ฐƒ็”จ็š„๏ผ‰๏ผŒ่€Œไธๆ˜ฏ็ฑปๆœฌ่บซใ€‚ -ไธบๆญค๏ผŒ้œ€่ฆๅฃฐๆ˜Ž `__call__` ๆ–นๆณ•๏ผš +ไธบๆญค๏ผŒๅฃฐๆ˜Žไธ€ไธช `__call__` ๆ–นๆณ•๏ผš -{* ../../docs_src/dependencies/tutorial011.py hl[10] *} +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} -ๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ไฝฟ็”จ `__call__` ๆฃ€ๆŸฅ้™„ๅŠ ๅ‚ๆ•ฐๅŠๅญไพ่ต–้กน๏ผŒ็จๅŽ๏ผŒ่ฟ˜่ฆ่ฐƒ็”จๅฎƒๅ‘*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไผ ้€’ๅ€ผใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ไผšไฝฟ็”จ่ฟ™ไธช `__call__` ๆฅๆฃ€ๆŸฅ้™„ๅŠ ๅ‚ๆ•ฐๅ’Œๅญไพ่ต–๏ผŒๅนถไธ”็จๅŽไผš่ฐƒ็”จๅฎƒ๏ผŒๆŠŠ่ฟ”ๅ›žๅ€ผไผ ้€’็ป™ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅ‚ๆ•ฐใ€‚ -## ๅ‚ๆ•ฐๅŒ–ๅฎžไพ‹ +## ๅ‚ๆ•ฐๅŒ–ๅฎžไพ‹ { #parameterize-the-instance } -ๆŽฅไธ‹ๆฅ๏ผŒไฝฟ็”จ `__init__` ๅฃฐๆ˜Ž็”จไบŽ**ๅ‚ๆ•ฐๅŒ–**ไพ่ต–้กน็š„ๅฎžไพ‹ๅ‚ๆ•ฐ๏ผš +็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅฏไปฅ็”จ `__init__` ๅฃฐๆ˜Žๅฎžไพ‹็š„ๅ‚ๆ•ฐ๏ผŒ็”จๆฅโ€œๅ‚ๆ•ฐๅŒ–โ€่ฟ™ไธชไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial011.py hl[7] *} +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} -ๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ไธไฝฟ็”จ `__init__`๏ผŒๆˆ‘ไปฌ่ฆ็›ดๆŽฅๅœจไปฃ็ ไธญไฝฟ็”จใ€‚ +ๅœจๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ไธไผšๆŽฅ่งฆๆˆ–ๅ…ณๅฟƒ `__init__`๏ผŒๆˆ‘ไปฌไผšๅœจ่‡ชๅทฑ็š„ไปฃ็ ไธญ็›ดๆŽฅไฝฟ็”จๅฎƒใ€‚ -## ๅˆ›ๅปบๅฎžไพ‹ +## ๅˆ›ๅปบๅฎžไพ‹ { #create-an-instance } -ไฝฟ็”จไปฅไธ‹ไปฃ็ ๅˆ›ๅปบ็ฑปๅฎžไพ‹๏ผš +ๆˆ‘ไปฌๅฏไปฅ่ฟ™ๆ ทๅˆ›ๅปบ่ฏฅ็ฑป็š„ๅฎžไพ‹๏ผš -{* ../../docs_src/dependencies/tutorial011.py hl[16] *} +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} -่ฟ™ๆ ทๅฐฑๅฏไปฅ**ๅ‚ๆ•ฐๅŒ–**ไพ่ต–้กน๏ผŒๅฎƒๅŒ…ๅซ `checker.fixed_content` ็š„ๅฑžๆ€ง - `"bar"`ใ€‚ +่ฟ™ๆ ทๅฐฑๆŠŠไพ่ต–้กนโ€œๅ‚ๆ•ฐๅŒ–โ€ไบ†๏ผŒ็Žฐๅœจๅฎƒๅ†…้ƒจๅธฆๆœ‰ๅฑžๆ€ง `checker.fixed_content` ็š„ๅ€ผ `"bar"`ใ€‚ -## ๆŠŠๅฎžไพ‹ไฝœไธบไพ่ต–้กน +## ๆŠŠๅฎžไพ‹ไฝœไธบไพ่ต–้กน { #use-the-instance-as-a-dependency } -็„ถๅŽ๏ผŒไธ่ฆๅ†ๅœจ `Depends(checker)` ไธญไฝฟ็”จ `Depends(FixedContentQueryChecker)`๏ผŒ ่€Œๆ˜ฏ่ฆไฝฟ็”จ `checker`๏ผŒๅ› ไธบไพ่ต–้กนๆ˜ฏ็ฑปๅฎžไพ‹ - `checker`๏ผŒไธๆ˜ฏ็ฑปใ€‚ +็„ถๅŽ๏ผŒๆˆ‘ไปฌๅฏไปฅๅœจ `Depends(checker)` ไธญไฝฟ็”จ่ฟ™ไธช `checker`๏ผŒ่€Œไธๆ˜ฏ `Depends(FixedContentQueryChecker)`๏ผŒๅ› ไธบไพ่ต–้กนๆ˜ฏๅฎžไพ‹ `checker`๏ผŒไธๆ˜ฏ็ฑปๆœฌ่บซใ€‚ -ๅค„็†ไพ่ต–้กนๆ—ถ๏ผŒ**FastAPI** ไปฅๅฆ‚ไธ‹ๆ–นๅผ่ฐƒ็”จ `checker`๏ผš +่งฃๆžไพ่ต–้กนๆ—ถ๏ผŒ**FastAPI** ไผšๅƒ่ฟ™ๆ ท่ฐƒ็”จ `checker`๏ผš ```Python checker(q="somequery") ``` -โ€ฆโ€ฆๅนถ็”จ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ `fixed_content_included` ่ฟ”ๅ›žไพ่ต–้กน็š„ๅ€ผ๏ผš +...ๅนถๅฐ†ๅ…ถ่ฟ”ๅ›žๅ€ผไฝœไธบไพ่ต–้กน็š„ๅ€ผ๏ผŒไผ ็ป™ๆˆ‘ไปฌ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅ‚ๆ•ฐ `fixed_content_included`๏ผš -{* ../../docs_src/dependencies/tutorial011.py hl[20] *} +{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} /// tip | ๆ็คบ -ๆœฌ็ซ ็คบไพ‹ๆœ‰ไบ›ๅˆปๆ„๏ผŒไนŸ็œ‹ไธๅ‡บๆœ‰ไป€ไนˆ็”จๅค„ใ€‚ +่ฟ™ไบ›็œ‹่ตทๆฅๅฏ่ƒฝๆœ‰ไบ›็‰ตๅผบ๏ผŒ็›ฎๅ‰ๅฎƒ็š„็”จๅค„ไนŸ่ฎธ่ฟ˜ไธๅคชๆ˜Žๆ˜พใ€‚ -่ฟ™ไธช็ฎ€ไพ‹ๅชๆ˜ฏไธบไบ†่ฏดๆ˜Ž้ซ˜็บงไพ่ต–้กน็š„่ฟไฝœๆœบๅˆถใ€‚ +่ฟ™ไบ›็คบไพ‹ๅˆปๆ„ไฟๆŒ็ฎ€ๅ•๏ผŒไฝ†ๅฑ•็คบไบ†ๆ•ดไฝ“็š„ๅทฅไฝœๆ–นๅผใ€‚ -ๅœจๆœ‰ๅ…ณๅฎ‰ๅ…จ็š„็ซ ่Š‚ไธญ๏ผŒๅทฅๅ…ทๅ‡ฝๆ•ฐๅฐ†ไปฅ่ฟ™็งๆ–นๅผๅฎž็Žฐใ€‚ +ๅœจๅฎ‰ๅ…จ็›ธๅ…ณ็š„็ซ ่Š‚้‡Œ๏ผŒๆœ‰ไธ€ไบ›ๅทฅๅ…ทๅ‡ฝๆ•ฐๅฐฑๆ˜ฏไปฅ็›ธๅŒ็š„ๆ–นๅผๅฎž็Žฐ็š„ใ€‚ -ๅช่ฆ่ƒฝ็†่งฃๆœฌ็ซ ๅ†…ๅฎน๏ผŒๅฐฑ่ƒฝ็†่งฃๅฎ‰ๅ…จๅทฅๅ…ท่ƒŒๅŽ็š„่ฟ่กŒๆœบๅˆถใ€‚ +ๅฆ‚ๆžœไฝ ็†่งฃไบ†่ฟ™้‡Œ็š„ๅ†…ๅฎน๏ผŒไฝ ๅฐฑๅทฒ็ป็Ÿฅ้“้‚ฃไบ›ๅฎ‰ๅ…จๅทฅๅ…ทๅœจๅบ•ๅฑ‚ๆ˜ฏๅฆ‚ไฝ•ๅทฅไฝœ็š„ใ€‚ /// + +## ๅธฆ `yield` ็š„ไพ่ต–้กนใ€`HTTPException`ใ€`except` ไธŽๅŽๅฐไปปๅŠก { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | ่ญฆๅ‘Š + +ไฝ ๅพˆๅฏ่ƒฝไธ้œ€่ฆไบ†่งฃ่ฟ™ไบ›ๆŠ€ๆœฏ็ป†่Š‚ใ€‚ + +่ฟ™ไบ›็ป†่Š‚ไธป่ฆๅœจไฝ ็š„ FastAPI ๅบ”็”จ็‰ˆๆœฌไฝŽไบŽ 0.121.0 ไธ”ไฝ ๆญฃ้‡ๅˆฐๅธฆ `yield` ็š„ไพ่ต–้กน้—ฎ้ข˜ๆ—ถๆ‰ๆœ‰็”จใ€‚ + +/// + +ๅธฆ `yield` ็š„ไพ่ต–้กน้š็€ๆ—ถ้—ดๆผ”่ฟ›ไปฅ่ฆ†็›–ไธๅŒ็”จไพ‹ๅนถไฟฎๅคไธ€ไบ›้—ฎ้ข˜๏ผŒไธ‹้ขๆ˜ฏๅ˜ๆ›ดๆ‘˜่ฆใ€‚ + +### ๅธฆ `yield` ็š„ไพ่ต–้กนไธŽ `scope` { #dependencies-with-yield-and-scope } + +ๅœจ 0.121.0 ็‰ˆๆœฌไธญ๏ผŒFastAPI ไธบๅธฆ `yield` ็š„ไพ่ต–้กนๆ–ฐๅขžไบ† `Depends(scope="function")` ็š„ๆ”ฏๆŒใ€‚ + +ไฝฟ็”จ `Depends(scope="function")` ๆ—ถ๏ผŒ`yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ไผšๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็ป“ๆŸๅŽใ€ๅ“ๅบ”ๅ‘้€็ป™ๅฎขๆˆท็ซฏไน‹ๅ‰็ซ‹ๅณๆ‰ง่กŒใ€‚ + +่€Œๅฝ“ไฝฟ็”จ้ป˜่ฎค็š„ `Depends(scope="request")` ๆ—ถ๏ผŒ`yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ไผšๅœจๅ“ๅบ”ๅ‘้€ไน‹ๅŽๆ‰ง่กŒใ€‚ + +ไฝ ๅฏไปฅๅœจๆ–‡ๆกฃ [ๅธฆ `yield` ็š„ไพ่ต–้กน - ๆๅ‰้€€ๅ‡บไธŽ `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) ไธญไบ†่งฃๆ›ดๅคšใ€‚ + +### ๅธฆ `yield` ็š„ไพ่ต–้กนไธŽ `StreamingResponse`๏ผˆๆŠ€ๆœฏ็ป†่Š‚๏ผ‰ { #dependencies-with-yield-and-streamingresponse-technical-details } + +ๅœจ FastAPI 0.118.0 ไน‹ๅ‰๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จๅธฆ `yield` ็š„ไพ่ต–้กน๏ผŒๅฎƒไผšๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*่ฟ”ๅ›žๅŽใ€ๅ‘้€ๅ“ๅบ”ไน‹ๅ‰่ฟ่กŒ `yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ใ€‚ + +่ฟ™ๆ ทๅš็š„็›ฎ็š„ๆ˜ฏ้ฟๅ…ๅœจ็ญ‰ๅพ…ๅ“ๅบ”้€š่ฟ‡็ฝ‘็ปœไผ ่พ“ๆœŸ้—ดไธๅฟ…่ฆๅœฐๅ ็”จ่ต„ๆบใ€‚ + +่ฟ™ไนŸๆ„ๅ‘ณ็€๏ผŒๅฆ‚ๆžœไฝ ่ฟ”ๅ›ž็š„ๆ˜ฏ `StreamingResponse`๏ผŒ้‚ฃไนˆ่ฏฅๅธฆ `yield` ็š„ไพ่ต–้กน็š„้€€ๅ‡บไปฃ็ ไผšๅœจๅผ€ๅง‹ๅ‘้€ๅ“ๅบ”ๅ‰ๅฐฑๅทฒ็ปๆ‰ง่กŒๅฎŒๆฏ•ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅœจๅธฆ `yield` ็š„ไพ่ต–้กนไธญๆŒๆœ‰ไธ€ไธชๆ•ฐๆฎๅบ“ไผš่ฏ๏ผŒ้‚ฃไนˆ `StreamingResponse` ๅœจๆตๅผๅ‘้€ๆ•ฐๆฎๆ—ถๅฐ†ๆ— ๆณ•ไฝฟ็”จ่ฏฅไผš่ฏ๏ผŒๅ› ไธบไผš่ฏๅทฒ็ปๅœจ `yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ้‡Œ่ขซๅ…ณ้—ญไบ†ใ€‚ + +ๅœจ 0.118.0 ไธญ๏ผŒ่ฟ™ไธ€่กŒไธบ่ขซๅ›ž้€€ไธบ๏ผš่ฎฉ `yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ๅœจๅ“ๅบ”ๅ‘้€ไน‹ๅŽๅ†ๆ‰ง่กŒใ€‚ + +/// info | ไฟกๆฏ + +ๅฆ‚ไฝ ๅœจไธ‹ๆ–‡ๆ‰€่ง๏ผŒ่ฟ™ไธŽ 0.106.0 ไน‹ๅ‰็š„่กŒไธบ้žๅธธ็›ธไผผ๏ผŒไฝ†ๅฏน่‹ฅๅนฒ่พน็•Œๆƒ…ๅ†ตๅšไบ†ๆ”น่ฟ›ๅ’Œไฟฎๅคใ€‚ + +/// + +#### ้œ€่ฆๆๅ‰ๆ‰ง่กŒ้€€ๅ‡บไปฃ็ ็š„็”จไพ‹ { #use-cases-with-early-exit-code } + +ๅœจๆŸไบ›็‰นๅฎšๆกไปถไธ‹๏ผŒๆ—ง็š„่กŒไธบ๏ผˆๅœจๅ‘้€ๅ“ๅบ”ไน‹ๅ‰ๆ‰ง่กŒๅธฆ `yield` ไพ่ต–้กน็š„้€€ๅ‡บไปฃ็ ๏ผ‰ไผšๆ›ดๆœ‰ๅˆฉใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฎพๆƒณไฝ ๅœจๅธฆ `yield` ็š„ไพ่ต–้กนไธญไป…็”จๆ•ฐๆฎๅบ“ไผš่ฏๆฅๆ ก้ชŒ็”จๆˆท๏ผŒ่€Œๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅนถไธไผšๅ†ๆฌกไฝฟ็”จ่ฏฅไผš่ฏ๏ผ›ๅŒๆ—ถ๏ผŒๅ“ๅบ”้œ€่ฆๅพˆ้•ฟๆ—ถ้—ดๆ‰่ƒฝๅ‘้€ๅฎŒ๏ผŒๆฏ”ๅฆ‚ไธ€ไธช็ผ“ๆ…ขๅ‘้€ๆ•ฐๆฎ็š„ `StreamingResponse`๏ผŒไธ”ๅฎƒๅ‡บไบŽๆŸ็งๅŽŸๅ› ๅนถไธไฝฟ็”จๆ•ฐๆฎๅบ“ใ€‚ + +่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไผšไธ€็›ดๆŒๆœ‰ๆ•ฐๆฎๅบ“ไผš่ฏ็›ดๅˆฐๅ“ๅบ”ๅ‘้€ๅฎŒๆฏ•๏ผ›ไฝ†ๅฆ‚ๆžœๅนถไธๅ†ไฝฟ็”จๅฎƒ๏ผŒๅฐฑๆฒกๆœ‰ๅฟ…่ฆไธ€็›ดๅ ็”จใ€‚ + +ไปฃ็ ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +้€€ๅ‡บไปฃ็ ๏ผˆ่‡ชๅŠจๅ…ณ้—ญ `Session`๏ผ‰ไฝไบŽ๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...ไผšๅœจๅ“ๅบ”ๆŠŠๆ…ข้€Ÿๆ•ฐๆฎๅ‘้€ๅฎŒไน‹ๅŽๆ‰่ฟ่กŒ๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +ไฝ†็”ฑไบŽ `generate_stream()` ๅนถไธไฝฟ็”จๆ•ฐๆฎๅบ“ไผš่ฏ๏ผŒๅ› ๆญคๅœจๅ‘้€ๅ“ๅบ”ๆœŸ้—ดไฟๆŒไผš่ฏๆ‰“ๅผ€ๅนถ้žๅฟ…่ฆใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏ SQLModel๏ผˆๆˆ– SQLAlchemy๏ผ‰ๅนถ็ขฐๅˆฐ่ฟ™็ง็‰นๅฎš็”จไพ‹๏ผŒไฝ ๅฏไปฅๅœจไธๅ†้œ€่ฆๆ—ถๆ˜พๅผๅ…ณ้—ญไผš่ฏ๏ผš + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +่ฟ™ๆ ทไผš่ฏไผš้‡Šๆ”พๆ•ฐๆฎๅบ“่ฟžๆŽฅ๏ผŒ่ฎฉๅ…ถไป–่ฏทๆฑ‚ๅฏไปฅไฝฟ็”จใ€‚ + +ๅฆ‚ๆžœไฝ ่ฟ˜ๆœ‰ๅ…ถไป–้œ€่ฆๅœจ `yield` ไพ่ต–้กนไธญๆๅ‰้€€ๅ‡บ็š„็”จไพ‹๏ผŒ่ฏทๅˆ›ๅปบไธ€ไธช GitHub ่ฎจ่ฎบ้—ฎ้ข˜๏ผŒ่ฏดๆ˜Žไฝ ็š„ๅ…ทไฝ“็”จไพ‹ไปฅๅŠไธบไฝ•ๆๅ‰ๅ…ณ้—ญไผšๅฏนไฝ ๆœ‰ๅธฎๅŠฉใ€‚ + +ๅฆ‚ๆžœ็กฎๆœ‰ๆœ‰ๅŠ›็š„็”จไพ‹้œ€่ฆๆๅ‰ๅ…ณ้—ญ๏ผŒๆˆ‘ไผš่€ƒ่™‘ๆ–ฐๅขžไธ€็ง้€‰ๆ‹ฉๆ€งๅฏ็”จๆๅ‰ๅ…ณ้—ญ็š„ๆ–นๅผใ€‚ + +### ๅธฆ `yield` ็š„ไพ่ต–้กนไธŽ `except`๏ผˆๆŠ€ๆœฏ็ป†่Š‚๏ผ‰ { #dependencies-with-yield-and-except-technical-details } + +ๅœจ FastAPI 0.110.0 ไน‹ๅ‰๏ผŒๅฆ‚ๆžœไฝ ๅœจๅธฆ `yield` ็š„ไพ่ต–้กนไธญ็”จ `except` ๆ•่Žทไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒๅนถไธ”ๆฒกๆœ‰ๅ†ๆฌกๆŠ›ๅ‡บๅฎƒ๏ผŒ้‚ฃไนˆ่ฏฅๅผ‚ๅธธไผš่ขซ่‡ชๅŠจๆŠ›ๅ‡บ/่ฝฌๅ‘็ป™ไปปๆ„ๅผ‚ๅธธๅค„็†ๅ™จๆˆ–ๅ†…้ƒจๆœๅŠกๅ™จ้”™่ฏฏๅค„็†ๅ™จใ€‚ + +ๅœจ 0.110.0 ไธญๅฏนๆญคไฝœๅ‡บไบ†ๅ˜ๆ›ด๏ผŒไปฅไฟฎๅคๅฐ†ๅผ‚ๅธธ่ฝฌๅ‘ไธบๆœชๅค„็†๏ผˆๅ†…้ƒจๆœๅŠกๅ™จ้”™่ฏฏ๏ผ‰ๆ—ถ้€ ๆˆ็š„ๅ†…ๅญ˜ๆถˆ่€—้—ฎ้ข˜๏ผŒๅนถไฝฟๅ…ถไธŽๅธธ่ง„ Python ไปฃ็ ็š„่กŒไธบไฟๆŒไธ€่‡ดใ€‚ + +### ๅŽๅฐไปปๅŠกไธŽๅธฆ `yield` ็š„ไพ่ต–้กน๏ผˆๆŠ€ๆœฏ็ป†่Š‚๏ผ‰ { #background-tasks-and-dependencies-with-yield-technical-details } + +ๅœจ FastAPI 0.106.0 ไน‹ๅ‰๏ผŒ`yield` ไน‹ๅŽๆŠ›ๅ‡บๅผ‚ๅธธๆ˜ฏไธๅฏ่กŒ็š„๏ผŒๅ› ไธบๅธฆ `yield` ็š„ไพ่ต–้กนไธญ็š„้€€ๅ‡บไปฃ็ ไผšๅœจๅ“ๅบ”ๅ‘้€ไน‹ๅŽๆ‰ๆ‰ง่กŒ๏ผŒๆญคๆ—ถ[ๅผ‚ๅธธๅค„็†ๅ™จ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ๅทฒ็ป่ฟ่กŒๅฎŒๆฏ•ใ€‚ + +ไน‹ๆ‰€ไปฅ่ฟ™ๆ ท่ฎพ่ฎก๏ผŒไธป่ฆๆ˜ฏไธบไบ†ๅ…่ฎธๅœจๅŽๅฐไปปๅŠกไธญ็ปง็ปญไฝฟ็”จไพ่ต–้กน้€š่ฟ‡ `yield`โ€œไบงๅ‡บโ€็š„ๅฏน่ฑก๏ผŒๅ› ไธบ้€€ๅ‡บไปฃ็ ไผšๅœจๅŽๅฐไปปๅŠกๅฎŒๆˆไน‹ๅŽๆ‰ๆ‰ง่กŒใ€‚ + +ๅœจ FastAPI 0.106.0 ไธญ๏ผŒ่ฟ™ไธ€่กŒไธบ่ขซไฟฎๆ”น๏ผŒ็›ฎ็š„ๆ˜ฏ้ฟๅ…ๅœจ็ญ‰ๅพ…ๅ“ๅบ”้€š่ฟ‡็ฝ‘็ปœไผ ่พ“ๆ—ถไธ€็›ดๅ ็”จ่ต„ๆบใ€‚ + +/// tip | ๆ็คบ + +ๅฆๅค–๏ผŒๅŽๅฐไปปๅŠก้€šๅธธๆ˜ฏไธ€ๆฎต็‹ฌ็ซ‹็š„้€ป่พ‘๏ผŒๅบ”่ฏฅๅ•็‹ฌๅค„็†๏ผŒๅนถไฝฟ็”จๅฎƒ่‡ชๅทฑ็š„่ต„ๆบ๏ผˆไพ‹ๅฆ‚ๅฎƒ่‡ชๅทฑ็š„ๆ•ฐๆฎๅบ“่ฟžๆŽฅ๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒ่ฟ™ๆ ทๅšไฝ ็š„ไปฃ็ ้€šๅธธไผšๆ›ดๆธ…ๆ™ฐใ€‚ + +/// + +ๅฆ‚ๆžœไฝ ่ฟ‡ๅŽปไพ่ต–ไบŽๆ—ง่กŒไธบ๏ผŒ็Žฐๅœจๅบ”ๅœจๅŽๅฐไปปๅŠกๅ†…้ƒจ่‡ช่กŒๅˆ›ๅปบๆ‰€้œ€่ต„ๆบ๏ผŒๅนถไธ”ๅชๅœจๅ†…้ƒจไฝฟ็”จไธไพ่ต–ไบŽๅธฆ `yield` ไพ่ต–้กน่ต„ๆบ็š„ๆ•ฐๆฎใ€‚ + +ไพ‹ๅฆ‚๏ผŒไธ่ฆๅค็”จ็›ธๅŒ็š„ๆ•ฐๆฎๅบ“ไผš่ฏ๏ผŒ่€Œๆ˜ฏๅœจๅŽๅฐไปปๅŠกๅ†…้ƒจๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ไผš่ฏ๏ผŒๅนถ็”จ่ฟ™ไธชๆ–ฐไผš่ฏไปŽๆ•ฐๆฎๅบ“่Žทๅ–ๅฏน่ฑกใ€‚็„ถๅŽ๏ผŒไธๆ˜ฏๆŠŠๆ•ฐๆฎๅบ“ๅฏน่ฑกๆœฌ่บซไฝœไธบๅ‚ๆ•ฐไผ ็ป™ๅŽๅฐไปปๅŠกๅ‡ฝๆ•ฐ๏ผŒ่€Œๆ˜ฏไผ ้€’่ฏฅๅฏน่ฑก็š„ ID๏ผŒๅนถๅœจๅŽๅฐไปปๅŠกๅ‡ฝๆ•ฐๅ†…้ƒจๅ†ๆฌก่Žทๅ–่ฏฅๅฏน่ฑกใ€‚ diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md index b5ac15b5b6..6803358d25 100644 --- a/docs/zh/docs/advanced/async-tests.md +++ b/docs/zh/docs/advanced/async-tests.md @@ -1,4 +1,4 @@ -# ๅผ‚ๆญฅๆต‹่ฏ• +# ๅผ‚ๆญฅๆต‹่ฏ• { #async-tests } ๆ‚จๅทฒ็ปไบ†่งฃไบ†ๅฆ‚ไฝ•ไฝฟ็”จ `TestClient` ๆต‹่ฏ• **FastAPI** ๅบ”็”จ็จ‹ๅบใ€‚ไฝ†ๆ˜ฏๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๆ‚จๅชไบ†่งฃไบ†ๅฆ‚ไฝ•็ผ–ๅ†™ๅŒๆญฅๆต‹่ฏ•๏ผŒ่€Œๆฒกๆœ‰ไฝฟ็”จ `async` ๅผ‚ๆญฅๅ‡ฝๆ•ฐใ€‚ @@ -6,11 +6,11 @@ ่ฎฉๆˆ‘ไปฌ็œ‹็œ‹ๅฆ‚ไฝ•ๆ‰่ƒฝๅฎž็Žฐ่ฟ™ไธ€็‚นใ€‚ -## pytest.mark.anyio +## pytest.mark.anyio { #pytest-mark-anyio } ๅฆ‚ๆžœๆˆ‘ไปฌๆƒณๅœจๆต‹่ฏ•ไธญ่ฐƒ็”จๅผ‚ๆญฅๅ‡ฝๆ•ฐ๏ผŒ้‚ฃไนˆๆˆ‘ไปฌ็š„ๆต‹่ฏ•ๅ‡ฝๆ•ฐๅฟ…้กปๆ˜ฏๅผ‚ๆญฅ็š„ใ€‚ AnyIO ไธบๆญคๆไพ›ไบ†ไธ€ไธช็ฎ€ๆด็š„ๆ’ไปถ๏ผŒๅฎƒๅ…่ฎธๆˆ‘ไปฌๆŒ‡ๅฎšไธ€ไบ›ๆต‹่ฏ•ๅ‡ฝๆ•ฐ่ฆๅผ‚ๆญฅ่ฐƒ็”จใ€‚ -## HTTPX +## HTTPX { #httpx } ๅณไฝฟๆ‚จ็š„ **FastAPI** ๅบ”็”จ็จ‹ๅบไฝฟ็”จๆ™ฎ้€š็š„ `def` ๅ‡ฝๆ•ฐ่€Œไธๆ˜ฏ `async def` ๏ผŒๅฎƒๆœฌ่ดจไธŠไปๆ˜ฏไธ€ไธช `async` ๅผ‚ๆญฅๅบ”็”จ็จ‹ๅบใ€‚ @@ -18,7 +18,7 @@ `TestClient` ๆ˜ฏๅŸบไบŽ HTTPX ็š„ใ€‚ๅนธ่ฟ็š„ๆ˜ฏ๏ผŒๆˆ‘ไปฌๅฏไปฅ็›ดๆŽฅไฝฟ็”จๅฎƒๆฅๆต‹่ฏ•APIใ€‚ -## ็คบไพ‹ +## ็คบไพ‹ { #example } ไธพไธช็ฎ€ๅ•็š„ไพ‹ๅญ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅ็œ‹ไธ€ไธช[ๆ›ดๅคง็š„ๅบ”็”จ](../tutorial/bigger-applications.md){.internal-link target=_blank}ๅ’Œ[ๆต‹่ฏ•](../tutorial/testing.md){.internal-link target=_blank}ไธญๆ่ฟฐ็š„็ฑปไผผๆ–‡ไปถ็ป“ๆž„๏ผš @@ -32,13 +32,13 @@ ๆ–‡ไปถ `main.py` ๅฐ†ๅŒ…ๅซ: -{* ../../docs_src/async_tests/main.py *} +{* ../../docs_src/async_tests/app_a_py39/main.py *} ๆ–‡ไปถ `test_main.py` ๅฐ†ๅŒ…ๅซ้’ˆๅฏน `main.py` ็š„ๆต‹่ฏ•๏ผŒ็Žฐๅœจๅฎƒๅฏ่ƒฝ็œ‹่ตทๆฅๅฆ‚ไธ‹๏ผš -{* ../../docs_src/async_tests/test_main.py *} +{* ../../docs_src/async_tests/app_a_py39/test_main.py *} -## ่ฟ่กŒๆต‹่ฏ• +## ่ฟ่กŒๆต‹่ฏ• { #run-it } ๆ‚จๅฏไปฅ้€š่ฟ‡ไปฅไธ‹ๆ–นๅผ็…งๅธธ่ฟ่กŒๆต‹่ฏ•๏ผš @@ -52,13 +52,13 @@ $ pytest
-## ่ฏฆ็ป†่ฏดๆ˜Ž +## ่ฏฆ็ป†่ฏดๆ˜Ž { #in-detail } ่ฟ™ไธชๆ ‡่ฎฐ `@pytest.mark.anyio` ไผšๅ‘Š่ฏ‰ pytest ่ฏฅๆต‹่ฏ•ๅ‡ฝๆ•ฐๅบ”่ฏฅ่ขซๅผ‚ๆญฅ่ฐƒ็”จ๏ผš -{* ../../docs_src/async_tests/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} -/// tip +/// tip | ๆ็คบ ่ฏทๆณจๆ„๏ผŒๆต‹่ฏ•ๅ‡ฝๆ•ฐ็Žฐๅœจ็”จ็š„ๆ˜ฏ `async def`๏ผŒ่€Œไธๆ˜ฏๅƒไปฅๅ‰ไฝฟ็”จ `TestClient` ๆ—ถ้‚ฃๆ ทๅชๆ˜ฏ `def` ใ€‚ @@ -66,7 +66,7 @@ $ pytest ๆˆ‘ไปฌ็Žฐๅœจๅฏไปฅไฝฟ็”จๅบ”็”จ็จ‹ๅบๅˆ›ๅปบไธ€ไธช `AsyncClient` ๏ผŒๅนถไฝฟ็”จ `await` ๅ‘ๅ…ถๅ‘้€ๅผ‚ๆญฅ่ฏทๆฑ‚ใ€‚ -{* ../../docs_src/async_tests/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} ่ฟ™็›ธๅฝ“ไบŽ๏ผš @@ -76,24 +76,24 @@ response = client.get('/') ๆˆ‘ไปฌๆ›พ็ป้€š่ฟ‡ๅฎƒๅ‘ `TestClient` ๅ‘ๅ‡บ่ฏทๆฑ‚ใ€‚ -/// tip +/// tip | ๆ็คบ ่ฏทๆณจๆ„๏ผŒๆˆ‘ไปฌๆญฃๅœจๅฐ† async/await ไธŽๆ–ฐ็š„ `AsyncClient` ไธ€่ตทไฝฟ็”จโ€”โ€”่ฏทๆฑ‚ๆ˜ฏๅผ‚ๆญฅ็š„ใ€‚ /// -/// warning +/// warning | ่ญฆๅ‘Š ๅฆ‚ๆžœๆ‚จ็š„ๅบ”็”จ็จ‹ๅบไพ่ต–ไบŽ็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ๏ผŒ `AsyncClient` ๅฐ†ไธไผš่งฆๅ‘่ฟ™ไบ›ไบ‹ไปถใ€‚ไธบไบ†็กฎไฟๅฎƒไปฌ่ขซ่งฆๅ‘๏ผŒ่ฏทไฝฟ็”จ florimondmanca/asgi-lifespan ไธญ็š„ `LifespanManager` ใ€‚ /// -## ๅ…ถไป–ๅผ‚ๆญฅๅ‡ฝๆ•ฐ่ฐƒ็”จ +## ๅ…ถไป–ๅผ‚ๆญฅๅ‡ฝๆ•ฐ่ฐƒ็”จ { #other-asynchronous-function-calls } ็”ฑไบŽๆต‹่ฏ•ๅ‡ฝๆ•ฐ็Žฐๅœจๆ˜ฏๅผ‚ๆญฅ็š„๏ผŒๅ› ๆญค้™คไบ†ๅœจๆต‹่ฏ•ไธญๅ‘ FastAPI ๅบ”็”จ็จ‹ๅบๅ‘้€่ฏทๆฑ‚ไน‹ๅค–๏ผŒๆ‚จ็Žฐๅœจ่ฟ˜ๅฏไปฅ่ฐƒ็”จ๏ผˆๅ’Œไฝฟ็”จ `await` ็ญ‰ๅพ…๏ผ‰ๅ…ถไป– `async` ๅผ‚ๆญฅๅ‡ฝๆ•ฐ๏ผŒๅฐฑๅ’Œๆ‚จๅœจไปฃ็ ไธญ็š„ๅ…ถไป–ไปปไฝ•ๅœฐๆ–น่ฐƒ็”จๅฎƒไปฌ็š„ๆ–นๆณ•ไธ€ๆ ทใ€‚ -/// tip +/// tip | ๆ็คบ -ๅฆ‚ๆžœๆ‚จๅœจๆต‹่ฏ•็จ‹ๅบไธญ้›†ๆˆๅผ‚ๆญฅๅ‡ฝๆ•ฐ่ฐƒ็”จ็š„ๆ—ถๅ€™้‡ๅˆฐไธ€ไธช `RuntimeError: Task attached to a different loop` ็š„ๆŠฅ้”™๏ผˆไพ‹ๅฆ‚๏ผŒไฝฟ็”จ MongoDB ็š„ MotorClient ๆ—ถ๏ผ‰๏ผŒ่ฏท่ฎฐไฝ๏ผŒๅช่ƒฝๅœจๅผ‚ๆญฅๅ‡ฝๆ•ฐไธญๅฎžไพ‹ๅŒ–้œ€่ฆไบ‹ไปถๅพช็Žฏ็š„ๅฏน่ฑก๏ผŒไพ‹ๅฆ‚้€š่ฟ‡ `'@app.on_event("startup")` ๅ›ž่ฐƒๅ‡ฝๆ•ฐ่ฟ›่กŒๅˆๅง‹ๅŒ–ใ€‚ +ๅฆ‚ๆžœๆ‚จๅœจๆต‹่ฏ•็จ‹ๅบไธญ้›†ๆˆๅผ‚ๆญฅๅ‡ฝๆ•ฐ่ฐƒ็”จ็š„ๆ—ถๅ€™้‡ๅˆฐไธ€ไธช `RuntimeError: Task attached to a different loop` ็š„ๆŠฅ้”™๏ผˆไพ‹ๅฆ‚๏ผŒไฝฟ็”จ MongoDB ็š„ MotorClient ๆ—ถ๏ผ‰๏ผŒ่ฏท่ฎฐไฝ๏ผŒๅช่ƒฝๅœจๅผ‚ๆญฅๅ‡ฝๆ•ฐไธญๅฎžไพ‹ๅŒ–้œ€่ฆไบ‹ไปถๅพช็Žฏ็š„ๅฏน่ฑก๏ผŒไพ‹ๅฆ‚ๅœจ `@app.on_event("startup")` ๅ›ž่ฐƒไธญๅˆๅง‹ๅŒ–ใ€‚ /// diff --git a/docs/zh/docs/advanced/behind-a-proxy.md b/docs/zh/docs/advanced/behind-a-proxy.md index f8f61c8a36..b44b0b5ac5 100644 --- a/docs/zh/docs/advanced/behind-a-proxy.md +++ b/docs/zh/docs/advanced/behind-a-proxy.md @@ -1,30 +1,131 @@ -# ไฝฟ็”จไปฃ็† +# ไฝฟ็”จไปฃ็† { #behind-a-proxy } -ๆœ‰ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฏ่ƒฝ่ฆไฝฟ็”จ Traefik ๆˆ– Nginx ็ญ‰**ไปฃ็†**ๆœๅŠกๅ™จ๏ผŒๅนถๆทปๅŠ ๅบ”็”จไธ่ƒฝ่ฏ†ๅˆซ็š„้™„ๅŠ ่ทฏๅพ„ๅ‰็ผ€้…็ฝฎใ€‚ +ๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ไผšๅœจ FastAPI ๅบ”็”จๅ‰้ขไฝฟ็”จๅƒ Traefik ๆˆ– Nginx ่ฟ™ๆ ท็š„**ไปฃ็†**ใ€‚ -ๆญคๆ—ถ๏ผŒ่ฆไฝฟ็”จ `root_path` ้…็ฝฎๅบ”็”จใ€‚ +่ฟ™ไบ›ไปฃ็†ๅฏไปฅๅค„็† HTTPS ่ฏไนฆ็ญ‰ไบ‹้กนใ€‚ -`root_path` ๆ˜ฏ ASGI ่ง„่Œƒๆไพ›็š„ๆœบๅˆถ๏ผŒFastAPI ๅฐฑๆ˜ฏๅŸบไบŽๆญค่ง„่Œƒๅผ€ๅ‘็š„๏ผˆ้€š่ฟ‡ Starlette๏ผ‰ใ€‚ +## ไปฃ็†่ฝฌๅ‘็š„่ฏทๆฑ‚ๅคด { #proxy-forwarded-headers } + +ๅœจไฝ ็š„ๅบ”็”จๅ‰้ข็š„**ไปฃ็†**้€šๅธธไผšๅœจๆŠŠ่ฏทๆฑ‚่ฝฌๅ‘็ป™ไฝ ็š„**ๆœๅŠกๅ™จ**ไน‹ๅ‰๏ผŒไธดๆ—ถ่ฎพ็ฝฎไธ€ไบ›่ฏทๆฑ‚ๅคด๏ผŒ่ฎฉๆœๅŠกๅ™จ็Ÿฅ้“่ฏฅ่ฏทๆฑ‚ๆ˜ฏ็”ฑไปฃ็†**่ฝฌๅ‘**็š„๏ผŒๅนถๅ‘Š็ŸฅๅŽŸๅง‹๏ผˆๅ…ฌ็ฝ‘๏ผ‰URL๏ผŒๅŒ…ๆ‹ฌๅŸŸๅใ€ๆ˜ฏๅฆไฝฟ็”จ HTTPS ็ญ‰ใ€‚ + +**ๆœๅŠกๅ™จ**็จ‹ๅบ๏ผˆไพ‹ๅฆ‚้€š่ฟ‡ **FastAPI CLI** ่ฟ่กŒ็š„ **Uvicorn**๏ผ‰่ƒฝๅคŸ่งฃๆž่ฟ™ไบ›่ฏทๆฑ‚ๅคด๏ผŒ็„ถๅŽๆŠŠ่ฟ™ไบ›ไฟกๆฏไผ ้€’็ป™ไฝ ็š„ๅบ”็”จใ€‚ + +ไฝ†ๅ‡บไบŽๅฎ‰ๅ…จ่€ƒ่™‘๏ผŒ็”ฑไบŽๆœๅŠกๅ™จๅนถไธ็Ÿฅ้“่‡ชๅทฑๅค„ๅœจๅ—ไฟกไปป็š„ไปฃ็†ไน‹ๅŽ๏ผŒๅฎƒ้ป˜่ฎคไธไผš่งฃๆž่ฟ™ไบ›่ฏทๆฑ‚ๅคดใ€‚ + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +่ฟ™ไบ›ไปฃ็†็›ธๅ…ณ็š„่ฏทๆฑ‚ๅคดๅŒ…ๆ‹ฌ๏ผš + +- X-Forwarded-For +- X-Forwarded-Proto +- X-Forwarded-Host + +/// + +### ๅฏ็”จไปฃ็†่ฝฌๅ‘็š„่ฏทๆฑ‚ๅคด { #enable-proxy-forwarded-headers } + +ไฝ ๅฏไปฅ็”จ *CLI ้€‰้กน* `--forwarded-allow-ips` ๅฏๅŠจ FastAPI CLI๏ผŒๅนถไผ ๅ…ฅๅบ”่ฏฅ่ขซไฟกไปปใ€ๅ…่ฎธ่ฏปๅ–่ฟ™ไบ›่ฝฌๅ‘่ฏทๆฑ‚ๅคด็š„ IP ๅœฐๅ€ๅˆ—่กจใ€‚ + +ๅฆ‚ๆžœ่ฎพ็ฝฎไธบ `--forwarded-allow-ips="*"`๏ผŒๅฐฑไผšไฟกไปปๆ‰€ๆœ‰ๆฅๆบ IPใ€‚ + +ๅฆ‚ๆžœไฝ ็š„**ๆœๅŠกๅ™จ**ไฝไบŽๅ—ไฟกไปป็š„**ไปฃ็†**ไน‹ๅŽ๏ผŒๅนถไธ”ๅชๆœ‰ไปฃ็†ไผšไธŽๅฎƒ้€šไฟก๏ผŒ่ฟ™ๅฐ†ไฝฟๅ…ถๆŽฅๅ—่ฏฅ**ไปฃ็†**็š„ไปปไฝ• IPใ€‚ + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ไฝฟ็”จ HTTPS ็š„้‡ๅฎšๅ‘ { #redirects-with-https } + +ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๅฎšไน‰ไบ†ไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* `/items/`๏ผš + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} + +ๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•่ฎฟ้—ฎ `/items`๏ผŒ้ป˜่ฎคไผš่ขซ้‡ๅฎšๅ‘ๅˆฐ `/items/`ใ€‚ + +ไฝ†ๅœจ่ฎพ็ฝฎ *CLI ้€‰้กน* `--forwarded-allow-ips` ไน‹ๅ‰๏ผŒๅฎƒๅฏ่ƒฝไผš้‡ๅฎšๅ‘ๅˆฐ `http://localhost:8000/items/`ใ€‚ + +่€Œไฝ ็š„ๅบ”็”จๅฏ่ƒฝๆ‰˜็ฎกๅœจ `https://mysuperapp.com`๏ผŒ้‡ๅฎšๅ‘ๅบ”ๅฝ“ๆ˜ฏ `https://mysuperapp.com/items/`ใ€‚ + +้€š่ฟ‡่ฎพ็ฝฎ `--proxy-headers`๏ผŒFastAPI ็Žฐๅœจๅฐฑๅฏไปฅ้‡ๅฎšๅ‘ๅˆฐๆญฃ็กฎ็š„ไฝ็ฝฎใ€‚๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃๆ›ดๅคšๅ…ณไบŽ HTTPS ็š„ๅ†…ๅฎน๏ผŒๆŸฅ็œ‹ๆŒ‡ๅ—๏ผš[ๅ…ณไบŽ HTTPS](../deployment/https.md){.internal-link target=_blank}ใ€‚ + +/// + +### ไปฃ็†่ฝฌๅ‘่ฏทๆฑ‚ๅคดๅฆ‚ไฝ•ๅทฅไฝœ { #how-proxy-forwarded-headers-work } + +ไธ‹้ขๆ˜ฏไธ€ไธชๅฏ่ง†ๅŒ–ๅ›พ็คบ๏ผŒๅฑ•็คบไบ†**ไปฃ็†**ๅฆ‚ไฝ•ๅœจๅฎขๆˆท็ซฏไธŽ**ๅบ”็”จๆœๅŠกๅ™จ**ไน‹้—ดๆทปๅŠ ่ฝฌๅ‘่ฏทๆฑ‚ๅคด๏ผš + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**ไปฃ็†**ไผšๆ‹ฆๆˆชๅŽŸๅง‹ๅฎขๆˆท็ซฏ่ฏทๆฑ‚๏ผŒๅนถๅœจๅฐ†่ฏทๆฑ‚ไผ ้€’็ป™**ๅบ”็”จๆœๅŠกๅ™จ**ไน‹ๅ‰๏ผŒๆทปๅŠ ็‰นๆฎŠ็š„*่ฝฌๅ‘*่ฏทๆฑ‚ๅคด๏ผˆ`X-Forwarded-*`๏ผ‰ใ€‚ + +่ฟ™ไบ›่ฏทๆฑ‚ๅคดไฟ็•™ไบ†ๅŽŸๅง‹่ฏทๆฑ‚ไธญๅฆๅˆ™ไผšไธขๅคฑ็š„ไฟกๆฏ๏ผš + +- X-Forwarded-For๏ผšๅŽŸๅง‹ๅฎขๆˆท็ซฏ็š„ IP ๅœฐๅ€ +- X-Forwarded-Proto๏ผšๅŽŸๅง‹ๅ่ฎฎ๏ผˆ`https`๏ผ‰ +- X-Forwarded-Host๏ผšๅŽŸๅง‹ไธปๆœบ๏ผˆ`mysuperapp.com`๏ผ‰ + +ๅฝ“ **FastAPI CLI** ้…็ฝฎไบ† `--forwarded-allow-ips` ๅŽ๏ผŒๅฎƒไผšไฟกไปปๅนถไฝฟ็”จ่ฟ™ไบ›่ฏทๆฑ‚ๅคด๏ผŒไพ‹ๅฆ‚็”จไบŽๅœจ้‡ๅฎšๅ‘ไธญ็”Ÿๆˆๆญฃ็กฎ็š„ URLใ€‚ + +## ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็† { #proxy-with-a-stripped-path-prefix } + +ไฝ ๅฏ่ƒฝไผšๆœ‰ไธ€ไธชไปฃ็†๏ผŒไธบไฝ ็š„ๅบ”็”จๆทปๅŠ ไธ€ไธช่ทฏๅพ„ๅ‰็ผ€ใ€‚ + +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `root_path` ๆฅ้…็ฝฎไฝ ็š„ๅบ”็”จใ€‚ + +`root_path` ๆ˜ฏ ASGI ่ง„่Œƒ๏ผˆFastAPI ๅŸบไบŽ่ฏฅ่ง„่Œƒ๏ผŒ้€š่ฟ‡ Starlette ๆž„ๅปบ๏ผ‰ๆไพ›็š„ๆœบๅˆถใ€‚ `root_path` ็”จไบŽๅค„็†่ฟ™ไบ›็‰นๅฎšๆƒ…ๅ†ตใ€‚ -ๅœจๆŒ‚่ฝฝๅญๅบ”็”จๆ—ถ๏ผŒไนŸๅฏไปฅๅœจๅ†…้ƒจไฝฟ็”จใ€‚ +ๅœจๆŒ‚่ฝฝๅญๅบ”็”จๆ—ถ๏ผŒๅฎƒไนŸไผšๅœจๅ†…้ƒจไฝฟ็”จใ€‚ -## ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็† +โ€œ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†โ€ๅœจ่ฟ™้‡Œ็š„ๆ„ๆ€ๆ˜ฏ๏ผšไฝ ๅฏไปฅๅœจไปฃ็ ไธญๅฃฐๆ˜Žไธ€ไธช่ทฏๅพ„ `/app`๏ผŒ็„ถๅŽๅœจ้กถๅฑ‚ๆทปๅŠ ไธ€ๅฑ‚๏ผˆไปฃ็†๏ผ‰๏ผŒๆŠŠไฝ ็š„ **FastAPI** ๅบ”็”จๆ”พๅœจ็ฑปไผผ `/api/v1` ็š„่ทฏๅพ„ไธ‹ใ€‚ -ๆœฌไพ‹ไธญ๏ผŒ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†ๆ˜ฏๆŒ‡ๅœจไปฃ็ ไธญๅฃฐๆ˜Ž่ทฏๅพ„ `/app`๏ผŒ็„ถๅŽๅœจๅบ”็”จ้กถๅฑ‚ๆทปๅŠ ไปฃ็†๏ผŒๆŠŠ **FastAPI** ๅบ”็”จๆ”พๅœจ `/api/v1` ่ทฏๅพ„ไธ‹ใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅŽŸๅง‹่ทฏๅพ„ `/app` ๅฎž้™…ไธŠไผšๅœจ `/api/v1/app` ๆไพ›ๆœๅŠกใ€‚ -ๆœฌไพ‹็š„ๅŽŸๅง‹่ทฏๅพ„ `/app` ๅฎž้™…ไธŠๆ˜ฏๅœจ `/api/v1/app` ๆไพ›ๆœๅŠกใ€‚ +ๅณไฝฟไฝ ็š„ๆ‰€ๆœ‰ไปฃ็ ้ƒฝๅ‡่ฎพๅชๆœ‰ `/app`ใ€‚ -ๅ“ชๆ€•ๆ‰€ๆœ‰ไปฃ็ ้ƒฝๅ‡่ฎพๅชๆœ‰ `/app`ใ€‚ +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} -ไปฃ็†ๅชๅœจๆŠŠ่ฏทๆฑ‚ไผ ้€็ป™ Uvicorn ไน‹ๅ‰ๆ‰ไผš**็งป้™ค่ทฏๅพ„ๅ‰็ผ€**๏ผŒ่ฎฉๅบ”็”จไปฅไธบๅฎƒๆ˜ฏๅœจ `/app` ๆไพ›ๆœๅŠก๏ผŒๅ› ๆญคไธๅฟ…ๅœจไปฃ็ ไธญๅŠ ๅ…ฅๅ‰็ผ€ `/api/v1`ใ€‚ +ไปฃ็†ไผšๅœจๅฐ†่ฏทๆฑ‚ไผ ้€’็ป™ๅบ”็”จๆœๅŠกๅ™จ๏ผˆๅฏ่ƒฝๆ˜ฏ้€š่ฟ‡ FastAPI CLI ่ฟ่กŒ็š„ Uvicorn๏ผ‰ไน‹ๅ‰๏ผŒๅฎžๆ—ถ**โ€œ็งป้™คโ€**่ฟ™ไธช**่ทฏๅพ„ๅ‰็ผ€**๏ผŒ่ฎฉไฝ ็š„ๅบ”็”จ่ฎคไธบๅฎƒๆ˜ฏๅœจ `/app` ่ขซๆœๅŠก๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑไธ้œ€่ฆๆ›ดๆ–ฐๆ‰€ๆœ‰ไปฃ็ ๅŽปๅŒ…ๅซ `/api/v1` ๅ‰็ผ€ใ€‚ -ไฝ†ไน‹ๅŽ๏ผŒๅœจ๏ผˆๅ‰็ซฏ๏ผ‰ๆ‰“ๅผ€ API ๆ–‡ๆกฃๆ—ถ๏ผŒไปฃ็†ไผš่ฆๆฑ‚ๅœจ `/openapi.json`๏ผŒ่€Œไธๆ˜ฏ `/api/v1/openapi.json` ไธญๆๅ– OpenAPI ๆฆ‚ๅ›พใ€‚ +ๅˆฐ่ฟ™้‡Œ๏ผŒไธ€ๅˆ‡้ƒฝไผšๅƒๅพ€ๅธธไธ€ๆ ทๅทฅไฝœใ€‚ -ๅ› ๆญค๏ผŒ ๏ผˆ่ฟ่กŒๅœจๆต่งˆๅ™จไธญ็š„๏ผ‰ๅ‰็ซฏไผšๅฐ่ฏ•่ฎฟ้—ฎ `/openapi.json`๏ผŒไฝ†ๆฒกๆœ‰ๅŠžๆณ•่Žทๅ– OpenAPI ๆฆ‚ๅ›พใ€‚ +ไฝ†ๆ˜ฏ๏ผŒๅฝ“ไฝ ๆ‰“ๅผ€้›†ๆˆ็š„ๆ–‡ๆกฃ็•Œ้ข๏ผˆๅ‰็ซฏ๏ผ‰ๆ—ถ๏ผŒๅฎƒไผšๆœŸๆœ›ๅœจ `/openapi.json` ่Žทๅ– OpenAPI ๆจกๅผ๏ผŒ่€Œไธๆ˜ฏๅœจ `/api/v1/openapi.json`ใ€‚ -่ฟ™ๆ˜ฏๅ› ไธบๅบ”็”จไฝฟ็”จไบ†ไปฅ `/api/v1` ไธบ่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†๏ผŒๅ‰็ซฏ่ฆไปŽ `/api/v1/openapi.json` ไธญๆๅ– OpenAPI ๆฆ‚ๅ›พใ€‚ +ๅ› ๆญค๏ผŒ๏ผˆๅœจๆต่งˆๅ™จไธญ่ฟ่กŒ็š„๏ผ‰ๅ‰็ซฏไผšๅฐ่ฏ•่ฎฟ้—ฎ `/openapi.json`๏ผŒไฝ†ๆ— ๆณ•่Žทๅ– OpenAPI ๆจกๅผใ€‚ + +ๅ› ไธบๆˆ‘ไปฌ็š„ๅบ”็”จไฝฟ็”จไบ†่ทฏๅพ„ๅ‰็ผ€ไธบ `/api/v1` ็š„ไปฃ็†๏ผŒๅ‰็ซฏ้œ€่ฆไปŽ `/api/v1/openapi.json` ่Žทๅ– OpenAPI ๆจกๅผใ€‚ ```mermaid graph LR @@ -39,15 +140,15 @@ proxy --> server /// tip | ๆ็คบ -IP `0.0.0.0` ๅธธ็”จไบŽๆŒ‡็จ‹ๅบ็›‘ๅฌๆœฌๆœบๆˆ–ๆœๅŠกๅ™จไธŠ็š„ๆ‰€ๆœ‰ๆœ‰ๆ•ˆ IPใ€‚ +IP `0.0.0.0` ้€šๅธธ่กจ็คบ็จ‹ๅบ็›‘ๅฌ่ฏฅๆœบๅ™จ/ๆœๅŠกๅ™จไธŠ็š„ๆ‰€ๆœ‰ๅฏ็”จ IPใ€‚ /// -API ๆ–‡ๆกฃ่ฟ˜้œ€่ฆ OpenAPI ๆฆ‚ๅ›พๅฃฐๆ˜Ž API `server` ไฝไบŽ `/api/v1`๏ผˆไฝฟ็”จไปฃ็†ๆ—ถ็š„ URL๏ผ‰ใ€‚ไพ‹ๅฆ‚๏ผš +ๆ–‡ๆกฃ็•Œ้ข่ฟ˜้œ€่ฆ OpenAPI ๆจกๅผๅฃฐๆ˜Ž่ฏฅ API ็š„ `server` ไฝไบŽ `/api/v1`๏ผˆไปฃ็†ๅŽ้ข๏ผ‰ใ€‚ไพ‹ๅฆ‚๏ผš ```JSON hl_lines="4-8" { - "openapi": "3.0.2", + "openapi": "3.1.0", // More stuff here "servers": [ { @@ -60,53 +161,53 @@ API ๆ–‡ๆกฃ่ฟ˜้œ€่ฆ OpenAPI ๆฆ‚ๅ›พๅฃฐๆ˜Ž API `server` ไฝไบŽ `/api/v1`๏ผˆไฝฟ็”จ } ``` -ๆœฌไพ‹ไธญ็š„ `Proxy` ๆ˜ฏ **Traefik**๏ผŒ`server` ๆ˜ฏ่ฟ่กŒ FastAPI ๅบ”็”จ็š„ **Uvicorn**ใ€‚ +ๅœจๆญค็คบไพ‹ไธญ๏ผŒโ€œProxyโ€ ๅฏไปฅๆ˜ฏ **Traefik** ไน‹็ฑป็š„ใ€‚ๆœๅŠกๅ™จๅฏไปฅๆ˜ฏ็”จ **Uvicorn** ็š„ **FastAPI CLI** ่ฟ่กŒไฝ ็š„ FastAPI ๅบ”็”จใ€‚ -### ๆไพ› `root_path` +### ๆไพ› `root_path` { #providing-the-root-path } -ไธบๆญค๏ผŒ่ฆไปฅๅฆ‚ไธ‹ๆ–นๅผไฝฟ็”จๅ‘ฝไปค่กŒ้€‰้กน `--root-path`๏ผš +ไธบๆญค๏ผŒไฝ ๅฏไปฅๅƒไธ‹้ข่ฟ™ๆ ทไฝฟ็”จๅ‘ฝไปค่กŒ้€‰้กน `--root-path`๏ผš
```console -$ uvicorn main:app --root-path /api/v1 +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-Hypercorn ไนŸๆ”ฏๆŒ `--root-path `้€‰้กนใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ Hypercorn๏ผŒๅฎƒไนŸๆœ‰ `--root-path` ้€‰้กนใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ASGI ่ง„่Œƒๅฎšไน‰็š„ `root_path` ๅฐฑๆ˜ฏไธบไบ†่ฟ™็ง็”จไพ‹ใ€‚ +ASGI ่ง„่Œƒไธบ่ฟ™็ง็”จไพ‹ๅฎšไน‰ไบ† `root_path`ใ€‚ -ๅนถไธ” `--root-path` ๅ‘ฝไปค่กŒ้€‰้กนๆ”ฏๆŒ `root_path`ใ€‚ +ๅ‘ฝไปค่กŒ้€‰้กน `--root-path` ไผšๆไพ›่ฏฅ `root_path`ใ€‚ /// -### ๆŸฅ็œ‹ๅฝ“ๅ‰็š„ `root_path` +### ๆŸฅ็œ‹ๅฝ“ๅ‰็š„ `root_path` { #checking-the-current-root-path } -่Žทๅ–ๅบ”็”จไธบๆฏไธช่ฏทๆฑ‚ไฝฟ็”จ็š„ๅฝ“ๅ‰ `root_path`๏ผŒ่ฟ™ๆ˜ฏ `scope` ๅญ—ๅ…ธ็š„ๅ†…ๅฎน๏ผˆไนŸๆ˜ฏ ASGI ่ง„่Œƒ็š„ๅ†…ๅฎน๏ผ‰ใ€‚ +ไฝ ๅฏไปฅ่Žทๅ–ๅบ”็”จๅœจๆฏไธช่ฏทๆฑ‚ไธญไฝฟ็”จ็š„ๅฝ“ๅ‰ `root_path`๏ผŒๅฎƒๆ˜ฏ `scope` ๅญ—ๅ…ธ็š„ไธ€้ƒจๅˆ†๏ผˆASGI ่ง„่Œƒ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ -ๆˆ‘ไปฌๅœจ่ฟ™้‡Œ็š„ไฟกๆฏ้‡ŒๅŒ…ๅซ `roo_path` ๅชๆ˜ฏไธบไบ†ๆผ”็คบใ€‚ +่ฟ™้‡Œๆˆ‘ไปฌๆŠŠๅฎƒๅŒ…ๅซๅœจๅ“ๅบ”ๆถˆๆฏไธญไป…็”จไบŽๆผ”็คบใ€‚ -{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} -็„ถๅŽ๏ผŒ็”จไปฅไธ‹ๅ‘ฝไปคๅฏๅŠจ Uvicorn๏ผš +็„ถๅŽ๏ผŒๅฆ‚ๆžœไฝ ่ฟ™ๆ ทๅฏๅŠจ Uvicorn๏ผš
```console -$ uvicorn main:app --root-path /api/v1 +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-่ฟ”ๅ›ž็š„ๅ“ๅบ”ๅฆ‚ไธ‹๏ผš +ๅ“ๅบ”็ฑปไผผไบŽ๏ผš ```JSON { @@ -115,19 +216,19 @@ $ uvicorn main:app --root-path /api/v1 } ``` -### ๅœจ FastAPI ๅบ”็”จ้‡Œ่ฎพ็ฝฎ `root_path` +### ๅœจ FastAPI ๅบ”็”จไธญ่ฎพ็ฝฎ `root_path` { #setting-the-root-path-in-the-fastapi-app } -่ฟ˜ๆœ‰ไธ€็งๆ–นๆกˆ๏ผŒๅฆ‚ๆžœไธ่ƒฝๆไพ› `--root-path` ๆˆ–็ญ‰ๆ•ˆ็š„ๅ‘ฝไปค่กŒ้€‰้กน๏ผŒๅˆ™ๅœจๅˆ›ๅปบ FastAPI ๅบ”็”จๆ—ถ่ฆ่ฎพ็ฝฎ `root_path` ๅ‚ๆ•ฐใ€‚ +ๆˆ–่€…๏ผŒๅฆ‚ๆžœไฝ ๆ— ๆณ•ๆไพ›็ฑปไผผ `--root-path` ็š„ๅ‘ฝไปค่กŒ้€‰้กน๏ผŒไฝ ๅฏไปฅๅœจๅˆ›ๅปบ FastAPI ๅบ”็”จๆ—ถ่ฎพ็ฝฎๅ‚ๆ•ฐ `root_path`๏ผš -{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} -ไผ ้€’ `root_path` ็ป™ `FastAPI` ไธŽไผ ้€’ `--root-path` ๅ‘ฝไปค่กŒ้€‰้กน็ป™ Uvicorn ๆˆ– Hypercorn ไธ€ๆ ทใ€‚ +ๆŠŠ `root_path` ไผ ็ป™ `FastAPI` ็ญ‰ๅŒไบŽๆŠŠๅ‘ฝไปค่กŒ้€‰้กน `--root-path` ไผ ็ป™ Uvicorn ๆˆ– Hypercornใ€‚ -### ๅ…ณไบŽ `root_path` +### ๅ…ณไบŽ `root_path` { #about-root-path } -ๆณจๆ„๏ผŒๆœๅŠกๅ™จ๏ผˆUvicorn๏ผ‰ๅชๆ˜ฏๆŠŠ `root_path` ไผ ้€’็ป™ๅบ”็”จใ€‚ +่ฏทๆณจๆ„๏ผŒๆœๅŠกๅ™จ๏ผˆUvicorn๏ผ‰ไธไผš็”จ่ฟ™ไธช `root_path` ๅšๅˆซ็š„ไบ‹ๆƒ…๏ผŒๅชไผšๆŠŠๅฎƒไผ ็ป™ๅบ”็”จใ€‚ -ๅœจๆต่งˆๅ™จไธญ่พ“ๅ…ฅ http://127.0.0.1:8000/appย ๆ—ถ่ƒฝ็œ‹ๅˆฐๆ ‡ๅ‡†ๅ“ๅบ”๏ผš +ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ ็”จๆต่งˆๅ™จๆ‰“ๅผ€ http://127.0.0.1:8000/app๏ผŒไฝ ไผš็œ‹ๅˆฐๆญฃๅธธ็š„ๅ“ๅบ”๏ผš ```JSON { @@ -136,25 +237,25 @@ $ uvicorn main:app --root-path /api/v1 } ``` -ๅฎƒไธ่ฆๆฑ‚่ฎฟ้—ฎ `http://127.0.0.1:800/api/v1/app`ใ€‚ +ๅ› ๆญค๏ผŒๅฎƒไธไผšๆœŸๆœ›่ขซ่ฎฟ้—ฎไบŽ `http://127.0.0.1:8000/api/v1/app`ใ€‚ -Uvicorn ้ข„ๆœŸไปฃ็†ๅœจ `http://127.0.0.1:8000/app` ่ฎฟ้—ฎ Uvicorn๏ผŒ่€Œๅœจ้กถ้ƒจๆทปๅŠ  `/api/v1` ๅ‰็ผ€ๆ˜ฏไปฃ็†่ฆๅš็š„ไบ‹ๆƒ…ใ€‚ +Uvicorn ไผšๆœŸๆœ›ไปฃ็†ไปฅ `http://127.0.0.1:8000/app` ่ฎฟ้—ฎ Uvicorn๏ผŒ่€Œๅœจ้กถ้ƒจ้ขๅค–ๆทปๅŠ  `/api/v1` ๅ‰็ผ€ๆ˜ฏไปฃ็†็š„่Œ่ดฃใ€‚ -## ๅ…ณไบŽ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็† +## ๅ…ณไบŽ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็† { #about-proxies-with-a-stripped-path-prefix } -ๆณจๆ„๏ผŒ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†ๅชๆ˜ฏ้…็ฝฎไปฃ็†็š„ๆ–นๅผไน‹ไธ€ใ€‚ +่ฏท่ฎฐไฝ๏ผŒ็งป้™ค่ทฏๅพ„ๅ‰็ผ€ๅชๆ˜ฏ้…็ฝฎไปฃ็†็š„ไธ€็งๆ–นๅผใ€‚ -ๅคง้ƒจๅˆ†ๆƒ…ๅ†ตไธ‹๏ผŒไปฃ็†้ป˜่ฎค้ƒฝไธไผš็งป้™ค่ทฏๅพ„ๅ‰็ผ€ใ€‚ +ๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒ้ป˜่ฎคๆ˜ฏไปฃ็†ไธไผš็งป้™ค่ทฏๅพ„ๅ‰็ผ€ใ€‚ -๏ผˆๆœช็งป้™ค่ทฏๅพ„ๅ‰็ผ€ๆ—ถ๏ผ‰ไปฃ็†็›‘ๅฌ `https://myawesomeapp.com` ็ญ‰ๅฏน่ฑก๏ผŒๅฆ‚ๆžœๆต่งˆๅ™จ่ทณ่ฝฌๅˆฐ `https://myawesomeapp.com/api/v1/app`๏ผŒไธ”ๆœๅŠกๅ™จ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰็›‘ๅฌ `http://127.0.0.1:8000` ไปฃ็†๏ผˆๆœช็งป้™ค่ทฏๅพ„ๅ‰็ผ€๏ผ‰ ไผšๅœจๅŒๆ ท็š„่ทฏๅพ„๏ผš`http://127.0.0.1:8000/api/v1/app` ่ฎฟ้—ฎ Uvicornใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผˆๆฒกๆœ‰็งป้™ค่ทฏๅพ„ๅ‰็ผ€๏ผ‰๏ผŒไปฃ็†ไผš็›‘ๅฌ็ฑปไผผ `https://myawesomeapp.com`๏ผŒๅฝ“ๆต่งˆๅ™จ่ฎฟ้—ฎ `https://myawesomeapp.com/api/v1/app` ไธ”ไฝ ็š„ๆœๅŠกๅ™จ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰็›‘ๅฌ `http://127.0.0.1:8000` ๆ—ถ๏ผŒไปฃ็†๏ผˆๆœช็งป้™ค่ทฏๅพ„ๅ‰็ผ€๏ผ‰ไผšไปฅ็›ธๅŒ่ทฏๅพ„่ฎฟ้—ฎ Uvicorn๏ผš`http://127.0.0.1:8000/api/v1/app`ใ€‚ -## ๆœฌๅœฐๆต‹่ฏ• Traefik +## ไฝฟ็”จ Traefik ่ฟ›่กŒๆœฌๅœฐๆต‹่ฏ• { #testing-locally-with-traefik } -ๆ‚จๅฏไปฅ่ฝปๆ˜“ๅœฐๅœจๆœฌๅœฐไฝฟ็”จ Traefik ่ฟ่กŒ็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„่ฏ•้ชŒใ€‚ +ไฝ ๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐไฝฟ็”จ Traefik ๅœจๆœฌๅœฐ่ฟ่กŒไธ€ไธช็งป้™ค่ทฏๅพ„ๅ‰็ผ€็š„ๅฎž้ชŒใ€‚ -ไธ‹่ฝฝ Traefik๏ผŒ่ฟ™ๆ˜ฏไธ€ไธชไบŒ่ฟ›ๅˆถๆ–‡ไปถ๏ผŒ้œ€่ฆ่งฃๅŽ‹ๆ–‡ไปถ๏ผŒๅนถๅœจ Terminal ไธญ็›ดๆŽฅ่ฟ่กŒใ€‚ +ไธ‹่ฝฝ Traefik๏ผŒๅฎƒๆ˜ฏไธ€ไธชๅ•็‹ฌ็š„ไบŒ่ฟ›ๅˆถๆ–‡ไปถ๏ผŒไฝ ๅฏไปฅ่งฃๅŽ‹ๅŽ‹็ผฉๅŒ…ๅนถ็›ดๆŽฅๅœจ็ปˆ็ซฏไธญ่ฟ่กŒใ€‚ -็„ถๅŽๅˆ›ๅปบๅŒ…ๅซๅฆ‚ไธ‹ๅ†…ๅฎน็š„ `traefik.toml` ๆ–‡ไปถ๏ผš +็„ถๅŽๅˆ›ๅปบไธ€ไธช `traefik.toml` ๆ–‡ไปถ๏ผŒๅ†…ๅฎนๅฆ‚ไธ‹๏ผš ```TOML hl_lines="3" [entryPoints] @@ -166,15 +267,15 @@ Uvicorn ้ข„ๆœŸไปฃ็†ๅœจ `http://127.0.0.1:8000/app` ่ฎฟ้—ฎ Uvicorn๏ผŒ่€Œๅœจ้กถ filename = "routes.toml" ``` -่ฟ™ไธชๆ–‡ไปถๆŠŠ Traefik ็›‘ๅฌ็ซฏๅฃ่ฎพ็ฝฎไธบ `9999`๏ผŒๅนถ่ฎพ็ฝฎ่ฆไฝฟ็”จๅฆไธ€ไธชๆ–‡ไปถ `routes.toml`ใ€‚ +่ฟ™ๅ‘Š่ฏ‰ Traefik ็›‘ๅฌ็ซฏๅฃ 9999๏ผŒๅนถไฝฟ็”จๅฆไธ€ไธชๆ–‡ไปถ `routes.toml`ใ€‚ /// tip | ๆ็คบ -ไฝฟ็”จ็ซฏๅฃ 9999 ไปฃๆ›ฟๆ ‡ๅ‡†็š„ HTTP ็ซฏๅฃ 80๏ผŒ่ฟ™ๆ ทๅฐฑไธๅฟ…ไฝฟ็”จ็ฎก็†ๅ‘˜ๆƒ้™่ฟ่กŒ๏ผˆ`sudo`๏ผ‰ใ€‚ +ๆˆ‘ไปฌไฝฟ็”จ 9999 ็ซฏๅฃ่€Œไธๆ˜ฏๆ ‡ๅ‡† HTTP ็ซฏๅฃ 80๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑไธ้œ€่ฆ็”จ็ฎก็†ๅ‘˜๏ผˆ`sudo`๏ผ‰ๆƒ้™่ฟ่กŒใ€‚ /// -ๆŽฅไธ‹ๆฅ๏ผŒๅˆ›ๅปบ `routes.toml`๏ผš +็Žฐๅœจๅˆ›ๅปบๅฆไธ€ไธชๆ–‡ไปถ `routes.toml`๏ผš ```TOML hl_lines="5 12 20" [http] @@ -201,9 +302,9 @@ Uvicorn ้ข„ๆœŸไปฃ็†ๅœจ `http://127.0.0.1:8000/app` ่ฎฟ้—ฎ Uvicorn๏ผŒ่€Œๅœจ้กถ ่ฟ™ไธชๆ–‡ไปถ้…็ฝฎ Traefik ไฝฟ็”จ่ทฏๅพ„ๅ‰็ผ€ `/api/v1`ใ€‚ -็„ถๅŽ๏ผŒๅฎƒๆŠŠ่ฏทๆฑ‚้‡ๅฎšไฝๅˆฐ่ฟ่กŒๅœจ `http://127.0.0.1:8000` ไธŠ็š„ Uvicornใ€‚ +้šๅŽ Traefik ไผšๆŠŠ่ฏทๆฑ‚่ฝฌๅ‘ๅˆฐ่ฟ่กŒๅœจ `http://127.0.0.1:8000` ็š„ Uvicornใ€‚ -็Žฐๅœจ๏ผŒๅฏๅŠจ Traefik๏ผš +็ŽฐๅœจๅฏๅŠจ Traefik๏ผš
@@ -215,21 +316,21 @@ INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
-ๆŽฅไธ‹ๆฅ๏ผŒไฝฟ็”จ Uvicorn ๅฏๅŠจๅบ”็”จ๏ผŒๅนถไฝฟ็”จ `--root-path` ้€‰้กน๏ผš +็„ถๅŽไฝฟ็”จ `--root-path` ้€‰้กนๅฏๅŠจไฝ ็š„ๅบ”็”จ๏ผš
```console -$ uvicorn main:app --root-path /api/v1 +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-### ๆŸฅ็œ‹ๅ“ๅบ” +### ๆŸฅ็œ‹ๅ“ๅบ” { #check-the-responses } -่ฎฟ้—ฎๅซ Uvicorn ็ซฏๅฃ็š„ URL๏ผšhttp://127.0.0.1:8000/app๏ผŒๅฐฑ่ƒฝ็œ‹ๅˆฐๆ ‡ๅ‡†ๅ“ๅบ”๏ผš +็Žฐๅœจ๏ผŒๅฆ‚ๆžœไฝ ่ฎฟ้—ฎ Uvicorn ็ซฏๅฃๅฏนๅบ”็š„ URL๏ผšhttp://127.0.0.1:8000/app๏ผŒไฝ ไผš็œ‹ๅˆฐๆญฃๅธธๅ“ๅบ”๏ผš ```JSON { @@ -240,13 +341,13 @@ $ uvicorn main:app --root-path /api/v1 /// tip | ๆ็คบ -ๆณจๆ„๏ผŒๅฐฑ็ฎ—่ฎฟ้—ฎ `http://127.0.0.1:8000/app`๏ผŒไนŸๆ˜พ็คบไปŽ้€‰้กน `--root-path` ไธญๆๅ–็š„ `/api/v1`๏ผŒ่ฟ™ๆ˜ฏ `root_path` ็š„ๅ€ผใ€‚ +ๆณจๆ„๏ผŒๅฐฝ็ฎกไฝ ๆ˜ฏ้€š่ฟ‡ `http://127.0.0.1:8000/app` ่ฎฟ้—ฎ๏ผŒๅฎƒไปๆ˜พ็คบ `root_path` ไธบ `/api/v1`๏ผŒ่ฏฅๅ€ผๆฅ่‡ช `--root-path` ้€‰้กนใ€‚ /// -ๆ‰“ๅผ€ๅซ Traefik ็ซฏๅฃ็š„ URL๏ผŒๅŒ…ๅซ่ทฏๅพ„ๅ‰็ผ€๏ผšhttp://127.0.0.1:9999/api/v1/appใ€‚ +็Žฐๅœจๆ‰“ๅผ€ๅŒ…ๅซ่ทฏๅพ„ๅ‰็ผ€ใ€ไฝฟ็”จ Traefik ็ซฏๅฃ็š„ URL๏ผšhttp://127.0.0.1:9999/api/v1/appใ€‚ -ๅพ—ๅˆฐๅŒๆ ท็š„ๅ“ๅบ”๏ผš +ๆˆ‘ไปฌๅพ—ๅˆฐ็›ธๅŒ็š„ๅ“ๅบ”๏ผš ```JSON { @@ -255,57 +356,57 @@ $ uvicorn main:app --root-path /api/v1 } ``` -ไฝ†่ฟ™ไธ€ๆฌก URL ๅŒ…ๅซไบ†ไปฃ็†ๆไพ›็š„่ทฏๅพ„ๅ‰็ผ€๏ผš`/api/v1`ใ€‚ +ไฝ†่ฟ™ๆฌก URL ไธญๅธฆๆœ‰ไปฃ็†ๆไพ›็š„ๅ‰็ผ€่ทฏๅพ„๏ผš`/api/v1`ใ€‚ -ๅฝ“็„ถ๏ผŒ่ฟ™ๆ˜ฏ้€š่ฟ‡ไปฃ็†่ฎฟ้—ฎๅบ”็”จ็š„ๆ–นๅผ๏ผŒๅ› ๆญค๏ผŒ่ทฏๅพ„ๅ‰็ผ€ `/app/v1` ็‰ˆๆœฌๆ‰ๆ˜ฏ**ๆญฃ็กฎ**็š„ใ€‚ +ๅฝ“็„ถ๏ผŒ่ฟ™้‡Œ็š„ๆƒณๆณ•ๆ˜ฏๆฏไธชไบบ้ƒฝ้€š่ฟ‡ไปฃ็†่ฎฟ้—ฎๅบ”็”จ๏ผŒๅ› ๆญคๅธฆๆœ‰่ทฏๅพ„ๅ‰็ผ€ `/api/v1` ็š„็‰ˆๆœฌๆ‰ๆ˜ฏโ€œๆญฃ็กฎโ€็š„ใ€‚ -่€Œไธๅธฆ่ทฏๅพ„ๅ‰็ผ€็š„็‰ˆๆœฌ๏ผˆ`http://127.0.0.1:8000/app`๏ผ‰๏ผŒๅˆ™็”ฑ Uvicorn ็›ดๆŽฅๆไพ›๏ผŒไธ“ไพ›*ไปฃ็†*๏ผˆTraefik๏ผ‰่ฎฟ้—ฎใ€‚ +่€Œไธๅธฆ่ทฏๅพ„ๅ‰็ผ€็š„็‰ˆๆœฌ๏ผˆ`http://127.0.0.1:8000/app`๏ผ‰็”ฑ Uvicorn ็›ดๆŽฅๆไพ›๏ผŒไป…ไพ›_ไปฃ็†_๏ผˆTraefik๏ผ‰่ฎฟ้—ฎใ€‚ -่ฟ™ๆผ”็คบไบ†ไปฃ็†๏ผˆTraefik๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ่ทฏๅพ„ๅ‰็ผ€๏ผŒไปฅๅŠๆœๅŠกๅ™จ๏ผˆUvicorn๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ้€‰้กน `--root-path` ไธญ็š„ `root_path`ใ€‚ +่ฟ™่ฏดๆ˜Žไบ†ไปฃ็†๏ผˆTraefik๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ่ทฏๅพ„ๅ‰็ผ€๏ผŒไปฅๅŠๆœๅŠกๅ™จ๏ผˆUvicorn๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ `--root-path` ้€‰้กนๆไพ›็š„ `root_path`ใ€‚ -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹ๆ–‡ๆกฃ็•Œ้ข { #check-the-docs-ui } -ไฝ†่ฟ™ๆ‰ๆ˜ฏๆœ‰่ถฃ็š„ๅœฐๆ–น โœจ +ๆœ‰่ถฃ็š„้ƒจๅˆ†ๆฅไบ†ใ€‚โœจ -่ฎฟ้—ฎๅบ”็”จ็š„**ๅฎ˜ๆ–น**ๆ–นๅผๆ˜ฏ้€š่ฟ‡ๅซ่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†ใ€‚ๅ› ๆญค๏ผŒไธๅ‡บๆ‰€ๆ–™๏ผŒๅฆ‚ๆžœๆฒกๆœ‰ๅœจ URL ไธญๆทปๅŠ ่ทฏๅพ„ๅ‰็ผ€๏ผŒ็›ดๆŽฅ่ฎฟ้—ฎ้€š่ฟ‡ Uvicorn ่ฟ่กŒ็š„ API ๆ–‡ๆกฃ๏ผŒไธ่ƒฝๆญฃๅธธ่ฎฟ้—ฎ๏ผŒๅ› ไธบ้œ€่ฆ้€š่ฟ‡ไปฃ็†ๆ‰่ƒฝ่ฎฟ้—ฎใ€‚ +่ฎฟ้—ฎๅบ”็”จ็š„โ€œๅฎ˜ๆ–นโ€ๆ–นๅผๅบ”่ฏฅๆ˜ฏ้€š่ฟ‡ๆˆ‘ไปฌๅฎšไน‰็š„ๅธฆๆœ‰่ทฏๅพ„ๅ‰็ผ€็š„ไปฃ็†ใ€‚ๅ› ๆญค๏ผŒๆญฃๅฆ‚้ข„ๆœŸ็š„้‚ฃๆ ท๏ผŒๅฆ‚ๆžœไฝ ๅฐ่ฏ•ไธๅธฆ่ทฏๅพ„ๅ‰็ผ€ใ€็›ดๆŽฅ็”ฑ Uvicorn ๆไพ›็š„ๆ–‡ๆกฃ็•Œ้ข๏ผŒๅฎƒๅฐ†ๆ— ๆณ•ๅทฅไฝœ๏ผŒๅ› ไธบๅฎƒๆœŸๆœ›้€š่ฟ‡ไปฃ็†่ฎฟ้—ฎใ€‚ -่พ“ๅ…ฅ http://127.0.0.1:8000/docsย ๆŸฅ็œ‹ API ๆ–‡ๆกฃ๏ผš +ไฝ ๅฏไปฅๅœจ http://127.0.0.1:8000/docs ๆŸฅ็œ‹๏ผš -ไฝ†่พ“ๅ…ฅ**ๅฎ˜ๆ–น**้“พๆŽฅ `/api/v1/docs`๏ผŒๅนถไฝฟ็”จ็ซฏๅฃ `9999` ่ฎฟ้—ฎ API ๆ–‡ๆกฃ๏ผŒๅฐฑ่ƒฝๆญฃๅธธ่ฟ่กŒไบ†๏ผ๐ŸŽ‰ +ไฝ†ๅฆ‚ๆžœๆˆ‘ไปฌๅœจโ€œๅฎ˜ๆ–นโ€URL๏ผˆไปฃ็†็ซฏๅฃไธบ `9999`๏ผ‰็š„ `/api/v1/docs` ่ฎฟ้—ฎๆ–‡ๆกฃ็•Œ้ข๏ผŒๅฎƒๅฐฑ่ƒฝๆญฃๅธธๅทฅไฝœ๏ผ๐ŸŽ‰ -่พ“ๅ…ฅ http://127.0.0.1:9999/api/v1/docsย ๆŸฅ็œ‹ๆ–‡ๆกฃ๏ผš +ไฝ ๅฏไปฅๅœจ http://127.0.0.1:9999/api/v1/docs ๆŸฅ็œ‹๏ผš -ไธ€ๅˆ‡ๆญฃๅธธใ€‚ โœ”๏ธ +ๅฎŒๅ…จ็ฌฆๅˆๆˆ‘ไปฌ็š„้ข„ๆœŸใ€‚โœ”๏ธ -่ฟ™ๆ˜ฏๅ› ไธบ FastAPI ๅœจ OpenAPI ้‡Œไฝฟ็”จ `root_path` ๆไพ›็š„ URL ๅˆ›ๅปบ้ป˜่ฎค `server`ใ€‚ +่ฟ™ๆ˜ฏๅ› ไธบ FastAPI ไฝฟ็”จ่ฏฅ `root_path` ๅœจ OpenAPI ไธญๅˆ›ๅปบ้ป˜่ฎค็š„ `server`๏ผŒๅ…ถ URL ๆฅ่‡ช `root_path`ใ€‚ -## ้™„ๅŠ ็š„ๆœๅŠกๅ™จ +## ้™„ๅŠ ็š„ๆœๅŠกๅ™จ { #additional-servers } /// warning | ่ญฆๅ‘Š -ๆญค็”จไพ‹่พƒ้šพ๏ผŒๅฏไปฅ่ทณ่ฟ‡ใ€‚ +่ฟ™ๆ˜ฏไธ€ไธชๆ›ด้ซ˜็บง็š„็”จไพ‹๏ผŒๅฏไปฅ่ทณ่ฟ‡ใ€‚ /// -้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ไฝฟ็”จ `root_path` ็š„้“พๆŽฅๅœจ OpenAPI ๆฆ‚ๅ›พไธญๅˆ›ๅปบ `server`ใ€‚ +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ไผšๅœจ OpenAPI ๆจกๅผไธญไฝฟ็”จ `root_path` ็š„ URL ๅˆ›ๅปบไธ€ไธช `server`ใ€‚ -ไฝ†ไนŸๅฏไปฅไฝฟ็”จๅ…ถๅฎƒๅค‡้€‰ `servers`๏ผŒไพ‹ๅฆ‚๏ผŒ้œ€่ฆๅŒไธ€ไธช API ๆ–‡ๆกฃไธŽ staging ๅ’Œ็”Ÿไบง็Žฏๅขƒไบคไบ’ใ€‚ +ไฝ†ไฝ ไนŸๅฏไปฅๆไพ›ๅ…ถไป–ๅค‡้€‰็š„ `servers`๏ผŒไพ‹ๅฆ‚ไฝ ๅธŒๆœ›่ฎฉโ€œๅŒไธ€ไธชโ€ๆ–‡ๆกฃ็•Œ้ขๅŒๆ—ถไธŽ้ข„ๅ‘ๅธƒ็Žฏๅขƒๅ’Œ็”Ÿไบง็Žฏๅขƒไบคไบ’ใ€‚ -ๅฆ‚ๆžœไผ ้€’่‡ชๅฎšไน‰ `servers` ๅˆ—่กจ๏ผŒๅนถๆœ‰ `root_path`๏ผˆ ๅ› ไธบ API ไฝฟ็”จไบ†ไปฃ็†๏ผ‰๏ผŒ**FastAPI** ไผšๅœจๅˆ—่กจๅผ€ๅคดไฝฟ็”จ่ฟ™ไธช `root_path` ๆ’ๅ…ฅ**ๆœๅŠกๅ™จ**ใ€‚ +ๅฆ‚ๆžœไฝ ไผ ๅ…ฅไบ†่‡ชๅฎšไน‰็š„ `servers` ๅˆ—่กจ๏ผŒๅนถไธ”ๅญ˜ๅœจ `root_path`๏ผˆๅ› ไธบไฝ ็š„ API ไฝไบŽไปฃ็†ๅŽ้ข๏ผ‰๏ผŒ**FastAPI** ไผšๅœจๅˆ—่กจๅผ€ๅคดๆ’ๅ…ฅไธ€ไธชไฝฟ็”จ่ฏฅ `root_path` ็š„โ€œserverโ€ใ€‚ ไพ‹ๅฆ‚๏ผš -{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} -่ฟ™ๆฎตไปฃ็ ็”Ÿไบงๅฆ‚ไธ‹ OpenAPI ๆฆ‚ๅ›พ๏ผš +ไผš็”Ÿๆˆๅฆ‚ไธ‹็š„ OpenAPI ๆจกๅผ๏ผš ```JSON hl_lines="5-7" { - "openapi": "3.0.2", + "openapi": "3.1.0", // More stuff here "servers": [ { @@ -328,30 +429,38 @@ $ uvicorn main:app --root-path /api/v1 /// tip | ๆ็คบ -ๆณจๆ„๏ผŒ่‡ชๅŠจ็”ŸๆˆๆœๅŠกๅ™จๆ—ถ๏ผŒ`url` ็š„ๅ€ผ `/api/v1` ๆๅ–่‡ช `roog_path`ใ€‚ +ๆณจๆ„่ฟ™ไธช่‡ชๅŠจ็”Ÿๆˆ็š„ๆœๅŠกๅ™จ๏ผŒ`url` ็š„ๅ€ผไธบ `/api/v1`๏ผŒๅ–่‡ช `root_path`ใ€‚ /// -http://127.0.0.1:9999/api/v1/docsย ็š„ API ๆ–‡ๆกฃๆ‰€็คบๅฆ‚ไธ‹๏ผš +ๅœจ http://127.0.0.1:9999/api/v1/docs ็š„ๆ–‡ๆกฃ็•Œ้ขไธญ๏ผŒๅฎƒ็œ‹่ตทๆฅๆ˜ฏ่ฟ™ๆ ท็š„๏ผš /// tip | ๆ็คบ -API ๆ–‡ๆกฃไธŽๆ‰€้€‰็š„ๆœๅŠกๅ™จ่ฟ›่กŒไบคไบ’ใ€‚ +ๆ–‡ๆกฃ็•Œ้ขไผšไธŽไฝ ๆ‰€้€‰ๆ‹ฉ็š„ๆœๅŠกๅ™จไบคไบ’ใ€‚ + +/// + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +OpenAPI ่ง„่Œƒไธญ็š„ `servers` ๅฑžๆ€งๆ˜ฏๅฏ้€‰็š„ใ€‚ + +ๅฆ‚ๆžœไฝ ๆฒกๆœ‰ๆŒ‡ๅฎš `servers` ๅ‚ๆ•ฐ๏ผŒๅนถไธ” `root_path` ็ญ‰ไบŽ `/`๏ผŒๅˆ™้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ็”Ÿๆˆ็š„ OpenAPI ๆจกๅผไธญไผšๅฎŒๅ…จ็œ็•ฅ `servers` ๅฑžๆ€ง๏ผŒ่ฟ™็ญ‰ไปทไบŽๅชๆœ‰ไธ€ไธช `url` ๅ€ผไธบ `/` ็š„ๆœๅŠกๅ™จใ€‚ /// -### ไปŽ `root_path` ็ฆ็”จ่‡ชๅŠจๆœๅŠกๅ™จ +### ไปŽ `root_path` ็ฆ็”จ่‡ชๅŠจๆœๅŠกๅ™จ { #disable-automatic-server-from-root-path } -ๅฆ‚ๆžœไธๆƒณ่ฎฉ **FastAPI** ๅŒ…ๅซไฝฟ็”จ `root_path` ็š„่‡ชๅŠจๆœๅŠกๅ™จ๏ผŒๅˆ™่ฆไฝฟ็”จๅ‚ๆ•ฐ `root_path_in_servers=False`๏ผš +ๅฆ‚ๆžœไฝ ไธๅธŒๆœ› **FastAPI** ๅŒ…ๅซไธ€ไธชไฝฟ็”จ `root_path` ็š„่‡ชๅŠจๆœๅŠกๅ™จ๏ผŒๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `root_path_in_servers=False`๏ผš -{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} -่ฟ™ๆ ท๏ผŒๅฐฑไธไผšๅœจ OpenAPI ๆฆ‚ๅ›พไธญๅŒ…ๅซๆœๅŠกๅ™จไบ†ใ€‚ +่ฟ™ๆ ทๅฎƒๅฐฑไธไผš่ขซๅŒ…ๅซๅˆฐ OpenAPI ๆจกๅผไธญใ€‚ -## ๆŒ‚่ฝฝๅญๅบ”็”จ +## ๆŒ‚่ฝฝๅญๅบ”็”จ { #mounting-a-sub-application } -ๅฆ‚้œ€ๆŒ‚่ฝฝๅญๅบ”็”จ๏ผˆ่ฏฆ่ง [ๅญๅบ”็”จ - ๆŒ‚่ฝฝ](sub-applications.md){.internal-link target=_blank}๏ผ‰๏ผŒไนŸ่ฆ้€š่ฟ‡ `root_path` ไฝฟ็”จไปฃ็†๏ผŒ่ฟ™ไธŽๆญฃๅธธๅบ”็”จไธ€ๆ ท๏ผŒๅˆซๆ— ไบŒ่‡ดใ€‚ +ๅฆ‚ๆžœไฝ ้œ€่ฆๅœจไฝฟ็”จๅธฆๆœ‰ `root_path` ็š„ไปฃ็†ๆ—ถๆŒ‚่ฝฝไธ€ไธชๅญๅบ”็”จ๏ผˆๅ‚่ง [ๅญๅบ”็”จ - ๆŒ‚่ฝฝ](sub-applications.md){.internal-link target=_blank}๏ผ‰๏ผŒไฝ ๅฏไปฅๅƒ้ข„ๆœŸ็š„้‚ฃๆ ทๆญฃๅธธๆ“ไฝœใ€‚ -FastAPI ๅœจๅ†…้ƒจไฝฟ็”จ `root_path`๏ผŒๅ› ๆญคๅญๅบ”็”จไนŸๅฏไปฅๆญฃๅธธ่ฟ่กŒใ€‚โœจ +FastAPI ไผšๅœจๅ†…้ƒจๆ™บ่ƒฝๅœฐไฝฟ็”จ `root_path`๏ผŒๅ› ๆญคๅฎƒๅฏไปฅ็›ดๆŽฅๆญฃๅธธๅทฅไฝœใ€‚โœจ diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md index 22a9b4b510..f5bec5fdcf 100644 --- a/docs/zh/docs/advanced/custom-response.md +++ b/docs/zh/docs/advanced/custom-response.md @@ -1,32 +1,38 @@ -# ่‡ชๅฎšไน‰ๅ“ๅบ” - HTML๏ผŒๆต๏ผŒๆ–‡ไปถๅ’Œๅ…ถไป– +# ่‡ชๅฎšไน‰ๅ“ๅบ” - HTMLใ€ๆตใ€ๆ–‡ไปถ็ญ‰ { #custom-response-html-stream-file-others } **FastAPI** ้ป˜่ฎคไผšไฝฟ็”จ `JSONResponse` ่ฟ”ๅ›žๅ“ๅบ”ใ€‚ ไฝ ๅฏไปฅ้€š่ฟ‡็›ดๆŽฅ่ฟ”ๅ›ž `Response` ๆฅ้‡่ฝฝๅฎƒ๏ผŒๅ‚่ง [็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”](response-directly.md){.internal-link target=_blank}ใ€‚ -ไฝ†ๅฆ‚ๆžœไฝ ็›ดๆŽฅ่ฟ”ๅ›ž `Response`๏ผŒ่ฟ”ๅ›žๆ•ฐๆฎไธไผš่‡ชๅŠจ่ฝฌๆข๏ผŒไนŸไธไผš่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ๏ผˆไพ‹ๅฆ‚๏ผŒๅœจ HTTP ๅคด `Content-Type` ไธญๅŒ…ๅซ็‰นๅฎš็š„ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€ไฝœไธบ็”Ÿๆˆ็š„ OpenAPI ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ +ไฝ†ๅฆ‚ๆžœไฝ ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `Response`๏ผˆๆˆ–ๅ…ถไปปๆ„ๅญ็ฑป๏ผŒๆฏ”ๅฆ‚ `JSONResponse`๏ผ‰๏ผŒ่ฟ”ๅ›žๆ•ฐๆฎไธไผš่‡ชๅŠจ่ฝฌๆข๏ผˆๅณไฝฟไฝ ๅฃฐๆ˜Žไบ† `response_model`๏ผ‰๏ผŒไนŸไธไผš่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ๏ผˆไพ‹ๅฆ‚๏ผŒๅœจ็”Ÿๆˆ็š„ OpenAPI ไธญ๏ผŒHTTP ๅคด `Content-Type` ้‡Œ็š„็‰นๅฎšใ€Œๅช’ไฝ“็ฑปๅž‹ใ€ไธไผš่ขซๅŒ…ๅซ๏ผ‰ใ€‚ -ไฝ ่ฟ˜ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* ไธญๅฃฐๆ˜Žไฝ ๆƒณ็”จ็š„ `Response`ใ€‚ +ไฝ ่ฟ˜ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* ไธญ้€š่ฟ‡ `response_class` ๅ‚ๆ•ฐๅฃฐๆ˜Ž่ฆไฝฟ็”จ็š„ `Response`๏ผˆไพ‹ๅฆ‚ไปปๆ„ `Response` ๅญ็ฑป๏ผ‰ใ€‚ ไฝ ไปŽ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญ่ฟ”ๅ›ž็š„ๅ†…ๅฎนๅฐ†่ขซๆ”พๅœจ่ฏฅ `Response` ไธญใ€‚ -ๅนถไธ”ๅฆ‚ๆžœ่ฏฅ `Response` ๆœ‰ไธ€ไธช JSON ๅช’ไฝ“็ฑปๅž‹๏ผˆ`application/json`๏ผ‰๏ผŒๆฏ”ๅฆ‚ไฝฟ็”จ `JSONResponse` ๆˆ–่€… `UJSONResponse` ็š„ๆ—ถๅ€™๏ผŒ่ฟ”ๅ›ž็š„ๆ•ฐๆฎๅฐ†ไฝฟ็”จไฝ ๅœจ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไธญๅฃฐๆ˜Ž็š„ไปปไฝ• Pydantic ็š„ `response_model` ่‡ชๅŠจ่ฝฌๆข๏ผˆๅ’Œ่ฟ‡ๆปค๏ผ‰ใ€‚ +ๅนถไธ”ๅฆ‚ๆžœ่ฏฅ `Response` ๆœ‰ไธ€ไธช JSON ๅช’ไฝ“็ฑปๅž‹๏ผˆ`application/json`๏ผ‰๏ผŒๆฏ”ๅฆ‚ไฝฟ็”จ `JSONResponse` ๆˆ– `UJSONResponse` ็š„ๆ—ถๅ€™๏ผŒ่ฟ”ๅ›ž็š„ๆ•ฐๆฎๅฐ†ไฝฟ็”จไฝ ๅœจ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไธญๅฃฐๆ˜Ž็š„ไปปไฝ• Pydantic ็š„ `response_model` ่‡ชๅŠจ่ฝฌๆข๏ผˆๅ’Œ่ฟ‡ๆปค๏ผ‰ใ€‚ -/// note | ่ฏดๆ˜Ž +/// note | ๆณจๆ„ -ๅฆ‚ๆžœไฝ ไฝฟ็”จไธๅธฆๆœ‰ไปปไฝ•ๅช’ไฝ“็ฑปๅž‹็š„ๅ“ๅบ”็ฑป๏ผŒFastAPI ่ฎคไธบไฝ ็š„ๅ“ๅบ”ๆฒกๆœ‰ไปปไฝ•ๅ†…ๅฎน๏ผŒๆ‰€ไปฅไธไผšๅœจ็”Ÿๆˆ็š„OpenAPIๆ–‡ๆกฃไธญ่ฎฐๅฝ•ๅ“ๅบ”ๆ ผๅผใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จไธๅธฆๆœ‰ไปปไฝ•ๅช’ไฝ“็ฑปๅž‹็š„ๅ“ๅบ”็ฑป๏ผŒFastAPI ไผš่ฎคไธบไฝ ็š„ๅ“ๅบ”ๆฒกๆœ‰ไปปไฝ•ๅ†…ๅฎน๏ผŒๆ‰€ไปฅไธไผšๅœจ็”Ÿๆˆ็š„ OpenAPI ๆ–‡ๆกฃไธญ่ฎฐๅฝ•ๅ“ๅบ”ๆ ผๅผใ€‚ /// -## ไฝฟ็”จ `ORJSONResponse` +## ไฝฟ็”จ `ORJSONResponse` { #use-orjsonresponse } ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ้œ€่ฆๅŽ‹ๆฆจๆ€ง่ƒฝ๏ผŒไฝ ๅฏไปฅๅฎ‰่ฃ…ๅนถไฝฟ็”จ `orjson` ๅนถๅฐ†ๅ“ๅบ”่ฎพ็ฝฎไธบ `ORJSONResponse`ใ€‚ ๅฏผๅ…ฅไฝ ๆƒณ่ฆไฝฟ็”จ็š„ `Response` ็ฑป๏ผˆๅญ็ฑป๏ผ‰็„ถๅŽๅœจ *่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* ไธญๅฃฐๆ˜Žๅฎƒใ€‚ -{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *} +ๅฏนไบŽ่พƒๅคง็š„ๅ“ๅบ”๏ผŒ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `Response` ไผšๆฏ”่ฟ”ๅ›žไธ€ไธชๅญ—ๅ…ธๅฟซๅพ—ๅคšใ€‚ -/// info | ๆ็คบ +่ฟ™ๆ˜ฏๅ› ไธบ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒFastAPI ไผšๆฃ€ๆŸฅๅ…ถไธญ็š„ๆฏไธ€้กนๅนถ็กฎไฟๅฎƒๅฏไปฅ่ขซๅบๅˆ—ๅŒ–ไธบ JSON๏ผŒไฝฟ็”จๆ•™็จ‹ไธญ่งฃ้‡Š็š„็›ธๅŒ [JSON ๅ…ผๅฎน็ผ–็ ๅ™จ](../tutorial/encoder.md){.internal-link target=_blank}ใ€‚่ฟ™ๆญฃๆ˜ฏๅฎƒๅ…่ฎธไฝ ่ฟ”ๅ›žใ€Œไปปๆ„ๅฏน่ฑกใ€็š„ๅŽŸๅ› ๏ผŒไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“ๆจกๅž‹ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็กฎๅฎšไฝ ่ฟ”ๅ›ž็š„ๅ†…ๅฎนๆ˜ฏใ€Œๅฏไปฅ็”จ JSON ๅบๅˆ—ๅŒ–ใ€็š„๏ผŒไฝ ๅฏไปฅๅฐ†ๅฎƒ็›ดๆŽฅไผ ็ป™ๅ“ๅบ”็ฑป๏ผŒไปŽ่€Œ้ฟๅ…ๅœจไผ ็ป™ๅ“ๅบ”็ฑปไน‹ๅ‰ๅ…ˆ้€š่ฟ‡ `jsonable_encoder` ๅธฆๆฅ็š„้ขๅค–ๅผ€้”€ใ€‚ + +{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} + +/// info | ไฟกๆฏ ๅ‚ๆ•ฐ `response_class` ไนŸไผš็”จๆฅๅฎšไน‰ๅ“ๅบ”็š„ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€ใ€‚ @@ -36,22 +42,22 @@ /// -/// tip | ๅฐ่ดดๅฃซ +/// tip | ๆ็คบ `ORJSONResponse` ็›ฎๅ‰ๅชๅœจ FastAPI ไธญๅฏ็”จ๏ผŒ่€Œๅœจ Starlette ไธญไธๅฏ็”จใ€‚ /// -## HTML ๅ“ๅบ” +## HTML ๅ“ๅบ” { #html-response } ไฝฟ็”จ `HTMLResponse` ๆฅไปŽ **FastAPI** ไธญ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช HTML ๅ“ๅบ”ใ€‚ * ๅฏผๅ…ฅ `HTMLResponse`ใ€‚ * ๅฐ† `HTMLResponse` ไฝœไธบไฝ ็š„ *่ทฏๅพ„ๆ“ไฝœ* ็š„ `response_class` ๅ‚ๆ•ฐไผ ๅ…ฅใ€‚ -{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} -/// info | ๆ็คบ +/// info | ไฟกๆฏ ๅ‚ๆ•ฐ `response_class` ไนŸไผš็”จๆฅๅฎšไน‰ๅ“ๅบ”็š„ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€ใ€‚ @@ -61,13 +67,13 @@ /// -### ่ฟ”ๅ›žไธ€ไธช `Response` +### ่ฟ”ๅ›žไธ€ไธช `Response` { #return-a-response } ๆญฃๅฆ‚ไฝ ๅœจ [็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”](response-directly.md){.internal-link target=_blank} ไธญไบ†่งฃๅˆฐ็š„๏ผŒไฝ ไนŸๅฏไปฅ้€š่ฟ‡็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”ๅœจ *่ทฏๅพ„ๆ“ไฝœ* ไธญ็›ดๆŽฅ้‡่ฝฝๅ“ๅบ”ใ€‚ ๅ’ŒไธŠ้ขไธ€ๆ ท็š„ไพ‹ๅญ๏ผŒ่ฟ”ๅ›žไธ€ไธช `HTMLResponse` ็œ‹่ตทๆฅๅฏ่ƒฝๆ˜ฏ่ฟ™ๆ ท๏ผš -{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} /// warning | ่ญฆๅ‘Š @@ -75,33 +81,33 @@ /// -/// info | ๆ็คบ +/// info | ไฟกๆฏ -ๅฝ“็„ถ๏ผŒๅฎž้™…็š„ `Content-Type` ๅคด๏ผŒ็Šถๆ€็ ็ญ‰็ญ‰๏ผŒๅฐ†ๆฅ่‡ชไบŽไฝ ่ฟ”ๅ›ž็š„ `Response` ๅฏน่ฑกใ€‚ +ๅฝ“็„ถ๏ผŒๅฎž้™…็š„ `Content-Type` ๅคดใ€็Šถๆ€็ ็ญ‰็ญ‰๏ผŒๅฐ†ๆฅ่‡ชไบŽไฝ ่ฟ”ๅ›ž็š„ `Response` ๅฏน่ฑกใ€‚ /// -### OpenAPI ไธญ็š„ๆ–‡ๆกฃๅ’Œ้‡่ฝฝ `Response` +### ๅœจ OpenAPI ไธญๆ–‡ๆกฃๅŒ–ๅนถ้‡่ฝฝ `Response` { #document-in-openapi-and-override-response } ๅฆ‚ๆžœไฝ ๆƒณ่ฆๅœจๅ‡ฝๆ•ฐๅ†…้‡่ฝฝๅ“ๅบ”๏ผŒไฝ†ๆ˜ฏๅŒๆ—ถๅœจ OpenAPI ไธญๆ–‡ๆกฃๅŒ–ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `response_class` ๅ‚ๆ•ฐๅนถ่ฟ”ๅ›žไธ€ไธช `Response` ๅฏน่ฑกใ€‚ ๆŽฅ็€ `response_class` ๅ‚ๆ•ฐๅชไผš่ขซ็”จๆฅๆ–‡ๆกฃๅŒ– OpenAPI ็š„ *่ทฏๅพ„ๆ“ไฝœ*๏ผŒไฝ ็š„ `Response` ็”จๆฅ่ฟ”ๅ›žๅ“ๅบ”ใ€‚ -### ็›ดๆŽฅ่ฟ”ๅ›ž `HTMLResponse` +#### ็›ดๆŽฅ่ฟ”ๅ›ž `HTMLResponse` { #return-an-htmlresponse-directly } ๆฏ”ๅฆ‚ๅƒ่ฟ™ๆ ท๏ผš -{* ../../docs_src/custom_response/tutorial004.py hl[7,23,21] *} +{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒๅ‡ฝๆ•ฐ `generate_html_response()` ๅทฒ็ป็”Ÿๆˆๅนถ่ฟ”ๅ›ž `Response` ๅฏน่ฑก่€Œไธๆ˜ฏๅœจ `str` ไธญ่ฟ”ๅ›ž HTMLใ€‚ -้€š่ฟ‡่ฟ”ๅ›žๅ‡ฝๆ•ฐ `generate_html_response()` ็š„่ฐƒ็”จ็ป“ๆžœ๏ผŒไฝ ๅทฒ็ป่ฟ”ๅ›žไธ€ไธช้‡่ฝฝ **FastAPI** ้ป˜่ฎค่กŒไธบ็š„ `Response` ๅฏน่ฑก๏ผŒ +้€š่ฟ‡่ฟ”ๅ›žๅ‡ฝๆ•ฐ `generate_html_response()` ็š„่ฐƒ็”จ็ป“ๆžœ๏ผŒไฝ ๅทฒ็ป่ฟ”ๅ›žไธ€ไธช้‡่ฝฝ **FastAPI** ้ป˜่ฎค่กŒไธบ็š„ `Response` ๅฏน่ฑกใ€‚ -ไฝ†ๅฆ‚ๆžœไฝ ๅœจ `response_class` ไธญไนŸไผ ๅ…ฅไบ† `HTMLResponse`๏ผŒ**FastAPI** ไผš็Ÿฅ้“ๅฆ‚ไฝ•ๅœจ OpenAPI ๅ’Œไบคไบ’ๅผๆ–‡ๆกฃไธญไฝฟ็”จ `text/html` ๅฐ†ๅ…ถๆ–‡ๆกฃๅŒ–ไธบ HTMLใ€‚ +ไฝ†ๅฆ‚ๆžœไฝ ๅœจ `response_class` ไธญไนŸไผ ๅ…ฅไบ† `HTMLResponse`๏ผŒ**FastAPI** ไผš็Ÿฅ้“ๅฆ‚ไฝ•ๅœจ OpenAPI ๅ’Œไบคไบ’ๅผๆ–‡ๆกฃไธญไฝฟ็”จ `text/html` ๅฐ†ๅ…ถๆ–‡ๆกฃๅŒ–ไธบ HTML๏ผš -## ๅฏ็”จๅ“ๅบ” +## ๅฏ็”จๅ“ๅบ” { #available-responses } ่ฟ™้‡Œๆœ‰ไธ€ไบ›ๅฏ็”จ็š„ๅ“ๅบ”ใ€‚ @@ -115,7 +121,7 @@ /// -### `Response` +### `Response` { #response } ๅ…ถไป–ๅ…จ้ƒจ็š„ๅ“ๅบ”้ƒฝ็ปงๆ‰ฟ่‡ชไธป็ฑป `Response`ใ€‚ @@ -128,77 +134,115 @@ * `headers` - ไธ€ไธช็”ฑๅญ—็ฌฆไธฒ็ป„ๆˆ็š„ `dict`ใ€‚ * `media_type` - ไธ€ไธช็ป™ๅ‡บๅช’ไฝ“็ฑปๅž‹็š„ `str`๏ผŒๆฏ”ๅฆ‚ `"text/html"`ใ€‚ -FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ่ฟ˜ๅฐ†ๅŒ…ๅซไธ€ไธชๅŸบไบŽ media_type ็š„ Content-Type ๅคด๏ผŒๅนถไธบๆ–‡ๆœฌ็ฑปๅž‹้™„ๅŠ ไธ€ไธชๅญ—็ฌฆ้›†ใ€‚ +FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ่ฟ˜ๅฐ†ๅŒ…ๅซไธ€ไธชๅŸบไบŽ `media_type` ็š„ Content-Type ๅคด๏ผŒๅนถไธบๆ–‡ๆœฌ็ฑปๅž‹้™„ๅŠ ไธ€ไธชๅญ—็ฌฆ้›†ใ€‚ +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} -{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} - -### `HTMLResponse` +### `HTMLResponse` { #htmlresponse } ๅฆ‚ไธŠๆ–‡ๆ‰€่ฟฐ๏ผŒๆŽฅๅ—ๆ–‡ๆœฌๆˆ–ๅญ—่Š‚ๅนถ่ฟ”ๅ›ž HTML ๅ“ๅบ”ใ€‚ -### `PlainTextResponse` +### `PlainTextResponse` { #plaintextresponse } ๆŽฅๅ—ๆ–‡ๆœฌๆˆ–ๅญ—่Š‚ๅนถ่ฟ”ๅ›ž็บฏๆ–‡ๆœฌๅ“ๅบ”ใ€‚ -{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} -### `JSONResponse` +### `JSONResponse` { #jsonresponse } ๆŽฅๅ—ๆ•ฐๆฎๅนถ่ฟ”ๅ›žไธ€ไธช `application/json` ็ผ–็ ็š„ๅ“ๅบ”ใ€‚ ๅฆ‚ไธŠๆ–‡ๆ‰€่ฟฐ๏ผŒ่ฟ™ๆ˜ฏ **FastAPI** ไธญไฝฟ็”จ็š„้ป˜่ฎคๅ“ๅบ”ใ€‚ -### `ORJSONResponse` +### `ORJSONResponse` { #orjsonresponse } ๅฆ‚ไธŠๆ–‡ๆ‰€่ฟฐ๏ผŒ`ORJSONResponse` ๆ˜ฏไธ€ไธชไฝฟ็”จ `orjson` ็š„ๅฟซ้€Ÿ็š„ๅฏ้€‰ JSON ๅ“ๅบ”ใ€‚ +/// info | ไฟกๆฏ + +่ฟ™้œ€่ฆๅ…ˆๅฎ‰่ฃ… `orjson`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install orjson`ใ€‚ + +/// -### `UJSONResponse` +### `UJSONResponse` { #ujsonresponse } `UJSONResponse` ๆ˜ฏไธ€ไธชไฝฟ็”จ `ujson` ็š„ๅฏ้€‰ JSON ๅ“ๅบ”ใ€‚ +/// info | ไฟกๆฏ + +่ฟ™้œ€่ฆๅ…ˆๅฎ‰่ฃ… `ujson`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install ujson`ใ€‚ + +/// + /// warning | ่ญฆๅ‘Š ๅœจๅค„็†ๆŸไบ›่พน็ผ˜ๆƒ…ๅ†ตๆ—ถ๏ผŒ`ujson` ไธๅฆ‚ Python ็š„ๅ†…็ฝฎๅฎž็Žฐ้‚ฃไนˆ่ฐจๆ…Žใ€‚ /// -{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} -/// tip | ๅฐ่ดดๅฃซ +/// tip | ๆ็คบ `ORJSONResponse` ๅฏ่ƒฝๆ˜ฏไธ€ไธชๆ›ดๅฟซ็š„้€‰ๆ‹ฉใ€‚ /// -### `RedirectResponse` +### `RedirectResponse` { #redirectresponse } + +่ฟ”ๅ›ž HTTP ้‡ๅฎšๅ‘ใ€‚้ป˜่ฎคๆƒ…ๅ†ตไธ‹ไฝฟ็”จ 307 ็Šถๆ€็ ๏ผˆไธดๆ—ถ้‡ๅฎšๅ‘๏ผ‰ใ€‚ -่ฟ”ๅ›ž HTTP ้‡ๅฎšๅ‘ใ€‚้ป˜่ฎคๆƒ…ๅ†ตไธ‹ไฝฟ็”จ 307 ็Šถๆ€ไปฃ็ ๏ผˆไธดๆ—ถ้‡ๅฎšๅ‘๏ผ‰ใ€‚ +ไฝ ๅฏไปฅ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `RedirectResponse`๏ผš -{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} -### `StreamingResponse` +--- + +ๆˆ–่€…ไฝ ๅฏไปฅๆŠŠๅฎƒ็”จไบŽ `response_class` ๅ‚ๆ•ฐ๏ผš + +{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} + +ๅฆ‚ๆžœไฝ ่ฟ™ไนˆๅš๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ* ๅ‡ฝๆ•ฐไธญ็›ดๆŽฅ่ฟ”ๅ›ž URLใ€‚ + +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฐ†ไฝฟ็”จ `RedirectResponse` ็š„้ป˜่ฎค `status_code`๏ผŒๅณ `307`ใ€‚ + +--- + +ไฝ ไนŸๅฏไปฅๅฐ† `status_code` ๅ‚ๆ•ฐๅ’Œ `response_class` ๅ‚ๆ•ฐ็ป“ๅˆไฝฟ็”จ๏ผš + +{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } ้‡‡็”จๅผ‚ๆญฅ็”Ÿๆˆๅ™จๆˆ–ๆ™ฎ้€š็”Ÿๆˆๅ™จ/่ฟญไปฃๅ™จ๏ผŒ็„ถๅŽๆตๅผไผ ่พ“ๅ“ๅบ”ไธปไฝ“ใ€‚ -{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} + +#### ๅฏน็ฑปไผผๆ–‡ไปถ็š„ๅฏน่ฑกไฝฟ็”จ `StreamingResponse` { #using-streamingresponse-with-file-like-objects } + +ๅฆ‚ๆžœๆ‚จๆœ‰ไธ€ไธช็ฑปๆ–‡ไปถๅฏน่ฑก๏ผˆไพ‹ๅฆ‚็”ฑ `open()` ่ฟ”ๅ›ž็š„ๅฏน่ฑก๏ผ‰๏ผŒไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐๆฅ่ฟญไปฃ่ฏฅ็ฑปๆ–‡ไปถๅฏน่ฑกใ€‚ + +่ฟ™ๆ ท๏ผŒไฝ ๅฐฑไธๅฟ…ๅ…ˆๆŠŠๅฎƒๅ…จ้ƒจ่ฏปๅ…ฅๅ†…ๅญ˜๏ผŒๅฏไปฅๅฐ†่ฏฅ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐไผ ็ป™ `StreamingResponse` ๅนถ่ฟ”ๅ›žๅฎƒใ€‚ + +่ฟ™ไนŸๅŒ…ๆ‹ฌ่ฎธๅคšไธŽไบ‘ๅญ˜ๅ‚จใ€่ง†้ข‘ๅค„็†็ญ‰ไบคไบ’็š„ๅบ“ใ€‚ -#### ๅฏน็ฑปไผผๆ–‡ไปถ็š„ๅฏน่ฑกไฝฟ็”จ `StreamingResponse` +{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} -ๅฆ‚ๆžœๆ‚จๆœ‰็ฑปไผผๆ–‡ไปถ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚๏ผŒ็”ฑ `open()` ่ฟ”ๅ›ž็š„ๅฏน่ฑก๏ผ‰๏ผŒๅˆ™ๅฏไปฅๅœจ `StreamingResponse` ไธญๅฐ†ๅ…ถ่ฟ”ๅ›žใ€‚ +1. ่ฟ™ๆ˜ฏ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐใ€‚ไน‹ๆ‰€ไปฅๆ˜ฏใ€Œ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐใ€๏ผŒๆ˜ฏๅ› ไธบๅฎƒๅ†…้ƒจๅŒ…ๅซ `yield` ่ฏญๅฅใ€‚ +2. ้€š่ฟ‡ไฝฟ็”จ `with` ไปฃ็ ๅ—๏ผŒๆˆ‘ไปฌๅฏไปฅ็กฎไฟๅœจ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐๅฎŒๆˆๅŽๅ…ณ้—ญ็ฑปๆ–‡ไปถๅฏน่ฑกใ€‚ๅ› ๆญค๏ผŒๅœจๅฎƒๅฎŒๆˆๅ‘้€ๅ“ๅบ”ไน‹ๅŽไผš่ขซๅ…ณ้—ญใ€‚ +3. ่ฟ™ไธช `yield from` ๅ‘Š่ฏ‰ๅ‡ฝๆ•ฐๅŽป่ฟญไปฃๅไธบ `file_like` ็š„้‚ฃไธชๅฏน่ฑกใ€‚็„ถๅŽ๏ผŒๅฏนไบŽๆฏไธช่ขซ่ฟญไปฃๅ‡บๆฅ็š„้ƒจๅˆ†๏ผŒ้ƒฝๆŠŠ่ฏฅ้ƒจๅˆ†ไฝœไธบๆฅ่‡ช่ฟ™ไธช็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐ๏ผˆ`iterfile`๏ผ‰็š„ๅ€ผๅ† `yield` ๅ‡บๅŽปใ€‚ -ๅŒ…ๆ‹ฌ่ฎธๅคšไธŽไบ‘ๅญ˜ๅ‚จ๏ผŒ่ง†้ข‘ๅค„็†็ญ‰ไบคไบ’็š„ๅบ“ใ€‚ + ๅ› ๆญค๏ผŒๅฎƒๆ˜ฏไธ€ไธชๆŠŠใ€Œ็”Ÿๆˆใ€ๅทฅไฝœๅ†…้ƒจ่ฝฌไบค็ป™ๅ…ถไป–ไธœ่ฅฟ็š„็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐใ€‚ -{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *} + ้€š่ฟ‡่ฟ™็งๆ–นๅผ๏ผŒๆˆ‘ไปฌๅฏไปฅๆŠŠๅฎƒๆ”พๅœจ `with` ไปฃ็ ๅ—ไธญ๏ผŒไปŽ่€Œ็กฎไฟ็ฑปๆ–‡ไปถๅฏน่ฑกๅœจ็ป“ๆŸๅŽ่ขซๅ…ณ้—ญใ€‚ -/// tip | ๅฐ่ดดๅฃซ +/// tip | ๆ็คบ ๆณจๆ„ๅœจ่ฟ™้‡Œ๏ผŒๅ› ไธบๆˆ‘ไปฌไฝฟ็”จ็š„ๆ˜ฏไธๆ”ฏๆŒ `async` ๅ’Œ `await` ็š„ๆ ‡ๅ‡† `open()`๏ผŒๆˆ‘ไปฌไฝฟ็”จๆ™ฎ้€š็š„ `def` ๅฃฐๆ˜Žไบ†่ทฏๅพ„ๆ“ไฝœใ€‚ /// -### `FileResponse` +### `FileResponse` { #fileresponse } ๅผ‚ๆญฅไผ ่พ“ๆ–‡ไปถไฝœไธบๅ“ๅบ”ใ€‚ @@ -209,10 +253,60 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ * `media_type` - ็ป™ๅ‡บๅช’ไฝ“็ฑปๅž‹็š„ๅญ—็ฌฆไธฒใ€‚ๅฆ‚ๆžœๆœช่ฎพ็ฝฎ๏ผŒๅˆ™ๆ–‡ไปถๅๆˆ–่ทฏๅพ„ๅฐ†็”จไบŽๆŽจๆ–ญๅช’ไฝ“็ฑปๅž‹ใ€‚ * `filename` - ๅฆ‚ๆžœ็ป™ๅ‡บ๏ผŒๅฎƒๅฐ†ๅŒ…ๅซๅœจๅ“ๅบ”็š„ `Content-Disposition` ไธญใ€‚ -ๆ–‡ไปถๅ“ๅบ”ๅฐ†ๅŒ…ๅซ้€‚ๅฝ“็š„ `Content-Length`๏ผŒ`Last-Modified` ๅ’Œ `ETag` ็š„ๅ“ๅบ”ๅคดใ€‚ +ๆ–‡ไปถๅ“ๅบ”ๅฐ†ๅŒ…ๅซ้€‚ๅฝ“็š„ `Content-Length`ใ€`Last-Modified` ๅ’Œ `ETag` ๅ“ๅบ”ๅคดใ€‚ -{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `response_class` ๅ‚ๆ•ฐ๏ผš + +{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} + +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ* ๅ‡ฝๆ•ฐไธญ็›ดๆŽฅ่ฟ”ๅ›žๆ–‡ไปถ่ทฏๅพ„ใ€‚ + +## ่‡ชๅฎšไน‰ๅ“ๅบ”็ฑป { #custom-response-class } + +ไฝ ๅฏไปฅๅˆ›ๅปบไฝ ่‡ชๅทฑ็š„่‡ชๅฎšไน‰ๅ“ๅบ”็ฑป๏ผŒ็ปงๆ‰ฟ่‡ช `Response` ๅนถไฝฟ็”จๅฎƒใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๆƒณไฝฟ็”จ `orjson`๏ผŒไฝ†่ฆไฝฟ็”จๅ†…็ฝฎ `ORJSONResponse` ็ฑปๆฒกๆœ‰ๅฏ็”จ็š„ไธ€ไบ›่‡ชๅฎšไน‰่ฎพ็ฝฎใ€‚ + +ๅ‡่ฎพไฝ ๆƒณ่ฎฉๅฎƒ่ฟ”ๅ›žๅธฆ็ผฉ่ฟ›ใ€ๆ ผๅผๅŒ–็š„ JSON๏ผŒๅ› ๆญคไฝ ๆƒณไฝฟ็”จ orjson ้€‰้กน `orjson.OPT_INDENT_2`ใ€‚ + +ไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช `CustomORJSONResponse`ใ€‚ไฝ ้œ€่ฆๅš็š„ไธป่ฆไบ‹ๆƒ…ๆ˜ฏๅฎž็Žฐไธ€ไธช่ฟ”ๅ›ž `bytes` ็š„ `Response.render(content)` ๆ–นๆณ•๏ผš + +{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} + +็Žฐๅœจ๏ผŒไธๅ†ๆ˜ฏ่ฟ”ๅ›ž๏ผš + +```json +{"message": "Hello World"} +``` + +โ€ฆ่ฟ™ไธชๅ“ๅบ”ๅฐ†่ฟ”ๅ›ž๏ผš + +```json +{ + "message": "Hello World" +} +``` + +ๅฝ“็„ถ๏ผŒไฝ ๅพˆๅฏ่ƒฝไผšๆ‰พๅˆฐๆฏ”ๆ ผๅผๅŒ– JSON ๆ›ดๅฅฝ็š„ๆ–นๅผๆฅๅˆฉ็”จ่ฟ™ไธ€็‚นใ€‚๐Ÿ˜‰ + +## ้ป˜่ฎคๅ“ๅบ”็ฑป { #default-response-class } + +ๅœจๅˆ›ๅปบ **FastAPI** ็ฑปๅฎžไพ‹ๆˆ– `APIRouter` ๆ—ถ๏ผŒไฝ ๅฏไปฅๆŒ‡ๅฎš้ป˜่ฎค่ฆไฝฟ็”จ็š„ๅ“ๅบ”็ฑปใ€‚ + +็”จไบŽๅฎšไน‰ๅฎƒ็š„ๅ‚ๆ•ฐๆ˜ฏ `default_response_class`ใ€‚ + +ๅœจไธ‹้ข็š„็คบไพ‹ไธญ๏ผŒ**FastAPI** ไผšๅœจๆ‰€ๆœ‰ *่ทฏๅพ„ๆ“ไฝœ* ไธญ้ป˜่ฎคไฝฟ็”จ `ORJSONResponse`๏ผŒ่€Œไธๆ˜ฏ `JSONResponse`ใ€‚ + +{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} + +/// tip | ๆ็คบ + +ไฝ ไป็„ถๅฏไปฅๅƒไน‹ๅ‰ไธ€ๆ ทๅœจ *่ทฏๅพ„ๆ“ไฝœ* ไธญ้‡่ฝฝ `response_class`ใ€‚ + +/// -## ้ขๅค–ๆ–‡ๆกฃ +## ้ขๅค–ๆ–‡ๆกฃ { #additional-documentation } -ๆ‚จ่ฟ˜ๅฏไปฅไฝฟ็”จ `response` ๅœจ OpenAPI ไธญๅฃฐๆ˜Žๅช’ไฝ“็ฑปๅž‹ๅ’Œ่ฎธๅคšๅ…ถไป–่ฏฆ็ป†ไฟกๆฏ๏ผš[OpenAPI ไธญ็š„้ขๅค–ๆ–‡ๆกฃ](additional-responses.md){.internal-link target=_blank}ใ€‚ +ไฝ ่ฟ˜ๅฏไปฅไฝฟ็”จ `responses` ๅœจ OpenAPI ไธญๅฃฐๆ˜Žๅช’ไฝ“็ฑปๅž‹ๅ’Œ่ฎธๅคšๅ…ถไป–่ฏฆ็ป†ไฟกๆฏ๏ผš[OpenAPI ไธญ็š„้ขๅค–ๆ–‡ๆกฃ](additional-responses.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md index 4e8e77d2ac..d62aef8f39 100644 --- a/docs/zh/docs/advanced/dataclasses.md +++ b/docs/zh/docs/advanced/dataclasses.md @@ -1,97 +1,87 @@ -# ไฝฟ็”จๆ•ฐๆฎ็ฑป +# ไฝฟ็”จๆ•ฐๆฎ็ฑป { #using-dataclasses } -FastAPI ๅŸบไบŽ **Pydantic** ๆž„ๅปบ๏ผŒๅ‰ๆ–‡ๅทฒ็ปไป‹็ป่ฟ‡ๅฆ‚ไฝ•ไฝฟ็”จ Pydantic ๆจกๅž‹ๅฃฐๆ˜Ž่ฏทๆฑ‚ไธŽๅ“ๅบ”ใ€‚ +FastAPI ๅŸบไบŽ **Pydantic** ๆž„ๅปบ๏ผŒๆˆ‘ๅทฒ็ปๅ‘ไฝ ๅฑ•็คบ่ฟ‡ๅฆ‚ไฝ•ไฝฟ็”จ Pydantic ๆจกๅž‹ๅฃฐๆ˜Ž่ฏทๆฑ‚ไธŽๅ“ๅบ”ใ€‚ -ไฝ† FastAPI ่ฟ˜ๅฏไปฅไฝฟ็”จๆ•ฐๆฎ็ฑป๏ผˆ`dataclasses`๏ผ‰๏ผš +ไฝ† FastAPI ไนŸๆ”ฏๆŒไปฅ็›ธๅŒๆ–นๅผไฝฟ็”จ `dataclasses`๏ผš -{* ../../docs_src/dataclasses_/tutorial001.py hl[1,7:12,19:20] *} +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -่ฟ™่ฟ˜ๆ˜ฏๅ€ŸๅŠฉไบŽ **Pydantic** ๅŠๅ…ถๅ†…็ฝฎ็š„ย `dataclasses`ใ€‚ +่ฟ™ไป็„ถๅพ—็›ŠไบŽ **Pydantic**๏ผŒๅ› ไธบๅฎƒๅฏน `dataclasses` ็š„ๅ†…็ฝฎๆ”ฏๆŒใ€‚ -ๅ› ๆญค๏ผŒๅณไพฟไธŠ่ฟฐไปฃ็ ๆฒกๆœ‰ๆ˜พๅผไฝฟ็”จ Pydantic๏ผŒFastAPI ไปไผšไฝฟ็”จ Pydantic ๆŠŠๆ ‡ๅ‡†ๆ•ฐๆฎ็ฑป่ฝฌๆขไธบ Pydantic ๆ•ฐๆฎ็ฑป๏ผˆ`dataclasses`๏ผ‰ใ€‚ +ๅ› ๆญค๏ผŒๅณไพฟไธŠ้ข็š„ไปฃ็ ๆฒกๆœ‰ๆ˜พๅผไฝฟ็”จ Pydantic๏ผŒFastAPI ไนŸไผšไฝฟ็”จ Pydantic ๅฐ†้‚ฃไบ›ๆ ‡ๅ‡†ๆ•ฐๆฎ็ฑป่ฝฌๆขไธบ Pydantic ้ฃŽๆ ผ็š„ dataclassesใ€‚ ๅนถไธ”๏ผŒๅฎƒไป็„ถๆ”ฏๆŒไปฅไธ‹ๅŠŸ่ƒฝ๏ผš * ๆ•ฐๆฎ้ชŒ่ฏ * ๆ•ฐๆฎๅบๅˆ—ๅŒ– -* ๆ•ฐๆฎๅญ˜ๆกฃ็ญ‰ +* ๆ•ฐๆฎๆ–‡ๆกฃ็ญ‰ -ๆ•ฐๆฎ็ฑป็š„ๅ’Œ่ฟไฝœๆ–นๅผไธŽ Pydantic ๆจกๅž‹็›ธๅŒใ€‚ๅฎž้™…ไธŠ๏ผŒๅฎƒ็š„ๅบ•ๅฑ‚ไฝฟ็”จ็š„ไนŸๆ˜ฏ Pydanticใ€‚ +่ฟ™ไธŽไฝฟ็”จ Pydantic ๆจกๅž‹ๆ—ถ็š„ๅทฅไฝœๆ–นๅผ็›ธๅŒใ€‚่€Œไธ”ๅบ•ๅฑ‚ๅฎž้™…ไธŠไนŸๆ˜ฏๅ€ŸๅŠฉ Pydantic ๅฎž็Žฐ็š„ใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๆณจๆ„๏ผŒๆ•ฐๆฎ็ฑปไธๆ”ฏๆŒ Pydantic ๆจกๅž‹็š„ๆ‰€ๆœ‰ๅŠŸ่ƒฝใ€‚ +่ฏทๆณจๆ„๏ผŒๆ•ฐๆฎ็ฑปไธ่ƒฝๅฎŒๆˆ Pydantic ๆจกๅž‹่ƒฝๅš็š„ๆ‰€ๆœ‰ไบ‹ๆƒ…ใ€‚ -ๅ› ๆญค๏ผŒๅผ€ๅ‘ๆ—ถไป้œ€่ฆไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ +ๅ› ๆญค๏ผŒไฝ ๅฏ่ƒฝไป็„ถ้œ€่ฆไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ -ไฝ†ๅฆ‚ๆžœๆ•ฐๆฎ็ฑปๅพˆๅคš๏ผŒ่ฟ™ไธ€ๆŠ€ๅทง่ƒฝ็ป™ FastAPI ๅผ€ๅ‘ Web API ๅขžๆทปไธๅฐ‘ๅŠฉๅŠ›ใ€‚๐Ÿค“ +ไฝ†ๅฆ‚ๆžœไฝ ๅทฒๆœ‰ไธ€ๅ †ๆ•ฐๆฎ็ฑป๏ผŒ่ฟ™ไธชๆŠ€ๅทงๅฏไปฅ่ฎฉๅฎƒไปฌๅพˆๅฅฝๅœฐไธบไฝฟ็”จ FastAPI ็š„ Web API ๆ‰€็”จใ€‚๐Ÿค“ /// -## `response_model` ไฝฟ็”จๆ•ฐๆฎ็ฑป +## ๅœจ `response_model` ไธญไฝฟ็”จๆ•ฐๆฎ็ฑป { #dataclasses-in-response-model } -ๅœจ `response_model` ๅ‚ๆ•ฐไธญไฝฟ็”จ `dataclasses`๏ผš +ไฝ ไนŸๅฏไปฅๅœจ `response_model` ๅ‚ๆ•ฐไธญไฝฟ็”จ `dataclasses`๏ผš -{* ../../docs_src/dataclasses_/tutorial002.py hl[1,7:13,19] *} +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} -ๆœฌไพ‹ๆŠŠๆ•ฐๆฎ็ฑป่‡ชๅŠจ่ฝฌๆขไธบ Pydantic ๆ•ฐๆฎ็ฑปใ€‚ +่ฏฅๆ•ฐๆฎ็ฑปไผš่ขซ่‡ชๅŠจ่ฝฌๆขไธบ Pydantic ็š„ๆ•ฐๆฎ็ฑปใ€‚ -API ๆ–‡ๆกฃไธญไนŸไผšๆ˜พ็คบ็›ธๅ…ณๆฆ‚ๅ›พ๏ผš +่ฟ™ๆ ท๏ผŒๅฎƒ็š„ๆจกๅผไผšๆ˜พ็คบๅœจ API ๆ–‡ๆกฃ็•Œ้ขไธญ๏ผš -## ๅœจๅตŒๅฅ—ๆ•ฐๆฎ็ป“ๆž„ไธญไฝฟ็”จๆ•ฐๆฎ็ฑป +## ๅœจๅตŒๅฅ—ๆ•ฐๆฎ็ป“ๆž„ไธญไฝฟ็”จๆ•ฐๆฎ็ฑป { #dataclasses-in-nested-data-structures } -ๆ‚จ่ฟ˜ๅฏไปฅๆŠŠ `dataclasses` ไธŽๅ…ถๅฎƒ็ฑปๅž‹ๆณจ่งฃ็ป„ๅˆๅœจไธ€่ตท๏ผŒๅˆ›ๅปบๅตŒๅฅ—ๆ•ฐๆฎ็ป“ๆž„ใ€‚ +ไฝ ไนŸๅฏไปฅๆŠŠ `dataclasses` ไธŽๅ…ถๅฎƒ็ฑปๅž‹ๆณจ่งฃ็ป„ๅˆๅœจไธ€่ตท๏ผŒๅˆ›ๅปบๅตŒๅฅ—ๆ•ฐๆฎ็ป“ๆž„ใ€‚ -่ฟ˜ๆœ‰ไธ€ไบ›ๆƒ…ๅ†ตไนŸๅฏไปฅไฝฟ็”จ Pydantic ็š„ `dataclasses`ใ€‚ไพ‹ๅฆ‚๏ผŒๅœจ API ๆ–‡ๆกฃไธญๆ˜พ็คบ้”™่ฏฏใ€‚ +ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝไป็„ถ้œ€่ฆไฝฟ็”จ Pydantic ็š„ `dataclasses` ็‰ˆๆœฌใ€‚ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ่‡ชๅŠจ็”Ÿๆˆ็š„ API ๆ–‡ๆกฃๅ‡บ็Žฐ้”™่ฏฏใ€‚ -ๆœฌไพ‹ๆŠŠๆ ‡ๅ‡†็š„ `dataclasses` ็›ดๆŽฅๆ›ฟๆขไธบ `pydantic.dataclasses`๏ผš +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๆŠŠๆ ‡ๅ‡†็š„ `dataclasses` ๆ›ฟๆขไธบ `pydantic.dataclasses`๏ผŒๅฎƒๆ˜ฏไธ€ไธชๅฏ็›ดๆŽฅๆ›ฟๆข็š„ๅฎž็Žฐ๏ผš -```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" } -{!../../docs_src/dataclasses_/tutorial003.py!} -``` +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} -1. ๆœฌไพ‹ไพ็„ถ่ฆไปŽๆ ‡ๅ‡†็š„ `dataclasses` ไธญๅฏผๅ…ฅ `field`๏ผ› +1. ๆˆ‘ไปฌไป็„ถไปŽๆ ‡ๅ‡†ๅบ“็š„ `dataclasses` ๅฏผๅ…ฅ `field`ใ€‚ +2. `pydantic.dataclasses` ๆ˜ฏ `dataclasses` ็š„ๅฏ็›ดๆŽฅๆ›ฟๆข็‰ˆๆœฌใ€‚ +3. `Author` ๆ•ฐๆฎ็ฑปๅŒ…ๅซไธ€ไธช็”ฑ `Item` ๆ•ฐๆฎ็ฑป็ป„ๆˆ็š„ๅˆ—่กจใ€‚ +4. `Author` ๆ•ฐๆฎ็ฑป่ขซ็”จไฝœ `response_model` ๅ‚ๆ•ฐใ€‚ +5. ไฝ ๅฏไปฅๅฐ†ๅ…ถๅฎƒๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃไธŽๆ•ฐๆฎ็ฑปไธ€่ตท็”จไฝœ่ฏทๆฑ‚ไฝ“ใ€‚ -2. ไฝฟ็”จ `pydantic.dataclasses` ็›ดๆŽฅๆ›ฟๆข `dataclasses`๏ผ› + ๅœจๆœฌไพ‹ไธญ๏ผŒๅฎƒๆ˜ฏไธ€ไธช `Item` ๆ•ฐๆฎ็ฑปๅˆ—่กจใ€‚ +6. ่ฟ™้‡Œๆˆ‘ไปฌ่ฟ”ๅ›žไธ€ไธชๅญ—ๅ…ธ๏ผŒ้‡Œ้ข็š„ `items` ๆ˜ฏไธ€ไธชๆ•ฐๆฎ็ฑปๅˆ—่กจใ€‚ -3. `Author` ๆ•ฐๆฎ็ฑปๅŒ…ๅซ `Item` ๆ•ฐๆฎ็ฑปๅˆ—่กจ๏ผ› + FastAPI ไป็„ถ่ƒฝๅคŸๅฐ†ๆ•ฐๆฎๅบๅˆ—ๅŒ–ไธบ JSONใ€‚ +7. ่ฟ™้‡Œ็š„ `response_model` ไฝฟ็”จไบ† โ€œ`Author` ๆ•ฐๆฎ็ฑปๅˆ—่กจโ€ ็š„็ฑปๅž‹ๆณจ่งฃใ€‚ -4. `Author` ๆ•ฐๆฎ็ฑป็”จไบŽ `response_model` ๅ‚ๆ•ฐ๏ผ› + ๅŒๆ ท๏ผŒไฝ ๅฏไปฅๅฐ† `dataclasses` ไธŽๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃ็ป„ๅˆไฝฟ็”จใ€‚ +8. ๆณจๆ„๏ผŒ่ฟ™ไธช *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไฝฟ็”จ็š„ๆ˜ฏๅธธ่ง„็š„ `def` ่€Œไธๆ˜ฏ `async def`ใ€‚ -5. ๅ…ถๅฎƒๅธฆๆœ‰ๆ•ฐๆฎ็ฑป็š„ๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃไนŸๅฏไปฅไฝœไธบ่ฏทๆฑ‚ไฝ“๏ผ› + ไธ€ๅฆ‚ๆ—ขๅพ€๏ผŒๅœจ FastAPI ไธญไฝ ๅฏไปฅๆŒ‰้œ€็ป„ๅˆ `def` ๅ’Œ `async def`ใ€‚ - ๆœฌไพ‹ไฝฟ็”จ็š„ๆ˜ฏ `Item` ๆ•ฐๆฎ็ฑปๅˆ—่กจ๏ผ› + ๅฆ‚ๆžœ้œ€่ฆๅ›ž้กพไฝ•ๆ—ถ็”จๅ“ชไธ€ไธช๏ผŒ่ฏทๆŸฅ็œ‹ๅ…ณไบŽ [`async` ๅ’Œ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ็š„ๆ–‡ๆกฃไธญ็š„ _โ€œๆ€ฅไธๅฏๅพ…๏ผŸโ€_ ไธ€่Š‚ใ€‚ +9. ่ฟ™ไธช *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ่ฟ”ๅ›ž็š„ไธๆ˜ฏๆ•ฐๆฎ็ฑป๏ผˆๅฝ“็„ถไนŸๅฏไปฅ่ฟ”ๅ›žๆ•ฐๆฎ็ฑป๏ผ‰๏ผŒ่€Œๆ˜ฏๅŒ…ๅซๅ†…้ƒจๆ•ฐๆฎ็š„ๅญ—ๅ…ธๅˆ—่กจใ€‚ -6. ่ฟ™่กŒไปฃ็ ่ฟ”ๅ›ž็š„ๆ˜ฏๅŒ…ๅซ `items` ็š„ๅญ—ๅ…ธ๏ผŒ`items` ๆ˜ฏๆ•ฐๆฎ็ฑปๅˆ—่กจ๏ผ› + FastAPI ไผšไฝฟ็”จ๏ผˆๅŒ…ๅซๆ•ฐๆฎ็ฑป็š„๏ผ‰`response_model` ๅ‚ๆ•ฐๆฅ่ฝฌๆขๅ“ๅบ”ใ€‚ - FastAPI ไป่ƒฝๆŠŠๆ•ฐๆฎๅบๅˆ—ๅŒ–ไธบ JSON๏ผ› +ไฝ ๅฏไปฅๅฐ† `dataclasses` ไธŽๅ…ถๅฎƒ็ฑปๅž‹ๆณจ่งฃไปฅๅคš็งไธๅŒๆ–นๅผ็ป„ๅˆ๏ผŒๆฅๆž„ๅปบๅคๆ‚็š„ๆ•ฐๆฎ็ป“ๆž„ใ€‚ -7. ่ฟ™่กŒไปฃ็ ไธญ๏ผŒ`response_model` ็š„็ฑปๅž‹ๆณจ่งฃๆ˜ฏ `Author` ๆ•ฐๆฎ็ฑปๅˆ—่กจ๏ผ› +ๆ›ดๅคš็ป†่Š‚่ฏทๅ‚่€ƒไธŠ้ขไปฃ็ ไธญ็š„ๅ†…่”ๆณจ้‡Šๆ็คบใ€‚ - ๅ†ไธ€ๆฌก๏ผŒๅฏไปฅๆŠŠ `dataclasses` ไธŽๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃไธ€่ตทไฝฟ็”จ๏ผ› +## ๆทฑๅ…ฅๅญฆไน  { #learn-more } -8. ๆณจๆ„๏ผŒ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไฝฟ็”จ็š„ๆ˜ฏๆ™ฎ้€šๅ‡ฝๆ•ฐ๏ผŒไธๆ˜ฏๅผ‚ๆญฅๅ‡ฝๆ•ฐ๏ผ› +ไฝ ่ฟ˜ๅฏไปฅๆŠŠ `dataclasses` ไธŽๅ…ถๅฎƒ Pydantic ๆจกๅž‹็ป„ๅˆใ€ไปŽๅฎƒไปฌ็ปงๆ‰ฟใ€ๆŠŠๅฎƒไปฌๅŒ…ๅซๅˆฐไฝ ่‡ชๅทฑ็š„ๆจกๅž‹ไธญ็ญ‰ใ€‚ - ไธŽๅพ€ๅธธไธ€ๆ ท๏ผŒๅœจ FastAPI ไธญ๏ผŒๅฏไปฅๆŒ‰้œ€็ป„ๅˆๆ™ฎ้€šๅ‡ฝๆ•ฐไธŽๅผ‚ๆญฅๅ‡ฝๆ•ฐ๏ผ› +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ฏทๆŸฅ็œ‹ Pydantic ๅ…ณไบŽ dataclasses ็š„ๆ–‡ๆกฃใ€‚ - ๅฆ‚ๆžœไธๆธ…ๆฅšไฝ•ๆ—ถไฝฟ็”จๅผ‚ๆญฅๅ‡ฝๆ•ฐๆˆ–ๆ™ฎ้€šๅ‡ฝๆ•ฐ๏ผŒ่ฏทๅ‚้˜…**ๆ€ฅไธๅฏๅพ…๏ผŸ**ไธ€่Š‚ไธญๅฏน `async`ย ไธŽย `await` ็š„่ฏดๆ˜Ž๏ผ› +## ็‰ˆๆœฌ { #version } -9. *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*่ฟ”ๅ›ž็š„ไธๆ˜ฏๆ•ฐๆฎ็ฑป๏ผˆ่™ฝ็„ถๅฎƒๅฏไปฅ่ฟ”ๅ›žๆ•ฐๆฎ็ฑป๏ผ‰๏ผŒ่€Œๆ˜ฏ่ฟ”ๅ›žๅ†…ๅซๆ•ฐๆฎ็š„ๅญ—ๅ…ธๅˆ—่กจ๏ผ› - - FastAPI ไฝฟ็”จ๏ผˆๅŒ…ๅซๆ•ฐๆฎ็ฑป็š„๏ผ‰ `response_model` ๅ‚ๆ•ฐ่ฝฌๆขๅ“ๅบ”ใ€‚ - -ๆŠŠ `dataclasses` ไธŽๅ…ถๅฎƒ็ฑปๅž‹ๆณจ่งฃ็ป„ๅˆๅœจไธ€่ตท๏ผŒๅฏไปฅ็ป„ๆˆไธๅŒๅฝขๅผ็š„ๅคๆ‚ๆ•ฐๆฎ็ป“ๆž„ใ€‚ - -ๆ›ดๅคšๅ†…ๅฎน่ฏฆ่งไธŠ่ฟฐไปฃ็ ๅ†…็š„ๆณจ้‡Šใ€‚ - -## ๆทฑๅ…ฅๅญฆไน  - -ๆ‚จ่ฟ˜ๅฏไปฅๆŠŠ `dataclasses` ไธŽๅ…ถๅฎƒ Pydantic ๆจกๅž‹็ป„ๅˆๅœจไธ€่ตท๏ผŒ็ปงๆ‰ฟๅˆๅนถ็š„ๆจกๅž‹๏ผŒๆŠŠๅฎƒไปฌๅŒ…ๅซๅœจๆ‚จ่‡ชๅทฑ็š„ๆจกๅž‹้‡Œใ€‚ - -่ฏฆ่ง Pydantic ๅฎ˜ๆกฃ - ๆ•ฐๆฎ็ฑปใ€‚ - -## ็‰ˆๆœฌ - -ๆœฌ็ซ ๅ†…ๅฎน่‡ช FastAPI `0.67.0` ็‰ˆ่ตท็”Ÿๆ•ˆใ€‚๐Ÿ”– +่‡ช FastAPI ็‰ˆๆœฌ `0.67.0` ่ตทๅฏ็”จใ€‚๐Ÿ”– diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md index 1ef6cdd3ce..7b49931a4c 100644 --- a/docs/zh/docs/advanced/events.md +++ b/docs/zh/docs/advanced/events.md @@ -1,18 +1,18 @@ -# ็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ +# ็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ { #lifespan-events } ไฝ ๅฏไปฅๅฎšไน‰ๅœจๅบ”็”จ**ๅฏๅŠจ**ๅ‰ๆ‰ง่กŒ็š„้€ป่พ‘๏ผˆไปฃ็ ๏ผ‰ใ€‚่ฟ™ๆ„ๅ‘ณ็€ๅœจๅบ”็”จ**ๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚**ไน‹ๅ‰๏ผŒ่ฟ™ไบ›ไปฃ็ ๅชไผš่ขซๆ‰ง่กŒ**ไธ€ๆฌก**ใ€‚ ๅŒๆ ทๅœฐ๏ผŒไฝ ๅฏไปฅๅฎšไน‰ๅœจๅบ”็”จ**ๅ…ณ้—ญ**ๆ—ถๅบ”ๆ‰ง่กŒ็š„้€ป่พ‘ใ€‚ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ่ฟ™ๆฎตไปฃ็ ๅฐ†ๅœจ**ๅค„็†ๅฏ่ƒฝ็š„ๅคšๆฌก่ฏทๆฑ‚ๅŽ**ๆ‰ง่กŒ**ไธ€ๆฌก**ใ€‚ -ๅ› ไธบ่ฟ™ๆฎตไปฃ็ ๅœจๅบ”็”จๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚**ไน‹ๅ‰**ๆ‰ง่กŒ๏ผŒไนŸไผšๅœจๅค„็†ๅฏ่ƒฝ็š„่‹ฅๅนฒ่ฏทๆฑ‚**ไน‹ๅŽ**ๆ‰ง่กŒ๏ผŒๅฎƒ่ฆ†็›–ไบ†ๆ•ดไธชๅบ”็”จ็จ‹ๅบ็š„**็”Ÿๅ‘ฝๅ‘จๆœŸ**๏ผˆ"็”Ÿๅ‘ฝๅ‘จๆœŸ"่ฟ™ไธช่ฏๅพˆ้‡่ฆ๐Ÿ˜‰๏ผ‰ใ€‚ +ๅ› ไธบ่ฟ™ๆฎตไปฃ็ ๅœจๅบ”็”จๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚**ไน‹ๅ‰**ๆ‰ง่กŒ๏ผŒไนŸไผšๅœจๅค„็†ๅฏ่ƒฝ็š„่‹ฅๅนฒ่ฏทๆฑ‚**ไน‹ๅŽ**ๆ‰ง่กŒ๏ผŒๅฎƒ่ฆ†็›–ไบ†ๆ•ดไธชๅบ”็”จ็จ‹ๅบ็š„**็”Ÿๅ‘ฝๅ‘จๆœŸ**๏ผˆโ€œ็”Ÿๅ‘ฝๅ‘จๆœŸโ€่ฟ™ไธช่ฏๅพˆ้‡่ฆ๐Ÿ˜‰๏ผ‰ใ€‚ ่ฟ™ๅฏนไบŽ่ฎพ็ฝฎไฝ ้œ€่ฆๅœจๆ•ดไธชๅบ”็”จไธญไฝฟ็”จ็š„**่ต„ๆบ**้žๅธธๆœ‰็”จ๏ผŒ่ฟ™ไบ›่ต„ๆบๅœจ่ฏทๆฑ‚ไน‹้—ด**ๅ…ฑไบซ**๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆๅœจไน‹ๅŽ่ฟ›่กŒ**้‡Šๆ”พ**ใ€‚ไพ‹ๅฆ‚๏ผŒๆ•ฐๆฎๅบ“่ฟžๆŽฅๆฑ ๏ผŒๆˆ–ๅŠ ่ฝฝไธ€ไธชๅ…ฑไบซ็š„ๆœบๅ™จๅญฆไน ๆจกๅž‹ใ€‚ -## ็”จไพ‹ +## ็”จไพ‹ { #use-case } -่ฎฉๆˆ‘ไปฌไปŽไธ€ไธช็คบไพ‹็”จไพ‹ๅผ€ๅง‹๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•่งฃๅ†ณๅฎƒใ€‚ +่ฎฉๆˆ‘ไปฌไปŽไธ€ไธช็คบไพ‹**็”จไพ‹**ๅผ€ๅง‹๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•็”จๅฎƒๆฅ่งฃๅ†ณ้—ฎ้ข˜ใ€‚ -ๅ‡่ฎพไฝ ๆœ‰ๅ‡ ไธช**ๆœบๅ™จๅญฆไน ็š„ๆจกๅž‹**๏ผŒไฝ ๆƒณ่ฆ็”จๅฎƒไปฌๆฅๅค„็†่ฏทๆฑ‚ใ€‚ +ๅ‡่ฎพไฝ ๆœ‰ๅ‡ ไธช**ๆœบๅ™จๅญฆไน ็š„ๆจกๅž‹**๏ผŒไฝ ๆƒณ่ฆ็”จๅฎƒไปฌๆฅๅค„็†่ฏทๆฑ‚ใ€‚๐Ÿค– ็›ธๅŒ็š„ๆจกๅž‹ๅœจ่ฏทๆฑ‚ไน‹้—ดๆ˜ฏๅ…ฑไบซ็š„๏ผŒๅ› ๆญคๅนถ้žๆฏไธช่ฏทๆฑ‚ๆˆ–ๆฏไธช็”จๆˆทๅ„่‡ชๆ‹ฅๆœ‰ไธ€ไธชๆจกๅž‹ใ€‚ @@ -20,19 +20,17 @@ ไฝ ๅฏไปฅๅœจๆจกๅ—/ๆ–‡ไปถ็š„้กถ้ƒจๅŠ ่ฝฝๅฎƒ๏ผŒไฝ†่ฟ™ไนŸๆ„ๅ‘ณ็€ๅณไฝฟไฝ ๅชๆ˜ฏๅœจ่ฟ่กŒไธ€ไธช็ฎ€ๅ•็š„่‡ชๅŠจๅŒ–ๆต‹่ฏ•๏ผŒๅฎƒไนŸไผš**ๅŠ ่ฝฝๆจกๅž‹**๏ผŒ่ฟ™ๆ ทๆต‹่ฏ•ๅฐ†**ๅ˜ๆ…ข**๏ผŒๅ› ไธบๅฎƒๅฟ…้กปๅœจ่ƒฝๅคŸ็‹ฌ็ซ‹่ฟ่กŒไปฃ็ ็š„ๅ…ถไป–้ƒจๅˆ†ไน‹ๅ‰็ญ‰ๅพ…ๆจกๅž‹ๅŠ ่ฝฝๅฎŒๆˆใ€‚ -่ฟ™ๅฐฑๆ˜ฏๆˆ‘ไปฌ่ฆ่งฃๅ†ณ็š„้—ฎ้ข˜โ€”โ€”ๅœจๅค„็†่ฏทๆฑ‚ๅ‰ๅŠ ่ฝฝๆจกๅž‹๏ผŒไฝ†ๅชๆ˜ฏๅœจๅบ”็”จๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚ๅ‰๏ผŒ่€Œไธๆ˜ฏไปฃ็ ๆ‰ง่กŒๆ—ถใ€‚ +่ฟ™ๅฐฑๆ˜ฏๆˆ‘ไปฌ่ฆ่งฃๅ†ณ็š„้—ฎ้ข˜โ€”โ€”ๅœจๅค„็†่ฏทๆฑ‚ๅ‰ๅŠ ่ฝฝๆจกๅž‹๏ผŒไฝ†ๅชๆ˜ฏๅœจๅบ”็”จๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚ๅ‰๏ผŒ่€Œไธๆ˜ฏๅœจไปฃ็ ่ขซๅŠ ่ฝฝๆ—ถใ€‚ -## ็”Ÿๅ‘ฝๅ‘จๆœŸ lifespan +## Lifespan { #lifespan } -ไฝ ๅฏไปฅไฝฟ็”จ`FastAPI()`ๅบ”็”จ็š„`lifespan`ๅ‚ๆ•ฐๅ’Œไธ€ไธชไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ๏ผˆ็จๅŽๆˆ‘ๅฐ†ไธบไฝ ๅฑ•็คบ๏ผ‰ๆฅๅฎšไน‰**ๅฏๅŠจ**ๅ’Œ**ๅ…ณ้—ญ**็š„้€ป่พ‘ใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ `FastAPI` ๅบ”็”จ็š„ `lifespan` ๅ‚ๆ•ฐๅ’Œไธ€ไธชโ€œไธŠไธ‹ๆ–‡็ฎก็†ๅ™จโ€๏ผˆ็จๅŽๆˆ‘ๅฐ†ไธบไฝ ๅฑ•็คบ๏ผ‰ๆฅๅฎšไน‰**ๅฏๅŠจ**ๅ’Œ**ๅ…ณ้—ญ**็š„้€ป่พ‘ใ€‚ ่ฎฉๆˆ‘ไปฌไปŽไธ€ไธชไพ‹ๅญๅผ€ๅง‹๏ผŒ็„ถๅŽ่ฏฆ็ป†ไป‹็ปใ€‚ -ๆˆ‘ไปฌไฝฟ็”จ`yield`ๅˆ›ๅปบไบ†ไธ€ไธชๅผ‚ๆญฅๅ‡ฝๆ•ฐ`lifespan()`ๅƒ่ฟ™ๆ ท๏ผš +ๆˆ‘ไปฌไฝฟ็”จ `yield` ๅˆ›ๅปบไบ†ไธ€ไธชๅผ‚ๆญฅๅ‡ฝๆ•ฐ `lifespan()` ๅƒ่ฟ™ๆ ท๏ผš -```Python hl_lines="16 19" -{!../../docs_src/events/tutorial003.py!} -``` +{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} ๅœจ่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌๅœจ `yield` ไน‹ๅ‰ๅฐ†๏ผˆ่™šๆ‹Ÿ็š„๏ผ‰ๆจกๅž‹ๅ‡ฝๆ•ฐๆ”พๅ…ฅๆœบๅ™จๅญฆไน ๆจกๅž‹็š„ๅญ—ๅ…ธไธญ๏ผŒไปฅๆญคๆจกๆ‹ŸๅŠ ่ฝฝๆจกๅž‹็š„่€—ๆ—ถ**ๅฏๅŠจ**ๆ“ไฝœใ€‚่ฟ™ๆฎตไปฃ็ ๅฐ†ๅœจๅบ”็”จ็จ‹ๅบ**ๅผ€ๅง‹ๅค„็†่ฏทๆฑ‚ไน‹ๅ‰**ๆ‰ง่กŒ๏ผŒๅณ**ๅฏๅŠจ**ๆœŸ้—ดใ€‚ @@ -40,35 +38,31 @@ /// tip | ๆ็คบ -**ๅ…ณ้—ญ**ไบ‹ไปถๅชไผšๅœจไฝ ๅœๆญขๅบ”็”จๆ—ถ่งฆๅ‘ใ€‚ +**ๅ…ณ้—ญ**ไบ‹ไปถไผšๅœจไฝ **ๅœๆญข**ๅบ”็”จๆ—ถๅ‘็”Ÿใ€‚ -ๅฏ่ƒฝไฝ ้œ€่ฆๅฏๅŠจไธ€ไธชๆ–ฐ็‰ˆๆœฌ๏ผŒๆˆ–่€…ไฝ ๅชๆ˜ฏไฝ ๅŽŒๅ€ฆไบ†่ฟ่กŒๅฎƒใ€‚ ๐Ÿคท +ๅฏ่ƒฝไฝ ้œ€่ฆๅฏๅŠจไธ€ไธชๆ–ฐ็‰ˆๆœฌ๏ผŒๆˆ–่€…ไฝ ๅชๆ˜ฏๅŽŒๅ€ฆไบ†่ฟ่กŒๅฎƒใ€‚ ๐Ÿคท /// -## ็”Ÿๅ‘ฝๅ‘จๆœŸๅ‡ฝๆ•ฐ +### ็”Ÿๅ‘ฝๅ‘จๆœŸๅ‡ฝๆ•ฐ { #lifespan-function } ้ฆ–ๅ…ˆ่ฆๆณจๆ„็š„ๆ˜ฏ๏ผŒๆˆ‘ไปฌๅฎšไน‰ไบ†ไธ€ไธชๅธฆๆœ‰ `yield` ็š„ๅผ‚ๆญฅๅ‡ฝๆ•ฐใ€‚่ฟ™ไธŽๅธฆๆœ‰ `yield` ็š„ไพ่ต–้กน้žๅธธ็›ธไผผใ€‚ -```Python hl_lines="14-19" -{!../../docs_src/events/tutorial003.py!} -``` +{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} -่ฟ™ไธชๅ‡ฝๆ•ฐๅœจ `yield`ไน‹ๅ‰็š„้ƒจๅˆ†๏ผŒไผšๅœจๅบ”็”จๅฏๅŠจๅ‰ๆ‰ง่กŒใ€‚ +่ฟ™ไธชๅ‡ฝๆ•ฐๅœจ `yield` ไน‹ๅ‰็š„้ƒจๅˆ†๏ผŒไผšๅœจๅบ”็”จๅฏๅŠจๅ‰ๆ‰ง่กŒใ€‚ ๅ‰ฉไธ‹็š„้ƒจๅˆ†ๅœจ `yield` ไน‹ๅŽ๏ผŒไผšๅœจๅบ”็”จๅฎŒๆˆๅŽๆ‰ง่กŒใ€‚ -## ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ +### ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ { #async-context-manager } -ๅฆ‚ไฝ ๆ‰€่ง๏ผŒ่ฟ™ไธชๅ‡ฝๆ•ฐๆœ‰ไธ€ไธช่ฃ…้ฅฐๅ™จ `@asynccontextmanager` ใ€‚ +ๅฆ‚ไฝ ๆ‰€่ง๏ผŒ่ฟ™ไธชๅ‡ฝๆ•ฐๆœ‰ไธ€ไธช่ฃ…้ฅฐๅ™จ `@asynccontextmanager`ใ€‚ ๅฎƒๅฐ†ๅ‡ฝๆ•ฐ่ฝฌๅŒ–ไธบๆ‰€่ฐ“็š„โ€œ**ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**โ€ใ€‚ -```Python hl_lines="1 13" -{!../../docs_src/events/tutorial003.py!} -``` +{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} -ๅœจ Python ไธญ๏ผŒ **ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**ๆ˜ฏไธ€ไธชไฝ ๅฏไปฅๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ็š„ไธœ่ฅฟ๏ผŒไพ‹ๅฆ‚๏ผŒ`open()` ๅฏไปฅไฝœไธบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จไฝฟ็”จใ€‚ +ๅœจ Python ไธญ๏ผŒ**ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**ๆ˜ฏไธ€ไธชไฝ ๅฏไปฅๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ็š„ไธœ่ฅฟ๏ผŒไพ‹ๅฆ‚๏ผŒ`open()` ๅฏไปฅไฝœไธบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จไฝฟ็”จใ€‚ ```Python with open("file.txt") as file: @@ -82,21 +76,19 @@ async with lifespan(app): await do_stuff() ``` -ไฝ ๅฏไปฅๅƒไธŠ้ขไธ€ๆ ทๅˆ›ๅปบไบ†ไธ€ไธชไธŠไธ‹ๆ–‡็ฎก็†ๅ™จๆˆ–่€…ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ๏ผŒๅฎƒ็š„ไฝœ็”จๆ˜ฏๅœจ่ฟ›ๅ…ฅ `with` ๅ—ๆ—ถ๏ผŒๆ‰ง่กŒ `yield` ไน‹ๅ‰็š„ไปฃ็ ๏ผŒๅนถไธ”ๅœจ็ฆปๅผ€ `with` ๅ—ๆ—ถ๏ผŒๆ‰ง่กŒ `yield` ๅŽ้ข็š„ไปฃ็ ใ€‚ +ไฝ ๅฏไปฅๅƒไธŠ้ขไธ€ๆ ทๅˆ›ๅปบไธ€ไธชไธŠไธ‹ๆ–‡็ฎก็†ๅ™จๆˆ–่€…ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ๏ผŒๅฎƒ็š„ไฝœ็”จๆ˜ฏๅœจ่ฟ›ๅ…ฅ `with` ๅ—ๆ—ถ๏ผŒๆ‰ง่กŒ `yield` ไน‹ๅ‰็š„ไปฃ็ ๏ผŒๅนถไธ”ๅœจ็ฆปๅผ€ `with` ๅ—ๆ—ถ๏ผŒๆ‰ง่กŒ `yield` ๅŽ้ข็š„ไปฃ็ ใ€‚ ไฝ†ๅœจๆˆ‘ไปฌไธŠ้ข็š„ไพ‹ๅญ้‡Œ๏ผŒๆˆ‘ไปฌๅนถไธๆ˜ฏ็›ดๆŽฅไฝฟ็”จ๏ผŒ่€Œๆ˜ฏไผ ้€’็ป™ FastAPI ๆฅไพ›ๅ…ถไฝฟ็”จใ€‚ -`FastAPI()` ็š„ `lifespan` ๅ‚ๆ•ฐๆŽฅๅ—ไธ€ไธช**ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๅฏไปฅๆŠŠๆˆ‘ไปฌๆ–ฐๅฎšไน‰็š„ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ `lifespan` ไผ ็ป™ๅฎƒใ€‚ +`FastAPI` ็š„ `lifespan` ๅ‚ๆ•ฐๆŽฅๅ—ไธ€ไธช**ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๅฏไปฅๆŠŠๆˆ‘ไปฌๆ–ฐๅฎšไน‰็š„ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ `lifespan` ไผ ็ป™ๅฎƒใ€‚ -```Python hl_lines="22" -{!../../docs_src/events/tutorial003.py!} -``` +{* ../../docs_src/events/tutorial003_py39.py hl[22] *} -## ๆ›ฟไปฃไบ‹ไปถ๏ผˆๅผƒ็”จ๏ผ‰ +## ๆ›ฟไปฃไบ‹ไปถ๏ผˆๅผƒ็”จ๏ผ‰ { #alternative-events-deprecated } /// warning | ่ญฆๅ‘Š -้…็ฝฎ**ๅฏๅŠจ**ๅ’Œ**ๅ…ณ้—ญ**ไบ‹ไปถ็š„ๆŽจ่ๆ–นๆณ•ๆ˜ฏไฝฟ็”จ `FastAPI()` ๅบ”็”จ็š„ `lifespan` ๅ‚ๆ•ฐ๏ผŒๅฆ‚ๅ‰ๆ‰€็คบใ€‚ๅฆ‚ๆžœไฝ ๆไพ›ไบ†ไธ€ไธช `lifespan` ๅ‚ๆ•ฐ๏ผŒๅฏๅŠจ๏ผˆ`startup`๏ผ‰ๅ’Œๅ…ณ้—ญ๏ผˆ`shutdown`๏ผ‰ไบ‹ไปถๅค„็†ๅ™จๅฐ†ไธๅ†็”Ÿๆ•ˆใ€‚่ฆไนˆไฝฟ็”จ `lifespan`๏ผŒ่ฆไนˆ้…็ฝฎๆ‰€ๆœ‰ไบ‹ไปถ๏ผŒไธค่€…ไธ่ƒฝๅ…ฑ็”จใ€‚ +้…็ฝฎ**ๅฏๅŠจ**ๅ’Œ**ๅ…ณ้—ญ**็š„ๆŽจ่ๆ–นๆณ•ๆ˜ฏไฝฟ็”จ `FastAPI` ๅบ”็”จ็š„ `lifespan` ๅ‚ๆ•ฐ๏ผŒๅฆ‚ๅ‰ๆ‰€็คบใ€‚ๅฆ‚ๆžœไฝ ๆไพ›ไบ†ไธ€ไธช `lifespan` ๅ‚ๆ•ฐ๏ผŒๅฏๅŠจ๏ผˆ`startup`๏ผ‰ๅ’Œๅ…ณ้—ญ๏ผˆ`shutdown`๏ผ‰ไบ‹ไปถๅค„็†ๅ™จๅฐ†ไธๅ†็”Ÿๆ•ˆใ€‚่ฆไนˆไฝฟ็”จ `lifespan`๏ผŒ่ฆไนˆ้…็ฝฎๆ‰€ๆœ‰ไบ‹ไปถ๏ผŒไธค่€…ไธ่ƒฝๅ…ฑ็”จใ€‚ ไฝ ๅฏไปฅ่ทณ่ฟ‡่ฟ™ไธ€้ƒจๅˆ†ใ€‚ @@ -104,70 +96,70 @@ async with lifespan(app): ๆœ‰ไธ€็งๆ›ฟไปฃๆ–นๆณ•ๅฏไปฅๅฎšไน‰ๅœจ**ๅฏๅŠจ**ๅ’Œ**ๅ…ณ้—ญ**ๆœŸ้—ดๆ‰ง่กŒ็š„้€ป่พ‘ใ€‚ -**FastAPI** ๆ”ฏๆŒๅฎšไน‰ๅœจๅบ”็”จๅฏๅŠจๅ‰๏ผŒๆˆ–ๅบ”็”จๅ…ณ้—ญๆ—ถๆ‰ง่กŒ็š„ไบ‹ไปถๅค„็†ๅ™จ๏ผˆๅ‡ฝๆ•ฐ๏ผ‰ใ€‚ +ไฝ ๅฏไปฅๅฎšไน‰ๅœจๅบ”็”จๅฏๅŠจๅ‰ๆˆ–ๅบ”็”จๅ…ณ้—ญๆ—ถ้œ€่ฆๆ‰ง่กŒ็š„ไบ‹ไปถๅค„็†ๅ™จ๏ผˆๅ‡ฝๆ•ฐ๏ผ‰ใ€‚ ไบ‹ไปถๅ‡ฝๆ•ฐๆ—ขๅฏไปฅๅฃฐๆ˜Žไธบๅผ‚ๆญฅๅ‡ฝๆ•ฐ๏ผˆ`async def`๏ผ‰๏ผŒไนŸๅฏไปฅๅฃฐๆ˜Žไธบๆ™ฎ้€šๅ‡ฝๆ•ฐ๏ผˆ`def`๏ผ‰ใ€‚ -### `startup` ไบ‹ไปถ +### `startup` ไบ‹ไปถ { #startup-event } -ไฝฟ็”จ `startup` ไบ‹ไปถๅฃฐๆ˜Ž `app` ๅฏๅŠจๅ‰่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš +ไฝฟ็”จไบ‹ไปถ `"startup"` ๅฃฐๆ˜Žไธ€ไธชๅœจๅบ”็”จๅฏๅŠจๅ‰่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/events/tutorial001.py hl[8] *} +{* ../../docs_src/events/tutorial001_py39.py hl[8] *} -ๆœฌไพ‹ไธญ๏ผŒ`startup` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐไธบ้กน็›ฎๆ•ฐๆฎๅบ“๏ผˆๅชๆ˜ฏ**ๅญ—ๅ…ธ**๏ผ‰ๆไพ›ไบ†ไธ€ไบ›ๅˆๅง‹ๅ€ผใ€‚ +ๆœฌไพ‹ไธญ๏ผŒ`startup` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐไธบ้กน็›ฎโ€œๆ•ฐๆฎๅบ“โ€๏ผˆๅชๆ˜ฏไธ€ไธช `dict`๏ผ‰ๆไพ›ไบ†ไธ€ไบ›ๅˆๅง‹ๅ€ผใ€‚ **FastAPI** ๆ”ฏๆŒๅคšไธชไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐใ€‚ ๅชๆœ‰ๆ‰€ๆœ‰ `startup` ไบ‹ไปถๅค„็†ๅ™จ่ฟ่กŒๅฎŒๆฏ•๏ผŒ**FastAPI** ๅบ”็”จๆ‰ๅผ€ๅง‹ๆŽฅๆ”ถ่ฏทๆฑ‚ใ€‚ -### `shutdown` ไบ‹ไปถ +### `shutdown` ไบ‹ไปถ { #shutdown-event } -ไฝฟ็”จ `shutdown` ไบ‹ไปถๅฃฐๆ˜Ž `app` ๅ…ณ้—ญๆ—ถ่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš +ไฝฟ็”จไบ‹ไปถ `"shutdown"` ๅฃฐๆ˜Žไธ€ไธชๅœจๅบ”็”จๅ…ณ้—ญๆ—ถ่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/events/tutorial002.py hl[6] *} +{* ../../docs_src/events/tutorial002_py39.py hl[6] *} -ๆญคๅค„๏ผŒ`shutdown` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐๅœจ `log.txt` ไธญๅ†™ๅ…ฅไธ€่กŒๆ–‡ๆœฌ `Application shutdown`ใ€‚ +ๆญคๅค„๏ผŒ`shutdown` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐไผšๅ‘ๆ–‡ไปถ `log.txt` ๅ†™ๅ…ฅไธ€่กŒๆ–‡ๆœฌ `"Application shutdown"`ใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -`open()` ๅ‡ฝๆ•ฐไธญ๏ผŒ`mode="a"` ๆŒ‡็š„ๆ˜ฏ**่ฟฝๅŠ **ใ€‚ๅ› ๆญค่ฟ™่กŒๆ–‡ๆœฌไผšๆทปๅŠ ๅœจๆ–‡ไปถๅทฒๆœ‰ๅ†…ๅฎนไน‹ๅŽ๏ผŒไธไผš่ฆ†็›–ไน‹ๅ‰็š„ๅ†…ๅฎนใ€‚ +ๅœจ `open()` ๅ‡ฝๆ•ฐไธญ๏ผŒ`mode="a"` ๆŒ‡็š„ๆ˜ฏโ€œ่ฟฝๅŠ โ€ใ€‚ๅ› ๆญค่ฟ™่กŒๆ–‡ๆœฌไผšๆทปๅŠ ๅœจๆ–‡ไปถๅทฒๆœ‰ๅ†…ๅฎนไน‹ๅŽ๏ผŒไธไผš่ฆ†็›–ไน‹ๅ‰็š„ๅ†…ๅฎนใ€‚ /// /// tip | ๆ็คบ -ๆณจๆ„๏ผŒๆœฌไพ‹ไฝฟ็”จ Python `open()` ๆ ‡ๅ‡†ๅ‡ฝๆ•ฐไธŽๆ–‡ไปถไบคไบ’ใ€‚ +ๆณจๆ„๏ผŒๆœฌไพ‹ไฝฟ็”จ Python ๆ ‡ๅ‡†็š„ `open()` ๅ‡ฝๆ•ฐไธŽๆ–‡ไปถไบคไบ’ใ€‚ -่ฟ™ไธชๅ‡ฝๆ•ฐๆ‰ง่กŒ I/O๏ผˆ่พ“ๅ…ฅ/่พ“ๅ‡บ๏ผ‰ๆ“ไฝœ๏ผŒ้œ€่ฆ็ญ‰ๅพ…ๅ†…ๅฎนๅ†™่ฟ›็ฃ็›˜ใ€‚ +่ฟ™ไธชๅ‡ฝๆ•ฐๆ‰ง่กŒ I/O๏ผˆ่พ“ๅ…ฅ/่พ“ๅ‡บ๏ผ‰ๆ“ไฝœ๏ผŒ้œ€่ฆโ€œ็ญ‰ๅพ…โ€ๅ†…ๅฎนๅ†™่ฟ›็ฃ็›˜ใ€‚ -ไฝ† `open()` ๅ‡ฝๆ•ฐไธๆ”ฏๆŒไฝฟ็”จ `async` ไธŽ `await`ใ€‚ +ไฝ† `open()` ไธไฝฟ็”จ `async` ๅ’Œ `await`ใ€‚ -ๅ› ๆญค๏ผŒๅฃฐๆ˜Žไบ‹ไปถๅค„็†ๅ‡ฝๆ•ฐ่ฆไฝฟ็”จ `def`๏ผŒไธ่ƒฝไฝฟ็”จ `asnyc def`ใ€‚ +ๅ› ๆญค๏ผŒๅฃฐๆ˜Žไบ‹ไปถๅค„็†ๅ‡ฝๆ•ฐ่ฆไฝฟ็”จ `def`๏ผŒ่€Œไธๆ˜ฏ `async def`ใ€‚ /// -### `startup` ๅ’Œ `shutdown` ไธ€่ตทไฝฟ็”จ +### `startup` ๅ’Œ `shutdown` ไธ€่ตทไฝฟ็”จ { #startup-and-shutdown-together } ๅฏๅŠจๅ’Œๅ…ณ้—ญ็š„้€ป่พ‘ๅพˆๅฏ่ƒฝๆ˜ฏ่ฟžๆŽฅๅœจไธ€่ตท็š„๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๅฏๅŠจๆŸไธชไธœ่ฅฟ็„ถๅŽ็ป“ๆŸๅฎƒ๏ผŒ่Žทๅ–ไธ€ไธช่ต„ๆบ็„ถๅŽ้‡Šๆ”พๅฎƒ็ญ‰็ญ‰ใ€‚ ๅœจไธๅ…ฑไบซ้€ป่พ‘ๆˆ–ๅ˜้‡็š„ไธๅŒๅ‡ฝๆ•ฐไธญๅค„็†่ฟ™ไบ›้€ป่พ‘ๆฏ”่พƒๅ›ฐ้šพ๏ผŒๅ› ไธบไฝ ้œ€่ฆๅœจๅ…จๅฑ€ๅ˜้‡ไธญๅญ˜ๅ‚จๅ€ผๆˆ–ไฝฟ็”จ็ฑปไผผ็š„ๆ–นๅผใ€‚ -ๅ› ๆญค๏ผŒๆŽจ่ไฝฟ็”จ `lifespan` ใ€‚ +ๅ› ๆญค๏ผŒๆŽจ่ไฝฟ็”จไธŠ้ขๆ‰€่ฟฐ็š„ `lifespan`ใ€‚ -## ๆŠ€ๆœฏ็ป†่Š‚ +## ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details } ๅชๆ˜ฏไธบๅฅฝๅฅ‡่€…ๆไพ›็š„ๆŠ€ๆœฏ็ป†่Š‚ใ€‚๐Ÿค“ -ๅœจๅบ•ๅฑ‚๏ผŒ่ฟ™้ƒจๅˆ†ๆ˜ฏ็”Ÿๅ‘ฝๅ‘จๆœŸๅ่ฎฎ็š„ไธ€้ƒจๅˆ†๏ผŒๅ‚่ง ASGI ๆŠ€ๆœฏ่ง„่Œƒ๏ผŒๅฎšไน‰ไบ†็งฐไธบๅฏๅŠจ๏ผˆ`startup`๏ผ‰ๅ’Œๅ…ณ้—ญ๏ผˆ`shutdown`๏ผ‰็š„ไบ‹ไปถใ€‚ +ๅœจๅบ•ๅฑ‚๏ผŒ่ฟ™้ƒจๅˆ†ๆ˜ฏ ASGI ๆŠ€ๆœฏ่ง„่Œƒไธญ็š„ Lifespan ๅ่ฎฎ็š„ไธ€้ƒจๅˆ†๏ผŒๅฎšไน‰ไบ†็งฐไธบ `startup` ๅ’Œ `shutdown` ็š„ไบ‹ไปถใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๆœ‰ๅ…ณไบ‹ไปถๅค„็†ๅ™จ็š„่ฏฆๆƒ…๏ผŒ่ฏทๅ‚้˜… Starlette ๅฎ˜ๆกฃ - ไบ‹ไปถใ€‚ +ไฝ ๅฏไปฅๅœจ Starlette ็š„ Lifespan ๆ–‡ๆกฃ ไธญ้˜…่ฏปๆ›ดๅคšๅ…ณไบŽ `lifespan` ๅค„็†ๅ™จ็š„ๅ†…ๅฎนใ€‚ -ๅŒ…ๆ‹ฌๅฆ‚ไฝ•ๅค„็†็”Ÿๅ‘ฝๅ‘จๆœŸ็Šถๆ€๏ผŒ่ฟ™ๅฏไปฅ็”จไบŽ็จ‹ๅบ็š„ๅ…ถไป–้ƒจๅˆ†ใ€‚ +ๅŒ…ๆ‹ฌๅฆ‚ไฝ•ๅค„็†็”Ÿๅ‘ฝๅ‘จๆœŸ็Šถๆ€๏ผŒไปฅไพฟๅœจไปฃ็ ็š„ๅ…ถไป–้ƒจๅˆ†ไฝฟ็”จใ€‚ /// -## ๅญๅบ”็”จ +## ๅญๅบ”็”จ { #sub-applications } -๐Ÿšจ **FastAPI** ๅชไผš่งฆๅ‘ไธปๅบ”็”จไธญ็š„็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ๏ผŒไธๅŒ…ๆ‹ฌ[ๅญๅบ”็”จ - ๆŒ‚่ฝฝ](sub-applications.md){.internal-link target=_blank}ไธญ็š„ใ€‚ +๐Ÿšจ ่ฏทๆณจๆ„๏ผŒ่ฟ™ไบ›็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ๏ผˆstartup ๅ’Œ shutdown๏ผ‰ๅชไผšๅœจไธปๅบ”็”จไธŠๆ‰ง่กŒ๏ผŒไธไผšๅœจ[ๅญๅบ”็”จ - ๆŒ‚่ฝฝ](sub-applications.md){.internal-link target=_blank}ไธŠๆ‰ง่กŒใ€‚ diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index bcb9ba2bf7..48a4ba07aa 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -1,237 +1,208 @@ -# ็”Ÿๆˆๅฎขๆˆท็ซฏ +# ็”Ÿๆˆ SDK { #generating-sdks } -ๅ› ไธบ **FastAPI** ๆ˜ฏๅŸบไบŽOpenAPI่ง„่Œƒ็š„๏ผŒ่‡ช็„ถๆ‚จๅฏไปฅไฝฟ็”จ่ฎธๅคš็›ธๅŒน้…็š„ๅทฅๅ…ท๏ผŒๅŒ…ๆ‹ฌ่‡ชๅŠจ็”ŸๆˆAPIๆ–‡ๆกฃ (็”ฑ Swagger UI ๆไพ›)ใ€‚ +ๅ› ไธบ **FastAPI** ๅŸบไบŽ **OpenAPI** ่ง„่Œƒ๏ผŒๅฎƒ็š„ API ๅฏไปฅ็”จ่ฎธๅคšๅทฅๅ…ท้ƒฝ่ƒฝ็†่งฃ็š„ๆ ‡ๅ‡†ๆ ผๅผๆฅๆ่ฟฐใ€‚ -ไธ€ไธชไธๅคชๆ˜Žๆ˜พ่€Œๅˆ็‰นๅˆซ็š„ไผ˜ๅŠฟๆ˜ฏ๏ผŒไฝ ๅฏไปฅไธบไฝ ็š„API้’ˆๅฏนไธๅŒ็š„**็ผ–็จ‹่ฏญ่จ€**ๆฅ**็”Ÿๆˆๅฎขๆˆท็ซฏ**(ๆœ‰ๆ—ถๅ€™่ขซๅซๅš **SDKs** )ใ€‚ +่ฟ™่ฎฉไฝ ๅฏไปฅ่ฝปๆพ็”Ÿๆˆๆœ€ๆ–ฐ็š„**ๆ–‡ๆกฃ**ใ€ๅคš่ฏญ่จ€็š„ๅฎขๆˆท็ซฏๅบ“๏ผˆ**SDKs**๏ผ‰๏ผŒไปฅๅŠไธŽไปฃ็ ไฟๆŒๅŒๆญฅ็š„**ๆต‹่ฏ•**ๆˆ–**่‡ชๅŠจๅŒ–ๅทฅไฝœๆต**ใ€‚ -## OpenAPI ๅฎขๆˆท็ซฏ็”Ÿๆˆ +ๆœฌๆŒ‡ๅ—ๅฐ†ๅธฆไฝ ไธบ FastAPI ๅŽ็ซฏ็”Ÿๆˆไธ€ไธช **TypeScript SDK**ใ€‚ -ๆœ‰่ฎธๅคšๅทฅๅ…ทๅฏไปฅไปŽ**OpenAPI**็”Ÿๆˆๅฎขๆˆท็ซฏใ€‚ +## ๅผ€ๆบ SDK ็”Ÿๆˆๅ™จ { #open-source-sdk-generators } -ไธ€ไธชๅธธ่ง็š„ๅทฅๅ…ทๆ˜ฏ OpenAPI Generatorใ€‚ +ไธ€ไธชๅŠŸ่ƒฝๅคšๆ ท็š„้€‰ๆ‹ฉๆ˜ฏ OpenAPI Generator๏ผŒๅฎƒๆ”ฏๆŒ**ๅคš็ง็ผ–็จ‹่ฏญ่จ€**๏ผŒๅฏไปฅๆ นๆฎไฝ ็š„ OpenAPI ่ง„่Œƒ็”Ÿๆˆ SDKใ€‚ -ๅฆ‚ๆžœๆ‚จๆญฃๅœจๅผ€ๅ‘**ๅ‰็ซฏ**๏ผŒไธ€ไธช้žๅธธๆœ‰่ถฃ็š„ๆ›ฟไปฃๆ–นๆกˆๆ˜ฏ openapi-tsใ€‚ +ๅฏนไบŽ **TypeScript ๅฎขๆˆท็ซฏ**๏ผŒHey API ๆ˜ฏไธบ TypeScript ็”Ÿๆ€ๆ‰“้€ ็š„ไธ“็”จๆ–นๆกˆ๏ผŒๆไพ›ไผ˜ๅŒ–็š„ไฝฟ็”จไฝ“้ชŒใ€‚ -## ็”Ÿๆˆไธ€ไธช TypeScript ๅ‰็ซฏๅฎขๆˆท็ซฏ +ไฝ ่ฟ˜ๅฏไปฅๅœจ OpenAPI.Tools ไธŠๅ‘็Žฐๆ›ดๅคš SDK ็”Ÿๆˆๅ™จใ€‚ -่ฎฉๆˆ‘ไปฌไปŽไธ€ไธช็ฎ€ๅ•็š„ FastAPI ๅบ”็”จๅผ€ๅง‹๏ผš +/// tip | ๆ็คบ -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} - -่ฏทๆณจๆ„๏ผŒ*่ทฏๅพ„ๆ“ไฝœ* ๅฎšไน‰ไบ†ไป–ไปฌๆ‰€็”จไบŽ่ฏทๆฑ‚ๆ•ฐๆฎๅ’Œๅ›žๅบ”ๆ•ฐๆฎ็š„ๆจกๅž‹๏ผŒๆ‰€ไฝฟ็”จ็š„ๆจกๅž‹ๆ˜ฏ`Item` ๅ’Œ `ResponseMessage`ใ€‚ - -### API ๆ–‡ๆกฃ - -ๅฆ‚ๆžœๆ‚จ่ฎฟ้—ฎAPIๆ–‡ๆกฃ๏ผŒๆ‚จๅฐ†็œ‹ๅˆฐๅฎƒๅ…ทๆœ‰ๅœจ่ฏทๆฑ‚ไธญๅ‘้€ๅ’Œๅœจๅ“ๅบ”ไธญๆŽฅๆ”ถๆ•ฐๆฎ็š„**ๆจกๅผ(schemas)**๏ผš +FastAPI ไผš่‡ชๅŠจ็”Ÿๆˆ **OpenAPI 3.1** ่ง„่Œƒ๏ผŒๅ› ๆญคไฝ ไฝฟ็”จ็š„ไปปไฝ•ๅทฅๅ…ท้ƒฝๅฟ…้กปๆ”ฏๆŒ่ฏฅ็‰ˆๆœฌใ€‚ - +/// -ๆ‚จๅฏไปฅ็œ‹ๅˆฐ่ฟ™ไบ›ๆจกๅผ๏ผŒๅ› ไธบๅฎƒไปฌๆ˜ฏ็”จ็จ‹ๅบไธญ็š„ๆจกๅž‹ๅฃฐๆ˜Ž็š„ใ€‚ +## ๆฅ่‡ช FastAPI ่ตžๅŠฉๅ•†็š„ SDK ็”Ÿๆˆๅ™จ { #sdk-generators-from-fastapi-sponsors } -้‚ฃไบ›ไฟกๆฏๅฏไปฅๅœจๅบ”็”จ็š„ **OpenAPIๆจกๅผ** ่ขซๆ‰พๅˆฐ๏ผŒ็„ถๅŽๆ˜พ็คบๅœจAPIๆ–‡ๆกฃไธญ๏ผˆ้€š่ฟ‡Swagger UI๏ผ‰ใ€‚ +ๆœฌ่Š‚ไป‹็ป็š„ๆ˜ฏ็”ฑ่ตžๅŠฉ FastAPI ็š„ๅ…ฌๅธๆไพ›็š„ใ€ๅ…ทๅค‡**้ฃŽ้™ฉๆŠ•่ต„่ƒŒๆ™ฏ**ๆˆ–**ๅ…ฌๅธๆ”ฏๆŒ**็š„ๆ–นๆกˆใ€‚่ฟ™ไบ›ไบงๅ“ๅœจ้ซ˜่ดจ้‡็”Ÿๆˆ็š„ SDK ไน‹ไธŠ๏ผŒๆไพ›ไบ†**ๆ›ดๅคš็‰นๆ€ง**ๅ’Œ**้›†ๆˆ**ใ€‚ -OpenAPIไธญๆ‰€ๅŒ…ๅซ็š„ๆจกๅž‹้‡Œๆœ‰็›ธๅŒ็š„ไฟกๆฏๅฏไปฅ็”จไบŽ **็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ **ใ€‚ +้€š่ฟ‡ โœจ [**่ตžๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๏ผŒ่ฟ™ไบ›ๅ…ฌๅธๅธฎๅŠฉ็กฎไฟๆก†ๆžถๅŠๅ…ถ**็”Ÿๆ€**ไฟๆŒๅฅๅบทๅนถไธ”**ๅฏๆŒ็ปญ**ใ€‚ -### ็”Ÿๆˆไธ€ไธชTypeScript ๅฎขๆˆท็ซฏ +ไป–ไปฌ็š„่ตžๅŠฉไนŸไฝ“็Žฐไบ†ๅฏน FastAPI **็คพๅŒบ**๏ผˆไนŸๅฐฑๆ˜ฏไฝ ๏ผ‰็š„้ซ˜ๅบฆๆ‰ฟ่ฏบ๏ผŒไธไป…ๅ…ณๆณจๆไพ›**ไผ˜็ง€็š„ๆœๅŠก**๏ผŒไนŸๆ”ฏๆŒไธ€ไธช**ๅฅๅฃฎไธ”็น่ฃ็š„ๆก†ๆžถ**โ€”โ€”FastAPIใ€‚๐Ÿ™‡ -็Žฐๅœจๆˆ‘ไปฌๆœ‰ไบ†ๅธฆๆœ‰ๆจกๅž‹็š„ๅบ”็”จ๏ผŒๆˆ‘ไปฌๅฏไปฅไธบๅ‰็ซฏ็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ ใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฐ่ฏ•๏ผš -#### ๅฎ‰่ฃ… `openapi-ts` +* Speakeasy +* Stainless +* liblab -ๆ‚จๅฏไปฅไฝฟ็”จไปฅไธ‹ๅทฅๅ…ทๅœจๅ‰็ซฏไปฃ็ ไธญๅฎ‰่ฃ… `openapi-ts`: +ๅ…ถไธญไธ€ไบ›ๆ–นๆกˆไนŸๅฏ่ƒฝๆ˜ฏๅผ€ๆบ็š„ๆˆ–ๆไพ›ๅ…่ดนๅฑ‚็บง๏ผŒไฝ ๅฏไปฅไธ่Šฑ้’ฑๅฐฑๅ…ˆ่ฏ•็”จใ€‚ๅ…ถไป–ๅ•†ไธš SDK ็”Ÿๆˆๅ™จไนŸๅฏๅœจ็ฝ‘ไธŠๆ‰พๅˆฐใ€‚๐Ÿค“ -
+## ๅˆ›ๅปบไธ€ไธช TypeScript SDK { #create-a-typescript-sdk } -```console -$ npm install @hey-api/openapi-ts --save-dev +ๅ…ˆไปŽไธ€ไธช็ฎ€ๅ•็š„ FastAPI ๅบ”็”จๅผ€ๅง‹๏ผš ----> 100% -``` +{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} -
+่ฏทๆณจๆ„๏ผŒ่ฟ™ไบ›*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จ `Item` ๅ’Œ `ResponseMessage` ๆจกๅž‹ๆฅๅฎšไน‰ๅฎƒไปฌ็š„่ฏทๆฑ‚่ฝฝ่ทๅ’Œๅ“ๅบ”่ฝฝ่ทใ€‚ -#### ็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็  +### API ๆ–‡ๆกฃ { #api-docs } -่ฆ็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ็Žฐๅœจๅฐ†่ฆๅฎ‰่ฃ…็š„ๅ‘ฝไปค่กŒๅบ”็”จ็จ‹ๅบ `openapi-ts`ใ€‚ +่ฎฟ้—ฎ `/docs` ๆ—ถ๏ผŒไฝ ไผš็œ‹ๅˆฐๆœ‰็”จไบŽ่ฏทๆฑ‚ๅ‘้€ๅ’Œๅ“ๅบ”ๆŽฅๆ”ถๆ•ฐๆฎ็š„**ๆจกๅผ**๏ผš -ๅ› ไธบๅฎƒๅฎ‰่ฃ…ๅœจๆœฌๅœฐ้กน็›ฎไธญ๏ผŒๆ‰€ไปฅๆ‚จๅฏ่ƒฝๆ— ๆณ•็›ดๆŽฅไฝฟ็”จๆญคๅ‘ฝไปค๏ผŒไฝ†ๆ‚จๅฏไปฅๅฐ†ๅ…ถๆ”พๅœจ `package.json` ๆ–‡ไปถไธญใ€‚ + -ๅฎƒๅฏ่ƒฝ็œ‹่ตทๆฅๆ˜ฏ่ฟ™ๆ ท็š„: +ไน‹ๆ‰€ไปฅ่ƒฝ็œ‹ๅˆฐ่ฟ™ไบ›ๆจกๅผ๏ผŒๆ˜ฏๅ› ไธบๅฎƒไปฌๅœจๅบ”็”จไธญ็”จๆจกๅž‹ๅฃฐๆ˜Žไบ†ใ€‚ -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} -``` +่ฟ™ไบ›ไฟกๆฏไผšๅŒ…ๅซๅœจๅบ”็”จ็š„ **OpenAPI ๆจกๅผ** ไธญ๏ผŒๅนถๆ˜พ็คบๅœจ API ๆ–‡ๆกฃ้‡Œใ€‚ -ๅœจ่ฟ™้‡ŒๆทปๅŠ  NPM `generate-client` ่„šๆœฌๅŽ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จไปฅไธ‹ๅ‘ฝไปค่ฟ่กŒๅฎƒ: +OpenAPI ไธญๅŒ…ๅซ็š„่ฟ™ไบ›ๆจกๅž‹ไฟกๆฏๅฐฑๆ˜ฏ็”จไบŽ**็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ **็š„ๅŸบ็ก€ใ€‚ -
+### Hey API { #hey-api } -```console -$ npm run generate-client +ๅฝ“ๆˆ‘ไปฌๆœ‰ไบ†ๅธฆๆจกๅž‹็š„ FastAPI ๅบ”็”จๅŽ๏ผŒๅฏไปฅไฝฟ็”จ Hey API ๆฅ็”Ÿๆˆ TypeScript ๅฎขๆˆท็ซฏใ€‚ๆœ€ๅฟซ็š„ๆ–นๅผๆ˜ฏ้€š่ฟ‡ npx๏ผš -frontend-app@1.0.0 generate-client /home/user/code/frontend-app -> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ``` -
+่ฟ™ไผšๅœจ `./src/client` ็”Ÿๆˆไธ€ไธช TypeScript SDKใ€‚ -ๆญคๅ‘ฝไปคๅฐ†ๅœจ `./src/client` ไธญ็”Ÿๆˆไปฃ็ ๏ผŒๅนถๅฐ†ๅœจๅ…ถๅ†…้ƒจไฝฟ็”จ `axios`๏ผˆๅ‰็ซฏHTTPๅบ“๏ผ‰ใ€‚ +ไฝ ๅฏไปฅๅœจๅ…ถๅฎ˜็ฝ‘ไบ†่งฃๅฆ‚ไฝ•ๅฎ‰่ฃ… `@hey-api/openapi-ts`๏ผŒไปฅๅŠ้˜…่ฏป็”Ÿๆˆ็ป“ๆžœ็š„่ฏดๆ˜Žใ€‚ -### ๅฐ่ฏ•ๅฎขๆˆท็ซฏไปฃ็  +### ไฝฟ็”จ SDK { #using-the-sdk } -็Žฐๅœจๆ‚จๅฏไปฅๅฏผๅ…ฅๅนถไฝฟ็”จๅฎขๆˆท็ซฏไปฃ็ ๏ผŒๅฎƒๅฏ่ƒฝ็œ‹่ตทๆฅๅƒ่ฟ™ๆ ท๏ผŒ่ฏทๆณจๆ„๏ผŒๆ‚จๅฏไปฅไธบ่ฟ™ไบ›ๆ–นๆณ•ไฝฟ็”จ่‡ชๅŠจ่กฅๅ…จ๏ผš +็Žฐๅœจไฝ ๅฏไปฅๅฏผๅ…ฅๅนถไฝฟ็”จๅฎขๆˆท็ซฏไปฃ็ ไบ†ใ€‚ๅฎƒๅฏ่ƒฝๆ˜ฏ่ฟ™ๆ ท๏ผŒๅนถไธ”ไฝ ไผšๅ‘็Žฐๆ–นๆณ•ๆœ‰่‡ชๅŠจ่กฅๅ…จ๏ผš -ๆ‚จ่ฟ˜ๅฐ†่‡ชๅŠจ่กฅๅ…จ่ฆๅ‘้€็š„ๆ•ฐๆฎ๏ผš +่ฆๅ‘้€็š„่ฝฝ่ทไนŸไผšๆœ‰่‡ชๅŠจ่กฅๅ…จ๏ผš -/// tip +/// tip | ๆ็คบ -่ฏทๆณจๆ„๏ผŒ `name` ๅ’Œ `price` ็š„่‡ชๅŠจ่กฅๅ…จ๏ผŒๆ˜ฏ้€š่ฟ‡ๅ…ถๅœจ`Item`ๆจกๅž‹(FastAPI)ไธญ็š„ๅฎšไน‰ๅฎž็Žฐ็š„ใ€‚ +่ฏทๆณจๆ„ `name` ๅ’Œ `price` ็š„่‡ชๅŠจ่กฅๅ…จ๏ผŒๅฎƒไปฌๆ˜ฏๅœจ FastAPI ๅบ”็”จไธญ็š„ `Item` ๆจกๅž‹้‡Œๅฎšไน‰็š„ใ€‚ /// -ๅฆ‚ๆžœๅ‘้€็š„ๆ•ฐๆฎๅญ—ๆฎตไธ็ฌฆ๏ผŒไฝ ไนŸไผš็œ‹ๅˆฐ็ผ–่พ‘ๅ™จ็š„้”™่ฏฏๆ็คบ: +ไฝ ๅ‘้€็š„ๆ•ฐๆฎๅฆ‚ๆžœไธ็ฌฆๅˆ่ฆๆฑ‚๏ผŒไผšๅœจ็ผ–่พ‘ๅ™จไธญๆ˜พ็คบๅ†…่”้”™่ฏฏ๏ผš -ๅ“ๅบ”(response)ๅฏน่ฑกไนŸๆ‹ฅๆœ‰่‡ชๅŠจ่กฅๅ…จ: +ๅ“ๅบ”ๅฏน่ฑกๅŒๆ ทๆœ‰่‡ชๅŠจ่กฅๅ…จ๏ผš -## ๅธฆๆœ‰ๆ ‡็ญพ็š„ FastAPI ๅบ”็”จ +## ๅธฆๆœ‰ๆ ‡็ญพ็š„ FastAPI ๅบ”็”จ { #fastapi-app-with-tags } -ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ็š„FastAPIๅบ”็”จ็จ‹ๅบไผšๆ›ดๅคๆ‚๏ผŒไฝ ๅฏ่ƒฝไผšไฝฟ็”จๆ ‡็ญพๆฅๅˆ†้š”ไธๅŒ็ป„็š„*่ทฏๅพ„ๆ“ไฝœ(path operations)*ใ€‚ +ๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ็š„ FastAPI ๅบ”็”จไผšๆ›ดๅคง๏ผŒไฝ ๅฏ่ƒฝไผš็”จๆ ‡็ญพๆฅๅˆ’ๅˆ†ไธๅŒ็ป„็š„*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅๆœ‰ไธ€ไธช็”จ `items` ็š„้ƒจๅˆ†ๅ’Œๅฆไธ€ไธช็”จไบŽ `users` ็š„้ƒจๅˆ†๏ผŒๅฎƒไปฌๅฏไปฅ็”จๆ ‡็ญพๆฅๅˆ†้š”๏ผš +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆœ‰ไธ€ไธช **items** ็›ธๅ…ณ็š„้ƒจๅˆ†ๅ’Œๅฆไธ€ไธช **users** ็›ธๅ…ณ็š„้ƒจๅˆ†๏ผŒๅฎƒไปฌๅฏไปฅ็”จๆ ‡็ญพๆฅๅˆ†้š”๏ผš {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} -### ็”Ÿๆˆๅธฆๆœ‰ๆ ‡็ญพ็š„ TypeScript ๅฎขๆˆท็ซฏ +### ็”Ÿๆˆๅธฆๆ ‡็ญพ็š„ TypeScript ๅฎขๆˆท็ซฏ { #generate-a-typescript-client-with-tags } -ๅฆ‚ๆžœๆ‚จไฝฟ็”จๆ ‡็ญพไธบFastAPIๅบ”็”จ็”Ÿๆˆๅฎขๆˆท็ซฏ๏ผŒๅฎƒ้€šๅธธไนŸไผšๆ นๆฎๆ ‡็ญพๅˆ†ๅ‰ฒๅฎขๆˆท็ซฏไปฃ็ ใ€‚ +ๅฆ‚ๆžœไฝ ไธบไฝฟ็”จไบ†ๆ ‡็ญพ็š„ FastAPI ๅบ”็”จ็”Ÿๆˆๅฎขๆˆท็ซฏ๏ผŒ้€šๅธธไนŸไผšๆ นๆฎๆ ‡็ญพๆฅๆ‹†ๅˆ†ๅฎขๆˆท็ซฏไปฃ็ ใ€‚ -้€š่ฟ‡่ฟ™็งๆ–นๅผ๏ผŒๆ‚จๅฐ†่ƒฝๅคŸไธบๅฎขๆˆท็ซฏไปฃ็ ่ฟ›่กŒๆญฃ็กฎๅœฐๆŽ’ๅบๅ’Œๅˆ†็ป„๏ผš +่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจๅฎขๆˆท็ซฏไปฃ็ ไธญๆŠŠๅ†…ๅฎนๆญฃ็กฎๅœฐ็ป„็ป‡ๅ’Œๅˆ†็ป„๏ผš -ๅœจ่ฟ™ไธชๆกˆไพ‹ไธญ๏ผŒๆ‚จๆœ‰๏ผš +ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒไฝ ไผšๆœ‰๏ผš * `ItemsService` * `UsersService` -### ๅฎขๆˆท็ซฏๆ–นๆณ•ๅ็งฐ +### ๅฎขๆˆท็ซฏๆ–นๆณ•ๅ { #client-method-names } -็Žฐๅœจ็”Ÿๆˆ็š„ๆ–นๆณ•ๅๅƒ `createItemItemsPost` ็œ‹่ตทๆฅไธๅคช็ฎ€ๆด: +็Žฐๅœจ๏ผŒๅƒ `createItemItemsPost` ่ฟ™ๆ ท็š„็”Ÿๆˆๆ–นๆณ•ๅ็œ‹่ตทๆฅไธๅคช็ฎ€ๆด๏ผš ```TypeScript ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -...่ฟ™ๆ˜ฏๅ› ไธบๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จไธบๆฏไธช *่ทฏๅพ„ๆ“ไฝœ* ไฝฟ็”จOpenAPI็š„ๅ†…้ƒจ **ๆ“ไฝœ ID(operation ID)**ใ€‚ +โ€ฆโ€ฆ่ฟ™ๆ˜ฏๅ› ไธบๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จไผšๆŠŠๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„ OpenAPI ๅ†…้ƒจ**ๆ“ไฝœ ID๏ผˆoperation ID๏ผ‰**็”จไฝœๆ–นๆณ•ๅ็š„ไธ€้ƒจๅˆ†ใ€‚ -OpenAPI่ฆๆฑ‚ๆฏไธชๆ“ไฝœ ID ๅœจๆ‰€ๆœ‰ *่ทฏๅพ„ๆ“ไฝœ* ไธญ้ƒฝๆ˜ฏๅ”ฏไธ€็š„๏ผŒๅ› ๆญค FastAPI ไฝฟ็”จ**ๅ‡ฝๆ•ฐๅ**ใ€**่ทฏๅพ„**ๅ’Œ**HTTPๆ–นๆณ•/ๆ“ไฝœ**ๆฅ็”Ÿๆˆๆญคๆ“ไฝœID๏ผŒๅ› ไธบ่ฟ™ๆ ทๅฏไปฅ็กฎไฟ่ฟ™ไบ›ๆ“ไฝœ ID ๆ˜ฏๅ”ฏไธ€็š„ใ€‚ +OpenAPI ่ฆๆฑ‚ๆฏไธชๆ“ไฝœ ID ๅœจๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ไธญ้ƒฝๆ˜ฏๅ”ฏไธ€็š„๏ผŒๅ› ๆญค FastAPI ไผšไฝฟ็”จ**ๅ‡ฝๆ•ฐๅ**ใ€**่ทฏๅพ„**ๅ’Œ**HTTP ๆ–นๆณ•/ๆ“ไฝœ**ๆฅ็”Ÿๆˆๆ“ไฝœ ID๏ผŒไปฅ็กฎไฟๅ…ถๅ”ฏไธ€ๆ€งใ€‚ -ไฝ†ๆŽฅไธ‹ๆฅๆˆ‘ไผšๅ‘Š่ฏ‰ไฝ ๅฆ‚ไฝ•ๆ”น่ฟ›ใ€‚ ๐Ÿค“ +ๆŽฅไธ‹ๆฅๆˆ‘ไผšๅ‘Š่ฏ‰ไฝ ๅฆ‚ไฝ•ๆ”น่ฟ›ใ€‚๐Ÿค“ -## ่‡ชๅฎšไน‰ๆ“ไฝœIDๅ’Œๆ›ดๅฅฝ็š„ๆ–นๆณ•ๅ +## ่‡ชๅฎšไน‰ๆ“ไฝœ ID ไธŽๆ›ดๅฅฝ็š„ๆ–นๆณ•ๅ { #custom-operation-ids-and-better-method-names } -ๆ‚จๅฏไปฅ**ไฟฎๆ”น**่ฟ™ไบ›ๆ“ไฝœID็š„**็”Ÿๆˆ**ๆ–นๅผ๏ผŒไปฅไฝฟๅ…ถๆ›ด็ฎ€ๆด๏ผŒๅนถๅœจๅฎขๆˆท็ซฏไธญๅ…ทๆœ‰**ๆ›ด็ฎ€ๆด็š„ๆ–นๆณ•ๅ็งฐ**ใ€‚ +ไฝ ๅฏไปฅ**ไฟฎๆ”น**่ฟ™ไบ›ๆ“ไฝœ ID ็š„**็”Ÿๆˆ**ๆ–นๅผ๏ผŒไฝฟไน‹ๆ›ด็ฎ€ๅ•๏ผŒไปŽ่€Œๅœจๅฎขๆˆท็ซฏไธญๅพ—ๅˆฐ**ๆ›ด็ฎ€ๆด็š„ๆ–นๆณ•ๅ**ใ€‚ -ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฟ…้กป็กฎไฟๆฏไธชๆ“ไฝœIDๅœจๅ…ถไป–ๆ–น้ขๆ˜ฏ**ๅ”ฏไธ€**็š„ใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ้œ€่ฆ็”จๅ…ถไป–ๆ–นๅผ็กฎไฟๆฏไธชๆ“ไฝœ ID ไพ็„ถๆ˜ฏ**ๅ”ฏไธ€**็š„ใ€‚ -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅ็กฎไฟๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*้ƒฝๆœ‰ไธ€ไธชๆ ‡็ญพ๏ผŒ็„ถๅŽๆ นๆฎ**ๆ ‡็ญพ**ๅ’Œ*่ทฏๅพ„ๆ“ไฝœ***ๅ็งฐ**๏ผˆๅ‡ฝๆ•ฐๅ๏ผ‰ๆฅ็”Ÿๆˆๆ“ไฝœIDใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็กฎไฟๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*้ƒฝๆœ‰ไธ€ไธชๆ ‡็ญพ๏ผŒ็„ถๅŽๅŸบไบŽ**ๆ ‡็ญพ**ๅ’Œ*่ทฏๅพ„ๆ“ไฝœ***ๅ็งฐ**๏ผˆๅ‡ฝๆ•ฐๅ๏ผ‰ๆฅ็”Ÿๆˆๆ“ไฝœ IDใ€‚ -### ่‡ชๅฎšไน‰็”Ÿๆˆๅ”ฏไธ€IDๅ‡ฝๆ•ฐ +### ่‡ชๅฎšไน‰ๅ”ฏไธ€ ID ็”Ÿๆˆๅ‡ฝๆ•ฐ { #custom-generate-unique-id-function } -FastAPIไธบๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จไธ€ไธช**ๅ”ฏไธ€ID**๏ผŒๅฎƒ็”จไบŽ**ๆ“ไฝœID**๏ผŒไนŸ็”จไบŽไปปไฝ•ๆ‰€้œ€่‡ชๅฎšไน‰ๆจกๅž‹็š„ๅ็งฐ๏ผŒ็”จไบŽ่ฏทๆฑ‚ๆˆ–ๅ“ๅบ”ใ€‚ +FastAPI ไธบๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จไธ€ไธช**ๅ”ฏไธ€ ID**๏ผŒๅฎƒๆ—ข็”จไบŽ**ๆ“ไฝœ ID**๏ผŒไนŸ็”จไบŽ่ฏทๆฑ‚ๆˆ–ๅ“ๅบ”้‡Œไปปไฝ•้œ€่ฆ็š„่‡ชๅฎšไน‰ๆจกๅž‹ๅ็งฐใ€‚ -ไฝ ๅฏไปฅ่‡ชๅฎšไน‰่ฏฅๅ‡ฝๆ•ฐใ€‚ๅฎƒๆŽฅๅ—ไธ€ไธช `APIRoute` ๅฏน่ฑกไฝœไธบ่พ“ๅ…ฅ๏ผŒๅนถ่พ“ๅ‡บไธ€ไธชๅญ—็ฌฆไธฒใ€‚ +ไฝ ๅฏไปฅ่‡ชๅฎšไน‰่ฟ™ไธชๅ‡ฝๆ•ฐใ€‚ๅฎƒๆŽฅๆ”ถไธ€ไธช `APIRoute` ๅนถ่ฟ”ๅ›žไธ€ไธชๅญ—็ฌฆไธฒใ€‚ -ไพ‹ๅฆ‚๏ผŒไปฅไธ‹ๆ˜ฏไธ€ไธช็คบไพ‹๏ผŒๅฎƒไฝฟ็”จ็ฌฌไธ€ไธชๆ ‡็ญพ๏ผˆไฝ ๅฏ่ƒฝๅชๆœ‰ไธ€ไธชๆ ‡็ญพ๏ผ‰ๅ’Œ*่ทฏๅพ„ๆ“ไฝœ*ๅ็งฐ๏ผˆๅ‡ฝๆ•ฐๅ๏ผ‰ใ€‚ +ไพ‹ๅฆ‚๏ผŒ่ฟ™้‡Œไฝฟ็”จ็ฌฌไธ€ไธชๆ ‡็ญพ๏ผˆไฝ ๅพˆๅฏ่ƒฝๅชๆœ‰ไธ€ไธชๆ ‡็ญพ๏ผ‰ๅ’Œ*่ทฏๅพ„ๆ“ไฝœ*ๅ็งฐ๏ผˆๅ‡ฝๆ•ฐๅ๏ผ‰ใ€‚ -็„ถๅŽ๏ผŒไฝ ๅฏไปฅๅฐ†่ฟ™ไธช่‡ชๅฎšไน‰ๅ‡ฝๆ•ฐไฝœไธบ `generate_unique_id_function` ๅ‚ๆ•ฐไผ ้€’็ป™ **FastAPI**: +็„ถๅŽไฝ ๅฏไปฅๆŠŠ่ฟ™ไธช่‡ชๅฎšไน‰ๅ‡ฝๆ•ฐ้€š่ฟ‡ `generate_unique_id_function` ๅ‚ๆ•ฐไผ ็ป™ **FastAPI**๏ผš {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} -### ไฝฟ็”จ่‡ชๅฎšไน‰ๆ“ไฝœID็”ŸๆˆTypeScriptๅฎขๆˆท็ซฏ +### ไฝฟ็”จ่‡ชๅฎšไน‰ๆ“ไฝœ ID ็”Ÿๆˆ TypeScript ๅฎขๆˆท็ซฏ { #generate-a-typescript-client-with-custom-operation-ids } -็Žฐๅœจ๏ผŒๅฆ‚ๆžœไฝ ๅ†ๆฌก็”Ÿๆˆๅฎขๆˆท็ซฏ๏ผŒไฝ ไผšๅ‘็Žฐๅฎƒๅ…ทๆœ‰ๆ”นๅ–„็š„ๆ–นๆณ•ๅ็งฐ๏ผš +็Žฐๅœจๅ†ๆฌก็”Ÿๆˆๅฎขๆˆท็ซฏ๏ผŒไฝ ไผš็œ‹ๅˆฐๆ–นๆณ•ๅๅทฒ็ปๆ”น่ฟ›๏ผš -ๆญฃๅฆ‚ไฝ ๆ‰€่ง๏ผŒ็Žฐๅœจๆ–นๆณ•ๅ็งฐไธญๅชๅŒ…ๅซๆ ‡็ญพๅ’Œๅ‡ฝๆ•ฐๅ๏ผŒไธๅ†ๅŒ…ๅซURL่ทฏๅพ„ๅ’ŒHTTPๆ“ไฝœ็š„ไฟกๆฏใ€‚ +ๅฆ‚ไฝ ๆ‰€่ง๏ผŒๆ–นๆณ•ๅ็Žฐๅœจ็”ฑๆ ‡็ญพๅ’Œๅ‡ฝๆ•ฐๅ็ป„ๆˆ๏ผŒไธๅ†ๅŒ…ๅซ URL ่ทฏๅพ„ๅ’Œ HTTP ๆ“ไฝœ็š„ไฟกๆฏใ€‚ + +### ไธบๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จ้ข„ๅค„็† OpenAPI ่ง„่Œƒ { #preprocess-the-openapi-specification-for-the-client-generator } -### ้ข„ๅค„็†็”จไบŽๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จ็š„OpenAPI่ง„่Œƒ +็”Ÿๆˆ็š„ไปฃ็ ไธญไปๆœ‰ไธ€ไบ›**้‡ๅคไฟกๆฏ**ใ€‚ -็”Ÿๆˆ็š„ไปฃ็ ไป็„ถๅญ˜ๅœจไธ€ไบ›**้‡ๅค็š„ไฟกๆฏ**ใ€‚ +ๆˆ‘ไปฌๅทฒ็ป็Ÿฅ้“่ฟ™ไธชๆ–นๆณ•ไธŽ **items** ๆœ‰ๅ…ณ๏ผŒๅ› ไธบๅฎƒไฝไบŽ `ItemsService`๏ผˆๆฅ่‡ชๆ ‡็ญพ๏ผ‰๏ผŒไฝ†ๆ–นๆณ•ๅ้‡Œไป็„ถๅธฆๆœ‰ๆ ‡็ญพๅๅ‰็ผ€ใ€‚๐Ÿ˜• -ๆˆ‘ไปฌๅทฒ็ป็Ÿฅ้“่ฏฅๆ–นๆณ•ไธŽ **items** ็›ธๅ…ณ๏ผŒๅ› ไธบๅฎƒๅœจ `ItemsService` ไธญ๏ผˆไปŽๆ ‡็ญพไธญ่Žทๅ–๏ผ‰๏ผŒไฝ†ๆ–นๆณ•ๅไธญไป็„ถๆœ‰ๆ ‡็ญพๅไฝœไธบๅ‰็ผ€ใ€‚๐Ÿ˜• +้€šๅธธๆˆ‘ไปฌไป็„ถๅธŒๆœ›ๅœจ OpenAPI ไธญไฟ็•™ๅฎƒ๏ผŒไปฅ็กฎไฟๆ“ไฝœ ID ็š„**ๅ”ฏไธ€ๆ€ง**ใ€‚ -ไธ€่ˆฌๆƒ…ๅ†ตไธ‹ๅฏนไบŽOpenAPI๏ผŒๆˆ‘ไปฌๅฏ่ƒฝไป็„ถๅธŒๆœ›ไฟ็•™ๅฎƒ๏ผŒๅ› ไธบ่ฟ™ๅฐ†็กฎไฟๆ“ไฝœIDๆ˜ฏ**ๅ”ฏไธ€็š„**ใ€‚ +ไฝ†ๅฏนไบŽ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏ๏ผŒๆˆ‘ไปฌๅฏไปฅๅœจ็”Ÿๆˆไน‹ๅ‰**ไฟฎๆ”น** OpenAPI ็š„ๆ“ไฝœ ID๏ผŒๅชๆ˜ฏไธบไบ†่ฎฉๆ–นๆณ•ๅๆ›ด็พŽ่ง‚ใ€ๆ›ด**็ฎ€ๆด**ใ€‚ -ไฝ†ๅฏนไบŽ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏ๏ผŒๆˆ‘ไปฌๅฏไปฅๅœจ็”Ÿๆˆๅฎขๆˆท็ซฏไน‹ๅ‰**ไฟฎๆ”น** OpenAPI ๆ“ไฝœID๏ผŒไปฅไฝฟๆ–นๆณ•ๅ็งฐๆ›ดๅŠ ็พŽ่ง‚ๅ’Œ**็ฎ€ๆด**ใ€‚ +ๆˆ‘ไปฌๅฏไปฅๆŠŠ OpenAPI JSON ไธ‹่ฝฝๅˆฐ `openapi.json` ๆ–‡ไปถไธญ๏ผŒ็„ถๅŽ็”จๅฆ‚ไธ‹่„šๆœฌ**็งป้™ค่ฟ™ไธชๆ ‡็ญพๅ‰็ผ€**๏ผš -ๆˆ‘ไปฌๅฏไปฅๅฐ† OpenAPI JSON ไธ‹่ฝฝๅˆฐไธ€ไธชๅไธบ`openapi.json`็š„ๆ–‡ไปถไธญ๏ผŒ็„ถๅŽไฝฟ็”จไปฅไธ‹่„šๆœฌ**ๅˆ ้™คๆญคๅ‰็ผ€็š„ๆ ‡็ญพ**๏ผš +{* ../../docs_src/generate_clients/tutorial004_py39.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` -{* ../../docs_src/generate_clients/tutorial004.py *} +//// -้€š่ฟ‡่ฟ™ๆ ทๅš๏ผŒๆ“ไฝœIDๅฐ†ไปŽ็ฑปไผผไบŽ `items-get_items` ็š„ๅ็งฐ้‡ๅ‘ฝๅไธบ `get_items` ๏ผŒ่ฟ™ๆ ทๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จๅฐฑๅฏไปฅ็”Ÿๆˆๆ›ด็ฎ€ๆด็š„ๆ–นๆณ•ๅ็งฐใ€‚ +่ฟ™ๆ ท๏ผŒๆ“ไฝœ ID ไผšไปŽ `items-get_items` ไน‹็ฑป็š„ๅๅญ—้‡ๅ‘ฝๅไธบ `get_items`๏ผŒไปŽ่€Œ่ฎฉๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จ็”Ÿๆˆๆ›ด็ฎ€ๆด็š„ๆ–นๆณ•ๅใ€‚ -### ไฝฟ็”จ้ข„ๅค„็†็š„OpenAPI็”ŸๆˆTypeScriptๅฎขๆˆท็ซฏ +### ไฝฟ็”จ้ข„ๅค„็†ๅŽ็š„ OpenAPI ็”Ÿๆˆ TypeScript ๅฎขๆˆท็ซฏ { #generate-a-typescript-client-with-the-preprocessed-openapi } -็Žฐๅœจ๏ผŒ็”ฑไบŽๆœ€็ปˆ็ป“ๆžœไฟๅญ˜ๅœจๆ–‡ไปถopenapi.jsonไธญ๏ผŒไฝ ๅฏไปฅไฟฎๆ”น package.json ๆ–‡ไปถไปฅไฝฟ็”จๆญคๆœฌๅœฐๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚๏ผš +ๅ› ไธบๆœ€็ปˆ็ป“ๆžœ็Žฐๅœจไฟๅญ˜ๅœจ `openapi.json` ไธญ๏ผŒไฝ ้œ€่ฆๆ›ดๆ–ฐ่พ“ๅ…ฅไฝ็ฝฎ๏ผš -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client ``` -็”Ÿๆˆๆ–ฐ็š„ๅฎขๆˆท็ซฏไน‹ๅŽ๏ผŒไฝ ็Žฐๅœจๅฐ†ๆ‹ฅๆœ‰**ๆธ…ๆ™ฐ็š„ๆ–นๆณ•ๅ็งฐ**๏ผŒๅ…ทๅค‡**่‡ชๅŠจ่กฅๅ…จ**ใ€**้”™่ฏฏๆ็คบ**็ญ‰ๅŠŸ่ƒฝ๏ผš +็”Ÿๆˆๆ–ฐๅฎขๆˆท็ซฏๅŽ๏ผŒไฝ ๅฐ†ๆ‹ฅๆœ‰**็ฎ€ๆด็š„ๆ–นๆณ•ๅ**๏ผŒๅนถๅ…ทๅค‡**่‡ชๅŠจ่กฅๅ…จ**ใ€**ๅ†…่”้”™่ฏฏ**็ญ‰ๅŠŸ่ƒฝ๏ผš -## ไผ˜็‚น +## ไผ˜็‚น { #benefits } -ๅฝ“ไฝฟ็”จ่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏๆ—ถ๏ผŒไฝ ๅฐ†่Žทๅพ—ไปฅไธ‹็š„่‡ชๅŠจ่กฅๅ…จๅŠŸ่ƒฝ๏ผš +ไฝฟ็”จ่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏๆ—ถ๏ผŒไฝ ไผš่Žทๅพ—ไปฅไธ‹ๅ†…ๅฎน็š„**่‡ชๅŠจ่กฅๅ…จ**๏ผš -* ๆ–นๆณ•ใ€‚ -* ่ฏทๆฑ‚ไฝ“ไธญ็š„ๆ•ฐๆฎใ€ๆŸฅ่ฏขๅ‚ๆ•ฐ็ญ‰ใ€‚ -* ๅ“ๅบ”ๆ•ฐๆฎใ€‚ +* ๆ–นๆณ• +* ่ฏทๆฑ‚ไฝ“ไธญ็š„ๆ•ฐๆฎใ€ๆŸฅ่ฏขๅ‚ๆ•ฐ็ญ‰ +* ๅ“ๅบ”ๆ•ฐๆฎ -ไฝ ่ฟ˜ๅฐ†่Žทๅพ—้’ˆๅฏนๆ‰€ๆœ‰ๅ†…ๅฎน็š„้”™่ฏฏๆ็คบใ€‚ +ไฝ ่ฟ˜ไผšไธบๆ‰€ๆœ‰ๅ†…ๅฎน่Žทๅพ—**ๅ†…่”้”™่ฏฏ**ใ€‚ -ๆฏๅฝ“ไฝ ๆ›ดๆ–ฐๅŽ็ซฏไปฃ็ ๅนถ**้‡ๆ–ฐ็”Ÿๆˆ**ๅ‰็ซฏไปฃ็ ๆ—ถ๏ผŒๆ–ฐ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅฐ†ไฝœไธบๆ–นๆณ•ๅฏ็”จ๏ผŒๆ—ง็š„ๆ–นๆณ•ๅฐ†่ขซๅˆ ้™ค๏ผŒๅนถไธ”ๅ…ถไป–ไปปไฝ•ๆ›ดๆ”นๅฐ†ๅๆ˜ ๅœจ็”Ÿๆˆ็š„ไปฃ็ ไธญใ€‚ ๐Ÿค“ +ๆฏๅฝ“ไฝ ๆ›ดๆ–ฐๅŽ็ซฏไปฃ็ ๅนถ**้‡ๆ–ฐ็”Ÿๆˆ**ๅ‰็ซฏๆ—ถ๏ผŒๆ–ฐ็š„*่ทฏๅพ„ๆ“ไฝœ*ไผšไฝœไธบๆ–นๆณ•ๅฏ็”จ๏ผŒๆ—ง็š„ๆ–นๆณ•ไผš่ขซ็งป้™ค๏ผŒๅ…ถไป–ไปปไฝ•ๆ›ดๆ”น้ƒฝไผšๅๆ˜ ๅˆฐ็”Ÿๆˆ็š„ไปฃ็ ไธญใ€‚๐Ÿค“ -่ฟ™ไนŸๆ„ๅ‘ณ็€ๅฆ‚ๆžœๆœ‰ไปปไฝ•ๆ›ดๆ”น๏ผŒๅฎƒๅฐ†่‡ชๅŠจ**ๅๆ˜ **ๅœจๅฎขๆˆท็ซฏไปฃ็ ไธญใ€‚ๅฆ‚ๆžœไฝ **ๆž„ๅปบ**ๅฎขๆˆท็ซฏ๏ผŒๅœจไฝฟ็”จ็š„ๆ•ฐๆฎไธŠๅญ˜ๅœจ**ไธๅŒน้…**ๆ—ถ๏ผŒๅฎƒๅฐ†ๆŠฅ้”™ใ€‚ +่ฟ™ไนŸๆ„ๅ‘ณ็€ๅฆ‚ๆžœๆœ‰ไปปไฝ•ๅ˜ๆ›ด๏ผŒๅฎƒไผš่‡ชๅŠจ**ๅๆ˜ **ๅˆฐๅฎขๆˆท็ซฏไปฃ็ ไธญใ€‚่€Œๅฝ“ไฝ **ๆž„ๅปบ**ๅฎขๆˆท็ซฏๆ—ถ๏ผŒๅฆ‚ๆžœๆ‰€็”จๆ•ฐๆฎๅญ˜ๅœจไปปไฝ•**ไธๅŒน้…**๏ผŒๅฎƒไผš็›ดๆŽฅๆŠฅ้”™ใ€‚ -ๅ› ๆญค๏ผŒไฝ ๅฐ†ๅœจๅผ€ๅ‘ๅ‘จๆœŸ็š„ๆ—ฉๆœŸ**ๆฃ€ๆต‹ๅˆฐ่ฎธๅคš้”™่ฏฏ**๏ผŒ่€Œไธๅฟ…็ญ‰ๅพ…้”™่ฏฏๅœจ็”Ÿไบง็Žฏๅขƒไธญๅ‘ๆœ€็ปˆ็”จๆˆทๅฑ•็คบ๏ผŒ็„ถๅŽๅฐ่ฏ•่ฐƒ่ฏ•้—ฎ้ข˜ๆ‰€ๅœจใ€‚ โœจ +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅœจๅผ€ๅ‘ๅ‘จๆœŸ็š„ๆ—ฉๆœŸๅฐฑ**ๅ‘็Žฐ่ฎธๅคš้”™่ฏฏ**๏ผŒ่€Œไธๅฟ…็ญ‰ๅˆฐ้”™่ฏฏๅœจ็”Ÿไบง็Žฏๅขƒไธญๆšด้œฒ็ป™ๆœ€็ปˆ็”จๆˆทๅŽๅ†ๅŽป่ฐƒ่ฏ•้—ฎ้ข˜ๆ‰€ๅœจใ€‚โœจ diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md index 6525802fca..610c187137 100644 --- a/docs/zh/docs/advanced/index.md +++ b/docs/zh/docs/advanced/index.md @@ -1,21 +1,21 @@ -# ้ซ˜็บง็”จๆˆทๆŒ‡ๅ— +# ้ซ˜็บง็”จๆˆทๆŒ‡ๅ— { #advanced-user-guide } -## ้ขๅค–็‰นๆ€ง +## ้™„ๅŠ ๅŠŸ่ƒฝ { #additional-features } -ไธป่ฆ็š„ๆ•™็จ‹ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank} ๅบ”่ฏฅ่ถณไปฅ่ฎฉไฝ ไบ†่งฃ **FastAPI** ็š„ๆ‰€ๆœ‰ไธป่ฆ็‰นๆ€งใ€‚ +ไธป่ฆ็š„[ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank}่ถณไปฅๅธฆไฝ ไบ†่งฃ **FastAPI** ็š„ๆ‰€ๆœ‰ไธป่ฆ็‰นๆ€งใ€‚ -ไฝ ไผšๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญไบ†่งฃๅˆฐๅ…ถไป–็š„้€‰้กนใ€้…็ฝฎไปฅๅŠ้ขๅค–็š„็‰นๆ€งใ€‚ +ๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญ๏ผŒไฝ ๅฐ†็œ‹ๅˆฐๅ…ถไป–้€‰้กนใ€้…็ฝฎๅ’Œ้™„ๅŠ ๅŠŸ่ƒฝใ€‚ -/// tip +/// tip | ๆ็คบ -ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚**ๅนถไธไธ€ๅฎšๆ˜ฏ**ใ€Œ้ซ˜็บง็š„ใ€ใ€‚ +ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธไธ€ๅฎšๆ˜ฏโ€œ้ซ˜็บงโ€็š„ใ€‚ -่€Œไธ”ๅฏนไบŽไฝ ็š„ไฝฟ็”จๅœบๆ™ฏๆฅ่ฏด๏ผŒ่งฃๅ†ณๆ–นๆกˆๅพˆๅฏ่ƒฝๅฐฑๅœจๅ…ถไธญใ€‚ +ๅฏนไบŽไฝ ็š„็”จไพ‹๏ผŒ่งฃๅ†ณๆ–นๆกˆๅพˆๅฏ่ƒฝๅฐฑๅœจๅ…ถไธญไน‹ไธ€ใ€‚ /// -## ๅ…ˆ้˜…่ฏปๆ•™็จ‹ +## ๅ…ˆ้˜…่ฏปๆ•™็จ‹ { #read-the-tutorial-first } -ไฝ ๅฏ่ƒฝไปไผš็”จๅˆฐ **FastAPI** ไธปๆ•™็จ‹ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank} ไธญ็š„ๅคงๅคšๆ•ฐ็‰นๆ€งใ€‚ +ไป…ๅ‡ญไธป่ฆ[ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank}ไธญ็š„็Ÿฅ่ฏ†๏ผŒไฝ ๅทฒ็ปๅฏไปฅไฝฟ็”จ **FastAPI** ็š„ๅคงๅคšๆ•ฐๅŠŸ่ƒฝใ€‚ -ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ๆˆ‘ไปฌ่ฎคไธบไฝ ๅทฒ็ป่ฏป่ฟ‡ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank}๏ผŒๅนถไธ”ๅ‡่ฎพไฝ ๅทฒ็ป็Ÿฅๆ™“ๅ…ถไธญไธป่ฆๆ€ๆƒณใ€‚ +ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚้ป˜่ฎคไฝ ๅทฒ็ป่ฏป่ฟ‡ๅฎƒ๏ผŒๅนถ็†่งฃๅ…ถไธญ็š„ๆ ธๅฟƒๆฆ‚ๅฟตใ€‚ diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md index 65e8c183f2..108bbbb5c1 100644 --- a/docs/zh/docs/advanced/middleware.md +++ b/docs/zh/docs/advanced/middleware.md @@ -1,4 +1,4 @@ -# ้ซ˜็บงไธญ้—ดไปถ +# ้ซ˜็บงไธญ้—ดไปถ { #advanced-middleware } ็”จๆˆทๆŒ‡ๅ—ไป‹็ปไบ†ๅฆ‚ไฝ•ไธบๅบ”็”จๆทปๅŠ [่‡ชๅฎšไน‰ไธญ้—ดไปถ](../tutorial/middleware.md){.internal-link target=_blank} ใ€‚ @@ -6,9 +6,9 @@ ๆœฌ็ซ ๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จๅ…ถๅฎƒไธญ้—ดไปถใ€‚ -## ๆทปๅŠ  ASGI ไธญ้—ดไปถ +## ๆทปๅŠ  ASGI ไธญ้—ดไปถ { #adding-asgi-middlewares } -ๅ› ไธบ **FastAPI** ๅŸบไบŽ Starlette๏ผŒไธ”ๆ‰ง่กŒ ASGI ่ง„่Œƒ๏ผŒๆ‰€ไปฅๅฏไปฅไฝฟ็”จไปปๆ„ ASGI ไธญ้—ดไปถใ€‚ +ๅ› ไธบ **FastAPI** ๅŸบไบŽ Starlette๏ผŒไธ”ๆ‰ง่กŒ ASGI ่ง„่Œƒ๏ผŒๆ‰€ไปฅๅฏไปฅไฝฟ็”จไปปๆ„ ASGI ไธญ้—ดไปถใ€‚ ไธญ้—ดไปถไธๅฟ…ๆ˜ฏไธ“ไธบ FastAPI ๆˆ– Starlette ๅฎšๅˆถ็š„๏ผŒๅช่ฆ้ตๅพช ASGI ่ง„่Œƒๅณๅฏใ€‚ @@ -39,11 +39,11 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") `app.add_middleware()` ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐๆ˜ฏไธญ้—ดไปถ็š„็ฑป๏ผŒๅ…ถๅฎƒๅ‚ๆ•ฐๅˆ™ๆ˜ฏ่ฆไผ ้€’็ป™ไธญ้—ดไปถ็š„ๅ‚ๆ•ฐใ€‚ -## ้›†ๆˆไธญ้—ดไปถ +## ้›†ๆˆไธญ้—ดไปถ { #integrated-middlewares } **FastAPI** ไธบๅธธ่ง็”จไพ‹ๆไพ›ไบ†ไธ€ไบ›ไธญ้—ดไปถ๏ผŒไธ‹้ขไป‹็ปๆ€Žไนˆไฝฟ็”จ่ฟ™ไบ›ไธญ้—ดไปถใ€‚ -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ ไปฅไธ‹ๅ‡ ไธช็คบไพ‹ไธญไนŸๅฏไปฅไฝฟ็”จ `from starlette.middleware.something import SomethingMiddleware`ใ€‚ @@ -51,45 +51,47 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") /// -## `HTTPSRedirectMiddleware` +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } ๅผบๅˆถๆ‰€ๆœ‰ไผ ๅ…ฅ่ฏทๆฑ‚ๅฟ…้กปๆ˜ฏ `https` ๆˆ– `wss`ใ€‚ ไปปไฝ•ไผ ๅ‘ `http` ๆˆ– `ws` ็š„่ฏทๆฑ‚้ƒฝไผš่ขซ้‡ๅฎšๅ‘่‡ณๅฎ‰ๅ…จๆ–นๆกˆใ€‚ -{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} -## `TrustedHostMiddleware` +## `TrustedHostMiddleware` { #trustedhostmiddleware } ๅผบๅˆถๆ‰€ๆœ‰ไผ ๅ…ฅ่ฏทๆฑ‚้ƒฝๅฟ…้กปๆญฃ็กฎ่ฎพ็ฝฎ `Host` ่ฏทๆฑ‚ๅคด๏ผŒไปฅ้˜ฒ HTTP ไธปๆœบๅคดๆ”ปๅ‡ปใ€‚ -{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} ๆ”ฏๆŒไปฅไธ‹ๅ‚ๆ•ฐ๏ผš -* `allowed_hosts` - ๅ…่ฎธ็š„ๅŸŸๅ๏ผˆไธปๆœบๅ๏ผ‰ๅˆ—่กจใ€‚`*.example.com` ็ญ‰้€š้…็ฌฆๅŸŸๅๅฏไปฅๅŒน้…ๅญๅŸŸๅ๏ผŒๆˆ–ไฝฟ็”จ `allowed_hosts=["*"]` ๅ…่ฎธไปปๆ„ไธปๆœบๅ๏ผŒๆˆ–็œ็•ฅไธญ้—ดไปถใ€‚ +* `allowed_hosts` - ๅ…่ฎธ็š„ๅŸŸๅ๏ผˆไธปๆœบๅ๏ผ‰ๅˆ—่กจใ€‚`*.example.com` ็ญ‰้€š้…็ฌฆๅŸŸๅๅฏไปฅๅŒน้…ๅญๅŸŸๅใ€‚่‹ฅ่ฆๅ…่ฎธไปปๆ„ไธปๆœบๅ๏ผŒๅฏไฝฟ็”จ `allowed_hosts=["*"]` ๆˆ–็œ็•ฅๆญคไธญ้—ดไปถใ€‚ +* `www_redirect` - ่‹ฅ่ฎพ็ฝฎไธบ `True`๏ผŒๅฏนๅ…่ฎธไธปๆœบ็š„้ž www ็‰ˆๆœฌ็š„่ฏทๆฑ‚ๅฐ†่ขซ้‡ๅฎšๅ‘ๅˆฐๅ…ถ www ็‰ˆๆœฌใ€‚้ป˜่ฎคไธบ `True`ใ€‚ ๅฆ‚ๆžœไผ ๅ…ฅ็š„่ฏทๆฑ‚ๆฒกๆœ‰้€š่ฟ‡้ชŒ่ฏ๏ผŒๅˆ™ๅ‘้€ `400` ๅ“ๅบ”ใ€‚ -## `GZipMiddleware` +## `GZipMiddleware` { #gzipmiddleware } -ๅค„็† `Accept-Encoding` ่ฏทๆฑ‚ๅคดไธญๅŒ…ๅซ `gzip` ่ฏทๆฑ‚็š„ GZip ๅ“ๅบ”ใ€‚ +ๅค„็† `Accept-Encoding` ่ฏทๆฑ‚ๅคดไธญๅŒ…ๅซ `"gzip"` ่ฏทๆฑ‚็š„ GZip ๅ“ๅบ”ใ€‚ ไธญ้—ดไปถไผšๅค„็†ๆ ‡ๅ‡†ๅ“ๅบ”ไธŽๆตๅ“ๅบ”ใ€‚ -{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} ๆ”ฏๆŒไปฅไธ‹ๅ‚ๆ•ฐ๏ผš -* `minimum_size` - ๅฐไบŽๆœ€ๅฐๅญ—่Š‚็š„ๅ“ๅบ”ไธไฝฟ็”จ GZipใ€‚ ้ป˜่ฎคๅ€ผๆ˜ฏ `500`ใ€‚ +* `minimum_size` - ๅฐไบŽ่ฏฅๆœ€ๅฐๅญ—่Š‚ๆ•ฐ็š„ๅ“ๅบ”ไธไฝฟ็”จ GZipใ€‚้ป˜่ฎคๅ€ผๆ˜ฏ `500`ใ€‚ +* `compresslevel` - GZip ๅŽ‹็ผฉไฝฟ็”จ็š„็บงๅˆซ๏ผŒไธบ 1 ๅˆฐ 9 ็š„ๆ•ดๆ•ฐใ€‚้ป˜่ฎคไธบ `9`ใ€‚ๅ€ผ่ถŠไฝŽๅŽ‹็ผฉ่ถŠๅฟซไฝ†ๆ–‡ไปถๆ›ดๅคง๏ผŒๅ€ผ่ถŠ้ซ˜ๅŽ‹็ผฉ่ถŠๆ…ขไฝ†ๆ–‡ไปถๆ›ดๅฐใ€‚ -## ๅ…ถๅฎƒไธญ้—ดไปถ +## ๅ…ถๅฎƒไธญ้—ดไปถ { #other-middlewares } ้™คไบ†ไธŠ่ฟฐไธญ้—ดไปถๅค–๏ผŒFastAPI ่ฟ˜ๆ”ฏๆŒๅ…ถๅฎƒASGI ไธญ้—ดไปถใ€‚ ไพ‹ๅฆ‚๏ผš -* Uvicorn ็š„ย `ProxyHeadersMiddleware` +* Uvicorn ็š„ `ProxyHeadersMiddleware` * MessagePack -ๅ…ถๅฎƒๅฏ็”จไธญ้—ดไปถ่ฏฆ่ง Starletteย ๅฎ˜ๆกฃย -ย ย ไธญ้—ดไปถ ๅŠ ASGI Awesome ๅˆ—่กจใ€‚ +ๅ…ถๅฎƒๅฏ็”จไธญ้—ดไปถ่ฏฆ่ง Starlette ๅฎ˜ๆกฃ - ไธญ้—ดไปถ ๅŠ ASGI Awesome ๅˆ—่กจใ€‚ diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md index f021eb10ae..6e8df68aef 100644 --- a/docs/zh/docs/advanced/openapi-callbacks.md +++ b/docs/zh/docs/advanced/openapi-callbacks.md @@ -1,12 +1,12 @@ -# OpenAPI ๅ›ž่ฐƒ +# OpenAPI ๅ›ž่ฐƒ { #openapi-callbacks } -ๆ‚จๅฏไปฅๅˆ›ๅปบ่งฆๅ‘ๅค–้ƒจ API ่ฏทๆฑ‚็š„*่ทฏๅพ„ๆ“ไฝœ* API๏ผŒ่ฟ™ไธชๅค–้ƒจ API ๅฏไปฅๆ˜ฏๅˆซไบบๅˆ›ๅปบ็š„๏ผŒไนŸๅฏไปฅๆ˜ฏ็”ฑๆ‚จ่‡ชๅทฑๅˆ›ๅปบ็š„ใ€‚ +ๆ‚จๅฏไปฅๅˆ›ๅปบไธ€ไธชๅŒ…ๅซ*่ทฏๅพ„ๆ“ไฝœ*็š„ API๏ผŒๅฎƒไผš่งฆๅ‘ๅฏนๅˆซไบบๅˆ›ๅปบ็š„*ๅค–้ƒจ API*็š„่ฏทๆฑ‚๏ผˆๅพˆๅฏ่ƒฝๅฐฑๆ˜ฏ้‚ฃไธชไผšโ€œไฝฟ็”จโ€ๆ‚จ API ็š„ๅŒไธ€ไธชๅผ€ๅ‘่€…๏ผ‰ใ€‚ -API ๅบ”็”จ่ฐƒ็”จๅค–้ƒจ API ๆ—ถ็š„ๆต็จ‹ๅซๅš**ๅ›ž่ฐƒ**ใ€‚ๅ› ไธบๅค–้ƒจๅผ€ๅ‘่€…็ผ–ๅ†™็š„่ฝฏไปถๅ‘้€่ฏทๆฑ‚่‡ณๆ‚จ็š„ API๏ผŒ็„ถๅŽๆ‚จ็š„ API ่ฆ่ฟ›่กŒๅ›ž่ฐƒ๏ผŒๅนถๆŠŠ่ฏทๆฑ‚ๅ‘้€่‡ณๅค–้ƒจ APIใ€‚ +ๅฝ“ๆ‚จ็š„ API ๅบ”็”จ่ฐƒ็”จ*ๅค–้ƒจ API*ๆ—ถ๏ผŒ่ฟ™ไธช่ฟ‡็จ‹่ขซ็งฐไธบโ€œๅ›ž่ฐƒโ€ใ€‚ๅ› ไธบๅค–้ƒจๅผ€ๅ‘่€…็ผ–ๅ†™็š„่ฝฏไปถไผšๅ…ˆๅ‘ๆ‚จ็š„ API ๅ‘้€่ฏทๆฑ‚๏ผŒ็„ถๅŽๆ‚จ็š„ API ๅ†่ฟ›่กŒ*ๅ›ž่ฐƒ*๏ผŒๅ‘*ๅค–้ƒจ API*ๅ‘้€่ฏทๆฑ‚๏ผˆๅพˆๅฏ่ƒฝไนŸๆ˜ฏ่ฏฅๅผ€ๅ‘่€…ๅˆ›ๅปบ็š„๏ผ‰ใ€‚ -ๆญคๆ—ถ๏ผŒๆˆ‘ไปฌ้œ€่ฆๅญ˜ๆกฃๅค–้ƒจ API ็š„*ไฟกๆฏ*๏ผŒๆฏ”ๅฆ‚ๅบ”่ฏฅๆœ‰ๅ“ชไบ›*่ทฏๅพ„ๆ“ไฝœ*๏ผŒ่ฟ”ๅ›žไป€ไนˆๆ ท็š„่ฏทๆฑ‚ไฝ“๏ผŒๅบ”่ฏฅ่ฟ”ๅ›žๅ“ช็งๅ“ๅบ”็ญ‰ใ€‚ +ๆญคๆ—ถ๏ผŒๆˆ‘ไปฌ้œ€่ฆๅญ˜ๆกฃๅค–้ƒจ API ็š„*ไฟกๆฏ*๏ผŒๆฏ”ๅฆ‚ๅบ”่ฏฅๆœ‰ๅ“ชไบ›*่ทฏๅพ„ๆ“ไฝœ*๏ผŒ่ฏทๆฑ‚ไฝ“ๅบ”่ฏฅๆ˜ฏไป€ไนˆ๏ผŒๅบ”่ฏฅ่ฟ”ๅ›žไป€ไนˆๅ“ๅบ”็ญ‰ใ€‚ -## ไฝฟ็”จๅ›ž่ฐƒ็š„ๅบ”็”จ +## ไฝฟ็”จๅ›ž่ฐƒ็š„ๅบ”็”จ { #an-app-with-callbacks } ็คบไพ‹ๅฆ‚ไธ‹ใ€‚ @@ -14,16 +14,16 @@ API ๅบ”็”จ่ฐƒ็”จๅค–้ƒจ API ๆ—ถ็š„ๆต็จ‹ๅซๅš**ๅ›ž่ฐƒ**ใ€‚ๅ› ไธบๅค–้ƒจๅผ€ๅ‘่€… ๅ‘็ฅจๅŒ…ๆ‹ฌ `id`ใ€`title`๏ผˆๅฏ้€‰๏ผ‰ใ€`customer`ใ€`total` ็ญ‰ๅฑžๆ€งใ€‚ -API ็š„็”จๆˆท ๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰่ฆๅœจๆ‚จ็š„ API ๅ†…ไฝฟ็”จ POST ่ฏทๆฑ‚ๅˆ›ๅปบไธ€ๆกๅ‘็ฅจ่ฎฐๅฝ•ใ€‚ +API ็š„็”จๆˆท๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰่ฆๅœจๆ‚จ็š„ API ๅ†…ไฝฟ็”จ POST ่ฏทๆฑ‚ๅˆ›ๅปบไธ€ๆกๅ‘็ฅจ่ฎฐๅฝ•ใ€‚ ๏ผˆๅ‡่ฎพ๏ผ‰ๆ‚จ็š„ API ๅฐ†๏ผš * ๆŠŠๅ‘็ฅจๅ‘้€่‡ณๅค–้ƒจๅผ€ๅ‘่€…็š„ๆถˆ่ดน่€… * ๅฝ’้›†็Žฐ้‡‘ * ๆŠŠ้€š็Ÿฅๅ‘้€่‡ณ API ็š„็”จๆˆท๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰ - * ้€š่ฟ‡๏ผˆไปŽๆ‚จ็š„ API๏ผ‰ๅ‘้€ POST ่ฏทๆฑ‚่‡ณๅค–้ƒจ API ๏ผˆๅณ**ๅ›ž่ฐƒ**๏ผ‰ๆฅๅฎŒๆˆ + * ้€š่ฟ‡๏ผˆไปŽๆ‚จ็š„ API๏ผ‰ๅ‘้€ POST ่ฏทๆฑ‚่‡ณๅค–้ƒจ API๏ผˆๅณ**ๅ›ž่ฐƒ**๏ผ‰ๆฅๅฎŒๆˆ -## ๅธธ่ง„ **FastAPI** ๅบ”็”จ +## ๅธธ่ง„ **FastAPI** ๅบ”็”จ { #the-normal-fastapi-app } ๆทปๅŠ ๅ›ž่ฐƒๅ‰๏ผŒ้ฆ–ๅ…ˆ็œ‹ไธ‹ๅธธ่ง„ API ๅบ”็”จๆ˜ฏไป€ไนˆๆ ทๅญใ€‚ @@ -31,17 +31,17 @@ API ็š„็”จๆˆท ๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰่ฆๅœจๆ‚จ็š„ API ๅ†…ไฝฟ็”จ POST ่ฏทๆฑ‚ๅˆ›ๅปบ ่ฟ™้ƒจๅˆ†ไปฃ็ ๅพˆๅธธ่ง„๏ผŒๆ‚จๅฏน็ปๅคงๅคšๆ•ฐไปฃ็ ๅบ”่ฏฅ้ƒฝๆฏ”่พƒ็†Ÿๆ‚‰ไบ†๏ผš -{* ../../docs_src/openapi_callbacks/tutorial001.py hl[10:14,37:54] *} +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} /// tip | ๆ็คบ -`callback_url` ๆŸฅ่ฏขๅ‚ๆ•ฐไฝฟ็”จ Pydantic ็š„ URL ็ฑปๅž‹ใ€‚ +`callback_url` ๆŸฅ่ฏขๅ‚ๆ•ฐไฝฟ็”จ Pydantic ็š„ Url ็ฑปๅž‹ใ€‚ /// ๆญคๅค„ๅ”ฏไธ€ๆฏ”่พƒๆ–ฐ็š„ๅ†…ๅฎนๆ˜ฏ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญ็š„ `callbacks=invoices_callback_router.routes` ๅ‚ๆ•ฐ๏ผŒไธ‹ๆ–‡ไป‹็ปใ€‚ -## ๅญ˜ๆกฃๅ›ž่ฐƒ +## ๅญ˜ๆกฃๅ›ž่ฐƒ { #documenting-the-callback } ๅฎž้™…็š„ๅ›ž่ฐƒไปฃ็ ้ซ˜ๅบฆไพ่ต–ไบŽๆ‚จ่‡ชๅทฑ็š„ API ๅบ”็”จใ€‚ @@ -51,14 +51,14 @@ API ็š„็”จๆˆท ๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰่ฆๅœจๆ‚จ็š„ API ๅ†…ไฝฟ็”จ POST ่ฏทๆฑ‚ๅˆ›ๅปบ ```Python callback_url = "https://example.com/api/v1/invoices/events/" -requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` ไฝ†ๅ›ž่ฐƒๆœ€้‡่ฆ็š„้ƒจๅˆ†ๅฏ่ƒฝๆ˜ฏ๏ผŒๆ นๆฎ API ่ฆๅ‘้€็ป™ๅ›ž่ฐƒ่ฏทๆฑ‚ไฝ“็š„ๆ•ฐๆฎ็ญ‰ๅ†…ๅฎน๏ผŒ็กฎไฟๆ‚จ็š„ API ็”จๆˆท๏ผˆๅค–้ƒจๅผ€ๅ‘่€…๏ผ‰ๆญฃ็กฎๅœฐๅฎž็Žฐ*ๅค–้ƒจ API*ใ€‚ ๅ› ๆญค๏ผŒๆˆ‘ไปฌไธ‹ไธ€ๆญฅ่ฆๅš็š„ๅฐฑๆ˜ฏๆทปๅŠ ไปฃ็ ๏ผŒไธบไปŽ API ๆŽฅๆ”ถๅ›ž่ฐƒ็š„*ๅค–้ƒจ API*ๅญ˜ๆกฃใ€‚ -่ฟ™้ƒจๅˆ†ๆ–‡ๆกฃๅœจ `/docs` ไธ‹็š„ Swagger API ๆ–‡ๆกฃไธญๆ˜พ็คบ๏ผŒๅนถไธ”ไผšๅ‘Š่ฏ‰ๅค–้ƒจๅผ€ๅ‘่€…ๅฆ‚ไฝ•ๆž„ๅปบ*ๅค–้ƒจ API*ใ€‚ +่ฟ™้ƒจๅˆ†ๆ–‡ๆกฃๅœจ `/docs` ไธ‹็š„ Swagger UI ไธญๆ˜พ็คบ๏ผŒๅนถไธ”ไผšๅ‘Š่ฏ‰ๅค–้ƒจๅผ€ๅ‘่€…ๅฆ‚ไฝ•ๆž„ๅปบ*ๅค–้ƒจ API*ใ€‚ ๆœฌไพ‹ๆฒกๆœ‰ๅฎž็Žฐๅ›ž่ฐƒๆœฌ่บซ๏ผˆๅชๆ˜ฏไธ€่กŒไปฃ็ ๏ผ‰๏ผŒๅชๆœ‰ๆ–‡ๆกฃ้ƒจๅˆ†ใ€‚ @@ -66,17 +66,17 @@ requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) ๅฎž้™…็š„ๅ›ž่ฐƒๅชๆ˜ฏ HTTP ่ฏทๆฑ‚ใ€‚ -ๅฎž็Žฐๅ›ž่ฐƒๆ—ถ๏ผŒ่ฆไฝฟ็”จ HTTPX ๆˆ– Requestsใ€‚ +ๅฎž็Žฐๅ›ž่ฐƒๆ—ถ๏ผŒ่ฆไฝฟ็”จ HTTPX ๆˆ– Requestsใ€‚ /// -## ็ผ–ๅ†™ๅ›ž่ฐƒๆ–‡ๆกฃไปฃ็  +## ็ผ–ๅ†™ๅ›ž่ฐƒๆ–‡ๆกฃไปฃ็  { #write-the-callback-documentation-code } ๅบ”็”จไธๆ‰ง่กŒ่ฟ™้ƒจๅˆ†ไปฃ็ ๏ผŒๅชๆ˜ฏ็”จๅฎƒๆฅ*่ฎฐๅฝ• ๅค–้ƒจ API* ใ€‚ ไฝ†๏ผŒๆ‚จๅทฒ็ป็Ÿฅ้“็”จ **FastAPI** ๅˆ›ๅปบ่‡ชๅŠจ API ๆ–‡ๆกฃๆœ‰ๅคš็ฎ€ๅ•ไบ†ใ€‚ -ๆˆ‘ไปฌ่ฆไฝฟ็”จไธŽๅญ˜ๆกฃ*ๅค–้ƒจ API* ็›ธๅŒ็š„็Ÿฅ่ฏ†โ€ฆโ€ฆ้€š่ฟ‡ๅˆ›ๅปบๅค–้ƒจ API ่ฆๅฎž็Žฐ็š„*่ทฏๅพ„ๆ“ไฝœ*๏ผˆๆ‚จ็š„ API ่ฆ่ฐƒ็”จ็š„๏ผ‰ใ€‚ +ๆˆ‘ไปฌ่ฆไฝฟ็”จไธŽๅญ˜ๆกฃ*ๅค–้ƒจ API* ็›ธๅŒ็š„็Ÿฅ่ฏ†...้€š่ฟ‡ๅˆ›ๅปบๅค–้ƒจ API ่ฆๅฎž็Žฐ็š„*่ทฏๅพ„ๆ“ไฝœ*๏ผˆๆ‚จ็š„ API ่ฆ่ฐƒ็”จ็š„๏ผ‰ใ€‚ /// tip | ๆ็คบ @@ -86,13 +86,13 @@ requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) /// -### ๅˆ›ๅปบๅ›ž่ฐƒ็š„ `APIRouter` +### ๅˆ›ๅปบๅ›ž่ฐƒ็š„ `APIRouter` { #create-a-callback-apirouter } ้ฆ–ๅ…ˆ๏ผŒๆ–ฐๅปบๅŒ…ๅซไธ€ไบ›็”จไบŽๅ›ž่ฐƒ็š„ `APIRouter`ใ€‚ -{* ../../docs_src/openapi_callbacks/tutorial001.py hl[5,26] *} +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} -### ๅˆ›ๅปบๅ›ž่ฐƒ*่ทฏๅพ„ๆ“ไฝœ* +### ๅˆ›ๅปบๅ›ž่ฐƒ*่ทฏๅพ„ๆ“ไฝœ* { #create-the-callback-path-operation } ๅˆ›ๅปบๅ›ž่ฐƒ*่ทฏๅพ„ๆ“ไฝœ*ไนŸไฝฟ็”จไน‹ๅ‰ๅˆ›ๅปบ็š„ `APIRouter`ใ€‚ @@ -101,16 +101,16 @@ requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) * ๅฃฐๆ˜Ž่ฆๆŽฅๆ”ถ็š„่ฏทๆฑ‚ไฝ“๏ผŒไพ‹ๅฆ‚๏ผŒ`body: InvoiceEvent` * ่ฟ˜่ฆๅฃฐๆ˜Ž่ฆ่ฟ”ๅ›ž็š„ๅ“ๅบ”๏ผŒไพ‹ๅฆ‚๏ผŒ`response_model=InvoiceEventReceived` -{* ../../docs_src/openapi_callbacks/tutorial001.py hl[17:19,22:23,29:33] *} +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} ๅ›ž่ฐƒ*่ทฏๅพ„ๆ“ไฝœ*ไธŽๅธธ่ง„*่ทฏๅพ„ๆ“ไฝœ*ๆœ‰ไธค็‚นไธป่ฆๅŒบๅˆซ๏ผš * ๅฎƒไธ้œ€่ฆไปปไฝ•ๅฎž้™…็š„ไปฃ็ ๏ผŒๅ› ไธบๅบ”็”จไธไผš่ฐƒ็”จ่ฟ™ๆฎตไปฃ็ ใ€‚ๅฎƒๅชๆ˜ฏ็”จไบŽๅญ˜ๆกฃ*ๅค–้ƒจ API*ใ€‚ๅ› ๆญค๏ผŒๅ‡ฝๆ•ฐ็š„ๅ†…ๅฎนๅช้œ€่ฆ `pass` ๅฐฑๅฏไปฅไบ† -* *่ทฏๅพ„*ๅฏไปฅๅŒ…ๅซ OpenAPI 3 ่กจ่พพๅผ๏ผˆ่ฏฆ่งไธ‹ๆ–‡๏ผ‰๏ผŒๅฏไปฅไฝฟ็”จๅธฆๅ‚ๆ•ฐ็š„ๅ˜้‡๏ผŒไปฅๅŠๅ‘้€่‡ณๆ‚จ็š„ API ็š„ๅŽŸๅง‹่ฏทๆฑ‚็š„้ƒจๅˆ† +* *่ทฏๅพ„*ๅฏไปฅๅŒ…ๅซ OpenAPI 3 ่กจ่พพๅผ๏ผˆ่ฏฆ่งไธ‹ๆ–‡๏ผ‰๏ผŒๅฏไปฅไฝฟ็”จๅธฆๅ‚ๆ•ฐ็š„ๅ˜้‡๏ผŒไปฅๅŠๅ‘้€่‡ณๆ‚จ็š„ API ็š„ๅŽŸๅง‹่ฏทๆฑ‚็š„้ƒจๅˆ† -### ๅ›ž่ฐƒ่ทฏๅพ„่กจ่พพๅผ +### ๅ›ž่ฐƒ่ทฏๅพ„่กจ่พพๅผ { #the-callback-path-expression } -ๅ›ž่ฐƒ*่ทฏๅพ„*ๆ”ฏๆŒๅŒ…ๅซๅ‘้€็ป™ๆ‚จ็š„ API ็š„ๅŽŸๅง‹่ฏทๆฑ‚็š„้ƒจๅˆ†็š„ OpenAPI 3 ่กจ่พพๅผใ€‚ +ๅ›ž่ฐƒ*่ทฏๅพ„*ๆ”ฏๆŒๅŒ…ๅซๅ‘้€็ป™ๆ‚จ็š„ API ็š„ๅŽŸๅง‹่ฏทๆฑ‚็š„้ƒจๅˆ†็š„ OpenAPI 3 ่กจ่พพๅผใ€‚ ๆœฌไพ‹ไธญๆ˜ฏ**ๅญ—็ฌฆไธฒ**๏ผš @@ -159,17 +159,17 @@ JSON ่ฏทๆฑ‚ไฝ“ๅŒ…ๅซๅฆ‚ไธ‹ๅ†…ๅฎน๏ผš /// tip | ๆ็คบ -ๆณจๆ„๏ผŒๅ›ž่ฐƒ URLๅŒ…ๅซ `callback_url` ๏ผˆ`https://www.external.org/events`๏ผ‰ไธญ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒ่ฟ˜ๆœ‰ JSON ่ฏทๆฑ‚ไฝ“ๅ†…้ƒจ็š„ๅ‘็ฅจ ID๏ผˆ`2expen51ve`๏ผ‰ใ€‚ +ๆณจๆ„๏ผŒๅ›ž่ฐƒ URL ๅŒ…ๅซ `callback_url`๏ผˆ`https://www.external.org/events`๏ผ‰ไธญ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒ่ฟ˜ๆœ‰ JSON ่ฏทๆฑ‚ไฝ“ๅ†…้ƒจ็š„ๅ‘็ฅจ ID๏ผˆ`2expen51ve`๏ผ‰ใ€‚ /// -### ๆทปๅŠ ๅ›ž่ฐƒ่ทฏ็”ฑ +### ๆทปๅŠ ๅ›ž่ฐƒ่ทฏ็”ฑ { #add-the-callback-router } ่‡ณๆญค๏ผŒๅœจไธŠๆ–‡ๅˆ›ๅปบ็š„ๅ›ž่ฐƒ่ทฏ็”ฑ้‡ŒๅฐฑๅŒ…ๅซไบ†*ๅ›ž่ฐƒ่ทฏๅพ„ๆ“ไฝœ*๏ผˆๅค–้ƒจๅผ€ๅ‘่€…่ฆๅœจๅค–้ƒจ API ไธญๅฎž็Žฐ๏ผ‰ใ€‚ ็Žฐๅœจไฝฟ็”จ API *่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*็š„ๅ‚ๆ•ฐ `callbacks`๏ผŒไปŽๅ›ž่ฐƒ่ทฏ็”ฑไผ ้€’ๅฑžๆ€ง `.routes`๏ผˆๅฎž้™…ไธŠๅชๆ˜ฏ่ทฏ็”ฑ/่ทฏๅพ„ๆ“ไฝœ็š„**ๅˆ—่กจ**๏ผ‰๏ผš -{* ../../docs_src/openapi_callbacks/tutorial001.py hl[36] *} +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | ๆ็คบ @@ -177,9 +177,9 @@ JSON ่ฏทๆฑ‚ไฝ“ๅŒ…ๅซๅฆ‚ไธ‹ๅ†…ๅฎน๏ผš /// -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } -็Žฐๅœจ๏ผŒไฝฟ็”จ Uvicorn ๅฏๅŠจๅบ”็”จ๏ผŒๆ‰“ๅผ€ http://127.0.0.1:8000/docsใ€‚ +็Žฐๅœจ๏ผŒไฝฟ็”จ Uvicorn ๅฏๅŠจๅบ”็”จ๏ผŒๆ‰“ๅผ€ http://127.0.0.1:8000/docsใ€‚ ๅฐฑ่ƒฝ็œ‹ๅˆฐๆ–‡ๆกฃ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅทฒ็ปๅŒ…ๅซไบ†**ๅ›ž่ฐƒ**็š„ๅ†…ๅฎนไปฅๅŠ*ๅค–้ƒจ API*๏ผš diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md index 92ae8db15f..9e64ed4e3c 100644 --- a/docs/zh/docs/advanced/openapi-webhooks.md +++ b/docs/zh/docs/advanced/openapi-webhooks.md @@ -1,4 +1,4 @@ -# OpenAPI ็ฝ‘็ปœ้’ฉๅญ +# OpenAPI ็ฝ‘็ปœ้’ฉๅญ { #openapi-webhooks } ๆœ‰ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฏ่ƒฝๆƒณๅ‘Š่ฏ‰ๆ‚จ็š„ API **็”จๆˆท**๏ผŒๆ‚จ็š„ๅบ”็”จ็จ‹ๅบๅฏไปฅๆบๅธฆไธ€ไบ›ๆ•ฐๆฎ่ฐƒ็”จ*ไป–ไปฌ็š„*ๅบ”็”จ็จ‹ๅบ๏ผˆ็ป™ๅฎƒไปฌๅ‘้€่ฏทๆฑ‚๏ผ‰๏ผŒ้€šๅธธๆ˜ฏไธบไบ†**้€š็Ÿฅ**ๆŸ็ง**ไบ‹ไปถ**ใ€‚ @@ -6,7 +6,7 @@ ่ฟ™้€šๅธธ่ขซ็งฐไธบ**็ฝ‘็ปœ้’ฉๅญ**๏ผˆWebhook๏ผ‰ใ€‚ -## ไฝฟ็”จ็ฝ‘็ปœ้’ฉๅญ็š„ๆญฅ้ชค +## ไฝฟ็”จ็ฝ‘็ปœ้’ฉๅญ็š„ๆญฅ้ชค { #webhooks-steps } ้€šๅธธ็š„่ฟ‡็จ‹ๆ˜ฏ**ๆ‚จ**ๅœจไปฃ็ ไธญ**ๅฎšไน‰**่ฆๅ‘้€็š„ๆถˆๆฏ๏ผŒๅณ**่ฏทๆฑ‚็š„ไธปไฝ“**ใ€‚ @@ -16,27 +16,27 @@ ๆ‰€ๆœ‰ๅ…ณไบŽๆณจๅ†Œ็ฝ‘็ปœ้’ฉๅญ็š„ URL ็š„**้€ป่พ‘**ไปฅๅŠๅ‘้€่ฟ™ไบ›่ฏทๆฑ‚็š„ๅฎž้™…ไปฃ็ ้ƒฝ็”ฑๆ‚จๅ†ณๅฎšใ€‚ๆ‚จๅฏไปฅๅœจ**่‡ชๅทฑ็š„ไปฃ็ **ไธญไปฅไปปไฝ•ๆƒณ่ฆ็š„ๆ–นๅผๆฅ็ผ–ๅ†™ๅฎƒใ€‚ -## ไฝฟ็”จ `FastAPI` ๅ’Œ OpenAPI ๆ–‡ๆกฃๅŒ–็ฝ‘็ปœ้’ฉๅญ +## ไฝฟ็”จ `FastAPI` ๅ’Œ OpenAPI ๆ–‡ๆกฃๅŒ–็ฝ‘็ปœ้’ฉๅญ { #documenting-webhooks-with-fastapi-and-openapi } ไฝฟ็”จ **FastAPI**๏ผŒๆ‚จๅฏไปฅๅˆฉ็”จ OpenAPI ๆฅ่‡ชๅฎšไน‰่ฟ™ไบ›็ฝ‘็ปœ้’ฉๅญ็š„ๅ็งฐใ€ๆ‚จ็š„ๅบ”็”จๅฏไปฅๅ‘้€็š„ HTTP ๆ“ไฝœ็ฑปๅž‹๏ผˆไพ‹ๅฆ‚ `POST`ใ€`PUT` ็ญ‰๏ผ‰ไปฅๅŠๆ‚จ็š„ๅบ”็”จๅฐ†ๅ‘้€็š„**่ฏทๆฑ‚ไฝ“**ใ€‚ ่ฟ™่ƒฝ่ฎฉๆ‚จ็š„็”จๆˆทๆ›ด่ฝปๆพๅœฐ**ๅฎž็Žฐไป–ไปฌ็š„ API** ๆฅๆŽฅๆ”ถๆ‚จ็š„**็ฝ‘็ปœ้’ฉๅญ**่ฏทๆฑ‚๏ผŒไป–ไปฌ็”š่‡ณๅฏ่ƒฝ่ƒฝๅคŸ่‡ชๅŠจ็”Ÿๆˆไธ€ไบ›่‡ชๅทฑ็š„ API ไปฃ็ ใ€‚ -/// info +/// info | ไฟกๆฏ ็ฝ‘็ปœ้’ฉๅญๅœจ OpenAPI 3.1.0 ๅŠไปฅไธŠ็‰ˆๆœฌไธญๅฏ็”จ๏ผŒFastAPI `0.99.0` ๅŠไปฅไธŠ็‰ˆๆœฌๆ”ฏๆŒใ€‚ /// -## ๅธฆๆœ‰็ฝ‘็ปœ้’ฉๅญ็š„ๅบ”็”จ็จ‹ๅบ +## ๅธฆๆœ‰็ฝ‘็ปœ้’ฉๅญ็š„ๅบ”็”จ็จ‹ๅบ { #an-app-with-webhooks } ๅฝ“ๆ‚จๅˆ›ๅปบไธ€ไธช **FastAPI** ๅบ”็”จ็จ‹ๅบๆ—ถ๏ผŒๆœ‰ไธ€ไธช `webhooks` ๅฑžๆ€งๅฏไปฅ็”จๆฅๅฎšไน‰็ฝ‘็ปœ้’ฉๅญ๏ผŒๆ–นๅผไธŽๆ‚จๅฎšไน‰*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ—ถๅ€™็›ธๅŒ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `@app.webhooks.post()` ใ€‚ -{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} ๆ‚จๅฎšไน‰็š„็ฝ‘็ปœ้’ฉๅญๅฐ†่ขซๅŒ…ๅซๅœจ `OpenAPI` ็š„ๆžถๆž„ไธญ๏ผŒๅนถๅ‡บ็Žฐๅœจ่‡ชๅŠจ็”Ÿๆˆ็š„**ๆ–‡ๆกฃ UI** ไธญใ€‚ -/// info +/// info | ไฟกๆฏ `app.webhooks` ๅฏน่ฑกๅฎž้™…ไธŠๅชๆ˜ฏไธ€ไธช `APIRouter` ๏ผŒไธŽๆ‚จๅœจไฝฟ็”จๅคšไธชๆ–‡ไปถๆฅๆž„ๅปบๅบ”็”จ็จ‹ๅบๆ—ถๆ‰€ไฝฟ็”จ็š„็ฑปๅž‹็›ธๅŒใ€‚ @@ -46,7 +46,7 @@ ่ฟ™ๆ˜ฏๅ› ไธบๆˆ‘ไปฌ้ข„่ฎก**ๆ‚จ็š„็”จๆˆท**ไผšไปฅๅ…ถไป–ๆ–นๅผ๏ผˆไพ‹ๅฆ‚้€š่ฟ‡็ฝ‘้กตไปช่กจๆฟ๏ผ‰ๆฅๅฎšไน‰ไป–ไปฌๅธŒๆœ›ๆŽฅๆ”ถ็ฝ‘็ปœ้’ฉๅญ็š„่ฏทๆฑ‚็š„ๅฎž้™… **URL ่ทฏๅพ„**ใ€‚ -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } ็Žฐๅœจๆ‚จๅฏไปฅๅฏๅŠจๆ‚จ็š„ๅบ”็”จ็จ‹ๅบๅนถ่ฎฟ้—ฎ http://127.0.0.1:8000/docs. diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md index 12600eddb1..6c9928ffce 100644 --- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md @@ -1,26 +1,26 @@ -# ่ทฏๅพ„ๆ“ไฝœ็š„้ซ˜็บง้…็ฝฎ +# ่ทฏๅพ„ๆ“ไฝœ็š„้ซ˜็บง้…็ฝฎ { #path-operation-advanced-configuration } -## OpenAPI ็š„ operationId +## OpenAPI ็š„ operationId { #openapi-operationid } /// warning -ๅฆ‚ๆžœไฝ ๅนถ้ž OpenAPI ็š„ใ€Œไธ“ๅฎถใ€๏ผŒไฝ ๅฏ่ƒฝไธ้œ€่ฆ่ฟ™้ƒจๅˆ†ๅ†…ๅฎนใ€‚ +ๅฆ‚ๆžœไฝ ๅนถ้ž OpenAPI ็š„โ€œไธ“ๅฎถโ€๏ผŒไฝ ๅฏ่ƒฝไธ้œ€่ฆ่ฟ™้ƒจๅˆ†ๅ†…ๅฎนใ€‚ /// -ไฝ ๅฏไปฅๅœจ่ทฏๅพ„ๆ“ไฝœไธญ้€š่ฟ‡ๅ‚ๆ•ฐ `operation_id` ่ฎพ็ฝฎ่ฆไฝฟ็”จ็š„ OpenAPI `operationId`ใ€‚ +ไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ* ไธญ้€š่ฟ‡ๅ‚ๆ•ฐ `operation_id` ่ฎพ็ฝฎ่ฆไฝฟ็”จ็š„ OpenAPI `operationId`ใ€‚ -ๅŠกๅฟ…็กฎไฟๆฏไธชๆ“ไฝœ่ทฏๅพ„็š„ `operation_id` ้ƒฝๆ˜ฏๅ”ฏไธ€็š„ใ€‚ +ๅŠกๅฟ…็กฎไฟๆฏไธชๆ“ไฝœ็š„ `operation_id` ้ƒฝๆ˜ฏๅ”ฏไธ€็š„ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} -### ไฝฟ็”จ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็š„ๅ‡ฝๆ•ฐๅไฝœไธบ operationId +### ไฝฟ็”จ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็š„ๅ‡ฝๆ•ฐๅไฝœไธบ operationId { #using-the-path-operation-function-name-as-the-operationid } -ๅฆ‚ๆžœไฝ ๆƒณ็”จไฝ ็š„ API ็š„ๅ‡ฝๆ•ฐๅไฝœไธบ `operationId` ็š„ๅๅญ—๏ผŒไฝ ๅฏไปฅ้ๅކไธ€้ API ็š„ๅ‡ฝๆ•ฐๅ๏ผŒ็„ถๅŽไฝฟ็”จไป–ไปฌ็š„ `APIRoute.name` ้‡ๅ†™ๆฏไธช *่ทฏๅพ„ๆ“ไฝœ* ็š„ `operation_id`ใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณ็”จ API ็š„ๅ‡ฝๆ•ฐๅไฝœไธบ `operationId`๏ผŒไฝ ๅฏไปฅ้ๅކๆ‰€ๆœ‰่ทฏๅพ„ๆ“ไฝœ๏ผŒๅนถไฝฟ็”จๅฎƒไปฌ็š„ `APIRoute.name` ้‡ๅ†™ๆฏไธช *่ทฏๅพ„ๆ“ไฝœ* ็š„ `operation_id`ใ€‚ ไฝ ๅบ”่ฏฅๅœจๆทปๅŠ ไบ†ๆ‰€ๆœ‰ *่ทฏๅพ„ๆ“ไฝœ* ไน‹ๅŽๆ‰ง่กŒๆญคๆ“ไฝœใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12,13,14,15,16,17,18,19,20,21,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} /// tip @@ -36,19 +36,137 @@ /// -## ไปŽ OpenAPI ไธญๆŽ’้™ค +## ไปŽ OpenAPI ไธญๆŽ’้™ค { #exclude-from-openapi } -ไฝฟ็”จๅ‚ๆ•ฐ `include_in_schema` ๅนถๅฐ†ๅ…ถ่ฎพ็ฝฎไธบ `False` ๏ผŒๆฅไปŽ็”Ÿๆˆ็š„ OpenAPI ๆ–นๆกˆไธญๆŽ’้™คไธ€ไธช *่ทฏๅพ„ๆ“ไฝœ*๏ผˆ่ฟ™ๆ ทไธ€ๆฅ๏ผŒๅฐฑไปŽ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃ็ณป็ปŸไธญๆŽ’้™คๆމไบ†๏ผ‰ใ€‚ +ไฝฟ็”จๅ‚ๆ•ฐ `include_in_schema` ๅนถๅฐ†ๅ…ถ่ฎพ็ฝฎไธบ `False`๏ผŒๆฅไปŽ็”Ÿๆˆ็š„ OpenAPI ๆ–นๆกˆไธญๆŽ’้™คไธ€ไธช *่ทฏๅพ„ๆ“ไฝœ*๏ผˆ่ฟ™ๆ ทไธ€ๆฅ๏ผŒๅฐฑไปŽ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃ็ณป็ปŸไธญๆŽ’้™คๆމไบ†๏ผ‰๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} -## docstring ็š„้ซ˜็บงๆ่ฟฐ +## ๆฅ่‡ช docstring ็š„้ซ˜็บงๆ่ฟฐ { #advanced-description-from-docstring } ไฝ ๅฏไปฅ้™ๅˆถ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็š„ `docstring` ไธญ็”จไบŽ OpenAPI ็š„่กŒๆ•ฐใ€‚ -ๆทปๅŠ ไธ€ไธช `\f` ๏ผˆไธ€ไธชใ€Œๆข้กตใ€็š„่ฝฌไน‰ๅญ—็ฌฆ๏ผ‰ๅฏไปฅไฝฟ **FastAPI** ๅœจ้‚ฃไธ€ไฝ็ฝฎๆˆชๆ–ญ็”จไบŽ OpenAPI ็š„่พ“ๅ‡บใ€‚ +ๆทปๅŠ ไธ€ไธช `\f`๏ผˆไธ€ไธชโ€œๆข้กตโ€็š„่ฝฌไน‰ๅญ—็ฌฆ๏ผ‰ๅฏไปฅไฝฟ **FastAPI** ๅœจ้‚ฃไธ€ไฝ็ฝฎๆˆชๆ–ญ็”จไบŽ OpenAPI ็š„่พ“ๅ‡บใ€‚ ๅ‰ฉไฝ™้ƒจๅˆ†ไธไผšๅ‡บ็Žฐๅœจๆ–‡ๆกฃไธญ๏ผŒไฝ†ๆ˜ฏๅ…ถไป–ๅทฅๅ…ท๏ผˆๆฏ”ๅฆ‚ Sphinx๏ผ‰ๅฏไปฅไฝฟ็”จๅ‰ฉไฝ™้ƒจๅˆ†ใ€‚ +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} -{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19,20,21,22,23,24,25,26,27,28,29] *} +## ้™„ๅŠ ๅ“ๅบ” { #additional-responses } + +ไฝ ๅฏ่ƒฝๅทฒ็ป่ง่ฟ‡ๅฆ‚ไฝ•ไธบไธ€ไธช *่ทฏๅพ„ๆ“ไฝœ* ๅฃฐๆ˜Ž `response_model` ๅ’Œ `status_code`ใ€‚ + +่ฟ™ๅฎšไน‰ไบ†่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ไธปๅ“ๅบ”็š„ๅ…ƒๆ•ฐๆฎใ€‚ + +ไฝ ไนŸๅฏไปฅไธบๅฎƒๅฃฐๆ˜Žๅธฆๆœ‰ๅ„่‡ชๆจกๅž‹ใ€็Šถๆ€็ ็ญ‰็š„้™„ๅŠ ๅ“ๅบ”ใ€‚ + +ๆ–‡ๆกฃไธญๆœ‰ไธ€ไธชๅฎŒๆ•ด็ซ ่Š‚๏ผŒไฝ ๅฏไปฅ้˜…่ฏป่ฟ™้‡Œ็š„[OpenAPI ไธญ็š„้™„ๅŠ ๅ“ๅบ”](additional-responses.md){.internal-link target=_blank}ใ€‚ + +## OpenAPI Extra { #openapi-extra } + +ๅฝ“ไฝ ๅœจๅบ”็”จไธญๅฃฐๆ˜Žไธ€ไธช *่ทฏๅพ„ๆ“ไฝœ* ๆ—ถ๏ผŒ**FastAPI** ไผš่‡ชๅŠจ็”ŸๆˆไธŽ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็›ธๅ…ณ็š„ๅ…ƒๆ•ฐๆฎ๏ผŒไปฅๅŒ…ๅซๅˆฐ OpenAPI ๆ–นๆกˆไธญใ€‚ + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +ๅœจ OpenAPI ่ง„่Œƒไธญ๏ผŒ่ฟ™่ขซ็งฐไธบ Operation ๅฏน่ฑกใ€‚ + +/// + +ๅฎƒๅŒ…ๅซๅ…ณไบŽ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็š„ๆ‰€ๆœ‰ไฟกๆฏ๏ผŒๅนถ็”จไบŽ็”Ÿๆˆ่‡ชๅŠจๆ–‡ๆกฃใ€‚ + +ๅฎƒๅŒ…ๆ‹ฌ `tags`ใ€`parameters`ใ€`requestBody`ใ€`responses` ็ญ‰ใ€‚ + +่ฟ™ไธช็‰นๅฎšไบŽ *่ทฏๅพ„ๆ“ไฝœ* ็š„ OpenAPI ๆ–นๆกˆ้€šๅธธ็”ฑ **FastAPI** ่‡ชๅŠจ็”Ÿๆˆ๏ผŒไฝ†ไฝ ไนŸๅฏไปฅๆ‰ฉๅฑ•ๅฎƒใ€‚ + +/// tip + +่ฟ™ๆ˜ฏไธ€ไธช่พƒไฝŽๅฑ‚็บง็š„ๆ‰ฉๅฑ•็‚นใ€‚ + +ๅฆ‚ๆžœไฝ ๅช้œ€่ฆๅฃฐๆ˜Ž้™„ๅŠ ๅ“ๅบ”๏ผŒๆ›ดๆ–นไพฟ็š„ๆ–นๅผๆ˜ฏไฝฟ็”จ[OpenAPI ไธญ็š„้™„ๅŠ ๅ“ๅบ”](additional-responses.md){.internal-link target=_blank}ใ€‚ + +/// + +ไฝ ๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `openapi_extra` ๆ‰ฉๅฑ•ๆŸไธช *่ทฏๅพ„ๆ“ไฝœ* ็š„ OpenAPI ๆ–นๆกˆใ€‚ + +### OpenAPI ๆ‰ฉๅฑ• { #openapi-extensions } + +ไพ‹ๅฆ‚๏ผŒ่ฟ™ไธช `openapi_extra` ๅฏ็”จไบŽๅฃฐๆ˜Ž [OpenAPI ๆ‰ฉๅฑ•](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} + +ๅฝ“ไฝ ๆ‰“ๅผ€่‡ชๅŠจ API ๆ–‡ๆกฃๆ—ถ๏ผŒไฝ ็š„ๆ‰ฉๅฑ•ไผšๆ˜พ็คบๅœจ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็š„ๅบ•้ƒจใ€‚ + + + +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ๆœ€็ปˆ็”Ÿๆˆ็š„ OpenAPI๏ผˆๅœจไฝ ็š„ API ็š„ `/openapi.json`๏ผ‰๏ผŒไฝ ไนŸไผš็œ‹ๅˆฐไฝ ็š„ๆ‰ฉๅฑ•ไฝœไธบ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็š„ไธ€้ƒจๅˆ†๏ผš + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ่‡ชๅฎšไน‰ OpenAPI ่ทฏๅพ„ๆ“ไฝœๆ–นๆกˆ { #custom-openapi-path-operation-schema } + +`openapi_extra` ไธญ็š„ๅญ—ๅ…ธไผšไธŽ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ่‡ชๅŠจ็”Ÿๆˆ็š„ OpenAPI ๆ–นๆกˆ่ฟ›่กŒๆทฑๅบฆๅˆๅนถใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅœจ่‡ชๅŠจ็”Ÿๆˆ็š„ๆ–นๆกˆไธŠๆทปๅŠ ้ขๅค–ๆ•ฐๆฎใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅ†ณๅฎš็”จ่‡ชๅทฑ็š„ไปฃ็ ่ฏปๅ–ๅนถ้ชŒ่ฏ่ฏทๆฑ‚๏ผŒ่€Œไธไฝฟ็”จ FastAPI ไธŽ Pydantic ็š„่‡ชๅŠจๅŠŸ่ƒฝ๏ผŒไฝ†ไฝ ไป็„ถๅธŒๆœ›ๅœจ OpenAPI ๆ–นๆกˆไธญๅฎšไน‰่ฏฅ่ฏทๆฑ‚ใ€‚ + +ไฝ ๅฏไปฅ็”จ `openapi_extra` ๆฅๅšๅˆฐ๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} + +ๅœจ่ฟ™ไธช็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ• Pydantic ๆจกๅž‹ใ€‚ไบ‹ๅฎžไธŠ๏ผŒ่ฏทๆฑ‚ไฝ“็”š่‡ณๆฒกๆœ‰่ขซ ่งฃๆž ไธบ JSON๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅไปฅ `bytes` ่ฏปๅ–๏ผŒๅนถ็”ฑๅ‡ฝๆ•ฐ `magic_data_reader()` ไปฅๆŸ็งๆ–นๅผ่ดŸ่ดฃ่งฃๆžใ€‚ + +ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒๆˆ‘ไปฌไป็„ถๅฏไปฅๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“็š„้ข„ๆœŸๆ–นๆกˆใ€‚ + +### ่‡ชๅฎšไน‰ OpenAPI ๅ†…ๅฎน็ฑปๅž‹ { #custom-openapi-content-type } + +ไฝฟ็”จๅŒๆ ท็š„ๆŠ€ๅทง๏ผŒไฝ ๅฏไปฅ็”จไธ€ไธช Pydantic ๆจกๅž‹ๆฅๅฎšไน‰ JSON Schema๏ผŒ็„ถๅŽๆŠŠๅฎƒๅŒ…ๅซๅˆฐ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็š„่‡ชๅฎšไน‰ OpenAPI ๆ–นๆกˆ้ƒจๅˆ†ไธญใ€‚ + +ๅณไฝฟ่ฏทๆฑ‚ไธญ็š„ๆ•ฐๆฎ็ฑปๅž‹ไธๆ˜ฏ JSON๏ผŒไฝ ไนŸๅฏไปฅ่ฟ™ๆ ทๅšใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅœจ่ฟ™ไธชๅบ”็”จไธญๆˆ‘ไปฌไธไฝฟ็”จ FastAPI ้›†ๆˆ็š„ไปŽ Pydantic ๆจกๅž‹ๆๅ– JSON Schema ็š„ๅŠŸ่ƒฝ๏ผŒไนŸไธไฝฟ็”จๅฏน JSON ็š„่‡ชๅŠจๆ ก้ชŒใ€‚ๅฎž้™…ไธŠ๏ผŒๆˆ‘ไปฌๅฐ†่ฏทๆฑ‚็š„ๅ†…ๅฎน็ฑปๅž‹ๅฃฐๆ˜Žไธบ YAML๏ผŒ่€Œไธๆ˜ฏ JSON๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} + +ๅฐฝ็ฎกๆˆ‘ไปฌๆฒกๆœ‰ไฝฟ็”จ้ป˜่ฎค็š„้›†ๆˆๅŠŸ่ƒฝ๏ผŒๆˆ‘ไปฌไป็„ถไฝฟ็”จ Pydantic ๆจกๅž‹ๆ‰‹ๅŠจ็”Ÿๆˆๆˆ‘ไปฌๆƒณไปฅ YAML ๆŽฅๆ”ถ็š„ๆ•ฐๆฎ็š„ JSON Schemaใ€‚ + +็„ถๅŽๆˆ‘ไปฌ็›ดๆŽฅไฝฟ็”จ่ฏทๆฑ‚ๅนถๅฐ†่ฏทๆฑ‚ไฝ“ๆๅ–ไธบ `bytes`ใ€‚่ฟ™ๆ„ๅ‘ณ็€ FastAPI ็”š่‡ณไธไผšๅฐ่ฏ•ๅฐ†่ฏทๆฑ‚่ดŸ่ฝฝ่งฃๆžไธบ JSONใ€‚ + +ๆŽฅ็€ๅœจๆˆ‘ไปฌ็š„ไปฃ็ ไธญ๏ผŒๆˆ‘ไปฌ็›ดๆŽฅ่งฃๆž่ฏฅ YAML ๅ†…ๅฎน๏ผŒ็„ถๅŽๅ†ๆฌกไฝฟ็”จๅŒไธ€ไธช Pydantic ๆจกๅž‹ๆฅ้ชŒ่ฏ่ฏฅ YAML ๅ†…ๅฎน๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} + +/// tip + +่ฟ™้‡Œๆˆ‘ไปฌๅค็”จไบ†ๅŒไธ€ไธช Pydantic ๆจกๅž‹ใ€‚ + +ไฝ†ๅŒๆ ทๅœฐ๏ผŒๆˆ‘ไปฌไนŸๅฏไปฅ็”จๅ…ถไป–ๆ–นๅผๅฏนๅ…ถ่ฟ›่กŒ้ชŒ่ฏใ€‚ + +/// diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md index cc1f2a73eb..cdcd39f50c 100644 --- a/docs/zh/docs/advanced/response-change-status-code.md +++ b/docs/zh/docs/advanced/response-change-status-code.md @@ -1,10 +1,10 @@ -# ๅ“ๅบ” - ๆ›ดๆ”น็Šถๆ€็  +# ๅ“ๅบ” - ๆ›ดๆ”น็Šถๆ€็  { #response-change-status-code } ไฝ ๅฏ่ƒฝไน‹ๅ‰ๅทฒ็ปไบ†่งฃๅˆฐ๏ผŒไฝ ๅฏไปฅ่ฎพ็ฝฎ้ป˜่ฎค็š„[ๅ“ๅบ”็Šถๆ€็ ](../tutorial/response-status-code.md){.internal-link target=_blank}ใ€‚ ไฝ†ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ้œ€่ฆ่ฟ”ๅ›žไธ€ไธชไธๅŒไบŽ้ป˜่ฎคๅ€ผ็š„็Šถๆ€็ ใ€‚ -## ไฝฟ็”จๅœบๆ™ฏ +## ไฝฟ็”จๅœบๆ™ฏ { #use-case } ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๆƒณ้ป˜่ฎค่ฟ”ๅ›žไธ€ไธชHTTP็Šถๆ€็ ไธบโ€œOKโ€`200`ใ€‚ @@ -14,16 +14,16 @@ ๅฏนไบŽ่ฟ™ไบ›ๆƒ…ๅ†ต๏ผŒไฝ ๅฏไปฅไฝฟ็”จไธ€ไธช`Response`ๅ‚ๆ•ฐใ€‚ -## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ +## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ { #use-a-response-parameter } ไฝ ๅฏไปฅๅœจไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Žไธ€ไธช`Response`็ฑปๅž‹็š„ๅ‚ๆ•ฐ๏ผˆๅฐฑๅƒไฝ ๅฏไปฅไธบcookiesๅ’Œๅคด้ƒจๅš็š„้‚ฃๆ ท๏ผ‰ใ€‚ ็„ถๅŽไฝ ๅฏไปฅๅœจ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎ`status_code`ใ€‚ -{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} ็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช`dict`ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช`response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ -**FastAPI**ๅฐ†ไฝฟ็”จ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๆฅๆๅ–็Šถๆ€็ ๏ผˆไนŸๅŒ…ๆ‹ฌcookiesๅ’Œๅคด้ƒจ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ•`response_model`่ฟ‡ๆปคใ€‚ +**FastAPI**ๅฐ†ไฝฟ็”จ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๆฅๆๅ–็Šถๆ€็ ๏ผˆไนŸๅŒ…ๆ‹ฌcookiesๅ’Œๅคด้ƒจ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ•`response_model`่ฟ‡ๆปคใ€‚ ไฝ ไนŸๅฏไปฅๅœจไพ่ต–้กนไธญๅฃฐๆ˜Ž`Response`ๅ‚ๆ•ฐ๏ผŒๅนถๅœจๅ…ถไธญ่ฎพ็ฝฎ็Šถๆ€็ ใ€‚ไฝ†่ฏทๆณจๆ„๏ผŒๆœ€ๅŽ่ฎพ็ฝฎ็š„็Šถๆ€็ ๅฐ†ไผš็”Ÿๆ•ˆใ€‚ diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md index d5f2fe6fc5..cc311a2708 100644 --- a/docs/zh/docs/advanced/response-cookies.md +++ b/docs/zh/docs/advanced/response-cookies.md @@ -1,10 +1,10 @@ -# ๅ“ๅบ”Cookies +# ๅ“ๅบ”Cookies { #response-cookies } -## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ +## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ { #use-a-response-parameter } -ไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๅ‡ฝๆ•ฐ* ไธญๅฎšไน‰ไธ€ไธช็ฑปๅž‹ไธบ `Response`็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎcookieไบ†ใ€‚ +ไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญๅฎšไน‰ไธ€ไธช็ฑปๅž‹ไธบ `Response` ็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎcookieไบ†ใ€‚ -{* ../../docs_src/response_cookies/tutorial002.py hl[1,8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} ่€Œไธ”ไฝ ่ฟ˜ๅฏไปฅๆ นๆฎไฝ ็š„้œ€่ฆๅ“ๅบ”ไธๅŒ็š„ๅฏน่ฑก๏ผŒๆฏ”ๅฆ‚ๅธธ็”จ็š„ `dict`๏ผŒๆ•ฐๆฎๅบ“model็ญ‰ใ€‚ @@ -12,17 +12,17 @@ **FastAPI** ไผšไฝฟ็”จ่ฟ™ไธช *ไธดๆ—ถ* ๅ“ๅบ”ๅฏน่ฑกๅŽป่ฃ…ๅœจ่ฟ™ไบ›cookiesไฟกๆฏ (ๅŒๆ ท่ฟ˜ๆœ‰headersๅ’Œ็Šถๆ€็ ็ญ‰ไฟกๆฏ), ๆœ€็ปˆไผšๅฐ†่ฟ™ไบ›ไฟกๆฏๅ’Œ้€š่ฟ‡`response_model`่ฝฌๅŒ–่ฟ‡็š„ๆ•ฐๆฎๅˆๅนถๅˆฐๆœ€็ปˆ็š„ๅ“ๅบ”้‡Œใ€‚ -ไฝ ไนŸๅฏไปฅๅœจdependไธญๅฎšไน‰`Response`ๅ‚ๆ•ฐ๏ผŒๅนถ่ฎพ็ฝฎcookieๅ’Œheaderใ€‚ +ไฝ ไนŸๅฏไปฅๅœจไพ่ต–ไธญๅฎšไน‰`Response`ๅ‚ๆ•ฐ๏ผŒๅนถ่ฎพ็ฝฎcookieๅ’Œheaderใ€‚ -## ็›ดๆŽฅๅ“ๅบ” `Response` +## ็›ดๆŽฅๅ“ๅบ” `Response` { #return-a-response-directly } ไฝ ่ฟ˜ๅฏไปฅๅœจ็›ดๆŽฅๅ“ๅบ”`Response`ๆ—ถ็›ดๆŽฅๅˆ›ๅปบcookiesใ€‚ -ไฝ ๅฏไปฅๅ‚่€ƒ[Return a Response Directly](response-directly.md){.internal-link target=_blank}ๆฅๅˆ›ๅปบresponse +ไฝ ๅฏไปฅๅ‚่€ƒ[็›ดๆŽฅ่ฟ”ๅ›ž Response](response-directly.md){.internal-link target=_blank}ๆฅๅˆ›ๅปบresponse ็„ถๅŽ่ฎพ็ฝฎCookies๏ผŒๅนถ่ฟ”ๅ›ž๏ผš -{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} /// tip @@ -34,7 +34,7 @@ /// -### ๆ›ดๅคšไฟกๆฏ +### ๆ›ดๅคšไฟกๆฏ { #more-info } /// note | ๆŠ€ๆœฏ็ป†่Š‚ diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md index 4d9cd53f2f..8a9cf6ab89 100644 --- a/docs/zh/docs/advanced/response-directly.md +++ b/docs/zh/docs/advanced/response-directly.md @@ -1,4 +1,4 @@ -# ็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ” +# ็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ” { #return-a-response-directly } ๅฝ“ไฝ ๅˆ›ๅปบไธ€ไธช **FastAPI** *่ทฏๅพ„ๆ“ไฝœ* ๆ—ถ๏ผŒไฝ ๅฏไปฅๆญฃๅธธ่ฟ”ๅ›žไปฅไธ‹ไปปๆ„ไธ€็งๆ•ฐๆฎ๏ผš`dict`๏ผŒ`list`๏ผŒPydantic ๆจกๅž‹๏ผŒๆ•ฐๆฎๅบ“ๆจกๅž‹็ญ‰็ญ‰ใ€‚ @@ -10,11 +10,11 @@ ็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”ๅฏ่ƒฝไผšๆœ‰็”จๅค„๏ผŒๆฏ”ๅฆ‚่ฟ”ๅ›ž่‡ชๅฎšไน‰็š„ๅ“ๅบ”ๅคดๅ’Œ cookiesใ€‚ -## ่ฟ”ๅ›ž `Response` +## ่ฟ”ๅ›ž `Response` { #return-a-response } ไบ‹ๅฎžไธŠ๏ผŒไฝ ๅฏไปฅ่ฟ”ๅ›žไปปๆ„ `Response` ๆˆ–่€…ไปปๆ„ `Response` ็š„ๅญ็ฑปใ€‚ -/// tip | ๅฐ่ดดๅฃซ +/// tip | ๆ็คบ `JSONResponse` ๆœฌ่บซๆ˜ฏไธ€ไธช `Response` ็š„ๅญ็ฑปใ€‚ @@ -26,18 +26,17 @@ ่ฟ™็ง็‰นๆ€ง็ป™ไฝ ๆžๅคง็š„ๅฏๆ‰ฉๅฑ•ๆ€งใ€‚ไฝ ๅฏไปฅ่ฟ”ๅ›žไปปไฝ•ๆ•ฐๆฎ็ฑปๅž‹๏ผŒ้‡ๅ†™ไปปไฝ•ๆ•ฐๆฎๅฃฐๆ˜Žๆˆ–่€…ๆ ก้ชŒ๏ผŒ็ญ‰็ญ‰ใ€‚ -## ๅœจ `Response` ไธญไฝฟ็”จ `jsonable_encoder` +## ๅœจ `Response` ไธญไฝฟ็”จ `jsonable_encoder` { #using-the-jsonable-encoder-in-a-response } ็”ฑไบŽ **FastAPI** ๅนถๆœชๅฏนไฝ ่ฟ”ๅ›ž็š„ `Response` ๅšไปปไฝ•ๆ”นๅ˜๏ผŒไฝ ๅฟ…้กป็กฎไฟไฝ ๅทฒ็ปๅ‡†ๅค‡ๅฅฝๅ“ๅบ”ๅ†…ๅฎนใ€‚ -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไธ้ฆ–ๅ…ˆๅฐ† Pydantic ๆจกๅž‹่ฝฌๆขไธบ `dict`๏ผŒๅนถๅฐ†ๆ‰€ๆœ‰ๆ•ฐๆฎ็ฑปๅž‹๏ผˆๅฆ‚ `datetime`ใ€`UUID` ็ญ‰๏ผ‰่ฝฌๆขไธบๅ…ผๅฎน JSON ็š„็ฑปๅž‹๏ผŒๅˆ™ไธ่ƒฝๅฐ†ๅ…ถๆ”พๅ…ฅJSONResponseไธญใ€‚ +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไธ้ฆ–ๅ…ˆๅฐ† Pydantic ๆจกๅž‹่ฝฌๆขไธบ `dict`๏ผŒๅนถๅฐ†ๆ‰€ๆœ‰ๆ•ฐๆฎ็ฑปๅž‹๏ผˆๅฆ‚ `datetime`ใ€`UUID` ็ญ‰๏ผ‰่ฝฌๆขไธบๅ…ผๅฎน JSON ็š„็ฑปๅž‹๏ผŒๅˆ™ไธ่ƒฝๅฐ†ๅ…ถๆ”พๅ…ฅ `JSONResponse` ไธญใ€‚ -ๅฏนไบŽ่ฟ™ไบ›ๆƒ…ๅ†ต๏ผŒๅœจๅฐ†ๆ•ฐๆฎไผ ้€’็ป™ๅ“ๅบ”ไน‹ๅ‰๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `jsonable_encoder` ๆฅ่ฝฌๆขไฝ ็š„ๆ•ฐๆฎใ€‚ +ๅฏนไบŽ่ฟ™ไบ›ๆƒ…ๅ†ต๏ผŒๅœจๅฐ†ๆ•ฐๆฎไผ ้€’็ป™ๅ“ๅบ”ไน‹ๅ‰๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `jsonable_encoder` ๆฅ่ฝฌๆขไฝ ็š„ๆ•ฐๆฎ๏ผš +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} -{* ../../docs_src/response_directly/tutorial001.py hl[4,6,20,21] *} - -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import JSONResponse`ใ€‚ @@ -45,22 +44,22 @@ /// -## ่ฟ”ๅ›ž่‡ชๅฎšไน‰ `Response` +## ่ฟ”ๅ›ž่‡ชๅฎšไน‰ `Response` { #returning-a-custom-response } -ไธŠ้ข็š„ไพ‹ๅญๅฑ•็คบไบ†้œ€่ฆ็š„ๆ‰€ๆœ‰้ƒจๅˆ†๏ผŒไฝ†่ฟ˜ไธๅคŸๅฎž็”จ๏ผŒๅ› ไธบไฝ ๆœฌๅฏไปฅๅชๆ˜ฏ็›ดๆŽฅ่ฟ”ๅ›ž `item`๏ผŒ่€Œ**FastAPI** ้ป˜่ฎคๅธฎไฝ ๆŠŠ่ฟ™ไธช `item` ๆ”พๅˆฐ `JSONResponse` ไธญ๏ผŒๅˆ้ป˜่ฎคๅฐ†ๅ…ถ่ฝฌๆขๆˆไบ† `dict`็ญ‰็ญ‰ใ€‚ +ไธŠ้ข็š„ไพ‹ๅญๅฑ•็คบไบ†้œ€่ฆ็š„ๆ‰€ๆœ‰้ƒจๅˆ†๏ผŒไฝ†่ฟ˜ไธๅคŸๅฎž็”จ๏ผŒๅ› ไธบไฝ ๆœฌๅฏไปฅๅชๆ˜ฏ็›ดๆŽฅ่ฟ”ๅ›ž `item`๏ผŒ่€Œ **FastAPI** ้ป˜่ฎคๅธฎไฝ ๆŠŠ่ฟ™ไธช `item` ๆ”พๅˆฐ `JSONResponse` ไธญ๏ผŒๅˆ้ป˜่ฎคๅฐ†ๅ…ถ่ฝฌๆขๆˆไบ† `dict` ็ญ‰็ญ‰ใ€‚ ็Žฐๅœจ๏ผŒ่ฎฉๆˆ‘ไปฌ็œ‹็œ‹ไฝ ๅฆ‚ไฝ•ๆ‰่ƒฝ่ฟ”ๅ›žไธ€ไธช่‡ชๅฎšไน‰็š„ๅ“ๅบ”ใ€‚ ๅ‡่ฎพไฝ ๆƒณ่ฆ่ฟ”ๅ›žไธ€ไธช XML ๅ“ๅบ”ใ€‚ -ไฝ ๅฏไปฅๆŠŠไฝ ็š„ XML ๅ†…ๅฎนๆ”พๅˆฐไธ€ไธชๅญ—็ฌฆไธฒไธญ๏ผŒๆ”พๅˆฐไธ€ไธช `Response` ไธญ๏ผŒ็„ถๅŽ่ฟ”ๅ›žใ€‚ +ไฝ ๅฏไปฅๆŠŠไฝ ็š„ XML ๅ†…ๅฎนๆ”พๅˆฐไธ€ไธชๅญ—็ฌฆไธฒไธญ๏ผŒๆ”พๅˆฐไธ€ไธช `Response` ไธญ๏ผŒ็„ถๅŽ่ฟ”ๅ›ž๏ผš -{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} -## ่ฏดๆ˜Ž +## ่ฏดๆ˜Ž { #notes } ๅฝ“ไฝ ็›ดๆŽฅ่ฟ”ๅ›ž `Response` ๆ—ถ๏ผŒๅฎƒ็š„ๆ•ฐๆฎๆ—ขๆฒกๆœ‰ๆ ก้ชŒ๏ผŒๅˆไธไผš่ฟ›่กŒ่ฝฌๆข๏ผˆๅบๅˆ—ๅŒ–๏ผ‰๏ผŒไนŸไธไผš่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃใ€‚ -ไฝ†ๆ˜ฏไฝ ไปๅฏไปฅๅ‚่€ƒ [OpenApI ไธญ็š„้ขๅค–ๅ“ๅบ”](additional-responses.md){.internal-link target=_blank} ็ป™ๅ“ๅบ”็ผ–ๅ†™ๆ–‡ๆกฃใ€‚ +ไฝ†ๆ˜ฏไฝ ไปๅฏไปฅๅ‚่€ƒ [OpenAPI ไธญ็š„้ขๅค–ๅ“ๅบ”](additional-responses.md){.internal-link target=_blank} ็ป™ๅ“ๅบ”็ผ–ๅ†™ๆ–‡ๆกฃใ€‚ ๅœจๅŽ็ปญ็š„็ซ ่Š‚ไธญไฝ ๅฏไปฅไบ†่งฃๅˆฐๅฆ‚ไฝ•ไฝฟ็”จ/ๅฃฐๆ˜Ž่ฟ™ไบ›่‡ชๅฎšไน‰็š„ `Response` ็š„ๅŒๆ—ถ่ฟ˜ไฟ็•™่‡ชๅŠจๅŒ–็š„ๆ•ฐๆฎ่ฝฌๆขๅ’Œๆ–‡ๆกฃ็ญ‰ใ€‚ diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md index 5c6a62e93c..fa02f53bea 100644 --- a/docs/zh/docs/advanced/response-headers.md +++ b/docs/zh/docs/advanced/response-headers.md @@ -1,39 +1,41 @@ -# ๅ“ๅบ”ๅคด +# ๅ“ๅบ”ๅคด { #response-headers } -## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ +## ไฝฟ็”จ `Response` ๅ‚ๆ•ฐ { #use-a-response-parameter } -ไฝ ๅฏไปฅๅœจไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Žไธ€ไธช`Response`็ฑปๅž‹็š„ๅ‚ๆ•ฐ๏ผˆๅฐฑๅƒไฝ ๅฏไปฅไธบcookiesๅš็š„้‚ฃๆ ท๏ผ‰ใ€‚ +ไฝ ๅฏไปฅๅœจไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Žไธ€ไธช `Response` ็ฑปๅž‹็š„ๅ‚ๆ•ฐ๏ผˆๅฐฑๅƒไฝ ๅฏไปฅไธบ cookies ๅš็š„้‚ฃๆ ท๏ผ‰ใ€‚ ็„ถๅŽไฝ ๅฏไปฅๅœจ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎๅคด้ƒจใ€‚ -{* ../../docs_src/response_headers/tutorial002.py hl[1,7:8] *} -็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช`dict`ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช`response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ +{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} -**FastAPI**ๅฐ†ไฝฟ็”จ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๆฅๆๅ–ๅคด้ƒจ๏ผˆไนŸๅŒ…ๆ‹ฌcookiesๅ’Œ็Šถๆ€็ ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ•`response_model`่ฟ‡ๆปคใ€‚ +็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช `dict` ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ -ไฝ ไนŸๅฏไปฅๅœจไพ่ต–้กนไธญๅฃฐๆ˜Ž`Response`ๅ‚ๆ•ฐ๏ผŒๅนถๅœจๅ…ถไธญ่ฎพ็ฝฎๅคด้ƒจ๏ผˆๅ’Œcookies๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช `response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ -## ็›ดๆŽฅ่ฟ”ๅ›ž `Response` +**FastAPI** ๅฐ†ไฝฟ็”จ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๆฅๆๅ–ๅคด้ƒจ๏ผˆไนŸๅŒ…ๆ‹ฌ cookies ๅ’Œ็Šถๆ€็ ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ• `response_model` ่ฟ‡ๆปคใ€‚ -ไฝ ไนŸๅฏไปฅๅœจ็›ดๆŽฅ่ฟ”ๅ›ž`Response`ๆ—ถๆทปๅŠ ๅคด้ƒจใ€‚ +ไฝ ไนŸๅฏไปฅๅœจไพ่ต–้กนไธญๅฃฐๆ˜Ž `Response` ๅ‚ๆ•ฐ๏ผŒๅนถๅœจๅ…ถไธญ่ฎพ็ฝฎๅคด้ƒจ๏ผˆๅ’Œ cookies๏ผ‰ใ€‚ -ๆŒ‰็…ง[็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”](response-directly.md){.internal-link target=_blank}ไธญๆ‰€่ฟฐๅˆ›ๅปบๅ“ๅบ”๏ผŒๅนถๅฐ†ๅคด้ƒจไฝœไธบ้™„ๅŠ ๅ‚ๆ•ฐไผ ้€’๏ผš +## ็›ดๆŽฅ่ฟ”ๅ›ž `Response` { #return-a-response-directly } + +ไฝ ไนŸๅฏไปฅๅœจ็›ดๆŽฅ่ฟ”ๅ›ž `Response` ๆ—ถๆทปๅŠ ๅคด้ƒจใ€‚ -{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *} +ๆŒ‰็…ง[็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”](response-directly.md){.internal-link target=_blank}ไธญๆ‰€่ฟฐๅˆ›ๅปบๅ“ๅบ”๏ผŒๅนถๅฐ†ๅคด้ƒจไฝœไธบ้™„ๅŠ ๅ‚ๆ•ฐไผ ้€’๏ผš +{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ไฝ ไนŸๅฏไปฅไฝฟ็”จ`from starlette.responses import Response`ๆˆ–`from starlette.responses import JSONResponse`ใ€‚ +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import Response` ๆˆ– `from starlette.responses import JSONResponse`ใ€‚ -**FastAPI**ๆไพ›ไบ†ไธŽ`fastapi.responses`็›ธๅŒ็š„`starlette.responses`๏ผŒๅชๆ˜ฏไธบไบ†ๆ–นไพฟๅผ€ๅ‘่€…ใ€‚ไฝ†ๆ˜ฏ๏ผŒๅคงๅคšๆ•ฐๅฏ็”จ็š„ๅ“ๅบ”้ƒฝ็›ดๆŽฅๆฅ่‡ชStarletteใ€‚ +**FastAPI** ๆไพ›ไบ†ไธŽ `fastapi.responses` ็›ธๅŒ็š„ `starlette.responses`๏ผŒๅชๆ˜ฏไธบไบ†ๆ–นไพฟไฝ ๏ผˆๅผ€ๅ‘่€…๏ผ‰ใ€‚ไฝ†ๆ˜ฏ๏ผŒๅคงๅคšๆ•ฐๅฏ็”จ็š„ๅ“ๅบ”้ƒฝ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ -็”ฑไบŽ`Response`็ปๅธธ็”จไบŽ่ฎพ็ฝฎๅคด้ƒจๅ’Œcookies๏ผŒๅ› ๆญค**FastAPI**่ฟ˜ๅœจ`fastapi.Response`ไธญๆไพ›ไบ†ๅฎƒใ€‚ +็”ฑไบŽ `Response` ็ปๅธธ็”จไบŽ่ฎพ็ฝฎๅคด้ƒจๅ’Œ cookies๏ผŒ**FastAPI** ่ฟ˜ๅœจ `fastapi.Response` ไธญๆไพ›ไบ†ๅฎƒใ€‚ /// -## ่‡ชๅฎšไน‰ๅคด้ƒจ +## ่‡ชๅฎšไน‰ๅคด้ƒจ { #custom-headers } -่ฏทๆณจๆ„๏ผŒๅฏไปฅไฝฟ็”จ'X-'ๅ‰็ผ€ๆทปๅŠ ่‡ชๅฎšไน‰ไธ“ๆœ‰ๅคด้ƒจใ€‚ +่ฏทๆณจๆ„๏ผŒๅฏไปฅ้€š่ฟ‡ไฝฟ็”จ `X-` ๅ‰็ผ€ๆทปๅŠ ่‡ชๅฎšไน‰ไธ“ๆœ‰ๅคด้ƒจใ€‚ -ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ ๆœ‰่‡ชๅฎšไน‰ๅคด้ƒจ๏ผŒไฝ ๅธŒๆœ›ๆต่งˆๅ™จไธญ็š„ๅฎขๆˆท็ซฏ่ƒฝๅคŸ็œ‹ๅˆฐๅฎƒไปฌ๏ผŒไฝ ้œ€่ฆๅฐ†ๅฎƒไปฌๆทปๅŠ ๅˆฐไฝ ็š„CORS้…็ฝฎไธญ๏ผˆๅœจ[CORS๏ผˆ่ทจๆบ่ต„ๆบๅ…ฑไบซ๏ผ‰](../tutorial/cors.md){.internal-link target=_blank}ไธญ้˜…่ฏปๆ›ดๅคš๏ผ‰๏ผŒไฝฟ็”จๅœจStarlette็š„CORSๆ–‡ๆกฃไธญ่ฎฐๅฝ•็š„`expose_headers`ๅ‚ๆ•ฐใ€‚ +ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ ๆœ‰่‡ชๅฎšไน‰ๅคด้ƒจ๏ผŒๅนถๅธŒๆœ›ๆต่งˆๅ™จไธญ็š„ๅฎขๆˆท็ซฏ่ƒฝๅคŸ็œ‹ๅˆฐๅฎƒไปฌ๏ผŒไฝ ้œ€่ฆๅฐ†ๅฎƒไปฌๆทปๅŠ ๅˆฐไฝ ็š„ CORS ้…็ฝฎไธญ๏ผˆๅœจ [CORS๏ผˆ่ทจๆบ่ต„ๆบๅ…ฑไบซ๏ผ‰](../tutorial/cors.md){.internal-link target=_blank} ไธญ้˜…่ฏปๆ›ดๅคš๏ผ‰๏ผŒไฝฟ็”จๅœจ Starlette ็š„ CORS ๆ–‡ๆกฃไธญ่ฎฐๅฝ•็š„ `expose_headers` ๅ‚ๆ•ฐใ€‚ diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md index 599429f9d2..55479d8e34 100644 --- a/docs/zh/docs/advanced/security/http-basic-auth.md +++ b/docs/zh/docs/advanced/security/http-basic-auth.md @@ -1,4 +1,4 @@ -# HTTP ๅŸบ็ก€ๆŽˆๆƒ +# HTTP ๅŸบ็ก€ๆŽˆๆƒ { #http-basic-auth } ๆœ€็ฎ€ๅ•็š„็”จไพ‹ๆ˜ฏไฝฟ็”จ HTTP ๅŸบ็ก€ๆŽˆๆƒ๏ผˆHTTP Basic Auth๏ผ‰ใ€‚ @@ -6,16 +6,16 @@ ๅฆ‚ๆžœๆฒกๆœ‰ๆŽฅๆ”ถๅˆฐ HTTP ๅŸบ็ก€ๆŽˆๆƒ๏ผŒๅฐฑ่ฟ”ๅ›ž HTTP 401 `"Unauthorized"` ้”™่ฏฏใ€‚ -ๅนถ่ฟ”ๅ›žๅซ `Basic` ๅ€ผ็š„่ฏทๆฑ‚ๅคด `WWW-Authenticate`ไปฅๅŠๅฏ้€‰็š„ `realm` ๅ‚ๆ•ฐใ€‚ +ๅนถ่ฟ”ๅ›žๅ“ๅบ”ๅคด `WWW-Authenticate`๏ผŒๅ…ถๅ€ผไธบ `Basic`๏ผŒไปฅๅŠๅฏ้€‰็š„ `realm` ๅ‚ๆ•ฐใ€‚ HTTP ๅŸบ็ก€ๆŽˆๆƒ่ฎฉๆต่งˆๅ™จๆ˜พ็คบๅ†…็ฝฎ็š„็”จๆˆทๅไธŽๅฏ†็ ๆ็คบใ€‚ ่พ“ๅ…ฅ็”จๆˆทๅไธŽๅฏ†็ ๅŽ๏ผŒๆต่งˆๅ™จไผšๆŠŠๅฎƒไปฌ่‡ชๅŠจๅ‘้€่‡ณ่ฏทๆฑ‚ๅคดใ€‚ -## ็ฎ€ๅ•็š„ HTTP ๅŸบ็ก€ๆŽˆๆƒ +## ็ฎ€ๅ•็š„ HTTP ๅŸบ็ก€ๆŽˆๆƒ { #simple-http-basic-auth } * ๅฏผๅ…ฅ `HTTPBasic` ไธŽ `HTTPBasicCredentials` -* ไฝฟ็”จ `HTTPBasic` ๅˆ›ๅปบ**ๅฎ‰ๅ…จๆฆ‚ๅ›พ** +* ไฝฟ็”จ `HTTPBasic` ๅˆ›ๅปบ**ๅฎ‰ๅ…จๆ–นๆกˆ** * ๅœจ*่ทฏๅพ„ๆ“ไฝœ*็š„ไพ่ต–้กนไธญไฝฟ็”จ `security` * ่ฟ”ๅ›ž็ฑปๅž‹ไธบ `HTTPBasicCredentials` ็š„ๅฏน่ฑก๏ผš * ๅŒ…ๅซๅ‘้€็š„ `username` ไธŽ `password` @@ -26,7 +26,7 @@ HTTP ๅŸบ็ก€ๆŽˆๆƒ่ฎฉๆต่งˆๅ™จๆ˜พ็คบๅ†…็ฝฎ็š„็”จๆˆทๅไธŽๅฏ†็ ๆ็คบใ€‚ -## ๆฃ€ๆŸฅ็”จๆˆทๅ +## ๆฃ€ๆŸฅ็”จๆˆทๅ { #check-the-username } ไปฅไธ‹ๆ˜ฏๆ›ดๅฎŒๆ•ด็š„็คบไพ‹ใ€‚ @@ -52,13 +52,13 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password == ไฝ†ไฝฟ็”จ `secrets.compare_digest()`๏ผŒๅฏไปฅ้˜ฒๅพก**ๆ—ถๅทฎๆ”ปๅ‡ป**๏ผŒๆ›ดๅŠ ๅฎ‰ๅ…จใ€‚ -### ๆ—ถๅทฎๆ”ปๅ‡ป +### ๆ—ถๅทฎๆ”ปๅ‡ป { #timing-attacks } ไป€ไนˆๆ˜ฏ**ๆ—ถๅทฎๆ”ปๅ‡ป**๏ผŸ ๅ‡่ฎพๆ”ปๅ‡ป่€…่ฏ•ๅ›พ็Œœๅ‡บ็”จๆˆทๅไธŽๅฏ†็ ใ€‚ -ไป–ไปฌๅ‘้€็”จๆˆทๅไธบ `johndoe`๏ผŒๅฏ†็ ไธบ `love123` ็š„่ฏทๆฑ‚ใ€‚ +ไป–ไปฌๅ‘้€็”จๆˆทๅไธบ `johndoe`๏ผŒๅฏ†็ ไธบ `love123` ็š„่ฏทๆฑ‚ใ€‚ ็„ถๅŽ๏ผŒPython ไปฃ็ ๆ‰ง่กŒๅฆ‚ไธ‹ๆ“ไฝœ๏ผš @@ -80,28 +80,28 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": ๆญคๆ—ถ๏ผŒPython ่ฆๅฏนๆฏ” `stanleyjobsox` ไธŽ `stanleyjobson` ไธญ็š„ `stanleyjobso`๏ผŒๆ‰่ƒฝ็Ÿฅ้“่ฟ™ไธคไธชๅญ—็ฌฆไธฒไธไธ€ๆ ทใ€‚ๅ› ๆญคไผšๅคš่Šฑ่ดนๅ‡ ๅพฎ็ง’ๆฅ่ฟ”ๅ›ž**้”™่ฏฏ็š„็”จๆˆทๆˆ–ๅฏ†็ **ใ€‚ -#### ๅๅบ”ๆ—ถ้—ดๅฏนๆ”ปๅ‡ป่€…็š„ๅธฎๅŠฉ +#### ๅๅบ”ๆ—ถ้—ดๅฏนๆ”ปๅ‡ป่€…็š„ๅธฎๅŠฉ { #the-time-to-answer-helps-the-attackers } ้€š่ฟ‡ๆœๅŠกๅ™จ่Šฑ่ดนไบ†ๆ›ดๅคšๅพฎ็ง’ๆ‰ๅ‘้€**้”™่ฏฏ็š„็”จๆˆทๆˆ–ๅฏ†็ **ๅ“ๅบ”๏ผŒๆ”ปๅ‡ป่€…ไผš็Ÿฅ้“็Œœๅฏนไบ†ไธ€ไบ›ๅ†…ๅฎน๏ผŒ่ตท็ ๅผ€ๅคดๅญ—ๆฏๆ˜ฏๆญฃ็กฎ็š„ใ€‚ ็„ถๅŽ๏ผŒไป–ไปฌๅฐฑๅฏไปฅๆ”พๅผƒ `johndoe`๏ผŒๅ†็”จ็ฑปไผผ `stanleyjobsox` ็š„ๅ†…ๅฎน่ฟ›่กŒๅฐ่ฏ•ใ€‚ -#### **ไธ“ไธš**ๆ”ปๅ‡ป +#### **ไธ“ไธš**ๆ”ปๅ‡ป { #a-professional-attack } ๅฝ“็„ถ๏ผŒๆ”ปๅ‡ป่€…ไธ็”จๆ‰‹ๅŠจๆ“ไฝœ๏ผŒ่€Œๆ˜ฏ็ผ–ๅ†™ๆฏ็ง’่ƒฝๆ‰ง่กŒๆˆๅƒไธŠไธ‡ๆฌกๆต‹่ฏ•็š„ๆ”ปๅ‡ป็จ‹ๅบ๏ผŒๆฏๆฌก้ƒฝไผšๆ‰พๅˆฐๆ›ดๅคšๆญฃ็กฎๅญ—็ฌฆใ€‚ ไฝ†ๆ˜ฏ๏ผŒๅœจๆ‚จ็š„ๅบ”็”จ็š„**ๅธฎๅŠฉ**ไธ‹๏ผŒๆ”ปๅ‡ป่€…ๅˆฉ็”จๆ—ถ้—ดๅทฎ๏ผŒๅฐฑ่ƒฝๅœจๅ‡ ๅˆ†้’Ÿๆˆ–ๅ‡ ๅฐๆ—ถๅ†…๏ผŒไปฅ่ฟ™็งๆ–นๅผ็Œœๅ‡บๆญฃ็กฎ็š„็”จๆˆทๅๅ’Œๅฏ†็ ใ€‚ -#### ไฝฟ็”จ `secrets.compare_digest()` ไฟฎ่กฅ +#### ไฝฟ็”จ `secrets.compare_digest()` ไฟฎ่กฅ { #fix-it-with-secrets-compare-digest } ๅœจๆญค๏ผŒไปฃ็ ไธญไฝฟ็”จไบ† `secrets.compare_digest()`ใ€‚ ็ฎ€ๅ•็š„่ฏด๏ผŒๅฎƒไฝฟ็”จ็›ธๅŒ็š„ๆ—ถ้—ดๅฏนๆฏ” `stanleyjobsox` ๅ’Œ `stanleyjobson`๏ผŒ่ฟ˜ๆœ‰ `johndoe` ๅ’Œ `stanleyjobson`ใ€‚ๅฏนๆฏ”ๅฏ†็ ๆ—ถไนŸไธ€ๆ ทใ€‚ -ๅœจไปฃ็ ไธญไฝฟ็”จ `secrets.compare_digest()` ๏ผŒๅฐฑๅฏไปฅๅฎ‰ๅ…จๅœฐ้˜ฒๅพกๅ…จ้ขๆ”ปๅ‡ปไบ†ใ€‚ +ๅœจไปฃ็ ไธญไฝฟ็”จ `secrets.compare_digest()` ๏ผŒๅฐฑๅฏไปฅๅฎ‰ๅ…จๅœฐ้˜ฒๅพก่ฟ™ๆ•ด็ฑปๅฎ‰ๅ…จๆ”ปๅ‡ปใ€‚ -### ่ฟ”ๅ›ž้”™่ฏฏ +### ่ฟ”ๅ›ž้”™่ฏฏ { #return-the-error } -ๆฃ€ๆต‹ๅˆฐๅ‡ญ่ฏไธๆญฃ็กฎๅŽ๏ผŒ่ฟ”ๅ›ž `HTTPException` ๅŠ็Šถๆ€็  401๏ผˆไธŽๆ— ๅ‡ญ่ฏๆ—ถ่ฟ”ๅ›ž็š„ๅ†…ๅฎนไธ€ๆ ท๏ผ‰๏ผŒๅนถๆทปๅŠ ่ฏทๆฑ‚ๅคด `WWW-Authenticate`๏ผŒ่ฎฉๆต่งˆๅ™จๅ†ๆฌกๆ˜พ็คบ็™ปๅฝ•ๆ็คบ๏ผš +ๆฃ€ๆต‹ๅˆฐๅ‡ญ่ฏไธๆญฃ็กฎๅŽ๏ผŒ่ฟ”ๅ›ž `HTTPException` ๅŠ็Šถๆ€็  401๏ผˆไธŽๆ— ๅ‡ญ่ฏๆ—ถ่ฟ”ๅ›ž็š„ๅ†…ๅฎนไธ€ๆ ท๏ผ‰๏ผŒๅนถๆทปๅŠ ๅ“ๅบ”ๅคด `WWW-Authenticate`๏ผŒ่ฎฉๆต่งˆๅ™จๅ†ๆฌกๆ˜พ็คบ็™ปๅฝ•ๆ็คบ๏ผš {* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md index 267e7ced70..84fec7aab8 100644 --- a/docs/zh/docs/advanced/security/index.md +++ b/docs/zh/docs/advanced/security/index.md @@ -1,19 +1,19 @@ -# ้ซ˜็บงๅฎ‰ๅ…จ +# ้ซ˜็บงๅฎ‰ๅ…จ { #advanced-security } -## ้™„ๅŠ ็‰นๆ€ง +## ้™„ๅŠ ็‰นๆ€ง { #additional-features } -้™ค [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—: ๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank} ไธญๆถต็›–็š„ๅŠŸ่ƒฝไน‹ๅค–๏ผŒ่ฟ˜ๆœ‰ไธ€ไบ›้ขๅค–็š„ๅŠŸ่ƒฝๆฅๅค„็†ๅฎ‰ๅ…จๆ€ง. +้™ค [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—: ๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank} ไธญๆถต็›–็š„ๅŠŸ่ƒฝไน‹ๅค–๏ผŒ่ฟ˜ๆœ‰ไธ€ไบ›้ขๅค–็š„ๅŠŸ่ƒฝๆฅๅค„็†ๅฎ‰ๅ…จๆ€งใ€‚ -/// tip | ๅฐ่ดดๅฃซ +/// tip | ๆ็คบ -ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ **ๅนถไธไธ€ๅฎšๆ˜ฏ "้ซ˜็บง็š„"**. +ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚**ๅนถไธไธ€ๅฎšๆ˜ฏ "้ซ˜็บง็š„"**ใ€‚ ่€Œไธ”ๅฏนไบŽไฝ ็š„ไฝฟ็”จๅœบๆ™ฏๆฅ่ฏด๏ผŒ่งฃๅ†ณๆ–นๆกˆๅพˆๅฏ่ƒฝๅฐฑๅœจๅ…ถไธญใ€‚ /// -## ๅ…ˆ้˜…่ฏปๆ•™็จ‹ +## ๅ…ˆ้˜…่ฏปๆ•™็จ‹ { #read-the-tutorial-first } -ๆŽฅไธ‹ๆฅ็š„้ƒจๅˆ†ๅ‡่ฎพไฝ ๅทฒ็ป้˜…่ฏปไบ†ไธป่ฆ็š„ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—: ๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank}. +ๆŽฅไธ‹ๆฅ็š„้ƒจๅˆ†ๅ‡่ฎพไฝ ๅทฒ็ป้˜…่ฏปไบ†ไธป่ฆ็š„ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—: ๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank}ใ€‚ -ๅฎƒไปฌ้ƒฝๅŸบไบŽ็›ธๅŒ็š„ๆฆ‚ๅฟต๏ผŒไฝ†ๆ”ฏๆŒไธ€ไบ›้ขๅค–็š„ๅŠŸ่ƒฝ. +ๅฎƒไปฌ้ƒฝๅŸบไบŽ็›ธๅŒ็š„ๆฆ‚ๅฟต๏ผŒไฝ†ๆ”ฏๆŒไธ€ไบ›้ขๅค–็š„ๅŠŸ่ƒฝใ€‚ diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md index 784c384901..ce7facf4be 100644 --- a/docs/zh/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh/docs/advanced/security/oauth2-scopes.md @@ -1,274 +1,274 @@ -# OAuth2 ไฝœ็”จๅŸŸ +# OAuth2 ไฝœ็”จๅŸŸ { #oauth2-scopes } -**FastAPI** ๆ— ็ผ้›†ๆˆ OAuth2 ไฝœ็”จๅŸŸ๏ผˆ`Scopes`๏ผ‰๏ผŒๅฏไปฅ็›ดๆŽฅไฝฟ็”จใ€‚ +ไฝ ๅฏไปฅๅœจ **FastAPI** ไธญ็›ดๆŽฅไฝฟ็”จ OAuth2 ไฝœ็”จๅŸŸ๏ผˆScopes๏ผ‰๏ผŒๅฎƒไปฌๅทฒๆ— ็ผ้›†ๆˆใ€‚ -ไฝœ็”จๅŸŸๆ˜ฏๆ›ด็ฒพๅฏ†็š„ๆƒ้™็ณป็ปŸ๏ผŒ้ตๅพช OAuth2 ๆ ‡ๅ‡†๏ผŒไธŽ OpenAPI ๅบ”็”จ๏ผˆๅ’Œ API ่‡ชๅŠจๆ–‡ๆกฃ๏ผ‰้›†ๆˆใ€‚ +่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๆŒ‰็…ง OAuth2 ๆ ‡ๅ‡†๏ผŒๆž„ๅปบๆ›ด็ฒพ็ป†็š„ๆƒ้™็ณป็ปŸ๏ผŒๅนถๅฐ†ๅ…ถ้›†ๆˆ่ฟ›ไฝ ็š„ OpenAPI ๅบ”็”จ๏ผˆไปฅๅŠ API ๆ–‡ๆกฃ๏ผ‰ไธญใ€‚ -OAuth2 ไนŸๆ˜ฏ่„ธไนฆใ€่ฐทๆญŒใ€GitHubใ€ๅพฎ่ฝฏใ€ๆŽจ็‰น็ญ‰็ฌฌไธ‰ๆ–น่บซไปฝ้ชŒ่ฏๅบ”็”จไฝฟ็”จ็š„ๆœบๅˆถใ€‚่ฟ™ไบ›่บซไปฝ้ชŒ่ฏๅบ”็”จๅœจ็”จๆˆท็™ปๅฝ•ๅบ”็”จๆ—ถไฝฟ็”จ OAuth2 ๆไพ›ๆŒ‡ๅฎšๆƒ้™ใ€‚ +ๅธฆไฝœ็”จๅŸŸ็š„ OAuth2 ๆ˜ฏๅพˆๅคšๅคงๅž‹่บซไปฝ้ชŒ่ฏๆไพ›ๅ•†ไฝฟ็”จ็š„ๆœบๅˆถ๏ผŒไพ‹ๅฆ‚ Facebookใ€Googleใ€GitHubใ€Microsoftใ€X (Twitter) ็ญ‰ใ€‚ๅฎƒไปฌ็”จๅฎƒๆฅไธบ็”จๆˆทๅ’Œๅบ”็”จๆŽˆไบˆ็‰นๅฎšๆƒ้™ใ€‚ -่„ธไนฆใ€่ฐทๆญŒใ€GitHubใ€ๅพฎ่ฝฏใ€ๆŽจ็‰นๅฐฑๆ˜ฏ OAuth2 ไฝœ็”จๅŸŸ็™ปๅฝ•ใ€‚ +ๆฏๆฌกไฝ โ€œไฝฟ็”จโ€ Facebookใ€Googleใ€GitHubใ€Microsoftใ€X (Twitter) โ€œ็™ปๅฝ•โ€ๆ—ถ๏ผŒ่ฏฅๅบ”็”จๅฐฑๅœจไฝฟ็”จๅธฆไฝœ็”จๅŸŸ็š„ OAuth2ใ€‚ -ๆœฌ็ซ ไป‹็ปๅฆ‚ไฝ•ๅœจ **FastAPI** ๅบ”็”จไธญไฝฟ็”จ OAuth2 ไฝœ็”จๅŸŸ็ฎก็†้ชŒ่ฏไธŽๆŽˆๆƒใ€‚ +ๆœฌ่Š‚ๅฐ†ไป‹็ปๅฆ‚ไฝ•ๅœจไฝ ็š„ **FastAPI** ๅบ”็”จไธญ๏ผŒไฝฟ็”จ็›ธๅŒ็š„ๅธฆไฝœ็”จๅŸŸ็š„ OAuth2 ็ฎก็†่ฎค่ฏไธŽๆŽˆๆƒใ€‚ /// warning | ่ญฆๅ‘Š -ๆœฌ็ซ ๅ†…ๅฎน่พƒ้šพ๏ผŒๅˆšๆŽฅ่งฆ FastAPI ็š„ๆ–ฐๆ‰‹ๅฏไปฅ่ทณ่ฟ‡ใ€‚ +ๆœฌ่Š‚ๅ†…ๅฎน็›ธๅฏน่ฟ›้˜ถ๏ผŒๅฆ‚ๆžœไฝ ๅˆšๅผ€ๅง‹๏ผŒๅฏไปฅๅ…ˆ่ทณ่ฟ‡ใ€‚ -OAuth2 ไฝœ็”จๅŸŸไธๆ˜ฏๅฟ…้œ€็š„๏ผŒๆฒกๆœ‰ๅฎƒ๏ผŒๆ‚จไนŸๅฏไปฅๅค„็†่บซไปฝ้ชŒ่ฏไธŽๆŽˆๆƒใ€‚ +ไฝ ๅนถไธไธ€ๅฎš้œ€่ฆ OAuth2 ไฝœ็”จๅŸŸ๏ผŒไฝ ไนŸๅฏไปฅ็”จไฝ ่‡ชๅทฑ็š„ๆ–นๅผๅค„็†่ฎค่ฏไธŽๆŽˆๆƒใ€‚ -ไฝ† OAuth2 ไฝœ็”จๅŸŸไธŽ API๏ผˆ้€š่ฟ‡ OpenAPI๏ผ‰ๅŠ API ๆ–‡ๆกฃ้›†ๆˆๅœฐๆ›ดๅฅฝใ€‚ +ไฝ†ๅธฆไฝœ็”จๅŸŸ็š„ OAuth2 ่ƒฝๅพˆๅฅฝๅœฐ้›†ๆˆ่ฟ›ไฝ ็š„ API๏ผˆ้€š่ฟ‡ OpenAPI๏ผ‰ๅ’Œ API ๆ–‡ๆกฃใ€‚ -ไธ็ฎกๆ€Žไนˆ่ฏด๏ผŒ**FastAPI** ๆ”ฏๆŒๅœจไปฃ็ ไธญไฝฟ็”จไฝœ็”จๅŸŸๆˆ–ๅ…ถๅฎƒๅฎ‰ๅ…จ/ๆŽˆๆƒ้œ€ๆฑ‚้กนใ€‚ +ไธ่ฟ‡๏ผŒๆ— ่ฎบๅฆ‚ไฝ•๏ผŒไฝ ้ƒฝๅฏไปฅๅœจไปฃ็ ไธญๆŒ‰้œ€ๅผบๅˆถ่ฟ™ไบ›ไฝœ็”จๅŸŸ๏ผŒๆˆ–ไปปไฝ•ๅ…ถๅฎƒๅฎ‰ๅ…จ/ๆŽˆๆƒ้œ€ๆฑ‚ใ€‚ -ๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒOAuth2 ไฝœ็”จๅŸŸๅฐฑๅƒไธ€ๆŠŠ็‰›ๅˆ€ใ€‚ +ๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒๅธฆไฝœ็”จๅŸŸ็š„ OAuth2 ๅฏ่ƒฝๆœ‰็‚นโ€œๅคงๆๅฐ็”จโ€ใ€‚ -ไฝ†ๅฆ‚ๆžœๆ‚จ็กฎๅฎš่ฆไฝฟ็”จไฝœ็”จๅŸŸ๏ผŒๆˆ–ๅฏนๅฎƒๆœ‰ๅ…ด่ถฃ๏ผŒ่ฏท็ปง็ปญ้˜…่ฏปใ€‚ +ไฝ†ๅฆ‚ๆžœไฝ ็กฎๅฎž้œ€่ฆๅฎƒ๏ผŒๆˆ–่€…ๅชๆ˜ฏๅฅฝๅฅ‡๏ผŒ่ฏท็ปง็ปญ้˜…่ฏปใ€‚ /// -## OAuth2 ไฝœ็”จๅŸŸไธŽ OpenAPI +## OAuth2 ไฝœ็”จๅŸŸไธŽ OpenAPI { #oauth2-scopes-and-openapi } -OAuth2 ่ง„่Œƒ็š„**ไฝœ็”จๅŸŸ**ๆ˜ฏ็”ฑ็ฉบๆ ผๅˆ†ๅ‰ฒ็š„ๅญ—็ฌฆไธฒ็ป„ๆˆ็š„ๅˆ—่กจใ€‚ +OAuth2 ่ง„่Œƒๅฐ†โ€œไฝœ็”จๅŸŸโ€ๅฎšไน‰ไธบ็”ฑ็ฉบๆ ผๅˆ†้š”็š„ๅญ—็ฌฆไธฒๅˆ—่กจใ€‚ -่ฟ™ไบ›ๅญ—็ฌฆไธฒๆ”ฏๆŒไปปไฝ•ๆ ผๅผ๏ผŒไฝ†ไธ่ƒฝๅŒ…ๅซ็ฉบๆ ผใ€‚ +่ฟ™ไบ›ๅญ—็ฌฆไธฒ็š„ๅ†…ๅฎนๅฏไปฅๆ˜ฏไปปๆ„ๆ ผๅผ๏ผŒไฝ†ไธๅบ”ๅŒ…ๅซ็ฉบๆ ผใ€‚ -ไฝœ็”จๅŸŸ่กจ็คบ็š„ๆ˜ฏ**ๆƒ้™**ใ€‚ +่ฟ™ไบ›ไฝœ็”จๅŸŸ่กจ็คบโ€œๆƒ้™โ€ใ€‚ -OpenAPI ไธญ๏ผˆไพ‹ๅฆ‚ API ๆ–‡ๆกฃ๏ผ‰ๅฏไปฅๅฎšไน‰**ๅฎ‰ๅ…จๆ–นๆกˆ**ใ€‚ +ๅœจ OpenAPI๏ผˆไพ‹ๅฆ‚ API ๆ–‡ๆกฃ๏ผ‰ไธญ๏ผŒไฝ ๅฏไปฅๅฎšไน‰โ€œๅฎ‰ๅ…จๆ–นๆกˆโ€๏ผˆsecurity schemes๏ผ‰ใ€‚ -่ฟ™ไบ›ๅฎ‰ๅ…จๆ–นๆกˆๅœจไฝฟ็”จ OAuth2 ๆ—ถ๏ผŒ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žๅ’Œไฝฟ็”จไฝœ็”จๅŸŸใ€‚ +ๅฝ“่ฟ™ไบ›ๅฎ‰ๅ…จๆ–นๆกˆไฝฟ็”จ OAuth2 ๆ—ถ๏ผŒไฝ ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žๅนถไฝฟ็”จไฝœ็”จๅŸŸใ€‚ -**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏ๏ผˆไธๅธฆ็ฉบๆ ผ็š„๏ผ‰ๅญ—็ฌฆไธฒใ€‚ +ๆฏไธชโ€œไฝœ็”จๅŸŸโ€ๅชๆ˜ฏไธ€ไธช๏ผˆไธๅธฆ็ฉบๆ ผ็š„๏ผ‰ๅญ—็ฌฆไธฒใ€‚ -ๅธธ็”จไบŽๅฃฐๆ˜Ž็‰นๅฎšๅฎ‰ๅ…จๆƒ้™๏ผŒไพ‹ๅฆ‚๏ผš +ๅฎƒไปฌ้€šๅธธ็”จไบŽๅฃฐๆ˜Ž็‰นๅฎš็š„ๅฎ‰ๅ…จๆƒ้™๏ผŒไพ‹ๅฆ‚๏ผš -* ๅธธ่ง็”จไพ‹ไธบ๏ผŒ`users:read` ๆˆ– `users:write` -* ่„ธไนฆๅ’Œ Instagram ไฝฟ็”จ `instagram_basic` -* ่ฐทๆญŒไฝฟ็”จ `https://www.googleapis.com/auth/drive` +* ๅธธ่ง็คบไพ‹๏ผš`users:read` ๆˆ– `users:write` +* Facebook / Instagram ไฝฟ็”จ `instagram_basic` +* Google ไฝฟ็”จ `https://www.googleapis.com/auth/drive` -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜Ž็‰นๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ +ๅœจ OAuth2 ไธญ๏ผŒโ€œไฝœ็”จๅŸŸโ€ๅชๆ˜ฏไธ€ไธชๅฃฐๆ˜Žๆ‰€้œ€็‰นๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ -ๆ˜ฏๅฆไฝฟ็”จๅ†’ๅท `:` ็ญ‰็ฌฆๅท๏ผŒๆˆ–ๆ˜ฏไธๆ˜ฏ URL ๅนถไธ้‡่ฆใ€‚ +ๆ˜ฏๅฆๅŒ…ๅซๅƒ `:` ่ฟ™ๆ ท็š„ๅญ—็ฌฆ๏ผŒๆˆ–่€…ๆ˜ฏไธๆ˜ฏไธ€ไธช URL๏ผŒๅนถไธ้‡่ฆใ€‚ -่ฟ™ไบ›็ป†่Š‚ๅชๆ˜ฏ็‰นๅฎš็š„ๅฎž็Žฐๆ–นๅผใ€‚ +่ฟ™ไบ›็ป†่Š‚ๅ–ๅ†ณไบŽๅ…ทไฝ“ๅฎž็Žฐใ€‚ -ๅฏน OAuth2 ๆฅ่ฏด๏ผŒๅฎƒไปฌ้ƒฝๅชๆ˜ฏๅญ—็ฌฆไธฒ่€Œๅทฒใ€‚ +ๅฏน OAuth2 ่€Œ่จ€๏ผŒๅฎƒไปฌ้ƒฝๅชๆ˜ฏๅญ—็ฌฆไธฒใ€‚ /// -## ๅ…จๅฑ€็บต่งˆ +## ๅ…จๅฑ€็บต่งˆ { #global-view } -้ฆ–ๅ…ˆ๏ผŒๅฟซ้€Ÿๆต่งˆไธ€ไธ‹ไปฅไธ‹ไปฃ็ ไธŽ**็”จๆˆทๆŒ‡ๅ—**ไธญ [OAuth2 ๅฎž็Žฐๅฏ†็ ๅ“ˆๅธŒไธŽ Bearer JWT ไปค็‰Œ้ชŒ่ฏ](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}ไธ€็ซ ไธญไปฃ็ ็š„ๅŒบๅˆซใ€‚ไปฅไธ‹ไปฃ็ ไฝฟ็”จ OAuth2 ไฝœ็”จๅŸŸ๏ผš +้ฆ–ๅ…ˆ๏ผŒ่ฎฉๆˆ‘ไปฌๅฟซ้€Ÿ็œ‹็œ‹ไธŽ**็”จๆˆทๆŒ‡ๅ—**ไธญ [OAuth2 ๅฎž็Žฐๅฏ†็ ๏ผˆๅซๅ“ˆๅธŒ๏ผ‰ใ€Bearer + JWT ไปค็‰Œ](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ็คบไพ‹็›ธๆฏ”ๆœ‰ๅ“ชไบ›ๅ˜ๅŒ–ใ€‚็Žฐๅœจๅผ€ๅง‹ไฝฟ็”จ OAuth2 ไฝœ็”จๅŸŸ๏ผš -{* ../../docs_src/security/tutorial005.py hl[2,4,8,12,46,64,105,107:115,121:124,128:134,139,153] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} -ไธ‹้ข๏ผŒๆˆ‘ไปฌ้€ๆญฅ่ฏดๆ˜Žไฟฎๆ”น็š„ไปฃ็ ๅ†…ๅฎนใ€‚ +ไธ‹้ขๆˆ‘ไปฌ้€ๆญฅๅ›ž้กพ่ฟ™ไบ›ๆ›ดๆ”นใ€‚ -## OAuth2 ๅฎ‰ๅ…จๆ–นๆกˆ +## OAuth2 ๅฎ‰ๅ…จๆ–นๆกˆ { #oauth2-security-scheme } -็ฌฌไธ€ไธชไฟฎๆ”น็š„ๅœฐๆ–นๆ˜ฏ๏ผŒไฝฟ็”จไธคไธชไฝœ็”จๅŸŸ `me` ๅ’Œ `items ` ๅฃฐๆ˜Ž OAuth2 ๅฎ‰ๅ…จๆ–นๆกˆใ€‚ +็ฌฌไธ€ไธชๅ˜ๅŒ–ๆ˜ฏ๏ผšๆˆ‘ไปฌๅœจๅฃฐๆ˜Ž OAuth2 ๅฎ‰ๅ…จๆ–นๆกˆๆ—ถ๏ผŒๆทปๅŠ ไบ†ไธคไธชๅฏ็”จ็š„ไฝœ็”จๅŸŸ `me` ๅ’Œ `items`ใ€‚ -`scopes` ๅ‚ๆ•ฐๆŽฅๆ”ถ**ๅญ—ๅ…ธ**๏ผŒ้”ฎๆ˜ฏไฝœ็”จๅŸŸใ€ๅ€ผๆ˜ฏไฝœ็”จๅŸŸ็š„ๆ่ฟฐ๏ผš +ๅ‚ๆ•ฐ `scopes` ๆŽฅๆ”ถไธ€ไธช `dict`๏ผŒไปฅไฝœ็”จๅŸŸไธบ้”ฎใ€ๆ่ฟฐไธบๅ€ผ๏ผš -{* ../../docs_src/security/tutorial005.py hl[62:65] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -ๅ› ไธบๅฃฐๆ˜Žไบ†ไฝœ็”จๅŸŸ๏ผŒๆ‰€ไปฅ็™ปๅฝ•ๆˆ–ๆŽˆๆƒๆ—ถไผšๅœจ API ๆ–‡ๆกฃไธญๆ˜พ็คบใ€‚ +ๅ› ไธบๆˆ‘ไปฌ็Žฐๅœจๅฃฐๆ˜Žไบ†่ฟ™ไบ›ไฝœ็”จๅŸŸ๏ผŒๆ‰€ไปฅๅฝ“ไฝ ็™ปๅฝ•/ๆŽˆๆƒๆ—ถ๏ผŒๅฎƒไปฌไผšๆ˜พ็คบๅœจ API ๆ–‡ๆกฃ้‡Œใ€‚ -ๆญคๅค„๏ผŒ้€‰ๆ‹ฉ็ป™ไบˆ่ฎฟ้—ฎๆƒ้™็š„ไฝœ็”จๅŸŸ๏ผš `me` ๅ’Œ `items`ใ€‚ +ไฝ ๅฏไปฅ้€‰ๆ‹ฉ่ฆๆŽˆไบˆ่ฎฟ้—ฎๆƒ้™็š„ไฝœ็”จๅŸŸ๏ผš`me` ๅ’Œ `items`ใ€‚ -่ฟ™ไนŸๆ˜ฏไฝฟ็”จ่„ธไนฆใ€่ฐทๆญŒใ€GitHub ็™ปๅฝ•ๆ—ถ็š„ๆŽˆๆƒๆœบๅˆถใ€‚ +่ฟ™ไธŽไฝฟ็”จ Facebookใ€Googleใ€GitHub ็ญ‰็™ปๅฝ•ๆ—ถๆŽˆไบˆๆƒ้™็š„ๆœบๅˆถ็›ธๅŒ๏ผš -## JWT ไปค็‰Œไฝœ็”จๅŸŸ +## ๅธฆไฝœ็”จๅŸŸ็š„ JWT ไปค็‰Œ { #jwt-token-with-scopes } -็Žฐๅœจ๏ผŒไฟฎๆ”นไปค็‰Œ*่ทฏๅพ„ๆ“ไฝœ*๏ผŒ่ฟ”ๅ›ž่ฏทๆฑ‚็š„ไฝœ็”จๅŸŸใ€‚ +็Žฐๅœจ๏ผŒไฟฎๆ”นไปค็‰Œ็š„*่ทฏๅพ„ๆ“ไฝœ*ไปฅ่ฟ”ๅ›ž่ฏทๆฑ‚็š„ไฝœ็”จๅŸŸใ€‚ -ๆญคๅค„ไป็„ถไฝฟ็”จ `OAuth2PasswordRequestForm`ใ€‚ๅฎƒๅŒ…ๅซ็ฑปๅž‹ไธบ**ๅญ—็ฌฆไธฒๅˆ—่กจ**็š„ `scopes` ๅฑžๆ€ง๏ผŒไธ”`scopes` ๅฑžๆ€งไธญๅŒ…ๅซ่ฆๅœจ่ฏทๆฑ‚้‡ŒๆŽฅๆ”ถ็š„ๆฏไธชไฝœ็”จๅŸŸใ€‚ +ๆˆ‘ไปฌไป็„ถไฝฟ็”จ `OAuth2PasswordRequestForm`ใ€‚ๅฎƒๅŒ…ๅซ `scopes` ๅฑžๆ€ง๏ผŒๅ…ถๅ€ผๆ˜ฏ `list[str]`๏ผŒๅŒ…ๅซ่ฏทๆฑ‚ไธญๆŽฅๆ”ถๅˆฐ็š„ๆฏไธชไฝœ็”จๅŸŸใ€‚ -่ฟ™ๆ ท๏ผŒ่ฟ”ๅ›ž็š„ JWT ไปค็‰ŒไธญๅฐฑๅŒ…ๅซไบ†ไฝœ็”จๅŸŸใ€‚ +ๆˆ‘ไปฌๆŠŠ่ฟ™ไบ›ไฝœ็”จๅŸŸไฝœไธบ JWT ไปค็‰Œ็š„ไธ€้ƒจๅˆ†่ฟ”ๅ›žใ€‚ /// danger | ๅฑ้™ฉ -ไธบไบ†็ฎ€ๆ˜Ž่ตท่ง๏ผŒๆœฌไพ‹ๆŠŠๆŽฅๆ”ถ็š„ไฝœ็”จๅŸŸ็›ดๆŽฅๆทปๅŠ ๅˆฐไบ†ไปค็‰Œ้‡Œใ€‚ +ไธบ็ฎ€ๅ•่ตท่ง๏ผŒๆญคๅค„ๆˆ‘ไปฌๅชๆ˜ฏๆŠŠๆŽฅๆ”ถๅˆฐ็š„ไฝœ็”จๅŸŸ็›ดๆŽฅๆทปๅŠ ๅˆฐไบ†ไปค็‰Œไธญใ€‚ -ไฝ†ๅœจๆ‚จ็š„ๅบ”็”จไธญ๏ผŒไธบไบ†ๅฎ‰ๅ…จ๏ผŒๅบ”่ฏฅๅชๆŠŠไฝœ็”จๅŸŸๆทปๅŠ ๅˆฐ็กฎๅฎž้œ€่ฆไฝœ็”จๅŸŸ็š„็”จๆˆท๏ผŒๆˆ–้ข„ๅฎšไน‰็š„็”จๆˆทใ€‚ +ไฝ†ๅœจไฝ ็š„ๅบ”็”จ้‡Œ๏ผŒไธบไบ†ๅฎ‰ๅ…จ่ตท่ง๏ผŒไฝ ๅบ”่ฏฅๅชๆทปๅŠ ่ฏฅ็”จๆˆทๅฎž้™…่ƒฝๅคŸๆ‹ฅๆœ‰็š„ไฝœ็”จๅŸŸ๏ผŒๆˆ–ไฝ ้ข„ๅ…ˆๅฎšไน‰็š„ไฝœ็”จๅŸŸใ€‚ /// -{* ../../docs_src/security/tutorial005.py hl[153] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## ๅœจ*่ทฏๅพ„ๆ“ไฝœ*ไธŽไพ่ต–้กนไธญๅฃฐๆ˜Žไฝœ็”จๅŸŸ +## ๅœจ*่ทฏๅพ„ๆ“ไฝœ*ไธŽไพ่ต–้กนไธญๅฃฐๆ˜Žไฝœ็”จๅŸŸ { #declare-scopes-in-path-operations-and-dependencies } -ๆŽฅไธ‹ๆฅ๏ผŒไธบ*่ทฏๅพ„ๆ“ไฝœ* `/users/me/items/` ๅฃฐๆ˜Žไฝœ็”จๅŸŸ `items`ใ€‚ +็Žฐๅœจๆˆ‘ไปฌๅฃฐๆ˜Ž๏ผŒ่ทฏๅพ„ๆ“ไฝœ `/users/me/items/` ้œ€่ฆไฝœ็”จๅŸŸ `items`ใ€‚ -ไธบๆญค๏ผŒ่ฆไปŽ `fastapi` ไธญๅฏผๅ…ฅๅนถไฝฟ็”จ `Security` ใ€‚ +ไธบๆญค๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅๅนถไฝฟ็”จ `Security`ใ€‚ -`Security` ๅฃฐๆ˜Žไพ่ต–้กน็š„ๆ–นๅผๅ’Œ `Depends` ไธ€ๆ ท๏ผŒไฝ† `Security` ่ฟ˜่ƒฝๆŽฅๆ”ถไฝœ็”จๅŸŸ๏ผˆๅญ—็ฌฆไธฒ๏ผ‰ๅˆ—่กจ็ฑปๅž‹็š„ๅ‚ๆ•ฐ `scopes`ใ€‚ +ไฝ ๅฏไปฅ็”จ `Security` ๆฅๅฃฐๆ˜Žไพ่ต–๏ผˆๅฐฑๅƒ `Depends` ไธ€ๆ ท๏ผ‰๏ผŒไฝ† `Security` ่ฟ˜ๆŽฅๆ”ถไธ€ไธช `scopes` ๅ‚ๆ•ฐ๏ผŒๅ…ถๅ€ผๆ˜ฏไฝœ็”จๅŸŸ๏ผˆๅญ—็ฌฆไธฒ๏ผ‰ๅˆ—่กจใ€‚ -ๆญคๅค„ไฝฟ็”จไธŽ `Depends` ็›ธๅŒ็š„ๆ–นๅผ๏ผŒๆŠŠไพ่ต–้กนๅ‡ฝๆ•ฐ `get_current_active_user` ไผ ้€’็ป™ `Security`ใ€‚ +ๅœจ่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌๆŠŠไพ่ต–ๅ‡ฝๆ•ฐ `get_current_active_user` ไผ ็ป™ `Security`๏ผˆๅฐฑๅƒ็”จ `Depends` ไธ€ๆ ท๏ผ‰ใ€‚ -ๅŒๆ—ถ๏ผŒ่ฟ˜ไผ ้€’ไบ†ไฝœ็”จๅŸŸ**ๅˆ—่กจ**๏ผŒๆœฌไพ‹ไธญๅชไผ ้€’ไบ†ไธ€ไธชไฝœ็”จๅŸŸ๏ผš`items`๏ผˆๆญคๅค„ๆ”ฏๆŒไผ ้€’ๆ›ดๅคšไฝœ็”จๅŸŸ๏ผ‰ใ€‚ +ๅŒๆ—ถ่ฟ˜ไผ ๅ…ฅไธ€ไธชไฝœ็”จๅŸŸ `list`๏ผŒๆญคๅค„ไป…ๅŒ…ๅซไธ€ไธชไฝœ็”จๅŸŸ๏ผš`items`๏ผˆไนŸๅฏไปฅๅŒ…ๅซๆ›ดๅคš๏ผ‰ใ€‚ -ไพ่ต–้กนๅ‡ฝๆ•ฐ `get_current_active_user` ่ฟ˜่ƒฝๅฃฐๆ˜Žๅญไพ่ต–้กน๏ผŒไธไป…ๅฏไปฅไฝฟ็”จ `Depends`๏ผŒไนŸๅฏไปฅไฝฟ็”จ `Security`ใ€‚ๅฃฐๆ˜Žๅญไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผˆ`get_current_user`๏ผ‰ๅŠๆ›ดๅคšไฝœ็”จๅŸŸใ€‚ +ไพ่ต–ๅ‡ฝๆ•ฐ `get_current_active_user` ไนŸๅฏไปฅๅฃฐๆ˜Žๅญไพ่ต–๏ผŒไธไป…ๅฏไปฅ็”จ `Depends`๏ผŒไนŸๅฏไปฅ็”จ `Security`ใ€‚ๅฎƒๅฃฐๆ˜Žไบ†่‡ชๅทฑ็š„ๅญไพ่ต–ๅ‡ฝๆ•ฐ๏ผˆ`get_current_user`๏ผ‰๏ผŒๅนถๆทปๅŠ ไบ†ๆ›ดๅคš็š„ไฝœ็”จๅŸŸ้œ€ๆฑ‚ใ€‚ -ๆœฌไพ‹่ฆๆฑ‚ไฝฟ็”จไฝœ็”จๅŸŸ `me`๏ผˆ่ฟ˜ๅฏไปฅไฝฟ็”จๆ›ดๅคšไฝœ็”จๅŸŸ๏ผ‰ใ€‚ +ๅœจ่ฟ™ไธชไพ‹ๅญ้‡Œ๏ผŒๅฎƒ้œ€่ฆไฝœ็”จๅŸŸ `me`๏ผˆไนŸๅฏไปฅ้œ€่ฆๅคšไธชไฝœ็”จๅŸŸ๏ผ‰ใ€‚ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ ไธๅฟ…ๅœจไธๅŒไฝ็ฝฎๆทปๅŠ ไธๅŒ็š„ไฝœ็”จๅŸŸใ€‚ -ๆœฌไพ‹ไฝฟ็”จ็š„่ฟ™็งๆ–นๅผๅชๆ˜ฏไธบไบ†ๅฑ•็คบ **FastAPI** ๅฆ‚ไฝ•ๅค„็†ๅœจไธๅŒๅฑ‚็บงๅฃฐๆ˜Ž็š„ไฝœ็”จๅŸŸใ€‚ +่ฟ™้‡Œ่ฟ™ๆ ทๅš๏ผŒๆ˜ฏไธบไบ†ๆผ”็คบ **FastAPI** ๅฆ‚ไฝ•ๅค„็†ๅœจไธๅŒๅฑ‚็บงๅฃฐๆ˜Ž็š„ไฝœ็”จๅŸŸใ€‚ /// -{* ../../docs_src/security/tutorial005.py hl[4,139,166] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} /// info | ๆŠ€ๆœฏ็ป†่Š‚ -`Security` ๅฎž้™…ไธŠๆ˜ฏ `Depends` ็š„ๅญ็ฑป๏ผŒ่€Œไธ”ๅชๆฏ” `Depends` ๅคšไธ€ไธชๅ‚ๆ•ฐใ€‚ +`Security` ๅฎž้™…ไธŠๆ˜ฏ `Depends` ็š„ๅญ็ฑป๏ผŒๅฎƒๅชๅคšไบ†ไธ€ไธชๆˆ‘ไปฌ็จๅŽไผš็œ‹ๅˆฐ็š„ๅ‚ๆ•ฐใ€‚ -ไฝ†ไฝฟ็”จ `Security` ไปฃๆ›ฟ `Depends`๏ผŒ**FastAPI** ๅฏไปฅๅฃฐๆ˜Žๅฎ‰ๅ…จไฝœ็”จๅŸŸ๏ผŒๅนถๅœจๅ†…้ƒจไฝฟ็”จ่ฟ™ไบ›ไฝœ็”จๅŸŸ๏ผŒๅŒๆ—ถ๏ผŒไฝฟ็”จ OpenAPI ๅญ˜ๆกฃ APIใ€‚ +ไฝ†ๅฝ“ไฝ ไฝฟ็”จ `Security` ่€Œไธๆ˜ฏ `Depends` ๆ—ถ๏ผŒ**FastAPI** ไผš็Ÿฅ้“ๅฎƒๅฏไปฅๅฃฐๆ˜Žๅฎ‰ๅ…จไฝœ็”จๅŸŸ๏ผŒๅœจๅ†…้ƒจไฝฟ็”จๅฎƒไปฌ๏ผŒๅนถ็”จ OpenAPI ๆ–‡ๆกฃๅŒ– APIใ€‚ -ไฝ†ๅฎž้™…ไธŠ๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ็š„ `Query`ใ€`Path`ใ€`Depends`ใ€`Security` ็ญ‰ๅฏน่ฑก๏ผŒๅชๆ˜ฏ่ฟ”ๅ›ž็‰นๆฎŠ็ฑป็š„ๅ‡ฝๆ•ฐใ€‚ +ๅฆๅค–๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ็š„ `Query`ใ€`Path`ใ€`Depends`ใ€`Security` ็ญ‰๏ผŒๅฎž้™…ไธŠ้ƒฝๆ˜ฏ่ฟ”ๅ›ž็‰นๆฎŠ็ฑป็š„ๅ‡ฝๆ•ฐใ€‚ /// -## ไฝฟ็”จ `SecurityScopes` +## ไฝฟ็”จ `SecurityScopes` { #use-securityscopes } -ไฟฎๆ”นไพ่ต–้กน `get_current_user`ใ€‚ +็Žฐๅœจๆ›ดๆ–ฐไพ่ต–้กน `get_current_user`ใ€‚ -่ฟ™ๆ˜ฏไธŠ้ข็š„ไพ่ต–้กนไฝฟ็”จ็š„ไพ่ต–้กนใ€‚ +ไธŠ้ข้‚ฃไบ›ไพ่ต–ไผš็”จๅˆฐๅฎƒใ€‚ -่ฟ™้‡Œไฝฟ็”จ็š„ไนŸๆ˜ฏไน‹ๅ‰ๅˆ›ๅปบ็š„ OAuth2 ๆ–นๆกˆ๏ผŒๅนถๆŠŠๅฎƒๅฃฐๆ˜Žไธบไพ่ต–้กน๏ผš`oauth2_scheme`ใ€‚ +่ฟ™้‡Œๆˆ‘ไปฌไฝฟ็”จไน‹ๅ‰ๅˆ›ๅปบ็š„ๅŒไธ€ไธช OAuth2 ๆ–นๆกˆ๏ผŒๅนถๆŠŠๅฎƒๅฃฐๆ˜Žไธบไพ่ต–๏ผš`oauth2_scheme`ใ€‚ -่ฏฅไพ่ต–้กนๅ‡ฝๆ•ฐๆœฌ่บซไธ้œ€่ฆไฝœ็”จๅŸŸ๏ผŒๅ› ๆญค๏ผŒๅฏไปฅไฝฟ็”จ `Depends` ๅ’Œ `oauth2_scheme`ใ€‚ไธ้œ€่ฆๆŒ‡ๅฎšๅฎ‰ๅ…จไฝœ็”จๅŸŸๆ—ถ๏ผŒไธๅฟ…ไฝฟ็”จ `Security`ใ€‚ +ๅ› ไธบ่ฟ™ไธชไพ่ต–ๅ‡ฝๆ•ฐๆœฌ่บซๆฒกๆœ‰ไปปไฝ•ไฝœ็”จๅŸŸ้œ€ๆฑ‚๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๅฏไปฅ็”จ `Depends(oauth2_scheme)`๏ผŒๅฝ“ไธ้œ€่ฆๆŒ‡ๅฎšๅฎ‰ๅ…จไฝœ็”จๅŸŸๆ—ถ๏ผŒไธๅฟ…ไฝฟ็”จ `Security`ใ€‚ -ๆญคๅค„่ฟ˜ๅฃฐๆ˜Žไบ†ไปŽ `fastapi.security` ๅฏผๅ…ฅ็š„ `SecurityScopes` ็ฑปๅž‹็š„็‰นๆฎŠๅ‚ๆ•ฐใ€‚ +ๆˆ‘ไปฌ่ฟ˜ๅฃฐๆ˜Žไบ†ไธ€ไธชไปŽ `fastapi.security` ๅฏผๅ…ฅ็š„็‰นๆฎŠๅ‚ๆ•ฐ `SecurityScopes` ็ฑปๅž‹ใ€‚ -`SecuriScopes` ็ฑปไธŽ `Request` ็ฑปไผผ๏ผˆ`Request` ็”จไบŽ็›ดๆŽฅๆๅ–่ฏทๆฑ‚ๅฏน่ฑก๏ผ‰ใ€‚ +่ฟ™ไธช `SecurityScopes` ็ฑป็ฑปไผผไบŽ `Request`๏ผˆ`Request` ็”จๆฅ็›ดๆŽฅ่Žทๅ–่ฏทๆฑ‚ๅฏน่ฑก๏ผ‰ใ€‚ -{* ../../docs_src/security/tutorial005.py hl[8,105] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} -## ไฝฟ็”จ `scopes` +## ไฝฟ็”จ `scopes` { #use-the-scopes } ๅ‚ๆ•ฐ `security_scopes` ็š„็ฑปๅž‹ๆ˜ฏ `SecurityScopes`ใ€‚ -ๅฎƒ็š„ๅฑžๆ€ง `scopes` ๆ˜ฏไฝœ็”จๅŸŸๅˆ—่กจ๏ผŒๆ‰€ๆœ‰ไพ่ต–้กน้ƒฝๆŠŠๅฎƒไฝœไธบๅญไพ่ต–้กนใ€‚ไนŸๅฐฑๆ˜ฏ่ฏดๆ‰€ๆœ‰**ไพ่ต–**โ€ฆโ€ฆ่ฟ™ๅฌ่ตทๆฅๆœ‰ไบ›็ป•๏ผŒๅŽๆ–‡ไผšๆœ‰่งฃ้‡Šใ€‚ +ๅฎƒไผšๆœ‰ไธ€ไธช `scopes` ๅฑžๆ€ง๏ผŒๅŒ…ๅซไธ€ไธชๅˆ—่กจ๏ผŒ้‡Œ้ขๆ˜ฏๅฎƒ่‡ช่บซไปฅๅŠๆ‰€ๆœ‰ๆŠŠๅฎƒไฝœไธบๅญไพ่ต–็š„ไพ่ต–้กนๆ‰€้œ€่ฆ็š„ๆ‰€ๆœ‰ไฝœ็”จๅŸŸใ€‚ไนŸๅฐฑๆ˜ฏ่ฏด๏ผŒๆ‰€ๆœ‰โ€œไพ่ต–่€…โ€โ€ฆโ€ฆ่ฟ™ๅฏ่ƒฝๆœ‰็‚น็ป•๏ผŒไธ‹้ขไผšๅ†ๆฌก่งฃ้‡Šใ€‚ -๏ผˆ็ฑป `SecurityScopes` ็š„๏ผ‰`security_scopes` ๅฏน่ฑก่ฟ˜ๆไพ›ไบ†ๅ•ๅญ—็ฌฆไธฒ็ฑปๅž‹็š„ๅฑžๆ€ง `scope_str`๏ผŒ่ฏฅๅฑžๆ€งๆ˜ฏ๏ผˆ่ฆๅœจๆœฌไพ‹ไธญไฝฟ็”จ็š„๏ผ‰็”จ็ฉบๆ ผๅˆ†ๅ‰ฒ็š„ไฝœ็”จๅŸŸใ€‚ +`security_scopes` ๅฏน่ฑก๏ผˆ็ฑปๅž‹ไธบ `SecurityScopes`๏ผ‰่ฟ˜ๆไพ›ไบ†ไธ€ไธช `scope_str` ๅฑžๆ€ง๏ผŒๅฎƒๆ˜ฏไธ€ไธช็”จ็ฉบๆ ผๅˆ†้š”่ฟ™ไบ›ไฝœ็”จๅŸŸ็š„ๅ•ไธชๅญ—็ฌฆไธฒ๏ผˆๆˆ‘ไปฌๅฐ†ไผš็”จๅˆฐๅฎƒ๏ผ‰ใ€‚ -ๆญคๅค„่ฟ˜ๅˆ›ๅปบไบ†ๅŽ็ปญไปฃ็ ไธญ่ฆๅค็”จ๏ผˆ`raise`๏ผ‰็š„ `HTTPException` ใ€‚ +ๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `HTTPException`๏ผŒๅŽ้ขๅฏไปฅๅœจๅคšไธชไฝ็ฝฎๅค็”จ๏ผˆ`raise`๏ผ‰ๅฎƒใ€‚ -่ฏฅๅผ‚ๅธธๅŒ…ๅซไบ†ไฝœ็”จๅŸŸๆ‰€้œ€็š„๏ผˆๅฆ‚ๆœ‰๏ผ‰๏ผŒไปฅ็ฉบๆ ผๅˆ†ๅ‰ฒ็š„ๅญ—็ฌฆไธฒ๏ผˆไฝฟ็”จ `scope_str`๏ผ‰ใ€‚่ฏฅๅญ—็ฌฆไธฒ่ฆๆ”พๅˆฐๅŒ…ๅซไฝœ็”จๅŸŸ็š„ `WWW-Authenticate` ่ฏทๆฑ‚ๅคดไธญ๏ผˆ่ฟ™ไนŸๆ˜ฏ่ง„่Œƒ็š„่ฆๆฑ‚๏ผ‰ใ€‚ +ๅœจ่ฟ™ไธชๅผ‚ๅธธไธญ๏ผŒๆˆ‘ไปฌๅŒ…ๅซๆ‰€้œ€็š„ไฝœ็”จๅŸŸ๏ผˆๅฆ‚ๆžœๆœ‰็š„่ฏ๏ผ‰๏ผŒไปฅ็ฉบๆ ผๅˆ†้š”็š„ๅญ—็ฌฆไธฒ๏ผˆไฝฟ็”จ `scope_str`๏ผ‰ใ€‚ๆˆ‘ไปฌๆŠŠ่ฟ™ไธชๅŒ…ๅซไฝœ็”จๅŸŸ็š„ๅญ—็ฌฆไธฒๆ”พๅœจ `WWW-Authenticate` ๅ“ๅบ”ๅคดไธญ๏ผˆ่ฟ™ๆ˜ฏ่ง„่Œƒ่ฆๆฑ‚็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ -{* ../../docs_src/security/tutorial005.py hl[105,107:115] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} -## ๆ ก้ชŒ `username` ไธŽๆ•ฐๆฎๅฝข็Šถ +## ๆ ก้ชŒ `username` ไธŽๆ•ฐๆฎๅฝข็Šถ { #verify-the-username-and-data-shape } -ๆˆ‘ไปฌๅฏไปฅๆ ก้ชŒๆ˜ฏๅฆ่Žทๅ–ไบ† `username`๏ผŒๅนถๆŠฝๅ–ไฝœ็”จๅŸŸใ€‚ +ๆˆ‘ไปฌๆ ก้ชŒๆ˜ฏๅฆ่Žทๅ–ๅˆฐไบ† `username`๏ผŒๅนถๆๅ–ไฝœ็”จๅŸŸใ€‚ -็„ถๅŽ๏ผŒไฝฟ็”จ Pydantic ๆจกๅž‹ๆ ก้ชŒๆ•ฐๆฎ๏ผˆๆ•่Žท `ValidationError` ๅผ‚ๅธธ๏ผ‰๏ผŒๅฆ‚ๆžœ่ฏปๅ– JWT ไปค็‰Œๆˆ–ไฝฟ็”จ Pydantic ๆจกๅž‹้ชŒ่ฏๆ•ฐๆฎๆ—ถๅ‡บ้”™๏ผŒๅฐฑไผš่งฆๅ‘ไน‹ๅ‰ๅˆ›ๅปบ็š„ `HTTPException` ๅผ‚ๅธธใ€‚ +็„ถๅŽไฝฟ็”จ Pydantic ๆจกๅž‹้ชŒ่ฏ่ฟ™ไบ›ๆ•ฐๆฎ๏ผˆๆ•่Žท `ValidationError` ๅผ‚ๅธธ๏ผ‰๏ผŒๅฆ‚ๆžœ่ฏปๅ– JWT ไปค็‰Œๆˆ–็”จ Pydantic ้ชŒ่ฏๆ•ฐๆฎๆ—ถๅ‡บ้”™๏ผŒๅฐฑๆŠ›ๅ‡บๆˆ‘ไปฌไน‹ๅ‰ๅˆ›ๅปบ็š„ `HTTPException`ใ€‚ -ๅฏนๆญค๏ผŒ่ฆไฝฟ็”จๆ–ฐ็š„ๅฑžๆ€ง `scopes` ๆ›ดๆ–ฐ Pydantic ๆจกๅž‹ `TokenData`ใ€‚ +ไธบๆญค๏ผŒๆˆ‘ไปฌ็ป™ Pydantic ๆจกๅž‹ `TokenData` ๆทปๅŠ ไบ†ไธ€ไธชๆ–ฐๅฑžๆ€ง `scopes`ใ€‚ -ไฝฟ็”จ Pydantic ้ชŒ่ฏๆ•ฐๆฎๅฏไปฅ็กฎไฟๆ•ฐๆฎไธญๅซๆœ‰็”ฑไฝœ็”จๅŸŸ็ป„ๆˆ็š„**ๅญ—็ฌฆไธฒๅˆ—่กจ**๏ผŒไปฅๅŠ `username` ๅญ—็ฌฆไธฒ็ญ‰ๅ†…ๅฎนใ€‚ +้€š่ฟ‡็”จ Pydantic ้ชŒ่ฏๆ•ฐๆฎ๏ผŒๆˆ‘ไปฌๅฏไปฅ็กฎไฟ็กฎๅฎžๅพ—ๅˆฐไบ†ไพ‹ๅฆ‚ไธ€ไธช็”ฑไฝœ็”จๅŸŸ็ป„ๆˆ็š„ `list[str]`๏ผŒไปฅๅŠไธ€ไธช `str` ็ฑปๅž‹็š„ `username`ใ€‚ -ๅไน‹๏ผŒๅฆ‚ๆžœไฝฟ็”จ**ๅญ—ๅ…ธ**ๆˆ–ๅ…ถๅฎƒๆ•ฐๆฎ็ป“ๆž„๏ผŒๅฐฑๆœ‰ๅฏ่ƒฝๅœจๅŽ้ขๆŸไบ›ไฝ็ฝฎ็ ดๅๅบ”็”จ๏ผŒๅฝขๆˆๅฎ‰ๅ…จ้šๆ‚ฃใ€‚ +่€Œไธๆ˜ฏ๏ผŒไพ‹ๅฆ‚ๅพ—ๅˆฐไธ€ไธช `dict` ๆˆ–ๅ…ถๅฎƒไป€ไนˆ๏ผŒ่ฟ™ๅฏ่ƒฝไผšๅœจๅŽ็ปญๆŸไธชๆ—ถๅˆป็ ดๅๅบ”็”จ๏ผŒๅฝขๆˆๅฎ‰ๅ…จ้ฃŽ้™ฉใ€‚ -่ฟ˜ๅฏไปฅไฝฟ็”จ็”จๆˆทๅ้ชŒ่ฏ็”จๆˆท๏ผŒๅฆ‚ๆžœๆฒกๆœ‰็”จๆˆท๏ผŒไนŸไผš่งฆๅ‘ไน‹ๅ‰ๅˆ›ๅปบ็š„ๅผ‚ๅธธใ€‚ +ๆˆ‘ไปฌ่ฟ˜้ชŒ่ฏๆ˜ฏๅฆๅญ˜ๅœจ่ฏฅ็”จๆˆทๅ็š„็”จๆˆท๏ผŒๅฆ‚ๆžœๆฒกๆœ‰๏ผŒๅฐฑๆŠ›ๅ‡บๅ‰้ขๅˆ›ๅปบ็š„ๅŒไธ€ไธชๅผ‚ๅธธใ€‚ -{* ../../docs_src/security/tutorial005.py hl[46,116:127] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} -## ๆ ก้ชŒ `scopes` +## ๆ ก้ชŒ `scopes` { #verify-the-scopes } -ๆŽฅไธ‹ๆฅ๏ผŒๆ ก้ชŒๆ‰€ๆœ‰ไพ่ต–้กนๅ’Œไพ่ต–่ฆ็ด ๏ผˆๅŒ…ๆ‹ฌ*่ทฏๅพ„ๆ“ไฝœ*๏ผ‰ๆ‰€้œ€็š„ไฝœ็”จๅŸŸใ€‚่ฟ™ไบ›ไฝœ็”จๅŸŸๅŒ…ๅซๅœจไปค็‰Œ็š„ `scopes` ้‡Œ๏ผŒๅฆ‚ๆžœไธๅœจๅ…ถไธญๅฐฑไผš่งฆๅ‘ `HTTPException` ๅผ‚ๅธธใ€‚ +็Žฐๅœจๆˆ‘ไปฌ่ฆ้ชŒ่ฏ๏ผŒ่ฟ™ไธชไพ่ต–ไปฅๅŠๆ‰€ๆœ‰ไพ่ต–่€…๏ผˆๅŒ…ๆ‹ฌ*่ทฏๅพ„ๆ“ไฝœ*๏ผ‰ๆ‰€้œ€็š„ๆ‰€ๆœ‰ไฝœ็”จๅŸŸ๏ผŒๆ˜ฏๅฆ้ƒฝๅŒ…ๅซๅœจๆŽฅๆ”ถๅˆฐ็š„ไปค็‰Œ้‡Œ็š„ไฝœ็”จๅŸŸไธญ๏ผŒๅฆๅˆ™ๅฐฑๆŠ›ๅ‡บ `HTTPException`ใ€‚ -ไธบๆญค๏ผŒ่ฆไฝฟ็”จๅŒ…ๅซๆ‰€ๆœ‰ไฝœ็”จๅŸŸ**ๅญ—็ฌฆไธฒๅˆ—่กจ**็š„ `security_scopes.scopes`๏ผŒ ใ€‚ +ไธบๆญค๏ผŒๆˆ‘ไปฌไฝฟ็”จ `security_scopes.scopes`๏ผŒๅฎƒๅŒ…ๅซไธ€ไธช็”ฑ่ฟ™ไบ›ไฝœ็”จๅŸŸ็ป„ๆˆ็š„ `list[str]`ใ€‚ -{* ../../docs_src/security/tutorial005.py hl[128:134] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} -## ไพ่ต–้กนๆ ‘ไธŽไฝœ็”จๅŸŸ +## ไพ่ต–ๆ ‘ไธŽไฝœ็”จๅŸŸ { #dependency-tree-and-scopes } -ๅ†ๆฌกๆŸฅ็œ‹่ฟ™ไธชไพ่ต–้กนๆ ‘ไธŽไฝœ็”จๅŸŸใ€‚ +ๅ†ๆฌกๅ›ž้กพ่ฟ™ไธชไพ่ต–ๆ ‘ไธŽไฝœ็”จๅŸŸใ€‚ -`get_current_active_user` ไพ่ต–้กนๅŒ…ๅซๅญไพ่ต–้กน `get_current_user`๏ผŒๅนถๅœจ `get_current_active_user`ไธญๅฃฐๆ˜Žไบ†ไฝœ็”จๅŸŸ `"me"` ๅŒ…ๅซๆ‰€้œ€ไฝœ็”จๅŸŸๅˆ—่กจ ๏ผŒๅœจ `security_scopes.scopes` ไธญไผ ้€’็ป™ `get_current_user`ใ€‚ +็”ฑไบŽ `get_current_active_user` ไพ่ต–ๆŠŠ `get_current_user` ไฝœไธบๅญไพ่ต–๏ผŒๅ› ๆญคๅœจ `get_current_active_user` ไธญๅฃฐๆ˜Ž็š„ไฝœ็”จๅŸŸ `"me"` ไผš่ขซๅŒ…ๅซๅœจไผ ็ป™ `get_current_user` ็š„ `security_scopes.scopes` ๆ‰€้œ€ไฝœ็”จๅŸŸๅˆ—่กจไธญใ€‚ -*่ทฏๅพ„ๆ“ไฝœ*่‡ช่บซไนŸๅฃฐๆ˜Žไบ†ไฝœ็”จๅŸŸ๏ผŒ`"items"`๏ผŒ่ฟ™ไนŸๆ˜ฏ `security_scopes.scopes` ๅˆ—่กจไผ ้€’็ป™ `get_current_user` ็š„ใ€‚ +*่ทฏๅพ„ๆ“ไฝœ*ๆœฌ่บซไนŸๅฃฐๆ˜Žไบ†ไธ€ไธชไฝœ็”จๅŸŸ `"items"`๏ผŒๅฎƒไนŸไผšๅŒ…ๅซๅœจไผ ็ป™ `get_current_user` ็š„ `security_scopes.scopes` ๅˆ—่กจไธญใ€‚ -ไพ่ต–้กนไธŽไฝœ็”จๅŸŸ็š„ๅฑ‚็บงๆžถๆž„ๅฆ‚ไธ‹๏ผš +ไพ่ต–ไธŽไฝœ็”จๅŸŸ็š„ๅฑ‚็บง็ป“ๆž„ๅฆ‚ไธ‹๏ผš * *่ทฏๅพ„ๆ“ไฝœ* `read_own_items` ๅŒ…ๅซ๏ผš - * ไพ่ต–้กนๆ‰€้œ€็š„ไฝœ็”จๅŸŸ `["items"]`๏ผš - * `get_current_active_user`: - * ไพ่ต–้กนๅ‡ฝๆ•ฐ `get_current_active_user` ๅŒ…ๅซ๏ผš - * ๆ‰€้œ€็š„ไฝœ็”จๅŸŸ `"me"` ๅŒ…ๅซไพ่ต–้กน๏ผš - * `get_current_user`: - * ไพ่ต–้กนๅ‡ฝๆ•ฐ `get_current_user` ๅŒ…ๅซ๏ผš - * ๆฒกๆœ‰ไฝœ็”จๅŸŸ้œ€ๆฑ‚ๅ…ถ่‡ช่บซ - * ไพ่ต–้กนไฝฟ็”จ `oauth2_scheme` - * `security_scopes` ๅ‚ๆ•ฐ็š„็ฑปๅž‹ๆ˜ฏ `SecurityScopes`๏ผš - * `security_scopes` ๅ‚ๆ•ฐ็š„ๅฑžๆ€ง `scopes` ๆ˜ฏๅŒ…ๅซไธŠ่ฟฐๅฃฐๆ˜Ž็š„ๆ‰€ๆœ‰ไฝœ็”จๅŸŸ็š„**ๅˆ—่กจ**๏ผŒๅ› ๆญค๏ผš - * `security_scopes.scopes` ๅŒ…ๅซ็”จไบŽ*่ทฏๅพ„ๆ“ไฝœ*็š„ `["me", "items"]` - * `security_scopes.scopes` ๅŒ…ๅซ*่ทฏๅพ„ๆ“ไฝœ* `read_users_me` ็š„ `["me"]`๏ผŒๅ› ไธบๅฎƒๅœจไพ่ต–้กน้‡Œ่ขซๅฃฐๆ˜Ž - * `security_scopes.scopes` ๅŒ…ๅซ็”จไบŽ*่ทฏๅพ„ๆ“ไฝœ* `read_system_status` ็š„ `[]`๏ผˆ็ฉบๅˆ—่กจ๏ผ‰๏ผŒๅนถไธ”ๅฎƒ็š„ไพ่ต–้กน `get_current_user` ไนŸๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ• `scope` + * ๅธฆๆœ‰ไพ่ต–็š„ๅฟ…้œ€ไฝœ็”จๅŸŸ `["items"]`๏ผš + * `get_current_active_user`๏ผš + * ไพ่ต–ๅ‡ฝๆ•ฐ `get_current_active_user` ๅŒ…ๅซ๏ผš + * ๅธฆๆœ‰ไพ่ต–็š„ๅฟ…้œ€ไฝœ็”จๅŸŸ `["me"]`๏ผš + * `get_current_user`๏ผš + * ไพ่ต–ๅ‡ฝๆ•ฐ `get_current_user` ๅŒ…ๅซ๏ผš + * ่‡ช่บซไธ้œ€่ฆไปปไฝ•ไฝœ็”จๅŸŸใ€‚ + * ไธ€ไธชไฝฟ็”จ `oauth2_scheme` ็š„ไพ่ต–ใ€‚ + * ไธ€ไธช็ฑปๅž‹ไธบ `SecurityScopes` ็š„ `security_scopes` ๅ‚ๆ•ฐ๏ผš + * ่ฏฅ `security_scopes` ๅ‚ๆ•ฐๆœ‰ไธ€ไธช `scopes` ๅฑžๆ€ง๏ผŒๅฎƒๆ˜ฏไธ€ไธชๅŒ…ๅซไธŠ้ขๆ‰€ๆœ‰ๅทฒๅฃฐๆ˜Žไฝœ็”จๅŸŸ็š„ `list`๏ผŒๅ› ๆญค๏ผš + * ๅฏนไบŽ*่ทฏๅพ„ๆ“ไฝœ* `read_own_items`๏ผŒ`security_scopes.scopes` ๅฐ†ๅŒ…ๅซ `["me", "items"]`ใ€‚ + * ๅฏนไบŽ*่ทฏๅพ„ๆ“ไฝœ* `read_users_me`๏ผŒ`security_scopes.scopes` ๅฐ†ๅŒ…ๅซ `["me"]`๏ผŒๅ› ไธบๅฎƒๅœจไพ่ต– `get_current_active_user` ไธญ่ขซๅฃฐๆ˜Žใ€‚ + * ๅฏนไบŽ*่ทฏๅพ„ๆ“ไฝœ* `read_system_status`๏ผŒ`security_scopes.scopes` ๅฐ†ๅŒ…ๅซ `[]`๏ผˆ็ฉบๅˆ—่กจ๏ผ‰๏ผŒๅ› ไธบๅฎƒๆ—ขๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ•ๅธฆ `scopes` ็š„ `Security`๏ผŒๅ…ถไพ่ต– `get_current_user` ไนŸๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ• `scopes`ใ€‚ /// tip | ๆ็คบ -ๆญคๅค„้‡่ฆไธ”**็ฅžๅฅ‡**็š„ไบ‹ๆƒ…ๆ˜ฏ๏ผŒ`get_current_user` ๆฃ€ๆŸฅๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ๆ—ถๅฏไปฅไฝฟ็”จไธๅŒ็š„ `scopes` ๅˆ—่กจใ€‚ +่ฟ™้‡Œ้‡่ฆไธ”โ€œ็ฅžๅฅ‡โ€็š„ๅœฐๆ–นๆ˜ฏ๏ผŒ`get_current_user` ๅœจๆฃ€ๆŸฅๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ๆ—ถไผšๅพ—ๅˆฐไธๅŒ็š„ `scopes` ๅˆ—่กจใ€‚ -ๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝไพ่ต–ไบŽๅœจๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ๅ’ŒๆŒ‡ๅฎš*่ทฏๅพ„ๆ“ไฝœ*็š„ไพ่ต–ๆ ‘ไธญ็š„ๆฏไธชไพ่ต–้กนใ€‚ +่ฟ™ไธ€ๅˆ‡้ƒฝๅ–ๅ†ณไบŽไธบ่ฏฅ็‰นๅฎš*่ทฏๅพ„ๆ“ไฝœ*ๅœจๅ…ถ่‡ช่บซไปฅๅŠไพ่ต–ๆ ‘ไธญ็š„ๆฏไธชไพ่ต–้‡Œๅฃฐๆ˜Ž็š„ `scopes`ใ€‚ /// -## `SecurityScopes` ็š„ๆ›ดๅคš็ป†่Š‚ +## ๅ…ณไบŽ `SecurityScopes` ็š„ๆ›ดๅคš็ป†่Š‚ { #more-details-about-securityscopes } -ๆ‚จๅฏไปฅไปปไฝ•ไฝ็ฝฎๆˆ–ๅคšไธชไฝ็ฝฎไฝฟ็”จ `SecurityScopes`๏ผŒไธไธ€ๅฎš้žๅพ—ๅœจ**ๆ น**ไพ่ต–้กนไธญไฝฟ็”จใ€‚ +ไฝ ๅฏไปฅๅœจไปปๆ„ไฝ็ฝฎใ€ๅคšไธชไฝ็ฝฎไฝฟ็”จ `SecurityScopes`๏ผŒไธไธ€ๅฎš้žๅพ—ๅœจโ€œๆ นโ€ไพ่ต–้‡Œใ€‚ -ๅฎƒๆ€ปๆ˜ฏๅœจๅฝ“ๅ‰ `Security` ไพ่ต–้กนไธญๅ’Œๆ‰€ๆœ‰ไพ่ต–ๅ› ๅญๅฏนไบŽ**็‰นๅฎš** *่ทฏๅพ„ๆ“ไฝœ*ๅ’Œ**็‰นๅฎš**ไพ่ต–ๆ ‘ไธญๅฎ‰ๅ…จไฝœ็”จๅŸŸ +ๅฎƒๆ€ปไผšๅŒ…ๅซๅฝ“ๅ‰ `Security` ไพ่ต–ไธญไปฅๅŠๆ‰€ๆœ‰ไพ่ต–่€…ๅœจโ€œ่ฏฅ็‰นๅฎšโ€*่ทฏๅพ„ๆ“ไฝœ*ๅ’Œโ€œ่ฏฅ็‰นๅฎšโ€ไพ่ต–ๆ ‘้‡Œๅฃฐๆ˜Ž็š„ๅฎ‰ๅ…จไฝœ็”จๅŸŸใ€‚ -ๅ› ไธบ `SecurityScopes` ๅŒ…ๅซๆ‰€ๆœ‰็”ฑไพ่ต–้กนๅฃฐๆ˜Ž็š„ไฝœ็”จๅŸŸ๏ผŒๅฏไปฅๅœจๆ ธๅฟƒไพ่ต–ๅ‡ฝๆ•ฐไธญ็”จๅฎƒ้ชŒ่ฏๆ‰€้œ€ไฝœ็”จๅŸŸ็š„ไปค็‰Œ๏ผŒ็„ถๅŽๅ†ๅœจไธๅŒ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜ŽไธๅŒไฝœ็”จๅŸŸ้œ€ๆฑ‚ใ€‚ +ๅ› ไธบ `SecurityScopes` ไผšๅŒ…ๅซไพ่ต–่€…ๅฃฐๆ˜Ž็š„ๆ‰€ๆœ‰ไฝœ็”จๅŸŸ๏ผŒไฝ ๅฏไปฅๅœจไธ€ไธชๆ ธๅฟƒไพ่ต–ๅ‡ฝๆ•ฐ้‡Œ็”จๅฎƒ้ชŒ่ฏไปค็‰Œๆ˜ฏๅฆๅ…ทๆœ‰ๆ‰€้œ€ไฝœ็”จๅŸŸ๏ผŒ็„ถๅŽๅœจไธๅŒ็š„*่ทฏๅพ„ๆ“ไฝœ*้‡Œๅฃฐๆ˜ŽไธๅŒ็š„ไฝœ็”จๅŸŸ้œ€ๆฑ‚ใ€‚ -ๅฎƒไปฌไผšไธบๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*่ฟ›่กŒๅ•็‹ฌๆฃ€ๆŸฅใ€‚ +ๅฎƒไปฌไผš้’ˆๅฏนๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ๅˆ†ๅˆซๆฃ€ๆŸฅใ€‚ -## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-it } -ๆ‰“ๅผ€ API ๆ–‡ๆกฃ๏ผŒ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏ๏ผŒๅนถๆŒ‡ๅฎš่ฆๆŽˆๆƒ็š„ไฝœ็”จๅŸŸใ€‚ +ๆ‰“ๅผ€ API ๆ–‡ๆกฃ๏ผŒไฝ ๅฏไปฅ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏ๏ผŒๅนถๆŒ‡ๅฎš่ฆๆŽˆๆƒ็š„ไฝœ็”จๅŸŸใ€‚ -ๆฒกๆœ‰้€‰ๆ‹ฉไปปไฝ•ไฝœ็”จๅŸŸ๏ผŒไนŸๅฏไปฅ่ฟ›่กŒ**่บซไปฝ้ชŒ่ฏ**๏ผŒไฝ†่ฎฟ้—ฎ `/uses/me` ๆˆ– `/users/me/items` ๆ—ถ๏ผŒไผšๆ˜พ็คบๆฒกๆœ‰่ถณๅคŸ็š„ๆƒ้™ใ€‚ไฝ†ไปๅฏไปฅ่ฎฟ้—ฎ `/status/`ใ€‚ +ๅฆ‚ๆžœไฝ ไธ้€‰ๆ‹ฉไปปไฝ•ไฝœ็”จๅŸŸ๏ผŒไฝ ไพ็„ถไผšโ€œ้€š่ฟ‡่ฎค่ฏโ€๏ผŒไฝ†ๅฝ“ไฝ ่ฎฟ้—ฎ `/users/me/` ๆˆ– `/users/me/items/` ๆ—ถ๏ผŒไผšๆ”ถๅˆฐไธ€ไธช้”™่ฏฏ๏ผŒๆ็คบไฝ ๆฒกๆœ‰่ถณๅคŸ็š„ๆƒ้™ใ€‚ไฝ ไป็„ถๅฏไปฅ่ฎฟ้—ฎ `/status/`ใ€‚ -ๅฆ‚ๆžœ้€‰ๆ‹ฉไบ†ไฝœ็”จๅŸŸ `me`๏ผŒไฝ†ๆฒกๆœ‰้€‰ๆ‹ฉไฝœ็”จๅŸŸ `items`๏ผŒๅˆ™ๅฏไปฅ่ฎฟ้—ฎ `/users/me/`๏ผŒไฝ†ไธ่ƒฝ่ฎฟ้—ฎ `/users/me/items`ใ€‚ +ๅฆ‚ๆžœไฝ ้€‰ๆ‹ฉไบ†ไฝœ็”จๅŸŸ `me`๏ผŒไฝ†ๆฒกๆœ‰้€‰ๆ‹ฉไฝœ็”จๅŸŸ `items`๏ผŒไฝ ๅฏไปฅ่ฎฟ้—ฎ `/users/me/`๏ผŒไฝ†ไธ่ƒฝ่ฎฟ้—ฎ `/users/me/items/`ใ€‚ -่ฟ™ๅฐฑๆ˜ฏ้€š่ฟ‡็”จๆˆทๆไพ›็š„ไปค็‰Œไฝฟ็”จ็ฌฌไธ‰ๆ–นๅบ”็”จ่ฎฟ้—ฎ่ฟ™ไบ›*่ทฏๅพ„ๆ“ไฝœ*ๆ—ถไผšๅ‘็”Ÿ็š„ๆƒ…ๅ†ต๏ผŒๅ…ทไฝ“ๆ€Žๆ ทๅ–ๅ†ณไบŽ็”จๆˆทๆŽˆไบˆ็ฌฌไธ‰ๆ–นๅบ”็”จ็š„ๆƒ้™ใ€‚ +ๅฝ“็ฌฌไธ‰ๆ–นๅบ”็”จไฝฟ็”จ็”จๆˆทๆไพ›็š„ไปค็‰Œ่ฎฟ้—ฎ่ฟ™ไบ›*่ทฏๅพ„ๆ“ไฝœ*ๆ—ถ๏ผŒไนŸไผšๅ‘็”ŸๅŒๆ ท็š„ๆƒ…ๅ†ต๏ผŒๅ–ๅ†ณไบŽ็”จๆˆทๆŽˆไบˆ่ฏฅๅบ”็”จไบ†ๅคšๅฐ‘ๆƒ้™ใ€‚ -## ๅ…ณไบŽ็ฌฌไธ‰ๆ–น้›†ๆˆ +## ๅ…ณไบŽ็ฌฌไธ‰ๆ–น้›†ๆˆ { #about-third-party-integrations } -ๆœฌไพ‹ไฝฟ็”จ OAuth2 **ๅฏ†็ **ๆตใ€‚ +ๅœจ่ฟ™ไธช็คบไพ‹ไธญๆˆ‘ไปฌไฝฟ็”จ็š„ๆ˜ฏ OAuth2 ็š„โ€œpasswordโ€ๆตใ€‚ -่ฟ™็งๆ–นๅผ้€‚็”จไบŽ็™ปๅฝ•ๆˆ‘ไปฌ่‡ชๅทฑ็š„ๅบ”็”จ๏ผŒๆœ€ๅฅฝไฝฟ็”จๆˆ‘ไปฌ่‡ชๅทฑ็š„ๅ‰็ซฏใ€‚ +ๅฝ“ๆˆ‘ไปฌ็™ปๅฝ•่‡ชๅทฑ็š„ๅบ”็”จ๏ผˆๅพˆๅฏ่ƒฝ่ฟ˜ๆœ‰ๆˆ‘ไปฌ่‡ชๅทฑ็š„ๅ‰็ซฏ๏ผ‰ๆ—ถ๏ผŒ่ฟ™ๆ˜ฏๅˆ้€‚็š„ใ€‚ -ๅ› ไธบๆˆ‘ไปฌ่ƒฝๆŽงๅˆถ่‡ชๅทฑ็š„ๅ‰็ซฏๅบ”็”จ๏ผŒๅฏไปฅไฟกไปปๅฎƒๆŽฅๆ”ถ `username` ไธŽ `password`ใ€‚ +ๅ› ไธบๆˆ‘ไปฌๅฏไปฅไฟกไปปๅฎƒๆฅๆŽฅๆ”ถ `username` ๅ’Œ `password`๏ผŒๆฏ•็ซŸๆˆ‘ไปฌๆŽŒๆŽงๅฎƒใ€‚ -ไฝ†ๅฆ‚ๆžœๆž„ๅปบ็š„ๆ˜ฏ่ฟžๆŽฅๅ…ถๅฎƒๅบ”็”จ็š„ OAuth2 ๅบ”็”จ๏ผŒๆฏ”ๅฆ‚ๅ…ทๆœ‰ไธŽ่„ธไนฆใ€่ฐทๆญŒใ€GitHub ็›ธๅŒๅŠŸ่ƒฝ็š„็ฌฌไธ‰ๆ–น่บซไปฝ้ชŒ่ฏๅบ”็”จใ€‚้‚ฃๆ‚จๅฐฑๅบ”่ฏฅไฝฟ็”จๅ…ถๅฎƒๅฎ‰ๅ…จๆตใ€‚ +ไฝ†ๅฆ‚ๆžœไฝ ๅœจๆž„ๅปบไธ€ไธช OAuth2 ๅบ”็”จ๏ผŒ่ฎฉๅ…ถๅฎƒๅบ”็”จๆฅ่ฟžๆŽฅ๏ผˆไนŸๅฐฑๆ˜ฏ่ฏด๏ผŒไฝ ๅœจๆž„ๅปบ็ญ‰ๅŒไบŽ Facebookใ€Googleใ€GitHub ็ญ‰็š„่บซไปฝ้ชŒ่ฏๆไพ›ๅ•†๏ผ‰๏ผŒไฝ ๅบ”่ฏฅไฝฟ็”จๅ…ถๅฎƒ็š„ๆตใ€‚ -ๆœ€ๅธธ็”จ็š„ๆ˜ฏ้šๅผๆตใ€‚ +ๆœ€ๅธธ่ง็š„ๆ˜ฏ้šๅผๆต๏ผˆimplicit flow๏ผ‰ใ€‚ -ๆœ€ๅฎ‰ๅ…จ็š„ๆ˜ฏไปฃ็ ๆต๏ผŒไฝ†ๅฎž็Žฐ่ตทๆฅๆ›ดๅคๆ‚๏ผŒ่€Œไธ”้œ€่ฆๆ›ดๅคšๆญฅ้ชคใ€‚ๅ› ไธบๅฎƒๆ›ดๅคๆ‚๏ผŒๅพˆๅคš็ฌฌไธ‰ๆ–น่บซไปฝ้ชŒ่ฏๅบ”็”จๆœ€็ปˆๅปบ่ฎฎไฝฟ็”จ้šๅผๆตใ€‚ +ๆœ€ๅฎ‰ๅ…จ็š„ๆ˜ฏไปฃ็ ๆต๏ผˆauthorization code flow๏ผ‰๏ผŒไฝ†ๅฎž็Žฐๆ›ดๅคๆ‚๏ผŒ้œ€่ฆๆ›ดๅคšๆญฅ้ชคใ€‚ไนŸๅ› ไธบๆ›ดๅคๆ‚๏ผŒๅพˆๅคšๆไพ›ๅ•†ๆœ€็ปˆไผšๅปบ่ฎฎไฝฟ็”จ้šๅผๆตใ€‚ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๆฏไธช่บซไปฝ้ชŒ่ฏๅบ”็”จ้ƒฝไผš้‡‡็”จไธๅŒๆ–นๅผไผšๅ‘ฝๅๆต๏ผŒไปฅไพฟ่žๅˆๅ…ฅ่‡ชๅทฑ็š„ๅ“็‰Œใ€‚ +ๆฏไธช่บซไปฝ้ชŒ่ฏๆไพ›ๅ•†ๅธธๅธธไผš็”จไธๅŒ็š„ๆ–นๅผ็ป™ๅฎƒไปฌ็š„ๆตๅ‘ฝๅ๏ผŒไปฅ่žๅ…ฅ่‡ชๅทฑ็š„ๅ“็‰Œใ€‚ -ไฝ†ๅฝ’ๆ น็ป“ๅบ•๏ผŒๅฎƒไปฌไฝฟ็”จ็š„้ƒฝๆ˜ฏ OAuth2 ๆ ‡ๅ‡†ใ€‚ +ไฝ†ๅฝ’ๆ น็ป“ๅบ•๏ผŒๅฎƒไปฌๅฎž็Žฐ็š„้ƒฝๆ˜ฏๅŒไธ€ไธช OAuth2 ๆ ‡ๅ‡†ใ€‚ /// -**FastAPI** ็š„ `fastapi.security.oauth2` ้‡ŒๅŒ…ๅซไบ†ๆ‰€ๆœ‰ OAuth2 ่บซไปฝ้ชŒ่ฏๆตๅทฅๅ…ทใ€‚ +**FastAPI** ๅœจ `fastapi.security.oauth2` ไธญไธบๆ‰€ๆœ‰่ฟ™ไบ› OAuth2 ่บซไปฝ้ชŒ่ฏๆตๆไพ›ไบ†ๅทฅๅ…ทใ€‚ -## ่ฃ…้ฅฐๅ™จ `dependencies` ไธญ็š„ `Security` +## ่ฃ…้ฅฐๅ™จ `dependencies` ไธญ็š„ `Security` { #security-in-decorator-dependencies } -ๅŒๆ ท๏ผŒๆ‚จๅฏไปฅๅœจ่ฃ…้ฅฐๅ™จ็š„ `dependencies` ๅ‚ๆ•ฐไธญๅฎšไน‰ `Depends` ๅˆ—่กจ๏ผŒ๏ผˆ่ฏฆ่ง[่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank})๏ผ‰๏ผŒไนŸๅฏไปฅๆŠŠ `scopes` ไธŽ `Security` ไธ€่ตทไฝฟ็”จใ€‚ +ๅฐฑๅƒไฝ ๅฏไปฅๅœจ่ฃ…้ฅฐๅ™จ็š„ `dependencies` ๅ‚ๆ•ฐไธญๅฎšไน‰ `Depends` ็š„ `list`๏ผˆ่ฏฆ่ง[่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}๏ผ‰๏ผŒไฝ ไนŸๅฏไปฅๅœจ้‚ฃๅ„ฟ้…ๅˆ `Security` ไฝฟ็”จ `scopes`ใ€‚ diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md index e33da136fa..adf2644915 100644 --- a/docs/zh/docs/advanced/settings.md +++ b/docs/zh/docs/advanced/settings.md @@ -1,190 +1,94 @@ -# ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡ +# ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡ { #settings-and-environment-variables } -ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จ็š„ๅบ”็”จ็จ‹ๅบๅฏ่ƒฝ้œ€่ฆไธ€ไบ›ๅค–้ƒจ่ฎพ็ฝฎๆˆ–้…็ฝฎ๏ผŒไพ‹ๅฆ‚ๅฏ†้’ฅใ€ๆ•ฐๆฎๅบ“ๅ‡ญๆฎใ€็”ตๅญ้‚ฎไปถๆœๅŠก็š„ๅ‡ญๆฎ็ญ‰็ญ‰ใ€‚ +ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ็š„ๅบ”็”จๅฏ่ƒฝ้œ€่ฆไธ€ไบ›ๅค–้ƒจ่ฎพ็ฝฎๆˆ–้…็ฝฎ๏ผŒไพ‹ๅฆ‚ๅฏ†้’ฅใ€ๆ•ฐๆฎๅบ“ๅ‡ญๆฎใ€็”ตๅญ้‚ฎไปถๆœๅŠก็š„ๅ‡ญๆฎ็ญ‰ใ€‚ -่ฟ™ไบ›่ฎพ็ฝฎไธญ็š„ๅคงๅคšๆ•ฐๆ˜ฏๅฏๅ˜็š„๏ผˆๅฏไปฅๆ›ดๆ”น็š„๏ผ‰๏ผŒๆฏ”ๅฆ‚ๆ•ฐๆฎๅบ“็š„ URLใ€‚่€Œไธ”่ฎธๅคš่ฎพ็ฝฎๅฏ่ƒฝๆ˜ฏๆ•ๆ„Ÿ็š„๏ผŒๆฏ”ๅฆ‚ๅฏ†้’ฅใ€‚ +่ฟ™ไบ›่ฎพ็ฝฎไธญ็š„ๅคงๅคšๆ•ฐๆ˜ฏๅฏๅ˜็š„๏ผˆๅฏ่ƒฝไผšๆ”นๅ˜๏ผ‰๏ผŒไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“ URLใ€‚ๅนถไธ”ๅพˆๅคšๅฏ่ƒฝๆ˜ฏๆ•ๆ„Ÿ็š„๏ผŒๆฏ”ๅฆ‚ๅฏ†้’ฅใ€‚ ๅ› ๆญค๏ผŒ้€šๅธธไผšๅฐ†ๅฎƒไปฌๆไพ›ไธบ็”ฑๅบ”็”จ็จ‹ๅบ่ฏปๅ–็š„็Žฏๅขƒๅ˜้‡ใ€‚ -## ็Žฏๅขƒๅ˜้‡ +/// tip | ๆ็คบ -/// tip - -ๅฆ‚ๆžœๆ‚จๅทฒ็ป็Ÿฅ้“ไป€ไนˆๆ˜ฏ"็Žฏๅขƒๅ˜้‡"ไปฅๅŠๅฆ‚ไฝ•ไฝฟ็”จๅฎƒไปฌ๏ผŒ่ฏท้šๆ„่ทณๅˆฐไธ‹้ข็š„ไธ‹ไธ€่Š‚ใ€‚ +่ฆ็†่งฃ็Žฏๅขƒๅ˜้‡๏ผŒไฝ ๅฏไปฅ้˜…่ฏป[็Žฏๅขƒๅ˜้‡](../environment-variables.md){.internal-link target=_blank}ใ€‚ /// -็Žฏๅขƒๅ˜้‡๏ผˆไนŸ็งฐไธบ"env var"๏ผ‰ๆ˜ฏไธ€็งๅญ˜ๅœจไบŽ Python ไปฃ็ ไน‹ๅค–ใ€ๅญ˜ๅœจไบŽๆ“ไฝœ็ณป็ปŸไธญ็š„ๅ˜้‡๏ผŒๅฏไปฅ่ขซๆ‚จ็š„ Python ไปฃ็ ๏ผˆๆˆ–ๅ…ถไป–็จ‹ๅบ๏ผ‰่ฏปๅ–ใ€‚ - -ๆ‚จๅฏไปฅๅœจ shell ไธญๅˆ›ๅปบๅ’Œไฝฟ็”จ็Žฏๅขƒๅ˜้‡๏ผŒ่€Œๆ— ้œ€ไฝฟ็”จ Python๏ผš - -//// tab | Linuxใ€macOSใ€Windows Bash - -
- -```console -// ๆ‚จๅฏไปฅๅˆ›ๅปบไธ€ไธชๅไธบ MY_NAME ็š„็Žฏๅขƒๅ˜้‡ -$ export MY_NAME="Wade Wilson" - -// ็„ถๅŽๆ‚จๅฏไปฅไธŽๅ…ถไป–็จ‹ๅบไธ€่ตทไฝฟ็”จๅฎƒ๏ผŒไพ‹ๅฆ‚ -$ echo "Hello $MY_NAME" - -Hello Wade Wilson -``` - -
- -//// - -//// tab | Windows PowerShell - -
- -```console -// ๅˆ›ๅปบไธ€ไธชๅไธบ MY_NAME ็š„็Žฏๅขƒๅ˜้‡ -$ $Env:MY_NAME = "Wade Wilson" - -// ไธŽๅ…ถไป–็จ‹ๅบไธ€่ตทไฝฟ็”จๅฎƒ๏ผŒไพ‹ๅฆ‚ -$ echo "Hello $Env:MY_NAME" - -Hello Wade Wilson -``` - -
- -//// - -### ๅœจ Python ไธญ่ฏปๅ–็Žฏๅขƒๅ˜้‡ - -ๆ‚จ่ฟ˜ๅฏไปฅๅœจ Python ไน‹ๅค–็š„ๅœฐๆ–น๏ผˆไพ‹ๅฆ‚็ปˆ็ซฏไธญๆˆ–ไฝฟ็”จไปปไฝ•ๅ…ถไป–ๆ–นๆณ•๏ผ‰ๅˆ›ๅปบ็Žฏๅขƒๅ˜้‡๏ผŒ็„ถๅŽๅœจ Python ไธญ่ฏปๅ–ๅฎƒไปฌใ€‚ - -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅๆœ‰ไธ€ไธชๅไธบ `main.py` ็š„ๆ–‡ไปถ๏ผŒๅ…ถไธญๅŒ…ๅซไปฅไธ‹ๅ†…ๅฎน๏ผš - -```Python hl_lines="3" -import os +## ็ฑปๅž‹ๅ’Œ้ชŒ่ฏ { #types-and-validation } -name = os.getenv("MY_NAME", "World") -print(f"Hello {name} from Python") -``` +่ฟ™ไบ›็Žฏๅขƒๅ˜้‡ๅช่ƒฝๅค„็†ๆ–‡ๆœฌๅญ—็ฌฆไธฒ๏ผŒๅ› ไธบๅฎƒไปฌๅœจ Python ไน‹ๅค–๏ผŒๅนถไธ”ๅฟ…้กปไธŽๅ…ถไป–็จ‹ๅบๅŠ็ณป็ปŸ็š„ๅ…ถไฝ™้ƒจๅˆ†ๅ…ผๅฎน๏ผˆ็”š่‡ณไธŽไธๅŒ็š„ๆ“ไฝœ็ณป็ปŸ๏ผŒๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰ใ€‚ -/// tip +่ฟ™ๆ„ๅ‘ณ็€๏ผŒๅœจ Python ไธญไปŽ็Žฏๅขƒๅ˜้‡่ฏปๅ–็š„ไปปไฝ•ๅ€ผ้ƒฝๆ˜ฏ `str` ็ฑปๅž‹๏ผŒไปปไฝ•ๅˆฐไธๅŒ็ฑปๅž‹็š„่ฝฌๆขๆˆ–ไปปไฝ•้ชŒ่ฏ้ƒฝๅฟ…้กปๅœจไปฃ็ ไธญๅฎŒๆˆใ€‚ -`os.getenv()` ็š„็ฌฌไบŒไธชๅ‚ๆ•ฐๆ˜ฏ่ฆ่ฟ”ๅ›ž็š„้ป˜่ฎคๅ€ผใ€‚ +## Pydantic ็š„ `Settings` { #pydantic-settings } -ๅฆ‚ๆžœๆฒกๆœ‰ๆไพ›้ป˜่ฎคๅ€ผ๏ผŒ้ป˜่ฎคไธบ `None`๏ผŒๆญคๅค„ๆˆ‘ไปฌๆไพ›ไบ† `"World"` ไฝœไธบ่ฆไฝฟ็”จ็š„้ป˜่ฎคๅ€ผใ€‚ +ๅนธ่ฟ็š„ๆ˜ฏ๏ผŒPydantic ๆไพ›ไบ†ไธ€ไธชๅพˆๅฅฝ็š„ๅทฅๅ…ทๆฅๅค„็†ๆฅ่‡ช็Žฏๅขƒๅ˜้‡็š„่ฟ™ไบ›่ฎพ็ฝฎ๏ผšPydantic: Settings managementใ€‚ -/// +### ๅฎ‰่ฃ… `pydantic-settings` { #install-pydantic-settings } -็„ถๅŽ๏ผŒๆ‚จๅฏไปฅ่ฐƒ็”จ่ฏฅ Python ็จ‹ๅบ๏ผš +้ฆ–ๅ…ˆ๏ผŒ็กฎไฟไฝ ๅˆ›ๅปบๅนถๆฟ€ๆดปไบ†[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ… `pydantic-settings` ๅŒ…๏ผš
```console -// ่ฟ™้‡Œๆˆ‘ไปฌ่ฟ˜ๆฒกๆœ‰่ฎพ็ฝฎ็Žฏๅขƒๅ˜้‡ -$ python main.py - -// ๅ› ไธบๆˆ‘ไปฌๆฒกๆœ‰่ฎพ็ฝฎ็Žฏๅขƒๅ˜้‡๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๅพ—ๅˆฐ้ป˜่ฎคๅ€ผ - -Hello World from Python - -// ไฝ†ๆ˜ฏๅฆ‚ๆžœๆˆ‘ไปฌๅ…ˆๅˆ›ๅปบไธ€ไธช็Žฏๅขƒๅ˜้‡ -$ export MY_NAME="Wade Wilson" - -// ็„ถๅŽๅ†ๆฌก่ฐƒ็”จ็จ‹ๅบ -$ python main.py - -// ็Žฐๅœจๅฎƒๅฏไปฅ่ฏปๅ–็Žฏๅขƒๅ˜้‡ - -Hello Wade Wilson from Python +$ pip install pydantic-settings +---> 100% ```
-็”ฑไบŽ็Žฏๅขƒๅ˜้‡ๅฏไปฅๅœจไปฃ็ ไน‹ๅค–่ฎพ็ฝฎ๏ผŒไฝ†ๅฏไปฅ็”ฑไปฃ็ ่ฏปๅ–๏ผŒๅนถไธ”ไธ้œ€่ฆไธŽๅ…ถไป–ๆ–‡ไปถไธ€่ตทๅญ˜ๅ‚จ๏ผˆๆไบคๅˆฐ `git`๏ผ‰๏ผŒๅ› ๆญค้€šๅธธๅฐ†ๅฎƒไปฌ็”จไบŽ้…็ฝฎๆˆ–่ฎพ็ฝฎใ€‚ - - - -ๆ‚จ่ฟ˜ๅฏไปฅไป…ไธบ็‰นๅฎš็จ‹ๅบ่ฐƒ็”จๅˆ›ๅปบไธ€ไธช็Žฏๅขƒๅ˜้‡๏ผŒ่ฏฅ็Žฏๅขƒๅ˜้‡ไป…ๅฏน่ฏฅ็จ‹ๅบๅฏ็”จ๏ผŒๅนถไธ”ไป…ๅœจๅ…ถ่ฟ่กŒๆœŸ้—ดๆœ‰ๆ•ˆใ€‚ - -่ฆๅšๅˆฐ่ฟ™ไธ€็‚น๏ผŒๅœจ็จ‹ๅบๆœฌ่บซไน‹ๅ‰็š„ๅŒไธ€่กŒๅˆ›ๅปบๅฎƒ๏ผš +ๅฝ“ไฝ ็”จไปฅไธ‹ๆ–นๅผๅฎ‰่ฃ… `all` ๆ‰ฉๅฑ•ๆ—ถ๏ผŒๅฎƒไนŸไผš่ขซไธ€ๅนถๅฎ‰่ฃ…๏ผš
```console -// ๅœจๆญค็จ‹ๅบ่ฐƒ็”จ่กŒไธญๅˆ›ๅปบไธ€ไธชๅไธบ MY_NAME ็š„็Žฏๅขƒๅ˜้‡ -$ MY_NAME="Wade Wilson" python main.py - -// ็Žฐๅœจๅฎƒๅฏไปฅ่ฏปๅ–็Žฏๅขƒๅ˜้‡ - -Hello Wade Wilson from Python - -// ไน‹ๅŽ็Žฏๅขƒๅ˜้‡ไธๅ†ๅญ˜ๅœจ -$ python main.py - -Hello World from Python +$ pip install "fastapi[all]" +---> 100% ```
-/// tip - -ๆ‚จๅฏไปฅๅœจ Twelve-Factor App: Config ไธญ้˜…่ฏปๆ›ดๅคš็›ธๅ…ณไฟกๆฏใ€‚ - -/// - -### ็ฑปๅž‹ๅ’Œ้ชŒ่ฏ - -่ฟ™ไบ›็Žฏๅขƒๅ˜้‡ๅช่ƒฝๅค„็†ๆ–‡ๆœฌๅญ—็ฌฆไธฒ๏ผŒๅ› ไธบๅฎƒไปฌๆ˜ฏๅค–้ƒจไบŽ Python ็š„๏ผŒๅนถไธ”ๅฟ…้กปไธŽๅ…ถไป–็จ‹ๅบๅ’Œๆ•ดไธช็ณป็ปŸๅ…ผๅฎน๏ผˆ็”š่‡ณไธŽไธๅŒ็š„ๆ“ไฝœ็ณป็ปŸ๏ผŒๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰ใ€‚ +### ๅˆ›ๅปบ `Settings` ๅฏน่ฑก { #create-the-settings-object } -่ฟ™ๆ„ๅ‘ณ็€ไปŽ็Žฏๅขƒๅ˜้‡ไธญๅœจ Python ไธญ่ฏปๅ–็š„ไปปไฝ•ๅ€ผ้ƒฝๅฐ†ๆ˜ฏ `str` ็ฑปๅž‹๏ผŒไปปไฝ•็ฑปๅž‹็š„่ฝฌๆขๆˆ–้ชŒ่ฏ้ƒฝๅฟ…้กปๅœจไปฃ็ ไธญๅฎŒๆˆใ€‚ +ไปŽ Pydantic ๅฏผๅ…ฅ `BaseSettings` ๅนถๅˆ›ๅปบไธ€ไธชๅญ็ฑป๏ผŒ่ฟ™ไธŽๅˆ›ๅปบ Pydantic ๆจกๅž‹้žๅธธ็›ธไผผใ€‚ -## Pydantic ็š„ `Settings` +ไธŽ Pydantic ๆจกๅž‹ไธ€ๆ ท๏ผŒ็”จ็ฑปๅž‹ๆณจ่งฃๅฃฐๆ˜Ž็ฑปๅฑžๆ€ง๏ผŒไนŸๅฏไปฅๆŒ‡ๅฎš้ป˜่ฎคๅ€ผใ€‚ -ๅนธ่ฟ็š„ๆ˜ฏ๏ผŒPydantic ๆไพ›ไบ†ไธ€ไธชๅพˆๅฅฝ็š„ๅทฅๅ…ทๆฅๅค„็†ๆฅ่‡ช็Žฏๅขƒๅ˜้‡็š„่ฎพ็ฝฎ๏ผŒๅณPydantic: Settings managementใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จไธŽ Pydantic ๆจกๅž‹็›ธๅŒ็š„้ชŒ่ฏๅŠŸ่ƒฝๅ’Œๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ไธๅŒ็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒไปฅๅŠไฝฟ็”จ `Field()` ่ฟ›่กŒ้™„ๅŠ ้ชŒ่ฏใ€‚ -### ๅˆ›ๅปบ `Settings` ๅฏน่ฑก +{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} -ไปŽ Pydantic ๅฏผๅ…ฅ `BaseSettings` ๅนถๅˆ›ๅปบไธ€ไธชๅญ็ฑป๏ผŒไธŽ Pydantic ๆจกๅž‹้žๅธธ็›ธไผผใ€‚ +/// tip | ๆ็คบ -ไธŽ Pydantic ๆจกๅž‹ไธ€ๆ ท๏ผŒๆ‚จไฝฟ็”จ็ฑปๅž‹ๆณจ้‡Šๅฃฐๆ˜Ž็ฑปๅฑžๆ€ง๏ผŒ่ฟ˜ๅฏไปฅๆŒ‡ๅฎš้ป˜่ฎคๅ€ผใ€‚ - -ๆ‚จๅฏไปฅไฝฟ็”จไธŽ Pydantic ๆจกๅž‹็›ธๅŒ็š„้ชŒ่ฏๅŠŸ่ƒฝๅ’Œๅทฅๅ…ท๏ผŒๆฏ”ๅฆ‚ไธๅŒ็š„ๆ•ฐๆฎ็ฑปๅž‹ๅ’Œไฝฟ็”จ `Field()` ่ฟ›่กŒ้™„ๅŠ ้ชŒ่ฏใ€‚ - -{* ../../docs_src/settings/tutorial001.py hl[2,5:8,11] *} - -/// tip - -ๅฆ‚ๆžœๆ‚จ้œ€่ฆไธ€ไธชๅฟซ้€Ÿ็š„ๅคๅˆถ็ฒ˜่ดด็คบไพ‹๏ผŒ่ฏทไธ่ฆไฝฟ็”จๆญค็คบไพ‹๏ผŒ่€Œๅบ”ไฝฟ็”จไธ‹้ข็š„ๆœ€ๅŽไธ€ไธช็คบไพ‹ใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณ่ฆไธ€ไธชๅฏไปฅๅฟซ้€Ÿๅคๅˆถ็ฒ˜่ดด็š„็คบไพ‹๏ผŒ่ฏทไธ่ฆไฝฟ็”จ่ฟ™ไธช็คบไพ‹๏ผŒไฝฟ็”จไธ‹้ขๆœ€ๅŽไธ€ไธช็คบไพ‹ใ€‚ /// -็„ถๅŽ๏ผŒๅฝ“ๆ‚จๅˆ›ๅปบ่ฏฅ `Settings` ็ฑป็š„ๅฎžไพ‹๏ผˆๅœจๆญค็คบไพ‹ไธญๆ˜ฏ `settings` ๅฏน่ฑก๏ผ‰ๆ—ถ๏ผŒPydantic ๅฐ†ไปฅไธๅŒบๅˆ†ๅคงๅฐๅ†™็š„ๆ–นๅผ่ฏปๅ–็Žฏๅขƒๅ˜้‡๏ผŒๅ› ๆญค๏ผŒๅคงๅ†™็š„ๅ˜้‡ `APP_NAME` ไปๅฐ†ไธบๅฑžๆ€ง `app_name` ่ฏปๅ–ใ€‚ +ๅฝ“ไฝ ๅˆ›ๅปบ่ฏฅ `Settings` ็ฑป็š„ๅฎžไพ‹๏ผˆๆญคๅค„ๆ˜ฏ `settings` ๅฏน่ฑก๏ผ‰ๆ—ถ๏ผŒPydantic ไผšไปฅไธๅŒบๅˆ†ๅคงๅฐๅ†™็š„ๆ–นๅผ่ฏปๅ–็Žฏๅขƒๅ˜้‡๏ผŒๅ› ๆญค๏ผŒๅคงๅ†™ๅ˜้‡ `APP_NAME` ไปไผš็”จไบŽๅฑžๆ€ง `app_name`ใ€‚ -็„ถๅŽ๏ผŒๅฎƒๅฐ†่ฝฌๆขๅ’Œ้ชŒ่ฏๆ•ฐๆฎใ€‚ๅ› ๆญค๏ผŒๅฝ“ๆ‚จไฝฟ็”จ่ฏฅ `settings` ๅฏน่ฑกๆ—ถ๏ผŒๆ‚จๅฐ†่Žทๅพ—ๆ‚จๅฃฐๆ˜Ž็š„็ฑปๅž‹็š„ๆ•ฐๆฎ๏ผˆไพ‹ๅฆ‚ `items_per_user` ๅฐ†ไธบ `int` ็ฑปๅž‹๏ผ‰ใ€‚ +ๆŽฅ็€ๅฎƒไผš่ฝฌๆขๅนถ้ชŒ่ฏๆ•ฐๆฎใ€‚ๅ› ๆญค๏ผŒๅฝ“ไฝ ไฝฟ็”จ่ฏฅ `settings` ๅฏน่ฑกๆ—ถ๏ผŒไฝ ๅฐ†่Žทๅพ—ไฝ ๅฃฐๆ˜Ž็š„็ฑปๅž‹็š„ๆ•ฐๆฎ๏ผˆไพ‹ๅฆ‚ `items_per_user` ๅฐ†ๆ˜ฏ `int`๏ผ‰ใ€‚ -### ไฝฟ็”จ `settings` +### ไฝฟ็”จ `settings` { #use-the-settings } -็„ถๅŽ๏ผŒๆ‚จๅฏไปฅๅœจๅบ”็”จ็จ‹ๅบไธญไฝฟ็”จๆ–ฐ็š„ `settings` ๅฏน่ฑก๏ผš +็„ถๅŽไฝ ๅฏไปฅๅœจๅบ”็”จไธญไฝฟ็”จๆ–ฐ็š„ `settings` ๅฏน่ฑก๏ผš -{* ../../docs_src/settings/tutorial001.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} -### ่ฟ่กŒๆœๅŠกๅ™จ +### ่ฟ่กŒๆœๅŠกๅ™จ { #run-the-server } -ๆŽฅไธ‹ๆฅ๏ผŒๆ‚จๅฐ†่ฟ่กŒๆœๅŠกๅ™จ๏ผŒๅนถๅฐ†้…็ฝฎไฝœไธบ็Žฏๅขƒๅ˜้‡ไผ ้€’ใ€‚ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅ่ฎพ็ฝฎไธ€ไธช `ADMIN_EMAIL` ๅ’Œ `APP_NAME`๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš +ๆŽฅไธ‹ๆฅ๏ผŒ่ฟ่กŒๆœๅŠกๅ™จ๏ผŒๅนถๆŠŠ้…็ฝฎไฝœไธบ็Žฏๅขƒๅ˜้‡ไผ ๅ…ฅ๏ผŒไพ‹ๅฆ‚ไฝ ๅฏไปฅ่ฎพ็ฝฎ `ADMIN_EMAIL` ๅ’Œ `APP_NAME`๏ผš
```console -$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp"uvicorn main:app +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-/// tip +/// tip | ๆ็คบ -่ฆไธบๅ•ไธชๅ‘ฝไปค่ฎพ็ฝฎๅคšไธช็Žฏๅขƒๅ˜้‡๏ผŒๅช้œ€็”จ็ฉบๆ ผๅˆ†้š”ๅฎƒไปฌ๏ผŒๅนถๅฐ†ๅฎƒไปฌๅ…จ้ƒจๆ”พๅœจๅ‘ฝไปคไน‹ๅ‰ใ€‚ +่ฆไธบๅ•ไธชๅ‘ฝไปค่ฎพ็ฝฎๅคšไธช็Žฏๅขƒๅ˜้‡๏ผŒๅช้œ€็”จ็ฉบๆ ผๅˆ†้š”ๅฎƒไปฌ๏ผŒๅนถๆŠŠๅฎƒไปฌ้ƒฝๆ”พๅœจๅ‘ฝไปคๅ‰้ขใ€‚ /// @@ -192,118 +96,118 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp"uvicorn main:app `app_name` ๅฐ†ไธบ `"ChimichangApp"`ใ€‚ -่€Œ `items_per_user` ๅฐ†ไฟๆŒๅ…ถ้ป˜่ฎคๅ€ผไธบ `50`ใ€‚ +่€Œ `items_per_user` ไผšไฟๆŒ้ป˜่ฎคๅ€ผ `50`ใ€‚ -## ๅœจๅฆไธ€ไธชๆจกๅ—ไธญ่ฎพ็ฝฎ +## ๅœจๅฆไธ€ไธชๆจกๅ—ไธญๆ”พ็ฝฎ่ฎพ็ฝฎ { #settings-in-another-module } -ๆ‚จๅฏไปฅๅฐ†่ฟ™ไบ›่ฎพ็ฝฎๆ”พๅœจๅฆไธ€ไธชๆจกๅ—ๆ–‡ไปถไธญ๏ผŒๅฐฑๅƒๆ‚จๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญๆ‰€่ง็š„้‚ฃๆ ทใ€‚ +ไฝ ๅฏไปฅๆŠŠ่ฟ™ไบ›่ฎพ็ฝฎๆ”พๅœจๅฆไธ€ไธชๆจกๅ—ๆ–‡ไปถไธญ๏ผŒๅฐฑๅƒไฝ ๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ -ไพ‹ๅฆ‚๏ผŒๆ‚จๅฏไปฅๅˆ›ๅปบไธ€ไธชๅไธบ `config.py` ็š„ๆ–‡ไปถ๏ผŒๅ…ถไธญๅŒ…ๅซไปฅไธ‹ๅ†…ๅฎน๏ผš +ไพ‹ๅฆ‚๏ผŒๅฏไปฅๆœ‰ไธ€ไธช `config.py` ๆ–‡ไปถ๏ผš -{* ../../docs_src/settings/app01/config.py *} +{* ../../docs_src/settings/app01_py39/config.py *} -็„ถๅŽๅœจไธ€ไธชๅไธบ `main.py` ็š„ๆ–‡ไปถไธญไฝฟ็”จๅฎƒ๏ผš +็„ถๅŽๅœจ `main.py` ๆ–‡ไปถไธญไฝฟ็”จๅฎƒ๏ผš -{* ../../docs_src/settings/app01/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} -/// tip +/// tip | ๆ็คบ -ๆ‚จ่ฟ˜้œ€่ฆไธ€ไธชๅไธบ `__init__.py` ็š„ๆ–‡ไปถ๏ผŒๅฐฑๅƒๆ‚จๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ +ไฝ ่ฟ˜้œ€่ฆไธ€ไธช `__init__.py` ๆ–‡ไปถ๏ผŒๅฐฑๅƒไฝ ๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ /// -## ๅœจไพ่ต–้กนไธญไฝฟ็”จ่ฎพ็ฝฎ +## ๅœจไพ่ต–้กนไธญๆไพ›่ฎพ็ฝฎ { #settings-in-a-dependency } -ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไปŽไพ่ต–้กนไธญๆไพ›่ฎพ็ฝฎๅฏ่ƒฝๆฏ”ๅœจๆ‰€ๆœ‰ๅœฐๆ–น้ƒฝไฝฟ็”จๅ…จๅฑ€ๅฏน่ฑก `settings` ๆ›ดๆœ‰็”จใ€‚ +ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไปŽไพ่ต–้กนไธญๆไพ›่ฎพ็ฝฎๅฏ่ƒฝๆ›ดๆœ‰็”จ๏ผŒ่€Œไธๆ˜ฏๅœจๆ‰€ๆœ‰ๅœฐๆ–น้ƒฝไฝฟ็”จไธ€ไธชๅ…จๅฑ€็š„ `settings` ๅฏน่ฑกใ€‚ -่ฟ™ๅœจๆต‹่ฏ•ๆœŸ้—ดๅฐคๅ…ถๆœ‰็”จ๏ผŒๅ› ไธบๅพˆๅฎนๆ˜“็”จ่‡ชๅฎšไน‰่ฎพ็ฝฎ่ฆ†็›–ไพ่ต–้กนใ€‚ +่ฟ™ๅœจๆต‹่ฏ•ๆœŸ้—ดๅฐคๅ…ถๆœ‰็”จ๏ผŒๅ› ไธบๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐ็”จไฝ ่‡ชๅทฑ็š„่‡ชๅฎšไน‰่ฎพ็ฝฎ่ฆ†็›–ไพ่ต–้กนใ€‚ -### ้…็ฝฎๆ–‡ไปถ +### ้…็ฝฎๆ–‡ไปถ { #the-config-file } -ๆ นๆฎๅ‰้ข็š„็คบไพ‹๏ผŒๆ‚จ็š„ `config.py` ๆ–‡ไปถๅฏ่ƒฝๅฆ‚ไธ‹ๆ‰€็คบ๏ผš +ๅปถ็ปญไธŠไธ€ไธช็คบไพ‹๏ผŒไฝ ็š„ `config.py` ๆ–‡ไปถๅฏ่ƒฝๅฆ‚ไธ‹ๆ‰€็คบ๏ผš -{* ../../docs_src/settings/app02/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} -่ฏทๆณจๆ„๏ผŒ็Žฐๅœจๆˆ‘ไปฌไธๅˆ›ๅปบ้ป˜่ฎคๅฎžไพ‹ `settings = Settings()`ใ€‚ +ๆณจๆ„๏ผŒ็Žฐๅœจๆˆ‘ไปฌไธๅ†ๅˆ›ๅปบ้ป˜่ฎคๅฎžไพ‹ `settings = Settings()`ใ€‚ -### ไธปๅบ”็”จ็จ‹ๅบๆ–‡ไปถ +### ไธปๅบ”็”จๆ–‡ไปถ { #the-main-app-file } ็Žฐๅœจๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธชไพ่ต–้กน๏ผŒ่ฟ”ๅ›žไธ€ไธชๆ–ฐ็š„ `config.Settings()`ใ€‚ {* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} -/// tip +/// tip | ๆ็คบ ๆˆ‘ไปฌ็จๅŽไผš่ฎจ่ฎบ `@lru_cache`ใ€‚ -็›ฎๅ‰๏ผŒๆ‚จๅฏไปฅๅฐ† `get_settings()` ่ง†ไธบๆ™ฎ้€šๅ‡ฝๆ•ฐใ€‚ +็›ฎๅ‰ไฝ ๅฏไปฅๆŠŠ `get_settings()` ๅฝ“ไฝœๆ™ฎ้€šๅ‡ฝๆ•ฐใ€‚ /// -็„ถๅŽ๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ†ๅ…ถไฝœไธบไพ่ต–้กนไปŽโ€œ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐโ€ไธญๅผ•ๅ…ฅ๏ผŒๅนถๅœจ้œ€่ฆๆ—ถไฝฟ็”จๅฎƒใ€‚ +็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅœจโ€œ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐโ€ไธญๅฐ†ๅ…ถไฝœไธบไพ่ต–้กนๅผ•ๅ…ฅ๏ผŒๅนถๅœจ้œ€่ฆ็š„ไปปไฝ•ๅœฐๆ–นไฝฟ็”จๅฎƒใ€‚ {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} -### ่ฎพ็ฝฎๅ’Œๆต‹่ฏ• +### ่ฎพ็ฝฎไธŽๆต‹่ฏ• { #settings-and-testing } -็„ถๅŽ๏ผŒๅœจๆต‹่ฏ•ๆœŸ้—ด๏ผŒ้€š่ฟ‡ๅˆ›ๅปบ `get_settings` ็š„ไพ่ต–้กน่ฆ†็›–๏ผŒๅพˆๅฎนๆ˜“ๆไพ›ไธ€ไธชไธๅŒ็š„่ฎพ็ฝฎๅฏน่ฑก๏ผš +ๆŽฅ็€๏ผŒๅœจๆต‹่ฏ•ๆœŸ้—ด๏ผŒ้€š่ฟ‡ไธบ `get_settings` ๅˆ›ๅปบไพ่ต–้กน่ฆ†็›–๏ผŒๅฐฑๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐๆไพ›ไธ€ไธชไธๅŒ็š„่ฎพ็ฝฎๅฏน่ฑก๏ผš -{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} ๅœจไพ่ต–้กน่ฆ†็›–ไธญ๏ผŒๆˆ‘ไปฌๅœจๅˆ›ๅปบๆ–ฐ็š„ `Settings` ๅฏน่ฑกๆ—ถไธบ `admin_email` ่ฎพ็ฝฎไบ†ไธ€ไธชๆ–ฐๅ€ผ๏ผŒ็„ถๅŽ่ฟ”ๅ›ž่ฏฅๆ–ฐๅฏน่ฑกใ€‚ -็„ถๅŽ๏ผŒๆˆ‘ไปฌๅฏไปฅๆต‹่ฏ•ๅฎƒๆ˜ฏๅฆ่ขซไฝฟ็”จใ€‚ +็„ถๅŽๆˆ‘ไปฌๅฏไปฅๆต‹่ฏ•ๅฎƒๆ˜ฏๅฆ่ขซไฝฟ็”จใ€‚ -## ไปŽ `.env` ๆ–‡ไปถไธญ่ฏปๅ–่ฎพ็ฝฎ +## ่ฏปๅ– `.env` ๆ–‡ไปถ { #reading-a-env-file } -ๅฆ‚ๆžœๆ‚จๆœ‰่ฎธๅคšๅฏ่ƒฝ็ปๅธธๆ›ดๆ”น็š„่ฎพ็ฝฎ๏ผŒๅฏ่ƒฝๅœจไธๅŒ็š„็Žฏๅขƒไธญ๏ผŒๅฐ†ๅฎƒไปฌๆ”พๅœจไธ€ไธชๆ–‡ไปถไธญ๏ผŒ็„ถๅŽไปŽ่ฏฅๆ–‡ไปถไธญ่ฏปๅ–ๅฎƒไปฌ๏ผŒๅฐฑๅƒๅฎƒไปฌๆ˜ฏ็Žฏๅขƒๅ˜้‡ไธ€ๆ ท๏ผŒๅฏ่ƒฝ้žๅธธๆœ‰็”จใ€‚ +ๅฆ‚ๆžœไฝ ๆœ‰่ฎธๅคš่ฎพ็ฝฎๅฏ่ƒฝ็ปๅธธๅ˜ๅŒ–๏ผŒๆˆ–ๅœจไธๅŒ็ŽฏๅขƒไธญไธๅŒ๏ผŒ้‚ฃไนˆๆŠŠๅฎƒไปฌๆ”พ่ฟ›ไธ€ไธชๆ–‡ไปถไธญ๏ผŒ็„ถๅŽๅƒ็Žฏๅขƒๅ˜้‡ไธ€ๆ ทไปŽไธญ่ฏปๅ–๏ผŒๅฏ่ƒฝ้žๅธธๆœ‰็”จใ€‚ -่ฟ™็งๅšๆณ•็›ธๅฝ“ๅธธ่ง๏ผŒๆœ‰ไธ€ไธชๅ็งฐ๏ผŒ่ฟ™ไบ›็Žฏๅขƒๅ˜้‡้€šๅธธๆ”พๅœจไธ€ไธชๅไธบ `.env` ็š„ๆ–‡ไปถไธญ๏ผŒ่ฏฅๆ–‡ไปถ่ขซ็งฐไธบโ€œdotenvโ€ใ€‚ +่ฟ™็งๅšๆณ•้žๅธธๅธธ่ง๏ผš่ฟ™ไบ›็Žฏๅขƒๅ˜้‡้€šๅธธๆ”พๅœจๅไธบ `.env` ็š„ๆ–‡ไปถไธญ๏ผŒ่ฏฅๆ–‡ไปถ่ขซ็งฐไธบ โ€œdotenvโ€ใ€‚ -/// tip +/// tip | ๆ็คบ -ไปฅ็‚น (`.`) ๅผ€ๅคด็š„ๆ–‡ไปถๆ˜ฏ Unix-like ็ณป็ปŸ๏ผˆๅฆ‚ Linux ๅ’Œ macOS๏ผ‰ไธญ็š„้š่—ๆ–‡ไปถใ€‚ +ไปฅ็‚น๏ผˆ`.`๏ผ‰ๅผ€ๅคด็š„ๆ–‡ไปถๅœจ็ฑป Unix ็ณป็ปŸ๏ผˆๅฆ‚ Linux ๅ’Œ macOS๏ผ‰ไธญๆ˜ฏ้š่—ๆ–‡ไปถใ€‚ -ไฝ†ๆ˜ฏ๏ผŒdotenv ๆ–‡ไปถๅฎž้™…ไธŠไธไธ€ๅฎš่ฆๅ…ทๆœ‰็กฎๅˆ‡็š„ๆ–‡ไปถๅใ€‚ +ไฝ† dotenv ๆ–‡ไปถๅนถไธไธ€ๅฎšๅฟ…้กปๆ˜ฏ่ฟ™ไธช็กฎๅˆ‡็š„ๆ–‡ไปถๅใ€‚ /// -Pydantic ๆ”ฏๆŒไฝฟ็”จๅค–้ƒจๅบ“ไปŽ่ฟ™ไบ›็ฑปๅž‹็š„ๆ–‡ไปถไธญ่ฏปๅ–ใ€‚ๆ‚จๅฏไปฅๅœจPydantic ่ฎพ็ฝฎ: Dotenv (.env) ๆ”ฏๆŒไธญ้˜…่ฏปๆ›ดๅคš็›ธๅ…ณไฟกๆฏใ€‚ +Pydantic ๆ”ฏๆŒไฝฟ็”จไธ€ไธชๅค–้ƒจๅบ“ๆฅไปŽ่ฟ™็ฑปๆ–‡ไปถไธญ่ฏปๅ–ใ€‚ไฝ ๅฏไปฅๅœจ Pydantic Settings: Dotenv (.env) support ไธญ้˜…่ฏปๆ›ดๅคšไฟกๆฏใ€‚ -/// tip +/// tip | ๆ็คบ -่ฆไฝฟๅ…ถๅทฅไฝœ๏ผŒๆ‚จ้œ€่ฆๆ‰ง่กŒ `pip install python-dotenv`ใ€‚ +่ฆไฝฟๅ…ถๅทฅไฝœ๏ผŒไฝ ้œ€่ฆๆ‰ง่กŒ `pip install python-dotenv`ใ€‚ /// -### `.env` ๆ–‡ไปถ +### `.env` ๆ–‡ไปถ { #the-env-file } -ๆ‚จๅฏไปฅไฝฟ็”จไปฅไธ‹ๅ†…ๅฎนๅˆ›ๅปบไธ€ไธชๅไธบ `.env` ็š„ๆ–‡ไปถ๏ผš +ไฝ ๅฏไปฅๆœ‰ไธ€ไธช `.env` ๆ–‡ไปถ๏ผŒๅ†…ๅฎนๅฆ‚ไธ‹๏ผš ```bash ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" ``` -### ไปŽ `.env` ๆ–‡ไปถไธญ่ฏปๅ–่ฎพ็ฝฎ +### ไปŽ `.env` ไธญ่ฏปๅ–่ฎพ็ฝฎ { #read-settings-from-env } -็„ถๅŽ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จไปฅไธ‹ๆ–นๅผๆ›ดๆ–ฐๆ‚จ็š„ `config.py`๏ผš +็„ถๅŽๆ›ดๆ–ฐ `config.py`๏ผš -{* ../../docs_src/settings/app03/config.py hl[9:10] *} +{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} -ๅœจ่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌๅœจ Pydantic ็š„ `Settings` ็ฑปไธญๅˆ›ๅปบไบ†ไธ€ไธชๅไธบ `Config` ็š„็ฑป๏ผŒๅนถๅฐ† `env_file` ่ฎพ็ฝฎไธบๆˆ‘ไปฌๆƒณ่ฆไฝฟ็”จ็š„ dotenv ๆ–‡ไปถ็š„ๆ–‡ไปถๅใ€‚ +/// tip | ๆ็คบ -/// tip - -`Config` ็ฑปไป…็”จไบŽ Pydantic ้…็ฝฎใ€‚ๆ‚จๅฏไปฅๅœจPydantic Model Configไธญ้˜…่ฏปๆ›ดๅคš็›ธๅ…ณไฟกๆฏใ€‚ +`model_config` ๅฑžๆ€งไป…็”จไบŽ Pydantic ้…็ฝฎใ€‚ไฝ ๅฏไปฅๅœจ Pydantic: Concepts: Configuration ไธญ้˜…่ฏปๆ›ดๅคšไฟกๆฏใ€‚ /// -### ไฝฟ็”จ `lru_cache` ไป…ๅˆ›ๅปบไธ€ๆฌก `Settings` +่ฟ™้‡Œๆˆ‘ไปฌๅœจไฝ ็š„ Pydantic `Settings` ็ฑปไธญๅฎšไน‰้…็ฝฎ้กน `env_file`๏ผŒๅนถๅฐ†ๅ…ถ่ฎพ็ฝฎไธบๆˆ‘ไปฌๆƒณ่ฆไฝฟ็”จ็š„ dotenv ๆ–‡ไปถๅใ€‚ + +### ไฝฟ็”จ `lru_cache` ไป…ๅˆ›ๅปบไธ€ๆฌก `Settings` { #creating-the-settings-only-once-with-lru-cache } -ไปŽ็ฃ็›˜ไธญ่ฏปๅ–ๆ–‡ไปถ้€šๅธธๆ˜ฏไธ€้กน่€—ๆ—ถ็š„๏ผˆๆ…ข๏ผ‰ๆ“ไฝœ๏ผŒๅ› ๆญคๆ‚จๅฏ่ƒฝๅธŒๆœ›ไป…ๅœจ้ฆ–ๆฌก่ฏปๅ–ๅŽๅนถ้‡ๅคไฝฟ็”จ็›ธๅŒ็š„่ฎพ็ฝฎๅฏน่ฑก๏ผŒ่€Œไธๆ˜ฏไธบๆฏไธช่ฏทๆฑ‚้ƒฝ่ฏปๅ–ๅฎƒใ€‚ +ไปŽ็ฃ็›˜่ฏปๅ–ๆ–‡ไปถ้€šๅธธๆ˜ฏไธ€ไธชไปฃไปท่พƒ้ซ˜๏ผˆ็ผ“ๆ…ข๏ผ‰็š„ๆ“ไฝœ๏ผŒๆ‰€ไปฅไฝ ๅฏ่ƒฝๅธŒๆœ›ๅชๅœจ็ฌฌไธ€ๆฌก่ฏปๅ–๏ผŒ็„ถๅŽๅค็”จๅŒไธ€ไธช่ฎพ็ฝฎๅฏน่ฑก๏ผŒ่€Œไธๆ˜ฏไธบๆฏไธช่ฏทๆฑ‚้ƒฝ้‡ๆ–ฐ่ฏปๅ–ใ€‚ -ไฝ†ๆ˜ฏ๏ผŒๆฏๆฌกๆ‰ง่กŒไปฅไธ‹ๆ“ไฝœ๏ผš +ไฝ†ๆ˜ฏ๏ผŒๆฏๆฌกๆˆ‘ไปฌๆ‰ง่กŒ๏ผš ```Python Settings() @@ -311,35 +215,36 @@ Settings() ้ƒฝไผšๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ `Settings` ๅฏน่ฑก๏ผŒๅนถไธ”ๅœจๅˆ›ๅปบๆ—ถไผšๅ†ๆฌก่ฏปๅ– `.env` ๆ–‡ไปถใ€‚ -ๅฆ‚ๆžœไพ่ต–้กนๅ‡ฝๆ•ฐๅชๆ˜ฏ่ฟ™ๆ ท็š„๏ผš +ๅฆ‚ๆžœไพ่ต–้กนๅ‡ฝๆ•ฐๆ˜ฏ่ฟ™ๆ ท็š„๏ผš ```Python def get_settings(): return Settings() ``` -ๆˆ‘ไปฌๅฐ†ไธบๆฏไธช่ฏทๆฑ‚ๅˆ›ๅปบ่ฏฅๅฏน่ฑก๏ผŒๅนถไธ”ๅฐ†ๅœจๆฏไธช่ฏทๆฑ‚ไธญ่ฏปๅ– `.env` ๆ–‡ไปถใ€‚ โš ๏ธ +ๆˆ‘ไปฌๅฐฑไผšไธบๆฏไธช่ฏทๆฑ‚ๅˆ›ๅปบ่ฏฅๅฏน่ฑก๏ผŒๅนถไธบๆฏไธช่ฏทๆฑ‚่ฏปๅ– `.env` ๆ–‡ไปถใ€‚ โš ๏ธ -ไฝ†ๆ˜ฏ๏ผŒ็”ฑไบŽๆˆ‘ไปฌๅœจ้กถ้ƒจไฝฟ็”จไบ† `@lru_cache` ่ฃ…้ฅฐๅ™จ๏ผŒๅ› ๆญคๅชๆœ‰ๅœจ็ฌฌไธ€ๆฌก่ฐƒ็”จๅฎƒๆ—ถ๏ผŒๆ‰ไผšๅˆ›ๅปบ `Settings` ๅฏน่ฑกไธ€ๆฌกใ€‚ โœ”๏ธ +ไฝ†็”ฑไบŽๆˆ‘ไปฌๅœจ้กถ้ƒจไฝฟ็”จไบ† `@lru_cache` ่ฃ…้ฅฐๅ™จ๏ผŒ`Settings` ๅฏน่ฑกๅชไผšๅœจ็ฌฌไธ€ๆฌก่ฐƒ็”จๆ—ถๅˆ›ๅปบไธ€ๆฌกใ€‚ โœ”๏ธ {* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} -็„ถๅŽ๏ผŒๅœจไธ‹ไธ€ๆฌก่ฏทๆฑ‚็š„ไพ่ต–้กนไธญๅฏน `get_settings()` ่ฟ›่กŒไปปไฝ•ๅŽ็ปญ่ฐƒ็”จๆ—ถ๏ผŒๅฎƒไธไผšๆ‰ง่กŒ `get_settings()` ็š„ๅ†…้ƒจไปฃ็ ๅนถๅˆ›ๅปบๆ–ฐ็š„ `Settings` ๅฏน่ฑก๏ผŒ่€Œๆ˜ฏ่ฟ”ๅ›žๅœจ็ฌฌไธ€ๆฌก่ฐƒ็”จๆ—ถ่ฟ”ๅ›ž็š„็›ธๅŒๅฏน่ฑก๏ผŒไธ€ๆฌกๅˆไธ€ๆฌกใ€‚ +ๆŽฅ็€๏ผŒๅฏนไบŽๅŽ็ปญ่ฏทๆฑ‚ไธญไพ่ต–้กน้‡Œๅฏน `get_settings()` ็š„ไปปไฝ•่ฐƒ็”จ๏ผŒๅฎƒไธไผšๅ†ๆฌกๆ‰ง่กŒ `get_settings()` ็š„ๅ†…้ƒจไปฃ็ ๅนถๅˆ›ๅปบๆ–ฐ็š„ `Settings` ๅฏน่ฑก๏ผŒ่€Œๆ˜ฏไผšไธ€้ๅˆไธ€้ๅœฐ่ฟ”ๅ›ž็ฌฌไธ€ๆฌก่ฐƒ็”จๆ—ถ่ฟ”ๅ›ž็š„้‚ฃไธช็›ธๅŒๅฏน่ฑกใ€‚ + +#### `lru_cache` ๆŠ€ๆœฏ็ป†่Š‚ { #lru-cache-technical-details } -#### `lru_cache` ๆŠ€ๆœฏ็ป†่Š‚ +`@lru_cache` ไผšไฟฎๆ”นๅฎƒๆ‰€่ฃ…้ฅฐ็š„ๅ‡ฝๆ•ฐ๏ผŒไฝฟๅ…ถ่ฟ”ๅ›ž็ฌฌไธ€ๆฌก่ฟ”ๅ›ž็š„็›ธๅŒๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆฏๆฌก้ƒฝ้‡ๆ–ฐ่ฎก็ฎ—ๅนถๆ‰ง่กŒๅ‡ฝๆ•ฐไปฃ็ ใ€‚ -`@lru_cache` ไฟฎๆ”นไบ†ๅฎƒๆ‰€่ฃ…้ฅฐ็š„ๅ‡ฝๆ•ฐ๏ผŒไปฅ่ฟ”ๅ›ž็ฌฌไธ€ๆฌก่ฟ”ๅ›ž็š„็›ธๅŒๅ€ผ๏ผŒ่€Œไธๆ˜ฏๅ†ๆฌก่ฎก็ฎ—ๅฎƒ๏ผŒๆฏๆฌก้ƒฝๆ‰ง่กŒๅ‡ฝๆ•ฐ็š„ไปฃ็ ใ€‚ +ๅ› ๆญค๏ผŒไธ‹้ข็š„ๅ‡ฝๆ•ฐไผš้’ˆๅฏนๆฏไธชๅ‚ๆ•ฐ็ป„ๅˆๆ‰ง่กŒไธ€ๆฌกใ€‚็„ถๅŽ๏ผŒๅฝ“ไปฅๅฎŒๅ…จ็›ธๅŒ็š„ๅ‚ๆ•ฐ็ป„ๅˆ่ฐƒ็”จ่ฏฅๅ‡ฝๆ•ฐๆ—ถ๏ผŒๅฐ†้‡ๅคไฝฟ็”จ่ฏฅๅ‚ๆ•ฐ็ป„ๅˆๅ…ˆๅ‰่ฟ”ๅ›ž็š„ๅ€ผใ€‚ -ๅ› ๆญค๏ผŒไธ‹้ข็š„ๅ‡ฝๆ•ฐๅฐ†ๅฏนๆฏไธชๅ‚ๆ•ฐ็ป„ๅˆๆ‰ง่กŒไธ€ๆฌกใ€‚็„ถๅŽ๏ผŒๆฏไธชๅ‚ๆ•ฐ็ป„ๅˆ่ฟ”ๅ›ž็š„ๅ€ผๅฐ†ๅœจไฝฟ็”จๅฎŒๅ…จ็›ธๅŒ็š„ๅ‚ๆ•ฐ็ป„ๅˆ่ฐƒ็”จๅ‡ฝๆ•ฐๆ—ถๅ†ๆฌกไฝฟ็”จใ€‚ +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธชๅ‡ฝๆ•ฐ๏ผš -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๆ‚จๆœ‰ไธ€ไธชๅ‡ฝๆ•ฐ๏ผš ```Python @lru_cache def say_hi(name: str, salutation: str = "Ms."): return f"Hello {salutation} {name}" ``` -ๆ‚จ็š„็จ‹ๅบๅฏไปฅๅƒ่ฟ™ๆ ทๆ‰ง่กŒ๏ผš +ไฝ ็š„็จ‹ๅบๅฏ่ƒฝไผšๅƒ่ฟ™ๆ ทๆ‰ง่กŒ๏ผš ```mermaid sequenceDiagram @@ -382,16 +287,16 @@ participant execute as Execute function end ``` -ๅฏนไบŽๆˆ‘ไปฌ็š„ไพ่ต–้กน `get_settings()`๏ผŒ่ฏฅๅ‡ฝๆ•ฐ็”š่‡ณไธๆŽฅๅ—ไปปไฝ•ๅ‚ๆ•ฐ๏ผŒๅ› ๆญคๅฎƒๅง‹็ปˆ่ฟ”ๅ›ž็›ธๅŒ็š„ๅ€ผใ€‚ +ๅœจๆˆ‘ไปฌ็š„ไพ่ต–้กน `get_settings()` ็š„ๆƒ…ๅ†ตไธ‹๏ผŒ่ฏฅๅ‡ฝๆ•ฐ็”š่‡ณไธๆŽฅๅ—ไปปไฝ•ๅ‚ๆ•ฐ๏ผŒๅ› ๆญคๅฎƒๅง‹็ปˆ่ฟ”ๅ›ž็›ธๅŒ็š„ๅ€ผใ€‚ -่ฟ™ๆ ท๏ผŒๅฎƒ็š„่กŒไธบๅ‡ ไนŽๅฐฑๅƒๆ˜ฏไธ€ไธชๅ…จๅฑ€ๅ˜้‡ใ€‚ไฝ†ๆ˜ฏ็”ฑไบŽๅฎƒไฝฟ็”จไบ†ไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผŒๅ› ๆญคๆˆ‘ไปฌๅฏไปฅ่ฝปๆพๅœฐ่ฟ›่กŒๆต‹่ฏ•ๆ—ถ็š„่ฆ†็›–ใ€‚ +่ฟ™ๆ ท๏ผŒๅฎƒ็š„่กŒไธบๅ‡ ไนŽๅฐฑๅƒๆ˜ฏไธ€ไธชๅ…จๅฑ€ๅ˜้‡ใ€‚ไฝ†็”ฑไบŽๅฎƒไฝฟ็”จไบ†ไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผŒๆˆ‘ไปฌๅฏไปฅๅœจๆต‹่ฏ•ๆ—ถๅพˆๅฎนๆ˜“ๅœฐ่ฆ†็›–ๅฎƒใ€‚ -`@lru_cache` ๆ˜ฏ `functools` ็š„ไธ€้ƒจๅˆ†๏ผŒๅฎƒๆ˜ฏ Python ๆ ‡ๅ‡†ๅบ“็š„ไธ€้ƒจๅˆ†๏ผŒๆ‚จๅฏไปฅๅœจPython ๆ–‡ๆกฃไธญไบ†่งฃๆœ‰ๅ…ณ `@lru_cache` ็š„ๆ›ดๅคšไฟกๆฏใ€‚ +`@lru_cache` ๆ˜ฏ `functools` ็š„ไธ€้ƒจๅˆ†๏ผŒๅฎƒๅฑžไบŽ Python ๆ ‡ๅ‡†ๅบ“ใ€‚ไฝ ๅฏไปฅๅœจ Python ๆ–‡ๆกฃไธญๅ…ณไบŽ `@lru_cache` ็š„็ซ ่Š‚้˜…่ฏปๆ›ดๅคšไฟกๆฏใ€‚ -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -ๆ‚จๅฏไปฅไฝฟ็”จ Pydantic ่ฎพ็ฝฎๅค„็†ๅบ”็”จ็จ‹ๅบ็š„่ฎพ็ฝฎๆˆ–้…็ฝฎ๏ผŒๅˆฉ็”จ Pydantic ๆจกๅž‹็š„ๆ‰€ๆœ‰ๅŠŸ่ƒฝใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic Settings ๆฅๅค„็†ๅบ”็”จ็š„่ฎพ็ฝฎๆˆ–้…็ฝฎ๏ผŒไบซๅ— Pydantic ๆจกๅž‹็š„ๅ…จ้ƒจ่ƒฝๅŠ›ใ€‚ -* ้€š่ฟ‡ไฝฟ็”จไพ่ต–้กน๏ผŒๆ‚จๅฏไปฅ็ฎ€ๅŒ–ๆต‹่ฏ•ใ€‚ -* ๆ‚จๅฏไปฅไฝฟ็”จ `.env` ๆ–‡ไปถใ€‚ -* ไฝฟ็”จ `@lru_cache` ๅฏไปฅ้ฟๅ…ไธบๆฏไธช่ฏทๆฑ‚้‡ๅค่ฏปๅ– dotenv ๆ–‡ไปถ๏ผŒๅŒๆ—ถๅ…่ฎธๆ‚จๅœจๆต‹่ฏ•ๆ—ถ่ฟ›่กŒ่ฆ†็›–ใ€‚ +- ้€š่ฟ‡ไฝฟ็”จไพ่ต–้กน๏ผŒไฝ ๅฏไปฅ็ฎ€ๅŒ–ๆต‹่ฏ•ใ€‚ +- ไฝ ๅฏไปฅไธŽๅฎƒไธ€่ตทไฝฟ็”จ `.env` ๆ–‡ไปถใ€‚ +- ไฝฟ็”จ `@lru_cache` ๅฏไปฅ้ฟๅ…ไธบๆฏไธช่ฏทๆฑ‚ๅๅค่ฏปๅ– dotenv ๆ–‡ไปถ๏ผŒๅŒๆ—ถๅ…่ฎธไฝ ๅœจๆต‹่ฏ•ๆ—ถ่ฟ›่กŒ่ฆ†็›–ใ€‚ diff --git a/docs/zh/docs/advanced/sub-applications.md b/docs/zh/docs/advanced/sub-applications.md index c42be2849a..fe1fcd1211 100644 --- a/docs/zh/docs/advanced/sub-applications.md +++ b/docs/zh/docs/advanced/sub-applications.md @@ -1,54 +1,54 @@ -# ๅญๅบ”็”จ - ๆŒ‚่ฝฝ +# ๅญๅบ”็”จ - ๆŒ‚่ฝฝ { #sub-applications-mounts } ๅฆ‚ๆžœ้œ€่ฆไธคไธช็‹ฌ็ซ‹็š„ FastAPI ๅบ”็”จ๏ผŒๆ‹ฅๆœ‰ๅ„่‡ช็‹ฌ็ซ‹็š„ OpenAPI ไธŽๆ–‡ๆกฃ๏ผŒๅˆ™้œ€่ฎพ็ฝฎไธ€ไธชไธปๅบ”็”จ๏ผŒๅนถ**ๆŒ‚่ฝฝ**ไธ€ไธช๏ผˆๆˆ–ๅคšไธช๏ผ‰ๅญๅบ”็”จใ€‚ -## ๆŒ‚่ฝฝ **FastAPI** ๅบ”็”จ +## ๆŒ‚่ฝฝ **FastAPI** ๅบ”็”จ { #mounting-a-fastapi-application } **ๆŒ‚่ฝฝ**ๆ˜ฏๆŒ‡ๅœจ็‰นๅฎš่ทฏๅพ„ไธญๆทปๅŠ ๅฎŒๅ…จ**็‹ฌ็ซ‹**็š„ๅบ”็”จ๏ผŒ็„ถๅŽๅœจ่ฏฅ่ทฏๅพ„ไธ‹ไฝฟ็”จ*่ทฏๅพ„ๆ“ไฝœ*ๅฃฐๆ˜Ž็š„ๅญๅบ”็”จๅค„็†ๆ‰€ๆœ‰ไบ‹ๅŠกใ€‚ -### ้กถๅฑ‚ๅบ”็”จ +### ้กถๅฑ‚ๅบ”็”จ { #top-level-application } ้ฆ–ๅ…ˆ๏ผŒๅˆ›ๅปบไธป๏ผˆ้กถๅฑ‚๏ผ‰**FastAPI** ๅบ”็”จๅŠๅ…ถ*่ทฏๅพ„ๆ“ไฝœ*๏ผš -{* ../../docs_src/sub_applications/tutorial001.py hl[3,6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} -### ๅญๅบ”็”จ +### ๅญๅบ”็”จ { #sub-application } ๆŽฅไธ‹ๆฅ๏ผŒๅˆ›ๅปบๅญๅบ”็”จๅŠๅ…ถ*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ ๅญๅบ”็”จๅชๆ˜ฏๅฆไธ€ไธชๆ ‡ๅ‡† FastAPI ๅบ”็”จ๏ผŒไฝ†่ฟ™ไธชๅบ”็”จๆ˜ฏ่ขซ**ๆŒ‚่ฝฝ**็š„ๅบ”็”จ๏ผš -{* ../../docs_src/sub_applications/tutorial001.py hl[11,14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} -### ๆŒ‚่ฝฝๅญๅบ”็”จ +### ๆŒ‚่ฝฝๅญๅบ”็”จ { #mount-the-sub-application } ๅœจ้กถๅฑ‚ๅบ”็”จ `app` ไธญ๏ผŒๆŒ‚่ฝฝๅญๅบ”็”จ `subapi`ใ€‚ ๆœฌไพ‹็š„ๅญๅบ”็”จๆŒ‚่ฝฝๅœจ `/subapi` ่ทฏๅพ„ไธ‹๏ผš -{* ../../docs_src/sub_applications/tutorial001.py hl[11,19] *} +{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹่‡ชๅŠจ API ๆ–‡ๆกฃ { #check-the-automatic-api-docs } -ๅฆ‚ๆžœไธปๆ–‡ไปถๆ˜ฏ `main.py`๏ผŒๅˆ™็”จไปฅไธ‹ `uvicorn` ๅ‘ฝไปค่ฟ่กŒไธปๅบ”็”จ๏ผš +็Žฐๅœจ๏ผŒไฝฟ็”จไฝ ็š„ๆ–‡ไปถ่ฟ่กŒ `fastapi` ๅ‘ฝไปค๏ผš
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-ๆŸฅ็œ‹ๆ–‡ๆกฃ http://127.0.0.1:8000/docsใ€‚ +็„ถๅŽๅœจ http://127.0.0.1:8000/docs ๆ‰“ๅผ€ๆ–‡ๆกฃใ€‚ ไธ‹ๅ›พๆ˜พ็คบ็š„ๆ˜ฏไธปๅบ”็”จ API ๆ–‡ๆกฃ๏ผŒๅชๅŒ…ๆ‹ฌๅ…ถ่‡ชๆœ‰็š„*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ -็„ถๅŽๆŸฅ็œ‹ๅญๅบ”็”จๆ–‡ๆกฃ http://127.0.0.1:8000/subapi/docsใ€‚ +็„ถๅŽๆŸฅ็œ‹ๅญๅบ”็”จๆ–‡ๆกฃ http://127.0.0.1:8000/subapi/docsใ€‚ ไธ‹ๅ›พๆ˜พ็คบ็š„ๆ˜ฏๅญๅบ”็”จ็š„ API ๆ–‡ๆกฃ๏ผŒไนŸๆ˜ฏๅชๅŒ…ๆ‹ฌๅ…ถ่‡ชๆœ‰็š„*่ทฏๅพ„ๆ“ไฝœ*๏ผŒๆ‰€ๆœ‰่ฟ™ไบ›่ทฏๅพ„ๆ“ไฝœ้ƒฝๅœจ `/subapi` ๅญ่ทฏๅพ„ๅ‰็ผ€ไธ‹ใ€‚ @@ -56,7 +56,7 @@ $ uvicorn main:app --reload ไธคไธช็”จๆˆท็•Œ้ข้ƒฝๅฏไปฅๆญฃๅธธ่ฟ่กŒ๏ผŒๅ› ไธบๆต่งˆๅ™จ่ƒฝๅคŸไธŽๆฏไธชๆŒ‡ๅฎš็š„ๅบ”็”จๆˆ–ๅญๅบ”็”จไผš่ฏใ€‚ -### ๆŠ€ๆœฏ็ป†่Š‚๏ผš`root_path` +### ๆŠ€ๆœฏ็ป†่Š‚๏ผš`root_path` { #technical-details-root-path } ไปฅไธŠ่ฟฐๆ–นๅผๆŒ‚่ฝฝๅญๅบ”็”จๆ—ถ๏ผŒFastAPI ไฝฟ็”จ ASGI ่ง„่Œƒไธญ็š„ `root_path` ๆœบๅˆถๅค„็†ๆŒ‚่ฝฝๅญๅบ”็”จ่ทฏๅพ„ไน‹้—ด็š„้€šไฟกใ€‚ diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md index e627eed980..f2e5c21cf3 100644 --- a/docs/zh/docs/advanced/templates.md +++ b/docs/zh/docs/advanced/templates.md @@ -1,4 +1,4 @@ -# ๆจกๆฟ +# ๆจกๆฟ { #templates } **FastAPI** ๆ”ฏๆŒๅคš็งๆจกๆฟๅผ•ๆ“Žใ€‚ @@ -6,9 +6,9 @@ Flask ็ญ‰ๅทฅๅ…ทไฝฟ็”จ็š„ Jinja2 ๆ˜ฏๆœ€็”จ็š„ๆจกๆฟๅผ•ๆ“Žใ€‚ ๅœจ Starlette ็š„ๆ”ฏๆŒไธ‹๏ผŒ**FastAPI** ๅบ”็”จๅฏไปฅ็›ดๆŽฅไฝฟ็”จๅทฅๅ…ท่ฝปๆ˜“ๅœฐ้…็ฝฎ Jinja2ใ€‚ -## ๅฎ‰่ฃ…ไพ่ต–้กน +## ๅฎ‰่ฃ…ไพ่ต–้กน { #install-dependencies } -ๅฎ‰่ฃ… `jinja2`๏ผš +็กฎไฟไฝ ๅˆ›ๅปบไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒๆฟ€ๆดปๅฎƒ๏ผŒๅนถๅฎ‰่ฃ… `jinja2`๏ผš
@@ -20,23 +20,23 @@ $ pip install jinja2
-## ไฝฟ็”จ `Jinja2Templates` +## ไฝฟ็”จ `Jinja2Templates` { #using-jinja2templates } * ๅฏผๅ…ฅ `Jinja2Templates` * ๅˆ›ๅปบๅฏๅค็”จ็š„ `templates` ๅฏน่ฑก * ๅœจ่ฟ”ๅ›žๆจกๆฟ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜Ž `Request` ๅ‚ๆ•ฐ -* ไฝฟ็”จ `templates` ๆธฒๆŸ“ๅนถ่ฟ”ๅ›ž `TemplateResponse`๏ผŒ ไผ ้€’ๆจกๆฟ็š„ๅ็งฐใ€requestๅฏน่ฑกไปฅๅŠไธ€ไธชๅŒ…ๅซๅคšไธช้”ฎๅ€ผๅฏน๏ผˆ็”จไบŽJinja2ๆจกๆฟ๏ผ‰็š„"context"ๅญ—ๅ…ธ๏ผŒ +* ไฝฟ็”จ `templates` ๆธฒๆŸ“ๅนถ่ฟ”ๅ›ž `TemplateResponse`๏ผŒไผ ้€’ๆจกๆฟ็š„ๅ็งฐใ€request ๅฏน่ฑกไปฅๅŠไธ€ไธชๅŒ…ๅซๅคšไธช้”ฎๅ€ผๅฏน๏ผˆ็”จไบŽ Jinja2 ๆจกๆฟ๏ผ‰็š„ "context" ๅญ—ๅ…ธใ€‚ -{* ../../docs_src/templates/tutorial001.py hl[4,11,15:16] *} +{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} -/// note | ็ฌ”่ฎฐ +/// note -ๅœจFastAPI 0.108.0๏ผŒStarlette 0.29.0ไน‹ๅ‰๏ผŒ`name`ๆ˜ฏ็ฌฌไธ€ไธชๅ‚ๆ•ฐใ€‚ -ๅนถไธ”๏ผŒๅœจๆญคไน‹ๅ‰๏ผŒ`request`ๅฏน่ฑกๆ˜ฏไฝœไธบcontext็š„ไธ€้ƒจๅˆ†ไปฅ้”ฎๅ€ผๅฏน็š„ๅฝขๅผไผ ้€’็š„ใ€‚ +ๅœจ FastAPI 0.108.0๏ผŒStarlette 0.29.0 ไน‹ๅ‰๏ผŒ`name` ๆ˜ฏ็ฌฌไธ€ไธชๅ‚ๆ•ฐใ€‚ +ๅนถไธ”๏ผŒๅœจๆญคไน‹ๅ‰๏ผŒ`request` ๅฏน่ฑกๆ˜ฏไฝœไธบ context ็š„ไธ€้ƒจๅˆ†ไปฅ้”ฎๅ€ผๅฏน็š„ๅฝขๅผไผ ้€’็š„ใ€‚ /// -/// tip | ๆ็คบ +/// tip ้€š่ฟ‡ๅฃฐๆ˜Ž `response_class=HTMLResponse`๏ผŒAPI ๆ–‡ๆกฃๅฐฑ่ƒฝ่ฏ†ๅˆซๅ“ๅบ”็š„ๅฏน่ฑกๆ˜ฏ HTMLใ€‚ @@ -46,11 +46,11 @@ $ pip install jinja2 ๆ‚จ่ฟ˜ๅฏไปฅไฝฟ็”จ `from starlette.templating import Jinja2Templates`ใ€‚ -**FastAPI** ็š„ `fastapi.templating` ๅชๆ˜ฏไธบๅผ€ๅ‘่€…ๆไพ›็š„ๅฟซๆทๆ–นๅผใ€‚ๅฎž้™…ไธŠ๏ผŒ็ปๅคงๅคšๆ•ฐๅฏ็”จๅ“ๅบ”้ƒฝ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช Starletteใ€‚ `Request` ไธŽ `StaticFiles` ไนŸไธ€ๆ ทใ€‚ +**FastAPI** ็š„ `fastapi.templating` ๅชๆ˜ฏไธบๅผ€ๅ‘่€…ๆไพ›็š„ๅฟซๆทๆ–นๅผใ€‚ๅฎž้™…ไธŠ๏ผŒ็ปๅคงๅคšๆ•ฐๅฏ็”จๅ“ๅบ”้ƒฝ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช Starletteใ€‚`Request` ไธŽ `StaticFiles` ไนŸไธ€ๆ ทใ€‚ /// -## ็ผ–ๅ†™ๆจกๆฟ +## ็ผ–ๅ†™ๆจกๆฟ { #writing-templates } ็ผ–ๅ†™ๆจกๆฟ `templates/item.html`๏ผŒไปฃ็ ๅฆ‚ไธ‹๏ผš @@ -58,7 +58,7 @@ $ pip install jinja2 {!../../docs_src/templates/templates/item.html!} ``` -### ๆจกๆฟไธŠไธ‹ๆ–‡ +### ๆจกๆฟไธŠไธ‹ๆ–‡ๅ€ผ { #template-context-values } ๅœจๅŒ…ๅซๅฆ‚ไธ‹่ฏญๅฅ็š„htmlไธญ: @@ -70,21 +70,21 @@ Item ID: {{ id }} {% endraw %} -...่ฟ™ๅฐ†ๆ˜พ็คบไฝ ไปŽ"context"ๅญ—ๅ…ธไผ ้€’็š„ `id`: +...่ฟ™ๅฐ†ๆ˜พ็คบไฝ ไปŽ "context" ๅญ—ๅ…ธไผ ้€’็š„ `id`: ```Python {"id": id} ``` -ไพ‹ๅฆ‚ใ€‚ๅฝ“IDไธบ `42`ๆ—ถ, ไผšๆธฒๆŸ“ๆˆ: +ไพ‹ๅฆ‚ใ€‚ๅฝ“ ID ไธบ `42` ๆ—ถ, ไผšๆธฒๆŸ“ๆˆ: ```html Item ID: 42 ``` -### ๆจกๆฟ `url_for` ๅ‚ๆ•ฐ +### ๆจกๆฟ `url_for` ๅ‚ๆ•ฐ { #template-url-for-arguments } -ไฝ ่ฟ˜ๅฏไปฅๅœจๆจกๆฟๅ†…ไฝฟ็”จ `url_for()`๏ผŒๅ…ถๅ‚ๆ•ฐไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ็›ธๅŒ. +ไฝ ่ฟ˜ๅฏไปฅๅœจๆจกๆฟๅ†…ไฝฟ็”จ `url_for()`๏ผŒๅ…ถๅ‚ๆ•ฐไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ็›ธๅŒใ€‚ ๆ‰€ไปฅ๏ผŒ่ฏฅ้ƒจๅˆ†: @@ -96,30 +96,30 @@ Item ID: 42 {% endraw %} -...ๅฐ†็”Ÿๆˆไธ€ไธชไธŽๅค„็†*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* `read_item(id=id)`็š„URL็›ธๅŒ็š„้“พๆŽฅ +...ๅฐ†็”Ÿๆˆไธ€ไธชไธŽๅค„็†*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* `read_item(id=id)`็š„ URL ็›ธๅŒ็š„้“พๆŽฅ -ไพ‹ๅฆ‚ใ€‚ๅฝ“IDไธบ `42`ๆ—ถ, ไผšๆธฒๆŸ“ๆˆ: +ไพ‹ๅฆ‚ใ€‚ๅฝ“ ID ไธบ `42` ๆ—ถ, ไผšๆธฒๆŸ“ๆˆ: ```html ``` -## ๆจกๆฟไธŽ้™ๆ€ๆ–‡ไปถ +## ๆจกๆฟไธŽ้™ๆ€ๆ–‡ไปถ { #templates-and-static-files } -ไฝ ่ฟ˜ๅฏไปฅๅœจๆจกๆฟๅ†…้ƒจๅฐ† `url_for()`็”จไบŽ้™ๆ€ๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚ไฝ ๆŒ‚่ฝฝ็š„ `name="static"`็š„ `StaticFiles`ใ€‚ +ไฝ ่ฟ˜ๅฏไปฅๅœจๆจกๆฟๅ†…้ƒจๅฐ† `url_for()` ็”จไบŽ้™ๆ€ๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚ไฝ ๆŒ‚่ฝฝ็š„ `name="static"` ็š„ `StaticFiles`ใ€‚ ```jinja hl_lines="4" {!../../docs_src/templates/templates/item.html!} ``` -ๆœฌไพ‹ไธญ๏ผŒๅฎƒๅฐ†้“พๆŽฅๅˆฐ `static/styles.css`ไธญ็š„CSSๆ–‡ไปถ๏ผš +ๆœฌไพ‹ไธญ๏ผŒๅฎƒๅฐ†้“พๆŽฅๅˆฐ `static/styles.css` ไธญ็š„ CSS ๆ–‡ไปถ๏ผš ```CSS hl_lines="4" {!../../docs_src/templates/static/styles.css!} ``` -ๅ› ไธบไฝฟ็”จไบ† `StaticFiles`๏ผŒ **FastAPI** ๅบ”็”จไผš่‡ชๅŠจๆไพ›ไฝไบŽ URL `/static/styles.css`็š„ CSS ๆ–‡ไปถใ€‚ +ๅ› ไธบไฝฟ็”จไบ† `StaticFiles`๏ผŒ**FastAPI** ๅบ”็”จไผš่‡ชๅŠจๆไพ›ไฝไบŽ URL `/static/styles.css` ็š„ CSS ๆ–‡ไปถใ€‚ -## ๆ›ดๅคš่ฏดๆ˜Ž +## ๆ›ดๅคš่ฏดๆ˜Ž { #more-details } ๅŒ…ๆ‹ฌๆต‹่ฏ•ๆจกๆฟ็ญ‰ๆ›ดๅคš่ฏฆๆƒ…๏ผŒ่ฏทๅ‚้˜… Starlette ๅฎ˜ๆ–นๆ–‡ๆกฃ - ๆจกๆฟใ€‚ diff --git a/docs/zh/docs/advanced/testing-dependencies.md b/docs/zh/docs/advanced/testing-dependencies.md index 8d53a6d496..db0b39483d 100644 --- a/docs/zh/docs/advanced/testing-dependencies.md +++ b/docs/zh/docs/advanced/testing-dependencies.md @@ -1,6 +1,6 @@ -# ๆต‹่ฏ•ไพ่ต–้กน +# ไฝฟ็”จ่ฆ†็›–ๆต‹่ฏ•ไพ่ต–้กน { #testing-dependencies-with-overrides } -## ๆต‹่ฏ•ๆ—ถ่ฆ†็›–ไพ่ต–้กน +## ๆต‹่ฏ•ๆ—ถ่ฆ†็›–ไพ่ต–้กน { #overriding-dependencies-during-testing } ๆœ‰ไบ›ๅœบๆ™ฏไธ‹๏ผŒๆ‚จๅฏ่ƒฝ้œ€่ฆๅœจๆต‹่ฏ•ๆ—ถ่ฆ†็›–ไพ่ต–้กนใ€‚ @@ -8,7 +8,7 @@ ๅไน‹๏ผŒ่ฆๅœจๆต‹่ฏ•ๆœŸ้—ด๏ผˆๆˆ–ๅชๆ˜ฏไธบๆŸไบ›็‰นๅฎšๆต‹่ฏ•๏ผ‰ๆไพ›ๅช็”จไบŽๆต‹่ฏ•็š„ไพ่ต–้กน๏ผŒๅนถไฝฟ็”จๆญคไพ่ต–้กน็š„ๅ€ผๆ›ฟๆขๅŽŸๆœ‰ไพ่ต–้กน็š„ๅ€ผใ€‚ -### ็”จไพ‹๏ผšๅค–้ƒจๆœๅŠก +### ็”จไพ‹๏ผšๅค–้ƒจๆœๅŠก { #use-cases-external-service } ๅธธ่งๅฎžไพ‹ๆ˜ฏ่ฐƒ็”จๅค–้ƒจ็ฌฌไธ‰ๆ–น่บซไปฝ้ชŒ่ฏๅบ”็”จใ€‚ @@ -20,7 +20,7 @@ ๆญคๆ—ถ๏ผŒๆœ€ๅฅฝ่ฆ†็›–่ฐƒ็”จๅค–้ƒจ้ชŒ่ฏๅบ”็”จ็š„ไพ่ต–้กน๏ผŒไฝฟ็”จ่ฟ”ๅ›žๆจกๆ‹Ÿๆต‹่ฏ•็”จๆˆท็š„่‡ชๅฎšไน‰ไพ่ต–้กนๅฐฑๅฏไปฅไบ†ใ€‚ -### ไฝฟ็”จ `app.dependency_overrides` ๅฑžๆ€ง +### ไฝฟ็”จ `app.dependency_overrides` ๅฑžๆ€ง { #use-the-app-dependency-overrides-attribute } ๅฏนไบŽ่ฟ™ไบ›็”จไพ‹๏ผŒ**FastAPI** ๅบ”็”จๆ”ฏๆŒ `app.dependency_overrides` ๅฑžๆ€ง๏ผŒ่ฏฅๅฑžๆ€งๅฐฑๆ˜ฏ**ๅญ—ๅ…ธ**ใ€‚ @@ -46,6 +46,7 @@ FastAPI ๅฏไปฅ่ฆ†็›–่ฟ™ไบ›ไฝ็ฝฎ็š„ไพ่ต–้กนใ€‚ app.dependency_overrides = {} ``` + /// tip | ๆ็คบ ๅฆ‚ๆžœๅชๅœจๆŸไบ›ๆต‹่ฏ•ๆ—ถ่ฆ†็›–ไพ่ต–้กน๏ผŒๆ‚จๅฏไปฅๅœจๆต‹่ฏ•ๅผ€ๅง‹ๆ—ถ๏ผˆๅœจๆต‹่ฏ•ๅ‡ฝๆ•ฐๅ†…๏ผ‰่ฎพ็ฝฎ่ฆ†็›–ไพ่ต–้กน๏ผŒๅนถๅœจ็ป“ๆŸๆ—ถ๏ผˆๅœจๆต‹่ฏ•ๅ‡ฝๆ•ฐ็ป“ๅฐพ๏ผ‰้‡็ฝฎ่ฆ†็›–ไพ่ต–้กนใ€‚ diff --git a/docs/zh/docs/advanced/testing-events.md b/docs/zh/docs/advanced/testing-events.md index 71b3739c3d..221984e906 100644 --- a/docs/zh/docs/advanced/testing-events.md +++ b/docs/zh/docs/advanced/testing-events.md @@ -1,5 +1,11 @@ -# ๆต‹่ฏ•ไบ‹ไปถ๏ผšๅฏๅŠจ - ๅ…ณ้—ญ +# ๆต‹่ฏ•ไบ‹ไปถ๏ผšlifespan ๅ’Œ startup - shutdown { #testing-events-lifespan-and-startup-shutdown } -ไฝฟ็”จ `TestClient` ๅ’Œ `with` ่ฏญๅฅ๏ผŒๅœจๆต‹่ฏ•ไธญ่ฟ่กŒไบ‹ไปถๅค„็†ๅ™จ๏ผˆ`startup` ไธŽ `shutdown`๏ผ‰ใ€‚ +ๅฝ“ไฝ ้œ€่ฆๅœจๆต‹่ฏ•ไธญ่ฟ่กŒ `lifespan` ๆ—ถ๏ผŒๅฏไปฅๅฐ† `TestClient` ไธŽ `with` ่ฏญๅฅไธ€่ตทไฝฟ็”จ๏ผš -{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} + +ไฝ ๅฏไปฅๅœจ[ๅฎ˜ๆ–น Starlette ๆ–‡ๆกฃ็ซ™็‚น็š„โ€œๅœจๆต‹่ฏ•ไธญ่ฟ่กŒ lifespanโ€](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)้˜…่ฏปๆ›ดๅคš็ป†่Š‚ใ€‚ + +ๅฏนไบŽๅทฒๅผƒ็”จ็š„ `startup` ๅ’Œ `shutdown` ไบ‹ไปถ๏ผŒๅฏไปฅๆŒ‰ๅฆ‚ไธ‹ๆ–นๅผไฝฟ็”จ `TestClient`๏ผš + +{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} diff --git a/docs/zh/docs/advanced/testing-websockets.md b/docs/zh/docs/advanced/testing-websockets.md index b84647a3ed..64e1d3005f 100644 --- a/docs/zh/docs/advanced/testing-websockets.md +++ b/docs/zh/docs/advanced/testing-websockets.md @@ -1,13 +1,13 @@ -# ๆต‹่ฏ• WebSockets +# ๆต‹่ฏ• WebSockets { #testing-websockets } -ๆต‹่ฏ• WebSockets ไนŸไฝฟ็”จ `TestClient`ใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จๅŒไธ€ไธช `TestClient` ๆฅๆต‹่ฏ• WebSocketsใ€‚ -ไธบๆญค๏ผŒ่ฆๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ `TestClient` ่ฟžๆŽฅ WebSocketใ€‚ +ไธบๆญค๏ผŒๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ `TestClient` ่ฟžๆŽฅๅˆฐ WebSocket๏ผš -{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๆ›ดๅคš็ป†่Š‚่ฏฆ่ง Starlette ๅฎ˜ๆกฃ - ๆต‹่ฏ• WebSocketsใ€‚ +ๆ›ดๅคš็ป†่Š‚่ฏทๆŸฅ็œ‹ Starlette ็š„ๆ–‡ๆกฃ๏ผšๆต‹่ฏ• WebSocketsใ€‚ /// diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md index a9658c0348..64ba8da1b4 100644 --- a/docs/zh/docs/advanced/using-request-directly.md +++ b/docs/zh/docs/advanced/using-request-directly.md @@ -1,4 +1,4 @@ -# ็›ดๆŽฅไฝฟ็”จ่ฏทๆฑ‚ +# ็›ดๆŽฅไฝฟ็”จ Request { #using-the-request-directly } ่‡ณๆญค๏ผŒๆˆ‘ไปฌๅทฒ็ปไฝฟ็”จๅคš็ง็ฑปๅž‹ๅฃฐๆ˜Žไบ†่ฏทๆฑ‚็š„ๅ„็ง็ป„ไปถใ€‚ @@ -13,23 +13,23 @@ ไฝ†ๆœ‰ๆ—ถ๏ผŒๆˆ‘ไปฌไนŸ้œ€่ฆ็›ดๆŽฅ่ฎฟ้—ฎ `Request` ๅฏน่ฑกใ€‚ -## `Request` ๅฏน่ฑก็š„็ป†่Š‚ +## `Request` ๅฏน่ฑก็š„็ป†่Š‚ { #details-about-the-request-object } ๅฎž้™…ไธŠ๏ผŒ**FastAPI** ็š„ๅบ•ๅฑ‚ๆ˜ฏ **Starlette**๏ผŒ**FastAPI** ๅชไธ่ฟ‡ๆ˜ฏๅœจ **Starlette** ้กถๅฑ‚ๆไพ›ไบ†ไธ€ไบ›ๅทฅๅ…ท๏ผŒๆ‰€ไปฅ่ƒฝ็›ดๆŽฅไฝฟ็”จ Starlette ็š„ `Request` ๅฏน่ฑกใ€‚ -ไฝ†็›ดๆŽฅไปŽ `Request` ๅฏน่ฑกๆๅ–ๆ•ฐๆฎๆ—ถ๏ผˆไพ‹ๅฆ‚๏ผŒ่ฏปๅ–่ฏทๆฑ‚ไฝ“๏ผ‰๏ผŒ**FastAPI** ไธไผš้ชŒ่ฏใ€่ฝฌๆขๅ’Œๅญ˜ๆกฃๆ•ฐๆฎ๏ผˆไธบ API ๆ–‡ๆกฃไฝฟ็”จ OpenAPI๏ผ‰ใ€‚ +ไฝ†็›ดๆŽฅไปŽ `Request` ๅฏน่ฑกๆๅ–ๆ•ฐๆฎๆ—ถ๏ผˆไพ‹ๅฆ‚๏ผŒ่ฏปๅ–่ฏทๆฑ‚ไฝ“๏ผ‰๏ผŒ่ฟ™ไบ›ๆ•ฐๆฎไธไผš่ขซ **FastAPI** ้ชŒ่ฏใ€่ฝฌๆขๆˆ–ๆ–‡ๆกฃๅŒ–๏ผˆไฝฟ็”จ OpenAPI๏ผŒไธบ่‡ชๅŠจ็š„ API ็”จๆˆท็•Œ้ข๏ผ‰ใ€‚ ไธ่ฟ‡๏ผŒไปๅฏไปฅ้ชŒ่ฏใ€่ฝฌๆขไธŽๆณจ้‡Š๏ผˆไฝฟ็”จ Pydantic ๆจกๅž‹็š„่ฏทๆฑ‚ไฝ“็ญ‰๏ผ‰ๅ…ถๅฎƒๆญฃๅธธๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐใ€‚ ไฝ†ๅœจๆŸไบ›็‰นๅฎšๆƒ…ๅ†ตไธ‹๏ผŒ่ฟ˜ๆ˜ฏ้œ€่ฆๆๅ– `Request` ๅฏน่ฑกใ€‚ -## ็›ดๆŽฅไฝฟ็”จ `Request` ๅฏน่ฑก +## ็›ดๆŽฅไฝฟ็”จ `Request` ๅฏน่ฑก { #use-the-request-object-directly } ๅ‡่ฎพ่ฆๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ่Žทๅ–ๅฎขๆˆท็ซฏ IP ๅœฐๅ€ๅ’Œไธปๆœบใ€‚ ๆญคๆ—ถ๏ผŒ้œ€่ฆ็›ดๆŽฅ่ฎฟ้—ฎ่ฏทๆฑ‚ใ€‚ -{* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} ๆŠŠ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ็ฑปๅž‹ๅฃฐๆ˜Žไธบ `Request`๏ผŒ**FastAPI** ๅฐฑ่ƒฝๆŠŠ `Request` ไผ ้€’ๅˆฐๅ‚ๆ•ฐ้‡Œใ€‚ @@ -43,7 +43,7 @@ /// -## `Request` ๆ–‡ๆกฃ +## `Request` ๆ–‡ๆกฃ { #request-documentation } ๆ›ดๅคš็ป†่Š‚่ฏฆ่ง Starlette ๅฎ˜ๆกฃ -ย `Request` ๅฏน่ฑกใ€‚ @@ -51,6 +51,6 @@ ๆ‚จไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request`ใ€‚ -**FastAPI** ็š„ `from fastapi import Request` ๅชๆ˜ฏไธบๅผ€ๅ‘่€…ๆไพ›็š„ๅฟซๆทๆ–นๅผ๏ผŒไฝ†ๅ…ถๅฎžๅฎƒ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช Starletteใ€‚ +**FastAPI** ็›ดๆŽฅๆไพ›ๅฎƒๅชๆ˜ฏไธบไบ†ๆ–นไพฟๅผ€ๅ‘่€…๏ผŒไฝ†ๅฎƒ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ /// diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md index 005ed9242c..4486a2e69f 100644 --- a/docs/zh/docs/advanced/websockets.md +++ b/docs/zh/docs/advanced/websockets.md @@ -1,10 +1,12 @@ -# WebSockets +# WebSockets { #websockets } -ๆ‚จๅฏไปฅๅœจ **FastAPI** ไธญไฝฟ็”จ [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)ใ€‚ +ๆ‚จๅฏไปฅๅœจ **FastAPI** ไธญไฝฟ็”จ WebSocketsใ€‚ -## ๅฎ‰่ฃ… `WebSockets` +## ๅฎ‰่ฃ… `websockets` { #install-websockets } -้ฆ–ๅ…ˆ๏ผŒๆ‚จ้œ€่ฆๅฎ‰่ฃ… `WebSockets`๏ผš +่ฏท็กฎไฟๆ‚จๅˆ›ๅปบไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๆฟ€ๆดปๅฎƒ๏ผŒๅนถๅฎ‰่ฃ… `websockets`๏ผˆไธ€ไธช่ฎฉไฝฟ็”จโ€œWebSocketโ€ๅ่ฎฎๆ›ดๅฎนๆ˜“็š„ Python ๅบ“๏ผ‰๏ผš + +
```console $ pip install websockets @@ -12,11 +14,13 @@ $ pip install websockets ---> 100% ``` -## WebSockets ๅฎขๆˆท็ซฏ +
+ +## WebSockets ๅฎขๆˆท็ซฏ { #websockets-client } -### ๅœจ็”Ÿไบง็Žฏๅขƒไธญ +### ๅœจ็”Ÿไบง็Žฏๅขƒไธญ { #in-production } -ๅœจๆ‚จ็š„็”Ÿไบง็ณป็ปŸไธญ๏ผŒๆ‚จๅฏ่ƒฝไฝฟ็”จ็Žฐไปฃๆก†ๆžถ๏ผˆๅฆ‚Reactใ€Vue.jsๆˆ–Angular๏ผ‰ๅˆ›ๅปบไบ†ไธ€ไธชๅ‰็ซฏใ€‚ +ๅœจๆ‚จ็š„็”Ÿไบง็ณป็ปŸไธญ๏ผŒๆ‚จๅฏ่ƒฝไฝฟ็”จ็Žฐไปฃๆก†ๆžถ๏ผˆๅฆ‚ Reactใ€Vue.js ๆˆ– Angular๏ผ‰ๅˆ›ๅปบไบ†ไธ€ไธชๅ‰็ซฏใ€‚ ่ฆไฝฟ็”จ WebSockets ไธŽๅŽ็ซฏ่ฟ›่กŒ้€šไฟก๏ผŒๆ‚จๅฏ่ƒฝไผšไฝฟ็”จๅ‰็ซฏ็š„ๅทฅๅ…ทใ€‚ @@ -26,7 +30,7 @@ $ pip install websockets --- -ไฝ†ๆ˜ฏ๏ผŒๅœจๆœฌ็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๅฐ†ไฝฟ็”จไธ€ไธช้žๅธธ็ฎ€ๅ•็š„HTMLๆ–‡ๆกฃ๏ผŒๅ…ถไธญๅŒ…ๅซไธ€ไบ›JavaScript๏ผŒๅ…จ้ƒจๆ”พๅœจไธ€ไธช้•ฟๅญ—็ฌฆไธฒไธญใ€‚ +ไฝ†ๆ˜ฏ๏ผŒๅœจๆœฌ็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๅฐ†ไฝฟ็”จไธ€ไธช้žๅธธ็ฎ€ๅ•็š„ HTML ๆ–‡ๆกฃ๏ผŒๅ…ถไธญๅŒ…ๅซไธ€ไบ› JavaScript๏ผŒๅ…จ้ƒจๆ”พๅœจไธ€ไธช้•ฟๅญ—็ฌฆไธฒไธญใ€‚ ๅฝ“็„ถ๏ผŒ่ฟ™ๅนถไธๆ˜ฏๆœ€ไผ˜็š„ๅšๆณ•๏ผŒๆ‚จไธๅบ”่ฏฅๅœจ็”Ÿไบง็Žฏๅขƒไธญไฝฟ็”จๅฎƒใ€‚ @@ -34,13 +38,13 @@ $ pip install websockets ไฝ†่ฟ™ๆ˜ฏไธ€็งไธ“ๆณจไบŽ WebSockets ็š„ๆœๅŠกๅ™จ็ซฏๅนถๆไพ›ไธ€ไธชๅทฅไฝœ็คบไพ‹็š„ๆœ€็ฎ€ๅ•ๆ–นๅผ๏ผš -{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} -## ๅˆ›ๅปบ `websocket` +## ๅˆ›ๅปบ `websocket` { #create-a-websocket } ๅœจๆ‚จ็š„ **FastAPI** ๅบ”็”จ็จ‹ๅบไธญ๏ผŒๅˆ›ๅปบไธ€ไธช `websocket`๏ผš -{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} /// note | ๆŠ€ๆœฏ็ป†่Š‚ @@ -50,24 +54,28 @@ $ pip install websockets /// -## ็ญ‰ๅพ…ๆถˆๆฏๅนถๅ‘้€ๆถˆๆฏ +## ็ญ‰ๅพ…ๆถˆๆฏๅนถๅ‘้€ๆถˆๆฏ { #await-for-messages-and-send-messages } ๅœจๆ‚จ็š„ WebSocket ่ทฏ็”ฑไธญ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ `await` ็ญ‰ๅพ…ๆถˆๆฏๅนถๅ‘้€ๆถˆๆฏใ€‚ -{* ../../docs_src/websockets/tutorial001.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} ๆ‚จๅฏไปฅๆŽฅๆ”ถๅ’Œๅ‘้€ไบŒ่ฟ›ๅˆถใ€ๆ–‡ๆœฌๅ’Œ JSON ๆ•ฐๆฎใ€‚ -## ๅฐ่ฏ•ไธ€ไธ‹ +## ๅฐ่ฏ•ไธ€ไธ‹ { #try-it } ๅฆ‚ๆžœๆ‚จ็š„ๆ–‡ไปถๅไธบ `main.py`๏ผŒ่ฏทไฝฟ็”จไปฅไธ‹ๅ‘ฝไปค่ฟ่กŒๅบ”็”จ็จ‹ๅบ๏ผš +
+ ```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` +
+ ๅœจๆต่งˆๅ™จไธญๆ‰“ๅผ€ http://127.0.0.1:8000ใ€‚ ๆ‚จๅฐ†็œ‹ๅˆฐไธ€ไธช็ฎ€ๅ•็š„้กต้ข๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš @@ -86,11 +94,9 @@ $ uvicorn main:app --reload -ๆ‰€ๆœ‰่ฟ™ไบ›ๆถˆๆฏ้ƒฝๅฐ†ไฝฟ็”จๅŒไธ€ไธช WebSocket ่ฟž +ๆ‰€ๆœ‰่ฟ™ไบ›ๆถˆๆฏ้ƒฝๅฐ†ไฝฟ็”จๅŒไธ€ไธช WebSocket ่ฟžๆŽฅใ€‚ -ๆŽฅใ€‚ - -## ไฝฟ็”จ `Depends` ๅ’Œๅ…ถไป–ไพ่ต–้กน +## ไฝฟ็”จ `Depends` ๅ’Œๅ…ถไป–ไพ่ต–้กน { #using-depends-and-others } ๅœจ WebSocket ็ซฏ็‚นไธญ๏ผŒๆ‚จๅฏไปฅไปŽ `fastapi` ๅฏผๅ…ฅๅนถไฝฟ็”จไปฅไธ‹ๅ†…ๅฎน๏ผš @@ -101,7 +107,7 @@ $ uvicorn main:app --reload * `Path` * `Query` -ๅฎƒไปฌ็š„ๅทฅไฝœๆ–นๅผไธŽๅ…ถไป– FastAPI ็ซฏ็‚น/ *่ทฏๅพ„ๆ“ไฝœ* ็›ธๅŒ๏ผš +ๅฎƒไปฌ็š„ๅทฅไฝœๆ–นๅผไธŽๅ…ถไป– FastAPI ็ซฏ็‚น/*่ทฏๅพ„ๆ“ไฝœ* ็›ธๅŒ๏ผš {* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} @@ -113,16 +119,20 @@ $ uvicorn main:app --reload /// -### ๅฐ่ฏ•ๅธฆๆœ‰ไพ่ต–้กน็š„ WebSockets +### ๅฐ่ฏ•ๅธฆๆœ‰ไพ่ต–้กน็š„ WebSockets { #try-the-websockets-with-dependencies } ๅฆ‚ๆžœๆ‚จ็š„ๆ–‡ไปถๅไธบ `main.py`๏ผŒ่ฏทไฝฟ็”จไปฅไธ‹ๅ‘ฝไปค่ฟ่กŒๅบ”็”จ็จ‹ๅบ๏ผš +
+ ```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` +
+ ๅœจๆต่งˆๅ™จไธญๆ‰“ๅผ€ http://127.0.0.1:8000ใ€‚ ๅœจ้กต้ขไธญ๏ผŒๆ‚จๅฏไปฅ่ฎพ็ฝฎ๏ผš @@ -140,7 +150,7 @@ $ uvicorn main:app --reload -## ๅค„็†ๆ–ญๅผ€่ฟžๆŽฅๅ’Œๅคšไธชๅฎขๆˆท็ซฏ +## ๅค„็†ๆ–ญๅผ€่ฟžๆŽฅๅ’Œๅคšไธชๅฎขๆˆท็ซฏ { #handling-disconnections-and-multiple-clients } ๅฝ“ WebSocket ่ฟžๆŽฅๅ…ณ้—ญๆ—ถ๏ผŒ`await websocket.receive_text()` ๅฐ†ๅผ•ๅ‘ `WebSocketDisconnect` ๅผ‚ๅธธ๏ผŒๆ‚จๅฏไปฅๆ•่Žทๅนถๅค„็†่ฏฅๅผ‚ๅธธ๏ผŒๅฐฑๅƒๆœฌ็คบไพ‹ไธญ็š„็คบไพ‹ไธ€ๆ ทใ€‚ @@ -164,13 +174,13 @@ Client #1596980209979 left the chat ไฝ†่ฏท่ฎฐไฝ๏ผŒ็”ฑไบŽๆ‰€ๆœ‰ๅ†…ๅฎน้ƒฝๅœจๅ†…ๅญ˜ไธญไปฅๅ•ไธชๅˆ—่กจ็š„ๅฝขๅผๅค„็†๏ผŒๅ› ๆญคๅฎƒๅช่ƒฝๅœจ่ฟ›็จ‹่ฟ่กŒๆ—ถๅทฅไฝœ๏ผŒๅนถไธ”ๅช่ƒฝไฝฟ็”จๅ•ไธช่ฟ›็จ‹ใ€‚ -ๅฆ‚ๆžœๆ‚จ้œ€่ฆไธŽ FastAPI ้›†ๆˆๆ›ด็ฎ€ๅ•ไฝ†ๆ›ดๅผบๅคง็š„ๅŠŸ่ƒฝ๏ผŒๆ”ฏๆŒ Redisใ€PostgreSQL ๆˆ–ๅ…ถไป–ๅŠŸ่ƒฝ๏ผŒ่ฏทๆŸฅ็œ‹ [encode/broadcaster](https://github.com/encode/broadcaster)ใ€‚ +ๅฆ‚ๆžœๆ‚จ้œ€่ฆไธŽ FastAPI ้›†ๆˆๆ›ด็ฎ€ๅ•ไฝ†ๆ›ดๅผบๅคง็š„ๅŠŸ่ƒฝ๏ผŒๆ”ฏๆŒ Redisใ€PostgreSQL ๆˆ–ๅ…ถไป–ๅŠŸ่ƒฝ๏ผŒ่ฏทๆŸฅ็œ‹ encode/broadcasterใ€‚ /// -## ๆ›ดๅคšไฟกๆฏ +## ๆ›ดๅคšไฟกๆฏ { #more-info } ่ฆไบ†่งฃๆ›ดๅคš้€‰้กน๏ผŒ่ฏทๆŸฅ็œ‹ Starlette ็š„ๆ–‡ๆกฃ๏ผš -* [WebSocket ็ฑป](https://www.starlette.dev/websockets/) -* [ๅŸบไบŽ็ฑป็š„ WebSocket ๅค„็†](https://www.starlette.dev/endpoints/#websocketendpoint)ใ€‚ +* `WebSocket` ็ฑปใ€‚ +* ๅŸบไบŽ็ฑป็š„ WebSocket ๅค„็†ใ€‚ diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md index 363025a343..73fcb32196 100644 --- a/docs/zh/docs/advanced/wsgi.md +++ b/docs/zh/docs/advanced/wsgi.md @@ -1,32 +1,48 @@ -# ๅŒ…ๅซ WSGI - Flask๏ผŒDjango๏ผŒๅ…ถๅฎƒ +# ๅŒ…ๅซ WSGI - Flask๏ผŒDjango๏ผŒๅ…ถๅฎƒ { #including-wsgi-flask-django-others } -ๆ‚จๅฏไปฅๆŒ‚่ฝฝๅคšไธช WSGI ๅบ”็”จ๏ผŒๆญฃๅฆ‚ๆ‚จๅœจ [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} ไธญๆ‰€็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ +ๆ‚จๅฏไปฅๆŒ‚่ฝฝ WSGI ๅบ”็”จ๏ผŒๆญฃๅฆ‚ๆ‚จๅœจ [ๅญๅบ”็”จ - ๆŒ‚่ฝฝ](sub-applications.md){.internal-link target=_blank}ใ€[ๅœจไปฃ็†ไน‹ๅŽ](behind-a-proxy.md){.internal-link target=_blank} ไธญๆ‰€็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ ไธบๆญค, ๆ‚จๅฏไปฅไฝฟ็”จ `WSGIMiddleware` ๆฅๅŒ…่ฃ…ไฝ ็š„ WSGI ๅบ”็”จ๏ผŒๅฆ‚๏ผšFlask๏ผŒDjango๏ผŒ็ญ‰็ญ‰ใ€‚ -## ไฝฟ็”จ `WSGIMiddleware` +## ไฝฟ็”จ `WSGIMiddleware` { #using-wsgimiddleware } -ๆ‚จ้œ€่ฆๅฏผๅ…ฅ `WSGIMiddleware`ใ€‚ +/// info | ไฟกๆฏ + +้œ€่ฆๅฎ‰่ฃ… `a2wsgi`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install a2wsgi`ใ€‚ + +/// + +ๆ‚จ้œ€่ฆไปŽ `a2wsgi` ๅฏผๅ…ฅ `WSGIMiddleware`ใ€‚ ็„ถๅŽไฝฟ็”จ่ฏฅไธญ้—ดไปถๅŒ…่ฃ… WSGI ๅบ”็”จ๏ผˆไพ‹ๅฆ‚ Flask๏ผ‰ใ€‚ ไน‹ๅŽๅฐ†ๅ…ถๆŒ‚่ฝฝๅˆฐๆŸไธ€ไธช่ทฏๅพ„ไธ‹ใ€‚ -{* ../../docs_src/wsgi/tutorial001.py hl[2:3,22] *} +{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} + +/// note | ๆณจๆ„ + +ไน‹ๅ‰ๆŽจ่ไฝฟ็”จ `fastapi.middleware.wsgi` ไธญ็š„ `WSGIMiddleware`๏ผŒไฝ†ๅฎƒ็Žฐๅœจๅทฒ่ขซๅผƒ็”จใ€‚ + +ๅปบ่ฎฎๆ”น็”จ `a2wsgi` ๅŒ…๏ผŒไฝฟ็”จๆ–นๅผไฟๆŒไธๅ˜ใ€‚ + +ๅช่ฆ็กฎไฟๅทฒๅฎ‰่ฃ… `a2wsgi` ๅŒ…๏ผŒๅนถไธ”ไปŽ `a2wsgi` ๆญฃ็กฎๅฏผๅ…ฅ `WSGIMiddleware` ๅณๅฏใ€‚ + +/// -## ๆฃ€ๆŸฅ +## ๆฃ€ๆŸฅ { #check-it } ็Žฐๅœจ๏ผŒๆ‰€ๆœ‰ๅฎšไน‰ๅœจ `/v1/` ่ทฏๅพ„ไธ‹็š„่ฏทๆฑ‚ๅฐ†ไผš่ขซ Flask ๅบ”็”จๅค„็†ใ€‚ ๅ…ถไฝ™็š„่ฏทๆฑ‚ๅˆ™ไผš่ขซ **FastAPI** ๅค„็†ใ€‚ -ๅฆ‚ๆžœๆ‚จไฝฟ็”จ Uvicorn ่ฟ่กŒๅบ”็”จๅฎžไพ‹ๅนถไธ”่ฎฟ้—ฎ http://localhost:8000/v1/๏ผŒๆ‚จๅฐ†ไผš็œ‹ๅˆฐ็”ฑ Flask ่ฟ”ๅ›ž็š„ๅ“ๅบ”๏ผš +ๅฆ‚ๆžœไฝ ่ฟ่กŒๅฎƒๅนถ่ฎฟ้—ฎ http://localhost:8000/v1/๏ผŒไฝ ๅฐ†ไผš็œ‹ๅˆฐ็”ฑ Flask ่ฟ”ๅ›ž็š„ๅ“ๅบ”๏ผš ```txt Hello, World from Flask! ``` -ๅนถไธ”ๅฆ‚ๆžœๆ‚จ่ฎฟ้—ฎ http://localhost:8000/v2๏ผŒๆ‚จๅฐ†ไผš็œ‹ๅˆฐ็”ฑ FastAPI ่ฟ”ๅ›ž็š„ๅ“ๅบ”๏ผš +ๅฆ‚ๆžœไฝ ่ฎฟ้—ฎ http://localhost:8000/v2๏ผŒไฝ ๅฐ†ไผš็œ‹ๅˆฐ็”ฑ FastAPI ่ฟ”ๅ›ž็š„ๅ“ๅบ”๏ผš ```JSON { diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index 4028ed51aa..c94c907873 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -1,10 +1,10 @@ -# ๅนถๅ‘ async / await +# ๅนถๅ‘ async / await { #concurrency-and-async-await } ๆœ‰ๅ…ณ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ `async def` ่ฏญๆณ•ไปฅๅŠๅผ‚ๆญฅไปฃ็ ใ€ๅนถๅ‘ๅ’Œๅนถ่กŒ็š„ไธ€ไบ›่ƒŒๆ™ฏ็Ÿฅ่ฏ†ใ€‚ -## ่ตถๆ—ถ้—ดๅ—๏ผŸ +## ่ตถๆ—ถ้—ดๅ—๏ผŸ { #in-a-hurry } -TL;DR: +TL;DR: ๅฆ‚ๆžœไฝ ๆญฃๅœจไฝฟ็”จ็ฌฌไธ‰ๆ–นๅบ“๏ผŒๅฎƒไปฌไผšๅ‘Š่ฏ‰ไฝ ไฝฟ็”จ `await` ๅ…ณ้”ฎๅญ—ๆฅ่ฐƒ็”จๅฎƒไปฌ๏ผŒๅฐฑๅƒ่ฟ™ๆ ท๏ผš @@ -21,7 +21,7 @@ async def read_results(): return results ``` -/// note +/// note | ๆณจๆ„ ไฝ ๅช่ƒฝๅœจ่ขซ `async def` ๅˆ›ๅปบ็š„ๅ‡ฝๆ•ฐๅ†…ไฝฟ็”จ `await` @@ -40,7 +40,7 @@ def results(): --- -ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบไธ้œ€่ฆไธŽๅ…ถไป–ไปปไฝ•ไธœ่ฅฟ้€šไฟก่€Œ็ญ‰ๅพ…ๅ…ถๅ“ๅบ”๏ผŒ่ฏทไฝฟ็”จ `async def`ใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบไธ้œ€่ฆไธŽๅ…ถไป–ไปปไฝ•ไธœ่ฅฟ้€šไฟก่€Œ็ญ‰ๅพ…ๅ…ถๅ“ๅบ”๏ผŒ่ฏทไฝฟ็”จ `async def`๏ผŒๅณไฝฟๅ‡ฝๆ•ฐๅ†…้ƒจไธ้œ€่ฆไฝฟ็”จ `await`ใ€‚ --- @@ -54,7 +54,7 @@ def results(): ไฝ†ๆ˜ฏ๏ผŒ้€š่ฟ‡้ตๅพชไธŠ่ฟฐๆญฅ้ชค๏ผŒๅฎƒๅฐ†่ƒฝๅคŸ่ฟ›่กŒไธ€ไบ›ๆ€ง่ƒฝไผ˜ๅŒ–ใ€‚ -## ๆŠ€ๆœฏ็ป†่Š‚ +## ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details } Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ `await` ่ฏญๆณ•็š„ไธœ่ฅฟๆฅๅ†™**โ€ๅผ‚ๆญฅไปฃ็ โ€œ**ใ€‚ @@ -64,7 +64,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ * **`async` ๅ’Œ `await`** * **ๅ็จ‹** -## ๅผ‚ๆญฅไปฃ็  +## ๅผ‚ๆญฅไปฃ็  { #asynchronous-code } ๅผ‚ๆญฅไปฃ็ ไป…ไป…ๆ„ๅ‘ณ็€็ผ–็จ‹่ฏญ่จ€ ๐Ÿ’ฌ ๆœ‰ๅŠžๆณ•ๅ‘Š่ฏ‰่ฎก็ฎ—ๆœบ/็จ‹ๅบ ๐Ÿค– ๅœจไปฃ็ ไธญ็š„ๆŸไธช็‚น๏ผŒๅฎƒ ๐Ÿค– ๅฐ†ไธๅพ—ไธ็ญ‰ๅพ…ๅœจๆŸไบ›ๅœฐๆ–นๅฎŒๆˆไธ€ไบ›ไบ‹ๆƒ…ใ€‚่ฎฉๆˆ‘ไปฌๅ‡่ฎพไธ€ไบ›ไบ‹ๆƒ…่ขซ็งฐไธบ "ๆ…ขๆ–‡ไปถ"๐Ÿ“. @@ -74,7 +74,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ๆŽฅไธ‹ๆฅ๏ผŒๅฎƒ ๐Ÿค– ๅฎŒๆˆ็ฌฌไธ€ไธชไปปๅŠก๏ผˆๆฏ”ๅฆ‚ๆ˜ฏๆˆ‘ไปฌ็š„"ๆ…ขๆ–‡ไปถ"๐Ÿ“) ๅนถ็ปง็ปญไธŽไน‹็›ธๅ…ณ็š„ไธ€ๅˆ‡ใ€‚ -่ฟ™ไธช"็ญ‰ๅพ…ๅ…ถไป–ไบ‹ๆƒ…"้€šๅธธๆŒ‡็š„ๆ˜ฏไธ€ไบ›็›ธๅฏน่พƒๆ…ข๏ผˆไธŽๅค„็†ๅ™จๅ’Œ RAM ๅญ˜ๅ‚จๅ™จ็š„้€Ÿๅบฆ็›ธๆฏ”๏ผ‰็š„ I/O ๆ“ไฝœ๏ผŒๆฏ”ๅฆ‚่ฏด๏ผš +่ฟ™ไธช"็ญ‰ๅพ…ๅ…ถไป–ไบ‹ๆƒ…"้€šๅธธๆŒ‡็š„ๆ˜ฏไธ€ไบ›็›ธๅฏน่พƒๆ…ข๏ผˆไธŽๅค„็†ๅ™จๅ’Œ RAM ๅญ˜ๅ‚จๅ™จ็š„้€Ÿๅบฆ็›ธๆฏ”๏ผ‰็š„ I/O ๆ“ไฝœ๏ผŒๆฏ”ๅฆ‚่ฏด๏ผš * ้€š่ฟ‡็ฝ‘็ปœๅ‘้€ๆฅ่‡ชๅฎขๆˆท็ซฏ็š„ๆ•ฐๆฎ * ๅฎขๆˆท็ซฏๆŽฅๆ”ถๆฅ่‡ช็ฝ‘็ปœไธญ็š„ๆ•ฐๆฎ @@ -85,7 +85,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ * ไธ€ไธชๆ•ฐๆฎๅบ“ๆŸฅ่ฏข๏ผŒ็›ดๅˆฐ่ฟ”ๅ›ž็ป“ๆžœ * ็ญ‰็ญ‰. -่ฟ™ไธชๆ‰ง่กŒ็š„ๆ—ถ้—ดๅคงๅคšๆ˜ฏๅœจ็ญ‰ๅพ… I/O ๆ“ไฝœ๏ผŒๅ› ๆญคๅฎƒไปฌ่ขซๅซๅš "I/O ๅฏ†้›†ๅž‹" ๆ“ไฝœใ€‚ +่ฟ™ไธชๆ‰ง่กŒ็š„ๆ—ถ้—ดๅคงๅคšๆ˜ฏๅœจ็ญ‰ๅพ… I/O ๆ“ไฝœ๏ผŒๅ› ๆญคๅฎƒไปฌ่ขซๅซๅš "I/O ๅฏ†้›†ๅž‹" ๆ“ไฝœใ€‚ ๅฎƒ่ขซ็งฐไธบ"ๅผ‚ๆญฅ"็š„ๅŽŸๅ› ๆ˜ฏๅ› ไธบ่ฎก็ฎ—ๆœบ/็จ‹ๅบไธๅฟ…ไธŽๆ…ขไปปๅŠก"ๅŒๆญฅ"๏ผŒๅŽป็ญ‰ๅพ…ไปปๅŠกๅฎŒๆˆ็š„็กฎๅˆ‡ๆ—ถๅˆป๏ผŒ่€ŒๅœจๆญคๆœŸ้—ดไธๅšไปปไฝ•ไบ‹ๆƒ…็›ดๅˆฐ่ƒฝๅคŸ่Žทๅ–ไปปๅŠก็ป“ๆžœๆ‰็ปง็ปญๅทฅไฝœใ€‚ @@ -93,7 +93,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ๅฏนไบŽ"ๅŒๆญฅ"๏ผˆไธŽ"ๅผ‚ๆญฅ"็›ธๅ๏ผ‰๏ผŒไป–ไปฌ้€šๅธธไนŸไฝฟ็”จ"้กบๅบ"ไธ€่ฏ๏ผŒๅ› ไธบ่ฎก็ฎ—ๆœบ็จ‹ๅบๅœจๅˆ‡ๆขๅˆฐๅฆไธ€ไธชไปปๅŠกไน‹ๅ‰ๆ˜ฏๆŒ‰้กบๅบๆ‰ง่กŒๆ‰€ๆœ‰ๆญฅ้ชค๏ผŒๅณไฝฟ่ฟ™ไบ›ๆญฅ้ชคๆถ‰ๅŠๅˆฐ็ญ‰ๅพ…ใ€‚ -### ๅนถๅ‘ไธŽๆฑ‰ๅ ก +### ๅนถๅ‘ไธŽๆฑ‰ๅ ก { #concurrency-and-burgers } ไธŠ่ฟฐๅผ‚ๆญฅไปฃ็ ็š„ๆ€ๆƒณๆœ‰ๆ—ถไนŸ่ขซ็งฐไธบโ€œๅนถๅ‘โ€๏ผŒๅฎƒไธๅŒไบŽโ€œๅนถ่กŒโ€ใ€‚ @@ -103,7 +103,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ่ฆไบ†่งฃๅทฎๅผ‚๏ผŒ่ฏทๆƒณ่ฑกไปฅไธ‹ๅ…ณไบŽๆฑ‰ๅ ก็š„ๆ•…ไบ‹๏ผš -### ๅนถๅ‘ๆฑ‰ๅ ก +### ๅนถๅ‘ๆฑ‰ๅ ก { #concurrent-burgers } ไฝ ๅ’Œไฝ ็š„ๆ‹ไบบไธ€่ตทๅŽปๅฟซ้คๅบ—๏ผŒไฝ ๆŽ’้˜ŸๅœจๅŽ้ข๏ผŒๆ”ถ้“ถๅ‘˜ไปŽไฝ ๅ‰้ข็š„ไบบๆŽฅๅ•ใ€‚๐Ÿ˜ @@ -139,7 +139,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ -/// info +/// info | ไฟกๆฏ ๆผ‚ไบฎ็š„ๆ’็”ปๆฅ่‡ช Ketrina Thompson. ๐ŸŽจ @@ -163,7 +163,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ็„ถๅŽไฝ ๅŽปๆŸœๅฐ๐Ÿ”€๏ผŒ ๅˆฐ็Žฐๅœจๅˆๅง‹ไปปๅŠกๅทฒ็ปๅฎŒๆˆโฏ๏ผŒ ๆ‹ฟ่ตทๆฑ‰ๅ ก๏ผŒ่ฏดๅฃฐ่ฐข่ฐข๏ผŒ็„ถๅŽๆŠŠๅฎƒไปฌ้€ๅˆฐๆกŒไธŠใ€‚่ฟ™ๅฐฑๅฎŒๆˆไบ†ไธŽ่ฎกๆ•ฐๅ™จไบคไบ’็š„ๆญฅ้ชค/ไปปๅŠกโน. ่ฟ™ๅ่ฟ‡ๆฅๅˆไบง็”Ÿไบ†ไธ€้กนๆ–ฐไปปๅŠก๏ผŒๅณ"ๅƒๆฑ‰ๅ ก"๐Ÿ”€ โฏ๏ผŒ ไธŠไธ€ไธช"ๆ‹ฟๆฑ‰ๅ ก"็š„ไปปๅŠกๅทฒ็ป็ป“ๆŸไบ†โน. -### ๅนถ่กŒๆฑ‰ๅ ก +### ๅนถ่กŒๆฑ‰ๅ ก { #parallel-burgers } ็Žฐๅœจ่ฎฉๆˆ‘ไปฌๅ‡่ฎพไธๆ˜ฏ"ๅนถๅ‘ๆฑ‰ๅ ก"๏ผŒ่€Œๆ˜ฏ"ๅนถ่กŒๆฑ‰ๅ ก"ใ€‚ @@ -205,7 +205,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ๆฒกๆœ‰ๅคชๅคš็š„ไบค่ฐˆๆˆ–่ฐƒๆƒ…๏ผŒๅ› ไธบๅคง้ƒจๅˆ†ๆ—ถ้—ด ๐Ÿ•™ ้ƒฝๅœจๆŸœๅฐๅ‰็ญ‰ๅพ…๐Ÿ˜žใ€‚ -/// info +/// info | ไฟกๆฏ ๆผ‚ไบฎ็š„ๆ’็”ปๆฅ่‡ช Ketrina Thompson. ๐ŸŽจ @@ -233,7 +233,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ไฝ ๅฏไธไผšๆƒณๅธฆไฝ ็š„ๆ‹ไบบ ๐Ÿ˜ ๅ’Œไฝ ไธ€่ตทๅŽป้“ถ่กŒๅŠžไบ‹๐Ÿฆ. -### ๆฑ‰ๅ ก็ป“่ฎบ +### ๆฑ‰ๅ ก็ป“่ฎบ { #burger-conclusion } ๅœจ"ไฝ ไธŽๆ‹ไบบไธ€่ตทๅƒๆฑ‰ๅ ก"็š„่ฟ™ไธชๅœบๆ™ฏไธญ๏ผŒๅ› ไธบๆœ‰ๅพˆๅคšไบบๅœจ็ญ‰ๅพ…๐Ÿ•™๏ผŒ ไฝฟ็”จๅนถๅ‘็ณป็ปŸๆ›ดๆœ‰ๆ„ไน‰โธ๐Ÿ”€โฏ. @@ -253,7 +253,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ไฝ ๅฏไปฅๅŒๆ—ถๆ‹ฅๆœ‰ๅนถ่กŒๆ€งๅ’Œๅผ‚ๆญฅๆ€ง๏ผŒไฝ ๅฏไปฅ่Žทๅพ—ๆฏ”ๅคงๅคšๆ•ฐ็ป่ฟ‡ๆต‹่ฏ•็š„ NodeJS ๆก†ๆžถๆ›ด้ซ˜็š„ๆ€ง่ƒฝ๏ผŒๅนถไธ”ไธŽ Go ไธ็›ธไธŠไธ‹๏ผŒ Go ๆ˜ฏไธ€็งๆ›ดๆŽฅ่ฟ‘ไบŽ C ็š„็ผ–่ฏ‘่ฏญ่จ€๏ผˆๅ…จ้ƒจๅฝ’ๅŠŸไบŽ Starlette๏ผ‰ใ€‚ -### ๅนถๅ‘ๆฏ”ๅนถ่กŒๅฅฝๅ—๏ผŸ +### ๅนถๅ‘ๆฏ”ๅนถ่กŒๅฅฝๅ—๏ผŸ { #is-concurrency-better-than-parallelism } ไธ๏ผ่ฟ™ไธๆ˜ฏๆ•…ไบ‹็š„ๆœฌๆ„ใ€‚ @@ -277,7 +277,7 @@ Python ็š„็Žฐไปฃ็‰ˆๆœฌๆ”ฏๆŒ้€š่ฟ‡ไธ€็งๅซ**"ๅ็จ‹"**โ€”โ€”ไฝฟ็”จ `async` ๅ’Œ ๅœจ่ฟ™ไธชๅœบๆ™ฏไธญ๏ผŒๆฏไธชๆธ…ๆดๅทฅ๏ผˆๅŒ…ๆ‹ฌไฝ ๏ผ‰้ƒฝๅฐ†ๆ˜ฏไธ€ไธชๅค„็†ๅ™จ๏ผŒๅฎŒๆˆ่ฟ™ไธชๅทฅไฝœ็š„ไธ€้ƒจๅˆ†ใ€‚ -็”ฑไบŽๅคงๅคšๆ•ฐๆ‰ง่กŒๆ—ถ้—ดๆ˜ฏ็”ฑๅฎž้™…ๅทฅไฝœ๏ผˆ่€Œไธๆ˜ฏ็ญ‰ๅพ…๏ผ‰ๅ ็”จ็š„๏ผŒๅนถไธ”่ฎก็ฎ—ๆœบไธญ็š„ๅทฅไฝœๆ˜ฏ็”ฑ CPU ๅฎŒๆˆ็š„๏ผŒๆ‰€ไปฅไป–ไปฌ็งฐ่ฟ™ไบ›้—ฎ้ข˜ไธบ"CPU ๅฏ†้›†ๅž‹"ใ€‚ +็”ฑไบŽๅคงๅคšๆ•ฐๆ‰ง่กŒๆ—ถ้—ดๆ˜ฏ็”ฑๅฎž้™…ๅทฅไฝœ๏ผˆ่€Œไธๆ˜ฏ็ญ‰ๅพ…๏ผ‰ๅ ็”จ็š„๏ผŒๅนถไธ”่ฎก็ฎ—ๆœบไธญ็š„ๅทฅไฝœๆ˜ฏ็”ฑ CPU ๅฎŒๆˆ็š„๏ผŒๆ‰€ไปฅไป–ไปฌ็งฐ่ฟ™ไบ›้—ฎ้ข˜ไธบ"CPU ๅฏ†้›†ๅž‹"ใ€‚ --- @@ -290,7 +290,7 @@ CPU ๅฏ†้›†ๅž‹ๆ“ไฝœ็š„ๅธธ่ง็คบไพ‹ๆ˜ฏ้œ€่ฆๅคๆ‚็š„ๆ•ฐๅญฆๅค„็†ใ€‚ * **ๆœบๅ™จๅญฆไน **: ๅฎƒ้€šๅธธ้œ€่ฆๅคง้‡็š„"็Ÿฉ้˜ต"ๅ’Œ"ๅ‘้‡"ไน˜ๆณ•ใ€‚ๆƒณ่ฑกไธ€ไธชๅŒ…ๅซๆ•ฐๅญ—็š„ๅทจๅคง็”ตๅญ่กจๆ ผ๏ผŒๅนถๅŒๆ—ถๅฐ†ๆ‰€ๆœ‰ๆ•ฐๅญ—็›ธไน˜๏ผ› * **ๆทฑๅบฆๅญฆไน **: ่ฟ™ๆ˜ฏๆœบๅ™จๅญฆไน ็š„ไธ€ไธชๅญ้ข†ๅŸŸ๏ผŒๅŒๆ ท้€‚็”จใ€‚ๅชๆ˜ฏๆฒกๆœ‰ไธ€ไธชๆ•ฐๅญ—็š„็”ตๅญ่กจๆ ผๅฏไปฅ็›ธไน˜๏ผŒ่€Œๆ˜ฏไธ€ไธชๅบžๅคง็š„ๆ•ฐๅญ—้›†ๅˆ๏ผŒๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ้œ€่ฆไฝฟ็”จไธ€ไธช็‰นๆฎŠ็š„ๅค„็†ๅ™จๆฅๆž„ๅปบๅ’Œไฝฟ็”จ่ฟ™ไบ›ๆจกๅž‹ใ€‚ -### ๅนถๅ‘ + ๅนถ่กŒ: Web + ๆœบๅ™จๅญฆไน  +### ๅนถๅ‘ + ๅนถ่กŒ: Web + ๆœบๅ™จๅญฆไน  { #concurrency-parallelism-web-machine-learning } ไฝฟ็”จ **FastAPI**๏ผŒไฝ ๅฏไปฅๅˆฉ็”จ Web ๅผ€ๅ‘ไธญๅธธ่ง็š„ๅนถๅ‘ๆœบๅˆถ็š„ไผ˜ๅŠฟ๏ผˆNodeJS ็š„ไธป่ฆๅธๅผ•ๅŠ›๏ผ‰ใ€‚ @@ -300,7 +300,7 @@ CPU ๅฏ†้›†ๅž‹ๆ“ไฝœ็š„ๅธธ่ง็คบไพ‹ๆ˜ฏ้œ€่ฆๅคๆ‚็š„ๆ•ฐๅญฆๅค„็†ใ€‚ ไบ†่งฃๅฆ‚ไฝ•ๅœจ็”Ÿไบง็Žฏๅขƒไธญๅฎž็Žฐ่ฟ™็งๅนถ่กŒๆ€ง๏ผŒๅฏๆŸฅ็œ‹ๆญคๆ–‡ [Deployment](deployment/index.md){.internal-link target=_blank}ใ€‚ -## `async` ๅ’Œ `await` +## `async` ๅ’Œ `await` { #async-and-await } ็Žฐไปฃ็‰ˆๆœฌ็š„ Python ๆœ‰ไธ€็ง้žๅธธ็›ด่ง‚็š„ๆ–นๅผๆฅๅฎšไน‰ๅผ‚ๆญฅไปฃ็ ใ€‚่ฟ™ไฝฟๅฎƒ็œ‹่ตทๆฅๅฐฑๅƒๆญฃๅธธ็š„"้กบๅบ"ไปฃ็ ๏ผŒๅนถๅœจ้€‚ๅฝ“็š„ๆ—ถๅ€™"็ญ‰ๅพ…"ใ€‚ @@ -316,16 +316,16 @@ burgers = await get_burgers(2) ```Python hl_lines="1" async def get_burgers(number: int): - # Do some asynchronous stuff to create the burgers + # ๆ‰ง่กŒไธ€ไบ›ๅผ‚ๆญฅๆ“ไฝœๆฅๅˆถไฝœๆฑ‰ๅ ก return burgers ``` ...่€Œไธๆ˜ฏ `def`: ```Python hl_lines="2" -# This is not asynchronous +# ่ฟ™ไธๆ˜ฏๅผ‚ๆญฅ็š„ def get_sequential_burgers(number: int): - # Do some sequential stuff to create the burgers + # ๆ‰ง่กŒไธ€ไบ›้กบๅบๆ“ไฝœๆฅๅˆถไฝœๆฑ‰ๅ ก return burgers ``` @@ -334,7 +334,7 @@ def get_sequential_burgers(number: int): ๅฝ“ไฝ ๆƒณ่ฐƒ็”จไธ€ไธช `async def` ๅ‡ฝๆ•ฐๆ—ถ๏ผŒไฝ ๅฟ…้กป"็ญ‰ๅพ…"ๅฎƒใ€‚ๅ› ๆญค๏ผŒ่ฟ™ไธไผš่ตทไฝœ็”จ๏ผš ```Python -# This won't work, because get_burgers was defined with: async def +# ่ฟ™ๆ ทไธ่กŒ๏ผŒๅ› ไธบ get_burgers ๆ˜ฏ็”จ async def ๅฎšไน‰็š„ burgers = get_burgers(2) ``` @@ -349,7 +349,7 @@ async def read_burgers(): return burgers ``` -### ๆ›ดๅคšๆŠ€ๆœฏ็ป†่Š‚ +### ๆ›ดๅคšๆŠ€ๆœฏ็ป†่Š‚ { #more-technical-details } ไฝ ๅฏ่ƒฝๅทฒ็ปๆณจๆ„ๅˆฐ๏ผŒ`await` ๅช่ƒฝๅœจ `async def` ๅฎšไน‰็š„ๅ‡ฝๆ•ฐๅ†…้ƒจไฝฟ็”จใ€‚ @@ -361,7 +361,7 @@ async def read_burgers(): ไฝ†ๅฆ‚ๆžœไฝ ๆƒณๅœจๆฒกๆœ‰ FastAPI ็š„ๆƒ…ๅ†ตไธ‹ไฝฟ็”จ `async` / `await`๏ผŒๅˆ™ๅฏไปฅ่ฟ™ๆ ทๅšใ€‚ -### ็ผ–ๅ†™่‡ชๅทฑ็š„ๅผ‚ๆญฅไปฃ็  +### ็ผ–ๅ†™่‡ชๅทฑ็š„ๅผ‚ๆญฅไปฃ็  { #write-your-own-async-code } Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบไบŽ AnyIO ๅฎž็Žฐ็š„๏ผŒ่ฟ™ไฝฟๅพ—ๅฎƒไปฌๅฏไปฅๅ…ผๅฎน Python ็š„ๆ ‡ๅ‡†ๅบ“ asyncio ๅ’Œ Trioใ€‚ @@ -371,7 +371,7 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบไบŽ Asyncerใ€‚ๅฆ‚ๆžœไฝ ๆœ‰**็ป“ๅˆไฝฟ็”จๅผ‚ๆญฅไปฃ็ ๅ’Œๅธธ่ง„**๏ผˆ้˜ปๅกž/ๅŒๆญฅ๏ผ‰ไปฃ็ ็š„้œ€ๆฑ‚๏ผŒ่ฟ™ไธชๅบ“ไผš็‰นๅˆซๆœ‰็”จใ€‚ -### ๅ…ถไป–ๅฝขๅผ็š„ๅผ‚ๆญฅไปฃ็  +### ๅ…ถไป–ๅฝขๅผ็š„ๅผ‚ๆญฅไปฃ็  { #other-forms-of-asynchronous-code } ่ฟ™็งไฝฟ็”จ `async` ๅ’Œ `await` ็š„้ฃŽๆ ผๅœจ่ฏญ่จ€ไธญ็›ธๅฏน่พƒๆ–ฐใ€‚ @@ -385,13 +385,13 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบไบŽ I/O ็š„ไปฃ็ ใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ่ฟ‡ๅฆไธ€ไธชไธไปฅไธŠ่ฟฐๆ–นๅผๅทฅไฝœ็š„ๅผ‚ๆญฅๆก†ๆžถ๏ผŒๅนถไธ”ไฝ ไน ๆƒฏไบŽ็”จๆ™ฎ้€š็š„ `def` ๅฎšไน‰ๆ™ฎ้€š็š„ไป…่ฎก็ฎ—่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ๏ผŒไปฅ่Žทๅพ—ๅพฎๅฐ็š„ๆ€ง่ƒฝๅขž็›Š๏ผˆๅคง็บฆ100็บณ็ง’๏ผ‰๏ผŒ่ฏทๆณจๆ„๏ผŒๅœจ FastAPI ไธญ๏ผŒๆ•ˆๆžœๅฐ†ๅฎŒๅ…จ็›ธๅใ€‚ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆœ€ๅฅฝไฝฟ็”จ `async def`๏ผŒ้™ค้ž่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐๅ†…ไฝฟ็”จๆ‰ง่กŒ้˜ปๅกž I/O ็š„ไปฃ็ ใ€‚ -ๅœจ่ฟ™ไธค็งๆƒ…ๅ†ตไธ‹๏ผŒไธŽไฝ ไน‹ๅ‰็š„ๆก†ๆžถ็›ธๆฏ”๏ผŒ**FastAPI** ๅฏ่ƒฝ[ไป็„ถๅพˆๅฟซ](index.md#_11){.internal-link target=_blank}ใ€‚ +ๅœจ่ฟ™ไธค็งๆƒ…ๅ†ตไธ‹๏ผŒไธŽไฝ ไน‹ๅ‰็š„ๆก†ๆžถ็›ธๆฏ”๏ผŒ**FastAPI** ๅฏ่ƒฝ[ไป็„ถๅพˆๅฟซ](index.md#performance){.internal-link target=_blank}ใ€‚ -### ไพ่ต– +### ไพ่ต– { #dependencies } ่ฟ™ๅŒๆ ท้€‚็”จไบŽ[ไพ่ต–](tutorial/dependencies/index.md){.internal-link target=_blank}ใ€‚ๅฆ‚ๆžœไธ€ไธชไพ่ต–ๆ˜ฏๆ ‡ๅ‡†็š„ `def` ๅ‡ฝๆ•ฐ่€Œไธๆ˜ฏ `async def`๏ผŒๅฎƒๅฐ†่ขซ่ฟ่กŒๅœจๅค–้ƒจ็บฟ็จ‹ๆฑ ไธญใ€‚ -### ๅญไพ่ต– +### ๅญไพ่ต– { #sub-dependencies } ไฝ ๅฏไปฅๆ‹ฅๆœ‰ๅคšไธช็›ธไบ’ไพ่ต–็š„ไพ่ต–ไปฅๅŠ[ๅญไพ่ต–](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} ๏ผˆไฝœไธบๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ๏ผ‰๏ผŒๅฎƒไปฌไธญ็š„ไธ€ไบ›ๅฏ่ƒฝๆ˜ฏ้€š่ฟ‡ `async def` ๅฃฐๆ˜Ž๏ผŒไนŸๅฏ่ƒฝๆ˜ฏ้€š่ฟ‡ `def` ๅฃฐๆ˜Žใ€‚ๅฎƒไปฌไป็„ถๅฏไปฅๆญฃๅธธๅทฅไฝœ๏ผŒ่ฟ™ไบ›้€š่ฟ‡ `def` ๅฃฐๆ˜Ž็š„ๅ‡ฝๆ•ฐๅฐ†ไผšๅœจๅค–้ƒจ็บฟ็จ‹ไธญ่ฐƒ็”จ๏ผˆๆฅ่‡ช็บฟ็จ‹ๆฑ ๏ผ‰๏ผŒ่€Œไธๆ˜ฏ"่ขซ็ญ‰ๅพ…"ใ€‚ -### ๅ…ถไป–ๅ‡ฝๆ•ฐ +### ๅ…ถไป–ๅ‡ฝๆ•ฐ { #other-utility-functions } ไฝ ๅฏ็›ดๆŽฅ่ฐƒ็”จ้€š่ฟ‡ `def` ๆˆ– `async def` ๅˆ›ๅปบ็š„ไปปไฝ•ๅ…ถไป–ๅ‡ฝๆ•ฐ๏ผŒFastAPI ไธไผšๅฝฑๅ“ไฝ ่ฐƒ็”จๅฎƒไปฌ็š„ๆ–นๅผใ€‚ @@ -441,4 +441,4 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบไบŽ ่ตถๆ—ถ้—ดๅ—๏ผŸ. +ๅฆๅˆ™๏ผŒไฝ ๆœ€ๅฅฝๅบ”่ฏฅ้ตๅฎˆ็š„ๆŒ‡ๅฏผๅŽŸๅˆ™่ตถๆ—ถ้—ดๅ—๏ผŸ. diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md index 71e8d48382..1a4b4a3de8 100644 --- a/docs/zh/docs/benchmarks.md +++ b/docs/zh/docs/benchmarks.md @@ -1,10 +1,10 @@ -# ๅŸบๅ‡†ๆต‹่ฏ• +# ๅŸบๅ‡†ๆต‹่ฏ• { #benchmarks } -็ฌฌไธ‰ๆ–นๆœบๆž„ TechEmpower ็š„ๅŸบๅ‡†ๆต‹่ฏ•่กจๆ˜Žๅœจ Uvicorn ไธ‹่ฟ่กŒ็š„ **FastAPI** ๅบ”็”จ็จ‹ๅบๆ˜ฏ ๅฏ็”จ็š„ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€๏ผŒไป…ๆฌกไบŽ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ (็”ฑ FastAPI ๅ†…้ƒจไฝฟ็”จ๏ผ‰ใ€‚(*) +็ฌฌไธ‰ๆ–นๆœบๆž„ TechEmpower ็š„ๅŸบๅ‡†ๆต‹่ฏ•่กจๆ˜Žๅœจ Uvicorn ไธ‹่ฟ่กŒ็š„ **FastAPI** ๅบ”็”จ็จ‹ๅบๆ˜ฏ ๅฏ็”จ็š„ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€๏ผŒไป…ๆฌกไบŽ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ๏ผˆ็”ฑ FastAPI ๅ†…้ƒจไฝฟ็”จ๏ผ‰ใ€‚ ไฝ†ๆ˜ฏๅœจๆŸฅ็œ‹ๅŸบๅ‡†ๅพ—ๅˆ†ๅ’Œๅฏนๆฏ”ๆ—ถ๏ผŒ่ฏทๆณจๆ„ไปฅไธ‹ๅ‡ ็‚นใ€‚ -## ๅŸบๅ‡†ๆต‹่ฏ•ๅ’Œ้€Ÿๅบฆ +## ๅŸบๅ‡†ๆต‹่ฏ•ๅ’Œ้€Ÿๅบฆ { #benchmarks-and-speed } ๅฝ“ไฝ ๆŸฅ็œ‹ๅŸบๅ‡†ๆต‹่ฏ•ๆ—ถ๏ผŒๅ‡ ไธชไธๅŒ็ฑปๅž‹็š„ๅทฅๅ…ท่ขซ็ญ‰ๆ•ˆๅœฐๅšๆฏ”่พƒๆ˜ฏๅพˆๅธธ่ง็š„ๆƒ…ๅ†ตใ€‚ @@ -20,15 +20,15 @@ * **Uvicorn**: * ๅ…ทๆœ‰ๆœ€ไฝณๆ€ง่ƒฝ๏ผŒๅ› ไธบ้™คไบ†ๆœๅŠกๅ™จๆœฌ่บซๅค–๏ผŒๅฎƒๆฒกๆœ‰ๅคชๅคš้ขๅค–็š„ไปฃ็ ใ€‚ - * ๆ‚จไธไผš็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบใ€‚่ฟ™ๆ„ๅ‘ณ็€ๆ‚จ็š„ไปฃ็ ่‡ณๅฐ‘ๅฟ…้กปๅŒ…ๅซ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰ๆไพ›็š„ไปฃ็ ใ€‚ๅฆ‚ๆžœๆ‚จ่ฟ™ๆ ทๅšไบ†๏ผˆๅณ็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบ๏ผ‰๏ผŒๆœ€็ปˆ็š„ๅบ”็”จ็จ‹ๅบไผšๅ’Œไฝฟ็”จไบ†ๆก†ๆžถๅนถไธ”ๆœ€ๅฐๅŒ–ไบ†ๅบ”็”จไปฃ็ ๅ’Œ bug ็š„ๆƒ…ๅ†ตๅ…ทๆœ‰็›ธๅŒ็š„ๆ€ง่ƒฝๆŸ่€—ใ€‚ - * ๅฆ‚ๆžœ่ฆๅฏนๆฏ”ไธŽ Uvicorn ๅฏนๆ ‡็š„ๆœๅŠกๅ™จ๏ผŒ่ฏทๅฐ†ๅ…ถไธŽ Daphne๏ผŒHypercorn๏ผŒuWSGI็ญ‰ๅบ”็”จๆœๅŠกๅ™จ่ฟ›่กŒๆฏ”่พƒใ€‚ + * ไฝ ไธไผš็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบใ€‚่ฟ™ๆ„ๅ‘ณ็€ไฝ ็š„ไปฃ็ ่‡ณๅฐ‘ๅฟ…้กปๅŒ…ๅซ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰ๆไพ›็š„ไปฃ็ ใ€‚ๅฆ‚ๆžœไฝ ่ฟ™ๆ ทๅšไบ†๏ผˆๅณ็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบ๏ผ‰๏ผŒๆœ€็ปˆ็š„ๅบ”็”จ็จ‹ๅบไผšๅ’Œไฝฟ็”จไบ†ๆก†ๆžถๅนถไธ”ๆœ€ๅฐๅŒ–ไบ†ๅบ”็”จไปฃ็ ๅ’Œ bug ็š„ๆƒ…ๅ†ตๅ…ทๆœ‰็›ธๅŒ็š„ๆ€ง่ƒฝๆŸ่€—ใ€‚ + * ๅฆ‚ๆžœไฝ ่ฆๅฏนๆฏ” Uvicorn๏ผŒ่ฏทๅฐ†ๅ…ถไธŽ Daphne๏ผŒHypercorn๏ผŒuWSGI ็ญ‰ๅบ”็”จๆœๅŠกๅ™จ่ฟ›่กŒๆฏ”่พƒใ€‚ * **Starlette**: - * ๅœจ Uvicorn ๅŽไฝฟ็”จ Starlette๏ผŒๆ€ง่ƒฝไผš็•ฅๆœ‰ไธ‹้™ใ€‚ๅฎž้™…ไธŠ๏ผŒStarlette ไฝฟ็”จ Uvicorn่ฟ่กŒใ€‚ๅ› ๆญค๏ผŒ็”ฑไบŽๅฟ…้กปๆ‰ง่กŒๆ›ดๅคš็š„ไปฃ็ ๏ผŒๅฎƒๅชไผšๆฏ” Uvicorn ๆ›ดๆ…ขใ€‚ - * ไฝ†ๅฎƒไธบๆ‚จๆไพ›ไบ†ๆž„ๅปบ็ฎ€ๅ•็š„็ฝ‘็ปœ็จ‹ๅบ็š„ๅทฅๅ…ท๏ผŒๅนถๅ…ทๆœ‰ๅŸบไบŽ่ทฏๅพ„็š„่ทฏ็”ฑ็ญ‰ๅŠŸ่ƒฝใ€‚ + * ๅœจ Uvicorn ๅŽไฝฟ็”จ Starlette๏ผŒๆ€ง่ƒฝไผš็•ฅๆœ‰ไธ‹้™ใ€‚ๅฎž้™…ไธŠ๏ผŒStarlette ไฝฟ็”จ Uvicorn ่ฟ่กŒใ€‚ๅ› ๆญค๏ผŒ็”ฑไบŽๅฟ…้กปๆ‰ง่กŒๆ›ดๅคš็š„ไปฃ็ ๏ผŒๅฎƒๅชไผšๆฏ” Uvicorn ๆ›ดๆ…ขใ€‚ + * ไฝ†ๅฎƒไธบไฝ ๆไพ›ไบ†ๆž„ๅปบ็ฎ€ๅ•็š„็ฝ‘็ปœ็จ‹ๅบ็š„ๅทฅๅ…ท๏ผŒๅนถๅ…ทๆœ‰ๅŸบไบŽ่ทฏๅพ„็š„่ทฏ็”ฑ็ญ‰ๅŠŸ่ƒฝใ€‚ * ๅฆ‚ๆžœๆƒณๅฏนๆฏ”ไธŽ Starlette ๅฏนๆ ‡็š„ๅผ€ๅ‘ๆก†ๆžถ๏ผŒ่ฏทๅฐ†ๅ…ถไธŽ Sanic๏ผŒFlask๏ผŒDjango ็ญ‰็ฝ‘็ปœๆก†ๆžถ๏ผˆๆˆ–ๅพฎๆก†ๆžถ๏ผ‰่ฟ›่กŒๆฏ”่พƒใ€‚ * **FastAPI**: * ไธŽ Starlette ไฝฟ็”จ Uvicorn ไธ€ๆ ท๏ผŒ็”ฑไบŽ **FastAPI** ไฝฟ็”จ Starlette๏ผŒๅ› ๆญค FastAPI ไธ่ƒฝๆฏ” Starlette ๆ›ดๅฟซใ€‚ - * FastAPI ๅœจ Starlette ๅŸบ็ก€ไธŠๆไพ›ไบ†ๆ›ดๅคšๅŠŸ่ƒฝใ€‚ไพ‹ๅฆ‚ๅœจๅผ€ๅ‘ API ๆ—ถ๏ผŒๆ‰€้œ€็š„ๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–ๅŠŸ่ƒฝใ€‚FastAPI ๅฏไปฅๅธฎๅŠฉๆ‚จ่‡ชๅŠจ็”Ÿๆˆ APIๆ–‡ๆกฃ๏ผŒ๏ผˆๆ–‡ๆกฃๅœจๅบ”็”จ็จ‹ๅบๅฏๅŠจๆ—ถ่‡ชๅŠจ็”Ÿๆˆ๏ผŒๆ‰€ไปฅไธไผšๅขžๅŠ ๅบ”็”จ็จ‹ๅบ่ฟ่กŒๆ—ถ็š„ๅผ€้”€๏ผ‰ใ€‚ - * ๅฆ‚ๆžœๆ‚จไธไฝฟ็”จ FastAPI ่€Œ็›ดๆŽฅไฝฟ็”จ Starlette๏ผˆๆˆ–่ฏธๅฆ‚ Sanic๏ผŒFlask๏ผŒResponder ็ญ‰ๅ…ถๅฎƒๅทฅๅ…ท๏ผ‰๏ผŒๆ‚จๅˆ™่ฆ่‡ชๅทฑๅฎž็Žฐๆ‰€ๆœ‰็š„ๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–ใ€‚้‚ฃไนˆๆœ€็ปˆๆ‚จ็š„ๅบ”็”จ็จ‹ๅบไผšๅ’Œไฝฟ็”จ FastAPI ๆž„ๅปบ็š„็จ‹ๅบๆœ‰็›ธๅŒ็š„ๅผ€้”€ใ€‚ไธ€่ˆฌ่ฟ™็งๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–็š„ๆ“ไฝœๅœจๆ‚จๅบ”็”จ็จ‹ๅบ็š„ไปฃ็ ไธญไผšๅ ๅพˆๅคงๆฏ”้‡ใ€‚ - * ๅ› ๆญค๏ผŒ้€š่ฟ‡ไฝฟ็”จ FastAPI ๆ„ๅ‘ณ็€ๆ‚จๅฏไปฅ่Š‚็œๅผ€ๅ‘ๆ—ถ้—ด๏ผŒๅ‡ๅฐ‘็ผ–็ ้”™่ฏฏ๏ผŒ็”จๆ›ดๅฐ‘็š„็ผ–็ ๅฎž็Žฐๅ…ถๅŠŸ่ƒฝ๏ผŒๅนถไธ”็›ธๆฏ”ไธไฝฟ็”จ FastAPI ๆ‚จๅพˆๅคงๅฏ่ƒฝไผš่Žทๅพ—็›ธๅŒๆˆ–ๆ›ดๅฅฝ็š„ๆ€ง่ƒฝ๏ผˆๅ› ไธบ้‚ฃๆ ทๆ‚จๅฟ…้กปๅœจไปฃ็ ไธญๅฎž็Žฐๆ‰€ๆœ‰็›ธๅŒ็š„ๅŠŸ่ƒฝ๏ผ‰ใ€‚ - * ๅฆ‚ๆžœๆ‚จๆƒณๅฏนๆฏ”ไธŽ FastAPI ๅฏนๆ ‡็š„ๅผ€ๅ‘ๆก†ๆžถ๏ผŒ่ฏทไธŽ่ƒฝๅคŸๆไพ›ๆ•ฐๆฎ้ชŒ่ฏ๏ผŒๅบๅˆ—ๅŒ–ๅ’Œๅธฆๆœ‰่‡ชๅŠจๆ–‡ๆกฃ็”Ÿๆˆ็š„็ฝ‘็ปœๅบ”็”จ็จ‹ๅบๆก†ๆžถ๏ผˆๆˆ–ๅทฅๅ…ท้›†๏ผ‰่ฟ›่กŒๅฏนๆฏ”๏ผŒไพ‹ๅฆ‚ๅ…ทๆœ‰้›†ๆˆ่‡ชๅŠจๆ•ฐๆฎ้ชŒ่ฏ๏ผŒๅบๅˆ—ๅŒ–ๅ’Œ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃ็š„ Flask-apispec๏ผŒNestJS๏ผŒMolten ็ญ‰ใ€‚ + * FastAPI ๅœจ Starlette ๅŸบ็ก€ไธŠๆไพ›ไบ†ๆ›ดๅคšๅŠŸ่ƒฝใ€‚ไพ‹ๅฆ‚ๅœจๅผ€ๅ‘ API ๆ—ถ๏ผŒๆ‰€้œ€็š„ๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–ๅŠŸ่ƒฝใ€‚FastAPI ๅฏไปฅๅธฎๅŠฉไฝ ่‡ชๅŠจ็”Ÿๆˆ APIๆ–‡ๆกฃ๏ผŒ๏ผˆๆ–‡ๆกฃๅœจๅบ”็”จ็จ‹ๅบๅฏๅŠจๆ—ถ่‡ชๅŠจ็”Ÿๆˆ๏ผŒๆ‰€ไปฅไธไผšๅขžๅŠ ๅบ”็”จ็จ‹ๅบ่ฟ่กŒๆ—ถ็š„ๅผ€้”€๏ผ‰ใ€‚ + * ๅฆ‚ๆžœไฝ ไธไฝฟ็”จ FastAPI ่€Œ็›ดๆŽฅไฝฟ็”จ Starlette๏ผˆๆˆ–่ฏธๅฆ‚ Sanic๏ผŒFlask๏ผŒResponder ็ญ‰ๅ…ถๅฎƒๅทฅๅ…ท๏ผ‰๏ผŒไฝ ๅˆ™่ฆ่‡ชๅทฑๅฎž็Žฐๆ‰€ๆœ‰็š„ๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–ใ€‚้‚ฃไนˆๆœ€็ปˆไฝ ็š„ๅบ”็”จ็จ‹ๅบไผšๅ’Œไฝฟ็”จ FastAPI ๆž„ๅปบ็š„็จ‹ๅบๆœ‰็›ธๅŒ็š„ๅผ€้”€ใ€‚ไธ€่ˆฌ่ฟ™็งๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–็š„ๆ“ไฝœๅœจไฝ ๅบ”็”จ็จ‹ๅบ็š„ไปฃ็ ไธญไผšๅ ๅพˆๅคงๆฏ”้‡ใ€‚ + * ๅ› ๆญค๏ผŒ้€š่ฟ‡ไฝฟ็”จ FastAPI ๆ„ๅ‘ณ็€ไฝ ๅฏไปฅ่Š‚็œๅผ€ๅ‘ๆ—ถ้—ด๏ผŒๅ‡ๅฐ‘็ผ–็ ้”™่ฏฏ๏ผŒ็”จๆ›ดๅฐ‘็š„็ผ–็ ๅฎž็Žฐๅ…ถๅŠŸ่ƒฝ๏ผŒๅนถไธ”็›ธๆฏ”ไธไฝฟ็”จ FastAPI ไฝ ๅพˆๅคงๅฏ่ƒฝไผš่Žทๅพ—็›ธๅŒๆˆ–ๆ›ดๅฅฝ็š„ๆ€ง่ƒฝ๏ผˆๅ› ไธบ้‚ฃๆ ทไฝ ๅฟ…้กปๅœจไปฃ็ ไธญๅฎž็Žฐๆ‰€ๆœ‰็›ธๅŒ็š„ๅŠŸ่ƒฝ๏ผ‰ใ€‚ + * ๅฆ‚ๆžœไฝ ๆƒณๅฏนๆฏ” FastAPI๏ผŒ่ฏทไธŽ่ƒฝๅคŸๆไพ›ๆ•ฐๆฎ้ชŒ่ฏใ€ๅบๅˆ—ๅŒ–ๅ’Œๆ–‡ๆกฃ็š„็ฝ‘็ปœๅบ”็”จ็จ‹ๅบๆก†ๆžถ๏ผˆๆˆ–ๅทฅๅ…ท้›†๏ผ‰่ฟ›่กŒๅฏนๆฏ”๏ผŒไพ‹ๅฆ‚ๅ…ทๆœ‰้›†ๆˆ่‡ชๅŠจๆ•ฐๆฎ้ชŒ่ฏใ€ๅบๅˆ—ๅŒ–ๅ’Œ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃ็š„ Flask-apispec๏ผŒNestJS๏ผŒMolten ็ญ‰ใ€‚ diff --git a/docs/zh/docs/deployment/cloud.md b/docs/zh/docs/deployment/cloud.md index 8a892a560b..96883bd6bf 100644 --- a/docs/zh/docs/deployment/cloud.md +++ b/docs/zh/docs/deployment/cloud.md @@ -1,13 +1,24 @@ -# ๅœจไบ‘ไธŠ้ƒจ็ฝฒ FastAPI +# ๅœจไบ‘ๆœๅŠกๅ•†ไธŠ้ƒจ็ฝฒ FastAPI { #deploy-fastapi-on-cloud-providers } -ๆ‚จๅ‡ ไนŽๅฏไปฅไฝฟ็”จ**ไปปไฝ•ไบ‘ๆœๅŠกๅ•†**ๆฅ้ƒจ็ฝฒ FastAPI ๅบ”็”จ็จ‹ๅบใ€‚ +ไฝ ๅ‡ ไนŽๅฏไปฅไฝฟ็”จ**ไปปไฝ•ไบ‘ๆœๅŠกๅ•†**ๆฅ้ƒจ็ฝฒไฝ ็š„ FastAPI ๅบ”็”จใ€‚ -ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไธป่ฆ็š„ไบ‘ๆœๅŠกๅ•†้ƒฝๆœ‰้ƒจ็ฝฒ FastAPI ็š„ๆŒ‡ๅ—ใ€‚ +ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไธปๆตไบ‘ๆœๅŠกๅ•†้ƒฝๆœ‰้ƒจ็ฝฒ FastAPI ็š„ๆŒ‡ๅ—ใ€‚ -## ไบ‘ๆœๅŠกๅ•† - ่ตžๅŠฉๅ•† +## FastAPI Cloud { #fastapi-cloud } -ไธ€ไบ›ไบ‘ๆœๅŠกๅ•† โœจ [**่ตžๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๏ผŒ่ฟ™็กฎไฟไบ†FastAPI ๅŠๅ…ถ**็”Ÿๆ€็ณป็ปŸ**ๆŒ็ปญๅฅๅบทๅœฐ**ๅ‘ๅฑ•**ใ€‚ +**FastAPI Cloud** ็”ฑ **FastAPI** ่ƒŒๅŽ็š„ๅŒไธ€ไฝœ่€…ไธŽๅ›ข้˜Ÿๆ‰“้€ ใ€‚ -่ฟ™่กจๆ˜Žไบ†ไป–ไปฌๅฏน FastAPI ๅŠๅ…ถ**็คพๅŒบ**๏ผˆๆ‚จ๏ผ‰็š„็œŸๆญฃๆ‰ฟ่ฏบ๏ผŒๅ› ไธบไป–ไปฌไธไป…ๆƒณไธบๆ‚จๆไพ›**่‰ฏๅฅฝ็š„ๆœๅŠก**๏ผŒ่€Œไธ”่ฟ˜ๆƒณ็กฎไฟๆ‚จๆ‹ฅๆœ‰ไธ€ไธช**่‰ฏๅฅฝไธ”ๅฅๅบท็š„ๆก†ๆžถ**๏ผšFastAPIใ€‚ ๐Ÿ™‡ +ๅฎƒ็ฎ€ๅŒ–ไบ†**ๆž„ๅปบ**ใ€**้ƒจ็ฝฒ**ๅ’Œ**่ฎฟ้—ฎ** API ็š„ๆต็จ‹๏ผŒๅ‡ ไนŽไธ่ดนๅŠ›ใ€‚ -ๆ‚จๅฏ่ƒฝๆƒณๅฐ่ฏ•ไป–ไปฌ็š„ๆœๅŠกๅนถ้˜…่ฏปไป–ไปฌ็š„ๆŒ‡ๅ—. +ๅฎƒๆŠŠไฝฟ็”จ FastAPI ๆž„ๅปบๅบ”็”จๆ—ถ็›ธๅŒ็š„**ๅผ€ๅ‘่€…ไฝ“้ชŒ**ๅธฆๅˆฐไบ†ๅฐ†ๅบ”็”จ**้ƒจ็ฝฒ**ๅˆฐไบ‘ไธŠ็š„่ฟ‡็จ‹ใ€‚๐ŸŽ‰ + +FastAPI Cloud ๆ˜ฏ *FastAPI and friends* ๅผ€ๆบ้กน็›ฎ็š„ไธป่ฆ่ตžๅŠฉๆ–นๅ’Œ่ต„้‡‘ๆไพ›่€…ใ€‚โœจ + +## ไบ‘ๆœๅŠกๅ•† - ่ตžๅŠฉๅ•† { #cloud-providers-sponsors } + +่ฟ˜ๆœ‰ไธ€ไบ›ไบ‘ๆœๅŠกๅ•†ไนŸไผš โœจ [**่ตžๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจใ€‚๐Ÿ™‡ + +ไฝ ไนŸๅฏไปฅ่€ƒ่™‘ๆŒ‰็…งไป–ไปฌ็š„ๆŒ‡ๅ—ๅฐ่ฏ•ไป–ไปฌ็š„ๆœๅŠก๏ผš + +* Render +* Railway diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index f7208da7c5..66d32629cb 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -1,4 +1,4 @@ -# ้ƒจ็ฝฒๆฆ‚ๅฟต +# ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployments-concepts } ๅœจ้ƒจ็ฝฒ **FastAPI** ๅบ”็”จ็จ‹ๅบๆˆ–ไปปไฝ•็ฑปๅž‹็š„ Web API ๆ—ถ๏ผŒๆœ‰ๅ‡ ไธชๆฆ‚ๅฟตๅ€ผๅพ—ไบ†่งฃ๏ผŒ้€š่ฟ‡ๆŽŒๆก่ฟ™ไบ›ๆฆ‚ๅฟตๆ‚จๅฏไปฅๆ‰พๅˆฐ**ๆœ€ๅˆ้€‚็š„**ๆ–นๆณ•ๆฅ**้ƒจ็ฝฒๆ‚จ็š„ๅบ”็”จ็จ‹ๅบ**ใ€‚ @@ -13,7 +13,7 @@ ๆˆ‘ไปฌๆŽฅไธ‹ๆฅไบ†่งฃๅฎƒไปฌๅฐ†ๅฆ‚ไฝ•ๅฝฑๅ“**้ƒจ็ฝฒ**ใ€‚ -ๆˆ‘ไปฌ็š„ๆœ€็ปˆ็›ฎๆ ‡ๆ˜ฏ่ƒฝๅคŸไปฅ**ๅฎ‰ๅ…จ**็š„ๆ–นๅผ**ไธบๆ‚จ็š„ API ๅฎขๆˆท็ซฏ**ๆไพ›ๆœๅŠก๏ผŒๅŒๆ—ถ่ฆ**้ฟๅ…ไธญๆ–ญ**๏ผŒๅนถไธ”ๅฐฝๅฏ่ƒฝ้ซ˜ๆ•ˆๅœฐๅˆฉ็”จ**่ฎก็ฎ—่ต„ๆบ**๏ผˆ ไพ‹ๅฆ‚ๆœๅŠกๅ™จCPU่ต„ๆบ๏ผ‰ใ€‚ ๐Ÿš€ +ๆˆ‘ไปฌ็š„ๆœ€็ปˆ็›ฎๆ ‡ๆ˜ฏ่ƒฝๅคŸไปฅ**ๅฎ‰ๅ…จ**็š„ๆ–นๅผ**ไธบๆ‚จ็š„ API ๅฎขๆˆท็ซฏ**ๆไพ›ๆœๅŠก๏ผŒๅŒๆ—ถ่ฆ**้ฟๅ…ไธญๆ–ญ**๏ผŒๅนถไธ”ๅฐฝๅฏ่ƒฝ้ซ˜ๆ•ˆๅœฐๅˆฉ็”จ**่ฎก็ฎ—่ต„ๆบ**๏ผˆไพ‹ๅฆ‚่ฟœ็จ‹ๆœๅŠกๅ™จ/่™šๆ‹Ÿๆœบ๏ผ‰ใ€‚ ๐Ÿš€ ๆˆ‘ๅฐ†ๅœจ่ฟ™้‡Œๅ‘Š่ฏ‰ๆ‚จๆ›ดๅคšๅ…ณไบŽ่ฟ™ไบ›**ๆฆ‚ๅฟต**็š„ไฟกๆฏ๏ผŒๅธŒๆœ›่ƒฝ็ป™ๆ‚จๆไพ›**็›ด่ง‰**ๆฅๅ†ณๅฎšๅฆ‚ไฝ•ๅœจ้žๅธธไธๅŒ็š„็Žฏๅขƒไธญ้ƒจ็ฝฒ API๏ผŒ็”š่‡ณๅœจๆ˜ฏๅฐšไธๅญ˜ๅœจ็š„**ๆœชๆฅ**็š„็Žฏๅขƒ้‡Œใ€‚ @@ -23,7 +23,7 @@ ไฝ†็Žฐๅœจ๏ผŒ่ฎฉๆˆ‘ไปฌไป”็ป†็œ‹ไธ€ไธ‹่ฟ™ไบ›้‡่ฆ็š„**ๆฆ‚ๅฟต**ใ€‚ ่ฟ™ไบ›ๆฆ‚ๅฟตไนŸ้€‚็”จไบŽไปปไฝ•ๅ…ถไป–็ฑปๅž‹็š„ Web APIใ€‚ ๐Ÿ’ก -## ๅฎ‰ๅ…จๆ€ง - HTTPS +## ๅฎ‰ๅ…จๆ€ง - HTTPS { #security-https } ๅœจ[ไธŠไธ€็ซ ๆœ‰ๅ…ณ HTTPS](https.md){.internal-link target=_blank} ไธญ๏ผŒๆˆ‘ไปฌไบ†่งฃไบ† HTTPS ๅฆ‚ไฝ•ไธบๆ‚จ็š„ API ๆไพ›ๅŠ ๅฏ†ใ€‚ @@ -31,21 +31,20 @@ ๅนถไธ”ๅฟ…้กปๆœ‰ๆŸไธชไธœ่ฅฟ่ดŸ่ดฃ**ๆ›ดๆ–ฐ HTTPS ่ฏไนฆ**๏ผŒๅฎƒๅฏไปฅๆ˜ฏ็›ธๅŒ็š„็ป„ไปถ๏ผŒไนŸๅฏไปฅๆ˜ฏไธๅŒ็š„็ป„ไปถใ€‚ - -### HTTPS ็คบไพ‹ๅทฅๅ…ท +### HTTPS ็คบไพ‹ๅทฅๅ…ท { #example-tools-for-https } ๆ‚จๅฏไปฅ็”จไฝœ TLS ็ปˆๆญขไปฃ็†็š„ไธ€ไบ›ๅทฅๅ…ทๅŒ…ๆ‹ฌ๏ผš * Traefik - * ่‡ชๅŠจๅค„็†่ฏไนฆๆ›ดๆ–ฐ โœจ + * ่‡ชๅŠจๅค„็†่ฏไนฆๆ›ดๆ–ฐ โœจ * Caddy - * ่‡ชๅŠจๅค„็†่ฏไนฆๆ›ดๆ–ฐ โœจ + * ่‡ชๅŠจๅค„็†่ฏไนฆๆ›ดๆ–ฐ โœจ * Nginx - * ไฝฟ็”จ Certbot ็ญ‰ๅค–้ƒจ็ป„ไปถ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ + * ไฝฟ็”จ Certbot ็ญ‰ๅค–้ƒจ็ป„ไปถ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ * HAProxy - * ไฝฟ็”จ Certbot ็ญ‰ๅค–้ƒจ็ป„ไปถ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ -* ๅธฆๆœ‰ Ingress Controller(ๅฆ‚Nginx) ็š„ Kubernetes - * ไฝฟ็”จ่ฏธๅฆ‚ cert-manager ไน‹็ฑป็š„ๅค–้ƒจ็ป„ไปถๆฅ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ + * ไฝฟ็”จ Certbot ็ญ‰ๅค–้ƒจ็ป„ไปถ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ +* ๅธฆๆœ‰ Ingress Controller๏ผˆๅฆ‚ Nginx๏ผ‰ ็š„ Kubernetes + * ไฝฟ็”จ่ฏธๅฆ‚ cert-manager ไน‹็ฑป็š„ๅค–้ƒจ็ป„ไปถๆฅ่ฟ›่กŒ่ฏไนฆๆ›ดๆ–ฐ * ็”ฑไบ‘ๆœๅŠกๅ•†ๅ†…้ƒจๅค„็†๏ผŒไฝœไธบๅ…ถๆœๅŠก็š„ไธ€้ƒจๅˆ†๏ผˆ่ฏท้˜…่ฏปไธ‹ๆ–‡๐Ÿ‘‡๏ผ‰ ๅฆไธ€็ง้€‰ๆ‹ฉๆ˜ฏๆ‚จๅฏไปฅไฝฟ็”จ**ไบ‘ๆœๅŠก**ๆฅๅฎŒๆˆๆ›ดๅคšๅทฅไฝœ๏ผŒๅŒ…ๆ‹ฌ่ฎพ็ฝฎ HTTPSใ€‚ ๅฎƒๅฏ่ƒฝๆœ‰ไธ€ไบ›้™ๅˆถๆˆ–ๅ‘ๆ‚จๆ”ถๅ–ๆ›ดๅคš่ดน็”จ็ญ‰ใ€‚ไฝ†ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จไธๅฟ…่‡ชๅทฑ่ฎพ็ฝฎ TLS ็ปˆๆญขไปฃ็†ใ€‚ @@ -56,11 +55,11 @@ ๆŽฅไธ‹ๆฅ่ฆ่€ƒ่™‘็š„ๆฆ‚ๅฟต้ƒฝๆ˜ฏๅ…ณไบŽ่ฟ่กŒๅฎž้™… API ็š„็จ‹ๅบ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ใ€‚ -## ็จ‹ๅบๅ’Œ่ฟ›็จ‹ +## ็จ‹ๅบๅ’Œ่ฟ›็จ‹ { #program-and-process } ๆˆ‘ไปฌๅฐ†่ฎจ่ฎบๅพˆๅคšๅ…ณไบŽๆญฃๅœจ่ฟ่กŒ็š„โ€œ**่ฟ›็จ‹**โ€็š„ๅ†…ๅฎน๏ผŒๅ› ๆญคๅผ„ๆธ…ๆฅšๅฎƒ็š„ๅซไน‰ไปฅๅŠไธŽโ€œ**็จ‹ๅบ**โ€่ฟ™ไธช่ฏๆœ‰ไป€ไนˆๅŒบๅˆซๆ˜ฏๅพˆๆœ‰็”จ็š„ใ€‚ -### ไป€ไนˆๆ˜ฏ็จ‹ๅบ +### ไป€ไนˆๆ˜ฏ็จ‹ๅบ { #what-is-a-program } **็จ‹ๅบ**่ฟ™ไธช่ฏ้€šๅธธ็”จๆฅๆ่ฟฐๅพˆๅคšไธœ่ฅฟ๏ผš @@ -68,12 +67,12 @@ * ๆ“ไฝœ็ณป็ปŸๅฏไปฅ**ๆ‰ง่กŒ**็š„**ๆ–‡ไปถ**๏ผŒไพ‹ๅฆ‚๏ผš`python`ใ€`python.exe`ๆˆ–`uvicorn`ใ€‚ * ๅœจๆ“ไฝœ็ณป็ปŸไธŠ**่ฟ่กŒ**ใ€ไฝฟ็”จCPU ๅนถๅฐ†ๅ†…ๅฎนๅญ˜ๅ‚จๅœจๅ†…ๅญ˜ไธŠ็š„็‰นๅฎš็จ‹ๅบใ€‚ ่ฟ™ไนŸ่ขซ็งฐไธบ**่ฟ›็จ‹**ใ€‚ -### ไป€ไนˆๆ˜ฏ่ฟ›็จ‹ +### ไป€ไนˆๆ˜ฏ่ฟ›็จ‹ { #what-is-a-process } **่ฟ›็จ‹** ่ฟ™ไธช่ฏ้€šๅธธไปฅๆ›ดๅ…ทไฝ“็š„ๆ–นๅผไฝฟ็”จ๏ผŒไป…ๆŒ‡ๅœจๆ“ไฝœ็ณป็ปŸไธญ่ฟ่กŒ็š„ไธœ่ฅฟ๏ผˆๅฆ‚ไธŠ้ข็š„ๆœ€ๅŽไธ€็‚น๏ผ‰๏ผš * ๅœจๆ“ไฝœ็ณป็ปŸไธŠ**่ฟ่กŒ**็š„็‰นๅฎš็จ‹ๅบใ€‚ - * ่ฟ™ไธๆ˜ฏๆŒ‡ๆ–‡ไปถ๏ผŒไนŸไธๆ˜ฏๆŒ‡ไปฃ็ ๏ผŒๅฎƒ**ๅ…ทไฝ“**ๆŒ‡็š„ๆ˜ฏๆ“ไฝœ็ณป็ปŸๆญฃๅœจ**ๆ‰ง่กŒ**ๅ’Œ็ฎก็†็š„ไธœ่ฅฟใ€‚ + * ่ฟ™ไธๆ˜ฏๆŒ‡ๆ–‡ไปถ๏ผŒไนŸไธๆ˜ฏๆŒ‡ไปฃ็ ๏ผŒๅฎƒ**ๅ…ทไฝ“**ๆŒ‡็š„ๆ˜ฏๆ“ไฝœ็ณป็ปŸๆญฃๅœจ**ๆ‰ง่กŒ**ๅ’Œ็ฎก็†็š„ไธœ่ฅฟใ€‚ * ไปปไฝ•็จ‹ๅบ๏ผŒไปปไฝ•ไปฃ็ ๏ผŒ**ๅชๆœ‰ๅœจๆ‰ง่กŒๆ—ถๆ‰่ƒฝๅšไบ‹**ใ€‚ ๅ› ๆญค๏ผŒๆ˜ฏๅฝ“ๆœ‰**่ฟ›็จ‹ๆญฃๅœจ่ฟ่กŒ**ๆ—ถใ€‚ * ่ฏฅ่ฟ›็จ‹ๅฏไปฅ็”ฑๆ‚จๆˆ–ๆ“ไฝœ็ณป็ปŸ**็ปˆๆญข**๏ผˆๆˆ–โ€œๆ€ๆญปโ€๏ผ‰ใ€‚ ้‚ฃๆ—ถ๏ผŒๅฎƒๅœๆญข่ฟ่กŒ/่ขซๆ‰ง่กŒ๏ผŒๅนถไธ”ๅฎƒๅฏไปฅ**ไธๅ†ๅšไบ‹ๆƒ…**ใ€‚ * ๆ‚จ่ฎก็ฎ—ๆœบไธŠ่ฟ่กŒ็š„ๆฏไธชๅบ”็”จ็จ‹ๅบ่ƒŒๅŽ้ƒฝๆœ‰ไธ€ไบ›่ฟ›็จ‹๏ผŒๆฏไธชๆญฃๅœจ่ฟ่กŒ็š„็จ‹ๅบ๏ผŒๆฏไธช็ช—ๅฃ็ญ‰ใ€‚ๅนถไธ”้€šๅธธๅœจ่ฎก็ฎ—ๆœบๆ‰“ๅผ€ๆ—ถ**ๅŒๆ—ถ**่ฟ่กŒ่ฎธๅคš่ฟ›็จ‹ใ€‚ @@ -89,13 +88,13 @@ ็Žฐๅœจๆˆ‘ไปฌ็Ÿฅ้“ไบ†ๆœฏ่ฏญโ€œ่ฟ›็จ‹โ€ๅ’Œโ€œ็จ‹ๅบโ€ไน‹้—ด็š„ๅŒบๅˆซ๏ผŒ่ฎฉๆˆ‘ไปฌ็ปง็ปญ่ฎจ่ฎบ้ƒจ็ฝฒใ€‚ -## ๅฏๅŠจๆ—ถ่ฟ่กŒ +## ๅฏๅŠจๆ—ถ่ฟ่กŒ { #running-on-startup } ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒๅฝ“ๆ‚จๅˆ›ๅปบ Web API ๆ—ถ๏ผŒๆ‚จๅธŒๆœ›ๅฎƒ**ๅง‹็ปˆ่ฟ่กŒ**ใ€ไธ้—ดๆ–ญ๏ผŒไปฅไพฟๆ‚จ็š„ๅฎขๆˆท็ซฏๅง‹็ปˆๅฏไปฅ่ฎฟ้—ฎๅฎƒใ€‚ ่ฟ™ๆ˜ฏๅฝ“็„ถ็š„๏ผŒ้™ค้žๆ‚จๆœ‰็‰นๅฎšๅŽŸๅ› ๅธŒๆœ›ๅฎƒไป…ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹่ฟ่กŒ๏ผŒไฝ†ๅคงๅคšๆ•ฐๆ—ถๅ€™ๆ‚จๅธŒๆœ›ๅฎƒไธๆ–ญ่ฟ่กŒๅนถไธ”**ๅฏ็”จ**ใ€‚ -### ๅœจ่ฟœ็จ‹ๆœๅŠกๅ™จไธญ +### ๅœจ่ฟœ็จ‹ๆœๅŠกๅ™จไธญ { #in-a-remote-server } -ๅฝ“ๆ‚จ่ฎพ็ฝฎ่ฟœ็จ‹ๆœๅŠกๅ™จ๏ผˆไบ‘ๆœๅŠกๅ™จใ€่™šๆ‹Ÿๆœบ็ญ‰๏ผ‰ๆ—ถ๏ผŒๆ‚จๅฏไปฅๅš็š„ๆœ€็ฎ€ๅ•็š„ไบ‹ๆƒ…ๅฐฑๆ˜ฏๆ‰‹ๅŠจ่ฟ่กŒ Uvicorn๏ผˆๆˆ–็ฑปไผผ็š„๏ผ‰๏ผŒๅฐฑๅƒๆœฌๅœฐๅผ€ๅ‘ๆ—ถไธ€ๆ ทใ€‚ +ๅฝ“ๆ‚จ่ฎพ็ฝฎ่ฟœ็จ‹ๆœๅŠกๅ™จ๏ผˆไบ‘ๆœๅŠกๅ™จใ€่™šๆ‹Ÿๆœบ็ญ‰๏ผ‰ๆ—ถ๏ผŒๆ‚จๅฏไปฅๅš็š„ๆœ€็ฎ€ๅ•็š„ไบ‹ๆƒ…ๅฐฑๆ˜ฏไฝฟ็”จ `fastapi run`๏ผˆๅฎƒไฝฟ็”จ Uvicorn๏ผ‰ๆˆ–็ฑปไผผๆ–นๅผ๏ผŒๆ‰‹ๅŠจ่ฟ่กŒ๏ผŒๅฐฑๅƒๆœฌๅœฐๅผ€ๅ‘ๆ—ถไธ€ๆ ทใ€‚ ๅฎƒๅฐ†ไผšๅœจ**ๅผ€ๅ‘่ฟ‡็จ‹ไธญ**ๅ‘ๆŒฅไฝœ็”จๅนถๅ‘ๆŒฅไฝœ็”จใ€‚ @@ -103,16 +102,15 @@ ๅฆ‚ๆžœๆœๅŠกๅ™จ้‡ๆ–ฐๅฏๅŠจ๏ผˆไพ‹ๅฆ‚ๆ›ดๆ–ฐๅŽๆˆ–ไปŽไบ‘ๆไพ›ๅ•†่ฟ็งปๅŽ๏ผ‰๏ผŒๆ‚จๅฏ่ƒฝ**ไธไผšๆณจๆ„ๅˆฐๅฎƒ**ใ€‚ ๅ› ๆญค๏ผŒๆ‚จ็”š่‡ณไธ็Ÿฅ้“ๅฟ…้กปๆ‰‹ๅŠจ้‡ๆ–ฐๅฏๅŠจ่ฏฅ่ฟ›็จ‹ใ€‚ ๆ‰€ไปฅ๏ผŒไฝ ็š„ API ๅฐ†ไธ€็›ดๅค„ไบŽๆŒ‚ๆމ็š„็Šถๆ€ใ€‚ ๐Ÿ˜ฑ - -### ๅฏๅŠจๆ—ถ่‡ชๅŠจ่ฟ่กŒ +### ๅฏๅŠจๆ—ถ่‡ชๅŠจ่ฟ่กŒ { #run-automatically-on-startup } ไธ€่ˆฌๆฅ่ฏด๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›ๆœๅŠกๅ™จ็จ‹ๅบ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ๅœจๆœๅŠกๅ™จๅฏๅŠจๆ—ถ่‡ชๅŠจๅฏๅŠจ๏ผŒๅนถไธ”ไธ้œ€่ฆไปปไฝ•**ไบบไธบๅนฒ้ข„**๏ผŒ่ฎฉ่ฟ›็จ‹ๅง‹็ปˆไธŽๆ‚จ็š„ API ไธ€่ตท่ฟ่กŒ๏ผˆไพ‹ๅฆ‚ Uvicorn ่ฟ่กŒๆ‚จ็š„ FastAPI ๅบ”็”จ็จ‹ๅบ๏ผ‰ ใ€‚ -### ๅ•็‹ฌ็š„็จ‹ๅบ +### ๅ•็‹ฌ็š„็จ‹ๅบ { #separate-program } ไธบไบ†ๅฎž็Žฐ่ฟ™ไธ€็‚น๏ผŒๆ‚จ้€šๅธธไผšๆœ‰ไธ€ไธช**ๅ•็‹ฌ็š„็จ‹ๅบ**ๆฅ็กฎไฟๆ‚จ็š„ๅบ”็”จ็จ‹ๅบๅœจๅฏๅŠจๆ—ถ่ฟ่กŒใ€‚ ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒ่ฟ˜ๅฏไปฅ็กฎไฟๅ…ถไป–็ป„ไปถๆˆ–ๅบ”็”จ็จ‹ๅบไนŸ่ฟ่กŒ๏ผŒไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“ใ€‚ -### ๅฏๅŠจๆ—ถ่ฟ่กŒ็š„็คบไพ‹ๅทฅๅ…ท +### ๅฏๅŠจๆ—ถ่ฟ่กŒ็š„็คบไพ‹ๅทฅๅ…ท { #example-tools-to-run-at-startup } ๅฏไปฅๅฎŒๆˆ่ฟ™้กนๅทฅไฝœ็š„ๅทฅๅ…ท็š„ไธ€ไบ›็คบไพ‹ๆ˜ฏ๏ผš @@ -127,44 +125,43 @@ ๆˆ‘ๅฐ†ๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญไธบๆ‚จๆไพ›ๆ›ดๅ…ทไฝ“็š„็คบไพ‹ใ€‚ - -## ้‡ๆ–ฐๅฏๅŠจ +## ้‡ๆ–ฐๅฏๅŠจ { #restarts } ไธŽ็กฎไฟๅบ”็”จ็จ‹ๅบๅœจๅฏๅŠจๆ—ถ่ฟ่กŒ็ฑปไผผ๏ผŒๆ‚จๅฏ่ƒฝ่ฟ˜ๆƒณ็กฎไฟๅฎƒๅœจๆŒ‚ๆމๅŽ**้‡ๆ–ฐๅฏๅŠจ**ใ€‚ -### ๆˆ‘ไปฌไผš็Šฏ้”™่ฏฏ +### ๆˆ‘ไปฌไผš็Šฏ้”™่ฏฏ { #we-make-mistakes } ไฝœไธบไบบ็ฑป๏ผŒๆˆ‘ไปฌๆ€ปๆ˜ฏไผš็Šฏ**้”™่ฏฏ**ใ€‚ ่ฝฏไปถๅ‡ ไนŽ*ๆ€ปๆ˜ฏ*ๅœจไธๅŒ็š„ๅœฐๆ–น้š่—็€**bug**ใ€‚ ๐Ÿ› ไฝœไธบๅผ€ๅ‘ไบบๅ‘˜๏ผŒๅฝ“ๆˆ‘ไปฌๅ‘็Žฐ่ฟ™ไบ›bugๅนถๅฎž็Žฐๆ–ฐๅŠŸ่ƒฝ๏ผˆไนŸๅฏ่ƒฝๆทปๅŠ ๆ–ฐbug๐Ÿ˜…๏ผ‰ๆ—ถ๏ผŒๆˆ‘ไปฌไผšไธๆ–ญๆ”น่ฟ›ไปฃ็ ใ€‚ -### ่‡ชๅŠจๅค„็†ๅฐ้”™่ฏฏ +### ่‡ชๅŠจๅค„็†ๅฐ้”™่ฏฏ { #small-errors-automatically-handled } ไฝฟ็”จ FastAPI ๆž„ๅปบ Web API ๆ—ถ๏ผŒๅฆ‚ๆžœๆˆ‘ไปฌ็š„ไปฃ็ ไธญๅญ˜ๅœจ้”™่ฏฏ๏ผŒFastAPI ้€šๅธธไผšๅฐ†ๅ…ถๅŒ…ๅซๅˆฐ่งฆๅ‘้”™่ฏฏ็š„ๅ•ไธช่ฏทๆฑ‚ไธญใ€‚ ๐Ÿ›ก ๅฏนไบŽ่ฏฅ่ฏทๆฑ‚๏ผŒๅฎขๆˆท็ซฏๅฐ†ๆ”ถๅˆฐ **500 ๅ†…้ƒจๆœๅŠกๅ™จ้”™่ฏฏ**๏ผŒไฝ†ๅบ”็”จ็จ‹ๅบๅฐ†็ปง็ปญๅค„็†ไธ‹ไธ€ไธช่ฏทๆฑ‚๏ผŒ่€Œไธๆ˜ฏๅฎŒๅ…จๅดฉๆบƒใ€‚ -### ๆ›ดๅคง็š„้”™่ฏฏ - ๅดฉๆบƒ +### ๆ›ดๅคง็š„้”™่ฏฏ - ๅดฉๆบƒ { #bigger-errors-crashes } ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆˆ‘ไปฌ็ผ–ๅ†™็š„ไธ€ไบ›ไปฃ็ ๅฏ่ƒฝไผšๅฏผ่‡ดๆ•ดไธชๅบ”็”จ็จ‹ๅบๅดฉๆบƒ๏ผŒไปŽ่€Œๅฏผ่‡ด Uvicorn ๅ’Œ Python ๅดฉๆบƒใ€‚ ๐Ÿ’ฅ ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒๆ‚จๅฏ่ƒฝไธๅธŒๆœ›ๅบ”็”จ็จ‹ๅบๅ› ไธบๆŸไธชๅœฐๆ–นๅ‡บ็Žฐ้”™่ฏฏ่€ŒไฟๆŒๆญปๆœบ็Šถๆ€๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›ๅฎƒ**็ปง็ปญ่ฟ่กŒ**๏ผŒ่‡ณๅฐ‘ๅฏนไบŽๆœช็ ดๅ็š„*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ -### ๅดฉๆบƒๅŽ้‡ๆ–ฐๅฏๅŠจ +### ๅดฉๆบƒๅŽ้‡ๆ–ฐๅฏๅŠจ { #restart-after-crash } ไฝ†ๅœจ้‚ฃไบ›ไธฅ้‡้”™่ฏฏๅฏผ่‡ดๆญฃๅœจ่ฟ่กŒ็š„**่ฟ›็จ‹**ๅดฉๆบƒ็š„ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จ้œ€่ฆไธ€ไธชๅค–้ƒจ็ป„ไปถๆฅ่ดŸ่ดฃ**้‡ๆ–ฐๅฏๅŠจ**่ฟ›็จ‹๏ผŒ่‡ณๅฐ‘ๅฐ่ฏ•ๅ‡ ๆฌก...... -/// tip +/// tip | ๆ็คบ ...ๅฐฝ็ฎกๅฆ‚ๆžœๆ•ดไธชๅบ”็”จ็จ‹ๅบๅชๆ˜ฏ**็ซ‹ๅณๅดฉๆบƒ**๏ผŒ้‚ฃไนˆๆฐธ่ฟœ้‡ๆ–ฐๅฏๅŠจๅฎƒๅฏ่ƒฝๆฒกๆœ‰ๆ„ไน‰ใ€‚ ไฝ†ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฏ่ƒฝไผšๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญๆณจๆ„ๅˆฐๅฎƒ๏ผŒๆˆ–่€…่‡ณๅฐ‘ๅœจ้ƒจ็ฝฒๅŽ็ซ‹ๅณๆณจๆ„ๅˆฐๅฎƒใ€‚ - ๅ› ๆญค๏ผŒ่ฎฉๆˆ‘ไปฌๅ…ณๆณจไธป่ฆๆƒ…ๅ†ต๏ผŒๅœจ**ๆœชๆฅ**็š„ๆŸไบ›็‰นๅฎšๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฏ่ƒฝไผšๅฎŒๅ…จๅดฉๆบƒ๏ผŒไฝ†้‡ๆ–ฐๅฏๅŠจๅฎƒไป็„ถๆœ‰ๆ„ไน‰ใ€‚ +ๅ› ๆญค๏ผŒ่ฎฉๆˆ‘ไปฌๅ…ณๆณจไธป่ฆๆƒ…ๅ†ต๏ผŒๅœจ**ๆœชๆฅ**็š„ๆŸไบ›็‰นๅฎšๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฏ่ƒฝไผšๅฎŒๅ…จๅดฉๆบƒ๏ผŒไฝ†้‡ๆ–ฐๅฏๅŠจๅฎƒไป็„ถๆœ‰ๆ„ไน‰ใ€‚ /// ๆ‚จๅฏ่ƒฝๅธŒๆœ›่ฎฉ่ฟ™ไธชไธœ่ฅฟไฝœไธบ **ๅค–้ƒจ็ป„ไปถ** ่ดŸ่ดฃ้‡ๆ–ฐๅฏๅŠจๆ‚จ็š„ๅบ”็”จ็จ‹ๅบ๏ผŒๅ› ไธบๅˆฐ้‚ฃๆ—ถ๏ผŒไฝฟ็”จ Uvicorn ๅ’Œ Python ็š„ๅŒไธ€ๅบ”็”จ็จ‹ๅบๅทฒ็ปๅดฉๆบƒไบ†๏ผŒๅ› ๆญคๅŒไธ€ๅบ”็”จ็จ‹ๅบ็š„็›ธๅŒไปฃ็ ไธญๆฒกๆœ‰ไธœ่ฅฟๅฏไปฅๅฏนๆญคๅšๅ‡บไป€ไนˆใ€‚ -### ่‡ชๅŠจ้‡ๆ–ฐๅฏๅŠจ็š„็คบไพ‹ๅทฅๅ…ท +### ่‡ชๅŠจ้‡ๆ–ฐๅฏๅŠจ็š„็คบไพ‹ๅทฅๅ…ท { #example-tools-to-restart-automatically } ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒ็”จไบŽ**ๅฏๅŠจๆ—ถ่ฟ่กŒ็จ‹ๅบ**็š„ๅŒไธ€ๅทฅๅ…ทไนŸ็”จไบŽๅค„็†่‡ชๅŠจ**้‡ๆ–ฐๅฏๅŠจ**ใ€‚ @@ -173,25 +170,25 @@ * Docker * Kubernetes * Docker Compose -* Docker in Swarm mode +* Docker in Swarm Mode * Systemd * Supervisor * ไฝœไธบๅ…ถๆœๅŠก็š„ไธ€้ƒจๅˆ†็”ฑไบ‘ๆไพ›ๅ•†ๅ†…้ƒจๅค„็† * ๅ…ถไป–็š„... -## ๅคๅˆถ - ่ฟ›็จ‹ๅ’Œๅ†…ๅญ˜ +## ๅคๅˆถ - ่ฟ›็จ‹ๅ’Œๅ†…ๅญ˜ { #replication-processes-and-memory } -ๅฏนไบŽ FastAPI ๅบ”็”จ็จ‹ๅบ๏ผŒไฝฟ็”จๅƒ Uvicorn ่ฟ™ๆ ท็š„ๆœๅŠกๅ™จ็จ‹ๅบ๏ผŒๅœจ**ไธ€ไธช่ฟ›็จ‹**ไธญ่ฟ่กŒไธ€ๆฌกๅฐฑๅฏไปฅๅŒๆ—ถไธบๅคšไธชๅฎขๆˆท็ซฏๆไพ›ๆœๅŠกใ€‚ +ๅฏนไบŽ FastAPI ๅบ”็”จ็จ‹ๅบ๏ผŒไฝฟ็”จๅƒ `fastapi` ๅ‘ฝไปค๏ผˆ่ฟ่กŒ Uvicorn๏ผ‰่ฟ™ๆ ท็š„ๆœๅŠกๅ™จ็จ‹ๅบ๏ผŒๅœจ**ไธ€ไธช่ฟ›็จ‹**ไธญ่ฟ่กŒไธ€ๆฌกๅฐฑๅฏไปฅๅŒๆ—ถไธบๅคšไธชๅฎขๆˆท็ซฏๆไพ›ๆœๅŠกใ€‚ ไฝ†ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จไผšๅธŒๆœ›ๅŒๆ—ถ่ฟ่กŒๅคšไธชๅทฅไฝœ่ฟ›็จ‹ใ€‚ -### ๅคš่ฟ›็จ‹ - Workers +### ๅคš่ฟ›็จ‹ - Workers { #multiple-processes-workers } -ๅฆ‚ๆžœๆ‚จ็š„ๅฎขๆˆท็ซฏๆ•ฐ้‡ๅคšไบŽๅ•ไธช่ฟ›็จ‹ๅฏไปฅๅค„็†็š„ๆ•ฐ้‡๏ผˆไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ่™šๆ‹Ÿๆœบไธๆ˜ฏๅคชๅคง๏ผ‰๏ผŒๅนถไธ”ๆœๅŠกๅ™จ็š„ CPU ไธญๆœ‰ **ๅคšไธชๆ ธๅฟƒ**๏ผŒ้‚ฃไนˆๆ‚จๅฏไปฅ่ฎฉ **ๅคšไธช่ฟ›็จ‹** ่ฟ่กŒ ๅŒๆ—ถๅค„็†ๅŒไธ€ไธชๅบ”็”จ็จ‹ๅบ๏ผŒๅนถๅœจๅฎƒไปฌไน‹้—ดๅˆ†ๅ‘ๆ‰€ๆœ‰่ฏทๆฑ‚ใ€‚ +ๅฆ‚ๆžœๆ‚จ็š„ๅฎขๆˆท็ซฏๆ•ฐ้‡ๅคšไบŽๅ•ไธช่ฟ›็จ‹ๅฏไปฅๅค„็†็š„ๆ•ฐ้‡๏ผˆไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ่™šๆ‹Ÿๆœบไธๆ˜ฏๅคชๅคง๏ผ‰๏ผŒๅนถไธ”ๆœๅŠกๅ™จ็š„ CPU ไธญๆœ‰ **ๅคšไธชๆ ธๅฟƒ**๏ผŒ้‚ฃไนˆๆ‚จๅฏไปฅ่ฎฉ **ๅคšไธช่ฟ›็จ‹** ๅŒๆ—ถ่ฟ่กŒๅŒไธ€ไธชๅบ”็”จ็จ‹ๅบ๏ผŒๅนถๅœจๅฎƒไปฌไน‹้—ดๅˆ†ๅ‘ๆ‰€ๆœ‰่ฏทๆฑ‚ใ€‚ ๅฝ“ๆ‚จ่ฟ่กŒๅŒไธ€ API ็จ‹ๅบ็š„**ๅคšไธช่ฟ›็จ‹**ๆ—ถ๏ผŒๅฎƒไปฌ้€šๅธธ็งฐไธบ **workers**ใ€‚ -### ๅทฅไฝœ่ฟ›็จ‹ๅ’Œ็ซฏๅฃ +### ๅทฅไฝœ่ฟ›็จ‹ๅ’Œ็ซฏๅฃ { #worker-processes-and-ports } ่ฟ˜่ฎฐๅพ—ๆ–‡ๆกฃ [About HTTPS](https.md){.internal-link target=_blank} ไธญๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ๅฏไปฅไพฆๅฌๆœๅŠกๅ™จไธญ็š„็ซฏๅฃๅ’Œ IP ๅœฐๅ€็š„ไธ€็ง็ป„ๅˆๅ—๏ผŸ @@ -199,20 +196,19 @@ ๅ› ๆญค๏ผŒไธบไบ†่ƒฝๅคŸๅŒๆ—ถๆ‹ฅๆœ‰**ๅคšไธช่ฟ›็จ‹**๏ผŒๅฟ…้กปๆœ‰ไธ€ไธช**ๅ•ไธช่ฟ›็จ‹ไพฆๅฌ็ซฏๅฃ**๏ผŒ็„ถๅŽไปฅๆŸ็งๆ–นๅผๅฐ†้€šไฟกไผ ่พ“ๅˆฐๆฏไธชๅทฅไฝœ่ฟ›็จ‹ใ€‚ -### ๆฏไธช่ฟ›็จ‹็š„ๅ†…ๅญ˜ +### ๆฏไธช่ฟ›็จ‹็š„ๅ†…ๅญ˜ { #memory-per-process } ็Žฐๅœจ๏ผŒๅฝ“็จ‹ๅบๅฐ†ๅ†…ๅฎนๅŠ ่ฝฝๅˆฐๅ†…ๅญ˜ไธญๆ—ถ๏ผŒไพ‹ๅฆ‚๏ผŒๅฐ†ๆœบๅ™จๅญฆไน ๆจกๅž‹ๅŠ ่ฝฝๅˆฐๅ˜้‡ไธญ๏ผŒๆˆ–่€…ๅฐ†ๅคงๆ–‡ไปถ็š„ๅ†…ๅฎนๅŠ ่ฝฝๅˆฐๅ˜้‡ไธญ๏ผŒๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝไผšๆถˆ่€—ๆœๅŠกๅ™จ็š„ไธ€็‚นๅ†…ๅญ˜ (RAM) ใ€‚ ๅคšไธช่ฟ›็จ‹้€šๅธธ**ไธๅ…ฑไบซไปปไฝ•ๅ†…ๅญ˜**ใ€‚ ่ฟ™ๆ„ๅ‘ณ็€ๆฏไธชๆญฃๅœจ่ฟ่กŒ็š„่ฟ›็จ‹้ƒฝๆœ‰่‡ชๅทฑ็š„ไธœ่ฅฟใ€ๅ˜้‡ๅ’Œๅ†…ๅญ˜ใ€‚ ๅฆ‚ๆžœๆ‚จ็š„ไปฃ็ ๆถˆ่€—ไบ†ๅคง้‡ๅ†…ๅญ˜๏ผŒ**ๆฏไธช่ฟ›็จ‹**ๅฐ†ๆถˆ่€—็ญ‰้‡็š„ๅ†…ๅญ˜ใ€‚ -### ๆœๅŠกๅ™จๅ†…ๅญ˜ +### ๆœๅŠกๅ™จๅ†…ๅญ˜ { #server-memory } ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๆ‚จ็š„ไปฃ็ ๅŠ ่ฝฝ **1 GB ๅคงๅฐ**็š„ๆœบๅ™จๅญฆไน ๆจกๅž‹๏ผŒๅˆ™ๅฝ“ๆ‚จไฝฟ็”จ API ่ฟ่กŒไธ€ไธช่ฟ›็จ‹ๆ—ถ๏ผŒๅฎƒๅฐ†่‡ณๅฐ‘ๆถˆ่€— 1 GB RAMใ€‚ ๅฆ‚ๆžœๆ‚จๅฏๅŠจ **4 ไธช่ฟ›็จ‹**๏ผˆ4 ไธชๅทฅไฝœ่ฟ›็จ‹๏ผ‰๏ผŒๆฏไธช่ฟ›็จ‹ๅฐ†ๆถˆ่€— 1 GB RAMใ€‚ ๅ› ๆญค๏ผŒๆ‚จ็š„ API ๆ€ปๅ…ฑๅฐ†ๆถˆ่€— **4 GB RAM**ใ€‚ ๅฆ‚ๆžœๆ‚จ็š„่ฟœ็จ‹ๆœๅŠกๅ™จๆˆ–่™šๆ‹Ÿๆœบๅชๆœ‰ 3 GB RAM๏ผŒๅฐ่ฏ•ๅŠ ่ฝฝ่ถ…่ฟ‡ 4 GB RAM ๅฐ†ๅฏผ่‡ด้—ฎ้ข˜ใ€‚ ๐Ÿšจ - -### ๅคš่ฟ›็จ‹ - ไธ€ไธชไพ‹ๅญ +### ๅคš่ฟ›็จ‹ - ไธ€ไธชไพ‹ๅญ { #multiple-processes-an-example } ๅœจๆญค็คบไพ‹ไธญ๏ผŒๆœ‰ไธ€ไธช **Manager Process** ๅฏๅŠจๅนถๆŽงๅˆถไธคไธช **Worker Processes**ใ€‚ @@ -224,11 +220,11 @@ ๅฝ“็„ถ๏ผŒ้™คไบ†ๆ‚จ็š„ๅบ”็”จ็จ‹ๅบไน‹ๅค–๏ผŒๅŒไธ€ๅฐๆœบๅ™จๅฏ่ƒฝ่ฟ˜่ฟ่กŒ**ๅ…ถไป–่ฟ›็จ‹**ใ€‚ -ไธ€ไธชๆœ‰่ถฃ็š„็ป†่Š‚ๆ˜ฏ๏ผŒ้š็€ๆ—ถ้—ด็š„ๆŽจ็งป๏ผŒๆฏไธช่ฟ›็จ‹ไฝฟ็”จ็š„ **CPU ็™พๅˆ†ๆฏ”ๅฏ่ƒฝไผšๅ‘็”Ÿๅพˆๅคงๅ˜ๅŒ–๏ผŒไฝ†ๅ†…ๅญ˜ (RAM) ้€šๅธธไผšๆˆ–ๅคšๆˆ–ๅฐ‘ไฟๆŒ็จณๅฎš**ใ€‚ +ไธ€ไธชๆœ‰่ถฃ็š„็ป†่Š‚ๆ˜ฏ๏ผŒ้š็€ๆ—ถ้—ด็š„ๆŽจ็งป๏ผŒๆฏไธช่ฟ›็จ‹ไฝฟ็”จ็š„ **CPU ็™พๅˆ†ๆฏ”**ๅฏ่ƒฝไผšๅ‘็”Ÿๅพˆๅคงๅ˜ๅŒ–๏ผŒไฝ†**ๅ†…ๅญ˜ (RAM)** ้€šๅธธไผšๆˆ–ๅคšๆˆ–ๅฐ‘ไฟๆŒ**็จณๅฎš**ใ€‚ ๅฆ‚ๆžœๆ‚จๆœ‰ไธ€ไธชๆฏๆฌกๆ‰ง่กŒ็›ธๅฝ“ๆ•ฐ้‡็š„่ฎก็ฎ—็š„ API๏ผŒๅนถไธ”ๆ‚จๆœ‰ๅพˆๅคšๅฎขๆˆท็ซฏ๏ผŒ้‚ฃไนˆ **CPU ๅˆฉ็”จ็އ** ๅฏ่ƒฝไนŸไผšไฟๆŒ็จณๅฎš๏ผˆ่€Œไธๆ˜ฏไธๆ–ญๅฟซ้€ŸไธŠๅ‡ๅ’Œไธ‹้™๏ผ‰ใ€‚ -### ๅคๅˆถๅทฅๅ…ทๅ’Œ็ญ–็•ฅ็คบไพ‹ +### ๅคๅˆถๅทฅๅ…ทๅ’Œ็ญ–็•ฅ็คบไพ‹ { #examples-of-replication-tools-and-strategies } ๅฏไปฅ้€š่ฟ‡ๅคš็งๆ–นๆณ•ๆฅๅฎž็Žฐ่ฟ™ไธ€็›ฎๆ ‡๏ผŒๆˆ‘ๅฐ†ๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญๅ‘ๆ‚จ่ฏฆ็ป†ไป‹็ปๅ…ทไฝ“็ญ–็•ฅ๏ผŒไพ‹ๅฆ‚ๅœจ่ฐˆ่ฎบ Docker ๅ’Œๅฎนๅ™จๆ—ถใ€‚ @@ -236,26 +232,22 @@ ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅฏ่ƒฝ็š„็ป„ๅˆๅ’Œ็ญ–็•ฅ๏ผš -* **Gunicorn** ็ฎก็† **Uvicorn workers** - * Gunicorn ๅฐ†ๆ˜ฏ็›‘ๅฌ **IP** ๅ’Œ **็ซฏๅฃ** ็š„ **่ฟ›็จ‹็ฎก็†ๅ™จ**๏ผŒๅคๅˆถๅฐ†้€š่ฟ‡ **ๅคšไธช Uvicorn ๅทฅไฝœ่ฟ›็จ‹** ่ฟ›่กŒ -* **Uvicorn** ็ฎก็† **Uvicorn workers** - * ไธ€ไธช Uvicorn **่ฟ›็จ‹็ฎก็†ๅ™จ** ๅฐ†็›‘ๅฌ **IP** ๅ’Œ **็ซฏๅฃ**๏ผŒๅนถไธ”ๅฎƒๅฐ†ๅฏๅŠจ **ๅคšไธช Uvicorn ๅทฅไฝœ่ฟ›็จ‹** +* ๅธฆๆœ‰ `--workers` ็š„ **Uvicorn** + * ไธ€ไธช Uvicorn **่ฟ›็จ‹็ฎก็†ๅ™จ** ๅฐ†็›‘ๅฌ **IP** ๅ’Œ **็ซฏๅฃ**๏ผŒๅนถไธ”ๅฎƒๅฐ†ๅฏๅŠจ **ๅคšไธช Uvicorn ๅทฅไฝœ่ฟ›็จ‹**ใ€‚ * **Kubernetes** ๅ’Œๅ…ถไป–ๅˆ†ๅธƒๅผ **ๅฎนๅ™จ็ณป็ปŸ** - * **Kubernetes** ๅฑ‚ไธญ็š„ๆŸไบ›ไธœ่ฅฟๅฐ†ไพฆๅฌ **IP** ๅ’Œ **็ซฏๅฃ**ใ€‚ ๅคๅˆถๅฐ†้€š่ฟ‡ๆ‹ฅๆœ‰**ๅคšไธชๅฎนๅ™จ**๏ผŒๆฏไธชๅฎนๅ™จ่ฟ่กŒ**ไธ€ไธช Uvicorn ่ฟ›็จ‹** + * **Kubernetes** ๅฑ‚ไธญ็š„ๆŸไบ›ไธœ่ฅฟๅฐ†ไพฆๅฌ **IP** ๅ’Œ **็ซฏๅฃ**ใ€‚ ๅคๅˆถๅฐ†้€š่ฟ‡ๆ‹ฅๆœ‰**ๅคšไธชๅฎนๅ™จ**๏ผŒๆฏไธชๅฎนๅ™จ่ฟ่กŒ**ไธ€ไธช Uvicorn ่ฟ›็จ‹**ใ€‚ * **ไบ‘ๆœๅŠก** ไธบๆ‚จๅค„็†ๆญค้—ฎ้ข˜ - * ไบ‘ๆœๅŠกๅฏ่ƒฝ**ไธบๆ‚จๅค„็†ๅคๅˆถ**ใ€‚ ๅฎƒๅฏ่ƒฝไผš่ฎฉๆ‚จๅฎšไน‰ **่ฆ่ฟ่กŒ็š„่ฟ›็จ‹**๏ผŒๆˆ–่ฆไฝฟ็”จ็š„ **ๅฎนๅ™จๆ˜ ๅƒ**๏ผŒๅœจไปปไฝ•ๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅพˆๅฏ่ƒฝๆ˜ฏ **ๅ•ไธช Uvicorn ่ฟ›็จ‹**๏ผŒๅนถไธ”ไบ‘ๆœๅŠกๅฐ†่ดŸ่ดฃๅคๅˆถๅฎƒใ€‚ - + * ไบ‘ๆœๅŠกๅฏ่ƒฝ**ไธบๆ‚จๅค„็†ๅคๅˆถ**ใ€‚ ๅฎƒๅฏ่ƒฝไผš่ฎฉๆ‚จๅฎšไน‰ **่ฆ่ฟ่กŒ็š„่ฟ›็จ‹**๏ผŒๆˆ–่ฆไฝฟ็”จ็š„ **ๅฎนๅ™จๆ˜ ๅƒ**๏ผŒๅœจไปปไฝ•ๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅพˆๅฏ่ƒฝๆ˜ฏ **ๅ•ไธช Uvicorn ่ฟ›็จ‹**๏ผŒๅนถไธ”ไบ‘ๆœๅŠกๅฐ†่ดŸ่ดฃๅคๅˆถๅฎƒใ€‚ - -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœ่ฟ™ไบ›ๅ…ณไบŽ **ๅฎนๅ™จ**ใ€Docker ๆˆ– Kubernetes ็š„ๅ†…ๅฎน่ฟ˜ๆฒกๆœ‰ๅคšๅคงๆ„ไน‰๏ผŒ่ฏทไธ่ฆๆ‹…ๅฟƒใ€‚ - ๆˆ‘ๅฐ†ๅœจไปฅๅŽ็š„็ซ ่Š‚ไธญๅ‘ๆ‚จ่ฏฆ็ป†ไป‹็ปๅฎนๅ™จ้•œๅƒใ€Dockerใ€Kubernetes ็ญ‰๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ +ๆˆ‘ๅฐ†ๅœจไปฅๅŽ็š„็ซ ่Š‚ไธญๅ‘ๆ‚จ่ฏฆ็ป†ไป‹็ปๅฎนๅ™จ้•œๅƒใ€Dockerใ€Kubernetes ็ญ‰๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ /// -## ๅฏๅŠจไน‹ๅ‰็š„ๆญฅ้ชค +## ๅฏๅŠจไน‹ๅ‰็š„ๆญฅ้ชค { #previous-steps-before-starting } ๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅธŒๆœ›ๅœจ**ๅฏๅŠจ**ๅบ”็”จ็จ‹ๅบไน‹ๅ‰ๆ‰ง่กŒไธ€ไบ›ๆญฅ้ชคใ€‚ @@ -269,15 +261,15 @@ ๅฝ“็„ถ๏ผŒไนŸๆœ‰ไธ€ไบ›ๆƒ…ๅ†ต๏ผŒๅคšๆฌก่ฟ่กŒๅ‰้ข็š„ๆญฅ้ชคไนŸๆฒกๆœ‰้—ฎ้ข˜๏ผŒ่ฟ™ๆ ท็š„่ฏๅฐฑๅฅฝๅŠžๅคšไบ†ใ€‚ -/// tip +/// tip | ๆ็คบ ๅฆๅค–๏ผŒ่ฏท่ฎฐไฝ๏ผŒๆ นๆฎๆ‚จ็š„่ฎพ็ฝฎ๏ผŒๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅœจๅผ€ๅง‹ๅบ”็”จ็จ‹ๅบไน‹ๅ‰**ๅฏ่ƒฝ็”š่‡ณไธ้œ€่ฆไปปไฝ•ๅ…ˆๅ‰็š„ๆญฅ้ชค**ใ€‚ - ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฐฑไธๅฟ…ๆ‹…ๅฟƒ่ฟ™ไบ›ใ€‚ ๐Ÿคท +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฐฑไธๅฟ…ๆ‹…ๅฟƒ่ฟ™ไบ›ใ€‚ ๐Ÿคท /// -### ๅ‰้ขๆญฅ้ชค็ญ–็•ฅ็š„็คบไพ‹ +### ๅ‰้ขๆญฅ้ชค็ญ–็•ฅ็š„็คบไพ‹ { #examples-of-previous-steps-strategies } ่ฟ™ๅฐ†ๅœจ**ๅพˆๅคง็จ‹ๅบฆไธŠๅ–ๅ†ณไบŽๆ‚จ้ƒจ็ฝฒ็ณป็ปŸ็š„ๆ–นๅผ**๏ผŒๅนถไธ”ๅฏ่ƒฝไธŽๆ‚จๅฏๅŠจ็จ‹ๅบใ€ๅค„็†้‡ๅฏ็ญ‰็š„ๆ–นๅผๆœ‰ๅ…ณใ€‚ @@ -285,15 +277,15 @@ * Kubernetes ไธญ็š„โ€œInit Containerโ€ๅœจๅบ”็”จ็จ‹ๅบๅฎนๅ™จไน‹ๅ‰่ฟ่กŒ * ไธ€ไธช bash ่„šๆœฌ๏ผŒ่ฟ่กŒๅ‰้ข็š„ๆญฅ้ชค๏ผŒ็„ถๅŽๅฏๅŠจๆ‚จ็š„ๅบ”็”จ็จ‹ๅบ - * ๆ‚จไป็„ถ้œ€่ฆไธ€็งๆ–นๆณ•ๆฅๅฏๅŠจ/้‡ๆ–ฐๅฏๅŠจ bash ่„šๆœฌใ€ๆฃ€ๆต‹้”™่ฏฏ็ญ‰ใ€‚ + * ๆ‚จไป็„ถ้œ€่ฆไธ€็งๆ–นๆณ•ๆฅๅฏๅŠจ/้‡ๆ–ฐๅฏๅŠจ bash ่„šๆœฌใ€ๆฃ€ๆต‹้”™่ฏฏ็ญ‰ใ€‚ -/// tip +/// tip | ๆ็คบ ๆˆ‘ๅฐ†ๅœจไปฅๅŽ็š„็ซ ่Š‚ไธญไธบๆ‚จๆไพ›ไฝฟ็”จๅฎนๅ™จๆ‰ง่กŒๆญคๆ“ไฝœ็š„ๆ›ดๅ…ทไฝ“็คบไพ‹๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ /// -## ่ต„ๆบๅˆฉ็”จ็އ +## ่ต„ๆบๅˆฉ็”จ็އ { #resource-utilization } ๆ‚จ็š„ๆœๅŠกๅ™จๆ˜ฏไธ€ไธช**่ต„ๆบ**๏ผŒๆ‚จๅฏไปฅ้€š่ฟ‡ๆ‚จ็š„็จ‹ๅบๆถˆ่€—ๆˆ–**ๅˆฉ็”จ**CPU ไธŠ็š„่ฎก็ฎ—ๆ—ถ้—ดไปฅๅŠๅฏ็”จ็š„ RAM ๅ†…ๅญ˜ใ€‚ @@ -313,8 +305,7 @@ ๆ‚จๅฏไปฅไฝฟ็”จโ€œhtopโ€็ญ‰็ฎ€ๅ•ๅทฅๅ…ทๆฅๆŸฅ็œ‹ๆœๅŠกๅ™จไธญไฝฟ็”จ็š„ CPU ๅ’Œ RAM ๆˆ–ๆฏไธช่ฟ›็จ‹ไฝฟ็”จ็š„ๆ•ฐ้‡ใ€‚ ๆˆ–่€…ๆ‚จๅฏไปฅไฝฟ็”จๆ›ดๅคๆ‚็š„็›‘ๆŽงๅทฅๅ…ท๏ผŒ่ฟ™ไบ›ๅทฅๅ…ทๅฏ่ƒฝๅˆ†ๅธƒๅœจๆœๅŠกๅ™จ็ญ‰ไธŠใ€‚ - -## ๅ›ž้กพ +## ๅ›ž้กพ { #recap } ๆ‚จๅœจ่ฟ™้‡Œ้˜…่ฏปไบ†ไธ€ไบ›ๅœจๅ†ณๅฎšๅฆ‚ไฝ•้ƒจ็ฝฒๅบ”็”จ็จ‹ๅบๆ—ถๅฏ่ƒฝ้œ€่ฆ็‰ข่ฎฐ็š„ไธป่ฆๆฆ‚ๅฟต๏ผš diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md index f120ebfb89..3d0c19903b 100644 --- a/docs/zh/docs/deployment/docker.md +++ b/docs/zh/docs/deployment/docker.md @@ -1,17 +1,17 @@ -# ๅฎนๅ™จไธญ็š„ FastAPI - Docker +# ๅฎนๅ™จไธญ็š„ FastAPI - Docker { #fastapi-in-containers-docker } -้ƒจ็ฝฒ FastAPI ๅบ”็”จ็จ‹ๅบๆ—ถ๏ผŒๅธธ่ง็š„ๆ–นๆณ•ๆ˜ฏๆž„ๅปบ **Linux ๅฎนๅ™จ้•œๅƒ**ใ€‚ ้€šๅธธไฝฟ็”จ **Docker** ๅฎŒๆˆใ€‚ ็„ถๅŽ๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ๅ‡ ็งๅฏ่ƒฝ็š„ๆ–นๅผไน‹ไธ€้ƒจ็ฝฒ่ฏฅๅฎนๅ™จ้•œๅƒใ€‚ +้ƒจ็ฝฒ FastAPI ๅบ”็”จๆ—ถ๏ผŒๅธธ่งๅšๆณ•ๆ˜ฏๆž„ๅปบไธ€ไธช**Linux ๅฎนๅ™จ้•œๅƒ**ใ€‚้€šๅธธไฝฟ็”จ **Docker** ๅฎž็Žฐใ€‚็„ถๅŽไฝ ๅฏไปฅ็”จๅ‡ ็งๆ–นๅผไน‹ไธ€้ƒจ็ฝฒ่ฏฅ้•œๅƒใ€‚ -ไฝฟ็”จ Linux ๅฎนๅ™จๆœ‰ๅ‡ ไธชไผ˜็‚น๏ผŒๅŒ…ๆ‹ฌ**ๅฎ‰ๅ…จๆ€ง**ใ€**ๅฏๅคๅˆถๆ€ง**ใ€**็ฎ€ๅ•ๆ€ง**็ญ‰ใ€‚ +ไฝฟ็”จ Linux ๅฎนๅ™จๆœ‰ๅคš็งไผ˜ๅŠฟ๏ผŒๅŒ…ๆ‹ฌ**ๅฎ‰ๅ…จๆ€ง**ใ€**ๅฏๅคๅˆถๆ€ง**ใ€**็ฎ€ๅ•ๆ€ง**็ญ‰ใ€‚ -/// tip +/// tip | ๆ็คบ -่ตถๆ—ถ้—ดๅนถไธ”ๅทฒ็ป็Ÿฅ้“่ฟ™ไบ›ไธœ่ฅฟไบ†๏ผŸ ่ทณ่ฝฌๅˆฐไธ‹้ข็š„ [`Dockerfile` ๐Ÿ‘‡](#fastapi-docker_1)ใ€‚ +่ตถๆ—ถ้—ดๅนถไธ”ๅทฒ็ปไบ†่งฃ่ฟ™ไบ›๏ผŸ็›ดๆŽฅ่ทณๅˆฐไธ‹้ข็š„ [`Dockerfile` ๐Ÿ‘‡](#build-a-docker-image-for-fastapi)ใ€‚ ///
-Dockerfile Preview ๐Ÿ‘€ +Dockerfile ้ข„่งˆ ๐Ÿ‘€ ```Dockerfile FROM python:3.9 @@ -24,140 +24,127 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./app /code/app -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--port", "80"] # If running behind a proxy like Nginx or Traefik add --proxy-headers -# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"] +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ```
-## ไป€ไนˆๆ˜ฏๅฎนๅ™จ +## ไป€ไนˆๆ˜ฏๅฎนๅ™จ { #what-is-a-container } -ๅฎนๅ™จ๏ผˆไธป่ฆๆ˜ฏ Linux ๅฎนๅ™จ๏ผ‰ๆ˜ฏไธ€็ง้žๅธธ**่ฝป้‡็บง**็š„ๆ‰“ๅŒ…ๅบ”็”จ็จ‹ๅบ็š„ๆ–นๅผ๏ผŒๅ…ถๅŒ…ๆ‹ฌๆ‰€ๆœ‰ไพ่ต–้กนๅ’Œๅฟ…่ฆ็š„ๆ–‡ไปถ๏ผŒๅŒๆ—ถๅฎƒไปฌๅฏไปฅๅ’ŒๅŒไธ€็ณป็ปŸไธญ็š„ๅ…ถไป–ๅฎนๅ™จ๏ผˆๆˆ–่€…ๅ…ถไป–ๅบ”็”จ็จ‹ๅบ/็ป„ไปถ๏ผ‰็›ธไบ’้š”็ฆปใ€‚ +ๅฎนๅ™จ๏ผˆไธป่ฆๆ˜ฏ Linux ๅฎนๅ™จ๏ผ‰ๆ˜ฏไธ€็ง้žๅธธ**่ฝป้‡**็š„ๆ–นๅผ๏ผŒ็”จๆฅๆ‰“ๅŒ…ๅบ”็”จๅŠๅ…ถๆ‰€ๆœ‰ไพ่ต–ๅ’Œๅฟ…่ฆๆ–‡ไปถ๏ผŒๅนถ่ฎฉๅฎƒไปฌไธŽๅŒไธ€็ณป็ปŸไธญ็š„ๅ…ถไป–ๅฎนๅ™จ๏ผˆๅ…ถไป–ๅบ”็”จๆˆ–็ป„ไปถ๏ผ‰็›ธไบ’้š”็ฆปใ€‚ -Linux ๅฎนๅ™จไฝฟ็”จๅฎฟไธปๆœบ๏ผˆๅฆ‚็‰ฉ็†ๆœๅŠกๅ™จใ€่™šๆ‹Ÿๆœบใ€ไบ‘ๆœๅŠกๅ™จ็ญ‰๏ผ‰็š„Linux ๅ†…ๆ ธ่ฟ่กŒใ€‚ ่ฟ™ๆ„ๅ‘ณ็€ๅฎƒไปฌ้žๅธธ่ฝป้‡๏ผˆไธŽๆจกๆ‹Ÿๆ•ดไธชๆ“ไฝœ็ณป็ปŸ็š„ๅฎŒๆ•ด่™šๆ‹Ÿๆœบ็›ธๆฏ”๏ผ‰ใ€‚ +Linux ๅฎนๅ™จๅค็”จๅฎฟไธปๆœบ๏ผˆ็‰ฉ็†ๆœบใ€่™šๆ‹Ÿๆœบใ€ไบ‘ๆœๅŠกๅ™จ็ญ‰๏ผ‰็š„ๅŒไธ€ไธช Linux ๅ†…ๆ ธใ€‚่ฟ™ๆ„ๅ‘ณ็€ๅฎƒไปฌ้žๅธธ่ฝป้‡๏ผˆ็›ธ่พƒไบŽๆจกๆ‹Ÿๆ•ดไธชๆ“ไฝœ็ณป็ปŸ็š„ๅฎŒๆ•ด่™šๆ‹Ÿๆœบ๏ผ‰ใ€‚ -้€š่ฟ‡่ฟ™ๆ ท็š„ๆ–นๅผ๏ผŒๅฎนๅ™จๆถˆ่€—**ๅพˆๅฐ‘็š„่ต„ๆบ**๏ผŒไธŽ็›ดๆŽฅ่ฟ่กŒ่ฟ›็จ‹็›ธๅฝ“๏ผˆ่™šๆ‹Ÿๆœบไผšๆถˆ่€—ๆ›ดๅคš๏ผ‰ใ€‚ +ๅ› ๆญค๏ผŒๅฎนๅ™จๆถˆ่€—็š„**่ต„ๆบๅพˆๅฐ‘**๏ผŒๅคง่‡ด็›ธๅฝ“ไบŽ็›ดๆŽฅ่ฟ่กŒ่ฟ›็จ‹๏ผˆ่€Œ่™šๆ‹Ÿๆœบไผšๅคšๅพˆๅคš๏ผ‰ใ€‚ -ๅฎนๅ™จ็š„่ฟ›็จ‹๏ผˆ้€šๅธธๅชๆœ‰ไธ€ไธช๏ผ‰ใ€ๆ–‡ไปถ็ณป็ปŸๅ’Œ็ฝ‘็ปœ้ƒฝ่ฟ่กŒๅœจ้š”็ฆป็š„็Žฏๅขƒ๏ผŒ่ฟ™็ฎ€ๅŒ–ไบ†้ƒจ็ฝฒใ€ๅฎ‰ๅ…จใ€ๅผ€ๅ‘็ญ‰ใ€‚ +ๅฎนๅ™จ่ฟ˜ๆ‹ฅๆœ‰ๅ„่‡ช**้š”็ฆป**็š„่ฟ่กŒ่ฟ›็จ‹๏ผˆ้€šๅธธๅชๆœ‰ไธ€ไธช๏ผ‰ใ€ๆ–‡ไปถ็ณป็ปŸๅ’Œ็ฝ‘็ปœ๏ผŒ็ฎ€ๅŒ–ไบ†้ƒจ็ฝฒใ€ๅฎ‰ๅ…จใ€ๅผ€ๅ‘็ญ‰ใ€‚ -## ไป€ไนˆๆ˜ฏๅฎนๅ™จ้•œๅƒ +## ไป€ไนˆๆ˜ฏๅฎนๅ™จ้•œๅƒ { #what-is-a-container-image } **ๅฎนๅ™จ**ๆ˜ฏไปŽ**ๅฎนๅ™จ้•œๅƒ**่ฟ่กŒ็š„ใ€‚ -ๅฎนๅ™จ้•œๅƒๆ˜ฏๅฎนๅ™จไธญๆ–‡ไปถใ€็Žฏๅขƒๅ˜้‡ๅ’Œ้ป˜่ฎคๅ‘ฝไปค/็จ‹ๅบ็š„**้™ๆ€**็‰ˆๆœฌใ€‚ **้™ๆ€**่ฟ™้‡Œ็š„ๆ„ๆ€ๆ˜ฏๅฎนๅ™จ**้•œๅƒ**่ฟ˜ๆฒกๆœ‰่ฟ่กŒ๏ผŒๅชๆ˜ฏๆ‰“ๅŒ…็š„ๆ–‡ไปถๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ +ๅฎนๅ™จ้•œๅƒๆ˜ฏๅฎนๅ™จไธญๆ‰€ๆœ‰ๆ–‡ไปถใ€็Žฏๅขƒๅ˜้‡ไปฅๅŠๅบ”่ฏฅ่ฟ่กŒ็š„้ป˜่ฎคๅ‘ฝไปค/็จ‹ๅบ็š„ไธ€ไธช**้™ๆ€**็‰ˆๆœฌใ€‚่ฟ™้‡Œ็š„**้™ๆ€**ๆŒ‡ๅฎนๅ™จ**้•œๅƒ**ๆœฌ่บซๅนถไธๅœจ่ฟ่กŒ๏ผŒไป…ไป…ๆ˜ฏ่ขซๆ‰“ๅŒ…็š„ๆ–‡ไปถๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ -ไธŽๅญ˜ๅ‚จ้™ๆ€ๅ†…ๅฎน็š„โ€œ**ๅฎนๅ™จ้•œๅƒ**โ€็›ธๅ๏ผŒโ€œ**ๅฎนๅ™จ**โ€้€šๅธธๆŒ‡ๆญฃๅœจ่ฟ่กŒ็š„ๅฎžไพ‹๏ผŒๅณๆญฃๅœจ**ๆ‰ง่กŒ็š„**ใ€‚ +ไธŽๅญ˜ๆ”พ้™ๆ€ๅ†…ๅฎน็š„โ€œ**ๅฎนๅ™จ้•œๅƒ**โ€็›ธๅฏน๏ผŒโ€œ**ๅฎนๅ™จ**โ€้€šๅธธๆŒ‡ไธ€ไธชๆญฃๅœจ่ฟ่กŒ็š„ๅฎžไพ‹๏ผŒๅณๆญฃๅœจ่ขซ**ๆ‰ง่กŒ**็š„ไธœ่ฅฟใ€‚ -ๅฝ“**ๅฎนๅ™จ**ๅฏๅŠจๅนถ่ฟ่กŒๆ—ถ๏ผˆไปŽ**ๅฎนๅ™จ้•œๅƒ**ๅฏๅŠจ๏ผ‰๏ผŒๅฎƒๅฏไปฅๅˆ›ๅปบๆˆ–ๆ›ดๆ”นๆ–‡ไปถใ€็Žฏๅขƒๅ˜้‡็ญ‰ใ€‚่ฟ™ไบ›ๆ›ดๆ”นๅฐ†ไป…ๅญ˜ๅœจไบŽ่ฏฅๅฎนๅ™จไธญ๏ผŒ่€ŒไธไผšๆŒไน…ๅŒ–ๅˆฐๅบ•ๅฑ‚็š„ๅฎนๅ™จ้•œๅƒไธญ๏ผˆไธไผšไฟๅญ˜ๅˆฐ็ฃ็›˜๏ผ‰ใ€‚ +ๅฝ“**ๅฎนๅ™จ**ๅฏๅŠจๅนถ่ฟ่กŒ๏ผˆไปŽ**ๅฎนๅ™จ้•œๅƒ**ๅฏๅŠจ๏ผ‰ๅŽ๏ผŒๅฎƒๅฏไปฅๅˆ›ๅปบๆˆ–ไฟฎๆ”นๆ–‡ไปถใ€็Žฏๅขƒๅ˜้‡็ญ‰ใ€‚่ฟ™ไบ›ๆ›ดๆ”นๅชๅญ˜ๅœจไบŽ่ฏฅๅฎนๅ™จไธญ๏ผŒไธไผšๆŒไน…ๅŒ–ๅˆฐๅบ•ๅฑ‚็š„ๅฎนๅ™จ้•œๅƒไธญ๏ผˆไธไผšๅ†™ๅ›ž็ฃ็›˜๏ผ‰ใ€‚ -ๅฎนๅ™จ้•œๅƒ็›ธๅฝ“ไบŽ**็จ‹ๅบ**ๅ’Œๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚ `python`ๅ‘ฝไปค ๅ’ŒๆŸไบ›ๆ–‡ไปถ ๅฆ‚`main.py`ใ€‚ +ๅฎนๅ™จ้•œๅƒๅฏ็ฑปๆฏ”ไธบ**็จ‹ๅบ**ๆ–‡ไปถๅŠๅ…ถๅ†…ๅฎน๏ผŒไพ‹ๅฆ‚ `python` ๅ’ŒๆŸไธชๆ–‡ไปถ `main.py`ใ€‚ -่€Œ**ๅฎนๅ™จ**ๆœฌ่บซ๏ผˆไธŽ**ๅฎนๅ™จ้•œๅƒ**็›ธๅ๏ผ‰ๆ˜ฏ้•œๅƒ็š„ๅฎž้™…่ฟ่กŒๅฎžไพ‹๏ผŒ็›ธๅฝ“ไบŽ**่ฟ›็จ‹**ใ€‚ ไบ‹ๅฎžไธŠ๏ผŒๅฎนๅ™จไป…ๅœจๆœ‰**่ฟ›็จ‹่ฟ่กŒ**ๆ—ถๆ‰่ฟ่กŒ๏ผˆ้€šๅธธๅฎƒๅชๆ˜ฏไธ€ไธชๅ•็‹ฌ็š„่ฟ›็จ‹๏ผ‰ใ€‚ ๅฝ“ๅฎนๅ™จไธญๆฒกๆœ‰่ฟ›็จ‹่ฟ่กŒๆ—ถ๏ผŒๅฎนๅ™จๅฐฑไผšๅœๆญขใ€‚ +่€Œ**ๅฎนๅ™จ**ๆœฌ่บซ๏ผˆ็›ธๅฏน**ๅฎนๅ™จ้•œๅƒ**๏ผ‰ๅฐฑๆ˜ฏ่ฏฅ้•œๅƒ็š„ๅฎž้™…่ฟ่กŒๅฎžไพ‹๏ผŒๅฏ็ฑปๆฏ”ไธบ**่ฟ›็จ‹**ใ€‚ไบ‹ๅฎžไธŠ๏ผŒๅฎนๅ™จๅชๆœ‰ๅœจๆœ‰**่ฟ›็จ‹ๅœจ่ฟ่กŒ**ๆ—ถๆ‰ๅค„ไบŽ่ฟ่กŒ็Šถๆ€๏ผˆ้€šๅธธๅชๆœ‰ไธ€ไธช่ฟ›็จ‹๏ผ‰ใ€‚ๅฝ“ๅฎนๅ™จไธญๆฒกๆœ‰ไปปไฝ•่ฟ›็จ‹ๅœจ่ฟ่กŒๆ—ถ๏ผŒๅฎนๅ™จๅฐฑไผšๅœๆญขใ€‚ +## ๅฎนๅ™จ้•œๅƒ { #container-images } +Docker ไธ€็›ดๆ˜ฏๅˆ›ๅปบๅ’Œ็ฎก็†**ๅฎนๅ™จ้•œๅƒ**ไธŽ**ๅฎนๅ™จ**็š„ไธป่ฆๅทฅๅ…ทไน‹ไธ€ใ€‚ -## ๅฎนๅ™จ้•œๅƒ +่ฟ˜ๆœ‰ไธ€ไธชๅ…ฌๅ…ฑ็š„ Docker Hub๏ผŒๅ…ถไธญไธบ่ฎธๅคšๅทฅๅ…ทใ€็Žฏๅขƒใ€ๆ•ฐๆฎๅบ“ๅ’Œๅบ”็”จๆไพ›ไบ†้ข„ๅˆถ็š„**ๅฎ˜ๆ–นๅฎนๅ™จ้•œๅƒ**ใ€‚ -Docker ไธ€็›ดๆ˜ฏๅˆ›ๅปบๅ’Œ็ฎก็†**ๅฎนๅ™จ้•œๅƒ**ๅ’Œ**ๅฎนๅ™จ**็š„ไธป่ฆๅทฅๅ…ทไน‹ไธ€ใ€‚ - -่ฟ˜ๆœ‰ไธ€ไธชๅ…ฌๅ…ฑ Docker Hub ๏ผŒๅ…ถไธญๅŒ…ๅซ้ข„ๅˆถ็š„ **ๅฎ˜ๆ–นๅฎนๅ™จ้•œๅƒ**, ้€‚็”จไบŽ่ฎธๅคšๅทฅๅ…ทใ€็Žฏๅขƒใ€ๆ•ฐๆฎๅบ“ๅ’Œๅบ”็”จ็จ‹ๅบใ€‚ - -ไพ‹ๅฆ‚๏ผŒๆœ‰ไธ€ไธชๅฎ˜ๆ–น็š„ Python ้•œๅƒใ€‚ - -่ฟ˜ๆœ‰่ฎธๅคšๅ…ถไป–้•œๅƒ็”จไบŽไธๅŒ็š„้œ€่ฆ๏ผˆไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš +ไพ‹ๅฆ‚๏ผŒๆœ‰ๅฎ˜ๆ–น็š„ Python ้•œๅƒใ€‚ +่ฟ˜ๆœ‰่ฎธๅคš็”จไบŽไธๅŒ็›ฎ็š„๏ผˆๅฆ‚ๆ•ฐๆฎๅบ“๏ผ‰็š„้•œๅƒ๏ผŒไพ‹ๅฆ‚๏ผš * PostgreSQL * MySQL * MongoDB -* Redis, etc. +* Redis ็ญ‰ใ€‚ +้€š่ฟ‡ไฝฟ็”จ้ข„ๅˆถ็š„ๅฎนๅ™จ้•œๅƒ๏ผŒๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐ**็ป„ๅˆ**ๅนถไฝฟ็”จไธๅŒๅทฅๅ…ทใ€‚ไพ‹ๅฆ‚๏ผŒ่ฏ•็”จไธ€ไธชๆ–ฐ็š„ๆ•ฐๆฎๅบ“ใ€‚ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ**ๅฎ˜ๆ–น้•œๅƒ**๏ผŒๅช้œ€้€š่ฟ‡็Žฏๅขƒๅ˜้‡้…็ฝฎๅณๅฏใ€‚ -้€š่ฟ‡ไฝฟ็”จ้ข„ๅˆถ็š„ๅฎนๅ™จ้•œๅƒ๏ผŒๅฏไปฅ้žๅธธ่ฝปๆพๅœฐ**็ป„ๅˆ**ๅนถไฝฟ็”จไธๅŒ็š„ๅทฅๅ…ทใ€‚ ไพ‹ๅฆ‚๏ผŒๅฐ่ฏ•ไธ€ไธชๆ–ฐ็š„ๆ•ฐๆฎๅบ“ใ€‚ ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ**ๅฎ˜ๆ–น้•œๅƒ**๏ผŒๅช้œ€ไธบๅ…ถ้…็ฝฎ็Žฏๅขƒๅ˜้‡ๅณๅฏใ€‚ +่ฟ™ๆ ท๏ผŒๅœจๅพˆๅคšๅœบๆ™ฏไธญไฝ ๅฏไปฅๅญฆไน ๅฎนๅ™จๅ’Œ Docker๏ผŒๅนถๅฐ†่ฟ™ไบ›็Ÿฅ่ฏ†ๅค็”จๅˆฐ่ฎธๅคšไธๅŒ็š„ๅทฅๅ…ทๅ’Œ็ป„ไปถไธญใ€‚ -่ฟ™ๆ ท๏ผŒๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไบ†่งฃๅฎนๅ™จๅ’Œ Docker๏ผŒๅนถ้€š่ฟ‡่ฎธๅคšไธๅŒ็š„ๅทฅๅ…ทๅ’Œ็ป„ไปถ้‡ๅคไฝฟ็”จ่ฟ™ไบ›็Ÿฅ่ฏ†ใ€‚ +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ่ฟ่กŒๅŒ…ๅซไธๅŒๅ†…ๅฎน็š„**ๅคšไธชๅฎนๅ™จ**๏ผŒๆฏ”ๅฆ‚ไธ€ไธชๆ•ฐๆฎๅบ“ใ€ไธ€ไธช Python ๅบ”็”จใ€ไธ€ไธชๅธฆ React ๅ‰็ซฏ็š„ Web ๆœๅŠกๅ™จ๏ผŒๅนถ้€š่ฟ‡ๅฎƒไปฌ็š„ๅ†…้ƒจ็ฝ‘็ปœ่ฟžๆŽฅๅœจไธ€่ตทใ€‚ -ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ่ฟ่กŒๅธฆๆœ‰ไธๅŒๅ†…ๅฎน็š„**ๅคšไธชๅฎนๅ™จ**๏ผŒไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“ใ€Python ๅบ”็”จ็จ‹ๅบใ€ๅธฆๆœ‰ React ๅ‰็ซฏๅบ”็”จ็จ‹ๅบ็š„ Web ๆœๅŠกๅ™จ๏ผŒๅนถ้€š่ฟ‡ๅ†…้ƒจ็ฝ‘็ปœๅฐ†ๅฎƒไปฌ่ฟžๆŽฅๅœจไธ€่ตทใ€‚ +ๆ‰€ๆœ‰ๅฎนๅ™จ็ฎก็†็ณป็ปŸ๏ผˆๅฆ‚ Docker ๆˆ– Kubernetes๏ผ‰้ƒฝๅ†…็ฝฎไบ†่ฟ™ไบ›็ฝ‘็ปœๅŠŸ่ƒฝใ€‚ -ๆ‰€ๆœ‰ๅฎนๅ™จ็ฎก็†็ณป็ปŸ๏ผˆๅฆ‚ Docker ๆˆ– Kubernetes๏ผ‰้ƒฝ้›†ๆˆไบ†่ฟ™ไบ›็ฝ‘็ปœๅŠŸ่ƒฝใ€‚ +## ๅฎนๅ™จไธŽ่ฟ›็จ‹ { #containers-and-processes } -## ๅฎนๅ™จๅ’Œ่ฟ›็จ‹ +**ๅฎนๅ™จ้•œๅƒ**้€šๅธธๅœจๅ…ถๅ…ƒๆ•ฐๆฎไธญๅŒ…ๅซๅœจ**ๅฎนๅ™จ**ๅฏๅŠจๆ—ถๅบ”่ฟ่กŒ็š„้ป˜่ฎค็จ‹ๅบๆˆ–ๅ‘ฝไปคไปฅๅŠ่ฆไผ ้€’็ป™่ฏฅ็จ‹ๅบ็š„ๅ‚ๆ•ฐใ€‚่ฟ™ไธŽๅ‘ฝไปค่กŒไธญๅš็š„ไบ‹ๆƒ…้žๅธธ็›ธไผผใ€‚ -**ๅฎนๅ™จ้•œๅƒ**้€šๅธธๅœจๅ…ถๅ…ƒๆ•ฐๆฎไธญๅŒ…ๅซๅฏๅŠจ**ๅฎนๅ™จ**ๆ—ถๅบ”่ฟ่กŒ็š„้ป˜่ฎค็จ‹ๅบๆˆ–ๅ‘ฝไปคไปฅๅŠ่ฆไผ ้€’็ป™่ฏฅ็จ‹ๅบ็š„ๅ‚ๆ•ฐใ€‚ ไธŽๅœจๅ‘ฝไปค่กŒไธญ็š„ๆƒ…ๅ†ต้žๅธธ็›ธไผผใ€‚ - -ๅฝ“ **ๅฎนๅ™จ** ๅฏๅŠจๆ—ถ๏ผŒๅฎƒๅฐ†่ฟ่กŒ่ฏฅๅ‘ฝไปค/็จ‹ๅบ๏ผˆๅฐฝ็ฎกไฝ ๅฏไปฅ่ฆ†็›–ๅฎƒๅนถไฝฟๅ…ถ่ฟ่กŒไธๅŒ็š„ๅ‘ฝไปค/็จ‹ๅบ๏ผ‰ใ€‚ +ๅฝ“**ๅฎนๅ™จ**ๅฏๅŠจๆ—ถ๏ผŒๅฎƒๅฐ†่ฟ่กŒ่ฏฅๅ‘ฝไปค/็จ‹ๅบ๏ผˆๅฐฝ็ฎกไฝ ๅฏไปฅ่ฆ†็›–ๅฎƒ๏ผŒ่ฎฉๅ…ถ่ฟ่กŒไธๅŒ็š„ๅ‘ฝไปค/็จ‹ๅบ๏ผ‰ใ€‚ ๅช่ฆ**ไธป่ฟ›็จ‹**๏ผˆๅ‘ฝไปคๆˆ–็จ‹ๅบ๏ผ‰ๅœจ่ฟ่กŒ๏ผŒๅฎนๅ™จๅฐฑๅœจ่ฟ่กŒใ€‚ -ๅฎนๅ™จ้€šๅธธๆœ‰ไธ€ไธช**ๅ•ไธช่ฟ›็จ‹**๏ผŒไฝ†ไนŸๅฏไปฅไปŽไธป่ฟ›็จ‹ๅฏๅŠจๅญ่ฟ›็จ‹๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจๅŒไธ€ไธชๅฎนๅ™จไธญๆ‹ฅๆœ‰**ๅคšไธช่ฟ›็จ‹**ใ€‚ - -ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœๆฒกๆœ‰**่‡ณๅฐ‘ไธ€ไธชๆญฃๅœจ่ฟ่กŒ็š„่ฟ›็จ‹**๏ผŒๅฐฑไธๅฏ่ƒฝๆœ‰ไธ€ไธชๆญฃๅœจ่ฟ่กŒ็š„ๅฎนๅ™จใ€‚ ๅฆ‚ๆžœไธป่ฟ›็จ‹ๅœๆญข๏ผŒๅฎนๅ™จไนŸไผšๅœๆญขใ€‚ +ๅฎนๅ™จ้€šๅธธๅชๆœ‰**ไธ€ไธช่ฟ›็จ‹**๏ผŒไฝ†ไนŸๅฏไปฅ็”ฑไธป่ฟ›็จ‹ๅฏๅŠจๅญ่ฟ›็จ‹๏ผŒ่ฟ™ๆ ทๅŒไธ€ไธชๅฎนๅ™จไธญๅฐฑไผšๆœ‰**ๅคšไธช่ฟ›็จ‹**ใ€‚ +ไฝ†ไธๅฏ่ƒฝๅœจๆฒกๆœ‰**่‡ณๅฐ‘ไธ€ไธช่ฟ่กŒไธญ็š„่ฟ›็จ‹**็š„ๆƒ…ๅ†ตไธ‹่ฎฉๅฎนๅ™จไฟๆŒ่ฟ่กŒใ€‚ๅฆ‚ๆžœไธป่ฟ›็จ‹ๅœๆญข๏ผŒๅฎนๅ™จไนŸไผšๅœๆญขใ€‚ -## ไธบ FastAPI ๆž„ๅปบ Docker ้•œๅƒ +## ไธบ FastAPI ๆž„ๅปบ Docker ้•œๅƒ { #build-a-docker-image-for-fastapi } -ๅฅฝๅง๏ผŒ่ฎฉๆˆ‘ไปฌ็Žฐๅœจๆž„ๅปบไธ€ไบ›ไธœ่ฅฟ๏ผ ๐Ÿš€ +ๅฅฝๅ•ฆ๏ผŒ็ŽฐๅœจๅŠจๆ‰‹ๆž„ๅปบ็‚นไธœ่ฅฟ๏ผ๐Ÿš€ -ๆˆ‘ๅฐ†ๅ‘ไฝ ๅฑ•็คบๅฆ‚ไฝ•ๅŸบไบŽ **ๅฎ˜ๆ–น Python** ้•œๅƒ **ไปŽๅคดๅผ€ๅง‹** ไธบ FastAPI ๆž„ๅปบ **Docker ้•œๅƒ**ใ€‚ +ๆˆ‘ๅฐ†ๆผ”็คบๅฆ‚ไฝ•ๅŸบไบŽ**ๅฎ˜ๆ–น Python** ้•œๅƒ๏ผŒ**ไปŽ้›ถๅผ€ๅง‹**ไธบ FastAPI ๆž„ๅปบไธ€ไธช**Docker ้•œๅƒ**ใ€‚ -่ฟ™ๆ˜ฏไฝ ๅœจ**ๅคงๅคšๆ•ฐๆƒ…ๅ†ต**ไธ‹ๆƒณ่ฆๅš็š„๏ผŒไพ‹ๅฆ‚๏ผš +่ฟ™ๅœจ**ๅคงๅคšๆ•ฐๆƒ…ๅ†ต**ไธ‹้ƒฝ้€‚็”จ๏ผŒไพ‹ๅฆ‚๏ผš * ไฝฟ็”จ **Kubernetes** ๆˆ–็ฑปไผผๅทฅๅ…ท -* ๅœจ **Raspberry Pi** ไธŠ่ฟ่กŒๆ—ถ -* ไฝฟ็”จๅฏไธบไฝ ่ฟ่กŒๅฎนๅ™จ้•œๅƒ็š„ไบ‘ๆœๅŠก็ญ‰ใ€‚ +* ่ฟ่กŒๅœจ **Raspberry Pi** +* ไฝฟ็”จๆŸไธชไธบไฝ ่ฟ่กŒๅฎนๅ™จ้•œๅƒ็š„ไบ‘ๆœๅŠก๏ผŒ็ญ‰็ญ‰ -### ไพ่ต–้กน +### ๅŒ…ไพ่ต– { #package-requirements } -ไฝ ้€šๅธธไผšๅœจๆŸไธชๆ–‡ไปถไธญๅŒ…ๅซๅบ”็”จ็จ‹ๅบ็š„**ไพ่ต–้กน**ใ€‚ +้€šๅธธไฝ ไผšๆŠŠๅบ”็”จ็š„**ๅŒ…ไพ่ต–**ๆ”พๅœจๆŸไธชๆ–‡ไปถ้‡Œใ€‚ -ๅ…ทไฝ“ๅšๆณ•ๅ–ๅ†ณไบŽไฝ **ๅฎ‰่ฃ…**่ฟ™ไบ›ไพ่ต–ๆ—ถๆ‰€ไฝฟ็”จ็š„ๅทฅๅ…ทใ€‚ +่ฟ™ไธป่ฆๅ–ๅ†ณไบŽไฝ ็”จๆฅ**ๅฎ‰่ฃ…**่ฟ™ไบ›ไพ่ต–็š„ๅทฅๅ…ทใ€‚ -ๆœ€ๅธธ่ง็š„ๆ–นๆณ•ๆ˜ฏๅˆ›ๅปบไธ€ไธช`requirements.txt`ๆ–‡ไปถ๏ผŒๅ…ถไธญๆฏ่กŒๅŒ…ๅซไธ€ไธชๅŒ…ๅ็งฐๅ’Œๅฎƒ็š„็‰ˆๆœฌใ€‚ +ๆœ€ๅธธ่ง็š„ๆ–นๅผๆ˜ฏไฝฟ็”จ `requirements.txt` ๆ–‡ไปถ๏ผŒๆฏ่กŒไธ€ไธชๅŒ…ๅๅŠๅ…ถ็‰ˆๆœฌ่Œƒๅ›ดใ€‚ -ไฝ ๅฝ“็„ถไนŸๅฏไปฅไฝฟ็”จๅœจ[ๅ…ณไบŽ FastAPI ็‰ˆๆœฌ](versions.md){.internal-link target=_blank} ไธญ่ฎฒๅˆฐ็š„ๆ–นๆณ•ๆฅ่ฎพ็ฝฎ็‰ˆๆœฌ่Œƒๅ›ดใ€‚ - -ไพ‹ๅฆ‚๏ผŒไฝ ็š„`requirements.txt`ๅฏ่ƒฝๅฆ‚ไธ‹ๆ‰€็คบ๏ผš +ๅฝ“็„ถ๏ผŒไฝ ไนŸๅฏไปฅๅ‚่€ƒไฝ ๅœจ[ๅ…ณไบŽ FastAPI ็‰ˆๆœฌ](versions.md){.internal-link target=_blank}ไธญ่ฏปๅˆฐ็š„ๆ€่ทฏๆฅ่ฎพ็ฝฎ็‰ˆๆœฌ่Œƒๅ›ดใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ็š„ `requirements.txt` ๅฏ่ƒฝๆ˜ฏ๏ผš ``` -fastapi>=0.68.0,<0.69.0 -pydantic>=1.8.0,<2.0.0 -uvicorn>=0.15.0,<0.16.0 +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 ``` -ไฝ ้€šๅธธไผšไฝฟ็”จ`pip`ๅฎ‰่ฃ…่ฟ™ไบ›ไพ่ต–้กน๏ผš +้€šๅธธไฝ ไผš็”จ `pip` ๅฎ‰่ฃ…่ฟ™ไบ›ไพ่ต–๏ผŒไพ‹ๅฆ‚๏ผš
```console $ pip install -r requirements.txt ---> 100% -Successfully installed fastapi pydantic uvicorn +Successfully installed fastapi pydantic ```
-/// info - -่ฟ˜ๆœ‰ๅ…ถไป–ๆ–‡ไปถๆ ผๅผๅ’Œๅทฅๅ…ทๆฅๅฎšไน‰ๅ’Œๅฎ‰่ฃ…ไพ่ต–้กนใ€‚ +/// info | ไฟกๆฏ - ๆˆ‘ๅฐ†ๅœจไธ‹้ข็š„้ƒจๅˆ†ไธญๅ‘ไฝ ๅฑ•็คบไธ€ไธชไฝฟ็”จ Poetry ็š„็คบไพ‹ใ€‚ ๐Ÿ‘‡ +่ฟ˜ๆœ‰ๅ…ถไป–ๆ ผๅผๅ’Œๅทฅๅ…ทๅฏไปฅๅฎšไน‰ๅนถๅฎ‰่ฃ…ๅŒ…ไพ่ต–ใ€‚ /// -### ๅˆ›ๅปบ **FastAPI** ไปฃ็  - -* ๅˆ›ๅปบ`app`็›ฎๅฝ•ๅนถ่ฟ›ๅ…ฅใ€‚ -* ๅˆ›ๅปบไธ€ไธช็ฉบๆ–‡ไปถ`__init__.py`ใ€‚ -* ๅˆ›ๅปบไธ€ไธช `main.py` ๆ–‡ไปถ๏ผš - +### ็ผ–ๅ†™ **FastAPI** ไปฃ็  { #create-the-fastapi-code } +* ๅˆ›ๅปบ `app` ็›ฎๅฝ•ๅนถ่ฟ›ๅ…ฅ +* ๅˆ›ๅปบ็ฉบๆ–‡ไปถ `__init__.py` +* ๅˆ›ๅปบ `main.py`๏ผŒๅ†…ๅฎนๅฆ‚ไธ‹๏ผš ```Python -from typing import Union - from fastapi import FastAPI app = FastAPI() @@ -169,84 +156,114 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -### Dockerfile +### Dockerfile { #dockerfile } -็Žฐๅœจๅœจ็›ธๅŒ็š„project็›ฎๅฝ•ๅˆ›ๅปบไธ€ไธชๅไธบ`Dockerfile`็š„ๆ–‡ไปถ: +็ŽฐๅœจๅœจๅŒไธ€ไธช้กน็›ฎ็›ฎๅฝ•ไธ‹ๅˆ›ๅปบ `Dockerfile` ๆ–‡ไปถ๏ผš ```{ .dockerfile .annotate } -# (1) +# (1)! FROM python:3.9 -# (2) +# (2)! WORKDIR /code -# (3) +# (3)! COPY ./requirements.txt /code/requirements.txt -# (4) +# (4)! RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -# (5) +# (5)! COPY ./app /code/app -# (6) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` -1. ไปŽๅฎ˜ๆ–นPythonๅŸบ็ก€้•œๅƒๅผ€ๅง‹ใ€‚ +1. ไปŽๅฎ˜ๆ–น Python ๅŸบ็ก€้•œๅƒๅผ€ๅง‹ใ€‚ + +2. ๅฐ†ๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•่ฎพ็ฝฎไธบ `/code`ใ€‚ -2. ๅฐ†ๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•่ฎพ็ฝฎไธบ`/code`ใ€‚ + ๆˆ‘ไปฌไผšๆŠŠ `requirements.txt` ๆ–‡ไปถๅ’Œ `app` ็›ฎๅฝ•ๆ”พๅœจ่ฟ™้‡Œใ€‚ - ่ฟ™ๆ˜ฏๆˆ‘ไปฌๆ”พ็ฝฎ`requirements.txt`ๆ–‡ไปถๅ’Œ`app`็›ฎๅฝ•็š„ไฝ็ฝฎใ€‚ +3. ๅฐ†ไพ่ต–ๆ–‡ไปถๅคๅˆถๅˆฐ `/code` ็›ฎๅฝ•ใ€‚ -3. ๅฐ†็ฌฆๅˆ่ฆๆฑ‚็š„ๆ–‡ไปถๅคๅˆถๅˆฐ`/code`็›ฎๅฝ•ไธญใ€‚ + ้ฆ–ๅ…ˆ**ๅช**ๅคๅˆถไพ่ต–ๆ–‡ไปถ๏ผŒไธ่ฆๅคๅˆถๅ…ถไป–ไปฃ็ ใ€‚ - ้ฆ–ๅ…ˆไป…ๅคๅˆถrequirements.txtๆ–‡ไปถ๏ผŒ่€Œไธๅคๅˆถๅ…ถไฝ™ไปฃ็ ใ€‚ + ๅ› ไธบ่ฟ™ไธชๆ–‡ไปถ**ไธๅธธๅ˜ๅŒ–**๏ผŒDocker ไผšๆฃ€ๆต‹ๅนถๅœจๆญคๆญฅ้ชคไฝฟ็”จ**็ผ“ๅญ˜**๏ผŒไปŽ่€ŒไนŸไธบไธ‹ไธ€ๆญฅๅฏ็”จ็ผ“ๅญ˜ใ€‚ - ็”ฑไบŽๆญคๆ–‡ไปถ**ไธ็ปๅธธๆ›ดๆ”น**๏ผŒDocker ๅฐ†ๆฃ€ๆต‹ๅˆฐๅฎƒๅนถๅœจ่ฟ™ไธ€ๆญฅไธญไฝฟ็”จ**็ผ“ๅญ˜**๏ผŒไปŽ่€Œไธบไธ‹ไธ€ๆญฅๅฏ็”จ็ผ“ๅญ˜ใ€‚ +4. ๅฎ‰่ฃ…ไพ่ต–ๆ–‡ไปถไธญ็š„ๅŒ…ไพ่ต–ใ€‚ -4. ๅฎ‰่ฃ…้œ€ๆฑ‚ๆ–‡ไปถไธญ็š„ๅŒ…ไพ่ต–้กนใ€‚ + `--no-cache-dir` ้€‰้กนๅ‘Š่ฏ‰ `pip` ไธ่ฆๅœจๆœฌๅœฐไฟๅญ˜ไธ‹่ฝฝ็š„ๅŒ…๏ผŒๅชๆœ‰ๅฝ“ไปฅๅŽ่ฟ˜่ฆๅ†ๆฌก็”จ `pip` ๅฎ‰่ฃ…็›ธๅŒๅŒ…ๆ—ถๆ‰้œ€่ฆ๏ผŒไฝ†ๅœจๅฎนๅ™จๅœบๆ™ฏไธ‹ไธๆ˜ฏ่ฟ™ๆ ทใ€‚ - `--no-cache-dir` ้€‰้กนๅ‘Š่ฏ‰ `pip` ไธ่ฆๅœจๆœฌๅœฐไฟๅญ˜ไธ‹่ฝฝ็š„ๅŒ…๏ผŒๅ› ไธบๅชๆœ‰ๅฝ“ `pip` ๅ†ๆฌก่ฟ่กŒไปฅๅฎ‰่ฃ…็›ธๅŒ็š„ๅŒ…ๆ—ถๆ‰ไผš่ฟ™ๆ ท๏ผŒไฝ†ๅœจไธŽๅฎนๅ™จไธ€่ตทๅทฅไฝœๆ—ถๆƒ…ๅ†ตๅนถ้žๅฆ‚ๆญคใ€‚ + /// note | ๆณจๆ„ - /// note | ็ฌ”่ฎฐ + `--no-cache-dir` ๅชๅ’Œ `pip` ๆœ‰ๅ…ณ๏ผŒไธŽ Docker ๆˆ–ๅฎนๅ™จๆ— ๅ…ณใ€‚ - `--no-cache-dir` ไป…ไธŽ `pip` ็›ธๅ…ณ๏ผŒไธŽ Docker ๆˆ–ๅฎนๅ™จๆ— ๅ…ณใ€‚ + /// - /// + `--upgrade` ้€‰้กนๅ‘Š่ฏ‰ `pip` ๅฆ‚ๆžœๅŒ…ๅทฒๅฎ‰่ฃ…ๅˆ™่ฟ›่กŒๅ‡็บงใ€‚ - `--upgrade` ้€‰้กนๅ‘Š่ฏ‰ `pip` ๅ‡็บง่ฝฏไปถๅŒ…๏ผˆๅฆ‚ๆžœๅทฒ็ปๅฎ‰่ฃ…๏ผ‰ใ€‚ + ็”ฑไบŽไธŠไธ€ๆญฅๅคๅˆถๆ–‡ไปถๅฏ่ƒฝ่ขซ **Docker ็ผ“ๅญ˜**ๆฃ€ๆต‹ๅˆฐ๏ผŒๅ› ๆญค่ฟ™ไธ€ๆญฅๅœจๅฏ็”จๆ—ถไนŸไผš**ไฝฟ็”จ Docker ็ผ“ๅญ˜**ใ€‚ - ๅ› ไธบไธŠไธ€ๆญฅๅคๅˆถๆ–‡ไปถๅฏไปฅ่ขซ **Docker ็ผ“ๅญ˜** ๆฃ€ๆต‹ๅˆฐ๏ผŒๆ‰€ไปฅๆญคๆญฅ้ชคไนŸๅฐ† **ไฝฟ็”จ Docker ็ผ“ๅญ˜**๏ผˆๅฆ‚ๆžœๅฏ็”จ๏ผ‰ใ€‚ + ๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญๅๅคๆž„ๅปบ้•œๅƒๆ—ถ๏ผŒๆญคๆญฅ้ชคไฝฟ็”จ็ผ“ๅญ˜ๅฏไปฅไธบไฝ **่Š‚็œๅคง้‡ๆ—ถ้—ด**๏ผŒ่€Œไธๅฟ…**ๆฏๆฌก**้ƒฝ**ไธ‹่ฝฝๅนถๅฎ‰่ฃ…**ๆ‰€ๆœ‰ไพ่ต–ใ€‚ - ๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญไธ€ๆฌกๅˆไธ€ๆฌกๆž„ๅปบ้•œๅƒๆ—ถ๏ผŒๅœจๆญคๆญฅ้ชคไธญไฝฟ็”จ็ผ“ๅญ˜ๅฐ†ไธบไฝ ่Š‚็œๅคง้‡**ๆ—ถ้—ด**๏ผŒ่€Œไธๆ˜ฏ**ๆฏๆฌก**้ƒฝ**ไธ‹่ฝฝๅ’Œๅฎ‰่ฃ…**ๆ‰€ๆœ‰ไพ่ต–้กนใ€‚ +5. ๅฐ† `./app` ็›ฎๅฝ•ๅคๅˆถๅˆฐ `/code` ็›ฎๅฝ•ใ€‚ + ่ฟ™้‡ŒๅŒ…ๅซไบ†ๆ‰€ๆœ‰**ๆœ€ๅธธๅ˜ๅŒ–**็š„ไปฃ็ ๏ผŒๅ› ๆญค Docker **็ผ“ๅญ˜**ๅพˆ้šพ็”จไบŽ่ฟ™ไธ€ๆญฅๆˆ–**ๅ…ถๅŽ็š„ๆญฅ้ชค**ใ€‚ -5. ๅฐ†โ€œ./appโ€็›ฎๅฝ•ๅคๅˆถๅˆฐโ€œ/codeโ€็›ฎๅฝ•ไธญใ€‚ + ๆ‰€ไปฅ๏ผŒๆŠŠๅฎƒๆ”พๅœจ `Dockerfile` ็š„**้ ๅŽไฝ็ฝฎ**๏ผŒๆœ‰ๅŠฉไบŽไผ˜ๅŒ–ๅฎนๅ™จ้•œๅƒ็š„ๆž„ๅปบๆ—ถ้—ดใ€‚ - ็”ฑไบŽๅ…ถไธญๅŒ…ๅซ**ๆ›ดๆ”นๆœ€้ข‘็น**็š„ๆ‰€ๆœ‰ไปฃ็ ๏ผŒๅ› ๆญค Docker **็ผ“ๅญ˜**ไธไผš่ฝปๆ˜“็”จไบŽๆญคๆ“ไฝœๆˆ–ไปปไฝ•**ๅŽ็ปญๆญฅ้ชค**ใ€‚ +6. ่ฎพ็ฝฎไฝฟ็”จ `fastapi run` ็š„**ๅ‘ฝไปค**๏ผˆๅบ•ๅฑ‚ไฝฟ็”จ Uvicorn๏ผ‰ใ€‚ - ๅ› ๆญค๏ผŒๅฐ†ๅ…ถๆ”พๅœจ`Dockerfile`**ๆŽฅ่ฟ‘ๆœ€ๅŽ**็š„ไฝ็ฝฎ้žๅธธ้‡่ฆ๏ผŒไปฅไผ˜ๅŒ–ๅฎนๅ™จ้•œๅƒ็š„ๆž„ๅปบๆ—ถ้—ดใ€‚ + `CMD` ๆŽฅๅ—ไธ€ไธชๅญ—็ฌฆไธฒๅˆ—่กจ๏ผŒๆฏไธชๅญ—็ฌฆไธฒ็›ธๅฝ“ไบŽไฝ ๅœจๅ‘ฝไปค่กŒไธญ็”จ็ฉบๆ ผๅˆ†้š”่พ“ๅ…ฅ็š„ๅ†…ๅฎนใ€‚ -6. ่ฎพ็ฝฎ**ๅ‘ฝไปค**ๆฅ่ฟ่กŒ `uvicorn` ๆœๅŠกๅ™จใ€‚ + ่ฏฅๅ‘ฝไปคไผšไปŽ**ๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•**่ฟ่กŒ๏ผŒไนŸๅฐฑๆ˜ฏไฝ ็”จ `WORKDIR /code` ่ฎพ็ฝฎ็š„ `/code` ็›ฎๅฝ•ใ€‚ - `CMD` ๆŽฅๅ—ไธ€ไธชๅญ—็ฌฆไธฒๅˆ—่กจ๏ผŒๆฏไธชๅญ—็ฌฆไธฒ้ƒฝๆ˜ฏไฝ ๅœจๅ‘ฝไปค่กŒไธญ่พ“ๅ…ฅ็š„ๅ†…ๅฎน๏ผŒๅนถ็”จ็ฉบๆ ผๅˆ†้š”ใ€‚ +/// tip | ๆ็คบ - ่ฏฅๅ‘ฝไปคๅฐ†ไปŽ **ๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•** ่ฟ่กŒ๏ผŒๅณไฝ ไธŠ้ขไฝฟ็”จ`WORKDIR /code`่ฎพ็ฝฎ็š„ๅŒไธ€`/code`็›ฎๅฝ•ใ€‚ +็‚นๅ‡ปไปฃ็ ไธญ็š„ๆฏไธช็ผ–ๅทๆฐ”ๆณกๆŸฅ็œ‹ๆฏ่กŒ็š„ไฝœ็”จใ€‚๐Ÿ‘† - ๅ› ไธบ็จ‹ๅบๅฐ†ไปŽ`/code`ๅฏๅŠจ๏ผŒๅนถไธ”ๅ…ถไธญๅŒ…ๅซไฝ ็š„ไปฃ็ ็š„็›ฎๅฝ•`./app`๏ผŒๆ‰€ไปฅ**Uvicorn**ๅฐ†่ƒฝๅคŸไปŽ`app.main`ไธญๆŸฅ็œ‹ๅนถ**import**`app`ใ€‚ +/// -/// tip +/// warning | ่ญฆๅ‘Š -้€š่ฟ‡ๅ•ๅ‡ปไปฃ็ ไธญ็š„ๆฏไธชๆ•ฐๅญ—ๆฐ”ๆณกๆฅๆŸฅ็œ‹ๆฏ่กŒ็š„ไฝœ็”จใ€‚ ๐Ÿ‘† +ๅŠกๅฟ…**ๅง‹็ปˆ**ไฝฟ็”จ `CMD` ๆŒ‡ไปค็š„**exec ๅฝขๅผ**๏ผŒๅฆ‚ไธ‹ๆ‰€่ฟฐใ€‚ /// -ไฝ ็Žฐๅœจๅบ”่ฏฅๅ…ทๆœ‰ๅฆ‚ไธ‹็›ฎๅฝ•็ป“ๆž„๏ผš +#### ไฝฟ็”จ `CMD` - Exec ๅฝขๅผ { #use-cmd-exec-form } + +`CMD` ๆŒ‡ไปคๆœ‰ไธค็งๅ†™ๆณ•๏ผš + +โœ… **Exec** ๅฝขๅผ๏ผš + +```Dockerfile +# โœ… ๆŽจ่ +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ **Shell** ๅฝขๅผ๏ผš + +```Dockerfile +# โ›”๏ธ ไธ่ฆ่ฟ™ๆ ท +CMD fastapi run app/main.py --port 80 +``` + +ๅŠกๅฟ…ไฝฟ็”จ**exec** ๅฝขๅผ๏ผŒไปฅ็กฎไฟ FastAPI ๅฏไปฅไผ˜้›…ๅœๆœบๅนถ่งฆๅ‘[็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ](../advanced/events.md){.internal-link target=_blank}ใ€‚ + +ไฝ ๅฏไปฅๅœจ Docker ๆ–‡ๆกฃ๏ผˆShell ไธŽ Exec ๅฝขๅผ๏ผ‰ไธญไบ†่งฃๆ›ดๅคšใ€‚ + +ๅœจไฝฟ็”จ `docker compose` ๆ—ถ่ฟ™ไธ€็‚นๅฐคไธบๆ˜Žๆ˜พใ€‚ๆ›ดๅคšๆŠ€ๆœฏ็ป†่Š‚ๅ‚่ง่ฏฅ FAQ๏ผšไธบไป€ไนˆๆˆ‘็š„ๆœๅŠก้œ€่ฆ 10 ็ง’ๆ‰่ƒฝ้‡ๆ–ฐๅˆ›ๅปบๆˆ–ๅœๆญข๏ผŸ + +#### ็›ฎๅฝ•็ป“ๆž„ { #directory-structure } + +ๆญคๆ—ถไฝ ็š„็›ฎๅฝ•็ป“ๆž„ๅบ”็ฑปไผผ๏ผš + ``` . โ”œโ”€โ”€ app @@ -256,56 +273,53 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] โ””โ”€โ”€ requirements.txt ``` +#### ๅœจ TLS ็ปˆๆญขไปฃ็†ๅŽ้ข { #behind-a-tls-termination-proxy } -#### ๅœจ TLS ็ปˆๆญขไปฃ็†ๅŽ้ข - -ๅฆ‚ๆžœไฝ ๅœจ Nginx ๆˆ– Traefik ็ญ‰ TLS ็ปˆๆญขไปฃ็†๏ผˆ่ดŸ่ฝฝๅ‡่กกๅ™จ๏ผ‰ๅŽ้ข่ฟ่กŒๅฎนๅ™จ๏ผŒ่ฏทๆทปๅŠ ้€‰้กน `--proxy-headers`๏ผŒ่ฟ™ๅฐ†ๅ‘Š่ฏ‰ Uvicorn ไฟกไปป่ฏฅไปฃ็†ๅ‘้€็š„ๆ ‡ๅคด๏ผŒๅ‘Š่ฏ‰ๅฎƒๅบ”็”จ็จ‹ๅบๆญฃๅœจ HTTPS ๅŽ้ข่ฟ่กŒ็ญ‰ไฟกๆฏ +ๅฆ‚ๆžœไฝ ๅœจ Nginx ๆˆ– Traefik ็ญ‰ TLS ็ปˆๆญขไปฃ็†๏ผˆ่ดŸ่ฝฝๅ‡่กกๅ™จ๏ผ‰ๅŽ้ข่ฟ่กŒๅฎนๅ™จ๏ผŒ่ฏทๆทปๅŠ  `--proxy-headers` ้€‰้กน๏ผŒ่ฟ™ไผš้€š่ฟ‡ FastAPI CLI ๅ‘Š่ฏ‰ Uvicorn ไฟกไปป่ฏฅไปฃ็†ๅ‘้€็š„ๆ ‡ๅคด๏ผŒ่กจๆ˜Žๅบ”็”จ่ฟ่กŒๅœจ HTTPS ๅŽ็ญ‰ใ€‚ ```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] ``` -#### Docker ็ผ“ๅญ˜ +#### Docker ็ผ“ๅญ˜ { #docker-cache } -่ฟ™ไธช`Dockerfile`ไธญๆœ‰ไธ€ไธช้‡่ฆ็š„ๆŠ€ๅทง๏ผŒๆˆ‘ไปฌ้ฆ–ๅ…ˆๅชๅ•็‹ฌๅคๅˆถ**ๅŒ…ๅซไพ่ต–้กน็š„ๆ–‡ไปถ**๏ผŒ่€Œไธๆ˜ฏๅ…ถไฝ™ไปฃ็ ใ€‚ ่ฎฉๆˆ‘ๆฅๅ‘Š่ฏ‰ไฝ ่ฟ™ๆ˜ฏไธบไป€ไนˆใ€‚ +่ฟ™ไธช `Dockerfile` ้‡Œๆœ‰ไธช้‡่ฆๆŠ€ๅทง๏ผšๆˆ‘ไปฌๅ…ˆ**ๅชๅคๅˆถไพ่ต–ๆ–‡ไปถ**๏ผŒ่€Œไธๆ˜ฏๅ…ถไป–ไปฃ็ ใ€‚ๅŽŸๅ› ๅฆ‚ไธ‹๏ผš ```Dockerfile COPY ./requirements.txt /code/requirements.txt ``` -Dockerไน‹็ฑป็š„ๆž„ๅปบๅทฅๅ…ทๆ˜ฏ้€š่ฟ‡**ๅขž้‡**็š„ๆ–นๅผๆฅๆž„ๅปบ่ฟ™ไบ›ๅฎนๅ™จ้•œๅƒ็š„ใ€‚ๅ…ทไฝ“ๅšๆณ•ๆ˜ฏไปŽ`Dockerfile`้กถ้ƒจๅผ€ๅง‹๏ผŒๆฏไธ€ๆกๆŒ‡ไปค็”Ÿๆˆ็š„ๆ–‡ไปถ้ƒฝๆ˜ฏ้•œๅƒ็š„โ€œไธ€ๅฑ‚โ€๏ผŒๅŒ่ฟ‡ๆŠŠ่ฟ™ไบ›โ€œๅฑ‚โ€ไธ€ๅฑ‚ไธ€ๅฑ‚ๅœฐๅ ๅŠ ๅˆฐๅŸบ็ก€้•œๅƒไธŠ๏ผŒๆœ€ๅŽๆˆ‘ไปฌๅฐฑๅพ—ๅˆฐไบ†ๆœ€็ปˆ็š„้•œๅƒใ€‚ +Docker ็ญ‰ๅทฅๅ…ทๆ˜ฏ**ๅขž้‡**ๅœฐ**ๆž„ๅปบ**ๅฎนๅ™จ้•œๅƒ็š„๏ผŒไปŽ `Dockerfile` ้กถ้ƒจๅผ€ๅง‹๏ผŒๆŒ‰้กบๅบไธบๆฏๆกๆŒ‡ไปคๅˆ›ๅปบ**ไธ€ๅฑ‚ๅ ๅŠ ๅฑ‚**๏ผŒๅนถๆŠŠๆฏๆญฅ็”Ÿๆˆ็š„ๆ–‡ไปถๅŠ ๅ…ฅใ€‚ -Docker ๅ’Œ็ฑปไผผๅทฅๅ…ทๅœจๆž„ๅปบ้•œๅƒๆ—ถไนŸไผšไฝฟ็”จ**ๅ†…้ƒจ็ผ“ๅญ˜**๏ผŒๅฆ‚ๆžœ่‡ชไธŠๆฌกๆž„ๅปบๅฎนๅ™จ้•œๅƒไปฅๆฅๆ–‡ไปถๆฒกๆœ‰ๆ›ดๆ”น๏ผŒ้‚ฃไนˆๅฎƒๅฐ†**้‡ๆ–ฐไฝฟ็”จไธŠๆฌกๅˆ›ๅปบ็š„ๅŒไธ€ๅฑ‚**๏ผŒ่€Œไธๆ˜ฏๅ†ๆฌกๅคๅˆถๆ–‡ไปถๅนถไปŽๅคดๅผ€ๅง‹ๅˆ›ๅปบๆ–ฐๅฑ‚ใ€‚ +ๆž„ๅปบ้•œๅƒๆ—ถ๏ผŒDocker ็ญ‰ๅทฅๅ…ทไนŸไผšไฝฟ็”จ**ๅ†…้ƒจ็ผ“ๅญ˜**ใ€‚ๅฆ‚ๆžœ่‡ชไธŠๆฌกๆž„ๅปบไปฅๆฅๆŸไธชๆ–‡ไปถๆฒกๆœ‰ๅ˜ๆ›ด๏ผŒๅฎƒไผš**้‡็”จ**ไธŠๆฌกๅˆ›ๅปบ็š„้‚ฃไธ€ๅฑ‚๏ผŒ่€Œไธๆ˜ฏๅ†ๆฌกๅคๅˆถๆ–‡ไปถๅนถไปŽๅคดๅˆ›ๅปบๆ–ฐๅฑ‚ใ€‚ -ไป…ไป…้ฟๅ…ๆ–‡ไปถ็š„ๅคๅˆถไธไธ€ๅฎšไผšๆœ‰ๅคชๅคš้€Ÿๅบฆๆๅ‡๏ผŒไฝ†ๆ˜ฏๅฆ‚ๆžœๅœจ่ฟ™ไธ€ๆญฅไฝฟ็”จไบ†็ผ“ๅญ˜๏ผŒ้‚ฃไนˆๆ‰ๅฏไปฅ**ๅœจไธ‹ไธ€ๆญฅไธญไฝฟ็”จ็ผ“ๅญ˜**ใ€‚ ไพ‹ๅฆ‚๏ผŒๅฏไปฅไฝฟ็”จๅฎ‰่ฃ…ไพ่ต–้กน้‚ฃๆกๆŒ‡ไปค็š„็ผ“ๅญ˜๏ผš +ไป…ไป…้ฟๅ…ๅคๅˆถๆ–‡ไปถๅนถไธไผšๅธฆๆฅๅคชๅคšๆ”น่ฟ›๏ผŒไฝ†ๅ› ไธบ่ฏฅๆญฅ้ชคไฝฟ็”จไบ†็ผ“ๅญ˜๏ผŒๅฎƒๅฐฑๅฏไปฅ**ๅœจไธ‹ไธ€ๆญฅไธญ็ปง็ปญไฝฟ็”จ็ผ“ๅญ˜**ใ€‚ไพ‹ๅฆ‚๏ผŒๅฎ‰่ฃ…ไพ่ต–็š„่ฟ™ๆกๆŒ‡ไปคไนŸ่ƒฝไฝฟ็”จ็ผ“ๅญ˜๏ผš ```Dockerfile RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt ``` +ๅŒ…ๅซๅŒ…ไพ่ต–็š„ๆ–‡ไปถ**ไธไผš้ข‘็นๅ˜ๆ›ด**ใ€‚ไป…ๅคๅˆถ่ฏฅๆ–‡ไปถ๏ผŒDocker ๅฐฑ่ƒฝๅœจ่ฟ™ไธ€ๆญฅ**ไฝฟ็”จ็ผ“ๅญ˜**ใ€‚ -ๅŒ…ๅซๅŒ…ไพ่ต–้กน็š„ๆ–‡ไปถ**ไธไผš้ข‘็นๆ›ดๆ”น**ใ€‚ ๅชๅคๅˆถ่ฏฅๆ–‡ไปถ๏ผˆไธๅคๅˆถๅ…ถไป–็š„ๅบ”็”จไปฃ็ ๏ผ‰๏ผŒDocker ๆ‰่ƒฝๅœจ่ฟ™ไธ€ๆญฅ**ไฝฟ็”จ็ผ“ๅญ˜**ใ€‚ - -Docker ่ฟ›่€Œ่ƒฝ**ไฝฟ็”จ็ผ“ๅญ˜่ฟ›่กŒไธ‹ไธ€ๆญฅ**๏ผŒๅณไธ‹่ฝฝๅนถๅฎ‰่ฃ…่ฟ™ไบ›ไพ่ต–้กนใ€‚ ่ฟ™ๆ‰ๆ˜ฏๆˆ‘ไปฌ**่Š‚็œๅคง้‡ๆ—ถ้—ด**็š„ๅœฐๆ–นใ€‚ โœจ ...ๅฏไปฅ้ฟๅ…ๆ— ่Š็š„็ญ‰ๅพ…ใ€‚ ๐Ÿ˜ช๐Ÿ˜† +้šๅŽ๏ผŒDocker ่ฟ˜่ƒฝ**ๅฏนไธ‹ไธ€ๆญฅ**๏ผˆไธ‹่ฝฝๅนถๅฎ‰่ฃ…ไพ่ต–๏ผ‰**ไฝฟ็”จ็ผ“ๅญ˜**ใ€‚่ฟ™ๆญฃๆ˜ฏๆˆ‘ไปฌ**่Š‚็œๅคง้‡ๆ—ถ้—ด**็š„ๅœฐๆ–นใ€‚โœจ ...ๅนถ้ฟๅ…ๆ— ่Š็š„็ญ‰ๅพ…ใ€‚๐Ÿ˜ช๐Ÿ˜† -ไธ‹่ฝฝๅ’Œๅฎ‰่ฃ…ไพ่ต–้กน**ๅฏ่ƒฝ้œ€่ฆๅ‡ ๅˆ†้’Ÿ**๏ผŒไฝ†ไฝฟ็”จ**็ผ“ๅญ˜**ๆœ€ๅคš**ๅช้œ€่ฆๅ‡ ็ง’้’Ÿ**ใ€‚ +ไธ‹่ฝฝๅนถๅฎ‰่ฃ…ไพ่ต–**ๅฏ่ƒฝ้œ€่ฆๅ‡ ๅˆ†้’Ÿ**๏ผŒ่€Œไฝฟ็”จ**็ผ“ๅญ˜**ๅˆ™**ๆœ€ๅคšๅช้œ€ๅ‡ ็ง’**ใ€‚ -็”ฑไบŽไฝ ๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญไผšไธ€ๆฌกๅˆไธ€ๆฌกๅœฐๆž„ๅปบๅฎนๅ™จ้•œๅƒไปฅๆฃ€ๆŸฅไปฃ็ ๆ›ดๆ”นๆ˜ฏๅฆๆœ‰ๆ•ˆ๏ผŒๅ› ๆญคๅฏไปฅ็ดฏ่ฎก่Š‚็œๅคง้‡ๆ—ถ้—ดใ€‚ +่€Œไธ”ๅœจๅผ€ๅ‘ไธญไฝ ไผšๅๅคๆž„ๅปบ้•œๅƒๆฅ้ชŒ่ฏไปฃ็ ๅ˜ๆ›ดๆ˜ฏๅฆ็”Ÿๆ•ˆ๏ผŒ็ดฏ่ฎก่Š‚็œ็š„ๆ—ถ้—ดไผšๅพˆๅคšใ€‚ -ๅœจ`Dockerfile`ๆœซๅฐพ้™„่ฟ‘๏ผŒๆˆ‘ไปฌๅ†ๆทปๅŠ ๅคๅˆถไปฃ็ ็š„ๆŒ‡ไปคใ€‚ ็”ฑไบŽไปฃ็ ๆ˜ฏ**ๆ›ดๆ”นๆœ€้ข‘็น็š„**๏ผŒๆ‰€ไปฅๅฐ†ๅ…ถๆ”พๅœจๆœ€ๅŽ๏ผŒๅ› ไธบ่ฟ™ไธ€ๆญฅไน‹ๅŽ็š„ๅ†…ๅฎนๅŸบๆœฌไธŠ้ƒฝๆ˜ฏๆ— ๆณ•ไฝฟ็”จ็ผ“ๅญ˜็š„ใ€‚ +ๆŽฅ็€๏ผŒๅœจ `Dockerfile` ็š„ๆœซๅฐพ้™„่ฟ‘ๆˆ‘ไปฌๅ†ๅคๅˆถๆ‰€ๆœ‰ไปฃ็ ใ€‚ๅ› ไธบ่ฟ™ๆ˜ฏ**ๅ˜ๅŒ–ๆœ€้ข‘็น**็š„้ƒจๅˆ†๏ผŒๆŠŠๅฎƒๆ”พๅœจๅŽ้ข๏ผŒ่ฟ™ๆ ทๅ‡ ไนŽๆ‰€ๆœ‰ๅœจๅฎƒไน‹ๅŽ็š„ๆญฅ้ชค้ƒฝไธไผšไฝฟ็”จๅˆฐ็ผ“ๅญ˜ใ€‚ ```Dockerfile COPY ./app /code/app ``` -### ๆž„ๅปบ Docker ้•œๅƒ +### ๆž„ๅปบ Docker ้•œๅƒ { #build-the-docker-image } -็Žฐๅœจๆ‰€ๆœ‰ๆ–‡ไปถ้ƒฝๅทฒๅฐฑไฝ๏ผŒ่ฎฉๆˆ‘ไปฌๆž„ๅปบๅฎนๅ™จ้•œๅƒใ€‚ +็Žฐๅœจๆ‰€ๆœ‰ๆ–‡ไปถ้ƒฝๅฐฑไฝไบ†๏ผŒๅผ€ๅง‹ๆž„ๅปบๅฎนๅ™จ้•œๅƒใ€‚ -* ่ฝฌๅˆฐ้กน็›ฎ็›ฎๅฝ•๏ผˆๅœจ`Dockerfile`ๆ‰€ๅœจ็š„ไฝ็ฝฎ๏ผŒๅŒ…ๅซ`app`็›ฎๅฝ•๏ผ‰ใ€‚ +* ่ฟ›ๅ…ฅ้กน็›ฎ็›ฎๅฝ•๏ผˆ`Dockerfile` ๆ‰€ๅœจไฝ็ฝฎ๏ผŒๅŒ…ๅซ `app` ็›ฎๅฝ•๏ผ‰ * ๆž„ๅปบไฝ ็š„ FastAPI ้•œๅƒ๏ผš -
```console @@ -316,18 +330,17 @@ $ docker build -t myimage .
+/// tip | ๆ็คบ -/// tip - -ๆณจๆ„ๆœ€ๅŽ็š„ `.`๏ผŒๅฎƒ็›ธๅฝ“ไบŽ`./`๏ผŒๅฎƒๅ‘Š่ฏ‰ Docker ็”จไบŽๆž„ๅปบๅฎนๅ™จ้•œๅƒ็š„็›ฎๅฝ•ใ€‚ +ๆณจๆ„ๆœซๅฐพ็š„ `.`๏ผŒๅฎƒ็ญ‰ไปทไบŽ `./`๏ผŒ็”จไบŽๅ‘Š่ฏ‰ Docker ไฝฟ็”จๅ“ชไธช็›ฎๅฝ•ๆฅๆž„ๅปบๅฎนๅ™จ้•œๅƒใ€‚ -ๅœจๆœฌไพ‹ไธญ๏ผŒๅฎƒๆ˜ฏ็›ธๅŒ็š„ๅฝ“ๅ‰็›ฎๅฝ•๏ผˆ`.`๏ผ‰ใ€‚ +ๆญคๅค„ๅฐฑๆ˜ฏๅฝ“ๅ‰็›ฎๅฝ•๏ผˆ`.`๏ผ‰ใ€‚ /// -### ๅฏๅŠจ Docker ๅฎนๅ™จ +### ๅฏๅŠจ Docker ๅฎนๅ™จ { #start-the-docker-container } -* ๆ นๆฎไฝ ็š„้•œๅƒ่ฟ่กŒๅฎนๅ™จ๏ผš +* ๅŸบไบŽไฝ ็š„้•œๅƒ่ฟ่กŒไธ€ไธชๅฎนๅ™จ๏ผš
@@ -337,10 +350,9 @@ $ docker run -d --name mycontainer -p 80:80 myimage
-## ๆฃ€ๆŸฅไธ€ไธ‹ +## ๆฃ€ๆŸฅไธ€ไธ‹ { #check-it } - -ไฝ ๅบ”่ฏฅ่ƒฝๅœจDockerๅฎนๅ™จ็š„URLไธญๆฃ€ๆŸฅๅฎƒ๏ผŒไพ‹ๅฆ‚: http://192.168.99.100/items/5?q=somequery ๆˆ– http://127.0.0.1/items/5?q=somequery (ๆˆ–ๅ…ถไป–็ญ‰ไปท็š„๏ผŒไฝฟ็”จ Docker ไธปๆœบ). +ไฝ ๅบ”่ฏฅ่ƒฝๅœจๅฎนๅ™จๆšด้œฒ็š„ URL ่ฎฟ้—ฎๅฎƒ๏ผŒไพ‹ๅฆ‚๏ผšhttp://192.168.99.100/items/5?q=somequery ๆˆ– http://127.0.0.1/items/5?q=somequery๏ผˆๆˆ–ๅ…ถไป–็ญ‰ไปทๅœฐๅ€๏ผŒๅ–ๅ†ณไบŽไฝ ็š„ Docker ไธปๆœบ๏ผ‰ใ€‚ ไฝ ไผš็œ‹ๅˆฐ็ฑปไผผๅ†…ๅฎน๏ผš @@ -348,25 +360,25 @@ $ docker run -d --name mycontainer -p 80:80 myimage {"item_id": 5, "q": "somequery"} ``` -## ไบคไบ’ๅผ API ๆ–‡ๆกฃ +## ไบคไบ’ๅผ API ๆ–‡ๆกฃ { #interactive-api-docs } -็Žฐๅœจไฝ ๅฏไปฅ่ฝฌๅˆฐ http://192.168.99.100/docs ๆˆ– http://127.0.0.1/docs ๏ผˆๆˆ–ๅ…ถไป–็ญ‰ไปท็š„๏ผŒไฝฟ็”จ Docker ไธปๆœบ๏ผ‰ใ€‚ +็Žฐๅœจไฝ ๅฏไปฅ่ฎฟ้—ฎ http://192.168.99.100/docs ๆˆ– http://127.0.0.1/docs๏ผˆๆˆ–ๅ…ถไป–็ญ‰ไปทๅœฐๅ€๏ผŒๅ–ๅ†ณไบŽไฝ ็š„ Docker ไธปๆœบ๏ผ‰ใ€‚ -ไฝ ๅฐ†็œ‹ๅˆฐ่‡ชๅŠจไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผˆ็”ฑ Swagger UI): +ไฝ ๅฐ†็œ‹ๅˆฐ่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผˆ็”ฑ Swagger UI ๆไพ›๏ผ‰๏ผš ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -## ๅค‡้€‰็š„ API ๆ–‡ๆกฃ +## ๅค‡้€‰ API ๆ–‡ๆกฃ { #alternative-api-docs } -ไฝ ่ฟ˜ๅฏไปฅ่ฎฟ้—ฎ http://192.168.99.100/redoc ๆˆ– http://127.0.0.1/redoc ๏ผˆๆˆ–ๅ…ถไป–็ญ‰ไปท็š„๏ผŒไฝฟ็”จ Docker ไธปๆœบ๏ผ‰ใ€‚ +ไฝ ่ฟ˜ๅฏไปฅ่ฎฟ้—ฎ http://192.168.99.100/redoc ๆˆ– http://127.0.0.1/redoc๏ผˆๆˆ–ๅ…ถไป–็ญ‰ไปทๅœฐๅ€๏ผŒๅ–ๅ†ณไบŽไฝ ็š„ Docker ไธปๆœบ๏ผ‰ใ€‚ ไฝ ๅฐ†็œ‹ๅˆฐๅค‡้€‰็š„่‡ชๅŠจๆ–‡ๆกฃ๏ผˆ็”ฑ ReDoc ๆไพ›๏ผ‰๏ผš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## ไฝฟ็”จๅ•ๆ–‡ไปถ FastAPI ๆž„ๅปบ Docker ้•œๅƒ +## ไฝฟ็”จๅ•ๆ–‡ไปถ FastAPI ๆž„ๅปบ Docker ้•œๅƒ { #build-a-docker-image-with-a-single-file-fastapi } -ๅฆ‚ๆžœไฝ ็š„ FastAPI ๆ˜ฏๅ•ไธชๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚ๆฒกๆœ‰`./app`็›ฎๅฝ•็š„`main.py`๏ผŒๅˆ™ไฝ ็š„ๆ–‡ไปถ็ป“ๆž„ๅฏ่ƒฝๅฆ‚ไธ‹ๆ‰€็คบ๏ผš +ๅฆ‚ๆžœไฝ ็š„ FastAPI ๆ˜ฏๅ•ไธชๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚ๆฒกๆœ‰ `./app` ็›ฎๅฝ•ใ€ๅชๆœ‰ `main.py`๏ผŒไฝ ็š„ๆ–‡ไปถ็ป“ๆž„ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš ``` . @@ -375,7 +387,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage โ””โ”€โ”€ requirements.txt ``` -็„ถๅŽไฝ ๅช้œ€ๆ›ดๆ”น็›ธๅบ”็š„่ทฏๅพ„ๅณๅฏๅฐ†ๆ–‡ไปถๅคๅˆถๅˆฐ`Dockerfile`ไธญ๏ผš +็„ถๅŽไฝ ๅช้œ€่ฆๅœจ `Dockerfile` ไธญไฟฎๆ”น็›ธๅบ”่ทฏๅพ„ๆฅๅคๅˆถ่ฏฅๆ–‡ไปถ๏ผš ```{ .dockerfile .annotate hl_lines="10 13" } FROM python:3.9 @@ -386,375 +398,221 @@ COPY ./requirements.txt /code/requirements.txt RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -# (1) +# (1)! COPY ./main.py /code/ -# (2) -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"] +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] ``` -1. ็›ดๆŽฅๅฐ†`main.py`ๆ–‡ไปถๅคๅˆถๅˆฐ`/code`็›ฎๅฝ•ไธญ๏ผˆไธๅŒ…ๅซไปปไฝ•`./app`็›ฎๅฝ•๏ผ‰ใ€‚ +1. ็›ดๆŽฅๅฐ† `main.py` ๅคๅˆถๅˆฐ `/code`๏ผˆๆฒกๆœ‰ `./app` ็›ฎๅฝ•๏ผ‰ใ€‚ -2. ่ฟ่กŒ Uvicorn ๅนถๅ‘Š่ฏ‰ๅฎƒไปŽ `main` ๅฏผๅ…ฅ `app` ๅฏน่ฑก๏ผˆ่€Œไธๆ˜ฏไปŽ `app.main` ๅฏผๅ…ฅ๏ผ‰ใ€‚ +2. ไฝฟ็”จ `fastapi run` ๆฅ่ฟ่กŒๅ•ๆ–‡ไปถ `main.py` ไธญ็š„ๅบ”็”จใ€‚ -็„ถๅŽ่ฐƒๆ•ดUvicornๅ‘ฝไปคไฝฟ็”จๆ–ฐๆจกๅ—`main`่€Œไธๆ˜ฏ`app.main`ๆฅๅฏผๅ…ฅFastAPI ๅฎžไพ‹`app`ใ€‚ +ๅฝ“ไฝ ๆŠŠๆ–‡ไปถไผ ็ป™ `fastapi run` ๆ—ถ๏ผŒๅฎƒไผš่‡ชๅŠจๆฃ€ๆต‹่ฟ™ๆ˜ฏไธ€ไธชๅ•ๆ–‡ไปถ่€Œไธๆ˜ฏๅŒ…๏ผŒๅนถ็Ÿฅ้“ๅฆ‚ไฝ•ๅฏผๅ…ฅๅนถๆœๅŠกไฝ ็š„ FastAPI ๅบ”็”จใ€‚๐Ÿ˜Ž -## ้ƒจ็ฝฒๆฆ‚ๅฟต +## ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployment-concepts } -ๆˆ‘ไปฌๅ†่ฐˆ่ฐˆๅฎนๅ™จๆ–น้ข็š„ไธ€ไบ›็›ธๅŒ็š„[้ƒจ็ฝฒๆฆ‚ๅฟต](concepts.md){.internal-link target=_blank}ใ€‚ +ๆˆ‘ไปฌๅ†ไปŽๅฎนๅ™จ็š„่ง’ๅบฆ่ฎจ่ฎบไธ€ไบ›็›ธๅŒ็š„[้ƒจ็ฝฒๆฆ‚ๅฟต](concepts.md){.internal-link target=_blank}ใ€‚ -ๅฎนๅ™จไธป่ฆๆ˜ฏไธ€็ง็ฎ€ๅŒ–**ๆž„ๅปบๅ’Œ้ƒจ็ฝฒ**ๅบ”็”จ็จ‹ๅบ็š„่ฟ‡็จ‹็š„ๅทฅๅ…ท๏ผŒไฝ†ๅฎƒไปฌๅนถไธๅผบๅˆถๆ‰ง่กŒ็‰นๅฎš็š„ๆ–นๆณ•ๆฅๅค„็†่ฟ™ไบ›**้ƒจ็ฝฒๆฆ‚ๅฟต**๏ผŒๅนถไธ”ๆœ‰ๅ‡ ็งๅฏ่ƒฝ็š„็ญ–็•ฅใ€‚ +ๅฎนๅ™จไธป่ฆๆ˜ฏ็ฎ€ๅŒ–ๅบ”็”จ**ๆž„ๅปบไธŽ้ƒจ็ฝฒ**ๆต็จ‹็š„ๅทฅๅ…ท๏ผŒไฝ†ๅฎƒไปฌๅนถไธๅผบๅˆถ้‡‡็”จๆŸ็ง็‰นๅฎšๆ–นๅผๆฅๅค„็†่ฟ™ไบ›**้ƒจ็ฝฒๆฆ‚ๅฟต**๏ผŒๅฏ้€‰็ญ–็•ฅๆœ‰ๅคš็งใ€‚ -**ๅฅฝๆถˆๆฏ**ๆ˜ฏ๏ผŒๅฏนไบŽๆฏ็งไธๅŒ็š„็ญ–็•ฅ๏ผŒ้ƒฝๆœ‰ไธ€็งๆ–นๆณ•ๅฏไปฅๆถต็›–ๆ‰€ๆœ‰้ƒจ็ฝฒๆฆ‚ๅฟตใ€‚ ๐ŸŽ‰ +**ๅฅฝๆถˆๆฏ**ๆ˜ฏ๏ผŒไธๅŒ็ญ–็•ฅไธ‹้ƒฝๆœ‰ๆ–นๅผ่ฆ†็›–ๆ‰€ๆœ‰้ƒจ็ฝฒๆฆ‚ๅฟตใ€‚๐ŸŽ‰ -่ฎฉๆˆ‘ไปฌไปŽๅฎนๅ™จ็š„่ง’ๅบฆๅ›ž้กพไธ€ไธ‹่ฟ™ไบ›**้ƒจ็ฝฒๆฆ‚ๅฟต**๏ผš +่ฎฉๆˆ‘ไปฌไปŽๅฎนๅ™จ่ง’ๅบฆๅ›ž้กพ่ฟ™ไบ›**้ƒจ็ฝฒๆฆ‚ๅฟต**๏ผš * HTTPS * ๅฏๅŠจๆ—ถ่ฟ่กŒ -* ้‡ๆ–ฐๅฏๅŠจ +* ๅคฑ่ดฅ้‡ๅฏ * ๅคๅˆถ๏ผˆ่ฟ่กŒ็š„่ฟ›็จ‹ๆ•ฐ๏ผ‰ * ๅ†…ๅญ˜ -* ๅผ€ๅง‹ๅ‰็š„ๅ…ˆๅ‰ๆญฅ้ชค - +* ๅฏๅŠจๅ‰็š„ๅ‰็ฝฎๆญฅ้ชค -## HTTPS +## HTTPS { #https } -ๅฆ‚ๆžœๆˆ‘ไปฌๅชๅ…ณๆณจ FastAPI ๅบ”็”จ็จ‹ๅบ็š„ **ๅฎนๅ™จ้•œๅƒ**๏ผˆไปฅๅŠ็จๅŽ่ฟ่กŒ็š„ **ๅฎนๅ™จ**๏ผ‰๏ผŒHTTPS ้€šๅธธไผš็”ฑๅฆไธ€ไธชๅทฅๅ…ทๅœจ **ๅค–้ƒจ** ๅค„็†ใ€‚ +ๅฆ‚ๆžœๆˆ‘ไปฌๅชๅ…ณๆณจ FastAPI ๅบ”็”จ็š„**ๅฎนๅ™จ้•œๅƒ**๏ผˆไปฅๅŠๅŽ็ปญ่ฟ่กŒ็š„**ๅฎนๅ™จ**๏ผ‰๏ผŒHTTPS ้€šๅธธ็”ฑ**ๅค–้ƒจ**็š„ๅ…ถไป–ๅทฅๅ…ทๅค„็†ใ€‚ -ๅฎƒๅฏไปฅๆ˜ฏๅฆไธ€ไธชๅฎนๅ™จ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ Traefik๏ผŒๅค„็† **HTTPS** ๅ’Œ **่‡ชๅŠจ**่Žทๅ–**่ฏไนฆ**ใ€‚ +ๅฎƒๅฏไปฅๆ˜ฏๅฆไธ€ไธชๅฎนๅ™จ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ Traefik๏ผŒๅค„็† **HTTPS** ๅนถ**่‡ชๅŠจ**่Žทๅ–**่ฏไนฆ**ใ€‚ -/// tip +/// tip | ๆ็คบ -TraefikๅฏไปฅไธŽ Dockerใ€Kubernetes ็ญ‰้›†ๆˆ๏ผŒๅ› ๆญคไฝฟ็”จๅฎƒไธบๅฎนๅ™จ่ฎพ็ฝฎๅ’Œ้…็ฝฎ HTTPS ้žๅธธๅฎนๆ˜“ใ€‚ +Traefik ไธŽ Dockerใ€Kubernetes ็ญ‰้ƒฝๆœ‰้›†ๆˆ๏ผŒๅ› ๆญคไธบๅฎนๅ™จ่ฎพ็ฝฎๅ’Œ้…็ฝฎ HTTPS ้žๅธธๅฎนๆ˜“ใ€‚ /// -ๆˆ–่€…๏ผŒHTTPS ๅฏไปฅ็”ฑไบ‘ๆœๅŠกๅ•†ไฝœไธบๅ…ถๆœๅŠกไน‹ไธ€่ฟ›่กŒๅค„็†๏ผˆๅŒๆ—ถไปๅœจๅฎนๅ™จไธญ่ฟ่กŒๅบ”็”จ็จ‹ๅบ๏ผ‰ใ€‚ +ๆˆ–่€…๏ผŒHTTPS ไนŸๅฏ่ƒฝ็”ฑไบ‘ๆœๅŠกๅ•†ไฝœไธบๅ…ถๆœๅŠกไน‹ไธ€ๆไพ›๏ผˆๅบ”็”จไป่ฟ่กŒๅœจๅฎนๅ™จไธญ๏ผ‰ใ€‚ -## ๅœจๅฏๅŠจๅ’Œ้‡ๆ–ฐๅฏๅŠจๆ—ถ่ฟ่กŒ +## ๅฏๅŠจๆ—ถ่ฟ่กŒไธŽ้‡ๅฏ { #running-on-startup-and-restarts } -้€šๅธธ่ฟ˜ๆœ‰ๅฆไธ€ไธชๅทฅๅ…ท่ดŸ่ดฃ**ๅฏๅŠจๅ’Œ่ฟ่กŒ**ไฝ ็š„ๅฎนๅ™จใ€‚ +้€šๅธธไผšๆœ‰ๅฆไธ€ไธชๅทฅๅ…ท่ดŸ่ดฃ**ๅฏๅŠจๅนถ่ฟ่กŒ**ไฝ ็š„ๅฎนๅ™จใ€‚ -ๅฎƒๅฏไปฅ็›ดๆŽฅๆ˜ฏ**Docker**, ๆˆ–่€…**Docker Compose**ใ€**Kubernetes**ใ€**ไบ‘ๆœๅŠก**็ญ‰ใ€‚ +ๅฎƒๅฏไปฅๆ˜ฏ็›ดๆŽฅ็š„ **Docker**ใ€**Docker Compose**ใ€**Kubernetes**ใ€ๆŸไธช**ไบ‘ๆœๅŠก**็ญ‰ใ€‚ -ๅœจๅคงๅคšๆ•ฐ๏ผˆๆˆ–ๆ‰€ๆœ‰๏ผ‰ๆƒ…ๅ†ตไธ‹๏ผŒๆœ‰ไธ€ไธช็ฎ€ๅ•็š„้€‰้กนๅฏไปฅๅœจๅฏๅŠจๆ—ถ่ฟ่กŒๅฎนๅ™จๅนถๅœจๅคฑ่ดฅๆ—ถ้‡ๆ–ฐๅฏๅŠจใ€‚ ไพ‹ๅฆ‚๏ผŒๅœจ Docker ไธญ๏ผŒๅฎƒๆ˜ฏๅ‘ฝไปค่กŒ้€‰้กน `--restart`ใ€‚ +ๅœจๅคงๅคšๆ•ฐ๏ผˆๆˆ–ๅ…จ้ƒจ๏ผ‰ๆƒ…ๅ†ตไธ‹๏ผŒ้ƒฝๆœ‰็ฎ€ๅ•้€‰้กนๅฏไปฅๅœจๅผ€ๆœบๆ—ถ่ฟ่กŒๅฎนๅ™จๅนถๅœจๅคฑ่ดฅๆ—ถๅฏ็”จ้‡ๅฏใ€‚ไพ‹ๅฆ‚๏ผŒๅœจ Docker ไธญๆ˜ฏๅ‘ฝไปค่กŒ้€‰้กน `--restart`ใ€‚ -ๅฆ‚ๆžœไธไฝฟ็”จๅฎนๅ™จ๏ผŒ่ฎฉๅบ”็”จ็จ‹ๅบๅœจๅฏๅŠจๆ—ถ่ฟ่กŒๅนถ้‡ๆ–ฐๅฏๅŠจๅฏ่ƒฝไผšๅพˆ้บป็ƒฆไธ”ๅ›ฐ้šพใ€‚ ไฝ†ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒๅฝ“**ไฝฟ็”จๅฎนๅ™จ**ๆ—ถ๏ผŒ้ป˜่ฎคๆƒ…ๅ†ตไธ‹ไผšๅŒ…ๅซ่ฏฅๅŠŸ่ƒฝใ€‚ โœจ +ๅฆ‚ๆžœไธไฝฟ็”จๅฎนๅ™จ๏ผŒ่ฆ่ฎฉๅบ”็”จๅผ€ๆœบ่‡ชๅฏๅนถๅธฆ้‡ๅฏๅฏ่ƒฝ็น็ไธ”ๅ›ฐ้šพใ€‚ไฝ†ๅœจ**ๅฎนๅ™จ**ๅœบๆ™ฏไธ‹๏ผŒ่ฟ™็งๅŠŸ่ƒฝ้€šๅธธ้ป˜่ฎคๅฐฑๅŒ…ๅซไบ†ใ€‚โœจ -## ๅคๅˆถ - ่ฟ›็จ‹ๆ•ฐ +## ๅคๅˆถ - ่ฟ›็จ‹ๆ•ฐ { #replication-number-of-processes } -ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช ้›†็พค, ๆฏ”ๅฆ‚ **Kubernetes**ใ€Docker Swarmใ€Nomad ๆˆ–ๅ…ถไป–็ฑปไผผ็š„ๅคๆ‚็ณป็ปŸๆฅ็ฎก็†ๅคšๅฐๆœบๅ™จไธŠ็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ๏ผŒ้‚ฃไนˆไฝ ๅฏ่ƒฝๅธŒๆœ›ๅœจ**้›†็พค็บงๅˆซ**ๅค„็†ๅคๅˆถ**๏ผŒ่€Œไธๆ˜ฏๅœจๆฏไธชๅฎนๅ™จไธญไฝฟ็”จ**่ฟ›็จ‹็ฎก็†ๅ™จ**๏ผˆๅฆ‚ๅธฆๆœ‰Worker็š„ Gunicorn๏ผ‰ ใ€‚ +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช็”ฑ **Kubernetes**ใ€Docker Swarm Modeใ€Nomad ๆˆ–ๅ…ถไป–็ฑปไผผ็š„ๅคๆ‚็ณป็ปŸ็ฎก็†็š„ใ€ๅœจๅคšๅฐๆœบๅ™จไธŠ่ฟ่กŒ็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ้›†็พค๏ผŒ้‚ฃไนˆไฝ ๅพˆๅฏ่ƒฝไผšๅธŒๆœ›ๅœจ**้›†็พคๅฑ‚้ข**ๆฅ**ๅค„็†ๅคๅˆถ**๏ผŒ่€Œไธๆ˜ฏๅœจๆฏไธชๅฎนๅ™จไธญไฝฟ็”จ**่ฟ›็จ‹็ฎก็†**๏ผˆๆฏ”ๅฆ‚่ฎฉ Uvicorn ่ฟ่กŒๅคšไธช workers๏ผ‰ใ€‚ -ๅƒ Kubernetes ่ฟ™ๆ ท็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸ้€šๅธธๆœ‰ไธ€ไบ›้›†ๆˆ็š„ๆ–นๆณ•ๆฅๅค„็†**ๅฎนๅ™จ็š„ๅคๅˆถ**๏ผŒๅŒๆ—ถไป็„ถๆ”ฏๆŒไผ ๅ…ฅ่ฏทๆฑ‚็š„**่ดŸ่ฝฝๅ‡่กก**ใ€‚ ๅ…จ้ƒจ้ƒฝๅœจ**้›†็พค็บงๅˆซ**ใ€‚ +ๅƒ Kubernetes ่ฟ™ๆ ท็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸ้€šๅธธ้ƒฝๆœ‰ๆŸ็งๅ†…็ฝฎๆ–นๅผๆฅๅค„็†**ๅฎนๅ™จๅคๅˆถ**๏ผŒๅŒๆ—ถๅฏนไผ ๅ…ฅ่ฏทๆฑ‚่ฟ›่กŒ**่ดŸ่ฝฝๅ‡่กก**ใ€‚่ฟ™ไธ€ๅˆ‡้ƒฝๅœจ**้›†็พคๅฑ‚้ข**ๅฎŒๆˆใ€‚ -ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ไปŽๅคดๅผ€ๅง‹ๆž„ๅปบไธ€ไธช **Docker ้•œๅƒ**๏ผŒๅฆ‚[ไธŠ้ขๆ‰€่งฃ้‡Š](#dockerfile)็š„้‚ฃๆ ท๏ผŒๅฎ‰่ฃ…ไพ่ต–้กนๅนถ่ฟ่กŒ **ๅ•ไธช Uvicorn ่ฟ›็จ‹**๏ผŒ่€Œไธๆ˜ฏ่ฟ่กŒ Gunicorn ๅ’Œ Uvicorn workers่ฟ™็งใ€‚ +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๅฆ‚[ไธŠๆ–‡ๆ‰€่ฟฐ](#dockerfile)้‚ฃๆ ท**ไปŽๅคดๆž„ๅปบ Docker ้•œๅƒ**๏ผŒๅฎ‰่ฃ…ไพ่ต–๏ผŒๅนถไป…่ฟ่กŒ**ๅ•ไธช Uvicorn ่ฟ›็จ‹**๏ผŒ่€Œไธๆ˜ฏไฝฟ็”จๅคšไธช Uvicorn workersใ€‚ +### ่ดŸ่ฝฝๅ‡่กกๅ™จ { #load-balancer } -### ่ดŸ่ฝฝๅ‡่กกๅ™จ +ไฝฟ็”จๅฎนๅ™จๆ—ถ๏ผŒ้€šๅธธไผšๆœ‰ๆŸไธช็ป„ไปถ**็›‘ๅฌไธป็ซฏๅฃ**ใ€‚ๅฎƒๅฏ่ƒฝๆ˜ฏๅฆไธ€ไธชๅŒๆ—ถๅ……ๅฝ“ **TLS ็ปˆๆญขไปฃ็†**ไปฅๅค„็† **HTTPS** ็š„ๅฎนๅ™จ๏ผŒๆˆ–็ฑปไผผๅทฅๅ…ทใ€‚ -ไฝฟ็”จๅฎนๅ™จๆ—ถ๏ผŒ้€šๅธธไผšๆœ‰ไธ€ไบ›็ป„ไปถ**็›‘ๅฌไธป็ซฏๅฃ**ใ€‚ ๅฎƒๅฏ่ƒฝๆ˜ฏๅค„็† **HTTPS** ็š„ **TLS ็ปˆๆญขไปฃ็†** ๆˆ–ไธ€ไบ›็ฑปไผผ็š„ๅทฅๅ…ท็š„ๅฆไธ€ไธชๅฎนๅ™จใ€‚ +็”ฑไบŽ่ฏฅ็ป„ไปถไผšๆ‰ฟๆŽฅ่ฏทๆฑ‚็š„**่ดŸ่ฝฝ**ๅนถไปฅ๏ผˆๆœŸๆœ›๏ผ‰**ๅ‡่กก**็š„ๆ–นๅผๅœจ workers ้—ดๅˆ†ๅ‘๏ผŒๅฎƒไนŸๅธธ่ขซ็งฐไธบ**่ดŸ่ฝฝๅ‡่กกๅ™จ**ใ€‚ -็”ฑไบŽ่ฏฅ็ป„ไปถๅฐ†ๆŽฅๅ—่ฏทๆฑ‚็š„**่ดŸ่ฝฝ**ๅนถ๏ผˆๅธŒๆœ›๏ผ‰ไปฅ**ๅนณ่กก**็š„ๆ–นๅผๅœจworkerไน‹้—ดๅˆ†้…่ฏฅ่ฏทๆฑ‚๏ผŒๅ› ๆญคๅฎƒ้€šๅธธไนŸ็งฐไธบ**่ดŸ่ฝฝๅ‡่กกๅ™จ**ใ€‚ +/// tip | ๆ็คบ -/// tip - -็”จไบŽ HTTPS **TLS ็ปˆๆญขไปฃ็†** ็š„็›ธๅŒ็ป„ไปถไนŸๅฏ่ƒฝๆ˜ฏ **่ดŸ่ฝฝๅ‡่กกๅ™จ**ใ€‚ +็”จไบŽ HTTPS ็š„**TLS ็ปˆๆญขไปฃ็†**็ป„ไปถ้€šๅธธไนŸไผšๆ˜ฏ**่ดŸ่ฝฝๅ‡่กกๅ™จ**ใ€‚ /// -ๅฝ“ไฝฟ็”จๅฎนๅ™จๆ—ถ๏ผŒไฝ ็”จๆฅๅฏๅŠจๅ’Œ็ฎก็†ๅฎนๅ™จ็š„ๅŒไธ€็ณป็ปŸๅทฒ็ปๅ…ทๆœ‰ๅ†…้ƒจๅทฅๅ…ทๆฅไผ ่พ“ๆฅ่‡ช่ฏฅ**่ดŸ่ฝฝๅ‡่กกๅ™จ**๏ผˆไนŸๅฏไปฅๆ˜ฏ**TLS ็ปˆๆญขไปฃ็†**) ็š„**็ฝ‘็ปœ้€šไฟก**๏ผˆไพ‹ๅฆ‚HTTP่ฏทๆฑ‚๏ผ‰ๅˆฐไฝ ็š„ๅบ”็”จ็จ‹ๅบๅฎนๅ™จใ€‚ - -### ไธ€ไธช่ดŸ่ฝฝๅ‡่กกๅ™จ - ๅคšไธชworkerๅฎนๅ™จ - -ๅฝ“ไฝฟ็”จ **Kubernetes** ๆˆ–็ฑปไผผ็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸๆ—ถ๏ผŒไฝฟ็”จๅ…ถๅ†…้ƒจ็ฝ‘็ปœๆœบๅˆถๅฐ†ๅ…่ฎธๅ•ไธชๅœจไธป **็ซฏๅฃ** ไธŠไพฆๅฌ็š„ **่ดŸ่ฝฝๅ‡่กกๅ™จ** ๅฐ†้€šไฟก๏ผˆ่ฏทๆฑ‚๏ผ‰ไผ ่พ“ๅˆฐๅฏ่ƒฝ็š„ **ๅคšไธช** ่ฟ่กŒไฝ ๅบ”็”จ็จ‹ๅบ็š„ๅฎนๅ™จใ€‚ - -่ฟ่กŒไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„ๆฏไธชๅฎนๅ™จ้€šๅธธ**ๅชๆœ‰ไธ€ไธช่ฟ›็จ‹**๏ผˆไพ‹ๅฆ‚๏ผŒ่ฟ่กŒ FastAPI ๅบ”็”จ็จ‹ๅบ็š„ Uvicorn ่ฟ›็จ‹๏ผ‰ใ€‚ ๅฎƒไปฌ้ƒฝๆ˜ฏ**็›ธๅŒ็š„ๅฎนๅ™จ**๏ผŒ่ฟ่กŒ็›ธๅŒ็š„ไธœ่ฅฟ๏ผŒไฝ†ๆฏไธชๅฎนๅ™จ้ƒฝๆœ‰่‡ชๅทฑ็š„่ฟ›็จ‹ใ€ๅ†…ๅญ˜็ญ‰ใ€‚่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจ CPU ็š„**ไธๅŒๆ ธๅฟƒ**๏ผŒ ็”š่‡ณๅœจ**ไธๅŒ็š„ๆœบๅ™จ**ๅ……ๅˆ†ๅˆฉ็”จ**ๅนถ่กŒๅŒ–(parallelization)**ใ€‚ +ไฝฟ็”จๅฎนๅ™จๆ—ถ๏ผŒไฝ ็”จๆฅๅฏๅŠจๅ’Œ็ฎก็†ๅฎนๅ™จ็š„็ณป็ปŸๆœฌ่บซๅฐฑๅทฒๆœ‰ๅ†…้ƒจๅทฅๅ…ท๏ผŒๅฐ†ๆฅ่‡ช่ฏฅ**่ดŸ่ฝฝๅ‡่กกๅ™จ**๏ผˆไนŸๅฏ่ƒฝๆ˜ฏ**TLS ็ปˆๆญขไปฃ็†**๏ผ‰็š„**็ฝ‘็ปœ้€šไฟก**๏ผˆไพ‹ๅฆ‚ HTTP ่ฏทๆฑ‚๏ผ‰ไผ ้€’ๅˆฐไฝ ็š„ๅบ”็”จๅฎนๅ™จไธญใ€‚ -ๅ…ทๆœ‰**่ดŸ่ฝฝๅ‡่กกๅ™จ**็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ็ณป็ปŸๅฐ†**ๅฐ†่ฏทๆฑ‚่ฝฎๆตๅˆ†้…**็ป™ไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„ๆฏไธชๅฎนๅ™จใ€‚ ๅ› ๆญค๏ผŒๆฏไธช่ฏทๆฑ‚้ƒฝๅฏไปฅ็”ฑ่ฟ่กŒไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„ๅคšไธช**ๅคๅˆถๅฎนๅ™จ**ไน‹ไธ€ๆฅๅค„็†ใ€‚ +### ไธ€ไธช่ดŸ่ฝฝๅ‡่กกๅ™จ - ๅคšไธช worker ๅฎนๅ™จ { #one-load-balancer-multiple-worker-containers } -้€šๅธธ๏ผŒ่ฟ™ไธช**่ดŸ่ฝฝๅ‡่กกๅ™จ**่ƒฝๅคŸๅค„็†ๅ‘้€ๅˆฐ้›†็พคไธญ็š„*ๅ…ถไป–*ๅบ”็”จ็จ‹ๅบ็š„่ฏทๆฑ‚๏ผˆไพ‹ๅฆ‚ๅ‘้€ๅˆฐไธๅŒ็š„ๅŸŸ๏ผŒๆˆ–ๅœจไธๅŒ็š„ URL ่ทฏๅพ„ๅ‰็ผ€ไธ‹๏ผ‰๏ผŒๅนถๆญฃ็กฎๅœฐๅฐ†่ฏฅ้€šไฟกไผ ่พ“ๅˆฐๅœจ้›†็พคไธญ่ฟ่กŒ็š„*ๅ…ถไป–*ๅบ”็”จ็จ‹ๅบ็š„ๅฏนๅบ”ๅฎนๅ™จใ€‚ +ๅœจ **Kubernetes** ็ญ‰ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸไธญ๏ผŒไฝฟ็”จๅ…ถๅ†…้ƒจ็ฝ‘็ปœๆœบๅˆถ๏ผŒๅ…่ฎธๅœจไธป**็ซฏๅฃ**ไธŠ็›‘ๅฌ็š„ๅ•ไธช**่ดŸ่ฝฝๅ‡่กกๅ™จ**ๅฐ†้€šไฟก๏ผˆ่ฏทๆฑ‚๏ผ‰่ฝฌๅ‘็ป™ๅฏ่ƒฝ**ๅคšไธช**่ฟ่กŒไฝ ๅบ”็”จ็š„ๅฎนๅ™จใ€‚ +่ฟ™ไบ›่ฟ่กŒไฝ ๅบ”็”จ็š„ๅฎนๅ™จ้€šๅธธๆฏไธชๅชๆœ‰**ไธ€ไธช่ฟ›็จ‹**๏ผˆไพ‹ๅฆ‚๏ผŒไธ€ไธช่ฟ่กŒ FastAPI ๅบ”็”จ็š„ Uvicorn ่ฟ›็จ‹๏ผ‰ใ€‚ๅฎƒไปฌ้ƒฝๆ˜ฏ**็›ธๅŒ็š„ๅฎนๅ™จ**๏ผŒ่ฟ่กŒ็›ธๅŒ็š„ไธœ่ฅฟ๏ผŒไฝ†ๆฏไธช้ƒฝๆœ‰่‡ชๅทฑ็š„่ฟ›็จ‹ใ€ๅ†…ๅญ˜็ญ‰ใ€‚่ฟ™ๆ ทไฝ ๅฐฑ่ƒฝๅœจ CPU ็š„**ไธๅŒๆ ธๅฟƒ**๏ผŒ็”š่‡ณๅœจ**ไธๅŒๆœบๅ™จ**ไธŠๅˆฉ็”จ**ๅนถ่กŒๅŒ–**ใ€‚ +ๅˆ†ๅธƒๅผๅฎนๅ™จ็ณป็ปŸ้…ๅˆ**่ดŸ่ฝฝๅ‡่กกๅ™จ**ไผšๆŠŠ่ฏทๆฑ‚**่ฝฎๆตๅˆ†้…**ๅˆฐๆฏไธชๅบ”็”จๅฎนๅ™จใ€‚ๅ› ๆญค๏ผŒๆฏไธช่ฏทๆฑ‚้ƒฝๅฏ่ƒฝ็”ฑๅคšไธช**ๅ‰ฏๆœฌๅฎนๅ™จ**ไน‹ไธ€ๆฅๅค„็†ใ€‚ +้€šๅธธ๏ผŒ่ฟ™ไธช**่ดŸ่ฝฝๅ‡่กกๅ™จ**่ฟ˜่ƒฝๅค„็†ๅ‘ๅพ€้›†็พคไธญ*ๅ…ถไป–*ๅบ”็”จ็š„่ฏทๆฑ‚๏ผˆไพ‹ๅฆ‚ไธๅŒๅŸŸๅ๏ผŒๆˆ–ไธๅŒ็š„ URL ่ทฏๅพ„ๅ‰็ผ€๏ผ‰๏ผŒๅนถๅฐ†้€šไฟก่ฝฌๅ‘ๅˆฐ่ฟ่กŒ*้‚ฃไธชๅ…ถไป–*ๅบ”็”จ็š„ๆญฃ็กฎๅฎนๅ™จใ€‚ +### ๆฏไธชๅฎนๅ™จไธ€ไธช่ฟ›็จ‹ { #one-process-per-container } +ๅœจ่ฟ™็งๅœบๆ™ฏไธ‹๏ผŒไฝ ๅคงๆฆ‚็އๅธŒๆœ›**ๆฏไธชๅฎนๅ™จๅชๆœ‰ไธ€ไธช๏ผˆUvicorn๏ผ‰่ฟ›็จ‹**๏ผŒๅ› ไธบไฝ ๅทฒ็ปๅœจ้›†็พคๅฑ‚้ขๅค„็†ไบ†ๅคๅˆถใ€‚ -### ๆฏไธชๅฎนๅ™จไธ€ไธช่ฟ›็จ‹ +ๅ› ๆญค๏ผŒ่ฟ™็งๆƒ…ๅ†ตไธ‹ไฝ **ไธๅธŒๆœ›**ๅœจๅฎนๅ™จๅ†…ๅ†ๅฏๅคšไธช workers๏ผˆไพ‹ๅฆ‚้€š่ฟ‡ `--workers` ๅ‘ฝไปค่กŒ้€‰้กน๏ผ‰ใ€‚ไฝ ไผšๅธŒๆœ›ๆฏไธชๅฎนๅ™จไป…ๆœ‰ไธ€ไธช**ๅ•็‹ฌ็š„ Uvicorn ่ฟ›็จ‹**๏ผˆไฝ†ๅฏ่ƒฝไผšๆœ‰ๅคšไธชๅฎนๅ™จ๏ผ‰ใ€‚ -ๅœจ่ฟ™็ง็ฑปๅž‹็š„ๅœบๆ™ฏไธญ๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›**ๆฏไธชๅฎนๅ™จๆœ‰ไธ€ไธช๏ผˆUvicorn๏ผ‰่ฟ›็จ‹**๏ผŒๅ› ไธบไฝ ๅทฒ็ปๅœจ้›†็พค็บงๅˆซๅค„็†ๅคๅˆถใ€‚ +ๅœจๅฎนๅ™จๅ†…ๅ†ๆ”พไธ€ไธช่ฟ›็จ‹็ฎก็†ๅ™จ๏ผˆๅฐฑๅƒๅฏๅคšไธช workers ไธ€ๆ ท๏ผ‰ๅชไผšๅผ•ๅ…ฅ**ไธๅฟ…่ฆ็š„ๅคๆ‚ๆ€ง**๏ผŒ่€Œ่ฟ™ไบ›ไฝ ๅพˆๅฏ่ƒฝๅทฒ็ปๅœจ้›†็พค็ณป็ปŸไธญๅค„็†ไบ†ใ€‚ -ๅ› ๆญค๏ผŒๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ **ไธไผš**ๅธŒๆœ›ๆ‹ฅๆœ‰ๅƒ Gunicorn ๅ’Œ Uvicorn workerไธ€ๆ ท็š„่ฟ›็จ‹็ฎก็†ๅ™จ๏ผŒๆˆ–่€… Uvicorn ไฝฟ็”จ่‡ชๅทฑ็š„ Uvicorn workerใ€‚ ไฝ ๅฏ่ƒฝๅธŒๆœ›ๆฏไธชๅฎนๅ™จ๏ผˆไฝ†ๅฏ่ƒฝๆœ‰ๅคšไธชๅฎนๅ™จ๏ผ‰ๅชๆœ‰ไธ€ไธช**ๅ•็‹ฌ็š„ Uvicorn ่ฟ›็จ‹**ใ€‚ +### ๅ…ทๆœ‰ๅคšไธช่ฟ›็จ‹ๅ’Œ็‰นๆฎŠๆƒ…ๅ†ต็š„ๅฎนๅ™จ { #containers-with-multiple-processes-and-special-cases } -ๅœจๅฎนๅ™จๅ†…ๆ‹ฅๆœ‰ๅฆไธ€ไธช่ฟ›็จ‹็ฎก็†ๅ™จ๏ผˆๅฐฑๅƒไฝฟ็”จ Gunicorn ๆˆ– Uvicorn ็ฎก็† Uvicorn ๅทฅไฝœ็บฟ็จ‹ไธ€ๆ ท๏ผ‰ๅชไผšๅขžๅŠ **ไธๅฟ…่ฆ็š„ๅคๆ‚ๆ€ง**๏ผŒ่€Œไฝ ๅพˆๅฏ่ƒฝๅทฒ็ปๅœจ้›†็พค็ณป็ปŸไธญๅค„็†่ฟ™ไบ›ๅคๆ‚ๆ€งไบ†ใ€‚ +ๅฝ“็„ถ๏ผŒไนŸๆœ‰ไธ€ไบ›**็‰นๆฎŠๆƒ…ๅ†ต**๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›่ฎฉ**ไธ€ไธชๅฎนๅ™จ**้‡Œ่ฟ่กŒๅคšไธช **Uvicorn worker ่ฟ›็จ‹**ใ€‚ -### ๅ…ทๆœ‰ๅคšไธช่ฟ›็จ‹็š„ๅฎนๅ™จ +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนๆฅ่ฎพ็ฝฎ่ฆ่ฟ่กŒ็š„ worker ๆ•ฐ้‡๏ผš -ๅฝ“็„ถ๏ผŒๅœจๆŸไบ›**็‰นๆฎŠๆƒ…ๅ†ต**๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๆ‹ฅๆœ‰ **ไธ€ไธชๅฎนๅ™จ**๏ผŒๅ…ถไธญๅŒ…ๅซ **Gunicorn ่ฟ›็จ‹็ฎก็†ๅ™จ**๏ผŒๅนถๅœจๅ…ถไธญๅฏๅŠจๅคšไธช **Uvicorn worker่ฟ›็จ‹**ใ€‚ - -ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ **ๅฎ˜ๆ–น Docker ้•œๅƒ**๏ผŒๅ…ถไธญๅŒ…ๅซ **Gunicorn** ไฝœไธบ่ฟ่กŒๅคšไธช **Uvicorn ๅทฅไฝœ่ฟ›็จ‹** ็š„่ฟ›็จ‹็ฎก็†ๅ™จ๏ผŒไปฅๅŠไธ€ไบ›้ป˜่ฎค่ฎพ็ฝฎๆฅๆ นๆฎๅฝ“ๅ‰ๆƒ…ๅ†ต่ฐƒๆ•ดๅทฅไฝœ่ฟ›็จ‹ๆ•ฐ้‡ ่‡ชๅŠจCPUๆ ธๅฟƒใ€‚ ๆˆ‘ๅฐ†ๅœจไธ‹้ข็š„ [Gunicorn - Uvicorn ๅฎ˜ๆ–น Docker ้•œๅƒ](#official-docker-image-with-gunicorn-uvicorn) ไธญๅ‘Š่ฏ‰ไฝ ๆ›ดๅคš็›ธๅ…ณไฟกๆฏใ€‚ +```{ .dockerfile .annotate } +FROM python:3.9 -ไธ‹้ขไธ€ไบ›ไป€ไนˆๆ—ถๅ€™่ฟ™็งๅšๆณ•ๆœ‰ๆ„ไน‰็š„็คบไพ‹๏ผš +WORKDIR /code +COPY ./requirements.txt /code/requirements.txt -#### ไธ€ไธช็ฎ€ๅ•็š„ๅบ”็”จ็จ‹ๅบ +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบ**่ถณๅคŸ็ฎ€ๅ•**๏ผŒไฝ ไธ้œ€่ฆ๏ผˆ่‡ณๅฐ‘็Žฐๅœจไธ้œ€่ฆ๏ผ‰่ฟ‡ๅคšๅœฐๅพฎ่ฐƒ่ฟ›็จ‹ๆ•ฐ้‡๏ผŒๅนถไธ”ไฝ ๅฏไปฅไฝฟ็”จ่‡ชๅŠจ้ป˜่ฎคๅ€ผ๏ผŒ้‚ฃไนˆไฝ ๅฏ่ƒฝ้œ€่ฆๅฎนๅ™จไธญ็š„่ฟ›็จ‹็ฎก็†ๅ™จ ๏ผˆไฝฟ็”จๅฎ˜ๆ–น Docker ้•œๅƒ๏ผ‰๏ผŒๅนถไธ”ไฝ ๅœจ**ๅ•ไธชๆœๅŠกๅ™จ**่€Œไธๆ˜ฏ้›†็พคไธŠ่ฟ่กŒๅฎƒใ€‚ +COPY ./app /code/app -#### Docker Compose +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` -ไฝ ๅฏไปฅไฝฟ็”จ **Docker Compose** ้ƒจ็ฝฒๅˆฐ**ๅ•ไธชๆœๅŠกๅ™จ**๏ผˆ่€Œไธๆ˜ฏ้›†็พค๏ผ‰๏ผŒๅ› ๆญคไฝ ๆฒกๆœ‰ไธ€็ง็ฎ€ๅ•็š„ๆ–นๆณ•ๆฅ็ฎก็†ๅฎนๅ™จ็š„ๅคๅˆถ๏ผˆไฝฟ็”จ Docker Compose๏ผ‰๏ผŒๅŒๆ—ถไฟ็•™ๅ…ฑไบซ็ฝ‘็ปœๅ’Œ **่ดŸ่ฝฝๅ‡่กก**ใ€‚ +1. ่ฟ™้‡Œๆˆ‘ไปฌไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนๅฐ† worker ๆ•ฐ้‡่ฎพ็ฝฎไธบ 4ใ€‚ -็„ถๅŽ๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๆ‹ฅๆœ‰ไธ€ไธช**ๅ•ไธชๅฎนๅ™จ**๏ผŒๅ…ถไธญๆœ‰ไธ€ไธช**่ฟ›็จ‹็ฎก็†ๅ™จ**๏ผŒๅœจๅ…ถไธญๅฏๅŠจ**ๅคšไธชworker่ฟ›็จ‹**ใ€‚ +ไปฅไธ‹ๆ˜ฏ่ฟ™็งๅšๆณ•ๅฏ่ƒฝๅˆ็†็š„ไธ€ไบ›็คบไพ‹๏ผš -#### Prometheusๅ’Œๅ…ถไป–ๅŽŸๅ›  +#### ไธ€ไธช็ฎ€ๅ•็š„ๅบ”็”จ { #a-simple-app } -ไฝ ่ฟ˜ๅฏ่ƒฝๆœ‰**ๅ…ถไป–ๅŽŸๅ› **๏ผŒ่ฟ™ๅฐ†ไฝฟไฝ ๆ›ดๅฎนๆ˜“ๆ‹ฅๆœ‰ไธ€ไธชๅธฆๆœ‰**ๅคšไธช่ฟ›็จ‹**็š„**ๅ•ไธชๅฎนๅ™จ**๏ผŒ่€Œไธๆ˜ฏๆ‹ฅๆœ‰ๆฏไธชๅฎนๅ™จไธญ้ƒฝๆœ‰**ๅ•ไธช่ฟ›็จ‹**็š„**ๅคšไธชๅฎนๅ™จ**ใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ**่ถณๅคŸ็ฎ€ๅ•**๏ผŒๅฏไปฅๅœจ**ๅ•ๅฐๆœๅŠกๅ™จ**๏ผˆไธๆ˜ฏ้›†็พค๏ผ‰ไธŠ่ฟ่กŒ๏ผŒไฝ ๅฏ่ƒฝไผšๅธŒๆœ›ๅœจๅฎนๅ™จๅ†…ๆœ‰ไธ€ไธช่ฟ›็จ‹็ฎก็†ๅ™จใ€‚ -ไพ‹ๅฆ‚๏ผˆๅ–ๅ†ณไบŽไฝ ็š„่ฎพ็ฝฎ๏ผ‰ไฝ ๅฏไปฅๅœจๅŒไธ€ไธชๅฎนๅ™จไธญๆ‹ฅๆœ‰ไธ€ไบ›ๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ Prometheus exporter๏ผŒ่ฏฅๅทฅๅ…ทๅบ”่ฏฅๆœ‰ๆƒ่ฎฟ้—ฎ**ๆฏไธช่ฏทๆฑ‚**ใ€‚ +#### Docker Compose { #docker-compose } -ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฆ‚ๆžœไฝ ๆœ‰**ๅคšไธชๅฎนๅ™จ**๏ผŒ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฝ“ Prometheus ๆฅ**่ฏปๅ–metrics**ๆ—ถ๏ผŒๅฎƒๆฏๆฌก้ƒฝไผš่Žทๅ–**ๅ•ไธชๅฎนๅ™จ**็š„metrics๏ผˆๅฏนไบŽๅค„็†่ฏฅ็‰นๅฎš่ฏทๆฑ‚็š„ๅฎนๅ™จ๏ผ‰๏ผŒ่€Œไธๆ˜ฏ่Žทๅ–ๆ‰€ๆœ‰ๅคๅˆถๅฎนๅ™จ็š„**็ดฏ็งฏmetrics**ใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ **Docker Compose** ้ƒจ็ฝฒๅˆฐ**ๅ•ๅฐๆœๅŠกๅ™จ**๏ผˆไธๆ˜ฏ้›†็พค๏ผ‰๏ผŒ้‚ฃไนˆไฝ ไธไผšๆœ‰ไธ€ไธช็ฎ€ๅ•็š„ๆ–นๆณ•ๅœจไฟ็•™ๅ…ฑไบซ็ฝ‘็ปœไธŽ**่ดŸ่ฝฝๅ‡่กก**็š„ๅŒๆ—ถ็ฎก็†ๅฎนๅ™จๅคๅˆถ๏ผˆ้€š่ฟ‡ Docker Compose๏ผ‰ใ€‚ -ๅœจ่ฟ™็งๆƒ…ๅ†ต๏ผŒ ่ฟ™็งๅšๆณ•ไผšๆ›ดๅŠ ็ฎ€ๅ•๏ผš่ฎฉ**ไธ€ไธชๅฎนๅ™จ**ๅ…ทๆœ‰**ๅคšไธช่ฟ›็จ‹**๏ผŒๅนถๅœจๅŒไธ€ไธชๅฎนๅ™จไธŠไฝฟ็”จๆœฌๅœฐๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ Prometheus exporter๏ผ‰ๆ”ถ้›†ๆ‰€ๆœ‰ๅ†…้ƒจ่ฟ›็จ‹็š„ Prometheus ๆŒ‡ๆ ‡ๅนถๅ…ฌๅผ€ๅ•ไธชๅฎนๅ™จไธŠ็š„่ฟ™ไบ›ๆŒ‡ๆ ‡ใ€‚ +่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›็”จ**ๅ•ไธชๅฎนๅ™จ**๏ผŒ็”ฑ**่ฟ›็จ‹็ฎก็†ๅ™จ**ๅœจๅฎนๅ™จๅ†…ๅฏๅŠจ**ๅคšไธช worker ่ฟ›็จ‹**ใ€‚ --- -่ฆ็‚นๆ˜ฏ๏ผŒ่ฟ™ไบ›้ƒฝ**ไธๆ˜ฏ**ไฝ ๅฟ…้กป็›ฒ็›ฎ้ตๅพช็š„**ไธ€ๆˆไธๅ˜็š„่ง„ๅˆ™**ใ€‚ ไฝ ๅฏไปฅๆ นๆฎ่ฟ™ไบ›ๆ€่ทฏ**่ฏ„ไผฐไฝ ่‡ชๅทฑ็š„ๅœบๆ™ฏ**ๅนถๅ†ณๅฎšไป€ไนˆๆ–นๆณ•ๆ˜ฏๆœ€้€‚ๅˆไฝ ็š„็š„็ณป็ปŸ๏ผŒ่€ƒ่™‘ๅฆ‚ไฝ•็ฎก็†ไปฅไธ‹ๆฆ‚ๅฟต๏ผš +่ฆ็‚นๆ˜ฏ๏ผŒ่ฟ™ไบ›้ƒฝ**ไธๆ˜ฏ**ไฝ ๅฟ…้กป็›ฒ็›ฎ้ตๅพช็š„**้“ๅพ‹**ใ€‚ไฝ ๅฏไปฅ็”จ่ฟ™ไบ›ๆ€่ทฏๆฅ**่ฏ„ไผฐไฝ ่‡ชๅทฑ็š„ๅœบๆ™ฏ**๏ผŒๅนถๅ†ณๅฎšๆœ€้€‚ๅˆไฝ ็š„็ณป็ปŸ็š„ๆ–นๆณ•๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•็ฎก็†ไปฅไธ‹ๆฆ‚ๅฟต๏ผš -* ๅฎ‰ๅ…จๆ€ง - HTTPS +* ๅฎ‰ๅ…จ - HTTPS * ๅฏๅŠจๆ—ถ่ฟ่กŒ -* ้‡ๆ–ฐๅฏๅŠจ +* ้‡ๅฏ * ๅคๅˆถ๏ผˆ่ฟ่กŒ็š„่ฟ›็จ‹ๆ•ฐ๏ผ‰ * ๅ†…ๅญ˜ -* ๅผ€ๅง‹ๅ‰็š„ๅ…ˆๅ‰ๆญฅ้ชค +* ๅฏๅŠจๅ‰็š„ๅ‰็ฝฎๆญฅ้ชค -## ๅ†…ๅญ˜ +## ๅ†…ๅญ˜ { #memory } -ๅฆ‚ๆžœไฝ **ๆฏไธชๅฎนๅ™จ่ฟ่กŒไธ€ไธช่ฟ›็จ‹**๏ผŒ้‚ฃไนˆๆฏไธชๅฎนๅ™จๆ‰€ๆถˆ่€—็š„ๅ†…ๅญ˜ๆˆ–ๅคšๆˆ–ๅฐ‘ๆ˜ฏๅฎšไน‰ๆ˜Ž็กฎ็š„ใ€็จณๅฎš็š„ไธ”ๆœ‰้™็š„๏ผˆๅฆ‚ๆžœๅฎƒไปฌๆ˜ฏๅคๅˆถ็š„๏ผŒๅˆ™ไธๆญขไธ€ไธช๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ **ๆฏไธชๅฎนๅ™จๅช่ฟ่กŒไธ€ไธช่ฟ›็จ‹**๏ผŒ้‚ฃไนˆๆฏไธชๅฎนๅ™จๆถˆ่€—็š„ๅ†…ๅญ˜ๅฐ†ๆ›ดๅฎนๆ˜“ๅฎšไน‰ใ€่พƒไธบ็จณๅฎšไธ”ๆœ‰้™๏ผˆๅฆ‚ๆžœๆœ‰ๅคๅˆถๅˆ™ไธบๅคšไธชๅฎนๅ™จ๏ผ‰ใ€‚ -็„ถๅŽ๏ผŒไฝ ๅฏไปฅๅœจๅฎนๅ™จ็ฎก็†็ณป็ปŸ็š„้…็ฝฎไธญ่ฎพ็ฝฎ็›ธๅŒ็š„ๅ†…ๅญ˜้™ๅˆถๅ’Œ่ฆๆฑ‚๏ผˆไพ‹ๅฆ‚ๅœจ **Kubernetes** ไธญ๏ผ‰ใ€‚ ่ฟ™ๆ ท๏ผŒๅฎƒๅฐ†่ƒฝๅคŸๅœจ**ๅฏ็”จๆœบๅ™จ**ไธญ**ๅคๅˆถๅฎนๅ™จ**๏ผŒๅŒๆ—ถ่€ƒ่™‘ๅฎนๅ™จๆ‰€้œ€็š„ๅ†…ๅญ˜้‡ไปฅๅŠ้›†็พคไธญๆœบๅ™จไธญ็š„ๅฏ็”จๅ†…ๅญ˜้‡ใ€‚ +ๆŽฅ็€๏ผŒไฝ ๅฏไปฅๅœจๅฎนๅ™จ็ฎก็†็ณป็ปŸ๏ผˆไพ‹ๅฆ‚ **Kubernetes**๏ผ‰็š„้…็ฝฎไธญ่ฎพ็ฝฎๅŒๆ ท็š„ๅ†…ๅญ˜้™ๅˆถไธŽ้œ€ๆฑ‚ใ€‚่ฟ™ๆ ทๅฎƒๅฐฑ่ƒฝๅœจ**ๅฏ็”จ็š„ๆœบๅ™จ**ไธŠ**ๅคๅˆถๅฎนๅ™จ**๏ผŒๅŒๆ—ถ่€ƒ่™‘ๅฎนๅ™จๆ‰€้œ€็š„ๅ†…ๅญ˜้‡ไปฅๅŠ้›†็พคไธญๆœบๅ™จๅฏ็”จ็š„ๅ†…ๅญ˜้‡ใ€‚ -ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบๅพˆ**็ฎ€ๅ•**๏ผŒ่ฟ™ๅฏ่ƒฝ**ไธๆ˜ฏ้—ฎ้ข˜**๏ผŒๅนถไธ”ไฝ ๅฏ่ƒฝไธ้œ€่ฆๆŒ‡ๅฎšๅ†…ๅญ˜้™ๅˆถใ€‚ ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ **ไฝฟ็”จๅคง้‡ๅ†…ๅญ˜**๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ**ๆœบๅ™จๅญฆไน **ๆจกๅž‹๏ผ‰๏ผŒๅˆ™ๅบ”่ฏฅๆฃ€ๆŸฅไฝ ๆถˆ่€—ไบ†ๅคšๅฐ‘ๅ†…ๅญ˜ๅนถ่ฐƒๆ•ด**ๆฏๅฐๆœบๅ™จ**ไธญ่ฟ่กŒ็š„**ๅฎนๅ™จๆ•ฐ้‡**๏ผˆไนŸ่ฎธๅฏไปฅๅ‘้›†็พคๆทปๅŠ ๆ›ดๅคšๆœบๅ™จ๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จๅพˆ**็ฎ€ๅ•**๏ผŒ่ฟ™ๅฏ่ƒฝ**ไธๆˆ้—ฎ้ข˜**๏ผŒไฝ ไนŸ่ฎธไธ้œ€่ฆ่ฎพ็ฝฎไธฅๆ ผ็š„ๅ†…ๅญ˜ไธŠ้™ใ€‚ไฝ†ๅฆ‚ๆžœไฝ **ไฝฟ็”จๅคง้‡ๅ†…ๅญ˜**๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ**ๆœบๅ™จๅญฆไน **ๆจกๅž‹๏ผ‰๏ผŒไฝ ๅบ”่ฏฅๆฃ€ๆŸฅ่‡ชๅทฑ็š„ๅ†…ๅญ˜ๆถˆ่€—๏ผŒๅนถ่ฐƒๆ•ด**ๆฏๅฐๆœบๅ™จ**ไธŠ่ฟ่กŒ็š„**ๅฎนๅ™จๆ•ฐ้‡**๏ผˆไนŸ่ฎธ่ฟ˜้œ€่ฆไธบ้›†็พคๅขžๅŠ ๆœบๅ™จ๏ผ‰ใ€‚ -ๅฆ‚ๆžœไฝ **ๆฏไธชๅฎนๅ™จ่ฟ่กŒๅคšไธช่ฟ›็จ‹**๏ผˆไพ‹ๅฆ‚ไฝฟ็”จๅฎ˜ๆ–น Docker ้•œๅƒ๏ผ‰๏ผŒไฝ ๅฟ…้กป็กฎไฟๅฏๅŠจ็š„่ฟ›็จ‹ๆ•ฐ้‡ไธไผšๆถˆ่€—ๆฏ”ๅฏ็”จๅ†…ๅญ˜**ๆ›ดๅคš็š„ๅ†…ๅญ˜**ใ€‚ +ๅฆ‚ๆžœไฝ **ๆฏไธชๅฎนๅ™จ่ฟ่กŒๅคšไธช่ฟ›็จ‹**๏ผŒไฝ ้œ€่ฆ็กฎไฟๅฏๅŠจ็š„่ฟ›็จ‹ๆ•ฐ้‡ไธไผš**ๆถˆ่€—่ถ…่ฟ‡ๅฏ็”จ็š„ๅ†…ๅญ˜**ใ€‚ -## ๅฏๅŠจไน‹ๅ‰็š„ๆญฅ้ชคๅ’Œๅฎนๅ™จ +## ๅฏๅŠจๅ‰็š„ๅ‰็ฝฎๆญฅ้ชคไธŽๅฎนๅ™จ { #previous-steps-before-starting-and-containers } -ๅฆ‚ๆžœไฝ ไฝฟ็”จๅฎนๅ™จ๏ผˆไพ‹ๅฆ‚ Dockerใ€Kubernetes๏ผ‰๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅไฝฟ็”จไธค็งไธป่ฆๆ–นๆณ•ใ€‚ +ๅฆ‚ๆžœไฝ ๅœจไฝฟ็”จๅฎนๅ™จ๏ผˆๅฆ‚ Dockerใ€Kubernetes๏ผ‰๏ผŒไฝ ๅฏไปฅ้‡‡็”จไธค็งไธป่ฆๆ–นๅผใ€‚ +### ๅคšไธชๅฎนๅ™จ { #multiple-containers } -### ๅคšไธชๅฎนๅ™จ +ๅฆ‚ๆžœไฝ ๆœ‰**ๅคšไธชๅฎนๅ™จ**๏ผŒๅฏ่ƒฝๆฏไธชๅฎนๅ™จ่ฟ่กŒไธ€ไธช**ๅ•็‹ฌ่ฟ›็จ‹**๏ผˆไพ‹ๅฆ‚ๅœจ **Kubernetes** ้›†็พคไธญ๏ผ‰๏ผŒ้‚ฃไนˆไฝ ๅฏ่ƒฝๅธŒๆœ›ไฝฟ็”จไธ€ไธช**ๅ•็‹ฌ็š„ๅฎนๅ™จ**ๆฅๆ‰ง่กŒ**ๅ‰็ฝฎๆญฅ้ชค**๏ผŒๅœจไธ€ไธชๅฎนๅ™จไธญ่ฟ่กŒไธ€ไธช่ฟ›็จ‹๏ผŒ**ๅœจ**ๅฏๅŠจ้‚ฃไบ›ๅคๅˆถ็š„ worker ๅฎนๅ™จ**ไน‹ๅ‰**ๅฎŒๆˆใ€‚ -ๅฆ‚ๆžœไฝ ๆœ‰ **ๅคšไธชๅฎนๅ™จ**๏ผŒๅฏ่ƒฝๆฏไธชๅฎนๅ™จ้ƒฝ่ฟ่กŒไธ€ไธช **ๅ•ไธช่ฟ›็จ‹**๏ผˆไพ‹ๅฆ‚๏ผŒๅœจ **Kubernetes** ้›†็พคไธญ๏ผ‰๏ผŒ้‚ฃไนˆไฝ ๅฏ่ƒฝๅธŒๆœ›ๆœ‰ไธ€ไธช **ๅ•็‹ฌ็š„ๅฎนๅ™จ** ๆ‰ง่กŒไปฅไธ‹ๆ“ไฝœ๏ผš ๅœจๅ•ไธชๅฎนๅ™จไธญ่ฟ่กŒๅ•ไธช่ฟ›็จ‹ๆ‰ง่กŒ**ๅ…ˆๅ‰ๆญฅ้ชค**๏ผŒๅณ่ฟ่กŒๅคๅˆถ็š„workerๅฎนๅ™จไน‹ๅ‰ใ€‚ +/// info | ไฟกๆฏ -/// info - -ๅฆ‚ๆžœไฝ ไฝฟ็”จ Kubernetes๏ผŒ่ฟ™ๅฏ่ƒฝๆ˜ฏ Init Containerใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ Kubernetes๏ผŒ่ฟ™้€šๅธธไผšๆ˜ฏไธ€ไธช Init Containerใ€‚ /// -ๅฆ‚ๆžœๅœจไฝ ็š„็”จไพ‹ไธญ๏ผŒ่ฟ่กŒๅ‰้ข็š„ๆญฅ้ชค**ๅนถ่กŒๅคšๆฌก**ๆฒกๆœ‰้—ฎ้ข˜๏ผˆไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๆฒกๆœ‰่ฟ่กŒๆ•ฐๆฎๅบ“่ฟ็งป๏ผŒ่€Œๅชๆ˜ฏๆฃ€ๆŸฅๆ•ฐๆฎๅบ“ๆ˜ฏๅฆๅทฒๅ‡†ๅค‡ๅฅฝ๏ผ‰๏ผŒ้‚ฃไนˆไฝ ไนŸๅฏไปฅๅฐ†ๅฎƒไปฌๆ”พๅœจๅผ€ๅง‹ไธป่ฟ›็จ‹ไน‹ๅ‰ๅœจๆฏไธชๅฎนๅ™จไธญใ€‚ - -### ๅ•ๅฎนๅ™จ - -ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช็ฎ€ๅ•็š„่ฎพ็ฝฎ๏ผŒไฝฟ็”จไธ€ไธช**ๅ•ไธชๅฎนๅ™จ**๏ผŒ็„ถๅŽๅฏๅŠจๅคšไธช**ๅทฅไฝœ่ฟ›็จ‹**๏ผˆๆˆ–่€…ไนŸๅชๆ˜ฏไธ€ไธช่ฟ›็จ‹๏ผ‰๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅๅœจๅฏๅŠจ่ฟ›็จ‹ไน‹ๅ‰ๅœจๅบ”็”จ็จ‹ๅบๅŒไธ€ไธชๅฎนๅ™จไธญ่ฟ่กŒๅ…ˆๅ‰็š„ๆญฅ้ชคใ€‚ ๅฎ˜ๆ–น Docker ้•œๅƒๅ†…้ƒจๆ”ฏๆŒ่ฟ™ไธ€็‚นใ€‚ - -## ๅธฆๆœ‰ Gunicorn ็š„ๅฎ˜ๆ–น Docker ้•œๅƒ - Uvicorn +ๅฆ‚ๆžœๅœจไฝ ็š„็”จไพ‹ไธญ๏ผŒ**ๅนถ่กŒๅคšๆฌก**่ฟ่กŒ่ฟ™ไบ›ๅ‰็ฝฎๆญฅ้ชคๆฒกๆœ‰้—ฎ้ข˜๏ผˆไพ‹ๅฆ‚ไฝ ไธๆ˜ฏๅœจ่ท‘ๆ•ฐๆฎๅบ“่ฟ็งป๏ผŒ่€Œๅชๆ˜ฏๆฃ€ๆŸฅๆ•ฐๆฎๅบ“ๆ˜ฏๅฆๅฐฑ็ปช๏ผ‰๏ผŒ้‚ฃไนˆไฝ ไนŸๅฏไปฅๆŠŠ่ฟ™ไบ›ๆญฅ้ชคๆ”พๅœจๆฏไธชๅฎนๅ™จไธญ๏ผŒๅœจๅฏๅŠจไธป่ฟ›็จ‹ไน‹ๅ‰ๆ‰ง่กŒใ€‚ -ๆœ‰ไธ€ไธชๅฎ˜ๆ–น Docker ้•œๅƒ๏ผŒๅ…ถไธญๅŒ…ๅซไธŽ Uvicorn workerไธ€่ตท่ฟ่กŒ็š„ Gunicorn๏ผŒๅฆ‚ไธŠไธ€็ซ ๆ‰€่ฟฐ๏ผš[ๆœๅŠกๅ™จๅทฅไฝœ็บฟ็จ‹ - Gunicorn ไธŽ Uvicorn](server-workers.md){.internal-link target=_blank}ใ€‚ +### ๅ•ไธชๅฎนๅ™จ { #single-container } -่ฏฅ้•œๅƒไธป่ฆๅœจไธŠ่ฟฐๆƒ…ๅ†ตไธ‹ๆœ‰็”จ๏ผš[ๅ…ทๆœ‰ๅคšไธช่ฟ›็จ‹ๅ’Œ็‰นๆฎŠๆƒ…ๅ†ต็š„ๅฎนๅ™จ](#containers-with-multiple-processes-and-special-cases)ใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๆžถๆž„่พƒไธบ็ฎ€ๅ•๏ผŒไฝฟ็”จไธ€ไธช**ๅ•ไธชๅฎนๅ™จ**๏ผŒๅ…ถๅŽๅ†ๅฏๅŠจๅคšไธช**worker ่ฟ›็จ‹**๏ผˆๆˆ–่€…ไนŸๅชๆœ‰ไธ€ไธช่ฟ›็จ‹๏ผ‰๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅๅœจๅŒไธ€ไธชๅฎนๅ™จไธญ๏ผŒๅœจๅฏๅŠจๅบ”็”จ่ฟ›็จ‹ไน‹ๅ‰ๆ‰ง่กŒ่ฟ™ไบ›ๅ‰็ฝฎๆญฅ้ชคใ€‚ +### ๅŸบ็ก€ Docker ้•œๅƒ { #base-docker-image } +ๆ›พ็ปๆœ‰ไธ€ไธชๅฎ˜ๆ–น็š„ FastAPI Docker ้•œๅƒ๏ผštiangolo/uvicorn-gunicorn-fastapiใ€‚ไฝ†ๅฎƒ็Žฐๅœจๅทฒ่ขซๅผƒ็”จใ€‚โ›”๏ธ -* tiangolo/uvicorn-gunicorn-fastapi. +ไฝ ๅคงๆฆ‚็އ**ไธๅบ”่ฏฅ**ไฝฟ็”จ่ฟ™ไธชๅŸบ็ก€้•œๅƒ๏ผˆๆˆ–ไปปไฝ•ๅ…ถๅฎƒ็ฑปไผผ็š„้•œๅƒ๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ **Kubernetes**๏ผˆๆˆ–ๅ…ถไป–๏ผ‰ๅนถไธ”ๅทฒ็ปๅœจ้›†็พคๅฑ‚้ข่ฎพ็ฝฎ**ๅคๅˆถ**ใ€ไฝฟ็”จๅคšไธช**ๅฎนๅ™จ**๏ผŒ้‚ฃไนˆๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆœ€ๅฅฝๅฆ‚ไธŠๆ‰€่ฟฐ**ไปŽๅคดๆž„ๅปบ้•œๅƒ**๏ผš[ไธบ FastAPI ๆž„ๅปบ Docker ้•œๅƒ](#build-a-docker-image-for-fastapi)ใ€‚ -/// warning +ๅฆ‚ๆžœไฝ ้œ€่ฆๅคšไธช workers๏ผŒๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนใ€‚ -ไฝ ๅพˆๆœ‰ๅฏ่ƒฝไธ้œ€่ฆๆญคๅŸบ็ก€้•œๅƒๆˆ–ไปปไฝ•ๅ…ถไป–็ฑปไผผ็š„้•œๅƒ๏ผŒๆœ€ๅฅฝไปŽๅคดๅผ€ๅง‹ๆž„ๅปบ้•œๅƒ๏ผŒๅฆ‚[ไธŠ้ขๆ‰€่ฟฐ๏ผšไธบ FastAPI ๆž„ๅปบ Docker ้•œๅƒ](#build-a-docker-image-for-fastapi)ใ€‚ +/// note | ๆŠ€ๆœฏ็ป†่Š‚ -/// - -่ฏฅ้•œๅƒๅŒ…ๅซไธ€ไธช**่‡ชๅŠจ่ฐƒๆ•ด**ๆœบๅˆถ๏ผŒ็”จไบŽๆ นๆฎๅฏ็”จ็š„ CPU ๆ ธๅฟƒ่ฎพ็ฝฎ**worker่ฟ›็จ‹ๆ•ฐ**ใ€‚ - -ๅฎƒๅ…ทๆœ‰**ๅˆ็†็š„้ป˜่ฎคๅ€ผ**๏ผŒไฝ†ไฝ ไป็„ถๅฏไปฅไฝฟ็”จ**็Žฏๅขƒๅ˜้‡**ๆˆ–้…็ฝฎๆ–‡ไปถๆ›ดๆ”นๅ’Œๆ›ดๆ–ฐๆ‰€ๆœ‰้…็ฝฎใ€‚ - -ๅฎƒ่ฟ˜ๆ”ฏๆŒ้€š่ฟ‡ไธ€ไธช่„šๆœฌ่ฟ่กŒ**ๅผ€ๅง‹ๅ‰็š„ๅ…ˆๅ‰ๆญฅ้ชค** ใ€‚ +่ฟ™ไธช Docker ้•œๅƒๅˆ›ๅปบไบŽ Uvicorn ่ฟ˜ไธๆ”ฏๆŒ็ฎก็†ไธŽ้‡ๅฏๅคฑๆ•ˆ workers ็š„ๆ—ถๆœŸ๏ผŒ้‚ฃๆ—ถ้œ€่ฆ็”จ Gunicorn ๆญ้… Uvicorn๏ผŒ่ฟ™ๅผ•ๅ…ฅไบ†ไธๅฐ‘ๅคๆ‚ๅบฆ๏ผŒๅชๆ˜ฏไธบไบ†่ฎฉ Gunicorn ็ฎก็†ๅนถ้‡ๅฏ Uvicorn ็š„ worker ่ฟ›็จ‹ใ€‚ -/// tip - -่ฆๆŸฅ็œ‹ๆ‰€ๆœ‰้…็ฝฎๅ’Œ้€‰้กน๏ผŒ่ฏท่ฝฌๅˆฐ Docker ้•œๅƒ้กต้ข๏ผš tiangolo/uvicorn-gunicorn-fastapiใ€‚ +ไฝ†็Žฐๅœจ Uvicorn๏ผˆไปฅๅŠ `fastapi` ๅ‘ฝไปค๏ผ‰ๅทฒ็ปๆ”ฏๆŒไฝฟ็”จ `--workers`๏ผŒๅ› ๆญคๆฒกๆœ‰็†็”ฑไธ่‡ชๅทฑๆž„ๅปบๅŸบ็ก€้•œๅƒ๏ผˆไปฃ็ ้‡ๅ‡ ไนŽไธ€ๆ ท ๐Ÿ˜…๏ผ‰ใ€‚ /// -### ๅฎ˜ๆ–น Docker ้•œๅƒไธŠ็š„่ฟ›็จ‹ๆ•ฐ - -ๆญค้•œๅƒไธŠ็š„**่ฟ›็จ‹ๆ•ฐ**ๆ˜ฏๆ นๆฎๅฏ็”จ็š„ CPU **ๆ ธๅฟƒ**่‡ชๅŠจ่ฎก็ฎ—็š„ใ€‚ - -่ฟ™ๆ„ๅ‘ณ็€ๅฎƒๅฐ†ๅฐ่ฏ•ๅฐฝๅฏ่ƒฝๅคšๅœฐ**ๆฆจๅ–**CPU ็š„**ๆ€ง่ƒฝ**ใ€‚ - -ไฝ ่ฟ˜ๅฏไปฅไฝฟ็”จ **็Žฏๅขƒๅ˜้‡** ็ญ‰้…็ฝฎๆฅ่ฐƒๆ•ดๅฎƒใ€‚ - -ไฝ†่ฟ™ไนŸๆ„ๅ‘ณ็€๏ผŒ็”ฑไบŽ่ฟ›็จ‹ๆ•ฐ้‡ๅ–ๅ†ณไบŽๅฎนๅ™จ่ฟ่กŒ็š„ CPU๏ผŒๅ› ๆญค**ๆถˆ่€—็š„ๅ†…ๅญ˜้‡**ไนŸๅฐ†ๅ–ๅ†ณไบŽ่ฏฅๆ•ฐ้‡ใ€‚ - -ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบๆถˆ่€—ๅคง้‡ๅ†…ๅญ˜๏ผˆไพ‹ๅฆ‚ๆœบๅ™จๅญฆไน ๆจกๅž‹๏ผ‰๏ผŒๅนถไธ”ไฝ ็š„ๆœๅŠกๅ™จๆœ‰ๅพˆๅคš CPU ๆ ธๅฟƒ**ไฝ†ๅ†…ๅญ˜ๅพˆๅฐ‘**๏ผŒ้‚ฃไนˆไฝ ็š„ๅฎนๅ™จๆœ€็ปˆๅฏ่ƒฝไผšๅฐ่ฏ•ไฝฟ็”จๆฏ”ๅฎž้™…ๆƒ…ๅ†ตๆ›ดๅคš็š„ๅ†…ๅญ˜ ๅฏ็”จ๏ผŒๅนถไธ”ๆ€ง่ƒฝไผšไธ‹้™ๅพˆๅคš๏ผˆ็”š่‡ณๅดฉๆบƒ๏ผ‰ใ€‚ ๐Ÿšจ - -### ๅˆ›ๅปบไธ€ไธช`Dockerfile` - -ไปฅไธ‹ๆ˜ฏๅฆ‚ไฝ•ๆ นๆฎๆญค้•œๅƒๅˆ›ๅปบ`Dockerfile`๏ผš - - -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt +## ้ƒจ็ฝฒๅฎนๅ™จ้•œๅƒ { #deploy-the-container-image } -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app -``` - -### ๆ›ดๅคง็š„ๅบ”็”จ็จ‹ๅบ - -ๅฆ‚ๆžœไฝ ๆŒ‰็…งๆœ‰ๅ…ณๅˆ›ๅปบ[ๅ…ทๆœ‰ๅคšไธชๆ–‡ไปถ็š„ๆ›ดๅคงๅบ”็”จ็จ‹ๅบ](../tutorial/bigger-applications.md){.internal-link target=_blank}็š„้ƒจๅˆ†่ฟ›่กŒๆ“ไฝœ๏ผŒไฝ ็š„`Dockerfile`ๅฏ่ƒฝ็œ‹่ตทๆฅ่ฟ™ๆ ท๏ผš - -```Dockerfile hl_lines="7" -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt - -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app/app -``` - -### ไฝ•ๆ—ถไฝฟ็”จ - -ๅฆ‚ๆžœไฝ ไฝฟ็”จ **Kubernetes** ๏ผˆๆˆ–ๅ…ถไป–๏ผ‰ๅนถไธ”ไฝ ๅทฒ็ปๅœจ้›†็พค็บงๅˆซ่ฎพ็ฝฎ **ๅคๅˆถ**๏ผŒๅนถไธ”ๅ…ทๆœ‰ๅคšไธช **ๅฎนๅ™จ**ใ€‚ ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๆœ€ๅฅฝๆŒ‰็…งไธŠ้ข็š„ๆ่ฟฐ **ไปŽๅคดๅผ€ๅง‹ๆž„ๅปบ้•œๅƒ**๏ผš[ไธบ FastAPI ๆž„ๅปบ Docker ้•œๅƒ](#build-a-docker-image-for-fastapi)ใ€‚ - -่ฏฅ้•œๅƒไธป่ฆๅœจ[ๅ…ทๆœ‰ๅคšไธช่ฟ›็จ‹็š„ๅฎนๅ™จๅ’Œ็‰นๆฎŠๆƒ…ๅ†ต](#containers-with-multiple-processes-and-special-cases)ไธญๆ่ฟฐ็š„็‰นๆฎŠๆƒ…ๅ†ตไธ‹ๆœ‰็”จใ€‚ ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ็š„ๅบ”็”จ็จ‹ๅบ**่ถณๅคŸ็ฎ€ๅ•**๏ผŒๅŸบไบŽ CPU ่ฎพ็ฝฎ้ป˜่ฎค่ฟ›็จ‹ๆ•ฐๆ•ˆๆžœๅพˆๅฅฝ๏ผŒไฝ ไธๆƒณๅœจ้›†็พค็บงๅˆซๆ‰‹ๅŠจ้…็ฝฎๅคๅˆถ๏ผŒๅนถไธ”ไธไผš่ฟ่กŒๆ›ดๅคš่ฟ›็จ‹, ๆˆ–่€…ไฝ ไฝฟ็”จ **Docker Compose** ่ฟ›่กŒ้ƒจ็ฝฒ๏ผŒๅœจๅ•ไธชๆœๅŠกๅ™จไธŠ่ฟ่กŒ็ญ‰ใ€‚ - -## ้ƒจ็ฝฒๅฎนๅ™จ้•œๅƒ - -ๆ‹ฅๆœ‰ๅฎนๅ™จ๏ผˆDocker๏ผ‰้•œๅƒๅŽ๏ผŒๆœ‰ๅคš็งๆ–นๆณ•ๅฏไปฅ้ƒจ็ฝฒๅฎƒใ€‚ +ๅพ—ๅˆฐๅฎนๅ™จ๏ผˆDocker๏ผ‰้•œๅƒๅŽ๏ผŒๆœ‰ๅคš็งๆ–นๅผๅฏไปฅ้ƒจ็ฝฒใ€‚ ไพ‹ๅฆ‚๏ผš -* ๅœจๅ•ไธชๆœๅŠกๅ™จไธญไฝฟ็”จ **Docker Compose** +* ๅœจๅ•ๅฐๆœๅŠกๅ™จไธŠไฝฟ็”จ **Docker Compose** * ไฝฟ็”จ **Kubernetes** ้›†็พค -* ไฝฟ็”จ Docker Swarm ๆจกๅผ้›†็พค -* ไฝฟ็”จNomad็ญ‰ๅ…ถไป–ๅทฅๅ…ท -* ไฝฟ็”จไบ‘ๆœๅŠก่Žทๅ–ๅฎนๅ™จ้•œๅƒๅนถ้ƒจ็ฝฒๅฎƒ - -## Docker ้•œๅƒไธŽPoetry - -ๅฆ‚ๆžœไฝ ไฝฟ็”จ Poetry ๆฅ็ฎก็†้กน็›ฎ็š„ไพ่ต–้กน๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Docker ๅคš้˜ถๆฎตๆž„ๅปบ๏ผš - - - -```{ .dockerfile .annotate } -# (1) -FROM python:3.9 as requirements-stage - -# (2) -WORKDIR /tmp - -# (3) -RUN pip install poetry - -# (4) -COPY ./pyproject.toml ./poetry.lock* /tmp/ - -# (5) -RUN poetry export -f requirements.txt --output requirements.txt --without-hashes - -# (6) -FROM python:3.9 - -# (7) -WORKDIR /code - -# (8) -COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt - -# (9) -RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt - -# (10) -COPY ./app /code/app - -# (11) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] -``` - -1. ่ฟ™ๆ˜ฏ็ฌฌไธ€้˜ถๆฎต๏ผŒ็งฐไธบ`requirements-stage`ใ€‚ - -2. ๅฐ† `/tmp` ่ฎพ็ฝฎไธบๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•ใ€‚ - - ่ฟ™ๆ˜ฏๆˆ‘ไปฌ็”Ÿๆˆๆ–‡ไปถ`requirements.txt`็š„ๅœฐๆ–น - -3. ๅœจๆญค้˜ถๆฎตๅฎ‰่ฃ…Poetryใ€‚ - -4. ๅฐ†`pyproject.toml`ๅ’Œ`poetry.lock`ๆ–‡ไปถๅคๅˆถๅˆฐ`/tmp`็›ฎๅฝ•ใ€‚ - - ๅ› ไธบๅฎƒไฝฟ็”จ `./poetry.lock*` ๏ผˆไปฅ `*` ็ป“ๅฐพ๏ผ‰๏ผŒๆ‰€ไปฅๅฆ‚ๆžœ่ฏฅๆ–‡ไปถๅฐšไธๅฏ็”จ๏ผŒๅฎƒไธไผšๅดฉๆบƒใ€‚ - -5. ็”Ÿๆˆ`requirements.txt`ๆ–‡ไปถใ€‚ - -6. ่ฟ™ๆ˜ฏๆœ€ๅŽ้˜ถๆฎต๏ผŒ่ฟ™้‡Œ็š„ไปปไฝ•ๅ†…ๅฎน้ƒฝๅฐ†ไฟ็•™ๅœจๆœ€็ปˆ็š„ๅฎนๅ™จ้•œๅƒไธญใ€‚ - -7. ๅฐ†ๅฝ“ๅ‰ๅทฅไฝœ็›ฎๅฝ•่ฎพ็ฝฎไธบ`/code`ใ€‚ - -8. ๅฐ† `requirements.txt` ๆ–‡ไปถๅคๅˆถๅˆฐ `/code` ็›ฎๅฝ•ใ€‚ - - ่ฏฅๆ–‡ไปถไป…ๅญ˜ๅœจไบŽๅ‰ไธ€ไธช้˜ถๆฎต๏ผŒ่ฟ™ๅฐฑๆ˜ฏไธบไป€ไนˆๆˆ‘ไปฌไฝฟ็”จ `--from-requirements-stage` ๆฅๅคๅˆถๅฎƒใ€‚ - -9. ๅฎ‰่ฃ…็”Ÿๆˆ็š„`requirements.txt`ๆ–‡ไปถไธญ็š„ไพ่ต–้กนใ€‚ - -10. ๅฐ†`app`็›ฎๅฝ•ๅคๅˆถๅˆฐ`/code`็›ฎๅฝ•ใ€‚ +* ไฝฟ็”จ Docker Swarm Mode ้›†็พค +* ไฝฟ็”จ Nomad ็ญ‰ๅ…ถไป–ๅทฅๅ…ท +* ไฝฟ็”จไบ‘ๆœๅŠก๏ผŒๆŽฅๆ”ถไฝ ็š„ๅฎนๅ™จ้•œๅƒๅนถ้ƒจ็ฝฒ -11. ่ฟ่กŒ`uvicorn`ๅ‘ฝไปค๏ผŒๅ‘Š่ฏ‰ๅฎƒไฝฟ็”จไปŽ`app.main`ๅฏผๅ…ฅ็š„`app`ๅฏน่ฑกใ€‚ +## ไฝฟ็”จ `uv` ็š„ Docker ้•œๅƒ { #docker-image-with-uv } -/// tip +ๅฆ‚ๆžœไฝ ไฝฟ็”จ uv ๆฅๅฎ‰่ฃ…ๅ’Œ็ฎก็†้กน็›ฎ๏ผŒๅฏไปฅๅ‚่€ƒไป–ไปฌ็š„ uv Docker ๆŒ‡ๅ—ใ€‚ -ๅ•ๅ‡ปๆฐ”ๆณกๆ•ฐๅญ—ๅฏๆŸฅ็œ‹ๆฏ่กŒ็š„ไฝœ็”จใ€‚ +## ๅ›ž้กพ { #recap } -/// - -**Docker stage** ๆ˜ฏ `Dockerfile` ็š„ไธ€้ƒจๅˆ†๏ผŒ็”จไฝœ **ไธดๆ—ถๅฎนๅ™จ้•œๅƒ**๏ผŒไป…็”จไบŽ็”Ÿๆˆไธ€ไบ›็จๅŽไฝฟ็”จ็š„ๆ–‡ไปถใ€‚ - -็ฌฌไธ€้˜ถๆฎตไป…็”จไบŽ **ๅฎ‰่ฃ… Poetry** ๅนถไฝฟ็”จ Poetry ็š„ `pyproject.toml` ๆ–‡ไปถไธญ็š„้กน็›ฎไพ่ต–้กน **็”Ÿๆˆ `requirements.txt`**ใ€‚ - -ๆญค`requirements.txt`ๆ–‡ไปถๅฐ†ๅœจ**ไธ‹ไธ€้˜ถๆฎต**ไธŽ`pip`ไธ€่ตทไฝฟ็”จใ€‚ - -ๅœจๆœ€็ปˆ็š„ๅฎนๅ™จ้•œๅƒไธญ**ไป…ไฟ็•™ๆœ€ๅŽ้˜ถๆฎต**ใ€‚ ไน‹ๅ‰็š„้˜ถๆฎตๅฐ†่ขซไธขๅผƒใ€‚ - -ไฝฟ็”จ Poetry ๆ—ถ๏ผŒไฝฟ็”จ **Docker ๅคš้˜ถๆฎตๆž„ๅปบ** ๆ˜ฏๆœ‰ๆ„ไน‰็š„๏ผŒๅ› ไธบไฝ ๅฎž้™…ไธŠๅนถไธ้œ€่ฆๅœจๆœ€็ปˆ็š„ๅฎนๅ™จ้•œๅƒไธญๅฎ‰่ฃ… Poetry ๅŠๅ…ถไพ่ต–้กน๏ผŒไฝ  **ๅช้œ€่ฆ** ็”Ÿๆˆ็”จไบŽๅฎ‰่ฃ…้กน็›ฎไพ่ต–้กน็š„`requirements.txt`ๆ–‡ไปถใ€‚ - -็„ถๅŽ๏ผŒๅœจไธ‹ไธ€ไธช๏ผˆไนŸๆ˜ฏๆœ€ๅŽไธ€ไธช๏ผ‰้˜ถๆฎต๏ผŒไฝ ๅฐ†ๆˆ–ๅคšๆˆ–ๅฐ‘ๅœฐไปฅไธŽๅ‰้ขๆ่ฟฐ็š„็›ธๅŒ็š„ๆ–นๅผๆž„ๅปบ้•œๅƒใ€‚ - -### ๅœจTLS ็ปˆๆญขไปฃ็†ๅŽ้ข - Poetry - -ๅŒๆ ท๏ผŒๅฆ‚ๆžœไฝ ๅœจ Nginx ๆˆ– Traefik ็ญ‰ TLS ็ปˆๆญขไปฃ็†๏ผˆ่ดŸ่ฝฝๅ‡่กกๅ™จ๏ผ‰ๅŽ้ข่ฟ่กŒๅฎนๅ™จ๏ผŒ่ฏทๅฐ†้€‰้กน`--proxy-headers`ๆทปๅŠ ๅˆฐๅ‘ฝไปคไธญ๏ผš - - -```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] -``` - -## ๅ›ž้กพ - -ไฝฟ็”จๅฎนๅ™จ็ณป็ปŸ๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ**Docker**ๅ’Œ**Kubernetes**๏ผ‰๏ผŒๅค„็†ๆ‰€ๆœ‰**้ƒจ็ฝฒๆฆ‚ๅฟต**ๅ˜ๅพ—็›ธๅฝ“็ฎ€ๅ•๏ผš +ไฝฟ็”จๅฎนๅ™จ็ณป็ปŸ๏ผˆไพ‹ๅฆ‚ **Docker** ไธŽ **Kubernetes**๏ผ‰ๅŽ๏ผŒๅค„็†ๆ‰€ๆœ‰**้ƒจ็ฝฒๆฆ‚ๅฟต**ไผšๅ˜ๅพ—็›ธๅฝ“็›ดๆŽฅ๏ผš * HTTPS * ๅฏๅŠจๆ—ถ่ฟ่กŒ -* ้‡ๆ–ฐๅฏๅŠจ +* ๅคฑ่ดฅ้‡ๅฏ * ๅคๅˆถ๏ผˆ่ฟ่กŒ็š„่ฟ›็จ‹ๆ•ฐ๏ผ‰ * ๅ†…ๅญ˜ -* ๅผ€ๅง‹ๅ‰็š„ๅ…ˆๅ‰ๆญฅ้ชค - -ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝไธๆƒณไฝฟ็”จไปปไฝ•ๅŸบ็ก€้•œๅƒ๏ผŒ่€Œๆ˜ฏๅŸบไบŽๅฎ˜ๆ–น Python Docker ้•œๅƒ **ไปŽๅคดๅผ€ๅง‹ๆž„ๅปบๅฎนๅ™จ้•œๅƒ** ใ€‚ +* ๅฏๅŠจๅ‰็š„ๅ‰็ฝฎๆญฅ้ชค -ๅค„็†ๅฅฝ`Dockerfile`ๅ’Œ **Docker ็ผ“ๅญ˜**ไธญๆŒ‡ไปค็š„**้กบๅบ**๏ผŒไฝ ๅฏไปฅ**ๆœ€ๅฐๅŒ–ๆž„ๅปบๆ—ถ้—ด**๏ผŒไปŽ่€Œๆœ€ๅคง้™ๅบฆๅœฐๆ้ซ˜็”ŸไบงๅŠ›๏ผˆๅนถ้ฟๅ…ๆ— ่Š๏ผ‰ใ€‚ ๐Ÿ˜Ž +ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝไธๆƒณไฝฟ็”จไปปไฝ•ๅŸบ็ก€้•œๅƒ๏ผŒ่€Œๆ˜ฏๅŸบไบŽๅฎ˜ๆ–น Python Docker ้•œๅƒ**ไปŽๅคดๆž„ๅปบๅฎนๅ™จ้•œๅƒ**ใ€‚ -ๅœจๆŸไบ›็‰นๆฎŠๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆไฝฟ็”จ FastAPI ็š„ๅฎ˜ๆ–น Docker ้•œๅƒใ€‚ ๐Ÿค“ +ๆณจๆ„ `Dockerfile` ไธญๆŒ‡ไปค็š„**้กบๅบ**ๅนถๅˆฉ็”จๅฅฝ**Docker ็ผ“ๅญ˜**๏ผŒๅฏไปฅ**ๆœ€ๅฐๅŒ–ๆž„ๅปบๆ—ถ้—ด**๏ผŒไปฅๆœ€ๅคงๅŒ–็”ŸไบงๅŠ›๏ผˆๅนถ้ฟๅ…ๆ— ่Š๏ผ‰ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index d994c4add8..4f60b7bca7 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -1,12 +1,12 @@ -# ๅ…ณไบŽ HTTPS +# ๅ…ณไบŽ HTTPS { #about-https } ไบบไปฌๅพˆๅฎนๆ˜“่ฎคไธบ HTTPS ไป…ไป…ๆ˜ฏโ€œๅฏ็”จโ€ๆˆ–โ€œๆœชๅฏ็”จโ€็š„ไธœ่ฅฟใ€‚ ไฝ†ๅฎž้™…ๆƒ…ๅ†ตๆฏ”่ฟ™ๅคๆ‚ๅพ—ๅคšใ€‚ -/// note | ๆ็คบ +/// tip | ๆ็คบ -ๅฆ‚ๆžœไฝ ๅพˆ่ตถๆ—ถ้—ดๆˆ–ไธๅœจไนŽ๏ผŒ่ฏท็ปง็ปญ้˜…่ฏปไธ‹ไธ€้ƒจๅˆ†๏ผŒไธ‹ไธ€้ƒจๅˆ†ไผšๆไพ›ไธ€ไธชstep-by-step็š„ๆ•™็จ‹๏ผŒๅ‘Š่ฏ‰ไฝ ๆ€Žไนˆไฝฟ็”จไธๅŒๆŠ€ๆœฏๆฅๆŠŠไธ€ๅˆ‡้ƒฝ้…็ฝฎๅฅฝใ€‚ +ๅฆ‚ๆžœไฝ ๅพˆ่ตถๆ—ถ้—ดๆˆ–ไธๅœจไนŽ๏ผŒ่ฏท็ปง็ปญ้˜…่ฏปๅŽ็ปญ็ซ ่Š‚๏ผŒๅฎƒไปฌไผšๆไพ›้€ๆญฅ็š„ๆ•™็จ‹๏ผŒๅ‘Š่ฏ‰ไฝ ๆ€Žไนˆไฝฟ็”จไธๅŒๆŠ€ๆœฏๆŠŠไธ€ๅˆ‡้ƒฝ้…็ฝฎๅฅฝใ€‚ /// @@ -15,24 +15,24 @@ ็Žฐๅœจ๏ผŒไปŽ**ๅผ€ๅ‘ไบบๅ‘˜็š„่ง†่ง’**๏ผŒๅœจไบ†่งฃ HTTPS ๆ—ถ้œ€่ฆ่ฎฐไฝไปฅไธ‹ๅ‡ ็‚น๏ผš * ่ฆไฝฟ็”จ HTTPS๏ผŒ**ๆœๅŠกๅ™จ**้œ€่ฆๆ‹ฅๆœ‰็”ฑ**็ฌฌไธ‰ๆ–น**็”Ÿๆˆ็š„**"่ฏไนฆ(certificate)"**ใ€‚ - * ่ฟ™ไบ›่ฏไนฆๅฎž้™…ไธŠๆ˜ฏไปŽ็ฌฌไธ‰ๆ–น**่Žทๅ–**็š„๏ผŒ่€Œไธๆ˜ฏโ€œ็”Ÿๆˆโ€็š„ใ€‚ + * ่ฟ™ไบ›่ฏไนฆๅฎž้™…ไธŠๆ˜ฏไปŽ็ฌฌไธ‰ๆ–น**่Žทๅ–**็š„๏ผŒ่€Œไธๆ˜ฏโ€œ็”Ÿๆˆโ€็š„ใ€‚ * ่ฏไนฆๆœ‰**็”Ÿๅ‘ฝๅ‘จๆœŸ**ใ€‚ - * ๅฎƒไปฌไผš**่ฟ‡ๆœŸ**ใ€‚ - * ็„ถๅŽๅฎƒไปฌ้œ€่ฆ**ๆ›ดๆ–ฐ**๏ผŒ**ๅ†ๆฌกไปŽ็ฌฌไธ‰ๆ–น่Žทๅ–**ใ€‚ + * ๅฎƒไปฌไผš**่ฟ‡ๆœŸ**ใ€‚ + * ็„ถๅŽๅฎƒไปฌ้œ€่ฆ**ๆ›ดๆ–ฐ**๏ผŒ**ๅ†ๆฌกไปŽ็ฌฌไธ‰ๆ–น่Žทๅ–**ใ€‚ * ่ฟžๆŽฅ็š„ๅŠ ๅฏ†ๅ‘็”Ÿๅœจ **TCP ๅฑ‚**ใ€‚ - * ่ฟ™ๆ˜ฏ HTTP ๅ่ฎฎ**ไธ‹้ข็š„ไธ€ๅฑ‚**ใ€‚ - * ๅ› ๆญค๏ผŒ**่ฏไนฆๅ’ŒๅŠ ๅฏ†**ๅค„็†ๆ˜ฏๅœจ **HTTPไน‹ๅ‰**ๅฎŒๆˆ็š„ใ€‚ + * ่ฟ™ๆ˜ฏ HTTP ๅ่ฎฎ**ไธ‹้ข็š„ไธ€ๅฑ‚**ใ€‚ + * ๅ› ๆญค๏ผŒ**่ฏไนฆๅ’ŒๅŠ ๅฏ†**ๅค„็†ๆ˜ฏๅœจ **HTTPไน‹ๅ‰**ๅฎŒๆˆ็š„ใ€‚ * **TCP ไธ็Ÿฅ้“ๅŸŸๅ**ใ€‚ ไป…ไป…็Ÿฅ้“ IP ๅœฐๅ€ใ€‚ - * ๆœ‰ๅ…ณๆ‰€่ฏทๆฑ‚็š„ **็‰นๅฎšๅŸŸๅ** ็š„ไฟกๆฏไฝไบŽ **HTTP ๆ•ฐๆฎ**ไธญใ€‚ + * ๆœ‰ๅ…ณๆ‰€่ฏทๆฑ‚็š„ **็‰นๅฎšๅŸŸๅ** ็š„ไฟกๆฏไฝไบŽ **HTTP ๆ•ฐๆฎ**ไธญใ€‚ * **HTTPS ่ฏไนฆ**โ€œ่ฏๆ˜Žโ€**ๆŸไธชๅŸŸๅ**๏ผŒไฝ†ๅ่ฎฎๅ’ŒๅŠ ๅฏ†ๅ‘็”Ÿๅœจ TCP ๅฑ‚๏ผŒๅœจ็Ÿฅ้“ๆญฃๅœจๅค„็†ๅ“ชไธชๅŸŸๅ**ไน‹ๅ‰**ใ€‚ * **้ป˜่ฎคๆƒ…ๅ†ตไธ‹**๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ไฝ **ๆฏไธช IP ๅœฐๅ€ๅช่ƒฝๆ‹ฅๆœ‰ไธ€ไธช HTTPS ่ฏไนฆ**ใ€‚ - * ๆ— ่ฎบไฝ ็š„ๆœๅŠกๅ™จๆœ‰ๅคšๅคง๏ผŒๆˆ–่€…ๆœๅŠกๅ™จไธŠ็š„ๆฏไธชๅบ”็”จ็จ‹ๅบๆœ‰ๅคšๅฐใ€‚ - * ไธ่ฟ‡๏ผŒๅฏนๆญคๆœ‰ไธ€ไธช**่งฃๅ†ณๆ–นๆกˆ**ใ€‚ -* **TLS** ๅ่ฎฎ๏ผˆๅœจ HTTP ไน‹ไธ‹็š„TCP ๅฑ‚ๅค„็†ๅŠ ๅฏ†็š„ๅ่ฎฎ๏ผ‰ๆœ‰ไธ€ไธช**ๆ‰ฉๅฑ•**๏ผŒ็งฐไธบ **SNI**ใ€‚ - * SNI ๆ‰ฉๅฑ•ๅ…่ฎธไธ€ๅฐๆœๅŠกๅ™จ๏ผˆๅ…ทๆœ‰ **ๅ•ไธช IP ๅœฐๅ€**๏ผ‰ๆ‹ฅๆœ‰ **ๅคšไธช HTTPS ่ฏไนฆ** ๅนถๆไพ› **ๅคšไธช HTTPS ๅŸŸๅ/ๅบ”็”จ็จ‹ๅบ**ใ€‚ - * ไธบๆญค๏ผŒๆœๅŠกๅ™จไธŠไผšๆœ‰**ๅ•็‹ฌ**็š„ไธ€ไธช็ป„ไปถ๏ผˆ็จ‹ๅบ๏ผ‰ไพฆๅฌ**ๅ…ฌๅ…ฑ IP ๅœฐๅ€**๏ผŒ่ฟ™ไธช็ป„ไปถๅฟ…้กปๆ‹ฅๆœ‰ๆœๅŠกๅ™จไธญ็š„**ๆ‰€ๆœ‰ HTTPS ่ฏไนฆ**ใ€‚ + * ๆ— ่ฎบไฝ ็š„ๆœๅŠกๅ™จๆœ‰ๅคšๅคง๏ผŒๆˆ–่€…ๆœๅŠกๅ™จไธŠ็š„ๆฏไธชๅบ”็”จ็จ‹ๅบๆœ‰ๅคšๅฐใ€‚ + * ไธ่ฟ‡๏ผŒๅฏนๆญคๆœ‰ไธ€ไธช**่งฃๅ†ณๆ–นๆกˆ**ใ€‚ +* **TLS** ๅ่ฎฎ๏ผˆๅœจ HTTP ไน‹ไธ‹็š„ TCP ๅฑ‚ๅค„็†ๅŠ ๅฏ†็š„ๅ่ฎฎ๏ผ‰ๆœ‰ไธ€ไธช**ๆ‰ฉๅฑ•**๏ผŒ็งฐไธบ **SNI**ใ€‚ + * SNI ๆ‰ฉๅฑ•ๅ…่ฎธไธ€ๅฐๆœๅŠกๅ™จ๏ผˆๅ…ทๆœ‰ **ๅ•ไธช IP ๅœฐๅ€**๏ผ‰ๆ‹ฅๆœ‰ **ๅคšไธช HTTPS ่ฏไนฆ** ๅนถๆไพ› **ๅคšไธช HTTPS ๅŸŸๅ/ๅบ”็”จ็จ‹ๅบ**ใ€‚ + * ไธบๆญค๏ผŒๆœๅŠกๅ™จไธŠไผšๆœ‰**ๅ•็‹ฌ**็š„ไธ€ไธช็ป„ไปถ๏ผˆ็จ‹ๅบ๏ผ‰ไพฆๅฌ**ๅ…ฌๅ…ฑ IP ๅœฐๅ€**๏ผŒ่ฟ™ไธช็ป„ไปถๅฟ…้กปๆ‹ฅๆœ‰ๆœๅŠกๅ™จไธญ็š„**ๆ‰€ๆœ‰ HTTPS ่ฏไนฆ**ใ€‚ * **่Žทๅพ—ๅฎ‰ๅ…จ่ฟžๆŽฅๅŽ**๏ผŒ้€šไฟกๅ่ฎฎ**ไป็„ถๆ˜ฏHTTP**ใ€‚ - * ๅ†…ๅฎนๆ˜ฏ **ๅŠ ๅฏ†่ฟ‡็š„**๏ผŒๅณไฝฟๅฎƒไปฌๆ˜ฏ้€š่ฟ‡ **HTTP ๅ่ฎฎ** ๅ‘้€็š„ใ€‚ + * ๅ†…ๅฎนๆ˜ฏ **ๅŠ ๅฏ†่ฟ‡็š„**๏ผŒๅณไฝฟๅฎƒไปฌๆ˜ฏ้€š่ฟ‡ **HTTP ๅ่ฎฎ** ๅ‘้€็š„ใ€‚ ้€šๅธธ็š„ๅšๆณ•ๆ˜ฏๅœจๆœๅŠกๅ™จไธŠ่ฟ่กŒ**ไธ€ไธช็จ‹ๅบ/HTTP ๆœๅŠกๅ™จ**ๅนถ**็ฎก็†ๆ‰€ๆœ‰ HTTPS ้ƒจๅˆ†**๏ผšๆŽฅๆ”ถ**ๅŠ ๅฏ†็š„ HTTPS ่ฏทๆฑ‚**๏ผŒ ๅฐ† **่งฃๅฏ†็š„ HTTP ่ฏทๆฑ‚** ๅ‘้€ๅˆฐๅœจๅŒไธ€ๆœๅŠกๅ™จไธญ่ฟ่กŒ็š„ๅฎž้™… HTTP ๅบ”็”จ็จ‹ๅบ๏ผˆๅœจๆœฌไพ‹ไธญไธบ **FastAPI** ๅบ”็”จ็จ‹ๅบ๏ผ‰๏ผŒไปŽๅบ”็”จ็จ‹ๅบไธญ่Žทๅ– **HTTP ๅ“ๅบ”**๏ผŒ ไฝฟ็”จ้€‚ๅฝ“็š„ **HTTPS ่ฏไนฆ**ๅฏนๅ…ถ่ฟ›่กŒๅŠ ๅฏ†ๅนถไฝฟ็”จ **HTTPS** ๅฐ†ๅ…ถๅ‘้€ๅ›žๅฎขๆˆท็ซฏใ€‚ ๆญคๆœๅŠกๅ™จ้€šๅธธ่ขซ็งฐไธบ **TLS ็ปˆๆญขไปฃ็†(TLS Termination Proxy)**ใ€‚ @@ -43,7 +43,7 @@ * Nginx * HAProxy -## Let's Encrypt +## Let's Encrypt { #lets-encrypt } ๅœจ Let's Encrypt ไน‹ๅ‰๏ผŒ่ฟ™ไบ› **HTTPS ่ฏไนฆ** ็”ฑๅ—ไฟกไปป็š„็ฌฌไธ‰ๆ–นๅ‡บๅ”ฎใ€‚ @@ -57,16 +57,15 @@ ๆˆ‘ไปฌ็š„ๆƒณๆณ•ๆ˜ฏ่‡ชๅŠจ่Žทๅ–ๅ’Œๆ›ดๆ–ฐ่ฟ™ไบ›่ฏไนฆ๏ผŒไปฅไพฟไฝ ๅฏไปฅๆฐธ่ฟœๅ…่ดนๆ‹ฅๆœ‰**ๅฎ‰ๅ…จ็š„ HTTPS**ใ€‚ -## ้ขๅ‘ๅผ€ๅ‘ไบบๅ‘˜็š„ HTTPS +## ้ขๅ‘ๅผ€ๅ‘ไบบๅ‘˜็š„ HTTPS { #https-for-developers } ่ฟ™้‡Œๆœ‰ไธ€ไธช HTTPS API ็œ‹่ตทๆฅๆ˜ฏไป€ไนˆๆ ท็š„็คบไพ‹๏ผŒๆˆ‘ไปฌไผšๅˆ†ๆญฅ่ฏดๆ˜Ž๏ผŒๅนถไธ”ไธป่ฆๅ…ณๆณจๅฏนๅผ€ๅ‘ไบบๅ‘˜้‡่ฆ็š„้ƒจๅˆ†ใ€‚ - -### ๅŸŸๅ +### ๅŸŸๅ { #domain-name } ็ฌฌไธ€ๆญฅๆˆ‘ไปฌ่ฆๅ…ˆ**่Žทๅ–**ไธ€ไบ›**ๅŸŸๅ(Domain Name)**ใ€‚ ็„ถๅŽๅฏไปฅๅœจ DNS ๆœๅŠกๅ™จ๏ผˆๅฏ่ƒฝๆ˜ฏไฝ ็š„ๅŒไธ€ๅฎถไบ‘ๆœๅŠกๅ•†ๆไพ›็š„๏ผ‰ไธญ้…็ฝฎๅฎƒใ€‚ -ไฝ ๅฏ่ƒฝๆ‹ฅๆœ‰ไธ€ไธชไบ‘ๆœๅŠกๅ™จ๏ผˆ่™šๆ‹Ÿๆœบ๏ผ‰ๆˆ–็ฑปไผผ็š„ไธœ่ฅฟ๏ผŒๅนถไธ”ๅฎƒไผšๆœ‰ไธ€ไธชๅ›บๅฎš **ๅ…ฌๅ…ฑIPๅœฐๅ€**ใ€‚ +ไฝ ๅฏ่ƒฝๆ‹ฅๆœ‰ไธ€ไธชไบ‘ๆœๅŠกๅ™จ๏ผˆ่™šๆ‹Ÿๆœบ๏ผ‰ๆˆ–็ฑปไผผ็š„ไธœ่ฅฟ๏ผŒๅนถไธ”ๅฎƒไผšๆœ‰ไธ€ไธชๅ›บๅฎš **ๅ…ฌๅ…ฑIPๅœฐๅ€**ใ€‚ ๅœจ DNS ๆœๅŠกๅ™จไธญ๏ผŒไฝ ๅฏไปฅ้…็ฝฎไธ€ๆก่ฎฐๅฝ•๏ผˆโ€œA ่ฎฐๅฝ•โ€๏ผ‰ไปฅๅฐ† **ไฝ ็š„ๅŸŸๅ** ๆŒ‡ๅ‘ไฝ ๆœๅŠกๅ™จ็š„ๅ…ฌๅ…ฑ **IP ๅœฐๅ€**ใ€‚ @@ -78,7 +77,7 @@ /// -### DNS +### DNS { #dns } ็Žฐๅœจ่ฎฉๆˆ‘ไปฌๅ…ณๆณจ็œŸๆญฃ็š„ HTTPS ้ƒจๅˆ†ใ€‚ @@ -88,7 +87,7 @@ DNS ๆœๅŠกๅ™จไผšๅ‘Š่ฏ‰ๆต่งˆๅ™จไฝฟ็”จๆŸไธช็‰นๅฎš็š„ **IP ๅœฐๅ€**ใ€‚ ่ฟ™ๅฐ†ๆ˜ฏ -### TLS ๆกๆ‰‹ๅผ€ๅง‹ +### TLS ๆกๆ‰‹ๅผ€ๅง‹ { #tls-handshake-start } ็„ถๅŽ๏ผŒๆต่งˆๅ™จๅฐ†ๅœจ**็ซฏๅฃ 443**๏ผˆHTTPS ็ซฏๅฃ๏ผ‰ไธŠไธŽ่ฏฅ IP ๅœฐๅ€่ฟ›่กŒ้€šไฟกใ€‚ @@ -98,7 +97,7 @@ DNS ๆœๅŠกๅ™จไผšๅ‘Š่ฏ‰ๆต่งˆๅ™จไฝฟ็”จๆŸไธช็‰นๅฎš็š„ **IP ๅœฐๅ€**ใ€‚ ่ฟ™ๅฐ†ๆ˜ฏ ๅฎขๆˆท็ซฏๅ’ŒๆœๅŠกๅ™จไน‹้—ดๅปบ็ซ‹ TLS ่ฟžๆŽฅ็š„่ฟ‡็จ‹็งฐไธบ **TLS ๆกๆ‰‹**ใ€‚ -### ๅธฆๆœ‰ SNI ๆ‰ฉๅฑ•็š„ TLS +### ๅธฆๆœ‰ SNI ๆ‰ฉๅฑ•็š„ TLS { #tls-with-sni-extension } **ๆœๅŠกๅ™จไธญๅชๆœ‰ไธ€ไธช่ฟ›็จ‹**ๅฏไปฅไพฆๅฌ็‰นๅฎš **IP ๅœฐๅ€**็š„็‰นๅฎš **็ซฏๅฃ**ใ€‚ ๅฏ่ƒฝๆœ‰ๅ…ถไป–่ฟ›็จ‹ๅœจๅŒไธ€ IP ๅœฐๅ€็š„ๅ…ถไป–็ซฏๅฃไธŠไพฆๅฌ๏ผŒไฝ†ๆฏไธช IP ๅœฐๅ€ๅ’Œ็ซฏๅฃ็ป„ๅˆๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ใ€‚ @@ -128,7 +127,7 @@ TLS ็ปˆๆญขไปฃ็†ๅฏไปฅ่ฎฟ้—ฎไธ€ไธชๆˆ–ๅคšไธช **TLS ่ฏไนฆ**๏ผˆHTTPS ่ฏไนฆ๏ผ‰ใ€‚ /// -### HTTPS ่ฏทๆฑ‚ +### HTTPS ่ฏทๆฑ‚ { #https-request } ็Žฐๅœจๅฎขๆˆท็ซฏๅ’ŒๆœๅŠกๅ™จ๏ผˆ็‰นๅˆซๆ˜ฏๆต่งˆๅ™จๅ’Œ TLS ็ปˆๆญขไปฃ็†๏ผ‰ๅ…ทๆœ‰ **ๅŠ ๅฏ†็š„ TCP ่ฟžๆŽฅ**๏ผŒๅฎƒไปฌๅฏไปฅๅผ€ๅง‹ **HTTP ้€šไฟก**ใ€‚ @@ -136,19 +135,19 @@ TLS ็ปˆๆญขไปฃ็†ๅฏไปฅ่ฎฟ้—ฎไธ€ไธชๆˆ–ๅคšไธช **TLS ่ฏไนฆ**๏ผˆHTTPS ่ฏไนฆ๏ผ‰ใ€‚ -### ่งฃๅฏ†่ฏทๆฑ‚ +### ่งฃๅฏ†่ฏทๆฑ‚ { #decrypt-the-request } TLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จๅๅ•†ๅฅฝ็š„ๅŠ ๅฏ†็ฎ—ๆณ•**่งฃๅฏ†่ฏทๆฑ‚**๏ผŒๅนถๅฐ†**๏ผˆ่งฃๅฏ†็š„๏ผ‰HTTP ่ฏทๆฑ‚**ไผ ่พ“ๅˆฐ่ฟ่กŒๅบ”็”จ็จ‹ๅบ็š„่ฟ›็จ‹๏ผˆไพ‹ๅฆ‚่ฟ่กŒ FastAPI ๅบ”็”จ็š„ Uvicorn ่ฟ›็จ‹๏ผ‰ใ€‚ -### HTTP ๅ“ๅบ” +### HTTP ๅ“ๅบ” { #http-response } ๅบ”็”จ็จ‹ๅบๅฐ†ๅค„็†่ฏทๆฑ‚ๅนถๅ‘ TLS ็ปˆๆญขไปฃ็†ๅ‘้€**๏ผˆๆœชๅŠ ๅฏ†๏ผ‰HTTP ๅ“ๅบ”**ใ€‚ -### HTTPS ๅ“ๅบ” +### HTTPS ๅ“ๅบ” { #https-response } ็„ถๅŽ๏ผŒTLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จไน‹ๅ‰ๅๅ•†็š„ๅŠ ๅฏ†็ฎ—ๆณ•๏ผˆไปฅ`someapp.example.com`็š„่ฏไนฆๅผ€ๅคด๏ผ‰ๅฏนๅ“ๅบ”่ฟ›่กŒๅŠ ๅฏ†๏ผŒๅนถๅฐ†ๅ…ถๅ‘้€ๅ›žๆต่งˆๅ™จใ€‚ @@ -158,7 +157,7 @@ TLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จๅๅ•†ๅฅฝ็š„ๅŠ ๅฏ†็ฎ—ๆณ•**่งฃๅฏ†่ฏทๆฑ‚**๏ผŒๅนถๅฐ†**๏ผˆ ๅฎขๆˆท็ซฏ๏ผˆๆต่งˆๅ™จ๏ผ‰ๅฐ†็Ÿฅ้“ๅ“ๅบ”ๆฅ่‡ชๆญฃ็กฎ็š„ๆœๅŠกๅ™จ๏ผŒๅ› ไธบๅฎƒไฝฟ็”จไบ†ไป–ไปฌไน‹ๅ‰ไฝฟ็”จ **HTTPS ่ฏไนฆ** ๅๅ•†ๅ‡บ็š„ๅŠ ๅฏ†็ฎ—ๆณ•ใ€‚ -### ๅคšไธชๅบ”็”จ็จ‹ๅบ +### ๅคšไธชๅบ”็”จ็จ‹ๅบ { #multiple-applications } ๅœจๅŒไธ€ๅฐ๏ผˆๆˆ–ๅคšๅฐ๏ผ‰ๆœๅŠกๅ™จไธญ๏ผŒๅฏ่ƒฝๅญ˜ๅœจ**ๅคšไธชๅบ”็”จ็จ‹ๅบ**๏ผŒไพ‹ๅฆ‚ๅ…ถไป– API ็จ‹ๅบๆˆ–ๆ•ฐๆฎๅบ“ใ€‚ @@ -168,7 +167,7 @@ TLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จๅๅ•†ๅฅฝ็š„ๅŠ ๅฏ†็ฎ—ๆณ•**่งฃๅฏ†่ฏทๆฑ‚**๏ผŒๅนถๅฐ†**๏ผˆ ่ฟ™ๆ ท๏ผŒTLS ็ปˆๆญขไปฃ็†ๅฐฑๅฏไปฅไธบๅคšไธชๅบ”็”จ็จ‹ๅบๅค„็†**ๅคšไธชๅŸŸๅ**็š„ HTTPS ๅ’Œ่ฏไนฆ๏ผŒ็„ถๅŽๅœจๆฏ็งๆƒ…ๅ†ตไธ‹ๅฐ†่ฏทๆฑ‚ไผ ่พ“ๅˆฐๆญฃ็กฎ็š„ๅบ”็”จ็จ‹ๅบใ€‚ -### ่ฏไนฆๆ›ดๆ–ฐ +### ่ฏไนฆๆ›ดๆ–ฐ { #certificate-renewal } ๅœจๆœชๆฅ็š„ๆŸไธชๆ—ถๅ€™๏ผŒๆฏไธช่ฏไนฆ้ƒฝไผš**่ฟ‡ๆœŸ**๏ผˆๅคง็บฆๅœจ่Žทๅพ—่ฏไนฆๅŽ 3 ไธชๆœˆ๏ผ‰ใ€‚ @@ -183,16 +182,48 @@ TLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จๅๅ•†ๅฅฝ็š„ๅŠ ๅฏ†็ฎ—ๆณ•**่งฃๅฏ†่ฏทๆฑ‚**๏ผŒๅนถๅฐ†**๏ผˆ ๆœ‰ๅคš็งๆ–นๆณ•ๅฏไปฅๅšๅˆฐ่ฟ™ไธ€็‚นใ€‚ ไธ€ไบ›ๆต่กŒ็š„ๆ–นๅผๆ˜ฏ๏ผš * **ไฟฎๆ”นไธ€ไบ›DNS่ฎฐๅฝ•**ใ€‚ - * ไธบๆญค๏ผŒ็ปญ่ฎข็จ‹ๅบ้œ€่ฆๆ”ฏๆŒ DNS ๆไพ›ๅ•†็š„ API๏ผŒๅ› ๆญค๏ผŒ่ฆ็œ‹ไฝ ไฝฟ็”จ็š„ DNS ๆไพ›ๅ•†ๆ˜ฏๅฆๆไพ›่ฟ™ไธ€ๅŠŸ่ƒฝใ€‚ + * ไธบๆญค๏ผŒ็ปญ่ฎข็จ‹ๅบ้œ€่ฆๆ”ฏๆŒ DNS ๆไพ›ๅ•†็š„ API๏ผŒๅ› ๆญค๏ผŒ่ฆ็œ‹ไฝ ไฝฟ็”จ็š„ DNS ๆไพ›ๅ•†ๆ˜ฏๅฆๆไพ›่ฟ™ไธ€ๅŠŸ่ƒฝใ€‚ * **ๅœจไธŽๅŸŸๅๅ…ณ่”็š„ๅ…ฌๅ…ฑ IP ๅœฐๅ€ไธŠไฝœไธบๆœๅŠกๅ™จ่ฟ่กŒ**๏ผˆ่‡ณๅฐ‘ๅœจ่ฏไนฆ่Žทๅ–่ฟ‡็จ‹ไธญ๏ผ‰ใ€‚ - * ๆญฃๅฆ‚ๆˆ‘ไปฌไธŠ้ขๆ‰€่ฏด๏ผŒๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ๅฏไปฅ็›‘ๅฌ็‰นๅฎš็š„ IP ๅ’Œ็ซฏๅฃใ€‚ - * ่ฟ™ๅฐฑๆ˜ฏๅฝ“ๅŒไธ€ไธช TLS ็ปˆๆญขไปฃ็†่ฟ˜่ดŸ่ดฃ่ฏไนฆ็ปญ่ฎข่ฟ‡็จ‹ๆ—ถๅฎƒ้žๅธธๆœ‰็”จ็š„ๅŽŸๅ› ไน‹ไธ€ใ€‚ - * ๅฆๅˆ™๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆๆš‚ๆ—ถๅœๆญข TLS ็ปˆๆญขไปฃ็†๏ผŒๅฏๅŠจ็ปญ่ฎข็จ‹ๅบไปฅ่Žทๅ–่ฏไนฆ๏ผŒ็„ถๅŽไฝฟ็”จ TLS ็ปˆๆญขไปฃ็†้…็ฝฎๅฎƒไปฌ๏ผŒ็„ถๅŽ้‡ๆ–ฐๅฏๅŠจ TLS ็ปˆๆญขไปฃ็†ใ€‚ ่ฟ™ๅนถไธ็†ๆƒณ๏ผŒๅ› ไธบไฝ ็š„ๅบ”็”จ็จ‹ๅบๅœจ TLS ็ปˆๆญขไปฃ็†ๅ…ณ้—ญๆœŸ้—ดๅฐ†ไธๅฏ็”จใ€‚ + * ๆญฃๅฆ‚ๆˆ‘ไปฌไธŠ้ขๆ‰€่ฏด๏ผŒๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ๅฏไปฅ็›‘ๅฌ็‰นๅฎš็š„ IP ๅ’Œ็ซฏๅฃใ€‚ + * ่ฟ™ๅฐฑๆ˜ฏๅฝ“ๅŒไธ€ไธช TLS ็ปˆๆญขไปฃ็†่ฟ˜่ดŸ่ดฃ่ฏไนฆ็ปญ่ฎข่ฟ‡็จ‹ๆ—ถๅฎƒ้žๅธธๆœ‰็”จ็š„ๅŽŸๅ› ไน‹ไธ€ใ€‚ + * ๅฆๅˆ™๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆๆš‚ๆ—ถๅœๆญข TLS ็ปˆๆญขไปฃ็†๏ผŒๅฏๅŠจ็ปญ่ฎข็จ‹ๅบไปฅ่Žทๅ–่ฏไนฆ๏ผŒ็„ถๅŽไฝฟ็”จ TLS ็ปˆๆญขไปฃ็†้…็ฝฎๅฎƒไปฌ๏ผŒ็„ถๅŽ้‡ๆ–ฐๅฏๅŠจ TLS ็ปˆๆญขไปฃ็†ใ€‚ ่ฟ™ๅนถไธ็†ๆƒณ๏ผŒๅ› ไธบไฝ ็š„ๅบ”็”จ็จ‹ๅบๅœจ TLS ็ปˆๆญขไปฃ็†ๅ…ณ้—ญๆœŸ้—ดๅฐ†ไธๅฏ็”จใ€‚ ้€š่ฟ‡ๆ‹ฅๆœ‰ไธ€ไธช**ๅ•็‹ฌ็š„็ณป็ปŸๆฅไฝฟ็”จ TLS ็ปˆๆญขไปฃ็†ๆฅๅค„็† HTTPS**, ่€Œไธๆ˜ฏ็›ดๆŽฅๅฐ† TLS ่ฏไนฆไธŽๅบ”็”จ็จ‹ๅบๆœๅŠกๅ™จไธ€่ตทไฝฟ็”จ ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰,ไฝ ๅฏไปฅๅœจ ๆ›ดๆ–ฐ่ฏไนฆ็š„่ฟ‡็จ‹ไธญๅŒๆ—ถไฟๆŒๆไพ›ๆœๅŠกใ€‚ -## ๅ›ž้กพ +## ไปฃ็†่ฝฌๅ‘่ฏทๆฑ‚ๅคด { #proxy-forwarded-headers } + +ๅฝ“ไฝฟ็”จไปฃ็†ๆฅๅค„็† HTTPS ๆ—ถ๏ผŒไฝ ็š„**ๅบ”็”จๆœๅŠกๅ™จ**๏ผˆไพ‹ๅฆ‚้€š่ฟ‡ FastAPI CLI ่ฟ่กŒ็š„ Uvicorn๏ผ‰ๅฏน HTTPS ่ฟ‡็จ‹ๅนถไธไบ†่งฃ๏ผŒๅฎƒๅช้€š่ฟ‡็บฏ HTTP ไธŽ **TLS ็ปˆๆญขไปฃ็†**้€šไฟกใ€‚ + +่ฟ™ไธช**ไปฃ็†**้€šๅธธไผšๅœจๅฐ†่ฏทๆฑ‚่ฝฌๅ‘็ป™**ๅบ”็”จๆœๅŠกๅ™จ**ไน‹ๅ‰๏ผŒไธดๆ—ถ่ฎพ็ฝฎไธ€ไบ› HTTP ่ฏทๆฑ‚ๅคด๏ผŒไปฅไพฟ่ฎฉๅบ”็”จๆœๅŠกๅ™จ็Ÿฅ้“่ฏฅ่ฏทๆฑ‚ๆ˜ฏ็”ฑไปฃ็†**่ฝฌๅ‘**่ฟ‡ๆฅ็š„ใ€‚ + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +่ฟ™ไบ›ไปฃ็†่ฏทๆฑ‚ๅคดๅŒ…ๆ‹ฌ๏ผš + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +ไธ่ฟ‡๏ผŒ็”ฑไบŽ**ๅบ”็”จๆœๅŠกๅ™จ**ๅนถไธ็Ÿฅ้“่‡ชๅทฑไฝไบŽๅ—ไฟกไปป็š„**ไปฃ็†**ไน‹ๅŽ๏ผŒ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒไธไผšไฟกไปป่ฟ™ไบ›่ฏทๆฑ‚ๅคดใ€‚ + +ไฝ†ไฝ ๅฏไปฅ้…็ฝฎ**ๅบ”็”จๆœๅŠกๅ™จ**ๅŽปไฟกไปป็”ฑ**ไปฃ็†**ๅ‘้€็š„่ฟ™ไบ›โ€œ่ฝฌๅ‘โ€่ฏทๆฑ‚ๅคดใ€‚ๅฆ‚ๆžœไฝ ๅœจไฝฟ็”จ FastAPI CLI๏ผŒๅฏไปฅไฝฟ็”จๅ‘ฝไปค่กŒ้€‰้กน `--forwarded-allow-ips` ๆŒ‡ๅฎšๅฎƒๅบ”่ฏฅไฟกไปปๅ“ชไบ› IP ๅ‘ๆฅ็š„่ฟ™ไบ›โ€œ่ฝฌๅ‘โ€่ฏทๆฑ‚ๅคดใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ**ๅบ”็”จๆœๅŠกๅ™จ**ๅชๆŽฅๆ”ถๆฅ่‡ชๅ—ไฟกไปป**ไปฃ็†**็š„้€šไฟก๏ผŒไฝ ๅฏไปฅ่ฎพ็ฝฎ `--forwarded-allow-ips="*"`๏ผŒ่ฎฉๅฎƒไฟกไปปๆ‰€ๆœ‰ไผ ๅ…ฅ็š„ IP๏ผŒๅ› ไธบๅฎƒๅชไผšๆŽฅๆ”ถๆฅ่‡ช**ไปฃ็†**ๆ‰€ไฝฟ็”จ IP ็š„่ฏทๆฑ‚ใ€‚ + +่ฟ™ๆ ท๏ผŒๅบ”็”จๅฐฑ่ƒฝ็Ÿฅ้“่‡ชๅทฑ็š„ๅ…ฌๅ…ฑ URLใ€ๆ˜ฏๅฆไฝฟ็”จ HTTPSใ€ๅŸŸๅ็ญ‰ไฟกๆฏใ€‚ + +่ฟ™ๅœจ้œ€่ฆๆญฃ็กฎๅค„็†้‡ๅฎšๅ‘็ญ‰ๅœบๆ™ฏๆ—ถๅพˆๆœ‰็”จใ€‚ + +/// tip + +ไฝ ๅฏไปฅๅœจๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคš๏ผš[ๅœจไปฃ็†ไน‹ๅŽ - ๅฏ็”จไปฃ็†่ฝฌๅ‘่ฏทๆฑ‚ๅคด](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} + +/// + +## ๅ›ž้กพ { #recap } ๆ‹ฅๆœ‰**HTTPS** ้žๅธธ้‡่ฆ๏ผŒๅนถไธ”ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹็›ธๅฝ“**ๅ…ณ้”ฎ**ใ€‚ ไฝœไธบๅผ€ๅ‘ไบบๅ‘˜๏ผŒไฝ ๅ›ด็ป• HTTPS ๆ‰€ๅš็š„ๅคง้ƒจๅˆ†ๅŠชๅŠ›ๅฐฑๆ˜ฏ**็†่งฃ่ฟ™ไบ›ๆฆ‚ๅฟต**ไปฅๅŠๅฎƒไปฌ็š„ๅทฅไฝœๅŽŸ็†ใ€‚ diff --git a/docs/zh/docs/deployment/index.md b/docs/zh/docs/deployment/index.md index 1ec0c5c5b5..47dcede653 100644 --- a/docs/zh/docs/deployment/index.md +++ b/docs/zh/docs/deployment/index.md @@ -1,21 +1,23 @@ -# ้ƒจ็ฝฒ +# ้ƒจ็ฝฒ { #deployment } ้ƒจ็ฝฒ **FastAPI** ๅบ”็”จ็จ‹ๅบ็›ธๅฏนๅฎนๆ˜“ใ€‚ -## ้ƒจ็ฝฒๆ˜ฏไป€ไนˆๆ„ๆ€ +## ้ƒจ็ฝฒๆ˜ฏไป€ไนˆๆ„ๆ€ { #what-does-deployment-mean } **้ƒจ็ฝฒ**ๅบ”็”จ็จ‹ๅบๆ„ๅ‘ณ็€ๆ‰ง่กŒๅฟ…่ฆ็š„ๆญฅ้ชคไปฅไฝฟๅ…ถ**ๅฏไพ›็”จๆˆทไฝฟ็”จ**ใ€‚ -ๅฏนไบŽ**Web API**ๆฅ่ฏด๏ผŒ้€šๅธธๆถ‰ๅŠๅฐ†ไธŠไผ ๅˆฐ**ไบ‘ๆœๅŠกๅ™จ**ไธญ๏ผŒๆญ้…ไธ€ไธชๆ€ง่ƒฝๅ’Œ็จณๅฎšๆ€ง้ƒฝไธ้”™็š„**ๆœๅŠกๅ™จ็จ‹ๅบ**๏ผŒไปฅไพฟไฝ ็š„**็”จๆˆท**ๅฏไปฅ้ซ˜ๆ•ˆๅœฐ**่ฎฟ้—ฎ**ไฝ ็š„ๅบ”็”จ็จ‹ๅบ๏ผŒ่€Œไธไผšๅ‡บ็Žฐไธญๆ–ญๆˆ–ๅ…ถไป–้—ฎ้ข˜ใ€‚ +ๅฏนไบŽ**Web API**ๆฅ่ฏด๏ผŒ้€šๅธธๆถ‰ๅŠๅฐ†ๅ…ถๆ”พๅˆฐไธ€ๅฐ**่ฟœ็จ‹ๆœบๅ™จ**ไธญ๏ผŒๆญ้…ไธ€ไธชๆ€ง่ƒฝๅ’Œ็จณๅฎšๆ€ง้ƒฝไธ้”™็š„**ๆœๅŠกๅ™จ็จ‹ๅบ**๏ผŒไปฅไพฟไฝ ็š„**็”จๆˆท**ๅฏไปฅ้ซ˜ๆ•ˆๅœฐ**่ฎฟ้—ฎ**ไฝ ็š„ๅบ”็”จ็จ‹ๅบ๏ผŒ่€Œไธไผšๅ‡บ็Žฐไธญๆ–ญๆˆ–ๅ…ถไป–้—ฎ้ข˜ใ€‚ -่ฟ™ไธŽ**ๅผ€ๅ‘**้˜ถๆฎตๅฝขๆˆ้ฒœๆ˜Žๅฏนๆฏ”๏ผŒๅœจ**ๅผ€ๅ‘**้˜ถๆฎต๏ผŒไฝ ไธๆ–ญๆ›ดๆ”นไปฃ็ ใ€็ ดๅไปฃ็ ใ€ไฟฎๅคไปฃ็ , ๆฅๅ›žๅœๆญขๅ’Œ้‡ๅฏๆœๅŠกๅ™จ็ญ‰ใ€‚ +่ฟ™ไธŽ**ๅผ€ๅ‘**้˜ถๆฎตๅฝขๆˆ้ฒœๆ˜Žๅฏนๆฏ”๏ผŒๅœจ**ๅผ€ๅ‘**้˜ถๆฎต๏ผŒไฝ ไธๆ–ญๆ›ดๆ”นไปฃ็ ใ€็ ดๅไปฃ็ ใ€ไฟฎๅคไปฃ็ ๏ผŒๆฅๅ›žๅœๆญขๅ’Œ้‡ๅฏๅผ€ๅ‘ๆœๅŠกๅ™จ็ญ‰ใ€‚ -## ้ƒจ็ฝฒ็ญ–็•ฅ +## ้ƒจ็ฝฒ็ญ–็•ฅ { #deployment-strategies } ๆ นๆฎไฝ ็š„ไฝฟ็”จๅœบๆ™ฏๅ’Œไฝฟ็”จ็š„ๅทฅๅ…ท๏ผŒๆœ‰ๅคš็งๆ–นๆณ•ๅฏไปฅๅฎž็Žฐๆญค็›ฎ็š„ใ€‚ ไฝ ๅฏไปฅไฝฟ็”จไธ€ไบ›ๅทฅๅ…ท่‡ช่กŒ**้ƒจ็ฝฒๆœๅŠกๅ™จ**๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ่ƒฝไธบไฝ ๅฎŒๆˆ้ƒจๅˆ†ๅทฅไฝœ็š„**ไบ‘ๆœๅŠก**๏ผŒๆˆ–ๅ…ถไป–ๅฏ่ƒฝ็š„้€‰้กนใ€‚ +ไพ‹ๅฆ‚๏ผŒๆˆ‘ไปฌ๏ผˆFastAPI ๅ›ข้˜Ÿ๏ผ‰ๆž„ๅปบไบ† **FastAPI Cloud**๏ผŒ่ฎฉๅฐ† FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐไบ‘็ซฏๅฐฝๅฏ่ƒฝๆต็•…๏ผŒๅนถไธ”ไฟๆŒไธŽไฝฟ็”จ FastAPI ๅผ€ๅ‘ๆ—ถ็›ธๅŒ็š„ๅผ€ๅ‘่€…ไฝ“้ชŒใ€‚ + ๆˆ‘ๅฐ†ๅ‘ไฝ ๅฑ•็คบๅœจ้ƒจ็ฝฒ **FastAPI** ๅบ”็”จ็จ‹ๅบๆ—ถไฝ ๅฏ่ƒฝๅบ”่ฏฅ่ฎฐไฝ็š„ไธ€ไบ›ไธป่ฆๆฆ‚ๅฟต๏ผˆๅฐฝ็ฎกๅ…ถไธญๅคง้ƒจๅˆ†้€‚็”จไบŽไปปไฝ•ๅ…ถไป–็ฑปๅž‹็š„ Web ๅบ”็”จ็จ‹ๅบ๏ผ‰ใ€‚ ๅœจๆŽฅไธ‹ๆฅ็š„้ƒจๅˆ†ไธญ๏ผŒไฝ ๅฐ†็œ‹ๅˆฐๆ›ดๅคš้œ€่ฆ่ฎฐไฝ็š„็ป†่Š‚ไปฅๅŠไธ€ไบ›ๆŠ€ๅทงใ€‚ โœจ diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index 2c2784a640..6f2ad27b2f 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -1,6 +1,6 @@ -# ๆ‰‹ๅŠจ่ฟ่กŒๆœๅŠกๅ™จ +# ๆ‰‹ๅŠจ่ฟ่กŒๆœๅŠกๅ™จ { #run-a-server-manually } -## ไฝฟ็”จ `fastapi run` ๅ‘ฝไปค +## ไฝฟ็”จ `fastapi run` ๅ‘ฝไปค { #use-the-fastapi-run-command } ็ฎ€่€Œ่จ€ไน‹๏ผŒไฝฟ็”จ `fastapi run` ๆฅ่ฟ่กŒๆ‚จ็š„ FastAPI ๅบ”็”จ็จ‹ๅบ๏ผš @@ -42,11 +42,11 @@ $ fastapi run ASGIใ€‚FastAPI ๆœฌ่ดจไธŠๆ˜ฏไธ€ไธช ASGI Web ๆก†ๆžถใ€‚ +FastAPI ไฝฟ็”จไบ†ไธ€็ง็”จไบŽๆž„ๅปบ Python Web ๆก†ๆžถๅ’ŒๆœๅŠกๅ™จ็š„ๆ ‡ๅ‡†๏ผŒ็งฐไธบ ASGIใ€‚FastAPI ๆœฌ่ดจไธŠๆ˜ฏไธ€ไธช ASGI Web ๆก†ๆžถใ€‚ ่ฆๅœจ่ฟœ็จ‹ๆœๅŠกๅ™จไธŠ่ฟ่กŒ **FastAPI** ๅบ”็”จ๏ผˆๆˆ–ไปปไฝ•ๅ…ถไป– ASGI ๅบ”็”จ๏ผ‰๏ผŒๆ‚จ้œ€่ฆไธ€ไธช ASGI ๆœๅŠกๅ™จ็จ‹ๅบ๏ผŒไพ‹ๅฆ‚ **Uvicorn**ใ€‚ๅฎƒๆ˜ฏ `fastapi` ๅ‘ฝไปค้ป˜่ฎคไฝฟ็”จ็š„ ASGI ๆœๅŠกๅ™จใ€‚ @@ -58,7 +58,7 @@ FastAPI ไฝฟ็”จไบ†ไธ€็ง็”จไบŽๆž„ๅปบ Python Web ๆก†ๆžถๅ’ŒๆœๅŠกๅ™จ็š„ๆ ‡ๅ‡†๏ผŒ็งฐ * Granian๏ผšๅŸบไบŽ Rust ็š„ HTTP ๆœๅŠกๅ™จ๏ผŒไธ“ไธบ Python ๅบ”็”จ่ฎพ่ฎกใ€‚ * NGINX Unit๏ผšNGINX Unit ๆ˜ฏไธ€ไธช่ฝป้‡็บงไธ”็ตๆดป็š„ Web ๅบ”็”จ่ฟ่กŒๆ—ถ็Žฏๅขƒใ€‚ -## ๆœๅŠกๅ™จไธปๆœบๅ’ŒๆœๅŠกๅ™จ็จ‹ๅบ +## ๆœๅŠกๅ™จไธปๆœบๅ’ŒๆœๅŠกๅ™จ็จ‹ๅบ { #server-machine-and-server-program } ๅ…ณไบŽๅ็งฐ๏ผŒๆœ‰ไธ€ไธชๅฐ็ป†่Š‚้œ€่ฆ่ฎฐไฝใ€‚ ๐Ÿ’ก @@ -68,8 +68,7 @@ FastAPI ไฝฟ็”จไบ†ไธ€็ง็”จไบŽๆž„ๅปบ Python Web ๆก†ๆžถๅ’ŒๆœๅŠกๅ™จ็š„ๆ ‡ๅ‡†๏ผŒ็งฐ ๅฝ“ๆๅˆฐ่ฟœ็จ‹ไธปๆœบๆ—ถ๏ผŒ้€šๅธธๅฐ†ๅ…ถ็งฐไธบ**ๆœๅŠกๅ™จ**๏ผŒไฝ†ไนŸ็งฐไธบ**ๆœบๅ™จ**(machine)ใ€**VM**๏ผˆ่™šๆ‹Ÿๆœบ๏ผ‰ใ€**่Š‚็‚น**ใ€‚ ่ฟ™ไบ›้ƒฝๆ˜ฏๆŒ‡ๆŸ็ง็ฑปๅž‹็š„่ฟœ็จ‹่ฎก็ฎ—ๆœบ๏ผŒ้€šๅธธ่ฟ่กŒ Linux๏ผŒๆ‚จๅฏไปฅๅœจๅ…ถไธญ่ฟ่กŒ็จ‹ๅบใ€‚ - -## ๅฎ‰่ฃ…ๆœๅŠกๅ™จ็จ‹ๅบ +## ๅฎ‰่ฃ…ๆœๅŠกๅ™จ็จ‹ๅบ { #install-the-server-program } ๅฝ“ๆ‚จๅฎ‰่ฃ… FastAPI ๆ—ถ๏ผŒๅฎƒ่‡ชๅธฆไธ€ไธช็”Ÿไบง็ŽฏๅขƒๆœๅŠกๅ™จโ€”โ€”Uvicorn๏ผŒๅนถไธ”ๆ‚จๅฏไปฅไฝฟ็”จ `fastapi run` ๅ‘ฝไปคๆฅๅฏๅŠจๅฎƒใ€‚ @@ -101,7 +100,7 @@ $ pip install "uvicorn[standard]" /// -## ่ฟ่กŒๆœๅŠกๅ™จ็จ‹ๅบ +## ่ฟ่กŒๆœๅŠกๅ™จ็จ‹ๅบ { #run-the-server-program } ๅฆ‚ๆžœๆ‚จๆ‰‹ๅŠจๅฎ‰่ฃ…ไบ† ASGI ๆœๅŠกๅ™จ๏ผŒ้€šๅธธ้œ€่ฆไปฅ็‰นๅฎšๆ ผๅผไผ ้€’ไธ€ไธชๅฏผๅ…ฅๅญ—็ฌฆไธฒ๏ผŒไปฅไพฟๆœๅŠกๅ™จ่ƒฝๅคŸๆญฃ็กฎๅฏผๅ…ฅๆ‚จ็š„ FastAPI ๅบ”็”จ๏ผš @@ -142,7 +141,7 @@ Uvicorn ๅ’Œๅ…ถไป–ๆœๅŠกๅ™จๆ”ฏๆŒ `--reload` ้€‰้กน๏ผŒ่ฏฅ้€‰้กนๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญ /// -## ้ƒจ็ฝฒๆฆ‚ๅฟต +## ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployment-concepts } ่ฟ™ไบ›็คบไพ‹่ฟ่กŒๆœๅŠกๅ™จ็จ‹ๅบ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰๏ผŒๅฏๅŠจ**ๅ•ไธช่ฟ›็จ‹**๏ผŒๅœจๆ‰€ๆœ‰ IP๏ผˆ`0.0.0.0`๏ผ‰ไธŠ็›‘ๅฌ้ข„ๅฎšไน‰็ซฏๅฃ๏ผˆไพ‹ๅฆ‚`80`๏ผ‰ใ€‚ diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md index e46ba7a09d..2bbd5d9b6a 100644 --- a/docs/zh/docs/deployment/server-workers.md +++ b/docs/zh/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# ๆœๅŠกๅ™จๅทฅไฝœ่ฟ›็จ‹๏ผˆWorkers๏ผ‰ - ไฝฟ็”จ Uvicorn ็š„ๅคšๅทฅไฝœ่ฟ›็จ‹ๆจกๅผ +# ๆœๅŠกๅ™จๅทฅไฝœ่ฟ›็จ‹๏ผˆWorkers๏ผ‰ - ไฝฟ็”จ Uvicorn ็š„ๅคšๅทฅไฝœ่ฟ›็จ‹ๆจกๅผ { #server-workers-uvicorn-with-workers } ่ฎฉๆˆ‘ไปฌๅ›ž้กพไธ€ไธ‹ไน‹ๅ‰็š„้ƒจ็ฝฒๆฆ‚ๅฟต๏ผš @@ -17,7 +17,7 @@ ๅœจๆœฌ็ซ ่Š‚ไธญ๏ผŒๆˆ‘ๅฐ†ๅ‘ๆ‚จๅฑ•็คบๅฆ‚ไฝ•ไฝฟ็”จ `fastapi` ๅ‘ฝไปคๆˆ–็›ดๆŽฅไฝฟ็”จ `uvicorn` ๅ‘ฝไปคไปฅ**ๅคšๅทฅไฝœ่ฟ›็จ‹ๆจกๅผ**่ฟ่กŒ **Uvicorn**ใ€‚ -/// info +/// info | ไฟกๆฏ ๅฆ‚ๆžœๆ‚จๆญฃๅœจไฝฟ็”จๅฎนๅ™จ๏ผŒไพ‹ๅฆ‚ Docker ๆˆ– Kubernetes๏ผŒๆˆ‘ๅฐ†ๅœจไธ‹ไธ€็ซ ไธญๅ‘Š่ฏ‰ๆ‚จๆ›ดๅคš็›ธๅ…ณไฟกๆฏ๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ @@ -25,7 +25,7 @@ /// -## ๅคšไธชๅทฅไฝœ่ฟ›็จ‹ +## ๅคšไธชๅทฅไฝœ่ฟ›็จ‹ { #multiple-workers } ๆ‚จๅฏไปฅไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนๆฅๅฏๅŠจๅคšไธชๅทฅไฝœ่ฟ›็จ‹๏ผš @@ -111,7 +111,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ๆ‚จ่ฟ˜ๅฏไปฅ็œ‹ๅˆฐๅฎƒๆ˜พ็คบไบ†ๆฏไธช่ฟ›็จ‹็š„ **PID**๏ผŒ็ˆถ่ฟ›็จ‹๏ผˆ่ฟ™ๆ˜ฏ**่ฟ›็จ‹็ฎก็†ๅ™จ**๏ผ‰็š„ PID ไธบ`27365`๏ผŒๆฏไธชๅทฅไฝœ่ฟ›็จ‹็š„ PID ไธบ๏ผš`27368`ใ€`27369`๏ผŒ `27370`ๅ’Œ`27367`ใ€‚ -## ้ƒจ็ฝฒๆฆ‚ๅฟต +## ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployment-concepts } ๅœจ่ฟ™้‡Œ๏ผŒๆ‚จๅญฆไน ไบ†ๅฆ‚ไฝ•ไฝฟ็”จๅคšไธช**ๅทฅไฝœ่ฟ›็จ‹๏ผˆworkers๏ผ‰**ๆฅ่ฎฉๅบ”็”จ็จ‹ๅบ็š„ๆ‰ง่กŒ**ๅนถ่กŒๅŒ–**๏ผŒๅ……ๅˆ†ๅˆฉ็”จ CPU ็š„**ๅคšๆ ธๆ€ง่ƒฝ**๏ผŒๅนถ่ƒฝๅคŸๅค„็†**ๆ›ดๅคš็š„่ฏทๆฑ‚**ใ€‚ @@ -124,13 +124,13 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 * **ๅ†…ๅญ˜** * **ๅฏๅŠจไน‹ๅ‰็š„ๅ…ˆๅ‰ๆญฅ้ชค** -## ๅฎนๅ™จๅ’Œ Docker +## ๅฎนๅ™จๅ’Œ Docker { #containers-and-docker } ๅœจๅ…ณไบŽ [ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank} ็š„ไธ‹ไธ€็ซ ไธญ๏ผŒๆˆ‘ๅฐ†ไป‹็ปไธ€ไบ›ๅฏ็”จไบŽๅค„็†ๅ…ถไป–**้ƒจ็ฝฒๆฆ‚ๅฟต**็š„็ญ–็•ฅใ€‚ ๆˆ‘ๅฐ†ๅ‘ๆ‚จๅฑ•็คบๅฆ‚ไฝ•**ไปŽ้›ถๅผ€ๅง‹ๆž„ๅปบ่‡ชๅทฑ็š„้•œๅƒ**๏ผŒไปฅ่ฟ่กŒไธ€ไธชๅ•็‹ฌ็š„ Uvicorn ่ฟ›็จ‹ใ€‚่ฟ™ไธช่ฟ‡็จ‹็›ธๅฏน็ฎ€ๅ•๏ผŒๅนถไธ”ๅœจไฝฟ็”จ **Kubernetes** ็ญ‰ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸๆ—ถ๏ผŒ่ฟ™้€šๅธธๆ˜ฏๆ‚จ้œ€่ฆ้‡‡ๅ–็š„ๆ–นๆณ•ใ€‚ -## ๅ›ž้กพ +## ๅ›ž้กพ { #recap } ๆ‚จๅฏไปฅๅœจไฝฟ็”จ `fastapi` ๆˆ– `uvicorn` ๅ‘ฝไปคๆ—ถ๏ผŒ้€š่ฟ‡ `--workers` CLI ้€‰้กนๅฏ็”จๅคšไธชๅทฅไฝœ่ฟ›็จ‹๏ผˆworkers๏ผ‰๏ผŒไปฅๅ……ๅˆ†ๅˆฉ็”จ**ๅคšๆ ธ CPU**๏ผŒไปฅ**ๅนถ่กŒ่ฟ่กŒๅคšไธช่ฟ›็จ‹**ใ€‚ diff --git a/docs/zh/docs/deployment/versions.md b/docs/zh/docs/deployment/versions.md index 228bb07653..23c37f3b5b 100644 --- a/docs/zh/docs/deployment/versions.md +++ b/docs/zh/docs/deployment/versions.md @@ -1,4 +1,4 @@ -# ๅ…ณไบŽ FastAPI ็‰ˆๆœฌ +# ๅ…ณไบŽ FastAPI ็‰ˆๆœฌ { #about-fastapi-versions } **FastAPI** ๅทฒๅœจ่ฎธๅคšๅบ”็”จ็จ‹ๅบๅ’Œ็ณป็ปŸ็š„็”Ÿไบง็Žฏๅขƒไธญไฝฟ็”จใ€‚ ๅนถไธ”ๆต‹่ฏ•่ฆ†็›–็އไฟๆŒๅœจ100%ใ€‚ ไฝ†ๅ…ถๅผ€ๅ‘่ฟ›ๅบฆไปๅœจๅฟซ้€ŸๆŽจ่ฟ›ใ€‚ @@ -8,41 +8,41 @@ ไฝ ็Žฐๅœจๅฐฑๅฏไปฅไฝฟ็”จ **FastAPI** ๅˆ›ๅปบ็”Ÿไบง็Žฏๅขƒๅบ”็”จ็จ‹ๅบ๏ผˆไฝ ๅฏ่ƒฝๅทฒ็ป่ฟ™ๆ ทๅšไบ†ไธ€ๆฎตๆ—ถ้—ด๏ผ‰๏ผŒไฝ ๅช้œ€็กฎไฟไฝฟ็”จ็š„็‰ˆๆœฌๅฏไปฅไธŽๅ…ถไฝ™ไปฃ็ ๆญฃ็กฎ้…ๅˆๅณๅฏใ€‚ -## ๅ›บๅฎšไฝ ็š„ `fastapi` ็‰ˆๆœฌ +## ๅ›บๅฎšไฝ ็š„ `fastapi` ็‰ˆๆœฌ { #pin-your-fastapi-version } ไฝ ๅบ”่ฏฅๅš็š„็ฌฌไธ€ไปถไบ‹ๆ˜ฏๅฐ†ไฝ ๆญฃๅœจไฝฟ็”จ็š„ **FastAPI** ็‰ˆๆœฌโ€œๅ›บๅฎšโ€ๅˆฐไฝ ็Ÿฅ้“้€‚็”จไบŽไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„็‰นๅฎšๆœ€ๆ–ฐ็‰ˆๆœฌใ€‚ -ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๅœจๅบ”็”จ็จ‹ๅบไธญไฝฟ็”จ็‰ˆๆœฌ`0.45.0`ใ€‚ +ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๅœจๅบ”็”จ็จ‹ๅบไธญไฝฟ็”จ็‰ˆๆœฌ`0.112.0`ใ€‚ ๅฆ‚ๆžœไฝ ไฝฟ็”จ`requirements.txt`ๆ–‡ไปถ๏ผŒไฝ ๅฏไปฅไฝฟ็”จไปฅไธ‹ๅ‘ฝไปคๆŒ‡ๅฎš็‰ˆๆœฌ๏ผš -````txt -fastapi==0.45.0 -```` +```txt +fastapi[standard]==0.112.0 +``` -่ฟ™ๆ„ๅ‘ณ็€ไฝ ๅฐ†ไฝฟ็”จ็‰ˆๆœฌ`0.45.0`ใ€‚ +่ฟ™ๆ„ๅ‘ณ็€ไฝ ๅฐ†ไฝฟ็”จ็‰ˆๆœฌ`0.112.0`ใ€‚ ๆˆ–่€…ไฝ ไนŸๅฏไปฅๅฐ†ๅ…ถๅ›บๅฎšไธบ๏ผš -````txt -fastapi>=0.45.0,<0.46.0 -```` +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` -่ฟ™ๆ„ๅ‘ณ็€ไฝ ๅฐ†ไฝฟ็”จ`0.45.0`ๆˆ–ๆ›ด้ซ˜็‰ˆๆœฌ๏ผŒไฝ†ไฝŽไบŽ`0.46.0`๏ผŒไพ‹ๅฆ‚๏ผŒ็‰ˆๆœฌ`0.45.2`ไปไผš่ขซๆŽฅๅ—ใ€‚ +่ฟ™ๆ„ๅ‘ณ็€ไฝ ๅฐ†ไฝฟ็”จ`0.112.0`ๆˆ–ๆ›ด้ซ˜็‰ˆๆœฌ๏ผŒไฝ†ไฝŽไบŽ`0.113.0`๏ผŒไพ‹ๅฆ‚๏ผŒ็‰ˆๆœฌ`0.112.2`ไปไผš่ขซๆŽฅๅ—ใ€‚ -ๅฆ‚ๆžœไฝ ไฝฟ็”จไปปไฝ•ๅ…ถไป–ๅทฅๅ…ทๆฅ็ฎก็†ไฝ ็š„ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚ Poetryใ€Pipenv ๆˆ–ๅ…ถไป–ๅทฅๅ…ท๏ผŒๅฎƒไปฌ้ƒฝๆœ‰ไธ€็งๅฎšไน‰ๅŒ…็š„็‰นๅฎš็‰ˆๆœฌ็š„ๆ–นๆณ•ใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จไปปไฝ•ๅ…ถไป–ๅทฅๅ…ทๆฅ็ฎก็†ไฝ ็š„ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚ `uv`ใ€Poetryใ€Pipenv ๆˆ–ๅ…ถไป–ๅทฅๅ…ท๏ผŒๅฎƒไปฌ้ƒฝๆœ‰ไธ€็งๅฎšไน‰ๅŒ…็š„็‰นๅฎš็‰ˆๆœฌ็š„ๆ–นๆณ•ใ€‚ -## ๅฏ็”จ็‰ˆๆœฌ +## ๅฏ็”จ็‰ˆๆœฌ { #available-versions } ไฝ ๅฏไปฅๅœจ[ๅ‘่กŒ่ฏดๆ˜Ž](../release-notes.md){.internal-link target=_blank}ไธญๆŸฅ็œ‹ๅฏ็”จ็‰ˆๆœฌ๏ผˆไพ‹ๅฆ‚ๆŸฅ็œ‹ๅฝ“ๅ‰ๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผ‰ใ€‚ -## ๅ…ณไบŽ็‰ˆๆœฌ +## ๅ…ณไบŽ็‰ˆๆœฌ { #about-versions } ้ตๅพช่ฏญไน‰็‰ˆๆœฌๆŽงๅˆถ็บฆๅฎš๏ผŒไปปไฝ•ไฝŽไบŽ`1.0.0`็š„็‰ˆๆœฌ้ƒฝๅฏ่ƒฝไผšๆทปๅŠ  breaking changesใ€‚ -FastAPI ่ฟ˜้ตๅพช่ฟ™ๆ ท็š„็บฆๅฎš๏ผšไปปไฝ•`PATCH`็‰ˆๆœฌๆ›ดๆ”น้ƒฝๆ˜ฏไธบไบ†bugไฟฎๅคๅ’Œnon-breaking changesใ€‚ +FastAPI ่ฟ˜้ตๅพช่ฟ™ๆ ท็š„็บฆๅฎš๏ผšไปปไฝ•"PATCH"็‰ˆๆœฌๆ›ดๆ”น้ƒฝๆ˜ฏไธบไบ†bugไฟฎๅคๅ’Œnon-breaking changesใ€‚ -/// tip +/// tip | ๆ็คบ "PATCH"ๆ˜ฏๆœ€ๅŽไธ€ไธชๆ•ฐๅญ—๏ผŒไพ‹ๅฆ‚๏ผŒๅœจ`0.2.3`ไธญ๏ผŒPATCH็‰ˆๆœฌๆ˜ฏ`3`ใ€‚ @@ -56,13 +56,13 @@ fastapi>=0.45.0,<0.46.0 "MINOR"็‰ˆๆœฌไธญไผšๆทปๅŠ breaking changesๅ’Œๆ–ฐๅŠŸ่ƒฝใ€‚ -/// tip +/// tip | ๆ็คบ "MINOR"ๆ˜ฏไธญ้—ด็š„ๆ•ฐๅญ—๏ผŒไพ‹ๅฆ‚๏ผŒๅœจ`0.2.3`ไธญ๏ผŒMINOR็‰ˆๆœฌๆ˜ฏ`2`ใ€‚ /// -## ๅ‡็บงFastAPI็‰ˆๆœฌ +## ๅ‡็บงFastAPI็‰ˆๆœฌ { #upgrading-the-fastapi-versions } ไฝ ๅบ”่ฏฅไธบไฝ ็š„ๅบ”็”จ็จ‹ๅบๆทปๅŠ ๆต‹่ฏ•ใ€‚ @@ -72,7 +72,7 @@ fastapi>=0.45.0,<0.46.0 ๅฆ‚ๆžœไธ€ๅˆ‡ๆญฃๅธธ๏ผŒๆˆ–่€…ๅœจ่ฟ›่กŒๅฟ…่ฆ็š„ๆ›ดๆ”นไน‹ๅŽ๏ผŒๅนถไธ”ๆ‰€ๆœ‰ๆต‹่ฏ•้ƒฝ้€š่ฟ‡ไบ†๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅๅฐ†`fastapi`ๅ›บๅฎšๅˆฐๆ–ฐ็š„็‰ˆๆœฌใ€‚ -## ๅ…ณไบŽStarlette +## ๅ…ณไบŽStarlette { #about-starlette } ไฝ ไธๅบ”่ฏฅๅ›บๅฎš`starlette`็š„็‰ˆๆœฌใ€‚ @@ -80,14 +80,14 @@ fastapi>=0.45.0,<0.46.0 ๅ› ๆญค๏ผŒ**FastAPI** ่‡ชๅทฑๅฏไปฅไฝฟ็”จๆญฃ็กฎ็š„ Starlette ็‰ˆๆœฌใ€‚ -## ๅ…ณไบŽ Pydantic +## ๅ…ณไบŽ Pydantic { #about-pydantic } Pydantic ๅŒ…ๅซ้’ˆๅฏน **FastAPI** ็š„ๆต‹่ฏ•ๅŠๅ…ถ่‡ชๅทฑ็š„ๆต‹่ฏ•๏ผŒๅ› ๆญค Pydantic ็š„ๆ–ฐ็‰ˆๆœฌ๏ผˆ`1.0.0`ไปฅไธŠ๏ผ‰ๅง‹็ปˆไธŽ FastAPI ๅ…ผๅฎนใ€‚ -ไฝ ๅฏไปฅๅฐ† Pydantic ๅ›บๅฎšๅˆฐ้€‚ๅˆไฝ ็š„`1.0.0`ไปฅไธŠๅ’Œ`2.0.0`ไปฅไธ‹็š„ไปปไฝ•็‰ˆๆœฌใ€‚ +ไฝ ๅฏไปฅๅฐ† Pydantic ๅ›บๅฎšๅˆฐไปปไฝ•้ซ˜ไบŽ `1.0.0` ไธ”้€‚ๅˆไฝ ็š„็‰ˆๆœฌใ€‚ ไพ‹ๅฆ‚๏ผš -````txt -pydantic>=1.2.0,<2.0.0 -```` +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/zh/docs/environment-variables.md b/docs/zh/docs/environment-variables.md index 812278051a..8729a6306a 100644 --- a/docs/zh/docs/environment-variables.md +++ b/docs/zh/docs/environment-variables.md @@ -1,6 +1,6 @@ -# ็Žฏๅขƒๅ˜้‡ +# ็Žฏๅขƒๅ˜้‡ { #environment-variables } -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœไฝ ๅทฒ็ป็Ÿฅ้“ไป€ไนˆๆ˜ฏโ€œ็Žฏๅขƒๅ˜้‡โ€ๅนถไธ”็Ÿฅ้“ๅฆ‚ไฝ•ไฝฟ็”จๅฎƒไปฌ๏ผŒไฝ ๅฏไปฅๆ”พๅฟƒ่ทณ่ฟ‡่ฟ™ไธ€้ƒจๅˆ†ใ€‚ @@ -10,7 +10,7 @@ ็Žฏๅขƒๅ˜้‡ๅฏนไบŽๅค„็†ๅบ”็”จ็จ‹ๅบ**่ฎพ็ฝฎ**ใ€ไฝœไธบ Python **ๅฎ‰่ฃ…**็š„ไธ€้ƒจๅˆ†็ญ‰ๆ–น้ข้žๅธธๆœ‰็”จใ€‚ -## ๅˆ›ๅปบๅ’Œไฝฟ็”จ็Žฏๅขƒๅ˜้‡ +## ๅˆ›ๅปบๅ’Œไฝฟ็”จ็Žฏๅขƒๅ˜้‡ { #create-and-use-env-vars } ไฝ ๅœจ **shell๏ผˆ็ปˆ็ซฏ๏ผ‰**ไธญๅฐฑๅฏไปฅ**ๅˆ›ๅปบ**ๅ’Œไฝฟ็”จ็Žฏๅขƒๅ˜้‡๏ผŒๅนถไธ้œ€่ฆ็”จๅˆฐ Python๏ผš @@ -50,7 +50,7 @@ Hello Wade Wilson //// -## ๅœจ Python ไธญ่ฏปๅ–็Žฏๅขƒๅ˜้‡ +## ๅœจ Python ไธญ่ฏปๅ–็Žฏๅขƒๅ˜้‡ { #read-env-vars-in-python } ไฝ ไนŸๅฏไปฅๅœจ Python **ไน‹ๅค–**็š„็ปˆ็ซฏไธญๅˆ›ๅปบ็Žฏๅขƒๅ˜้‡๏ผˆๆˆ–ไฝฟ็”จไปปไฝ•ๅ…ถไป–ๆ–นๆณ•๏ผ‰๏ผŒ็„ถๅŽๅœจ Python ไธญ**่ฏปๅ–**ๅฎƒไปฌใ€‚ @@ -63,9 +63,9 @@ name = os.getenv("MY_NAME", "World") print(f"Hello {name} from Python") ``` -/// tip +/// tip | ๆ็คบ -็ฌฌไบŒไธชๅ‚ๆ•ฐๆ˜ฏ `os.getenv()` ็š„้ป˜่ฎค่ฟ”ๅ›žๅ€ผใ€‚ +็ฌฌไบŒไธชๅ‚ๆ•ฐๆ˜ฏ `os.getenv()` ็š„้ป˜่ฎค่ฟ”ๅ›žๅ€ผใ€‚ ๅฆ‚ๆžœๆฒกๆœ‰ๆไพ›๏ผŒ้ป˜่ฎคๅ€ผไธบ `None`๏ผŒ่ฟ™้‡Œๆˆ‘ไปฌๆไพ› `"World"` ไฝœไธบ้ป˜่ฎคๅ€ผใ€‚ @@ -151,21 +151,21 @@ Hello World from Python -/// tip +/// tip | ๆ็คบ -ไฝ ๅฏไปฅๅœจ The Twelve-Factor App: ้…็ฝฎไธญไบ†่งฃๆ›ดๅคšไฟกๆฏใ€‚ +ไฝ ๅฏไปฅๅœจ The Twelve-Factor App: ้…็ฝฎไธญไบ†่งฃๆ›ดๅคšไฟกๆฏใ€‚ /// -## ็ฑปๅž‹ๅ’Œ้ชŒ่ฏ +## ็ฑปๅž‹ๅ’Œ้ชŒ่ฏ { #types-and-validation } ่ฟ™ไบ›็Žฏๅขƒๅ˜้‡ๅช่ƒฝๅค„็†**ๆ–‡ๆœฌๅญ—็ฌฆไธฒ**๏ผŒๅ› ไธบๅฎƒไปฌๆ˜ฏๅค„ไบŽ Python ่Œƒ็•ดไน‹ๅค–็š„๏ผŒๅฟ…้กปไธŽๅ…ถไป–็จ‹ๅบๅ’Œๆ“ไฝœ็ณป็ปŸ็š„ๅ…ถไฝ™้ƒจๅˆ†ๅ…ผๅฎน๏ผˆ็”š่‡ณไธŽไธๅŒ็š„ๆ“ไฝœ็ณป็ปŸๅ…ผๅฎน๏ผŒๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰ใ€‚ ่ฟ™ๆ„ๅ‘ณ็€ไปŽ็Žฏๅขƒๅ˜้‡ไธญ่ฏปๅ–็š„**ไปปไฝ•ๅ€ผ**ๅœจ Python ไธญ้ƒฝๅฐ†ๆ˜ฏไธ€ไธช `str`๏ผŒไปปไฝ•็ฑปๅž‹่ฝฌๆขๆˆ–้ชŒ่ฏ้ƒฝๅฟ…้กปๅœจไปฃ็ ไธญๅฎŒๆˆใ€‚ -ไฝ ๅฐ†ๅœจ[้ซ˜็บง็”จๆˆทๆŒ‡ๅ— - ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡](./advanced/settings.md)ไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽไฝฟ็”จ็Žฏๅขƒๅ˜้‡ๅค„็†**ๅบ”็”จ็จ‹ๅบ่ฎพ็ฝฎ**็š„ไฟกๆฏใ€‚ +ไฝ ๅฐ†ๅœจ[้ซ˜็บง็”จๆˆทๆŒ‡ๅ— - ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡](./advanced/settings.md){.internal-link target=_blank}ไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽไฝฟ็”จ็Žฏๅขƒๅ˜้‡ๅค„็†**ๅบ”็”จ็จ‹ๅบ่ฎพ็ฝฎ**็š„ไฟกๆฏใ€‚ -## `PATH` ็Žฏๅขƒๅ˜้‡ +## `PATH` ็Žฏๅขƒๅ˜้‡ { #path-environment-variable } ๆœ‰ไธ€ไธช**็‰นๆฎŠ็š„**็Žฏๅขƒๅ˜้‡็งฐไธบ **`PATH`**๏ผŒๆ“ไฝœ็ณป็ปŸ๏ผˆLinuxใ€macOSใ€Windows๏ผ‰็”จๅฎƒๆฅๆŸฅๆ‰พ่ฆ่ฟ่กŒ็š„็จ‹ๅบใ€‚ @@ -209,7 +209,7 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 ๅฆ‚ๆžœๆ‰พๅˆฐไบ†๏ผŒ้‚ฃไนˆๆ“ไฝœ็ณป็ปŸๅฐ†**ไฝฟ็”จๅฎƒ**๏ผ›ๅฆๅˆ™๏ผŒๆ“ไฝœ็ณป็ปŸไผš็ปง็ปญๅœจ**ๅ…ถไป–็›ฎๅฝ•**ไธญๆŸฅๆ‰พใ€‚ -### ๅฎ‰่ฃ… Python ๅ’Œๆ›ดๆ–ฐ `PATH` +### ๅฎ‰่ฃ… Python ๅ’Œๆ›ดๆ–ฐ `PATH` { #installing-python-and-updating-the-path } ๅฎ‰่ฃ… Python ๆ—ถ๏ผŒๅฏ่ƒฝไผš่ฏข้—ฎไฝ ๆ˜ฏๅฆ่ฆๆ›ดๆ–ฐ `PATH` ็Žฏๅขƒๅ˜้‡ใ€‚ @@ -233,7 +233,7 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 ๅ‡่ฎพไฝ ๅฎ‰่ฃ… Python ๅนถๆœ€็ปˆๅฐ†ๅ…ถๅฎ‰่ฃ…ๅœจไบ†็›ฎๅฝ• `C:\opt\custompython\bin` ไธญใ€‚ -ๅฆ‚ๆžœไฝ ๅŒๆ„ๆ›ดๆ–ฐ `PATH` ็Žฏๅขƒๅ˜้‡ (ๅœจ Python ๅฎ‰่ฃ…็จ‹ๅบไธญ๏ผŒ่ฟ™ไธชๆ“ไฝœๆ˜ฏๅไธบ `Add Python x.xx to PATH` ็š„ๅค้€‰ๆก† โ€”โ€” ่ฏ‘่€…ๆณจ)๏ผŒ้‚ฃไนˆๅฎ‰่ฃ…็จ‹ๅบๅฐ†ไผšๅฐ† `C:\opt\custompython\bin` ๆทปๅŠ ๅˆฐ `PATH` ็Žฏๅขƒๅ˜้‡ไธญใ€‚ +ๅฆ‚ๆžœไฝ ๅŒๆ„ๆ›ดๆ–ฐ `PATH` ็Žฏๅขƒๅ˜้‡๏ผŒ้‚ฃไนˆๅฎ‰่ฃ…็จ‹ๅบๅฐ†ไผšๅฐ† `C:\opt\custompython\bin` ๆทปๅŠ ๅˆฐ `PATH` ็Žฏๅขƒๅ˜้‡ไธญใ€‚ ```plaintext C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -ๅฝ“ๅญฆไน [่™šๆ‹Ÿ็Žฏๅขƒ](virtual-environments.md)ๆ—ถ๏ผŒ่ฟ™ไบ›ไฟกๆฏๅฐ†ไผšๅพˆๆœ‰็”จใ€‚ +ๅฝ“ๅญฆไน [่™šๆ‹Ÿ็Žฏๅขƒ](virtual-environments.md){.internal-link target=_blank}ๆ—ถ๏ผŒ่ฟ™ไบ›ไฟกๆฏๅฐ†ไผšๅพˆๆœ‰็”จใ€‚ -## ็ป“่ฎบ +## ็ป“่ฎบ { #conclusion } ้€š่ฟ‡่ฟ™ไธชๆ•™็จ‹๏ผŒไฝ ๅบ”่ฏฅๅฏน**็Žฏๅขƒๅ˜้‡**ๆ˜ฏไป€ไนˆไปฅๅŠๅฆ‚ไฝ•ๅœจ Python ไธญไฝฟ็”จๅฎƒไปฌๆœ‰ไบ†ๅŸบๆœฌ็š„ไบ†่งฃใ€‚ -ไฝ ไนŸๅฏไปฅๅœจ็Žฏๅขƒๅ˜้‡ - ็ปดๅŸบ็™พ็ง‘ (Wikipedia for Environment Variable) ไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽๅฎƒไปฌ็š„ไฟกๆฏใ€‚ +ไฝ ไนŸๅฏไปฅๅœจ็Žฏๅขƒๅ˜้‡ - ็ปดๅŸบ็™พ็ง‘ไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽๅฎƒไปฌ็š„ไฟกๆฏใ€‚ ๅœจ่ฎธๅคšๆƒ…ๅ†ตไธ‹๏ผŒ็Žฏๅขƒๅ˜้‡็š„็”จ้€”ๅ’Œ้€‚็”จๆ€งๅนถไธๆ˜ฏๅพˆๆ˜Žๆ˜พใ€‚ไฝ†ๆ˜ฏๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญ๏ผŒๅฎƒไปฌไผšๅœจ่ฎธๅคšไธๅŒ็š„ๅœบๆ™ฏไธญๅ‡บ็Žฐ๏ผŒๅ› ๆญคไบ†่งฃๅฎƒไปฌๆ˜ฏๅพˆๆœ‰ๅฟ…่ฆ็š„ใ€‚ diff --git a/docs/zh/docs/fastapi-cli.md b/docs/zh/docs/fastapi-cli.md index 3b67eb6645..4d3b51a57a 100644 --- a/docs/zh/docs/fastapi-cli.md +++ b/docs/zh/docs/fastapi-cli.md @@ -1,8 +1,8 @@ -# FastAPI CLI +# FastAPI CLI { #fastapi-cli } **FastAPI CLI** ๆ˜ฏไธ€ไธชๅ‘ฝไปค่กŒ็จ‹ๅบ๏ผŒไฝ ๅฏไปฅ็”จๅฎƒๆฅ้ƒจ็ฝฒๅ’Œ่ฟ่กŒไฝ ็š„ FastAPI ๅบ”็”จ็จ‹ๅบ๏ผŒ็ฎก็†ไฝ ็š„ FastAPI ้กน็›ฎ๏ผŒ็ญ‰็ญ‰ใ€‚ -ๅฝ“ไฝ ๅฎ‰่ฃ… FastAPI ๆ—ถ๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ `pip install FastAPI` ๅ‘ฝไปค๏ผ‰๏ผŒไผšๅŒ…ๅซไธ€ไธชๅไธบ `fastapi-cli` ็š„่ฝฏไปถๅŒ…๏ผŒ่ฏฅ่ฝฏไปถๅŒ…ๅœจ็ปˆ็ซฏไธญๆไพ› `fastapi` ๅ‘ฝไปคใ€‚ +ๅฝ“ไฝ ๅฎ‰่ฃ… FastAPI ๆ—ถ๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ `pip install "fastapi[standard]"`๏ผ‰๏ผŒไผšๅŒ…ๅซไธ€ไธชๅไธบ `fastapi-cli` ็š„่ฝฏไปถๅŒ…๏ผŒ่ฏฅ่ฝฏไปถๅŒ…ๅœจ็ปˆ็ซฏไธญๆไพ› `fastapi` ๅ‘ฝไปคใ€‚ ่ฆๅœจๅผ€ๅ‘็Žฏๅขƒไธญ่ฟ่กŒไฝ ็š„ FastAPI ๅบ”็”จ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `fastapi dev` ๅ‘ฝไปค๏ผš @@ -48,32 +48,28 @@ $ fastapi dev Uvicorn๏ผŒ่ฟ™ๆ˜ฏไธ€ไธช้ซ˜ๆ€ง่ƒฝใ€้€‚็”จไบŽ็”Ÿไบง็Žฏๅขƒ็š„ ASGI ๆœๅŠกๅ™จใ€‚๐Ÿ˜Ž -## `fastapi dev` +## `fastapi dev` { #fastapi-dev } ๅฝ“ไฝ ่ฟ่กŒ `fastapi dev` ๆ—ถ๏ผŒๅฎƒๅฐ†ไปฅๅผ€ๅ‘ๆจกๅผ่ฟ่กŒใ€‚ -้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒไผšๅฏ็”จ**่‡ชๅŠจ้‡่ฝฝ**๏ผŒๅ› ๆญคๅฝ“ไฝ ๆ›ดๆ”นไปฃ็ ๆ—ถ๏ผŒๅฎƒไผš่‡ชๅŠจ้‡ๆ–ฐๅŠ ่ฝฝๆœๅŠกๅ™จใ€‚่ฏฅๅŠŸ่ƒฝๆ˜ฏ่ต„ๆบๅฏ†้›†ๅž‹็š„๏ผŒไธ”็›ธ่พƒไธๅฏ็”จๆ—ถๆ›ดไธ็จณๅฎš๏ผŒๅ› ๆญคไฝ ๅบ”่ฏฅไป…ๅœจๅผ€ๅ‘็Žฏๅขƒไธ‹ไฝฟ็”จๅฎƒใ€‚ +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒไผšๅฏ็”จ**่‡ชๅŠจ้‡่ฝฝ**๏ผŒๅ› ๆญคๅฝ“ไฝ ๆ›ดๆ”นไปฃ็ ๆ—ถ๏ผŒๅฎƒไผš่‡ชๅŠจ้‡ๆ–ฐๅŠ ่ฝฝๆœๅŠกๅ™จใ€‚่ฏฅๅŠŸ่ƒฝๆ˜ฏ่ต„ๆบๅฏ†้›†ๅž‹็š„๏ผŒไธ”็›ธ่พƒไธๅฏ็”จๆ—ถๆ›ดไธ็จณๅฎš๏ผŒๅ› ๆญคไฝ ๅบ”่ฏฅไป…ๅœจๅผ€ๅ‘็Žฏๅขƒไธ‹ไฝฟ็”จๅฎƒใ€‚ๅฎƒ่ฟ˜ไผš็›‘ๅฌ IP ๅœฐๅ€ `127.0.0.1`๏ผŒ่ฟ™ๆ˜ฏไฝ ็š„ๆœบๅ™จไป…ไธŽ่‡ช่บซ้€šไฟก็š„ IP๏ผˆ`localhost`๏ผ‰ใ€‚ -้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฐ†็›‘ๅฌ IP ๅœฐๅ€ `127.0.0.1`๏ผŒ่ฟ™ๆ˜ฏไฝ ็š„ๆœบๅ™จไธŽ่‡ช่บซ้€šไฟก็š„ IP ๅœฐๅ€๏ผˆ`localhost`๏ผ‰ใ€‚ - -## `fastapi run` +## `fastapi run` { #fastapi-run } ๅฝ“ไฝ ่ฟ่กŒ `fastapi run` ๆ—ถ๏ผŒๅฎƒ้ป˜่ฎคไปฅ็”Ÿไบง็Žฏๅขƒๆจกๅผ่ฟ่กŒใ€‚ -้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ**่‡ชๅŠจ้‡่ฝฝๆ˜ฏ็ฆ็”จ็š„**ใ€‚ - -ๅฎƒๅฐ†็›‘ๅฌ IP ๅœฐๅ€ `0.0.0.0`๏ผŒๅณๆ‰€ๆœ‰ๅฏ็”จ็š„ IP ๅœฐๅ€๏ผŒ่ฟ™ๆ ทไปปไฝ•่ƒฝๅคŸไธŽ่ฏฅๆœบๅ™จ้€šไฟก็š„ไบบ้ƒฝๅฏไปฅๅ…ฌๅผ€่ฎฟ้—ฎๅฎƒใ€‚่ฟ™้€šๅธธๆ˜ฏไฝ ๅœจ็”Ÿไบง็Žฏๅขƒไธญ่ฟ่กŒๅฎƒ็š„ๆ–นๅผ๏ผŒไพ‹ๅฆ‚ๅœจๅฎนๅ™จไธญ่ฟ่กŒใ€‚ +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ**่‡ชๅŠจ้‡่ฝฝๆ˜ฏ็ฆ็”จ็š„**ใ€‚ๅฎƒๅฐ†็›‘ๅฌ IP ๅœฐๅ€ `0.0.0.0`๏ผŒๅณๆ‰€ๆœ‰ๅฏ็”จ็š„ IP ๅœฐๅ€๏ผŒ่ฟ™ๆ ทไปปไฝ•่ƒฝๅคŸไธŽ่ฏฅๆœบๅ™จ้€šไฟก็š„ไบบ้ƒฝๅฏไปฅๅ…ฌๅผ€่ฎฟ้—ฎๅฎƒใ€‚่ฟ™้€šๅธธๆ˜ฏไฝ ๅœจ็”Ÿไบง็Žฏๅขƒไธญ่ฟ่กŒๅฎƒ็š„ๆ–นๅผ๏ผŒไพ‹ๅฆ‚ๅœจๅฎนๅ™จไธญ่ฟ่กŒใ€‚ ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ไผš๏ผˆไธ”ๅบ”่ฏฅ๏ผ‰ๆœ‰ไธ€ไธชโ€œ็ปˆๆญขไปฃ็†โ€ๅœจไธŠๅฑ‚ไธบไฝ ๅค„็† HTTPS๏ผŒ่ฟ™ๅ–ๅ†ณไบŽไฝ ๅฆ‚ไฝ•้ƒจ็ฝฒๅบ”็”จ็จ‹ๅบ๏ผŒไฝ ็š„ๆœๅŠกๆไพ›ๅ•†ๅฏ่ƒฝไผšไธบไฝ ๅค„็†ๆญคไบ‹๏ผŒๆˆ–่€…ไฝ ๅฏ่ƒฝ้œ€่ฆ่‡ชๅทฑ่ฎพ็ฝฎใ€‚ /// tip | ๆ็คบ -ไฝ ๅฏไปฅๅœจ [deployment documentation](deployment/index.md){.internal-link target=_blank} ่Žทๅพ—ๆ›ดๅคšไฟกๆฏใ€‚ +ไฝ ๅฏไปฅๅœจ[้ƒจ็ฝฒๆ–‡ๆกฃ](deployment/index.md){.internal-link target=_blank}ไธญไบ†่งฃๆ›ดๅคšใ€‚ /// diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index eaf8daff7e..7d7aa19c06 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -1,22 +1,21 @@ -# ็‰นๆ€ง +# ็‰นๆ€ง { #features } -## FastAPI ็‰นๆ€ง +## FastAPI ็‰นๆ€ง { #fastapi-features } **FastAPI** ๆไพ›ไบ†ไปฅไธ‹ๅ†…ๅฎน๏ผš -### ๅŸบไบŽๅผ€ๆ”พๆ ‡ๅ‡† +### ๅŸบไบŽๅผ€ๆ”พๆ ‡ๅ‡† { #based-on-open-standards } - -* ็”จไบŽๅˆ›ๅปบ API ็š„ OpenAPI ๅŒ…ๅซไบ†่ทฏๅพ„ๆ“ไฝœ๏ผŒ่ฏทๆฑ‚ๅ‚ๆ•ฐ๏ผŒ่ฏทๆฑ‚ไฝ“๏ผŒๅฎ‰ๅ…จๆ€ง็ญ‰็š„ๅฃฐๆ˜Žใ€‚ -* ไฝฟ็”จ JSON Schema (ๅ› ไธบ OpenAPI ๆœฌ่บซๅฐฑๆ˜ฏๅŸบไบŽ JSON Schema ็š„)่‡ชๅŠจ็”Ÿๆˆๆ•ฐๆฎๆจกๅž‹ๆ–‡ๆกฃใ€‚ +* ็”จไบŽๅˆ›ๅปบ API ็š„ OpenAPI๏ผŒๅŒ…ๅซๅฏน่ทฏๅพ„ ๆ“ไฝœใ€ๅ‚ๆ•ฐใ€่ฏทๆฑ‚ไฝ“ใ€ๅฎ‰ๅ…จ็ญ‰็š„ๅฃฐๆ˜Žใ€‚ +* ไฝฟ็”จ JSON Schema ่‡ชๅŠจ็”Ÿๆˆๆ•ฐๆฎๆจกๅž‹ๆ–‡ๆกฃ๏ผˆๅ› ไธบ OpenAPI ๆœฌ่บซๅฐฑๆ˜ฏๅŸบไบŽ JSON Schema ็š„๏ผ‰ใ€‚ * ็ป่ฟ‡ไบ†็ผœๅฏ†็š„็ ”็ฉถๅŽๅ›ด็ป•่ฟ™ไบ›ๆ ‡ๅ‡†่€Œ่ฎพ่ฎกใ€‚ๅนถ้ž็‹—ๅฐพ็ปญ่ฒ‚ใ€‚ * ่ฟ™ไนŸๅ…่ฎธไบ†ๅœจๅพˆๅคš่ฏญ่จ€ไธญ่‡ชๅŠจ**็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ **ใ€‚ -### ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ +### ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ { #automatic-docs } ไบคไบ’ๅผ API ๆ–‡ๆกฃไปฅๅŠๅ…ทๆŽข็ดขๆ€ง web ็•Œ้ขใ€‚ๅ› ไธบ่ฏฅๆก†ๆžถๆ˜ฏๅŸบไบŽ OpenAPI๏ผŒๆ‰€ไปฅๆœ‰ๅพˆๅคšๅฏ้€‰้กน๏ผŒFastAPI ้ป˜่ฎค่‡ชๅธฆไธคไธชไบคไบ’ๅผ API ๆ–‡ๆกฃใ€‚ -* Swagger UI๏ผŒๅฏไบคไบ’ๅผๆ“ไฝœ๏ผŒ่ƒฝๅœจๆต่งˆๅ™จไธญ็›ดๆŽฅ่ฐƒ็”จๅ’Œๆต‹่ฏ•ไฝ ็š„ API ใ€‚ +* Swagger UI๏ผŒๅฏไบคไบ’ๅผๆ“ไฝœ๏ผŒ่ƒฝๅœจๆต่งˆๅ™จไธญ็›ดๆŽฅ่ฐƒ็”จๅ’Œๆต‹่ฏ•ไฝ ็š„ APIใ€‚ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -24,11 +23,11 @@ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ๆ›ดไธปๆต็š„ Python +### ๆ›ดไธปๆต็š„ Python { #just-modern-python } -ๅ…จ้ƒจ้ƒฝๅŸบไบŽๆ ‡ๅ‡†็š„ **Python 3.6 ็ฑปๅž‹**ๅฃฐๆ˜Ž๏ผˆๆ„Ÿ่ฐข Pydantic ๏ผ‰ใ€‚ๆฒกๆœ‰ๆ–ฐ็š„่ฏญๆณ•้œ€่ฆๅญฆไน ใ€‚ๅช้œ€่ฆๆ ‡ๅ‡†็š„ Python ใ€‚ +ๅ…จ้ƒจ้ƒฝๅŸบไบŽๆ ‡ๅ‡†็š„ **Python ็ฑปๅž‹** ๅฃฐๆ˜Ž๏ผˆๆ„Ÿ่ฐข Pydantic๏ผ‰ใ€‚ๆฒกๆœ‰ๆ–ฐ็š„่ฏญๆณ•้œ€่ฆๅญฆไน ใ€‚ๅช้œ€่ฆๆ ‡ๅ‡†็š„็Žฐไปฃ Pythonใ€‚ -ๅฆ‚ๆžœไฝ ้œ€่ฆ2ๅˆ†้’Ÿๆฅๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จ Python ็ฑปๅž‹๏ผˆๅณไฝฟไฝ ไธไฝฟ็”จ FastAPI ๏ผ‰๏ผŒ็œ‹็œ‹่ฟ™ไธช็ฎ€็Ÿญ็š„ๆ•™็จ‹๏ผš[Python Types](python-types.md){.internal-link target=_blank}ใ€‚ +ๅฆ‚ๆžœไฝ ้œ€่ฆ2ๅˆ†้’Ÿๆฅๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จ Python ็ฑปๅž‹๏ผˆๅณไฝฟไฝ ไธไฝฟ็”จ FastAPI๏ผ‰๏ผŒ็œ‹็œ‹่ฟ™ไธช็ฎ€็Ÿญ็š„ๆ•™็จ‹๏ผš[Python Types](python-types.md){.internal-link target=_blank}ใ€‚ ็ผ–ๅ†™ๅธฆๆœ‰็ฑปๅž‹ๆ ‡ๆณจ็š„ๆ ‡ๅ‡† Python๏ผš @@ -37,13 +36,13 @@ from datetime import date from pydantic import BaseModel -# Declare a variable as a str -# and get editor support inside the function +# ๅฐ†ๅ˜้‡ๅฃฐๆ˜Žไธบ str +# ๅนถๅœจๅ‡ฝๆ•ฐๅ†…่Žทๅพ—็ผ–่พ‘ๅ™จๆ”ฏๆŒ def main(user_id: str): return user_id -# A Pydantic model +# ไธ€ไธช Pydantic ๆจกๅž‹ class User(BaseModel): id: int name: str @@ -65,19 +64,19 @@ my_second_user: User = User(**second_user_data) ``` -/// info +/// info | ไฟกๆฏ -`**second_user_data` ๆ„ๆ€ๆ˜ฏ: +`**second_user_data` ๆ„ๆ€ๆ˜ฏ๏ผš -็›ดๆŽฅๅฐ†`second_user_data`ๅญ—ๅ…ธ็š„้”ฎๅ’Œๅ€ผ็›ดๆŽฅไฝœไธบkey-valueๅ‚ๆ•ฐไผ ้€’๏ผŒ็ญ‰ๅŒไบŽ๏ผš`User(id=4, name="Mary", joined="2018-11-30")` +็›ดๆŽฅๅฐ† `second_user_data` ๅญ—ๅ…ธ็š„้”ฎๅ’Œๅ€ผไฝœไธบ key-value ๅ‚ๆ•ฐไผ ๅ…ฅ๏ผŒ็ญ‰ๅŒไบŽ๏ผš`User(id=4, name="Mary", joined="2018-11-30")` /// -### ็ผ–่พ‘ๅ™จๆ”ฏๆŒ +### ็ผ–่พ‘ๅ™จๆ”ฏๆŒ { #editor-support } ๆ•ดไธชๆก†ๆžถ้ƒฝ่ขซ่ฎพ่ฎกๅพ—ๆ˜“ไบŽไฝฟ็”จไธ”็›ด่ง‚๏ผŒๆ‰€ๆœ‰็š„ๅ†ณๅฎš้ƒฝๅœจๅผ€ๅ‘ไน‹ๅ‰ๅฐฑๅœจๅคšไธช็ผ–่พ‘ๅ™จไธŠ่ฟ›่กŒไบ†ๆต‹่ฏ•๏ผŒๆฅ็กฎไฟๆœ€ไฝณ็š„ๅผ€ๅ‘ไฝ“้ชŒใ€‚ -ๅœจๆœ€่ฟ‘็š„ Python ๅผ€ๅ‘่€…่ฐƒๆŸฅไธญ๏ผŒๆˆ‘ไปฌ่ƒฝ็œ‹ๅˆฐ ่ขซไฝฟ็”จๆœ€ๅคš็š„ๅŠŸ่ƒฝๆ˜ฏ"่‡ชๅŠจ่กฅๅ…จ"ใ€‚ +ๅœจๆœ€่ฟ‘็š„ Python ๅผ€ๅ‘่€…่ฐƒๆŸฅไธญ๏ผŒๆˆ‘ไปฌ่ƒฝ็œ‹ๅˆฐ ่ขซไฝฟ็”จๆœ€ๅคš็š„ๅŠŸ่ƒฝๆ˜ฏโ€œ่‡ชๅŠจ่กฅๅ…จโ€ใ€‚ ๆ•ดไธช **FastAPI** ๆก†ๆžถๅฐฑๆ˜ฏๅŸบไบŽ่ฟ™ไธ€็‚น็š„ใ€‚ไปปไฝ•ๅœฐๆ–น้ƒฝๅฏไปฅ่ฟ›่กŒ่‡ชๅŠจ่กฅๅ…จใ€‚ @@ -85,62 +84,58 @@ my_second_user: User = User(**second_user_data) ๅœจ่ฟ™้‡Œ๏ผŒไฝ ็š„็ผ–่พ‘ๅ™จๅฏ่ƒฝไผš่ฟ™ๆ ทๅธฎๅŠฉไฝ ๏ผš -* Visual Studio Code ไธญ: +* ๅœจ Visual Studio Code ไธญ: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* PyCharm ไธญ: +* ๅœจ PyCharm ไธญ: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) ไฝ ๅฐ†่ƒฝ่ฟ›่กŒไปฃ็ ่กฅๅ…จ๏ผŒ่ฟ™ๆ˜ฏๅœจไน‹ๅ‰ไฝ ๅฏ่ƒฝๆ›พ่ฎคไธบไธๅฏ่ƒฝ็š„ไบ‹ใ€‚ไพ‹ๅฆ‚๏ผŒๅœจๆฅ่‡ช่ฏทๆฑ‚ JSON ไฝ“๏ผˆๅฏ่ƒฝๆ˜ฏๅตŒๅฅ—็š„๏ผ‰ไธญ็š„้”ฎ `price`ใ€‚ -ไธไผšๅ†่พ“้”™้”ฎๅ๏ผŒๆฅๅ›ž็ฟป็œ‹ๆ–‡ๆกฃ๏ผŒๆˆ–่€…ๆฅๅ›žๆปšๅŠจๅฏปๆ‰พไฝ ๆœ€ๅŽไฝฟ็”จ็š„ `username` ๆˆ–่€… `user_name` ใ€‚ - - +ไธไผšๅ†่พ“้”™้”ฎๅ๏ผŒๆฅๅ›ž็ฟป็œ‹ๆ–‡ๆกฃ๏ผŒๆˆ–่€…ๆฅๅ›žๆปšๅŠจๅฏปๆ‰พไฝ ๆœ€ๅŽไฝฟ็”จ็š„ `username` ๆˆ–่€… `user_name`ใ€‚ -### ็ฎ€ๆด +### ็ฎ€ๆด { #short } ไปปไฝ•็ฑปๅž‹้ƒฝๆœ‰ๅˆ็†็š„**้ป˜่ฎคๅ€ผ**๏ผŒไปปไฝ•ๅ’Œๅœฐๆ–น้ƒฝๆœ‰ๅฏ้€‰้…็ฝฎใ€‚ๆ‰€ๆœ‰็š„ๅ‚ๆ•ฐ่ขซๅพฎ่ฐƒ๏ผŒๆฅๆปก่ถณไฝ ็š„้œ€ๆฑ‚๏ผŒๅฎšไน‰ๆˆไฝ ้œ€่ฆ็š„ APIใ€‚ ไฝ†ๆ˜ฏ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒไธ€ๅˆ‡้ƒฝ่ƒฝ**โ€œ้กบๅˆฉๅทฅไฝœโ€**ใ€‚ -### ้ชŒ่ฏ +### ้ชŒ่ฏ { #validation } * ๆ ก้ชŒๅคง้ƒจๅˆ†๏ผˆ็”š่‡ณๆ‰€ๆœ‰๏ผŸ๏ผ‰็š„ Python **ๆ•ฐๆฎ็ฑปๅž‹**๏ผŒๅŒ…ๆ‹ฌ๏ผš - * JSON ๅฏน่ฑก (`dict`). + * JSON ๅฏน่ฑก (`dict`)ใ€‚ * JSON ๆ•ฐ็ป„ (`list`) ๅฎšไน‰ๆˆๅ‘˜็ฑปๅž‹ใ€‚ - * ๅญ—็ฌฆไธฒ (`str`) ๅญ—ๆฎต, ๅฎšไน‰ๆœ€ๅฐๆˆ–ๆœ€ๅคง้•ฟๅบฆใ€‚ - * ๆ•ฐๅญ— (`int`, `float`) ๆœ‰ๆœ€ๅคงๅ€ผๅ’Œๆœ€ๅฐๅ€ผ๏ผŒ ็ญ‰็ญ‰ใ€‚ + * ๅญ—็ฌฆไธฒ (`str`) ๅญ—ๆฎต๏ผŒๅฎšไน‰ๆœ€ๅฐๆˆ–ๆœ€ๅคง้•ฟๅบฆใ€‚ + * ๆ•ฐๅญ— (`int`, `float`) ๆœ‰ๆœ€ๅคงๅ€ผๅ’Œๆœ€ๅฐๅ€ผ๏ผŒ็ญ‰็ญ‰ใ€‚ -* ๆ ก้ชŒๅค–ๆฅ็ฑปๅž‹๏ผŒ ๆฏ”ๅฆ‚: - * URL. - * Email. - * UUID. - * ...ๅŠๅ…ถไป–. +* ๆ ก้ชŒๅค–ๆฅ็ฑปๅž‹๏ผŒๆฏ”ๅฆ‚๏ผš + * URLใ€‚ + * Emailใ€‚ + * UUIDใ€‚ + * ...ๅŠๅ…ถไป–ใ€‚ ๆ‰€ๆœ‰็š„ๆ ก้ชŒ้ƒฝ็”ฑๅฎŒๅ–„ไธ”ๅผบๅคง็š„ **Pydantic** ๅค„็†ใ€‚ -### ๅฎ‰ๅ…จๆ€งๅŠ่บซไปฝ้ชŒ่ฏ +### ๅฎ‰ๅ…จๆ€งๅŠ่บซไปฝ้ชŒ่ฏ { #security-and-authentication } ้›†ๆˆไบ†ๅฎ‰ๅ…จๆ€งๅ’Œ่บซไปฝ่ฎค่ฏใ€‚ๆœ็ปๆ•ฐๆฎๅบ“ๆˆ–่€…ๆ•ฐๆฎๆจกๅž‹็š„ๆธ—้€้ฃŽ้™ฉใ€‚ OpenAPI ไธญๅฎšไน‰็š„ๅฎ‰ๅ…จๆจกๅผ๏ผŒๅŒ…ๆ‹ฌ๏ผš * HTTP ๅŸบๆœฌ่ฎค่ฏใ€‚ -* **OAuth2** (ไนŸไฝฟ็”จ **JWT tokens**)ใ€‚ๅœจ [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}ๆŸฅ็œ‹ๆ•™็จ‹ใ€‚ +* **OAuth2**๏ผˆไนŸไฝฟ็”จ **JWT tokens**๏ผ‰ใ€‚ๅœจ [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}ๆŸฅ็œ‹ๆ•™็จ‹ใ€‚ * API ๅฏ†้’ฅ๏ผŒๅœจ: * ่ฏทๆฑ‚ๅคดใ€‚ * ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ - * Cookies, ็ญ‰็ญ‰ใ€‚ + * Cookies๏ผŒ็ญ‰็ญ‰ใ€‚ ๅŠ ไธŠๆฅ่‡ช Starlette๏ผˆๅŒ…ๆ‹ฌ **session cookie**๏ผ‰็š„ๆ‰€ๆœ‰ๅฎ‰ๅ…จ็‰นๆ€งใ€‚ ๆ‰€ๆœ‰็š„่ฟ™ไบ›้ƒฝๆ˜ฏๅฏๅค็”จ็š„ๅทฅๅ…ทๅ’Œ็ป„ไปถ๏ผŒๅฏไปฅ่ฝปๆพไธŽไฝ ็š„็ณป็ปŸ๏ผŒๆ•ฐๆฎไป“ๅบ“๏ผŒๅ…ณ็ณปๅž‹ไปฅๅŠ NoSQL ๆ•ฐๆฎๅบ“็ญ‰็ญ‰้›†ๆˆใ€‚ - - -### ไพ่ต–ๆณจๅ…ฅ +### ไพ่ต–ๆณจๅ…ฅ { #dependency-injection } FastAPI ๆœ‰ไธ€ไธชไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผบๅคง็š„ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ @@ -149,48 +144,47 @@ FastAPI ๆœ‰ไธ€ไธชไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผบๅคง็š„IDE/linter/brain** ้€‚้…: * ๅ› ไธบ pydantic ๆ•ฐๆฎ็ป“ๆž„ไป…ไป…ๆ˜ฏไฝ ๅฎšไน‰็š„็ฑป็š„ๅฎžไพ‹๏ผ›่‡ชๅŠจ่กฅๅ…จ๏ผŒlinting๏ผŒmypy ไปฅๅŠไฝ ็š„็›ด่ง‰ๅบ”่ฏฅๅฏไปฅๅ’Œไฝ ้ชŒ่ฏ็š„ๆ•ฐๆฎไธ€่ตทๆญฃๅธธๅทฅไฝœใ€‚ * ้ชŒ่ฏ**ๅคๆ‚็ป“ๆž„**: - * ไฝฟ็”จๅˆ†ๅฑ‚็š„ Pydantic ๆจกๅž‹, Python `typing`็š„ `List` ๅ’Œ `Dict` ็ญ‰็ญ‰ใ€‚ - * ้ชŒ่ฏๅ™จไฝฟๆˆ‘ไปฌ่ƒฝๅคŸ็ฎ€ๅ•ๆธ…ๆฅš็š„ๅฐ†ๅคๆ‚็š„ๆ•ฐๆฎๆจกๅผๅฎšไน‰ใ€ๆฃ€ๆŸฅๅนถ่ฎฐๅฝ•ไธบ JSON Schemaใ€‚ + * ไฝฟ็”จๅˆ†ๅฑ‚็š„ Pydantic ๆจกๅž‹๏ผŒPython `typing` ็š„ `List` ๅ’Œ `Dict` ็ญ‰็ญ‰ใ€‚ + * ้ชŒ่ฏๅ™จไฝฟๆˆ‘ไปฌ่ƒฝๅคŸ็ฎ€ๅ•ๆธ…ๆฅšๅœฐๅฐ†ๅคๆ‚็š„ๆ•ฐๆฎๆจกๅผๅฎšไน‰ใ€ๆฃ€ๆŸฅๅนถ่ฎฐๅฝ•ไธบ JSON Schemaใ€‚ * ไฝ ๅฏไปฅๆ‹ฅๆœ‰ๆทฑๅบฆ**ๅตŒๅฅ—็š„ JSON** ๅฏน่ฑกๅนถๅฏนๅฎƒไปฌ่ฟ›่กŒ้ชŒ่ฏๅ’Œๆณจ้‡Šใ€‚ * **ๅฏๆ‰ฉๅฑ•**: * Pydantic ๅ…่ฎธๅฎšไน‰่‡ชๅฎšไน‰ๆ•ฐๆฎ็ฑปๅž‹ๆˆ–่€…ไฝ ๅฏไปฅ็”จ้ชŒ่ฏๅ™จ่ฃ…้ฅฐๅ™จๅฏน่ขซ่ฃ…้ฅฐ็š„ๆจกๅž‹ไธŠ็š„ๆ–นๆณ•ๆ‰ฉๅฑ•้ชŒ่ฏใ€‚ diff --git a/docs/zh/docs/help-fastapi.md b/docs/zh/docs/help-fastapi.md index f01eb9eb5d..5a5157b5d3 100644 --- a/docs/zh/docs/help-fastapi.md +++ b/docs/zh/docs/help-fastapi.md @@ -1,147 +1,254 @@ -# ๅธฎๅŠฉ FastAPI ไธŽๆฑ‚ๅŠฉ +# ๅธฎๅŠฉ FastAPI - ่Žทๅ–ๅธฎๅŠฉ { #help-fastapi-get-help } -ๆ‚จๅ–œๆฌข **FastAPI** ๅ—๏ผŸ +ไฝ ๅ–œๆฌข **FastAPI** ๅ—๏ผŸ -ๆƒณๅธฎๅŠฉ FastAPI๏ผŸๅ…ถๅฎƒ็”จๆˆท๏ผŸ่ฟ˜ๆœ‰้กน็›ฎไฝœ่€…๏ผŸ +ๆƒณๅธฎๅŠฉ FastAPIใ€ๅ…ถไป–็”จๆˆทๅ’Œไฝœ่€…ๅ—๏ผŸ -ๆˆ–่ฆๆฑ‚ๅŠฉๆ€Žไนˆไฝฟ็”จ **FastAPI**๏ผŸ +ๆˆ–่€…ไฝ ๆƒณ่Žทๅ– **FastAPI** ็š„ๅธฎๅŠฉ๏ผŸ -ไปฅไธ‹ๅ‡ ็งๅธฎๅŠฉ็š„ๆ–นๅผ้ƒฝ้žๅธธ็ฎ€ๅ•๏ผˆๆœ‰ไบ›ๅช้œ€่ฆ็‚นๅ‡ปไธ€ไธคไธ‹้ผ ๆ ‡๏ผ‰ใ€‚ +ๆœ‰ๅพˆๅคš้žๅธธ็ฎ€ๅ•็š„ๆ–นๅผๅฏไปฅๅธฎๅฟ™๏ผˆๆœ‰ไบ›ๅช้œ€็‚นไธ€ไธคไธ‹๏ผ‰ใ€‚ -ๆฑ‚ๅŠฉ็š„ๆธ ้“ไนŸๅพˆๅคšใ€‚ +ๅŒๆ ท๏ผŒไนŸๆœ‰ๅคš็ง้€”ๅพ„ๅฏไปฅ่Žทๅพ—ๅธฎๅŠฉใ€‚ -## ่ฎข้˜…ๆ–ฐ้—ป้‚ฎไปถ +## ่ฎข้˜…ๆ–ฐ้—ป้‚ฎไปถ { #subscribe-to-the-newsletter } -ๆ‚จๅฏไปฅ่ฎข้˜… [**FastAPI ๅ’Œๅฎƒ็š„ๅฐไผ™ไผด** ๆ–ฐ้—ป้‚ฎไปถ](newsletter.md){.internal-link target=_blank}๏ผˆไธไผš็ปๅธธๆ”ถๅˆฐ๏ผ‰ +ไฝ ๅฏไปฅ่ฎข้˜…๏ผˆไธ้ข‘็น็š„๏ผ‰[**FastAPI and friends** ๆ–ฐ้—ป้‚ฎไปถ](newsletter.md){.internal-link target=_blank}๏ผŒ่Žทๅ–ๅฆ‚ไธ‹ๆ›ดๆ–ฐ๏ผš * FastAPI ๅŠๅ…ถๅฐไผ™ไผด็š„ๆ–ฐ้—ป ๐Ÿš€ * ๆŒ‡ๅ— ๐Ÿ“ * ๅŠŸ่ƒฝ โœจ * ็ ดๅๆ€งๆ›ดๆ”น ๐Ÿšจ -* ๅผ€ๅ‘ๆŠ€ๅทง โœ… +* ไฝฟ็”จๆŠ€ๅทง โœ… -## ๅœจๆŽจ็‰นไธŠๅ…ณๆณจ FastAPI +## ๅœจ X (Twitter) ไธŠๅ…ณๆณจ FastAPI { #follow-fastapi-on-x-twitter } -ๅœจ **X (Twitter)**ย ไธŠๅ…ณๆณจ @fastapi ่Žทๅ– **FastAPI** ็š„ๆœ€ๆ–ฐๆถˆๆฏใ€‚๐Ÿฆ +ๅœจ **X (Twitter)** ไธŠๅ…ณๆณจ @fastapi ่Žทๅ– **FastAPI** ็š„ๆœ€ๆ–ฐๅŠจๆ€ใ€‚๐Ÿฆ -## ๅœจ GitHub ไธŠไธบ **FastAPI** ๅŠ ๆ˜Ÿ +## ๅœจ GitHub ไธŠไธบ **FastAPI** ๅŠ ๆ˜Ÿ { #star-fastapi-in-github } -ๆ‚จๅฏไปฅๅœจ GitHub ไธŠ **Star** FastAPI๏ผˆๅช่ฆ็‚นๅ‡ปๅณไธŠ่ง’็š„ๆ˜Ÿๆ˜Ÿๅฐฑๅฏไปฅไบ†๏ผ‰๏ผš https://github.com/fastapi/fastapiใ€‚โญ๏ธ +ไฝ ๅฏไปฅๅœจ GitHub ไธŠไธบ FastAPI ็‚นไบฎใ€Œๆ˜Ÿๆ ‡ใ€๏ผˆ็‚นๅ‡ปๅณไธŠ่ง’็š„ๆ˜ŸๅฝขๆŒ‰้’ฎ๏ผ‰๏ผšhttps://github.com/fastapi/fastapiใ€‚โญ๏ธ -**Star** ไปฅๅŽ๏ผŒๅ…ถๅฎƒ็”จๆˆทๅฐฑ่ƒฝๆ›ดๅฎนๆ˜“ๆ‰พๅˆฐ FastAPI๏ผŒๅนถไบ†่งฃๅˆฐๅทฒ็ปๆœ‰ๅ…ถไป–็”จๆˆทๅœจไฝฟ็”จๅฎƒไบ†ใ€‚ +็‚นไบฎๆ˜Ÿๆ ‡ๅŽ๏ผŒๅ…ถไป–็”จๆˆทๆ›ดๅฎนๆ˜“ๅ‘็Žฐๅฎƒ๏ผŒๅนถ็œ‹ๅˆฐๅฎƒๅทฒ็ปๅฏน่ฎธๅคšไบบๆœ‰ๅธฎๅŠฉใ€‚ -## ๅ…ณๆณจ GitHub ่ต„ๆบๅบ“็š„็‰ˆๆœฌๅ‘ๅธƒ +## ๅ…ณๆณจ GitHub ่ต„ๆบๅบ“็š„็‰ˆๆœฌๅ‘ๅธƒ { #watch-the-github-repository-for-releases } -ๆ‚จ่ฟ˜ๅฏไปฅๅœจ GitHub ไธŠ **Watch** FastAPI๏ผŒ๏ผˆ็‚นๅ‡ปๅณไธŠ่ง’็š„ **Watch** ๆŒ‰้’ฎ๏ผ‰https://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ +ไฝ ๅฏไปฅๅœจ GitHub ไธŠใ€Œๅ…ณๆณจใ€FastAPI๏ผˆ็‚นๅ‡ปๅณไธŠ่ง’็š„ใ€Œwatchใ€ๆŒ‰้’ฎ๏ผ‰๏ผšhttps://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ -ๆ‚จๅฏไปฅ้€‰ๆ‹ฉๅชๅ…ณๆณจๅ‘ๅธƒ๏ผˆ**Releases only**๏ผ‰ใ€‚ +ๅœจ้‚ฃ้‡Œไฝ ๅฏไปฅ้€‰ๆ‹ฉใ€ŒReleases onlyใ€ใ€‚ -่ฟ™ๆ ท๏ผŒๆ‚จๅฐฑๅฏไปฅ๏ผˆๅœจ็”ตๅญ้‚ฎไปถ้‡Œ๏ผ‰ๆŽฅๆ”ถๅˆฐ **FastAPI** ๆ–ฐ็‰ˆๅ‘ๅธƒ็š„้€š็Ÿฅ๏ผŒๅŠๆ—ถไบ†่งฃ bug ไฟฎๅคไธŽๆ–ฐๅŠŸ่ƒฝใ€‚ +่ฟ™ๆ ทๅšไน‹ๅŽ๏ผŒๆฏๅฝ“ **FastAPI** ๅ‘ๅธƒๆ–ฐ็‰ˆๆœฌ๏ผˆๅŒ…ๅซไฟฎๅคๅ’Œๆ–ฐๅŠŸ่ƒฝ๏ผ‰๏ผŒไฝ ้ƒฝไผšๆ”ถๅˆฐ้€š็Ÿฅ๏ผˆ้‚ฎไปถ๏ผ‰ใ€‚ -## ่”็ณปไฝœ่€… +## ่”็ณปไฝœ่€… { #connect-with-the-author } -ๆ‚จๅฏไปฅ่”็ณป้กน็›ฎไฝœ่€…๏ผŒๅฐฑๆ˜ฏๆˆ‘๏ผˆSebastiรกn Ramรญrez / `tiangolo`๏ผ‰ใ€‚ +ไฝ ๅฏไปฅ่”็ณปๆˆ‘๏ผˆSebastiรกn Ramรญrez / `tiangolo`๏ผ‰๏ผŒไฝœ่€…ๆœฌไบบใ€‚ -ๆ‚จๅฏไปฅ๏ผš +ไฝ ๅฏไปฅ๏ผš -* ๅœจย **GitHub**ย ไธŠๅ…ณๆณจๆˆ‘ - * ไบ†่งฃๅ…ถๅฎƒๆˆ‘ๅˆ›ๅปบ็š„ๅผ€ๆบ้กน็›ฎ๏ผŒๆˆ–่ฎธๅฏนๆ‚จไผšๆœ‰ๅธฎๅŠฉ - * ๅ…ณๆณจๆˆ‘ไป€ไนˆๆ—ถๅ€™ๅˆ›ๅปบๆ–ฐ็š„ๅผ€ๆบ้กน็›ฎ -* ๅœจ **X (Twitter)**ย ไธŠๅ…ณๆณจๆˆ‘ - * ๅ‘Š่ฏ‰ๆˆ‘ๆ‚จไฝฟ็”จ FastAPI๏ผˆๆˆ‘้žๅธธไนๆ„ๅฌๅˆฐ่ฟ™็งๆถˆๆฏ๏ผ‰ - * ๆŽฅๆ”ถๆˆ‘ๅ‘ๅธƒๅ…ฌๅ‘Šๆˆ–ๆ–ฐๅทฅๅ…ท็š„ๆถˆๆฏ - * ๆ‚จ่ฟ˜ๅฏไปฅๅ…ณๆณจ@fastapi on X (Twitter)๏ผŒ่ฟ™ๆ˜ฏไธช็‹ฌ็ซ‹็š„่ดฆๅท -* ๅœจ**้ข†่‹ฑ**ไธŠ่”็ณปๆˆ‘ - * ๆŽฅๆ”ถๆˆ‘ๅ‘ๅธƒๅ…ฌๅ‘Šๆˆ–ๆ–ฐๅทฅๅ…ท็š„ๆถˆๆฏ๏ผˆ่™ฝ็„ถๆˆ‘็”จ X (Twitter) ๆฏ”่พƒๅคš๏ผ‰ -* ้˜…่ฏปๆˆ‘ๅœจ **Dev.to** ๆˆ– **Medium** ไธŠ็š„ๆ–‡็ซ ๏ผŒๆˆ–ๅ…ณๆณจๆˆ‘ - * ้˜…่ฏปๆˆ‘็š„ๅ…ถๅฎƒๆƒณๆณ•ใ€ๆ–‡็ซ ๏ผŒไบ†่งฃๆˆ‘ๅˆ›ๅปบ็š„ๅทฅๅ…ท - * ๅ…ณๆณจๆˆ‘๏ผŒ่ฟ™ๆ ทๅฐฑๅฏไปฅ้šๆ—ถ็œ‹ๅˆฐๆˆ‘ๅ‘ๅธƒ็š„ๆ–ฐๆ–‡็ซ  +* ๅœจ **GitHub** ไธŠๅ…ณๆณจๆˆ‘ใ€‚ + * ไบ†่งฃๆˆ‘ๅˆ›ๅปบ็š„ๅ…ถไป–ๅผ€ๆบ้กน็›ฎ๏ผŒไนŸ่ฎธๅฏนไฝ ๆœ‰ๅธฎๅŠฉใ€‚ + * ๅ…ณๆณจๆˆ‘ไฝ•ๆ—ถๅˆ›ๅปบๆ–ฐ็š„ๅผ€ๆบ้กน็›ฎใ€‚ +* ๅ…ณๆณจๆˆ‘ๅœจ **X (Twitter)** ๆˆ– Mastodonใ€‚ + * ๅ‘Š่ฏ‰ๆˆ‘ไฝ ๅฆ‚ไฝ•ไฝฟ็”จ FastAPI๏ผˆๆˆ‘ๅพˆๅ–œๆฌขๅฌ่ฟ™ไบ›๏ผ‰ใ€‚ + * ่Žทๅ–ๆˆ‘ๅ‘ๅธƒๅ…ฌๅ‘Šๆˆ–ๆ–ฐๅทฅๅ…ท็š„ๆถˆๆฏใ€‚ + * ไฝ ไนŸๅฏไปฅๅ…ณๆณจ @fastapi on X (Twitter)๏ผˆ็‹ฌ็ซ‹่ดฆๅท๏ผ‰ใ€‚ +* ๅœจ **LinkedIn** ไธŠๅ…ณๆณจๆˆ‘ใ€‚ + * ่Žทๅ–ๆˆ‘ๅ‘ๅธƒๅ…ฌๅ‘Šๆˆ–ๆ–ฐๅทฅๅ…ท็š„ๆถˆๆฏ๏ผˆไธ่ฟ‡ๆˆ‘ๆ›ดๅธธ็”จ X (Twitter) ๐Ÿคทโ€โ™‚๏ผ‰ใ€‚ +* ้˜…่ฏปๆˆ‘ๅœจ **Dev.to** ๆˆ– **Medium** ไธŠ็š„ๆ–‡็ซ ๏ผˆๆˆ–ๅ…ณๆณจๆˆ‘๏ผ‰ใ€‚ + * ้˜…่ฏปๆˆ‘็š„ๅ…ถไป–ๆƒณๆณ•ใ€ๆ–‡็ซ ๏ผŒไปฅๅŠๆˆ‘ๅˆ›ๅปบ็š„ๅทฅๅ…ทใ€‚ + * ๅ…ณๆณจๆˆ‘๏ผŒ่ฟ™ๆ ทๅฝ“ๆˆ‘ๅ‘ๅธƒๆ–ฐๆ–‡็ซ ๆ—ถไฝ ไผš็ฌฌไธ€ๆ—ถ้—ด็œ‹ๅˆฐใ€‚ -## Tweet about **FastAPI** +## ๅ‘ๆŽจ่ฐˆ่ฐˆ **FastAPI** { #tweet-about-fastapi } -Tweet about **FastAPI** ่ฎฉๆˆ‘ๅ’Œๅคงๅฎถ็Ÿฅ้“ๆ‚จไธบไป€ไนˆๅ–œๆฌข FastAPIใ€‚๐ŸŽ‰ +Tweet about **FastAPI**๏ผŒๅ‘Š่ฏ‰ๆˆ‘ๅ’Œๅคงๅฎถไฝ ไธบไป€ไนˆๅ–œๆฌขๅฎƒใ€‚๐ŸŽ‰ -็Ÿฅ้“ๆœ‰ไบบไฝฟ็”จ **FastAPI**๏ผŒๆˆ‘ไผšๅพˆๅผ€ๅฟƒ๏ผŒๆˆ‘ไนŸๆƒณ็Ÿฅ้“ๆ‚จไธบไป€ไนˆๅ–œๆฌข FastAPI๏ผŒไปฅๅŠๆ‚จๅœจไป€ไนˆ้กน็›ฎ/ๅ“ชไบ›ๅ…ฌๅธไฝฟ็”จ FastAPI๏ผŒ็ญ‰็ญ‰ใ€‚ +ๆˆ‘ๅพˆ้ซ˜ๅ…ดๅฌๅˆฐ **FastAPI** ็š„ไฝฟ็”จๆƒ…ๅ†ตใ€ไฝ ๅ–œๆฌขๅฎƒ็š„ๅ“ชไบ›็‚นใ€ไฝ ๅœจๅ“ชไธช้กน็›ฎ/ๅ…ฌๅธไฝฟ็”จๅฎƒ๏ผŒ็ญ‰็ญ‰ใ€‚ -## ไธบ FastAPI ๆŠ•็ฅจ +## ไธบ FastAPI ๆŠ•็ฅจ { #vote-for-fastapi } -* ๅœจ Slant ไธŠไธบย **FastAPI** ๆŠ•็ฅจ -* ๅœจ AlternativeTo ไธŠไธบย **FastAPI** ๆŠ•็ฅจ +* ๅœจ Slant ไธŠไธบ **FastAPI** ๆŠ•็ฅจใ€‚ +* ๅœจ AlternativeTo ไธŠไธบ **FastAPI** ๆŠ•็ฅจใ€‚ +* ๅœจ StackShare ไธŠๆ ‡ๆณจไฝ ๅœจ็”จ **FastAPI**ใ€‚ -## ๅœจ GitHub ไธŠๅธฎๅŠฉๅ…ถไป–ไบบ่งฃๅ†ณ้—ฎ้ข˜ +## ๅœจ GitHub ไธŠๅธฎๅˆซไบบ่งฃ็ญ”้—ฎ้ข˜ { #help-others-with-questions-in-github } -ๆ‚จๅฏไปฅๆŸฅ็œ‹็Žฐๆœ‰ issues๏ผŒๅนถๅฐ่ฏ•ๅธฎๅŠฉๅ…ถไป–ไบบ่งฃๅ†ณ้—ฎ้ข˜๏ผŒ่ฏดไธๅฎšๆ‚จ่ƒฝ่งฃๅ†ณ่ฟ™ไบ›้—ฎ้ข˜ๅ‘ขใ€‚๐Ÿค“ +ไฝ ๅฏไปฅๅฐ่ฏ•ๅœจไปฅไธ‹ๅœฐๆ–นๅธฎๅŠฉไป–ไบบ่งฃ็ญ”้—ฎ้ข˜๏ผš -ๅฆ‚ๆžœๅธฎๅŠฉๅพˆๅคšไบบ่งฃๅ†ณไบ†้—ฎ้ข˜๏ผŒๆ‚จๅฐฑๆœ‰ๅฏ่ƒฝๆˆไธบ [FastAPI ็š„ๅฎ˜ๆ–นไธ“ๅฎถ](fastapi-people.md#_3){.internal-link target=_blank}ใ€‚๐ŸŽ‰ +* GitHub Discussions +* GitHub Issues -## ็›‘ๅฌ GitHub ่ต„ๆบๅบ“ +ๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝ ไนŸ่ฎธๅทฒ็ป็Ÿฅ้“่ฟ™ไบ›้—ฎ้ข˜็š„็ญ”ๆกˆไบ†ใ€‚๐Ÿค“ -ๆ‚จๅฏไปฅๅœจ GitHub ไธŠใ€Œ็›‘ๅฌใ€FastAPI๏ผˆ็‚นๅ‡ปๅณไธŠ่ง’็š„ "watch" ๆŒ‰้’ฎ๏ผ‰๏ผš https://github.com/fastapi/fastapi. ๐Ÿ‘€ +ๅฆ‚ๆžœไฝ ๅธฎๅŠฉไบ†ๅพˆๅคšไบบ่งฃ็ญ”้—ฎ้ข˜๏ผŒไฝ ไผšๆˆไธบๅฎ˜ๆ–น็š„ [FastAPI ไธ“ๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank}ใ€‚๐ŸŽ‰ -ๅฆ‚ๆžœๆ‚จ้€‰ๆ‹ฉ "Watching" ่€Œไธๆ˜ฏ "Releases only"๏ผŒๆœ‰ไบบๅˆ›ๅปบๆ–ฐ Issue ๆ—ถ๏ผŒๆ‚จไผšๆŽฅๆ”ถๅˆฐ้€š็Ÿฅใ€‚ +ๅช่ฆ่ฎฐไฝ๏ผŒๆœ€้‡่ฆ็š„ไธ€็‚นๆ˜ฏ๏ผšๅฐฝ้‡ๅ‹ๅ–„ใ€‚ไบบไปฌๅธฆ็€ๆŒซ่ดฅๆ„Ÿ่€Œๆฅ๏ผŒๅพˆๅคšๆ—ถๅ€™ไป–ไปฌ็š„ๆ้—ฎๆ–นๅผๅนถไธ็†ๆƒณ๏ผŒไฝ†่ฏทๅฐฝไฝ ๆ‰€่ƒฝๅœฐๅ‹ๅฅฝๅฏนๅพ…ใ€‚๐Ÿค— -็„ถๅŽๆ‚จๅฐฑๅฏไปฅๅฐ่ฏ•ๅนถๅธฎๅŠฉไป–ไปฌ่งฃๅ†ณ้—ฎ้ข˜ใ€‚ +ๆˆ‘ไปฌ็š„็›ฎๆ ‡ๆ˜ฏ่ฎฉ **FastAPI** ็คพๅŒบๅ‹ๅฅฝไธ”ๅŒ…ๅฎนใ€‚ๅŒๆ—ถ๏ผŒไนŸไธ่ฆๆŽฅๅ—ๅฏนไป–ไบบ็š„้œธๅ‡Œๆˆ–ไธๅฐŠ้‡ใ€‚ๆˆ‘ไปฌ้œ€่ฆๅฝผๆญค็…ง้กพใ€‚ -## ๅˆ›ๅปบ Issue +--- -ๆ‚จๅฏไปฅๅœจ GitHub ่ต„ๆบๅบ“ไธญๅˆ›ๅปบ Issue๏ผŒไพ‹ๅฆ‚๏ผš +ไปฅไธ‹ๆ˜ฏๅฆ‚ไฝ•ๅธฎๅŠฉไป–ไบบ่งฃ็ญ”้—ฎ้ข˜๏ผˆๅœจ Discussions ๆˆ– Issues ไธญ๏ผ‰๏ผš -* ๆๅ‡บ**้—ฎ้ข˜**ๆˆ–**ๆ„่ง** -* ๆๅ‡บๆ–ฐ**็‰นๆ€ง**ๅปบ่ฎฎ +### ็†่งฃ้—ฎ้ข˜ { #understand-the-question } -**ๆณจๆ„**๏ผšๅฆ‚ๆžœๆ‚จๅˆ›ๅปบ Issue๏ผŒๆˆ‘ไผš่ฆๆฑ‚ๆ‚จไนŸ่ฆๅธฎๅŠฉๅˆซ็š„็”จๆˆทใ€‚๐Ÿ˜‰ +* ็œ‹็œ‹ไฝ ๆ˜ฏๅฆ่ƒฝ็†่งฃๆ้—ฎ่€…็š„**็›ฎ็š„**ๅ’Œไฝฟ็”จๅœบๆ™ฏใ€‚ -## ๅˆ›ๅปบ PR +* ็„ถๅŽๆฃ€ๆŸฅ้—ฎ้ข˜๏ผˆ็ปๅคงๅคšๆ•ฐๆ˜ฏๆ้—ฎ๏ผ‰ๆ˜ฏๅฆ**ๆธ…ๆ™ฐ**ใ€‚ -ๆ‚จๅฏไปฅๅˆ›ๅปบ PR ไธบๆบไปฃ็ ๅš[่ดก็Œฎ](contributing.md){.internal-link target=_blank}๏ผŒไพ‹ๅฆ‚๏ผš +* ๅพˆๅคšๆ—ถๅ€™๏ผŒ้—ฎ้ข˜ๆ˜ฏๅ›ด็ป•ๆ้—ฎ่€…ๆƒณ่ฑกไธญ็š„่งฃๅ†ณๆ–นๆกˆ๏ผŒไฝ†ๅฏ่ƒฝๆœ‰**ๆ›ดๅฅฝ็š„**ๆ–นๆกˆใ€‚ๅฆ‚ๆžœไฝ ๆ›ดๅฅฝๅœฐ็†่งฃไบ†้—ฎ้ข˜ๅ’Œไฝฟ็”จๅœบๆ™ฏ๏ผŒไฝ ๅฐฑๅฏ่ƒฝๆๅ‡บๆ›ด**ๅˆ้€‚็š„ๆ›ฟไปฃๆ–นๆกˆ**ใ€‚ -* ไฟฎๆ”นๆ–‡ๆกฃ้”™ๅˆซๅญ— -* ็ผ–่พ‘่ฟ™ไธชๆ–‡ไปถ๏ผŒๅˆ†ไบซ FastAPI ็š„ๆ–‡็ซ ใ€่ง†้ข‘ใ€ๅšๅฎข๏ผŒไธ่ฎบๆ˜ฏๆ‚จ่‡ชๅทฑ็š„๏ผŒ่ฟ˜ๆ˜ฏๆ‚จ็œ‹ๅˆฐ็š„้ƒฝๆˆ - * ๆณจๆ„๏ผŒๆทปๅŠ ็š„้“พๆŽฅ่ฆๆ”พๅœจๅฏนๅบ”ๅŒบๅ—็š„ๅผ€ๅคด -* [็ฟป่ฏ‘ๆ–‡ๆกฃ](contributing.md#_8){.internal-link target=_blank} - * ๅฎก้˜…ๅˆซไบบ็ฟป่ฏ‘็š„ๆ–‡ๆกฃ -* ๆทปๅŠ ๆ–ฐ็š„ๆ–‡ๆกฃๅ†…ๅฎน -* ไฟฎๅค็Žฐๆœ‰้—ฎ้ข˜/Bug -* ๆทปๅŠ ๆ–ฐๅŠŸ่ƒฝ +* ๅฆ‚ๆžœไฝ ๆฒก่ƒฝ็†่งฃ้—ฎ้ข˜๏ผŒ่ฏท่ฏทๆฑ‚ๆ›ดๅคš**็ป†่Š‚**ใ€‚ -## ๅŠ ๅ…ฅ่Šๅคฉ +### ๅค็Žฐ้—ฎ้ข˜ { #reproduce-the-problem } -ๅฟซๅŠ ๅ…ฅ ๐Ÿ‘ฅ Discord ่ŠๅคฉๆœๅŠกๅ™จ ๐Ÿ‘ฅ ๅ’Œ FastAPI ็คพๅŒบ้‡Œ็š„ๅฐไผ™ไผดไธ€่ตทๅ“ˆ็šฎๅงใ€‚ +ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹ไธŽ้—ฎ้ข˜็›ธๅ…ณ็š„้ƒฝๆ˜ฏๆ้—ฎ่€…็š„**ๅŽŸๅง‹ไปฃ็ **ใ€‚ -/// tip | ๆ็คบ +ๅพˆๅคšๆ—ถๅ€™ไป–ไปฌๅชไผš็ฒ˜่ดดไธ€ๅฐๆฎตไปฃ็ ๏ผŒไฝ†่ฟ™ไธ่ถณไปฅ**ๅค็Žฐ้—ฎ้ข˜**ใ€‚ + +* ไฝ ๅฏไปฅ่ฏทไป–ไปฌๆไพ›ไธ€ไธชๅฏๆœ€ๅฐๅค็Žฐ็š„็คบไพ‹๏ผŒไฝ ๅฏไปฅ**ๅคๅˆถ็ฒ˜่ดด**ๅนถๅœจๆœฌๅœฐ่ฟ่กŒ๏ผŒ็œ‹ๅˆฐไธŽไป–ไปฌ็›ธๅŒ็š„้”™่ฏฏๆˆ–่กŒไธบ๏ผŒๆˆ–่€…ๆ›ดๅฅฝๅœฐ็†่งฃไป–ไปฌ็š„็”จไพ‹ใ€‚ + +* ๅฆ‚ๆžœไฝ ้žๅธธ็ƒญๅฟƒ๏ผŒไฝ ไนŸๅฏไปฅๅฐ่ฏ•ไป…ๆ นๆฎ้—ฎ้ข˜ๆ่ฟฐ่‡ชๅทฑ**ๆž„้€ ไธ€ไธช็คบไพ‹**ใ€‚ไธ่ฟ‡่ฆ่ฎฐไฝ๏ผŒ่ฟ™ๅฏ่ƒฝไผš่Šฑๅพˆๅคšๆ—ถ้—ด๏ผŒ้€šๅธธๅ…ˆ่ฏทไป–ไปฌๆพ„ๆธ…้—ฎ้ข˜ไผšๆ›ดๅฅฝใ€‚ + +### ๆๅ‡บ่งฃๅ†ณๆ–นๆกˆ { #suggest-solutions } + +* ๅœจ่ƒฝๅคŸ็†่งฃ้—ฎ้ข˜ไน‹ๅŽ๏ผŒไฝ ๅฏไปฅ็ป™ๅ‡บไธ€ไธชๅฏ่ƒฝ็š„**็ญ”ๆกˆ**ใ€‚ + +* ๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒๆ›ดๅฅฝ็š„ๆ˜ฏๅŽป็†่งฃไป–ไปฌ**ๅบ•ๅฑ‚็š„้—ฎ้ข˜ๆˆ–ๅœบๆ™ฏ**๏ผŒๅ› ไธบๅฏ่ƒฝๅญ˜ๅœจๆฏ”ไป–ไปฌๅฐ่ฏ•็š„ๆ–นๆณ•ๆ›ดๅฅฝ็š„่งฃๅ†ณๆ–นๅผใ€‚ + +### ่ฏทๆฑ‚ๅ…ณ้—ญ้—ฎ้ข˜ { #ask-to-close } + +ๅฆ‚ๆžœไป–ไปฌๅ›žๅคไบ†๏ผŒๅพˆๆœ‰ๅฏ่ƒฝไฝ ๅทฒ็ป่งฃๅ†ณไบ†ไป–ไปฌ็š„้—ฎ้ข˜๏ผŒๆญๅ–œ๏ผŒ**ไฝ ๆ˜ฏ่‹ฑ้›„**๏ผ๐Ÿฆธ + +* ็Žฐๅœจ๏ผŒๅฆ‚ๆžœ้—ฎ้ข˜ๅทฒ่งฃๅ†ณ๏ผŒไฝ ๅฏไปฅ่ฏทไป–ไปฌ๏ผš + * ๅœจ GitHub Discussions ไธญ๏ผšๅฐ†ไฝ ็š„่ฏ„่ฎบๆ ‡่ฎฐไธบ**็ญ”ๆกˆ**ใ€‚ + * ๅœจ GitHub Issues ไธญ๏ผš**ๅ…ณ้—ญ**่ฏฅ issueใ€‚ + +## ๅ…ณๆณจ GitHub ่ต„ๆบๅบ“ { #watch-the-github-repository } + +ไฝ ๅฏไปฅๅœจ GitHub ไธŠใ€Œๅ…ณๆณจใ€FastAPI๏ผˆ็‚นๅ‡ปๅณไธŠ่ง’็š„ใ€Œwatchใ€ๆŒ‰้’ฎ๏ผ‰๏ผšhttps://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ + +ๅฆ‚ๆžœไฝ ้€‰ๆ‹ฉใ€ŒWatchingใ€่€Œ้žใ€ŒReleases onlyใ€๏ผŒๅฝ“ๆœ‰ไบบๅˆ›ๅปบๆ–ฐ็š„ issue ๆˆ–้—ฎ้ข˜ๆ—ถไฝ ไผšๆ”ถๅˆฐ้€š็Ÿฅใ€‚ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšๅช้€š็Ÿฅๆ–ฐ issuesใ€discussionsใ€PR ็ญ‰ใ€‚ + +็„ถๅŽไฝ ๅฐฑๅฏไปฅๅฐ่ฏ•ๅธฎๅŠฉไป–ไปฌ่งฃๅ†ณ่ฟ™ไบ›้—ฎ้ข˜ใ€‚ + +## ๆ้—ฎ { #ask-questions } + +ไฝ ๅฏไปฅๅœจ GitHub ่ต„ๆบๅบ“ไธญๅˆ›ๅปบไธ€ไธชๆ–ฐ้—ฎ้ข˜๏ผˆQuestion๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + +* ๆๅ‡บไธ€ไธช**้—ฎ้ข˜**ๆˆ–ๅ…ณไบŽๆŸไธช**้—ฎ้ข˜**็š„ๆฑ‚ๅŠฉใ€‚ +* ๅปบ่ฎฎไธ€ไธชๆ–ฐ็š„**ๅŠŸ่ƒฝ**ใ€‚ + +**ๆณจๆ„**๏ผšๅฆ‚ๆžœไฝ ่ฟ™ไนˆๅšไบ†๏ผŒๆˆ‘ไนŸไผš่ฏทไฝ ๅŽปๅธฎๅŠฉๅ…ถไป–ไบบใ€‚๐Ÿ˜‰ + +## ๅฎก้˜… Pull Request { #review-pull-requests } + +ไฝ ๅฏไปฅๅธฎๆˆ‘ๅฎก้˜…ไป–ไบบ็š„ Pull Requestใ€‚ + +ๅ†ๆฌกๆ้†’๏ผŒ่ฏทๅฐฝๅŠ›ไฟๆŒๅ‹ๅ–„ใ€‚๐Ÿค— + +--- + +ไธ‹้ขๆ˜ฏ้œ€่ฆๆณจๆ„็š„็‚น๏ผŒไปฅๅŠๅฆ‚ไฝ•ๅฎก้˜…ไธ€ไธช Pull Request๏ผš + +### ็†่งฃ้—ฎ้ข˜ { #understand-the-problem } + +* ้ฆ–ๅ…ˆ๏ผŒ็กฎไฟไฝ **็†่งฃ่ฟ™ไธช PR ่ฆ่งฃๅ†ณ็š„้—ฎ้ข˜**ใ€‚ๅฎƒๅฏ่ƒฝๅœจ GitHub Discussion ๆˆ– issue ไธญๆœ‰ๆ›ด้•ฟ็š„่ฎจ่ฎบใ€‚ + +* ไนŸๆœ‰ๅพˆๅคงๅฏ่ƒฝ่ฟ™ไธช PR ๅฎž้™…ไธŠๅนถไธ้œ€่ฆ๏ผŒๅ› ไธบ้—ฎ้ข˜ๅฏไปฅ็”จ**ไธๅŒๆ–นๅผ**่งฃๅ†ณใ€‚่ฟ™็งๆƒ…ๅ†ตไธ‹ไฝ ๅฏไปฅๆๅ‡บๆˆ–่ฏข้—ฎ่ฏฅๆ–นๆกˆใ€‚ + +### ไธ็”จ่ฟ‡ๅˆ†ๆ‹…ๅฟƒ้ฃŽๆ ผ { #dont-worry-about-style } -ๅฆ‚ๆœ‰้—ฎ้ข˜๏ผŒ่ฏทๅœจ GitHub Issues ้‡Œๆ้—ฎ๏ผŒๅœจ่ฟ™้‡Œๆ›ดๅฎนๆ˜“ๅพ—ๅˆฐ [FastAPI ไธ“ๅฎถ](fastapi-people.md#_3){.internal-link target=_blank}็š„ๅธฎๅŠฉใ€‚ +* ไธ็”จๅคชๅœจๆ„ๆไบคไฟกๆฏ้ฃŽๆ ผ็ญ‰๏ผŒๆˆ‘ไผšๅœจๅˆๅนถๆ—ถ squash ๅนถๆ‰‹ๅŠจ่ฐƒๆ•ดๆไบคไฟกๆฏใ€‚ -่Šๅคฉๅฎคไป…ไพ›้—ฒ่Šใ€‚ +* ไนŸไธ็”จ่ฟ‡ๅˆ†ๆ‹…ๅฟƒไปฃ็ ้ฃŽๆ ผ่ง„ๅˆ™๏ผŒๅทฒ็ปๆœ‰่‡ชๅŠจๅŒ–ๅทฅๅ…ทๅœจๆฃ€ๆŸฅใ€‚ + +ๅฆ‚ๆžœ่ฟ˜ๆœ‰ๅ…ถไป–้ฃŽๆ ผๆˆ–ไธ€่‡ดๆ€ง้œ€ๆฑ‚๏ผŒๆˆ‘ไผš็›ดๆŽฅๆๅ‡บ๏ผŒๆˆ–่€…ๆˆ‘ไผšๅœจๅ…ถไธŠ่ฟฝๅŠ ๆไบคๅšๅฟ…่ฆไฟฎๆ”นใ€‚ + +### ๆฃ€ๆŸฅไปฃ็  { #check-the-code } + +* ๆฃ€ๆŸฅๅนถ้˜…่ฏปไปฃ็ ๏ผŒ็œ‹็œ‹ๆ˜ฏๅฆ่ฏดๅพ—้€š๏ผŒ**ๅœจๆœฌๅœฐ่ฟ่กŒ**ๅนถ็กฎ่ฎคๅฎƒ็กฎๅฎž่งฃๅ†ณไบ†้—ฎ้ข˜ใ€‚ + +* ็„ถๅŽ**่ฏ„่ฎบ**่ฏดๆ˜Žไฝ ๅทฒ็ป่ฟ™ๆ ทๅšไบ†๏ผŒ่ฟ™ๆ ทๆˆ‘ๅฐฑ็Ÿฅ้“ไฝ ็กฎๅฎžๆฃ€ๆŸฅ่ฟ‡ใ€‚ + +/// info | ไฟกๆฏ + +ไธๅนธ็š„ๆ˜ฏ๏ผŒๆˆ‘ไธ่ƒฝไป…ไป…ไฟกไปป้‚ฃไบ›ๆœ‰ๅพˆๅคšไบบๆ‰นๅ‡†็š„ PRใ€‚ + +ๅคšๆฌกๅ‘็”Ÿ่ฟ‡่ฟ™ๆ ท็š„ๆƒ…ๅ†ต๏ผšPR ๆœ‰ 3ใ€5 ไธช็”š่‡ณๆ›ดๅคš็š„ๆ‰นๅ‡†๏ผŒๅฏ่ƒฝๆ˜ฏๅ› ไธบๆ่ฟฐๅพˆๅธๅผ•ไบบ๏ผŒไฝ†ๅฝ“ๆˆ‘ๆฃ€ๆŸฅๆ—ถ๏ผŒๅฎƒไปฌๅฎž้™…ไธŠๆ˜ฏๅ็š„ใ€ๆœ‰ bug๏ผŒๆˆ–่€…ๅนถๆฒกๆœ‰่งฃๅ†ณๅฎƒๅฃฐ็งฐ่ฆ่งฃๅ†ณ็š„้—ฎ้ข˜ใ€‚๐Ÿ˜… + +ๆ‰€ไปฅ๏ผŒ็œŸๆญฃ้‡่ฆ็š„ๆ˜ฏไฝ ็กฎๅฎž่ฏป่ฟ‡ๅนถ่ฟ่กŒ่ฟ‡ไปฃ็ ๏ผŒๅนถๅœจ่ฏ„่ฎบ้‡Œๅ‘Š่ฏ‰ๆˆ‘ไฝ ๅš่ฟ‡่ฟ™ไบ›ใ€‚๐Ÿค“ /// -### ๅˆซๅœจ่Šๅคฉๅฎค้‡Œๆ้—ฎ +* ๅฆ‚ๆžœ PR ๅฏไปฅๅœจๆŸไบ›ๆ–น้ข็ฎ€ๅŒ–๏ผŒไฝ ๅฏไปฅๆๅ‡บๅปบ่ฎฎ๏ผŒไฝ†ๆฒกๅฟ…่ฆ่ฟ‡ๅˆ†ๆŒ‘ๅ‰”๏ผŒๅพˆๅคšไธœ่ฅฟๆฏ”่พƒไธป่ง‚๏ผˆๆˆ‘ไนŸไผšๆœ‰ๆˆ‘่‡ชๅทฑ็š„็œ‹ๆณ• ๐Ÿ™ˆ๏ผ‰๏ผŒๅ› ๆญคๅฐฝ้‡ๅ…ณๆณจๅ…ณ้”ฎ็‚นๆ›ดๅฅฝใ€‚ + +### ๆต‹่ฏ• { #tests } + +* ๅธฎๆˆ‘ๆฃ€ๆŸฅ PR ๆ˜ฏๅฆๅŒ…ๅซ**ๆต‹่ฏ•**ใ€‚ + +* ็กฎ่ฎคๅœจๅˆๅนถ PR ไน‹ๅ‰๏ผŒๆต‹่ฏ•**ไผšๅคฑ่ดฅ**ใ€‚๐Ÿšจ + +* ็„ถๅŽ็กฎ่ฎคๅˆๅนถ PR ไน‹ๅŽ๏ผŒๆต‹่ฏ•**่ƒฝ้€š่ฟ‡**ใ€‚โœ… + +* ๅพˆๅคš PR ๆฒกๆœ‰ๆต‹่ฏ•๏ผŒไฝ ๅฏไปฅ**ๆ้†’**ไป–ไปฌๆทปๅŠ ๆต‹่ฏ•๏ผŒๆˆ–่€…ไฝ ็”š่‡ณๅฏไปฅ่‡ชๅทฑ**ๅปบ่ฎฎ**ไธ€ไบ›ๆต‹่ฏ•ใ€‚่ฟ™ๆ˜ฏๆœ€่€—ๆ—ถ็š„้ƒจๅˆ†ไน‹ไธ€๏ผŒไฝ ่ƒฝๅœจ่ฟ™ๆ–น้ขๅธฎไธŠๅคงๅฟ™ใ€‚ + +* ็„ถๅŽไนŸ่ฏท่ฏ„่ฎบไฝ ๅšไบ†ๅ“ชไบ›้ชŒ่ฏ๏ผŒ่ฟ™ๆ ทๆˆ‘ๅฐฑ็Ÿฅ้“ไฝ ๆฃ€ๆŸฅ่ฟ‡ใ€‚๐Ÿค“ -ๆณจๆ„๏ผŒ่Šๅคฉๅฎคๆ›ดๅ€พๅ‘ไบŽโ€œ้—ฒ่Šโ€๏ผŒ็ปๅธธๆœ‰ไบบไผšๆๅ‡บไธ€ไบ›็ฌผ็ปŸๅพ—่ฎฉไบบ้šพไปฅๅ›ž็ญ”็š„้—ฎ้ข˜๏ผŒๆ‰€ไปฅๅœจ่ฟ™้‡Œๆ้—ฎไธ€่ˆฌๆฒกไบบๅ›ž็ญ”ใ€‚ +## ๅˆ›ๅปบ Pull Request { #create-a-pull-request } -GitHub Issues ้‡Œๆไพ›ไบ†ๆจกๆฟ๏ผŒๆŒ‡ๅผ•ๆ‚จๆๅ‡บๆญฃ็กฎ็š„้—ฎ้ข˜๏ผŒๆœ‰ๅˆฉไบŽ่Žทๅพ—ไผ˜่ดจ็š„ๅ›ž็ญ”๏ผŒ็”š่‡ณๅฏ่ƒฝ่งฃๅ†ณๆ‚จ่ฟ˜ๆฒกๆœ‰ๆƒณๅˆฐ็š„้—ฎ้ข˜ใ€‚่€Œไธ”ๅฐฑ็ฎ—็ญ”็–‘่งฃๆƒ‘่ฆ่€—่ดนไธๅฐ‘ๆ—ถ้—ด๏ผŒๆˆ‘่ฟ˜ๆ˜ฏไผšๅฐฝ้‡ๅœจ GitHub ้‡Œๅ›ž็ญ”้—ฎ้ข˜ใ€‚ไฝ†ๅœจ่Šๅคฉๅฎค้‡Œ๏ผŒๆˆ‘ๅฐฑๆฒกๅŠŸๅคซ่ฟ™ไนˆๅšไบ†ใ€‚๐Ÿ˜… +ไฝ ๅฏไปฅ้€š่ฟ‡ Pull Request ไธบๆบไปฃ็ [ๅš่ดก็Œฎ](contributing.md){.internal-link target=_blank}๏ผŒไพ‹ๅฆ‚๏ผš -่Šๅคฉๅฎค้‡Œ็š„่Šๅคฉๅ†…ๅฎนไนŸไธๅฆ‚ GitHub ้‡Œๅฅฝๆœ็ดข๏ผŒ่Šๅคฉ้‡Œ็š„้—ฎ็ญ”ๅพˆๅฎนๆ˜“ๅฐฑๆ‰พไธๅˆฐไบ†ใ€‚ๅชๆœ‰ๅœจ GitHub Issues ้‡Œ็š„้—ฎ็ญ”ๆ‰่ƒฝๅธฎๅŠฉๆ‚จๆˆไธบ [FastAPI ไธ“ๅฎถ](fastapi-people.md#_3){.internal-link target=_blank}๏ผŒๅœจ GitHub Issues ไธญไธบๆ‚จๅธฆๆฅๆ›ดๅคšๅ…ณๆณจใ€‚ +* ไฟฎๆญฃๆ–‡ๆกฃไธญ็š„ไธ€ไธช้”™ๅˆซๅญ—ใ€‚ +* ้€š่ฟ‡็ผ–่พ‘่ฟ™ไธชๆ–‡ไปถๅˆ†ไบซไฝ ๅˆ›ๅปบๆˆ–ๅ‘็Žฐ็š„ๅ…ณไบŽ FastAPI ็š„ๆ–‡็ซ ใ€่ง†้ข‘ๆˆ–ๆ’ญๅฎขใ€‚ + * ่ฏท็กฎไฟๆŠŠไฝ ็š„้“พๆŽฅๆทปๅŠ ๅˆฐ็›ธๅบ”ๅŒบๅ—็š„ๅผ€ๅคดใ€‚ +* ๅธฎๅŠฉๆŠŠ[ๆ–‡ๆกฃ็ฟป่ฏ‘](contributing.md#translations){.internal-link target=_blank}ๆˆไฝ ็š„่ฏญ่จ€ใ€‚ + * ไฝ ไนŸๅฏไปฅๅฎก้˜…ไป–ไบบๅˆ›ๅปบ็š„็ฟป่ฏ‘ใ€‚ +* ๆ่ฎฎๆ–ฐๅขžๆ–‡ๆกฃ็ซ ่Š‚ใ€‚ +* ไฟฎๅค็Žฐๆœ‰ issue/bugใ€‚ + * ่ฎฐๅพ—ๆทปๅŠ ๆต‹่ฏ•ใ€‚ +* ๆทปๅŠ ๆ–ฐๅŠŸ่ƒฝใ€‚ + * ่ฎฐๅพ—ๆทปๅŠ ๆต‹่ฏ•ใ€‚ + * ๅฆ‚ๆžœ็›ธๅ…ณ๏ผŒ่ฎฐๅพ—่กฅๅ……ๆ–‡ๆกฃใ€‚ -ๅฆไธ€ๆ–น้ข๏ผŒ่Šๅคฉๅฎค้‡Œๆœ‰ๆˆๅƒไธŠไธ‡็š„็”จๆˆท๏ผŒๅœจ่ฟ™้‡Œ๏ผŒๆ‚จๆœ‰ๅพˆๅคงๅฏ่ƒฝ้‡ๅˆฐ่Šๅพ—ๆฅ็š„ไบบใ€‚๐Ÿ˜„ +## ๅธฎๅฟ™็ปดๆŠค FastAPI { #help-maintain-fastapi } -## ่ตžๅŠฉไฝœ่€… +ๅธฎๆˆ‘ไธ€่ตท็ปดๆŠค **FastAPI** ๅง๏ผ๐Ÿค“ + +ๆœ‰ๅพˆๅคšๅทฅไฝœ่ฆๅš๏ผŒๅ…ถไธญๅคง้ƒจๅˆ†ๅ…ถๅฎž**ไฝ **้ƒฝ่ƒฝๅšใ€‚ + +ไฝ ็Žฐๅœจๅฐฑ่ƒฝๅš็š„ไธป่ฆไบ‹ๆƒ…ๆœ‰๏ผš + +* [ๅœจ GitHub ไธŠๅธฎๅˆซไบบ่งฃ็ญ”้—ฎ้ข˜](#help-others-with-questions-in-github){.internal-link target=_blank}๏ผˆ่งไธŠ้ข็š„็ซ ่Š‚๏ผ‰ใ€‚ +* [ๅฎก้˜… Pull Request](#review-pull-requests){.internal-link target=_blank}๏ผˆ่งไธŠ้ข็š„็ซ ่Š‚๏ผ‰ใ€‚ + +่ฟ™ไธค้กนๅทฅไฝœๆ˜ฏ**ๆœ€่€—ๆ—ถ**็š„ใ€‚่ฟ™ไนŸๆ˜ฏ็ปดๆŠค FastAPI ็š„ไธป่ฆๅทฅไฝœใ€‚ + +ๅฆ‚ๆžœไฝ ่ƒฝๅœจ่ฟ™ๆ–น้ขๅธฎๆˆ‘๏ผŒ**ไฝ ๅฐฑๆ˜ฏๅœจๅธฎๆˆ‘็ปดๆŠค FastAPI**๏ผŒๅนถ็กฎไฟๅฎƒ**ๆ›ดๅฟซๆ›ดๅฅฝๅœฐๅ‰่ฟ›**ใ€‚๐Ÿš€ + +## ๅŠ ๅ…ฅ่Šๅคฉ { #join-the-chat } + +ๅŠ ๅ…ฅ ๐Ÿ‘ฅ Discord ่ŠๅคฉๆœๅŠกๅ™จ ๐Ÿ‘ฅ๏ผŒๅ’Œ FastAPI ็คพๅŒบ็š„ๅฐไผ™ไผดไปฌไธ€่ตทไบคๆตใ€‚ + +/// tip | ๆ็คบ + +ๅ…ณไบŽๆ้—ฎ๏ผŒ่ฏทๅœจ GitHub Discussions ไธญๅ‘ๅธƒ๏ผŒ่ฟ™ๆ ทๆ›ดๆœ‰ๆœบไผšๅพ—ๅˆฐ [FastAPI ไธ“ๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank} ็š„ๅธฎๅŠฉใ€‚ + +่Šๅคฉไป…็”จไบŽๅ…ถไป–ๆ—ฅๅธธไบคๆตใ€‚ + +/// -ๆ‚จ่ฟ˜ๅฏไปฅ้€š่ฟ‡ GitHub ่ตžๅŠฉๅ•†่ต„ๅŠฉๆœฌ้กน็›ฎ็š„ไฝœ่€…๏ผˆๅฐฑๆ˜ฏๆˆ‘๏ผ‰ใ€‚ +### ๅˆซๅœจ่Šๅคฉ้‡Œๆ้—ฎ { #dont-use-the-chat-for-questions } -็ป™ๆˆ‘ไนฐๆฏๅ’–ๅ•ก โ˜•๏ธ ไปฅ็คบๆ„Ÿ่ฐข ๐Ÿ˜„ +่ฏท่ฎฐไฝ๏ผŒ่Šๅคฉๆ›ดๅๅ‘โ€œ่‡ช็”ฑไบคๆตโ€๏ผŒๅพˆๅฎนๆ˜“ๆๅ‡บ่ฟ‡ไบŽ็ฌผ็ปŸใ€้šพไปฅๅ›ž็ญ”็š„้—ฎ้ข˜๏ผŒๅ› ๆญคไฝ ๅฏ่ƒฝๆ”ถไธๅˆฐ่งฃ็ญ”ใ€‚ -ๅฝ“็„ถๆ‚จไนŸๅฏไปฅๆˆไธบ FastAPI ็š„้‡‘็‰Œๆˆ–้“ถ็‰Œ่ตžๅŠฉๅ•†ใ€‚๐Ÿ…๐ŸŽ‰ +ๅœจ GitHub ไธญ๏ผŒๆจกๆฟไผšๅผ•ๅฏผไฝ ๅ†™ๅ‡บๆฐๅฝ“็š„้—ฎ้ข˜๏ผŒไปŽ่€Œๆ›ดๅฎนๆ˜“่Žทๅพ—ๅฅฝ็š„ๅ›ž็ญ”๏ผŒ็”š่‡ณๅœจๆ้—ฎไน‹ๅ‰ๅฐฑ่ƒฝ่‡ชๅทฑ่งฃๅ†ณใ€‚่€Œไธ”ๅœจ GitHub ้‡Œ๏ผŒๆˆ‘่ƒฝๅฐฝ้‡็กฎไฟๆœ€็ปˆๅ›žๅคๆฏไธช้—ฎ้ข˜๏ผŒๅณไฝฟ่ฟ™้œ€่ฆไธ€ไบ›ๆ—ถ้—ดใ€‚ๅฏน่Šๅคฉ็ณป็ปŸๆฅ่ฏด๏ผŒๆˆ‘ไธชไบบๅšไธๅˆฐ่ฟ™ไธ€็‚นใ€‚๐Ÿ˜… -## ่ตžๅŠฉ FastAPI ไฝฟ็”จ็š„ๅทฅๅ…ท +่Šๅคฉ็ณป็ปŸไธญ็š„ๅฏน่ฏไนŸไธๅƒ GitHub ้‚ฃๆ ทๅฎนๆ˜“ๆœ็ดข๏ผŒๅ› ๆญค้—ฎ็ญ”ๅฏ่ƒฝๅœจ่Šๅคฉไธญๆทนๆฒกใ€‚่€Œไธ”ๅชๆœ‰ๅœจ GitHub ไธญ็š„้—ฎ็ญ”ๆ‰ไผš่ฎกๅ…ฅๆˆไธบ [FastAPI ไธ“ๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank} ็š„่ดก็Œฎ๏ผŒๆ‰€ไปฅไฝ ๅœจ GitHub ไธŠๆ›ดๅฏ่ƒฝ่Žทๅพ—ๅ…ณๆณจใ€‚ -ๅฆ‚ๆ‚จๅœจๆœฌๆ–‡ๆกฃไธญๆ‰€่ง๏ผŒFastAPI ็ซ™ๅœจๅทจไบบ็š„่‚ฉ่†€ไธŠ๏ผŒๅฎƒไปฌๅˆ†ๅˆซๆ˜ฏ Starlette ๅ’Œ Pydanticใ€‚ +ๅฆไธ€ๆ–น้ข๏ผŒ่Šๅคฉ็ณป็ปŸ้‡Œๆœ‰ๆˆๅƒไธŠไธ‡็š„็”จๆˆท๏ผŒไฝ ๅ‡ ไนŽ้šๆ—ถ้ƒฝ่ƒฝๅœจ้‚ฃ้‡Œๆ‰พๅˆฐ่Šๅพ—ๆฅ็š„ไบบใ€‚๐Ÿ˜„ -ๆ‚จ่ฟ˜ๅฏไปฅ่ตžๅŠฉ๏ผš +## ่ตžๅŠฉไฝœ่€… { #sponsor-the-author } -* Samuel Colvin ๏ผˆPydantic๏ผ‰ -* Encode ๏ผˆStarlette, Uvicorn๏ผ‰ +ๅฆ‚ๆžœไฝ ็š„**ไบงๅ“/ๅ…ฌๅธ**ไพ่ต–ๆˆ–ไธŽ **FastAPI** ็›ธๅ…ณ๏ผŒๅนถไธ”ไฝ ๆƒณ่งฆ่พพๅฎƒ็š„็”จๆˆท๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ GitHub sponsors ่ตžๅŠฉไฝœ่€…๏ผˆๆˆ‘๏ผ‰ใ€‚ๆ นๆฎ่ตžๅŠฉๅฑ‚็บง๏ผŒไฝ ่ฟ˜ๅฏ่ƒฝ่Žทๅพ—ไธ€ไบ›้ขๅค–็ฆๅˆฉ๏ผŒๆฏ”ๅฆ‚ๅœจๆ–‡ๆกฃไธญๅฑ•็คบๅพฝ็ซ ใ€‚๐ŸŽ --- diff --git a/docs/zh/docs/history-design-future.md b/docs/zh/docs/history-design-future.md index 4db5c84724..00945eab59 100644 --- a/docs/zh/docs/history-design-future.md +++ b/docs/zh/docs/history-design-future.md @@ -1,12 +1,12 @@ -# ๅކๅฒใ€่ฎพ่ฎกใ€ๆœชๆฅ +# ๅކๅฒใ€่ฎพ่ฎกใ€ๆœชๆฅ { #history-design-and-future } ไธไน…ๅ‰๏ผŒๆ›พๆœ‰ย **FastAPI** ็”จๆˆท้—ฎ่ฟ‡๏ผš -> ่ฟ™ไธช้กน็›ฎๆœ‰ๆ€Žๆ ท็š„ๅކๅฒ๏ผŸๅฅฝๅƒๅฎƒๅช็”จไบ†ๅ‡ ๅ‘จๅฐฑไปŽ้ป˜้ป˜ๆ— ้—ปๅ˜ๅพ—ไผ—ๆ‰€ๅ‘จ็Ÿฅโ€ฆโ€ฆ +> ่ฟ™ไธช้กน็›ฎๆœ‰ๆ€Žๆ ท็š„ๅކๅฒ๏ผŸๅฅฝๅƒๅฎƒๅช็”จไบ†ๅ‡ ๅ‘จๅฐฑไปŽ้ป˜้ป˜ๆ— ้—ปๅ˜ๅพ—ไผ—ๆ‰€ๅ‘จ็Ÿฅ... ๅœจๆญค๏ผŒๆˆ‘ไปฌ็ฎ€ๅ•ๅ›ž้กพไธ€ไธ‹ **FastAPI** ็š„ๅކๅฒใ€‚ -## ๅค‡้€‰ๆ–นๆกˆ +## ๅค‡้€‰ๆ–นๆกˆ { #alternatives } ๆœ‰้‚ฃไนˆๅ‡ ๅนด๏ผŒๆˆ‘ๆ›พ้ข†ๅฏผๆ•ฐไธชๅผ€ๅ‘ๅ›ข้˜Ÿไธบ่ฏธๅคšๅคๆ‚้œ€ๆฑ‚ๅˆ›ๅปบๅ„็ง API๏ผŒ่ฟ™ไบ›้œ€ๆฑ‚ๅŒ…ๆ‹ฌๆœบๅ™จๅญฆไน ใ€ๅˆ†ๅธƒ็ณป็ปŸใ€ๅผ‚ๆญฅไปปๅŠกใ€NoSQL ๆ•ฐๆฎๅบ“็ญ‰้ข†ๅŸŸใ€‚ @@ -24,10 +24,9 @@ ๅœจ้‚ฃๅ‡ ๅนดไธญ๏ผŒๆˆ‘ไธ€็›ดๅ›ž้ฟๅˆ›ๅปบๆ–ฐ็š„ๆก†ๆžถใ€‚้ฆ–ๅ…ˆ๏ผŒๆˆ‘ๅฐ่ฏ•ไฝฟ็”จๅ„็งๆก†ๆžถใ€ๆ’ไปถใ€ๅทฅๅ…ท่งฃๅ†ณ **FastAPI** ็Žฐๅœจ็š„ๅŠŸ่ƒฝใ€‚ ไฝ†ๅˆฐไบ†ไธ€ๅฎš็จ‹ๅบฆไน‹ๅŽ๏ผŒๆˆ‘ๅˆซๆ— ้€‰ๆ‹ฉ๏ผŒๅช่ƒฝไปŽไน‹ๅ‰็š„ๅทฅๅ…ทไธญๆฑฒๅ–ๆœ€ไผ˜ๆ€่ทฏ๏ผŒๅนถไปฅๅฐฝ้‡ๅฅฝ็š„ๆ–นๅผๆŠŠ่ฟ™ไบ›ๆ€่ทฏๆ•ดๅˆๅœจไธ€่ตท๏ผŒไฝฟ็”จไน‹ๅ‰็”š่‡ณๆ˜ฏไธๆ”ฏๆŒ็š„่ฏญ่จ€็‰นๆ€ง๏ผˆPython 3.6+ ็š„็ฑปๅž‹ๆ็คบ๏ผ‰๏ผŒไปŽ่€Œๅˆ›ๅปบไธ€ไธช่ƒฝๆปก่ถณๆˆ‘ๆ‰€ๆœ‰้œ€ๆฑ‚็š„ๆก†ๆžถใ€‚ - -## ่ฐƒ็ ” +## ่ฐƒ็ ” { #investigation } ้€š่ฟ‡ไฝฟ็”จไน‹ๅ‰ๆ‰€ๆœ‰็š„ๅค‡้€‰ๆ–นๆกˆ๏ผŒๆˆ‘ๆœ‰ๆœบไผšไปŽๅฎƒไปฌไน‹ไธญๅญฆๅˆฐไบ†ๅพˆๅคšไธœ่ฅฟ๏ผŒ่Žทๅ–ไบ†ๅพˆๅคšๆƒณๆณ•๏ผŒๅนถไปฅๆˆ‘ๅ’Œๆˆ‘็š„ๅผ€ๅ‘ๅ›ข้˜Ÿ่ƒฝๆƒณๅˆฐ็š„ๆœ€ๅฅฝๆ–นๅผๆŠŠ่ฟ™ไบ›ๆ€่ทฏๆ•ดๅˆๆˆไธ€ไฝ“ใ€‚ @@ -37,7 +36,7 @@ ๅ› ๆญค๏ผŒ็”š่‡ณๅœจๅผ€ๅ‘ **FastAPI** ๅ‰๏ผŒๆˆ‘ๅฐฑ่Šฑไบ†ๅ‡ ไธชๆœˆ็š„ๆ—ถ้—ด็ ”็ฉถ OpenAPIใ€JSON Schemaใ€OAuth2 ็ญ‰่ง„่Œƒใ€‚ๆทฑๅ…ฅ็†่งฃๅฎƒไปฌไน‹้—ด็š„ๅ…ณ็ณปใ€้‡ๅ ๅŠๅŒบๅˆซไน‹ๅค„ใ€‚ -## ่ฎพ่ฎก +## ่ฎพ่ฎก { #design } ็„ถๅŽ๏ผŒๆˆ‘ๅˆ่Šฑไบ†ไธ€ไบ›ๆ—ถ้—ดไปŽ็”จๆˆท่ง’ๅบฆ๏ผˆไฝฟ็”จ FastAPI ็š„ๅผ€ๅ‘่€…๏ผ‰่ฎพ่ฎกไบ†ๅผ€ๅ‘่€… **API**ใ€‚ @@ -51,7 +50,7 @@ ๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝๆ˜ฏไธบไบ†็ป™ๅผ€ๅ‘่€…ๆไพ›ๆœ€ไฝณ็š„ๅผ€ๅ‘ไฝ“้ชŒใ€‚ -## ้œ€ๆฑ‚้กน +## ้œ€ๆฑ‚้กน { #requirements } ็ป่ฟ‡ๆต‹่ฏ•ๅคš็งๅค‡้€‰ๆ–นๆกˆ๏ผŒๆˆ‘ๆœ€็ปˆๅ†ณๅฎšไฝฟ็”จ **Pydantic**๏ผŒๅนถๅ……ๅˆ†ๅˆฉ็”จๅฎƒ็š„ไผ˜ๅŠฟใ€‚ @@ -59,11 +58,11 @@ ๅœจๅผ€ๅ‘ๆœŸ้—ด๏ผŒๆˆ‘่ฟ˜ไธบ **Starlette** ๅšไบ†ไธๅฐ‘่ดก็Œฎ๏ผŒ่ฟ™ๆ˜ฏๅฆไธ€ไธชๅ…ณ้”ฎ้œ€ๆฑ‚้กนใ€‚ -## ๅผ€ๅ‘ +## ๅผ€ๅ‘ { #development } ๅฝ“ๆˆ‘ๅฏๅŠจ **FastAPI** ๅผ€ๅ‘็š„ๆ—ถๅ€™๏ผŒ็ปๅคงๅคšๆ•ฐ้ƒจไปถ้ƒฝๅทฒ็ปๅฐฑไฝ๏ผŒ่ฎพ่ฎกๅทฒ็ปๅฎšไน‰๏ผŒ้œ€ๆฑ‚้กนๅ’Œๅทฅๅ…ทไนŸๅทฒ็ปๅ‡†ๅค‡ๅฐฑ็ปช๏ผŒ็›ธๅ…ณๆ ‡ๅ‡†ไธŽ่ง„่Œƒ็š„็Ÿฅ่ฏ†ๅ‚จๅค‡ไนŸ้žๅธธๆธ…ๆ™ฐ่€Œๆ–ฐ้ฒœใ€‚ -## ๆœชๆฅ +## ๆœชๆฅ { #future } ่‡ณๆญค๏ผŒ**FastAPI** ๅŠๅ…ถ็†ๅฟตๅทฒ็ปไธบๅพˆๅคšไบบๆ‰€็”จใ€‚ @@ -73,6 +72,6 @@ ไฝ†๏ผŒ**FastAPI** ไปๆœ‰ๅพˆๅคšๆ”น่ฟ›็š„ไฝ™ๅœฐ๏ผŒไนŸ่ฟ˜้œ€่ฆๆทปๅŠ ๆ›ดๅคš็š„ๅŠŸ่ƒฝใ€‚ -ๆ€ปไน‹๏ผŒ**FastAPI** ๅ‰ๆ™ฏๅ…‰ๆ˜Žใ€‚ +**FastAPI** ๅ‰ๆ™ฏๅ…‰ๆ˜Žใ€‚ ๅœจๆญค๏ผŒๆˆ‘ไปฌ่กทๅฟƒๆ„Ÿ่ฐข[ๆ‚จ็š„ๅธฎๅŠฉ](help-fastapi.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md index 108e0cb95a..104baff4bd 100644 --- a/docs/zh/docs/how-to/configure-swagger-ui.md +++ b/docs/zh/docs/how-to/configure-swagger-ui.md @@ -1,4 +1,4 @@ -# ้…็ฝฎ Swagger UI +# ้…็ฝฎ Swagger UI { #configure-swagger-ui } ไฝ ๅฏไปฅ้…็ฝฎไธ€ไบ›้ขๅค–็š„ Swagger UI ๅ‚ๆ•ฐ. @@ -8,7 +8,7 @@ FastAPIไผšๅฐ†่ฟ™ไบ›้…็ฝฎ่ฝฌๆขไธบ **JSON**๏ผŒไฝฟๅ…ถไธŽ JavaScript ๅ…ผๅฎน๏ผŒๅ› ไธบ่ฟ™ๆ˜ฏ Swagger UI ้œ€่ฆ็š„ใ€‚ -## ไธไฝฟ็”จ่ฏญๆณ•้ซ˜ไบฎ +## ็ฆ็”จ่ฏญๆณ•้ซ˜ไบฎ { #disable-syntax-highlighting } ๆฏ”ๅฆ‚๏ผŒไฝ ๅฏไปฅ็ฆ็”จ Swagger UI ไธญ็š„่ฏญๆณ•้ซ˜ไบฎใ€‚ @@ -18,41 +18,41 @@ FastAPIไผšๅฐ†่ฟ™ไบ›้…็ฝฎ่ฝฌๆขไธบ **JSON**๏ผŒไฝฟๅ…ถไธŽ JavaScript ๅ…ผๅฎน๏ผŒๅ›  ไฝ†ๆ˜ฏไฝ ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `syntaxHighlight` ไธบ `False` ๆฅ็ฆ็”จ Swagger UI ไธญ็š„่ฏญๆณ•้ซ˜ไบฎ๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} ...ๅœจๆญคไน‹ๅŽ๏ผŒSwagger UI ๅฐ†ไธไผš้ซ˜ไบฎไปฃ็ : -## ๆ”นๅ˜ไธป้ข˜ +## ๆ”นๅ˜ไธป้ข˜ { #change-the-theme } ๅŒๆ ทๅœฐ๏ผŒไฝ ไนŸๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ้”ฎ `"syntaxHighlight.theme"` ๆฅ่ฎพ็ฝฎ่ฏญๆณ•้ซ˜ไบฎไธป้ข˜๏ผˆๆณจๆ„ไธญ้—ดๆœ‰ไธ€ไธช็‚น๏ผ‰๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} ่ฟ™ไธช้…็ฝฎไผšๆ”นๅ˜่ฏญๆณ•้ซ˜ไบฎไธป้ข˜๏ผš -## ๆ”นๅ˜้ป˜่ฎค Swagger UI ๅ‚ๆ•ฐ +## ๆ”นๅ˜้ป˜่ฎค Swagger UI ๅ‚ๆ•ฐ { #change-default-swagger-ui-parameters } FastAPI ๅŒ…ๅซไบ†ไธ€ไบ›้ป˜่ฎค้…็ฝฎๅ‚ๆ•ฐ๏ผŒ้€‚็”จไบŽๅคงๅคšๆ•ฐ็”จไพ‹ใ€‚ ๅ…ถๅŒ…ๆ‹ฌ่ฟ™ไบ›้ป˜่ฎค้…็ฝฎๅ‚ๆ•ฐ๏ผš -{* ../../fastapi/openapi/docs.py ln[7:23] *} +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} ไฝ ๅฏไปฅ้€š่ฟ‡ๅœจ `swagger_ui_parameters` ไธญ่ฎพ็ฝฎไธๅŒ็š„ๅ€ผๆฅ่ฆ†็›–ๅฎƒไปฌใ€‚ ๆฏ”ๅฆ‚๏ผŒๅฆ‚ๆžœ่ฆ็ฆ็”จ `deepLinking`๏ผŒไฝ ๅฏไปฅๅƒ่ฟ™ๆ ทไผ ้€’่ฎพ็ฝฎๅˆฐ `swagger_ui_parameters` ไธญ๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} -## ๅ…ถไป– Swagger UI ๅ‚ๆ•ฐ +## ๅ…ถไป– Swagger UI ๅ‚ๆ•ฐ { #other-swagger-ui-parameters } -ๆŸฅ็œ‹ๅ…ถไป– Swagger UI ๅ‚ๆ•ฐ๏ผŒ่ฏท้˜…่ฏป docs for Swagger UI parametersใ€‚ +ๆŸฅ็œ‹ๆ‰€ๆœ‰ๅ…ถไป–ๅฏ็”จ็š„้…็ฝฎ๏ผŒ่ฏท้˜…่ฏป Swagger UI ๅ‚ๆ•ฐๆ–‡ๆกฃใ€‚ -## JavaScript-only ้…็ฝฎ +## JavaScript-only ้…็ฝฎ { #javascript-only-settings } Swagger UI ๅŒๆ ทๅ…่ฎธไฝฟ็”จ **JavaScript-only** ้…็ฝฎๅฏน่ฑก๏ผˆไพ‹ๅฆ‚๏ผŒJavaScript ๅ‡ฝๆ•ฐ๏ผ‰ใ€‚ @@ -67,4 +67,4 @@ presets: [ ่ฟ™ไบ›ๆ˜ฏ **JavaScript** ๅฏน่ฑก๏ผŒ่€Œไธๆ˜ฏๅญ—็ฌฆไธฒ๏ผŒๆ‰€ไปฅไฝ ไธ่ƒฝ็›ดๆŽฅไปŽ Python ไปฃ็ ไธญไผ ้€’ๅฎƒไปฌใ€‚ -ๅฆ‚ๆžœไฝ ้œ€่ฆๅƒ่ฟ™ๆ ทไฝฟ็”จ JavaScript-only ้…็ฝฎ๏ผŒไฝ ๅฏไปฅไฝฟ็”จไธŠ่ฟฐๆ–นๆณ•ไน‹ไธ€ใ€‚่ฆ†็›–ๆ‰€ๆœ‰ Swagger UI *path operation* ๅนถๆ‰‹ๅŠจ็ผ–ๅ†™ไปปไฝ•ไฝ ้œ€่ฆ็š„ JavaScriptใ€‚ +ๅฆ‚ๆžœไฝ ้œ€่ฆๅƒ่ฟ™ๆ ทไฝฟ็”จ JavaScript-only ้…็ฝฎ๏ผŒไฝ ๅฏไปฅไฝฟ็”จไธŠ่ฟฐๆ–นๆณ•ไน‹ไธ€ใ€‚่ฆ†็›–ๆ‰€ๆœ‰ Swagger UI *่ทฏๅพ„ๆ“ไฝœ* ๅนถๆ‰‹ๅŠจ็ผ–ๅ†™ไปปไฝ•ไฝ ้œ€่ฆ็š„ JavaScriptใ€‚ diff --git a/docs/zh/docs/how-to/general.md b/docs/zh/docs/how-to/general.md index e8b6dd3b23..e75ad6c79d 100644 --- a/docs/zh/docs/how-to/general.md +++ b/docs/zh/docs/how-to/general.md @@ -1,39 +1,39 @@ -# ้€š็”จ - ๅฆ‚ไฝ•ๆ“ไฝœ - ่ฏ€็ช +# ้€š็”จ - ๅฆ‚ไฝ•ๆ“ไฝœ - ่ฏ€็ช { #general-how-to-recipes } ่ฟ™้‡Œๆ˜ฏไธ€ไบ›ๆŒ‡ๅ‘ๆ–‡ๆกฃไธญๅ…ถไป–้ƒจๅˆ†็š„้“พๆŽฅ๏ผŒ็”จไบŽ่งฃ็ญ”ไธ€่ˆฌๆ€งๆˆ–ๅธธ่ง้—ฎ้ข˜ใ€‚ -## ๆ•ฐๆฎ่ฟ‡ๆปค - ๅฎ‰ๅ…จๆ€ง +## ๆ•ฐๆฎ่ฟ‡ๆปค - ๅฎ‰ๅ…จๆ€ง { #filter-data-security } ไธบ็กฎไฟไธ่ฟ”ๅ›ž่ถ…่ฟ‡้œ€่ฆ็š„ๆ•ฐๆฎ๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ“ๅบ”ๆจกๅž‹ - ่ฟ”ๅ›ž็ฑปๅž‹](../tutorial/response-model.md){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## ๆ–‡ๆกฃ็š„ๆ ‡็ญพ - OpenAPI +## ๆ–‡ๆกฃ็š„ๆ ‡็ญพ - OpenAPI { #documentation-tags-openapi } ๅœจๆ–‡ๆกฃ็•Œ้ขไธญๆทปๅŠ **่ทฏๅพ„ๆ“ไฝœ**็š„ๆ ‡็ญพๅ’Œ่ฟ›่กŒๅˆ†็ป„๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ - Tags ๅ‚ๆ•ฐ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## ๆ–‡ๆกฃ็š„ๆฆ‚่ฆๅ’Œๆ่ฟฐ - OpenAPI +## ๆ–‡ๆกฃ็š„ๆฆ‚่ฆๅ’Œๆ่ฟฐ - OpenAPI { #documentation-summary-and-description-openapi } -ๅœจๆ–‡ๆกฃ็•Œ้ขไธญๆทปๅŠ **่ทฏๅพ„ๆ“ไฝœ**็š„ๆฆ‚่ฆๅ’Œๆ่ฟฐ๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ - Summary ๅ’Œ Description ๅ‚ๆ•ฐ](../tutorial/path-operation-configuration.md#summary-description){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ +ๅœจๆ–‡ๆกฃ็•Œ้ขไธญๆทปๅŠ **่ทฏๅพ„ๆ“ไฝœ**็š„ๆฆ‚่ฆๅ’Œๆ่ฟฐ๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ - Summary ๅ’Œ Description ๅ‚ๆ•ฐ](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## ๆ–‡ๆกฃ็š„ๅ“ๅบ”ๆ่ฟฐ - OpenAPI +## ๆ–‡ๆกฃ็š„ๅ“ๅบ”ๆ่ฟฐ - OpenAPI { #documentation-response-description-openapi } ๅœจๆ–‡ๆกฃ็•Œ้ขไธญๅฎšไน‰ๅนถๆ˜พ็คบๅ“ๅบ”ๆ่ฟฐ๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ - ๅ“ๅบ”ๆ่ฟฐ](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## ๆ–‡ๆกฃๅผƒ็”จ**่ทฏๅพ„ๆ“ไฝœ** - OpenAPI +## ๆ–‡ๆกฃๅผƒ็”จ**่ทฏๅพ„ๆ“ไฝœ** - OpenAPI { #documentation-deprecate-a-path-operation-openapi } ๅœจๆ–‡ๆกฃ็•Œ้ขไธญๆ˜พ็คบๅผƒ็”จ็š„**่ทฏๅพ„ๆ“ไฝœ**๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ - ๅผƒ็”จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## ๅฐ†ไปปไฝ•ๆ•ฐๆฎ่ฝฌๆขไธบ JSON ๅ…ผๅฎนๆ ผๅผ +## ๅฐ†ไปปไฝ•ๆ•ฐๆฎ่ฝฌๆขไธบ JSON ๅ…ผๅฎนๆ ผๅผ { #convert-any-data-to-json-compatible } ่ฆๅฐ†ไปปไฝ•ๆ•ฐๆฎ่ฝฌๆขไธบ JSON ๅ…ผๅฎนๆ ผๅผ๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - JSON ๅ…ผๅฎน็ผ–็ ๅ™จ](../tutorial/encoder.md){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## OpenAPI ๅ…ƒๆ•ฐๆฎ - ๆ–‡ๆกฃ +## OpenAPI ๅ…ƒๆ•ฐๆฎ - ๆ–‡ๆกฃ { #openapi-metadata-docs } ่ฆๆทปๅŠ  OpenAPI ็š„ๅ…ƒๆ•ฐๆฎ๏ผŒๅŒ…ๆ‹ฌ่ฎธๅฏ่ฏใ€็‰ˆๆœฌใ€่”็ณปๆ–นๅผ็ญ‰๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## OpenAPI ่‡ชๅฎšไน‰ URL +## OpenAPI ่‡ชๅฎšไน‰ URL { #openapi-custom-url } ่ฆ่‡ชๅฎšไน‰ OpenAPI ็š„ URL๏ผˆๆˆ–ๅˆ ้™คๅฎƒ๏ผ‰๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} ๆ–‡ๆกฃใ€‚ -## OpenAPI ๆ–‡ๆกฃ URL +## OpenAPI ๆ–‡ๆกฃ URL { #openapi-docs-urls } -่ฆๆ›ดๆ”น็”จไบŽ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ็š„ URL๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. +่ฆๆ›ดๆ”น็”จไบŽ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ็š„ URL๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh/docs/how-to/index.md b/docs/zh/docs/how-to/index.md index ac097618be..980dcd1a65 100644 --- a/docs/zh/docs/how-to/index.md +++ b/docs/zh/docs/how-to/index.md @@ -1,4 +1,4 @@ -# ๅฆ‚ไฝ•ๆ“ไฝœ - ่ฏ€็ช +# ๅฆ‚ไฝ•ๆ“ไฝœ - ่ฏ€็ช { #how-to-recipes } ๅœจ่ฟ™้‡Œ๏ผŒไฝ ๅฐ†็œ‹ๅˆฐๅ…ณไบŽ**ๅคšไธชไธป้ข˜**็š„ไธๅŒ่ฏ€็ชๆˆ–โ€œๅฆ‚ไฝ•ๆ“ไฝœโ€ๆŒ‡ๅ—ใ€‚ @@ -6,7 +6,7 @@ ๅฆ‚ๆžœๆŸไบ›ๅ†…ๅฎน็œ‹่ตทๆฅๅฏนไฝ ็š„้กน็›ฎๆœ‰็”จ๏ผŒ่ฏท็ปง็ปญๆŸฅ้˜…๏ผŒๅฆๅˆ™่ฏท็›ดๆŽฅ่ทณ่ฟ‡ๅฎƒไปฌใ€‚ -/// tip | ๅฐๆŠ€ๅทง +/// tip | ๆ็คบ ๅฆ‚ๆžœไฝ ๆƒณไปฅ็ณป็ปŸ็š„ๆ–นๅผ**ๅญฆไน  FastAPI**๏ผˆๆŽจ่๏ผ‰๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank} ็š„ๆฏไธ€็ซ ่Š‚ใ€‚ diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 9f4b6d3d56..1c2aea3285 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -1,11 +1,11 @@ -# FastAPI +# FastAPI { #fastapi }

- FastAPI + FastAPI

FastAPI ๆก†ๆžถ๏ผŒ้ซ˜ๆ€ง่ƒฝ๏ผŒๆ˜“ไบŽๅญฆไน ๏ผŒ้ซ˜ๆ•ˆ็ผ–็ ๏ผŒ็”Ÿไบงๅฏ็”จ @@ -27,135 +27,140 @@ --- -**ๆ–‡ๆกฃ**๏ผš https://fastapi.tiangolo.com +**ๆ–‡ๆกฃ**๏ผš https://fastapi.tiangolo.com **ๆบ็ **๏ผš https://github.com/fastapi/fastapi --- -FastAPI ๆ˜ฏไธ€ไธช็”จไบŽๆž„ๅปบ API ็š„็Žฐไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ€ง่ƒฝ๏ผ‰็š„ web ๆก†ๆžถ๏ผŒไฝฟ็”จ Python ๅนถๅŸบไบŽๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ๆ็คบใ€‚ +FastAPI ๆ˜ฏไธ€ไธช็”จไบŽๆž„ๅปบ API ็š„็Žฐไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ€ง่ƒฝ๏ผ‰็š„ Web ๆก†ๆžถ๏ผŒไฝฟ็”จ Python ๅนถๅŸบไบŽๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ๆ็คบใ€‚ -ๅ…ณ้”ฎ็‰นๆ€ง: +ๅ…ณ้”ฎ็‰นๆ€ง๏ผš -* **ๅฟซ้€Ÿ**๏ผšๅฏไธŽ **NodeJS** ๅ’Œ **Go** ๅนถ่‚ฉ็š„ๆž้ซ˜ๆ€ง่ƒฝ๏ผˆๅฝ’ๅŠŸไบŽ Starlette ๅ’Œ Pydantic๏ผ‰ใ€‚[ๆœ€ๅฟซ็š„ Python web ๆก†ๆžถไน‹ไธ€](#_11)ใ€‚ +* **ๅฟซ้€Ÿ**๏ผšๆž้ซ˜ๆ€ง่ƒฝ๏ผŒๅฏไธŽ **NodeJS** ๅ’Œ **Go** ๅนถ่‚ฉ๏ผˆๅฝ’ๅŠŸไบŽ Starlette ๅ’Œ Pydantic๏ผ‰ใ€‚[ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€](#performance)ใ€‚ +* **้ซ˜ๆ•ˆ็ผ–็ **๏ผšๅŠŸ่ƒฝๅผ€ๅ‘้€Ÿๅบฆๆๅ‡็บฆ 200% ๏ฝž 300%ใ€‚* +* **ๆ›ดๅฐ‘ bug**๏ผšไบบไธบ๏ผˆๅผ€ๅ‘่€…๏ผ‰้”™่ฏฏๅ‡ๅฐ‘็บฆ 40%ใ€‚* +* **็›ด่ง‚**๏ผšๆžไฝณ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ๅค„ๅค„็š†ๅฏ่‡ชๅŠจ่กฅๅ…จใ€‚ๆ›ดๅฐ‘็š„่ฐƒ่ฏ•ๆ—ถ้—ดใ€‚ +* **ๆ˜“็”จ**๏ผšไธบๆ˜“็”จๅ’Œๆ˜“ๅญฆ่€Œ่ฎพ่ฎกใ€‚ๆ›ดๅฐ‘็š„ๆ–‡ๆกฃ้˜…่ฏปๆ—ถ้—ดใ€‚ +* **็ฎ€็Ÿญ**๏ผšๆœ€ๅฐๅŒ–ไปฃ็ ้‡ๅคใ€‚ไธ€ๆฌกๅ‚ๆ•ฐๅฃฐๆ˜Žๅณๅฏ่Žทๅพ—ๅคš็งๅŠŸ่ƒฝใ€‚ๆ›ดๅฐ‘็š„ bugใ€‚ +* **ๅฅๅฃฎ**๏ผš็”Ÿไบงๅฏ็”จ็บงไปฃ็ ใ€‚ๅนถๅธฆๆœ‰่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผๆ–‡ๆกฃใ€‚ +* **ๆ ‡ๅ‡†ๅŒ–**๏ผšๅŸบไบŽ๏ผˆๅนถๅฎŒๅ…จๅ…ผๅฎน๏ผ‰API ็š„ๅผ€ๆ”พๆ ‡ๅ‡†๏ผšOpenAPI๏ผˆไปฅๅ‰็งฐไธบ Swagger๏ผ‰ๅ’Œ JSON Schemaใ€‚ -* **้ซ˜ๆ•ˆ็ผ–็ **๏ผšๆ้ซ˜ๅŠŸ่ƒฝๅผ€ๅ‘้€Ÿๅบฆ็บฆ 200๏ผ… ่‡ณ 300๏ผ…ใ€‚* -* **ๆ›ดๅฐ‘ bug**๏ผšๅ‡ๅฐ‘็บฆ 40๏ผ… ็š„ไบบไธบ๏ผˆๅผ€ๅ‘่€…๏ผ‰ๅฏผ่‡ด้”™่ฏฏใ€‚* -* **ๆ™บ่ƒฝ**๏ผšๆžไฝณ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ๅค„ๅค„็š†ๅฏ่‡ชๅŠจ่กฅๅ…จ๏ผŒๅ‡ๅฐ‘่ฐƒ่ฏ•ๆ—ถ้—ดใ€‚ -* **็ฎ€ๅ•**๏ผš่ฎพ่ฎก็š„ๆ˜“ไบŽไฝฟ็”จๅ’Œๅญฆไน ๏ผŒ้˜…่ฏปๆ–‡ๆกฃ็š„ๆ—ถ้—ดๆ›ด็Ÿญใ€‚ -* **็ฎ€็Ÿญ**๏ผšไฝฟไปฃ็ ้‡ๅคๆœ€ๅฐๅŒ–ใ€‚้€š่ฟ‡ไธๅŒ็š„ๅ‚ๆ•ฐๅฃฐๆ˜Žๅฎž็ŽฐไธฐๅฏŒๅŠŸ่ƒฝใ€‚bug ๆ›ดๅฐ‘ใ€‚ -* **ๅฅๅฃฎ**๏ผš็”Ÿไบงๅฏ็”จ็บงๅˆซ็š„ไปฃ็ ใ€‚่ฟ˜ๆœ‰่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผๆ–‡ๆกฃใ€‚ -* **ๆ ‡ๅ‡†ๅŒ–**๏ผšๅŸบไบŽ๏ผˆๅนถๅฎŒๅ…จๅ…ผๅฎน๏ผ‰API ็š„็›ธๅ…ณๅผ€ๆ”พๆ ‡ๅ‡†๏ผšOpenAPI (ไปฅๅ‰่ขซ็งฐไธบ Swagger) ๅ’Œ JSON Schemaใ€‚ +* ๅŸบไบŽๆŸๅ†…้ƒจๅผ€ๅ‘ๅ›ข้˜Ÿๅœจๆž„ๅปบ็”Ÿไบงๅบ”็”จๆ—ถ็š„ๆต‹่ฏ•ไผฐ็ฎ—ใ€‚ -* ๆ นๆฎๅฏนๆŸไธชๆž„ๅปบ็บฟไธŠๅบ”็”จ็š„ๅ†…้ƒจๅผ€ๅ‘ๅ›ข้˜Ÿๆ‰€่ฟ›่กŒ็š„ๆต‹่ฏ•ไผฐ็ฎ—ๅพ—ๅ‡บใ€‚ - -## Sponsors +## ่ตžๅŠฉๅ•† { #sponsors } -{% if sponsors %} +### Keystone ่ตžๅŠฉๅ•† { #keystone-sponsor } + +{% for sponsor in sponsors.keystone -%} + +{% endfor -%} + +### ้‡‘็‰Œๅ’Œ้“ถ็‰Œ่ตžๅŠฉๅ•† { #gold-and-silver-sponsors } + {% for sponsor in sponsors.gold -%} {% endfor -%} {%- for sponsor in sponsors.silver -%} {% endfor %} -{% endif %} -Other sponsors +ๅ…ถไป–่ตžๅŠฉๅ•† -## ่ฏ„ไปท +## ่ฏ„ไปท { #opinions } -ใ€Œ_[...] ๆœ€่ฟ‘ๆˆ‘ไธ€็›ดๅœจไฝฟ็”จ **FastAPI**ใ€‚[...] ๅฎž้™…ไธŠๆˆ‘ๆญฃๅœจ่ฎกๅˆ’ๅฐ†ๅ…ถ็”จไบŽๆˆ‘ๆ‰€ๅœจ็š„**ๅพฎ่ฝฏ**ๅ›ข้˜Ÿ็š„ๆ‰€ๆœ‰**ๆœบๅ™จๅญฆไน ๆœๅŠก**ใ€‚ๅ…ถไธญไธ€ไบ›ๆœๅŠกๆญฃ่ขซ้›†ๆˆ่ฟ›ๆ ธๅฟƒ **Windows** ไบงๅ“ๅ’Œไธ€ไบ› **Office** ไบงๅ“ใ€‚_ใ€ +ใ€Œ_[...] ๆœ€่ฟ‘ๆˆ‘ๅคง้‡ไฝฟ็”จ **FastAPI**ใ€‚[...] ๆˆ‘ๅฎž้™…ไธŠ่ฎกๅˆ’ๆŠŠๅฎƒ็”จไบŽๆˆ‘ๅ›ข้˜Ÿๅœจ **ๅพฎ่ฝฏ** ็š„ๆ‰€ๆœ‰ **ๆœบๅ™จๅญฆไน ๆœๅŠก**ใ€‚ๅ…ถไธญไธ€ไบ›ๆญฃๅœจ้›†ๆˆ่ฟ›ๆ ธๅฟƒ **Windows** ไบงๅ“ไปฅๅŠไธ€ไบ› **Office** ไบงๅ“ใ€‚_ใ€ -

Kabir Khan - ๅพฎ่ฝฏ (ref)
+
Kabir Khan - Microsoft (ref)
--- -ใ€Œ_ๆˆ‘ไปฌ้€‰ๆ‹ฉไบ† **FastAPI** ๆฅๅˆ›ๅปบ็”จไบŽ่Žทๅ–**้ข„ๆต‹็ป“ๆžœ**็š„ **REST** ๆœๅŠกใ€‚[็”จไบŽ Ludwig]_ใ€ +ใ€Œ_ๆˆ‘ไปฌ้‡‡็”จ **FastAPI** ๆฅๆž„ๅปบๅฏๆŸฅ่ฏขไปฅ่Žทๅ–**้ข„ๆต‹็ป“ๆžœ**็š„ **REST** ๆœๅŠกๅ™จใ€‚[็”จไบŽ Ludwig]_ใ€ -
Piero Molino๏ผŒYaroslav Dudin ๅ’Œ Sai Sumanth Miryala - Uber (ref)
+
Piero Molino๏ผŒYaroslav Dudin๏ผŒSai Sumanth Miryala - Uber (ref)
--- -ใ€Œ_**Netflix** ้žๅธธ้ซ˜ๅ…ดๅœฐๅฎฃๅธƒ๏ผŒๆญฃๅผๅผ€ๆบๆˆ‘ไปฌ็š„**ๅฑๆœบ็ฎก็†**็ผ–ๆŽ’ๆก†ๆžถ๏ผš**Dispatch**๏ผ[ไฝฟ็”จ **FastAPI** ๆž„ๅปบ]_ใ€ +ใ€Œ_**Netflix** ๅพˆ้ซ˜ๅ…ดๅฎฃๅธƒๅผ€ๆบๆˆ‘ไปฌ็š„**ๅฑๆœบ็ฎก็†**็ผ–ๆŽ’ๆก†ๆžถ๏ผš**Dispatch**๏ผ[ไฝฟ็”จ **FastAPI** ๆž„ๅปบ]_ใ€
Kevin Glisson๏ผŒMarc Vilanova๏ผŒForest Monsen - Netflix (ref)
--- -ใ€Œ_**FastAPI** ่ฎฉๆˆ‘ๅ…ดๅฅ‹็š„ๆฌฃๅ–œ่‹ฅ็‹‚ใ€‚ๅฎƒๅคชๆฃ’ไบ†๏ผ_ใ€ +ใ€Œ_ๆˆ‘ๅฏน **FastAPI** ๅ…ดๅฅ‹ๅˆฐ้ฃž่ตทใ€‚ๅฎƒๅคชๆœ‰่ถฃไบ†๏ผ_ใ€
Brian Okken - Python Bytes ๆ’ญๅฎขไธปๆŒไบบ (ref)
--- -ใ€Œ_่€ๅฎž่ฏด๏ผŒไฝ ็š„ไฝœๅ“็œ‹่ตทๆฅ้žๅธธๅฏ้ ๅ’Œไผ˜็พŽใ€‚ๅœจๅพˆๅคšๆ–น้ข๏ผŒ่ฟ™ๅฐฑๆ˜ฏๆˆ‘ๆƒณ่ฎฉ **Hug** ๆˆไธบ็š„ๆ ทๅญ - ็œ‹ๅˆฐๆœ‰ไบบๅฎž็Žฐไบ†ๅฎƒ็œŸ็š„ๅพˆ้ผ“่ˆžไบบๅฟƒใ€‚_ใ€ +ใ€Œ_่€ๅฎž่ฏด๏ผŒไฝ ๆž„ๅปบ็š„ไธœ่ฅฟ้žๅธธ็จณๅฅ่€Œไธ”ๆ‰“็ฃจๅพ—ๅพˆๅฅฝใ€‚ไปŽๅพˆๅคšๆ–น้ข็œ‹๏ผŒ่ฟ™ๅฐฑๆ˜ฏๆˆ‘ๆƒณ่ฎฉ **Hug** ๆˆไธบ็š„ๆ ทๅญ โ€”โ€” ็œ‹ๅˆฐๆœ‰ไบบๆŠŠๅฎƒๅšๅ‡บๆฅ็œŸ็š„ๅพˆ้ผ“่ˆžไบบๅฟƒใ€‚_ใ€
Timothy Crosley - Hug ไฝœ่€… (ref)
--- -ใ€Œ_ๅฆ‚ๆžœไฝ ๆญฃๆ‰“็ฎ—ๅญฆไน ไธ€ไธช**็Žฐไปฃๆก†ๆžถ**็”จๆฅๆž„ๅปบ REST API๏ผŒๆฅ็œ‹ไธ‹ **FastAPI** [...] ๅฎƒๅฟซ้€Ÿใ€ๆ˜“็”จไธ”ๆ˜“ไบŽๅญฆไน  [...]_ใ€ +ใ€Œ_ๅฆ‚ๆžœไฝ ๆƒณๅญฆไธ€ไธช็”จไบŽๆž„ๅปบ REST API ็š„**็Žฐไปฃๆก†ๆžถ**๏ผŒ็œ‹็œ‹ **FastAPI** [...] ๅฎƒๅฟซ้€Ÿใ€ๆ˜“็”จไธ”ๆ˜“ๅญฆ [...]_ใ€ -ใ€Œ_ๆˆ‘ไปฌๅทฒ็ปๅฐ† **API** ๆœๅŠกๅˆ‡ๆขๅˆฐไบ† **FastAPI** [...] ๆˆ‘่ฎคไธบไฝ ไผšๅ–œๆฌขๅฎƒ็š„ [...]_ใ€ +ใ€Œ_ๆˆ‘ไปฌๅทฒ็ปๆŠŠๆˆ‘ไปฌ็š„ **API** ๅˆ‡ๆขๅˆฐ **FastAPI** [...] ๆˆ‘ๆƒณไฝ ไผšๅ–œๆฌขๅฎƒ [...]_ใ€
Ines Montani - Matthew Honnibal - Explosion AI ๅˆ›ๅง‹ไบบ - spaCy ไฝœ่€… (ref) - (ref)
--- -## **Typer**๏ผŒๅ‘ฝไปค่กŒไธญ็š„ FastAPI +ใ€Œ_ๅฆ‚ๆžœๆœ‰ไบบๆญฃๅœจๆž„ๅปบ็”Ÿไบง็บง็š„ Python API๏ผŒๆˆ‘ๅผบ็ƒˆๆŽจ่ **FastAPI**ใ€‚ๅฎƒ**่ฎพ่ฎกไผ˜้›…**ใ€**ไฝฟ็”จ็ฎ€ๅ•**ไธ”**้ซ˜ๅบฆๅฏๆ‰ฉๅฑ•**๏ผŒๅทฒ็ปๆˆไธบๆˆ‘ไปฌ API ไผ˜ๅ…ˆๅผ€ๅ‘ๆˆ˜็•ฅไธญ็š„**ๅ…ณ้”ฎ็ป„ไปถ**๏ผŒๅนถ้ฉฑๅŠจไบ†่ฎธๅคš่‡ชๅŠจๅŒ–ๅ’ŒๆœๅŠก๏ผŒๆฏ”ๅฆ‚ๆˆ‘ไปฌ็š„ Virtual TAC Engineerใ€‚_ใ€ - +
Deon Pillsbury - Cisco (ref)
-ๅฆ‚ๆžœไฝ ๆญฃๅœจๅผ€ๅ‘ไธ€ไธชๅœจ็ปˆ็ซฏไธญ่ฟ่กŒ็š„ๅ‘ฝไปค่กŒๅบ”็”จ่€Œไธๆ˜ฏ web API๏ผŒไธๅฆจ่ฏ•ไธ‹ **Typer**ใ€‚ +--- -**Typer** ๆ˜ฏ FastAPI ็š„ๅฐๅŒ่ƒžใ€‚ๅฎƒๆƒณ่ฆๆˆไธบ**ๅ‘ฝไปค่กŒไธญ็š„ FastAPI**ใ€‚ โŒจ๏ธ ๐Ÿš€ +## FastAPI ่ฟทไฝ ็บชๅฝ•็‰‡ { #fastapi-mini-documentary } -## ไพ่ต– +ๅœจ 2025 ๅนดๆœซๅ‘ๅธƒไบ†ไธ€้ƒจFastAPI ่ฟทไฝ ็บชๅฝ•็‰‡๏ผŒไฝ ๅฏไปฅๅœจ็บฟ่ง‚็œ‹๏ผš -Python ๅŠๆ›ด้ซ˜็‰ˆๆœฌ +FastAPI Mini Documentary -FastAPI ็ซ™ๅœจไปฅไธ‹ๅทจไบบ็š„่‚ฉ่†€ไน‹ไธŠ๏ผš +## **Typer**๏ผŒๅ‘ฝไปค่กŒไธญ็š„ FastAPI { #typer-the-fastapi-of-clis } -* Starlette ่ดŸ่ดฃ web ้ƒจๅˆ†ใ€‚ -* Pydantic ่ดŸ่ดฃๆ•ฐๆฎ้ƒจๅˆ†ใ€‚ + -## ๅฎ‰่ฃ… +ๅฆ‚ๆžœไฝ ่ฆๅผ€ๅ‘ไธ€ไธช็”จไบŽ็ปˆ็ซฏ็š„ ๅ‘ฝไปค่กŒๅบ”็”จ่€Œไธๆ˜ฏ Web API๏ผŒ็œ‹็œ‹ **Typer**ใ€‚ -
+**Typer** ๆ˜ฏ FastAPI ็š„ๅฐๅŒ่ƒžใ€‚ๅฎƒ็š„็›ฎๆ ‡ๆ˜ฏๆˆไธบ**ๅ‘ฝไปค่กŒไธญ็š„ FastAPI**ใ€‚โŒจ๏ธ ๐Ÿš€ -```console -$ pip install fastapi +## ไพ่ต– { #requirements } ----> 100% -``` +FastAPI ็ซ™ๅœจๅทจไบบ็š„่‚ฉ่†€ไน‹ไธŠ๏ผš -
+* Starlette ่ดŸ่ดฃ Web ้ƒจๅˆ†ใ€‚ +* Pydantic ่ดŸ่ดฃๆ•ฐๆฎ้ƒจๅˆ†ใ€‚ + +## ๅฎ‰่ฃ… { #installation } -ไฝ ่ฟ˜ไผš้œ€่ฆไธ€ไธช ASGI ๆœๅŠกๅ™จ๏ผŒ็”Ÿไบง็Žฏๅขƒๅฏไปฅไฝฟ็”จ Uvicorn ๆˆ–่€… Hypercornใ€‚ +ๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ๏ผŒ็„ถๅŽๅฎ‰่ฃ… FastAPI๏ผš
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
-## ็คบไพ‹ +**Note**: ่ฏท็กฎไฟๆŠŠ `"fastapi[standard]"` ็”จๅผ•ๅทๅŒ…่ตทๆฅ๏ผŒไปฅไฟ่ฏๅœจๆ‰€ๆœ‰็ปˆ็ซฏไธญ้ƒฝ่ƒฝๆญฃๅธธๅทฅไฝœใ€‚ -### ๅˆ›ๅปบ +## ็คบไพ‹ { #example } -* ๅˆ›ๅปบไธ€ไธช `main.py` ๆ–‡ไปถๅนถๅ†™ๅ…ฅไปฅไธ‹ๅ†…ๅฎน: +### ๅˆ›ๅปบ { #create-it } -```Python -from typing import Union +ๅˆ›ๅปบๆ–‡ไปถ `main.py`๏ผŒๅ†…ๅฎนๅฆ‚ไธ‹๏ผš +```Python from fastapi import FastAPI app = FastAPI() @@ -167,18 +172,16 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ```
ๆˆ–่€…ไฝฟ็”จ async def... -ๅฆ‚ๆžœไฝ ็š„ไปฃ็ ้‡Œไผšๅ‡บ็Žฐ `async` / `await`๏ผŒ่ฏทไฝฟ็”จ `async def`๏ผš - -```Python hl_lines="9 14" -from typing import Union +ๅฆ‚ๆžœไฝ ็š„ไปฃ็ ้‡Œไผš็”จๅˆฐ `async` / `await`๏ผŒ่ฏทไฝฟ็”จ `async def`๏ผš +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -190,28 +193,41 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: Union[str, None] = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` **Note**: -ๅฆ‚ๆžœไฝ ไธ็Ÿฅ้“ๆ˜ฏๅฆไผš็”จๅˆฐ๏ผŒๅฏไปฅๆŸฅ็œ‹ๆ–‡ๆกฃ็š„ _"In a hurry?"_ ็ซ ่Š‚ไธญ ๅ…ณไบŽ `async` ๅ’Œ `await` ็š„้ƒจๅˆ†ใ€‚ +ๅฆ‚ๆžœไฝ ไธ็กฎๅฎš๏ผŒ่ฏทๆŸฅ็œ‹ๆ–‡ๆกฃไธญ _"In a hurry?"_ ็ซ ่Š‚็š„`async` ๅ’Œ `await`้ƒจๅˆ†ใ€‚
-### ่ฟ่กŒ +### ่ฟ่กŒ { #run-it } -้€š่ฟ‡ไปฅไธ‹ๅ‘ฝไปค่ฟ่กŒๆœๅŠกๅ™จ๏ผš +็”จไธ‹้ข็š„ๅ‘ฝไปค่ฟ่กŒๆœๅŠกๅ™จ๏ผš
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ + โ”‚ โ”‚ + โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ + โ”‚ โ”‚ + โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ + โ”‚ โ”‚ + โ”‚ Running in development mode, for production use: โ”‚ + โ”‚ โ”‚ + โ”‚ fastapi run โ”‚ + โ”‚ โ”‚ + โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -219,58 +235,56 @@ INFO: Application startup complete.
-ๅ…ณไบŽ uvicorn main:app --reload ๅ‘ฝไปค...... +ๅ…ณไบŽๅ‘ฝไปค fastapi dev main.py... + +`fastapi dev` ๅ‘ฝไปคไผš่ฏปๅ–ไฝ ็š„ `main.py` ๆ–‡ไปถ๏ผŒๆฃ€ๆต‹ๅ…ถไธญ็š„ **FastAPI** ๅบ”็”จ๏ผŒๅนถไฝฟ็”จ Uvicorn ๅฏๅŠจๆœๅŠกๅ™จใ€‚ - `uvicorn main:app` ๅ‘ฝไปคๅซไน‰ๅฆ‚ไธ‹: +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ`fastapi dev` ไผšๅœจๆœฌๅœฐๅผ€ๅ‘ๆ—ถๅฏ็”จ่‡ชๅŠจ้‡่ฝฝใ€‚ -* `main`๏ผš`main.py` ๆ–‡ไปถ๏ผˆไธ€ไธช Python "ๆจกๅ—"๏ผ‰ใ€‚ -* `app`๏ผšๅœจ `main.py` ๆ–‡ไปถไธญ้€š่ฟ‡ `app = FastAPI()` ๅˆ›ๅปบ็š„ๅฏน่ฑกใ€‚ -* `--reload`๏ผš่ฎฉๆœๅŠกๅ™จๅœจๆ›ดๆ–ฐไปฃ็ ๅŽ้‡ๆ–ฐๅฏๅŠจใ€‚ไป…ๅœจๅผ€ๅ‘ๆ—ถไฝฟ็”จ่ฏฅ้€‰้กนใ€‚ +ไฝ ๅฏไปฅๅœจ FastAPI CLI ๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšใ€‚
-### ๆฃ€ๆŸฅ +### ๆฃ€ๆŸฅ { #check-it } -ไฝฟ็”จๆต่งˆๅ™จ่ฎฟ้—ฎ http://127.0.0.1:8000/items/5?q=somequeryใ€‚ +็”จๆต่งˆๅ™จๆ‰“ๅผ€ http://127.0.0.1:8000/items/5?q=somequeryใ€‚ -ไฝ ๅฐ†ไผš็œ‹ๅˆฐๅฆ‚ไธ‹ JSON ๅ“ๅบ”๏ผš +ไฝ ไผš็œ‹ๅˆฐๅฆ‚ไธ‹ JSON ๅ“ๅบ”๏ผš ```JSON {"item_id": 5, "q": "somequery"} ``` -ไฝ ๅทฒ็ปๅˆ›ๅปบไบ†ไธ€ไธชๅ…ทๆœ‰ไปฅไธ‹ๅŠŸ่ƒฝ็š„ API๏ผš +ไฝ ๅทฒ็ปๅˆ›ๅปบไบ†ไธ€ไธช API๏ผŒๅฎƒๅฏไปฅ๏ผš -* ้€š่ฟ‡ _่ทฏๅพ„_ `/` ๅ’Œ `/items/{item_id}` ๆŽฅๅ— HTTP ่ฏทๆฑ‚ใ€‚ -* ไปฅไธŠ _่ทฏๅพ„_ ้ƒฝๆŽฅๅ— `GET` ๆ“ไฝœ๏ผˆไนŸ่ขซ็งฐไธบ HTTP _ๆ–นๆณ•_๏ผ‰ใ€‚ -* `/items/{item_id}` _่ทฏๅพ„_ ๆœ‰ไธ€ไธช _่ทฏๅพ„ๅ‚ๆ•ฐ_ `item_id` ๅนถไธ”ๅบ”่ฏฅไธบ `int` ็ฑปๅž‹ใ€‚ -* `/items/{item_id}` _่ทฏๅพ„_ ๆœ‰ไธ€ไธชๅฏ้€‰็š„ `str` ็ฑปๅž‹็š„ _ๆŸฅ่ฏขๅ‚ๆ•ฐ_ `q`ใ€‚ +* ๅœจ่ทฏๅพ„ `/` ๅ’Œ `/items/{item_id}` ๆŽฅๆ”ถ HTTP ่ฏทๆฑ‚ใ€‚ +* ไปฅไธŠไธคไธช่ทฏๅพ„้ƒฝๆŽฅๅ— `GET` ๆ“ไฝœ๏ผˆไนŸ็งฐไธบ HTTP ๆ–นๆณ•๏ผ‰ใ€‚ +* ่ทฏๅพ„ `/items/{item_id}` ๆœ‰ไธ€ไธชๅบ”ไธบ `int` ็š„่ทฏๅพ„ๅ‚ๆ•ฐ `item_id`ใ€‚ +* ่ทฏๅพ„ `/items/{item_id}` ๆœ‰ไธ€ไธชๅฏ้€‰็š„ `str` ็ฑปๅž‹ๆŸฅ่ฏขๅ‚ๆ•ฐ `q`ใ€‚ -### ไบคไบ’ๅผ API ๆ–‡ๆกฃ +### ไบคไบ’ๅผ API ๆ–‡ๆกฃ { #interactive-api-docs } ็Žฐๅœจ่ฎฟ้—ฎ http://127.0.0.1:8000/docsใ€‚ -ไฝ ไผš็œ‹ๅˆฐ่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผˆ็”ฑ Swagger UI็”Ÿๆˆ๏ผ‰๏ผš +ไฝ ไผš็œ‹ๅˆฐ่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผˆ็”ฑ Swagger UI ๆไพ›๏ผ‰๏ผš ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ๅฏ้€‰็š„ API ๆ–‡ๆกฃ +### ๅฏ้€‰็š„ API ๆ–‡ๆกฃ { #alternative-api-docs } -่ฎฟ้—ฎ http://127.0.0.1:8000/redocใ€‚ +็„ถๅŽ่ฎฟ้—ฎ http://127.0.0.1:8000/redocใ€‚ -ไฝ ไผš็œ‹ๅˆฐๅฆไธ€ไธช่‡ชๅŠจ็”Ÿๆˆ็š„ๆ–‡ๆกฃ๏ผˆ็”ฑ ReDoc ็”Ÿๆˆ๏ผ‰๏ผš +ไฝ ไผš็œ‹ๅˆฐๅฆไธ€ไธช่‡ชๅŠจ็”Ÿๆˆ็š„ๆ–‡ๆกฃ๏ผˆ็”ฑ ReDoc ๆไพ›๏ผ‰๏ผš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## ็คบไพ‹ๅ‡็บง +## ็คบไพ‹ๅ‡็บง { #example-upgrade } -็Žฐๅœจไฟฎๆ”น `main.py` ๆ–‡ไปถๆฅไปŽ `PUT` ่ฏทๆฑ‚ไธญๆŽฅๆ”ถ่ฏทๆฑ‚ไฝ“ใ€‚ +็Žฐๅœจไฟฎๆ”น `main.py` ๆ–‡ไปถๆฅๆŽฅๆ”ถๆฅ่‡ช `PUT` ่ฏทๆฑ‚็š„่ฏทๆฑ‚ไฝ“ใ€‚ -ๆˆ‘ไปฌๅ€ŸๅŠฉ Pydantic ๆฅไฝฟ็”จๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“ใ€‚ - -```Python hl_lines="4 9-12 25-27" -from typing import Union +ๅ€ŸๅŠฉ Pydantic๏ผŒไฝฟ็”จๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ๆฅๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“ใ€‚ +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -280,7 +294,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool, None] = None + is_offer: bool | None = None @app.get("/") @@ -289,7 +303,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: Union[str, None] = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -298,173 +312,248 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -ๆœๅŠกๅ™จๅฐ†ไผš่‡ชๅŠจ้‡่ฝฝ๏ผˆๅ› ไธบๅœจไธŠ้ข็š„ๆญฅ้ชคไธญไฝ ๅ‘ `uvicorn` ๅ‘ฝไปคๆทปๅŠ ไบ† `--reload` ้€‰้กน๏ผ‰ใ€‚ +`fastapi dev` ๆœๅŠกๅ™จไผš่‡ชๅŠจ้‡่ฝฝใ€‚ -### ไบคไบ’ๅผ API ๆ–‡ๆกฃๅ‡็บง +### ไบคไบ’ๅผ API ๆ–‡ๆกฃๅ‡็บง { #interactive-api-docs-upgrade } -่ฎฟ้—ฎ http://127.0.0.1:8000/docsใ€‚ +็Žฐๅœจ่ฎฟ้—ฎ http://127.0.0.1:8000/docsใ€‚ -* ไบคไบ’ๅผ API ๆ–‡ๆกฃๅฐ†ไผš่‡ชๅŠจๆ›ดๆ–ฐ๏ผŒๅนถๅŠ ๅ…ฅๆ–ฐ็š„่ฏทๆฑ‚ไฝ“๏ผš +* ไบคไบ’ๅผ API ๆ–‡ๆกฃไผš่‡ชๅŠจๆ›ดๆ–ฐ๏ผŒๅนถๅŒ…ๅซๆ–ฐ็š„่ฏทๆฑ‚ไฝ“๏ผš ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ็‚นๅ‡ปใ€ŒTry it outใ€ๆŒ‰้’ฎ๏ผŒไน‹ๅŽไฝ ๅฏไปฅๅกซๅ†™ๅ‚ๆ•ฐๅนถ็›ดๆŽฅ่ฐƒ็”จ API๏ผš +* ็‚นๅ‡ปใ€ŒTry it outใ€ๆŒ‰้’ฎ๏ผŒๅฎƒๅ…่ฎธไฝ ๅกซๅ†™ๅ‚ๆ•ฐๅนถ็›ดๆŽฅไธŽ API ไบคไบ’๏ผš ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -* ็„ถๅŽ็‚นๅ‡ปใ€ŒExecuteใ€ๆŒ‰้’ฎ๏ผŒ็”จๆˆท็•Œ้ขๅฐ†ไผšๅ’Œ API ่ฟ›่กŒ้€šไฟก๏ผŒๅ‘้€ๅ‚ๆ•ฐ๏ผŒ่Žทๅ–็ป“ๆžœๅนถๅœจๅฑๅน•ไธŠๅฑ•็คบ๏ผš +* ็„ถๅŽ็‚นๅ‡ปใ€ŒExecuteใ€ๆŒ‰้’ฎ๏ผŒ็•Œ้ขไผšไธŽไฝ ็š„ API ้€šไฟกใ€ๅ‘้€ๅ‚ๆ•ฐใ€่Žทๅ–็ป“ๆžœๅนถๅœจๅฑๅน•ไธŠๅฑ•็คบ๏ผš ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) -### ๅฏ้€‰ๆ–‡ๆกฃๅ‡็บง +### ๅฏ้€‰ๆ–‡ๆกฃๅ‡็บง { #alternative-api-docs-upgrade } -่ฎฟ้—ฎ http://127.0.0.1:8000/redocใ€‚ +ๅ†่ฎฟ้—ฎ http://127.0.0.1:8000/redocใ€‚ -* ๅฏ้€‰ๆ–‡ๆกฃๅŒๆ ทไผšไฝ“็Žฐๆ–ฐๅŠ ๅ…ฅ็š„่ฏทๆฑ‚ๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“๏ผš +* ๅฏ้€‰ๆ–‡ๆกฃๅŒๆ ทไผšไฝ“็Žฐๆ–ฐ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“๏ผš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ๆ€ป็ป“ +### ๆ€ป็ป“ { #recap } -ๆ€ป็š„ๆฅ่ฏด๏ผŒไฝ ๅฐฑๅƒๅฃฐๆ˜Žๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ็ฑปๅž‹ไธ€ๆ ทๅชๅฃฐๆ˜Žไบ†**ไธ€ๆฌก**่ฏทๆฑ‚ๅ‚ๆ•ฐใ€่ฏทๆฑ‚ไฝ“็ญ‰็š„็ฑปๅž‹ใ€‚ +ๆ€ปไน‹๏ผŒไฝ ๅช้œ€่ฆๆŠŠๅ‚ๆ•ฐใ€่ฏทๆฑ‚ไฝ“็ญ‰็š„็ฑปๅž‹ไฝœไธบๅ‡ฝๆ•ฐๅ‚ๆ•ฐ**ๅฃฐๆ˜Žไธ€ๆฌก**ใ€‚ -ไฝ ไฝฟ็”จไบ†ๆ ‡ๅ‡†็š„็Žฐไปฃ Python ็ฑปๅž‹ๆฅๅฎŒๆˆๅฃฐๆ˜Žใ€‚ +่ฟ™ไบ›้ƒฝไฝฟ็”จๆ ‡ๅ‡†็š„็Žฐไปฃ Python ็ฑปๅž‹ๅณๅฏใ€‚ -ไฝ ไธ้œ€่ฆๅŽปๅญฆไน ๆ–ฐ็š„่ฏญๆณ•ใ€ไบ†่งฃ็‰นๅฎšๅบ“็š„ๆ–นๆณ•ๆˆ–็ฑป๏ผŒ็ญ‰็ญ‰ใ€‚ +ไฝ ไธ้œ€่ฆๅญฆไน ๆ–ฐ็š„่ฏญๆณ•ใ€ๆŸไธช็‰นๅฎšๅบ“็š„ๆ–นๆณ•ๆˆ–็ฑป็ญ‰ใ€‚ -ๅช้œ€่ฆไฝฟ็”จๆ ‡ๅ‡†็š„ **Python ๅŠๆ›ด้ซ˜็‰ˆๆœฌ**ใ€‚ +ๅช้œ€่ฆๆ ‡ๅ‡†็š„ **Python**ใ€‚ -ไธพไธชไพ‹ๅญ๏ผŒๆฏ”ๅฆ‚ๅฃฐๆ˜Ž `int` ็ฑปๅž‹๏ผš +ไพ‹ๅฆ‚๏ผŒไธ€ไธช `int`๏ผš ```Python item_id: int ``` -ๆˆ–่€…ไธ€ไธชๆ›ดๅคๆ‚็š„ `Item` ๆจกๅž‹๏ผš +ๆˆ–่€…ๆ›ดๅคๆ‚็š„ `Item` ๆจกๅž‹๏ผš ```Python item: Item ``` -......ๅœจ่ฟ›่กŒไธ€ๆฌกๅฃฐๆ˜Žไน‹ๅŽ๏ผŒไฝ ๅฐ†่Žทๅพ—๏ผš +โ€ฆโ€ฆ้€š่ฟ‡ไธ€ๆฌกๅฃฐๆ˜Ž๏ผŒไฝ ๅฐ†่Žทๅพ—๏ผš * ็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผŒๅŒ…ๆ‹ฌ๏ผš - * ่‡ชๅŠจ่กฅๅ…จ - * ็ฑปๅž‹ๆฃ€ๆŸฅ + * ่‡ชๅŠจ่กฅๅ…จใ€‚ + * ็ฑปๅž‹ๆฃ€ๆŸฅใ€‚ * ๆ•ฐๆฎๆ ก้ชŒ๏ผš - * ๅœจๆ ก้ชŒๅคฑ่ดฅๆ—ถ่‡ชๅŠจ็”Ÿๆˆๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏ - * ๅฏนๅคšๅฑ‚ๅตŒๅฅ—็š„ JSON ๅฏน่ฑกไพ็„ถๆ‰ง่กŒๆ ก้ชŒ -* ่ฝฌๆข ๆฅ่‡ช็ฝ‘็ปœ่ฏทๆฑ‚็š„่พ“ๅ…ฅๆ•ฐๆฎไธบ Python ๆ•ฐๆฎ็ฑปๅž‹ใ€‚ๅŒ…ๆ‹ฌไปฅไธ‹ๆ•ฐๆฎ๏ผš - * JSON - * ่ทฏๅพ„ๅ‚ๆ•ฐ - * ๆŸฅ่ฏขๅ‚ๆ•ฐ - * Cookies - * ่ฏทๆฑ‚ๅคด - * ่กจๅ• - * ๆ–‡ไปถ -* ่ฝฌๆข ่พ“ๅ‡บ็š„ๆ•ฐๆฎ๏ผš่ฝฌๆข Python ๆ•ฐๆฎ็ฑปๅž‹ไธบไพ›็ฝ‘็ปœไผ ่พ“็š„ JSON ๆ•ฐๆฎ๏ผš - * ่ฝฌๆข Python ๅŸบ็ก€็ฑปๅž‹ ๏ผˆ`str`ใ€ `int`ใ€ `float`ใ€ `bool`ใ€ `list` ็ญ‰๏ผ‰ - * `datetime` ๅฏน่ฑก - * `UUID` ๅฏน่ฑก - * ๆ•ฐๆฎๅบ“ๆจกๅž‹ - * ......ไปฅๅŠๆ›ดๅคšๅ…ถไป–็ฑปๅž‹ + * ๅฝ“ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถ่‡ชๅŠจ็”Ÿๆˆๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏใ€‚ + * ๅณไพฟๆ˜ฏๅคšๅฑ‚ๅตŒๅฅ—็š„ JSON ๅฏน่ฑกไนŸไผš่ฟ›่กŒๆ ก้ชŒใ€‚ +* ่พ“ๅ…ฅๆ•ฐๆฎ็š„่ฝฌๆข๏ผšไปŽ็ฝ‘็ปœ่ฏปๅ–ๅˆฐ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹ใ€‚่ฏปๅ–ๆฅๆบ๏ผš + * JSONใ€‚ + * ่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ + * ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ + * Cookiesใ€‚ + * Headersใ€‚ + * Formsใ€‚ + * Filesใ€‚ +* ่พ“ๅ‡บๆ•ฐๆฎ็š„่ฝฌๆข๏ผšไปŽ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹่ฝฌๆขไธบ็ฝ‘็ปœๆ•ฐๆฎ๏ผˆJSON๏ผ‰๏ผš + * ่ฝฌๆข Python ็ฑปๅž‹๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ็ญ‰๏ผ‰ใ€‚ + * `datetime` ๅฏน่ฑกใ€‚ + * `UUID` ๅฏน่ฑกใ€‚ + * ๆ•ฐๆฎๅบ“ๆจกๅž‹ใ€‚ + * โ€ฆโ€ฆไปฅๅŠๆ›ดๅคšใ€‚ * ่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผŒๅŒ…ๆ‹ฌไธค็งๅฏ้€‰็š„็”จๆˆท็•Œ้ข๏ผš - * Swagger UI - * ReDoc + * Swagger UIใ€‚ + * ReDocใ€‚ --- -ๅ›žๅˆฐๅ‰้ข็š„ไปฃ็ ็คบไพ‹๏ผŒ**FastAPI** ๅฐ†ไผš๏ผš +ๅ›žๅˆฐไน‹ๅ‰็š„ไปฃ็ ็คบไพ‹๏ผŒ**FastAPI** ๅฐ†ไผš๏ผš -* ๆ ก้ชŒ `GET` ๅ’Œ `PUT` ่ฏทๆฑ‚็š„่ทฏๅพ„ไธญๆ˜ฏๅฆๅซๆœ‰ `item_id`ใ€‚ +* ๆ ก้ชŒ `GET` ๅ’Œ `PUT` ่ฏทๆฑ‚็š„่ทฏๅพ„ไธญๆ˜ฏๅฆๅŒ…ๅซ `item_id`ใ€‚ * ๆ ก้ชŒ `GET` ๅ’Œ `PUT` ่ฏทๆฑ‚ไธญ็š„ `item_id` ๆ˜ฏๅฆไธบ `int` ็ฑปๅž‹ใ€‚ - * ๅฆ‚ๆžœไธๆ˜ฏ๏ผŒๅฎขๆˆท็ซฏๅฐ†ไผšๆ”ถๅˆฐๆธ…ๆ™ฐๆœ‰็”จ็š„้”™่ฏฏไฟกๆฏใ€‚ -* ๆฃ€ๆŸฅ `GET` ่ฏทๆฑ‚ไธญๆ˜ฏๅฆๆœ‰ๅ‘ฝๅไธบ `q` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผˆๆฏ”ๅฆ‚ `http://127.0.0.1:8000/items/foo?q=somequery`๏ผ‰ใ€‚ - * ๅ› ไธบ `q` ่ขซๅฃฐๆ˜Žไธบ `= None`๏ผŒๆ‰€ไปฅๅฎƒๆ˜ฏๅฏ้€‰็š„ใ€‚ - * ๅฆ‚ๆžœๆฒกๆœ‰ `None` ๅฎƒๅฐ†ไผšๆ˜ฏๅฟ…้œ€็š„ (ๅฆ‚ `PUT` ไพ‹ๅญไธญ็š„่ฏทๆฑ‚ไฝ“)ใ€‚ -* ๅฏนไบŽ่ฎฟ้—ฎ `/items/{item_id}` ็š„ `PUT` ่ฏทๆฑ‚๏ผŒๅฐ†่ฏทๆฑ‚ไฝ“่ฏปๅ–ไธบ JSON ๅนถ๏ผš - * ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ๅฟ…้œ€ๅฑžๆ€ง `name` ๅนถไธ”ๅ€ผไธบ `str` ็ฑปๅž‹ ใ€‚ - * ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ๅฟ…้œ€ๅฑžๆ€ง `price` ๅนถไธ”ๅ€ผไธบ `float` ็ฑปๅž‹ใ€‚ - * ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ๅฏ้€‰ๅฑžๆ€ง `is_offer`๏ผŒ ๅฆ‚ๆžœๆœ‰็š„่ฏๅ€ผๅบ”่ฏฅไธบ `bool` ็ฑปๅž‹ใ€‚ - * ไปฅไธŠ่ฟ‡็จ‹ๅฏนไบŽๅคšๅฑ‚ๅตŒๅฅ—็š„ JSON ๅฏน่ฑกๅŒๆ ทไนŸไผšๆ‰ง่กŒ -* ่‡ชๅŠจๅฏน JSON ่ฟ›่กŒ่ฝฌๆขๆˆ–่ฝฌๆขๆˆ JSONใ€‚ -* ้€š่ฟ‡ OpenAPI ๆ–‡ๆกฃๆฅ่ฎฐๅฝ•ๆ‰€ๆœ‰ๅ†…ๅฎน๏ผŒๅฏ่ขซ็”จไบŽ๏ผš - * ไบคไบ’ๅผๆ–‡ๆกฃ็ณป็ปŸ - * ่ฎธๅคš็ผ–็จ‹่ฏญ่จ€็š„ๅฎขๆˆท็ซฏไปฃ็ ่‡ชๅŠจ็”Ÿๆˆ็ณป็ปŸ -* ็›ดๆŽฅๆไพ› 2 ็งไบคไบ’ๅผๆ–‡ๆกฃ web ็•Œ้ขใ€‚ + * ๅฆ‚ๆžœไธๆ˜ฏ๏ผŒๅฎขๆˆท็ซฏไผš็œ‹ๅˆฐๆธ…ๆ™ฐๆœ‰็”จ็š„้”™่ฏฏไฟกๆฏใ€‚ +* ๅฏนไบŽ `GET` ่ฏทๆฑ‚๏ผŒๆฃ€ๆŸฅๆ˜ฏๅฆๅญ˜ๅœจๅไธบ `q` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผˆๅฆ‚ `http://127.0.0.1:8000/items/foo?q=somequery`๏ผ‰ใ€‚ + * ๅ› ไธบๅ‚ๆ•ฐ `q` ่ขซๅฃฐๆ˜Žไธบ `= None`๏ผŒๆ‰€ไปฅๅฎƒๆ˜ฏๅฏ้€‰็š„ใ€‚ + * ๅฆ‚ๆžœๆฒกๆœ‰ `None`๏ผŒๅฎƒๅฐฑๆ˜ฏๅฟ…้œ€็š„๏ผˆๅฐฑๅƒ `PUT` ๆƒ…ๅ†ตไธ‹็š„่ฏทๆฑ‚ไฝ“๏ผ‰ใ€‚ +* ๅฏนไบŽๅ‘้€ๅˆฐ `/items/{item_id}` ็š„ `PUT` ่ฏทๆฑ‚๏ผŒๆŠŠ่ฏทๆฑ‚ไฝ“ไฝœไธบ JSON ่ฏปๅ–๏ผš + * ๆฃ€ๆŸฅๆ˜ฏๅฆๅญ˜ๅœจๅฟ…้œ€ๅฑžๆ€ง `name`๏ผŒไธ”ไธบ `str`ใ€‚ + * ๆฃ€ๆŸฅๆ˜ฏๅฆๅญ˜ๅœจๅฟ…้œ€ๅฑžๆ€ง `price`๏ผŒไธ”ไธบ `float`ใ€‚ + * ๆฃ€ๆŸฅๆ˜ฏๅฆๅญ˜ๅœจๅฏ้€‰ๅฑžๆ€ง `is_offer`๏ผŒๅฆ‚ๆžœๅญ˜ๅœจๅˆ™ๅบ”ไธบ `bool`ใ€‚ + * ๅฏนไบŽๅคšๅฑ‚ๅตŒๅฅ—็š„ JSON ๅฏน่ฑก๏ผŒๅŒๆ ท้€‚็”จใ€‚ +* ่‡ชๅŠจๅฎŒๆˆ JSON ็š„่ฏปๅ–ไธŽ่พ“ๅ‡บ่ฝฌๆขใ€‚ +* ไฝฟ็”จ OpenAPI ่ฎฐๅฝ•ๆ‰€ๆœ‰ๅ†…ๅฎน๏ผŒๅฏ็”จไบŽ๏ผš + * ไบคไบ’ๅผๆ–‡ๆกฃ็ณป็ปŸใ€‚ + * ๅคš่ฏญ่จ€็š„ๅฎขๆˆท็ซฏไปฃ็ ่‡ชๅŠจ็”Ÿๆˆ็ณป็ปŸใ€‚ +* ็›ดๆŽฅๆไพ› 2 ็งไบคไบ’ๅผๆ–‡ๆกฃ Web ็•Œ้ขใ€‚ --- -่™ฝ็„ถๆˆ‘ไปฌๆ‰ๅˆšๅˆšๅผ€ๅง‹๏ผŒไฝ†ๅ…ถๅฎžไฝ ๅทฒ็ปไบ†่งฃไบ†่ฟ™ไธ€ๅˆ‡ๆ˜ฏๅฆ‚ไฝ•ๅทฅไฝœ็š„ใ€‚ +ๆˆ‘ไปฌๅชๆ˜ฏๆต…ๅฐ่พ„ๆญข๏ผŒไฝ†ไฝ ๅทฒ็ปๅคง่‡ดไบ†่งฃๅ…ถๅทฅไฝœๆ–นๅผไบ†ใ€‚ -ๅฐ่ฏ•ๆ›ดๆ”นไธ‹้ข่ฟ™่กŒไปฃ็ ๏ผš +ๅฐ่ฏ•ๆŠŠ่ฟ™ไธ€่กŒ๏ผš ```Python return {"item_name": item.name, "item_id": item_id} ``` -......ไปŽ๏ผš +โ€ฆโ€ฆไปŽ๏ผš ```Python ... "item_name": item.name ... ``` -......ๆ”นไธบ๏ผš +โ€ฆโ€ฆๆ”นไธบ๏ผš ```Python ... "item_price": item.price ... ``` -......ๆณจๆ„่ง‚ๅฏŸ็ผ–่พ‘ๅ™จๆ˜ฏๅฆ‚ไฝ•่‡ชๅŠจ่กฅๅ…จๅฑžๆ€งๅนถไธ”่ฟ˜็Ÿฅ้“ๅฎƒไปฌ็š„็ฑปๅž‹๏ผš +โ€ฆโ€ฆ็œ‹็œ‹ไฝ ็š„็ผ–่พ‘ๅ™จๅฆ‚ไฝ•่‡ชๅŠจ่กฅๅ…จๅฑžๆ€งๅนถ็Ÿฅ้“ๅฎƒไปฌ็š„็ฑปๅž‹๏ผš ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ— ไธญๆœ‰ๅŒ…ๅซๆ›ดๅคš็‰นๆ€ง็š„ๆ›ดๅฎŒๆ•ด็คบไพ‹ใ€‚ +ๆ›ดๅคšๅŒ…ๅซๆ›ดๅคš็‰นๆ€ง็š„ๅฎŒๆ•ด็คบไพ‹๏ผŒ่ฏทๅ‚้˜… ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—ใ€‚ -**ๅ‰ง้€่ญฆๅ‘Š**๏ผš ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—ไธญ็š„ๅ†…ๅฎนๆœ‰๏ผš +**ๅ‰ง้€่ญฆๅ‘Š**๏ผšๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—ๅŒ…ๆ‹ฌ๏ผš -* ๅฏนๆฅ่‡ชไธๅŒๅœฐๆ–น็š„ๅ‚ๆ•ฐ่ฟ›่กŒๅฃฐๆ˜Ž๏ผŒๅฆ‚๏ผš**่ฏทๆฑ‚ๅคด**ใ€**cookies**ใ€**form ่กจๅ•**ไปฅๅŠ**ไธŠไผ ็š„ๆ–‡ไปถ**ใ€‚ -* ๅฆ‚ไฝ•่ฎพ็ฝฎ**ๆ ก้ชŒ็บฆๆŸ**ๅฆ‚ `maximum_length` ๆˆ–่€… `regex`ใ€‚ -* ไธ€ไธชๅผบๅคงๅนถๆ˜“ไบŽไฝฟ็”จ็š„ **ไพ่ต–ๆณจๅ…ฅ** ็ณป็ปŸใ€‚ -* ๅฎ‰ๅ…จๆ€งๅ’Œ่บซไปฝ้ชŒ่ฏ๏ผŒๅŒ…ๆ‹ฌ้€š่ฟ‡ **JWT ไปค็‰Œ**ๅ’Œ **HTTP ๅŸบๆœฌ่บซไปฝ่ฎค่ฏ**ๆฅๆ”ฏๆŒ **OAuth2**ใ€‚ -* ๆ›ด่ฟ›้˜ถ๏ผˆไฝ†ๅŒๆ ท็ฎ€ๅ•๏ผ‰็š„ๆŠ€ๅทงๆฅๅฃฐๆ˜Ž **ๅคšๅฑ‚ๅตŒๅฅ— JSON ๆจกๅž‹** ๏ผˆๅ€ŸๅŠฉ Pydantic๏ผ‰ใ€‚ -* ่ฎธๅคš้ขๅค–ๅŠŸ่ƒฝ๏ผˆๅฝ’ๅŠŸไบŽ Starlette๏ผ‰ๆฏ”ๅฆ‚๏ผš +* ๆฅ่‡ชไธๅŒไฝ็ฝฎ็š„**ๅ‚ๆ•ฐ**ๅฃฐๆ˜Ž๏ผš**headers**ใ€**cookies**ใ€**form ๅญ—ๆฎต**ๅ’Œ**ๆ–‡ไปถ**ใ€‚ +* ๅฆ‚ไฝ•่ฎพ็ฝฎ**ๆ ก้ชŒ็บฆๆŸ**๏ผŒๅฆ‚ `maximum_length` ๆˆ– `regex`ใ€‚ +* ๅŠŸ่ƒฝๅผบๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ต–ๆณจๅ…ฅ** ็ณป็ปŸใ€‚ +* ๅฎ‰ๅ…จไธŽ่ฎค่ฏ๏ผŒๅŒ…ๆ‹ฌๅฏน **OAuth2**ใ€**JWT tokens** ๅ’Œ **HTTP Basic** ่ฎค่ฏ็š„ๆ”ฏๆŒใ€‚ +* ๆ›ด้ซ˜็บง๏ผˆไฝ†ๅŒๆ ท็ฎ€ๅ•๏ผ‰็š„ **ๅคšๅฑ‚ๅตŒๅฅ— JSON ๆจกๅž‹** ๅฃฐๆ˜ŽๆŠ€ๅทง๏ผˆๅพ—็›ŠไบŽ Pydantic๏ผ‰ใ€‚ +* ้€š่ฟ‡ Strawberry ็ญ‰ๅบ“่ฟ›่กŒ **GraphQL** ้›†ๆˆใ€‚ +* ่ฎธๅคš้ขๅค–็‰นๆ€ง๏ผˆๅฝ’ๅŠŸไบŽ Starlette๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš * **WebSockets** - * **GraphQL** * ๅŸบไบŽ HTTPX ๅ’Œ `pytest` ็š„ๆžๅ…ถ็ฎ€ๅ•็š„ๆต‹่ฏ• * **CORS** * **Cookie Sessions** - * ......ไปฅๅŠๆ›ดๅคš + * โ€ฆโ€ฆไปฅๅŠๆ›ดๅคšใ€‚ + +### ้ƒจ็ฝฒไฝ ็š„ๅบ”็”จ๏ผˆๅฏ้€‰๏ผ‰ { #deploy-your-app-optional } + +ไฝ ๅฏไปฅ้€‰ๆ‹ฉๆŠŠ FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloud๏ผŒๅฆ‚ๆžœ่ฟ˜ๆฒกๆœ‰็š„่ฏๅŽปๅŠ ๅ…ฅๅ€™่กฅๅๅ•ๅงใ€‚๐Ÿš€ + +ๅฆ‚ๆžœไฝ ๅทฒ็ปๆœ‰ **FastAPI Cloud** ่ดฆๅท๏ผˆๆˆ‘ไปฌไปŽๅ€™่กฅๅๅ•้‚€่ฏทไบ†ไฝ  ๐Ÿ˜‰๏ผ‰๏ผŒไฝ ๅฏไปฅ็”จไธ€ไธชๅ‘ฝไปค้ƒจ็ฝฒไฝ ็š„ๅบ”็”จใ€‚ + +้ƒจ็ฝฒๅ‰๏ผŒๅ…ˆ็กฎ่ฎคๅทฒ็™ปๅฝ•๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` -## ๆ€ง่ƒฝ +
+ +็„ถๅŽ้ƒจ็ฝฒไฝ ็š„ๅบ”็”จ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ่ฟ™ๆ ท๏ผ็Žฐๅœจไฝ ๅฏไปฅ้€š่ฟ‡่ฏฅ URL ่ฎฟ้—ฎไฝ ็š„ๅบ”็”จไบ†ใ€‚โœจ + +#### ๅ…ณไบŽ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ๅŒไธ€ไฝไฝœ่€…ๅ’Œๅ›ข้˜Ÿๆ‰“้€ ใ€‚ + +ๅฎƒ่ฎฉไฝ ไปฅๆœ€ๅฐ็š„ๅทฅไฝœ้‡ๅฐฑ่ƒฝ**ๆž„ๅปบ**ใ€**้ƒจ็ฝฒ**ๅนถ**่ฎฟ้—ฎ**ไธ€ไธช APIใ€‚ + +ๅฎƒๆŠŠ็”จ FastAPI ๆž„ๅปบๅบ”็”จๆ—ถ็š„**ๅผ€ๅ‘่€…ไฝ“้ชŒ**ๅธฆๅˆฐไบ†้ƒจ็ฝฒๅˆฐไบ‘ไธŠ็š„่ฟ‡็จ‹ใ€‚๐ŸŽ‰ -็‹ฌ็ซ‹ๆœบๆž„ TechEmpower ๆ‰€ไฝœ็š„ๅŸบๅ‡†ๆต‹่ฏ•็ป“ๆžœๆ˜พ็คบ๏ผŒๅŸบไบŽ Uvicorn ่ฟ่กŒ็š„ **FastAPI** ็จ‹ๅบๆ˜ฏ ๆœ€ๅฟซ็š„ Python web ๆก†ๆžถไน‹ไธ€๏ผŒไป…ๆฌกไบŽ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ๏ผˆFastAPI ๅ†…้ƒจไฝฟ็”จไบ†ๅฎƒไปฌ๏ผ‰ใ€‚(*) +FastAPI Cloud ๆ˜ฏใ€ŒFastAPI and friendsใ€ๅผ€ๆบ้กน็›ฎ็š„ไธป่ฆ่ตžๅŠฉๆ–นๅ’Œ่ต„้‡‘ๆไพ›่€…ใ€‚โœจ -ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ฏทๆŸฅ้˜… ๅŸบๅ‡†ๆต‹่ฏ• ็ซ ่Š‚ใ€‚ +#### ้ƒจ็ฝฒๅˆฐๅ…ถไป–ไบ‘ๅŽ‚ๅ•† { #deploy-to-other-cloud-providers } -## ๅฏ้€‰ไพ่ต– +FastAPI ๆ˜ฏๅผ€ๆบไธ”ๅŸบไบŽๆ ‡ๅ‡†็š„ใ€‚ไฝ ๅฏไปฅ้ƒจ็ฝฒ FastAPI ๅบ”็”จๅˆฐไฝ ้€‰ๆ‹ฉ็š„ไปปๆ„ไบ‘ๅŽ‚ๅ•†ใ€‚ -็”จไบŽ Pydantic๏ผš +ๆŒ‰็…งไฝ ็š„ไบ‘ๅŽ‚ๅ•†็š„ๆŒ‡ๅ—้ƒจ็ฝฒ FastAPI ๅบ”็”จๅณๅฏใ€‚๐Ÿค“ + +## ๆ€ง่ƒฝ { #performance } + +็‹ฌ็ซ‹ๆœบๆž„ TechEmpower ็š„ๅŸบๅ‡†ๆต‹่ฏ•ๆ˜พ็คบ๏ผŒ่ฟ่กŒๅœจ Uvicorn ไธ‹็š„ **FastAPI** ๅบ”็”จๆ˜ฏๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€๏ผŒไป…ๆฌกไบŽ Starlette ๅ’Œ Uvicorn ๆœฌ่บซ๏ผˆFastAPI ๅ†…้ƒจไฝฟ็”จๅฎƒไปฌ๏ผ‰ใ€‚(*) + +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ฏทๅ‚้˜…ๅŸบๅ‡†ๆต‹่ฏ•็ซ ่Š‚ใ€‚ + +## ไพ่ต–้กน { #dependencies } + +FastAPI ไพ่ต– Pydantic ๅ’Œ Starletteใ€‚ + +### `standard` ไพ่ต– { #standard-dependencies } + +ๅฝ“ไฝ ้€š่ฟ‡ `pip install "fastapi[standard]"` ๅฎ‰่ฃ… FastAPI ๆ—ถ๏ผŒไผšๅŒ…ๅซ `standard` ็ป„็š„ไธ€ไบ›ๅฏ้€‰ไพ่ต–๏ผš + +Pydantic ไฝฟ็”จ๏ผš * email-validator - ็”จไบŽ email ๆ ก้ชŒใ€‚ -็”จไบŽ Starlette๏ผš +Starlette ไฝฟ็”จ๏ผš + +* httpx - ไฝฟ็”จ `TestClient` ๆ—ถ้œ€่ฆใ€‚ +* jinja2 - ไฝฟ็”จ้ป˜่ฎคๆจกๆฟ้…็ฝฎๆ—ถ้œ€่ฆใ€‚ +* python-multipart - ไฝฟ็”จ `request.form()` ๆ”ฏๆŒ่กจๅ•ใ€Œ่งฃๆžใ€ๆ—ถ้œ€่ฆใ€‚ + +FastAPI ไฝฟ็”จ๏ผš + +* uvicorn - ๅŠ ่ฝฝๅนถๆไพ›ไฝ ็š„ๅบ”็”จ็š„ๆœๅŠกๅ™จใ€‚ๅŒ…ๅซ `uvicorn[standard]`๏ผŒๅ…ถไธญๅŒ…ๅซ้ซ˜ๆ€ง่ƒฝๆœๅŠกๆ‰€้œ€็š„ไธ€ไบ›ไพ่ต–๏ผˆไพ‹ๅฆ‚ `uvloop`๏ผ‰ใ€‚ +* `fastapi-cli[standard]` - ๆไพ› `fastapi` ๅ‘ฝไปคใ€‚ + * ๅ…ถไธญๅŒ…ๅซ `fastapi-cloud-cli`๏ผŒๅฎƒๅ…่ฎธไฝ ๅฐ† FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloudใ€‚ + +### ไธๅŒ…ๅซ `standard` ไพ่ต– { #without-standard-dependencies } + +ๅฆ‚ๆžœไฝ ไธๆƒณๅŒ…ๅซ่ฟ™ไบ› `standard` ๅฏ้€‰ไพ่ต–๏ผŒๅฏไปฅไฝฟ็”จ `pip install fastapi`๏ผŒ่€Œไธๆ˜ฏ `pip install "fastapi[standard]"`ใ€‚ + +### ไธๅŒ…ๅซ `fastapi-cloud-cli` { #without-fastapi-cloud-cli } + +ๅฆ‚ๆžœไฝ ๆƒณๅฎ‰่ฃ…ๅธฆๆœ‰ standard ไพ่ต–ไฝ†ไธๅŒ…ๅซ `fastapi-cloud-cli` ็š„ FastAPI๏ผŒๅฏไปฅไฝฟ็”จ `pip install "fastapi[standard-no-fastapi-cloud-cli]"`ใ€‚ + +### ๅ…ถไป–ๅฏ้€‰ไพ่ต– { #additional-optional-dependencies } + +่ฟ˜ๆœ‰ไธ€ไบ›ไฝ ๅฏ่ƒฝๆƒณๅฎ‰่ฃ…็š„ๅฏ้€‰ไพ่ต–ใ€‚ -* httpx - ไฝฟ็”จ `TestClient` ๆ—ถๅฎ‰่ฃ…ใ€‚ -* jinja2 - ไฝฟ็”จ้ป˜่ฎคๆจกๆฟ้…็ฝฎๆ—ถๅฎ‰่ฃ…ใ€‚ -* python-multipart - ้œ€่ฆ้€š่ฟ‡ `request.form()` ๅฏน่กจๅ•่ฟ›่กŒใ€Œ่งฃๆžใ€ๆ—ถๅฎ‰่ฃ…ใ€‚ -* itsdangerous - ้œ€่ฆ `SessionMiddleware` ๆ”ฏๆŒๆ—ถๅฎ‰่ฃ…ใ€‚ -* pyyaml - ไฝฟ็”จ Starlette ๆไพ›็š„ `SchemaGenerator` ๆ—ถๅฎ‰่ฃ…๏ผˆๆœ‰ FastAPI ไฝ ๅฏ่ƒฝๅนถไธ้œ€่ฆๅฎƒ๏ผ‰ใ€‚ -* graphene - ้œ€่ฆ `GraphQLApp` ๆ”ฏๆŒๆ—ถๅฎ‰่ฃ…ใ€‚ +้ขๅค–็š„ Pydantic ๅฏ้€‰ไพ่ต–๏ผš -็”จไบŽ FastAPI / Starlette๏ผš +* pydantic-settings - ็”จไบŽ้…็ฝฎ็ฎก็†ใ€‚ +* pydantic-extra-types - ็”จไบŽๅœจ Pydantic ไธญไฝฟ็”จ็š„้ขๅค–็ฑปๅž‹ใ€‚ -* uvicorn - ็”จไบŽๅŠ ่ฝฝๅ’Œ่ฟ่กŒไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„ๆœๅŠกๅ™จใ€‚ -* orjson - ไฝฟ็”จ `ORJSONResponse` ๆ—ถๅฎ‰่ฃ…ใ€‚ -* ujson - ไฝฟ็”จ `UJSONResponse` ๆ—ถๅฎ‰่ฃ…ใ€‚ +้ขๅค–็š„ FastAPI ๅฏ้€‰ไพ่ต–๏ผš -ไฝ ๅฏไปฅ้€š่ฟ‡ `pip install "fastapi[all]"` ๅ‘ฝไปคๆฅๅฎ‰่ฃ…ไปฅไธŠๆ‰€ๆœ‰ไพ่ต–ใ€‚ +* orjson - ไฝฟ็”จ `ORJSONResponse` ๆ—ถ้œ€่ฆใ€‚ +* ujson - ไฝฟ็”จ `UJSONResponse` ๆ—ถ้œ€่ฆใ€‚ -## ่ฎธๅฏๅ่ฎฎ +## ่ฎธๅฏๅ่ฎฎ { #license } ่ฏฅ้กน็›ฎ้ตๅพช MIT ่ฎธๅฏๅ่ฎฎใ€‚ diff --git a/docs/zh/docs/learn/index.md b/docs/zh/docs/learn/index.md index 38696f6fea..144d5b2a9d 100644 --- a/docs/zh/docs/learn/index.md +++ b/docs/zh/docs/learn/index.md @@ -1,4 +1,4 @@ -# ๅญฆไน  +# ๅญฆไน  { #learn } ไปฅไธ‹ๆ˜ฏๅญฆไน  **FastAPI** ็š„ไป‹็ป้ƒจๅˆ†ๅ’Œๆ•™็จ‹ใ€‚ diff --git a/docs/zh/docs/project-generation.md b/docs/zh/docs/project-generation.md index 48eb990df3..a6ad9f94ac 100644 --- a/docs/zh/docs/project-generation.md +++ b/docs/zh/docs/project-generation.md @@ -1,28 +1,28 @@ -# FastAPIๅ…จๆ ˆๆจกๆฟ +# FastAPIๅ…จๆ ˆๆจกๆฟ { #full-stack-fastapi-template } -ๆจกๆฟ้€šๅธธๅธฆๆœ‰็‰นๅฎš็š„่ฎพ็ฝฎ๏ผŒ่€Œไธ”่ขซ่ฎพ่ฎกไธบ็ตๆดปๅ’Œๅฏๅฎšๅˆถ็š„ใ€‚่ฟ™ๅ…่ฎธๆ‚จๆ นๆฎ้กน็›ฎ็š„้œ€ๆฑ‚ไฟฎๆ”นๅ’Œ่ฐƒๆ•ดๅฎƒไปฌ๏ผŒไฝฟๅฎƒไปฌๆˆไธบไธ€ไธชๅพˆๅฅฝ็š„่ตท็‚นใ€‚๐Ÿ +ๆจกๆฟ้€šๅธธๅธฆๆœ‰็‰นๅฎš็š„่ฎพ็ฝฎ๏ผŒไฝ†ๅฎƒไปฌ่ขซ่ฎพ่ฎกไธบ็ตๆดปไธ”ๅฏๅฎšๅˆถใ€‚่ฟ™ๆ ทไฝ ๅฏไปฅๆ นๆฎ้กน็›ฎ้œ€ๆฑ‚่ฟ›่กŒไฟฎๆ”นๅ’Œ่ฐƒๆ•ด๏ผŒไฝฟๅ…ถๆˆไธบๅพˆๅฅฝ็š„่ตท็‚นใ€‚๐Ÿ -ๆ‚จๅฏไปฅไฝฟ็”จๆญคๆจกๆฟๅผ€ๅง‹๏ผŒๅ› ไธบๅฎƒๅŒ…ๅซไบ†่ฎธๅคšๅทฒ็ปไธบๆ‚จๅฎŒๆˆ็š„ๅˆๅง‹่ฎพ็ฝฎใ€ๅฎ‰ๅ…จๆ€งใ€ๆ•ฐๆฎๅบ“ๅ’Œไธ€ไบ›API็ซฏ็‚นใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จๆญคๆจกๆฟๅผ€ๅง‹๏ผŒๅฎƒๅทฒ็ปไธบไฝ ๅฎŒๆˆไบ†ๅคง้‡็š„ๅˆๅง‹่ฎพ็ฝฎใ€ๅฎ‰ๅ…จๆ€งใ€ๆ•ฐๆฎๅบ“ไปฅๅŠไธ€ไบ› API ็ซฏ็‚นใ€‚ -ไปฃ็ ไป“๏ผš Full Stack FastAPI Template +GitHub ไป“ๅบ“๏ผš Full Stack FastAPI Template -## FastAPIๅ…จๆ ˆๆจกๆฟ - ๆŠ€ๆœฏๆ ˆๅ’Œ็‰นๆ€ง +## FastAPIๅ…จๆ ˆๆจกๆฟ - ๆŠ€ๆœฏๆ ˆๅ’Œ็‰นๆ€ง { #full-stack-fastapi-template-technology-stack-and-features } -- โšก [**FastAPI**](https://fastapi.tiangolo.com) ็”จไบŽPythonๅŽ็ซฏAPI. - - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) ็”จไบŽPythonๅ’ŒSQLๆ•ฐๆฎๅบ“็š„้›†ๆˆ๏ผˆORM๏ผ‰ใ€‚ - - ๐Ÿ” [Pydantic](https://docs.pydantic.dev) FastAPI็š„ไพ่ต–้กนไน‹ไธ€๏ผŒ็”จไบŽๆ•ฐๆฎ้ชŒ่ฏๅ’Œ้…็ฝฎ็ฎก็†ใ€‚ - - ๐Ÿ’พ [PostgreSQL](https://www.postgresql.org) ไฝœไธบSQLๆ•ฐๆฎๅบ“ใ€‚ +- โšก [**FastAPI**](https://fastapi.tiangolo.com/zh) ็”จไบŽ Python ๅŽ็ซฏ APIใ€‚ + - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) ็”จไบŽ Python ไธŽ SQL ๆ•ฐๆฎๅบ“็š„ไบคไบ’๏ผˆORM๏ผ‰ใ€‚ + - ๐Ÿ” [Pydantic](https://docs.pydantic.dev)๏ผŒFastAPI ไฝฟ็”จ๏ผŒ็”จไบŽๆ•ฐๆฎ้ชŒ่ฏไธŽ้…็ฝฎ็ฎก็†ใ€‚ + - ๐Ÿ’พ [PostgreSQL](https://www.postgresql.org) ไฝœไธบ SQL ๆ•ฐๆฎๅบ“ใ€‚ - ๐Ÿš€ [React](https://react.dev) ็”จไบŽๅ‰็ซฏใ€‚ - - ๐Ÿ’ƒ ไฝฟ็”จไบ†TypeScriptใ€hooksใ€[Vite](https://vitejs.dev)ๅ’Œๅ…ถไป–ไธ€ไบ›็ŽฐไปฃๅŒ–็š„ๅ‰็ซฏๆŠ€ๆœฏๆ ˆใ€‚ - - ๐ŸŽจ [Chakra UI](https://chakra-ui.com) ็”จไบŽๅ‰็ซฏ็ป„ไปถใ€‚ - - ๐Ÿค– ไธ€ไธช่‡ชๅŠจๅŒ–็”Ÿๆˆ็š„ๅ‰็ซฏๅฎขๆˆท็ซฏใ€‚ - - ๐Ÿงช [Playwright](https://playwright.dev)็”จไบŽ็ซฏๅˆฐ็ซฏๆต‹่ฏ•ใ€‚ - - ๐Ÿฆ‡ ๆ”ฏๆŒๆš—้ป‘ไธป้ข˜๏ผˆDark mode๏ผ‰ใ€‚ -- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ็”จไบŽๅผ€ๅ‘็Žฏๅขƒๅ’Œ็”Ÿไบง็Žฏๅขƒใ€‚ -- ๐Ÿ”’ ้ป˜่ฎคไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒๆฅไฟ่ฏๅฎ‰ๅ…จใ€‚ -- ๐Ÿ”‘ JWTไปค็‰Œ็”จไบŽๆƒ้™้ชŒ่ฏใ€‚ -- ๐Ÿ“ซ ไฝฟ็”จ้‚ฎ็ฎฑๆฅ่ฟ›่กŒๅฏ†็ ๆขๅคใ€‚ -- โœ… ๅ•ๅ…ƒๆต‹่ฏ•็”จไบ†[Pytest](https://pytest.org). -- ๐Ÿ“ž [Traefik](https://traefik.io) ็”จไบŽๅๅ‘ไปฃ็†ๅ’Œ่ดŸ่ฝฝๅ‡่กกใ€‚ -- ๐Ÿšข ้ƒจ็ฝฒๆŒ‡ๅ—๏ผˆDocker Compose๏ผ‰ๅŒ…ๅซไบ†ๅฆ‚ไฝ•่ตทไธ€ไธชTraefikๅ‰็ซฏไปฃ็†ๆฅ่‡ชๅŠจๅŒ–HTTPS่ฎค่ฏใ€‚ -- ๐Ÿญ CI๏ผˆๆŒ็ปญ้›†ๆˆ๏ผ‰ๅ’Œ CD๏ผˆๆŒ็ปญ้ƒจ็ฝฒ๏ผ‰ๅŸบไบŽGitHub Actionsใ€‚ + - ๐Ÿ’ƒ ไฝฟ็”จ TypeScriptใ€hooksใ€Vite ไปฅๅŠ็Žฐไปฃๅ‰็ซฏๆŠ€ๆœฏๆ ˆ็š„ๅ…ถไป–้ƒจๅˆ†ใ€‚ + - ๐ŸŽจ [Tailwind CSS](https://tailwindcss.com) ไธŽ [shadcn/ui](https://ui.shadcn.com) ็”จไบŽๅ‰็ซฏ็ป„ไปถใ€‚ + - ๐Ÿค– ่‡ชๅŠจ็”Ÿๆˆ็š„ๅ‰็ซฏๅฎขๆˆท็ซฏใ€‚ + - ๐Ÿงช [Playwright](https://playwright.dev) ็”จไบŽ็ซฏๅˆฐ็ซฏๆต‹่ฏ•ใ€‚ + - ๐Ÿฆ‡ ๆ”ฏๆŒๆš—้ป‘ๆจกๅผใ€‚ +- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ็”จไบŽๅผ€ๅ‘ไธŽ็”Ÿไบงใ€‚ +- ๐Ÿ”’ ้ป˜่ฎคๅฏ็”จๅฎ‰ๅ…จ็š„ๅฏ†็ ๅ“ˆๅธŒใ€‚ +- ๐Ÿ”‘ JWT๏ผˆJSON Web Token๏ผ‰่ฎค่ฏใ€‚ +- ๐Ÿ“ซ ๅŸบไบŽ้‚ฎ็ฎฑ็š„ๅฏ†็ ๆ‰พๅ›žใ€‚ +- โœ… ไฝฟ็”จ [Pytest](https://pytest.org) ่ฟ›่กŒๆต‹่ฏ•ใ€‚ +- ๐Ÿ“ž [Traefik](https://traefik.io) ็”จไฝœๅๅ‘ไปฃ็†/่ดŸ่ฝฝๅ‡่กกใ€‚ +- ๐Ÿšข ไฝฟ็”จ Docker Compose ็š„้ƒจ็ฝฒๆŒ‡ๅ—๏ผŒๅŒ…ๆ‹ฌๅฆ‚ไฝ•่ฎพ็ฝฎๅ‰็ซฏ Traefik ไปฃ็†ไปฅ่‡ชๅŠจๅค„็† HTTPS ่ฏไนฆใ€‚ +- ๐Ÿญ ๅŸบไบŽ GitHub Actions ็š„ CI๏ผˆๆŒ็ปญ้›†ๆˆ๏ผ‰ไธŽ CD๏ผˆๆŒ็ปญ้ƒจ็ฝฒ๏ผ‰ใ€‚ diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index a7f76d97fa..3e1c593c11 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -1,31 +1,30 @@ -# Python ็ฑปๅž‹ๆ็คบ็ฎ€ไป‹ +# Python ็ฑปๅž‹ๆ็คบ็ฎ€ไป‹ { #python-types-intro } -**Python 3.6+ ็‰ˆๆœฌ**ๅŠ ๅ…ฅไบ†ๅฏน"็ฑปๅž‹ๆ็คบ"็š„ๆ”ฏๆŒใ€‚ +Python ๆ”ฏๆŒๅฏ้€‰็š„โ€œ็ฑปๅž‹ๆ็คบโ€๏ผˆไนŸๅซโ€œ็ฑปๅž‹ๆณจ่งฃโ€๏ผ‰ใ€‚ -่ฟ™ไบ›**"็ฑปๅž‹ๆ็คบ"**ๆ˜ฏไธ€็งๆ–ฐ็š„่ฏญๆณ•๏ผˆๅœจ Python 3.6 ็‰ˆๆœฌๅŠ ๅ…ฅ๏ผ‰็”จๆฅๅฃฐๆ˜Žไธ€ไธชๅ˜้‡็š„็ฑปๅž‹ใ€‚ +่ฟ™ไบ›โ€œ็ฑปๅž‹ๆ็คบโ€ๆˆ–ๆณจ่งฃๆ˜ฏไธ€็ง็‰นๆฎŠ่ฏญๆณ•๏ผŒ็”จๆฅๅฃฐๆ˜Žๅ˜้‡็š„็ฑปๅž‹ใ€‚ -้€š่ฟ‡ๅฃฐๆ˜Žๅ˜้‡็š„็ฑปๅž‹๏ผŒ็ผ–่พ‘ๅ™จๅ’Œไธ€ไบ›ๅทฅๅ…ท่ƒฝ็ป™ไฝ ๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒใ€‚ +้€š่ฟ‡ไธบๅ˜้‡ๅฃฐๆ˜Ž็ฑปๅž‹๏ผŒ็ผ–่พ‘ๅ™จๅ’Œๅทฅๅ…ทๅฏไปฅไธบไฝ ๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒใ€‚ -่ฟ™ๅชๆ˜ฏไธ€ไธชๅ…ณไบŽ Python ็ฑปๅž‹ๆ็คบ็š„**ๅฟซ้€Ÿๅ…ฅ้—จ / ๅคไน **ใ€‚ๅฎƒไป…ๆถต็›–ไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จๆ‰€้œ€็š„ๆœ€ๅฐ‘้ƒจๅˆ†...ๅฎž้™…ไธŠๅชๆœ‰ๅพˆๅฐ‘ไธ€็‚นใ€‚ +่ฟ™ๅชๆ˜ฏไธ€ไธชๅ…ณไบŽ Python ็ฑปๅž‹ๆ็คบ็š„ๅฟซ้€Ÿๅ…ฅ้—จ/ๅคไน ใ€‚ๅฎƒๅชๆถต็›–ไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จๆ‰€้œ€็š„ๆœ€ๅฐ‘้ƒจๅˆ†โ€ฆโ€ฆๅฎž้™…ไธŠ้žๅธธๅฐ‘ใ€‚ -ๆ•ดไธช **FastAPI** ้ƒฝๅŸบไบŽ่ฟ™ไบ›็ฑปๅž‹ๆ็คบๆž„ๅปบ๏ผŒๅฎƒไปฌๅธฆๆฅไบ†่ฎธๅคšไผ˜็‚นๅ’Œๅฅฝๅค„ใ€‚ +**FastAPI** ๅฎŒๅ…จๅŸบไบŽ่ฟ™ไบ›็ฑปๅž‹ๆ็คบๆž„ๅปบ๏ผŒๅฎƒไปฌๅธฆๆฅไบ†่ฎธๅคšไผ˜ๅŠฟๅ’Œๅฅฝๅค„ใ€‚ -ไฝ†ๅณไฝฟไฝ ไธไผš็”จๅˆฐ **FastAPI**๏ผŒไบ†่งฃไธ€ไธ‹็ฑปๅž‹ๆ็คบไนŸไผš่ฎฉไฝ ไปŽไธญๅ—็›Šใ€‚ +ไฝ†ๅณไฝฟไฝ ไปŽไธไฝฟ็”จ **FastAPI**๏ผŒไบ†่งฃไธ€ไบ›็ฑปๅž‹ๆ็คบไนŸไผš่ฎฉไฝ ๅ—็›Šใ€‚ -/// note +/// note | ๆณจๆ„ -ๅฆ‚ๆžœไฝ ๅทฒ็ป็ฒพ้€š Python๏ผŒๅนถไธ”ไบ†่งฃๅ…ณไบŽ็ฑปๅž‹ๆ็คบ็š„ไธ€ๅˆ‡็Ÿฅ่ฏ†๏ผŒ็›ดๆŽฅ่ทณๅˆฐไธ‹ไธ€็ซ ่Š‚ๅงใ€‚ +ๅฆ‚ๆžœไฝ ๅทฒ็ปๆ˜ฏ Python ไธ“ๅฎถ๏ผŒๅนถไธ”ๅฏน็ฑปๅž‹ๆ็คบไบ†ๅฆ‚ๆŒ‡ๆŽŒ๏ผŒๅฏไปฅ่ทณๅˆฐไธ‹ไธ€็ซ ใ€‚ /// -## ๅŠจๆœบ +## ๅŠจๆœบ { #motivation } ่ฎฉๆˆ‘ไปฌไปŽไธ€ไธช็ฎ€ๅ•็š„ไพ‹ๅญๅผ€ๅง‹๏ผš -{* ../../docs_src/python_types/tutorial001.py *} +{* ../../docs_src/python_types/tutorial001_py39.py *} - -่ฟ่กŒ่ฟ™ๆฎต็จ‹ๅบๅฐ†่พ“ๅ‡บ๏ผš +่ฟ่กŒ่ฟ™ไธช็จ‹ๅบไผš่พ“ๅ‡บ๏ผš ``` John Doe @@ -33,38 +32,37 @@ John Doe ่ฟ™ไธชๅ‡ฝๆ•ฐๅšไบ†ไธ‹้ข่ฟ™ไบ›ไบ‹ๆƒ…๏ผš -* ๆŽฅๆ”ถ `first_name` ๅ’Œ `last_name` ๅ‚ๆ•ฐใ€‚ -* ้€š่ฟ‡ `title()` ๅฐ†ๆฏไธชๅ‚ๆ•ฐ็š„็ฌฌไธ€ไธชๅญ—ๆฏ่ฝฌๆขไธบๅคงๅ†™ๅฝขๅผใ€‚ -* ไธญ้—ด็”จไธ€ไธช็ฉบๆ ผๆฅๆ‹ผๆŽฅๅฎƒไปฌใ€‚ - -{* ../../docs_src/python_types/tutorial001.py hl[2] *} +* ๆŽฅๆ”ถ `first_name` ๅ’Œ `last_name`ใ€‚ +* ้€š่ฟ‡ `title()` ๅฐ†ๆฏไธชๅ‚ๆ•ฐ็š„็ฌฌไธ€ไธชๅญ—ๆฏ่ฝฌๆขไธบๅคงๅ†™ใ€‚ +* ็”จไธ€ไธช็ฉบๆ ผๅฐ†ๅฎƒไปฌๆ‹ผๆŽฅ่ตทๆฅใ€‚ +{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} -### ไฟฎๆ”น็คบไพ‹ +### ไฟฎๆ”นๅฎƒ { #edit-it } ่ฟ™ๆ˜ฏไธ€ไธช้žๅธธ็ฎ€ๅ•็š„็จ‹ๅบใ€‚ -็Žฐๅœจๅ‡่ฎพไฝ ๅฐ†ไปŽๅคดๅผ€ๅง‹็ผ–ๅ†™่ฟ™ๆฎต็จ‹ๅบใ€‚ +ไฝ†็Žฐๅœจๆƒณ่ฑกไฝ ่ฆไปŽ้›ถๅผ€ๅง‹ๅ†™ๅฎƒใ€‚ -ๅœจๆŸไธ€ๆ—ถๅˆป๏ผŒไฝ ๅผ€ๅง‹ๅฎšไน‰ๅ‡ฝๆ•ฐ๏ผŒๅนถไธ”ๅ‡†ๅค‡ๅฅฝไบ†ๅ‚ๆ•ฐ...ใ€‚ +ๅœจๆŸไธชๆ—ถๅˆปไฝ ๅผ€ๅง‹ๅฎšไน‰ๅ‡ฝๆ•ฐ๏ผŒๅนถไธ”ๅ‡†ๅค‡ๅฅฝไบ†ๅ‚ๆ•ฐโ€ฆโ€ฆ -็Žฐๅœจไฝ ้œ€่ฆ่ฐƒ็”จไธ€ไธช"ๅฐ†็ฌฌไธ€ไธชๅญ—ๆฏ่ฝฌๆขไธบๅคงๅ†™ๅฝขๅผ็š„ๆ–นๆณ•"ใ€‚ +ๆŽฅไธ‹ๆฅไฝ ้œ€่ฆ่ฐƒ็”จโ€œ้‚ฃไธชๆŠŠ้ฆ–ๅญ—ๆฏๅ˜ๅคงๅ†™็š„ๆ–นๆณ•โ€ใ€‚ -็ญ‰็ญ‰๏ผŒ้‚ฃไธชๆ–นๆณ•ๆ˜ฏไป€ไนˆๆฅ็€๏ผŸ`upper`๏ผŸ่ฟ˜ๆ˜ฏ `uppercase`๏ผŸ`first_uppercase`๏ผŸ`capitalize`๏ผŸ +ๆ˜ฏ `upper`๏ผŸๆ˜ฏ `uppercase`๏ผŸ`first_uppercase`๏ผŸ่ฟ˜ๆ˜ฏ `capitalize`๏ผŸ -็„ถๅŽไฝ ๅฐ่ฏ•ๅ‘็จ‹ๅบๅ‘˜่€ๆ‰‹็š„ๆœ‹ๅ‹โ€”โ€”็ผ–่พ‘ๅ™จ่‡ชๅŠจ่กฅๅ…จๅฏปๆฑ‚ๅธฎๅŠฉใ€‚ +็„ถๅŽ๏ผŒไฝ ่ฏ•่ฏ•็จ‹ๅบๅ‘˜็š„่€ๆœ‹ๅ‹โ€”โ€”็ผ–่พ‘ๅ™จ็š„่‡ชๅŠจ่กฅๅ…จใ€‚ -่พ“ๅ…ฅๅ‡ฝๆ•ฐ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐ `first_name`๏ผŒ่พ“ๅ…ฅ็‚นๅท๏ผˆ`.`๏ผ‰็„ถๅŽๆ•ฒไธ‹ `Ctrl+Space` ๆฅ่งฆๅ‘ไปฃ็ ่กฅๅ…จใ€‚ +ไฝ ่พ“ๅ…ฅๅ‡ฝๆ•ฐ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐ `first_name`๏ผŒๅ†่พ“ๅ…ฅไธ€ไธช็‚น๏ผˆ`.`๏ผ‰๏ผŒ็„ถๅŽๆŒ‰ไธ‹ `Ctrl+Space` ่งฆๅ‘่กฅๅ…จใ€‚ -ไฝ†้—ๆ†พ็š„ๆ˜ฏๅนถๆฒกๆœ‰่ตทไป€ไนˆไฝœ็”จ๏ผš +ไฝ†ๅพˆ้—ๆ†พ๏ผŒๆฒกๆœ‰ไป€ไนˆๆœ‰็”จ็š„ๆ็คบ๏ผš - + -### ๆทปๅŠ ็ฑปๅž‹ +### ๆทปๅŠ ็ฑปๅž‹ { #add-types } -่ฎฉๆˆ‘ไปฌๆฅไฟฎๆ”นไธŠ้ขไพ‹ๅญ็š„ไธ€่กŒไปฃ็ ใ€‚ +ๆˆ‘ไปฌๆฅๆ”นๅ‰ไธ€ไธช็‰ˆๆœฌ็š„ไธ€่กŒไปฃ็ ใ€‚ -ๆˆ‘ไปฌๅฐ†ๆŠŠไธ‹้ข่ฟ™ๆฎตไปฃ็ ไธญ็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐไปŽ๏ผš +ๆŠŠๅ‡ฝๆ•ฐๅ‚ๆ•ฐไปŽ๏ผš ```Python first_name, last_name @@ -78,227 +76,389 @@ John Doe ๅฐฑๆ˜ฏ่ฟ™ๆ ทใ€‚ -่ฟ™ไบ›ๅฐฑๆ˜ฏ"็ฑปๅž‹ๆ็คบ"๏ผš - -{* ../../docs_src/python_types/tutorial002.py hl[1] *} +่ฟ™ไบ›ๅฐฑๆ˜ฏโ€œ็ฑปๅž‹ๆ็คบโ€๏ผš +{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} -่ฟ™ๅ’Œๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผๆ˜ฏไธๅŒ็š„๏ผŒไพ‹ๅฆ‚๏ผš +่ฟ™ๅ’Œๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผไธๅŒ๏ผŒๆฏ”ๅฆ‚๏ผš ```Python first_name="john", last_name="doe" ``` -่ฟ™ไธค่€…ไธไธ€ๆ ทใ€‚ +่ฟ™ๆ˜ฏไธค็ ไบ‹ใ€‚ ๆˆ‘ไปฌ็”จ็š„ๆ˜ฏๅ†’ๅท๏ผˆ`:`๏ผ‰๏ผŒไธๆ˜ฏ็ญ‰ๅท๏ผˆ`=`๏ผ‰ใ€‚ -่€Œไธ”ๆทปๅŠ ็ฑปๅž‹ๆ็คบไธ€่ˆฌไธไผšๆ”นๅ˜ๅŽŸๆฅ็š„่ฟ่กŒ็ป“ๆžœใ€‚ +่€Œไธ”ๆทปๅŠ ็ฑปๅž‹ๆ็คบ้€šๅธธไธไผšๆ”นๅ˜ไปฃ็ ๆœฌๆฅ็š„่กŒไธบใ€‚ -็Žฐๅœจๅ‡่ฎพๆˆ‘ไปฌๅˆไธ€ๆฌกๆญฃๅœจๅˆ›ๅปบ่ฟ™ไธชๅ‡ฝๆ•ฐ๏ผŒ่ฟ™ๆฌกๆทปๅŠ ไบ†็ฑปๅž‹ๆ็คบใ€‚ +็Žฐๅœจ๏ผŒๅ†ๆƒณ่ฑกไฝ ๅˆๅœจ็ผ–ๅ†™่ฟ™ไธชๅ‡ฝๆ•ฐไบ†๏ผŒไธ่ฟ‡่ฟ™ๆฌกๅŠ ไธŠไบ†็ฑปๅž‹ๆ็คบใ€‚ -ๅœจๅŒๆ ท็š„ๅœฐๆ–น๏ผŒ้€š่ฟ‡ `Ctrl+Space` ่งฆๅ‘่‡ชๅŠจ่กฅๅ…จ๏ผŒไฝ ไผšๅ‘็Žฐ๏ผš +ๅœจๅŒๆ ท็š„ไฝ็ฝฎ๏ผŒไฝ ็”จ `Ctrl+Space` ่งฆๅ‘่‡ชๅŠจ่กฅๅ…จ๏ผŒๅฐฑ่ƒฝ็œ‹ๅˆฐ๏ผš - + -่ฟ™ๆ ท๏ผŒไฝ ๅฏไปฅๆปšๅŠจๆŸฅ็œ‹้€‰้กน๏ผŒ็›ดๅˆฐไฝ ๆ‰พๅˆฐ็œ‹่ตทๆฅ็œผ็†Ÿ็š„้‚ฃไธช๏ผš +่ฟ™ๆ ท๏ผŒไฝ ๅฏไปฅๆปšๅŠจๆŸฅ็œ‹้€‰้กน๏ผŒ็›ดๅˆฐๆ‰พๅˆฐ้‚ฃไธชโ€œ็œ‹็€็œผ็†Ÿโ€็š„๏ผš - + -## ๆ›ดๅคšๅŠจๆœบ +## ๆ›ดๅคšๅŠจๆœบ { #more-motivation } -ไธ‹้ขๆ˜ฏไธ€ไธชๅทฒ็ปๆœ‰็ฑปๅž‹ๆ็คบ็š„ๅ‡ฝๆ•ฐ๏ผš +็œ‹่ฟ™ไธชๅทฒ็ปๅธฆๆœ‰็ฑปๅž‹ๆ็คบ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/python_types/tutorial003.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +ๅ› ไธบ็ผ–่พ‘ๅ™จ็Ÿฅ้“ๅ˜้‡็š„็ฑปๅž‹๏ผŒไฝ ไธไป…่ƒฝๅพ—ๅˆฐ่กฅๅ…จ๏ผŒ่ฟ˜่ƒฝ่Žทๅพ—้”™่ฏฏๆฃ€ๆŸฅ๏ผš -ๅ› ไธบ็ผ–่พ‘ๅ™จๅทฒ็ป็Ÿฅ้“ไบ†่ฟ™ไบ›ๅ˜้‡็š„็ฑปๅž‹๏ผŒๆ‰€ไปฅไธไป…่ƒฝๅฏนไปฃ็ ่ฟ›่กŒ่กฅๅ…จ๏ผŒ่ฟ˜่ƒฝๆฃ€ๆŸฅๅ…ถไธญ็š„้”™่ฏฏ๏ผš + - +็Žฐๅœจไฝ ็Ÿฅ้“้œ€่ฆไฟฎๅคๅฎƒ๏ผŒ็”จ `str(age)` ๆŠŠ `age` ่ฝฌๆˆๅญ—็ฌฆไธฒ๏ผš -็Žฐๅœจไฝ ็Ÿฅ้“ไบ†ๅฟ…้กปๅ…ˆไฟฎๅค่ฟ™ไธช้—ฎ้ข˜๏ผŒ้€š่ฟ‡ `str(age)` ๆŠŠ `age` ่ฝฌๆขๆˆๅญ—็ฌฆไธฒ๏ผš +{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} -{* ../../docs_src/python_types/tutorial004.py hl[2] *} +## ๅฃฐๆ˜Ž็ฑปๅž‹ { #declaring-types } +ไฝ ๅˆšๅˆš็œ‹ๅˆฐ็š„ๆ˜ฏๅฃฐๆ˜Ž็ฑปๅž‹ๆ็คบ็š„ไธป่ฆไฝ็ฝฎ๏ผšๅ‡ฝๆ•ฐๅ‚ๆ•ฐใ€‚ -## ๅฃฐๆ˜Ž็ฑปๅž‹ +่ฟ™ไนŸๆ˜ฏไฝ ๅœจ **FastAPI** ไธญไฝฟ็”จๅฎƒไปฌ็š„ไธป่ฆๅœบๆ™ฏใ€‚ -ไฝ ๅˆšๅˆš็œ‹ๅˆฐ็š„ๅฐฑๆ˜ฏๅฃฐๆ˜Ž็ฑปๅž‹ๆ็คบ็š„ไธป่ฆๅœบๆ™ฏใ€‚็”จไบŽๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐใ€‚ +### ็ฎ€ๅ•็ฑปๅž‹ { #simple-types } -่ฟ™ไนŸๆ˜ฏไฝ ๅฐ†ๅœจ **FastAPI** ไธญไฝฟ็”จๅฎƒไปฌ็š„ไธป่ฆๅœบๆ™ฏใ€‚ +ไฝ ไธไป…ๅฏไปฅๅฃฐๆ˜Ž `str`๏ผŒ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žๆ‰€ๆœ‰ๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ใ€‚ -### ็ฎ€ๅ•็ฑปๅž‹ - -ไธๅชๆ˜ฏ `str`๏ผŒไฝ ่ƒฝๅคŸๅฃฐๆ˜Žๆ‰€ๆœ‰็š„ๆ ‡ๅ‡† Python ็ฑปๅž‹ใ€‚ - -ๆฏ”ๅฆ‚ไปฅไธ‹็ฑปๅž‹๏ผš +ไพ‹ๅฆ‚๏ผš * `int` * `float` * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} + +### ๅธฆ็ฑปๅž‹ๅ‚ๆ•ฐ็š„ๆณ›ๅž‹็ฑปๅž‹ { #generic-types-with-type-parameters } +ๆœ‰ไบ›ๆ•ฐๆฎ็ป“ๆž„ๅฏไปฅๅŒ…ๅซๅ…ถไป–ๅ€ผ๏ผŒๆฏ”ๅฆ‚ `dict`ใ€`list`ใ€`set` ๅ’Œ `tuple`ใ€‚่€Œๅ†…้ƒจ็š„ๅ€ผไนŸไผšๆœ‰่‡ชๅทฑ็š„็ฑปๅž‹ใ€‚ -### ๅตŒๅฅ—็ฑปๅž‹ +่ฟ™ไบ›ๅธฆๆœ‰ๅ†…้ƒจ็ฑปๅž‹็š„็ฑปๅž‹็งฐไธบโ€œๆณ›ๅž‹โ€๏ผˆgeneric๏ผ‰็ฑปๅž‹ใ€‚ๅฏไปฅๆŠŠๅฎƒไปฌ่ฟžๅŒๅ†…้ƒจ็ฑปๅž‹ไธ€่ตทๅฃฐๆ˜Žๅ‡บๆฅใ€‚ -ๆœ‰ไบ›ๅฎนๅ™จๆ•ฐๆฎ็ป“ๆž„ๅฏไปฅๅŒ…ๅซๅ…ถไป–็š„ๅ€ผ๏ผŒๆฏ”ๅฆ‚ `dict`ใ€`list`ใ€`set` ๅ’Œ `tuple`ใ€‚ๅฎƒไปฌๅ†…้ƒจ็š„ๅ€ผไนŸไผšๆ‹ฅๆœ‰่‡ชๅทฑ็š„็ฑปๅž‹ใ€‚ +่ฆๅฃฐๆ˜Ž่ฟ™ไบ›็ฑปๅž‹ไปฅๅŠๅ†…้ƒจ็ฑปๅž‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Python ๆ ‡ๅ‡†ๅบ“ๆจกๅ— `typing`ใ€‚ๅฎƒๅฐฑๆ˜ฏไธบๆ”ฏๆŒ่ฟ™ไบ›็ฑปๅž‹ๆ็คบ่€Œๅญ˜ๅœจ็š„ใ€‚ -ไฝ ๅฏไปฅไฝฟ็”จ Python ็š„ `typing` ๆ ‡ๅ‡†ๅบ“ๆฅๅฃฐๆ˜Ž่ฟ™ไบ›็ฑปๅž‹ไปฅๅŠๅญ็ฑปๅž‹ใ€‚ +#### ๆ›ดๆ–ฐ็š„ Python ็‰ˆๆœฌ { #newer-versions-of-python } -ๅฎƒไธ“้—จ็”จๆฅๆ”ฏๆŒ่ฟ™ไบ›็ฑปๅž‹ๆ็คบใ€‚ +ไฝฟ็”จ `typing` ็š„่ฏญๆณ•ไธŽๆ‰€ๆœ‰็‰ˆๆœฌๅ…ผๅฎน๏ผŒไปŽ Python 3.6 ๅˆฐๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผˆๅŒ…ๆ‹ฌ Python 3.9ใ€Python 3.10 ็ญ‰๏ผ‰ใ€‚ -#### ๅˆ—่กจ +้š็€ Python ็š„ๅ‘ๅฑ•๏ผŒๆ›ดๆ–ฐ็š„็‰ˆๆœฌๅฏน่ฟ™ไบ›็ฑปๅž‹ๆณจ่งฃ็š„ๆ”ฏๆŒๆ›ดๅฅฝ๏ผŒๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹ไฝ ็”š่‡ณไธ้œ€่ฆๅฏผๅ…ฅๅ’Œไฝฟ็”จ `typing` ๆจกๅ—ๆฅๅฃฐๆ˜Ž็ฑปๅž‹ๆณจ่งฃใ€‚ -ไพ‹ๅฆ‚๏ผŒ่ฎฉๆˆ‘ไปฌๆฅๅฎšไน‰ไธ€ไธช็”ฑ `str` ็ป„ๆˆ็š„ `list` ๅ˜้‡ใ€‚ +ๅฆ‚ๆžœไฝ ๅฏไปฅไธบ้กน็›ฎ้€‰ๆ‹ฉๆ›ด้ซ˜็‰ˆๆœฌ็š„ Python๏ผŒไฝ ๅฐ†่ƒฝไบซๅ—ๅˆฐ่ฟ™็ง้ขๅค–็š„็ฎ€ๅŒ–ใ€‚ -ไปŽ `typing` ๆจกๅ—ๅฏผๅ…ฅ `List`๏ผˆๆณจๆ„ๆ˜ฏๅคงๅ†™็š„ `L`๏ผ‰๏ผš +ๅœจๆ•ดไธชๆ–‡ๆกฃไธญ๏ผŒไผšๆ นๆฎไธๅŒ Python ็‰ˆๆœฌๆไพ›็›ธๅบ”็š„็คบไพ‹๏ผˆๅฝ“ๅญ˜ๅœจๅทฎๅผ‚ๆ—ถ๏ผ‰ใ€‚ -{* ../../docs_src/python_types/tutorial006.py hl[1] *} +ๆฏ”ๅฆ‚โ€œPython 3.6+โ€่กจ็คบๅ…ผๅฎน Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ 3.7ใ€3.8ใ€3.9ใ€3.10 ็ญ‰๏ผ‰ใ€‚่€Œโ€œPython 3.9+โ€่กจ็คบๅ…ผๅฎน Python 3.9 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ 3.10 ็ญ‰๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ๅฏไปฅไฝฟ็”จๆœ€ๆ–ฐ็š„ Python ็‰ˆๆœฌ๏ผŒ่ฏทไฝฟ็”จๆœ€ๆ–ฐ็‰ˆๆœฌ็š„็คบไพ‹๏ผŒๅฎƒไปฌๅฐ†ๆ‹ฅๆœ‰ๆœ€็ฎ€ๆด็š„่ฏญๆณ•๏ผŒไพ‹ๅฆ‚โ€œPython 3.10+โ€ใ€‚ -ๅŒๆ ทไปฅๅ†’ๅท๏ผˆ`:`๏ผ‰ๆฅๅฃฐๆ˜Ž่ฟ™ไธชๅ˜้‡ใ€‚ +#### ๅˆ—่กจ { #list } -่พ“ๅ…ฅ `List` ไฝœไธบ็ฑปๅž‹ใ€‚ +ไพ‹ๅฆ‚๏ผŒๆˆ‘ไปฌๆฅๅฎšไน‰ไธ€ไธช็”ฑ `str` ็ป„ๆˆ็š„ `list` ๅ˜้‡ใ€‚ -็”ฑไบŽๅˆ—่กจๆ˜ฏๅธฆๆœ‰"ๅญ็ฑปๅž‹"็š„็ฑปๅž‹๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๆŠŠๅญ็ฑปๅž‹ๆ”พๅœจๆ–นๆ‹ฌๅทไธญ๏ผš +็”จๅŒๆ ท็š„ๅ†’ๅท๏ผˆ`:`๏ผ‰่ฏญๆณ•ๅฃฐๆ˜Žๅ˜้‡ใ€‚ -{* ../../docs_src/python_types/tutorial006.py hl[4] *} +็ฑปๅž‹ๅ†™ `list`ใ€‚ +ๅ› ไธบ list ๆ˜ฏไธ€็งๅŒ…ๅซๅ†…้ƒจ็ฑปๅž‹็š„็ฑปๅž‹๏ผŒๆŠŠๅ†…้ƒจ็ฑปๅž‹ๅ†™ๅœจๆ–นๆ‹ฌๅท้‡Œ๏ผš -่ฟ™่กจ็คบ๏ผš"ๅ˜้‡ `items` ๆ˜ฏไธ€ไธช `list`๏ผŒๅนถไธ”่ฟ™ไธชๅˆ—่กจ้‡Œ็š„ๆฏไธ€ไธชๅ…ƒ็ด ้ƒฝๆ˜ฏ `str`"ใ€‚ +{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} -่ฟ™ๆ ท๏ผŒๅณไฝฟๅœจๅค„็†ๅˆ—่กจไธญ็š„ๅ…ƒ็ด ๆ—ถ๏ผŒไฝ ็š„็ผ–่พ‘ๅ™จไนŸๅฏไปฅๆไพ›ๆ”ฏๆŒใ€‚ +/// info | ไฟกๆฏ -ๆฒกๆœ‰็ฑปๅž‹๏ผŒๅ‡ ไนŽๆ˜ฏไธๅฏ่ƒฝๅฎž็Žฐไธ‹้ข่ฟ™ๆ ท๏ผš +ๆ–นๆ‹ฌๅทไธญ็š„่ฟ™ไบ›ๅ†…้ƒจ็ฑปๅž‹็งฐไธบโ€œ็ฑปๅž‹ๅ‚ๆ•ฐโ€๏ผˆtype parameters๏ผ‰ใ€‚ - +ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒ`str` ๆ˜ฏไผ ็ป™ `list` ็š„็ฑปๅž‹ๅ‚ๆ•ฐใ€‚ -ๆณจๆ„๏ผŒๅ˜้‡ `item` ๆ˜ฏๅˆ—่กจ `items` ไธญ็š„ๅ…ƒ็ด ไน‹ไธ€ใ€‚ +/// -่€Œไธ”๏ผŒ็ผ–่พ‘ๅ™จไป็„ถ็Ÿฅ้“ๅฎƒๆ˜ฏไธ€ไธช `str`๏ผŒๅนถไธบๆญคๆไพ›ไบ†ๆ”ฏๆŒใ€‚ +่ฟ™่กจ็คบ๏ผšโ€œๅ˜้‡ `items` ๆ˜ฏไธ€ไธช `list`๏ผŒๅนถไธ”ๅˆ—่กจไธญ็š„ๆฏไธ€ไธชๅ…ƒ็ด ้ƒฝๆ˜ฏ `str`โ€ใ€‚ -#### ๅ…ƒ็ป„ๅ’Œ้›†ๅˆ +่ฟ™ๆ ท๏ผŒๅณไฝฟๆ˜ฏๅœจๅค„็†ๅˆ—่กจไธญ็š„ๅ…ƒ็ด ๆ—ถ๏ผŒ็ผ–่พ‘ๅ™จไนŸ่ƒฝ็ป™ไฝ ๆไพ›ๆ”ฏๆŒ๏ผš -ๅฃฐๆ˜Ž `tuple` ๅ’Œ `set` ็š„ๆ–นๆณ•ไนŸๆ˜ฏไธ€ๆ ท็š„๏ผš + -{* ../../docs_src/python_types/tutorial007.py hl[1,4] *} +ๆฒกๆœ‰็ฑปๅž‹็š„่ฏ๏ผŒ่ฟ™ๅ‡ ไนŽๆ˜ฏไธๅฏ่ƒฝๅšๅˆฐ็š„ใ€‚ +ๆณจๆ„๏ผŒๅ˜้‡ `item` ๆ˜ฏๅˆ—่กจ `items` ไธญ็š„ไธ€ไธชๅ…ƒ็ด ใ€‚ -่ฟ™่กจ็คบ๏ผš +ๅณไพฟๅฆ‚ๆญค๏ผŒ็ผ–่พ‘ๅ™จไป็„ถ็Ÿฅ้“ๅฎƒๆ˜ฏ `str`๏ผŒๅนถไธบๆญคๆไพ›ๆ”ฏๆŒใ€‚ + +#### ๅ…ƒ็ป„ๅ’Œ้›†ๅˆ { #tuple-and-set } -* ๅ˜้‡ `items_t` ๆ˜ฏไธ€ไธช `tuple`๏ผŒๅ…ถไธญ็š„ๅ‰ไธคไธชๅ…ƒ็ด ้ƒฝๆ˜ฏ `int` ็ฑปๅž‹, ๆœ€ๅŽไธ€ไธชๅ…ƒ็ด ๆ˜ฏ `str` ็ฑปๅž‹ใ€‚ -* ๅ˜้‡ `items_s` ๆ˜ฏไธ€ไธช `set`๏ผŒๅ…ถไธญ็š„ๆฏไธชๅ…ƒ็ด ้ƒฝๆ˜ฏ `bytes` ็ฑปๅž‹ใ€‚ +ๅฃฐๆ˜Ž `tuple` ๅ’Œ `set` ็š„ๆ–นๅผ็ฑปไผผ๏ผš + +{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} + +่ฟ™่กจ็คบ๏ผš -#### ๅญ—ๅ…ธ +* ๅ˜้‡ `items_t` ๆ˜ฏไธ€ไธชๅซๆœ‰ 3 ไธชๅ…ƒ็ด ็š„ `tuple`๏ผŒๅˆ†ๅˆซๆ˜ฏไธ€ไธช `int`ใ€ๅฆไธ€ไธช `int`๏ผŒไปฅๅŠไธ€ไธช `str`ใ€‚ +* ๅ˜้‡ `items_s` ๆ˜ฏไธ€ไธช `set`๏ผŒๅ…ถไธญๆฏไธชๅ…ƒ็ด ็š„็ฑปๅž‹ๆ˜ฏ `bytes`ใ€‚ -ๅฎšไน‰ `dict` ๆ—ถ๏ผŒ้œ€่ฆไผ ๅ…ฅไธคไธชๅญ็ฑปๅž‹๏ผŒ็”จ้€—ๅท่ฟ›่กŒๅˆ†้š”ใ€‚ +#### ๅญ—ๅ…ธ { #dict } -็ฌฌไธ€ไธชๅญ็ฑปๅž‹ๅฃฐๆ˜Ž `dict` ็š„ๆ‰€ๆœ‰้”ฎใ€‚ +ๅฎšไน‰ `dict` ๆ—ถ๏ผŒ้œ€่ฆไผ ๅ…ฅ 2 ไธช็ฑปๅž‹ๅ‚ๆ•ฐ๏ผŒ็”จ้€—ๅทๅˆ†้š”ใ€‚ -็ฌฌไบŒไธชๅญ็ฑปๅž‹ๅฃฐๆ˜Ž `dict` ็š„ๆ‰€ๆœ‰ๅ€ผ๏ผš +็ฌฌไธ€ไธช็ฑปๅž‹ๅ‚ๆ•ฐ็”จไบŽๅญ—ๅ…ธ็š„้”ฎใ€‚ -{* ../../docs_src/python_types/tutorial008.py hl[1,4] *} +็ฌฌไบŒไธช็ฑปๅž‹ๅ‚ๆ•ฐ็”จไบŽๅญ—ๅ…ธ็š„ๅ€ผ๏ผš +{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} ่ฟ™่กจ็คบ๏ผš * ๅ˜้‡ `prices` ๆ˜ฏไธ€ไธช `dict`๏ผš - * ่ฟ™ไธช `dict` ็š„ๆ‰€ๆœ‰้”ฎไธบ `str` ็ฑปๅž‹๏ผˆๅฏไปฅ็œ‹ไฝœๆ˜ฏๅญ—ๅ…ธๅ†…ๆฏไธชๅ…ƒ็ด ็š„ๅ็งฐ๏ผ‰ใ€‚ - * ่ฟ™ไธช `dict` ็š„ๆ‰€ๆœ‰ๅ€ผไธบ `float` ็ฑปๅž‹๏ผˆๅฏไปฅ็œ‹ไฝœๆ˜ฏๅญ—ๅ…ธๅ†…ๆฏไธชๅ…ƒ็ด ็š„ไปทๆ ผ๏ผ‰ใ€‚ + * ่ฟ™ไธช `dict` ็š„้”ฎๆ˜ฏ `str` ็ฑปๅž‹๏ผˆๆฏ”ๅฆ‚๏ผŒๆฏไธชๆก็›ฎ็š„ๅ็งฐ๏ผ‰ใ€‚ + * ่ฟ™ไธช `dict` ็š„ๅ€ผๆ˜ฏ `float` ็ฑปๅž‹๏ผˆๆฏ”ๅฆ‚๏ผŒๆฏไธชๆก็›ฎ็š„ไปทๆ ผ๏ผ‰ใ€‚ -### ็ฑปไฝœไธบ็ฑปๅž‹ +#### Union { #union } -ไฝ ไนŸๅฏไปฅๅฐ†็ฑปๅฃฐๆ˜Žไธบๅ˜้‡็š„็ฑปๅž‹ใ€‚ +ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ˜้‡ๅฏไปฅๆ˜ฏ่‹ฅๅนฒ็ง็ฑปๅž‹ไธญ็š„ไปปๆ„ไธ€็ง๏ผŒๆฏ”ๅฆ‚ๆ—ขๅฏไปฅๆ˜ฏ `int` ไนŸๅฏไปฅๆ˜ฏ `str`ใ€‚ -ๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๅไธบ `Person` ็š„็ฑป๏ผŒๆ‹ฅๆœ‰ name ๅฑžๆ€ง๏ผš +ๅœจ Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ Python 3.10๏ผ‰๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `typing` ไธญ็š„ `Union`๏ผŒๆŠŠๅฏ่ƒฝ็š„็ฑปๅž‹ๆ”พๅˆฐๆ–นๆ‹ฌๅท้‡Œใ€‚ -{* ../../docs_src/python_types/tutorial010.py hl[1:3] *} +ๅœจ Python 3.10 ไธญ่ฟ˜ๆœ‰ไธ€็งๆ–ฐ็š„่ฏญๆณ•๏ผŒๅฏไปฅ็”จ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๆŠŠๅฏ่ƒฝ็š„็ฑปๅž‹ๅˆ†้š”ๅผ€ใ€‚ +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` -ๆŽฅไธ‹ๆฅ๏ผŒไฝ ๅฏไปฅๅฐ†ไธ€ไธชๅ˜้‡ๅฃฐๆ˜Žไธบ `Person` ็ฑปๅž‹๏ผš +//// -{* ../../docs_src/python_types/tutorial010.py hl[6] *} +//// tab | Python 3.9+ +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008b_py39.py!} +``` -็„ถๅŽ๏ผŒไฝ ๅฐ†ๅ†ๆฌก่Žทๅพ—ๆ‰€ๆœ‰็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผš +//// - +ไธค็งๆ–นๅผ็š„ๅซไน‰ไธ€่‡ด๏ผš`item` ๅฏไปฅๆ˜ฏ `int` ๆˆ– `str`ใ€‚ -## Pydantic ๆจกๅž‹ +#### ๅฏ่ƒฝไธบ `None` { #possibly-none } -Pydantic ๆ˜ฏไธ€ไธช็”จๆฅๆ‰ง่กŒๆ•ฐๆฎๆ ก้ชŒ็š„ Python ๅบ“ใ€‚ +ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ€ผ็š„็ฑปๅž‹ๆ˜ฏๆŸ็ง็ฑปๅž‹๏ผˆๆฏ”ๅฆ‚ `str`๏ผ‰๏ผŒไฝ†ๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`ใ€‚ -ไฝ ๅฏไปฅๅฐ†ๆ•ฐๆฎ็š„"็ป“ๆž„"ๅฃฐๆ˜Žไธบๅ…ทๆœ‰ๅฑžๆ€ง็š„็ฑปใ€‚ +ๅœจ Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ Python 3.10๏ผ‰๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ไปŽ `typing` ๆจกๅ—ๅฏผๅ…ฅๅนถไฝฟ็”จ `Optional` ๆฅๅฃฐๆ˜Ž๏ผš -ๆฏไธชๅฑžๆ€ง้ƒฝๆ‹ฅๆœ‰็ฑปๅž‹ใ€‚ +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009_py39.py!} +``` -ๆŽฅ็€ไฝ ็”จไธ€ไบ›ๅ€ผๆฅๅˆ›ๅปบ่ฟ™ไธช็ฑป็š„ๅฎžไพ‹๏ผŒ่ฟ™ไบ›ๅ€ผไผš่ขซๆ ก้ชŒ๏ผŒๅนถ่ขซ่ฝฌๆขไธบ้€‚ๅฝ“็š„็ฑปๅž‹๏ผˆๅœจ้œ€่ฆ็š„ๆƒ…ๅ†ตไธ‹๏ผ‰๏ผŒ่ฟ”ๅ›žไธ€ไธชๅŒ…ๅซๆ‰€ๆœ‰ๆ•ฐๆฎ็š„ๅฏน่ฑกใ€‚ +ไฝฟ็”จ `Optional[str]` ่€Œไธๆ˜ฏไป…ไป… `str`๏ผŒๅฏไปฅ่ฎฉ็ผ–่พ‘ๅ™จๅธฎๅŠฉไฝ ๅ‘็ŽฐๆŠŠๅ€ผๅฝ“ๆˆๆ€ปๆ˜ฏ `str` ็š„้”™่ฏฏ๏ผˆๅฎž้™…ไธŠๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`๏ผ‰ใ€‚ -็„ถๅŽ๏ผŒไฝ ๅฐ†่Žทๅพ—่ฟ™ไธชๅฏน่ฑก็š„ๆ‰€ๆœ‰็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ +`Optional[Something]` ๅฎž้™…ไธŠๆ˜ฏ `Union[Something, None]` ็š„็ฎ€ๅ†™๏ผŒๅฎƒไปฌ็ญ‰ไปทใ€‚ -ไธ‹้ข็š„ไพ‹ๅญๆฅ่‡ช Pydantic ๅฎ˜ๆ–นๆ–‡ๆกฃ๏ผš +่ฟ™ไนŸๆ„ๅ‘ณ็€ๅœจ Python 3.10 ไธญ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Something | None`๏ผš //// tab | Python 3.10+ -```Python -{!> ../../docs_src/python_types/tutorial011_py310.py!} +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} ``` //// //// tab | Python 3.9+ -```Python -{!> ../../docs_src/python_types/tutorial011_py39.py!} +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009_py39.py!} ``` //// -//// tab | Python 3.8+ +//// tab | Python 3.9+ ๅฆไธ€็งๅ†™ๆณ• + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009b_py39.py!} +``` + +//// + +#### ไฝฟ็”จ `Union` ๆˆ– `Optional` { #using-union-or-optional } + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏ 3.10 ไปฅไธ‹็š„ Python ็‰ˆๆœฌ๏ผŒ่ฟ™้‡Œๆœ‰ไธชๆฅ่‡ชๆˆ‘้žๅธธไธป่ง‚็š„ๅปบ่ฎฎ๏ผš + +* ๐Ÿšจ ้ฟๅ…ไฝฟ็”จ `Optional[SomeType]` +* ๆ”น็”จ โœจ**`Union[SomeType, None]`**โœจ + +ไธค่€…็ญ‰ไปท๏ผŒๅบ•ๅฑ‚็›ธๅŒ๏ผŒไฝ†ๆˆ‘ๆ›ดๆŽจ่ `Union` ่€Œไธๆ˜ฏ `Optional`๏ผŒๅ› ไธบโ€œoptional๏ผˆๅฏ้€‰๏ผ‰โ€่ฟ™ไธช่ฏ็œ‹่ตทๆฅๅƒๆ˜ฏๅœจ่ฏดโ€œๅ‚ๆ•ฐๅฏ้€‰โ€๏ผŒ่€Œๅฎƒๅฎž้™…ไธŠ่กจ็คบโ€œๅฎƒๅฏไปฅๆ˜ฏ `None`โ€๏ผŒๅณไฝฟๅฎƒๅนถไธๆ˜ฏๅฏ้€‰็š„๏ผŒไป็„ถๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ + +ๆˆ‘่ฎคไธบ `Union[SomeType, None]` ๆ›ดๆ˜Ž็กฎๅœฐ่กจ่พพไบ†ๅฎƒ็š„ๆ„ๆ€ใ€‚ + +่ฟ™ๅชๆ˜ฏๅ…ณไบŽ่ฏ่ฏญๅ’Œๅๅญ—ใ€‚ไฝ†่ฟ™ไบ›่ฏไผšๅฝฑๅ“ไฝ ๅ’Œไฝ ็š„้˜Ÿๅ‹ๅฆ‚ไฝ•็†่งฃไปฃ็ ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็œ‹ไธ‹้ข่ฟ™ไธชๅ‡ฝๆ•ฐ๏ผš + +{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} + +ๅ‚ๆ•ฐ `name` ่ขซๅฎšไน‰ไธบ `Optional[str]`๏ผŒไฝ†ๅฎƒๅนถไธๆ˜ฏโ€œๅฏ้€‰โ€็š„๏ผŒไฝ ไธ่ƒฝไธไผ ่ฟ™ไธชๅ‚ๆ•ฐๅฐฑ่ฐƒ็”จๅ‡ฝๆ•ฐ๏ผš ```Python -{!> ../../docs_src/python_types/tutorial011.py!} +say_hi() # ๅ“ฆไธ๏ผŒ่ฟ™ไผšๆŠ›้”™๏ผ๐Ÿ˜ฑ ``` +ๅ‚ๆ•ฐ `name` ไป็„ถๆ˜ฏๅฟ…ๅกซ็š„๏ผˆไธๆ˜ฏโ€œๅฏ้€‰โ€๏ผ‰๏ผŒๅ› ไธบๅฎƒๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ไธ่ฟ‡๏ผŒ`name` ๆŽฅๅ— `None` ไฝœไธบๅ€ผ๏ผš + +```Python +say_hi(name=None) # ่ฟ™ๆ ทๅฏไปฅ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆๅ€ผ ๐ŸŽ‰ +``` + +ๅฅฝๆถˆๆฏๆ˜ฏ๏ผŒไธ€ๆ—ฆไฝ ไฝฟ็”จ Python 3.10๏ผŒๅฐฑๆ— ้œ€ๅ†ไธบๆญคๆ“ๅฟƒ๏ผŒๅ› ไธบไฝ ๅฏไปฅ็›ดๆŽฅ็”จ `|` ๆฅๅฎšไน‰็ฑปๅž‹่”ๅˆ๏ผš + +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} + +่ฟ™ๆ ทไฝ ๅฐฑไธๅฟ…ๅ†่€ƒ่™‘ `Optional` ๅ’Œ `Union` ่ฟ™ไบ›ๅๅญ—ไบ†ใ€‚๐Ÿ˜Ž + +#### ๆณ›ๅž‹็ฑปๅž‹ { #generic-types } + +่ฟ™ไบ›ๅœจๆ–นๆ‹ฌๅทไธญๆŽฅๆ”ถ็ฑปๅž‹ๅ‚ๆ•ฐ็š„็ฑปๅž‹็งฐไธบโ€œๆณ›ๅž‹็ฑปๅž‹โ€๏ผˆGeneric types๏ผ‰ๆˆ–โ€œๆณ›ๅž‹โ€๏ผˆGenerics๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + +//// tab | Python 3.10+ + +ไฝ ๅฏไปฅๆŠŠๅŒๆ ท็š„ๅ†…ๅปบ็ฑปๅž‹ไฝœไธบๆณ›ๅž‹ไฝฟ็”จ๏ผˆๅธฆๆ–นๆ‹ฌๅทๅ’Œๅ†…้ƒจ็ฑปๅž‹๏ผ‰๏ผš + +* `list` +* `tuple` +* `set` +* `dict` + +ไปฅๅŠไธŽไน‹ๅ‰็š„ Python ็‰ˆๆœฌไธ€ๆ ท๏ผŒๆฅ่‡ช `typing` ๆจกๅ—็š„๏ผš + +* `Union` +* `Optional` +* โ€ฆโ€ฆไปฅๅŠๅ…ถไป–ใ€‚ + +ๅœจ Python 3.10 ไธญ๏ผŒไฝœไธบไฝฟ็”จๆณ›ๅž‹ `Union` ๅ’Œ `Optional` ็š„ๆ›ฟไปฃ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๆฅๅฃฐๆ˜Ž็ฑปๅž‹่”ๅˆ๏ผŒ่ฟ™ๆ›ดๅฅฝไนŸๆ›ด็ฎ€ๅ•ใ€‚ + +//// + +//// tab | Python 3.9+ + +ไฝ ๅฏไปฅๆŠŠๅŒๆ ท็š„ๅ†…ๅปบ็ฑปๅž‹ไฝœไธบๆณ›ๅž‹ไฝฟ็”จ๏ผˆๅธฆๆ–นๆ‹ฌๅทๅ’Œๅ†…้ƒจ็ฑปๅž‹๏ผ‰๏ผš + +* `list` +* `tuple` +* `set` +* `dict` + +ไปฅๅŠๆฅ่‡ช `typing` ๆจกๅ—็š„ๆณ›ๅž‹๏ผš + +* `Union` +* `Optional` +* โ€ฆโ€ฆไปฅๅŠๅ…ถไป–ใ€‚ + //// +### ็ฑปไฝœไธบ็ฑปๅž‹ { #classes-as-types } + +ไฝ ไนŸๅฏไปฅๆŠŠ็ฑปๅฃฐๆ˜Žไธบๅ˜้‡็š„็ฑปๅž‹ใ€‚ + +ๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๅไธบ `Person` ็š„็ฑป๏ผŒๅธฆๆœ‰ name๏ผš + +{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} + +็„ถๅŽไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ˜้‡ๆ˜ฏ `Person` ็ฑปๅž‹๏ผš + +{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} + +ๆŽฅ็€๏ผŒไฝ ไผšๅ†ๆฌก่Žทๅพ—ๆ‰€ๆœ‰็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผš + + + +ๆณจๆ„๏ผŒ่ฟ™่กจ็คบโ€œ`one_person` ๆ˜ฏ็ฑป `Person` ็š„ไธ€ไธชๅฎžไพ‹๏ผˆinstance๏ผ‰โ€ใ€‚ + +ๅฎƒๅนถไธ่กจ็คบโ€œ`one_person` ๆ˜ฏๅไธบ `Person` ็š„็ฑปๆœฌ่บซ๏ผˆclass๏ผ‰โ€ใ€‚ + +## Pydantic ๆจกๅž‹ { #pydantic-models } + +Pydantic ๆ˜ฏไธ€ไธช็”จไบŽๆ‰ง่กŒๆ•ฐๆฎๆ ก้ชŒ็š„ Python ๅบ“ใ€‚ + +ไฝ ๅฐ†ๆ•ฐๆฎ็š„โ€œ็ป“ๆž„โ€ๅฃฐๆ˜Žไธบๅธฆๆœ‰ๅฑžๆ€ง็š„็ฑปใ€‚ -/// info +ๆฏไธชๅฑžๆ€ง้ƒฝๆœ‰ไธ€ไธช็ฑปๅž‹ใ€‚ -ๆƒณ่ฟ›ไธ€ๆญฅไบ†่งฃ Pydantic๏ผŒ่ฏท้˜…่ฏปๅ…ถๆ–‡ๆกฃ. +็„ถๅŽไฝ ็”จไธ€ไบ›ๅ€ผๅˆ›ๅปบ่ฟ™ไธช็ฑป็š„ๅฎžไพ‹๏ผŒๅฎƒไผšๆ ก้ชŒ่ฟ™ไบ›ๅ€ผ๏ผŒๅนถๅœจ้œ€่ฆๆ—ถๆŠŠๅฎƒไปฌ่ฝฌๆขไธบๅˆ้€‚็š„็ฑปๅž‹๏ผŒ่ฟ”ๅ›žไธ€ไธชๅŒ…ๅซๆ‰€ๆœ‰ๆ•ฐๆฎ็š„ๅฏน่ฑกใ€‚ + +ไฝ ่ฟ˜่ƒฝๅฏน่ฟ™ไธช็ป“ๆžœๅฏน่ฑก่Žทๅพ—ๅฎŒๆ•ด็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ + +ไธ‹้ขๆ˜ฏๆฅ่‡ช Pydantic ๅฎ˜ๆ–นๆ–‡ๆกฃ็š„ไธ€ไธช็คบไพ‹๏ผš + +{* ../../docs_src/python_types/tutorial011_py310.py *} + +/// info | ไฟกๆฏ + +ๆƒณไบ†่งฃๆ›ดๅคšๅ…ณไบŽ Pydantic ็š„ไฟกๆฏ๏ผŒ่ฏทๆŸฅ็œ‹ๅ…ถๆ–‡ๆกฃใ€‚ + +/// + +**FastAPI** ๅฎŒๅ…จๅปบ็ซ‹ๅœจ Pydantic ไน‹ไธŠใ€‚ + +ไฝ ไผšๅœจ[ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐๆ›ดๅคš็š„ๅฎžๆˆ˜็คบไพ‹ใ€‚ + +/// tip | ๆ็คบ + +ๅฝ“ไฝ ๅœจๆฒกๆœ‰้ป˜่ฎคๅ€ผ็š„ๆƒ…ๅ†ตไธ‹ไฝฟ็”จ `Optional` ๆˆ– `Union[Something, None]` ๆ—ถ๏ผŒPydantic ๆœ‰ไธ€ไธช็‰นๆฎŠ่กŒไธบ๏ผŒไฝ ๅฏไปฅๅœจ Pydantic ๆ–‡ๆกฃ็š„ ๅฟ…ๅกซ็š„ Optional ๅญ—ๆฎต ไธญไบ†่งฃๆ›ดๅคšใ€‚ /// -ๆ•ดไธช **FastAPI** ๅปบ็ซ‹ๅœจ Pydantic ็š„ๅŸบ็ก€ไน‹ไธŠใ€‚ +## ๅธฆๅ…ƒๆ•ฐๆฎๆณจ่งฃ็š„็ฑปๅž‹ๆ็คบ { #type-hints-with-metadata-annotations } + +Python ่ฟ˜ๆไพ›ไบ†ไธ€ไธช็‰นๆ€ง๏ผŒๅฏไปฅไฝฟ็”จ `Annotated` ๅœจ่ฟ™ไบ›็ฑปๅž‹ๆ็คบไธญๆ”พๅ…ฅ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎใ€‚ -ๅฎž้™…ไธŠไฝ ๅฐ†ๅœจ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank} ็œ‹ๅˆฐๅพˆๅคš่ฟ™็งๆƒ…ๅ†ตใ€‚ +ไปŽ Python 3.9 ่ตท๏ผŒ`Annotated` ๆ˜ฏๆ ‡ๅ‡†ๅบ“็š„ไธ€้ƒจๅˆ†๏ผŒๅ› ๆญคๅฏไปฅไปŽ `typing` ๅฏผๅ…ฅใ€‚ + +{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} + +Python ๆœฌ่บซไธไผšๅฏน่ฟ™ไธช `Annotated` ๅšไปปไฝ•ๅค„็†ใ€‚ๅฏนไบŽ็ผ–่พ‘ๅ™จๅ’Œๅ…ถไป–ๅทฅๅ…ท๏ผŒ็ฑปๅž‹ไป็„ถๆ˜ฏ `str`ใ€‚ + +ไฝ†ไฝ ๅฏไปฅๅœจ `Annotated` ไธญไธบ **FastAPI** ๆไพ›้ขๅค–็š„ๅ…ƒๆ•ฐๆฎ๏ผŒๆฅๆ่ฟฐไฝ ๅธŒๆœ›ๅบ”็”จๅฆ‚ไฝ•่กŒไธบใ€‚ + +้‡่ฆ็š„ๆ˜ฏ่ฆ่ฎฐไฝ๏ผšไผ ็ป™ `Annotated` ็š„็ฌฌไธ€ไธช็ฑปๅž‹ๅ‚ๆ•ฐๆ‰ๆ˜ฏๅฎž้™…็ฑปๅž‹ใ€‚ๅ…ถไฝ™็š„ๅชๆ˜ฏ็ป™ๅ…ถไป–ๅทฅๅ…ท็”จ็š„ๅ…ƒๆ•ฐๆฎใ€‚ + +็Žฐๅœจไฝ ๅช้œ€่ฆ็Ÿฅ้“ `Annotated` ็š„ๅญ˜ๅœจ๏ผŒๅนถไธ”ๅฎƒๆ˜ฏๆ ‡ๅ‡† Pythonใ€‚๐Ÿ˜Ž + +็จๅŽไฝ ไผš็œ‹ๅˆฐๅฎƒๆœ‰ๅคšไนˆๅผบๅคงใ€‚ + +/// tip | ๆ็คบ + +่ฟ™ๆ˜ฏๆ ‡ๅ‡† Python๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ไฝ ไป็„ถๅฏไปฅๅœจ็ผ–่พ‘ๅ™จ้‡Œ่Žทๅพ—ๅฐฝๅฏ่ƒฝๅฅฝ็š„ๅผ€ๅ‘ไฝ“้ชŒ๏ผŒๅนถ่ƒฝๅ’Œไฝ ็”จๆฅๅˆ†ๆžใ€้‡ๆž„ไปฃ็ ็š„ๅทฅๅ…ท่‰ฏๅฅฝๅไฝœ็ญ‰ใ€‚โœจ + +ๅŒๆ—ถไฝ ็š„ไปฃ็ ไนŸ่ƒฝไธŽ่ฎธๅคšๅ…ถไป– Python ๅทฅๅ…ทๅ’Œๅบ“้ซ˜ๅบฆๅ…ผๅฎนใ€‚๐Ÿš€ + +/// -## **FastAPI** ไธญ็š„็ฑปๅž‹ๆ็คบ +## **FastAPI** ไธญ็š„็ฑปๅž‹ๆ็คบ { #type-hints-in-fastapi } -**FastAPI** ๅˆฉ็”จ่ฟ™ไบ›็ฑปๅž‹ๆ็คบๆฅๅšไธ‹้ขๅ‡ ไปถไบ‹ใ€‚ +**FastAPI** ๅˆฉ็”จ่ฟ™ไบ›็ฑปๅž‹ๆ็คบๆฅๅฎŒๆˆๅคšไปถไบ‹ๆƒ…ใ€‚ -ไฝฟ็”จ **FastAPI** ๆ—ถ็”จ็ฑปๅž‹ๆ็คบๅฃฐๆ˜Žๅ‚ๆ•ฐๅฏไปฅ่Žทๅพ—๏ผš +ๅœจ **FastAPI** ไธญ๏ผŒ็”จ็ฑปๅž‹ๆ็คบๆฅๅฃฐๆ˜Žๅ‚ๆ•ฐ๏ผŒไฝ ๅฐ†่Žทๅพ—๏ผš -* **็ผ–่พ‘ๅ™จๆ”ฏๆŒ**ใ€‚ -* **็ฑปๅž‹ๆฃ€ๆŸฅ**ใ€‚ +* ็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ +* ็ฑปๅž‹ๆฃ€ๆŸฅใ€‚ -...ๅนถไธ” **FastAPI** ่ฟ˜ไผš็”จ่ฟ™ไบ›็ฑปๅž‹ๅฃฐๆ˜Žๆฅ๏ผš +โ€ฆโ€ฆๅนถไธ” **FastAPI** ไผšไฝฟ็”จ็›ธๅŒ็š„ๅฃฐๆ˜Žๆฅ๏ผš -* **ๅฎšไน‰ๅ‚ๆ•ฐ่ฆๆฑ‚**๏ผšๅฃฐๆ˜Žๅฏน่ฏทๆฑ‚่ทฏๅพ„ๅ‚ๆ•ฐใ€ๆŸฅ่ฏขๅ‚ๆ•ฐใ€่ฏทๆฑ‚ๅคดใ€่ฏทๆฑ‚ไฝ“ใ€ไพ่ต–็ญ‰็š„่ฆๆฑ‚ใ€‚ -* **่ฝฌๆขๆ•ฐๆฎ**๏ผšๅฐ†ๆฅ่‡ช่ฏทๆฑ‚็š„ๆ•ฐๆฎ่ฝฌๆขไธบ้œ€่ฆ็š„็ฑปๅž‹ใ€‚ -* **ๆ ก้ชŒๆ•ฐๆฎ**๏ผš ๅฏนไบŽๆฏไธ€ไธช่ฏทๆฑ‚๏ผš - * ๅฝ“ๆ•ฐๆฎๆ ก้ชŒๅคฑ่ดฅๆ—ถ่‡ชๅŠจ็”Ÿๆˆ**้”™่ฏฏไฟกๆฏ**่ฟ”ๅ›ž็ป™ๅฎขๆˆท็ซฏใ€‚ -* ไฝฟ็”จ OpenAPI **่ฎฐๅฝ•** API๏ผš - * ็„ถๅŽ็”จไบŽ่‡ชๅŠจ็”Ÿๆˆไบคไบ’ๅผๆ–‡ๆกฃ็š„็”จๆˆท็•Œ้ขใ€‚ +* ๅฎšไน‰่ฆๆฑ‚๏ผšไปŽ่ฏทๆฑ‚่ทฏๅพ„ๅ‚ๆ•ฐใ€ๆŸฅ่ฏขๅ‚ๆ•ฐใ€่ฏทๆฑ‚ๅคดใ€่ฏทๆฑ‚ไฝ“ใ€ไพ่ต–็ญ‰ใ€‚ +* ่ฝฌๆขๆ•ฐๆฎ๏ผšๆŠŠ่ฏทๆฑ‚ไธญ็š„ๆ•ฐๆฎ่ฝฌๆขไธบๆ‰€้œ€็ฑปๅž‹ใ€‚ +* ๆ ก้ชŒๆ•ฐๆฎ๏ผšๅฏนไบŽๆฏไธช่ฏทๆฑ‚๏ผš + * ๅฝ“ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถ๏ผŒ่‡ชๅŠจ็”Ÿๆˆ้”™่ฏฏไฟกๆฏ่ฟ”ๅ›ž็ป™ๅฎขๆˆท็ซฏใ€‚ +* ไฝฟ็”จ OpenAPI ่ฎฐๅฝ• API๏ผš + * ็„ถๅŽ็”จไบŽ่‡ชๅŠจ็”Ÿๆˆไบคไบ’ๅผๆ–‡ๆกฃ็•Œ้ขใ€‚ -ๅฌไธŠๅŽปๆœ‰็‚นๆŠฝ่ฑกใ€‚ไธ่ฟ‡ไธ็”จๆ‹…ๅฟƒใ€‚ไฝ ๅฐ†ๅœจ [ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank} ไธญ็œ‹ๅˆฐๆ‰€ๆœ‰็š„ๅฎžๆˆ˜ใ€‚ +่ฟ™ไบ›ๅฌ่ตทๆฅๅฏ่ƒฝๆœ‰็‚นๆŠฝ่ฑกใ€‚ๅˆซๆ‹…ๅฟƒใ€‚ไฝ ไผšๅœจ[ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐๆ‰€ๆœ‰่ฟ™ไบ›็š„ๅฎž้™…ๆ•ˆๆžœใ€‚ -ๆœ€้‡่ฆ็š„ๆ˜ฏ๏ผŒ้€š่ฟ‡ไฝฟ็”จๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹๏ผŒๅช้œ€่ฆๅœจไธ€ไธชๅœฐๆ–นๅฃฐๆ˜Ž๏ผˆ่€Œไธๆ˜ฏๆทปๅŠ ๆ›ดๅคš็š„็ฑปใ€่ฃ…้ฅฐๅ™จ็ญ‰๏ผ‰๏ผŒ**FastAPI** ไผšไธบไฝ ๅฎŒๆˆๅพˆๅคš็š„ๅทฅไฝœใ€‚ +้‡่ฆ็š„ๆ˜ฏ๏ผŒ้€š่ฟ‡ไฝฟ็”จๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹๏ผŒ่€Œไธ”ๅชๅœจไธ€ไธชๅœฐๆ–นๅฃฐๆ˜Ž๏ผˆ่€Œไธๆ˜ฏๆทปๅŠ ๆ›ดๅคš็ฑปใ€่ฃ…้ฅฐๅ™จ็ญ‰๏ผ‰๏ผŒ**FastAPI** ไผšไธบไฝ ๅฎŒๆˆๅคง้‡ๅทฅไฝœใ€‚ -/// info +/// info | ไฟกๆฏ -ๅฆ‚ๆžœไฝ ๅทฒ็ป้˜…่ฏปไบ†ๆ‰€ๆœ‰ๆ•™็จ‹๏ผŒๅ›ž่ฟ‡ๅคดๆฅๆƒณไบ†่งฃๆœ‰ๅ…ณ็ฑปๅž‹็š„ๆ›ดๅคšไฟกๆฏ๏ผŒๆฅ่‡ช `mypy` ็š„"้€ŸๆŸฅ่กจ"ๆ˜ฏไธ้”™็š„่ต„ๆบใ€‚ +ๅฆ‚ๆžœไฝ ๅทฒ็ป่ฏปๅฎŒๆ‰€ๆœ‰ๆ•™็จ‹๏ผŒๅˆๅ›žๆฅๆƒณ่ฟ›ไธ€ๆญฅไบ†่งฃ็ฑปๅž‹๏ผŒไธ€ไธชไธ้”™็š„่ต„ๆบๆ˜ฏ `mypy` ็š„โ€œ้€ŸๆŸฅ่กจโ€ใ€‚ /// diff --git a/docs/zh/docs/tutorial/background-tasks.md b/docs/zh/docs/tutorial/background-tasks.md index b9becd8bff..8398472c37 100644 --- a/docs/zh/docs/tutorial/background-tasks.md +++ b/docs/zh/docs/tutorial/background-tasks.md @@ -1,4 +1,4 @@ -# ๅŽๅฐไปปๅŠก +# ๅŽๅฐไปปๅŠก { #background-tasks } ไฝ ๅฏไปฅๅฎšไน‰ๅœจ่ฟ”ๅ›žๅ“ๅบ”ๅŽ่ฟ่กŒ็š„ๅŽๅฐไปปๅŠกใ€‚ @@ -11,15 +11,15 @@ * ๅค„็†ๆ•ฐๆฎ๏ผš * ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพๆ‚จๆ”ถๅˆฐ็š„ๆ–‡ไปถๅฟ…้กป็ป่ฟ‡ไธ€ไธช็ผ“ๆ…ข็š„่ฟ‡็จ‹๏ผŒๆ‚จๅฏไปฅ่ฟ”ๅ›žไธ€ไธช"Accepted"(HTTP 202)ๅ“ๅบ”ๅนถๅœจๅŽๅฐๅค„็†ๅฎƒใ€‚ -## ไฝฟ็”จ `BackgroundTasks` +## ไฝฟ็”จ `BackgroundTasks` { #using-backgroundtasks } ้ฆ–ๅ…ˆๅฏผๅ…ฅ `BackgroundTasks` ๅนถๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญไฝฟ็”จ็ฑปๅž‹ๅฃฐๆ˜Ž `BackgroundTasks` ๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/background_tasks/tutorial001.py hl[1, 13] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} **FastAPI** ไผšๅˆ›ๅปบไธ€ไธช `BackgroundTasks` ็ฑปๅž‹็š„ๅฏน่ฑกๅนถไฝœไธบ่ฏฅๅ‚ๆ•ฐไผ ๅ…ฅใ€‚ -## ๅˆ›ๅปบไธ€ไธชไปปๅŠกๅ‡ฝๆ•ฐ +## ๅˆ›ๅปบไธ€ไธชไปปๅŠกๅ‡ฝๆ•ฐ { #create-a-task-function } ๅˆ›ๅปบ่ฆไฝœไธบๅŽๅฐไปปๅŠก่ฟ่กŒ็š„ๅ‡ฝๆ•ฐใ€‚ @@ -31,13 +31,13 @@ ็”ฑไบŽๅ†™ๆ“ไฝœไธไฝฟ็”จ `async` ๅ’Œ `await`๏ผŒๆˆ‘ไปฌ็”จๆ™ฎ้€š็š„ `def` ๅฎšไน‰ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} -## ๆทปๅŠ ๅŽๅฐไปปๅŠก +## ๆทปๅŠ ๅŽๅฐไปปๅŠก { #add-the-background-task } ๅœจไฝ ็š„ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ้‡Œ๏ผŒ็”จ `.add_task()` ๆ–นๆณ•ๅฐ†ไปปๅŠกๅ‡ฝๆ•ฐไผ ๅˆฐ *ๅŽๅฐไปปๅŠก* ๅฏน่ฑกไธญ๏ผš -{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} `.add_task()` ๆŽฅๆ”ถไปฅไธ‹ๅ‚ๆ•ฐ๏ผš @@ -45,53 +45,13 @@ * ๅบ”ๆŒ‰้กบๅบไผ ้€’็ป™ไปปๅŠกๅ‡ฝๆ•ฐ็š„ไปปๆ„ๅ‚ๆ•ฐๅบๅˆ—(`email`)ใ€‚ * ๅบ”ไผ ้€’็ป™ไปปๅŠกๅ‡ฝๆ•ฐ็š„ไปปๆ„ๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ(`message="some notification"`)ใ€‚ -## ไพ่ต–ๆณจๅ…ฅ +## ไพ่ต–ๆณจๅ…ฅ { #dependency-injection } ไฝฟ็”จ `BackgroundTasks` ไนŸ้€‚็”จไบŽไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ๏ผŒไฝ ๅฏไปฅๅœจๅคšไธช็บงๅˆซๅฃฐๆ˜Ž `BackgroundTasks` ็ฑปๅž‹็š„ๅ‚ๆ•ฐ๏ผšๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ้‡Œ๏ผŒๅœจไพ่ต–ไธญ(ๅฏไพ่ต–)๏ผŒๅœจๅญไพ่ต–ไธญ๏ผŒ็ญ‰็ญ‰ใ€‚ **FastAPI** ็Ÿฅ้“ๅœจๆฏ็งๆƒ…ๅ†ตไธ‹่ฏฅๅšไป€ไนˆไปฅๅŠๅฆ‚ไฝ•ๅค็”จๅŒไธ€ๅฏน่ฑก๏ผŒๅ› ๆญคๆ‰€ๆœ‰ๅŽๅฐไปปๅŠก่ขซๅˆๅนถๅœจไธ€่ตทๅนถไธ”้šๅŽๅœจๅŽๅฐ่ฟ่กŒ๏ผš -//// tab | Python 3.10+ - -{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13, 15, 22, 25] *} - -//// - -//// tab | Python 3.9+ - -{* ../../docs_src/background_tasks/tutorial002_an_py39.py hl[13, 15, 22, 25] *} - -//// - -//// tab | Python 3.8+ - -{* ../../docs_src/background_tasks/tutorial002_an.py hl[14, 16, 23, 26] *} - -//// - -//// tab | Python 3.10+ ๆฒกAnnotated - -/// tip - -ๅฐฝๅฏ่ƒฝ้€‰ๆ‹ฉไฝฟ็”จ `Annotated` ็š„็‰ˆๆœฌใ€‚ - -/// - -{* ../../docs_src/background_tasks/tutorial002_py310.py hl[11, 13, 20, 23] *} - -//// - -//// tab | Python 3.8+ ๆฒกAnnotated - -/// tip - -ๅฐฝๅฏ่ƒฝ้€‰ๆ‹ฉไฝฟ็”จ `Annotated` ็š„็‰ˆๆœฌใ€‚ - -/// - -{* ../../docs_src/background_tasks/tutorial002.py hl[13, 15, 22, 25] *} - -//// +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} ่ฏฅ็คบไพ‹ไธญ๏ผŒไฟกๆฏไผšๅœจๅ“ๅบ”ๅ‘ๅ‡บ *ไน‹ๅŽ* ่ขซๅ†™ๅˆฐ `log.txt` ๆ–‡ไปถใ€‚ @@ -99,7 +59,7 @@ ็„ถๅŽๅฆไธ€ไธชๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็”Ÿๆˆ็š„ๅŽๅฐไปปๅŠกไผšไฝฟ็”จ่ทฏๅพ„ๅ‚ๆ•ฐ `email` ๅ†™ๅ…ฅไธ€ๆกไฟกๆฏใ€‚ -## ๆŠ€ๆœฏ็ป†่Š‚ +## ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details } `BackgroundTasks` ็ฑป็›ดๆŽฅๆฅ่‡ช `starlette.background`ใ€‚ @@ -111,7 +71,7 @@ ๆ›ดๅคš็ป†่Š‚ๆŸฅ็œ‹ Starlette's official docs for Background Tasks. -## ๅ‘Š่ฏซ +## ๅ‘Š่ฏซ { #caveat } ๅฆ‚ๆžœๆ‚จ้œ€่ฆๆ‰ง่กŒ็น้‡็š„ๅŽๅฐ่ฎก็ฎ—๏ผŒๅนถไธ”ไธไธ€ๅฎš้œ€่ฆ็”ฑๅŒไธ€่ฟ›็จ‹่ฟ่กŒ๏ผˆไพ‹ๅฆ‚๏ผŒๆ‚จไธ้œ€่ฆๅ…ฑไบซๅ†…ๅญ˜ใ€ๅ˜้‡็ญ‰๏ผ‰๏ผŒ้‚ฃไนˆไฝฟ็”จๅ…ถไป–ๆ›ดๅคง็š„ๅทฅๅ…ท๏ผˆๅฆ‚ Celery๏ผ‰ๅฏ่ƒฝๆ›ดๅฅฝใ€‚ @@ -119,6 +79,6 @@ ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœๆ‚จ้œ€่ฆไปŽๅŒไธ€ไธช**FastAPI**ๅบ”็”จ็จ‹ๅบ่ฎฟ้—ฎๅ˜้‡ๅ’Œๅฏน่ฑก๏ผŒๆˆ–่€…ๆ‚จ้œ€่ฆๆ‰ง่กŒๅฐๅž‹ๅŽๅฐไปปๅŠก๏ผˆๅฆ‚ๅ‘้€็”ตๅญ้‚ฎไปถ้€š็Ÿฅ๏ผ‰๏ผŒๆ‚จๅช้œ€ไฝฟ็”จ `BackgroundTasks` ๅณๅฏใ€‚ -## ๅ›ž้กพ +## ๅ›ž้กพ { #recap } ๅฏผๅ…ฅๅนถไฝฟ็”จ `BackgroundTasks` ้€š่ฟ‡ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญ็š„ๅ‚ๆ•ฐๅ’Œไพ่ต–้กนๆฅๆทปๅŠ ๅŽๅฐไปปๅŠกใ€‚ diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index 554bc654f0..1ced002dc3 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -1,16 +1,16 @@ -# ๆ›ดๅคง็š„ๅบ”็”จ - ๅคšไธชๆ–‡ไปถ +# ๆ›ดๅคง็š„ๅบ”็”จ - ๅคšไธชๆ–‡ไปถ { #bigger-applications-multiple-files } ๅฆ‚ๆžœไฝ ๆญฃๅœจๅผ€ๅ‘ไธ€ไธชๅบ”็”จ็จ‹ๅบๆˆ– Web API๏ผŒๅพˆๅฐ‘ไผšๅฐ†ๆ‰€ๆœ‰็š„ๅ†…ๅฎน้ƒฝๆ”พๅœจไธ€ไธชๆ–‡ไปถไธญใ€‚ **FastAPI** ๆไพ›ไบ†ไธ€ไธชๆ–นไพฟ็š„ๅทฅๅ…ท๏ผŒๅฏไปฅๅœจไฟๆŒๆ‰€ๆœ‰็ตๆดปๆ€ง็š„ๅŒๆ—ถๆž„ๅปบไฝ ็š„ๅบ”็”จ็จ‹ๅบใ€‚ -/// info +/// info | ไฟกๆฏ ๅฆ‚ๆžœไฝ ๆฅ่‡ช Flask๏ผŒ้‚ฃ่ฟ™ๅฐ†็›ธๅฝ“ไบŽ Flask ็š„ Blueprintsใ€‚ /// -## ไธ€ไธชๆ–‡ไปถ็ป“ๆž„็คบไพ‹ +## ไธ€ไธชๆ–‡ไปถ็ป“ๆž„็คบไพ‹ { #an-example-file-structure } ๅ‡่ฎพไฝ ็š„ๆ–‡ไปถ็ป“ๆž„ๅฆ‚ไธ‹๏ผš @@ -29,7 +29,7 @@ โ”‚ย ย  โ””โ”€โ”€ admin.py ``` -/// tip +/// tip | ๆ็คบ ไธŠ้ขๆœ‰ๅ‡ ไธช `__init__.py` ๆ–‡ไปถ๏ผšๆฏไธช็›ฎๅฝ•ๆˆ–ๅญ็›ฎๅฝ•ไธญ้ƒฝๆœ‰ไธ€ไธชใ€‚ @@ -52,11 +52,11 @@ from app.routers import items * ่ฟ˜ๆœ‰ไธ€ไธชๅญ็›ฎๅฝ• `app/internal/` ๅŒ…ๅซๅฆไธ€ไธช `__init__.py` ๆ–‡ไปถ๏ผŒๅ› ๆญคๅฎƒๆ˜ฏๅˆไธ€ไธชใ€ŒPython ๅญๅŒ…ใ€๏ผš`app.internal`ใ€‚ * `app/internal/admin.py` ๆ˜ฏๅฆไธ€ไธชๅญๆจกๅ—๏ผš`app.internal.admin`ใ€‚ - + ๅธฆๆœ‰ๆณจ้‡Š็š„ๅŒไธ€ๆ–‡ไปถ็ป“ๆž„๏ผš -``` +```bash . โ”œโ”€โ”€ app # ใ€Œappใ€ๆ˜ฏไธ€ไธช Python ๅŒ… โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ่ฟ™ไธชๆ–‡ไปถไฝฟใ€Œappใ€ๆˆไธบไธ€ไธช Python ๅŒ… @@ -71,7 +71,7 @@ from app.routers import items โ”‚ย ย  โ””โ”€โ”€ admin.py # ใ€Œadminใ€ๅญๆจกๅ—๏ผŒไพ‹ๅฆ‚ import app.internal.admin ``` -## `APIRouter` +## `APIRouter` { #apirouter } ๅ‡่ฎพไธ“้—จ็”จไบŽๅค„็†็”จๆˆท้€ป่พ‘็š„ๆ–‡ไปถๆ˜ฏไฝไบŽ `/app/routers/users.py` ็š„ๅญๆจกๅ—ใ€‚ @@ -81,23 +81,19 @@ from app.routers import items ไฝ ๅฏไปฅไฝฟ็”จ `APIRouter` ไธบ่ฏฅๆจกๅ—ๅˆ›ๅปบ*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ -### ๅฏผๅ…ฅ `APIRouter` +### ๅฏผๅ…ฅ `APIRouter` { #import-apirouter } ไฝ ๅฏไปฅๅฏผๅ…ฅๅฎƒๅนถ้€š่ฟ‡ไธŽ `FastAPI` ็ฑป็›ธๅŒ็š„ๆ–นๅผๅˆ›ๅปบไธ€ไธชใ€Œๅฎžไพ‹ใ€๏ผš -```Python hl_lines="1 3" title="app/routers/users.py" -{!../../docs_src/bigger_applications/app/routers/users.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} -### ไฝฟ็”จ `APIRouter` ็š„*่ทฏๅพ„ๆ“ไฝœ* +### ไฝฟ็”จ `APIRouter` ็š„*่ทฏๅพ„ๆ“ไฝœ* { #path-operations-with-apirouter } ็„ถๅŽไฝ ๅฏไปฅไฝฟ็”จๅฎƒๆฅๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ ไฝฟ็”จๆ–นๅผไธŽ `FastAPI` ็ฑป็›ธๅŒ๏ผš -```Python hl_lines="6 11 16" title="app/routers/users.py" -{!../../docs_src/bigger_applications/app/routers/users.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} ไฝ ๅฏไปฅๅฐ† `APIRouter` ่ง†ไธบไธ€ไธชใ€Œ่ฟทไฝ  `FastAPI`ใ€็ฑปใ€‚ @@ -105,7 +101,7 @@ from app.routers import items ๆ‰€ๆœ‰็›ธๅŒ็š„ `parameters`ใ€`responses`ใ€`dependencies`ใ€`tags` ็ญ‰็ญ‰ใ€‚ -/// tip +/// tip | ๆ็คบ ๅœจๆญค็คบไพ‹ไธญ๏ผŒ่ฏฅๅ˜้‡่ขซๅ‘ฝๅไธบ `router`๏ผŒไฝ†ไฝ ๅฏไปฅๆ นๆฎไฝ ็š„ๆƒณๆณ•่‡ช็”ฑๅ‘ฝๅใ€‚ @@ -113,7 +109,7 @@ from app.routers import items ๆˆ‘ไปฌๅฐ†ๅœจไธป `FastAPI` ๅบ”็”จไธญๅŒ…ๅซ่ฏฅ `APIRouter`๏ผŒไฝ†้ฆ–ๅ…ˆ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅ็œ‹็œ‹ไพ่ต–้กนๅ’Œๅฆไธ€ไธช `APIRouter`ใ€‚ -## ไพ่ต–้กน +## ไพ่ต–้กน { #dependencies } ๆˆ‘ไปฌไบ†่งฃๅˆฐๆˆ‘ไปฌๅฐ†้œ€่ฆไธ€ไบ›ๅœจๅบ”็”จ็จ‹ๅบ็š„ๅฅฝๅ‡ ไธชๅœฐๆ–นๆ‰€ไฝฟ็”จ็š„ไพ่ต–้กนใ€‚ @@ -121,11 +117,9 @@ from app.routers import items ็Žฐๅœจๆˆ‘ไปฌๅฐ†ไฝฟ็”จไธ€ไธช็ฎ€ๅ•็š„ไพ่ต–้กนๆฅ่ฏปๅ–ไธ€ไธช่‡ชๅฎšไน‰็š„ `X-Token` ่ฏทๆฑ‚้ฆ–้ƒจ๏ผš -```Python hl_lines="1 4-6" title="app/dependencies.py" -{!../../docs_src/bigger_applications/app/dependencies.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} -/// tip +/// tip | ๆ็คบ ๆˆ‘ไปฌๆญฃๅœจไฝฟ็”จ่™šๆž„็š„่ฏทๆฑ‚้ฆ–้ƒจๆฅ็ฎ€ๅŒ–ๆญค็คบไพ‹ใ€‚ @@ -133,7 +127,7 @@ from app.routers import items /// -## ๅ…ถไป–ไฝฟ็”จ `APIRouter` ็š„ๆจกๅ— +## ๅ…ถไป–ไฝฟ็”จ `APIRouter` ็š„ๆจกๅ— { #another-module-with-apirouter } ๅ‡่ฎพไฝ ๅœจไฝไบŽ `app/routers/items.py` ็š„ๆจกๅ—ไธญ่ฟ˜ๆœ‰ไธ“้—จ็”จไบŽๅค„็†ๅบ”็”จ็จ‹ๅบไธญใ€Œ้กน็›ฎใ€็š„็ซฏ็‚นใ€‚ @@ -155,9 +149,7 @@ from app.routers import items ๅ› ๆญค๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ†ๅ…ถๆทปๅŠ ๅˆฐ `APIRouter` ไธญ๏ผŒ่€Œไธๆ˜ฏๅฐ†ๅ…ถๆทปๅŠ ๅˆฐๆฏไธช่ทฏๅพ„ๆ“ไฝœไธญใ€‚ -```Python hl_lines="5-10 16 21" title="app/routers/items.py" -{!../../docs_src/bigger_applications/app/routers/items.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} ็”ฑไบŽๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„่ทฏๅพ„้ƒฝๅฟ…้กปไปฅ `/` ๅผ€ๅคด๏ผŒไพ‹ๅฆ‚๏ผš @@ -175,7 +167,7 @@ async def read_item(item_id: str): ๆˆ‘ไปฌๅฏไปฅๆทปๅŠ ไธ€ไธช `dependencies` ๅˆ—่กจ๏ผŒ่ฟ™ไบ›ไพ่ต–้กนๅฐ†่ขซๆทปๅŠ ๅˆฐ่ทฏ็”ฑๅ™จไธญ็š„ๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ไธญ๏ผŒๅนถๅฐ†้’ˆๅฏนๅ‘ๅฎƒไปฌๅ‘่ตท็š„ๆฏไธช่ฏทๆฑ‚ๆ‰ง่กŒ/่งฃๅ†ณใ€‚ -/// tip +/// tip | ๆ็คบ ่ฏทๆณจๆ„๏ผŒๅ’Œ[*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญ็š„ไพ่ต–้กน](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}ๅพˆ็ฑปไผผ๏ผŒๆฒกๆœ‰ๅ€ผไผš่ขซไผ ้€’็ป™ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ @@ -196,19 +188,19 @@ async def read_item(item_id: str): * ่ทฏ็”ฑๅ™จ็š„ไพ่ต–้กนๆœ€ๅ…ˆๆ‰ง่กŒ๏ผŒ็„ถๅŽๆ˜ฏ[่ฃ…้ฅฐๅ™จไธญ็š„ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}๏ผŒๅ†็„ถๅŽๆ˜ฏๆ™ฎ้€š็š„ๅ‚ๆ•ฐไพ่ต–้กนใ€‚ * ไฝ ่ฟ˜ๅฏไปฅๆทปๅŠ [ๅ…ทๆœ‰ `scopes` ็š„ `Security` ไพ่ต–้กน](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}ใ€‚ -/// tip +/// tip | ๆ็คบ ๅœจ `APIRouter`ไธญๅ…ทๆœ‰ `dependencies` ๅฏไปฅ็”จๆฅ๏ผŒไพ‹ๅฆ‚๏ผŒๅฏนไธ€ๆ•ด็ป„็š„*่ทฏๅพ„ๆ“ไฝœ*่ฆๆฑ‚่บซไปฝ่ฎค่ฏใ€‚ๅณไฝฟ่ฟ™ไบ›ไพ่ต–้กนๅนถๆฒกๆœ‰ๅˆ†ๅˆซๆทปๅŠ ๅˆฐๆฏไธช่ทฏๅพ„ๆ“ไฝœไธญใ€‚ /// -/// check +/// check | ๆฃ€ๆŸฅ `prefix`ใ€`tags`ใ€`responses` ไปฅๅŠ `dependencies` ๅ‚ๆ•ฐๅชๆ˜ฏ๏ผˆๅ’Œๅ…ถไป–ๅพˆๅคšๆƒ…ๅ†ตไธ€ๆ ท๏ผ‰**FastAPI** ็š„ไธ€ไธช็”จไบŽๅธฎๅŠฉไฝ ้ฟๅ…ไปฃ็ ้‡ๅค็š„ๅŠŸ่ƒฝใ€‚ /// -### ๅฏผๅ…ฅไพ่ต–้กน +### ๅฏผๅ…ฅไพ่ต–้กน { #import-the-dependencies } ่ฟ™ไบ›ไปฃ็ ไฝไบŽ `app.routers.items` ๆจกๅ—๏ผŒ`app/routers/items.py` ๆ–‡ไปถไธญใ€‚ @@ -216,13 +208,11 @@ async def read_item(item_id: str): ๅ› ๆญค๏ผŒๆˆ‘ไปฌ้€š่ฟ‡ `..` ๅฏนไพ่ต–้กนไฝฟ็”จไบ†็›ธๅฏนๅฏผๅ…ฅ๏ผš -```Python hl_lines="3" title="app/routers/items.py" -{!../../docs_src/bigger_applications/app/routers/items.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} -#### ็›ธๅฏนๅฏผๅ…ฅๅฆ‚ไฝ•ๅทฅไฝœ +#### ็›ธๅฏนๅฏผๅ…ฅๅฆ‚ไฝ•ๅทฅไฝœ { #how-relative-imports-work } -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœไฝ ๅฎŒๅ…จไบ†่งฃๅฏผๅ…ฅ็š„ๅทฅไฝœๅŽŸ็†๏ผŒ่ฏทไปŽไธ‹้ข็š„ไธ‹ไธ€้ƒจๅˆ†็ปง็ปญใ€‚ @@ -244,7 +234,7 @@ from .dependencies import get_token_header ่ฏท่ฎฐไฝๆˆ‘ไปฌ็š„็จ‹ๅบ/ๆ–‡ไปถ็ป“ๆž„ๆ˜ฏๆ€Žๆ ท็š„๏ผš - + --- @@ -276,24 +266,22 @@ from ...dependencies import get_token_header * ไปŽ่ฏฅๆจกๅ—๏ผˆ`app/routers/items.py` ๆ–‡ไปถ๏ผ‰ๆ‰€ๅœจ็š„ๅŒไธ€ไธชๅŒ…๏ผˆ`app/routers/` ็›ฎๅฝ•๏ผ‰ๅผ€ๅง‹... * ่ทณ่ฝฌๅˆฐๅ…ถ็ˆถๅŒ…๏ผˆ`app/` ็›ฎๅฝ•๏ผ‰... * ็„ถๅŽ่ทณ่ฝฌๅˆฐ่ฏฅๅŒ…็š„็ˆถๅŒ…๏ผˆ่ฏฅ็ˆถๅŒ…ๅนถไธๅญ˜ๅœจ๏ผŒ`app` ๅทฒ็ปๆ˜ฏๆœ€้กถๅฑ‚็š„ๅŒ… ๐Ÿ˜ฑ๏ผ‰... -* ๅœจ่ฏฅ็ˆถๅŒ…ไธญ๏ผŒๆ‰พๅˆฐ `dependencies` ๆจกๅ—๏ผˆไฝไบŽ `app/` ๆ›ดไธŠไธ€็บง็›ฎๅฝ•ไธญ็š„ `dependencies.py` ๆ–‡ไปถ๏ผ‰... +* ๅœจ่ฏฅ็ˆถๅŒ…ไธญ๏ผŒๆ‰พๅˆฐ `dependencies` ๆจกๅ—๏ผˆไฝไบŽ `app/dependencies.py` ็š„ๆ–‡ไปถ๏ผ‰... * ็„ถๅŽไปŽไธญๅฏผๅ…ฅๅ‡ฝๆ•ฐ `get_token_header`ใ€‚ ่ฟ™ๅฐ†ๅผ•็”จ `app/` ็š„ๅพ€ไธŠไธ€็บง๏ผŒๅธฆๆœ‰ๅ…ถ่‡ชๅทฑ็š„ `__init __.py` ็ญ‰ๆ–‡ไปถ็š„ๆŸไธชๅŒ…ใ€‚ไฝ†ๆ˜ฏๆˆ‘ไปฌๅนถๆฒกๆœ‰่ฟ™ไธชๅŒ…ใ€‚ๅ› ๆญค๏ผŒ่ฟ™ๅฐ†ๅœจๆˆ‘ไปฌ็š„็คบไพ‹ไธญๅผ•ๅ‘้”™่ฏฏใ€‚๐Ÿšจ ไฝ†ๆ˜ฏ็Žฐๅœจไฝ ็Ÿฅ้“ไบ†ๅฎƒ็š„ๅทฅไฝœๅŽŸ็†๏ผŒๅ› ๆญคๆ— ่ฎบๅฎƒไปฌๅคšไนˆๅคๆ‚๏ผŒไฝ ้ƒฝๅฏไปฅๅœจ่‡ชๅทฑ็š„ๅบ”็”จ็จ‹ๅบไธญไฝฟ็”จ็›ธๅฏนๅฏผๅ…ฅใ€‚๐Ÿค“ -### ๆทปๅŠ ไธ€ไบ›่‡ชๅฎšไน‰็š„ `tags`ใ€`responses` ๅ’Œ `dependencies` +### ๆทปๅŠ ไธ€ไบ›่‡ชๅฎšไน‰็š„ `tags`ใ€`responses` ๅ’Œ `dependencies` { #add-some-custom-tags-responses-and-dependencies } ๆˆ‘ไปฌไธๆ‰“็ฎ—ๅœจๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ไธญๆทปๅŠ ๅ‰็ผ€ `/items` ๆˆ– `tags =["items"]`๏ผŒๅ› ไธบๆˆ‘ไปฌๅฐ†ๅฎƒไปฌๆทปๅŠ ๅˆฐไบ† `APIRouter` ไธญใ€‚ ไฝ†ๆ˜ฏๆˆ‘ไปฌไป็„ถๅฏไปฅๆทปๅŠ *ๆ›ดๅคš*ๅฐ†ไผšๅบ”็”จไบŽ็‰นๅฎš็š„*่ทฏๅพ„ๆ“ไฝœ*็š„ `tags`๏ผŒไปฅๅŠไธ€ไบ›็‰นๅฎšไบŽ่ฏฅ*่ทฏๅพ„ๆ“ไฝœ*็š„้ขๅค– `responses`๏ผš -```Python hl_lines="30-31" title="app/routers/items.py" -{!../../docs_src/bigger_applications/app/routers/items.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} -/// tip +/// tip | ๆ็คบ ๆœ€ๅŽ็š„่ฟ™ไธช่ทฏๅพ„ๆ“ไฝœๅฐ†ๅŒ…ๅซๆ ‡็ญพ็š„็ป„ๅˆ๏ผš`["items"๏ผŒ"custom"]`ใ€‚ @@ -301,7 +289,7 @@ from ...dependencies import get_token_header /// -## `FastAPI` ไธปไฝ“ +## `FastAPI` ไธปไฝ“ { #the-main-fastapi } ็Žฐๅœจ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅ็œ‹็œ‹ไฝไบŽ `app/main.py` ็š„ๆจกๅ—ใ€‚ @@ -311,27 +299,23 @@ from ...dependencies import get_token_header ๅนถไธ”็”ฑไบŽไฝ ็š„ๅคง้ƒจๅˆ†้€ป่พ‘็Žฐๅœจ้ƒฝๅญ˜ๅœจไบŽๅ…ถ่‡ชๅทฑ็š„็‰นๅฎšๆจกๅ—ไธญ๏ผŒๅ› ๆญคไธปๆ–‡ไปถ็š„ๅ†…ๅฎนๅฐ†้žๅธธ็ฎ€ๅ•ใ€‚ -### ๅฏผๅ…ฅ `FastAPI` +### ๅฏผๅ…ฅ `FastAPI` { #import-fastapi } ไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ทๅฏผๅ…ฅๅนถๅˆ›ๅปบไธ€ไธช `FastAPI` ็ฑปใ€‚ ๆˆ‘ไปฌ็”š่‡ณๅฏไปฅๅฃฐๆ˜Ž[ๅ…จๅฑ€ไพ่ต–้กน](dependencies/global-dependencies.md){.internal-link target=_blank}๏ผŒๅฎƒไผšๅ’Œๆฏไธช `APIRouter` ็š„ไพ่ต–้กน็ป„ๅˆๅœจไธ€่ตท๏ผš -```Python hl_lines="1 3 7" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} -### ๅฏผๅ…ฅ `APIRouter` +### ๅฏผๅ…ฅ `APIRouter` { #import-the-apirouter } ็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅฏผๅ…ฅๅ…ทๆœ‰ `APIRouter` ็š„ๅ…ถไป–ๅญๆจกๅ—๏ผš -```Python hl_lines="5" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} ็”ฑไบŽๆ–‡ไปถ `app/routers/users.py` ๅ’Œ `app/routers/items.py` ๆ˜ฏๅŒไธ€ Python ๅŒ… `app` ไธ€ไธช้ƒจๅˆ†็š„ๅญๆจกๅ—๏ผŒๅ› ๆญคๆˆ‘ไปฌๅฏไปฅไฝฟ็”จๅ•ไธช็‚น ` .` ้€š่ฟ‡ใ€Œ็›ธๅฏนๅฏผๅ…ฅใ€ๆฅๅฏผๅ…ฅๅฎƒไปฌใ€‚ -### ๅฏผๅ…ฅๆ˜ฏๅฆ‚ไฝ•ๅทฅไฝœ็š„ +### ๅฏผๅ…ฅๆ˜ฏๅฆ‚ไฝ•ๅทฅไฝœ็š„ { #how-the-importing-works } ่ฟ™ๆฎตไปฃ็ ๏ผš @@ -355,7 +339,7 @@ from .routers import items, users from app.routers import items, users ``` -/// info +/// info | ไฟกๆฏ ็ฌฌไธ€ไธช็‰ˆๆœฌๆ˜ฏใ€Œ็›ธๅฏนๅฏผๅ…ฅใ€๏ผš @@ -373,7 +357,7 @@ from app.routers import items, users /// -### ้ฟๅ…ๅ็งฐๅ†ฒ็ช +### ้ฟๅ…ๅ็งฐๅ†ฒ็ช { #avoid-name-collisions } ๆˆ‘ไปฌๅฐ†็›ดๆŽฅๅฏผๅ…ฅ `items` ๅญๆจกๅ—๏ผŒ่€Œไธๆ˜ฏไป…ๅฏผๅ…ฅๅ…ถ `router` ๅ˜้‡ใ€‚ @@ -390,19 +374,15 @@ from .routers.users import router ๅ› ๆญค๏ผŒไธบไบ†่ƒฝๅคŸๅœจๅŒไธ€ไธชๆ–‡ไปถไธญไฝฟ็”จๅฎƒไปฌ๏ผŒๆˆ‘ไปฌ็›ดๆŽฅๅฏผๅ…ฅๅญๆจกๅ—๏ผš -```Python hl_lines="5" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} -### ๅŒ…ๅซ `users` ๅ’Œ `items` ็š„ `APIRouter` +### ๅŒ…ๅซ `users` ๅ’Œ `items` ็š„ `APIRouter` { #include-the-apirouters-for-users-and-items } ็Žฐๅœจ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅๅŒ…ๅซๆฅ่‡ช `users` ๅ’Œ `items` ๅญๆจกๅ—็š„ `router`ใ€‚ -```Python hl_lines="10-11" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} -/// info +/// info | ไฟกๆฏ `users.router` ๅŒ…ๅซไบ† `app/routers/users.py` ๆ–‡ไปถไธญ็š„ `APIRouter`ใ€‚ @@ -422,7 +402,7 @@ from .routers.users import router /// -/// check +/// check | ๆฃ€ๆŸฅ ๅŒ…ๅซ่ทฏ็”ฑๅ™จๆ—ถ๏ผŒไฝ ไธๅฟ…ๆ‹…ๅฟƒๆ€ง่ƒฝ้—ฎ้ข˜ใ€‚ @@ -432,7 +412,7 @@ from .routers.users import router /// -### ๅŒ…ๅซไธ€ไธชๆœ‰่‡ชๅฎšไน‰ `prefix`ใ€`tags`ใ€`responses` ๅ’Œ `dependencies` ็š„ `APIRouter` +### ๅŒ…ๅซไธ€ไธชๆœ‰่‡ชๅฎšไน‰ `prefix`ใ€`tags`ใ€`responses` ๅ’Œ `dependencies` ็š„ `APIRouter` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } ็Žฐๅœจ๏ผŒๅ‡่ฎพไฝ ็š„็ป„็ป‡ไธบไฝ ๆไพ›ไบ† `app/internal/admin.py` ๆ–‡ไปถใ€‚ @@ -440,17 +420,13 @@ from .routers.users import router ๅฏนไบŽๆญค็คบไพ‹๏ผŒๅฎƒๅฐ†้žๅธธ็ฎ€ๅ•ใ€‚ไฝ†ๆ˜ฏๅ‡่ฎพ็”ฑไบŽๅฎƒๆ˜ฏไธŽ็ป„็ป‡ไธญ็š„ๅ…ถไป–้กน็›ฎๆ‰€ๅ…ฑไบซ็š„๏ผŒๅ› ๆญคๆˆ‘ไปฌๆ— ๆณ•ๅฏนๅ…ถ่ฟ›่กŒไฟฎๆ”น๏ผŒไปฅๅŠ็›ดๆŽฅๅœจ `APIRouter` ไธญๆทปๅŠ  `prefix`ใ€`dependencies`ใ€`tags` ็ญ‰๏ผš -```Python hl_lines="3" title="app/internal/admin.py" -{!../../docs_src/bigger_applications/app/internal/admin.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} ไฝ†ๆ˜ฏๆˆ‘ไปฌไป็„ถๅธŒๆœ›ๅœจๅŒ…ๅซ `APIRouter` ๆ—ถ่ฎพ็ฝฎไธ€ไธช่‡ชๅฎšไน‰็š„ `prefix`๏ผŒไปฅไพฟๅ…ถๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ไปฅ `/admin` ๅผ€ๅคด๏ผŒๆˆ‘ไปฌๅธŒๆœ›ไฝฟ็”จๆœฌ้กน็›ฎๅทฒ็ปๆœ‰็š„ `dependencies` ไฟๆŠคๅฎƒ๏ผŒๅนถไธ”ๆˆ‘ไปฌๅธŒๆœ›ๅฎƒๅŒ…ๅซ่‡ชๅฎšไน‰็š„ `tags` ๅ’Œ `responses`ใ€‚ ๆˆ‘ไปฌๅฏไปฅ้€š่ฟ‡ๅฐ†่ฟ™ไบ›ๅ‚ๆ•ฐไผ ้€’็ป™ `app.include_router()` ๆฅๅฎŒๆˆๆ‰€ๆœ‰็š„ๅฃฐๆ˜Ž๏ผŒ่€Œไธๅฟ…ไฟฎๆ”นๅŽŸๅง‹็š„ `APIRouter`๏ผš -```Python hl_lines="14-17" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} ่ฟ™ๆ ท๏ผŒๅŽŸๅง‹็š„ `APIRouter` ๅฐ†ไฟๆŒไธๅ˜๏ผŒๅ› ๆญคๆˆ‘ไปฌไป็„ถๅฏไปฅไธŽ็ป„็ป‡ไธญ็š„ๅ…ถไป–้กน็›ฎๅ…ฑไบซ็›ธๅŒ็š„ `app/internal/admin.py` ๆ–‡ไปถใ€‚ @@ -465,15 +441,13 @@ from .routers.users import router ๅ› ๆญค๏ผŒไธพไพ‹ๆฅ่ฏด๏ผŒๅ…ถไป–้กน็›ฎ่ƒฝๅคŸไปฅไธๅŒ็š„่บซไปฝ่ฎค่ฏๆ–นๆณ•ไฝฟ็”จ็›ธๅŒ็š„ `APIRouter`ใ€‚ -### ๅŒ…ๅซไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* +### ๅŒ…ๅซไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* { #include-a-path-operation } ๆˆ‘ไปฌ่ฟ˜ๅฏไปฅ็›ดๆŽฅๅฐ†*่ทฏๅพ„ๆ“ไฝœ*ๆทปๅŠ ๅˆฐ `FastAPI` ๅบ”็”จไธญใ€‚ ่ฟ™้‡Œๆˆ‘ไปฌ่ฟ™ๆ ทๅšไบ†...ๅชๆ˜ฏไธบไบ†่กจๆ˜Žๆˆ‘ไปฌๅฏไปฅๅšๅˆฐ๐Ÿคท๏ผš -```Python hl_lines="21-23" title="app/main.py" -{!../../docs_src/bigger_applications/app/main.py!} -``` +{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} ๅฎƒๅฐ†ไธŽ้€š่ฟ‡ `app.include_router()` ๆทปๅŠ ็š„ๆ‰€ๆœ‰ๅ…ถไป–*่ทฏๅพ„ๆ“ไฝœ*ไธ€่ตทๆญฃๅธธ่ฟ่กŒใ€‚ @@ -491,14 +465,14 @@ from .routers.users import router /// -## ๆŸฅ็œ‹่‡ชๅŠจๅŒ–็š„ API ๆ–‡ๆกฃ +## ๆŸฅ็œ‹่‡ชๅŠจๅŒ–็š„ API ๆ–‡ๆกฃ { #check-the-automatic-api-docs } -็Žฐๅœจ๏ผŒไฝฟ็”จ `app.main` ๆจกๅ—ๅ’Œ `app` ๅ˜้‡่ฟ่กŒ `uvicorn`๏ผš +็Žฐๅœจ๏ผŒ่ฟ่กŒไฝ ็š„ๅบ”็”จ๏ผš
```console -$ uvicorn app.main:app --reload +$ fastapi dev app/main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -509,9 +483,9 @@ $ uvicorn app.main:app --reload ไฝ ๅฐ†็œ‹ๅˆฐไฝฟ็”จไบ†ๆญฃ็กฎ่ทฏๅพ„๏ผˆๅ’Œๅ‰็ผ€๏ผ‰ๅ’Œๆญฃ็กฎๆ ‡็ญพ็š„่‡ชๅŠจๅŒ– API ๆ–‡ๆกฃ๏ผŒๅŒ…ๆ‹ฌไบ†ๆฅ่‡ชๆ‰€ๆœ‰ๅญๆจกๅ—็š„่ทฏๅพ„๏ผš - + -## ๅคšๆฌกไฝฟ็”จไธๅŒ็š„ `prefix` ๅŒ…ๅซๅŒไธ€ไธช่ทฏ็”ฑๅ™จ +## ๅคšๆฌกไฝฟ็”จไธๅŒ็š„ `prefix` ๅŒ…ๅซๅŒไธ€ไธช่ทฏ็”ฑๅ™จ { #include-the-same-router-multiple-times-with-different-prefix } ไฝ ไนŸๅฏไปฅๅœจ*ๅŒไธ€*่ทฏ็”ฑๅ™จไธŠไฝฟ็”จไธๅŒ็š„ๅ‰็ผ€ๆฅๅคšๆฌกไฝฟ็”จ `.include_router()`ใ€‚ @@ -519,7 +493,7 @@ $ uvicorn app.main:app --reload ่ฟ™ๆ˜ฏไธ€ไธชไฝ ๅฏ่ƒฝๅนถไธ็œŸๆญฃ้œ€่ฆ็š„้ซ˜็บง็”จๆณ•๏ผŒไฝ†ไธ‡ไธ€ไฝ ๆœ‰้œ€่ฆไบ†ๅฐฑ่ƒฝๅคŸ็”จไธŠใ€‚ -## ๅœจๅฆไธ€ไธช `APIRouter` ไธญๅŒ…ๅซไธ€ไธช `APIRouter` +## ๅœจๅฆไธ€ไธช `APIRouter` ไธญๅŒ…ๅซไธ€ไธช `APIRouter` { #include-an-apirouter-in-another } ไธŽๅœจ `FastAPI` ๅบ”็”จ็จ‹ๅบไธญๅŒ…ๅซ `APIRouter` ็š„ๆ–นๅผ็›ธๅŒ๏ผŒไฝ ไนŸๅฏไปฅๅœจๅฆไธ€ไธช `APIRouter` ไธญๅŒ…ๅซ `APIRouter`๏ผŒ้€š่ฟ‡๏ผš @@ -527,4 +501,4 @@ $ uvicorn app.main:app --reload router.include_router(other_router) ``` -่ฏท็กฎไฟๅœจไฝ ๅฐ† `router` ๅŒ…ๅซๅˆฐ `FastAPI` ๅบ”็”จ็จ‹ๅบไน‹ๅ‰่ฟ›่กŒๆญคๆ“ไฝœ๏ผŒไปฅไพฟ `other_router` ไธญ็š„`่ทฏๅพ„ๆ“ไฝœ`ไนŸ่ƒฝ่ขซๅŒ…ๅซ่ฟ›ๆฅใ€‚ +่ฏท็กฎไฟๅœจไฝ ๅฐ† `router` ๅŒ…ๅซๅˆฐ `FastAPI` ๅบ”็”จ็จ‹ๅบไน‹ๅ‰่ฟ›่กŒๆญคๆ“ไฝœ๏ผŒไปฅไพฟ `other_router` ไธญ็š„*่ทฏๅพ„ๆ“ไฝœ*ไนŸ่ƒฝ่ขซๅŒ…ๅซ่ฟ›ๆฅใ€‚ diff --git a/docs/zh/docs/tutorial/body-fields.md b/docs/zh/docs/tutorial/body-fields.md index 4cff58bfc5..36be7c4191 100644 --- a/docs/zh/docs/tutorial/body-fields.md +++ b/docs/zh/docs/tutorial/body-fields.md @@ -1,8 +1,8 @@ -# ่ฏทๆฑ‚ไฝ“ - ๅญ—ๆฎต +# ่ฏทๆฑ‚ไฝ“ - ๅญ—ๆฎต { #body-fields } ไธŽๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญไฝฟ็”จ `Query`ใ€`Path` ใ€`Body` ๅฃฐๆ˜Žๆ ก้ชŒไธŽๅ…ƒๆ•ฐๆฎ็š„ๆ–นๅผไธ€ๆ ท๏ผŒๅฏไปฅไฝฟ็”จ Pydantic ็š„ `Field` ๅœจ Pydantic ๆจกๅž‹ๅ†…้ƒจๅฃฐๆ˜Žๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ -## ๅฏผๅ…ฅ `Field` +## ๅฏผๅ…ฅ `Field` { #import-field } ้ฆ–ๅ…ˆ๏ผŒไปŽ Pydantic ไธญๅฏผๅ…ฅ `Field`๏ผš @@ -14,7 +14,7 @@ /// -## ๅฃฐๆ˜Žๆจกๅž‹ๅฑžๆ€ง +## ๅฃฐๆ˜Žๆจกๅž‹ๅฑžๆ€ง { #declare-model-attributes } ็„ถๅŽ๏ผŒไฝฟ็”จ `Field` ๅฎšไน‰ๆจกๅž‹็š„ๅฑžๆ€ง๏ผš @@ -24,7 +24,7 @@ /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ๅฎž้™…ไธŠ๏ผŒ`Query`ใ€`Path` ้ƒฝๆ˜ฏ `Params` ็š„ๅญ็ฑป๏ผŒ่€Œ `Params` ็ฑปๅˆๆ˜ฏ Pydantic ไธญ `FieldInfo` ็š„ๅญ็ฑปใ€‚ +ๅฎž้™…ไธŠ๏ผŒ`Query`ใ€`Path` ไปฅๅŠไฝ ๆŽฅไธ‹ๆฅไผš็œ‹ๅˆฐ็š„ๅ…ถๅฎƒๅฏน่ฑก๏ผŒไผšๅˆ›ๅปบๅ…ฌๅ…ฑ `Param` ็ฑป็š„ๅญ็ฑป็š„ๅฏน่ฑก๏ผŒ่€Œ `Param` ๆœฌ่บซๆ˜ฏ Pydantic ไธญ `FieldInfo` ็š„ๅญ็ฑปใ€‚ Pydantic ็š„ `Field` ่ฟ”ๅ›žไนŸๆ˜ฏ `FieldInfo` ็š„็ฑปๅฎžไพ‹ใ€‚ @@ -40,13 +40,20 @@ Pydantic ็š„ `Field` ่ฟ”ๅ›žไนŸๆ˜ฏ `FieldInfo` ็š„็ฑปๅฎžไพ‹ใ€‚ /// -## ๆทปๅŠ ๆ›ดๅคšไฟกๆฏ +## ๆทปๅŠ ๆ›ดๅคšไฟกๆฏ { #add-extra-information } `Field`ใ€`Query`ใ€`Body` ็ญ‰ๅฏน่ฑก้‡Œๅฏไปฅๅฃฐๆ˜Žๆ›ดๅคšไฟกๆฏ๏ผŒๅนถไธ” JSON Schema ไธญไนŸไผš้›†ๆˆ่ฟ™ไบ›ไฟกๆฏใ€‚ *ๅฃฐๆ˜Ž็คบไพ‹*ไธ€็ซ ไธญๅฐ†่ฏฆ็ป†ไป‹็ปๆทปๅŠ ๆ›ดๅคšไฟกๆฏ็š„็Ÿฅ่ฏ†ใ€‚ -## ๅฐ็ป“ +/// warning | ่ญฆๅ‘Š + +ไผ ้€’็ป™ `Field` ็š„้ขๅค–้”ฎไนŸไผšๅ‡บ็Žฐๅœจไฝ ็š„ๅบ”็”จ็”Ÿๆˆ็š„ OpenAPI ๆžถๆž„ไธญใ€‚ +็”ฑไบŽ่ฟ™ไบ›้”ฎไธไธ€ๅฎšๅฑžไบŽ OpenAPI ่ง„่Œƒ็š„ไธ€้ƒจๅˆ†๏ผŒๆŸไบ› OpenAPI ๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ [OpenAPI ้ชŒ่ฏๅ™จ](https://validator.swagger.io/)๏ผ‰ๅฏ่ƒฝๆ— ๆณ•ๅค„็†ไฝ ็”Ÿๆˆ็š„ๆžถๆž„ใ€‚ + +/// + +## ๅฐ็ป“ { #recap } Pydantic ็š„ `Field` ๅฏไปฅไธบๆจกๅž‹ๅฑžๆ€งๅฃฐๆ˜Žๆ›ดๅคšๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ diff --git a/docs/zh/docs/tutorial/body-multiple-params.md b/docs/zh/docs/tutorial/body-multiple-params.md index b4356fdcb4..7d0ddfc1ec 100644 --- a/docs/zh/docs/tutorial/body-multiple-params.md +++ b/docs/zh/docs/tutorial/body-multiple-params.md @@ -1,8 +1,8 @@ -# ่ฏทๆฑ‚ไฝ“ - ๅคšไธชๅ‚ๆ•ฐ +# ่ฏทๆฑ‚ไฝ“ - ๅคšไธชๅ‚ๆ•ฐ { #body-multiple-parameters } ๆ—ข็„ถๆˆ‘ไปฌๅทฒ็ป็Ÿฅ้“ไบ†ๅฆ‚ไฝ•ไฝฟ็”จ `Path` ๅ’Œ `Query`๏ผŒไธ‹้ข่ฎฉๆˆ‘ไปฌๆฅไบ†่งฃไธ€ไธ‹่ฏทๆฑ‚ไฝ“ๅฃฐๆ˜Ž็š„ๆ›ด้ซ˜็บง็”จๆณ•ใ€‚ -## ๆททๅˆไฝฟ็”จ `Path`ใ€`Query` ๅ’Œ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ +## ๆททๅˆไฝฟ็”จ `Path`ใ€`Query` ๅ’Œ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ { #mix-path-query-and-body-parameters } ้ฆ–ๅ…ˆ๏ผŒๆฏซๆ— ็–‘้—ฎๅœฐ๏ผŒไฝ ๅฏไปฅ้šๆ„ๅœฐๆททๅˆไฝฟ็”จ `Path`ใ€`Query` ๅ’Œ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐๅฃฐๆ˜Ž๏ผŒ**FastAPI** ไผš็Ÿฅ้“่ฏฅๅฆ‚ไฝ•ๅค„็†ใ€‚ @@ -10,13 +10,13 @@ {* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} -/// note +/// note | ๆณจๆ„ ่ฏทๆณจๆ„๏ผŒๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฐ†ไปŽ่ฏทๆฑ‚ไฝ“่Žทๅ–็š„ `item` ๆ˜ฏๅฏ้€‰็š„ใ€‚ๅ› ไธบๅฎƒ็š„้ป˜่ฎคๅ€ผไธบ `None`ใ€‚ /// -## ๅคšไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ +## ๅคšไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ { #multiple-body-parameters } ๅœจไธŠ้ข็š„็คบไพ‹ไธญ๏ผŒ*่ทฏๅพ„ๆ“ไฝœ*ๅฐ†ๆœŸๆœ›ไธ€ไธชๅ…ทๆœ‰ `Item` ็š„ๅฑžๆ€ง็š„ JSON ่ฏทๆฑ‚ไฝ“๏ผŒๅฐฑๅƒ๏ผš @@ -52,7 +52,7 @@ } ``` -/// note +/// note | ๆณจๆ„ ่ฏทๆณจๆ„๏ผŒๅณไฝฟ `item` ็š„ๅฃฐๆ˜Žๆ–นๅผไธŽไน‹ๅ‰็›ธๅŒ๏ผŒไฝ†็Žฐๅœจๅฎƒ่ขซๆœŸๆœ›้€š่ฟ‡ `item` ้”ฎๅ†…ๅตŒๅœจ่ฏทๆฑ‚ไฝ“ไธญใ€‚ @@ -62,7 +62,7 @@ ๅฎƒๅฐ†ๆ‰ง่กŒๅฏนๅคๅˆๆ•ฐๆฎ็š„ๆ ก้ชŒ๏ผŒๅนถไธ”ๅƒ็Žฐๅœจ่ฟ™ๆ ทไธบ OpenAPI ๆจกๅผๅ’Œ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃๅฏนๅ…ถ่ฟ›่กŒ่ฎฐๅฝ•ใ€‚ -## ่ฏทๆฑ‚ไฝ“ไธญ็š„ๅ•ไธ€ๅ€ผ +## ่ฏทๆฑ‚ไฝ“ไธญ็š„ๅ•ไธ€ๅ€ผ { #singular-values-in-body } ไธŽไฝฟ็”จ `Query` ๅ’Œ `Path` ไธบๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œ่ทฏๅพ„ๅ‚ๆ•ฐๅฎšไน‰้ขๅค–ๆ•ฐๆฎ็š„ๆ–นๅผ็›ธๅŒ๏ผŒ**FastAPI** ๆไพ›ไบ†ไธ€ไธชๅŒ็ญ‰็š„ `Body`ใ€‚ @@ -72,12 +72,10 @@ ไฝ†ๆ˜ฏไฝ ๅฏไปฅไฝฟ็”จ `Body` ๆŒ‡็คบ **FastAPI** ๅฐ†ๅ…ถไฝœไธบ่ฏทๆฑ‚ไฝ“็š„ๅฆไธ€ไธช้”ฎ่ฟ›่กŒๅค„็†ใ€‚ - {* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ๅฐ†ๆœŸๆœ›ๅƒ่ฟ™ๆ ท็š„่ฏทๆฑ‚ไฝ“๏ผš - ```JSON { "item": { @@ -96,27 +94,33 @@ ๅŒๆ ท็š„๏ผŒๅฎƒๅฐ†่ฝฌๆขๆ•ฐๆฎ็ฑปๅž‹๏ผŒๆ ก้ชŒ๏ผŒ็”Ÿๆˆๆ–‡ๆกฃ็ญ‰ใ€‚ -## ๅคšไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ +## ๅคšไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ { #multiple-body-params-and-query } ๅฝ“็„ถ๏ผŒ้™คไบ†่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐๅค–๏ผŒไฝ ่ฟ˜ๅฏไปฅๅœจไปปไฝ•้œ€่ฆ็š„ๆ—ถๅ€™ๅฃฐๆ˜Ž้ขๅค–็š„ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ -็”ฑไบŽ้ป˜่ฎคๆƒ…ๅ†ตไธ‹ๅ•ไธ€ๅ€ผ่ขซ่งฃ้‡ŠไธบๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒๅ› ๆญคไฝ ไธๅฟ…ๆ˜พๅผๅœฐๆทปๅŠ  `Query`๏ผŒไฝ ๅฏไปฅไป…ๆ‰ง่กŒไปฅไธ‹ๆ“ไฝœ๏ผš +็”ฑไบŽ้ป˜่ฎคๆƒ…ๅ†ตไธ‹ๅ•ไธ€ๅ€ผไผš่ขซ่งฃ้‡ŠไธบๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒๅ› ๆญคไฝ ไธๅฟ…ๆ˜พๅผๅœฐๆทปๅŠ  `Query`๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ทๅ†™๏ผš + +```Python +q: str | None = None +``` + +ๆˆ–่€…ๅœจ Python 3.9 ไธญ๏ผš ```Python -q: str = None +q: Union[str, None] = None ``` ๆฏ”ๅฆ‚๏ผš -{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[27] *} +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info +/// info | ไฟกๆฏ `Body` ๅŒๆ ทๅ…ทๆœ‰ไธŽ `Query`ใ€`Path` ไปฅๅŠๅ…ถไป–ๅŽ้ขๅฐ†็œ‹ๅˆฐ็š„็ฑปๅฎŒๅ…จ็›ธๅŒ็š„้ขๅค–ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎๅ‚ๆ•ฐใ€‚ /// -## ๅตŒๅ…ฅๅ•ไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ +## ๅตŒๅ…ฅๅ•ไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ { #embed-a-single-body-parameter } ๅ‡่ฎพไฝ ๅชๆœ‰ไธ€ไธชๆฅ่‡ช Pydantic ๆจกๅž‹ `Item` ็š„่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ `item`ใ€‚ @@ -156,7 +160,7 @@ item: Item = Body(embed=True) } ``` -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #recap } ไฝ ๅฏไปฅๆทปๅŠ ๅคšไธช่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐๅˆฐ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ๏ผŒๅณไฝฟไธ€ไธช่ฏทๆฑ‚ๅช่ƒฝๆœ‰ไธ€ไธช่ฏทๆฑ‚ไฝ“ใ€‚ diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md index df96d96b4b..242aa5822c 100644 --- a/docs/zh/docs/tutorial/body-nested-models.md +++ b/docs/zh/docs/tutorial/body-nested-models.md @@ -1,53 +1,42 @@ -# ่ฏทๆฑ‚ไฝ“ - ๅตŒๅฅ—ๆจกๅž‹ +# ่ฏทๆฑ‚ไฝ“ - ๅตŒๅฅ—ๆจกๅž‹ { #body-nested-models } ไฝฟ็”จ **FastAPI**๏ผŒไฝ ๅฏไปฅๅฎšไน‰ใ€ๆ ก้ชŒใ€่ฎฐๅฝ•ๆ–‡ๆกฃๅนถไฝฟ็”จไปปๆ„ๆทฑๅบฆๅตŒๅฅ—็š„ๆจกๅž‹๏ผˆๅฝ’ๅŠŸไบŽPydantic๏ผ‰ใ€‚ -## List ๅญ—ๆฎต +## List ๅญ—ๆฎต { #list-fields } -ไฝ ๅฏไปฅๅฐ†ไธ€ไธชๅฑžๆ€งๅฎšไน‰ไธบๆ‹ฅๆœ‰ๅญๅ…ƒ็ด ็š„็ฑปๅž‹ใ€‚ไพ‹ๅฆ‚ Python `list`๏ผš +ไฝ ๅฏไปฅๅฐ†ไธ€ไธชๅฑžๆ€งๅฎšไน‰ไธบไธ€ไธชๅญ็ฑปๅž‹ใ€‚ไพ‹ๅฆ‚๏ผŒPython `list`๏ผš {* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} ่ฟ™ๅฐ†ไฝฟ `tags` ๆˆไธบไธ€ไธช็”ฑๅ…ƒ็ด ็ป„ๆˆ็š„ๅˆ—่กจใ€‚ไธ่ฟ‡ๅฎƒๆฒกๆœ‰ๅฃฐๆ˜Žๆฏไธชๅ…ƒ็ด ็š„็ฑปๅž‹ใ€‚ -## ๅ…ทๆœ‰ๅญ็ฑปๅž‹็š„ List ๅญ—ๆฎต +## ๅธฆ็ฑปๅž‹ๅ‚ๆ•ฐ็š„ List ๅญ—ๆฎต { #list-fields-with-type-parameter } -ไฝ†ๆ˜ฏ Python ๆœ‰ไธ€็ง็‰นๅฎš็š„ๆ–นๆณ•ๆฅๅฃฐๆ˜Žๅ…ทๆœ‰ๅญ็ฑปๅž‹็š„ๅˆ—่กจ๏ผš +ไธ่ฟ‡๏ผŒPython ๆœ‰ไธ€็ง็”จไบŽๅฃฐๆ˜Žๅ…ทๆœ‰ๅ†…้ƒจ็ฑปๅž‹๏ผˆ็ฑปๅž‹ๅ‚ๆ•ฐ๏ผ‰็š„ๅˆ—่กจ็š„็‰นๅฎšๆ–นๅผ๏ผš -### ไปŽ typing ๅฏผๅ…ฅ `List` +### ๅฃฐๆ˜Žๅธฆ็ฑปๅž‹ๅ‚ๆ•ฐ็š„ `list` { #declare-a-list-with-a-type-parameter } -้ฆ–ๅ…ˆ๏ผŒไปŽ Python ็š„ๆ ‡ๅ‡†ๅบ“ `typing` ๆจกๅ—ไธญๅฏผๅ…ฅ `List`๏ผš - -{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *} - -### ๅฃฐๆ˜Žๅ…ทๆœ‰ๅญ็ฑปๅž‹็š„ List - -่ฆๅฃฐๆ˜Žๅ…ทๆœ‰ๅญ็ฑปๅž‹็š„็ฑปๅž‹๏ผŒไพ‹ๅฆ‚ `list`ใ€`dict`ใ€`tuple`๏ผš - -* ไปŽ `typing` ๆจกๅ—ๅฏผๅ…ฅๅฎƒไปฌ -* ไฝฟ็”จๆ–นๆ‹ฌๅท `[` ๅ’Œ `]` ๅฐ†ๅญ็ฑปๅž‹ไฝœไธบใ€Œ็ฑปๅž‹ๅ‚ๆ•ฐใ€ไผ ๅ…ฅ +่ฆๅฃฐๆ˜Žๅ…ทๆœ‰็ฑปๅž‹ๅ‚ๆ•ฐ๏ผˆๅ†…้ƒจ็ฑปๅž‹๏ผ‰็š„็ฑปๅž‹๏ผŒไพ‹ๅฆ‚ `list`ใ€`dict`ใ€`tuple`๏ผŒไฝฟ็”จๆ–นๆ‹ฌๅท `[` ๅ’Œ `]` ไผ ๅ…ฅๅ†…้ƒจ็ฑปๅž‹ไฝœไธบใ€Œ็ฑปๅž‹ๅ‚ๆ•ฐใ€๏ผš ```Python -from typing import List - -my_list: List[str] +my_list: list[str] ``` ่ฟ™ๅฎŒๅ…จๆ˜ฏ็”จไบŽ็ฑปๅž‹ๅฃฐๆ˜Ž็š„ๆ ‡ๅ‡† Python ่ฏญๆณ•ใ€‚ -ๅฏนๅ…ทๆœ‰ๅญ็ฑปๅž‹็š„ๆจกๅž‹ๅฑžๆ€งไนŸไฝฟ็”จ็›ธๅŒ็š„ๆ ‡ๅ‡†่ฏญๆณ•ใ€‚ +ๅฏนๅ…ทๆœ‰ๅ†…้ƒจ็ฑปๅž‹็š„ๆจกๅž‹ๅฑžๆ€งไนŸไฝฟ็”จ็›ธๅŒ็š„ๆ ‡ๅ‡†่ฏญๆณ•ใ€‚ ๅ› ๆญค๏ผŒๅœจๆˆ‘ไปฌ็š„็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ† `tags` ๆ˜Ž็กฎๅœฐๆŒ‡ๅฎšไธบไธ€ไธชใ€Œๅญ—็ฌฆไธฒๅˆ—่กจใ€๏ผš {* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} -## Set ็ฑปๅž‹ +## Set ็ฑปๅž‹ { #set-types } ไฝ†ๆ˜ฏ้šๅŽๆˆ‘ไปฌ่€ƒ่™‘ไบ†ไธ€ไธ‹๏ผŒๆ„่ฏ†ๅˆฐๆ ‡็ญพไธๅบ”่ฏฅ้‡ๅค๏ผŒๅฎƒไปฌๅพˆๅคงๅฏ่ƒฝไผšๆ˜ฏๅ”ฏไธ€็š„ๅญ—็ฌฆไธฒใ€‚ -Python ๅ…ทๆœ‰ไธ€็ง็‰นๆฎŠ็š„ๆ•ฐๆฎ็ฑปๅž‹ๆฅไฟๅญ˜ไธ€็ป„ๅ”ฏไธ€็š„ๅ…ƒ็ด ๏ผŒๅณ `set`ใ€‚ +่€Œ Python ๆœ‰ไธ€็ง็”จไบŽไฟๅญ˜ๅ”ฏไธ€ๅ…ƒ็ด ้›†ๅˆ็š„็‰นๆฎŠๆ•ฐๆฎ็ฑปๅž‹ `set`ใ€‚ -็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅฏผๅ…ฅ `Set` ๅนถๅฐ† `tag` ๅฃฐๆ˜Žไธบไธ€ไธช็”ฑ `str` ็ป„ๆˆ็š„ `set`๏ผš +็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅฐ† `tags` ๅฃฐๆ˜Žไธบไธ€ไธช็”ฑๅญ—็ฌฆไธฒ็ป„ๆˆ็š„ set๏ผš {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} @@ -57,7 +46,7 @@ Python ๅ…ทๆœ‰ไธ€็ง็‰นๆฎŠ็š„ๆ•ฐๆฎ็ฑปๅž‹ๆฅไฟๅญ˜ไธ€็ป„ๅ”ฏไธ€็š„ๅ…ƒ็ด ๏ผŒๅณ `se ๅนถไธ”่ฟ˜ไผš่ขซ็›ธๅบ”ๅœฐๆ ‡ๆณจ / ่ฎฐๅฝ•ๆ–‡ๆกฃใ€‚ -## ๅตŒๅฅ—ๆจกๅž‹ +## ๅตŒๅฅ—ๆจกๅž‹ { #nested-models } Pydantic ๆจกๅž‹็š„ๆฏไธชๅฑžๆ€ง้ƒฝๅ…ทๆœ‰็ฑปๅž‹ใ€‚ @@ -67,13 +56,13 @@ Pydantic ๆจกๅž‹็š„ๆฏไธชๅฑžๆ€ง้ƒฝๅ…ทๆœ‰็ฑปๅž‹ใ€‚ ไธŠ่ฟฐ่ฟ™ไบ›้ƒฝๅฏไปฅไปปๆ„็š„ๅตŒๅฅ—ใ€‚ -### ๅฎšไน‰ๅญๆจกๅž‹ +### ๅฎšไน‰ๅญๆจกๅž‹ { #define-a-submodel } ไพ‹ๅฆ‚๏ผŒๆˆ‘ไปฌๅฏไปฅๅฎšไน‰ไธ€ไธช `Image` ๆจกๅž‹๏ผš {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} -### ๅฐ†ๅญๆจกๅž‹็”จไฝœ็ฑปๅž‹ +### ๅฐ†ๅญๆจกๅž‹็”จไฝœ็ฑปๅž‹ { #use-the-submodel-as-a-type } ็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅฐ†ๅ…ถ็”จไฝœไธ€ไธชๅฑžๆ€ง็š„็ฑปๅž‹๏ผš @@ -102,11 +91,11 @@ Pydantic ๆจกๅž‹็š„ๆฏไธชๅฑžๆ€ง้ƒฝๅ…ทๆœ‰็ฑปๅž‹ใ€‚ * ๆ•ฐๆฎๆ ก้ชŒ * ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ -## ็‰นๆฎŠ็š„็ฑปๅž‹ๅ’Œๆ ก้ชŒ +## ็‰นๆฎŠ็š„็ฑปๅž‹ๅ’Œๆ ก้ชŒ { #special-types-and-validation } ้™คไบ†ๆ™ฎ้€š็š„ๅ•ไธ€ๅ€ผ็ฑปๅž‹๏ผˆๅฆ‚ `str`ใ€`int`ใ€`float` ็ญ‰๏ผ‰ๅค–๏ผŒไฝ ่ฟ˜ๅฏไปฅไฝฟ็”จไปŽ `str` ็ปงๆ‰ฟ็š„ๆ›ดๅคๆ‚็š„ๅ•ไธ€ๅ€ผ็ฑปๅž‹ใ€‚ -่ฆไบ†่งฃๆ‰€ๆœ‰็š„ๅฏ็”จ้€‰้กน๏ผŒ่ฏทๆŸฅ็œ‹ๅ…ณไบŽ ๆฅ่‡ช Pydantic ็š„ๅค–้ƒจ็ฑปๅž‹ ็š„ๆ–‡ๆกฃใ€‚ไฝ ๅฐ†ๅœจไธ‹ไธ€็ซ ่Š‚ไธญ็œ‹ๅˆฐไธ€ไบ›็คบไพ‹ใ€‚ +่ฆไบ†่งฃๆ‰€ๆœ‰็š„ๅฏ็”จ้€‰้กน๏ผŒ่ฏทๆŸฅ็œ‹ Pydantic ็š„็ฑปๅž‹ๆฆ‚่งˆใ€‚ไฝ ๅฐ†ๅœจไธ‹ไธ€็ซ ่Š‚ไธญ็œ‹ๅˆฐไธ€ไบ›็คบไพ‹ใ€‚ ไพ‹ๅฆ‚๏ผŒๅœจ `Image` ๆจกๅž‹ไธญๆˆ‘ไปฌๆœ‰ไธ€ไธช `url` ๅญ—ๆฎต๏ผŒๆˆ‘ไปฌๅฏไปฅๆŠŠๅฎƒๅฃฐๆ˜Žไธบ Pydantic ็š„ `HttpUrl`๏ผŒ่€Œไธๆ˜ฏ `str`๏ผš @@ -114,7 +103,7 @@ Pydantic ๆจกๅž‹็š„ๆฏไธชๅฑžๆ€ง้ƒฝๅ…ทๆœ‰็ฑปๅž‹ใ€‚ ่ฏฅๅญ—็ฌฆไธฒๅฐ†่ขซๆฃ€ๆŸฅๆ˜ฏๅฆไธบๆœ‰ๆ•ˆ็š„ URL๏ผŒๅนถๅœจ JSON Schema / OpenAPI ๆ–‡ๆกฃไธญ่ฟ›่กŒ่ฎฐๅฝ•ใ€‚ -## ๅธฆๆœ‰ไธ€็ป„ๅญๆจกๅž‹็š„ๅฑžๆ€ง +## ๅธฆๆœ‰ไธ€็ป„ๅญๆจกๅž‹็š„ๅฑžๆ€ง { #attributes-with-lists-of-submodels } ไฝ ่ฟ˜ๅฏไปฅๅฐ† Pydantic ๆจกๅž‹็”จไฝœ `list`ใ€`set` ็ญ‰็š„ๅญ็ฑปๅž‹๏ผš @@ -146,49 +135,49 @@ Pydantic ๆจกๅž‹็š„ๆฏไธชๅฑžๆ€ง้ƒฝๅ…ทๆœ‰็ฑปๅž‹ใ€‚ } ``` -/// info +/// info | ไฟกๆฏ ่ฏทๆณจๆ„ `images` ้”ฎ็Žฐๅœจๅ…ทๆœ‰ไธ€็ป„ image ๅฏน่ฑกๆ˜ฏๅฆ‚ไฝ•ๅ‘็”Ÿ็š„ใ€‚ /// -## ๆทฑๅบฆๅตŒๅฅ—ๆจกๅž‹ +## ๆทฑๅบฆๅตŒๅฅ—ๆจกๅž‹ { #deeply-nested-models } ไฝ ๅฏไปฅๅฎšไน‰ไปปๆ„ๆทฑๅบฆ็š„ๅตŒๅฅ—ๆจกๅž‹๏ผš {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info +/// info | ไฟกๆฏ ่ฏทๆณจๆ„ `Offer` ๆ‹ฅๆœ‰ไธ€็ป„ `Item` ่€Œๅ่ฟ‡ๆฅ `Item` ๅˆๆ˜ฏไธ€ไธชๅฏ้€‰็š„ `Image` ๅˆ—่กจๆ˜ฏๅฆ‚ไฝ•ๅ‘็”Ÿ็š„ใ€‚ /// -## ็บฏๅˆ—่กจ่ฏทๆฑ‚ไฝ“ +## ็บฏๅˆ—่กจ่ฏทๆฑ‚ไฝ“ { #bodies-of-pure-lists } ๅฆ‚ๆžœไฝ ๆœŸๆœ›็š„ JSON ่ฏทๆฑ‚ไฝ“็š„ๆœ€ๅค–ๅฑ‚ๆ˜ฏไธ€ไธช JSON `array`๏ผˆๅณ Python `list`๏ผ‰๏ผŒๅˆ™ๅฏไปฅๅœจ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐไธญๅฃฐๆ˜Žๆญค็ฑปๅž‹๏ผŒๅฐฑๅƒๅฃฐๆ˜Ž Pydantic ๆจกๅž‹ไธ€ๆ ท๏ผš ```Python -images: List[Image] +images: list[Image] ``` ไพ‹ๅฆ‚๏ผš {* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} -## ๆ— ๅค„ไธๅœจ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ +## ๆ— ๅค„ไธๅœจ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ { #editor-support-everywhere } ไฝ ๅฏไปฅ้šๅค„่Žทๅพ—็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ ๅณไฝฟๆ˜ฏๅˆ—่กจไธญ็š„ๅ…ƒ็ด ๏ผš - + ๅฆ‚ๆžœไฝ ็›ดๆŽฅไฝฟ็”จ `dict` ่€Œไธๆ˜ฏ Pydantic ๆจกๅž‹๏ผŒ้‚ฃไฝ ๅฐ†ๆ— ๆณ•่Žทๅพ—่ฟ™็ง็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ ไฝ†ๆ˜ฏไฝ ๆ นๆœฌไธๅฟ…ๆ‹…ๅฟƒ่ฟ™ไธค่€…๏ผŒไผ ๅ…ฅ็š„ๅญ—ๅ…ธไผš่‡ชๅŠจ่ขซ่ฝฌๆข๏ผŒไฝ ็š„่พ“ๅ‡บไนŸไผš่‡ชๅŠจ่ขซ่ฝฌๆขไธบ JSONใ€‚ -## ไปปๆ„ `dict` ๆž„ๆˆ็š„่ฏทๆฑ‚ไฝ“ +## ไปปๆ„ `dict` ๆž„ๆˆ็š„่ฏทๆฑ‚ไฝ“ { #bodies-of-arbitrary-dicts } ไฝ ไนŸๅฏไปฅๅฐ†่ฏทๆฑ‚ไฝ“ๅฃฐๆ˜Žไธบไฝฟ็”จๆŸ็ฑปๅž‹็š„้”ฎๅ’Œๅ…ถไป–็ฑปๅž‹ๅ€ผ็š„ `dict`ใ€‚ @@ -206,7 +195,7 @@ images: List[Image] {* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} -/// tip +/// tip | ๆ็คบ ่ฏท่ฎฐไฝ JSON ไป…ๆ”ฏๆŒๅฐ† `str` ไฝœไธบ้”ฎใ€‚ @@ -218,7 +207,7 @@ images: List[Image] /// -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #recap } ไฝฟ็”จ **FastAPI** ไฝ ๅฏไปฅๆ‹ฅๆœ‰ Pydantic ๆจกๅž‹ๆไพ›็š„ๆž้ซ˜็ตๆดปๆ€ง๏ผŒๅŒๆ—ถไฟๆŒไปฃ็ ็š„็ฎ€ๅ•ใ€็ฎ€็Ÿญๅ’Œไผ˜้›…ใ€‚ diff --git a/docs/zh/docs/tutorial/body-updates.md b/docs/zh/docs/tutorial/body-updates.md index 87f88f2553..000201de99 100644 --- a/docs/zh/docs/tutorial/body-updates.md +++ b/docs/zh/docs/tutorial/body-updates.md @@ -1,18 +1,18 @@ -# ่ฏทๆฑ‚ไฝ“ - ๆ›ดๆ–ฐๆ•ฐๆฎ +# ่ฏทๆฑ‚ไฝ“ - ๆ›ดๆ–ฐๆ•ฐๆฎ { #body-updates } -## ็”จ `PUT` ๆ›ดๆ–ฐๆ•ฐๆฎ +## ็”จ `PUT` ๆ›ฟๆขๅผๆ›ดๆ–ฐ { #update-replacing-with-put } -ๆ›ดๆ–ฐๆ•ฐๆฎ่ฏท็”จ HTTP `PUT` ๆ“ไฝœใ€‚ +ๆ›ดๆ–ฐๆ•ฐๆฎๅฏไปฅไฝฟ็”จ HTTP `PUT` ๆ“ไฝœใ€‚ ๆŠŠ่พ“ๅ…ฅๆ•ฐๆฎ่ฝฌๆขไธบไปฅ JSON ๆ ผๅผๅญ˜ๅ‚จ็š„ๆ•ฐๆฎ๏ผˆๆฏ”ๅฆ‚๏ผŒไฝฟ็”จ NoSQL ๆ•ฐๆฎๅบ“ๆ—ถ๏ผ‰๏ผŒๅฏไปฅไฝฟ็”จ `jsonable_encoder`ใ€‚ไพ‹ๅฆ‚๏ผŒๆŠŠ `datetime` ่ฝฌๆขไธบ `str`ใ€‚ -{* ../../docs_src/body_updates/tutorial001.py hl[30:35] *} +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} `PUT` ็”จไบŽๆŽฅๆ”ถๆ›ฟๆข็Žฐๆœ‰ๆ•ฐๆฎ็š„ๆ•ฐๆฎใ€‚ -### ๅ…ณไบŽๆ›ดๆ–ฐๆ•ฐๆฎ็š„่ญฆๅ‘Š +### ๅ…ณไบŽๆ›ฟๆข็š„่ญฆๅ‘Š { #warning-about-replacing } -็”จ `PUT` ๆŠŠๆ•ฐๆฎ้กน `bar` ๆ›ดๆ–ฐไธบไปฅไธ‹ๅ†…ๅฎนๆ—ถ๏ผš +็”จ `PUT` ๆŠŠๆ•ฐๆฎ้กน `bar` ๆ›ดๆ–ฐไธบไปฅไธ‹่ฏทๆฑ‚ไฝ“ๆ—ถ๏ผš ```Python { @@ -22,78 +22,79 @@ } ``` -ๅ› ไธบไธŠ่ฟฐๆ•ฐๆฎๆœชๅŒ…ๅซๅทฒๅญ˜ๅ‚จ็š„ๅฑžๆ€ง `"tax": 20.2`๏ผŒๆ–ฐ็š„่พ“ๅ…ฅๆจกๅž‹ไผšๆŠŠ `"tax": 10.5` ไฝœไธบ้ป˜่ฎคๅ€ผใ€‚ +ๅ› ไธบๅ…ถไธญๆœชๅŒ…ๅซๅทฒๅญ˜ๅ‚จ็š„ๅฑžๆ€ง `"tax": 20.2`๏ผŒ่พ“ๅ…ฅๆจกๅž‹ไผšๅ– `"tax": 10.5` ็š„้ป˜่ฎคๅ€ผใ€‚ -ๅ› ๆญค๏ผŒๆœฌๆฌกๆ“ไฝœๆŠŠ `tax` ็š„ๅ€ผใ€Œๆ›ดๆ–ฐใ€ไธบ `10.5`ใ€‚ +ๅ› ๆญค๏ผŒไฟๅญ˜็š„ๆ•ฐๆฎไผšๅธฆๆœ‰่ฟ™ไธชโ€œๆ–ฐ็š„โ€ `tax` ๅ€ผ `10.5`ใ€‚ -## ็”จ `PATCH` ่ฟ›่กŒ้ƒจๅˆ†ๆ›ดๆ–ฐ +## ็”จ `PATCH` ่ฟ›่กŒ้ƒจๅˆ†ๆ›ดๆ–ฐ { #partial-updates-with-patch } -HTTP `PATCH` ๆ“ไฝœ็”จไบŽๆ›ดๆ–ฐ *้ƒจๅˆ†* ๆ•ฐๆฎใ€‚ +ไนŸๅฏไปฅไฝฟ็”จ HTTP `PATCH` ๆ“ไฝœๅฏนๆ•ฐๆฎ่ฟ›่กŒ*้ƒจๅˆ†*ๆ›ดๆ–ฐใ€‚ -ๅณ๏ผŒๅชๅ‘้€่ฆๆ›ดๆ–ฐ็š„ๆ•ฐๆฎ๏ผŒๅ…ถไฝ™ๆ•ฐๆฎไฟๆŒไธๅ˜ใ€‚ +ไนŸๅฐฑๆ˜ฏ่ฏด๏ผŒไฝ ๅช้œ€ๅ‘้€ๆƒณ่ฆๆ›ดๆ–ฐ็š„ๆ•ฐๆฎ๏ผŒๅ…ถไฝ™ๆ•ฐๆฎไฟๆŒไธๅ˜ใ€‚ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -`PATCH` ๆฒกๆœ‰ `PUT` ็Ÿฅๅ๏ผŒไนŸๆ€Žไนˆไธๅธธ็”จใ€‚ +`PATCH` ๆฒกๆœ‰ `PUT` ็Ÿฅๅ๏ผŒไนŸๆฒก้‚ฃไนˆๅธธ็”จใ€‚ -ๅพˆๅคšไบบ็”š่‡ณๅช็”จ `PUT` ๅฎž็Žฐ้ƒจๅˆ†ๆ›ดๆ–ฐใ€‚ +ๅพˆๅคšๅ›ข้˜Ÿ็”š่‡ณๅช็”จ `PUT` ๅฎž็Žฐ้ƒจๅˆ†ๆ›ดๆ–ฐใ€‚ -**FastAPI** ๅฏนๆญคๆฒกๆœ‰ไปปไฝ•้™ๅˆถ๏ผŒๅฏไปฅ**้šๆ„**ไบ’ๆขไฝฟ็”จ่ฟ™ไธค็งๆ“ไฝœใ€‚ +ไฝ ๅฏไปฅ**้šๆ„**้€‰ๆ‹ฉๅฆ‚ไฝ•ไฝฟ็”จๅฎƒไปฌ๏ผŒ**FastAPI** ไธๅšไปปไฝ•้™ๅˆถใ€‚ -ไฝ†ๆœฌๆŒ‡ๅ—ไนŸไผšๅˆ†ๅˆซไป‹็ป่ฟ™ไธค็งๆ“ไฝœๅ„่‡ช็š„็”จ้€”ใ€‚ +ไฝ†ๆœฌๆŒ‡ๅ—ไผšๅคง่‡ดๅฑ•็คบๅฎƒไปฌ็š„้ข„ๆœŸ็”จๆณ•ใ€‚ /// -### ไฝฟ็”จ Pydantic ็š„ `exclude_unset` ๅ‚ๆ•ฐ +### ไฝฟ็”จ Pydantic ็š„ `exclude_unset` ๅ‚ๆ•ฐ { #using-pydantics-exclude-unset-parameter } -ๆ›ดๆ–ฐ้ƒจๅˆ†ๆ•ฐๆฎๆ—ถ๏ผŒๅฏไปฅๅœจ Pydantic ๆจกๅž‹็š„ `.dict()` ไธญไฝฟ็”จ `exclude_unset` ๅ‚ๆ•ฐใ€‚ +ๅฆ‚ๆžœ่ฆๆŽฅๆ”ถ้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒๅปบ่ฎฎๅœจ Pydantic ๆจกๅž‹็š„ `.model_dump()` ไธญไฝฟ็”จ `exclude_unset` ๅ‚ๆ•ฐใ€‚ -ๆฏ”ๅฆ‚๏ผŒ`item.dict(exclude_unset=True)`ใ€‚ +ๆฏ”ๅฆ‚๏ผŒ`item.model_dump(exclude_unset=True)`ใ€‚ -่ฟ™ๆฎตไปฃ็ ็”Ÿๆˆ็š„ `dict` ๅชๅŒ…ๅซๅˆ›ๅปบ `item` ๆจกๅž‹ๆ—ถๆ˜พๅผ่ฎพ็ฝฎ็š„ๆ•ฐๆฎ๏ผŒ่€ŒไธๅŒ…ๆ‹ฌ้ป˜่ฎคๅ€ผใ€‚ +่ฟ™ไผš็”Ÿๆˆไธ€ไธช `dict`๏ผŒๅชๅŒ…ๅซๅˆ›ๅปบ `item` ๆจกๅž‹ๆ—ถๆ˜พๅผ่ฎพ็ฝฎ็š„ๆ•ฐๆฎ๏ผŒไธๅŒ…ๅซ้ป˜่ฎคๅ€ผใ€‚ -็„ถๅŽๅ†็”จๅฎƒ็”Ÿๆˆไธ€ไธชๅชๅซๅทฒ่ฎพ็ฝฎ๏ผˆๅœจ่ฏทๆฑ‚ไธญๆ‰€ๅ‘้€๏ผ‰ๆ•ฐๆฎ๏ผŒไธ”็œ็•ฅไบ†้ป˜่ฎคๅ€ผ็š„ `dict`๏ผš +็„ถๅŽๅ†็”จๅฎƒ็”Ÿๆˆไธ€ไธชๅชๅซๅทฒ่ฎพ็ฝฎ๏ผˆๅœจ่ฏทๆฑ‚ไธญๅ‘้€๏ผ‰ๆ•ฐๆฎใ€ไธ”็œ็•ฅ้ป˜่ฎคๅ€ผ็š„ `dict`๏ผš -{* ../../docs_src/body_updates/tutorial002.py hl[34] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} -### ไฝฟ็”จ Pydantic ็š„ `update` ๅ‚ๆ•ฐ +### ไฝฟ็”จ Pydantic ็š„ `update` ๅ‚ๆ•ฐ { #using-pydantics-update-parameter } -ๆŽฅไธ‹ๆฅ๏ผŒ็”จ `.copy()` ไธบๅทฒๆœ‰ๆจกๅž‹ๅˆ›ๅปบ่ฐƒ็”จ `update` ๅ‚ๆ•ฐ็š„ๅ‰ฏๆœฌ๏ผŒ่ฏฅๅ‚ๆ•ฐไธบๅŒ…ๅซๆ›ดๆ–ฐๆ•ฐๆฎ็š„ `dict`ใ€‚ +ๆŽฅไธ‹ๆฅ๏ผŒ็”จ `.model_copy()` ไธบๅทฒๆœ‰ๆจกๅž‹ๅˆ›ๅปบๅ‰ฏๆœฌ๏ผŒๅนถไผ ๅ…ฅ `update` ๅ‚ๆ•ฐ๏ผŒๅ€ผไธบๅŒ…ๅซๆ›ดๆ–ฐๆ•ฐๆฎ็š„ `dict`ใ€‚ -ไพ‹ๅฆ‚๏ผŒ`stored_item_model.copy(update=update_data)`๏ผš +ไพ‹ๅฆ‚๏ผŒ`stored_item_model.model_copy(update=update_data)`๏ผš -{* ../../docs_src/body_updates/tutorial002.py hl[35] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} -### ๆ›ดๆ–ฐ้ƒจๅˆ†ๆ•ฐๆฎๅฐ็ป“ +### ้ƒจๅˆ†ๆ›ดๆ–ฐๅฐ็ป“ { #partial-updates-recap } -็ฎ€่€Œ่จ€ไน‹๏ผŒๆ›ดๆ–ฐ้ƒจๅˆ†ๆ•ฐๆฎๅบ”๏ผš +็ฎ€่€Œ่จ€ไน‹๏ผŒๅบ”็”จ้ƒจๅˆ†ๆ›ดๆ–ฐๅบ”ๅฝ“๏ผš -* ไฝฟ็”จ `PATCH` ่€Œไธๆ˜ฏ `PUT` ๏ผˆๅฏ้€‰๏ผŒไนŸๅฏไปฅ็”จ `PUT`๏ผ‰๏ผ› -* ๆๅ–ๅญ˜ๅ‚จ็š„ๆ•ฐๆฎ๏ผ› -* ๆŠŠๆ•ฐๆฎๆ”พๅ…ฅ Pydantic ๆจกๅž‹๏ผ› -* ็”Ÿๆˆไธๅซ่พ“ๅ…ฅๆจกๅž‹้ป˜่ฎคๅ€ผ็š„ `dict` ๏ผˆไฝฟ็”จ `exclude_unset` ๅ‚ๆ•ฐ๏ผ‰๏ผ› - * ๅชๆ›ดๆ–ฐ็”จๆˆท่ฎพ็ฝฎ่ฟ‡็š„ๅ€ผ๏ผŒไธ็”จๆจกๅž‹ไธญ็š„้ป˜่ฎคๅ€ผ่ฆ†็›–ๅทฒๅญ˜ๅ‚จ่ฟ‡็š„ๅ€ผใ€‚ -* ไธบๅทฒๅญ˜ๅ‚จ็š„ๆจกๅž‹ๅˆ›ๅปบๅ‰ฏๆœฌ๏ผŒ็”จๆŽฅๆ”ถ็š„ๆ•ฐๆฎๆ›ดๆ–ฐๅ…ถๅฑžๆ€ง ๏ผˆไฝฟ็”จ `update` ๅ‚ๆ•ฐ๏ผ‰ใ€‚ +* ๏ผˆๅฏ้€‰๏ผ‰ไฝฟ็”จ `PATCH` ่€Œไธๆ˜ฏ `PUT`ใ€‚ +* ๆๅ–ๅทฒๅญ˜ๅ‚จ็š„ๆ•ฐๆฎใ€‚ +* ๆŠŠ่ฏฅๆ•ฐๆฎๆ”พๅ…ฅ Pydantic ๆจกๅž‹ใ€‚ +* ็”Ÿๆˆไธๅซ่พ“ๅ…ฅๆจกๅž‹้ป˜่ฎคๅ€ผ็š„ `dict`๏ผˆไฝฟ็”จ `exclude_unset`๏ผ‰ใ€‚ + * ่ฟ™ๆ ทๅชไผšๆ›ดๆ–ฐ็”จๆˆทๅฎž้™…่ฎพ็ฝฎ็š„ๅ€ผ๏ผŒ่€Œไธไผš็”จๆจกๅž‹ไธญ็š„้ป˜่ฎคๅ€ผ่ฆ†็›–ๅทฒๅญ˜ๅ‚จ็š„ๅ€ผใ€‚ +* ไธบๅทฒๅญ˜ๅ‚จ็š„ๆจกๅž‹ๅˆ›ๅปบๅ‰ฏๆœฌ๏ผŒ็”จๆŽฅๆ”ถๅˆฐ็š„้ƒจๅˆ†ๆ›ดๆ–ฐๆ•ฐๆฎๆ›ดๆ–ฐๅ…ถๅฑžๆ€ง๏ผˆไฝฟ็”จ `update` ๅ‚ๆ•ฐ๏ผ‰ใ€‚ * ๆŠŠๆจกๅž‹ๅ‰ฏๆœฌ่ฝฌๆขไธบๅฏๅญ˜ๅ…ฅๆ•ฐๆฎๅบ“็š„ๅฝขๅผ๏ผˆๆฏ”ๅฆ‚๏ผŒไฝฟ็”จ `jsonable_encoder`๏ผ‰ใ€‚ - * ่ฟ™็งๆ–นๅผไธŽ Pydantic ๆจกๅž‹็š„ `.dict()` ๆ–นๆณ•็ฑปไผผ๏ผŒไฝ†่ƒฝ็กฎไฟๆŠŠๅ€ผ่ฝฌๆขไธบ้€‚้… JSON ็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒไพ‹ๅฆ‚๏ผŒ ๆŠŠ `datetime` ่ฝฌๆขไธบ `str` ใ€‚ -* ๆŠŠๆ•ฐๆฎไฟๅญ˜่‡ณๆ•ฐๆฎๅบ“๏ผ› + * ่ฟ™็ฑปไผผไบŽๅ†ๆฌก่ฐƒ็”จๆจกๅž‹็š„ `.model_dump()` ๆ–นๆณ•๏ผŒไฝ†ไผš็กฎไฟ๏ผˆๅนถ่ฝฌๆข๏ผ‰ๅ€ผไธบๅฏ่ฝฌๆขไธบ JSON ็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒไพ‹ๅฆ‚ๆŠŠ `datetime` ่ฝฌๆขไธบ `str`ใ€‚ +* ๆŠŠๆ•ฐๆฎไฟๅญ˜่‡ณๆ•ฐๆฎๅบ“ใ€‚ * ่ฟ”ๅ›žๆ›ดๆ–ฐๅŽ็š„ๆจกๅž‹ใ€‚ -{* ../../docs_src/body_updates/tutorial002.py hl[30:37] *} +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} /// tip | ๆ็คบ -ๅฎž้™…ไธŠ๏ผŒHTTP `PUT` ไนŸๅฏไปฅๅฎŒๆˆ็›ธๅŒ็š„ๆ“ไฝœใ€‚ -ไฝ†ๆœฌ่Š‚ไปฅ `PATCH` ไธบไพ‹็š„ๅŽŸๅ› ๆ˜ฏ๏ผŒ่ฏฅๆ“ไฝœๅฐฑๆ˜ฏไธบไบ†่ฟ™็ง็”จไพ‹ๅˆ›ๅปบ็š„ใ€‚ +ๅฎž้™…ไธŠ๏ผŒHTTP `PUT` ไนŸๅฏไปฅไฝฟ็”จๅŒๆ ท็š„ๆŠ€ๅทงใ€‚ + +ไฝ†่ฟ™้‡Œ็”จ `PATCH` ไธพไพ‹๏ผŒๅ› ไธบๅฎƒๅฐฑๆ˜ฏไธบ่ฟ™็ง็”จไพ‹่ฎพ่ฎก็š„ใ€‚ /// -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๆณจๆ„๏ผŒ่พ“ๅ…ฅๆจกๅž‹ไป้œ€้ชŒ่ฏใ€‚ +ๆณจๆ„๏ผŒ่พ“ๅ…ฅๆจกๅž‹ไปไผš่ขซ้ชŒ่ฏใ€‚ -ๅ› ๆญค๏ผŒๅฆ‚ๆžœๅธŒๆœ›ๆŽฅๆ”ถ็š„้ƒจๅˆ†ๆ›ดๆ–ฐๆ•ฐๆฎๅฏไปฅ็œ็•ฅๅ…ถไป–ๆ‰€ๆœ‰ๅฑžๆ€ง๏ผŒๅˆ™่ฆๆŠŠๆจกๅž‹ไธญๆ‰€ๆœ‰็š„ๅฑžๆ€งๆ ‡่ฎฐไธบๅฏ้€‰๏ผˆไฝฟ็”จ้ป˜่ฎคๅ€ผๆˆ– `None`๏ผ‰ใ€‚ +ๅ› ๆญค๏ผŒๅฆ‚ๆžœๅธŒๆœ›ๆŽฅๆ”ถ็š„้ƒจๅˆ†ๆ›ดๆ–ฐๅฏไปฅ็œ็•ฅๆ‰€ๆœ‰ๅฑžๆ€ง๏ผŒๅˆ™้œ€่ฆไธ€ไธชๆ‰€ๆœ‰ๅฑžๆ€ง้ƒฝๆ ‡่ฎฐไธบๅฏ้€‰๏ผˆๅธฆ้ป˜่ฎคๅ€ผๆˆ– `None`๏ผ‰็š„ๆจกๅž‹ใ€‚ -ไธบไบ†ๅŒบๅˆ†็”จไบŽ**ๆ›ดๆ–ฐ**ๆ‰€ๆœ‰ๅฏ้€‰ๅ€ผ็š„ๆจกๅž‹ไธŽ็”จไบŽ**ๅˆ›ๅปบ**ๅŒ…ๅซๅฟ…้€‰ๅ€ผ็š„ๆจกๅž‹๏ผŒ่ฏทๅ‚็…ง[ๆ›ดๅคšๆจกๅž‹](extra-models.md){.internal-link target=_blank} ไธ€่Š‚ไธญ็š„ๆ€่ทฏใ€‚ +ไธบไบ†ๅŒบๅˆ†็”จไบŽ**ๆ›ดๆ–ฐ**๏ผˆๅ…จ้ƒจๅฏ้€‰๏ผ‰ๅ’Œ็”จไบŽ**ๅˆ›ๅปบ**๏ผˆๅฟ…ๅกซ๏ผ‰็š„ๆจกๅž‹๏ผŒๅฏไปฅๅ‚่€ƒ[ๆ›ดๅคšๆจกๅž‹](extra-models.md){.internal-link target=_blank} ไธญไป‹็ป็š„ๆ€่ทฏใ€‚ /// diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md index 3820fc7477..60088a0482 100644 --- a/docs/zh/docs/tutorial/body.md +++ b/docs/zh/docs/tutorial/body.md @@ -1,30 +1,30 @@ -# ่ฏทๆฑ‚ไฝ“ +# ่ฏทๆฑ‚ไฝ“ { #request-body } -FastAPI ไฝฟ็”จ**่ฏทๆฑ‚ไฝ“**ไปŽๅฎขๆˆท็ซฏ๏ผˆไพ‹ๅฆ‚ๆต่งˆๅ™จ๏ผ‰ๅ‘ API ๅ‘้€ๆ•ฐๆฎใ€‚ +ๅฝ“ไฝ ้œ€่ฆไปŽๅฎขๆˆท็ซฏ๏ผˆๆฏ”ๅฆ‚ๆต่งˆๅ™จ๏ผ‰ๅ‘ไฝ ็š„ API ๅ‘้€ๆ•ฐๆฎๆ—ถ๏ผŒไผšๆŠŠๅฎƒไฝœไธบ**่ฏทๆฑ‚ไฝ“**ๅ‘้€ใ€‚ -**่ฏทๆฑ‚ไฝ“**ๆ˜ฏๅฎขๆˆท็ซฏๅ‘้€็ป™ API ็š„ๆ•ฐๆฎใ€‚**ๅ“ๅบ”ไฝ“**ๆ˜ฏ API ๅ‘้€็ป™ๅฎขๆˆท็ซฏ็š„ๆ•ฐๆฎใ€‚ +**่ฏทๆฑ‚ไฝ“**ๆ˜ฏๅฎขๆˆท็ซฏๅ‘้€็ป™ไฝ ็š„ API ็š„ๆ•ฐๆฎใ€‚**ๅ“ๅบ”ไฝ“**ๆ˜ฏไฝ ็š„ API ๅ‘้€็ป™ๅฎขๆˆท็ซฏ็š„ๆ•ฐๆฎใ€‚ -API ๅŸบๆœฌไธŠ่‚ฏๅฎš่ฆๅ‘้€**ๅ“ๅบ”ไฝ“**๏ผŒไฝ†ๆ˜ฏๅฎขๆˆท็ซฏไธไธ€ๅฎšๅ‘้€**่ฏทๆฑ‚ไฝ“**ใ€‚ +ไฝ ็š„ API ๅ‡ ไนŽๆ€ปๆ˜ฏ้œ€่ฆๅ‘้€**ๅ“ๅบ”ไฝ“**ใ€‚ไฝ†ๅฎขๆˆท็ซฏไธไธ€ๅฎšๆ€ปๆ˜ฏ่ฆๅ‘้€**่ฏทๆฑ‚ไฝ“**๏ผŒๆœ‰ๆ—ถๅฎƒไปฌๅช่ฏทๆฑ‚ๆŸไธช่ทฏๅพ„๏ผŒๅฏ่ƒฝๅธฆไธ€ไบ›ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒไฝ†ไธไผšๅ‘้€่ฏทๆฑ‚ไฝ“ใ€‚ -ไฝฟ็”จ Pydantic ๆจกๅž‹ๅฃฐๆ˜Ž**่ฏทๆฑ‚ไฝ“**๏ผŒ่ƒฝๅ……ๅˆ†ๅˆฉ็”จๅฎƒ็š„ๅŠŸ่ƒฝๅ’Œไผ˜็‚นใ€‚ +ไฝฟ็”จ Pydantic ๆจกๅž‹ๆฅๅฃฐๆ˜Ž**่ฏทๆฑ‚ไฝ“**๏ผŒ่ƒฝๅ……ๅˆ†ๅˆฉ็”จๅฎƒ็š„ๅŠŸ่ƒฝๅ’Œไผ˜็‚นใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๅ‘้€ๆ•ฐๆฎไฝฟ็”จ `POST`๏ผˆๆœ€ๅธธ็”จ๏ผ‰ใ€`PUT`ใ€`DELETE`ใ€`PATCH` ็ญ‰ๆ“ไฝœใ€‚ +ๅ‘้€ๆ•ฐๆฎๅบ”ไฝฟ็”จไปฅไธ‹ไน‹ไธ€๏ผš`POST`๏ผˆๆœ€ๅธธ่ง๏ผ‰ใ€`PUT`ใ€`DELETE` ๆˆ– `PATCH`ใ€‚ -่ง„่Œƒไธญๆฒกๆœ‰ๅฎšไน‰ไฝฟ็”จ `GET` ๅ‘้€่ฏทๆฑ‚ไฝ“็š„ๆ“ไฝœ๏ผŒไฝ†ไธ็ฎกๆ€Žๆ ท๏ผŒFastAPI ไนŸๆ”ฏๆŒ่ฟ™็งๆ–นๅผ๏ผŒๅชไธ่ฟ‡ไป…็”จไบŽ้žๅธธๅคๆ‚ๆˆ–ๆž็ซฏ็š„็”จไพ‹ใ€‚ +่ง„่Œƒไธญๆฒกๆœ‰ๅฎšไน‰็”จ `GET` ่ฏทๆฑ‚ๅ‘้€่ฏทๆฑ‚ไฝ“็š„่กŒไธบ๏ผŒไฝ† FastAPI ไปๆ”ฏๆŒ่ฟ™็งๆ–นๅผ๏ผŒๅช็”จไบŽ้žๅธธๅคๆ‚/ๆž็ซฏ็š„็”จไพ‹ใ€‚ -ๆˆ‘ไปฌไธๅปบ่ฎฎไฝฟ็”จ `GET`๏ผŒๅ› ๆญค๏ผŒๅœจ Swagger UI ไบคไบ’ๆ–‡ๆกฃไธญไธไผšๆ˜พ็คบๆœ‰ๅ…ณ `GET` ็š„ๅ†…ๅฎน๏ผŒ่€Œไธ”ไปฃ็†ๅ่ฎฎไนŸไธไธ€ๅฎšๆ”ฏๆŒ `GET`ใ€‚ +็”ฑไบŽไธๆŽจ่๏ผŒๅœจไฝฟ็”จ `GET` ๆ—ถ๏ผŒSwagger UI ็š„ไบคไบ’ๅผๆ–‡ๆกฃไธไผšๆ˜พ็คบ่ฏทๆฑ‚ไฝ“็š„ๆ–‡ๆกฃ๏ผŒ่€Œไธ”ไธญ้—ด็š„ไปฃ็†ๅฏ่ƒฝไนŸไธๆ”ฏๆŒๅฎƒใ€‚ /// -## ๅฏผๅ…ฅ Pydantic ็š„ `BaseModel` +## ๅฏผๅ…ฅ Pydantic ็š„ `BaseModel` { #import-pydantics-basemodel } ไปŽ `pydantic` ไธญๅฏผๅ…ฅ `BaseModel`๏ผš {* ../../docs_src/body/tutorial001_py310.py hl[2] *} -## ๅˆ›ๅปบๆ•ฐๆฎๆจกๅž‹ +## ๅˆ›ๅปบๆ•ฐๆฎๆจกๅž‹ { #create-your-data-model } ๆŠŠๆ•ฐๆฎๆจกๅž‹ๅฃฐๆ˜Žไธบ็ปงๆ‰ฟ `BaseModel` ็š„็ฑปใ€‚ @@ -32,9 +32,9 @@ API ๅŸบๆœฌไธŠ่‚ฏๅฎš่ฆๅ‘้€**ๅ“ๅบ”ไฝ“**๏ผŒไฝ†ๆ˜ฏๅฎขๆˆท็ซฏไธไธ€ๅฎšๅ‘้€**่ฏท {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} -ไธŽๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐไธ€ๆ ท๏ผŒๅŒ…ๅซ้ป˜่ฎคๅ€ผ็š„ๆจกๅž‹ๅฑžๆ€งๆ˜ฏๅฏ้€‰็š„๏ผŒๅฆๅˆ™ๅฐฑๆ˜ฏๅฟ…้€‰็š„ใ€‚้ป˜่ฎคๅ€ผไธบ `None` ็š„ๆจกๅž‹ๅฑžๆ€งไนŸๆ˜ฏๅฏ้€‰็š„ใ€‚ +ไธŽๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐไธ€ๆ ท๏ผŒๅŒ…ๅซ้ป˜่ฎคๅ€ผ็š„ๆจกๅž‹ๅฑžๆ€งๆ˜ฏๅฏ้€‰็š„๏ผŒๅฆๅˆ™ๅฐฑๆ˜ฏๅฟ…้€‰็š„ใ€‚ๆŠŠ้ป˜่ฎคๅ€ผ่ฎพไธบ `None` ๅฏไฝฟๅ…ถๅ˜ไธบๅฏ้€‰ใ€‚ -ไพ‹ๅฆ‚๏ผŒไธŠ่ฟฐๆจกๅž‹ๅฃฐๆ˜Žๅฆ‚ไธ‹ JSON **ๅฏน่ฑก**๏ผˆๅณ Python **ๅญ—ๅ…ธ**๏ผ‰๏ผš +ไพ‹ๅฆ‚๏ผŒไธŠ่ฟฐๆจกๅž‹ๅฃฐๆ˜Žๅฆ‚ไธ‹ JSON "object"๏ผˆๅณ Python `dict`๏ผ‰๏ผš ```JSON { @@ -45,7 +45,7 @@ API ๅŸบๆœฌไธŠ่‚ฏๅฎš่ฆๅ‘้€**ๅ“ๅบ”ไฝ“**๏ผŒไฝ†ๆ˜ฏๅฎขๆˆท็ซฏไธไธ€ๅฎšๅ‘้€**่ฏท } ``` -โ€ฆโ€ฆ็”ฑไบŽ `description` ๅ’Œ `tax` ๆ˜ฏๅฏ้€‰็š„๏ผˆ้ป˜่ฎคๅ€ผไธบ `None`๏ผ‰๏ผŒไธ‹้ข็š„ JSON **ๅฏน่ฑก**ไนŸๆœ‰ๆ•ˆ๏ผš +...็”ฑไบŽ `description` ๅ’Œ `tax` ๆ˜ฏๅฏ้€‰็š„๏ผˆ้ป˜่ฎคๅ€ผไธบ `None`๏ผ‰๏ผŒไธ‹้ข็š„ JSON "object" ไนŸๆœ‰ๆ•ˆ๏ผš ```JSON { @@ -54,40 +54,40 @@ API ๅŸบๆœฌไธŠ่‚ฏๅฎš่ฆๅ‘้€**ๅ“ๅบ”ไฝ“**๏ผŒไฝ†ๆ˜ฏๅฎขๆˆท็ซฏไธไธ€ๅฎšๅ‘้€**่ฏท } ``` -## ๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ +## ๅฃฐๆ˜Žไธบๅ‚ๆ•ฐ { #declare-it-as-a-parameter } -ไฝฟ็”จไธŽๅฃฐๆ˜Ž่ทฏๅพ„ๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ็›ธๅŒ็š„ๆ–นๅผๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“๏ผŒๆŠŠ่ฏทๆฑ‚ไฝ“ๆทปๅŠ ่‡ณ*่ทฏๅพ„ๆ“ไฝœ*๏ผš +ไฝฟ็”จไธŽๅฃฐๆ˜Ž่ทฏๅพ„ๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ็›ธๅŒ็š„ๆ–นๅผ๏ผŒๆŠŠๅฎƒๆทปๅŠ ่‡ณ*่ทฏๅพ„ๆ“ไฝœ*๏ผš {* ../../docs_src/body/tutorial001_py310.py hl[16] *} -โ€ฆโ€ฆๆญคๅค„๏ผŒ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ็š„็ฑปๅž‹ไธบ `Item` ๆจกๅž‹ใ€‚ +...ๅนถๆŠŠๅ…ถ็ฑปๅž‹ๅฃฐๆ˜Žไธบไฝ ๅˆ›ๅปบ็š„ๆจกๅž‹ `Item`ใ€‚ -## ็ป“่ฎบ +## ็ป“ๆžœ { #results } -ไป…ไฝฟ็”จ Python ็ฑปๅž‹ๅฃฐๆ˜Ž๏ผŒ**FastAPI** ๅฐฑๅฏไปฅ๏ผš +ไป…ไฝฟ็”จ่ฟ™ไบ› Python ็ฑปๅž‹ๅฃฐๆ˜Ž๏ผŒ**FastAPI** ๅฐฑๅฏไปฅ๏ผš -* ไปฅ JSON ๅฝขๅผ่ฏปๅ–่ฏทๆฑ‚ไฝ“ -* ๏ผˆๅœจๅฟ…่ฆๆ—ถ๏ผ‰ๆŠŠ่ฏทๆฑ‚ไฝ“่ฝฌๆขไธบๅฏนๅบ”็š„็ฑปๅž‹ -* ๆ ก้ชŒๆ•ฐๆฎ๏ผš - * ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถ่ฟ”ๅ›ž้”™่ฏฏไฟกๆฏ๏ผŒๅนถๆŒ‡ๅ‡บ้”™่ฏฏๆ•ฐๆฎ็š„็กฎๅˆ‡ไฝ็ฝฎๅ’Œๅ†…ๅฎน -* ๆŠŠๆŽฅๆ”ถ็š„ๆ•ฐๆฎ่ต‹ๅ€ผ็ป™ๅ‚ๆ•ฐ `item` - * ๆŠŠๅ‡ฝๆ•ฐไธญ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `Item`๏ผŒ่ฟ˜่ƒฝ่Žทๅพ—ไปฃ็ ่กฅๅ…จ็ญ‰็ผ–่พ‘ๅ™จๆ”ฏๆŒ -* ไธบๆจกๅž‹็”Ÿๆˆ JSON Schema๏ผŒๅœจ้กน็›ฎไธญๆ‰€้œ€็š„ไฝ็ฝฎไฝฟ็”จ -* ่ฟ™ไบ›ๆฆ‚ๅ›พๆ˜ฏ OpenAPI ๆฆ‚ๅ›พ็š„้ƒจไปถ๏ผŒ็”จไบŽ API ๆ–‡ๆกฃ UI +* ไปฅ JSON ๅฝขๅผ่ฏปๅ–่ฏทๆฑ‚ไฝ“ใ€‚ +* ๏ผˆๅœจๅฟ…่ฆๆ—ถ๏ผ‰ๆŠŠ่ฏทๆฑ‚ไฝ“่ฝฌๆขไธบๅฏนๅบ”็š„็ฑปๅž‹ใ€‚ +* ๆ ก้ชŒๆ•ฐๆฎใ€‚ + * ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถ่ฟ”ๅ›žๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏ๏ผŒๅนถๆŒ‡ๅ‡บ้”™่ฏฏๆ•ฐๆฎ็š„็กฎๅˆ‡ไฝ็ฝฎๅ’Œๅ†…ๅฎนใ€‚ +* ๆŠŠๆŽฅๆ”ถ็š„ๆ•ฐๆฎ่ต‹ๅ€ผ็ป™ๅ‚ๆ•ฐ `item`ใ€‚ + * ๅ› ไธบไฝ ๆŠŠๅ‡ฝๆ•ฐไธญ็š„ๅ‚ๆ•ฐ็ฑปๅž‹ๅฃฐๆ˜Žไธบ `Item`๏ผŒๆ‰€ไปฅ่ฟ˜่ƒฝ่Žทๅพ—ๆ‰€ๆœ‰ๅฑžๆ€งๅŠๅ…ถ็ฑปๅž‹็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผˆ่กฅๅ…จ็ญ‰๏ผ‰ใ€‚ +* ไธบไฝ ็š„ๆจกๅž‹็”Ÿๆˆ JSON Schema ๅฎšไน‰๏ผŒๅฆ‚ๆžœๅฏนไฝ ็š„้กน็›ฎๆœ‰ๆ„ไน‰๏ผŒ่ฟ˜ๅฏไปฅๅœจๅ…ถไป–ๅœฐๆ–นไฝฟ็”จๅฎƒไปฌใ€‚ +* ่ฟ™ไบ› schema ไผšๆˆไธบ็”Ÿๆˆ็š„ OpenAPI Schema ็š„ไธ€้ƒจๅˆ†๏ผŒๅนถ่ขซ่‡ชๅŠจๆ–‡ๆกฃ็š„ UIs ไฝฟ็”จใ€‚ -## API ๆ–‡ๆกฃ +## ่‡ชๅŠจๆ–‡ๆกฃ { #automatic-docs } -Pydantic ๆจกๅž‹็š„ JSON ๆฆ‚ๅ›พๆ˜ฏ OpenAPI ็”Ÿๆˆ็š„ๆฆ‚ๅ›พ้ƒจไปถ๏ผŒๅฏๅœจ API ๆ–‡ๆกฃไธญๆ˜พ็คบ๏ผš +ไฝ ็š„ๆจกๅž‹็š„ JSON Schema ไผšๆˆไธบ็”Ÿๆˆ็š„ OpenAPI Schema ็š„ไธ€้ƒจๅˆ†๏ผŒๅนถๆ˜พ็คบๅœจไบคไบ’ๅผ API ๆ–‡ๆกฃไธญ๏ผš -่€Œไธ”๏ผŒ่ฟ˜ไผš็”จไบŽ API ๆ–‡ๆกฃไธญไฝฟ็”จไบ†ๆฆ‚ๅ›พ็š„*่ทฏๅพ„ๆ“ไฝœ*๏ผš +ๅนถไธ”๏ผŒ่ฟ˜ไผš็”จไบŽ้œ€่ฆๅฎƒไปฌ็š„ๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„ API ๆ–‡ๆกฃไธญ๏ผš -## ็ผ–่พ‘ๅ™จๆ”ฏๆŒ +## ็ผ–่พ‘ๅ™จๆ”ฏๆŒ { #editor-support } -ๅœจ็ผ–่พ‘ๅ™จไธญ๏ผŒๅ‡ฝๆ•ฐๅ†…้ƒจๅ‡ๅฏไฝฟ็”จ็ฑปๅž‹ๆ็คบใ€ไปฃ็ ่กฅๅ…จ๏ผˆๅฆ‚ๆžœๆŽฅๆ”ถ็š„ไธๆ˜ฏ Pydantic ๆจกๅž‹๏ผŒ่€Œๆ˜ฏ**ๅญ—ๅ…ธ**๏ผŒๅฐฑๆฒกๆœ‰่ฟ™ๆ ท็š„ๆ”ฏๆŒ๏ผ‰๏ผš +ๅœจ็ผ–่พ‘ๅ™จไธญ๏ผŒๅ‡ฝๆ•ฐๅ†…้ƒจไฝ ไผšๅœจๅ„ๅค„ๅพ—ๅˆฐ็ฑปๅž‹ๆ็คบไธŽ่กฅๅ…จ๏ผˆๅฆ‚ๆžœๆŽฅๆ”ถ็š„ไธๆ˜ฏ Pydantic ๆจกๅž‹๏ผŒ่€Œๆ˜ฏ `dict`๏ผŒๅฐฑไธไผšๆœ‰่ฟ™ๆ ท็š„ๆ”ฏๆŒ๏ผ‰๏ผš @@ -95,23 +95,23 @@ Pydantic ๆจกๅž‹็š„ JSON ๆฆ‚ๅ›พๆ˜ฏ OpenAPI ็”Ÿๆˆ็š„ๆฆ‚ๅ›พ้ƒจไปถ๏ผŒๅฏๅœจ API ๆ–‡ -่ฟ™ๅนถ้žๅถ็„ถ๏ผŒๆ•ดไธช **FastAPI** ๆก†ๆžถ้ƒฝๆ˜ฏๅ›ด็ป•่ฟ™็งๆ€่ทฏ็ฒพๅฟƒ่ฎพ่ฎก็š„ใ€‚ +่ฟ™ๅนถ้žๅถ็„ถ๏ผŒๆ•ดไธชๆก†ๆžถ้ƒฝๆ˜ฏๅ›ด็ป•่ฟ™็ง่ฎพ่ฎกๆž„ๅปบ็š„ใ€‚ -ๅนถไธ”๏ผŒๅœจ FastAPI ็š„่ฎพ่ฎก้˜ถๆฎต๏ผŒๆˆ‘ไปฌๅฐฑๅทฒ็ป่ฟ›่กŒไบ†ๅ…จ้ขๆต‹่ฏ•๏ผŒไปฅ็กฎไฟ FastAPI ๅฏไปฅ่Žทๅพ—ๆ‰€ๆœ‰็ผ–่พ‘ๅ™จ็š„ๆ”ฏๆŒใ€‚ +ๅนถไธ”ๅœจ่ฎพ่ฎก้˜ถๆฎตใ€ๅฎž็Žฐไน‹ๅ‰ๅฐฑ่ฟ›่กŒไบ†ๅ…จ้ขๆต‹่ฏ•๏ผŒไปฅ็กฎไฟๅฎƒ่ƒฝๅœจๆ‰€ๆœ‰็ผ–่พ‘ๅ™จไธญๆญฃๅธธๅทฅไฝœใ€‚ -ๆˆ‘ไปฌ่ฟ˜ๆ”น่ฟ›ไบ† Pydantic๏ผŒ่ฎฉๅฎƒไนŸๆ”ฏๆŒ่ฟ™ไบ›ๅŠŸ่ƒฝใ€‚ +ๆˆ‘ไปฌ็”š่‡ณๅฏน Pydantic ๆœฌ่บซๅšไบ†ไธ€ไบ›ๆ”นๅŠจไปฅๆ”ฏๆŒ่ฟ™ไบ›ๅŠŸ่ƒฝใ€‚ -่™ฝ็„ถไธŠ้ข็š„ๆˆชๅ›พๅ–่‡ช Visual Studio Codeใ€‚ +ไธŠ้ข็š„ๆˆชๅ›พๆฅ่‡ช Visual Studio Codeใ€‚ -ไฝ† PyCharm ๅ’Œๅคงๅคšๆ•ฐ Python ็ผ–่พ‘ๅ™จไนŸๆ”ฏๆŒๅŒๆ ท็š„ๅŠŸ่ƒฝ๏ผš +ไฝ†ไฝฟ็”จ PyCharm ๅ’Œๅคงๅคšๆ•ฐๅ…ถไป– Python ็ผ–่พ‘ๅ™จ๏ผŒไฝ ไนŸไผš่Žทๅพ—็›ธๅŒ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผš /// tip | ๆ็คบ -ไฝฟ็”จ PyCharm ็ผ–่พ‘ๅ™จๆ—ถ๏ผŒๆŽจ่ๅฎ‰่ฃ… Pydantic PyCharm ๆ’ไปถใ€‚ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ PyCharm ไฝœไธบ็ผ–่พ‘ๅ™จ๏ผŒๅฏไปฅไฝฟ็”จ Pydantic PyCharm ๆ’ไปถใ€‚ -่ฏฅๆ’ไปถ็”จไบŽๅฎŒๅ–„ PyCharm ๅฏน Pydantic ๆจกๅž‹็š„ๆ”ฏๆŒ๏ผŒไผ˜ๅŒ–็š„ๅŠŸ่ƒฝๅฆ‚ไธ‹๏ผš +ๅฎƒ่ƒฝๆ”น่ฟ›ๅฏน Pydantic ๆจกๅž‹็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผŒๅŒ…ๆ‹ฌ๏ผš * ่‡ชๅŠจ่กฅๅ…จ * ็ฑปๅž‹ๆฃ€ๆŸฅ @@ -121,42 +121,44 @@ Pydantic ๆจกๅž‹็š„ JSON ๆฆ‚ๅ›พๆ˜ฏ OpenAPI ็”Ÿๆˆ็š„ๆฆ‚ๅ›พ้ƒจไปถ๏ผŒๅฏๅœจ API ๆ–‡ /// -## ไฝฟ็”จๆจกๅž‹ +## ไฝฟ็”จๆจกๅž‹ { #use-the-model } -ๅœจ*่ทฏๅพ„ๆ“ไฝœ*ๅ‡ฝๆ•ฐๅ†…้ƒจ็›ดๆŽฅ่ฎฟ้—ฎๆจกๅž‹ๅฏน่ฑก็š„ๅฑžๆ€ง๏ผš +ๅœจ*่ทฏๅพ„ๆ“ไฝœ*ๅ‡ฝๆ•ฐๅ†…้ƒจ็›ดๆŽฅ่ฎฟ้—ฎๆจกๅž‹ๅฏน่ฑก็š„ๆ‰€ๆœ‰ๅฑžๆ€ง๏ผš -{* ../../docs_src/body/tutorial002_py310.py hl[19] *} +{* ../../docs_src/body/tutorial002_py310.py *} -## ่ฏทๆฑ‚ไฝ“ + ่ทฏๅพ„ๅ‚ๆ•ฐ +## ่ฏทๆฑ‚ไฝ“ + ่ทฏๅพ„ๅ‚ๆ•ฐ { #request-body-path-parameters } -**FastAPI** ๆ”ฏๆŒๅŒๆ—ถๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“ใ€‚ +ๅฏไปฅๅŒๆ—ถๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“ใ€‚ -**FastAPI** ่ƒฝ่ฏ†ๅˆซไธŽ**่ทฏๅพ„ๅ‚ๆ•ฐ**ๅŒน้…็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ๏ผŒ่ฟ˜่ƒฝ่ฏ†ๅˆซไปŽ**่ฏทๆฑ‚ไฝ“**ไธญ่Žทๅ–็š„็ฑปๅž‹ไธบ Pydantic ๆจกๅž‹็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐใ€‚ +**FastAPI** ่ƒฝ่ฏ†ๅˆซไธŽ**่ทฏๅพ„ๅ‚ๆ•ฐ**ๅŒน้…็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐๅบ”่ฏฅ**ไปŽ่ทฏๅพ„ไธญ่Žทๅ–**๏ผŒ่€Œๅฃฐๆ˜Žไธบ Pydantic ๆจกๅž‹็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐๅบ”่ฏฅ**ไปŽ่ฏทๆฑ‚ไฝ“ไธญ่Žทๅ–**ใ€‚ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} -## ่ฏทๆฑ‚ไฝ“ + ่ทฏๅพ„ๅ‚ๆ•ฐ + ๆŸฅ่ฏขๅ‚ๆ•ฐ +## ่ฏทๆฑ‚ไฝ“ + ่ทฏๅพ„ + ๆŸฅ่ฏขๅ‚ๆ•ฐ { #request-body-path-query-parameters } -**FastAPI** ๆ”ฏๆŒๅŒๆ—ถๅฃฐๆ˜Ž**่ฏทๆฑ‚ไฝ“**ใ€**่ทฏๅพ„ๅ‚ๆ•ฐ**ๅ’Œ**ๆŸฅ่ฏขๅ‚ๆ•ฐ**ใ€‚ +ไนŸๅฏไปฅๅŒๆ—ถๅฃฐๆ˜Ž**่ฏทๆฑ‚ไฝ“**ใ€**่ทฏๅพ„**ๅ’Œ**ๆŸฅ่ฏข**ๅ‚ๆ•ฐใ€‚ -**FastAPI** ่ƒฝๅคŸๆญฃ็กฎ่ฏ†ๅˆซ่ฟ™ไธ‰็งๅ‚ๆ•ฐ๏ผŒๅนถไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่Žทๅ–ๆ•ฐๆฎใ€‚ +**FastAPI** ไผšๅˆ†ๅˆซ่ฏ†ๅˆซๅฎƒไปฌ๏ผŒๅนถไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่Žทๅ–ๆ•ฐๆฎใ€‚ {* ../../docs_src/body/tutorial004_py310.py hl[16] *} ๅ‡ฝๆ•ฐๅ‚ๆ•ฐๆŒ‰ๅฆ‚ไธ‹่ง„ๅˆ™่ฟ›่กŒ่ฏ†ๅˆซ๏ผš -- **่ทฏๅพ„**ไธญๅฃฐๆ˜Žไบ†็›ธๅŒๅ‚ๆ•ฐ็š„ๅ‚ๆ•ฐ๏ผŒๆ˜ฏ่ทฏๅพ„ๅ‚ๆ•ฐ -- ็ฑปๅž‹ๆ˜ฏ๏ผˆ`int`ใ€`float`ใ€`str`ใ€`bool` ็ญ‰๏ผ‰**ๅ•็ฑปๅž‹**็š„ๅ‚ๆ•ฐ๏ผŒๆ˜ฏ**ๆŸฅ่ฏข**ๅ‚ๆ•ฐ -- ็ฑปๅž‹ๆ˜ฏ **Pydantic ๆจกๅž‹**็š„ๅ‚ๆ•ฐ๏ผŒๆ˜ฏ**่ฏทๆฑ‚ไฝ“** +* ๅฆ‚ๆžœ่ฏฅๅ‚ๆ•ฐไนŸๅœจ**่ทฏๅพ„**ไธญๅฃฐๆ˜Žไบ†๏ผŒๅฎƒๅฐฑๆ˜ฏ่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ +* ๅฆ‚ๆžœ่ฏฅๅ‚ๆ•ฐๆ˜ฏ๏ผˆ`int`ใ€`float`ใ€`str`ใ€`bool` ็ญ‰๏ผ‰**ๅ•ไธ€็ฑปๅž‹**๏ผŒๅฎƒไผš่ขซๅฝ“ไฝœ**ๆŸฅ่ฏข**ๅ‚ๆ•ฐใ€‚ +* ๅฆ‚ๆžœ่ฏฅๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ **Pydantic ๆจกๅž‹**๏ผŒๅฎƒไผš่ขซๅฝ“ไฝœ่ฏทๆฑ‚**ไฝ“**ใ€‚ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๅ› ไธบ้ป˜่ฎคๅ€ผๆ˜ฏ `None`๏ผŒ FastAPI ไผšๆŠŠ `q` ๅฝ“ไฝœๅฏ้€‰ๅ‚ๆ•ฐใ€‚ +FastAPI ไผšๆ นๆฎ้ป˜่ฎคๅ€ผ `= None` ็Ÿฅ้“ `q` ็š„ๅ€ผไธๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ -FastAPI ไธไฝฟ็”จ `Optional[str]` ไธญ็š„ `Optional`๏ผŒ ไฝ† `Optional` ๅฏไปฅ่ฎฉ็ผ–่พ‘ๅ™จๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒ๏ผŒๅนถๆฃ€ๆต‹้”™่ฏฏใ€‚ +`str | None`๏ผˆPython 3.10+๏ผ‰ๆˆ– `Union[str, None]`๏ผˆPython 3.9+ ไธญ็š„ `Union`๏ผ‰ๅนถไธๆ˜ฏ FastAPI ็”จๆฅๅˆคๆ–ญๆ˜ฏๅฆๅฟ…ๅกซ็š„ไพๆฎ๏ผ›ๆ˜ฏๅฆๅฟ…ๅกซ็”ฑๆ˜ฏๅฆๆœ‰้ป˜่ฎคๅ€ผ `= None` ๅ†ณๅฎšใ€‚ + +ไฝ†ๆทปๅŠ ่ฟ™ไบ›็ฑปๅž‹ๆณจ่งฃๅฏไปฅ่ฎฉไฝ ็š„็ผ–่พ‘ๅ™จๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒๅนถๆฃ€ๆต‹้”™่ฏฏใ€‚ /// -## ไธไฝฟ็”จ Pydantic +## ไธไฝฟ็”จ Pydantic { #without-pydantic } -ๅณไพฟไธไฝฟ็”จ Pydantic ๆจกๅž‹ไนŸ่ƒฝไฝฟ็”จ **Body** ๅ‚ๆ•ฐใ€‚่ฏฆ่ง[่ฏทๆฑ‚ไฝ“ - ๅคšๅ‚ๆ•ฐ๏ผš่ฏทๆฑ‚ไฝ“ไธญ็š„ๅ•ๅ€ผ](body-multiple-params.md#_2){.internal-link target=\_blank}ใ€‚ +ๅณไพฟไธไฝฟ็”จ Pydantic ๆจกๅž‹ไนŸ่ƒฝไฝฟ็”จ **Body** ๅ‚ๆ•ฐใ€‚่ฏฆ่ง[่ฏทๆฑ‚ไฝ“ - ๅคšๅ‚ๆ•ฐ๏ผš่ฏทๆฑ‚ไฝ“ไธญ็š„ๅ•ๅ€ผ](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh/docs/tutorial/cookie-param-models.md b/docs/zh/docs/tutorial/cookie-param-models.md index 6a7b09e257..707a6a9c79 100644 --- a/docs/zh/docs/tutorial/cookie-param-models.md +++ b/docs/zh/docs/tutorial/cookie-param-models.md @@ -1,22 +1,22 @@ -# Cookie ๅ‚ๆ•ฐๆจกๅž‹ +# Cookie ๅ‚ๆ•ฐๆจกๅž‹ { #cookie-parameter-models } ๅฆ‚ๆžœๆ‚จๆœ‰ไธ€็ป„็›ธๅ…ณ็š„ **cookie**๏ผŒๆ‚จๅฏไปฅๅˆ›ๅปบไธ€ไธช **Pydantic ๆจกๅž‹**ๆฅๅฃฐๆ˜Žๅฎƒไปฌใ€‚๐Ÿช ่ฟ™ๅฐ†ๅ…่ฎธๆ‚จๅœจ**ๅคšไธชๅœฐๆ–น**่ƒฝๅคŸ**้‡็”จๆจกๅž‹**๏ผŒๅนถไธ”ๅฏไปฅไธ€ๆฌกๆ€งๅฃฐๆ˜Žๆ‰€ๆœ‰ๅ‚ๆ•ฐ็š„้ชŒ่ฏๆ–นๅผๅ’Œๅ…ƒๆ•ฐๆฎใ€‚๐Ÿ˜Ž -/// note +/// note | ๆณจๆ„ ่‡ช FastAPI ็‰ˆๆœฌ `0.115.0` ่ตทๆ”ฏๆŒๆญคๅŠŸ่ƒฝใ€‚๐Ÿค“ /// -/// tip +/// tip | ๆ็คบ ๆญคๆŠ€ๆœฏๅŒๆ ท้€‚็”จไบŽ `Query` ใ€ `Cookie` ๅ’Œ `Header` ใ€‚๐Ÿ˜Ž /// -## ๅธฆๆœ‰ Pydantic ๆจกๅž‹็š„ Cookie +## ๅธฆๆœ‰ Pydantic ๆจกๅž‹็š„ Cookie { #cookies-with-a-pydantic-model } ๅœจ **Pydantic** ๆจกๅž‹ไธญๅฃฐๆ˜Žๆ‰€้œ€็š„ **cookie** ๅ‚ๆ•ฐ๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Cookie` ๏ผš @@ -24,7 +24,7 @@ **FastAPI** ๅฐ†ไปŽ่ฏทๆฑ‚ไธญๆŽฅๆ”ถๅˆฐ็š„ **cookie** ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๆไพ›ๆ‚จๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ -## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } ๆ‚จๅฏไปฅๅœจๆ–‡ๆกฃ UI ็š„ `/docs` ไธญๆŸฅ็œ‹ๅฎšไน‰็š„ cookie๏ผš @@ -32,7 +32,7 @@
-/// info +/// info | ไฟกๆฏ ่ฏท่ฎฐไฝ๏ผŒ็”ฑไบŽ**ๆต่งˆๅ™จ**ไปฅ็‰นๆฎŠๆ–นๅผ**ๅค„็† cookie**๏ผŒๅนถๅœจๅŽๅฐ่ฟ›่กŒๆ“ไฝœ๏ผŒๅ› ๆญคๅฎƒไปฌ**ไธไผš**่ฝปๆ˜“ๅ…่ฎธ **JavaScript** ่ฎฟ้—ฎ่ฟ™ไบ› cookieใ€‚ @@ -42,7 +42,7 @@ /// -## ็ฆๆญข้ขๅค–็š„ Cookie +## ็ฆๆญข้ขๅค–็š„ Cookie { #forbid-extra-cookies } ๅœจๆŸไบ›็‰นๆฎŠไฝฟ็”จๆƒ…ๅ†ตไธ‹๏ผˆๅฏ่ƒฝๅนถไธๅธธ่ง๏ผ‰๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›**้™ๅˆถ**ๆ‚จๆƒณ่ฆๆŽฅๆ”ถ็š„ cookieใ€‚ @@ -50,7 +50,7 @@ ๆ‚จๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ็ฆๆญข๏ผˆ `forbid` ๏ผ‰ไปปไฝ•้ขๅค–๏ผˆ `extra` ๏ผ‰ๅญ—ๆฎต๏ผš -{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} ๅฆ‚ๆžœๅฎขๆˆทๅฐ่ฏ•ๅ‘้€ไธ€ไบ›**้ขๅค–็š„ cookie**๏ผŒไป–ไปฌๅฐ†ๆ”ถๅˆฐ**้”™่ฏฏ**ๅ“ๅบ”ใ€‚ @@ -71,6 +71,6 @@ } ``` -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #summary } ๆ‚จๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญๅฃฐๆ˜Ž **cookie**ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/tutorial/cookie-params.md b/docs/zh/docs/tutorial/cookie-params.md index 4956008149..ab05cd7d24 100644 --- a/docs/zh/docs/tutorial/cookie-params.md +++ b/docs/zh/docs/tutorial/cookie-params.md @@ -1,20 +1,19 @@ -# Cookie ๅ‚ๆ•ฐ +# Cookie ๅ‚ๆ•ฐ { #cookie-parameters } - ๅฎšไน‰ `Cookie` ๅ‚ๆ•ฐไธŽๅฎšไน‰ `Query` ๅ’Œ `Path` ๅ‚ๆ•ฐไธ€ๆ ทใ€‚ +ๅฎšไน‰ `Cookie` ๅ‚ๆ•ฐไธŽๅฎšไน‰ `Query` ๅ’Œ `Path` ๅ‚ๆ•ฐไธ€ๆ ทใ€‚ -## ๅฏผๅ…ฅ `Cookie` +## ๅฏผๅ…ฅ `Cookie` { #import-cookie } ้ฆ–ๅ…ˆ๏ผŒๅฏผๅ…ฅ `Cookie`๏ผš {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} -## ๅฃฐๆ˜Ž `Cookie` ๅ‚ๆ•ฐ +## ๅฃฐๆ˜Ž `Cookie` ๅ‚ๆ•ฐ { #declare-cookie-parameters } ๅฃฐๆ˜Ž `Cookie` ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽๅฃฐๆ˜Ž `Query` ๅ’Œ `Path` ๅ‚ๆ•ฐ็›ธๅŒใ€‚ ็ฌฌไธ€ไธชๅ€ผๆ˜ฏ้ป˜่ฎคๅ€ผ๏ผŒ่ฟ˜ๅฏไปฅไผ ้€’ๆ‰€ๆœ‰้ชŒ่ฏๅ‚ๆ•ฐๆˆ–ๆณจ้‡Šๅ‚ๆ•ฐ๏ผš - {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} /// note | ๆŠ€ๆœฏ็ป†่Š‚ @@ -25,12 +24,22 @@ /// -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ ๅฟ…้กปไฝฟ็”จ `Cookie` ๅฃฐๆ˜Ž cookie ๅ‚ๆ•ฐ๏ผŒๅฆๅˆ™่ฏฅๅ‚ๆ•ฐไผš่ขซ่งฃ้‡ŠไธบๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ /// -## ๅฐ็ป“ +/// info | ไฟกๆฏ + +่ฏทๆณจๆ„๏ผŒ็”ฑไบŽ**ๆต่งˆๅ™จไผšไปฅ็‰นๆฎŠๆ–นๅผๅนถๅœจๅน•ๅŽๅค„็† cookies**๏ผŒๅฎƒไปฌ**ไธไผš**่ฝปๆ˜“ๅ…่ฎธ**JavaScript**่ฎฟ้—ฎๅฎƒไปฌใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€ไฝไบŽ `/docs` ็š„**API ๆ–‡ๆกฃ็•Œ้ข**๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญๆœ‰ๅ…ณ cookies ็š„**ๆ–‡ๆกฃ**ใ€‚ + +ไฝ†ๅณไฝฟไฝ **ๅกซๅ†™ไบ†ๆ•ฐๆฎ**ๅนถ็‚นๅ‡ป "Execute"๏ผŒ็”ฑไบŽๆ–‡ๆกฃ็•Œ้ขไพ่ต–ไบŽ**JavaScript**ๅทฅไฝœ๏ผŒcookies ไนŸไธไผš่ขซๅ‘้€๏ผŒไฝ ไผš็œ‹ๅˆฐไธ€ไธช**้”™่ฏฏ**ๆถˆๆฏ๏ผŒๅฅฝๅƒไฝ ๆฒกๆœ‰ๅกซๅ†™ไปปไฝ•ๅ€ผไธ€ๆ ทใ€‚ + +/// + +## ๅฐ็ป“ { #recap } ไฝฟ็”จ `Cookie` ๅฃฐๆ˜Ž cookie ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Query` ๅ’Œ `Path` ็›ธๅŒใ€‚ diff --git a/docs/zh/docs/tutorial/cors.md b/docs/zh/docs/tutorial/cors.md index a4f15f6478..3a296ca723 100644 --- a/docs/zh/docs/tutorial/cors.md +++ b/docs/zh/docs/tutorial/cors.md @@ -1,8 +1,8 @@ -# CORS๏ผˆ่ทจๅŸŸ่ต„ๆบๅ…ฑไบซ๏ผ‰ +# CORS๏ผˆ่ทจๅŸŸ่ต„ๆบๅ…ฑไบซ๏ผ‰ { #cors-cross-origin-resource-sharing } CORS ๆˆ–่€…ใ€Œ่ทจๅŸŸ่ต„ๆบๅ…ฑไบซใ€ ๆŒ‡ๆต่งˆๅ™จไธญ่ฟ่กŒ็š„ๅ‰็ซฏๆ‹ฅๆœ‰ไธŽๅŽ็ซฏ้€šไฟก็š„ JavaScript ไปฃ็ ๏ผŒ่€ŒๅŽ็ซฏๅค„ไบŽไธŽๅ‰็ซฏไธๅŒ็š„ใ€Œๆบใ€็š„ๆƒ…ๅ†ตใ€‚ -## ๆบ +## ๆบ { #origin } ๆบๆ˜ฏๅ่ฎฎ๏ผˆ`http`๏ผŒ`https`๏ผ‰ใ€ๅŸŸ๏ผˆ`myapp.com`๏ผŒ`localhost`๏ผŒ`localhost.tiangolo.com`๏ผ‰ไปฅๅŠ็ซฏๅฃ๏ผˆ`80`ใ€`443`ใ€`8080`๏ผ‰็š„็ป„ๅˆใ€‚ @@ -14,25 +14,25 @@ ๅณไฝฟๅฎƒไปฌ้ƒฝๅœจ `localhost` ไธญ๏ผŒไฝ†ๆ˜ฏๅฎƒไปฌไฝฟ็”จไธๅŒ็š„ๅ่ฎฎๆˆ–่€…็ซฏๅฃ๏ผŒๆ‰€ไปฅๅฎƒไปฌ้ƒฝๆ˜ฏไธๅŒ็š„ใ€Œๆบใ€ใ€‚ -## ๆญฅ้ชค +## ๆญฅ้ชค { #steps } ๅ‡่ฎพไฝ ็š„ๆต่งˆๅ™จไธญๆœ‰ไธ€ไธชๅ‰็ซฏ่ฟ่กŒๅœจ `http://localhost:8080`๏ผŒๅนถไธ”ๅฎƒ็š„ JavaScript ๆญฃๅœจๅฐ่ฏ•ไธŽ่ฟ่กŒๅœจ `http://localhost` ็š„ๅŽ็ซฏ้€šไฟก๏ผˆๅ› ไธบๆˆ‘ไปฌๆฒกๆœ‰ๆŒ‡ๅฎš็ซฏๅฃ๏ผŒๆต่งˆๅ™จไผš้‡‡็”จ้ป˜่ฎค็š„็ซฏๅฃ `80`๏ผ‰ใ€‚ -็„ถๅŽ๏ผŒๆต่งˆๅ™จไผšๅ‘ๅŽ็ซฏๅ‘้€ไธ€ไธช HTTP `OPTIONS` ่ฏทๆฑ‚๏ผŒๅฆ‚ๆžœๅŽ็ซฏๅ‘้€้€‚ๅฝ“็š„ headers ๆฅๆŽˆๆƒๆฅ่‡ช่ฟ™ไธชไธๅŒๆบ๏ผˆ`http://localhost:8080`๏ผ‰็š„้€šไฟก๏ผŒๆต่งˆๅ™จๅฐ†ๅ…่ฎธๅ‰็ซฏ็š„ JavaScript ๅ‘ๅŽ็ซฏๅ‘้€่ฏทๆฑ‚ใ€‚ +็„ถๅŽ๏ผŒๆต่งˆๅ™จไผšๅ‘ `:80` ็š„ๅŽ็ซฏๅ‘้€ไธ€ไธช HTTP `OPTIONS` ่ฏทๆฑ‚๏ผŒๅฆ‚ๆžœๅŽ็ซฏๅ‘้€้€‚ๅฝ“็š„ headers ๆฅๆŽˆๆƒๆฅ่‡ช่ฟ™ไธชไธๅŒๆบ๏ผˆ`http://localhost:8080`๏ผ‰็š„้€šไฟก๏ผŒ้‚ฃไนˆ่ฟ่กŒๅœจ `:8080` ็š„ๆต่งˆๅ™จๅฐฑไผšๅ…่ฎธๅ‰็ซฏไธญ็š„ JavaScript ๅ‘ `:80` ็š„ๅŽ็ซฏๅ‘้€่ฏทๆฑ‚ใ€‚ -ไธบๆญค๏ผŒๅŽ็ซฏๅฟ…้กปๆœ‰ไธ€ไธชใ€Œๅ…่ฎธ็š„ๆบใ€ๅˆ—่กจใ€‚ +ไธบๆญค๏ผŒ`:80` ็š„ๅŽ็ซฏๅฟ…้กปๆœ‰ไธ€ไธชใ€Œๅ…่ฎธ็š„ๆบใ€ๅˆ—่กจใ€‚ -ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฟ…้กปๅŒ…ๅซ `http://localhost:8080`๏ผŒๅ‰็ซฏๆ‰่ƒฝๆญฃๅธธๅทฅไฝœใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฟ…้กปๅŒ…ๅซ `http://localhost:8080`๏ผŒ่ฟ™ๆ ท `:8080` ็š„ๅ‰็ซฏๆ‰่ƒฝๆญฃๅธธๅทฅไฝœใ€‚ -## ้€š้…็ฌฆ +## ้€š้…็ฌฆ { #wildcards } ไนŸๅฏไปฅไฝฟ็”จ `"*"`๏ผˆไธ€ไธชใ€Œ้€š้…็ฌฆใ€๏ผ‰ๅฃฐๆ˜Ž่ฟ™ไธชๅˆ—่กจ๏ผŒ่กจ็คบๅ…จ้ƒจ้ƒฝๆ˜ฏๅ…่ฎธ็š„ใ€‚ -ไฝ†่ฟ™ไป…ๅ…่ฎธๆŸไบ›็ฑปๅž‹็š„้€šไฟก๏ผŒไธๅŒ…ๆ‹ฌๆ‰€ๆœ‰ๆถ‰ๅŠๅ‡ญๆฎ็š„ๅ†…ๅฎน๏ผšๅƒ Cookies ไปฅๅŠ้‚ฃไบ›ไฝฟ็”จ Bearer ไปค็‰Œ็š„ๆŽˆๆƒ headers ็ญ‰ใ€‚ +ไฝ†่ฟ™ไป…ๅ…่ฎธๆŸไบ›็ฑปๅž‹็š„้€šไฟก๏ผŒไธๅŒ…ๆ‹ฌๆ‰€ๆœ‰ๆถ‰ๅŠๅ‡ญๆฎ็š„ๅ†…ๅฎน๏ผšๆฏ”ๅฆ‚ Cookies๏ผŒไปฅๅŠ้‚ฃไบ›ไฝฟ็”จ Bearer ไปค็‰Œ็š„ Authorization ่ฏทๆฑ‚ๅคด็ญ‰ใ€‚ ๅ› ๆญค๏ผŒไธบไบ†ไธ€ๅˆ‡้ƒฝ่ƒฝๆญฃๅธธๅทฅไฝœ๏ผŒๆœ€ๅฅฝๆ˜พๅผๅœฐๆŒ‡ๅฎšๅ…่ฎธ็š„ๆบใ€‚ -## ไฝฟ็”จ `CORSMiddleware` +## ไฝฟ็”จ `CORSMiddleware` { #use-corsmiddleware } ไฝ ๅฏไปฅๅœจ **FastAPI** ๅบ”็”จไธญไฝฟ็”จ `CORSMiddleware` ๆฅ้…็ฝฎๅฎƒใ€‚ @@ -42,11 +42,11 @@ ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšๅŽ็ซฏๆ˜ฏๅฆๅ…่ฎธ๏ผš -* ๅ‡ญ่ฏ๏ผˆๆŽˆๆƒ headers๏ผŒCookies ็ญ‰๏ผ‰ใ€‚ +* ๅ‡ญ่ฏ๏ผˆAuthorization ่ฏทๆฑ‚ๅคดใ€Cookies ็ญ‰๏ผ‰ใ€‚ * ็‰นๅฎš็š„ HTTP ๆ–นๆณ•๏ผˆ`POST`๏ผŒ`PUT`๏ผ‰ๆˆ–่€…ไฝฟ็”จ้€š้…็ฌฆ `"*"` ๅ…่ฎธๆ‰€ๆœ‰ๆ–นๆณ•ใ€‚ -* ็‰นๅฎš็š„ HTTP headers ๆˆ–่€…ไฝฟ็”จ้€š้…็ฌฆ `"*"` ๅ…่ฎธๆ‰€ๆœ‰ headersใ€‚ +* ็‰นๅฎš็š„ HTTP ่ฏทๆฑ‚ๅคดๆˆ–่€…ไฝฟ็”จ้€š้…็ฌฆ `"*"` ๅ…่ฎธๆ‰€ๆœ‰่ฏทๆฑ‚ๅคดใ€‚ -{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ่ฟ™ไธช `CORSMiddleware` ๅฎž็Žฐๆ‰€ไฝฟ็”จ็š„้ป˜่ฎคๅ‚ๆ•ฐ่พƒไธบไฟๅฎˆ๏ผŒๆ‰€ไปฅไฝ ้œ€่ฆๆ˜พๅผๅœฐๅฏ็”จ็‰นๅฎš็š„ๆบใ€ๆ–นๆณ•ๆˆ–่€… headers๏ผŒไปฅไพฟๆต่งˆๅ™จ่ƒฝๅคŸๅœจ่ทจๅŸŸไธŠไธ‹ๆ–‡ไธญไฝฟ็”จๅฎƒไปฌใ€‚ @@ -55,26 +55,29 @@ * `allow_origins` - ไธ€ไธชๅ…่ฎธ่ทจๅŸŸ่ฏทๆฑ‚็š„ๆบๅˆ—่กจใ€‚ไพ‹ๅฆ‚ `['https://example.org', 'https://www.example.org']`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ๅ…่ฎธไปปไฝ•ๆบใ€‚ * `allow_origin_regex` - ไธ€ไธชๆญฃๅˆ™่กจ่พพๅผๅญ—็ฌฆไธฒ๏ผŒๅŒน้…็š„ๆบๅ…่ฎธ่ทจๅŸŸ่ฏทๆฑ‚ใ€‚ไพ‹ๅฆ‚ `'https://.*\.example\.org'`ใ€‚ * `allow_methods` - ไธ€ไธชๅ…่ฎธ่ทจๅŸŸ่ฏทๆฑ‚็š„ HTTP ๆ–นๆณ•ๅˆ—่กจใ€‚้ป˜่ฎคไธบ `['GET']`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ๆฅๅ…่ฎธๆ‰€ๆœ‰ๆ ‡ๅ‡†ๆ–นๆณ•ใ€‚ -* `allow_headers` - ไธ€ไธชๅ…่ฎธ่ทจๅŸŸ่ฏทๆฑ‚็š„ HTTP ่ฏทๆฑ‚ๅคดๅˆ—่กจใ€‚้ป˜่ฎคไธบ `[]`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ๅ…่ฎธๆ‰€ๆœ‰็š„่ฏทๆฑ‚ๅคดใ€‚`Accept`ใ€`Accept-Language`ใ€`Content-Language` ไปฅๅŠ `Content-Type` ่ฏทๆฑ‚ๅคดๆ€ปๆ˜ฏๅ…่ฎธ CORS ่ฏทๆฑ‚ใ€‚ -* `allow_credentials` - ๆŒ‡็คบ่ทจๅŸŸ่ฏทๆฑ‚ๆ”ฏๆŒ cookiesใ€‚้ป˜่ฎคๆ˜ฏ `False`ใ€‚ๅฆๅค–๏ผŒๅ…่ฎธๅ‡ญ่ฏๆ—ถ `allow_origins` ไธ่ƒฝ่ฎพๅฎšไธบ `['*']`๏ผŒๅฟ…้กปๆŒ‡ๅฎšๆบใ€‚ +* `allow_headers` - ไธ€ไธชๅ…่ฎธ่ทจๅŸŸ่ฏทๆฑ‚็š„ HTTP ่ฏทๆฑ‚ๅคดๅˆ—่กจใ€‚้ป˜่ฎคไธบ `[]`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ๅ…่ฎธๆ‰€ๆœ‰็š„่ฏทๆฑ‚ๅคดใ€‚`Accept`ใ€`Accept-Language`ใ€`Content-Language` ไปฅๅŠ `Content-Type` ่ฟ™ๅ‡ ไธช่ฏทๆฑ‚ๅคดๅœจ็ฎ€ๅ• CORS ่ฏทๆฑ‚ไธญๆ€ปๆ˜ฏ่ขซๅ…่ฎธใ€‚ +* `allow_credentials` - ๆŒ‡็คบ่ทจๅŸŸ่ฏทๆฑ‚ๆ”ฏๆŒ cookiesใ€‚้ป˜่ฎคๆ˜ฏ `False`ใ€‚ + + ๅฝ“ `allow_credentials` ่ฎพไธบ `True` ๆ—ถ๏ผŒ`allow_origins`ใ€`allow_methods` ๅ’Œ `allow_headers` ้ƒฝไธ่ƒฝ่ฎพไธบ `['*']`ใ€‚ๅฎƒไปฌๅฟ…้กปๆ˜พๅผๆŒ‡ๅฎšใ€‚ + * `expose_headers` - ๆŒ‡็คบๅฏไปฅ่ขซๆต่งˆๅ™จ่ฎฟ้—ฎ็š„ๅ“ๅบ”ๅคดใ€‚้ป˜่ฎคไธบ `[]`ใ€‚ * `max_age` - ่ฎพๅฎšๆต่งˆๅ™จ็ผ“ๅญ˜ CORS ๅ“ๅบ”็š„ๆœ€้•ฟๆ—ถ้—ด๏ผŒๅ•ไฝๆ˜ฏ็ง’ใ€‚้ป˜่ฎคไธบ `600`ใ€‚ ไธญ้—ดไปถๅ“ๅบ”ไธค็ง็‰นๅฎš็ฑปๅž‹็š„ HTTP ่ฏทๆฑ‚โ€ฆโ€ฆ -### CORS ้ข„ๆฃ€่ฏทๆฑ‚ +### CORS ้ข„ๆฃ€่ฏทๆฑ‚ { #cors-preflight-requests } ่ฟ™ๆ˜ฏไบ›ๅธฆๆœ‰ `Origin` ๅ’Œ `Access-Control-Request-Method` ่ฏทๆฑ‚ๅคด็š„ `OPTIONS` ่ฏทๆฑ‚ใ€‚ ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไธญ้—ดไปถๅฐ†ๆ‹ฆๆˆชไผ ๅ…ฅ็š„่ฏทๆฑ‚ๅนถ่ฟ›่กŒๅ“ๅบ”๏ผŒๅ‡บไบŽๆไพ›ไฟกๆฏ็š„็›ฎ็š„่ฟ”ๅ›žไธ€ไธชไฝฟ็”จไบ†้€‚ๅฝ“็š„ CORS headers ็š„ `200` ๆˆ– `400` ๅ“ๅบ”ใ€‚ -### ็ฎ€ๅ•่ฏทๆฑ‚ +### ็ฎ€ๅ•่ฏทๆฑ‚ { #simple-requests } ไปปไฝ•ๅธฆๆœ‰ `Origin` ่ฏทๆฑ‚ๅคด็š„่ฏทๆฑ‚ใ€‚ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไธญ้—ดไปถๅฐ†ๅƒๅนณๅธธไธ€ๆ ทไผ ้€’่ฏทๆฑ‚๏ผŒไฝ†ๆ˜ฏๅœจๅ“ๅบ”ไธญๅŒ…ๅซ้€‚ๅฝ“็š„ CORS headersใ€‚ -## ๆ›ดๅคšไฟกๆฏ +## ๆ›ดๅคšไฟกๆฏ { #more-info } -ๆ›ดๅคšๅ…ณไบŽ CORS ็š„ไฟกๆฏ๏ผŒ่ฏทๆŸฅ็œ‹ Mozilla CORS ๆ–‡ๆกฃใ€‚ +ๆ›ดๅคšๅ…ณไบŽ CORS ็š„ไฟกๆฏ๏ผŒ่ฏทๆŸฅ็œ‹ Mozilla CORS ๆ–‡ๆกฃใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md index 734b855653..6e0cefe5b5 100644 --- a/docs/zh/docs/tutorial/debugging.md +++ b/docs/zh/docs/tutorial/debugging.md @@ -1,14 +1,14 @@ -# ่ฐƒ่ฏ• +# ่ฐƒ่ฏ• { #debugging } ไฝ ๅฏไปฅๅœจ็ผ–่พ‘ๅ™จไธญ่ฟžๆŽฅ่ฐƒ่ฏ•ๅ™จ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ Visual Studio Code ๆˆ– PyCharmใ€‚ -## ่ฐƒ็”จ `uvicorn` +## ่ฐƒ็”จ `uvicorn` { #call-uvicorn } ๅœจไฝ ็š„ FastAPI ๅบ”็”จไธญ็›ดๆŽฅๅฏผๅ…ฅ `uvicorn` ๅนถ่ฟ่กŒ๏ผš -{* ../../docs_src/debugging/tutorial001.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} -### ๅ…ณไบŽ `__name__ == "__main__"` +### ๅ…ณไบŽ `__name__ == "__main__"` { #about-name-main } `__name__ == "__main__"` ็š„ไธป่ฆ็›ฎ็š„ๆ˜ฏไฝฟ็”จไปฅไธ‹ไปฃ็ ่ฐƒ็”จๆ–‡ไปถๆ—ถๆ‰ง่กŒไธ€ไบ›ไปฃ็ ๏ผš @@ -26,7 +26,7 @@ $ python myapp.py from myapp import app ``` -#### ๆ›ดๅคš็ป†่Š‚ +#### ๆ›ดๅคš็ป†่Š‚ { #more-details } ๅ‡่ฎพไฝ ็š„ๆ–‡ไปถๅ‘ฝๅไธบ `myapp.py`ใ€‚ @@ -57,7 +57,7 @@ $ python myapp.py ```Python from myapp import app -# Some more code +# ๅ…ถไป–ไธ€ไบ›ไปฃ็  ``` ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ`myapp.py` ๅ†…้ƒจ็š„่‡ชๅŠจๅ˜้‡ไธไผšๆœ‰ๅ€ผไธบ `"__main__"` ็š„ๅ˜้‡ `__name__`ใ€‚ @@ -74,7 +74,7 @@ from myapp import app /// -## ไฝฟ็”จไฝ ็š„่ฐƒ่ฏ•ๅ™จ่ฟ่กŒไปฃ็  +## ไฝฟ็”จไฝ ็š„่ฐƒ่ฏ•ๅ™จ่ฟ่กŒไปฃ็  { #run-your-code-with-your-debugger } ็”ฑไบŽๆ˜ฏไปŽไปฃ็ ็›ดๆŽฅ่ฟ่กŒ็š„ Uvicorn ๆœๅŠกๅ™จ๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅไปŽ่ฐƒ่ฏ•ๅ™จ็›ดๆŽฅ่ฐƒ็”จ Python ็จ‹ๅบ๏ผˆไฝ ็š„ FastAPI ๅบ”็”จ๏ผ‰ใ€‚ diff --git a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md index f07280790c..d83321ddd6 100644 --- a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md @@ -1,12 +1,12 @@ -# ็ฑปไฝœไธบไพ่ต–้กน +# ็ฑปไฝœไธบไพ่ต–้กน { #classes-as-dependencies } ๅœจๆทฑๅ…ฅๆŽข็ฉถ **ไพ่ต–ๆณจๅ…ฅ** ็ณป็ปŸไน‹ๅ‰๏ผŒ่ฎฉๆˆ‘ไปฌๅ‡็บงไน‹ๅ‰็š„ไพ‹ๅญใ€‚ -## ๆฅ่‡ชๅ‰ไธ€ไธชไพ‹ๅญ็š„`dict` +## ๆฅ่‡ชๅ‰ไธ€ไธชไพ‹ๅญ็š„`dict` { #a-dict-from-the-previous-example } ๅœจๅ‰้ข็š„ไพ‹ๅญไธญ, ๆˆ‘ไปฌไปŽไพ่ต–้กน ("ๅฏไพ่ต–ๅฏน่ฑก") ไธญ่ฟ”ๅ›žไบ†ไธ€ไธช `dict`: -{* ../../docs_src/dependencies/tutorial001_py310.py hl[7] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} ไฝ†ๆ˜ฏๅŽ้ขๆˆ‘ไปฌๅœจ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ `commons` ไธญๅพ—ๅˆฐไบ†ไธ€ไธช `dict`ใ€‚ @@ -14,9 +14,9 @@ ๅฏนๆญค๏ผŒๆˆ‘ไปฌๅฏไปฅๅš็š„ๆ›ดๅฅฝ... -## ไป€ไนˆๆž„ๆˆไบ†ไพ่ต–้กน๏ผŸ +## ไป€ไนˆๆž„ๆˆไบ†ไพ่ต–้กน๏ผŸ { #what-makes-a-dependency } -ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๆ‚จ็œ‹ๅˆฐ็š„ไพ่ต–้กน้ƒฝ่ขซๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐใ€‚ +ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒไฝ ็œ‹ๅˆฐ็š„ไพ่ต–้กน้ƒฝ่ขซๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐใ€‚ ไฝ†่ฟ™ๅนถไธๆ˜ฏๅฃฐๆ˜Žไพ่ต–้กน็š„ๅ”ฏไธ€ๆ–นๆณ•(ๅฐฝ็ฎกๅฎƒๅฏ่ƒฝๆ˜ฏๆ›ดๅธธ่ง็š„ๆ–นๆณ•)ใ€‚ @@ -38,9 +38,9 @@ something(some_argument, some_keyword_argument="foo") ่ฟ™ๅฐฑๆ˜ฏ "ๅฏ่ฐƒ็”จๅฏน่ฑก"ใ€‚ -## ็ฑปไฝœไธบไพ่ต–้กน +## ็ฑปไฝœไธบไพ่ต–้กน { #classes-as-dependencies_1 } -ๆ‚จๅฏ่ƒฝไผšๆณจๆ„ๅˆฐ๏ผŒ่ฆๅˆ›ๅปบไธ€ไธช Python ็ฑป็š„ๅฎžไพ‹๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ็›ธๅŒ็š„่ฏญๆณ•ใ€‚ +ไฝ ๅฏ่ƒฝไผšๆณจๆ„ๅˆฐ๏ผŒ่ฆๅˆ›ๅปบไธ€ไธช Python ็ฑป็š„ๅฎžไพ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ็›ธๅŒ็š„่ฏญๆณ•ใ€‚ ไธพไธชไพ‹ๅญ: @@ -63,21 +63,21 @@ fluffy = Cat(name="Mr Fluffy") ๅฎž้™…ไธŠ FastAPI ๆฃ€ๆŸฅ็š„ๆ˜ฏๅฎƒๆ˜ฏไธ€ไธช "ๅฏ่ฐƒ็”จๅฏน่ฑก"๏ผˆๅ‡ฝๆ•ฐ๏ผŒ็ฑปๆˆ–ๅ…ถไป–ไปปไฝ•็ฑปๅž‹๏ผ‰ไปฅๅŠๅฎšไน‰็š„ๅ‚ๆ•ฐใ€‚ -ๅฆ‚ๆžœๆ‚จๅœจ **FastAPI** ไธญไผ ้€’ไธ€ไธช "ๅฏ่ฐƒ็”จๅฏน่ฑก" ไฝœไธบไพ่ต–้กน๏ผŒๅฎƒๅฐ†ๅˆ†ๆž่ฏฅ "ๅฏ่ฐƒ็”จๅฏน่ฑก" ็š„ๅ‚ๆ•ฐ๏ผŒๅนถไปฅๅค„็†่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ็š„ๆ–นๅผๆฅๅค„็†ๅฎƒไปฌใ€‚ๅŒ…ๆ‹ฌๅญไพ่ต–้กนใ€‚ +ๅฆ‚ๆžœไฝ ๅœจ **FastAPI** ไธญไผ ้€’ไธ€ไธช "ๅฏ่ฐƒ็”จๅฏน่ฑก" ไฝœไธบไพ่ต–้กน๏ผŒๅฎƒๅฐ†ๅˆ†ๆž่ฏฅ "ๅฏ่ฐƒ็”จๅฏน่ฑก" ็š„ๅ‚ๆ•ฐ๏ผŒๅนถไปฅๅค„็†่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ็š„ๆ–นๅผๆฅๅค„็†ๅฎƒไปฌใ€‚ๅŒ…ๆ‹ฌๅญไพ่ต–้กนใ€‚ ่ฟ™ไนŸ้€‚็”จไบŽๅฎŒๅ…จๆฒกๆœ‰ๅ‚ๆ•ฐ็š„ๅฏ่ฐƒ็”จๅฏน่ฑกใ€‚่ฟ™ไธŽไธๅธฆๅ‚ๆ•ฐ็š„่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไธ€ๆ ทใ€‚ ๆ‰€ไปฅ๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ†ไธŠ้ข็š„ไพ่ต–้กน "ๅฏไพ่ต–ๅฏน่ฑก" `common_parameters` ๆ›ดๆ”นไธบ็ฑป `CommonQueryParams`: -{* ../../docs_src/dependencies/tutorial002_py310.py hl[9:13] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} ๆณจๆ„็”จไบŽๅˆ›ๅปบ็ฑปๅฎžไพ‹็š„ `__init__` ๆ–นๆณ•๏ผš -{* ../../docs_src/dependencies/tutorial002_py310.py hl[10] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} ...ๅฎƒไธŽๆˆ‘ไปฌไปฅๅ‰็š„ `common_parameters` ๅ…ทๆœ‰็›ธๅŒ็š„ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/dependencies/tutorial001_py310.py hl[6] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} ่ฟ™ไบ›ๅ‚ๆ•ฐๅฐฑๆ˜ฏ **FastAPI** ็”จๆฅ "ๅค„็†" ไพ่ต–้กน็š„ใ€‚ @@ -89,26 +89,44 @@ fluffy = Cat(name="Mr Fluffy") ๅœจไธคไธชไพ‹ๅญไธ‹๏ผŒๆ•ฐๆฎ้ƒฝๅฐ†่ขซ่ฝฌๆขใ€้ชŒ่ฏใ€ๅœจ OpenAPI schema ไธŠๆ–‡ๆกฃๅŒ–๏ผŒ็ญ‰็ญ‰ใ€‚ -## ไฝฟ็”จๅฎƒ +## ไฝฟ็”จๅฎƒ { #use-it } -็Žฐๅœจ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ่ฟ™ไธช็ฑปๆฅๅฃฐๆ˜Žไฝ ็š„ไพ่ต–้กนไบ†ใ€‚ +็Žฐๅœจ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ่ฟ™ไธช็ฑปๆฅๅฃฐๆ˜Žไฝ ็š„ไพ่ต–้กนไบ†ใ€‚ -{* ../../docs_src/dependencies/tutorial002_py310.py hl[17] *} +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} **FastAPI** ่ฐƒ็”จ `CommonQueryParams` ็ฑปใ€‚่ฟ™ๅฐ†ๅˆ›ๅปบ่ฏฅ็ฑป็š„ไธ€ไธช "ๅฎžไพ‹"๏ผŒ่ฏฅๅฎžไพ‹ๅฐ†ไฝœไธบๅ‚ๆ•ฐ `commons` ่ขซไผ ้€’็ป™ไฝ ็š„ๅ‡ฝๆ•ฐใ€‚ -## ็ฑปๅž‹ๆณจ่งฃ vs `Depends` +## ็ฑปๅž‹ๆณจ่งฃ vs `Depends` { #type-annotation-vs-depends } ๆณจๆ„๏ผŒๆˆ‘ไปฌๅœจไธŠ้ข็š„ไปฃ็ ไธญ็ผ–ๅ†™ไบ†ไธคๆฌก`CommonQueryParams`๏ผš +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + ๆœ€ๅŽ็š„ `CommonQueryParams`: ```Python -... = Depends(CommonQueryParams) +... Depends(CommonQueryParams) ``` ...ๅฎž้™…ไธŠๆ˜ฏ **Fastapi** ็”จๆฅ็Ÿฅ้“ไพ่ต–้กนๆ˜ฏไป€ไนˆ็š„ใ€‚ @@ -119,62 +137,152 @@ FastAPI ๅฐ†ไปŽไพ่ต–้กนไธญๆๅ–ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ‰ๆ˜ฏ FastAPI ๅฎž้™…่ฐƒ็”จ ๅœจๆœฌไพ‹ไธญ๏ผŒ็ฌฌไธ€ไธช `CommonQueryParams` ๏ผš +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + ```Python commons: CommonQueryParams ... ``` -...ๅฏนไบŽ **FastAPI** ๆฒกๆœ‰ไปปไฝ•็‰นๆฎŠ็š„ๆ„ไน‰ใ€‚FastAPI ไธไผšไฝฟ็”จๅฎƒ่ฟ›่กŒๆ•ฐๆฎ่ฝฌๆขใ€้ชŒ่ฏ็ญ‰ (ๅ› ไธบๅฏนไบŽ่ฟ™๏ผŒๅฎƒไฝฟ็”จ `= Depends(CommonQueryParams)`)ใ€‚ +//// + +...ๅฏนไบŽ **FastAPI** ๆฒกๆœ‰ไปปไฝ•็‰นๆฎŠ็š„ๆ„ไน‰ใ€‚FastAPI ไธไผšไฝฟ็”จๅฎƒ่ฟ›่กŒๆ•ฐๆฎ่ฝฌๆขใ€้ชŒ่ฏ็ญ‰ (ๅ› ไธบๅฏนไบŽ่ฟ™๏ผŒๅฎƒไฝฟ็”จ `Depends(CommonQueryParams)`)ใ€‚ ไฝ ๅฎž้™…ไธŠๅฏไปฅๅช่ฟ™ๆ ท็ผ–ๅ†™: +//// tab | Python 3.9+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + ```Python commons = Depends(CommonQueryParams) ``` +//// + ..ๅฐฑๅƒ: -{* ../../docs_src/dependencies/tutorial003_py310.py hl[17] *} +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} ไฝ†ๆ˜ฏๅฃฐๆ˜Ž็ฑปๅž‹ๆ˜ฏ่ขซ้ผ“ๅŠฑ็š„๏ผŒๅ› ไธบ้‚ฃๆ ทไฝ ็š„็ผ–่พ‘ๅ™จๅฐฑไผš็Ÿฅ้“ๅฐ†ไผ ้€’ไป€ไนˆไฝœไธบๅ‚ๆ•ฐ `commons` ๏ผŒ็„ถๅŽๅฎƒๅฏไปฅๅธฎๅŠฉไฝ ๅฎŒๆˆไปฃ็ ๏ผŒ็ฑปๅž‹ๆฃ€ๆŸฅ๏ผŒ็ญ‰็ญ‰๏ผš -## ๅฟซๆทๆ–นๅผ +## ๅฟซๆทๆ–นๅผ { #shortcut } -ไฝ†ๆ˜ฏๆ‚จๅฏไปฅ็œ‹ๅˆฐ๏ผŒๆˆ‘ไปฌๅœจ่ฟ™้‡Œๆœ‰ไธ€ไบ›ไปฃ็ ้‡ๅคไบ†๏ผŒ็ผ–ๅ†™ไบ†`CommonQueryParams`ไธคๆฌก๏ผš +ไฝ†ๆ˜ฏไฝ ๅฏไปฅ็œ‹ๅˆฐ๏ผŒๆˆ‘ไปฌๅœจ่ฟ™้‡Œๆœ‰ไธ€ไบ›ไปฃ็ ้‡ๅคไบ†๏ผŒ็ผ–ๅ†™ไบ†`CommonQueryParams`ไธคๆฌก๏ผš + +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + **FastAPI** ไธบ่ฟ™ไบ›ๆƒ…ๅ†ตๆไพ›ไบ†ไธ€ไธชๅฟซๆทๆ–นๅผ๏ผŒๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไพ่ต–้กน *ๆ˜Ž็กฎๅœฐ* ๆ˜ฏไธ€ไธช็ฑป๏ผŒ**FastAPI** ๅฐ† "่ฐƒ็”จ" ๅฎƒๆฅๅˆ›ๅปบ็ฑปๆœฌ่บซ็š„ไธ€ไธชๅฎžไพ‹ใ€‚ -ๅฏนไบŽ่ฟ™ไบ›็‰นๅฎš็š„ๆƒ…ๅ†ต๏ผŒๆ‚จๅฏไปฅ่ทŸ้šไปฅไธ‹ๆ“ไฝœ๏ผš +ๅฏนไบŽ่ฟ™ไบ›็‰นๅฎš็š„ๆƒ…ๅ†ต๏ผŒไฝ ๅฏไปฅๆŒ‰ๅฆ‚ไธ‹ๆ“ไฝœ๏ผš ไธๆ˜ฏๅ†™ๆˆ่ฟ™ๆ ท๏ผš +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends(CommonQueryParams) ``` +//// + ...่€Œๆ˜ฏ่ฟ™ๆ ทๅ†™: +//// tab | Python 3.9+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + ```Python commons: CommonQueryParams = Depends() ``` -ๆ‚จๅฃฐๆ˜Žไพ่ต–้กนไฝœไธบๅ‚ๆ•ฐ็š„็ฑปๅž‹๏ผŒๅนถไฝฟ็”จ `Depends()` ไฝœไธบ่ฏฅๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ็š„ "้ป˜่ฎค" ๅ€ผ(ๅœจ `=` ไน‹ๅŽ)๏ผŒ่€Œๅœจ `Depends()` ไธญๆฒกๆœ‰ไปปไฝ•ๅ‚ๆ•ฐ๏ผŒ่€Œไธๆ˜ฏๅœจ `Depends(CommonQueryParams)` ็ผ–ๅ†™ๅฎŒๆ•ด็š„็ฑปใ€‚ +//// + +ไฝ ๅฃฐๆ˜Žไพ่ต–้กนไฝœไธบๅ‚ๆ•ฐ็š„็ฑปๅž‹๏ผŒๅนถไฝฟ็”จ `Depends()` ไฝœไธบ่ฏฅๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ็š„ "้ป˜่ฎค" ๅ€ผ(ๅœจ `=` ไน‹ๅŽ)๏ผŒ่€Œๅœจ `Depends()` ไธญๆฒกๆœ‰ไปปไฝ•ๅ‚ๆ•ฐ๏ผŒ่€Œไธๆ˜ฏๅœจ `Depends(CommonQueryParams)` ไธญ*ๅ†ๆฌก*็ผ–ๅ†™ๅฎŒๆ•ด็š„็ฑปใ€‚ ๅŒๆ ท็š„ไพ‹ๅญ็œ‹่ตทๆฅๅƒ่ฟ™ๆ ท๏ผš -{* ../../docs_src/dependencies/tutorial004_py310.py hl[17] *} +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} ... **FastAPI** ไผš็Ÿฅ้“ๆ€Žไนˆๅค„็†ใ€‚ -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœ่ฟ™็œ‹่ตทๆฅๆ›ดๅŠ ๆททไนฑ่€Œไธๆ˜ฏๆ›ดๅŠ ๆœ‰ๅธฎๅŠฉ๏ผŒ้‚ฃไนˆ่ฏทๅฟฝ็•ฅๅฎƒ๏ผŒไฝ ไธ*้œ€่ฆ*ๅฎƒใ€‚ -่ฟ™ๅชๆ˜ฏไธ€ไธชๅฟซๆทๆ–นๅผใ€‚ๅ› ไธบ **FastAPI** ๅ…ณๅฟƒ็š„ๆ˜ฏๅธฎๅŠฉๆ‚จๅ‡ๅฐ‘ไปฃ็ ้‡ๅคใ€‚ +่ฟ™ๅชๆ˜ฏไธ€ไธชๅฟซๆทๆ–นๅผใ€‚ๅ› ไธบ **FastAPI** ๅ…ณๅฟƒ็š„ๆ˜ฏๅธฎๅŠฉไฝ ๅ‡ๅฐ‘ไปฃ็ ้‡ๅคใ€‚ /// diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 51b3e9fc39..02fcf62a0a 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -1,4 +1,4 @@ -# ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน +# ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน { #dependencies-in-path-operation-decorators } ๆœ‰ๆ—ถ๏ผŒๆˆ‘ไปฌๅนถไธ้œ€่ฆๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญไฝฟ็”จไพ่ต–้กน็š„่ฟ”ๅ›žๅ€ผใ€‚ @@ -8,15 +8,15 @@ ๅฏนไบŽ่ฟ™็งๆƒ…ๅ†ต๏ผŒไธๅฟ…ๅœจๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐๆ—ถไฝฟ็”จ `Depends`๏ผŒ่€Œๆ˜ฏๅฏไปฅๅœจ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญๆทปๅŠ ไธ€ไธช็”ฑ `dependencies` ็ป„ๆˆ็š„ `list`ใ€‚ -## ๅœจ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญๆทปๅŠ  `dependencies` ๅ‚ๆ•ฐ +## ๅœจ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญๆทปๅŠ  `dependencies` ๅ‚ๆ•ฐ { #add-dependencies-to-the-path-operation-decorator } -*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ๆ”ฏๆŒๅฏ้€‰ๅ‚ๆ•ฐ ~ `dependencies`ใ€‚ +*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ๆ”ฏๆŒๅฏ้€‰ๅ‚ๆ•ฐ `dependencies`ใ€‚ ่ฏฅๅ‚ๆ•ฐ็š„ๅ€ผๆ˜ฏ็”ฑ `Depends()` ็ป„ๆˆ็š„ `list`๏ผš -{* ../../docs_src/dependencies/tutorial006.py hl[17] *} +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} -่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน๏ผˆไปฅไธ‹็ฎ€็งฐไธบ**โ€œ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนโ€**๏ผ‰็š„ๆ‰ง่กŒๆˆ–่งฃๆžๆ–นๅผๅ’Œๆ™ฎ้€šไพ่ต–้กนไธ€ๆ ท๏ผŒไฝ†ๅฐฑ็ฎ—่ฟ™ไบ›ไพ่ต–้กนไผš่ฟ”ๅ›žๅ€ผ๏ผŒๅฎƒไปฌ็š„ๅ€ผไนŸไธไผšไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ +่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน็š„ๆ‰ง่กŒๆˆ–่งฃๆžๆ–นๅผๅ’Œๆ™ฎ้€šไพ่ต–้กนไธ€ๆ ท๏ผŒไฝ†ๅฐฑ็ฎ—่ฟ™ไบ›ไพ่ต–้กนไผš่ฟ”ๅ›žๅ€ผ๏ผŒๅฎƒไปฌ็š„ๅ€ผไนŸไธไผšไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ /// tip | ๆ็คบ @@ -36,34 +36,34 @@ /// -## ไพ่ต–้กน้”™่ฏฏๅ’Œ่ฟ”ๅ›žๅ€ผ +## ไพ่ต–้กน้”™่ฏฏๅ’Œ่ฟ”ๅ›žๅ€ผ { #dependencies-errors-and-return-values } ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนไนŸๅฏไปฅไฝฟ็”จๆ™ฎ้€š็š„ไพ่ต–้กน*ๅ‡ฝๆ•ฐ*ใ€‚ -### ไพ่ต–้กน็š„้œ€ๆฑ‚้กน +### ไพ่ต–้กน็š„้œ€ๆฑ‚้กน { #dependency-requirements } ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนๅฏไปฅๅฃฐๆ˜Ž่ฏทๆฑ‚็š„้œ€ๆฑ‚้กน๏ผˆๆฏ”ๅฆ‚ๅ“ๅบ”ๅคด๏ผ‰ๆˆ–ๅ…ถไป–ๅญไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial006.py hl[6,11] *} +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} -### ่งฆๅ‘ๅผ‚ๅธธ +### ่งฆๅ‘ๅผ‚ๅธธ { #raise-exceptions } ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนไธŽๆญฃๅธธ็š„ไพ่ต–้กนไธ€ๆ ท๏ผŒๅฏไปฅ `raise` ๅผ‚ๅธธ๏ผš -{* ../../docs_src/dependencies/tutorial006.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} -### ่ฟ”ๅ›žๅ€ผ +### ่ฟ”ๅ›žๅ€ผ { #return-values } ๆ— ่ฎบ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนๆ˜ฏๅฆ่ฟ”ๅ›žๅ€ผ๏ผŒ่ทฏๅพ„ๆ“ไฝœ้ƒฝไธไผšไฝฟ็”จ่ฟ™ไบ›ๅ€ผใ€‚ ๅ› ๆญค๏ผŒๅฏไปฅๅค็”จๅœจๅ…ถไป–ไฝ็ฝฎไฝฟ็”จ่ฟ‡็š„ใ€๏ผˆ่ƒฝ่ฟ”ๅ›žๅ€ผ็š„๏ผ‰ๆ™ฎ้€šไพ่ต–้กน๏ผŒๅณไฝฟๆฒกๆœ‰ไฝฟ็”จ่ฟ™ไธชๅ€ผ๏ผŒไนŸไผšๆ‰ง่กŒ่ฏฅไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial006.py hl[9,14] *} +{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} -## ไธบไธ€็ป„่ทฏๅพ„ๆ“ไฝœๅฎšไน‰ไพ่ต–้กน +## ไธบไธ€็ป„่ทฏๅพ„ๆ“ไฝœๅฎšไน‰ไพ่ต–้กน { #dependencies-for-a-group-of-path-operations } -็จๅŽ๏ผŒ[ๅคงๅž‹ๅบ”็”จ - ๅคšๆ–‡ไปถ](../../tutorial/bigger-applications.md){.internal-link target=\_blank}ไธ€็ซ ไธญไผšไป‹็ปๅฆ‚ไฝ•ไฝฟ็”จๅคšไธชๆ–‡ไปถๅˆ›ๅปบๅคงๅž‹ๅบ”็”จ็จ‹ๅบ๏ผŒๅœจ่ฟ™ไธ€็ซ ไธญ๏ผŒๆ‚จๅฐ†ไบ†่งฃๅˆฐๅฆ‚ไฝ•ไธบไธ€็ป„*่ทฏๅพ„ๆ“ไฝœ*ๅฃฐๆ˜Žๅ•ไธช `dependencies` ๅ‚ๆ•ฐใ€‚ +็จๅŽ๏ผŒ[ๅคงๅž‹ๅบ”็”จ - ๅคšๆ–‡ไปถ](../../tutorial/bigger-applications.md){.internal-link target=_blank}ไธ€็ซ ไธญไผšไป‹็ปๅฆ‚ไฝ•ไฝฟ็”จๅคšไธชๆ–‡ไปถๅˆ›ๅปบๅคงๅž‹ๅบ”็”จ็จ‹ๅบ๏ผŒๅœจ่ฟ™ไธ€็ซ ไธญ๏ผŒๆ‚จๅฐ†ไบ†่งฃๅˆฐๅฆ‚ไฝ•ไธบไธ€็ป„*่ทฏๅพ„ๆ“ไฝœ*ๅฃฐๆ˜Žๅ•ไธช `dependencies` ๅ‚ๆ•ฐใ€‚ -## ๅ…จๅฑ€ไพ่ต–้กน +## ๅ…จๅฑ€ไพ่ต–้กน { #global-dependencies } ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅฐ†ๅญฆไน ๅฆ‚ไฝ•ไธบ `FastAPI` ๅบ”็”จ็จ‹ๅบๆทปๅŠ ๅ…จๅฑ€ไพ่ต–้กน๏ผŒๅˆ›ๅปบๅบ”็”จไบŽๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„ไพ่ต–้กนใ€‚ diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index a863bb861e..bf495c9f39 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,136 +1,139 @@ -# ไฝฟ็”จyield็š„ไพ่ต–้กน +# ไฝฟ็”จ yield ็š„ไพ่ต–้กน { #dependencies-with-yield } -FastAPIๆ”ฏๆŒๅœจๅฎŒๆˆๅŽๆ‰ง่กŒไธ€ไบ›้ขๅค–ๆญฅ้ชค็š„ไพ่ต–้กน. +FastAPI ๆ”ฏๆŒ้‚ฃไบ›ๅœจๅฎŒๆˆๅŽๆ‰ง่กŒไธ€ไบ›้ขๅค–ๆญฅ้ชค็š„ไพ่ต–้กนใ€‚ -ไธบๆญค๏ผŒไฝ ้œ€่ฆไฝฟ็”จ `yield` ่€Œไธๆ˜ฏ `return`๏ผŒ็„ถๅŽๅ†็ผ–ๅ†™่ฟ™ไบ›้ขๅค–็š„ๆญฅ้ชค๏ผˆไปฃ็ ๏ผ‰ใ€‚ +ไธบๆญค๏ผŒไฝฟ็”จ `yield` ่€Œไธๆ˜ฏ `return`๏ผŒๅนถๆŠŠ่ฟ™ไบ›้ขๅค–ๆญฅ้ชค๏ผˆไปฃ็ ๏ผ‰ๅ†™ๅœจๅŽ้ขใ€‚ /// tip | ๆ็คบ -็กฎไฟๅœจๆฏไธชไพ่ต–ไธญๅชไฝฟ็”จไธ€ๆฌก `yield`ใ€‚ +็กฎไฟๅœจๆฏไธชไพ่ต–้‡Œๅชไฝฟ็”จไธ€ๆฌก `yield`ใ€‚ /// /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ไปปไฝ•ไธ€ไธชๅฏไปฅไธŽไปฅไธ‹ๅ†…ๅฎนไธ€่ตทไฝฟ็”จ็š„ๅ‡ฝๆ•ฐ๏ผš +ไปปไฝ•ๅฏไปฅไธŽไปฅไธ‹่ฃ…้ฅฐๅ™จไธ€่ตทไฝฟ็”จ็š„ๅ‡ฝๆ•ฐ๏ผš -* `@contextlib.contextmanager` ๆˆ–่€… +* `@contextlib.contextmanager` ๆˆ– * `@contextlib.asynccontextmanager` ้ƒฝๅฏไปฅไฝœไธบ **FastAPI** ็š„ไพ่ต–้กนใ€‚ -ๅฎž้™…ไธŠ๏ผŒFastAPIๅ†…้ƒจๅฐฑไฝฟ็”จไบ†่ฟ™ไธคไธช่ฃ…้ฅฐๅ™จใ€‚ +ๅฎž้™…ไธŠ๏ผŒFastAPI ๅœจๅ†…้ƒจๅฐฑๆ˜ฏ็”จ็š„่ฟ™ไธคไธช่ฃ…้ฅฐๅ™จใ€‚ /// -## ไฝฟ็”จ `yield` ็š„ๆ•ฐๆฎๅบ“ไพ่ต–้กน +## ไฝฟ็”จ `yield` ็š„ๆ•ฐๆฎๅบ“ไพ่ต–้กน { #a-database-dependency-with-yield } -ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅไฝฟ็”จ่ฟ™็งๆ–นๅผๅˆ›ๅปบไธ€ไธชๆ•ฐๆฎๅบ“ไผš่ฏ๏ผŒๅนถๅœจๅฎŒๆˆๅŽๅ…ณ้—ญๅฎƒใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จ่ฟ™็งๆ–นๅผๅˆ›ๅปบไธ€ไธชๆ•ฐๆฎๅบ“ไผš่ฏ๏ผŒๅนถๅœจๅฎŒๆˆๅŽๅฐ†ๅ…ถๅ…ณ้—ญใ€‚ -ๅœจๅ‘้€ๅ“ๅบ”ไน‹ๅ‰๏ผŒๅชไผšๆ‰ง่กŒ `yield` ่ฏญๅฅๅŠไน‹ๅ‰็š„ไปฃ็ ๏ผš +ๅœจๅˆ›ๅปบๅ“ๅบ”ไน‹ๅ‰๏ผŒๅชไผšๆ‰ง่กŒ `yield` ่ฏญๅฅๅŠๅ…ถไน‹ๅ‰็š„ไปฃ็ ๏ผš -{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} -็”Ÿๆˆ็š„ๅ€ผไผšๆณจๅ…ฅๅˆฐ *่ทฏ็”ฑๅ‡ฝๆ•ฐ* ๅ’Œๅ…ถไป–ไพ่ต–้กนไธญ๏ผš +`yield` ไบง็”Ÿ็š„ๅ€ผไผšๆณจๅ…ฅๅˆฐ *่ทฏๅพ„ๆ“ไฝœ* ๅ’Œๅ…ถไป–ไพ่ต–้กนไธญ๏ผš -{* ../../docs_src/dependencies/tutorial007.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} -`yield` ่ฏญๅฅๅŽ้ข็š„ไปฃ็ ไผšๅœจๅˆ›ๅปบๅ“ๅบ”ๅŽ๏ผŒๅ‘้€ๅ“ๅบ”ๅ‰ๆ‰ง่กŒ๏ผš +`yield` ่ฏญๅฅๅŽ้ข็š„ไปฃ็ ไผšๅœจๅ“ๅบ”ไน‹ๅŽๆ‰ง่กŒ๏ผš -{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} /// tip | ๆ็คบ ไฝ ๅฏไปฅไฝฟ็”จ `async` ๆˆ–ๆ™ฎ้€šๅ‡ฝๆ•ฐใ€‚ -**FastAPI** ไผšๅƒๅค„็†ๆ™ฎ้€šไพ่ต–ไธ€ๆ ท๏ผŒๅฏนๆฏไธชไพ่ต–ๅšๆญฃ็กฎ็š„ๅค„็†ใ€‚ +**FastAPI** ไผšๅƒๅค„็†ๆ™ฎ้€šไพ่ต–ไธ€ๆ ทๅฏนๅฎƒไปฌ่ฟ›่กŒๆญฃ็กฎๅค„็†ใ€‚ /// -## ๅŒ…ๅซ `yield` ๅ’Œ `try` ็š„ไพ่ต–้กน +## ๅŒๆ—ถไฝฟ็”จ `yield` ๅ’Œ `try` ็š„ไพ่ต–้กน { #a-dependency-with-yield-and-try } -ๅฆ‚ๆžœๅœจๅŒ…ๅซ `yield` ็š„ไพ่ต–ไธญไฝฟ็”จ `try` ไปฃ็ ๅ—๏ผŒไฝ ไผšๆ•่Žทๅˆฐไฝฟ็”จไพ่ต–ๆ—ถๆŠ›ๅ‡บ็š„ไปปไฝ•ๅผ‚ๅธธใ€‚ +ๅฆ‚ๆžœไฝ ๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญไฝฟ็”จไบ† `try` ไปฃ็ ๅ—๏ผŒ้‚ฃไนˆๅฝ“ไฝฟ็”จ่ฏฅไพ่ต–ๆ—ถๆŠ›ๅ‡บ็š„ไปปไฝ•ๅผ‚ๅธธไฝ ้ƒฝไผšๆ”ถๅˆฐใ€‚ -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๆŸๆฎตไปฃ็ ๅœจๅฆไธ€ไธชไพ่ต–ไธญๆˆ–ๅœจ *่ทฏ็”ฑๅ‡ฝๆ•ฐ* ไธญไฝฟๆ•ฐๆฎๅบ“ไบ‹ๅŠก"ๅ›žๆปš"ๆˆ–ไบง็”Ÿไปปไฝ•ๅ…ถไป–้”™่ฏฏ๏ผŒไฝ ๅฐ†ไผšๅœจไพ่ต–ไธญๆ•่Žทๅˆฐๅผ‚ๅธธใ€‚ +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๅœจไธญ้—ด็š„ๆŸๅค„ไปฃ็ ไธญ๏ผˆๅœจๅฆไธ€ไธชไพ่ต–ๆˆ–ๅœจๆŸไธช *่ทฏๅพ„ๆ“ไฝœ* ไธญ๏ผ‰ๅ‘็”Ÿไบ†ๆ•ฐๆฎๅบ“ไบ‹ๅŠกโ€œๅ›žๆปšโ€ๆˆ–ไบง็”Ÿไบ†ๅ…ถไป–ๅผ‚ๅธธ๏ผŒไฝ ไผšๅœจไฝ ็š„ไพ่ต–ไธญๆ”ถๅˆฐ่ฟ™ไธชๅผ‚ๅธธใ€‚ -ๅ› ๆญค๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `except SomeException` ๅœจไพ่ต–ไธญๆ•่Žท็‰นๅฎš็š„ๅผ‚ๅธธใ€‚ +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅœจ่ฏฅไพ่ต–ไธญ็”จ `except SomeException` ๆฅๆ•่Žท่ฟ™ไธช็‰นๅฎšๅผ‚ๅธธใ€‚ -ๅŒๆ ท๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ `finally` ๆฅ็กฎไฟ้€€ๅ‡บๆญฅ้ชคๅพ—ๅˆฐๆ‰ง่กŒ๏ผŒๆ— ่ฎบๆ˜ฏๅฆๅญ˜ๅœจๅผ‚ๅธธใ€‚ +ๅŒๆ ทๅœฐ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `finally` ๆฅ็กฎไฟ้€€ๅ‡บๆญฅ้ชคไธ€ๅฎšไผš่ขซๆ‰ง่กŒ๏ผŒๆ— ่ฎบๆ˜ฏๅฆๅ‘็”Ÿๅผ‚ๅธธใ€‚ -{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *} -## ไฝฟ็”จ `yield` ็š„ๅญไพ่ต–้กน +{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} -ไฝ ๅฏไปฅๅฃฐๆ˜Žไปปๆ„ๆ•ฐ้‡ๅ’Œๅฑ‚็บง็š„ๆ ‘็Šถไพ่ต–๏ผŒ่€Œไธ”ๅฎƒไปฌไธญ็š„ไปปไฝ•ไธ€ไธชๆˆ–ๆ‰€ๆœ‰็š„้ƒฝๅฏไปฅไฝฟ็”จ `yield`ใ€‚ +## ไฝฟ็”จ `yield` ็š„ๅญไพ่ต–้กน { #sub-dependencies-with-yield } -**FastAPI** ไผš็กฎไฟๆฏไธชๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญ็š„"้€€ๅ‡บไปฃ็ "ๆŒ‰ๆญฃ็กฎ้กบๅบ่ฟ่กŒใ€‚ +ไฝ ๅฏไปฅๅฃฐๆ˜Žไปปๆ„ๅคงๅฐๅ’Œๅฝข็Šถ็š„ๅญไพ่ต–ๅŠๅ…ถโ€œๆ ‘โ€๏ผŒๅ…ถไธญไปปๆ„ไธ€ไธชๆˆ–ๅ…จ้ƒจ้ƒฝๅฏไปฅไฝฟ็”จ `yield`ใ€‚ -ไพ‹ๅฆ‚๏ผŒ`dependency_c` ๅฏไปฅไพ่ต–ไบŽ `dependency_b`๏ผŒ่€Œ `dependency_b` ๅˆ™ไพ่ต–ไบŽ `dependency_a`ใ€‚ +**FastAPI** ไผš็กฎไฟๆฏไธชๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญ็š„โ€œ้€€ๅ‡บไปฃ็ โ€ๆŒ‰ๆญฃ็กฎ็š„้กบๅบ่ฟ่กŒใ€‚ + +ไพ‹ๅฆ‚๏ผŒ`dependency_c` ๅฏไปฅไพ่ต– `dependency_b`๏ผŒ่€Œ `dependency_b` ๅˆ™ไพ่ต– `dependency_a`๏ผš {* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} -ๆ‰€ๆœ‰่ฟ™ไบ›ไพ่ต–้ƒฝๅฏไปฅไฝฟ็”จ `yield`ใ€‚ +ๅนถไธ”ๅฎƒไปฌ้ƒฝๅฏไปฅไฝฟ็”จ `yield`ใ€‚ -ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ`dependency_c` ๅœจๆ‰ง่กŒๅ…ถ้€€ๅ‡บไปฃ็ ๆ—ถ้œ€่ฆ `dependency_b`๏ผˆๆญคๅค„็งฐไธบ `dep_b`๏ผ‰็š„ๅ€ผไป็„ถๅฏ็”จใ€‚ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ`dependency_c` ๅœจๆ‰ง่กŒๅ…ถ้€€ๅ‡บไปฃ็ ๆ—ถ้œ€่ฆ `dependency_b`๏ผˆๆญคๅค„ๅ‘ฝๅไธบ `dep_b`๏ผ‰็š„ๅ€ผไป็„ถๅฏ็”จใ€‚ -่€Œ `dependency_b` ๅ่ฟ‡ๆฅๅˆ™้œ€่ฆ `dependency_a`๏ผˆๆญคๅค„็งฐไธบ `dep_a` ๏ผ‰็š„ๅ€ผๅœจๅ…ถ้€€ๅ‡บไปฃ็ ไธญๅฏ็”จใ€‚ +่€Œ `dependency_b` ๅˆ้œ€่ฆ `dependency_a`๏ผˆๆญคๅค„ๅ‘ฝๅไธบ `dep_a`๏ผ‰็š„ๅ€ผๅœจๅ…ถ้€€ๅ‡บไปฃ็ ไธญๅฏ็”จใ€‚ {* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} -ๅŒๆ ท๏ผŒไฝ ๅฏไปฅๆททๅˆไฝฟ็”จๅธฆๆœ‰ `yield` ๆˆ– `return` ็š„ไพ่ต–ใ€‚ +ๅŒๆ ทๅœฐ๏ผŒไฝ ๅฏไปฅๅฐ†ไธ€ไบ›ไพ่ต–็”จ `yield`๏ผŒๅฆไธ€ไบ›็”จ `return`๏ผŒๅนถ่ฎฉๅ…ถไธญไธ€ไบ›ไพ่ต–ไพ่ต–ไบŽๅฆไธ€ไบ›ใ€‚ -ไฝ ไนŸๅฏไปฅๅฃฐๆ˜Žไธ€ไธชไพ่ต–ไบŽๅคšไธชๅธฆๆœ‰ `yield` ็š„ไพ่ต–๏ผŒ็ญ‰็ญ‰ใ€‚ +ไฝ ไนŸๅฏไปฅๆœ‰ไธ€ไธชไพ่ต–้œ€่ฆๅคšไธชๅธฆๆœ‰ `yield` ็š„ไพ่ต–๏ผŒ็ญ‰็ญ‰ใ€‚ ไฝ ๅฏไปฅๆ‹ฅๆœ‰ไปปไฝ•ไฝ ๆƒณ่ฆ็š„ไพ่ต–็ป„ๅˆใ€‚ -**FastAPI** ๅฐ†็กฎไฟๆŒ‰ๆญฃ็กฎ็š„้กบๅบ่ฟ่กŒๆ‰€ๆœ‰ๅ†…ๅฎนใ€‚ +**FastAPI** ๅฐ†็กฎไฟไธ€ๅˆ‡้ƒฝๆŒ‰ๆญฃ็กฎ็š„้กบๅบ่ฟ่กŒใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ -่ฟ™ๆ˜ฏ็”ฑ Python ็š„ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จๅฎŒๆˆ็š„ใ€‚ +่ฟ™่ฆๅฝ’ๅŠŸไบŽ Python ็š„ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จใ€‚ **FastAPI** ๅœจๅ†…้ƒจไฝฟ็”จๅฎƒไปฌๆฅๅฎž็Žฐ่ฟ™ไธ€็‚นใ€‚ /// -## ๅŒ…ๅซ `yield` ๅ’Œ `HTTPException` ็š„ไพ่ต–้กน +## ๅŒๆ—ถไฝฟ็”จ `yield` ๅ’Œ `HTTPException` ็š„ไพ่ต–้กน { #dependencies-with-yield-and-httpexception } + +ไฝ ๅทฒ็ป็œ‹ๅˆฐๅฏไปฅๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญไฝฟ็”จ `try` ๅ—ๅฐ่ฏ•ๆ‰ง่กŒไธ€ไบ›ไปฃ็ ๏ผŒ็„ถๅŽๅœจ `finally` ไน‹ๅŽ่ฟ่กŒไธ€ไบ›้€€ๅ‡บไปฃ็ ใ€‚ -ไฝ ๅฏไปฅไฝฟ็”จๅธฆๆœ‰ `yield` ็š„ไพ่ต–้กน๏ผŒๅนถไธ”ๅฏไปฅๅŒ…ๅซ `try` ไปฃ็ ๅ—็”จไบŽๆ•่Žทๅผ‚ๅธธใ€‚ +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `except` ๆฅๆ•่Žทๅผ•ๅ‘็š„ๅผ‚ๅธธๅนถๅฏนๅ…ถ่ฟ›่กŒๅค„็†ใ€‚ -ๅŒๆ ท๏ผŒไฝ ๅฏไปฅๅœจ `yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ไธญๆŠ›ๅ‡บไธ€ไธช `HTTPException` ๆˆ–็ฑปไผผ็š„ๅผ‚ๅธธใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆŠ›ๅ‡บไธ€ไธชไธๅŒ็š„ๅผ‚ๅธธ๏ผŒๅฆ‚ `HTTPException`ใ€‚ /// tip | ๆ็คบ -่ฟ™ๆ˜ฏไธ€็ง็›ธๅฏน้ซ˜็บง็š„ๆŠ€ๅทง๏ผŒๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹ไฝ ๅนถไธ้œ€่ฆไฝฟ็”จๅฎƒ๏ผŒๅ› ไธบไฝ ๅฏไปฅๅœจๅ…ถไป–ไปฃ็ ไธญๆŠ›ๅ‡บๅผ‚ๅธธ๏ผˆๅŒ…ๆ‹ฌ `HTTPException` ๏ผ‰๏ผŒไพ‹ๅฆ‚ๅœจ *่ทฏ็”ฑๅ‡ฝๆ•ฐ* ไธญใ€‚ +่ฟ™ๆ˜ฏไธ€็ง็›ธๅฏน้ซ˜็บง็š„ๆŠ€ๅทง๏ผŒๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹ไฝ ๅนถไธ้œ€่ฆไฝฟ็”จๅฎƒ๏ผŒๅ› ไธบไฝ ๅฏไปฅๅœจๅบ”็”จ็š„ๅ…ถไป–ไปฃ็ ไธญ๏ผˆไพ‹ๅฆ‚ๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ้‡Œ๏ผ‰ๆŠ›ๅ‡บๅผ‚ๅธธ๏ผˆๅŒ…ๆ‹ฌ `HTTPException`๏ผ‰ใ€‚ -ไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ้œ€่ฆ๏ผŒไฝ ไนŸๅฏไปฅๅœจไพ่ต–้กนไธญๅšๅˆฐ่ฟ™ไธ€็‚นใ€‚๐Ÿค“ +ไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ้œ€่ฆ๏ผŒๅฎƒๅฐฑๅœจ่ฟ™้‡Œใ€‚๐Ÿค“ /// {* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} -ไฝ ่ฟ˜ๅฏไปฅๅˆ›ๅปบไธ€ไธช [่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} ็”จไบŽๆ•่Žทๅผ‚ๅธธ๏ผˆๅŒๆ—ถไนŸๅฏไปฅๆŠ›ๅ‡บๅฆไธ€ไธช `HTTPException`๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณๆ•่Žทๅผ‚ๅธธๅนถๅŸบไบŽๅฎƒๅˆ›ๅปบไธ€ไธช่‡ชๅฎšไน‰ๅ“ๅบ”๏ผŒ่ฏทๅˆ›ๅปบไธ€ไธช[่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ใ€‚ -## ๅŒ…ๅซ `yield` ๅ’Œ `except` ็š„ไพ่ต–้กน +## ๅŒๆ—ถไฝฟ็”จ `yield` ๅ’Œ `except` ็š„ไพ่ต–้กน { #dependencies-with-yield-and-except } -ๅฆ‚ๆžœไฝ ๅœจๅŒ…ๅซ `yield` ็š„ไพ่ต–้กนไธญไฝฟ็”จ `except` ๆ•่Žทไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒ็„ถๅŽไฝ ๆฒกๆœ‰้‡ๆ–ฐๆŠ›ๅ‡บ่ฏฅๅผ‚ๅธธ๏ผˆๆˆ–ๆŠ›ๅ‡บไธ€ไธชๆ–ฐๅผ‚ๅธธ๏ผ‰๏ผŒไธŽๅœจๆ™ฎ้€š็š„Pythonไปฃ็ ไธญ็›ธๅŒ๏ผŒFastAPIไธไผšๆณจๆ„ๅˆฐๅ‘็”Ÿไบ†ๅผ‚ๅธธใ€‚ +ๅฆ‚ๆžœไฝ ๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญไฝฟ็”จ `except` ๆ•่Žทไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒๅนถไธ”ไฝ ๆฒกๆœ‰ๅ†ๆฌกๆŠ›ๅ‡บๅฎƒ๏ผˆๆˆ–ๆŠ›ๅ‡บไธ€ไธชๆ–ฐๅผ‚ๅธธ๏ผ‰๏ผŒFastAPI ๅฐ†ๆ— ๆณ•ๅฏŸ่ง‰ๅ‘็”Ÿ่ฟ‡ๅผ‚ๅธธ๏ผŒๅฐฑๅƒๆ™ฎ้€š็š„ Python ไปฃ็ ้‚ฃๆ ท๏ผš {* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} -ๅœจ็คบไพ‹ไปฃ็ ็š„ๆƒ…ๅ†ตไธ‹๏ผŒๅฎขๆˆท็ซฏๅฐ†ไผšๆ”ถๅˆฐ *HTTP 500 Internal Server Error* ็š„ๅ“ๅบ”๏ผŒๅ› ไธบๆˆ‘ไปฌๆฒกๆœ‰ๆŠ›ๅ‡บ `HTTPException` ๆˆ–่€…็ฑปไผผ็š„ๅผ‚ๅธธ๏ผŒๅนถไธ”ๆœๅŠกๅ™จไนŸ **ไธไผšๆœ‰ไปปไฝ•ๆ—ฅๅฟ—** ๆˆ–่€…ๅ…ถไป–ๆ็คบๆฅๅ‘Š่ฏ‰ๆˆ‘ไปฌ้”™่ฏฏๆ˜ฏไป€ไนˆใ€‚๐Ÿ˜ฑ +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฎขๆˆท็ซฏไผšๅƒ้ข„ๆœŸ้‚ฃๆ ท็œ‹ๅˆฐไธ€ไธช *HTTP 500 Internal Server Error* ๅ“ๅบ”๏ผŒๅ› ไธบๆˆ‘ไปฌๆฒกๆœ‰ๆŠ›ๅ‡บ `HTTPException` ๆˆ–็ฑปไผผๅผ‚ๅธธ๏ผŒไฝ†ๆœๅŠกๅ™จๅฐ†**ๆฒกๆœ‰ไปปไฝ•ๆ—ฅๅฟ—**ๆˆ–ๅ…ถไป–ๅ…ณไบŽ้”™่ฏฏๆ˜ฏไป€ไนˆ็š„ๆ็คบใ€‚๐Ÿ˜ฑ -### ๅœจๅŒ…ๅซ `yield` ๅ’Œ `except` ็š„ไพ่ต–้กนไธญไธ€ๅฎš่ฆ `raise` +### ๅœจๅธฆๆœ‰ `yield` ๅ’Œ `except` ็š„ไพ่ต–ไธญๅŠกๅฟ… `raise` { #always-raise-in-dependencies-with-yield-and-except } -ๅฆ‚ๆžœไฝ ๅœจไฝฟ็”จ `yield` ็š„ไพ่ต–้กนไธญๆ•่Žทๅˆฐไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒไฝ ๅบ”่ฏฅๅ†ๆฌกๆŠ›ๅ‡บๆ•่Žทๅˆฐ็š„ๅผ‚ๅธธ๏ผŒ้™ค้žไฝ ๆŠ›ๅ‡บ `HTTPException` ๆˆ–็ฑปไผผ็š„ๅ…ถไป–ๅผ‚ๅธธ๏ผŒ +ๅฆ‚ๆžœไฝ ๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญๆ•่Žทๅˆฐไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒ้™ค้žไฝ ๆŠ›ๅ‡บๅฆไธ€ไธช `HTTPException` ๆˆ–็ฑปไผผๅผ‚ๅธธ๏ผŒ**ๅฆๅˆ™ไฝ ๅบ”่ฏฅ้‡ๆ–ฐๆŠ›ๅ‡บๅŽŸๅง‹ๅผ‚ๅธธ**ใ€‚ -ไฝ ๅฏไปฅไฝฟ็”จ `raise` ๅ†ๆฌกๆŠ›ๅ‡บๆ•่Žทๅˆฐ็š„ๅผ‚ๅธธใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ `raise` ้‡ๆ–ฐๆŠ›ๅ‡บๅŒไธ€ไธชๅผ‚ๅธธ๏ผš {* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} -็Žฐๅœจๅฎขๆˆท็ซฏๅŒๆ ทไผšๅพ—ๅˆฐ *HTTP 500 Internal Server Error* ๅ“ๅบ”๏ผŒไฝ†ๆ˜ฏๆœๅŠกๅ™จๆ—ฅๅฟ—ไผš่ฎฐๅฝ•ไธ‹ๆˆ‘ไปฌ่‡ชๅฎšไน‰็š„ `InternalError`ใ€‚ +็Žฐๅœจๅฎขๆˆท็ซฏไปไผšๅพ—ๅˆฐๅŒๆ ท็š„ *HTTP 500 Internal Server Error* ๅ“ๅบ”๏ผŒไฝ†ๆœๅŠกๅ™จๆ—ฅๅฟ—ไธญไผšๆœ‰ๆˆ‘ไปฌ่‡ชๅฎšไน‰็š„ `InternalError`ใ€‚๐Ÿ˜Ž -## ไฝฟ็”จ `yield` ็š„ไพ่ต–้กน็š„ๆ‰ง่กŒ +## ไฝฟ็”จ `yield` ็š„ไพ่ต–้กน็š„ๆ‰ง่กŒ { #execution-of-dependencies-with-yield } -ๆ‰ง่กŒ้กบๅบๅคง่‡ดๅฆ‚ไธ‹ๆ—ถๅบๅ›พๆ‰€็คบใ€‚ๆ—ถ้—ด่ฝดไปŽไธŠๅˆฐไธ‹๏ผŒๆฏไธ€ๅˆ—้ƒฝไปฃ่กจไบคไบ’ๆˆ–่€…ไปฃ็ ๆ‰ง่กŒ็š„ไธ€้ƒจๅˆ†ใ€‚ +ๆ‰ง่กŒ้กบๅบๅคง่‡ดๅฆ‚ไธ‹ๅ›พๆ‰€็คบใ€‚ๆ—ถ้—ด่ฝดไปŽไธŠๅˆฐไธ‹๏ผŒๆฏไธ€ๅˆ—้ƒฝไปฃ่กจไบคไบ’ๆˆ–ๆ‰ง่กŒไปฃ็ ็š„ไธ€้ƒจๅˆ†ใ€‚ ```mermaid sequenceDiagram @@ -167,63 +170,78 @@ participant tasks as Background tasks end ``` -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๅชไผšๅ‘ๅฎขๆˆท็ซฏๅ‘้€ **ไธ€ๆฌกๅ“ๅบ”** ๏ผŒๅฏ่ƒฝๆ˜ฏไธ€ไธช้”™่ฏฏๅ“ๅบ”๏ผŒไนŸๅฏ่ƒฝๆ˜ฏๆฅ่‡ช *่ทฏ็”ฑๅ‡ฝๆ•ฐ* ็š„ๅ“ๅบ”ใ€‚ +ๅชไผšๅ‘ๅฎขๆˆท็ซฏๅ‘้€**ไธ€ๆฌกๅ“ๅบ”**ใ€‚ๅฎƒๅฏ่ƒฝๆ˜ฏๆŸไธช้”™่ฏฏๅ“ๅบ”๏ผŒๆˆ–่€…ๆ˜ฏๆฅ่‡ช *่ทฏๅพ„ๆ“ไฝœ* ็š„ๅ“ๅบ”ใ€‚ -ๅœจๅ‘้€ไบ†ๅ…ถไธญไธ€ไธชๅ“ๅบ”ไน‹ๅŽ๏ผŒๅฐฑๆ— ๆณ•ๅ†ๅ‘้€ๅ…ถไป–ๅ“ๅบ”ไบ†ใ€‚ +ๅœจๅ…ถไธญไธ€ไธชๅ“ๅบ”ๅ‘้€ไน‹ๅŽ๏ผŒๅฐฑไธ่ƒฝๅ†ๅ‘้€ๅ…ถไป–ๅ“ๅบ”ไบ†ใ€‚ /// /// tip | ๆ็คบ -่ฟ™ไธชๆ—ถๅบๅ›พๅฑ•็คบไบ† `HTTPException`๏ผŒ้™คๆญคไน‹ๅค–ไฝ ไนŸๅฏไปฅๆŠ›ๅ‡บไปปไฝ•ไฝ ๅœจไฝฟ็”จ `yield` ็š„ไพ่ต–้กนไธญๆˆ–่€…[่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ไธญๆ•่Žท็š„ๅผ‚ๅธธใ€‚ - -ๅฆ‚ๆžœไฝ ๅผ•ๅ‘ไปปไฝ•ๅผ‚ๅธธ๏ผŒๅฎƒๅฐ†ไผ ้€’็ป™ไฝฟ็”จ `yield` ็š„ไพ่ต–้กน๏ผŒๅŒ…ๆ‹ฌ `HTTPException`ใ€‚ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹ไฝ ๅบ”ๅฝ“ไปŽไฝฟ็”จ `yield` ็š„ไพ่ต–้กนไธญ้‡ๆ–ฐๆŠ›ๅ‡บๆ•่Žท็š„ๅผ‚ๅธธๆˆ–่€…ไธ€ไธชๆ–ฐ็š„ๅผ‚ๅธธๆฅ็กฎไฟๅฎƒไผš่ขซๆญฃ็กฎ็š„ๅค„็†ใ€‚ +ๅฆ‚ๆžœไฝ ๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็š„ไปฃ็ ไธญๅผ•ๅ‘ไปปไฝ•ๅผ‚ๅธธ๏ผŒๅฎƒ้ƒฝไผš่ขซไผ ้€’็ป™ๅธฆๆœ‰ `yield` ็š„ไพ่ต–้กน๏ผŒๅŒ…ๆ‹ฌ `HTTPException`ใ€‚ๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ไผšๅธŒๆœ›ๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญ้‡ๆ–ฐๆŠ›ๅ‡บ็›ธๅŒ็š„ๅผ‚ๅธธๆˆ–ไธ€ไธชๆ–ฐ็š„ๅผ‚ๅธธ๏ผŒไปฅ็กฎไฟๅฎƒ่ขซๆญฃ็กฎๅค„็†ใ€‚ /// -## ๅŒ…ๅซ `yield`, `HTTPException`, `except` ็š„ไพ่ต–้กนๅ’ŒๅŽๅฐไปปๅŠก +## ๆๅ‰้€€ๅ‡บไธŽ `scope` { #early-exit-and-scope } -/// warning | ๆณจๆ„ +้€šๅธธ๏ผŒๅธฆๆœ‰ `yield` ็š„ไพ่ต–็š„้€€ๅ‡บไปฃ็ ไผšๅœจๅ“ๅบ”ๅ‘้€็ป™ๅฎขๆˆท็ซฏ**ไน‹ๅŽ**ๆ‰ง่กŒใ€‚ -ไฝ ๅคงๆฆ‚็އไธ้œ€่ฆไบ†่งฃ่ฟ™ไบ›ๆŠ€ๆœฏ็ป†่Š‚๏ผŒๅฏไปฅ่ทณ่ฟ‡่ฟ™ไธ€็ซ ่Š‚็ปง็ปญ้˜…่ฏปๅŽ็ปญ็š„ๅ†…ๅฎนใ€‚ +ไฝ†ๅฆ‚ๆžœไฝ ็Ÿฅ้“ๅœจไปŽ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ่ฟ”ๅ›žไน‹ๅŽไธๅ†้œ€่ฆไฝฟ็”จ่ฏฅไพ่ต–๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Depends(scope="function")` ๅ‘Š่ฏ‰ FastAPI๏ผšๅบ”ๅฝ“ๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ่ฟ”ๅ›žๅŽใ€ไฝ†ๅœจ**ๅ“ๅบ”ๅ‘้€ไน‹ๅ‰**ๅ…ณ้—ญ่ฏฅไพ่ต–ใ€‚ -ๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„FastAPI็š„็‰ˆๆœฌๆ—ฉไบŽ0.106.0๏ผŒๅนถไธ”ๅœจไฝฟ็”จๅŽๅฐไปปๅŠกไธญไฝฟ็”จไบ†ๅŒ…ๅซ `yield` ็š„ไพ่ต–้กนไธญ็š„่ต„ๆบ๏ผŒ้‚ฃไนˆ่ฟ™ไบ›็ป†่Š‚ไผšๅฏนไฝ ๆœ‰ไธ€ไบ›็”จๅค„ใ€‚ +{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} -/// +`Depends()` ๆŽฅๆ”ถไธ€ไธช `scope` ๅ‚ๆ•ฐ๏ผŒๅฏไธบ๏ผš -### ๅŒ…ๅซ `yield` ๅ’Œ `except` ็š„ไพ่ต–้กน็š„ๆŠ€ๆœฏ็ป†่Š‚ +* `"function"`๏ผšๅœจๅค„็†่ฏทๆฑ‚็š„ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไน‹ๅ‰ๅฏๅŠจไพ่ต–๏ผŒๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็ป“ๆŸๅŽ็ป“ๆŸไพ่ต–๏ผŒไฝ†ๅœจๅ“ๅบ”ๅ‘้€็ป™ๅฎขๆˆท็ซฏ**ไน‹ๅ‰**ใ€‚ๅ› ๆญค๏ผŒไพ่ต–ๅ‡ฝๆ•ฐๅฐ†ๅ›ด็ป•่ฟ™ไธช*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ๆ‰ง่กŒใ€‚ +* `"request"`๏ผšๅœจๅค„็†่ฏทๆฑ‚็š„ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไน‹ๅ‰ๅฏๅŠจไพ่ต–๏ผˆไธŽไฝฟ็”จ `"function"` ๆ—ถ็ฑปไผผ๏ผ‰๏ผŒไฝ†ๅœจๅ“ๅบ”ๅ‘้€็ป™ๅฎขๆˆท็ซฏ**ไน‹ๅŽ**็ป“ๆŸใ€‚ๅ› ๆญค๏ผŒไพ่ต–ๅ‡ฝๆ•ฐๅฐ†ๅ›ด็ป•่ฟ™ไธช**่ฏทๆฑ‚**ไธŽๅ“ๅบ”ๅ‘จๆœŸๆ‰ง่กŒใ€‚ -ๅœจFastAPI 0.110.0็‰ˆๆœฌไน‹ๅ‰๏ผŒๅฆ‚ๆžœไฝฟ็”จไบ†ไธ€ไธชๅŒ…ๅซ `yield` ็š„ไพ่ต–้กน๏ผŒไฝ ๅœจไพ่ต–้กนไธญไฝฟ็”จ `except` ๆ•่Žทไบ†ไธ€ไธชๅผ‚ๅธธ๏ผŒไฝ†ๆ˜ฏไฝ ๆฒกๆœ‰ๅ†ๆฌกๆŠ›ๅ‡บ่ฏฅๅผ‚ๅธธ๏ผŒ่ฟ™ไธชๅผ‚ๅธธไผš่ขซ่‡ชๅŠจๆŠ›ๅ‡บ/่ฝฌๅ‘ๅˆฐๅผ‚ๅธธๅค„็†ๅ™จๆˆ–่€…ๅ†…้ƒจๆœๅŠก้”™่ฏฏๅค„็†ๅ™จใ€‚ +ๅฆ‚ๆžœๆœชๆŒ‡ๅฎšไธ”ไพ่ต–ๅŒ…ๅซ `yield`๏ผŒๅˆ™้ป˜่ฎค `scope` ไธบ `"request"`ใ€‚ -### ๅŽๅฐไปปๅŠกๅ’Œไฝฟ็”จ `yield` ็š„ไพ่ต–้กน็š„ๆŠ€ๆœฏ็ป†่Š‚ +### ๅญไพ่ต–็š„ `scope` { #scope-for-sub-dependencies } -ๅœจFastAPI 0.106.0็‰ˆๆœฌไน‹ๅ‰๏ผŒๅœจ `yield` ๅŽ้ขๆŠ›ๅ‡บๅผ‚ๅธธๆ˜ฏไธๅฏ่กŒ็š„๏ผŒๅ› ไธบ `yield` ไน‹ๅŽ็š„้€€ๅ‡บไปฃ็ ๆ˜ฏๅœจๅ“ๅบ”่ขซๅ‘้€ไน‹ๅŽๅ†ๆ‰ง่กŒ๏ผŒ่ฟ™ไธชๆ—ถๅ€™ๅผ‚ๅธธๅค„็†ๅ™จๅทฒ็ปๆ‰ง่กŒ่ฟ‡ไบ†ใ€‚ +ๅฝ“ไฝ ๅฃฐๆ˜Žไธ€ไธช `scope="request"`๏ผˆ้ป˜่ฎค๏ผ‰็š„ไพ่ต–ๆ—ถ๏ผŒไปปไฝ•ๅญไพ่ต–ไนŸ้œ€่ฆๆœ‰ `"request"` ็š„ `scope`ใ€‚ -่ฟ™ๆ ท่ฎพ่ฎก็š„็›ฎ็š„ไธป่ฆๆ˜ฏไธบไบ†ๅ…่ฎธๅœจๅŽๅฐไปปๅŠกไธญไฝฟ็”จ่ขซไพ่ต–้กน`yield`็š„ๅฏน่ฑก๏ผŒๅ› ไธบ้€€ๅ‡บไปฃ็ ไผšๅœจๅŽๅฐไปปๅŠก็ป“ๆŸๅŽๅ†ๆ‰ง่กŒใ€‚ +ไฝ†ไธ€ไธช `scope` ไธบ `"function"` ็š„ไพ่ต–ๅฏไปฅๆœ‰ `scope` ไธบ `"function"` ๅ’Œ `"request"` ็š„ๅญไพ่ต–ใ€‚ -็„ถ่€Œ่ฟ™ไนŸๆ„ๅ‘ณ็€ๅœจ็ญ‰ๅพ…ๅ“ๅบ”้€š่ฟ‡็ฝ‘็ปœไผ ่พ“็š„ๅŒๆ—ถ๏ผŒ้žๅฟ…่ฆ็š„ๆŒๆœ‰ไธ€ไธช `yield` ไพ่ต–้กนไธญ็š„่ต„ๆบ๏ผˆไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“่ฟžๆŽฅ๏ผ‰๏ผŒ่ฟ™ไธ€่กŒไธบๅœจFastAPI 0.106.0่ขซๆ”นๅ˜ไบ†ใ€‚ +่ฟ™ๆ˜ฏๅ› ไธบไปปไฝ•ไพ่ต–้ƒฝ้œ€่ฆ่ƒฝๅคŸๅœจๅญไพ่ต–ไน‹ๅ‰่ฟ่กŒๅ…ถ้€€ๅ‡บไปฃ็ ๏ผŒๅ› ไธบๅฎƒ็š„้€€ๅ‡บไปฃ็ ไธญๅฏ่ƒฝ่ฟ˜้œ€่ฆไฝฟ็”จ่ฟ™ไบ›ๅญไพ่ต–ใ€‚ -/// tip | ๆ็คบ +```mermaid +sequenceDiagram -้™คๆญคไน‹ๅค–๏ผŒๅŽๅฐไปปๅŠก้€šๅธธๆ˜ฏไธ€็ป„็‹ฌ็ซ‹็š„้€ป่พ‘๏ผŒๅบ”่ฏฅ่ขซๅ•็‹ฌๅค„็†๏ผŒๅนถไธ”ไฝฟ็”จๅฎƒ่‡ชๅทฑ็š„่ต„ๆบ๏ผˆไพ‹ๅฆ‚ๅฎƒ่‡ชๅทฑ็š„ๆ•ฐๆฎๅบ“่ฟžๆŽฅ๏ผ‰ใ€‚ +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation -่ฟ™ๆ ทไนŸไผš่ฎฉไฝ ็š„ไปฃ็ ๆ›ดๅŠ ็ฎ€ๆดใ€‚ + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` -/// +## ๅŒ…ๅซ `yield`ใ€`HTTPException`ใ€`except` ๅ’ŒๅŽๅฐไปปๅŠก็š„ไพ่ต–้กน { #dependencies-with-yield-httpexception-except-and-background-tasks } -ๅฆ‚ๆžœไฝ ไน‹ๅ‰ไพ่ต–ไบŽ่ฟ™ไธ€่กŒไธบ๏ผŒ้‚ฃไนˆ็Žฐๅœจไฝ ๅบ”่ฏฅๅœจๅŽๅฐไปปๅŠกไธญๅˆ›ๅปบๅนถไฝฟ็”จๅฎƒ่‡ชๅทฑ็š„่ต„ๆบ๏ผŒไธ่ฆๅœจๅ†…้ƒจไฝฟ็”จๅฑžไบŽ `yield` ไพ่ต–้กน็š„่ต„ๆบใ€‚ +ๅธฆๆœ‰ `yield` ็š„ไพ่ต–้กน้š็€ๆ—ถ้—ดๆผ”่ฟ›ไปฅๆถต็›–ไธๅŒ็š„็”จไพ‹ๅนถไฟฎๅคไบ†ไธ€ไบ›้—ฎ้ข˜ใ€‚ -ไพ‹ๅฆ‚๏ผŒไฝ ๅบ”่ฏฅๅœจๅŽๅฐไปปๅŠกไธญๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ๆ•ฐๆฎๅบ“ไผš่ฏ็”จไบŽๆŸฅ่ฏขๆ•ฐๆฎ๏ผŒ่€Œไธๆ˜ฏไฝฟ็”จ็›ธๅŒ็š„ไผš่ฏใ€‚ไฝ ๅบ”่ฏฅๅฐ†ๅฏน่ฑก็š„IDไฝœไธบๅ‚ๆ•ฐไผ ้€’็ป™ๅŽๅฐไปปๅŠกๅ‡ฝๆ•ฐ๏ผŒ็„ถๅŽๅœจ่ฏฅๅ‡ฝๆ•ฐไธญ้‡ๆ–ฐ่Žทๅ–่ฏฅๅฏน่ฑก๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๅฐ†ๆ•ฐๆฎๅบ“ๅฏน่ฑกไฝœไธบๅ‚ๆ•ฐใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃๅœจไธๅŒ FastAPI ็‰ˆๆœฌไธญๅ‘็”Ÿไบ†ๅ“ชไบ›ๅ˜ๅŒ–๏ผŒๅฏไปฅๅœจ่ฟ›้˜ถๆŒ‡ๅ—ไธญ้˜…่ฏปๆ›ดๅคš๏ผš[้ซ˜็บงไพ่ต–้กน โ€”โ€” ๅŒ…ๅซ `yield`ใ€`HTTPException`ใ€`except` ๅ’ŒๅŽๅฐไปปๅŠก็š„ไพ่ต–้กน](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}ใ€‚ -## ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ +## ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ { #context-managers } -### ไป€ไนˆๆ˜ฏ"ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ" +### ไป€ไนˆๆ˜ฏโ€œไธŠไธ‹ๆ–‡็ฎก็†ๅ™จโ€ { #what-are-context-managers } -"ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ"ๆ˜ฏไฝ ๅฏไปฅๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ็š„ไปปไฝ•Pythonๅฏน่ฑกใ€‚ +โ€œไธŠไธ‹ๆ–‡็ฎก็†ๅ™จโ€ๆ˜ฏไฝ ๅฏไปฅๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ็š„ไปปๆ„ Python ๅฏน่ฑกใ€‚ -ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅไฝฟ็”จ`with`่ฏปๅ–ๆ–‡ไปถ๏ผš +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จ `with` ๆฅ่ฏปๅ–ๆ–‡ไปถ๏ผš ```Python with open("./somefile.txt") as f: @@ -231,37 +249,39 @@ with open("./somefile.txt") as f: print(contents) ``` -ๅœจๅบ•ๅฑ‚๏ผŒ`open("./somefile.txt")`ๅˆ›ๅปบไบ†ไธ€ไธช่ขซ็งฐไธบ"ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ"็š„ๅฏน่ฑกใ€‚ +ๅœจๅบ•ๅฑ‚๏ผŒ`open("./somefile.txt")` ไผšๅˆ›ๅปบไธ€ไธชโ€œไธŠไธ‹ๆ–‡็ฎก็†ๅ™จโ€ๅฏน่ฑกใ€‚ -ๅฝ“ `with` ไปฃ็ ๅ—็ป“ๆŸๆ—ถ๏ผŒๅฎƒไผš็กฎไฟๅ…ณ้—ญๆ–‡ไปถ๏ผŒๅณไฝฟๅ‘็”Ÿไบ†ๅผ‚ๅธธไนŸๆ˜ฏๅฆ‚ๆญคใ€‚ +ๅฝ“ `with` ไปฃ็ ๅ—็ป“ๆŸๆ—ถ๏ผŒๅฎƒไผš็กฎไฟๆ–‡ไปถ่ขซๅ…ณ้—ญ๏ผŒๅณไฝฟๆœŸ้—ดๅ‘็”Ÿไบ†ๅผ‚ๅธธใ€‚ -ๅฝ“ไฝ ไฝฟ็”จ `yield` ๅˆ›ๅปบไธ€ไธชไพ่ต–้กนๆ—ถ๏ผŒ**FastAPI** ไผšๅœจๅ†…้ƒจๅฐ†ๅ…ถ่ฝฌๆขไธบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ๏ผŒๅนถไธŽๅ…ถไป–็›ธๅ…ณๅทฅๅ…ท็ป“ๅˆไฝฟ็”จใ€‚ +ๅฝ“ไฝ ็”จ `yield` ๅˆ›ๅปบไธ€ไธชไพ่ต–ๆ—ถ๏ผŒ**FastAPI** ไผšๅœจๅ†…้ƒจไธบๅฎƒๅˆ›ๅปบไธ€ไธชไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ๏ผŒๅนถไธŽๅ…ถไป–็›ธๅ…ณๅทฅๅ…ท็ป“ๅˆไฝฟ็”จใ€‚ -### ๅœจไฝฟ็”จ `yield` ็š„ไพ่ต–้กนไธญไฝฟ็”จไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ +### ๅœจๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญไฝฟ็”จไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ { #using-context-managers-in-dependencies-with-yield } -/// warning | ๆณจๆ„ +/// warning | ่ญฆๅ‘Š -่ฟ™ๆ˜ฏไธ€ไธชๆ›ดไธบ"้ซ˜็บง"็š„ๆƒณๆณ•ใ€‚ +่ฟ™็ฎ—ๆ˜ฏไธ€ไธชโ€œ้ซ˜็บงโ€ๆฆ‚ๅฟตใ€‚ -ๅฆ‚ๆžœไฝ ๅˆšๅผ€ๅง‹ไฝฟ็”จ **FastAPI** ๏ผŒไฝ ๅฏไปฅๆš‚ๆ—ถๅฏไปฅ่ทณ่ฟ‡ๅฎƒใ€‚ +ๅฆ‚ๆžœไฝ ๅˆšๅผ€ๅง‹ไฝฟ็”จ **FastAPI**๏ผŒ็Žฐๅœจๅฏไปฅๅ…ˆ่ทณ่ฟ‡ใ€‚ /// -ๅœจPythonไธญ๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ๅˆ›ๅปบไธ€ไธชๅธฆๆœ‰`__enter__()`ๅ’Œ`__exit__()`ๆ–นๆณ•็š„็ฑปๆฅๅˆ›ๅปบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จใ€‚ +ๅœจ Python ไธญ๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ๅˆ›ๅปบไธ€ไธชๅธฆๆœ‰ `__enter__()` ๅ’Œ `__exit__()` ๆ–นๆณ•็š„็ฑปๆฅๅˆ›ๅปบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จใ€‚ -ไฝ ไนŸๅฏไปฅๅœจ **FastAPI** ็š„ `yield` ไพ่ต–้กนไธญ้€š่ฟ‡ `with` ๆˆ–่€… `async with` ่ฏญๅฅๆฅไฝฟ็”จๅฎƒไปฌ๏ผš +ไฝ ไนŸๅฏไปฅๅœจ **FastAPI** ็š„ๅธฆๆœ‰ `yield` ็š„ไพ่ต–ไธญ๏ผŒไฝฟ็”จไพ่ต–ๅ‡ฝๆ•ฐๅ†…้ƒจ็š„ `with` ๆˆ– `async with` ่ฏญๅฅๆฅไฝฟ็”จๅฎƒไปฌ๏ผš -{* ../../docs_src/dependencies/tutorial010.py hl[1:9,13] *} +{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *} /// tip | ๆ็คบ -ๅฆไธ€็งๅˆ›ๅปบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ็š„ๆ–นๆณ•ๆ˜ฏ๏ผš +ๅฆไธ€็งๅˆ›ๅปบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ็š„ๆ–นๅผๆ˜ฏ๏ผš + +* `@contextlib.contextmanager` ๆˆ– +* `@contextlib.asynccontextmanager` -* `@contextlib.contextmanager`ๆˆ–่€… -* `@contextlib.asynccontextmanager` +็”จๅฎƒไปฌๅŽป่ฃ…้ฅฐไธ€ไธชๅชๅŒ…ๅซๅ•ไธช `yield` ็š„ๅ‡ฝๆ•ฐใ€‚ -ไฝฟ็”จๅฎƒไปฌ่ฃ…้ฅฐไธ€ไธชๅชๆœ‰ๅ•ไธช `yield` ็š„ๅ‡ฝๆ•ฐใ€‚่ฟ™ๅฐฑๆ˜ฏ **FastAPI** ๅ†…้ƒจๅฏนไบŽ `yield` ไพ่ต–้กน็š„ๅค„็†ๆ–นๅผใ€‚ +่ฟ™ๆญฃๆ˜ฏ **FastAPI** ๅœจๅ†…้ƒจๅค„็†ๅธฆๆœ‰ `yield` ็š„ไพ่ต–ๆ—ถๆ‰€ไฝฟ็”จ็š„ๆ–นๅผใ€‚ -ไฝ†ๆ˜ฏไฝ ไธ้œ€่ฆไธบFastAPI็š„ไพ่ต–้กนไฝฟ็”จ่ฟ™ไบ›่ฃ…้ฅฐๅ™จ๏ผˆ่€Œไธ”ไนŸไธๅบ”่ฏฅ๏ผ‰ใ€‚FastAPIไผšๅœจๅ†…้ƒจไธบไฝ ๅค„็†่ฟ™ไบ›ใ€‚ +ไฝ†ไฝ ไธ้œ€่ฆ๏ผˆไนŸไธๅบ”่ฏฅ๏ผ‰ไธบ FastAPI ็š„ไพ่ต–ๅŽปไฝฟ็”จ่ฟ™ไบ›่ฃ…้ฅฐๅ™จใ€‚FastAPI ไผšๅœจๅ†…้ƒจไธบไฝ ๅค„็†ๅฅฝใ€‚ /// diff --git a/docs/zh/docs/tutorial/dependencies/global-dependencies.md b/docs/zh/docs/tutorial/dependencies/global-dependencies.md index 797fd76b7c..36cf9cf447 100644 --- a/docs/zh/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/global-dependencies.md @@ -1,15 +1,15 @@ -# ๅ…จๅฑ€ไพ่ต–้กน +# ๅ…จๅฑ€ไพ่ต–้กน { #global-dependencies } ๆœ‰ๆ—ถ๏ผŒๆˆ‘ไปฌ่ฆไธบๆ•ดไธชๅบ”็”จๆทปๅŠ ไพ่ต–้กนใ€‚ -้€š่ฟ‡ไธŽๅฎšไน‰[*่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กน*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ็ฑปไผผ็š„ๆ–นๅผ๏ผŒๅฏไปฅๆŠŠไพ่ต–้กนๆทปๅŠ ่‡ณๆ•ดไธช `FastAPI` ๅบ”็”จใ€‚ +้€š่ฟ‡ไธŽ[ๅฐ† `dependencies` ๆทปๅŠ ๅˆฐ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ็ฑปไผผ็š„ๆ–นๅผ๏ผŒๅฏไปฅๆŠŠไพ่ต–้กนๆทปๅŠ ่‡ณๆ•ดไธช `FastAPI` ๅบ”็”จใ€‚ ่ฟ™ๆ ทไธ€ๆฅ๏ผŒๅฐฑๅฏไปฅไธบๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ๅบ”็”จ่ฏฅไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial012.py hl[15] *} +{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *} -[*่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กน*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ไธ€็ซ ็š„ๆ€่ทฏๅ‡้€‚็”จไบŽๅ…จๅฑ€ไพ่ต–้กน๏ผŒ ๅœจๆœฌไพ‹ไธญ๏ผŒ่ฟ™ไบ›ไพ่ต–้กนๅฏไปฅ็”จไบŽๅบ”็”จไธญ็š„ๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ +[ๅฐ† `dependencies` ๆทปๅŠ ๅˆฐ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ไธ€็ซ ็š„ๆ€่ทฏๅ‡้€‚็”จไบŽๅ…จๅฑ€ไพ่ต–้กน๏ผŒ ๅœจๆœฌไพ‹ไธญ๏ผŒ่ฟ™ไบ›ไพ่ต–้กนๅฏไปฅ็”จไบŽๅบ”็”จไธญ็š„ๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ -## ไธบไธ€็ป„่ทฏๅพ„ๆ“ไฝœๅฎšไน‰ไพ่ต–้กน +## ไธบไธ€็ป„่ทฏๅพ„ๆ“ไฝœๅฎšไน‰ไพ่ต–้กน { #dependencies-for-groups-of-path-operations } ็จๅŽ๏ผŒ[ๅคงๅž‹ๅบ”็”จ - ๅคšๆ–‡ไปถ](../../tutorial/bigger-applications.md){.internal-link target=_blank}ไธ€็ซ ไธญไผšไป‹็ปๅฆ‚ไฝ•ไฝฟ็”จๅคšไธชๆ–‡ไปถๅˆ›ๅปบๅคงๅž‹ๅบ”็”จ็จ‹ๅบ๏ผŒๅœจ่ฟ™ไธ€็ซ ไธญ๏ผŒๆ‚จๅฐ†ไบ†่งฃๅˆฐๅฆ‚ไฝ•ไธบไธ€็ป„*่ทฏๅพ„ๆ“ไฝœ*ๅฃฐๆ˜Žๅ•ไธช `dependencies` ๅ‚ๆ•ฐใ€‚ diff --git a/docs/zh/docs/tutorial/dependencies/index.md b/docs/zh/docs/tutorial/dependencies/index.md index 9eec69ed5d..20d2c0b643 100644 --- a/docs/zh/docs/tutorial/dependencies/index.md +++ b/docs/zh/docs/tutorial/dependencies/index.md @@ -1,85 +1,97 @@ -# ไพ่ต–้กน +# ไพ่ต–้กน { #dependencies } -FastAPI ๆไพ›ไบ†็ฎ€ๅ•ๆ˜“็”จ๏ผŒไฝ†ๅŠŸ่ƒฝๅผบๅคง็š„**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸใ€‚ +**FastAPI** ๆไพ›ไบ†็ฎ€ๅ•็›ด่ง‚ไฝ†ๅŠŸ่ƒฝๅผบๅคง็š„**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸใ€‚ -่ฟ™ไธชไพ่ต–็ณป็ปŸ่ฎพ่ฎก็š„็ฎ€ๅ•ๆ˜“็”จ๏ผŒๅฏไปฅ่ฎฉๅผ€ๅ‘ไบบๅ‘˜่ฝปๆพๅœฐๆŠŠ็ป„ไปถ้›†ๆˆ่‡ณ **FastAPI**ใ€‚ +ๅฎƒ่ขซ่ฎพ่ฎกๅพ—้žๅธธๆ˜“็”จ๏ผŒ่ƒฝ่ฎฉไปปไฝ•ๅผ€ๅ‘่€…้ƒฝ่ƒฝ่ฝปๆพๆŠŠๅ…ถไป–็ป„ไปถไธŽ **FastAPI** ้›†ๆˆใ€‚ -## ไป€ไนˆๆ˜ฏใ€Œไพ่ต–ๆณจๅ…ฅใ€ +## ไป€ไนˆๆ˜ฏใ€Œไพ่ต–ๆณจๅ…ฅใ€ { #what-is-dependency-injection } -็ผ–็จ‹ไธญ็š„**ใ€Œไพ่ต–ๆณจๅ…ฅใ€**ๆ˜ฏๅฃฐๆ˜Žไปฃ็ ๏ผˆๆœฌๆ–‡ไธญไธบ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ๏ผ‰่ฟ่กŒๆ‰€้œ€็š„๏ผŒๆˆ–่ฆไฝฟ็”จ็š„ใ€Œไพ่ต–ใ€็š„ไธ€็งๆ–นๅผใ€‚ +ๅœจ็ผ–็จ‹ไธญ๏ผŒ**ใ€Œไพ่ต–ๆณจๅ…ฅใ€**ๆŒ‡็š„ๆ˜ฏ๏ผŒไฝ ็š„ไปฃ็ ๏ผˆๆœฌๆ–‡ไธญไธบ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*๏ผ‰ๅฃฐๆ˜Žๅ…ถ่ฟ่กŒๆ‰€้œ€ๅนถ่ฆไฝฟ็”จ็š„ไธœ่ฅฟ๏ผšโ€œไพ่ต–โ€ใ€‚ -็„ถๅŽ๏ผŒ็”ฑ็ณป็ปŸ๏ผˆๆœฌๆ–‡ไธญไธบ **FastAPI**๏ผ‰่ดŸ่ดฃๆ‰ง่กŒไปปๆ„้œ€่ฆ็š„้€ป่พ‘๏ผŒไธบไปฃ็ ๆไพ›่ฟ™ไบ›ไพ่ต–๏ผˆใ€Œๆณจๅ…ฅใ€ไพ่ต–้กน๏ผ‰ใ€‚ +็„ถๅŽ๏ผŒ็”ฑ่ฏฅ็ณป็ปŸ๏ผˆๆœฌๆ–‡ไธญไธบ **FastAPI**๏ผ‰่ดŸ่ดฃๆ‰ง่กŒๆ‰€ๆœ‰ๅฟ…่ฆ็š„้€ป่พ‘๏ผŒไธบไฝ ็š„ไปฃ็ ๆไพ›่ฟ™ไบ›ๆ‰€้œ€็š„ไพ่ต–๏ผˆโ€œๆณจๅ…ฅโ€ไพ่ต–๏ผ‰ใ€‚ -ไพ่ต–ๆณจๅ…ฅๅธธ็”จไบŽไปฅไธ‹ๅœบๆ™ฏ๏ผš +ๅฝ“ไฝ ้œ€่ฆไปฅไธ‹ๅ†…ๅฎนๆ—ถ๏ผŒ่ฟ™้žๅธธๆœ‰็”จ๏ผš -* ๅ…ฑไบซไธšๅŠก้€ป่พ‘๏ผˆๅค็”จ็›ธๅŒ็š„ไปฃ็ ้€ป่พ‘๏ผ‰ +* ๅ…ฑไบซไธšๅŠก้€ป่พ‘๏ผˆๅŒไธ€ๆฎตไปฃ็ ้€ป่พ‘ๅๅคๅค็”จ๏ผ‰ * ๅ…ฑไบซๆ•ฐๆฎๅบ“่ฟžๆŽฅ -* ๅฎž็Žฐๅฎ‰ๅ…จใ€้ชŒ่ฏใ€่ง’่‰ฒๆƒ้™ -* ็ญ‰โ€ฆโ€ฆ +* ๅฎžๆ–ฝๅฎ‰ๅ…จใ€่ฎค่ฏใ€่ง’่‰ฒๆƒ้™็ญ‰่ฆๆฑ‚ +* ไปฅๅŠๆ›ดๅคšๅ…ถไป–ๅ†…ๅฎน... -ไธŠ่ฟฐๅœบๆ™ฏๅ‡ๅฏไปฅไฝฟ็”จ**ไพ่ต–ๆณจๅ…ฅ**๏ผŒๅฐ†ไปฃ็ ้‡ๅคๆœ€ๅฐๅŒ–ใ€‚ +ๅŒๆ—ถๅฐฝ้‡ๅ‡ๅฐ‘ไปฃ็ ้‡ๅคใ€‚ -## ็ฌฌไธ€ๆญฅ +## ็ฌฌไธ€ๆญฅ { #first-steps } -ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅญฆไน ไธ€ไธช้žๅธธ็ฎ€ๅ•็š„ไพ‹ๅญ๏ผŒๅฐฝ็ฎกๅฎƒ่ฟ‡ไบŽ็ฎ€ๅ•๏ผŒไธๆ˜ฏๅพˆๅฎž็”จใ€‚ +ๅ…ˆๆฅ็œ‹ไธ€ไธช้žๅธธ็ฎ€ๅ•็š„ไพ‹ๅญใ€‚ๅฎƒ็Žฐๅœจ็ฎ€ๅ•ๅˆฐๅ‡ ไนŽๆฒกไป€ไนˆ็”จใ€‚ -ไฝ†้€š่ฟ‡่ฟ™ไธชไพ‹ๅญ๏ผŒๆ‚จๅฏไปฅๅˆๆญฅไบ†่งฃใ€Œไพ่ต–ๆณจๅ…ฅใ€็š„ๅทฅไฝœๆœบๅˆถใ€‚ +ไฝ†่ฟ™ๆ ทๆˆ‘ไปฌๅฐฑๅฏไปฅไธ“ๆณจไบŽ**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸๆ˜ฏๅฆ‚ไฝ•ๅทฅไฝœ็š„ใ€‚ -### ๅˆ›ๅปบไพ่ต–้กน +### ๅˆ›ๅปบไพ่ต–้กน๏ผŒๆˆ–โ€œdependableโ€ { #create-a-dependency-or-dependable } -้ฆ–ๅ…ˆ๏ผŒ่ฆๅ…ณๆณจ็š„ๆ˜ฏไพ่ต–้กนใ€‚ +้ฆ–ๅ…ˆๅ…ณๆณจไพ่ต–้กนใ€‚ -ไพ่ต–้กนๅฐฑๆ˜ฏไธ€ไธชๅ‡ฝๆ•ฐ๏ผŒไธ”ๅฏไปฅไฝฟ็”จไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็›ธๅŒ็š„ๅ‚ๆ•ฐ๏ผš +ๅฎƒๅชๆ˜ฏไธ€ไธชๅ‡ฝๆ•ฐ๏ผŒไธ”ๅฏไปฅๆŽฅๆ”ถไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็›ธๅŒ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/dependencies/tutorial001.py hl[8:11] *} +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} ๅคงๅŠŸๅ‘Šๆˆใ€‚ ๅช็”จไบ†**2 ่กŒ**ไปฃ็ ใ€‚ -ไพ่ต–้กนๅ‡ฝๆ•ฐ็š„ๅฝขๅผๅ’Œ็ป“ๆž„ไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธ€ๆ ทใ€‚ +ๅฎƒ็š„ๅฝขๅผๅ’Œ็ป“ๆž„ไธŽๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็›ธๅŒใ€‚ -ๅ› ๆญค๏ผŒๅฏไปฅๆŠŠไพ่ต–้กนๅฝ“ไฝœๆฒกๆœ‰ใ€Œ่ฃ…้ฅฐๅ™จใ€๏ผˆๅณ๏ผŒๆฒกๆœ‰ `@app.get("/some-path")` ๏ผ‰็š„่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐใ€‚ +ไฝ ๅฏไปฅๆŠŠๅฎƒๅฝ“ไฝœๆฒกๆœ‰โ€œ่ฃ…้ฅฐๅ™จโ€๏ผˆๆฒกๆœ‰ `@app.get("/some-path")`๏ผ‰็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ -ไพ่ต–้กนๅฏไปฅ่ฟ”ๅ›žๅ„็งๅ†…ๅฎนใ€‚ +่€Œไธ”ๅฎƒๅฏไปฅ่ฟ”ๅ›žไปปไฝ•ไฝ ๆƒณ่ฆ็š„ๅ†…ๅฎนใ€‚ -ๆœฌไพ‹ไธญ็š„ไพ่ต–้กน้ข„ๆœŸๆŽฅๆ”ถๅฆ‚ไธ‹ๅ‚ๆ•ฐ๏ผš +ๆœฌไพ‹ไธญ็š„ไพ่ต–้กน้ข„ๆœŸๆŽฅๆ”ถ๏ผš * ็ฑปๅž‹ไธบ `str` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `q` -* ็ฑปๅž‹ไธบ `int` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `skip`๏ผŒ้ป˜่ฎคๅ€ผๆ˜ฏ `0` -* ็ฑปๅž‹ไธบ `int` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `limit`๏ผŒ้ป˜่ฎคๅ€ผๆ˜ฏ `100` +* ็ฑปๅž‹ไธบ `int` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `skip`๏ผŒ้ป˜่ฎคๅ€ผ `0` +* ็ฑปๅž‹ไธบ `int` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `limit`๏ผŒ้ป˜่ฎคๅ€ผ `100` -็„ถๅŽ๏ผŒไพ่ต–้กนๅ‡ฝๆ•ฐ่ฟ”ๅ›žๅŒ…ๅซ่ฟ™ไบ›ๅ€ผ็š„ `dict`ใ€‚ +็„ถๅŽๅฎƒๅช้œ€่ฟ”ๅ›žไธ€ไธชๅŒ…ๅซ่ฟ™ไบ›ๅ€ผ็š„ `dict`ใ€‚ -### ๅฏผๅ…ฅ `Depends` +/// info | ไฟกๆฏ -{* ../../docs_src/dependencies/tutorial001.py hl[3] *} +FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌไธญๆ–ฐๅขžไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ไฝฟ็”จ๏ผ‰ใ€‚ -### ๅฃฐๆ˜Žไพ่ต–้กน +ๅฆ‚ๆžœไฝ ็š„็‰ˆๆœฌ่พƒๆ—ง๏ผŒๅฐ่ฏ•ไฝฟ็”จ `Annotated` ไผšๆŠฅ้”™ใ€‚ -ไธŽๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ๅ‚ๆ•ฐไธญไฝฟ็”จ `Body`ใ€`Query` ็š„ๆ–นๅผ็›ธๅŒ๏ผŒๅฃฐๆ˜Žไพ่ต–้กน้œ€่ฆไฝฟ็”จ `Depends` ๅ’Œไธ€ไธชๆ–ฐ็š„ๅ‚ๆ•ฐ๏ผš +ๅœจไฝฟ็”จ `Annotated` ไน‹ๅ‰๏ผŒ่ฏท็กฎไฟ[ๅ‡็บง FastAPI ็‰ˆๆœฌ](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ๅˆฐ่‡ณๅฐ‘ 0.95.1ใ€‚ -{* ../../docs_src/dependencies/tutorial001.py hl[15,20] *} +/// + +### ๅฏผๅ…ฅ `Depends` { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### ๅœจโ€œdependantโ€ไธญๅฃฐๆ˜Žไพ่ต–้กน { #declare-the-dependency-in-the-dependant } + +ไธŽๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐไธญไฝฟ็”จ `Body`ใ€`Query` ็ญ‰็›ธๅŒ๏ผŒ็ป™ๅ‚ๆ•ฐไฝฟ็”จ `Depends` ๆฅๅฃฐๆ˜Žไธ€ไธชๆ–ฐ็š„ไพ่ต–้กน๏ผš + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} -่™ฝ็„ถ๏ผŒๅœจ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐไธญไฝฟ็”จ `Depends` ็š„ๆ–นๅผไธŽ `Body`ใ€`Query` ็›ธๅŒ๏ผŒไฝ† `Depends` ็š„ๅทฅไฝœๆ–นๅผ็•ฅๆœ‰ไธๅŒใ€‚ +่™ฝ็„ถไฝ ๅœจๅ‡ฝๆ•ฐๅ‚ๆ•ฐไธญไฝฟ็”จ `Depends` ็š„ๆ–นๅผไธŽ `Body`ใ€`Query` ็ญ‰็›ธๅŒ๏ผŒไฝ† `Depends` ็š„ๅทฅไฝœๆ–นๅผ็•ฅๆœ‰ไธๅŒใ€‚ -่ฟ™้‡Œๅช่ƒฝไผ ็ป™ Depends ไธ€ไธชๅ‚ๆ•ฐใ€‚ +่ฟ™้‡Œๅช่ƒฝ็ป™ `Depends` ไผ ๅ…ฅไธ€ไธชๅ‚ๆ•ฐใ€‚ -ไธ”่ฏฅๅ‚ๆ•ฐๅฟ…้กปๆ˜ฏๅฏ่ฐƒ็”จๅฏน่ฑก๏ผŒๆฏ”ๅฆ‚ๅ‡ฝๆ•ฐใ€‚ +่ฟ™ไธชๅ‚ๆ•ฐๅฟ…้กปๆ˜ฏ็ฑปไผผๅ‡ฝๆ•ฐ็š„ๅฏ่ฐƒ็”จๅฏน่ฑกใ€‚ -่ฏฅๅ‡ฝๆ•ฐๆŽฅๆ”ถ็š„ๅ‚ๆ•ฐๅ’Œ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐไธ€ๆ ทใ€‚ +ไฝ ไธ้œ€่ฆ็›ดๆŽฅ่ฐƒ็”จๅฎƒ๏ผˆไธ่ฆๅœจๆœซๅฐพๅŠ ๆ‹ฌๅท๏ผ‰๏ผŒๅช้œ€ๅฐ†ๅ…ถไฝœไธบๅ‚ๆ•ฐไผ ็ป™ `Depends()`ใ€‚ + +่ฏฅๅ‡ฝๆ•ฐๆŽฅๆ”ถ็š„ๅ‚ๆ•ฐไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ็›ธๅŒใ€‚ /// tip | ๆ็คบ -ไธ‹ไธ€็ซ ไป‹็ป๏ผŒ้™คไบ†ๅ‡ฝๆ•ฐ่ฟ˜ๆœ‰ๅ“ชไบ›ใ€Œๅฏน่ฑกใ€ๅฏไปฅ็”จไฝœไพ่ต–้กนใ€‚ +ไธ‹ไธ€็ซ ไผšไป‹็ป้™คไบ†ๅ‡ฝๆ•ฐไน‹ๅค–๏ผŒ่ฟ˜ๆœ‰ๅ“ชไบ›โ€œไธœ่ฅฟโ€ๅฏไปฅ็”จไฝœไพ่ต–้กนใ€‚ /// -ๆŽฅๆ”ถๅˆฐๆ–ฐ็š„่ฏทๆฑ‚ๆ—ถ๏ผŒ**FastAPI** ๆ‰ง่กŒๅฆ‚ไธ‹ๆ“ไฝœ๏ผš +ๆŽฅๆ”ถๅˆฐๆ–ฐ็š„่ฏทๆฑ‚ๆ—ถ๏ผŒ**FastAPI** ไผš่ดŸ่ดฃ๏ผš -* ็”จๆญฃ็กฎ็š„ๅ‚ๆ•ฐ่ฐƒ็”จไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผˆใ€Œๅฏไพ่ต–้กนใ€๏ผ‰ +* ็”จๆญฃ็กฎ็š„ๅ‚ๆ•ฐ่ฐƒ็”จไฝ ็š„ไพ่ต–้กน๏ผˆโ€œdependableโ€๏ผ‰ๅ‡ฝๆ•ฐ * ่Žทๅ–ๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„็ป“ๆžœ -* ๆŠŠๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„็ป“ๆžœ่ต‹ๅ€ผ็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ +* ๅฐ†่ฏฅ็ป“ๆžœ่ต‹ๅ€ผ็ป™ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅ‚ๆ•ฐ ```mermaid graph TB @@ -92,95 +104,121 @@ common_parameters --> read_items common_parameters --> read_users ``` -่ฟ™ๆ ท๏ผŒๅช็ผ–ๅ†™ไธ€ๆฌกไปฃ็ ๏ผŒ**FastAPI** ๅฐฑๅฏไปฅไธบๅคšไธช*่ทฏๅพ„ๆ“ไฝœ*ๅ…ฑไบซ่ฟ™ๆฎตไปฃ็  ใ€‚ +่ฟ™ๆ ท๏ผŒไฝ ๅช้œ€็ผ–ๅ†™ไธ€ๆฌกๅ…ฑไบซไปฃ็ ๏ผŒ**FastAPI** ไผšๅœจไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญไธบไฝ ่ฐƒ็”จๅฎƒใ€‚ /// check | ๆฃ€ๆŸฅ -ๆณจๆ„๏ผŒๆ— ้œ€ๅˆ›ๅปบไธ“้—จ็š„็ฑป๏ผŒๅนถๅฐ†ไน‹ไผ ้€’็ป™ **FastAPI** ไปฅ่ฟ›่กŒใ€Œๆณจๅ†Œใ€ๆˆ–ๆ‰ง่กŒ็ฑปไผผ็š„ๆ“ไฝœใ€‚ +ๆณจๆ„๏ผŒๆ— ้œ€ๅˆ›ๅปบไธ“้—จ็š„็ฑปๅนถไผ ็ป™ **FastAPI** ๅŽปโ€œๆณจๅ†Œโ€ไน‹็ฑป็š„ๆ“ไฝœใ€‚ + +ๅช่ฆๆŠŠๅฎƒไผ ็ป™ `Depends`๏ผŒ**FastAPI** ๅฐฑ็Ÿฅ้“่ฏฅๆ€Žไนˆๅšไบ†ใ€‚ + +/// + +## ๅ…ฑไบซ `Annotated` ไพ่ต–้กน { #share-annotated-dependencies } -ๅช่ฆๆŠŠๅฎƒไผ ้€’็ป™ `Depends`๏ผŒ**FastAPI** ๅฐฑ็Ÿฅ้“่ฏฅๅฆ‚ไฝ•ๆ‰ง่กŒๅŽ็ปญๆ“ไฝœใ€‚ +ๅœจไธŠ้ข็š„็คบไพ‹ไธญ๏ผŒไฝ ไผšๅ‘็Žฐ่ฟ™้‡Œๆœ‰ไธ€็‚น็‚น**ไปฃ็ ้‡ๅค**ใ€‚ + +ๅฝ“ไฝ ้œ€่ฆไฝฟ็”จ `common_parameters()` ่ฟ™ไธชไพ่ต–ๆ—ถ๏ผŒไฝ ๅฟ…้กปๅ†™ๅ‡บๅฎŒๆ•ด็š„ๅธฆ็ฑปๅž‹ๆณจ่งฃๅ’Œ `Depends()` ็š„ๅ‚ๆ•ฐ๏ผš + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +ไฝ†ๅ› ไธบๆˆ‘ไปฌไฝฟ็”จไบ† `Annotated`๏ผŒๅฏไปฅๆŠŠ่ฟ™ไธช `Annotated` ็š„ๅ€ผๅญ˜ๅˆฐไธ€ไธชๅ˜้‡้‡Œ๏ผŒๅœจๅคšไธชๅœฐๆ–นๅค็”จ๏ผš + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | ๆ็คบ + +่ฟ™ๅชๆ˜ฏๆ ‡ๅ‡†็š„ Python๏ผŒๅซๅšโ€œ็ฑปๅž‹ๅˆซๅโ€๏ผŒๅนถไธๆ˜ฏ **FastAPI** ็‰นๆœ‰็š„ใ€‚ + +ไฝ†ๅ› ไธบ **FastAPI** ๅŸบไบŽ Python ๆ ‡ๅ‡†๏ผˆๅŒ…ๆ‹ฌ `Annotated`๏ผ‰๏ผŒไฝ ๅฐฑๅฏไปฅๅœจไปฃ็ ้‡Œไฝฟ็”จ่ฟ™ไธชๆŠ€ๅทงใ€‚๐Ÿ˜Ž /// -## ่ฆไธ่ฆไฝฟ็”จ `async`๏ผŸ +่ฟ™ไบ›ไพ่ต–ไผš็…งๅธธๅทฅไฝœ๏ผŒ่€Œ**ๆœ€ๆฃ’็š„ๆ˜ฏ**๏ผŒ**็ฑปๅž‹ไฟกๆฏไผš่ขซไฟ็•™**๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ไฝ ็š„็ผ–่พ‘ๅ™จไพ็„ถ่ƒฝๆไพ›**่‡ชๅŠจ่กฅๅ…จ**ใ€**่กŒๅ†…ๆŠฅ้”™**็ญ‰ใ€‚ๅŒๆ ท้€‚็”จไบŽ `mypy` ็ญ‰ๅ…ถไป–ๅทฅๅ…ทใ€‚ + +ๅฝ“ไฝ ๅœจ**ๅคงๅž‹ไปฃ็ ๅบ“**ไธญ๏ผŒๅœจ**ๅพˆๅคš*่ทฏๅพ„ๆ“ไฝœ***้‡Œๅๅคไฝฟ็”จ**็›ธๅŒ็š„ไพ่ต–**ๆ—ถ๏ผŒ่ฟ™ไผš็‰นๅˆซๆœ‰็”จใ€‚ + +## ่ฆไธ่ฆไฝฟ็”จ `async`๏ผŸ { #to-async-or-not-to-async } -**FastAPI** ่ฐƒ็”จไพ่ต–้กน็š„ๆ–นๅผไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธ€ๆ ท๏ผŒๅ› ๆญค๏ผŒๅฎšไน‰ไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผŒไนŸ่ฆๅบ”็”จไธŽ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ็›ธๅŒ็š„่ง„ๅˆ™ใ€‚ +็”ฑไบŽไพ่ต–้กนไนŸไผš็”ฑ **FastAPI** ่ฐƒ็”จ๏ผˆไธŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็›ธๅŒ๏ผ‰๏ผŒๅ› ๆญคๅฎšไน‰ๅ‡ฝๆ•ฐๆ—ถๅŒๆ ท็š„่ง„ๅˆ™ไนŸ้€‚็”จใ€‚ -ๅณ๏ผŒๆ—ขๅฏไปฅไฝฟ็”จๅผ‚ๆญฅ็š„ `async def`๏ผŒไนŸๅฏไปฅไฝฟ็”จๆ™ฎ้€š็š„ `def` ๅฎšไน‰ไพ่ต–้กนใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ `async def` ๆˆ–ๆ™ฎ้€š็š„ `def`ใ€‚ -ๅœจๆ™ฎ้€š็š„ `def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ๏ผŒๅฏไปฅๅฃฐๆ˜Žๅผ‚ๆญฅ็š„ `async def` ไพ่ต–้กน๏ผ›ไนŸๅฏไปฅๅœจๅผ‚ๆญฅ็š„ `async def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Žๆ™ฎ้€š็š„ `def` ไพ่ต–้กนใ€‚ +ไฝ ๅฏไปฅๅœจๆ™ฎ้€š็š„ `def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Ž `async def` ็š„ไพ่ต–้กน๏ผ›ไนŸๅฏไปฅๅœจๅผ‚ๆญฅ็š„ `async def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅฃฐๆ˜Žๆ™ฎ้€š็š„ `def` ไพ่ต–้กน๏ผŒ็ญ‰็ญ‰ใ€‚ -ไธŠ่ฟฐ่ฟ™ไบ›ๆ“ไฝœ้ƒฝๆ˜ฏๅฏ่กŒ็š„๏ผŒ**FastAPI** ็Ÿฅ้“่ฏฅๆ€Žไนˆๅค„็†ใ€‚ +้ƒฝๆฒกๅ…ณ็ณป๏ผŒ**FastAPI** ็Ÿฅ้“่ฏฅๆ€Žไนˆๅค„็†ใ€‚ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๅฆ‚้‡Œไธไบ†่งฃๅผ‚ๆญฅ๏ผŒ่ฏทๅ‚้˜…[ๅผ‚ๆญฅ๏ผš*โ€œ็€ๆ€ฅไบ†๏ผŸโ€*](../../async.md){.internal-link target=_blank} ไธ€็ซ ไธญ `async` ๅ’Œ `await` ็š„ๅ†…ๅฎนใ€‚ +ๅฆ‚ๆžœไธไบ†่งฃๅผ‚ๆญฅ๏ผŒ่ฏทๅ‚้˜…ๆ–‡ๆกฃไธญๅ…ณไบŽ `async` ๅ’Œ `await` ็š„็ซ ่Š‚๏ผš[ๅผ‚ๆญฅ๏ผš*โ€œ็€ๆ€ฅไบ†๏ผŸโ€*](../../async.md#in-a-hurry){.internal-link target=_blank}ใ€‚ /// -## ไธŽ OpenAPI ้›†ๆˆ +## ไธŽ OpenAPI ้›†ๆˆ { #integrated-with-openapi } -ไพ่ต–้กนๅŠๅญไพ่ต–้กน็š„ๆ‰€ๆœ‰่ฏทๆฑ‚ๅฃฐๆ˜Žใ€้ชŒ่ฏๅ’Œ้œ€ๆฑ‚้ƒฝๅฏไปฅ้›†ๆˆ่‡ณๅŒไธ€ไธช OpenAPI ๆฆ‚ๅ›พใ€‚ +ไพ่ต–้กนๅŠๅญไพ่ต–้กนไธญๅฃฐๆ˜Ž็š„ๆ‰€ๆœ‰่ฏทๆฑ‚ใ€้ชŒ่ฏๅ’Œ้œ€ๆฑ‚้ƒฝไผš้›†ๆˆๅˆฐๅŒไธ€ไธช OpenAPI ๆจกๅผไธญใ€‚ -ๆ‰€ไปฅ๏ผŒไบคไบ’ๆ–‡ๆกฃ้‡ŒไนŸไผšๆ˜พ็คบไพ่ต–้กน็š„ๆ‰€ๆœ‰ไฟกๆฏ๏ผš +ๅ› ๆญค๏ผŒไบคไบ’ๅผๆ–‡ๆกฃไธญไนŸไผšๅŒ…ๅซ่ฟ™ไบ›ไพ่ต–้กน็š„ๆ‰€ๆœ‰ไฟกๆฏ๏ผš -## ็ฎ€ๅ•็”จๆณ• +## ็ฎ€ๅ•็”จๆณ• { #simple-usage } -่ง‚ๅฏŸไธ€ไธ‹ๅฐฑไผšๅ‘็Žฐ๏ผŒๅช่ฆ*่ทฏๅพ„* ๅ’Œ*ๆ“ไฝœ*ๅŒน้…๏ผŒๅฐฑๅฏไปฅไฝฟ็”จๅฃฐๆ˜Ž็š„่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐใ€‚็„ถๅŽ๏ผŒ**FastAPI** ไผš็”จๆญฃ็กฎ็š„ๅ‚ๆ•ฐ่ฐƒ็”จๅ‡ฝๆ•ฐ๏ผŒๅนถๆๅ–่ฏทๆฑ‚ไธญ็š„ๆ•ฐๆฎใ€‚ +่ง‚ๅฏŸไธ€ไธ‹ๅฐฑไผšๅ‘็Žฐ๏ผŒๅช่ฆ*่ทฏๅพ„*ๅ’Œ*ๆ“ไฝœ*ๅŒน้…๏ผŒๅฐฑไผšไฝฟ็”จๅฃฐๆ˜Ž็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚้šๅŽ๏ผŒ**FastAPI** ไผš็”จๆญฃ็กฎ็š„ๅ‚ๆ•ฐ่ฐƒ็”จ่ฏฅๅ‡ฝๆ•ฐ๏ผŒๅนถไปŽ่ฏทๆฑ‚ไธญๆๅ–ๆ•ฐๆฎใ€‚ -ๅฎž้™…ไธŠ๏ผŒๆ‰€ๆœ‰๏ผˆๆˆ–ๅคงๅคšๆ•ฐ๏ผ‰็ฝ‘็ปœๆก†ๆžถ็š„ๅทฅไฝœๆ–นๅผ้ƒฝๆ˜ฏ่ฟ™ๆ ท็š„ใ€‚ +ไบ‹ๅฎžไธŠ๏ผŒๆ‰€ๆœ‰๏ผˆๆˆ–ๅคงๅคšๆ•ฐ๏ผ‰Web ๆก†ๆžถ็š„ๅทฅไฝœๆ–นๅผ้ƒฝๆ˜ฏ่ฟ™ๆ ท็š„ใ€‚ -ๅผ€ๅ‘ไบบๅ‘˜ๆฐธ่ฟœ้ƒฝไธ้œ€่ฆ็›ดๆŽฅ่ฐƒ็”จ่ฟ™ไบ›ๅ‡ฝๆ•ฐ๏ผŒ่ฟ™ไบ›ๅ‡ฝๆ•ฐๆ˜ฏ็”ฑๆก†ๆžถ๏ผˆๅœจๆญคไธบ **FastAPI** ๏ผ‰่ฐƒ็”จ็š„ใ€‚ +ไฝ ไปŽไธไผš็›ดๆŽฅ่ฐƒ็”จ่ฟ™ไบ›ๅ‡ฝๆ•ฐใ€‚ๅฎƒไปฌ็”ฑไฝ ็š„ๆก†ๆžถ๏ผˆๆญคๅค„ไธบ **FastAPI**๏ผ‰่ฐƒ็”จใ€‚ -้€š่ฟ‡ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ๏ผŒๅช่ฆๅ‘Š่ฏ‰ **FastAPI** *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ่ฟ˜่ฆใ€Œไพ่ต–ใ€ๅ…ถไป–ๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไน‹ๅ‰ๆ‰ง่กŒ็š„ๅ†…ๅฎน๏ผŒ**FastAPI** ๅฐฑไผšๆ‰ง่กŒๅ‡ฝๆ•ฐไปฃ็ ๏ผŒๅนถใ€Œๆณจๅ…ฅใ€ๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„็ป“ๆžœใ€‚ +้€š่ฟ‡ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ๏ผŒไฝ ่ฟ˜ๅฏไปฅๅ‘Š่ฏ‰ **FastAPI**๏ผŒไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*่ฟ˜โ€œไพ่ต–โ€ๆŸไบ›ๅบ”ๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไน‹ๅ‰ๆ‰ง่กŒ็š„ๅ†…ๅฎน๏ผŒ**FastAPI** ไผš่ดŸ่ดฃๆ‰ง่กŒๅฎƒๅนถโ€œๆณจๅ…ฅโ€็ป“ๆžœใ€‚ -ๅ…ถไป–ไธŽใ€Œไพ่ต–ๆณจๅ…ฅใ€ๆฆ‚ๅฟต็›ธๅŒ็š„ๆœฏ่ฏญไธบ๏ผš +โ€œไพ่ต–ๆณจๅ…ฅโ€็š„ๅ…ถไป–ๅธธ่งๆœฏ่ฏญๅŒ…ๆ‹ฌ๏ผš -* ่ต„ๆบ๏ผˆResource๏ผ‰ -* ๆไพ›ๆ–น๏ผˆProvider๏ผ‰ -* ๆœๅŠก๏ผˆService๏ผ‰ -* ๅฏๆณจๅ…ฅ๏ผˆInjectable๏ผ‰ -* ็ป„ไปถ๏ผˆComponent๏ผ‰ +* ่ต„ๆบ๏ผˆresources๏ผ‰ +* ๆไพ›ๆ–น๏ผˆproviders๏ผ‰ +* ๆœๅŠก๏ผˆservices๏ผ‰ +* ๅฏๆณจๅ…ฅ๏ผˆinjectables๏ผ‰ +* ็ป„ไปถ๏ผˆcomponents๏ผ‰ -## **FastAPI** ๆ’ไปถ +## **FastAPI** ๆ’ไปถ { #fastapi-plug-ins } -**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸๆ”ฏๆŒๆž„ๅปบ้›†ๆˆๅ’Œใ€Œๆ’ไปถใ€ใ€‚ไฝ†ๅฎž้™…ไธŠ๏ผŒFastAPI ๆ นๆœฌ**ไธ้œ€่ฆๅˆ›ๅปบใ€Œๆ’ไปถใ€**๏ผŒๅ› ไธบไฝฟ็”จไพ่ต–้กนๅฏไปฅๅฃฐๆ˜Žไธ้™ๆ•ฐ้‡็š„ใ€ๅฏ็”จไบŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„้›†ๆˆไธŽไบคไบ’ใ€‚ +ๅฏไปฅไฝฟ็”จ**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸๆž„ๅปบ้›†ๆˆๅ’Œโ€œๆ’ไปถโ€ใ€‚ไฝ†ๅฎž้™…ไธŠ๏ผŒๆ นๆœฌ**ไธ้œ€่ฆๅˆ›ๅปบโ€œๆ’ไปถโ€**๏ผŒๅ› ไธบ้€š่ฟ‡ไพ่ต–้กนๅฏไปฅๅฃฐๆ˜Žๆ— ้™ๅคš็š„้›†ๆˆไธŽไบคไบ’๏ผŒไฝฟๅ…ถๅฏ็”จไบŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ -ๅˆ›ๅปบไพ่ต–้กน้žๅธธ็ฎ€ๅ•ใ€็›ด่ง‚๏ผŒๅนถไธ”่ฟ˜ๆ”ฏๆŒๅฏผๅ…ฅ Python ๅŒ…ใ€‚ๆฏซไธๅคธๅผ ๅœฐ่ฏด๏ผŒๅช่ฆๅ‡ ่กŒไปฃ็ ๅฐฑๅฏไปฅๆŠŠ้œ€่ฆ็š„ Python ๅŒ…ไธŽ API ๅ‡ฝๆ•ฐ้›†ๆˆๅœจไธ€่ตทใ€‚ +ไพ่ต–้กนๅฏไปฅ็”จ้žๅธธ็ฎ€ๅ•็›ด่ง‚็š„ๆ–นๅผๅˆ›ๅปบ๏ผŒไฝ ๅช้œ€ๅฏผๅ…ฅๆ‰€้œ€็š„ Python ๅŒ…๏ผŒ็”จ*ๅญ—้ขๆ„ไน‰ไธŠ็š„*ๅ‡ ่กŒไปฃ็ ๅฐฑ่ƒฝๆŠŠๅฎƒไปฌไธŽไฝ ็š„ API ๅ‡ฝๆ•ฐ้›†ๆˆ่ตทๆฅใ€‚ -ไธ‹ไธ€็ซ ๅฐ†่ฏฆ็ป†ไป‹็ปๅœจๅ…ณ็ณปๅž‹ๆ•ฐๆฎๅบ“ใ€NoSQL ๆ•ฐๆฎๅบ“ใ€ๅฎ‰ๅ…จ็ญ‰ๆ–น้ขไฝฟ็”จไพ่ต–้กน็š„ไพ‹ๅญใ€‚ +ๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญ๏ผŒไฝ ไผš็œ‹ๅˆฐๅ…ณไบŽๅ…ณ็ณปๅž‹ๆ•ฐๆฎๅบ“ใ€NoSQL ๆ•ฐๆฎๅบ“ใ€ๅฎ‰ๅ…จ็ญ‰ๆ–น้ข็š„็คบไพ‹ใ€‚ -## **FastAPI** ๅ…ผๅฎนๆ€ง +## **FastAPI** ๅ…ผๅฎนๆ€ง { #fastapi-compatibility } -ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸๅฆ‚ๆญค็ฎ€ๆด็š„็‰นๆ€ง๏ผŒ่ฎฉ **FastAPI** ๅฏไปฅไธŽไธ‹ๅˆ—็ณป็ปŸๅ…ผๅฎน๏ผš +ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ็š„็ฎ€ๆด่ฎฉ **FastAPI** ่ƒฝไธŽไปฅไธ‹ๅ†…ๅฎนๅ…ผๅฎน๏ผš -* ๅ…ณ็ณปๅž‹ๆ•ฐๆฎๅบ“ +* ๅ„็ฑปๅ…ณ็ณปๅž‹ๆ•ฐๆฎๅบ“ * NoSQL ๆ•ฐๆฎๅบ“ -* ๅค–้ƒจๆ”ฏๆŒๅบ“ +* ๅค–้ƒจๅŒ… * ๅค–้ƒจ API -* ่ฎค่ฏๅ’Œ้‰ดๆƒ็ณป็ปŸ +* ่ฎค่ฏไธŽๆŽˆๆƒ็ณป็ปŸ * API ไฝฟ็”จ็›‘ๆŽง็ณป็ปŸ * ๅ“ๅบ”ๆ•ฐๆฎๆณจๅ…ฅ็ณป็ปŸ -* ็ญ‰็ญ‰โ€ฆโ€ฆ +* ็ญ‰็ญ‰... -## ็ฎ€ๅ•่€Œๅผบๅคง +## ็ฐกๅ•่€Œๅผบๅคง { #simple-and-powerful } -่™ฝ็„ถ๏ผŒ**ๅฑ‚็บงๅผไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ**็š„ๅฎšไน‰ไธŽไฝฟ็”จๅๅˆ†็ฎ€ๅ•๏ผŒไฝ†ๅฎƒๅด้žๅธธๅผบๅคงใ€‚ +่™ฝ็„ถ**ๅฑ‚็บงๅผไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ**็š„ๅฎšไน‰ไธŽไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๅฎƒไพ็„ถ้žๅธธๅผบๅคงใ€‚ -ๆฏ”ๅฆ‚๏ผŒๅฏไปฅๅฎšไน‰ไพ่ต–ๅ…ถไป–ไพ่ต–้กน็š„ไพ่ต–้กนใ€‚ +ไฝ ๅฏไปฅๅฎšไน‰ไพ่ต–ๅ…ถไป–ไพ่ต–้กน็š„ไพ่ต–้กนใ€‚ -ๆœ€ๅŽ๏ผŒไพ่ต–้กนๅฑ‚็บงๆ ‘ๆž„ๅปบๅŽ๏ผŒ**ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ**ไผšๅค„็†ๆ‰€ๆœ‰ไพ่ต–้กนๅŠๅ…ถๅญไพ่ต–้กน๏ผŒๅนถไธบๆฏไธ€ๆญฅๆ“ไฝœๆไพ›๏ผˆๆณจๅ…ฅ๏ผ‰็ป“ๆžœใ€‚ +ๆœ€็ปˆไผšๆž„ๅปบๅ‡บไธ€ไธชไพ่ต–้กน็š„ๅฑ‚็บงๆ ‘๏ผŒ**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸไผšๅค„็†ๆ‰€ๆœ‰่ฟ™ไบ›ไพ่ต–๏ผˆๅŠๅ…ถๅญไพ่ต–๏ผ‰๏ผŒๅนถๅœจๆฏไธ€ๆญฅๆไพ›๏ผˆๆณจๅ…ฅ๏ผ‰็›ธๅบ”็š„็ป“ๆžœใ€‚ -ๆฏ”ๅฆ‚๏ผŒไธ‹้ขๆœ‰ 4 ไธช API ่ทฏๅพ„ๆ“ไฝœ๏ผˆ*็ซฏ็‚น*๏ผ‰๏ผš +ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๆœ‰ 4 ไธช API ่ทฏๅพ„ๆ“ไฝœ๏ผˆ*็ซฏ็‚น*๏ผ‰๏ผš * `/items/public/` * `/items/private/` * `/users/{user_id}/activate` * `/items/pro/` -ๅผ€ๅ‘ไบบๅ‘˜ๅฏไปฅไฝฟ็”จไพ่ต–้กนๅŠๅ…ถๅญไพ่ต–้กนไธบ่ฟ™ไบ›่ทฏๅพ„ๆ“ไฝœๆทปๅŠ ไธๅŒ็š„ๆƒ้™๏ผš +ไฝ ๅฏไปฅไป…้€š่ฟ‡ไพ่ต–้กนๅŠๅ…ถๅญไพ่ต–้กนไธบๅฎƒไปฌๆทปๅŠ ไธๅŒ็š„ๆƒ้™่ฆๆฑ‚๏ผš ```mermaid graph TB @@ -205,8 +243,8 @@ admin_user --> activate_user paying_user --> pro_items ``` -## ไธŽ **OpenAPI** ้›†ๆˆ +## ไธŽ **OpenAPI** ้›†ๆˆ { #integrated-with-openapi_1 } -ๅœจๅฃฐๆ˜Ž้œ€ๆฑ‚ๆ—ถ๏ผŒๆ‰€ๆœ‰่ฟ™ไบ›ไพ่ต–้กน่ฟ˜ไผšๆŠŠๅ‚ๆ•ฐใ€้ชŒ่ฏ็ญ‰ๅŠŸ่ƒฝๆทปๅŠ ่‡ณ่ทฏๅพ„ๆ“ไฝœใ€‚ +ๅœจๅฃฐๆ˜Ž้œ€ๆฑ‚็š„ๅŒๆ—ถ๏ผŒๆ‰€ๆœ‰่ฟ™ไบ›ไพ่ต–้กนไนŸไผšไธบไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ๆทปๅŠ ๅ‚ๆ•ฐใ€้ชŒ่ฏ็ญ‰ๅ†…ๅฎนใ€‚ -**FastAPI** ่ดŸ่ดฃๆŠŠไธŠ่ฟฐๅ†…ๅฎนๅ…จ้ƒจๆทปๅŠ ๅˆฐ OpenAPI ๆฆ‚ๅ›พ๏ผŒๅนถๆ˜พ็คบๅœจไบคไบ’ๆ–‡ๆกฃไธญใ€‚ +**FastAPI** ไผš่ดŸ่ดฃๆŠŠ่ฟ™ไบ›ๅ…จ้ƒจๆทปๅŠ ๅˆฐ OpenAPI ๆจกๅผไธญ๏ผŒไปฅไพฟๅฎƒไปฌๆ˜พ็คบๅœจไบคไบ’ๅผๆ–‡ๆกฃ็ณป็ปŸ้‡Œใ€‚ diff --git a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md index 2e77464335..0b73c392d8 100644 --- a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md @@ -1,4 +1,4 @@ -# ๅญไพ่ต–้กน +# ๅญไพ่ต–้กน { #sub-dependencies } FastAPI ๆ”ฏๆŒๅˆ›ๅปบๅซ**ๅญไพ่ต–้กน**็š„ไพ่ต–้กนใ€‚ @@ -6,34 +6,34 @@ FastAPI ๆ”ฏๆŒๅˆ›ๅปบๅซ**ๅญไพ่ต–้กน**็š„ไพ่ต–้กนใ€‚ **FastAPI** ่ดŸ่ดฃๅค„็†่งฃๆžไธๅŒๆทฑๅบฆ็š„ๅญไพ่ต–้กนใ€‚ -### ็ฌฌไธ€ๅฑ‚ไพ่ต–้กน +## ็ฌฌไธ€ๅฑ‚ไพ่ต–้กน โ€œdependableโ€ { #first-dependency-dependable } -ไธ‹ๅˆ—ไปฃ็ ๅˆ›ๅปบไบ†็ฌฌไธ€ๅฑ‚ไพ่ต–้กน๏ผš +ไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช็ฌฌไธ€ๅฑ‚ไพ่ต–้กน๏ผˆโ€œdependableโ€๏ผ‰๏ผŒๅฆ‚ไธ‹๏ผš -{* ../../docs_src/dependencies/tutorial005.py hl[8:9] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} ่ฟ™ๆฎตไปฃ็ ๅฃฐๆ˜Žไบ†็ฑปๅž‹ไธบ `str` ็š„ๅฏ้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผŒ็„ถๅŽ่ฟ”ๅ›ž่ฟ™ไธชๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ ่ฟ™ไธชๅ‡ฝๆ•ฐๅพˆ็ฎ€ๅ•๏ผˆไธ่ฟ‡ไนŸๆฒกไป€ไนˆ็”จ๏ผ‰๏ผŒไฝ†ๅดๆœ‰ๅŠฉไบŽ่ฎฉๆˆ‘ไปฌไธ“ๆณจไบŽไบ†่งฃๅญไพ่ต–้กน็š„ๅทฅไฝœๆ–นๅผใ€‚ -### ็ฌฌไบŒๅฑ‚ไพ่ต–้กน +## ็ฌฌไบŒๅฑ‚ไพ่ต–้กน๏ผŒโ€œdependableโ€ๅ’Œโ€œdependantโ€ { #second-dependency-dependable-and-dependant } -ๆŽฅไธ‹ๆฅ๏ผŒๅˆ›ๅปบๅฆไธ€ไธชไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผŒๅนถๅŒๆ—ถ็”จ่ฏฅไพ่ต–้กน่‡ช่บซๅ†ๅฃฐๆ˜Žไธ€ไธชไพ่ต–้กน๏ผˆๆ‰€ไปฅ่ฟ™ไนŸๆ˜ฏไธ€ไธชใ€Œไพ่ต–้กนใ€๏ผ‰๏ผš +ๆŽฅไธ‹ๆฅ๏ผŒๅˆ›ๅปบๅฆไธ€ไธชไพ่ต–้กนๅ‡ฝๆ•ฐ๏ผˆไธ€ไธชโ€œdependableโ€๏ผ‰๏ผŒๅนถๅŒๆ—ถไธบๅฎƒ่‡ช่บซๅ†ๅฃฐๆ˜Žไธ€ไธชไพ่ต–้กน๏ผˆๅ› ๆญคๅฎƒๅŒๆ—ถไนŸๆ˜ฏไธ€ไธชโ€œdependantโ€๏ผ‰๏ผš -{* ../../docs_src/dependencies/tutorial005.py hl[13] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} ่ฟ™้‡Œ้‡็‚น่ฏดๆ˜Žไธ€ไธ‹ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐ๏ผš -* ๅฐฝ็ฎก่ฏฅๅ‡ฝๆ•ฐ่‡ช่บซๆ˜ฏไพ่ต–้กน๏ผŒไฝ†่ฟ˜ๅฃฐๆ˜Žไบ†ๅฆไธ€ไธชไพ่ต–้กน๏ผˆๅฎƒใ€Œไพ่ต–ใ€ไบŽๅ…ถไป–ๅฏน่ฑก๏ผ‰ +* ๅฐฝ็ฎก่ฏฅๅ‡ฝๆ•ฐ่‡ช่บซๆ˜ฏไพ่ต–้กน๏ผˆโ€œdependableโ€๏ผ‰๏ผŒไฝ†่ฟ˜ๅฃฐๆ˜Žไบ†ๅฆไธ€ไธชไพ่ต–้กน๏ผˆๅฎƒโ€œไพ่ต–โ€ไบŽๅ…ถไป–ๅฏน่ฑก๏ผ‰ * ่ฏฅๅ‡ฝๆ•ฐไพ่ต– `query_extractor`, ๅนถๆŠŠ `query_extractor` ็š„่ฟ”ๅ›žๅ€ผ่ต‹็ป™ๅ‚ๆ•ฐ `q` * ๅŒๆ—ถ๏ผŒ่ฏฅๅ‡ฝๆ•ฐ่ฟ˜ๅฃฐๆ˜Žไบ†็ฑปๅž‹ๆ˜ฏ `str` ็š„ๅฏ้€‰ cookie๏ผˆ`last_query`๏ผ‰ * ็”จๆˆทๆœชๆไพ›ๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ๆ—ถ๏ผŒๅˆ™ไฝฟ็”จไธŠๆฌกไฝฟ็”จๅŽไฟๅญ˜ๅœจ cookie ไธญ็š„ๆŸฅ่ฏข -### ไฝฟ็”จไพ่ต–้กน +## ไฝฟ็”จไพ่ต–้กน { #use-the-dependency } ๆŽฅไธ‹ๆฅ๏ผŒๅฐฑๅฏไปฅไฝฟ็”จไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial005.py hl[22] *} +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} /// info | ไฟกๆฏ @@ -54,20 +54,39 @@ read_query["/items/"] query_extractor --> query_or_cookie_extractor --> read_query ``` -## ๅคšๆฌกไฝฟ็”จๅŒไธ€ไธชไพ่ต–้กน +## ๅคšๆฌกไฝฟ็”จๅŒไธ€ไธชไพ่ต–้กน { #using-the-same-dependency-multiple-times } ๅฆ‚ๆžœๅœจๅŒไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* ๅคšๆฌกๅฃฐๆ˜Žไบ†ๅŒไธ€ไธชไพ่ต–้กน๏ผŒไพ‹ๅฆ‚๏ผŒๅคšไธชไพ่ต–้กนๅ…ฑ็”จไธ€ไธชๅญไพ่ต–้กน๏ผŒ**FastAPI** ๅœจๅค„็†ๅŒไธ€่ฏทๆฑ‚ๆ—ถ๏ผŒๅช่ฐƒ็”จไธ€ๆฌก่ฏฅๅญไพ่ต–้กนใ€‚ FastAPI ไธไผšไธบๅŒไธ€ไธช่ฏทๆฑ‚ๅคšๆฌก่ฐƒ็”จๅŒไธ€ไธชไพ่ต–้กน๏ผŒ่€Œๆ˜ฏๆŠŠไพ่ต–้กน็š„่ฟ”ๅ›žๅ€ผ่ฟ›่กŒใ€Œ็ผ“ๅญ˜ใ€๏ผŒๅนถๆŠŠๅฎƒไผ ้€’็ป™ๅŒไธ€่ฏทๆฑ‚ไธญๆ‰€ๆœ‰้œ€่ฆไฝฟ็”จ่ฏฅ่ฟ”ๅ›žๅ€ผ็š„ใ€Œไพ่ต–้กนใ€ใ€‚ -ๅœจ้ซ˜็บงไฝฟ็”จๅœบๆ™ฏไธญ๏ผŒๅฆ‚ๆžœไธๆƒณไฝฟ็”จใ€Œ็ผ“ๅญ˜ใ€ๅ€ผ๏ผŒ่€Œๆ˜ฏไธบ้œ€่ฆๅœจๅŒไธ€่ฏทๆฑ‚็š„ๆฏไธ€ๆญฅๆ“ไฝœ๏ผˆๅคšๆฌก๏ผ‰ไธญ้ƒฝๅฎž้™…่ฐƒ็”จไพ่ต–้กน๏ผŒๅฏไปฅๆŠŠ `Depends` ็š„ๅ‚ๆ•ฐ `use_cache` ็š„ๅ€ผ่ฎพ็ฝฎไธบ `False` : +ๅœจ้ซ˜็บงไฝฟ็”จๅœบๆ™ฏไธญ๏ผŒๅฆ‚ๆžœไธๆƒณไฝฟ็”จใ€Œ็ผ“ๅญ˜ใ€ๅ€ผ๏ผŒ่€Œๆ˜ฏไธบ้œ€่ฆๅœจๅŒไธ€่ฏทๆฑ‚็š„ๆฏไธ€ๆญฅๆ“ไฝœ๏ผˆๅคšๆฌก๏ผ‰ไธญ้ƒฝๅฎž้™…่ฐƒ็”จไพ่ต–้กน๏ผŒๅฏไปฅๆŠŠ `Depends` ็š„ๅ‚ๆ•ฐ `use_cache` ็š„ๅ€ผ่ฎพ็ฝฎไธบ `False`: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.9+ ้ž Annotated + +/// tip | ๆ็คบ + +ๅฐฝๅฏ่ƒฝไผ˜ๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// ```Python hl_lines="1" async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): return {"fresh_value": fresh_value} ``` -## ๅฐ็ป“ +//// + +## ๅฐ็ป“ { #recap } ๅƒไธ‡ๅˆซ่ขซๆœฌ็ซ ้‡Œ่ฟ™ไบ›่Šฑ้‡Œ่ƒกๅ“จ็š„่ฏ่—ปๅ“ๅ€’ไบ†๏ผŒๅ…ถๅฎž**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸ้žๅธธ็ฎ€ๅ•ใ€‚ diff --git a/docs/zh/docs/tutorial/encoder.md b/docs/zh/docs/tutorial/encoder.md index e52aaa2ed2..f47a092010 100644 --- a/docs/zh/docs/tutorial/encoder.md +++ b/docs/zh/docs/tutorial/encoder.md @@ -1,4 +1,4 @@ -# JSON ๅ…ผๅฎน็ผ–็ ๅ™จ +# JSON ๅ…ผๅฎน็ผ–็ ๅ™จ { #json-compatible-encoder } ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๆ‚จๅฏ่ƒฝ้œ€่ฆๅฐ†ๆ•ฐๆฎ็ฑปๅž‹๏ผˆๅฆ‚Pydanticๆจกๅž‹๏ผ‰่ฝฌๆขไธบไธŽJSONๅ…ผๅฎน็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผˆๅฆ‚`dict`ใ€`list`็ญ‰๏ผ‰ใ€‚ @@ -6,7 +6,7 @@ ๅฏนไบŽ่ฟ™็ง่ฆๆฑ‚๏ผŒ **FastAPI**ๆไพ›ไบ†`jsonable_encoder()`ๅ‡ฝๆ•ฐใ€‚ -## ไฝฟ็”จ`jsonable_encoder` +## ไฝฟ็”จ`jsonable_encoder` { #using-the-jsonable-encoder } ่ฎฉๆˆ‘ไปฌๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๆ•ฐๆฎๅบ“ๅไธบ`fake_db`๏ผŒๅฎƒๅช่ƒฝๆŽฅๆ”ถไธŽJSONๅ…ผๅฎน็š„ๆ•ฐๆฎใ€‚ @@ -28,7 +28,7 @@ ่ฟ™ไธชๆ“ไฝœไธไผš่ฟ”ๅ›žไธ€ไธชๅŒ…ๅซJSONๆ ผๅผ๏ผˆไฝœไธบๅญ—็ฌฆไธฒ๏ผ‰ๆ•ฐๆฎ็š„ๅบžๅคง็š„`str`ใ€‚ๅฎƒๅฐ†่ฟ”ๅ›žไธ€ไธชPythonๆ ‡ๅ‡†ๆ•ฐๆฎ็ป“ๆž„๏ผˆไพ‹ๅฆ‚`dict`๏ผ‰๏ผŒๅ…ถๅ€ผๅ’Œๅญๅ€ผ้ƒฝไธŽJSONๅ…ผๅฎนใ€‚ -/// note +/// note | ๆณจๆ„ `jsonable_encoder`ๅฎž้™…ไธŠๆ˜ฏFastAPIๅ†…้ƒจ็”จๆฅ่ฝฌๆขๆ•ฐๆฎ็š„ใ€‚ไฝ†ๆ˜ฏๅฎƒๅœจ่ฎธๅคšๅ…ถไป–ๅœบๆ™ฏไธญไนŸๅพˆๆœ‰็”จใ€‚ diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md index b064ee551e..2cefd163d3 100644 --- a/docs/zh/docs/tutorial/extra-data-types.md +++ b/docs/zh/docs/tutorial/extra-data-types.md @@ -1,4 +1,4 @@ -# ้ขๅค–ๆ•ฐๆฎ็ฑปๅž‹ +# ้ขๅค–ๆ•ฐๆฎ็ฑปๅž‹ { #extra-data-types } ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๆ‚จไธ€็›ดๅœจไฝฟ็”จๅธธ่ง็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒๅฆ‚: @@ -15,9 +15,9 @@ * ไผ ๅ…ฅ่ฏทๆฑ‚็š„ๆ•ฐๆฎ่ฝฌๆขใ€‚ * ๅ“ๅบ”ๆ•ฐๆฎ่ฝฌๆขใ€‚ * ๆ•ฐๆฎ้ชŒ่ฏใ€‚ -* ่‡ชๅŠจ่กฅๅ…จๅ’Œๆ–‡ๆกฃใ€‚ +* ่‡ชๅŠจๆณจ่งฃๅ’Œๆ–‡ๆกฃใ€‚ -## ๅ…ถไป–ๆ•ฐๆฎ็ฑปๅž‹ +## ๅ…ถไป–ๆ•ฐๆฎ็ฑปๅž‹ { #other-data-types } ไธ‹้ขๆ˜ฏไธ€ไบ›ไฝ ๅฏไปฅไฝฟ็”จ็š„ๅ…ถไป–ๆ•ฐๆฎ็ฑปๅž‹: @@ -36,12 +36,12 @@ * `datetime.timedelta`: * ไธ€ไธช Python `datetime.timedelta`. * ๅœจ่ฏทๆฑ‚ๅ’Œๅ“ๅบ”ไธญๅฐ†่กจ็คบไธบ `float` ไปฃ่กจๆ€ป็ง’ๆ•ฐใ€‚ - * Pydantic ไนŸๅ…่ฎธๅฐ†ๅ…ถ่กจ็คบไธบ "ISO 8601 ๆ—ถ้—ดๅทฎๅผ‚็ผ–็ ", ๆŸฅ็œ‹ๆ–‡ๆกฃไบ†่งฃๆ›ดๅคšไฟกๆฏใ€‚ + * Pydantic ไนŸๅ…่ฎธๅฐ†ๅ…ถ่กจ็คบไธบ "ISO 8601 ๆ—ถ้—ดๅทฎๅผ‚็ผ–็ ", ๆŸฅ็œ‹ๆ–‡ๆกฃไบ†่งฃๆ›ดๅคšไฟกๆฏใ€‚ * `frozenset`: * ๅœจ่ฏทๆฑ‚ๅ’Œๅ“ๅบ”ไธญ๏ผŒไฝœไธบ `set` ๅฏนๅพ…๏ผš * ๅœจ่ฏทๆฑ‚ไธญ๏ผŒๅˆ—่กจๅฐ†่ขซ่ฏปๅ–๏ผŒๆถˆ้™ค้‡ๅค๏ผŒๅนถๅฐ†ๅ…ถ่ฝฌๆขไธบไธ€ไธช `set`ใ€‚ * ๅœจๅ“ๅบ”ไธญ `set` ๅฐ†่ขซ่ฝฌๆขไธบ `list` ใ€‚ - * ไบง็”Ÿ็š„ๆจกๅผๅฐ†ๆŒ‡ๅฎš้‚ฃไบ› `set` ็š„ๅ€ผๆ˜ฏๅ”ฏไธ€็š„ (ไฝฟ็”จ JSON ๆจกๅผ็š„ `uniqueItems`)ใ€‚ + * ไบง็”Ÿ็š„ๆจกๅผๅฐ†ๆŒ‡ๅฎš้‚ฃไบ› `set` ็š„ๅ€ผๆ˜ฏๅ”ฏไธ€็š„ (ไฝฟ็”จ JSON Schema ็š„ `uniqueItems`)ใ€‚ * `bytes`: * ๆ ‡ๅ‡†็š„ Python `bytes`ใ€‚ * ๅœจ่ฏทๆฑ‚ๅ’Œๅ“ๅบ”ไธญ่ขซๅฝ“ไฝœ `str` ๅค„็†ใ€‚ @@ -49,9 +49,9 @@ * `Decimal`: * ๆ ‡ๅ‡†็š„ Python `Decimal`ใ€‚ * ๅœจ่ฏทๆฑ‚ๅ’Œๅ“ๅบ”ไธญ่ขซๅฝ“ๅš `float` ไธ€ๆ ทๅค„็†ใ€‚ -* ๆ‚จๅฏไปฅๅœจ่ฟ™้‡Œๆฃ€ๆŸฅๆ‰€ๆœ‰ๆœ‰ๆ•ˆ็š„pydanticๆ•ฐๆฎ็ฑปๅž‹: Pydantic data types. +* ๆ‚จๅฏไปฅๅœจ่ฟ™้‡Œๆฃ€ๆŸฅๆ‰€ๆœ‰ๆœ‰ๆ•ˆ็š„ Pydantic ๆ•ฐๆฎ็ฑปๅž‹: Pydantic data types. -## ไพ‹ๅญ +## ไพ‹ๅญ { #example } ไธ‹้ขๆ˜ฏไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*็š„็คบไพ‹๏ผŒๅ…ถไธญ็š„ๅ‚ๆ•ฐไฝฟ็”จไบ†ไธŠ้ข็š„ไธ€ไบ›็ฑปๅž‹ใ€‚ diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md index ccfb3aa5ab..4d18c76ec1 100644 --- a/docs/zh/docs/tutorial/extra-models.md +++ b/docs/zh/docs/tutorial/extra-models.md @@ -1,4 +1,4 @@ -# ๆ›ดๅคšๆจกๅž‹ +# ๆ›ดๅคšๆจกๅž‹ { #extra-models } ไนฆๆŽฅไธŠๆ–‡๏ผŒๅคšไธชๅ…ณ่”ๆจกๅž‹่ฟ™็งๆƒ…ๅ†ตๅพˆๅธธ่งใ€‚ @@ -6,29 +6,29 @@ * **่พ“ๅ…ฅๆจกๅž‹**ๅบ”่ฏฅๅซๅฏ†็  * **่พ“ๅ‡บๆจกๅž‹**ไธๅบ”ๅซๅฏ†็  -* **ๆ•ฐๆฎๅบ“ๆจกๅž‹**้œ€่ฆๅŠ ๅฏ†็š„ๅฏ†็  +* **ๆ•ฐๆฎๅบ“ๆจกๅž‹**ๅฏ่ƒฝ้œ€่ฆๅŒ…ๅซๅ“ˆๅธŒๅŽ็š„ๅฏ†็  -/// danger | ๅฑ้™ฉ +/// danger -ๅƒไธ‡ไธ่ฆๅญ˜ๅ‚จ็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ใ€‚ๅง‹็ปˆๅญ˜ๅ‚จๅฏไปฅ่ฟ›่กŒ้ชŒ่ฏ็š„**ๅฎ‰ๅ…จๅ“ˆๅธŒๅ€ผ**ใ€‚ +ไธ่ฆๅญ˜ๅ‚จ็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ใ€‚ๅง‹็ปˆๅชๅญ˜ๅ‚จไน‹ๅŽๅฏ็”จไบŽๆ ก้ชŒ็š„โ€œๅฎ‰ๅ…จๅ“ˆๅธŒโ€ใ€‚ -ๅฆ‚ๆžœไธไบ†่งฃ่ฟ™ๆ–น้ข็š„็Ÿฅ่ฏ†๏ผŒ่ฏทๅ‚้˜…[ๅฎ‰ๅ…จๆ€งไธญ็š„็ซ ่Š‚](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}๏ผŒไบ†่งฃไป€ไนˆๆ˜ฏ**ๅฏ†็ ๅ“ˆๅธŒ**ใ€‚ +ๅฆ‚ๆžœไฝ ่ฟ˜ไธไบ†่งฃ๏ผŒๅฏไปฅๅœจ[ๅฎ‰ๅ…จๆ€ง็ซ ่Š‚](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}ไธญๅญฆไน ไป€ไนˆๆ˜ฏโ€œๅฏ†็ ๅ“ˆๅธŒโ€ใ€‚ /// -## ๅคšไธชๆจกๅž‹ +## ๅคšไธชๆจกๅž‹ { #multiple-models } ไธ‹้ข็š„ไปฃ็ ๅฑ•็คบไบ†ไธๅŒๆจกๅž‹ๅค„็†ๅฏ†็ ๅญ—ๆฎต็š„ๆ–นๅผ๏ผŒๅŠไฝฟ็”จไฝ็ฝฎ็š„ๅคง่‡ดๆ€่ทฏ๏ผš {* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} -### `**user_in.dict()` ็ฎ€ไป‹ +### ๅ…ณไบŽ `**user_in.model_dump()` { #about-user-in-model-dump } -#### Pydantic ็š„ `.dict()` +#### Pydantic ็š„ `.model_dump()` { #pydantics-model-dump } `user_in` ๆ˜ฏ็ฑป `UserIn` ็š„ Pydantic ๆจกๅž‹ใ€‚ -Pydantic ๆจกๅž‹ๆ”ฏๆŒ `.dict()` ๆ–นๆณ•๏ผŒ่ƒฝ่ฟ”ๅ›žๅŒ…ๅซๆจกๅž‹ๆ•ฐๆฎ็š„**ๅญ—ๅ…ธ**ใ€‚ +Pydantic ๆจกๅž‹ๆœ‰ `.model_dump()` ๆ–นๆณ•๏ผŒไผš่ฟ”ๅ›žๅŒ…ๅซๆจกๅž‹ๆ•ฐๆฎ็š„ `dict`ใ€‚ ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝฟ็”จๅฆ‚ไธ‹ๆ–นๅผๅˆ›ๅปบ Pydantic ๅฏน่ฑก `user_in`๏ผš @@ -39,10 +39,10 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com ๅฐฑ่ƒฝไปฅๅฆ‚ไธ‹ๆ–นๅผ่ฐƒ็”จ๏ผš ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() ``` -็Žฐๅœจ๏ผŒๅ˜้‡ `user_dict`ไธญ็š„ๅฐฑๆ˜ฏๅŒ…ๅซๆ•ฐๆฎ็š„**ๅญ—ๅ…ธ**๏ผˆๅ˜้‡ `user_dict` ๆ˜ฏๅญ—ๅ…ธ๏ผŒไธๆ˜ฏ Pydantic ๆจกๅž‹ๅฏน่ฑก๏ผ‰ใ€‚ +็Žฐๅœจ๏ผŒๅ˜้‡ `user_dict` ไธญ็š„ๆ˜ฏๅŒ…ๅซๆ•ฐๆฎ็š„ `dict`๏ผˆๅฎƒๆ˜ฏ `dict`๏ผŒไธๆ˜ฏ Pydantic ๆจกๅž‹ๅฏน่ฑก๏ผ‰ใ€‚ ไปฅๅฆ‚ไธ‹ๆ–นๅผ่ฐƒ็”จ๏ผš @@ -50,7 +50,7 @@ user_dict = user_in.dict() print(user_dict) ``` -่พ“ๅ‡บ็š„ๅฐฑๆ˜ฏ Python **ๅญ—ๅ…ธ**๏ผš +่พ“ๅ‡บ็š„ๅฐฑๆ˜ฏ Python `dict`๏ผš ```Python { @@ -61,9 +61,9 @@ print(user_dict) } ``` -#### ่งฃๅŒ… `dict` +#### ่งฃๅŒ… `dict` { #unpacking-a-dict } -ๆŠŠ**ๅญ—ๅ…ธ** `user_dict` ไปฅ `**user_dict` ๅฝขๅผไผ ้€’็ป™ๅ‡ฝๆ•ฐ๏ผˆๆˆ–็ฑป๏ผ‰๏ผŒPython ไผšๆ‰ง่กŒ**่งฃๅŒ…**ๆ“ไฝœใ€‚ๅฎƒไผšๆŠŠ `user_dict` ็š„้”ฎๅ’Œๅ€ผไฝœไธบๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ็›ดๆŽฅไผ ้€’ใ€‚ +ๆŠŠ `dict`๏ผˆๅฆ‚ `user_dict`๏ผ‰ไปฅ `**user_dict` ๅฝขๅผไผ ้€’็ป™ๅ‡ฝๆ•ฐ๏ผˆๆˆ–็ฑป๏ผ‰๏ผŒPython ไผšๆ‰ง่กŒโ€œ่งฃๅŒ…โ€ใ€‚ๅฎƒไผšๆŠŠ `user_dict` ็š„้”ฎๅ’Œๅ€ผไฝœไธบๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ็›ดๆŽฅไผ ้€’ใ€‚ ๅ› ๆญค๏ผŒๆŽฅ็€ไธŠ้ข็š„ `user_dict` ็ปง็ปญ็ผ–ๅ†™ๅฆ‚ไธ‹ไปฃ็ ๏ผš @@ -82,7 +82,7 @@ UserInDB( ) ``` -ๆˆ–ๆ›ด็ฒพๅ‡†๏ผŒ็›ดๆŽฅๆŠŠๅฏ่ƒฝไผš็”จๅˆฐ็š„ๅ†…ๅฎนไธŽ `user_dict` ไธ€่ตทไฝฟ็”จ๏ผš +ๆˆ–ๆ›ด็ฒพๅ‡†๏ผŒ็›ดๆŽฅไฝฟ็”จ `user_dict`๏ผˆๆ— ่ฎบๅฎƒๅฐ†ๆฅๅŒ…ๅซไป€ไนˆๅญ—ๆฎต๏ผ‰๏ผš ```Python UserInDB( @@ -93,31 +93,31 @@ UserInDB( ) ``` -#### ็”จๅ…ถๅฎƒๆจกๅž‹ไธญ็š„ๅ†…ๅฎน็”Ÿๆˆ Pydantic ๆจกๅž‹ +#### ็”จๅฆไธ€ไธชๆจกๅž‹็š„ๅ†…ๅฎน็”Ÿๆˆ Pydantic ๆจกๅž‹ { #a-pydantic-model-from-the-contents-of-another } -ไธŠไพ‹ไธญ ๏ผŒไปŽ `user_in.dict()` ไธญๅพ—ๅˆฐไบ† `user_dict`๏ผŒไธ‹้ข็š„ไปฃ็ ๏ผš +ไธŠไพ‹ไธญ ๏ผŒไปŽ `user_in.model_dump()` ไธญๅพ—ๅˆฐไบ† `user_dict`๏ผŒไธ‹้ข็š„ไปฃ็ ๏ผš ```Python -user_dict = user_in.dict() +user_dict = user_in.model_dump() UserInDB(**user_dict) ``` ็ญ‰ๆ•ˆไบŽ๏ผš ```Python -UserInDB(**user_in.dict()) +UserInDB(**user_in.model_dump()) ``` -โ€ฆโ€ฆๅ› ไธบ `user_in.dict()` ๆ˜ฏๅญ—ๅ…ธ๏ผŒๅœจไผ ้€’็ป™ `UserInDB` ๆ—ถ๏ผŒๆŠŠ `**` ๅŠ ๅœจ `user_in.dict()` ๅ‰๏ผŒๅฏไปฅ่ฎฉ Python ่ฟ›่กŒ**่งฃๅŒ…**ใ€‚ +โ€ฆโ€ฆๅ› ไธบ `user_in.model_dump()` ๆ˜ฏ `dict`๏ผŒๅœจไผ ้€’็ป™ `UserInDB` ๆ—ถ๏ผŒๆŠŠ `**` ๅŠ ๅœจ `user_in.model_dump()` ๅ‰๏ผŒๅฏไปฅ่ฎฉ Python ่ฟ›่กŒ่งฃๅŒ…ใ€‚ ่ฟ™ๆ ท๏ผŒๅฐฑๅฏไปฅ็”จๅ…ถๅฎƒ Pydantic ๆจกๅž‹ไธญ็š„ๆ•ฐๆฎ็”Ÿๆˆ Pydantic ๆจกๅž‹ใ€‚ -#### ่งฃๅŒ… `dict` ๅ’Œๆ›ดๅคšๅ…ณ้”ฎๅญ— +#### ่งฃๅŒ… `dict` ๅนถๆทปๅŠ ้ขๅค–ๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ { #unpacking-a-dict-and-extra-keywords } ๆŽฅไธ‹ๆฅ๏ผŒ็ปง็ปญๆทปๅŠ ๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ `hashed_password=hashed_password`๏ผŒไพ‹ๅฆ‚๏ผš ```Python -UserInDB(**user_in.dict(), hashed_password=hashed_password) +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` โ€ฆโ€ฆ่พ“ๅ‡บ็ป“ๆžœๅฆ‚ไธ‹๏ผš @@ -132,68 +132,80 @@ UserInDB( ) ``` -/// warning | ่ญฆๅ‘Š +/// warning -่พ…ๅŠฉ็š„้™„ๅŠ ๅ‡ฝๆ•ฐๅชๆ˜ฏไธบไบ†ๆผ”็คบๅฏ่ƒฝ็š„ๆ•ฐๆฎๆต๏ผŒไฝ†ๅฎƒไปฌๆ˜พ็„ถไธ่ƒฝๆไพ›ไปปไฝ•็œŸๆญฃ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +้…ๅฅ—็š„่พ…ๅŠฉๅ‡ฝๆ•ฐ `fake_password_hasher` ๅ’Œ `fake_save_user` ไป…็”จไบŽๆผ”็คบๅฏ่ƒฝ็š„ๆ•ฐๆฎๆต๏ผŒๅฝ“็„ถๅนถไธๆไพ›็œŸๅฎž็š„ๅฎ‰ๅ…จๆ€งใ€‚ /// -## ๅ‡ๅฐ‘้‡ๅค +## ๅ‡ๅฐ‘้‡ๅค { #reduce-duplication } -**FastAPI** ็š„ๆ ธๅฟƒๆ€ๆƒณๅฐฑๆ˜ฏๅ‡ๅฐ‘ไปฃ็ ้‡ๅคใ€‚ +ๅ‡ๅฐ‘ไปฃ็ ้‡ๅคๆ˜ฏ **FastAPI** ็š„ๆ ธๅฟƒๆ€ๆƒณไน‹ไธ€ใ€‚ ไปฃ็ ้‡ๅคไผšๅฏผ่‡ด bugใ€ๅฎ‰ๅ…จ้—ฎ้ข˜ใ€ไปฃ็ ๅคฑๆญฅ็ญ‰้—ฎ้ข˜๏ผˆๆ›ดๆ–ฐไบ†ๆŸไธชไฝ็ฝฎ็š„ไปฃ็ ๏ผŒไฝ†ๆฒกๆœ‰ๅŒๆญฅๆ›ดๆ–ฐๅ…ถๅฎƒไฝ็ฝฎ็š„ไปฃ็ ๏ผ‰ใ€‚ ไธŠ้ข็š„่ฟ™ไบ›ๆจกๅž‹ๅ…ฑไบซไบ†ๅคง้‡ๆ•ฐๆฎ๏ผŒๆ‹ฅๆœ‰้‡ๅค็š„ๅฑžๆ€งๅๅ’Œ็ฑปๅž‹ใ€‚ -FastAPI ๅฏไปฅๅšๅพ—ๆ›ดๅฅฝใ€‚ +ๆˆ‘ไปฌๅฏไปฅๅšๅพ—ๆ›ดๅฅฝใ€‚ -ๅฃฐๆ˜Ž `UserBase` ๆจกๅž‹ไฝœไธบๅ…ถๅฎƒๆจกๅž‹็š„ๅŸบ็ฑปใ€‚็„ถๅŽ๏ผŒ็”จ่ฏฅ็ฑป่ก็”Ÿๅ‡บ็ปงๆ‰ฟๅ…ถๅฑžๆ€ง๏ผˆ็ฑปๅž‹ๅฃฐๆ˜Žใ€้ชŒ่ฏ็ญ‰๏ผ‰็š„ๅญ็ฑปใ€‚ +ๅฃฐๆ˜Ž `UserBase` ๆจกๅž‹ไฝœไธบๅ…ถๅฎƒๆจกๅž‹็š„ๅŸบ็ฑปใ€‚็„ถๅŽ๏ผŒ็”จ่ฏฅ็ฑป่ก็”Ÿๅ‡บ็ปงๆ‰ฟๅ…ถๅฑžๆ€ง๏ผˆ็ฑปๅž‹ๅฃฐๆ˜Žใ€ๆ ก้ชŒ็ญ‰๏ผ‰็š„ๅญ็ฑปใ€‚ ๆ‰€ๆœ‰ๆ•ฐๆฎ่ฝฌๆขใ€ๆ ก้ชŒใ€ๆ–‡ๆกฃ็ญ‰ๅŠŸ่ƒฝไปๅฐ†ๆญฃๅธธ่ฟ่กŒใ€‚ -่ฟ™ๆ ท๏ผŒๅฐฑๅฏไปฅไป…ๅฃฐๆ˜Žๆจกๅž‹ไน‹้—ด็š„ๅทฎๅผ‚้ƒจๅˆ†๏ผˆๅ…ทๆœ‰ๆ˜Žๆ–‡็š„ `password`ใ€ๅ…ทๆœ‰ `hashed_password` ไปฅๅŠไธๅŒ…ๆ‹ฌๅฏ†็ ๏ผ‰ใ€‚ - -้€š่ฟ‡่ฟ™็งๆ–นๅผ๏ผŒๅฏไปฅๅชๅฃฐๆ˜Žๆจกๅž‹ไน‹้—ด็š„ๅŒบๅˆซ๏ผˆๅˆ†ๅˆซๅŒ…ๅซๆ˜Žๆ–‡ๅฏ†็ ใ€ๅ“ˆๅธŒๅฏ†็ ๏ผŒไปฅๅŠๆ— ๅฏ†็ ็š„ๆจกๅž‹๏ผ‰ใ€‚ +่ฟ™ๆ ท๏ผŒๅฐฑๅฏไปฅไป…ๅฃฐๆ˜Žๆจกๅž‹ไน‹้—ด็š„ๅทฎๅผ‚้ƒจๅˆ†๏ผˆๅ…ทๆœ‰ๆ˜Žๆ–‡็š„ `password`ใ€ๅ…ทๆœ‰ `hashed_password` ไปฅๅŠไธๅŒ…ๆ‹ฌๅฏ†็ ๏ผ‰๏ผš {* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} -## `Union` ๆˆ–่€… `anyOf` +## `Union` ๆˆ– `anyOf` { #union-or-anyof } -ๅ“ๅบ”ๅฏไปฅๅฃฐๆ˜Žไธบไธค็ง็ฑปๅž‹็š„ `Union` ็ฑปๅž‹๏ผŒๅณ่ฏฅๅ“ๅบ”ๅฏไปฅๆ˜ฏไธค็ง็ฑปๅž‹ไธญ็š„ไปปๆ„็ฑปๅž‹ใ€‚ +ๅ“ๅบ”ๅฏไปฅๅฃฐๆ˜Žไธบไธคไธชๆˆ–ๅคšไธช็ฑปๅž‹็š„ `Union`๏ผŒๅณ่ฏฅๅ“ๅบ”ๅฏไปฅๆ˜ฏ่ฟ™ไบ›็ฑปๅž‹ไธญ็š„ไปปๆ„ไธ€็งใ€‚ -ๅœจ OpenAPI ไธญๅฏไปฅไฝฟ็”จ `anyOf` ๅฎšไน‰ใ€‚ +ๅœจ OpenAPI ไธญไผš็”จ `anyOf` ่กจ็คบใ€‚ ไธบๆญค๏ผŒ่ฏทไฝฟ็”จ Python ๆ ‡ๅ‡†็ฑปๅž‹ๆ็คบ `typing.Union`๏ผš -/// note | ็ฌ”่ฎฐ +/// note -ๅฎšไน‰ `Union` ็ฑปๅž‹ๆ—ถ๏ผŒ่ฆๆŠŠ่ฏฆ็ป†็š„็ฑปๅž‹ๅ†™ๅœจๅ‰้ข๏ผŒ็„ถๅŽๆ˜ฏไธๅคช่ฏฆ็ป†็š„็ฑปๅž‹ใ€‚ไธ‹ไพ‹ไธญ๏ผŒๆ›ด่ฏฆ็ป†็š„ `PlaneItem` ไฝไบŽ `Union[PlaneItem๏ผŒCarItem]` ไธญ็š„ `CarItem` ไน‹ๅ‰ใ€‚ +ๅฎšไน‰ `Union` ็ฑปๅž‹ๆ—ถ๏ผŒ่ฆๆŠŠๆ›ดๅ…ทไฝ“็š„็ฑปๅž‹ๅ†™ๅœจๅ‰้ข๏ผŒ็„ถๅŽๆ˜ฏไธๅคชๅ…ทไฝ“็š„็ฑปๅž‹ใ€‚ไธ‹ไพ‹ไธญ๏ผŒๆ›ดๅ…ทไฝ“็š„ `PlaneItem` ไฝไบŽ `Union[PlaneItem, CarItem]` ไธญ็š„ `CarItem` ไน‹ๅ‰ใ€‚ /// {* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} -## ๆจกๅž‹ๅˆ—่กจ +### Python 3.10 ไธญ็š„ `Union` { #union-in-python-3-10 } + +ๅœจ่ฟ™ไธช็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๆŠŠ `Union[PlaneItem, CarItem]` ไฝœไธบๅ‚ๆ•ฐ `response_model` ็š„ๅ€ผไผ ๅ…ฅใ€‚ + +ๅ› ไธบ่ฟ™ๆ˜ฏไฝœไธบโ€œๅ‚ๆ•ฐ็š„ๅ€ผโ€่€Œไธๆ˜ฏๆ”พๅœจโ€œ็ฑปๅž‹ๆณจ่งฃโ€ไธญ๏ผŒๆ‰€ไปฅๅณไฝฟๅœจ Python 3.10 ไนŸๅฟ…้กปไฝฟ็”จ `Union`ใ€‚ + +ๅฆ‚ๆžœๆ˜ฏๅœจ็ฑปๅž‹ๆณจ่งฃไธญ๏ผŒๆˆ‘ไปฌๅฐฑๅฏไปฅไฝฟ็”จ็ซ–็บฟ๏ผš + +```Python +some_variable: PlaneItem | CarItem +``` + +ไฝ†ๅฆ‚ๆžœๆŠŠๅฎƒๅ†™ๆˆ่ต‹ๅ€ผ `response_model=PlaneItem | CarItem`๏ผŒๅฐฑไผšๆŠฅ้”™๏ผŒๅ› ไธบ Python ไผšๅฐ่ฏ•ๅœจ `PlaneItem` ๅ’Œ `CarItem` ไน‹้—ดๆ‰ง่กŒไธ€ไธชโ€œๆ— ๆ•ˆ็š„่ฟ็ฎ—โ€๏ผŒ่€Œไธๆ˜ฏๆŠŠๅฎƒๅฝ“ไฝœ็ฑปๅž‹ๆณจ่งฃๆฅ่งฃๆžใ€‚ + +## ๆจกๅž‹ๅˆ—่กจ { #list-of-models } -ไฝฟ็”จๅŒๆ ท็š„ๆ–นๅผไนŸๅฏไปฅๅฃฐๆ˜Ž็”ฑๅฏน่ฑกๅˆ—่กจๆž„ๆˆ็š„ๅ“ๅบ”ใ€‚ +ๅŒๆ ทๅœฐ๏ผŒไฝ ๅฏไปฅๅฃฐๆ˜Ž็”ฑๅฏน่ฑกๅˆ—่กจๆž„ๆˆ็š„ๅ“ๅบ”ใ€‚ -ไธบๆญค๏ผŒ่ฏทไฝฟ็”จๆ ‡ๅ‡†็š„ Python `typing.List`๏ผš +ไธบๆญค๏ผŒ่ฏทไฝฟ็”จๆ ‡ๅ‡†็š„ Python `typing.List`๏ผˆๅœจ Python 3.9+ ไธญไนŸๅฏไปฅ็›ดๆŽฅ็”จ `list`๏ผ‰๏ผš {* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} -## ไปปๆ„ `dict` ๆž„ๆˆ็š„ๅ“ๅบ” +## ไปปๆ„ `dict` ็š„ๅ“ๅบ” { #response-with-arbitrary-dict } -ไปปๆ„็š„ `dict` ้ƒฝ่ƒฝ็”จไบŽๅฃฐๆ˜Žๅ“ๅบ”๏ผŒๅช่ฆๅฃฐๆ˜Ž้”ฎๅ’Œๅ€ผ็š„็ฑปๅž‹๏ผŒๆ— ้œ€ไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ +ไฝ ไนŸๅฏไปฅไฝฟ็”จๆ™ฎ้€š็š„ไปปๆ„ `dict` ๆฅๅฃฐๆ˜Žๅ“ๅบ”๏ผŒๅช้œ€ๅฃฐๆ˜Ž้”ฎๅ’Œๅ€ผ็š„็ฑปๅž‹๏ผŒๆ— ้œ€ไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ -ไบ‹ๅ…ˆไธ็Ÿฅ้“ๅฏ็”จ็š„ๅญ—ๆฎต / ๅฑžๆ€งๅๆ—ถ๏ผˆPydantic ๆจกๅž‹ๅฟ…้กป็Ÿฅ้“ๅญ—ๆฎตๆ˜ฏไป€ไนˆ๏ผ‰๏ผŒ่ฟ™็งๆ–นๅผ็‰นๅˆซๆœ‰็”จใ€‚ +ๅฆ‚ๆžœไฝ ไบ‹ๅ…ˆไธ็Ÿฅ้“ๆœ‰ๆ•ˆ็š„ๅญ—ๆฎต/ๅฑžๆ€งๅ๏ผˆPydantic ๆจกๅž‹้œ€่ฆ้ข„ๅ…ˆ็Ÿฅ้“ๅญ—ๆฎต๏ผ‰ๆ—ถ๏ผŒ่ฟ™ๅพˆๆœ‰็”จใ€‚ -ๆญคๆ—ถ๏ผŒๅฏไปฅไฝฟ็”จ `typing.Dict`๏ผš +ๆญคๆ—ถ๏ผŒๅฏไปฅไฝฟ็”จ `typing.Dict`๏ผˆๅœจ Python 3.9+ ไธญไนŸๅฏไปฅ็›ดๆŽฅ็”จ `dict`๏ผ‰๏ผš {* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -้’ˆๅฏนไธๅŒๅœบๆ™ฏ๏ผŒๅฏไปฅ้šๆ„ไฝฟ็”จไธๅŒ็š„ Pydantic ๆจกๅž‹็ปงๆ‰ฟๅฎšไน‰็š„ๅŸบ็ฑปใ€‚ +้’ˆๅฏนไธๅŒๅœบๆ™ฏ๏ผŒๅฏไปฅ้šๆ„ไฝฟ็”จไธๅŒ็š„ Pydantic ๆจกๅž‹ๅนถ้€š่ฟ‡็ปงๆ‰ฟๅค็”จใ€‚ -ๅฎžไฝ“ๅฟ…้กปๅ…ทๆœ‰ไธๅŒ็š„**็Šถๆ€**ๆ—ถ๏ผŒไธๅฟ…ไธบไธๅŒ็Šถๆ€็š„ๅฎžไฝ“ๅ•็‹ฌๅฎšไน‰ๆ•ฐๆฎๆจกๅž‹ใ€‚ไพ‹ๅฆ‚๏ผŒ็”จๆˆท**ๅฎžไฝ“**ๅฐฑๆœ‰ๅŒ…ๅซ `password`ใ€ๅŒ…ๅซ `password_hash` ไปฅๅŠไธๅซๅฏ†็ ็ญ‰ๅคš็ง็Šถๆ€ใ€‚ +ๅฝ“ไธ€ไธชๅฎžไฝ“้œ€่ฆๅ…ทๅค‡ไธๅŒ็š„โ€œ็Šถๆ€โ€ๆ—ถ๏ผŒๆ— ้œ€ๅชไธบ่ฏฅๅฎžไฝ“ๅฎšไน‰ไธ€ไธชๆ•ฐๆฎๆจกๅž‹ใ€‚ไพ‹ๅฆ‚๏ผŒ็”จๆˆทโ€œๅฎžไฝ“โ€ๅฐฑๅฏ่ƒฝๆœ‰ๅŒ…ๅซ `password`ใ€ๅŒ…ๅซ `password_hash` ไปฅๅŠไธๅซๅฏ†็ ็ญ‰ๅคš็ง็Šถๆ€ใ€‚ diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index 2d7c35c8c7..5d01884b80 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -1,8 +1,8 @@ -# ็ฌฌไธ€ๆญฅ +# ็ฌฌไธ€ๆญฅ { #first-steps } ๆœ€็ฎ€ๅ•็š„ FastAPI ๆ–‡ไปถๅฏ่ƒฝๅƒไธ‹้ข่ฟ™ๆ ท๏ผš -{* ../../docs_src/first_steps/tutorial001.py *} +{* ../../docs_src/first_steps/tutorial001_py39.py *} ๅฐ†ๅ…ถๅคๅˆถๅˆฐ `main.py` ๆ–‡ไปถไธญใ€‚ @@ -56,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ่ฏฅ่กŒๆ˜พ็คบไบ†ไฝ ็š„ๅบ”็”จๅœจๆœฌๆœบๆ‰€ๆไพ›ๆœๅŠก็š„ URL ๅœฐๅ€ใ€‚ -### ๆŸฅ็œ‹ +### ๆŸฅ็œ‹ { #check-it } ๆ‰“ๅผ€ๆต่งˆๅ™จ่ฎฟ้—ฎ http://127.0.0.1:8000ใ€‚ @@ -66,7 +66,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) {"message": "Hello World"} ``` -### ไบคไบ’ๅผ API ๆ–‡ๆกฃ +### ไบคไบ’ๅผ API ๆ–‡ๆกฃ { #interactive-api-docs } ่ทณ่ฝฌๅˆฐ http://127.0.0.1:8000/docsใ€‚ @@ -74,7 +74,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### ๅฏ้€‰็š„ API ๆ–‡ๆกฃ +### ๅฏ้€‰็š„ API ๆ–‡ๆกฃ { #alternative-api-docs } ๅ‰ๅพ€ http://127.0.0.1:8000/redocใ€‚ @@ -82,35 +82,35 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } **FastAPI** ไฝฟ็”จๅฎšไน‰ API ็š„ **OpenAPI** ๆ ‡ๅ‡†ๅฐ†ไฝ ็š„ๆ‰€ๆœ‰ API ่ฝฌๆขๆˆใ€Œๆจกๅผใ€ใ€‚ -#### ใ€Œๆจกๅผใ€ +#### ใ€Œๆจกๅผใ€ { #schema } ใ€Œๆจกๅผใ€ๆ˜ฏๅฏนไบ‹็‰ฉ็š„ไธ€็งๅฎšไน‰ๆˆ–ๆ่ฟฐใ€‚ๅฎƒๅนถ้žๅ…ทไฝ“็š„ๅฎž็Žฐไปฃ็ ๏ผŒ่€Œๅชๆ˜ฏๆŠฝ่ฑก็š„ๆ่ฟฐใ€‚ -#### APIใ€Œๆจกๅผใ€ +#### APIใ€Œๆจกๅผใ€ { #api-schema } ๅœจ่ฟ™็งๅœบๆ™ฏไธ‹๏ผŒOpenAPI ๆ˜ฏไธ€็ง่ง„ๅฎšๅฆ‚ไฝ•ๅฎšไน‰ API ๆจกๅผ็š„่ง„่Œƒใ€‚ ใ€Œๆจกๅผใ€็š„ๅฎšไน‰ๅŒ…ๆ‹ฌไฝ ็š„ API ่ทฏๅพ„๏ผŒไปฅๅŠๅฎƒไปฌๅฏ่ƒฝไฝฟ็”จ็š„ๅ‚ๆ•ฐ็ญ‰็ญ‰ใ€‚ -#### ๆ•ฐๆฎใ€Œๆจกๅผใ€ +#### ๆ•ฐๆฎใ€Œๆจกๅผใ€ { #data-schema } ใ€Œๆจกๅผใ€่ฟ™ไธชๆœฏ่ฏญไนŸๅฏ่ƒฝๆŒ‡็š„ๆ˜ฏๆŸไบ›ๆ•ฐๆฎๆฏ”ๅฆ‚ JSON ็š„็ป“ๆž„ใ€‚ ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฏไปฅ่กจ็คบ JSON ็š„ๅฑžๆ€งๅŠๅ…ถๅ…ทๆœ‰็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒ็ญ‰็ญ‰ใ€‚ -#### OpenAPI ๅ’Œ JSON Schema +#### OpenAPI ๅ’Œ JSON Schema { #openapi-and-json-schema } OpenAPI ไธบไฝ ็š„ API ๅฎšไน‰ API ๆจกๅผใ€‚่ฏฅๆจกๅผไธญๅŒ…ๅซไบ†ไฝ ็š„ API ๅ‘้€ๅ’ŒๆŽฅๆ”ถ็š„ๆ•ฐๆฎ็š„ๅฎšไน‰๏ผˆๆˆ–็งฐไธบใ€Œๆจกๅผใ€๏ผ‰๏ผŒ่ฟ™ไบ›ๅฎšไน‰้€š่ฟ‡ JSON ๆ•ฐๆฎๆจกๅผๆ ‡ๅ‡† **JSON Schema** ๆ‰€็”Ÿๆˆใ€‚ -#### ๆŸฅ็œ‹ `openapi.json` +#### ๆŸฅ็œ‹ `openapi.json` { #check-the-openapi-json } ๅฆ‚ๆžœไฝ ๅฏนๅŽŸๅง‹็š„ OpenAPI ๆจกๅผ้•ฟไป€ไนˆๆ ทๅญๆ„Ÿๅˆฐๅฅฝๅฅ‡๏ผŒFastAPI ่‡ชๅŠจ็”Ÿๆˆไบ†ๅŒ…ๅซๆ‰€ๆœ‰ API ๆ่ฟฐ็š„ JSON๏ผˆๆจกๅผ๏ผ‰ใ€‚ -ไฝ ๅฏไปฅ็›ดๆŽฅๅœจ๏ผšhttp://127.0.0.1:8000/openapi.json ็œ‹ๅˆฐๅฎƒใ€‚ +ไฝ ๅฏไปฅ็›ดๆŽฅๅœจ๏ผšhttp://127.0.0.1:800api.json ็œ‹ๅˆฐๅฎƒใ€‚ ๅฎƒๅฐ†ๆ˜พ็คบไปฅๅฆ‚ไธ‹ๅ†…ๅฎนๅผ€ๅคด็š„ JSON๏ผš @@ -135,7 +135,7 @@ OpenAPI ไธบไฝ ็š„ API ๅฎšไน‰ API ๆจกๅผใ€‚่ฏฅๆจกๅผไธญๅŒ…ๅซไบ†ไฝ ็š„ API ๅ‘้€ ... ``` -#### OpenAPI ็š„็”จ้€” +#### OpenAPI ็š„็”จ้€” { #what-is-openapi-for } ้ฉฑๅŠจ FastAPI ๅ†…็ฝฎ็š„ 2 ไธชไบคไบ’ๅผๆ–‡ๆกฃ็ณป็ปŸ็š„ๆญฃๆ˜ฏ OpenAPI ๆจกๅผใ€‚ @@ -143,11 +143,47 @@ OpenAPI ไธบไฝ ็š„ API ๅฎšไน‰ API ๆจกๅผใ€‚่ฏฅๆจกๅผไธญๅŒ…ๅซไบ†ไฝ ็š„ API ๅ‘้€ ไฝ ่ฟ˜ๅฏไปฅไฝฟ็”จๅฎƒ่‡ชๅŠจ็”ŸๆˆไธŽไฝ ็š„ API ่ฟ›่กŒ้€šไฟก็š„ๅฎขๆˆท็ซฏไปฃ็ ใ€‚ไพ‹ๅฆ‚ web ๅ‰็ซฏ๏ผŒ็งปๅŠจ็ซฏๆˆ–็‰ฉ่”็ฝ‘ๅตŒๅ…ฅ็จ‹ๅบใ€‚ -## ๅˆ†ๆญฅๆฆ‚ๆ‹ฌ +### ้ƒจ็ฝฒไฝ ็š„ๅบ”็”จ๏ผˆๅฏ้€‰๏ผ‰ { #deploy-your-app-optional } -### ๆญฅ้ชค 1๏ผšๅฏผๅ…ฅ `FastAPI` +ไฝ ๅฏไปฅ้€‰ๆ‹ฉๅฐ† FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloud๏ผŒๅฆ‚ๆžœ่ฟ˜ๆฒกๆœ‰๏ผŒๅ…ˆๅŽปๅŠ ๅ…ฅๅ€™่กฅๅๅ•ใ€‚๐Ÿš€ -{* ../../docs_src/first_steps/tutorial001.py hl[1] *} +ๅฆ‚ๆžœไฝ ๅทฒ็ปๆ‹ฅๆœ‰ **FastAPI Cloud** ่ดฆๆˆท๏ผˆๆˆ‘ไปฌไปŽๅ€™่กฅๅๅ•้‚€่ฏทไบ†ไฝ  ๐Ÿ˜‰๏ผ‰๏ผŒไฝ ๅฏไปฅ็”จไธ€ๆกๅ‘ฝไปค้ƒจ็ฝฒๅบ”็”จใ€‚ + +้ƒจ็ฝฒๅ‰๏ผŒๅ…ˆ็กฎไฟๅทฒ็™ปๅฝ•๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +็„ถๅŽ้ƒจ็ฝฒไฝ ็š„ๅบ”็”จ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ่ฟ™ไบ›๏ผ็Žฐๅœจไฝ ๅฏไปฅ้€š่ฟ‡่ฏฅ URL ่ฎฟ้—ฎไฝ ็š„ๅบ”็”จไบ†ใ€‚โœจ + +## ๅˆ†ๆญฅๆฆ‚ๆ‹ฌ { #recap-step-by-step } + +### ๆญฅ้ชค 1๏ผšๅฏผๅ…ฅ `FastAPI` { #step-1-import-fastapi } + +{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} `FastAPI` ๆ˜ฏไธ€ไธชไธบไฝ ็š„ API ๆไพ›ไบ†ๆ‰€ๆœ‰ๅŠŸ่ƒฝ็š„ Python ็ฑปใ€‚ @@ -159,17 +195,17 @@ OpenAPI ไธบไฝ ็š„ API ๅฎšไน‰ API ๆจกๅผใ€‚่ฏฅๆจกๅผไธญๅŒ…ๅซไบ†ไฝ ็š„ API ๅ‘้€ /// -### ๆญฅ้ชค 2๏ผšๅˆ›ๅปบไธ€ไธช `FastAPI`ใ€Œๅฎžไพ‹ใ€ +### ๆญฅ้ชค 2๏ผšๅˆ›ๅปบไธ€ไธช `FastAPI`ใ€Œๅฎžไพ‹ใ€ { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} ่ฟ™้‡Œ็š„ๅ˜้‡ `app` ไผšๆ˜ฏ `FastAPI` ็ฑป็š„ไธ€ไธชใ€Œๅฎžไพ‹ใ€ใ€‚ ่ฟ™ไธชๅฎžไพ‹ๅฐ†ๆ˜ฏๅˆ›ๅปบไฝ ๆ‰€ๆœ‰ API ็š„ไธป่ฆไบคไบ’ๅฏน่ฑกใ€‚ -### ๆญฅ้ชค 3๏ผšๅˆ›ๅปบไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* +### ๆญฅ้ชค 3๏ผšๅˆ›ๅปบไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* { #step-3-create-a-path-operation } -#### ่ทฏๅพ„ +#### ่ทฏๅพ„ { #path } ่ฟ™้‡Œ็š„ใ€Œ่ทฏๅพ„ใ€ๆŒ‡็š„ๆ˜ฏ URL ไธญไปŽ็ฌฌไธ€ไธช `/` ่ตท็š„ๅŽๅŠ้ƒจๅˆ†ใ€‚ @@ -193,7 +229,7 @@ https://example.com/items/foo ๅผ€ๅ‘ API ๆ—ถ๏ผŒใ€Œ่ทฏๅพ„ใ€ๆ˜ฏ็”จๆฅๅˆ†็ฆปใ€Œๅ…ณๆณจ็‚นใ€ๅ’Œใ€Œ่ต„ๆบใ€็š„ไธป่ฆๆ‰‹ๆฎตใ€‚ -#### ๆ“ไฝœ +#### ๆ“ไฝœ { #operation } ่ฟ™้‡Œ็š„ใ€Œๆ“ไฝœใ€ๆŒ‡็š„ๆ˜ฏไธ€็ง HTTPใ€Œๆ–นๆณ•ใ€ใ€‚ @@ -228,9 +264,9 @@ https://example.com/items/foo ๆˆ‘ไปฌไนŸๆ‰“็ฎ—็งฐๅ‘ผๅฎƒไปฌไธบใ€Œๆ“ไฝœใ€ใ€‚ -#### ๅฎšไน‰ไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* +#### ๅฎšไน‰ไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} `@app.get("/")` ๅ‘Š่ฏ‰ **FastAPI** ๅœจๅฎƒไธ‹ๆ–น็š„ๅ‡ฝๆ•ฐ่ดŸ่ดฃๅค„็†ๅฆ‚ไธ‹่ฎฟ้—ฎ่ฏทๆฑ‚๏ผš @@ -276,7 +312,7 @@ https://example.com/items/foo /// -### ๆญฅ้ชค 4๏ผšๅฎšไน‰**่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ** +### ๆญฅ้ชค 4๏ผšๅฎšไน‰**่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ** { #step-4-define-the-path-operation-function } ่ฟ™ๆ˜ฏๆˆ‘ไปฌ็š„ใ€Œ**่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ**ใ€๏ผš @@ -284,7 +320,7 @@ https://example.com/items/foo * **ๆ“ไฝœ**๏ผšๆ˜ฏ `get`ใ€‚ * **ๅ‡ฝๆ•ฐ**๏ผšๆ˜ฏไฝไบŽใ€Œ่ฃ…้ฅฐๅ™จใ€ไธ‹ๆ–น็š„ๅ‡ฝๆ•ฐ๏ผˆไฝไบŽ `@app.get("/")` ไธ‹ๆ–น๏ผ‰ใ€‚ -{* ../../docs_src/first_steps/tutorial001.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} ่ฟ™ๆ˜ฏไธ€ไธช Python ๅ‡ฝๆ•ฐใ€‚ @@ -296,17 +332,17 @@ https://example.com/items/foo ไฝ ไนŸๅฏไปฅๅฐ†ๅ…ถๅฎšไน‰ไธบๅธธ่ง„ๅ‡ฝๆ•ฐ่€Œไธไฝฟ็”จ `async def`: -{* ../../docs_src/first_steps/tutorial003.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} /// note -ๅฆ‚ๆžœไฝ ไธ็Ÿฅ้“ไธค่€…็š„ๅŒบๅˆซ๏ผŒ่ฏทๆŸฅ้˜… [ๅนถๅ‘: *่ตถๆ—ถ้—ดๅ—๏ผŸ*](../async.md#_1){.internal-link target=_blank}ใ€‚ +ๅฆ‚ๆžœไฝ ไธ็Ÿฅ้“ไธค่€…็š„ๅŒบๅˆซ๏ผŒ่ฏทๆŸฅ้˜… [ๅนถๅ‘: *่ตถๆ—ถ้—ดๅ—๏ผŸ*](../async.md#in-a-hurry){.internal-link target=_blank}ใ€‚ /// -### ๆญฅ้ชค 5๏ผš่ฟ”ๅ›žๅ†…ๅฎน +### ๆญฅ้ชค 5๏ผš่ฟ”ๅ›žๅ†…ๅฎน { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} ไฝ ๅฏไปฅ่ฟ”ๅ›žไธ€ไธช `dict`ใ€`list`๏ผŒๅƒ `str`ใ€`int` ไธ€ๆ ท็š„ๅ•ไธชๅ€ผ๏ผŒ็ญ‰็ญ‰ใ€‚ @@ -314,10 +350,31 @@ https://example.com/items/foo ่ฟ˜ๆœ‰่ฎธๅคšๅ…ถไป–ๅฐ†ไผš่‡ชๅŠจ่ฝฌๆขไธบ JSON ็š„ๅฏน่ฑกๅ’Œๆจกๅž‹๏ผˆๅŒ…ๆ‹ฌ ORM ๅฏน่ฑก็ญ‰๏ผ‰ใ€‚ๅฐ่ฏ•ไธ‹ไฝฟ็”จไฝ ๆœ€ๅ–œๆฌข็š„ไธ€็ง๏ผŒๅฎƒๅพˆๆœ‰ๅฏ่ƒฝๅทฒ็ป่ขซๆ”ฏๆŒใ€‚ -## ๆ€ป็ป“ +### ๆญฅ้ชค 6๏ผš้ƒจ็ฝฒ { #step-6-deploy-it } + +็”จไธ€ๆกๅ‘ฝไปคๅฐ†ไฝ ็š„ๅบ”็”จ้ƒจ็ฝฒๅˆฐ **FastAPI Cloud**๏ผš`fastapi deploy`ใ€‚๐ŸŽ‰ + +#### ๅ…ณไบŽ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ไฝœ่€…ๅ’Œๅ›ข้˜Ÿๆ‰“้€ ใ€‚ + +ๅฎƒไปฅๆœ€ๅฐ็š„ๆŠ•ๅ…ฅ็ฎ€ๅŒ–ไบ† **ๆž„ๅปบ**ใ€**้ƒจ็ฝฒ** ๅ’Œ **่ฎฟ้—ฎ** API ็š„ๆต็จ‹ใ€‚ + +ๅฎƒๆŠŠไฝฟ็”จ FastAPI ๆž„ๅปบๅบ”็”จ็š„็›ธๅŒ**ๅผ€ๅ‘่€…ไฝ“้ชŒ**ๅธฆๅˆฐไบ†ๅฐ†ๅบ”็”จ**้ƒจ็ฝฒ**ๅˆฐไบ‘็ซฏ็š„่ฟ‡็จ‹ใ€‚๐ŸŽ‰ + +FastAPI Cloud ๆ˜ฏ *FastAPI ๅŠๅ…ถๆœ‹ๅ‹ไปฌ* ๅผ€ๆบ้กน็›ฎ็š„ไธป่ฆ่ตžๅŠฉๅ’Œ่ต„้‡‘ๆไพ›ๆ–นใ€‚โœจ + +#### ้ƒจ็ฝฒๅˆฐๅ…ถไป–ไบ‘ๆœๅŠกๅ•† { #deploy-to-other-cloud-providers } + +FastAPI ๆ˜ฏๅผ€ๆบๅนถๅŸบไบŽๆ ‡ๅ‡†็š„ใ€‚ไฝ ๅฏไปฅๅฐ† FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐไฝ ้€‰ๆ‹ฉ็š„ไปปไฝ•ไบ‘ๆœๅŠกๅ•†ใ€‚ + +ๆŒ‰็…งไฝ ็š„ไบ‘ๆœๅŠกๅ•†็š„ๆŒ‡ๅ—้ƒจ็ฝฒ FastAPI ๅบ”็”จๅณๅฏใ€‚๐Ÿค“ + +## ๆ€ป็ป“ { #recap } * ๅฏผๅ…ฅ `FastAPI`ใ€‚ * ๅˆ›ๅปบไธ€ไธช `app` ๅฎžไพ‹ใ€‚ * ็ผ–ๅ†™ไธ€ไธช**่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ**๏ผŒๅฆ‚ `@app.get("/")`ใ€‚ * ๅฎšไน‰ไธ€ไธช**่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ**๏ผŒๅฆ‚ `def root(): ...`ใ€‚ * ไฝฟ็”จๅ‘ฝไปค `fastapi dev` ่ฟ่กŒๅผ€ๅ‘ๆœๅŠกๅ™จใ€‚ +* ๅฏ้€‰๏ผšไฝฟ็”จ `fastapi deploy` ้ƒจ็ฝฒไฝ ็š„ๅบ”็”จใ€‚ diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md index ae667b74a7..986a847728 100644 --- a/docs/zh/docs/tutorial/handling-errors.md +++ b/docs/zh/docs/tutorial/handling-errors.md @@ -1,64 +1,62 @@ -# ๅค„็†้”™่ฏฏ +# ๅค„็†้”™่ฏฏ { #handling-errors } -ๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒ้œ€่ฆๅ‘ๅฎขๆˆท็ซฏ่ฟ”ๅ›ž้”™่ฏฏๆ็คบใ€‚ +ๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒ้œ€่ฆๅ‘ไฝฟ็”จไฝ ็š„ API ็š„ๅฎขๆˆท็ซฏ่ฟ”ๅ›ž้”™่ฏฏๆ็คบใ€‚ -่ฟ™้‡Œๆ‰€่ฐ“็š„ๅฎขๆˆท็ซฏๅŒ…ๆ‹ฌๅ‰็ซฏๆต่งˆๅ™จใ€ๅ…ถไป–ๅบ”็”จ็จ‹ๅบใ€็‰ฉ่”็ฝ‘่ฎพๅค‡็ญ‰ใ€‚ +่ฟ™้‡Œๆ‰€่ฐ“็š„ๅฎขๆˆท็ซฏๅŒ…ๆ‹ฌๅ‰็ซฏๆต่งˆๅ™จใ€ไป–ไบบ็š„ไปฃ็ ใ€็‰ฉ่”็ฝ‘่ฎพๅค‡็ญ‰ใ€‚ -้œ€่ฆๅ‘ๅฎขๆˆท็ซฏ่ฟ”ๅ›ž้”™่ฏฏๆ็คบ็š„ๅœบๆ™ฏไธป่ฆๅฆ‚ไธ‹๏ผš +ไฝ ๅฏ่ƒฝ้œ€่ฆๅ‘Š่ฏ‰ๅฎขๆˆท็ซฏ๏ผš -- ๅฎขๆˆท็ซฏๆฒกๆœ‰ๆ‰ง่กŒๆ“ไฝœ็š„ๆƒ้™ -- ๅฎขๆˆท็ซฏๆฒกๆœ‰่ฎฟ้—ฎ่ต„ๆบ็š„ๆƒ้™ +- ๅฎขๆˆท็ซฏๆฒกๆœ‰ๆ‰ง่กŒ่ฏฅๆ“ไฝœ็š„ๆƒ้™ +- ๅฎขๆˆท็ซฏๆฒกๆœ‰่ฎฟ้—ฎ่ฏฅ่ต„ๆบ็š„ๆƒ้™ - ๅฎขๆˆท็ซฏ่ฆ่ฎฟ้—ฎ็š„้กน็›ฎไธๅญ˜ๅœจ -- ็ญ‰็ญ‰ ... +- ็ญ‰็ญ‰ ้‡ๅˆฐ่ฟ™ไบ›ๆƒ…ๅ†ตๆ—ถ๏ผŒ้€šๅธธ่ฆ่ฟ”ๅ›ž **4XX**๏ผˆ400 ่‡ณ 499๏ผ‰**HTTP ็Šถๆ€็ **ใ€‚ -**4XX** ็Šถๆ€็ ไธŽ่กจ็คบ่ฏทๆฑ‚ๆˆๅŠŸ็š„ **2XX**๏ผˆ200 ่‡ณ 299๏ผ‰ HTTP ็Šถๆ€็ ็ฑปไผผใ€‚ +่ฟ™ไธŽ่กจ็คบ่ฏทๆฑ‚ๆˆๅŠŸ็š„ **2XX**๏ผˆ200 ่‡ณ 299๏ผ‰HTTP ็Šถๆ€็ ็ฑปไผผใ€‚้‚ฃไบ›โ€œ200โ€็Šถๆ€็ ่กจ็คบๆŸ็ง็จ‹ๅบฆไธŠ็š„โ€œๆˆๅŠŸโ€ใ€‚ -ๅชไธ่ฟ‡๏ผŒ**4XX** ็Šถๆ€็ ่กจ็คบๅฎขๆˆท็ซฏๅ‘็”Ÿ็š„้”™่ฏฏใ€‚ +่€Œ **4XX** ็Šถๆ€็ ่กจ็คบๅฎขๆˆท็ซฏๅ‘็”Ÿไบ†้”™่ฏฏใ€‚ ๅคงๅฎถ้ƒฝ็Ÿฅ้“**ใ€Œ404 Not Foundใ€**้”™่ฏฏ๏ผŒ่ฟ˜ๆœ‰่ฐƒไพƒ่ฟ™ไธช้”™่ฏฏ็š„็ฌ‘่ฏๅง๏ผŸ -## ไฝฟ็”จ `HTTPException` +## ไฝฟ็”จ `HTTPException` { #use-httpexception } ๅ‘ๅฎขๆˆท็ซฏ่ฟ”ๅ›ž HTTP ้”™่ฏฏๅ“ๅบ”๏ผŒๅฏไปฅไฝฟ็”จ `HTTPException`ใ€‚ -### ๅฏผๅ…ฅ `HTTPException` +### ๅฏผๅ…ฅ `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} -### ่งฆๅ‘ `HTTPException` +### ๅœจไปฃ็ ไธญ่งฆๅ‘ `HTTPException` { #raise-an-httpexception-in-your-code } `HTTPException` ๆ˜ฏ้ขๅค–ๅŒ…ๅซไบ†ๅ’Œ API ๆœ‰ๅ…ณๆ•ฐๆฎ็š„ๅธธ่ง„ Python ๅผ‚ๅธธใ€‚ ๅ› ไธบๆ˜ฏ Python ๅผ‚ๅธธ๏ผŒๆ‰€ไปฅไธ่ƒฝ `return`๏ผŒๅช่ƒฝ `raise`ใ€‚ -ๅฆ‚ๅœจ่ฐƒ็”จ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*้‡Œ็š„ๅทฅๅ…ทๅ‡ฝๆ•ฐๆ—ถ๏ผŒ่งฆๅ‘ไบ† `HTTPException`๏ผŒFastAPI ๅฐฑไธๅ†็ปง็ปญๆ‰ง่กŒ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅŽ็ปญไปฃ็ ๏ผŒ่€Œๆ˜ฏ็ซ‹ๅณ็ปˆๆญข่ฏทๆฑ‚๏ผŒๅนถๆŠŠ `HTTPException` ็š„ HTTP ้”™่ฏฏๅ‘้€่‡ณๅฎขๆˆท็ซฏใ€‚ +่ฟ™ไนŸๆ„ๅ‘ณ็€๏ผŒๅฆ‚ๆžœไฝ ๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*้‡Œ่ฐƒ็”จ็š„ๆŸไธชๅทฅๅ…ทๅ‡ฝๆ•ฐๅ†…้ƒจ่งฆๅ‘ไบ† `HTTPException`๏ผŒ้‚ฃไนˆ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญๅŽ็ปญ็š„ไปฃ็ ๅฐ†ไธไผš็ปง็ปญๆ‰ง่กŒ๏ผŒ่ฏทๆฑ‚ไผš็ซ‹ๅˆป็ปˆๆญข๏ผŒๅนถๆŠŠ `HTTPException` ็š„ HTTP ้”™่ฏฏๅ‘้€็ป™ๅฎขๆˆท็ซฏใ€‚ -ๅœจไป‹็ปไพ่ต–้กนไธŽๅฎ‰ๅ…จ็š„็ซ ่Š‚ไธญ๏ผŒๆ‚จๅฏไปฅไบ†่งฃๆ›ดๅคš็”จ `raise` ๅผ‚ๅธธไปฃๆ›ฟ `return` ๅ€ผ็š„ไผ˜ๅŠฟใ€‚ +ๅœจไป‹็ปไพ่ต–้กนไธŽๅฎ‰ๅ…จ็š„็ซ ่Š‚ไธญ๏ผŒไฝ ๅฏไปฅๆ›ด็›ด่ง‚ๅœฐ็œ‹ๅˆฐ็”จ `raise` ๅผ‚ๅธธไปฃๆ›ฟ `return` ๅ€ผ็š„ไผ˜ๅŠฟใ€‚ -ๆœฌไพ‹ไธญ๏ผŒๅฎขๆˆท็ซฏ็”จ `ID` ่ฏทๆฑ‚็š„ `item` ไธๅญ˜ๅœจๆ—ถ๏ผŒ่งฆๅ‘็Šถๆ€็ ไธบ `404` ็š„ๅผ‚ๅธธ๏ผš +ๆœฌไพ‹ไธญ๏ผŒๅฎขๆˆท็ซฏ็”จไธๅญ˜ๅœจ็š„ `ID` ่ฏทๆฑ‚ `item` ๆ—ถ๏ผŒ่งฆๅ‘็Šถๆ€็ ไธบ `404` ็š„ๅผ‚ๅธธ๏ผš -{* ../../docs_src/handling_errors/tutorial001.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} -### ๅ“ๅบ”็ป“ๆžœ +### ๅ“ๅบ”็ป“ๆžœ { #the-resulting-response } -่ฏทๆฑ‚ไธบ `http://example.com/items/foo`๏ผˆ`item_id` ไธบ `ใ€Œfooใ€`๏ผ‰ๆ—ถ๏ผŒๅฎขๆˆท็ซฏไผšๆŽฅๆ”ถๅˆฐ HTTP ็Šถๆ€็  - 200 ๅŠๅฆ‚ไธ‹ JSON ๅ“ๅบ”็ป“ๆžœ๏ผš +่ฏทๆฑ‚ไธบ `http://example.com/items/foo`๏ผˆ`item_id` ไธบ `"foo"`๏ผ‰ๆ—ถ๏ผŒๅฎขๆˆท็ซฏไผšๆŽฅๆ”ถๅˆฐ HTTP ็Šถๆ€็  200 ๅŠๅฆ‚ไธ‹ JSON ๅ“ๅบ”็ป“ๆžœ๏ผš ```JSON { "item": "The Foo Wrestlers" } - ``` -ไฝ†ๅฆ‚ๆžœๅฎขๆˆท็ซฏ่ฏทๆฑ‚ `http://example.com/items/bar`๏ผˆ`item_id` `ใ€Œbarใ€` ไธๅญ˜ๅœจๆ—ถ๏ผ‰๏ผŒๅˆ™ไผšๆŽฅๆ”ถๅˆฐ HTTP ็Šถๆ€็  - 404๏ผˆใ€Œๆœชๆ‰พๅˆฐใ€้”™่ฏฏ๏ผ‰ๅŠๅฆ‚ไธ‹ JSON ๅ“ๅบ”็ป“ๆžœ๏ผš +ไฝ†ๅฆ‚ๆžœๅฎขๆˆท็ซฏ่ฏทๆฑ‚ `http://example.com/items/bar`๏ผˆไธๅญ˜ๅœจ็š„ `item_id` `"bar"`๏ผ‰๏ผŒๅˆ™ไผšๆŽฅๆ”ถๅˆฐ HTTP ็Šถๆ€็  404๏ผˆโ€œๆœชๆ‰พๅˆฐโ€้”™่ฏฏ๏ผ‰ๅŠๅฆ‚ไธ‹ JSON ๅ“ๅบ”็ป“ๆžœ๏ผš ```JSON { "detail": "Item not found" } - ``` /// tip | ๆ็คบ @@ -71,68 +69,67 @@ /// -## ๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคด +## ๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคด { #add-custom-headers } -ๆœ‰ไบ›ๅœบๆ™ฏไธ‹่ฆไธบ HTTP ้”™่ฏฏๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคดใ€‚ไพ‹ๅฆ‚๏ผŒๅ‡บไบŽๆŸไบ›ๆ–น้ข็š„ๅฎ‰ๅ…จ้œ€่ฆใ€‚ +ๆœ‰ไบ›ๅœบๆ™ฏไธ‹่ฆไธบ HTTP ้”™่ฏฏๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคดใ€‚ไพ‹ๅฆ‚๏ผŒๅ‡บไบŽๆŸไบ›็ฑปๅž‹็š„ๅฎ‰ๅ…จ้œ€่ฆใ€‚ -ไธ€่ˆฌๆƒ…ๅ†ตไธ‹ๅฏ่ƒฝไธไผš้œ€่ฆๅœจไปฃ็ ไธญ็›ดๆŽฅไฝฟ็”จๅ“ๅบ”ๅคดใ€‚ +ไธ€่ˆฌๆƒ…ๅ†ตไธ‹ไฝ ๅฏ่ƒฝไธไผšๅœจไปฃ็ ไธญ็›ดๆŽฅไฝฟ็”จๅฎƒใ€‚ -ไฝ†ๅฏนไบŽๆŸไบ›้ซ˜็บงๅบ”็”จๅœบๆ™ฏ๏ผŒ่ฟ˜ๆ˜ฏ้œ€่ฆๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคด๏ผš +ไฝ†ๅœจๆŸไบ›้ซ˜็บงๅœบๆ™ฏไธญ้œ€่ฆๆ—ถ๏ผŒไฝ ๅฏไปฅๆทปๅŠ ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคด๏ผš -{* ../../docs_src/handling_errors/tutorial002.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} -## ๅฎ‰่ฃ…่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ +## ๅฎ‰่ฃ…่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ { #install-custom-exception-handlers } -ๆทปๅŠ ่‡ชๅฎšไน‰ๅค„็†ๅ™จ๏ผŒ่ฆไฝฟ็”จ [Starlette ็š„ๅผ‚ๅธธๅทฅๅ…ท](https://www.starlette.dev/exceptions/)ใ€‚ +ๅฏไปฅไฝฟ็”จไธŽ Starlette ็›ธๅŒ็š„ๅผ‚ๅธธๅค„็†ๅทฅๅ…ทๆทปๅŠ ่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จใ€‚ -ๅ‡่ฎพ่ฆ่งฆๅ‘็š„่‡ชๅฎšไน‰ๅผ‚ๅธธๅซไฝœ `UnicornException`ใ€‚ +ๅ‡่ฎพๆœ‰ไธ€ไธช่‡ชๅฎšไน‰ๅผ‚ๅธธ `UnicornException`๏ผˆไฝ ่‡ชๅทฑๆˆ–ไฝ ไฝฟ็”จ็š„ๅบ“ๅฏ่ƒฝไผš `raise` ๅฎƒ๏ผ‰ใ€‚ -ไธ”้œ€่ฆ FastAPI ๅฎž็Žฐๅ…จๅฑ€ๅค„็†่ฏฅๅผ‚ๅธธใ€‚ +ๅนถไธ”ไฝ ๅธŒๆœ›็”จ FastAPI ๅœจๅ…จๅฑ€ๅค„็†่ฏฅๅผ‚ๅธธใ€‚ -ๆญคๆ—ถ๏ผŒๅฏไปฅ็”จ `@app.exception_handler()` ๆทปๅŠ ่‡ชๅฎšไน‰ๅผ‚ๅธธๆŽงๅˆถๅ™จ๏ผš +ๆญคๆ—ถ๏ผŒๅฏไปฅ็”จ `@app.exception_handler()` ๆทปๅŠ ่‡ชๅฎšไน‰ๅผ‚ๅธธๅค„็†ๅ™จ๏ผš -{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} -่ฏทๆฑ‚ `/unicorns/yolo` ๆ—ถ๏ผŒ่ทฏๅพ„ๆ“ไฝœไผš่งฆๅ‘ `UnicornException`ใ€‚ +่ฟ™้‡Œ๏ผŒ่ฏทๆฑ‚ `/unicorns/yolo` ๆ—ถ๏ผŒ่ทฏๅพ„ๆ“ไฝœไผš่งฆๅ‘ `UnicornException`ใ€‚ ไฝ†่ฏฅๅผ‚ๅธธๅฐ†ไผš่ขซ `unicorn_exception_handler` ๅค„็†ใ€‚ -ๆŽฅๆ”ถๅˆฐ็š„้”™่ฏฏไฟกๆฏๆธ…ๆ™ฐๆ˜Žไบ†๏ผŒHTTP ็Šถๆ€็ ไธบ `418`๏ผŒJSON ๅ†…ๅฎนๅฆ‚ไธ‹๏ผš +ไฝ ไผšๆ”ถๅˆฐๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏ๏ผŒHTTP ็Šถๆ€็ ไธบ `418`๏ผŒJSON ๅ†…ๅฎนๅฆ‚ไธ‹๏ผš ```JSON {"message": "Oops! yolo did something. There goes a rainbow..."} - ``` /// note | ๆŠ€ๆœฏ็ป†่Š‚ -`from starlette.requests import Request` ๅ’Œ `from starlette.responses import JSONResponse` ไนŸๅฏไปฅ็”จไบŽๅฏผๅ…ฅ `Request` ๅ’Œ `JSONResponse`ใ€‚ +ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request` ๅ’Œ `from starlette.responses import JSONResponse`ใ€‚ -**FastAPI** ๆไพ›ไบ†ไธŽ `starlette.responses` ็›ธๅŒ็š„ `fastapi.responses` ไฝœไธบๅฟซๆทๆ–นๅผ๏ผŒไฝ†ๅคง้ƒจๅˆ†ๅ“ๅบ”ๆ“ไฝœ้ƒฝๅฏไปฅ็›ดๆŽฅไปŽ Starlette ๅฏผๅ…ฅใ€‚ๅŒ็†๏ผŒ`Request` ไนŸๆ˜ฏๅฆ‚ๆญคใ€‚ +**FastAPI** ๆไพ›ไบ†ไธŽ `starlette.responses` ็›ธๅŒ็š„ `fastapi.responses` ไฝœไธบไพฟๆทๆ–นๅผ๏ผŒไฝ†ๅคงๅคšๆ•ฐๅฏ็”จ็š„ๅ“ๅบ”้ƒฝ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚`Request` ไนŸๆ˜ฏๅฆ‚ๆญคใ€‚ /// -## ่ฆ†็›–้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จ +## ่ฆ†็›–้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จ { #override-the-default-exception-handlers } **FastAPI** ่‡ชๅธฆไบ†ไธ€ไบ›้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จใ€‚ -่งฆๅ‘ `HTTPException` ๆˆ–่ฏทๆฑ‚ๆ— ๆ•ˆๆ•ฐๆฎๆ—ถ๏ผŒ่ฟ™ไบ›ๅค„็†ๅ™จ่ฟ”ๅ›ž้ป˜่ฎค็š„ JSON ๅ“ๅบ”็ป“ๆžœใ€‚ +ๅฝ“ไฝ ่งฆๅ‘ `HTTPException`๏ผŒๆˆ–่€…่ฏทๆฑ‚ไธญๅŒ…ๅซๆ— ๆ•ˆๆ•ฐๆฎๆ—ถ๏ผŒ่ฟ™ไบ›ๅค„็†ๅ™จ่ดŸ่ดฃ่ฟ”ๅ›ž้ป˜่ฎค็š„ JSON ๅ“ๅบ”ใ€‚ -ไธ่ฟ‡๏ผŒไนŸๅฏไปฅไฝฟ็”จ่‡ชๅฎšไน‰ๅค„็†ๅ™จ่ฆ†็›–้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จใ€‚ +ไฝ ไนŸๅฏไปฅ็”จ่‡ชๅทฑ็š„ๅค„็†ๅ™จ่ฆ†็›–ๅฎƒไปฌใ€‚ -### ่ฆ†็›–่ฏทๆฑ‚้ชŒ่ฏๅผ‚ๅธธ +### ่ฆ†็›–่ฏทๆฑ‚้ชŒ่ฏๅผ‚ๅธธ { #override-request-validation-exceptions } ่ฏทๆฑ‚ไธญๅŒ…ๅซๆ— ๆ•ˆๆ•ฐๆฎๆ—ถ๏ผŒ**FastAPI** ๅ†…้ƒจไผš่งฆๅ‘ `RequestValidationError`ใ€‚ -่ฏฅๅผ‚ๅธธไนŸๅ†…็ฝฎไบ†้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จใ€‚ +ๅฎƒไนŸๅ†…็ฝฎไบ†่ฏฅๅผ‚ๅธธ็š„้ป˜่ฎคๅค„็†ๅ™จใ€‚ -่ฆ†็›–้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จๆ—ถ้œ€่ฆๅฏผๅ…ฅ `RequestValidationError`๏ผŒๅนถ็”จ `@app.excption_handler(RequestValidationError)` ่ฃ…้ฅฐๅผ‚ๅธธๅค„็†ๅ™จใ€‚ +่ฆ่ฆ†็›–ๅฎƒ๏ผŒๅฏผๅ…ฅ `RequestValidationError`๏ผŒๅนถ็”จ `@app.exception_handler(RequestValidationError)` ่ฃ…้ฅฐไฝ ็š„ๅผ‚ๅธธๅค„็†ๅ™จใ€‚ -่ฟ™ๆ ท๏ผŒๅผ‚ๅธธๅค„็†ๅ™จๅฐฑๅฏไปฅๆŽฅๆ”ถ `Request` ไธŽๅผ‚ๅธธใ€‚ +ๅผ‚ๅธธๅค„็†ๅ™จไผšๆŽฅๆ”ถ `Request` ๅ’Œ่ฏฅๅผ‚ๅธธใ€‚ -{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *} +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} -่ฎฟ้—ฎ `/items/foo`๏ผŒๅฏไปฅ็œ‹ๅˆฐ้ป˜่ฎค็š„ JSON ้”™่ฏฏไฟกๆฏ๏ผš +็Žฐๅœจ๏ผŒ่ฎฟ้—ฎ `/items/foo` ๆ—ถ๏ผŒ้ป˜่ฎค็š„ JSON ้”™่ฏฏไธบ๏ผš ```JSON { @@ -147,59 +144,46 @@ } ] } - ``` -่ขซๆ›ฟๆขไธบไบ†ไปฅไธ‹ๆ–‡ๆœฌๆ ผๅผ็š„้”™่ฏฏไฟกๆฏ๏ผš +ๅฐ†ๅพ—ๅˆฐๅฆ‚ไธ‹ๆ–‡ๆœฌๅ†…ๅฎน๏ผš ``` -1 validation error -path -> item_id - value is not a valid integer (type=type_error.integer) - +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer ``` -### `RequestValidationError` vs `ValidationError` - -/// warning | ่ญฆๅ‘Š - -ๅฆ‚ๆžœๆ‚จ่ง‰ๅพ—็Žฐๅœจ่ฟ˜็”จไธๅˆฐไปฅไธ‹ๆŠ€ๆœฏ็ป†่Š‚๏ผŒๅฏไปฅๅ…ˆ่ทณ่ฟ‡ไธ‹้ข็š„ๅ†…ๅฎนใ€‚ - -/// - -`RequestValidationError` ๆ˜ฏ Pydantic ็š„ `ValidationError` ็š„ๅญ็ฑปใ€‚ - -**FastAPI** ่ฐƒ็”จ็š„ๅฐฑๆ˜ฏ `RequestValidationError` ็ฑป๏ผŒๅ› ๆญค๏ผŒๅฆ‚ๆžœๅœจ `response_model` ไธญไฝฟ็”จ Pydantic ๆจกๅž‹๏ผŒไธ”ๆ•ฐๆฎๆœ‰้”™่ฏฏๆ—ถ๏ผŒๅœจๆ—ฅๅฟ—ไธญๅฐฑไผš็œ‹ๅˆฐ่ฟ™ไธช้”™่ฏฏใ€‚ +### ่ฆ†็›– `HTTPException` ้”™่ฏฏๅค„็†ๅ™จ { #override-the-httpexception-error-handler } -ไฝ†ๅฎขๆˆท็ซฏๆˆ–็”จๆˆท็œ‹ไธๅˆฐ่ฟ™ไธช้”™่ฏฏใ€‚ๅไน‹๏ผŒๅฎขๆˆท็ซฏๆŽฅๆ”ถๅˆฐ็š„ๆ˜ฏ HTTP ็Šถๆ€็ ไธบ `500` ็š„ใ€Œๅ†…้ƒจๆœๅŠกๅ™จ้”™่ฏฏใ€ใ€‚ +ๅŒ็†๏ผŒไนŸๅฏไปฅ่ฆ†็›– `HTTPException` ็š„ๅค„็†ๅ™จใ€‚ -่ฟ™ๆ˜ฏๅ› ไธบๅœจ*ๅ“ๅบ”*ๆˆ–ไปฃ็ ๏ผˆไธๆ˜ฏๅœจๅฎขๆˆท็ซฏ็š„่ฏทๆฑ‚้‡Œ๏ผ‰ไธญๅ‡บ็Žฐ็š„ Pydantic `ValidationError` ๆ˜ฏไปฃ็ ็š„ bugใ€‚ +ไพ‹ๅฆ‚๏ผŒๅชไธบ่ฟ™ไบ›้”™่ฏฏ่ฟ”ๅ›ž็บฏๆ–‡ๆœฌๅ“ๅบ”๏ผŒ่€Œไธๆ˜ฏ JSON๏ผš -ไฟฎๅค้”™่ฏฏๆ—ถ๏ผŒๅฎขๆˆท็ซฏๆˆ–็”จๆˆทไธ่ƒฝ่ฎฟ้—ฎ้”™่ฏฏ็š„ๅ†…้ƒจไฟกๆฏ๏ผŒๅฆๅˆ™ไผš้€ ๆˆๅฎ‰ๅ…จ้šๆ‚ฃใ€‚ +{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} -### ่ฆ†็›– `HTTPException` ้”™่ฏฏๅค„็†ๅ™จ +/// note | ๆŠ€ๆœฏ็ป†่Š‚ -ๅŒ็†๏ผŒไนŸๅฏไปฅ่ฆ†็›– `HTTPException` ๅค„็†ๅ™จใ€‚ +่ฟ˜ๅฏไปฅไฝฟ็”จ `from starlette.responses import PlainTextResponse`ใ€‚ -ไพ‹ๅฆ‚๏ผŒๅชไธบ้”™่ฏฏ่ฟ”ๅ›ž็บฏๆ–‡ๆœฌๅ“ๅบ”๏ผŒ่€Œไธๆ˜ฏ่ฟ”ๅ›ž JSON ๆ ผๅผ็š„ๅ†…ๅฎน๏ผš +**FastAPI** ๆไพ›ไบ†ไธŽ `starlette.responses` ็›ธๅŒ็š„ `fastapi.responses` ไฝœไธบไพฟๆทๆ–นๅผ๏ผŒไฝ†ๅคงๅคšๆ•ฐๅฏ็”จ็š„ๅ“ๅบ”้ƒฝ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ -{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *} +/// -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// warning | ่ญฆๅ‘Š -่ฟ˜ๅฏไปฅไฝฟ็”จ `from starlette.responses import PlainTextResponse`ใ€‚ +่ฏทๆณจๆ„๏ผŒ`RequestValidationError` ๅŒ…ๅซๅ‘็”Ÿ้ชŒ่ฏ้”™่ฏฏ็š„ๆ–‡ไปถๅๅ’Œ่กŒๅทไฟกๆฏ๏ผŒไฝ ๅฏไปฅๅœจ้œ€่ฆๆ—ถๅฐ†ๅ…ถ่ฎฐๅฝ•ๅˆฐๆ—ฅๅฟ—ไธญไปฅๆไพ›็›ธๅ…ณไฟกๆฏใ€‚ -**FastAPI** ๆไพ›ไบ†ไธŽ `starlette.responses` ็›ธๅŒ็š„ `fastapi.responses` ไฝœไธบๅฟซๆทๆ–นๅผ๏ผŒไฝ†ๅคง้ƒจๅˆ†ๅ“ๅบ”้ƒฝๅฏไปฅ็›ดๆŽฅไปŽ Starlette ๅฏผๅ…ฅใ€‚ +ไฝ†่ฟ™ไนŸๆ„ๅ‘ณ็€๏ผŒๅฆ‚ๆžœไฝ ๅชๆ˜ฏๅฐ†ๅ…ถ็›ดๆŽฅ่ฝฌๆขไธบๅญ—็ฌฆไธฒๅนถ่ฟ”ๅ›ž๏ผŒๅฏ่ƒฝไผšๆณ„้œฒไธ€ไบ›ๅ…ณไบŽ็ณป็ปŸ็š„็ป†่Š‚ไฟกๆฏใ€‚ๅ› ๆญค๏ผŒ่ฟ™้‡Œ็š„ไปฃ็ ไผšๆๅ–ๅนถๅˆ†ๅˆซๆ˜พ็คบๆฏไธช้”™่ฏฏใ€‚ /// -### ไฝฟ็”จ `RequestValidationError` ็š„่ฏทๆฑ‚ไฝ“ +### ไฝฟ็”จ `RequestValidationError` ็š„่ฏทๆฑ‚ไฝ“ { #use-the-requestvalidationerror-body } -`RequestValidationError` ๅŒ…ๅซๅ…ถๆŽฅๆ”ถๅˆฐ็š„ๆ— ๆ•ˆๆ•ฐๆฎ่ฏทๆฑ‚็š„ `body` ใ€‚ +`RequestValidationError` ๅŒ…ๅซๅ…ถๆŽฅๆ”ถๅˆฐ็š„ๅธฆๆœ‰ๆ— ๆ•ˆๆ•ฐๆฎ็š„่ฏทๆฑ‚ไฝ“ `body`ใ€‚ -ๅผ€ๅ‘ๆ—ถ๏ผŒๅฏไปฅ็”จ่ฟ™ไธช่ฏทๆฑ‚ไฝ“็”Ÿๆˆๆ—ฅๅฟ—ใ€่ฐƒ่ฏ•้”™่ฏฏ๏ผŒๅนถ่ฟ”ๅ›ž็ป™็”จๆˆทใ€‚ +ๅผ€ๅ‘ๆ—ถ๏ผŒไฝ ๅฏไปฅ็”จๅฎƒๆฅ่ฎฐๅฝ•่ฏทๆฑ‚ไฝ“ใ€่ฐƒ่ฏ•้”™่ฏฏ๏ผŒๆˆ–่ฟ”ๅ›ž็ป™็”จๆˆท็ญ‰ใ€‚ -{* ../../docs_src/handling_errors/tutorial005.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} ็Žฐๅœจ่ฏ•็€ๅ‘้€ไธ€ไธชๆ— ๆ•ˆ็š„ `item`๏ผŒไพ‹ๅฆ‚๏ผš @@ -208,10 +192,9 @@ path -> item_id "title": "towel", "size": "XL" } - ``` -ๆ”ถๅˆฐ็š„ๅ“ๅบ”ๅŒ…ๅซ `body` ไฟกๆฏ๏ผŒๅนถ่ฏดๆ˜Žๆ•ฐๆฎๆ˜ฏๆ— ๆ•ˆ็š„๏ผš +ๆ”ถๅˆฐ็š„ๅ“ๅบ”ไผšๅ‘Š่ฏ‰ไฝ ๆ•ฐๆฎๆ— ๆ•ˆ๏ผŒๅนถๅŒ…ๅซๆ”ถๅˆฐ็š„่ฏทๆฑ‚ไฝ“๏ผš ```JSON hl_lines="12-15" { @@ -230,40 +213,32 @@ path -> item_id "size": "XL" } } - ``` -### FastAPI `HTTPException` vs Starlette `HTTPException` +#### FastAPI ็š„ `HTTPException` vs Starlette ็š„ `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } **FastAPI** ไนŸๆไพ›ไบ†่‡ชๆœ‰็š„ `HTTPException`ใ€‚ -**FastAPI** ็š„ `HTTPException` ็ปงๆ‰ฟ่‡ช Starlette ็š„ `HTTPException` ้”™่ฏฏ็ฑปใ€‚ - -ๅฎƒไปฌไน‹้—ด็š„ๅ”ฏไธ€ๅŒบๅˆซๆ˜ฏ๏ผŒ**FastAPI** ็š„ `HTTPException` ๅฏไปฅๅœจๅ“ๅบ”ไธญๆทปๅŠ ๅ“ๅบ”ๅคดใ€‚ +**FastAPI** ็š„ `HTTPException` ้”™่ฏฏ็ฑป็ปงๆ‰ฟ่‡ช Starlette ็š„ `HTTPException` ้”™่ฏฏ็ฑปใ€‚ -OAuth 2.0 ็ญ‰ๅฎ‰ๅ…จๅทฅๅ…ท้œ€่ฆๅœจๅ†…้ƒจ่ฐƒ็”จ่ฟ™ไบ›ๅ“ๅบ”ๅคดใ€‚ +ๅฎƒไปฌไน‹้—ด็š„ๅ”ฏไธ€ๅŒบๅˆซๆ˜ฏ๏ผŒ**FastAPI** ็š„ `HTTPException` ๅœจ `detail` ๅญ—ๆฎตไธญๆŽฅๅ—ไปปๆ„ๅฏ่ฝฌๆขไธบ JSON ็š„ๆ•ฐๆฎ๏ผŒ่€Œ Starlette ็š„ `HTTPException` ๅชๆŽฅๅ—ๅญ—็ฌฆไธฒใ€‚ -ๅ› ๆญคไฝ ๅฏไปฅ็ปง็ปญๅƒๅนณๅธธไธ€ๆ ทๅœจไปฃ็ ไธญ่งฆๅ‘ **FastAPI** ็š„ `HTTPException` ใ€‚ +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ็ปง็ปญๅƒๅนณๅธธไธ€ๆ ทๅœจไปฃ็ ไธญ่งฆๅ‘ **FastAPI** ็š„ `HTTPException`ใ€‚ ไฝ†ๆณจๅ†Œๅผ‚ๅธธๅค„็†ๅ™จๆ—ถ๏ผŒๅบ”่ฏฅๆณจๅ†Œๅˆฐๆฅ่‡ช Starlette ็š„ `HTTPException`ใ€‚ -่ฟ™ๆ ทๅšๆ˜ฏไธบไบ†๏ผŒๅฝ“ Starlette ็š„ๅ†…้ƒจไปฃ็ ใ€ๆ‰ฉๅฑ•ๆˆ–ๆ’ไปถ่งฆๅ‘ Starlette `HTTPException` ๆ—ถ๏ผŒๅค„็†็จ‹ๅบ่ƒฝๅคŸๆ•่Žทใ€ๅนถๅค„็†ๆญคๅผ‚ๅธธใ€‚ +่ฟ™ๆ ทๅšๆ˜ฏไธบไบ†๏ผŒๅฝ“ Starlette ็š„ๅ†…้ƒจไปฃ็ ใ€ๆ‰ฉๅฑ•ๆˆ–ๆ’ไปถ่งฆๅ‘ Starlette `HTTPException` ๆ—ถ๏ผŒไฝ ็š„ๅค„็†ๅ™จ่ƒฝๅคŸๆ•่Žทๅนถๅค„็†ๅฎƒใ€‚ -ๆณจๆ„๏ผŒๆœฌไพ‹ไปฃ็ ไธญๅŒๆ—ถไฝฟ็”จไบ†่ฟ™ไธคไธช `HTTPException`๏ผŒๆญคๆ—ถ๏ผŒ่ฆๆŠŠ Starlette ็š„ `HTTPException` ๅ‘ฝๅไธบ `StarletteHTTPException`๏ผš +ๆœฌไพ‹ไธญ๏ผŒไธบไบ†ๅœจๅŒไธ€ไปฝไปฃ็ ไธญๅŒๆ—ถไฝฟ็”จไธคไธช `HTTPException`๏ผŒๅฐ† Starlette ็š„ๅผ‚ๅธธ้‡ๅ‘ฝๅไธบ `StarletteHTTPException`๏ผš ```Python from starlette.exceptions import HTTPException as StarletteHTTPException - ``` -### ๅค็”จ **FastAPI** ๅผ‚ๅธธๅค„็†ๅ™จ - -FastAPI ๆ”ฏๆŒๅ…ˆๅฏนๅผ‚ๅธธ่ฟ›่กŒๆŸไบ›ๅค„็†๏ผŒ็„ถๅŽๅ†ไฝฟ็”จ **FastAPI** ไธญๅค„็†่ฏฅๅผ‚ๅธธ็š„้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จใ€‚ - -ไปŽ `fastapi.exception_handlers` ไธญๅฏผๅ…ฅ่ฆๅค็”จ็š„้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จ๏ผš +### ๅค็”จ **FastAPI** ็š„ๅผ‚ๅธธๅค„็†ๅ™จ { #reuse-fastapis-exception-handlers } -{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} +ๅฆ‚ๆžœไฝ ๆƒณๅœจ่‡ชๅฎšไน‰ๅค„็†ๅŽไปๅค็”จ **FastAPI** ็š„้ป˜่ฎคๅผ‚ๅธธๅค„็†ๅ™จ๏ผŒๅฏไปฅไปŽ `fastapi.exception_handlers` ๅฏผๅ…ฅๅนถๅค็”จ่ฟ™ไบ›้ป˜่ฎคๅค„็†ๅ™จ๏ผš -่™ฝ็„ถ๏ผŒๆœฌไพ‹ๅชๆ˜ฏ่พ“ๅ‡บไบ†ๅคธๅคงๅ…ถ่ฏ็š„้”™่ฏฏไฟกๆฏใ€‚ +{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} -ไฝ†ไนŸ่ถณไปฅ่ฏดๆ˜Ž๏ผŒๅฏไปฅๅœจๅค„็†ๅผ‚ๅธธไน‹ๅŽๅ†ๅค็”จ้ป˜่ฎค็š„ๅผ‚ๅธธๅค„็†ๅ™จใ€‚ +่™ฝ็„ถๆœฌไพ‹ๅชๆ˜ฏ็”จ้žๅธธๅคธๅผ ็š„ไฟกๆฏๆ‰“ๅฐไบ†้”™่ฏฏ๏ผŒไฝ†่ถณไปฅ่ฏดๆ˜Ž๏ผšไฝ ๅฏไปฅๅ…ˆๅค„็†ๅผ‚ๅธธ๏ผŒ็„ถๅŽๅ†ๅค็”จ้ป˜่ฎค็š„ๅผ‚ๅธธๅค„็†ๅ™จใ€‚ diff --git a/docs/zh/docs/tutorial/header-param-models.md b/docs/zh/docs/tutorial/header-param-models.md index 13366aebc9..e7d5483173 100644 --- a/docs/zh/docs/tutorial/header-param-models.md +++ b/docs/zh/docs/tutorial/header-param-models.md @@ -1,16 +1,16 @@ -# Header ๅ‚ๆ•ฐๆจกๅž‹ +# Header ๅ‚ๆ•ฐๆจกๅž‹ { #header-parameter-models } ๅฆ‚ๆžœๆ‚จๆœ‰ไธ€็ป„็›ธๅ…ณ็š„ **header ๅ‚ๆ•ฐ**๏ผŒๆ‚จๅฏไปฅๅˆ›ๅปบไธ€ไธช **Pydantic ๆจกๅž‹**ๆฅๅฃฐๆ˜Žๅฎƒไปฌใ€‚ ่ฟ™ๅฐ†ๅ…่ฎธๆ‚จๅœจ**ๅคšไธชๅœฐๆ–น**่ƒฝๅคŸ**้‡็”จๆจกๅž‹**๏ผŒๅนถไธ”ๅฏไปฅไธ€ๆฌกๆ€งๅฃฐๆ˜Žๆ‰€ๆœ‰ๅ‚ๆ•ฐ็š„้ชŒ่ฏๅ’Œๅ…ƒๆ•ฐๆฎใ€‚๐Ÿ˜Ž -/// note +/// note | ๆณจๆ„ ่‡ช FastAPI ็‰ˆๆœฌ `0.115.0` ่ตทๆ”ฏๆŒๆญคๅŠŸ่ƒฝใ€‚๐Ÿค“ /// -## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ Header ๅ‚ๆ•ฐ +## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ Header ๅ‚ๆ•ฐ { #header-parameters-with-a-pydantic-model } ๅœจ **Pydantic ๆจกๅž‹**ไธญๅฃฐๆ˜Žๆ‰€้œ€็š„ **header ๅ‚ๆ•ฐ**๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Header` : @@ -18,7 +18,7 @@ **FastAPI** ๅฐ†ไปŽ่ฏทๆฑ‚ไธญๆŽฅๆ”ถๅˆฐ็š„ **headers** ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๆไพ›ๆ‚จๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ -## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } ๆ‚จๅฏไปฅๅœจๆ–‡ๆกฃ UI ็š„ `/docs` ไธญๆŸฅ็œ‹ๆ‰€้œ€็š„ headers๏ผš @@ -26,7 +26,7 @@ -## ็ฆๆญข้ขๅค–็š„ Headers +## ็ฆๆญข้ขๅค–็š„ Headers { #forbid-extra-headers } ๅœจๆŸไบ›็‰นๆฎŠไฝฟ็”จๆƒ…ๅ†ตไธ‹๏ผˆๅฏ่ƒฝๅนถไธๅธธ่ง๏ผ‰๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›**้™ๅˆถ**ๆ‚จๆƒณ่ฆๆŽฅๆ”ถ็š„ headersใ€‚ @@ -51,6 +51,22 @@ } ``` -## ๆ€ป็ป“ +## ็ฆ็”จไธ‹ๅˆ’็บฟ่ฝฌๆข { #disable-convert-underscores } + +ไธŽๅธธ่ง„็š„ header ๅ‚ๆ•ฐ็›ธๅŒ๏ผŒๅฝ“ๅ‚ๆ•ฐๅไธญๅŒ…ๅซไธ‹ๅˆ’็บฟๆ—ถ๏ผŒไผš**่‡ชๅŠจ่ฝฌๆขไธบ่ฟžๅญ—็ฌฆ**ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ็š„ไปฃ็ ไธญๆœ‰ไธ€ไธชๅไธบ `save_data` ็š„ header ๅ‚ๆ•ฐ๏ผŒ้‚ฃไนˆ้ข„ๆœŸ็š„ HTTP ๅคดๅฐ†ๆ˜ฏ `save-data`๏ผŒๅนถไธ”ๅœจๆ–‡ๆกฃไธญไนŸไผšไปฅ่ฟ™็งๅฝขๅผๆ˜พ็คบใ€‚ + +ๅฆ‚ๆžœ็”ฑไบŽๆŸไบ›ๅŽŸๅ› ไฝ ้œ€่ฆ็ฆ็”จ่ฟ™็ง่‡ชๅŠจ่ฝฌๆข๏ผŒไฝ ไนŸๅฏไปฅๅœจ็”จไบŽ header ๅ‚ๆ•ฐ็š„ Pydantic ๆจกๅž‹ไธญ่ฟ›่กŒ่ฎพ็ฝฎใ€‚ + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | ่ญฆๅ‘Š + +ๅœจๅฐ† `convert_underscores` ่ฎพไธบ `False` ไน‹ๅ‰๏ผŒ่ฏทๆณจๆ„ๆŸไบ› HTTP ไปฃ็†ๅ’ŒๆœๅŠกๅ™จไธๅ…่ฎธไฝฟ็”จๅธฆไธ‹ๅˆ’็บฟ็š„ headersใ€‚ + +/// + +## ๆ€ป็ป“ { #summary } ๆ‚จๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญๅฃฐๆ˜Ž **headers**ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/tutorial/header-params.md b/docs/zh/docs/tutorial/header-params.md index 19bb455cf4..ccb88ae7fa 100644 --- a/docs/zh/docs/tutorial/header-params.md +++ b/docs/zh/docs/tutorial/header-params.md @@ -1,14 +1,14 @@ -# Header ๅ‚ๆ•ฐ +# Header ๅ‚ๆ•ฐ { #header-parameters } ๅฎšไน‰ `Header` ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽๅฎšไน‰ `Query`ใ€`Path`ใ€`Cookie` ๅ‚ๆ•ฐ็›ธๅŒใ€‚ -## ๅฏผๅ…ฅ `Header` +## ๅฏผๅ…ฅ `Header` { #import-header } ้ฆ–ๅ…ˆ๏ผŒๅฏผๅ…ฅ `Header`๏ผš {* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} -## ๅฃฐๆ˜Ž `Header` ๅ‚ๆ•ฐ +## ๅฃฐๆ˜Ž `Header` ๅ‚ๆ•ฐ { #declare-header-parameters } ็„ถๅŽ๏ผŒไฝฟ็”จๅ’Œ `Path`ใ€`Query`ใ€`Cookie` ไธ€ๆ ท็š„็ป“ๆž„ๅฎšไน‰ header ๅ‚ๆ•ฐใ€‚ @@ -24,13 +24,13 @@ /// -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ ๅฟ…้กปไฝฟ็”จ `Header` ๅฃฐๆ˜Ž header ๅ‚ๆ•ฐ๏ผŒๅฆๅˆ™่ฏฅๅ‚ๆ•ฐไผš่ขซ่งฃ้‡ŠไธบๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ /// -## ่‡ชๅŠจ่ฝฌๆข +## ่‡ชๅŠจ่ฝฌๆข { #automatic-conversion } `Header` ๆฏ” `Path`ใ€`Query` ๅ’Œ `Cookie` ๆไพ›ไบ†ๆ›ดๅคšๅŠŸ่ƒฝใ€‚ @@ -54,7 +54,7 @@ /// -## ้‡ๅค็š„่ฏทๆฑ‚ๅคด +## ้‡ๅค็š„่ฏทๆฑ‚ๅคด { #duplicate-headers } ๆœ‰ๆ—ถ๏ผŒๅฏ่ƒฝ้œ€่ฆๆŽฅๆ”ถ้‡ๅค็š„่ฏทๆฑ‚ๅคดใ€‚ๅณๅŒไธ€ไธช่ฏทๆฑ‚ๅคดๆœ‰ๅคšไธชๅ€ผใ€‚ @@ -84,7 +84,7 @@ X-Token: bar } ``` -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } ไฝฟ็”จ `Header` ๅฃฐๆ˜Ž่ฏทๆฑ‚ๅคด็š„ๆ–นๅผไธŽ `Query`ใ€`Path` ใ€`Cookie` ็›ธๅŒใ€‚ diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index 3ca927337f..7934583023 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -1,12 +1,12 @@ -# ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ— +# ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ— { #tutorial-user-guide } ๆœฌๆ•™็จ‹ๅฐ†ไธ€ๆญฅๆญฅๅ‘ๆ‚จๅฑ•็คบๅฆ‚ไฝ•ไฝฟ็”จ **FastAPI** ็š„็ปๅคง้ƒจๅˆ†็‰นๆ€งใ€‚ -ๅ„ไธช็ซ ่Š‚็š„ๅ†…ๅฎนๅพชๅบๆธ่ฟ›๏ผŒไฝ†ๆ˜ฏๅˆๅ›ด็ป•็€ๅ•็‹ฌ็š„ไธป้ข˜๏ผŒๆ‰€ไปฅๆ‚จๅฏไปฅ็›ดๆŽฅ่ทณ่ฝฌๅˆฐๆŸไธช็ซ ่Š‚ไปฅ่งฃๅ†ณๆ‚จ็š„็‰นๅฎš้œ€ๆฑ‚ใ€‚ +ๅ„ไธช็ซ ่Š‚็š„ๅ†…ๅฎนๅพชๅบๆธ่ฟ›๏ผŒไฝ†ๆ˜ฏๅˆๅ›ด็ป•็€ๅ•็‹ฌ็š„ไธป้ข˜๏ผŒๆ‰€ไปฅๆ‚จๅฏไปฅ็›ดๆŽฅ่ทณ่ฝฌๅˆฐๆŸไธช็ซ ่Š‚ไปฅ่งฃๅ†ณๆ‚จ็š„็‰นๅฎš API ้œ€ๆฑ‚ใ€‚ ๆœฌๆ•™็จ‹ๅŒๆ ทๅฏไปฅไฝœไธบๅฐ†ๆฅ็š„ๅ‚่€ƒๆ‰‹ๅ†Œ๏ผŒๆ‰€ไปฅๆ‚จๅฏไปฅ้šๆ—ถๅ›žๅˆฐๆœฌๆ•™็จ‹ๅนถๆŸฅ้˜…ๆ‚จ้œ€่ฆ็š„ๅ†…ๅฎนใ€‚ -## ่ฟ่กŒไปฃ็  +## ่ฟ่กŒไปฃ็  { #run-the-code } ๆ‰€ๆœ‰ไปฃ็ ็‰‡ๆฎต้ƒฝๅฏไปฅๅคๅˆถๅŽ็›ดๆŽฅไฝฟ็”จ๏ผˆๅฎƒไปฌๅฎž้™…ไธŠๆ˜ฏ็ป่ฟ‡ๆต‹่ฏ•็š„ Python ๆ–‡ไปถ๏ผ‰ใ€‚ @@ -58,7 +58,7 @@ $ fastapi dev -/// note +/// note | ๆณจๆ„ -ๅฝ“ๆ‚จไฝฟ็”จ `pip install "fastapi[standard]"` ่ฟ›่กŒๅฎ‰่ฃ…ๆ—ถ๏ผŒๅฎƒไผš้™„ๅธฆไธ€ไบ›้ป˜่ฎค็š„ๅฏ้€‰ๆ ‡ๅ‡†ไพ่ต–้กนใ€‚ +ๅฝ“ๆ‚จไฝฟ็”จ `pip install "fastapi[standard]"` ๅฎ‰่ฃ…ๆ—ถ๏ผŒๅฎƒไผš้™„ๅธฆไธ€ไบ›้ป˜่ฎค็š„ๅฏ้€‰ๆ ‡ๅ‡†ไพ่ต–้กน๏ผŒๅ…ถไธญๅŒ…ๆ‹ฌ `fastapi-cloud-cli`๏ผŒๅฎƒๅฏไปฅ่ฎฉๆ‚จ้ƒจ็ฝฒๅˆฐ FastAPI Cloudใ€‚ ๅฆ‚ๆžœๆ‚จไธๆƒณๅฎ‰่ฃ…่ฟ™ไบ›ๅฏ้€‰ไพ่ต–๏ผŒๅฏไปฅ้€‰ๆ‹ฉๅฎ‰่ฃ… `pip install fastapi`ใ€‚ +ๅฆ‚ๆžœๆ‚จๆƒณๅฎ‰่ฃ…ๆ ‡ๅ‡†ไพ่ต–ไฝ†ไธๅŒ…ๅซ `fastapi-cloud-cli`๏ผŒๅฏไปฅไฝฟ็”จ `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ๅฎ‰่ฃ…ใ€‚ + /// -## ่ฟ›้˜ถ็”จๆˆทๆŒ‡ๅ— +## ่ฟ›้˜ถ็”จๆˆทๆŒ‡ๅ— { #advanced-user-guide } ๅœจๆœฌ**ๆ•™็จ‹-็”จๆˆทๆŒ‡ๅ—**ไน‹ๅŽ๏ผŒๆ‚จๅฏไปฅ้˜…่ฏป**่ฟ›้˜ถ็”จๆˆทๆŒ‡ๅ—**ใ€‚ diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md index d29a1e6d05..6ec7e9add1 100644 --- a/docs/zh/docs/tutorial/metadata.md +++ b/docs/zh/docs/tutorial/metadata.md @@ -1,28 +1,28 @@ -# ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL +# ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL { #metadata-and-docs-urls } ไฝ ๅฏไปฅๅœจ FastAPI ๅบ”็”จ็จ‹ๅบไธญ่‡ชๅฎšไน‰ๅคšไธชๅ…ƒๆ•ฐๆฎ้…็ฝฎใ€‚ -## API ๅ…ƒๆ•ฐๆฎ +## API ๅ…ƒๆ•ฐๆฎ { #metadata-for-api } ไฝ ๅฏไปฅๅœจ่ฎพ็ฝฎ OpenAPI ่ง„่Œƒๅ’Œ่‡ชๅŠจ API ๆ–‡ๆกฃ UI ไธญไฝฟ็”จ็š„ไปฅไธ‹ๅญ—ๆฎต๏ผš | ๅ‚ๆ•ฐ | ็ฑปๅž‹ | ๆ่ฟฐ | |------------|------|-------------| | `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` ใ€‚ | +| `summary` | `str` | API ็š„็ฎ€็Ÿญๆ‘˜่ฆใ€‚ ่‡ช OpenAPI 3.1.0ใ€FastAPI 0.99.0 ่ตทๅฏ็”จใ€‚ | +| `description` | `str` | API ็š„็ฎ€็Ÿญๆ่ฟฐใ€‚ๅฏไปฅไฝฟ็”จ Markdownใ€‚ | +| `version` | `string` | API ็š„็‰ˆๆœฌใ€‚่ฟ™ๆ˜ฏๆ‚จ่‡ชๅทฑ็š„ๅบ”็”จ็จ‹ๅบ็š„็‰ˆๆœฌ๏ผŒ่€Œไธๆ˜ฏ OpenAPI ็š„็‰ˆๆœฌใ€‚ไพ‹ๅฆ‚ `2.5.0`ใ€‚ | | `terms_of_service` | `str` | API ๆœๅŠกๆกๆฌพ็š„ URLใ€‚ๅฆ‚ๆžœๆไพ›๏ผŒๅˆ™ๅฟ…้กปๆ˜ฏ URLใ€‚ | -| `contact` | `dict` | ๅ…ฌๅผ€็š„ API ็š„่”็ณปไฟกๆฏใ€‚ๅฎƒๅฏไปฅๅŒ…ๅซๅคšไธชๅญ—ๆฎตใ€‚
contact ๅญ—ๆฎต
ๅ‚ๆ•ฐTypeๆ่ฟฐ
namestr่”็ณปไบบ/็ป„็ป‡็š„่ฏ†ๅˆซๅ็งฐใ€‚
urlstrๆŒ‡ๅ‘่”็ณปไฟกๆฏ็š„ URLใ€‚ๅฟ…้กป้‡‡็”จ URL ๆ ผๅผใ€‚
emailstr่”็ณปไบบ/็ป„็ป‡็š„็”ตๅญ้‚ฎไปถๅœฐๅ€ใ€‚ๅฟ…้กป้‡‡็”จ็”ตๅญ้‚ฎไปถๅœฐๅ€็š„ๆ ผๅผใ€‚
| -| `license_info` | `dict` | ๅ…ฌๅผ€็š„ API ็š„่ฎธๅฏ่ฏไฟกๆฏใ€‚ๅฎƒๅฏไปฅๅŒ…ๅซๅคšไธชๅญ—ๆฎตใ€‚
license_info ๅญ—ๆฎต
ๅ‚ๆ•ฐ็ฑปๅž‹ๆ่ฟฐ
namestrๅฟ…้กป็š„ (ๅฆ‚ๆžœ่ฎพ็ฝฎไบ†license_info). ็”จไบŽ API ็š„่ฎธๅฏ่ฏๅ็งฐใ€‚
identifierstrไธ€ไธชAPI็š„SPDX่ฎธๅฏ่ฏ่กจ่พพใ€‚ The identifier field is mutually exclusive of the url field. ่‡ช OpenAPI 3.1.0ใ€FastAPI 0.99.0 ่ตทๅฏ็”จใ€‚
urlstr็”จไบŽ API ็š„่ฎธๅฏ่ฏ็š„ URLใ€‚ๅฟ…้กป้‡‡็”จ URL ๆ ผๅผใ€‚
| +| `contact` | `dict` | ๅ…ฌๅผ€็š„ API ็š„่”็ณปไฟกๆฏใ€‚ๅฎƒๅฏไปฅๅŒ…ๅซๅคšไธชๅญ—ๆฎตใ€‚
contact ๅญ—ๆฎต
ๅ‚ๆ•ฐ็ฑปๅž‹ๆ่ฟฐ
namestr่”็ณปไบบ/็ป„็ป‡็š„่ฏ†ๅˆซๅ็งฐใ€‚
urlstrๆŒ‡ๅ‘่”็ณปไฟกๆฏ็š„ URLใ€‚ๅฟ…้กป้‡‡็”จ URL ๆ ผๅผใ€‚
emailstr่”็ณปไบบ/็ป„็ป‡็š„็”ตๅญ้‚ฎไปถๅœฐๅ€ใ€‚ๅฟ…้กป้‡‡็”จ็”ตๅญ้‚ฎไปถๅœฐๅ€็š„ๆ ผๅผใ€‚
| +| `license_info` | `dict` | ๅ…ฌๅผ€็š„ API ็š„่ฎธๅฏ่ฏไฟกๆฏใ€‚ๅฎƒๅฏไปฅๅŒ…ๅซๅคšไธชๅญ—ๆฎตใ€‚
license_info ๅญ—ๆฎต
ๅ‚ๆ•ฐ็ฑปๅž‹ๆ่ฟฐ
namestrๅฟ…้กป๏ผˆๅฆ‚ๆžœ่ฎพ็ฝฎไบ† license_info๏ผ‰ใ€‚็”จไบŽ API ็š„่ฎธๅฏ่ฏๅ็งฐใ€‚
identifierstrAPI ็š„ SPDX ่ฎธๅฏ่ฏ่กจ่พพๅผใ€‚ๅญ—ๆฎต identifier ไธŽๅญ—ๆฎต url ไบ’ๆ–ฅใ€‚่‡ช OpenAPI 3.1.0ใ€FastAPI 0.99.0 ่ตทๅฏ็”จใ€‚
urlstr็”จไบŽ API ็š„่ฎธๅฏ่ฏ็š„ URLใ€‚ๅฟ…้กป้‡‡็”จ URL ๆ ผๅผใ€‚
| ไฝ ๅฏไปฅๆŒ‰ๅฆ‚ไธ‹ๆ–นๅผ่ฎพ็ฝฎๅฎƒไปฌ๏ผš -{* ../../docs_src/metadata/tutorial001.py hl[4:6] *} +{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} -/// tip +/// tip | ๆ็คบ -ๆ‚จๅฏไปฅๅœจ `description` ๅญ—ๆฎตไธญ็ผ–ๅ†™ Markdown๏ผŒๅฎƒๅฐ†ๅœจ่พ“ๅ‡บไธญๅ‘ˆ็Žฐใ€‚ +ไฝ ๅฏไปฅๅœจ `description` ๅญ—ๆฎตไธญ็ผ–ๅ†™ Markdown๏ผŒๅฎƒไผšๅœจ่พ“ๅ‡บไธญๆธฒๆŸ“ใ€‚ /// @@ -30,15 +30,35 @@ -## ๆ ‡็ญพๅ…ƒๆ•ฐๆฎ +## ่ฎธๅฏ่ฏๆ ‡่ฏ†็ฌฆ { #license-identifier } + +่‡ช OpenAPI 3.1.0 ๅ’Œ FastAPI 0.99.0 ่ตท๏ผŒไฝ ่ฟ˜ๅฏไปฅๅœจ `license_info` ไธญไฝฟ็”จ `identifier` ่€Œไธๆ˜ฏ `url`ใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} + +## ๆ ‡็ญพๅ…ƒๆ•ฐๆฎ { #metadata-for-tags } + +ไฝ ไนŸๅฏไปฅ้€š่ฟ‡ๅ‚ๆ•ฐ `openapi_tags` ไธบ็”จไบŽๅˆ†็ป„่ทฏๅพ„ๆ“ไฝœ็š„ไธๅŒๆ ‡็ญพๆทปๅŠ ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎใ€‚ + +ๅฎƒๆŽฅๆ”ถไธ€ไธชๅˆ—่กจ๏ผŒๅˆ—่กจไธญๆฏไธชๆ ‡็ญพๅฏนๅบ”ไธ€ไธชๅญ—ๅ…ธใ€‚ + +ๆฏไธชๅญ—ๅ…ธๅฏไปฅๅŒ…ๅซ๏ผš + +- `name`๏ผˆๅฟ…ๅกซ๏ผ‰๏ผšไธ€ไธช `str`๏ผŒไธŽๅœจไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅ’Œ `APIRouter` ็š„ `tags` ๅ‚ๆ•ฐไธญไฝฟ็”จ็š„ๆ ‡็ญพๅ็›ธๅŒใ€‚ +- `description`๏ผšไธ€ไธช `str`๏ผŒ่ฏฅๆ ‡็ญพ็š„็ฎ€็Ÿญๆ่ฟฐใ€‚ๅฏไปฅไฝฟ็”จ Markdown๏ผŒๅนถไผšๆ˜พ็คบๅœจๆ–‡ๆกฃ UI ไธญใ€‚ +- `externalDocs`๏ผšไธ€ไธช `dict`๏ผŒๆ่ฟฐๅค–้ƒจๆ–‡ๆกฃ๏ผŒๅŒ…ๅซ๏ผš + - `description`๏ผšไธ€ไธช `str`๏ผŒ่ฏฅๅค–้ƒจๆ–‡ๆกฃ็š„็ฎ€็Ÿญๆ่ฟฐใ€‚ + - `url`๏ผˆๅฟ…ๅกซ๏ผ‰๏ผšไธ€ไธช `str`๏ผŒ่ฏฅๅค–้ƒจๆ–‡ๆกฃ็š„ URLใ€‚ -### ๅˆ›ๅปบๆ ‡็ญพๅ…ƒๆ•ฐๆฎ +### ๅˆ›ๅปบๆ ‡็ญพๅ…ƒๆ•ฐๆฎ { #create-metadata-for-tags } ่ฎฉๆˆ‘ไปฌๅœจๅธฆๆœ‰ๆ ‡็ญพ็š„็คบไพ‹ไธญไธบ `users` ๅ’Œ `items` ่ฏ•ไธ€ไธ‹ใ€‚ ๅˆ›ๅปบๆ ‡็ญพๅ…ƒๆ•ฐๆฎๅนถๆŠŠๅฎƒไผ ้€’็ป™ `openapi_tags` ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} ๆณจๆ„ไฝ ๅฏไปฅๅœจๆ่ฟฐๅ†…ไฝฟ็”จ Markdown๏ผŒไพ‹ๅฆ‚ใ€Œloginใ€ไผšๆ˜พ็คบไธบ็ฒ—ไฝ“๏ผˆ**login**๏ผ‰ไปฅๅŠใ€Œfancyใ€ไผšๆ˜พ็คบไธบๆ–œไฝ“๏ผˆ_fancy_๏ผ‰ใ€‚ @@ -48,11 +68,11 @@ /// -### ไฝฟ็”จไฝ ็š„ๆ ‡็ญพ +### ไฝฟ็”จไฝ ็š„ๆ ‡็ญพ { #use-your-tags } ๅฐ† `tags` ๅ‚ๆ•ฐๅ’Œ*่ทฏๅพ„ๆ“ไฝœ*๏ผˆไปฅๅŠ `APIRouter`๏ผ‰ไธ€่ตทไฝฟ็”จ๏ผŒๅฐ†ๅ…ถๅˆ†้…็ป™ไธๅŒ็š„ๆ ‡็ญพ๏ผš -{* ../../docs_src/metadata/tutorial004.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} /// info | ไฟกๆฏ @@ -60,19 +80,19 @@ /// -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } ๅฆ‚ๆžœไฝ ็ŽฐๅœจๆŸฅ็œ‹ๆ–‡ๆกฃ๏ผŒๅฎƒไปฌไผšๆ˜พ็คบๆ‰€ๆœ‰้™„ๅŠ ็š„ๅ…ƒๆ•ฐๆฎ๏ผš -### ๆ ‡็ญพ้กบๅบ +### ๆ ‡็ญพ้กบๅบ { #order-of-tags } ๆฏไธชๆ ‡็ญพๅ…ƒๆ•ฐๆฎๅญ—ๅ…ธ็š„้กบๅบไนŸๅฎšไน‰ไบ†ๅœจๆ–‡ๆกฃ็”จๆˆท็•Œ้ขๆ˜พ็คบ็š„้กบๅบใ€‚ ไพ‹ๅฆ‚ๆŒ‰็…งๅญ—ๆฏ้กบๅบ๏ผŒๅณไฝฟ `users` ๆŽ’ๅœจ `items` ไน‹ๅŽ๏ผŒๅฎƒไนŸไผšๆ˜พ็คบๅœจๅ‰้ข๏ผŒๅ› ไธบๆˆ‘ไปฌๅฐ†ๅฎƒ็š„ๅ…ƒๆ•ฐๆฎๆทปๅŠ ไธบๅˆ—่กจๅ†…็š„็ฌฌไธ€ไธชๅญ—ๅ…ธใ€‚ -## OpenAPI URL +## OpenAPI URL { #openapi-url } ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒOpenAPI ๆจกๅผๆœๅŠกไบŽ `/openapi.json`ใ€‚ @@ -80,21 +100,21 @@ ไพ‹ๅฆ‚๏ผŒๅฐ†ๅ…ถ่ฎพ็ฝฎไธบๆœๅŠกไบŽ `/api/v1/openapi.json`๏ผš -{* ../../docs_src/metadata/tutorial002.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} ๅฆ‚ๆžœไฝ ๆƒณๅฎŒๅ…จ็ฆ็”จ OpenAPI ๆจกๅผ๏ผŒๅฏไปฅๅฐ†ๅ…ถ่ฎพ็ฝฎไธบ `openapi_url=None`๏ผŒ่ฟ™ๆ ทไนŸไผš็ฆ็”จไฝฟ็”จๅฎƒ็š„ๆ–‡ๆกฃ็”จๆˆท็•Œ้ขใ€‚ -## ๆ–‡ๆกฃ URLs +## ๆ–‡ๆกฃ URLs { #docs-urls } ไฝ ๅฏไปฅ้…็ฝฎไธคไธชๆ–‡ๆกฃ็”จๆˆท็•Œ้ข๏ผŒๅŒ…ๆ‹ฌ๏ผš -* **Swagger UI**๏ผšๆœๅŠกไบŽ `/docs`ใ€‚ - * ๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `docs_url` ่ฎพ็ฝฎๅฎƒ็š„ URLใ€‚ - * ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `docs_url=None` ็ฆ็”จๅฎƒใ€‚ -* ReDoc๏ผšๆœๅŠกไบŽ `/redoc`ใ€‚ - * ๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `redoc_url` ่ฎพ็ฝฎๅฎƒ็š„ URLใ€‚ - * ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `redoc_url=None` ็ฆ็”จๅฎƒใ€‚ +- **Swagger UI**๏ผšๆœๅŠกไบŽ `/docs`ใ€‚ + - ๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `docs_url` ่ฎพ็ฝฎๅฎƒ็š„ URLใ€‚ + - ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `docs_url=None` ็ฆ็”จๅฎƒใ€‚ +- **ReDoc**๏ผšๆœๅŠกไบŽ `/redoc`ใ€‚ + - ๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `redoc_url` ่ฎพ็ฝฎๅฎƒ็š„ URLใ€‚ + - ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `redoc_url=None` ็ฆ็”จๅฎƒใ€‚ ไพ‹ๅฆ‚๏ผŒ่ฎพ็ฝฎ Swagger UI ๆœๅŠกไบŽ `/documentation` ๅนถ็ฆ็”จ ReDoc๏ผš -{* ../../docs_src/metadata/tutorial003.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} diff --git a/docs/zh/docs/tutorial/middleware.md b/docs/zh/docs/tutorial/middleware.md index 5608c4ee15..a3f833d78c 100644 --- a/docs/zh/docs/tutorial/middleware.md +++ b/docs/zh/docs/tutorial/middleware.md @@ -1,66 +1,95 @@ -# ไธญ้—ดไปถ +# ไธญ้—ดไปถ { #middleware } -ไฝ ๅฏไปฅๅ‘ **FastAPI** ๅบ”็”จๆทปๅŠ ไธญ้—ดไปถ. +ไฝ ๅฏไปฅๅ‘ **FastAPI** ๅบ”็”จๆทปๅŠ ไธญ้—ดไปถใ€‚ -"ไธญ้—ดไปถ"ๆ˜ฏไธ€ไธชๅ‡ฝๆ•ฐ,ๅฎƒๅœจๆฏไธช**่ฏทๆฑ‚**่ขซ็‰นๅฎš็š„*่ทฏๅพ„ๆ“ไฝœ*ๅค„็†ไน‹ๅ‰,ไปฅๅŠๅœจๆฏไธช**ๅ“ๅบ”**่ฟ”ๅ›žไน‹ๅ‰ๅทฅไฝœ. +โ€œไธญ้—ดไปถโ€ๆ˜ฏไธ€ไธชๅ‡ฝๆ•ฐ๏ผŒๅฎƒไผšๅœจๆฏไธช็‰นๅฎš็š„*่ทฏๅพ„ๆ“ไฝœ*ๅค„็†ๆฏไธช**่ฏทๆฑ‚**ไน‹ๅ‰่ฟ่กŒ๏ผŒไนŸไผšๅœจ่ฟ”ๅ›žๆฏไธช**ๅ“ๅบ”**ไน‹ๅ‰่ฟ่กŒใ€‚ -* ๅฎƒๆŽฅๆ”ถไฝ ็š„ๅบ”็”จ็จ‹ๅบ็š„ๆฏไธ€ไธช**่ฏทๆฑ‚**. -* ็„ถๅŽๅฎƒๅฏไปฅๅฏน่ฟ™ไธช**่ฏทๆฑ‚**ๅšไธ€ไบ›ไบ‹ๆƒ…ๆˆ–่€…ๆ‰ง่กŒไปปไฝ•้œ€่ฆ็š„ไปฃ็ . -* ็„ถๅŽๅฎƒๅฐ†**่ฏทๆฑ‚**ไผ ้€’็ป™ๅบ”็”จ็จ‹ๅบ็š„ๅ…ถไป–้ƒจๅˆ† (้€š่ฟ‡ๆŸ็ง*่ทฏๅพ„ๆ“ไฝœ*). -* ็„ถๅŽๅฎƒ่Žทๅ–ๅบ”็”จ็จ‹ๅบ็”Ÿไบง็š„**ๅ“ๅบ”** (้€š่ฟ‡ๆŸ็ง*่ทฏๅพ„ๆ“ไฝœ*). -* ๅฎƒๅฏไปฅๅฏน่ฏฅ**ๅ“ๅบ”**ๅšไบ›ไป€ไนˆๆˆ–่€…ๆ‰ง่กŒไปปไฝ•้œ€่ฆ็š„ไปฃ็ . -* ็„ถๅŽๅฎƒ่ฟ”ๅ›ž่ฟ™ไธช **ๅ“ๅบ”**. +* ๅฎƒๆŽฅๆ”ถไฝ ็š„ๅบ”็”จ็š„ๆฏไธ€ไธช**่ฏทๆฑ‚**ใ€‚ +* ็„ถๅŽๅฎƒๅฏไปฅๅฏน่ฟ™ไธช**่ฏทๆฑ‚**ๅšไธ€ไบ›ไบ‹ๆƒ…ๆˆ–่€…ๆ‰ง่กŒไปปไฝ•้œ€่ฆ็š„ไปฃ็ ใ€‚ +* ็„ถๅŽๅฎƒๅฐ†่ฟ™ไธช**่ฏทๆฑ‚**ไผ ้€’็ป™ๅบ”็”จ็จ‹ๅบ็š„ๅ…ถไป–้ƒจๅˆ†๏ผˆๆŸไธช*่ทฏๅพ„ๆ“ไฝœ*๏ผ‰ๅค„็†ใ€‚ +* ไน‹ๅŽๅฎƒ่Žทๅ–ๅบ”็”จ็จ‹ๅบ็”Ÿๆˆ็š„**ๅ“ๅบ”**๏ผˆ็”ฑๆŸไธช*่ทฏๅพ„ๆ“ไฝœ*ไบง็”Ÿ๏ผ‰ใ€‚ +* ๅฎƒๅฏไปฅๅฏน่ฏฅ**ๅ“ๅบ”**ๅšไธ€ไบ›ไบ‹ๆƒ…ๆˆ–่€…ๆ‰ง่กŒไปปไฝ•้œ€่ฆ็š„ไปฃ็ ใ€‚ +* ็„ถๅŽๅฎƒ่ฟ”ๅ›ž่ฟ™ไธช**ๅ“ๅบ”**ใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ๅฆ‚ๆžœไฝ ไฝฟ็”จไบ† `yield` ๅ…ณ้”ฎๅญ—ไพ่ต–, ไพ่ต–ไธญ็š„้€€ๅ‡บไปฃ็ ๅฐ†ๅœจๆ‰ง่กŒไธญ้—ดไปถ*ๅŽ*ๆ‰ง่กŒ. +ๅฆ‚ๆžœไฝ ๆœ‰ไฝฟ็”จ `yield` ็š„ไพ่ต–๏ผŒไพ่ต–ไธญ็š„้€€ๅ‡บไปฃ็ ไผšๅœจไธญ้—ดไปถไน‹ๅŽ่ฟ่กŒใ€‚ -ๅฆ‚ๆžœๆœ‰ไปปไฝ•ๅŽๅฐไปปๅŠก(็จๅŽ่ฎฐๅฝ•), ๅฎƒไปฌๅฐ†ๅœจๆ‰ง่กŒไธญ้—ดไปถ*ๅŽ*่ฟ่กŒ. +ๅฆ‚ๆžœๆœ‰ไปปไฝ•ๅŽๅฐไปปๅŠก๏ผˆไผšๅœจ[ๅŽๅฐไปปๅŠก](background-tasks.md){.internal-link target=_blank}ไธ€่Š‚ไธญไป‹็ป๏ผŒไฝ ็จๅŽไผš็œ‹ๅˆฐ๏ผ‰๏ผŒๅฎƒไปฌไผšๅœจๆ‰€ๆœ‰ไธญ้—ดไปถไน‹ๅŽ่ฟ่กŒใ€‚ /// -## ๅˆ›ๅปบไธญ้—ดไปถ +## ๅˆ›ๅปบไธญ้—ดไปถ { #create-a-middleware } -่ฆๅˆ›ๅปบไธญ้—ดไปถไฝ ๅฏไปฅๅœจๅ‡ฝๆ•ฐ็š„้กถ้ƒจไฝฟ็”จ่ฃ…้ฅฐๅ™จ `@app.middleware("http")`. +่ฆๅˆ›ๅปบไธญ้—ดไปถ๏ผŒไฝ ๅฏไปฅๅœจๅ‡ฝๆ•ฐ็š„้กถ้ƒจไฝฟ็”จ่ฃ…้ฅฐๅ™จ `@app.middleware("http")`ใ€‚ -ไธญ้—ดไปถๅ‚ๆ•ฐๆŽฅๆ”ถๅฆ‚ไธ‹ๅ‚ๆ•ฐ: +ไธญ้—ดไปถๅ‡ฝๆ•ฐไผšๆŽฅๆ”ถ๏ผš -* `request`. -* ไธ€ไธชๅ‡ฝๆ•ฐ `call_next` ๅฎƒๅฐ†ๆŽฅๆ”ถ `request` ไฝœไธบๅ‚ๆ•ฐ. - * ่ฟ™ไธชๅ‡ฝๆ•ฐๅฐ† `request` ไผ ้€’็ป™็›ธๅบ”็š„ *่ทฏๅพ„ๆ“ไฝœ*. - * ็„ถๅŽๅฎƒๅฐ†่ฟ”ๅ›ž็”ฑ็›ธๅบ”็š„*่ทฏๅพ„ๆ“ไฝœ*็”Ÿๆˆ็š„ `response`. -* ็„ถๅŽไฝ ๅฏไปฅๅœจ่ฟ”ๅ›ž `response` ๅ‰่ฟ›ไธ€ๆญฅไฟฎๆ”นๅฎƒ. +* `request`ใ€‚ +* ไธ€ไธชๅ‡ฝๆ•ฐ `call_next`๏ผŒๅฎƒไผšๆŠŠ `request` ไฝœไธบๅ‚ๆ•ฐๆŽฅๆ”ถใ€‚ + * ่ฟ™ไธชๅ‡ฝๆ•ฐไผšๆŠŠ `request` ไผ ้€’็ป™็›ธๅบ”็š„*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ + * ็„ถๅŽๅฎƒ่ฟ”ๅ›ž็”ฑ็›ธๅบ”*่ทฏๅพ„ๆ“ไฝœ*็”Ÿๆˆ็š„ `response`ใ€‚ +* ๅœจ่ฟ”ๅ›žไน‹ๅ‰๏ผŒไฝ ๅฏไปฅ่ฟ›ไธ€ๆญฅไฟฎๆ”น `response`ใ€‚ -{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} /// tip -่ฏท่ฎฐไฝๅฏไปฅ ็”จ'X-' ๅ‰็ผ€ๆทปๅŠ ไธ“ๆœ‰่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคด. +่ฏท่ฎฐไฝๅฏไปฅไฝฟ็”จ `X-` ๅ‰็ผ€ๆทปๅŠ ไธ“ๆœ‰่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคดใ€‚ -ไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ๆƒณ่ฎฉๆต่งˆๅ™จไธญ็š„ๅฎขๆˆท็ซฏ็œ‹ๅˆฐไฝ ็š„่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคด, ไฝ ้œ€่ฆๆŠŠๅฎƒไปฌๅŠ ๅˆฐ CORS ้…็ฝฎ ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) ็š„ `expose_headers` ๅ‚ๆ•ฐไธญ,ๅœจ Starlette's CORS docsๆ–‡ๆกฃไธญ. +ไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ๆœ‰ๅธŒๆœ›่ฎฉๆต่งˆๅ™จไธญ็š„ๅฎขๆˆท็ซฏๅฏ่ง็š„่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคด๏ผŒไฝ ้œ€่ฆๆŠŠๅฎƒไปฌๅŠ ๅˆฐไฝ ็š„ CORS ้…็ฝฎ๏ผˆ[CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}๏ผ‰็š„ `expose_headers` ๅ‚ๆ•ฐไธญ๏ผŒๅ‚่ง Starlette ็š„ CORS ๆ–‡ๆกฃใ€‚ /// /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request`. +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request`ใ€‚ -**FastAPI** ไธบไบ†ๅผ€ๅ‘่€…ๆ–นไพฟๆไพ›ไบ†่ฏฅๅฏน่ฑก. ไฝ†ๅ…ถๅฎžๅฎƒ็›ดๆŽฅๆฅ่‡ชไบŽ Starlette. +**FastAPI** ไธบไบ†ๅผ€ๅ‘่€…ๆ–นไพฟๆไพ›ไบ†่ฏฅๅฏน่ฑก๏ผŒไฝ†ๅฎƒ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ /// -### ๅœจ `response` ็š„ๅ‰ๅ’ŒๅŽ +### ๅœจ `response` ไน‹ๅ‰ไธŽไน‹ๅŽ { #before-and-after-the-response } -ๅœจไปปไฝ•*่ทฏๅพ„ๆ“ไฝœ*ๆ”ถๅˆฐ`request`ๅ‰,ๅฏไปฅๆทปๅŠ ่ฆๅ’Œ่ฏทๆฑ‚ไธ€่ตท่ฟ่กŒ็š„ไปฃ็ . +ไฝ ๅฏไปฅๅœจไปปไฝ•*่ทฏๅพ„ๆ“ไฝœ*ๆŽฅๆ”ถ `request` ไน‹ๅ‰๏ผŒๆทปๅŠ ่ฆไธŽ่ฏฅ `request` ไธ€่ตท่ฟ่กŒ็š„ไปฃ็ ใ€‚ -ไนŸๅฏไปฅๅœจ*ๅ“ๅบ”*็”Ÿๆˆไฝ†ๆ˜ฏ่ฟ”ๅ›žไน‹ๅ‰ๆทปๅŠ ไปฃ็ . +ไนŸๅฏไปฅๅœจ็”Ÿๆˆ `response` ไน‹ๅŽใ€่ฟ”ๅ›žไน‹ๅ‰ๆทปๅŠ ไปฃ็ ใ€‚ -ไพ‹ๅฆ‚ไฝ ๅฏไปฅๆทปๅŠ ่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคด `X-Process-Time` ๅŒ…ๅซไปฅ็ง’ไธบๅ•ไฝ็š„ๆŽฅๆ”ถ่ฏทๆฑ‚ๅ’Œ็”Ÿๆˆๅ“ๅบ”็š„ๆ—ถ้—ด: +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆทปๅŠ ไธ€ไธช่‡ชๅฎšไน‰่ฏทๆฑ‚ๅคด `X-Process-Time`๏ผŒๅ…ถๅ€ผไธบๅค„็†่ฏทๆฑ‚ๅนถ็”Ÿๆˆๅ“ๅบ”ๆ‰€่Šฑ่ดน็š„็ง’ๆ•ฐ๏ผš -{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} -## ๅ…ถไป–ไธญ้—ดไปถ +/// tip + +่ฟ™้‡Œๆˆ‘ไปฌไฝฟ็”จ `time.perf_counter()` ่€Œไธๆ˜ฏ `time.time()`๏ผŒๅ› ไธบๅœจ่ฟ™็ฑปๅœบๆ™ฏไธญๅฎƒๅฏ่ƒฝๆ›ด็ฒพ็กฎใ€‚๐Ÿค“ + +/// + +## ๅคšไธชไธญ้—ดไปถ็š„ๆ‰ง่กŒ้กบๅบ { #multiple-middleware-execution-order } + +ๅฝ“ไฝ ไฝฟ็”จ `@app.middleware()` ่ฃ…้ฅฐๅ™จๆˆ– `app.add_middleware()` ๆ–นๆณ•ๆทปๅŠ ๅคšไธชไธญ้—ดไปถๆ—ถ๏ผŒๆฏไธชๆ–ฐไธญ้—ดไปถ้ƒฝไผšๅŒ…่ฃนๅบ”็”จ๏ผŒๅฝขๆˆไธ€ไธชๆ ˆใ€‚ๆœ€ๅŽๆทปๅŠ ็š„ไธญ้—ดไปถๆ˜ฏโ€œๆœ€ๅค–ๅฑ‚โ€็š„๏ผŒๆœ€ๅ…ˆๆทปๅŠ ็š„ๆ˜ฏโ€œๆœ€ๅ†…ๅฑ‚โ€็š„ใ€‚ + +ๅœจ่ฏทๆฑ‚่ทฏๅพ„ไธŠ๏ผŒๆœ€ๅค–ๅฑ‚็š„ไธญ้—ดไปถๅ…ˆ่ฟ่กŒใ€‚ + +ๅœจๅ“ๅบ”่ทฏๅพ„ไธŠ๏ผŒๅฎƒๆœ€ๅŽ่ฟ่กŒใ€‚ + +ไพ‹ๅฆ‚๏ผš + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +่ฟ™ไผšไบง็”Ÿๅฆ‚ไธ‹ๆ‰ง่กŒ้กบๅบ๏ผš + +* ่ฏทๆฑ‚๏ผšMiddlewareB โ†’ MiddlewareA โ†’ ่ทฏ็”ฑ + +* ๅ“ๅบ”๏ผš่ทฏ็”ฑ โ†’ MiddlewareA โ†’ MiddlewareB + +่ฟ™็งๆ ˆๅผ่กŒไธบ็กฎไฟไธญ้—ดไปถๆŒ‰ๅฏ้ข„ๆต‹ไธ”ๅฏๆŽง็š„้กบๅบๆ‰ง่กŒใ€‚ + +## ๅ…ถไป–ไธญ้—ดไปถ { #other-middlewares } -ไฝ ๅฏไปฅ็จๅŽๅœจ [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}้˜…่ฏปๆ›ดๅคšๅ…ณไบŽไธญ้—ดไปถ็š„ๆ•™็จ‹. +ไฝ ๅฏไปฅ็จๅŽๅœจ[้ซ˜็บง็”จๆˆทๆŒ‡ๅ—๏ผš้ซ˜็บงไธญ้—ดไปถ](../advanced/middleware.md){.internal-link target=_blank}ไธญ้˜…่ฏปๆ›ดๅคšๅ…ณไบŽๅ…ถไป–ไธญ้—ดไปถ็š„ๅ†…ๅฎนใ€‚ -ไฝ ๅฐ†ๅœจไธ‹ไธ€่Š‚ไธญๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จไธญ้—ดไปถๅค„็† CORS . +ไฝ ๅฐ†ๅœจไธ‹ไธ€่Š‚ไธญไบ†่งฃๅฆ‚ไฝ•ไฝฟ็”จไธญ้—ดไปถๅค„็† CORSใ€‚ diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md index adeca2d3fd..49b7baabcc 100644 --- a/docs/zh/docs/tutorial/path-operation-configuration.md +++ b/docs/zh/docs/tutorial/path-operation-configuration.md @@ -1,66 +1,76 @@ -# ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ +# ่ทฏๅพ„ๆ“ไฝœ้…็ฝฎ { #path-operation-configuration } *่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ๆ”ฏๆŒๅคš็ง้…็ฝฎๅ‚ๆ•ฐใ€‚ /// warning | ่ญฆๅ‘Š -ๆณจๆ„๏ผšไปฅไธ‹ๅ‚ๆ•ฐๅบ”็›ดๆŽฅไผ ้€’็ป™**่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ**๏ผŒไธ่ƒฝไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ +ๆณจๆ„๏ผšไปฅไธ‹ๅ‚ๆ•ฐๅบ”็›ดๆŽฅไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*๏ผŒไธ่ƒฝไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ /// -## `status_code` ็Šถๆ€็  +## ๅ“ๅบ”็Šถๆ€็  { #response-status-code } -`status_code` ็”จไบŽๅฎšไน‰*่ทฏๅพ„ๆ“ไฝœ*ๅ“ๅบ”ไธญ็š„ HTTP ็Šถๆ€็ ใ€‚ +ๅฏไปฅๅœจ*่ทฏๅพ„ๆ“ไฝœ*็š„ๅ“ๅบ”ไธญๅฎšไน‰๏ผˆHTTP๏ผ‰`status_code`ใ€‚ -ๅฏไปฅ็›ดๆŽฅไผ ้€’ `int` ไปฃ็ ๏ผŒ ๆฏ”ๅฆ‚ `404`ใ€‚ +ๅฏไปฅ็›ดๆŽฅไผ ้€’ `int` ไปฃ็ ๏ผŒๆฏ”ๅฆ‚ `404`ใ€‚ -ๅฆ‚ๆžœ่ฎฐไธไฝๆ•ฐๅญ—็ ็š„ๆถตไน‰๏ผŒไนŸๅฏไปฅ็”จ `status` ็š„ๅฟซๆทๅธธ้‡๏ผš +ๅฆ‚ๆžœ่ฎฐไธไฝๆ•ฐๅญ—็ ็š„ๅซไน‰๏ผŒไนŸๅฏไปฅ็”จ `status` ็š„ๅฟซๆทๅธธ้‡๏ผš -{* ../../docs_src/path_operation_configuration/tutorial001.py hl[3,17] *} +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} -็Šถๆ€็ ๅœจๅ“ๅบ”ไธญไฝฟ็”จ๏ผŒๅนถไผš่ขซๆทปๅŠ ๅˆฐ OpenAPI ๆฆ‚ๅ›พใ€‚ +่ฏฅ็Šถๆ€็ ไผš็”จไบŽๅ“ๅบ”ไธญ๏ผŒๅนถไผš่ขซๆทปๅŠ ๅˆฐ OpenAPI ๆฆ‚ๅ›พใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ ไนŸๅฏไปฅไฝฟ็”จ `from starlette import status` ๅฏผๅ…ฅ็Šถๆ€็ ใ€‚ -**FastAPI** ็š„`fastapi.status` ๅ’Œ `starlette.status` ไธ€ๆ ท๏ผŒๅชๆ˜ฏๅฟซๆทๆ–นๅผใ€‚ๅฎž้™…ไธŠ๏ผŒ`fastapi.status` ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช Starletteใ€‚ +**FastAPI** ๆไพ›็š„ `fastapi.status` ไธŽ `starlette.status` ็›ธๅŒ๏ผŒๆ–นไพฟไฝ ไฝœไธบๅผ€ๅ‘่€…ไฝฟ็”จใ€‚ๅฎž้™…ไธŠๅฎƒ็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ /// -## `tags` ๅ‚ๆ•ฐ +## ๆ ‡็ญพ { #tags } -`tags` ๅ‚ๆ•ฐ็š„ๅ€ผๆ˜ฏ็”ฑ `str` ็ป„ๆˆ็š„ `list` ๏ผˆไธ€่ˆฌๅชๆœ‰ไธ€ไธช `str` ๏ผ‰๏ผŒ`tags` ็”จไบŽไธบ*่ทฏๅพ„ๆ“ไฝœ*ๆทปๅŠ ๆ ‡็ญพ๏ผš +ๅฏไปฅ้€š่ฟ‡ไผ ๅ…ฅ็”ฑ `str` ็ป„ๆˆ็š„ `list`๏ผˆ้€šๅธธๅชๆœ‰ไธ€ไธช `str`๏ผ‰็š„ๅ‚ๆ•ฐ `tags`๏ผŒไธบ*่ทฏๅพ„ๆ“ไฝœ*ๆทปๅŠ ๆ ‡็ญพ๏ผš -{* ../../docs_src/path_operation_configuration/tutorial002.py hl[17,22,27] *} +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} OpenAPI ๆฆ‚ๅ›พไผš่‡ชๅŠจๆทปๅŠ ๆ ‡็ญพ๏ผŒไพ› API ๆ–‡ๆกฃๆŽฅๅฃไฝฟ็”จ๏ผš -## `summary` ๅ’Œ `description` ๅ‚ๆ•ฐ +### ไฝฟ็”จ Enum ็š„ๆ ‡็ญพ { #tags-with-enums } -่ทฏๅพ„่ฃ…้ฅฐๅ™จ่ฟ˜ๆ”ฏๆŒ `summary` ๅ’Œ `description` ่ฟ™ไธคไธชๅ‚ๆ•ฐ๏ผš +ๅฆ‚ๆžœไฝ ็š„ๅบ”็”จๅพˆๅคง๏ผŒๅฏ่ƒฝไผš็งฏ็ดฏๅ‡บๅพˆๅคšๆ ‡็ญพ๏ผŒไฝ ไผšๅธŒๆœ›็กฎไฟ็›ธๅ…ณ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅง‹็ปˆไฝฟ็”จ็›ธๅŒ็š„ๆ ‡็ญพใ€‚ -{* ../../docs_src/path_operation_configuration/tutorial003.py hl[20:21] *} +่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๆŠŠๆ ‡็ญพๅญ˜ๆ”พๅœจ `Enum` ไธญไผšๆ›ดๅˆ้€‚ใ€‚ -## ๆ–‡ๆกฃๅญ—็ฌฆไธฒ๏ผˆ`docstring`๏ผ‰ +**FastAPI** ๅฏนๆญค็š„ๆ”ฏๆŒไธŽไฝฟ็”จๆ™ฎ้€šๅญ—็ฌฆไธฒ็›ธๅŒ๏ผš -ๆ่ฟฐๅ†…ๅฎนๆฏ”่พƒ้•ฟไธ”ๅ ็”จๅคš่กŒๆ—ถ๏ผŒๅฏไปฅๅœจๅ‡ฝๆ•ฐ็š„ docstring ไธญๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ่ฟฐ๏ผŒ**FastAPI** ๆ”ฏๆŒไปŽๆ–‡ๆกฃๅญ—็ฌฆไธฒไธญ่ฏปๅ–ๆ่ฟฐๅ†…ๅฎนใ€‚ +{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} + +## ๆ‘˜่ฆๅ’Œๆ่ฟฐ { #summary-and-description } + +ๅฏไปฅๆทปๅŠ  `summary` ๅ’Œ `description`๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## ไปŽ docstring ่Žทๅ–ๆ่ฟฐ { #description-from-docstring } + +ๆ่ฟฐๅ†…ๅฎนๆฏ”่พƒ้•ฟไธ”ๅ ็”จๅคš่กŒๆ—ถ๏ผŒๅฏไปฅๅœจๅ‡ฝๆ•ฐ็š„ docstring ไธญๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ่ฟฐ๏ผŒ**FastAPI** ไผšไปŽไธญ่ฏปๅ–ใ€‚ ๆ–‡ๆกฃๅญ—็ฌฆไธฒๆ”ฏๆŒ Markdown๏ผŒ่ƒฝๆญฃ็กฎ่งฃๆžๅ’Œๆ˜พ็คบ Markdown ็š„ๅ†…ๅฎน๏ผŒไฝ†่ฆๆณจๆ„ๆ–‡ๆกฃๅญ—็ฌฆไธฒ็š„็ผฉ่ฟ›ใ€‚ -{* ../../docs_src/path_operation_configuration/tutorial004.py hl[19:27] *} +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} ไธ‹ๅ›พไธบ Markdown ๆ–‡ๆœฌๅœจ API ๆ–‡ๆกฃไธญ็š„ๆ˜พ็คบๆ•ˆๆžœ๏ผš -## ๅ“ๅบ”ๆ่ฟฐ +## ๅ“ๅบ”ๆ่ฟฐ { #response-description } `response_description` ๅ‚ๆ•ฐ็”จไบŽๅฎšไน‰ๅ“ๅบ”็š„ๆ่ฟฐ่ฏดๆ˜Ž๏ผš -{* ../../docs_src/path_operation_configuration/tutorial005.py hl[21] *} +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} /// info | ่ฏดๆ˜Ž @@ -78,11 +88,11 @@ OpenAPI ่ง„ๅฎšๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*้ƒฝ่ฆๆœ‰ๅ“ๅบ”ๆ่ฟฐใ€‚ -## ๅผƒ็”จ*่ทฏๅพ„ๆ“ไฝœ* +## ๅผƒ็”จ*่ทฏๅพ„ๆ“ไฝœ* { #deprecate-a-path-operation } `deprecated` ๅ‚ๆ•ฐๅฏไปฅๆŠŠ*่ทฏๅพ„ๆ“ไฝœ*ๆ ‡่ฎฐไธบๅผƒ็”จ๏ผŒๆ— ้œ€็›ดๆŽฅๅˆ ้™ค๏ผš -{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} API ๆ–‡ๆกฃไผšๆŠŠ่ฏฅ่ทฏๅพ„ๆ“ไฝœๆ ‡่ฎฐไธบๅผƒ็”จ๏ผš @@ -92,6 +102,6 @@ API ๆ–‡ๆกฃไผšๆŠŠ่ฏฅ่ทฏๅพ„ๆ“ไฝœๆ ‡่ฎฐไธบๅผƒ็”จ๏ผš -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -้€š่ฟ‡ไผ ้€’ๅ‚ๆ•ฐ็ป™*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ* ๏ผŒๅณๅฏ่ฝปๆพๅœฐ้…็ฝฎ*่ทฏๅพ„ๆ“ไฝœ*ใ€ๆทปๅŠ ๅ…ƒๆ•ฐๆฎใ€‚ +้€š่ฟ‡ไผ ้€’ๅ‚ๆ•ฐ็ป™*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*๏ผŒๅณๅฏ่ฝปๆพๅœฐ้…็ฝฎ*่ทฏๅพ„ๆ“ไฝœ*ใ€ๆทปๅŠ ๅ…ƒๆ•ฐๆฎใ€‚ diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md index ff62428359..ff8b1762cf 100644 --- a/docs/zh/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md @@ -1,91 +1,128 @@ -# ่ทฏๅพ„ๅ‚ๆ•ฐๅ’Œๆ•ฐๅ€ผๆ ก้ชŒ +# ่ทฏๅพ„ๅ‚ๆ•ฐๅ’Œๆ•ฐๅ€ผๆ ก้ชŒ { #path-parameters-and-numeric-validations } ไธŽไฝฟ็”จ `Query` ไธบๆŸฅ่ฏขๅ‚ๆ•ฐๅฃฐๆ˜Žๆ›ดๅคš็š„ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎ็š„ๆ–นๅผ็›ธๅŒ๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ `Path` ไธบ่ทฏๅพ„ๅ‚ๆ•ฐๅฃฐๆ˜Ž็›ธๅŒ็ฑปๅž‹็š„ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ -## ๅฏผๅ…ฅ Path +## ๅฏผๅ…ฅ `Path` { #import-path } -้ฆ–ๅ…ˆ๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ `Path`๏ผš +้ฆ–ๅ…ˆ๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ `Path`๏ผŒๅนถๅฏผๅ…ฅ `Annotated`๏ผš {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -## ๅฃฐๆ˜Žๅ…ƒๆ•ฐๆฎ +/// info | ไฟกๆฏ + +FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌๆทปๅŠ ไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ไฝฟ็”จๅฎƒ๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏๆ›ดๆ—ง็š„็‰ˆๆœฌ๏ผŒๅฐ่ฏ•ไฝฟ็”จ `Annotated` ไผšๆŠฅ้”™ใ€‚ + +่ฏท็กฎไฟๅœจไฝฟ็”จ `Annotated` ไน‹ๅ‰๏ผŒๅฐ† FastAPI ็‰ˆๆœฌ[ๅ‡็บง](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ๅˆฐ่‡ณๅฐ‘ 0.95.1ใ€‚ + +/// + +## ๅฃฐๆ˜Žๅ…ƒๆ•ฐๆฎ { #declare-metadata } ไฝ ๅฏไปฅๅฃฐๆ˜ŽไธŽ `Query` ็›ธๅŒ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐใ€‚ -ไพ‹ๅฆ‚๏ผŒ่ฆๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ `item_id`็š„ `title` ๅ…ƒๆ•ฐๆฎๅ€ผ๏ผŒไฝ ๅฏไปฅ่พ“ๅ…ฅ๏ผš +ไพ‹ๅฆ‚๏ผŒ่ฆไธบ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ๅฃฐๆ˜Ž `title` ๅ…ƒๆ•ฐๆฎๅ€ผ๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ทๅ†™๏ผš {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} -/// note +/// note | ๆณจๆ„ -่ทฏๅพ„ๅ‚ๆ•ฐๆ€ปๆ˜ฏๅฟ…้œ€็š„๏ผŒๅ› ไธบๅฎƒๅฟ…้กปๆ˜ฏ่ทฏๅพ„็š„ไธ€้ƒจๅˆ†ใ€‚ +่ทฏๅพ„ๅ‚ๆ•ฐๆ€ปๆ˜ฏๅฟ…้œ€็š„๏ผŒๅ› ไธบๅฎƒๅฟ…้กปๆ˜ฏ่ทฏๅพ„็š„ไธ€้ƒจๅˆ†ใ€‚ๅณไฝฟไฝ ๅฐ†ๅ…ถๅฃฐๆ˜Žไธบ `None` ๆˆ–่ฎพ็ฝฎไบ†้ป˜่ฎคๅ€ผ๏ผŒไนŸไธไผšไบง็”Ÿไปปไฝ•ๅฝฑๅ“๏ผŒๅฎƒไพ็„ถๅง‹็ปˆๆ˜ฏๅฟ…้œ€ๅ‚ๆ•ฐใ€‚ -ๆ‰€ไปฅ๏ผŒไฝ ๅบ”่ฏฅๅœจๅฃฐๆ˜Žๆ—ถไฝฟ็”จ `...` ๅฐ†ๅ…ถๆ ‡่ฎฐไธบๅฟ…้œ€ๅ‚ๆ•ฐใ€‚ +/// -็„ถ่€Œ๏ผŒๅณไฝฟไฝ ไฝฟ็”จ `None` ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐๆˆ–่ฎพ็ฝฎไธ€ไธชๅ…ถไป–้ป˜่ฎคๅ€ผไนŸไธไผšๆœ‰ไปปไฝ•ๅฝฑๅ“๏ผŒๅฎƒไพ็„ถไผšๆ˜ฏๅฟ…้œ€ๅ‚ๆ•ฐใ€‚ +## ๆŒ‰้œ€ๅฏนๅ‚ๆ•ฐๆŽ’ๅบ { #order-the-parameters-as-you-need } -/// +/// tip | ๆ็คบ -## ๆŒ‰้œ€ๅฏนๅ‚ๆ•ฐๆŽ’ๅบ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒ่ฟ™็‚นๅฏ่ƒฝไธ้‚ฃไนˆ้‡่ฆๆˆ–ๅฟ…่ฆใ€‚ -ๅ‡่ฎพไฝ ๆƒณ่ฆๅฃฐๆ˜Žไธ€ไธชๅฟ…้œ€็š„ `str` ็ฑปๅž‹ๆŸฅ่ฏขๅ‚ๆ•ฐ `q`ใ€‚ +/// -่€Œไธ”ไฝ ไธ้œ€่ฆไธบ่ฏฅๅ‚ๆ•ฐๅฃฐๆ˜Žไปปไฝ•ๅ…ถไป–ๅ†…ๅฎน๏ผŒๆ‰€ไปฅๅฎž้™…ไธŠไฝ ๅนถไธ้œ€่ฆไฝฟ็”จ `Query`ใ€‚ +ๅ‡่ฎพไฝ ๆƒณ่ฆๅฐ†ๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ๅฃฐๆ˜Žไธบๅฟ…้œ€็š„ `str`ใ€‚ -ไฝ†ๆ˜ฏไฝ ไป็„ถ้œ€่ฆไฝฟ็”จ `Path` ๆฅๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ `item_id`ใ€‚ +ๅนถไธ”ไฝ ไธ้œ€่ฆไธบ่ฏฅๅ‚ๆ•ฐๅฃฐๆ˜Žๅ…ถไป–ๅ†…ๅฎน๏ผŒๆ‰€ไปฅๅฎž้™…ไธŠไธ้œ€่ฆ็”จๅˆฐ `Query`ใ€‚ -ๅฆ‚ๆžœไฝ ๅฐ†ๅธฆๆœ‰ใ€Œ้ป˜่ฎคๅ€ผใ€็š„ๅ‚ๆ•ฐๆ”พๅœจๆฒกๆœ‰ใ€Œ้ป˜่ฎคๅ€ผใ€็š„ๅ‚ๆ•ฐไน‹ๅ‰๏ผŒPython ๅฐ†ไผšๆŠฅ้”™ใ€‚ +ไฝ†ๆ˜ฏไฝ ไป็„ถ้œ€่ฆไธบ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ไฝฟ็”จ `Path`ใ€‚ๅนถไธ”ๅ‡บไบŽๆŸไบ›ๅŽŸๅ› ไฝ ไธๆƒณไฝฟ็”จ `Annotated`ใ€‚ -ไฝ†ๆ˜ฏไฝ ๅฏไปฅๅฏนๅ…ถ้‡ๆ–ฐๆŽ’ๅบ๏ผŒๅนถๅฐ†ไธๅธฆ้ป˜่ฎคๅ€ผ็š„ๅ€ผ๏ผˆๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผ‰ๆ”พๅˆฐๆœ€ๅ‰้ขใ€‚ +ๅฆ‚ๆžœไฝ ๅฐ†ๅธฆๆœ‰โ€œ้ป˜่ฎคๅ€ผโ€็š„ๅ‚ๆ•ฐๆ”พๅœจๆฒกๆœ‰โ€œ้ป˜่ฎคๅ€ผโ€็š„ๅ‚ๆ•ฐไน‹ๅ‰๏ผŒPython ไผšๆŠฅ้”™ใ€‚ -ๅฏน **FastAPI** ๆฅ่ฏด่ฟ™ๆ— ๅ…ณ็ดง่ฆใ€‚ๅฎƒๅฐ†้€š่ฟ‡ๅ‚ๆ•ฐ็š„ๅ็งฐใ€็ฑปๅž‹ๅ’Œ้ป˜่ฎคๅ€ผๅฃฐๆ˜Ž๏ผˆ`Query`ใ€`Path` ็ญ‰๏ผ‰ๆฅๆฃ€ๆต‹ๅ‚ๆ•ฐ๏ผŒ่€ŒไธๅœจไนŽๅ‚ๆ•ฐ็š„้กบๅบใ€‚ +ไธ่ฟ‡ไฝ ๅฏไปฅ้‡ๆ–ฐๆŽ’ๅบ๏ผŒ่ฎฉๆฒกๆœ‰้ป˜่ฎคๅ€ผ็š„ๅ‚ๆ•ฐ๏ผˆๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผ‰ๆ”พๅœจๆœ€ๅ‰้ขใ€‚ + +ๅฏน **FastAPI** ๆฅ่ฏด่ฟ™ๆ— ๅ…ณ็ดง่ฆใ€‚ๅฎƒไผš้€š่ฟ‡ๅ‚ๆ•ฐ็š„ๅ็งฐใ€็ฑปๅž‹ๅ’Œ้ป˜่ฎคๅ€ผๅฃฐๆ˜Ž๏ผˆ`Query`ใ€`Path` ็ญ‰๏ผ‰ๆฅๆฃ€ๆต‹ๅ‚ๆ•ฐ๏ผŒ่€Œไธๅ…ณๅฟƒ้กบๅบใ€‚ ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅฐ†ๅ‡ฝๆ•ฐๅฃฐๆ˜Žไธบ๏ผš -{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} + +ไฝ†่ฏท่ฎฐไฝ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒไฝ ๅฐฑไธไผš้‡ๅˆฐ่ฟ™ไธช้—ฎ้ข˜๏ผŒๅ› ไธบไฝ ๆฒกๆœ‰ไฝฟ็”จ `Query()` ๆˆ– `Path()` ไฝœไธบๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} + +## ๆŒ‰้œ€ๅฏนๅ‚ๆ•ฐๆŽ’ๅบ็š„ๆŠ€ๅทง { #order-the-parameters-as-you-need-tricks } + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒ่ฟ™็‚นๅฏ่ƒฝไธ้‚ฃไนˆ้‡่ฆๆˆ–ๅฟ…่ฆใ€‚ + +/// + +่ฟ™้‡Œๆœ‰ไธ€ไธชๅฐๆŠ€ๅทง๏ผŒๅฏ่ƒฝไผšๅพˆๆ–นไพฟ๏ผŒไฝ†ไฝ ๅนถไธไผš็ปๅธธ้œ€่ฆๅฎƒใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณ่ฆ๏ผš + +* ๅœจๆฒกๆœ‰ `Query` ไธ”ๆฒกๆœ‰ไปปไฝ•้ป˜่ฎคๅ€ผ็š„ๆƒ…ๅ†ตไธ‹ๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐ `q` +* ไฝฟ็”จ `Path` ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` +* ่ฎฉๅฎƒไปฌ็š„้กบๅบไธŽไธŠ้ขไธๅŒ +* ไธไฝฟ็”จ `Annotated` + +...Python ไธบๆญคๆœ‰ไธ€ไธชๅฐ็š„็‰นๆฎŠ่ฏญๆณ•ใ€‚ + +ๅœจๅ‡ฝๆ•ฐ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐไฝ็ฝฎไผ ๅ…ฅ `*`ใ€‚ -## ๆŒ‰้œ€ๅฏนๅ‚ๆ•ฐๆŽ’ๅบ็š„ๆŠ€ๅทง +Python ไธไผšๅฏน่ฟ™ไธช `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒไผš็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ้ƒฝๅบ”่ฏฅไฝœไธบๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ๏ผˆ้”ฎๅ€ผๅฏน๏ผ‰ๆฅ่ฐƒ็”จ๏ผŒไนŸ่ขซ็งฐไธบ kwargsใ€‚ๅณไฝฟๅฎƒไปฌๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ -ๅฆ‚ๆžœไฝ ๆƒณไธไฝฟ็”จ `Query` ๅฃฐๆ˜Žๆฒกๆœ‰้ป˜่ฎคๅ€ผ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผŒๅŒๆ—ถไฝฟ็”จ `Path` ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ `item_id`๏ผŒๅนถไฝฟๅฎƒไปฌ็š„้กบๅบไธŽไธŠ้ขไธๅŒ๏ผŒPython ๅฏนๆญคๆœ‰ไธ€ไบ›็‰นๆฎŠ็š„่ฏญๆณ•ใ€‚ +{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} -ไผ ้€’ `*` ไฝœไธบๅ‡ฝๆ•ฐ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐใ€‚ +### ไฝฟ็”จ `Annotated` ๆ›ดๅฅฝ { #better-with-annotated } -Python ไธไผšๅฏน่ฏฅ `*` ๅšไปปไฝ•ไบ‹ๆƒ…๏ผŒไฝ†ๆ˜ฏๅฎƒๅฐ†็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ้ƒฝๅบ”ไฝœไธบๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ๏ผˆ้”ฎๅ€ผๅฏน๏ผ‰๏ผŒไนŸ่ขซ็งฐไธบ kwargs๏ผŒๆฅ่ฐƒ็”จใ€‚ๅณไฝฟๅฎƒไปฌๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ +่ฏท่ฎฐไฝ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒๅ› ไธบไฝ ๆฒกๆœ‰ไฝฟ็”จๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒๆ‰€ไปฅไฝ ไธไผšๆœ‰่ฟ™ไธช้—ฎ้ข˜๏ผŒไฝ ๅคงๆฆ‚็އไนŸไธ้œ€่ฆไฝฟ็”จ `*`ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} -## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽ็ญ‰ไบŽ +## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽ็ญ‰ไบŽ { #number-validations-greater-than-or-equal } -ไฝฟ็”จ `Query` ๅ’Œ `Path`๏ผˆไปฅๅŠไฝ ๅฐ†ๅœจๅŽ้ข็œ‹ๅˆฐ็š„ๅ…ถไป–็ฑป๏ผ‰ๅฏไปฅๅฃฐๆ˜Žๅญ—็ฌฆไธฒ็บฆๆŸ๏ผŒไฝ†ไนŸๅฏไปฅๅฃฐๆ˜Žๆ•ฐๅ€ผ็บฆๆŸใ€‚ +ไฝฟ็”จ `Query` ๅ’Œ `Path`๏ผˆไปฅๅŠไฝ ็จๅŽไผš็œ‹ๅˆฐ็š„ๅ…ถไป–็ฑป๏ผ‰ไฝ ๅฏไปฅๅฃฐๆ˜Žๆ•ฐๅ€ผ็บฆๆŸใ€‚ -ๅƒไธ‹้ข่ฟ™ๆ ท๏ผŒๆทปๅŠ  `ge=1` ๅŽ๏ผŒ`item_id` ๅฐ†ๅฟ…้กปๆ˜ฏไธ€ไธชๅคงไบŽ๏ผˆ`g`reater than๏ผ‰ๆˆ–็ญ‰ไบŽ๏ผˆ`e`qual๏ผ‰`1` ็š„ๆ•ดๆ•ฐใ€‚ +ๅœจ่ฟ™้‡Œ๏ผŒไฝฟ็”จ `ge=1` ๅŽ๏ผŒ`item_id` ๅฟ…้กปๆ˜ฏไธ€ไธชๆ•ดๆ•ฐ๏ผŒๅ€ผ่ฆใ€Œ`g`reater than or `e`qualใ€1ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial004.py hl[8] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} -## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽๅ’ŒๅฐไบŽ็ญ‰ไบŽ +## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽๅ’ŒๅฐไบŽ็ญ‰ไบŽ { #number-validations-greater-than-and-less-than-or-equal } -ๅŒๆ ท็š„่ง„ๅˆ™้€‚็”จไบŽ๏ผš +ๅŒๆ ท้€‚็”จไบŽ๏ผš * `gt`๏ผšๅคงไบŽ๏ผˆ`g`reater `t`han๏ผ‰ * `le`๏ผšๅฐไบŽ็ญ‰ไบŽ๏ผˆ`l`ess than or `e`qual๏ผ‰ -{* ../../docs_src/path_params_numeric_validations/tutorial005.py hl[9] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} -## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๆตฎ็‚นๆ•ฐใ€ๅคงไบŽๅ’ŒๅฐไบŽ +## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๆตฎ็‚นๆ•ฐใ€ๅคงไบŽๅ’ŒๅฐไบŽ { #number-validations-floats-greater-than-and-less-than } ๆ•ฐๅ€ผๆ ก้ชŒๅŒๆ ท้€‚็”จไบŽ `float` ๅ€ผใ€‚ -่ƒฝๅคŸๅฃฐๆ˜Ž gt ่€Œไธไป…ไป…ๆ˜ฏ ge ๅœจ่ฟ™ไธชๅ‰ๆไธ‹ๅ˜ๅพ—้‡่ฆ่ตทๆฅใ€‚ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ่ฆๆฑ‚ไธ€ไธชๅ€ผๅฟ…้กปๅคงไบŽ `0`๏ผŒๅณไฝฟๅฎƒๅฐไบŽ `1`ใ€‚ +่ƒฝๅคŸๅฃฐๆ˜Ž gt ่€Œไธไป…ไป…ๆ˜ฏ ge ๅœจ่ฟ™้‡Œๅ˜ๅพ—ๅพˆ้‡่ฆใ€‚ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ่ฆๆฑ‚ไธ€ไธชๅ€ผๅฟ…้กปๅคงไบŽ `0`๏ผŒๅณไฝฟๅฎƒๅฐไบŽ `1`ใ€‚ -ๅ› ๆญค๏ผŒ`0.5` ๅฐ†ๆ˜ฏๆœ‰ๆ•ˆๅ€ผใ€‚ไฝ†ๆ˜ฏ `0.0`ๆˆ– `0` ไธๆ˜ฏใ€‚ +ๅ› ๆญค๏ผŒ`0.5` ๅฐ†ๆ˜ฏๆœ‰ๆ•ˆๅ€ผใ€‚ไฝ†ๆ˜ฏ `0.0` ๆˆ– `0` ไธๆ˜ฏใ€‚ -ๅฏนไบŽ lt ไนŸๆ˜ฏไธ€ๆ ท็š„ใ€‚ +ๅฏนไบŽ lt ไนŸๆ˜ฏไธ€ๆ ท็š„ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial006.py hl[11] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #recap } -ไฝ ่ƒฝๅคŸไปฅไธŽ [ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒ](query-params-str-validations.md){.internal-link target=_blank} ็›ธๅŒ็š„ๆ–นๅผไฝฟ็”จ `Query`ใ€`Path`๏ผˆไปฅๅŠๅ…ถไป–ไฝ ่ฟ˜ๆฒก่ง่ฟ‡็š„็ฑป๏ผ‰ๅฃฐๆ˜Žๅ…ƒๆ•ฐๆฎๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒใ€‚ +ไฝ ่ƒฝๅคŸไปฅไธŽ[ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒ](query-params-str-validations.md){.internal-link target=_blank}็›ธๅŒ็š„ๆ–นๅผไฝฟ็”จ `Query`ใ€`Path`๏ผˆไปฅๅŠๅ…ถไป–ไฝ ่ฟ˜ๆฒก่ง่ฟ‡็š„็ฑป๏ผ‰ๅฃฐๆ˜Žๅ…ƒๆ•ฐๆฎๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒใ€‚ ่€Œไธ”ไฝ ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žๆ•ฐๅ€ผๆ ก้ชŒ๏ผš @@ -94,24 +131,24 @@ Python ไธไผšๅฏน่ฏฅ `*` ๅšไปปไฝ•ไบ‹ๆƒ…๏ผŒไฝ†ๆ˜ฏๅฎƒๅฐ†็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ * `lt`๏ผšๅฐไบŽ๏ผˆ`l`ess `t`han๏ผ‰ * `le`๏ผšๅฐไบŽ็ญ‰ไบŽ๏ผˆ`l`ess than or `e`qual๏ผ‰ -/// info +/// info | ไฟกๆฏ -`Query`ใ€`Path` ไปฅๅŠไฝ ๅŽ้ขไผš็œ‹ๅˆฐ็š„ๅ…ถไป–็ฑป็ปงๆ‰ฟ่‡ชไธ€ไธชๅ…ฑๅŒ็š„ `Param` ็ฑป๏ผˆไธ้œ€่ฆ็›ดๆŽฅไฝฟ็”จๅฎƒ๏ผ‰ใ€‚ +`Query`ใ€`Path` ไปฅๅŠไฝ ๅŽ้ขไผš็œ‹ๅˆฐ็š„ๅ…ถไป–็ฑป๏ผŒ้ƒฝๆ˜ฏไธ€ไธช้€š็”จ `Param` ็ฑป็š„ๅญ็ฑปใ€‚ -่€Œไธ”ๅฎƒไปฌ้ƒฝๅ…ฑไบซ็›ธๅŒ็š„ๆ‰€ๆœ‰ไฝ ๅทฒ็œ‹ๅˆฐๅนถ็”จไบŽๆทปๅŠ ้ขๅค–ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎ็š„ๅ‚ๆ•ฐใ€‚ +ๅฎƒไปฌ้ƒฝๅ…ฑไบซ็›ธๅŒ็š„ๅ‚ๆ•ฐ๏ผŒ็”จไบŽไฝ ๅทฒ็œ‹ๅˆฐ็š„้ขๅค–ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ /// /// note | ๆŠ€ๆœฏ็ป†่Š‚ -ๅฝ“ไฝ ไปŽ `fastapi` ๅฏผๅ…ฅ `Query`ใ€`Path` ๅ’Œๅ…ถไป–ๅŒ็ฑปๅฏน่ฑกๆ—ถ๏ผŒๅฎƒไปฌๅฎž้™…ไธŠๆ˜ฏๅ‡ฝๆ•ฐใ€‚ +ๅฝ“ไฝ ไปŽ `fastapi` ๅฏผๅ…ฅ `Query`ใ€`Path` ๅ’Œๅ…ถไป–ๅฏน่ฑกๆ—ถ๏ผŒๅฎƒไปฌๅฎž้™…ไธŠๆ˜ฏๅ‡ฝๆ•ฐใ€‚ -ๅฝ“่ขซ่ฐƒ็”จๆ—ถ๏ผŒๅฎƒไปฌ่ฟ”ๅ›žๅŒๅ็ฑป็š„ๅฎžไพ‹ใ€‚ +ๅฝ“่ขซ่ฐƒ็”จๆ—ถ๏ผŒๅฎƒไปฌไผš่ฟ”ๅ›žๅŒๅ็ฑป็š„ๅฎžไพ‹ใ€‚ -ๅฆ‚ๆญค๏ผŒไฝ ๅฏผๅ…ฅ `Query` ่ฟ™ไธชๅ‡ฝๆ•ฐใ€‚ๅฝ“ไฝ ่ฐƒ็”จๅฎƒๆ—ถ๏ผŒๅฎƒๅฐ†่ฟ”ๅ›žไธ€ไธชๅŒๆ ทๅ‘ฝๅไธบ `Query` ็š„็ฑป็š„ๅฎžไพ‹ใ€‚ +ไนŸๅฐฑๆ˜ฏ่ฏด๏ผŒไฝ ๅฏผๅ…ฅ็š„ๆ˜ฏๅ‡ฝๆ•ฐ `Query`ใ€‚ๅฝ“ไฝ ่ฐƒ็”จๅฎƒๆ—ถ๏ผŒๅฎƒไผš่ฟ”ๅ›žไธ€ไธชๅŒๅ็š„ `Query` ็ฑป็š„ๅฎžไพ‹ใ€‚ -ๅ› ไธบไฝฟ็”จไบ†่ฟ™ไบ›ๅ‡ฝๆ•ฐ๏ผˆ่€Œไธๆ˜ฏ็›ดๆŽฅไฝฟ็”จ็ฑป๏ผ‰๏ผŒๆ‰€ไปฅไฝ ็š„็ผ–่พ‘ๅ™จไธไผšๆ ‡่ฎฐๆœ‰ๅ…ณๅ…ถ็ฑปๅž‹็š„้”™่ฏฏใ€‚ +ไน‹ๆ‰€ไปฅไฝฟ็”จ่ฟ™ไบ›ๅ‡ฝๆ•ฐ๏ผˆ่€Œไธๆ˜ฏ็›ดๆŽฅไฝฟ็”จ็ฑป๏ผ‰๏ผŒๆ˜ฏไธบไบ†่ฎฉไฝ ็š„็ผ–่พ‘ๅ™จไธ่ฆๅ› ไธบๅฎƒไปฌ็š„็ฑปๅž‹่€Œๆ ‡่ฎฐ้”™่ฏฏใ€‚ -่ฟ™ๆ ท๏ผŒไฝ ๅฏไปฅไฝฟ็”จๅธธ่ง„็š„็ผ–่พ‘ๅ™จๅ’Œ็ผ–็ ๅทฅๅ…ท๏ผŒ่€Œไธๅฟ…ๆทปๅŠ ่‡ชๅฎšไน‰้…็ฝฎๆฅๅฟฝ็•ฅ่ฟ™ไบ›้”™่ฏฏใ€‚ +่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅไฝฟ็”จๅธธ่ง„็š„็ผ–่พ‘ๅ™จๅ’Œ็ผ–็ ๅทฅๅ…ท๏ผŒ่€Œไธๅฟ…ๆทปๅŠ ่‡ชๅฎšไน‰้…็ฝฎๆฅๅฟฝ็•ฅ่ฟ™ไบ›้”™่ฏฏใ€‚ /// diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md index ac9df08317..fa4c9514a9 100644 --- a/docs/zh/docs/tutorial/path-params.md +++ b/docs/zh/docs/tutorial/path-params.md @@ -1,10 +1,10 @@ -# ่ทฏๅพ„ๅ‚ๆ•ฐ +# ่ทฏๅพ„ๅ‚ๆ•ฐ { #path-parameters } -FastAPI ๆ”ฏๆŒไฝฟ็”จ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–่ฏญๆณ•ๅฃฐๆ˜Ž**่ทฏๅพ„ๅ‚ๆ•ฐ**๏ผˆ**ๅ˜้‡**๏ผ‰๏ผš +ไฝ ๅฏไปฅไฝฟ็”จไธŽ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–็›ธๅŒ็š„่ฏญๆณ•ๅฃฐๆ˜Ž่ทฏๅพ„โ€œๅ‚ๆ•ฐโ€ๆˆ–โ€œๅ˜้‡โ€๏ผš -{* ../../docs_src/path_params/tutorial001.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} -่ฟ™ๆฎตไปฃ็ ๆŠŠ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ็š„ๅ€ผไผ ้€’็ป™่ทฏๅพ„ๅ‡ฝๆ•ฐ็š„ๅ‚ๆ•ฐ `item_id`ใ€‚ +่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ็š„ๅ€ผไผšไฝœไธบๅ‚ๆ•ฐ `item_id` ไผ ้€’็ป™ไฝ ็š„ๅ‡ฝๆ•ฐใ€‚ ่ฟ่กŒ็คบไพ‹ๅนถ่ฎฟ้—ฎ http://127.0.0.1:8000/items/foo๏ผŒๅฏ่Žทๅพ—ๅฆ‚ไธ‹ๅ“ๅบ”๏ผš @@ -12,11 +12,11 @@ FastAPI ๆ”ฏๆŒไฝฟ็”จ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–่ฏญๆณ•ๅฃฐๆ˜Ž**่ทฏๅพ„ๅ‚ๆ•ฐ**๏ผˆ** {"item_id":"foo"} ``` -## ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹ +## ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹ { #path-parameters-with-types } -ไฝฟ็”จ Python ๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃ๏ผŒๅฃฐๆ˜Ž่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไธญ่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹ใ€‚ +ไฝฟ็”จ Python ๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃ๏ผŒๅฃฐๆ˜Ž่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไธญ่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹๏ผš -{* ../../docs_src/path_params/tutorial002.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} ๆœฌไพ‹ๆŠŠ `item_id` ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `int`ใ€‚ @@ -26,7 +26,7 @@ FastAPI ๆ”ฏๆŒไฝฟ็”จ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–่ฏญๆณ•ๅฃฐๆ˜Ž**่ทฏๅพ„ๅ‚ๆ•ฐ**๏ผˆ** /// -## ๆ•ฐๆฎ่ฝฌๆข +## ๆ•ฐๆฎ่ฝฌๆข { #data-conversion } ่ฟ่กŒ็คบไพ‹ๅนถ่ฎฟ้—ฎ http://127.0.0.1:8000/items/3๏ผŒ่ฟ”ๅ›ž็š„ๅ“ๅบ”ๅฆ‚ไธ‹๏ผš @@ -42,56 +42,57 @@ FastAPI ๆ”ฏๆŒไฝฟ็”จ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–่ฏญๆณ•ๅฃฐๆ˜Ž**่ทฏๅพ„ๅ‚ๆ•ฐ**๏ผˆ** /// -## ๆ•ฐๆฎๆ ก้ชŒ +## ๆ•ฐๆฎๆ ก้ชŒ { #data-validation } ้€š่ฟ‡ๆต่งˆๅ™จ่ฎฟ้—ฎ http://127.0.0.1:8000/items/foo๏ผŒๆŽฅๆ”ถๅฆ‚ไธ‹ HTTP ้”™่ฏฏไฟกๆฏ๏ผš ```JSON { - "detail": [ - { - "loc": [ - "path", - "item_id" - ], - "msg": "value is not a valid integer", - "type": "type_error.integer" - } - ] + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] } ``` -่ฟ™ๆ˜ฏๅ› ไธบ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ็š„ๅ€ผ ๏ผˆ`"foo"`๏ผ‰็š„็ฑปๅž‹ไธๆ˜ฏ `int`ใ€‚ +่ฟ™ๆ˜ฏๅ› ไธบ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ็š„ๅ€ผ๏ผˆ`"foo"`๏ผ‰็š„็ฑปๅž‹ไธๆ˜ฏ `int`ใ€‚ -ๅ€ผ็š„็ฑปๅž‹ไธๆ˜ฏ `int ` ่€Œๆ˜ฏๆตฎ็‚นๆ•ฐ๏ผˆ`float`๏ผ‰ๆ—ถไนŸไผšๆ˜พ็คบๅŒๆ ท็š„้”™่ฏฏ๏ผŒๆฏ”ๅฆ‚๏ผš http://127.0.0.1:8000/items/4.2ใ€‚ +ๅ€ผ็š„็ฑปๅž‹ไธๆ˜ฏ `int` ่€Œๆ˜ฏๆตฎ็‚นๆ•ฐ๏ผˆ`float`๏ผ‰ๆ—ถไนŸไผšๆ˜พ็คบๅŒๆ ท็š„้”™่ฏฏ๏ผŒๆฏ”ๅฆ‚๏ผš http://127.0.0.1:8000/items/4.2 /// check | ๆฃ€ๆŸฅ -**FastAPI** ไฝฟ็”จ Python ็ฑปๅž‹ๅฃฐๆ˜Žๅฎž็Žฐไบ†ๆ•ฐๆฎๆ ก้ชŒใ€‚ +**FastAPI** ไฝฟ็”จๅŒๆ ท็š„ Python ็ฑปๅž‹ๅฃฐๆ˜Žๅฎž็Žฐไบ†ๆ•ฐๆฎๆ ก้ชŒใ€‚ -ๆณจๆ„๏ผŒไธŠ้ข็š„้”™่ฏฏๆธ…ๆ™ฐๅœฐๆŒ‡ๅ‡บไบ†ๆœช้€š่ฟ‡ๆ ก้ชŒ็š„ๅ…ทไฝ“ๅŽŸๅ› ใ€‚ +ๆณจๆ„๏ผŒไธŠ้ข็š„้”™่ฏฏๆธ…ๆ™ฐๅœฐๆŒ‡ๅ‡บไบ†ๆœช้€š่ฟ‡ๆ ก้ชŒ็š„ๅ…ทไฝ“ไฝ็ฝฎใ€‚ ่ฟ™ๅœจๅผ€ๅ‘่ฐƒ่ฏ•ไธŽ API ไบคไบ’็š„ไปฃ็ ๆ—ถ้žๅธธๆœ‰็”จใ€‚ /// -## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆ–‡ๆกฃ { #documentation } -่ฎฟ้—ฎ http://127.0.0.1:8000/docs๏ผŒๆŸฅ็œ‹่‡ชๅŠจ็”Ÿๆˆ็š„ API ๆ–‡ๆกฃ๏ผš +่ฎฟ้—ฎ http://127.0.0.1:8000/docs๏ผŒๆŸฅ็œ‹่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผš /// check | ๆฃ€ๆŸฅ -่ฟ˜ๆ˜ฏไฝฟ็”จ Python ็ฑปๅž‹ๅฃฐๆ˜Ž๏ผŒ**FastAPI** ๆไพ›ไบ†๏ผˆ้›†ๆˆ Swagger UI ็š„๏ผ‰API ๆ–‡ๆกฃใ€‚ +่ฟ˜ๆ˜ฏไฝฟ็”จ Python ็ฑปๅž‹ๅฃฐๆ˜Ž๏ผŒ**FastAPI** ๆไพ›ไบ†๏ผˆ้›†ๆˆ Swagger UI ็š„๏ผ‰่‡ชๅŠจไบคไบ’ๅผๆ–‡ๆกฃใ€‚ ๆณจๆ„๏ผŒ่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹ๆ˜ฏๆ•ดๆ•ฐใ€‚ /// -## ๅŸบไบŽๆ ‡ๅ‡†็š„ๅฅฝๅค„๏ผŒๅค‡้€‰ๆ–‡ๆกฃ +## ๅŸบไบŽๆ ‡ๅ‡†็š„ๅฅฝๅค„๏ผŒๅค‡้€‰ๆ–‡ๆกฃ { #standards-based-benefits-alternative-documentation } -**FastAPI** ไฝฟ็”จ OpenAPI ็”Ÿๆˆๆฆ‚ๅ›พ๏ผŒๆ‰€ไปฅ่ƒฝๅ…ผๅฎนๅพˆๅคšๅทฅๅ…ทใ€‚ +**FastAPI** ไฝฟ็”จ OpenAPI ็”Ÿๆˆๆฆ‚ๅ›พ๏ผŒๆ‰€ไปฅ่ƒฝๅ…ผๅฎนๅพˆๅคšๅทฅๅ…ทใ€‚ ๅ› ๆญค๏ผŒ**FastAPI** ่ฟ˜ๅ†…็ฝฎไบ† ReDoc ็”Ÿๆˆ็š„ๅค‡้€‰ API ๆ–‡ๆกฃ๏ผŒๅฏๅœจๆญคๆŸฅ็œ‹ http://127.0.0.1:8000/redoc๏ผš @@ -99,15 +100,15 @@ FastAPI ๆ”ฏๆŒไฝฟ็”จ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–่ฏญๆณ•ๅฃฐๆ˜Ž**่ทฏๅพ„ๅ‚ๆ•ฐ**๏ผˆ** ๅŒๆ ท๏ผŒ่ฟ˜ๆœ‰ๅพˆๅคšๅ…ผๅฎนๅทฅๅ…ท๏ผŒๅŒ…ๆ‹ฌๅคš็ง่ฏญ่จ€็š„ไปฃ็ ็”Ÿๆˆๅทฅๅ…ทใ€‚ -## Pydantic +## Pydantic { #pydantic } FastAPI ๅ……ๅˆ†ๅœฐๅˆฉ็”จไบ† Pydantic ็š„ไผ˜ๅŠฟ๏ผŒ็”จๅฎƒๅœจๅŽๅฐๆ ก้ชŒๆ•ฐๆฎใ€‚ไผ—ๆ‰€ๅ‘จ็Ÿฅ๏ผŒPydantic ๆ“…้•ฟ็š„ๅฐฑๆ˜ฏๆ•ฐๆฎๆ ก้ชŒใ€‚ ๅŒๆ ท๏ผŒ`str`ใ€`float`ใ€`bool` ไปฅๅŠๅพˆๅคšๅคๅˆๆ•ฐๆฎ็ฑปๅž‹้ƒฝๅฏไปฅไฝฟ็”จ็ฑปๅž‹ๅฃฐๆ˜Žใ€‚ -ไธ‹ไธ€็ซ ไป‹็ป่ฏฆ็ป†ๅ†…ๅฎนใ€‚ +ๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไผšไป‹็ปๅ…ถไธญ็š„ๅฅฝๅ‡ ็งใ€‚ -## ้กบๅบๅพˆ้‡่ฆ +## ้กบๅบๅพˆ้‡่ฆ { #order-matters } ๆœ‰ๆ—ถ๏ผŒ*่ทฏๅพ„ๆ“ไฝœ*ไธญ็š„่ทฏๅพ„ๆ˜ฏๅ†™ๆญป็š„ใ€‚ @@ -117,63 +118,63 @@ FastAPI ๅ……ๅˆ†ๅœฐๅˆฉ็”จไบ† `Enum` ็ฑปๅž‹ๆŽฅๆ”ถ้ข„่ฎพ็š„*่ทฏๅพ„ๅ‚ๆ•ฐ*ใ€‚ +{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} -### ๅˆ›ๅปบ `Enum` ็ฑป +็”ฑไบŽ่ทฏๅพ„้ฆ–ๅ…ˆๅŒน้…๏ผŒๅง‹็ปˆไผšไฝฟ็”จ็ฌฌไธ€ไธชๅฎšไน‰็š„ใ€‚ -ๅฏผๅ…ฅ `Enum` ๅนถๅˆ›ๅปบ็ปงๆ‰ฟ่‡ช `str` ๅ’Œ `Enum` ็š„ๅญ็ฑปใ€‚ +## ้ข„่ฎพๅ€ผ { #predefined-values } -้€š่ฟ‡ไปŽ `str` ็ปงๆ‰ฟ๏ผŒAPI ๆ–‡ๆกฃๅฐฑ่ƒฝๆŠŠๅ€ผ็š„็ฑปๅž‹ๅฎšไน‰ไธบ**ๅญ—็ฌฆไธฒ**๏ผŒๅนถไธ”่ƒฝๆญฃ็กฎๆธฒๆŸ“ใ€‚ +่ทฏๅพ„ๆ“ไฝœไฝฟ็”จ Python ็š„ `Enum` ็ฑปๅž‹ๆŽฅๆ”ถ้ข„่ฎพ็š„่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ -็„ถๅŽ๏ผŒๅˆ›ๅปบๅŒ…ๅซๅ›บๅฎšๅ€ผ็š„็ฑปๅฑžๆ€ง๏ผŒ่ฟ™ไบ›ๅ›บๅฎšๅ€ผๆ˜ฏๅฏ็”จ็š„ๆœ‰ๆ•ˆๅ€ผ๏ผš +### ๅˆ›ๅปบ `Enum` ็ฑป { #create-an-enum-class } -{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *} +ๅฏผๅ…ฅ `Enum` ๅนถๅˆ›ๅปบ็ปงๆ‰ฟ่‡ช `str` ๅ’Œ `Enum` ็š„ๅญ็ฑปใ€‚ -/// info | ่ฏดๆ˜Ž +้€š่ฟ‡ไปŽ `str` ็ปงๆ‰ฟ๏ผŒAPI ๆ–‡ๆกฃๅฐฑ่ƒฝๆŠŠๅ€ผ็š„็ฑปๅž‹ๅฎšไน‰ไธบ**ๅญ—็ฌฆไธฒ**๏ผŒๅนถไธ”่ƒฝๆญฃ็กฎๆธฒๆŸ“ใ€‚ -Python 3.4 ๅŠไน‹ๅŽ็‰ˆๆœฌๆ”ฏๆŒๆžšไธพ๏ผˆๅณ enums๏ผ‰ใ€‚ +็„ถๅŽ๏ผŒๅˆ›ๅปบๅŒ…ๅซๅ›บๅฎšๅ€ผ็š„็ฑปๅฑžๆ€ง๏ผŒ่ฟ™ไบ›ๅ›บๅฎšๅ€ผๆ˜ฏๅฏ็”จ็š„ๆœ‰ๆ•ˆๅ€ผ๏ผš -/// +{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} /// tip | ๆ็คบ -**AlexNet**ใ€**ResNet**ใ€**LeNet** ๆ˜ฏๆœบๅ™จๅญฆไน ๆจกๅž‹ใ€‚ +**AlexNet**ใ€**ResNet**ใ€**LeNet** ๆ˜ฏๆœบๅ™จๅญฆไน ๆจกๅž‹็š„ๅๅญ—ใ€‚ /// -### ๅฃฐๆ˜Ž*่ทฏๅพ„ๅ‚ๆ•ฐ* +### ๅฃฐๆ˜Ž่ทฏๅพ„ๅ‚ๆ•ฐ { #declare-a-path-parameter } -ไฝฟ็”จ Enum ็ฑป๏ผˆ`ModelName`๏ผ‰ๅˆ›ๅปบไฝฟ็”จ็ฑปๅž‹ๆณจ่งฃ็š„*่ทฏๅพ„ๅ‚ๆ•ฐ*๏ผš +ไฝฟ็”จ Enum ็ฑป๏ผˆ`ModelName`๏ผ‰ๅˆ›ๅปบไฝฟ็”จ็ฑปๅž‹ๆณจ่งฃ็š„่ทฏๅพ„ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/path_params/tutorial005.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} -### ๆŸฅ็œ‹ๆ–‡ๆกฃ +### ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } - API ๆ–‡ๆกฃไผšๆ˜พ็คบ้ข„ๅฎšไน‰*่ทฏๅพ„ๅ‚ๆ•ฐ*็š„ๅฏ็”จๅ€ผ๏ผš +API ๆ–‡ๆกฃไผšๆ˜พ็คบ้ข„ๅฎšไน‰่ทฏๅพ„ๅ‚ๆ•ฐ็š„ๅฏ็”จๅ€ผ๏ผš -### ไฝฟ็”จ Python _ๆžšไธพ็ฑปๅž‹_ +### ไฝฟ็”จ Python ๆžšไธพ { #working-with-python-enumerations } -*่ทฏๅพ„ๅ‚ๆ•ฐ*็š„ๅ€ผๆ˜ฏๆžšไธพ็š„ๅ…ƒ็ด ใ€‚ +่ทฏๅพ„ๅ‚ๆ•ฐ็š„ๅ€ผๆ˜ฏไธ€ไธชๆžšไธพๆˆๅ‘˜ใ€‚ -#### ๆฏ”่พƒ*ๆžšไธพๅ…ƒ็ด * +#### ๆฏ”่พƒๆžšไธพๆˆๅ‘˜ { #compare-enumeration-members } -ๆžšไธพ็ฑป `ModelName` ไธญ็š„*ๆžšไธพๅ…ƒ็ด *ๆ”ฏๆŒๆฏ”่พƒๆ“ไฝœ๏ผš +ๅฏไปฅๅฐ†ๅ…ถไธŽๆžšไธพ็ฑป `ModelName` ไธญ็š„ๆžšไธพๆˆๅ‘˜่ฟ›่กŒๆฏ”่พƒ๏ผš -{* ../../docs_src/path_params/tutorial005.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} -#### ่Žทๅ–*ๆžšไธพๅ€ผ* +#### ่Žทๅ–ๆžšไธพๅ€ผ { #get-the-enumeration-value } -ไฝฟ็”จ `model_name.value` ๆˆ– `your_enum_member.value` ่Žทๅ–ๅฎž้™…็š„ๅ€ผ๏ผˆๆœฌไพ‹ไธญไธบ**ๅญ—็ฌฆไธฒ**๏ผ‰๏ผš +ไฝฟ็”จ `model_name.value` ๆˆ–้€š็”จ็š„ `your_enum_member.value` ่Žทๅ–ๅฎž้™…็š„ๅ€ผ๏ผˆๆœฌไพ‹ไธญไธบ `str`๏ผ‰๏ผš -{* ../../docs_src/path_params/tutorial005.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} /// tip | ๆ็คบ @@ -181,13 +182,13 @@ Python 3.4 ๅŠไน‹ๅŽ็‰ˆๆœฌๆ”ฏๆŒ่งฃๆž** +- ๆ•ฐๆฎ "่งฃๆž" - ๆ•ฐๆฎๆ ก้ชŒ -- API ๆณจ่งฃๅ’Œ API ๆ–‡ๆกฃ +- API ๆณจ่งฃๅ’Œ่‡ชๅŠจๆ–‡ๆกฃ ๅช้œ€่ฆๅฃฐๆ˜Žไธ€ๆฌกๅณๅฏใ€‚ diff --git a/docs/zh/docs/tutorial/query-param-models.md b/docs/zh/docs/tutorial/query-param-models.md index c6a79a71a2..fc691839d5 100644 --- a/docs/zh/docs/tutorial/query-param-models.md +++ b/docs/zh/docs/tutorial/query-param-models.md @@ -1,16 +1,16 @@ -# ๆŸฅ่ฏขๅ‚ๆ•ฐๆจกๅž‹ +# ๆŸฅ่ฏขๅ‚ๆ•ฐๆจกๅž‹ { #query-parameter-models } ๅฆ‚ๆžœไฝ ๆœ‰ไธ€็ป„ๅ…ทๆœ‰็›ธๅ…ณๆ€ง็š„**ๆŸฅ่ฏขๅ‚ๆ•ฐ**๏ผŒไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช **Pydantic ๆจกๅž‹**ๆฅๅฃฐๆ˜Žๅฎƒไปฌใ€‚ ่ฟ™ๅฐ†ๅ…่ฎธไฝ ๅœจ**ๅคšไธชๅœฐๆ–น**ๅŽป**ๅค็”จๆจกๅž‹**๏ผŒๅนถไธ”ไธ€ๆฌกๆ€งไธบๆ‰€ๆœ‰ๅ‚ๆ•ฐๅฃฐๆ˜Ž้ชŒ่ฏๅ’Œๅ…ƒๆ•ฐๆฎใ€‚๐Ÿ˜Ž -/// note +/// note | ๆณจๆ„ FastAPI ไปŽ `0.115.0` ็‰ˆๆœฌๅผ€ๅง‹ๆ”ฏๆŒ่ฟ™ไธช็‰นๆ€งใ€‚๐Ÿค“ /// -## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ +## ไฝฟ็”จ Pydantic ๆจกๅž‹็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ { #query-parameters-with-a-pydantic-model } ๅœจไธ€ไธช **Pydantic ๆจกๅž‹**ไธญๅฃฐๆ˜Žไฝ ้œ€่ฆ็š„**ๆŸฅ่ฏขๅ‚ๆ•ฐ**๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Query`๏ผš @@ -18,7 +18,7 @@ FastAPI ไปŽ `0.115.0` ็‰ˆๆœฌๅผ€ๅง‹ๆ”ฏๆŒ่ฟ™ไธช็‰นๆ€งใ€‚๐Ÿค“ **FastAPI** ๅฐ†ไผšไปŽ่ฏทๆฑ‚็š„**ๆŸฅ่ฏขๅ‚ๆ•ฐ**ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๅฐ†ๅ…ถๆไพ›็ป™ไฝ ๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ -## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } ไฝ ๅฏไปฅๅœจ `/docs` ้กต้ข็š„ UI ไธญๆŸฅ็œ‹ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผš @@ -26,11 +26,11 @@ FastAPI ไปŽ `0.115.0` ็‰ˆๆœฌๅผ€ๅง‹ๆ”ฏๆŒ่ฟ™ไธช็‰นๆ€งใ€‚๐Ÿค“ -## ็ฆๆญข้ขๅค–็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ +## ็ฆๆญข้ขๅค–็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ { #forbid-extra-query-parameters } ๅœจไธ€ไบ›็‰นๆฎŠ็š„ไฝฟ็”จๅœบๆ™ฏไธญ๏ผˆๅฏ่ƒฝไธๆ˜ฏๅพˆๅธธ่ง๏ผ‰๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›**้™ๅˆถ**ไฝ ่ฆๆŽฅๆ”ถ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ -ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ `forbid`๏ผˆๆ„ไธบ็ฆๆญข โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰ไปปไฝ• `extra`๏ผˆๆ„ไธบ้ขๅค–็š„ โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰ๅญ—ๆฎต๏ผš +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ `forbid` ไปปไฝ• `extra` ๅญ—ๆฎต๏ผš {* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} @@ -57,11 +57,11 @@ https://example.com/items/?limit=10&tool=plumbus } ``` -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #summary } ไฝ ๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญๅฃฐๆ˜Ž**ๆŸฅ่ฏขๅ‚ๆ•ฐ**ใ€‚๐Ÿ˜Ž -/// tip +/// tip | ๆ็คบ ๅ‰ง้€่ญฆๅ‘Š๏ผšไฝ ไนŸๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ๆฅๅฃฐๆ˜Ž cookie ๅ’Œ headers๏ผŒไฝ†ไฝ ๅฐ†ๅœจๆœฌๆ•™็จ‹็š„ๅŽ้ข้ƒจๅˆ†้˜…่ฏปๅˆฐ่ฟ™้ƒจๅˆ†ๅ†…ๅฎนใ€‚๐Ÿคซ diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index c2f9a7e9f0..62552e6d08 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -1,142 +1,271 @@ -# ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒ +# ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œๅญ—็ฌฆไธฒๆ ก้ชŒ { #query-parameters-and-string-validations } **FastAPI** ๅ…่ฎธไฝ ไธบๅ‚ๆ•ฐๅฃฐๆ˜Ž้ขๅค–็š„ไฟกๆฏๅ’Œๆ ก้ชŒใ€‚ -่ฎฉๆˆ‘ไปฌไปฅไธ‹้ข็š„ๅบ”็”จ็จ‹ๅบไธบไพ‹๏ผš +่ฎฉๆˆ‘ไปฌไปฅไธ‹้ข็š„ๅบ”็”จไธบไพ‹๏ผš {* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -ๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ็š„็ฑปๅž‹ไธบ `str`๏ผŒ้ป˜่ฎคๅ€ผไธบ `None`๏ผŒๅ› ๆญคๅฎƒๆ˜ฏๅฏ้€‰็š„ใ€‚ +ๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ็š„็ฑปๅž‹ไธบ `str | None`๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ๅฎƒๆ˜ฏ `str` ็ฑปๅž‹๏ผŒไฝ†ไนŸๅฏไปฅๆ˜ฏ `None`ใ€‚ๅ…ถ้ป˜่ฎคๅ€ผ็กฎๅฎžไธบ `None`๏ผŒๆ‰€ไปฅ FastAPI ไผš็Ÿฅ้“ๅฎƒไธๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ -## ้ขๅค–็š„ๆ ก้ชŒ +/// note | ๆณจๆ„ -ๆˆ‘ไปฌๆ‰“็ฎ—ๆทปๅŠ ็บฆๆŸๆกไปถ๏ผšๅณไฝฟ `q` ๆ˜ฏๅฏ้€‰็š„๏ผŒไฝ†ๅช่ฆๆไพ›ไบ†่ฏฅๅ‚ๆ•ฐ๏ผŒๅˆ™่ฏฅๅ‚ๆ•ฐๅ€ผ**ไธ่ƒฝ่ถ…่ฟ‡50ไธชๅญ—็ฌฆ็š„้•ฟๅบฆ**ใ€‚ +FastAPI ไผšๅ› ไธบ้ป˜่ฎคๅ€ผ `= None` ่€Œ็Ÿฅ้“ `q` ็š„ๅ€ผไธๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ -### ๅฏผๅ…ฅ `Query` +ๅฐ†็ฑปๅž‹ๆ ‡ๆณจไธบ `str | None` ่ƒฝ่ฎฉไฝ ็š„็ผ–่พ‘ๅ™จๆไพ›ๆ›ดๅฅฝ็š„่พ…ๅŠฉๅ’Œ้”™่ฏฏๆฃ€ๆต‹ใ€‚ -ไธบๆญค๏ผŒ้ฆ–ๅ…ˆไปŽ `fastapi` ๅฏผๅ…ฅ `Query`๏ผš +/// -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[1] *} +## ้ขๅค–ๆ ก้ชŒ { #additional-validation } -## ไฝฟ็”จ `Query` ไฝœไธบ้ป˜่ฎคๅ€ผ +ๆˆ‘ไปฌๆ‰“็ฎ—ๆทปๅŠ ็บฆๆŸ๏ผšๅณไฝฟ `q` ๆ˜ฏๅฏ้€‰็š„๏ผŒไฝ†ๅช่ฆๆไพ›ไบ†่ฏฅๅ‚ๆ•ฐ๏ผŒ**ๅ…ถ้•ฟๅบฆไธ่ƒฝ่ถ…่ฟ‡ 50 ไธชๅญ—็ฌฆ**ใ€‚ -็Žฐๅœจ๏ผŒๅฐ† `Query` ็”จไฝœๆŸฅ่ฏขๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒๅนถๅฐ†ๅฎƒ็š„ `max_length` ๅ‚ๆ•ฐ่ฎพ็ฝฎไธบ 50๏ผš +### ๅฏผๅ…ฅ `Query` ๅ’Œ `Annotated` { #import-query-and-annotated } -{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *} +ไธบๆญค๏ผŒๅ…ˆๅฏผๅ…ฅ๏ผš -็”ฑไบŽๆˆ‘ไปฌๅฟ…้กป็”จ `Query(default=None)` ๆ›ฟๆข้ป˜่ฎคๅ€ผ `None`๏ผŒ`Query` ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐๅŒๆ ทไนŸๆ˜ฏ็”จไบŽๅฎšไน‰้ป˜่ฎคๅ€ผใ€‚ +- ไปŽ `fastapi` ๅฏผๅ…ฅ `Query` +- ไปŽ `typing` ๅฏผๅ…ฅ `Annotated` -ๆ‰€ไปฅ๏ผš +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | ไฟกๆฏ + +FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌไธญๆทปๅŠ ไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ไฝฟ็”จ๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ็š„็‰ˆๆœฌๆ›ดๆ—ง๏ผŒไฝฟ็”จ `Annotated` ไผšๆŠฅ้”™ใ€‚ + +ๅœจไฝฟ็”จ `Annotated` ไน‹ๅ‰๏ผŒ่ฏท็กฎไฟๅ…ˆ[ๅ‡็บง FastAPI ็‰ˆๆœฌ](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ๅˆฐ่‡ณๅฐ‘ 0.95.1ใ€‚ + +/// + +## ๅœจ `q` ๅ‚ๆ•ฐ็š„็ฑปๅž‹ไธญไฝฟ็”จ `Annotated` { #use-annotated-in-the-type-for-the-q-parameter } + +่ฟ˜่ฎฐๅพ—ๆˆ‘ไน‹ๅ‰ๅœจ[Python ็ฑปๅž‹็ฎ€ไป‹](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}ไธญ่ฏด่ฟ‡ๅฏไปฅ็”จ `Annotated` ็ป™ๅ‚ๆ•ฐๆทปๅŠ ๅ…ƒๆ•ฐๆฎๅ—๏ผŸ + +็Žฐๅœจๆญฃๆ˜ฏไธŽ FastAPI ๆญ้…ไฝฟ็”จๅฎƒ็š„ๆ—ถๅ€™ใ€‚๐Ÿš€ + +ๆˆ‘ไปฌไน‹ๅ‰็š„็ฑปๅž‹ๆ ‡ๆณจๆ˜ฏ๏ผš + +//// tab | Python 3.10+ + +```Python +q: str | None = None +``` + +//// + +//// tab | Python 3.9+ ```Python -q: Union[str, None] = Query(default=None) +q: Union[str, None] = None ``` -...ไฝฟๅพ—ๅ‚ๆ•ฐๅฏ้€‰๏ผŒ็ญ‰ๅŒไบŽ๏ผš +//// + +ๆˆ‘ไปฌ่ฆๅš็š„ๆ˜ฏ็”จ `Annotated` ๆŠŠๅฎƒๅŒ…่ตทๆฅ๏ผŒๅ˜ๆˆ๏ผš + +//// tab | Python 3.10+ ```Python -q: str = None +q: Annotated[str | None] = None ``` -ไฝ†ๆ˜ฏ `Query` ๆ˜พๅผๅœฐๅฐ†ๅ…ถๅฃฐๆ˜ŽไธบๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ +//// -็„ถๅŽ๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ†ๆ›ดๅคš็š„ๅ‚ๆ•ฐไผ ้€’็ป™ `Query`ใ€‚ๅœจๆœฌไพ‹ไธญ๏ผŒ้€‚็”จไบŽๅญ—็ฌฆไธฒ็š„ `max_length` ๅ‚ๆ•ฐ๏ผš +//// tab | Python 3.9+ ```Python -q: Union[str, None] = Query(default=None, max_length=50) +q: Annotated[Union[str, None]] = None ``` -ๅฐ†ไผšๆ ก้ชŒๆ•ฐๆฎ๏ผŒๅœจๆ•ฐๆฎๆ— ๆ•ˆๆ—ถๅฑ•็คบๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏ๏ผŒๅนถๅœจ OpenAPI ๆจกๅผ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญ่ฎฐๅฝ•่ฏฅๅ‚โ€‹โ€‹ๆ•ฐใ€‚ +//// -## ๆทปๅŠ ๆ›ดๅคšๆ ก้ชŒ +่ฟ™ไธค็งๅ†™ๆณ•ๅซไน‰็›ธๅŒ๏ผŒ`q` ๆ˜ฏไธ€ไธชๅฏไปฅๆ˜ฏ `str` ๆˆ– `None` ็š„ๅ‚ๆ•ฐ๏ผŒ้ป˜่ฎคๆ˜ฏ `None`ใ€‚ -ไฝ ่ฟ˜ๅฏไปฅๆทปๅŠ  `min_length` ๅ‚ๆ•ฐ๏ผš +็Žฐๅœจ่ฟ›ๅ…ฅๆ›ดๆœ‰่ถฃ็š„้ƒจๅˆ†ใ€‚๐ŸŽ‰ -{* ../../docs_src/query_params_str_validations/tutorial003.py hl[10] *} +## ๅœจ `q` ็š„ `Annotated` ไธญๆทปๅŠ  `Query` { #add-query-to-annotated-in-the-q-parameter } -## ๆทปๅŠ ๆญฃๅˆ™่กจ่พพๅผ +ๆœ‰ไบ† `Annotated` ไน‹ๅŽ๏ผŒๆˆ‘ไปฌๅฐฑๅฏไปฅๆ”พๅ…ฅๆ›ดๅคšไฟกๆฏ๏ผˆๆœฌไพ‹ไธญๆ˜ฏ้ขๅค–็š„ๆ ก้ชŒ๏ผ‰ใ€‚ๅœจ `Annotated` ไธญๆทปๅŠ  `Query`๏ผŒๅนถๆŠŠๅ‚ๆ•ฐ `max_length` ่ฎพไธบ `50`๏ผš -ไฝ ๅฏไปฅๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐๅ€ผๅฟ…้กปๅŒน้…็š„ๆญฃๅˆ™่กจ่พพๅผ๏ผš +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} -{* ../../docs_src/query_params_str_validations/tutorial004.py hl[11] *} +ๆณจๆ„้ป˜่ฎคๅ€ผไพ็„ถๆ˜ฏ `None`๏ผŒๆ‰€ไปฅ่ฏฅๅ‚ๆ•ฐไปๆ˜ฏๅฏ้€‰็š„ใ€‚ -่ฟ™ไธชๆŒ‡ๅฎš็š„ๆญฃๅˆ™่กจ่พพๅผ้€š่ฟ‡ไปฅไธ‹่ง„ๅˆ™ๆฃ€ๆŸฅๆŽฅๆ”ถๅˆฐ็š„ๅ‚ๆ•ฐๅ€ผ๏ผš +ไฝ†็ŽฐๅœจๆŠŠ `Query(max_length=50)` ๆ”พๅˆฐ `Annotated` ้‡Œ๏ผŒๆˆ‘ไปฌๅฐฑๅœจๅ‘Š่ฏ‰ FastAPI๏ผŒ่ฟ™ไธชๅ€ผ้œ€่ฆ**้ขๅค–ๆ ก้ชŒ**๏ผŒๆœ€ๅคง้•ฟๅบฆไธบ 50 ไธชๅญ—็ฌฆใ€‚๐Ÿ˜Ž -* `^`๏ผšไปฅ่ฏฅ็ฌฆๅทไน‹ๅŽ็š„ๅญ—็ฌฆๅผ€ๅคด๏ผŒ็ฌฆๅทไน‹ๅ‰ๆฒกๆœ‰ๅญ—็ฌฆใ€‚ -* `fixedquery`: ๅ€ผ็ฒพ็กฎๅœฐ็ญ‰ไบŽ `fixedquery`ใ€‚ -* `$`: ๅˆฐๆญค็ป“ๆŸ๏ผŒๅœจ `fixedquery` ไน‹ๅŽๆฒกๆœ‰ๆ›ดๅคšๅญ—็ฌฆใ€‚ +/// tip | ๆ็คบ -ๅฆ‚ๆžœไฝ ๅฏนๆ‰€ๆœ‰็š„่ฟ™ไบ›**ใ€Œๆญฃๅˆ™่กจ่พพๅผใ€**ๆฆ‚ๅฟตๆ„Ÿๅˆฐ่ฟท่Œซ๏ผŒ่ฏทไธ่ฆๆ‹…ๅฟƒใ€‚ๅฏนไบŽ่ฎธๅคšไบบๆฅ่ฏด่ฟ™้ƒฝๆ˜ฏไธ€ไธชๅ›ฐ้šพ็š„ไธป้ข˜ใ€‚ไฝ ไป็„ถๅฏไปฅๅœจๆ— ้œ€ๆญฃๅˆ™่กจ่พพๅผ็š„ๆƒ…ๅ†ตไธ‹ๅšๅพˆๅคšไบ‹ๆƒ…ใ€‚ +่ฟ™้‡Œ็”จ็š„ๆ˜ฏ `Query()`๏ผŒๅ› ไธบ่ฟ™ๆ˜ฏไธ€ไธช**ๆŸฅ่ฏขๅ‚ๆ•ฐ**ใ€‚็จๅŽๆˆ‘ไปฌ่ฟ˜ไผš็œ‹ๅˆฐ `Path()`ใ€`Body()`ใ€`Header()` ๅ’Œ `Cookie()`๏ผŒๅฎƒไปฌไนŸๆŽฅๅ—ไธŽ `Query()` ็›ธๅŒ็š„ๅ‚ๆ•ฐใ€‚ -ไฝ†ๆ˜ฏ๏ผŒไธ€ๆ—ฆไฝ ้œ€่ฆ็”จๅˆฐๅนถๅŽปๅญฆไน ๅฎƒไปฌๆ—ถ๏ผŒ่ฏทไบ†่งฃไฝ ๅทฒ็ปๅฏไปฅๅœจ **FastAPI** ไธญ็›ดๆŽฅไฝฟ็”จๅฎƒไปฌใ€‚ +/// -## ้ป˜่ฎคๅ€ผ +FastAPI ็Žฐๅœจไผš๏ผš -ไฝ ๅฏไปฅๅ‘ `Query` ็š„็ฌฌไธ€ไธชๅ‚ๆ•ฐไผ ๅ…ฅ `None` ็”จไฝœๆŸฅ่ฏขๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒไปฅๅŒๆ ท็š„ๆ–นๅผไฝ ไนŸๅฏไปฅไผ ้€’ๅ…ถไป–้ป˜่ฎคๅ€ผใ€‚ +- ๅฏนๆ•ฐๆฎ่ฟ›่กŒ**ๆ ก้ชŒ**๏ผŒ็กฎไฟๆœ€ๅคง้•ฟๅบฆไธบ 50 ไธชๅญ—็ฌฆ +- ๅฝ“ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถๅ‘ๅฎขๆˆท็ซฏๅฑ•็คบ**ๆธ…ๆ™ฐ็š„้”™่ฏฏ** +- ๅœจ OpenAPI ๆจกๅผ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญ**่ฎฐๅฝ•**่ฏฅๅ‚ๆ•ฐ๏ผˆๅ› ๆญคไผšๅ‡บ็Žฐๅœจ**่‡ชๅŠจๆ–‡ๆกฃ UI** ไธญ๏ผ‰ -ๅ‡่ฎพไฝ ๆƒณ่ฆๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผŒไฝฟๅ…ถ `min_length` ไธบ `3`๏ผŒๅนถไธ”้ป˜่ฎคๅ€ผไธบ `fixedquery`๏ผš +## ๅฆไธ€็ง๏ผˆๆ—ง็š„๏ผ‰ๆ–นๅผ๏ผšๆŠŠ `Query` ไฝœไธบ้ป˜่ฎคๅ€ผ { #alternative-old-query-as-the-default-value } -{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *} +ๆ—ฉๆœŸ็‰ˆๆœฌ็š„ FastAPI๏ผˆ0.95.0 ไน‹ๅ‰๏ผ‰่ฆๆฑ‚ไฝ ๆŠŠ `Query` ไฝœไธบๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆ”พๅœจ `Annotated` ้‡Œใ€‚ไฝ ๅพˆๅฏ่ƒฝไผšๅœจๅˆซๅค„็œ‹ๅˆฐ่ฟ™็งๅ†™ๆณ•๏ผŒๆ‰€ไปฅๆˆ‘ไนŸ็ป™ไฝ ่งฃ้‡Šไธ€ไธ‹ใ€‚ -/// note +/// tip | ๆ็คบ -ๅ…ทๆœ‰้ป˜่ฎคๅ€ผ่ฟ˜ไผšไฝฟ่ฏฅๅ‚ๆ•ฐๆˆไธบๅฏ้€‰ๅ‚ๆ•ฐใ€‚ +ๅฏนไบŽๆ–ฐไปฃ็ ไปฅๅŠๅœจๅฏ่ƒฝ็š„ๆƒ…ๅ†ตไธ‹๏ผŒ่ฏทๆŒ‰ไธŠๆ–‡ๆ‰€่ฟฐไฝฟ็”จ `Annotated`ใ€‚ๅฎƒๆœ‰ๅคš้กนไผ˜ๅŠฟ๏ผˆๅฆ‚ไธ‹ๆ‰€่ฟฐ๏ผ‰๏ผŒๆฒกๆœ‰ๅŠฃๅŠฟใ€‚๐Ÿฐ /// -## ๅฃฐๆ˜Žไธบๅฟ…้œ€ๅ‚ๆ•ฐ +ๅƒ่ฟ™ๆ ทๆŠŠ `Query()` ไฝœไธบๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒๅนถๆŠŠๅ‚ๆ•ฐ `max_length` ่ฎพไธบ 50๏ผš -ๅฝ“ๆˆ‘ไปฌไธ้œ€่ฆๅฃฐๆ˜Ž้ขๅค–็š„ๆ ก้ชŒๆˆ–ๅ…ƒๆ•ฐๆฎๆ—ถ๏ผŒๅช้œ€ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผๅฐฑๅฏไปฅไฝฟ `q` ๅ‚ๆ•ฐๆˆไธบๅฟ…้œ€ๅ‚ๆ•ฐ๏ผŒไพ‹ๅฆ‚๏ผš +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +็”ฑไบŽ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผˆไธไฝฟ็”จ `Annotated`๏ผ‰ๆˆ‘ไปฌๅฟ…้กปๆŠŠๅ‡ฝๆ•ฐไธญ็š„้ป˜่ฎคๅ€ผ `None` ๆ›ฟๆขไธบ `Query()`๏ผŒๅ› ๆญค้œ€่ฆ้€š่ฟ‡ๅ‚ๆ•ฐ `Query(default=None)` ๆฅ่ฎพ็ฝฎ้ป˜่ฎคๅ€ผ๏ผŒๅฎƒ่ตทๅˆฐๅŒๆ ท็š„ไฝœ็”จ๏ผˆ่‡ณๅฐ‘ๅฏน FastAPI ๆฅ่ฏด๏ผ‰ใ€‚ + +ๆ‰€ไปฅ๏ผš ```Python -q: str +q: str | None = Query(default=None) ``` -ไปฃๆ›ฟ๏ผš +โ€ฆโ€ฆไผš่ฎฉๅ‚ๆ•ฐๅ˜ๆˆๅฏ้€‰๏ผŒ้ป˜่ฎคๅ€ผไธบ `None`๏ผŒ็ญ‰ๅŒไบŽ๏ผš ```Python -q: Union[str, None] = None +q: str | None = None +``` + +ไฝ†ไฝฟ็”จ `Query` ็š„็‰ˆๆœฌไผšๆ˜พๅผๆŠŠๅฎƒๅฃฐๆ˜Žไธบไธ€ไธชๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ + +็„ถๅŽ๏ผŒๆˆ‘ไปฌๅฏไปฅๅ‘ `Query` ไผ ๅ…ฅๆ›ดๅคšๅ‚ๆ•ฐใ€‚ๆœฌไพ‹ไธญๆ˜ฏ้€‚็”จไบŽๅญ—็ฌฆไธฒ็š„ `max_length` ๅ‚ๆ•ฐ๏ผš + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +่ฟ™ไผšๆ ก้ชŒๆ•ฐๆฎใ€ๅœจๆ•ฐๆฎๆ— ๆ•ˆๆ—ถๅฑ•็คบๆธ…ๆ™ฐ็š„้”™่ฏฏ๏ผŒๅนถๅœจ OpenAPI ๆจกๅผ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญ่ฎฐๅฝ•่ฏฅๅ‚ๆ•ฐใ€‚ + +### ๅœจ้ป˜่ฎคๅ€ผไธญไฝฟ็”จ `Query` ๆˆ–ๅœจ `Annotated` ไธญไฝฟ็”จ `Query` { #query-as-the-default-value-or-in-annotated } + +ๆณจๆ„๏ผŒๅฝ“ไฝ ๅœจ `Annotated` ไธญไฝฟ็”จ `Query` ๆ—ถ๏ผŒไธ่ƒฝๅ†็ป™ `Query` ไผ  `default` ๅ‚ๆ•ฐใ€‚ + +็›ธๅ๏ผŒๅบ”ไฝฟ็”จๅ‡ฝๆ•ฐๅ‚ๆ•ฐๆœฌ่บซ็š„ๅฎž้™…้ป˜่ฎคๅ€ผใ€‚ๅฆๅˆ™ไผšไธไธ€่‡ดใ€‚ + +ไพ‹ๅฆ‚๏ผŒไธ‹้ข่ฟ™ๆ ทๆ˜ฏไธๅ…่ฎธ็š„๏ผš + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +โ€ฆโ€ฆๅ› ไธบไธๆธ…ๆฅš้ป˜่ฎคๅ€ผๅบ”่ฏฅๆ˜ฏ `"rick"` ่ฟ˜ๆ˜ฏ `"morty"`ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅบ”่ฏฅ่ฟ™ๆ ท็”จ๏ผˆๆŽจ่๏ผ‰๏ผš + +```Python +q: Annotated[str, Query()] = "rick" ``` -ไฝ†ๆ˜ฏ็Žฐๅœจๆˆ‘ไปฌๆญฃๅœจ็”จ `Query` ๅฃฐๆ˜Žๅฎƒ๏ผŒไพ‹ๅฆ‚๏ผš +โ€ฆโ€ฆๆˆ–่€…ๅœจๆ—งไปฃ็ ๅบ“ไธญไฝ ไผš่งๅˆฐ๏ผš ```Python -q: Union[str, None] = Query(default=None, min_length=3) +q: str = Query(default="rick") ``` -ๅ› ๆญค๏ผŒๅฝ“ไฝ ๅœจไฝฟ็”จ `Query` ไธ”้œ€่ฆๅฃฐๆ˜Žไธ€ไธชๅ€ผๆ˜ฏๅฟ…้œ€็š„ๆ—ถ๏ผŒๅช้œ€ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ‚ๆ•ฐ๏ผš +### `Annotated` ็š„ไผ˜ๅŠฟ { #advantages-of-annotated } + +**ๆŽจ่ไฝฟ็”จ `Annotated`**๏ผŒ่€Œไธๆ˜ฏๆŠŠ `Query` ๆ”พๅœจๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ้‡Œ๏ผŒ่ฟ™ๆ ทๅšๅœจๅคšๆ–น้ข้ƒฝ**ๆ›ดๅฅฝ**ใ€‚๐Ÿค“ + +ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„**้ป˜่ฎคๅ€ผ**ๅฐฑๆ˜ฏ**็œŸๆญฃ็š„้ป˜่ฎคๅ€ผ**๏ผŒ่ฟ™ไธŽ Python ็š„็›ด่ง‰ๆ›ดไธ€่‡ดใ€‚๐Ÿ˜Œ + +ไฝ ๅฏไปฅๅœจ**ๅ…ถไป–ๅœฐๆ–น**ไธ้€š่ฟ‡ FastAPI **็›ดๆŽฅ่ฐƒ็”จ**่ฟ™ไธชๅ‡ฝๆ•ฐ๏ผŒ่€Œไธ”ๅฎƒไผš**ๆŒ‰้ข„ๆœŸๅทฅไฝœ**ใ€‚ๅฆ‚ๆžœๆœ‰**ๅฟ…ๅกซ**ๅ‚ๆ•ฐ๏ผˆๆฒกๆœ‰้ป˜่ฎคๅ€ผ๏ผ‰๏ผŒไฝ ็š„**็ผ–่พ‘ๅ™จ**ไผšๆŠฅ้”™ๆ็คบ๏ผ›ๅฆ‚ๆžœๅœจ่ฟ่กŒๆ—ถๆฒกๆœ‰ไผ ๅ…ฅๅฟ…ๅกซๅ‚ๆ•ฐ๏ผŒ**Python** ไนŸไผšๆŠฅ้”™ใ€‚ + +ๅฝ“ไฝ ไธไฝฟ็”จ `Annotated` ่€Œๆ˜ฏไฝฟ็”จ**๏ผˆๆ—ง็š„๏ผ‰้ป˜่ฎคๅ€ผ้ฃŽๆ ผ**ๆ—ถ๏ผŒๅฆ‚ๆžœไฝ ๅœจ**ๅ…ถไป–ๅœฐๆ–น**ไธ้€š่ฟ‡ FastAPI ่ฐƒ็”จ่ฏฅๅ‡ฝๆ•ฐ๏ผŒไฝ ๅฟ…้กป**่ฎฐๅพ—**็ป™ๅ‡ฝๆ•ฐไผ ๅ‚๏ผŒๅฆๅˆ™ๅพ—ๅˆฐ็š„ๅ€ผไผšๅ’Œ้ข„ๆœŸไธๅŒ๏ผˆไพ‹ๅฆ‚ๅพ—ๅˆฐ `QueryInfo` ไน‹็ฑป็š„ๅฏน่ฑก่€Œไธๆ˜ฏ `str`๏ผ‰ใ€‚่€Œไฝ ็š„็ผ–่พ‘ๅ™จไธไผšๆŠฅ้”™๏ผŒPython ไนŸไธไผšๅœจ่ฐƒ็”จๆ—ถๆŠฅ้”™๏ผŒๅชๆœ‰ๅœจๅ‡ฝๆ•ฐๅ†…้ƒจ็š„ๆ“ไฝœๅ‡บ้”™ๆ—ถๆ‰ไผšๆšด้œฒ้—ฎ้ข˜ใ€‚ + +็”ฑไบŽ `Annotated` ๅฏไปฅๅŒ…ๅซๅคšไธชๅ…ƒๆ•ฐๆฎๆ ‡ๆณจ๏ผŒไฝ ็”š่‡ณๅฏไปฅ็”จๅŒไธ€ไธชๅ‡ฝๆ•ฐไธŽๅ…ถไป–ๅทฅๅ…ท้…ๅˆ๏ผŒไพ‹ๅฆ‚ Typerใ€‚๐Ÿš€ + +## ๆทปๅŠ ๆ›ดๅคšๆ ก้ชŒ { #add-more-validations } + +ไฝ ่ฟ˜ๅฏไปฅๆทปๅŠ  `min_length` ๅ‚ๆ•ฐ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## ๆทปๅŠ ๆญฃๅˆ™่กจ่พพๅผ { #add-regular-expressions } + +ไฝ ๅฏไปฅๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐๅฟ…้กปๅŒน้…็š„ ๆญฃๅˆ™่กจ่พพๅผ `pattern`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +่ฟ™ไธช็‰นๅฎš็š„ๆญฃๅˆ™่กจ่พพๅผ้€š่ฟ‡ไปฅไธ‹่ง„ๅˆ™ๆฃ€ๆŸฅๆŽฅๆ”ถๅˆฐ็š„ๅ‚ๆ•ฐๅ€ผ๏ผš + +- `^`๏ผšๅฟ…้กปไปฅๆŽฅไธ‹ๆฅ็š„ๅญ—็ฌฆๅผ€ๅคด๏ผŒๅ‰้ขๆฒกๆœ‰ๅ…ถไป–ๅญ—็ฌฆใ€‚ +- `fixedquery`๏ผšๅ€ผๅฟ…้กป็ฒพ็กฎ็ญ‰ไบŽ `fixedquery`ใ€‚ +- `$`๏ผšๅˆฐๆญค็ป“ๆŸ๏ผŒๅœจ `fixedquery` ไน‹ๅŽๆฒกๆœ‰ๆ›ดๅคšๅญ—็ฌฆใ€‚ -{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *} +ๅฆ‚ๆžœไฝ ๅฏน่ฟ™ไบ›**ใ€Œๆญฃๅˆ™่กจ่พพๅผใ€**ๆฆ‚ๅฟตๆ„Ÿๅˆฐ่ฟท่Œซ๏ผŒไธๅฟ…ๆ‹…ๅฟƒใ€‚ๅฏนๅพˆๅคšไบบๆฅ่ฏด่ฟ™้ƒฝๆ˜ฏไธช้šพ็‚นใ€‚ไฝ ไป็„ถๅฏไปฅๅœจไธไฝฟ็”จๆญฃๅˆ™่กจ่พพๅผ็š„ๆƒ…ๅ†ตไธ‹ๅšๅพˆๅคšไบ‹ๆƒ…ใ€‚ -### ไฝฟ็”จ`None`ๅฃฐๆ˜Žๅฟ…้œ€ๅ‚ๆ•ฐ +็Žฐๅœจไฝ ็Ÿฅ้“ไบ†๏ผŒไธ€ๆ—ฆ้œ€่ฆๆ—ถ๏ผŒไฝ ๅฏไปฅๅœจ **FastAPI** ไธญ็›ดๆŽฅไฝฟ็”จๅฎƒไปฌใ€‚ -ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ‚ๆ•ฐๅฏไปฅๆŽฅๆ”ถ`None`ๅ€ผ๏ผŒไฝ†ๅฎƒไป็„ถๆ˜ฏๅฟ…้œ€็š„ใ€‚่ฟ™ๅฐ†ๅผบๅˆถๅฎขๆˆท็ซฏๅ‘้€ไธ€ไธชๅ€ผ๏ผŒๅณไฝฟ่ฏฅๅ€ผๆ˜ฏ`None`ใ€‚ +## ้ป˜่ฎคๅ€ผ { #default-values } -ไธบๆญค๏ผŒไฝ ๅฏไปฅๅฃฐๆ˜Ž`None`ๆ˜ฏไธ€ไธชๆœ‰ๆ•ˆ็š„็ฑปๅž‹๏ผŒๅนถไป็„ถไฝฟ็”จ`default=...`๏ผš +ๅฝ“็„ถ๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ `None` ไปฅๅค–็š„้ป˜่ฎคๅ€ผใ€‚ -{* ../../docs_src/query_params_str_validations/tutorial006c.py hl[9] *} +ๅ‡่ฎพไฝ ๆƒณ่ฆๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ็š„ `min_length` ไธบ `3`๏ผŒๅนถไธ”้ป˜่ฎคๅ€ผไธบ `"fixedquery"`๏ผš -/// tip +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} -Pydantic ๆ˜ฏ FastAPI ไธญๆ‰€ๆœ‰ๆ•ฐๆฎ้ชŒ่ฏๅ’Œๅบๅˆ—ๅŒ–็š„ๆ ธๅฟƒ๏ผŒๅฝ“ไฝ ๅœจๆฒกๆœ‰่ฎพ้ป˜่ฎคๅ€ผ็š„ๆƒ…ๅ†ตไธ‹ไฝฟ็”จ `Optional` ๆˆ– `Union[Something, None]` ๆ—ถ๏ผŒๅฎƒๅ…ทๆœ‰็‰นๆฎŠ่กŒไธบ๏ผŒไฝ ๅฏไปฅๅœจ Pydantic ๆ–‡ๆกฃไธญ้˜…่ฏปๆœ‰ๅ…ณๅฟ…้œ€ๅฏ้€‰ๅญ—ๆฎต็š„ๆ›ดๅคšไฟกๆฏใ€‚ +/// note | ๆณจๆ„ + +ไปปไฝ•็ฑปๅž‹็š„้ป˜่ฎคๅ€ผ๏ผˆๅŒ…ๆ‹ฌ `None`๏ผ‰้ƒฝไผš่ฎฉ่ฏฅๅ‚ๆ•ฐๅ˜ไธบๅฏ้€‰๏ผˆ้žๅฟ…ๅกซ๏ผ‰ใ€‚ /// -## ๆŸฅ่ฏขๅ‚ๆ•ฐๅˆ—่กจ / ๅคšไธชๅ€ผ +## ๅฟ…ๅกซๅ‚ๆ•ฐ { #required-parameters } + +ๅฝ“ๆˆ‘ไปฌไธ้œ€่ฆๅฃฐๆ˜Žๆ›ดๅคšๆ ก้ชŒๆˆ–ๅ…ƒๆ•ฐๆฎๆ—ถ๏ผŒๅช้œ€ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผๅฐฑๅฏไปฅ่ฎฉๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ๆˆไธบๅฟ…ๅกซๅ‚ๆ•ฐ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +q: str +``` + +่€Œไธๆ˜ฏ๏ผš + +```Python +q: str | None = None +``` + +ไฝ†็Žฐๅœจๆˆ‘ไปฌ็”จ `Query` ๆฅๅฃฐๆ˜Žๅฎƒ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +ๅ› ๆญค๏ผŒๅœจไฝฟ็”จ `Query` ็š„ๅŒๆ—ถ้œ€่ฆๆŠŠๆŸไธชๅ€ผๅฃฐๆ˜Žไธบๅฟ…ๅกซๆ—ถ๏ผŒๅช้œ€ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผš -ๅฝ“ไฝ ไฝฟ็”จ `Query` ๆ˜พๅผๅœฐๅฎšไน‰ๆŸฅ่ฏขๅ‚ๆ•ฐๆ—ถ๏ผŒไฝ ่ฟ˜ๅฏไปฅๅฃฐๆ˜ŽๅฎƒๅŽปๆŽฅๆ”ถไธ€็ป„ๅ€ผ๏ผŒๆˆ–ๆขๅฅ่ฏๆฅ่ฏด๏ผŒๆŽฅๆ”ถๅคšไธชๅ€ผใ€‚ +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} + +### ๅฟ…ๅกซ๏ผŒไฝ†ๅฏไปฅไธบ `None` { #required-can-be-none } + +ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ‚ๆ•ฐๅฏไปฅๆŽฅๆ”ถ `None`๏ผŒไฝ†ๅฎƒไป็„ถๆ˜ฏๅฟ…ๅกซ็š„ใ€‚่ฟ™ๅฐ†ๅผบๅˆถๅฎขๆˆท็ซฏๅฟ…้กปๅ‘้€ไธ€ไธชๅ€ผ๏ผŒๅณไฝฟ่ฏฅๅ€ผๆ˜ฏ `None`ใ€‚ + +ไธบๆญค๏ผŒไฝ ๅฏไปฅๅฃฐๆ˜Ž `None` ๆ˜ฏๆœ‰ๆ•ˆ็ฑปๅž‹๏ผŒไฝ†ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## ๆŸฅ่ฏขๅ‚ๆ•ฐๅˆ—่กจ / ๅคšไธชๅ€ผ { #query-parameter-list-multiple-values } + +ๅฝ“ไฝ ็”จ `Query` ๆ˜พๅผๅœฐๅฎšไน‰ๆŸฅ่ฏขๅ‚ๆ•ฐๆ—ถ๏ผŒไฝ ่ฟ˜ๅฏไปฅๅฃฐๆ˜ŽๅฎƒๆŽฅๆ”ถไธ€ไธชๅ€ผๅˆ—่กจ๏ผŒๆขๅฅ่ฏ่ฏด๏ผŒๆŽฅๆ”ถๅคšไธชๅ€ผใ€‚ ไพ‹ๅฆ‚๏ผŒ่ฆๅฃฐๆ˜Žไธ€ไธชๅฏๅœจ URL ไธญๅ‡บ็Žฐๅคšๆฌก็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ `q`๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ทๅ†™๏ผš -{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -็„ถๅŽ๏ผŒ่พ“ๅ…ฅๅฆ‚ไธ‹็ฝ‘ๅ€๏ผš +็„ถๅŽ๏ผŒ่ฎฟ้—ฎๅฆ‚ไธ‹ URL๏ผš ``` http://localhost:8000/items/?q=foo&q=bar ``` -ไฝ ไผšๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„*ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ* `q` ไธญไปฅไธ€ไธช Python `list` ็š„ๅฝขๅผๆŽฅๆ”ถๅˆฐ*ๆŸฅ่ฏขๅ‚ๆ•ฐ* `q` ็š„ๅคšไธชๅ€ผ๏ผˆ`foo` ๅ’Œ `bar`๏ผ‰ใ€‚ +ไฝ ไผšๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„*ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ* `q` ไธญไปฅไธ€ไธช Python `list` ็š„ๅฝขๅผๆŽฅๆ”ถๅˆฐๅคšไธช `q` *ๆŸฅ่ฏขๅ‚ๆ•ฐ* ็š„ๅ€ผ๏ผˆ`foo` ๅ’Œ `bar`๏ผ‰ใ€‚ ๅ› ๆญค๏ผŒ่ฏฅ URL ็š„ๅ“ๅบ”ๅฐ†ไผšๆ˜ฏ๏ผš @@ -149,21 +278,21 @@ http://localhost:8000/items/?q=foo&q=bar } ``` -/// tip +/// tip | ๆ็คบ -่ฆๅฃฐๆ˜Ž็ฑปๅž‹ไธบ `list` ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผŒๅฆ‚ไธŠไพ‹ๆ‰€็คบ๏ผŒไฝ ้œ€่ฆๆ˜พๅผๅœฐไฝฟ็”จ `Query`๏ผŒๅฆๅˆ™่ฏฅๅ‚ๆ•ฐๅฐ†่ขซ่งฃ้‡Šไธบ่ฏทๆฑ‚ไฝ“ใ€‚ +่ฆๅฃฐๆ˜Ž็ฑปๅž‹ไธบ `list` ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผˆๅฆ‚ไธŠไพ‹๏ผ‰๏ผŒไฝ ้œ€่ฆๆ˜พๅผๅœฐไฝฟ็”จ `Query`๏ผŒๅฆๅˆ™ๅฎƒไผš่ขซ่งฃ้‡Šไธบ่ฏทๆฑ‚ไฝ“ใ€‚ /// -ไบคไบ’ๅผ API ๆ–‡ๆกฃๅฐ†ไผš็›ธๅบ”ๅœฐ่ฟ›่กŒๆ›ดๆ–ฐ๏ผŒไปฅๅ…่ฎธไฝฟ็”จๅคšไธชๅ€ผ๏ผš +ไบคไบ’ๅผ API ๆ–‡ๆกฃไผš็›ธๅบ”ๆ›ดๆ–ฐ๏ผŒไปฅๆ”ฏๆŒๅคšไธชๅ€ผ๏ผš - + -### ๅ…ทๆœ‰้ป˜่ฎคๅ€ผ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐๅˆ—่กจ / ๅคšไธชๅ€ผ +### ๅ…ทๆœ‰้ป˜่ฎคๅ€ผ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐๅˆ—่กจ / ๅคšไธชๅ€ผ { #query-parameter-list-multiple-values-with-defaults } -ไฝ ่ฟ˜ๅฏไปฅๅฎšไน‰ๅœจๆฒกๆœ‰ไปปไฝ•็ป™ๅฎšๅ€ผๆ—ถ็š„้ป˜่ฎค `list` ๅ€ผ๏ผš +ไฝ ่ฟ˜ๅฏไปฅๅฎšไน‰ๅœจๆฒกๆœ‰็ป™ๅฎšๅ€ผๆ—ถ็š„้ป˜่ฎค `list`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} ๅฆ‚ๆžœไฝ ่ฎฟ้—ฎ๏ผš @@ -182,93 +311,163 @@ http://localhost:8000/items/ } ``` -#### ไฝฟ็”จ `list` +#### ๅชไฝฟ็”จ `list` { #using-just-list } -ไฝ ไนŸๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `list` ไปฃๆ›ฟ `List [str]`๏ผš +ไฝ ไนŸๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `list`๏ผŒ่€Œไธๆ˜ฏ `list[str]`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} -/// note +/// note | ๆณจๆ„ -่ฏท่ฎฐไฝ๏ผŒๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹ FastAPI ๅฐ†ไธไผšๆฃ€ๆŸฅๅˆ—่กจ็š„ๅ†…ๅฎนใ€‚ +่ฏท่ฎฐไฝ๏ผŒๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹ FastAPI ไธไผšๆฃ€ๆŸฅๅˆ—่กจ็š„ๅ†…ๅฎนใ€‚ -ไพ‹ๅฆ‚๏ผŒ`List[int]` ๅฐ†ๆฃ€ๆŸฅ๏ผˆๅนถ่ฎฐๅฝ•ๅˆฐๆ–‡ๆกฃ๏ผ‰ๅˆ—่กจ็š„ๅ†…ๅฎนๅฟ…้กปๆ˜ฏๆ•ดๆ•ฐใ€‚ไฝ†ๆ˜ฏๅ•็‹ฌ็š„ `list` ไธไผšใ€‚ +ไพ‹ๅฆ‚๏ผŒ`list[int]` ไผšๆฃ€ๆŸฅ๏ผˆๅนถ่ฎฐๅฝ•ๅˆฐๆ–‡ๆกฃ๏ผ‰ๅˆ—่กจ็š„ๅ†…ๅฎนๅฟ…้กปๆ˜ฏๆ•ดๆ•ฐใ€‚ไฝ†ไป…็”จ `list` ไธไผšใ€‚ /// -## ๅฃฐๆ˜Žๆ›ดๅคšๅ…ƒๆ•ฐๆฎ +## ๅฃฐๆ˜Žๆ›ดๅคšๅ…ƒๆ•ฐๆฎ { #declare-more-metadata } ไฝ ๅฏไปฅๆทปๅŠ ๆ›ดๅคšๆœ‰ๅ…ณ่ฏฅๅ‚ๆ•ฐ็š„ไฟกๆฏใ€‚ -่ฟ™ไบ›ไฟกๆฏๅฐ†ๅŒ…ๅซๅœจ็”Ÿๆˆ็š„ OpenAPI ๆจกๅผไธญ๏ผŒๅนถ็”ฑๆ–‡ๆกฃ็”จๆˆท็•Œ้ขๅ’Œๅค–้ƒจๅทฅๅ…ทๆ‰€ไฝฟ็”จใ€‚ +่ฟ™ไบ›ไฟกๆฏไผšๅŒ…ๅซๅœจ็”Ÿๆˆ็š„ OpenAPI ไธญ๏ผŒๅนถ่ขซๆ–‡ๆกฃ็”จๆˆท็•Œ้ขๅ’Œๅค–้ƒจๅทฅๅ…ทไฝฟ็”จใ€‚ -/// note +/// note | ๆณจๆ„ ่ฏท่ฎฐไฝ๏ผŒไธๅŒ็š„ๅทฅๅ…ทๅฏน OpenAPI ็š„ๆ”ฏๆŒ็จ‹ๅบฆๅฏ่ƒฝไธๅŒใ€‚ -ๅ…ถไธญไธ€ไบ›ๅฏ่ƒฝไธไผšๅฑ•็คบๆ‰€ๆœ‰ๅทฒๅฃฐๆ˜Ž็š„้ขๅค–ไฟกๆฏ๏ผŒๅฐฝ็ฎกๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒ็ผบๅฐ‘็š„่ฟ™้ƒจๅˆ†ๅŠŸ่ƒฝๅทฒ็ป่ฎกๅˆ’่ฟ›่กŒๅผ€ๅ‘ใ€‚ +ๅ…ถไธญไธ€ไบ›ๅฏ่ƒฝ่ฟ˜ไธไผšๅฑ•็คบๆ‰€ๆœ‰ๅทฒๅฃฐๆ˜Ž็š„้ขๅค–ไฟกๆฏ๏ผŒๅฐฝ็ฎกๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒ็ผบๅคฑ็š„ๅŠŸ่ƒฝๅทฒ็ปๅœจ่ฎกๅˆ’ๅผ€ๅ‘ไธญใ€‚ /// ไฝ ๅฏไปฅๆทปๅŠ  `title`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *} +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} ไปฅๅŠ `description`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *} +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} -## ๅˆซๅๅ‚ๆ•ฐ +## ๅˆซๅๅ‚ๆ•ฐ { #alias-parameters } -ๅ‡่ฎพไฝ ๆƒณ่ฆๆŸฅ่ฏขๅ‚ๆ•ฐไธบ `item-query`ใ€‚ +ๅ‡่ฎพไฝ ๆƒณ่ฆๅ‚ๆ•ฐๅไธบ `item-query`ใ€‚ -ๅƒไธ‹้ข่ฟ™ๆ ท๏ผš +ๅƒ่ฟ™ๆ ท๏ผš ``` http://127.0.0.1:8000/items/?item-query=foobaritems ``` -ไฝ†ๆ˜ฏ `item-query` ไธๆ˜ฏไธ€ไธชๆœ‰ๆ•ˆ็š„ Python ๅ˜้‡ๅ็งฐใ€‚ +ไฝ† `item-query` ไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Python ๅ˜้‡ๅใ€‚ ๆœ€ๆŽฅ่ฟ‘็š„ๆœ‰ๆ•ˆๅ็งฐๆ˜ฏ `item_query`ใ€‚ -ไฝ†ๆ˜ฏไฝ ไป็„ถ่ฆๆฑ‚ๅฎƒๅœจ URL ไธญๅฟ…้กปๆ˜ฏ `item-query`... +ไฝ†ไฝ ไป็„ถ้œ€่ฆๅฎƒๅœจ URL ไธญๅฐฑๆ˜ฏ `item-query`โ€ฆโ€ฆ -่ฟ™ๆ—ถไฝ ๅฏไปฅ็”จ `alias` ๅ‚ๆ•ฐๅฃฐๆ˜Žไธ€ไธชๅˆซๅ๏ผŒ่ฏฅๅˆซๅๅฐ†็”จไบŽๅœจ URL ไธญๆŸฅๆ‰พๆŸฅ่ฏขๅ‚ๆ•ฐๅ€ผ๏ผš +่ฟ™ๆ—ถๅฏไปฅ็”จ `alias` ๅ‚ๆ•ฐๅฃฐๆ˜Žไธ€ไธชๅˆซๅ๏ผŒFastAPI ไผš็”จ่ฏฅๅˆซๅๅœจ URL ไธญๆŸฅๆ‰พๅ‚ๆ•ฐๅ€ผ๏ผš -{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} -## ๅผƒ็”จๅ‚ๆ•ฐ +## ๅผƒ็”จๅ‚ๆ•ฐ { #deprecating-parameters } -็Žฐๅœจๅ‡่ฎพไฝ ไธๅ†ๅ–œๆฌขๆญคๅ‚ๆ•ฐใ€‚ +็Žฐๅœจๅ‡่ฎพไฝ ไธๅ†ๅ–œๆฌข่ฟ™ไธชๅ‚ๆ•ฐไบ†ใ€‚ -ไฝ ไธๅพ—ไธๅฐ†ๅ…ถไฟ็•™ไธ€ๆฎตๆ—ถ้—ด๏ผŒๅ› ไธบๆœ‰ไบ›ๅฎขๆˆท็ซฏๆญฃๅœจไฝฟ็”จๅฎƒ๏ผŒไฝ†ไฝ ๅธŒๆœ›ๆ–‡ๆกฃๆธ…ๆฅšๅœฐๅฐ†ๅ…ถๅฑ•็คบไธบๅทฒๅผƒ็”จใ€‚ +็”ฑไบŽ่ฟ˜ๆœ‰ๅฎขๆˆท็ซฏๅœจไฝฟ็”จๅฎƒ๏ผŒไฝ ไธๅพ—ไธไฟ็•™ไธ€ๆฎตๆ—ถ้—ด๏ผŒไฝ†ไฝ ๅธŒๆœ›ๆ–‡ๆกฃๆธ…ๆฅšๅœฐๅฐ†ๅ…ถๅฑ•็คบไธบๅทฒๅผƒ็”จใ€‚ -้‚ฃไนˆๅฐ†ๅ‚ๆ•ฐ `deprecated=True` ไผ ๅ…ฅ `Query`๏ผš +้‚ฃไนˆๅฐ†ๅ‚ๆ•ฐ `deprecated=True` ไผ ็ป™ `Query`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *} +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} ๆ–‡ๆกฃๅฐ†ไผšๅƒไธ‹้ข่ฟ™ๆ ทๅฑ•็คบๅฎƒ๏ผš - + + +## ไปŽ OpenAPI ไธญๆŽ’้™คๅ‚ๆ•ฐ { #exclude-parameters-from-openapi } + +่ฆๆŠŠๆŸไธชๆŸฅ่ฏขๅ‚ๆ•ฐไปŽ็”Ÿๆˆ็š„ OpenAPI ๆจกๅผไธญๆŽ’้™ค๏ผˆไปŽ่€ŒไนŸไธไผšๅ‡บ็Žฐๅœจ่‡ชๅŠจๆ–‡ๆกฃ็ณป็ปŸไธญ๏ผ‰๏ผŒๅฐ† `Query` ็š„ๅ‚ๆ•ฐ `include_in_schema` ่ฎพไธบ `False`๏ผš -## ๆ€ป็ป“ +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} -ไฝ ๅฏไปฅไธบๆŸฅ่ฏขๅ‚ๆ•ฐๅฃฐๆ˜Ž้ขๅค–็š„ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ +## ่‡ชๅฎšไน‰ๆ ก้ชŒ { #custom-validation } + +ๆœ‰ไบ›ๆƒ…ๅ†ตไธ‹ไฝ ้œ€่ฆๅšไธ€ไบ›ๆ— ๆณ•้€š่ฟ‡ไธŠ่ฟฐๅ‚ๆ•ฐๅฎŒๆˆ็š„**่‡ชๅฎšไน‰ๆ ก้ชŒ**ใ€‚ + +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ**่‡ชๅฎšไน‰ๆ ก้ชŒๅ‡ฝๆ•ฐ**๏ผŒ่ฏฅๅ‡ฝๆ•ฐไผšๅœจๆญฃๅธธๆ ก้ชŒไน‹ๅŽๅบ”็”จ๏ผˆไพ‹ๅฆ‚๏ผŒๅœจๅ…ˆๆ ก้ชŒๅ€ผๆ˜ฏ `str` ไน‹ๅŽ๏ผ‰ใ€‚ + +ไฝ ๅฏไปฅๅœจ `Annotated` ไธญไฝฟ็”จ Pydantic ็š„ `AfterValidator` ๆฅๅฎž็Žฐใ€‚ + +/// tip | ๆ็คบ + +Pydantic ่ฟ˜ๆœ‰ `BeforeValidator` ็ญ‰ใ€‚๐Ÿค“ + +/// + +ไพ‹ๅฆ‚๏ผŒ่ฟ™ไธช่‡ชๅฎšไน‰ๆ ก้ชŒๅ™จไผšๆฃ€ๆŸฅๆก็›ฎ ID ๆ˜ฏๅฆไปฅ `isbn-`๏ผˆ็”จไบŽ ISBN ไนฆๅท๏ผ‰ๆˆ– `imdb-`๏ผˆ็”จไบŽ IMDB ็”ตๅฝฑ URL ็š„ ID๏ผ‰ๅผ€ๅคด๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | ไฟกๆฏ + +่ฟ™ๅœจ Pydantic 2 ๆˆ–ๆ›ด้ซ˜็‰ˆๆœฌไธญๅฏ็”จใ€‚๐Ÿ˜Ž + +/// + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ้œ€่ฆ่ฟ›่กŒไปปไฝ•้œ€่ฆไธŽ**ๅค–้ƒจ็ป„ไปถ**้€šไฟก็š„ๆ ก้ชŒ๏ผŒไพ‹ๅฆ‚ๆ•ฐๆฎๅบ“ๆˆ–ๅ…ถไป– API๏ผŒไฝ ๅบ”่ฏฅๆ”น็”จ **FastAPI ไพ่ต–้กน**๏ผŒ็จๅŽไฝ ไผšๅญฆๅˆฐๅฎƒไปฌใ€‚ + +่ฟ™ไบ›่‡ชๅฎšไน‰ๆ ก้ชŒๅ™จ็”จไบŽๅช้œ€ๆฃ€ๆŸฅ่ฏทๆฑ‚ไธญ**ๅŒไธ€ไปฝๆ•ฐๆฎ**ๅณๅฏๅฎŒๆˆ็š„ไบ‹ๆƒ…ใ€‚ + +/// + +### ็†่งฃ่ฟ™ๆฎตไปฃ็  { #understand-that-code } + +ๅ…ณ้”ฎ็‚นไป…ไป…ๆ˜ฏ๏ผšๅœจ `Annotated` ไธญไฝฟ็”จๅธฆๅ‡ฝๆ•ฐ็š„ **`AfterValidator`**ใ€‚ไธๆ„Ÿๅ…ด่ถฃๅฏไปฅ่ทณ่ฟ‡่ฟ™ไธ€่Š‚ใ€‚๐Ÿคธ + +--- + +ไฝ†ๅฆ‚ๆžœไฝ ๅฏน่ฟ™ไธชๅ…ทไฝ“็คบไพ‹ๅฅฝๅฅ‡๏ผŒๅนถไธ”่ฟ˜ๆ„ฟๆ„็ปง็ปญ็œ‹๏ผŒ่ฟ™้‡Œๆœ‰ไธ€ไบ›้ขๅค–็ป†่Š‚ใ€‚ + +#### ๅญ—็ฌฆไธฒไธŽ `value.startswith()` { #string-with-value-startswith } + +ๆณจๆ„ๅˆฐไบ†ๅ—๏ผŸๅญ—็ฌฆไธฒ็š„ `value.startswith()` ๅฏไปฅๆŽฅๆ”ถไธ€ไธชๅ…ƒ็ป„๏ผŒๅฎƒไผšๆฃ€ๆŸฅๅ…ƒ็ป„ไธญ็š„ๆฏไธชๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### ไธ€ไธช้šๆœบๆก็›ฎ { #a-random-item } + +ไฝฟ็”จ `data.items()` ๆˆ‘ไปฌไผšๅพ—ๅˆฐไธ€ไธชๅŒ…ๅซๆฏไธชๅญ—ๅ…ธ้กน้”ฎๅ’Œๅ€ผ็š„ๅ…ƒ็ป„็š„ ๅฏ่ฟญไปฃๅฏน่ฑกใ€‚ + +ๆˆ‘ไปฌ็”จ `list(data.items())` ๆŠŠ่ฟ™ไธชๅฏ่ฟญไปฃๅฏน่ฑก่ฝฌๆขๆˆไธ€ไธช็œŸๆญฃ็š„ `list`ใ€‚ + +็„ถๅŽ็”จ `random.choice()` ๅฏไปฅไปŽ่ฏฅๅˆ—่กจไธญ่Žทๅ–ไธ€ไธช**้šๆœบๅ€ผ**๏ผŒไนŸๅฐฑๆ˜ฏไธ€ไธช `(id, name)` ็š„ๅ…ƒ็ป„ใ€‚ๅฎƒๅฏ่ƒฝๅƒ `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` ่ฟ™ๆ ทใ€‚ + +ๆŽฅ็€ๆˆ‘ไปฌๆŠŠ่ฟ™ไธชๅ…ƒ็ป„็š„**ไธคไธชๅ€ผ**ๅˆ†ๅˆซ่ต‹็ป™ๅ˜้‡ `id` ๅ’Œ `name`ใ€‚ + +ๆ‰€ไปฅ๏ผŒๅณไฝฟ็”จๆˆทๆฒกๆœ‰ๆไพ›ๆก็›ฎ ID๏ผŒไป–ไปฌไป็„ถไผšๆ”ถๅˆฐไธ€ไธช้šๆœบๆŽจ่ใ€‚ + +โ€ฆโ€ฆ่€Œๆˆ‘ไปฌๆŠŠ่ฟ™ไบ›้ƒฝๆ”พๅœจ**ไธ€่กŒ็ฎ€ๅ•็š„ไปฃ็ **้‡ŒๅฎŒๆˆใ€‚๐Ÿคฏ ไฝ ไธ็ˆฑ Python ๅ—๏ผŸ๐Ÿ + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## ๆ€ป็ป“ { #recap } + +ไฝ ๅฏไปฅไธบๅ‚ๆ•ฐๅฃฐๆ˜Ž้ขๅค–็š„ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎใ€‚ ้€š็”จ็š„ๆ ก้ชŒๅ’Œๅ…ƒๆ•ฐๆฎ๏ผš -* `alias` -* `title` -* `description` -* `deprecated` +- `alias` +- `title` +- `description` +- `deprecated` + +ๅญ—็ฌฆไธฒ็‰นๆœ‰็š„ๆ ก้ชŒ๏ผš -็‰นๅฎšไบŽๅญ—็ฌฆไธฒ็š„ๆ ก้ชŒ๏ผš +- `min_length` +- `max_length` +- `pattern` -* `min_length` -* `max_length` -* `regex` +ไนŸๅฏไปฅไฝฟ็”จ `AfterValidator` ่ฟ›่กŒ่‡ชๅฎšไน‰ๆ ก้ชŒใ€‚ -ๅœจ่ฟ™ไบ›็คบไพ‹ไธญ๏ผŒไฝ ไบ†่งฃไบ†ๅฆ‚ไฝ•ๅฃฐๆ˜Žๅฏน `str` ๅ€ผ็š„ๆ ก้ชŒใ€‚ +ๅœจ่ฟ™ไบ›็คบไพ‹ไธญ๏ผŒไฝ ็œ‹ๅˆฐไบ†ๅฆ‚ไฝ•ไธบ `str` ๅ€ผๅฃฐๆ˜Žๆ ก้ชŒใ€‚ -่ฏทๅ‚้˜…ไธ‹ไธ€็ซ ่Š‚๏ผŒไปฅไบ†่งฃๅฆ‚ไฝ•ๅฃฐๆ˜Žๅฏนๅ…ถไป–็ฑปๅž‹ไพ‹ๅฆ‚ๆ•ฐๅ€ผ็š„ๆ ก้ชŒใ€‚ +ๅ‚้˜…ไธ‹ไธ€็ซ ่Š‚๏ผŒไบ†่งฃๅฆ‚ไฝ•ไธบๅ…ถไป–็ฑปๅž‹๏ผˆไพ‹ๅฆ‚ๆ•ฐๅ€ผ๏ผ‰ๅฃฐๆ˜Žๆ ก้ชŒใ€‚ diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md index cc2e74b9ea..9ef998731a 100644 --- a/docs/zh/docs/tutorial/query-params.md +++ b/docs/zh/docs/tutorial/query-params.md @@ -1,8 +1,8 @@ -# ๆŸฅ่ฏขๅ‚ๆ•ฐ +# ๆŸฅ่ฏขๅ‚ๆ•ฐ { #query-parameters } ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐไธๆ˜ฏ่ทฏๅพ„ๅ‚ๆ•ฐๆ—ถ๏ผŒ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไผšๆŠŠ่ฏฅๅ‚ๆ•ฐ่‡ชๅŠจ่งฃ้‡Šไธบ**ๆŸฅ่ฏข**ๅ‚ๆ•ฐใ€‚ -{* ../../docs_src/query_params/tutorial001.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} ๆŸฅ่ฏขๅญ—็ฌฆไธฒๆ˜ฏ้”ฎๅ€ผๅฏน็š„้›†ๅˆ๏ผŒ่ฟ™ไบ›้”ฎๅ€ผๅฏนไฝไบŽ URL ็š„ `?` ไน‹ๅŽ๏ผŒไปฅ `&` ๅˆ†้š”ใ€‚ @@ -26,9 +26,9 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 * ๏ผˆๆ˜พ่€Œๆ˜“่ง็š„๏ผ‰็ผ–่พ‘ๅ™จๆ”ฏๆŒ * ๆ•ฐๆฎ**่งฃๆž** * ๆ•ฐๆฎๆ ก้ชŒ -* API ๆ–‡ๆกฃ +* ่‡ชๅŠจๆ–‡ๆกฃ -## ้ป˜่ฎคๅ€ผ +## ้ป˜่ฎคๅ€ผ { #defaults } ๆŸฅ่ฏขๅ‚ๆ•ฐไธๆ˜ฏ่ทฏๅพ„็š„ๅ›บๅฎšๅ†…ๅฎน๏ผŒๅฎƒๆ˜ฏๅฏ้€‰็š„๏ผŒ่ฟ˜ๆ”ฏๆŒ้ป˜่ฎคๅ€ผใ€‚ @@ -57,7 +57,7 @@ http://127.0.0.1:8000/items/?skip=20 * `skip=20`๏ผšๅœจ URL ไธญ่ฎพๅฎš็š„ๅ€ผ * `limit=10`๏ผšไฝฟ็”จ้ป˜่ฎคๅ€ผ -## ๅฏ้€‰ๅ‚ๆ•ฐ +## ๅฏ้€‰ๅ‚ๆ•ฐ { #optional-parameters } ๅŒ็†๏ผŒๆŠŠ้ป˜่ฎคๅ€ผ่ฎพไธบ `None` ๅณๅฏๅฃฐๆ˜Ž**ๅฏ้€‰็š„**ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผš @@ -71,15 +71,7 @@ http://127.0.0.1:8000/items/?skip=20 /// -/// note | ็ฌ”่ฎฐ - -ๅ› ไธบ้ป˜่ฎคๅ€ผไธบ `= None`๏ผŒFastAPI ๆŠŠ `q` ่ฏ†ๅˆซไธบๅฏ้€‰ๅ‚ๆ•ฐใ€‚ - -FastAPI ไธไฝฟ็”จ `Optional[str]` ไธญ็š„ `Optional`๏ผˆๅชไฝฟ็”จ `str`๏ผ‰๏ผŒไฝ† `Optional[str]` ๅฏไปฅๅธฎๅŠฉ็ผ–่พ‘ๅ™จๅ‘็Žฐไปฃ็ ไธญ็š„้”™่ฏฏใ€‚ - -/// - -## ๆŸฅ่ฏขๅ‚ๆ•ฐ็ฑปๅž‹่ฝฌๆข +## ๆŸฅ่ฏขๅ‚ๆ•ฐ็ฑปๅž‹่ฝฌๆข { #query-parameter-type-conversion } ๅ‚ๆ•ฐ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žไธบ `bool` ็ฑปๅž‹๏ผŒFastAPI ไผš่‡ชๅŠจ่ฝฌๆขๅ‚ๆ•ฐ็ฑปๅž‹๏ผš @@ -116,10 +108,10 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -ๆˆ–ๅ…ถๅฎƒไปปๆ„ๅคงๅฐๅ†™ๅฝขๅผ๏ผˆๅคงๅ†™ใ€้ฆ–ๅญ—ๆฏๅคงๅ†™็ญ‰๏ผ‰๏ผŒๅ‡ฝๆ•ฐๆŽฅๆ”ถ็š„ `short` ๅ‚ๆ•ฐ้ƒฝๆ˜ฏๅธƒๅฐ”ๅ€ผ `True`ใ€‚ๅ€ผไธบ `False` ๆ—ถไนŸไธ€ๆ ทใ€‚ +ๆˆ–ๅ…ถๅฎƒไปปๆ„ๅคงๅฐๅ†™ๅฝขๅผ๏ผˆๅคงๅ†™ใ€้ฆ–ๅญ—ๆฏๅคงๅ†™็ญ‰๏ผ‰๏ผŒๅ‡ฝๆ•ฐๆŽฅๆ”ถ็š„ `short` ๅ‚ๆ•ฐ้ƒฝๆ˜ฏๅธƒๅฐ”ๅ€ผ `True`ใ€‚ๅฆๅˆ™ไธบ `False`ใ€‚ -## ๅคšไธช่ทฏๅพ„ๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ +## ๅคšไธช่ทฏๅพ„ๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐ { #multiple-path-and-query-parameters } **FastAPI** ๅฏไปฅ่ฏ†ๅˆซๅŒๆ—ถๅฃฐๆ˜Ž็š„ๅคšไธช่ทฏๅพ„ๅ‚ๆ•ฐๅ’ŒๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ @@ -129,7 +121,7 @@ FastAPI ้€š่ฟ‡ๅ‚ๆ•ฐๅ่ฟ›่กŒๆฃ€ๆต‹๏ผš {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## ๅฟ…้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ +## ๅฟ…้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐ { #required-query-parameters } ไธบไธๆ˜ฏ่ทฏๅพ„ๅ‚ๆ•ฐ็š„ๅ‚ๆ•ฐๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผˆ่‡ณๆญค๏ผŒไป…ๆœ‰ๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผ‰๏ผŒ่ฏฅๅ‚ๆ•ฐๅฐฑ**ไธๆ˜ฏๅฟ…้€‰**็š„ไบ†ใ€‚ @@ -137,7 +129,7 @@ FastAPI ้€š่ฟ‡ๅ‚ๆ•ฐๅ่ฟ›่กŒๆฃ€ๆต‹๏ผš ๅฆ‚ๆžœ่ฆๆŠŠๆŸฅ่ฏขๅ‚ๆ•ฐ่ฎพ็ฝฎไธบ**ๅฟ…้€‰**๏ผŒๅฐฑไธ่ฆๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผš -{* ../../docs_src/query_params/tutorial005.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} ่ฟ™้‡Œ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ `needy` ๆ˜ฏ็ฑปๅž‹ไธบ `str` ็š„ๅฟ…้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ @@ -151,16 +143,17 @@ http://127.0.0.1:8000/items/foo-item ```JSON { - "detail": [ - { - "loc": [ - "query", - "needy" - ], - "msg": "field required", - "type": "value_error.missing" - } - ] + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] } ``` @@ -191,6 +184,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip | ๆ็คบ -่ฟ˜ๅฏไปฅๅƒๅœจ[่ทฏๅพ„ๅ‚ๆ•ฐ](path-params.md#_8){.internal-link target=_blank} ไธญ้‚ฃๆ ทไฝฟ็”จ `Enum`ใ€‚ +่ฟ˜ๅฏไปฅๅƒๅœจ[่ทฏๅพ„ๅ‚ๆ•ฐ](path-params.md#predefined-values){.internal-link target=_blank} ไธญ้‚ฃๆ ทไฝฟ็”จ `Enum`ใ€‚ /// diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md index 81ddc7238a..927bd093b0 100644 --- a/docs/zh/docs/tutorial/request-files.md +++ b/docs/zh/docs/tutorial/request-files.md @@ -1,159 +1,163 @@ -# ่ฏทๆฑ‚ๆ–‡ไปถ +# ่ฏทๆฑ‚ๆ–‡ไปถ { #request-files } -`File` ็”จไบŽๅฎšไน‰ๅฎขๆˆท็ซฏ็š„ไธŠไผ ๆ–‡ไปถใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ `File` ๅฎšไน‰็”ฑๅฎขๆˆท็ซฏไธŠไผ ็š„ๆ–‡ไปถใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๅ› ไธบไธŠไผ ๆ–‡ไปถไปฅใ€Œ่กจๅ•ๆ•ฐๆฎใ€ๅฝขๅผๅ‘้€ใ€‚ +่ฆๆŽฅๆ”ถไธŠไผ ็š„ๆ–‡ไปถ๏ผŒ่ฏทๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ -ๆ‰€ไปฅๆŽฅๆ”ถไธŠไผ ๆ–‡ไปถ๏ผŒ่ฆ้ข„ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ +่ฏท็กฎไฟไฝ ๅˆ›ๅปบไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๆฟ€ๆดปๅฎƒ๏ผŒ็„ถๅŽๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš -ไพ‹ๅฆ‚๏ผš `pip install python-multipart`ใ€‚ +```console +$ pip install python-multipart +``` + +่ฟ™ๆ˜ฏๅ› ไธบไธŠไผ ๆ–‡ไปถๆ˜ฏไปฅใ€Œ่กจๅ•ๆ•ฐๆฎใ€ๅ‘้€็š„ใ€‚ /// -## ๅฏผๅ…ฅ `File` +## ๅฏผๅ…ฅ `File` { #import-file } ไปŽ `fastapi` ๅฏผๅ…ฅ `File` ๅ’Œ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial001.py hl[1] *} +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} -## ๅฎšไน‰ `File` ๅ‚ๆ•ฐ +## ๅฎšไน‰ `File` ๅ‚ๆ•ฐ { #define-file-parameters } -ๅˆ›ๅปบๆ–‡ไปถ๏ผˆ`File`๏ผ‰ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๅ’Œ `Form` ไธ€ๆ ท๏ผš +ๅƒไธบ `Body` ๆˆ– `Form` ไธ€ๆ ทๅˆ›ๅปบๆ–‡ไปถๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/request_files/tutorial001.py hl[7] *} +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ `File` ๆ˜ฏ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช `Form` ็š„็ฑปใ€‚ -ๆณจๆ„๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ็š„ `Query`ใ€`Path`ใ€`File` ็ญ‰้กน๏ผŒๅฎž้™…ไธŠๆ˜ฏ่ฟ”ๅ›ž็‰นๅฎš็ฑป็š„ๅ‡ฝๆ•ฐใ€‚ +ไฝ†่ฆๆณจๆ„๏ผŒไปŽ `fastapi` ๅฏผๅ…ฅ็š„ `Query`ใ€`Path`ใ€`File` ็ญ‰้กน๏ผŒๅฎž้™…ไธŠๆ˜ฏ่ฟ”ๅ›ž็‰นๅฎš็ฑป็š„ๅ‡ฝๆ•ฐใ€‚ /// /// tip | ๆ็คบ -ๅฃฐๆ˜Žๆ–‡ไปถไฝ“ๅฟ…้กปไฝฟ็”จ `File`๏ผŒๅฆๅˆ™๏ผŒFastAPI ไผšๆŠŠ่ฏฅๅ‚ๆ•ฐๅฝ“ไฝœๆŸฅ่ฏขๅ‚ๆ•ฐๆˆ–่ฏทๆฑ‚ไฝ“๏ผˆJSON๏ผ‰ๅ‚ๆ•ฐใ€‚ +ๅฃฐๆ˜Žๆ–‡ไปถไฝ“ๅฟ…้กปไฝฟ็”จ `File`๏ผŒๅฆๅˆ™๏ผŒ่ฟ™ไบ›ๅ‚ๆ•ฐไผš่ขซๅฝ“ไฝœๆŸฅ่ฏขๅ‚ๆ•ฐๆˆ–่ฏทๆฑ‚ไฝ“๏ผˆJSON๏ผ‰ๅ‚ๆ•ฐใ€‚ /// -ๆ–‡ไปถไฝœไธบใ€Œ่กจๅ•ๆ•ฐๆฎใ€ไธŠไผ ใ€‚ +ๆ–‡ไปถๅฐ†ไฝœไธบใ€Œ่กจๅ•ๆ•ฐๆฎใ€ไธŠไผ ใ€‚ -ๅฆ‚ๆžœๆŠŠ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `bytes`๏ผŒ**FastAPI** ๅฐ†ไปฅ `bytes` ๅฝขๅผ่ฏปๅ–ๅ’ŒๆŽฅๆ”ถๆ–‡ไปถๅ†…ๅฎนใ€‚ +ๅฆ‚ๆžœๆŠŠ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `bytes`๏ผŒ**FastAPI** ไผšไธบไฝ ่ฏปๅ–ๆ–‡ไปถ๏ผŒๅนถไปฅ `bytes` ็š„ๅฝขๅผๆŽฅๆ”ถๅ…ถๅ†…ๅฎนใ€‚ -่ฟ™็งๆ–นๅผๆŠŠๆ–‡ไปถ็š„ๆ‰€ๆœ‰ๅ†…ๅฎน้ƒฝๅญ˜ๅ‚จๅœจๅ†…ๅญ˜้‡Œ๏ผŒ้€‚็”จไบŽๅฐๅž‹ๆ–‡ไปถใ€‚ +่ฏทๆณจๆ„๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ๆ•ดไธชๅ†…ๅฎนไผšๅญ˜ๅ‚จๅœจๅ†…ๅญ˜ไธญ๏ผŒ้€‚็”จไบŽๅฐๅž‹ๆ–‡ไปถใ€‚ -ไธ่ฟ‡๏ผŒๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒ`UploadFile` ๆ›ดๅฅฝ็”จใ€‚ +ไธ่ฟ‡๏ผŒๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒไฝฟ็”จ `UploadFile` ไผšๆ›ดๆœ‰ไผ˜ๅŠฟใ€‚ -## ๅซ `UploadFile` ็š„ๆ–‡ไปถๅ‚ๆ•ฐ +## ๅซ `UploadFile` ็š„ๆ–‡ไปถๅ‚ๆ•ฐ { #file-parameters-with-uploadfile } -ๅฎšไน‰ๆ–‡ไปถๅ‚ๆ•ฐๆ—ถไฝฟ็”จ `UploadFile`๏ผš +ๅฐ†ๆ–‡ไปถๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial001.py hl[12] *} +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} -`UploadFile` ไธŽ `bytes` ็›ธๆฏ”ๆœ‰ๆ›ดๅคšไผ˜ๅŠฟ๏ผš +ไธŽ `bytes` ็›ธๆฏ”๏ผŒไฝฟ็”จ `UploadFile` ๆœ‰ๅคš้กนไผ˜ๅŠฟ๏ผš -* ไฝฟ็”จ `spooled` ๆ–‡ไปถ๏ผš - * ๅญ˜ๅ‚จๅœจๅ†…ๅญ˜็š„ๆ–‡ไปถ่ถ…ๅ‡บๆœ€ๅคงไธŠ้™ๆ—ถ๏ผŒFastAPI ไผšๆŠŠๆ–‡ไปถๅญ˜ๅ…ฅ็ฃ็›˜๏ผ› -* ่ฟ™็งๆ–นๅผๆ›ด้€‚ไบŽๅค„็†ๅ›พๅƒใ€่ง†้ข‘ใ€ไบŒ่ฟ›ๅˆถๆ–‡ไปถ็ญ‰ๅคงๅž‹ๆ–‡ไปถ๏ผŒๅฅฝๅค„ๆ˜ฏไธไผšๅ ็”จๆ‰€ๆœ‰ๅ†…ๅญ˜๏ผ› -* ๅฏ่Žทๅ–ไธŠไผ ๆ–‡ไปถ็š„ๅ…ƒๆ•ฐๆฎ๏ผ› -* ่‡ชๅธฆ file-like `async` ๆŽฅๅฃ๏ผ› -* ๆšด้œฒ็š„ Python `SpooledTemporaryFile` ๅฏน่ฑก๏ผŒๅฏ็›ดๆŽฅไผ ้€’็ป™ๅ…ถไป–้ข„ๆœŸใ€Œfile-likeใ€ๅฏน่ฑก็š„ๅบ“ใ€‚ +* ๆ— ้œ€ๅœจๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผไธญไฝฟ็”จ `File()`ใ€‚ +* ๅฎƒไฝฟ็”จโ€œspooledโ€ๆ–‡ไปถ๏ผš + * ๆ–‡ไปถไผšๅ…ˆๅญ˜ๅ‚จๅœจๅ†…ๅญ˜ไธญ๏ผŒ็›ดๅˆฐ่พพๅˆฐๆœ€ๅคงไธŠ้™๏ผŒ่ถ…่ฟ‡่ฏฅไธŠ้™ๅŽไผšๅ†™ๅ…ฅ็ฃ็›˜ใ€‚ +* ๅ› ๆญค๏ผŒ้žๅธธ้€‚ๅˆๅค„็†ๅ›พๅƒใ€่ง†้ข‘ใ€ๅคงๅž‹ไบŒ่ฟ›ๅˆถ็ญ‰ๅคงๆ–‡ไปถ๏ผŒ่€Œไธไผšๅ ็”จๆ‰€ๆœ‰ๅ†…ๅญ˜ใ€‚ +* ไฝ ๅฏไปฅ่Žทๅ–ไธŠไผ ๆ–‡ไปถ็š„ๅ…ƒๆ•ฐๆฎใ€‚ +* ๅฎƒๆไพ› file-like ็š„ `async` ๆŽฅๅฃใ€‚ +* ๅฎƒๆšด้œฒไบ†ไธ€ไธชๅฎž้™…็š„ Python `SpooledTemporaryFile` ๅฏน่ฑก๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไผ ็ป™ๆœŸๆœ›ใ€Œfile-likeใ€ๅฏน่ฑก็š„ๅ…ถไป–ๅบ“ใ€‚ -### `UploadFile` +### `UploadFile` { #uploadfile } `UploadFile` ็š„ๅฑžๆ€งๅฆ‚ไธ‹๏ผš -* `filename`๏ผšไธŠไผ ๆ–‡ไปถๅๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผŒ `myimage.jpg`๏ผ› -* `content_type`๏ผšๅ†…ๅฎน็ฑปๅž‹๏ผˆMIME ็ฑปๅž‹ / ๅช’ไฝ“็ฑปๅž‹๏ผ‰ๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผŒ`image/jpeg`๏ผ› -* `file`๏ผš `SpooledTemporaryFile`๏ผˆ file-like ๅฏน่ฑก๏ผ‰ใ€‚ๅ…ถๅฎžๅฐฑๆ˜ฏ Pythonๆ–‡ไปถ๏ผŒๅฏ็›ดๆŽฅไผ ้€’็ป™ๅ…ถไป–้ข„ๆœŸ `file-like` ๅฏน่ฑก็š„ๅ‡ฝๆ•ฐๆˆ–ๆ”ฏๆŒๅบ“ใ€‚ +* `filename`๏ผšไธŠไผ ็š„ๅŽŸๅง‹ๆ–‡ไปถๅๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰๏ผŒไพ‹ๅฆ‚ `myimage.jpg`ใ€‚ +* `content_type`๏ผšๅ†…ๅฎน็ฑปๅž‹๏ผˆMIME ็ฑปๅž‹ / ๅช’ไฝ“็ฑปๅž‹๏ผ‰็š„ๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰๏ผŒไพ‹ๅฆ‚ `image/jpeg`ใ€‚ +* `file`๏ผš`SpooledTemporaryFile`๏ผˆไธ€ไธช file-like ๅฏน่ฑก๏ผ‰ใ€‚่ฟ™ๆ˜ฏๅฎž้™…็š„ Python ๆ–‡ไปถๅฏน่ฑก๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไผ ้€’็ป™ๅ…ถไป–ๆœŸๆœ›ใ€Œfile-likeใ€ๅฏน่ฑก็š„ๅ‡ฝๆ•ฐๆˆ–ๅบ“ใ€‚ -`UploadFile` ๆ”ฏๆŒไปฅไธ‹ `async` ๆ–นๆณ•๏ผŒ๏ผˆไฝฟ็”จๅ†…้ƒจ `SpooledTemporaryFile`๏ผ‰ๅฏ่ฐƒ็”จ็›ธๅบ”็š„ๆ–‡ไปถๆ–นๆณ•ใ€‚ +`UploadFile` ๅ…ทๆœ‰ไปฅไธ‹ `async` ๆ–นๆณ•ใ€‚ๅฎƒไปฌ้ƒฝไผšๅœจๅบ•ๅฑ‚่ฐƒ็”จๅฏนๅบ”็š„ๆ–‡ไปถๆ–นๆณ•๏ผˆไฝฟ็”จๅ†…้ƒจ็š„ `SpooledTemporaryFile`๏ผ‰ใ€‚ -* `write(data)`๏ผšๆŠŠ `data` ๏ผˆ`str` ๆˆ– `bytes`๏ผ‰ๅ†™ๅ…ฅๆ–‡ไปถ๏ผ› -* `read(size)`๏ผšๆŒ‰ๆŒ‡ๅฎšๆ•ฐ้‡็š„ๅญ—่Š‚ๆˆ–ๅญ—็ฌฆ๏ผˆ`size` (`int`)๏ผ‰่ฏปๅ–ๆ–‡ไปถๅ†…ๅฎน๏ผ› -* `seek(offset)`๏ผš็งปๅŠจ่‡ณๆ–‡ไปถ `offset` ๏ผˆ`int`๏ผ‰ๅญ—่Š‚ๅค„็š„ไฝ็ฝฎ๏ผ› - * ไพ‹ๅฆ‚๏ผŒ`await myfile.seek(0) ` ็งปๅŠจๅˆฐๆ–‡ไปถๅผ€ๅคด๏ผ› - * ๆ‰ง่กŒ `await myfile.read()` ๅŽ๏ผŒ้œ€ๅ†ๆฌก่ฏปๅ–ๅทฒ่ฏปๅ–ๅ†…ๅฎนๆ—ถ๏ผŒ่ฟ™็งๆ–นๆณ•็‰นๅˆซๅฅฝ็”จ๏ผ› +* `write(data)`๏ผšๅฐ† `data`๏ผˆ`str` ๆˆ– `bytes`๏ผ‰ๅ†™ๅ…ฅๆ–‡ไปถใ€‚ +* `read(size)`๏ผš่ฏปๅ–ๆ–‡ไปถไธญ `size`๏ผˆ`int`๏ผ‰ไธชๅญ—่Š‚/ๅญ—็ฌฆใ€‚ +* `seek(offset)`๏ผš็งปๅŠจๅˆฐๆ–‡ไปถไธญๅญ—่Š‚ไฝ็ฝฎ `offset`๏ผˆ`int`๏ผ‰ใ€‚ + * ไพ‹ๅฆ‚๏ผŒ`await myfile.seek(0)` ไผš็งปๅŠจๅˆฐๆ–‡ไปถๅผ€ๅคดใ€‚ + * ๅฆ‚ๆžœไฝ ๅ…ˆ่ฟ่กŒ่ฟ‡ `await myfile.read()`๏ผŒ็„ถๅŽ้œ€่ฆๅ†ๆฌก่ฏปๅ–ๅ†…ๅฎนๆ—ถ๏ผŒ่ฟ™ๅฐคๅ…ถๆœ‰็”จใ€‚ * `close()`๏ผšๅ…ณ้—ญๆ–‡ไปถใ€‚ -ๅ› ไธบไธŠ่ฟฐๆ–นๆณ•้ƒฝๆ˜ฏ `async` ๆ–นๆณ•๏ผŒ่ฆๆญ้…ใ€Œawaitใ€ไฝฟ็”จใ€‚ +็”ฑไบŽ่ฟ™ไบ›ๆ–นๆณ•้ƒฝๆ˜ฏ `async` ๆ–นๆณ•๏ผŒไฝ ้œ€่ฆๅฏนๅฎƒไปฌไฝฟ็”จ awaitใ€‚ -ไพ‹ๅฆ‚๏ผŒๅœจ `async` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ๅ†…๏ผŒ่ฆ็”จไปฅไธ‹ๆ–นๅผ่ฏปๅ–ๆ–‡ไปถๅ†…ๅฎน๏ผš +ไพ‹ๅฆ‚๏ผŒๅœจ `async` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ๅ†…๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ท่Žทๅ–ๅ†…ๅฎน๏ผš ```Python contents = await myfile.read() ``` -ๅœจๆ™ฎ้€š `def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ๅ†…๏ผŒๅˆ™ๅฏไปฅ็›ดๆŽฅ่ฎฟ้—ฎ `UploadFile.file`๏ผŒไพ‹ๅฆ‚๏ผš +ๅฆ‚ๆžœๆ˜ฏๅœจๆ™ฎ้€š `def` *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ๅ†…๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅ่ฎฟ้—ฎ `UploadFile.file`๏ผŒไพ‹ๅฆ‚๏ผš ```Python contents = myfile.file.read() ``` -/// note | `async` ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ -ไฝฟ็”จ `async` ๆ–นๆณ•ๆ—ถ๏ผŒ**FastAPI** ๅœจ็บฟ็จ‹ๆฑ ไธญๆ‰ง่กŒๆ–‡ไปถๆ–นๆณ•๏ผŒๅนถ `await` ๆ“ไฝœๅฎŒๆˆใ€‚ +ๅฝ“ไฝ ไฝฟ็”จ่ฟ™ไบ› `async` ๆ–นๆณ•ๆ—ถ๏ผŒ**FastAPI** ไผšๅœจ็บฟ็จ‹ๆฑ ไธญ่ฟ่กŒ็›ธๅบ”็š„ๆ–‡ไปถๆ–นๆณ•ๅนถ็ญ‰ๅพ…ๅ…ถๅฎŒๆˆใ€‚ /// -/// note | Starlette ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ -**FastAPI** ็š„ `UploadFile` ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช **Starlette** ็š„ `UploadFile`๏ผŒไฝ†ๆทปๅŠ ไบ†ไธ€ไบ›ๅฟ…่ฆๅŠŸ่ƒฝ๏ผŒไฝฟไน‹ไธŽ **Pydantic** ๅŠ FastAPI ็š„ๅ…ถๅฎƒ้ƒจไปถๅ…ผๅฎนใ€‚ +**FastAPI** ็š„ `UploadFile` ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช **Starlette** ็š„ `UploadFile`๏ผŒไฝ†ๆทปๅŠ ไบ†ไธ€ไบ›ๅฟ…่ฆ็š„้ƒจๅˆ†๏ผŒไฝฟๅ…ถไธŽ **Pydantic** ไปฅๅŠ FastAPI ็š„ๅ…ถไป–้ƒจๅˆ†ๅ…ผๅฎนใ€‚ /// -## ไป€ไนˆๆ˜ฏ ใ€Œ่กจๅ•ๆ•ฐๆฎใ€ +## ไป€ไนˆๆ˜ฏใ€Œ่กจๅ•ๆ•ฐๆฎใ€ { #what-is-form-data } -ไธŽ JSON ไธๅŒ๏ผŒHTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ้€šๅธธไฝฟ็”จใ€Œ็‰นๆฎŠใ€็š„็ผ–็ ใ€‚ +HTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ็š„ๆ–นๅผ้€šๅธธไผšๅฏนๆ•ฐๆฎไฝฟ็”จไธ€็งใ€Œ็‰นๆฎŠใ€็š„็ผ–็ ๏ผŒ่ฟ™ไธŽ JSON ไธๅŒใ€‚ -**FastAPI** ่ฆ็กฎไฟไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่ฏปๅ–ๆ•ฐๆฎ๏ผŒ่€Œไธๆ˜ฏ่ฏปๅ– JSONใ€‚ +**FastAPI** ไผš็กฎไฟไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่ฏปๅ–่ฟ™ไบ›ๆ•ฐๆฎ๏ผŒ่€Œไธๆ˜ฏไปŽ JSON ไธญ่ฏปๅ–ใ€‚ -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ -ไธๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒ่กจๅ•ๆ•ฐๆฎไธ€่ˆฌ็”จ `application/x-www-form-urlencoded`ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€็ผ–็ ใ€‚ +ๅฝ“ไธๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒๆฅ่‡ช่กจๅ•็š„ๆ•ฐๆฎ้€šๅธธไฝฟ็”จใ€Œๅช’ไฝ“็ฑปๅž‹ใ€`application/x-www-form-urlencoded` ็ผ–็ ใ€‚ -ไฝ†่กจๅ•ๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒ็ผ–็ ไธบ `multipart/form-data`ใ€‚ไฝฟ็”จไบ† `File`๏ผŒ**FastAPI** ๅฐฑ็Ÿฅ้“่ฆไปŽ่ฏทๆฑ‚ไฝ“็š„ๆญฃ็กฎไฝ็ฝฎ่Žทๅ–ๆ–‡ไปถใ€‚ +ไฝ†ๅฝ“่กจๅ•ๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒไผš็ผ–็ ไธบ `multipart/form-data`ใ€‚ๅฆ‚ๆžœไฝ ไฝฟ็”จ `File`๏ผŒ**FastAPI** ไผš็Ÿฅ้“้œ€่ฆไปŽ่ฏทๆฑ‚ไฝ“็š„ๆญฃ็กฎไฝ็ฝฎ่Žทๅ–ๆ–‡ไปถใ€‚ -็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต่ฏฆ่ง MDN Web ๆ–‡ๆกฃ็š„ POST ๅฐ่Š‚ใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณ่ฟ›ไธ€ๆญฅไบ†่งฃ่ฟ™ไบ›็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต๏ผŒ่ฏทๅ‚้˜… MDN web docs for POSTใ€‚ /// /// warning | ่ญฆๅ‘Š -ๅฏๅœจไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜Žๅคšไธช `File` ๅ’Œ `Form` ๅ‚ๆ•ฐ๏ผŒไฝ†ไธ่ƒฝๅŒๆ—ถๅฃฐๆ˜Ž่ฆๆŽฅๆ”ถ JSON ็š„ `Body` ๅญ—ๆฎตใ€‚ๅ› ไธบๆญคๆ—ถ่ฏทๆฑ‚ไฝ“็š„็ผ–็ ๆ˜ฏ `multipart/form-data`๏ผŒไธๆ˜ฏ `application/json`ใ€‚ +ไฝ ๅฏไปฅๅœจไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜Žๅคšไธช `File` ๅ’Œ `Form` ๅ‚ๆ•ฐ๏ผŒไฝ†ไธ่ƒฝๅŒๆ—ถๅฃฐๆ˜ŽๅธŒๆœ›ไปฅ JSON ๆŽฅๆ”ถ็š„ `Body` ๅญ—ๆฎต๏ผŒๅ› ไธบๆญคๆ—ถ่ฏทๆฑ‚ไฝ“ไผšไฝฟ็”จ `multipart/form-data` ็ผ–็ ๏ผŒ่€Œไธๆ˜ฏ `application/json`ใ€‚ -่ฟ™ไธๆ˜ฏ **FastAPI** ็š„้—ฎ้ข˜๏ผŒ่€Œๆ˜ฏ HTTP ๅ่ฎฎ็š„่ง„ๅฎšใ€‚ +่ฟ™ไธๆ˜ฏ **FastAPI** ็š„้™ๅˆถ๏ผŒ่€Œๆ˜ฏ HTTP ๅ่ฎฎ็š„ไธ€้ƒจๅˆ†ใ€‚ /// -## ๅฏ้€‰ๆ–‡ไปถไธŠไผ  +## ๅฏ้€‰ๆ–‡ไปถไธŠไผ  { #optional-file-upload } ๆ‚จๅฏไปฅ้€š่ฟ‡ไฝฟ็”จๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃๅนถๅฐ† None ไฝœไธบ้ป˜่ฎคๅ€ผ็š„ๆ–นๅผๅฐ†ไธ€ไธชๆ–‡ไปถๅ‚ๆ•ฐ่ฎพไธบๅฏ้€‰: -{* ../../docs_src/request_files/tutorial001_02_py310.py hl[7,14] *} +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} -## ๅธฆๆœ‰้ขๅค–ๅ…ƒๆ•ฐๆฎ็š„ `UploadFile` +## ๅธฆๆœ‰้ขๅค–ๅ…ƒๆ•ฐๆฎ็š„ `UploadFile` { #uploadfile-with-additional-metadata } ๆ‚จไนŸๅฏไปฅๅฐ† `File()` ไธŽ `UploadFile` ไธ€่ตทไฝฟ็”จ๏ผŒไพ‹ๅฆ‚๏ผŒ่ฎพ็ฝฎ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎ: -{* ../../docs_src/request_files/tutorial001_03.py hl[13] *} +{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} -## ๅคšๆ–‡ไปถไธŠไผ  +## ๅคšๆ–‡ไปถไธŠไผ  { #multiple-file-uploads } FastAPI ๆ”ฏๆŒๅŒๆ—ถไธŠไผ ๅคšไธชๆ–‡ไปถใ€‚ -ๅฏ็”จๅŒไธ€ไธชใ€Œ่กจๅ•ๅญ—ๆฎตใ€ๅ‘้€ๅซๅคšไธชๆ–‡ไปถ็š„ใ€Œ่กจๅ•ๆ•ฐๆฎใ€ใ€‚ +ๅฎƒไปฌไผš่ขซๅ…ณ่”ๅˆฐๅŒไธ€ไธช้€š่ฟ‡ใ€Œ่กจๅ•ๆ•ฐๆฎใ€ๅ‘้€็š„ใ€Œ่กจๅ•ๅญ—ๆฎตใ€ใ€‚ -ไธŠไผ ๅคšไธชๆ–‡ไปถๆ—ถ๏ผŒ่ฆๅฃฐๆ˜Žๅซ `bytes` ๆˆ– `UploadFile` ็š„ๅˆ—่กจ๏ผˆ`List`๏ผ‰๏ผš +่ฆๅฎž็Žฐ่ฟ™ไธ€็‚น๏ผŒๅฃฐๆ˜Žไธ€ไธช็”ฑ `bytes` ๆˆ– `UploadFile` ็ป„ๆˆ็š„ๅˆ—่กจ๏ผˆ`List`๏ผ‰๏ผš -{* ../../docs_src/request_files/tutorial002_py39.py hl[8,13] *} +{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} ๆŽฅๆ”ถ็š„ไนŸๆ˜ฏๅซ `bytes` ๆˆ– `UploadFile` ็š„ๅˆ—่กจ๏ผˆ`list`๏ผ‰ใ€‚ - -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import HTMLResponse`ใ€‚ @@ -161,12 +165,12 @@ FastAPI ๆ”ฏๆŒๅŒๆ—ถไธŠไผ ๅคšไธชๆ–‡ไปถใ€‚ /// -### ๅธฆๆœ‰้ขๅค–ๅ…ƒๆ•ฐๆฎ็š„ๅคšๆ–‡ไปถไธŠไผ  +### ๅธฆๆœ‰้ขๅค–ๅ…ƒๆ•ฐๆฎ็š„ๅคšๆ–‡ไปถไธŠไผ  { #multiple-file-uploads-with-additional-metadata } -ๅ’Œไน‹ๅ‰็š„ๆ–นๅผไธ€ๆ ท, ๆ‚จๅฏไปฅไธบ `File()` ่ฎพ็ฝฎ้ขๅค–ๅ‚ๆ•ฐ, ๅณไฝฟๆ˜ฏ `UploadFile`: +ๅ’Œไน‹ๅ‰็š„ๆ–นๅผไธ€ๆ ท๏ผŒไฝ ๅฏไปฅไธบ `File()` ่ฎพ็ฝฎ้ขๅค–ๅ‚ๆ•ฐ๏ผŒๅณไฝฟๆ˜ฏ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial003_py39.py hl[16] *} +{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -ๆœฌ่Š‚ไป‹็ปไบ†ๅฆ‚ไฝ•็”จ `File` ๆŠŠไธŠไผ ๆ–‡ไปถๅฃฐๆ˜Žไธบ๏ผˆ่กจๅ•ๆ•ฐๆฎ็š„๏ผ‰่พ“ๅ…ฅๅ‚ๆ•ฐใ€‚ +ไฝฟ็”จ `File`ใ€`bytes` ๅ’Œ `UploadFile` ๆฅๅฃฐๆ˜Žๅœจ่ฏทๆฑ‚ไธญไธŠไผ ็š„ๆ–‡ไปถ๏ผŒๅฎƒไปฌไปฅ่กจๅ•ๆ•ฐๆฎๅ‘้€ใ€‚ diff --git a/docs/zh/docs/tutorial/request-form-models.md b/docs/zh/docs/tutorial/request-form-models.md index e639e4b9fc..4eb98ea225 100644 --- a/docs/zh/docs/tutorial/request-form-models.md +++ b/docs/zh/docs/tutorial/request-form-models.md @@ -1,12 +1,12 @@ -# ่กจๅ•ๆจกๅž‹ +# ่กจๅ•ๆจกๅž‹ { #form-models } -ๆ‚จๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ FastAPI ไธญๅฃฐๆ˜Ž**่กจๅ•ๅญ—ๆฎต**ใ€‚ +ไฝ ๅฏไปฅๅœจ FastAPI ไธญไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅฃฐๆ˜Ž**่กจๅ•ๅญ—ๆฎต**ใ€‚ -/// info +/// info | ไฟกๆฏ -่ฆไฝฟ็”จ่กจๅ•๏ผŒ้œ€้ข„ๅ…ˆๅฎ‰่ฃ… `python-multipart` ใ€‚ +่ฆไฝฟ็”จ่กจๅ•๏ผŒ้ฆ–ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ -็กฎไฟๆ‚จๅˆ›ๅปบใ€ๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}ๅŽๅ†ๅฎ‰่ฃ…ใ€‚ +็กฎไฟไฝ ๅˆ›ๅปบไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒๆฟ€ๆดปๅฎƒ๏ผŒ็„ถๅŽๅ†ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš ```console $ pip install python-multipart @@ -14,51 +14,51 @@ $ pip install python-multipart /// -/// note +/// note | ๆณจๆ„ ่‡ช FastAPI ็‰ˆๆœฌ `0.113.0` ่ตทๆ”ฏๆŒๆญคๅŠŸ่ƒฝใ€‚๐Ÿค“ /// -## ่กจๅ•็š„ Pydantic ๆจกๅž‹ +## ่กจๅ•็š„ Pydantic ๆจกๅž‹ { #pydantic-models-for-forms } -ๆ‚จๅช้œ€ๅฃฐๆ˜Žไธ€ไธช **Pydantic ๆจกๅž‹**๏ผŒๅ…ถไธญๅŒ…ๅซๆ‚จๅธŒๆœ›ๆŽฅๆ”ถ็š„**่กจๅ•ๅญ—ๆฎต**๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Form` : +ไฝ ๅช้œ€ๅฃฐๆ˜Žไธ€ไธช **Pydantic ๆจกๅž‹**๏ผŒๅ…ถไธญๅŒ…ๅซไฝ ๅธŒๆœ›ๆŽฅๆ”ถ็š„**่กจๅ•ๅญ—ๆฎต**๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Form`๏ผš {* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} -**FastAPI** ๅฐ†ไปŽ่ฏทๆฑ‚ไธญ็š„**่กจๅ•ๆ•ฐๆฎ**ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๆไพ›ๆ‚จๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ +**FastAPI** ๅฐ†ไปŽ่ฏทๆฑ‚ไธญ็š„**่กจๅ•ๆ•ฐๆฎ**ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๆไพ›ไฝ ๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ -## ๆฃ€ๆŸฅๆ–‡ๆกฃ +## ๆฃ€ๆŸฅๆ–‡ๆกฃ { #check-the-docs } -ๆ‚จๅฏไปฅๅœจๆ–‡ๆกฃ UI ไธญ้ชŒ่ฏๅฎƒ๏ผŒๅœฐๅ€ไธบ `/docs` ๏ผš +ไฝ ๅฏไปฅๅœจๆ–‡ๆกฃ UI ไธญ้ชŒ่ฏๅฎƒ๏ผŒๅœฐๅ€ไธบ `/docs`๏ผš
-## ็ฆๆญข้ขๅค–็š„่กจๅ•ๅญ—ๆฎต +## ็ฆๆญข้ขๅค–็š„่กจๅ•ๅญ—ๆฎต { #forbid-extra-form-fields } -ๅœจๆŸไบ›็‰นๆฎŠไฝฟ็”จๆƒ…ๅ†ตไธ‹๏ผˆๅฏ่ƒฝๅนถไธๅธธ่ง๏ผ‰๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›ๅฐ†่กจๅ•ๅญ—ๆฎต**้™ๅˆถ**ไธบไป…ๅœจ Pydantic ๆจกๅž‹ไธญๅฃฐๆ˜Ž่ฟ‡็š„ๅญ—ๆฎต๏ผŒๅนถ**็ฆๆญข**ไปปไฝ•**้ขๅค–**็š„ๅญ—ๆฎตใ€‚ +ๅœจๆŸไบ›็‰นๆฎŠไฝฟ็”จๆƒ…ๅ†ตไธ‹๏ผˆๅฏ่ƒฝๅนถไธๅธธ่ง๏ผ‰๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๅฐ†่กจๅ•ๅญ—ๆฎต**้™ๅˆถ**ไธบไป…ๅœจ Pydantic ๆจกๅž‹ไธญๅฃฐๆ˜Ž่ฟ‡็š„ๅญ—ๆฎต๏ผŒๅนถ**็ฆๆญข**ไปปไฝ•**้ขๅค–**็š„ๅญ—ๆฎตใ€‚ -/// note +/// note | ๆณจๆ„ ่‡ช FastAPI ็‰ˆๆœฌ `0.114.0` ่ตทๆ”ฏๆŒๆญคๅŠŸ่ƒฝใ€‚๐Ÿค“ /// -ๆ‚จๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ็ฆๆญข๏ผˆ `forbid` ๏ผ‰ไปปไฝ•้ขๅค–๏ผˆ `extra` ๏ผ‰ๅญ—ๆฎต๏ผš +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ `forbid` ไปปไฝ• `extra` ๅญ—ๆฎต๏ผš {* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} ๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ไธ€ไบ›้ขๅค–็š„ๆ•ฐๆฎ๏ผŒไป–ไปฌๅฐ†ๆ”ถๅˆฐ**้”™่ฏฏ**ๅ“ๅบ”ใ€‚ -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€่ฟ™ๆ ท็š„่กจๅ•ๅญ—ๆฎต๏ผš +ไพ‹ๅฆ‚๏ผŒๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ๅฆ‚ไธ‹่กจๅ•ๅญ—ๆฎต๏ผš * `username`: `Rick` * `password`: `Portal Gun` * `extra`: `Mr. Poopybutthole` -ไป–ไปฌๅฐ†ๆ”ถๅˆฐไธ€ๆก้”™่ฏฏๅ“ๅบ”๏ผŒ่กจๆ˜Žๅญ—ๆฎต `extra` ๆ˜ฏไธ่ขซๅ…่ฎธ็š„๏ผš +ไป–ไปฌๅฐ†ๆ”ถๅˆฐไธ€ๆก้”™่ฏฏๅ“ๅบ”๏ผŒ่กจๆ˜Žๅญ—ๆฎต `extra` ไธ่ขซๅ…่ฎธ๏ผš ```json { @@ -73,6 +73,6 @@ $ pip install python-multipart } ``` -## ๆ€ป็ป“ +## ๆ€ป็ป“ { #summary } -ๆ‚จๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ๅœจ FastAPI ไธญๅฃฐๆ˜Ž่กจๅ•ๅญ—ๆฎตใ€‚๐Ÿ˜Ž +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ๅœจ FastAPI ไธญๅฃฐๆ˜Ž่กจๅ•ๅญ—ๆฎตใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md index f72e5047a9..3c809868b2 100644 --- a/docs/zh/docs/tutorial/request-forms-and-files.md +++ b/docs/zh/docs/tutorial/request-forms-and-files.md @@ -1,24 +1,28 @@ -# ่ฏทๆฑ‚่กจๅ•ไธŽๆ–‡ไปถ +# ่ฏทๆฑ‚่กจๅ•ไธŽๆ–‡ไปถ { #request-forms-and-files } FastAPI ๆ”ฏๆŒๅŒๆ—ถไฝฟ็”จ `File` ๅ’Œ `Form` ๅฎšไน‰ๆ–‡ไปถๅ’Œ่กจๅ•ๅญ—ๆฎตใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๆŽฅๆ”ถไธŠไผ ๆ–‡ไปถๆˆ–่กจๅ•ๆ•ฐๆฎ๏ผŒ่ฆ้ข„ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ +ๆŽฅๆ”ถไธŠไผ ็š„ๆ–‡ไปถๅ’Œ/ๆˆ–่กจๅ•ๆ•ฐๆฎ๏ผŒ้ฆ–ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ -ไพ‹ๅฆ‚๏ผŒ`pip install python-multipart`ใ€‚ +่ฏทๅ…ˆๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅ†ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` /// -## ๅฏผๅ…ฅ `File` ไธŽ `Form` +## ๅฏผๅ…ฅ `File` ไธŽ `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001.py hl[1] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} -## ๅฎšไน‰ `File` ไธŽ `Form` ๅ‚ๆ•ฐ +## ๅฎšไน‰ `File` ไธŽ `Form` ๅ‚ๆ•ฐ { #define-file-and-form-parameters } ๅˆ›ๅปบๆ–‡ไปถๅ’Œ่กจๅ•ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๅ’Œ `Query` ไธ€ๆ ท๏ผš -{* ../../docs_src/request_forms_and_files/tutorial001.py hl[8] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} ๆ–‡ไปถๅ’Œ่กจๅ•ๅญ—ๆฎตไฝœไธบ่กจๅ•ๆ•ฐๆฎไธŠไผ ไธŽๆŽฅๆ”ถใ€‚ @@ -32,6 +36,6 @@ FastAPI ๆ”ฏๆŒๅŒๆ—ถไฝฟ็”จ `File` ๅ’Œ `Form` ๅฎšไน‰ๆ–‡ไปถๅ’Œ่กจๅ•ๅญ—ๆฎตใ€‚ /// -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } ๅœจๅŒไธ€ไธช่ฏทๆฑ‚ไธญๆŽฅๆ”ถๆ•ฐๆฎๅ’Œๆ–‡ไปถๆ—ถ๏ผŒๅบ”ๅŒๆ—ถไฝฟ็”จ `File` ๅ’Œ `Form`ใ€‚ diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md index ee03e82a7f..70eb93a260 100644 --- a/docs/zh/docs/tutorial/request-forms.md +++ b/docs/zh/docs/tutorial/request-forms.md @@ -1,69 +1,73 @@ -# ่กจๅ•ๆ•ฐๆฎ +# ่กจๅ•ๆ•ฐๆฎ { #form-data } -ๆŽฅๆ”ถ็š„ไธๆ˜ฏ JSON๏ผŒ่€Œๆ˜ฏ่กจๅ•ๅญ—ๆฎตๆ—ถ๏ผŒ่ฆไฝฟ็”จ `Form`ใ€‚ +ๅฝ“ไฝ ้œ€่ฆๆŽฅๆ”ถ่กจๅ•ๅญ—ๆฎต่€Œไธๆ˜ฏ JSON ๆ—ถ๏ผŒๅฏไปฅไฝฟ็”จ `Form`ใ€‚ -/// info | ่ฏดๆ˜Ž +/// info -่ฆไฝฟ็”จ่กจๅ•๏ผŒ้œ€้ข„ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ +่ฆไฝฟ็”จ่กจๅ•๏ผŒ้ฆ–ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ -ไพ‹ๅฆ‚๏ผŒ`pip install python-multipart`ใ€‚ +่ฏทๅ…ˆๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅ†่ฟ›่กŒๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` /// -## ๅฏผๅ…ฅ `Form` +## ๅฏผๅ…ฅ `Form` { #import-form } ไปŽ `fastapi` ๅฏผๅ…ฅ `Form`๏ผš -{* ../../docs_src/request_forms/tutorial001.py hl[1] *} +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} -## ๅฎšไน‰ `Form` ๅ‚ๆ•ฐ +## ๅฎšไน‰ `Form` ๅ‚ๆ•ฐ { #define-form-parameters } -ๅˆ›ๅปบ่กจๅ•๏ผˆ`Form`๏ผ‰ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๅ’Œ `Query` ไธ€ๆ ท๏ผš +ๅˆ›ๅปบ่กจๅ•ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๆˆ– `Query` ็›ธๅŒ๏ผš -{* ../../docs_src/request_forms/tutorial001.py hl[7] *} +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} -ไพ‹ๅฆ‚๏ผŒOAuth2 ่ง„่Œƒ็š„ "ๅฏ†็ ๆต" ๆจกๅผ่ง„ๅฎš่ฆ้€š่ฟ‡่กจๅ•ๅญ—ๆฎตๅ‘้€ `username` ๅ’Œ `password`ใ€‚ +ไพ‹ๅฆ‚๏ผŒๅœจ OAuth2 ่ง„่Œƒ็š„ไธ€็งไฝฟ็”จๆ–นๅผ๏ผˆ็งฐไธบโ€œๅฏ†็ ๆตโ€๏ผ‰ไธญ๏ผŒ่ฆๆฑ‚ๅฐ† `username` ๅ’Œ `password` ไฝœไธบ่กจๅ•ๅญ—ๆฎตๅ‘้€ใ€‚ -่ฏฅ่ง„่Œƒ่ฆๆฑ‚ๅญ—ๆฎตๅฟ…้กปๅ‘ฝๅไธบ `username` ๅ’Œ `password`๏ผŒๅนถ้€š่ฟ‡่กจๅ•ๅญ—ๆฎตๅ‘้€๏ผŒไธ่ƒฝ็”จ JSONใ€‚ +spec ่ฆๆฑ‚่ฟ™ไบ›ๅญ—ๆฎตๅฟ…้กป็ฒพ็กฎๅ‘ฝๅไธบ `username` ๅ’Œ `password`๏ผŒๅนถไธ”ไฝœไธบ่กจๅ•ๅญ—ๆฎตๅ‘้€๏ผŒ่€Œไธๆ˜ฏ JSONใ€‚ -ไฝฟ็”จ `Form` ๅฏไปฅๅฃฐๆ˜ŽไธŽ `Body` ๏ผˆๅŠ `Query`ใ€`Path`ใ€`Cookie`๏ผ‰็›ธๅŒ็š„ๅ…ƒๆ•ฐๆฎๅ’Œ้ชŒ่ฏใ€‚ +ไฝฟ็”จ `Form` ๅฏไปฅๅƒไฝฟ็”จ `Body`๏ผˆไปฅๅŠ `Query`ใ€`Path`ใ€`Cookie`๏ผ‰ไธ€ๆ ทๅฃฐๆ˜Ž็›ธๅŒ็š„้…็ฝฎ๏ผŒๅŒ…ๆ‹ฌๆ ก้ชŒใ€็คบไพ‹ใ€ๅˆซๅ๏ผˆไพ‹ๅฆ‚ๅฐ† `username` ๅ†™ๆˆ `user-name`๏ผ‰็ญ‰ใ€‚ -/// info | ่ฏดๆ˜Ž +/// info `Form` ๆ˜ฏ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช `Body` ็š„็ฑปใ€‚ /// -/// tip | ๆ็คบ +/// tip -ๅฃฐๆ˜Ž่กจๅ•ไฝ“่ฆๆ˜พๅผไฝฟ็”จ `Form` ๏ผŒๅฆๅˆ™๏ผŒFastAPI ไผšๆŠŠ่ฏฅๅ‚ๆ•ฐๅฝ“ไฝœๆŸฅ่ฏขๅ‚ๆ•ฐๆˆ–่ฏทๆฑ‚ไฝ“๏ผˆJSON๏ผ‰ๅ‚ๆ•ฐใ€‚ +่ฆๅฃฐๆ˜Ž่กจๅ•่ฏทๆฑ‚ไฝ“๏ผŒๅฟ…้กปๆ˜พๅผไฝฟ็”จ `Form`๏ผŒๅฆๅˆ™่ฟ™ไบ›ๅ‚ๆ•ฐไผš่ขซๅฝ“ไฝœๆŸฅ่ฏขๅ‚ๆ•ฐๆˆ–่ฏทๆฑ‚ไฝ“๏ผˆJSON๏ผ‰ๅ‚ๆ•ฐใ€‚ /// -## ๅ…ณไบŽ "่กจๅ•ๅญ—ๆฎต" +## ๅ…ณไบŽ "่กจๅ•ๅญ—ๆฎต" { #about-form-fields } -ไธŽ JSON ไธๅŒ๏ผŒHTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ้€šๅธธไฝฟ็”จใ€Œ็‰นๆฎŠใ€็š„็ผ–็ ใ€‚ +HTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎๆ—ถ้€šๅธธไผšๅฏนๆ•ฐๆฎไฝฟ็”จไธ€็งโ€œ็‰นๆฎŠโ€็š„็ผ–็ ๆ–นๅผ๏ผŒ่ฟ™ไธŽ JSON ไธๅŒใ€‚ -**FastAPI** ่ฆ็กฎไฟไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่ฏปๅ–ๆ•ฐๆฎ๏ผŒ่€Œไธๆ˜ฏ่ฏปๅ– JSONใ€‚ +**FastAPI** ไผš็กฎไฟไปŽๆญฃ็กฎ็š„ไฝ็ฝฎ่ฏปๅ–่ฟ™ไบ›ๆ•ฐๆฎ๏ผŒ่€Œไธๆ˜ฏไปŽ JSON ไธญ่ฏปๅ–ใ€‚ /// note | ๆŠ€ๆœฏ็ป†่Š‚ -่กจๅ•ๆ•ฐๆฎ็š„ใ€Œๅช’ไฝ“็ฑปๅž‹ใ€็ผ–็ ไธ€่ˆฌไธบ `application/x-www-form-urlencoded`ใ€‚ +่กจๅ•ๆ•ฐๆฎ้€šๅธธไฝฟ็”จโ€œๅช’ไฝ“็ฑปๅž‹โ€ `application/x-www-form-urlencoded` ่ฟ›่กŒ็ผ–็ ใ€‚ -ไฝ†ๅŒ…ๅซๆ–‡ไปถ็š„่กจๅ•็ผ–็ ไธบ `multipart/form-data`ใ€‚ๆ–‡ไปถๅค„็†่ฏฆ่งไธ‹่Š‚ใ€‚ +ไฝ†ๅฝ“่กจๅ•ๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒไผš็ผ–็ ไธบ `multipart/form-data`ใ€‚ไฝ ๅฐ†ๅœจไธ‹ไธ€็ซ ้˜…่ฏปๅฆ‚ไฝ•ๅค„็†ๆ–‡ไปถใ€‚ -็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต่ฏฆ่ง MDN Web ๆ–‡ๆกฃ็š„ POSTๅฐ่Š‚ใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃๆ›ดๅคšๅ…ณไบŽ่ฟ™ไบ›็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต็š„ไฟกๆฏ๏ผŒ่ฏทๅ‚้˜… MDN Web ๆ–‡ๆกฃ็š„ POSTใ€‚ /// -/// warning | ่ญฆๅ‘Š +/// warning -ๅฏๅœจไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜Žๅคšไธช `Form` ๅ‚ๆ•ฐ๏ผŒไฝ†ไธ่ƒฝๅŒๆ—ถๅฃฐๆ˜Ž่ฆๆŽฅๆ”ถ JSON ็š„ `Body` ๅญ—ๆฎตใ€‚ๅ› ไธบๆญคๆ—ถ่ฏทๆฑ‚ไฝ“็š„็ผ–็ ๆ˜ฏ `application/x-www-form-urlencoded`๏ผŒไธๆ˜ฏ `application/json`ใ€‚ +ไฝ ๅฏไปฅๅœจไธ€ไธช่ทฏๅพ„ๆ“ไฝœไธญๅฃฐๆ˜Žๅคšไธช `Form` ๅ‚ๆ•ฐ๏ผŒไฝ†ไธ่ƒฝๅŒๆ—ถๅ†ๅฃฐๆ˜Ž่ฆๆŽฅๆ”ถไธบ JSON ็š„ `Body` ๅญ—ๆฎต๏ผŒๅ› ไธบๆญคๆ—ถ่ฏทๆฑ‚ไฝ“ไผšไฝฟ็”จ `application/x-www-form-urlencoded` ่€Œไธๆ˜ฏ `application/json` ่ฟ›่กŒ็ผ–็ ใ€‚ -่ฟ™ไธๆ˜ฏ **FastAPI** ็š„้—ฎ้ข˜๏ผŒ่€Œๆ˜ฏ HTTP ๅ่ฎฎ็š„่ง„ๅฎšใ€‚ +่ฟ™ไธๆ˜ฏ **FastAPI** ็š„้™ๅˆถ๏ผŒ่€Œๆ˜ฏ HTTP ๅ่ฎฎ็š„ไธ€้ƒจๅˆ†ใ€‚ /// -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -ๆœฌ่Š‚ไป‹็ปไบ†ๅฆ‚ไฝ•ไฝฟ็”จ `Form` ๅฃฐๆ˜Ž่กจๅ•ๆ•ฐๆฎ่พ“ๅ…ฅๅ‚ๆ•ฐใ€‚ +ไฝฟ็”จ `Form` ๆฅๅฃฐๆ˜Ž่กจๅ•ๆ•ฐๆฎ่พ“ๅ…ฅๅ‚ๆ•ฐใ€‚ diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md index 049cd12238..791eb66fb7 100644 --- a/docs/zh/docs/tutorial/response-model.md +++ b/docs/zh/docs/tutorial/response-model.md @@ -1,6 +1,35 @@ -# ๅ“ๅบ”ๆจกๅž‹ +# ๅ“ๅบ”ๆจกๅž‹ - ่ฟ”ๅ›ž็ฑปๅž‹ { #response-model-return-type } -ไฝ ๅฏไปฅๅœจไปปๆ„็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญไฝฟ็”จ `response_model` ๅ‚ๆ•ฐๆฅๅฃฐๆ˜Ž็”จไบŽๅ“ๅบ”็š„ๆจกๅž‹๏ผš +ไฝ ๅฏไปฅ้€š่ฟ‡ไธบ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„**่ฟ”ๅ›ž็ฑปๅž‹**ๆทปๅŠ ๆณจ่งฃๆฅๅฃฐๆ˜Ž็”จไบŽๅ“ๅบ”็š„็ฑปๅž‹ใ€‚ + +ๅ’Œไธบ่พ“ๅ…ฅๆ•ฐๆฎๅœจๅ‡ฝๆ•ฐ**ๅ‚ๆ•ฐ**้‡Œๅš็ฑปๅž‹ๆณจ่งฃ็š„ๆ–นๅผ็›ธๅŒ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ใ€`list`ใ€`dict`ใ€ไปฅๅŠๆ•ดๆ•ฐใ€ๅธƒๅฐ”ๅ€ผ็ญ‰ๆ ‡้‡็ฑปๅž‹ใ€‚ + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI ไผšไฝฟ็”จ่ฟ™ไธช่ฟ”ๅ›ž็ฑปๅž‹ๆฅ๏ผš + +* ๅฏน่ฟ”ๅ›žๆ•ฐๆฎ่ฟ›่กŒ**ๆ ก้ชŒ**ใ€‚ + * ๅฆ‚ๆžœๆ•ฐๆฎๆ— ๆ•ˆ๏ผˆไพ‹ๅฆ‚็ผบๅฐ‘ๆŸไธชๅญ—ๆฎต๏ผ‰๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ไฝ ็š„ๅบ”็”จไปฃ็ ๆœ‰้—ฎ้ข˜๏ผŒๆฒกๆœ‰่ฟ”ๅ›žๅบ”ๆœ‰็š„ๆ•ฐๆฎ๏ผŒFastAPI ๅฐ†่ฟ”ๅ›žๆœๅŠกๅ™จ้”™่ฏฏ่€Œไธๆ˜ฏ่ฟ”ๅ›ž้”™่ฏฏ็š„ๆ•ฐๆฎใ€‚่ฟ™ๆ ทไฝ ๅ’Œไฝ ็š„ๅฎขๆˆท็ซฏ้ƒฝๅฏไปฅ็กฎๅฎšไผšๆ”ถๅˆฐๆœŸๆœ›็š„ๆ•ฐๆฎๅŠๅ…ถ็ป“ๆž„ใ€‚ +* ๅœจ OpenAPI ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญไธบๅ“ๅบ”ๆทปๅŠ **JSON Schema**ใ€‚ + * ๅฎƒไผš่ขซ**่‡ชๅŠจๆ–‡ๆกฃ**ไฝฟ็”จใ€‚ + * ๅฎƒไนŸไผš่ขซ่‡ชๅŠจๅฎขๆˆท็ซฏไปฃ็ ็”Ÿๆˆๅทฅๅ…ทไฝฟ็”จใ€‚ + +ไฝ†ๆ›ด้‡่ฆ็š„ๆ˜ฏ๏ผš + +* ๅฎƒไผšๅฐ†่พ“ๅ‡บๆ•ฐๆฎ**้™ๅˆถๅนถ่ฟ‡ๆปค**ไธบ่ฟ”ๅ›ž็ฑปๅž‹ไธญๅฎšไน‰็š„ๅ†…ๅฎนใ€‚ + * ่ฟ™ๅฏน**ๅฎ‰ๅ…จๆ€ง**ๅฐคไธบ้‡่ฆ๏ผŒไธ‹้ขไผš่ฟ›ไธ€ๆญฅไป‹็ปใ€‚ + +## `response_model` ๅ‚ๆ•ฐ { #response-model-parameter } + +ๅœจไธ€ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ้œ€่ฆๆˆ–ๅธŒๆœ›่ฟ”ๅ›ž็š„ๆ•ฐๆฎไธŽๅฃฐๆ˜Ž็š„็ฑปๅž‹ไธๅฎŒๅ…จไธ€่‡ดใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›**่ฟ”ๅ›žไธ€ไธชๅญ—ๅ…ธ**ๆˆ–ๆ•ฐๆฎๅบ“ๅฏน่ฑก๏ผŒไฝ†**ๅฐ†ๅ…ถๅฃฐๆ˜Žไธบไธ€ไธช Pydantic ๆจกๅž‹**ใ€‚่ฟ™ๆ ท Pydantic ๆจกๅž‹ๅฐฑไผšไธบไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ๅญ—ๅ…ธๆˆ–ๆ•ฐๆฎๅบ“ๅฏน่ฑก๏ผ‰ๅฎŒๆˆๆ–‡ๆกฃใ€ๆ ก้ชŒ็ญ‰ๅทฅไฝœใ€‚ + +ๅฆ‚ๆžœไฝ ๆทปๅŠ ไบ†่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ๏ผŒๅทฅๅ…ทๅ’Œ็ผ–่พ‘ๅ™จไผš๏ผˆๆญฃ็กฎๅœฐ๏ผ‰ๆŠฅ้”™๏ผŒๆ็คบไฝ ็š„ๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„็ฑปๅž‹๏ผˆไพ‹ๅฆ‚ `dict`๏ผ‰ไธŽๅฃฐๆ˜Ž็š„็ฑปๅž‹๏ผˆไพ‹ๅฆ‚ไธ€ไธช Pydantic ๆจกๅž‹๏ผ‰ไธๅŒใ€‚ + +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ๅ‚ๆ•ฐ `response_model`๏ผŒ่€Œไธๆ˜ฏ่ฟ”ๅ›ž็ฑปๅž‹ใ€‚ + +ไฝ ๅฏไปฅๅœจไปปๆ„*่ทฏๅพ„ๆ“ไฝœ*ไธญไฝฟ็”จ `response_model` ๅ‚ๆ•ฐ๏ผš * `@app.get()` * `@app.post()` @@ -10,102 +39,209 @@ {* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} -/// note +/// note | ๆณจๆ„ -ๆณจๆ„๏ผŒ`response_model`ๆ˜ฏใ€Œ่ฃ…้ฅฐๅ™จใ€ๆ–นๆณ•๏ผˆ`get`๏ผŒ`post` ็ญ‰๏ผ‰็š„ไธ€ไธชๅ‚ๆ•ฐใ€‚ไธๅƒไน‹ๅ‰็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“๏ผŒๅฎƒไธๅฑžไบŽ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ +ๆณจๆ„๏ผŒ`response_model` ๆ˜ฏใ€Œ่ฃ…้ฅฐๅ™จใ€ๆ–นๆณ•๏ผˆ`get`ใ€`post` ็ญ‰๏ผ‰็š„ไธ€ไธชๅ‚ๆ•ฐใ€‚ไธๆ˜ฏไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ๏ผŒไธๅƒๆ‰€ๆœ‰ๆŸฅ่ฏขๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“้‚ฃๆ ทใ€‚ /// -ๅฎƒๆŽฅๆ”ถ็š„็ฑปๅž‹ไธŽไฝ ๅฐ†ไธบ Pydantic ๆจกๅž‹ๅฑžๆ€งๆ‰€ๅฃฐๆ˜Ž็š„็ฑปๅž‹็›ธๅŒ๏ผŒๅ› ๆญคๅฎƒๅฏไปฅๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹๏ผŒไฝ†ไนŸๅฏไปฅๆ˜ฏไธ€ไธช็”ฑ Pydantic ๆจกๅž‹็ป„ๆˆ็š„ `list`๏ผŒไพ‹ๅฆ‚ `List[Item]`ใ€‚ +`response_model` ๆŽฅๆ”ถ็š„็ฑปๅž‹ไธŽไธบ Pydantic ๆจกๅž‹ๅญ—ๆฎตๅฃฐๆ˜Ž็š„็ฑปๅž‹็›ธๅŒ๏ผŒๅ› ๆญคๅฎƒๅฏไปฅๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹๏ผŒไนŸๅฏไปฅๆ˜ฏไธ€ไธช็”ฑ Pydantic ๆจกๅž‹็ป„ๆˆ็š„ `list`๏ผŒไพ‹ๅฆ‚ `List[Item]`ใ€‚ -FastAPI ๅฐ†ไฝฟ็”จๆญค `response_model` ๆฅ๏ผš +FastAPI ไผšไฝฟ็”จ่ฟ™ไธช `response_model` ๆฅๅฎŒๆˆๆ•ฐๆฎๆ–‡ๆกฃใ€ๆ ก้ชŒ็ญ‰๏ผŒๅนถไธ”่ฟ˜ไผšๅฐ†่พ“ๅ‡บๆ•ฐๆฎ**่ฝฌๆขๅนถ่ฟ‡ๆปค**ไธบๅ…ถ็ฑปๅž‹ๅฃฐๆ˜Žใ€‚ -* ๅฐ†่พ“ๅ‡บๆ•ฐๆฎ่ฝฌๆขไธบๅ…ถๅฃฐๆ˜Ž็š„็ฑปๅž‹ใ€‚ -* ๆ ก้ชŒๆ•ฐๆฎใ€‚ -* ๅœจ OpenAPI ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญไธบๅ“ๅบ”ๆทปๅŠ ไธ€ไธช JSON Schemaใ€‚ -* ๅนถๅœจ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ็ณป็ปŸไธญไฝฟ็”จใ€‚ +/// tip | ๆ็คบ -ไฝ†ๆœ€้‡่ฆ็š„ๆ˜ฏ๏ผš +ๅฆ‚ๆžœไฝ ็š„็ผ–่พ‘ๅ™จใ€mypy ็ญ‰่ฟ›่กŒไธฅๆ ผ็ฑปๅž‹ๆฃ€ๆŸฅ๏ผŒไฝ ๅฏไปฅๅฐ†ๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็ฑปๅž‹ๅฃฐๆ˜Žไธบ `Any`ใ€‚ -* ไผšๅฐ†่พ“ๅ‡บๆ•ฐๆฎ้™ๅˆถๅœจ่ฏฅๆจกๅž‹ๅฎšไน‰ๅ†…ใ€‚ไธ‹้ขๆˆ‘ไปฌไผš็œ‹ๅˆฐ่ฟ™ไธ€็‚นๆœ‰ๅคš้‡่ฆใ€‚ +่ฟ™ๆ ทไฝ ๅ‘Š่ฏ‰็ผ–่พ‘ๅ™จไฝ ๆ˜ฏๆœ‰ๆ„่ฟ”ๅ›žไปปๆ„็ฑปๅž‹ใ€‚ไฝ† FastAPI ไปไผšไฝฟ็”จ `response_model` ๅšๆ•ฐๆฎๆ–‡ๆกฃใ€ๆ ก้ชŒใ€่ฟ‡ๆปค็ญ‰ๅทฅไฝœใ€‚ -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// -ๅ“ๅบ”ๆจกๅž‹ๅœจๅ‚ๆ•ฐไธญ่ขซๅฃฐๆ˜Ž๏ผŒ่€Œไธๆ˜ฏไฝœไธบๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็ฑปๅž‹็š„ๆณจ่งฃ๏ผŒ่ฟ™ๆ˜ฏๅ› ไธบ่ทฏๅพ„ๅ‡ฝๆ•ฐๅฏ่ƒฝไธไผš็œŸๆญฃ่ฟ”ๅ›ž่ฏฅๅ“ๅบ”ๆจกๅž‹๏ผŒ่€Œๆ˜ฏ่ฟ”ๅ›žไธ€ไธช `dict`ใ€ๆ•ฐๆฎๅบ“ๅฏน่ฑกๆˆ–ๅ…ถไป–ๆจกๅž‹๏ผŒ็„ถๅŽๅ†ไฝฟ็”จ `response_model` ๆฅๆ‰ง่กŒๅญ—ๆฎต็บฆๆŸๅ’Œๅบๅˆ—ๅŒ–ใ€‚ +### `response_model` ็š„ไผ˜ๅ…ˆ็บง { #response-model-priority } -/// +ๅฆ‚ๆžœไฝ ๅŒๆ—ถๅฃฐๆ˜Žไบ†่ฟ”ๅ›ž็ฑปๅž‹ๅ’Œ `response_model`๏ผŒ`response_model` ไผšๅ…ทๆœ‰ไผ˜ๅ…ˆ็บงๅนถ็”ฑ FastAPI ไฝฟ็”จใ€‚ -## ่ฟ”ๅ›žไธŽ่พ“ๅ…ฅ็›ธๅŒ็š„ๆ•ฐๆฎ +่ฟ™ๆ ท๏ผŒๅณไฝฟไฝ ่ฟ”ๅ›ž็š„็ฑปๅž‹ไธŽๅ“ๅบ”ๆจกๅž‹ไธๅŒ๏ผŒไฝ ไนŸๅฏไปฅไธบๅ‡ฝๆ•ฐๆทปๅŠ ๆญฃ็กฎ็š„็ฑปๅž‹ๆณจ่งฃ๏ผŒไพ›็ผ–่พ‘ๅ™จๅ’Œ mypy ็ญ‰ๅทฅๅ…ทไฝฟ็”จใ€‚ๅŒๆ—ถไฝ ไป็„ถๅฏไปฅ่ฎฉ FastAPI ไฝฟ็”จ `response_model` ่ฟ›่กŒๆ•ฐๆฎๆ ก้ชŒใ€ๆ–‡ๆกฃ็ญ‰ใ€‚ -็Žฐๅœจๆˆ‘ไปฌๅฃฐๆ˜Žไธ€ไธช `UserIn` ๆจกๅž‹๏ผŒๅฎƒๅฐ†ๅŒ…ๅซไธ€ไธชๆ˜Žๆ–‡ๅฏ†็ ๅฑžๆ€งใ€‚ +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `response_model=None` ๆฅ็ฆ็”จ่ฏฅ*่ทฏๅพ„ๆ“ไฝœ*็š„ๅ“ๅบ”ๆจกๅž‹็”Ÿๆˆ๏ผ›ๅฝ“ไฝ ไธบไธ€ไบ›ไธๆ˜ฏๆœ‰ๆ•ˆ Pydantic ๅญ—ๆฎต็š„ไธœ่ฅฟๆทปๅŠ ็ฑปๅž‹ๆณจ่งฃๆ—ถ๏ผŒๅฏ่ƒฝ้œ€่ฆ่ฟ™ๆ ทๅš๏ผŒไธ‹้ข็š„็ซ ่Š‚ไผšๆœ‰็คบไพ‹ใ€‚ -{* ../../docs_src/response_model/tutorial002.py hl[9,11] *} +## ่ฟ”ๅ›žไธŽ่พ“ๅ…ฅ็›ธๅŒ็š„ๆ•ฐๆฎ { #return-the-same-input-data } -ๆˆ‘ไปฌๆญฃๅœจไฝฟ็”จๆญคๆจกๅž‹ๅฃฐๆ˜Ž่พ“ๅ…ฅๆ•ฐๆฎ๏ผŒๅนถไฝฟ็”จๅŒไธ€ๆจกๅž‹ๅฃฐๆ˜Ž่พ“ๅ‡บๆ•ฐๆฎ๏ผš +่ฟ™้‡Œๆˆ‘ไปฌๅฃฐๆ˜Žไธ€ไธช `UserIn` ๆจกๅž‹๏ผŒๅฎƒๅŒ…ๅซไธ€ไธชๆ˜Žๆ–‡ๅฏ†็ ๏ผš -{* ../../docs_src/response_model/tutorial002.py hl[17:18] *} +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -็Žฐๅœจ๏ผŒๆฏๅฝ“ๆต่งˆๅ™จไฝฟ็”จไธ€ไธชๅฏ†็ ๅˆ›ๅปบ็”จๆˆทๆ—ถ๏ผŒAPI ้ƒฝไผšๅœจๅ“ๅบ”ไธญ่ฟ”ๅ›ž็›ธๅŒ็š„ๅฏ†็ ใ€‚ +/// info | ไฟกๆฏ -ๅœจ่ฟ™ไธชๆกˆไพ‹ไธญ๏ผŒ่ฟ™ๅฏ่ƒฝไธ็ฎ—ๆ˜ฏ้—ฎ้ข˜๏ผŒๅ› ไธบ็”จๆˆท่‡ชๅทฑๆญฃๅœจๅ‘้€ๅฏ†็ ใ€‚ +่ฆไฝฟ็”จ `EmailStr`๏ผŒ้ฆ–ๅ…ˆๅฎ‰่ฃ… `email-validator`ใ€‚ -ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœๆˆ‘ไปฌๅœจๅ…ถไป–็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญไฝฟ็”จ็›ธๅŒ็š„ๆจกๅž‹๏ผŒๅˆ™ๅฏ่ƒฝไผšๅฐ†็”จๆˆท็š„ๅฏ†็ ๅ‘้€็ป™ๆฏไธชๅฎขๆˆท็ซฏใ€‚ +่ฏทๅ…ˆๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš -/// danger +```console +$ pip install email-validator +``` -ๆฐธ่ฟœไธ่ฆๅญ˜ๅ‚จ็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ๏ผŒไนŸไธ่ฆๅœจๅ“ๅบ”ไธญๅ‘้€ๅฏ†็ ใ€‚ +ๆˆ–่€…๏ผš + +```console +$ pip install "pydantic[email]" +``` /// -## ๆทปๅŠ ่พ“ๅ‡บๆจกๅž‹ +ๆˆ‘ไปฌไฝฟ็”จ่ฟ™ไธชๆจกๅž‹ๆฅๅฃฐๆ˜Ž่พ“ๅ…ฅ๏ผŒๅŒๆ—ถไนŸ็”จ็›ธๅŒ็š„ๆจกๅž‹ๆฅๅฃฐๆ˜Ž่พ“ๅ‡บ๏ผš + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +็Žฐๅœจ๏ผŒๆฏๅฝ“ๆต่งˆๅ™จไฝฟ็”จๅฏ†็ ๅˆ›ๅปบ็”จๆˆทๆ—ถ๏ผŒAPI ไผšๅœจๅ“ๅบ”ไธญ่ฟ”ๅ›ž็›ธๅŒ็š„ๅฏ†็ ใ€‚ -็›ธๅ๏ผŒๆˆ‘ไปฌๅฏไปฅๅˆ›ๅปบไธ€ไธชๆœ‰ๆ˜Žๆ–‡ๅฏ†็ ็š„่พ“ๅ…ฅๆจกๅž‹ๅ’Œไธ€ไธชๆฒกๆœ‰ๆ˜Žๆ–‡ๅฏ†็ ็š„่พ“ๅ‡บๆจกๅž‹๏ผš +ๅœจ่ฟ™ไธชๅœบๆ™ฏไธ‹๏ผŒ่ฟ™ๅฏ่ƒฝไธ็ฎ—้—ฎ้ข˜๏ผŒๅ› ไธบๅ‘้€ๅฏ†็ ็š„ๆ˜ฏๅŒไธ€ไธช็”จๆˆทใ€‚ + +ไฝ†ๅฆ‚ๆžœๆˆ‘ไปฌๅœจๅ…ถไป–*่ทฏๅพ„ๆ“ไฝœ*ไธญไฝฟ็”จ็›ธๅŒ็š„ๆจกๅž‹๏ผŒๅฐฑๅฏ่ƒฝไผšๆŠŠ็”จๆˆท็š„ๅฏ†็ ๅ‘้€็ป™ๆฏไธชๅฎขๆˆท็ซฏใ€‚ + +/// danger | ๅฑ้™ฉ + +้™ค้žไฝ ้žๅธธๆธ…ๆฅšๆ‰€ๆœ‰ๆณจๆ„ไบ‹้กนๅนถ็กฎๅฎž็Ÿฅ้“่‡ชๅทฑๅœจๅšไป€ไนˆ๏ผŒๅฆๅˆ™ๆฐธ่ฟœไธ่ฆๅญ˜ๅ‚จ็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ๏ผŒไนŸไธ่ฆๅƒ่ฟ™ๆ ทๅœจๅ“ๅบ”ไธญๅ‘้€ๅฎƒใ€‚ + +/// + +## ๆทปๅŠ ่พ“ๅ‡บๆจกๅž‹ { #add-an-output-model } + +็›ธๅ๏ผŒๆˆ‘ไปฌๅฏไปฅๅˆ›ๅปบไธ€ไธชๅŒ…ๅซๆ˜Žๆ–‡ๅฏ†็ ็š„่พ“ๅ…ฅๆจกๅž‹ๅ’Œไธ€ไธชไธๅŒ…ๅซๅฎƒ็š„่พ“ๅ‡บๆจกๅž‹๏ผš {* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} -่ฟ™ๆ ท๏ผŒๅณไพฟๆˆ‘ไปฌ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ๅฐ†ไผš่ฟ”ๅ›žๅŒ…ๅซๅฏ†็ ็š„็›ธๅŒ่พ“ๅ…ฅ็”จๆˆท๏ผš +่ฟ™้‡Œ๏ผŒๅณไฝฟๆˆ‘ไปฌ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*่ฟ”ๅ›ž็š„ๆ˜ฏๅŒ…ๅซๅฏ†็ ็š„ๅŒไธ€ไธช่พ“ๅ…ฅ็”จๆˆท๏ผš {* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} -...ๆˆ‘ไปฌๅทฒ็ปๅฐ† `response_model` ๅฃฐๆ˜Žไธบไบ†ไธๅŒ…ๅซๅฏ†็ ็š„ `UserOut` ๆจกๅž‹๏ผš +โ€ฆโ€ฆๆˆ‘ไปฌไปๅฐ† `response_model` ๅฃฐๆ˜ŽไธบไธๅŒ…ๅซๅฏ†็ ็š„ `UserOut` ๆจกๅž‹๏ผš {* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} -ๅ› ๆญค๏ผŒ**FastAPI** ๅฐ†ไผš่ดŸ่ดฃ่ฟ‡ๆปคๆމๆœชๅœจ่พ“ๅ‡บๆจกๅž‹ไธญๅฃฐๆ˜Ž็š„ๆ‰€ๆœ‰ๆ•ฐๆฎ๏ผˆไฝฟ็”จ Pydantic๏ผ‰ใ€‚ +ๅ› ๆญค๏ผŒ**FastAPI** ไผš่ดŸ่ดฃ่ฟ‡ๆปคๆމ่พ“ๅ‡บๆจกๅž‹ไธญๆœชๅฃฐๆ˜Ž็š„ๆ‰€ๆœ‰ๆ•ฐๆฎ๏ผˆไฝฟ็”จ Pydantic๏ผ‰ใ€‚ + +### `response_model` ่ฟ˜ๆ˜ฏ่ฟ”ๅ›ž็ฑปๅž‹ { #response-model-or-return-type } + +ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒๅ› ไธบไธคไธชๆจกๅž‹ไธๅŒ๏ผŒๅฆ‚ๆžœๆˆ‘ไปฌๅฐ†ๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃไธบ `UserOut`๏ผŒ็ผ–่พ‘ๅ™จๅ’Œๅทฅๅ…ทไผšๆŠฑๆ€จๆˆ‘ไปฌ่ฟ”ๅ›žไบ†ๆ— ๆ•ˆ็ฑปๅž‹๏ผŒๅ› ไธบๅฎƒไปฌๆ˜ฏไธๅŒ็š„็ฑปใ€‚ + +่ฟ™ๅฐฑๆ˜ฏไธบไป€ไนˆๅœจ่ฟ™ไธชไพ‹ๅญ้‡Œๆˆ‘ไปฌๅฟ…้กปๅœจ `response_model` ๅ‚ๆ•ฐไธญๅฃฐๆ˜Žๅฎƒใ€‚ + +โ€ฆโ€ฆไฝ†็ปง็ปญๅพ€ไธ‹่ฏป๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•ๆ›ดๅฅฝๅœฐๅค„็†่ฟ™็งๆƒ…ๅ†ตใ€‚ + +## ่ฟ”ๅ›ž็ฑปๅž‹ไธŽๆ•ฐๆฎ่ฟ‡ๆปค { #return-type-and-data-filtering } + +ๅปถ็ปญไธŠไธ€ไธชไพ‹ๅญใ€‚ๆˆ‘ไปฌๅธŒๆœ›**็”จไธ€็ง็ฑปๅž‹ๆฅๆณจ่งฃๅ‡ฝๆ•ฐ**๏ผŒไฝ†ๅธŒๆœ›ไปŽๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„ๅ†…ๅฎนๅฎž้™…ไธŠๅฏไปฅ**ๅŒ…ๅซๆ›ดๅคšๆ•ฐๆฎ**ใ€‚ + +ๆˆ‘ไปฌๅธŒๆœ› FastAPI ็ปง็ปญไฝฟ็”จๅ“ๅบ”ๆจกๅž‹ๆฅ**่ฟ‡ๆปค**ๆ•ฐๆฎใ€‚่ฟ™ๆ ทๅณไฝฟๅ‡ฝๆ•ฐ่ฟ”ๅ›žไบ†ๆ›ดๅคšๆ•ฐๆฎ๏ผŒๅ“ๅบ”ไนŸๅชไผšๅŒ…ๅซๅ“ๅบ”ๆจกๅž‹ไธญๅฃฐๆ˜Ž็š„ๅญ—ๆฎตใ€‚ + +ๅœจไธŠไธ€ไธชไพ‹ๅญไธญ๏ผŒๅ› ไธบ็ฑปไธๅŒ๏ผŒๆˆ‘ไปฌไธๅพ—ไธไฝฟ็”จ `response_model` ๅ‚ๆ•ฐใ€‚ไฝ†่ฟ™ไนŸๆ„ๅ‘ณ็€ๆˆ‘ไปฌๆ— ๆณ•ไปŽ็ผ–่พ‘ๅ™จๅ’Œๅทฅๅ…ทๅค„่Žทๅพ—ๅฏนๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็ฑปๅž‹็š„ๆฃ€ๆŸฅๆ”ฏๆŒใ€‚ + +ไธ่ฟ‡ๅœจๅคงๅคšๆ•ฐ้œ€่ฆ่ฟ™ๆ ทๅš็š„ๅœบๆ™ฏ้‡Œ๏ผŒๆˆ‘ไปฌๅชๆ˜ฏๅธŒๆœ›ๆจกๅž‹ๅƒ่ฟ™ไธชไพ‹ๅญไธญ้‚ฃๆ ท**่ฟ‡ๆปค/็งป้™ค**ไธ€้ƒจๅˆ†ๆ•ฐๆฎใ€‚ + +ๅœจ่ฟ™ไบ›ๅœบๆ™ฏ้‡Œ๏ผŒๆˆ‘ไปฌๅฏไปฅไฝฟ็”จ็ฑปๅ’Œ็ปงๆ‰ฟ๏ผŒๆ—ขๅˆฉ็”จๅ‡ฝๆ•ฐ็š„**็ฑปๅž‹ๆณจ่งฃ**่Žทๅ–ๆ›ดๅฅฝ็š„็ผ–่พ‘ๅ™จๅ’Œๅทฅๅ…ทๆ”ฏๆŒ๏ผŒๅˆ่ƒฝ่Žทๅพ— FastAPI ็š„**ๆ•ฐๆฎ่ฟ‡ๆปค**ใ€‚ + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} -## ๅœจๆ–‡ๆกฃไธญๆŸฅ็œ‹ +่ฟ™ๆ ทไธ€ๆฅ๏ผŒๆˆ‘ไปฌๆ—ข่ƒฝไปŽ็ผ–่พ‘ๅ™จๅ’Œ mypy ่Žทๅพ—ๅทฅๅ…ทๆ”ฏๆŒ๏ผˆ่ฟ™ๆฎตไปฃ็ ๅœจ็ฑปๅž‹ไธŠๆ˜ฏๆญฃ็กฎ็š„๏ผ‰๏ผŒไนŸ่ƒฝไปŽ FastAPI ่Žทๅพ—ๆ•ฐๆฎ่ฟ‡ๆปคใ€‚ -ๅฝ“ไฝ ๆŸฅ็œ‹่‡ชๅŠจๅŒ–ๆ–‡ๆกฃๆ—ถ๏ผŒไฝ ๅฏไปฅๆฃ€ๆŸฅ่พ“ๅ…ฅๆจกๅž‹ๅ’Œ่พ“ๅ‡บๆจกๅž‹ๆ˜ฏๅฆ้ƒฝๅ…ทๆœ‰่‡ชๅทฑ็š„ JSON Schema๏ผš +่ฟ™ๆ˜ฏๅฆ‚ไฝ•ๅšๅˆฐ็š„๏ผŸๆˆ‘ไปฌๆฅ็œ‹็œ‹ใ€‚๐Ÿค“ - +### ็ฑปๅž‹ๆณจ่งฃไธŽๅทฅๅ…ท้“พ { #type-annotations-and-tooling } -ๅนถไธ”ไธค็งๆจกๅž‹้ƒฝๅฐ†ๅœจไบคไบ’ๅผ API ๆ–‡ๆกฃไธญไฝฟ็”จ๏ผš +ๅ…ˆ็œ‹็œ‹็ผ–่พ‘ๅ™จใ€mypy ๅ’Œๅ…ถไป–ๅทฅๅ…ทไผšๅฆ‚ไฝ•็œ‹ๅพ…ๅฎƒใ€‚ - +`BaseUser` ๆœ‰ๅŸบ็ก€ๅญ—ๆฎตใ€‚็„ถๅŽ `UserIn` ็ปงๆ‰ฟ่‡ช `BaseUser` ๅนถๆ–ฐๅขžไบ† `password` ๅญ—ๆฎต๏ผŒๅ› ๆญคๅฎƒๅŒ…ๅซไบ†ไธคไธชๆจกๅž‹็š„ๅ…จ้ƒจๅญ—ๆฎตใ€‚ -## ๅ“ๅบ”ๆจกๅž‹็ผ–็ ๅ‚ๆ•ฐ +ๆˆ‘ไปฌๆŠŠๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃไธบ `BaseUser`๏ผŒไฝ†ๅฎž้™…ไธŠ่ฟ”ๅ›ž็š„ๆ˜ฏไธ€ไธช `UserIn` ๅฎžไพ‹ใ€‚ + +็ผ–่พ‘ๅ™จใ€mypy ๅ’Œๅ…ถไป–ๅทฅๅ…ทไธไผšๅฏนๆญคๆŠฑๆ€จ๏ผŒๅ› ไธบๅœจ็ฑปๅž‹็ณป็ปŸ้‡Œ๏ผŒ`UserIn` ๆ˜ฏ `BaseUser` ็š„ๅญ็ฑป๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ๅฝ“ๆœŸๆœ› `BaseUser` ๆ—ถ๏ผŒ่ฟ”ๅ›ž `UserIn` ๆ˜ฏ*ๅˆๆณ•*็š„ใ€‚ + +### FastAPI ็š„ๆ•ฐๆฎ่ฟ‡ๆปค { #fastapi-data-filtering } + +ๅฏนไบŽ FastAPI๏ผŒๅฎƒไผšๆŸฅ็œ‹่ฟ”ๅ›ž็ฑปๅž‹ๅนถ็กฎไฟไฝ ่ฟ”ๅ›ž็š„ๅ†…ๅฎน**ๅช**ๅŒ…ๅซ่ฏฅ็ฑปๅž‹ไธญๅฃฐๆ˜Ž็š„ๅญ—ๆฎตใ€‚ + +FastAPI ๅœจๅ†…้ƒจ้…ๅˆ Pydantic ๅšไบ†ๅคš้กนๅค„็†๏ผŒ็กฎไฟไธไผšๆŠŠ็ฑป็ปงๆ‰ฟ็š„่ฟ™ไบ›่ง„ๅˆ™็”จไบŽ่ฟ”ๅ›žๆ•ฐๆฎ็š„่ฟ‡ๆปค๏ผŒๅฆๅˆ™ไฝ ๅฏ่ƒฝไผš่ฟ”ๅ›žๆฏ”้ข„ๆœŸๅคšๅพ—ๅคš็š„ๆ•ฐๆฎใ€‚ + +่ฟ™ๆ ท๏ผŒไฝ ๅฐฑ่ƒฝๅ…ผๅพ—ไธคๆ–น้ข็š„ไผ˜ๅŠฟ๏ผšๅธฆๆœ‰**ๅทฅๅ…ทๆ”ฏๆŒ**็š„็ฑปๅž‹ๆณจ่งฃๅ’Œ**ๆ•ฐๆฎ่ฟ‡ๆปค**ใ€‚ + +## ๅœจๆ–‡ๆกฃไธญๆŸฅ็œ‹ { #see-it-in-the-docs } + +ๅฝ“ไฝ ๆŸฅ็œ‹่‡ชๅŠจๆ–‡ๆกฃๆ—ถ๏ผŒไฝ ไผš็œ‹ๅˆฐ่พ“ๅ…ฅๆจกๅž‹ๅ’Œ่พ“ๅ‡บๆจกๅž‹้ƒฝไผšๆœ‰ๅ„่‡ช็š„ JSON Schema๏ผš + + + +ๅนถไธ”ไธคไธชๆจกๅž‹้ƒฝไผš็”จไบŽไบคไบ’ๅผ API ๆ–‡ๆกฃ๏ผš + + + +## ๅ…ถไป–่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ { #other-return-type-annotations } + +ๆœ‰ไบ›ๆƒ…ๅ†ตไธ‹ไฝ ไผš่ฟ”ๅ›žไธ€ไบ›ไธๆ˜ฏๆœ‰ๆ•ˆ Pydantic ๅญ—ๆฎต็š„ๅ†…ๅฎน๏ผŒๅนถๅœจๅ‡ฝๆ•ฐไธŠๅšไบ†็›ธๅบ”ๆณจ่งฃ๏ผŒๅชๆ˜ฏไธบไบ†่Žทๅพ—ๅทฅๅ…ท้“พ๏ผˆ็ผ–่พ‘ๅ™จใ€mypy ็ญ‰๏ผ‰็š„ๆ”ฏๆŒใ€‚ + +### ็›ดๆŽฅ่ฟ”ๅ›ž Response { #return-a-response-directly } + +ๆœ€ๅธธ่ง็š„ๆƒ…ๅ†ตๆ˜ฏ[็›ดๆŽฅ่ฟ”ๅ›ž Response๏ผŒ่ฏฆ่ง่ฟ›้˜ถๆ–‡ๆกฃ](../advanced/response-directly.md){.internal-link target=_blank}ใ€‚ + +{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} + +่ฟ™ไธช็ฎ€ๅ•ๅœบๆ™ฏ FastAPI ไผš่‡ชๅŠจๅค„็†๏ผŒๅ› ไธบ่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃๆ˜ฏ `Response`๏ผˆๆˆ–ๅ…ถๅญ็ฑป๏ผ‰ใ€‚ + +ๅทฅๅ…ทไนŸไผšๆปกๆ„๏ผŒๅ› ไธบ `RedirectResponse` ๅ’Œ `JSONResponse` ้ƒฝๆ˜ฏ `Response` ็š„ๅญ็ฑป๏ผŒๆ‰€ไปฅ็ฑปๅž‹ๆณจ่งฃๆ˜ฏๆญฃ็กฎ็š„ใ€‚ + +### ๆณจ่งฃ Response ็š„ๅญ็ฑป { #annotate-a-response-subclass } + +ไฝ ไนŸๅฏไปฅๅœจ็ฑปๅž‹ๆณจ่งฃไธญไฝฟ็”จ `Response` ็š„ๅญ็ฑป๏ผš + +{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} + +่ฟ™ๅŒๆ ทๅฏ่กŒ๏ผŒๅ› ไธบ `RedirectResponse` ๆ˜ฏ `Response` ็š„ๅญ็ฑป๏ผŒFastAPI ไผš่‡ชๅŠจๅค„็†่ฟ™ไธช็ฎ€ๅ•ๅœบๆ™ฏใ€‚ + +### ๆ— ๆ•ˆ็š„่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ { #invalid-return-type-annotations } + +ไฝ†ๅฝ“ไฝ ่ฟ”ๅ›žๅ…ถไป–ไปปๆ„ๅฏน่ฑก๏ผˆๅฆ‚ๆ•ฐๆฎๅบ“ๅฏน่ฑก๏ผ‰่€Œๅฎƒไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ็ฑปๅž‹๏ผŒๅนถๅœจๅ‡ฝๆ•ฐไธญๆŒ‰ๆญค่ฟ›่กŒไบ†ๆณจ่งฃๆ—ถ๏ผŒFastAPI ไผšๅฐ่ฏ•ๅŸบไบŽ่ฏฅ็ฑปๅž‹ๆณจ่งฃๅˆ›ๅปบไธ€ไธช Pydantic ๅ“ๅบ”ๆจกๅž‹๏ผŒไฝ†ไผšๅคฑ่ดฅใ€‚ + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธชๅœจๅคšไธช็ฑปๅž‹ไน‹้—ด็š„่”ๅˆ็ฑปๅž‹๏ผŒๅ…ถไธญไธ€ไธชๆˆ–ๅคšไธชไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ็ฑปๅž‹๏ผŒไนŸไผšๅ‘็”ŸๅŒๆ ท็š„ๆƒ…ๅ†ต๏ผŒไพ‹ๅฆ‚่ฟ™ไธชไผšๅคฑ่ดฅ ๐Ÿ’ฅ๏ผš + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +โ€ฆโ€ฆๅฎƒๅคฑ่ดฅๆ˜ฏๅ› ไธบ่ฏฅ็ฑปๅž‹ๆณจ่งฃไธๆ˜ฏ Pydantic ็ฑปๅž‹๏ผŒไนŸไธๅชๆ˜ฏๅ•ไธช `Response` ็ฑปๆˆ–ๅ…ถๅญ็ฑป๏ผŒ่€Œๆ˜ฏ `Response` ไธŽ `dict` ็š„่”ๅˆ็ฑปๅž‹๏ผˆไปปๆ„ๅ…ถไธ€๏ผ‰ใ€‚ + +### ็ฆ็”จๅ“ๅบ”ๆจกๅž‹ { #disable-response-model } + +ๅปถ็ปญไธŠ้ข็š„ไพ‹ๅญ๏ผŒไฝ ๅฏ่ƒฝไธๆƒณ่ฆ FastAPI ๆ‰ง่กŒ้ป˜่ฎค็š„ๆ•ฐๆฎๆ ก้ชŒใ€ๆ–‡ๆกฃใ€่ฟ‡ๆปค็ญ‰ใ€‚ + +ไฝ†ไฝ ๅฏ่ƒฝไป็„ถๆƒณๅœจๅ‡ฝๆ•ฐไธŠไฟ็•™่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ๏ผŒไปฅ่Žทๅพ—็ผ–่พ‘ๅ™จๅ’Œ็ฑปๅž‹ๆฃ€ๆŸฅๅ™จ๏ผˆๅฆ‚ mypy๏ผ‰็š„ๆ”ฏๆŒใ€‚ + +ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `response_model=None` ๆฅ็ฆ็”จๅ“ๅบ”ๆจกๅž‹็”Ÿๆˆ๏ผš + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +่ฟ™ไผš่ฎฉ FastAPI ่ทณ่ฟ‡ๅ“ๅบ”ๆจกๅž‹็š„็”Ÿๆˆ๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๆŒ‰้œ€ไฝฟ็”จไปปๆ„่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ๏ผŒ่€Œไธไผšๅฝฑๅ“ไฝ ็š„ FastAPI ๅบ”็”จใ€‚๐Ÿค“ + +## ๅ“ๅบ”ๆจกๅž‹็š„็ผ–็ ๅ‚ๆ•ฐ { #response-model-encoding-parameters } ไฝ ็š„ๅ“ๅบ”ๆจกๅž‹ๅฏไปฅๅ…ทๆœ‰้ป˜่ฎคๅ€ผ๏ผŒไพ‹ๅฆ‚๏ผš -{* ../../docs_src/response_model/tutorial004.py hl[11,13:14] *} +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} -* `description: Union[str, None] = None` ๅ…ทๆœ‰้ป˜่ฎคๅ€ผ `None`ใ€‚ -* `tax: float = 10.5` ๅ…ทๆœ‰้ป˜่ฎคๅ€ผ `10.5`. -* `tags: List[str] = []` ๅ…ทๆœ‰ไธ€ไธช็ฉบๅˆ—่กจไฝœไธบ้ป˜่ฎคๅ€ผ๏ผš `[]`. +* `description: Union[str, None] = None`๏ผˆๆˆ–ๅœจ Python 3.10 ไธญ็š„ `str | None = None`๏ผ‰้ป˜่ฎคๅ€ผไธบ `None`ใ€‚ +* `tax: float = 10.5` ้ป˜่ฎคๅ€ผไธบ `10.5`ใ€‚ +* `tags: List[str] = []` ้ป˜่ฎคๅ€ผไธบไธ€ไธช็ฉบๅˆ—่กจ๏ผš`[]`ใ€‚ -ไฝ†ๅฆ‚ๆžœๅฎƒไปฌๅนถๆฒกๆœ‰ๅญ˜ๅ‚จๅฎž้™…็š„ๅ€ผ๏ผŒไฝ ๅฏ่ƒฝๆƒณไปŽ็ป“ๆžœไธญๅฟฝ็•ฅๅฎƒไปฌ็š„้ป˜่ฎคๅ€ผใ€‚ +ไฝ†ๅฆ‚ๆžœๅฎƒไปฌๅนถๆฒกๆœ‰่ขซๅฎž้™…ๅญ˜ๅ‚จ๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๅœจ็ป“ๆžœไธญ็œ็•ฅ่ฟ™ไบ›้ป˜่ฎคๅ€ผใ€‚ -ไธพไธชไพ‹ๅญ๏ผŒๅฝ“ไฝ ๅœจ NoSQL ๆ•ฐๆฎๅบ“ไธญไฟๅญ˜ไบ†ๅ…ทๆœ‰่ฎธๅคšๅฏ้€‰ๅฑžๆ€ง็š„ๆจกๅž‹๏ผŒไฝ†ไฝ ๅˆไธๆƒณๅ‘้€ๅ……ๆปก้ป˜่ฎคๅ€ผ็š„ๅพˆ้•ฟ็š„ JSON ๅ“ๅบ”ใ€‚ +ไพ‹ๅฆ‚๏ผŒๅฝ“ไฝ ๅœจ NoSQL ๆ•ฐๆฎๅบ“ไธญไฟๅญ˜ไบ†ๅ…ทๆœ‰่ฎธๅคšๅฏ้€‰ๅฑžๆ€ง็š„ๆจกๅž‹๏ผŒไฝ†ๅˆไธๆƒณๅ‘้€ๅ……ๆปก้ป˜่ฎคๅ€ผ็š„ๅ†—้•ฟ JSON ๅ“ๅบ”ใ€‚ -### ไฝฟ็”จ `response_model_exclude_unset` ๅ‚ๆ•ฐ +### ไฝฟ็”จ `response_model_exclude_unset` ๅ‚ๆ•ฐ { #use-the-response-model-exclude-unset-parameter } -ไฝ ๅฏไปฅ่ฎพ็ฝฎ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*็š„ `response_model_exclude_unset=True` ๅ‚ๆ•ฐ๏ผš +ไฝ ๅฏไปฅ่ฎพ็ฝฎ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ๅ‚ๆ•ฐ `response_model_exclude_unset=True`๏ผš -{* ../../docs_src/response_model/tutorial004.py hl[24] *} +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} -็„ถๅŽๅ“ๅบ”ไธญๅฐ†ไธไผšๅŒ…ๅซ้‚ฃไบ›้ป˜่ฎคๅ€ผ๏ผŒ่€Œๆ˜ฏไป…ๆœ‰ๅฎž้™…่ฎพ็ฝฎ็š„ๅ€ผใ€‚ +่ฟ™ๆ ทๅ“ๅบ”ไธญๅฐ†ไธไผšๅŒ…ๅซ้‚ฃไบ›้ป˜่ฎคๅ€ผ๏ผŒ่€ŒๅชๅŒ…ๅซๅฎž้™…่ฎพ็ฝฎ็š„ๅ€ผใ€‚ -ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๅ‘*่ทฏๅพ„ๆ“ไฝœ*ๅ‘้€ ID ไธบ `foo` ็š„ๅ•†ๅ“็š„่ฏทๆฑ‚๏ผŒๅˆ™ๅ“ๅบ”๏ผˆไธๅŒ…ๆ‹ฌ้ป˜่ฎคๅ€ผ๏ผ‰ๅฐ†ไธบ๏ผš +ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๅ‘่ฏฅ*่ทฏๅพ„ๆ“ไฝœ*่ฏทๆฑ‚ ID ไธบ `foo` ็š„ๅ•†ๅ“๏ผŒๅ“ๅบ”๏ผˆไธๅŒ…ๆ‹ฌ้ป˜่ฎคๅ€ผ๏ผ‰ๅฐ†ไธบ๏ผš ```JSON { @@ -114,24 +250,18 @@ FastAPI ๅฐ†ไฝฟ็”จๆญค `response_model` ๆฅ๏ผš } ``` -/// info - -FastAPI ้€š่ฟ‡ Pydantic ๆจกๅž‹็š„ `.dict()` ้…ๅˆ ่ฏฅๆ–นๆณ•็š„ `exclude_unset` ๅ‚ๆ•ฐ ๆฅๅฎž็ŽฐๆญคๅŠŸ่ƒฝใ€‚ - -/// - -/// info +/// info | ไฟกๆฏ ไฝ ่ฟ˜ๅฏไปฅไฝฟ็”จ๏ผš * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -ๅ‚่€ƒ Pydantic ๆ–‡ๆกฃ ไธญๅฏน `exclude_defaults` ๅ’Œ `exclude_none` ็š„ๆ่ฟฐใ€‚ +่ฏฆ่ง Pydantic ๆ–‡ๆกฃไธญๅฏน `exclude_defaults` ๅ’Œ `exclude_none` ็š„่ฏดๆ˜Žใ€‚ /// -#### ้ป˜่ฎคๅ€ผๅญ—ๆฎตๆœ‰ๅฎž้™…ๅ€ผ็š„ๆ•ฐๆฎ +#### ้ป˜่ฎคๅญ—ๆฎตๆœ‰ๅฎž้™…ๅ€ผ็š„ๆ•ฐๆฎ { #data-with-values-for-fields-with-defaults } ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ ็š„ๆ•ฐๆฎๅœจๅ…ทๆœ‰้ป˜่ฎคๅ€ผ็š„ๆจกๅž‹ๅญ—ๆฎตไธญๆœ‰ๅฎž้™…็š„ๅ€ผ๏ผŒไพ‹ๅฆ‚ ID ไธบ `bar` ็š„้กน๏ผš @@ -146,7 +276,7 @@ FastAPI ้€š่ฟ‡ Pydantic ๆจกๅž‹็š„ `.dict()` ้…ๅˆ `http.HTTPStatus`ใ€‚ @@ -31,7 +31,7 @@ -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ ๆŸไบ›ๅ“ๅบ”็Šถๆ€็ ่กจ็คบๅ“ๅบ”ๆฒกๆœ‰ๅ“ๅบ”ไฝ“๏ผˆๅ‚้˜…ไธ‹ไธ€็ซ ๏ผ‰ใ€‚ @@ -39,9 +39,9 @@ FastAPI ๅฏไปฅ่ฟ›่กŒ่ฏ†ๅˆซ๏ผŒๅนถ็”Ÿๆˆ่กจๆ˜Žๆ— ๅ“ๅบ”ไฝ“็š„ OpenAPI ๆ–‡ๆกฃใ€‚ /// -## ๅ…ณไบŽ HTTP ็Šถๆ€็  +## ๅ…ณไบŽ HTTP ็Šถๆ€็  { #about-http-status-codes } -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ ๅฆ‚ๆžœๅทฒ็ปไบ†่งฃ HTTP ็Šถๆ€็ ๏ผŒ่ฏท่ทณๅˆฐไธ‹ไธ€็ซ ใ€‚ @@ -53,40 +53,40 @@ FastAPI ๅฏไปฅ่ฟ›่กŒ่ฏ†ๅˆซ๏ผŒๅนถ็”Ÿๆˆ่กจๆ˜Žๆ— ๅ“ๅบ”ไฝ“็š„ OpenAPI ๆ–‡ๆกฃใ€‚ ็ฎ€่จ€ไน‹๏ผš -* `100` ๅŠไปฅไธŠ็š„็Šถๆ€็ ็”จไบŽ่ฟ”ๅ›ž**ไฟกๆฏ**ใ€‚่ฟ™็ฑป็Šถๆ€็ ๅพˆๅฐ‘็›ดๆŽฅไฝฟ็”จใ€‚ๅ…ทๆœ‰่ฟ™ไบ›็Šถๆ€็ ็š„ๅ“ๅบ”ไธ่ƒฝๅŒ…ๅซๅ“ๅบ”ไฝ“ -* **`200`** ๅŠไปฅไธŠ็š„็Šถๆ€็ ็”จไบŽ่กจ็คบ**ๆˆๅŠŸ**ใ€‚่ฟ™ไบ›็Šถๆ€็ ๆ˜ฏๆœ€ๅธธ็”จ็š„ - * `200` ๆ˜ฏ้ป˜่ฎค็Šถๆ€ไปฃ็ ๏ผŒ่กจ็คบไธ€ๅˆ‡**ๆญฃๅธธ** - * `201` ่กจ็คบ**ๅทฒๅˆ›ๅปบ**๏ผŒ้€šๅธธๅœจๆ•ฐๆฎๅบ“ไธญๅˆ›ๅปบๆ–ฐ่ฎฐๅฝ•ๅŽไฝฟ็”จ - * `204` ๆ˜ฏไธ€็ง็‰นๆฎŠ็š„ไพ‹ๅญ๏ผŒ่กจ็คบ**ๆ— ๅ†…ๅฎน**ใ€‚่ฏฅๅ“ๅบ”ๅœจๆฒกๆœ‰ไธบๅฎขๆˆท็ซฏ่ฟ”ๅ›žๅ†…ๅฎนๆ—ถไฝฟ็”จ๏ผŒๅ› ๆญค๏ผŒ่ฏฅๅ“ๅบ”ไธ่ƒฝๅŒ…ๅซๅ“ๅบ”ไฝ“ -* **`300`** ๅŠไปฅไธŠ็š„็Šถๆ€็ ็”จไบŽ**้‡ๅฎšๅ‘**ใ€‚ๅ…ทๆœ‰่ฟ™ไบ›็Šถๆ€็ ็š„ๅ“ๅบ”ไธไธ€ๅฎšๅŒ…ๅซๅ“ๅบ”ไฝ“๏ผŒไฝ† `304`**ๆœชไฟฎๆ”น**ๆ˜ฏไธชไพ‹ๅค–๏ผŒ่ฏฅๅ“ๅบ”ไธๅพ—ๅŒ…ๅซๅ“ๅบ”ไฝ“ -* **`400`** ๅŠไปฅไธŠ็š„็Šถๆ€็ ็”จไบŽ่กจ็คบ**ๅฎขๆˆท็ซฏ้”™่ฏฏ**ใ€‚่ฟ™ไบ›ๅฏ่ƒฝๆ˜ฏ็ฌฌไบŒๅธธ็”จ็š„็ฑปๅž‹ - * `404`๏ผŒ็”จไบŽ**ๆœชๆ‰พๅˆฐ**ๅ“ๅบ” +* `100 - 199` ็”จไบŽ่ฟ”ๅ›žโ€œไฟกๆฏโ€ใ€‚่ฟ™็ฑป็Šถๆ€็ ๅพˆๅฐ‘็›ดๆŽฅไฝฟ็”จใ€‚ๅ…ทๆœ‰่ฟ™ไบ›็Šถๆ€็ ็š„ๅ“ๅบ”ไธ่ƒฝๅŒ…ๅซๅ“ๅบ”ไฝ“ +* **`200 - 299`** ็”จไบŽ่กจ็คบโ€œๆˆๅŠŸโ€ใ€‚่ฟ™ไบ›็Šถๆ€็ ๆ˜ฏๆœ€ๅธธ็”จ็š„ + * `200` ๆ˜ฏ้ป˜่ฎค็Šถๆ€็ ๏ผŒ่กจ็คบไธ€ๅˆ‡โ€œOKโ€ + * `201` ่กจ็คบโ€œๅทฒๅˆ›ๅปบโ€๏ผŒ้€šๅธธๅœจๆ•ฐๆฎๅบ“ไธญๅˆ›ๅปบๆ–ฐ่ฎฐๅฝ•ๅŽไฝฟ็”จ + * `204` ๆ˜ฏไธ€็ง็‰นๆฎŠ็š„ไพ‹ๅญ๏ผŒ่กจ็คบโ€œๆ— ๅ†…ๅฎนโ€ใ€‚่ฏฅๅ“ๅบ”ๅœจๆฒกๆœ‰ไธบๅฎขๆˆท็ซฏ่ฟ”ๅ›žๅ†…ๅฎนๆ—ถไฝฟ็”จ๏ผŒๅ› ๆญค๏ผŒ่ฏฅๅ“ๅบ”ไธ่ƒฝๅŒ…ๅซๅ“ๅบ”ไฝ“ +* **`300 - 399`** ็”จไบŽโ€œ้‡ๅฎšๅ‘โ€ใ€‚ๅ…ทๆœ‰่ฟ™ไบ›็Šถๆ€็ ็š„ๅ“ๅบ”ไธไธ€ๅฎšๅŒ…ๅซๅ“ๅบ”ไฝ“๏ผŒไฝ† `304`โ€œๆœชไฟฎๆ”นโ€ๆ˜ฏไธชไพ‹ๅค–๏ผŒ่ฏฅๅ“ๅบ”ไธๅพ—ๅŒ…ๅซๅ“ๅบ”ไฝ“ +* **`400 - 499`** ็”จไบŽ่กจ็คบโ€œๅฎขๆˆท็ซฏ้”™่ฏฏโ€ใ€‚่ฟ™ไบ›ๅฏ่ƒฝๆ˜ฏ็ฌฌไบŒๅธธ็”จ็š„็ฑปๅž‹ + * `404`๏ผŒ็”จไบŽโ€œๆœชๆ‰พๅˆฐโ€ๅ“ๅบ” * ๅฏนไบŽๆฅ่‡ชๅฎขๆˆท็ซฏ็š„ไธ€่ˆฌ้”™่ฏฏ๏ผŒๅฏไปฅๅชไฝฟ็”จ `400` -* `500` ๅŠไปฅไธŠ็š„็Šถๆ€็ ็”จไบŽ่กจ็คบๆœๅŠกๅ™จ็ซฏ้”™่ฏฏใ€‚ๅ‡ ไนŽๆฐธ่ฟœไธไผš็›ดๆŽฅไฝฟ็”จ่ฟ™ไบ›็Šถๆ€็ ใ€‚ๅบ”็”จไปฃ็ ๆˆ–ๆœๅŠกๅ™จๅ‡บ็Žฐ้—ฎ้ข˜ๆ—ถ๏ผŒไผš่‡ชๅŠจ่ฟ”ๅ›ž่ฟ™ไบ›็Šถๆ€ไปฃ็  +* `500 - 599` ็”จไบŽ่กจ็คบๆœๅŠกๅ™จ็ซฏ้”™่ฏฏใ€‚ๅ‡ ไนŽๆฐธ่ฟœไธไผš็›ดๆŽฅไฝฟ็”จ่ฟ™ไบ›็Šถๆ€็ ใ€‚ๅบ”็”จไปฃ็ ๆˆ–ๆœๅŠกๅ™จๅ‡บ็Žฐ้—ฎ้ข˜ๆ—ถ๏ผŒไผš่‡ชๅŠจ่ฟ”ๅ›ž่ฟ™ไบ›็Šถๆ€็  /// tip | ๆ็คบ -็Šถๆ€็ ๅŠ้€‚็”จๅœบๆ™ฏ็š„่ฏฆๆƒ…๏ผŒ่ฏทๅ‚้˜… MDN ็š„ HTTP ็Šถๆ€็ ๆ–‡ๆกฃใ€‚ +็Šถๆ€็ ๅŠ้€‚็”จๅœบๆ™ฏ็š„่ฏฆๆƒ…๏ผŒ่ฏทๅ‚้˜… MDN ็š„ HTTP ็Šถๆ€็ ๆ–‡ๆกฃใ€‚ /// -## ็Šถๆ€็ ๅ็งฐๅฟซๆทๆ–นๅผ +## ็Šถๆ€็ ๅ็งฐๅฟซๆทๆ–นๅผ { #shortcut-to-remember-the-names } ๅ†็œ‹ไธ‹ไน‹ๅ‰็š„ไพ‹ๅญ๏ผš -{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} -`201` ่กจ็คบ**ๅทฒๅˆ›ๅปบ**็š„็Šถๆ€็ ใ€‚ +`201` ่กจ็คบโ€œๅทฒๅˆ›ๅปบโ€็š„็Šถๆ€็ ใ€‚ ไฝ†ๆˆ‘ไปฌๆฒกๆœ‰ๅฟ…่ฆ่ฎฐไฝๆ‰€ๆœ‰ไปฃ็ ็š„ๅซไน‰ใ€‚ ๅฏไปฅไฝฟ็”จ `fastapi.status` ไธญ็š„ๅฟซๆทๅ˜้‡ใ€‚ -{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} ่ฟ™ๅชๆ˜ฏไธ€็งๅฟซๆทๆ–นๅผ๏ผŒๅ…ทๆœ‰็›ธๅŒ็š„ๆ•ฐๅญ—ไปฃ็ ๏ผŒไฝ†ๅฎƒๅฏไปฅไฝฟ็”จ็ผ–่พ‘ๅ™จ็š„่‡ชๅŠจ่กฅๅ…จๅŠŸ่ƒฝ๏ผš - + /// note | ๆŠ€ๆœฏ็ป†่Š‚ @@ -96,6 +96,6 @@ FastAPI ๅฏไปฅ่ฟ›่กŒ่ฏ†ๅˆซ๏ผŒๅนถ็”Ÿๆˆ่กจๆ˜Žๆ— ๅ“ๅบ”ไฝ“็š„ OpenAPI ๆ–‡ๆกฃใ€‚ /// -## ๆ›ดๆ”น้ป˜่ฎค็Šถๆ€็  +## ๆ›ดๆ”น้ป˜่ฎค็Šถๆ€็  { #changing-the-default } [้ซ˜็บง็”จๆˆทๆŒ‡ๅ—](../advanced/response-change-status-code.md){.internal-link target=_blank}ไธญ๏ผŒๅฐ†ไป‹็ปๅฆ‚ไฝ•่ฟ”ๅ›žไธŽๅœจๆญคๅฃฐๆ˜Ž็š„้ป˜่ฎค็Šถๆ€็ ไธๅŒ็š„็Šถๆ€็ ใ€‚ diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md index 6c132eed3f..818ff5087b 100644 --- a/docs/zh/docs/tutorial/schema-extra-example.md +++ b/docs/zh/docs/tutorial/schema-extra-example.md @@ -1,55 +1,202 @@ -# ๆจกๅผ็š„้ขๅค–ไฟกๆฏ - ไพ‹ๅญ +# ๅฃฐๆ˜Ž่ฏทๆฑ‚็คบไพ‹ๆ•ฐๆฎ { #declare-request-example-data } -ๆ‚จๅฏไปฅๅœจJSONๆจกๅผไธญๅฎšไน‰้ขๅค–็š„ไฟกๆฏใ€‚ +ไฝ ๅฏไปฅไธบไฝ ็š„ๅบ”็”จๅฐ†ๆŽฅๆ”ถ็š„ๆ•ฐๆฎๅฃฐๆ˜Ž็คบไพ‹ใ€‚ -ไธ€ไธชๅธธ่ง็š„็”จไพ‹ๆ˜ฏๆทปๅŠ ไธ€ไธชๅฐ†ๅœจๆ–‡ๆกฃไธญๆ˜พ็คบ็š„`example`ใ€‚ +่ฟ™้‡Œๆœ‰ๅ‡ ็งๅฎž็Žฐๆ–นๅผใ€‚ -ๆœ‰ๅ‡ ็งๆ–นๆณ•ๅฏไปฅๅฃฐๆ˜Ž้ขๅค–็š„ JSON ๆจกๅผไฟกๆฏใ€‚ +## Pydantic ๆจกๅž‹ไธญ็š„้ขๅค– JSON Schema ๆ•ฐๆฎ { #extra-json-schema-data-in-pydantic-models } -## Pydantic `schema_extra` +ไฝ ๅฏไปฅไธบไธ€ไธช Pydantic ๆจกๅž‹ๅฃฐๆ˜Ž `examples`๏ผŒๅฎƒไปฌไผš่ขซๆทปๅŠ ๅˆฐ็”Ÿๆˆ็š„ JSON Schema ไธญใ€‚ -ๆ‚จๅฏไปฅไฝฟ็”จ `Config` ๅ’Œ `schema_extra` ไธบPydanticๆจกๅž‹ๅฃฐๆ˜Žไธ€ไธช็คบไพ‹๏ผŒๅฆ‚Pydantic ๆ–‡ๆกฃ๏ผšๅฎšๅˆถ Schema ไธญๆ‰€่ฟฐ: +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:21] *} +่ฟ™ไบ›้ขๅค–ไฟกๆฏไผšๅŽŸๆ ทๆทปๅŠ ๅˆฐ่ฏฅๆจกๅž‹่พ“ๅ‡บ็š„ JSON Schema ไธญ๏ผŒๅนถไผšๅœจ API ๆ–‡ๆกฃไธญไฝฟ็”จใ€‚ -่ฟ™ไบ›้ขๅค–็š„ไฟกๆฏๅฐ†ๆŒ‰ๅŽŸๆ ทๆทปๅŠ ๅˆฐ่พ“ๅ‡บ็š„JSONๆจกๅผไธญใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จๅฑžๆ€ง `model_config`๏ผŒๅฎƒๆŽฅๆ”ถไธ€ไธช `dict`๏ผŒ่ฏฆ่ง Pydantic ๆ–‡ๆกฃ๏ผš้…็ฝฎใ€‚ -## `Field` ็š„้™„ๅŠ ๅ‚ๆ•ฐ +ไฝ ๅฏไปฅ่ฎพ็ฝฎ `"json_schema_extra"`๏ผŒๅ…ถๅ€ผไธบไธ€ไธช `dict`๏ผŒๅŒ…ๅซไฝ ๅธŒๆœ›ๅ‡บ็Žฐๅœจ็”Ÿๆˆ JSON Schema ไธญ็š„ไปปๆ„้™„ๅŠ ๆ•ฐๆฎ๏ผŒๅŒ…ๆ‹ฌ `examples`ใ€‚ -ๅœจ `Field`, `Path`, `Query`, `Body` ๅ’Œๅ…ถไป–ไฝ ไน‹ๅŽๅฐ†ไผš็œ‹ๅˆฐ็š„ๅทฅๅŽ‚ๅ‡ฝๆ•ฐ๏ผŒไฝ ๅฏไปฅไธบJSON ๆจกๅผๅฃฐๆ˜Ž้ขๅค–ไฟกๆฏ๏ผŒไฝ ไนŸๅฏไปฅ้€š่ฟ‡็ป™ๅทฅๅŽ‚ๅ‡ฝๆ•ฐไผ ้€’ๅ…ถไป–็š„ไปปๆ„ๅ‚ๆ•ฐๆฅ็ป™JSON ๆจกๅผๅฃฐๆ˜Ž้ขๅค–ไฟกๆฏ๏ผŒๆฏ”ๅฆ‚ๅขžๅŠ  `example`: +/// tip | ๆ็คบ -{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} +ไฝ ไนŸๅฏไปฅ็”จๅŒๆ ท็š„ๆŠ€ๅทงๆ‰ฉๅฑ• JSON Schema๏ผŒๆทปๅŠ ไฝ ่‡ชๅทฑ็š„่‡ชๅฎšไน‰้ขๅค–ไฟกๆฏใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒไธบๅ‰็ซฏ็”จๆˆท็•Œ้ขๆทปๅŠ ๅ…ƒๆ•ฐๆฎ็ญ‰ใ€‚ + +/// + +/// info | ไฟกๆฏ -/// warning +OpenAPI 3.1.0๏ผˆ่‡ช FastAPI 0.99.0 ่ตทไฝฟ็”จ๏ผ‰ๅขžๅŠ ไบ†ๅฏน `examples` ็š„ๆ”ฏๆŒ๏ผŒๅฎƒๆ˜ฏ JSON Schema ๆ ‡ๅ‡†็š„ไธ€้ƒจๅˆ†ใ€‚ -่ฏท่ฎฐไฝ๏ผŒไผ ้€’็š„้‚ฃไบ›้ขๅค–ๅ‚ๆ•ฐไธไผšๆทปๅŠ ไปปไฝ•้ชŒ่ฏ๏ผŒๅชไผšๆทปๅŠ ๆณจ้‡Š๏ผŒ็”จไบŽๆ–‡ๆกฃ็š„็›ฎ็š„ใ€‚ +ๅœจๆญคไน‹ๅ‰๏ผŒๅชๆ”ฏๆŒไฝฟ็”จๅ•ไธช็คบไพ‹็š„ๅ…ณ้”ฎๅญ— `example`ใ€‚OpenAPI 3.1.0 ไป็„ถๆ”ฏๆŒๅฎƒ๏ผŒไฝ†ๅฎƒๅทฒ่ขซๅผƒ็”จ๏ผŒๅนถไธๅฑžไบŽ JSON Schema ๆ ‡ๅ‡†ใ€‚ๅ› ๆญค๏ผŒๅปบ่ฎฎไฝ ๆŠŠ `example` ่ฟ็งปๅˆฐ `examples`ใ€‚๐Ÿค“ + +ไฝ ๅฏไปฅๅœจๆœฌ้กตๆœซๅฐพ้˜…่ฏปๆ›ดๅคšๅ†…ๅฎนใ€‚ /// -## `Body` ้ขๅค–ๅ‚ๆ•ฐ +## `Field` ็š„้™„ๅŠ ๅ‚ๆ•ฐ { #field-additional-arguments } + +ๅœจ Pydantic ๆจกๅž‹ไธญไฝฟ็”จ `Field()` ๆ—ถ๏ผŒไฝ ไนŸๅฏไปฅๅฃฐๆ˜Ž้ขๅค–็š„ `examples`๏ผš + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## JSON Schema ไธญ็š„ `examples` - OpenAPI { #examples-in-json-schema-openapi } + +ๅœจไปฅไธ‹ไปปๆ„ๅœบๆ™ฏไธญไฝฟ็”จ๏ผš + +- `Path()` +- `Query()` +- `Header()` +- `Cookie()` +- `Body()` +- `Form()` +- `File()` -ไฝ ๅฏไปฅ้€š่ฟ‡ไผ ้€’้ขๅค–ไฟกๆฏ็ป™ `Field` ๅŒๆ ท็š„ๆ–นๅผๆ“ไฝœ`Path`, `Query`, `Body`็ญ‰ใ€‚ +ไฝ ไนŸๅฏไปฅๅฃฐๆ˜Žไธ€็ป„ `examples`๏ผŒ่ฟ™ไบ›ๅธฆๆœ‰้™„ๅŠ ไฟกๆฏ็š„็คบไพ‹ๅฐ†่ขซๆทปๅŠ ๅˆฐๅฎƒไปฌๅœจ OpenAPI ไธญ็š„ JSON Schema ้‡Œใ€‚ -ๆฏ”ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฐ†่ฏทๆฑ‚ไฝ“็š„ไธ€ไธช `example` ไผ ้€’็ป™ `Body`: +### ๅธฆๆœ‰ `examples` ็š„ `Body` { #body-with-examples } -{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:27] *} +่ฟ™้‡Œๆˆ‘ไปฌๅ‘ `Body()` ไผ ๅ…ฅ `examples`๏ผŒๅ…ถไธญๅŒ…ๅซไธ€ไธชๆœŸๆœ›็š„ๆ•ฐๆฎ็คบไพ‹๏ผš -## ๆ–‡ๆกฃ UI ไธญ็š„ไพ‹ๅญ +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} -ไฝฟ็”จไธŠ้ข็š„ไปปไฝ•ๆ–นๆณ•๏ผŒๅฎƒๅœจ `/docs` ไธญ็œ‹่ตทๆฅ้ƒฝๆ˜ฏ่ฟ™ๆ ท็š„: +### ๆ–‡ๆกฃ UI ไธญ็š„็คบไพ‹ { #example-in-the-docs-ui } + +ไฝฟ็”จไธŠ่ฟฐไปปไธ€ๆ–นๆณ•๏ผŒๅœจ `/docs` ไธญ็œ‹่ตทๆฅไผšๆ˜ฏ่ฟ™ๆ ท๏ผš -## ๆŠ€ๆœฏ็ป†่Š‚ +### ๅธฆๆœ‰ๅคšไธช `examples` ็š„ `Body` { #body-with-multiple-examples } + +ๅฝ“็„ถ๏ผŒไฝ ไนŸๅฏไปฅไผ ๅ…ฅๅคšไธช `examples`๏ผš + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +่ฟ™ๆ ทๅšๆ—ถ๏ผŒ่ฟ™ไบ›็คบไพ‹ไผšๆˆไธบ่ฏฅ่ฏทๆฑ‚ไฝ“ๆ•ฐๆฎๅ†…้ƒจ JSON Schema ็š„ไธ€้ƒจๅˆ†ใ€‚ + +ไธ่ฟ‡๏ผŒๅœจๆ’ฐๅ†™ๆœฌๆ–‡ๆ—ถ๏ผŒ็”จไบŽๅฑ•็คบๆ–‡ๆกฃ UI ็š„ Swagger UI ๅนถไธๆ”ฏๆŒๆ˜พ็คบ JSON Schema ไธญๆ•ฐๆฎ็š„ๅคšไธช็คบไพ‹ใ€‚ไฝ†่ฏท็ปง็ปญ้˜…่ฏป๏ผŒไธ‹้ขๆœ‰ไธ€็งๅ˜้€šๆ–นๆณ•ใ€‚ + +### OpenAPI ็‰นๅฎš็š„ `examples` { #openapi-specific-examples } + +ๅœจ JSON Schema ๆ”ฏๆŒ `examples` ไน‹ๅ‰๏ผŒOpenAPI ๅฐฑๅทฒๆ”ฏๆŒไธ€ไธชๅŒๅไฝ†ไธๅŒ็š„ๅญ—ๆฎต `examples`ใ€‚ + +่ฟ™ไธช้ขๅ‘ OpenAPI ็š„ `examples` ไฝไบŽ OpenAPI ่ง„่Œƒ็š„ๅฆไธ€ๅค„ใ€‚ๅฎƒๆ”พๅœจๆฏไธช่ทฏๅพ„ๆ“ไฝœ็š„่ฏฆ็ป†ไฟกๆฏไธญ๏ผŒ่€Œไธๆ˜ฏๆฏไธช JSON Schema ้‡Œใ€‚ + +่€Œ Swagger UI ๆ—ฉๅฐฑๆ”ฏๆŒ่ฟ™ไธช็‰นๅฎš็š„ `examples` ๅญ—ๆฎตใ€‚ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ็”จๅฎƒๅœจๆ–‡ๆกฃ UI ไธญๅฑ•็คบไธๅŒ็š„็คบไพ‹ใ€‚ + +่ฟ™ไธช OpenAPI ็‰นๅฎšๅญ—ๆฎต `examples` ็š„็ป“ๆž„ๆ˜ฏไธ€ไธชๅŒ…ๅซๅคšไธช็คบไพ‹็š„ `dict`๏ผˆ่€Œไธๆ˜ฏไธ€ไธช `list`๏ผ‰๏ผŒๆฏไธช็คบไพ‹้ƒฝๅŒ…ๅซไผš่ขซๆทปๅŠ ๅˆฐ OpenAPI ็š„้ขๅค–ไฟกๆฏใ€‚ + +่ฟ™ไธๆ”พๅœจ OpenAPI ๅ†…้ƒจๅŒ…ๅซ็š„ๅ„ไธช JSON Schema ้‡Œ๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅๆ”พๅœจ่ทฏๅพ„ๆ“ไฝœไธŠใ€‚ + +### ไฝฟ็”จ `openapi_examples` ๅ‚ๆ•ฐ { #using-the-openapi-examples-parameter } + +ไฝ ๅฏไปฅๅœจ FastAPI ไธญ้€š่ฟ‡ๅ‚ๆ•ฐ `openapi_examples` ๆฅๅฃฐๆ˜Ž่ฟ™ไธช OpenAPI ็‰นๅฎš็š„ `examples`๏ผŒ้€‚็”จไบŽ๏ผš + +- `Path()` +- `Query()` +- `Header()` +- `Cookie()` +- `Body()` +- `Form()` +- `File()` + +่ฟ™ไธช `dict` ็š„้”ฎ็”จไบŽๆ ‡่ฏ†ๆฏไธช็คบไพ‹๏ผŒๆฏไธชๅ€ผๆ˜ฏๅฆไธ€ไธช `dict`ใ€‚ + +`examples` ไธญๆฏไธชๅ…ทไฝ“็คบไพ‹็š„ `dict` ๅฏไปฅๅŒ…ๅซ๏ผš + +- `summary`๏ผš่ฏฅ็คบไพ‹็š„็ฎ€็Ÿญๆ่ฟฐใ€‚ +- `description`๏ผš่พƒ้•ฟๆ่ฟฐ๏ผŒๅฏไปฅๅŒ…ๅซ Markdown ๆ–‡ๆœฌใ€‚ +- `value`๏ผšๅฎž้™…ๅฑ•็คบ็š„็คบไพ‹๏ผŒไพ‹ๅฆ‚ไธ€ไธช `dict`ใ€‚ +- `externalValue`๏ผš`value` ็š„ๆ›ฟไปฃ้กน๏ผŒๆŒ‡ๅ‘่ฏฅ็คบไพ‹็š„ URLใ€‚ไธ่ฟ‡ๅฎƒ็š„ๅทฅๅ…ทๆ”ฏๆŒๅบฆๅฏ่ƒฝไธๅฆ‚ `value`ใ€‚ + +ไฝ ๅฏไปฅ่ฟ™ๆ ทไฝฟ็”จ๏ผš + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### ๆ–‡ๆกฃ UI ไธญ็š„ OpenAPI ็คบไพ‹ { #openapi-examples-in-the-docs-ui } + +ๅฝ“ๆŠŠ `openapi_examples` ๆทปๅŠ ๅˆฐ `Body()` ๅŽ๏ผŒ`/docs` ไผšๅฆ‚ไธ‹ๆ‰€็คบ๏ผš + + + +## ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details } + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ๅทฒ็ปๅœจไฝฟ็”จ FastAPI ็‰ˆๆœฌ 0.99.0 ๆˆ–ๆ›ด้ซ˜็‰ˆๆœฌ๏ผŒไฝ ๅคงๆฆ‚็އๅฏไปฅ่ทณ่ฟ‡่ฟ™ไบ›็ป†่Š‚ใ€‚ + +ๅฎƒไปฌๅฏนๆ›ดๆ—ฉ็‰ˆๆœฌ๏ผˆOpenAPI 3.1.0 ๅฐšไธๅฏ็”จไน‹ๅ‰๏ผ‰ๆ›ด็›ธๅ…ณใ€‚ + +ไฝ ๅฏไปฅๆŠŠ่ฟ™ๅฝ“ไฝœไธ€ๅ ‚็ฎ€็Ÿญ็š„ OpenAPI ๅ’Œ JSON Schema ๅކๅฒ่ฏพใ€‚๐Ÿค“ + +/// + +/// warning | ่ญฆๅ‘Š + +ไปฅไธ‹ๆ˜ฏๅ…ณไบŽ JSON Schema ๅ’Œ OpenAPI ๆ ‡ๅ‡†็š„้žๅธธๆŠ€ๆœฏๆ€ง็š„็ป†่Š‚ใ€‚ + +ๅฆ‚ๆžœไธŠ้ข็š„ๆ€่ทฏๅฏนไฝ ๅทฒ็ป่ถณๅคŸๅฏ็”จ๏ผŒไฝ ๅฏ่ƒฝไธ้œ€่ฆ่ฟ™ไบ›็ป†่Š‚๏ผŒๅฏไปฅ็›ดๆŽฅ่ทณ่ฟ‡ใ€‚ + +/// + +ๅœจ OpenAPI 3.1.0 ไน‹ๅ‰๏ผŒOpenAPI ไฝฟ็”จ็š„ๆ˜ฏไธ€ไธชๆ›ดๆ—งไธ”็ป่ฟ‡ไฟฎๆ”น็š„ JSON Schema ็‰ˆๆœฌใ€‚ + +ๅฝ“ๆ—ถ JSON Schema ๆฒกๆœ‰ `examples`๏ผŒๆ‰€ไปฅ OpenAPI ๅœจๅฎƒไฟฎๆ”น่ฟ‡็š„็‰ˆๆœฌไธญๆทปๅŠ ไบ†่‡ชๅทฑ็š„ `example` ๅญ—ๆฎตใ€‚ + +OpenAPI ่ฟ˜ๅœจ่ง„่Œƒ็š„ๅ…ถไป–้ƒจๅˆ†ๆทปๅŠ ไบ† `example` ๅ’Œ `examples` ๅญ—ๆฎต๏ผš + +- `Parameter Object`๏ผˆ่ง„่Œƒไธญ๏ผ‰๏ผŒ่ขซ FastAPI ็š„ไปฅไธ‹ๅ†…ๅฎนไฝฟ็”จ๏ผš + - `Path()` + - `Query()` + - `Header()` + - `Cookie()` +- `Request Body Object` ไธญ็š„ `content` ๅญ—ๆฎต้‡Œ็š„ `Media Type Object`๏ผˆ่ง„่Œƒไธญ๏ผ‰๏ผŒ่ขซ FastAPI ็š„ไปฅไธ‹ๅ†…ๅฎนไฝฟ็”จ๏ผš + - `Body()` + - `File()` + - `Form()` + +/// info | ไฟกๆฏ + +่ฟ™ไธชๆ—ง็š„ใ€OpenAPI ็‰นๅฎš็š„ `examples` ๅ‚ๆ•ฐ๏ผŒ่‡ช FastAPI `0.103.0` ่ตทๆ”นๅไธบ `openapi_examples`ใ€‚ + +/// + +### JSON Schema ็š„ `examples` ๅญ—ๆฎต { #json-schemas-examples-field } + +ๅŽๆฅ๏ผŒJSON Schema ๅœจๆ–ฐ็‰ˆๆœฌ็š„่ง„่ŒƒไธญๆทปๅŠ ไบ† `examples` ๅญ—ๆฎตใ€‚ + +้šๅŽๆ–ฐ็š„ OpenAPI 3.1.0 ๅŸบไบŽๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผˆJSON Schema 2020-12๏ผ‰๏ผŒๅ…ถไธญๅŒ…ๅซไบ†่ฟ™ไธชๆ–ฐ็š„ `examples` ๅญ—ๆฎตใ€‚ + +็Žฐๅœจ๏ผŒ่ฟ™ไธชๆ–ฐ็š„ `examples` ๅญ—ๆฎตไผ˜ๅ…ˆไบŽๆ—ง็š„ๅ•ไธช๏ผˆไธ”่‡ชๅฎšไน‰็š„๏ผ‰`example` ๅญ—ๆฎต๏ผŒๅŽ่€…ๅทฒ่ขซๅผƒ็”จใ€‚ + +JSON Schema ไธญ่ฟ™ไธชๆ–ฐ็š„ `examples` ๅญ—ๆฎตๅชๆ˜ฏไธ€ไธช็”ฑ็คบไพ‹็ป„ๆˆ็š„ `list`๏ผŒ่€Œไธๆ˜ฏๅƒไธŠ้ขๆๅˆฐ็š„ OpenAPI ๅ…ถไป–ไฝ็ฝฎ้‚ฃๆ ทๅธฆๆœ‰้ขๅค–ๅ…ƒๆ•ฐๆฎ็š„ `dict`ใ€‚ + +/// info | ไฟกๆฏ + +ๅณไฝฟๅœจ OpenAPI 3.1.0 ๅ‘ๅธƒใ€ๅนถไธŽ JSON Schema ๆœ‰ไบ†่ฟ™็งๆ›ด็ฎ€ๅ•็š„้›†ๆˆไน‹ๅŽ๏ผŒๆœ‰ไธ€ๆฎตๆ—ถ้—ด้‡Œ๏ผŒๆไพ›่‡ชๅŠจๆ–‡ๆกฃ็š„ Swagger UI ๅนถไธๆ”ฏๆŒ OpenAPI 3.1.0๏ผˆๅฎƒ่‡ช 5.0.0 ็‰ˆๆœฌ่ตทๅทฒๆ”ฏๆŒ ๐ŸŽ‰๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒFastAPI 0.99.0 ไน‹ๅ‰็š„็‰ˆๆœฌไป็„ถไฝฟ็”จไฝŽไบŽ 3.1.0 ็š„ OpenAPI ็‰ˆๆœฌใ€‚ + +/// + +### Pydantic ไธŽ FastAPI ็š„ `examples` { #pydantic-and-fastapi-examples } + +ๅฝ“ไฝ ๅœจ Pydantic ๆจกๅž‹ไธญๆทปๅŠ  `examples`๏ผŒ้€š่ฟ‡ `schema_extra` ๆˆ– `Field(examples=["something"])`๏ผŒ่ฟ™ไบ›็คบไพ‹ไผš่ขซๆทปๅŠ ๅˆฐ่ฏฅ Pydantic ๆจกๅž‹็š„ JSON Schema ไธญใ€‚ + +่ฟ™ไธช Pydantic ๆจกๅž‹็š„ JSON Schema ไผš่ขซๅŒ…ๅซๅˆฐไฝ ็š„ API ็š„ OpenAPI ไธญ๏ผŒ็„ถๅŽๅœจๆ–‡ๆกฃ UI ไธญไฝฟ็”จใ€‚ + +ๅœจ FastAPI 0.99.0 ไน‹ๅ‰็š„็‰ˆๆœฌ๏ผˆ0.99.0 ๅŠไปฅไธŠไฝฟ็”จๆ›ดๆ–ฐ็š„ OpenAPI 3.1.0๏ผ‰๏ผŒๅฝ“ไฝ ๅœจๅ…ถไป–ๅทฅๅ…ท๏ผˆ`Query()`ใ€`Body()` ็ญ‰๏ผ‰ไธญไฝฟ็”จ `example` ๆˆ– `examples` ๆ—ถ๏ผŒ่ฟ™ไบ›็คบไพ‹ไธไผš่ขซๆทปๅŠ ๅˆฐๆ่ฟฐ่ฏฅๆ•ฐๆฎ็š„ JSON Schema ไธญ๏ผˆ็”š่‡ณไธไผšๆทปๅŠ ๅˆฐ OpenAPI ่‡ชๅทฑ็š„ JSON Schema ็‰ˆๆœฌไธญ๏ผ‰๏ผŒ่€Œๆ˜ฏไผš็›ดๆŽฅๆทปๅŠ ๅˆฐ OpenAPI ็š„่ทฏๅพ„ๆ“ไฝœๅฃฐๆ˜Žไธญ๏ผˆๅœจ OpenAPI ไฝฟ็”จ JSON Schema ็š„้ƒจๅˆ†ไน‹ๅค–๏ผ‰ใ€‚ + +ไฝ†็Žฐๅœจ FastAPI 0.99.0 ๅŠไปฅไธŠไฝฟ็”จ OpenAPI 3.1.0๏ผˆๅ…ถไฝฟ็”จ JSON Schema 2020-12๏ผ‰ไปฅๅŠ Swagger UI 5.0.0 ๅŠไปฅไธŠๅŽ๏ผŒไธ€ๅˆ‡ๆ›ดๅŠ ไธ€่‡ด๏ผŒ็คบไพ‹ไผšๅŒ…ๅซๅœจ JSON Schema ไธญใ€‚ -ๅ…ณไบŽ `example` ๅ’Œ `examples`... +### Swagger UI ไธŽ OpenAPI ็‰นๅฎš็š„ `examples` { #swagger-ui-and-openapi-specific-examples } -JSON Schemaๅœจๆœ€ๆ–ฐ็š„ไธ€ไธช็‰ˆๆœฌไธญๅฎšไน‰ไบ†ไธ€ไธชๅญ—ๆฎต `examples` ๏ผŒไฝ†ๆ˜ฏ OpenAPI ๅŸบไบŽไน‹ๅ‰็š„ไธ€ไธชๆ—ง็‰ˆJSON Schema๏ผŒๅนถๆฒกๆœ‰ `examples`. +ๆญคๅ‰๏ผŒ็”ฑไบŽ Swagger UI ไธๆ”ฏๆŒๅคšไธช JSON Schema ็คบไพ‹๏ผˆๆˆช่‡ณ 2023-08-26๏ผ‰๏ผŒ็”จๆˆทๆ— ๆณ•ๅœจๆ–‡ๆกฃไธญๅฑ•็คบๅคšไธช็คบไพ‹ใ€‚ -ๆ‰€ไปฅ OpenAPIไธบไบ†็›ธไผผ็š„็›ฎ็š„ๅฎšไน‰ไบ†่‡ชๅทฑ็š„ `example` (ไฝฟ็”จ `example`, ่€Œไธๆ˜ฏ `examples`), ่ฟ™ไนŸๆ˜ฏๆ–‡ๆกฃ UI ๆ‰€ไฝฟ็”จ็š„ (ไฝฟ็”จ Swagger UI). +ไธบไบ†่งฃๅ†ณ่ฟ™ไธช้—ฎ้ข˜๏ผŒFastAPI `0.103.0` ้€š่ฟ‡ๆ–ฐๅขžๅ‚ๆ•ฐ `openapi_examples`๏ผŒไธบๅฃฐๆ˜ŽๅŒๆ ท็š„ๆ—งๅผ OpenAPI ็‰นๅฎš `examples` ๅญ—ๆฎตๆไพ›ไบ†ๆ”ฏๆŒใ€‚๐Ÿค“ -ๆ‰€ไปฅ๏ผŒ่™ฝ็„ถ `example` ไธๆ˜ฏJSON Schema็š„ไธ€้ƒจๅˆ†๏ผŒไฝ†ๅฎƒๆ˜ฏOpenAPI็š„ไธ€้ƒจๅˆ†๏ผŒ่ฟ™ๅฐ†่ขซๆ–‡ๆกฃUIไฝฟ็”จใ€‚ +### ๆ€ป็ป“ { #summary } -## ๅ…ถไป–ไฟกๆฏ +ๆˆ‘ๆ›พ็ป่ฏดๆˆ‘ไธๅคชๅ–œๆฌขๅކๅฒโ€ฆโ€ฆ็ป“ๆžœ็Žฐๅœจๅœจ่ฟ™ๅ„ฟไธŠโ€œๆŠ€ๆœฏๅฒโ€่ฏพใ€‚๐Ÿ˜… -ๅŒๆ ท็š„ๆ–นๆณ•๏ผŒไฝ ๅฏไปฅๆทปๅŠ ไฝ ่‡ชๅทฑ็š„้ขๅค–ไฟกๆฏ๏ผŒ่ฟ™ไบ›ไฟกๆฏๅฐ†่ขซๆทปๅŠ ๅˆฐๆฏไธชๆจกๅž‹็š„JSONๆจกๅผไธญ๏ผŒไพ‹ๅฆ‚ๅฎšๅˆถๅ‰็ซฏ็”จๆˆท็•Œ้ข๏ผŒ็ญ‰็ญ‰ใ€‚ +็ฎ€่€Œ่จ€ไน‹๏ผŒๅ‡็บงๅˆฐ FastAPI 0.99.0 ๆˆ–ๆ›ด้ซ˜็‰ˆๆœฌ๏ผŒไธ€ๅˆ‡ไผšๆ›ด็ฎ€ๅ•ใ€ไธ€่‡ดใ€็›ด่ง‚๏ผŒไฝ ไนŸไธๅฟ…ไบ†่งฃ่ฟ™ไบ›ๅކๅฒ็ป†่Š‚ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md index 225eb26951..43b7c66579 100644 --- a/docs/zh/docs/tutorial/security/first-steps.md +++ b/docs/zh/docs/tutorial/security/first-steps.md @@ -1,197 +1,203 @@ -# ๅฎ‰ๅ…จ - ็ฌฌไธ€ๆญฅ +# ๅฎ‰ๅ…จ - ็ฌฌไธ€ๆญฅ { #security-first-steps } -ๅ‡่ฎพ**ๅŽ็ซฏ** API ๅœจๆŸไธชๅŸŸใ€‚ +ๅ‡่ฎพไฝ ็š„**ๅŽ็ซฏ** API ไฝไบŽๆŸไธชๅŸŸๅไธ‹ใ€‚ -**ๅ‰็ซฏ**ๅœจๅฆไธ€ไธชๅŸŸ๏ผŒๆˆ–๏ผˆ็งปๅŠจๅบ”็”จไธญ๏ผ‰ๅœจๅŒไธ€ไธชๅŸŸ็š„ไธๅŒ่ทฏๅพ„ไธ‹ใ€‚ +่€Œ**ๅ‰็ซฏ**ๅœจๅฆไธ€ไธชๅŸŸๅ๏ผŒๆˆ–ๅŒไธ€ๅŸŸๅ็š„ไธๅŒ่ทฏๅพ„๏ผˆๆˆ–ๅœจ็งปๅŠจๅบ”็”จไธญ๏ผ‰ใ€‚ -ๅนถไธ”๏ผŒๅ‰็ซฏ่ฆไฝฟ็”จๅŽ็ซฏ็š„ **username** ไธŽ **password** ้ชŒ่ฏ็”จๆˆท่บซไปฝใ€‚ +ไฝ ๅธŒๆœ›ๅ‰็ซฏ่ƒฝ้€š่ฟ‡**username** ๅ’Œ **password** ไธŽๅŽ็ซฏ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏใ€‚ -ๅ›บ็„ถ๏ผŒ**FastAPI** ๆ”ฏๆŒ **OAuth2** ่บซไปฝ้ชŒ่ฏใ€‚ +ๆˆ‘ไปฌๅฏไปฅ็”จ **OAuth2** ๅœจ **FastAPI** ไธญๅฎž็Žฐๅฎƒใ€‚ -ไฝ†ไธบไบ†่Š‚็œๅผ€ๅ‘่€…็š„ๆ—ถ้—ด๏ผŒไธ่ฆๅชไธบไบ†ๆŸฅๆ‰พๅพˆๅฐ‘็š„ๅ†…ๅฎน๏ผŒไธๅพ—ไธ้˜…่ฏปๅ†—้•ฟ็š„่ง„่Œƒๆ–‡ๆกฃใ€‚ +ไฝ†ไธบไบ†่Š‚็œไฝ ็š„ๆ—ถ้—ด๏ผŒไธๅฟ…ไธบ่Žทๅ–ๅฐ‘้‡ไฟกๆฏ่€Œ้€š่ฏปๅ†—้•ฟ็š„่ง„่Œƒใ€‚ -ๆˆ‘ไปฌๅปบ่ฎฎไฝฟ็”จ **FastAPI** ็š„ๅฎ‰ๅ…จๅทฅๅ…ทใ€‚ +ๆˆ‘ไปฌ็›ดๆŽฅไฝฟ็”จ **FastAPI** ๆไพ›็š„ๅฎ‰ๅ…จๅทฅๅ…ทใ€‚ -## ๆฆ‚่งˆ +## ๆ•ˆๆžœ้ข„่งˆ { #how-it-looks } -้ฆ–ๅ…ˆ๏ผŒ็œ‹็œ‹ไธ‹้ข็š„ไปฃ็ ๆ˜ฏๆ€Žไนˆ่ฟ่กŒ็š„๏ผŒ็„ถๅŽๅ†ๅ›ž่ฟ‡ๅคดๆฅไบ†่งฃๅ…ถ่ƒŒๅŽ็š„ๅŽŸ็†ใ€‚ +ๅ…ˆ็›ดๆŽฅ่ฟ่กŒไปฃ็ ็œ‹็œ‹ๆ•ˆๆžœ๏ผŒไน‹ๅŽๅ†ๅ›ž่ฟ‡ๅคด็†่งฃๅ…ถ่ƒŒๅŽ็š„ๅŽŸ็†ใ€‚ -## ๅˆ›ๅปบ `main.py` +## ๅˆ›ๅปบ `main.py` { #create-main-py } ๆŠŠไธ‹้ข็š„็คบไพ‹ไปฃ็ ๅคๅˆถๅˆฐ `main.py`๏ผš {* ../../docs_src/security/tutorial001_an_py39.py *} -## ่ฟ่กŒ +## ่ฟ่กŒ { #run-it } -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๅ…ˆๅฎ‰่ฃ… `python-multipart`ใ€‚ +ๅฝ“ไฝ ไฝฟ็”จๅ‘ฝไปค `pip install "fastapi[standard]"` ๅฎ‰่ฃ… **FastAPI** ๆ—ถ๏ผŒ`python-multipart` ๅŒ…ไผš่‡ชๅŠจๅฎ‰่ฃ…ใ€‚ -ๅฎ‰่ฃ…ๅ‘ฝไปค๏ผš `pip install python-multipart`ใ€‚ +ไฝ†ๆ˜ฏ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `pip install fastapi`๏ผŒ้ป˜่ฎคไธไผšๅŒ…ๅซ `python-multipart` ๅŒ…ใ€‚ -่ฟ™ๆ˜ฏๅ› ไธบ **OAuth2** ไฝฟ็”จ**่กจๅ•ๆ•ฐๆฎ**ๅ‘้€ `username` ไธŽ `password`ใ€‚ +ๅฆ‚้œ€ๆ‰‹ๅŠจๅฎ‰่ฃ…๏ผŒ่ฏทๅ…ˆๅˆ›ๅปบๅนถๆฟ€ๆดป[่™šๆ‹Ÿ็Žฏๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๆ‰ง่กŒ๏ผš + +```console +$ pip install python-multipart +``` + +่ฟ™ๆ˜ฏๅ› ไธบ **OAuth2** ไฝฟ็”จโ€œ่กจๅ•ๆ•ฐๆฎโ€ๆฅๅ‘้€ `username` ๅ’Œ `password`ใ€‚ /// -็”จไธ‹้ข็š„ๅ‘ฝไปค่ฟ่กŒ่ฏฅ็คบไพ‹๏ผš +็”จไธ‹้ข็š„ๅ‘ฝไปค่ฟ่กŒ็คบไพ‹๏ผš
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-## ๆŸฅ็œ‹ๆ–‡ๆกฃ +## ๆŸฅ็œ‹ { #check-it } -ๆ‰“ๅผ€ API ๆ–‡ๆกฃ๏ผš http://127.0.0.1:8000/docsใ€‚ +ๆ‰“ๅผ€ไบคไบ’ๅผๆ–‡ๆกฃ๏ผšhttp://127.0.0.1:8000/docsใ€‚ -็•Œ้ขๅฆ‚ไธ‹ๅ›พๆ‰€็คบ๏ผš +ไฝ ไผš็œ‹ๅˆฐ็ฑปไผผ่ฟ™ๆ ท็š„็•Œ้ข๏ผš /// check | Authorize ๆŒ‰้’ฎ๏ผ -้กต้ขๅณไธŠ่ง’ๅ‡บ็Žฐไบ†ไธ€ไธชใ€Œ**Authorize**ใ€ๆŒ‰้’ฎใ€‚ +้กต้ขๅณไธŠ่ง’ๅทฒ็ปๆœ‰ไธ€ไธชๅดญๆ–ฐ็š„โ€œAuthorizeโ€ๆŒ‰้’ฎใ€‚ -*่ทฏๅพ„ๆ“ไฝœ*็š„ๅณไธŠ่ง’ไนŸๅ‡บ็Žฐไบ†ไธ€ไธชๅฏไปฅ็‚นๅ‡ป็š„ๅฐ้”ๅ›พๆ ‡ใ€‚ +ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅณไธŠ่ง’่ฟ˜ๆœ‰ไธ€ไธชๅฏ็‚นๅ‡ป็š„ๅฐ้”ๅ›พๆ ‡ใ€‚ /// -็‚นๅ‡ป **Authorize** ๆŒ‰้’ฎ๏ผŒๅผนๅ‡บๆŽˆๆƒ่กจๅ•๏ผŒ่พ“ๅ…ฅ `username` ไธŽ `password` ๅŠๅ…ถๅฎƒๅฏ้€‰ๅญ—ๆฎต๏ผš +็‚นๅ‡ปๅฎƒ๏ผŒไผšๅผนๅ‡บไธ€ไธชๆŽˆๆƒ่กจๅ•๏ผŒๅฏ่พ“ๅ…ฅ `username` ๅ’Œ `password`๏ผˆไปฅๅŠๅ…ถๅฎƒๅฏ้€‰ๅญ—ๆฎต๏ผ‰๏ผš -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -็›ฎๅ‰๏ผŒๅœจ่กจๅ•ไธญ่พ“ๅ…ฅๅ†…ๅฎนไธไผšๆœ‰ไปปไฝ•ๅๅบ”๏ผŒๅŽๆ–‡ไผšไป‹็ป็›ธๅ…ณๅ†…ๅฎนใ€‚ +็›ฎๅ‰ๆ— ่ฎบๅœจ่กจๅ•ไธญ่พ“ๅ…ฅไป€ไนˆ้ƒฝไธไผš็”Ÿๆ•ˆ๏ผŒๆˆ‘ไปฌ็จๅŽๅฐฑไผšๅฎž็Žฐๅฎƒใ€‚ /// -่™ฝ็„ถๆญคๆ–‡ๆกฃไธๆ˜ฏ็ป™ๅ‰็ซฏๆœ€็ปˆ็”จๆˆทไฝฟ็”จ็š„๏ผŒไฝ†่ฟ™ไธช่‡ชๅŠจๅทฅๅ…ท้žๅธธๅฎž็”จ๏ผŒๅฏๅœจๆ–‡ๆกฃไธญไธŽๆ‰€ๆœ‰ API ไบคไบ’ใ€‚ +่ฟ™ๅฝ“็„ถไธๆ˜ฏ้ขๅ‘ๆœ€็ปˆ็”จๆˆท็š„ๅ‰็ซฏ๏ผŒไฝ†ๅฎƒๆ˜ฏไธ€ไธชๅพˆๆฃ’็š„่‡ชๅŠจๅŒ–ๅทฅๅ…ท๏ผŒๅฏไบคไบ’ๅผๅœฐไธบๆ•ดไธช API ๆไพ›ๆ–‡ๆกฃใ€‚ -ๅ‰็ซฏๅ›ข้˜Ÿ๏ผˆๅฏ่ƒฝๅฐฑๆ˜ฏๅผ€ๅ‘่€…ๆœฌไบบ๏ผ‰ๅฏไปฅไฝฟ็”จๆœฌๅทฅๅ…ทใ€‚ +ๅ‰็ซฏๅ›ข้˜Ÿ๏ผˆไนŸๅฏ่ƒฝๅฐฑๆ˜ฏไฝ ่‡ชๅทฑ๏ผ‰ๅฏไปฅไฝฟ็”จๅฎƒใ€‚ -็ฌฌไธ‰ๆ–นๅบ”็”จไธŽ็ณป็ปŸไนŸๅฏไปฅ่ฐƒ็”จๆœฌๅทฅๅ…ทใ€‚ +็ฌฌไธ‰ๆ–นๅบ”็”จๅ’Œ็ณป็ปŸไนŸๅฏไปฅไฝฟ็”จๅฎƒใ€‚ -ๅผ€ๅ‘่€…ไนŸๅฏไปฅ็”จๅฎƒๆฅ่ฐƒ่ฏ•ใ€ๆฃ€ๆŸฅใ€ๆต‹่ฏ•ๅบ”็”จใ€‚ +ไฝ ไนŸๅฏไปฅ็”จๅฎƒๆฅ่ฐƒ่ฏ•ใ€ๆฃ€ๆŸฅๅ’Œๆต‹่ฏ•ๅŒไธ€ไธชๅบ”็”จใ€‚ -## ๅฏ†็ ๆต +## `password` ๆต { #the-password-flow } -็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅ›ž่ฟ‡ๅคดๆฅไป‹็ป่ฟ™ๆฎตไปฃ็ ็š„ๅŽŸ็†ใ€‚ +็Žฐๅœจๅ›ž่ฟ‡ๅคดๆฅ็†่งฃ่ฟ™ไบ›ๅ†…ๅฎนใ€‚ -`Password` **ๆต**ๆ˜ฏ OAuth2 ๅฎšไน‰็š„๏ผŒ็”จไบŽๅค„็†ๅฎ‰ๅ…จไธŽ่บซไปฝ้ชŒ่ฏ็š„ๆ–นๅผ๏ผˆ**ๆต**๏ผ‰ใ€‚ +`password` โ€œๆตโ€๏ผˆflow๏ผ‰ๆ˜ฏ OAuth2 ๅฎšไน‰็š„ๅค„็†ๅฎ‰ๅ…จไธŽ่บซไปฝ้ชŒ่ฏ็š„ไธ€็งๆ–นๅผใ€‚ -OAuth2 ็š„่ฎพ่ฎก็›ฎๆ ‡ๆ˜ฏไธบไบ†่ฎฉๅŽ็ซฏๆˆ– API ็‹ฌ็ซ‹ไบŽๆœๅŠกๅ™จ้ชŒ่ฏ็”จๆˆท่บซไปฝใ€‚ +OAuth2 ็š„่ฎพ่ฎก็›ฎๆ ‡ๆ˜ฏ่ฎฉๅŽ็ซฏๆˆ– API ไธŽ่ดŸ่ดฃ็”จๆˆท่ฎค่ฏ็š„ๆœๅŠกๅ™จ่งฃ่€ฆใ€‚ -ไฝ†ๅœจๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ๅบ”็”จไผšๅค„็† API ไธŽ่บซไปฝ้ชŒ่ฏใ€‚ +ไฝ†ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒ**FastAPI** ๅบ”็”จๅŒๆ—ถๅค„็† API ๅ’Œ่ฎค่ฏใ€‚ -ไธ‹้ข๏ผŒๆˆ‘ไปฌๆฅ็œ‹ไธ€ไธ‹็ฎ€ๅŒ–็š„่ฟ่กŒๆต็จ‹๏ผš +ไปŽ่ฟ™ไธช็ฎ€ๅŒ–็š„่ง’ๅบฆๆฅ็œ‹็œ‹ๆต็จ‹๏ผš -- ็”จๆˆทๅœจๅ‰็ซฏ่พ“ๅ…ฅ `username` ไธŽ`password`๏ผŒๅนถ็‚นๅ‡ป**ๅ›ž่ฝฆ** -- ๏ผˆ็”จๆˆทๆต่งˆๅ™จไธญ่ฟ่กŒ็š„๏ผ‰ๅ‰็ซฏๆŠŠ `username` ไธŽ`password` ๅ‘้€่‡ณ API ไธญๆŒ‡ๅฎš็š„ URL๏ผˆไฝฟ็”จ `tokenUrl="token"` ๅฃฐๆ˜Ž๏ผ‰ -- API ๆฃ€ๆŸฅ `username` ไธŽ`password`๏ผŒๅนถ็”จไปค็‰Œ๏ผˆ`Token`๏ผ‰ ๅ“ๅบ”๏ผˆๆš‚ๆœชๅฎž็ŽฐๆญคๅŠŸ่ƒฝ๏ผ‰๏ผš - - ไปค็‰Œๅชๆ˜ฏ็”จไบŽ้ชŒ่ฏ็”จๆˆท็š„ๅญ—็ฌฆไธฒ - - ไธ€่ˆฌๆฅ่ฏด๏ผŒไปค็‰Œไผšๅœจไธ€ๆฎตๆ—ถ้—ดๅŽ่ฟ‡ๆœŸ - - ่ฟ‡ๆ—ถๅŽ๏ผŒ็”จๆˆท่ฆๅ†ๆฌก็™ปๅฝ• - - ่ฟ™ๆ ทไธ€ๆฅ๏ผŒๅฐฑ็ฎ—ไปค็‰Œ่ขซไบบ็ชƒๅ–๏ผŒ้ฃŽ้™ฉไนŸ่พƒไฝŽใ€‚ๅ› ไธบๅฎƒไธŽๆฐธไน…ๅฏ†้’ฅไธๅŒ๏ผŒ**ๅœจ็ปๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹**ไธไผš้•ฟๆœŸๆœ‰ๆ•ˆ -- ๅ‰็ซฏไธดๆ—ถๅฐ†ไปค็‰Œๅญ˜ๅ‚จๅœจๆŸไธชไฝ็ฝฎ -- ็”จๆˆท็‚นๅ‡ปๅ‰็ซฏ๏ผŒๅ‰ๅพ€ๅ‰็ซฏๅบ”็”จ็š„ๅ…ถๅฎƒ้ƒจไปถ -- ๅ‰็ซฏ้œ€่ฆไปŽ API ไธญๆๅ–ๆ›ดๅคšๆ•ฐๆฎ๏ผš - - ไธบๆŒ‡ๅฎš็š„็ซฏ็‚น๏ผˆEndpoint๏ผ‰่ฟ›่กŒ่บซไปฝ้ชŒ่ฏ - - ๅ› ๆญค๏ผŒ็”จ API ้ชŒ่ฏ่บซไปฝๆ—ถ๏ผŒ่ฆๅ‘้€ๅ€ผไธบ `Bearer` + ไปค็‰Œ็š„่ฏทๆฑ‚ๅคด `Authorization` - - ๅ‡ๅฆ‚ไปค็‰Œไธบ `foobar`๏ผŒ`Authorization` ่ฏทๆฑ‚ๅคดๅฐฑๆ˜ฏ๏ผš `Bearer foobar` +* ็”จๆˆทๅœจๅ‰็ซฏ่พ“ๅ…ฅ `username` ๅ’Œ `password`๏ผŒ็„ถๅŽๆŒ‰ไธ‹ `Enter`ใ€‚ +* ๅ‰็ซฏ๏ผˆ่ฟ่กŒๅœจ็”จๆˆทๆต่งˆๅ™จไธญ๏ผ‰ๆŠŠ `username` ๅ’Œ `password` ๅ‘้€ๅˆฐๆˆ‘ไปฌ API ไธญ็š„็‰นๅฎš URL๏ผˆไฝฟ็”จ `tokenUrl="token"` ๅฃฐๆ˜Ž๏ผ‰ใ€‚ +* API ๆ ก้ชŒ `username` ๅ’Œ `password`๏ผŒๅนถ่ฟ”ๅ›žไธ€ไธชโ€œไปค็‰Œโ€๏ผˆ่ฟ™ไบ›ๆˆ‘ไปฌๅฐšๆœชๅฎž็Žฐ๏ผ‰ใ€‚ + * โ€œไปค็‰Œโ€ๅชๆ˜ฏไธ€ไธชๅญ—็ฌฆไธฒ๏ผŒๅŒ…ๅซไธ€ไบ›ๅ†…ๅฎน๏ผŒไน‹ๅŽๅฏ็”จๆฅ้ชŒ่ฏ่ฏฅ็”จๆˆทใ€‚ + * ้€šๅธธ๏ผŒไปค็‰Œไผšๅœจไธ€ๆฎตๆ—ถ้—ดๅŽ่ฟ‡ๆœŸใ€‚ + * ๅ› ๆญค๏ผŒ็”จๆˆท่ฟ‡ไธ€ๆฎตๆ—ถ้—ด้œ€่ฆ้‡ๆ–ฐ็™ปๅฝ•ใ€‚ + * ๅฆ‚ๆžœไปค็‰Œ่ขซ็ชƒๅ–๏ผŒ้ฃŽ้™ฉไนŸๆ›ดๅฐใ€‚ๅฎƒไธๅƒไธ€ๆŠŠๆฐธไน…ๆœ‰ๆ•ˆ็š„้’ฅๅŒ™๏ผˆๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผ‰ใ€‚ +* ๅ‰็ซฏไผšๆŠŠไปค็‰Œไธดๆ—ถๅญ˜ๅ‚จๅœจๆŸๅค„ใ€‚ +* ็”จๆˆทๅœจๅ‰็ซฏไธญ็‚นๅ‡ป่ทณ่ฝฌๅˆฐๅ‰็ซฏๅบ”็”จ็š„ๅ…ถไป–้ƒจๅˆ†ใ€‚ +* ๅ‰็ซฏ้œ€่ฆไปŽ API ่Žทๅ–ๆ›ดๅคšๆ•ฐๆฎใ€‚ + * ไฝ†่ฏฅ็ซฏ็‚น้œ€่ฆ่บซไปฝ้ชŒ่ฏใ€‚ + * ๅ› ๆญค๏ผŒไธบไบ†ไธŽๆˆ‘ไปฌ็š„ API ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏ๏ผŒๅฎƒไผšๅ‘้€ไธ€ไธช `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๅ€ผไธบ `Bearer ` ๅŠ ไธŠไปค็‰Œใ€‚ + * ๅฆ‚ๆžœไปค็‰Œๅ†…ๅฎนๆ˜ฏ `foobar`๏ผŒ`Authorization` ่ฏทๆฑ‚ๅคด็š„ๅ†…ๅฎนๅฐฑๆ˜ฏ๏ผš`Bearer foobar`ใ€‚ -## **FastAPI** ็š„ `OAuth2PasswordBearer` +## **FastAPI** ็š„ `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } -**FastAPI** ๆไพ›ไบ†ไธๅŒๆŠฝ่ฑก็บงๅˆซ็š„ๅฎ‰ๅ…จๅทฅๅ…ทใ€‚ +**FastAPI** ๅœจไธๅŒๆŠฝ่ฑกๅฑ‚็บงๆไพ›ไบ†ๅคš็งๅฎ‰ๅ…จๅทฅๅ…ทใ€‚ -ๆœฌไพ‹ไฝฟ็”จ **OAuth2** ็š„ **Password** ๆตไปฅๅŠ **Bearer** ไปค็‰Œ๏ผˆ`Token`๏ผ‰ใ€‚ไธบๆญค่ฆไฝฟ็”จ `OAuth2PasswordBearer` ็ฑปใ€‚ +ๆœฌ็คบไพ‹ๅฐ†ไฝฟ็”จ **OAuth2** ็š„ **Password** ๆต็จ‹ๅนถ้…ๅˆ **Bearer** ไปค็‰Œ๏ผŒ้€š่ฟ‡ `OAuth2PasswordBearer` ็ฑปๆฅๅฎž็Žฐใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -`Bearer` ไปค็‰Œไธๆ˜ฏๅ”ฏไธ€็š„้€‰ๆ‹ฉใ€‚ +โ€œBearerโ€ ไปค็‰Œๅนถ้žๅ”ฏไธ€้€‰้กนใ€‚ -ไฝ†ๅฎƒๆ˜ฏๆœ€้€‚ๅˆ่ฟ™ไธช็”จไพ‹็š„ๆ–นๆกˆใ€‚ +ไฝ†ๅฎƒ้žๅธธ้€‚ๅˆๆˆ‘ไปฌ็š„็”จไพ‹ใ€‚ -็”š่‡ณๅฏไปฅ่ฏด๏ผŒๅฎƒๆ˜ฏ้€‚็”จไบŽ็ปๅคงๅคšๆ•ฐ็”จไพ‹็š„ๆœ€ไฝณๆ–นๆกˆ๏ผŒ้™ค้žๆ‚จๆ˜ฏ OAuth2 ็š„ไธ“ๅฎถ๏ผŒ็Ÿฅ้“ไธบไป€ไนˆๅ…ถๅฎƒๆ–นๆกˆๆ›ดๅˆ้€‚ใ€‚ +ๅฏนไบŽๅคงๅคšๆ•ฐ็”จไพ‹๏ผŒๅฎƒไนŸๅฏ่ƒฝๆ˜ฏๆœ€ไฝณ้€‰ๆ‹ฉ๏ผŒ้™ค้žไฝ ๆ˜ฏ OAuth2 ไธ“ๅฎถ๏ผŒๅนถๆ˜Ž็กฎ็Ÿฅ้“ไธบไฝ•ๅ…ถไป–ๆ–นๆกˆๆ›ด้€‚ๅˆไฝ ็š„้œ€ๆฑ‚ใ€‚ -ๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ่ฟ˜ๆไพ›ไบ†ๆž„ๅปบๅทฅๅ…ทใ€‚ +ๅœจ้‚ฃ็งๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ๅŒๆ ทๆไพ›ไบ†็›ธๅบ”็š„ๆž„ๅปบๅทฅๅ…ทใ€‚ /// -ๅˆ›ๅปบ `OAuth2PasswordBearer` ็š„็ฑปๅฎžไพ‹ๆ—ถ๏ผŒ่ฆไผ ้€’ `tokenUrl` ๅ‚ๆ•ฐใ€‚่ฏฅๅ‚ๆ•ฐๅŒ…ๅซๅฎขๆˆท็ซฏ๏ผˆ็”จๆˆทๆต่งˆๅ™จไธญ่ฟ่กŒ็š„ๅ‰็ซฏ๏ผ‰ ็š„ URL๏ผŒ็”จไบŽๅ‘้€ `username` ไธŽ `password`๏ผŒๅนถ่Žทๅ–ไปค็‰Œใ€‚ +ๅˆ›ๅปบ `OAuth2PasswordBearer` ็ฑปๅฎžไพ‹ๆ—ถ๏ผŒ้œ€่ฆไผ ๅ…ฅ `tokenUrl` ๅ‚ๆ•ฐใ€‚่ฏฅๅ‚ๆ•ฐๅŒ…ๅซๅฎขๆˆท็ซฏ๏ผˆ่ฟ่กŒๅœจ็”จๆˆทๆต่งˆๅ™จไธญ็š„ๅ‰็ซฏ๏ผ‰็”จๆฅๅ‘้€ `username` ๅ’Œ `password` ไปฅ่Žทๅ–ไปค็‰Œ็š„ URLใ€‚ -{* ../../docs_src/security/tutorial001.py hl[6] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} /// tip | ๆ็คบ -ๅœจๆญค๏ผŒ`tokenUrl="token"` ๆŒ‡ๅ‘็š„ๆ˜ฏๆš‚ๆœชๅˆ›ๅปบ็š„็›ธๅฏน URL `token`ใ€‚่ฟ™ไธช็›ธๅฏน URL ็›ธๅฝ“ไบŽ `./token`ใ€‚ +่ฟ™้‡Œ็š„ `tokenUrl="token"` ๆŒ‡ๅ‘็š„ๆ˜ฏๅฐšๆœชๅˆ›ๅปบ็š„็›ธๅฏน URL `token`๏ผŒ็ญ‰ไปทไบŽ `./token`ใ€‚ -ๅ› ไธบไฝฟ็”จ็š„ๆ˜ฏ็›ธๅฏน URL๏ผŒๅฆ‚ๆžœ API ไฝไบŽ `https://example.com/`๏ผŒๅˆ™ๆŒ‡ๅ‘ `https://example.com/token`ใ€‚ไฝ†ๅฆ‚ๆžœ API ไฝไบŽ `https://example.com/api/v1/`๏ผŒๅฎƒๆŒ‡ๅ‘็š„ๅฐฑๆ˜ฏ`https://example.com/api/v1/token`ใ€‚ +ๅ› ไธบไฝฟ็”จ็š„ๆ˜ฏ็›ธๅฏน URL๏ผŒ่‹ฅไฝ ็š„ API ไฝไบŽ `https://example.com/`๏ผŒๅฎƒๅฐ†ๆŒ‡ๅ‘ `https://example.com/token`๏ผ›่‹ฅไฝ ็š„ API ไฝไบŽ `https://example.com/api/v1/`๏ผŒๅฎƒๅฐ†ๆŒ‡ๅ‘ `https://example.com/api/v1/token`ใ€‚ -ไฝฟ็”จ็›ธๅฏน URL ้žๅธธ้‡่ฆ๏ผŒๅฏไปฅ็กฎไฟๅบ”็”จๅœจ้‡ๅˆฐ[ไฝฟ็”จไปฃ็†](../../advanced/behind-a-proxy.md){.internal-link target=_blank}่ฟ™ๆ ท็š„้ซ˜็บง็”จไพ‹ๆ—ถ๏ผŒไนŸ่ƒฝๆญฃๅธธ่ฟ่กŒใ€‚ +ไฝฟ็”จ็›ธๅฏน URL ๅพˆ้‡่ฆ๏ผŒ่ฟ™่ƒฝ็กฎไฟไฝ ็š„ๅบ”็”จๅœจ่ฏธๅฆ‚[ไฝฟ็”จไปฃ็†](../../advanced/behind-a-proxy.md){.internal-link target=_blank}็ญ‰้ซ˜็บง็”จไพ‹ไธญไพ็„ถๆญฃๅธธๅทฅไฝœใ€‚ /// -่ฏฅๅ‚ๆ•ฐไธไผšๅˆ›ๅปบ็ซฏ็‚นๆˆ–*่ทฏๅพ„ๆ“ไฝœ*๏ผŒไฝ†ไผšๅฃฐๆ˜Žๅฎขๆˆท็ซฏ็”จๆฅ่Žทๅ–ไปค็‰Œ็š„ URL `/token` ใ€‚ๆญคไฟกๆฏ็”จไบŽ OpenAPI ๅŠ API ๆ–‡ๆกฃใ€‚ +่ฟ™ไธชๅ‚ๆ•ฐไธไผšๅˆ›ๅปบ่ฏฅ็ซฏ็‚น/*่ทฏๅพ„ๆ“ไฝœ*๏ผŒ่€Œๆ˜ฏๅฃฐๆ˜Žๅฎขๆˆท็ซฏๅบ”ไฝฟ็”จ `/token` ่ฟ™ไธช URL ๆฅ่Žทๅ–ไปค็‰Œใ€‚่ฟ™ไบ›ไฟกๆฏไผš็”จไบŽ OpenAPI๏ผŒ่ฟ›่€Œ็”จไบŽไบคไบ’ๅผ API ๆ–‡ๆกฃ็ณป็ปŸใ€‚ -ๆŽฅไธ‹ๆฅ๏ผŒๅญฆไน ๅฆ‚ไฝ•ๅˆ›ๅปบๅฎž้™…็š„่ทฏๅพ„ๆ“ไฝœใ€‚ +ๆˆ‘ไปฌๅพˆๅฟซไนŸไผšๅˆ›ๅปบๅฏนๅบ”็š„ๅฎž้™…่ทฏๅพ„ๆ“ไฝœใ€‚ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ไธฅ่‹›็š„ **Pythonista** ๅฏ่ƒฝไธๅ–œๆฌข็”จ `tokenUrl` ่ฟ™็งๅ‘ฝๅ้ฃŽๆ ผไปฃๆ›ฟ `token_url`ใ€‚ +ๅฆ‚ๆžœไฝ ๆ˜ฏ้žๅธธไธฅๆ ผ็š„ โ€œPythonistaโ€๏ผŒๅฏ่ƒฝไธๅ–œๆฌขไฝฟ็”จๅ‚ๆ•ฐๅ `tokenUrl` ่€Œไธๆ˜ฏ `token_url`ใ€‚ -่ฟ™็งๅ‘ฝๅๆ–นๅผๆ˜ฏๅ› ไธบ่ฆไฝฟ็”จไธŽ OpenAPI ่ง„่Œƒไธญ็›ธๅŒ็š„ๅๅญ—ใ€‚ไปฅไพฟๅœจๆทฑๅ…ฅๆ ก้ชŒๅฎ‰ๅ…จๆ–นๆกˆๆ—ถ๏ผŒ่ƒฝ้€š่ฟ‡ๅคๅˆถ็ฒ˜่ดดๆŸฅๆ‰พๆ›ดๅคš็›ธๅ…ณไฟกๆฏใ€‚ +่ฟ™ๆ˜ฏๅ› ไธบๅฎƒไฝฟ็”จไบ†ไธŽ OpenAPI ่ง„่Œƒไธญ็›ธๅŒ็š„ๅ็งฐใ€‚่ฟ™ๆ ทๅฝ“ไฝ ้œ€่ฆๆทฑๅ…ฅไบ†่งฃ่ฟ™ไบ›ๅฎ‰ๅ…จๆ–นๆกˆๆ—ถ๏ผŒๅฏไปฅ็›ดๆŽฅๅคๅˆถ็ฒ˜่ดดๅŽปๆŸฅๆ‰พๆ›ดๅคšไฟกๆฏใ€‚ /// -`oauth2_scheme` ๅ˜้‡ๆ˜ฏ `OAuth2PasswordBearer` ็š„ๅฎžไพ‹๏ผŒไนŸๆ˜ฏ**ๅฏ่ฐƒ็”จ้กน**ใ€‚ +`oauth2_scheme` ๅ˜้‡ๆ˜ฏ `OAuth2PasswordBearer` ็š„ไธ€ไธชๅฎžไพ‹๏ผŒๅŒๆ—ถๅฎƒไนŸๆ˜ฏโ€œๅฏ่ฐƒ็”จโ€็š„ใ€‚ -ไปฅๅฆ‚ไธ‹ๆ–นๅผ่ฐƒ็”จ๏ผš +ๅฏไปฅๅƒ่ฟ™ๆ ท่ฐƒ็”จ๏ผš ```Python oauth2_scheme(some, parameters) ``` -ๅ› ๆญค๏ผŒ`Depends` ๅฏไปฅ่ฐƒ็”จ `oauth2_scheme` ๅ˜้‡ใ€‚ +ๅ› ๆญค๏ผŒๅฎƒๅฏไปฅไธŽ `Depends` ไธ€่ตทไฝฟ็”จใ€‚ -### ไฝฟ็”จ +### ไฝฟ็”จ { #use-it } -ๆŽฅไธ‹ๆฅ๏ผŒไฝฟ็”จ `Depends` ๆŠŠ `oauth2_scheme` ไผ ๅ…ฅไพ่ต–้กนใ€‚ +็Žฐๅœจไฝ ๅฏไปฅ้€š่ฟ‡ `Depends` ๅฐ† `oauth2_scheme` ไฝœไธบไพ่ต–ไผ ๅ…ฅใ€‚ -{* ../../docs_src/security/tutorial001.py hl[10] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} -่ฏฅไพ่ต–้กนไฝฟ็”จๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰ๆŽฅๆ”ถ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ `token` ใ€‚ +่ฏฅไพ่ต–ไผšๆไพ›ไธ€ไธช `str`๏ผŒ่ต‹ๅ€ผ็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ `token`ใ€‚ -**FastAPI** ไฝฟ็”จไพ่ต–้กนๅœจ OpenAPI ๆฆ‚ๅ›พ๏ผˆๅŠ API ๆ–‡ๆกฃ๏ผ‰ไธญๅฎšไน‰**ๅฎ‰ๅ…จๆ–นๆกˆ**ใ€‚ +**FastAPI** ไผšๆฎๆญคๅœจ OpenAPI ๆžถๆž„๏ผˆไปฅๅŠ่‡ชๅŠจ็”Ÿๆˆ็š„ API ๆ–‡ๆกฃ๏ผ‰ไธญๅฎšไน‰ไธ€ไธชโ€œๅฎ‰ๅ…จๆ–นๆกˆโ€ใ€‚ /// info | ๆŠ€ๆœฏ็ป†่Š‚ -**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 ็š„ๆ–นๅผใ€‚ /// -## ๅฎž็Žฐ็š„ๆ“ไฝœ +## ๅฎƒๅšไบ†ไป€ไนˆ { #what-it-does } -FastAPI ๆ ก้ชŒ่ฏทๆฑ‚ไธญ็š„ `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๆ ธๅฏน่ฏทๆฑ‚ๅคด็š„ๅ€ผๆ˜ฏไธๆ˜ฏ็”ฑ `Bearer ` ๏ผ‹ ไปค็‰Œ็ป„ๆˆ๏ผŒ ๅนถ่ฟ”ๅ›žไปค็‰Œๅญ—็ฌฆไธฒ๏ผˆ`str`๏ผ‰ใ€‚ +ๅฎƒไผšๅœจ่ฏทๆฑ‚ไธญๆŸฅๆ‰พ `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๆฃ€ๆŸฅๅ…ถๅ€ผๆ˜ฏๅฆไธบ `Bearer ` ๅŠ ไธŠไธ€ไบ›ไปค็‰Œ๏ผŒๅนถๅฐ†่ฏฅไปค็‰Œไฝœไธบ `str` ่ฟ”ๅ›žใ€‚ -ๅฆ‚ๆžœๆฒกๆœ‰ๆ‰พๅˆฐ `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๆˆ–่ฏทๆฑ‚ๅคด็š„ๅ€ผไธๆ˜ฏ `Bearer ` ๏ผ‹ ไปค็‰Œใ€‚FastAPI ็›ดๆŽฅ่ฟ”ๅ›ž 401 ้”™่ฏฏ็Šถๆ€็ ๏ผˆ`UNAUTHORIZED`๏ผ‰ใ€‚ +ๅฆ‚ๆžœๆฒกๆœ‰ `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๆˆ–่€…ๅ…ถๅ€ผไธๅŒ…ๅซ `Bearer ` ไปค็‰Œ๏ผŒๅฎƒไผš็›ดๆŽฅ่ฟ”ๅ›ž 401 ็Šถๆ€็ ้”™่ฏฏ๏ผˆ`UNAUTHORIZED`๏ผ‰ใ€‚ -ๅผ€ๅ‘่€…ไธ้œ€่ฆๆฃ€ๆŸฅ้”™่ฏฏไฟกๆฏ๏ผŒๆŸฅ็œ‹ไปค็‰Œๆ˜ฏๅฆๅญ˜ๅœจ๏ผŒๅช่ฆ่ฏฅๅ‡ฝๆ•ฐ่ƒฝๅคŸๆ‰ง่กŒ๏ผŒๅ‡ฝๆ•ฐไธญๅฐฑไผšๅŒ…ๅซไปค็‰Œๅญ—็ฌฆไธฒใ€‚ +ไฝ ็”š่‡ณๆ— ้œ€ๆฃ€ๆŸฅไปค็‰Œๆ˜ฏๅฆๅญ˜ๅœจๅณๅฏ่ฟ”ๅ›ž้”™่ฏฏ๏ผ›ๅช่ฆไฝ ็š„ๅ‡ฝๆ•ฐ่ขซๆ‰ง่กŒ๏ผŒๅฐฑๅฏไปฅ็กฎๅฎšไผšๆ‹ฟๅˆฐไธ€ไธช `str` ็ฑปๅž‹็š„ไปค็‰Œใ€‚ -ๆญฃๅฆ‚ไธ‹ๅ›พๆ‰€็คบ๏ผŒAPI ๆ–‡ๆกฃๅทฒ็ปๅŒ…ๅซไบ†่ฟ™้กนๅŠŸ่ƒฝ๏ผš +ไฝ ๅทฒ็ปๅฏไปฅๅœจไบคไบ’ๅผๆ–‡ๆกฃไธญ่ฏ•่ฏ•ไบ†๏ผš -็›ฎๅ‰๏ผŒๆš‚ๆ—ถ่ฟ˜ๆฒกๆœ‰ๅฎž็Žฐ้ชŒ่ฏไปค็‰Œๆ˜ฏๅฆๆœ‰ๆ•ˆ็š„ๅŠŸ่ƒฝ๏ผŒไธ่ฟ‡ๅŽๆ–‡ๅพˆๅฟซๅฐฑไผšไป‹็ป็š„ใ€‚ +ๆˆ‘ไปฌ่ฟ˜ๆฒกๆœ‰้ชŒ่ฏไปค็‰Œๆ˜ฏๅฆๆœ‰ๆ•ˆ๏ผŒไฝ†่ฟ™ๅทฒ็ปๆ˜ฏไธ€ไธช่‰ฏๅฅฝ็š„ๅผ€็ซฏใ€‚ -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -็œ‹ๅˆฐไบ†ๅง๏ผŒๅช่ฆๅคšๅ†™ไธ‰ๅ››่กŒไปฃ็ ๏ผŒๅฐฑๅฏไปฅๆทปๅŠ ๅŸบ็ก€็š„ๅฎ‰ๅ…จ่กจๅ•ใ€‚ +ๅช้œ€ๅขžๅŠ ไธ‰ๅ››่กŒไปฃ็ ๏ผŒไฝ ๅฐฑๅทฒ็ปๆ‹ฅๆœ‰ไบ†ไธ€็งๅˆๆญฅ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md index 1f254a1037..c14bba28af 100644 --- a/docs/zh/docs/tutorial/security/get-current-user.md +++ b/docs/zh/docs/tutorial/security/get-current-user.md @@ -1,23 +1,23 @@ -# ่Žทๅ–ๅฝ“ๅ‰็”จๆˆท +# ่Žทๅ–ๅฝ“ๅ‰็”จๆˆท { #get-current-user } ไธŠไธ€็ซ ไธญ๏ผŒ๏ผˆๅŸบไบŽไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ็š„๏ผ‰ๅฎ‰ๅ…จ็ณป็ปŸๅ‘*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไผ ้€’ไบ† `str` ็ฑปๅž‹็š„ `token`๏ผš -{* ../../docs_src/security/tutorial001.py hl[10] *} +{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} ไฝ†่ฟ™ๅนถไธๅฎž็”จใ€‚ ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅญฆไน ๅฆ‚ไฝ•่ฟ”ๅ›žๅฝ“ๅ‰็”จๆˆทใ€‚ -## ๅˆ›ๅปบ็”จๆˆทๆจกๅž‹ +## ๅˆ›ๅปบ็”จๆˆทๆจกๅž‹ { #create-a-user-model } ้ฆ–ๅ…ˆ๏ผŒๅˆ›ๅปบ Pydantic ็”จๆˆทๆจกๅž‹ใ€‚ ไธŽไฝฟ็”จ Pydantic ๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“็›ธๅŒ๏ผŒๅนถไธ”ๅฏๅœจไปปไฝ•ไฝ็ฝฎไฝฟ็”จ๏ผš -{* ../../docs_src/security/tutorial002.py hl[5,12:16] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} -## ๅˆ›ๅปบ `get_current_user` ไพ่ต–้กน +## ๅˆ›ๅปบ `get_current_user` ไพ่ต–้กน { #create-a-get-current-user-dependency } ๅˆ›ๅปบ `get_current_user` ไพ่ต–้กนใ€‚ @@ -27,19 +27,19 @@ ไธŽไน‹ๅ‰็›ดๆŽฅๅœจ่ทฏๅพ„ๆ“ไฝœไธญ็š„ๅšๆณ•็›ธๅŒ๏ผŒๆ–ฐ็š„ `get_current_user` ไพ่ต–้กนไปŽๅญไพ่ต–้กน `oauth2_scheme` ไธญๆŽฅๆ”ถ `str` ็ฑปๅž‹็š„ `token`๏ผš -{* ../../docs_src/security/tutorial002.py hl[25] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} -## ่Žทๅ–็”จๆˆท +## ่Žทๅ–็”จๆˆท { #get-the-user } `get_current_user` ไฝฟ็”จๅˆ›ๅปบ็š„๏ผˆไผช๏ผ‰ๅทฅๅ…ทๅ‡ฝๆ•ฐ๏ผŒ่ฏฅๅ‡ฝๆ•ฐๆŽฅๆ”ถ `str` ็ฑปๅž‹็š„ไปค็‰Œ๏ผŒๅนถ่ฟ”ๅ›ž Pydantic ็š„ `User` ๆจกๅž‹๏ผš -{* ../../docs_src/security/tutorial002.py hl[19:22,26:27] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} -## ๆณจๅ…ฅๅฝ“ๅ‰็”จๆˆท +## ๆณจๅ…ฅๅฝ“ๅ‰็”จๆˆท { #inject-the-current-user } ๅœจ*่ทฏๅพ„ๆ“ไฝœ* ็š„ `Depends` ไธญไฝฟ็”จ `get_current_user`๏ผš -{* ../../docs_src/security/tutorial002.py hl[31] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} ๆณจๆ„๏ผŒๆญคๅค„ๆŠŠ `current_user` ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ Pydantic ็š„ `User` ๆจกๅž‹ใ€‚ @@ -61,7 +61,7 @@ /// -## ๅ…ถๅฎƒๆจกๅž‹ +## ๅ…ถๅฎƒๆจกๅž‹ { #other-models } ๆŽฅไธ‹ๆฅ๏ผŒ็›ดๆŽฅๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ่Žทๅ–ๅฝ“ๅ‰็”จๆˆท๏ผŒๅนถ็”จ `Depends` ๅœจ**ไพ่ต–ๆณจๅ…ฅ**็ณป็ปŸไธญๅค„็†ๅฎ‰ๅ…จๆœบๅˆถใ€‚ @@ -78,7 +78,7 @@ ๅฐฝ็ฎกไฝฟ็”จๅบ”็”จๆ‰€้œ€็š„ไปปไฝ•ๆจกๅž‹ใ€็ฑปใ€ๆ•ฐๆฎๅบ“ใ€‚**FastAPI** ้€š่ฟ‡ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ้ƒฝ่ƒฝๅธฎๆ‚จๆžๅฎšใ€‚ -## ไปฃ็ ๅคงๅฐ +## ไปฃ็ ๅคงๅฐ { #code-size } ่ฟ™ไธช็คบไพ‹็œ‹่ตทๆฅๆœ‰ไบ›ๅ†—้•ฟใ€‚ๆฏ•็ซŸ่ฟ™ไธชๆ–‡ไปถๅŒๆ—ถๅŒ…ๅซไบ†ๅฎ‰ๅ…จใ€ๆ•ฐๆฎๆจกๅž‹็š„ๅทฅๅ…ทๅ‡ฝๆ•ฐ๏ผŒไปฅๅŠ่ทฏๅพ„ๆ“ไฝœ็ญ‰ไปฃ็ ใ€‚ @@ -94,9 +94,9 @@ ๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ๅช้œ€ 3 ่กŒไปฃ็ ๅฐฑๅฏไปฅไบ†๏ผš -{* ../../docs_src/security/tutorial002.py hl[30:32] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } ็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅฏไปฅ็›ดๆŽฅๅœจ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ่Žทๅ–ๅฝ“ๅ‰็”จๆˆทใ€‚ diff --git a/docs/zh/docs/tutorial/security/index.md b/docs/zh/docs/tutorial/security/index.md index 1484b99fd8..589f93c3e9 100644 --- a/docs/zh/docs/tutorial/security/index.md +++ b/docs/zh/docs/tutorial/security/index.md @@ -1,4 +1,4 @@ -# ๅฎ‰ๅ…จๆ€ง +# ๅฎ‰ๅ…จๆ€ง { #security } ๆœ‰่ฎธๅคšๆ–นๆณ•ๅฏไปฅๅค„็†ๅฎ‰ๅ…จๆ€งใ€่บซไปฝ่ฎค่ฏๅ’ŒๆŽˆๆƒ็ญ‰้—ฎ้ข˜ใ€‚ @@ -10,11 +10,11 @@ ไฝ†้ฆ–ๅ…ˆ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅ็œ‹ไธ€ไบ›ๅฐ็š„ๆฆ‚ๅฟตใ€‚ -## ๆฒกๆœ‰ๆ—ถ้—ด๏ผŸ +## ๆฒกๆœ‰ๆ—ถ้—ด๏ผŸ { #in-a-hurry } -ๅฆ‚ๆžœไฝ ไธๅ…ณๅฟƒ่ฟ™ไบ›ๆœฏ่ฏญ๏ผŒ่€Œๅช้œ€่ฆ*็ซ‹ๅณ*้€š่ฟ‡ๅŸบไบŽ็”จๆˆทๅๅ’Œๅฏ†็ ็š„่บซไปฝ่ฎค่ฏๆฅๅขžๅŠ ๅฎ‰ๅ…จๆ€ง๏ผŒ่ฏท่ทณ่ฝฌๅˆฐไธ‹ไธ€็ซ ใ€‚ +ๅฆ‚ๆžœไฝ ไธๅ…ณๅฟƒ่ฟ™ไบ›ๆœฏ่ฏญ๏ผŒ่€Œๅช้œ€่ฆ*็ซ‹ๅณ*้€š่ฟ‡ๅŸบไบŽ็”จๆˆทๅๅ’Œๅฏ†็ ็š„่บซไปฝ่ฎค่ฏๆฅๅขžๅŠ ๅฎ‰ๅ…จๆ€ง๏ผŒ่ฏท่ทณ่ฝฌๅˆฐๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ใ€‚ -## OAuth2 +## OAuth2 { #oauth2 } OAuth2ๆ˜ฏไธ€ไธช่ง„่Œƒ๏ผŒๅฎƒๅฎšไน‰ไบ†ๅ‡ ็งๅค„็†่บซไปฝ่ฎค่ฏๅ’ŒๆŽˆๆƒ็š„ๆ–นๆณ•ใ€‚ @@ -24,7 +24,7 @@ OAuth2ๆ˜ฏไธ€ไธช่ง„่Œƒ๏ผŒๅฎƒๅฎšไน‰ไบ†ๅ‡ ็งๅค„็†่บซไปฝ่ฎค่ฏๅ’ŒๆŽˆๆƒ็š„ๆ–นๆณ• ่ฟ™ๅฐฑๆ˜ฏๆ‰€ๆœ‰ๅธฆๆœ‰ใ€Œไฝฟ็”จ Facebook๏ผŒGoogle๏ผŒX (Twitter)๏ผŒGitHub ็™ปๅฝ•ใ€็š„็ณป็ปŸ่ƒŒๅŽๆ‰€ไฝฟ็”จ็š„ๆœบๅˆถใ€‚ -### OAuth 1 +### OAuth 1 { #oauth-1 } ๆœ‰ไธ€ไธช OAuth 1๏ผŒๅฎƒไธŽ OAuth2 ๅฎŒๅ…จไธๅŒ๏ผŒๅนถไธ”ๆ›ดไธบๅคๆ‚๏ผŒๅ› ไธบๅฎƒ็›ดๆŽฅๅŒ…ๅซไบ†ๆœ‰ๅ…ณๅฆ‚ไฝ•ๅŠ ๅฏ†้€šไฟก็š„่ง„่Œƒใ€‚ @@ -32,13 +32,13 @@ OAuth2ๆ˜ฏไธ€ไธช่ง„่Œƒ๏ผŒๅฎƒๅฎšไน‰ไบ†ๅ‡ ็งๅค„็†่บซไปฝ่ฎค่ฏๅ’ŒๆŽˆๆƒ็š„ๆ–นๆณ• OAuth2 ๆฒกๆœ‰ๆŒ‡ๅฎšๅฆ‚ไฝ•ๅŠ ๅฏ†้€šไฟก๏ผŒๅฎƒๆœŸๆœ›ไฝ ไธบๅบ”็”จ็จ‹ๅบไฝฟ็”จ HTTPS ่ฟ›่กŒ้€šไฟกใ€‚ -/// tip +/// tip | ๆ็คบ ๅœจๆœ‰ๅ…ณ**้ƒจ็ฝฒ**็š„็ซ ่Š‚ไธญ๏ผŒไฝ ๅฐ†ไบ†่งฃๅฆ‚ไฝ•ไฝฟ็”จ Traefik ๅ’Œ Let's Encrypt ๅ…่ดน่ฎพ็ฝฎ HTTPSใ€‚ /// -## OpenID Connect +## OpenID Connect { #openid-connect } OpenID Connect ๆ˜ฏๅฆไธ€ไธชๅŸบไบŽ **OAuth2** ็š„่ง„่Œƒใ€‚ @@ -48,7 +48,7 @@ OpenID Connect ๆ˜ฏๅฆไธ€ไธชๅŸบไบŽ **OAuth2** ็š„่ง„่Œƒใ€‚ ไฝ†ๆ˜ฏ Facebook ็™ปๅฝ•ไธๆ”ฏๆŒ OpenID Connectใ€‚ๅฎƒๅ…ทๆœ‰่‡ชๅทฑ็š„ OAuth2 ้ฃŽๆ ผใ€‚ -### OpenID๏ผˆ้žใ€ŒOpenID Connectใ€๏ผ‰ +### OpenID๏ผˆ้žใ€ŒOpenID Connectใ€๏ผ‰ { #openid-not-openid-connect } ่ฟ˜ๆœ‰ไธ€ไธชใ€ŒOpenIDใ€่ง„่Œƒใ€‚ๅฎƒ่ฏ•ๅ›พ่งฃๅ†ณไธŽ **OpenID Connect** ็›ธๅŒ็š„้—ฎ้ข˜๏ผŒไฝ†ๅฎƒไธๆ˜ฏๅŸบไบŽ OAuth2ใ€‚ @@ -56,7 +56,7 @@ OpenID Connect ๆ˜ฏๅฆไธ€ไธชๅŸบไบŽ **OAuth2** ็š„่ง„่Œƒใ€‚ ๅฆ‚ไปŠๅฎƒๅทฒ็ปไธๆ˜ฏๅพˆๆต่กŒ๏ผŒๆฒกๆœ‰่ขซๅนฟๆณ›ไฝฟ็”จไบ†ใ€‚ -## OpenAPI +## OpenAPI { #openapi } OpenAPI๏ผˆไปฅๅ‰็งฐไธบ Swagger๏ผ‰ๆ˜ฏ็”จไบŽๆž„ๅปบ API ็š„ๅผ€ๆ”พ่ง„่Œƒ๏ผˆ็Žฐๅทฒๆˆไธบ Linux Foundation ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ @@ -75,7 +75,7 @@ OpenAPI ๅฎšไน‰ไบ†ไปฅไธ‹ๅฎ‰ๅ…จๆ–นๆกˆ๏ผš * ่ฏทๆฑ‚ๅคดใ€‚ * cookieใ€‚ * `http`๏ผšๆ ‡ๅ‡†็š„ HTTP ่บซไปฝ่ฎค่ฏ็ณป็ปŸ๏ผŒๅŒ…ๆ‹ฌ๏ผš - * `bearer`: ไธ€ไธชๅ€ผไธบ `Bearer` ๅŠ ไปค็‰Œๅญ—็ฌฆไธฒ็š„ `Authorization` ่ฏทๆฑ‚ๅคดใ€‚่ฟ™ๆ˜ฏไปŽ OAuth2 ็ปงๆ‰ฟ็š„ใ€‚ + * `bearer`: ไธ€ไธชๅ€ผไธบ `Bearer ` ๅŠ ไปค็‰Œๅญ—็ฌฆไธฒ็š„ `Authorization` ่ฏทๆฑ‚ๅคดใ€‚่ฟ™ๆ˜ฏไปŽ OAuth2 ็ปงๆ‰ฟ็š„ใ€‚ * HTTP Basic ่ฎค่ฏๆ–นๅผใ€‚ * HTTP Digest๏ผŒ็ญ‰็ญ‰ใ€‚ * `oauth2`๏ผšๆ‰€ๆœ‰็š„ OAuth2 ๅค„็†ๅฎ‰ๅ…จๆ€ง็š„ๆ–นๅผ๏ผˆ็งฐไธบใ€Œๆต็จ‹ใ€๏ผ‰ใ€‚ @@ -89,7 +89,7 @@ OpenAPI ๅฎšไน‰ไบ†ไปฅไธ‹ๅฎ‰ๅ…จๆ–นๆกˆ๏ผš * ๆญค่‡ชๅŠจๅ‘็Žฐๆœบๅˆถๆ˜ฏ OpenID Connect ่ง„่Œƒไธญๅฎšไน‰็š„ๅ†…ๅฎนใ€‚ -/// tip +/// tip | ๆ็คบ ้›†ๆˆๅ…ถไป–่บซไปฝ่ฎค่ฏ/ๆŽˆๆƒๆไพ›่€…๏ผˆไพ‹ๅฆ‚Google๏ผŒFacebook๏ผŒX (Twitter)๏ผŒGitHub็ญ‰๏ผ‰ไนŸๆ˜ฏๅฏ่ƒฝ็š„๏ผŒ่€Œไธ”่พƒไธบๅฎนๆ˜“ใ€‚ @@ -97,10 +97,10 @@ OpenAPI ๅฎšไน‰ไบ†ไปฅไธ‹ๅฎ‰ๅ…จๆ–นๆกˆ๏ผš /// -## **FastAPI** ๅฎž็”จๅทฅๅ…ท +## **FastAPI** ๅฎž็”จๅทฅๅ…ท { #fastapi-utilities } FastAPI ๅœจ `fastapi.security` ๆจกๅ—ไธญไธบๆฏไธชๅฎ‰ๅ…จๆ–นๆกˆๆไพ›ไบ†ๅ‡ ็งๅทฅๅ…ท๏ผŒ่ฟ™ไบ›ๅทฅๅ…ท็ฎ€ๅŒ–ไบ†่ฟ™ไบ›ๅฎ‰ๅ…จๆœบๅˆถ็š„ไฝฟ็”จๆ–นๆณ•ใ€‚ -ๅœจไธ‹ไธ€็ซ ไธญ๏ผŒไฝ ๅฐ†็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จ **FastAPI** ๆ‰€ๆไพ›็š„่ฟ™ไบ›ๅทฅๅ…ทไธบไฝ ็š„ API ๅขžๅŠ ๅฎ‰ๅ…จๆ€งใ€‚ +ๅœจๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ไธญ๏ผŒไฝ ๅฐ†็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จ **FastAPI** ๆ‰€ๆไพ›็š„่ฟ™ไบ›ๅทฅๅ…ทไธบไฝ ็š„ API ๅขžๅŠ ๅฎ‰ๅ…จๆ€งใ€‚ ่€Œไธ”ไฝ ่ฟ˜ๅฐ†็œ‹ๅˆฐๅฎƒๅฆ‚ไฝ•่‡ชๅŠจๅœฐ่ขซ้›†ๆˆๅˆฐไบคไบ’ๅผๆ–‡ๆกฃ็ณป็ปŸไธญใ€‚ diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index 7d338419b5..c7eb9bd907 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -1,34 +1,36 @@ -# OAuth2 ๅฎž็Žฐๅฏ†็ ๅ“ˆๅธŒไธŽ Bearer JWT ไปค็‰Œ้ชŒ่ฏ +# ไฝฟ็”จๅฏ†็ ๏ผˆๅŠๅ“ˆๅธŒ๏ผ‰็š„ OAuth2๏ผŒๅŸบไบŽ JWT ็š„ Bearer ไปค็‰Œ { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -่‡ณๆญค๏ผŒๆˆ‘ไปฌๅทฒ็ป็ผ–ๅ†™ไบ†ๆ‰€ๆœ‰ๅฎ‰ๅ…จๆต๏ผŒๆœฌ็ซ ๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จ JWT ไปค็‰Œ๏ผˆToken๏ผ‰ๅ’Œๅฎ‰ๅ…จๅฏ†็ ๅ“ˆๅธŒ๏ผˆHash๏ผ‰ๅฎž็Žฐ็œŸๆญฃ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +็Žฐๅœจๆˆ‘ไปฌๅทฒ็ปๆœ‰ไบ†ๅฎŒๆ•ด็š„ๅฎ‰ๅ…จๆต็จ‹๏ผŒๆŽฅไธ‹ๆฅ็”จ JWT ไปค็‰Œๅ’Œๅฎ‰ๅ…จ็š„ๅฏ†็ ๅ“ˆๅธŒ๏ผŒ่ฎฉๅบ”็”จ็œŸๆญฃๅฎ‰ๅ…จ่ตทๆฅใ€‚ -ๆœฌ็ซ ็š„็คบไพ‹ไปฃ็ ็œŸๆญฃๅฎž็Žฐไบ†ๅœจๅบ”็”จ็š„ๆ•ฐๆฎๅบ“ไธญไฟๅญ˜ๅ“ˆๅธŒๅฏ†็ ็ญ‰ๅŠŸ่ƒฝใ€‚ +่ฟ™ไบ›ไปฃ็ ๅฏไปฅ็›ดๆŽฅ็”จไบŽไฝ ็š„ๅบ”็”จ๏ผŒไฝ ๅฏไปฅๆŠŠๅฏ†็ ๅ“ˆๅธŒไฟๅญ˜ๅˆฐๆ•ฐๆฎๅบ“ไธญ๏ผŒ็ญ‰็ญ‰ใ€‚ -ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌ็ดงๆŽฅไธŠไธ€็ซ ๏ผŒ็ปง็ปญๅฎŒๅ–„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ๆˆ‘ไปฌๅฐ†ไปŽไธŠไธ€็ซ ็ป“ๆŸ็š„ๅœฐๆ–น็ปง็ปญ๏ผŒ้€ๆญฅๅฎŒๅ–„ใ€‚ -## JWT ็ฎ€ไป‹ +## ๅ…ณไบŽ JWT { #about-jwt } -JWT ๅณ**JSON ็ฝ‘็ปœไปค็‰Œ**๏ผˆJSON Web Tokens๏ผ‰ใ€‚ +JWT ๆ„ไธบ โ€œJSON Web Tokensโ€ใ€‚ -JWT ๆ˜ฏไธ€็งๅฐ† JSON ๅฏน่ฑก็ผ–็ ไธบๆฒกๆœ‰็ฉบๆ ผ๏ผŒไธ”้šพไปฅ็†่งฃ็š„้•ฟๅญ—็ฌฆไธฒ็š„ๆ ‡ๅ‡†ใ€‚JWT ็š„ๅ†…ๅฎนๅฆ‚ไธ‹ๆ‰€็คบ๏ผš +ๅฎƒๆ˜ฏไธ€็งๆ ‡ๅ‡†๏ผŒๆŠŠไธ€ไธช JSON ๅฏน่ฑก็ผ–็ ๆˆๆฒกๆœ‰็ฉบๆ ผใ€ๅพˆๅฏ†้›†็š„ไธ€้•ฟไธฒๅญ—็ฌฆไธฒใ€‚็œ‹่ตทๆฅๅƒ่ฟ™ๆ ท๏ผš ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` -JWT ๅญ—็ฌฆไธฒๆฒกๆœ‰ๅŠ ๅฏ†๏ผŒไปปไฝ•ไบบ้ƒฝ่ƒฝ็”จๅฎƒๆขๅคๅŽŸๅง‹ไฟกๆฏใ€‚ +ๅฎƒไธๆ˜ฏๅŠ ๅฏ†็š„๏ผŒๆ‰€ไปฅไปปไฝ•ไบบ้ƒฝๅฏไปฅไปŽๅ†…ๅฎนไธญๆขๅคไฟกๆฏใ€‚ -ไฝ† JWT ไฝฟ็”จไบ†็ญพๅๆœบๅˆถใ€‚ๆŽฅๅ—ไปค็‰Œๆ—ถ๏ผŒๅฏไปฅ็”จ็ญพๅๆ ก้ชŒไปค็‰Œใ€‚ +ไฝ†ๅฎƒๆ˜ฏโ€œ็ญพๅโ€็š„ใ€‚ๅ› ๆญค๏ผŒๅฝ“ไฝ ๆ”ถๅˆฐไธ€ไธช่‡ชๅทฑ็ญพๅ‘็š„ไปค็‰Œๆ—ถ๏ผŒไฝ ๅฏไปฅ้ชŒ่ฏๅฎƒ็กฎๅฎžๆ˜ฏไฝ ็ญพๅ‘็š„ใ€‚ -ไฝฟ็”จ JWT ๅˆ›ๅปบๆœ‰ๆ•ˆๆœŸไธบไธ€ๅ‘จ็š„ไปค็‰Œใ€‚็ฌฌไบŒๅคฉ๏ผŒ็”จๆˆทๆŒไปค็‰Œๅ†ๆฌก่ฎฟ้—ฎๆ—ถ๏ผŒไปไธบ็™ปๅฝ•็Šถๆ€ใ€‚ +่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅˆ›ๅปบไธ€ไธชไพ‹ๅฆ‚ๆœ‰ๆ•ˆๆœŸไธบ 1 ๅ‘จ็š„ไปค็‰Œใ€‚็„ถๅŽๅฝ“็”จๆˆท็ฌฌไบŒๅคฉๅธฆ็€่ฟ™ไธชไปค็‰Œๅ›žๆฅๆ—ถ๏ผŒไฝ ่ƒฝ็Ÿฅ้“่ฏฅ็”จๆˆทไป็„ถๅค„ไบŽ็™ปๅฝ•็Šถๆ€ใ€‚ -ไปค็‰ŒไบŽไธ€ๅ‘จๅŽ่ฟ‡ๆœŸ๏ผŒๅฑŠๆ—ถ๏ผŒ็”จๆˆท่บซไปฝ้ชŒ่ฏๅฐฑไผšๅคฑ่ดฅใ€‚ๅชๆœ‰ๅ†ๆฌก็™ปๅฝ•๏ผŒๆ‰่ƒฝ่Žทๅพ—ๆ–ฐ็š„ไปค็‰Œใ€‚ๅฆ‚ๆžœ็”จๆˆท๏ผˆๆˆ–็ฌฌไธ‰ๆ–น๏ผ‰็ฏกๆ”นไปค็‰Œ็š„่ฟ‡ๆœŸๆ—ถ้—ด๏ผŒๅ› ไธบ็ญพๅไธๅŒน้…ไผšๅฏผ่‡ด่บซไปฝ้ชŒ่ฏๅคฑ่ดฅใ€‚ +ไธ€ๅ‘จๅŽไปค็‰Œ่ฟ‡ๆœŸ๏ผŒ็”จๆˆทๅฐ†ไธๅ†่ขซๆŽˆๆƒ๏ผŒ้œ€่ฆ้‡ๆ–ฐ็™ปๅฝ•ไปฅ่Žทๅ–ๆ–ฐไปค็‰Œใ€‚่€Œๅฆ‚ๆžœ็”จๆˆท๏ผˆๆˆ–็ฌฌไธ‰ๆ–น๏ผ‰ๅฐ่ฏ•ไฟฎๆ”นไปค็‰Œๆฅๆ›ดๆ”น่ฟ‡ๆœŸๆ—ถ้—ด๏ผŒไฝ ไนŸ่ƒฝๅ‘็Žฐ๏ผŒๅ› ไธบ็ญพๅๅฐ†ไธๅŒน้…ใ€‚ -ๅฆ‚้œ€ๆทฑๅ…ฅไบ†่งฃ JWT ไปค็‰Œ๏ผŒไบ†่งฃๅฎƒ็š„ๅทฅไฝœๆ–นๅผ๏ผŒ่ฏทๅ‚้˜… https://jwt.ioใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณๅŠจๆ‰‹ไฝ“้ชŒ JWT ไปค็‰Œๅนถไบ†่งฃๅฎƒ็š„ๅทฅไฝœๆ–นๅผ๏ผŒ่ฏท่ฎฟ้—ฎ https://jwt.ioใ€‚ -## ๅฎ‰่ฃ… `PyJWT` +## ๅฎ‰่ฃ… `PyJWT` { #install-pyjwt } -ๅฎ‰่ฃ… `PyJWT`๏ผŒๅœจ Python ไธญ็”Ÿๆˆๅ’Œๆ ก้ชŒ JWT ไปค็‰Œ๏ผš +ๆˆ‘ไปฌ้œ€่ฆๅฎ‰่ฃ… `PyJWT`๏ผŒไปฅไพฟๅœจ Python ไธญ็”Ÿๆˆๅ’Œๆ ก้ชŒ JWT ไปค็‰Œใ€‚ + +่ฏท็กฎไฟๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ… `pyjwt`๏ผš
@@ -40,42 +42,42 @@ $ pip install pyjwt
-/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -ๅฆ‚ๆžœๆ‚จๆ‰“็ฎ—ไฝฟ็”จ็ฑปไผผ RSA ๆˆ– ECDSA ็š„ๆ•ฐๅญ—็ญพๅ็ฎ—ๆณ•๏ผŒๆ‚จๅบ”่ฏฅๅฎ‰่ฃ…ๅŠ ๅฏ†ๅบ“ไพ่ต–้กน `pyjwt[crypto]`ใ€‚ +ๅฆ‚ๆžœไฝ ่ฎกๅˆ’ไฝฟ็”จ็ฑปไผผ RSA ๆˆ– ECDSA ็š„ๆ•ฐๅญ—็ญพๅ็ฎ—ๆณ•๏ผŒไฝ ๅบ”่ฏฅๅฎ‰่ฃ…ๅŠ ๅฏ†ๅบ“ไพ่ต–้กน `pyjwt[crypto]`ใ€‚ -ๆ‚จๅฏไปฅๅœจ PyJWT Installation docs ่Žทๅพ—ๆ›ดๅคšไฟกๆฏใ€‚ +ๅฏไปฅๅœจ PyJWT ๅฎ‰่ฃ…ๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšใ€‚ /// -## ๅฏ†็ ๅ“ˆๅธŒ +## ๅฏ†็ ๅ“ˆๅธŒ { #password-hashing } -**ๅ“ˆๅธŒ**ๆ˜ฏๆŒ‡ๆŠŠ็‰นๅฎšๅ†…ๅฎน๏ผˆๆœฌไพ‹ไธญไธบๅฏ†็ ๏ผ‰่ฝฌๆขไธบไนฑ็ ๅฝขๅผ็š„ๅญ—่Š‚ๅบๅˆ—๏ผˆๅ…ถๅฎžๅฐฑๆ˜ฏๅญ—็ฌฆไธฒ๏ผ‰ใ€‚ +โ€œๅ“ˆๅธŒโ€ๆ˜ฏๆŒ‡ๆŠŠไธ€ไบ›ๅ†…ๅฎน๏ผˆ่ฟ™้‡Œๆ˜ฏๅฏ†็ ๏ผ‰่ฝฌๆขๆˆ็œ‹่ตทๆฅๅƒไนฑ็ ็š„ไธ€ไธฒๅญ—่Š‚๏ผˆๅ…ถๅฎžๅฐฑๆ˜ฏๅญ—็ฌฆไธฒ๏ผ‰ใ€‚ -ๆฏๆฌกไผ ๅ…ฅๅฎŒๅ…จ็›ธๅŒ็š„ๅ†…ๅฎนๆ—ถ๏ผˆๆฏ”ๅฆ‚๏ผŒๅฎŒๅ…จ็›ธๅŒ็š„ๅฏ†็ ๏ผ‰๏ผŒ่ฟ”ๅ›ž็š„้ƒฝๆ˜ฏๅฎŒๅ…จ็›ธๅŒ็š„ไนฑ็ ใ€‚ +ๅฝ“ไฝ ๆฏๆฌกไผ ๅ…ฅๅฎŒๅ…จ็›ธๅŒ็š„ๅ†…ๅฎน๏ผˆๅฎŒๅ…จ็›ธๅŒ็š„ๅฏ†็ ๏ผ‰ๆ—ถ๏ผŒ้ƒฝไผšๅพ—ๅˆฐๅฎŒๅ…จ็›ธๅŒ็š„โ€œไนฑ็ โ€ใ€‚ -ไฝ†่ฟ™ไธชไนฑ็ ๆ— ๆณ•่ฝฌๆขๅ›žไผ ๅ…ฅ็š„ๅฏ†็ ใ€‚ +ไฝ†ไฝ ๆ— ๆณ•ไปŽ่ฟ™ไธชโ€œไนฑ็ โ€ๅๅ‘่ฟ˜ๅŽŸๅ‡บๅฏ†็ ใ€‚ -### ไธบไป€ไนˆไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒ +### ไธบไป€ไนˆไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒ { #why-use-password-hashing } -ๅŽŸๅ› ๅพˆ็ฎ€ๅ•๏ผŒๅ‡ๅฆ‚ๆ•ฐๆฎๅบ“่ขซ็›—๏ผŒ็ชƒ่ดผๆ— ๆณ•่Žทๅ–็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ๏ผŒๅพ—ๅˆฐ็š„ๅชๆ˜ฏๅ“ˆๅธŒๅ€ผใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๆ•ฐๆฎๅบ“่ขซ็›—๏ผŒ็ชƒ่ดผๆ‹ฟๅˆฐ็š„ไธไผšๆ˜ฏ็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ๏ผŒ่€Œๅชๆ˜ฏๅ“ˆๅธŒๅ€ผใ€‚ -่ฟ™ๆ ทไธ€ๆฅ๏ผŒ็ชƒ่ดผๅฐฑๆ— ๆณ•ๅœจๅ…ถๅฎƒๅบ”็”จไธญไฝฟ็”จ็ชƒๅ–็š„ๅฏ†็ ๏ผˆ่ฆ็Ÿฅ้“๏ผŒๅพˆๅคš็”จๆˆทๅœจๆ‰€ๆœ‰็ณป็ปŸไธญ้ƒฝไฝฟ็”จ็›ธๅŒ็š„ๅฏ†็ ๏ผŒ้ฃŽ้™ฉ่ถ…ๅคง๏ผ‰ใ€‚ +ๅ› ๆญค๏ผŒ็ชƒ่ดผๆ— ๆณ•ๆŠŠ่ฏฅๅฏ†็ ๆ‹ฟๅŽปๅฐ่ฏ•็™ปๅฝ•ๅฆไธ€ไธช็ณป็ปŸ๏ผˆๅพˆๅคš็”จๆˆทๅœจๅ„ๅค„้ƒฝ็”จ็›ธๅŒ็š„ๅฏ†็ ๏ผŒ่ฟ™ๅฐ†้žๅธธๅฑ้™ฉ๏ผ‰ใ€‚ -## ๅฎ‰่ฃ… `passlib` +## ๅฎ‰่ฃ… `pwdlib` { #install-pwdlib } -Passlib ๆ˜ฏๅค„็†ๅฏ†็ ๅ“ˆๅธŒ็š„ Python ๅŒ…ใ€‚ +pwdlib ๆ˜ฏไธ€ไธช็”จไบŽๅค„็†ๅฏ†็ ๅ“ˆๅธŒ็š„ไผ˜็ง€ Python ๅŒ…ใ€‚ -ๅฎƒๆ”ฏๆŒๅพˆๅคšๅฎ‰ๅ…จๅ“ˆๅธŒ็ฎ—ๆณ•ๅŠ้…ๅฅ—ๅทฅๅ…ทใ€‚ +ๅฎƒๆ”ฏๆŒๅคš็งๅฎ‰ๅ…จ็š„ๅ“ˆๅธŒ็ฎ—ๆณ•ไปฅๅŠ็›ธๅ…ณๅทฅๅ…ทใ€‚ -ๆœฌๆ•™็จ‹ๆŽจ่็š„็ฎ—ๆณ•ๆ˜ฏ **Bcrypt**ใ€‚ +ๆŽจ่็š„็ฎ—ๆณ•ๆ˜ฏ โ€œArgon2โ€ใ€‚ -ๅ› ๆญค๏ผŒ่ฏทๅ…ˆๅฎ‰่ฃ…้™„ๅธฆ Bcrypt ็š„ PassLib๏ผš +่ฏท็กฎไฟๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ…ๅธฆ Argon2 ็š„ pwdlib๏ผš
```console -$ pip install passlib[bcrypt] +$ pip install "pwdlib[argon2]" ---> 100% ``` @@ -84,51 +86,51 @@ $ pip install passlib[bcrypt] /// tip | ๆ็คบ -`passlib` ็”š่‡ณๅฏไปฅ่ฏปๅ– Djangoใ€Flask ็š„ๅฎ‰ๅ…จๆ’ไปถ็ญ‰ๅทฅๅ…ทๅˆ›ๅปบ็š„ๅฏ†็ ใ€‚ +ไฝฟ็”จ `pwdlib`๏ผŒไฝ ็”š่‡ณๅฏไปฅๆŠŠๅฎƒ้…็ฝฎไธบ่ƒฝๅคŸ่ฏปๅ–็”ฑ **Django**ใ€**Flask** ๅฎ‰ๅ…จๆ’ไปถๆˆ–ๅ…ถไป–่ฎธๅคšๅทฅๅ…ทๅˆ›ๅปบ็š„ๅฏ†็ ใ€‚ -ไพ‹ๅฆ‚๏ผŒๆŠŠ Django ๅบ”็”จ็š„ๆ•ฐๆฎๅ…ฑไบซ็ป™ FastAPI ๅบ”็”จ็š„ๆ•ฐๆฎๅบ“ใ€‚ๆˆ–ๅˆฉ็”จๅŒไธ€ไธชๆ•ฐๆฎๅบ“๏ผŒๅฏไปฅ้€ๆญฅๆŠŠๅบ”็”จไปŽ Django ่ฟ็งปๅˆฐ FastAPIใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅœจๆ•ฐๆฎๅบ“ไธญ่ฎฉไธ€ไธช Django ๅบ”็”จๅ’Œไธ€ไธช FastAPI ๅบ”็”จๅ…ฑไบซๅŒไธ€ไปฝๆ•ฐๆฎใ€‚ๆˆ–่€…ๅœจไฝฟ็”จๅŒไธ€ไธชๆ•ฐๆฎๅบ“็š„ๅ‰ๆไธ‹๏ผŒ้€ๆญฅ่ฟ็งปไธ€ไธช Django ๅบ”็”จๅˆฐ FastAPIใ€‚ -ๅนถไธ”๏ผŒ็”จๆˆทๅฏไปฅๅŒๆ—ถไปŽ Django ๅบ”็”จๆˆ– FastAPI ๅบ”็”จ็™ปๅฝ•ใ€‚ +ๅŒๆ—ถ๏ผŒไฝ ็š„็”จๆˆทๆ—ขๅฏไปฅไปŽ Django ๅบ”็”จ็™ปๅฝ•๏ผŒไนŸๅฏไปฅไปŽ **FastAPI** ๅบ”็”จ็™ปๅฝ•ใ€‚ /// -## ๅฏ†็ ๅ“ˆๅธŒไธŽๆ ก้ชŒ +## ๅ“ˆๅธŒๅนถๆ ก้ชŒๅฏ†็  { #hash-and-verify-the-passwords } -ไปŽ `passlib` ๅฏผๅ…ฅๆ‰€้œ€ๅทฅๅ…ทใ€‚ +ไปŽ `pwdlib` ๅฏผๅ…ฅๆ‰€้œ€ๅทฅๅ…ทใ€‚ -ๅˆ›ๅปบ็”จไบŽๅฏ†็ ๅ“ˆๅธŒๅ’Œ่บซไปฝๆ ก้ชŒ็š„ PassLib **ไธŠไธ‹ๆ–‡**ใ€‚ +็”จๆŽจ่่ฎพ็ฝฎๅˆ›ๅปบไธ€ไธช PasswordHash ๅฎžไพ‹โ€”โ€”ๅฎƒๅฐ†็”จไบŽๅ“ˆๅธŒไธŽๆ ก้ชŒๅฏ†็ ใ€‚ /// tip | ๆ็คบ -PassLib ไธŠไธ‹ๆ–‡่ฟ˜ๆ”ฏๆŒไฝฟ็”จไธๅŒๅ“ˆๅธŒ็ฎ—ๆณ•็š„ๅŠŸ่ƒฝ๏ผŒๅŒ…ๆ‹ฌๅช่ƒฝๆ ก้ชŒ็š„ๅทฒๅผƒ็”จๆ—ง็ฎ—ๆณ•็ญ‰ใ€‚ +pwdlib ไนŸๆ”ฏๆŒ bcrypt ๅ“ˆๅธŒ็ฎ—ๆณ•๏ผŒไฝ†ไธๅŒ…ๅซ้—็•™็ฎ—ๆณ•โ€”โ€”ๅฆ‚ๆžœ้œ€่ฆๅค„็†่ฟ‡ๆ—ถ็š„ๅ“ˆๅธŒ๏ผŒๅปบ่ฎฎไฝฟ็”จ passlib ๅบ“ใ€‚ -ไพ‹ๅฆ‚๏ผŒ็”จๅฎƒ่ฏปๅ–ๅ’Œๆ ก้ชŒๅ…ถๅฎƒ็ณป็ปŸ๏ผˆๅฆ‚ Django๏ผ‰็”Ÿๆˆ็š„ๅฏ†็ ๏ผŒไฝ†่ฆไฝฟ็”จๅ…ถๅฎƒ็ฎ—ๆณ•๏ผŒๅฆ‚ Bcrypt๏ผŒ็”Ÿๆˆๆ–ฐ็š„ๅ“ˆๅธŒๅฏ†็ ใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒ่ฏปๅ–ๅนถๆ ก้ชŒๅ…ถไป–็ณป็ปŸ๏ผˆๅฆ‚ Django๏ผ‰็”Ÿๆˆ็š„ๅฏ†็ ๏ผŒไฝ†ๅฏนไปปไฝ•ๆ–ฐๅฏ†็ ไฝฟ็”จไธๅŒ็š„็ฎ—ๆณ•๏ผˆๅฆ‚ Argon2 ๆˆ– Bcrypt๏ผ‰่ฟ›่กŒๅ“ˆๅธŒใ€‚ -ๅŒๆ—ถ๏ผŒ่ฟ™ไบ›ๅŠŸ่ƒฝ้ƒฝๆ˜ฏๅ…ผๅฎน็š„ใ€‚ +ๅนถไธ”่ƒฝๅคŸๅŒๆ—ถไธŽๅฎƒไปฌๅ…จ้ƒจๅ…ผๅฎนใ€‚ /// -ๆŽฅไธ‹ๆฅ๏ผŒๅˆ›ๅปบไธ‰ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐ๏ผŒๅ…ถไธญไธ€ไธชๅ‡ฝๆ•ฐ็”จไบŽๅ“ˆๅธŒ็”จๆˆท็š„ๅฏ†็ ใ€‚ +ๅˆ›ๅปบไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐๆฅๅ“ˆๅธŒ็”จๆˆทไผ ๅ…ฅ็š„ๅฏ†็ ใ€‚ -็ฌฌไธ€ไธชๅ‡ฝๆ•ฐ็”จไบŽๆ ก้ชŒๆŽฅๆ”ถ็š„ๅฏ†็ ๆ˜ฏๅฆๅŒน้…ๅญ˜ๅ‚จ็š„ๅ“ˆๅธŒๅ€ผใ€‚ +ๅ†ๅˆ›ๅปบไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐๆฅๆ ก้ชŒๆŽฅๆ”ถ็š„ๅฏ†็ ๆ˜ฏๅฆๅŒน้…ๅทฒๅญ˜ๅ‚จ็š„ๅ“ˆๅธŒใ€‚ -็ฌฌไธ‰ไธชๅ‡ฝๆ•ฐ็”จไบŽ่บซไปฝ้ชŒ่ฏ๏ผŒๅนถ่ฟ”ๅ›ž็”จๆˆทใ€‚ +ๅ†ๅˆ›ๅปบไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐๆฅ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏๅนถ่ฟ”ๅ›ž็”จๆˆทใ€‚ {* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๆŸฅ็œ‹ๆ–ฐ็š„๏ผˆไผช๏ผ‰ๆ•ฐๆฎๅบ“ `fake_users_db`๏ผŒๅฐฑ่ƒฝ็œ‹ๅˆฐๅ“ˆๅธŒๅŽ็š„ๅฏ†็ ๏ผš`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`ใ€‚ +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ๆ–ฐ็š„๏ผˆไผช๏ผ‰ๆ•ฐๆฎๅบ“ `fake_users_db`๏ผŒ็Žฐๅœจไฝ ไผš็œ‹ๅˆฐๅ“ˆๅธŒๅŽ็š„ๅฏ†็ ็ฑปไผผ่ฟ™ๆ ท๏ผš`"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`ใ€‚ /// -## ๅค„็† JWT ไปค็‰Œ +## ๅค„็† JWT ไปค็‰Œ { #handle-jwt-tokens } ๅฏผๅ…ฅๅทฒๅฎ‰่ฃ…็š„ๆจกๅ—ใ€‚ -ๅˆ›ๅปบ็”จไบŽ JWT ไปค็‰Œ็ญพๅ็š„้šๆœบๅฏ†้’ฅใ€‚ +ๅˆ›ๅปบไธ€ไธช็”จไบŽๅฏน JWT ไปค็‰Œ่ฟ›่กŒ็ญพๅ็š„้šๆœบๅฏ†้’ฅใ€‚ -ไฝฟ็”จไปฅไธ‹ๅ‘ฝไปค๏ผŒ็”Ÿๆˆๅฎ‰ๅ…จ็š„้šๆœบๅฏ†้’ฅ๏ผš +ไฝฟ็”จไธ‹ๅˆ—ๅ‘ฝไปค็”Ÿๆˆไธ€ไธชๅฎ‰ๅ…จ็š„้šๆœบๅฏ†้’ฅ๏ผš
@@ -140,81 +142,82 @@ $ openssl rand -hex 32
-็„ถๅŽ๏ผŒๆŠŠ็”Ÿๆˆ็š„ๅฏ†้’ฅๅคๅˆถๅˆฐๅ˜้‡**SECRET_KEY**๏ผŒๆณจๆ„๏ผŒไธ่ฆไฝฟ็”จๆœฌไพ‹ๆ‰€็คบ็š„ๅฏ†้’ฅใ€‚ +ๆŠŠ่พ“ๅ‡บๅคๅˆถๅˆฐๅ˜้‡ `SECRET_KEY`๏ผˆไธ่ฆไฝฟ็”จ็คบไพ‹ไธญ็š„้‚ฃไธช๏ผ‰ใ€‚ -ๅˆ›ๅปบๆŒ‡ๅฎš JWT ไปค็‰Œ็ญพๅ็ฎ—ๆณ•็š„ๅ˜้‡ **ALGORITHM**๏ผŒๆœฌไพ‹ไธญ็š„ๅ€ผไธบ `"HS256"`ใ€‚ +ๅˆ›ๅปบๅ˜้‡ `ALGORITHM`๏ผŒ่ฎพ็ฝฎ็”จไบŽ็ญพๅ JWT ไปค็‰Œ็š„็ฎ—ๆณ•๏ผŒ่ฟ™้‡Œ่ฎพไธบ `"HS256"`ใ€‚ -ๅˆ›ๅปบ่ฎพ็ฝฎไปค็‰Œ่ฟ‡ๆœŸๆ—ถ้—ด็š„ๅ˜้‡ใ€‚ +ๅˆ›ๅปบไธ€ไธชๅ˜้‡็”จไบŽ่ฎพ็ฝฎไปค็‰Œ็š„่ฟ‡ๆœŸๆ—ถ้—ดใ€‚ -ๅฎšไน‰ไปค็‰Œ็ซฏ็‚นๅ“ๅบ”็š„ Pydantic ๆจกๅž‹ใ€‚ +ๅฎšไน‰ไธ€ไธช็”จไบŽไปค็‰Œ็ซฏ็‚นๅ“ๅบ”็š„ Pydantic ๆจกๅž‹ใ€‚ -ๅˆ›ๅปบ็”Ÿๆˆๆ–ฐ็š„่ฎฟ้—ฎไปค็‰Œ็š„ๅทฅๅ…ทๅ‡ฝๆ•ฐใ€‚ +ๅˆ›ๅปบไธ€ไธช็”Ÿๆˆๆ–ฐ่ฎฟ้—ฎไปค็‰Œ็š„ๅทฅๅ…ทๅ‡ฝๆ•ฐใ€‚ -{* ../../docs_src/security/tutorial004.py hl[6,12:14,28:30,78:86] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} -## ๆ›ดๆ–ฐไพ่ต–้กน +## ๆ›ดๆ–ฐไพ่ต–้กน { #update-the-dependencies } -ๆ›ดๆ–ฐ `get_current_user` ไปฅๆŽฅๆ”ถไธŽไน‹ๅ‰็›ธๅŒ็š„ไปค็‰Œ๏ผŒไฝ†่ฟ™้‡Œ็”จ็š„ๆ˜ฏ JWT ไปค็‰Œใ€‚ +ๆ›ดๆ–ฐ `get_current_user` ไปฅๆŽฅๆ”ถไธŽไน‹ๅ‰็›ธๅŒ็š„ไปค็‰Œ๏ผŒไฝ†่ฟ™ๆฌกไฝฟ็”จ็š„ๆ˜ฏ JWT ไปค็‰Œใ€‚ -่งฃ็ ๅนถๆ ก้ชŒๆŽฅๆ”ถๅˆฐ็š„ไปค็‰Œ๏ผŒ็„ถๅŽ๏ผŒ่ฟ”ๅ›žๅฝ“ๅ‰็”จๆˆทใ€‚ +่งฃ็ ๆŽฅๆ”ถๅˆฐ็š„ไปค็‰Œ๏ผŒ่ฟ›่กŒๆ ก้ชŒ๏ผŒๅนถ่ฟ”ๅ›žๅฝ“ๅ‰็”จๆˆทใ€‚ -ๅฆ‚ๆžœไปค็‰Œๆ— ๆ•ˆ๏ผŒๅˆ™็›ดๆŽฅ่ฟ”ๅ›ž HTTP ้”™่ฏฏใ€‚ +ๅฆ‚ๆžœไปค็‰Œๆ— ๆ•ˆ๏ผŒ็ซ‹ๅณ่ฟ”ๅ›žไธ€ไธช HTTP ้”™่ฏฏใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} -## ๆ›ดๆ–ฐ `/token` *่ทฏๅพ„ๆ“ไฝœ* +## ๆ›ดๆ–ฐ `/token` ่ทฏๅพ„ๆ“ไฝœ { #update-the-token-path-operation } -็”จไปค็‰Œ่ฟ‡ๆœŸๆ—ถ้—ดๅˆ›ๅปบ `timedelta` ๅฏน่ฑกใ€‚ +็”จไปค็‰Œ็š„่ฟ‡ๆœŸๆ—ถ้—ดๅˆ›ๅปบไธ€ไธช `timedelta`ใ€‚ -ๅˆ›ๅปบๅนถ่ฟ”ๅ›ž็œŸๆญฃ็š„ JWT ่ฎฟ้—ฎไปค็‰Œใ€‚ +ๅˆ›ๅปบไธ€ไธช็œŸๆญฃ็š„ JWT ่ฎฟ้—ฎไปค็‰Œๅนถ่ฟ”ๅ›žๅฎƒใ€‚ {* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} -### JWT `sub` ็š„ๆŠ€ๆœฏ็ป†่Š‚ +### ๅ…ณไบŽ JWT โ€œไธป้ข˜โ€ `sub` ็š„ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details-about-the-jwt-subject-sub } -JWT ่ง„่Œƒ่ฟ˜ๅŒ…ๆ‹ฌ `sub` ้”ฎ๏ผŒๅ€ผๆ˜ฏไปค็‰Œ็š„ไธป้ข˜ใ€‚ +JWT ่ง„่Œƒไธญๆœ‰ไธ€ไธช `sub` ้”ฎ๏ผŒ่กจ็คบไปค็‰Œ็š„โ€œไธป้ข˜โ€๏ผˆsubject๏ผ‰ใ€‚ -่ฏฅ้”ฎๆ˜ฏๅฏ้€‰็š„๏ผŒไฝ†่ฆๆŠŠ็”จๆˆทๆ ‡่ฏ†ๆ”พๅœจ่ฟ™ไธช้”ฎ้‡Œ๏ผŒๆ‰€ไปฅๆœฌไพ‹ไฝฟ็”จไบ†่ฏฅ้”ฎใ€‚ +ไฝฟ็”จๅฎƒๆ˜ฏๅฏ้€‰็š„๏ผŒไฝ†้€šๅธธไผšๆŠŠ็”จๆˆท็š„ๆ ‡่ฏ†ๆ”พๅœจ่ฟ™้‡Œ๏ผŒๆ‰€ไปฅๆœฌไพ‹ไธญๆˆ‘ไปฌไฝฟ็”จๅฎƒใ€‚ -้™คไบ†่ฏ†ๅˆซ็”จๆˆทไธŽ่ฎธๅฏ็”จๆˆทๅœจ API ไธŠ็›ดๆŽฅๆ‰ง่กŒๆ“ไฝœไน‹ๅค–๏ผŒJWT ่ฟ˜ๅฏ่ƒฝ็”จไบŽๅ…ถๅฎƒไบ‹ๆƒ…ใ€‚ +JWT ้™คไบ†็”จไบŽ่ฏ†ๅˆซ็”จๆˆทๅนถๅ…่ฎธๅ…ถ็›ดๆŽฅๅœจไฝ ็š„ API ไธŠๆ‰ง่กŒๆ“ไฝœไน‹ๅค–๏ผŒ่ฟ˜ๅฏ่ƒฝ็”จไบŽๅ…ถไป–ๅœบๆ™ฏใ€‚ -ไพ‹ๅฆ‚๏ผŒ่ฏ†ๅˆซ**ๆฑฝ่ฝฆ**ๆˆ–**ๅšๅฎข**ใ€‚ +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒๆฅๆ ‡่ฏ†ไธ€่พ†โ€œ่ฝฆโ€ๆˆ–ไธ€็ฏ‡โ€œๅšๅฎขๆ–‡็ซ โ€ใ€‚ -ๆŽฅ็€๏ผŒไธบๅฎžไฝ“ๆทปๅŠ ๆƒ้™๏ผŒๆฏ”ๅฆ‚**้ฉพ้ฉถ**๏ผˆๆฑฝ่ฝฆ๏ผ‰ๆˆ–**็ผ–่พ‘**๏ผˆๅšๅฎข๏ผ‰ใ€‚ +็„ถๅŽไฝ ๅฏไปฅไธบ่ฏฅๅฎžไฝ“ๆทปๅŠ ๆƒ้™๏ผŒๆฏ”ๅฆ‚โ€œdriveโ€๏ผˆ็”จไบŽ่ฝฆ๏ผ‰ๆˆ–โ€œeditโ€๏ผˆ็”จไบŽๅšๅฎข๏ผ‰ใ€‚ -็„ถๅŽ๏ผŒๆŠŠ JWT ไปค็‰Œไบค็ป™็”จๆˆท๏ผˆๆˆ–ๆœบๅ™จไบบ๏ผ‰๏ผŒไป–ไปฌๅฐฑๅฏไปฅๆ‰ง่กŒ้ฉพ้ฉถๆฑฝ่ฝฆ๏ผŒๆˆ–็ผ–่พ‘ๅšๅฎข็ญ‰ๆ“ไฝœใ€‚ๆ— ้œ€ๆณจๅ†Œ่ดฆๆˆท๏ผŒๅช่ฆๆœ‰ API ็”Ÿๆˆ็š„ JWT ไปค็‰Œๅฐฑๅฏไปฅใ€‚ +ๆŽฅ็€๏ผŒไฝ ๅฏไปฅๆŠŠ่ฟ™ไธช JWT ไปค็‰Œไบค็ป™ไธ€ไธช็”จๆˆท๏ผˆๆˆ–ๆœบๅ™จไบบ๏ผ‰๏ผŒไป–ไปฌๅฐฑๅฏไปฅๅœจๆฒกๆœ‰่ดฆๆˆท็š„ๅ‰ๆไธ‹๏ผŒไป…ๅ‡ญไฝ ็š„ API ็”Ÿๆˆ็š„ JWT ไปค็‰Œๆฅๆ‰ง่กŒ่ฟ™ไบ›ๆ“ไฝœ๏ผˆๅผ€่ฝฆใ€็ผ–่พ‘ๆ–‡็ซ ๏ผ‰ใ€‚ -ๅŒ็†๏ผŒJWT ๅฏไปฅ็”จไบŽๆ›ดๅคๆ‚็š„ๅœบๆ™ฏใ€‚ +ๅŸบไบŽ่ฟ™ไบ›ๆƒณๆณ•๏ผŒJWT ๅฏไปฅ็”จไบŽๆ›ดๅคๆ‚็š„ๅœบๆ™ฏใ€‚ -ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๅคšไธชๅฎžไฝ“็š„ ID ๅฏ่ƒฝๆ˜ฏ็›ธๅŒ็š„๏ผŒไปฅ ID `foo` ไธบไพ‹๏ผŒ็”จๆˆท็š„ ID ๆ˜ฏ `foo`๏ผŒ่ฝฆ็š„ ID ๆ˜ฏ `foo`๏ผŒๅšๅฎข็š„ ID ไนŸๆ˜ฏ `foo`ใ€‚ +ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๅคšไธชๅฎžไฝ“ๅฏ่ƒฝไผšๆœ‰็›ธๅŒ็š„ ID๏ผŒๆฏ”ๅฆ‚้ƒฝๅซ `foo`๏ผˆ็”จๆˆท `foo`ใ€่ฝฆ `foo`ใ€ๅšๅฎขๆ–‡็ซ  `foo`๏ผ‰ใ€‚ -ไธบไบ†้ฟๅ… ID ๅ†ฒ็ช๏ผŒๅœจ็ป™็”จๆˆทๅˆ›ๅปบ JWT ไปค็‰Œๆ—ถ๏ผŒๅฏไปฅไธบ `sub` ้”ฎ็š„ๅ€ผๅŠ ไธŠๅ‰็ผ€๏ผŒไพ‹ๅฆ‚ `username:`ใ€‚ๅ› ๆญค๏ผŒๅœจๆœฌไพ‹ไธญ๏ผŒ`sub` ็š„ๅ€ผๅฏไปฅๆ˜ฏ๏ผš`username:johndoe`ใ€‚ +ๅ› ๆญค๏ผŒไธบไบ†้ฟๅ… ID ๅ†ฒ็ช๏ผŒๅœจไธบ็”จๆˆทๅˆ›ๅปบ JWT ไปค็‰Œๆ—ถ๏ผŒไฝ ๅฏไปฅ็ป™ `sub` ้”ฎ็š„ๅ€ผๅŠ ไธ€ไธชๅ‰็ผ€๏ผŒไพ‹ๅฆ‚ `username:`ใ€‚ๆ‰€ไปฅๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒ`sub` ็š„ๅ€ผๅฏไปฅๆ˜ฏ๏ผš`username:johndoe`ใ€‚ -ๆณจๆ„๏ผŒๅˆ’้‡็‚น๏ผŒ`sub` ้”ฎๅœจๆ•ดไธชๅบ”็”จไธญๅบ”่ฏฅๅชๆœ‰ไธ€ไธชๅ”ฏไธ€็š„ๆ ‡่ฏ†็ฌฆ๏ผŒ่€Œไธ”ๅบ”่ฏฅๆ˜ฏๅญ—็ฌฆไธฒใ€‚ +้œ€่ฆ็‰ข่ฎฐ็š„ไธ€็‚นๆ˜ฏ๏ผŒ`sub` ้”ฎๅœจๆ•ดไธชๅบ”็”จไธญๅบ”่ฏฅๆ˜ฏไธ€ไธชๅ”ฏไธ€ๆ ‡่ฏ†็ฌฆ๏ผŒๅนถไธ”ๅฎƒๅบ”่ฏฅๆ˜ฏๅญ—็ฌฆไธฒใ€‚ -## ๆฃ€ๆŸฅ +## ๆฃ€ๆŸฅ { #check-it } -่ฟ่กŒๆœๅŠกๅ™จๅนถ่ฎฟ้—ฎๆ–‡ๆกฃ๏ผš http://127.0.0.1:8000/docsใ€‚ +่ฟ่กŒๆœๅŠกๅ™จๅนถๆ‰“ๅผ€ๆ–‡ๆกฃ๏ผšhttp://127.0.0.1:8000/docsใ€‚ -ๅฏไปฅ็œ‹ๅˆฐๅฆ‚ไธ‹็”จๆˆท็•Œ้ข๏ผš +ไฝ ไผš็œ‹ๅˆฐ่ฟ™ๆ ท็š„็”จๆˆท็•Œ้ข๏ผš - + -็”จไธŽไธŠไธ€็ซ ๅŒๆ ท็š„ๆ–นๅผๅฎž็Žฐๅบ”็”จๆŽˆๆƒใ€‚ +ๅƒไน‹ๅ‰ไธ€ๆ ท่ฟ›่กŒๆŽˆๆƒใ€‚ -ไฝฟ็”จๅฆ‚ไธ‹ๅ‡ญ่ฏ๏ผš +ไฝฟ็”จไปฅไธ‹ๅ‡ญ่ฏ๏ผš -็”จๆˆทๅ: `johndoe` ๅฏ†็ : `secret` +็”จๆˆทๅ: `johndoe` +ๅฏ†็ : `secret` /// check | ๆฃ€ๆŸฅ -ๆณจๆ„๏ผŒไปฃ็ ไธญๆฒกๆœ‰ๆ˜Žๆ–‡ๅฏ†็ **`secret`**๏ผŒๅชไฟๅญ˜ไบ†ๅฎƒ็š„ๅ“ˆๅธŒๅ€ผใ€‚ +ๆณจๆ„๏ผŒไปฃ็ ไธญ็š„ไปปไฝ•ๅœฐๆ–น้ƒฝๆฒกๆœ‰ๆ˜Žๆ–‡ๅฏ†็  โ€œ`secret`โ€๏ผŒๆˆ‘ไปฌๅชๆœ‰ๅฎƒ็š„ๅ“ˆๅธŒ็‰ˆๆœฌใ€‚ /// - + -่ฐƒ็”จ `/users/me/` ็ซฏ็‚น๏ผŒๆ”ถๅˆฐไธ‹้ข็š„ๅ“ๅบ”๏ผš +่ฐƒ็”จ `/users/me/` ็ซฏ็‚น๏ผŒไฝ ๅฐ†ๅพ—ๅˆฐๅฆ‚ไธ‹ๅ“ๅบ”๏ผš ```JSON { @@ -225,46 +228,46 @@ JWT ่ง„่Œƒ่ฟ˜ๅŒ…ๆ‹ฌ `sub` ้”ฎ๏ผŒๅ€ผๆ˜ฏไปค็‰Œ็š„ไธป้ข˜ใ€‚ } ``` - + -ๆ‰“ๅผ€ๆต่งˆๅ™จ็š„ๅผ€ๅ‘่€…ๅทฅๅ…ท๏ผŒๆŸฅ็œ‹ๆ•ฐๆฎๆ˜ฏๆ€Žไนˆๅ‘้€็š„๏ผŒ่€Œไธ”ๆ•ฐๆฎ้‡ŒๅชๅŒ…ๅซไบ†ไปค็‰Œ๏ผŒๅชๆœ‰้ชŒ่ฏ็”จๆˆท็š„็ฌฌไธ€ไธช่ฏทๆฑ‚ๆ‰ๅ‘้€ๅฏ†็ ๏ผŒๅนถ่Žทๅ–่ฎฟ้—ฎไปค็‰Œ๏ผŒไฝ†ไน‹ๅŽไธไผšๅ†ๅ‘้€ๅฏ†็ ๏ผš +ๅฆ‚ๆžœไฝ ๆ‰“ๅผ€ๅผ€ๅ‘่€…ๅทฅๅ…ท๏ผŒไฝ ไผš็œ‹ๅˆฐๅ‘้€็š„ๆ•ฐๆฎๅชๅŒ…ๅซไปค็‰Œใ€‚ๅฏ†็ ๅชไผšๅœจ็ฌฌไธ€ไธช่ฏทๆฑ‚ไธญ็”จไบŽ่ฎค่ฏ็”จๆˆทๅนถ่Žทๅ–่ฎฟ้—ฎไปค็‰Œ๏ผŒไน‹ๅŽๅฐฑไธไผšๅ†ๅ‘้€ๅฏ†็ ไบ†๏ผš - + -/// note | ็ฌ”่ฎฐ +/// note | ๆณจๆ„ -ๆณจๆ„๏ผŒ่ฏทๆฑ‚ไธญ `Authorization` ๅ“ๅบ”ๅคด็š„ๅ€ผไปฅ `Bearer` ๅผ€ๅคดใ€‚ +ๆณจๆ„ `Authorization` ่ฏทๆฑ‚ๅคด๏ผŒๅ…ถๅ€ผไปฅ `Bearer ` ๅผ€ๅคดใ€‚ /// -## `scopes` ้ซ˜็บง็”จๆณ• +## ไฝฟ็”จ `scopes` ็š„้ซ˜็บง็”จๆณ• { #advanced-usage-with-scopes } -OAuth2 ๆ”ฏๆŒ**`scopes`**๏ผˆไฝœ็”จๅŸŸ๏ผ‰ใ€‚ +OAuth2 ๆ”ฏๆŒ โ€œscopesโ€๏ผˆไฝœ็”จๅŸŸ๏ผ‰ใ€‚ -**`scopes`**ไธบ JWT ไปค็‰ŒๆทปๅŠ ๆŒ‡ๅฎšๆƒ้™ใ€‚ +ไฝ ๅฏไปฅ็”จๅฎƒไปฌไธบ JWT ไปค็‰ŒๆทปๅŠ ไธ€็ป„็‰นๅฎš็š„ๆƒ้™ใ€‚ -่ฎฉๆŒๆœ‰ไปค็‰Œ็š„็”จๆˆทๆˆ–็ฌฌไธ‰ๆ–นๅœจๆŒ‡ๅฎš้™ๅˆถๆกไปถไธ‹ไธŽ API ไบคไบ’ใ€‚ +็„ถๅŽไฝ ๅฏไปฅๆŠŠ่ฟ™ไธชไปค็‰Œ็›ดๆŽฅไบค็ป™็”จๆˆทๆˆ–็ฌฌไธ‰ๆ–น๏ผŒๅœจไธ€็ป„้™ๅˆถๆกไปถไธ‹ไธŽ API ไบคไบ’ใ€‚ -**้ซ˜็บง็”จๆˆทๆŒ‡ๅ—**ไธญๅฐ†ไป‹็ปๅฆ‚ไฝ•ไฝฟ็”จ `scopes`๏ผŒๅŠๅฆ‚ไฝ•ๆŠŠ `scopes` ้›†ๆˆ่‡ณ **FastAPI**ใ€‚ +ๅœจ**้ซ˜็บง็”จๆˆทๆŒ‡ๅ—**ไธญไฝ ๅฐ†ๅญฆไน ๅฆ‚ไฝ•ไฝฟ็”จๅฎƒไปฌ๏ผŒไปฅๅŠๅฎƒไปฌๅฆ‚ไฝ•้›†ๆˆ่ฟ› **FastAPI**ใ€‚ -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } -่‡ณๆญค๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ OAuth2 ๅ’Œ JWT ็ญ‰ๆ ‡ๅ‡†้…็ฝฎๅฎ‰ๅ…จ็š„ **FastAPI** ๅบ”็”จใ€‚ +้€š่ฟ‡็›ฎๅ‰ๆ‰€ๅญฆๅ†…ๅฎน๏ผŒไฝ ๅฏไปฅไฝฟ็”จ OAuth2 ๅ’Œ JWT ็ญ‰ๆ ‡ๅ‡†ๆฅๆญๅปบไธ€ไธชๅฎ‰ๅ…จ็š„ **FastAPI** ๅบ”็”จใ€‚ -ๅ‡ ไนŽๅœจๆ‰€ๆœ‰ๆก†ๆžถไธญ๏ผŒๅค„็†ๅฎ‰ๅ…จ้—ฎ้ข˜ๅพˆๅฟซ้ƒฝไผšๅ˜ๅพ—้žๅธธๅคๆ‚ใ€‚ +ๅœจๅ‡ ไนŽไปปไฝ•ๆก†ๆžถไธญ๏ผŒๅค„็†ๅฎ‰ๅ…จ้—ฎ้ข˜้ƒฝไผšๅพˆๅฟซๅ˜ๅพ—็›ธๅฝ“ๅคๆ‚ใ€‚ -ๆœ‰ไบ›ๅŒ…ไธบไบ†็ฎ€ๅŒ–ๅฎ‰ๅ…จๆต๏ผŒไธๅพ—ไธๅœจๆ•ฐๆฎๆจกๅž‹ใ€ๆ•ฐๆฎๅบ“ๅ’ŒๅŠŸ่ƒฝไธŠๅšๅ‡บๅฆฅๅใ€‚่€Œๆœ‰ไบ›่ฟ‡ไบŽ็ฎ€ๅŒ–็š„่ฝฏไปถๅŒ…ๅ…ถๅฎžๅญ˜ๅœจไบ†ๅฎ‰ๅ…จ้šๆ‚ฃใ€‚ +่ฎธๅคšๆŠŠๅฎ‰ๅ…จๆต็จ‹ๅคงๅน…็ฎ€ๅŒ–็š„ๅŒ…๏ผŒๅพ€ๅพ€่ฆๅœจๆ•ฐๆฎๆจกๅž‹ใ€ๆ•ฐๆฎๅบ“ๅ’Œๅฏ็”จ็‰นๆ€งไธŠๅšๅ‡บๅคง้‡ๅฆฅๅใ€‚่€Œๆœ‰ไบ›่ฟ‡ๅบฆ็ฎ€ๅŒ–็š„ๅŒ…ๅฎž้™…ไธŠๅœจๅบ•ๅฑ‚ๅญ˜ๅœจๅฎ‰ๅ…จ้šๆ‚ฃใ€‚ --- -**FastAPI** ไธๅ‘ไปปไฝ•ๆ•ฐๆฎๅบ“ใ€ๆ•ฐๆฎๆจกๅž‹ๆˆ–ๅทฅๅ…ทๅšๅฆฅๅใ€‚ +**FastAPI** ไธไผšๅœจไปปไฝ•ๆ•ฐๆฎๅบ“ใ€ๆ•ฐๆฎๆจกๅž‹ๆˆ–ๅทฅๅ…ทไธŠๅšๅฆฅๅใ€‚ -ๅผ€ๅ‘่€…ๅฏไปฅ็ตๆดป้€‰ๆ‹ฉๆœ€้€‚ๅˆ้กน็›ฎ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ๅฎƒ็ป™ไบˆไฝ ๅฎŒๅ…จ็š„็ตๆดปๆ€ง๏ผŒ้€‰ๆ‹ฉๆœ€้€‚ๅˆไฝ ้กน็›ฎ็š„ๆ–นๆกˆใ€‚ -่ฟ˜ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `passlib` ๅ’Œ `PyJWT` ็ญ‰็ปดๆŠค่‰ฏๅฅฝใ€ไฝฟ็”จๅนฟๆณ›็š„ๅŒ…๏ผŒ่ฟ™ๆ˜ฏๅ› ไธบ **FastAPI** ไธ้œ€่ฆไปปไฝ•ๅคๆ‚ๆœบๅˆถ๏ผŒๅฐฑ่ƒฝ้›†ๆˆๅค–้ƒจ็š„ๅŒ…ใ€‚ +่€Œไธ”ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ่ฎธๅคš็ปดๆŠค่‰ฏๅฅฝใ€ๅนฟๆณ›ไฝฟ็”จ็š„ๅŒ…๏ผŒๆฏ”ๅฆ‚ `pwdlib` ๅ’Œ `PyJWT`๏ผŒๅ› ไธบ **FastAPI** ไธ้œ€่ฆๅคๆ‚ๆœบๅˆถๆฅ้›†ๆˆๅค–้ƒจๅŒ…ใ€‚ -่€Œไธ”๏ผŒ**FastAPI** ่ฟ˜ๆไพ›ไบ†ไธ€ไบ›ๅทฅๅ…ท๏ผŒๅœจไธๅฝฑๅ“็ตๆดปใ€็จณๅฎšๅ’Œๅฎ‰ๅ…จ็š„ๅ‰ๆไธ‹๏ผŒๅฐฝๅฏ่ƒฝๅœฐ็ฎ€ๅŒ–ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ๅŒๆ—ถๅฎƒไนŸไธบไฝ ๆไพ›ๅฐฝๅฏ่ƒฝ็ฎ€ๅŒ–ๆต็จ‹็š„ๅทฅๅ…ท๏ผŒ่€Œไธ็‰บ็‰ฒ็ตๆดปๆ€งใ€ๅฅๅฃฎๆ€งๆˆ–ๅฎ‰ๅ…จๆ€งใ€‚ -**FastAPI** ่ฟ˜ๆ”ฏๆŒไปฅ็›ธๅฏน็ฎ€ๅ•็š„ๆ–นๅผ๏ผŒไฝฟ็”จ OAuth2 ็ญ‰ๅฎ‰ๅ…จใ€ๆ ‡ๅ‡†็š„ๅ่ฎฎใ€‚ +ไฝ ๅฏไปฅไปฅ็›ธๅฏน็ฎ€ๅ•็š„ๆ–นๅผไฝฟ็”จๅ’Œๅฎž็Žฐๅƒ OAuth2 ่ฟ™ๆ ท็š„ๅฎ‰ๅ…จใ€ๆ ‡ๅ‡†ๅ่ฎฎใ€‚ -**้ซ˜็บง็”จๆˆทๆŒ‡ๅ—**ไธญ่ฏฆ็ป†ไป‹็ปไบ† OAuth2**`scopes`**็š„ๅ†…ๅฎน๏ผŒ้ตๅพชๅŒๆ ท็š„ๆ ‡ๅ‡†๏ผŒๅฎž็Žฐๆ›ด็ฒพๅฏ†็š„ๆƒ้™็ณป็ปŸใ€‚OAuth2 ็š„ไฝœ็”จๅŸŸๆ˜ฏ่„ธไนฆใ€่ฐทๆญŒใ€GitHubใ€ๅพฎ่ฝฏใ€ๆŽจ็‰น็ญ‰็ฌฌไธ‰ๆ–น่บซไปฝ้ชŒ่ฏๅบ”็”จไฝฟ็”จ็š„ๆœบๅˆถ๏ผŒ่ฎฉ็”จๆˆทๆŽˆๆƒ็ฌฌไธ‰ๆ–นๅบ”็”จไธŽ API ไบคไบ’ใ€‚ +ๅœจ**้ซ˜็บง็”จๆˆทๆŒ‡ๅ—**ไธญ๏ผŒไฝ ๅฏไปฅ่ฟ›ไธ€ๆญฅไบ†่งฃๅฆ‚ไฝ•ไฝฟ็”จ OAuth2 ็š„ โ€œscopesโ€๏ผŒไปฅ้ตๅพช็›ธๅŒๆ ‡ๅ‡†ๅฎž็Žฐๆ›ด็ป†็ฒ’ๅบฆ็š„ๆƒ้™็ณป็ปŸใ€‚ๅธฆไฝœ็”จๅŸŸ็š„ OAuth2 ๆ˜ฏ่ฎธๅคšๅคงๅž‹่บซไปฝ่ฎค่ฏๆไพ›ๅ•†๏ผˆๅฆ‚ Facebookใ€Googleใ€GitHubใ€Microsoftใ€X๏ผˆTwitter๏ผ‰็ญ‰๏ผ‰็”จๆฅๆŽˆๆƒ็ฌฌไธ‰ๆ–นๅบ”็”จไปฃ่กจๅ…ถ็”จๆˆทไธŽๅ…ถ API ไบคไบ’็š„ๆœบๅˆถใ€‚ diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md index f70678df8f..3037a983b3 100644 --- a/docs/zh/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh/docs/tutorial/security/simple-oauth2.md @@ -1,8 +1,8 @@ -# OAuth2 ๅฎž็Žฐ็ฎ€ๅ•็š„ Password ๅ’Œ Bearer ้ชŒ่ฏ +# OAuth2 ๅฎž็Žฐ็ฎ€ๅ•็š„ Password ๅ’Œ Bearer ้ชŒ่ฏ { #simple-oauth2-with-password-and-bearer } ๆœฌ็ซ ๆทปๅŠ ไธŠไธ€็ซ ็คบไพ‹ไธญๆฌ ็ผบ็š„้ƒจๅˆ†๏ผŒๅฎž็ŽฐๅฎŒๆ•ด็š„ๅฎ‰ๅ…จๆตใ€‚ -## ่Žทๅ– `username` ๅ’Œ `password` +## ่Žทๅ– `username` ๅ’Œ `password` { #get-the-username-and-password } ้ฆ–ๅ…ˆ๏ผŒไฝฟ็”จ **FastAPI** ๅฎ‰ๅ…จๅทฅๅ…ท่Žทๅ– `username` ๅ’Œ `password`ใ€‚ @@ -18,7 +18,7 @@ OAuth2 ่ง„่Œƒ่ฆๆฑ‚ไฝฟ็”จ**ๅฏ†็ ๆต**ๆ—ถ๏ผŒๅฎขๆˆท็ซฏๆˆ–็”จๆˆทๅฟ…้กปไปฅ่กจๅ•ๆ•ฐ ่ฏฅ่ง„่Œƒ่ฆๆฑ‚ๅฟ…้กปไปฅ่กจๅ•ๆ•ฐๆฎๅฝขๅผๅ‘้€ `username` ๅ’Œ `password`๏ผŒๅ› ๆญค๏ผŒไธ่ƒฝไฝฟ็”จ JSON ๅฏน่ฑกใ€‚ -### `Scope`๏ผˆไฝœ็”จๅŸŸ๏ผ‰ +### `scope` { #scope } OAuth2 ่ฟ˜ๆ”ฏๆŒๅฎขๆˆท็ซฏๅ‘้€**`scope`**่กจๅ•ๅญ—ๆฎตใ€‚ @@ -32,7 +32,7 @@ OAuth2 ่ฟ˜ๆ”ฏๆŒๅฎขๆˆท็ซฏๅ‘้€**`scope`**่กจๅ•ๅญ—ๆฎตใ€‚ * ่„ธไนฆๅ’Œ Instagram ไฝฟ็”จ `instagram_basic` * ่ฐทๆญŒไฝฟ็”จ `https://www.googleapis.com/auth/drive` -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ @@ -44,15 +44,15 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ /// -## ่Žทๅ– `username` ๅ’Œ `password` ็š„ไปฃ็  +## ่Žทๅ– `username` ๅ’Œ `password` ็š„ไปฃ็  { #code-to-get-the-username-and-password } ๆŽฅไธ‹ๆฅ๏ผŒไฝฟ็”จ **FastAPI** ๅทฅๅ…ท่Žทๅ–็”จๆˆทๅไธŽๅฏ†็ ใ€‚ -### `OAuth2PasswordRequestForm` +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } ้ฆ–ๅ…ˆ๏ผŒๅฏผๅ…ฅ `OAuth2PasswordRequestForm`๏ผŒ็„ถๅŽ๏ผŒๅœจ `/token` *่ทฏๅพ„ๆ“ไฝœ* ไธญ๏ผŒ็”จ `Depends` ๆŠŠ่ฏฅ็ฑปไฝœไธบไพ่ต–้กนใ€‚ -{* ../../docs_src/security/tutorial003.py hl[4,76] *} +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} `OAuth2PasswordRequestForm` ๆ˜ฏ็”จไปฅไธ‹ๅ‡ ้กนๅ†…ๅฎนๅฃฐๆ˜Ž่กจๅ•่ฏทๆฑ‚ไฝ“็š„็ฑปไพ่ต–้กน๏ผš @@ -72,7 +72,7 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ * ๅฏ้€‰็š„ `client_id`๏ผˆๆœฌไพ‹ๆœชไฝฟ็”จ๏ผ‰ * ๅฏ้€‰็š„ `client_secret`๏ผˆๆœฌไพ‹ๆœชไฝฟ็”จ๏ผ‰ -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ `OAuth2PasswordRequestForm` ไธŽ `OAuth2PasswordBearer` ไธ€ๆ ท๏ผŒ้ƒฝไธๆ˜ฏ FastAPI ็š„็‰นๆฎŠ็ฑปใ€‚ @@ -84,7 +84,7 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ /// -### ไฝฟ็”จ่กจๅ•ๆ•ฐๆฎ +### ไฝฟ็”จ่กจๅ•ๆ•ฐๆฎ { #use-the-form-data } /// tip | ๆ็คบ @@ -100,9 +100,9 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ ๆœฌไพ‹ไฝฟ็”จ `HTTPException` ๅผ‚ๅธธๆ˜พ็คบๆญค้”™่ฏฏ๏ผš -{* ../../docs_src/security/tutorial003.py hl[3,77:79] *} +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} -### ๆ ก้ชŒๅฏ†็  +### ๆ ก้ชŒๅฏ†็  { #check-the-password } ่‡ณๆญค๏ผŒๆˆ‘ไปฌๅทฒ็ปไปŽๆ•ฐๆฎๅบ“ไธญ่Žทๅ–ไบ†็”จๆˆทๆ•ฐๆฎ๏ผŒไฝ†ๅฐšๆœชๆ ก้ชŒๅฏ†็ ใ€‚ @@ -112,7 +112,7 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ ๅฆ‚ๆžœๅฏ†็ ไธๅŒน้…๏ผŒๅˆ™่ฟ”ๅ›žไธŽไธŠ้ข็›ธๅŒ็š„้”™่ฏฏใ€‚ -#### ๅฏ†็ ๅ“ˆๅธŒ +#### ๅฏ†็ ๅ“ˆๅธŒ { #password-hashing } **ๅ“ˆๅธŒ**ๆ˜ฏๆŒ‡๏ผŒๅฐ†ๆŒ‡ๅฎšๅ†…ๅฎน๏ผˆๆœฌไพ‹ไธญไธบๅฏ†็ ๏ผ‰่ฝฌๆขไธบๅฝขไผผไนฑ็ ็š„ๅญ—่Š‚ๅบๅˆ—๏ผˆๅ…ถๅฎžๅฐฑๆ˜ฏๅญ—็ฌฆไธฒ๏ผ‰ใ€‚ @@ -120,15 +120,15 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ ไฝ†่ฟ™ไธชไนฑ็ ๆ— ๆณ•่ฝฌๆขๅ›žไผ ๅ…ฅ็š„ๅฏ†็ ใ€‚ -##### ไธบไป€ไนˆไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒ +##### ไธบไป€ไนˆไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒ { #why-use-password-hashing } ๅŽŸๅ› ๅพˆ็ฎ€ๅ•๏ผŒๅ‡ๅฆ‚ๆ•ฐๆฎๅบ“่ขซ็›—๏ผŒ็ชƒ่ดผๆ— ๆณ•่Žทๅ–็”จๆˆท็š„ๆ˜Žๆ–‡ๅฏ†็ ๏ผŒๅพ—ๅˆฐ็š„ๅชๆ˜ฏๅ“ˆๅธŒๅ€ผใ€‚ ่ฟ™ๆ ทไธ€ๆฅ๏ผŒ็ชƒ่ดผๅฐฑๆ— ๆณ•ๅœจๅ…ถๅฎƒๅบ”็”จไธญไฝฟ็”จ็ชƒๅ–็š„ๅฏ†็ ๏ผŒ่ฆ็Ÿฅ้“๏ผŒๅพˆๅคš็”จๆˆทๅœจๆ‰€ๆœ‰็ณป็ปŸไธญ้ƒฝไฝฟ็”จ็›ธๅŒ็š„ๅฏ†็ ๏ผŒ้ฃŽ้™ฉ่ถ…ๅคงใ€‚ -{* ../../docs_src/security/tutorial003.py hl[80:83] *} +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} -#### ๅ…ณไบŽ `**user_dict` +#### ๅ…ณไบŽ `**user_dict` { #about-user-dict } `UserInDB(**user_dict)` ๆ˜ฏๆŒ‡๏ผš @@ -144,13 +144,13 @@ UserInDB( ) ``` -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ -`user_dict` ็š„่ฏดๆ˜Ž๏ผŒ่ฏฆ่ง[**ๆ›ดๅคšๆจกๅž‹**ไธ€็ซ ](../extra-models.md#user_indict){.internal-link target=_blank}ใ€‚ +`user_dict` ็š„่ฏดๆ˜Ž๏ผŒ่ฏฆ่ง[**ๆ›ดๅคšๆจกๅž‹**ไธ€็ซ ](../extra-models.md#about-user-in-dict){.internal-link target=_blank}ใ€‚ /// -## ่ฟ”ๅ›ž Token +## ่ฟ”ๅ›ž Token { #return-the-token } `token` ็ซฏ็‚น็š„ๅ“ๅบ”ๅฟ…้กปๆ˜ฏ JSON ๅฏน่ฑกใ€‚ @@ -162,13 +162,13 @@ UserInDB( /// tip | ๆ็คบ -ไธ‹ไธ€็ซ ไป‹็ปไฝฟ็”จๅ“ˆๅธŒๅฏ†็ ๅ’Œ JWT Token ็š„็œŸๆญฃๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ไธ‹ไธ€็ซ ไป‹็ปไฝฟ็”จๅ“ˆๅธŒๅฏ†็ ๅ’Œ JWT Token ็š„็œŸๆญฃๅฎ‰ๅ…จๆœบๅˆถใ€‚ ไฝ†็Žฐๅœจ๏ผŒไป…ๅ…ณๆณจๆ‰€้œ€็š„็‰นๅฎš็ป†่Š‚ใ€‚ /// -{* ../../docs_src/security/tutorial003.py hl[85] *} +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} /// tip | ๆ็คบ @@ -182,7 +182,7 @@ UserInDB( /// -## ๆ›ดๆ–ฐไพ่ต–้กน +## ๆ›ดๆ–ฐไพ่ต–้กน { #update-the-dependencies } ๆŽฅไธ‹ๆฅ๏ผŒๆ›ดๆ–ฐไพ่ต–้กนใ€‚ @@ -194,9 +194,9 @@ UserInDB( ๅ› ๆญค๏ผŒๅœจ็ซฏ็‚นไธญ๏ผŒๅชๆœ‰ๅฝ“็”จๆˆทๅญ˜ๅœจใ€้€š่ฟ‡่บซไปฝ้ชŒ่ฏใ€ไธ”็Šถๆ€ไธบๆฟ€ๆดปๆ—ถ๏ผŒๆ‰่ƒฝ่Žทๅพ—่ฏฅ็”จๆˆท๏ผš -{* ../../docs_src/security/tutorial003.py hl[58:67,69:72,90] *} +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ ๆญคๅค„่ฟ”ๅ›žๅ€ผไธบ `Bearer` ็š„ๅ“ๅบ”ๅคด `WWW-Authenticate` ไนŸๆ˜ฏ่ง„่Œƒ็š„ไธ€้ƒจๅˆ†ใ€‚ @@ -210,15 +210,15 @@ UserInDB( ่ฏดไธๅฎšไป€ไนˆๆ—ถๅ€™๏ผŒๅฐฑๆœ‰ๅทฅๅ…ท็”จๅพ—ไธŠๅฎƒ๏ผŒ่€Œไธ”๏ผŒๅผ€ๅ‘่€…ๆˆ–็”จๆˆทไนŸๅฏ่ƒฝ็”จๅพ—ไธŠใ€‚ -่ฟ™ๅฐฑๆ˜ฏ้ตๅพชๆ ‡ๅ‡†็š„ๅฅฝๅค„โ€ฆโ€ฆ +่ฟ™ๅฐฑๆ˜ฏ้ตๅพชๆ ‡ๅ‡†็š„ๅฅฝๅค„... /// -## ๅฎž้™…ๆ•ˆๆžœ +## ๅฎž้™…ๆ•ˆๆžœ { #see-it-in-action } ๆ‰“ๅผ€ API ๆ–‡ๆกฃ๏ผšhttp://127.0.0.1:8000/docsใ€‚ -### ่บซไปฝ้ชŒ่ฏ +### ่บซไปฝ้ชŒ่ฏ { #authenticate } ็‚นๅ‡ป**Authorize**ๆŒ‰้’ฎใ€‚ @@ -228,13 +228,13 @@ UserInDB( ๅฏ†็ ๏ผš`secret` - + ้€š่ฟ‡่บซไปฝ้ชŒ่ฏๅŽ๏ผŒๆ˜พ็คบไธ‹ๅ›พๆ‰€็คบ็š„ๅ†…ๅฎน๏ผš - + -### ่Žทๅ–ๅฝ“ๅ‰็”จๆˆทๆ•ฐๆฎ +### ่Žทๅ–ๅฝ“ๅ‰็”จๆˆทๆ•ฐๆฎ { #get-your-own-user-data } ไฝฟ็”จ `/users/me` ่ทฏๅพ„็š„ `GET` ๆ“ไฝœใ€‚ @@ -250,7 +250,7 @@ UserInDB( } ``` - + ็‚นๅ‡ปๅฐ้”ๅ›พๆ ‡๏ผŒๆณจ้”€ๅŽ๏ผŒๅ†ๆ‰ง่กŒๅŒๆ ท็š„ๆ“ไฝœ๏ผŒๅˆ™ไผšๅพ—ๅˆฐ HTTP 401 ้”™่ฏฏ๏ผš @@ -260,7 +260,7 @@ UserInDB( } ``` -### ๆœชๆฟ€ๆดป็”จๆˆท +### ๆœชๆฟ€ๆดป็”จๆˆท { #inactive-user } ๆต‹่ฏ•ๆœชๆฟ€ๆดป็”จๆˆท๏ผŒ่พ“ๅ…ฅไปฅไธ‹ไฟกๆฏ๏ผŒ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏ๏ผš @@ -278,7 +278,7 @@ UserInDB( } ``` -## ๅฐ็ป“ +## ๅฐ็ป“ { #recap } ไฝฟ็”จๆœฌ็ซ ็š„ๅทฅๅ…ทๅฎž็ŽฐๅŸบไบŽ `username` ๅ’Œ `password` ็š„ๅฎŒๆ•ด API ๅฎ‰ๅ…จ็ณป็ปŸใ€‚ @@ -286,4 +286,4 @@ UserInDB( ๅ”ฏไธ€ๆฌ ็ผบ็š„ๆ˜ฏ๏ผŒๅฎƒไป็„ถไธๆ˜ฏ็œŸ็š„**ๅฎ‰ๅ…จ**ใ€‚ -ไธ‹ไธ€็ซ ๏ผŒไป‹็ปไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒๆ”ฏๆŒๅบ“ไธŽ JWT ไปค็‰Œๅฎž็Žฐ็œŸๆญฃ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ไธ‹ไธ€็ซ ๏ผŒไป‹็ปไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒๆ”ฏๆŒๅบ“ไธŽ JWT ไปค็‰Œๅฎž็Žฐ็œŸๆญฃ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md index fbdf3be6cc..944e960a76 100644 --- a/docs/zh/docs/tutorial/sql-databases.md +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -1,40 +1,40 @@ -# SQL๏ผˆๅ…ณ็ณปๅž‹๏ผ‰ๆ•ฐๆฎๅบ“ +# SQL๏ผˆๅ…ณ็ณปๅž‹๏ผ‰ๆ•ฐๆฎๅบ“ { #sql-relational-databases } -**FastAPI** ๅนถไธ่ฆๆฑ‚ๆ‚จไฝฟ็”จ SQL๏ผˆๅ…ณ็ณปๅž‹๏ผ‰ๆ•ฐๆฎๅบ“ใ€‚ๆ‚จๅฏไปฅไฝฟ็”จ**ไปปไฝ•**ๆƒณ็”จ็š„ๆ•ฐๆฎๅบ“ใ€‚ +**FastAPI** ๅนถไธ่ฆๆฑ‚ไฝ ไฝฟ็”จ SQL๏ผˆๅ…ณ็ณปๅž‹๏ผ‰ๆ•ฐๆฎๅบ“ใ€‚ไฝ ๅฏไปฅไฝฟ็”จไฝ ๆƒณ็”จ็š„**ไปปไฝ•ๆ•ฐๆฎๅบ“**ใ€‚ ่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌๆฅ็œ‹ไธ€ไธชไฝฟ็”จ SQLModel ็š„็คบไพ‹ใ€‚ -**SQLModel** ๆ˜ฏๅŸบไบŽ SQLAlchemy ๅ’Œ Pydantic ๆž„ๅปบ็š„ใ€‚ๅฎƒ็”ฑ **FastAPI** ็š„ๅŒไธ€ไฝœ่€…ๅˆถไฝœ๏ผŒๆ—จๅœจๅฎŒ็พŽๅŒน้…้œ€่ฆไฝฟ็”จ **SQL ๆ•ฐๆฎๅบ“**็š„ FastAPI ๅบ”็”จ็จ‹ๅบใ€‚ +**SQLModel** ๅŸบไบŽ SQLAlchemy ๅ’Œ Pydantic ๆž„ๅปบใ€‚ๅฎƒ็”ฑ **FastAPI** ็š„ๅŒไธ€ไฝœ่€…ๅˆถไฝœ๏ผŒๆ—จๅœจๅฎŒ็พŽๅŒน้…้œ€่ฆไฝฟ็”จ**SQL ๆ•ฐๆฎๅบ“**็š„ FastAPI ๅบ”็”จ็จ‹ๅบใ€‚ -/// tip +/// tip | ๆ็คบ -ๆ‚จๅฏไปฅไฝฟ็”จไปปไฝ•ๅ…ถไป–ๆ‚จๆƒณ่ฆ็š„ SQL ๆˆ– NoSQL ๆ•ฐๆฎๅบ“๏ผˆๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹็งฐไธบ โ€œORMโ€๏ผ‰๏ผŒFastAPI ไธไผšๅผบ่ฟซๆ‚จไฝฟ็”จไปปไฝ•ไธœ่ฅฟใ€‚๐Ÿ˜Ž +ไฝ ๅฏไปฅไฝฟ็”จไปปๆ„ๅ…ถไป–ไฝ ๆƒณ่ฆ็š„ SQL ๆˆ– NoSQL ๆ•ฐๆฎๅบ“ๅบ“๏ผˆๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹็งฐไธบ "ORMs"๏ผ‰๏ผŒFastAPI ไธไผšๅผบ่ฟซไฝ ไฝฟ็”จไปปไฝ•ไธœ่ฅฟใ€‚๐Ÿ˜Ž /// -็”ฑไบŽ SQLModel ๅŸบไบŽ SQLAlchemy๏ผŒๅ› ๆญคๆ‚จๅฏไปฅ่ฝปๆพไฝฟ็”จไปปไฝ•็”ฑ SQLAlchemy **ๆ”ฏๆŒ็š„ๆ•ฐๆฎๅบ“**๏ผˆ่ฟ™ไนŸ่ฎฉๅฎƒไปฌ่ขซ SQLModel ๆ”ฏๆŒ๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš +็”ฑไบŽ SQLModel ๅŸบไบŽ SQLAlchemy๏ผŒๅ› ๆญคไฝ ๅฏไปฅ่ฝปๆพไฝฟ็”จไปปไฝ•็”ฑ SQLAlchemy **ๆ”ฏๆŒ็š„ๆ•ฐๆฎๅบ“**๏ผˆ่ฟ™ไนŸ่ฎฉๅฎƒไปฌ่ขซ SQLModel ๆ”ฏๆŒ๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš * PostgreSQL * MySQL * SQLite * Oracle -* Microsoft SQL Server ็ญ‰. +* Microsoft SQL Server ็ญ‰ -ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒๆˆ‘ไปฌๅฐ†ไฝฟ็”จ **SQLite**๏ผŒๅ› ไธบๅฎƒไฝฟ็”จๅ•ไธชๆ–‡ไปถ๏ผŒๅนถไธ” Python ๅฏนๅ…ถๆœ‰้›†ๆˆๆ”ฏๆŒใ€‚ๅ› ๆญค๏ผŒๆ‚จๅฏไปฅ็›ดๆŽฅๅคๅˆถ่ฟ™ไธชไพ‹ๅญๅนถ่ฟ่กŒใ€‚ +ๅœจ่ฟ™ไธช็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๅฐ†ไฝฟ็”จ **SQLite**๏ผŒๅ› ไธบๅฎƒไฝฟ็”จๅ•ไธชๆ–‡ไปถ๏ผŒๅนถไธ” Python ๅฏนๅ…ถๆœ‰้›†ๆˆๆ”ฏๆŒใ€‚ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅคๅˆถ่ฟ™ไธช็คบไพ‹ๅนถ่ฟ่กŒใ€‚ -ไน‹ๅŽ๏ผŒๅฏนไบŽๆ‚จ็š„็”Ÿไบงๅบ”็”จ็จ‹ๅบ๏ผŒๆ‚จๅฏ่ƒฝไผšๆƒณ่ฆไฝฟ็”จๅƒ PostgreSQL ่ฟ™ๆ ท็š„ๆ•ฐๆฎๅบ“ๆœๅŠกๅ™จใ€‚ +ไน‹ๅŽ๏ผŒๅฏนไบŽไฝ ็š„็”Ÿไบงๅบ”็”จ็จ‹ๅบ๏ผŒไฝ ๅฏ่ƒฝไผšๆƒณ่ฆไฝฟ็”จๅƒ **PostgreSQL** ่ฟ™ๆ ท็š„ๆ•ฐๆฎๅบ“ๆœๅŠกๅ™จใ€‚ -/// tip +/// tip | ๆ็คบ -ๆœ‰ไธ€ไธชไฝฟ็”จ **FastAPI** ๅ’Œ **PostgreSQL** ็š„ๅฎ˜ๆ–น็š„้กน็›ฎ็”Ÿๆˆๅ™จ๏ผŒๅ…ถไธญๅŒ…ๆ‹ฌไบ†ๅ‰็ซฏๅ’Œๆ›ดๅคšๅทฅๅ…ท๏ผš https://github.com/fastapi/full-stack-fastapi-template +ๆœ‰ไธ€ไธชไฝฟ็”จ **FastAPI** ๅ’Œ **PostgreSQL** ็š„ๅฎ˜ๆ–น้กน็›ฎ็”Ÿๆˆๅ™จ๏ผŒๅ…ถไธญๅŒ…ๆ‹ฌไบ†ๅ‰็ซฏๅ’Œๆ›ดๅคšๅทฅๅ…ท๏ผš https://github.com/fastapi/full-stack-fastapi-template /// -่ฟ™ๆ˜ฏไธ€ไธช้žๅธธ็ฎ€ๅ•ๅ’Œ็ฎ€็Ÿญ็š„ๆ•™็จ‹ใ€‚ๅฆ‚ๆžœๆ‚จๆƒณไบ†่งฃไธ€่ˆฌ็š„ๆ•ฐๆฎๅบ“ใ€SQL ๆˆ–ๆ›ด้ซ˜็บง็š„ๅŠŸ่ƒฝ๏ผŒ่ฏทๆŸฅ็œ‹ SQLModel ๆ–‡ๆกฃใ€‚ +่ฟ™ๆ˜ฏไธ€ไธช้žๅธธ็ฎ€ๅ•ๅ’Œ็ฎ€็Ÿญ็š„ๆ•™็จ‹ใ€‚ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃไธ€่ˆฌ็š„ๆ•ฐๆฎๅบ“ใ€SQL ๆˆ–ๆ›ด้ซ˜็บง็š„ๅŠŸ่ƒฝ๏ผŒ่ฏทๆŸฅ็œ‹ SQLModel ๆ–‡ๆกฃใ€‚ -## ๅฎ‰่ฃ… `SQLModel` +## ๅฎ‰่ฃ… `SQLModel` { #install-sqlmodel } -้ฆ–ๅ…ˆ๏ผŒ็กฎไฟๆ‚จๅˆ›ๅปบๅนถๆฟ€ๆดปไบ†[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ…ไบ† `sqlmodel` : +้ฆ–ๅ…ˆ๏ผŒ็กฎไฟไฝ ๅˆ›ๅปบๅนถๆฟ€ๆดปไบ†[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅฎ‰่ฃ… `sqlmodel`๏ผš
@@ -45,61 +45,61 @@ $ pip install sqlmodel
-## ๅˆ›ๅปบๅซๆœ‰ๅ•ไธ€ๆจกๅž‹็š„ๅบ”็”จ็จ‹ๅบ +## ๅˆ›ๅปบๅซๆœ‰ๅ•ไธ€ๆจกๅž‹็š„ๅบ”็”จ { #create-the-app-with-a-single-model } -ๆˆ‘ไปฌ้ฆ–ๅ…ˆๅˆ›ๅปบๅบ”็”จ็จ‹ๅบ็š„ๆœ€็ฎ€ๅ•็š„็ฌฌไธ€ไธช็‰ˆๆœฌ๏ผŒๅชๆœ‰ไธ€ไธช **SQLModel** ๆจกๅž‹ใ€‚ +ๆˆ‘ไปฌๅ…ˆๅˆ›ๅปบๅบ”็”จ็š„ๆœ€็ฎ€ๅ•็š„็ฌฌไธ€ไธช็‰ˆๆœฌ๏ผŒๅชๆœ‰ไธ€ไธช **SQLModel** ๆจกๅž‹ใ€‚ ็จๅŽๆˆ‘ไปฌๅฐ†้€š่ฟ‡ไธ‹้ข็š„**ๅคšไธชๆจกๅž‹**ๆ้ซ˜ๅ…ถๅฎ‰ๅ…จๆ€งๅ’ŒๅคšๅŠŸ่ƒฝๆ€งใ€‚๐Ÿค“ -### ๅˆ›ๅปบๆจกๅž‹ +### ๅˆ›ๅปบๆจกๅž‹ { #create-models } ๅฏผๅ…ฅ `SQLModel` ๅนถๅˆ›ๅปบไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผš {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` ็ฑปไธŽ Pydantic ๆจกๅž‹้žๅธธ็›ธไผผ๏ผˆๅฎž้™…ไธŠ๏ผŒไปŽๅบ•ๅฑ‚ๆฅ็œ‹๏ผŒๅฎƒ็กฎๅฎž*ๅฐฑๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹*๏ผ‰ใ€‚ +`Hero` ็ฑปไธŽ Pydantic ๆจกๅž‹้žๅธธ็›ธไผผ๏ผˆๅฎž้™…ไธŠ๏ผŒไปŽๅบ•ๅฑ‚ๆฅ็œ‹๏ผŒๅฎƒ็กฎๅฎžๅฐฑๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹๏ผ‰ใ€‚ ๆœ‰ไธ€ไบ›ๅŒบๅˆซ๏ผš -* `table=True` ไผšๅ‘Š่ฏ‰ SQLModel ่ฟ™ๆ˜ฏไธ€ไธช*่กจๆจกๅž‹*๏ผŒๅฎƒๅบ”่ฏฅ่กจ็คบ SQL ๆ•ฐๆฎๅบ“ไธญ็š„ไธ€ไธช*่กจ*๏ผŒ่€Œไธไป…ไป…ๆ˜ฏไธ€ไธช*ๆ•ฐๆฎๆจกๅž‹*๏ผˆๅฐฑๅƒๅ…ถไป–ๅธธ่ง„็š„ Pydantic ็ฑปไธ€ๆ ท๏ผ‰ใ€‚ +* `table=True` ไผšๅ‘Š่ฏ‰ SQLModel ่ฟ™ๆ˜ฏไธ€ไธช*่กจๆจกๅž‹*๏ผŒๅฎƒๅบ”่ฏฅ่กจ็คบ SQL ๆ•ฐๆฎๅบ“ไธญ็š„ไธ€ไธช**่กจ**๏ผŒ่€Œไธไป…ไป…ๆ˜ฏไธ€ไธช*ๆ•ฐๆฎๆจกๅž‹*๏ผˆๅฐฑๅƒๅ…ถไป–ๅธธ่ง„็š„ Pydantic ็ฑปไธ€ๆ ท๏ผ‰ใ€‚ -* `Field(primary_key=True)` ไผšๅ‘Š่ฏ‰ SQLModel `id` ๆ˜ฏ SQL ๆ•ฐๆฎๅบ“ไธญ็š„**ไธป้”ฎ**๏ผˆๆ‚จๅฏไปฅๅœจ SQLModel ๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽ SQL ไธป้”ฎ็š„ไฟกๆฏ๏ผ‰ใ€‚ +* `Field(primary_key=True)` ไผšๅ‘Š่ฏ‰ SQLModel `id` ๆ˜ฏ SQL ๆ•ฐๆฎๅบ“ไธญ็š„**ไธป้”ฎ**๏ผˆไฝ ๅฏไปฅๅœจ SQLModel ๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽ SQL ไธป้”ฎ็š„ไฟกๆฏ๏ผ‰ใ€‚ - ๆŠŠ็ฑปๅž‹่ฎพ็ฝฎไธบ `int | None` ๏ผŒSQLModel ๅฐฑ่ƒฝ็Ÿฅ้“่ฏฅๅˆ—ๅœจ SQL ๆ•ฐๆฎๅบ“ไธญๅบ”่ฏฅๆ˜ฏ `INTEGER` ็ฑปๅž‹๏ผŒๅนถไธ”ๅบ”่ฏฅๆ˜ฏ `NULLABLE` ใ€‚ + **ๆณจๆ„๏ผš** ๆˆ‘ไปฌไธบไธป้”ฎๅญ—ๆฎตไฝฟ็”จ `int | None`๏ผŒ่ฟ™ๆ ทๅœจ Python ไปฃ็ ไธญๆˆ‘ไปฌๅฏไปฅๅœจๆฒกๆœ‰ `id`๏ผˆ`id=None`๏ผ‰็š„ๆƒ…ๅ†ตไธ‹ๅˆ›ๅปบๅฏน่ฑก๏ผŒๅนถๅ‡ๅฎšๆ•ฐๆฎๅบ“ๅœจไฟๅญ˜ๆ—ถไผš็”Ÿๆˆๅฎƒใ€‚SQLModel ไผš็†่งฃๆ•ฐๆฎๅบ“ไผšๆไพ› `id`๏ผŒๅนถๅœจๆ•ฐๆฎๅบ“ๆจกๅผไธญๅฐ†่ฏฅๅˆ—ๅฎšไน‰ไธบ้ž็ฉบ็š„ `INTEGER`ใ€‚่ฏฆ่ง SQLModel ๅ…ณไบŽไธป้”ฎ็š„ๆ–‡ๆกฃใ€‚ * `Field(index=True)` ไผšๅ‘Š่ฏ‰ SQLModel ๅบ”่ฏฅไธบๆญคๅˆ—ๅˆ›ๅปบไธ€ไธช **SQL ็ดขๅผ•**๏ผŒ่ฟ™ๆ ทๅœจ่ฏปๅ–ๆŒ‰ๆญคๅˆ—่ฟ‡ๆปค็š„ๆ•ฐๆฎๆ—ถ๏ผŒ็จ‹ๅบ่ƒฝๅœจๆ•ฐๆฎๅบ“ไธญ่ฟ›่กŒๆ›ดๅฟซ็š„ๆŸฅๆ‰พใ€‚ - SQLModel ไผš็Ÿฅ้“ๅฃฐๆ˜Žไธบ `str` ็š„ๅ†…ๅฎนๅฐ†ๆ˜ฏ็ฑปๅž‹ไธบ `TEXT` ๏ผˆๆˆ– `VARCHAR` ๏ผŒๅ…ทไฝ“ๅ–ๅ†ณไบŽๆ•ฐๆฎๅบ“๏ผ‰็š„ SQL ๅˆ—ใ€‚ + SQLModel ไผš็Ÿฅ้“ๅฃฐๆ˜Žไธบ `str` ็š„ๅ†…ๅฎนๅฐ†ๆ˜ฏ็ฑปๅž‹ไธบ `TEXT`๏ผˆๆˆ– `VARCHAR`๏ผŒๅ…ทไฝ“ๅ–ๅ†ณไบŽๆ•ฐๆฎๅบ“๏ผ‰็š„ SQL ๅˆ—ใ€‚ -### ๅˆ›ๅปบๅผ•ๆ“Ž๏ผˆEngine๏ผ‰ +### ๅˆ›ๅปบๅผ•ๆ“Ž๏ผˆEngine๏ผ‰ { #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 ๆ•ฐๆฎๅบ“ใ€‚่ฟ™ๅพˆๆœ‰ๅฟ…่ฆ๏ผŒๅ› ไธบ**ๅ•ไธช่ฏทๆฑ‚**ๅฏ่ƒฝไผšไฝฟ็”จ**ๅคšไธช็บฟ็จ‹**๏ผˆไพ‹ๅฆ‚ๅœจไพ่ต–้กนไธญ๏ผ‰ใ€‚ -ไธ็”จๆ‹…ๅฟƒ๏ผŒๆˆ‘ไปฌไผšๆŒ‰็…งไปฃ็ ็ป“ๆž„็กฎไฟ**ๆฏไธช่ฏทๆฑ‚ไฝฟ็”จไธ€ไธชๅ•็‹ฌ็š„ SQLModel *ไผš่ฏ***๏ผŒ่ฟ™ๅฎž้™…ไธŠๅฐฑๆ˜ฏ `check_same_thread` ๆƒณ่ฆๅฎž็Žฐ็š„ใ€‚ +ไธ็”จๆ‹…ๅฟƒ๏ผŒๆˆ‘ไปฌไผšๆŒ‰็…งไปฃ็ ็ป“ๆž„็กฎไฟ**ๆฏไธช่ฏทๆฑ‚ไฝฟ็”จไธ€ไธชๅ•็‹ฌ็š„ SQLModel ไผš่ฏ๏ผˆsession๏ผ‰**๏ผŒ่ฟ™ๅฎž้™…ไธŠๅฐฑๆ˜ฏ `check_same_thread` ๆƒณ่ฆๅฎž็Žฐ็š„ใ€‚ -### ๅˆ›ๅปบ่กจ +### ๅˆ›ๅปบ่กจ { #create-the-tables } ็„ถๅŽ๏ผŒๆˆ‘ไปฌๆฅๆทปๅŠ ไธ€ไธชๅ‡ฝๆ•ฐ๏ผŒไฝฟ็”จ `SQLModel.metadata.create_all(engine)` ไธบๆ‰€ๆœ‰*่กจๆจกๅž‹***ๅˆ›ๅปบ่กจ**ใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} -### ๅˆ›ๅปบไผš่ฏ๏ผˆSession๏ผ‰ไพ่ต–้กน +### ๅˆ›ๅปบไผš่ฏ๏ผˆSession๏ผ‰ไพ่ต–้กน { #create-a-session-dependency } **`Session`** ไผšๅญ˜ๅ‚จ**ๅ†…ๅญ˜ไธญ็š„ๅฏน่ฑก**ๅนถ่ทŸ่ธชๆ•ฐๆฎไธญๆ‰€้œ€ๆ›ดๆ”น็š„ๅ†…ๅฎน๏ผŒ็„ถๅŽๅฎƒ**ไฝฟ็”จ `engine`** ไธŽๆ•ฐๆฎๅบ“่ฟ›่กŒ้€šไฟกใ€‚ -ๆˆ‘ไปฌไผšไฝฟ็”จ `yield` ๅˆ›ๅปบไธ€ไธช FastAPI **ไพ่ต–้กน**๏ผŒไธบๆฏไธช่ฏทๆฑ‚ๆไพ›ไธ€ไธชๆ–ฐ็š„ `Session` ใ€‚่ฟ™็กฎไฟๆˆ‘ไปฌๆฏไธช่ฏทๆฑ‚ไฝฟ็”จไธ€ไธชๅ•็‹ฌ็š„ไผš่ฏใ€‚๐Ÿค“ +ๆˆ‘ไปฌไผšไฝฟ็”จ `yield` ๅˆ›ๅปบไธ€ไธช FastAPI **ไพ่ต–้กน**๏ผŒไธบๆฏไธช่ฏทๆฑ‚ๆไพ›ไธ€ไธชๆ–ฐ็š„ `Session`ใ€‚่ฟ™็กฎไฟๆˆ‘ไปฌๆฏไธช่ฏทๆฑ‚ไฝฟ็”จไธ€ไธชๅ•็‹ฌ็š„ไผš่ฏใ€‚๐Ÿค“ ็„ถๅŽๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `Annotated` ็š„ไพ่ต–้กน `SessionDep` ๆฅ็ฎ€ๅŒ–ๅ…ถไป–ไนŸไผš็”จๅˆฐๆญคไพ่ต–็š„ไปฃ็ ใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} -### ๅœจๅฏๅŠจๆ—ถๅˆ›ๅปบๆ•ฐๆฎๅบ“่กจ +### ๅœจๅฏๅŠจๆ—ถๅˆ›ๅปบๆ•ฐๆฎๅบ“่กจ { #create-database-tables-on-startup } ๆˆ‘ไปฌไผšๅœจๅบ”็”จ็จ‹ๅบๅฏๅŠจๆ—ถๅˆ›ๅปบๆ•ฐๆฎๅบ“่กจใ€‚ @@ -107,49 +107,47 @@ SQLModel ็š„ๅผ•ๆ“Ž `engine`๏ผˆๅฎž้™…ไธŠๅฎƒๆ˜ฏไธ€ไธช SQLAlchemy `engine` ๏ผ‰ๆ˜ฏ ๆญคๅค„๏ผŒๅœจๅบ”็”จ็จ‹ๅบๅฏๅŠจไบ‹ไปถไธญ๏ผŒๆˆ‘ไปฌๅˆ›ๅปบไบ†่กจใ€‚ -่€ŒๅฏนไบŽ็”Ÿไบง็Žฏๅขƒ๏ผŒๆ‚จๅฏ่ƒฝไผš็”จไธ€ไธช่ƒฝๅคŸๅœจๅฏๅŠจๅบ”็”จ็จ‹ๅบไน‹ๅ‰่ฟ่กŒ็š„่ฟ็งป่„šๆœฌใ€‚๐Ÿค“ +ๅœจ็”Ÿไบง็Žฏๅขƒไธญ๏ผŒไฝ ๅฏ่ƒฝไผšไฝฟ็”จไธ€ไธชๅœจๅฏๅŠจๅบ”็”จ็จ‹ๅบไน‹ๅ‰่ฟ่กŒ็š„่ฟ็งป่„šๆœฌใ€‚๐Ÿค“ -/// tip +/// tip | ๆ็คบ -SQLModel ๅฐ†ไผšๆ‹ฅๆœ‰ๅฐ่ฃ… Alembic ็š„่ฟ็งปๅทฅๅ…ท๏ผŒไฝ†็›ฎๅ‰ๆ‚จๅฏไปฅ็›ดๆŽฅไฝฟ็”จ Alembicใ€‚ +SQLModel ๅฐ†ไผšๆ‹ฅๆœ‰ๅฐ่ฃ… Alembic ็š„่ฟ็งปๅทฅๅ…ท๏ผŒไฝ†็›ฎๅ‰ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ Alembicใ€‚ /// -### ๅˆ›ๅปบ Hero ็ฑป +### ๅˆ›ๅปบ Hero { #create-a-hero } -ๅ› ไธบๆฏไธช SQLModel ๆจกๅž‹ๅŒๆ—ถไนŸๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹๏ผŒๆ‰€ไปฅๆ‚จๅฏไปฅๅœจไธŽ Pydantic ๆจกๅž‹็›ธๅŒ็š„**็ฑปๅž‹ๆณจ้‡Š**ไธญไฝฟ็”จๅฎƒใ€‚ +ๅ› ไธบๆฏไธช SQLModel ๆจกๅž‹ๅŒๆ—ถไนŸๆ˜ฏไธ€ไธช Pydantic ๆจกๅž‹๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅๅœจไธŽ Pydantic ๆจกๅž‹็›ธๅŒ็š„**็ฑปๅž‹ๆณจ่งฃ**ไธญไฝฟ็”จๅฎƒใ€‚ -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๆ‚จๅฃฐๆ˜Žไธ€ไธช็ฑปๅž‹ไธบ `Hero` ็š„ๅ‚ๆ•ฐ๏ผŒๅฎƒๅฐ†ไปŽ **JSON ไธปไฝ“**ไธญ่ฏปๅ–ๆ•ฐๆฎใ€‚ +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไธ€ไธช็ฑปๅž‹ไธบ `Hero` ็š„ๅ‚ๆ•ฐ๏ผŒๅฎƒๅฐ†ไปŽ **JSON ไธปไฝ“**ไธญ่ฏปๅ–ๆ•ฐๆฎใ€‚ -ๅŒๆ ท๏ผŒๆ‚จๅฏไปฅๅฐ†ๅ…ถๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐ็š„**่ฟ”ๅ›ž็ฑปๅž‹**๏ผŒ็„ถๅŽๆ•ฐๆฎ็š„็ป“ๆž„ๅฐฑไผšๆ˜พ็คบๅœจ่‡ชๅŠจ็”Ÿๆˆ็š„ API ๆ–‡ๆกฃ็•Œ้ขไธญใ€‚ +ๅŒๆ ท๏ผŒไฝ ๅฏไปฅๅฐ†ๅ…ถๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐ็š„**่ฟ”ๅ›ž็ฑปๅž‹**๏ผŒ็„ถๅŽๆ•ฐๆฎ็š„็ป“ๆž„ๅฐฑไผšๆ˜พ็คบๅœจ่‡ชๅŠจ็”Ÿๆˆ็š„ API ๆ–‡ๆกฃ็•Œ้ขไธญใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} - +่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌไฝฟ็”จ `SessionDep` ไพ่ต–้กน๏ผˆไธ€ไธช `Session`๏ผ‰ๅฐ†ๆ–ฐ็š„ `Hero` ๆทปๅŠ ๅˆฐ `Session` ๅฎžไพ‹ไธญ๏ผŒๆไบคๆ›ดๆ”นๅˆฐๆ•ฐๆฎๅบ“๏ผŒๅˆทๆ–ฐ `hero` ไธญ็š„ๆ•ฐๆฎ๏ผŒๅนถ่ฟ”ๅ›žๅฎƒใ€‚ -่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌไฝฟ็”จ `SessionDep` ไพ่ต–้กน๏ผˆไธ€ไธช `Session` ๏ผ‰ๅฐ†ๆ–ฐ็š„ `Hero` ๆทปๅŠ ๅˆฐ `Session` ๅฎžไพ‹ไธญ๏ผŒๆไบคๆ›ดๆ”นๅˆฐๆ•ฐๆฎๅบ“๏ผŒๅˆทๆ–ฐ hero ไธญ็š„ๆ•ฐๆฎ๏ผŒๅนถ่ฟ”ๅ›žๅฎƒใ€‚ +### ่ฏปๅ– Hero { #read-heroes } -### ่ฏปๅ– Hero ็ฑป - -ๆˆ‘ไปฌๅฏไปฅไฝฟ็”จ `select()` ไปŽๆ•ฐๆฎๅบ“ไธญ**่ฏปๅ–** `Hero` ็ฑป๏ผŒๅนถๅˆฉ็”จ `limit` ๅ’Œ `offset` ๆฅๅฏน็ป“ๆžœ่ฟ›่กŒๅˆ†้กตใ€‚ +ๆˆ‘ไปฌๅฏไปฅไฝฟ็”จ `select()` ไปŽๆ•ฐๆฎๅบ“ไธญ**่ฏปๅ–** `Hero`๏ผŒๅนถๅˆฉ็”จ `limit` ๅ’Œ `offset` ๆฅๅฏน็ป“ๆžœ่ฟ›่กŒๅˆ†้กตใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} -### ่ฏปๅ–ๅ•ไธช Hero +### ่ฏปๅ–ๅ•ไธช Hero { #read-one-hero } -ๆˆ‘ไปฌๅฏไปฅ**่ฏปๅ–**ๅ•ไธช `Hero` ใ€‚ +ๆˆ‘ไปฌๅฏไปฅ**่ฏปๅ–**ๅ•ไธช `Hero`ใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} -### ๅˆ ้™คๅ•ไธช Hero +### ๅˆ ้™คๅ•ไธช Hero { #delete-a-hero } -ๆˆ‘ไปฌไนŸๅฏไปฅ**ๅˆ ้™ค**ๅ•ไธช `Hero` ใ€‚ +ๆˆ‘ไปฌไนŸๅฏไปฅ**ๅˆ ้™ค**ไธ€ไธช `Hero`ใ€‚ {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} -### ่ฟ่กŒๅบ”็”จ็จ‹ๅบ +### ่ฟ่กŒๅบ”็”จ { #run-the-app } -ๆ‚จๅฏไปฅ่ฟ่กŒ่ฟ™ไธชๅบ”็”จ็จ‹ๅบ๏ผš +ไฝ ๅฏไปฅ่ฟ่กŒ่ฟ™ไธชๅบ”็”จ๏ผš
@@ -161,25 +159,25 @@ $ fastapi dev main.py
-็„ถๅŽๅœจ `/docs` UI ไธญ๏ผŒๆ‚จ่ƒฝๅคŸ็œ‹ๅˆฐ **FastAPI** ไผš็”จ่ฟ™ไบ›**ๆจกๅž‹**ๆฅ**่ฎฐๅฝ•** API๏ผŒๅนถไธ”่ฟ˜ไผš็”จๅฎƒไปฌๆฅ**ๅบๅˆ—ๅŒ–**ๅ’Œ**้ชŒ่ฏ**ๆ•ฐๆฎใ€‚ +็„ถๅŽๅœจ `/docs` UI ไธญ๏ผŒไฝ ่ƒฝๅคŸ็œ‹ๅˆฐ **FastAPI** ไผš็”จ่ฟ™ไบ›**ๆจกๅž‹**ๆฅ**่ฎฐๅฝ•** API๏ผŒๅนถไธ”่ฟ˜ไผš็”จๅฎƒไปฌๆฅ**ๅบๅˆ—ๅŒ–**ๅ’Œ**้ชŒ่ฏ**ๆ•ฐๆฎใ€‚
-## ๆ›ดๆ–ฐๅบ”็”จ็จ‹ๅบไปฅๆ”ฏๆŒๅคšไธชๆจกๅž‹ +## ไฝฟ็”จๅคšไธชๆจกๅž‹ๆ›ดๆ–ฐๅบ”็”จ { #update-the-app-with-multiple-models } ็Žฐๅœจ่ฎฉๆˆ‘ไปฌ็จๅพฎ**้‡ๆž„**ไธ€ไธ‹่ฟ™ไธชๅบ”็”จ๏ผŒไปฅๆ้ซ˜**ๅฎ‰ๅ…จๆ€ง**ๅ’Œ**ๅคšๅŠŸ่ƒฝๆ€ง**ใ€‚ -ๅฆ‚ๆžœๆ‚จๆŸฅ็œ‹ไน‹ๅ‰็š„ๅบ”็”จ็จ‹ๅบ๏ผŒๆ‚จๅฏไปฅๅœจ UI ็•Œ้ขไธญ็œ‹ๅˆฐ๏ผŒๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒ็”ฑๅฎขๆˆท็ซฏๅ†ณๅฎš่ฆๅˆ›ๅปบ็š„ `Hero` ็š„ `id` ๅ€ผใ€‚๐Ÿ˜ฑ +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ไน‹ๅ‰็š„ๅบ”็”จ็จ‹ๅบ๏ผŒไฝ ๅฏไปฅๅœจ UI ็•Œ้ขไธญ็œ‹ๅˆฐ๏ผŒๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๅฎƒๅ…่ฎธๅฎขๆˆท็ซฏๅ†ณๅฎš่ฆๅˆ›ๅปบ็š„ `Hero` ็š„ `id`ใ€‚๐Ÿ˜ฑ -ๆˆ‘ไปฌไธๅบ”่ฏฅๅ…่ฎธ่ฟ™ๆ ทๅš๏ผŒๅ› ไธบไป–ไปฌๅฏ่ƒฝไผš่ฆ†็›–ๆˆ‘ไปฌๅœจๆ•ฐๆฎๅบ“ไธญๅทฒ็ปๅˆ†้…็š„ `id` ใ€‚ๅ†ณๅฎš `id` ็š„่กŒไธบๅบ”่ฏฅ็”ฑ**ๅŽ็ซฏ**ๆˆ–**ๆ•ฐๆฎๅบ“**ๆฅๅฎŒๆˆ๏ผŒ**่€Œ้žๅฎขๆˆท็ซฏ**ใ€‚ +ๆˆ‘ไปฌไธๅบ”่ฏฅๅ…่ฎธ่ฟ™ๆ ทๅš๏ผŒๅ› ไธบไป–ไปฌๅฏ่ƒฝไผš่ฆ†็›–ๆˆ‘ไปฌๅœจๆ•ฐๆฎๅบ“ไธญๅทฒ็ปๅˆ†้…็š„ `id`ใ€‚ๅ†ณๅฎš `id` ็š„่กŒไธบๅบ”่ฏฅ็”ฑ**ๅŽ็ซฏ**ๆˆ–**ๆ•ฐๆฎๅบ“**ๆฅๅฎŒๆˆ๏ผŒ**่€Œ้žๅฎขๆˆท็ซฏ**ใ€‚ -ๆญคๅค–๏ผŒๆˆ‘ไปฌไธบ hero ๅˆ›ๅปบไบ†ไธ€ไธช `secret_name` ๏ผŒไฝ†ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๆˆ‘ไปฌๅœจๅ„ๅค„้ƒฝ่ฟ”ๅ›žไบ†ๅฎƒ๏ผŒ่ฟ™ๅฐฑไธๅคช**็ง˜ๅฏ†**ไบ†โ€ฆโ€ฆ๐Ÿ˜… +ๆญคๅค–๏ผŒๆˆ‘ไปฌไธบ hero ๅˆ›ๅปบไบ†ไธ€ไธช `secret_name`๏ผŒไฝ†ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒๆˆ‘ไปฌๅœจๅ„ๅค„้ƒฝ่ฟ”ๅ›žไบ†ๅฎƒ๏ผŒ่ฟ™ๅฐฑไธๅคช**็ง˜ๅฏ†**ไบ†โ€ฆโ€ฆ๐Ÿ˜… ๆˆ‘ไปฌๅฐ†้€š่ฟ‡ๆทปๅŠ ไธ€ไบ›**้ขๅค–็š„ๆจกๅž‹**ๆฅ่งฃๅ†ณ่ฟ™ไบ›้—ฎ้ข˜๏ผŒ่€Œ SQLModel ๅฐ†ๅœจ่ฟ™้‡Œๅคงๆ”พๅผ‚ๅฝฉใ€‚โœจ -### ๅˆ›ๅปบๅคšไธชๆจกๅž‹ +### ๅˆ›ๅปบๅคšไธชๆจกๅž‹ { #create-multiple-models } ๅœจ **SQLModel** ไธญ๏ผŒไปปไฝ•ๅซๆœ‰ `table=True` ๅฑžๆ€ง็š„ๆจกๅž‹็ฑป้ƒฝๆ˜ฏไธ€ไธช**่กจๆจกๅž‹**ใ€‚ @@ -187,7 +185,7 @@ $ fastapi dev main.py ๆœ‰ไบ† SQLModel๏ผŒๆˆ‘ไปฌๅฐฑๅฏไปฅๅˆฉ็”จ**็ปงๆ‰ฟ**ๆฅๅœจๆ‰€ๆœ‰ๆƒ…ๅ†ตไธ‹**้ฟๅ…้‡ๅค**ๆ‰€ๆœ‰ๅญ—ๆฎตใ€‚ -#### `HeroBase` - ๅŸบ็ฑป +#### `HeroBase` - ๅŸบ็ฑป { #herobase-the-base-class } ๆˆ‘ไปฌไปŽไธ€ไธช `HeroBase` ๆจกๅž‹ๅผ€ๅง‹๏ผŒ่ฏฅๆจกๅž‹ๅ…ทๆœ‰ๆ‰€ๆœ‰ๆจกๅž‹**ๅ…ฑไบซ็š„ๅญ—ๆฎต**๏ผš @@ -196,14 +194,14 @@ $ fastapi dev main.py {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} -#### `Hero` - *่กจๆจกๅž‹* +#### `Hero` - *่กจๆจกๅž‹* { #hero-the-table-model } -ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅˆ›ๅปบ `Hero` ๏ผŒๅฎž้™…็š„*่กจๆจกๅž‹*๏ผŒๅนถๆทปๅŠ ้‚ฃไบ›ไธๆ€ปๆ˜ฏๅœจๅ…ถไป–ๆจกๅž‹ไธญ็š„**้ขๅค–ๅญ—ๆฎต**๏ผš +ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅˆ›ๅปบ `Hero`๏ผŒๅฎž้™…็š„*่กจๆจกๅž‹*๏ผŒๅนถๆทปๅŠ ้‚ฃไบ›ไธๆ€ปๆ˜ฏๅœจๅ…ถไป–ๆจกๅž‹ไธญ็š„**้ขๅค–ๅญ—ๆฎต**๏ผš * `id` * `secret_name` -ๅ› ไธบ `Hero` ็ปงๆ‰ฟ่‡ช HeroBase ๏ผŒๆ‰€ไปฅๅฎƒ**ไนŸ**ๅŒ…ๅซไบ†ๅœจ `HeroBase` ไธญๅฃฐๆ˜Ž่ฟ‡็š„**ๅญ—ๆฎต**ใ€‚ๅ› ๆญค `Hero` ็š„ๆ‰€ๆœ‰ๅญ—ๆฎตไธบ๏ผš +ๅ› ไธบ `Hero` ็ปงๆ‰ฟ่‡ช `HeroBase`๏ผŒๆ‰€ไปฅๅฎƒ**ไนŸ**ๅŒ…ๅซไบ†ๅœจ `HeroBase` ไธญๅฃฐๆ˜Ž่ฟ‡็š„**ๅญ—ๆฎต**ใ€‚ๅ› ๆญค `Hero` ็š„ๆ‰€ๆœ‰ๅญ—ๆฎตไธบ๏ผš * `id` * `name` @@ -212,46 +210,45 @@ $ fastapi dev main.py {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} -#### `HeroPublic` - ๅ…ฌๅ…ฑ*ๆ•ฐๆฎๆจกๅž‹* +#### `HeroPublic` - ๅ…ฌๅ…ฑ*ๆ•ฐๆฎๆจกๅž‹* { #heropublic-the-public-data-model } ๆŽฅไธ‹ๆฅ๏ผŒๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `HeroPublic` ๆจกๅž‹๏ผŒ่ฟ™ๆ˜ฏๅฐ†**่ฟ”ๅ›ž**็ป™ API ๅฎขๆˆท็ซฏ็š„ๆจกๅž‹ใ€‚ -ๅฎƒๅŒ…ๅซไธŽ `HeroBase` ็›ธๅŒ็š„ๅญ—ๆฎต๏ผŒๅ› ๆญคไธไผšๅŒ…ๆ‹ฌ `secret_name` ใ€‚ +ๅฎƒๅŒ…ๅซไธŽ `HeroBase` ็›ธๅŒ็š„ๅญ—ๆฎต๏ผŒๅ› ๆญคไธไผšๅŒ…ๆ‹ฌ `secret_name`ใ€‚ -็ปˆไบŽ๏ผŒๆˆ‘ไปฌ่‹ฑ้›„๏ผˆhero๏ผ‰็š„่บซไปฝๅพ—ๅˆฐไบ†ไฟๆŠค๏ผ ๐Ÿฅท +็ปˆไบŽ๏ผŒๆˆ‘ไปฌ่‹ฑ้›„๏ผˆhero๏ผ‰็š„่บซไปฝๅพ—ๅˆฐไบ†ไฟๆŠค๏ผ๐Ÿฅท -ๅฎƒ่ฟ˜้‡ๆ–ฐๅฃฐๆ˜Žไบ† `id: int` ใ€‚่ฟ™ๆ ทๆˆ‘ไปฌไพฟไธŽ API ๅฎขๆˆท็ซฏๅปบ็ซ‹ไบ†ไธ€็ง**็บฆๅฎš**๏ผŒไฝฟไป–ไปฌๅง‹็ปˆๅฏไปฅๆœŸๅพ… `id` ๅญ˜ๅœจๅนถไธ”ๆ˜ฏไธ€ไธชๆ•ดๆ•ฐ `int`๏ผˆๆฐธ่ฟœไธไผšๆ˜ฏ `None` ๏ผ‰ใ€‚ +ๅฎƒ่ฟ˜้‡ๆ–ฐๅฃฐๆ˜Žไบ† `id: int`ใ€‚่ฟ™ๆ ทๆˆ‘ไปฌไพฟไธŽ API ๅฎขๆˆท็ซฏๅปบ็ซ‹ไบ†ไธ€็ง**็บฆๅฎš**๏ผŒไฝฟไป–ไปฌๅง‹็ปˆๅฏไปฅๆœŸๅพ… `id` ๅญ˜ๅœจๅนถไธ”ๆ˜ฏไธ€ไธชๆ•ดๆ•ฐ `int`๏ผˆๆฐธ่ฟœไธไผšๆ˜ฏ `None`๏ผ‰ใ€‚ -/// tip +/// tip | ๆ็คบ -็กฎไฟ่ฟ”ๅ›žๆจกๅž‹ๅง‹็ปˆๆไพ›ไธ€ไธชๅ€ผๅนถไธ”ๅง‹็ปˆๆ˜ฏ `int` ๏ผˆ่€Œไธๆ˜ฏ `None` ๏ผ‰ๅฏน API ๅฎขๆˆท็ซฏ้žๅธธๆœ‰็”จ๏ผŒไป–ไปฌๅฏไปฅๅœจ่ฟ™็ง็กฎๅฎšๆ€งไธ‹็ผ–ๅ†™ๆ›ด็ฎ€ๅ•็š„ไปฃ็ ใ€‚ +็กฎไฟ่ฟ”ๅ›žๆจกๅž‹ๅง‹็ปˆๆไพ›ไธ€ไธชๅ€ผๅนถไธ”ๅง‹็ปˆๆ˜ฏ `int`๏ผˆ่€Œไธๆ˜ฏ `None`๏ผ‰ๅฏน API ๅฎขๆˆท็ซฏ้žๅธธๆœ‰็”จ๏ผŒไป–ไปฌๅฏไปฅๅœจ่ฟ™็ง็กฎๅฎšๆ€งไธ‹็ผ–ๅ†™ๆ›ด็ฎ€ๅ•็š„ไปฃ็ ใ€‚ -ๆญคๅค–๏ผŒ**่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏ**ๅฐ†ๆ‹ฅๆœ‰ๆ›ด็ฎ€ๆด็š„ๆŽฅๅฃ๏ผŒ่ฟ™ๆ ทไธŽๆ‚จ็š„ API ไบคไบ’็š„ๅผ€ๅ‘่€…ๅฐฑ่ƒฝๆ›ด่ฝปๆพๅœฐไฝฟ็”จๆ‚จ็š„ APIใ€‚๐Ÿ˜Ž +ๆญคๅค–๏ผŒ**่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏ**ๅฐ†ๆ‹ฅๆœ‰ๆ›ด็ฎ€ๆด็š„ๆŽฅๅฃ๏ผŒ่ฟ™ๆ ทไธŽไฝ ็š„ API ไบคไบ’็š„ๅผ€ๅ‘่€…ๅฐฑ่ƒฝๆ›ด่ฝปๆพๅœฐไฝฟ็”จไฝ ็š„ APIใ€‚๐Ÿ˜Ž /// -`HeroPublic` ไธญ็š„ๆ‰€ๆœ‰ๅญ—ๆฎต้ƒฝไธŽ `HeroBase` ไธญ็š„็›ธๅŒ๏ผŒๅ…ถไธญ `id` ๅฃฐๆ˜Žไธบ `int` ๏ผˆไธๆ˜ฏ `None` ๏ผ‰๏ผš +`HeroPublic` ไธญ็š„ๆ‰€ๆœ‰ๅญ—ๆฎต้ƒฝไธŽ `HeroBase` ไธญ็š„็›ธๅŒ๏ผŒๅ…ถไธญ `id` ๅฃฐๆ˜Žไธบ `int`๏ผˆไธๆ˜ฏ `None`๏ผ‰๏ผš * `id` * `name` * `age` -* `secret_name` {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} -#### `HeroCreate` - ็”จไบŽๅˆ›ๅปบ hero ็š„*ๆ•ฐๆฎๆจกๅž‹* +#### `HeroCreate` - ็”จไบŽๅˆ›ๅปบ hero ็š„*ๆ•ฐๆฎๆจกๅž‹* { #herocreate-the-data-model-to-create-a-hero } -็Žฐๅœจๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `HeroCreate` ๆจกๅž‹๏ผŒ่ฟ™ๆ˜ฏ็”จไบŽ**้ชŒ่ฏ**ๅฎขๆˆทๆ•ฐๆฎ็š„ๆจกๅž‹ใ€‚ +็Žฐๅœจๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `HeroCreate` ๆจกๅž‹๏ผŒ่ฟ™ๆ˜ฏ็”จไบŽ**้ชŒ่ฏ**ๅฎขๆˆท็ซฏๆ•ฐๆฎ็š„ๆจกๅž‹ใ€‚ -ๅฎƒไธไป…ๆ‹ฅๆœ‰ไธŽ `HeroBase` ็›ธๅŒ็š„ๅญ—ๆฎต๏ผŒ่ฟ˜ๆœ‰ `secret_name` ใ€‚ +ๅฎƒไธไป…ๆ‹ฅๆœ‰ไธŽ `HeroBase` ็›ธๅŒ็š„ๅญ—ๆฎต๏ผŒ่ฟ˜ๆœ‰ `secret_name`ใ€‚ -็Žฐๅœจ๏ผŒๅฝ“ๅฎขๆˆท็ซฏ**ๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ hero** ๆ—ถ๏ผŒไป–ไปฌไผšๅ‘้€ `secret_name` ๏ผŒๅฎƒไผš่ขซๅญ˜ๅ‚จๅˆฐๆ•ฐๆฎๅบ“ไธญ๏ผŒไฝ†่ฟ™ไบ› `secret_name` ไธไผš้€š่ฟ‡ API ่ฟ”ๅ›ž็ป™ๅฎขๆˆท็ซฏใ€‚ +็Žฐๅœจ๏ผŒๅฝ“ๅฎขๆˆท็ซฏ**ๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ hero** ๆ—ถ๏ผŒไป–ไปฌไผšๅ‘้€ `secret_name`๏ผŒๅฎƒไผš่ขซๅญ˜ๅ‚จๅˆฐๆ•ฐๆฎๅบ“ไธญ๏ผŒไฝ†่ฟ™ไบ› `secret_name` ไธไผš้€š่ฟ‡ API ่ฟ”ๅ›ž็ป™ๅฎขๆˆท็ซฏใ€‚ -/// tip +/// tip | ๆ็คบ ่ฟ™ๅบ”ๅฝ“ๆ˜ฏ**ๅฏ†็ **่ขซๅค„็†็š„ๆ–นๅผ๏ผšๆŽฅๆ”ถๅฏ†็ ๏ผŒไฝ†ไธ่ฆ้€š่ฟ‡ API ่ฟ”ๅ›žๅฎƒไปฌใ€‚ -ๅœจๅญ˜ๅ‚จๅฏ†็ ไน‹ๅ‰๏ผŒๆ‚จ่ฟ˜ๅบ”่ฏฅๅฏนๅฏ†็ ็š„ๅ€ผ่ฟ›่กŒ**ๅ“ˆๅธŒ**ๅค„็†๏ผŒ**็ปไธ่ฆไปฅๆ˜Žๆ–‡ๅฝขๅผๅญ˜ๅ‚จๅฎƒไปฌ**ใ€‚ +ๅœจๅญ˜ๅ‚จๅฏ†็ ไน‹ๅ‰๏ผŒไฝ ่ฟ˜ๅบ”่ฏฅๅฏนๅฏ†็ ็š„ๅ€ผ่ฟ›่กŒ**ๅ“ˆๅธŒ**ๅค„็†๏ผŒ**็ปไธ่ฆไปฅๆ˜Žๆ–‡ๅฝขๅผๅญ˜ๅ‚จๅฎƒไปฌ**ใ€‚ /// @@ -263,17 +260,17 @@ $ fastapi dev main.py {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} -#### `HeroUpdate` - ็”จไบŽๆ›ดๆ–ฐ hero ็š„*ๆ•ฐๆฎๆจกๅž‹* +#### `HeroUpdate` - ็”จไบŽๆ›ดๆ–ฐ hero ็š„*ๆ•ฐๆฎๆจกๅž‹* { #heroupdate-the-data-model-to-update-a-hero } ๅœจไน‹ๅ‰็š„ๅบ”็”จ็จ‹ๅบไธญ๏ผŒๆˆ‘ไปฌๆฒกๆœ‰ๅŠžๆณ•**ๆ›ดๆ–ฐ hero**๏ผŒไฝ†็Žฐๅœจๆœ‰ไบ†**ๅคšไธชๆจกๅž‹**๏ผŒๆˆ‘ไปฌไพฟ่ƒฝๅšๅˆฐ่ฟ™ไธ€็‚นไบ†ใ€‚๐ŸŽ‰ -`HeroUpdate` *ๆ•ฐๆฎๆจกๅž‹*ๆœ‰ไบ›็‰นๆฎŠ๏ผŒๅฎƒๅŒ…ๅซๅˆ›ๅปบๆ–ฐ hero ๆ‰€้œ€็š„**ๆ‰€ๆœ‰็›ธๅŒๅญ—ๆฎต**๏ผŒไฝ†ๆ‰€ๆœ‰ๅญ—ๆฎต้ƒฝๆ˜ฏ**ๅฏ้€‰็š„**๏ผˆๅฎƒไปฌ้ƒฝๆœ‰้ป˜่ฎคๅ€ผ๏ผ‰ใ€‚่ฟ™ๆ ท๏ผŒๅฝ“ๆ‚จๆ›ดๆ–ฐไธ€ไธช hero ๆ—ถ๏ผŒๆ‚จๅฏไปฅๅชๅ‘้€ๆ‚จๆƒณ่ฆๆ›ดๆ–ฐ็š„ๅญ—ๆฎตใ€‚ +`HeroUpdate` *ๆ•ฐๆฎๆจกๅž‹*ๆœ‰ไบ›็‰นๆฎŠ๏ผŒๅฎƒๅŒ…ๅซๅˆ›ๅปบๆ–ฐ hero ๆ‰€้œ€็š„**ๆ‰€ๆœ‰็›ธๅŒๅญ—ๆฎต**๏ผŒไฝ†ๆ‰€ๆœ‰ๅญ—ๆฎต้ƒฝๆ˜ฏ**ๅฏ้€‰็š„**๏ผˆๅฎƒไปฌ้ƒฝๆœ‰้ป˜่ฎคๅ€ผ๏ผ‰ใ€‚่ฟ™ๆ ท๏ผŒๅฝ“ไฝ ๆ›ดๆ–ฐไธ€ไธช hero ๆ—ถ๏ผŒไฝ ๅฏไปฅๅชๅ‘้€ไฝ ๆƒณ่ฆๆ›ดๆ–ฐ็š„ๅญ—ๆฎตใ€‚ -ๅ› ไธบๆ‰€ๆœ‰**ๅญ—ๆฎตๅฎž้™…ไธŠ**้ƒฝๅ‘็”Ÿไบ†**ๅ˜ๅŒ–**๏ผˆ็ฑปๅž‹็ŽฐๅœจๅŒ…ๆ‹ฌ `None` ๏ผŒๅนถไธ”ๅฎƒไปฌ็Žฐๅœจๆœ‰ไธ€ไธช้ป˜่ฎคๅ€ผ `None` ๏ผ‰๏ผŒๆˆ‘ไปฌ้œ€่ฆ**้‡ๆ–ฐๅฃฐๆ˜Ž**ๅฎƒไปฌใ€‚ +ๅ› ไธบๆ‰€ๆœ‰**ๅญ—ๆฎตๅฎž้™…ไธŠ**้ƒฝๅ‘็”Ÿไบ†**ๅ˜ๅŒ–**๏ผˆ็ฑปๅž‹็ŽฐๅœจๅŒ…ๆ‹ฌ `None`๏ผŒๅนถไธ”ๅฎƒไปฌ็Žฐๅœจๆœ‰ไธ€ไธช้ป˜่ฎคๅ€ผ `None`๏ผ‰๏ผŒๆˆ‘ไปฌ้œ€่ฆ**้‡ๆ–ฐๅฃฐๆ˜Ž**ๅฎƒไปฌใ€‚ -ๆˆ‘ไปฌไผš้‡ๆ–ฐๅฃฐๆ˜Žๆ‰€ๆœ‰ๅญ—ๆฎต๏ผŒๅ› ๆญคๆˆ‘ไปฌๅนถไธๆ˜ฏ็œŸ็š„้œ€่ฆไปŽ `HeroBase` ็ปงๆ‰ฟใ€‚ๆˆ‘ไผš่ฎฉๅฎƒ็ปงๆ‰ฟๅชๆ˜ฏไธบไบ†ไฟๆŒไธ€่‡ด๏ผŒไฝ†่ฟ™ๅนถไธๅฟ…่ฆใ€‚่ฟ™ๆ›ดๅคšๆ˜ฏไธชไบบๅ–œๅฅฝ็š„้—ฎ้ข˜ใ€‚๐Ÿคท +ๆˆ‘ไปฌๅนถไธ็œŸ็š„้œ€่ฆไปŽ `HeroBase` ็ปงๆ‰ฟ๏ผŒๅ› ไธบๆˆ‘ไปฌไผš้‡ๆ–ฐๅฃฐๆ˜Žๆ‰€ๆœ‰ๅญ—ๆฎตใ€‚ๆˆ‘ไผš่ฎฉๅฎƒ็ปงๆ‰ฟๅชๆ˜ฏไธบไบ†ไฟๆŒไธ€่‡ด๏ผŒไฝ†่ฟ™ๅนถไธๅฟ…่ฆใ€‚่ฟ™ๆ›ดๅคšๆ˜ฏไธชไบบๅ–œๅฅฝ็š„้—ฎ้ข˜ใ€‚๐Ÿคท -`HeroUpdate` ็š„ๅญ—ๆฎตๅŒ…ๆ‹ฌ: +`HeroUpdate` ็š„ๅญ—ๆฎตๅŒ…ๆ‹ฌ๏ผš * `name` * `age` @@ -281,51 +278,51 @@ $ fastapi dev main.py {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} -### ไฝฟ็”จ `HeroCreate` ๅˆ›ๅปบๅนถ่ฟ”ๅ›ž `HeroPublic` +### ไฝฟ็”จ `HeroCreate` ๅˆ›ๅปบๅนถ่ฟ”ๅ›ž `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } ๆ—ข็„ถๆˆ‘ไปฌๆœ‰ไบ†**ๅคšไธชๆจกๅž‹**๏ผŒๆˆ‘ไปฌๅฐฑๅฏไปฅๅฏนไฝฟ็”จๅฎƒไปฌ็š„ๅบ”็”จ็จ‹ๅบ้ƒจๅˆ†่ฟ›่กŒๆ›ดๆ–ฐใ€‚ ๆˆ‘ไปฌๅœจ่ฏทๆฑ‚ไธญๆŽฅๆ”ถๅˆฐไธ€ไธช `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 +/// tip | ๆ็คบ -็Žฐๅœจๆˆ‘ไปฌไฝฟ็”จ `response_model=HeroPublic` ๆฅไปฃๆ›ฟ**่ฟ”ๅ›ž็ฑปๅž‹ๆณจ้‡Š** `-> HeroPublic` ๏ผŒๅ› ไธบๆˆ‘ไปฌ่ฟ”ๅ›ž็š„ๅ€ผๅฎž้™…ไธŠ**ๅนถไธๆ˜ฏ** `HeroPublic` ็ฑปๅž‹ใ€‚ +็Žฐๅœจๆˆ‘ไปฌไฝฟ็”จ `response_model=HeroPublic` ๆฅไปฃๆ›ฟ**่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃ** `-> HeroPublic`๏ผŒๅ› ไธบๆˆ‘ไปฌ่ฟ”ๅ›ž็š„ๅ€ผๅฎž้™…ไธŠๅนถไธๆ˜ฏ `HeroPublic`ใ€‚ -ๅฆ‚ๆžœๆˆ‘ไปฌๅฃฐๆ˜Žไบ† `-> HeroPublic` ๏ผŒๆ‚จ็š„็ผ–่พ‘ๅ™จๅ’Œไปฃ็ ๆฃ€ๆŸฅๅทฅๅ…ทไผšๆŠฑๆ€จ๏ผˆไฝ†ไนŸ็กฎๅฎž็†ๆ‰€ๅบ”ๅฝ“๏ผ‰ๆ‚จ่ฟ”ๅ›žไบ†ไธ€ไธช `Hero` ่€Œไธๆ˜ฏไธ€ไธช `HeroPublic` ใ€‚ +ๅฆ‚ๆžœๆˆ‘ไปฌๅฃฐๆ˜Žไบ† `-> HeroPublic`๏ผŒไฝ ็š„็ผ–่พ‘ๅ™จๅ’Œไปฃ็ ๆฃ€ๆŸฅๅทฅๅ…ทไผš๏ผˆ็†ๆ‰€ๅบ”ๅฝ“ๅœฐ๏ผ‰ๆŠฑๆ€จไฝ ่ฟ”ๅ›žไบ†ไธ€ไธช `Hero` ่€Œไธๆ˜ฏไธ€ไธช `HeroPublic`ใ€‚ ้€š่ฟ‡ `response_model` ็š„ๅฃฐๆ˜Ž๏ผŒๆˆ‘ไปฌ่ฎฉ **FastAPI** ๆŒ‰็…งๅฎƒ่‡ชๅทฑ็š„ๆ–นๅผๅค„็†๏ผŒ่€Œไธไผšๅนฒๆ‰ฐ็ฑปๅž‹ๆณจ่งฃไปฅๅŠ็ผ–่พ‘ๅ™จๅ’Œๅ…ถไป–ๅทฅๅ…ทๆไพ›็š„ๅธฎๅŠฉใ€‚ /// -### ็”จ `HeroPublic` ่ฏปๅ– Hero +### ไฝฟ็”จ `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 +### ไฝฟ็”จ `HeroPublic` ่ฏปๅ–ๅ•ไธช Hero { #read-one-hero-with-heropublic } -ๆˆ‘ไปฌๅฏไปฅ**่ฏปๅ–**ๅ•ไธช `hero` ใ€‚ +ๆˆ‘ไปฌๅฏไปฅ**่ฏปๅ–**ๅ•ไธช hero๏ผš {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} -### ็”จ `HeroUpdate` ๆ›ดๆ–ฐๅ•ไธช Hero +### ไฝฟ็”จ `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` ใ€‚ +็„ถๅŽๆˆ‘ไปฌไผšไฝฟ็”จ `hero_db.sqlmodel_update(hero_data)`๏ผŒๆฅๅˆฉ็”จ `hero_data` ็š„ๆ•ฐๆฎๆ›ดๆ–ฐ `hero_db`ใ€‚ {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} -### ๏ผˆๅˆไธ€ๆฌก๏ผ‰ๅˆ ้™คๅ•ไธช Hero +### ๏ผˆๅ†ๆฌก๏ผ‰ๅˆ ้™คๅ•ไธช Hero { #delete-a-hero-again } **ๅˆ ้™ค**ไธ€ไธช hero ๅŸบๆœฌไฟๆŒไธๅ˜ใ€‚ @@ -333,9 +330,9 @@ $ fastapi dev main.py {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} -### ๏ผˆๅˆไธ€ๆฌก๏ผ‰่ฟ่กŒๅบ”็”จ็จ‹ๅบ +### ๏ผˆๅ†ๆฌก๏ผ‰่ฟ่กŒๅบ”็”จ { #run-the-app-again } -ๆ‚จๅฏไปฅๅ†่ฟ่กŒไธ€ๆฌกๅบ”็”จ็จ‹ๅบ๏ผš +ไฝ ๅฏไปฅๅ†่ฟ่กŒไธ€ๆฌกๅบ”็”จ็จ‹ๅบ๏ผš
@@ -347,14 +344,14 @@ $ fastapi dev main.py
-ๆ‚จไผšๅœจ `/docs` API UI ็œ‹ๅˆฐๅฎƒ็Žฐๅœจๅทฒ็ปๆ›ดๆ–ฐ๏ผŒๅนถไธ”ๅœจ่ฟ›่กŒๅˆ›ๅปบ hero ็ญ‰ๆ“ไฝœๆ—ถ๏ผŒๅฎƒไธไผšๅ†ๆœŸๆœ›ไปŽๅฎขๆˆท็ซฏๆŽฅๆ”ถ `id` ๆ•ฐๆฎใ€‚ +ๅฆ‚ๆžœไฝ ่ฟ›ๅ…ฅ `/docs` API UI๏ผŒไฝ ไผš็œ‹ๅˆฐๅฎƒ็Žฐๅœจๅทฒ็ปๆ›ดๆ–ฐ๏ผŒๅนถไธ”ๅœจๅˆ›ๅปบ hero ๆ—ถ๏ผŒๅฎƒไธไผšๅ†ๆœŸๆœ›ไปŽๅฎขๆˆท็ซฏๆŽฅๆ”ถ `id` ๆ•ฐๆฎ็ญ‰ใ€‚
-## ๆ€ป็ป“ +## ๆ€ป็ป“ { #recap } -ๆ‚จๅฏไปฅไฝฟ็”จ **SQLModel** ไธŽ SQL ๆ•ฐๆฎๅบ“่ฟ›่กŒไบคไบ’๏ผŒๅนถ้€š่ฟ‡*ๆ•ฐๆฎๆจกๅž‹*ๅ’Œ*่กจๆจกๅž‹*็ฎ€ๅŒ–ไปฃ็ ใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ **SQLModel** ไธŽ SQL ๆ•ฐๆฎๅบ“่ฟ›่กŒไบคไบ’๏ผŒๅนถ้€š่ฟ‡*ๆ•ฐๆฎๆจกๅž‹*ๅ’Œ*่กจๆจกๅž‹*็ฎ€ๅŒ–ไปฃ็ ใ€‚ -ๆ‚จๅฏไปฅๅœจ SQLModel ็š„ๆ–‡ๆกฃไธญๅญฆไน ๅˆฐๆ›ดๅคšๅ†…ๅฎน๏ผŒๅ…ถไธญๆœ‰ไธ€ไธชๆ›ด่ฏฆ็ป†็š„ๅ…ณไบŽๅฆ‚ไฝ•ๅฐ† SQLModel ไธŽ FastAPI ไธ€่ตทไฝฟ็”จ็š„ๆ•™็จ‹ใ€‚๐Ÿš€ +ไฝ ๅฏไปฅๅœจ **SQLModel** ๆ–‡ๆกฃไธญๅญฆไน ๅˆฐๆ›ดๅคšๅ†…ๅฎน๏ผŒๅ…ถไธญๆœ‰ไธ€ไธชๆ›ด่ฏฆ็ป†็š„ๅฐ† SQLModel ไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จ็š„่ฟทไฝ ๆ•™็จ‹ใ€‚๐Ÿš€ diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index 1a0d4504cc..5b2f920b2c 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -1,40 +1,40 @@ -# ้™ๆ€ๆ–‡ไปถ +# ้™ๆ€ๆ–‡ไปถ { #static-files } -ๆ‚จๅฏไปฅไฝฟ็”จ `StaticFiles`ไปŽ็›ฎๅฝ•ไธญ่‡ชๅŠจๆไพ›้™ๆ€ๆ–‡ไปถใ€‚ +ไฝ ๅฏไปฅไฝฟ็”จ `StaticFiles` ไปŽ็›ฎๅฝ•ไธญ่‡ชๅŠจๆไพ›้™ๆ€ๆ–‡ไปถใ€‚ -## ไฝฟ็”จ`StaticFiles` +## ไฝฟ็”จ `StaticFiles` { #use-staticfiles } -* ๅฏผๅ…ฅ`StaticFiles`ใ€‚ -* "ๆŒ‚่ฝฝ"(Mount) ไธ€ไธช `StaticFiles()` ๅฎžไพ‹ๅˆฐไธ€ไธชๆŒ‡ๅฎš่ทฏๅพ„ใ€‚ +* ๅฏผๅ…ฅ `StaticFiles`ใ€‚ +* ๅฐ†ไธ€ไธช `StaticFiles()` ๅฎžไพ‹โ€œๆŒ‚่ฝฝโ€๏ผˆMount๏ผ‰ๅˆฐๆŒ‡ๅฎš่ทฏๅพ„ใ€‚ -{* ../../docs_src/static_files/tutorial001.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ ไฝ ไนŸๅฏไปฅ็”จ `from starlette.staticfiles import StaticFiles`ใ€‚ -**FastAPI** ๆไพ›ไบ†ๅ’Œ `starlette.staticfiles` ็›ธๅŒ็š„ `fastapi.staticfiles` ๏ผŒๅชๆ˜ฏไธบไบ†ๆ–นไพฟไฝ ๏ผŒๅผ€ๅ‘่€…ใ€‚ไฝ†ๅฎƒ็กฎๅฎžๆฅ่‡ชStarletteใ€‚ +**FastAPI** ๆไพ›ไบ†ๅ’Œ `starlette.staticfiles` ็›ธๅŒ็š„ `fastapi.staticfiles`๏ผŒๅชๆ˜ฏไธบไบ†ๆ–นไพฟไฝ ่ฟ™ไธชๅผ€ๅ‘่€…ใ€‚ไฝ†ๅฎƒ็กฎๅฎž็›ดๆŽฅๆฅ่‡ช Starletteใ€‚ /// -### ไป€ไนˆๆ˜ฏ"ๆŒ‚่ฝฝ"(Mounting) +### ไป€ไนˆๆ˜ฏโ€œๆŒ‚่ฝฝโ€๏ผˆMounting๏ผ‰ { #what-is-mounting } -"ๆŒ‚่ฝฝ" ่กจ็คบๅœจ็‰นๅฎš่ทฏๅพ„ๆทปๅŠ ไธ€ไธชๅฎŒๅ…จ"็‹ฌ็ซ‹็š„"ๅบ”็”จ๏ผŒ็„ถๅŽ่ดŸ่ดฃๅค„็†ๆ‰€ๆœ‰ๅญ่ทฏๅพ„ใ€‚ +โ€œๆŒ‚่ฝฝโ€่กจ็คบๅœจ็‰นๅฎš่ทฏๅพ„ๆทปๅŠ ไธ€ไธชๅฎŒๅ…จโ€œ็‹ฌ็ซ‹โ€็š„ๅบ”็”จ๏ผŒ็„ถๅŽ่ดŸ่ดฃๅค„็†ๆ‰€ๆœ‰ๅญ่ทฏๅพ„ใ€‚ -่ฟ™ไธŽไฝฟ็”จ`APIRouter`ไธๅŒ๏ผŒๅ› ไธบๅฎ‰่ฃ…็š„ๅบ”็”จ็จ‹ๅบๆ˜ฏๅฎŒๅ…จ็‹ฌ็ซ‹็š„ใ€‚OpenAPIๅ’Œๆฅ่‡ชไฝ ไธปๅบ”็”จ็š„ๆ–‡ๆกฃไธไผšๅŒ…ๅซๅทฒๆŒ‚่ฝฝๅบ”็”จ็š„ไปปไฝ•ไธœ่ฅฟ็ญ‰็ญ‰ใ€‚ +่ฟ™ไธŽไฝฟ็”จ `APIRouter` ไธๅŒ๏ผŒๅ› ไธบๆŒ‚่ฝฝ็š„ๅบ”็”จๆ˜ฏๅฎŒๅ…จ็‹ฌ็ซ‹็š„ใ€‚ไธปๅบ”็”จ็š„ OpenAPI ๅ’Œๆ–‡ๆกฃไธไผšๅŒ…ๅซๅทฒๆŒ‚่ฝฝๅบ”็”จ็š„ไปปไฝ•ๅ†…ๅฎน๏ผŒ็ญ‰็ญ‰ใ€‚ -ไฝ ๅฏไปฅๅœจ**้ซ˜็บง็”จๆˆทๆŒ‡ๅ—**ไธญไบ†่งฃๆ›ดๅคšใ€‚ +ไฝ ๅฏไปฅๅœจ[้ซ˜็บง็”จๆˆทๆŒ‡ๅ—](../advanced/index.md){.internal-link target=_blank}ไธญไบ†่งฃๆ›ดๅคšใ€‚ -## ็ป†่Š‚ +## ็ป†่Š‚ { #details } -่ฟ™ไธช "ๅญๅบ”็”จ" ไผš่ขซ "ๆŒ‚่ฝฝ" ๅˆฐ็ฌฌไธ€ไธช `"/static"` ๆŒ‡ๅ‘็š„ๅญ่ทฏๅพ„ใ€‚ๅ› ๆญค๏ผŒไปปไฝ•ไปฅ`"/static"`ๅผ€ๅคด็š„่ทฏๅพ„้ƒฝไผš่ขซๅฎƒๅค„็†ใ€‚ +็ฌฌไธ€ไธช `"/static"` ๆŒ‡็š„ๆ˜ฏ่ฟ™ไธชโ€œๅญๅบ”็”จโ€ๅฐ†่ขซโ€œๆŒ‚่ฝฝโ€ๅˆฐ็š„ๅญ่ทฏๅพ„ใ€‚ๅ› ๆญค๏ผŒไปปไฝ•ไปฅ `"/static"` ๅผ€ๅคด็š„่ทฏๅพ„้ƒฝไผš็”ฑๅฎƒๅค„็†ใ€‚ - `directory="static"` ๆŒ‡ๅ‘ๅŒ…ๅซไฝ ็š„้™ๆ€ๆ–‡ไปถ็š„็›ฎๅฝ•ๅๅญ—ใ€‚ +`directory="static"` ๆŒ‡็š„ๆ˜ฏๅŒ…ๅซไฝ ็š„้™ๆ€ๆ–‡ไปถ็š„็›ฎๅฝ•ๅ็งฐใ€‚ -`name="static"` ๆไพ›ไบ†ไธ€ไธช่ƒฝ่ขซ**FastAPI**ๅ†…้ƒจไฝฟ็”จ็š„ๅๅญ—ใ€‚ +`name="static"` ไธบๅฎƒๆไพ›ไบ†ไธ€ไธชๅฏ่ขซ **FastAPI** ๅ†…้ƒจไฝฟ็”จ็š„ๅ็งฐใ€‚ -ๆ‰€ๆœ‰่ฟ™ไบ›ๅ‚ๆ•ฐๅฏไปฅไธๅŒไบŽ"`static`"๏ผŒๆ นๆฎไฝ ๅบ”็”จ็š„้œ€่ฆๅ’Œๅ…ทไฝ“็ป†่Š‚่ฐƒๆ•ดๅฎƒไปฌใ€‚ +่ฟ™ไบ›ๅ‚ๆ•ฐ้ƒฝๅฏไปฅไธๆ˜ฏโ€œ`static`โ€๏ผŒ่ฏทๆ นๆฎไฝ ็š„ๅบ”็”จ้œ€ๆฑ‚ๅ’Œๅ…ทไฝ“็ป†่Š‚่ฟ›่กŒ่ฐƒๆ•ดใ€‚ -## ๆ›ดๅคšไฟกๆฏ +## ๆ›ดๅคšไฟกๆฏ { #more-info } -ๆ›ดๅคš็ป†่Š‚ๅ’Œ้€‰ๆ‹ฉๆŸฅ้˜… Starlette's docs about Static Files. +ๆ›ดๅคš็ป†่Š‚ๅ’Œ้€‰้กน่ฏทๆŸฅ้˜… Starlette ็š„้™ๆ€ๆ–‡ไปถๆ–‡ๆกฃใ€‚ diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 3877adbac6..1aff9f799c 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -1,4 +1,4 @@ -# ๆต‹่ฏ• +# ๆต‹่ฏ• { #testing } ๆ„Ÿ่ฐข Starlette๏ผŒๆต‹่ฏ•**FastAPI** ๅบ”็”จ่ฝปๆพๅˆๆ„‰ๅฟซใ€‚ @@ -6,17 +6,21 @@ ๆœ‰ไบ†ๅฎƒ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไธŽ**FastAPI**ไธ€่ตทไฝฟ็”จ pytestใ€‚ -## ไฝฟ็”จ `TestClient` +## ไฝฟ็”จ `TestClient` { #using-testclient } /// info | ไฟกๆฏ -่ฆไฝฟ็”จ `TestClient`๏ผŒๅ…ˆ่ฆๅฎ‰่ฃ… `httpx`. +่ฆไฝฟ็”จ `TestClient`๏ผŒๅ…ˆ่ฆๅฎ‰่ฃ… `httpx`ใ€‚ -ไพ‹๏ผš`pip install httpx`. +็กฎไฟไฝ ๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅ†ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install httpx +``` /// -ๅฏผๅ…ฅ `TestClient`. +ๅฏผๅ…ฅ `TestClient`ใ€‚ ้€š่ฟ‡ไผ ๅ…ฅไฝ ็š„**FastAPI**ๅบ”็”จๅˆ›ๅปบไธ€ไธช `TestClient` ใ€‚ @@ -26,7 +30,7 @@ ไธบไฝ ้œ€่ฆๆฃ€ๆŸฅ็š„ๅœฐๆ–น็”จๆ ‡ๅ‡†็š„Python่กจ่พพๅผๅ†™ไธช็ฎ€ๅ•็š„ `assert` ่ฏญๅฅ๏ผˆ้‡็”ณ๏ผŒๆ ‡ๅ‡†็š„`pytest`๏ผ‰ใ€‚ -{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} /// tip | ๆ็คบ @@ -52,13 +56,13 @@ /// -## ๅˆ†็ฆปๆต‹่ฏ• +## ๅˆ†็ฆปๆต‹่ฏ• { #separating-tests } ๅœจๅฎž้™…ๅบ”็”จไธญ๏ผŒไฝ ๅฏ่ƒฝไผšๆŠŠไฝ ็š„ๆต‹่ฏ•ๆ”พๅœจๅฆไธ€ไธชๆ–‡ไปถ้‡Œใ€‚ ๆ‚จ็š„**FastAPI**ๅบ”็”จ็จ‹ๅบไนŸๅฏ่ƒฝ็”ฑไธ€ไบ›ๆ–‡ไปถ/ๆจกๅ—็ป„ๆˆ็ญ‰็ญ‰ใ€‚ -### **FastAPI** app ๆ–‡ไปถ +### **FastAPI** app ๆ–‡ไปถ { #fastapi-app-file } ๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๅƒ [ๆ›ดๅคง็š„ๅบ”็”จ](bigger-applications.md){.internal-link target=_blank} ไธญๆ‰€ๆ่ฟฐ็š„ๆ–‡ไปถ็ป“ๆž„: @@ -72,9 +76,9 @@ ๅœจ `main.py` ๆ–‡ไปถไธญไฝ ๆœ‰ไธ€ไธช **FastAPI** app: -{* ../../docs_src/app_testing/main.py *} +{* ../../docs_src/app_testing/app_a_py39/main.py *} -### ๆต‹่ฏ•ๆ–‡ไปถ +### ๆต‹่ฏ•ๆ–‡ไปถ { #testing-file } ็„ถๅŽไฝ ไผšๆœ‰ไธ€ไธชๅŒ…ๅซๆต‹่ฏ•็š„ๆ–‡ไปถ `test_main.py` ใ€‚appๅฏไปฅๅƒPythonๅŒ…้‚ฃๆ ทๅญ˜ๅœจ๏ผˆไธ€ๆ ทๆ˜ฏ็›ฎๅฝ•๏ผŒไฝ†ๆœ‰ไธช `__init__.py` ๆ–‡ไปถ๏ผ‰๏ผš @@ -88,15 +92,15 @@ ๅ› ไธบ่ฟ™ๆ–‡ไปถๅœจๅŒไธ€ไธชๅŒ…ไธญ๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅ้€š่ฟ‡็›ธๅฏนๅฏผๅ…ฅไปŽ `main` ๆจกๅ—๏ผˆ`main.py`๏ผ‰ๅฏผๅ…ฅ`app`ๅฏน่ฑก๏ผš -{* ../../docs_src/app_testing/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} ...็„ถๅŽๆต‹่ฏ•ไปฃ็ ๅ’Œไน‹ๅ‰ไธ€ๆ ท็š„ใ€‚ -## ๆต‹่ฏ•๏ผšๆ‰ฉๅฑ•็คบไพ‹ +## ๆต‹่ฏ•๏ผšๆ‰ฉๅฑ•็คบไพ‹ { #testing-extended-example } ็Žฐๅœจ่ฎฉๆˆ‘ไปฌๆ‰ฉๅฑ•่ฟ™ไธชไพ‹ๅญ๏ผŒๅนถๆทปๅŠ ๆ›ดๅคš็ป†่Š‚๏ผŒ็œ‹ไธ‹ๅฆ‚ไฝ•ๆต‹่ฏ•ไธๅŒ้ƒจๅˆ†ใ€‚ -### ๆ‰ฉๅฑ•ๅŽ็š„ **FastAPI** app ๆ–‡ไปถ +### ๆ‰ฉๅฑ•ๅŽ็š„ **FastAPI** app ๆ–‡ไปถ { #extended-fastapi-app-file } ่ฎฉๆˆ‘ไปฌ็ปง็ปญไน‹ๅ‰็š„ๆ–‡ไปถ็ป“ๆž„๏ผš @@ -116,63 +120,13 @@ ๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ* ้ƒฝ้œ€่ฆไธ€ไธช`X-Token` ๅคดใ€‚ -//// tab | Python 3.10+ - -```Python -{!> ../../docs_src/app_testing/app_b_an_py310/main.py!} -``` - -//// - -//// tab | Python 3.9+ - -```Python -{!> ../../docs_src/app_testing/app_b_an_py39/main.py!} -``` - -//// - -//// tab | Python 3.8+ - -```Python -{!> ../../docs_src/app_testing/app_b_an/main.py!} -``` - -//// - -//// tab | Python 3.10+ non-Annotated - -/// tip | ๆ็คบ +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} -Prefer to use the `Annotated` version if possible. - -/// - -```Python -{!> ../../docs_src/app_testing/app_b_py310/main.py!} -``` - -//// - -//// tab | Python 3.8+ non-Annotated - -/// tip | ๆ็คบ - -Prefer to use the `Annotated` version if possible. - -/// - -```Python -{!> ../../docs_src/app_testing/app_b/main.py!} -``` - -//// - -### ๆ‰ฉๅฑ•ๅŽ็š„ๆต‹่ฏ•ๆ–‡ไปถ +### ๆ‰ฉๅฑ•ๅŽ็š„ๆต‹่ฏ•ๆ–‡ไปถ { #extended-testing-file } ็„ถๅŽๆ‚จๅฏไปฅไฝฟ็”จๆ‰ฉๅฑ•ๅŽ็š„ๆต‹่ฏ•ๆ›ดๆ–ฐ`test_main.py`๏ผš -{* ../../docs_src/app_testing/app_b/test_main.py *} +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} ๆฏๅฝ“ไฝ ้œ€่ฆๅฎขๆˆท็ซฏๅœจ่ฏทๆฑ‚ไธญไผ ้€’ไฟกๆฏ๏ผŒไฝ†ไฝ ไธ็Ÿฅ้“ๅฆ‚ไฝ•ไผ ้€’ๆ—ถ๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ๆœ็ดข๏ผˆ่ฐทๆญŒ๏ผ‰ๅฆ‚ไฝ•็”จ `httpx`ๅš๏ผŒๆˆ–่€…ๆ˜ฏ็”จ `requests` ๅš๏ผŒๆฏ•็ซŸHTTPX็š„่ฎพ่ฎกๆ˜ฏๅŸบไบŽRequests็š„่ฎพ่ฎก็š„ใ€‚ @@ -196,9 +150,11 @@ Prefer to use the `Annotated` version if possible. /// -## ่ฟ่กŒ่ตทๆฅ +## ่ฟ่กŒ่ตทๆฅ { #run-it } + +ไน‹ๅŽ๏ผŒไฝ ๅช้œ€่ฆๅฎ‰่ฃ… `pytest`ใ€‚ -ไน‹ๅŽ๏ผŒไฝ ๅช้œ€่ฆๅฎ‰่ฃ… `pytest`: +็กฎไฟไฝ ๅˆ›ๅปบๅนถๆฟ€ๆดปไธ€ไธช[่™šๆ‹Ÿ็Žฏๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅŽๅ†ๅฎ‰่ฃ…๏ผŒไพ‹ๅฆ‚๏ผš
diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index 9b3c0340a6..29e272b59a 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -1,14 +1,14 @@ -# ่™šๆ‹Ÿ็Žฏๅขƒ +# ่™šๆ‹Ÿ็Žฏๅขƒ { #virtual-environments } ๅฝ“ไฝ ๅœจ Python ๅทฅ็จ‹ไธญๅทฅไฝœๆ—ถ๏ผŒไฝ ๅฏ่ƒฝไผšๆœ‰ๅฟ…่ฆ็”จๅˆฐไธ€ไธช**่™šๆ‹Ÿ็Žฏๅขƒ**๏ผˆๆˆ–็ฑปไผผ็š„ๆœบๅˆถ๏ผ‰ๆฅ้š”็ฆปไฝ ไธบๆฏไธชๅทฅ็จ‹ๅฎ‰่ฃ…็š„ๅŒ…ใ€‚ -/// info +/// info | ไฟกๆฏ ๅฆ‚ๆžœไฝ ๅทฒ็ปไบ†่งฃ่™šๆ‹Ÿ็Žฏๅขƒ๏ผŒ็Ÿฅ้“ๅฆ‚ไฝ•ๅˆ›ๅปบๅ’Œไฝฟ็”จๅฎƒไปฌ๏ผŒไฝ ๅฏไปฅ่€ƒ่™‘่ทณ่ฟ‡่ฟ™ไธ€้ƒจๅˆ†ใ€‚๐Ÿค“ /// -/// tip +/// tip | ๆ็คบ **่™šๆ‹Ÿ็Žฏๅขƒ**ๅ’Œ**็Žฏๅขƒๅ˜้‡**ๆ˜ฏไธๅŒ็š„ใ€‚ @@ -18,7 +18,7 @@ /// -/// info +/// info | ไฟกๆฏ ่ฟ™ไธช้กต้ขๅฐ†ๆ•™ไฝ ๅฆ‚ไฝ•ไฝฟ็”จ**่™šๆ‹Ÿ็Žฏๅขƒ**ไปฅๅŠไบ†่งฃๅฎƒไปฌ็š„ๅทฅไฝœๅŽŸ็†ใ€‚ @@ -26,7 +26,7 @@ /// -## ๅˆ›ๅปบไธ€ไธชๅทฅ็จ‹ +## ๅˆ›ๅปบไธ€ไธชๅทฅ็จ‹ { #create-a-project } ้ฆ–ๅ…ˆ๏ผŒไธบไฝ ็š„ๅทฅ็จ‹ๅˆ›ๅปบไธ€ไธช็›ฎๅฝ•ใ€‚ @@ -51,11 +51,11 @@ $ cd awesome-project
-## ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ +## ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ { #create-a-virtual-environment } ๅœจๅผ€ๅง‹ไธ€ไธช Python ๅทฅ็จ‹็š„**็ฌฌไธ€ๆ—ถ้—ด**๏ผŒ**ๅœจไฝ ็š„ๅทฅ็จ‹ๅ†…้ƒจ**ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒใ€‚ -/// tip +/// tip | ๆ็คบ ไฝ ๅช้œ€่ฆ **ๅœจๆฏไธชๅทฅ็จ‹ไธญๆ“ไฝœไธ€ๆฌก**๏ผŒ่€Œไธๆ˜ฏๆฏๆฌกๅทฅไฝœๆ—ถ้ƒฝๆ“ไฝœใ€‚ @@ -96,7 +96,7 @@ $ uv venv
-/// tip +/// tip | ๆ็คบ ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ`uv` ไผšๅœจไธ€ไธชๅไธบ `.venv` ็š„็›ฎๅฝ•ไธญๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒใ€‚ @@ -114,11 +114,11 @@ $ uv venv /// -## ๆฟ€ๆดป่™šๆ‹Ÿ็Žฏๅขƒ +## ๆฟ€ๆดป่™šๆ‹Ÿ็Žฏๅขƒ { #activate-the-virtual-environment } ๆฟ€ๆดปๆ–ฐ็š„่™šๆ‹Ÿ็Žฏๅขƒๆฅ็กฎไฟไฝ ่ฟ่กŒ็š„ไปปไฝ• Python ๅ‘ฝไปคๆˆ–ๅฎ‰่ฃ…็š„ๅŒ…้ƒฝ่ƒฝไฝฟ็”จๅˆฐๅฎƒใ€‚ -/// tip +/// tip | ๆ็คบ **ๆฏๆฌก**ๅผ€ๅง‹ไธ€ไธช **ๆ–ฐ็š„็ปˆ็ซฏไผš่ฏ** ๆฅๅทฅไฝœๅœจ่ฟ™ไธชๅทฅ็จ‹ๆ—ถ๏ผŒไฝ ้ƒฝ้œ€่ฆๆ‰ง่กŒ่ฟ™ไธชๆ“ไฝœใ€‚ @@ -162,19 +162,19 @@ $ source .venv/Scripts/activate //// -/// tip +/// tip | ๆ็คบ ๆฏๆฌกไฝ ๅœจ่ฟ™ไธช็Žฏๅขƒไธญๅฎ‰่ฃ…ไธ€ไธช **ๆ–ฐ็š„ๅŒ…** ๆ—ถ๏ผŒ้ƒฝ้œ€่ฆ **้‡ๆ–ฐๆฟ€ๆดป** ่ฟ™ไธช็Žฏๅขƒใ€‚ -่ฟ™ไนˆๅš็กฎไฟไบ†ๅฝ“ไฝ ไฝฟ็”จไธ€ไธช็”ฑ่ฟ™ไธชๅŒ…ๅฎ‰่ฃ…็š„ **็ปˆ็ซฏ๏ผˆCLI๏ผ‰็จ‹ๅบ** ๆ—ถ๏ผŒไฝ ไฝฟ็”จ็š„ๆ˜ฏไฝ ็š„่™šๆ‹Ÿ็Žฏๅขƒไธญ็š„็จ‹ๅบ๏ผŒ่€Œไธๆ˜ฏๅ…จๅฑ€ๅฎ‰่ฃ…ใ€ๅฏ่ƒฝ็‰ˆๆœฌไธๅŒ็š„็จ‹ๅบใ€‚ +่ฟ™ไนˆๅš็กฎไฟไบ†ๅฝ“ไฝ ไฝฟ็”จไธ€ไธช็”ฑ่ฟ™ไธชๅŒ…ๅฎ‰่ฃ…็š„ **็ปˆ็ซฏ๏ผˆCLI๏ผ‰็จ‹ๅบ** ๆ—ถ๏ผŒไฝ ไฝฟ็”จ็š„ๆ˜ฏไฝ ็š„่™šๆ‹Ÿ็Žฏๅขƒไธญ็š„็จ‹ๅบ๏ผŒ่€Œไธๆ˜ฏๅ…จๅฑ€ๅฎ‰่ฃ…ใ€ๅฏ่ƒฝ็‰ˆๆœฌไธๅŒ็š„็จ‹ๅบใ€‚ /// -## ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒๆ˜ฏๅฆๆฟ€ๆดป +## ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒๆ˜ฏๅฆๆฟ€ๆดป { #check-the-virtual-environment-is-active } ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒๆ˜ฏๅฆๆฟ€ๆดป (ๅ‰้ข็š„ๅ‘ฝไปคๆ˜ฏๅฆ็”Ÿๆ•ˆ)ใ€‚ -/// tip +/// tip | ๆ็คบ ่ฟ™ๆ˜ฏ **ๅฏ้€‰็š„**๏ผŒไฝ†่ฟ™ๆ˜ฏไธ€ไธชๅพˆๅฅฝ็š„ๆ–นๆณ•๏ผŒๅฏไปฅ **ๆฃ€ๆŸฅ** ไธ€ๅˆ‡ๆ˜ฏๅฆๆŒ‰้ข„ๆœŸๅทฅไฝœ๏ผŒไปฅๅŠไฝ ๆ˜ฏๅฆไฝฟ็”จไบ†ไฝ ๆ‰“็ฎ—ไฝฟ็”จ็š„่™šๆ‹Ÿ็Žฏๅขƒใ€‚ @@ -212,9 +212,9 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -## ๅ‡็บง `pip` +## ๅ‡็บง `pip` { #upgrade-pip } -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœไฝ ไฝฟ็”จ `uv` ๆฅๅฎ‰่ฃ…ๅ†…ๅฎน๏ผŒ่€Œไธๆ˜ฏ `pip`๏ผŒ้‚ฃไนˆไฝ ๅฐฑไธ้œ€่ฆๅ‡็บง `pip`ใ€‚๐Ÿ˜Ž @@ -224,7 +224,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ๅœจๅฎ‰่ฃ…ๅŒ…ๆ—ถๅ‡บ็Žฐ็š„่ฎธๅคšๅฅ‡ๆ€ช็š„้”™่ฏฏ้ƒฝๅฏไปฅ้€š่ฟ‡ๅ…ˆๅ‡็บง `pip` ๆฅ่งฃๅ†ณใ€‚ -/// tip +/// tip | ๆ็คบ ้€šๅธธไฝ ๅช้œ€่ฆๅœจๅˆ›ๅปบ่™šๆ‹Ÿ็ŽฏๅขƒๅŽ **ๆ‰ง่กŒไธ€ๆฌก** ่ฟ™ไธชๆ“ไฝœใ€‚ @@ -242,17 +242,37 @@ $ python -m pip install --upgrade pip -## ๆทปๅŠ  `.gitignore` +/// tip | ๆ็คบ + +ๆœ‰ๆ—ถๅœจๅฐ่ฏ•ๅ‡็บง pip ๆ—ถ๏ผŒไฝ ๅฏ่ƒฝไผš้‡ๅˆฐ **`No module named pip`** ้”™่ฏฏใ€‚ + +ๅฆ‚ๆžœๅ‘็”Ÿ่ฟ™็งๆƒ…ๅ†ต๏ผŒไฝฟ็”จไธ‹้ข็š„ๅ‘ฝไปคๆฅๅฎ‰่ฃ…ๅนถๅ‡็บง pip๏ผš + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +่ฏฅๅ‘ฝไปคไผšๅœจๅฐšๆœชๅฎ‰่ฃ… pip ๆ—ถ่ฟ›่กŒๅฎ‰่ฃ…๏ผŒๅนถ็กฎไฟๅฎ‰่ฃ…็š„ pip ็‰ˆๆœฌไธๆ—ฉไบŽ `ensurepip` ๆไพ›็š„็‰ˆๆœฌใ€‚ + +/// + +## ๆทปๅŠ  `.gitignore` { #add-gitignore } ๅฆ‚ๆžœไฝ ไฝฟ็”จ **Git** (่ฟ™ๆ˜ฏไฝ ๅบ”่ฏฅไฝฟ็”จ็š„)๏ผŒๆทปๅŠ ไธ€ไธช `.gitignore` ๆ–‡ไปถๆฅๆŽ’้™คไฝ ็š„ `.venv` ไธญ็š„ๆ‰€ๆœ‰ๅ†…ๅฎนใ€‚ -/// tip +/// tip | ๆ็คบ ๅฆ‚ๆžœไฝ ไฝฟ็”จ `uv` ๆฅๅˆ›ๅปบ่™šๆ‹Ÿ็Žฏๅขƒ๏ผŒๅฎƒไผš่‡ชๅŠจไธบไฝ ๅฎŒๆˆ่ฟ™ไธชๆ“ไฝœ๏ผŒไฝ ๅฏไปฅ่ทณ่ฟ‡่ฟ™ไธ€ๆญฅใ€‚๐Ÿ˜Ž /// -/// tip +/// tip | ๆ็คบ ้€šๅธธไฝ ๅช้œ€่ฆๅœจๅˆ›ๅปบ่™šๆ‹Ÿ็ŽฏๅขƒๅŽ **ๆ‰ง่กŒไธ€ๆฌก** ่ฟ™ไธชๆ“ไฝœใ€‚ @@ -282,11 +302,11 @@ $ echo "*" > .venv/.gitignore /// -## ๅฎ‰่ฃ…่ฝฏไปถๅŒ… +## ๅฎ‰่ฃ…่ฝฏไปถๅŒ… { #install-packages } ๅœจๆฟ€ๆดป่™šๆ‹Ÿ็ŽฏๅขƒๅŽ๏ผŒไฝ ๅฏไปฅๅœจๅ…ถไธญๅฎ‰่ฃ…่ฝฏไปถๅŒ…ใ€‚ -/// tip +/// tip | ๆ็คบ ๅฝ“ไฝ ้œ€่ฆๅฎ‰่ฃ…ๆˆ–ๅ‡็บง่ฝฏไปถๅŒ…ๆ—ถ๏ผŒๆ‰ง่กŒๆœฌๆ“ไฝœ**ไธ€ๆฌก**๏ผ› @@ -294,11 +314,11 @@ $ echo "*" > .venv/.gitignore /// -### ็›ดๆŽฅๅฎ‰่ฃ…ๅŒ… +### ็›ดๆŽฅๅฎ‰่ฃ…ๅŒ… { #install-packages-directly } ๅฆ‚ๆžœไฝ ๆ€ฅไบŽๅฎ‰่ฃ…๏ผŒไธๆƒณไฝฟ็”จๆ–‡ไปถๆฅๅฃฐๆ˜Žๅทฅ็จ‹็š„่ฝฏไปถๅŒ…ไพ่ต–๏ผŒๆ‚จๅฏไปฅ็›ดๆŽฅๅฎ‰่ฃ…ๅฎƒไปฌใ€‚ -/// tip +/// tip | ๆ็คบ ๅฐ†็จ‹ๅบๆ‰€้œ€็š„่ฝฏไปถๅŒ…ๅŠๅ…ถ็‰ˆๆœฌๆ”พๅœจๆ–‡ไปถไธญ๏ผˆไพ‹ๅฆ‚ `requirements.txt` ๆˆ– `pyproject.toml`๏ผ‰ๆ˜ฏไธชๅฅฝ๏ผˆๅนถไธ”้žๅธธๅฅฝ๏ผ‰็š„ไธปๆ„ใ€‚ @@ -333,7 +353,7 @@ $ uv pip install "fastapi[standard]" //// -### ไปŽ `requirements.txt` ๅฎ‰่ฃ… +### ไปŽ `requirements.txt` ๅฎ‰่ฃ… { #install-from-requirements-txt } ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช `requirements.txt` ๆ–‡ไปถ๏ผŒไฝ ๅฏไปฅไฝฟ็”จๅฎƒๆฅๅฎ‰่ฃ…ๅ…ถไธญ็š„่ฝฏไปถๅŒ…ใ€‚ @@ -376,7 +396,7 @@ pydantic==2.8.0 /// -## ่ฟ่กŒ็จ‹ๅบ +## ่ฟ่กŒ็จ‹ๅบ { #run-your-program } ๅœจไฝ ๆฟ€ๆดป่™šๆ‹Ÿ็ŽฏๅขƒๅŽ๏ผŒไฝ ๅฏไปฅ่ฟ่กŒไฝ ็š„็จ‹ๅบ๏ผŒๅฎƒๅฐ†ไฝฟ็”จ่™šๆ‹Ÿ็Žฏๅขƒไธญ็š„ Python ๅ’Œไฝ ๅœจๅ…ถไธญๅฎ‰่ฃ…็š„่ฝฏไปถๅŒ…ใ€‚ @@ -390,7 +410,7 @@ Hello World -## ้…็ฝฎ็ผ–่พ‘ๅ™จ +## ้…็ฝฎ็ผ–่พ‘ๅ™จ { #configure-your-editor } ไฝ ๅฏ่ƒฝไผš็”จๅˆฐ็ผ–่พ‘ๅ™จ๏ผˆๅณ IDE โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰๏ผŒ่ฏท็กฎไฟ้…็ฝฎๅฎƒไฝฟ็”จไธŽไฝ ๅˆ›ๅปบ็š„็›ธๅŒ็š„่™šๆ‹Ÿ็Žฏๅขƒ๏ผˆๅฎƒๅฏ่ƒฝไผš่‡ชๅŠจๆฃ€ๆต‹ๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ่Žทๅพ—่‡ชๅŠจ่กฅๅ…จๅ’Œๅ†…่”้”™่ฏฏๆ็คบใ€‚ @@ -399,13 +419,13 @@ Hello World * VS Code * PyCharm -/// tip +/// tip | ๆ็คบ ้€šๅธธไฝ ๅช้œ€่ฆๅœจๅˆ›ๅปบ่™šๆ‹Ÿ็Žฏๅขƒๆ—ถๆ‰ง่กŒๆญคๆ“ไฝœ**ไธ€ๆฌก**ใ€‚ /// -## ้€€ๅ‡บ่™šๆ‹Ÿ็Žฏๅขƒ +## ้€€ๅ‡บ่™šๆ‹Ÿ็Žฏๅขƒ { #deactivate-the-virtual-environment } ๅฝ“ไฝ ๅฎŒๆˆๅทฅไฝœๅŽ๏ผŒไฝ ๅฏไปฅ**้€€ๅ‡บ**่™šๆ‹Ÿ็Žฏๅขƒใ€‚ @@ -419,13 +439,13 @@ $ deactivate ่ฟ™ๆ ท๏ผŒๅฝ“ไฝ ่ฟ่กŒ `python` ๆ—ถ๏ผŒๅฎƒไธไผšๅฐ่ฏ•ไปŽๅฎ‰่ฃ…ไบ†่ฝฏไปถๅŒ…็š„่™šๆ‹Ÿ็Žฏๅขƒไธญ่ฟ่กŒใ€‚๏ผˆๅณ๏ผŒๅฎƒๅฐ†ไธๅ†ไผšๅฐ่ฏ•ไปŽ่™šๆ‹Ÿ็Žฏๅขƒไธญ่ฟ่กŒ๏ผŒไนŸไธไผšไฝฟ็”จๅ…ถไธญๅฎ‰่ฃ…็š„่ฝฏไปถๅŒ…ใ€‚โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰ -## ๅผ€ๅง‹ๅทฅไฝœ +## ๅผ€ๅง‹ๅทฅไฝœ { #ready-to-work } ็Žฐๅœจไฝ ๅทฒ็ปๅ‡†ๅค‡ๅฅฝๅผ€ๅง‹ไฝ ็š„ๅทฅไฝœไบ†ใ€‚ -/// tip +/// tip | ๆ็คบ ไฝ ๆƒณ่ฆ็†่งฃไธŠ้ข็š„ๆ‰€ๆœ‰ๅ†…ๅฎนๅ—๏ผŸ @@ -433,7 +453,7 @@ $ deactivate /// -## ไธบไป€ไนˆ่ฆไฝฟ็”จ่™šๆ‹Ÿ็Žฏๅขƒ +## ไธบไป€ไนˆ่ฆไฝฟ็”จ่™šๆ‹Ÿ็Žฏๅขƒ { #why-virtual-environments } ไฝ ้œ€่ฆๅฎ‰่ฃ… Python ๆ‰่ƒฝไฝฟ็”จ FastAPIใ€‚ @@ -443,7 +463,7 @@ $ deactivate ็„ถ่€Œ๏ผŒๅฆ‚ๆžœไฝ ็›ดๆŽฅไฝฟ็”จ `pip`๏ผŒ่ฝฏไปถๅŒ…ๅฐ†่ขซๅฎ‰่ฃ…ๅœจไฝ ็š„**ๅ…จๅฑ€ Python ็Žฏๅขƒ**ไธญ๏ผˆๅณ Python ็š„ๅ…จๅฑ€ๅฎ‰่ฃ…๏ผ‰ใ€‚ -### ๅญ˜ๅœจ็š„้—ฎ้ข˜ +### ๅญ˜ๅœจ็š„้—ฎ้ข˜ { #the-problem } ้‚ฃไนˆ๏ผŒๅœจๅ…จๅฑ€ Python ็Žฏๅขƒไธญๅฎ‰่ฃ…่ฝฏไปถๅŒ…ๆœ‰ไป€ไนˆ้—ฎ้ข˜ๅ‘ข๏ผŸ @@ -516,7 +536,7 @@ flowchart LR end ``` -/// tip +/// tip | ๆ็คบ Python ๅŒ…ๅœจๆŽจๅ‡บ**ๆ–ฐ็‰ˆๆœฌ**ๆ—ถ้€šๅธธไผšๅฐฝ้‡**้ฟๅ…็ ดๅๆ€งๆ›ดๆ”น**๏ผŒไฝ†ๆœ€ๅฅฝ่ฟ˜ๆ˜ฏ่ฆๅฐๅฟƒ๏ผŒ่ฆๆƒณๆธ…ๆฅšๅ†ๅฎ‰่ฃ…ๆ–ฐ็‰ˆๆœฌ๏ผŒ่€Œไธ”ๅœจ่ฟ่กŒๆต‹่ฏ•ไปฅ็กฎไฟไธ€ๅˆ‡่ƒฝๆญฃๅธธๅทฅไฝœๆ—ถๅ†ๅฎ‰่ฃ…ใ€‚ @@ -526,7 +546,7 @@ Python ๅŒ…ๅœจๆŽจๅ‡บ**ๆ–ฐ็‰ˆๆœฌ**ๆ—ถ้€šๅธธไผšๅฐฝ้‡**้ฟๅ…็ ดๅๆ€งๆ›ดๆ”น**๏ผŒ ๆญคๅค–๏ผŒๅ–ๅ†ณไบŽไฝ ็š„ๆ“ไฝœ็ณป็ปŸ๏ผˆไพ‹ๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰๏ผŒๅฎƒๅฏ่ƒฝๅทฒ็ป้ข„ๅ…ˆๅฎ‰่ฃ…ไบ† Pythonใ€‚ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒๅฏ่ƒฝๅทฒ็ป้ข„ๅ…ˆๅฎ‰่ฃ…ไบ†ไธ€ไบ›่ฝฏไปถๅŒ…๏ผŒ่ฟ™ไบ›่ฝฏไปถๅŒ…็š„็‰นๅฎš็‰ˆๆœฌๆ˜ฏ**็ณป็ปŸๆ‰€้œ€็š„**ใ€‚ๅฆ‚ๆžœไฝ ๅœจๅ…จๅฑ€ Python ็Žฏๅขƒไธญๅฎ‰่ฃ…่ฝฏไปถๅŒ…๏ผŒไฝ ๅฏ่ƒฝไผš**็ ดๅ**ไธ€ไบ›้šๆ“ไฝœ็ณป็ปŸไธ€่ตทๅฎ‰่ฃ…็š„็จ‹ๅบใ€‚ -## ่ฝฏไปถๅŒ…ๅฎ‰่ฃ…ๅœจๅ“ช้‡Œ +## ่ฝฏไปถๅŒ…ๅฎ‰่ฃ…ๅœจๅ“ช้‡Œ { #where-are-packages-installed } ๅฝ“ไฝ ๅฎ‰่ฃ… Python ๆ—ถ๏ผŒๅฎƒไผšๅœจไฝ ็š„่ฎก็ฎ—ๆœบไธŠๅˆ›ๅปบไธ€ไบ›็›ฎๅฝ•๏ผŒๅนถๅœจ่ฟ™ไบ›็›ฎๅฝ•ไธญๆ”พไธ€ไบ›ๆ–‡ไปถใ€‚ @@ -552,7 +572,7 @@ $ pip install "fastapi[standard]" ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒๅฎƒไผšๅฐ†ไธ‹่ฝฝๅนถ่งฃๅŽ‹็š„่ฟ™ไบ›ๆ–‡ไปถๆ”พๅœจ้š Python ๅฎ‰่ฃ…็š„็›ฎๅฝ•ไธญ๏ผŒ่ฟ™ๅฐฑๆ˜ฏ**ๅ…จๅฑ€็Žฏๅขƒ**ใ€‚ -## ไป€ไนˆๆ˜ฏ่™šๆ‹Ÿ็Žฏๅขƒ +## ไป€ไนˆๆ˜ฏ่™šๆ‹Ÿ็Žฏๅขƒ { #what-are-virtual-environments } ่งฃๅ†ณ่ฝฏไปถๅŒ…้ƒฝๅฎ‰่ฃ…ๅœจๅ…จๅฑ€็Žฏๅขƒไธญ็š„้—ฎ้ข˜็š„ๆ–นๆณ•ๆ˜ฏไธบไฝ ๆ‰€ๅš็š„ๆฏไธชๅทฅ็จ‹ไฝฟ็”จไธ€ไธช**่™šๆ‹Ÿ็Žฏๅขƒ**ใ€‚ @@ -577,7 +597,7 @@ flowchart TB stone-project ~~~ azkaban-project ``` -## ๆฟ€ๆดป่™šๆ‹Ÿ็Žฏๅขƒๆ„ๅ‘ณ็€ไป€ไนˆ +## ๆฟ€ๆดป่™šๆ‹Ÿ็Žฏๅขƒๆ„ๅ‘ณ็€ไป€ไนˆ { #what-does-activating-a-virtual-environment-mean } ๅฝ“ไฝ ๆฟ€ๆดปไบ†ไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ๏ผŒไพ‹ๅฆ‚๏ผš @@ -623,7 +643,7 @@ $ source .venv/Scripts/activate ๅ…ถไธญไน‹ไธ€ๆ˜ฏ `PATH` ๅ˜้‡ใ€‚ -/// tip +/// tip | ๆ็คบ ไฝ ๅฏไปฅๅœจ [็Žฏๅขƒๅ˜้‡](environment-variables.md#path-environment-variable){.internal-link target=_blank} ้ƒจๅˆ†ไบ†่งฃๆ›ดๅคšๅ…ณไบŽ `PATH` ็Žฏๅขƒๅ˜้‡็š„ๅ†…ๅฎนใ€‚ @@ -714,7 +734,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ๆฟ€ๆดป่™šๆ‹Ÿ็Žฏๅขƒ่ฟ˜ไผšๆ”นๅ˜ๅ…ถไป–ไธ€ไบ›ไธœ่ฅฟ๏ผŒไฝ†่ฟ™ๆ˜ฏๅฎƒๆ‰€ๅš็š„ๆœ€้‡่ฆ็š„ไบ‹ๆƒ…ไน‹ไธ€ใ€‚ -## ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒ +## ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒ { #checking-a-virtual-environment } ๅฝ“ไฝ ๆฃ€ๆŸฅ่™šๆ‹Ÿ็Žฏๅขƒๆ˜ฏๅฆๆฟ€ๆดปๆ—ถ๏ผŒไพ‹ๅฆ‚๏ผš @@ -756,7 +776,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ็กฎ่ฎคไฝ ๆ˜ฏๅฆๅœจๆญฃ็กฎ็š„่™šๆ‹Ÿ็Žฏๅขƒไธญใ€‚ -/// tip +/// tip | ๆ็คบ ๆฟ€ๆดปไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ๏ผŒ่Žทๅ–ไธ€ไธช Python๏ผŒ็„ถๅŽ**่ฝฌๅˆฐๅฆไธ€ไธชๅทฅ็จ‹**ๆ˜ฏไธ€ไปถๅพˆๅฎนๆ˜“็š„ไบ‹ๆƒ…๏ผ› @@ -766,7 +786,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// -## ไธบไป€ไนˆ่ฆๅœ็”จ่™šๆ‹Ÿ็Žฏๅขƒ +## ไธบไป€ไนˆ่ฆๅœ็”จ่™šๆ‹Ÿ็Žฏๅขƒ { #why-deactivate-a-virtual-environment } ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๆญฃๅœจไธ€ไธชๅทฅ็จ‹ `philosophers-stone` ไธŠๅทฅไฝœ๏ผŒ**ๆฟ€ๆดปไบ†่ฏฅ่™šๆ‹Ÿ็Žฏๅขƒ**๏ผŒๅฎ‰่ฃ…ไบ†ๅŒ…ๅนถไฝฟ็”จไบ†่ฏฅ็Žฏๅขƒ๏ผŒ @@ -820,7 +840,7 @@ I solemnly swear ๐Ÿบ -## ๆ›ฟไปฃๆ–นๆกˆ +## ๆ›ฟไปฃๆ–นๆกˆ { #alternatives } ่ฟ™ๆ˜ฏไธ€ไธช็ฎ€ๅ•็š„ๆŒ‡ๅ—๏ผŒๅฏไปฅๅธฎๅŠฉไฝ ๅ…ฅ้—จๅนถๆ•™ไผšไฝ ๅฆ‚ไฝ•็†่งฃไธ€ๅˆ‡**ๅบ•ๅฑ‚**็š„ไธœ่ฅฟใ€‚ @@ -837,7 +857,7 @@ I solemnly swear ๐Ÿบ * ็กฎไฟไฝ ๆœ‰ไธ€ไธช**็กฎๅˆ‡**็š„่ฝฏไปถๅŒ…ๅ’Œ็‰ˆๆœฌ้›†ๅˆๆฅๅฎ‰่ฃ…๏ผŒๅŒ…ๆ‹ฌๅฎƒไปฌ็š„ไพ่ต–้กน๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅ็กฎไฟๅœจ็”Ÿไบงไธญ่ฟ่กŒไฝ ็š„ๅทฅ็จ‹ไธŽๅœจๅผ€ๅ‘ๆ—ถๅœจไฝ ็š„่ฎก็ฎ—ๆœบไธŠ่ฟ่กŒ็š„ๅทฅ็จ‹ๅฎŒๅ…จ็›ธๅŒ๏ผŒ่ฟ™่ขซ็งฐไธบ**้”ๅฎš** * ่ฟ˜ๆœ‰ๅพˆๅคšๅ…ถไป–ๅŠŸ่ƒฝ -## ็ป“่ฎบ +## ็ป“่ฎบ { #conclusion } ๅฆ‚ๆžœไฝ ่ฏป่ฟ‡ๅนถ็†่งฃไบ†ๆ‰€ๆœ‰่ฟ™ไบ›๏ผŒ็Žฐๅœจ**ไฝ ๅฏน่™šๆ‹Ÿ็Žฏๅขƒ็š„ไบ†่งฃๆฏ”ๅพˆๅคšๅผ€ๅ‘่€…้ƒฝ่ฆๅคš**ใ€‚๐Ÿค“ diff --git a/scripts/docs.py b/scripts/docs.py index 2c7d6d5e4e..3cf62f084c 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -30,7 +30,7 @@ SUPPORTED_LANGS = { "ru", "tr", "uk", - # "zh", + "zh", "zh-hant", } From cd31576d5704b6aef1bdadc43770238cd88aad2b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Feb 2026 10:40:08 +0000 Subject: [PATCH 173/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5a714d1a03..238a4ff2a2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* ๐ŸŒ Update translations for zh (update-outdated). PR [#14843](https://github.com/fastapi/fastapi/pull/14843) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.5 ### Refactors From 227cb85a03ec6522f641467fbf6af9bc5b1c2e75 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:35:43 +0100 Subject: [PATCH 174/367] =?UTF-8?q?=E2=9C=85=20Fix=20parameterized=20tests?= =?UTF-8?q?=20with=20snapshots=20(#14875)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_path/test_required_str.py | 6 +-- ...est_tutorial001_tutorial002_tutorial003.py | 4 +- ...est_tutorial002_tutorial003_tutorial004.py | 4 +- .../test_tutorial003_tutorial004.py | 4 +- .../test_tutorial010.py | 39 +++++++++---------- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/tests/test_request_params/test_path/test_required_str.py b/tests/test_request_params/test_path/test_required_str.py index 5add058c2b..aecc2eb6c9 100644 --- a/tests/test_request_params/test_path/test_required_str.py +++ b/tests/test_request_params/test_path/test_required_str.py @@ -3,7 +3,7 @@ from typing import Annotated import pytest from fastapi import FastAPI, Path from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot app = FastAPI() @@ -58,8 +58,8 @@ def test_schema(path: str, expected_name: str, expected_title: str): [ { "required": True, - "schema": {"title": expected_title, "type": "string"}, - "name": expected_name, + "schema": {"title": Is(expected_title), "type": "string"}, + "name": Is(expected_name), "in": "path", } ] diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py index 78e5e53a20..18bce279b9 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py @@ -3,7 +3,7 @@ import importlib import pytest from dirty_equals import IsList from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot from ...utils import needs_py310 @@ -212,7 +212,7 @@ def test_openapi_schema(client: TestClient, mod_name: str): "title": "Tax", "anyOf": [{"type": "number"}, {"type": "null"}], }, - "tags": tags_schema, + "tags": Is(tags_schema), }, "required": [ "name", diff --git a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py index f79d38b831..68e046ac5a 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py @@ -2,7 +2,7 @@ import importlib import pytest from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot @pytest.fixture( @@ -59,7 +59,7 @@ def test_openapi_schema(client: TestClient, mod_name: str): "responses": { "200": { "description": "Successful Response", - "content": response_content, + "content": Is(response_content), } }, "summary": "Read Items", diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py index 8e86cd8a51..c13a3c38c8 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py @@ -4,7 +4,7 @@ from textwrap import dedent import pytest from dirty_equals import IsList from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot from ...utils import needs_py310 @@ -75,7 +75,7 @@ def test_openapi_schema(client: TestClient, mod_name: str): "/items/": { "post": { "summary": "Create an item", - "description": DESCRIPTIONS[mod_name], + "description": Is(DESCRIPTIONS[mod_name]), "operationId": "create_item_items__post", "requestBody": { "content": { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index 395f795184..efe9f1fa6b 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -3,7 +3,7 @@ import importlib import pytest from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot from ...utils import needs_py310 @@ -66,6 +66,23 @@ def test_query_params_str_validations_item_query_nonregexquery(client: TestClien def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text + + parameters_schema = { + "anyOf": [ + { + "type": "string", + "minLength": 3, + "maxLength": 50, + "pattern": "^fixedquery$", + }, + {"type": "null"}, + ], + "title": "Query string", + "description": "Query string for the items to search in the database that have a good match", + # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. + **({"deprecated": True} if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) else {}), + } + assert response.json() == snapshot( { "openapi": "3.1.0", @@ -96,25 +113,7 @@ def test_openapi_schema(client: TestClient): "description": "Query string for the items to search in the database that have a good match", "required": False, "deprecated": True, - "schema": { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", - "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - }, + "schema": Is(parameters_schema), "name": "item-query", "in": "query", } From 0c0f6332e29f62001c94bf5c2d77ff1d79b73bf9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Feb 2026 15:36:09 +0000 Subject: [PATCH 175/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 238a4ff2a2..fb404fcbda 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * ๐ŸŒ Update translations for zh (update-outdated). PR [#14843](https://github.com/fastapi/fastapi/pull/14843) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* โœ… Fix parameterized tests with snapshots. PR [#14875](https://github.com/fastapi/fastapi/pull/14875) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.128.5 ### Refactors From ed2512a5ec33d9d70f7a9ef2e5f9fe52d3b77ab2 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:31:57 +0100 Subject: [PATCH 176/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20`on=5Fstartup`=20a?= =?UTF-8?q?nd=20`on=5Fshutdown`=20parameters=20of=20`APIRouter`=20(#14873)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- fastapi/routing.py | 21 ++++++------- tests/test_router_events.py | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index 0b4d28873c..16a89ef3e3 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -952,16 +952,6 @@ class APIRouter(routing.Router): ), ] = Default(generate_unique_id), ) -> None: - # Handle on_startup/on_shutdown locally since Starlette removed support - # Ref: https://github.com/Kludex/starlette/pull/3117 - # TODO: deprecate this once the lifespan (or alternative) interface is improved - self.on_startup: list[Callable[[], Any]] = ( - [] if on_startup is None else list(on_startup) - ) - self.on_shutdown: list[Callable[[], Any]] = ( - [] if on_shutdown is None else list(on_shutdown) - ) - # Determine the lifespan context to use if lifespan is None: # Use the default lifespan that runs on_startup/on_shutdown handlers @@ -985,6 +975,17 @@ class APIRouter(routing.Router): assert not prefix.endswith("/"), ( "A path prefix must not end with '/', as the routes will start with '/'" ) + + # Handle on_startup/on_shutdown locally since Starlette removed support + # Ref: https://github.com/Kludex/starlette/pull/3117 + # TODO: deprecate this once the lifespan (or alternative) interface is improved + self.on_startup: list[Callable[[], Any]] = ( + [] if on_startup is None else list(on_startup) + ) + self.on_shutdown: list[Callable[[], Any]] = ( + [] if on_shutdown is None else list(on_shutdown) + ) + self.prefix = prefix self.tags: list[Union[str, Enum]] = tags or [] self.dependencies = list(dependencies or []) diff --git a/tests/test_router_events.py b/tests/test_router_events.py index 65f2f521c1..a47d119139 100644 --- a/tests/test_router_events.py +++ b/tests/test_router_events.py @@ -317,3 +317,63 @@ def test_router_async_generator_lifespan(state: State) -> None: assert response.json() == {"message": "Hello World"} assert state.app_startup is True assert state.app_shutdown is True + + +def test_startup_shutdown_handlers_as_parameters(state: State) -> None: + """Test that startup/shutdown handlers passed as parameters to FastAPI are called correctly.""" + + def app_startup() -> None: + state.app_startup = True + + def app_shutdown() -> None: + state.app_shutdown = True + + app = FastAPI(on_startup=[app_startup], on_shutdown=[app_shutdown]) + + @app.get("/") + def main() -> dict[str, str]: + return {"message": "Hello World"} + + def router_startup() -> None: + state.router_startup = True + + def router_shutdown() -> None: + state.router_shutdown = True + + router = APIRouter(on_startup=[router_startup], on_shutdown=[router_shutdown]) + + def sub_router_startup() -> None: + state.sub_router_startup = True + + def sub_router_shutdown() -> None: + state.sub_router_shutdown = True + + sub_router = APIRouter( + on_startup=[sub_router_startup], on_shutdown=[sub_router_shutdown] + ) + + router.include_router(sub_router) + app.include_router(router) + + assert state.app_startup is False + assert state.router_startup is False + assert state.sub_router_startup is False + assert state.app_shutdown is False + assert state.router_shutdown is False + assert state.sub_router_shutdown is False + with TestClient(app) as client: + assert state.app_startup is True + assert state.router_startup is True + assert state.sub_router_startup is True + assert state.app_shutdown is False + assert state.router_shutdown is False + assert state.sub_router_shutdown is False + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {"message": "Hello World"} + assert state.app_startup is True + assert state.router_startup is True + assert state.sub_router_startup is True + assert state.app_shutdown is True + assert state.router_shutdown is True + assert state.sub_router_shutdown is True From 0a4033aeeedcf8243502794648b25059e950e499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 9 Feb 2026 18:19:22 +0100 Subject: [PATCH 177/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fb404fcbda..9a1751d3a2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.6 + ### Translations * ๐ŸŒ Update translations for zh (update-outdated). PR [#14843](https://github.com/fastapi/fastapi/pull/14843) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 1176856891..95e57e2eba 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.5" +__version__ = "0.128.6" from starlette import status as status From 4e879799dd134e8e634d3e54c0973c0515a32d2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Feb 2026 17:21:32 +0000 Subject: [PATCH 178/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9a1751d3a2..0abdfe6f28 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* ๐Ÿ› Fix `on_startup` and `on_shutdown` parameters of `APIRouter`. PR [#14873](https://github.com/fastapi/fastapi/pull/14873) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.128.6 ### Translations From fbca586c1df1940f07ff8051716ec5a9ba97b149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 9 Feb 2026 18:25:04 +0100 Subject: [PATCH 179/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0abdfe6f28..b151ff8525 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,12 +7,12 @@ hide: ## Latest Changes +## 0.128.6 + ### Fixes * ๐Ÿ› Fix `on_startup` and `on_shutdown` parameters of `APIRouter`. PR [#14873](https://github.com/fastapi/fastapi/pull/14873) by [@YuriiMotov](https://github.com/YuriiMotov). -## 0.128.6 - ### Translations * ๐ŸŒ Update translations for zh (update-outdated). PR [#14843](https://github.com/fastapi/fastapi/pull/14843) by [@tiangolo](https://github.com/tiangolo). From 8fd291465b1211f88958c86779b9759b1268fddd Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 9 Feb 2026 18:38:48 +0100 Subject: [PATCH 180/367] =?UTF-8?q?=F0=9F=94=A7=20Configure=20`test`=20wor?= =?UTF-8?q?kflow=20to=20run=20tests=20with=20`inline-snapshot=3Dreview`=20?= =?UTF-8?q?(#14876)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e314b6a041..3fb837c04d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,7 @@ on: env: UV_NO_SYNC: true + INLINE_SNAPSHOT_DEFAULT_FLAGS: review jobs: changes: From e94028ab60d18080810910352bc9129e8046c92d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Feb 2026 17:39:11 +0000 Subject: [PATCH 181/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b151ff8525..71dc7bb74a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.128.6 ### Fixes From 66dc695071d8a040db72d5546eb848a58b41152e Mon Sep 17 00:00:00 2001 From: rijenkii Date: Tue, 10 Feb 2026 17:52:24 +0700 Subject: [PATCH 182/367] =?UTF-8?q?=E2=9C=A8=20Replace=20`dict`=20by=20`Ma?= =?UTF-8?q?pping`=20on=20`HTTPException.headers`=20(#12997)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- fastapi/exceptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index 62b4674de3..9924d0e2bd 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -1,4 +1,4 @@ -from collections.abc import Sequence +from collections.abc import Mapping, Sequence from typing import Annotated, Any, Optional, TypedDict, Union from annotated_doc import Doc @@ -68,7 +68,7 @@ class HTTPException(StarletteHTTPException): ), ] = None, headers: Annotated[ - Optional[dict[str, str]], + Optional[Mapping[str, str]], Doc( """ Any headers to send to the client in the response. From 363aced75a26a5247855ea41b2bee53481be4d52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 10:52:51 +0000 Subject: [PATCH 183/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 71dc7bb74a..fff7ccc332 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* โœจ Replace `dict` by `Mapping` on `HTTPException.headers`. PR [#12997](https://github.com/fastapi/fastapi/pull/12997) by [@rijenkii](https://github.com/rijenkii). + ### Internal * ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). From df950111fe97c8040e49f4600d6f563456bbdba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20S=C3=A1nchez=20Castro?= <72013291+JavierSanchezCastro@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:58:40 +0100 Subject: [PATCH 184/367] =?UTF-8?q?=E2=9C=A8=20Show=20a=20clear=20error=20?= =?UTF-8?q?on=20attempt=20to=20include=20router=20into=20itself=20(#14258)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Javier Sรกnchez Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/routing.py | 4 ++++ tests/test_router_circular_import.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/test_router_circular_import.py diff --git a/fastapi/routing.py b/fastapi/routing.py index 16a89ef3e3..ed873fda8c 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1393,6 +1393,10 @@ class APIRouter(routing.Router): app.include_router(internal_router) ``` """ + assert self is not router, ( + "Cannot include the same APIRouter instance into itself. " + "Did you mean to include a different router?" + ) if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" assert not prefix.endswith("/"), ( diff --git a/tests/test_router_circular_import.py b/tests/test_router_circular_import.py new file mode 100644 index 0000000000..492a26d005 --- /dev/null +++ b/tests/test_router_circular_import.py @@ -0,0 +1,12 @@ +import pytest +from fastapi import APIRouter + + +def test_router_circular_import(): + router = APIRouter() + + with pytest.raises( + AssertionError, + match="Cannot include the same APIRouter instance into itself. Did you mean to include a different router?", + ): + router.include_router(router) From 8bdb0d22423fdfbc4e12eee1baa339ffa960471d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 10:59:10 +0000 Subject: [PATCH 185/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fff7ccc332..495bf83b4c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Features +* โœจ Show a clear error on attempt to include router into itself. PR [#14258](https://github.com/fastapi/fastapi/pull/14258) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro). * โœจ Replace `dict` by `Mapping` on `HTTPException.headers`. PR [#12997](https://github.com/fastapi/fastapi/pull/12997) by [@rijenkii](https://github.com/rijenkii). ### Internal From 25270fcee0c71c3bc661e40501fa3838beb6d99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 10 Feb 2026 03:36:53 -0800 Subject: [PATCH 186/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20reading?= =?UTF-8?q?=20files=20in=20memory,=20do=20it=20sequentially=20instead=20of?= =?UTF-8?q?=20(fake)=20parallel=20(#14884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 80f9c76e90..23d8cd9fbf 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,7 +1,7 @@ import dataclasses import inspect import sys -from collections.abc import Coroutine, Mapping, Sequence +from collections.abc import Mapping, Sequence from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass @@ -15,7 +15,6 @@ from typing import ( cast, ) -import anyio from fastapi import params from fastapi._compat import ( ModelField, @@ -903,16 +902,8 @@ async def _extract_form_body( # For types assert isinstance(value, sequence_types) results: list[Union[bytes, str]] = [] - - async def process_fn( - fn: Callable[[], Coroutine[Any, Any, Any]], - ) -> None: - result = await fn() - results.append(result) # noqa: B023 - - async with anyio.create_task_group() as tg: - for sub_value in value: - tg.start_soon(process_fn, sub_value.read) + for sub_value in value: + results.append(await sub_value.read()) value = serialize_sequence_value(field=field, value=results) if value is not None: values[get_validation_alias(field)] = value From 3f1cc8f8f5fabaf85a0c3d9428004001af2486a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 11:37:19 +0000 Subject: [PATCH 187/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 495bf83b4c..72be2c6bd3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -12,6 +12,10 @@ hide: * โœจ Show a clear error on attempt to include router into itself. PR [#14258](https://github.com/fastapi/fastapi/pull/14258) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro). * โœจ Replace `dict` by `Mapping` on `HTTPException.headers`. PR [#12997](https://github.com/fastapi/fastapi/pull/12997) by [@rijenkii](https://github.com/rijenkii). +### Refactors + +* โ™ป๏ธ Simplify reading files in memory, do it sequentially instead of (fake) parallel. PR [#14884](https://github.com/fastapi/fastapi/pull/14884) by [@tiangolo](https://github.com/tiangolo). + ### Internal * ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). From 38f965985e3111162070136acf92b0843c1d48b8 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Tue, 10 Feb 2026 06:46:48 -0500 Subject: [PATCH 188/367] =?UTF-8?q?=E2=9C=85=20Test=20order=20for=20the=20?= =?UTF-8?q?submitted=20byte=20Files=20(#14828)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Valentyn Druzhynin Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastiรกn Ramรญrez --- ..._bytes_file_order_preserved_issue_14811.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/test_list_bytes_file_order_preserved_issue_14811.py diff --git a/tests/test_list_bytes_file_order_preserved_issue_14811.py b/tests/test_list_bytes_file_order_preserved_issue_14811.py new file mode 100644 index 0000000000..399235bdbf --- /dev/null +++ b/tests/test_list_bytes_file_order_preserved_issue_14811.py @@ -0,0 +1,46 @@ +""" +Regression test: preserve order when using list[bytes] + File() +See https://github.com/fastapi/fastapi/discussions/14811 +Related: PR #3372 +""" + +from typing import Annotated + +import anyio +import pytest +from fastapi import FastAPI, File +from fastapi.testclient import TestClient +from starlette.datastructures import UploadFile as StarletteUploadFile + + +def test_list_bytes_file_preserves_order( + monkeypatch: pytest.MonkeyPatch, +) -> None: + app = FastAPI() + + @app.post("/upload") + async def upload(files: Annotated[list[bytes], File()]): + # return something that makes order obvious + return [b[0] for b in files] + + original_read = StarletteUploadFile.read + + async def patched_read(self: StarletteUploadFile, size: int = -1) -> bytes: + # Make the FIRST file slower *deterministically* + if self.filename == "slow.txt": + await anyio.sleep(0.05) + return await original_read(self, size) + + monkeypatch.setattr(StarletteUploadFile, "read", patched_read) + + client = TestClient(app) + + files = [ + ("files", ("slow.txt", b"A" * 10, "text/plain")), + ("files", ("fast.txt", b"B" * 10, "text/plain")), + ] + r = client.post("/upload", files=files) + assert r.status_code == 200, r.text + + # Must preserve request order: slow first, fast second + assert r.json() == [ord("A"), ord("B")] From 1133a4594d96cd4c26d734f74444110ec9260405 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 11:47:26 +0000 Subject: [PATCH 189/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 72be2c6bd3..ea027ae6f6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* โœ… Test order for the submitted byte Files. PR [#14828](https://github.com/fastapi/fastapi/pull/14828) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.128.6 From ca76a4eba9bb9ddd082b6d16f14d8b0d7977235b Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:48:27 +0100 Subject: [PATCH 190/367] =?UTF-8?q?=F0=9F=93=9D=20Use=20`dfn`=20tag=20for?= =?UTF-8?q?=20definitions=20instead=20of=20`abbr`=20in=20docs=20(#14744)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Sebastiรกn Ramรญrez --- README.md | 10 +++++----- docs/en/docs/advanced/dataclasses.md | 2 +- .../advanced/path-operation-advanced-configuration.md | 2 +- docs/en/docs/alternatives.md | 8 ++++---- docs/en/docs/css/custom.css | 5 +++++ docs/en/docs/deployment/docker.md | 2 +- docs/en/docs/deployment/https.md | 2 +- docs/en/docs/features.md | 10 +++++----- docs/en/docs/index.md | 10 +++++----- docs/en/docs/python-types.md | 10 +++++----- docs/en/docs/tutorial/cookie-param-models.md | 8 ++++---- .../tutorial/dependencies/dependencies-with-yield.md | 2 +- docs/en/docs/tutorial/dependencies/index.md | 2 +- docs/en/docs/tutorial/dependencies/sub-dependencies.md | 2 +- docs/en/docs/tutorial/first-steps.md | 2 +- docs/en/docs/tutorial/path-operation-configuration.md | 4 ++-- docs/en/docs/tutorial/path-params.md | 8 ++++---- docs/en/docs/tutorial/query-params-str-validations.md | 10 +++++----- docs/en/docs/tutorial/query-params.md | 2 +- docs/en/docs/tutorial/request-forms.md | 2 +- docs/en/docs/tutorial/response-model.md | 2 +- docs/en/docs/tutorial/schema-extra-example.md | 2 +- docs/en/docs/virtual-environments.md | 2 +- 23 files changed, 57 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 963de51edf..16d149f8fe 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The key features are: * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). * **Fast to code**: Increase the speed to develop features by about 200% to 300%. * * **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * -* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. * **Easy**: Designed to be easy to use and learn. Less time reading docs. * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **Robust**: Get production-ready code. With automatic interactive documentation. @@ -371,7 +371,7 @@ item: Item * Validation of data: * Automatic and clear errors when the data is invalid. * Validation even for deeply nested JSON objects. -* Conversion of input data: coming from the network to Python data and types. Reading from: +* Conversion of input data: coming from the network to Python data and types. Reading from: * JSON. * Path parameters. * Query parameters. @@ -379,7 +379,7 @@ item: Item * Headers. * Forms. * Files. -* Conversion of output data: converting from Python data and types to network data (as JSON): +* Conversion of output data: converting from Python data and types to network data (as JSON): * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). * `datetime` objects. * `UUID` objects. @@ -442,7 +442,7 @@ For a more complete example including more features, see the Dependency Injection** system. +* A very powerful and easy to use **Dependency Injection** system. * Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. * More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). * **GraphQL** integration with Strawberry and other libraries. @@ -527,7 +527,7 @@ Used by Starlette: * httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. -* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. Used by FastAPI: diff --git a/docs/en/docs/advanced/dataclasses.md b/docs/en/docs/advanced/dataclasses.md index dbc91409a5..be85303bfb 100644 --- a/docs/en/docs/advanced/dataclasses.md +++ b/docs/en/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ In that case, you can simply swap the standard `dataclasses` with `pydantic.data 6. Here we are returning a dictionary that contains `items` which is a list of dataclasses. - FastAPI is still capable of serializing the data to JSON. + FastAPI is still capable of serializing the data to JSON. 7. Here the `response_model` is using a type annotation of a list of `Author` dataclasses. diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index e0e3c96a0e..3d7bfdee59 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -141,7 +141,7 @@ You could do that with `openapi_extra`: {* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} -In this example, we didn't declare any Pydantic model. In fact, the request body is not even parsed as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way. +In this example, we didn't declare any Pydantic model. In fact, the request body is not even parsed as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way. Nevertheless, we can declare the expected schema for the request body. diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index e656815430..73a6c1cb59 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -137,7 +137,7 @@ There are several Flask REST frameworks, but after investing the time and work i ### Marshmallow { #marshmallow } -One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc. +One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc. Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data. @@ -145,7 +145,7 @@ Without a data validation system, you would have to do all the checks by hand, i These features are what Marshmallow was built to provide. It is a great library, and I have used it a lot before. -But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow. +But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow. /// check | Inspired **FastAPI** to @@ -155,7 +155,7 @@ Use code to define "schemas" that provide data types and validation, automatical ### Webargs { #webargs } -Another big feature required by APIs is parsing data from incoming requests. +Another big feature required by APIs is parsing data from incoming requests. Webargs is a tool that was made to provide that on top of several frameworks, including Flask. @@ -419,7 +419,7 @@ Handle all the data validation, data serialization and automatic model documenta ### Starlette { #starlette } -Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. +Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. It is very simple and intuitive. It's designed to be easily extensible, and have modular components. diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index 87111ff64e..7c50dbd9be 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -203,3 +203,8 @@ Inspired by Termynal's CSS tricks with modifications -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; } + +.md-typeset dfn { + border-bottom: .05rem dotted var(--md-default-fg-color--light); + cursor: help; +} diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index 7219f3afca..0f15a60a47 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -454,7 +454,7 @@ Without using containers, making applications run on startup and with restarts c ## Replication - Number of Processes { #replication-number-of-processes } -If you have a cluster of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container. +If you have a cluster of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container. One of those distributed container management systems like Kubernetes normally has some integrated way of handling **replication of containers** while still supporting **load balancing** for the incoming requests. All at the **cluster level**. diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md index a249a36721..6ae1228b9a 100644 --- a/docs/en/docs/deployment/https.md +++ b/docs/en/docs/deployment/https.md @@ -65,7 +65,7 @@ Here's an example of how an HTTPS API could look like, step by step, paying atte It would probably all start by you **acquiring** some **domain name**. Then, you would configure it in a DNS server (possibly your same cloud provider). -You would probably get a cloud server (a virtual machine) or something similar, and it would have a fixed **public IP address**. +You would probably get a cloud server (a virtual machine) or something similar, and it would have a fixed **public IP address**. In the DNS server(s) you would configure a record (an "`A record`") to point **your domain** to the public **IP address of your server**. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index a345e4a0e3..307607ad7f 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -6,7 +6,7 @@ ### Based on open standards { #based-on-open-standards } -* OpenAPI for API creation, including declarations of path operations, parameters, request bodies, security, etc. +* OpenAPI for API creation, including declarations of path operations, parameters, request bodies, security, etc. * Automatic data model documentation with JSON Schema (as OpenAPI itself is based on JSON Schema). * Designed around these standards, after a meticulous study. Instead of an afterthought layer on top. * This also allows using automatic **client code generation** in many languages. @@ -136,7 +136,7 @@ All built as reusable tools and components that are easy to integrate with your ### Dependency Injection { #dependency-injection } -FastAPI includes an extremely easy to use, but extremely powerful Dependency Injection system. +FastAPI includes an extremely easy to use, but extremely powerful Dependency Injection system. * Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**. * All **automatically handled** by the framework. @@ -153,8 +153,8 @@ Any integration is designed to be so simple to use (with dependencies) that you ### Tested { #tested } -* 100% test coverage. -* 100% type annotated code base. +* 100% test coverage. +* 100% type annotated code base. * Used in production applications. ## Starlette features { #starlette-features } @@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on * **No brainfuck**: * No new schema definition micro-language to learn. * If you know Python types you know how to use Pydantic. -* Plays nicely with your **IDE/linter/brain**: +* Plays nicely with your **IDE/linter/brain**: * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. * Validate **complex structures**: * Use of hierarchical Pydantic models, Python `typing`โ€™s `List` and `Dict`, etc. diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index ff0f4e9d9d..7f9d5efbf2 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -40,7 +40,7 @@ The key features are: * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). * **Fast to code**: Increase the speed to develop features by about 200% to 300%. * * **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * -* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. * **Easy**: Designed to be easy to use and learn. Less time reading docs. * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **Robust**: Get production-ready code. With automatic interactive documentation. @@ -368,7 +368,7 @@ item: Item * Validation of data: * Automatic and clear errors when the data is invalid. * Validation even for deeply nested JSON objects. -* Conversion of input data: coming from the network to Python data and types. Reading from: +* Conversion of input data: coming from the network to Python data and types. Reading from: * JSON. * Path parameters. * Query parameters. @@ -376,7 +376,7 @@ item: Item * Headers. * Forms. * Files. -* Conversion of output data: converting from Python data and types to network data (as JSON): +* Conversion of output data: converting from Python data and types to network data (as JSON): * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). * `datetime` objects. * `UUID` objects. @@ -439,7 +439,7 @@ For a more complete example including more features, see the Dependency Injection** system. +* A very powerful and easy to use **Dependency Injection** system. * Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. * More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). * **GraphQL** integration with Strawberry and other libraries. @@ -524,7 +524,7 @@ Used by Starlette: * httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. -* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. Used by FastAPI: diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index b685deef29..6de170ada4 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -2,7 +2,7 @@ Python has support for optional "type hints" (also called "type annotations"). -These **"type hints"** or annotations are a special syntax that allow declaring the type of a variable. +These **"type hints"** or annotations are a special syntax that allow declaring the type of a variable. By declaring types for your variables, editors and tools can give you better support. @@ -34,7 +34,7 @@ The function does the following: * Takes a `first_name` and `last_name`. * Converts the first letter of each one to upper case with `title()`. -* Concatenates them with a space in the middle. +* Concatenates them with a space in the middle. {* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} @@ -222,7 +222,7 @@ You can declare that a variable can be any of **several types**, for example, an In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept. -In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a vertical bar (`|`). +In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a vertical bar (`|`). //// tab | Python 3.10+ @@ -336,7 +336,7 @@ And the same as with previous Python versions, from the `typing` module: * `Optional` * ...and others. -In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the vertical bar (`|`) to declare unions of types, that's a lot better and simpler. +In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the vertical bar (`|`) to declare unions of types, that's a lot better and simpler. //// @@ -411,7 +411,7 @@ Pydantic has a special behavior when you use `Optional` or `Union[Something, Non ## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations } -Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`. +Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`. Since Python 3.9, `Annotated` is a part of the standard library, so you can import it from `typing`. diff --git a/docs/en/docs/tutorial/cookie-param-models.md b/docs/en/docs/tutorial/cookie-param-models.md index 016a65d7f0..609838f766 100644 --- a/docs/en/docs/tutorial/cookie-param-models.md +++ b/docs/en/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ But even if you **fill the data** and click "Execute", because the docs UI works In some special use cases (probably not very common), you might want to **restrict** the cookies that you want to receive. -Your API now has the power to control its own cookie consent. ๐Ÿคช๐Ÿช +Your API now has the power to control its own cookie consent. ๐Ÿคช๐Ÿช You can use Pydantic's model configuration to `forbid` any `extra` fields: @@ -54,9 +54,9 @@ You can use Pydantic's model configuration to `forbid` any `extra` fields: If a client tries to send some **extra cookies**, they will receive an **error** response. -Poor cookie banners with all their effort to get your consent for the API to reject it. ๐Ÿช +Poor cookie banners with all their effort to get your consent for the API to reject it. ๐Ÿช -For example, if the client tries to send a `santa_tracker` cookie with a value of `good-list-please`, the client will receive an **error** response telling them that the `santa_tracker` cookie is not allowed: +For example, if the client tries to send a `santa_tracker` cookie with a value of `good-list-please`, the client will receive an **error** response telling them that the `santa_tracker` cookie is not allowed: ```json { @@ -73,4 +73,4 @@ For example, if the client tries to send a `santa_tracker` cookie with a value o ## Summary { #summary } -You can use **Pydantic models** to declare **cookies** in **FastAPI**. ๐Ÿ˜Ž +You can use **Pydantic models** to declare **cookies** in **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index d9f3345619..cfcd961baa 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Dependencies with yield { #dependencies-with-yield } -FastAPI supports dependencies that do some extra steps after finishing. +FastAPI supports dependencies that do some extra steps after finishing. To do this, use `yield` instead of `return`, and write the extra steps (code) after. diff --git a/docs/en/docs/tutorial/dependencies/index.md b/docs/en/docs/tutorial/dependencies/index.md index d1116b2be0..4a1bb774d9 100644 --- a/docs/en/docs/tutorial/dependencies/index.md +++ b/docs/en/docs/tutorial/dependencies/index.md @@ -1,6 +1,6 @@ # Dependencies { #dependencies } -**FastAPI** has a very powerful but intuitive **Dependency Injection** system. +**FastAPI** has a very powerful but intuitive **Dependency Injection** system. It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**. diff --git a/docs/en/docs/tutorial/dependencies/sub-dependencies.md b/docs/en/docs/tutorial/dependencies/sub-dependencies.md index 967bffda79..b9a4e3ce74 100644 --- a/docs/en/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/sub-dependencies.md @@ -58,7 +58,7 @@ query_extractor --> query_or_cookie_extractor --> read_query If one of your dependencies is declared multiple times for the same *path operation*, for example, multiple dependencies have a common sub-dependency, **FastAPI** will know to call that sub-dependency only once per request. -And it will save the returned value in a "cache" and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request. +And it will save the returned value in a "cache" and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request. In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter `use_cache=False` when using `Depends`: diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index df8e91ecd4..a3263593dd 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -271,7 +271,7 @@ We are going to call them "**operations**" too. The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to: * the path `/` -* using a get operation +* using a get operation /// info | `@decorator` Info diff --git a/docs/en/docs/tutorial/path-operation-configuration.md b/docs/en/docs/tutorial/path-operation-configuration.md index 1bb7ee5544..f5c603880a 100644 --- a/docs/en/docs/tutorial/path-operation-configuration.md +++ b/docs/en/docs/tutorial/path-operation-configuration.md @@ -56,7 +56,7 @@ You can add a `summary` and `description`: ## Description from docstring { #description-from-docstring } -As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function docstring and **FastAPI** will read it from there. +As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function docstring and **FastAPI** will read it from there. You can write Markdown in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation). @@ -90,7 +90,7 @@ So, if you don't provide one, **FastAPI** will automatically generate one of "Su ## Deprecate a *path operation* { #deprecate-a-path-operation } -If you need to mark a *path operation* as deprecated, but without removing it, pass the parameter `deprecated`: +If you need to mark a *path operation* as deprecated, but without removing it, pass the parameter `deprecated`: {* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md index ea4307900c..cf312f1fef 100644 --- a/docs/en/docs/tutorial/path-params.md +++ b/docs/en/docs/tutorial/path-params.md @@ -26,7 +26,7 @@ This will give you editor support inside of your function, with error checks, co /// -## Data conversion { #data-conversion } +## Data conversion { #data-conversion } If you run this example and open your browser at http://127.0.0.1:8000/items/3, you will see a response of: @@ -38,7 +38,7 @@ If you run this example and open your browser at "parsing". +So, with that type declaration, **FastAPI** gives you automatic request "parsing". /// @@ -144,7 +144,7 @@ Then create class attributes with fixed values, which will be the available vali /// tip -If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models. +If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models. /// @@ -242,7 +242,7 @@ In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double With **FastAPI**, by using short, intuitive and standard Python type declarations, you get: * Editor support: error checks, autocompletion, etc. -* Data "parsing" +* Data "parsing" * Data validation * API annotation and automatic documentation diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index 4b8cc9d297..1846ad56a9 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -109,7 +109,7 @@ FastAPI will now: ## Alternative (old): `Query` as the default value { #alternative-old-query-as-the-default-value } -Previous versions of FastAPI (before 0.95.0) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you. +Previous versions of FastAPI (before 0.95.0) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you. /// tip @@ -192,7 +192,7 @@ You can also add a parameter `min_length`: ## Add regular expressions { #add-regular-expressions } -You can define a regular expression `pattern` that the parameter should match: +You can define a regular expression `pattern` that the parameter should match: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -372,7 +372,7 @@ Then you can declare an `alias`, and that alias is what will be used to find the Now let's say you don't like this parameter anymore. -You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as deprecated. +You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as deprecated. Then pass the parameter `deprecated=True` to `Query`: @@ -402,7 +402,7 @@ Pydantic also has ISBN book number or with `imdb-` for an IMDB movie URL ID: +For example, this custom validator checks that the item ID starts with `isbn-` for an ISBN book number or with `imdb-` for an IMDB movie URL ID: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -436,7 +436,7 @@ Did you notice? a string using `value.startswith()` can take a tuple, and it wil #### A Random Item { #a-random-item } -With `data.items()` we get an iterable object with tuples containing the key and value for each dictionary item. +With `data.items()` we get an iterable object with tuples containing the key and value for each dictionary item. We convert this iterable object into a proper `list` with `list(data.items())`. diff --git a/docs/en/docs/tutorial/query-params.md b/docs/en/docs/tutorial/query-params.md index 3c9c225fb0..eeb59f9258 100644 --- a/docs/en/docs/tutorial/query-params.md +++ b/docs/en/docs/tutorial/query-params.md @@ -24,7 +24,7 @@ But when you declare them with Python types (in the example above, as `int`), th All the same process that applied for path parameters also applies for query parameters: * Editor support (obviously) -* Data "parsing" +* Data "parsing" * Data validation * Automatic documentation diff --git a/docs/en/docs/tutorial/request-forms.md b/docs/en/docs/tutorial/request-forms.md index d743c2ec4e..d63ffd5655 100644 --- a/docs/en/docs/tutorial/request-forms.md +++ b/docs/en/docs/tutorial/request-forms.md @@ -28,7 +28,7 @@ Create form parameters the same way you would for `Body` or `Query`: For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields. -The spec requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON. +The spec requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON. With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc. diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md index b287cdf50a..ac35390fad 100644 --- a/docs/en/docs/tutorial/response-model.md +++ b/docs/en/docs/tutorial/response-model.md @@ -201,7 +201,7 @@ This will also work because `RedirectResponse` is a subclass of `Response`, and But when you return some other arbitrary object that is not a valid Pydantic type (e.g. a database object) and you annotate it like that in the function, FastAPI will try to create a Pydantic response model from that type annotation, and will fail. -The same would happen if you had something like a union between different types where one or more of them are not valid Pydantic types, for example this would fail ๐Ÿ’ฅ: +The same would happen if you had something like a union between different types where one or more of them are not valid Pydantic types, for example this would fail ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index daaea73c87..432f58b1e3 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ You can of course also pass multiple `examples`: When you do this, the examples will be part of the internal **JSON Schema** for that body data. -Nevertheless, at the time of writing this, Swagger UI, the tool in charge of showing the docs UI, doesn't support showing multiple examples for the data in **JSON Schema**. But read below for a workaround. +Nevertheless, at the time of writing this, Swagger UI, the tool in charge of showing the docs UI, doesn't support showing multiple examples for the data in **JSON Schema**. But read below for a workaround. ### OpenAPI-specific `examples` { #openapi-specific-examples } diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md index c02e43ab91..615d7949f9 100644 --- a/docs/en/docs/virtual-environments.md +++ b/docs/en/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Create a Virtual Environment { #create-a-virtual-environment } -When you start working on a Python project **for the first time**, create a virtual environment **inside your project**. +When you start working on a Python project **for the first time**, create a virtual environment **inside your project**. /// tip From ff721017df331de1357270f03f1f03382a50477f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 11:49:54 +0000 Subject: [PATCH 191/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ea027ae6f6..bd4a6726e9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -16,6 +16,10 @@ hide: * โ™ป๏ธ Simplify reading files in memory, do it sequentially instead of (fake) parallel. PR [#14884](https://github.com/fastapi/fastapi/pull/14884) by [@tiangolo](https://github.com/tiangolo). +### Docs + +* ๐Ÿ“ Use `dfn` tag for definitions instead of `abbr` in docs. PR [#14744](https://github.com/fastapi/fastapi/pull/14744) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Internal * โœ… Test order for the submitted byte Files. PR [#14828](https://github.com/fastapi/fastapi/pull/14828) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 81f82fd9558b077017e80adc448fe5f7807d3732 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:56:20 +0100 Subject: [PATCH 192/367] =?UTF-8?q?=F0=9F=94=A7=20Update=20LLM-prompt=20fo?= =?UTF-8?q?r=20`abbr`=20and=20`dfn`=20tags=20(#14747)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastiรกn Ramรญrez --- docs/de/docs/_llm-test.md | 14 ++++---- docs/en/docs/_llm-test.md | 10 +++--- docs/es/docs/_llm-test.md | 14 ++++---- docs/ko/docs/_llm-test.md | 12 +++---- docs/pt/docs/_llm-test.md | 18 +++++----- docs/ru/docs/_llm-test.md | 10 +++--- scripts/general-llm-prompt.md | 64 +++++++++++++---------------------- 7 files changed, 63 insertions(+), 79 deletions(-) diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index 0b95fe3a8d..498a2e5b6a 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -35,7 +35,7 @@ Siehe Abschnitt `### Content of code snippets` im allgemeinen Prompt in `scripts //// tab | Test -Gestern schrieb mein Freund: โ€žWenn man unkorrekt korrekt schreibt, hat man es unkorrekt geschriebenโ€œ. Worauf ich antwortete: โ€žKorrekt, aber โ€šunkorrektโ€˜ ist unkorrekterweise nicht โ€šโ€žunkorrektโ€œโ€˜โ€œ. +Gestern schrieb mein Freund: โ€žWenn man โ€šincorrectlyโ€˜ korrekt schreibt, hat man es falsch geschriebenโ€œ. Worauf ich antwortete: โ€žKorrekt, aber โ€šincorrectlyโ€˜ ist inkorrekterweise nicht โ€šโ€žincorrectlyโ€œโ€˜โ€œ. /// note | Hinweis @@ -202,11 +202,6 @@ Hier einige Dinge, die in HTML-โ€žabbrโ€œ-Elemente gepackt sind (einige sind erf * XWT * PSGI -### Das abbr gibt eine Erklรคrung { #the-abbr-gives-an-explanation } - -* Cluster -* Deep Learning - ### Das abbr gibt eine vollstรคndige Phrase und eine Erklรคrung { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN @@ -224,6 +219,11 @@ Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/trans //// +## HTML โ€ždfnโ€œ-Elemente { #html-dfn-elements } + +* Cluster +* Deep Learning + ## รœberschriften { #headings } //// tab | Test @@ -248,7 +248,7 @@ Die einzige strenge Regel fรผr รœberschriften ist, dass das LLM den Hash-Teil in Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. -Fรผr einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. +Fรผr einige sprachsspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. //// diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md index d218f7c76f..ff0e24f26c 100644 --- a/docs/en/docs/_llm-test.md +++ b/docs/en/docs/_llm-test.md @@ -202,11 +202,6 @@ Here some things wrapped in HTML "abbr" elements (Some are invented): * XWT * PSGI -### The abbr gives an explanation { #the-abbr-gives-an-explanation } - -* cluster -* Deep Learning - ### The abbr gives a full phrase and an explanation { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN @@ -224,6 +219,11 @@ See section `### HTML abbr elements` in the general prompt in `scripts/translate //// +## HTML "dfn" elements { #html-dfn-elements } + +* cluster +* Deep Learning + ## Headings { #headings } //// tab | Test diff --git a/docs/es/docs/_llm-test.md b/docs/es/docs/_llm-test.md index 591b1008bd..dda425acbc 100644 --- a/docs/es/docs/_llm-test.md +++ b/docs/es/docs/_llm-test.md @@ -202,15 +202,10 @@ Aquรญ algunas cosas envueltas en elementos HTML "abbr" (algunas son inventadas): * XWT * PSGI -### El abbr da una explicaciรณn { #the-abbr-gives-an-explanation } - -* clรบster -* Deep Learning - ### El abbr da una frase completa y una explicaciรณn { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN -* I/O. +* I/O. //// @@ -224,6 +219,11 @@ Consulta la secciรณn `### HTML abbr elements` en el prompt general en `scripts/t //// +## Elementos HTML "dfn" { #html-dfn-elements } + +* clรบster +* Deep Learning + ## Encabezados { #headings } //// tab | Prueba @@ -433,7 +433,7 @@ Para instrucciones especรญficas del idioma, mira p. ej. la secciรณn `### Heading * el motor de plantillas * la anotaciรณn de tipos -* las anotaciones de tipos +* la anotaciรณn de tipos * el worker del servidor * el worker de Uvicorn diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md index 1b828c663e..272af763a5 100644 --- a/docs/ko/docs/_llm-test.md +++ b/docs/ko/docs/_llm-test.md @@ -132,7 +132,7 @@ works(foo="bar") # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ ์ผ๋ถ€ ํ…์ŠคํŠธ /// -/// note Technical details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ ์ผ๋ถ€ ํ…์ŠคํŠธ /// @@ -202,11 +202,6 @@ works(foo="bar") # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ * XWT * PSGI -### abbr๊ฐ€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-an-explanation } - -* cluster -* Deep Learning - ### abbr๊ฐ€ ์ „์ฒด ๋ฌธ๊ตฌ์™€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN @@ -224,6 +219,11 @@ works(foo="bar") # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ //// +## HTML "dfn" ์š”์†Œ { #html-dfn-elements } + +* ํด๋Ÿฌ์Šคํ„ฐ +* ๋”ฅ ๋Ÿฌ๋‹ + ## ์ œ๋ชฉ { #headings } //// tab | ํ…Œ์ŠคํŠธ diff --git a/docs/pt/docs/_llm-test.md b/docs/pt/docs/_llm-test.md index b59292f47c..3a2801fdda 100644 --- a/docs/pt/docs/_llm-test.md +++ b/docs/pt/docs/_llm-test.md @@ -197,15 +197,10 @@ Aqui estรฃo algumas coisas envolvidas em elementos HTML "abbr" (algumas sรฃo inv ### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase } -* GTD -* lt -* XWT -* PSGI - -### O abbr fornece uma explicaรงรฃo { #the-abbr-gives-an-explanation } - -* cluster -* Deep Learning +* GTD +* lt +* XWT +* PSGI ### O abbr fornece uma frase completa e uma explicaรงรฃo { #the-abbr-gives-a-full-phrase-and-an-explanation } @@ -224,6 +219,11 @@ Veja a seรงรฃo `### HTML abbr elements` no prompt geral em `scripts/translate.py //// +## Elementos HTML "dfn" { #html-dfn-elements } + +* cluster +* Deep Learning + ## Tรญtulos { #headings } //// tab | Teste diff --git a/docs/ru/docs/_llm-test.md b/docs/ru/docs/_llm-test.md index 6a0272f3a5..247d3a964f 100644 --- a/docs/ru/docs/_llm-test.md +++ b/docs/ru/docs/_llm-test.md @@ -202,11 +202,6 @@ works(foo="bar") # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ๐ŸŽ‰ * XWT * PSGI -### abbr ะดะฐั‘ั‚ ะพะฑัŠััะฝะตะฝะธะต { #the-abbr-gives-an-explanation } - -* ะบะปะฐัั‚ะตั€ -* ะ“ะปัƒะฑะพะบะพะต ะพะฑัƒั‡ะตะฝะธะต - ### abbr ะดะฐั‘ั‚ ะฟะพะปะฝัƒัŽ ั€ะฐััˆะธั„ั€ะพะฒะบัƒ ะธ ะพะฑัŠััะฝะตะฝะธะต { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN @@ -224,6 +219,11 @@ works(foo="bar") # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚ ๐ŸŽ‰ //// +## HTML-ัะปะตะผะตะฝั‚ั‹ "dfn" { #html-dfn-elements } + +* ะบะปะฐัั‚ะตั€ +* ะ“ะปัƒะฑะพะบะพะต ะพะฑัƒั‡ะตะฝะธะต + ## ะ—ะฐะณะพะปะพะฒะบะธ { #headings } //// tab | ะขะตัั‚ diff --git a/scripts/general-llm-prompt.md b/scripts/general-llm-prompt.md index d45ab8eb07..23926bd8e9 100644 --- a/scripts/general-llm-prompt.md +++ b/scripts/general-llm-prompt.md @@ -353,7 +353,9 @@ Erstelle eine [Virtuelle Umgebung](../virtual-environments.md){.internal-link ta Translate HTML abbr elements (`text`) as follows: -- If the text surrounded by the abbr element is an abbreviation (the text may be surrounded by further HTML or Markdown markup or quotes, for example text or `text` or "text", ignore that further markup when deciding if the text is an abbreviation), and if the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash (-) to the full phrase, followed by the translation of the full phrase. +- The text inside abbr tag may be surrounded by further HTML or Markdown markup or quotes, for example text or `text` or "text". Preserve markup and only translate visible text inside the abbr element. + +- If the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash (-) to the full phrase, followed by the translation of the full phrase. Conversion scheme: @@ -421,45 +423,7 @@ Result (German): ASGI ``` -- If the description is not a full phrase for an abbreviation which the abbr element surrounds, but some other information, then just translate the description. - -Conversion scheme: - -Source (English): - -``` -{text} -``` - -Result: - -``` -{translation of text} -``` - -Examples: - - Source (English): - -``` -path -linter -parsing -0.95.0 -at the time of writing this -``` - -Result (German): - -``` -Pfad -Linter -Parsen -0.95.0 -zum Zeitpunkt als das hier geschrieben wurde -``` - -- If the text surrounded by the abbr element is an abbreviation and the description contains both the full phrase for that abbreviation, and other information, separated by a colon (`:`), then append a dash (`-`) and the translation of the full phrase to the original full phrase and translate the other information. +- If the title of abbr element contains a full phrase for that abbreviation, and other information, separated by a colon (`:`), then append a dash (`-`) and the translation of the full phrase to the original full phrase and translate the other information. Conversion scheme: @@ -526,3 +490,23 @@ Result (German): - If there is an existing translation, and it has ADDITIONAL abbr elements in a sentence, and these additional abbr elements do not exist in the related sentence in the English text, then KEEP those additional abbr elements in the translation. Do not remove them. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text, then also remove the abbr element. The reasoning for this rule is, that such additional abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. These additional abbr elements would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to abbr elements. - Apply above rules also when there is an existing translation! Make sure that all title attributes in abbr elements get properly translated or updated, using the schemes given above. However, leave the ADDITIONAL abbr's described above alone. Do not change their formatting or content. + +### HTML dfn elements + +For HTML dfn elements (`text`), translate the text inside the dfn element and the title attribute. Do not include the original English text in the title attribute. + +Examples: + +Source (English): + +``` +path +linter +``` + +Result (German): + +``` +Pfad +Linter +``` From 65da3dde120c7efee7868890ff3e6e788a860ed6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 11:56:45 +0000 Subject: [PATCH 193/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bd4a6726e9..e46f585090 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* ๐Ÿ”ง Update LLM-prompt for `abbr` and `dfn` tags. PR [#14747](https://github.com/fastapi/fastapi/pull/14747) by [@YuriiMotov](https://github.com/YuriiMotov). * โœ… Test order for the submitted byte Files. PR [#14828](https://github.com/fastapi/fastapi/pull/14828) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). From 6ce5e3e961876c39d8a60a3a2cb4147a6748d116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 10 Feb 2026 04:14:38 -0800 Subject: [PATCH 194/367] =?UTF-8?q?=E2=9C=85=20Tweak=20comment=20in=20test?= =?UTF-8?q?=20to=20reference=20PR=20(#14885)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_list_bytes_file_order_preserved_issue_14811.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_list_bytes_file_order_preserved_issue_14811.py b/tests/test_list_bytes_file_order_preserved_issue_14811.py index 399235bdbf..dbf0a78186 100644 --- a/tests/test_list_bytes_file_order_preserved_issue_14811.py +++ b/tests/test_list_bytes_file_order_preserved_issue_14811.py @@ -1,7 +1,7 @@ """ Regression test: preserve order when using list[bytes] + File() See https://github.com/fastapi/fastapi/discussions/14811 -Related: PR #3372 +Fixed in PR: https://github.com/fastapi/fastapi/pull/14884 """ from typing import Annotated From 5bb3423205daf98f88f14d696d104fea2221028a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 12:15:02 +0000 Subject: [PATCH 195/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e46f585090..bdf15719bf 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* โœ… Tweak comment in test to reference PR. PR [#14885](https://github.com/fastapi/fastapi/pull/14885) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update LLM-prompt for `abbr` and `dfn` tags. PR [#14747](https://github.com/fastapi/fastapi/pull/14747) by [@YuriiMotov](https://github.com/YuriiMotov). * โœ… Test order for the submitted byte Files. PR [#14828](https://github.com/fastapi/fastapi/pull/14828) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ๐Ÿ”ง Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). From 8f82c94de0ff641a239db59e58dfdc6010a4b26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 10 Feb 2026 13:24:38 +0100 Subject: [PATCH 196/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bdf15719bf..87aa6d2612 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.7 + ### Features * โœจ Show a clear error on attempt to include router into itself. PR [#14258](https://github.com/fastapi/fastapi/pull/14258) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 95e57e2eba..a9fe3e9719 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.6" +__version__ = "0.128.7" from starlette import status as status From f0f3e7a113b7771388aef6d4a4cb863ce3890d9c Mon Sep 17 00:00:00 2001 From: Sanjana S <158697809+SanjanaS10@users.noreply.github.com> Date: Tue, 10 Feb 2026 17:56:10 +0530 Subject: [PATCH 197/367] =?UTF-8?q?=F0=9F=93=9D=20Fix=20grammar=20in=20`do?= =?UTF-8?q?cs/en/docs/tutorial/first-steps.md`=20(#14708)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/first-steps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index a3263593dd..ceae6c475e 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -54,7 +54,7 @@ In the output, there's a line with something like: INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -That line shows the URL where your app is being served, in your local machine. +That line shows the URL where your app is being served on your local machine. ### Check it { #check-it } From 93fa935fb8ac1c40488da7bf9b134466588ffaee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Feb 2026 12:26:38 +0000 Subject: [PATCH 198/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 87aa6d2612..bf8850828f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* ๐Ÿ“ Fix grammar in `docs/en/docs/tutorial/first-steps.md`. PR [#14708](https://github.com/fastapi/fastapi/pull/14708) by [@SanjanaS10](https://github.com/SanjanaS10). + ## 0.128.7 ### Features From ffb8965260c71657f26644673f218b99b1315cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 11 Feb 2026 04:33:49 -0800 Subject: [PATCH 199/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20build=20s?= =?UTF-8?q?etup=20for=20`fastapi-slim`,=20deprecate=20it,=20and=20make=20i?= =?UTF-8?q?t=20only=20depend=20on=20`fastapi`=20(#14894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-redistribute.yml | 9 ----- fastapi-slim/README.md | 54 +++++++++++++++++++++++++ pdm_build.py | 28 +++++++++++-- pyproject.toml | 23 +++++++++++ 4 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 fastapi-slim/README.md diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 0491d33ba7..ad9df4bf98 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -12,11 +12,6 @@ on: jobs: test-redistribute: runs-on: ubuntu-latest - strategy: - matrix: - package: - - fastapi - - fastapi-slim steps: - name: Dump GitHub context env: @@ -30,8 +25,6 @@ jobs: - name: Install build dependencies run: pip install build - name: Build source distribution - env: - TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} run: python -m build --sdist - name: Decompress source distribution run: | @@ -41,8 +34,6 @@ jobs: run: | cd dist/fastapi*/ pip install --group tests --editable .[all] - env: - TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} - name: Run source distribution tests run: | cd dist/fastapi*/ diff --git a/fastapi-slim/README.md b/fastapi-slim/README.md new file mode 100644 index 0000000000..e378a9c8c2 --- /dev/null +++ b/fastapi-slim/README.md @@ -0,0 +1,54 @@ +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/fastapi/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints. + +## `fastapi-slim` + +โš ๏ธ Do not install this package. โš ๏ธ + +This package, `fastapi-slim`, does nothing other than depend on `fastapi`. + +All the functionality has been integrated into `fastapi`. + +The only reason this package exists is as a migration path for old projects that used to depend on `fastapi-slim`, so that they can get the latest version of `fastapi`. + +You **should not** install this package. + +Install instead: + +```bash +pip install fastapi +``` + +This package is deprecated and will stop receiving any updates and published versions. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/pdm_build.py b/pdm_build.py index a0eb88eebb..67e71cbb05 100644 --- a/pdm_build.py +++ b/pdm_build.py @@ -3,18 +3,38 @@ from typing import Any from pdm.backend.hooks import Context -TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "fastapi") +TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "typer") def pdm_build_initialize(context: Context) -> None: metadata = context.config.metadata + # Get main version + version = metadata["version"] # Get custom config for the current package, from the env var - config: dict[str, Any] = context.config.data["tool"]["tiangolo"][ + all_configs_config: dict[str, Any] = context.config.data["tool"]["tiangolo"][ "_internal-slim-build" - ]["packages"].get(TIANGOLO_BUILD_PACKAGE) - if not config: + ]["packages"] + + if TIANGOLO_BUILD_PACKAGE not in all_configs_config: return + + config = all_configs_config[TIANGOLO_BUILD_PACKAGE] project_config: dict[str, Any] = config["project"] # Override main [project] configs with custom configs for this package for key, value in project_config.items(): metadata[key] = value + # Get custom build config for the current package + build_config: dict[str, Any] = ( + config.get("tool", {}).get("pdm", {}).get("build", {}) + ) + # Override PDM build config with custom build config for this package + for key, value in build_config.items(): + context.config.build_config[key] = value + # Get main dependencies + dependencies: list[str] = metadata.get("dependencies", []) + # Sync versions in dependencies + new_dependencies = [] + for dep in dependencies: + new_dep = f"{dep}>={version}" + new_dependencies.append(new_dep) + metadata["dependencies"] = new_dependencies diff --git a/pyproject.toml b/pyproject.toml index 4895c2d34e..d8c43f7a48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -202,6 +202,29 @@ source-includes = [ [tool.tiangolo._internal-slim-build.packages.fastapi-slim.project] name = "fastapi-slim" +readme = "fastapi-slim/README.md" +dependencies = [ + "fastapi", +] +optional-dependencies = {} +scripts = {} + +[tool.tiangolo._internal-slim-build.packages.fastapi-slim.tool.pdm.build] +# excludes needs to explicitly exclude the top level python packages, +# otherwise PDM includes them by default +# A "*" glob pattern can't be used here because in PDM internals, the patterns are put +# in a set (unordered, order varies) and each excluded file is assigned one of the +# glob patterns that matches, as the set is unordered, the matched pattern could be "*" +# independent of the order here. And then the internal code would give it a lower score +# than the one for a default included file. +# By not using "*" and explicitly excluding the top level packages, they get a higher +# score than the default inclusion +excludes = ["fastapi", "tests", "pdm_build.py"] +# source-includes needs to explicitly define some value because PDM will check the +# truthy value of the list, and if empty, will include some defaults, including "tests", +# an empty string doesn't match anything, but makes the list truthy, so that PDM +# doesn't override it during the build. +source-includes = [""] [tool.mypy] plugins = ["pydantic.mypy"] From 417f1ee07825c6f4e983629bee6039857197112f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Feb 2026 12:34:12 +0000 Subject: [PATCH 200/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bf8850828f..014bae1abf 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * ๐Ÿ“ Fix grammar in `docs/en/docs/tutorial/first-steps.md`. PR [#14708](https://github.com/fastapi/fastapi/pull/14708) by [@SanjanaS10](https://github.com/SanjanaS10). +### Internal + +* โ™ป๏ธ Update build setup for `fastapi-slim`, deprecate it, and make it only depend on `fastapi`. PR [#14894](https://github.com/fastapi/fastapi/pull/14894) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.7 ### Features From aac30fd7071d79798130137728aeb363c8c5f695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 11 Feb 2026 05:37:09 -0800 Subject: [PATCH 201/367] =?UTF-8?q?=F0=9F=94=A8=20Tweak=20PDM=20hook=20scr?= =?UTF-8?q?ipt=20(#14895)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pdm_build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdm_build.py b/pdm_build.py index 67e71cbb05..b1b662bd39 100644 --- a/pdm_build.py +++ b/pdm_build.py @@ -3,7 +3,7 @@ from typing import Any from pdm.backend.hooks import Context -TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "typer") +TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE") def pdm_build_initialize(context: Context) -> None: From 1ed9bd49230b192bb531f4195d3d6a309261a777 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Feb 2026 13:37:37 +0000 Subject: [PATCH 202/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 014bae1abf..65668c8abe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ๐Ÿ”จ Tweak PDM hook script. PR [#14895](https://github.com/fastapi/fastapi/pull/14895) by [@tiangolo](https://github.com/tiangolo). * โ™ป๏ธ Update build setup for `fastapi-slim`, deprecate it, and make it only depend on `fastapi`. PR [#14894](https://github.com/fastapi/fastapi/pull/14894) by [@tiangolo](https://github.com/tiangolo). ## 0.128.7 From bdd20051c42d08762b2cdcc6571e4356014de572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 11 Feb 2026 16:16:34 +0100 Subject: [PATCH 203/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?8.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 65668c8abe..be11b78276 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.128.8 + ### Docs * ๐Ÿ“ Fix grammar in `docs/en/docs/tutorial/first-steps.md`. PR [#14708](https://github.com/fastapi/fastapi/pull/14708) by [@SanjanaS10](https://github.com/SanjanaS10). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index a9fe3e9719..9931216ee1 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.7" +__version__ = "0.128.8" from starlette import status as status From ad4e8e006016e088dbccdb73305a58a1338b1ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 11 Feb 2026 10:32:12 -0800 Subject: [PATCH 204/367] =?UTF-8?q?=E2=9E=96=20Drop=20support=20for=20Pyth?= =?UTF-8?q?on=203.9=20(#14897)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .github/workflows/test.yml | 6 +- .../en/docs/advanced/advanced-python-types.md | 61 + docs/en/docs/deployment/docker.md | 8 +- docs/en/docs/python-types.md | 156 +- docs/en/docs/tutorial/body-multiple-params.md | 7 - docs/en/docs/tutorial/body.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +- .../tutorial/dependencies/sub-dependencies.md | 4 +- docs/en/docs/tutorial/extra-models.md | 4 +- .../tutorial/query-params-str-validations.md | 24 - docs/en/mkdocs.yml | 1 + fastapi/_compat/shared.py | 30 +- fastapi/dependencies/utils.py | 79 +- pyproject.toml | 3 +- tests/test_dependencies_utils.py | 8 + uv.lock | 2300 +++-------------- 16 files changed, 486 insertions(+), 2231 deletions(-) create mode 100644 docs/en/docs/advanced/advanced-python-types.md create mode 100644 tests/test_dependencies_utils.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3fb837c04d..338f6c390f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,14 +56,10 @@ jobs: - starlette-pypi - starlette-git include: - - os: ubuntu-latest - python-version: "3.9" - coverage: coverage - uv-resolution: lowest-direct - os: macos-latest python-version: "3.10" coverage: coverage - uv-resolution: highest + uv-resolution: lowest-direct - os: windows-latest python-version: "3.12" coverage: coverage diff --git a/docs/en/docs/advanced/advanced-python-types.md b/docs/en/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..6495cbe443 --- /dev/null +++ b/docs/en/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Advanced Python Types { #advanced-python-types } + +Here are some additional ideas that might be useful when working with Python types. + +## Using `Union` or `Optional` { #using-union-or-optional } + +If your code for some reason can't use `|`, for example if it's not in a type annotation but in something like `response_model=`, instead of using the vertical bar (`|`) you can use `Union` from `typing`. + +For example, you could declare that something could be a `str` or `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` also has a shortcut to declare that something could be `None`, with `Optional`. + +Here's a tip from my very **subjective** point of view: + +* ๐Ÿšจ Avoid using `Optional[SomeType]` +* Instead โœจ **use `Union[SomeType, None]`** โœจ. + +Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required. + +I think `Union[SomeType, None]` is more explicit about what it means. + +It's just about the words and names. But those words can affect how you and your teammates think about the code. + +As an example, let's take this function: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter: + +```Python +say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ +``` + +The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value: + +```Python +say_hi(name=None) # This works, None is valid ๐ŸŽ‰ +``` + +The good news is, in most cases, you will be able to simply use `|` to define unions of types: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +So, normally you don't have to worry about names like `Optional` and `Union`. ๐Ÿ˜Ž diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index 0f15a60a47..4806d779d3 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -14,7 +14,7 @@ In a hurry and already know this stuff? Jump to the [`Dockerfile` below ๐Ÿ‘‡](#b Dockerfile Preview ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ Now in the same project directory create a file `Dockerfile` with: ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ If your FastAPI is a single file, for example, `main.py` without an `./app` dire Then you would just have to change the corresponding paths to copy the file inside the `Dockerfile`: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -499,7 +499,7 @@ Of course, there are **special cases** where you could want to have **a containe In those cases, you can use the `--workers` command line option to set the number of workers that you want to run: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index 6de170ada4..f2ad35d710 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -135,27 +135,30 @@ You can use, for example: {* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} -### Generic types with type parameters { #generic-types-with-type-parameters } +### `typing` module { #typing-module } -There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too. +For some additional use cases, you might need to import some things from the standard library `typing` module, for example when you want to declare that something has "any type", you can use `Any` from `typing`: -These types that have internal types are called "**generic**" types. And it's possible to declare them, even with their internal types. +```python +from typing import Any -To declare those types and the internal types, you can use the standard Python module `typing`. It exists specifically to support these type hints. -#### Newer versions of Python { #newer-versions-of-python } - -The syntax using `typing` is **compatible** with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc. +def some_function(data: Any): + print(data) +``` -As Python advances, **newer versions** come with improved support for these type annotations and in many cases you won't even need to import and use the `typing` module to declare the type annotations. +### Generic types { #generic-types } -If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity. +Some types can take "type parameters" in square brackets, to define their internal types, for example a "list of strings" would be declared `list[str]`. -In all the docs there are examples compatible with each version of Python (when there's a difference). +These types that can take type parameters are called **Generic types** or **Generics**. -For example "**Python 3.6+**" means it's compatible with Python 3.6 or above (including 3.7, 3.8, 3.9, 3.10, etc). And "**Python 3.9+**" means it's compatible with Python 3.9 or above (including 3.10, etc). +You can use the same builtin types as generics (with square brackets and types inside): -If you can use the **latest versions of Python**, use the examples for the latest version, those will have the **best and simplest syntax**, for example, "**Python 3.10+**". +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -220,44 +223,20 @@ This means: You can declare that a variable can be any of **several types**, for example, an `int` or a `str`. -In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept. - -In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a vertical bar (`|`). +To define it you use the vertical bar (`|`) to separate both types. -//// tab | Python 3.10+ +This is called a "union", because the variable can be anything in the union of those two sets of types. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -In both cases this means that `item` could be an `int` or a `str`. +This means that `item` could be an `int` or a `str`. #### Possibly `None` { #possibly-none } You can declare that a value could have a type, like `str`, but that it could also be `None`. -In Python 3.6 and above (including Python 3.10) you can declare it by importing and using `Optional` from the `typing` module. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Using `Optional[str]` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too. - -`Optional[Something]` is actually a shortcut for `Union[Something, None]`, they are equivalent. - -This also means that in Python 3.10, you can use `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ This also means that in Python 3.10, you can use `Something | None`: //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### Using `Union` or `Optional` { #using-union-or-optional } - -If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view: - -* ๐Ÿšจ Avoid using `Optional[SomeType]` -* Instead โœจ **use `Union[SomeType, None]`** โœจ. - -Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required. - -I think `Union[SomeType, None]` is more explicit about what it means. - -It's just about the words and names. But those words can affect how you and your teammates think about the code. - -As an example, let's take this function: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter: - -```Python -say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ -``` - -The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value: - -```Python -say_hi(name=None) # This works, None is valid ๐ŸŽ‰ -``` - -The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -And then you won't have to worry about names like `Optional` and `Union`. ๐Ÿ˜Ž - -#### Generic types { #generic-types } - -These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example: - -//// tab | Python 3.10+ - -You can use the same builtin types as generics (with square brackets and types inside): - -* `list` -* `tuple` -* `set` -* `dict` - -And the same as with previous Python versions, from the `typing` module: - -* `Union` -* `Optional` -* ...and others. - -In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the vertical bar (`|`) to declare unions of types, that's a lot better and simpler. - -//// - -//// tab | Python 3.9+ - -You can use the same builtin types as generics (with square brackets and types inside): - -* `list` -* `tuple` -* `set` -* `dict` - -And generics from the `typing` module: - -* `Union` -* `Optional` -* ...and others. - -//// +Using `str | None` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too. ### Classes as types { #classes-as-types } @@ -403,17 +293,11 @@ To learn more about Required Optional fields. - -/// - ## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations } Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`. -Since Python 3.9, `Annotated` is a part of the standard library, so you can import it from `typing`. +You can import `Annotated` from `typing`. {* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index bb0c583685..d904fb8397 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -106,13 +106,6 @@ As, by default, singular values are interpreted as query parameters, you don't h q: str | None = None ``` -Or in Python 3.9: - -```Python -q: Union[str, None] = None -``` - - For example: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md index 2d0dfcbb59..fb4471836e 100644 --- a/docs/en/docs/tutorial/body.md +++ b/docs/en/docs/tutorial/body.md @@ -155,7 +155,7 @@ The function parameters will be recognized as follows: FastAPI will know that the value of `q` is not required because of the default value `= None`. -The `str | None` (Python 3.10+) or `Union` in `Union[str, None]` (Python 3.9+) is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of `= None`. +The `str | None` is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of `= None`. But adding the type annotations will allow your editor to give you better support and detect errors. diff --git a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md index 0a6a786b50..d9a02d5b80 100644 --- a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ Now you can declare your dependency using this class. Notice how we write `CommonQueryParams` twice in the above code: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip @@ -137,7 +137,7 @@ It is from this one that FastAPI will extract the declared parameters and that i In this case, the first `CommonQueryParams`, in: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip @@ -163,7 +163,7 @@ commons: CommonQueryParams ... You could actually write just: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip @@ -197,7 +197,7 @@ But declaring the type is encouraged as that way your editor will know what will But you see that we are having some code repetition here, writing `CommonQueryParams` twice: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip @@ -225,7 +225,7 @@ For those specific cases, you can do the following: Instead of writing: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...you write: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip diff --git a/docs/en/docs/tutorial/dependencies/sub-dependencies.md b/docs/en/docs/tutorial/dependencies/sub-dependencies.md index b9a4e3ce74..99588dd3c5 100644 --- a/docs/en/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/sub-dependencies.md @@ -62,7 +62,7 @@ And it will save the returned value in a TypeGuard[type[_T]]: try: return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] @@ -57,13 +55,13 @@ def lenient_issubclass( raise # pragma: no cover -def _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool: +def _annotation_is_sequence(annotation: type[Any] | None) -> bool: if lenient_issubclass(annotation, (str, bytes)): return False return lenient_issubclass(annotation, sequence_types) -def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool: +def field_annotation_is_sequence(annotation: type[Any] | None) -> bool: origin = get_origin(annotation) if origin is Union or origin is UnionType: for arg in get_args(annotation): @@ -79,7 +77,7 @@ def value_is_sequence(value: Any) -> bool: return isinstance(value, sequence_types) and not isinstance(value, (str, bytes)) -def _annotation_is_complex(annotation: Union[type[Any], None]) -> bool: +def _annotation_is_complex(annotation: type[Any] | None) -> bool: return ( lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile)) or _annotation_is_sequence(annotation) @@ -87,7 +85,7 @@ def _annotation_is_complex(annotation: Union[type[Any], None]) -> bool: ) -def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool: +def field_annotation_is_complex(annotation: type[Any] | None) -> bool: origin = get_origin(annotation) if origin is Union or origin is UnionType: return any(field_annotation_is_complex(arg) for arg in get_args(annotation)) @@ -108,7 +106,7 @@ def field_annotation_is_scalar(annotation: Any) -> bool: return annotation is Ellipsis or not field_annotation_is_complex(annotation) -def field_annotation_is_scalar_sequence(annotation: Union[type[Any], None]) -> bool: +def field_annotation_is_scalar_sequence(annotation: type[Any] | None) -> bool: origin = get_origin(annotation) if origin is Union or origin is UnionType: at_least_one_scalar_sequence = False diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 23d8cd9fbf..ab18ec2db6 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,18 +1,19 @@ import dataclasses import inspect import sys -from collections.abc import Mapping, Sequence +from collections.abc import Callable, Mapping, Sequence from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass from typing import ( Annotated, Any, - Callable, ForwardRef, - Optional, + Literal, Union, cast, + get_args, + get_origin, ) from fastapi import params @@ -63,7 +64,6 @@ from starlette.datastructures import ( from starlette.requests import HTTPConnection, Request from starlette.responses import Response from starlette.websockets import WebSocket -from typing_extensions import Literal, get_args, get_origin from typing_inspection.typing_objects import is_typealiastype multipart_not_installed_error = ( @@ -127,8 +127,8 @@ def get_flat_dependant( dependant: Dependant, *, skip_repeats: bool = False, - visited: Optional[list[DependencyCacheKey]] = None, - parent_oauth_scopes: Optional[list[str]] = None, + visited: list[DependencyCacheKey] | None = None, + parent_oauth_scopes: list[str] | None = None, ) -> Dependant: if visited is None: visited = [] @@ -199,20 +199,17 @@ def get_flat_params(dependant: Dependant) -> list[ModelField]: def _get_signature(call: Callable[..., Any]) -> inspect.Signature: - if sys.version_info >= (3, 10): - try: - signature = inspect.signature(call, eval_str=True) - except NameError: - # Handle type annotations with if TYPE_CHECKING, not used by FastAPI - # e.g. dependency return types - if sys.version_info >= (3, 14): - from annotationlib import Format - - signature = inspect.signature(call, annotation_format=Format.FORWARDREF) - else: - signature = inspect.signature(call) - else: - signature = inspect.signature(call) + try: + signature = inspect.signature(call, eval_str=True) + except NameError: + # Handle type annotations with if TYPE_CHECKING, not used by FastAPI + # e.g. dependency return types + if sys.version_info >= (3, 14): + from annotationlib import Format + + signature = inspect.signature(call, annotation_format=Format.FORWARDREF) + else: + signature = inspect.signature(call) return signature @@ -258,11 +255,11 @@ def get_dependant( *, path: str, call: Callable[..., Any], - name: Optional[str] = None, - own_oauth_scopes: Optional[list[str]] = None, - parent_oauth_scopes: Optional[list[str]] = None, + name: str | None = None, + own_oauth_scopes: list[str] | None = None, + parent_oauth_scopes: list[str] | None = None, use_cache: bool = True, - scope: Union[Literal["function", "request"], None] = None, + scope: Literal["function", "request"] | None = None, ) -> Dependant: dependant = Dependant( call=call, @@ -331,7 +328,7 @@ def get_dependant( def add_non_field_param_to_dependency( *, param_name: str, type_annotation: Any, dependant: Dependant -) -> Optional[bool]: +) -> bool | None: if lenient_issubclass(type_annotation, Request): dependant.request_param_name = param_name return True @@ -356,8 +353,8 @@ def add_non_field_param_to_dependency( @dataclass class ParamDetails: type_annotation: Any - depends: Optional[params.Depends] - field: Optional[ModelField] + depends: params.Depends | None + field: ModelField | None def analyze_param( @@ -399,7 +396,7 @@ def analyze_param( ) ] if fastapi_specific_annotations: - fastapi_annotation: Union[FieldInfo, params.Depends, None] = ( + fastapi_annotation: FieldInfo | params.Depends | None = ( fastapi_specific_annotations[-1] ) else: @@ -560,20 +557,20 @@ async def _solve_generator( class SolvedDependency: values: dict[str, Any] errors: list[Any] - background_tasks: Optional[StarletteBackgroundTasks] + background_tasks: StarletteBackgroundTasks | None response: Response dependency_cache: dict[DependencyCacheKey, Any] async def solve_dependencies( *, - request: Union[Request, WebSocket], + request: Request | WebSocket, dependant: Dependant, - body: Optional[Union[dict[str, Any], FormData]] = None, - background_tasks: Optional[StarletteBackgroundTasks] = None, - response: Optional[Response] = None, - dependency_overrides_provider: Optional[Any] = None, - dependency_cache: Optional[dict[DependencyCacheKey, Any]] = None, + body: dict[str, Any] | FormData | None = None, + background_tasks: StarletteBackgroundTasks | None = None, + response: Response | None = None, + dependency_overrides_provider: Any | None = None, + dependency_cache: dict[DependencyCacheKey, Any] | None = None, # TODO: remove this parameter later, no longer used, not removing it yet as some # people might be monkey patching this function (although that's not supported) async_exit_stack: AsyncExitStack, @@ -721,7 +718,7 @@ def _is_json_field(field: ModelField) -> bool: def _get_multidict_value( - field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None + field: ModelField, values: Mapping[str, Any], alias: str | None = None ) -> Any: alias = alias or get_validation_alias(field) if ( @@ -753,7 +750,7 @@ def _get_multidict_value( def request_params_to_args( fields: Sequence[ModelField], - received_params: Union[Mapping[str, Any], QueryParams, Headers], + received_params: Mapping[str, Any] | QueryParams | Headers, ) -> tuple[dict[str, Any], list[Any]]: values: dict[str, Any] = {} errors: list[dict[str, Any]] = [] @@ -901,7 +898,7 @@ async def _extract_form_body( ): # For types assert isinstance(value, sequence_types) - results: list[Union[bytes, str]] = [] + results: list[bytes | str] = [] for sub_value in value: results.append(await sub_value.read()) value = serialize_sequence_value(field=field, value=results) @@ -920,7 +917,7 @@ async def _extract_form_body( async def request_body_to_args( body_fields: list[ModelField], - received_body: Optional[Union[dict[str, Any], FormData]], + received_body: dict[str, Any] | FormData | None, embed_body_fields: bool, ) -> tuple[dict[str, Any], list[dict[str, Any]]]: values: dict[str, Any] = {} @@ -950,7 +947,7 @@ async def request_body_to_args( return {first_field.name: v_}, errors_ for field in body_fields: loc = ("body", get_validation_alias(field)) - value: Optional[Any] = None + value: Any | None = None if body_to_process is not None: try: value = body_to_process.get(get_validation_alias(field)) @@ -970,7 +967,7 @@ async def request_body_to_args( def get_body_field( *, flat_dependant: Dependant, name: str, embed_body_fields: bool -) -> Optional[ModelField]: +) -> ModelField | None: """ Get a ModelField representing the request body for a path operation, combining all body parameters into a single field if necessary. diff --git a/pyproject.toml b/pyproject.toml index d8c43f7a48..e1ce30507a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "FastAPI framework, high performance, easy to learn, fast to code, readme = "README.md" license = "MIT" license-files = ["LICENSE"] -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ { name = "Sebastiรกn Ramรญrez", email = "tiangolo@gmail.com" }, ] @@ -33,7 +33,6 @@ classifiers = [ "Framework :: Pydantic :: 2", "Intended Audience :: Developers", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/tests/test_dependencies_utils.py b/tests/test_dependencies_utils.py new file mode 100644 index 0000000000..9257d1c9ee --- /dev/null +++ b/tests/test_dependencies_utils.py @@ -0,0 +1,8 @@ +from fastapi.dependencies.utils import get_typed_annotation + + +def test_get_typed_annotation(): + # For coverage + annotation = "None" + typed_annotation = get_typed_annotation(annotation, globals()) + assert typed_annotation is None diff --git a/uv.lock b/uv.lock index 9a807f8b4d..736b0e1457 100644 --- a/uv.lock +++ b/uv.lock @@ -1,10 +1,9 @@ version = 1 revision = 3 -requires-python = ">=3.9" +requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", - "python_full_version < '3.10'", + "python_full_version < '3.14'", ] [[package]] @@ -158,23 +157,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, - { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, - { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, - { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, - { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, - { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, - { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, - { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, - { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, - { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, - { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, - { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, - { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, ] [[package]] @@ -243,8 +225,7 @@ wheels = [ [package.optional-dependencies] trio = [ - { name = "trio", version = "0.31.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "trio", version = "0.32.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "trio" }, ] [[package]] @@ -256,31 +237,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, ] -[[package]] -name = "argon2-cffi" -version = "23.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "argon2-cffi-bindings", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/31/fa/57ec2c6d16ecd2ba0cf15f3c7d1c3c2e7b5fcb83555ff56d7ab10888ec8f/argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", size = 42798, upload-time = "2023-08-15T14:13:12.711Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/6a/e8a041599e78b6b3752da48000b14c8d1e8a04ded09c88c714ba047f34f5/argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea", size = 15124, upload-time = "2023-08-15T14:13:10.752Z" }, -] - [[package]] name = "argon2-cffi" version = "25.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "argon2-cffi-bindings", marker = "python_full_version >= '3.10'" }, + { name = "argon2-cffi-bindings" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } wheels = [ @@ -355,7 +317,7 @@ name = "authlib" version = "1.6.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "python_full_version >= '3.10'" }, + { name = "cryptography" }, ] sdist = { url = "https://files.pythonhosted.org/packages/49/dc/ed1681bf1339dd6ea1ce56136bad4baabc6f7ad466e375810702b0237047/authlib-1.6.7.tar.gz", hash = "sha256:dbf10100011d1e1b34048c9d120e83f13b35d69a826ae762b93d2fb5aafc337b", size = 164950, upload-time = "2026-02-06T14:04:14.171Z" } wheels = [ @@ -403,69 +365,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, ] -[[package]] -name = "black" -version = "25.11.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "mypy-extensions", marker = "python_full_version < '3.10'" }, - { name = "packaging", marker = "python_full_version < '3.10'" }, - { name = "pathspec", marker = "python_full_version < '3.10'" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytokens", marker = "python_full_version < '3.10'" }, - { name = "tomli", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8c/ad/33adf4708633d047950ff2dfdea2e215d84ac50ef95aff14a614e4b6e9b2/black-25.11.0.tar.gz", hash = "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", size = 655669, upload-time = "2025-11-10T01:53:50.558Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/d2/6caccbc96f9311e8ec3378c296d4f4809429c43a6cd2394e3c390e86816d/black-25.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e", size = 1743501, upload-time = "2025-11-10T01:59:06.202Z" }, - { url = "https://files.pythonhosted.org/packages/69/35/b986d57828b3f3dccbf922e2864223197ba32e74c5004264b1c62bc9f04d/black-25.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0", size = 1597308, upload-time = "2025-11-10T01:57:58.633Z" }, - { url = "https://files.pythonhosted.org/packages/39/8e/8b58ef4b37073f52b64a7b2dd8c9a96c84f45d6f47d878d0aa557e9a2d35/black-25.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37", size = 1656194, upload-time = "2025-11-10T01:57:10.909Z" }, - { url = "https://files.pythonhosted.org/packages/8d/30/9c2267a7955ecc545306534ab88923769a979ac20a27cf618d370091e5dd/black-25.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03", size = 1347996, upload-time = "2025-11-10T01:57:22.391Z" }, - { url = "https://files.pythonhosted.org/packages/c4/62/d304786b75ab0c530b833a89ce7d997924579fb7484ecd9266394903e394/black-25.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a", size = 1727891, upload-time = "2025-11-10T02:01:40.507Z" }, - { url = "https://files.pythonhosted.org/packages/82/5d/ffe8a006aa522c9e3f430e7b93568a7b2163f4b3f16e8feb6d8c3552761a/black-25.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170", size = 1581875, upload-time = "2025-11-10T01:57:51.192Z" }, - { url = "https://files.pythonhosted.org/packages/cb/c8/7c8bda3108d0bb57387ac41b4abb5c08782b26da9f9c4421ef6694dac01a/black-25.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc", size = 1642716, upload-time = "2025-11-10T01:56:51.589Z" }, - { url = "https://files.pythonhosted.org/packages/34/b9/f17dea34eecb7cc2609a89627d480fb6caea7b86190708eaa7eb15ed25e7/black-25.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e", size = 1352904, upload-time = "2025-11-10T01:59:26.252Z" }, - { url = "https://files.pythonhosted.org/packages/7f/12/5c35e600b515f35ffd737da7febdb2ab66bb8c24d88560d5e3ef3d28c3fd/black-25.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", size = 1772831, upload-time = "2025-11-10T02:03:47Z" }, - { url = "https://files.pythonhosted.org/packages/1a/75/b3896bec5a2bb9ed2f989a970ea40e7062f8936f95425879bbe162746fe5/black-25.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", size = 1608520, upload-time = "2025-11-10T01:58:46.895Z" }, - { url = "https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", size = 1682719, upload-time = "2025-11-10T01:56:55.24Z" }, - { url = "https://files.pythonhosted.org/packages/96/fb/f7dc2793a22cdf74a72114b5ed77fe3349a2e09ef34565857a2f917abdf2/black-25.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", size = 1362684, upload-time = "2025-11-10T01:57:07.639Z" }, - { url = "https://files.pythonhosted.org/packages/ad/47/3378d6a2ddefe18553d1115e36aea98f4a90de53b6a3017ed861ba1bd3bc/black-25.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", size = 1772446, upload-time = "2025-11-10T02:02:16.181Z" }, - { url = "https://files.pythonhosted.org/packages/ba/4b/0f00bfb3d1f7e05e25bfc7c363f54dc523bb6ba502f98f4ad3acf01ab2e4/black-25.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", size = 1607983, upload-time = "2025-11-10T02:02:52.502Z" }, - { url = "https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", size = 1682481, upload-time = "2025-11-10T01:57:12.35Z" }, - { url = "https://files.pythonhosted.org/packages/55/17/7e10ff1267bfa950cc16f0a411d457cdff79678fbb77a6c73b73a5317904/black-25.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", size = 1363869, upload-time = "2025-11-10T01:58:24.608Z" }, - { url = "https://files.pythonhosted.org/packages/67/c0/cc865ce594d09e4cd4dfca5e11994ebb51604328489f3ca3ae7bb38a7db5/black-25.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", size = 1771358, upload-time = "2025-11-10T02:03:33.331Z" }, - { url = "https://files.pythonhosted.org/packages/37/77/4297114d9e2fd2fc8ab0ab87192643cd49409eb059e2940391e7d2340e57/black-25.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", size = 1612902, upload-time = "2025-11-10T01:59:33.382Z" }, - { url = "https://files.pythonhosted.org/packages/de/63/d45ef97ada84111e330b2b2d45e1dd163e90bd116f00ac55927fb6bf8adb/black-25.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", size = 1680571, upload-time = "2025-11-10T01:57:04.239Z" }, - { url = "https://files.pythonhosted.org/packages/ff/4b/5604710d61cdff613584028b4cb4607e56e148801ed9b38ee7970799dab6/black-25.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", size = 1382599, upload-time = "2025-11-10T01:57:57.427Z" }, - { url = "https://files.pythonhosted.org/packages/d5/9a/5b2c0e3215fe748fcf515c2dd34658973a1210bf610e24de5ba887e4f1c8/black-25.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06", size = 1743063, upload-time = "2025-11-10T02:02:43.175Z" }, - { url = "https://files.pythonhosted.org/packages/a1/20/245164c6efc27333409c62ba54dcbfbe866c6d1957c9a6c0647786e950da/black-25.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2", size = 1596867, upload-time = "2025-11-10T02:00:17.157Z" }, - { url = "https://files.pythonhosted.org/packages/ca/6f/1a3859a7da205f3d50cf3a8bec6bdc551a91c33ae77a045bb24c1f46ab54/black-25.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc", size = 1655678, upload-time = "2025-11-10T01:57:09.028Z" }, - { url = "https://files.pythonhosted.org/packages/56/1a/6dec1aeb7be90753d4fcc273e69bc18bfd34b353223ed191da33f7519410/black-25.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc", size = 1347452, upload-time = "2025-11-10T01:57:01.871Z" }, - { url = "https://files.pythonhosted.org/packages/00/5d/aed32636ed30a6e7f9efd6ad14e2a0b0d687ae7c8c7ec4e4a557174b895c/black-25.11.0-py3-none-any.whl", hash = "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", size = 204918, upload-time = "2025-11-10T01:53:48.917Z" }, -] - [[package]] name = "black" version = "26.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "mypy-extensions", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "pathspec", marker = "python_full_version >= '3.10'" }, - { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pytokens", marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/13/88/560b11e521c522440af991d46848a2bde64b5f7202ec14e1f46f9509d328/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58", size = 658785, upload-time = "2026-01-18T04:50:11.993Z" } wheels = [ @@ -527,8 +439,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/af/d6/def916ad1d13de5d511074afcde538a958e2e8a7c7020fb698d1f392f63b/botocore-1.42.43.tar.gz", hash = "sha256:41d04ead0b0862eec21f841811fb5764fe370a2df9b319e0d5297325c50fba1b", size = 14934077, upload-time = "2026-02-05T20:31:35.15Z" } wheels = [ @@ -564,10 +475,8 @@ dependencies = [ { name = "cairocffi" }, { name = "cssselect2" }, { name = "defusedxml" }, - { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "tinycss2", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "tinycss2", version = "1.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pillow" }, + { name = "tinycss2" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ab/b9/5106168bd43d7cd8b7cc2a2ee465b385f14b63f4c092bb89eee2d48c8e67/cairosvg-2.8.2.tar.gz", hash = "sha256:07cbf4e86317b27a92318a4cac2a4bb37a5e9c1b8a27355d06874b22f85bef9f", size = 8398590, upload-time = "2025-05-15T06:56:32.653Z" } wheels = [ @@ -588,8 +497,7 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", version = "2.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and implementation_name != 'PyPy'" }, - { name = "pycparser", version = "3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and implementation_name != 'PyPy'" }, + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ @@ -664,18 +572,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cc/08ed5a43f2996a16b462f64a7055c6e962803534924b9b2f1371d8c00b7b/cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf", size = 184288, upload-time = "2025-09-08T23:23:48.404Z" }, - { url = "https://files.pythonhosted.org/packages/3d/de/38d9726324e127f727b4ecc376bc85e505bfe61ef130eaf3f290c6847dd4/cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7", size = 180509, upload-time = "2025-09-08T23:23:49.73Z" }, - { url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" }, - { url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/5c51c1c7600bdd7ed9a24a203ec255dccdd0ebf4527f7b922a0bde2fb6ed/cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", size = 203243, upload-time = "2025-09-08T23:23:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/32/f2/81b63e288295928739d715d00952c8c6034cb6c6a516b17d37e0c8be5600/cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", size = 203158, upload-time = "2025-09-08T23:23:55.169Z" }, - { url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" }, - { url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" }, - { url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" }, - { url = "https://files.pythonhosted.org/packages/2b/e7/7c769804eb75e4c4b35e658dba01de1640a351a9653c3d49ca89d16ccc91/cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", size = 218041, upload-time = "2025-09-08T23:24:00.496Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d9/6218d78f920dcd7507fc16a766b5ef8f3b913cc7aa938e7fc80b9978d089/cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a", size = 172138, upload-time = "2025-09-08T23:24:01.7Z" }, - { url = "https://files.pythonhosted.org/packages/54/8f/a1e836f82d8e32a97e6b29cc8f641779181ac7363734f12df27db803ebda/cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9", size = 182794, upload-time = "2025-09-08T23:24:02.943Z" }, ] [[package]] @@ -764,50 +660,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/46/7c/0c4760bccf082737ca7ab84a4c2034fcc06b1f21cf3032ea98bd6feb1725/charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9", size = 209609, upload-time = "2025-10-14T04:42:10.922Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a4/69719daef2f3d7f1819de60c9a6be981b8eeead7542d5ec4440f3c80e111/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d", size = 149029, upload-time = "2025-10-14T04:42:12.38Z" }, - { url = "https://files.pythonhosted.org/packages/e6/21/8d4e1d6c1e6070d3672908b8e4533a71b5b53e71d16828cc24d0efec564c/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608", size = 144580, upload-time = "2025-10-14T04:42:13.549Z" }, - { url = "https://files.pythonhosted.org/packages/a7/0a/a616d001b3f25647a9068e0b9199f697ce507ec898cacb06a0d5a1617c99/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc", size = 162340, upload-time = "2025-10-14T04:42:14.892Z" }, - { url = "https://files.pythonhosted.org/packages/85/93/060b52deb249a5450460e0585c88a904a83aec474ab8e7aba787f45e79f2/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e", size = 159619, upload-time = "2025-10-14T04:42:16.676Z" }, - { url = "https://files.pythonhosted.org/packages/dd/21/0274deb1cc0632cd587a9a0ec6b4674d9108e461cb4cd40d457adaeb0564/charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1", size = 153980, upload-time = "2025-10-14T04:42:17.917Z" }, - { url = "https://files.pythonhosted.org/packages/28/2b/e3d7d982858dccc11b31906976323d790dded2017a0572f093ff982d692f/charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3", size = 152174, upload-time = "2025-10-14T04:42:19.018Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ff/4a269f8e35f1e58b2df52c131a1fa019acb7ef3f8697b7d464b07e9b492d/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6", size = 151666, upload-time = "2025-10-14T04:42:20.171Z" }, - { url = "https://files.pythonhosted.org/packages/da/c9/ec39870f0b330d58486001dd8e532c6b9a905f5765f58a6f8204926b4a93/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88", size = 145550, upload-time = "2025-10-14T04:42:21.324Z" }, - { url = "https://files.pythonhosted.org/packages/75/8f/d186ab99e40e0ed9f82f033d6e49001701c81244d01905dd4a6924191a30/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1", size = 163721, upload-time = "2025-10-14T04:42:22.46Z" }, - { url = "https://files.pythonhosted.org/packages/96/b1/6047663b9744df26a7e479ac1e77af7134b1fcf9026243bb48ee2d18810f/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf", size = 152127, upload-time = "2025-10-14T04:42:23.712Z" }, - { url = "https://files.pythonhosted.org/packages/59/78/e5a6eac9179f24f704d1be67d08704c3c6ab9f00963963524be27c18ed87/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318", size = 161175, upload-time = "2025-10-14T04:42:24.87Z" }, - { url = "https://files.pythonhosted.org/packages/e5/43/0e626e42d54dd2f8dd6fc5e1c5ff00f05fbca17cb699bedead2cae69c62f/charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c", size = 155375, upload-time = "2025-10-14T04:42:27.246Z" }, - { url = "https://files.pythonhosted.org/packages/e9/91/d9615bf2e06f35e4997616ff31248c3657ed649c5ab9d35ea12fce54e380/charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505", size = 99692, upload-time = "2025-10-14T04:42:28.425Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a9/6c040053909d9d1ef4fcab45fddec083aedc9052c10078339b47c8573ea8/charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966", size = 107192, upload-time = "2025-10-14T04:42:29.482Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c6/4fa536b2c0cd3edfb7ccf8469fa0f363ea67b7213a842b90909ca33dd851/charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50", size = 100220, upload-time = "2025-10-14T04:42:30.632Z" }, { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] -[[package]] -name = "click" -version = "8.1.8" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, -] - [[package]] name = "click" version = "8.3.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } wheels = [ @@ -834,8 +695,7 @@ dependencies = [ { name = "pydantic-core" }, { name = "requests" }, { name = "tokenizers" }, - { name = "types-requests", version = "2.31.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "types-requests", version = "2.32.4.20260107", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "types-requests" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/35/37/65af9c50b5d5772a5528c6a949799f98ae286b8ebb924e0fac0619b3ae88/cohere-5.20.4.tar.gz", hash = "sha256:3b3017048ff5d5b4f113180947d538ca3d0f274de5875f0345be4c8cb3d5119a", size = 180737, upload-time = "2026-02-05T14:47:54.639Z" } @@ -852,133 +712,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] -[[package]] -name = "coverage" -version = "7.10.7" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239", size = 827704, upload-time = "2025-09-21T20:03:56.815Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/6c/3a3f7a46888e69d18abe3ccc6fe4cb16cccb1e6a2f99698931dafca489e6/coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a", size = 217987, upload-time = "2025-09-21T20:00:57.218Z" }, - { url = "https://files.pythonhosted.org/packages/03/94/952d30f180b1a916c11a56f5c22d3535e943aa22430e9e3322447e520e1c/coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5", size = 218388, upload-time = "2025-09-21T20:01:00.081Z" }, - { url = "https://files.pythonhosted.org/packages/50/2b/9e0cf8ded1e114bcd8b2fd42792b57f1c4e9e4ea1824cde2af93a67305be/coverage-7.10.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17", size = 245148, upload-time = "2025-09-21T20:01:01.768Z" }, - { url = "https://files.pythonhosted.org/packages/19/20/d0384ac06a6f908783d9b6aa6135e41b093971499ec488e47279f5b846e6/coverage-7.10.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b", size = 246958, upload-time = "2025-09-21T20:01:03.355Z" }, - { url = "https://files.pythonhosted.org/packages/60/83/5c283cff3d41285f8eab897651585db908a909c572bdc014bcfaf8a8b6ae/coverage-7.10.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87", size = 248819, upload-time = "2025-09-21T20:01:04.968Z" }, - { url = "https://files.pythonhosted.org/packages/60/22/02eb98fdc5ff79f423e990d877693e5310ae1eab6cb20ae0b0b9ac45b23b/coverage-7.10.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e", size = 245754, upload-time = "2025-09-21T20:01:06.321Z" }, - { url = "https://files.pythonhosted.org/packages/b4/bc/25c83bcf3ad141b32cd7dc45485ef3c01a776ca3aa8ef0a93e77e8b5bc43/coverage-7.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e", size = 246860, upload-time = "2025-09-21T20:01:07.605Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b7/95574702888b58c0928a6e982038c596f9c34d52c5e5107f1eef729399b5/coverage-7.10.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df", size = 244877, upload-time = "2025-09-21T20:01:08.829Z" }, - { url = "https://files.pythonhosted.org/packages/47/b6/40095c185f235e085df0e0b158f6bd68cc6e1d80ba6c7721dc81d97ec318/coverage-7.10.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0", size = 245108, upload-time = "2025-09-21T20:01:10.527Z" }, - { url = "https://files.pythonhosted.org/packages/c8/50/4aea0556da7a4b93ec9168420d170b55e2eb50ae21b25062513d020c6861/coverage-7.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13", size = 245752, upload-time = "2025-09-21T20:01:11.857Z" }, - { url = "https://files.pythonhosted.org/packages/6a/28/ea1a84a60828177ae3b100cb6723838523369a44ec5742313ed7db3da160/coverage-7.10.7-cp310-cp310-win32.whl", hash = "sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b", size = 220497, upload-time = "2025-09-21T20:01:13.459Z" }, - { url = "https://files.pythonhosted.org/packages/fc/1a/a81d46bbeb3c3fd97b9602ebaa411e076219a150489bcc2c025f151bd52d/coverage-7.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807", size = 221392, upload-time = "2025-09-21T20:01:14.722Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5d/c1a17867b0456f2e9ce2d8d4708a4c3a089947d0bec9c66cdf60c9e7739f/coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59", size = 218102, upload-time = "2025-09-21T20:01:16.089Z" }, - { url = "https://files.pythonhosted.org/packages/54/f0/514dcf4b4e3698b9a9077f084429681bf3aad2b4a72578f89d7f643eb506/coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a", size = 218505, upload-time = "2025-09-21T20:01:17.788Z" }, - { url = "https://files.pythonhosted.org/packages/20/f6/9626b81d17e2a4b25c63ac1b425ff307ecdeef03d67c9a147673ae40dc36/coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699", size = 248898, upload-time = "2025-09-21T20:01:19.488Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ef/bd8e719c2f7417ba03239052e099b76ea1130ac0cbb183ee1fcaa58aaff3/coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d", size = 250831, upload-time = "2025-09-21T20:01:20.817Z" }, - { url = "https://files.pythonhosted.org/packages/a5/b6/bf054de41ec948b151ae2b79a55c107f5760979538f5fb80c195f2517718/coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e", size = 252937, upload-time = "2025-09-21T20:01:22.171Z" }, - { url = "https://files.pythonhosted.org/packages/0f/e5/3860756aa6f9318227443c6ce4ed7bf9e70bb7f1447a0353f45ac5c7974b/coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23", size = 249021, upload-time = "2025-09-21T20:01:23.907Z" }, - { url = "https://files.pythonhosted.org/packages/26/0f/bd08bd042854f7fd07b45808927ebcce99a7ed0f2f412d11629883517ac2/coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab", size = 250626, upload-time = "2025-09-21T20:01:25.721Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a7/4777b14de4abcc2e80c6b1d430f5d51eb18ed1d75fca56cbce5f2db9b36e/coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82", size = 248682, upload-time = "2025-09-21T20:01:27.105Z" }, - { url = "https://files.pythonhosted.org/packages/34/72/17d082b00b53cd45679bad682fac058b87f011fd8b9fe31d77f5f8d3a4e4/coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2", size = 248402, upload-time = "2025-09-21T20:01:28.629Z" }, - { url = "https://files.pythonhosted.org/packages/81/7a/92367572eb5bdd6a84bfa278cc7e97db192f9f45b28c94a9ca1a921c3577/coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61", size = 249320, upload-time = "2025-09-21T20:01:30.004Z" }, - { url = "https://files.pythonhosted.org/packages/2f/88/a23cc185f6a805dfc4fdf14a94016835eeb85e22ac3a0e66d5e89acd6462/coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14", size = 220536, upload-time = "2025-09-21T20:01:32.184Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ef/0b510a399dfca17cec7bc2f05ad8bd78cf55f15c8bc9a73ab20c5c913c2e/coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2", size = 221425, upload-time = "2025-09-21T20:01:33.557Z" }, - { url = "https://files.pythonhosted.org/packages/51/7f/023657f301a276e4ba1850f82749bc136f5a7e8768060c2e5d9744a22951/coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a", size = 220103, upload-time = "2025-09-21T20:01:34.929Z" }, - { url = "https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417", size = 218290, upload-time = "2025-09-21T20:01:36.455Z" }, - { url = "https://files.pythonhosted.org/packages/37/66/593f9be12fc19fb36711f19a5371af79a718537204d16ea1d36f16bd78d2/coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973", size = 218515, upload-time = "2025-09-21T20:01:37.982Z" }, - { url = "https://files.pythonhosted.org/packages/66/80/4c49f7ae09cafdacc73fbc30949ffe77359635c168f4e9ff33c9ebb07838/coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c", size = 250020, upload-time = "2025-09-21T20:01:39.617Z" }, - { url = "https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7", size = 252769, upload-time = "2025-09-21T20:01:41.341Z" }, - { url = "https://files.pythonhosted.org/packages/98/2e/2dda59afd6103b342e096f246ebc5f87a3363b5412609946c120f4e7750d/coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6", size = 253901, upload-time = "2025-09-21T20:01:43.042Z" }, - { url = "https://files.pythonhosted.org/packages/53/dc/8d8119c9051d50f3119bb4a75f29f1e4a6ab9415cd1fa8bf22fcc3fb3b5f/coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59", size = 250413, upload-time = "2025-09-21T20:01:44.469Z" }, - { url = "https://files.pythonhosted.org/packages/98/b3/edaff9c5d79ee4d4b6d3fe046f2b1d799850425695b789d491a64225d493/coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b", size = 251820, upload-time = "2025-09-21T20:01:45.915Z" }, - { url = "https://files.pythonhosted.org/packages/11/25/9a0728564bb05863f7e513e5a594fe5ffef091b325437f5430e8cfb0d530/coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a", size = 249941, upload-time = "2025-09-21T20:01:47.296Z" }, - { url = "https://files.pythonhosted.org/packages/e0/fd/ca2650443bfbef5b0e74373aac4df67b08180d2f184b482c41499668e258/coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb", size = 249519, upload-time = "2025-09-21T20:01:48.73Z" }, - { url = "https://files.pythonhosted.org/packages/24/79/f692f125fb4299b6f963b0745124998ebb8e73ecdfce4ceceb06a8c6bec5/coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1", size = 251375, upload-time = "2025-09-21T20:01:50.529Z" }, - { url = "https://files.pythonhosted.org/packages/5e/75/61b9bbd6c7d24d896bfeec57acba78e0f8deac68e6baf2d4804f7aae1f88/coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256", size = 220699, upload-time = "2025-09-21T20:01:51.941Z" }, - { url = "https://files.pythonhosted.org/packages/ca/f3/3bf7905288b45b075918d372498f1cf845b5b579b723c8fd17168018d5f5/coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba", size = 221512, upload-time = "2025-09-21T20:01:53.481Z" }, - { url = "https://files.pythonhosted.org/packages/5c/44/3e32dbe933979d05cf2dac5e697c8599cfe038aaf51223ab901e208d5a62/coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf", size = 220147, upload-time = "2025-09-21T20:01:55.2Z" }, - { url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d", size = 218320, upload-time = "2025-09-21T20:01:56.629Z" }, - { url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b", size = 218575, upload-time = "2025-09-21T20:01:58.203Z" }, - { url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e", size = 249568, upload-time = "2025-09-21T20:01:59.748Z" }, - { url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b", size = 252174, upload-time = "2025-09-21T20:02:01.192Z" }, - { url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49", size = 253447, upload-time = "2025-09-21T20:02:02.701Z" }, - { url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911", size = 249779, upload-time = "2025-09-21T20:02:04.185Z" }, - { url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0", size = 251604, upload-time = "2025-09-21T20:02:06.034Z" }, - { url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f", size = 249497, upload-time = "2025-09-21T20:02:07.619Z" }, - { url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c", size = 249350, upload-time = "2025-09-21T20:02:10.34Z" }, - { url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f", size = 251111, upload-time = "2025-09-21T20:02:12.122Z" }, - { url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698", size = 220746, upload-time = "2025-09-21T20:02:13.919Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843", size = 221541, upload-time = "2025-09-21T20:02:15.57Z" }, - { url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546", size = 220170, upload-time = "2025-09-21T20:02:17.395Z" }, - { url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c", size = 219029, upload-time = "2025-09-21T20:02:18.936Z" }, - { url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15", size = 219259, upload-time = "2025-09-21T20:02:20.44Z" }, - { url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4", size = 260592, upload-time = "2025-09-21T20:02:22.313Z" }, - { url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0", size = 262768, upload-time = "2025-09-21T20:02:24.287Z" }, - { url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0", size = 264995, upload-time = "2025-09-21T20:02:26.133Z" }, - { url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65", size = 259546, upload-time = "2025-09-21T20:02:27.716Z" }, - { url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541", size = 262544, upload-time = "2025-09-21T20:02:29.216Z" }, - { url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6", size = 260308, upload-time = "2025-09-21T20:02:31.226Z" }, - { url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999", size = 258920, upload-time = "2025-09-21T20:02:32.823Z" }, - { url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2", size = 261434, upload-time = "2025-09-21T20:02:34.86Z" }, - { url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a", size = 221403, upload-time = "2025-09-21T20:02:37.034Z" }, - { url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb", size = 222469, upload-time = "2025-09-21T20:02:39.011Z" }, - { url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb", size = 220731, upload-time = "2025-09-21T20:02:40.939Z" }, - { url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520", size = 218302, upload-time = "2025-09-21T20:02:42.527Z" }, - { url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32", size = 218578, upload-time = "2025-09-21T20:02:44.468Z" }, - { url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f", size = 249629, upload-time = "2025-09-21T20:02:46.503Z" }, - { url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a", size = 252162, upload-time = "2025-09-21T20:02:48.689Z" }, - { url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360", size = 253517, upload-time = "2025-09-21T20:02:50.31Z" }, - { url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69", size = 249632, upload-time = "2025-09-21T20:02:51.971Z" }, - { url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14", size = 251520, upload-time = "2025-09-21T20:02:53.858Z" }, - { url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe", size = 249455, upload-time = "2025-09-21T20:02:55.807Z" }, - { url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e", size = 249287, upload-time = "2025-09-21T20:02:57.784Z" }, - { url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd", size = 250946, upload-time = "2025-09-21T20:02:59.431Z" }, - { url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2", size = 221009, upload-time = "2025-09-21T20:03:01.324Z" }, - { url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681", size = 221804, upload-time = "2025-09-21T20:03:03.4Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880", size = 220384, upload-time = "2025-09-21T20:03:05.111Z" }, - { url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63", size = 219047, upload-time = "2025-09-21T20:03:06.795Z" }, - { url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2", size = 219266, upload-time = "2025-09-21T20:03:08.495Z" }, - { url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d", size = 260767, upload-time = "2025-09-21T20:03:10.172Z" }, - { url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0", size = 262931, upload-time = "2025-09-21T20:03:11.861Z" }, - { url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699", size = 265186, upload-time = "2025-09-21T20:03:13.539Z" }, - { url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9", size = 259470, upload-time = "2025-09-21T20:03:15.584Z" }, - { url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f", size = 262626, upload-time = "2025-09-21T20:03:17.673Z" }, - { url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1", size = 260386, upload-time = "2025-09-21T20:03:19.36Z" }, - { url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0", size = 258852, upload-time = "2025-09-21T20:03:21.007Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399", size = 261534, upload-time = "2025-09-21T20:03:23.12Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235", size = 221784, upload-time = "2025-09-21T20:03:24.769Z" }, - { url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d", size = 222905, upload-time = "2025-09-21T20:03:26.93Z" }, - { url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a", size = 220922, upload-time = "2025-09-21T20:03:28.672Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/d1c25053764b4c42eb294aae92ab617d2e4f803397f9c7c8295caa77a260/coverage-7.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3", size = 217978, upload-time = "2025-09-21T20:03:30.362Z" }, - { url = "https://files.pythonhosted.org/packages/52/2f/b9f9daa39b80ece0b9548bbb723381e29bc664822d9a12c2135f8922c22b/coverage-7.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c", size = 218370, upload-time = "2025-09-21T20:03:32.147Z" }, - { url = "https://files.pythonhosted.org/packages/dd/6e/30d006c3b469e58449650642383dddf1c8fb63d44fdf92994bfd46570695/coverage-7.10.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396", size = 244802, upload-time = "2025-09-21T20:03:33.919Z" }, - { url = "https://files.pythonhosted.org/packages/b0/49/8a070782ce7e6b94ff6a0b6d7c65ba6bc3091d92a92cef4cd4eb0767965c/coverage-7.10.7-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40", size = 246625, upload-time = "2025-09-21T20:03:36.09Z" }, - { url = "https://files.pythonhosted.org/packages/6a/92/1c1c5a9e8677ce56d42b97bdaca337b2d4d9ebe703d8c174ede52dbabd5f/coverage-7.10.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594", size = 248399, upload-time = "2025-09-21T20:03:38.342Z" }, - { url = "https://files.pythonhosted.org/packages/c0/54/b140edee7257e815de7426d5d9846b58505dffc29795fff2dfb7f8a1c5a0/coverage-7.10.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a", size = 245142, upload-time = "2025-09-21T20:03:40.591Z" }, - { url = "https://files.pythonhosted.org/packages/e4/9e/6d6b8295940b118e8b7083b29226c71f6154f7ff41e9ca431f03de2eac0d/coverage-7.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b", size = 246284, upload-time = "2025-09-21T20:03:42.355Z" }, - { url = "https://files.pythonhosted.org/packages/db/e5/5e957ca747d43dbe4d9714358375c7546cb3cb533007b6813fc20fce37ad/coverage-7.10.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3", size = 244353, upload-time = "2025-09-21T20:03:44.218Z" }, - { url = "https://files.pythonhosted.org/packages/9a/45/540fc5cc92536a1b783b7ef99450bd55a4b3af234aae35a18a339973ce30/coverage-7.10.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0", size = 244430, upload-time = "2025-09-21T20:03:46.065Z" }, - { url = "https://files.pythonhosted.org/packages/75/0b/8287b2e5b38c8fe15d7e3398849bb58d382aedc0864ea0fa1820e8630491/coverage-7.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f", size = 245311, upload-time = "2025-09-21T20:03:48.19Z" }, - { url = "https://files.pythonhosted.org/packages/0c/1d/29724999984740f0c86d03e6420b942439bf5bd7f54d4382cae386a9d1e9/coverage-7.10.7-cp39-cp39-win32.whl", hash = "sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431", size = 220500, upload-time = "2025-09-21T20:03:50.024Z" }, - { url = "https://files.pythonhosted.org/packages/43/11/4b1e6b129943f905ca54c339f343877b55b365ae2558806c1be4f7476ed5/coverage-7.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07", size = 221408, upload-time = "2025-09-21T20:03:51.803Z" }, - { url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" }, -] - -[package.optional-dependencies] -toml = [ - { name = "tomli", marker = "python_full_version < '3.10'" }, -] - [[package]] name = "coverage" version = "7.13.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/11/43/3e4ac666cc35f231fa70c94e9f38459299de1a152813f9d2f60fc5f3ecaf/coverage-7.13.3.tar.gz", hash = "sha256:f7f6182d3dfb8802c1747eacbfe611b669455b69b7c037484bb1efbbb56711ac", size = 826832, upload-time = "2026-02-03T14:02:30.944Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ab/07/1c8099563a8a6c389a31c2d0aa1497cee86d6248bb4b9ba5e779215db9f9/coverage-7.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b4f345f7265cdbdb5ec2521ffff15fa49de6d6c39abf89fc7ad68aa9e3a55f0", size = 219143, upload-time = "2026-02-03T13:59:40.459Z" }, @@ -1076,7 +813,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version >= '3.10' and python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] @@ -1084,8 +821,8 @@ name = "croniter" version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, - { name = "pytz", marker = "python_full_version >= '3.10'" }, + { name = "python-dateutil" }, + { name = "pytz" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ad/2f/44d1ae153a0e27be56be43465e5cb39b9650c781e001e7864389deb25090/croniter-6.0.0.tar.gz", hash = "sha256:37c504b313956114a983ece2c2b07790b1f1094fe9d81cc94739214748255577", size = 64481, upload-time = "2024-12-17T17:17:47.32Z" } wheels = [ @@ -1169,8 +906,7 @@ name = "cssselect2" version = "0.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "tinycss2", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "tinycss2", version = "1.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "tinycss2" }, { name = "webencodings" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/86/fd7f58fc498b3166f3a7e8e0cddb6e620fe1da35b02248b1bd59e95dbaaa/cssselect2-0.8.0.tar.gz", hash = "sha256:7674ffb954a3b46162392aee2a3a0aedb2e14ecf99fcc28644900f4e6e3e9d3a", size = 35716, upload-time = "2025-03-05T14:46:07.988Z" } @@ -1192,12 +928,12 @@ name = "cyclopts" version = "4.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", marker = "python_full_version >= '3.10'" }, - { name = "docstring-parser", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, - { name = "rich-rst", marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "attrs" }, + { name = "docstring-parser" }, + { name = "rich" }, + { name = "rich-rst" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d4/93/6085aa89c3fff78a5180987354538d72e43b0db27e66a959302d0c07821a/cyclopts-4.5.1.tar.gz", hash = "sha256:fadc45304763fd9f5d6033727f176898d17a1778e194436964661a005078a3dd", size = 162075, upload-time = "2026-01-25T15:23:54.07Z" } wheels = [ @@ -1240,26 +976,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] -[[package]] -name = "dnspython" -version = "2.7.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197, upload-time = "2024-10-05T20:14:59.362Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632, upload-time = "2024-10-05T20:14:57.687Z" }, -] - [[package]] name = "dnspython" version = "2.8.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, @@ -1288,8 +1008,7 @@ name = "email-validator" version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "dnspython", version = "2.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "dnspython", version = "2.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "dnspython" }, { name = "idna" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } @@ -1332,9 +1051,9 @@ name = "fakeredis" version = "2.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "redis", marker = "python_full_version >= '3.10'" }, - { name = "sortedcontainers", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "redis" }, + { name = "sortedcontainers" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" } wheels = [ @@ -1343,7 +1062,7 @@ wheels = [ [package.optional-dependencies] lua = [ - { name = "lupa", marker = "python_full_version >= '3.10'" }, + { name = "lupa" }, ] [[package]] @@ -1352,8 +1071,7 @@ source = { editable = "." } dependencies = [ { name = "annotated-doc" }, { name = "pydantic" }, - { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "starlette" }, { name = "typing-extensions" }, { name = "typing-inspection" }, ] @@ -1365,17 +1083,13 @@ all = [ { name = "httpx" }, { name = "itsdangerous" }, { name = "jinja2" }, - { name = "orjson", version = "3.11.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "orjson", version = "3.11.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "orjson" }, { name = "pydantic-extra-types" }, - { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, { name = "pyyaml" }, { name = "ujson" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", extra = ["standard"] }, ] standard = [ { name = "email-validator" }, @@ -1383,12 +1097,9 @@ standard = [ { name = "httpx" }, { name = "jinja2" }, { name = "pydantic-extra-types" }, - { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "uvicorn", extra = ["standard"] }, ] standard-no-fastapi-cloud-cli = [ { name = "email-validator" }, @@ -1396,23 +1107,18 @@ standard-no-fastapi-cloud-cli = [ { name = "httpx" }, { name = "jinja2" }, { name = "pydantic-extra-types" }, - { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-multipart", version = "0.0.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "uvicorn", extra = ["standard"] }, ] [package.dev-dependencies] dev = [ { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, - { name = "black", version = "25.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "black", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "black" }, { name = "cairosvg" }, - { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", extra = ["toml"] }, { name = "dirty-equals" }, { name = "flask" }, { name = "gitpython" }, @@ -1426,17 +1132,13 @@ dev = [ { name = "mkdocs-macros-plugin" }, { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, - { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version >= '3.10'" }, + { name = "mkdocstrings", extra = ["python"] }, { name = "mypy" }, - { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pillow" }, { name = "playwright" }, { name = "prek" }, - { name = "pwdlib", version = "0.2.1", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version < '3.10'" }, - { name = "pwdlib", version = "0.3.0", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version >= '3.10'" }, - { name = "pydantic-ai", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-ai", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pwdlib", extra = ["argon2"] }, + { name = "pydantic-ai" }, { name = "pygithub" }, { name = "pyjwt" }, { name = "pytest" }, @@ -1445,15 +1147,13 @@ dev = [ { name = "pyyaml" }, { name = "ruff" }, { name = "sqlmodel" }, - { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.291.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql" }, { name = "typer" }, { name = "types-orjson" }, { name = "types-ujson" }, ] docs = [ - { name = "black", version = "25.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "black", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "black" }, { name = "cairosvg" }, { name = "griffe-typingdoc" }, { name = "griffe-warnings-deprecated" }, @@ -1464,10 +1164,8 @@ docs = [ { name = "mkdocs-macros-plugin" }, { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, - { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, extra = ["python"], marker = "python_full_version >= '3.10'" }, - { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pillow", version = "12.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "mkdocstrings", extra = ["python"] }, + { name = "pillow" }, { name = "python-slugify" }, { name = "pyyaml" }, { name = "ruff" }, @@ -1480,8 +1178,7 @@ docs-tests = [ github-actions = [ { name = "httpx" }, { name = "pydantic" }, - { name = "pydantic-settings", version = "2.11.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-settings" }, { name = "pygithub" }, { name = "pyyaml" }, { name = "smokeshow" }, @@ -1489,30 +1186,26 @@ github-actions = [ tests = [ { name = "a2wsgi" }, { name = "anyio", extra = ["trio"] }, - { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, - { name = "coverage", version = "7.13.3", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, + { name = "coverage", extra = ["toml"] }, { name = "dirty-equals" }, { name = "flask" }, { name = "httpx" }, { name = "inline-snapshot" }, { name = "mypy" }, - { name = "pwdlib", version = "0.2.1", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version < '3.10'" }, - { name = "pwdlib", version = "0.3.0", source = { registry = "https://pypi.org/simple" }, extra = ["argon2"], marker = "python_full_version >= '3.10'" }, + { name = "pwdlib", extra = ["argon2"] }, { name = "pyjwt" }, { name = "pytest" }, { name = "pytest-codspeed" }, { name = "pyyaml" }, { name = "ruff" }, { name = "sqlmodel" }, - { name = "strawberry-graphql", version = "0.283.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "strawberry-graphql", version = "0.291.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "strawberry-graphql" }, { name = "types-orjson" }, { name = "types-ujson" }, ] translations = [ { name = "gitpython" }, - { name = "pydantic-ai", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pydantic-ai", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-ai" }, { name = "pygithub" }, ] @@ -1659,8 +1352,7 @@ dependencies = [ { name = "rich-toolkit" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typer" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", extra = ["standard"] }, ] sdist = { url = "https://files.pythonhosted.org/packages/d3/ca/d90fb3bfbcbd6e56c77afd9d114dd6ce8955d8bb90094399d1c70e659e40/fastapi_cli-0.0.20.tar.gz", hash = "sha256:d17c2634f7b96b6b560bc16b0035ed047d523c912011395f49f00a421692bc3a", size = 19786, upload-time = "2025-12-22T17:13:33.794Z" } wheels = [ @@ -1670,12 +1362,10 @@ wheels = [ [package.optional-dependencies] standard = [ { name = "fastapi-cloud-cli" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", extra = ["standard"] }, ] standard-no-fastapi-cloud-cli = [ - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", extra = ["standard"] }, ] [[package]] @@ -1690,8 +1380,7 @@ dependencies = [ { name = "rignore" }, { name = "sentry-sdk" }, { name = "typer" }, - { name = "uvicorn", version = "0.39.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version < '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, extra = ["standard"], marker = "python_full_version >= '3.10'" }, + { name = "uvicorn", extra = ["standard"] }, ] sdist = { url = "https://files.pythonhosted.org/packages/11/15/6c3d85d63964340fde6f36cc80f3f365d35f371e6a918d68ff3a3d588ef2/fastapi_cloud_cli-0.11.0.tar.gz", hash = "sha256:ecc83a5db106be35af528eccb01aa9bced1d29783efd48c8c1c831cf111eea99", size = 36170, upload-time = "2026-01-15T09:51:33.681Z" } wheels = [ @@ -1793,20 +1482,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c9/e2/dfa19a4b260b8ab3581b7484dcb80c09b25324f4daa6b6ae1c7640d1607a/fastar-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:187f61dc739afe45ac8e47ed7fd1adc45d52eac110cf27d579155720507d6fbe", size = 455767, upload-time = "2025-11-26T02:36:34.758Z" }, { url = "https://files.pythonhosted.org/packages/51/47/df65c72afc1297797b255f90c4778b5d6f1f0f80282a134d5ab610310ed9/fastar-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:40e9d763cf8bf85ce2fa256e010aa795c0fe3d3bd1326d5c3084e6ce7857127e", size = 489971, upload-time = "2025-11-26T02:36:22.081Z" }, { url = "https://files.pythonhosted.org/packages/85/11/0aa8455af26f0ae89e42be67f3a874255ee5d7f0f026fc86e8d56f76b428/fastar-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:e59673307b6a08210987059a2bdea2614fe26e3335d0e5d1a3d95f49a05b1418", size = 460467, upload-time = "2025-11-26T02:36:07.978Z" }, - { url = "https://files.pythonhosted.org/packages/fd/0d/462ce073b1f87cc6bf33b656c340c103eeb67487d118b761a697f1ee454f/fastar-0.8.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:923afc2db5192e56e71952a88e3fe5965c7c9c910d385d2db7573136f064f2fa", size = 709519, upload-time = "2025-11-26T02:34:44.783Z" }, - { url = "https://files.pythonhosted.org/packages/0d/f1/ceca1e04fd3266f866efdbb5d343fee1d8ff8fe94c64c8d1aab68b483ad0/fastar-0.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4fbe775356930f3aab0ce709fdf8ecf90c10882f5bbdcea215c89a3b14090c50", size = 632509, upload-time = "2025-11-26T02:34:29.428Z" }, - { url = "https://files.pythonhosted.org/packages/4f/db/fdb07e9dce80ebb38138f166a30dc482c82cc8dfcfda1024e8b100a53d1c/fastar-0.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ff516154e77f4bf78c31a0c11aa78a8a80e11b6964ec6f28982e42ffcbb543c", size = 871400, upload-time = "2025-11-26T02:33:58.461Z" }, - { url = "https://files.pythonhosted.org/packages/54/6d/d0a342528002cf7527339fd275bdee5e5cc90c2f193e8418d3510ffedcd7/fastar-0.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d2fdd1c987ff2300bdf39baed556f8e155f8577018775e794a268ecf1707610", size = 765781, upload-time = "2025-11-26T02:32:53.929Z" }, - { url = "https://files.pythonhosted.org/packages/bc/96/dd2721e7160eed7bc9c3b695e942868c7ba2fab41947278fa380c18569be/fastar-0.8.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d80e4dad8ee2362a71870b1e735800bb5e97f12ebbee4bd0cf15a81ad2428b5a", size = 766126, upload-time = "2025-11-26T02:33:10.075Z" }, - { url = "https://files.pythonhosted.org/packages/9c/ac/6533d2608254def722cd8c852f4ac8fb413fc43ad3251b7fb99863ffaa83/fastar-0.8.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a17abee1febf5363ed2633f5e13de4be481ba1ab5f77860d39470eccdc4b65af", size = 932549, upload-time = "2025-11-26T02:33:25.866Z" }, - { url = "https://files.pythonhosted.org/packages/97/dc/aac042d0d0017b8d75ff34381cc28b482ace0d78a26d4eef9a8674f850c2/fastar-0.8.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64cbde8e0ece3d799090a4727f936f66c5990d3ac59416f3de76a2c676e8e568", size = 821860, upload-time = "2025-11-26T02:33:41.423Z" }, - { url = "https://files.pythonhosted.org/packages/b2/ef/c31057572e3a5a2c90da4986d8594d0ff33097b4a44058f9f52103c33677/fastar-0.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63d98b26590d293a9d9a379bae88367a8f3a6137c28819ed6dd6e11aca4a5c6e", size = 821660, upload-time = "2025-11-26T02:34:13.84Z" }, - { url = "https://files.pythonhosted.org/packages/39/00/d42fc84e8ce8587eb746406aa74ec231f97ce659a48bc064d5ff5cd78889/fastar-0.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf440983d4d64582bddf2f0bd3c43ea1db93a8c31cf7c20e473bffaf6d9c0b6d", size = 987026, upload-time = "2025-11-26T02:35:01.181Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d9/5e4d37faca6f2df6a0bf1efc340192a871356162a7cc53626dc117645ad6/fastar-0.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1d90cbf984a39afda27afe08e40c2d8eddc49c5e80590af641610c7b6dc20161", size = 1042165, upload-time = "2025-11-26T02:35:18.729Z" }, - { url = "https://files.pythonhosted.org/packages/77/fd/bb4731243e42f385e8db9da824971f5d0380e6b31466c36eb089d631c589/fastar-0.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ca0db5e563d84b639fe15385eeca940777b6d2f0a1f3bb7cd5b55ab7124f0554", size = 1046990, upload-time = "2025-11-26T02:35:36.158Z" }, - { url = "https://files.pythonhosted.org/packages/c4/50/2ac066f771858ea45d885cfde7262b286a223af9538d3f85d29d5159b4fb/fastar-0.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:42ff3052d74684a636423d4f040db88eebd4caf20842fa5f06020e0130c01f69", size = 995637, upload-time = "2025-11-26T02:35:54.714Z" }, - { url = "https://files.pythonhosted.org/packages/d3/04/c884ea3fa7c154ac0e89219a337c9d6e0d52d0eb5547b3f99b896eca417e/fastar-0.8.0-cp39-cp39-win32.whl", hash = "sha256:15e3dfaa769d2117ef707e5f47c62126d1b63f8e9c85133112f33f1fbdf8942f", size = 456817, upload-time = "2025-11-26T02:36:33.198Z" }, - { url = "https://files.pythonhosted.org/packages/aa/0f/3a5758cca852bb221e78950fbfece0b932c6de6981ee36fb0ac57cf66c13/fastar-0.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:5153aa1c194316d0f67b6884a62d122d51fce4196263e92e4bca2a6c47cd44c0", size = 490633, upload-time = "2025-11-26T02:36:19.976Z" }, { url = "https://files.pythonhosted.org/packages/25/9f/6eaa810c240236eff2edf736cd50a17c97dbab1693cda4f7bcea09d13418/fastar-0.8.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2127cf2e80ffd49744a160201e0e2f55198af6c028a7b3f750026e0b1f1caa4e", size = 710544, upload-time = "2025-11-26T02:34:46.195Z" }, { url = "https://files.pythonhosted.org/packages/1d/a5/58ff9e49a1cd5fbfc8f1238226cbf83b905376a391a6622cdd396b2cfa29/fastar-0.8.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ff85094f10003801339ac4fa9b20a3410c2d8f284d4cba2dc99de6e98c877812", size = 634020, upload-time = "2025-11-26T02:34:31.085Z" }, { url = "https://files.pythonhosted.org/packages/80/94/f839257c6600a83fbdb5a7fcc06319599086137b25ba38ca3d2c0fe14562/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3dbca235f0bd804cca6602fe055d3892bebf95fb802e6c6c7d872fb10f7abc6c", size = 871735, upload-time = "2025-11-26T02:34:00.088Z" }, @@ -1831,18 +1506,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/b9/9a8c3fd59958c1c8027bc075af11722cdc62c4968bb277e841d131232289/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:382bfe82c026086487cb17fee12f4c1e2b4e67ce230f2e04487d3e7ddfd69031", size = 1042911, upload-time = "2025-11-26T02:35:21.857Z" }, { url = "https://files.pythonhosted.org/packages/e2/2f/c3f30963b47022134b8a231c12845f4d7cfba520f59bbc1a82468aea77c7/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:908d2b9a1ff3d549cc304b32f95706a536da8f0bcb0bc0f9e4c1cce39b80e218", size = 1047464, upload-time = "2025-11-26T02:35:39.376Z" }, { url = "https://files.pythonhosted.org/packages/9e/8a/218ab6d9a2bab3b07718e6cd8405529600edc1e9c266320e8524c8f63251/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1aa7dbde2d2d73eb5b6203d0f74875cb66350f0f1b4325b4839fc8fbbf5d074e", size = 997309, upload-time = "2025-11-26T02:35:57.722Z" }, - { url = "https://files.pythonhosted.org/packages/4e/ef/da0cbac6da78b22ddb6ec0bbf3ad1813f8dd991a911342fc20e5feabaa15/fastar-0.8.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:284036bae786a520456ad3f58e72aaf1bd5d74e309132e568343564daa4ae383", size = 710367, upload-time = "2025-11-26T02:34:48.853Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f0/951d368b4538477fe44651aaa7436318c22bf89e8e18086a68bd89e14a82/fastar-0.8.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5aba0942b4f56acdb8fa8aa7cb506f70c1a17bf13dcab318a17ffb467cb2e7ec", size = 633744, upload-time = "2025-11-26T02:34:33.723Z" }, - { url = "https://files.pythonhosted.org/packages/1e/d2/5f37b634aff1e27191874b7f0fb7306e60566d984df06ff5c2f901ef123b/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:52eda6230799db7bbd44461c622161e9bcd43603399da19b0daab2782e0030b0", size = 871412, upload-time = "2025-11-26T02:34:02.738Z" }, - { url = "https://files.pythonhosted.org/packages/b4/cd/41148c74cc164aacb8b5e7cb938a7ecc5a4e595f95e312aafcc8dbe36e48/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f860566b9f3cb1900980f46a4c3f003990c0009c11730f988f758542c17a2364", size = 766470, upload-time = "2025-11-26T02:32:58.503Z" }, - { url = "https://files.pythonhosted.org/packages/5f/89/b5715d4f969f15fe78b184ae42295e71f0ad2e0e083f0625212271cbda55/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:78f3fe5f45437c66d1dbece5f31aa487e48ef46d76b2082b873d5fa18013ebe1", size = 765285, upload-time = "2025-11-26T02:33:14.148Z" }, - { url = "https://files.pythonhosted.org/packages/39/4a/88223721278a663684c4fa6cb95ca296e0ba385362de4809a5e85cacfb36/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:82bc445202bbc53f067bb15e3b8639f01fd54d3096a0f9601240690cfd7c9684", size = 933881, upload-time = "2025-11-26T02:33:29.637Z" }, - { url = "https://files.pythonhosted.org/packages/ac/73/a13d6d57029378477c4d9232eddfb81bb2f74e0e91bdbca864c74223d877/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b1208b5453cfe7192e54765f73844b80d684bd8dc6d6acbbb60ead42590b13e", size = 822511, upload-time = "2025-11-26T02:33:45.882Z" }, - { url = "https://files.pythonhosted.org/packages/a4/96/79000571a10d93e2110e72b5e7155e6bf138c8cb896117cfb768c74d01ff/fastar-0.8.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8922754c66699e27d4f1ce07c9c256228054cdc9bb36363e8bb5b503453a6da", size = 822204, upload-time = "2025-11-26T02:34:18.164Z" }, - { url = "https://files.pythonhosted.org/packages/35/e4/c2066024f336349ce36f85b0df9d082981d453cfdb5c139af2c5eebcc49a/fastar-0.8.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:92cad46dfbb9969359823c9f61165ec32d5d675d86e863889416e9b64efea95c", size = 987454, upload-time = "2025-11-26T02:35:05.827Z" }, - { url = "https://files.pythonhosted.org/packages/4a/b7/e3a062534af02610dea226d2c14e70beb90b91a23562fed8f76bfa35e6cd/fastar-0.8.0-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:f4eb9560a447ff6a4b377f08b6e5d3a31909a612b028f2c57810ffaf570eceb8", size = 1041310, upload-time = "2025-11-26T02:35:23.305Z" }, - { url = "https://files.pythonhosted.org/packages/91/73/1640476553705ee29ff9350a3b6c707ac150be53094d326e0d81d62a65ec/fastar-0.8.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:52455794e6cc2b6a6dbf141a1c4312a1a1215d75e8849a35fcff694454da880f", size = 1047020, upload-time = "2025-11-26T02:35:40.95Z" }, - { url = "https://files.pythonhosted.org/packages/b7/79/9b492c4da885a6699bc76032dbc285c565429ca1b6dc6b5aa5c908111d22/fastar-0.8.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8de5decfa18a03807ae26ba5af095c2c04ac31ae915e9a849363a4495463171f", size = 996379, upload-time = "2025-11-26T02:35:59.297Z" }, ] [[package]] @@ -1890,12 +1553,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/1c/6dfd082a205be4510543221b734b1191299e6a1810c452b6bc76dfa6968e/fastavro-1.12.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6a3462934b20a74f9ece1daa49c2e4e749bd9a35fa2657b53bf62898fba80f5", size = 3433972, upload-time = "2025-10-10T15:42:14.485Z" }, { url = "https://files.pythonhosted.org/packages/24/90/9de694625a1a4b727b1ad0958d220cab25a9b6cf7f16a5c7faa9ea7b2261/fastavro-1.12.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1f81011d54dd47b12437b51dd93a70a9aa17b61307abf26542fc3c13efbc6c51", size = 3368752, upload-time = "2025-10-10T15:42:16.618Z" }, { url = "https://files.pythonhosted.org/packages/fa/93/b44f67589e4d439913dab6720f7e3507b0fa8b8e56d06f6fc875ced26afb/fastavro-1.12.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43ded16b3f4a9f1a42f5970c2aa618acb23ea59c4fcaa06680bdf470b255e5a8", size = 3386636, upload-time = "2025-10-10T15:42:18.974Z" }, - { url = "https://files.pythonhosted.org/packages/8f/b8/67f5682cd59cb59ec6eecb5479b132caaf69709d1e1ceda4f92d8c69d7f1/fastavro-1.12.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:02281432dcb11c78b3280da996eff61ee0eff39c5de06c6e0fbf19275093e6d4", size = 1002311, upload-time = "2025-10-10T15:42:20.415Z" }, - { url = "https://files.pythonhosted.org/packages/93/38/2f15a7ad24e4b6e0239016c068f142358732bf8ead0315ee926b88634bec/fastavro-1.12.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4128978b930aaf930332db4b3acc290783183f3be06a241ae4a482f3ed8ce892", size = 3195871, upload-time = "2025-10-10T15:42:22.675Z" }, - { url = "https://files.pythonhosted.org/packages/c1/e5/6fc0250b3006b1b42c1ab9f0511ccd44e1aeb15a63a77fc780ee97f58797/fastavro-1.12.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:546ffffda6610fca672f0ed41149808e106d8272bb246aa7539fa8bb6f117f17", size = 3204127, upload-time = "2025-10-10T15:42:24.855Z" }, - { url = "https://files.pythonhosted.org/packages/c6/43/1f3909eb096eb1066e416f0875abe783b73fabe823ad616f6956b3e80e84/fastavro-1.12.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a7d840ccd9aacada3ddc80fbcc4ea079b658107fe62e9d289a0de9d54e95d366", size = 3135604, upload-time = "2025-10-10T15:42:28.899Z" }, - { url = "https://files.pythonhosted.org/packages/e6/61/ec083a3a5d7c2b97d0e2c9e137a6e667583afe884af0e49318f7ee7eaa5a/fastavro-1.12.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3100ad643e7fa658469a2a2db229981c1a000ff16b8037c0b58ce3ec4d2107e8", size = 3210932, upload-time = "2025-10-10T15:42:30.891Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ba/b814fb09b32c8f3059451c33bb11d55eb23188e6a499f5dde628d13bc076/fastavro-1.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:a38607444281619eda3a9c1be9f5397634012d1b237142eee1540e810b30ac8b", size = 510328, upload-time = "2025-10-10T15:42:32.415Z" }, ] [[package]] @@ -1903,50 +1560,34 @@ name = "fastmcp" version = "2.14.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "authlib", marker = "python_full_version >= '3.10'" }, - { name = "cyclopts", marker = "python_full_version >= '3.10'" }, - { name = "exceptiongroup", marker = "python_full_version >= '3.10'" }, - { name = "httpx", marker = "python_full_version >= '3.10'" }, - { name = "jsonref", marker = "python_full_version >= '3.10'" }, - { name = "jsonschema-path", marker = "python_full_version >= '3.10'" }, - { name = "mcp", marker = "python_full_version >= '3.10'" }, - { name = "openapi-pydantic", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "py-key-value-aio", extra = ["disk", "keyring", "memory"], marker = "python_full_version >= '3.10'" }, - { name = "pydantic", extra = ["email"], marker = "python_full_version >= '3.10'" }, - { name = "pydocket", marker = "python_full_version >= '3.10'" }, - { name = "pyperclip", marker = "python_full_version >= '3.10'" }, - { name = "python-dotenv", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "websockets", marker = "python_full_version >= '3.10'" }, + { name = "authlib" }, + { name = "cyclopts" }, + { name = "exceptiongroup" }, + { name = "httpx" }, + { name = "jsonref" }, + { name = "jsonschema-path" }, + { name = "mcp" }, + { name = "openapi-pydantic" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "py-key-value-aio", extra = ["disk", "keyring", "memory"] }, + { name = "pydantic", extra = ["email"] }, + { name = "pydocket" }, + { name = "pyperclip" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "uvicorn" }, + { name = "websockets" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3b/32/982678d44f13849530a74ab101ed80e060c2ee6cf87471f062dcf61705fd/fastmcp-2.14.5.tar.gz", hash = "sha256:38944dc582c541d55357082bda2241cedb42cd3a78faea8a9d6a2662c62a42d7", size = 8296329, upload-time = "2026-02-03T15:35:21.005Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e5/c1/1a35ec68ff76ea8443aa115b18bcdee748a4ada2124537ee90522899ff9f/fastmcp-2.14.5-py3-none-any.whl", hash = "sha256:d81e8ec813f5089d3624bec93944beaefa86c0c3a4ef1111cbef676a761ebccf", size = 417784, upload-time = "2026-02-03T15:35:18.489Z" }, ] -[[package]] -name = "filelock" -version = "3.19.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, -] - [[package]] name = "filelock" version = "3.20.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, @@ -1958,9 +1599,7 @@ version = "3.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blinker" }, - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "click" }, { name = "itsdangerous" }, { name = "jinja2" }, { name = "markupsafe" }, @@ -2089,45 +1728,13 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, - { url = "https://files.pythonhosted.org/packages/c2/59/ae5cdac87a00962122ea37bb346d41b66aec05f9ce328fa2b9e216f8967b/frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47", size = 86967, upload-time = "2025-10-06T05:37:55.607Z" }, - { url = "https://files.pythonhosted.org/packages/8a/10/17059b2db5a032fd9323c41c39e9d1f5f9d0c8f04d1e4e3e788573086e61/frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca", size = 49984, upload-time = "2025-10-06T05:37:57.049Z" }, - { url = "https://files.pythonhosted.org/packages/4b/de/ad9d82ca8e5fa8f0c636e64606553c79e2b859ad253030b62a21fe9986f5/frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068", size = 50240, upload-time = "2025-10-06T05:37:58.145Z" }, - { url = "https://files.pythonhosted.org/packages/4e/45/3dfb7767c2a67d123650122b62ce13c731b6c745bc14424eea67678b508c/frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95", size = 219472, upload-time = "2025-10-06T05:37:59.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/bf/5bf23d913a741b960d5c1dac7c1985d8a2a1d015772b2d18ea168b08e7ff/frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459", size = 221531, upload-time = "2025-10-06T05:38:00.521Z" }, - { url = "https://files.pythonhosted.org/packages/d0/03/27ec393f3b55860859f4b74cdc8c2a4af3dbf3533305e8eacf48a4fd9a54/frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675", size = 219211, upload-time = "2025-10-06T05:38:01.842Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ad/0fd00c404fa73fe9b169429e9a972d5ed807973c40ab6b3cf9365a33d360/frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61", size = 231775, upload-time = "2025-10-06T05:38:03.384Z" }, - { url = "https://files.pythonhosted.org/packages/8a/c3/86962566154cb4d2995358bc8331bfc4ea19d07db1a96f64935a1607f2b6/frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6", size = 236631, upload-time = "2025-10-06T05:38:04.609Z" }, - { url = "https://files.pythonhosted.org/packages/ea/9e/6ffad161dbd83782d2c66dc4d378a9103b31770cb1e67febf43aea42d202/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5", size = 218632, upload-time = "2025-10-06T05:38:05.917Z" }, - { url = "https://files.pythonhosted.org/packages/58/b2/4677eee46e0a97f9b30735e6ad0bf6aba3e497986066eb68807ac85cf60f/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3", size = 235967, upload-time = "2025-10-06T05:38:07.614Z" }, - { url = "https://files.pythonhosted.org/packages/05/f3/86e75f8639c5a93745ca7addbbc9de6af56aebb930d233512b17e46f6493/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1", size = 228799, upload-time = "2025-10-06T05:38:08.845Z" }, - { url = "https://files.pythonhosted.org/packages/30/00/39aad3a7f0d98f5eb1d99a3c311215674ed87061aecee7851974b335c050/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178", size = 230566, upload-time = "2025-10-06T05:38:10.52Z" }, - { url = "https://files.pythonhosted.org/packages/0d/4d/aa144cac44568d137846ddc4d5210fb5d9719eb1d7ec6fa2728a54b5b94a/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda", size = 217715, upload-time = "2025-10-06T05:38:11.832Z" }, - { url = "https://files.pythonhosted.org/packages/64/4c/8f665921667509d25a0dd72540513bc86b356c95541686f6442a3283019f/frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087", size = 39933, upload-time = "2025-10-06T05:38:13.061Z" }, - { url = "https://files.pythonhosted.org/packages/79/bd/bcc926f87027fad5e59926ff12d136e1082a115025d33c032d1cd69ab377/frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a", size = 44121, upload-time = "2025-10-06T05:38:14.572Z" }, - { url = "https://files.pythonhosted.org/packages/4c/07/9c2e4eb7584af4b705237b971b89a4155a8e57599c4483a131a39256a9a0/frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103", size = 40312, upload-time = "2025-10-06T05:38:15.699Z" }, { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, ] -[[package]] -name = "fsspec" -version = "2025.10.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/24/7f/2747c0d332b9acfa75dc84447a066fdf812b5a6b8d30472b74d309bfe8cb/fsspec-2025.10.0.tar.gz", hash = "sha256:b6789427626f068f9a83ca4e8a3cc050850b6c0f71f99ddb4f542b8266a26a59", size = 309285, upload-time = "2025-10-30T14:58:44.036Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/02/a6b21098b1d5d6249b7c5ab69dde30108a71e4e819d4a9778f1de1d5b70d/fsspec-2025.10.0-py3-none-any.whl", hash = "sha256:7c7712353ae7d875407f97715f0e1ffcc21e33d5b24556cb1e090ae9409ec61d", size = 200966, upload-time = "2025-10-30T14:58:42.53Z" }, -] - [[package]] name = "fsspec" version = "2026.2.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, @@ -2138,7 +1745,6 @@ name = "genai-prices" version = "0.0.52" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, { name = "httpx" }, { name = "pydantic" }, ] @@ -2177,7 +1783,6 @@ version = "3.1.46" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "gitdb" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/b5/59d16470a1f0dfe8c793f9ef56fd3826093fc52b3bd96d6b9d6c26c7e27b/gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", size = 215371, upload-time = "2026-01-01T15:37:32.073Z" } wheels = [ @@ -2200,50 +1805,24 @@ wheels = [ [package.optional-dependencies] requests = [ - { name = "requests", marker = "python_full_version >= '3.10'" }, -] - -[[package]] -name = "google-genai" -version = "1.47.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "anyio", marker = "python_full_version < '3.10'" }, - { name = "google-auth", marker = "python_full_version < '3.10'" }, - { name = "httpx", marker = "python_full_version < '3.10'" }, - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "requests", marker = "python_full_version < '3.10'" }, - { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, - { name = "websockets", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/97/784fba9bc6c41263ff90cb9063eadfdd755dde79cfa5a8d0e397b067dcf9/google_genai-1.47.0.tar.gz", hash = "sha256:ecece00d0a04e6739ea76cc8dad82ec9593d9380aaabef078990e60574e5bf59", size = 241471, upload-time = "2025-10-29T22:01:02.88Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/ef/e080e8d67c270ea320956bb911a9359664fc46d3b87d1f029decd33e5c4c/google_genai-1.47.0-py3-none-any.whl", hash = "sha256:e3851237556cbdec96007d8028b4b1f2425cdc5c099a8dc36b72a57e42821b60", size = 241506, upload-time = "2025-10-29T22:01:00.982Z" }, + { name = "requests" }, ] [[package]] name = "google-genai" version = "1.62.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "distro", marker = "python_full_version >= '3.10'" }, - { name = "google-auth", extra = ["requests"], marker = "python_full_version >= '3.10'" }, - { name = "httpx", marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, - { name = "sniffio", marker = "python_full_version >= '3.10'" }, - { name = "tenacity", version = "9.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, - { name = "websockets", marker = "python_full_version >= '3.10'" }, + { name = "anyio" }, + { name = "distro" }, + { name = "google-auth", extra = ["requests"] }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "sniffio" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, ] sdist = { url = "https://files.pythonhosted.org/packages/94/4c/71b32b5c8db420cf2fd0d5ef8a672adbde97d85e5d44a0b4fca712264ef1/google_genai-1.62.0.tar.gz", hash = "sha256:709468a14c739a080bc240a4f3191df597bf64485b1ca3728e0fb67517774c18", size = 490888, upload-time = "2026-02-04T22:48:41.989Z" } wheels = [ @@ -2255,7 +1834,7 @@ name = "googleapis-common-protos" version = "1.72.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "protobuf" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } wheels = [ @@ -2266,98 +1845,15 @@ wheels = [ name = "graphql-core" version = "3.2.7" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] sdist = { url = "https://files.pythonhosted.org/packages/ac/9b/037a640a2983b09aed4a823f9cf1729e6d780b0671f854efa4727a7affbe/graphql_core-3.2.7.tar.gz", hash = "sha256:27b6904bdd3b43f2a0556dad5d579bdfdeab1f38e8e8788e555bdcb586a6f62c", size = 513484, upload-time = "2025-11-01T22:30:40.436Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0a/14/933037032608787fb92e365883ad6a741c235e0ff992865ec5d904a38f1e/graphql_core-3.2.7-py3-none-any.whl", hash = "sha256:17fc8f3ca4a42913d8e24d9ac9f08deddf0a0b2483076575757f6c412ead2ec0", size = 207262, upload-time = "2025-11-01T22:30:38.912Z" }, ] -[[package]] -name = "greenlet" -version = "3.2.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260, upload-time = "2025-08-07T13:24:33.51Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/ed/6bfa4109fcb23a58819600392564fea69cdc6551ffd5e69ccf1d52a40cbc/greenlet-3.2.4-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c", size = 271061, upload-time = "2025-08-07T13:17:15.373Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fc/102ec1a2fc015b3a7652abab7acf3541d58c04d3d17a8d3d6a44adae1eb1/greenlet-3.2.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590", size = 629475, upload-time = "2025-08-07T13:42:54.009Z" }, - { url = "https://files.pythonhosted.org/packages/c5/26/80383131d55a4ac0fb08d71660fd77e7660b9db6bdb4e8884f46d9f2cc04/greenlet-3.2.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c", size = 640802, upload-time = "2025-08-07T13:45:25.52Z" }, - { url = "https://files.pythonhosted.org/packages/9f/7c/e7833dbcd8f376f3326bd728c845d31dcde4c84268d3921afcae77d90d08/greenlet-3.2.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c8c9e331e58180d0d83c5b7999255721b725913ff6bc6cf39fa2a45841a4fd4b", size = 636703, upload-time = "2025-08-07T13:53:12.622Z" }, - { url = "https://files.pythonhosted.org/packages/e9/49/547b93b7c0428ede7b3f309bc965986874759f7d89e4e04aeddbc9699acb/greenlet-3.2.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31", size = 635417, upload-time = "2025-08-07T13:18:25.189Z" }, - { url = "https://files.pythonhosted.org/packages/7f/91/ae2eb6b7979e2f9b035a9f612cf70f1bf54aad4e1d125129bef1eae96f19/greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d", size = 584358, upload-time = "2025-08-07T13:18:23.708Z" }, - { url = "https://files.pythonhosted.org/packages/f7/85/433de0c9c0252b22b16d413c9407e6cb3b41df7389afc366ca204dbc1393/greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5", size = 1113550, upload-time = "2025-08-07T13:42:37.467Z" }, - { url = "https://files.pythonhosted.org/packages/a1/8d/88f3ebd2bc96bf7747093696f4335a0a8a4c5acfcf1b757717c0d2474ba3/greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f", size = 1137126, upload-time = "2025-08-07T13:18:20.239Z" }, - { url = "https://files.pythonhosted.org/packages/f1/29/74242b7d72385e29bcc5563fba67dad94943d7cd03552bac320d597f29b2/greenlet-3.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f47617f698838ba98f4ff4189aef02e7343952df3a615f847bb575c3feb177a7", size = 1544904, upload-time = "2025-11-04T12:42:04.763Z" }, - { url = "https://files.pythonhosted.org/packages/c8/e2/1572b8eeab0f77df5f6729d6ab6b141e4a84ee8eb9bc8c1e7918f94eda6d/greenlet-3.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af41be48a4f60429d5cad9d22175217805098a9ef7c40bfef44f7669fb9d74d8", size = 1611228, upload-time = "2025-11-04T12:42:08.423Z" }, - { url = "https://files.pythonhosted.org/packages/d6/6f/b60b0291d9623c496638c582297ead61f43c4b72eef5e9c926ef4565ec13/greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c", size = 298654, upload-time = "2025-08-07T13:50:00.469Z" }, - { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, - { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519, upload-time = "2025-08-07T13:53:13.928Z" }, - { url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707, upload-time = "2025-08-07T13:18:27.146Z" }, - { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, - { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, - { url = "https://files.pythonhosted.org/packages/3f/cc/b07000438a29ac5cfb2194bfc128151d52f333cee74dd7dfe3fb733fc16c/greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa", size = 1142073, upload-time = "2025-08-07T13:18:21.737Z" }, - { url = "https://files.pythonhosted.org/packages/67/24/28a5b2fa42d12b3d7e5614145f0bd89714c34c08be6aabe39c14dd52db34/greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c", size = 1548385, upload-time = "2025-11-04T12:42:11.067Z" }, - { url = "https://files.pythonhosted.org/packages/6a/05/03f2f0bdd0b0ff9a4f7b99333d57b53a7709c27723ec8123056b084e69cd/greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5", size = 1613329, upload-time = "2025-11-04T12:42:12.928Z" }, - { url = "https://files.pythonhosted.org/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9", size = 299100, upload-time = "2025-08-07T13:44:12.287Z" }, - { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, - { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, - { url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185, upload-time = "2025-08-07T13:45:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926, upload-time = "2025-08-07T13:53:15.251Z" }, - { url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839, upload-time = "2025-08-07T13:18:30.281Z" }, - { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, - { url = "https://files.pythonhosted.org/packages/3f/c7/12381b18e21aef2c6bd3a636da1088b888b97b7a0362fac2e4de92405f97/greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f", size = 1151142, upload-time = "2025-08-07T13:18:22.981Z" }, - { url = "https://files.pythonhosted.org/packages/27/45/80935968b53cfd3f33cf99ea5f08227f2646e044568c9b1555b58ffd61c2/greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0", size = 1564846, upload-time = "2025-11-04T12:42:15.191Z" }, - { url = "https://files.pythonhosted.org/packages/69/02/b7c30e5e04752cb4db6202a3858b149c0710e5453b71a3b2aec5d78a1aab/greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d", size = 1633814, upload-time = "2025-11-04T12:42:17.175Z" }, - { url = "https://files.pythonhosted.org/packages/e9/08/b0814846b79399e585f974bbeebf5580fbe59e258ea7be64d9dfb253c84f/greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02", size = 299899, upload-time = "2025-08-07T13:38:53.448Z" }, - { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, - { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, - { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, - { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, - { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, - { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, - { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, - { url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210, upload-time = "2025-08-07T13:18:24.072Z" }, - { url = "https://files.pythonhosted.org/packages/1c/53/f9c440463b3057485b8594d7a638bed53ba531165ef0ca0e6c364b5cc807/greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b", size = 1564759, upload-time = "2025-11-04T12:42:19.395Z" }, - { url = "https://files.pythonhosted.org/packages/47/e4/3bb4240abdd0a8d23f4f88adec746a3099f0d86bfedb623f063b2e3b4df0/greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929", size = 1634288, upload-time = "2025-11-04T12:42:21.174Z" }, - { url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685, upload-time = "2025-08-07T13:24:38.824Z" }, - { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, - { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, - { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, - { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, - { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, - { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, - { url = "https://files.pythonhosted.org/packages/0d/da/343cd760ab2f92bac1845ca07ee3faea9fe52bee65f7bcb19f16ad7de08b/greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681", size = 1680760, upload-time = "2025-11-04T12:42:25.341Z" }, - { url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425, upload-time = "2025-08-07T13:32:27.59Z" }, - { url = "https://files.pythonhosted.org/packages/f7/c0/93885c4106d2626bf51fdec377d6aef740dfa5c4877461889a7cf8e565cc/greenlet-3.2.4-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:b6a7c19cf0d2742d0809a4c05975db036fdff50cd294a93632d6a310bf9ac02c", size = 269859, upload-time = "2025-08-07T13:16:16.003Z" }, - { url = "https://files.pythonhosted.org/packages/4d/f5/33f05dc3ba10a02dedb1485870cf81c109227d3d3aa280f0e48486cac248/greenlet-3.2.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:27890167f55d2387576d1f41d9487ef171849ea0359ce1510ca6e06c8bece11d", size = 627610, upload-time = "2025-08-07T13:43:01.345Z" }, - { url = "https://files.pythonhosted.org/packages/b2/a7/9476decef51a0844195f99ed5dc611d212e9b3515512ecdf7321543a7225/greenlet-3.2.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:18d9260df2b5fbf41ae5139e1be4e796d99655f023a636cd0e11e6406cca7d58", size = 639417, upload-time = "2025-08-07T13:45:32.094Z" }, - { url = "https://files.pythonhosted.org/packages/bd/e0/849b9159cbb176f8c0af5caaff1faffdece7a8417fcc6fe1869770e33e21/greenlet-3.2.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:671df96c1f23c4a0d4077a325483c1503c96a1b7d9db26592ae770daa41233d4", size = 634751, upload-time = "2025-08-07T13:53:18.848Z" }, - { url = "https://files.pythonhosted.org/packages/5f/d3/844e714a9bbd39034144dca8b658dcd01839b72bb0ec7d8014e33e3705f0/greenlet-3.2.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:16458c245a38991aa19676900d48bd1a6f2ce3e16595051a4db9d012154e8433", size = 634020, upload-time = "2025-08-07T13:18:36.841Z" }, - { url = "https://files.pythonhosted.org/packages/6b/4c/f3de2a8de0e840ecb0253ad0dc7e2bb3747348e798ec7e397d783a3cb380/greenlet-3.2.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9913f1a30e4526f432991f89ae263459b1c64d1608c0d22a5c79c287b3c70df", size = 582817, upload-time = "2025-08-07T13:18:35.48Z" }, - { url = "https://files.pythonhosted.org/packages/89/80/7332915adc766035c8980b161c2e5d50b2f941f453af232c164cff5e0aeb/greenlet-3.2.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b90654e092f928f110e0007f572007c9727b5265f7632c2fa7415b4689351594", size = 1111985, upload-time = "2025-08-07T13:42:42.425Z" }, - { url = "https://files.pythonhosted.org/packages/66/71/1928e2c80197353bcb9b50aa19c4d8e26ee6d7a900c564907665cf4b9a41/greenlet-3.2.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81701fd84f26330f0d5f4944d4e92e61afe6319dcd9775e39396e39d7c3e5f98", size = 1136137, upload-time = "2025-08-07T13:18:26.168Z" }, - { url = "https://files.pythonhosted.org/packages/4b/bf/7bd33643e48ed45dcc0e22572f650767832bd4e1287f97434943cc402148/greenlet-3.2.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:28a3c6b7cd72a96f61b0e4b2a36f681025b60ae4779cc73c1535eb5f29560b10", size = 1542941, upload-time = "2025-11-04T12:42:27.427Z" }, - { url = "https://files.pythonhosted.org/packages/9b/74/4bc433f91d0d09a1c22954a371f9df928cb85e72640870158853a83415e5/greenlet-3.2.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52206cd642670b0b320a1fd1cbfd95bca0e043179c1d8a045f2c6109dfe973be", size = 1609685, upload-time = "2025-11-04T12:42:29.242Z" }, - { url = "https://files.pythonhosted.org/packages/89/48/a5dc74dde38aeb2b15d418cec76ed50e1dd3d620ccda84d8199703248968/greenlet-3.2.4-cp39-cp39-win32.whl", hash = "sha256:65458b409c1ed459ea899e939f0e1cdb14f58dbc803f2f93c5eab5694d32671b", size = 281400, upload-time = "2025-08-07T14:02:20.263Z" }, - { url = "https://files.pythonhosted.org/packages/e5/44/342c4591db50db1076b8bda86ed0ad59240e3e1da17806a4cf10a6d0e447/greenlet-3.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:d2e685ade4dafd447ede19c31277a224a239a0a1a4eca4e6390efedf20260cfb", size = 298533, upload-time = "2025-08-07T13:56:34.168Z" }, -] - [[package]] name = "greenlet" version = "3.3.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/8a/99/1cd3411c56a410994669062bd73dd58270c00cc074cac15f385a1fd91f8a/greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98", size = 184690, upload-time = "2026-01-23T15:31:02.076Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fe/65/5b235b40581ad75ab97dcd8b4218022ae8e3ab77c13c919f1a1dfe9171fd/greenlet-3.3.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13", size = 273723, upload-time = "2026-01-23T15:30:37.521Z" }, @@ -2414,31 +1910,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e1/2b/98c7f93e6db9977aaee07eb1e51ca63bd5f779b900d362791d3252e60558/greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451", size = 233181, upload-time = "2026-01-23T15:33:00.29Z" }, ] -[[package]] -name = "griffe" -version = "1.14.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ec/d7/6c09dd7ce4c7837e4cdb11dce980cb45ae3cd87677298dc3b781b6bce7d3/griffe-1.14.0.tar.gz", hash = "sha256:9d2a15c1eca966d68e00517de5d69dd1bc5c9f2335ef6c1775362ba5b8651a13", size = 424684, upload-time = "2025-09-05T15:02:29.167Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" }, -] - [[package]] name = "griffe" version = "1.15.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.10'" }, + { name = "colorama" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0d/0c/3a471b6e31951dce2360477420d0a8d1e00dea6cf33b70f3e8c3ab6e28e1/griffe-1.15.0.tar.gz", hash = "sha256:7726e3afd6f298fbc3696e67958803e7ac843c1cfe59734b6251a40cdbfb5eea", size = 424112, upload-time = "2025-11-10T15:03:15.52Z" } wheels = [ @@ -2450,8 +1927,7 @@ name = "griffe-typingdoc" version = "0.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "griffe" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/77/d5e5fa0a8391bc2890ae45255847197299739833108dd76ee3c9b2ff0bba/griffe_typingdoc-0.3.0.tar.gz", hash = "sha256:59d9ef98d02caa7aed88d8df1119c9e48c02ed049ea50ce4018ace9331d20f8b", size = 33169, upload-time = "2025-10-23T12:01:39.037Z" } @@ -2464,8 +1940,7 @@ name = "griffe-warnings-deprecated" version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "griffe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7e/0e/f034e1714eb2c694d6196c75f77a02f9c69d19f9961c4804a016397bf3e5/griffe_warnings_deprecated-1.1.0.tar.gz", hash = "sha256:7bf21de327d59c66c7ce08d0166aa4292ce0577ff113de5878f428d102b6f7c5", size = 33260, upload-time = "2024-12-10T21:02:18.395Z" } wheels = [ @@ -2494,7 +1969,7 @@ name = "grpcio" version = "1.78.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/06/8a/3d098f35c143a89520e568e6539cc098fcd294495910e359889ce8741c84/grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5", size = 12852416, upload-time = "2026-02-06T09:57:18.093Z" } wheels = [ @@ -2548,16 +2023,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3c/05/33a7a4985586f27e1de4803887c417ec7ced145ebd069bc38a9607059e2b/grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65", size = 7696837, upload-time = "2026-02-06T09:56:40.173Z" }, { url = "https://files.pythonhosted.org/packages/73/77/7382241caf88729b106e49e7d18e3116216c778e6a7e833826eb96de22f7/grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c", size = 4142439, upload-time = "2026-02-06T09:56:43.258Z" }, { url = "https://files.pythonhosted.org/packages/48/b2/b096ccce418882fbfda4f7496f9357aaa9a5af1896a9a7f60d9f2b275a06/grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb", size = 4929852, upload-time = "2026-02-06T09:56:45.885Z" }, - { url = "https://files.pythonhosted.org/packages/58/6c/40a4bba2c753ea8eeb8d776a31e9c54f4e506edf36db93a3db5456725294/grpcio-1.78.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:86f85dd7c947baa707078a236288a289044836d4b640962018ceb9cd1f899af5", size = 5947902, upload-time = "2026-02-06T09:56:48.469Z" }, - { url = "https://files.pythonhosted.org/packages/c0/4c/ed7664a37a7008be41204c77e0d88bbc4ac531bcf0c27668cd066f9ff6e2/grpcio-1.78.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:de8cb00d1483a412a06394b8303feec5dcb3b55f81d83aa216dbb6a0b86a94f5", size = 11824772, upload-time = "2026-02-06T09:56:51.264Z" }, - { url = "https://files.pythonhosted.org/packages/9a/5b/45a5c23ba3c4a0f51352366d9b25369a2a51163ab1c93482cb8408726617/grpcio-1.78.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e888474dee2f59ff68130f8a397792d8cb8e17e6b3434339657ba4ee90845a8c", size = 6521579, upload-time = "2026-02-06T09:56:54.967Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/392e647d918004231e3d1c780ed125c48939bfc8f845adb8b5820410da3e/grpcio-1.78.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:86ce2371bfd7f212cf60d8517e5e854475c2c43ce14aa910e136ace72c6db6c1", size = 7199330, upload-time = "2026-02-06T09:56:57.611Z" }, - { url = "https://files.pythonhosted.org/packages/68/2f/42a52d78bdbdb3f1310ed690a3511cd004740281ca75d300b7bd6d9d3de3/grpcio-1.78.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0c689c02947d636bc7fab3e30cc3a3445cca99c834dfb77cd4a6cabfc1c5597", size = 6726696, upload-time = "2026-02-06T09:57:00.357Z" }, - { url = "https://files.pythonhosted.org/packages/0f/83/b3d932a4fbb2dce3056f6df2926fc2d3ddc5d5acbafbec32c84033cf3f23/grpcio-1.78.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ce7599575eeb25c0f4dc1be59cada6219f3b56176f799627f44088b21381a28a", size = 7299076, upload-time = "2026-02-06T09:57:04.124Z" }, - { url = "https://files.pythonhosted.org/packages/ba/d9/70ea1be55efaf91fd19f7258b1292772a8226cf1b0e237717fba671073cb/grpcio-1.78.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:684083fd383e9dc04c794adb838d4faea08b291ce81f64ecd08e4577c7398adf", size = 8284493, upload-time = "2026-02-06T09:57:06.746Z" }, - { url = "https://files.pythonhosted.org/packages/d0/2f/3dddccf49e3e75564655b84175fca092d3efd81d2979fc89c4b1c1d879dc/grpcio-1.78.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab399ef5e3cd2a721b1038a0f3021001f19c5ab279f145e1146bb0b9f1b2b12c", size = 7724340, upload-time = "2026-02-06T09:57:09.453Z" }, - { url = "https://files.pythonhosted.org/packages/79/ae/dfdb3183141db787a9363078a98764675996a7c2448883153091fd7c8527/grpcio-1.78.0-cp39-cp39-win32.whl", hash = "sha256:f3d6379493e18ad4d39537a82371c5281e153e963cecb13f953ebac155756525", size = 4077641, upload-time = "2026-02-06T09:57:11.881Z" }, - { url = "https://files.pythonhosted.org/packages/aa/aa/694b2f505345cfdd234cffb2525aa379a81695e6c02fd40d7e9193e871c6/grpcio-1.78.0-cp39-cp39-win_amd64.whl", hash = "sha256:5361a0630a7fdb58a6a97638ab70e1dae2893c4d08d7aba64ded28bb9e7a29df", size = 4799428, upload-time = "2026-02-06T09:57:14.493Z" }, ] [[package]] @@ -2661,13 +2126,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4d/31/14df99e1c43bd132eec921c2e7e11cda7852f65619bc0fc5bdc2d0cb126c/httptools-0.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f084813239e1eb403ddacd06a30de3d3e09a9b76e7894dcda2b22f8a726e9c60", size = 452631, upload-time = "2025-10-10T03:54:58.219Z" }, { url = "https://files.pythonhosted.org/packages/22/d2/b7e131f7be8d854d48cb6d048113c30f9a46dca0c9a8b08fcb3fcd588cdc/httptools-0.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7347714368fb2b335e9063bc2b96f2f87a9ceffcd9758ac295f8bbcd3ffbc0ca", size = 452910, upload-time = "2025-10-10T03:54:59.366Z" }, { url = "https://files.pythonhosted.org/packages/53/cf/878f3b91e4e6e011eff6d1fa9ca39f7eb17d19c9d7971b04873734112f30/httptools-0.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:cfabda2a5bb85aa2a904ce06d974a3f30fb36cc63d7feaddec05d2050acede96", size = 88205, upload-time = "2025-10-10T03:55:00.389Z" }, - { url = "https://files.pythonhosted.org/packages/90/de/b1fe0e8890f0292c266117d4cd268186758a9c34e576fbd573fdf3beacff/httptools-0.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ac50afa68945df63ec7a2707c506bd02239272288add34539a2ef527254626a4", size = 206454, upload-time = "2025-10-10T03:55:01.528Z" }, - { url = "https://files.pythonhosted.org/packages/57/a7/a675c90b49e550c7635ce209c01bc61daa5b08aef17da27ef4e0e78fcf3f/httptools-0.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de987bb4e7ac95b99b805b99e0aae0ad51ae61df4263459d36e07cf4052d8b3a", size = 110260, upload-time = "2025-10-10T03:55:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/03/44/fb5ef8136e6e97f7b020e97e40c03a999f97e68574d4998fa52b0a62b01b/httptools-0.7.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d169162803a24425eb5e4d51d79cbf429fd7a491b9e570a55f495ea55b26f0bf", size = 441524, upload-time = "2025-10-10T03:55:03.292Z" }, - { url = "https://files.pythonhosted.org/packages/b4/62/8496a5425341867796d7e2419695f74a74607054e227bbaeabec8323e87f/httptools-0.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49794f9250188a57fa73c706b46cb21a313edb00d337ca4ce1a011fe3c760b28", size = 440877, upload-time = "2025-10-10T03:55:04.282Z" }, - { url = "https://files.pythonhosted.org/packages/e8/f1/26c2e5214106bf6ed04d03e518ff28ca0c6b5390c5da7b12bbf94b40ae43/httptools-0.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aeefa0648362bb97a7d6b5ff770bfb774930a327d7f65f8208394856862de517", size = 425775, upload-time = "2025-10-10T03:55:05.341Z" }, - { url = "https://files.pythonhosted.org/packages/3a/34/7500a19257139725281f7939a7d1aa3701cf1ac4601a1690f9ab6f510e15/httptools-0.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0d92b10dbf0b3da4823cde6a96d18e6ae358a9daa741c71448975f6a2c339cad", size = 425001, upload-time = "2025-10-10T03:55:06.389Z" }, - { url = "https://files.pythonhosted.org/packages/71/04/31a7949d645ebf33a67f56a0024109444a52a271735e0647a210264f3e61/httptools-0.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:5ddbd045cfcb073db2449563dd479057f2c2b681ebc232380e63ef15edc9c023", size = 86818, upload-time = "2025-10-10T03:55:07.316Z" }, ] [[package]] @@ -2699,10 +2157,8 @@ name = "huggingface-hub" version = "0.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "filelock", version = "3.20.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "fsspec", version = "2025.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "fsspec", version = "2026.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "filelock" }, + { name = "fsspec" }, { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, { name = "packaging" }, { name = "pyyaml" }, @@ -2741,26 +2197,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] -[[package]] -name = "iniconfig" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, -] - [[package]] name = "iniconfig" version = "2.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, @@ -2805,7 +2245,7 @@ name = "jaraco-classes" version = "3.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "more-itertools", marker = "python_full_version >= '3.10'" }, + { name = "more-itertools" }, ] sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } wheels = [ @@ -2817,7 +2257,7 @@ name = "jaraco-context" version = "6.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "backports-tarfile", marker = "python_full_version >= '3.10' and python_full_version < '3.12'" }, + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/9c/a788f5bb29c61e456b8ee52ce76dbdd32fd72cd73dd67bc95f42c7a8d13c/jaraco_context-6.1.0.tar.gz", hash = "sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f", size = 15850, upload-time = "2026-01-13T02:53:53.847Z" } wheels = [ @@ -2829,7 +2269,7 @@ name = "jaraco-functools" version = "4.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "more-itertools", marker = "python_full_version >= '3.10'" }, + { name = "more-itertools" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } wheels = [ @@ -2950,18 +2390,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, - { url = "https://files.pythonhosted.org/packages/41/95/8e6611379c9ce8534ff94dd800c50d6d0061b2c9ae6386fbcd86c7386f0a/jiter-0.13.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:4397ee562b9f69d283e5674445551b47a5e8076fdde75e71bfac5891113dc543", size = 313635, upload-time = "2026-02-02T12:37:23.545Z" }, - { url = "https://files.pythonhosted.org/packages/70/ea/17db64dcaf84bbb187874232222030ea4d689e6008f93bda6e7c691bc4c7/jiter-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f90023f8f672e13ea1819507d2d21b9d2d1c18920a3b3a5f1541955a85b5504", size = 309761, upload-time = "2026-02-02T12:37:25.075Z" }, - { url = "https://files.pythonhosted.org/packages/a3/36/b2e2a7b12b94ecc7248acf2a8fe6288be893d1ebb9728655ceada22f00ad/jiter-0.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed0240dd1536a98c3ab55e929c60dfff7c899fecafcb7d01161b21a99fc8c363", size = 355245, upload-time = "2026-02-02T12:37:26.646Z" }, - { url = "https://files.pythonhosted.org/packages/77/3f/5b159663c5be622daec20074c997bb66bc1fac63c167c02aef3df476fb32/jiter-0.13.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6207fc61c395b26fffdcf637a0b06b4326f35bfa93c6e92fe1a166a21aeb6731", size = 365842, upload-time = "2026-02-02T12:37:28.207Z" }, - { url = "https://files.pythonhosted.org/packages/98/30/76a68fa2c9c815c6b7802a92fc354080d66ffba9acc4690fd85622f77ad4/jiter-0.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00203f47c214156df427b5989de74cb340c65c8180d09be1bf9de81d0abad599", size = 489223, upload-time = "2026-02-02T12:37:29.571Z" }, - { url = "https://files.pythonhosted.org/packages/a3/39/7c5cb85ccd71241513c878054c26a55828ccded6567d931a23ea4be73787/jiter-0.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c26ad6967c9dcedf10c995a21539c3aa57d4abad7001b7a84f621a263a6b605", size = 375762, upload-time = "2026-02-02T12:37:31.186Z" }, - { url = "https://files.pythonhosted.org/packages/a8/6a/381cd18d050b0102e60324e8d3f51f37ef02c56e9f4e5f0b7d26ba18958d/jiter-0.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a576f5dce9ac7de5d350b8e2f552cf364f32975ed84717c35379a51c7cb198bd", size = 364996, upload-time = "2026-02-02T12:37:32.931Z" }, - { url = "https://files.pythonhosted.org/packages/37/1e/d66310f1f7085c13ea6f1119c9566ec5d2cfd1dc90df963118a6869247bb/jiter-0.13.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b22945be8425d161f2e536cdae66da300b6b000f1c0ba3ddf237d1bfd45d21b8", size = 395463, upload-time = "2026-02-02T12:37:34.446Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ab/06ae77cb293f860b152c356c635c15aaa800ce48772865a41704d9fac80d/jiter-0.13.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6eeb7db8bc77dc20476bc2f7407a23dbe3d46d9cc664b166e3d474e1c1de4baa", size = 520944, upload-time = "2026-02-02T12:37:35.987Z" }, - { url = "https://files.pythonhosted.org/packages/f1/8e/57b49b20361c42a80d455a6d83cb38626204508cab4298d6a22880205319/jiter-0.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:19cd6f85e1dc090277c3ce90a5b7d96f32127681d825e71c9dce28788e39fc0c", size = 554955, upload-time = "2026-02-02T12:37:37.656Z" }, - { url = "https://files.pythonhosted.org/packages/79/dd/113489973c3b4256e383321aea11bd57389e401912fa48eb145a99b38767/jiter-0.13.0-cp39-cp39-win32.whl", hash = "sha256:dc3ce84cfd4fa9628fe62c4f85d0d597a4627d4242cfafac32a12cc1455d00f7", size = 206876, upload-time = "2026-02-02T12:37:39.225Z" }, - { url = "https://files.pythonhosted.org/packages/6e/73/2bdfc7133c5ee0c8f18cfe4a7582f3cfbbf3ff672cec1b5f4ca67ff9d041/jiter-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:9ffda299e417dc83362963966c50cb76d42da673ee140de8a8ac762d4bb2378b", size = 206404, upload-time = "2026-02-02T12:37:40.632Z" }, { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, @@ -2995,10 +2423,10 @@ name = "jsonschema" version = "4.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", marker = "python_full_version >= '3.10'" }, - { name = "jsonschema-specifications", marker = "python_full_version >= '3.10'" }, - { name = "referencing", marker = "python_full_version >= '3.10'" }, - { name = "rpds-py", marker = "python_full_version >= '3.10'" }, + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ @@ -3010,10 +2438,10 @@ name = "jsonschema-path" version = "0.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pathable", marker = "python_full_version >= '3.10'" }, - { name = "pyyaml", marker = "python_full_version >= '3.10'" }, - { name = "referencing", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, + { name = "pathable" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "requests" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } wheels = [ @@ -3025,7 +2453,7 @@ name = "jsonschema-specifications" version = "2025.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "referencing", marker = "python_full_version >= '3.10'" }, + { name = "referencing" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } wheels = [ @@ -3037,31 +2465,19 @@ name = "keyring" version = "25.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version >= '3.10' and python_full_version < '3.12'" }, - { name = "jaraco-classes", marker = "python_full_version >= '3.10'" }, - { name = "jaraco-context", marker = "python_full_version >= '3.10'" }, - { name = "jaraco-functools", marker = "python_full_version >= '3.10'" }, - { name = "jeepney", marker = "python_full_version >= '3.10' and sys_platform == 'linux'" }, - { name = "pywin32-ctypes", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, - { name = "secretstorage", marker = "python_full_version >= '3.10' and sys_platform == 'linux'" }, + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] -[[package]] -name = "lia-web" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cross-web", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/3d/7d574a7a5cf5fbc5fc09c07ea3696dd400353b7702bc009cf596b8c12035/lia_web-0.3.1.tar.gz", hash = "sha256:7f551269eddd729f1437e9341ad21622a849eb0c0975d9232ccbbaadbdc74c06", size = 2021, upload-time = "2025-12-25T20:41:51.195Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/8b/b628fc18658f94b3d094708a18b71083cf47628e85cbc6b9edba54d5b2d7/lia_web-0.3.1-py3-none-any.whl", hash = "sha256:e4e6e7a9381e228aca60a6f3d67dbae9a5f4638eced242d931f95797ddba3f8b", size = 5933, upload-time = "2025-12-25T20:41:52.289Z" }, -] - [[package]] name = "librt" version = "0.7.8" @@ -3133,16 +2549,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365", size = 41173, upload-time = "2026-01-14T12:55:59.315Z" }, { url = "https://files.pythonhosted.org/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32", size = 47668, upload-time = "2026-01-14T12:56:00.261Z" }, { url = "https://files.pythonhosted.org/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06", size = 40550, upload-time = "2026-01-14T12:56:01.542Z" }, - { url = "https://files.pythonhosted.org/packages/3b/9b/2668bb01f568bc89ace53736df950845f8adfcacdf6da087d5cef12110cb/librt-0.7.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c7e8f88f79308d86d8f39c491773cbb533d6cb7fa6476f35d711076ee04fceb6", size = 56680, upload-time = "2026-01-14T12:56:02.602Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d4/dbb3edf2d0ec4ba08dcaf1865833d32737ad208962d4463c022cea6e9d3c/librt-0.7.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:389bd25a0db916e1d6bcb014f11aa9676cedaa485e9ec3752dfe19f196fd377b", size = 58612, upload-time = "2026-01-14T12:56:03.616Z" }, - { url = "https://files.pythonhosted.org/packages/0f/c9/64b029de4ac9901fcd47832c650a0fd050555a452bd455ce8deddddfbb9f/librt-0.7.8-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73fd300f501a052f2ba52ede721232212f3b06503fa12665408ecfc9d8fd149c", size = 163654, upload-time = "2026-01-14T12:56:04.975Z" }, - { url = "https://files.pythonhosted.org/packages/81/5c/95e2abb1b48eb8f8c7fc2ae945321a6b82777947eb544cc785c3f37165b2/librt-0.7.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d772edc6a5f7835635c7562f6688e031f0b97e31d538412a852c49c9a6c92d5", size = 172477, upload-time = "2026-01-14T12:56:06.103Z" }, - { url = "https://files.pythonhosted.org/packages/7e/27/9bdf12e05b0eb089dd008d9c8aabc05748aad9d40458ade5e627c9538158/librt-0.7.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde8a130bd0f239e45503ab39fab239ace094d63ee1d6b67c25a63d741c0f71", size = 186220, upload-time = "2026-01-14T12:56:09.958Z" }, - { url = "https://files.pythonhosted.org/packages/53/6a/c3774f4cc95e68ed444a39f2c8bd383fd18673db7d6b98cfa709f6634b93/librt-0.7.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fdec6e2368ae4f796fc72fad7fd4bd1753715187e6d870932b0904609e7c878e", size = 183841, upload-time = "2026-01-14T12:56:11.109Z" }, - { url = "https://files.pythonhosted.org/packages/58/6b/48702c61cf83e9c04ad5cec8cad7e5e22a2cde23a13db8ef341598897ddd/librt-0.7.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00105e7d541a8f2ee5be52caacea98a005e0478cfe78c8080fbb7b5d2b340c63", size = 179751, upload-time = "2026-01-14T12:56:12.278Z" }, - { url = "https://files.pythonhosted.org/packages/35/87/5f607fc73a131d4753f4db948833063c6aad18e18a4e6fbf64316c37ae65/librt-0.7.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c6f8947d3dfd7f91066c5b4385812c18be26c9d5a99ca56667547f2c39149d94", size = 199319, upload-time = "2026-01-14T12:56:13.425Z" }, - { url = "https://files.pythonhosted.org/packages/6e/cc/b7c5ac28ae0f0645a9681248bae4ede665bba15d6f761c291853c5c5b78e/librt-0.7.8-cp39-cp39-win32.whl", hash = "sha256:41d7bb1e07916aeb12ae4a44e3025db3691c4149ab788d0315781b4d29b86afb", size = 43434, upload-time = "2026-01-14T12:56:14.781Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5d/dce0c92f786495adf2c1e6784d9c50a52fb7feb1cfb17af97a08281a6e82/librt-0.7.8-cp39-cp39-win_amd64.whl", hash = "sha256:e90a8e237753c83b8e484d478d9a996dc5e39fd5bd4c6ce32563bc8123f132be", size = 49801, upload-time = "2026-01-14T12:56:15.827Z" }, ] [[package]] @@ -3150,14 +2556,14 @@ name = "logfire" version = "4.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "executing", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-exporter-otlp-proto-http", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-instrumentation", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, - { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b1/29/4386b331b8aecad429c043bbd1b7684cdb56ff9e11a5bd96845483dc0968/logfire-4.22.0.tar.gz", hash = "sha256:284b3b955c7515d4428dbc1e04784c3e652e62acf7597bd64a0aa9ecb6a7dedd", size = 654771, upload-time = "2026-02-04T12:17:57.635Z" } wheels = [ @@ -3166,7 +2572,7 @@ wheels = [ [package.optional-dependencies] httpx = [ - { name = "opentelemetry-instrumentation-httpx", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-instrumentation-httpx" }, ] [[package]] @@ -3250,42 +2656,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/a0/89e6a024c3b4485b89ef86881c9d55e097e7cb0bdb74efb746f2fa6a9a76/lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80", size = 2153693, upload-time = "2025-10-24T07:19:31.379Z" }, { url = "https://files.pythonhosted.org/packages/b6/36/a0f007dc58fc1bbf51fb85dcc82fcb1f21b8c4261361de7dab0e3d8521ef/lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291", size = 1590104, upload-time = "2025-10-24T07:19:33.514Z" }, { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818, upload-time = "2025-10-24T07:19:36.039Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c5/918ed6c3af793764bae155d68df47bab2635ab7c94dee3dbb5d9c6d5ba38/lupa-2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8897dc6c3249786b2cdf2f83324febb436193d4581b6a71dea49f77bf8b19bb0", size = 956718, upload-time = "2025-10-24T07:20:03.086Z" }, - { url = "https://files.pythonhosted.org/packages/da/91/0ca797da854478225c0f6a8fc3c500a2f5c11826d732735beb5dffff9e85/lupa-2.6-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:4446396ca3830be0c106c70db4b4f622c37b2d447874c07952cafb9c57949a4a", size = 1923934, upload-time = "2025-10-24T07:20:05.428Z" }, - { url = "https://files.pythonhosted.org/packages/f5/7f/98a6a2535285d43457eb665822ab08447e2196b614db3152772d457ca426/lupa-2.6-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:5826e687c89995a6eaafeae242071ba16448eec1a9ee8e17ed48551b5d1e21c2", size = 987286, upload-time = "2025-10-24T07:20:07.338Z" }, - { url = "https://files.pythonhosted.org/packages/5f/50/edad7c180ab28aa543e6c3895e56a2c7a6ff92140a283316e6086f118552/lupa-2.6-cp39-cp39-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:5871935cb36d1d22f9c04ac0db75c06751bd95edcfa0d9309f732de908e297a9", size = 1176541, upload-time = "2025-10-24T07:20:09.305Z" }, - { url = "https://files.pythonhosted.org/packages/24/b3/27a0ec4c73011e86f9bd2eada010062308a4ed32921898d066ae54e064e1/lupa-2.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:43eb6e43ea8512d0d65b995d36dd9d77aa02598035e25b84c23a1b58700c9fb2", size = 1058981, upload-time = "2025-10-24T07:20:11.7Z" }, - { url = "https://files.pythonhosted.org/packages/a4/12/d55d45a8c253e7981f59ae920bac49dbd49888954b25fd1eb3a7be1321db/lupa-2.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:559714053018d9885cc8c36a33c5b7eb9aad30fb6357719cac3ce4dc6b39157e", size = 2103336, upload-time = "2025-10-24T07:20:13.71Z" }, - { url = "https://files.pythonhosted.org/packages/ab/17/058cc212c22d6a25990226afd02c741b2813b5f325396a9180b4accb70ac/lupa-2.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:57ac88a00ce59bd9d4ddcd4fca8e02564765725f5068786b011c9d1be3de20c5", size = 1083209, upload-time = "2025-10-24T07:20:15.587Z" }, - { url = "https://files.pythonhosted.org/packages/e6/01/8ca3a56a4e127784a15f0c7ec1f67e9894c2e9d4bf402389ddda4ea8081b/lupa-2.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:b683fbd867c2e54c44a686361b75eee7e7a790da55afdbe89f1f23b106de0274", size = 1193077, upload-time = "2025-10-24T07:20:17.857Z" }, - { url = "https://files.pythonhosted.org/packages/07/1b/c7fe79bcda6d489306bb7c1a9b4d545b7f0930b9ce80080643fc39b3fdc9/lupa-2.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d2f656903a2ed2e074bf2b7d300968028dfa327a45b055be8e3b51ef0b82f9bf", size = 2198584, upload-time = "2025-10-24T07:20:20.468Z" }, - { url = "https://files.pythonhosted.org/packages/9e/df/3f7631eea3478ac3868cbcb2763c1a4e2f7b875fcb2683f956bf7aabf65f/lupa-2.6-cp39-cp39-win32.whl", hash = "sha256:bf28f68ae231b72008523ab5ac23835ba0f76e0e99ec38b59766080a84eb596a", size = 1414693, upload-time = "2025-10-24T07:20:23.477Z" }, - { url = "https://files.pythonhosted.org/packages/08/e0/3fd9617814663129fa4a9b33a980c3fe344297337cb550c738f87f730f6b/lupa-2.6-cp39-cp39-win_amd64.whl", hash = "sha256:b4b2e9b3795a9897cf6cfcc58d08210fdc0d13ab47c9a0e13858c68932d8353c", size = 1658877, upload-time = "2025-10-24T07:20:27.086Z" }, -] - -[[package]] -name = "markdown" -version = "3.9" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8d/37/02347f6d6d8279247a5837082ebc26fc0d5aaeaf75aa013fcbb433c777ab/markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a", size = 364585, upload-time = "2025-09-04T20:25:22.885Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/ae/44c4a6a4cbb496d93c6257954260fe3a6e91b7bed2240e5dad2a717f5111/markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280", size = 107441, upload-time = "2025-09-04T20:25:21.784Z" }, ] [[package]] name = "markdown" version = "3.10.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/b7/b1/af95bcae8549f1f3fd70faacb29075826a0d689a27f232e8cee315efa053/markdown-3.10.1.tar.gz", hash = "sha256:1c19c10bd5c14ac948c53d0d762a04e2fa35a6d58a6b7b1e6bfcbe6fefc0001a", size = 365402, upload-time = "2026-01-21T18:09:28.206Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/59/1b/6ef961f543593969d25b2afe57a3564200280528caa9bd1082eecdd7b3bc/markdown-3.10.1-py3-none-any.whl", hash = "sha256:867d788939fe33e4b736426f5b9f651ad0c0ae0ecf89df0ca5d1176c70812fe3", size = 107684, upload-time = "2026-01-21T18:09:27.203Z" }, @@ -3296,39 +2672,19 @@ name = "markdown-include-variants" version = "0.0.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c5/47/ec9eae4a6d2f336d95681df43720e2b25b045dc3ed44ae6d30a5ce2f5dff/markdown_include_variants-0.0.8.tar.gz", hash = "sha256:46d812340c64dcd3646b1eaa356bafb31626dd7b4955d15c44ff8c48c6357227", size = 46882, upload-time = "2025-12-12T16:11:04.254Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4e/0e/130958e7ec50d13f2ee7b6c142df5c352520a9251baf1652e41262703857/markdown_include_variants-0.0.8-py3-none-any.whl", hash = "sha256:425a300ae25fbcd598506cba67859a9dfa047333e869e0ff2e11a5e354b326dc", size = 8120, upload-time = "2025-12-12T16:11:02.881Z" }, ] -[[package]] -name = "markdown-it-py" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "mdurl", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, -] - [[package]] name = "markdown-it-py" version = "4.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "mdurl", marker = "python_full_version >= '3.10'" }, + { name = "mdurl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } wheels = [ @@ -3418,17 +2774,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, - { url = "https://files.pythonhosted.org/packages/56/23/0d8c13a44bde9154821586520840643467aee574d8ce79a17da539ee7fed/markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", size = 11623, upload-time = "2025-09-27T18:37:29.296Z" }, - { url = "https://files.pythonhosted.org/packages/fd/23/07a2cb9a8045d5f3f0890a8c3bc0859d7a47bfd9a560b563899bec7b72ed/markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", size = 12049, upload-time = "2025-09-27T18:37:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e4/6be85eb81503f8e11b61c0b6369b6e077dcf0a74adbd9ebf6b349937b4e9/markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", size = 21923, upload-time = "2025-09-27T18:37:31.177Z" }, - { url = "https://files.pythonhosted.org/packages/6f/bc/4dc914ead3fe6ddaef035341fee0fc956949bbd27335b611829292b89ee2/markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", size = 20543, upload-time = "2025-09-27T18:37:32.168Z" }, - { url = "https://files.pythonhosted.org/packages/89/6e/5fe81fbcfba4aef4093d5f856e5c774ec2057946052d18d168219b7bd9f9/markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", size = 20585, upload-time = "2025-09-27T18:37:33.166Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f6/e0e5a3d3ae9c4020f696cd055f940ef86b64fe88de26f3a0308b9d3d048c/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", size = 21387, upload-time = "2025-09-27T18:37:34.185Z" }, - { url = "https://files.pythonhosted.org/packages/c8/25/651753ef4dea08ea790f4fbb65146a9a44a014986996ca40102e237aa49a/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", size = 20133, upload-time = "2025-09-27T18:37:35.138Z" }, - { url = "https://files.pythonhosted.org/packages/dc/0a/c3cf2b4fef5f0426e8a6d7fce3cb966a17817c568ce59d76b92a233fdbec/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", size = 20588, upload-time = "2025-09-27T18:37:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/cd/1b/a7782984844bd519ad4ffdbebbba2671ec5d0ebbeac34736c15fb86399e8/markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", size = 14566, upload-time = "2025-09-27T18:37:37.09Z" }, - { url = "https://files.pythonhosted.org/packages/18/1f/8d9c20e1c9440e215a44be5ab64359e207fcb4f675543f1cf9a2a7f648d0/markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", size = 15053, upload-time = "2025-09-27T18:37:38.054Z" }, - { url = "https://files.pythonhosted.org/packages/4e/d3/fe08482b5cd995033556d45041a4f4e76e7f0521112a9c9991d40d39825f/markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", size = 13928, upload-time = "2025-09-27T18:37:39.037Z" }, ] [[package]] @@ -3436,20 +2781,20 @@ name = "mcp" version = "1.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "httpx", marker = "python_full_version >= '3.10'" }, - { name = "httpx-sse", marker = "python_full_version >= '3.10'" }, - { name = "jsonschema", marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "pydantic-settings", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pyjwt", extra = ["crypto"], marker = "python_full_version >= '3.10'" }, - { name = "python-multipart", version = "0.0.22", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pywin32", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, - { name = "sse-starlette", marker = "python_full_version >= '3.10'" }, - { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, - { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, - { name = "uvicorn", version = "0.40.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and sys_platform != 'emscripten'" }, + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" } wheels = [ @@ -3471,8 +2816,7 @@ version = "1.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cyclic" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "rcslice" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bf/f0/f395a9cf164471d3c7bbe58cbd64d74289575a8b85a962b49a804ab7ed34/mdx_include-1.4.2.tar.gz", hash = "sha256:992f9fbc492b5cf43f7d8cb4b90b52a4e4c5fdd7fd04570290a83eea5c84f297", size = 15051, upload-time = "2022-07-26T05:46:14.129Z" } @@ -3512,14 +2856,11 @@ name = "mkdocs" version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "ghp-import" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "markupsafe" }, { name = "mergedeep" }, { name = "mkdocs-get-deps" }, @@ -3539,8 +2880,7 @@ name = "mkdocs-autorefs" version = "1.4.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "markupsafe" }, { name = "mkdocs" }, ] @@ -3554,10 +2894,8 @@ name = "mkdocs-get-deps" version = "0.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "mergedeep" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "platformdirs", version = "4.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "platformdirs" }, { name = "pyyaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" } @@ -3579,8 +2917,7 @@ dependencies = [ { name = "pyyaml" }, { name = "requests" }, { name = "super-collections" }, - { name = "termcolor", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "termcolor", version = "3.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "termcolor" }, ] sdist = { url = "https://files.pythonhosted.org/packages/92/15/e6a44839841ebc9c5872fa0e6fad1c3757424e4fe026093b68e9f386d136/mkdocs_macros_plugin-1.5.0.tar.gz", hash = "sha256:12aa45ce7ecb7a445c66b9f649f3dd05e9b92e8af6bc65e4acd91d26f878c01f", size = 37730, upload-time = "2025-11-13T08:08:55.545Z" } wheels = [ @@ -3596,8 +2933,7 @@ dependencies = [ { name = "backrefs" }, { name = "colorama" }, { name = "jinja2" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "mkdocs" }, { name = "mkdocs-material-extensions" }, { name = "paginate" }, @@ -3631,47 +2967,17 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c4/ec/38443b1f2a3821bbcb24e46cd8ba979154417794d54baf949fefde1c2146/mkdocs_redirects-1.2.2-py3-none-any.whl", hash = "sha256:7dbfa5647b79a3589da4401403d69494bd1f4ad03b9c15136720367e1f340ed5", size = 6142, upload-time = "2024-11-07T14:57:19.143Z" }, ] -[[package]] -name = "mkdocstrings" -version = "0.30.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, - { name = "jinja2", marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markupsafe", marker = "python_full_version < '3.10'" }, - { name = "mkdocs", marker = "python_full_version < '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, - { name = "pymdown-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c5/33/2fa3243439f794e685d3e694590d28469a9b8ea733af4b48c250a3ffc9a0/mkdocstrings-0.30.1.tar.gz", hash = "sha256:84a007aae9b707fb0aebfc9da23db4b26fc9ab562eb56e335e9ec480cb19744f", size = 106350, upload-time = "2025-09-19T10:49:26.446Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/2c/f0dc4e1ee7f618f5bff7e05898d20bf8b6e7fa612038f768bfa295f136a4/mkdocstrings-0.30.1-py3-none-any.whl", hash = "sha256:41bd71f284ca4d44a668816193e4025c950b002252081e387433656ae9a70a82", size = 36704, upload-time = "2025-09-19T10:49:24.805Z" }, -] - -[package.optional-dependencies] -python = [ - { name = "mkdocstrings-python", version = "1.18.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] - [[package]] name = "mkdocstrings" version = "1.0.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "jinja2", marker = "python_full_version >= '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "markupsafe", marker = "python_full_version >= '3.10'" }, - { name = "mkdocs", marker = "python_full_version >= '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version >= '3.10'" }, - { name = "pymdown-extensions", marker = "python_full_version >= '3.10'" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mkdocs" }, + { name = "mkdocs-autorefs" }, + { name = "pymdown-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/4d/1ca8a9432579184599714aaeb36591414cc3d3bfd9d494f6db540c995ae4/mkdocstrings-1.0.2.tar.gz", hash = "sha256:48edd0ccbcb9e30a3121684e165261a9d6af4d63385fc4f39a54a49ac3b32ea8", size = 101048, upload-time = "2026-01-24T15:57:25.735Z" } wheels = [ @@ -3680,40 +2986,18 @@ wheels = [ [package.optional-dependencies] python = [ - { name = "mkdocstrings-python", version = "2.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, -] - -[[package]] -name = "mkdocstrings-python" -version = "1.18.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version < '3.10'" }, - { name = "mkdocstrings", version = "0.30.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" }, + { name = "mkdocstrings-python" }, ] [[package]] name = "mkdocstrings-python" version = "2.0.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "mkdocs-autorefs", marker = "python_full_version >= '3.10'" }, - { name = "mkdocstrings", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "griffe" }, + { name = "mkdocs-autorefs" }, + { name = "mkdocstrings" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/24/75/d30af27a2906f00eb90143470272376d728521997800f5dce5b340ba35bc/mkdocstrings_python-2.0.1.tar.gz", hash = "sha256:843a562221e6a471fefdd4b45cc6c22d2607ccbad632879234fa9692e9cf7732", size = 199345, upload-time = "2025-12-03T14:26:11.755Z" } wheels = [ @@ -3864,24 +3148,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ee/74525ebe3eb5fddcd6735fc03cbea3feeed4122b53bc798ac32d297ac9ae/multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f", size = 77107, upload-time = "2026-01-26T02:46:12.608Z" }, - { url = "https://files.pythonhosted.org/packages/f0/9a/ce8744e777a74b3050b1bf56be3eed1053b3457302ea055f1ea437200a23/multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358", size = 44943, upload-time = "2026-01-26T02:46:14.016Z" }, - { url = "https://files.pythonhosted.org/packages/83/9c/1d2a283d9c6f31e260cb6c2fccadc3edcf6c4c14ee0929cd2af4d2606dd7/multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5", size = 44603, upload-time = "2026-01-26T02:46:15.391Z" }, - { url = "https://files.pythonhosted.org/packages/87/9d/3b186201671583d8e8d6d79c07481a5aafd0ba7575e3d8566baec80c1e82/multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0", size = 240573, upload-time = "2026-01-26T02:46:16.783Z" }, - { url = "https://files.pythonhosted.org/packages/42/7d/a52f5d4d0754311d1ac78478e34dff88de71259a8585e05ee14e5f877caf/multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8", size = 240106, upload-time = "2026-01-26T02:46:18.432Z" }, - { url = "https://files.pythonhosted.org/packages/84/9f/d80118e6c30ff55b7d171bdc5520aad4b9626e657520b8d7c8ca8c2fad12/multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0", size = 219418, upload-time = "2026-01-26T02:46:20.526Z" }, - { url = "https://files.pythonhosted.org/packages/c7/bd/896e60b3457f194de77c7de64f9acce9f75da0518a5230ce1df534f6747b/multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f", size = 252124, upload-time = "2026-01-26T02:46:22.157Z" }, - { url = "https://files.pythonhosted.org/packages/f4/de/ba6b30447c36a37078d0ba604aa12c1a52887af0c355236ca6e0a9d5286f/multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f", size = 249402, upload-time = "2026-01-26T02:46:23.718Z" }, - { url = "https://files.pythonhosted.org/packages/c2/b2/50a383c96230e432895a2fd3bcfe1b65785899598259d871d5de6b93180c/multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e", size = 240346, upload-time = "2026-01-26T02:46:25.393Z" }, - { url = "https://files.pythonhosted.org/packages/89/37/16d391fd8da544b1489306e38a46785fa41dd0f0ef766837ed7d4676dde0/multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2", size = 237010, upload-time = "2026-01-26T02:46:27.408Z" }, - { url = "https://files.pythonhosted.org/packages/b0/24/3152ee026eda86d5d3e3685182911e6951af7a016579da931080ce6ac9ad/multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8", size = 232018, upload-time = "2026-01-26T02:46:29.941Z" }, - { url = "https://files.pythonhosted.org/packages/9c/1f/48d3c27a72be7fd23a55d8847193c459959bf35a5bb5844530dab00b739b/multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941", size = 241498, upload-time = "2026-01-26T02:46:32.052Z" }, - { url = "https://files.pythonhosted.org/packages/1a/45/413643ae2952d0decdf6c1250f86d08a43e143271441e81027e38d598bd7/multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a", size = 247957, upload-time = "2026-01-26T02:46:33.666Z" }, - { url = "https://files.pythonhosted.org/packages/50/f8/f1d0ac23df15e0470776388bdb261506f63af1f81d28bacb5e262d6e12b6/multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de", size = 241651, upload-time = "2026-01-26T02:46:35.7Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c9/1a2a18f383cf129add66b6c36b75c3911a7ba95cf26cb141482de085cc12/multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5", size = 236371, upload-time = "2026-01-26T02:46:37.37Z" }, - { url = "https://files.pythonhosted.org/packages/bb/aa/77d87e3fca31325b87e0eb72d5fe9a7472dcb51391a42df7ac1f3842f6c0/multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0", size = 41426, upload-time = "2026-01-26T02:46:39.026Z" }, - { url = "https://files.pythonhosted.org/packages/e3/b3/e8863e6a2da15a9d7e98976ff402e871b7352c76566df6c18d0378e0d9cf/multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4", size = 46180, upload-time = "2026-01-26T02:46:40.422Z" }, - { url = "https://files.pythonhosted.org/packages/93/d3/dd4fa951ad5b5fa216bf30054d705683d13405eea7459833d78f31b74c9c/multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9", size = 43231, upload-time = "2026-01-26T02:46:41.945Z" }, { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, ] @@ -3928,12 +3194,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/88436084550ca9af5e610fa45286be04c3b63374df3e021c762fe8c4369f/mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3", size = 13102606, upload-time = "2025-12-15T05:02:46.833Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a5/43dfad311a734b48a752790571fd9e12d61893849a01bff346a54011957f/mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a", size = 12164496, upload-time = "2025-12-15T05:03:41.947Z" }, - { url = "https://files.pythonhosted.org/packages/88/f0/efbfa391395cce2f2771f937e0620cfd185ec88f2b9cd88711028a768e96/mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67", size = 12772068, upload-time = "2025-12-15T05:02:53.689Z" }, - { url = "https://files.pythonhosted.org/packages/25/05/58b3ba28f5aed10479e899a12d2120d582ba9fa6288851b20bf1c32cbb4f/mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e", size = 13520385, upload-time = "2025-12-15T05:02:38.328Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a0/c006ccaff50b31e542ae69b92fe7e2f55d99fba3a55e01067dd564325f85/mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376", size = 13796221, upload-time = "2025-12-15T05:03:22.147Z" }, - { url = "https://files.pythonhosted.org/packages/b2/ff/8bdb051cd710f01b880472241bd36b3f817a8e1c5d5540d0b761675b6de2/mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24", size = 10055456, upload-time = "2025-12-15T05:03:35.169Z" }, { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, ] @@ -3946,31 +3206,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] -[[package]] -name = "nexus-rpc" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, -] - [[package]] name = "nexus-rpc" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/06/50/95d7bc91f900da5e22662c82d9bf0f72a4b01f2a552708bf2f43807707a1/nexus_rpc-1.2.0.tar.gz", hash = "sha256:b4ddaffa4d3996aaeadf49b80dfcdfbca48fe4cb616defaf3b3c5c2c8fc61890", size = 74142, upload-time = "2025-11-17T19:17:06.798Z" } wheels = [ @@ -4001,7 +3242,7 @@ name = "openapi-pydantic" version = "0.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pydantic", marker = "python_full_version >= '3.10'" }, + { name = "pydantic" }, ] sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } wheels = [ @@ -4026,7 +3267,7 @@ name = "opentelemetry-exporter-otlp-proto-common" version = "1.39.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "opentelemetry-proto", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-proto" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" } wheels = [ @@ -4038,13 +3279,13 @@ name = "opentelemetry-exporter-otlp-proto-http" version = "1.39.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "googleapis-common-protos", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-exporter-otlp-proto-common", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-proto", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" } wheels = [ @@ -4056,10 +3297,10 @@ name = "opentelemetry-instrumentation" version = "0.60b1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "wrapt", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, ] sdist = { url = "https://files.pythonhosted.org/packages/41/0f/7e6b713ac117c1f5e4e3300748af699b9902a2e5e34c9cf443dde25a01fa/opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a", size = 31706, upload-time = "2025-12-11T13:36:42.515Z" } wheels = [ @@ -4071,11 +3312,11 @@ name = "opentelemetry-instrumentation-httpx" version = "0.60b1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-instrumentation", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-util-http", marker = "python_full_version >= '3.10'" }, - { name = "wrapt", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, ] sdist = { url = "https://files.pythonhosted.org/packages/86/08/11208bcfcab4fc2023252c3f322aa397fd9ad948355fea60f5fc98648603/opentelemetry_instrumentation_httpx-0.60b1.tar.gz", hash = "sha256:a506ebaf28c60112cbe70ad4f0338f8603f148938cb7b6794ce1051cd2b270ae", size = 20611, upload-time = "2025-12-11T13:37:01.661Z" } wheels = [ @@ -4087,7 +3328,7 @@ name = "opentelemetry-proto" version = "1.39.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "protobuf" }, ] sdist = { url = "https://files.pythonhosted.org/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" } wheels = [ @@ -4099,9 +3340,9 @@ name = "opentelemetry-sdk" version = "1.39.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-semantic-conventions", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" } wheels = [ @@ -4113,8 +3354,8 @@ name = "opentelemetry-semantic-conventions" version = "0.60b1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" } wheels = [ @@ -4130,111 +3371,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/5c/d3f1733665f7cd582ef0842fb1d2ed0bc1fba10875160593342d22bba375/opentelemetry_util_http-0.60b1-py3-none-any.whl", hash = "sha256:66381ba28550c91bee14dcba8979ace443444af1ed609226634596b4b0faf199", size = 8947, upload-time = "2025-12-11T13:36:37.151Z" }, ] -[[package]] -name = "orjson" -version = "3.11.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/04/b8/333fdb27840f3bf04022d21b654a35f58e15407183aeb16f3b41aa053446/orjson-3.11.5.tar.gz", hash = "sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5", size = 5972347, upload-time = "2025-12-06T15:55:39.458Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/19/b22cf9dad4db20c8737041046054cbd4f38bb5a2d0e4bb60487832ce3d76/orjson-3.11.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:df9eadb2a6386d5ea2bfd81309c505e125cfc9ba2b1b99a97e60985b0b3665d1", size = 245719, upload-time = "2025-12-06T15:53:43.877Z" }, - { url = "https://files.pythonhosted.org/packages/03/2e/b136dd6bf30ef5143fbe76a4c142828b55ccc618be490201e9073ad954a1/orjson-3.11.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccc70da619744467d8f1f49a8cadae5ec7bbe054e5232d95f92ed8737f8c5870", size = 132467, upload-time = "2025-12-06T15:53:45.379Z" }, - { url = "https://files.pythonhosted.org/packages/ae/fc/ae99bfc1e1887d20a0268f0e2686eb5b13d0ea7bbe01de2b566febcd2130/orjson-3.11.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:073aab025294c2f6fc0807201c76fdaed86f8fc4be52c440fb78fbb759a1ac09", size = 130702, upload-time = "2025-12-06T15:53:46.659Z" }, - { url = "https://files.pythonhosted.org/packages/6e/43/ef7912144097765997170aca59249725c3ab8ef6079f93f9d708dd058df5/orjson-3.11.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:835f26fa24ba0bb8c53ae2a9328d1706135b74ec653ed933869b74b6909e63fd", size = 135907, upload-time = "2025-12-06T15:53:48.487Z" }, - { url = "https://files.pythonhosted.org/packages/3f/da/24d50e2d7f4092ddd4d784e37a3fa41f22ce8ed97abc9edd222901a96e74/orjson-3.11.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667c132f1f3651c14522a119e4dd631fad98761fa960c55e8e7430bb2a1ba4ac", size = 139935, upload-time = "2025-12-06T15:53:49.88Z" }, - { url = "https://files.pythonhosted.org/packages/02/4a/b4cb6fcbfff5b95a3a019a8648255a0fac9b221fbf6b6e72be8df2361feb/orjson-3.11.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42e8961196af655bb5e63ce6c60d25e8798cd4dfbc04f4203457fa3869322c2e", size = 137541, upload-time = "2025-12-06T15:53:51.226Z" }, - { url = "https://files.pythonhosted.org/packages/a5/99/a11bd129f18c2377c27b2846a9d9be04acec981f770d711ba0aaea563984/orjson-3.11.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75412ca06e20904c19170f8a24486c4e6c7887dea591ba18a1ab572f1300ee9f", size = 139031, upload-time = "2025-12-06T15:53:52.309Z" }, - { url = "https://files.pythonhosted.org/packages/64/29/d7b77d7911574733a036bb3e8ad7053ceb2b7d6ea42208b9dbc55b23b9ed/orjson-3.11.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6af8680328c69e15324b5af3ae38abbfcf9cbec37b5346ebfd52339c3d7e8a18", size = 141622, upload-time = "2025-12-06T15:53:53.606Z" }, - { url = "https://files.pythonhosted.org/packages/93/41/332db96c1de76b2feda4f453e91c27202cd092835936ce2b70828212f726/orjson-3.11.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a86fe4ff4ea523eac8f4b57fdac319faf037d3c1be12405e6a7e86b3fbc4756a", size = 413800, upload-time = "2025-12-06T15:53:54.866Z" }, - { url = "https://files.pythonhosted.org/packages/76/e1/5a0d148dd1f89ad2f9651df67835b209ab7fcb1118658cf353425d7563e9/orjson-3.11.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e607b49b1a106ee2086633167033afbd63f76f2999e9236f638b06b112b24ea7", size = 151198, upload-time = "2025-12-06T15:53:56.383Z" }, - { url = "https://files.pythonhosted.org/packages/0d/96/8db67430d317a01ae5cf7971914f6775affdcfe99f5bff9ef3da32492ecc/orjson-3.11.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7339f41c244d0eea251637727f016b3d20050636695bc78345cce9029b189401", size = 141984, upload-time = "2025-12-06T15:53:57.746Z" }, - { url = "https://files.pythonhosted.org/packages/71/49/40d21e1aa1ac569e521069228bb29c9b5a350344ccf922a0227d93c2ed44/orjson-3.11.5-cp310-cp310-win32.whl", hash = "sha256:8be318da8413cdbbce77b8c5fac8d13f6eb0f0db41b30bb598631412619572e8", size = 135272, upload-time = "2025-12-06T15:53:59.769Z" }, - { url = "https://files.pythonhosted.org/packages/c4/7e/d0e31e78be0c100e08be64f48d2850b23bcb4d4c70d114f4e43b39f6895a/orjson-3.11.5-cp310-cp310-win_amd64.whl", hash = "sha256:b9f86d69ae822cabc2a0f6c099b43e8733dda788405cba2665595b7e8dd8d167", size = 133360, upload-time = "2025-12-06T15:54:01.25Z" }, - { url = "https://files.pythonhosted.org/packages/fd/68/6b3659daec3a81aed5ab47700adb1a577c76a5452d35b91c88efee89987f/orjson-3.11.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9c8494625ad60a923af6b2b0bd74107146efe9b55099e20d7740d995f338fcd8", size = 245318, upload-time = "2025-12-06T15:54:02.355Z" }, - { url = "https://files.pythonhosted.org/packages/e9/00/92db122261425f61803ccf0830699ea5567439d966cbc35856fe711bfe6b/orjson-3.11.5-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:7bb2ce0b82bc9fd1168a513ddae7a857994b780b2945a8c51db4ab1c4b751ebc", size = 129491, upload-time = "2025-12-06T15:54:03.877Z" }, - { url = "https://files.pythonhosted.org/packages/94/4f/ffdcb18356518809d944e1e1f77589845c278a1ebbb5a8297dfefcc4b4cb/orjson-3.11.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67394d3becd50b954c4ecd24ac90b5051ee7c903d167459f93e77fc6f5b4c968", size = 132167, upload-time = "2025-12-06T15:54:04.944Z" }, - { url = "https://files.pythonhosted.org/packages/97/c6/0a8caff96f4503f4f7dd44e40e90f4d14acf80d3b7a97cb88747bb712d3e/orjson-3.11.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:298d2451f375e5f17b897794bcc3e7b821c0f32b4788b9bcae47ada24d7f3cf7", size = 130516, upload-time = "2025-12-06T15:54:06.274Z" }, - { url = "https://files.pythonhosted.org/packages/4d/63/43d4dc9bd9954bff7052f700fdb501067f6fb134a003ddcea2a0bb3854ed/orjson-3.11.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa5e4244063db8e1d87e0f54c3f7522f14b2dc937e65d5241ef0076a096409fd", size = 135695, upload-time = "2025-12-06T15:54:07.702Z" }, - { url = "https://files.pythonhosted.org/packages/87/6f/27e2e76d110919cb7fcb72b26166ee676480a701bcf8fc53ac5d0edce32f/orjson-3.11.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1db2088b490761976c1b2e956d5d4e6409f3732e9d79cfa69f876c5248d1baf9", size = 139664, upload-time = "2025-12-06T15:54:08.828Z" }, - { url = "https://files.pythonhosted.org/packages/d4/f8/5966153a5f1be49b5fbb8ca619a529fde7bc71aa0a376f2bb83fed248bcd/orjson-3.11.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2ed66358f32c24e10ceea518e16eb3549e34f33a9d51f99ce23b0251776a1ef", size = 137289, upload-time = "2025-12-06T15:54:09.898Z" }, - { url = "https://files.pythonhosted.org/packages/a7/34/8acb12ff0299385c8bbcbb19fbe40030f23f15a6de57a9c587ebf71483fb/orjson-3.11.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2021afda46c1ed64d74b555065dbd4c2558d510d8cec5ea6a53001b3e5e82a9", size = 138784, upload-time = "2025-12-06T15:54:11.022Z" }, - { url = "https://files.pythonhosted.org/packages/ee/27/910421ea6e34a527f73d8f4ee7bdffa48357ff79c7b8d6eb6f7b82dd1176/orjson-3.11.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b42ffbed9128e547a1647a3e50bc88ab28ae9daa61713962e0d3dd35e820c125", size = 141322, upload-time = "2025-12-06T15:54:12.427Z" }, - { url = "https://files.pythonhosted.org/packages/87/a3/4b703edd1a05555d4bb1753d6ce44e1a05b7a6d7c164d5b332c795c63d70/orjson-3.11.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:8d5f16195bb671a5dd3d1dbea758918bada8f6cc27de72bd64adfbd748770814", size = 413612, upload-time = "2025-12-06T15:54:13.858Z" }, - { url = "https://files.pythonhosted.org/packages/1b/36/034177f11d7eeea16d3d2c42a1883b0373978e08bc9dad387f5074c786d8/orjson-3.11.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c0e5d9f7a0227df2927d343a6e3859bebf9208b427c79bd31949abcc2fa32fa5", size = 150993, upload-time = "2025-12-06T15:54:15.189Z" }, - { url = "https://files.pythonhosted.org/packages/44/2f/ea8b24ee046a50a7d141c0227c4496b1180b215e728e3b640684f0ea448d/orjson-3.11.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:23d04c4543e78f724c4dfe656b3791b5f98e4c9253e13b2636f1af5d90e4a880", size = 141774, upload-time = "2025-12-06T15:54:16.451Z" }, - { url = "https://files.pythonhosted.org/packages/8a/12/cc440554bf8200eb23348a5744a575a342497b65261cd65ef3b28332510a/orjson-3.11.5-cp311-cp311-win32.whl", hash = "sha256:c404603df4865f8e0afe981aa3c4b62b406e6d06049564d58934860b62b7f91d", size = 135109, upload-time = "2025-12-06T15:54:17.73Z" }, - { url = "https://files.pythonhosted.org/packages/a3/83/e0c5aa06ba73a6760134b169f11fb970caa1525fa4461f94d76e692299d9/orjson-3.11.5-cp311-cp311-win_amd64.whl", hash = "sha256:9645ef655735a74da4990c24ffbd6894828fbfa117bc97c1edd98c282ecb52e1", size = 133193, upload-time = "2025-12-06T15:54:19.426Z" }, - { url = "https://files.pythonhosted.org/packages/cb/35/5b77eaebc60d735e832c5b1a20b155667645d123f09d471db0a78280fb49/orjson-3.11.5-cp311-cp311-win_arm64.whl", hash = "sha256:1cbf2735722623fcdee8e712cbaaab9e372bbcb0c7924ad711b261c2eccf4a5c", size = 126830, upload-time = "2025-12-06T15:54:20.836Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:334e5b4bff9ad101237c2d799d9fd45737752929753bf4faf4b207335a416b7d", size = 245347, upload-time = "2025-12-06T15:54:22.061Z" }, - { url = "https://files.pythonhosted.org/packages/64/67/574a7732bd9d9d79ac620c8790b4cfe0717a3d5a6eb2b539e6e8995e24a0/orjson-3.11.5-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:ff770589960a86eae279f5d8aa536196ebda8273a2a07db2a54e82b93bc86626", size = 129435, upload-time = "2025-12-06T15:54:23.615Z" }, - { url = "https://files.pythonhosted.org/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed24250e55efbcb0b35bed7caaec8cedf858ab2f9f2201f17b8938c618c8ca6f", size = 132074, upload-time = "2025-12-06T15:54:24.694Z" }, - { url = "https://files.pythonhosted.org/packages/6e/57/b9f5b5b6fbff9c26f77e785baf56ae8460ef74acdb3eae4931c25b8f5ba9/orjson-3.11.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a66d7769e98a08a12a139049aac2f0ca3adae989817f8c43337455fbc7669b85", size = 130520, upload-time = "2025-12-06T15:54:26.185Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6d/d34970bf9eb33f9ec7c979a262cad86076814859e54eb9a059a52f6dc13d/orjson-3.11.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86cfc555bfd5794d24c6a1903e558b50644e5e68e6471d66502ce5cb5fdef3f9", size = 136209, upload-time = "2025-12-06T15:54:27.264Z" }, - { url = "https://files.pythonhosted.org/packages/e7/39/bc373b63cc0e117a105ea12e57280f83ae52fdee426890d57412432d63b3/orjson-3.11.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a230065027bc2a025e944f9d4714976a81e7ecfa940923283bca7bbc1f10f626", size = 139837, upload-time = "2025-12-06T15:54:28.75Z" }, - { url = "https://files.pythonhosted.org/packages/cb/aa/7c4818c8d7d324da220f4f1af55c343956003aa4d1ce1857bdc1d396ba69/orjson-3.11.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b29d36b60e606df01959c4b982729c8845c69d1963f88686608be9ced96dbfaa", size = 137307, upload-time = "2025-12-06T15:54:29.856Z" }, - { url = "https://files.pythonhosted.org/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c74099c6b230d4261fdc3169d50efc09abf38ace1a42ea2f9994b1d79153d477", size = 139020, upload-time = "2025-12-06T15:54:31.024Z" }, - { url = "https://files.pythonhosted.org/packages/65/e8/83a6c95db3039e504eda60fc388f9faedbb4f6472f5aba7084e06552d9aa/orjson-3.11.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e697d06ad57dd0c7a737771d470eedc18e68dfdefcdd3b7de7f33dfda5b6212e", size = 141099, upload-time = "2025-12-06T15:54:32.196Z" }, - { url = "https://files.pythonhosted.org/packages/b9/b4/24fdc024abfce31c2f6812973b0a693688037ece5dc64b7a60c1ce69e2f2/orjson-3.11.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e08ca8a6c851e95aaecc32bc44a5aa75d0ad26af8cdac7c77e4ed93acf3d5b69", size = 413540, upload-time = "2025-12-06T15:54:33.361Z" }, - { url = "https://files.pythonhosted.org/packages/d9/37/01c0ec95d55ed0c11e4cae3e10427e479bba40c77312b63e1f9665e0737d/orjson-3.11.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e8b5f96c05fce7d0218df3fdfeb962d6b8cfff7e3e20264306b46dd8b217c0f3", size = 151530, upload-time = "2025-12-06T15:54:34.6Z" }, - { url = "https://files.pythonhosted.org/packages/f9/d4/f9ebc57182705bb4bbe63f5bbe14af43722a2533135e1d2fb7affa0c355d/orjson-3.11.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ddbfdb5099b3e6ba6d6ea818f61997bb66de14b411357d24c4612cf1ebad08ca", size = 141863, upload-time = "2025-12-06T15:54:35.801Z" }, - { url = "https://files.pythonhosted.org/packages/0d/04/02102b8d19fdcb009d72d622bb5781e8f3fae1646bf3e18c53d1bc8115b5/orjson-3.11.5-cp312-cp312-win32.whl", hash = "sha256:9172578c4eb09dbfcf1657d43198de59b6cef4054de385365060ed50c458ac98", size = 135255, upload-time = "2025-12-06T15:54:37.209Z" }, - { url = "https://files.pythonhosted.org/packages/d4/fb/f05646c43d5450492cb387de5549f6de90a71001682c17882d9f66476af5/orjson-3.11.5-cp312-cp312-win_amd64.whl", hash = "sha256:2b91126e7b470ff2e75746f6f6ee32b9ab67b7a93c8ba1d15d3a0caaf16ec875", size = 133252, upload-time = "2025-12-06T15:54:38.401Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/7b8c0b26ba18c793533ac1cd145e131e46fcf43952aa94c109b5b913c1f0/orjson-3.11.5-cp312-cp312-win_arm64.whl", hash = "sha256:acbc5fac7e06777555b0722b8ad5f574739e99ffe99467ed63da98f97f9ca0fe", size = 126777, upload-time = "2025-12-06T15:54:39.515Z" }, - { url = "https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629", size = 245271, upload-time = "2025-12-06T15:54:40.878Z" }, - { url = "https://files.pythonhosted.org/packages/55/f9/0f79be617388227866d50edd2fd320cb8fb94dc1501184bb1620981a0aba/orjson-3.11.5-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:61de247948108484779f57a9f406e4c84d636fa5a59e411e6352484985e8a7c3", size = 129422, upload-time = "2025-12-06T15:54:42.403Z" }, - { url = "https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39", size = 132060, upload-time = "2025-12-06T15:54:43.531Z" }, - { url = "https://files.pythonhosted.org/packages/25/49/825aa6b929f1a6ed244c78acd7b22c1481fd7e5fda047dc8bf4c1a807eb6/orjson-3.11.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ddc21521598dbe369d83d4d40338e23d4101dad21dae0e79fa20465dbace019f", size = 130391, upload-time = "2025-12-06T15:54:45.059Z" }, - { url = "https://files.pythonhosted.org/packages/42/ec/de55391858b49e16e1aa8f0bbbb7e5997b7345d8e984a2dec3746d13065b/orjson-3.11.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cce16ae2f5fb2c53c3eafdd1706cb7b6530a67cc1c17abe8ec747f5cd7c0c51", size = 135964, upload-time = "2025-12-06T15:54:46.576Z" }, - { url = "https://files.pythonhosted.org/packages/1c/40/820bc63121d2d28818556a2d0a09384a9f0262407cf9fa305e091a8048df/orjson-3.11.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e46c762d9f0e1cfb4ccc8515de7f349abbc95b59cb5a2bd68df5973fdef913f8", size = 139817, upload-time = "2025-12-06T15:54:48.084Z" }, - { url = "https://files.pythonhosted.org/packages/09/c7/3a445ca9a84a0d59d26365fd8898ff52bdfcdcb825bcc6519830371d2364/orjson-3.11.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7345c759276b798ccd6d77a87136029e71e66a8bbf2d2755cbdde1d82e78706", size = 137336, upload-time = "2025-12-06T15:54:49.426Z" }, - { url = "https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f", size = 138993, upload-time = "2025-12-06T15:54:50.939Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a2/65267e959de6abe23444659b6e19c888f242bf7725ff927e2292776f6b89/orjson-3.11.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:54aae9b654554c3b4edd61896b978568c6daa16af96fa4681c9b5babd469f863", size = 141070, upload-time = "2025-12-06T15:54:52.414Z" }, - { url = "https://files.pythonhosted.org/packages/63/c9/da44a321b288727a322c6ab17e1754195708786a04f4f9d2220a5076a649/orjson-3.11.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4bdd8d164a871c4ec773f9de0f6fe8769c2d6727879c37a9666ba4183b7f8228", size = 413505, upload-time = "2025-12-06T15:54:53.67Z" }, - { url = "https://files.pythonhosted.org/packages/7f/17/68dc14fa7000eefb3d4d6d7326a190c99bb65e319f02747ef3ebf2452f12/orjson-3.11.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a261fef929bcf98a60713bf5e95ad067cea16ae345d9a35034e73c3990e927d2", size = 151342, upload-time = "2025-12-06T15:54:55.113Z" }, - { url = "https://files.pythonhosted.org/packages/c4/c5/ccee774b67225bed630a57478529fc026eda33d94fe4c0eac8fe58d4aa52/orjson-3.11.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c028a394c766693c5c9909dec76b24f37e6a1b91999e8d0c0d5feecbe93c3e05", size = 141823, upload-time = "2025-12-06T15:54:56.331Z" }, - { url = "https://files.pythonhosted.org/packages/67/80/5d00e4155d0cd7390ae2087130637671da713959bb558db9bac5e6f6b042/orjson-3.11.5-cp313-cp313-win32.whl", hash = "sha256:2cc79aaad1dfabe1bd2d50ee09814a1253164b3da4c00a78c458d82d04b3bdef", size = 135236, upload-time = "2025-12-06T15:54:57.507Z" }, - { url = "https://files.pythonhosted.org/packages/95/fe/792cc06a84808dbdc20ac6eab6811c53091b42f8e51ecebf14b540e9cfe4/orjson-3.11.5-cp313-cp313-win_amd64.whl", hash = "sha256:ff7877d376add4e16b274e35a3f58b7f37b362abf4aa31863dadacdd20e3a583", size = 133167, upload-time = "2025-12-06T15:54:58.71Z" }, - { url = "https://files.pythonhosted.org/packages/46/2c/d158bd8b50e3b1cfdcf406a7e463f6ffe3f0d167b99634717acdaf5e299f/orjson-3.11.5-cp313-cp313-win_arm64.whl", hash = "sha256:59ac72ea775c88b163ba8d21b0177628bd015c5dd060647bbab6e22da3aad287", size = 126712, upload-time = "2025-12-06T15:54:59.892Z" }, - { url = "https://files.pythonhosted.org/packages/c2/60/77d7b839e317ead7bb225d55bb50f7ea75f47afc489c81199befc5435b50/orjson-3.11.5-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e446a8ea0a4c366ceafc7d97067bfd55292969143b57e3c846d87fc701e797a0", size = 245252, upload-time = "2025-12-06T15:55:01.127Z" }, - { url = "https://files.pythonhosted.org/packages/f1/aa/d4639163b400f8044cef0fb9aa51b0337be0da3a27187a20d1166e742370/orjson-3.11.5-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:53deb5addae9c22bbe3739298f5f2196afa881ea75944e7720681c7080909a81", size = 129419, upload-time = "2025-12-06T15:55:02.723Z" }, - { url = "https://files.pythonhosted.org/packages/30/94/9eabf94f2e11c671111139edf5ec410d2f21e6feee717804f7e8872d883f/orjson-3.11.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82cd00d49d6063d2b8791da5d4f9d20539c5951f965e45ccf4e96d33505ce68f", size = 132050, upload-time = "2025-12-06T15:55:03.918Z" }, - { url = "https://files.pythonhosted.org/packages/3d/c8/ca10f5c5322f341ea9a9f1097e140be17a88f88d1cfdd29df522970d9744/orjson-3.11.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fd15f9fc8c203aeceff4fda211157fad114dde66e92e24097b3647a08f4ee9e", size = 130370, upload-time = "2025-12-06T15:55:05.173Z" }, - { url = "https://files.pythonhosted.org/packages/25/d4/e96824476d361ee2edd5c6290ceb8d7edf88d81148a6ce172fc00278ca7f/orjson-3.11.5-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9df95000fbe6777bf9820ae82ab7578e8662051bb5f83d71a28992f539d2cda7", size = 136012, upload-time = "2025-12-06T15:55:06.402Z" }, - { url = "https://files.pythonhosted.org/packages/85/8e/9bc3423308c425c588903f2d103cfcfe2539e07a25d6522900645a6f257f/orjson-3.11.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92a8d676748fca47ade5bc3da7430ed7767afe51b2f8100e3cd65e151c0eaceb", size = 139809, upload-time = "2025-12-06T15:55:07.656Z" }, - { url = "https://files.pythonhosted.org/packages/e9/3c/b404e94e0b02a232b957c54643ce68d0268dacb67ac33ffdee24008c8b27/orjson-3.11.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa0f513be38b40234c77975e68805506cad5d57b3dfd8fe3baa7f4f4051e15b4", size = 137332, upload-time = "2025-12-06T15:55:08.961Z" }, - { url = "https://files.pythonhosted.org/packages/51/30/cc2d69d5ce0ad9b84811cdf4a0cd5362ac27205a921da524ff42f26d65e0/orjson-3.11.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1863e75b92891f553b7922ce4ee10ed06db061e104f2b7815de80cdcb135ad", size = 138983, upload-time = "2025-12-06T15:55:10.595Z" }, - { url = "https://files.pythonhosted.org/packages/0e/87/de3223944a3e297d4707d2fe3b1ffb71437550e165eaf0ca8bbe43ccbcb1/orjson-3.11.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4be86b58e9ea262617b8ca6251a2f0d63cc132a6da4b5fcc8e0a4128782c829", size = 141069, upload-time = "2025-12-06T15:55:11.832Z" }, - { url = "https://files.pythonhosted.org/packages/65/30/81d5087ae74be33bcae3ff2d80f5ccaa4a8fedc6d39bf65a427a95b8977f/orjson-3.11.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:b923c1c13fa02084eb38c9c065afd860a5cff58026813319a06949c3af5732ac", size = 413491, upload-time = "2025-12-06T15:55:13.314Z" }, - { url = "https://files.pythonhosted.org/packages/d0/6f/f6058c21e2fc1efaf918986dbc2da5cd38044f1a2d4b7b91ad17c4acf786/orjson-3.11.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1b6bd351202b2cd987f35a13b5e16471cf4d952b42a73c391cc537974c43ef6d", size = 151375, upload-time = "2025-12-06T15:55:14.715Z" }, - { url = "https://files.pythonhosted.org/packages/54/92/c6921f17d45e110892899a7a563a925b2273d929959ce2ad89e2525b885b/orjson-3.11.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bb150d529637d541e6af06bbe3d02f5498d628b7f98267ff87647584293ab439", size = 141850, upload-time = "2025-12-06T15:55:15.94Z" }, - { url = "https://files.pythonhosted.org/packages/88/86/cdecb0140a05e1a477b81f24739da93b25070ee01ce7f7242f44a6437594/orjson-3.11.5-cp314-cp314-win32.whl", hash = "sha256:9cc1e55c884921434a84a0c3dd2699eb9f92e7b441d7f53f3941079ec6ce7499", size = 135278, upload-time = "2025-12-06T15:55:17.202Z" }, - { url = "https://files.pythonhosted.org/packages/e4/97/b638d69b1e947d24f6109216997e38922d54dcdcdb1b11c18d7efd2d3c59/orjson-3.11.5-cp314-cp314-win_amd64.whl", hash = "sha256:a4f3cb2d874e03bc7767c8f88adaa1a9a05cecea3712649c3b58589ec7317310", size = 133170, upload-time = "2025-12-06T15:55:18.468Z" }, - { url = "https://files.pythonhosted.org/packages/8f/dd/f4fff4a6fe601b4f8f3ba3aa6da8ac33d17d124491a3b804c662a70e1636/orjson-3.11.5-cp314-cp314-win_arm64.whl", hash = "sha256:38b22f476c351f9a1c43e5b07d8b5a02eb24a6ab8e75f700f7d479d4568346a5", size = 126713, upload-time = "2025-12-06T15:55:19.738Z" }, - { url = "https://files.pythonhosted.org/packages/50/c7/7b682849dd4c9fb701a981669b964ea700516ecbd8e88f62aae07c6852bd/orjson-3.11.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1b280e2d2d284a6713b0cfec7b08918ebe57df23e3f76b27586197afca3cb1e9", size = 245298, upload-time = "2025-12-06T15:55:20.984Z" }, - { url = "https://files.pythonhosted.org/packages/1b/3f/194355a9335707a15fdc79ddc670148987b43d04712dd26898a694539ce6/orjson-3.11.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d8a112b274fae8c5f0f01954cb0480137072c271f3f4958127b010dfefaec", size = 132150, upload-time = "2025-12-06T15:55:22.364Z" }, - { url = "https://files.pythonhosted.org/packages/e9/08/d74b3a986d37e6c2e04b8821c62927620c9a1924bb49ea51519a87751b86/orjson-3.11.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0a2ae6f09ac7bd47d2d5a5305c1d9ed08ac057cda55bb0a49fa506f0d2da00", size = 130490, upload-time = "2025-12-06T15:55:23.619Z" }, - { url = "https://files.pythonhosted.org/packages/b2/16/ebd04c38c1db01e493a68eee442efdffc505a43112eccd481e0146c6acc2/orjson-3.11.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0d87bd1896faac0d10b4f849016db81a63e4ec5df38757ffae84d45ab38aa71", size = 135726, upload-time = "2025-12-06T15:55:24.912Z" }, - { url = "https://files.pythonhosted.org/packages/06/64/2ce4b2c09a099403081c37639c224bdcdfe401138bd66fed5c96d4f8dbd3/orjson-3.11.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:801a821e8e6099b8c459ac7540b3c32dba6013437c57fdcaec205b169754f38c", size = 139640, upload-time = "2025-12-06T15:55:26.535Z" }, - { url = "https://files.pythonhosted.org/packages/cd/e2/425796df8ee1d7cea3a7edf868920121dd09162859dbb76fffc9a5c37fd3/orjson-3.11.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69a0f6ac618c98c74b7fbc8c0172ba86f9e01dbf9f62aa0b1776c2231a7bffe5", size = 137289, upload-time = "2025-12-06T15:55:27.78Z" }, - { url = "https://files.pythonhosted.org/packages/32/a2/88e482eb8e899a037dcc9eff85ef117a568e6ca1ffa1a2b2be3fcb51b7bb/orjson-3.11.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea7339bdd22e6f1060c55ac31b6a755d86a5b2ad3657f2669ec243f8e3b2bdb", size = 138761, upload-time = "2025-12-06T15:55:29.388Z" }, - { url = "https://files.pythonhosted.org/packages/f1/fd/131dd6d32eeb74c513bfa487f434a2150811d0fbd9cb06689284f2f21b34/orjson-3.11.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4dad582bc93cef8f26513e12771e76385a7e6187fd713157e971c784112aad56", size = 141357, upload-time = "2025-12-06T15:55:31.064Z" }, - { url = "https://files.pythonhosted.org/packages/7a/90/e4a0abbcca7b53e9098ac854f27f5ed9949c796f3c760bc04af997da0eb2/orjson-3.11.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:0522003e9f7fba91982e83a97fec0708f5a714c96c4209db7104e6b9d132f111", size = 413638, upload-time = "2025-12-06T15:55:32.344Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c2/df91e385514924120001ade9cd52d6295251023d3bfa2c0a01f38cfc485a/orjson-3.11.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7403851e430a478440ecc1258bcbacbfbd8175f9ac1e39031a7121dd0de05ff8", size = 150972, upload-time = "2025-12-06T15:55:33.725Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ff/c76cc5a30a4451191ff1b868a331ad1354433335277fc40931f5fc3cab9d/orjson-3.11.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5f691263425d3177977c8d1dd896cde7b98d93cbf390b2544a090675e83a6a0a", size = 141729, upload-time = "2025-12-06T15:55:35.317Z" }, - { url = "https://files.pythonhosted.org/packages/27/c3/7830bf74389ea1eaab2b017d8b15d1cab2bb0737d9412dfa7fb8644f7d78/orjson-3.11.5-cp39-cp39-win32.whl", hash = "sha256:61026196a1c4b968e1b1e540563e277843082e9e97d78afa03eb89315af531f1", size = 135100, upload-time = "2025-12-06T15:55:36.57Z" }, - { url = "https://files.pythonhosted.org/packages/69/e6/babf31154e047e465bc194eb72d1326d7c52ad4d7f50bf92b02b3cacda5c/orjson-3.11.5-cp39-cp39-win_amd64.whl", hash = "sha256:09b94b947ac08586af635ef922d69dc9bc63321527a3a04647f4986a73f4bd30", size = 133189, upload-time = "2025-12-06T15:55:38.143Z" }, -] - [[package]] name = "orjson" version = "3.11.7" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/de/1a/a373746fa6d0e116dd9e54371a7b54622c44d12296d5d0f3ad5e3ff33490/orjson-3.11.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174", size = 229140, upload-time = "2026-02-02T15:37:06.082Z" }, @@ -4369,130 +3509,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" }, ] -[[package]] -name = "pillow" -version = "11.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/5d/45a3553a253ac8763f3561371432a90bdbe6000fbdcf1397ffe502aa206c/pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860", size = 5316554, upload-time = "2025-07-01T09:13:39.342Z" }, - { url = "https://files.pythonhosted.org/packages/7c/c8/67c12ab069ef586a25a4a79ced553586748fad100c77c0ce59bb4983ac98/pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad", size = 4686548, upload-time = "2025-07-01T09:13:41.835Z" }, - { url = "https://files.pythonhosted.org/packages/2f/bd/6741ebd56263390b382ae4c5de02979af7f8bd9807346d068700dd6d5cf9/pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0", size = 5859742, upload-time = "2025-07-03T13:09:47.439Z" }, - { url = "https://files.pythonhosted.org/packages/ca/0b/c412a9e27e1e6a829e6ab6c2dca52dd563efbedf4c9c6aa453d9a9b77359/pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b", size = 7633087, upload-time = "2025-07-03T13:09:51.796Z" }, - { url = "https://files.pythonhosted.org/packages/59/9d/9b7076aaf30f5dd17e5e5589b2d2f5a5d7e30ff67a171eb686e4eecc2adf/pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50", size = 5963350, upload-time = "2025-07-01T09:13:43.865Z" }, - { url = "https://files.pythonhosted.org/packages/f0/16/1a6bf01fb622fb9cf5c91683823f073f053005c849b1f52ed613afcf8dae/pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae", size = 6631840, upload-time = "2025-07-01T09:13:46.161Z" }, - { url = "https://files.pythonhosted.org/packages/7b/e6/6ff7077077eb47fde78739e7d570bdcd7c10495666b6afcd23ab56b19a43/pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9", size = 6074005, upload-time = "2025-07-01T09:13:47.829Z" }, - { url = "https://files.pythonhosted.org/packages/c3/3a/b13f36832ea6d279a697231658199e0a03cd87ef12048016bdcc84131601/pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e", size = 6708372, upload-time = "2025-07-01T09:13:52.145Z" }, - { url = "https://files.pythonhosted.org/packages/6c/e4/61b2e1a7528740efbc70b3d581f33937e38e98ef3d50b05007267a55bcb2/pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6", size = 6277090, upload-time = "2025-07-01T09:13:53.915Z" }, - { url = "https://files.pythonhosted.org/packages/a9/d3/60c781c83a785d6afbd6a326ed4d759d141de43aa7365725cbcd65ce5e54/pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f", size = 6985988, upload-time = "2025-07-01T09:13:55.699Z" }, - { url = "https://files.pythonhosted.org/packages/9f/28/4f4a0203165eefb3763939c6789ba31013a2e90adffb456610f30f613850/pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f", size = 2422899, upload-time = "2025-07-01T09:13:57.497Z" }, - { url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", size = 5316531, upload-time = "2025-07-01T09:13:59.203Z" }, - { url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", size = 4686560, upload-time = "2025-07-01T09:14:01.101Z" }, - { url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", size = 5870978, upload-time = "2025-07-03T13:09:55.638Z" }, - { url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", size = 7641168, upload-time = "2025-07-03T13:10:00.37Z" }, - { url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", size = 5973053, upload-time = "2025-07-01T09:14:04.491Z" }, - { url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", size = 6640273, upload-time = "2025-07-01T09:14:06.235Z" }, - { url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", size = 6082043, upload-time = "2025-07-01T09:14:07.978Z" }, - { url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", size = 6715516, upload-time = "2025-07-01T09:14:10.233Z" }, - { url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", size = 6274768, upload-time = "2025-07-01T09:14:11.921Z" }, - { url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", size = 6986055, upload-time = "2025-07-01T09:14:13.623Z" }, - { url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", size = 2423079, upload-time = "2025-07-01T09:14:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", size = 5278800, upload-time = "2025-07-01T09:14:17.648Z" }, - { url = "https://files.pythonhosted.org/packages/2c/32/7e2ac19b5713657384cec55f89065fb306b06af008cfd87e572035b27119/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", size = 4686296, upload-time = "2025-07-01T09:14:19.828Z" }, - { url = "https://files.pythonhosted.org/packages/8e/1e/b9e12bbe6e4c2220effebc09ea0923a07a6da1e1f1bfbc8d7d29a01ce32b/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", size = 5871726, upload-time = "2025-07-03T13:10:04.448Z" }, - { url = "https://files.pythonhosted.org/packages/8d/33/e9200d2bd7ba00dc3ddb78df1198a6e80d7669cce6c2bdbeb2530a74ec58/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", size = 7644652, upload-time = "2025-07-03T13:10:10.391Z" }, - { url = "https://files.pythonhosted.org/packages/41/f1/6f2427a26fc683e00d985bc391bdd76d8dd4e92fac33d841127eb8fb2313/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", size = 5977787, upload-time = "2025-07-01T09:14:21.63Z" }, - { url = "https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", size = 6645236, upload-time = "2025-07-01T09:14:23.321Z" }, - { url = "https://files.pythonhosted.org/packages/40/e7/848f69fb79843b3d91241bad658e9c14f39a32f71a301bcd1d139416d1be/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", size = 6086950, upload-time = "2025-07-01T09:14:25.237Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1a/7cff92e695a2a29ac1958c2a0fe4c0b2393b60aac13b04a4fe2735cad52d/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", size = 6723358, upload-time = "2025-07-01T09:14:27.053Z" }, - { url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", size = 6275079, upload-time = "2025-07-01T09:14:30.104Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", size = 6986324, upload-time = "2025-07-01T09:14:31.899Z" }, - { url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", size = 2423067, upload-time = "2025-07-01T09:14:33.709Z" }, - { url = "https://files.pythonhosted.org/packages/1e/93/0952f2ed8db3a5a4c7a11f91965d6184ebc8cd7cbb7941a260d5f018cd2d/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", size = 2128328, upload-time = "2025-07-01T09:14:35.276Z" }, - { url = "https://files.pythonhosted.org/packages/4b/e8/100c3d114b1a0bf4042f27e0f87d2f25e857e838034e98ca98fe7b8c0a9c/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", size = 2170652, upload-time = "2025-07-01T09:14:37.203Z" }, - { url = "https://files.pythonhosted.org/packages/aa/86/3f758a28a6e381758545f7cdb4942e1cb79abd271bea932998fc0db93cb6/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", size = 2227443, upload-time = "2025-07-01T09:14:39.344Z" }, - { url = "https://files.pythonhosted.org/packages/01/f4/91d5b3ffa718df2f53b0dc109877993e511f4fd055d7e9508682e8aba092/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", size = 5278474, upload-time = "2025-07-01T09:14:41.843Z" }, - { url = "https://files.pythonhosted.org/packages/f9/0e/37d7d3eca6c879fbd9dba21268427dffda1ab00d4eb05b32923d4fbe3b12/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", size = 4686038, upload-time = "2025-07-01T09:14:44.008Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b0/3426e5c7f6565e752d81221af9d3676fdbb4f352317ceafd42899aaf5d8a/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", size = 5864407, upload-time = "2025-07-03T13:10:15.628Z" }, - { url = "https://files.pythonhosted.org/packages/fc/c1/c6c423134229f2a221ee53f838d4be9d82bab86f7e2f8e75e47b6bf6cd77/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", size = 7639094, upload-time = "2025-07-03T13:10:21.857Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c9/09e6746630fe6372c67c648ff9deae52a2bc20897d51fa293571977ceb5d/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", size = 5973503, upload-time = "2025-07-01T09:14:45.698Z" }, - { url = "https://files.pythonhosted.org/packages/d5/1c/a2a29649c0b1983d3ef57ee87a66487fdeb45132df66ab30dd37f7dbe162/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", size = 6642574, upload-time = "2025-07-01T09:14:47.415Z" }, - { url = "https://files.pythonhosted.org/packages/36/de/d5cc31cc4b055b6c6fd990e3e7f0f8aaf36229a2698501bcb0cdf67c7146/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", size = 6084060, upload-time = "2025-07-01T09:14:49.636Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ea/502d938cbaeec836ac28a9b730193716f0114c41325db428e6b280513f09/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", size = 6721407, upload-time = "2025-07-01T09:14:51.962Z" }, - { url = "https://files.pythonhosted.org/packages/45/9c/9c5e2a73f125f6cbc59cc7087c8f2d649a7ae453f83bd0362ff7c9e2aee2/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", size = 6273841, upload-time = "2025-07-01T09:14:54.142Z" }, - { url = "https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", size = 6978450, upload-time = "2025-07-01T09:14:56.436Z" }, - { url = "https://files.pythonhosted.org/packages/17/d2/622f4547f69cd173955194b78e4d19ca4935a1b0f03a302d655c9f6aae65/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", size = 2423055, upload-time = "2025-07-01T09:14:58.072Z" }, - { url = "https://files.pythonhosted.org/packages/dd/80/a8a2ac21dda2e82480852978416cfacd439a4b490a501a288ecf4fe2532d/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", size = 5281110, upload-time = "2025-07-01T09:14:59.79Z" }, - { url = "https://files.pythonhosted.org/packages/44/d6/b79754ca790f315918732e18f82a8146d33bcd7f4494380457ea89eb883d/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", size = 4689547, upload-time = "2025-07-01T09:15:01.648Z" }, - { url = "https://files.pythonhosted.org/packages/49/20/716b8717d331150cb00f7fdd78169c01e8e0c219732a78b0e59b6bdb2fd6/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", size = 5901554, upload-time = "2025-07-03T13:10:27.018Z" }, - { url = "https://files.pythonhosted.org/packages/74/cf/a9f3a2514a65bb071075063a96f0a5cf949c2f2fce683c15ccc83b1c1cab/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", size = 7669132, upload-time = "2025-07-03T13:10:33.01Z" }, - { url = "https://files.pythonhosted.org/packages/98/3c/da78805cbdbee9cb43efe8261dd7cc0b4b93f2ac79b676c03159e9db2187/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", size = 6005001, upload-time = "2025-07-01T09:15:03.365Z" }, - { url = "https://files.pythonhosted.org/packages/6c/fa/ce044b91faecf30e635321351bba32bab5a7e034c60187fe9698191aef4f/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", size = 6668814, upload-time = "2025-07-01T09:15:05.655Z" }, - { url = "https://files.pythonhosted.org/packages/7b/51/90f9291406d09bf93686434f9183aba27b831c10c87746ff49f127ee80cb/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", size = 6113124, upload-time = "2025-07-01T09:15:07.358Z" }, - { url = "https://files.pythonhosted.org/packages/cd/5a/6fec59b1dfb619234f7636d4157d11fb4e196caeee220232a8d2ec48488d/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", size = 6747186, upload-time = "2025-07-01T09:15:09.317Z" }, - { url = "https://files.pythonhosted.org/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", size = 6277546, upload-time = "2025-07-01T09:15:11.311Z" }, - { url = "https://files.pythonhosted.org/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", size = 6985102, upload-time = "2025-07-01T09:15:13.164Z" }, - { url = "https://files.pythonhosted.org/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", size = 2424803, upload-time = "2025-07-01T09:15:15.695Z" }, - { url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12", size = 5278520, upload-time = "2025-07-01T09:15:17.429Z" }, - { url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a", size = 4686116, upload-time = "2025-07-01T09:15:19.423Z" }, - { url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632", size = 5864597, upload-time = "2025-07-03T13:10:38.404Z" }, - { url = "https://files.pythonhosted.org/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673", size = 7638246, upload-time = "2025-07-03T13:10:44.987Z" }, - { url = "https://files.pythonhosted.org/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027", size = 5973336, upload-time = "2025-07-01T09:15:21.237Z" }, - { url = "https://files.pythonhosted.org/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77", size = 6642699, upload-time = "2025-07-01T09:15:23.186Z" }, - { url = "https://files.pythonhosted.org/packages/6f/d2/a9a4f280c6aefedce1e8f615baaa5474e0701d86dd6f1dede66726462bbd/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874", size = 6083789, upload-time = "2025-07-01T09:15:25.1Z" }, - { url = "https://files.pythonhosted.org/packages/fe/54/86b0cd9dbb683a9d5e960b66c7379e821a19be4ac5810e2e5a715c09a0c0/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a", size = 6720386, upload-time = "2025-07-01T09:15:27.378Z" }, - { url = "https://files.pythonhosted.org/packages/e7/95/88efcaf384c3588e24259c4203b909cbe3e3c2d887af9e938c2022c9dd48/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214", size = 6370911, upload-time = "2025-07-01T09:15:29.294Z" }, - { url = "https://files.pythonhosted.org/packages/2e/cc/934e5820850ec5eb107e7b1a72dd278140731c669f396110ebc326f2a503/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635", size = 7117383, upload-time = "2025-07-01T09:15:31.128Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e9/9c0a616a71da2a5d163aa37405e8aced9a906d574b4a214bede134e731bc/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6", size = 2511385, upload-time = "2025-07-01T09:15:33.328Z" }, - { url = "https://files.pythonhosted.org/packages/1a/33/c88376898aff369658b225262cd4f2659b13e8178e7534df9e6e1fa289f6/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae", size = 5281129, upload-time = "2025-07-01T09:15:35.194Z" }, - { url = "https://files.pythonhosted.org/packages/1f/70/d376247fb36f1844b42910911c83a02d5544ebd2a8bad9efcc0f707ea774/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653", size = 4689580, upload-time = "2025-07-01T09:15:37.114Z" }, - { url = "https://files.pythonhosted.org/packages/eb/1c/537e930496149fbac69efd2fc4329035bbe2e5475b4165439e3be9cb183b/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6", size = 5902860, upload-time = "2025-07-03T13:10:50.248Z" }, - { url = "https://files.pythonhosted.org/packages/bd/57/80f53264954dcefeebcf9dae6e3eb1daea1b488f0be8b8fef12f79a3eb10/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36", size = 7670694, upload-time = "2025-07-03T13:10:56.432Z" }, - { url = "https://files.pythonhosted.org/packages/70/ff/4727d3b71a8578b4587d9c276e90efad2d6fe0335fd76742a6da08132e8c/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b", size = 6005888, upload-time = "2025-07-01T09:15:39.436Z" }, - { url = "https://files.pythonhosted.org/packages/05/ae/716592277934f85d3be51d7256f3636672d7b1abfafdc42cf3f8cbd4b4c8/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477", size = 6670330, upload-time = "2025-07-01T09:15:41.269Z" }, - { url = "https://files.pythonhosted.org/packages/e7/bb/7fe6cddcc8827b01b1a9766f5fdeb7418680744f9082035bdbabecf1d57f/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50", size = 6114089, upload-time = "2025-07-01T09:15:43.13Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f5/06bfaa444c8e80f1a8e4bff98da9c83b37b5be3b1deaa43d27a0db37ef84/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b", size = 6748206, upload-time = "2025-07-01T09:15:44.937Z" }, - { url = "https://files.pythonhosted.org/packages/f0/77/bc6f92a3e8e6e46c0ca78abfffec0037845800ea38c73483760362804c41/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12", size = 6377370, upload-time = "2025-07-01T09:15:46.673Z" }, - { url = "https://files.pythonhosted.org/packages/4a/82/3a721f7d69dca802befb8af08b7c79ebcab461007ce1c18bd91a5d5896f9/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db", size = 7121500, upload-time = "2025-07-01T09:15:48.512Z" }, - { url = "https://files.pythonhosted.org/packages/89/c7/5572fa4a3f45740eaab6ae86fcdf7195b55beac1371ac8c619d880cfe948/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa", size = 2512835, upload-time = "2025-07-01T09:15:50.399Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8e/9c089f01677d1264ab8648352dcb7773f37da6ad002542760c80107da816/pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f", size = 5316478, upload-time = "2025-07-01T09:15:52.209Z" }, - { url = "https://files.pythonhosted.org/packages/b5/a9/5749930caf674695867eb56a581e78eb5f524b7583ff10b01b6e5048acb3/pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081", size = 4686522, upload-time = "2025-07-01T09:15:54.162Z" }, - { url = "https://files.pythonhosted.org/packages/43/46/0b85b763eb292b691030795f9f6bb6fcaf8948c39413c81696a01c3577f7/pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4", size = 5853376, upload-time = "2025-07-03T13:11:01.066Z" }, - { url = "https://files.pythonhosted.org/packages/5e/c6/1a230ec0067243cbd60bc2dad5dc3ab46a8a41e21c15f5c9b52b26873069/pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc", size = 7626020, upload-time = "2025-07-03T13:11:06.479Z" }, - { url = "https://files.pythonhosted.org/packages/63/dd/f296c27ffba447bfad76c6a0c44c1ea97a90cb9472b9304c94a732e8dbfb/pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06", size = 5956732, upload-time = "2025-07-01T09:15:56.111Z" }, - { url = "https://files.pythonhosted.org/packages/a5/a0/98a3630f0b57f77bae67716562513d3032ae70414fcaf02750279c389a9e/pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a", size = 6624404, upload-time = "2025-07-01T09:15:58.245Z" }, - { url = "https://files.pythonhosted.org/packages/de/e6/83dfba5646a290edd9a21964da07674409e410579c341fc5b8f7abd81620/pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978", size = 6067760, upload-time = "2025-07-01T09:16:00.003Z" }, - { url = "https://files.pythonhosted.org/packages/bc/41/15ab268fe6ee9a2bc7391e2bbb20a98d3974304ab1a406a992dcb297a370/pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d", size = 6700534, upload-time = "2025-07-01T09:16:02.29Z" }, - { url = "https://files.pythonhosted.org/packages/64/79/6d4f638b288300bed727ff29f2a3cb63db054b33518a95f27724915e3fbc/pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71", size = 6277091, upload-time = "2025-07-01T09:16:04.4Z" }, - { url = "https://files.pythonhosted.org/packages/46/05/4106422f45a05716fd34ed21763f8ec182e8ea00af6e9cb05b93a247361a/pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada", size = 6986091, upload-time = "2025-07-01T09:16:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/63/c6/287fd55c2c12761d0591549d48885187579b7c257bef0c6660755b0b59ae/pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb", size = 2422632, upload-time = "2025-07-01T09:16:08.142Z" }, - { url = "https://files.pythonhosted.org/packages/6f/8b/209bd6b62ce8367f47e68a218bffac88888fdf2c9fcf1ecadc6c3ec1ebc7/pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967", size = 5270556, upload-time = "2025-07-01T09:16:09.961Z" }, - { url = "https://files.pythonhosted.org/packages/2e/e6/231a0b76070c2cfd9e260a7a5b504fb72da0a95279410fa7afd99d9751d6/pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe", size = 4654625, upload-time = "2025-07-01T09:16:11.913Z" }, - { url = "https://files.pythonhosted.org/packages/13/f4/10cf94fda33cb12765f2397fc285fa6d8eb9c29de7f3185165b702fc7386/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c", size = 4874207, upload-time = "2025-07-03T13:11:10.201Z" }, - { url = "https://files.pythonhosted.org/packages/72/c9/583821097dc691880c92892e8e2d41fe0a5a3d6021f4963371d2f6d57250/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25", size = 6583939, upload-time = "2025-07-03T13:11:15.68Z" }, - { url = "https://files.pythonhosted.org/packages/3b/8e/5c9d410f9217b12320efc7c413e72693f48468979a013ad17fd690397b9a/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27", size = 4957166, upload-time = "2025-07-01T09:16:13.74Z" }, - { url = "https://files.pythonhosted.org/packages/62/bb/78347dbe13219991877ffb3a91bf09da8317fbfcd4b5f9140aeae020ad71/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a", size = 5581482, upload-time = "2025-07-01T09:16:16.107Z" }, - { url = "https://files.pythonhosted.org/packages/d9/28/1000353d5e61498aaeaaf7f1e4b49ddb05f2c6575f9d4f9f914a3538b6e1/pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f", size = 6984596, upload-time = "2025-07-01T09:16:18.07Z" }, - { url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", size = 5270566, upload-time = "2025-07-01T09:16:19.801Z" }, - { url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", size = 4654618, upload-time = "2025-07-01T09:16:21.818Z" }, - { url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3", size = 4874248, upload-time = "2025-07-03T13:11:20.738Z" }, - { url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", size = 6583963, upload-time = "2025-07-03T13:11:26.283Z" }, - { url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", size = 4957170, upload-time = "2025-07-01T09:16:23.762Z" }, - { url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", size = 5581505, upload-time = "2025-07-01T09:16:25.593Z" }, - { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" }, -] - [[package]] name = "pillow" version = "12.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/fe/41/f73d92b6b883a579e79600d391f2e21cb0df767b2714ecbd2952315dfeef/pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd", size = 5304089, upload-time = "2026-01-02T09:10:24.953Z" }, @@ -4587,26 +3607,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/71/64e9b1c7f04ae0027f788a248e6297d7fcc29571371fe7d45495a78172c0/pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19", size = 7029809, upload-time = "2026-01-02T09:13:26.541Z" }, ] -[[package]] -name = "platformdirs" -version = "4.4.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, -] - [[package]] name = "platformdirs" version = "4.5.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, @@ -4617,8 +3621,7 @@ name = "playwright" version = "1.58.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "greenlet", version = "3.2.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "greenlet", version = "3.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "greenlet" }, { name = "pyee" }, ] wheels = [ @@ -4797,51 +3800,13 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, - { url = "https://files.pythonhosted.org/packages/9b/01/0ebaec9003f5d619a7475165961f8e3083cf8644d704b60395df3601632d/propcache-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", size = 80277, upload-time = "2025-10-08T19:48:36.647Z" }, - { url = "https://files.pythonhosted.org/packages/34/58/04af97ac586b4ef6b9026c3fd36ee7798b737a832f5d3440a4280dcebd3a/propcache-0.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", size = 45865, upload-time = "2025-10-08T19:48:37.859Z" }, - { url = "https://files.pythonhosted.org/packages/7c/19/b65d98ae21384518b291d9939e24a8aeac4fdb5101b732576f8f7540e834/propcache-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", size = 47636, upload-time = "2025-10-08T19:48:39.038Z" }, - { url = "https://files.pythonhosted.org/packages/b3/0f/317048c6d91c356c7154dca5af019e6effeb7ee15fa6a6db327cc19e12b4/propcache-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", size = 201126, upload-time = "2025-10-08T19:48:40.774Z" }, - { url = "https://files.pythonhosted.org/packages/71/69/0b2a7a5a6ee83292b4b997dbd80549d8ce7d40b6397c1646c0d9495f5a85/propcache-0.4.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", size = 209837, upload-time = "2025-10-08T19:48:42.167Z" }, - { url = "https://files.pythonhosted.org/packages/a5/92/c699ac495a6698df6e497fc2de27af4b6ace10d8e76528357ce153722e45/propcache-0.4.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", size = 215578, upload-time = "2025-10-08T19:48:43.56Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ee/14de81c5eb02c0ee4f500b4e39c4e1bd0677c06e72379e6ab18923c773fc/propcache-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", size = 197187, upload-time = "2025-10-08T19:48:45.309Z" }, - { url = "https://files.pythonhosted.org/packages/1d/94/48dce9aaa6d8dd5a0859bad75158ec522546d4ac23f8e2f05fac469477dd/propcache-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", size = 193478, upload-time = "2025-10-08T19:48:47.743Z" }, - { url = "https://files.pythonhosted.org/packages/60/b5/0516b563e801e1ace212afde869a0596a0d7115eec0b12d296d75633fb29/propcache-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", size = 190650, upload-time = "2025-10-08T19:48:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/24/89/e0f7d4a5978cd56f8cd67735f74052f257dc471ec901694e430f0d1572fe/propcache-0.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", size = 200251, upload-time = "2025-10-08T19:48:51.4Z" }, - { url = "https://files.pythonhosted.org/packages/06/7d/a1fac863d473876ed4406c914f2e14aa82d2f10dd207c9e16fc383cc5a24/propcache-0.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781", size = 200919, upload-time = "2025-10-08T19:48:53.227Z" }, - { url = "https://files.pythonhosted.org/packages/c3/4e/f86a256ff24944cf5743e4e6c6994e3526f6acfcfb55e21694c2424f758c/propcache-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", size = 193211, upload-time = "2025-10-08T19:48:55.027Z" }, - { url = "https://files.pythonhosted.org/packages/6e/3f/3fbad5f4356b068f1b047d300a6ff2c66614d7030f078cd50be3fec04228/propcache-0.4.1-cp39-cp39-win32.whl", hash = "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", size = 38314, upload-time = "2025-10-08T19:48:56.792Z" }, - { url = "https://files.pythonhosted.org/packages/a4/45/d78d136c3a3d215677abb886785aae744da2c3005bcb99e58640c56529b1/propcache-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", size = 41912, upload-time = "2025-10-08T19:48:57.995Z" }, - { url = "https://files.pythonhosted.org/packages/fc/2a/b0632941f25139f4e58450b307242951f7c2717a5704977c6d5323a800af/propcache-0.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", size = 38450, upload-time = "2025-10-08T19:48:59.349Z" }, { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, ] -[[package]] -name = "protobuf" -version = "5.29.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/7e/57/394a763c103e0edf87f0938dafcd918d53b4c011dfc5c8ae80f3b0452dbb/protobuf-5.29.6.tar.gz", hash = "sha256:da9ee6a5424b6b30fd5e45c5ea663aef540ca95f9ad99d1e887e819cdf9b8723", size = 425623, upload-time = "2026-02-04T22:54:40.584Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/88/9ee58ff7863c479d6f8346686d4636dd4c415b0cbeed7a6a7d0617639c2a/protobuf-5.29.6-cp310-abi3-win32.whl", hash = "sha256:62e8a3114992c7c647bce37dcc93647575fc52d50e48de30c6fcb28a6a291eb1", size = 423357, upload-time = "2026-02-04T22:54:25.805Z" }, - { url = "https://files.pythonhosted.org/packages/1c/66/2dc736a4d576847134fb6d80bd995c569b13cdc7b815d669050bf0ce2d2c/protobuf-5.29.6-cp310-abi3-win_amd64.whl", hash = "sha256:7e6ad413275be172f67fdee0f43484b6de5a904cc1c3ea9804cb6fe2ff366eda", size = 435175, upload-time = "2026-02-04T22:54:28.592Z" }, - { url = "https://files.pythonhosted.org/packages/06/db/49b05966fd208ae3f44dcd33837b6243b4915c57561d730a43f881f24dea/protobuf-5.29.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:b5a169e664b4057183a34bdc424540e86eea47560f3c123a0d64de4e137f9269", size = 418619, upload-time = "2026-02-04T22:54:30.266Z" }, - { url = "https://files.pythonhosted.org/packages/b7/d7/48cbf6b0c3c39761e47a99cb483405f0fde2be22cf00d71ef316ce52b458/protobuf-5.29.6-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:a8866b2cff111f0f863c1b3b9e7572dc7eaea23a7fae27f6fc613304046483e6", size = 320284, upload-time = "2026-02-04T22:54:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/e3/dd/cadd6ec43069247d91f6345fa7a0d2858bef6af366dbd7ba8f05d2c77d3b/protobuf-5.29.6-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3387f44798ac1106af0233c04fb8abf543772ff241169946f698b3a9a3d3ab9", size = 320478, upload-time = "2026-02-04T22:54:32.909Z" }, - { url = "https://files.pythonhosted.org/packages/30/a4/ff263f5687815e1a10a9243a3a6463af42ca251224bf4b8fc4c93b9f5b80/protobuf-5.29.6-cp39-cp39-win32.whl", hash = "sha256:cb4c86de9cd8a7f3a256b9744220d87b847371c6b2f10bde87768918ef33ba49", size = 423352, upload-time = "2026-02-04T22:54:37.375Z" }, - { url = "https://files.pythonhosted.org/packages/5c/64/e943206d3b5069050d570a2c53a90631240d99adcc9a91c6ff7b41876f4d/protobuf-5.29.6-cp39-cp39-win_amd64.whl", hash = "sha256:76e07e6567f8baf827137e8d5b8204b6c7b6488bbbff1bf0a72b383f77999c18", size = 435222, upload-time = "2026-02-04T22:54:38.418Z" }, - { url = "https://files.pythonhosted.org/packages/5a/cb/e3065b447186cb70aa65acc70c86baf482d82bf75625bf5a2c4f6919c6a3/protobuf-5.29.6-py3-none-any.whl", hash = "sha256:6b9edb641441b2da9fa8f428760fc136a49cf97a52076010cf22a2ff73438a86", size = 173126, upload-time = "2026-02-04T22:54:39.462Z" }, -] - [[package]] name = "protobuf" version = "6.33.5" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, @@ -4850,36 +3815,13 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, - { url = "https://files.pythonhosted.org/packages/08/60/84d5f6dcda9165e4d6a56ac8433c9f40a8906bf2966150b8a0cfde097d78/protobuf-6.33.5-cp39-cp39-win32.whl", hash = "sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c", size = 425892, upload-time = "2026-01-29T21:51:30.382Z" }, - { url = "https://files.pythonhosted.org/packages/68/19/33d7dc2dc84439587fa1e21e1c0026c01ad2af0a62f58fd54002a7546307/protobuf-6.33.5-cp39-cp39-win_amd64.whl", hash = "sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a", size = 437137, upload-time = "2026-01-29T21:51:31.456Z" }, { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, ] -[[package]] -name = "pwdlib" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/82/a0/9daed437a6226f632a25d98d65d60ba02bdafa920c90dcb6454c611ead6c/pwdlib-0.2.1.tar.gz", hash = "sha256:9a1d8a8fa09a2f7ebf208265e55d7d008103cbdc82b9e4902ffdd1ade91add5e", size = 11699, upload-time = "2024-08-19T06:48:59.58Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/01/f3/0dae5078a486f0fdf4d4a1121e103bc42694a9da9bea7b0f2c63f29cfbd3/pwdlib-0.2.1-py3-none-any.whl", hash = "sha256:1823dc6f22eae472b540e889ecf57fd424051d6a4023ec0bcf7f0de2d9d7ef8c", size = 8082, upload-time = "2024-08-19T06:49:00.997Z" }, -] - -[package.optional-dependencies] -argon2 = [ - { name = "argon2-cffi", version = "23.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] - [[package]] name = "pwdlib" version = "0.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/5f/41/a7c0d8a003c36ce3828ae3ed0391fe6a15aad65f082dbd6bec817ea95c0b/pwdlib-0.3.0.tar.gz", hash = "sha256:6ca30f9642a1467d4f5d0a4d18619de1c77f17dfccb42dd200b144127d3c83fc", size = 215810, upload-time = "2025-10-25T12:44:24.395Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/62/0c/9086a357d02a050fbb3270bf5043ac284dbfb845670e16c9389a41defc9e/pwdlib-0.3.0-py3-none-any.whl", hash = "sha256:f86c15c138858c09f3bba0a10984d4f9178158c55deaa72eac0210849b1a140d", size = 8633, upload-time = "2025-10-25T12:44:23.406Z" }, @@ -4887,7 +3829,7 @@ wheels = [ [package.optional-dependencies] argon2 = [ - { name = "argon2-cffi", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "argon2-cffi" }, ] [[package]] @@ -4895,8 +3837,8 @@ name = "py-key-value-aio" version = "0.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "beartype", marker = "python_full_version >= '3.10'" }, - { name = "py-key-value-shared", marker = "python_full_version >= '3.10'" }, + { name = "beartype" }, + { name = "py-key-value-shared" }, ] sdist = { url = "https://files.pythonhosted.org/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" } wheels = [ @@ -4905,17 +3847,17 @@ wheels = [ [package.optional-dependencies] disk = [ - { name = "diskcache", marker = "python_full_version >= '3.10'" }, - { name = "pathvalidate", marker = "python_full_version >= '3.10'" }, + { name = "diskcache" }, + { name = "pathvalidate" }, ] keyring = [ - { name = "keyring", marker = "python_full_version >= '3.10'" }, + { name = "keyring" }, ] memory = [ - { name = "cachetools", marker = "python_full_version >= '3.10'" }, + { name = "cachetools" }, ] redis = [ - { name = "redis", marker = "python_full_version >= '3.10'" }, + { name = "redis" }, ] [[package]] @@ -4923,8 +3865,8 @@ name = "py-key-value-shared" version = "0.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "beartype", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "beartype" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" } wheels = [ @@ -4952,26 +3894,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, ] -[[package]] -name = "pycparser" -version = "2.23" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, -] - [[package]] name = "pycparser" version = "3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, @@ -4997,126 +3923,31 @@ email = [ { name = "email-validator" }, ] -[[package]] -name = "pydantic-ai" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "pydantic-ai-slim", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "google", "groq", "huggingface", "mistral", "openai", "retries", "temporal", "vertexai"], marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/56/d7/fcc18ce80008e888404a3615f973aa3f39b98384d61b03621144c9f4c2d4/pydantic_ai-0.8.1.tar.gz", hash = "sha256:05974382082ee4f3706909d06bdfcc5e95f39e29230cc4d00e47429080099844", size = 43772581, upload-time = "2025-08-29T14:46:23.201Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/04/802b8cf834dffcda8baabb3b76c549243694a83346c3f54e47a3a4d519fb/pydantic_ai-0.8.1-py3-none-any.whl", hash = "sha256:5fa923097132aa69b4d6a310b462dc091009c7b87705edf4443d37b887d5ef9a", size = 10188, upload-time = "2025-08-29T14:46:11.137Z" }, -] - [[package]] name = "pydantic-ai" version = "1.56.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "pydantic-ai-slim", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"], marker = "python_full_version >= '3.10'" }, + { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"] }, ] sdist = { url = "https://files.pythonhosted.org/packages/60/1a/800a1e02b259152a49d4c11d9103784a7482c7e9b067eeea23e949d3d80f/pydantic_ai-1.56.0.tar.gz", hash = "sha256:643ff71612df52315b3b4c4b41543657f603f567223eb33245dc8098f005bdc4", size = 11795, upload-time = "2026-02-06T01:13:21.122Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/5c/35/f4a7fd2b9962ddb9b021f76f293e74fda71da190bb74b57ed5b343c93022/pydantic_ai-1.56.0-py3-none-any.whl", hash = "sha256:b6b3ac74bdc004693834750da4420ea2cde0d3cbc3f134c0b7544f98f1c00859", size = 7222, upload-time = "2026-02-06T01:13:11.755Z" }, ] -[[package]] -name = "pydantic-ai-slim" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, - { name = "genai-prices", marker = "python_full_version < '3.10'" }, - { name = "griffe", version = "1.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "httpx", marker = "python_full_version < '3.10'" }, - { name = "opentelemetry-api", marker = "python_full_version < '3.10'" }, - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "pydantic-graph", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "typing-inspection", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a2/91/08137459b3745900501b3bd11852ced6c81b7ce6e628696d75b09bb786c5/pydantic_ai_slim-0.8.1.tar.gz", hash = "sha256:12ef3dcbe5e1dad195d5e256746ef960f6e59aeddda1a55bdd553ee375ff53ae", size = 218906, upload-time = "2025-08-29T14:46:27.517Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/ce/8dbadd04f578d02a9825a46e931005743fe223736296f30b55846c084fab/pydantic_ai_slim-0.8.1-py3-none-any.whl", hash = "sha256:fc7edc141b21fe42bc54a2d92c1127f8a75160c5e57a168dba154d3f4adb963f", size = 297821, upload-time = "2025-08-29T14:46:14.647Z" }, -] - -[package.optional-dependencies] -ag-ui = [ - { name = "ag-ui-protocol", marker = "python_full_version < '3.10'" }, - { name = "starlette", version = "0.49.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] -anthropic = [ - { name = "anthropic", marker = "python_full_version < '3.10'" }, -] -bedrock = [ - { name = "boto3", marker = "python_full_version < '3.10'" }, -] -cli = [ - { name = "argcomplete", marker = "python_full_version < '3.10'" }, - { name = "prompt-toolkit", marker = "python_full_version < '3.10'" }, - { name = "pyperclip", marker = "python_full_version < '3.10'" }, - { name = "rich", marker = "python_full_version < '3.10'" }, -] -cohere = [ - { name = "cohere", marker = "python_full_version < '3.10' and sys_platform != 'emscripten'" }, -] -evals = [ - { name = "pydantic-evals", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] -google = [ - { name = "google-genai", version = "1.47.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] -groq = [ - { name = "groq", marker = "python_full_version < '3.10'" }, -] -huggingface = [ - { name = "huggingface-hub", extra = ["inference"], marker = "python_full_version < '3.10'" }, -] -mistral = [ - { name = "mistralai", marker = "python_full_version < '3.10'" }, -] -openai = [ - { name = "openai", marker = "python_full_version < '3.10'" }, -] -retries = [ - { name = "tenacity", version = "9.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] -temporal = [ - { name = "temporalio", version = "1.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, -] -vertexai = [ - { name = "google-auth", marker = "python_full_version < '3.10'" }, - { name = "requests", marker = "python_full_version < '3.10'" }, -] - [[package]] name = "pydantic-ai-slim" version = "1.56.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, - { name = "genai-prices", marker = "python_full_version >= '3.10'" }, - { name = "griffe", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "httpx", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "pydantic-graph", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "genai-prices" }, + { name = "griffe" }, + { name = "httpx" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "pydantic-graph" }, + { name = "typing-inspection" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ce/5c/3a577825b9c1da8f287be7f2ee6fe9aab48bc8a80e65c8518052c589f51c/pydantic_ai_slim-1.56.0.tar.gz", hash = "sha256:9f9f9c56b1c735837880a515ae5661b465b40207b25f3a3434178098b2137f05", size = 415265, upload-time = "2026-02-06T01:13:23.58Z" } wheels = [ @@ -5125,67 +3956,67 @@ wheels = [ [package.optional-dependencies] ag-ui = [ - { name = "ag-ui-protocol", marker = "python_full_version >= '3.10'" }, - { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "ag-ui-protocol" }, + { name = "starlette" }, ] anthropic = [ - { name = "anthropic", marker = "python_full_version >= '3.10'" }, + { name = "anthropic" }, ] bedrock = [ - { name = "boto3", marker = "python_full_version >= '3.10'" }, + { name = "boto3" }, ] cli = [ - { name = "argcomplete", marker = "python_full_version >= '3.10'" }, - { name = "prompt-toolkit", marker = "python_full_version >= '3.10'" }, - { name = "pyperclip", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "argcomplete" }, + { name = "prompt-toolkit" }, + { name = "pyperclip" }, + { name = "rich" }, ] cohere = [ - { name = "cohere", marker = "python_full_version >= '3.10' and sys_platform != 'emscripten'" }, + { name = "cohere", marker = "sys_platform != 'emscripten'" }, ] evals = [ - { name = "pydantic-evals", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pydantic-evals" }, ] fastmcp = [ - { name = "fastmcp", marker = "python_full_version >= '3.10'" }, + { name = "fastmcp" }, ] google = [ - { name = "google-genai", version = "1.62.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "google-genai" }, ] groq = [ - { name = "groq", marker = "python_full_version >= '3.10'" }, + { name = "groq" }, ] huggingface = [ - { name = "huggingface-hub", extra = ["inference"], marker = "python_full_version >= '3.10'" }, + { name = "huggingface-hub", extra = ["inference"] }, ] logfire = [ - { name = "logfire", extra = ["httpx"], marker = "python_full_version >= '3.10'" }, + { name = "logfire", extra = ["httpx"] }, ] mcp = [ - { name = "mcp", marker = "python_full_version >= '3.10'" }, + { name = "mcp" }, ] mistral = [ - { name = "mistralai", marker = "python_full_version >= '3.10'" }, + { name = "mistralai" }, ] openai = [ - { name = "openai", marker = "python_full_version >= '3.10'" }, - { name = "tiktoken", marker = "python_full_version >= '3.10'" }, + { name = "openai" }, + { name = "tiktoken" }, ] retries = [ - { name = "tenacity", version = "9.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "tenacity" }, ] temporal = [ - { name = "temporalio", version = "1.20.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "temporalio" }, ] ui = [ - { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "starlette" }, ] vertexai = [ - { name = "google-auth", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, + { name = "google-auth" }, + { name = "requests" }, ] xai = [ - { name = "xai-sdk", marker = "python_full_version >= '3.10'" }, + { name = "xai-sdk" }, ] [[package]] @@ -5280,19 +4111,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/54/db/160dffb57ed9a3705c4cbcbff0ac03bdae45f1ca7d58ab74645550df3fbd/pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", size = 2107999, upload-time = "2025-11-04T13:42:03.885Z" }, - { url = "https://files.pythonhosted.org/packages/a3/7d/88e7de946f60d9263cc84819f32513520b85c0f8322f9b8f6e4afc938383/pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", size = 1929745, upload-time = "2025-11-04T13:42:06.075Z" }, - { url = "https://files.pythonhosted.org/packages/d5/c2/aef51e5b283780e85e99ff19db0f05842d2d4a8a8cd15e63b0280029b08f/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", size = 1920220, upload-time = "2025-11-04T13:42:08.457Z" }, - { url = "https://files.pythonhosted.org/packages/c7/97/492ab10f9ac8695cd76b2fdb24e9e61f394051df71594e9bcc891c9f586e/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", size = 2067296, upload-time = "2025-11-04T13:42:10.817Z" }, - { url = "https://files.pythonhosted.org/packages/ec/23/984149650e5269c59a2a4c41d234a9570adc68ab29981825cfaf4cfad8f4/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", size = 2231548, upload-time = "2025-11-04T13:42:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/71/0c/85bcbb885b9732c28bec67a222dbed5ed2d77baee1f8bba2002e8cd00c5c/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", size = 2362571, upload-time = "2025-11-04T13:42:16.208Z" }, - { url = "https://files.pythonhosted.org/packages/c0/4a/412d2048be12c334003e9b823a3fa3d038e46cc2d64dd8aab50b31b65499/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", size = 2068175, upload-time = "2025-11-04T13:42:18.911Z" }, - { url = "https://files.pythonhosted.org/packages/73/f4/c58b6a776b502d0a5540ad02e232514285513572060f0d78f7832ca3c98b/pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", size = 2177203, upload-time = "2025-11-04T13:42:22.578Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ae/f06ea4c7e7a9eead3d165e7623cd2ea0cb788e277e4f935af63fc98fa4e6/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", size = 2148191, upload-time = "2025-11-04T13:42:24.89Z" }, - { url = "https://files.pythonhosted.org/packages/c1/57/25a11dcdc656bf5f8b05902c3c2934ac3ea296257cc4a3f79a6319e61856/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", size = 2343907, upload-time = "2025-11-04T13:42:27.683Z" }, - { url = "https://files.pythonhosted.org/packages/96/82/e33d5f4933d7a03327c0c43c65d575e5919d4974ffc026bc917a5f7b9f61/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", size = 2322174, upload-time = "2025-11-04T13:42:30.776Z" }, - { url = "https://files.pythonhosted.org/packages/81/45/4091be67ce9f469e81656f880f3506f6a5624121ec5eb3eab37d7581897d/pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", size = 1990353, upload-time = "2025-11-04T13:42:33.111Z" }, - { url = "https://files.pythonhosted.org/packages/44/8a/a98aede18db6e9cd5d66bcacd8a409fcf8134204cdede2e7de35c5a2c5ef/pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", size = 2015698, upload-time = "2025-11-04T13:42:35.484Z" }, { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, @@ -5319,42 +4137,17 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] -[[package]] -name = "pydantic-evals" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "anyio", marker = "python_full_version < '3.10'" }, - { name = "eval-type-backport", marker = "python_full_version < '3.10'" }, - { name = "logfire-api", marker = "python_full_version < '3.10'" }, - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "pydantic-ai-slim", version = "0.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pyyaml", marker = "python_full_version < '3.10'" }, - { name = "rich", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6c/9d/460a1f2c9f5f263e9d8e9661acbd654ccc81ad3373ea43048d914091a817/pydantic_evals-0.8.1.tar.gz", hash = "sha256:c398a623c31c19ce70e346ad75654fcb1517c3f6a821461f64fe5cbbe0813023", size = 43933, upload-time = "2025-08-29T14:46:28.903Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/f9/1d21c4687167c4fa76fd3b1ed47f9bc2d38fd94cbacd9aa3f19e82e59830/pydantic_evals-0.8.1-py3-none-any.whl", hash = "sha256:6c76333b1d79632f619eb58a24ac656e9f402c47c75ad750ba0230d7f5514344", size = 52602, upload-time = "2025-08-29T14:46:16.602Z" }, -] - [[package]] name = "pydantic-evals" version = "1.56.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "logfire-api", marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "pydantic-ai-slim", version = "1.56.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pyyaml", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "anyio" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "pydantic-ai-slim" }, + { name = "pyyaml" }, + { name = "rich" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/f2/8c59284a2978af3fbda45ae3217218eaf8b071207a9290b54b7613983e5d/pydantic_evals-1.56.0.tar.gz", hash = "sha256:206635107127af6a3ee4b1fc8f77af6afb14683615a2d6b3609f79467c1c0d28", size = 47210, upload-time = "2026-02-06T01:13:25.714Z" } wheels = [ @@ -5374,72 +4167,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fe/17/fabd56da47096d240dd45ba627bead0333b0cf0ee8ada9bec579287dadf3/pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6", size = 74296, upload-time = "2025-12-31T16:18:26.38Z" }, ] -[[package]] -name = "pydantic-graph" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "httpx", marker = "python_full_version < '3.10'" }, - { name = "logfire-api", marker = "python_full_version < '3.10'" }, - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "typing-inspection", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/97/b35b7cb82d9f1bb6d5c6d21bba54f6196a3a5f593373f3a9c163a3821fd7/pydantic_graph-0.8.1.tar.gz", hash = "sha256:c61675a05c74f661d4ff38d04b74bd652c1e0959467801986f2f85dc7585410d", size = 21675, upload-time = "2025-08-29T14:46:29.839Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/e3/5908643b049bb2384d143885725cbeb0f53707d418357d4d1ac8d2c82629/pydantic_graph-0.8.1-py3-none-any.whl", hash = "sha256:f1dd5db0fe22f4e3323c04c65e2f0013846decc312b3efc3196666764556b765", size = 27239, upload-time = "2025-08-29T14:46:18.317Z" }, -] - [[package]] name = "pydantic-graph" version = "1.56.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "httpx", marker = "python_full_version >= '3.10'" }, - { name = "logfire-api", marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, + { name = "httpx" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "typing-inspection" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ff/03/f92881cdb12d6f43e60e9bfd602e41c95408f06e2324d3729f7a194e2bcd/pydantic_graph-1.56.0.tar.gz", hash = "sha256:5e22972dbb43dbc379ab9944252ff864019abf3c7d465dcdf572fc8aec9a44a1", size = 58460, upload-time = "2026-02-06T01:13:26.708Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/08/07/8c823eb4d196137c123d4d67434e185901d3cbaea3b0c2b7667da84e72c1/pydantic_graph-1.56.0-py3-none-any.whl", hash = "sha256:ec3f0a1d6fcedd4eb9c59fef45079c2ee4d4185878d70dae26440a9c974c6bb3", size = 72346, upload-time = "2026-02-06T01:13:18.792Z" }, ] -[[package]] -name = "pydantic-settings" -version = "2.11.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "pydantic", marker = "python_full_version < '3.10'" }, - { name = "python-dotenv", marker = "python_full_version < '3.10'" }, - { name = "typing-inspection", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/20/c5/dbbc27b814c71676593d1c3f718e6cd7d4f00652cefa24b75f7aa3efb25e/pydantic_settings-2.11.0.tar.gz", hash = "sha256:d0e87a1c7d33593beb7194adb8470fc426e95ba02af83a0f23474a04c9a08180", size = 188394, upload-time = "2025-09-24T14:19:11.764Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/d6/887a1ff844e64aa823fb4905978d882a633cfe295c32eacad582b78a7d8b/pydantic_settings-2.11.0-py3-none-any.whl", hash = "sha256:fe2cea3413b9530d10f3a5875adffb17ada5c1e1bab0b2885546d7310415207c", size = 48608, upload-time = "2025-09-24T14:19:10.015Z" }, -] - [[package]] name = "pydantic-settings" version = "2.12.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "python-dotenv", marker = "python_full_version >= '3.10'" }, - { name = "typing-inspection", marker = "python_full_version >= '3.10'" }, + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/4b/ac7e0aae12027748076d72a8764ff1c9d82ca75a7a52622e67ed3f765c54/pydantic_settings-2.12.0.tar.gz", hash = "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0", size = 194184, upload-time = "2025-11-10T14:25:47.013Z" } wheels = [ @@ -5451,19 +4201,19 @@ name = "pydocket" version = "0.17.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cloudpickle", marker = "python_full_version >= '3.10'" }, - { name = "croniter", marker = "python_full_version >= '3.10'" }, - { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, - { name = "fakeredis", extra = ["lua"], marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-api", marker = "python_full_version >= '3.10'" }, - { name = "prometheus-client", marker = "python_full_version >= '3.10'" }, - { name = "py-key-value-aio", extra = ["memory", "redis"], marker = "python_full_version >= '3.10'" }, - { name = "python-json-logger", marker = "python_full_version >= '3.10'" }, - { name = "redis", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, - { name = "taskgroup", marker = "python_full_version == '3.10.*'" }, - { name = "typer", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "cloudpickle" }, + { name = "croniter" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "fakeredis", extra = ["lua"] }, + { name = "opentelemetry-api" }, + { name = "prometheus-client" }, + { name = "py-key-value-aio", extra = ["memory", "redis"] }, + { name = "python-json-logger" }, + { name = "redis" }, + { name = "rich" }, + { name = "taskgroup", marker = "python_full_version < '3.11'" }, + { name = "typer" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/73/26/ac23ead3725475468b50b486939bf5feda27180050a614a7407344a0af0e/pydocket-0.17.5.tar.gz", hash = "sha256:19a6976d8fd11c1acf62feb0291a339e06beaefa100f73dd38c6499760ad3e62", size = 334829, upload-time = "2026-01-30T18:44:39.702Z" } wheels = [ @@ -5491,8 +4241,7 @@ dependencies = [ { name = "pynacl" }, { name = "requests" }, { name = "typing-extensions" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c1/74/e560bdeffea72ecb26cff27f0fad548bbff5ecc51d6a155311ea7f9e4c4c/pygithub-2.8.1.tar.gz", hash = "sha256:341b7c78521cb07324ff670afd1baa2bf5c286f8d9fd302c1798ba594a5400c9", size = 2246994, upload-time = "2025-09-02T17:41:54.674Z" } wheels = [ @@ -5527,8 +4276,7 @@ name = "pymdown-extensions" version = "10.20.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown", version = "3.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown", version = "3.10.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown" }, { name = "pyyaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1e/6c/9e370934bfa30e889d12e61d0dae009991294f40055c238980066a7fbd83/pymdown_extensions-10.20.1.tar.gz", hash = "sha256:e7e39c865727338d434b55f1dd8da51febcffcaebd6e1a0b9c836243f660740a", size = 852860, upload-time = "2026-01-24T05:56:56.758Z" } @@ -5587,8 +4335,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, - { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, @@ -5605,7 +4352,6 @@ version = "4.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "pytest" }, { name = "rich" }, ] @@ -5623,8 +4369,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/14/8d9340d7dc0ae647991b28a396e16b3403e10def883cde90d6b663d3f7ec/pytest_codspeed-4.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0ebd87f2a99467a1cfd8e83492c4712976e43d353ee0b5f71cbb057f1393aca", size = 251057, upload-time = "2025-10-24T09:02:49.102Z" }, { url = "https://files.pythonhosted.org/packages/4b/39/48cf6afbca55bc7c8c93c3d4ae926a1068bcce3f0241709db19b078d5418/pytest_codspeed-4.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbbb2d61b85bef8fc7e2193f723f9ac2db388a48259d981bbce96319043e9830", size = 267983, upload-time = "2025-10-24T09:02:50.558Z" }, { url = "https://files.pythonhosted.org/packages/33/86/4407341efb5dceb3e389635749ce1d670542d6ca148bd34f9d5334295faf/pytest_codspeed-4.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:748411c832147bfc85f805af78a1ab1684f52d08e14aabe22932bbe46c079a5f", size = 256732, upload-time = "2025-10-24T09:02:51.603Z" }, - { url = "https://files.pythonhosted.org/packages/fe/60/c395c19c14a1345d41ac3f7f0a9b372b666e88f9ba1f71988215174882bb/pytest_codspeed-4.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:238e17abe8f08d8747fa6c7acff34fefd3c40f17a56a7847ca13dc8d6e8c6009", size = 261935, upload-time = "2025-10-24T09:02:52.702Z" }, - { url = "https://files.pythonhosted.org/packages/15/ed/442fb6a1832c2c9002653f24770873839b24c091bd2ed658090c7862c563/pytest_codspeed-4.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0881a736285f33b9a8894da8fe8e1775aa1a4310226abe5d1f0329228efb680c", size = 250770, upload-time = "2025-10-24T09:02:53.73Z" }, { url = "https://files.pythonhosted.org/packages/25/0e/8cb71fd3ed4ed08c07aec1245aea7bc1b661ba55fd9c392db76f1978d453/pytest_codspeed-4.2.0-py3-none-any.whl", hash = "sha256:e81bbb45c130874ef99aca97929d72682733527a49f84239ba575b5cb843bab0", size = 113726, upload-time = "2025-10-24T09:02:54.785Z" }, ] @@ -5658,26 +4402,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, ] -[[package]] -name = "python-multipart" -version = "0.0.20" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, -] - [[package]] name = "python-multipart" version = "0.0.22" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, @@ -5731,11 +4459,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, - { url = "https://files.pythonhosted.org/packages/51/2a/f125667ce48105bf1f4e50e03cfa7b24b8c4f47684d7f1cf4dcb6f6b1c15/pytokens-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3", size = 161464, upload-time = "2026-01-30T01:03:39.11Z" }, - { url = "https://files.pythonhosted.org/packages/40/df/065a30790a7ca6bb48ad9018dd44668ed9135610ebf56a2a4cb8e513fd5c/pytokens-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1", size = 246159, upload-time = "2026-01-30T01:03:40.131Z" }, - { url = "https://files.pythonhosted.org/packages/a5/1c/fd09976a7e04960dabc07ab0e0072c7813d566ec67d5490a4c600683c158/pytokens-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db", size = 259120, upload-time = "2026-01-30T01:03:41.233Z" }, - { url = "https://files.pythonhosted.org/packages/52/49/59fdc6fc5a390ae9f308eadeb97dfc70fc2d804ffc49dd39fc97604622ec/pytokens-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1", size = 262196, upload-time = "2026-01-30T01:03:42.696Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e7/d6734dccf0080e3dc00a55b0827ab5af30c886f8bc127bbc04bc3445daec/pytokens-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a", size = 103510, upload-time = "2026-01-30T01:03:43.915Z" }, { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, ] @@ -5768,9 +4491,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, - { url = "https://files.pythonhosted.org/packages/59/42/b86689aac0cdaee7ae1c58d464b0ff04ca909c19bb6502d4973cdd9f9544/pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b", size = 8760837, upload-time = "2025-07-14T20:12:59.59Z" }, - { url = "https://files.pythonhosted.org/packages/9f/8a/1403d0353f8c5a2f0829d2b1c4becbf9da2f0a4d040886404fc4a5431e4d/pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91", size = 9590187, upload-time = "2025-07-14T20:13:01.419Z" }, - { url = "https://files.pythonhosted.org/packages/60/22/e0e8d802f124772cec9c75430b01a212f86f9de7546bda715e54140d5aeb/pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d", size = 8778162, upload-time = "2025-07-14T20:13:03.544Z" }, ] [[package]] @@ -5844,15 +4564,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, - { url = "https://files.pythonhosted.org/packages/9f/62/67fc8e68a75f738c9200422bf65693fb79a4cd0dc5b23310e5202e978090/pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da", size = 184450, upload-time = "2025-09-25T21:33:00.618Z" }, - { url = "https://files.pythonhosted.org/packages/ae/92/861f152ce87c452b11b9d0977952259aa7df792d71c1053365cc7b09cc08/pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917", size = 174319, upload-time = "2025-09-25T21:33:02.086Z" }, - { url = "https://files.pythonhosted.org/packages/d0/cd/f0cfc8c74f8a030017a2b9c771b7f47e5dd702c3e28e5b2071374bda2948/pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9", size = 737631, upload-time = "2025-09-25T21:33:03.25Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b2/18f2bd28cd2055a79a46c9b0895c0b3d987ce40ee471cecf58a1a0199805/pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5", size = 836795, upload-time = "2025-09-25T21:33:05.014Z" }, - { url = "https://files.pythonhosted.org/packages/73/b9/793686b2d54b531203c160ef12bec60228a0109c79bae6c1277961026770/pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a", size = 750767, upload-time = "2025-09-25T21:33:06.398Z" }, - { url = "https://files.pythonhosted.org/packages/a9/86/a137b39a611def2ed78b0e66ce2fe13ee701a07c07aebe55c340ed2a050e/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", size = 727982, upload-time = "2025-09-25T21:33:08.708Z" }, - { url = "https://files.pythonhosted.org/packages/dd/62/71c27c94f457cf4418ef8ccc71735324c549f7e3ea9d34aba50874563561/pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7", size = 755677, upload-time = "2025-09-25T21:33:09.876Z" }, - { url = "https://files.pythonhosted.org/packages/29/3d/6f5e0d58bd924fb0d06c3a6bad00effbdae2de5adb5cda5648006ffbd8d3/pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0", size = 142592, upload-time = "2025-09-25T21:33:10.983Z" }, - { url = "https://files.pythonhosted.org/packages/f0/0c/25113e0b5e103d7f1490c0e947e303fe4a696c10b501dea7a9f49d4e876c/pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007", size = 158777, upload-time = "2025-09-25T21:33:15.55Z" }, ] [[package]] @@ -5881,7 +4592,7 @@ name = "redis" version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "async-timeout", marker = "python_full_version >= '3.10' and python_full_version < '3.11.3'" }, + { name = "async-timeout", marker = "python_full_version < '3.11.3'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } wheels = [ @@ -5893,9 +4604,9 @@ name = "referencing" version = "0.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", marker = "python_full_version >= '3.10'" }, - { name = "rpds-py", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.13'" }, + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } wheels = [ @@ -6021,23 +4732,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/0d/3a6cfa9ae99606afb612d8fb7a66b245a9d5ff0f29bb347c8a30b6ad561b/regex-2026.1.15-cp314-cp314t-win32.whl", hash = "sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e", size = 274667, upload-time = "2026-01-14T23:17:19.301Z" }, { url = "https://files.pythonhosted.org/packages/5b/b2/297293bb0742fd06b8d8e2572db41a855cdf1cae0bf009b1cb74fe07e196/regex-2026.1.15-cp314-cp314t-win_amd64.whl", hash = "sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf", size = 284386, upload-time = "2026-01-14T23:17:21.231Z" }, { url = "https://files.pythonhosted.org/packages/95/e4/a3b9480c78cf8ee86626cb06f8d931d74d775897d44201ccb813097ae697/regex-2026.1.15-cp314-cp314t-win_arm64.whl", hash = "sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70", size = 274837, upload-time = "2026-01-14T23:17:23.146Z" }, - { url = "https://files.pythonhosted.org/packages/a2/e7/0e1913dc52eee9c5cf8417c9813c4c55972a3f37d27cfa2e623b79b63dbc/regex-2026.1.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:55b4ea996a8e4458dd7b584a2f89863b1655dd3d17b88b46cbb9becc495a0ec5", size = 488185, upload-time = "2026-01-14T23:17:25.2Z" }, - { url = "https://files.pythonhosted.org/packages/78/df/c52c1ff4221529faad0953e197982fe9508c6dbb42327e31bf98ea07472a/regex-2026.1.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e1e28be779884189cdd57735e997f282b64fd7ccf6e2eef3e16e57d7a34a815", size = 290628, upload-time = "2026-01-14T23:17:27.125Z" }, - { url = "https://files.pythonhosted.org/packages/4b/d2/a2fef3717deaff647d7de2bccf899a576c7eaf042b6b271fc4474515fe97/regex-2026.1.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0057de9eaef45783ff69fa94ae9f0fd906d629d0bd4c3217048f46d1daa32e9b", size = 288509, upload-time = "2026-01-14T23:17:29.017Z" }, - { url = "https://files.pythonhosted.org/packages/70/89/faf5ee5c69168753c845a3d58b4683f61c899d162bfe1264fca88d5b3924/regex-2026.1.15-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7cd0b2be0f0269283a45c0d8b2c35e149d1319dcb4a43c9c3689fa935c1ee6", size = 781088, upload-time = "2026-01-14T23:17:30.961Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2c/707e5c380ad547c93686e21144e7e24dc2064dd84ec5b751b6dbdfc9be2b/regex-2026.1.15-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8db052bbd981e1666f09e957f3790ed74080c2229007c1dd67afdbf0b469c48b", size = 850516, upload-time = "2026-01-14T23:17:32.946Z" }, - { url = "https://files.pythonhosted.org/packages/5d/3b/baa816cdcad1c0f8195f9f40ab2b2a2246c8a2989dcd90641c0c6559e3fd/regex-2026.1.15-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:343db82cb3712c31ddf720f097ef17c11dab2f67f7a3e7be976c4f82eba4e6df", size = 898124, upload-time = "2026-01-14T23:17:36.019Z" }, - { url = "https://files.pythonhosted.org/packages/e7/74/1eb46bde30899825ed9fdf645eba16b7b97c49d12d300f5177989b9a09a4/regex-2026.1.15-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:55e9d0118d97794367309635df398bdfd7c33b93e2fdfa0b239661cd74b4c14e", size = 791290, upload-time = "2026-01-14T23:17:38.097Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5d/b72e176fb21e2ec248baed01151a342d1f44dd43c2b6bb6a41ad183b274e/regex-2026.1.15-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:008b185f235acd1e53787333e5690082e4f156c44c87d894f880056089e9bc7c", size = 781996, upload-time = "2026-01-14T23:17:40.109Z" }, - { url = "https://files.pythonhosted.org/packages/61/0e/d3b3710eaafd994a4a71205d114abc38cda8691692a2ce2313abe68e7eb7/regex-2026.1.15-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fd65af65e2aaf9474e468f9e571bd7b189e1df3a61caa59dcbabd0000e4ea839", size = 767578, upload-time = "2026-01-14T23:17:42.134Z" }, - { url = "https://files.pythonhosted.org/packages/09/51/c6a6311833e040f95d229a34d82ac1cec2af8a5c00d58b244f2fceecef87/regex-2026.1.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f42e68301ff4afee63e365a5fc302b81bb8ba31af625a671d7acb19d10168a8c", size = 774354, upload-time = "2026-01-14T23:17:44.392Z" }, - { url = "https://files.pythonhosted.org/packages/cc/97/c522d1f19fb2c549aaf680b115c110cd124c02062bc8c95f33db8583b4bb/regex-2026.1.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f7792f27d3ee6e0244ea4697d92b825f9a329ab5230a78c1a68bd274e64b5077", size = 845297, upload-time = "2026-01-14T23:17:47.145Z" }, - { url = "https://files.pythonhosted.org/packages/99/a0/99468c386ab68a5e24c946c5c353c29c33a95523e275c17839f2446db15d/regex-2026.1.15-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:dbaf3c3c37ef190439981648ccbf0c02ed99ae066087dd117fcb616d80b010a4", size = 755132, upload-time = "2026-01-14T23:17:49.796Z" }, - { url = "https://files.pythonhosted.org/packages/70/33/d5748c7b6c9d3621f12570583561ba529e2d1b12e4f70b8f17979b133e65/regex-2026.1.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:adc97a9077c2696501443d8ad3fa1b4fc6d131fc8fd7dfefd1a723f89071cf0a", size = 835662, upload-time = "2026-01-14T23:17:52.559Z" }, - { url = "https://files.pythonhosted.org/packages/ad/15/1986972c276672505437f1ba3c9706c2d91f321cfb9b2f4d06e8bff1b999/regex-2026.1.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:069f56a7bf71d286a6ff932a9e6fb878f151c998ebb2519a9f6d1cee4bffdba3", size = 779513, upload-time = "2026-01-14T23:17:54.711Z" }, - { url = "https://files.pythonhosted.org/packages/bc/f9/124f6a5cb3969d8e30471ed4f46cfc17c47aef1a9863ee8b4ba1d98b1bc4/regex-2026.1.15-cp39-cp39-win32.whl", hash = "sha256:ea4e6b3566127fda5e007e90a8fd5a4169f0cf0619506ed426db647f19c8454a", size = 265923, upload-time = "2026-01-14T23:17:56.69Z" }, - { url = "https://files.pythonhosted.org/packages/7b/c2/bb8fad7d27f1d71fc9772befd544bccd22eddc62a6735f57b003b4aff005/regex-2026.1.15-cp39-cp39-win_amd64.whl", hash = "sha256:cda1ed70d2b264952e88adaa52eea653a33a1b98ac907ae2f86508eb44f65cdc", size = 277900, upload-time = "2026-01-14T23:17:58.72Z" }, - { url = "https://files.pythonhosted.org/packages/f7/fa/4e033327c1d8350bc812cac906d873984d3d4b39529252f392a47ccc356d/regex-2026.1.15-cp39-cp39-win_arm64.whl", hash = "sha256:b325d4714c3c48277bfea1accd94e193ad6ed42b4bad79ad64f3b8f8a31260a5", size = 270413, upload-time = "2026-01-14T23:18:00.764Z" }, ] [[package]] @@ -6048,8 +4742,7 @@ dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, { name = "idna" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ @@ -6061,8 +4754,7 @@ name = "rich" version = "14.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown-it-py" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/99/a4cab2acbb884f80e558b0771e97e21e939c5dfb460f488d19df485e8298/rich-14.3.2.tar.gz", hash = "sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8", size = 230143, upload-time = "2026-02-01T16:20:47.908Z" } @@ -6075,8 +4767,8 @@ name = "rich-rst" version = "1.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils", marker = "python_full_version >= '3.10'" }, - { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "docutils" }, + { name = "rich" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } wheels = [ @@ -6088,8 +4780,7 @@ name = "rich-toolkit" version = "0.18.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "rich" }, { name = "typing-extensions" }, ] @@ -6193,20 +4884,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/d3/18210222b37e87e36357f7b300b7d98c6dd62b133771e71ae27acba83a4f/rignore-0.7.6-cp314-cp314t-win32.whl", hash = "sha256:c1d8f117f7da0a4a96a8daef3da75bc090e3792d30b8b12cfadc240c631353f9", size = 647033, upload-time = "2025-11-05T21:42:00.095Z" }, { url = "https://files.pythonhosted.org/packages/3e/87/033eebfbee3ec7d92b3bb1717d8f68c88e6fc7de54537040f3b3a405726f/rignore-0.7.6-cp314-cp314t-win_amd64.whl", hash = "sha256:ca36e59408bec81de75d307c568c2d0d410fb880b1769be43611472c61e85c96", size = 725647, upload-time = "2025-11-05T21:41:44.449Z" }, { url = "https://files.pythonhosted.org/packages/79/62/b88e5879512c55b8ee979c666ee6902adc4ed05007226de266410ae27965/rignore-0.7.6-cp314-cp314t-win_arm64.whl", hash = "sha256:b83adabeb3e8cf662cabe1931b83e165b88c526fa6af6b3aa90429686e474896", size = 656035, upload-time = "2025-11-05T21:41:31.13Z" }, - { url = "https://files.pythonhosted.org/packages/b9/b4/e7577504d926ced2d6a3fa5ec5f27756639a1ed58a6a3fbefcf3a5659721/rignore-0.7.6-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b3746bda73f2fe6a9c3ab2f20b792e7d810b30acbdba044313fbd2d0174802e7", size = 886535, upload-time = "2025-11-05T20:42:49.317Z" }, - { url = "https://files.pythonhosted.org/packages/2b/74/098bc71a33e2997bc3291d500760123d23e3a6d354380d26c8a7ddc036de/rignore-0.7.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:67a99cf19a5137cc12f14b78dc1bb3f48500f1d5580702c623297d5297bf2752", size = 826621, upload-time = "2025-11-05T20:42:32.421Z" }, - { url = "https://files.pythonhosted.org/packages/7b/73/5f8c276d71009a7e73fb3af6ec3bb930269efeae5830de5c796fa1fb020f/rignore-0.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9e851cfa87033c0c3fd9d35dd8b102aff2981db8bc6e0cab27b460bfe38bf3f", size = 900335, upload-time = "2025-11-05T20:40:59.178Z" }, - { url = "https://files.pythonhosted.org/packages/0d/5f/dde3758084a087e6a5cd981c5277c6171d12127deed64fc4fbf12fb8ceaa/rignore-0.7.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e9b0def154665036516114437a5d603274e5451c0dc9694f622cc3b7e94603e7", size = 874274, upload-time = "2025-11-05T20:41:14.512Z" }, - { url = "https://files.pythonhosted.org/packages/58/b9/da85646824ab728036378ce62c330316108a52f30f36e6c69cac6ceda376/rignore-0.7.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b81274a47e8121224f7f637392b5dfcd9558e32a53e67ba7d04007d8b5281da9", size = 1171639, upload-time = "2025-11-05T20:41:31.206Z" }, - { url = "https://files.pythonhosted.org/packages/35/d1/8c12b779b7f0302c03c1d41511f2ab47012afecdfcd684fbec80af06b331/rignore-0.7.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d75d0b0696fb476664bea1169c8e67b13197750b91eceb4f10b3c7f379c7a204", size = 943985, upload-time = "2025-11-05T20:41:45.598Z" }, - { url = "https://files.pythonhosted.org/packages/79/bf/c233a85d31e4f94b911e92ee7e2dd2b962a5c2528f5ebd79a702596f0626/rignore-0.7.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ad3aa4dca77cef9168d0c142f72376f5bd27d1d4b8a81561bd01276d3ad9fe1", size = 961707, upload-time = "2025-11-05T20:42:16.461Z" }, - { url = "https://files.pythonhosted.org/packages/9d/eb/cadee9316a5f2a52b4aa7051967ecb94ec17938d6b425bd842d9317559eb/rignore-0.7.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00f8a59e19d219f44a93af7173de197e0d0e61c386364da20ebe98a303cbe38c", size = 986638, upload-time = "2025-11-05T20:42:00.65Z" }, - { url = "https://files.pythonhosted.org/packages/d0/f0/2c3042c8c9639056593def5e99c3bfe850fbb9a38d061ba67b6314315bad/rignore-0.7.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6c682f3cdd741e7a30af2581f6a382ac910080977cd1f97c651467b6268352", size = 1080136, upload-time = "2025-11-05T21:40:21.551Z" }, - { url = "https://files.pythonhosted.org/packages/fc/28/7237b9eb1257b593ee51cd7ef8eed7cc32f50ccff18cb4d7cfe1e6dc54d7/rignore-0.7.6-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ae4e93193f75ebf6b820241594a78f347785cfd5a5fbbac94634052589418352", size = 1139413, upload-time = "2025-11-05T21:40:39.025Z" }, - { url = "https://files.pythonhosted.org/packages/a5/df/c3f382a31ad7ed68510b411c28fec42354d2c43fecb7c053d998ee9410ed/rignore-0.7.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1163d8b5d3a320d4d7cc8635213328850dc41f60e438c7869d540061adf66c98", size = 1120204, upload-time = "2025-11-05T21:40:56.062Z" }, - { url = "https://files.pythonhosted.org/packages/9c/3d/e8585c4e9c0077255ba599684aee78326176ab13ff13805ea62aa7e3235f/rignore-0.7.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3e685f47b4c58b2df7dee81ebc1ec9dbb7f798b9455c3f22be6d75ac6bddee30", size = 1129757, upload-time = "2025-11-05T21:41:14.148Z" }, - { url = "https://files.pythonhosted.org/packages/fd/56/852226c13f89ddbbf12d639900941dc55dcbcf79f5d15294796fd3279d73/rignore-0.7.6-cp39-cp39-win32.whl", hash = "sha256:2af6a0a76575220863cd838693c808a94e750640e0c8a3e9f707e93c2f131fdf", size = 648265, upload-time = "2025-11-05T21:41:58.589Z" }, - { url = "https://files.pythonhosted.org/packages/cc/c6/14e7585dc453a870fe99b1270ee95e2adff02ea0d297cd6e2c4aa46cd43a/rignore-0.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:a326eab6db9ab85b4afb5e6eb28736a9f2b885a9246d9e8c1989bc693dd059a0", size = 728715, upload-time = "2025-11-05T21:41:42.823Z" }, { url = "https://files.pythonhosted.org/packages/85/12/62d690b4644c330d7ac0f739b7f078190ab4308faa909a60842d0e4af5b2/rignore-0.7.6-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3d3a523af1cd4ed2c0cba8d277a32d329b0c96ef9901fb7ca45c8cfaccf31a5", size = 887462, upload-time = "2025-11-05T20:42:50.804Z" }, { url = "https://files.pythonhosted.org/packages/05/bc/6528a0e97ed2bd7a7c329183367d1ffbc5b9762ae8348d88dae72cc9d1f5/rignore-0.7.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:990853566e65184a506e1e2af2d15045afad3ebaebb8859cb85b882081915110", size = 826918, upload-time = "2025-11-05T20:42:33.689Z" }, { url = "https://files.pythonhosted.org/packages/3e/2c/7d7bad116e09a04e9e1688c6f891fa2d4fd33f11b69ac0bd92419ddebeae/rignore-0.7.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cab9ff2e436ce7240d7ee301c8ef806ed77c1fd6b8a8239ff65f9bbbcb5b8a3", size = 900922, upload-time = "2025-11-05T20:41:00.361Z" }, @@ -6231,18 +4908,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/56/36d5d34210e5e7dfcd134eed8335b19e80ae940ee758f493e4f2b344dd70/rignore-0.7.6-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:c081f17290d8a2b96052b79207622aa635686ea39d502b976836384ede3d303c", size = 1139789, upload-time = "2025-11-05T21:40:42.119Z" }, { url = "https://files.pythonhosted.org/packages/6b/5b/bb4f9420802bf73678033a4a55ab1bede36ce2e9b41fec5f966d83d932b3/rignore-0.7.6-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:57e8327aacc27f921968cb2a174f9e47b084ce9a7dd0122c8132d22358f6bd79", size = 1120308, upload-time = "2025-11-05T21:40:59.402Z" }, { url = "https://files.pythonhosted.org/packages/ce/8b/a1299085b28a2f6135e30370b126e3c5055b61908622f2488ade67641479/rignore-0.7.6-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d8955b57e42f2a5434670d5aa7b75eaf6e74602ccd8955dddf7045379cd762fb", size = 1129444, upload-time = "2025-11-05T21:41:17.906Z" }, - { url = "https://files.pythonhosted.org/packages/47/98/80ef6fda78161e88ef9336fcbe851afccf78c48e69e8266a23fb7922b5aa/rignore-0.7.6-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e6ba1511c0ab8cd1ed8d6055bb0a6e629f48bfe04854293e0cd2dd88bd7153f8", size = 887180, upload-time = "2025-11-05T21:40:07.665Z" }, - { url = "https://files.pythonhosted.org/packages/21/d7/8666e7081f8476b003d8d2c8f39ecc17c93b7efd261740d15b6830acde82/rignore-0.7.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:50586d90be15f9aa8a2e2ee5a042ee6c51e28848812a35f0c95d4bfc0533d469", size = 827029, upload-time = "2025-11-05T20:42:36.628Z" }, - { url = "https://files.pythonhosted.org/packages/01/aa/3aba657d17b1737f4180b143866fedd269de15f361a8cb26ba363c0c3c13/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b129873dd0ade248e67f25a09b5b72288cbef76ba1a9aae6bac193ee1d8be72", size = 901338, upload-time = "2025-11-05T20:41:03.059Z" }, - { url = "https://files.pythonhosted.org/packages/90/cc/d8c2c9770f5f61b28999c582804f282f2227c155ba13dfb0e9ea03daeaaf/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d9d6dd947556ddebfd62753005104986ee14a4e0663818aed19cdf2c33a6b5d5", size = 877563, upload-time = "2025-11-05T20:41:19.209Z" }, - { url = "https://files.pythonhosted.org/packages/55/63/42dd625bf96989be4a928b5444ddec9101ee63a98a15646e611b3ce58b82/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91b95faa532efba888b196331e9af69e693635d469185ac52c796e435e2484e5", size = 1171087, upload-time = "2025-11-05T20:41:35.558Z" }, - { url = "https://files.pythonhosted.org/packages/bf/1e/4130fb622c2081c5322caf7a8888d1d265b99cd5d62cb714b512b8911233/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a1016f430fb56f7e400838bbc56fdf43adddb6fcb7bf2a14731dfd725c2fae6c", size = 944335, upload-time = "2025-11-05T20:41:49.859Z" }, - { url = "https://files.pythonhosted.org/packages/0f/b9/3d3ef7773da85e002fab53b1fdd9e9bb111cc86792b761cb38bd00c1532e/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f00c519861926dc703ecbb7bbeb884be67099f96f98b175671fa0a54718f55d1", size = 961500, upload-time = "2025-11-05T20:42:20.798Z" }, - { url = "https://files.pythonhosted.org/packages/1f/bc/346c874a31a721064935c60666a19016b6b01cd716cf73d52dc64e467b30/rignore-0.7.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e34d172bf50e881b7c02e530ae8b1ea96093f0b16634c344f637227b39707b41", size = 987741, upload-time = "2025-11-05T20:42:05.071Z" }, - { url = "https://files.pythonhosted.org/packages/6d/b8/d12dc548da8fdb63292a38727b035153495220cd93730019ee8ed3bdcffb/rignore-0.7.6-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:101d3143619898db1e7bede2e3e647daf19bb867c4fb25978016d67978d14868", size = 1081057, upload-time = "2025-11-05T21:40:26.53Z" }, - { url = "https://files.pythonhosted.org/packages/8e/51/7eea5d949212709740ad07e01c524336e44608ef0614a2a1cb31c9a0ea30/rignore-0.7.6-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:c9f3b420f54199a2b2b3b532d8c7e0860be3fa51f67501113cca6c7bfc392840", size = 1141653, upload-time = "2025-11-05T21:40:43.676Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2b/76ec843cc392fcb4e37d6a8340e823a0bf644872e191d2f5652a4c2c18ee/rignore-0.7.6-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:1c6795e3694d750ae5ef172eab7d68a52aefbd9168d2e06647df691db2b03a50", size = 1121465, upload-time = "2025-11-05T21:41:00.904Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9d/e69ad5cf03211a1076f9fe04ca2698c9cb8208b63419c928c26646bdf1d9/rignore-0.7.6-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:750a83a254b020e1193bfa7219dc7edca26bd8888a94cdc59720cbe386ab0c72", size = 1130110, upload-time = "2025-11-05T21:41:20.263Z" }, ] [[package]] @@ -6421,8 +5086,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "python_full_version >= '3.10'" }, - { name = "jeepney", marker = "python_full_version >= '3.10'" }, + { name = "cryptography" }, + { name = "jeepney" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ @@ -6435,8 +5100,7 @@ version = "2.52.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, - { name = "urllib3", version = "1.26.20", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/59/eb/1b497650eb564701f9a7b8a95c51b2abe9347ed2c0b290ba78f027ebe4ea/sentry_sdk-2.52.0.tar.gz", hash = "sha256:fa0bec872cfec0302970b2996825723d67390cdd5f0229fb9efed93bd5384899", size = 410273, upload-time = "2026-02-04T15:03:54.706Z" } wheels = [ @@ -6506,8 +5170,7 @@ name = "sqlalchemy" version = "2.0.46" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "greenlet", version = "3.2.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.10' and platform_machine == 'AMD64') or (python_full_version < '3.10' and platform_machine == 'WIN32') or (python_full_version < '3.10' and platform_machine == 'aarch64') or (python_full_version < '3.10' and platform_machine == 'amd64') or (python_full_version < '3.10' and platform_machine == 'ppc64le') or (python_full_version < '3.10' and platform_machine == 'win32') or (python_full_version < '3.10' and platform_machine == 'x86_64')" }, - { name = "greenlet", version = "3.3.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and platform_machine == 'AMD64') or (python_full_version >= '3.10' and platform_machine == 'WIN32') or (python_full_version >= '3.10' and platform_machine == 'aarch64') or (python_full_version >= '3.10' and platform_machine == 'amd64') or (python_full_version >= '3.10' and platform_machine == 'ppc64le') or (python_full_version >= '3.10' and platform_machine == 'win32') or (python_full_version >= '3.10' and platform_machine == 'x86_64')" }, + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" } @@ -6555,13 +5218,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" }, { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" }, { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" }, - { url = "https://files.pythonhosted.org/packages/9a/06/a29b51a577cc5746712ed8a2870794659a6bf405264b32dd5ccc380844d1/sqlalchemy-2.0.46-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3", size = 2158097, upload-time = "2026-01-21T18:24:45.892Z" }, - { url = "https://files.pythonhosted.org/packages/be/55/44689ed21b5a82708502243310878cfc76e0f326ed16103f4336f605055b/sqlalchemy-2.0.46-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a", size = 3233722, upload-time = "2026-01-21T18:30:56.334Z" }, - { url = "https://files.pythonhosted.org/packages/be/11/1d6024d9cdd2108d500b399bdc77a1738119789aa70c83d68e1012d32596/sqlalchemy-2.0.46-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce", size = 3233038, upload-time = "2026-01-21T18:32:26.945Z" }, - { url = "https://files.pythonhosted.org/packages/38/6d/f813e3204baea710f2d82a61821bdf7b39cebda6dbba7cdeb976b0552239/sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5", size = 3183163, upload-time = "2026-01-21T18:30:58.647Z" }, - { url = "https://files.pythonhosted.org/packages/8d/5d/32b70643ef73c1bb3723a98316b89182cad2b9a6744d5335f1d69fcdb3f2/sqlalchemy-2.0.46-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc", size = 3205174, upload-time = "2026-01-21T18:32:28.684Z" }, - { url = "https://files.pythonhosted.org/packages/99/a9/b9f7bd299b7550925e1e7d71d634e1eee23c035abed7de125fda7c74b0c8/sqlalchemy-2.0.46-cp39-cp39-win32.whl", hash = "sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d", size = 2117095, upload-time = "2026-01-21T18:34:02.596Z" }, - { url = "https://files.pythonhosted.org/packages/04/0b/2e376b34a7c2f3d9d40811c3412fdc65cd35c6da2d660c283ad24bd9bab1/sqlalchemy-2.0.46-cp39-cp39-win_amd64.whl", hash = "sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be", size = 2140517, upload-time = "2026-01-21T18:34:03.958Z" }, { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" }, ] @@ -6583,80 +5239,37 @@ name = "sse-starlette" version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "starlette", version = "0.52.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "anyio" }, + { name = "starlette" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8b/8d/00d280c03ffd39aaee0e86ec81e2d3b9253036a0f93f51d10503adef0e65/sse_starlette-3.2.0.tar.gz", hash = "sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422", size = 27253, upload-time = "2026-01-17T13:11:05.62Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/96/7f/832f015020844a8b8f7a9cbc103dd76ba8e3875004c41e08440ea3a2b41a/sse_starlette-3.2.0-py3-none-any.whl", hash = "sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf", size = 12763, upload-time = "2026-01-17T13:11:03.775Z" }, ] -[[package]] -name = "starlette" -version = "0.49.3" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "anyio", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/de/1a/608df0b10b53b0beb96a37854ee05864d182ddd4b1156a22f1ad3860425a/starlette-0.49.3.tar.gz", hash = "sha256:1c14546f299b5901a1ea0e34410575bc33bbd741377a10484a54445588d00284", size = 2655031, upload-time = "2025-11-01T15:12:26.13Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/e0/021c772d6a662f43b63044ab481dc6ac7592447605b5b35a957785363122/starlette-0.49.3-py3-none-any.whl", hash = "sha256:b579b99715fdc2980cf88c8ec96d3bf1ce16f5a8051a7c2b84ef9b1cdecaea2f", size = 74340, upload-time = "2025-11-01T15:12:24.387Z" }, -] - [[package]] name = "starlette" version = "0.52.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.13'" }, + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, ] -[[package]] -name = "strawberry-graphql" -version = "0.283.3" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "graphql-core", marker = "python_full_version < '3.10'" }, - { name = "lia-web", marker = "python_full_version < '3.10'" }, - { name = "packaging", marker = "python_full_version < '3.10'" }, - { name = "python-dateutil", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/30/74/729c227b1e7fce28678290a5013ddceb543f350b6c14ae83400ab2c727d1/strawberry_graphql-0.283.3.tar.gz", hash = "sha256:375e545856b7587debd4e0f1e2a6fca19d09cc126238a07b9e5164e5eb09342a", size = 212141, upload-time = "2025-10-10T20:03:46.985Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/23/1b/aa358ef730d727d2e42810bf943542a8cc4c15aa2401f8629d356643a06f/strawberry_graphql-0.283.3-py3-none-any.whl", hash = "sha256:3751d86a219d81a16a13f335bb7d2fa3f57a85fab83d7d284b8ea88e2261d68b", size = 309885, upload-time = "2025-10-10T20:03:44.051Z" }, -] - [[package]] name = "strawberry-graphql" version = "0.291.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "cross-web", marker = "python_full_version >= '3.10'" }, - { name = "graphql-core", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "python-dateutil", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "cross-web" }, + { name = "graphql-core" }, + { name = "packaging" }, + { name = "python-dateutil" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/dd/e0e68f4b17da6ff5773fcd4bebf86fc4ff8620c854be816d047e9af8c4aa/strawberry_graphql-0.291.2.tar.gz", hash = "sha256:e6076604a786e8437bc64a27348584c082113442f072daf757b56e4863543a97", size = 217730, upload-time = "2026-02-06T14:40:51.173Z" } wheels = [ @@ -6680,50 +5293,24 @@ name = "taskgroup" version = "0.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version >= '3.10' and python_full_version < '3.14'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10' and python_full_version < '3.14'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.14'" }, + { name = "typing-extensions", marker = "python_full_version < '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f0/8d/e218e0160cc1b692e6e0e5ba34e8865dbb171efeb5fc9a704544b3020605/taskgroup-0.2.2.tar.gz", hash = "sha256:078483ac3e78f2e3f973e2edbf6941374fbea81b9c5d0a96f51d297717f4752d", size = 11504, upload-time = "2025-01-03T09:24:13.761Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b1/74babcc824a57904e919f3af16d86c08b524c0691504baf038ef2d7f655c/taskgroup-0.2.2-py2.py3-none-any.whl", hash = "sha256:e2c53121609f4ae97303e9ea1524304b4de6faf9eb2c9280c7f87976479a52fb", size = 14237, upload-time = "2025-01-03T09:24:11.41Z" }, ] -[[package]] -name = "temporalio" -version = "1.16.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "nexus-rpc", version = "1.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "protobuf", version = "5.29.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "python-dateutil", marker = "python_full_version < '3.10'" }, - { name = "types-protobuf", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/32/375ab75d0ebb468cf9c8abbc450a03d3a8c66401fc320b338bd8c00d36b4/temporalio-1.16.0.tar.gz", hash = "sha256:dd926f3e30626fd4edf5e0ce596b75ecb5bbe0e4a0281e545ac91b5577967c91", size = 1733873, upload-time = "2025-08-21T22:12:50.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/36/12bb7234c83ddca4b8b032c8f1a9e07a03067c6ed6d2ddb39c770a4c87c6/temporalio-1.16.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:547c0853310350d3e5b5b9c806246cbf2feb523f685b05bf14ec1b0ece8a7bb6", size = 12540769, upload-time = "2025-08-21T22:11:24.551Z" }, - { url = "https://files.pythonhosted.org/packages/3c/16/a7d402435b8f994979abfeffd3f5ffcaaeada467ac16438e61c51c9f7abe/temporalio-1.16.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b05bb0d06025645aed6f936615311a6774eb8dc66280f32a810aac2283e1258", size = 12968631, upload-time = "2025-08-21T22:11:48.375Z" }, - { url = "https://files.pythonhosted.org/packages/11/6f/16663eef877b61faa5fd917b3a63497416ec4319195af75f6169a1594479/temporalio-1.16.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a08aed4e0f6c2b6bfc779b714e91dfe8c8491a0ddb4c4370627bb07f9bddcfd", size = 13164612, upload-time = "2025-08-21T22:12:16.366Z" }, - { url = "https://files.pythonhosted.org/packages/af/0e/8c6704ca7033aa09dc084f285d70481d758972cc341adc3c84d5f82f7b01/temporalio-1.16.0-cp39-abi3-win_amd64.whl", hash = "sha256:7c190362b0d7254f1f93fb71456063e7b299ac85a89f6227758af82c6a5aa65b", size = 13177058, upload-time = "2025-08-21T22:12:44.239Z" }, -] - [[package]] name = "temporalio" version = "1.20.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "nexus-rpc", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-dateutil", marker = "python_full_version == '3.10.*'" }, - { name = "types-protobuf", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "nexus-rpc" }, + { name = "protobuf" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "types-protobuf" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/21/db/7d5118d28b0918888e1ec98f56f659fdb006351e06d95f30f4274962a76f/temporalio-1.20.0.tar.gz", hash = "sha256:5a6a85b7d298b7359bffa30025f7deac83c74ac095a4c6952fbf06c249a2a67c", size = 1850498, upload-time = "2025-11-25T21:25:20.225Z" } wheels = [ @@ -6734,51 +5321,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/23/5689c014a76aff3b744b3ee0d80815f63b1362637814f5fbb105244df09b/temporalio-1.20.0-cp310-abi3-win_amd64.whl", hash = "sha256:eacfd571b653e0a0f4aa6593f4d06fc628797898f0900d400e833a1f40cad03a", size = 12745027, upload-time = "2025-11-25T21:25:16.827Z" }, ] -[[package]] -name = "tenacity" -version = "9.1.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, -] - [[package]] name = "tenacity" version = "9.1.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/1e/4a/c3357c8742f361785e3702bb4c9c68c4cb37a80aa657640b820669be5af1/tenacity-9.1.3.tar.gz", hash = "sha256:a6724c947aa717087e2531f883bde5c9188f603f6669a9b8d54eb998e604c12a", size = 49002, upload-time = "2026-02-05T06:33:12.866Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/6b/cdc85edb15e384d8e934aad89638cc8646e118c80de94c60125d0fc0a185/tenacity-9.1.3-py3-none-any.whl", hash = "sha256:51171cfc6b8a7826551e2f029426b10a6af189c5ac6986adcd7eb36d42f17954", size = 28858, upload-time = "2026-02-05T06:33:11.219Z" }, ] -[[package]] -name = "termcolor" -version = "3.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/ca/6c/3d75c196ac07ac8749600b60b03f4f6094d54e132c4d94ebac6ee0e0add0/termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970", size = 14324, upload-time = "2025-04-30T11:37:53.791Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/bd/de8d508070629b6d84a30d01d57e4a65c69aa7f5abe7560b8fad3b50ea59/termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa", size = 7684, upload-time = "2025-04-30T11:37:52.382Z" }, -] - [[package]] name = "termcolor" version = "3.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/46/79/cf31d7a93a8fdc6aa0fbb665be84426a8c5a557d9240b6239e9e11e35fc5/termcolor-3.3.0.tar.gz", hash = "sha256:348871ca648ec6a9a983a13ab626c0acce02f515b9e1983332b17af7979521c5", size = 14434, upload-time = "2025-12-29T12:55:21.882Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, @@ -6798,8 +5353,8 @@ name = "tiktoken" version = "0.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "regex", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, + { name = "regex" }, + { name = "requests" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } wheels = [ @@ -6852,40 +5407,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" }, { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" }, { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" }, - { url = "https://files.pythonhosted.org/packages/c7/d1/7507bfb9c2ceef52ae3ae813013215c185648e21127538aae66dedd3af9c/tiktoken-0.12.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:d51d75a5bffbf26f86554d28e78bfb921eae998edc2675650fd04c7e1f0cdc1e", size = 1053407, upload-time = "2025-10-06T20:22:35.492Z" }, - { url = "https://files.pythonhosted.org/packages/ee/4a/8ea1da602ac39dee4356b4cd6040a2325507482c36043044b6f581597b4f/tiktoken-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:09eb4eae62ae7e4c62364d9ec3a57c62eea707ac9a2b2c5d6bd05de6724ea179", size = 997150, upload-time = "2025-10-06T20:22:37.286Z" }, - { url = "https://files.pythonhosted.org/packages/2c/1a/62d1d36b167eccd441aff2f0091551ca834295541b949d161021aa658167/tiktoken-0.12.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:df37684ace87d10895acb44b7f447d4700349b12197a526da0d4a4149fde074c", size = 1131575, upload-time = "2025-10-06T20:22:39.023Z" }, - { url = "https://files.pythonhosted.org/packages/f7/16/544207d63c8c50edd2321228f21d236e4e49d235128bb7e3e0f69eed0807/tiktoken-0.12.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:4c9614597ac94bb294544345ad8cf30dac2129c05e2db8dc53e082f355857af7", size = 1154920, upload-time = "2025-10-06T20:22:40.175Z" }, - { url = "https://files.pythonhosted.org/packages/99/4c/0a3504157c81364fc0c64cada54efef0567961357e786706ea63bc8946e1/tiktoken-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:20cf97135c9a50de0b157879c3c4accbb29116bcf001283d26e073ff3b345946", size = 1196766, upload-time = "2025-10-06T20:22:41.365Z" }, - { url = "https://files.pythonhosted.org/packages/d4/46/8e6a258ae65447c75770fe5ea8968acab369e8c9f537f727c91f83772325/tiktoken-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:15d875454bbaa3728be39880ddd11a5a2a9e548c29418b41e8fd8a767172b5ec", size = 1258278, upload-time = "2025-10-06T20:22:42.846Z" }, - { url = "https://files.pythonhosted.org/packages/35/43/3b95de4f5e76f3cafc70dac9b1b9cfe759ff3bfd494ac91a280e93772e90/tiktoken-0.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cff3688ba3c639ebe816f8d58ffbbb0aa7433e23e08ab1cade5d175fc973fb3", size = 881888, upload-time = "2025-10-06T20:22:44.059Z" }, -] - -[[package]] -name = "tinycss2" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "webencodings", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, ] [[package]] name = "tinycss2" version = "1.5.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "webencodings", marker = "python_full_version >= '3.10'" }, + { name = "webencodings" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/ae/2ca4913e5c0f09781d75482874c3a95db9105462a92ddd303c7d285d3df2/tinycss2-1.5.1.tar.gz", hash = "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957", size = 88195, upload-time = "2025-11-23T10:29:10.082Z" } wheels = [ @@ -6920,10 +5449,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/46/cd/e4851401f3d8f6f45d8480262ab6a5c8cb9c4302a790a35aa14eeed6d2fd/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", size = 3161308, upload-time = "2026-01-05T10:40:40.737Z" }, { url = "https://files.pythonhosted.org/packages/6f/6e/55553992a89982cd12d4a66dddb5e02126c58677ea3931efcbe601d419db/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", size = 3718964, upload-time = "2026-01-05T10:40:46.56Z" }, { url = "https://files.pythonhosted.org/packages/59/8c/b1c87148aa15e099243ec9f0cf9d0e970cc2234c3257d558c25a2c5304e6/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5", size = 3373542, upload-time = "2026-01-05T10:40:52.803Z" }, - { url = "https://files.pythonhosted.org/packages/27/46/8d7db1dff181be50b207ab0a7483a22d5c3a4f903a9afc7cf7e465ad8109/tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319f659ee992222f04e58f84cbf407cfa66a65fe3a8de44e8ad2bc53e7d99012", size = 3287784, upload-time = "2026-01-05T10:40:37.108Z" }, - { url = "https://files.pythonhosted.org/packages/5b/6e/3bc33cae8bf114afa5a98e35eb065c72b7c37d01d370906a893f33881767/tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e50f8554d504f617d9e9d6e4c2c2884a12b388a97c5c77f0bc6cf4cd032feee", size = 3164301, upload-time = "2026-01-05T10:40:42.367Z" }, - { url = "https://files.pythonhosted.org/packages/91/fc/6aa749d7d443aab4daa6f8bc00338389149fd2534e25b772285c3301993e/tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a62ba2c5faa2dd175aaeed7b15abf18d20266189fb3406c5d0550dd34dd5f37", size = 3717771, upload-time = "2026-01-05T10:40:49.076Z" }, - { url = "https://files.pythonhosted.org/packages/fc/60/5b440d251863bd33f9b0a416c695b0309487b83abf6f2dafe9163a3aeac2/tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143b999bdc46d10febb15cbffb4207ddd1f410e2c755857b5a0797961bbdc113", size = 3377740, upload-time = "2026-01-05T10:40:54.859Z" }, ] [[package]] @@ -6992,43 +5517,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] -[[package]] -name = "trio" -version = "0.31.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "attrs", marker = "python_full_version < '3.10'" }, - { name = "cffi", marker = "python_full_version < '3.10' and implementation_name != 'pypy' and os_name == 'nt'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, - { name = "idna", marker = "python_full_version < '3.10'" }, - { name = "outcome", marker = "python_full_version < '3.10'" }, - { name = "sniffio", marker = "python_full_version < '3.10'" }, - { name = "sortedcontainers", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/76/8f/c6e36dd11201e2a565977d8b13f0b027ba4593c1a80bed5185489178e257/trio-0.31.0.tar.gz", hash = "sha256:f71d551ccaa79d0cb73017a33ef3264fde8335728eb4c6391451fe5d253a9d5b", size = 605825, upload-time = "2025-09-09T15:17:15.242Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/5b/94237a3485620dbff9741df02ff6d8acaa5fdec67d81ab3f62e4d8511bf7/trio-0.31.0-py3-none-any.whl", hash = "sha256:b5d14cd6293d79298b49c3485ffd9c07e3ce03a6da8c7dfbe0cb3dd7dc9a4774", size = 512679, upload-time = "2025-09-09T15:17:13.821Z" }, -] - [[package]] name = "trio" version = "0.32.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "attrs", marker = "python_full_version >= '3.10'" }, - { name = "cffi", marker = "python_full_version >= '3.10' and implementation_name != 'pypy' and os_name == 'nt'" }, - { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, - { name = "idna", marker = "python_full_version >= '3.10'" }, - { name = "outcome", marker = "python_full_version >= '3.10'" }, - { name = "sniffio", marker = "python_full_version >= '3.10'" }, - { name = "sortedcontainers", marker = "python_full_version >= '3.10'" }, + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d8/ce/0041ddd9160aac0031bcf5ab786c7640d795c797e67c438e15cfedf815c8/trio-0.32.0.tar.gz", hash = "sha256:150f29ec923bcd51231e1d4c71c7006e65247d68759dd1c19af4ea815a25806b", size = 605323, upload-time = "2025-10-31T07:18:17.466Z" } wheels = [ @@ -7040,8 +5540,7 @@ name = "typer" version = "0.21.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click" }, { name = "rich" }, { name = "shellingham" }, { name = "typing-extensions" }, @@ -7069,31 +5568,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/43/58e75bac4219cbafee83179505ff44cae3153ec279be0e30583a73b8f108/types_protobuf-6.32.1.20251210-py3-none-any.whl", hash = "sha256:2641f78f3696822a048cfb8d0ff42ccd85c25f12f871fbebe86da63793692140", size = 77921, upload-time = "2025-12-10T03:14:24.477Z" }, ] -[[package]] -name = "types-requests" -version = "2.31.0.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "types-urllib3", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f9/b8/c1e8d39996b4929b918aba10dba5de07a8b3f4c8487bb61bb79882544e69/types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0", size = 15535, upload-time = "2023-09-27T06:19:38.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/a1/6f8dc74d9069e790d604ddae70cb46dcbac668f1bb08136e7b0f2f5cd3bf/types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9", size = 14516, upload-time = "2023-09-27T06:19:36.373Z" }, -] - [[package]] name = "types-requests" version = "2.32.4.20260107" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/f3/a0663907082280664d745929205a89d41dffb29e89a50f753af7d57d0a96/types_requests-2.32.4.20260107.tar.gz", hash = "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f", size = 23165, upload-time = "2026-01-07T03:20:54.091Z" } wheels = [ @@ -7109,15 +5589,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/f2/d812543c350674d8b3f6e17c8922248ee3bb752c2a76f64beb8c538b40cf/types_ujson-5.10.0.20250822-py3-none-any.whl", hash = "sha256:3e9e73a6dc62ccc03449d9ac2c580cd1b7a8e4873220db498f7dd056754be080", size = 7657, upload-time = "2025-08-22T03:02:18.699Z" }, ] -[[package]] -name = "types-urllib3" -version = "1.26.25.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/de/b9d7a68ad39092368fb21dd6194b362b98a1daeea5dcfef5e1adb5031c7e/types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f", size = 11239, upload-time = "2023-07-20T15:19:31.307Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/7b/3fc711b2efea5e85a7a0bbfe269ea944aa767bbba5ec52f9ee45d362ccf3/types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e", size = 15377, upload-time = "2023-07-20T15:19:30.379Z" }, -] - [[package]] name = "typing-extensions" version = "4.15.0" @@ -7211,17 +5682,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/30/ed/5a057199fb0a5deabe0957073a1c1c1c02a3e99476cd03daee98ea21fa57/ujson-5.11.0-cp314-cp314t-win32.whl", hash = "sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5", size = 41859, upload-time = "2025-08-20T11:56:30.495Z" }, { url = "https://files.pythonhosted.org/packages/aa/03/b19c6176bdf1dc13ed84b886e99677a52764861b6cc023d5e7b6ebda249d/ujson-5.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec", size = 46183, upload-time = "2025-08-20T11:56:31.574Z" }, { url = "https://files.pythonhosted.org/packages/5d/ca/a0413a3874b2dc1708b8796ca895bf363292f9c70b2e8ca482b7dbc0259d/ujson-5.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab", size = 40264, upload-time = "2025-08-20T11:56:32.773Z" }, - { url = "https://files.pythonhosted.org/packages/39/bf/c6f59cdf74ce70bd937b97c31c42fd04a5ed1a9222d0197e77e4bd899841/ujson-5.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694", size = 55283, upload-time = "2025-08-20T11:56:33.947Z" }, - { url = "https://files.pythonhosted.org/packages/8d/c1/a52d55638c0c644b8a63059f95ad5ffcb4ad8f60d8bc3e8680f78e77cc75/ujson-5.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac", size = 53168, upload-time = "2025-08-20T11:56:35.141Z" }, - { url = "https://files.pythonhosted.org/packages/75/6c/e64e19a01d59c8187d01ffc752ee3792a09f5edaaac2a0402de004459dd7/ujson-5.11.0-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a", size = 57809, upload-time = "2025-08-20T11:56:36.293Z" }, - { url = "https://files.pythonhosted.org/packages/9f/36/910117b7a8a1c188396f6194ca7bc8fd75e376d8f7e3cf5eb6219fc8b09d/ujson-5.11.0-cp39-cp39-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02", size = 59797, upload-time = "2025-08-20T11:56:37.746Z" }, - { url = "https://files.pythonhosted.org/packages/c7/17/bcc85d282ee2f4cdef5f577e0a43533eedcae29cc6405edf8c62a7a50368/ujson-5.11.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c", size = 57378, upload-time = "2025-08-20T11:56:39.123Z" }, - { url = "https://files.pythonhosted.org/packages/ef/39/120bb76441bf835f3c3f42db9c206f31ba875711637a52a8209949ab04b0/ujson-5.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a", size = 1036515, upload-time = "2025-08-20T11:56:40.848Z" }, - { url = "https://files.pythonhosted.org/packages/b6/ae/fe1b4ff6388f681f6710e9494656957725b1e73ae50421ec04567df9fb75/ujson-5.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052", size = 1195753, upload-time = "2025-08-20T11:56:42.341Z" }, - { url = "https://files.pythonhosted.org/packages/92/20/005b93f2cf846ae50b46812fcf24bbdd127521197e5f1e1a82e3b3e730a1/ujson-5.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596", size = 1088844, upload-time = "2025-08-20T11:56:43.777Z" }, - { url = "https://files.pythonhosted.org/packages/41/9e/3142023c30008e2b24d7368a389b26d28d62fcd3f596d3d898a72dd09173/ujson-5.11.0-cp39-cp39-win32.whl", hash = "sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547", size = 39652, upload-time = "2025-08-20T11:56:45.034Z" }, - { url = "https://files.pythonhosted.org/packages/ca/89/f4de0a3c485d0163f85f552886251876645fb62cbbe24fcdc0874b9fae03/ujson-5.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b", size = 43783, upload-time = "2025-08-20T11:56:46.156Z" }, - { url = "https://files.pythonhosted.org/packages/48/b1/2d50987a7b7cccb5c1fbe9ae7b184211106237b32c7039118c41d79632ea/ujson-5.11.0-cp39-cp39-win_arm64.whl", hash = "sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9", size = 38430, upload-time = "2025-08-20T11:56:47.653Z" }, { url = "https://files.pythonhosted.org/packages/50/17/30275aa2933430d8c0c4ead951cc4fdb922f575a349aa0b48a6f35449e97/ujson-5.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362", size = 51206, upload-time = "2025-08-20T11:56:48.797Z" }, { url = "https://files.pythonhosted.org/packages/c3/15/42b3924258eac2551f8f33fa4e35da20a06a53857ccf3d4deb5e5d7c0b6c/ujson-5.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39", size = 48907, upload-time = "2025-08-20T11:56:50.136Z" }, { url = "https://files.pythonhosted.org/packages/94/7e/0519ff7955aba581d1fe1fb1ca0e452471250455d182f686db5ac9e46119/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc", size = 50319, upload-time = "2025-08-20T11:56:51.63Z" }, @@ -7230,71 +5690,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/5b/8c5e33228f7f83f05719964db59f3f9f276d272dc43752fa3bbf0df53e7b/ujson-5.11.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04", size = 43835, upload-time = "2025-08-20T11:56:55.237Z" }, ] -[[package]] -name = "urllib3" -version = "1.26.20" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, -] - [[package]] name = "urllib3" version = "2.6.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] -[[package]] -name = "uvicorn" -version = "0.39.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "h11", marker = "python_full_version < '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/4f/f9fdac7cf6dd79790eb165639b5c452ceeabc7bbabbba4569155470a287d/uvicorn-0.39.0.tar.gz", hash = "sha256:610512b19baa93423d2892d7823741f6d27717b642c8964000d7194dded19302", size = 82001, upload-time = "2025-12-21T13:05:17.973Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/25/db2b1c6c35bf22e17fe5412d2ee5d3fd7a20d07ebc9dac8b58f7db2e23a0/uvicorn-0.39.0-py3-none-any.whl", hash = "sha256:7beec21bd2693562b386285b188a7963b06853c0d006302b3e4cfed950c9929a", size = 68491, upload-time = "2025-12-21T13:05:16.291Z" }, -] - -[package.optional-dependencies] -standard = [ - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, - { name = "httptools", marker = "python_full_version < '3.10'" }, - { name = "python-dotenv", marker = "python_full_version < '3.10'" }, - { name = "pyyaml", marker = "python_full_version < '3.10'" }, - { name = "uvloop", marker = "python_full_version < '3.10' and platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, - { name = "watchfiles", marker = "python_full_version < '3.10'" }, - { name = "websockets", marker = "python_full_version < '3.10'" }, -] - [[package]] name = "uvicorn" version = "0.40.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.10' and python_full_version < '3.14'", -] dependencies = [ - { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "h11", marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" } wheels = [ @@ -7303,13 +5715,13 @@ wheels = [ [package.optional-dependencies] standard = [ - { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, - { name = "httptools", marker = "python_full_version >= '3.10'" }, - { name = "python-dotenv", marker = "python_full_version >= '3.10'" }, - { name = "pyyaml", marker = "python_full_version >= '3.10'" }, - { name = "uvloop", marker = "python_full_version >= '3.10' and platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, - { name = "watchfiles", marker = "python_full_version >= '3.10'" }, - { name = "websockets", marker = "python_full_version >= '3.10'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, ] [[package]] @@ -7354,12 +5766,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/37/945b4ca0ac27e3dc4952642d4c900edd030b3da6c9634875af6e13ae80e5/uvloop-0.22.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21", size = 4467065, upload-time = "2025-10-16T22:16:58.206Z" }, { url = "https://files.pythonhosted.org/packages/97/cc/48d232f33d60e2e2e0b42f4e73455b146b76ebe216487e862700457fbf3c/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88", size = 4328384, upload-time = "2025-10-16T22:16:59.36Z" }, { url = "https://files.pythonhosted.org/packages/e4/16/c1fd27e9549f3c4baf1dc9c20c456cd2f822dbf8de9f463824b0c0357e06/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e", size = 4296730, upload-time = "2025-10-16T22:17:00.744Z" }, - { url = "https://files.pythonhosted.org/packages/bd/1b/6fbd611aeba01ef802c5876c94d7be603a9710db055beacbad39e75a31aa/uvloop-0.22.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b45649628d816c030dba3c80f8e2689bab1c89518ed10d426036cdc47874dfc4", size = 1345858, upload-time = "2025-10-16T22:17:11.106Z" }, - { url = "https://files.pythonhosted.org/packages/9e/91/2c84f00bdbe3c51023cc83b027bac1fe959ba4a552e970da5ef0237f7945/uvloop-0.22.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ea721dd3203b809039fcc2983f14608dae82b212288b346e0bfe46ec2fab0b7c", size = 743913, upload-time = "2025-10-16T22:17:12.165Z" }, - { url = "https://files.pythonhosted.org/packages/cc/10/76aec83886d41a88aca5681db6a2c0601622d0d2cb66cd0d200587f962ad/uvloop-0.22.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ae676de143db2b2f60a9696d7eca5bb9d0dd6cc3ac3dad59a8ae7e95f9e1b54", size = 3635818, upload-time = "2025-10-16T22:17:13.812Z" }, - { url = "https://files.pythonhosted.org/packages/d5/9a/733fcb815d345979fc54d3cdc3eb50bc75a47da3e4003ea7ada58e6daa65/uvloop-0.22.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17d4e97258b0172dfa107b89aa1eeba3016f4b1974ce85ca3ef6a66b35cbf659", size = 3685477, upload-time = "2025-10-16T22:17:15.307Z" }, - { url = "https://files.pythonhosted.org/packages/83/fb/bee1eb11cc92bd91f76d97869bb6a816e80d59fd73721b0a3044dc703d9c/uvloop-0.22.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:05e4b5f86e621cf3927631789999e697e58f0d2d32675b67d9ca9eb0bca55743", size = 3496128, upload-time = "2025-10-16T22:17:16.558Z" }, - { url = "https://files.pythonhosted.org/packages/76/ee/3fdfeaa9776c0fd585d358c92b1dbca669720ffa476f0bbe64ed8f245bd7/uvloop-0.22.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:286322a90bea1f9422a470d5d2ad82d38080be0a29c4dd9b3e6384320a4d11e7", size = 3602565, upload-time = "2025-10-16T22:17:17.755Z" }, ] [[package]] @@ -7380,13 +5786,8 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, - { url = "https://files.pythonhosted.org/packages/05/52/7223011bb760fce8ddc53416beb65b83a3ea6d7d13738dde75eeb2c89679/watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8", size = 96390, upload-time = "2024-11-01T14:06:49.325Z" }, - { url = "https://files.pythonhosted.org/packages/9c/62/d2b21bc4e706d3a9d467561f487c2938cbd881c69f3808c43ac1ec242391/watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a", size = 88386, upload-time = "2024-11-01T14:06:50.536Z" }, - { url = "https://files.pythonhosted.org/packages/ea/22/1c90b20eda9f4132e4603a26296108728a8bfe9584b006bd05dd94548853/watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c", size = 89017, upload-time = "2024-11-01T14:06:51.717Z" }, { url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" }, { url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" }, - { url = "https://files.pythonhosted.org/packages/5b/79/69f2b0e8d3f2afd462029031baafb1b75d11bb62703f0e1022b2e54d49ee/watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa", size = 87903, upload-time = "2024-11-01T14:06:57.052Z" }, - { url = "https://files.pythonhosted.org/packages/e2/2b/dc048dd71c2e5f0f7ebc04dd7912981ec45793a03c0dc462438e0591ba5d/watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e", size = 88381, upload-time = "2024-11-01T14:06:58.193Z" }, { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, @@ -7492,18 +5893,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c", size = 455072, upload-time = "2025-10-14T15:05:48.928Z" }, { url = "https://files.pythonhosted.org/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099", size = 629104, upload-time = "2025-10-14T15:05:49.908Z" }, { url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" }, - { url = "https://files.pythonhosted.org/packages/a4/68/a7303a15cc797ab04d58f1fea7f67c50bd7f80090dfd7e750e7576e07582/watchfiles-1.1.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c882d69f6903ef6092bedfb7be973d9319940d56b8427ab9187d1ecd73438a70", size = 409220, upload-time = "2025-10-14T15:05:51.917Z" }, - { url = "https://files.pythonhosted.org/packages/99/b8/d1857ce9ac76034c053fa7ef0e0ef92d8bd031e842ea6f5171725d31e88f/watchfiles-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d6ff426a7cb54f310d51bfe83fe9f2bbe40d540c741dc974ebc30e6aa238f52e", size = 396712, upload-time = "2025-10-14T15:05:53.437Z" }, - { url = "https://files.pythonhosted.org/packages/41/7a/da7ada566f48beaa6a30b13335b49d1f6febaf3a5ddbd1d92163a1002cf4/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79ff6c6eadf2e3fc0d7786331362e6ef1e51125892c75f1004bd6b52155fb956", size = 451462, upload-time = "2025-10-14T15:05:54.742Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b2/7cb9e0d5445a8d45c4cccd68a590d9e3a453289366b96ff37d1075aaebef/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c1f5210f1b8fc91ead1283c6fd89f70e76fb07283ec738056cf34d51e9c1d62c", size = 460811, upload-time = "2025-10-14T15:05:55.743Z" }, - { url = "https://files.pythonhosted.org/packages/04/9d/b07d4491dde6db6ea6c680fdec452f4be363d65c82004faf2d853f59b76f/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9c4702f29ca48e023ffd9b7ff6b822acdf47cb1ff44cb490a3f1d5ec8987e9c", size = 490576, upload-time = "2025-10-14T15:05:56.983Z" }, - { url = "https://files.pythonhosted.org/packages/56/03/e64dcab0a1806157db272a61b7891b062f441a30580a581ae72114259472/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acb08650863767cbc58bca4813b92df4d6c648459dcaa3d4155681962b2aa2d3", size = 597726, upload-time = "2025-10-14T15:05:57.986Z" }, - { url = "https://files.pythonhosted.org/packages/5c/8e/a827cf4a8d5f2903a19a934dcf512082eb07675253e154d4cd9367978a58/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08af70fd77eee58549cd69c25055dc344f918d992ff626068242259f98d598a2", size = 474900, upload-time = "2025-10-14T15:05:59.378Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/94fed0b346b85b22303a12eee5f431006fae6af70d841cac2f4403245533/watchfiles-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c3631058c37e4a0ec440bf583bc53cdbd13e5661bb6f465bc1d88ee9a0a4d02", size = 457521, upload-time = "2025-10-14T15:06:00.419Z" }, - { url = "https://files.pythonhosted.org/packages/c4/64/bc3331150e8f3c778d48a4615d4b72b3d2d87868635e6c54bbd924946189/watchfiles-1.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cf57a27fb986c6243d2ee78392c503826056ffe0287e8794503b10fb51b881be", size = 632191, upload-time = "2025-10-14T15:06:01.621Z" }, - { url = "https://files.pythonhosted.org/packages/e4/84/f39e19549c2f3ec97225dcb2ceb9a7bb3c5004ed227aad1f321bf0ff2051/watchfiles-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d7e7067c98040d646982daa1f37a33d3544138ea155536c2e0e63e07ff8a7e0f", size = 623923, upload-time = "2025-10-14T15:06:02.671Z" }, - { url = "https://files.pythonhosted.org/packages/0e/24/0759ae15d9a0c9c5fe946bd4cf45ab9e7bad7cfede2c06dc10f59171b29f/watchfiles-1.1.1-cp39-cp39-win32.whl", hash = "sha256:6c9c9262f454d1c4d8aaa7050121eb4f3aea197360553699520767daebf2180b", size = 274010, upload-time = "2025-10-14T15:06:03.779Z" }, - { url = "https://files.pythonhosted.org/packages/7e/3b/eb26cddd4dfa081e2bf6918be3b2fc05ee3b55c1d21331d5562ee0c6aaad/watchfiles-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:74472234c8370669850e1c312490f6026d132ca2d396abfad8830b4f1c096957", size = 289090, upload-time = "2025-10-14T15:06:04.821Z" }, { url = "https://files.pythonhosted.org/packages/ba/4c/a888c91e2e326872fa4705095d64acd8aa2fb9c1f7b9bd0588f33850516c/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:17ef139237dfced9da49fb7f2232c86ca9421f666d78c264c7ffca6601d154c3", size = 409611, upload-time = "2025-10-14T15:06:05.809Z" }, { url = "https://files.pythonhosted.org/packages/1e/c7/5420d1943c8e3ce1a21c0a9330bcf7edafb6aa65d26b21dbb3267c9e8112/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:672b8adf25b1a0d35c96b5888b7b18699d27d4194bac8beeae75be4b7a3fc9b2", size = 396889, upload-time = "2025-10-14T15:06:07.035Z" }, { url = "https://files.pythonhosted.org/packages/0c/e5/0072cef3804ce8d3aaddbfe7788aadff6b3d3f98a286fdbee9fd74ca59a7/watchfiles-1.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a13aea58bc2b90173bc69f2a90de8e282648939a00a602e1dc4ee23e26b66d", size = 451616, upload-time = "2025-10-14T15:06:08.072Z" }, @@ -7512,10 +5901,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336", size = 396117, upload-time = "2025-10-14T15:06:11.28Z" }, { url = "https://files.pythonhosted.org/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24", size = 450493, upload-time = "2025-10-14T15:06:12.321Z" }, { url = "https://files.pythonhosted.org/packages/6e/d4/ed38dd3b1767193de971e694aa544356e63353c33a85d948166b5ff58b9e/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e6f39af2eab0118338902798b5aa6664f46ff66bc0280de76fca67a7f262a49", size = 457546, upload-time = "2025-10-14T15:06:13.372Z" }, - { url = "https://files.pythonhosted.org/packages/00/db/38a2c52fdbbfe2fc7ffaaaaaebc927d52b9f4d5139bba3186c19a7463001/watchfiles-1.1.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdab464fee731e0884c35ae3588514a9bcf718d0e2c82169c1c4a85cc19c3c7f", size = 409210, upload-time = "2025-10-14T15:06:14.492Z" }, - { url = "https://files.pythonhosted.org/packages/d1/43/d7e8b71f6c21ff813ee8da1006f89b6c7fff047fb4c8b16ceb5e840599c5/watchfiles-1.1.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3dbd8cbadd46984f802f6d479b7e3afa86c42d13e8f0f322d669d79722c8ec34", size = 397286, upload-time = "2025-10-14T15:06:16.177Z" }, - { url = "https://files.pythonhosted.org/packages/1f/5d/884074a5269317e75bd0b915644b702b89de73e61a8a7446e2b225f45b1f/watchfiles-1.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5524298e3827105b61951a29c3512deb9578586abf3a7c5da4a8069df247cccc", size = 451768, upload-time = "2025-10-14T15:06:18.266Z" }, - { url = "https://files.pythonhosted.org/packages/17/71/7ffcaa9b5e8961a25026058058c62ec8f604d2a6e8e1e94bee8a09e1593f/watchfiles-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b943d3668d61cfa528eb949577479d3b077fd25fb83c641235437bc0b5bc60e", size = 458561, upload-time = "2025-10-14T15:06:19.323Z" }, ] [[package]] @@ -7586,29 +5971,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, - { url = "https://files.pythonhosted.org/packages/36/db/3fff0bcbe339a6fa6a3b9e3fbc2bfb321ec2f4cd233692272c5a8d6cf801/websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5", size = 175424, upload-time = "2025-03-05T20:02:56.505Z" }, - { url = "https://files.pythonhosted.org/packages/46/e6/519054c2f477def4165b0ec060ad664ed174e140b0d1cbb9fafa4a54f6db/websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a", size = 173077, upload-time = "2025-03-05T20:02:58.37Z" }, - { url = "https://files.pythonhosted.org/packages/1a/21/c0712e382df64c93a0d16449ecbf87b647163485ca1cc3f6cbadb36d2b03/websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b", size = 173324, upload-time = "2025-03-05T20:02:59.773Z" }, - { url = "https://files.pythonhosted.org/packages/1c/cb/51ba82e59b3a664df54beed8ad95517c1b4dc1a913730e7a7db778f21291/websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770", size = 182094, upload-time = "2025-03-05T20:03:01.827Z" }, - { url = "https://files.pythonhosted.org/packages/fb/0f/bf3788c03fec679bcdaef787518dbe60d12fe5615a544a6d4cf82f045193/websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb", size = 181094, upload-time = "2025-03-05T20:03:03.123Z" }, - { url = "https://files.pythonhosted.org/packages/5e/da/9fb8c21edbc719b66763a571afbaf206cb6d3736d28255a46fc2fe20f902/websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054", size = 181397, upload-time = "2025-03-05T20:03:04.443Z" }, - { url = "https://files.pythonhosted.org/packages/2e/65/65f379525a2719e91d9d90c38fe8b8bc62bd3c702ac651b7278609b696c4/websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee", size = 181794, upload-time = "2025-03-05T20:03:06.708Z" }, - { url = "https://files.pythonhosted.org/packages/d9/26/31ac2d08f8e9304d81a1a7ed2851c0300f636019a57cbaa91342015c72cc/websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed", size = 181194, upload-time = "2025-03-05T20:03:08.844Z" }, - { url = "https://files.pythonhosted.org/packages/98/72/1090de20d6c91994cd4b357c3f75a4f25ee231b63e03adea89671cc12a3f/websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880", size = 181164, upload-time = "2025-03-05T20:03:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/2d/37/098f2e1c103ae8ed79b0e77f08d83b0ec0b241cf4b7f2f10edd0126472e1/websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411", size = 176381, upload-time = "2025-03-05T20:03:12.77Z" }, - { url = "https://files.pythonhosted.org/packages/75/8b/a32978a3ab42cebb2ebdd5b05df0696a09f4d436ce69def11893afa301f0/websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4", size = 176841, upload-time = "2025-03-05T20:03:14.367Z" }, { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, - { url = "https://files.pythonhosted.org/packages/b7/48/4b67623bac4d79beb3a6bb27b803ba75c1bdedc06bd827e465803690a4b2/websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940", size = 173106, upload-time = "2025-03-05T20:03:29.404Z" }, - { url = "https://files.pythonhosted.org/packages/ed/f0/adb07514a49fe5728192764e04295be78859e4a537ab8fcc518a3dbb3281/websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e", size = 173339, upload-time = "2025-03-05T20:03:30.755Z" }, - { url = "https://files.pythonhosted.org/packages/87/28/bd23c6344b18fb43df40d0700f6d3fffcd7cef14a6995b4f976978b52e62/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9", size = 174597, upload-time = "2025-03-05T20:03:32.247Z" }, - { url = "https://files.pythonhosted.org/packages/6d/79/ca288495863d0f23a60f546f0905ae8f3ed467ad87f8b6aceb65f4c013e4/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b", size = 174205, upload-time = "2025-03-05T20:03:33.731Z" }, - { url = "https://files.pythonhosted.org/packages/04/e4/120ff3180b0872b1fe6637f6f995bcb009fb5c87d597c1fc21456f50c848/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f", size = 174150, upload-time = "2025-03-05T20:03:35.757Z" }, - { url = "https://files.pythonhosted.org/packages/cb/c3/30e2f9c539b8da8b1d76f64012f3b19253271a63413b2d3adb94b143407f/websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123", size = 176877, upload-time = "2025-03-05T20:03:37.199Z" }, { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] @@ -7690,16 +6058,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, - { url = "https://files.pythonhosted.org/packages/41/be/be9b3b0a461ee3e30278706f3f3759b9b69afeedef7fe686036286c04ac6/wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc", size = 53485, upload-time = "2025-08-12T05:51:53.11Z" }, - { url = "https://files.pythonhosted.org/packages/b3/a8/8f61d6b8f526efc8c10e12bf80b4206099fea78ade70427846a37bc9cbea/wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9", size = 38675, upload-time = "2025-08-12T05:51:42.885Z" }, - { url = "https://files.pythonhosted.org/packages/48/f1/23950c29a25637b74b322f9e425a17cc01a478f6afb35138ecb697f9558d/wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d", size = 38956, upload-time = "2025-08-12T05:52:03.149Z" }, - { url = "https://files.pythonhosted.org/packages/43/46/dd0791943613885f62619f18ee6107e6133237a6b6ed8a9ecfac339d0b4f/wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a", size = 81745, upload-time = "2025-08-12T05:52:49.62Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ec/bb2d19bd1a614cc4f438abac13ae26c57186197920432d2a915183b15a8b/wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139", size = 82833, upload-time = "2025-08-12T05:52:27.738Z" }, - { url = "https://files.pythonhosted.org/packages/8d/eb/66579aea6ad36f07617fedca8e282e49c7c9bab64c63b446cfe4f7f47a49/wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df", size = 81889, upload-time = "2025-08-12T05:52:29.023Z" }, - { url = "https://files.pythonhosted.org/packages/04/9c/a56b5ac0e2473bdc3fb11b22dd69ff423154d63861cf77911cdde5e38fd2/wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b", size = 81344, upload-time = "2025-08-12T05:52:50.869Z" }, - { url = "https://files.pythonhosted.org/packages/93/4c/9bd735c42641d81cb58d7bfb142c58f95c833962d15113026705add41a07/wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81", size = 36462, upload-time = "2025-08-12T05:53:19.623Z" }, - { url = "https://files.pythonhosted.org/packages/f0/ea/0b72f29cb5ebc16eb55c57dc0c98e5de76fc97f435fd407f7d409459c0a6/wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f", size = 38740, upload-time = "2025-08-12T05:53:18.271Z" }, - { url = "https://files.pythonhosted.org/packages/c3/8b/9eae65fb92321e38dbfec7719b87d840a4b92fde83fd1bbf238c5488d055/wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f", size = 36806, upload-time = "2025-08-12T05:52:58.765Z" }, { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, ] @@ -7708,14 +6066,14 @@ name = "xai-sdk" version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aiohttp", marker = "python_full_version >= '3.10'" }, - { name = "googleapis-common-protos", marker = "python_full_version >= '3.10'" }, - { name = "grpcio", marker = "python_full_version >= '3.10'" }, - { name = "opentelemetry-sdk", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "protobuf", version = "6.33.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "pydantic", marker = "python_full_version >= '3.10'" }, - { name = "requests", marker = "python_full_version >= '3.10'" }, + { name = "aiohttp" }, + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-sdk" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "pydantic" }, + { name = "requests" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9e/66/1e0163eac090733d0ed0836a0cd3c14f5b59abeaa6fdba71c7b56b1916e4/xai_sdk-1.6.1.tar.gz", hash = "sha256:b55528df188f8c8448484021d735f75b0e7d71719ddeb432c5f187ac67e3c983", size = 388223, upload-time = "2026-01-29T03:13:07.373Z" } wheels = [ @@ -7845,22 +6203,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, - { url = "https://files.pythonhosted.org/packages/94/fd/6480106702a79bcceda5fd9c63cb19a04a6506bd5ce7fd8d9b63742f0021/yarl-1.22.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748", size = 141301, upload-time = "2025-10-06T14:12:19.01Z" }, - { url = "https://files.pythonhosted.org/packages/42/e1/6d95d21b17a93e793e4ec420a925fe1f6a9342338ca7a563ed21129c0990/yarl-1.22.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859", size = 93864, upload-time = "2025-10-06T14:12:21.05Z" }, - { url = "https://files.pythonhosted.org/packages/32/58/b8055273c203968e89808413ea4c984988b6649baabf10f4522e67c22d2f/yarl-1.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9", size = 94706, upload-time = "2025-10-06T14:12:23.287Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/d7bfbc28a88c2895ecd0da6a874def0c147de78afc52c773c28e1aa233a3/yarl-1.22.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054", size = 347100, upload-time = "2025-10-06T14:12:28.527Z" }, - { url = "https://files.pythonhosted.org/packages/bd/e8/37a1e7b99721c0564b1fc7b0a4d1f595ef6fb8060d82ca61775b644185f7/yarl-1.22.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b", size = 318902, upload-time = "2025-10-06T14:12:30.528Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ef/34724449d7ef2db4f22df644f2dac0b8a275d20f585e526937b3ae47b02d/yarl-1.22.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60", size = 363302, upload-time = "2025-10-06T14:12:32.295Z" }, - { url = "https://files.pythonhosted.org/packages/8a/04/88a39a5dad39889f192cce8d66cc4c58dbeca983e83f9b6bf23822a7ed91/yarl-1.22.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890", size = 370816, upload-time = "2025-10-06T14:12:34.01Z" }, - { url = "https://files.pythonhosted.org/packages/6b/1f/5e895e547129413f56c76be2c3ce4b96c797d2d0ff3e16a817d9269b12e6/yarl-1.22.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba", size = 346465, upload-time = "2025-10-06T14:12:35.977Z" }, - { url = "https://files.pythonhosted.org/packages/11/13/a750e9fd6f9cc9ed3a52a70fe58ffe505322f0efe0d48e1fd9ffe53281f5/yarl-1.22.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca", size = 341506, upload-time = "2025-10-06T14:12:37.788Z" }, - { url = "https://files.pythonhosted.org/packages/3c/67/bb6024de76e7186611ebe626aec5b71a2d2ecf9453e795f2dbd80614784c/yarl-1.22.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba", size = 335030, upload-time = "2025-10-06T14:12:39.775Z" }, - { url = "https://files.pythonhosted.org/packages/a2/be/50b38447fd94a7992996a62b8b463d0579323fcfc08c61bdba949eef8a5d/yarl-1.22.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b", size = 358560, upload-time = "2025-10-06T14:12:41.547Z" }, - { url = "https://files.pythonhosted.org/packages/e2/89/c020b6f547578c4e3dbb6335bf918f26e2f34ad0d1e515d72fd33ac0c635/yarl-1.22.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e", size = 357290, upload-time = "2025-10-06T14:12:43.861Z" }, - { url = "https://files.pythonhosted.org/packages/8c/52/c49a619ee35a402fa3a7019a4fa8d26878fec0d1243f6968bbf516789578/yarl-1.22.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8", size = 350700, upload-time = "2025-10-06T14:12:46.868Z" }, - { url = "https://files.pythonhosted.org/packages/ab/c9/f5042d87777bf6968435f04a2bbb15466b2f142e6e47fa4f34d1a3f32f0c/yarl-1.22.0-cp39-cp39-win32.whl", hash = "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b", size = 82323, upload-time = "2025-10-06T14:12:48.633Z" }, - { url = "https://files.pythonhosted.org/packages/fd/58/d00f7cad9eba20c4eefac2682f34661d1d1b3a942fc0092eb60e78cfb733/yarl-1.22.0-cp39-cp39-win_amd64.whl", hash = "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed", size = 87145, upload-time = "2025-10-06T14:12:50.241Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a3/70904f365080780d38b919edd42d224b8c4ce224a86950d2eaa2a24366ad/yarl-1.22.0-cp39-cp39-win_arm64.whl", hash = "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2", size = 82173, upload-time = "2025-10-06T14:12:51.869Z" }, { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, ] From cc903bd440a4a443510c7b10ef7e9a1f88f44e0e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Feb 2026 18:32:39 +0000 Subject: [PATCH 205/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index be11b78276..e0ca3de72e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Breaking Changes + +* โž– Drop support for Python 3.9. PR [#14897](https://github.com/fastapi/fastapi/pull/14897) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.8 ### Docs From 3da206c06df1283518a54b18f27bed33f2d22612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 11 Feb 2026 10:41:21 -0800 Subject: [PATCH 206/367] =?UTF-8?q?=F0=9F=8E=A8=20Update=20internal=20type?= =?UTF-8?q?s=20for=20Python=203.10=20(#14898)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/v2.py | 26 +- fastapi/applications.py | 354 +++++++++---------- fastapi/background.py | 3 +- fastapi/datastructures.py | 10 +- fastapi/dependencies/models.py | 32 +- fastapi/encoders.py | 13 +- fastapi/exceptions.py | 14 +- fastapi/openapi/docs.py | 8 +- fastapi/openapi/models.py | 326 ++++++++--------- fastapi/openapi/utils.py | 31 +- fastapi/param_functions.py | 380 ++++++++++---------- fastapi/params.py | 446 ++++++++++++------------ fastapi/routing.py | 412 +++++++++++----------- fastapi/security/api_key.py | 26 +- fastapi/security/http.py | 36 +- fastapi/security/oauth2.py | 42 +-- fastapi/security/open_id_connect_url.py | 8 +- fastapi/security/utils.py | 5 +- fastapi/types.py | 7 +- fastapi/utils.py | 18 +- 20 files changed, 1087 insertions(+), 1110 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 87b9fb47fa..b83bc1b55b 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -8,8 +8,11 @@ from functools import lru_cache from typing import ( Annotated, Any, + Literal, Union, cast, + get_args, + get_origin, ) from fastapi._compat import lenient_issubclass, shared @@ -32,7 +35,6 @@ from pydantic_core import Url as Url from pydantic_core.core_schema import ( with_info_plain_validator_function as with_info_plain_validator_function, ) -from typing_extensions import Literal, get_args, get_origin RequiredParam = PydanticUndefined Undefined = PydanticUndefined @@ -83,7 +85,7 @@ class ModelField: field_info: FieldInfo name: str mode: Literal["validation", "serialization"] = "validation" - config: Union[ConfigDict, None] = None + config: ConfigDict | None = None @property def alias(self) -> str: @@ -91,14 +93,14 @@ class ModelField: return a if a is not None else self.name @property - def validation_alias(self) -> Union[str, None]: + def validation_alias(self) -> str | None: va = self.field_info.validation_alias if isinstance(va, str) and va: return va return None @property - def serialization_alias(self) -> Union[str, None]: + def serialization_alias(self) -> str | None: sa = self.field_info.serialization_alias return sa or None @@ -143,7 +145,7 @@ class ModelField: value: Any, values: dict[str, Any] = {}, # noqa: B006 *, - loc: tuple[Union[int, str], ...] = (), + loc: tuple[int | str, ...] = (), ) -> tuple[Any, list[dict[str, Any]]]: try: return ( @@ -160,8 +162,8 @@ class ModelField: value: Any, *, mode: Literal["json", "python"] = "json", - include: Union[IncEx, None] = None, - exclude: Union[IncEx, None] = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = True, exclude_unset: bool = False, exclude_defaults: bool = False, @@ -202,7 +204,7 @@ def get_schema_from_model_field( ], separate_input_output_schemas: bool = True, ) -> dict[str, Any]: - override_mode: Union[Literal["validation"], None] = ( + override_mode: Literal["validation"] | None = ( None if (separate_input_output_schemas or _has_computed_fields(field)) else "validation" @@ -318,7 +320,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index] -def get_missing_field_error(loc: tuple[Union[int, str], ...]) -> dict[str, Any]: +def get_missing_field_error(loc: tuple[int | str, ...]) -> dict[str, Any]: error = ValidationError.from_exception_data( "Field required", [{"type": "missing", "loc": loc, "input": {}}] ).errors(include_url=False)[0] @@ -360,7 +362,7 @@ def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]: # Duplicate of several schema functions from Pydantic v1 to make them compatible with # Pydantic v2 and allow mixing the models -TypeModelOrEnum = Union[type["BaseModel"], type[Enum]] +TypeModelOrEnum = type["BaseModel"] | type[Enum] TypeModelSet = set[TypeModelOrEnum] @@ -377,7 +379,7 @@ def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str def get_flat_models_from_model( - model: type["BaseModel"], known_models: Union[TypeModelSet, None] = None + model: type["BaseModel"], known_models: TypeModelSet | None = None ) -> TypeModelSet: known_models = known_models or set() fields = get_model_fields(model) @@ -426,7 +428,7 @@ def get_flat_models_from_fields( def _regenerate_error_with_loc( - *, errors: Sequence[Any], loc_prefix: tuple[Union[str, int], ...] + *, errors: Sequence[Any], loc_prefix: tuple[str | int, ...] ) -> list[dict[str, Any]]: updated_loc_errors: list[Any] = [ {**err, "loc": loc_prefix + err.get("loc", ())} for err in errors diff --git a/fastapi/applications.py b/fastapi/applications.py index 340cabfc29..41d86143ec 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1,12 +1,9 @@ -from collections.abc import Awaitable, Coroutine, Sequence +from collections.abc import Awaitable, Callable, Coroutine, Sequence from enum import Enum from typing import ( Annotated, Any, - Callable, - Optional, TypeVar, - Union, ) from annotated_doc import Doc @@ -77,7 +74,7 @@ class FastAPI(Starlette): ), ] = False, routes: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ **Note**: you probably shouldn't use this parameter, it is inherited @@ -120,7 +117,7 @@ class FastAPI(Starlette): ), ] = "FastAPI", summary: Annotated[ - Optional[str], + str | None, Doc( """ A short summary of the API. @@ -203,7 +200,7 @@ class FastAPI(Starlette): ), ] = "0.1.0", openapi_url: Annotated[ - Optional[str], + str | None, Doc( """ The URL where the OpenAPI schema will be served from. @@ -226,7 +223,7 @@ class FastAPI(Starlette): ), ] = "/openapi.json", openapi_tags: Annotated[ - Optional[list[dict[str, Any]]], + list[dict[str, Any]] | None, Doc( """ A list of tags used by OpenAPI, these are the same `tags` you can set @@ -286,7 +283,7 @@ class FastAPI(Starlette): ), ] = None, servers: Annotated[ - Optional[list[dict[str, Union[str, Any]]]], + list[dict[str, str | Any]] | None, Doc( """ A `list` of `dict`s with connectivity information to a target server. @@ -335,7 +332,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of global dependencies, they will be applied to each @@ -402,7 +399,7 @@ class FastAPI(Starlette): ), ] = True, docs_url: Annotated[ - Optional[str], + str | None, Doc( """ The path to the automatic interactive API documentation. @@ -426,7 +423,7 @@ class FastAPI(Starlette): ), ] = "/docs", redoc_url: Annotated[ - Optional[str], + str | None, Doc( """ The path to the alternative automatic interactive API documentation @@ -450,7 +447,7 @@ class FastAPI(Starlette): ), ] = "/redoc", swagger_ui_oauth2_redirect_url: Annotated[ - Optional[str], + str | None, Doc( """ The OAuth2 redirect endpoint for the Swagger UI. @@ -463,7 +460,7 @@ class FastAPI(Starlette): ), ] = "/docs/oauth2-redirect", swagger_ui_init_oauth: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ OAuth2 configuration for the Swagger UI, by default shown at `/docs`. @@ -474,7 +471,7 @@ class FastAPI(Starlette): ), ] = None, middleware: Annotated[ - Optional[Sequence[Middleware]], + Sequence[Middleware] | None, Doc( """ List of middleware to be added when creating the application. @@ -488,12 +485,11 @@ class FastAPI(Starlette): ), ] = None, exception_handlers: Annotated[ - Optional[ - dict[ - Union[int, type[Exception]], - Callable[[Request, Any], Coroutine[Any, Any, Response]], - ] - ], + dict[ + int | type[Exception], + Callable[[Request, Any], Coroutine[Any, Any, Response]], + ] + | None, Doc( """ A dictionary with handlers for exceptions. @@ -507,7 +503,7 @@ class FastAPI(Starlette): ), ] = None, on_startup: Annotated[ - Optional[Sequence[Callable[[], Any]]], + Sequence[Callable[[], Any]] | None, Doc( """ A list of startup event handler functions. @@ -519,7 +515,7 @@ class FastAPI(Starlette): ), ] = None, on_shutdown: Annotated[ - Optional[Sequence[Callable[[], Any]]], + Sequence[Callable[[], Any]] | None, Doc( """ A list of shutdown event handler functions. @@ -532,7 +528,7 @@ class FastAPI(Starlette): ), ] = None, lifespan: Annotated[ - Optional[Lifespan[AppType]], + Lifespan[AppType] | None, Doc( """ A `Lifespan` context manager handler. This replaces `startup` and @@ -544,7 +540,7 @@ class FastAPI(Starlette): ), ] = None, terms_of_service: Annotated[ - Optional[str], + str | None, Doc( """ A URL to the Terms of Service for your API. @@ -563,7 +559,7 @@ class FastAPI(Starlette): ), ] = None, contact: Annotated[ - Optional[dict[str, Union[str, Any]]], + dict[str, str | Any] | None, Doc( """ A dictionary with the contact information for the exposed API. @@ -596,7 +592,7 @@ class FastAPI(Starlette): ), ] = None, license_info: Annotated[ - Optional[dict[str, Union[str, Any]]], + dict[str, str | Any] | None, Doc( """ A dictionary with the license information for the exposed API. @@ -685,7 +681,7 @@ class FastAPI(Starlette): ), ] = True, responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses to be shown in OpenAPI. @@ -701,7 +697,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ OpenAPI callbacks that should apply to all *path operations*. @@ -714,7 +710,7 @@ class FastAPI(Starlette): ), ] = None, webhooks: Annotated[ - Optional[routing.APIRouter], + routing.APIRouter | None, Doc( """ Add OpenAPI webhooks. This is similar to `callbacks` but it doesn't @@ -730,7 +726,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark all *path operations* as deprecated. You probably don't need it, @@ -758,7 +754,7 @@ class FastAPI(Starlette): ), ] = True, swagger_ui_parameters: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Parameters to configure Swagger UI, the autogenerated interactive API @@ -819,7 +815,7 @@ class FastAPI(Starlette): ), ] = True, openapi_external_docs: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ This field allows you to provide additional external documentation links. @@ -905,7 +901,7 @@ class FastAPI(Starlette): """ ), ] = "3.1.0" - self.openapi_schema: Optional[dict[str, Any]] = None + self.openapi_schema: dict[str, Any] | None = None if self.openapi_url: assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" @@ -980,7 +976,7 @@ class FastAPI(Starlette): generate_unique_id_function=generate_unique_id_function, ) self.exception_handlers: dict[ - Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]] + Any, Callable[[Request, Any], Response | Awaitable[Response]] ] = {} if exception_handlers is None else dict(exception_handlers) self.exception_handlers.setdefault(HTTPException, http_exception_handler) self.exception_handlers.setdefault( @@ -995,7 +991,7 @@ class FastAPI(Starlette): self.user_middleware: list[Middleware] = ( [] if middleware is None else list(middleware) ) - self.middleware_stack: Union[ASGIApp, None] = None + self.middleware_stack: ASGIApp | None = None self.setup() def build_middleware_stack(self) -> ASGIApp: @@ -1143,28 +1139,26 @@ class FastAPI(Starlette): endpoint: Callable[..., Any], *, response_model: Any = Default(None), - status_code: Optional[int] = None, - tags: Optional[list[Union[str, Enum]]] = None, - dependencies: Optional[Sequence[Depends]] = None, - summary: Optional[str] = None, - description: Optional[str] = None, + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[Depends] | None = None, + summary: str | None = None, + description: str | None = None, response_description: str = "Successful Response", - responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, - deprecated: Optional[bool] = None, - methods: Optional[list[str]] = None, - operation_id: Optional[str] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + methods: list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, - response_class: Union[type[Response], DefaultPlaceholder] = Default( - JSONResponse - ), - name: Optional[str] = None, - openapi_extra: Optional[dict[str, Any]] = None, + response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), + name: str | None = None, + openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( generate_unique_id ), @@ -1201,26 +1195,26 @@ class FastAPI(Starlette): path: str, *, response_model: Any = Default(None), - status_code: Optional[int] = None, - tags: Optional[list[Union[str, Enum]]] = None, - dependencies: Optional[Sequence[Depends]] = None, - summary: Optional[str] = None, - description: Optional[str] = None, + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[Depends] | None = None, + summary: str | None = None, + description: str | None = None, response_description: str = "Successful Response", - responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, - deprecated: Optional[bool] = None, - methods: Optional[list[str]] = None, - operation_id: Optional[str] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + methods: list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, response_class: type[Response] = Default(JSONResponse), - name: Optional[str] = None, - openapi_extra: Optional[dict[str, Any]] = None, + name: str | None = None, + openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( generate_unique_id ), @@ -1260,9 +1254,9 @@ class FastAPI(Starlette): self, path: str, endpoint: Callable[..., Any], - name: Optional[str] = None, + name: str | None = None, *, - dependencies: Optional[Sequence[Depends]] = None, + dependencies: Sequence[Depends] | None = None, ) -> None: self.router.add_api_websocket_route( path, @@ -1282,7 +1276,7 @@ class FastAPI(Starlette): ), ], name: Annotated[ - Optional[str], + str | None, Doc( """ A name for the WebSocket. Only used internally. @@ -1291,7 +1285,7 @@ class FastAPI(Starlette): ] = None, *, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be used for this @@ -1342,7 +1336,7 @@ class FastAPI(Starlette): *, prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to all the *path operations* in this @@ -1356,7 +1350,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to all the @@ -1384,7 +1378,7 @@ class FastAPI(Starlette): ), ] = None, responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses to be shown in OpenAPI. @@ -1400,7 +1394,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark all the *path operations* in this router as deprecated. @@ -1479,7 +1473,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -1589,7 +1583,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -1602,7 +1596,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -1615,7 +1609,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -1627,7 +1621,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -1640,7 +1634,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -1668,7 +1662,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -1678,7 +1672,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -1688,7 +1682,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -1708,7 +1702,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -1720,7 +1714,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -1822,7 +1816,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -1830,7 +1824,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -1846,7 +1840,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -1962,7 +1956,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -1975,7 +1969,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -1988,7 +1982,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -2000,7 +1994,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -2013,7 +2007,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2041,7 +2035,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2051,7 +2045,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2061,7 +2055,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2081,7 +2075,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2093,7 +2087,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2195,7 +2189,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2203,7 +2197,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2219,7 +2213,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -2340,7 +2334,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -2353,7 +2347,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -2366,7 +2360,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -2378,7 +2372,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -2391,7 +2385,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2419,7 +2413,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2429,7 +2423,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2439,7 +2433,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2459,7 +2453,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2471,7 +2465,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2573,7 +2567,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2581,7 +2575,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2597,7 +2591,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -2718,7 +2712,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -2731,7 +2725,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -2744,7 +2738,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -2756,7 +2750,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -2769,7 +2763,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2797,7 +2791,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2807,7 +2801,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2817,7 +2811,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2837,7 +2831,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2849,7 +2843,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2951,7 +2945,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2959,7 +2953,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2975,7 +2969,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3091,7 +3085,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3104,7 +3098,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3117,7 +3111,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3129,7 +3123,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3142,7 +3136,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3170,7 +3164,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3180,7 +3174,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3190,7 +3184,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3210,7 +3204,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3222,7 +3216,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -3324,7 +3318,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -3332,7 +3326,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -3348,7 +3342,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3464,7 +3458,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3477,7 +3471,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3490,7 +3484,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3502,7 +3496,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3515,7 +3509,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3543,7 +3537,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3553,7 +3547,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3563,7 +3557,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3583,7 +3577,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3595,7 +3589,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -3697,7 +3691,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -3705,7 +3699,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -3721,7 +3715,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3837,7 +3831,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3850,7 +3844,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3863,7 +3857,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3875,7 +3869,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3888,7 +3882,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3916,7 +3910,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3926,7 +3920,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3936,7 +3930,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3956,7 +3950,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3968,7 +3962,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -4070,7 +4064,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -4078,7 +4072,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -4094,7 +4088,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -4215,7 +4209,7 @@ class FastAPI(Starlette): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -4228,7 +4222,7 @@ class FastAPI(Starlette): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -4241,7 +4235,7 @@ class FastAPI(Starlette): ), ] = None, dependencies: Annotated[ - Optional[Sequence[Depends]], + Sequence[Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -4253,7 +4247,7 @@ class FastAPI(Starlette): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -4266,7 +4260,7 @@ class FastAPI(Starlette): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -4294,7 +4288,7 @@ class FastAPI(Starlette): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -4304,7 +4298,7 @@ class FastAPI(Starlette): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -4314,7 +4308,7 @@ class FastAPI(Starlette): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -4334,7 +4328,7 @@ class FastAPI(Starlette): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -4346,7 +4340,7 @@ class FastAPI(Starlette): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -4448,7 +4442,7 @@ class FastAPI(Starlette): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -4456,7 +4450,7 @@ class FastAPI(Starlette): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -4472,7 +4466,7 @@ class FastAPI(Starlette): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -4541,7 +4535,7 @@ class FastAPI(Starlette): ) def websocket_route( - self, path: str, name: Union[str, None] = None + self, path: str, name: str | None = None ) -> Callable[[DecoratedCallable], DecoratedCallable]: def decorator(func: DecoratedCallable) -> DecoratedCallable: self.router.add_websocket_route(path, func, name=name) @@ -4627,7 +4621,7 @@ class FastAPI(Starlette): def exception_handler( self, exc_class_or_status_code: Annotated[ - Union[int, type[Exception]], + int | type[Exception], Doc( """ The Exception class this would handle, or a status code. diff --git a/fastapi/background.py b/fastapi/background.py index 20803ba670..7677058c43 100644 --- a/fastapi/background.py +++ b/fastapi/background.py @@ -1,4 +1,5 @@ -from typing import Annotated, Any, Callable +from collections.abc import Callable +from typing import Annotated, Any from annotated_doc import Doc from starlette.background import BackgroundTasks as StarletteBackgroundTasks diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py index 2bf5fdb262..c04b5f0f39 100644 --- a/fastapi/datastructures.py +++ b/fastapi/datastructures.py @@ -1,10 +1,8 @@ -from collections.abc import Mapping +from collections.abc import Callable, Mapping from typing import ( Annotated, Any, BinaryIO, - Callable, - Optional, TypeVar, cast, ) @@ -58,11 +56,11 @@ class UploadFile(StarletteUploadFile): BinaryIO, Doc("The standard Python file object (non-async)."), ] - filename: Annotated[Optional[str], Doc("The original file name.")] - size: Annotated[Optional[int], Doc("The size of the file in bytes.")] + filename: Annotated[str | None, Doc("The original file name.")] + size: Annotated[int | None, Doc("The size of the file in bytes.")] headers: Annotated[Headers, Doc("The headers of the request.")] content_type: Annotated[ - Optional[str], Doc("The content type of the request, from the headers.") + str | None, Doc("The content type of the request, from the headers.") ] async def write( diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py index 58392326d6..25ffb0d2da 100644 --- a/fastapi/dependencies/models.py +++ b/fastapi/dependencies/models.py @@ -1,13 +1,13 @@ import inspect import sys +from collections.abc import Callable from dataclasses import dataclass, field from functools import cached_property, partial -from typing import Any, Callable, Optional, Union +from typing import Any, Literal from fastapi._compat import ModelField from fastapi.security.base import SecurityBase from fastapi.types import DependencyCacheKey -from typing_extensions import Literal if sys.version_info >= (3, 13): # pragma: no cover from inspect import iscoroutinefunction @@ -15,7 +15,7 @@ else: # pragma: no cover from asyncio import iscoroutinefunction -def _unwrapped_call(call: Optional[Callable[..., Any]]) -> Any: +def _unwrapped_call(call: Callable[..., Any] | None) -> Any: if call is None: return call # pragma: no cover unwrapped = inspect.unwrap(_impartial(call)) @@ -36,19 +36,19 @@ class Dependant: cookie_params: list[ModelField] = field(default_factory=list) body_params: list[ModelField] = field(default_factory=list) dependencies: list["Dependant"] = field(default_factory=list) - name: Optional[str] = None - call: Optional[Callable[..., Any]] = None - request_param_name: Optional[str] = None - websocket_param_name: Optional[str] = None - http_connection_param_name: Optional[str] = None - response_param_name: Optional[str] = None - background_tasks_param_name: Optional[str] = None - security_scopes_param_name: Optional[str] = None - own_oauth_scopes: Optional[list[str]] = None - parent_oauth_scopes: Optional[list[str]] = None + name: str | None = None + call: Callable[..., Any] | None = None + request_param_name: str | None = None + websocket_param_name: str | None = None + http_connection_param_name: str | None = None + response_param_name: str | None = None + background_tasks_param_name: str | None = None + security_scopes_param_name: str | None = None + own_oauth_scopes: list[str] | None = None + parent_oauth_scopes: list[str] | None = None use_cache: bool = True - path: Optional[str] = None - scope: Union[Literal["function", "request"], None] = None + path: str | None = None + scope: Literal["function", "request"] | None = None @cached_property def oauth_scopes(self) -> list[str]: @@ -185,7 +185,7 @@ class Dependant: return False @cached_property - def computed_scope(self) -> Union[str, None]: + def computed_scope(self) -> str | None: if self.scope: return self.scope if self.is_gen_callable or self.is_async_gen_callable: diff --git a/fastapi/encoders.py b/fastapi/encoders.py index b4661be4fa..e20255c110 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -1,6 +1,7 @@ import dataclasses import datetime from collections import defaultdict, deque +from collections.abc import Callable from decimal import Decimal from enum import Enum from ipaddress import ( @@ -14,7 +15,7 @@ from ipaddress import ( from pathlib import Path, PurePath from re import Pattern from types import GeneratorType -from typing import Annotated, Any, Callable, Optional, Union +from typing import Annotated, Any from uuid import UUID from annotated_doc import Doc @@ -33,13 +34,13 @@ from ._compat import ( # Taken from Pydantic v1 as is -def isoformat(o: Union[datetime.date, datetime.time]) -> str: +def isoformat(o: datetime.date | datetime.time) -> str: return o.isoformat() # Adapted from Pydantic v1 # TODO: pv2 should this return strings instead? -def decimal_encoder(dec_value: Decimal) -> Union[int, float]: +def decimal_encoder(dec_value: Decimal) -> int | float: """ Encodes a Decimal as int if there's no exponent, otherwise float @@ -118,7 +119,7 @@ def jsonable_encoder( ), ], include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Pydantic's `include` parameter, passed to Pydantic models to set the @@ -127,7 +128,7 @@ def jsonable_encoder( ), ] = None, exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Pydantic's `exclude` parameter, passed to Pydantic models to set the @@ -177,7 +178,7 @@ def jsonable_encoder( ), ] = False, custom_encoder: Annotated[ - Optional[dict[Any, Callable[[Any], Any]]], + dict[Any, Callable[[Any], Any]] | None, Doc( """ Pydantic's `custom_encoder` parameter, passed to Pydantic models to define diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index 9924d0e2bd..d7065c52fe 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -1,5 +1,5 @@ from collections.abc import Mapping, Sequence -from typing import Annotated, Any, Optional, TypedDict, Union +from typing import Annotated, Any, TypedDict from annotated_doc import Doc from pydantic import BaseModel, create_model @@ -68,7 +68,7 @@ class HTTPException(StarletteHTTPException): ), ] = None, headers: Annotated[ - Optional[Mapping[str, str]], + Mapping[str, str] | None, Doc( """ Any headers to send to the client in the response. @@ -137,7 +137,7 @@ class WebSocketException(StarletteWebSocketException): ), ], reason: Annotated[ - Union[str, None], + str | None, Doc( """ The reason to close the WebSocket connection. @@ -176,7 +176,7 @@ class ValidationException(Exception): self, errors: Sequence[Any], *, - endpoint_ctx: Optional[EndpointContext] = None, + endpoint_ctx: EndpointContext | None = None, ) -> None: self._errors = errors self.endpoint_ctx = endpoint_ctx @@ -215,7 +215,7 @@ class RequestValidationError(ValidationException): errors: Sequence[Any], *, body: Any = None, - endpoint_ctx: Optional[EndpointContext] = None, + endpoint_ctx: EndpointContext | None = None, ) -> None: super().__init__(errors, endpoint_ctx=endpoint_ctx) self.body = body @@ -226,7 +226,7 @@ class WebSocketRequestValidationError(ValidationException): self, errors: Sequence[Any], *, - endpoint_ctx: Optional[EndpointContext] = None, + endpoint_ctx: EndpointContext | None = None, ) -> None: super().__init__(errors, endpoint_ctx=endpoint_ctx) @@ -237,7 +237,7 @@ class ResponseValidationError(ValidationException): errors: Sequence[Any], *, body: Any = None, - endpoint_ctx: Optional[EndpointContext] = None, + endpoint_ctx: EndpointContext | None = None, ) -> None: super().__init__(errors, endpoint_ctx=endpoint_ctx) self.body = body diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index bb387c609a..b845f87c1c 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -1,5 +1,5 @@ import json -from typing import Annotated, Any, Optional +from typing import Annotated, Any from annotated_doc import Doc from fastapi.encoders import jsonable_encoder @@ -85,7 +85,7 @@ def get_swagger_ui_html( ), ] = "https://fastapi.tiangolo.com/img/favicon.png", oauth2_redirect_url: Annotated[ - Optional[str], + str | None, Doc( """ The OAuth2 redirect URL, it is normally automatically handled by FastAPI. @@ -96,7 +96,7 @@ def get_swagger_ui_html( ), ] = None, init_oauth: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ A dictionary with Swagger UI OAuth2 initialization configurations. @@ -107,7 +107,7 @@ def get_swagger_ui_html( ), ] = None, swagger_ui_parameters: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Configuration parameters for Swagger UI. diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index 0959906390..d7950241fc 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -1,6 +1,6 @@ -from collections.abc import Iterable, Mapping +from collections.abc import Callable, Iterable, Mapping from enum import Enum -from typing import Annotated, Any, Callable, Optional, Union +from typing import Annotated, Any, Literal, Optional, Union from fastapi._compat import with_info_plain_validator_function from fastapi.logger import logger @@ -10,7 +10,7 @@ from pydantic import ( Field, GetJsonSchemaHandler, ) -from typing_extensions import Literal, TypedDict +from typing_extensions import TypedDict from typing_extensions import deprecated as typing_deprecated try: @@ -59,37 +59,37 @@ class BaseModelWithConfig(BaseModel): class Contact(BaseModelWithConfig): - name: Optional[str] = None - url: Optional[AnyUrl] = None - email: Optional[EmailStr] = None + name: str | None = None + url: AnyUrl | None = None + email: EmailStr | None = None class License(BaseModelWithConfig): name: str - identifier: Optional[str] = None - url: Optional[AnyUrl] = None + identifier: str | None = None + url: AnyUrl | None = None class Info(BaseModelWithConfig): title: str - summary: Optional[str] = None - description: Optional[str] = None - termsOfService: Optional[str] = None - contact: Optional[Contact] = None - license: Optional[License] = None + summary: str | None = None + description: str | None = None + termsOfService: str | None = None + contact: Contact | None = None + license: License | None = None version: str class ServerVariable(BaseModelWithConfig): - enum: Annotated[Optional[list[str]], Field(min_length=1)] = None + enum: Annotated[list[str] | None, Field(min_length=1)] = None default: str - description: Optional[str] = None + description: str | None = None class Server(BaseModelWithConfig): - url: Union[AnyUrl, str] - description: Optional[str] = None - variables: Optional[dict[str, ServerVariable]] = None + url: AnyUrl | str + description: str | None = None + variables: dict[str, ServerVariable] | None = None class Reference(BaseModel): @@ -98,19 +98,19 @@ class Reference(BaseModel): class Discriminator(BaseModel): propertyName: str - mapping: Optional[dict[str, str]] = None + mapping: dict[str, str] | None = None class XML(BaseModelWithConfig): - name: Optional[str] = None - namespace: Optional[str] = None - prefix: Optional[str] = None - attribute: Optional[bool] = None - wrapped: Optional[bool] = None + name: str | None = None + namespace: str | None = None + prefix: str | None = None + attribute: bool | None = None + wrapped: bool | None = None class ExternalDocumentation(BaseModelWithConfig): - description: Optional[str] = None + description: str | None = None url: AnyUrl @@ -123,80 +123,80 @@ SchemaType = Literal[ class Schema(BaseModelWithConfig): # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu # Core Vocabulary - schema_: Optional[str] = Field(default=None, alias="$schema") - vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") - id: Optional[str] = Field(default=None, alias="$id") - anchor: Optional[str] = Field(default=None, alias="$anchor") - dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") - ref: Optional[str] = Field(default=None, alias="$ref") - dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") - defs: Optional[dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs") - comment: Optional[str] = Field(default=None, alias="$comment") + schema_: str | None = Field(default=None, alias="$schema") + vocabulary: str | None = Field(default=None, alias="$vocabulary") + id: str | None = Field(default=None, alias="$id") + anchor: str | None = Field(default=None, alias="$anchor") + dynamicAnchor: str | None = Field(default=None, alias="$dynamicAnchor") + ref: str | None = Field(default=None, alias="$ref") + dynamicRef: str | None = Field(default=None, alias="$dynamicRef") + defs: dict[str, "SchemaOrBool"] | None = Field(default=None, alias="$defs") + comment: str | None = Field(default=None, alias="$comment") # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s # A Vocabulary for Applying Subschemas - allOf: Optional[list["SchemaOrBool"]] = None - anyOf: Optional[list["SchemaOrBool"]] = None - oneOf: Optional[list["SchemaOrBool"]] = None + allOf: list["SchemaOrBool"] | None = None + anyOf: list["SchemaOrBool"] | None = None + oneOf: list["SchemaOrBool"] | None = None not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") then: Optional["SchemaOrBool"] = None else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") - dependentSchemas: Optional[dict[str, "SchemaOrBool"]] = None - prefixItems: Optional[list["SchemaOrBool"]] = None + dependentSchemas: dict[str, "SchemaOrBool"] | None = None + prefixItems: list["SchemaOrBool"] | None = None items: Optional["SchemaOrBool"] = None contains: Optional["SchemaOrBool"] = None - properties: Optional[dict[str, "SchemaOrBool"]] = None - patternProperties: Optional[dict[str, "SchemaOrBool"]] = None + properties: dict[str, "SchemaOrBool"] | None = None + patternProperties: dict[str, "SchemaOrBool"] | None = None additionalProperties: Optional["SchemaOrBool"] = None propertyNames: Optional["SchemaOrBool"] = None unevaluatedItems: Optional["SchemaOrBool"] = None unevaluatedProperties: Optional["SchemaOrBool"] = None # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural # A Vocabulary for Structural Validation - type: Optional[Union[SchemaType, list[SchemaType]]] = None - enum: Optional[list[Any]] = None - const: Optional[Any] = None - multipleOf: Optional[float] = Field(default=None, gt=0) - maximum: Optional[float] = None - exclusiveMaximum: Optional[float] = None - minimum: Optional[float] = None - exclusiveMinimum: Optional[float] = None - maxLength: Optional[int] = Field(default=None, ge=0) - minLength: Optional[int] = Field(default=None, ge=0) - pattern: Optional[str] = None - maxItems: Optional[int] = Field(default=None, ge=0) - minItems: Optional[int] = Field(default=None, ge=0) - uniqueItems: Optional[bool] = None - maxContains: Optional[int] = Field(default=None, ge=0) - minContains: Optional[int] = Field(default=None, ge=0) - maxProperties: Optional[int] = Field(default=None, ge=0) - minProperties: Optional[int] = Field(default=None, ge=0) - required: Optional[list[str]] = None - dependentRequired: Optional[dict[str, set[str]]] = None + type: SchemaType | list[SchemaType] | None = None + enum: list[Any] | None = None + const: Any | None = None + multipleOf: float | None = Field(default=None, gt=0) + maximum: float | None = None + exclusiveMaximum: float | None = None + minimum: float | None = None + exclusiveMinimum: float | None = None + maxLength: int | None = Field(default=None, ge=0) + minLength: int | None = Field(default=None, ge=0) + pattern: str | None = None + maxItems: int | None = Field(default=None, ge=0) + minItems: int | None = Field(default=None, ge=0) + uniqueItems: bool | None = None + maxContains: int | None = Field(default=None, ge=0) + minContains: int | None = Field(default=None, ge=0) + maxProperties: int | None = Field(default=None, ge=0) + minProperties: int | None = Field(default=None, ge=0) + required: list[str] | None = None + dependentRequired: dict[str, set[str]] | None = None # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c # Vocabularies for Semantic Content With "format" - format: Optional[str] = None + format: str | None = None # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten # A Vocabulary for the Contents of String-Encoded Data - contentEncoding: Optional[str] = None - contentMediaType: Optional[str] = None + contentEncoding: str | None = None + contentMediaType: str | None = None contentSchema: Optional["SchemaOrBool"] = None # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta # A Vocabulary for Basic Meta-Data Annotations - title: Optional[str] = None - description: Optional[str] = None - default: Optional[Any] = None - deprecated: Optional[bool] = None - readOnly: Optional[bool] = None - writeOnly: Optional[bool] = None - examples: Optional[list[Any]] = None + title: str | None = None + description: str | None = None + default: Any | None = None + deprecated: bool | None = None + readOnly: bool | None = None + writeOnly: bool | None = None + examples: list[Any] | None = None # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object # Schema Object - discriminator: Optional[Discriminator] = None - xml: Optional[XML] = None - externalDocs: Optional[ExternalDocumentation] = None + discriminator: Discriminator | None = None + xml: XML | None = None + externalDocs: ExternalDocumentation | None = None example: Annotated[ - Optional[Any], + Any | None, typing_deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." @@ -206,14 +206,14 @@ class Schema(BaseModelWithConfig): # Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents # A JSON Schema MUST be an object or a boolean. -SchemaOrBool = Union[Schema, bool] +SchemaOrBool = Schema | bool class Example(TypedDict, total=False): - summary: Optional[str] - description: Optional[str] - value: Optional[Any] - externalValue: Optional[AnyUrl] + summary: str | None + description: str | None + value: Any | None + externalValue: AnyUrl | None __pydantic_config__ = {"extra": "allow"} # type: ignore[misc] @@ -226,33 +226,33 @@ class ParameterInType(Enum): class Encoding(BaseModelWithConfig): - contentType: Optional[str] = None - headers: Optional[dict[str, Union["Header", Reference]]] = None - style: Optional[str] = None - explode: Optional[bool] = None - allowReserved: Optional[bool] = None + contentType: str | None = None + headers: dict[str, Union["Header", Reference]] | None = None + style: str | None = None + explode: bool | None = None + allowReserved: bool | None = None class MediaType(BaseModelWithConfig): - schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") - example: Optional[Any] = None - examples: Optional[dict[str, Union[Example, Reference]]] = None - encoding: Optional[dict[str, Encoding]] = None + schema_: Schema | Reference | None = Field(default=None, alias="schema") + example: Any | None = None + examples: dict[str, Example | Reference] | None = None + encoding: dict[str, Encoding] | None = None class ParameterBase(BaseModelWithConfig): - description: Optional[str] = None - required: Optional[bool] = None - deprecated: Optional[bool] = None + description: str | None = None + required: bool | None = None + deprecated: bool | None = None # Serialization rules for simple scenarios - style: Optional[str] = None - explode: Optional[bool] = None - allowReserved: Optional[bool] = None - schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") - example: Optional[Any] = None - examples: Optional[dict[str, Union[Example, Reference]]] = None + style: str | None = None + explode: bool | None = None + allowReserved: bool | None = None + schema_: Schema | Reference | None = Field(default=None, alias="schema") + example: Any | None = None + examples: dict[str, Example | Reference] | None = None # Serialization rules for more complex scenarios - content: Optional[dict[str, MediaType]] = None + content: dict[str, MediaType] | None = None class Parameter(ParameterBase): @@ -265,57 +265,57 @@ class Header(ParameterBase): class RequestBody(BaseModelWithConfig): - description: Optional[str] = None + description: str | None = None content: dict[str, MediaType] - required: Optional[bool] = None + required: bool | None = None class Link(BaseModelWithConfig): - operationRef: Optional[str] = None - operationId: Optional[str] = None - parameters: Optional[dict[str, Union[Any, str]]] = None - requestBody: Optional[Union[Any, str]] = None - description: Optional[str] = None - server: Optional[Server] = None + operationRef: str | None = None + operationId: str | None = None + parameters: dict[str, Any | str] | None = None + requestBody: Any | str | None = None + description: str | None = None + server: Server | None = None class Response(BaseModelWithConfig): description: str - headers: Optional[dict[str, Union[Header, Reference]]] = None - content: Optional[dict[str, MediaType]] = None - links: Optional[dict[str, Union[Link, Reference]]] = None + headers: dict[str, Header | Reference] | None = None + content: dict[str, MediaType] | None = None + links: dict[str, Link | Reference] | None = None class Operation(BaseModelWithConfig): - tags: Optional[list[str]] = None - summary: Optional[str] = None - description: Optional[str] = None - externalDocs: Optional[ExternalDocumentation] = None - operationId: Optional[str] = None - parameters: Optional[list[Union[Parameter, Reference]]] = None - requestBody: Optional[Union[RequestBody, Reference]] = None + tags: list[str] | None = None + summary: str | None = None + description: str | None = None + externalDocs: ExternalDocumentation | None = None + operationId: str | None = None + parameters: list[Parameter | Reference] | None = None + requestBody: RequestBody | Reference | None = None # Using Any for Specification Extensions - responses: Optional[dict[str, Union[Response, Any]]] = None - callbacks: Optional[dict[str, Union[dict[str, "PathItem"], Reference]]] = None - deprecated: Optional[bool] = None - security: Optional[list[dict[str, list[str]]]] = None - servers: Optional[list[Server]] = None + responses: dict[str, Response | Any] | None = None + callbacks: dict[str, dict[str, "PathItem"] | Reference] | None = None + deprecated: bool | None = None + security: list[dict[str, list[str]]] | None = None + servers: list[Server] | None = None class PathItem(BaseModelWithConfig): - ref: Optional[str] = Field(default=None, alias="$ref") - summary: Optional[str] = None - description: Optional[str] = None - get: Optional[Operation] = None - put: Optional[Operation] = None - post: Optional[Operation] = None - delete: Optional[Operation] = None - options: Optional[Operation] = None - head: Optional[Operation] = None - patch: Optional[Operation] = None - trace: Optional[Operation] = None - servers: Optional[list[Server]] = None - parameters: Optional[list[Union[Parameter, Reference]]] = None + ref: str | None = Field(default=None, alias="$ref") + summary: str | None = None + description: str | None = None + get: Operation | None = None + put: Operation | None = None + post: Operation | None = None + delete: Operation | None = None + options: Operation | None = None + head: Operation | None = None + patch: Operation | None = None + trace: Operation | None = None + servers: list[Server] | None = None + parameters: list[Parameter | Reference] | None = None class SecuritySchemeType(Enum): @@ -327,7 +327,7 @@ class SecuritySchemeType(Enum): class SecurityBase(BaseModelWithConfig): type_: SecuritySchemeType = Field(alias="type") - description: Optional[str] = None + description: str | None = None class APIKeyIn(Enum): @@ -349,11 +349,11 @@ class HTTPBase(SecurityBase): class HTTPBearer(HTTPBase): scheme: Literal["bearer"] = "bearer" - bearerFormat: Optional[str] = None + bearerFormat: str | None = None class OAuthFlow(BaseModelWithConfig): - refreshUrl: Optional[str] = None + refreshUrl: str | None = None scopes: dict[str, str] = {} @@ -375,10 +375,10 @@ class OAuthFlowAuthorizationCode(OAuthFlow): class OAuthFlows(BaseModelWithConfig): - implicit: Optional[OAuthFlowImplicit] = None - password: Optional[OAuthFlowPassword] = None - clientCredentials: Optional[OAuthFlowClientCredentials] = None - authorizationCode: Optional[OAuthFlowAuthorizationCode] = None + implicit: OAuthFlowImplicit | None = None + password: OAuthFlowPassword | None = None + clientCredentials: OAuthFlowClientCredentials | None = None + authorizationCode: OAuthFlowAuthorizationCode | None = None class OAuth2(SecurityBase): @@ -393,41 +393,41 @@ class OpenIdConnect(SecurityBase): openIdConnectUrl: str -SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer] +SecurityScheme = APIKey | HTTPBase | OAuth2 | OpenIdConnect | HTTPBearer class Components(BaseModelWithConfig): - schemas: Optional[dict[str, Union[Schema, Reference]]] = None - responses: Optional[dict[str, Union[Response, Reference]]] = None - parameters: Optional[dict[str, Union[Parameter, Reference]]] = None - examples: Optional[dict[str, Union[Example, Reference]]] = None - requestBodies: Optional[dict[str, Union[RequestBody, Reference]]] = None - headers: Optional[dict[str, Union[Header, Reference]]] = None - securitySchemes: Optional[dict[str, Union[SecurityScheme, Reference]]] = None - links: Optional[dict[str, Union[Link, Reference]]] = None + schemas: dict[str, Schema | Reference] | None = None + responses: dict[str, Response | Reference] | None = None + parameters: dict[str, Parameter | Reference] | None = None + examples: dict[str, Example | Reference] | None = None + requestBodies: dict[str, RequestBody | Reference] | None = None + headers: dict[str, Header | Reference] | None = None + securitySchemes: dict[str, SecurityScheme | Reference] | None = None + links: dict[str, Link | Reference] | None = None # Using Any for Specification Extensions - callbacks: Optional[dict[str, Union[dict[str, PathItem], Reference, Any]]] = None - pathItems: Optional[dict[str, Union[PathItem, Reference]]] = None + callbacks: dict[str, dict[str, PathItem] | Reference | Any] | None = None + pathItems: dict[str, PathItem | Reference] | None = None class Tag(BaseModelWithConfig): name: str - description: Optional[str] = None - externalDocs: Optional[ExternalDocumentation] = None + description: str | None = None + externalDocs: ExternalDocumentation | None = None class OpenAPI(BaseModelWithConfig): openapi: str info: Info - jsonSchemaDialect: Optional[str] = None - servers: Optional[list[Server]] = None + jsonSchemaDialect: str | None = None + servers: list[Server] | None = None # Using Any for Specification Extensions - paths: Optional[dict[str, Union[PathItem, Any]]] = None - webhooks: Optional[dict[str, Union[PathItem, Reference]]] = None - components: Optional[Components] = None - security: Optional[list[dict[str, list[str]]]] = None - tags: Optional[list[Tag]] = None - externalDocs: Optional[ExternalDocumentation] = None + paths: dict[str, PathItem | Any] | None = None + webhooks: dict[str, PathItem | Reference] | None = None + components: Components | None = None + security: list[dict[str, list[str]]] | None = None + tags: list[Tag] | None = None + externalDocs: ExternalDocumentation | None = None Schema.model_rebuild() diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index bcad0be75d..812003aee3 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -3,7 +3,7 @@ import http.client import inspect import warnings from collections.abc import Sequence -from typing import Any, Optional, Union, cast +from typing import Any, Literal, cast from fastapi import routing from fastapi._compat import ( @@ -38,7 +38,6 @@ from fastapi.utils import ( from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute -from typing_extensions import Literal validation_error_definition = { "title": "ValidationError", @@ -180,13 +179,13 @@ def _get_openapi_operation_parameters( def get_openapi_operation_request_body( *, - body_field: Optional[ModelField], + body_field: ModelField | None, model_name_map: ModelNameMap, field_mapping: dict[ tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any] ], separate_input_output_schemas: bool = True, -) -> Optional[dict[str, Any]]: +) -> dict[str, Any] | None: if not body_field: return None assert isinstance(body_field, ModelField) @@ -279,7 +278,7 @@ def get_openapi_path( else: current_response_class = route.response_class assert current_response_class, "A response class is needed to generate OpenAPI" - route_response_media_type: Optional[str] = current_response_class.media_type + route_response_media_type: str | None = current_response_class.media_type if route.include_in_schema: for method in route.methods: operation = get_openapi_operation_metadata( @@ -393,7 +392,7 @@ def get_openapi_path( "An additional response must be a dict" ) field = route.response_fields.get(additional_status_code) - additional_field_schema: Optional[dict[str, Any]] = None + additional_field_schema: dict[str, Any] | None = None if field: additional_field_schema = get_schema_from_model_field( field=field, @@ -408,7 +407,7 @@ def get_openapi_path( .setdefault("schema", {}) ) deep_dict_update(additional_schema, additional_field_schema) - status_text: Optional[str] = status_code_ranges.get( + status_text: str | None = status_code_ranges.get( str(additional_status_code).upper() ) or http.client.responses.get(int(additional_status_code)) description = ( @@ -482,17 +481,17 @@ def get_openapi( title: str, version: str, openapi_version: str = "3.1.0", - summary: Optional[str] = None, - description: Optional[str] = None, + summary: str | None = None, + description: str | None = None, routes: Sequence[BaseRoute], - webhooks: Optional[Sequence[BaseRoute]] = None, - tags: Optional[list[dict[str, Any]]] = None, - servers: Optional[list[dict[str, Union[str, Any]]]] = None, - terms_of_service: Optional[str] = None, - contact: Optional[dict[str, Union[str, Any]]] = None, - license_info: Optional[dict[str, Union[str, Any]]] = None, + webhooks: Sequence[BaseRoute] | None = None, + tags: list[dict[str, Any]] | None = None, + servers: list[dict[str, str | Any]] | None = None, + terms_of_service: str | None = None, + contact: dict[str, str | Any] | None = None, + license_info: dict[str, str | Any] | None = None, separate_input_output_schemas: bool = True, - external_docs: Optional[dict[str, Any]] = None, + external_docs: dict[str, Any] | None = None, ) -> dict[str, Any]: info: dict[str, Any] = {"title": title, "version": version} if summary: diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index 9bd92be4c7..4be504f435 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -1,12 +1,12 @@ -from collections.abc import Sequence -from typing import Annotated, Any, Callable, Optional, Union +from collections.abc import Callable, Sequence +from typing import Annotated, Any, Literal from annotated_doc import Doc from fastapi import params from fastapi._compat import Undefined from fastapi.openapi.models import Example from pydantic import AliasChoices, AliasPath -from typing_extensions import Literal, deprecated +from typing_extensions import deprecated _Unset: Any = Undefined @@ -25,7 +25,7 @@ def Path( # noqa: N802 ] = ..., *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -36,7 +36,7 @@ def Path( # noqa: N802 ), ] = _Unset, alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -48,7 +48,7 @@ def Path( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -56,7 +56,7 @@ def Path( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -65,7 +65,7 @@ def Path( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -75,7 +75,7 @@ def Path( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -86,7 +86,7 @@ def Path( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -94,7 +94,7 @@ def Path( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -106,7 +106,7 @@ def Path( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -118,7 +118,7 @@ def Path( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -129,7 +129,7 @@ def Path( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -141,7 +141,7 @@ def Path( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -149,7 +149,7 @@ def Path( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -157,7 +157,7 @@ def Path( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -165,7 +165,7 @@ def Path( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -176,7 +176,7 @@ def Path( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -184,7 +184,7 @@ def Path( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -192,7 +192,7 @@ def Path( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -200,7 +200,7 @@ def Path( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -208,7 +208,7 @@ def Path( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -216,7 +216,7 @@ def Path( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -224,7 +224,7 @@ def Path( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -235,14 +235,14 @@ def Path( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -259,7 +259,7 @@ def Path( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -280,7 +280,7 @@ def Path( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -369,7 +369,7 @@ def Query( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -380,7 +380,7 @@ def Query( # noqa: N802 ), ] = _Unset, alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -395,7 +395,7 @@ def Query( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -403,7 +403,7 @@ def Query( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -412,7 +412,7 @@ def Query( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -422,7 +422,7 @@ def Query( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -433,7 +433,7 @@ def Query( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -444,7 +444,7 @@ def Query( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -456,7 +456,7 @@ def Query( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -468,7 +468,7 @@ def Query( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -479,7 +479,7 @@ def Query( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -491,7 +491,7 @@ def Query( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -502,7 +502,7 @@ def Query( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -513,7 +513,7 @@ def Query( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -524,7 +524,7 @@ def Query( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -535,7 +535,7 @@ def Query( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -543,7 +543,7 @@ def Query( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -551,7 +551,7 @@ def Query( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -559,7 +559,7 @@ def Query( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -567,7 +567,7 @@ def Query( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -575,7 +575,7 @@ def Query( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -583,7 +583,7 @@ def Query( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -594,14 +594,14 @@ def Query( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -618,7 +618,7 @@ def Query( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -645,7 +645,7 @@ def Query( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -710,7 +710,7 @@ def Header( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -721,7 +721,7 @@ def Header( # noqa: N802 ), ] = _Unset, alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -733,7 +733,7 @@ def Header( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -741,7 +741,7 @@ def Header( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -750,7 +750,7 @@ def Header( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -771,7 +771,7 @@ def Header( # noqa: N802 ), ] = True, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -779,7 +779,7 @@ def Header( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -787,7 +787,7 @@ def Header( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -796,7 +796,7 @@ def Header( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -805,7 +805,7 @@ def Header( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -813,7 +813,7 @@ def Header( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -822,7 +822,7 @@ def Header( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -830,7 +830,7 @@ def Header( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -838,7 +838,7 @@ def Header( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -846,7 +846,7 @@ def Header( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -857,7 +857,7 @@ def Header( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -865,7 +865,7 @@ def Header( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -873,7 +873,7 @@ def Header( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -881,7 +881,7 @@ def Header( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -889,7 +889,7 @@ def Header( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -897,7 +897,7 @@ def Header( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -905,7 +905,7 @@ def Header( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -916,14 +916,14 @@ def Header( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -940,7 +940,7 @@ def Header( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -961,7 +961,7 @@ def Header( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -1027,7 +1027,7 @@ def Cookie( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -1038,7 +1038,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -1050,7 +1050,7 @@ def Cookie( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -1058,7 +1058,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -1067,7 +1067,7 @@ def Cookie( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -1077,7 +1077,7 @@ def Cookie( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -1085,7 +1085,7 @@ def Cookie( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -1093,7 +1093,7 @@ def Cookie( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -1102,7 +1102,7 @@ def Cookie( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -1111,7 +1111,7 @@ def Cookie( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -1119,7 +1119,7 @@ def Cookie( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -1128,7 +1128,7 @@ def Cookie( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -1136,7 +1136,7 @@ def Cookie( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -1144,7 +1144,7 @@ def Cookie( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1152,7 +1152,7 @@ def Cookie( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1163,7 +1163,7 @@ def Cookie( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -1171,7 +1171,7 @@ def Cookie( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -1179,7 +1179,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -1187,7 +1187,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -1195,7 +1195,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -1203,7 +1203,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -1211,7 +1211,7 @@ def Cookie( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -1222,14 +1222,14 @@ def Cookie( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -1246,7 +1246,7 @@ def Cookie( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -1267,7 +1267,7 @@ def Cookie( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -1332,7 +1332,7 @@ def Body( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -1343,7 +1343,7 @@ def Body( # noqa: N802 ), ] = _Unset, embed: Annotated[ - Union[bool, None], + bool | None, Doc( """ When `embed` is `True`, the parameter will be expected in a JSON body as a @@ -1366,7 +1366,7 @@ def Body( # noqa: N802 ), ] = "application/json", alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -1378,7 +1378,7 @@ def Body( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -1386,7 +1386,7 @@ def Body( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -1395,7 +1395,7 @@ def Body( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -1405,7 +1405,7 @@ def Body( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -1413,7 +1413,7 @@ def Body( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -1421,7 +1421,7 @@ def Body( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -1430,7 +1430,7 @@ def Body( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -1439,7 +1439,7 @@ def Body( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -1447,7 +1447,7 @@ def Body( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -1456,7 +1456,7 @@ def Body( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -1464,7 +1464,7 @@ def Body( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -1472,7 +1472,7 @@ def Body( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1480,7 +1480,7 @@ def Body( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1491,7 +1491,7 @@ def Body( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -1499,7 +1499,7 @@ def Body( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -1507,7 +1507,7 @@ def Body( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -1515,7 +1515,7 @@ def Body( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -1523,7 +1523,7 @@ def Body( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -1531,7 +1531,7 @@ def Body( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -1539,7 +1539,7 @@ def Body( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -1550,14 +1550,14 @@ def Body( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -1574,7 +1574,7 @@ def Body( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -1595,7 +1595,7 @@ def Body( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -1662,7 +1662,7 @@ def Form( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -1682,7 +1682,7 @@ def Form( # noqa: N802 ), ] = "application/x-www-form-urlencoded", alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -1694,7 +1694,7 @@ def Form( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -1702,7 +1702,7 @@ def Form( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -1711,7 +1711,7 @@ def Form( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -1721,7 +1721,7 @@ def Form( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -1729,7 +1729,7 @@ def Form( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -1737,7 +1737,7 @@ def Form( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -1746,7 +1746,7 @@ def Form( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -1755,7 +1755,7 @@ def Form( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -1763,7 +1763,7 @@ def Form( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -1772,7 +1772,7 @@ def Form( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -1780,7 +1780,7 @@ def Form( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -1788,7 +1788,7 @@ def Form( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1796,7 +1796,7 @@ def Form( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -1807,7 +1807,7 @@ def Form( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -1815,7 +1815,7 @@ def Form( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -1823,7 +1823,7 @@ def Form( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -1831,7 +1831,7 @@ def Form( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -1839,7 +1839,7 @@ def Form( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -1847,7 +1847,7 @@ def Form( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -1855,7 +1855,7 @@ def Form( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -1866,14 +1866,14 @@ def Form( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -1890,7 +1890,7 @@ def Form( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -1911,7 +1911,7 @@ def Form( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -1977,7 +1977,7 @@ def File( # noqa: N802 ] = Undefined, *, default_factory: Annotated[ - Union[Callable[[], Any], None], + Callable[[], Any] | None, Doc( """ A callable to generate the default value. @@ -1997,7 +1997,7 @@ def File( # noqa: N802 ), ] = "multipart/form-data", alias: Annotated[ - Optional[str], + str | None, Doc( """ An alternative name for the parameter field. @@ -2009,7 +2009,7 @@ def File( # noqa: N802 ), ] = None, alias_priority: Annotated[ - Union[int, None], + int | None, Doc( """ Priority of the alias. This affects whether an alias generator is used. @@ -2017,7 +2017,7 @@ def File( # noqa: N802 ), ] = _Unset, validation_alias: Annotated[ - Union[str, AliasPath, AliasChoices, None], + str | AliasPath | AliasChoices | None, Doc( """ 'Whitelist' validation step. The parameter field will be the single one @@ -2026,7 +2026,7 @@ def File( # noqa: N802 ), ] = None, serialization_alias: Annotated[ - Union[str, None], + str | None, Doc( """ 'Blacklist' validation step. The vanilla parameter field will be the @@ -2036,7 +2036,7 @@ def File( # noqa: N802 ), ] = None, title: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable title. @@ -2044,7 +2044,7 @@ def File( # noqa: N802 ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Human-readable description. @@ -2052,7 +2052,7 @@ def File( # noqa: N802 ), ] = None, gt: Annotated[ - Optional[float], + float | None, Doc( """ Greater than. If set, value must be greater than this. Only applicable to @@ -2061,7 +2061,7 @@ def File( # noqa: N802 ), ] = None, ge: Annotated[ - Optional[float], + float | None, Doc( """ Greater than or equal. If set, value must be greater than or equal to @@ -2070,7 +2070,7 @@ def File( # noqa: N802 ), ] = None, lt: Annotated[ - Optional[float], + float | None, Doc( """ Less than. If set, value must be less than this. Only applicable to numbers. @@ -2078,7 +2078,7 @@ def File( # noqa: N802 ), ] = None, le: Annotated[ - Optional[float], + float | None, Doc( """ Less than or equal. If set, value must be less than or equal to this. @@ -2087,7 +2087,7 @@ def File( # noqa: N802 ), ] = None, min_length: Annotated[ - Optional[int], + int | None, Doc( """ Minimum length for strings. @@ -2095,7 +2095,7 @@ def File( # noqa: N802 ), ] = None, max_length: Annotated[ - Optional[int], + int | None, Doc( """ Maximum length for strings. @@ -2103,7 +2103,7 @@ def File( # noqa: N802 ), ] = None, pattern: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -2111,7 +2111,7 @@ def File( # noqa: N802 ), ] = None, regex: Annotated[ - Optional[str], + str | None, Doc( """ RegEx pattern for strings. @@ -2122,7 +2122,7 @@ def File( # noqa: N802 ), ] = None, discriminator: Annotated[ - Union[str, None], + str | None, Doc( """ Parameter field name for discriminating the type in a tagged union. @@ -2130,7 +2130,7 @@ def File( # noqa: N802 ), ] = None, strict: Annotated[ - Union[bool, None], + bool | None, Doc( """ If `True`, strict validation is applied to the field. @@ -2138,7 +2138,7 @@ def File( # noqa: N802 ), ] = _Unset, multiple_of: Annotated[ - Union[float, None], + float | None, Doc( """ Value must be a multiple of this. Only applicable to numbers. @@ -2146,7 +2146,7 @@ def File( # noqa: N802 ), ] = _Unset, allow_inf_nan: Annotated[ - Union[bool, None], + bool | None, Doc( """ Allow `inf`, `-inf`, `nan`. Only applicable to numbers. @@ -2154,7 +2154,7 @@ def File( # noqa: N802 ), ] = _Unset, max_digits: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of allow digits for strings. @@ -2162,7 +2162,7 @@ def File( # noqa: N802 ), ] = _Unset, decimal_places: Annotated[ - Union[int, None], + int | None, Doc( """ Maximum number of decimal places allowed for numbers. @@ -2170,7 +2170,7 @@ def File( # noqa: N802 ), ] = _Unset, examples: Annotated[ - Optional[list[Any]], + list[Any] | None, Doc( """ Example values for this field. @@ -2181,14 +2181,14 @@ def File( # noqa: N802 ), ] = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, openapi_examples: Annotated[ - Optional[dict[str, Example]], + dict[str, Example] | None, Doc( """ OpenAPI-specific examples. @@ -2205,7 +2205,7 @@ def File( # noqa: N802 ), ] = None, deprecated: Annotated[ - Union[deprecated, str, bool, None], + deprecated | str | bool | None, Doc( """ Mark this parameter field as deprecated. @@ -2226,7 +2226,7 @@ def File( # noqa: N802 ), ] = True, json_schema_extra: Annotated[ - Union[dict[str, Any], None], + dict[str, Any] | None, Doc( """ Any additional JSON schema data. @@ -2283,7 +2283,7 @@ def File( # noqa: N802 def Depends( # noqa: N802 dependency: Annotated[ - Optional[Callable[..., Any]], + Callable[..., Any] | None, Doc( """ A "dependable" callable (like a function). @@ -2315,7 +2315,7 @@ def Depends( # noqa: N802 ), ] = True, scope: Annotated[ - Union[Literal["function", "request"], None], + Literal["function", "request"] | None, Doc( """ Mainly for dependencies with `yield`, define when the dependency function @@ -2372,7 +2372,7 @@ def Depends( # noqa: N802 def Security( # noqa: N802 dependency: Annotated[ - Optional[Callable[..., Any]], + Callable[..., Any] | None, Doc( """ A "dependable" callable (like a function). @@ -2387,7 +2387,7 @@ def Security( # noqa: N802 ] = None, *, scopes: Annotated[ - Optional[Sequence[str]], + Sequence[str] | None, Doc( """ OAuth2 scopes required for the *path operation* that uses this Security diff --git a/fastapi/params.py b/fastapi/params.py index 72e797f833..68f9870810 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -1,14 +1,14 @@ import warnings -from collections.abc import Sequence +from collections.abc import Callable, Sequence from dataclasses import dataclass from enum import Enum -from typing import Annotated, Any, Callable, Optional, Union +from typing import Annotated, Any, Literal from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.openapi.models import Example from pydantic import AliasChoices, AliasPath from pydantic.fields import FieldInfo -from typing_extensions import Literal, deprecated +from typing_extensions import deprecated from ._compat import ( Undefined, @@ -31,45 +31,45 @@ class Param(FieldInfo): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): if example is not _Unset: @@ -142,45 +142,45 @@ class Path(Param): # type: ignore[misc] self, default: Any = ..., *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): assert default is ..., "Path parameters cannot have a default value" @@ -226,45 +226,45 @@ class Query(Param): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): super().__init__( @@ -308,46 +308,46 @@ class Header(Param): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, convert_underscores: bool = True, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): self.convert_underscores = convert_underscores @@ -392,45 +392,45 @@ class Cookie(Param): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): super().__init__( @@ -472,47 +472,47 @@ class Body(FieldInfo): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, - embed: Union[bool, None] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, + embed: bool | None = None, media_type: str = "application/json", - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): self.embed = embed @@ -584,46 +584,46 @@ class Form(Body): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, media_type: str = "application/x-www-form-urlencoded", - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): super().__init__( @@ -666,46 +666,46 @@ class File(Form): # type: ignore[misc] self, default: Any = Undefined, *, - default_factory: Union[Callable[[], Any], None] = _Unset, - annotation: Optional[Any] = None, + default_factory: Callable[[], Any] | None = _Unset, + annotation: Any | None = None, media_type: str = "multipart/form-data", - alias: Optional[str] = None, - alias_priority: Union[int, None] = _Unset, - validation_alias: Union[str, AliasPath, AliasChoices, None] = None, - serialization_alias: Union[str, None] = None, - title: Optional[str] = None, - description: Optional[str] = None, - gt: Optional[float] = None, - ge: Optional[float] = None, - lt: Optional[float] = None, - le: Optional[float] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - pattern: Optional[str] = None, + alias: str | None = None, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = None, + serialization_alias: str | None = None, + title: str | None = None, + description: str | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | None = None, regex: Annotated[ - Optional[str], + str | None, deprecated( "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." ), ] = None, - discriminator: Union[str, None] = None, - strict: Union[bool, None] = _Unset, - multiple_of: Union[float, None] = _Unset, - allow_inf_nan: Union[bool, None] = _Unset, - max_digits: Union[int, None] = _Unset, - decimal_places: Union[int, None] = _Unset, - examples: Optional[list[Any]] = None, + discriminator: str | None = None, + strict: bool | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + examples: list[Any] | None = None, example: Annotated[ - Optional[Any], + Any | None, deprecated( "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " "although still supported. Use examples instead." ), ] = _Unset, - openapi_examples: Optional[dict[str, Example]] = None, - deprecated: Union[deprecated, str, bool, None] = None, + openapi_examples: dict[str, Example] | None = None, + deprecated: deprecated | str | bool | None = None, include_in_schema: bool = True, - json_schema_extra: Union[dict[str, Any], None] = None, + json_schema_extra: dict[str, Any] | None = None, **extra: Any, ): super().__init__( @@ -745,11 +745,11 @@ class File(Form): # type: ignore[misc] @dataclass(frozen=True) class Depends: - dependency: Optional[Callable[..., Any]] = None + dependency: Callable[..., Any] | None = None use_cache: bool = True - scope: Union[Literal["function", "request"], None] = None + scope: Literal["function", "request"] | None = None @dataclass(frozen=True) class Security(Depends): - scopes: Optional[Sequence[str]] = None + scopes: Sequence[str] | None = None diff --git a/fastapi/routing.py b/fastapi/routing.py index ed873fda8c..ea82ab14a3 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -7,6 +7,7 @@ import types from collections.abc import ( AsyncIterator, Awaitable, + Callable, Collection, Coroutine, Generator, @@ -23,10 +24,7 @@ from enum import Enum, IntEnum from typing import ( Annotated, Any, - Callable, - Optional, TypeVar, - Union, ) from annotated_doc import Doc @@ -84,7 +82,7 @@ from typing_extensions import deprecated # Copy of starlette.routing.request_response modified to include the # dependencies' AsyncExitStack def request_response( - func: Callable[[Request], Union[Awaitable[Response], Response]], + func: Callable[[Request], Awaitable[Response] | Response], ) -> ASGIApp: """ Takes a function or coroutine `func(request) -> response`, @@ -168,10 +166,10 @@ class _AsyncLiftContextManager(AbstractAsyncContextManager[_T]): async def __aexit__( self, - exc_type: Optional[type[BaseException]], - exc_value: Optional[BaseException], - traceback: Optional[types.TracebackType], - ) -> Optional[bool]: + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: types.TracebackType | None, + ) -> bool | None: return self._cm.__exit__(exc_type, exc_value, traceback) @@ -199,7 +197,7 @@ def _merge_lifespan_context( @asynccontextmanager async def merged_lifespan( app: AppType, - ) -> AsyncIterator[Optional[Mapping[str, Any]]]: + ) -> AsyncIterator[Mapping[str, Any] | None]: async with original_context(app) as maybe_original_state: async with nested_context(app) as maybe_nested_state: if maybe_nested_state is None and maybe_original_state is None: @@ -263,16 +261,16 @@ def _extract_endpoint_context(func: Any) -> EndpointContext: async def serialize_response( *, - field: Optional[ModelField] = None, + field: ModelField | None = None, response_content: Any, - include: Optional[IncEx] = None, - exclude: Optional[IncEx] = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = True, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, is_coroutine: bool = True, - endpoint_ctx: Optional[EndpointContext] = None, + endpoint_ctx: EndpointContext | None = None, ) -> Any: if field: if is_coroutine: @@ -318,17 +316,17 @@ async def run_endpoint_function( def get_request_handler( dependant: Dependant, - body_field: Optional[ModelField] = None, - status_code: Optional[int] = None, - response_class: Union[type[Response], DefaultPlaceholder] = Default(JSONResponse), - response_field: Optional[ModelField] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + body_field: ModelField | None = None, + status_code: int | None = None, + response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), + response_field: ModelField | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Any | None = None, embed_body_fields: bool = False, ) -> Callable[[Request], Coroutine[Any, Any, Response]]: assert dependant.call is not None, "dependant.call must be a function" @@ -340,7 +338,7 @@ def get_request_handler( actual_response_class = response_class async def app(request: Request) -> Response: - response: Union[Response, None] = None + response: Response | None = None file_stack = request.scope.get("fastapi_middleware_astack") assert isinstance(file_stack, AsyncExitStack), ( "fastapi_middleware_astack not found in request scope" @@ -476,7 +474,7 @@ def get_request_handler( def get_websocket_app( dependant: Dependant, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Any | None = None, embed_body_fields: bool = False, ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: async def app(websocket: WebSocket) -> None: @@ -517,9 +515,9 @@ class APIWebSocketRoute(routing.WebSocketRoute): path: str, endpoint: Callable[..., Any], *, - name: Optional[str] = None, - dependencies: Optional[Sequence[params.Depends]] = None, - dependency_overrides_provider: Optional[Any] = None, + name: str | None = None, + dependencies: Sequence[params.Depends] | None = None, + dependency_overrides_provider: Any | None = None, ) -> None: self.path = path self.endpoint = endpoint @@ -560,33 +558,30 @@ class APIRoute(routing.Route): endpoint: Callable[..., Any], *, response_model: Any = Default(None), - status_code: Optional[int] = None, - tags: Optional[list[Union[str, Enum]]] = None, - dependencies: Optional[Sequence[params.Depends]] = None, - summary: Optional[str] = None, - description: Optional[str] = None, + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[params.Depends] | None = None, + summary: str | None = None, + description: str | None = None, response_description: str = "Successful Response", - responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, - deprecated: Optional[bool] = None, - name: Optional[str] = None, - methods: Optional[Union[set[str], list[str]]] = None, - operation_id: Optional[str] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + name: str | None = None, + methods: set[str] | list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, - response_class: Union[type[Response], DefaultPlaceholder] = Default( - JSONResponse - ), - dependency_overrides_provider: Optional[Any] = None, - callbacks: Optional[list[BaseRoute]] = None, - openapi_extra: Optional[dict[str, Any]] = None, - generate_unique_id_function: Union[ - Callable[["APIRoute"], str], DefaultPlaceholder - ] = Default(generate_unique_id), + response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), + dependency_overrides_provider: Any | None = None, + callbacks: list[BaseRoute] | None = None, + openapi_extra: dict[str, Any] | None = None, + generate_unique_id_function: Callable[["APIRoute"], str] + | DefaultPlaceholder = Default(generate_unique_id), ) -> None: self.path = path self.endpoint = endpoint @@ -662,7 +657,7 @@ class APIRoute(routing.Route): ) response_fields[additional_status_code] = response_field if response_fields: - self.response_fields: dict[Union[int, str], ModelField] = response_fields + self.response_fields: dict[int | str, ModelField] = response_fields else: self.response_fields = {} @@ -742,7 +737,7 @@ class APIRouter(routing.Router): *, prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to all the *path operations* in this @@ -756,7 +751,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to all the @@ -779,7 +774,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses to be shown in OpenAPI. @@ -795,7 +790,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ OpenAPI callbacks that should apply to all *path operations* in this @@ -809,7 +804,7 @@ class APIRouter(routing.Router): ), ] = None, routes: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ **Note**: you probably shouldn't use this parameter, it is inherited @@ -840,7 +835,7 @@ class APIRouter(routing.Router): ), ] = True, default: Annotated[ - Optional[ASGIApp], + ASGIApp | None, Doc( """ Default function handler for this router. Used to handle @@ -849,7 +844,7 @@ class APIRouter(routing.Router): ), ] = None, dependency_overrides_provider: Annotated[ - Optional[Any], + Any | None, Doc( """ Only used internally by FastAPI to handle dependency overrides. @@ -871,7 +866,7 @@ class APIRouter(routing.Router): ), ] = APIRoute, on_startup: Annotated[ - Optional[Sequence[Callable[[], Any]]], + Sequence[Callable[[], Any]] | None, Doc( """ A list of startup event handler functions. @@ -883,7 +878,7 @@ class APIRouter(routing.Router): ), ] = None, on_shutdown: Annotated[ - Optional[Sequence[Callable[[], Any]]], + Sequence[Callable[[], Any]] | None, Doc( """ A list of shutdown event handler functions. @@ -898,7 +893,7 @@ class APIRouter(routing.Router): # the generic to Lifespan[AppType] is the type of the top level application # which the router cannot know statically, so we use typing.Any lifespan: Annotated[ - Optional[Lifespan[Any]], + Lifespan[Any] | None, Doc( """ A `Lifespan` context manager handler. This replaces `startup` and @@ -910,7 +905,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark all *path operations* in this router as deprecated. @@ -987,7 +982,7 @@ class APIRouter(routing.Router): ) self.prefix = prefix - self.tags: list[Union[str, Enum]] = tags or [] + self.tags: list[str | Enum] = tags or [] self.dependencies = list(dependencies or []) self.deprecated = deprecated self.include_in_schema = include_in_schema @@ -1001,8 +996,8 @@ class APIRouter(routing.Router): def route( self, path: str, - methods: Optional[Collection[str]] = None, - name: Optional[str] = None, + methods: Collection[str] | None = None, + name: str | None = None, include_in_schema: bool = True, ) -> Callable[[DecoratedCallable], DecoratedCallable]: def decorator(func: DecoratedCallable) -> DecoratedCallable: @@ -1023,33 +1018,30 @@ class APIRouter(routing.Router): endpoint: Callable[..., Any], *, response_model: Any = Default(None), - status_code: Optional[int] = None, - tags: Optional[list[Union[str, Enum]]] = None, - dependencies: Optional[Sequence[params.Depends]] = None, - summary: Optional[str] = None, - description: Optional[str] = None, + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[params.Depends] | None = None, + summary: str | None = None, + description: str | None = None, response_description: str = "Successful Response", - responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, - deprecated: Optional[bool] = None, - methods: Optional[Union[set[str], list[str]]] = None, - operation_id: Optional[str] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + methods: set[str] | list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, - response_class: Union[type[Response], DefaultPlaceholder] = Default( - JSONResponse - ), - name: Optional[str] = None, - route_class_override: Optional[type[APIRoute]] = None, - callbacks: Optional[list[BaseRoute]] = None, - openapi_extra: Optional[dict[str, Any]] = None, - generate_unique_id_function: Union[ - Callable[[APIRoute], str], DefaultPlaceholder - ] = Default(generate_unique_id), + response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), + name: str | None = None, + route_class_override: type[APIRoute] | None = None, + callbacks: list[BaseRoute] | None = None, + openapi_extra: dict[str, Any] | None = None, + generate_unique_id_function: Callable[[APIRoute], str] + | DefaultPlaceholder = Default(generate_unique_id), ) -> None: route_class = route_class_override or self.route_class responses = responses or {} @@ -1104,27 +1096,27 @@ class APIRouter(routing.Router): path: str, *, response_model: Any = Default(None), - status_code: Optional[int] = None, - tags: Optional[list[Union[str, Enum]]] = None, - dependencies: Optional[Sequence[params.Depends]] = None, - summary: Optional[str] = None, - description: Optional[str] = None, + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[params.Depends] | None = None, + summary: str | None = None, + description: str | None = None, response_description: str = "Successful Response", - responses: Optional[dict[Union[int, str], dict[str, Any]]] = None, - deprecated: Optional[bool] = None, - methods: Optional[list[str]] = None, - operation_id: Optional[str] = None, - response_model_include: Optional[IncEx] = None, - response_model_exclude: Optional[IncEx] = None, + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + methods: list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, response_model_by_alias: bool = True, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, response_class: type[Response] = Default(JSONResponse), - name: Optional[str] = None, - callbacks: Optional[list[BaseRoute]] = None, - openapi_extra: Optional[dict[str, Any]] = None, + name: str | None = None, + callbacks: list[BaseRoute] | None = None, + openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[APIRoute], str] = Default( generate_unique_id ), @@ -1165,9 +1157,9 @@ class APIRouter(routing.Router): self, path: str, endpoint: Callable[..., Any], - name: Optional[str] = None, + name: str | None = None, *, - dependencies: Optional[Sequence[params.Depends]] = None, + dependencies: Sequence[params.Depends] | None = None, ) -> None: current_dependencies = self.dependencies.copy() if dependencies: @@ -1193,7 +1185,7 @@ class APIRouter(routing.Router): ), ], name: Annotated[ - Optional[str], + str | None, Doc( """ A name for the WebSocket. Only used internally. @@ -1202,7 +1194,7 @@ class APIRouter(routing.Router): ] = None, *, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be used for this @@ -1250,7 +1242,7 @@ class APIRouter(routing.Router): return decorator def websocket_route( - self, path: str, name: Union[str, None] = None + self, path: str, name: str | None = None ) -> Callable[[DecoratedCallable], DecoratedCallable]: def decorator(func: DecoratedCallable) -> DecoratedCallable: self.add_websocket_route(path, func, name=name) @@ -1264,7 +1256,7 @@ class APIRouter(routing.Router): *, prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to all the *path operations* in this @@ -1278,7 +1270,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to all the @@ -1301,7 +1293,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses to be shown in OpenAPI. @@ -1317,7 +1309,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ OpenAPI callbacks that should apply to all *path operations* in this @@ -1331,7 +1323,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark all *path operations* in this router as deprecated. @@ -1554,7 +1546,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -1567,7 +1559,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -1580,7 +1572,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -1592,7 +1584,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -1605,7 +1597,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -1633,7 +1625,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -1643,7 +1635,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -1653,7 +1645,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -1673,7 +1665,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -1685,7 +1677,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -1787,7 +1779,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -1795,7 +1787,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -1811,7 +1803,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -1931,7 +1923,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -1944,7 +1936,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -1957,7 +1949,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -1969,7 +1961,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -1982,7 +1974,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2010,7 +2002,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2020,7 +2012,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2030,7 +2022,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2050,7 +2042,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2062,7 +2054,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2164,7 +2156,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2172,7 +2164,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2188,7 +2180,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -2313,7 +2305,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -2326,7 +2318,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -2339,7 +2331,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -2351,7 +2343,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -2364,7 +2356,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2392,7 +2384,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2402,7 +2394,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2412,7 +2404,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2432,7 +2424,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2444,7 +2436,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2546,7 +2538,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2554,7 +2546,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2570,7 +2562,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -2695,7 +2687,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -2708,7 +2700,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -2721,7 +2713,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -2733,7 +2725,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -2746,7 +2738,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -2774,7 +2766,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -2784,7 +2776,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -2794,7 +2786,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -2814,7 +2806,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -2826,7 +2818,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -2928,7 +2920,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -2936,7 +2928,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -2952,7 +2944,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3072,7 +3064,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3085,7 +3077,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3098,7 +3090,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3110,7 +3102,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3123,7 +3115,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3151,7 +3143,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3161,7 +3153,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3171,7 +3163,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3191,7 +3183,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3203,7 +3195,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -3305,7 +3297,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -3313,7 +3305,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -3329,7 +3321,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3449,7 +3441,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3462,7 +3454,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3475,7 +3467,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3487,7 +3479,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3500,7 +3492,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3528,7 +3520,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3538,7 +3530,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3548,7 +3540,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3568,7 +3560,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3580,7 +3572,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -3682,7 +3674,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -3690,7 +3682,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -3706,7 +3698,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -3831,7 +3823,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -3844,7 +3836,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -3857,7 +3849,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -3869,7 +3861,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -3882,7 +3874,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -3910,7 +3902,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -3920,7 +3912,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -3930,7 +3922,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -3950,7 +3942,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -3962,7 +3954,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -4064,7 +4056,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -4072,7 +4064,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -4088,7 +4080,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path @@ -4213,7 +4205,7 @@ class APIRouter(routing.Router): ), ] = Default(None), status_code: Annotated[ - Optional[int], + int | None, Doc( """ The default status code to be used for the response. @@ -4226,7 +4218,7 @@ class APIRouter(routing.Router): ), ] = None, tags: Annotated[ - Optional[list[Union[str, Enum]]], + list[str | Enum] | None, Doc( """ A list of tags to be applied to the *path operation*. @@ -4239,7 +4231,7 @@ class APIRouter(routing.Router): ), ] = None, dependencies: Annotated[ - Optional[Sequence[params.Depends]], + Sequence[params.Depends] | None, Doc( """ A list of dependencies (using `Depends()`) to be applied to the @@ -4251,7 +4243,7 @@ class APIRouter(routing.Router): ), ] = None, summary: Annotated[ - Optional[str], + str | None, Doc( """ A summary for the *path operation*. @@ -4264,7 +4256,7 @@ class APIRouter(routing.Router): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ A description for the *path operation*. @@ -4292,7 +4284,7 @@ class APIRouter(routing.Router): ), ] = "Successful Response", responses: Annotated[ - Optional[dict[Union[int, str], dict[str, Any]]], + dict[int | str, dict[str, Any]] | None, Doc( """ Additional responses that could be returned by this *path operation*. @@ -4302,7 +4294,7 @@ class APIRouter(routing.Router): ), ] = None, deprecated: Annotated[ - Optional[bool], + bool | None, Doc( """ Mark this *path operation* as deprecated. @@ -4312,7 +4304,7 @@ class APIRouter(routing.Router): ), ] = None, operation_id: Annotated[ - Optional[str], + str | None, Doc( """ Custom operation ID to be used by this *path operation*. @@ -4332,7 +4324,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_include: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to include only certain fields in the @@ -4344,7 +4336,7 @@ class APIRouter(routing.Router): ), ] = None, response_model_exclude: Annotated[ - Optional[IncEx], + IncEx | None, Doc( """ Configuration passed to Pydantic to exclude certain fields in the @@ -4446,7 +4438,7 @@ class APIRouter(routing.Router): ), ] = Default(JSONResponse), name: Annotated[ - Optional[str], + str | None, Doc( """ Name for this *path operation*. Only used internally. @@ -4454,7 +4446,7 @@ class APIRouter(routing.Router): ), ] = None, callbacks: Annotated[ - Optional[list[BaseRoute]], + list[BaseRoute] | None, Doc( """ List of *path operations* that will be used as OpenAPI callbacks. @@ -4470,7 +4462,7 @@ class APIRouter(routing.Router): ), ] = None, openapi_extra: Annotated[ - Optional[dict[str, Any]], + dict[str, Any] | None, Doc( """ Extra metadata to be included in the OpenAPI schema for this *path diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index 18dfb8e618..89358a9136 100644 --- a/fastapi/security/api_key.py +++ b/fastapi/security/api_key.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional, Union +from typing import Annotated from annotated_doc import Doc from fastapi.openapi.models import APIKey, APIKeyIn @@ -13,8 +13,8 @@ class APIKeyBase(SecurityBase): self, location: APIKeyIn, name: str, - description: Union[str, None], - scheme_name: Union[str, None], + description: str | None, + scheme_name: str | None, auto_error: bool, ): self.auto_error = auto_error @@ -42,7 +42,7 @@ class APIKeyBase(SecurityBase): headers={"WWW-Authenticate": "APIKey"}, ) - def check_api_key(self, api_key: Optional[str]) -> Optional[str]: + def check_api_key(self, api_key: str | None) -> str | None: if not api_key: if self.auto_error: raise self.make_not_authenticated_error() @@ -90,7 +90,7 @@ class APIKeyQuery(APIKeyBase): Doc("Query parameter name."), ], scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -100,7 +100,7 @@ class APIKeyQuery(APIKeyBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -137,7 +137,7 @@ class APIKeyQuery(APIKeyBase): auto_error=auto_error, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: api_key = request.query_params.get(self.model.name) return self.check_api_key(api_key) @@ -179,7 +179,7 @@ class APIKeyHeader(APIKeyBase): *, name: Annotated[str, Doc("Header name.")], scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -189,7 +189,7 @@ class APIKeyHeader(APIKeyBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -225,7 +225,7 @@ class APIKeyHeader(APIKeyBase): auto_error=auto_error, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: api_key = request.headers.get(self.model.name) return self.check_api_key(api_key) @@ -267,7 +267,7 @@ class APIKeyCookie(APIKeyBase): *, name: Annotated[str, Doc("Cookie name.")], scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -277,7 +277,7 @@ class APIKeyCookie(APIKeyBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -313,6 +313,6 @@ class APIKeyCookie(APIKeyBase): auto_error=auto_error, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: api_key = request.cookies.get(self.model.name) return self.check_api_key(api_key) diff --git a/fastapi/security/http.py b/fastapi/security/http.py index b4c3bc6d85..05299323cb 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -1,6 +1,6 @@ import binascii from base64 import b64decode -from typing import Annotated, Optional +from typing import Annotated from annotated_doc import Doc from fastapi.exceptions import HTTPException @@ -71,8 +71,8 @@ class HTTPBase(SecurityBase): self, *, scheme: str, - scheme_name: Optional[str] = None, - description: Optional[str] = None, + scheme_name: str | None = None, + description: str | None = None, auto_error: bool = True, ): self.model: HTTPBaseModel = HTTPBaseModel( @@ -91,9 +91,7 @@ class HTTPBase(SecurityBase): headers=self.make_authenticate_headers(), ) - async def __call__( - self, request: Request - ) -> Optional[HTTPAuthorizationCredentials]: + async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): @@ -143,7 +141,7 @@ class HTTPBasic(HTTPBase): self, *, scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -153,7 +151,7 @@ class HTTPBasic(HTTPBase): ), ] = None, realm: Annotated[ - Optional[str], + str | None, Doc( """ HTTP Basic authentication realm. @@ -161,7 +159,7 @@ class HTTPBasic(HTTPBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -203,7 +201,7 @@ class HTTPBasic(HTTPBase): async def __call__( # type: ignore self, request: Request - ) -> Optional[HTTPBasicCredentials]: + ) -> HTTPBasicCredentials | None: authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "basic": @@ -256,9 +254,9 @@ class HTTPBearer(HTTPBase): def __init__( self, *, - bearerFormat: Annotated[Optional[str], Doc("Bearer token format.")] = None, + bearerFormat: Annotated[str | None, Doc("Bearer token format.")] = None, scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -268,7 +266,7 @@ class HTTPBearer(HTTPBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -302,9 +300,7 @@ class HTTPBearer(HTTPBase): self.scheme_name = scheme_name or self.__class__.__name__ self.auto_error = auto_error - async def __call__( - self, request: Request - ) -> Optional[HTTPAuthorizationCredentials]: + async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): @@ -362,7 +358,7 @@ class HTTPDigest(HTTPBase): self, *, scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -372,7 +368,7 @@ class HTTPDigest(HTTPBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -405,9 +401,7 @@ class HTTPDigest(HTTPBase): self.scheme_name = scheme_name or self.__class__.__name__ self.auto_error = auto_error - async def __call__( - self, request: Request - ) -> Optional[HTTPAuthorizationCredentials]: + async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 58ffc5c762..661043ce7b 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -1,4 +1,4 @@ -from typing import Annotated, Any, Optional, Union, cast +from typing import Annotated, Any, cast from annotated_doc import Doc from fastapi.exceptions import HTTPException @@ -60,7 +60,7 @@ class OAuth2PasswordRequestForm: self, *, grant_type: Annotated[ - Union[str, None], + str | None, Form(pattern="^password$"), Doc( """ @@ -128,7 +128,7 @@ class OAuth2PasswordRequestForm: ), ] = "", client_id: Annotated[ - Union[str, None], + str | None, Form(), Doc( """ @@ -139,7 +139,7 @@ class OAuth2PasswordRequestForm: ), ] = None, client_secret: Annotated[ - Union[str, None], + str | None, Form(json_schema_extra={"format": "password"}), Doc( """ @@ -294,7 +294,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): ), ] = "", client_id: Annotated[ - Union[str, None], + str | None, Form(), Doc( """ @@ -305,7 +305,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): ), ] = None, client_secret: Annotated[ - Union[str, None], + str | None, Form(), Doc( """ @@ -344,7 +344,7 @@ class OAuth2(SecurityBase): self, *, flows: Annotated[ - Union[OAuthFlowsModel, dict[str, dict[str, Any]]], + OAuthFlowsModel | dict[str, dict[str, Any]], Doc( """ The dictionary of OAuth2 flows. @@ -352,7 +352,7 @@ class OAuth2(SecurityBase): ), ] = OAuthFlowsModel(), scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -362,7 +362,7 @@ class OAuth2(SecurityBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -420,7 +420,7 @@ class OAuth2(SecurityBase): headers={"WWW-Authenticate": "Bearer"}, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: authorization = request.headers.get("Authorization") if not authorization: if self.auto_error: @@ -454,7 +454,7 @@ class OAuth2PasswordBearer(OAuth2): ), ], scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -464,7 +464,7 @@ class OAuth2PasswordBearer(OAuth2): ), ] = None, scopes: Annotated[ - Optional[dict[str, str]], + dict[str, str] | None, Doc( """ The OAuth2 scopes that would be required by the *path operations* that @@ -476,7 +476,7 @@ class OAuth2PasswordBearer(OAuth2): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -506,7 +506,7 @@ class OAuth2PasswordBearer(OAuth2): ), ] = True, refreshUrl: Annotated[ - Optional[str], + str | None, Doc( """ The URL to refresh the token and obtain a new one. @@ -533,7 +533,7 @@ class OAuth2PasswordBearer(OAuth2): auto_error=auto_error, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "bearer": @@ -562,7 +562,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): ), ], refreshUrl: Annotated[ - Optional[str], + str | None, Doc( """ The URL to refresh the token and obtain a new one. @@ -570,7 +570,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): ), ] = None, scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -580,7 +580,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): ), ] = None, scopes: Annotated[ - Optional[dict[str, str]], + dict[str, str] | None, Doc( """ The OAuth2 scopes that would be required by the *path operations* that @@ -589,7 +589,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -639,7 +639,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): auto_error=auto_error, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "bearer": @@ -666,7 +666,7 @@ class SecurityScopes: def __init__( self, scopes: Annotated[ - Optional[list[str]], + list[str] | None, Doc( """ This will be filled by FastAPI. diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py index f4d953351e..1c6fcc7440 100644 --- a/fastapi/security/open_id_connect_url.py +++ b/fastapi/security/open_id_connect_url.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated from annotated_doc import Doc from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel @@ -31,7 +31,7 @@ class OpenIdConnect(SecurityBase): ), ], scheme_name: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme name. @@ -41,7 +41,7 @@ class OpenIdConnect(SecurityBase): ), ] = None, description: Annotated[ - Optional[str], + str | None, Doc( """ Security scheme description. @@ -84,7 +84,7 @@ class OpenIdConnect(SecurityBase): headers={"WWW-Authenticate": "Bearer"}, ) - async def __call__(self, request: Request) -> Optional[str]: + async def __call__(self, request: Request) -> str | None: authorization = request.headers.get("Authorization") if not authorization: if self.auto_error: diff --git a/fastapi/security/utils.py b/fastapi/security/utils.py index fd349aec74..8ee66fd381 100644 --- a/fastapi/security/utils.py +++ b/fastapi/security/utils.py @@ -1,8 +1,5 @@ -from typing import Optional - - def get_authorization_scheme_param( - authorization_header_value: Optional[str], + authorization_header_value: str | None, ) -> tuple[str, str]: if not authorization_header_value: return "", "" diff --git a/fastapi/types.py b/fastapi/types.py index 1c3a6de749..1fb86e13b1 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -1,11 +1,12 @@ import types +from collections.abc import Callable from enum import Enum -from typing import Any, Callable, Optional, TypeVar, Union +from typing import Any, TypeVar, Union from pydantic import BaseModel from pydantic.main import IncEx as IncEx DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) UnionType = getattr(types, "UnionType", Union) -ModelNameMap = dict[Union[type[BaseModel], type[Enum]], str] -DependencyCacheKey = tuple[Optional[Callable[..., Any]], tuple[str, ...], str] +ModelNameMap = dict[type[BaseModel] | type[Enum], str] +DependencyCacheKey = tuple[Callable[..., Any] | None, tuple[str, ...], str] diff --git a/fastapi/utils.py b/fastapi/utils.py index 28c7cdfccb..12eaa2bf08 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -3,8 +3,7 @@ import warnings from typing import ( TYPE_CHECKING, Any, - Optional, - Union, + Literal, ) import fastapi @@ -17,7 +16,6 @@ from fastapi._compat import ( from fastapi.datastructures import DefaultPlaceholder, DefaultType from fastapi.exceptions import FastAPIDeprecationWarning, PydanticV1NotSupportedError from pydantic.fields import FieldInfo -from typing_extensions import Literal from ._compat import v2 @@ -25,7 +23,7 @@ if TYPE_CHECKING: # pragma: nocover from .routing import APIRoute -def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: +def is_body_allowed_for_status_code(status_code: int | str | None) -> bool: if status_code is None: return True # Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1 @@ -60,9 +58,9 @@ _invalid_args_message = ( def create_model_field( name: str, type_: Any, - default: Optional[Any] = Undefined, - field_info: Optional[FieldInfo] = None, - alias: Optional[str] = None, + default: Any | None = Undefined, + field_info: FieldInfo | None = None, + alias: str | None = None, mode: Literal["validation", "serialization"] = "validation", ) -> ModelField: if annotation_is_pydantic_v1(type_): @@ -121,9 +119,9 @@ def deep_dict_update(main_dict: dict[Any, Any], update_dict: dict[Any, Any]) -> def get_value_or_default( - first_item: Union[DefaultPlaceholder, DefaultType], - *extra_items: Union[DefaultPlaceholder, DefaultType], -) -> Union[DefaultPlaceholder, DefaultType]: + first_item: DefaultPlaceholder | DefaultType, + *extra_items: DefaultPlaceholder | DefaultType, +) -> DefaultPlaceholder | DefaultType: """ Pass items or `DefaultPlaceholder`s by descending priority. From d06ab3f5c7c1b6229e28af37905eb51ab4b4cdb7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 11 Feb 2026 18:41:46 +0000 Subject: [PATCH 207/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e0ca3de72e..7640bd6fa7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * โž– Drop support for Python 3.9. PR [#14897](https://github.com/fastapi/fastapi/pull/14897) by [@tiangolo](https://github.com/tiangolo). +### Refactors + +* ๐ŸŽจ Update internal types for Python 3.10. PR [#14898](https://github.com/fastapi/fastapi/pull/14898) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.8 ### Docs From c9e2277d8b3b0feead4bdad97fca7cf05c9263fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 12 Feb 2026 05:19:43 -0800 Subject: [PATCH 208/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20source=20exampl?= =?UTF-8?q?es=20and=20docs=20from=20Python=203.9=20to=203.10=20(#14900)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/additional-responses.md | 4 +- .../en/docs/advanced/advanced-dependencies.md | 8 +- docs/en/docs/advanced/async-tests.md | 8 +- docs/en/docs/advanced/behind-a-proxy.md | 12 +- docs/en/docs/advanced/custom-response.md | 32 +-- docs/en/docs/advanced/events.md | 12 +- docs/en/docs/advanced/generate-clients.md | 8 +- docs/en/docs/advanced/middleware.md | 6 +- docs/en/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 14 +- .../advanced/response-change-status-code.md | 2 +- docs/en/docs/advanced/response-cookies.md | 4 +- docs/en/docs/advanced/response-directly.md | 2 +- docs/en/docs/advanced/response-headers.md | 4 +- .../docs/advanced/security/http-basic-auth.md | 6 +- docs/en/docs/advanced/settings.md | 20 +- docs/en/docs/advanced/sub-applications.md | 6 +- docs/en/docs/advanced/templates.md | 2 +- docs/en/docs/advanced/testing-events.md | 4 +- docs/en/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/en/docs/advanced/websockets.md | 8 +- docs/en/docs/advanced/wsgi.md | 2 +- .../authentication-error-status-code.md | 2 +- docs/en/docs/how-to/conditional-openapi.md | 2 +- docs/en/docs/how-to/configure-swagger-ui.md | 6 +- docs/en/docs/how-to/custom-docs-ui-assets.md | 14 +- docs/en/docs/how-to/extending-openapi.md | 10 +- docs/en/docs/how-to/graphql.md | 2 +- docs/en/docs/python-types.md | 24 +- docs/en/docs/tutorial/background-tasks.md | 6 +- docs/en/docs/tutorial/bigger-applications.md | 26 +- docs/en/docs/tutorial/body-nested-models.md | 4 +- docs/en/docs/tutorial/cors.md | 2 +- docs/en/docs/tutorial/debugging.md | 2 +- ...pendencies-in-path-operation-decorators.md | 8 +- .../dependencies/dependencies-with-yield.md | 22 +- .../dependencies/global-dependencies.md | 2 +- docs/en/docs/tutorial/extra-models.md | 4 +- docs/en/docs/tutorial/first-steps.md | 14 +- docs/en/docs/tutorial/handling-errors.md | 16 +- docs/en/docs/tutorial/metadata.md | 12 +- docs/en/docs/tutorial/middleware.md | 4 +- .../tutorial/path-operation-configuration.md | 4 +- .../path-params-numeric-validations.md | 14 +- docs/en/docs/tutorial/path-params.md | 20 +- .../tutorial/query-params-str-validations.md | 8 +- docs/en/docs/tutorial/query-params.md | 4 +- docs/en/docs/tutorial/request-files.md | 12 +- docs/en/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/en/docs/tutorial/request-forms.md | 4 +- docs/en/docs/tutorial/response-model.md | 4 +- docs/en/docs/tutorial/response-status-code.md | 6 +- docs/en/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/en/docs/tutorial/static-files.md | 2 +- docs/en/docs/tutorial/testing.md | 6 +- .../additional_responses/tutorial001_py310.py | 22 ++ .../additional_responses/tutorial002_py39.py | 30 --- .../additional_responses/tutorial003_py310.py | 37 +++ .../additional_responses/tutorial004_py39.py | 32 --- .../tutorial001_an_py39.py | 25 -- .../tutorial001_py39.py | 25 -- .../advanced_middleware/tutorial001_py310.py | 11 + .../advanced_middleware/tutorial002_py310.py | 13 + .../advanced_middleware/tutorial003_py310.py | 11 + .../__init__.py | 0 docs_src/app_testing/app_a_py310/main.py | 8 + docs_src/app_testing/app_a_py310/test_main.py | 11 + docs_src/app_testing/app_b_an_py39/main.py | 38 --- .../app_testing/app_b_an_py39/test_main.py | 65 ----- docs_src/app_testing/app_b_py39/main.py | 38 --- docs_src/app_testing/app_b_py39/test_main.py | 65 ----- docs_src/app_testing/tutorial001_py310.py | 18 ++ docs_src/app_testing/tutorial002_py310.py | 31 +++ docs_src/app_testing/tutorial003_py310.py | 24 ++ docs_src/app_testing/tutorial004_py310.py | 43 ++++ .../app_a_py310}/__init__.py | 0 docs_src/async_tests/app_a_py310/main.py | 8 + docs_src/async_tests/app_a_py310/test_main.py | 14 + .../tutorial001_an_py310.py | 21 ++ .../background_tasks/tutorial001_py310.py | 15 ++ .../background_tasks/tutorial002_an_py39.py | 26 -- docs_src/background_tasks/tutorial002_py39.py | 26 -- .../behind_a_proxy/tutorial001_01_py310.py | 8 + docs_src/behind_a_proxy/tutorial001_py310.py | 8 + docs_src/behind_a_proxy/tutorial002_py310.py | 8 + docs_src/behind_a_proxy/tutorial003_py310.py | 14 + docs_src/behind_a_proxy/tutorial004_py310.py | 15 ++ .../internal => app_an_py310}/__init__.py | 0 .../app_an_py310/dependencies.py | 13 + .../internal}/__init__.py | 0 .../internal/admin.py | 0 .../bigger_applications/app_an_py310/main.py | 23 ++ .../app_an_py310/routers/__init__.py | 0 .../routers/items.py | 0 .../routers/users.py | 0 docs_src/body/tutorial001_py39.py | 19 -- docs_src/body/tutorial002_py39.py | 23 -- docs_src/body/tutorial003_py39.py | 19 -- docs_src/body/tutorial004_py39.py | 22 -- docs_src/body_fields/tutorial001_an_py39.py | 21 -- docs_src/body_fields/tutorial001_py39.py | 21 -- .../tutorial001_an_py39.py | 27 -- .../body_multiple_params/tutorial001_py39.py | 28 -- .../body_multiple_params/tutorial002_py39.py | 24 -- .../tutorial003_an_py39.py | 26 -- .../body_multiple_params/tutorial003_py39.py | 24 -- .../tutorial004_an_py39.py | 33 --- .../body_multiple_params/tutorial004_py39.py | 33 --- .../tutorial005_an_py39.py | 19 -- .../body_multiple_params/tutorial005_py39.py | 19 -- .../body_nested_models/tutorial001_py39.py | 20 -- .../body_nested_models/tutorial002_py39.py | 20 -- .../body_nested_models/tutorial003_py39.py | 20 -- .../body_nested_models/tutorial004_py39.py | 26 -- .../body_nested_models/tutorial005_py39.py | 26 -- .../body_nested_models/tutorial006_py39.py | 26 -- .../body_nested_models/tutorial007_py39.py | 32 --- .../body_nested_models/tutorial008_py310.py | 14 + .../body_nested_models/tutorial009_py310.py | 8 + docs_src/body_updates/tutorial001_py39.py | 34 --- docs_src/body_updates/tutorial002_py39.py | 37 --- .../conditional_openapi/tutorial001_py310.py | 16 ++ .../configure_swagger_ui/tutorial001_py310.py | 8 + .../configure_swagger_ui/tutorial002_py310.py | 8 + .../configure_swagger_ui/tutorial003_py310.py | 8 + .../tutorial001_an_py39.py | 17 -- .../cookie_param_models/tutorial001_py39.py | 17 -- .../tutorial002_an_py39.py | 19 -- .../cookie_param_models/tutorial002_py39.py | 19 -- docs_src/cookie_params/tutorial001_an_py39.py | 10 - docs_src/cookie_params/tutorial001_py39.py | 10 - docs_src/cors/tutorial001_py310.py | 24 ++ docs_src/custom_docs_ui/tutorial001_py310.py | 38 +++ docs_src/custom_docs_ui/tutorial002_py310.py | 41 +++ .../tutorial001_an_py39.py | 35 --- .../tutorial001_py39.py | 35 --- .../tutorial002_an_py39.py | 29 --- .../tutorial002_py39.py | 29 --- .../tutorial003_py39.py | 39 --- docs_src/custom_response/tutorial001_py310.py | 9 + .../custom_response/tutorial001b_py310.py | 9 + docs_src/custom_response/tutorial002_py310.py | 18 ++ docs_src/custom_response/tutorial003_py310.py | 19 ++ docs_src/custom_response/tutorial004_py310.py | 23 ++ docs_src/custom_response/tutorial005_py310.py | 9 + docs_src/custom_response/tutorial006_py310.py | 9 + .../custom_response/tutorial006b_py310.py | 9 + .../custom_response/tutorial006c_py310.py | 9 + docs_src/custom_response/tutorial007_py310.py | 14 + docs_src/custom_response/tutorial008_py310.py | 14 + docs_src/custom_response/tutorial009_py310.py | 10 + .../custom_response/tutorial009b_py310.py | 10 + .../custom_response/tutorial009c_py310.py | 19 ++ docs_src/custom_response/tutorial010_py310.py | 9 + docs_src/dataclasses_/tutorial001_py39.py | 20 -- docs_src/dataclasses_/tutorial002_py39.py | 26 -- docs_src/dataclasses_/tutorial003_py39.py | 55 ---- docs_src/debugging/tutorial001_py310.py | 15 ++ .../dependencies/tutorial001_02_an_py39.py | 24 -- docs_src/dependencies/tutorial001_an_py39.py | 21 -- docs_src/dependencies/tutorial001_py39.py | 21 -- docs_src/dependencies/tutorial002_an_py39.py | 25 -- docs_src/dependencies/tutorial002_py39.py | 25 -- docs_src/dependencies/tutorial003_an_py39.py | 25 -- docs_src/dependencies/tutorial003_py39.py | 25 -- docs_src/dependencies/tutorial004_an_py39.py | 25 -- docs_src/dependencies/tutorial004_py39.py | 25 -- docs_src/dependencies/tutorial005_an_py39.py | 25 -- docs_src/dependencies/tutorial005_py39.py | 23 -- docs_src/dependencies/tutorial006_an_py310.py | 21 ++ docs_src/dependencies/tutorial006_py310.py | 19 ++ docs_src/dependencies/tutorial007_py310.py | 6 + docs_src/dependencies/tutorial008_an_py310.py | 27 ++ docs_src/dependencies/tutorial008_py310.py | 25 ++ .../dependencies/tutorial008b_an_py310.py | 32 +++ docs_src/dependencies/tutorial008b_py310.py | 30 +++ .../dependencies/tutorial008c_an_py310.py | 29 +++ docs_src/dependencies/tutorial008c_py310.py | 27 ++ .../dependencies/tutorial008d_an_py310.py | 30 +++ docs_src/dependencies/tutorial008d_py310.py | 28 ++ .../dependencies/tutorial008e_an_py310.py | 17 ++ docs_src/dependencies/tutorial008e_py310.py | 15 ++ docs_src/dependencies/tutorial010_py310.py | 14 + docs_src/dependencies/tutorial011_an_py310.py | 23 ++ docs_src/dependencies/tutorial011_py310.py | 21 ++ docs_src/dependencies/tutorial012_an_py310.py | 27 ++ docs_src/dependencies/tutorial012_py310.py | 25 ++ .../dependency_testing/tutorial001_an_py39.py | 59 ----- .../dependency_testing/tutorial001_py39.py | 59 ----- docs_src/encoder/tutorial001_py39.py | 23 -- docs_src/events/tutorial001_py310.py | 16 ++ docs_src/events/tutorial002_py310.py | 14 + docs_src/events/tutorial003_py310.py | 28 ++ .../extending_openapi/tutorial001_py310.py | 29 +++ .../extra_data_types/tutorial001_an_py39.py | 28 -- docs_src/extra_data_types/tutorial001_py39.py | 28 -- docs_src/extra_models/tutorial001_py39.py | 43 ---- docs_src/extra_models/tutorial002_py39.py | 41 --- docs_src/extra_models/tutorial003_py39.py | 35 --- docs_src/extra_models/tutorial004_py310.py | 20 ++ docs_src/extra_models/tutorial005_py310.py | 8 + docs_src/first_steps/tutorial001_py310.py | 8 + docs_src/first_steps/tutorial003_py310.py | 8 + .../generate_clients/tutorial001_py310.py | 26 ++ .../generate_clients/tutorial002_py310.py | 36 +++ .../generate_clients/tutorial003_py310.py | 42 +++ .../generate_clients/tutorial004_py310.py | 15 ++ docs_src/graphql_/tutorial001_py310.py | 25 ++ docs_src/handling_errors/tutorial001_py310.py | 12 + docs_src/handling_errors/tutorial002_py310.py | 16 ++ docs_src/handling_errors/tutorial003_py310.py | 25 ++ docs_src/handling_errors/tutorial004_py310.py | 26 ++ docs_src/handling_errors/tutorial005_py310.py | 25 ++ docs_src/handling_errors/tutorial006_py310.py | 28 ++ .../tutorial001_an_py39.py | 19 -- .../header_param_models/tutorial001_py39.py | 19 -- .../tutorial002_an_py39.py | 21 -- .../header_param_models/tutorial002_py39.py | 21 -- .../tutorial003_an_py39.py | 21 -- .../header_param_models/tutorial003_py39.py | 19 -- docs_src/header_params/tutorial001_an_py39.py | 10 - docs_src/header_params/tutorial001_py39.py | 10 - docs_src/header_params/tutorial002_an_py39.py | 14 - docs_src/header_params/tutorial002_py39.py | 12 - docs_src/header_params/tutorial003_an_py39.py | 10 - docs_src/header_params/tutorial003_py39.py | 10 - docs_src/metadata/tutorial001_1_py310.py | 38 +++ docs_src/metadata/tutorial001_py310.py | 38 +++ docs_src/metadata/tutorial002_py310.py | 8 + docs_src/metadata/tutorial003_py310.py | 8 + docs_src/metadata/tutorial004_py310.py | 28 ++ docs_src/middleware/tutorial001_py310.py | 14 + .../openapi_callbacks/tutorial001_py39.py | 53 ---- .../openapi_webhooks/tutorial001_py310.py | 25 ++ .../tutorial001_py310.py | 8 + .../tutorial002_py310.py | 24 ++ .../tutorial003_py310.py | 8 + .../tutorial004_py39.py | 30 --- .../tutorial005_py310.py | 8 + .../tutorial006_py310.py | 41 +++ ...al007_pv1_py39.py => tutorial007_py310.py} | 8 +- .../tutorial001_py39.py | 19 -- .../tutorial002_py39.py | 29 --- .../tutorial002b_py310.py | 20 ++ .../tutorial003_py39.py | 23 -- .../tutorial004_py39.py | 28 -- .../tutorial005_py39.py | 32 --- .../tutorial006_py310.py | 18 ++ docs_src/path_params/tutorial001_py310.py | 8 + docs_src/path_params/tutorial002_py310.py | 8 + docs_src/path_params/tutorial003_py310.py | 13 + docs_src/path_params/tutorial003b_py310.py | 13 + docs_src/path_params/tutorial004_py310.py | 8 + docs_src/path_params/tutorial005_py310.py | 23 ++ .../tutorial002_an_py310.py | 15 ++ .../tutorial002_py310.py | 11 + .../tutorial003_an_py310.py | 15 ++ .../tutorial003_py310.py | 11 + .../tutorial004_an_py310.py | 15 ++ .../tutorial004_py310.py | 13 + .../tutorial005_an_py310.py | 16 ++ .../tutorial005_py310.py | 15 ++ ...001_an_py39.py => tutorial006_an_py310.py} | 10 +- ...torial001_py39.py => tutorial006_py310.py} | 10 +- .../pydantic_v1_in_v2/tutorial001_an_py39.py | 9 - .../pydantic_v1_in_v2/tutorial002_an_py39.py | 18 -- .../pydantic_v1_in_v2/tutorial003_an_py39.py | 25 -- .../pydantic_v1_in_v2/tutorial004_an_py39.py | 19 -- docs_src/python_types/tutorial001_py310.py | 6 + docs_src/python_types/tutorial002_py310.py | 6 + docs_src/python_types/tutorial003_py310.py | 3 + docs_src/python_types/tutorial004_py310.py | 3 + docs_src/python_types/tutorial005_py310.py | 2 + docs_src/python_types/tutorial006_py310.py | 3 + docs_src/python_types/tutorial007_py310.py | 2 + docs_src/python_types/tutorial008_py310.py | 4 + docs_src/python_types/tutorial010_py310.py | 7 + docs_src/python_types/tutorial011_py39.py | 23 -- docs_src/python_types/tutorial012_py39.py | 8 - docs_src/python_types/tutorial013_py310.py | 5 + .../query_param_models/tutorial001_an_py39.py | 18 -- .../query_param_models/tutorial001_py39.py | 18 -- .../query_param_models/tutorial002_an_py39.py | 20 -- .../query_param_models/tutorial002_py39.py | 20 -- docs_src/query_params/tutorial001_py310.py | 10 + docs_src/query_params/tutorial002_py39.py | 12 - docs_src/query_params/tutorial003_py39.py | 17 -- docs_src/query_params/tutorial004_py39.py | 19 -- docs_src/query_params/tutorial005_py310.py | 9 + docs_src/query_params/tutorial006_py39.py | 13 - .../tutorial001_py39.py | 13 - .../tutorial002_an_py39.py | 13 - .../tutorial003_an_py39.py | 15 -- .../tutorial003_py39.py | 15 -- .../tutorial004_an_py39.py | 17 -- .../tutorial004_py39.py | 17 -- .../tutorial004_regex_an_py310.py | 17 -- ...ial002_py39.py => tutorial005_an_py310.py} | 4 +- ...torial009_py39.py => tutorial005_py310.py} | 4 +- ...al006c_py39.py => tutorial006_an_py310.py} | 4 +- ...al006c_an_py39.py => tutorial006_py310.py} | 4 +- .../tutorial007_an_py39.py | 15 -- .../tutorial007_py39.py | 15 -- .../tutorial008_an_py39.py | 22 -- .../tutorial008_py39.py | 20 -- .../tutorial009_an_py39.py | 13 - .../tutorial010_an_py39.py | 26 -- .../tutorial010_py39.py | 24 -- ...011_an_py39.py => tutorial012_an_py310.py} | 4 +- .../tutorial012_py310.py | 9 + ...ial011_py39.py => tutorial013_an_py310.py} | 4 +- .../tutorial013_py310.py | 9 + .../tutorial014_an_py39.py | 15 -- .../tutorial014_py39.py | 15 -- .../tutorial015_an_py39.py | 30 --- .../request_files/tutorial001_02_an_py39.py | 21 -- docs_src/request_files/tutorial001_02_py39.py | 21 -- .../request_files/tutorial001_03_an_py310.py | 17 ++ .../request_files/tutorial001_03_py310.py | 15 ++ .../request_files/tutorial001_an_py310.py | 15 ++ docs_src/request_files/tutorial001_py310.py | 13 + .../request_files/tutorial002_an_py310.py | 33 +++ docs_src/request_files/tutorial002_py310.py | 31 +++ .../request_files/tutorial003_an_py310.py | 39 +++ docs_src/request_files/tutorial003_py310.py | 35 +++ .../tutorial001_an_py310.py | 16 ++ .../request_form_models/tutorial001_py310.py | 14 + .../tutorial002_an_py310.py | 17 ++ .../request_form_models/tutorial002_py310.py | 15 ++ .../request_forms/tutorial001_an_py310.py | 10 + docs_src/request_forms/tutorial001_py310.py | 8 + .../tutorial001_an_py310.py | 18 ++ .../tutorial001_py310.py | 14 + .../tutorial001_py310.py | 13 + .../response_cookies/tutorial001_py310.py | 12 + .../response_cookies/tutorial002_py310.py | 9 + .../response_directly/tutorial001_py39.py | 22 -- .../response_directly/tutorial002_py310.py | 18 ++ .../response_headers/tutorial001_py310.py | 11 + .../response_headers/tutorial002_py310.py | 9 + .../response_model/tutorial001_01_py39.py | 27 -- docs_src/response_model/tutorial001_py39.py | 27 -- docs_src/response_model/tutorial002_py39.py | 19 -- .../response_model/tutorial003_01_py39.py | 21 -- .../response_model/tutorial003_02_py310.py | 11 + .../response_model/tutorial003_03_py310.py | 9 + .../response_model/tutorial003_04_py39.py | 13 - .../response_model/tutorial003_05_py39.py | 13 - docs_src/response_model/tutorial003_py39.py | 24 -- docs_src/response_model/tutorial004_py39.py | 26 -- docs_src/response_model/tutorial005_py39.py | 39 --- docs_src/response_model/tutorial006_py39.py | 39 --- .../response_status_code/tutorial001_py310.py | 8 + .../response_status_code/tutorial002_py310.py | 8 + .../tutorial001_pv1_py310.py | 29 --- .../tutorial001_pv1_py39.py | 31 --- .../schema_extra_example/tutorial001_py39.py | 32 --- .../schema_extra_example/tutorial002_py39.py | 19 -- .../tutorial003_an_py39.py | 34 --- .../schema_extra_example/tutorial003_py39.py | 31 --- .../tutorial004_an_py39.py | 43 ---- .../schema_extra_example/tutorial004_py39.py | 40 --- .../tutorial005_an_py39.py | 54 ---- .../schema_extra_example/tutorial005_py39.py | 51 ---- docs_src/security/tutorial001_an_py310.py | 13 + docs_src/security/tutorial001_py310.py | 11 + docs_src/security/tutorial002_an_py39.py | 32 --- docs_src/security/tutorial002_py39.py | 32 --- docs_src/security/tutorial003_an_py39.py | 94 ------- docs_src/security/tutorial003_py39.py | 90 ------- docs_src/security/tutorial004_an_py39.py | 147 ----------- docs_src/security/tutorial004_py39.py | 141 ---------- docs_src/security/tutorial005_an_py39.py | 179 ------------- docs_src/security/tutorial005_py39.py | 177 ------------- docs_src/security/tutorial006_an_py310.py | 13 + docs_src/security/tutorial006_py310.py | 11 + docs_src/security/tutorial007_an_py310.py | 36 +++ docs_src/security/tutorial007_py310.py | 33 +++ .../tutorial001_py39.py | 28 -- .../tutorial002_py39.py | 28 -- docs_src/settings/app01_py310/__init__.py | 0 .../config_pv1.py => app01_py310/config.py} | 6 +- docs_src/settings/app01_py310/main.py | 14 + docs_src/settings/app02_an_py310/__init__.py | 0 .../config.py} | 5 +- docs_src/settings/app02_an_py310/main.py | 22 ++ docs_src/settings/app02_an_py310/test_main.py | 23 ++ docs_src/settings/app02_py310/__init__.py | 0 docs_src/settings/app02_py310/config.py | 7 + docs_src/settings/app02_py310/main.py | 21 ++ docs_src/settings/app02_py310/test_main.py | 23 ++ docs_src/settings/app03_an_py310/__init__.py | 0 docs_src/settings/app03_an_py310/config.py | 9 + docs_src/settings/app03_an_py310/main.py | 22 ++ docs_src/settings/app03_py310/__init__.py | 0 docs_src/settings/app03_py310/config.py | 9 + docs_src/settings/app03_py310/main.py | 21 ++ ...al001_pv1_py39.py => tutorial001_py310.py} | 2 +- docs_src/sql_databases/tutorial001_an_py39.py | 73 ------ docs_src/sql_databases/tutorial001_py39.py | 71 ----- docs_src/sql_databases/tutorial002_an_py39.py | 103 -------- docs_src/sql_databases/tutorial002_py39.py | 104 -------- docs_src/static_files/tutorial001_py310.py | 6 + .../sub_applications/tutorial001_py310.py | 19 ++ docs_src/templates/tutorial001_py310.py | 18 ++ .../tutorial001_py310.py | 9 + docs_src/websockets/tutorial001_py310.py | 51 ++++ docs_src/websockets/tutorial002_an_py39.py | 92 ------- docs_src/websockets/tutorial002_py39.py | 91 ------- docs_src/websockets/tutorial003_py310.py | 81 ++++++ docs_src/wsgi/tutorial001_py310.py | 23 ++ pyproject.toml | 243 ++++++++++++++++-- .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 1 - .../test_tutorial003.py | 2 +- .../test_tutorial004.py | 1 - .../test_tutorial001.py | 2 - .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 2 +- .../test_tutorial003.py | 2 +- .../test_async_tests/test_main_a.py | 2 +- .../test_tutorial001.py | 2 +- .../test_background_tasks/test_tutorial001.py | 2 +- .../test_background_tasks/test_tutorial002.py | 2 - .../test_behind_a_proxy/test_tutorial001.py | 2 +- .../test_tutorial001_01.py | 2 +- .../test_behind_a_proxy/test_tutorial002.py | 2 +- .../test_behind_a_proxy/test_tutorial003.py | 2 +- .../test_behind_a_proxy/test_tutorial004.py | 2 +- .../test_bigger_applications/test_main.py | 3 +- .../test_body/test_tutorial001.py | 1 - .../test_body/test_tutorial002.py | 6 +- .../test_body/test_tutorial003.py | 1 - .../test_body/test_tutorial004.py | 1 - .../test_body_fields/test_tutorial001.py | 2 - .../test_tutorial001.py | 2 - .../test_tutorial002.py | 1 - .../test_tutorial003.py | 2 - .../test_tutorial004.py | 2 - .../test_tutorial005.py | 2 - ...est_tutorial001_tutorial002_tutorial003.py | 3 - .../test_tutorial004.py | 1 - .../test_tutorial005.py | 1 - .../test_tutorial006.py | 1 - .../test_tutorial007.py | 1 - .../test_tutorial008.py | 2 +- .../test_tutorial009.py | 2 +- .../test_body_updates/test_tutorial001.py | 1 - .../test_body_updates/test_tutorial002.py | 1 - .../test_tutorial001.py | 6 +- .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 2 +- .../test_tutorial003.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial002.py | 2 - .../test_cookie_params/test_tutorial001.py | 2 - .../test_cors/test_tutorial001.py | 2 +- .../test_custom_docs_ui/test_tutorial001.py | 2 +- .../test_custom_docs_ui/test_tutorial002.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial002.py | 2 - .../test_tutorial003.py | 1 - .../test_custom_response/test_tutorial001.py | 4 +- .../test_custom_response/test_tutorial001b.py | 2 +- ...est_tutorial002_tutorial003_tutorial004.py | 6 +- .../test_custom_response/test_tutorial005.py | 2 +- .../test_custom_response/test_tutorial006.py | 2 +- .../test_custom_response/test_tutorial006b.py | 2 +- .../test_custom_response/test_tutorial006c.py | 2 +- .../test_custom_response/test_tutorial007.py | 2 +- .../test_custom_response/test_tutorial008.py | 6 +- .../test_custom_response/test_tutorial009.py | 6 +- .../test_custom_response/test_tutorial009b.py | 6 +- .../test_custom_response/test_tutorial009c.py | 2 +- .../test_dataclasses/test_tutorial001.py | 1 - .../test_dataclasses/test_tutorial002.py | 1 - .../test_dataclasses/test_tutorial003.py | 1 - .../test_debugging/test_tutorial001.py | 2 +- .../test_tutorial001_tutorial001_02.py | 3 - ...est_tutorial002_tutorial003_tutorial004.py | 6 - .../test_dependencies/test_tutorial005.py | 2 - .../test_dependencies/test_tutorial006.py | 4 +- .../test_dependencies/test_tutorial007.py | 4 +- .../test_dependencies/test_tutorial008.py | 4 +- .../test_dependencies/test_tutorial008b.py | 4 +- .../test_dependencies/test_tutorial008c.py | 4 +- .../test_dependencies/test_tutorial008d.py | 4 +- .../test_dependencies/test_tutorial008e.py | 4 +- .../test_dependencies/test_tutorial010.py | 4 +- .../test_dependencies/test_tutorial011.py | 4 +- .../test_dependencies/test_tutorial012.py | 4 +- .../test_encoder/test_tutorial001.py | 1 - .../test_events/test_tutorial001.py | 2 +- .../test_events/test_tutorial002.py | 2 +- .../test_events/test_tutorial003.py | 2 +- .../test_tutorial001.py | 2 +- .../test_extra_data_types/test_tutorial001.py | 2 - .../test_tutorial001_tutorial002.py | 2 - .../test_extra_models/test_tutorial003.py | 1 - .../test_extra_models/test_tutorial004.py | 2 +- .../test_extra_models/test_tutorial005.py | 2 +- ...est_tutorial001_tutorial002_tutorial003.py | 4 +- .../test_generate_clients/test_tutorial001.py | 2 +- .../test_generate_clients/test_tutorial002.py | 2 +- .../test_generate_clients/test_tutorial003.py | 2 +- .../test_generate_clients/test_tutorial004.py | 6 +- .../test_graphql/test_tutorial001.py | 2 +- .../test_handling_errors/test_tutorial001.py | 2 +- .../test_handling_errors/test_tutorial002.py | 2 +- .../test_handling_errors/test_tutorial003.py | 2 +- .../test_handling_errors/test_tutorial004.py | 2 +- .../test_handling_errors/test_tutorial005.py | 2 +- .../test_handling_errors/test_tutorial006.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial002.py | 2 - .../test_tutorial003.py | 2 - .../test_header_params/test_tutorial001.py | 2 - .../test_header_params/test_tutorial002.py | 2 - .../test_header_params/test_tutorial003.py | 2 - .../test_metadata/test_tutorial001.py | 2 +- .../test_metadata/test_tutorial001_1.py | 2 +- .../test_metadata/test_tutorial002.py | 2 +- .../test_metadata/test_tutorial003.py | 2 +- .../test_metadata/test_tutorial004.py | 2 +- .../test_middleware/test_tutorial001.py | 2 +- .../test_tutorial001.py | 1 - .../test_openapi_webhooks/test_tutorial001.py | 2 +- .../test_tutorial001.py | 2 +- .../test_tutorial002.py | 2 +- .../test_tutorial003.py | 2 +- .../test_tutorial004.py | 1 - .../test_tutorial005.py | 2 +- .../test_tutorial006.py | 2 +- .../test_tutorial007.py | 2 +- .../test_tutorial001.py | 1 - .../test_tutorial002.py | 1 - .../test_tutorial002b.py | 2 +- .../test_tutorial003_tutorial004.py | 2 - .../test_tutorial005.py | 1 - .../test_tutorial006.py | 2 +- .../test_path_params/test_tutorial001.py | 2 +- .../test_path_params/test_tutorial002.py | 2 +- .../test_path_params/test_tutorial003.py | 2 +- .../test_path_params/test_tutorial003b.py | 2 +- .../test_path_params/test_tutorial004.py | 2 +- .../test_path_params/test_tutorial005.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial002_tutorial003.py | 8 +- .../test_tutorial004.py | 4 +- .../test_tutorial005.py | 4 +- .../test_tutorial006.py | 4 +- .../test_tutorial001_tutorial002.py | 4 +- .../test_python_types/test_tutorial003.py | 2 +- .../test_python_types/test_tutorial004.py | 2 +- .../test_python_types/test_tutorial005.py | 2 +- .../test_python_types/test_tutorial006.py | 2 +- .../test_python_types/test_tutorial007.py | 2 +- .../test_python_types/test_tutorial008.py | 2 +- .../test_python_types/test_tutorial008b.py | 2 +- .../test_tutorial009_tutorial009b.py | 3 +- .../test_python_types/test_tutorial009c.py | 2 +- .../test_python_types/test_tutorial010.py | 2 +- .../test_python_types/test_tutorial011.py | 1 - .../test_python_types/test_tutorial012.py | 7 - .../test_python_types/test_tutorial013.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial002.py | 2 - .../test_query_params/test_tutorial001.py | 2 +- .../test_query_params/test_tutorial002.py | 1 - .../test_query_params/test_tutorial003.py | 1 - .../test_query_params/test_tutorial004.py | 1 - .../test_query_params/test_tutorial005.py | 2 +- .../test_query_params/test_tutorial006.py | 1 - .../test_tutorial001.py | 1 - .../test_tutorial002.py | 2 - .../test_tutorial003.py | 2 - .../test_tutorial004.py | 11 - .../test_tutorial005.py | 4 +- .../test_tutorial006.py | 4 +- .../test_tutorial006c.py | 2 - .../test_tutorial007.py | 2 - .../test_tutorial008.py | 2 - .../test_tutorial009.py | 2 - .../test_tutorial010.py | 2 - .../test_tutorial011.py | 2 - .../test_tutorial012.py | 4 +- .../test_tutorial013.py | 4 +- .../test_tutorial014.py | 2 - .../test_tutorial015.py | 1 - .../test_request_files/test_tutorial001.py | 4 +- .../test_request_files/test_tutorial001_02.py | 2 - .../test_request_files/test_tutorial001_03.py | 4 +- .../test_request_files/test_tutorial002.py | 4 +- .../test_request_files/test_tutorial003.py | 4 +- .../test_tutorial001.py | 4 +- .../test_tutorial002.py | 4 +- .../test_request_forms/test_tutorial001.py | 4 +- .../test_tutorial001.py | 4 +- .../test_tutorial001.py | 2 +- .../test_response_cookies/test_tutorial001.py | 2 +- .../test_response_cookies/test_tutorial002.py | 2 +- .../test_tutorial001.py | 1 - .../test_tutorial002.py | 2 +- .../test_response_headers/test_tutorial001.py | 2 +- .../test_response_headers/test_tutorial002.py | 2 +- .../test_tutorial001_tutorial001_01.py | 2 - .../test_response_model/test_tutorial002.py | 1 - .../test_response_model/test_tutorial003.py | 1 - .../test_tutorial003_01.py | 1 - .../test_tutorial003_02.py | 2 +- .../test_tutorial003_03.py | 2 +- .../test_tutorial003_04.py | 1 - .../test_tutorial003_05.py | 1 - .../test_response_model/test_tutorial004.py | 1 - .../test_response_model/test_tutorial005.py | 1 - .../test_response_model/test_tutorial006.py | 1 - .../test_tutorial001_tutorial002.py | 4 +- .../test_tutorial001.py | 1 - .../test_tutorial002.py | 1 - .../test_tutorial003.py | 2 - .../test_tutorial004.py | 2 - .../test_tutorial005.py | 2 - .../test_security/test_tutorial001.py | 4 +- .../test_security/test_tutorial002.py | 2 - .../test_security/test_tutorial003.py | 2 - .../test_security/test_tutorial004.py | 2 - .../test_security/test_tutorial005.py | 2 - .../test_security/test_tutorial006.py | 4 +- .../test_security/test_tutorial007.py | 4 +- .../test_tutorial001.py | 1 - .../test_tutorial002.py | 1 - .../test_tutorial/test_settings/test_app01.py | 2 +- .../test_tutorial/test_settings/test_app02.py | 4 +- .../test_tutorial/test_settings/test_app03.py | 4 +- .../test_settings/test_tutorial001.py | 2 +- .../test_sql_databases/test_tutorial001.py | 2 - .../test_sql_databases/test_tutorial002.py | 2 - .../test_static_files/test_tutorial001.py | 2 +- .../test_sub_applications/test_tutorial001.py | 2 +- .../test_templates/test_tutorial001.py | 2 +- .../test_tutorial/test_testing/test_main_a.py | 2 +- .../test_tutorial/test_testing/test_main_b.py | 2 - .../test_testing/test_tutorial001.py | 2 +- .../test_testing/test_tutorial002.py | 2 +- .../test_testing/test_tutorial003.py | 2 +- .../test_testing/test_tutorial004.py | 2 +- .../test_tutorial001.py | 2 - .../test_tutorial001.py | 2 +- .../test_websockets/test_tutorial001.py | 2 +- .../test_websockets/test_tutorial002.py | 2 - .../test_websockets/test_tutorial003.py | 2 +- .../test_wsgi/test_tutorial001.py | 2 +- 655 files changed, 3701 insertions(+), 5658 deletions(-) create mode 100644 docs_src/additional_responses/tutorial001_py310.py delete mode 100644 docs_src/additional_responses/tutorial002_py39.py create mode 100644 docs_src/additional_responses/tutorial003_py310.py delete mode 100644 docs_src/additional_responses/tutorial004_py39.py delete mode 100644 docs_src/additional_status_codes/tutorial001_an_py39.py delete mode 100644 docs_src/additional_status_codes/tutorial001_py39.py create mode 100644 docs_src/advanced_middleware/tutorial001_py310.py create mode 100644 docs_src/advanced_middleware/tutorial002_py310.py create mode 100644 docs_src/advanced_middleware/tutorial003_py310.py rename docs_src/app_testing/{app_b_an_py39 => app_a_py310}/__init__.py (100%) create mode 100644 docs_src/app_testing/app_a_py310/main.py create mode 100644 docs_src/app_testing/app_a_py310/test_main.py delete mode 100644 docs_src/app_testing/app_b_an_py39/main.py delete mode 100644 docs_src/app_testing/app_b_an_py39/test_main.py delete mode 100644 docs_src/app_testing/app_b_py39/main.py delete mode 100644 docs_src/app_testing/app_b_py39/test_main.py create mode 100644 docs_src/app_testing/tutorial001_py310.py create mode 100644 docs_src/app_testing/tutorial002_py310.py create mode 100644 docs_src/app_testing/tutorial003_py310.py create mode 100644 docs_src/app_testing/tutorial004_py310.py rename docs_src/{app_testing/app_b_py39 => async_tests/app_a_py310}/__init__.py (100%) create mode 100644 docs_src/async_tests/app_a_py310/main.py create mode 100644 docs_src/async_tests/app_a_py310/test_main.py create mode 100644 docs_src/authentication_error_status_code/tutorial001_an_py310.py create mode 100644 docs_src/background_tasks/tutorial001_py310.py delete mode 100644 docs_src/background_tasks/tutorial002_an_py39.py delete mode 100644 docs_src/background_tasks/tutorial002_py39.py create mode 100644 docs_src/behind_a_proxy/tutorial001_01_py310.py create mode 100644 docs_src/behind_a_proxy/tutorial001_py310.py create mode 100644 docs_src/behind_a_proxy/tutorial002_py310.py create mode 100644 docs_src/behind_a_proxy/tutorial003_py310.py create mode 100644 docs_src/behind_a_proxy/tutorial004_py310.py rename docs_src/bigger_applications/{app_py39/internal => app_an_py310}/__init__.py (100%) create mode 100644 docs_src/bigger_applications/app_an_py310/dependencies.py rename docs_src/bigger_applications/{app_py39/routers => app_an_py310/internal}/__init__.py (100%) rename docs_src/bigger_applications/{app_py39 => app_an_py310}/internal/admin.py (100%) create mode 100644 docs_src/bigger_applications/app_an_py310/main.py create mode 100644 docs_src/bigger_applications/app_an_py310/routers/__init__.py rename docs_src/bigger_applications/{app_py39 => app_an_py310}/routers/items.py (100%) rename docs_src/bigger_applications/{app_py39 => app_an_py310}/routers/users.py (100%) delete mode 100644 docs_src/body/tutorial001_py39.py delete mode 100644 docs_src/body/tutorial002_py39.py delete mode 100644 docs_src/body/tutorial003_py39.py delete mode 100644 docs_src/body/tutorial004_py39.py delete mode 100644 docs_src/body_fields/tutorial001_an_py39.py delete mode 100644 docs_src/body_fields/tutorial001_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial001_an_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial001_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial002_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial003_an_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial003_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial004_an_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial004_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial005_an_py39.py delete mode 100644 docs_src/body_multiple_params/tutorial005_py39.py delete mode 100644 docs_src/body_nested_models/tutorial001_py39.py delete mode 100644 docs_src/body_nested_models/tutorial002_py39.py delete mode 100644 docs_src/body_nested_models/tutorial003_py39.py delete mode 100644 docs_src/body_nested_models/tutorial004_py39.py delete mode 100644 docs_src/body_nested_models/tutorial005_py39.py delete mode 100644 docs_src/body_nested_models/tutorial006_py39.py delete mode 100644 docs_src/body_nested_models/tutorial007_py39.py create mode 100644 docs_src/body_nested_models/tutorial008_py310.py create mode 100644 docs_src/body_nested_models/tutorial009_py310.py delete mode 100644 docs_src/body_updates/tutorial001_py39.py delete mode 100644 docs_src/body_updates/tutorial002_py39.py create mode 100644 docs_src/conditional_openapi/tutorial001_py310.py create mode 100644 docs_src/configure_swagger_ui/tutorial001_py310.py create mode 100644 docs_src/configure_swagger_ui/tutorial002_py310.py create mode 100644 docs_src/configure_swagger_ui/tutorial003_py310.py delete mode 100644 docs_src/cookie_param_models/tutorial001_an_py39.py delete mode 100644 docs_src/cookie_param_models/tutorial001_py39.py delete mode 100644 docs_src/cookie_param_models/tutorial002_an_py39.py delete mode 100644 docs_src/cookie_param_models/tutorial002_py39.py delete mode 100644 docs_src/cookie_params/tutorial001_an_py39.py delete mode 100644 docs_src/cookie_params/tutorial001_py39.py create mode 100644 docs_src/cors/tutorial001_py310.py create mode 100644 docs_src/custom_docs_ui/tutorial001_py310.py create mode 100644 docs_src/custom_docs_ui/tutorial002_py310.py delete mode 100644 docs_src/custom_request_and_route/tutorial001_an_py39.py delete mode 100644 docs_src/custom_request_and_route/tutorial001_py39.py delete mode 100644 docs_src/custom_request_and_route/tutorial002_an_py39.py delete mode 100644 docs_src/custom_request_and_route/tutorial002_py39.py delete mode 100644 docs_src/custom_request_and_route/tutorial003_py39.py create mode 100644 docs_src/custom_response/tutorial001_py310.py create mode 100644 docs_src/custom_response/tutorial001b_py310.py create mode 100644 docs_src/custom_response/tutorial002_py310.py create mode 100644 docs_src/custom_response/tutorial003_py310.py create mode 100644 docs_src/custom_response/tutorial004_py310.py create mode 100644 docs_src/custom_response/tutorial005_py310.py create mode 100644 docs_src/custom_response/tutorial006_py310.py create mode 100644 docs_src/custom_response/tutorial006b_py310.py create mode 100644 docs_src/custom_response/tutorial006c_py310.py create mode 100644 docs_src/custom_response/tutorial007_py310.py create mode 100644 docs_src/custom_response/tutorial008_py310.py create mode 100644 docs_src/custom_response/tutorial009_py310.py create mode 100644 docs_src/custom_response/tutorial009b_py310.py create mode 100644 docs_src/custom_response/tutorial009c_py310.py create mode 100644 docs_src/custom_response/tutorial010_py310.py delete mode 100644 docs_src/dataclasses_/tutorial001_py39.py delete mode 100644 docs_src/dataclasses_/tutorial002_py39.py delete mode 100644 docs_src/dataclasses_/tutorial003_py39.py create mode 100644 docs_src/debugging/tutorial001_py310.py delete mode 100644 docs_src/dependencies/tutorial001_02_an_py39.py delete mode 100644 docs_src/dependencies/tutorial001_an_py39.py delete mode 100644 docs_src/dependencies/tutorial001_py39.py delete mode 100644 docs_src/dependencies/tutorial002_an_py39.py delete mode 100644 docs_src/dependencies/tutorial002_py39.py delete mode 100644 docs_src/dependencies/tutorial003_an_py39.py delete mode 100644 docs_src/dependencies/tutorial003_py39.py delete mode 100644 docs_src/dependencies/tutorial004_an_py39.py delete mode 100644 docs_src/dependencies/tutorial004_py39.py delete mode 100644 docs_src/dependencies/tutorial005_an_py39.py delete mode 100644 docs_src/dependencies/tutorial005_py39.py create mode 100644 docs_src/dependencies/tutorial006_an_py310.py create mode 100644 docs_src/dependencies/tutorial006_py310.py create mode 100644 docs_src/dependencies/tutorial007_py310.py create mode 100644 docs_src/dependencies/tutorial008_an_py310.py create mode 100644 docs_src/dependencies/tutorial008_py310.py create mode 100644 docs_src/dependencies/tutorial008b_an_py310.py create mode 100644 docs_src/dependencies/tutorial008b_py310.py create mode 100644 docs_src/dependencies/tutorial008c_an_py310.py create mode 100644 docs_src/dependencies/tutorial008c_py310.py create mode 100644 docs_src/dependencies/tutorial008d_an_py310.py create mode 100644 docs_src/dependencies/tutorial008d_py310.py create mode 100644 docs_src/dependencies/tutorial008e_an_py310.py create mode 100644 docs_src/dependencies/tutorial008e_py310.py create mode 100644 docs_src/dependencies/tutorial010_py310.py create mode 100644 docs_src/dependencies/tutorial011_an_py310.py create mode 100644 docs_src/dependencies/tutorial011_py310.py create mode 100644 docs_src/dependencies/tutorial012_an_py310.py create mode 100644 docs_src/dependencies/tutorial012_py310.py delete mode 100644 docs_src/dependency_testing/tutorial001_an_py39.py delete mode 100644 docs_src/dependency_testing/tutorial001_py39.py delete mode 100644 docs_src/encoder/tutorial001_py39.py create mode 100644 docs_src/events/tutorial001_py310.py create mode 100644 docs_src/events/tutorial002_py310.py create mode 100644 docs_src/events/tutorial003_py310.py create mode 100644 docs_src/extending_openapi/tutorial001_py310.py delete mode 100644 docs_src/extra_data_types/tutorial001_an_py39.py delete mode 100644 docs_src/extra_data_types/tutorial001_py39.py delete mode 100644 docs_src/extra_models/tutorial001_py39.py delete mode 100644 docs_src/extra_models/tutorial002_py39.py delete mode 100644 docs_src/extra_models/tutorial003_py39.py create mode 100644 docs_src/extra_models/tutorial004_py310.py create mode 100644 docs_src/extra_models/tutorial005_py310.py create mode 100644 docs_src/first_steps/tutorial001_py310.py create mode 100644 docs_src/first_steps/tutorial003_py310.py create mode 100644 docs_src/generate_clients/tutorial001_py310.py create mode 100644 docs_src/generate_clients/tutorial002_py310.py create mode 100644 docs_src/generate_clients/tutorial003_py310.py create mode 100644 docs_src/generate_clients/tutorial004_py310.py create mode 100644 docs_src/graphql_/tutorial001_py310.py create mode 100644 docs_src/handling_errors/tutorial001_py310.py create mode 100644 docs_src/handling_errors/tutorial002_py310.py create mode 100644 docs_src/handling_errors/tutorial003_py310.py create mode 100644 docs_src/handling_errors/tutorial004_py310.py create mode 100644 docs_src/handling_errors/tutorial005_py310.py create mode 100644 docs_src/handling_errors/tutorial006_py310.py delete mode 100644 docs_src/header_param_models/tutorial001_an_py39.py delete mode 100644 docs_src/header_param_models/tutorial001_py39.py delete mode 100644 docs_src/header_param_models/tutorial002_an_py39.py delete mode 100644 docs_src/header_param_models/tutorial002_py39.py delete mode 100644 docs_src/header_param_models/tutorial003_an_py39.py delete mode 100644 docs_src/header_param_models/tutorial003_py39.py delete mode 100644 docs_src/header_params/tutorial001_an_py39.py delete mode 100644 docs_src/header_params/tutorial001_py39.py delete mode 100644 docs_src/header_params/tutorial002_an_py39.py delete mode 100644 docs_src/header_params/tutorial002_py39.py delete mode 100644 docs_src/header_params/tutorial003_an_py39.py delete mode 100644 docs_src/header_params/tutorial003_py39.py create mode 100644 docs_src/metadata/tutorial001_1_py310.py create mode 100644 docs_src/metadata/tutorial001_py310.py create mode 100644 docs_src/metadata/tutorial002_py310.py create mode 100644 docs_src/metadata/tutorial003_py310.py create mode 100644 docs_src/metadata/tutorial004_py310.py create mode 100644 docs_src/middleware/tutorial001_py310.py delete mode 100644 docs_src/openapi_callbacks/tutorial001_py39.py create mode 100644 docs_src/openapi_webhooks/tutorial001_py310.py create mode 100644 docs_src/path_operation_advanced_configuration/tutorial001_py310.py create mode 100644 docs_src/path_operation_advanced_configuration/tutorial002_py310.py create mode 100644 docs_src/path_operation_advanced_configuration/tutorial003_py310.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial004_py39.py create mode 100644 docs_src/path_operation_advanced_configuration/tutorial005_py310.py create mode 100644 docs_src/path_operation_advanced_configuration/tutorial006_py310.py rename docs_src/path_operation_advanced_configuration/{tutorial007_pv1_py39.py => tutorial007_py310.py} (68%) delete mode 100644 docs_src/path_operation_configuration/tutorial001_py39.py delete mode 100644 docs_src/path_operation_configuration/tutorial002_py39.py create mode 100644 docs_src/path_operation_configuration/tutorial002b_py310.py delete mode 100644 docs_src/path_operation_configuration/tutorial003_py39.py delete mode 100644 docs_src/path_operation_configuration/tutorial004_py39.py delete mode 100644 docs_src/path_operation_configuration/tutorial005_py39.py create mode 100644 docs_src/path_operation_configuration/tutorial006_py310.py create mode 100644 docs_src/path_params/tutorial001_py310.py create mode 100644 docs_src/path_params/tutorial002_py310.py create mode 100644 docs_src/path_params/tutorial003_py310.py create mode 100644 docs_src/path_params/tutorial003b_py310.py create mode 100644 docs_src/path_params/tutorial004_py310.py create mode 100644 docs_src/path_params/tutorial005_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial002_an_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial002_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial003_an_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial003_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial004_an_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial004_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial005_an_py310.py create mode 100644 docs_src/path_params_numeric_validations/tutorial005_py310.py rename docs_src/path_params_numeric_validations/{tutorial001_an_py39.py => tutorial006_an_py310.py} (61%) rename docs_src/path_params_numeric_validations/{tutorial001_py39.py => tutorial006_py310.py} (53%) delete mode 100644 docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py delete mode 100644 docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py delete mode 100644 docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py delete mode 100644 docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py create mode 100644 docs_src/python_types/tutorial001_py310.py create mode 100644 docs_src/python_types/tutorial002_py310.py create mode 100644 docs_src/python_types/tutorial003_py310.py create mode 100644 docs_src/python_types/tutorial004_py310.py create mode 100644 docs_src/python_types/tutorial005_py310.py create mode 100644 docs_src/python_types/tutorial006_py310.py create mode 100644 docs_src/python_types/tutorial007_py310.py create mode 100644 docs_src/python_types/tutorial008_py310.py create mode 100644 docs_src/python_types/tutorial010_py310.py delete mode 100644 docs_src/python_types/tutorial011_py39.py delete mode 100644 docs_src/python_types/tutorial012_py39.py create mode 100644 docs_src/python_types/tutorial013_py310.py delete mode 100644 docs_src/query_param_models/tutorial001_an_py39.py delete mode 100644 docs_src/query_param_models/tutorial001_py39.py delete mode 100644 docs_src/query_param_models/tutorial002_an_py39.py delete mode 100644 docs_src/query_param_models/tutorial002_py39.py create mode 100644 docs_src/query_params/tutorial001_py310.py delete mode 100644 docs_src/query_params/tutorial002_py39.py delete mode 100644 docs_src/query_params/tutorial003_py39.py delete mode 100644 docs_src/query_params/tutorial004_py39.py create mode 100644 docs_src/query_params/tutorial005_py310.py delete mode 100644 docs_src/query_params/tutorial006_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial001_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial002_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial003_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial003_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial004_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial004_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial004_regex_an_py310.py rename docs_src/query_params_str_validations/{tutorial002_py39.py => tutorial005_an_py310.py} (65%) rename docs_src/query_params_str_validations/{tutorial009_py39.py => tutorial005_py310.py} (64%) rename docs_src/query_params_str_validations/{tutorial006c_py39.py => tutorial006_an_py310.py} (69%) rename docs_src/query_params_str_validations/{tutorial006c_an_py39.py => tutorial006_py310.py} (64%) delete mode 100644 docs_src/query_params_str_validations/tutorial007_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial007_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial008_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial008_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial009_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial010_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial010_py39.py rename docs_src/query_params_str_validations/{tutorial011_an_py39.py => tutorial012_an_py310.py} (52%) create mode 100644 docs_src/query_params_str_validations/tutorial012_py310.py rename docs_src/query_params_str_validations/{tutorial011_py39.py => tutorial013_an_py310.py} (56%) create mode 100644 docs_src/query_params_str_validations/tutorial013_py310.py delete mode 100644 docs_src/query_params_str_validations/tutorial014_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial014_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial015_an_py39.py delete mode 100644 docs_src/request_files/tutorial001_02_an_py39.py delete mode 100644 docs_src/request_files/tutorial001_02_py39.py create mode 100644 docs_src/request_files/tutorial001_03_an_py310.py create mode 100644 docs_src/request_files/tutorial001_03_py310.py create mode 100644 docs_src/request_files/tutorial001_an_py310.py create mode 100644 docs_src/request_files/tutorial001_py310.py create mode 100644 docs_src/request_files/tutorial002_an_py310.py create mode 100644 docs_src/request_files/tutorial002_py310.py create mode 100644 docs_src/request_files/tutorial003_an_py310.py create mode 100644 docs_src/request_files/tutorial003_py310.py create mode 100644 docs_src/request_form_models/tutorial001_an_py310.py create mode 100644 docs_src/request_form_models/tutorial001_py310.py create mode 100644 docs_src/request_form_models/tutorial002_an_py310.py create mode 100644 docs_src/request_form_models/tutorial002_py310.py create mode 100644 docs_src/request_forms/tutorial001_an_py310.py create mode 100644 docs_src/request_forms/tutorial001_py310.py create mode 100644 docs_src/request_forms_and_files/tutorial001_an_py310.py create mode 100644 docs_src/request_forms_and_files/tutorial001_py310.py create mode 100644 docs_src/response_change_status_code/tutorial001_py310.py create mode 100644 docs_src/response_cookies/tutorial001_py310.py create mode 100644 docs_src/response_cookies/tutorial002_py310.py delete mode 100644 docs_src/response_directly/tutorial001_py39.py create mode 100644 docs_src/response_directly/tutorial002_py310.py create mode 100644 docs_src/response_headers/tutorial001_py310.py create mode 100644 docs_src/response_headers/tutorial002_py310.py delete mode 100644 docs_src/response_model/tutorial001_01_py39.py delete mode 100644 docs_src/response_model/tutorial001_py39.py delete mode 100644 docs_src/response_model/tutorial002_py39.py delete mode 100644 docs_src/response_model/tutorial003_01_py39.py create mode 100644 docs_src/response_model/tutorial003_02_py310.py create mode 100644 docs_src/response_model/tutorial003_03_py310.py delete mode 100644 docs_src/response_model/tutorial003_04_py39.py delete mode 100644 docs_src/response_model/tutorial003_05_py39.py delete mode 100644 docs_src/response_model/tutorial003_py39.py delete mode 100644 docs_src/response_model/tutorial004_py39.py delete mode 100644 docs_src/response_model/tutorial005_py39.py delete mode 100644 docs_src/response_model/tutorial006_py39.py create mode 100644 docs_src/response_status_code/tutorial001_py310.py create mode 100644 docs_src/response_status_code/tutorial002_py310.py delete mode 100644 docs_src/schema_extra_example/tutorial001_pv1_py310.py delete mode 100644 docs_src/schema_extra_example/tutorial001_pv1_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial001_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial002_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial003_an_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial003_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial004_an_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial004_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial005_an_py39.py delete mode 100644 docs_src/schema_extra_example/tutorial005_py39.py create mode 100644 docs_src/security/tutorial001_an_py310.py create mode 100644 docs_src/security/tutorial001_py310.py delete mode 100644 docs_src/security/tutorial002_an_py39.py delete mode 100644 docs_src/security/tutorial002_py39.py delete mode 100644 docs_src/security/tutorial003_an_py39.py delete mode 100644 docs_src/security/tutorial003_py39.py delete mode 100644 docs_src/security/tutorial004_an_py39.py delete mode 100644 docs_src/security/tutorial004_py39.py delete mode 100644 docs_src/security/tutorial005_an_py39.py delete mode 100644 docs_src/security/tutorial005_py39.py create mode 100644 docs_src/security/tutorial006_an_py310.py create mode 100644 docs_src/security/tutorial006_py310.py create mode 100644 docs_src/security/tutorial007_an_py310.py create mode 100644 docs_src/security/tutorial007_py310.py delete mode 100644 docs_src/separate_openapi_schemas/tutorial001_py39.py delete mode 100644 docs_src/separate_openapi_schemas/tutorial002_py39.py create mode 100644 docs_src/settings/app01_py310/__init__.py rename docs_src/settings/{app03_an_py39/config_pv1.py => app01_py310/config.py} (59%) create mode 100644 docs_src/settings/app01_py310/main.py create mode 100644 docs_src/settings/app02_an_py310/__init__.py rename docs_src/settings/{app03_py39/config_pv1.py => app02_an_py310/config.py} (58%) create mode 100644 docs_src/settings/app02_an_py310/main.py create mode 100644 docs_src/settings/app02_an_py310/test_main.py create mode 100644 docs_src/settings/app02_py310/__init__.py create mode 100644 docs_src/settings/app02_py310/config.py create mode 100644 docs_src/settings/app02_py310/main.py create mode 100644 docs_src/settings/app02_py310/test_main.py create mode 100644 docs_src/settings/app03_an_py310/__init__.py create mode 100644 docs_src/settings/app03_an_py310/config.py create mode 100644 docs_src/settings/app03_an_py310/main.py create mode 100644 docs_src/settings/app03_py310/__init__.py create mode 100644 docs_src/settings/app03_py310/config.py create mode 100644 docs_src/settings/app03_py310/main.py rename docs_src/settings/{tutorial001_pv1_py39.py => tutorial001_py310.py} (89%) delete mode 100644 docs_src/sql_databases/tutorial001_an_py39.py delete mode 100644 docs_src/sql_databases/tutorial001_py39.py delete mode 100644 docs_src/sql_databases/tutorial002_an_py39.py delete mode 100644 docs_src/sql_databases/tutorial002_py39.py create mode 100644 docs_src/static_files/tutorial001_py310.py create mode 100644 docs_src/sub_applications/tutorial001_py310.py create mode 100644 docs_src/templates/tutorial001_py310.py create mode 100644 docs_src/using_request_directly/tutorial001_py310.py create mode 100644 docs_src/websockets/tutorial001_py310.py delete mode 100644 docs_src/websockets/tutorial002_an_py39.py delete mode 100644 docs_src/websockets/tutorial002_py39.py create mode 100644 docs_src/websockets/tutorial003_py310.py create mode 100644 docs_src/wsgi/tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_python_types/test_tutorial012.py diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md index bb70753edd..6306bd1f9a 100644 --- a/docs/en/docs/advanced/additional-responses.md +++ b/docs/en/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ Each of those response `dict`s can have a key `model`, containing a Pydantic mod For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note @@ -203,7 +203,7 @@ For example, you can declare a response with a status code `404` that uses a Pyd And a response with a status code `200` that uses your `response_model`, but includes a custom `example`: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} It will all be combined and included in your OpenAPI, and shown in the API docs: diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index 0d03507b7e..3a23a6d1ad 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Not the class itself (which is already a callable), but an instance of that clas To do that, we declare a method `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later. @@ -26,7 +26,7 @@ In this case, this `__call__` is what **FastAPI** will use to check for addition And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code. @@ -34,7 +34,7 @@ In this case, **FastAPI** won't ever touch or care about `__init__`, we will use We could create an instance of this class with: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") ...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md index 65ddc60b2d..cefb1d1841 100644 --- a/docs/en/docs/advanced/async-tests.md +++ b/docs/en/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ For a simple example, let's consider a file structure similar to the one describ The file `main.py` would have: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} The file `test_main.py` would have the tests for `main.py`, it could look like this now: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## Run it { #run-it } @@ -56,7 +56,7 @@ $ pytest The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip @@ -66,7 +66,7 @@ Note that the test function is now `async def` instead of just `def` as before w Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} This is the equivalent to: diff --git a/docs/en/docs/advanced/behind-a-proxy.md b/docs/en/docs/advanced/behind-a-proxy.md index 4fef02bd1c..770e9cd3ca 100644 --- a/docs/en/docs/advanced/behind-a-proxy.md +++ b/docs/en/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" For example, let's say you define a *path operation* `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} If the client tries to go to `/items`, by default, it would be redirected to `/items/`. @@ -115,7 +115,7 @@ In this case, the original path `/app` would actually be served at `/api/v1/app` Even though all your code is written assuming there's just `/app`. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`. @@ -193,7 +193,7 @@ You can get the current `root_path` used by your application for each request, i Here we are including it in the message just for demonstration purposes. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Then, if you start Uvicorn with: @@ -220,7 +220,7 @@ The response would be something like: Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn. @@ -400,7 +400,7 @@ If you pass a custom list of `servers` and there's a `root_path` (because your A For example: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} Will generate an OpenAPI schema like: @@ -455,7 +455,7 @@ If you don't specify the `servers` parameter and `root_path` is equal to `/`, th If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} and then it won't include it in the OpenAPI schema. diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index e53409c39d..8b4b3da339 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ This is because by default, FastAPI will inspect every item inside and make sure But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info @@ -55,7 +55,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`. * Import `HTMLResponse`. * Pass `HTMLResponse` as the parameter `response_class` of your *path operation decorator*. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info @@ -73,7 +73,7 @@ As seen in [Return a Response directly](response-directly.md){.internal-link tar The same example from above, returning an `HTMLResponse`, could look like: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning @@ -97,7 +97,7 @@ The `response_class` will then be used only to document the OpenAPI *path operat For example, it could be something like: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`. @@ -136,7 +136,7 @@ It accepts the following parameters: FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the `media_type` and appending a charset for text types. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ Takes some text or bytes and returns an HTML response, as you read above. Takes some text or bytes and returns a plain text response. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ This requires installing `ujson` for example with `pip install ujson`. /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip @@ -194,14 +194,14 @@ Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default You can return a `RedirectResponse` directly: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- Or you can use it in the `response_class` parameter: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} If you do that, then you can return the URL directly from your *path operation* function. @@ -211,13 +211,13 @@ In this case, the `status_code` used will be the default one for the `RedirectRe You can also use the `status_code` parameter combined with the `response_class` parameter: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } Takes an async generator or a normal generator/iterator and streams the response body. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects } @@ -227,7 +227,7 @@ That way, you don't have to read it all first in memory, and you can pass that g This includes many libraries to interact with cloud storage, video processing, and others. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. This is the generator function. It's a "generator function" because it contains `yield` statements inside. 2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response. @@ -256,11 +256,11 @@ Takes a different set of arguments to instantiate than the other response types: File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} You can also use the `response_class` parameter: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} In this case, you can return the file path directly from your *path operation* function. @@ -274,7 +274,7 @@ Let's say you want it to return indented and formatted JSON, so you want to use You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} Now instead of returning: @@ -300,7 +300,7 @@ The parameter that defines this is `default_response_class`. In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md index 9414b7a3f0..302e963251 100644 --- a/docs/en/docs/advanced/events.md +++ b/docs/en/docs/advanced/events.md @@ -30,7 +30,7 @@ Let's start with an example and then see it in detail. We create an async function `lifespan()` with `yield` like this: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*. @@ -48,7 +48,7 @@ Maybe you need to start a new version, or you just got tired of running it. ๐Ÿคท The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} The first part of the function, before the `yield`, will be executed **before** the application starts. @@ -60,7 +60,7 @@ If you check, the function is decorated with an `@asynccontextmanager`. That converts the function into something called an "**async context manager**". -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager: @@ -82,7 +82,7 @@ In our code example above, we don't use it directly, but we pass it to FastAPI f The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Alternative Events (deprecated) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ These functions can be declared with `async def` or normal `def`. To add a function that should be run before the application starts, declare it with the event `"startup"`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} In this case, the `startup` event handler function will initialize the items "database" (just a `dict`) with some values. @@ -116,7 +116,7 @@ And your application won't start receiving requests until all the `startup` even To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Here, the `shutdown` event handler function will write a text line `"Application shutdown"` to a file `log.txt`. diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 2d0c2aa0c9..1e6173c9ae 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -40,7 +40,7 @@ Some of these solutions may also be open source or offer free tiers, so you can Let's start with a simple FastAPI application: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`. @@ -98,7 +98,7 @@ In many cases, your FastAPI app will be bigger, and you will probably use tags t For example, you could have a section for **items** and another section for **users**, and they could be separated by tags: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Generate a TypeScript Client with Tags { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ For example, here it is using the first tag (you will probably have only one tag You can then pass that custom function to **FastAPI** as the `generate_unique_id_function` parameter: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### Generate a TypeScript Client with Custom Operation IDs { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ But for the generated client, we could **modify** the OpenAPI operation IDs righ We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md index 765b389329..b448f5c520 100644 --- a/docs/en/docs/advanced/middleware.md +++ b/docs/en/docs/advanced/middleware.md @@ -57,13 +57,13 @@ Enforces that all incoming requests must either be `https` or `wss`. Any incoming request to `http` or `ws` will be redirected to the secure scheme instead. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} The following arguments are supported: @@ -78,7 +78,7 @@ Handles GZip responses for any request that includes `"gzip"` in the `Accept-Enc The middleware will handle both standard and streaming responses. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} The following arguments are supported: diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md index 59f060c032..f4f586f84c 100644 --- a/docs/en/docs/advanced/openapi-webhooks.md +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:13,36:53] *} The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**. diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index 3d7bfdee59..fdc77c8a25 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ You can set the OpenAPI `operationId` to be used in your *path operation* with t You would have to make sure that it is unique for each operation. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ If you want to use your APIs' function names as `operationId`s, you can iterate You should do it after adding all your *path operations*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip @@ -40,7 +40,7 @@ Even if they are in different modules (Python files). To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Advanced description from docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ You can extend the OpenAPI schema for a *path operation* using the parameter `op This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} If you open the automatic API docs, your extension will show up at the bottom of the specific *path operation*. @@ -139,7 +139,7 @@ For example, you could decide to read and validate the request with your own cod You could do that with `openapi_extra`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} In this example, we didn't declare any Pydantic model. In fact, the request body is not even parsed as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way. @@ -153,7 +153,7 @@ And you could do this even if the data type in the request is not JSON. For example, in this application we don't use FastAPI's integrated functionality to extract the JSON Schema from Pydantic models nor the automatic validation for JSON. In fact, we are declaring the request content type as YAML, not JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Nevertheless, although we are not using the default integrated functionality, we are still using a Pydantic model to manually generate the JSON Schema for the data that we want to receive in YAML. @@ -161,7 +161,7 @@ Then we use the request directly, and extract the body as `bytes`. This means th And then in our code, we parse that YAML content directly, and then we are again using the same Pydantic model to validate the YAML content: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip diff --git a/docs/en/docs/advanced/response-change-status-code.md b/docs/en/docs/advanced/response-change-status-code.md index d9708aa627..8aa601e7bd 100644 --- a/docs/en/docs/advanced/response-change-status-code.md +++ b/docs/en/docs/advanced/response-change-status-code.md @@ -20,7 +20,7 @@ You can declare a parameter of type `Response` in your *path operation function* And then you can set the `status_code` in that *temporal* response object. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} And then you can return any object you need, as you normally would (a `dict`, a database model, etc). diff --git a/docs/en/docs/advanced/response-cookies.md b/docs/en/docs/advanced/response-cookies.md index 5b6fab112b..cfc615d7e4 100644 --- a/docs/en/docs/advanced/response-cookies.md +++ b/docs/en/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ You can declare a parameter of type `Response` in your *path operation function* And then you can set cookies in that *temporal* response object. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} And then you can return any object you need, as you normally would (a `dict`, a database model, etc). @@ -24,7 +24,7 @@ To do that, you can create a response as described in [Return a Response Directl Then set Cookies in it, and then return it: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index 4374cb9637..76cc50d03c 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ Let's say that you want to return an Strawberry documentation. diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index f2ad35d710..90c32cec8c 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -22,7 +22,7 @@ If you are a Python expert, and you already know everything about type hints, sk Let's start with a simple example: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Calling this program outputs: @@ -36,7 +36,7 @@ The function does the following: * Converts the first letter of each one to upper case with `title()`. * Concatenates them with a space in the middle. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Edit it { #edit-it } @@ -78,7 +78,7 @@ That's it. Those are the "type hints": -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} That is not the same as declaring default values like would be with: @@ -106,7 +106,7 @@ With that, you can scroll, seeing the options, until you find the one that "ring Check this function, it already has type hints: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Because the editor knows the types of the variables, you don't only get completion, you also get error checks: @@ -114,7 +114,7 @@ Because the editor knows the types of the variables, you don't only get completi Now you know that you have to fix it, convert `age` to a string with `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## Declaring types { #declaring-types } @@ -133,7 +133,7 @@ You can use, for example: * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} ### `typing` module { #typing-module } @@ -170,7 +170,7 @@ As the type, put `list`. As the list is a type that contains some internal types, you put them in square brackets: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info @@ -196,7 +196,7 @@ And still, the editor knows it is a `str`, and provides support for that. You would do the same to declare `tuple`s and `set`s: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} This means: @@ -211,7 +211,7 @@ The first type parameter is for the keys of the `dict`. The second type parameter is for the values of the `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} This means: @@ -253,11 +253,11 @@ You can also declare a class as the type of a variable. Let's say you have a class `Person`, with a name: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Then you can declare a variable to be of type `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} And then, again, you get all the editor support: @@ -299,7 +299,7 @@ Python also has a feature that allows putting **additional deprecated, but without removing it, pass the parameter `deprecated`: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} It will be clearly marked as deprecated in the interactive docs: diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index 8b1b8a8392..de63a51f59 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names, So, you can declare your function as: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} But keep in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Order the parameters as you need, tricks { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ Pass `*`, as the first parameter of the function. Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as kwargs. Even if they don't have a default value. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Better with `Annotated` { #better-with-annotated } Keep in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and you probably won't need to use `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Number validations: greater than or equal { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ With `Query` and `Path` (and others you'll see later) you can declare number con Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Number validations: greater than and less than or equal { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ The same applies for: * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Number validations: floats, greater than and less than { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ So, `0.5` would be a valid value. But `0.0` or `0` would not. And the same for lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Recap { #recap } diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md index cf312f1fef..8adbbcfa1b 100644 --- a/docs/en/docs/tutorial/path-params.md +++ b/docs/en/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ You can declare path "parameters" or "variables" with the same syntax used by Python format strings: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} The value of the path parameter `item_id` will be passed to your function as the argument `item_id`. @@ -16,7 +16,7 @@ So, if you run this example and go to Item: - if x_token != fake_secret_token: - raise HTTPException(status_code=400, detail="Invalid X-Token header") - if item.id in fake_db: - raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item.model_dump() - return item diff --git a/docs_src/app_testing/app_b_an_py39/test_main.py b/docs_src/app_testing/app_b_an_py39/test_main.py deleted file mode 100644 index 4e1c51ecc8..0000000000 --- a/docs_src/app_testing/app_b_an_py39/test_main.py +++ /dev/null @@ -1,65 +0,0 @@ -from fastapi.testclient import TestClient - -from .main import app - -client = TestClient(app) - - -def test_read_item(): - response = client.get("/items/foo", headers={"X-Token": "coneofsilence"}) - assert response.status_code == 200 - assert response.json() == { - "id": "foo", - "title": "Foo", - "description": "There goes my hero", - } - - -def test_read_item_bad_token(): - response = client.get("/items/foo", headers={"X-Token": "hailhydra"}) - assert response.status_code == 400 - assert response.json() == {"detail": "Invalid X-Token header"} - - -def test_read_nonexistent_item(): - response = client.get("/items/baz", headers={"X-Token": "coneofsilence"}) - assert response.status_code == 404 - assert response.json() == {"detail": "Item not found"} - - -def test_create_item(): - response = client.post( - "/items/", - headers={"X-Token": "coneofsilence"}, - json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"}, - ) - assert response.status_code == 200 - assert response.json() == { - "id": "foobar", - "title": "Foo Bar", - "description": "The Foo Barters", - } - - -def test_create_item_bad_token(): - response = client.post( - "/items/", - headers={"X-Token": "hailhydra"}, - json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"}, - ) - assert response.status_code == 400 - assert response.json() == {"detail": "Invalid X-Token header"} - - -def test_create_existing_item(): - response = client.post( - "/items/", - headers={"X-Token": "coneofsilence"}, - json={ - "id": "foo", - "title": "The Foo ID Stealers", - "description": "There goes my stealer", - }, - ) - assert response.status_code == 409 - assert response.json() == {"detail": "Item already exists"} diff --git a/docs_src/app_testing/app_b_py39/main.py b/docs_src/app_testing/app_b_py39/main.py deleted file mode 100644 index ed38f4721c..0000000000 --- a/docs_src/app_testing/app_b_py39/main.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header, HTTPException -from pydantic import BaseModel - -fake_secret_token = "coneofsilence" - -fake_db = { - "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"}, - "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"}, -} - -app = FastAPI() - - -class Item(BaseModel): - id: str - title: str - description: Union[str, None] = None - - -@app.get("/items/{item_id}", response_model=Item) -async def read_main(item_id: str, x_token: str = Header()): - if x_token != fake_secret_token: - raise HTTPException(status_code=400, detail="Invalid X-Token header") - if item_id not in fake_db: - raise HTTPException(status_code=404, detail="Item not found") - return fake_db[item_id] - - -@app.post("/items/") -async def create_item(item: Item, x_token: str = Header()) -> Item: - if x_token != fake_secret_token: - raise HTTPException(status_code=400, detail="Invalid X-Token header") - if item.id in fake_db: - raise HTTPException(status_code=409, detail="Item already exists") - fake_db[item.id] = item.model_dump() - return item diff --git a/docs_src/app_testing/app_b_py39/test_main.py b/docs_src/app_testing/app_b_py39/test_main.py deleted file mode 100644 index 4e1c51ecc8..0000000000 --- a/docs_src/app_testing/app_b_py39/test_main.py +++ /dev/null @@ -1,65 +0,0 @@ -from fastapi.testclient import TestClient - -from .main import app - -client = TestClient(app) - - -def test_read_item(): - response = client.get("/items/foo", headers={"X-Token": "coneofsilence"}) - assert response.status_code == 200 - assert response.json() == { - "id": "foo", - "title": "Foo", - "description": "There goes my hero", - } - - -def test_read_item_bad_token(): - response = client.get("/items/foo", headers={"X-Token": "hailhydra"}) - assert response.status_code == 400 - assert response.json() == {"detail": "Invalid X-Token header"} - - -def test_read_nonexistent_item(): - response = client.get("/items/baz", headers={"X-Token": "coneofsilence"}) - assert response.status_code == 404 - assert response.json() == {"detail": "Item not found"} - - -def test_create_item(): - response = client.post( - "/items/", - headers={"X-Token": "coneofsilence"}, - json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"}, - ) - assert response.status_code == 200 - assert response.json() == { - "id": "foobar", - "title": "Foo Bar", - "description": "The Foo Barters", - } - - -def test_create_item_bad_token(): - response = client.post( - "/items/", - headers={"X-Token": "hailhydra"}, - json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"}, - ) - assert response.status_code == 400 - assert response.json() == {"detail": "Invalid X-Token header"} - - -def test_create_existing_item(): - response = client.post( - "/items/", - headers={"X-Token": "coneofsilence"}, - json={ - "id": "foo", - "title": "The Foo ID Stealers", - "description": "There goes my stealer", - }, - ) - assert response.status_code == 409 - assert response.json() == {"detail": "Item already exists"} diff --git a/docs_src/app_testing/tutorial001_py310.py b/docs_src/app_testing/tutorial001_py310.py new file mode 100644 index 0000000000..79a853b487 --- /dev/null +++ b/docs_src/app_testing/tutorial001_py310.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +app = FastAPI() + + +@app.get("/") +async def read_main(): + return {"msg": "Hello World"} + + +client = TestClient(app) + + +def test_read_main(): + response = client.get("/") + assert response.status_code == 200 + assert response.json() == {"msg": "Hello World"} diff --git a/docs_src/app_testing/tutorial002_py310.py b/docs_src/app_testing/tutorial002_py310.py new file mode 100644 index 0000000000..71c898b3cf --- /dev/null +++ b/docs_src/app_testing/tutorial002_py310.py @@ -0,0 +1,31 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient +from fastapi.websockets import WebSocket + +app = FastAPI() + + +@app.get("/") +async def read_main(): + return {"msg": "Hello World"} + + +@app.websocket("/ws") +async def websocket(websocket: WebSocket): + await websocket.accept() + await websocket.send_json({"msg": "Hello WebSocket"}) + await websocket.close() + + +def test_read_main(): + client = TestClient(app) + response = client.get("/") + assert response.status_code == 200 + assert response.json() == {"msg": "Hello World"} + + +def test_websocket(): + client = TestClient(app) + with client.websocket_connect("/ws") as websocket: + data = websocket.receive_json() + assert data == {"msg": "Hello WebSocket"} diff --git a/docs_src/app_testing/tutorial003_py310.py b/docs_src/app_testing/tutorial003_py310.py new file mode 100644 index 0000000000..ca6b45ce03 --- /dev/null +++ b/docs_src/app_testing/tutorial003_py310.py @@ -0,0 +1,24 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +app = FastAPI() + +items = {} + + +@app.on_event("startup") +async def startup_event(): + items["foo"] = {"name": "Fighters"} + items["bar"] = {"name": "Tenders"} + + +@app.get("/items/{item_id}") +async def read_items(item_id: str): + return items[item_id] + + +def test_read_items(): + with TestClient(app) as client: + response = client.get("/items/foo") + assert response.status_code == 200 + assert response.json() == {"name": "Fighters"} diff --git a/docs_src/app_testing/tutorial004_py310.py b/docs_src/app_testing/tutorial004_py310.py new file mode 100644 index 0000000000..f83ac9ae9a --- /dev/null +++ b/docs_src/app_testing/tutorial004_py310.py @@ -0,0 +1,43 @@ +from contextlib import asynccontextmanager + +from fastapi import FastAPI +from fastapi.testclient import TestClient + +items = {} + + +@asynccontextmanager +async def lifespan(app: FastAPI): + items["foo"] = {"name": "Fighters"} + items["bar"] = {"name": "Tenders"} + yield + # clean up items + items.clear() + + +app = FastAPI(lifespan=lifespan) + + +@app.get("/items/{item_id}") +async def read_items(item_id: str): + return items[item_id] + + +def test_read_items(): + # Before the lifespan starts, "items" is still empty + assert items == {} + + with TestClient(app) as client: + # Inside the "with TestClient" block, the lifespan starts and items added + assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}} + + response = client.get("/items/foo") + assert response.status_code == 200 + assert response.json() == {"name": "Fighters"} + + # After the requests is done, the items are still there + assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}} + + # The end of the "with TestClient" block simulates terminating the app, so + # the lifespan ends and items are cleaned up + assert items == {} diff --git a/docs_src/app_testing/app_b_py39/__init__.py b/docs_src/async_tests/app_a_py310/__init__.py similarity index 100% rename from docs_src/app_testing/app_b_py39/__init__.py rename to docs_src/async_tests/app_a_py310/__init__.py diff --git a/docs_src/async_tests/app_a_py310/main.py b/docs_src/async_tests/app_a_py310/main.py new file mode 100644 index 0000000000..9594f859c7 --- /dev/null +++ b/docs_src/async_tests/app_a_py310/main.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def root(): + return {"message": "Tomato"} diff --git a/docs_src/async_tests/app_a_py310/test_main.py b/docs_src/async_tests/app_a_py310/test_main.py new file mode 100644 index 0000000000..a57a31f7d8 --- /dev/null +++ b/docs_src/async_tests/app_a_py310/test_main.py @@ -0,0 +1,14 @@ +import pytest +from httpx import ASGITransport, AsyncClient + +from .main import app + + +@pytest.mark.anyio +async def test_root(): + async with AsyncClient( + transport=ASGITransport(app=app), base_url="http://test" + ) as ac: + response = await ac.get("/") + assert response.status_code == 200 + assert response.json() == {"message": "Tomato"} diff --git a/docs_src/authentication_error_status_code/tutorial001_an_py310.py b/docs_src/authentication_error_status_code/tutorial001_an_py310.py new file mode 100644 index 0000000000..7bbc2f717d --- /dev/null +++ b/docs_src/authentication_error_status_code/tutorial001_an_py310.py @@ -0,0 +1,21 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, HTTPException, status +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer + +app = FastAPI() + + +class HTTPBearer403(HTTPBearer): + def make_not_authenticated_error(self) -> HTTPException: + return HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + + +CredentialsDep = Annotated[HTTPAuthorizationCredentials, Depends(HTTPBearer403())] + + +@app.get("/me") +def read_me(credentials: CredentialsDep): + return {"message": "You are authenticated", "token": credentials.credentials} diff --git a/docs_src/background_tasks/tutorial001_py310.py b/docs_src/background_tasks/tutorial001_py310.py new file mode 100644 index 0000000000..1720a74333 --- /dev/null +++ b/docs_src/background_tasks/tutorial001_py310.py @@ -0,0 +1,15 @@ +from fastapi import BackgroundTasks, FastAPI + +app = FastAPI() + + +def write_notification(email: str, message=""): + with open("log.txt", mode="w") as email_file: + content = f"notification for {email}: {message}" + email_file.write(content) + + +@app.post("/send-notification/{email}") +async def send_notification(email: str, background_tasks: BackgroundTasks): + background_tasks.add_task(write_notification, email, message="some notification") + return {"message": "Notification sent in the background"} diff --git a/docs_src/background_tasks/tutorial002_an_py39.py b/docs_src/background_tasks/tutorial002_an_py39.py deleted file mode 100644 index bfdd148753..0000000000 --- a/docs_src/background_tasks/tutorial002_an_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Annotated, Union - -from fastapi import BackgroundTasks, Depends, FastAPI - -app = FastAPI() - - -def write_log(message: str): - with open("log.txt", mode="a") as log: - log.write(message) - - -def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None): - if q: - message = f"found query: {q}\n" - background_tasks.add_task(write_log, message) - return q - - -@app.post("/send-notification/{email}") -async def send_notification( - email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)] -): - message = f"message to {email}\n" - background_tasks.add_task(write_log, message) - return {"message": "Message sent"} diff --git a/docs_src/background_tasks/tutorial002_py39.py b/docs_src/background_tasks/tutorial002_py39.py deleted file mode 100644 index 2e1b2f6c6c..0000000000 --- a/docs_src/background_tasks/tutorial002_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union - -from fastapi import BackgroundTasks, Depends, FastAPI - -app = FastAPI() - - -def write_log(message: str): - with open("log.txt", mode="a") as log: - log.write(message) - - -def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None): - if q: - message = f"found query: {q}\n" - background_tasks.add_task(write_log, message) - return q - - -@app.post("/send-notification/{email}") -async def send_notification( - email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query) -): - message = f"message to {email}\n" - background_tasks.add_task(write_log, message) - return {"message": "Message sent"} diff --git a/docs_src/behind_a_proxy/tutorial001_01_py310.py b/docs_src/behind_a_proxy/tutorial001_01_py310.py new file mode 100644 index 0000000000..52b114395b --- /dev/null +++ b/docs_src/behind_a_proxy/tutorial001_01_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/") +def read_items(): + return ["plumbus", "portal gun"] diff --git a/docs_src/behind_a_proxy/tutorial001_py310.py b/docs_src/behind_a_proxy/tutorial001_py310.py new file mode 100644 index 0000000000..ede59ada11 --- /dev/null +++ b/docs_src/behind_a_proxy/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI, Request + +app = FastAPI() + + +@app.get("/app") +def read_main(request: Request): + return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial002_py310.py b/docs_src/behind_a_proxy/tutorial002_py310.py new file mode 100644 index 0000000000..c1600cde9e --- /dev/null +++ b/docs_src/behind_a_proxy/tutorial002_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI, Request + +app = FastAPI(root_path="/api/v1") + + +@app.get("/app") +def read_main(request: Request): + return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial003_py310.py b/docs_src/behind_a_proxy/tutorial003_py310.py new file mode 100644 index 0000000000..3b7d8be018 --- /dev/null +++ b/docs_src/behind_a_proxy/tutorial003_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI, Request + +app = FastAPI( + servers=[ + {"url": "https://stag.example.com", "description": "Staging environment"}, + {"url": "https://prod.example.com", "description": "Production environment"}, + ], + root_path="/api/v1", +) + + +@app.get("/app") +def read_main(request: Request): + return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial004_py310.py b/docs_src/behind_a_proxy/tutorial004_py310.py new file mode 100644 index 0000000000..51bd5babc1 --- /dev/null +++ b/docs_src/behind_a_proxy/tutorial004_py310.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, Request + +app = FastAPI( + servers=[ + {"url": "https://stag.example.com", "description": "Staging environment"}, + {"url": "https://prod.example.com", "description": "Production environment"}, + ], + root_path="/api/v1", + root_path_in_servers=False, +) + + +@app.get("/app") +def read_main(request: Request): + return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/bigger_applications/app_py39/internal/__init__.py b/docs_src/bigger_applications/app_an_py310/__init__.py similarity index 100% rename from docs_src/bigger_applications/app_py39/internal/__init__.py rename to docs_src/bigger_applications/app_an_py310/__init__.py diff --git a/docs_src/bigger_applications/app_an_py310/dependencies.py b/docs_src/bigger_applications/app_an_py310/dependencies.py new file mode 100644 index 0000000000..5c7612aa09 --- /dev/null +++ b/docs_src/bigger_applications/app_an_py310/dependencies.py @@ -0,0 +1,13 @@ +from typing import Annotated + +from fastapi import Header, HTTPException + + +async def get_token_header(x_token: Annotated[str, Header()]): + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token header invalid") + + +async def get_query_token(token: str): + if token != "jessica": + raise HTTPException(status_code=400, detail="No Jessica token provided") diff --git a/docs_src/bigger_applications/app_py39/routers/__init__.py b/docs_src/bigger_applications/app_an_py310/internal/__init__.py similarity index 100% rename from docs_src/bigger_applications/app_py39/routers/__init__.py rename to docs_src/bigger_applications/app_an_py310/internal/__init__.py diff --git a/docs_src/bigger_applications/app_py39/internal/admin.py b/docs_src/bigger_applications/app_an_py310/internal/admin.py similarity index 100% rename from docs_src/bigger_applications/app_py39/internal/admin.py rename to docs_src/bigger_applications/app_an_py310/internal/admin.py diff --git a/docs_src/bigger_applications/app_an_py310/main.py b/docs_src/bigger_applications/app_an_py310/main.py new file mode 100644 index 0000000000..ae544a3aac --- /dev/null +++ b/docs_src/bigger_applications/app_an_py310/main.py @@ -0,0 +1,23 @@ +from fastapi import Depends, FastAPI + +from .dependencies import get_query_token, get_token_header +from .internal import admin +from .routers import items, users + +app = FastAPI(dependencies=[Depends(get_query_token)]) + + +app.include_router(users.router) +app.include_router(items.router) +app.include_router( + admin.router, + prefix="/admin", + tags=["admin"], + dependencies=[Depends(get_token_header)], + responses={418: {"description": "I'm a teapot"}}, +) + + +@app.get("/") +async def root(): + return {"message": "Hello Bigger Applications!"} diff --git a/docs_src/bigger_applications/app_an_py310/routers/__init__.py b/docs_src/bigger_applications/app_an_py310/routers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/bigger_applications/app_py39/routers/items.py b/docs_src/bigger_applications/app_an_py310/routers/items.py similarity index 100% rename from docs_src/bigger_applications/app_py39/routers/items.py rename to docs_src/bigger_applications/app_an_py310/routers/items.py diff --git a/docs_src/bigger_applications/app_py39/routers/users.py b/docs_src/bigger_applications/app_an_py310/routers/users.py similarity index 100% rename from docs_src/bigger_applications/app_py39/routers/users.py rename to docs_src/bigger_applications/app_an_py310/routers/users.py diff --git a/docs_src/body/tutorial001_py39.py b/docs_src/body/tutorial001_py39.py deleted file mode 100644 index f933172746..0000000000 --- a/docs_src/body/tutorial001_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item): - return item diff --git a/docs_src/body/tutorial002_py39.py b/docs_src/body/tutorial002_py39.py deleted file mode 100644 index fb212e8e79..0000000000 --- a/docs_src/body/tutorial002_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item): - item_dict = item.model_dump() - if item.tax is not None: - price_with_tax = item.price + item.tax - item_dict.update({"price_with_tax": price_with_tax}) - return item_dict diff --git a/docs_src/body/tutorial003_py39.py b/docs_src/body/tutorial003_py39.py deleted file mode 100644 index 636ba2275a..0000000000 --- a/docs_src/body/tutorial003_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - return {"item_id": item_id, **item.model_dump()} diff --git a/docs_src/body/tutorial004_py39.py b/docs_src/body/tutorial004_py39.py deleted file mode 100644 index 2c157abfa1..0000000000 --- a/docs_src/body/tutorial004_py39.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item, q: Union[str, None] = None): - result = {"item_id": item_id, **item.model_dump()} - if q: - result.update({"q": q}) - return result diff --git a/docs_src/body_fields/tutorial001_an_py39.py b/docs_src/body_fields/tutorial001_an_py39.py deleted file mode 100644 index 6ef14470cd..0000000000 --- a/docs_src/body_fields/tutorial001_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel, Field - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = Field( - default=None, title="The description of the item", max_length=300 - ) - price: float = Field(gt=0, description="The price must be greater than zero") - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_fields/tutorial001_py39.py b/docs_src/body_fields/tutorial001_py39.py deleted file mode 100644 index cbeebd614a..0000000000 --- a/docs_src/body_fields/tutorial001_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel, Field - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = Field( - default=None, title="The description of the item", max_length=300 - ) - price: float = Field(gt=0, description="The price must be greater than zero") - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item = Body(embed=True)): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_multiple_params/tutorial001_an_py39.py b/docs_src/body_multiple_params/tutorial001_an_py39.py deleted file mode 100644 index 1c0ac3a7b3..0000000000 --- a/docs_src/body_multiple_params/tutorial001_an_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Path -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], - q: Union[str, None] = None, - item: Union[Item, None] = None, -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - if item: - results.update({"item": item}) - return results diff --git a/docs_src/body_multiple_params/tutorial001_py39.py b/docs_src/body_multiple_params/tutorial001_py39.py deleted file mode 100644 index a73975b3a2..0000000000 --- a/docs_src/body_multiple_params/tutorial001_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Path -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int = Path(title="The ID of the item to get", ge=0, le=1000), - q: Union[str, None] = None, - item: Union[Item, None] = None, -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - if item: - results.update({"item": item}) - return results diff --git a/docs_src/body_multiple_params/tutorial002_py39.py b/docs_src/body_multiple_params/tutorial002_py39.py deleted file mode 100644 index 2d7160ae8e..0000000000 --- a/docs_src/body_multiple_params/tutorial002_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -class User(BaseModel): - username: str - full_name: Union[str, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item, user: User): - results = {"item_id": item_id, "item": item, "user": user} - return results diff --git a/docs_src/body_multiple_params/tutorial003_an_py39.py b/docs_src/body_multiple_params/tutorial003_an_py39.py deleted file mode 100644 index 042351e0b7..0000000000 --- a/docs_src/body_multiple_params/tutorial003_an_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -class User(BaseModel): - username: str - full_name: Union[str, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - item_id: int, item: Item, user: User, importance: Annotated[int, Body()] -): - results = {"item_id": item_id, "item": item, "user": user, "importance": importance} - return results diff --git a/docs_src/body_multiple_params/tutorial003_py39.py b/docs_src/body_multiple_params/tutorial003_py39.py deleted file mode 100644 index cf344e6c5d..0000000000 --- a/docs_src/body_multiple_params/tutorial003_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -class User(BaseModel): - username: str - full_name: Union[str, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item, user: User, importance: int = Body()): - results = {"item_id": item_id, "item": item, "user": user, "importance": importance} - return results diff --git a/docs_src/body_multiple_params/tutorial004_an_py39.py b/docs_src/body_multiple_params/tutorial004_an_py39.py deleted file mode 100644 index 567427c03e..0000000000 --- a/docs_src/body_multiple_params/tutorial004_an_py39.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -class User(BaseModel): - username: str - full_name: Union[str, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Item, - user: User, - importance: Annotated[int, Body(gt=0)], - q: Union[str, None] = None, -): - results = {"item_id": item_id, "item": item, "user": user, "importance": importance} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/body_multiple_params/tutorial004_py39.py b/docs_src/body_multiple_params/tutorial004_py39.py deleted file mode 100644 index 8ce4c7a976..0000000000 --- a/docs_src/body_multiple_params/tutorial004_py39.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -class User(BaseModel): - username: str - full_name: Union[str, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Item, - user: User, - importance: int = Body(gt=0), - q: Union[str, None] = None, -): - results = {"item_id": item_id, "item": item, "user": user, "importance": importance} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/body_multiple_params/tutorial005_an_py39.py b/docs_src/body_multiple_params/tutorial005_an_py39.py deleted file mode 100644 index 9a52425c16..0000000000 --- a/docs_src/body_multiple_params/tutorial005_an_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_multiple_params/tutorial005_py39.py b/docs_src/body_multiple_params/tutorial005_py39.py deleted file mode 100644 index 29e6e14b7e..0000000000 --- a/docs_src/body_multiple_params/tutorial005_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item = Body(embed=True)): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial001_py39.py b/docs_src/body_nested_models/tutorial001_py39.py deleted file mode 100644 index 37ef6dda58..0000000000 --- a/docs_src/body_nested_models/tutorial001_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: list = [] - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial002_py39.py b/docs_src/body_nested_models/tutorial002_py39.py deleted file mode 100644 index 8a93a7233f..0000000000 --- a/docs_src/body_nested_models/tutorial002_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: list[str] = [] - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial003_py39.py b/docs_src/body_nested_models/tutorial003_py39.py deleted file mode 100644 index b590ece369..0000000000 --- a/docs_src/body_nested_models/tutorial003_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial004_py39.py b/docs_src/body_nested_models/tutorial004_py39.py deleted file mode 100644 index dc2b175fb2..0000000000 --- a/docs_src/body_nested_models/tutorial004_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Image(BaseModel): - url: str - name: str - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - image: Union[Image, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial005_py39.py b/docs_src/body_nested_models/tutorial005_py39.py deleted file mode 100644 index 47db90008a..0000000000 --- a/docs_src/body_nested_models/tutorial005_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, HttpUrl - -app = FastAPI() - - -class Image(BaseModel): - url: HttpUrl - name: str - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - image: Union[Image, None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial006_py39.py b/docs_src/body_nested_models/tutorial006_py39.py deleted file mode 100644 index b14409703a..0000000000 --- a/docs_src/body_nested_models/tutorial006_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, HttpUrl - -app = FastAPI() - - -class Image(BaseModel): - url: HttpUrl - name: str - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - images: Union[list[Image], None] = None - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/body_nested_models/tutorial007_py39.py b/docs_src/body_nested_models/tutorial007_py39.py deleted file mode 100644 index 59cf01e236..0000000000 --- a/docs_src/body_nested_models/tutorial007_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, HttpUrl - -app = FastAPI() - - -class Image(BaseModel): - url: HttpUrl - name: str - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - images: Union[list[Image], None] = None - - -class Offer(BaseModel): - name: str - description: Union[str, None] = None - price: float - items: list[Item] - - -@app.post("/offers/") -async def create_offer(offer: Offer): - return offer diff --git a/docs_src/body_nested_models/tutorial008_py310.py b/docs_src/body_nested_models/tutorial008_py310.py new file mode 100644 index 0000000000..854a7a5a46 --- /dev/null +++ b/docs_src/body_nested_models/tutorial008_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI +from pydantic import BaseModel, HttpUrl + +app = FastAPI() + + +class Image(BaseModel): + url: HttpUrl + name: str + + +@app.post("/images/multiple/") +async def create_multiple_images(images: list[Image]): + return images diff --git a/docs_src/body_nested_models/tutorial009_py310.py b/docs_src/body_nested_models/tutorial009_py310.py new file mode 100644 index 0000000000..59c1e50828 --- /dev/null +++ b/docs_src/body_nested_models/tutorial009_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.post("/index-weights/") +async def create_index_weights(weights: dict[int, float]): + return weights diff --git a/docs_src/body_updates/tutorial001_py39.py b/docs_src/body_updates/tutorial001_py39.py deleted file mode 100644 index 999bcdb82d..0000000000 --- a/docs_src/body_updates/tutorial001_py39.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from fastapi.encoders import jsonable_encoder -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: Union[str, None] = None - description: Union[str, None] = None - price: Union[float, None] = None - tax: float = 10.5 - tags: list[str] = [] - - -items = { - "foo": {"name": "Foo", "price": 50.2}, - "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, - "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}, -} - - -@app.get("/items/{item_id}", response_model=Item) -async def read_item(item_id: str): - return items[item_id] - - -@app.put("/items/{item_id}", response_model=Item) -async def update_item(item_id: str, item: Item): - update_item_encoded = jsonable_encoder(item) - items[item_id] = update_item_encoded - return update_item_encoded diff --git a/docs_src/body_updates/tutorial002_py39.py b/docs_src/body_updates/tutorial002_py39.py deleted file mode 100644 index 3714b5a55d..0000000000 --- a/docs_src/body_updates/tutorial002_py39.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from fastapi.encoders import jsonable_encoder -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: Union[str, None] = None - description: Union[str, None] = None - price: Union[float, None] = None - tax: float = 10.5 - tags: list[str] = [] - - -items = { - "foo": {"name": "Foo", "price": 50.2}, - "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, - "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}, -} - - -@app.get("/items/{item_id}", response_model=Item) -async def read_item(item_id: str): - return items[item_id] - - -@app.patch("/items/{item_id}") -async def update_item(item_id: str, item: Item) -> Item: - stored_item_data = items[item_id] - stored_item_model = Item(**stored_item_data) - update_data = item.model_dump(exclude_unset=True) - updated_item = stored_item_model.model_copy(update=update_data) - items[item_id] = jsonable_encoder(updated_item) - return updated_item diff --git a/docs_src/conditional_openapi/tutorial001_py310.py b/docs_src/conditional_openapi/tutorial001_py310.py new file mode 100644 index 0000000000..eedb0d2742 --- /dev/null +++ b/docs_src/conditional_openapi/tutorial001_py310.py @@ -0,0 +1,16 @@ +from fastapi import FastAPI +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + openapi_url: str = "/openapi.json" + + +settings = Settings() + +app = FastAPI(openapi_url=settings.openapi_url) + + +@app.get("/") +def root(): + return {"message": "Hello World"} diff --git a/docs_src/configure_swagger_ui/tutorial001_py310.py b/docs_src/configure_swagger_ui/tutorial001_py310.py new file mode 100644 index 0000000000..6c24ce7583 --- /dev/null +++ b/docs_src/configure_swagger_ui/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI(swagger_ui_parameters={"syntaxHighlight": False}) + + +@app.get("/users/{username}") +async def read_user(username: str): + return {"message": f"Hello {username}"} diff --git a/docs_src/configure_swagger_ui/tutorial002_py310.py b/docs_src/configure_swagger_ui/tutorial002_py310.py new file mode 100644 index 0000000000..cc75c21968 --- /dev/null +++ b/docs_src/configure_swagger_ui/tutorial002_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI(swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}}) + + +@app.get("/users/{username}") +async def read_user(username: str): + return {"message": f"Hello {username}"} diff --git a/docs_src/configure_swagger_ui/tutorial003_py310.py b/docs_src/configure_swagger_ui/tutorial003_py310.py new file mode 100644 index 0000000000..b4449f5c6a --- /dev/null +++ b/docs_src/configure_swagger_ui/tutorial003_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI(swagger_ui_parameters={"deepLinking": False}) + + +@app.get("/users/{username}") +async def read_user(username: str): + return {"message": f"Hello {username}"} diff --git a/docs_src/cookie_param_models/tutorial001_an_py39.py b/docs_src/cookie_param_models/tutorial001_an_py39.py deleted file mode 100644 index 3d90c2007b..0000000000 --- a/docs_src/cookie_param_models/tutorial001_an_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Cookie, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Cookies(BaseModel): - session_id: str - fatebook_tracker: Union[str, None] = None - googall_tracker: Union[str, None] = None - - -@app.get("/items/") -async def read_items(cookies: Annotated[Cookies, Cookie()]): - return cookies diff --git a/docs_src/cookie_param_models/tutorial001_py39.py b/docs_src/cookie_param_models/tutorial001_py39.py deleted file mode 100644 index cc65c43e1a..0000000000 --- a/docs_src/cookie_param_models/tutorial001_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Union - -from fastapi import Cookie, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Cookies(BaseModel): - session_id: str - fatebook_tracker: Union[str, None] = None - googall_tracker: Union[str, None] = None - - -@app.get("/items/") -async def read_items(cookies: Cookies = Cookie()): - return cookies diff --git a/docs_src/cookie_param_models/tutorial002_an_py39.py b/docs_src/cookie_param_models/tutorial002_an_py39.py deleted file mode 100644 index a906ce6a1c..0000000000 --- a/docs_src/cookie_param_models/tutorial002_an_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Cookie, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Cookies(BaseModel): - model_config = {"extra": "forbid"} - - session_id: str - fatebook_tracker: Union[str, None] = None - googall_tracker: Union[str, None] = None - - -@app.get("/items/") -async def read_items(cookies: Annotated[Cookies, Cookie()]): - return cookies diff --git a/docs_src/cookie_param_models/tutorial002_py39.py b/docs_src/cookie_param_models/tutorial002_py39.py deleted file mode 100644 index 9679e890f6..0000000000 --- a/docs_src/cookie_param_models/tutorial002_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import Cookie, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Cookies(BaseModel): - model_config = {"extra": "forbid"} - - session_id: str - fatebook_tracker: Union[str, None] = None - googall_tracker: Union[str, None] = None - - -@app.get("/items/") -async def read_items(cookies: Cookies = Cookie()): - return cookies diff --git a/docs_src/cookie_params/tutorial001_an_py39.py b/docs_src/cookie_params/tutorial001_an_py39.py deleted file mode 100644 index e18d0a332e..0000000000 --- a/docs_src/cookie_params/tutorial001_an_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Cookie, FastAPI - -app = FastAPI() - - -@app.get("/items/") -async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None): - return {"ads_id": ads_id} diff --git a/docs_src/cookie_params/tutorial001_py39.py b/docs_src/cookie_params/tutorial001_py39.py deleted file mode 100644 index c4a497fda5..0000000000 --- a/docs_src/cookie_params/tutorial001_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Union - -from fastapi import Cookie, FastAPI - -app = FastAPI() - - -@app.get("/items/") -async def read_items(ads_id: Union[str, None] = Cookie(default=None)): - return {"ads_id": ads_id} diff --git a/docs_src/cors/tutorial001_py310.py b/docs_src/cors/tutorial001_py310.py new file mode 100644 index 0000000000..d59ab27acc --- /dev/null +++ b/docs_src/cors/tutorial001_py310.py @@ -0,0 +1,24 @@ +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware + +app = FastAPI() + +origins = [ + "http://localhost.tiangolo.com", + "https://localhost.tiangolo.com", + "http://localhost", + "http://localhost:8080", +] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.get("/") +async def main(): + return {"message": "Hello World"} diff --git a/docs_src/custom_docs_ui/tutorial001_py310.py b/docs_src/custom_docs_ui/tutorial001_py310.py new file mode 100644 index 0000000000..1cfcce19aa --- /dev/null +++ b/docs_src/custom_docs_ui/tutorial001_py310.py @@ -0,0 +1,38 @@ +from fastapi import FastAPI +from fastapi.openapi.docs import ( + get_redoc_html, + get_swagger_ui_html, + get_swagger_ui_oauth2_redirect_html, +) + +app = FastAPI(docs_url=None, redoc_url=None) + + +@app.get("/docs", include_in_schema=False) +async def custom_swagger_ui_html(): + return get_swagger_ui_html( + openapi_url=app.openapi_url, + title=app.title + " - Swagger UI", + oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, + swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js", + swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css", + ) + + +@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) +async def swagger_ui_redirect(): + return get_swagger_ui_oauth2_redirect_html() + + +@app.get("/redoc", include_in_schema=False) +async def redoc_html(): + return get_redoc_html( + openapi_url=app.openapi_url, + title=app.title + " - ReDoc", + redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js", + ) + + +@app.get("/users/{username}") +async def read_user(username: str): + return {"message": f"Hello {username}"} diff --git a/docs_src/custom_docs_ui/tutorial002_py310.py b/docs_src/custom_docs_ui/tutorial002_py310.py new file mode 100644 index 0000000000..23ea368f8b --- /dev/null +++ b/docs_src/custom_docs_ui/tutorial002_py310.py @@ -0,0 +1,41 @@ +from fastapi import FastAPI +from fastapi.openapi.docs import ( + get_redoc_html, + get_swagger_ui_html, + get_swagger_ui_oauth2_redirect_html, +) +from fastapi.staticfiles import StaticFiles + +app = FastAPI(docs_url=None, redoc_url=None) + +app.mount("/static", StaticFiles(directory="static"), name="static") + + +@app.get("/docs", include_in_schema=False) +async def custom_swagger_ui_html(): + return get_swagger_ui_html( + openapi_url=app.openapi_url, + title=app.title + " - Swagger UI", + oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, + swagger_js_url="/static/swagger-ui-bundle.js", + swagger_css_url="/static/swagger-ui.css", + ) + + +@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) +async def swagger_ui_redirect(): + return get_swagger_ui_oauth2_redirect_html() + + +@app.get("/redoc", include_in_schema=False) +async def redoc_html(): + return get_redoc_html( + openapi_url=app.openapi_url, + title=app.title + " - ReDoc", + redoc_js_url="/static/redoc.standalone.js", + ) + + +@app.get("/users/{username}") +async def read_user(username: str): + return {"message": f"Hello {username}"} diff --git a/docs_src/custom_request_and_route/tutorial001_an_py39.py b/docs_src/custom_request_and_route/tutorial001_an_py39.py deleted file mode 100644 index 076727e643..0000000000 --- a/docs_src/custom_request_and_route/tutorial001_an_py39.py +++ /dev/null @@ -1,35 +0,0 @@ -import gzip -from typing import Annotated, Callable - -from fastapi import Body, FastAPI, Request, Response -from fastapi.routing import APIRoute - - -class GzipRequest(Request): - async def body(self) -> bytes: - if not hasattr(self, "_body"): - body = await super().body() - if "gzip" in self.headers.getlist("Content-Encoding"): - body = gzip.decompress(body) - self._body = body - return self._body - - -class GzipRoute(APIRoute): - def get_route_handler(self) -> Callable: - original_route_handler = super().get_route_handler() - - async def custom_route_handler(request: Request) -> Response: - request = GzipRequest(request.scope, request.receive) - return await original_route_handler(request) - - return custom_route_handler - - -app = FastAPI() -app.router.route_class = GzipRoute - - -@app.post("/sum") -async def sum_numbers(numbers: Annotated[list[int], Body()]): - return {"sum": sum(numbers)} diff --git a/docs_src/custom_request_and_route/tutorial001_py39.py b/docs_src/custom_request_and_route/tutorial001_py39.py deleted file mode 100644 index 54b20b9425..0000000000 --- a/docs_src/custom_request_and_route/tutorial001_py39.py +++ /dev/null @@ -1,35 +0,0 @@ -import gzip -from typing import Callable - -from fastapi import Body, FastAPI, Request, Response -from fastapi.routing import APIRoute - - -class GzipRequest(Request): - async def body(self) -> bytes: - if not hasattr(self, "_body"): - body = await super().body() - if "gzip" in self.headers.getlist("Content-Encoding"): - body = gzip.decompress(body) - self._body = body - return self._body - - -class GzipRoute(APIRoute): - def get_route_handler(self) -> Callable: - original_route_handler = super().get_route_handler() - - async def custom_route_handler(request: Request) -> Response: - request = GzipRequest(request.scope, request.receive) - return await original_route_handler(request) - - return custom_route_handler - - -app = FastAPI() -app.router.route_class = GzipRoute - - -@app.post("/sum") -async def sum_numbers(numbers: list[int] = Body()): - return {"sum": sum(numbers)} diff --git a/docs_src/custom_request_and_route/tutorial002_an_py39.py b/docs_src/custom_request_and_route/tutorial002_an_py39.py deleted file mode 100644 index e7de09de44..0000000000 --- a/docs_src/custom_request_and_route/tutorial002_an_py39.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Annotated, Callable - -from fastapi import Body, FastAPI, HTTPException, Request, Response -from fastapi.exceptions import RequestValidationError -from fastapi.routing import APIRoute - - -class ValidationErrorLoggingRoute(APIRoute): - def get_route_handler(self) -> Callable: - original_route_handler = super().get_route_handler() - - async def custom_route_handler(request: Request) -> Response: - try: - return await original_route_handler(request) - except RequestValidationError as exc: - body = await request.body() - detail = {"errors": exc.errors(), "body": body.decode()} - raise HTTPException(status_code=422, detail=detail) - - return custom_route_handler - - -app = FastAPI() -app.router.route_class = ValidationErrorLoggingRoute - - -@app.post("/") -async def sum_numbers(numbers: Annotated[list[int], Body()]): - return sum(numbers) diff --git a/docs_src/custom_request_and_route/tutorial002_py39.py b/docs_src/custom_request_and_route/tutorial002_py39.py deleted file mode 100644 index c4e4748281..0000000000 --- a/docs_src/custom_request_and_route/tutorial002_py39.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Callable - -from fastapi import Body, FastAPI, HTTPException, Request, Response -from fastapi.exceptions import RequestValidationError -from fastapi.routing import APIRoute - - -class ValidationErrorLoggingRoute(APIRoute): - def get_route_handler(self) -> Callable: - original_route_handler = super().get_route_handler() - - async def custom_route_handler(request: Request) -> Response: - try: - return await original_route_handler(request) - except RequestValidationError as exc: - body = await request.body() - detail = {"errors": exc.errors(), "body": body.decode()} - raise HTTPException(status_code=422, detail=detail) - - return custom_route_handler - - -app = FastAPI() -app.router.route_class = ValidationErrorLoggingRoute - - -@app.post("/") -async def sum_numbers(numbers: list[int] = Body()): - return sum(numbers) diff --git a/docs_src/custom_request_and_route/tutorial003_py39.py b/docs_src/custom_request_and_route/tutorial003_py39.py deleted file mode 100644 index aabe760685..0000000000 --- a/docs_src/custom_request_and_route/tutorial003_py39.py +++ /dev/null @@ -1,39 +0,0 @@ -import time -from typing import Callable - -from fastapi import APIRouter, FastAPI, Request, Response -from fastapi.routing import APIRoute - - -class TimedRoute(APIRoute): - def get_route_handler(self) -> Callable: - original_route_handler = super().get_route_handler() - - async def custom_route_handler(request: Request) -> Response: - before = time.time() - response: Response = await original_route_handler(request) - duration = time.time() - before - response.headers["X-Response-Time"] = str(duration) - print(f"route duration: {duration}") - print(f"route response: {response}") - print(f"route response headers: {response.headers}") - return response - - return custom_route_handler - - -app = FastAPI() -router = APIRouter(route_class=TimedRoute) - - -@app.get("/") -async def not_timed(): - return {"message": "Not timed"} - - -@router.get("/timed") -async def timed(): - return {"message": "It's the time of my life"} - - -app.include_router(router) diff --git a/docs_src/custom_response/tutorial001_py310.py b/docs_src/custom_response/tutorial001_py310.py new file mode 100644 index 0000000000..0f09bdf77f --- /dev/null +++ b/docs_src/custom_response/tutorial001_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import UJSONResponse + +app = FastAPI() + + +@app.get("/items/", response_class=UJSONResponse) +async def read_items(): + return [{"item_id": "Foo"}] diff --git a/docs_src/custom_response/tutorial001b_py310.py b/docs_src/custom_response/tutorial001b_py310.py new file mode 100644 index 0000000000..95e6ca7637 --- /dev/null +++ b/docs_src/custom_response/tutorial001b_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import ORJSONResponse + +app = FastAPI() + + +@app.get("/items/", response_class=ORJSONResponse) +async def read_items(): + return ORJSONResponse([{"item_id": "Foo"}]) diff --git a/docs_src/custom_response/tutorial002_py310.py b/docs_src/custom_response/tutorial002_py310.py new file mode 100644 index 0000000000..23c495867b --- /dev/null +++ b/docs_src/custom_response/tutorial002_py310.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.get("/items/", response_class=HTMLResponse) +async def read_items(): + return """ + + + Some HTML in here + + +

Look ma! HTML!

+ + + """ diff --git a/docs_src/custom_response/tutorial003_py310.py b/docs_src/custom_response/tutorial003_py310.py new file mode 100644 index 0000000000..51ad3c146b --- /dev/null +++ b/docs_src/custom_response/tutorial003_py310.py @@ -0,0 +1,19 @@ +from fastapi import FastAPI +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.get("/items/") +async def read_items(): + html_content = """ + + + Some HTML in here + + +

Look ma! HTML!

+ + + """ + return HTMLResponse(content=html_content, status_code=200) diff --git a/docs_src/custom_response/tutorial004_py310.py b/docs_src/custom_response/tutorial004_py310.py new file mode 100644 index 0000000000..0e90f20126 --- /dev/null +++ b/docs_src/custom_response/tutorial004_py310.py @@ -0,0 +1,23 @@ +from fastapi import FastAPI +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +def generate_html_response(): + html_content = """ + + + Some HTML in here + + +

Look ma! HTML!

+ + + """ + return HTMLResponse(content=html_content, status_code=200) + + +@app.get("/items/", response_class=HTMLResponse) +async def read_items(): + return generate_html_response() diff --git a/docs_src/custom_response/tutorial005_py310.py b/docs_src/custom_response/tutorial005_py310.py new file mode 100644 index 0000000000..3d58f57fb6 --- /dev/null +++ b/docs_src/custom_response/tutorial005_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import PlainTextResponse + +app = FastAPI() + + +@app.get("/", response_class=PlainTextResponse) +async def main(): + return "Hello World" diff --git a/docs_src/custom_response/tutorial006_py310.py b/docs_src/custom_response/tutorial006_py310.py new file mode 100644 index 0000000000..332f8f87f1 --- /dev/null +++ b/docs_src/custom_response/tutorial006_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import RedirectResponse + +app = FastAPI() + + +@app.get("/typer") +async def redirect_typer(): + return RedirectResponse("https://typer.tiangolo.com") diff --git a/docs_src/custom_response/tutorial006b_py310.py b/docs_src/custom_response/tutorial006b_py310.py new file mode 100644 index 0000000000..03a7be3995 --- /dev/null +++ b/docs_src/custom_response/tutorial006b_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import RedirectResponse + +app = FastAPI() + + +@app.get("/fastapi", response_class=RedirectResponse) +async def redirect_fastapi(): + return "https://fastapi.tiangolo.com" diff --git a/docs_src/custom_response/tutorial006c_py310.py b/docs_src/custom_response/tutorial006c_py310.py new file mode 100644 index 0000000000..87c720364b --- /dev/null +++ b/docs_src/custom_response/tutorial006c_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import RedirectResponse + +app = FastAPI() + + +@app.get("/pydantic", response_class=RedirectResponse, status_code=302) +async def redirect_pydantic(): + return "https://docs.pydantic.dev/" diff --git a/docs_src/custom_response/tutorial007_py310.py b/docs_src/custom_response/tutorial007_py310.py new file mode 100644 index 0000000000..e2a53a2119 --- /dev/null +++ b/docs_src/custom_response/tutorial007_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI +from fastapi.responses import StreamingResponse + +app = FastAPI() + + +async def fake_video_streamer(): + for i in range(10): + yield b"some fake video bytes" + + +@app.get("/") +async def main(): + return StreamingResponse(fake_video_streamer()) diff --git a/docs_src/custom_response/tutorial008_py310.py b/docs_src/custom_response/tutorial008_py310.py new file mode 100644 index 0000000000..fc071cbee4 --- /dev/null +++ b/docs_src/custom_response/tutorial008_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI +from fastapi.responses import StreamingResponse + +some_file_path = "large-video-file.mp4" +app = FastAPI() + + +@app.get("/") +def main(): + def iterfile(): # (1) + with open(some_file_path, mode="rb") as file_like: # (2) + yield from file_like # (3) + + return StreamingResponse(iterfile(), media_type="video/mp4") diff --git a/docs_src/custom_response/tutorial009_py310.py b/docs_src/custom_response/tutorial009_py310.py new file mode 100644 index 0000000000..71cf50cc18 --- /dev/null +++ b/docs_src/custom_response/tutorial009_py310.py @@ -0,0 +1,10 @@ +from fastapi import FastAPI +from fastapi.responses import FileResponse + +some_file_path = "large-video-file.mp4" +app = FastAPI() + + +@app.get("/") +async def main(): + return FileResponse(some_file_path) diff --git a/docs_src/custom_response/tutorial009b_py310.py b/docs_src/custom_response/tutorial009b_py310.py new file mode 100644 index 0000000000..27200ee4ba --- /dev/null +++ b/docs_src/custom_response/tutorial009b_py310.py @@ -0,0 +1,10 @@ +from fastapi import FastAPI +from fastapi.responses import FileResponse + +some_file_path = "large-video-file.mp4" +app = FastAPI() + + +@app.get("/", response_class=FileResponse) +async def main(): + return some_file_path diff --git a/docs_src/custom_response/tutorial009c_py310.py b/docs_src/custom_response/tutorial009c_py310.py new file mode 100644 index 0000000000..de6b6688e6 --- /dev/null +++ b/docs_src/custom_response/tutorial009c_py310.py @@ -0,0 +1,19 @@ +from typing import Any + +import orjson +from fastapi import FastAPI, Response + +app = FastAPI() + + +class CustomORJSONResponse(Response): + media_type = "application/json" + + def render(self, content: Any) -> bytes: + assert orjson is not None, "orjson must be installed" + return orjson.dumps(content, option=orjson.OPT_INDENT_2) + + +@app.get("/", response_class=CustomORJSONResponse) +async def main(): + return {"message": "Hello World"} diff --git a/docs_src/custom_response/tutorial010_py310.py b/docs_src/custom_response/tutorial010_py310.py new file mode 100644 index 0000000000..57cb062604 --- /dev/null +++ b/docs_src/custom_response/tutorial010_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import ORJSONResponse + +app = FastAPI(default_response_class=ORJSONResponse) + + +@app.get("/items/") +async def read_items(): + return [{"item_id": "Foo"}] diff --git a/docs_src/dataclasses_/tutorial001_py39.py b/docs_src/dataclasses_/tutorial001_py39.py deleted file mode 100644 index 2954c391f1..0000000000 --- a/docs_src/dataclasses_/tutorial001_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from dataclasses import dataclass -from typing import Union - -from fastapi import FastAPI - - -@dataclass -class Item: - name: str - price: float - description: Union[str, None] = None - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item): - return item diff --git a/docs_src/dataclasses_/tutorial002_py39.py b/docs_src/dataclasses_/tutorial002_py39.py deleted file mode 100644 index 0c23765d84..0000000000 --- a/docs_src/dataclasses_/tutorial002_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from dataclasses import dataclass, field -from typing import Union - -from fastapi import FastAPI - - -@dataclass -class Item: - name: str - price: float - tags: list[str] = field(default_factory=list) - description: Union[str, None] = None - tax: Union[float, None] = None - - -app = FastAPI() - - -@app.get("/items/next", response_model=Item) -async def read_next_item(): - return { - "name": "Island In The Moon", - "price": 12.99, - "description": "A place to be playin' and havin' fun", - "tags": ["breater"], - } diff --git a/docs_src/dataclasses_/tutorial003_py39.py b/docs_src/dataclasses_/tutorial003_py39.py deleted file mode 100644 index 991708c009..0000000000 --- a/docs_src/dataclasses_/tutorial003_py39.py +++ /dev/null @@ -1,55 +0,0 @@ -from dataclasses import field # (1) -from typing import Union - -from fastapi import FastAPI -from pydantic.dataclasses import dataclass # (2) - - -@dataclass -class Item: - name: str - description: Union[str, None] = None - - -@dataclass -class Author: - name: str - items: list[Item] = field(default_factory=list) # (3) - - -app = FastAPI() - - -@app.post("/authors/{author_id}/items/", response_model=Author) # (4) -async def create_author_items(author_id: str, items: list[Item]): # (5) - return {"name": author_id, "items": items} # (6) - - -@app.get("/authors/", response_model=list[Author]) # (7) -def get_authors(): # (8) - return [ # (9) - { - "name": "Breaters", - "items": [ - { - "name": "Island In The Moon", - "description": "A place to be playin' and havin' fun", - }, - {"name": "Holy Buddies"}, - ], - }, - { - "name": "System of an Up", - "items": [ - { - "name": "Salt", - "description": "The kombucha mushroom people's favorite", - }, - {"name": "Pad Thai"}, - { - "name": "Lonely Night", - "description": "The mostests lonliest nightiest of allest", - }, - ], - }, - ] diff --git a/docs_src/debugging/tutorial001_py310.py b/docs_src/debugging/tutorial001_py310.py new file mode 100644 index 0000000000..3de21d2a82 --- /dev/null +++ b/docs_src/debugging/tutorial001_py310.py @@ -0,0 +1,15 @@ +import uvicorn +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def root(): + a = "a" + b = "b" + a + return {"hello world": b} + + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/docs_src/dependencies/tutorial001_02_an_py39.py b/docs_src/dependencies/tutorial001_02_an_py39.py deleted file mode 100644 index df969ae9c8..0000000000 --- a/docs_src/dependencies/tutorial001_02_an_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 -): - return {"q": q, "skip": skip, "limit": limit} - - -CommonsDep = Annotated[dict, Depends(common_parameters)] - - -@app.get("/items/") -async def read_items(commons: CommonsDep): - return commons - - -@app.get("/users/") -async def read_users(commons: CommonsDep): - return commons diff --git a/docs_src/dependencies/tutorial001_an_py39.py b/docs_src/dependencies/tutorial001_an_py39.py deleted file mode 100644 index 5d9fe6ddfd..0000000000 --- a/docs_src/dependencies/tutorial001_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 -): - return {"q": q, "skip": skip, "limit": limit} - - -@app.get("/items/") -async def read_items(commons: Annotated[dict, Depends(common_parameters)]): - return commons - - -@app.get("/users/") -async def read_users(commons: Annotated[dict, Depends(common_parameters)]): - return commons diff --git a/docs_src/dependencies/tutorial001_py39.py b/docs_src/dependencies/tutorial001_py39.py deleted file mode 100644 index b1275103a0..0000000000 --- a/docs_src/dependencies/tutorial001_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 -): - return {"q": q, "skip": skip, "limit": limit} - - -@app.get("/items/") -async def read_items(commons: dict = Depends(common_parameters)): - return commons - - -@app.get("/users/") -async def read_users(commons: dict = Depends(common_parameters)): - return commons diff --git a/docs_src/dependencies/tutorial002_an_py39.py b/docs_src/dependencies/tutorial002_an_py39.py deleted file mode 100644 index 844a23c5a7..0000000000 --- a/docs_src/dependencies/tutorial002_an_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial002_py39.py b/docs_src/dependencies/tutorial002_py39.py deleted file mode 100644 index 8e863e4fab..0000000000 --- a/docs_src/dependencies/tutorial002_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial003_an_py39.py b/docs_src/dependencies/tutorial003_an_py39.py deleted file mode 100644 index 9e9123ad2f..0000000000 --- a/docs_src/dependencies/tutorial003_an_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Annotated, Any, Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial003_py39.py b/docs_src/dependencies/tutorial003_py39.py deleted file mode 100644 index 34614e5397..0000000000 --- a/docs_src/dependencies/tutorial003_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons=Depends(CommonQueryParams)): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial004_an_py39.py b/docs_src/dependencies/tutorial004_an_py39.py deleted file mode 100644 index 74268626b4..0000000000 --- a/docs_src/dependencies/tutorial004_an_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons: Annotated[CommonQueryParams, Depends()]): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial004_py39.py b/docs_src/dependencies/tutorial004_py39.py deleted file mode 100644 index d9fe881488..0000000000 --- a/docs_src/dependencies/tutorial004_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): - self.q = q - self.skip = skip - self.limit = limit - - -@app.get("/items/") -async def read_items(commons: CommonQueryParams = Depends()): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response diff --git a/docs_src/dependencies/tutorial005_an_py39.py b/docs_src/dependencies/tutorial005_an_py39.py deleted file mode 100644 index d5dd8dca9a..0000000000 --- a/docs_src/dependencies/tutorial005_an_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Cookie, Depends, FastAPI - -app = FastAPI() - - -def query_extractor(q: Union[str, None] = None): - return q - - -def query_or_cookie_extractor( - q: Annotated[str, Depends(query_extractor)], - last_query: Annotated[Union[str, None], Cookie()] = None, -): - if not q: - return last_query - return q - - -@app.get("/items/") -async def read_query( - query_or_default: Annotated[str, Depends(query_or_cookie_extractor)], -): - return {"q_or_cookie": query_or_default} diff --git a/docs_src/dependencies/tutorial005_py39.py b/docs_src/dependencies/tutorial005_py39.py deleted file mode 100644 index 697332b5ba..0000000000 --- a/docs_src/dependencies/tutorial005_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Union - -from fastapi import Cookie, Depends, FastAPI - -app = FastAPI() - - -def query_extractor(q: Union[str, None] = None): - return q - - -def query_or_cookie_extractor( - q: str = Depends(query_extractor), - last_query: Union[str, None] = Cookie(default=None), -): - if not q: - return last_query - return q - - -@app.get("/items/") -async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): - return {"q_or_cookie": query_or_default} diff --git a/docs_src/dependencies/tutorial006_an_py310.py b/docs_src/dependencies/tutorial006_an_py310.py new file mode 100644 index 0000000000..11976ed6a2 --- /dev/null +++ b/docs_src/dependencies/tutorial006_an_py310.py @@ -0,0 +1,21 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, Header, HTTPException + +app = FastAPI() + + +async def verify_token(x_token: Annotated[str, Header()]): + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token header invalid") + + +async def verify_key(x_key: Annotated[str, Header()]): + if x_key != "fake-super-secret-key": + raise HTTPException(status_code=400, detail="X-Key header invalid") + return x_key + + +@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) +async def read_items(): + return [{"item": "Foo"}, {"item": "Bar"}] diff --git a/docs_src/dependencies/tutorial006_py310.py b/docs_src/dependencies/tutorial006_py310.py new file mode 100644 index 0000000000..9aff4154f4 --- /dev/null +++ b/docs_src/dependencies/tutorial006_py310.py @@ -0,0 +1,19 @@ +from fastapi import Depends, FastAPI, Header, HTTPException + +app = FastAPI() + + +async def verify_token(x_token: str = Header()): + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token header invalid") + + +async def verify_key(x_key: str = Header()): + if x_key != "fake-super-secret-key": + raise HTTPException(status_code=400, detail="X-Key header invalid") + return x_key + + +@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) +async def read_items(): + return [{"item": "Foo"}, {"item": "Bar"}] diff --git a/docs_src/dependencies/tutorial007_py310.py b/docs_src/dependencies/tutorial007_py310.py new file mode 100644 index 0000000000..2e4ab4777b --- /dev/null +++ b/docs_src/dependencies/tutorial007_py310.py @@ -0,0 +1,6 @@ +async def get_db(): + db = DBSession() + try: + yield db + finally: + db.close() diff --git a/docs_src/dependencies/tutorial008_an_py310.py b/docs_src/dependencies/tutorial008_an_py310.py new file mode 100644 index 0000000000..acc804c320 --- /dev/null +++ b/docs_src/dependencies/tutorial008_an_py310.py @@ -0,0 +1,27 @@ +from typing import Annotated + +from fastapi import Depends + + +async def dependency_a(): + dep_a = generate_dep_a() + try: + yield dep_a + finally: + dep_a.close() + + +async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]): + dep_b = generate_dep_b() + try: + yield dep_b + finally: + dep_b.close(dep_a) + + +async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]): + dep_c = generate_dep_c() + try: + yield dep_c + finally: + dep_c.close(dep_b) diff --git a/docs_src/dependencies/tutorial008_py310.py b/docs_src/dependencies/tutorial008_py310.py new file mode 100644 index 0000000000..8472f642de --- /dev/null +++ b/docs_src/dependencies/tutorial008_py310.py @@ -0,0 +1,25 @@ +from fastapi import Depends + + +async def dependency_a(): + dep_a = generate_dep_a() + try: + yield dep_a + finally: + dep_a.close() + + +async def dependency_b(dep_a=Depends(dependency_a)): + dep_b = generate_dep_b() + try: + yield dep_b + finally: + dep_b.close(dep_a) + + +async def dependency_c(dep_b=Depends(dependency_b)): + dep_c = generate_dep_c() + try: + yield dep_c + finally: + dep_c.close(dep_b) diff --git a/docs_src/dependencies/tutorial008b_an_py310.py b/docs_src/dependencies/tutorial008b_an_py310.py new file mode 100644 index 0000000000..3b8434c816 --- /dev/null +++ b/docs_src/dependencies/tutorial008b_an_py310.py @@ -0,0 +1,32 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +data = { + "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"}, + "portal-gun": {"description": "Gun to create portals", "owner": "Rick"}, +} + + +class OwnerError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except OwnerError as e: + raise HTTPException(status_code=400, detail=f"Owner error: {e}") + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): + if item_id not in data: + raise HTTPException(status_code=404, detail="Item not found") + item = data[item_id] + if item["owner"] != username: + raise OwnerError(username) + return item diff --git a/docs_src/dependencies/tutorial008b_py310.py b/docs_src/dependencies/tutorial008b_py310.py new file mode 100644 index 0000000000..163e96600f --- /dev/null +++ b/docs_src/dependencies/tutorial008b_py310.py @@ -0,0 +1,30 @@ +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +data = { + "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"}, + "portal-gun": {"description": "Gun to create portals", "owner": "Rick"}, +} + + +class OwnerError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except OwnerError as e: + raise HTTPException(status_code=400, detail=f"Owner error: {e}") + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: str = Depends(get_username)): + if item_id not in data: + raise HTTPException(status_code=404, detail="Item not found") + item = data[item_id] + if item["owner"] != username: + raise OwnerError(username) + return item diff --git a/docs_src/dependencies/tutorial008c_an_py310.py b/docs_src/dependencies/tutorial008c_an_py310.py new file mode 100644 index 0000000000..da92efa9c3 --- /dev/null +++ b/docs_src/dependencies/tutorial008c_an_py310.py @@ -0,0 +1,29 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +class InternalError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except InternalError: + print("Oops, we didn't raise again, Britney ๐Ÿ˜ฑ") + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): + if item_id == "portal-gun": + raise InternalError( + f"The portal gun is too dangerous to be owned by {username}" + ) + if item_id != "plumbus": + raise HTTPException( + status_code=404, detail="Item not found, there's only a plumbus here" + ) + return item_id diff --git a/docs_src/dependencies/tutorial008c_py310.py b/docs_src/dependencies/tutorial008c_py310.py new file mode 100644 index 0000000000..4b99a5a311 --- /dev/null +++ b/docs_src/dependencies/tutorial008c_py310.py @@ -0,0 +1,27 @@ +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +class InternalError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except InternalError: + print("Oops, we didn't raise again, Britney ๐Ÿ˜ฑ") + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: str = Depends(get_username)): + if item_id == "portal-gun": + raise InternalError( + f"The portal gun is too dangerous to be owned by {username}" + ) + if item_id != "plumbus": + raise HTTPException( + status_code=404, detail="Item not found, there's only a plumbus here" + ) + return item_id diff --git a/docs_src/dependencies/tutorial008d_an_py310.py b/docs_src/dependencies/tutorial008d_an_py310.py new file mode 100644 index 0000000000..99bd5cb911 --- /dev/null +++ b/docs_src/dependencies/tutorial008d_an_py310.py @@ -0,0 +1,30 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +class InternalError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except InternalError: + print("We don't swallow the internal error here, we raise again ๐Ÿ˜Ž") + raise + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): + if item_id == "portal-gun": + raise InternalError( + f"The portal gun is too dangerous to be owned by {username}" + ) + if item_id != "plumbus": + raise HTTPException( + status_code=404, detail="Item not found, there's only a plumbus here" + ) + return item_id diff --git a/docs_src/dependencies/tutorial008d_py310.py b/docs_src/dependencies/tutorial008d_py310.py new file mode 100644 index 0000000000..93039343d1 --- /dev/null +++ b/docs_src/dependencies/tutorial008d_py310.py @@ -0,0 +1,28 @@ +from fastapi import Depends, FastAPI, HTTPException + +app = FastAPI() + + +class InternalError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except InternalError: + print("We don't swallow the internal error here, we raise again ๐Ÿ˜Ž") + raise + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: str = Depends(get_username)): + if item_id == "portal-gun": + raise InternalError( + f"The portal gun is too dangerous to be owned by {username}" + ) + if item_id != "plumbus": + raise HTTPException( + status_code=404, detail="Item not found, there's only a plumbus here" + ) + return item_id diff --git a/docs_src/dependencies/tutorial008e_an_py310.py b/docs_src/dependencies/tutorial008e_an_py310.py new file mode 100644 index 0000000000..80a44c7e23 --- /dev/null +++ b/docs_src/dependencies/tutorial008e_an_py310.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): + return username diff --git a/docs_src/dependencies/tutorial008e_py310.py b/docs_src/dependencies/tutorial008e_py310.py new file mode 100644 index 0000000000..1ed056e91e --- /dev/null +++ b/docs_src/dependencies/tutorial008e_py310.py @@ -0,0 +1,15 @@ +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: str = Depends(get_username, scope="function")): + return username diff --git a/docs_src/dependencies/tutorial010_py310.py b/docs_src/dependencies/tutorial010_py310.py new file mode 100644 index 0000000000..c27f1b1702 --- /dev/null +++ b/docs_src/dependencies/tutorial010_py310.py @@ -0,0 +1,14 @@ +class MySuperContextManager: + def __init__(self): + self.db = DBSession() + + def __enter__(self): + return self.db + + def __exit__(self, exc_type, exc_value, traceback): + self.db.close() + + +async def get_db(): + with MySuperContextManager() as db: + yield db diff --git a/docs_src/dependencies/tutorial011_an_py310.py b/docs_src/dependencies/tutorial011_an_py310.py new file mode 100644 index 0000000000..68b7434ec2 --- /dev/null +++ b/docs_src/dependencies/tutorial011_an_py310.py @@ -0,0 +1,23 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI + +app = FastAPI() + + +class FixedContentQueryChecker: + def __init__(self, fixed_content: str): + self.fixed_content = fixed_content + + def __call__(self, q: str = ""): + if q: + return self.fixed_content in q + return False + + +checker = FixedContentQueryChecker("bar") + + +@app.get("/query-checker/") +async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]): + return {"fixed_content_in_query": fixed_content_included} diff --git a/docs_src/dependencies/tutorial011_py310.py b/docs_src/dependencies/tutorial011_py310.py new file mode 100644 index 0000000000..5d22f68237 --- /dev/null +++ b/docs_src/dependencies/tutorial011_py310.py @@ -0,0 +1,21 @@ +from fastapi import Depends, FastAPI + +app = FastAPI() + + +class FixedContentQueryChecker: + def __init__(self, fixed_content: str): + self.fixed_content = fixed_content + + def __call__(self, q: str = ""): + if q: + return self.fixed_content in q + return False + + +checker = FixedContentQueryChecker("bar") + + +@app.get("/query-checker/") +async def read_query_check(fixed_content_included: bool = Depends(checker)): + return {"fixed_content_in_query": fixed_content_included} diff --git a/docs_src/dependencies/tutorial012_an_py310.py b/docs_src/dependencies/tutorial012_an_py310.py new file mode 100644 index 0000000000..6503591fc3 --- /dev/null +++ b/docs_src/dependencies/tutorial012_an_py310.py @@ -0,0 +1,27 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI, Header, HTTPException + + +async def verify_token(x_token: Annotated[str, Header()]): + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token header invalid") + + +async def verify_key(x_key: Annotated[str, Header()]): + if x_key != "fake-super-secret-key": + raise HTTPException(status_code=400, detail="X-Key header invalid") + return x_key + + +app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]) + + +@app.get("/items/") +async def read_items(): + return [{"item": "Portal Gun"}, {"item": "Plumbus"}] + + +@app.get("/users/") +async def read_users(): + return [{"username": "Rick"}, {"username": "Morty"}] diff --git a/docs_src/dependencies/tutorial012_py310.py b/docs_src/dependencies/tutorial012_py310.py new file mode 100644 index 0000000000..36ce6c7111 --- /dev/null +++ b/docs_src/dependencies/tutorial012_py310.py @@ -0,0 +1,25 @@ +from fastapi import Depends, FastAPI, Header, HTTPException + + +async def verify_token(x_token: str = Header()): + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token header invalid") + + +async def verify_key(x_key: str = Header()): + if x_key != "fake-super-secret-key": + raise HTTPException(status_code=400, detail="X-Key header invalid") + return x_key + + +app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]) + + +@app.get("/items/") +async def read_items(): + return [{"item": "Portal Gun"}, {"item": "Plumbus"}] + + +@app.get("/users/") +async def read_users(): + return [{"username": "Rick"}, {"username": "Morty"}] diff --git a/docs_src/dependency_testing/tutorial001_an_py39.py b/docs_src/dependency_testing/tutorial001_an_py39.py deleted file mode 100644 index bccb0cdb1f..0000000000 --- a/docs_src/dependency_testing/tutorial001_an_py39.py +++ /dev/null @@ -1,59 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI -from fastapi.testclient import TestClient - -app = FastAPI() - - -async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 -): - return {"q": q, "skip": skip, "limit": limit} - - -@app.get("/items/") -async def read_items(commons: Annotated[dict, Depends(common_parameters)]): - return {"message": "Hello Items!", "params": commons} - - -@app.get("/users/") -async def read_users(commons: Annotated[dict, Depends(common_parameters)]): - return {"message": "Hello Users!", "params": commons} - - -client = TestClient(app) - - -async def override_dependency(q: Union[str, None] = None): - return {"q": q, "skip": 5, "limit": 10} - - -app.dependency_overrides[common_parameters] = override_dependency - - -def test_override_in_items(): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -def test_override_in_items_with_q(): - response = client.get("/items/?q=foo") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -def test_override_in_items_with_params(): - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } diff --git a/docs_src/dependency_testing/tutorial001_py39.py b/docs_src/dependency_testing/tutorial001_py39.py deleted file mode 100644 index a5fe1d9bff..0000000000 --- a/docs_src/dependency_testing/tutorial001_py39.py +++ /dev/null @@ -1,59 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI -from fastapi.testclient import TestClient - -app = FastAPI() - - -async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 -): - return {"q": q, "skip": skip, "limit": limit} - - -@app.get("/items/") -async def read_items(commons: dict = Depends(common_parameters)): - return {"message": "Hello Items!", "params": commons} - - -@app.get("/users/") -async def read_users(commons: dict = Depends(common_parameters)): - return {"message": "Hello Users!", "params": commons} - - -client = TestClient(app) - - -async def override_dependency(q: Union[str, None] = None): - return {"q": q, "skip": 5, "limit": 10} - - -app.dependency_overrides[common_parameters] = override_dependency - - -def test_override_in_items(): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -def test_override_in_items_with_q(): - response = client.get("/items/?q=foo") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -def test_override_in_items_with_params(): - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200 - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } diff --git a/docs_src/encoder/tutorial001_py39.py b/docs_src/encoder/tutorial001_py39.py deleted file mode 100644 index 5f7e7061e4..0000000000 --- a/docs_src/encoder/tutorial001_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from datetime import datetime -from typing import Union - -from fastapi import FastAPI -from fastapi.encoders import jsonable_encoder -from pydantic import BaseModel - -fake_db = {} - - -class Item(BaseModel): - title: str - timestamp: datetime - description: Union[str, None] = None - - -app = FastAPI() - - -@app.put("/items/{id}") -def update_item(id: str, item: Item): - json_compatible_item_data = jsonable_encoder(item) - fake_db[id] = json_compatible_item_data diff --git a/docs_src/events/tutorial001_py310.py b/docs_src/events/tutorial001_py310.py new file mode 100644 index 0000000000..128004c9fb --- /dev/null +++ b/docs_src/events/tutorial001_py310.py @@ -0,0 +1,16 @@ +from fastapi import FastAPI + +app = FastAPI() + +items = {} + + +@app.on_event("startup") +async def startup_event(): + items["foo"] = {"name": "Fighters"} + items["bar"] = {"name": "Tenders"} + + +@app.get("/items/{item_id}") +async def read_items(item_id: str): + return items[item_id] diff --git a/docs_src/events/tutorial002_py310.py b/docs_src/events/tutorial002_py310.py new file mode 100644 index 0000000000..a71fea8025 --- /dev/null +++ b/docs_src/events/tutorial002_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.on_event("shutdown") +def shutdown_event(): + with open("log.txt", mode="a") as log: + log.write("Application shutdown") + + +@app.get("/items/") +async def read_items(): + return [{"name": "Foo"}] diff --git a/docs_src/events/tutorial003_py310.py b/docs_src/events/tutorial003_py310.py new file mode 100644 index 0000000000..2b650590b0 --- /dev/null +++ b/docs_src/events/tutorial003_py310.py @@ -0,0 +1,28 @@ +from contextlib import asynccontextmanager + +from fastapi import FastAPI + + +def fake_answer_to_everything_ml_model(x: float): + return x * 42 + + +ml_models = {} + + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Load the ML model + ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model + yield + # Clean up the ML models and release the resources + ml_models.clear() + + +app = FastAPI(lifespan=lifespan) + + +@app.get("/predict") +async def predict(x: float): + result = ml_models["answer_to_everything"](x) + return {"result": result} diff --git a/docs_src/extending_openapi/tutorial001_py310.py b/docs_src/extending_openapi/tutorial001_py310.py new file mode 100644 index 0000000000..35e31c0e0c --- /dev/null +++ b/docs_src/extending_openapi/tutorial001_py310.py @@ -0,0 +1,29 @@ +from fastapi import FastAPI +from fastapi.openapi.utils import get_openapi + +app = FastAPI() + + +@app.get("/items/") +async def read_items(): + return [{"name": "Foo"}] + + +def custom_openapi(): + if app.openapi_schema: + return app.openapi_schema + openapi_schema = get_openapi( + title="Custom title", + version="2.5.0", + summary="This is a very custom OpenAPI schema", + description="Here's a longer description of the custom **OpenAPI** schema", + routes=app.routes, + ) + openapi_schema["info"]["x-logo"] = { + "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" + } + app.openapi_schema = openapi_schema + return app.openapi_schema + + +app.openapi = custom_openapi diff --git a/docs_src/extra_data_types/tutorial001_an_py39.py b/docs_src/extra_data_types/tutorial001_an_py39.py deleted file mode 100644 index fa3551d665..0000000000 --- a/docs_src/extra_data_types/tutorial001_an_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from datetime import datetime, time, timedelta -from typing import Annotated, Union -from uuid import UUID - -from fastapi import Body, FastAPI - -app = FastAPI() - - -@app.put("/items/{item_id}") -async def read_items( - item_id: UUID, - start_datetime: Annotated[datetime, Body()], - end_datetime: Annotated[datetime, Body()], - process_after: Annotated[timedelta, Body()], - repeat_at: Annotated[Union[time, None], Body()] = None, -): - start_process = start_datetime + process_after - duration = end_datetime - start_process - return { - "item_id": item_id, - "start_datetime": start_datetime, - "end_datetime": end_datetime, - "process_after": process_after, - "repeat_at": repeat_at, - "start_process": start_process, - "duration": duration, - } diff --git a/docs_src/extra_data_types/tutorial001_py39.py b/docs_src/extra_data_types/tutorial001_py39.py deleted file mode 100644 index 71de958ff5..0000000000 --- a/docs_src/extra_data_types/tutorial001_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from datetime import datetime, time, timedelta -from typing import Union -from uuid import UUID - -from fastapi import Body, FastAPI - -app = FastAPI() - - -@app.put("/items/{item_id}") -async def read_items( - item_id: UUID, - start_datetime: datetime = Body(), - end_datetime: datetime = Body(), - process_after: timedelta = Body(), - repeat_at: Union[time, None] = Body(default=None), -): - start_process = start_datetime + process_after - duration = end_datetime - start_process - return { - "item_id": item_id, - "start_datetime": start_datetime, - "end_datetime": end_datetime, - "process_after": process_after, - "repeat_at": repeat_at, - "start_process": start_process, - "duration": duration, - } diff --git a/docs_src/extra_models/tutorial001_py39.py b/docs_src/extra_models/tutorial001_py39.py deleted file mode 100644 index 327ffcdf09..0000000000 --- a/docs_src/extra_models/tutorial001_py39.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, EmailStr - -app = FastAPI() - - -class UserIn(BaseModel): - username: str - password: str - email: EmailStr - full_name: Union[str, None] = None - - -class UserOut(BaseModel): - username: str - email: EmailStr - full_name: Union[str, None] = None - - -class UserInDB(BaseModel): - username: str - hashed_password: str - email: EmailStr - full_name: Union[str, None] = None - - -def fake_password_hasher(raw_password: str): - return "supersecret" + raw_password - - -def fake_save_user(user_in: UserIn): - hashed_password = fake_password_hasher(user_in.password) - user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password) - print("User saved! ..not really") - return user_in_db - - -@app.post("/user/", response_model=UserOut) -async def create_user(user_in: UserIn): - user_saved = fake_save_user(user_in) - return user_saved diff --git a/docs_src/extra_models/tutorial002_py39.py b/docs_src/extra_models/tutorial002_py39.py deleted file mode 100644 index 6543796015..0000000000 --- a/docs_src/extra_models/tutorial002_py39.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, EmailStr - -app = FastAPI() - - -class UserBase(BaseModel): - username: str - email: EmailStr - full_name: Union[str, None] = None - - -class UserIn(UserBase): - password: str - - -class UserOut(UserBase): - pass - - -class UserInDB(UserBase): - hashed_password: str - - -def fake_password_hasher(raw_password: str): - return "supersecret" + raw_password - - -def fake_save_user(user_in: UserIn): - hashed_password = fake_password_hasher(user_in.password) - user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password) - print("User saved! ..not really") - return user_in_db - - -@app.post("/user/", response_model=UserOut) -async def create_user(user_in: UserIn): - user_saved = fake_save_user(user_in) - return user_saved diff --git a/docs_src/extra_models/tutorial003_py39.py b/docs_src/extra_models/tutorial003_py39.py deleted file mode 100644 index 06675cbc09..0000000000 --- a/docs_src/extra_models/tutorial003_py39.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class BaseItem(BaseModel): - description: str - type: str - - -class CarItem(BaseItem): - type: str = "car" - - -class PlaneItem(BaseItem): - type: str = "plane" - size: int - - -items = { - "item1": {"description": "All my friends drive a low rider", "type": "car"}, - "item2": { - "description": "Music is my aeroplane, it's my aeroplane", - "type": "plane", - "size": 5, - }, -} - - -@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem]) -async def read_item(item_id: str): - return items[item_id] diff --git a/docs_src/extra_models/tutorial004_py310.py b/docs_src/extra_models/tutorial004_py310.py new file mode 100644 index 0000000000..28cacde4d4 --- /dev/null +++ b/docs_src/extra_models/tutorial004_py310.py @@ -0,0 +1,20 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str + + +items = [ + {"name": "Foo", "description": "There comes my hero"}, + {"name": "Red", "description": "It's my aeroplane"}, +] + + +@app.get("/items/", response_model=list[Item]) +async def read_items(): + return items diff --git a/docs_src/extra_models/tutorial005_py310.py b/docs_src/extra_models/tutorial005_py310.py new file mode 100644 index 0000000000..9da2a0a0f4 --- /dev/null +++ b/docs_src/extra_models/tutorial005_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/keyword-weights/", response_model=dict[str, float]) +async def read_keyword_weights(): + return {"foo": 2.3, "bar": 3.4} diff --git a/docs_src/first_steps/tutorial001_py310.py b/docs_src/first_steps/tutorial001_py310.py new file mode 100644 index 0000000000..ee60be1f96 --- /dev/null +++ b/docs_src/first_steps/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def root(): + return {"message": "Hello World"} diff --git a/docs_src/first_steps/tutorial003_py310.py b/docs_src/first_steps/tutorial003_py310.py new file mode 100644 index 0000000000..e30b827eab --- /dev/null +++ b/docs_src/first_steps/tutorial003_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def root(): + return {"message": "Hello World"} diff --git a/docs_src/generate_clients/tutorial001_py310.py b/docs_src/generate_clients/tutorial001_py310.py new file mode 100644 index 0000000000..6a5ae23202 --- /dev/null +++ b/docs_src/generate_clients/tutorial001_py310.py @@ -0,0 +1,26 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + + +class ResponseMessage(BaseModel): + message: str + + +@app.post("/items/", response_model=ResponseMessage) +async def create_item(item: Item): + return {"message": "item received"} + + +@app.get("/items/", response_model=list[Item]) +async def get_items(): + return [ + {"name": "Plumbus", "price": 3}, + {"name": "Portal Gun", "price": 9001}, + ] diff --git a/docs_src/generate_clients/tutorial002_py310.py b/docs_src/generate_clients/tutorial002_py310.py new file mode 100644 index 0000000000..83309760b9 --- /dev/null +++ b/docs_src/generate_clients/tutorial002_py310.py @@ -0,0 +1,36 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + + +class ResponseMessage(BaseModel): + message: str + + +class User(BaseModel): + username: str + email: str + + +@app.post("/items/", response_model=ResponseMessage, tags=["items"]) +async def create_item(item: Item): + return {"message": "Item received"} + + +@app.get("/items/", response_model=list[Item], tags=["items"]) +async def get_items(): + return [ + {"name": "Plumbus", "price": 3}, + {"name": "Portal Gun", "price": 9001}, + ] + + +@app.post("/users/", response_model=ResponseMessage, tags=["users"]) +async def create_user(user: User): + return {"message": "User received"} diff --git a/docs_src/generate_clients/tutorial003_py310.py b/docs_src/generate_clients/tutorial003_py310.py new file mode 100644 index 0000000000..40722cf103 --- /dev/null +++ b/docs_src/generate_clients/tutorial003_py310.py @@ -0,0 +1,42 @@ +from fastapi import FastAPI +from fastapi.routing import APIRoute +from pydantic import BaseModel + + +def custom_generate_unique_id(route: APIRoute): + return f"{route.tags[0]}-{route.name}" + + +app = FastAPI(generate_unique_id_function=custom_generate_unique_id) + + +class Item(BaseModel): + name: str + price: float + + +class ResponseMessage(BaseModel): + message: str + + +class User(BaseModel): + username: str + email: str + + +@app.post("/items/", response_model=ResponseMessage, tags=["items"]) +async def create_item(item: Item): + return {"message": "Item received"} + + +@app.get("/items/", response_model=list[Item], tags=["items"]) +async def get_items(): + return [ + {"name": "Plumbus", "price": 3}, + {"name": "Portal Gun", "price": 9001}, + ] + + +@app.post("/users/", response_model=ResponseMessage, tags=["users"]) +async def create_user(user: User): + return {"message": "User received"} diff --git a/docs_src/generate_clients/tutorial004_py310.py b/docs_src/generate_clients/tutorial004_py310.py new file mode 100644 index 0000000000..894dc7f8df --- /dev/null +++ b/docs_src/generate_clients/tutorial004_py310.py @@ -0,0 +1,15 @@ +import json +from pathlib import Path + +file_path = Path("./openapi.json") +openapi_content = json.loads(file_path.read_text()) + +for path_data in openapi_content["paths"].values(): + for operation in path_data.values(): + tag = operation["tags"][0] + operation_id = operation["operationId"] + to_remove = f"{tag}-" + new_operation_id = operation_id[len(to_remove) :] + operation["operationId"] = new_operation_id + +file_path.write_text(json.dumps(openapi_content)) diff --git a/docs_src/graphql_/tutorial001_py310.py b/docs_src/graphql_/tutorial001_py310.py new file mode 100644 index 0000000000..e92b2d71c4 --- /dev/null +++ b/docs_src/graphql_/tutorial001_py310.py @@ -0,0 +1,25 @@ +import strawberry +from fastapi import FastAPI +from strawberry.fastapi import GraphQLRouter + + +@strawberry.type +class User: + name: str + age: int + + +@strawberry.type +class Query: + @strawberry.field + def user(self) -> User: + return User(name="Patrick", age=100) + + +schema = strawberry.Schema(query=Query) + + +graphql_app = GraphQLRouter(schema) + +app = FastAPI() +app.include_router(graphql_app, prefix="/graphql") diff --git a/docs_src/handling_errors/tutorial001_py310.py b/docs_src/handling_errors/tutorial001_py310.py new file mode 100644 index 0000000000..e5f32aac29 --- /dev/null +++ b/docs_src/handling_errors/tutorial001_py310.py @@ -0,0 +1,12 @@ +from fastapi import FastAPI, HTTPException + +app = FastAPI() + +items = {"foo": "The Foo Wrestlers"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: str): + if item_id not in items: + raise HTTPException(status_code=404, detail="Item not found") + return {"item": items[item_id]} diff --git a/docs_src/handling_errors/tutorial002_py310.py b/docs_src/handling_errors/tutorial002_py310.py new file mode 100644 index 0000000000..e48c295c9c --- /dev/null +++ b/docs_src/handling_errors/tutorial002_py310.py @@ -0,0 +1,16 @@ +from fastapi import FastAPI, HTTPException + +app = FastAPI() + +items = {"foo": "The Foo Wrestlers"} + + +@app.get("/items-header/{item_id}") +async def read_item_header(item_id: str): + if item_id not in items: + raise HTTPException( + status_code=404, + detail="Item not found", + headers={"X-Error": "There goes my error"}, + ) + return {"item": items[item_id]} diff --git a/docs_src/handling_errors/tutorial003_py310.py b/docs_src/handling_errors/tutorial003_py310.py new file mode 100644 index 0000000000..791cd6838c --- /dev/null +++ b/docs_src/handling_errors/tutorial003_py310.py @@ -0,0 +1,25 @@ +from fastapi import FastAPI, Request +from fastapi.responses import JSONResponse + + +class UnicornException(Exception): + def __init__(self, name: str): + self.name = name + + +app = FastAPI() + + +@app.exception_handler(UnicornException) +async def unicorn_exception_handler(request: Request, exc: UnicornException): + return JSONResponse( + status_code=418, + content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, + ) + + +@app.get("/unicorns/{name}") +async def read_unicorn(name: str): + if name == "yolo": + raise UnicornException(name=name) + return {"unicorn_name": name} diff --git a/docs_src/handling_errors/tutorial004_py310.py b/docs_src/handling_errors/tutorial004_py310.py new file mode 100644 index 0000000000..ae50807e97 --- /dev/null +++ b/docs_src/handling_errors/tutorial004_py310.py @@ -0,0 +1,26 @@ +from fastapi import FastAPI, HTTPException +from fastapi.exceptions import RequestValidationError +from fastapi.responses import PlainTextResponse +from starlette.exceptions import HTTPException as StarletteHTTPException + +app = FastAPI() + + +@app.exception_handler(StarletteHTTPException) +async def http_exception_handler(request, exc): + return PlainTextResponse(str(exc.detail), status_code=exc.status_code) + + +@app.exception_handler(RequestValidationError) +async def validation_exception_handler(request, exc: RequestValidationError): + message = "Validation errors:" + for error in exc.errors(): + message += f"\nField: {error['loc']}, Error: {error['msg']}" + return PlainTextResponse(message, status_code=400) + + +@app.get("/items/{item_id}") +async def read_item(item_id: int): + if item_id == 3: + raise HTTPException(status_code=418, detail="Nope! I don't like 3.") + return {"item_id": item_id} diff --git a/docs_src/handling_errors/tutorial005_py310.py b/docs_src/handling_errors/tutorial005_py310.py new file mode 100644 index 0000000000..0e04fa0864 --- /dev/null +++ b/docs_src/handling_errors/tutorial005_py310.py @@ -0,0 +1,25 @@ +from fastapi import FastAPI, Request +from fastapi.encoders import jsonable_encoder +from fastapi.exceptions import RequestValidationError +from fastapi.responses import JSONResponse +from pydantic import BaseModel + +app = FastAPI() + + +@app.exception_handler(RequestValidationError) +async def validation_exception_handler(request: Request, exc: RequestValidationError): + return JSONResponse( + status_code=422, + content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), + ) + + +class Item(BaseModel): + title: str + size: int + + +@app.post("/items/") +async def create_item(item: Item): + return item diff --git a/docs_src/handling_errors/tutorial006_py310.py b/docs_src/handling_errors/tutorial006_py310.py new file mode 100644 index 0000000000..e05160d7e1 --- /dev/null +++ b/docs_src/handling_errors/tutorial006_py310.py @@ -0,0 +1,28 @@ +from fastapi import FastAPI, HTTPException +from fastapi.exception_handlers import ( + http_exception_handler, + request_validation_exception_handler, +) +from fastapi.exceptions import RequestValidationError +from starlette.exceptions import HTTPException as StarletteHTTPException + +app = FastAPI() + + +@app.exception_handler(StarletteHTTPException) +async def custom_http_exception_handler(request, exc): + print(f"OMG! An HTTP error!: {repr(exc)}") + return await http_exception_handler(request, exc) + + +@app.exception_handler(RequestValidationError) +async def validation_exception_handler(request, exc): + print(f"OMG! The client sent invalid data!: {exc}") + return await request_validation_exception_handler(request, exc) + + +@app.get("/items/{item_id}") +async def read_item(item_id: int): + if item_id == 3: + raise HTTPException(status_code=418, detail="Nope! I don't like 3.") + return {"item_id": item_id} diff --git a/docs_src/header_param_models/tutorial001_an_py39.py b/docs_src/header_param_models/tutorial001_an_py39.py deleted file mode 100644 index 51a5f94fc8..0000000000 --- a/docs_src/header_param_models/tutorial001_an_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items(headers: Annotated[CommonHeaders, Header()]): - return headers diff --git a/docs_src/header_param_models/tutorial001_py39.py b/docs_src/header_param_models/tutorial001_py39.py deleted file mode 100644 index 4c1137813a..0000000000 --- a/docs_src/header_param_models/tutorial001_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items(headers: CommonHeaders = Header()): - return headers diff --git a/docs_src/header_param_models/tutorial002_an_py39.py b/docs_src/header_param_models/tutorial002_an_py39.py deleted file mode 100644 index ca5208c9d0..0000000000 --- a/docs_src/header_param_models/tutorial002_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - model_config = {"extra": "forbid"} - - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items(headers: Annotated[CommonHeaders, Header()]): - return headers diff --git a/docs_src/header_param_models/tutorial002_py39.py b/docs_src/header_param_models/tutorial002_py39.py deleted file mode 100644 index f8ce559a74..0000000000 --- a/docs_src/header_param_models/tutorial002_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - model_config = {"extra": "forbid"} - - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items(headers: CommonHeaders = Header()): - return headers diff --git a/docs_src/header_param_models/tutorial003_an_py39.py b/docs_src/header_param_models/tutorial003_an_py39.py deleted file mode 100644 index 8be6b01d0e..0000000000 --- a/docs_src/header_param_models/tutorial003_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items( - headers: Annotated[CommonHeaders, Header(convert_underscores=False)], -): - return headers diff --git a/docs_src/header_param_models/tutorial003_py39.py b/docs_src/header_param_models/tutorial003_py39.py deleted file mode 100644 index 848c341119..0000000000 --- a/docs_src/header_param_models/tutorial003_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header -from pydantic import BaseModel - -app = FastAPI() - - -class CommonHeaders(BaseModel): - host: str - save_data: bool - if_modified_since: Union[str, None] = None - traceparent: Union[str, None] = None - x_tag: list[str] = [] - - -@app.get("/items/") -async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): - return headers diff --git a/docs_src/header_params/tutorial001_an_py39.py b/docs_src/header_params/tutorial001_an_py39.py deleted file mode 100644 index 1fbe3bb99a..0000000000 --- a/docs_src/header_params/tutorial001_an_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items(user_agent: Annotated[Union[str, None], Header()] = None): - return {"User-Agent": user_agent} diff --git a/docs_src/header_params/tutorial001_py39.py b/docs_src/header_params/tutorial001_py39.py deleted file mode 100644 index 74429c8e2d..0000000000 --- a/docs_src/header_params/tutorial001_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items(user_agent: Union[str, None] = Header(default=None)): - return {"User-Agent": user_agent} diff --git a/docs_src/header_params/tutorial002_an_py39.py b/docs_src/header_params/tutorial002_an_py39.py deleted file mode 100644 index 008e4b6e1a..0000000000 --- a/docs_src/header_params/tutorial002_an_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - strange_header: Annotated[ - Union[str, None], Header(convert_underscores=False) - ] = None, -): - return {"strange_header": strange_header} diff --git a/docs_src/header_params/tutorial002_py39.py b/docs_src/header_params/tutorial002_py39.py deleted file mode 100644 index 0a34f17cc4..0000000000 --- a/docs_src/header_params/tutorial002_py39.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - strange_header: Union[str, None] = Header(default=None, convert_underscores=False), -): - return {"strange_header": strange_header} diff --git a/docs_src/header_params/tutorial003_an_py39.py b/docs_src/header_params/tutorial003_an_py39.py deleted file mode 100644 index 5aad89407e..0000000000 --- a/docs_src/header_params/tutorial003_an_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items(x_token: Annotated[Union[list[str], None], Header()] = None): - return {"X-Token values": x_token} diff --git a/docs_src/header_params/tutorial003_py39.py b/docs_src/header_params/tutorial003_py39.py deleted file mode 100644 index 34437db161..0000000000 --- a/docs_src/header_params/tutorial003_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Header - -app = FastAPI() - - -@app.get("/items/") -async def read_items(x_token: Union[list[str], None] = Header(default=None)): - return {"X-Token values": x_token} diff --git a/docs_src/metadata/tutorial001_1_py310.py b/docs_src/metadata/tutorial001_1_py310.py new file mode 100644 index 0000000000..419232d861 --- /dev/null +++ b/docs_src/metadata/tutorial001_1_py310.py @@ -0,0 +1,38 @@ +from fastapi import FastAPI + +description = """ +ChimichangApp API helps you do awesome stuff. ๐Ÿš€ + +## Items + +You can **read items**. + +## Users + +You will be able to: + +* **Create users** (_not implemented_). +* **Read users** (_not implemented_). +""" + +app = FastAPI( + title="ChimichangApp", + description=description, + summary="Deadpool's favorite app. Nuff said.", + version="0.0.1", + terms_of_service="http://example.com/terms/", + contact={ + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + license_info={ + "name": "Apache 2.0", + "identifier": "Apache-2.0", + }, +) + + +@app.get("/items/") +async def read_items(): + return [{"name": "Katana"}] diff --git a/docs_src/metadata/tutorial001_py310.py b/docs_src/metadata/tutorial001_py310.py new file mode 100644 index 0000000000..76656e81b4 --- /dev/null +++ b/docs_src/metadata/tutorial001_py310.py @@ -0,0 +1,38 @@ +from fastapi import FastAPI + +description = """ +ChimichangApp API helps you do awesome stuff. ๐Ÿš€ + +## Items + +You can **read items**. + +## Users + +You will be able to: + +* **Create users** (_not implemented_). +* **Read users** (_not implemented_). +""" + +app = FastAPI( + title="ChimichangApp", + description=description, + summary="Deadpool's favorite app. Nuff said.", + version="0.0.1", + terms_of_service="http://example.com/terms/", + contact={ + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + }, + license_info={ + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, +) + + +@app.get("/items/") +async def read_items(): + return [{"name": "Katana"}] diff --git a/docs_src/metadata/tutorial002_py310.py b/docs_src/metadata/tutorial002_py310.py new file mode 100644 index 0000000000..cf9ed7087e --- /dev/null +++ b/docs_src/metadata/tutorial002_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI(openapi_url="/api/v1/openapi.json") + + +@app.get("/items/") +async def read_items(): + return [{"name": "Foo"}] diff --git a/docs_src/metadata/tutorial003_py310.py b/docs_src/metadata/tutorial003_py310.py new file mode 100644 index 0000000000..ee09c7f37b --- /dev/null +++ b/docs_src/metadata/tutorial003_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI(docs_url="/documentation", redoc_url=None) + + +@app.get("/items/") +async def read_items(): + return [{"name": "Foo"}] diff --git a/docs_src/metadata/tutorial004_py310.py b/docs_src/metadata/tutorial004_py310.py new file mode 100644 index 0000000000..465bd659d5 --- /dev/null +++ b/docs_src/metadata/tutorial004_py310.py @@ -0,0 +1,28 @@ +from fastapi import FastAPI + +tags_metadata = [ + { + "name": "users", + "description": "Operations with users. The **login** logic is also here.", + }, + { + "name": "items", + "description": "Manage items. So _fancy_ they have their own docs.", + "externalDocs": { + "description": "Items external docs", + "url": "https://fastapi.tiangolo.com/", + }, + }, +] + +app = FastAPI(openapi_tags=tags_metadata) + + +@app.get("/users/", tags=["users"]) +async def get_users(): + return [{"name": "Harry"}, {"name": "Ron"}] + + +@app.get("/items/", tags=["items"]) +async def get_items(): + return [{"name": "wand"}, {"name": "flying broom"}] diff --git a/docs_src/middleware/tutorial001_py310.py b/docs_src/middleware/tutorial001_py310.py new file mode 100644 index 0000000000..e65a7dade1 --- /dev/null +++ b/docs_src/middleware/tutorial001_py310.py @@ -0,0 +1,14 @@ +import time + +from fastapi import FastAPI, Request + +app = FastAPI() + + +@app.middleware("http") +async def add_process_time_header(request: Request, call_next): + start_time = time.perf_counter() + response = await call_next(request) + process_time = time.perf_counter() - start_time + response.headers["X-Process-Time"] = str(process_time) + return response diff --git a/docs_src/openapi_callbacks/tutorial001_py39.py b/docs_src/openapi_callbacks/tutorial001_py39.py deleted file mode 100644 index 3f1bac6e29..0000000000 --- a/docs_src/openapi_callbacks/tutorial001_py39.py +++ /dev/null @@ -1,53 +0,0 @@ -from typing import Union - -from fastapi import APIRouter, FastAPI -from pydantic import BaseModel, HttpUrl - -app = FastAPI() - - -class Invoice(BaseModel): - id: str - title: Union[str, None] = None - customer: str - total: float - - -class InvoiceEvent(BaseModel): - description: str - paid: bool - - -class InvoiceEventReceived(BaseModel): - ok: bool - - -invoices_callback_router = APIRouter() - - -@invoices_callback_router.post( - "{$callback_url}/invoices/{$request.body.id}", response_model=InvoiceEventReceived -) -def invoice_notification(body: InvoiceEvent): - pass - - -@app.post("/invoices/", callbacks=invoices_callback_router.routes) -def create_invoice(invoice: Invoice, callback_url: Union[HttpUrl, None] = None): - """ - Create an invoice. - - This will (let's imagine) let the API user (some external developer) create an - invoice. - - And this path operation will: - - * Send the invoice to the client. - * Collect the money from the client. - * Send a notification back to the API user (the external developer), as a callback. - * At this point is that the API will somehow send a POST request to the - external API with the notification of the invoice event - (e.g. "payment successful"). - """ - # Send the invoice, collect the money, send the notification (the callback) - return {"msg": "Invoice received"} diff --git a/docs_src/openapi_webhooks/tutorial001_py310.py b/docs_src/openapi_webhooks/tutorial001_py310.py new file mode 100644 index 0000000000..55822bb48f --- /dev/null +++ b/docs_src/openapi_webhooks/tutorial001_py310.py @@ -0,0 +1,25 @@ +from datetime import datetime + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Subscription(BaseModel): + username: str + monthly_fee: float + start_date: datetime + + +@app.webhooks.post("new-subscription") +def new_subscription(body: Subscription): + """ + When a new user subscribes to your service we'll send you a POST request with this + data to the URL that you register for the event `new-subscription` in the dashboard. + """ + + +@app.get("/users/") +def read_users(): + return ["Rick", "Morty"] diff --git a/docs_src/path_operation_advanced_configuration/tutorial001_py310.py b/docs_src/path_operation_advanced_configuration/tutorial001_py310.py new file mode 100644 index 0000000000..fafa8ffb8e --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/", operation_id="some_specific_id_you_define") +async def read_items(): + return [{"item_id": "Foo"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial002_py310.py b/docs_src/path_operation_advanced_configuration/tutorial002_py310.py new file mode 100644 index 0000000000..3aaae9b371 --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial002_py310.py @@ -0,0 +1,24 @@ +from fastapi import FastAPI +from fastapi.routing import APIRoute + +app = FastAPI() + + +@app.get("/items/") +async def read_items(): + return [{"item_id": "Foo"}] + + +def use_route_names_as_operation_ids(app: FastAPI) -> None: + """ + Simplify operation IDs so that generated API clients have simpler function + names. + + Should be called only after all routes have been added. + """ + for route in app.routes: + if isinstance(route, APIRoute): + route.operation_id = route.name # in this case, 'read_items' + + +use_route_names_as_operation_ids(app) diff --git a/docs_src/path_operation_advanced_configuration/tutorial003_py310.py b/docs_src/path_operation_advanced_configuration/tutorial003_py310.py new file mode 100644 index 0000000000..dcc358e323 --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial003_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/", include_in_schema=False) +async def read_items(): + return [{"item_id": "Foo"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial004_py39.py b/docs_src/path_operation_advanced_configuration/tutorial004_py39.py deleted file mode 100644 index 8fabe7cb80..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial004_py39.py +++ /dev/null @@ -1,30 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post("/items/", summary="Create an item") -async def create_item(item: Item) -> Item: - """ - Create an item with all the information: - - - **name**: each item must have a name - - **description**: a long description - - **price**: required - - **tax**: if the item doesn't have tax, you can omit this - - **tags**: a set of unique tag strings for this item - \f - :param item: User input. - """ - return item diff --git a/docs_src/path_operation_advanced_configuration/tutorial005_py310.py b/docs_src/path_operation_advanced_configuration/tutorial005_py310.py new file mode 100644 index 0000000000..5837ad8351 --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial005_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/", openapi_extra={"x-aperture-labs-portal": "blue"}) +async def read_items(): + return [{"item_id": "portal-gun"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial006_py310.py b/docs_src/path_operation_advanced_configuration/tutorial006_py310.py new file mode 100644 index 0000000000..403c3ee3fb --- /dev/null +++ b/docs_src/path_operation_advanced_configuration/tutorial006_py310.py @@ -0,0 +1,41 @@ +from fastapi import FastAPI, Request + +app = FastAPI() + + +def magic_data_reader(raw_body: bytes): + return { + "size": len(raw_body), + "content": { + "name": "Maaaagic", + "price": 42, + "description": "Just kiddin', no magic here. โœจ", + }, + } + + +@app.post( + "/items/", + openapi_extra={ + "requestBody": { + "content": { + "application/json": { + "schema": { + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"type": "string"}, + "price": {"type": "number"}, + "description": {"type": "string"}, + }, + } + } + }, + "required": True, + }, + }, +) +async def create_item(request: Request): + raw_body = await request.body() + data = magic_data_reader(raw_body) + return data diff --git a/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py b/docs_src/path_operation_advanced_configuration/tutorial007_py310.py similarity index 68% rename from docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py rename to docs_src/path_operation_advanced_configuration/tutorial007_py310.py index 849f648e12..ff64ef7923 100644 --- a/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py +++ b/docs_src/path_operation_advanced_configuration/tutorial007_py310.py @@ -1,6 +1,6 @@ import yaml from fastapi import FastAPI, HTTPException, Request -from pydantic.v1 import BaseModel, ValidationError +from pydantic import BaseModel, ValidationError app = FastAPI() @@ -14,7 +14,7 @@ class Item(BaseModel): "/items/", openapi_extra={ "requestBody": { - "content": {"application/x-yaml": {"schema": Item.schema()}}, + "content": {"application/x-yaml": {"schema": Item.model_json_schema()}}, "required": True, }, }, @@ -26,7 +26,7 @@ async def create_item(request: Request): except yaml.YAMLError: raise HTTPException(status_code=422, detail="Invalid YAML") try: - item = Item.parse_obj(data) + item = Item.model_validate(data) except ValidationError as e: - raise HTTPException(status_code=422, detail=e.errors()) + raise HTTPException(status_code=422, detail=e.errors(include_url=False)) return item diff --git a/docs_src/path_operation_configuration/tutorial001_py39.py b/docs_src/path_operation_configuration/tutorial001_py39.py deleted file mode 100644 index 09b3182821..0000000000 --- a/docs_src/path_operation_configuration/tutorial001_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, status -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post("/items/", status_code=status.HTTP_201_CREATED) -async def create_item(item: Item) -> Item: - return item diff --git a/docs_src/path_operation_configuration/tutorial002_py39.py b/docs_src/path_operation_configuration/tutorial002_py39.py deleted file mode 100644 index fca3b0de9e..0000000000 --- a/docs_src/path_operation_configuration/tutorial002_py39.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post("/items/", tags=["items"]) -async def create_item(item: Item) -> Item: - return item - - -@app.get("/items/", tags=["items"]) -async def read_items(): - return [{"name": "Foo", "price": 42}] - - -@app.get("/users/", tags=["users"]) -async def read_users(): - return [{"username": "johndoe"}] diff --git a/docs_src/path_operation_configuration/tutorial002b_py310.py b/docs_src/path_operation_configuration/tutorial002b_py310.py new file mode 100644 index 0000000000..d53b4d817d --- /dev/null +++ b/docs_src/path_operation_configuration/tutorial002b_py310.py @@ -0,0 +1,20 @@ +from enum import Enum + +from fastapi import FastAPI + +app = FastAPI() + + +class Tags(Enum): + items = "items" + users = "users" + + +@app.get("/items/", tags=[Tags.items]) +async def get_items(): + return ["Portal gun", "Plumbus"] + + +@app.get("/users/", tags=[Tags.users]) +async def read_users(): + return ["Rick", "Morty"] diff --git a/docs_src/path_operation_configuration/tutorial003_py39.py b/docs_src/path_operation_configuration/tutorial003_py39.py deleted file mode 100644 index a77fb34d89..0000000000 --- a/docs_src/path_operation_configuration/tutorial003_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post( - "/items/", - summary="Create an item", - description="Create an item with all the information, name, description, price, tax and a set of unique tags", -) -async def create_item(item: Item) -> Item: - return item diff --git a/docs_src/path_operation_configuration/tutorial004_py39.py b/docs_src/path_operation_configuration/tutorial004_py39.py deleted file mode 100644 index 31dfbff1d2..0000000000 --- a/docs_src/path_operation_configuration/tutorial004_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post("/items/", summary="Create an item") -async def create_item(item: Item) -> Item: - """ - Create an item with all the information: - - - **name**: each item must have a name - - **description**: a long description - - **price**: required - - **tax**: if the item doesn't have tax, you can omit this - - **tags**: a set of unique tag strings for this item - """ - return item diff --git a/docs_src/path_operation_configuration/tutorial005_py39.py b/docs_src/path_operation_configuration/tutorial005_py39.py deleted file mode 100644 index 0a53a8f2dd..0000000000 --- a/docs_src/path_operation_configuration/tutorial005_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: set[str] = set() - - -@app.post( - "/items/", - summary="Create an item", - response_description="The created item", -) -async def create_item(item: Item) -> Item: - """ - Create an item with all the information: - - - **name**: each item must have a name - - **description**: a long description - - **price**: required - - **tax**: if the item doesn't have tax, you can omit this - - **tags**: a set of unique tag strings for this item - """ - return item diff --git a/docs_src/path_operation_configuration/tutorial006_py310.py b/docs_src/path_operation_configuration/tutorial006_py310.py new file mode 100644 index 0000000000..7c1aa9b206 --- /dev/null +++ b/docs_src/path_operation_configuration/tutorial006_py310.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/", tags=["items"]) +async def read_items(): + return [{"name": "Foo", "price": 42}] + + +@app.get("/users/", tags=["users"]) +async def read_users(): + return [{"username": "johndoe"}] + + +@app.get("/elements/", tags=["items"], deprecated=True) +async def read_elements(): + return [{"item_id": "Foo"}] diff --git a/docs_src/path_params/tutorial001_py310.py b/docs_src/path_params/tutorial001_py310.py new file mode 100644 index 0000000000..7bbf70e6c8 --- /dev/null +++ b/docs_src/path_params/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_item(item_id): + return {"item_id": item_id} diff --git a/docs_src/path_params/tutorial002_py310.py b/docs_src/path_params/tutorial002_py310.py new file mode 100644 index 0000000000..8272ad70d4 --- /dev/null +++ b/docs_src/path_params/tutorial002_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_item(item_id: int): + return {"item_id": item_id} diff --git a/docs_src/path_params/tutorial003_py310.py b/docs_src/path_params/tutorial003_py310.py new file mode 100644 index 0000000000..5f0aa09234 --- /dev/null +++ b/docs_src/path_params/tutorial003_py310.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/users/me") +async def read_user_me(): + return {"user_id": "the current user"} + + +@app.get("/users/{user_id}") +async def read_user(user_id: str): + return {"user_id": user_id} diff --git a/docs_src/path_params/tutorial003b_py310.py b/docs_src/path_params/tutorial003b_py310.py new file mode 100644 index 0000000000..822d373694 --- /dev/null +++ b/docs_src/path_params/tutorial003b_py310.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/users") +async def read_users(): + return ["Rick", "Morty"] + + +@app.get("/users") +async def read_users2(): + return ["Bean", "Elfo"] diff --git a/docs_src/path_params/tutorial004_py310.py b/docs_src/path_params/tutorial004_py310.py new file mode 100644 index 0000000000..2961e6178e --- /dev/null +++ b/docs_src/path_params/tutorial004_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/files/{file_path:path}") +async def read_file(file_path: str): + return {"file_path": file_path} diff --git a/docs_src/path_params/tutorial005_py310.py b/docs_src/path_params/tutorial005_py310.py new file mode 100644 index 0000000000..9a24a4963a --- /dev/null +++ b/docs_src/path_params/tutorial005_py310.py @@ -0,0 +1,23 @@ +from enum import Enum + +from fastapi import FastAPI + + +class ModelName(str, Enum): + alexnet = "alexnet" + resnet = "resnet" + lenet = "lenet" + + +app = FastAPI() + + +@app.get("/models/{model_name}") +async def get_model(model_name: ModelName): + if model_name is ModelName.alexnet: + return {"model_name": model_name, "message": "Deep Learning FTW!"} + + if model_name.value == "lenet": + return {"model_name": model_name, "message": "LeCNN all the images"} + + return {"model_name": model_name, "message": "Have some residuals"} diff --git a/docs_src/path_params_numeric_validations/tutorial002_an_py310.py b/docs_src/path_params_numeric_validations/tutorial002_an_py310.py new file mode 100644 index 0000000000..cd882abb2c --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial002_an_py310.py @@ -0,0 +1,15 @@ +from typing import Annotated + +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + q: str, item_id: Annotated[int, Path(title="The ID of the item to get")] +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial002_py310.py b/docs_src/path_params_numeric_validations/tutorial002_py310.py new file mode 100644 index 0000000000..63ac691a83 --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial002_py310.py @@ -0,0 +1,11 @@ +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial003_an_py310.py b/docs_src/path_params_numeric_validations/tutorial003_an_py310.py new file mode 100644 index 0000000000..1588556e78 --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial003_an_py310.py @@ -0,0 +1,15 @@ +from typing import Annotated + +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + item_id: Annotated[int, Path(title="The ID of the item to get")], q: str +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial003_py310.py b/docs_src/path_params_numeric_validations/tutorial003_py310.py new file mode 100644 index 0000000000..8df0ffc620 --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial003_py310.py @@ -0,0 +1,11 @@ +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial004_an_py310.py b/docs_src/path_params_numeric_validations/tutorial004_an_py310.py new file mode 100644 index 0000000000..f67f6450e7 --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial004_an_py310.py @@ -0,0 +1,15 @@ +from typing import Annotated + +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial004_py310.py b/docs_src/path_params_numeric_validations/tutorial004_py310.py new file mode 100644 index 0000000000..86651d47cf --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial004_py310.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial005_an_py310.py b/docs_src/path_params_numeric_validations/tutorial005_an_py310.py new file mode 100644 index 0000000000..571dd583ce --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial005_an_py310.py @@ -0,0 +1,16 @@ +from typing import Annotated + +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)], + q: str, +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial005_py310.py b/docs_src/path_params_numeric_validations/tutorial005_py310.py new file mode 100644 index 0000000000..8f12f2da02 --- /dev/null +++ b/docs_src/path_params_numeric_validations/tutorial005_py310.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, Path + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_items( + *, + item_id: int = Path(title="The ID of the item to get", gt=0, le=1000), + q: str, +): + results = {"item_id": item_id} + if q: + results.update({"q": q}) + return results diff --git a/docs_src/path_params_numeric_validations/tutorial001_an_py39.py b/docs_src/path_params_numeric_validations/tutorial006_an_py310.py similarity index 61% rename from docs_src/path_params_numeric_validations/tutorial001_an_py39.py rename to docs_src/path_params_numeric_validations/tutorial006_an_py310.py index b36315a46d..426ec37764 100644 --- a/docs_src/path_params_numeric_validations/tutorial001_an_py39.py +++ b/docs_src/path_params_numeric_validations/tutorial006_an_py310.py @@ -1,4 +1,4 @@ -from typing import Annotated, Union +from typing import Annotated from fastapi import FastAPI, Path, Query @@ -7,10 +7,14 @@ app = FastAPI() @app.get("/items/{item_id}") async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get")], - q: Annotated[Union[str, None], Query(alias="item-query")] = None, + *, + item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], + q: str, + size: Annotated[float, Query(gt=0, lt=10.5)], ): results = {"item_id": item_id} if q: results.update({"q": q}) + if size: + results.update({"size": size}) return results diff --git a/docs_src/path_params_numeric_validations/tutorial001_py39.py b/docs_src/path_params_numeric_validations/tutorial006_py310.py similarity index 53% rename from docs_src/path_params_numeric_validations/tutorial001_py39.py rename to docs_src/path_params_numeric_validations/tutorial006_py310.py index 5301470282..f07629aa0a 100644 --- a/docs_src/path_params_numeric_validations/tutorial001_py39.py +++ b/docs_src/path_params_numeric_validations/tutorial006_py310.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import FastAPI, Path, Query app = FastAPI() @@ -7,10 +5,14 @@ app = FastAPI() @app.get("/items/{item_id}") async def read_items( - item_id: int = Path(title="The ID of the item to get"), - q: Union[str, None] = Query(default=None, alias="item-query"), + *, + item_id: int = Path(title="The ID of the item to get", ge=0, le=1000), + q: str, + size: float = Query(gt=0, lt=10.5), ): results = {"item_id": item_id} if q: results.update({"q": q}) + if size: + results.update({"size": size}) return results diff --git a/docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py b/docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py deleted file mode 100644 index 62a4b2c210..0000000000 --- a/docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Union - -from pydantic.v1 import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - size: float diff --git a/docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py b/docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py deleted file mode 100644 index 3c6a060807..0000000000 --- a/docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic.v1 import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - size: float - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item) -> Item: - return item diff --git a/docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py b/docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py deleted file mode 100644 index 117d6f7a4c..0000000000 --- a/docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel as BaseModelV2 -from pydantic.v1 import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - size: float - - -class ItemV2(BaseModelV2): - name: str - description: Union[str, None] = None - size: float - - -app = FastAPI() - - -@app.post("/items/", response_model=ItemV2) -async def create_item(item: Item): - return item diff --git a/docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py b/docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py deleted file mode 100644 index 150ab20ae5..0000000000 --- a/docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI -from fastapi.temp_pydantic_v1_params import Body -from pydantic.v1 import BaseModel - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - size: float - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Annotated[Item, Body(embed=True)]) -> Item: - return item diff --git a/docs_src/python_types/tutorial001_py310.py b/docs_src/python_types/tutorial001_py310.py new file mode 100644 index 0000000000..09039435f1 --- /dev/null +++ b/docs_src/python_types/tutorial001_py310.py @@ -0,0 +1,6 @@ +def get_full_name(first_name, last_name): + full_name = first_name.title() + " " + last_name.title() + return full_name + + +print(get_full_name("john", "doe")) diff --git a/docs_src/python_types/tutorial002_py310.py b/docs_src/python_types/tutorial002_py310.py new file mode 100644 index 0000000000..c0857a1160 --- /dev/null +++ b/docs_src/python_types/tutorial002_py310.py @@ -0,0 +1,6 @@ +def get_full_name(first_name: str, last_name: str): + full_name = first_name.title() + " " + last_name.title() + return full_name + + +print(get_full_name("john", "doe")) diff --git a/docs_src/python_types/tutorial003_py310.py b/docs_src/python_types/tutorial003_py310.py new file mode 100644 index 0000000000..d021d82113 --- /dev/null +++ b/docs_src/python_types/tutorial003_py310.py @@ -0,0 +1,3 @@ +def get_name_with_age(name: str, age: int): + name_with_age = name + " is this old: " + age + return name_with_age diff --git a/docs_src/python_types/tutorial004_py310.py b/docs_src/python_types/tutorial004_py310.py new file mode 100644 index 0000000000..9400269e26 --- /dev/null +++ b/docs_src/python_types/tutorial004_py310.py @@ -0,0 +1,3 @@ +def get_name_with_age(name: str, age: int): + name_with_age = name + " is this old: " + str(age) + return name_with_age diff --git a/docs_src/python_types/tutorial005_py310.py b/docs_src/python_types/tutorial005_py310.py new file mode 100644 index 0000000000..6c8edb0ec4 --- /dev/null +++ b/docs_src/python_types/tutorial005_py310.py @@ -0,0 +1,2 @@ +def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes): + return item_a, item_b, item_c, item_d, item_e diff --git a/docs_src/python_types/tutorial006_py310.py b/docs_src/python_types/tutorial006_py310.py new file mode 100644 index 0000000000..486b67cafd --- /dev/null +++ b/docs_src/python_types/tutorial006_py310.py @@ -0,0 +1,3 @@ +def process_items(items: list[str]): + for item in items: + print(item) diff --git a/docs_src/python_types/tutorial007_py310.py b/docs_src/python_types/tutorial007_py310.py new file mode 100644 index 0000000000..ea96c79642 --- /dev/null +++ b/docs_src/python_types/tutorial007_py310.py @@ -0,0 +1,2 @@ +def process_items(items_t: tuple[int, int, str], items_s: set[bytes]): + return items_t, items_s diff --git a/docs_src/python_types/tutorial008_py310.py b/docs_src/python_types/tutorial008_py310.py new file mode 100644 index 0000000000..a393385b05 --- /dev/null +++ b/docs_src/python_types/tutorial008_py310.py @@ -0,0 +1,4 @@ +def process_items(prices: dict[str, float]): + for item_name, item_price in prices.items(): + print(item_name) + print(item_price) diff --git a/docs_src/python_types/tutorial010_py310.py b/docs_src/python_types/tutorial010_py310.py new file mode 100644 index 0000000000..468cffc2dc --- /dev/null +++ b/docs_src/python_types/tutorial010_py310.py @@ -0,0 +1,7 @@ +class Person: + def __init__(self, name: str): + self.name = name + + +def get_person_name(one_person: Person): + return one_person.name diff --git a/docs_src/python_types/tutorial011_py39.py b/docs_src/python_types/tutorial011_py39.py deleted file mode 100644 index 4eb40b405f..0000000000 --- a/docs_src/python_types/tutorial011_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from datetime import datetime -from typing import Union - -from pydantic import BaseModel - - -class User(BaseModel): - id: int - name: str = "John Doe" - signup_ts: Union[datetime, None] = None - friends: list[int] = [] - - -external_data = { - "id": "123", - "signup_ts": "2017-06-01 12:22", - "friends": [1, "2", b"3"], -} -user = User(**external_data) -print(user) -# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3] -print(user.id) -# > 123 diff --git a/docs_src/python_types/tutorial012_py39.py b/docs_src/python_types/tutorial012_py39.py deleted file mode 100644 index 74fa94c432..0000000000 --- a/docs_src/python_types/tutorial012_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class User(BaseModel): - name: str - age: Optional[int] diff --git a/docs_src/python_types/tutorial013_py310.py b/docs_src/python_types/tutorial013_py310.py new file mode 100644 index 0000000000..65a0eaa939 --- /dev/null +++ b/docs_src/python_types/tutorial013_py310.py @@ -0,0 +1,5 @@ +from typing import Annotated + + +def say_hello(name: Annotated[str, "this is just metadata"]) -> str: + return f"Hello {name}" diff --git a/docs_src/query_param_models/tutorial001_an_py39.py b/docs_src/query_param_models/tutorial001_an_py39.py deleted file mode 100644 index 71427acae1..0000000000 --- a/docs_src/query_param_models/tutorial001_an_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Annotated, Literal - -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - - -class FilterParams(BaseModel): - limit: int = Field(100, gt=0, le=100) - offset: int = Field(0, ge=0) - order_by: Literal["created_at", "updated_at"] = "created_at" - tags: list[str] = [] - - -@app.get("/items/") -async def read_items(filter_query: Annotated[FilterParams, Query()]): - return filter_query diff --git a/docs_src/query_param_models/tutorial001_py39.py b/docs_src/query_param_models/tutorial001_py39.py deleted file mode 100644 index 3ebf9f4d70..0000000000 --- a/docs_src/query_param_models/tutorial001_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Literal - -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - - -class FilterParams(BaseModel): - limit: int = Field(100, gt=0, le=100) - offset: int = Field(0, ge=0) - order_by: Literal["created_at", "updated_at"] = "created_at" - tags: list[str] = [] - - -@app.get("/items/") -async def read_items(filter_query: FilterParams = Query()): - return filter_query diff --git a/docs_src/query_param_models/tutorial002_an_py39.py b/docs_src/query_param_models/tutorial002_an_py39.py deleted file mode 100644 index 9759565023..0000000000 --- a/docs_src/query_param_models/tutorial002_an_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Annotated, Literal - -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - - -class FilterParams(BaseModel): - model_config = {"extra": "forbid"} - - limit: int = Field(100, gt=0, le=100) - offset: int = Field(0, ge=0) - order_by: Literal["created_at", "updated_at"] = "created_at" - tags: list[str] = [] - - -@app.get("/items/") -async def read_items(filter_query: Annotated[FilterParams, Query()]): - return filter_query diff --git a/docs_src/query_param_models/tutorial002_py39.py b/docs_src/query_param_models/tutorial002_py39.py deleted file mode 100644 index 6ec4184991..0000000000 --- a/docs_src/query_param_models/tutorial002_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Literal - -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - - -class FilterParams(BaseModel): - model_config = {"extra": "forbid"} - - limit: int = Field(100, gt=0, le=100) - offset: int = Field(0, ge=0) - order_by: Literal["created_at", "updated_at"] = "created_at" - tags: list[str] = [] - - -@app.get("/items/") -async def read_items(filter_query: FilterParams = Query()): - return filter_query diff --git a/docs_src/query_params/tutorial001_py310.py b/docs_src/query_params/tutorial001_py310.py new file mode 100644 index 0000000000..74e1a17604 --- /dev/null +++ b/docs_src/query_params/tutorial001_py310.py @@ -0,0 +1,10 @@ +from fastapi import FastAPI + +app = FastAPI() + +fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] + + +@app.get("/items/") +async def read_item(skip: int = 0, limit: int = 10): + return fake_items_db[skip : skip + limit] diff --git a/docs_src/query_params/tutorial002_py39.py b/docs_src/query_params/tutorial002_py39.py deleted file mode 100644 index 8465f45eed..0000000000 --- a/docs_src/query_params/tutorial002_py39.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Union - -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_item(item_id: str, q: Union[str, None] = None): - if q: - return {"item_id": item_id, "q": q} - return {"item_id": item_id} diff --git a/docs_src/query_params/tutorial003_py39.py b/docs_src/query_params/tutorial003_py39.py deleted file mode 100644 index 3362715b39..0000000000 --- a/docs_src/query_params/tutorial003_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Union - -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False): - item = {"item_id": item_id} - if q: - item.update({"q": q}) - if not short: - item.update( - {"description": "This is an amazing item that has a long description"} - ) - return item diff --git a/docs_src/query_params/tutorial004_py39.py b/docs_src/query_params/tutorial004_py39.py deleted file mode 100644 index 049c3ae934..0000000000 --- a/docs_src/query_params/tutorial004_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/users/{user_id}/items/{item_id}") -async def read_user_item( - user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False -): - item = {"item_id": item_id, "owner_id": user_id} - if q: - item.update({"q": q}) - if not short: - item.update( - {"description": "This is an amazing item that has a long description"} - ) - return item diff --git a/docs_src/query_params/tutorial005_py310.py b/docs_src/query_params/tutorial005_py310.py new file mode 100644 index 0000000000..e16a40574d --- /dev/null +++ b/docs_src/query_params/tutorial005_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/items/{item_id}") +async def read_user_item(item_id: str, needy: str): + item = {"item_id": item_id, "needy": needy} + return item diff --git a/docs_src/query_params/tutorial006_py39.py b/docs_src/query_params/tutorial006_py39.py deleted file mode 100644 index f0dbfe08fe..0000000000 --- a/docs_src/query_params/tutorial006_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union - -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_user_item( - item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None -): - item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit} - return item diff --git a/docs_src/query_params_str_validations/tutorial001_py39.py b/docs_src/query_params_str_validations/tutorial001_py39.py deleted file mode 100644 index e38326b18c..0000000000 --- a/docs_src/query_params_str_validations/tutorial001_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union - -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Union[str, None] = None): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial002_an_py39.py b/docs_src/query_params_str_validations/tutorial002_an_py39.py deleted file mode 100644 index 2d8fc97985..0000000000 --- a/docs_src/query_params_str_validations/tutorial002_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial003_an_py39.py b/docs_src/query_params_str_validations/tutorial003_an_py39.py deleted file mode 100644 index 3d6697793f..0000000000 --- a/docs_src/query_params_str_validations/tutorial003_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Annotated[Union[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 diff --git a/docs_src/query_params_str_validations/tutorial003_py39.py b/docs_src/query_params_str_validations/tutorial003_py39.py deleted file mode 100644 index 7d4917373a..0000000000 --- a/docs_src/query_params_str_validations/tutorial003_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Union[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 diff --git a/docs_src/query_params_str_validations/tutorial004_an_py39.py b/docs_src/query_params_str_validations/tutorial004_an_py39.py deleted file mode 100644 index de27097b38..0000000000 --- a/docs_src/query_params_str_validations/tutorial004_an_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Annotated[ - Union[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 diff --git a/docs_src/query_params_str_validations/tutorial004_py39.py b/docs_src/query_params_str_validations/tutorial004_py39.py deleted file mode 100644 index 64a647a16a..0000000000 --- a/docs_src/query_params_str_validations/tutorial004_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Union[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 diff --git a/docs_src/query_params_str_validations/tutorial004_regex_an_py310.py b/docs_src/query_params_str_validations/tutorial004_regex_an_py310.py deleted file mode 100644 index 21e0d3eb85..0000000000 --- a/docs_src/query_params_str_validations/tutorial004_regex_an_py310.py +++ /dev/null @@ -1,17 +0,0 @@ -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, regex="^fixedquery$") - ] = None, -): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial002_py39.py b/docs_src/query_params_str_validations/tutorial005_an_py310.py similarity index 65% rename from docs_src/query_params_str_validations/tutorial002_py39.py rename to docs_src/query_params_str_validations/tutorial005_an_py310.py index 17e017b7e7..b1f6046b50 100644 --- a/docs_src/query_params_str_validations/tutorial002_py39.py +++ b/docs_src/query_params_str_validations/tutorial005_an_py310.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Annotated from fastapi import FastAPI, Query @@ -6,7 +6,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Union[str, None] = Query(default=None, max_length=50)): +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}) diff --git a/docs_src/query_params_str_validations/tutorial009_py39.py b/docs_src/query_params_str_validations/tutorial005_py310.py similarity index 64% rename from docs_src/query_params_str_validations/tutorial009_py39.py rename to docs_src/query_params_str_validations/tutorial005_py310.py index 8a6bfe2d93..8ab42869e6 100644 --- a/docs_src/query_params_str_validations/tutorial009_py39.py +++ b/docs_src/query_params_str_validations/tutorial005_py310.py @@ -1,12 +1,10 @@ -from typing import Union - from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") -async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")): +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}) diff --git a/docs_src/query_params_str_validations/tutorial006c_py39.py b/docs_src/query_params_str_validations/tutorial006_an_py310.py similarity index 69% rename from docs_src/query_params_str_validations/tutorial006c_py39.py rename to docs_src/query_params_str_validations/tutorial006_an_py310.py index 0a0e820da3..3b4a676d2e 100644 --- a/docs_src/query_params_str_validations/tutorial006c_py39.py +++ b/docs_src/query_params_str_validations/tutorial006_an_py310.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Annotated from fastapi import FastAPI, Query @@ -6,7 +6,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Union[str, None] = Query(min_length=3)): +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}) diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py39.py b/docs_src/query_params_str_validations/tutorial006_py310.py similarity index 64% rename from docs_src/query_params_str_validations/tutorial006c_an_py39.py rename to docs_src/query_params_str_validations/tutorial006_py310.py index 76a1cd49ac..9a90eb64ef 100644 --- a/docs_src/query_params_str_validations/tutorial006c_an_py39.py +++ b/docs_src/query_params_str_validations/tutorial006_py310.py @@ -1,12 +1,10 @@ -from typing import Annotated, Union - from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") -async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]): +async def read_items(q: str = Query(min_length=3)): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial007_an_py39.py b/docs_src/query_params_str_validations/tutorial007_an_py39.py deleted file mode 100644 index 8d7a82c465..0000000000 --- a/docs_src/query_params_str_validations/tutorial007_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Annotated[Union[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 diff --git a/docs_src/query_params_str_validations/tutorial007_py39.py b/docs_src/query_params_str_validations/tutorial007_py39.py deleted file mode 100644 index 27b649e145..0000000000 --- a/docs_src/query_params_str_validations/tutorial007_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Union[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 diff --git a/docs_src/query_params_str_validations/tutorial008_an_py39.py b/docs_src/query_params_str_validations/tutorial008_an_py39.py deleted file mode 100644 index f3f2f2c0e7..0000000000 --- a/docs_src/query_params_str_validations/tutorial008_an_py39.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Annotated[ - Union[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 diff --git a/docs_src/query_params_str_validations/tutorial008_py39.py b/docs_src/query_params_str_validations/tutorial008_py39.py deleted file mode 100644 index e3e0b50aa1..0000000000 --- a/docs_src/query_params_str_validations/tutorial008_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Union[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 diff --git a/docs_src/query_params_str_validations/tutorial009_an_py39.py b/docs_src/query_params_str_validations/tutorial009_an_py39.py deleted file mode 100644 index 70a89e6137..0000000000 --- a/docs_src/query_params_str_validations/tutorial009_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial010_an_py39.py b/docs_src/query_params_str_validations/tutorial010_an_py39.py deleted file mode 100644 index b126c116f0..0000000000 --- a/docs_src/query_params_str_validations/tutorial010_an_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Annotated[ - Union[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 diff --git a/docs_src/query_params_str_validations/tutorial010_py39.py b/docs_src/query_params_str_validations/tutorial010_py39.py deleted file mode 100644 index ff29176fe5..0000000000 --- a/docs_src/query_params_str_validations/tutorial010_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - q: Union[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 diff --git a/docs_src/query_params_str_validations/tutorial011_an_py39.py b/docs_src/query_params_str_validations/tutorial012_an_py310.py similarity index 52% rename from docs_src/query_params_str_validations/tutorial011_an_py39.py rename to docs_src/query_params_str_validations/tutorial012_an_py310.py index 416e3990dc..9b5a9c2fb2 100644 --- a/docs_src/query_params_str_validations/tutorial011_an_py39.py +++ b/docs_src/query_params_str_validations/tutorial012_an_py310.py @@ -1,4 +1,4 @@ -from typing import Annotated, Union +from typing import Annotated from fastapi import FastAPI, Query @@ -6,6 +6,6 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Annotated[Union[list[str], None], Query()] = None): +async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]): query_items = {"q": q} return query_items diff --git a/docs_src/query_params_str_validations/tutorial012_py310.py b/docs_src/query_params_str_validations/tutorial012_py310.py new file mode 100644 index 0000000000..070d0b04bf --- /dev/null +++ b/docs_src/query_params_str_validations/tutorial012_py310.py @@ -0,0 +1,9 @@ +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 diff --git a/docs_src/query_params_str_validations/tutorial011_py39.py b/docs_src/query_params_str_validations/tutorial013_an_py310.py similarity index 56% rename from docs_src/query_params_str_validations/tutorial011_py39.py rename to docs_src/query_params_str_validations/tutorial013_an_py310.py index 878f95c798..602734145d 100644 --- a/docs_src/query_params_str_validations/tutorial011_py39.py +++ b/docs_src/query_params_str_validations/tutorial013_an_py310.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Annotated from fastapi import FastAPI, Query @@ -6,6 +6,6 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Union[list[str], None] = Query(default=None)): +async def read_items(q: Annotated[list, Query()] = []): query_items = {"q": q} return query_items diff --git a/docs_src/query_params_str_validations/tutorial013_py310.py b/docs_src/query_params_str_validations/tutorial013_py310.py new file mode 100644 index 0000000000..0b0f44869f --- /dev/null +++ b/docs_src/query_params_str_validations/tutorial013_py310.py @@ -0,0 +1,9 @@ +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 diff --git a/docs_src/query_params_str_validations/tutorial014_an_py39.py b/docs_src/query_params_str_validations/tutorial014_an_py39.py deleted file mode 100644 index aaf7703a57..0000000000 --- a/docs_src/query_params_str_validations/tutorial014_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None, -): - if hidden_query: - return {"hidden_query": hidden_query} - else: - return {"hidden_query": "Not found"} diff --git a/docs_src/query_params_str_validations/tutorial014_py39.py b/docs_src/query_params_str_validations/tutorial014_py39.py deleted file mode 100644 index 779db1c80e..0000000000 --- a/docs_src/query_params_str_validations/tutorial014_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items( - hidden_query: Union[str, None] = Query(default=None, include_in_schema=False), -): - if hidden_query: - return {"hidden_query": hidden_query} - else: - return {"hidden_query": "Not found"} diff --git a/docs_src/query_params_str_validations/tutorial015_an_py39.py b/docs_src/query_params_str_validations/tutorial015_an_py39.py deleted file mode 100644 index 989b6d2c25..0000000000 --- a/docs_src/query_params_str_validations/tutorial015_an_py39.py +++ /dev/null @@ -1,30 +0,0 @@ -import random -from typing import Annotated, Union - -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[Union[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} diff --git a/docs_src/request_files/tutorial001_02_an_py39.py b/docs_src/request_files/tutorial001_02_an_py39.py deleted file mode 100644 index bb090ff6ca..0000000000 --- a/docs_src/request_files/tutorial001_02_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated, Union - -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: Annotated[Union[bytes, None], File()] = None): - if not file: - return {"message": "No file sent"} - else: - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file(file: Union[UploadFile, None] = None): - if not file: - return {"message": "No upload file sent"} - else: - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_02_py39.py b/docs_src/request_files/tutorial001_02_py39.py deleted file mode 100644 index ac30be2d30..0000000000 --- a/docs_src/request_files/tutorial001_02_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: Union[bytes, None] = File(default=None)): - if not file: - return {"message": "No file sent"} - else: - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file(file: Union[UploadFile, None] = None): - if not file: - return {"message": "No upload file sent"} - else: - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_03_an_py310.py b/docs_src/request_files/tutorial001_03_an_py310.py new file mode 100644 index 0000000000..93098a677a --- /dev/null +++ b/docs_src/request_files/tutorial001_03_an_py310.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from fastapi import FastAPI, File, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]): + return {"file_size": len(file)} + + +@app.post("/uploadfile/") +async def create_upload_file( + file: Annotated[UploadFile, File(description="A file read as UploadFile")], +): + return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_03_py310.py b/docs_src/request_files/tutorial001_03_py310.py new file mode 100644 index 0000000000..d8005cc7d2 --- /dev/null +++ b/docs_src/request_files/tutorial001_03_py310.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, File, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file(file: bytes = File(description="A file read as bytes")): + return {"file_size": len(file)} + + +@app.post("/uploadfile/") +async def create_upload_file( + file: UploadFile = File(description="A file read as UploadFile"), +): + return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_an_py310.py b/docs_src/request_files/tutorial001_an_py310.py new file mode 100644 index 0000000000..26a7672216 --- /dev/null +++ b/docs_src/request_files/tutorial001_an_py310.py @@ -0,0 +1,15 @@ +from typing import Annotated + +from fastapi import FastAPI, File, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file(file: Annotated[bytes, File()]): + return {"file_size": len(file)} + + +@app.post("/uploadfile/") +async def create_upload_file(file: UploadFile): + return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_py310.py b/docs_src/request_files/tutorial001_py310.py new file mode 100644 index 0000000000..2e0ea63912 --- /dev/null +++ b/docs_src/request_files/tutorial001_py310.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI, File, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file(file: bytes = File()): + return {"file_size": len(file)} + + +@app.post("/uploadfile/") +async def create_upload_file(file: UploadFile): + return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial002_an_py310.py b/docs_src/request_files/tutorial002_an_py310.py new file mode 100644 index 0000000000..db524ceab6 --- /dev/null +++ b/docs_src/request_files/tutorial002_an_py310.py @@ -0,0 +1,33 @@ +from typing import Annotated + +from fastapi import FastAPI, File, UploadFile +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.post("/files/") +async def create_files(files: Annotated[list[bytes], File()]): + return {"file_sizes": [len(file) for file in files]} + + +@app.post("/uploadfiles/") +async def create_upload_files(files: list[UploadFile]): + return {"filenames": [file.filename for file in files]} + + +@app.get("/") +async def main(): + content = """ + +
+ + +
+
+ + +
+ + """ + return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial002_py310.py b/docs_src/request_files/tutorial002_py310.py new file mode 100644 index 0000000000..b64cf55987 --- /dev/null +++ b/docs_src/request_files/tutorial002_py310.py @@ -0,0 +1,31 @@ +from fastapi import FastAPI, File, UploadFile +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.post("/files/") +async def create_files(files: list[bytes] = File()): + return {"file_sizes": [len(file) for file in files]} + + +@app.post("/uploadfiles/") +async def create_upload_files(files: list[UploadFile]): + return {"filenames": [file.filename for file in files]} + + +@app.get("/") +async def main(): + content = """ + +
+ + +
+
+ + +
+ + """ + return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial003_an_py310.py b/docs_src/request_files/tutorial003_an_py310.py new file mode 100644 index 0000000000..5a8c5dab5c --- /dev/null +++ b/docs_src/request_files/tutorial003_an_py310.py @@ -0,0 +1,39 @@ +from typing import Annotated + +from fastapi import FastAPI, File, UploadFile +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.post("/files/") +async def create_files( + files: Annotated[list[bytes], File(description="Multiple files as bytes")], +): + return {"file_sizes": [len(file) for file in files]} + + +@app.post("/uploadfiles/") +async def create_upload_files( + files: Annotated[ + list[UploadFile], File(description="Multiple files as UploadFile") + ], +): + return {"filenames": [file.filename for file in files]} + + +@app.get("/") +async def main(): + content = """ + +
+ + +
+
+ + +
+ + """ + return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial003_py310.py b/docs_src/request_files/tutorial003_py310.py new file mode 100644 index 0000000000..96f5e8742d --- /dev/null +++ b/docs_src/request_files/tutorial003_py310.py @@ -0,0 +1,35 @@ +from fastapi import FastAPI, File, UploadFile +from fastapi.responses import HTMLResponse + +app = FastAPI() + + +@app.post("/files/") +async def create_files( + files: list[bytes] = File(description="Multiple files as bytes"), +): + return {"file_sizes": [len(file) for file in files]} + + +@app.post("/uploadfiles/") +async def create_upload_files( + files: list[UploadFile] = File(description="Multiple files as UploadFile"), +): + return {"filenames": [file.filename for file in files]} + + +@app.get("/") +async def main(): + content = """ + +
+ + +
+
+ + +
+ + """ + return HTMLResponse(content=content) diff --git a/docs_src/request_form_models/tutorial001_an_py310.py b/docs_src/request_form_models/tutorial001_an_py310.py new file mode 100644 index 0000000000..7cc81aae95 --- /dev/null +++ b/docs_src/request_form_models/tutorial001_an_py310.py @@ -0,0 +1,16 @@ +from typing import Annotated + +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + + +@app.post("/login/") +async def login(data: Annotated[FormData, Form()]): + return data diff --git a/docs_src/request_form_models/tutorial001_py310.py b/docs_src/request_form_models/tutorial001_py310.py new file mode 100644 index 0000000000..98feff0b9f --- /dev/null +++ b/docs_src/request_form_models/tutorial001_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + + +@app.post("/login/") +async def login(data: FormData = Form()): + return data diff --git a/docs_src/request_form_models/tutorial002_an_py310.py b/docs_src/request_form_models/tutorial002_an_py310.py new file mode 100644 index 0000000000..3004e08524 --- /dev/null +++ b/docs_src/request_form_models/tutorial002_an_py310.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + model_config = {"extra": "forbid"} + + +@app.post("/login/") +async def login(data: Annotated[FormData, Form()]): + return data diff --git a/docs_src/request_form_models/tutorial002_py310.py b/docs_src/request_form_models/tutorial002_py310.py new file mode 100644 index 0000000000..59b329e8d8 --- /dev/null +++ b/docs_src/request_form_models/tutorial002_py310.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + model_config = {"extra": "forbid"} + + +@app.post("/login/") +async def login(data: FormData = Form()): + return data diff --git a/docs_src/request_forms/tutorial001_an_py310.py b/docs_src/request_forms/tutorial001_an_py310.py new file mode 100644 index 0000000000..8e9d2ea53a --- /dev/null +++ b/docs_src/request_forms/tutorial001_an_py310.py @@ -0,0 +1,10 @@ +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} diff --git a/docs_src/request_forms/tutorial001_py310.py b/docs_src/request_forms/tutorial001_py310.py new file mode 100644 index 0000000000..a537700019 --- /dev/null +++ b/docs_src/request_forms/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI, Form + +app = FastAPI() + + +@app.post("/login/") +async def login(username: str = Form(), password: str = Form()): + return {"username": username} diff --git a/docs_src/request_forms_and_files/tutorial001_an_py310.py b/docs_src/request_forms_and_files/tutorial001_an_py310.py new file mode 100644 index 0000000000..12cc43e50a --- /dev/null +++ b/docs_src/request_forms_and_files/tutorial001_an_py310.py @@ -0,0 +1,18 @@ +from typing import Annotated + +from fastapi import FastAPI, File, Form, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file( + file: Annotated[bytes, File()], + fileb: Annotated[UploadFile, File()], + token: Annotated[str, Form()], +): + return { + "file_size": len(file), + "token": token, + "fileb_content_type": fileb.content_type, + } diff --git a/docs_src/request_forms_and_files/tutorial001_py310.py b/docs_src/request_forms_and_files/tutorial001_py310.py new file mode 100644 index 0000000000..7b5224ce53 --- /dev/null +++ b/docs_src/request_forms_and_files/tutorial001_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI, File, Form, UploadFile + +app = FastAPI() + + +@app.post("/files/") +async def create_file( + file: bytes = File(), fileb: UploadFile = File(), token: str = Form() +): + return { + "file_size": len(file), + "token": token, + "fileb_content_type": fileb.content_type, + } diff --git a/docs_src/response_change_status_code/tutorial001_py310.py b/docs_src/response_change_status_code/tutorial001_py310.py new file mode 100644 index 0000000000..197decbfbf --- /dev/null +++ b/docs_src/response_change_status_code/tutorial001_py310.py @@ -0,0 +1,13 @@ +from fastapi import FastAPI, Response, status + +app = FastAPI() + +tasks = {"foo": "Listen to the Bar Fighters"} + + +@app.put("/get-or-create-task/{task_id}", status_code=200) +def get_or_create_task(task_id: str, response: Response): + if task_id not in tasks: + tasks[task_id] = "This didn't exist before" + response.status_code = status.HTTP_201_CREATED + return tasks[task_id] diff --git a/docs_src/response_cookies/tutorial001_py310.py b/docs_src/response_cookies/tutorial001_py310.py new file mode 100644 index 0000000000..33f8e8f6e9 --- /dev/null +++ b/docs_src/response_cookies/tutorial001_py310.py @@ -0,0 +1,12 @@ +from fastapi import FastAPI +from fastapi.responses import JSONResponse + +app = FastAPI() + + +@app.post("/cookie/") +def create_cookie(): + content = {"message": "Come to the dark side, we have cookies"} + response = JSONResponse(content=content) + response.set_cookie(key="fakesession", value="fake-cookie-session-value") + return response diff --git a/docs_src/response_cookies/tutorial002_py310.py b/docs_src/response_cookies/tutorial002_py310.py new file mode 100644 index 0000000000..76c06fdb9f --- /dev/null +++ b/docs_src/response_cookies/tutorial002_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI, Response + +app = FastAPI() + + +@app.post("/cookie-and-object/") +def create_cookie(response: Response): + response.set_cookie(key="fakesession", value="fake-cookie-session-value") + return {"message": "Come to the dark side, we have cookies"} diff --git a/docs_src/response_directly/tutorial001_py39.py b/docs_src/response_directly/tutorial001_py39.py deleted file mode 100644 index 5ab655a8a7..0000000000 --- a/docs_src/response_directly/tutorial001_py39.py +++ /dev/null @@ -1,22 +0,0 @@ -from datetime import datetime -from typing import Union - -from fastapi import FastAPI -from fastapi.encoders import jsonable_encoder -from fastapi.responses import JSONResponse -from pydantic import BaseModel - - -class Item(BaseModel): - title: str - timestamp: datetime - description: Union[str, None] = None - - -app = FastAPI() - - -@app.put("/items/{id}") -def update_item(id: str, item: Item): - json_compatible_item_data = jsonable_encoder(item) - return JSONResponse(content=json_compatible_item_data) diff --git a/docs_src/response_directly/tutorial002_py310.py b/docs_src/response_directly/tutorial002_py310.py new file mode 100644 index 0000000000..6643da6e6d --- /dev/null +++ b/docs_src/response_directly/tutorial002_py310.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI, Response + +app = FastAPI() + + +@app.get("/legacy/") +def get_legacy_data(): + data = """ + +
+ Apply shampoo here. +
+ + You'll have to use soap here. + +
+ """ + return Response(content=data, media_type="application/xml") diff --git a/docs_src/response_headers/tutorial001_py310.py b/docs_src/response_headers/tutorial001_py310.py new file mode 100644 index 0000000000..2da02a470b --- /dev/null +++ b/docs_src/response_headers/tutorial001_py310.py @@ -0,0 +1,11 @@ +from fastapi import FastAPI +from fastapi.responses import JSONResponse + +app = FastAPI() + + +@app.get("/headers/") +def get_headers(): + content = {"message": "Hello World"} + headers = {"X-Cat-Dog": "alone in the world", "Content-Language": "en-US"} + return JSONResponse(content=content, headers=headers) diff --git a/docs_src/response_headers/tutorial002_py310.py b/docs_src/response_headers/tutorial002_py310.py new file mode 100644 index 0000000000..d2c4983051 --- /dev/null +++ b/docs_src/response_headers/tutorial002_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI, Response + +app = FastAPI() + + +@app.get("/headers-and-object/") +def get_headers(response: Response): + response.headers["X-Cat-Dog"] = "alone in the world" + return {"message": "Hello World"} diff --git a/docs_src/response_model/tutorial001_01_py39.py b/docs_src/response_model/tutorial001_01_py39.py deleted file mode 100644 index 16c78aa3fd..0000000000 --- a/docs_src/response_model/tutorial001_01_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: list[str] = [] - - -@app.post("/items/") -async def create_item(item: Item) -> Item: - return item - - -@app.get("/items/") -async def read_items() -> list[Item]: - return [ - Item(name="Portal Gun", price=42.0), - Item(name="Plumbus", price=32.0), - ] diff --git a/docs_src/response_model/tutorial001_py39.py b/docs_src/response_model/tutorial001_py39.py deleted file mode 100644 index 261e252d00..0000000000 --- a/docs_src/response_model/tutorial001_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Any, Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - tags: list[str] = [] - - -@app.post("/items/", response_model=Item) -async def create_item(item: Item) -> Any: - return item - - -@app.get("/items/", response_model=list[Item]) -async def read_items() -> Any: - return [ - {"name": "Portal Gun", "price": 42.0}, - {"name": "Plumbus", "price": 32.0}, - ] diff --git a/docs_src/response_model/tutorial002_py39.py b/docs_src/response_model/tutorial002_py39.py deleted file mode 100644 index a58668f9ef..0000000000 --- a/docs_src/response_model/tutorial002_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, EmailStr - -app = FastAPI() - - -class UserIn(BaseModel): - username: str - password: str - email: EmailStr - full_name: Union[str, None] = None - - -# Don't do this in production! -@app.post("/user/") -async def create_user(user: UserIn) -> UserIn: - return user diff --git a/docs_src/response_model/tutorial003_01_py39.py b/docs_src/response_model/tutorial003_01_py39.py deleted file mode 100644 index 52694b5510..0000000000 --- a/docs_src/response_model/tutorial003_01_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, EmailStr - -app = FastAPI() - - -class BaseUser(BaseModel): - username: str - email: EmailStr - full_name: Union[str, None] = None - - -class UserIn(BaseUser): - password: str - - -@app.post("/user/") -async def create_user(user: UserIn) -> BaseUser: - return user diff --git a/docs_src/response_model/tutorial003_02_py310.py b/docs_src/response_model/tutorial003_02_py310.py new file mode 100644 index 0000000000..df6a09646d --- /dev/null +++ b/docs_src/response_model/tutorial003_02_py310.py @@ -0,0 +1,11 @@ +from fastapi import FastAPI, Response +from fastapi.responses import JSONResponse, RedirectResponse + +app = FastAPI() + + +@app.get("/portal") +async def get_portal(teleport: bool = False) -> Response: + if teleport: + return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") + return JSONResponse(content={"message": "Here's your interdimensional portal."}) diff --git a/docs_src/response_model/tutorial003_03_py310.py b/docs_src/response_model/tutorial003_03_py310.py new file mode 100644 index 0000000000..0d4bd8de57 --- /dev/null +++ b/docs_src/response_model/tutorial003_03_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI +from fastapi.responses import RedirectResponse + +app = FastAPI() + + +@app.get("/teleport") +async def get_teleport() -> RedirectResponse: + return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") diff --git a/docs_src/response_model/tutorial003_04_py39.py b/docs_src/response_model/tutorial003_04_py39.py deleted file mode 100644 index b13a926929..0000000000 --- a/docs_src/response_model/tutorial003_04_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Response -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/portal") -async def get_portal(teleport: bool = False) -> Union[Response, dict]: - if teleport: - return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") - return {"message": "Here's your interdimensional portal."} diff --git a/docs_src/response_model/tutorial003_05_py39.py b/docs_src/response_model/tutorial003_05_py39.py deleted file mode 100644 index 0962061a60..0000000000 --- a/docs_src/response_model/tutorial003_05_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union - -from fastapi import FastAPI, Response -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/portal", response_model=None) -async def get_portal(teleport: bool = False) -> Union[Response, dict]: - if teleport: - return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") - return {"message": "Here's your interdimensional portal."} diff --git a/docs_src/response_model/tutorial003_py39.py b/docs_src/response_model/tutorial003_py39.py deleted file mode 100644 index c42dbc7077..0000000000 --- a/docs_src/response_model/tutorial003_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Any, Union - -from fastapi import FastAPI -from pydantic import BaseModel, EmailStr - -app = FastAPI() - - -class UserIn(BaseModel): - username: str - password: str - email: EmailStr - full_name: Union[str, None] = None - - -class UserOut(BaseModel): - username: str - email: EmailStr - full_name: Union[str, None] = None - - -@app.post("/user/", response_model=UserOut) -async def create_user(user: UserIn) -> Any: - return user diff --git a/docs_src/response_model/tutorial004_py39.py b/docs_src/response_model/tutorial004_py39.py deleted file mode 100644 index 9463b45ec1..0000000000 --- a/docs_src/response_model/tutorial004_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: float = 10.5 - tags: list[str] = [] - - -items = { - "foo": {"name": "Foo", "price": 50.2}, - "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, - "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}, -} - - -@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True) -async def read_item(item_id: str): - return items[item_id] diff --git a/docs_src/response_model/tutorial005_py39.py b/docs_src/response_model/tutorial005_py39.py deleted file mode 100644 index 30eb9f8e3f..0000000000 --- a/docs_src/response_model/tutorial005_py39.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: float = 10.5 - - -items = { - "foo": {"name": "Foo", "price": 50.2}, - "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2}, - "baz": { - "name": "Baz", - "description": "There goes my baz", - "price": 50.2, - "tax": 10.5, - }, -} - - -@app.get( - "/items/{item_id}/name", - response_model=Item, - response_model_include={"name", "description"}, -) -async def read_item_name(item_id: str): - return items[item_id] - - -@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"}) -async def read_item_public_data(item_id: str): - return items[item_id] diff --git a/docs_src/response_model/tutorial006_py39.py b/docs_src/response_model/tutorial006_py39.py deleted file mode 100644 index 3ffdb512bc..0000000000 --- a/docs_src/response_model/tutorial006_py39.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: float = 10.5 - - -items = { - "foo": {"name": "Foo", "price": 50.2}, - "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2}, - "baz": { - "name": "Baz", - "description": "There goes my baz", - "price": 50.2, - "tax": 10.5, - }, -} - - -@app.get( - "/items/{item_id}/name", - response_model=Item, - response_model_include=["name", "description"], -) -async def read_item_name(item_id: str): - return items[item_id] - - -@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"]) -async def read_item_public_data(item_id: str): - return items[item_id] diff --git a/docs_src/response_status_code/tutorial001_py310.py b/docs_src/response_status_code/tutorial001_py310.py new file mode 100644 index 0000000000..14b6d6e675 --- /dev/null +++ b/docs_src/response_status_code/tutorial001_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.post("/items/", status_code=201) +async def create_item(name: str): + return {"name": name} diff --git a/docs_src/response_status_code/tutorial002_py310.py b/docs_src/response_status_code/tutorial002_py310.py new file mode 100644 index 0000000000..4fcc9829db --- /dev/null +++ b/docs_src/response_status_code/tutorial002_py310.py @@ -0,0 +1,8 @@ +from fastapi import FastAPI, status + +app = FastAPI() + + +@app.post("/items/", status_code=status.HTTP_201_CREATED) +async def create_item(name: str): + return {"name": name} diff --git a/docs_src/schema_extra_example/tutorial001_pv1_py310.py b/docs_src/schema_extra_example/tutorial001_pv1_py310.py deleted file mode 100644 index b13b8a8c2c..0000000000 --- a/docs_src/schema_extra_example/tutorial001_pv1_py310.py +++ /dev/null @@ -1,29 +0,0 @@ -from fastapi import FastAPI -from pydantic.v1 import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str | None = None - price: float - tax: float | None = None - - class Config: - schema_extra = { - "examples": [ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } - ] - } - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial001_pv1_py39.py b/docs_src/schema_extra_example/tutorial001_pv1_py39.py deleted file mode 100644 index 3240b35d6d..0000000000 --- a/docs_src/schema_extra_example/tutorial001_pv1_py39.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic.v1 import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - class Config: - schema_extra = { - "examples": [ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } - ] - } - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial001_py39.py b/docs_src/schema_extra_example/tutorial001_py39.py deleted file mode 100644 index 32a66db3a9..0000000000 --- a/docs_src/schema_extra_example/tutorial001_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - model_config = { - "json_schema_extra": { - "examples": [ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } - ] - } - } - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial002_py39.py b/docs_src/schema_extra_example/tutorial002_py39.py deleted file mode 100644 index 70f06567c3..0000000000 --- a/docs_src/schema_extra_example/tutorial002_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -from fastapi import FastAPI -from pydantic import BaseModel, Field - -app = FastAPI() - - -class Item(BaseModel): - name: str = Field(examples=["Foo"]) - description: Union[str, None] = Field(default=None, examples=["A very nice Item"]) - price: float = Field(examples=[35.4]) - tax: Union[float, None] = Field(default=None, examples=[3.2]) - - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial003_an_py39.py b/docs_src/schema_extra_example/tutorial003_an_py39.py deleted file mode 100644 index 4728085617..0000000000 --- a/docs_src/schema_extra_example/tutorial003_an_py39.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - item_id: int, - item: Annotated[ - Item, - Body( - examples=[ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } - ], - ), - ], -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial003_py39.py b/docs_src/schema_extra_example/tutorial003_py39.py deleted file mode 100644 index 385f3de8a1..0000000000 --- a/docs_src/schema_extra_example/tutorial003_py39.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - item_id: int, - item: Item = Body( - examples=[ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - } - ], - ), -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial004_an_py39.py b/docs_src/schema_extra_example/tutorial004_an_py39.py deleted file mode 100644 index dc5a8fe49c..0000000000 --- a/docs_src/schema_extra_example/tutorial004_an_py39.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Annotated[ - Item, - Body( - examples=[ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, - { - "name": "Bar", - "price": "35.4", - }, - { - "name": "Baz", - "price": "thirty five point four", - }, - ], - ), - ], -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial004_py39.py b/docs_src/schema_extra_example/tutorial004_py39.py deleted file mode 100644 index 75514a3e91..0000000000 --- a/docs_src/schema_extra_example/tutorial004_py39.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Item = Body( - examples=[ - { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, - { - "name": "Bar", - "price": "35.4", - }, - { - "name": "Baz", - "price": "thirty five point four", - }, - ], - ), -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial005_an_py39.py b/docs_src/schema_extra_example/tutorial005_an_py39.py deleted file mode 100644 index edeb1affce..0000000000 --- a/docs_src/schema_extra_example/tutorial005_an_py39.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Annotated[ - Item, - Body( - openapi_examples={ - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": { - "name": "Bar", - "price": "35.4", - }, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", - }, - }, - }, - ), - ], -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/schema_extra_example/tutorial005_py39.py b/docs_src/schema_extra_example/tutorial005_py39.py deleted file mode 100644 index b8217c27e9..0000000000 --- a/docs_src/schema_extra_example/tutorial005_py39.py +++ /dev/null @@ -1,51 +0,0 @@ -from typing import Union - -from fastapi import Body, FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: Union[str, None] = None - price: float - tax: Union[float, None] = None - - -@app.put("/items/{item_id}") -async def update_item( - *, - item_id: int, - item: Item = Body( - openapi_examples={ - "normal": { - "summary": "A normal example", - "description": "A **normal** item works correctly.", - "value": { - "name": "Foo", - "description": "A very nice Item", - "price": 35.4, - "tax": 3.2, - }, - }, - "converted": { - "summary": "An example with converted data", - "description": "FastAPI can convert price `strings` to actual `numbers` automatically", - "value": { - "name": "Bar", - "price": "35.4", - }, - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": { - "name": "Baz", - "price": "thirty five point four", - }, - }, - }, - ), -): - results = {"item_id": item_id, "item": item} - return results diff --git a/docs_src/security/tutorial001_an_py310.py b/docs_src/security/tutorial001_an_py310.py new file mode 100644 index 0000000000..de110402ef --- /dev/null +++ b/docs_src/security/tutorial001_an_py310.py @@ -0,0 +1,13 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI +from fastapi.security import OAuth2PasswordBearer + +app = FastAPI() + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + + +@app.get("/items/") +async def read_items(token: Annotated[str, Depends(oauth2_scheme)]): + return {"token": token} diff --git a/docs_src/security/tutorial001_py310.py b/docs_src/security/tutorial001_py310.py new file mode 100644 index 0000000000..224e59602e --- /dev/null +++ b/docs_src/security/tutorial001_py310.py @@ -0,0 +1,11 @@ +from fastapi import Depends, FastAPI +from fastapi.security import OAuth2PasswordBearer + +app = FastAPI() + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") + + +@app.get("/items/") +async def read_items(token: str = Depends(oauth2_scheme)): + return {"token": token} diff --git a/docs_src/security/tutorial002_an_py39.py b/docs_src/security/tutorial002_an_py39.py deleted file mode 100644 index 7ff1c470bb..0000000000 --- a/docs_src/security/tutorial002_an_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI -from fastapi.security import OAuth2PasswordBearer -from pydantic import BaseModel - -app = FastAPI() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -def fake_decode_token(token): - return User( - username=token + "fakedecoded", email="john@example.com", full_name="John Doe" - ) - - -async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): - user = fake_decode_token(token) - return user - - -@app.get("/users/me") -async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]): - return current_user diff --git a/docs_src/security/tutorial002_py39.py b/docs_src/security/tutorial002_py39.py deleted file mode 100644 index bfd035221c..0000000000 --- a/docs_src/security/tutorial002_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI -from fastapi.security import OAuth2PasswordBearer -from pydantic import BaseModel - -app = FastAPI() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -def fake_decode_token(token): - return User( - username=token + "fakedecoded", email="john@example.com", full_name="John Doe" - ) - - -async def get_current_user(token: str = Depends(oauth2_scheme)): - user = fake_decode_token(token) - return user - - -@app.get("/users/me") -async def read_users_me(current_user: User = Depends(get_current_user)): - return current_user diff --git a/docs_src/security/tutorial003_an_py39.py b/docs_src/security/tutorial003_an_py39.py deleted file mode 100644 index b396210c82..0000000000 --- a/docs_src/security/tutorial003_an_py39.py +++ /dev/null @@ -1,94 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from pydantic import BaseModel - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "fakehashedsecret", - "disabled": False, - }, - "alice": { - "username": "alice", - "full_name": "Alice Wonderson", - "email": "alice@example.com", - "hashed_password": "fakehashedsecret2", - "disabled": True, - }, -} - -app = FastAPI() - - -def fake_hash_password(password: str): - return "fakehashed" + password - - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def fake_decode_token(token): - # This doesn't provide any security at all - # Check the next version - user = get_user(fake_users_db, token) - return user - - -async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): - user = fake_decode_token(token) - if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers={"WWW-Authenticate": "Bearer"}, - ) - return user - - -async def get_current_active_user( - current_user: Annotated[User, Depends(get_current_user)], -): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]): - user_dict = fake_users_db.get(form_data.username) - if not user_dict: - raise HTTPException(status_code=400, detail="Incorrect username or password") - user = UserInDB(**user_dict) - hashed_password = fake_hash_password(form_data.password) - if not hashed_password == user.hashed_password: - raise HTTPException(status_code=400, detail="Incorrect username or password") - - return {"access_token": user.username, "token_type": "bearer"} - - -@app.get("/users/me") -async def read_users_me( - current_user: Annotated[User, Depends(get_current_active_user)], -): - return current_user diff --git a/docs_src/security/tutorial003_py39.py b/docs_src/security/tutorial003_py39.py deleted file mode 100644 index ce7a71b68b..0000000000 --- a/docs_src/security/tutorial003_py39.py +++ /dev/null @@ -1,90 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from pydantic import BaseModel - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "fakehashedsecret", - "disabled": False, - }, - "alice": { - "username": "alice", - "full_name": "Alice Wonderson", - "email": "alice@example.com", - "hashed_password": "fakehashedsecret2", - "disabled": True, - }, -} - -app = FastAPI() - - -def fake_hash_password(password: str): - return "fakehashed" + password - - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def fake_decode_token(token): - # This doesn't provide any security at all - # Check the next version - user = get_user(fake_users_db, token) - return user - - -async def get_current_user(token: str = Depends(oauth2_scheme)): - user = fake_decode_token(token) - if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers={"WWW-Authenticate": "Bearer"}, - ) - return user - - -async def get_current_active_user(current_user: User = Depends(get_current_user)): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login(form_data: OAuth2PasswordRequestForm = Depends()): - user_dict = fake_users_db.get(form_data.username) - if not user_dict: - raise HTTPException(status_code=400, detail="Incorrect username or password") - user = UserInDB(**user_dict) - hashed_password = fake_hash_password(form_data.password) - if not hashed_password == user.hashed_password: - raise HTTPException(status_code=400, detail="Incorrect username or password") - - return {"access_token": user.username, "token_type": "bearer"} - - -@app.get("/users/me") -async def read_users_me(current_user: User = Depends(get_current_active_user)): - return current_user diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py deleted file mode 100644 index 73b3d456d1..0000000000 --- a/docs_src/security/tutorial004_an_py39.py +++ /dev/null @@ -1,147 +0,0 @@ -from datetime import datetime, timedelta, timezone -from typing import Annotated, Union - -import jwt -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from jwt.exceptions import InvalidTokenError -from pwdlib import PasswordHash -from pydantic import BaseModel - -# to get a string like this run: -# openssl rand -hex 32 -SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 30 - - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", - "disabled": False, - } -} - - -class Token(BaseModel): - access_token: str - token_type: str - - -class TokenData(BaseModel): - username: Union[str, None] = None - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -password_hash = PasswordHash.recommended() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - -app = FastAPI() - - -def verify_password(plain_password, hashed_password): - return password_hash.verify(plain_password, hashed_password) - - -def get_password_hash(password): - return password_hash.hash(password) - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def authenticate_user(fake_db, username: str, password: str): - user = get_user(fake_db, username) - if not user: - return False - if not verify_password(password, user.hashed_password): - return False - return user - - -def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): - to_encode = data.copy() - if expires_delta: - expire = datetime.now(timezone.utc) + expires_delta - else: - expire = datetime.now(timezone.utc) + timedelta(minutes=15) - to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - return encoded_jwt - - -async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): - credentials_exception = HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Could not validate credentials", - headers={"WWW-Authenticate": "Bearer"}, - ) - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username = payload.get("sub") - if username is None: - raise credentials_exception - token_data = TokenData(username=username) - except InvalidTokenError: - raise credentials_exception - user = get_user(fake_users_db, username=token_data.username) - if user is None: - raise credentials_exception - return user - - -async def get_current_active_user( - current_user: Annotated[User, Depends(get_current_user)], -): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login_for_access_token( - form_data: Annotated[OAuth2PasswordRequestForm, Depends()], -) -> Token: - user = authenticate_user(fake_users_db, form_data.username, form_data.password) - if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect username or password", - headers={"WWW-Authenticate": "Bearer"}, - ) - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - access_token = create_access_token( - data={"sub": user.username}, expires_delta=access_token_expires - ) - return Token(access_token=access_token, token_type="bearer") - - -@app.get("/users/me/") -async def read_users_me( - current_user: Annotated[User, Depends(get_current_active_user)], -) -> User: - return current_user - - -@app.get("/users/me/items/") -async def read_own_items( - current_user: Annotated[User, Depends(get_current_active_user)], -): - return [{"item_id": "Foo", "owner": current_user.username}] diff --git a/docs_src/security/tutorial004_py39.py b/docs_src/security/tutorial004_py39.py deleted file mode 100644 index e67403d5d7..0000000000 --- a/docs_src/security/tutorial004_py39.py +++ /dev/null @@ -1,141 +0,0 @@ -from datetime import datetime, timedelta, timezone -from typing import Union - -import jwt -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from jwt.exceptions import InvalidTokenError -from pwdlib import PasswordHash -from pydantic import BaseModel - -# to get a string like this run: -# openssl rand -hex 32 -SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 30 - - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", - "disabled": False, - } -} - - -class Token(BaseModel): - access_token: str - token_type: str - - -class TokenData(BaseModel): - username: Union[str, None] = None - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -password_hash = PasswordHash.recommended() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - -app = FastAPI() - - -def verify_password(plain_password, hashed_password): - return password_hash.verify(plain_password, hashed_password) - - -def get_password_hash(password): - return password_hash.hash(password) - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def authenticate_user(fake_db, username: str, password: str): - user = get_user(fake_db, username) - if not user: - return False - if not verify_password(password, user.hashed_password): - return False - return user - - -def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): - to_encode = data.copy() - if expires_delta: - expire = datetime.now(timezone.utc) + expires_delta - else: - expire = datetime.now(timezone.utc) + timedelta(minutes=15) - to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - return encoded_jwt - - -async def get_current_user(token: str = Depends(oauth2_scheme)): - credentials_exception = HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Could not validate credentials", - headers={"WWW-Authenticate": "Bearer"}, - ) - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username = payload.get("sub") - if username is None: - raise credentials_exception - token_data = TokenData(username=username) - except InvalidTokenError: - raise credentials_exception - user = get_user(fake_users_db, username=token_data.username) - if user is None: - raise credentials_exception - return user - - -async def get_current_active_user(current_user: User = Depends(get_current_user)): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login_for_access_token( - form_data: OAuth2PasswordRequestForm = Depends(), -) -> Token: - user = authenticate_user(fake_users_db, form_data.username, form_data.password) - if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect username or password", - headers={"WWW-Authenticate": "Bearer"}, - ) - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - access_token = create_access_token( - data={"sub": user.username}, expires_delta=access_token_expires - ) - return Token(access_token=access_token, token_type="bearer") - - -@app.get("/users/me/") -async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: - return current_user - - -@app.get("/users/me/items/") -async def read_own_items(current_user: User = Depends(get_current_active_user)): - return [{"item_id": "Foo", "owner": current_user.username}] diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py deleted file mode 100644 index 1aeba688a6..0000000000 --- a/docs_src/security/tutorial005_an_py39.py +++ /dev/null @@ -1,179 +0,0 @@ -from datetime import datetime, timedelta, timezone -from typing import Annotated, Union - -import jwt -from fastapi import Depends, FastAPI, HTTPException, Security, status -from fastapi.security import ( - OAuth2PasswordBearer, - OAuth2PasswordRequestForm, - SecurityScopes, -) -from jwt.exceptions import InvalidTokenError -from pwdlib import PasswordHash -from pydantic import BaseModel, ValidationError - -# to get a string like this run: -# openssl rand -hex 32 -SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 30 - - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", - "disabled": False, - }, - "alice": { - "username": "alice", - "full_name": "Alice Chains", - "email": "alicechains@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", - "disabled": True, - }, -} - - -class Token(BaseModel): - access_token: str - token_type: str - - -class TokenData(BaseModel): - username: Union[str, None] = None - scopes: list[str] = [] - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -password_hash = PasswordHash.recommended() - -oauth2_scheme = OAuth2PasswordBearer( - tokenUrl="token", - scopes={"me": "Read information about the current user.", "items": "Read items."}, -) - -app = FastAPI() - - -def verify_password(plain_password, hashed_password): - return password_hash.verify(plain_password, hashed_password) - - -def get_password_hash(password): - return password_hash.hash(password) - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def authenticate_user(fake_db, username: str, password: str): - user = get_user(fake_db, username) - if not user: - return False - if not verify_password(password, user.hashed_password): - return False - return user - - -def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): - to_encode = data.copy() - if expires_delta: - expire = datetime.now(timezone.utc) + expires_delta - else: - expire = datetime.now(timezone.utc) + timedelta(minutes=15) - to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - return encoded_jwt - - -async def get_current_user( - security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)] -): - if security_scopes.scopes: - authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' - else: - authenticate_value = "Bearer" - credentials_exception = HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Could not validate credentials", - headers={"WWW-Authenticate": authenticate_value}, - ) - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username = payload.get("sub") - if username is None: - raise credentials_exception - scope: str = payload.get("scope", "") - token_scopes = scope.split(" ") - token_data = TokenData(scopes=token_scopes, username=username) - except (InvalidTokenError, ValidationError): - raise credentials_exception - user = get_user(fake_users_db, username=token_data.username) - if user is None: - raise credentials_exception - for scope in security_scopes.scopes: - if scope not in token_data.scopes: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Not enough permissions", - headers={"WWW-Authenticate": authenticate_value}, - ) - return user - - -async def get_current_active_user( - current_user: Annotated[User, Security(get_current_user, scopes=["me"])], -): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login_for_access_token( - form_data: Annotated[OAuth2PasswordRequestForm, Depends()], -) -> Token: - user = authenticate_user(fake_users_db, form_data.username, form_data.password) - if not user: - raise HTTPException(status_code=400, detail="Incorrect username or password") - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - access_token = create_access_token( - data={"sub": user.username, "scope": " ".join(form_data.scopes)}, - expires_delta=access_token_expires, - ) - return Token(access_token=access_token, token_type="bearer") - - -@app.get("/users/me/") -async def read_users_me( - current_user: Annotated[User, Depends(get_current_active_user)], -) -> User: - return current_user - - -@app.get("/users/me/items/") -async def read_own_items( - current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])], -): - return [{"item_id": "Foo", "owner": current_user.username}] - - -@app.get("/status/") -async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]): - return {"status": "ok"} diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py deleted file mode 100644 index 32280aa48b..0000000000 --- a/docs_src/security/tutorial005_py39.py +++ /dev/null @@ -1,177 +0,0 @@ -from datetime import datetime, timedelta, timezone -from typing import Union - -import jwt -from fastapi import Depends, FastAPI, HTTPException, Security, status -from fastapi.security import ( - OAuth2PasswordBearer, - OAuth2PasswordRequestForm, - SecurityScopes, -) -from jwt.exceptions import InvalidTokenError -from pwdlib import PasswordHash -from pydantic import BaseModel, ValidationError - -# to get a string like this run: -# openssl rand -hex 32 -SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 30 - - -fake_users_db = { - "johndoe": { - "username": "johndoe", - "full_name": "John Doe", - "email": "johndoe@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", - "disabled": False, - }, - "alice": { - "username": "alice", - "full_name": "Alice Chains", - "email": "alicechains@example.com", - "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", - "disabled": True, - }, -} - - -class Token(BaseModel): - access_token: str - token_type: str - - -class TokenData(BaseModel): - username: Union[str, None] = None - scopes: list[str] = [] - - -class User(BaseModel): - username: str - email: Union[str, None] = None - full_name: Union[str, None] = None - disabled: Union[bool, None] = None - - -class UserInDB(User): - hashed_password: str - - -password_hash = PasswordHash.recommended() - -oauth2_scheme = OAuth2PasswordBearer( - tokenUrl="token", - scopes={"me": "Read information about the current user.", "items": "Read items."}, -) - -app = FastAPI() - - -def verify_password(plain_password, hashed_password): - return password_hash.verify(plain_password, hashed_password) - - -def get_password_hash(password): - return password_hash.hash(password) - - -def get_user(db, username: str): - if username in db: - user_dict = db[username] - return UserInDB(**user_dict) - - -def authenticate_user(fake_db, username: str, password: str): - user = get_user(fake_db, username) - if not user: - return False - if not verify_password(password, user.hashed_password): - return False - return user - - -def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): - to_encode = data.copy() - if expires_delta: - expire = datetime.now(timezone.utc) + expires_delta - else: - expire = datetime.now(timezone.utc) + timedelta(minutes=15) - to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - return encoded_jwt - - -async def get_current_user( - security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme) -): - if security_scopes.scopes: - authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' - else: - authenticate_value = "Bearer" - credentials_exception = HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Could not validate credentials", - headers={"WWW-Authenticate": authenticate_value}, - ) - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") - if username is None: - raise credentials_exception - scope: str = payload.get("scope", "") - token_scopes = scope.split(" ") - token_data = TokenData(scopes=token_scopes, username=username) - except (InvalidTokenError, ValidationError): - raise credentials_exception - user = get_user(fake_users_db, username=token_data.username) - if user is None: - raise credentials_exception - for scope in security_scopes.scopes: - if scope not in token_data.scopes: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Not enough permissions", - headers={"WWW-Authenticate": authenticate_value}, - ) - return user - - -async def get_current_active_user( - current_user: User = Security(get_current_user, scopes=["me"]), -): - if current_user.disabled: - raise HTTPException(status_code=400, detail="Inactive user") - return current_user - - -@app.post("/token") -async def login_for_access_token( - form_data: OAuth2PasswordRequestForm = Depends(), -) -> Token: - user = authenticate_user(fake_users_db, form_data.username, form_data.password) - if not user: - raise HTTPException(status_code=400, detail="Incorrect username or password") - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - access_token = create_access_token( - data={"sub": user.username, "scope": " ".join(form_data.scopes)}, - expires_delta=access_token_expires, - ) - return Token(access_token=access_token, token_type="bearer") - - -@app.get("/users/me/") -async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User: - return current_user - - -@app.get("/users/me/items/") -async def read_own_items( - current_user: User = Security(get_current_active_user, scopes=["items"]), -): - return [{"item_id": "Foo", "owner": current_user.username}] - - -@app.get("/status/") -async def read_system_status(current_user: User = Depends(get_current_user)): - return {"status": "ok"} diff --git a/docs_src/security/tutorial006_an_py310.py b/docs_src/security/tutorial006_an_py310.py new file mode 100644 index 0000000000..03c696a4b6 --- /dev/null +++ b/docs_src/security/tutorial006_an_py310.py @@ -0,0 +1,13 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI +from fastapi.security import HTTPBasic, HTTPBasicCredentials + +app = FastAPI() + +security = HTTPBasic() + + +@app.get("/users/me") +def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]): + return {"username": credentials.username, "password": credentials.password} diff --git a/docs_src/security/tutorial006_py310.py b/docs_src/security/tutorial006_py310.py new file mode 100644 index 0000000000..29121ffd63 --- /dev/null +++ b/docs_src/security/tutorial006_py310.py @@ -0,0 +1,11 @@ +from fastapi import Depends, FastAPI +from fastapi.security import HTTPBasic, HTTPBasicCredentials + +app = FastAPI() + +security = HTTPBasic() + + +@app.get("/users/me") +def read_current_user(credentials: HTTPBasicCredentials = Depends(security)): + return {"username": credentials.username, "password": credentials.password} diff --git a/docs_src/security/tutorial007_an_py310.py b/docs_src/security/tutorial007_an_py310.py new file mode 100644 index 0000000000..87ef986574 --- /dev/null +++ b/docs_src/security/tutorial007_an_py310.py @@ -0,0 +1,36 @@ +import secrets +from typing import Annotated + +from fastapi import Depends, FastAPI, HTTPException, status +from fastapi.security import HTTPBasic, HTTPBasicCredentials + +app = FastAPI() + +security = HTTPBasic() + + +def get_current_username( + credentials: Annotated[HTTPBasicCredentials, Depends(security)], +): + current_username_bytes = credentials.username.encode("utf8") + correct_username_bytes = b"stanleyjobson" + is_correct_username = secrets.compare_digest( + current_username_bytes, correct_username_bytes + ) + current_password_bytes = credentials.password.encode("utf8") + correct_password_bytes = b"swordfish" + is_correct_password = secrets.compare_digest( + current_password_bytes, correct_password_bytes + ) + if not (is_correct_username and is_correct_password): + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Incorrect username or password", + headers={"WWW-Authenticate": "Basic"}, + ) + return credentials.username + + +@app.get("/users/me") +def read_current_user(username: Annotated[str, Depends(get_current_username)]): + return {"username": username} diff --git a/docs_src/security/tutorial007_py310.py b/docs_src/security/tutorial007_py310.py new file mode 100644 index 0000000000..ac816eb0c1 --- /dev/null +++ b/docs_src/security/tutorial007_py310.py @@ -0,0 +1,33 @@ +import secrets + +from fastapi import Depends, FastAPI, HTTPException, status +from fastapi.security import HTTPBasic, HTTPBasicCredentials + +app = FastAPI() + +security = HTTPBasic() + + +def get_current_username(credentials: HTTPBasicCredentials = Depends(security)): + current_username_bytes = credentials.username.encode("utf8") + correct_username_bytes = b"stanleyjobson" + is_correct_username = secrets.compare_digest( + current_username_bytes, correct_username_bytes + ) + current_password_bytes = credentials.password.encode("utf8") + correct_password_bytes = b"swordfish" + is_correct_password = secrets.compare_digest( + current_password_bytes, correct_password_bytes + ) + if not (is_correct_username and is_correct_password): + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Incorrect username or password", + headers={"WWW-Authenticate": "Basic"}, + ) + return credentials.username + + +@app.get("/users/me") +def read_current_user(username: str = Depends(get_current_username)): + return {"username": username} diff --git a/docs_src/separate_openapi_schemas/tutorial001_py39.py b/docs_src/separate_openapi_schemas/tutorial001_py39.py deleted file mode 100644 index 63cffd1e30..0000000000 --- a/docs_src/separate_openapi_schemas/tutorial001_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Optional - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Optional[str] = None - - -app = FastAPI() - - -@app.post("/items/") -def create_item(item: Item): - return item - - -@app.get("/items/") -def read_items() -> list[Item]: - return [ - Item( - name="Portal Gun", - description="Device to travel through the multi-rick-verse", - ), - Item(name="Plumbus"), - ] diff --git a/docs_src/separate_openapi_schemas/tutorial002_py39.py b/docs_src/separate_openapi_schemas/tutorial002_py39.py deleted file mode 100644 index 50d997d92a..0000000000 --- a/docs_src/separate_openapi_schemas/tutorial002_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Optional - -from fastapi import FastAPI -from pydantic import BaseModel - - -class Item(BaseModel): - name: str - description: Optional[str] = None - - -app = FastAPI(separate_input_output_schemas=False) - - -@app.post("/items/") -def create_item(item: Item): - return item - - -@app.get("/items/") -def read_items() -> list[Item]: - return [ - Item( - name="Portal Gun", - description="Device to travel through the multi-rick-verse", - ), - Item(name="Plumbus"), - ] diff --git a/docs_src/settings/app01_py310/__init__.py b/docs_src/settings/app01_py310/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/settings/app03_an_py39/config_pv1.py b/docs_src/settings/app01_py310/config.py similarity index 59% rename from docs_src/settings/app03_an_py39/config_pv1.py rename to docs_src/settings/app01_py310/config.py index 7ae66ef77c..b31b8811d6 100644 --- a/docs_src/settings/app03_an_py39/config_pv1.py +++ b/docs_src/settings/app01_py310/config.py @@ -1,4 +1,4 @@ -from pydantic.v1 import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): @@ -6,5 +6,5 @@ class Settings(BaseSettings): admin_email: str items_per_user: int = 50 - class Config: - env_file = ".env" + +settings = Settings() diff --git a/docs_src/settings/app01_py310/main.py b/docs_src/settings/app01_py310/main.py new file mode 100644 index 0000000000..4a3a86ce20 --- /dev/null +++ b/docs_src/settings/app01_py310/main.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI + +from .config import settings + +app = FastAPI() + + +@app.get("/info") +async def info(): + return { + "app_name": settings.app_name, + "admin_email": settings.admin_email, + "items_per_user": settings.items_per_user, + } diff --git a/docs_src/settings/app02_an_py310/__init__.py b/docs_src/settings/app02_an_py310/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/settings/app03_py39/config_pv1.py b/docs_src/settings/app02_an_py310/config.py similarity index 58% rename from docs_src/settings/app03_py39/config_pv1.py rename to docs_src/settings/app02_an_py310/config.py index 7ae66ef77c..e17b5035dc 100644 --- a/docs_src/settings/app03_py39/config_pv1.py +++ b/docs_src/settings/app02_an_py310/config.py @@ -1,10 +1,7 @@ -from pydantic.v1 import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): app_name: str = "Awesome API" admin_email: str items_per_user: int = 50 - - class Config: - env_file = ".env" diff --git a/docs_src/settings/app02_an_py310/main.py b/docs_src/settings/app02_an_py310/main.py new file mode 100644 index 0000000000..6d5db12a87 --- /dev/null +++ b/docs_src/settings/app02_an_py310/main.py @@ -0,0 +1,22 @@ +from functools import lru_cache +from typing import Annotated + +from fastapi import Depends, FastAPI + +from .config import Settings + +app = FastAPI() + + +@lru_cache +def get_settings(): + return Settings() + + +@app.get("/info") +async def info(settings: Annotated[Settings, Depends(get_settings)]): + return { + "app_name": settings.app_name, + "admin_email": settings.admin_email, + "items_per_user": settings.items_per_user, + } diff --git a/docs_src/settings/app02_an_py310/test_main.py b/docs_src/settings/app02_an_py310/test_main.py new file mode 100644 index 0000000000..7a04d7e8ee --- /dev/null +++ b/docs_src/settings/app02_an_py310/test_main.py @@ -0,0 +1,23 @@ +from fastapi.testclient import TestClient + +from .config import Settings +from .main import app, get_settings + +client = TestClient(app) + + +def get_settings_override(): + return Settings(admin_email="testing_admin@example.com") + + +app.dependency_overrides[get_settings] = get_settings_override + + +def test_app(): + response = client.get("/info") + data = response.json() + assert data == { + "app_name": "Awesome API", + "admin_email": "testing_admin@example.com", + "items_per_user": 50, + } diff --git a/docs_src/settings/app02_py310/__init__.py b/docs_src/settings/app02_py310/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/settings/app02_py310/config.py b/docs_src/settings/app02_py310/config.py new file mode 100644 index 0000000000..e17b5035dc --- /dev/null +++ b/docs_src/settings/app02_py310/config.py @@ -0,0 +1,7 @@ +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + app_name: str = "Awesome API" + admin_email: str + items_per_user: int = 50 diff --git a/docs_src/settings/app02_py310/main.py b/docs_src/settings/app02_py310/main.py new file mode 100644 index 0000000000..941f82e6b3 --- /dev/null +++ b/docs_src/settings/app02_py310/main.py @@ -0,0 +1,21 @@ +from functools import lru_cache + +from fastapi import Depends, FastAPI + +from .config import Settings + +app = FastAPI() + + +@lru_cache +def get_settings(): + return Settings() + + +@app.get("/info") +async def info(settings: Settings = Depends(get_settings)): + return { + "app_name": settings.app_name, + "admin_email": settings.admin_email, + "items_per_user": settings.items_per_user, + } diff --git a/docs_src/settings/app02_py310/test_main.py b/docs_src/settings/app02_py310/test_main.py new file mode 100644 index 0000000000..7a04d7e8ee --- /dev/null +++ b/docs_src/settings/app02_py310/test_main.py @@ -0,0 +1,23 @@ +from fastapi.testclient import TestClient + +from .config import Settings +from .main import app, get_settings + +client = TestClient(app) + + +def get_settings_override(): + return Settings(admin_email="testing_admin@example.com") + + +app.dependency_overrides[get_settings] = get_settings_override + + +def test_app(): + response = client.get("/info") + data = response.json() + assert data == { + "app_name": "Awesome API", + "admin_email": "testing_admin@example.com", + "items_per_user": 50, + } diff --git a/docs_src/settings/app03_an_py310/__init__.py b/docs_src/settings/app03_an_py310/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/settings/app03_an_py310/config.py b/docs_src/settings/app03_an_py310/config.py new file mode 100644 index 0000000000..08f8f88c28 --- /dev/null +++ b/docs_src/settings/app03_an_py310/config.py @@ -0,0 +1,9 @@ +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + app_name: str = "Awesome API" + admin_email: str + items_per_user: int = 50 + + model_config = SettingsConfigDict(env_file=".env") diff --git a/docs_src/settings/app03_an_py310/main.py b/docs_src/settings/app03_an_py310/main.py new file mode 100644 index 0000000000..2f64b9cd17 --- /dev/null +++ b/docs_src/settings/app03_an_py310/main.py @@ -0,0 +1,22 @@ +from functools import lru_cache +from typing import Annotated + +from fastapi import Depends, FastAPI + +from . import config + +app = FastAPI() + + +@lru_cache +def get_settings(): + return config.Settings() + + +@app.get("/info") +async def info(settings: Annotated[config.Settings, Depends(get_settings)]): + return { + "app_name": settings.app_name, + "admin_email": settings.admin_email, + "items_per_user": settings.items_per_user, + } diff --git a/docs_src/settings/app03_py310/__init__.py b/docs_src/settings/app03_py310/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/settings/app03_py310/config.py b/docs_src/settings/app03_py310/config.py new file mode 100644 index 0000000000..08f8f88c28 --- /dev/null +++ b/docs_src/settings/app03_py310/config.py @@ -0,0 +1,9 @@ +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + app_name: str = "Awesome API" + admin_email: str + items_per_user: int = 50 + + model_config = SettingsConfigDict(env_file=".env") diff --git a/docs_src/settings/app03_py310/main.py b/docs_src/settings/app03_py310/main.py new file mode 100644 index 0000000000..ea64a5709c --- /dev/null +++ b/docs_src/settings/app03_py310/main.py @@ -0,0 +1,21 @@ +from functools import lru_cache + +from fastapi import Depends, FastAPI + +from . import config + +app = FastAPI() + + +@lru_cache +def get_settings(): + return config.Settings() + + +@app.get("/info") +async def info(settings: config.Settings = Depends(get_settings)): + return { + "app_name": settings.app_name, + "admin_email": settings.admin_email, + "items_per_user": settings.items_per_user, + } diff --git a/docs_src/settings/tutorial001_pv1_py39.py b/docs_src/settings/tutorial001_py310.py similarity index 89% rename from docs_src/settings/tutorial001_pv1_py39.py rename to docs_src/settings/tutorial001_py310.py index 20ad2bbf62..d48c4c060c 100644 --- a/docs_src/settings/tutorial001_pv1_py39.py +++ b/docs_src/settings/tutorial001_py310.py @@ -1,5 +1,5 @@ from fastapi import FastAPI -from pydantic.v1 import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): diff --git a/docs_src/sql_databases/tutorial001_an_py39.py b/docs_src/sql_databases/tutorial001_an_py39.py deleted file mode 100644 index 5958927461..0000000000 --- a/docs_src/sql_databases/tutorial001_an_py39.py +++ /dev/null @@ -1,73 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class Hero(SQLModel, table=True): - id: Union[int, None] = Field(default=None, primary_key=True) - name: str = Field(index=True) - age: Union[int, None] = Field(default=None, index=True) - secret_name: str - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -SessionDep = Annotated[Session, Depends(get_session)] - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/") -def create_hero(hero: Hero, session: SessionDep) -> Hero: - session.add(hero) - session.commit() - session.refresh(hero) - return hero - - -@app.get("/heroes/") -def read_heroes( - session: SessionDep, - offset: int = 0, - limit: Annotated[int, Query(le=100)] = 100, -) -> list[Hero]: - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes - - -@app.get("/heroes/{hero_id}") -def read_hero(hero_id: int, session: SessionDep) -> Hero: - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero - - -@app.delete("/heroes/{hero_id}") -def delete_hero(hero_id: int, session: SessionDep): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} diff --git a/docs_src/sql_databases/tutorial001_py39.py b/docs_src/sql_databases/tutorial001_py39.py deleted file mode 100644 index 410a52d0c0..0000000000 --- a/docs_src/sql_databases/tutorial001_py39.py +++ /dev/null @@ -1,71 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class Hero(SQLModel, table=True): - id: Union[int, None] = Field(default=None, primary_key=True) - name: str = Field(index=True) - age: Union[int, None] = Field(default=None, index=True) - secret_name: str - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/") -def create_hero(hero: Hero, session: Session = Depends(get_session)) -> Hero: - session.add(hero) - session.commit() - session.refresh(hero) - return hero - - -@app.get("/heroes/") -def read_heroes( - session: Session = Depends(get_session), - offset: int = 0, - limit: int = Query(default=100, le=100), -) -> list[Hero]: - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes - - -@app.get("/heroes/{hero_id}") -def read_hero(hero_id: int, session: Session = Depends(get_session)) -> Hero: - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero - - -@app.delete("/heroes/{hero_id}") -def delete_hero(hero_id: int, session: Session = Depends(get_session)): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} diff --git a/docs_src/sql_databases/tutorial002_an_py39.py b/docs_src/sql_databases/tutorial002_an_py39.py deleted file mode 100644 index a8a0721ff6..0000000000 --- a/docs_src/sql_databases/tutorial002_an_py39.py +++ /dev/null @@ -1,103 +0,0 @@ -from typing import Annotated, Union - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - age: Union[int, None] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Union[int, None] = Field(default=None, primary_key=True) - secret_name: str - - -class HeroPublic(HeroBase): - id: int - - -class HeroCreate(HeroBase): - secret_name: str - - -class HeroUpdate(HeroBase): - name: Union[str, None] = None - age: Union[int, None] = None - secret_name: Union[str, None] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -SessionDep = Annotated[Session, Depends(get_session)] -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -def create_hero(hero: HeroCreate, session: SessionDep): - db_hero = Hero.model_validate(hero) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero - - -@app.get("/heroes/", response_model=list[HeroPublic]) -def read_heroes( - session: SessionDep, - offset: int = 0, - limit: Annotated[int, Query(le=100)] = 100, -): - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes - - -@app.get("/heroes/{hero_id}", response_model=HeroPublic) -def read_hero(hero_id: int, session: SessionDep): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero - - -@app.patch("/heroes/{hero_id}", response_model=HeroPublic) -def update_hero(hero_id: int, hero: HeroUpdate, session: SessionDep): - hero_db = session.get(Hero, hero_id) - if not hero_db: - raise HTTPException(status_code=404, detail="Hero not found") - hero_data = hero.model_dump(exclude_unset=True) - hero_db.sqlmodel_update(hero_data) - session.add(hero_db) - session.commit() - session.refresh(hero_db) - return hero_db - - -@app.delete("/heroes/{hero_id}") -def delete_hero(hero_id: int, session: SessionDep): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} diff --git a/docs_src/sql_databases/tutorial002_py39.py b/docs_src/sql_databases/tutorial002_py39.py deleted file mode 100644 index d8f5dd0901..0000000000 --- a/docs_src/sql_databases/tutorial002_py39.py +++ /dev/null @@ -1,104 +0,0 @@ -from typing import Union - -from fastapi import Depends, FastAPI, HTTPException, Query -from sqlmodel import Field, Session, SQLModel, create_engine, select - - -class HeroBase(SQLModel): - name: str = Field(index=True) - age: Union[int, None] = Field(default=None, index=True) - - -class Hero(HeroBase, table=True): - id: Union[int, None] = Field(default=None, primary_key=True) - secret_name: str - - -class HeroPublic(HeroBase): - id: int - - -class HeroCreate(HeroBase): - secret_name: str - - -class HeroUpdate(HeroBase): - name: Union[str, None] = None - age: Union[int, None] = None - secret_name: Union[str, None] = None - - -sqlite_file_name = "database.db" -sqlite_url = f"sqlite:///{sqlite_file_name}" - -connect_args = {"check_same_thread": False} -engine = create_engine(sqlite_url, connect_args=connect_args) - - -def create_db_and_tables(): - SQLModel.metadata.create_all(engine) - - -def get_session(): - with Session(engine) as session: - yield session - - -app = FastAPI() - - -@app.on_event("startup") -def on_startup(): - create_db_and_tables() - - -@app.post("/heroes/", response_model=HeroPublic) -def create_hero(hero: HeroCreate, session: Session = Depends(get_session)): - db_hero = Hero.model_validate(hero) - session.add(db_hero) - session.commit() - session.refresh(db_hero) - return db_hero - - -@app.get("/heroes/", response_model=list[HeroPublic]) -def read_heroes( - session: Session = Depends(get_session), - offset: int = 0, - limit: int = Query(default=100, le=100), -): - heroes = session.exec(select(Hero).offset(offset).limit(limit)).all() - return heroes - - -@app.get("/heroes/{hero_id}", response_model=HeroPublic) -def read_hero(hero_id: int, session: Session = Depends(get_session)): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - return hero - - -@app.patch("/heroes/{hero_id}", response_model=HeroPublic) -def update_hero( - hero_id: int, hero: HeroUpdate, session: Session = Depends(get_session) -): - hero_db = session.get(Hero, hero_id) - if not hero_db: - raise HTTPException(status_code=404, detail="Hero not found") - hero_data = hero.model_dump(exclude_unset=True) - hero_db.sqlmodel_update(hero_data) - session.add(hero_db) - session.commit() - session.refresh(hero_db) - return hero_db - - -@app.delete("/heroes/{hero_id}") -def delete_hero(hero_id: int, session: Session = Depends(get_session)): - hero = session.get(Hero, hero_id) - if not hero: - raise HTTPException(status_code=404, detail="Hero not found") - session.delete(hero) - session.commit() - return {"ok": True} diff --git a/docs_src/static_files/tutorial001_py310.py b/docs_src/static_files/tutorial001_py310.py new file mode 100644 index 0000000000..460352c7e1 --- /dev/null +++ b/docs_src/static_files/tutorial001_py310.py @@ -0,0 +1,6 @@ +from fastapi import FastAPI +from fastapi.staticfiles import StaticFiles + +app = FastAPI() + +app.mount("/static", StaticFiles(directory="static"), name="static") diff --git a/docs_src/sub_applications/tutorial001_py310.py b/docs_src/sub_applications/tutorial001_py310.py new file mode 100644 index 0000000000..57e627e804 --- /dev/null +++ b/docs_src/sub_applications/tutorial001_py310.py @@ -0,0 +1,19 @@ +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/app") +def read_main(): + return {"message": "Hello World from main app"} + + +subapi = FastAPI() + + +@subapi.get("/sub") +def read_sub(): + return {"message": "Hello World from sub API"} + + +app.mount("/subapi", subapi) diff --git a/docs_src/templates/tutorial001_py310.py b/docs_src/templates/tutorial001_py310.py new file mode 100644 index 0000000000..81ccc8d4d0 --- /dev/null +++ b/docs_src/templates/tutorial001_py310.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +app = FastAPI() + +app.mount("/static", StaticFiles(directory="static"), name="static") + + +templates = Jinja2Templates(directory="templates") + + +@app.get("/items/{id}", response_class=HTMLResponse) +async def read_item(request: Request, id: str): + return templates.TemplateResponse( + request=request, name="item.html", context={"id": id} + ) diff --git a/docs_src/using_request_directly/tutorial001_py310.py b/docs_src/using_request_directly/tutorial001_py310.py new file mode 100644 index 0000000000..2d7288b54d --- /dev/null +++ b/docs_src/using_request_directly/tutorial001_py310.py @@ -0,0 +1,9 @@ +from fastapi import FastAPI, Request + +app = FastAPI() + + +@app.get("/items/{item_id}") +def read_root(item_id: str, request: Request): + client_host = request.client.host + return {"client_host": client_host, "item_id": item_id} diff --git a/docs_src/websockets/tutorial001_py310.py b/docs_src/websockets/tutorial001_py310.py new file mode 100644 index 0000000000..a43a2be17c --- /dev/null +++ b/docs_src/websockets/tutorial001_py310.py @@ -0,0 +1,51 @@ +from fastapi import FastAPI, WebSocket +from fastapi.responses import HTMLResponse + +app = FastAPI() + +html = """ + + + + Chat + + +

WebSocket Chat

+
+ + +
+
    +
+ + + +""" + + +@app.get("/") +async def get(): + return HTMLResponse(html) + + +@app.websocket("/ws") +async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + while True: + data = await websocket.receive_text() + await websocket.send_text(f"Message text was: {data}") diff --git a/docs_src/websockets/tutorial002_an_py39.py b/docs_src/websockets/tutorial002_an_py39.py deleted file mode 100644 index 606d355fe1..0000000000 --- a/docs_src/websockets/tutorial002_an_py39.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Annotated, Union - -from fastapi import ( - Cookie, - Depends, - FastAPI, - Query, - WebSocket, - WebSocketException, - status, -) -from fastapi.responses import HTMLResponse - -app = FastAPI() - -html = """ - - - - Chat - - -

WebSocket Chat

-
- - - -
- - -
-
    -
- - - -""" - - -@app.get("/") -async def get(): - return HTMLResponse(html) - - -async def get_cookie_or_token( - websocket: WebSocket, - session: Annotated[Union[str, None], Cookie()] = None, - token: Annotated[Union[str, None], Query()] = None, -): - if session is None and token is None: - raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION) - return session or token - - -@app.websocket("/items/{item_id}/ws") -async def websocket_endpoint( - *, - websocket: WebSocket, - item_id: str, - q: Union[int, None] = None, - cookie_or_token: Annotated[str, Depends(get_cookie_or_token)], -): - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text( - f"Session cookie or query token value is: {cookie_or_token}" - ) - if q is not None: - await websocket.send_text(f"Query parameter q is: {q}") - await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}") diff --git a/docs_src/websockets/tutorial002_py39.py b/docs_src/websockets/tutorial002_py39.py deleted file mode 100644 index cab749e4db..0000000000 --- a/docs_src/websockets/tutorial002_py39.py +++ /dev/null @@ -1,91 +0,0 @@ -from typing import Union - -from fastapi import ( - Cookie, - Depends, - FastAPI, - Query, - WebSocket, - WebSocketException, - status, -) -from fastapi.responses import HTMLResponse - -app = FastAPI() - -html = """ - - - - Chat - - -

WebSocket Chat

-
- - - -
- - -
-
    -
- - - -""" - - -@app.get("/") -async def get(): - return HTMLResponse(html) - - -async def get_cookie_or_token( - websocket: WebSocket, - session: Union[str, None] = Cookie(default=None), - token: Union[str, None] = Query(default=None), -): - if session is None and token is None: - raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION) - return session or token - - -@app.websocket("/items/{item_id}/ws") -async def websocket_endpoint( - websocket: WebSocket, - item_id: str, - q: Union[int, None] = None, - cookie_or_token: str = Depends(get_cookie_or_token), -): - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text( - f"Session cookie or query token value is: {cookie_or_token}" - ) - if q is not None: - await websocket.send_text(f"Query parameter q is: {q}") - await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}") diff --git a/docs_src/websockets/tutorial003_py310.py b/docs_src/websockets/tutorial003_py310.py new file mode 100644 index 0000000000..3162180889 --- /dev/null +++ b/docs_src/websockets/tutorial003_py310.py @@ -0,0 +1,81 @@ +from fastapi import FastAPI, WebSocket, WebSocketDisconnect +from fastapi.responses import HTMLResponse + +app = FastAPI() + +html = """ + + + + Chat + + +

WebSocket Chat

+

Your ID:

+
+ + +
+
    +
+ + + +""" + + +class ConnectionManager: + def __init__(self): + self.active_connections: list[WebSocket] = [] + + async def connect(self, websocket: WebSocket): + await websocket.accept() + self.active_connections.append(websocket) + + def disconnect(self, websocket: WebSocket): + self.active_connections.remove(websocket) + + async def send_personal_message(self, message: str, websocket: WebSocket): + await websocket.send_text(message) + + async def broadcast(self, message: str): + for connection in self.active_connections: + await connection.send_text(message) + + +manager = ConnectionManager() + + +@app.get("/") +async def get(): + return HTMLResponse(html) + + +@app.websocket("/ws/{client_id}") +async def websocket_endpoint(websocket: WebSocket, client_id: int): + await manager.connect(websocket) + try: + while True: + data = await websocket.receive_text() + await manager.send_personal_message(f"You wrote: {data}", websocket) + await manager.broadcast(f"Client #{client_id} says: {data}") + except WebSocketDisconnect: + manager.disconnect(websocket) + await manager.broadcast(f"Client #{client_id} left the chat") diff --git a/docs_src/wsgi/tutorial001_py310.py b/docs_src/wsgi/tutorial001_py310.py new file mode 100644 index 0000000000..8eeceb829e --- /dev/null +++ b/docs_src/wsgi/tutorial001_py310.py @@ -0,0 +1,23 @@ +from a2wsgi import WSGIMiddleware +from fastapi import FastAPI +from flask import Flask, request +from markupsafe import escape + +flask_app = Flask(__name__) + + +@flask_app.route("/") +def flask_main(): + name = request.args.get("name", "World") + return f"Hello, {escape(name)} from Flask!" + + +app = FastAPI() + + +@app.get("/v2") +def read_main(): + return {"message": "Hello World"} + + +app.mount("/v1", WSGIMiddleware(flask_app)) diff --git a/pyproject.toml b/pyproject.toml index e1ce30507a..1e6fda3b1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -285,20 +285,205 @@ omit = [ "docs_src/dependencies/tutorial014_an_py310.py", # temporary code example? # Pydantic v1 migration, no longer tested "docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py", - "docs_src/pydantic_v1_in_v2/tutorial001_an_py39.py", "docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py", - "docs_src/pydantic_v1_in_v2/tutorial002_an_py39.py", "docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py", - "docs_src/pydantic_v1_in_v2/tutorial003_an_py39.py", "docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py", - "docs_src/pydantic_v1_in_v2/tutorial004_an_py39.py", - # TODO: remove when removing this file, after updating translations, Pydantic v1 - "docs_src/schema_extra_example/tutorial001_pv1_py310.py", - "docs_src/schema_extra_example/tutorial001_pv1_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py", - "docs_src/settings/app03_py39/config_pv1.py", - "docs_src/settings/app03_an_py39/config_pv1.py", - "docs_src/settings/tutorial001_pv1_py39.py", + # TODO: remove all the ignores below when all translations use the new Python 3.10 files + "docs_src/additional_responses/tutorial001_py39.py", + "docs_src/additional_responses/tutorial003_py39.py", + "docs_src/advanced_middleware/tutorial001_py39.py", + "docs_src/advanced_middleware/tutorial002_py39.py", + "docs_src/advanced_middleware/tutorial003_py39.py", + "docs_src/app_testing/app_a_py39/main.py", + "docs_src/app_testing/app_a_py39/test_main.py", + "docs_src/app_testing/tutorial001_py39.py", + "docs_src/app_testing/tutorial002_py39.py", + "docs_src/app_testing/tutorial003_py39.py", + "docs_src/app_testing/tutorial004_py39.py", + "docs_src/async_tests/app_a_py39/main.py", + "docs_src/async_tests/app_a_py39/test_main.py", + "docs_src/authentication_error_status_code/tutorial001_an_py39.py", + "docs_src/background_tasks/tutorial001_py39.py", + "docs_src/behind_a_proxy/tutorial001_01_py39.py", + "docs_src/behind_a_proxy/tutorial001_py39.py", + "docs_src/behind_a_proxy/tutorial002_py39.py", + "docs_src/behind_a_proxy/tutorial003_py39.py", + "docs_src/behind_a_proxy/tutorial004_py39.py", + "docs_src/bigger_applications/app_an_py39/dependencies.py", + "docs_src/bigger_applications/app_an_py39/internal/admin.py", + "docs_src/bigger_applications/app_an_py39/main.py", + "docs_src/bigger_applications/app_an_py39/routers/items.py", + "docs_src/bigger_applications/app_an_py39/routers/users.py", + "docs_src/bigger_applications/app_py39/dependencies.py", + "docs_src/bigger_applications/app_py39/main.py", + "docs_src/body_nested_models/tutorial008_py39.py", + "docs_src/body_nested_models/tutorial009_py39.py", + "docs_src/conditional_openapi/tutorial001_py39.py", + "docs_src/configure_swagger_ui/tutorial001_py39.py", + "docs_src/configure_swagger_ui/tutorial002_py39.py", + "docs_src/configure_swagger_ui/tutorial003_py39.py", + "docs_src/cors/tutorial001_py39.py", + "docs_src/custom_docs_ui/tutorial001_py39.py", + "docs_src/custom_docs_ui/tutorial002_py39.py", + "docs_src/custom_response/tutorial001_py39.py", + "docs_src/custom_response/tutorial001b_py39.py", + "docs_src/custom_response/tutorial002_py39.py", + "docs_src/custom_response/tutorial003_py39.py", + "docs_src/custom_response/tutorial004_py39.py", + "docs_src/custom_response/tutorial005_py39.py", + "docs_src/custom_response/tutorial006_py39.py", + "docs_src/custom_response/tutorial006b_py39.py", + "docs_src/custom_response/tutorial006c_py39.py", + "docs_src/custom_response/tutorial007_py39.py", + "docs_src/custom_response/tutorial008_py39.py", + "docs_src/custom_response/tutorial009_py39.py", + "docs_src/custom_response/tutorial009b_py39.py", + "docs_src/custom_response/tutorial009c_py39.py", + "docs_src/custom_response/tutorial010_py39.py", + "docs_src/debugging/tutorial001_py39.py", + "docs_src/dependencies/tutorial006_an_py39.py", + "docs_src/dependencies/tutorial006_py39.py", + "docs_src/dependencies/tutorial007_py39.py", + "docs_src/dependencies/tutorial008_py39.py", + "docs_src/dependencies/tutorial008b_an_py39.py", + "docs_src/dependencies/tutorial008b_py39.py", + "docs_src/dependencies/tutorial008c_an_py39.py", + "docs_src/dependencies/tutorial008c_py39.py", + "docs_src/dependencies/tutorial008d_an_py39.py", + "docs_src/dependencies/tutorial008d_py39.py", + "docs_src/dependencies/tutorial008e_an_py39.py", + "docs_src/dependencies/tutorial008e_py39.py", + "docs_src/dependencies/tutorial010_py39.py", + "docs_src/dependencies/tutorial011_an_py39.py", + "docs_src/dependencies/tutorial011_py39.py", + "docs_src/dependencies/tutorial012_an_py39.py", + "docs_src/dependencies/tutorial012_py39.py", + "docs_src/events/tutorial001_py39.py", + "docs_src/events/tutorial002_py39.py", + "docs_src/events/tutorial003_py39.py", + "docs_src/extending_openapi/tutorial001_py39.py", + "docs_src/extra_models/tutorial004_py39.py", + "docs_src/extra_models/tutorial005_py39.py", + "docs_src/first_steps/tutorial001_py39.py", + "docs_src/first_steps/tutorial003_py39.py", + "docs_src/generate_clients/tutorial001_py39.py", + "docs_src/generate_clients/tutorial002_py39.py", + "docs_src/generate_clients/tutorial003_py39.py", + "docs_src/generate_clients/tutorial004_py39.py", + "docs_src/graphql_/tutorial001_py39.py", + "docs_src/handling_errors/tutorial001_py39.py", + "docs_src/handling_errors/tutorial002_py39.py", + "docs_src/handling_errors/tutorial003_py39.py", + "docs_src/handling_errors/tutorial004_py39.py", + "docs_src/handling_errors/tutorial005_py39.py", + "docs_src/handling_errors/tutorial006_py39.py", + "docs_src/metadata/tutorial001_1_py39.py", + "docs_src/metadata/tutorial001_py39.py", + "docs_src/metadata/tutorial002_py39.py", + "docs_src/metadata/tutorial003_py39.py", + "docs_src/metadata/tutorial004_py39.py", + "docs_src/middleware/tutorial001_py39.py", + "docs_src/openapi_webhooks/tutorial001_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial001_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial002_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial003_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial005_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial006_py39.py", + "docs_src/path_operation_advanced_configuration/tutorial007_py39.py", + "docs_src/path_operation_configuration/tutorial002b_py39.py", + "docs_src/path_operation_configuration/tutorial006_py39.py", + "docs_src/path_params/tutorial001_py39.py", + "docs_src/path_params/tutorial002_py39.py", + "docs_src/path_params/tutorial003_py39.py", + "docs_src/path_params/tutorial003b_py39.py", + "docs_src/path_params/tutorial004_py39.py", + "docs_src/path_params/tutorial005_py39.py", + "docs_src/path_params_numeric_validations/tutorial002_an_py39.py", + "docs_src/path_params_numeric_validations/tutorial002_py39.py", + "docs_src/path_params_numeric_validations/tutorial003_an_py39.py", + "docs_src/path_params_numeric_validations/tutorial003_py39.py", + "docs_src/path_params_numeric_validations/tutorial004_an_py39.py", + "docs_src/path_params_numeric_validations/tutorial004_py39.py", + "docs_src/path_params_numeric_validations/tutorial005_an_py39.py", + "docs_src/path_params_numeric_validations/tutorial005_py39.py", + "docs_src/path_params_numeric_validations/tutorial006_an_py39.py", + "docs_src/path_params_numeric_validations/tutorial006_py39.py", + "docs_src/python_types/tutorial001_py39.py", + "docs_src/python_types/tutorial002_py39.py", + "docs_src/python_types/tutorial003_py39.py", + "docs_src/python_types/tutorial004_py39.py", + "docs_src/python_types/tutorial005_py39.py", + "docs_src/python_types/tutorial006_py39.py", + "docs_src/python_types/tutorial007_py39.py", + "docs_src/python_types/tutorial008_py39.py", + "docs_src/python_types/tutorial008b_py39.py", + "docs_src/python_types/tutorial009_py39.py", + "docs_src/python_types/tutorial009b_py39.py", + "docs_src/python_types/tutorial009c_py39.py", + "docs_src/python_types/tutorial010_py39.py", + "docs_src/python_types/tutorial013_py39.py", + "docs_src/query_params/tutorial001_py39.py", + "docs_src/query_params/tutorial005_py39.py", + "docs_src/query_params_str_validations/tutorial005_an_py39.py", + "docs_src/query_params_str_validations/tutorial005_py39.py", + "docs_src/query_params_str_validations/tutorial006_an_py39.py", + "docs_src/query_params_str_validations/tutorial006_py39.py", + "docs_src/query_params_str_validations/tutorial012_an_py39.py", + "docs_src/query_params_str_validations/tutorial012_py39.py", + "docs_src/query_params_str_validations/tutorial013_an_py39.py", + "docs_src/query_params_str_validations/tutorial013_py39.py", + "docs_src/request_files/tutorial001_03_an_py39.py", + "docs_src/request_files/tutorial001_03_py39.py", + "docs_src/request_files/tutorial001_an_py39.py", + "docs_src/request_files/tutorial001_py39.py", + "docs_src/request_files/tutorial002_an_py39.py", + "docs_src/request_files/tutorial002_py39.py", + "docs_src/request_files/tutorial003_an_py39.py", + "docs_src/request_files/tutorial003_py39.py", + "docs_src/request_form_models/tutorial001_an_py39.py", + "docs_src/request_form_models/tutorial001_py39.py", + "docs_src/request_form_models/tutorial002_an_py39.py", + "docs_src/request_form_models/tutorial002_py39.py", + "docs_src/request_forms/tutorial001_an_py39.py", + "docs_src/request_forms/tutorial001_py39.py", + "docs_src/request_forms_and_files/tutorial001_an_py39.py", + "docs_src/request_forms_and_files/tutorial001_py39.py", + "docs_src/response_change_status_code/tutorial001_py39.py", + "docs_src/response_cookies/tutorial001_py39.py", + "docs_src/response_cookies/tutorial002_py39.py", + "docs_src/response_directly/tutorial002_py39.py", + "docs_src/response_headers/tutorial001_py39.py", + "docs_src/response_headers/tutorial002_py39.py", + "docs_src/response_model/tutorial003_02_py39.py", + "docs_src/response_model/tutorial003_03_py39.py", + "docs_src/response_status_code/tutorial001_py39.py", + "docs_src/response_status_code/tutorial002_py39.py", + "docs_src/security/tutorial001_an_py39.py", + "docs_src/security/tutorial001_py39.py", + "docs_src/security/tutorial006_an_py39.py", + "docs_src/security/tutorial006_py39.py", + "docs_src/security/tutorial007_an_py39.py", + "docs_src/security/tutorial007_py39.py", + "docs_src/settings/app01_py39/config.py", + "docs_src/settings/app01_py39/main.py", + "docs_src/settings/app02_an_py39/config.py", + "docs_src/settings/app02_an_py39/main.py", + "docs_src/settings/app02_an_py39/test_main.py", + "docs_src/settings/app02_py39/config.py", + "docs_src/settings/app02_py39/main.py", + "docs_src/settings/app02_py39/test_main.py", + "docs_src/settings/app03_an_py39/config.py", + "docs_src/settings/app03_an_py39/main.py", + "docs_src/settings/app03_py39/config.py", + "docs_src/settings/app03_py39/main.py", + "docs_src/settings/tutorial001_py39.py", + "docs_src/static_files/tutorial001_py39.py", + "docs_src/sub_applications/tutorial001_py39.py", + "docs_src/templates/tutorial001_py39.py", + "docs_src/using_request_directly/tutorial001_py39.py", + "docs_src/websockets/tutorial001_py39.py", + "docs_src/websockets/tutorial003_py39.py", + "docs_src/wsgi/tutorial001_py39.py", ] [tool.coverage.report] @@ -327,32 +512,42 @@ ignore = [ [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401"] +"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"] +"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"] +"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"] +"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"] +"docs_src/custom_response/tutorial007_py310.py" = ["B007"] +"docs_src/custom_response/tutorial007_py39.py" = ["B007"] +"docs_src/dataclasses/tutorial003_py39.py" = ["I001"] +"docs_src/dependencies/tutorial007_py310.py" = ["F821"] "docs_src/dependencies/tutorial007_py39.py" = ["F821"] +"docs_src/dependencies/tutorial008_an_py310.py" = ["F821"] +"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"] +"docs_src/dependencies/tutorial008_py310.py" = ["F821"] "docs_src/dependencies/tutorial008_py39.py" = ["F821"] +"docs_src/dependencies/tutorial008b_an_py310.py" = ["B904"] +"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"] +"docs_src/dependencies/tutorial008b_py310.py" = ["B904"] +"docs_src/dependencies/tutorial008b_py39.py" = ["B904"] +"docs_src/dependencies/tutorial009_py310.py" = ["F821"] "docs_src/dependencies/tutorial009_py39.py" = ["F821"] +"docs_src/dependencies/tutorial010_py310.py" = ["F821"] "docs_src/dependencies/tutorial010_py39.py" = ["F821"] -"docs_src/custom_response/tutorial007_py39.py" = ["B007"] -"docs_src/dataclasses/tutorial003_py39.py" = ["I001"] -"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"] "docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py" = ["B904"] -"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"] -"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"] -"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"] -"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"] -"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"] +"docs_src/path_operation_advanced_configuration/tutorial007_py310.py" = ["B904"] +"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"] +"docs_src/query_params_str_validations/tutorial012_an_py310.py" = ["B006"] "docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"] +"docs_src/query_params_str_validations/tutorial013_an_py310.py" = ["B006"] "docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"] -"docs_src/security/tutorial004_py39.py" = ["B904"] -"docs_src/security/tutorial004_an_py39.py" = ["B904"] "docs_src/security/tutorial004_an_py310.py" = ["B904"] +"docs_src/security/tutorial004_an_py39.py" = ["B904"] "docs_src/security/tutorial004_py310.py" = ["B904"] +"docs_src/security/tutorial004_py39.py" = ["B904"] "docs_src/security/tutorial005_an_py310.py" = ["B904"] "docs_src/security/tutorial005_an_py39.py" = ["B904"] "docs_src/security/tutorial005_py310.py" = ["B904"] "docs_src/security/tutorial005_py39.py" = ["B904"] -"docs_src/dependencies/tutorial008b_py39.py" = ["B904"] -"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"] - [tool.ruff.lint.isort] known-third-party = ["fastapi", "pydantic", "starlette"] diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial001.py b/tests/test_tutorial/test_additional_responses/test_tutorial001.py index d8d9d4130b..456070c9c3 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.additional_responses.tutorial001_py39 import app +from docs_src.additional_responses.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial002.py b/tests/test_tutorial/test_additional_responses/test_tutorial002.py index 4fae59d222..586779e44f 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial002.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial002.py @@ -12,7 +12,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial003.py b/tests/test_tutorial/test_additional_responses/test_tutorial003.py index e888819dfe..56eeacb605 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial003.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.additional_responses.tutorial003_py39 import app +from docs_src.additional_responses.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_additional_responses/test_tutorial004.py b/tests/test_tutorial/test_additional_responses/test_tutorial004.py index 9df326a5ce..fe56fbb8b5 100644 --- a/tests/test_tutorial/test_additional_responses/test_tutorial004.py +++ b/tests/test_tutorial/test_additional_responses/test_tutorial004.py @@ -12,7 +12,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py b/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py index bced1f6dfe..f57ea2bcf2 100644 --- a/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py +++ b/tests/test_tutorial/test_additional_status_codes/test_tutorial001.py @@ -9,9 +9,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), - "tutorial001_an_py39", pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py index f17391956e..6231cf4cb1 100644 --- a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py +++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.advanced_middleware.tutorial001_py39 import app +from docs_src.advanced_middleware.tutorial001_py310 import app def test_middleware(): diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py index bae915406e..fa8ac41d79 100644 --- a/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py +++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.advanced_middleware.tutorial002_py39 import app +from docs_src.advanced_middleware.tutorial002_py310 import app def test_middleware(): diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py index 66697997c8..8602e15697 100644 --- a/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py +++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.responses import PlainTextResponse from fastapi.testclient import TestClient -from docs_src.advanced_middleware.tutorial003_py39 import app +from docs_src.advanced_middleware.tutorial003_py310 import app @app.get("/large") diff --git a/tests/test_tutorial/test_async_tests/test_main_a.py b/tests/test_tutorial/test_async_tests/test_main_a.py index f29acaa9a0..4e33692d0c 100644 --- a/tests/test_tutorial/test_async_tests/test_main_a.py +++ b/tests/test_tutorial/test_async_tests/test_main_a.py @@ -1,6 +1,6 @@ import pytest -from docs_src.async_tests.app_a_py39.test_main import test_root +from docs_src.async_tests.app_a_py310.test_main import test_root @pytest.mark.anyio diff --git a/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py b/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py index 6f58116313..7e1588d676 100644 --- a/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py +++ b/tests/test_tutorial/test_authentication_error_status_code/test_tutorial001.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_an_py39", + "tutorial001_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_background_tasks/test_tutorial001.py b/tests/test_tutorial/test_background_tasks/test_tutorial001.py index c0ad27a6f5..100583f77a 100644 --- a/tests/test_tutorial/test_background_tasks/test_tutorial001.py +++ b/tests/test_tutorial/test_background_tasks/test_tutorial001.py @@ -3,7 +3,7 @@ from pathlib import Path from fastapi.testclient import TestClient -from docs_src.background_tasks.tutorial001_py39 import app +from docs_src.background_tasks.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_background_tasks/test_tutorial002.py b/tests/test_tutorial/test_background_tasks/test_tutorial002.py index 288a1c244e..f29402c833 100644 --- a/tests/test_tutorial/test_background_tasks/test_tutorial002.py +++ b/tests/test_tutorial/test_background_tasks/test_tutorial002.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial002_py39", pytest.param("tutorial002_py310", marks=needs_py310), - "tutorial002_an_py39", pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py index 31adaa56a6..38ae460fbe 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.behind_a_proxy.tutorial001_py39 import app +from docs_src.behind_a_proxy.tutorial001_py310 import app client = TestClient(app, root_path="/api/v1") diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py index da4acb28cc..190b33c50f 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial001_01.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.behind_a_proxy.tutorial001_01_py39 import app +from docs_src.behind_a_proxy.tutorial001_01_py310 import app client = TestClient( app, diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py index 56e6f2f9d2..c9356a5130 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.behind_a_proxy.tutorial002_py39 import app +from docs_src.behind_a_proxy.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py index a164bb80b5..d74da5b73e 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.behind_a_proxy.tutorial003_py39 import app +from docs_src.behind_a_proxy.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py index 01bba9fedd..f5e27c1183 100644 --- a/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py +++ b/tests/test_tutorial/test_behind_a_proxy/test_tutorial004.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.behind_a_proxy.tutorial004_py39 import app +from docs_src.behind_a_proxy.tutorial004_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_bigger_applications/test_main.py b/tests/test_tutorial/test_bigger_applications/test_main.py index 18845e4702..abe008d9e2 100644 --- a/tests/test_tutorial/test_bigger_applications/test_main.py +++ b/tests/test_tutorial/test_bigger_applications/test_main.py @@ -8,8 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "app_py39.main", - "app_an_py39.main", + "app_an_py310.main", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index c1877a72ef..bdabf8d68b 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body/test_tutorial002.py b/tests/test_tutorial/test_body/test_tutorial002.py index 94bf213e3f..f1e1236c99 100644 --- a/tests/test_tutorial/test_body/test_tutorial002.py +++ b/tests/test_tutorial/test_body/test_tutorial002.py @@ -1,5 +1,4 @@ import importlib -from typing import Union import pytest from fastapi.testclient import TestClient @@ -11,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) @@ -23,7 +21,7 @@ def get_client(request: pytest.FixtureRequest): @pytest.mark.parametrize("price", ["50.5", 50.5]) -def test_post_with_tax(client: TestClient, price: Union[str, float]): +def test_post_with_tax(client: TestClient, price: str | float): response = client.post( "/items/", json={"name": "Foo", "price": price, "description": "Some Foo", "tax": 0.3}, @@ -39,7 +37,7 @@ def test_post_with_tax(client: TestClient, price: Union[str, float]): @pytest.mark.parametrize("price", ["50.5", 50.5]) -def test_post_without_tax(client: TestClient, price: Union[str, float]): +def test_post_without_tax(client: TestClient, price: str | float): response = client.post( "/items/", json={"name": "Foo", "price": price, "description": "Some Foo"} ) diff --git a/tests/test_tutorial/test_body/test_tutorial003.py b/tests/test_tutorial/test_body/test_tutorial003.py index 832c211f66..b4767cf285 100644 --- a/tests/test_tutorial/test_body/test_tutorial003.py +++ b/tests/test_tutorial/test_body/test_tutorial003.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body/test_tutorial004.py b/tests/test_tutorial/test_body/test_tutorial004.py index 1019a168cf..f0a50a64c6 100644 --- a/tests/test_tutorial/test_body/test_tutorial004.py +++ b/tests/test_tutorial/test_body/test_tutorial004.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_fields/test_tutorial001.py b/tests/test_tutorial/test_body_fields/test_tutorial001.py index 0116dcb09c..eb94d24cda 100644 --- a/tests/test_tutorial/test_body_fields/test_tutorial001.py +++ b/tests/test_tutorial/test_body_fields/test_tutorial001.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), - "tutorial001_an_py39", pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py index 2e8ba457be..f510f1c156 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial001.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), - "tutorial001_an_py39", pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py index 0c94e9dd1e..b23402c3cb 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index c27f3d5ba8..89fabd3ba2 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial003_py39", pytest.param("tutorial003_py310", marks=needs_py310), - "tutorial003_an_py39", pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py index 2a39f3d713..c5b4b452d5 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial004.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), - pytest.param("tutorial004_an_py39"), pytest.param("tutorial004_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py index d600e0767d..b8fc98cd7e 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), - pytest.param("tutorial005_an_py39"), pytest.param("tutorial005_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py index 18bce279b9..2e2f329f79 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial001_tutorial002_tutorial003.py @@ -17,11 +17,8 @@ SET_OF_STR_SCHEMA = {"type": "array", "items": {"type": "string"}, "uniqueItems" @pytest.fixture( name="mod_name", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py index 6a70779b68..4605a757d4 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial004.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial004.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py index 2ff3d4f220..ffa02cd65f 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial005.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial005.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py index 229216fc58..4551a72b31 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial006.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial006.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), pytest.param("tutorial006_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py index 5a7763f598..5b99b41b6a 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial007.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial007.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial007_py39"), pytest.param("tutorial007_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py index 26f48f1d5f..d038805bd7 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial008.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial008.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial008_py39"), + pytest.param("tutorial008_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py index 492dcecd2b..a747e2a64c 100644 --- a/tests/test_tutorial/test_body_nested_models/test_tutorial009.py +++ b/tests/test_tutorial/test_body_nested_models/test_tutorial009.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial009_py39", + "tutorial009_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index feb07b8595..ba8d7baf33 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_body_updates/test_tutorial002.py b/tests/test_tutorial/test_body_updates/test_tutorial002.py index a34d08b52b..cf0ee7ada4 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial002.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py index 644b82ad9a..a7aa9dbe27 100644 --- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py @@ -5,11 +5,11 @@ from inline_snapshot import snapshot def get_client() -> TestClient: - from docs_src.conditional_openapi import tutorial001_py39 + from docs_src.conditional_openapi import tutorial001_py310 - importlib.reload(tutorial001_py39) + importlib.reload(tutorial001_py310) - client = TestClient(tutorial001_py39.app) + client = TestClient(tutorial001_py310.app) return client diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py index 1fa9419a76..e2f1fbf907 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.configure_swagger_ui.tutorial001_py39 import app +from docs_src.configure_swagger_ui.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py index c218cc858c..ce1cb4bace 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.configure_swagger_ui.tutorial002_py39 import app +from docs_src.configure_swagger_ui.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py index 8b73685499..6f28e77341 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.configure_swagger_ui.tutorial003_py39 import app +from docs_src.configure_swagger_ui.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py index f391c569a8..c4de7ad450 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial001.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), - "tutorial001_an_py39", pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py index 6583045dc8..37be0f1ddb 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=[needs_py310]), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=[needs_py310]), ], ) diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index 4d7adf0d60..db0765ea51 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="mod", params=[ - "tutorial001_py39", pytest.param("tutorial001_py310", marks=needs_py310), - "tutorial001_an_py39", pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_cors/test_tutorial001.py b/tests/test_tutorial/test_cors/test_tutorial001.py index 6a733693ae..428378cd44 100644 --- a/tests/test_tutorial/test_cors/test_tutorial001.py +++ b/tests/test_tutorial/test_cors/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.cors.tutorial001_py39 import app +from docs_src.cors.tutorial001_py310 import app def test_cors(): diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py index 1816e5d975..f7eb7fd97d 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py @@ -10,7 +10,7 @@ def client(): static_dir: Path = Path(os.getcwd()) / "static" print(static_dir) static_dir.mkdir(exist_ok=True) - from docs_src.custom_docs_ui.tutorial001_py39 import app + from docs_src.custom_docs_ui.tutorial001_py310 import app with TestClient(app) as client: yield client diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py index e8b7eb7aa3..28945d8387 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py @@ -10,7 +10,7 @@ def client(): static_dir: Path = Path(os.getcwd()) / "static" print(static_dir) static_dir.mkdir(exist_ok=True) - from docs_src.custom_docs_ui.tutorial002_py39 import app + from docs_src.custom_docs_ui.tutorial002_py310 import app with TestClient(app) as client: yield client diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py index b4ea537846..39d3bd4065 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py @@ -12,9 +12,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py index a9c7ae638b..746d6c9d2f 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py index 6cad7bd3f0..c11ea12590 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py @@ -9,7 +9,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index 20244bef45..a5fe4c8f4c 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), - pytest.param("tutorial010_py39"), + pytest.param("tutorial001_py310"), + pytest.param("tutorial010_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index 746801df16..32437db86b 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial001b_py39 import app +from docs_src.custom_response.tutorial001b_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py index 68e046ac5a..42fd85583c 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial002_tutorial003_tutorial004.py @@ -8,9 +8,9 @@ from inline_snapshot import Is, snapshot @pytest.fixture( name="mod_name", params=[ - pytest.param("tutorial002_py39"), - pytest.param("tutorial003_py39"), - pytest.param("tutorial004_py39"), + pytest.param("tutorial002_py310"), + pytest.param("tutorial003_py310"), + pytest.param("tutorial004_py310"), ], ) def get_mod_name(request: pytest.FixtureRequest) -> str: diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py index b4919af6c3..297e488225 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial005.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial005.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial005_py39 import app +from docs_src.custom_response.tutorial005_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py index ea2d366aa0..4365090c27 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial006_py39 import app +from docs_src.custom_response.tutorial006_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py index 133a591b16..a776188471 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial006b_py39 import app +from docs_src.custom_response.tutorial006b_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py index 5b17d815d0..f29bda2c29 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial006c_py39 import app +from docs_src.custom_response.tutorial006c_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial007.py b/tests/test_tutorial/test_custom_response/test_tutorial007.py index a62476ec14..5f2e233f8b 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial007.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial007.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.custom_response.tutorial007_py39 import app +from docs_src.custom_response.tutorial007_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_custom_response/test_tutorial008.py b/tests/test_tutorial/test_custom_response/test_tutorial008.py index d9fe61f539..1be7c1a622 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial008.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial008.py @@ -2,15 +2,15 @@ from pathlib import Path from fastapi.testclient import TestClient -from docs_src.custom_response import tutorial008_py39 -from docs_src.custom_response.tutorial008_py39 import app +from docs_src.custom_response import tutorial008_py310 +from docs_src.custom_response.tutorial008_py310 import app client = TestClient(app) def test_get(tmp_path: Path): file_path: Path = tmp_path / "large-video-file.mp4" - tutorial008_py39.some_file_path = str(file_path) + tutorial008_py310.some_file_path = str(file_path) test_content = b"Fake video bytes" file_path.write_bytes(test_content) response = client.get("/") diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009.py b/tests/test_tutorial/test_custom_response/test_tutorial009.py index cb6a514be6..a6564d5516 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial009.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial009.py @@ -2,15 +2,15 @@ from pathlib import Path from fastapi.testclient import TestClient -from docs_src.custom_response import tutorial009_py39 -from docs_src.custom_response.tutorial009_py39 import app +from docs_src.custom_response import tutorial009_py310 +from docs_src.custom_response.tutorial009_py310 import app client = TestClient(app) def test_get(tmp_path: Path): file_path: Path = tmp_path / "large-video-file.mp4" - tutorial009_py39.some_file_path = str(file_path) + tutorial009_py310.some_file_path = str(file_path) test_content = b"Fake video bytes" file_path.write_bytes(test_content) response = client.get("/") diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009b.py b/tests/test_tutorial/test_custom_response/test_tutorial009b.py index 9918bdb1ac..05ac62f3d0 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial009b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial009b.py @@ -2,15 +2,15 @@ from pathlib import Path from fastapi.testclient import TestClient -from docs_src.custom_response import tutorial009b_py39 -from docs_src.custom_response.tutorial009b_py39 import app +from docs_src.custom_response import tutorial009b_py310 +from docs_src.custom_response.tutorial009b_py310 import app client = TestClient(app) def test_get(tmp_path: Path): file_path: Path = tmp_path / "large-video-file.mp4" - tutorial009b_py39.some_file_path = str(file_path) + tutorial009b_py310.some_file_path = str(file_path) test_content = b"Fake video bytes" file_path.write_bytes(test_content) response = client.get("/") diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009c.py b/tests/test_tutorial/test_custom_response/test_tutorial009c.py index efc3a6b4a0..7a1b713079 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial009c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial009c.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.custom_response.tutorial009c_py39 import app +from docs_src.custom_response.tutorial009c_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial001.py b/tests/test_tutorial/test_dataclasses/test_tutorial001.py index a3d2cf5152..62de135dcd 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial001.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial001.py @@ -10,7 +10,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial002.py b/tests/test_tutorial/test_dataclasses/test_tutorial002.py index 210d743bb8..f6607c8e02 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial002.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial002.py @@ -10,7 +10,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index e023271bc3..5a35e5c4a8 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_debugging/test_tutorial001.py b/tests/test_tutorial/test_debugging/test_tutorial001.py index 1a0ca6cad7..fbf2bfa025 100644 --- a/tests/test_tutorial/test_debugging/test_tutorial001.py +++ b/tests/test_tutorial/test_debugging/test_tutorial001.py @@ -7,7 +7,7 @@ import pytest from fastapi.testclient import TestClient from inline_snapshot import snapshot -MOD_NAME = "docs_src.debugging.tutorial001_py39" +MOD_NAME = "docs_src.debugging.tutorial001_py310" @pytest.fixture(name="client") diff --git a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py index 74f4a8f3a2..11e732e6de 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial001_tutorial001_02.py @@ -10,11 +10,8 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), - pytest.param("tutorial001_02_an_py39"), pytest.param("tutorial001_02_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py index 6e1cea5a08..a9ddf8a521 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial002_tutorial003_tutorial004.py @@ -10,17 +10,11 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), - pytest.param("tutorial004_an_py39"), pytest.param("tutorial004_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial005.py b/tests/test_tutorial/test_dependencies/test_tutorial005.py index 31054744a1..3cd083b351 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial005.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial005.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), - pytest.param("tutorial005_an_py39"), pytest.param("tutorial005_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_dependencies/test_tutorial006.py b/tests/test_tutorial/test_dependencies/test_tutorial006.py index 8d6cfa2d65..f6e6f83685 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial006.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial006.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), - pytest.param("tutorial006_an_py39"), + pytest.param("tutorial006_py310"), + pytest.param("tutorial006_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial007.py b/tests/test_tutorial/test_dependencies/test_tutorial007.py index 3e188abcf6..c984856117 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial007.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial007.py @@ -2,7 +2,7 @@ import asyncio from contextlib import asynccontextmanager from unittest.mock import Mock, patch -from docs_src.dependencies.tutorial007_py39 import get_db +from docs_src.dependencies.tutorial007_py310 import get_db def test_get_db(): # Just for coverage @@ -14,7 +14,7 @@ def test_get_db(): # Just for coverage dbsession_moock = Mock() with patch( - "docs_src.dependencies.tutorial007_py39.DBSession", + "docs_src.dependencies.tutorial007_py310.DBSession", return_value=dbsession_moock, create=True, ): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008.py b/tests/test_tutorial/test_dependencies/test_tutorial008.py index 5a2d226bff..e23ac0ac51 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008.py @@ -12,9 +12,9 @@ from fastapi.testclient import TestClient @pytest.fixture( name="module", params=[ - "tutorial008_py39", + "tutorial008_py310", pytest.param( - "tutorial008_an_py39", + "tutorial008_an_py310", marks=pytest.mark.xfail( sys.version_info < (3, 14), reason="Fails with `NameError: name 'DepA' is not defined`", diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008b.py b/tests/test_tutorial/test_dependencies/test_tutorial008b.py index 91e00b3705..d2493d0cce 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008b.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008b.py @@ -7,8 +7,8 @@ from fastapi.testclient import TestClient @pytest.fixture( name="client", params=[ - pytest.param("tutorial008b_py39"), - pytest.param("tutorial008b_an_py39"), + pytest.param("tutorial008b_py310"), + pytest.param("tutorial008b_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c.py b/tests/test_tutorial/test_dependencies/test_tutorial008c.py index aede6f8d25..b7713c73b5 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008c.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008c.py @@ -9,8 +9,8 @@ from fastapi.testclient import TestClient @pytest.fixture( name="mod", params=[ - pytest.param("tutorial008c_py39"), - pytest.param("tutorial008c_an_py39"), + pytest.param("tutorial008c_py310"), + pytest.param("tutorial008c_an_py310"), ], ) def get_mod(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008d.py b/tests/test_tutorial/test_dependencies/test_tutorial008d.py index 5477f8b953..e831c055ec 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008d.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008d.py @@ -8,8 +8,8 @@ from fastapi.testclient import TestClient @pytest.fixture( name="mod", params=[ - pytest.param("tutorial008d_py39"), - pytest.param("tutorial008d_an_py39"), + pytest.param("tutorial008d_py310"), + pytest.param("tutorial008d_an_py310"), ], ) def get_mod(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008e.py b/tests/test_tutorial/test_dependencies/test_tutorial008e.py index c433157ea1..18eba9f775 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008e.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008e.py @@ -7,8 +7,8 @@ from fastapi.testclient import TestClient @pytest.fixture( name="client", params=[ - pytest.param("tutorial008e_py39"), - pytest.param("tutorial008e_an_py39"), + pytest.param("tutorial008e_py310"), + pytest.param("tutorial008e_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial010.py b/tests/test_tutorial/test_dependencies/test_tutorial010.py index 6d3815ada2..954d09f20d 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial010.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial010.py @@ -4,7 +4,7 @@ from unittest.mock import Mock, patch from fastapi import Depends, FastAPI from fastapi.testclient import TestClient -from docs_src.dependencies.tutorial010_py39 import get_db +from docs_src.dependencies.tutorial010_py310 import get_db def test_get_db(): @@ -19,7 +19,7 @@ def test_get_db(): dbsession_mock = Mock() with patch( - "docs_src.dependencies.tutorial010_py39.DBSession", + "docs_src.dependencies.tutorial010_py310.DBSession", return_value=dbsession_mock, create=True, ): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial011.py b/tests/test_tutorial/test_dependencies/test_tutorial011.py index 383422a7e6..16167fd2e0 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial011.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial011.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial011_py39", - pytest.param("tutorial011_an_py39"), + "tutorial011_py310", + pytest.param("tutorial011_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_dependencies/test_tutorial012.py b/tests/test_tutorial/test_dependencies/test_tutorial012.py index a156889245..e0148e0521 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial012.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial012.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial012_py39"), - pytest.param("tutorial012_an_py39"), + pytest.param("tutorial012_py310"), + pytest.param("tutorial012_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_encoder/test_tutorial001.py b/tests/test_tutorial/test_encoder/test_tutorial001.py index a3d6723336..e8c1f3c73f 100644 --- a/tests/test_tutorial/test_encoder/test_tutorial001.py +++ b/tests/test_tutorial/test_encoder/test_tutorial001.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="mod", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_events/test_tutorial001.py b/tests/test_tutorial/test_events/test_tutorial001.py index 63215c00db..e392cdcc90 100644 --- a/tests/test_tutorial/test_events/test_tutorial001.py +++ b/tests/test_tutorial/test_events/test_tutorial001.py @@ -7,7 +7,7 @@ from inline_snapshot import snapshot @pytest.fixture(name="app", scope="module") def get_app(): with pytest.warns(DeprecationWarning): - from docs_src.events.tutorial001_py39 import app + from docs_src.events.tutorial001_py310 import app yield app diff --git a/tests/test_tutorial/test_events/test_tutorial002.py b/tests/test_tutorial/test_events/test_tutorial002.py index f98d8921f7..47af7a9527 100644 --- a/tests/test_tutorial/test_events/test_tutorial002.py +++ b/tests/test_tutorial/test_events/test_tutorial002.py @@ -7,7 +7,7 @@ from inline_snapshot import snapshot @pytest.fixture(name="app", scope="module") def get_app(): with pytest.warns(DeprecationWarning): - from docs_src.events.tutorial002_py39 import app + from docs_src.events.tutorial002_py310 import app yield app diff --git a/tests/test_tutorial/test_events/test_tutorial003.py b/tests/test_tutorial/test_events/test_tutorial003.py index 4fc848e116..3da0b2ca52 100644 --- a/tests/test_tutorial/test_events/test_tutorial003.py +++ b/tests/test_tutorial/test_events/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.events.tutorial003_py39 import ( +from docs_src.events.tutorial003_py310 import ( app, fake_answer_to_everything_ml_model, ml_models, diff --git a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py index bc10c888c1..06c56565f6 100644 --- a/tests/test_tutorial/test_extending_openapi/test_tutorial001.py +++ b/tests/test_tutorial/test_extending_openapi/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.extending_openapi.tutorial001_py39 import app +from docs_src.extending_openapi.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py index 28fe68f285..2e7f0e522e 100644 --- a/tests/test_tutorial/test_extra_data_types/test_tutorial001.py +++ b/tests/test_tutorial/test_extra_data_types/test_tutorial001.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py index 4248878b5a..4fcb7ff78b 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial001_tutorial002.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index 38e8741582..2a2cf8afae 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_extra_models/test_tutorial004.py b/tests/test_tutorial/test_extra_models/test_tutorial004.py index c64371e3be..3ded20959a 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial004.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial004.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), + pytest.param("tutorial004_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_extra_models/test_tutorial005.py b/tests/test_tutorial/test_extra_models/test_tutorial005.py index 43b8bae8e5..265b768326 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial005.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial005.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), + pytest.param("tutorial005_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py b/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py index 5457ad132a..30eab21e93 100644 --- a/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_first_steps/test_tutorial001_tutorial002_tutorial003.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_py39", - "tutorial003_py39", + "tutorial001_py310", + "tutorial003_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial001.py b/tests/test_tutorial/test_generate_clients/test_tutorial001.py index 62799d259b..40ed3eeea2 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial001.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial001.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), + pytest.param("tutorial001_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial002.py b/tests/test_tutorial/test_generate_clients/test_tutorial002.py index f64f5f8666..6557b8c275 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial002.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.generate_clients.tutorial002_py39 import app +from docs_src.generate_clients.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial003.py b/tests/test_tutorial/test_generate_clients/test_tutorial003.py index 34ede61946..cded241ae1 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial003.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.generate_clients.tutorial003_py39 import app +from docs_src.generate_clients.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_generate_clients/test_tutorial004.py b/tests/test_tutorial/test_generate_clients/test_tutorial004.py index d04bfbfe87..1d71de869f 100644 --- a/tests/test_tutorial/test_generate_clients/test_tutorial004.py +++ b/tests/test_tutorial/test_generate_clients/test_tutorial004.py @@ -5,16 +5,16 @@ from unittest.mock import patch from inline_snapshot import snapshot -from docs_src.generate_clients import tutorial003_py39 +from docs_src.generate_clients import tutorial003_py310 def test_remove_tags(tmp_path: pathlib.Path): tmp_file = tmp_path / "openapi.json" - openapi_json = tutorial003_py39.app.openapi() + openapi_json = tutorial003_py310.app.openapi() tmp_file.write_text(json.dumps(openapi_json)) with patch("pathlib.Path", return_value=tmp_file): - importlib.import_module("docs_src.generate_clients.tutorial004_py39") + importlib.import_module("docs_src.generate_clients.tutorial004_py310") modified_openapi = json.loads(tmp_file.read_text()) assert modified_openapi == snapshot( diff --git a/tests/test_tutorial/test_graphql/test_tutorial001.py b/tests/test_tutorial/test_graphql/test_tutorial001.py index cc3be6a190..c933470814 100644 --- a/tests/test_tutorial/test_graphql/test_tutorial001.py +++ b/tests/test_tutorial/test_graphql/test_tutorial001.py @@ -10,7 +10,7 @@ warnings.filterwarnings( category=DeprecationWarning, ) -from docs_src.graphql_.tutorial001_py39 import app # noqa: E402 +from docs_src.graphql_.tutorial001_py310 import app # noqa: E402 @pytest.fixture(name="client") diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial001.py b/tests/test_tutorial/test_handling_errors/test_tutorial001.py index 8283cdc73e..001a02a0fd 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial001.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial001_py39 import app +from docs_src.handling_errors.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial002.py b/tests/test_tutorial/test_handling_errors/test_tutorial002.py index c437693d3d..0e7321ee7c 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial002.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial002_py39 import app +from docs_src.handling_errors.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial003.py b/tests/test_tutorial/test_handling_errors/test_tutorial003.py index 959729e53f..cc11985be1 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial003.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial003_py39 import app +from docs_src.handling_errors.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial004.py b/tests/test_tutorial/test_handling_errors/test_tutorial004.py index 16165bb3d3..5471cb0d82 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial004.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial004.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial004_py39 import app +from docs_src.handling_errors.tutorial004_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial005.py b/tests/test_tutorial/test_handling_errors/test_tutorial005.py index af924a9f76..c04b510c39 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial005.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial005.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial005_py39 import app +from docs_src.handling_errors.tutorial005_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_handling_errors/test_tutorial006.py b/tests/test_tutorial/test_handling_errors/test_tutorial006.py index 4c069d81e2..666e44f3a8 100644 --- a/tests/test_tutorial/test_handling_errors/test_tutorial006.py +++ b/tests/test_tutorial/test_handling_errors/test_tutorial006.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.handling_errors.tutorial006_py39 import app +from docs_src.handling_errors.tutorial006_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial001.py b/tests/test_tutorial/test_header_param_models/test_tutorial001.py index 2d14c698e0..8391bd1197 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial001.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py index 478ac84087..3d66dca08d 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=[needs_py310]), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=[needs_py310]), ], ) diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial003.py b/tests/test_tutorial/test_header_param_models/test_tutorial003.py index 00636c2b53..7d0da24fd5 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial003.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial003.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial001.py b/tests/test_tutorial/test_header_params/test_tutorial001.py index 2e97a83221..900d35adc5 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial001.py +++ b/tests/test_tutorial/test_header_params/test_tutorial001.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial002.py b/tests/test_tutorial/test_header_params/test_tutorial002.py index ba86c55bf6..c756eae71f 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial002.py +++ b/tests/test_tutorial/test_header_params/test_tutorial002.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py index 30e5133c01..1f71322b69 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_metadata/test_tutorial001.py b/tests/test_tutorial/test_metadata/test_tutorial001.py index ba3c09ce4c..ce0c1643a9 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.metadata.tutorial001_py39 import app +from docs_src.metadata.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_metadata/test_tutorial001_1.py b/tests/test_tutorial/test_metadata/test_tutorial001_1.py index 9339549731..ba9ba9dcbc 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial001_1.py +++ b/tests/test_tutorial/test_metadata/test_tutorial001_1.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.metadata.tutorial001_1_py39 import app +from docs_src.metadata.tutorial001_1_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_metadata/test_tutorial002.py b/tests/test_tutorial/test_metadata/test_tutorial002.py index 5a252475eb..979a6a7b84 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial002.py +++ b/tests/test_tutorial/test_metadata/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.metadata.tutorial002_py39 import app +from docs_src.metadata.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_metadata/test_tutorial003.py b/tests/test_tutorial/test_metadata/test_tutorial003.py index 778781e665..ee29780288 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial003.py +++ b/tests/test_tutorial/test_metadata/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.metadata.tutorial003_py39 import app +from docs_src.metadata.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_metadata/test_tutorial004.py b/tests/test_tutorial/test_metadata/test_tutorial004.py index 5c309a830e..ef0533d506 100644 --- a/tests/test_tutorial/test_metadata/test_tutorial004.py +++ b/tests/test_tutorial/test_metadata/test_tutorial004.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.metadata.tutorial004_py39 import app +from docs_src.metadata.tutorial004_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_middleware/test_tutorial001.py b/tests/test_tutorial/test_middleware/test_tutorial001.py index 18047f3430..1fa1e5a507 100644 --- a/tests/test_tutorial/test_middleware/test_tutorial001.py +++ b/tests/test_tutorial/test_middleware/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.middleware.tutorial001_py39 import app +from docs_src.middleware.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py index 1e937d0c90..62374ef270 100644 --- a/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py @@ -11,7 +11,6 @@ from tests.utils import needs_py310 @pytest.fixture( name="mod", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py index 0482c94bf9..696a2bed53 100644 --- a/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py +++ b/tests/test_tutorial/test_openapi_webhooks/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.openapi_webhooks.tutorial001_py39 import app +from docs_src.openapi_webhooks.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py index 3a4f648241..ecda8a3153 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_advanced_configuration.tutorial001_py39 import app +from docs_src.path_operation_advanced_configuration.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py index c26c36030b..c5067e233a 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_advanced_configuration.tutorial002_py39 import app +from docs_src.path_operation_advanced_configuration.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py index f060647b29..36fe21678f 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_advanced_configuration.tutorial003_py39 import app +from docs_src.path_operation_advanced_configuration.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index bf79345449..894cd9749b 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py index 779e54f9e7..f129ec6f4a 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial005.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_advanced_configuration.tutorial005_py39 import app +from docs_src.path_operation_advanced_configuration.tutorial005_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py index d63b5f912d..f3bf2b5bfd 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_advanced_configuration.tutorial006_py39 import app +from docs_src.path_operation_advanced_configuration.tutorial006_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index ec0c91bdad..ad06e6c05f 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial007_py39"), + pytest.param("tutorial007_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py index 500cb057c5..1b81b6f863 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial001.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py index 1cc560cb9a..675f3b1aea 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py index 98319645c2..f9a5ff7601 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial002b.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_configuration.tutorial002b_py39 import app +from docs_src.path_operation_configuration.tutorial002b_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py index c13a3c38c8..6d1afecc80 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial003_tutorial004.py @@ -25,9 +25,7 @@ DESCRIPTIONS = { @pytest.fixture( name="mod_name", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index 07152755f5..b186c0a684 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py index 5f56ab929e..27a93f563f 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py @@ -2,7 +2,7 @@ import pytest from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_operation_configuration.tutorial006_py39 import app +from docs_src.path_operation_configuration.tutorial006_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial001.py b/tests/test_tutorial/test_path_params/test_tutorial001.py index ec598832b0..75c47c8553 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params/test_tutorial001.py @@ -2,7 +2,7 @@ import pytest from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial001_py39 import app +from docs_src.path_params.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial002.py b/tests/test_tutorial/test_path_params/test_tutorial002.py index 8384ec8eff..416c705585 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial002.py +++ b/tests/test_tutorial/test_path_params/test_tutorial002.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial002_py39 import app +from docs_src.path_params.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial003.py b/tests/test_tutorial/test_path_params/test_tutorial003.py index 432ccde49d..2c07ebbc83 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial003.py +++ b/tests/test_tutorial/test_path_params/test_tutorial003.py @@ -2,7 +2,7 @@ import pytest from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial003_py39 import app +from docs_src.path_params.tutorial003_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial003b.py b/tests/test_tutorial/test_path_params/test_tutorial003b.py index 1cf39eca9a..debf985033 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial003b.py +++ b/tests/test_tutorial/test_path_params/test_tutorial003b.py @@ -3,7 +3,7 @@ import asyncio from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial003b_py39 import app, read_users2 +from docs_src.path_params.tutorial003b_py310 import app, read_users2 client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial004.py b/tests/test_tutorial/test_path_params/test_tutorial004.py index b691e821df..2f2a72e64e 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params/test_tutorial004.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial004_py39 import app +from docs_src.path_params.tutorial004_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params/test_tutorial005.py b/tests/test_tutorial/test_path_params/test_tutorial005.py index c60fee3f0c..bf54b59a91 100644 --- a/tests/test_tutorial/test_path_params/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params/test_tutorial005.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.path_params.tutorial005_py39 import app +from docs_src.path_params.tutorial005_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py index b43de70325..868b0ea786 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial001.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py index 1bb2a3ea8e..55d5b418cd 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial002_tutorial003.py @@ -8,10 +8,10 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), - pytest.param("tutorial002_an_py39"), - pytest.param("tutorial003_py39"), - pytest.param("tutorial003_an_py39"), + pytest.param("tutorial002_py310"), + pytest.param("tutorial002_an_py310"), + pytest.param("tutorial003_py310"), + pytest.param("tutorial003_an_py310"), ], ) def get_client(request: pytest.FixtureRequest) -> TestClient: diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py index 37c16d2954..7b1272fa10 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial004.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), - pytest.param("tutorial004_an_py39"), + pytest.param("tutorial004_py310"), + pytest.param("tutorial004_an_py310"), ], ) def get_client(request: pytest.FixtureRequest) -> TestClient: diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py index 0afc9dcbc9..d2c9b6077d 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial005.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), - pytest.param("tutorial005_an_py39"), + pytest.param("tutorial005_py310"), + pytest.param("tutorial005_an_py310"), ], ) def get_client(request: pytest.FixtureRequest) -> TestClient: diff --git a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py index e0a9694c12..9fb1f8b3b5 100644 --- a/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_params_numeric_validations/test_tutorial006.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), - pytest.param("tutorial006_an_py39"), + pytest.param("tutorial006_py310"), + pytest.param("tutorial006_an_py310"), ], ) def get_client(request: pytest.FixtureRequest) -> TestClient: diff --git a/tests/test_tutorial/test_python_types/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_python_types/test_tutorial001_tutorial002.py index ccb0968576..d7bf599fe5 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_python_types/test_tutorial001_tutorial002.py @@ -7,8 +7,8 @@ import pytest @pytest.mark.parametrize( "module_name", [ - "tutorial001_py39", - "tutorial002_py39", + "tutorial001_py310", + "tutorial002_py310", ], ) def test_run_module(module_name: str): diff --git a/tests/test_tutorial/test_python_types/test_tutorial003.py b/tests/test_tutorial/test_python_types/test_tutorial003.py index 34d2649171..20b1e7101d 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial003.py +++ b/tests/test_tutorial/test_python_types/test_tutorial003.py @@ -1,6 +1,6 @@ import pytest -from docs_src.python_types.tutorial003_py39 import get_name_with_age +from docs_src.python_types.tutorial003_py310 import get_name_with_age def test_get_name_with_age_pass_int(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial004.py b/tests/test_tutorial/test_python_types/test_tutorial004.py index 24af32883e..0b16c0cb45 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial004.py +++ b/tests/test_tutorial/test_python_types/test_tutorial004.py @@ -1,4 +1,4 @@ -from docs_src.python_types.tutorial004_py39 import get_name_with_age +from docs_src.python_types.tutorial004_py310 import get_name_with_age def test_get_name_with_age_pass_int(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial005.py b/tests/test_tutorial/test_python_types/test_tutorial005.py index 6d67ec4716..b5c847523d 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial005.py +++ b/tests/test_tutorial/test_python_types/test_tutorial005.py @@ -1,4 +1,4 @@ -from docs_src.python_types.tutorial005_py39 import get_items +from docs_src.python_types.tutorial005_py310 import get_items def test_get_items(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial006.py b/tests/test_tutorial/test_python_types/test_tutorial006.py index 50976926e7..fbe929a766 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial006.py +++ b/tests/test_tutorial/test_python_types/test_tutorial006.py @@ -1,6 +1,6 @@ from unittest.mock import patch -from docs_src.python_types.tutorial006_py39 import process_items +from docs_src.python_types.tutorial006_py310 import process_items def test_process_items(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial007.py b/tests/test_tutorial/test_python_types/test_tutorial007.py index c045294652..b664d2784c 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial007.py +++ b/tests/test_tutorial/test_python_types/test_tutorial007.py @@ -1,4 +1,4 @@ -from docs_src.python_types.tutorial007_py39 import process_items +from docs_src.python_types.tutorial007_py310 import process_items def test_process_items(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial008.py b/tests/test_tutorial/test_python_types/test_tutorial008.py index 33cf6cbfbc..74a4e9cace 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial008.py +++ b/tests/test_tutorial/test_python_types/test_tutorial008.py @@ -1,6 +1,6 @@ from unittest.mock import patch -from docs_src.python_types.tutorial008_py39 import process_items +from docs_src.python_types.tutorial008_py310 import process_items def test_process_items(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial008b.py b/tests/test_tutorial/test_python_types/test_tutorial008b.py index 1ef0d4ea16..60d7e51c12 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial008b.py +++ b/tests/test_tutorial/test_python_types/test_tutorial008b.py @@ -10,7 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="module", params=[ - pytest.param("tutorial008b_py39"), + pytest.param("tutorial008b_py310"), pytest.param("tutorial008b_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_python_types/test_tutorial009_tutorial009b.py b/tests/test_tutorial/test_python_types/test_tutorial009_tutorial009b.py index 34046c5c48..eec51b1bec 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial009_tutorial009b.py +++ b/tests/test_tutorial/test_python_types/test_tutorial009_tutorial009b.py @@ -10,9 +10,8 @@ from ...utils import needs_py310 @pytest.fixture( name="module", params=[ - pytest.param("tutorial009_py39"), + pytest.param("tutorial009_py310"), pytest.param("tutorial009_py310", marks=needs_py310), - pytest.param("tutorial009b_py39"), ], ) def get_module(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_python_types/test_tutorial009c.py b/tests/test_tutorial/test_python_types/test_tutorial009c.py index 7bd4049113..17c4b9e0c2 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial009c.py +++ b/tests/test_tutorial/test_python_types/test_tutorial009c.py @@ -11,7 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="module", params=[ - pytest.param("tutorial009c_py39"), + pytest.param("tutorial009c_py310"), pytest.param("tutorial009c_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_python_types/test_tutorial010.py b/tests/test_tutorial/test_python_types/test_tutorial010.py index 9e4d2e36bf..8525e6d843 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial010.py +++ b/tests/test_tutorial/test_python_types/test_tutorial010.py @@ -1,4 +1,4 @@ -from docs_src.python_types.tutorial010_py39 import Person, get_person_name +from docs_src.python_types.tutorial010_py310 import Person, get_person_name def test_get_person_name(): diff --git a/tests/test_tutorial/test_python_types/test_tutorial011.py b/tests/test_tutorial/test_python_types/test_tutorial011.py index a05751b974..3761eb9243 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial011.py +++ b/tests/test_tutorial/test_python_types/test_tutorial011.py @@ -9,7 +9,6 @@ from ...utils import needs_py310 @pytest.mark.parametrize( "module_name", [ - pytest.param("tutorial011_py39"), pytest.param("tutorial011_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_python_types/test_tutorial012.py b/tests/test_tutorial/test_python_types/test_tutorial012.py deleted file mode 100644 index e578048204..0000000000 --- a/tests/test_tutorial/test_python_types/test_tutorial012.py +++ /dev/null @@ -1,7 +0,0 @@ -from docs_src.python_types.tutorial012_py39 import User - - -def test_user(): - user = User(name="John Doe", age=30) - assert user.name == "John Doe" - assert user.age == 30 diff --git a/tests/test_tutorial/test_python_types/test_tutorial013.py b/tests/test_tutorial/test_python_types/test_tutorial013.py index 5602ef76f8..d8669b485c 100644 --- a/tests/test_tutorial/test_python_types/test_tutorial013.py +++ b/tests/test_tutorial/test_python_types/test_tutorial013.py @@ -1,4 +1,4 @@ -from docs_src.python_types.tutorial013_py39 import say_hello +from docs_src.python_types.tutorial013_py310 import say_hello def test_say_hello(): diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial001.py b/tests/test_tutorial/test_query_param_models/test_tutorial001.py index 38b767154a..75d1b97622 100644 --- a/tests/test_tutorial/test_query_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_query_param_models/test_tutorial001.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial002.py b/tests/test_tutorial/test_query_param_models/test_tutorial002.py index b173a2df45..da2b6608ab 100644 --- a/tests/test_tutorial/test_query_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_query_param_models/test_tutorial002.py @@ -10,9 +10,7 @@ from tests.utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=[needs_py310]), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=[needs_py310]), ], ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial001.py b/tests/test_tutorial/test_query_params/test_tutorial001.py index 40ada0e8e4..d687025871 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params/test_tutorial001.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), + pytest.param("tutorial001_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params/test_tutorial002.py b/tests/test_tutorial/test_query_params/test_tutorial002.py index 1da308a7e2..9be507fba7 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial003.py b/tests/test_tutorial/test_query_params/test_tutorial003.py index 9bb58ff9fe..2951f1adf9 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params/test_tutorial003.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial004.py b/tests/test_tutorial/test_query_params/test_tutorial004.py index 20aadb3acd..9786f861f1 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params/test_tutorial004.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params/test_tutorial005.py b/tests/test_tutorial/test_query_params/test_tutorial005.py index e023fe6d80..b21e97f0b3 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params/test_tutorial005.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.query_params.tutorial005_py39 import app +from docs_src.query_params.tutorial005_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_query_params/test_tutorial006.py b/tests/test_tutorial/test_query_params/test_tutorial006.py index b28e126556..a27f2bbb01 100644 --- a/tests/test_tutorial/test_query_params/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params/test_tutorial006.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), pytest.param("tutorial006_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py index ed73b7329e..1eb424e4fe 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py index 3eac1f2b36..feb59f1690 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial002.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py index 59d5160acb..4e1ef1da7f 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial003.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py index abf08c9328..9c2d442c8c 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial004.py @@ -10,19 +10,8 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), - pytest.param("tutorial004_an_py39"), pytest.param("tutorial004_an_py310", marks=needs_py310), - pytest.param( - "tutorial004_regex_an_py310", - marks=( - needs_py310, - pytest.mark.filterwarnings( - "ignore:`regex` has been deprecated, please use `pattern` instead:fastapi.exceptions.FastAPIDeprecationWarning" - ), - ), - ), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py index 7b5368abc4..61f07631b3 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial005.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), - pytest.param("tutorial005_an_py39"), + pytest.param("tutorial005_py310"), + pytest.param("tutorial005_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py index 2c1df2c08f..18ee8dbdcf 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), - pytest.param("tutorial006_an_py39"), + pytest.param("tutorial006_py310"), + pytest.param("tutorial006_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py index 3df9efa839..74c10b885d 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial006c_py39"), pytest.param("tutorial006c_py310", marks=needs_py310), - pytest.param("tutorial006c_an_py39"), pytest.param("tutorial006c_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py index 874002b173..3a23ce4a43 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial007.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial007_py39"), pytest.param("tutorial007_py310", marks=needs_py310), - pytest.param("tutorial007_an_py39"), pytest.param("tutorial007_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py index b9613a17b8..430d1bc188 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial008.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial008_py39"), pytest.param("tutorial008_py310", marks=needs_py310), - pytest.param("tutorial008_an_py39"), pytest.param("tutorial008_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py index d749d85f7a..a81e1c40e3 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial009.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial009_py39"), pytest.param("tutorial009_py310", marks=needs_py310), - pytest.param("tutorial009_an_py39"), pytest.param("tutorial009_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index efe9f1fa6b..bb8fbfceec 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial010_py39"), pytest.param("tutorial010_py310", marks=needs_py310), - pytest.param("tutorial010_an_py39"), pytest.param("tutorial010_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index c25357fdd1..8d558efec9 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial011_py39"), pytest.param("tutorial011_py310", marks=needs_py310), - pytest.param("tutorial011_an_py39"), pytest.param("tutorial011_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index c3d01e90ea..5aae7fcc69 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial012_py39"), - pytest.param("tutorial012_an_py39"), + pytest.param("tutorial012_py310"), + pytest.param("tutorial012_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 74efa46958..29d49a5b77 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial013_py39", - "tutorial013_an_py39", + "tutorial013_py310", + "tutorial013_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 6dff18b787..683e39795a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial014_py39"), pytest.param("tutorial014_py310", marks=needs_py310), - pytest.param("tutorial014_an_py39"), pytest.param("tutorial014_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py index 32a990e748..01d7c983a6 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py @@ -11,7 +11,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial015_an_py39"), pytest.param("tutorial015_an_py310", marks=[needs_py310]), ], ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index fd5c3b0559..4d3c35d65d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_py39", - "tutorial001_an_py39", + "tutorial001_py310", + "tutorial001_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index feeb5363ed..f199b992ae 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_02_py39"), pytest.param("tutorial001_02_py310", marks=needs_py310), - pytest.param("tutorial001_02_an_py39"), pytest.param("tutorial001_02_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index 5ef8df178c..ce22c1b5c4 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_03_py39", - "tutorial001_03_an_py39", + "tutorial001_03_py310", + "tutorial001_03_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index 52655fd63b..ebf76b3a07 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -9,8 +9,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="app", params=[ - "tutorial002_py39", - "tutorial002_an_py39", + "tutorial002_py310", + "tutorial002_an_py310", ], ) def get_app(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index a1425ba330..f11658d27c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -9,8 +9,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="app", params=[ - "tutorial003_py39", - "tutorial003_an_py39", + "tutorial003_py310", + "tutorial003_an_py310", ], ) def get_app(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial001.py b/tests/test_tutorial/test_request_form_models/test_tutorial001.py index 68fa074dc3..3122e97e81 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial001.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial001.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_py39", - "tutorial001_an_py39", + "tutorial001_py310", + "tutorial001_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002.py b/tests/test_tutorial/test_request_form_models/test_tutorial002.py index ed5ae109a0..e5dc6e486b 100644 --- a/tests/test_tutorial/test_request_form_models/test_tutorial002.py +++ b/tests/test_tutorial/test_request_form_models/test_tutorial002.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial002_py39", - "tutorial002_an_py39", + "tutorial002_py310", + "tutorial002_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_forms/test_tutorial001.py b/tests/test_tutorial/test_request_forms/test_tutorial001.py index d1596f137e..ff3421aac0 100644 --- a/tests/test_tutorial/test_request_forms/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms/test_tutorial001.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - "tutorial001_py39", - "tutorial001_an_py39", + "tutorial001_py310", + "tutorial001_an_py310", ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index 6e9165c425..e2462e040b 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -9,8 +9,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="app", params=[ - "tutorial001_py39", - "tutorial001_an_py39", + "tutorial001_py310", + "tutorial001_an_py310", ], ) def get_app(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py b/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py index 05d5ca619f..d046bd266f 100644 --- a/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py +++ b/tests/test_tutorial/test_response_change_status_code/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.response_change_status_code.tutorial001_py39 import app +from docs_src.response_change_status_code.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_cookies/test_tutorial001.py b/tests/test_tutorial/test_response_cookies/test_tutorial001.py index 6b931c8bda..1068983395 100644 --- a/tests/test_tutorial/test_response_cookies/test_tutorial001.py +++ b/tests/test_tutorial/test_response_cookies/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.response_cookies.tutorial001_py39 import app +from docs_src.response_cookies.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_cookies/test_tutorial002.py b/tests/test_tutorial/test_response_cookies/test_tutorial002.py index 3ee5f500c5..66812e4807 100644 --- a/tests/test_tutorial/test_response_cookies/test_tutorial002.py +++ b/tests/test_tutorial/test_response_cookies/test_tutorial002.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.response_cookies.tutorial002_py39 import app +from docs_src.response_cookies.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_directly/test_tutorial001.py b/tests/test_tutorial/test_response_directly/test_tutorial001.py index 2b034f1c98..54406684d8 100644 --- a/tests/test_tutorial/test_response_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_response_directly/test_tutorial001.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_directly/test_tutorial002.py b/tests/test_tutorial/test_response_directly/test_tutorial002.py index 047e82c148..7dcb8d2926 100644 --- a/tests/test_tutorial/test_response_directly/test_tutorial002.py +++ b/tests/test_tutorial/test_response_directly/test_tutorial002.py @@ -8,7 +8,7 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), + pytest.param("tutorial002_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_response_headers/test_tutorial001.py b/tests/test_tutorial/test_response_headers/test_tutorial001.py index 6232aad23e..ea182246f6 100644 --- a/tests/test_tutorial/test_response_headers/test_tutorial001.py +++ b/tests/test_tutorial/test_response_headers/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.response_headers.tutorial001_py39 import app +from docs_src.response_headers.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_headers/test_tutorial002.py b/tests/test_tutorial/test_response_headers/test_tutorial002.py index 2ac2226cb1..9b90459cb7 100644 --- a/tests/test_tutorial/test_response_headers/test_tutorial002.py +++ b/tests/test_tutorial/test_response_headers/test_tutorial002.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.response_headers.tutorial002_py39 import app +from docs_src.response_headers.tutorial002_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py index 914f53783c..bbdcc68202 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial001_tutorial001_01.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_01_py39"), pytest.param("tutorial001_01_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial002.py b/tests/test_tutorial/test_response_model/test_tutorial002.py index 10a4e37cd3..31b4659905 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial002.py +++ b/tests/test_tutorial/test_response_model/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index a1477b7dfd..8178c81963 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01.py b/tests/test_tutorial/test_response_model/test_tutorial003_01.py index a60a14ae8d..1a0c4f2603 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_01_py39"), pytest.param("tutorial003_01_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_02.py b/tests/test_tutorial/test_response_model/test_tutorial003_02.py index 460c882516..a28c56be92 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_02.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_02.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.response_model.tutorial003_02_py39 import app +from docs_src.response_model.tutorial003_02_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_03.py b/tests/test_tutorial/test_response_model/test_tutorial003_03.py index c83d78c4fa..65e7470222 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_03.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_03.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.response_model.tutorial003_03_py39 import app +from docs_src.response_model.tutorial003_03_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_04.py b/tests/test_tutorial/test_response_model/test_tutorial003_04.py index 145af126fd..44f2e504ea 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_04.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_04.py @@ -9,7 +9,6 @@ from ...utils import needs_py310 @pytest.mark.parametrize( "module_name", [ - pytest.param("tutorial003_04_py39"), pytest.param("tutorial003_04_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_05.py b/tests/test_tutorial/test_response_model/test_tutorial003_05.py index 187b6491fc..0f0e94fdaa 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_05.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_05.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_05_py39"), pytest.param("tutorial003_05_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py index d40bce261b..e7c0e79f21 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py index 55b2334d46..75c8fc0aca 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py index 5d6f542b5d..f80ce1b28b 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), pytest.param("tutorial006_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py index 7199ceed65..69c32f92e2 100644 --- a/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_response_status_code/test_tutorial001_tutorial002.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), - pytest.param("tutorial002_py39"), + pytest.param("tutorial001_py310"), + pytest.param("tutorial002_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py index f19346a3a4..126dfbe7d3 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py index 8313cb14f6..cac3337a24 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py index 3c45a64bcf..1ccca4da85 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial003.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py index 4b8e15fa19..cffd270665 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial004.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), - pytest.param("tutorial004_an_py39"), pytest.param("tutorial004_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py index 7f8e36df21..0bc17a00e1 100644 --- a/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py +++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial005.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), - pytest.param("tutorial005_an_py39"), pytest.param("tutorial005_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_security/test_tutorial001.py b/tests/test_tutorial/test_security/test_tutorial001.py index 5742b51bf0..c1a15ae009 100644 --- a/tests/test_tutorial/test_security/test_tutorial001.py +++ b/tests/test_tutorial/test_security/test_tutorial001.py @@ -8,8 +8,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), - pytest.param("tutorial001_an_py39"), + pytest.param("tutorial001_py310"), + pytest.param("tutorial001_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_security/test_tutorial002.py b/tests/test_tutorial/test_security/test_tutorial002.py index 1e8c6e0180..4d1202c325 100644 --- a/tests/test_tutorial/test_security/test_tutorial002.py +++ b/tests/test_tutorial/test_security/test_tutorial002.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index acd910c71f..45f4e57bba 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -10,9 +10,7 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial003_py39"), pytest.param("tutorial003_py310", marks=needs_py310), - pytest.param("tutorial003_an_py39"), pytest.param("tutorial003_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_security/test_tutorial004.py b/tests/test_tutorial/test_security/test_tutorial004.py index e842c92a13..e52a029bd4 100644 --- a/tests/test_tutorial/test_security/test_tutorial004.py +++ b/tests/test_tutorial/test_security/test_tutorial004.py @@ -12,9 +12,7 @@ from ...utils import needs_py310 @pytest.fixture( name="mod", params=[ - pytest.param("tutorial004_py39"), pytest.param("tutorial004_py310", marks=needs_py310), - pytest.param("tutorial004_an_py39"), pytest.param("tutorial004_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index 76b08860f5..c6e0e78e09 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="mod", params=[ - pytest.param("tutorial005_py39"), pytest.param("tutorial005_py310", marks=needs_py310), - pytest.param("tutorial005_an_py39"), pytest.param("tutorial005_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_security/test_tutorial006.py b/tests/test_tutorial/test_security/test_tutorial006.py index 1c96f62ae3..671946d97e 100644 --- a/tests/test_tutorial/test_security/test_tutorial006.py +++ b/tests/test_tutorial/test_security/test_tutorial006.py @@ -9,8 +9,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial006_py39"), - pytest.param("tutorial006_an_py39"), + pytest.param("tutorial006_py310"), + pytest.param("tutorial006_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_security/test_tutorial007.py b/tests/test_tutorial/test_security/test_tutorial007.py index 24667422fe..e735457536 100644 --- a/tests/test_tutorial/test_security/test_tutorial007.py +++ b/tests/test_tutorial/test_security/test_tutorial007.py @@ -9,8 +9,8 @@ from inline_snapshot import snapshot @pytest.fixture( name="client", params=[ - pytest.param("tutorial007_py39"), - pytest.param("tutorial007_an_py39"), + pytest.param("tutorial007_py310"), + pytest.param("tutorial007_an_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py index 0be3b59f99..653b20c7d2 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py index 87c63f69e0..0ef706a4d1 100644 --- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py +++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py @@ -10,7 +10,6 @@ from ...utils import needs_py310 @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_settings/test_app01.py b/tests/test_tutorial/test_settings/test_app01.py index 52b9b1e629..da27308e80 100644 --- a/tests/test_tutorial/test_settings/test_app01.py +++ b/tests/test_tutorial/test_settings/test_app01.py @@ -12,7 +12,7 @@ from pytest import MonkeyPatch @pytest.fixture( name="mod_name", params=[ - pytest.param("app01_py39"), + pytest.param("app01_py310"), ], ) def get_mod_name(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_settings/test_app02.py b/tests/test_tutorial/test_settings/test_app02.py index 9cbed4fd1b..20594ebb74 100644 --- a/tests/test_tutorial/test_settings/test_app02.py +++ b/tests/test_tutorial/test_settings/test_app02.py @@ -8,8 +8,8 @@ from pytest import MonkeyPatch @pytest.fixture( name="mod_path", params=[ - pytest.param("app02_py39"), - pytest.param("app02_an_py39"), + pytest.param("app02_py310"), + pytest.param("app02_an_py310"), ], ) def get_mod_path(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_settings/test_app03.py b/tests/test_tutorial/test_settings/test_app03.py index 72de497967..f4539c96d7 100644 --- a/tests/test_tutorial/test_settings/test_app03.py +++ b/tests/test_tutorial/test_settings/test_app03.py @@ -9,8 +9,8 @@ from pytest import MonkeyPatch @pytest.fixture( name="mod_path", params=[ - pytest.param("app03_py39"), - pytest.param("app03_an_py39"), + pytest.param("app03_py310"), + pytest.param("app03_an_py310"), ], ) def get_mod_path(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_settings/test_tutorial001.py b/tests/test_tutorial/test_settings/test_tutorial001.py index f4576a0d21..8857c35df3 100644 --- a/tests/test_tutorial/test_settings/test_tutorial001.py +++ b/tests/test_tutorial/test_settings/test_tutorial001.py @@ -5,7 +5,7 @@ from fastapi.testclient import TestClient from pytest import MonkeyPatch -@pytest.fixture(name="app", params=[pytest.param("tutorial001_py39")]) +@pytest.fixture(name="app", params=[pytest.param("tutorial001_py310")]) def get_app(request: pytest.FixtureRequest, monkeypatch: MonkeyPatch): monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com") mod = importlib.import_module(f"docs_src.settings.{request.param}") diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial001.py b/tests/test_tutorial/test_sql_databases/test_tutorial001.py index aec20e42e1..3407ec7588 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial001.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial001.py @@ -22,9 +22,7 @@ def clear_sqlmodel(): @pytest.fixture( name="client", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial002.py b/tests/test_tutorial/test_sql_databases/test_tutorial002.py index 4ea7d5f647..51a36b6c79 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial002.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial002.py @@ -22,9 +22,7 @@ def clear_sqlmodel(): @pytest.fixture( name="client", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_static_files/test_tutorial001.py b/tests/test_tutorial/test_static_files/test_tutorial001.py index dd93fee790..1d57310f30 100644 --- a/tests/test_tutorial/test_static_files/test_tutorial001.py +++ b/tests/test_tutorial/test_static_files/test_tutorial001.py @@ -12,7 +12,7 @@ def client(): static_dir.mkdir(exist_ok=True) sample_file = static_dir / "sample.txt" sample_file.write_text("This is a sample static file.") - from docs_src.static_files.tutorial001_py39 import app + from docs_src.static_files.tutorial001_py310 import app with TestClient(app) as client: yield client diff --git a/tests/test_tutorial/test_sub_applications/test_tutorial001.py b/tests/test_tutorial/test_sub_applications/test_tutorial001.py index a8fb3dc36f..63fb68fb27 100644 --- a/tests/test_tutorial/test_sub_applications/test_tutorial001.py +++ b/tests/test_tutorial/test_sub_applications/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.sub_applications.tutorial001_py39 import app +from docs_src.sub_applications.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_templates/test_tutorial001.py b/tests/test_tutorial/test_templates/test_tutorial001.py index 818508037d..04bc3fce86 100644 --- a/tests/test_tutorial/test_templates/test_tutorial001.py +++ b/tests/test_tutorial/test_templates/test_tutorial001.py @@ -11,7 +11,7 @@ def test_main(): shutil.rmtree("./templates") shutil.copytree("./docs_src/templates/templates/", "./templates") shutil.copytree("./docs_src/templates/static/", "./static") - from docs_src.templates.tutorial001_py39 import app + from docs_src.templates.tutorial001_py310 import app client = TestClient(app) response = client.get("/items/foo") diff --git a/tests/test_tutorial/test_testing/test_main_a.py b/tests/test_tutorial/test_testing/test_main_a.py index 5284888053..d071d53095 100644 --- a/tests/test_tutorial/test_testing/test_main_a.py +++ b/tests/test_tutorial/test_testing/test_main_a.py @@ -1,6 +1,6 @@ from inline_snapshot import snapshot -from docs_src.app_testing.app_a_py39.test_main import client, test_read_main +from docs_src.app_testing.app_a_py310.test_main import client, test_read_main def test_main(): diff --git a/tests/test_tutorial/test_testing/test_main_b.py b/tests/test_tutorial/test_testing/test_main_b.py index 3d679cd5a6..2d042fd690 100644 --- a/tests/test_tutorial/test_testing/test_main_b.py +++ b/tests/test_tutorial/test_testing/test_main_b.py @@ -9,9 +9,7 @@ from ...utils import needs_py310 @pytest.fixture( name="test_module", params=[ - "app_b_py39.test_main", pytest.param("app_b_py310.test_main", marks=needs_py310), - "app_b_an_py39.test_main", pytest.param("app_b_an_py310.test_main", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_testing/test_tutorial001.py b/tests/test_tutorial/test_testing/test_tutorial001.py index 2b501d36a7..b9bb182b77 100644 --- a/tests/test_tutorial/test_testing/test_tutorial001.py +++ b/tests/test_tutorial/test_testing/test_tutorial001.py @@ -1,6 +1,6 @@ from inline_snapshot import snapshot -from docs_src.app_testing.tutorial001_py39 import client, test_read_main +from docs_src.app_testing.tutorial001_py310 import client, test_read_main def test_main(): diff --git a/tests/test_tutorial/test_testing/test_tutorial002.py b/tests/test_tutorial/test_testing/test_tutorial002.py index cc9b5ba27c..840248dc30 100644 --- a/tests/test_tutorial/test_testing/test_tutorial002.py +++ b/tests/test_tutorial/test_testing/test_tutorial002.py @@ -1,4 +1,4 @@ -from docs_src.app_testing.tutorial002_py39 import test_read_main, test_websocket +from docs_src.app_testing.tutorial002_py310 import test_read_main, test_websocket def test_main(): diff --git a/tests/test_tutorial/test_testing/test_tutorial003.py b/tests/test_tutorial/test_testing/test_tutorial003.py index 4faa820e98..196fc45559 100644 --- a/tests/test_tutorial/test_testing/test_tutorial003.py +++ b/tests/test_tutorial/test_testing/test_tutorial003.py @@ -3,5 +3,5 @@ import pytest def test_main(): with pytest.warns(DeprecationWarning): - from docs_src.app_testing.tutorial003_py39 import test_read_items + from docs_src.app_testing.tutorial003_py310 import test_read_items test_read_items() diff --git a/tests/test_tutorial/test_testing/test_tutorial004.py b/tests/test_tutorial/test_testing/test_tutorial004.py index c95214ffe3..d5de1bb603 100644 --- a/tests/test_tutorial/test_testing/test_tutorial004.py +++ b/tests/test_tutorial/test_testing/test_tutorial004.py @@ -1,4 +1,4 @@ -from docs_src.app_testing.tutorial004_py39 import test_read_items +from docs_src.app_testing.tutorial004_py310 import test_read_items def test_main(): diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py index 6e9656bf55..81491276eb 100644 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py +++ b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py @@ -9,9 +9,7 @@ from ...utils import needs_py310 @pytest.fixture( name="test_module", params=[ - pytest.param("tutorial001_py39"), pytest.param("tutorial001_py310", marks=needs_py310), - pytest.param("tutorial001_an_py39"), pytest.param("tutorial001_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py index cb8ae8b050..4145177e4a 100644 --- a/tests/test_tutorial/test_using_request_directly/test_tutorial001.py +++ b/tests/test_tutorial/test_using_request_directly/test_tutorial001.py @@ -1,7 +1,7 @@ from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.using_request_directly.tutorial001_py39 import app +from docs_src.using_request_directly.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_websockets/test_tutorial001.py b/tests/test_tutorial/test_websockets/test_tutorial001.py index 4f8368db28..6f3bf1429a 100644 --- a/tests/test_tutorial/test_websockets/test_tutorial001.py +++ b/tests/test_tutorial/test_websockets/test_tutorial001.py @@ -2,7 +2,7 @@ import pytest from fastapi.testclient import TestClient from fastapi.websockets import WebSocketDisconnect -from docs_src.websockets.tutorial001_py39 import app +from docs_src.websockets.tutorial001_py310 import app client = TestClient(app) diff --git a/tests/test_tutorial/test_websockets/test_tutorial002.py b/tests/test_tutorial/test_websockets/test_tutorial002.py index ebf1fc8e81..0509b0d0d6 100644 --- a/tests/test_tutorial/test_websockets/test_tutorial002.py +++ b/tests/test_tutorial/test_websockets/test_tutorial002.py @@ -11,9 +11,7 @@ from ...utils import needs_py310 @pytest.fixture( name="app", params=[ - pytest.param("tutorial002_py39"), pytest.param("tutorial002_py310", marks=needs_py310), - pytest.param("tutorial002_an_py39"), pytest.param("tutorial002_an_py310", marks=needs_py310), ], ) diff --git a/tests/test_tutorial/test_websockets/test_tutorial003.py b/tests/test_tutorial/test_websockets/test_tutorial003.py index 0be1fc81d6..781146371d 100644 --- a/tests/test_tutorial/test_websockets/test_tutorial003.py +++ b/tests/test_tutorial/test_websockets/test_tutorial003.py @@ -8,7 +8,7 @@ from fastapi.testclient import TestClient @pytest.fixture( name="mod", params=[ - pytest.param("tutorial003_py39"), + pytest.param("tutorial003_py310"), ], ) def get_mod(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_wsgi/test_tutorial001.py b/tests/test_tutorial/test_wsgi/test_tutorial001.py index 9fe8c2a4b8..9bcd56dfc2 100644 --- a/tests/test_tutorial/test_wsgi/test_tutorial001.py +++ b/tests/test_tutorial/test_wsgi/test_tutorial001.py @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from docs_src.wsgi.tutorial001_py39 import app +from docs_src.wsgi.tutorial001_py310 import app client = TestClient(app) From 0e460654af7101866b7d0f22735ef6337fe13d0c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 12 Feb 2026 13:20:10 +0000 Subject: [PATCH 209/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7640bd6fa7..52cc3836aa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,10 @@ hide: * ๐ŸŽจ Update internal types for Python 3.10. PR [#14898](https://github.com/fastapi/fastapi/pull/14898) by [@tiangolo](https://github.com/tiangolo). +### Docs + +* ๐Ÿ“ Update source examples and docs from Python 3.9 to 3.10. PR [#14900](https://github.com/fastapi/fastapi/pull/14900) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.8 ### Docs From c82a3d8a13af58e092ba95ffb4b8a64b9ca82726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 12 Feb 2026 05:24:28 -0800 Subject: [PATCH 210/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20highlights=20in?= =?UTF-8?q?=20webhooks=20docs=20(#14905)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/openapi-webhooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md index f4f586f84c..d9b73ea4a2 100644 --- a/docs/en/docs/advanced/openapi-webhooks.md +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**. From 109cc8aff126b60971ec27d68d32b8713f0ec72a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 12 Feb 2026 13:24:54 +0000 Subject: [PATCH 211/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 52cc3836aa..e3804c6e37 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Docs +* ๐Ÿ“ Update highlights in webhooks docs. PR [#14905](https://github.com/fastapi/fastapi/pull/14905) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update source examples and docs from Python 3.9 to 3.10. PR [#14900](https://github.com/fastapi/fastapi/pull/14900) by [@tiangolo](https://github.com/tiangolo). ## 0.128.8 From 31d9750aceaff347bd55be37880b7f36bc26c1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 12 Feb 2026 05:31:33 -0800 Subject: [PATCH 212/367] =?UTF-8?q?=F0=9F=94=A8=20Update=20docs.py=20scrip?= =?UTF-8?q?ts=20to=20migrate=20Python=203.9=20to=20Python=203.10=20(#14906?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/docs.py | 211 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 206 insertions(+), 5 deletions(-) diff --git a/scripts/docs.py b/scripts/docs.py index 3cf62f084c..23d74aaf4a 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -8,7 +8,7 @@ from html.parser import HTMLParser from http.server import HTTPServer, SimpleHTTPRequestHandler from multiprocessing import Pool from pathlib import Path -from typing import Any, Optional, Union +from typing import Any import mkdocs.utils import typer @@ -103,7 +103,7 @@ def get_lang_paths() -> list[Path]: return sorted(docs_path.iterdir()) -def lang_callback(lang: Optional[str]) -> Union[str, None]: +def lang_callback(lang: str | None) -> str | None: if lang is None: return None lang = lang.lower() @@ -412,6 +412,13 @@ def langs_json(): @app.command() def generate_docs_src_versions_for_file(file_path: Path) -> None: target_versions = ["py39", "py310"] + full_path_str = str(file_path) + for target_version in target_versions: + if f"_{target_version}" in full_path_str: + logging.info( + f"Skipping {file_path}, already a version file for {target_version}" + ) + return base_content = file_path.read_text(encoding="utf-8") previous_content = {base_content} for target_version in target_versions: @@ -438,13 +445,207 @@ def generate_docs_src_versions_for_file(file_path: Path) -> None: if content_format in previous_content: continue previous_content.add(content_format) - version_file = file_path.with_name( - file_path.name.replace(".py", f"_{target_version}.py") - ) + # Determine where the version label should go: in the parent directory + # name or in the file name, matching the source structure. + label_in_parent = False + for v in target_versions: + if f"_{v}" in file_path.parent.name: + label_in_parent = True + break + if label_in_parent: + parent_name = file_path.parent.name + for v in target_versions: + parent_name = parent_name.replace(f"_{v}", "") + new_parent = file_path.parent.parent / f"{parent_name}_{target_version}" + new_parent.mkdir(parents=True, exist_ok=True) + version_file = new_parent / file_path.name + else: + base_name = file_path.stem + for v in target_versions: + if base_name.endswith(f"_{v}"): + base_name = base_name[: -len(f"_{v}")] + break + version_file = file_path.with_name(f"{base_name}_{target_version}.py") logging.info(f"Writing to {version_file}") version_file.write_text(content_format, encoding="utf-8") +@app.command() +def generate_docs_src_versions() -> None: + """ + Generate Python version-specific files for all .py files in docs_src. + """ + docs_src_path = Path("docs_src") + for py_file in sorted(docs_src_path.rglob("*.py")): + generate_docs_src_versions_for_file(py_file) + + +@app.command() +def copy_py39_to_py310() -> None: + """ + For each docs_src file/directory with a _py39 label that has no _py310 + counterpart, copy it with the _py310 label. + """ + docs_src_path = Path("docs_src") + # Handle directory-level labels (e.g. app_b_an_py39/) + for dir_path in sorted(docs_src_path.rglob("*_py39")): + if not dir_path.is_dir(): + continue + py310_dir = dir_path.parent / dir_path.name.replace("_py39", "_py310") + if py310_dir.exists(): + continue + logging.info(f"Copying directory {dir_path} -> {py310_dir}") + shutil.copytree(dir_path, py310_dir) + # Handle file-level labels (e.g. tutorial001_py39.py) + for file_path in sorted(docs_src_path.rglob("*_py39.py")): + if not file_path.is_file(): + continue + # Skip files inside _py39 directories (already handled above) + if "_py39" in file_path.parent.name: + continue + py310_file = file_path.with_name( + file_path.name.replace("_py39.py", "_py310.py") + ) + if py310_file.exists(): + continue + logging.info(f"Copying file {file_path} -> {py310_file}") + shutil.copy2(file_path, py310_file) + + +@app.command() +def update_docs_includes_py39_to_py310() -> None: + """ + Update .md files in docs/en/ to replace _py39 includes with _py310 versions. + + For each include line referencing a _py39 file or directory in docs_src, replace + the _py39 label with _py310. + """ + include_pattern = re.compile(r"\{[^}]*docs_src/[^}]*_py39[^}]*\.py[^}]*\}") + count = 0 + for md_file in sorted(en_docs_path.rglob("*.md")): + content = md_file.read_text(encoding="utf-8") + if "_py39" not in content: + continue + new_content = include_pattern.sub( + lambda m: m.group(0).replace("_py39", "_py310"), content + ) + if new_content != content: + md_file.write_text(new_content, encoding="utf-8") + count += 1 + logging.info(f"Updated includes in {md_file}") + print(f"Updated {count} file(s) โœ…") + + +@app.command() +def remove_unused_docs_src() -> None: + """ + Delete .py files in docs_src that are not included in any .md file under docs/. + """ + docs_src_path = Path("docs_src") + # Collect all docs .md content referencing docs_src + all_docs_content = "" + for md_file in docs_path.rglob("*.md"): + all_docs_content += md_file.read_text(encoding="utf-8") + # Build a set of directory-based package roots (e.g. docs_src/bigger_applications/app_py39) + # where at least one file is referenced in docs. All files in these directories + # should be kept since they may be internally imported by the referenced files. + used_package_dirs: set[Path] = set() + for py_file in docs_src_path.rglob("*.py"): + if py_file.name == "__init__.py": + continue + rel_path = str(py_file) + if rel_path in all_docs_content: + # Walk up from the file's parent to find the package root + # (a subdirectory under docs_src//) + parts = py_file.relative_to(docs_src_path).parts + if len(parts) > 2: + # File is inside a sub-package like docs_src/topic/app_xxx/... + package_root = docs_src_path / parts[0] / parts[1] + used_package_dirs.add(package_root) + removed = 0 + for py_file in sorted(docs_src_path.rglob("*.py")): + if py_file.name == "__init__.py": + continue + # Build the relative path as it appears in includes (e.g. docs_src/first_steps/tutorial001.py) + rel_path = str(py_file) + if rel_path in all_docs_content: + continue + # If this file is inside a directory-based package where any sibling is + # referenced, keep it (it's likely imported internally). + parts = py_file.relative_to(docs_src_path).parts + if len(parts) > 2: + package_root = docs_src_path / parts[0] / parts[1] + if package_root in used_package_dirs: + continue + # Check if the _an counterpart (or non-_an counterpart) is referenced. + # If either variant is included, keep both. + # Handle both file-level _an (tutorial001_an.py) and directory-level _an + # (app_an/main.py) + counterpart_found = False + full_path_str = str(py_file) + if "_an" in py_file.stem: + # This is an _an file, check if the non-_an version is referenced + counterpart = full_path_str.replace( + f"/{py_file.stem}", f"/{py_file.stem.replace('_an', '', 1)}" + ) + if counterpart in all_docs_content: + counterpart_found = True + else: + # This is a non-_an file, check if there's an _an version referenced + # Insert _an before any version suffix or at the end of the stem + stem = py_file.stem + for suffix in ("_py39", "_py310"): + if suffix in stem: + an_stem = stem.replace(suffix, f"_an{suffix}", 1) + break + else: + an_stem = f"{stem}_an" + counterpart = full_path_str.replace(f"/{stem}.", f"/{an_stem}.") + if counterpart in all_docs_content: + counterpart_found = True + # Also check directory-level _an counterparts + if not counterpart_found: + parent_name = py_file.parent.name + if "_an" in parent_name: + counterpart_parent = parent_name.replace("_an", "", 1) + counterpart_dir = str(py_file).replace( + f"/{parent_name}/", f"/{counterpart_parent}/" + ) + if counterpart_dir in all_docs_content: + counterpart_found = True + else: + # Try inserting _an into parent directory name + for suffix in ("_py39", "_py310"): + if suffix in parent_name: + an_parent = parent_name.replace(suffix, f"_an{suffix}", 1) + break + else: + an_parent = f"{parent_name}_an" + counterpart_dir = str(py_file).replace( + f"/{parent_name}/", f"/{an_parent}/" + ) + if counterpart_dir in all_docs_content: + counterpart_found = True + if counterpart_found: + continue + logging.info(f"Removing unused file: {py_file}") + py_file.unlink() + removed += 1 + # Clean up directories that are empty or only contain __init__.py / __pycache__ + for dir_path in sorted(docs_src_path.rglob("*"), reverse=True): + if not dir_path.is_dir(): + continue + remaining = [ + f + for f in dir_path.iterdir() + if f.name != "__pycache__" and f.name != "__init__.py" + ] + if not remaining: + logging.info(f"Removing empty/init-only directory: {dir_path}") + shutil.rmtree(dir_path) + print(f"Removed {removed} unused file(s) โœ…") + + @app.command() def add_permalinks_page(path: Path, update_existing: bool = False): """ From b7ce02ae86ee466380d2db09be008cfe83a1ca35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 12 Feb 2026 13:32:02 +0000 Subject: [PATCH 213/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e3804c6e37..a428a4d860 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,10 @@ hide: * ๐Ÿ“ Update highlights in webhooks docs. PR [#14905](https://github.com/fastapi/fastapi/pull/14905) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update source examples and docs from Python 3.9 to 3.10. PR [#14900](https://github.com/fastapi/fastapi/pull/14900) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* ๐Ÿ”จ Update docs.py scripts to migrate Python 3.9 to Python 3.10. PR [#14906](https://github.com/fastapi/fastapi/pull/14906) by [@tiangolo](https://github.com/tiangolo). + ## 0.128.8 ### Docs From a2e51363c721ee6fccb148bff95ca328b4efdfed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 12 Feb 2026 14:52:27 +0100 Subject: [PATCH 214/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?9.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a428a4d860..e85ed4b3ee 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.129.0 + ### Breaking Changes * โž– Drop support for Python 3.9. PR [#14897](https://github.com/fastapi/fastapi/pull/14897) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 9931216ee1..de5a0be382 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.128.8" +__version__ = "0.129.0" from starlette import status as status From d11f820ac38bdea38e50c9ede001a6c9b57eac6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 12 Feb 2026 10:10:35 -0800 Subject: [PATCH 215/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20for=20JW?= =?UTF-8?q?T=20to=20prevent=20timing=20attacks=20(#14908)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/security/oauth2-jwt.md | 12 ++++++++---- docs_src/security/tutorial004_an_py310.py | 3 +++ docs_src/security/tutorial004_py310.py | 3 +++ docs_src/security/tutorial005_an_py310.py | 3 +++ docs_src/security/tutorial005_py310.py | 3 +++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md index 95baf871c1..26894ab287 100644 --- a/docs/en/docs/tutorial/security/oauth2-jwt.md +++ b/docs/en/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ And another utility to verify if a received password matches the hash stored. And another one to authenticate and return a user. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +When `authenticate_user` is called with a username that doesn't exist in the database, we still run `verify_password` against a dummy hash. + +This ensures the endpoint takes roughly the same amount of time to respond whether the username is valid or not, preventing **timing attacks** that could be used to enumerate existing usernames. /// note @@ -152,7 +156,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response Create a utility function to generate a new access token. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## Update the dependencies { #update-the-dependencies } @@ -162,7 +166,7 @@ Decode the received token, verify it, and return the current user. If the token is invalid, return an HTTP error right away. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## Update the `/token` *path operation* { #update-the-token-path-operation } @@ -170,7 +174,7 @@ Create a `timedelta` with the expiration time of the token. Create a real JWT access token and return it. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### Technical details about the JWT "subject" `sub` { #technical-details-about-the-jwt-subject-sub } diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py index 368c743bf9..685cb034ee 100644 --- a/docs_src/security/tutorial004_an_py310.py +++ b/docs_src/security/tutorial004_an_py310.py @@ -48,6 +48,8 @@ class UserInDB(User): password_hash = PasswordHash.recommended() +DUMMY_HASH = password_hash.hash("dummypassword") + oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") app = FastAPI() @@ -70,6 +72,7 @@ def get_user(db, username: str): def authenticate_user(fake_db, username: str, password: str): user = get_user(fake_db, username) if not user: + verify_password(password, DUMMY_HASH) return False if not verify_password(password, user.hashed_password): return False diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py index 8d0785b404..dc7f1c9e29 100644 --- a/docs_src/security/tutorial004_py310.py +++ b/docs_src/security/tutorial004_py310.py @@ -47,6 +47,8 @@ class UserInDB(User): password_hash = PasswordHash.recommended() +DUMMY_HASH = password_hash.hash("dummypassword") + oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") app = FastAPI() @@ -69,6 +71,7 @@ def get_user(db, username: str): def authenticate_user(fake_db, username: str, password: str): user = get_user(fake_db, username) if not user: + verify_password(password, DUMMY_HASH) return False if not verify_password(password, user.hashed_password): return False diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py index fef0ab71ca..9911723db7 100644 --- a/docs_src/security/tutorial005_an_py310.py +++ b/docs_src/security/tutorial005_an_py310.py @@ -60,6 +60,8 @@ class UserInDB(User): password_hash = PasswordHash.recommended() +DUMMY_HASH = password_hash.hash("dummypassword") + oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", scopes={"me": "Read information about the current user.", "items": "Read items."}, @@ -85,6 +87,7 @@ def get_user(db, username: str): def authenticate_user(fake_db, username: str, password: str): user = get_user(fake_db, username) if not user: + verify_password(password, DUMMY_HASH) return False if not verify_password(password, user.hashed_password): return False diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py index 412fbf7984..710cdac329 100644 --- a/docs_src/security/tutorial005_py310.py +++ b/docs_src/security/tutorial005_py310.py @@ -59,6 +59,8 @@ class UserInDB(User): password_hash = PasswordHash.recommended() +DUMMY_HASH = password_hash.hash("dummypassword") + oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", scopes={"me": "Read information about the current user.", "items": "Read items."}, @@ -84,6 +86,7 @@ def get_user(db, username: str): def authenticate_user(fake_db, username: str, password: str): user = get_user(fake_db, username) if not user: + verify_password(password, DUMMY_HASH) return False if not verify_password(password, user.hashed_password): return False From c206f19b5d39fe9fbf90b67229290b41f8fabeec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 12 Feb 2026 18:10:57 +0000 Subject: [PATCH 216/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e85ed4b3ee..d8bc3a26f6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* ๐Ÿ“ Update docs for JWT to prevent timing attacks. PR [#14908](https://github.com/fastapi/fastapi/pull/14908) by [@tiangolo](https://github.com/tiangolo). + ## 0.129.0 ### Breaking Changes From 55a9eee13a7c228b358bd110976b3aeab3185fe2 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:57:34 +0100 Subject: [PATCH 217/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#14909)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * Reflect latest changes in `docs/en/docs/tutorial/security/oauth2-jwt.md` --- docs/ru/docs/advanced/additional-responses.md | 4 +- .../ru/docs/advanced/advanced-dependencies.md | 8 +- .../ru/docs/advanced/advanced-python-types.md | 61 ++++++ docs/ru/docs/advanced/async-tests.md | 10 +- docs/ru/docs/advanced/behind-a-proxy.md | 22 +- docs/ru/docs/advanced/custom-response.md | 36 ++-- docs/ru/docs/advanced/dataclasses.md | 2 +- docs/ru/docs/advanced/events.md | 12 +- docs/ru/docs/advanced/generate-clients.md | 12 +- docs/ru/docs/advanced/middleware.md | 6 +- docs/ru/docs/advanced/openapi-webhooks.md | 6 +- .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 2 +- docs/ru/docs/advanced/response-cookies.md | 4 +- docs/ru/docs/advanced/response-directly.md | 2 +- docs/ru/docs/advanced/response-headers.md | 4 +- .../docs/advanced/security/http-basic-auth.md | 6 +- docs/ru/docs/advanced/settings.md | 20 +- docs/ru/docs/advanced/sub-applications.md | 6 +- docs/ru/docs/advanced/templates.md | 2 +- docs/ru/docs/advanced/testing-events.md | 4 +- docs/ru/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/ru/docs/advanced/websockets.md | 8 +- docs/ru/docs/advanced/wsgi.md | 2 +- docs/ru/docs/alternatives.md | 12 +- docs/ru/docs/async.md | 12 +- docs/ru/docs/benchmarks.md | 10 +- docs/ru/docs/deployment/concepts.md | 10 +- docs/ru/docs/deployment/docker.md | 20 +- docs/ru/docs/deployment/https.md | 2 +- docs/ru/docs/deployment/index.md | 2 +- docs/ru/docs/deployment/versions.md | 4 +- docs/ru/docs/environment-variables.md | 2 +- docs/ru/docs/fastapi-cli.md | 2 +- docs/ru/docs/features.md | 24 +-- docs/ru/docs/history-design-future.md | 8 +- .../authentication-error-status-code.md | 2 +- docs/ru/docs/how-to/conditional-openapi.md | 6 +- docs/ru/docs/how-to/configure-swagger-ui.md | 6 +- docs/ru/docs/how-to/custom-docs-ui-assets.md | 14 +- docs/ru/docs/how-to/extending-openapi.md | 12 +- docs/ru/docs/how-to/graphql.md | 2 +- docs/ru/docs/how-to/index.md | 6 +- docs/ru/docs/index.md | 12 +- docs/ru/docs/project-generation.md | 2 +- docs/ru/docs/python-types.md | 190 ++++-------------- docs/ru/docs/tutorial/background-tasks.md | 10 +- docs/ru/docs/tutorial/bigger-applications.md | 26 +-- docs/ru/docs/tutorial/body-multiple-params.md | 8 +- docs/ru/docs/tutorial/body-nested-models.md | 4 +- docs/ru/docs/tutorial/body.md | 6 +- docs/ru/docs/tutorial/cookie-param-models.md | 8 +- docs/ru/docs/tutorial/cookie-params.md | 6 +- docs/ru/docs/tutorial/cors.md | 4 +- docs/ru/docs/tutorial/debugging.md | 8 +- .../dependencies/classes-as-dependencies.md | 28 +-- ...pendencies-in-path-operation-decorators.md | 12 +- .../dependencies/dependencies-with-yield.md | 24 +-- .../dependencies/global-dependencies.md | 4 +- docs/ru/docs/tutorial/dependencies/index.md | 2 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/ru/docs/tutorial/encoder.md | 4 +- docs/ru/docs/tutorial/extra-models.md | 8 +- docs/ru/docs/tutorial/first-steps.md | 16 +- docs/ru/docs/tutorial/handling-errors.md | 20 +- docs/ru/docs/tutorial/metadata.md | 12 +- docs/ru/docs/tutorial/middleware.md | 32 ++- .../tutorial/path-operation-configuration.md | 10 +- .../path-params-numeric-validations.md | 16 +- docs/ru/docs/tutorial/path-params.md | 30 +-- docs/ru/docs/tutorial/query-param-models.md | 2 +- .../tutorial/query-params-str-validations.md | 42 +--- docs/ru/docs/tutorial/query-params.md | 8 +- docs/ru/docs/tutorial/request-files.md | 14 +- docs/ru/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/ru/docs/tutorial/request-forms.md | 10 +- docs/ru/docs/tutorial/response-model.md | 6 +- docs/ru/docs/tutorial/response-status-code.md | 10 +- docs/ru/docs/tutorial/schema-extra-example.md | 2 +- docs/ru/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/ru/docs/tutorial/security/index.md | 84 ++++---- docs/ru/docs/tutorial/security/oauth2-jwt.md | 28 ++- .../docs/tutorial/security/simple-oauth2.md | 2 +- docs/ru/docs/tutorial/sql-databases.md | 6 +- docs/ru/docs/tutorial/static-files.md | 2 +- docs/ru/docs/tutorial/testing.md | 10 +- docs/ru/docs/virtual-environments.md | 4 +- 90 files changed, 549 insertions(+), 620 deletions(-) create mode 100644 docs/ru/docs/advanced/advanced-python-types.md diff --git a/docs/ru/docs/advanced/additional-responses.md b/docs/ru/docs/advanced/additional-responses.md index fca4f072da..ca36ba20e3 100644 --- a/docs/ru/docs/advanced/additional-responses.md +++ b/docs/ru/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ ะะฐะฟั€ะธะผะตั€, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะธั‚ัŒ ะตั‰ั‘ ะพะดะธะฝ ะพั‚ะฒะตั‚ ัะพ ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ `404` ะธ Pydantic-ะผะพะดะตะปัŒัŽ `Message`, ะผะพะถะฝะพ ะฝะฐะฟะธัะฐั‚ัŒ: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -203,7 +203,7 @@ ะ ั‚ะฐะบะถะต ะพั‚ะฒะตั‚ ัะพ ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ `200`, ะบะพั‚ะพั€ั‹ะน ะธัะฟะพะปัŒะทัƒะตั‚ ะฒะฐัˆ `response_model`, ะฝะพ ะฒะบะปัŽั‡ะฐะตั‚ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน `example`: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} ะ’ัั‘ ัั‚ะพ ะฑัƒะดะตั‚ ะพะฑัŠะตะดะธะฝะตะฝะพ ะธ ะฒะบะปัŽั‡ะตะฝะพ ะฒ ะฒะฐัˆ OpenAPI ะธ ะพั‚ะพะฑั€ะฐะถะตะฝะพ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API: diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index fb2643cd5c..686a0cf91e 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ ะ”ะปั ัั‚ะพะณะพ ะพะฑัŠัะฒะปัะตะผ ะผะตั‚ะพะด `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะธะผะตะฝะฝะพ `__call__` **FastAPI** ะธัะฟะพะปัŒะทัƒะตั‚ ะดะปั ะฟั€ะพะฒะตั€ะบะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ ะธ ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ะตะน, ะธ ะธะผะตะฝะฝะพ ะพะฝ ะฑัƒะดะตั‚ ะฒั‹ะทะฒะฐะฝ, ั‡ั‚ะพะฑั‹ ะฟะพะทะถะต ะฟะตั€ะตะดะฐั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะฐั€ะฐะผะตั‚ั€ัƒ ะฒ ะฒะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ*. @@ -26,7 +26,7 @@ ะขะตะฟะตั€ัŒ ะผั‹ ะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `__init__`, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ัะบะทะตะผะฟะปัั€ะฐ, ั ะฟะพะผะพั‰ัŒัŽ ะบะพั‚ะพั€ั‹ั… ะฑัƒะดะตะผ ยซะฟะฐั€ะฐะผะตั‚ั€ะธะทะพะฒะฐั‚ัŒยป ะทะฐะฒะธัะธะผะพัั‚ัŒ: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต **FastAPI** ะฒะพะฒัะต ะฝะต ั‚ั€ะพะณะฐะตั‚ `__init__` ะธ ะฝะต ะทะฐะฒะธัะธั‚ ะพั‚ ะฝะตะณะพ โ€” ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะตะณะพ ะฝะฐะฟั€ัะผัƒัŽ ะฒ ะฝะฐัˆะตะผ ะบะพะดะต. @@ -34,7 +34,7 @@ ะœั‹ ะผะพะถะตะผ ัะพะทะดะฐั‚ัŒ ัะบะทะตะผะฟะปัั€ ัั‚ะพะณะพ ะบะปะฐััะฐ ั‚ะฐะบ: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} ะขะฐะบ ะผั‹ ยซะฟะฐั€ะฐะผะตั‚ั€ะธะทัƒะตะผยป ะฝะฐัˆัƒ ะทะฐะฒะธัะธะผะพัั‚ัŒ: ั‚ะตะฟะตั€ัŒ ะฒะฝัƒั‚ั€ะธ ะฝะตั‘ ั…ั€ะฐะฝะธั‚ัั "bar" ะฒ ะฐั‚ั€ะธะฑัƒั‚ะต `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") โ€ฆะธ ะฟะตั€ะตะดะฐัั‚ ะฒะพะทะฒั€ะฐั‰ั‘ะฝะฝะพะต ะทะฝะฐั‡ะตะฝะธะต ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `fixed_content_included` ะฝะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/advanced/advanced-python-types.md b/docs/ru/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..62dcf8c4f1 --- /dev/null +++ b/docs/ru/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ะŸั€ะพะดะฒะธะฝัƒั‚ั‹ะต ั‚ะธะฟั‹ Python { #advanced-python-types } + +ะะธะถะต ะฝะตัะบะพะปัŒะบะพ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะธะดะตะน, ะบะพั‚ะพั€ั‹ะต ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะฟะพะปะตะทะฝั‹ ะฟั€ะธ ั€ะฐะฑะพั‚ะต ั ั‚ะธะฟะฐะผะธ Python. + +## ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `Union` ะธะปะธ `Optional` { #using-union-or-optional } + +ะ•ัะปะธ ะฟะพ ะบะฐะบะพะน-ั‚ะพ ะฟั€ะธั‡ะธะฝะต ะฒะฐัˆ ะบะพะด ะฝะต ะผะพะถะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `|`, ะฝะฐะฟั€ะธะผะตั€, ะตัะปะธ ัั‚ะพ ะฝะต ะฐะฝะฝะพั‚ะฐั†ะธั ั‚ะธะฟะพะฒ, ะฐ ั‡ั‚ะพ-ั‚ะพ ะฒั€ะพะดะต `response_model=`, ะฒะผะตัั‚ะพ ะฒะตั€ั‚ะธะบะฐะปัŒะฝะพะน ั‡ะตั€ั‚ั‹ (`|`) ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Union` ะธะท `typing`. + +ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `str` ะธะปะธ `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +ะ’ `typing` ั‚ะฐะบะถะต ะตัั‚ัŒ ัะพะบั€ะฐั‰ะตะฝะธะต, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None`, โ€” `Optional`. + +ะ’ะพั‚ ัะพะฒะตั‚ ั ะผะพะตะน ะพั‡ะตะฝัŒ ััƒะฑัŠะตะบั‚ะธะฒะฝะพะน ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั: + +- ๐Ÿšจ ะ˜ะทะฑะตะณะฐะนั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั `Optional[SomeType]` +- ะ’ะผะตัั‚ะพ ัั‚ะพะณะพ โœจ ะธัะฟะพะปัŒะทัƒะนั‚ะต **`Union[SomeType, None]`** โœจ. + +ะžะฑะฐ ะฒะฐั€ะธะฐะฝั‚ะฐ ัะบะฒะธะฒะฐะปะตะฝั‚ะฝั‹ ะธ ะฟะพะด ะบะฐะฟะพั‚ะพะผ ัั‚ะพ ะพะดะฝะพ ะธ ั‚ะพ ะถะต, ะฝะพ ั ะฑั‹ ั€ะตะบะพะผะตะฝะดะพะฒะฐะป `Union` ะฒะผะตัั‚ะพ `Optional`, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัะปะพะฒะพ ยซoptionalยป ะผะพะถะตั‚ ะฝะฐะฒะพะดะธั‚ัŒ ะฝะฐ ะผั‹ัะปัŒ, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝะพะต, ั‚ะพะณะดะฐ ะบะฐะบ ะฝะฐ ัะฐะผะพะผ ะดะตะปะต ัั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚ ยซะทะฝะฐั‡ะตะฝะธะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None`ยป, ะดะฐะถะต ะตัะปะธ ะพะฝะพ ะฝะต ัะฒะปัะตั‚ัั ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ ะธ ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ั‚ั€ะตะฑัƒะตั‚ัั. + +ะŸะพ-ะผะพะตะผัƒ, `Union[SomeType, None]` ะฑะพะปะตะต ัะฒะฝะพ ะฟะตั€ะตะดะฐั‘ั‚ ัะผั‹ัะป. + +ะ ะตั‡ัŒ ั‚ะพะปัŒะบะพ ะพ ัะปะพะฒะฐั… ะธ ะฝะฐะทะฒะฐะฝะธัั…. ะะพ ัั‚ะธ ัะปะพะฒะฐ ะผะพะณัƒั‚ ะฒะปะธัั‚ัŒ ะฝะฐ ั‚ะพ, ะบะฐะบ ะฒั‹ ะธ ะฒะฐัˆะฐ ะบะพะผะฐะฝะดะฐ ะดัƒะผะฐะตั‚ะต ะพ ะบะพะดะต. + +ะ’ ะบะฐั‡ะตัั‚ะฒะต ะฟั€ะธะผะตั€ะฐ ะฒะพะทัŒะผั‘ะผ ั‚ะฐะบัƒัŽ ั„ัƒะฝะบั†ะธัŽ: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +ะŸะฐั€ะฐะผะตั‚ั€ `name` ะพะฑัŠัะฒะปะตะฝ ะบะฐะบ `Optional[str]`, ะฝะพ ะพะฝ ะฝะต ัะฒะปัะตั‚ัั ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ: ะฒั‹ ะฝะต ะผะพะถะตั‚ะต ะฒั‹ะทะฒะฐั‚ัŒ ั„ัƒะฝะบั†ะธัŽ ะฑะตะท ัั‚ะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ: + +```Python +say_hi() # ะž ะฝะตั‚, ัั‚ะพ ะฒั‹ะทั‹ะฒะฐะตั‚ ะพัˆะธะฑะบัƒ! ๐Ÿ˜ฑ +``` + +ะŸะฐั€ะฐะผะตั‚ั€ `name` ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ะพะฑัะทะฐั‚ะตะปะตะฝ (ะฝะต ยซoptionalยป), ั‚ะฐะบ ะบะฐะบ ัƒ ะฝะตะณะพ ะฝะตั‚ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. ะŸั€ะธ ัั‚ะพะผ `name` ะฟั€ะธะฝะธะผะฐะตั‚ `None` ะฒ ะบะฐั‡ะตัั‚ะฒะต ะทะฝะฐั‡ะตะฝะธั: + +```Python +say_hi(name=None) # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, None ะดะพะฟัƒัั‚ะธะผ ๐ŸŽ‰ +``` + +ะฅะพั€ะพัˆะฐั ะฝะพะฒะพัั‚ัŒ: ะฒ ะฑะพะปัŒัˆะธะฝัั‚ะฒะต ัะปัƒั‡ะฐะตะฒ ะฒั‹ ัะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `|` ะดะปั ะพะฑัŠัะฒะปะตะฝะธั ะพะฑัŠะตะดะธะฝะตะฝะธะน ั‚ะธะฟะพะฒ: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +ะขะฐะบ ั‡ั‚ะพ ะพะฑั‹ั‡ะฝะพ ะฒะฐะผ ะฝะต ะพ ั‡ะตะผ ะฟะตั€ะตะถะธะฒะฐั‚ัŒ ะธะทโ€‘ะทะฐ ะฝะฐะทะฒะฐะฝะธะน ะฒั€ะพะดะต `Optional` ะธ `Union`. ๐Ÿ˜Ž diff --git a/docs/ru/docs/advanced/async-tests.md b/docs/ru/docs/advanced/async-tests.md index e689704066..52939c2559 100644 --- a/docs/ru/docs/advanced/async-tests.md +++ b/docs/ru/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ ะคะฐะนะป `main.py`: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} ะคะฐะนะป `test_main.py` ัะพะดะตั€ะถะธั‚ ั‚ะตัั‚ั‹ ะดะปั `main.py`, ั‚ะตะฟะตั€ัŒ ะพะฝ ะผะพะถะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## ะ—ะฐะฟัƒัะบ ั‚ะตัั‚ะพะฒ { #run-it } @@ -56,7 +56,7 @@ $ pytest ะœะฐั€ะบะตั€ `@pytest.mark.anyio` ะณะพะฒะพั€ะธั‚ pytest, ั‡ั‚ะพ ั‚ะตัั‚ะพะฒะฐั ั„ัƒะฝะบั†ะธั ะดะพะปะถะฝะฐ ะฑั‹ั‚ัŒ ะฒั‹ะทะฒะฐะฝะฐ ะฐัะธะฝั…ั€ะพะฝะฝะพ: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -66,7 +66,7 @@ $ pytest ะ—ะฐั‚ะตะผ ะผั‹ ะผะพะถะตะผ ัะพะทะดะฐั‚ัŒ `AsyncClient` ัะพ ััั‹ะปะบะพะน ะฝะฐ ะฟั€ะธะปะพะถะตะฝะธะต ะธ ะฟะพัั‹ะปะฐั‚ัŒ ะฐัะธะฝั…ั€ะพะฝะฝั‹ะต ะทะฐะฟั€ะพัั‹, ะธัะฟะพะปัŒะทัƒั `await`. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} ะญั‚ะพ ัะบะฒะธะฒะฐะปะตะฝั‚ะฝะพ ัะปะตะดัƒัŽั‰ะตะผัƒ: @@ -94,6 +94,6 @@ response = client.get('/') /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ•ัะปะธ ะฒั‹ ัั‚ะพะปะบะฝัƒะปะธััŒ ั `RuntimeError: Task attached to a different loop` ะฟั€ะธ ะฒั‹ะทะพะฒะต ะฐัะธะฝั…ั€ะพะฝะฝั‹ั… ั„ัƒะฝะบั†ะธะน ะฒ ะฒะฐัˆะธั… ั‚ะตัั‚ะฐั… (ะฝะฐะฟั€ะธะผะตั€, ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ
MongoDB's MotorClient), ั‚ะพ ะฝะต ะทะฐะฑั‹ะฒะฐะนั‚ะต ะธะฝะธั†ะธะฐะปะธะทะธั€ะพะฒะฐั‚ัŒ ะพะฑัŠะตะบั‚ั‹, ะบะพั‚ะพั€ั‹ะผ ะฝัƒะถะตะฝ ั†ะธะบะป ัะพะฑั‹ั‚ะธะน (event loop), ั‚ะพะปัŒะบะพ ะฒะฝัƒั‚ั€ะธ ะฐัะธะฝั…ั€ะพะฝะฝั‹ั… ั„ัƒะฝะบั†ะธะน, ะฝะฐะฟั€ะธะผะตั€, ะฒ `'@app.on_event("startup")` callback. +ะ•ัะปะธ ะฒั‹ ัั‚ะพะปะบะฝัƒะปะธััŒ ั `RuntimeError: Task attached to a different loop` ะฟั€ะธ ะฒั‹ะทะพะฒะต ะฐัะธะฝั…ั€ะพะฝะฝั‹ั… ั„ัƒะฝะบั†ะธะน ะฒ ะฒะฐัˆะธั… ั‚ะตัั‚ะฐั… (ะฝะฐะฟั€ะธะผะตั€, ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ MongoDB's MotorClient), ั‚ะพ ะฝะต ะทะฐะฑั‹ะฒะฐะนั‚ะต ะธะฝะธั†ะธะฐะปะธะทะธั€ะพะฒะฐั‚ัŒ ะพะฑัŠะตะบั‚ั‹, ะบะพั‚ะพั€ั‹ะผ ะฝัƒะถะตะฝ ั†ะธะบะป ัะพะฑั‹ั‚ะธะน (event loop), ั‚ะพะปัŒะบะพ ะฒะฝัƒั‚ั€ะธ ะฐัะธะฝั…ั€ะพะฝะฝั‹ั… ั„ัƒะฝะบั†ะธะน, ะฝะฐะฟั€ะธะผะตั€, ะฒ `@app.on_event("startup")` callback. /// diff --git a/docs/ru/docs/advanced/behind-a-proxy.md b/docs/ru/docs/advanced/behind-a-proxy.md index f78da01a09..ec75ed3698 100644 --- a/docs/ru/docs/advanced/behind-a-proxy.md +++ b/docs/ru/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะพะฑัŠัะฒะธะปะธ ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} ะ•ัะปะธ ะบะปะธะตะฝั‚ ะพะฑั€ะฐั‚ะธั‚ัั ะบ `/items`, ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฟั€ะพะธะทะพะนะดั‘ั‚ ั€ะตะดะธั€ะตะบั‚ ะฝะฐ `/items/`. @@ -115,7 +115,7 @@ sequenceDiagram ะฅะพั‚ั ะฒะตััŒ ะฒะฐัˆ ะบะพะด ะฝะฐะฟะธัะฐะฝ ั ั€ะฐัั‡ั‘ั‚ะพะผ, ั‡ั‚ะพ ะฟัƒั‚ัŒ ะพะดะธะฝ โ€” `/app`. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} ะŸั€ะพะบัะธ ะฑัƒะดะตั‚ ยซะพะฑั€ะตะทะฐั‚ัŒยป ะฟั€ะตั„ะธะบั ะฟัƒั‚ะธ ะฝะฐ ะปะตั‚ัƒ ะฟะตั€ะตะด ะฟะตั€ะตะดะฐั‡ะตะน ะทะฐะฟั€ะพัะฐ ะฝะฐ ัะตั€ะฒะตั€ ะฟั€ะธะปะพะถะตะฝะธั (ัะบะพั€ะตะต ะฒัะตะณะพ Uvicorn, ะทะฐะฟัƒั‰ะตะฝะฝั‹ะน ั‡ะตั€ะตะท FastAPI CLI), ะฟะพะดะดะตั€ะถะธะฒะฐั ัƒ ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั ะธะปะปัŽะทะธัŽ, ั‡ั‚ะพ ะตะณะพ ะพะฑัะปัƒะถะธะฒะฐัŽั‚ ะฟะพ `/app`, ั‡ั‚ะพะฑั‹ ะฒะฐะผ ะฝะต ะฟั€ะธัˆะปะพััŒ ะผะตะฝัั‚ัŒ ะฒะตััŒ ะบะพะด ะธ ะดะพะฑะฐะฒะปัั‚ัŒ ะฟั€ะตั„ะธะบั `/api/v1`. @@ -193,7 +193,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ะ—ะดะตััŒ ะผั‹ ะดะพะฑะฐะฒะปัะตะผ ะตะณะพ ะฒ ัะพะพะฑั‰ะตะฝะธะต ะปะธัˆัŒ ะดะปั ะดะตะผะพะฝัั‚ั€ะฐั†ะธะธ. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} ะ—ะฐั‚ะตะผ, ะตัะปะธ ะฒั‹ ะทะฐะฟัƒัั‚ะธั‚ะต Uvicorn ั‚ะฐะบ: @@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ะ•ัะปะธ ะฝะตั‚ ะฒะพะทะผะพะถะฝะพัั‚ะธ ะฟะตั€ะตะดะฐั‚ัŒ ะพะฟั†ะธัŽ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ `--root-path` (ะธะปะธ ะฐะฝะฐะปะพะณ), ะฒั‹ ะผะพะถะตั‚ะต ัƒะบะฐะทะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `root_path` ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะฟั€ะธะปะพะถะตะฝะธั FastAPI: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} ะŸะตั€ะตะดะฐั‡ะฐ `root_path` ะฒ `FastAPI` ัะบะฒะธะฒะฐะปะตะฝั‚ะฝะฐ ะพะฟั†ะธะธ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ `--root-path` ะดะปั Uvicorn ะธะปะธ Hypercorn. @@ -241,17 +241,17 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 Uvicorn ะพะถะธะดะฐะตั‚, ั‡ั‚ะพ ะฟั€ะพะบัะธ ะพะฑั€ะฐั‚ะธั‚ัั ะบ ะฝะตะผัƒ ะฟะพ `http://127.0.0.1:8000/app`, ะฐ ัƒะถะต ะทะฐะดะฐั‡ะฐ ะฟั€ะพะบัะธ โ€” ะดะพะฑะฐะฒะธั‚ัŒ ัะฒะตั€ั…ัƒ ะฟั€ะตั„ะธะบั `/api/v1`. -## ะž ะฟั€ะพะบัะธ ั ัƒั€ะตะทะฐะฝะฝั‹ะผ ะฟั€ะตั„ะธะบัะพะผ ะฟัƒั‚ะธ { #about-proxies-with-a-stripped-path-prefix } +## ะž ะฟั€ะพะบัะธ ั ั„ัƒะฝะบั†ะธะตะน ัƒะดะฐะปะตะฝะธั ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ { #about-proxies-with-a-stripped-path-prefix } -ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ะฟั€ะพะบัะธ ั ัƒั€ะตะทะฐะฝะฝั‹ะผ ะฟั€ะตั„ะธะบัะพะผ ะฟัƒั‚ะธ โ€” ะปะธัˆัŒ ะพะดะธะฝ ะธะท ะฒะฐั€ะธะฐะฝั‚ะพะฒ ะฝะฐัั‚ั€ะพะนะบะธ. +ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ะฟั€ะพะบัะธ ั ั„ัƒะฝะบั†ะธะตะน ัƒะดะฐะปะตะฝะธั ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ โ€” ะปะธัˆัŒ ะพะดะธะฝ ะธะท ะฒะฐั€ะธะฐะฝั‚ะพะฒ ะฝะฐัั‚ั€ะพะนะบะธ. -ะ’ะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฟั€ะพะบัะธ ะฑัƒะดะตั‚ ะฑะตะท ัƒั€ะตะทะฐะฝะฝะพะณะพ ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ. +ะ’ะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฟั€ะพะบัะธ ะฑัƒะดะตั‚ ะฑะตะท ั„ัƒะฝะบั†ะธะธ ัƒะดะฐะปะตะฝะธั ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ. -ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต (ะฑะตะท ัƒั€ะตะทะฐะฝะฝะพะณะพ ะฟั€ะตั„ะธะบัะฐ) ะฟั€ะพะบัะธ ัะปัƒัˆะฐะตั‚, ะฝะฐะฟั€ะธะผะตั€, ะฟะพ ะฐะดั€ะตััƒ `https://myawesomeapp.com`, ะธ ะตัะปะธ ะฑั€ะฐัƒะทะตั€ ะธะดั‘ั‚ ะฝะฐ `https://myawesomeapp.com/api/v1/app`, ะฐ ะฒะฐัˆ ัะตั€ะฒะตั€ (ะฝะฐะฟั€ะธะผะตั€, Uvicorn) ัะปัƒัˆะฐะตั‚ ะฝะฐ `http://127.0.0.1:8000`, ั‚ะพ ะฟั€ะพะบัะธ (ะฑะตะท ัƒั€ะตะทะฐะฝะฝะพะณะพ ะฟั€ะตั„ะธะบัะฐ) ะพะฑั€ะฐั‚ะธั‚ัั ะบ Uvicorn ะฟะพ ั‚ะพะผัƒ ะถะต ะฟัƒั‚ะธ: `http://127.0.0.1:8000/api/v1/app`. +ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต (ะฑะตะท ั„ัƒะฝะบั†ะธะธ ัƒะดะฐะปะตะฝะธั ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ) ะฟั€ะพะบัะธ ัะปัƒัˆะฐะตั‚, ะฝะฐะฟั€ะธะผะตั€, ะฟะพ ะฐะดั€ะตััƒ `https://myawesomeapp.com`, ะธ ะตัะปะธ ะฑั€ะฐัƒะทะตั€ ะธะดั‘ั‚ ะฝะฐ `https://myawesomeapp.com/api/v1/app`, ะฐ ะฒะฐัˆ ัะตั€ะฒะตั€ (ะฝะฐะฟั€ะธะผะตั€, Uvicorn) ัะปัƒัˆะฐะตั‚ ะฝะฐ `http://127.0.0.1:8000`, ั‚ะพ ะฟั€ะพะบัะธ (ะฑะตะท ัƒั€ะตะทะฐะฝะฝะพะณะพ ะฟั€ะตั„ะธะบัะฐ) ะพะฑั€ะฐั‚ะธั‚ัั ะบ Uvicorn ะฟะพ ั‚ะพะผัƒ ะถะต ะฟัƒั‚ะธ: `http://127.0.0.1:8000/api/v1/app`. ## ะ›ะพะบะฐะปัŒะฝะพะต ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธะต ั Traefik { #testing-locally-with-traefik } -ะ’ั‹ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฟะพัะบัะฟะตั€ะธะผะตะฝั‚ะธั€ะพะฒะฐั‚ัŒ ะปะพะบะฐะปัŒะฝะพ ั ัƒั€ะตะทะฐะฝะฝั‹ะผ ะฟั€ะตั„ะธะบัะพะผ ะฟัƒั‚ะธ, ะธัะฟะพะปัŒะทัƒั Traefik. +ะ’ั‹ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฟะพัะบัะฟะตั€ะธะผะตะฝั‚ะธั€ะพะฒะฐั‚ัŒ ะปะพะบะฐะปัŒะฝะพ ั ั„ัƒะฝะบั†ะธะตะน ัƒะดะฐะปะตะฝะธั ะฟั€ะตั„ะธะบัะฐ ะฟัƒั‚ะธ, ะธัะฟะพะปัŒะทัƒั Traefik. ะกะบะฐั‡ะฐะนั‚ะต Traefik โ€” ัั‚ะพ ะพะดะธะฝ ะฑะธะฝะฐั€ะฝั‹ะน ั„ะฐะนะป; ั€ะฐัะฟะฐะบัƒะนั‚ะต ะฐั€ั…ะธะฒ ะธ ะทะฐะฟัƒัั‚ะธั‚ะต ะตะณะพ ะฟั€ัะผะพ ะธะท ั‚ะตั€ะผะธะฝะฐะปะฐ. @@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ะะฐะฟั€ะธะผะตั€: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} ะ‘ัƒะดะตั‚ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฐ ัั…ะตะผะฐ OpenAPI ะฟั€ะธะผะตั€ะฝะพ ั‚ะฐะบะฐั: @@ -455,7 +455,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ะ•ัะปะธ ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต, ั‡ั‚ะพะฑั‹ FastAPI ะดะพะฑะฐะฒะปัะป ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะน ัะตั€ะฒะตั€, ะธัะฟะพะปัŒะทัƒั `root_path`, ัƒะบะฐะถะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} ะธ ั‚ะพะณะดะฐ ัั‚ะพั‚ ัะตั€ะฒะตั€ ะฝะต ะฑัƒะดะตั‚ ะดะพะฑะฐะฒะปะตะฝ ะฒ ัั…ะตะผัƒ OpenAPI. diff --git a/docs/ru/docs/advanced/custom-response.md b/docs/ru/docs/advanced/custom-response.md index 49550b49ff..b9f91373da 100644 --- a/docs/ru/docs/advanced/custom-response.md +++ b/docs/ru/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ ะะพ ะตัะปะธ ะฒั‹ ัƒะฒะตั€ะตะฝั‹, ั‡ั‚ะพ ัะพะดะตั€ะถะธะผะพะต, ะบะพั‚ะพั€ะพะต ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต, **ัะตั€ะธะฐะปะธะทัƒะตะผะพ ะฒ JSON**, ะฒั‹ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ัŒ ะตะณะพ ะฝะฐะฟั€ัะผัƒัŽ ะฒ ะบะปะฐัั ะพั‚ะฒะตั‚ะฐ ะธ ะธะทะฑะตะถะฐั‚ัŒ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะฝะฐะบะปะฐะดะฝั‹ั… ั€ะฐัั…ะพะดะพะฒ, ะบะพั‚ะพั€ั‹ะต FastAPI ะฟะพะฝั‘ั ะฑั‹, ะฟั€ะพะฟัƒัะบะฐั ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะต ัะพะดะตั€ะถะธะผะพะต ั‡ะตั€ะตะท `jsonable_encoder` ะฟะตั€ะตะด ะฟะตั€ะตะดะฐั‡ะตะน ะฒ ะบะปะฐัั ะพั‚ะฒะตั‚ะฐ. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั @@ -55,7 +55,7 @@ - ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `HTMLResponse`. - ะŸะตั€ะตะดะฐะนั‚ะต `HTMLResponse` ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `response_class` ะฒะฐัˆะตะณะพ ะดะตะบะพั€ะฐั‚ะพั€ะฐ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั @@ -73,17 +73,17 @@ ะขะพั‚ ะถะต ะฟั€ะธะผะตั€ ัะฒะตั€ั…ัƒ, ะฒะพะทะฒั€ะฐั‰ะฐัŽั‰ะธะน `HTMLResponse`, ะผะพะถะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | ะŸั€ะตะดัƒะฟั€ะตะถะดะตะฝะธะต -`Response`, ะฒะพะทะฒั€ะฐั‰ั‘ะฝะฝั‹ะน ะฝะฐะฟั€ัะผัƒัŽ ะฒะฐัˆะตะน ั„ัƒะฝะบั†ะธะตะน-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะพะผ ะฟัƒั‚ะธ, ะฝะต ะฑัƒะดะตั‚ ะทะฐะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝ ะฒ OpenAPI (ะฝะฐะฟั€ะธะผะตั€, `Content-Type` ะฝะฝะต ะฑัƒะดะตั‚ ะทะฐะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐ) ะธ ะฝะต ะฑัƒะดะตั‚ ะฒะธะดะตะฝ ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. +`Response`, ะฒะพะทะฒั€ะฐั‰ั‘ะฝะฝั‹ะน ะฝะฐะฟั€ัะผัƒัŽ ะฒะฐัˆะตะน ั„ัƒะฝะบั†ะธะตะน-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะพะผ ะฟัƒั‚ะธ, ะฝะต ะฑัƒะดะตั‚ ะทะฐะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝ ะฒ OpenAPI (ะฝะฐะฟั€ะธะผะตั€, `Content-Type` ะฝะต ะฑัƒะดะตั‚ ะทะฐะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝ) ะธ ะฝะต ะฑัƒะดะตั‚ ะฒะธะดะตะฝ ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. /// /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั -ะ ะฐะทัƒะผะตะตั‚ัั, ั„ะฐะบั‚ะธั‡ะตัะบะธะต ะทะฐะณะพะปะพะฒะพะบ `Content-Type`, ัั‚ะฐั‚ัƒั-ะบะพะด ะธ ั‚.ะด. ะฒะพะทัŒะผัƒั‚ัั ะธะท ะพะฑัŠะตะบั‚ะฐ `Response`, ะบะพั‚ะพั€ั‹ะน ะฒั‹ ะฒะตั€ะฝัƒะปะธ. +ะ ะฐะทัƒะผะตะตั‚ัั, ั„ะฐะบั‚ะธั‡ะตัะบะธะน ะทะฐะณะพะปะพะฒะพะบ `Content-Type`, ัั‚ะฐั‚ัƒั-ะบะพะด ะธ ั‚.ะด. ะฒะพะทัŒะผัƒั‚ัั ะธะท ะพะฑัŠะตะบั‚ะฐ `Response`, ะบะพั‚ะพั€ั‹ะน ะฒั‹ ะฒะตั€ะฝัƒะปะธ. /// @@ -97,7 +97,7 @@ ะะฐะฟั€ะธะผะตั€, ัั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั‡ั‚ะพ-ั‚ะพ ะฒั€ะพะดะต: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ั„ัƒะฝะบั†ะธั `generate_html_response()` ัƒะถะต ะณะตะฝะตั€ะธั€ัƒะตั‚ ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ `Response` ะฒะผะตัั‚ะพ ะฒะพะทะฒั€ะฐั‚ะฐ HTML ะฒ `str`. @@ -136,7 +136,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธั‚ ะทะฐะณะพะปะพะฒะพะบ Content-Length. ะขะฐะบะถะต ะฑัƒะดะตั‚ ะดะพะฑะฐะฒะปะตะฝ ะทะฐะณะพะปะพะฒะพะบ Content-Type, ะพัะฝะพะฒะฐะฝะฝั‹ะน ะฝะฐ `media_type` ะธ ั ะดะพะฑะฐะฒะปะตะฝะธะตะผ charset ะดะปั ั‚ะตะบัั‚ะพะฒั‹ั… ั‚ะธะฟะพะฒ. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะŸั€ะธะฝะธะผะฐะตั‚ ั‚ะตะบัั‚ ะธะปะธ ะฑะฐะนั‚ั‹ ะธ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะพั‚ะฒะตั‚ ะฒ ะฒะธะดะต ะฟั€ะพัั‚ะพะณะพ ั‚ะตะบัั‚ะฐ. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | ะกะพะฒะตั‚ @@ -194,13 +194,13 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะ’ั‹ ะผะพะถะตั‚ะต ะฒะตั€ะฝัƒั‚ัŒ `RedirectResponse` ะฝะฐะฟั€ัะผัƒัŽ: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- ะ˜ะปะธ ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะตะณะพ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ะต `response_class`: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} ะ•ัะปะธ ะฒั‹ ัะดะตะปะฐะตั‚ะต ั‚ะฐะบ, ั‚ะพ ัะผะพะถะตั‚ะต ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ URL ะฝะฐะฟั€ัะผัƒัŽ ะธะท ัะฒะพะตะน ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ. @@ -210,13 +210,13 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะขะฐะบะถะต ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `status_code` ะฒ ัะพั‡ะตั‚ะฐะฝะธะธ ั ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `response_class`: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } ะŸั€ะธะฝะธะผะฐะตั‚ ะฐัะธะฝั…ั€ะพะฝะฝั‹ะน ะณะตะฝะตั€ะฐั‚ะพั€ ะธะปะธ ะพะฑั‹ั‡ะฝั‹ะน ะณะตะฝะตั€ะฐั‚ะพั€/ะธั‚ะตั€ะฐั‚ะพั€ ะธ ะพั‚ะฟั€ะฐะฒะปัะตั‚ ั‚ะตะปะพ ะพั‚ะฒะตั‚ะฐ ะฟะพั‚ะพะบะพะฒะพ. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `StreamingResponse` ั ั„ะฐะนะปะพะฟะพะดะพะฑะฝั‹ะผะธ ะพะฑัŠะตะบั‚ะฐะผะธ { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะญั‚ะพ ะฒะบะปัŽั‡ะฐะตั‚ ะผะฝะพะณะธะต ะฑะธะฑะปะธะพั‚ะตะบะธ ะดะปั ั€ะฐะฑะพั‚ั‹ ั ะพะฑะปะฐั‡ะฝั‹ะผ ั…ั€ะฐะฝะธะปะธั‰ะตะผ, ะพะฑั€ะฐะฑะพั‚ะบะธ ะฒะธะดะตะพ ะธ ั‚.ะด. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. ะญั‚ะพ ั„ัƒะฝะบั†ะธั-ะณะตะฝะตั€ะฐั‚ะพั€. ะžะฝะฐ ัะฒะปัะตั‚ัั ยซั„ัƒะฝะบั†ะธะตะน-ะณะตะฝะตั€ะฐั‚ะพั€ะพะผยป, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัะพะดะตั€ะถะธั‚ ะพะฟะตั€ะฐั‚ะพั€(ั‹) `yield` ะฒะฝัƒั‚ั€ะธ. 2. ะ˜ัะฟะพะปัŒะทัƒั ะฑะปะพะบ `with`, ะผั‹ ะณะฐั€ะฐะฝั‚ะธั€ัƒะตะผ, ั‡ั‚ะพ ั„ะฐะนะปะพะฟะพะดะพะฑะฝั‹ะน ะพะฑัŠะตะบั‚ ะฑัƒะดะตั‚ ะทะฐะบั€ั‹ั‚ ะฟะพัะปะต ะทะฐะฒะตั€ัˆะตะฝะธั ั€ะฐะฑะพั‚ั‹ ั„ัƒะฝะบั†ะธะธ-ะณะตะฝะตั€ะฐั‚ะพั€ะฐ. ะขะพ ะตัั‚ัŒ ะฟะพัะปะต ั‚ะพะณะพ, ะบะฐะบ ะพะฝะฐ ะทะฐะบะพะฝั‡ะธั‚ ะพั‚ะฟั€ะฐะฒะบัƒ ะพั‚ะฒะตั‚ะฐ. @@ -255,11 +255,11 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะคะฐะนะปะพะฒั‹ะต ะพั‚ะฒะตั‚ั‹ ะฑัƒะดัƒั‚ ัะพะดะตั€ะถะฐั‚ัŒ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะธะต ะทะฐะณะพะปะพะฒะบะธ `Content-Length`, `Last-Modified` ะธ `ETag`. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `response_class`: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ะฟัƒั‚ัŒ ะบ ั„ะฐะนะปัƒ ะฝะฐะฟั€ัะผัƒัŽ ะธะท ัะฒะพะตะน ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ. @@ -273,7 +273,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะ’ั‹ ะผะพะณะปะธ ะฑั‹ ัะพะทะดะฐั‚ัŒ `CustomORJSONResponse`. ะ“ะปะฐะฒะฝะพะต, ั‡ั‚ะพ ะฒะฐะผ ะฝัƒะถะฝะพ ัะดะตะปะฐั‚ัŒ โ€” ั€ะตะฐะปะธะทะพะฒะฐั‚ัŒ ะผะตั‚ะพะด `Response.render(content)`, ะบะพั‚ะพั€ั‹ะน ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ัะพะดะตั€ะถะธะผะพะต ะบะฐะบ `bytes`: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} ะขะตะฟะตั€ัŒ ะฒะผะตัั‚ะพ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ: @@ -299,7 +299,7 @@ FastAPI (ั„ะฐะบั‚ะธั‡ะตัะบะธ Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะดะพะฑะฐะฒะธ ะ’ ะฟั€ะธะผะตั€ะต ะฝะธะถะต **FastAPI** ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `ORJSONResponse` ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฒะพ ะฒัะตั… ะพะฟะตั€ะฐั†ะธัั… ะฟัƒั‚ะธ ะฒะผะตัั‚ะพ `JSONResponse`. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/advanced/dataclasses.md b/docs/ru/docs/advanced/dataclasses.md index b3ced37c1e..87a5763c10 100644 --- a/docs/ru/docs/advanced/dataclasses.md +++ b/docs/ru/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ FastAPI ะฟะพัั‚ั€ะพะตะฝ ะฟะพะฒะตั€ั… **Pydantic**, ะธ ั ะฟะพะบะฐะทั‹ะฒะฐะป ะฒ 6. ะ—ะดะตััŒ ะผั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ัะปะพะฒะฐั€ัŒ, ัะพะดะตั€ะถะฐั‰ะธะน `items`, ะบะพั‚ะพั€ั‹ะน ัะฒะปัะตั‚ัั ัะฟะธัะบะพะผ dataclass. - FastAPI ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ัะฟะพัะพะฑะตะฝ ัะตั€ะธะฐะปะธะทะพะฒะฐั‚ัŒ ะดะฐะฝะฝั‹ะต ะฒ JSON. + FastAPI ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ัะฟะพัะพะฑะตะฝ ัะตั€ะธะฐะปะธะทะพะฒะฐั‚ัŒ ะดะฐะฝะฝั‹ะต ะฒ JSON. 7. ะ—ะดะตััŒ `response_model` ะธัะฟะพะปัŒะทัƒะตั‚ ะฐะฝะฝะพั‚ะฐั†ะธัŽ ั‚ะธะฟะฐ โ€” ัะฟะธัะพะบ dataclass `Author`. diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index db73d9094e..bcb5b000a4 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -30,7 +30,7 @@ ะœั‹ ัะพะทะดะฐั‘ะผ ะฐัะธะฝั…ั€ะพะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ `lifespan()` ั `yield` ะฟั€ะธะผะตั€ะฝะพ ั‚ะฐะบ: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} ะ—ะดะตััŒ ะผั‹ ัะธะผัƒะปะธั€ัƒะตะผ ะดะพั€ะพะณัƒัŽ ะพะฟะตั€ะฐั†ะธัŽ startup ะฟะพ ะทะฐะณั€ัƒะทะบะต ะผะพะดะตะปะธ, ะฟะพะผะตั‰ะฐั (ั„ะธะบั‚ะธะฒะฝัƒัŽ) ั„ัƒะฝะบั†ะธัŽ ะผะพะดะตะปะธ ะฒ ัะปะพะฒะฐั€ัŒ ั ะผะพะดะตะปัะผะธ ะœะฐัˆะธะฝะฝะพะณะพ ะพะฑัƒั‡ะตะฝะธั ะดะพ `yield`. ะญั‚ะพั‚ ะบะพะด ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝะตะฝ ะดะพ ั‚ะพะณะพ, ะบะฐะบ ะฟั€ะธะปะพะถะตะฝะธะต ะฝะฐั‡ะฝะตั‚ ะฟั€ะธะฝะธะผะฐั‚ัŒ ะทะฐะฟั€ะพัั‹, ะฒะพ ะฒั€ะตะผั startup. @@ -48,7 +48,7 @@ ะŸะตั€ะฒะพะต, ะฝะฐ ั‡ั‚ะพ ัั‚ะพะธั‚ ะพะฑั€ะฐั‚ะธั‚ัŒ ะฒะฝะธะผะฐะฝะธะต, โ€” ะผั‹ ะพะฟั€ะตะดะตะปัะตะผ ะฐัะธะฝั…ั€ะพะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ ั `yield`. ะญั‚ะพ ะพั‡ะตะฝัŒ ะฟะพั…ะพะถะต ะฝะฐ ะ—ะฐะฒะธัะธะผะพัั‚ะธ ั `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} ะŸะตั€ะฒะฐั ั‡ะฐัั‚ัŒ ั„ัƒะฝะบั†ะธะธ, ะดะพ `yield`, ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝะตะฝะฐ ะดะพ ะทะฐะฟัƒัะบะฐ ะฟั€ะธะปะพะถะตะฝะธั. @@ -60,7 +60,7 @@ ะญั‚ะพ ะฟั€ะตะฒั€ะฐั‰ะฐะตั‚ ั„ัƒะฝะบั†ะธัŽ ะฒ ยซะฐัะธะฝั…ั€ะพะฝะฝั‹ะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ะฐยป. -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} ะœะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ะฐ ะฒ Python โ€” ัั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒ ะพะฟะตั€ะฐั‚ะพั€ะต `with`. ะะฐะฟั€ะธะผะตั€, `open()` ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะฐะบ ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ะฐ: @@ -82,7 +82,7 @@ async with lifespan(app): ะŸะฐั€ะฐะผะตั‚ั€ `lifespan` ะฟั€ะธะปะพะถะตะฝะธั `FastAPI` ะฟั€ะธะฝะธะผะฐะตั‚ ะฐัะธะฝั…ั€ะพะฝะฝั‹ะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ะฐ, ะฟะพัั‚ะพะผัƒ ะผั‹ ะผะพะถะตะผ ะฟะตั€ะตะดะฐั‚ัŒ ะตะผัƒ ะฝะฐัˆ ะฝะพะฒั‹ะน ะฐัะธะฝั…ั€ะพะฝะฝั‹ะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ะฐ `lifespan`. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝั‹ะต ัะพะฑั‹ั‚ะธั (ัƒัั‚ะฐั€ะตะฒัˆะธะต) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ async with lifespan(app): ะงั‚ะพะฑั‹ ะดะพะฑะฐะฒะธั‚ัŒ ั„ัƒะฝะบั†ะธัŽ, ะบะพั‚ะพั€ัƒัŽ ะฝัƒะถะฝะพ ะทะฐะฟัƒัั‚ะธั‚ัŒ ะดะพ ัั‚ะฐั€ั‚ะฐ ะฟั€ะธะปะพะถะตะฝะธั, ะพะฑัŠัะฒะธั‚ะต ะตั‘ ะบะฐะบ ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธั `"startup"`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ั„ัƒะฝะบั†ะธั-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธั `startup` ะธะฝะธั†ะธะฐะปะธะทะธั€ัƒะตั‚ ยซะฑะฐะทัƒ ะดะฐะฝะฝั‹ั…ยป items (ัั‚ะพ ะฟั€ะพัั‚ะพ `dict`) ะฝะตะบะพั‚ะพั€ั‹ะผะธ ะทะฝะฐั‡ะตะฝะธัะผะธ. @@ -116,7 +116,7 @@ async with lifespan(app): ะงั‚ะพะฑั‹ ะดะพะฑะฐะฒะธั‚ัŒ ั„ัƒะฝะบั†ะธัŽ, ะบะพั‚ะพั€ัƒัŽ ะฝัƒะถะฝะพ ะทะฐะฟัƒัั‚ะธั‚ัŒ ะฟั€ะธ ะทะฐะฒะตั€ัˆะตะฝะธะธ ั€ะฐะฑะพั‚ั‹ ะฟั€ะธะปะพะถะตะฝะธั, ะพะฑัŠัะฒะธั‚ะต ะตั‘ ะบะฐะบ ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธั `"shutdown"`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} ะ—ะดะตััŒ ั„ัƒะฝะบั†ะธั-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธั `shutdown` ะทะฐะฟะธัˆะตั‚ ัั‚ั€ะพะบัƒ ั‚ะตะบัั‚ะฐ `"Application shutdown"` ะฒ ั„ะฐะนะป `log.txt`. diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index 00bdd31fe8..4eb098a88f 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -2,7 +2,7 @@ ะŸะพัะบะพะปัŒะบัƒ **FastAPI** ะพัะฝะพะฒะฐะฝ ะฝะฐ ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ **OpenAPI**, ะตะณะพ API ะผะพะถะฝะพ ะพะฟะธัะฐั‚ัŒ ะฒ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะผ ั„ะพั€ะผะฐั‚ะต, ะฟะพะฝัั‚ะฝะพะผ ะผะฝะพะถะตัั‚ะฒัƒ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ. -ะญั‚ะพ ัƒะฟั€ะพั‰ะฐะตั‚ ะณะตะฝะตั€ะฐั†ะธัŽ ะฐะบั‚ัƒะฐะปัŒะฝะพะน **ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ**, ะบะปะธะตะฝั‚ัะบะธั… ะฑะธะฑะปะธะพั‚ะตะบ (**SDKs**) ะฝะฐ ั€ะฐะทะฝั‹ั… ัะทั‹ะบะฐั…, ะฐ ั‚ะฐะบะถะต **ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั** ะธะปะธ **ะฒะพั€ะบั„ะปะพัƒ ะฐะฒั‚ะพะผะฐั‚ะธะทะฐั†ะธะธ**, ะบะพั‚ะพั€ั‹ะต ะพัั‚ะฐัŽั‚ัั ัะธะฝั…ั€ะพะฝะธะทะธั€ะพะฒะฐะฝะฝั‹ะผะธ ั ะฒะฐัˆะธะผ ะบะพะดะพะผ. +ะญั‚ะพ ัƒะฟั€ะพั‰ะฐะตั‚ ะณะตะฝะตั€ะฐั†ะธัŽ ะฐะบั‚ัƒะฐะปัŒะฝะพะน **ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ**, ะบะปะธะตะฝั‚ัะบะธั… ะฑะธะฑะปะธะพั‚ะตะบ (**SDKs**) ะฝะฐ ั€ะฐะทะฝั‹ั… ัะทั‹ะบะฐั…, ะฐ ั‚ะฐะบะถะต **ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั** ะธะปะธ **ะฒะพั€ะบั„ะปะพัƒ ะฐะฒั‚ะพะผะฐั‚ะธะทะฐั†ะธะธ**, ะบะพั‚ะพั€ั‹ะต ะพัั‚ะฐัŽั‚ัั ัะธะฝั…ั€ะพะฝะธะทะธั€ะพะฒะฐะฝะฝั‹ะผะธ ั ะฒะฐัˆะธะผ ะบะพะดะพะผ. ะ’ ัั‚ะพะผ ั€ัƒะบะพะฒะพะดัั‚ะฒะต ะฒั‹ ัƒะทะฝะฐะตั‚ะต, ะบะฐะบ ัะณะตะฝะตั€ะธั€ะพะฒะฐั‚ัŒ **TypeScript SDK** ะดะปั ะฒะฐัˆะตะณะพ ะฑัะบะตะฝะดะฐ ะฝะฐ FastAPI. @@ -40,7 +40,7 @@ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะณะตะฝะตั€ะธั€ัƒะตั‚ ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ ะะฐั‡ะฝั‘ะผ ั ะฟั€ะพัั‚ะพะณะพ ะฟั€ะธะปะพะถะตะฝะธั FastAPI: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ)* ะพะฟั€ะตะดะตะปััŽั‚ ะผะพะดะตะปะธ, ะบะพั‚ะพั€ั‹ะต ะพะฝะธ ะธัะฟะพะปัŒะทัƒัŽั‚ ะดะปั ะฟะพะปะตะทะฝะพะน ะฝะฐะณั€ัƒะทะบะธ ะทะฐะฟั€ะพัะฐ ะธ ะฟะพะปะตะทะฝะพะน ะฝะฐะณั€ัƒะทะบะธ ะพั‚ะฒะตั‚ะฐ, ั ะฟะพะผะพั‰ัŒัŽ ะผะพะดะตะปะตะน `Item` ะธ `ResponseMessage`. @@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ะะฐะฟั€ะธะผะตั€, ัƒ ะฒะฐั ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั€ะฐะทะดะตะป ะดะปั **items** ะธ ะดั€ัƒะณะพะน ั€ะฐะทะดะตะป ะดะปั **users**, ะธ ะพะฝะธ ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ั€ะฐะทะดะตะปะตะฝั‹ ั‚ะตะณะฐะผะธ: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### ะ“ะตะฝะตั€ะฐั†ะธั TypeScriptโ€‘ะบะปะธะตะฝั‚ะฐ ั ั‚ะตะณะฐะผะธ { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ FastAPI ะธัะฟะพะปัŒะทัƒะตั‚ **ัƒะฝะธะบะฐะปัŒะฝั‹ะน ID** ะดะปั ะบะฐะถะดะพะน *ะพ ะ—ะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ัŒ ัั‚ัƒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบัƒัŽ ั„ัƒะฝะบั†ะธัŽ ะฒ **FastAPI** ั‡ะตั€ะตะท ะฟะฐั€ะฐะผะตั‚ั€ `generate_unique_id_function`: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### ะ“ะตะฝะตั€ะฐั†ะธั TypeScriptโ€‘ะบะปะธะตะฝั‚ะฐ ั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะผะธ ID ะพะฟะตั€ะฐั†ะธะน { #generate-a-typescript-client-with-custom-operation-ids } @@ -157,7 +157,7 @@ FastAPI ะธัะฟะพะปัŒะทัƒะตั‚ **ัƒะฝะธะบะฐะปัŒะฝั‹ะน ID** ะดะปั ะบะฐะถะดะพะน *ะพ ### ะŸั€ะตะดะพะฑั€ะฐะฑะพั‚ะบะฐ ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OpenAPI ะดะปั ะณะตะฝะตั€ะฐั‚ะพั€ะฐ ะบะปะธะตะฝั‚ะฐ { #preprocess-the-openapi-specification-for-the-client-generator } -ะกะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะผ ะบะพะดะต ะฒัั‘ ะตั‰ั‘ ะตัั‚ัŒ **ะดัƒะฑะปะธั€ัƒัŽั‰ะฐััั ะธะฝั„ะพั€ะผะฐั†ะธั**. +ะ’ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะผ ะบะพะดะต ะฒัั‘ ะตั‰ั‘ ะตัั‚ัŒ **ะดัƒะฑะปะธั€ัƒัŽั‰ะฐััั ะธะฝั„ะพั€ะผะฐั†ะธั**. ะœั‹ ัƒะถะต ะทะฝะฐะตะผ, ั‡ั‚ะพ ัั‚ะพั‚ ะผะตั‚ะพะด ะพั‚ะฝะพัะธั‚ัั ะบ **items**, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัั‚ะพ ัะปะพะฒะพ ะตัั‚ัŒ ะฒ `ItemsService` (ะฒะทัั‚ะพ ะธะท ั‚ะตะณะฐ), ะฝะพ ะฟั€ะธ ัั‚ะพะผ ะธะผั ั‚ะตะณะฐ ะฒัั‘ ะตั‰ั‘ ะดะพะฑะฐะฒะปะตะฝะพ ะฟั€ะตั„ะธะบัะพะผ ะบ ะธะผะตะฝะธ ะผะตั‚ะพะดะฐ. ๐Ÿ˜• @@ -167,7 +167,7 @@ FastAPI ะธัะฟะพะปัŒะทัƒะตั‚ **ัƒะฝะธะบะฐะปัŒะฝั‹ะน ID** ะดะปั ะบะฐะถะดะพะน *ะพ ะœั‹ ะผะพะถะตะผ ัะบะฐั‡ะฐั‚ัŒ OpenAPI JSON ะฒ ั„ะฐะนะป `openapi.json`, ะฐ ะทะฐั‚ะตะผ **ัƒะฑั€ะฐั‚ัŒ ัั‚ะพั‚ ะฟั€ะตั„ะธะบัโ€‘ั‚ะตะณ** ั‚ะฐะบะธะผ ัะบั€ะธะฟั‚ะพะผ: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md index 5ebe010782..034feae7eb 100644 --- a/docs/ru/docs/advanced/middleware.md +++ b/docs/ru/docs/advanced/middleware.md @@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ะ›ัŽะฑะพะน ะฒั…ะพะดัั‰ะธะน ะทะฐะฟั€ะพั ะฟะพ `http` ะธะปะธ `ws` ะฑัƒะดะตั‚ ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝ ะฝะฐ ะฑะตะทะพะฟะฐัะฝัƒัŽ ัั…ะตะผัƒ. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } ะ“ะฐั€ะฐะฝั‚ะธั€ัƒะตั‚, ั‡ั‚ะพ ะฒะพ ะฒัะตั… ะฒั…ะพะดัั‰ะธั… ะทะฐะฟั€ะพัะฐั… ะบะพั€ั€ะตะบั‚ะฝะพ ัƒัั‚ะฐะฝะพะฒะปะตะฝ `Host`โ€‘ะทะฐะณะพะปะพะฒะพะบ, ั‡ั‚ะพะฑั‹ ะทะฐั‰ะธั‚ะธั‚ัŒัั ะพั‚ ะฐั‚ะฐะบ ะฝะฐ HTTPโ€‘ะทะฐะณะพะปะพะฒะพะบ Host. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} ะŸะพะดะดะตั€ะถะธะฒะฐัŽั‚ัั ัะปะตะดัƒัŽั‰ะธะต ะฐั€ะณัƒะผะตะฝั‚ั‹: @@ -78,7 +78,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ะญั‚ะพ middleware ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ ะบะฐะบ ะพะฑั‹ั‡ะฝั‹ะต, ั‚ะฐะบ ะธ ะฟะพั‚ะพะบะพะฒั‹ะต ะพั‚ะฒะตั‚ั‹. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} ะŸะพะดะดะตั€ะถะธะฒะฐัŽั‚ัั ัะปะตะดัƒัŽั‰ะธะต ะฐั€ะณัƒะผะตะฝั‚ั‹: diff --git a/docs/ru/docs/advanced/openapi-webhooks.md b/docs/ru/docs/advanced/openapi-webhooks.md index 3a2b9fff74..b477075c11 100644 --- a/docs/ru/docs/advanced/openapi-webhooks.md +++ b/docs/ru/docs/advanced/openapi-webhooks.md @@ -16,9 +16,9 @@ ะ’ัั ะปะพะณะธะบะฐ ั€ะตะณะธัั‚ั€ะฐั†ะธะธ URL-ะฐะดั€ะตัะพะฒ ะดะปั ะฒะตะฑั…ัƒะบะพะฒ ะธ ะบะพะด, ะบะพั‚ะพั€ั‹ะน ั€ะตะฐะปัŒะฝะพ ะพั‚ะฟั€ะฐะฒะปัะตั‚ ัั‚ะธ ะทะฐะฟั€ะพัั‹, ั†ะตะปะธะบะพะผ ะฝะฐ ะฒะฐัˆะตะน ัั‚ะพั€ะพะฝะต. ะ’ั‹ ะฟะธัˆะตั‚ะต ัั‚ะพ ั‚ะฐะบ, ะบะฐะบ ะฒะฐะผ ะฝัƒะถะฝะพ, ะฒ ัะฒะพะตะผ ัะพะฑัั‚ะฒะตะฝะฝะพะผ ะบะพะดะต. -## ะ”ะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต ะฒะตะฑั…ัƒะบะพะฒ ั ะฟะพะผะพั‰ัŒัŽ FastAPI ะธ OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } +## ะ”ะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธะต ะฒะตะฑั…ัƒะบะพะฒ ั ะฟะพะผะพั‰ัŒัŽ **FastAPI** ะธ OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } -ะก FastAPI, ะธัะฟะพะปัŒะทัƒั OpenAPI, ะฒั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะธะผะตะฝะฐ ัั‚ะธั… ะฒะตะฑั…ัƒะบะพะฒ, ั‚ะธะฟั‹ HTTP-ะพะฟะตั€ะฐั†ะธะน, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะผะพะถะตั‚ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ (ะฝะฐะฟั€ะธะผะตั€, `POST`, `PUT` ะธ ั‚.ะด.), ะฐ ั‚ะฐะบะถะต ั‚ะตะปะฐ ะทะฐะฟั€ะพัะพะฒ, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะฑัƒะดะตั‚ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ. +ะก **FastAPI**, ะธัะฟะพะปัŒะทัƒั OpenAPI, ะฒั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะธะผะตะฝะฐ ัั‚ะธั… ะฒะตะฑั…ัƒะบะพะฒ, ั‚ะธะฟั‹ HTTP-ะพะฟะตั€ะฐั†ะธะน, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะผะพะถะตั‚ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ (ะฝะฐะฟั€ะธะผะตั€, `POST`, `PUT` ะธ ั‚.ะด.), ะฐ ั‚ะฐะบะถะต ั‚ะตะปะฐ ะทะฐะฟั€ะพัะพะฒ, ะบะพั‚ะพั€ั‹ะต ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะฑัƒะดะตั‚ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ. ะญั‚ะพ ะทะฝะฐั‡ะธั‚ะตะปัŒะฝะพ ัƒะฟั€ะพัั‚ะธั‚ ะฒะฐัˆะธะผ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัะผ ั€ะตะฐะปะธะทะฐั†ะธัŽ ะธั… API ะดะปั ะฟั€ะธะตะผะฐ ะฒะฐัˆะธั… ะฒะตะฑั…ัƒะบ-ะทะฐะฟั€ะพัะพะฒ; ะฒะพะทะผะพะถะฝะพ, ะพะฝะธ ะดะฐะถะต ัะผะพะณัƒั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐั‚ัŒ ั‡ะฐัั‚ัŒ ะบะพะดะฐ ัะฒะพะตะณะพ API. @@ -32,7 +32,7 @@ ะŸั€ะธ ัะพะทะดะฐะฝะธะธ ะฟั€ะธะปะพะถะตะฝะธั ะฝะฐ **FastAPI** ะตัั‚ัŒ ะฐั‚ั€ะธะฑัƒั‚ `webhooks`, ั ะฟะพะผะพั‰ัŒัŽ ะบะพั‚ะพั€ะพะณะพ ะผะพะถะฝะพ ะพะฑัŠัะฒะปัั‚ัŒ ะฒะตะฑั…ัƒะบะธ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ), ะฝะฐะฟั€ะธะผะตั€ ั `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} ะžะฟั€ะตะดะตะปะตะฝะฝั‹ะต ะฒะฐะผะธ ะฒะตะฑั…ัƒะบะธ ะฟะพะฟะฐะดัƒั‚ ะฒ ัั…ะตะผัƒ **OpenAPI** ะธ ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะน **ะธะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ**. diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md index 86d3a5b630..b8c879bf6f 100644 --- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ ะัƒะถะฝะพ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ะพะฝ ัƒะฝะธะบะฐะปะตะฝ ะดะปั ะบะฐะถะดะพะน ะพะฟะตั€ะฐั†ะธะธ. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะธะผะตะฝะธ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ* ะบะฐะบ operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ ะ”ะตะปะฐั‚ัŒ ัั‚ะพ ัะปะตะดัƒะตั‚ ะฟะพัะปะต ะดะพะฑะฐะฒะปะตะฝะธั ะฒัะตั… *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | ะกะพะฒะตั‚ @@ -40,7 +40,7 @@ ะงั‚ะพะฑั‹ ะธัะบะปัŽั‡ะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะธะท ะณะตะฝะตั€ะธั€ัƒะตะผะพะน ัั…ะตะผั‹ OpenAPI (ะฐ ะทะฝะฐั‡ะธั‚, ะธ ะธะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธั… ัะธัั‚ะตะผ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ), ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `include_in_schema` ะธ ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะตะณะพ ะฒ `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## ะ ะฐััˆะธั€ะตะฝะฝะพะต ะพะฟะธัะฐะฝะธะต ะธะท docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ `openapi_extra` ะผะพะถะตั‚ ะฟั€ะธะณะพะดะธั‚ัŒัั, ะฝะฐะฟั€ะธะผะตั€, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะธั‚ัŒ [ะ ะฐััˆะธั€ะตะฝะธั OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} ะ•ัะปะธ ะฒั‹ ะพั‚ะบั€ะพะตั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ API, ะฒะฐัˆะต ั€ะฐััˆะธั€ะตะฝะธะต ะฟะพัะฒะธั‚ัั ะฒะฝะธะทัƒ ัั‚ั€ะฐะฝะธั†ั‹ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. @@ -139,9 +139,9 @@ ะญั‚ะพ ะผะพะถะฝะพ ัะดะตะปะฐั‚ัŒ ั ะฟะพะผะพั‰ัŒัŽ `openapi_extra`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะฝะต ะพะฑัŠัะฒะปัะปะธ ะฝะธะบะฐะบัƒัŽ Pydantic-ะผะพะดะตะปัŒ. ะคะฐะบั‚ะธั‡ะตัะบะธ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะดะฐะถะต ะฝะต ั€ะฐัะฟะฐั€ัะตะฝะพ ะบะฐะบ JSON, ะพะฝะพ ั‡ะธั‚ะฐะตั‚ัั ะฝะฐะฟั€ัะผัƒัŽ ะบะฐะบ `bytes`, ะฐ ั„ัƒะฝะบั†ะธั `magic_data_reader()` ะฑัƒะดะตั‚ ะพั‚ะฒะตั‡ะฐั‚ัŒ ะทะฐ ะตะณะพ ะฟะฐั€ัะธะฝะณ ะบะฐะบะธะผ-ั‚ะพ ัะฟะพัะพะฑะพะผ. +ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะฝะต ะพะฑัŠัะฒะปัะปะธ ะฝะธะบะฐะบัƒัŽ Pydantic-ะผะพะดะตะปัŒ. ะคะฐะบั‚ะธั‡ะตัะบะธ ั‚ะตะปะพ ะทะฐะฟั€ะพัะฐ ะดะฐะถะต ะฝะต ั€ะฐัะฟะฐั€ัะตะฝะพ ะบะฐะบ JSON, ะพะฝะพ ั‡ะธั‚ะฐะตั‚ัั ะฝะฐะฟั€ัะผัƒัŽ ะบะฐะบ `bytes`, ะฐ ั„ัƒะฝะบั†ะธั `magic_data_reader()` ะฑัƒะดะตั‚ ะพั‚ะฒะตั‡ะฐั‚ัŒ ะทะฐ ะตะณะพ ะฟะฐั€ัะธะฝะณ ะบะฐะบะธะผ-ั‚ะพ ัะฟะพัะพะฑะพะผ. ะขะตะผ ะฝะต ะผะตะฝะตะต, ะผั‹ ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ ะพะถะธะดะฐะตะผัƒัŽ ัั…ะตะผัƒ ะดะปั ั‚ะตะปะฐ ะทะฐะฟั€ะพัะฐ. @@ -153,7 +153,7 @@ ะะฐะฟั€ะธะผะตั€, ะฒ ัั‚ะพะผ ะฟั€ะธะปะพะถะตะฝะธะธ ะผั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตะผ ะฒัั‚ั€ะพะตะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ FastAPI ะดะปั ะธะทะฒะปะตั‡ะตะฝะธั JSON Schema ะธะท ะผะพะดะตะปะตะน Pydantic, ั€ะฐะฒะฝะพ ะบะฐะบ ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ JSON. ะœั‹ ะพะฑัŠัะฒะปัะตะผ ั‚ะธะฟ ัะพะดะตั€ะถะธะผะพะณะพ HTTP-ะทะฐะฟั€ะพัะฐ ะบะฐะบ YAML, ะฐ ะฝะต JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} ะขะตะผ ะฝะต ะผะตะฝะตะต, ั…ะพั‚ั ะผั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตะผ ะฒัั‚ั€ะพะตะฝะฝัƒัŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ะธัะฟะพะปัŒะทัƒะตะผ Pydantic-ะผะพะดะตะปัŒ, ั‡ั‚ะพะฑั‹ ะฒั€ัƒั‡ะฝัƒัŽ ัะณะตะฝะตั€ะธั€ะพะฒะฐั‚ัŒ JSON Schema ะดะปั ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะผั‹ ั…ะพั‚ะธะผ ะฟะพะปัƒั‡ะธั‚ัŒ ะฒ YAML. @@ -161,7 +161,7 @@ ะ ะทะฐั‚ะตะผ ะฒ ะฝะฐัˆะตะผ ะบะพะดะต ะผั‹ ะฝะฐะฟั€ัะผัƒัŽ ะฟะฐั€ัะธะผ ัั‚ะพ ัะพะดะตั€ะถะธะผะพะต YAML ะธ ัะฝะพะฒะฐ ะธัะฟะพะปัŒะทัƒะตะผ ั‚ัƒ ะถะต Pydantic-ะผะพะดะตะปัŒ, ั‡ั‚ะพะฑั‹ ะฒะฐะปะธะดะธั€ะพะฒะฐั‚ัŒ YAML-ัะพะดะตั€ะถะธะผะพะต: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md index 85d9050ffc..273862bae9 100644 --- a/docs/ru/docs/advanced/response-change-status-code.md +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -20,7 +20,7 @@ ะ˜ ะทะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ `status_code` ะฒ ัั‚ะพะผ *ะฒั€ะตะผะตะฝะฝะพะผ* ะพะฑัŠะตะบั‚ะต ะพั‚ะฒะตั‚ะฐ. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} ะŸะพัะปะต ัั‚ะพะณะพ ะฒั‹ ะผะพะถะตั‚ะต ะฒะตั€ะฝัƒั‚ัŒ ะปัŽะฑะพะน ะพะฑัŠะตะบั‚, ะบะพั‚ะพั€ั‹ะน ะฒะฐะผ ะฝัƒะถะตะฝ, ะบะฐะบ ะพะฑั‹ั‡ะฝะพ (`dict`, ะผะพะดะตะปัŒ ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะด.). diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md index 2872d6c0ad..d3662ef8ed 100644 --- a/docs/ru/docs/advanced/response-cookies.md +++ b/docs/ru/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ ะ—ะฐั‚ะตะผ ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ cookies ะฒ ัั‚ะพะผ ะฒั€ะตะผะตะฝะฝะพะผ ะพะฑัŠะตะบั‚ะต ะพั‚ะฒะตั‚ะฐ. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} ะŸะพัะปะต ัั‚ะพะณะพ ะผะพะถะฝะพ ะฒะตั€ะฝัƒั‚ัŒ ะปัŽะฑะพะน ะพะฑัŠะตะบั‚, ะบะฐะบ ะธ ั€ะฐะฝัŒัˆะต (ะฝะฐะฟั€ะธะผะตั€, `dict`, ะพะฑัŠะตะบั‚ ะผะพะดะตะปะธ ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั… ะธ ั‚ะฐะบ ะดะฐะปะตะต). @@ -24,7 +24,7 @@ ะ—ะฐั‚ะตะผ ัƒัั‚ะฐะฝะพะฒะธั‚ะต cookies ะธ ะฒะตั€ะฝะธั‚ะต ัั‚ะพั‚ ะพะฑัŠะตะบั‚: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md index b452810714..60facdd857 100644 --- a/docs/ru/docs/advanced/response-directly.md +++ b/docs/ru/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะฟะพะผะตัั‚ะธั‚ัŒ ะฒะฐัˆ XML-ะบะพะฝั‚ะตะฝั‚ ะฒ ัั‚ั€ะพะบัƒ, ะฟะพะผะตัั‚ะธั‚ัŒ ะตั‘ ะฒ `Response` ะธ ะฒะตั€ะฝัƒั‚ัŒ: -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ## ะŸั€ะธะผะตั‡ะฐะฝะธั { #notes } diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index 8f24f05b07..dc821983bc 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -6,7 +6,7 @@ ะ ะทะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ัƒัั‚ะฐะฝะฐะฒะปะธะฒะฐั‚ัŒ HTTP-ะทะฐะณะพะปะพะฒะบะธ ะฒ ัั‚ะพะผ *ะฒั€ะตะผะตะฝะฝะพะผ* ะพะฑัŠะตะบั‚ะต ะพั‚ะฒะตั‚ะฐ. -{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} ะŸะพัะปะต ัั‚ะพะณะพ ะฒั‹ ะผะพะถะตั‚ะต ะฒะตั€ะฝัƒั‚ัŒ ะปัŽะฑะพะน ะฝัƒะถะฝั‹ะน ะพะฑัŠะตะบั‚, ะบะฐะบ ะพะฑั‹ั‡ะฝะพ (ะฝะฐะฟั€ะธะผะตั€, `dict`, ะผะพะดะตะปัŒ ะธะท ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะด.). @@ -22,7 +22,7 @@ ะกะพะทะดะฐะนั‚ะต ะพั‚ะฒะตั‚, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะฒ [ะ’ะตั€ะฝัƒั‚ัŒ Response ะฝะฐะฟั€ัะผัƒัŽ](response-directly.md){.internal-link target=_blank}, ะธ ะฟะตั€ะตะดะฐะนั‚ะต ะทะฐะณะพะปะพะฒะบะธ ะบะฐะบ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะน ะฟะฐั€ะฐะผะตั‚ั€: -{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ diff --git a/docs/ru/docs/advanced/security/http-basic-auth.md b/docs/ru/docs/advanced/security/http-basic-auth.md index 41e62d4bf3..a6bfb7c546 100644 --- a/docs/ru/docs/advanced/security/http-basic-auth.md +++ b/docs/ru/docs/advanced/security/http-basic-auth.md @@ -20,7 +20,7 @@ * ะžะฝะฐ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะพะฑัŠะตะบั‚ ั‚ะธะฟะฐ `HTTPBasicCredentials`: * ะžะฝ ัะพะดะตั€ะถะธั‚ ะพั‚ะฟั€ะฐะฒะปะตะฝะฝั‹ะต `username` ะธ `password`. -{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} ะšะพะณะดะฐ ะฒั‹ ะฒะฟะตั€ะฒั‹ะต ะพั‚ะบั€ะพะตั‚ะต URL (ะธะปะธ ะฝะฐะถะผั‘ั‚ะต ะบะฝะพะฟะบัƒ ยซExecuteยป ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ), ะฑั€ะฐัƒะทะตั€ ะฟะพะฟั€ะพัะธั‚ ะฒะฒะตัั‚ะธ ะธะผั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะธ ะฟะฐั€ะพะปัŒ: @@ -40,7 +40,7 @@ ะ—ะฐั‚ะตะผ ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `secrets.compare_digest()`, ั‡ั‚ะพะฑั‹ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ `credentials.username` ั€ะฐะฒะตะฝ `"stanleyjobson"`, ะฐ `credentials.password` โ€” `"swordfish"`. -{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} ะญั‚ะพ ะฑั‹ะปะพ ะฑั‹ ะฟะพั…ะพะถะต ะฝะฐ: @@ -104,4 +104,4 @@ Pythonัƒ ะฟั€ะธะดั‘ั‚ัั ัั€ะฐะฒะฝะธั‚ัŒ ะฒะตััŒ ะพะฑั‰ะธะน ะฟั€ะตั„ะธะบั `s ะŸะพัะปะต ั‚ะพะณะพ ะบะฐะบ ะพะฑะฝะฐั€ัƒะถะตะฝะพ, ั‡ั‚ะพ ัƒั‡ั‘ั‚ะฝั‹ะต ะดะฐะฝะฝั‹ะต ะฝะตะบะพั€ั€ะตะบั‚ะฝั‹, ะฒะตั€ะฝะธั‚ะต `HTTPException` ัะพ ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ ะพั‚ะฒะตั‚ะฐ 401 (ั‚ะตะผ ะถะต, ั‡ั‚ะพ ะธ ะฟั€ะธ ะพั‚ััƒั‚ัั‚ะฒะธะธ ัƒั‡ั‘ั‚ะฝั‹ั… ะดะฐะฝะฝั‹ั…) ะธ ะดะพะฑะฐะฒัŒั‚ะต HTTP-ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate`, ั‡ั‚ะพะฑั‹ ะฑั€ะฐัƒะทะตั€ ัะฝะพะฒะฐ ะฟะพะบะฐะทะฐะป ะพะบะฝะพ ะฒั…ะพะดะฐ: -{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index 8408faebff..15537e2b40 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -54,7 +54,7 @@ $ pip install "fastapi[all]" ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒัะต ั‚ะต ะถะต ะฒะพะทะผะพะถะฝะพัั‚ะธ ะฒะฐะปะธะดะฐั†ะธะธ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ั‡ั‚ะพ ะธ ะดะปั Pydanticโ€‘ะผะพะดะตะปะตะน, ะฝะฐะฟั€ะธะผะตั€ ั€ะฐะทะฝั‹ะต ั‚ะธะฟั‹ ะดะฐะฝะฝั‹ั… ะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝัƒัŽ ะฒะฐะปะธะดะฐั†ะธัŽ ั‡ะตั€ะตะท `Field()`. -{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} /// tip | ะกะพะฒะตั‚ @@ -70,7 +70,7 @@ $ pip install "fastapi[all]" ะ—ะฐั‚ะตะผ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฝะพะฒั‹ะน ะพะฑัŠะตะบั‚ `settings` ะฒ ะฒะฐัˆะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ: -{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} ### ะ—ะฐะฟัƒัะบ ัะตั€ะฒะตั€ะฐ { #run-the-server } @@ -104,11 +104,11 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ะะฐะฟั€ะธะผะตั€, ัƒ ะฒะฐั ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั„ะฐะนะป `config.py` ัะพ ัะปะตะดัƒัŽั‰ะธะผ ัะพะดะตั€ะถะธะผั‹ะผ: -{* ../../docs_src/settings/app01_py39/config.py *} +{* ../../docs_src/settings/app01_py310/config.py *} ะ ะทะฐั‚ะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะตะณะพ ะฒ ั„ะฐะนะปะต `main.py`: -{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} /// tip | ะกะพะฒะตั‚ @@ -126,7 +126,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ะŸั€ะพะดะพะปะถะฐั ะฟั€ะตะดั‹ะดัƒั‰ะธะน ะฟั€ะธะผะตั€, ะฒะฐัˆ ั„ะฐะนะป `config.py` ะผะพะถะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: -{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ั‚ะตะฟะตั€ัŒ ะผั‹ ะฝะต ัะพะทะดะฐะตะผ ัะบะทะตะผะฟะปัั€ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `settings = Settings()`. @@ -134,7 +134,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ะขะตะฟะตั€ัŒ ะผั‹ ัะพะทะดะฐะตะผ ะทะฐะฒะธัะธะผะพัั‚ัŒ, ะบะพั‚ะพั€ะฐั ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะฝะพะฒั‹ะน `config.Settings()`. -{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} /// tip | ะกะพะฒะตั‚ @@ -146,13 +146,13 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ะ—ะฐั‚ะตะผ ะผั‹ ะผะพะถะตะผ ะทะฐะฟั€ะพัะธั‚ัŒ ะตะต ะฒ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ* ะบะฐะบ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะฐะผ, ะณะดะต ะฝัƒะถะฝะพ. -{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} ### ะะฐัั‚ั€ะพะนะบะธ ะธ ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธะต { #settings-and-testing } ะ”ะฐะปะตะต ะฑัƒะดะตั‚ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพ ะฟั€ะตะดะพัั‚ะฐะฒะธั‚ัŒ ะดั€ัƒะณะพะน ะพะฑัŠะตะบั‚ ะฝะฐัั‚ั€ะพะตะบ ะฒะพ ะฒั€ะตะผั ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั, ัะพะทะดะฐะฒ ะฟะตั€ะตะพะฟั€ะตะดะตะปะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะดะปั `get_settings`: -{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} ะ’ ะฟะตั€ะตะพะฟั€ะตะดะตะปะตะฝะธะธ ะทะฐะฒะธัะธะผะพัั‚ะธ ะผั‹ ะทะฐะดะฐะตะผ ะฝะพะฒะพะต ะทะฝะฐั‡ะตะฝะธะต `admin_email` ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะฝะพะฒะพะณะพ ะพะฑัŠะตะบั‚ะฐ `Settings`, ะฐ ะทะฐั‚ะตะผ ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ัั‚ะพั‚ ะฝะพะฒั‹ะน ะพะฑัŠะตะบั‚. @@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" ะ—ะฐั‚ะตะผ ะพะฑะฝะพะฒะธั‚ะต ะฒะฐัˆ `config.py` ั‚ะฐะบ: -{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} /// tip | ะกะพะฒะตั‚ @@ -226,7 +226,7 @@ def get_settings(): ะะพ ั‚ะฐะบ ะบะฐะบ ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะดะตะบะพั€ะฐั‚ะพั€ `@lru_cache` ัะฒะตั€ั…ัƒ, ะพะฑัŠะตะบั‚ `Settings` ะฑัƒะดะตั‚ ัะพะทะดะฐะฝ ั‚ะพะปัŒะบะพ ะพะดะธะฝ ั€ะฐะท โ€” ะฟั€ะธ ะฟะตั€ะฒะพะผ ะฒั‹ะทะพะฒะต. โœ”๏ธ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} ะ—ะฐั‚ะตะผ ะฟั€ะธ ะปัŽะฑั‹ั… ะฟะพัะปะตะดัƒัŽั‰ะธั… ะฒั‹ะทะพะฒะฐั… `get_settings()` ะฒ ะทะฐะฒะธัะธะผะพัั‚ัั… ะดะปั ัะปะตะดัƒัŽั‰ะธั… ะทะฐะฟั€ะพัะพะฒ, ะฒะผะตัั‚ะพ ะฒั‹ะฟะพะปะฝะตะฝะธั ะฒะฝัƒั‚ั€ะตะฝะฝะตะณะพ ะบะพะดะฐ `get_settings()` ะธ ัะพะทะดะฐะฝะธั ะฝะพะฒะพะณะพ ะพะฑัŠะตะบั‚ะฐ `Settings`, ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒัั ั‚ะพั‚ ะถะต ะพะฑัŠะตะบั‚, ั‡ั‚ะพ ะฑั‹ะป ะฒะพะทะฒั€ะฐั‰ะตะฝ ะฟั€ะธ ะฟะตั€ะฒะพะผ ะฒั‹ะทะพะฒะต, ัะฝะพะฒะฐ ะธ ัะฝะพะฒะฐ. diff --git a/docs/ru/docs/advanced/sub-applications.md b/docs/ru/docs/advanced/sub-applications.md index fa5a683f45..4fd5649ce3 100644 --- a/docs/ru/docs/advanced/sub-applications.md +++ b/docs/ru/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ ะกะฝะฐั‡ะฐะปะฐ ัะพะทะดะฐะนั‚ะต ะพัะฝะพะฒะฝะพะต, ะฒะตั€ั…ะฝะตะณะพ ัƒั€ะพะฒะฝั, ะฟั€ะธะปะพะถะตะฝะธะต **FastAPI** ะธ ะตะณะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### ะŸะพะดะฟั€ะธะปะพะถะตะฝะธะต { #sub-application } @@ -18,7 +18,7 @@ ะญั‚ะพ ะฟะพะดะฟั€ะธะปะพะถะตะฝะธะต โ€” ะพะฑั‹ั‡ะฝะพะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะต ะฟั€ะธะปะพะถะตะฝะธะต FastAPI, ะฝะพ ะธะผะตะฝะฝะพ ะพะฝะพ ะฑัƒะดะตั‚ ยซัะผะพะฝั‚ะธั€ะพะฒะฐะฝะพยป: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### ะกะผะพะฝั‚ะธั€ัƒะนั‚ะต ะฟะพะดะฟั€ะธะปะพะถะตะฝะธะต { #mount-the-sub-application } @@ -26,7 +26,7 @@ ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะพะฝะพ ะฑัƒะดะตั‚ ัะผะพะฝั‚ะธั€ะพะฒะฐะฝะพ ะฟะพ ะฟัƒั‚ะธ `/subapi`: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### ะŸั€ะพะฒะตั€ัŒั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ API { #check-the-automatic-api-docs } diff --git a/docs/ru/docs/advanced/templates.md b/docs/ru/docs/advanced/templates.md index 460e2e4660..68adcb5151 100644 --- a/docs/ru/docs/advanced/templates.md +++ b/docs/ru/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 - ะžะฑัŠัะฒะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `Request` ะฒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะบะพั‚ะพั€ะฐั ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ัˆะฐะฑะปะพะฝ. - ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ัะพะทะดะฐะฝะฝั‹ะน `templates`, ั‡ั‚ะพะฑั‹ ะพั‚ั€ะตะฝะดะตั€ะธั‚ัŒ ะธ ะฒะตั€ะฝัƒั‚ัŒ `TemplateResponse`; ะฟะตั€ะตะดะฐะนั‚ะต ะธะผั ัˆะฐะฑะปะพะฝะฐ, ะพะฑัŠะตะบั‚ `request` ะธ ัะปะพะฒะฐั€ัŒ ยซcontextยป ั ะฟะฐั€ะฐะผะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะธะต ะดะปั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะฒะฝัƒั‚ั€ะธ ัˆะฐะฑะปะพะฝะฐ Jinja2. -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต diff --git a/docs/ru/docs/advanced/testing-events.md b/docs/ru/docs/advanced/testing-events.md index 82caea845b..452342cdd2 100644 --- a/docs/ru/docs/advanced/testing-events.md +++ b/docs/ru/docs/advanced/testing-events.md @@ -2,11 +2,11 @@ ะ•ัะปะธ ะฒะฐะผ ะฝัƒะถะฝะพ, ั‡ั‚ะพะฑั‹ `lifespan` ะฒั‹ะฟะพะปะฝัะปัั ะฒ ะฒะฐัˆะธั… ั‚ะตัั‚ะฐั…, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `TestClient` ะฒะผะตัั‚ะต ั ะพะฟะตั€ะฐั‚ะพั€ะพะผ `with`: -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} ะ’ั‹ ะผะพะถะตั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะฟะพะดั€ะพะฑะฝะพัั‚ะตะน ะฒ ัั‚ะฐั‚ัŒะต [ะ—ะฐะฟัƒัะบ lifespan ะฒ ั‚ะตัั‚ะฐั… ะฝะฐ ะพั„ะธั†ะธะฐะปัŒะฝะพะผ ัะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Starlette.](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) ะ”ะปั ัƒัั‚ะฐั€ะตะฒัˆะธั… ัะพะฑั‹ั‚ะธะน `startup` ะธ `shutdown` ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `TestClient` ัะปะตะดัƒัŽั‰ะธะผ ะพะฑั€ะฐะทะพะผ: -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/ru/docs/advanced/testing-websockets.md b/docs/ru/docs/advanced/testing-websockets.md index b6626679e4..f6fa6a04be 100644 --- a/docs/ru/docs/advanced/testing-websockets.md +++ b/docs/ru/docs/advanced/testing-websockets.md @@ -4,7 +4,7 @@ ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต `TestClient` ั ะผะตะฝะตะดะถะตั€ะพะผ ะบะพะฝั‚ะตะบัั‚ะฐ `with`, ะฟะพะดะบะปัŽั‡ะฐัััŒ ะบ WebSocket: -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต diff --git a/docs/ru/docs/advanced/using-request-directly.md b/docs/ru/docs/advanced/using-request-directly.md index cdf500c0e2..0c091cdeda 100644 --- a/docs/ru/docs/advanced/using-request-directly.md +++ b/docs/ru/docs/advanced/using-request-directly.md @@ -29,7 +29,7 @@ ะ”ะปั ัั‚ะพะณะพ ะฝัƒะถะฝะพ ะพะฑั€ะฐั‚ะธั‚ัŒัั ะบ ะทะฐะฟั€ะพััƒ ะฝะฐะฟั€ัะผัƒัŽ. -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} ะ•ัะปะธ ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ* ั ั‚ะธะฟะพะผ `Request`, **FastAPI** ะฟะพะนะผั‘ั‚, ั‡ั‚ะพ ะฝัƒะถะฝะพ ะฟะตั€ะตะดะฐั‚ัŒ ะพะฑัŠะตะบั‚ `Request` ะฒ ัั‚ะพั‚ ะฟะฐั€ะฐะผะตั‚ั€. diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md index fa5e4738eb..446cc2505e 100644 --- a/docs/ru/docs/advanced/websockets.md +++ b/docs/ru/docs/advanced/websockets.md @@ -38,13 +38,13 @@ $ pip install websockets ะ”ะปั ะฟั€ะธะผะตั€ะฐ ะฝะฐะผ ะฝัƒะถะตะฝ ะฝะฐะธะฑะพะปะตะต ะฟั€ะพัั‚ะพะน ัะฟะพัะพะฑ, ะบะพั‚ะพั€ั‹ะน ะฟะพะทะฒะพะปะธั‚ ัะพัั€ะตะดะพั‚ะพั‡ะธั‚ัŒัั ะฝะฐ ัะตั€ะฒะตั€ะฝะพะน ั‡ะฐัั‚ะธ ะฒะตะฑโ€‘ัะพะบะตั‚ะพะฒ ะธ ะฟะพะปัƒั‡ะธั‚ัŒ ั€ะฐะฑะพั‡ะธะน ะบะพะด: -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## ะกะพะทะดะฐะฝะธะต `websocket` { #create-a-websocket } ะกะพะทะดะฐะนั‚ะต `websocket` ะฒ ัะฒะพะตะผ **FastAPI** ะฟั€ะธะปะพะถะตะฝะธะธ: -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ @@ -58,7 +58,7 @@ $ pip install websockets ะงะตั€ะตะท ัะฝะดะฟะพะธะฝั‚ ะฒะตะฑ-ัะพะบะตั‚ะฐ ะฒั‹ ะผะพะถะตั‚ะต ะฟะพะปัƒั‡ะฐั‚ัŒ ะธ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ ัะพะพะฑั‰ะตะฝะธั. -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} ะ’ั‹ ะผะพะถะตั‚ะต ะฟะพะปัƒั‡ะฐั‚ัŒ ะธ ะพั‚ะฟั€ะฐะฒะปัั‚ัŒ ะดะฒะพะธั‡ะฝั‹ะต, ั‚ะตะบัั‚ะพะฒั‹ะต ะธ JSON ะดะฐะฝะฝั‹ะต. @@ -154,7 +154,7 @@ $ fastapi dev main.py ะ•ัะปะธ ะฒะตะฑ-ัะพะบะตั‚ ัะพะตะดะธะฝะตะฝะธะต ะทะฐะบั€ั‹ั‚ะพ, ั‚ะพ `await websocket.receive_text()` ะฒั‹ะทะพะฒะตั‚ ะธัะบะปัŽั‡ะตะฝะธะต `WebSocketDisconnect`, ะบะพั‚ะพั€ะพะต ะผะพะถะฝะพ ะฟะพะนะผะฐั‚ัŒ ะธ ะพะฑั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะฐะบ ะฒ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต: -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} ะงั‚ะพะฑั‹ ะฒะพัะฟั€ะพะธะทะฒะตัั‚ะธ ะฟั€ะธะผะตั€: diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index 41d3a169c7..aa630c228e 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ ะŸะพัะปะต ัั‚ะพะณะพ ัะผะพะฝั‚ะธั€ัƒะนั‚ะต ะตะณะพ ะฝะฐ ะฟัƒั‚ัŒ. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md index 17b54aad2f..1f713c3f39 100644 --- a/docs/ru/docs/alternatives.md +++ b/docs/ru/docs/alternatives.md @@ -137,7 +137,7 @@ def read_url(): ### Marshmallow { #marshmallow } -ะžะดะฝะฐ ะธะท ะพัะฝะพะฒะฝั‹ั… ะฒะพะทะผะพะถะฝะพัั‚ะตะน, ะฝัƒะถะฝั‹ั… ัะธัั‚ะตะผะฐะผ API, โ€” ยซัะตั€ะธะฐะปะธะทะฐั†ะธัยป ะดะฐะฝะฝั‹ั…, ั‚ะพ ะตัั‚ัŒ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั… ะธะท ะบะพะดะฐ (Python) ะฒะพ ั‡ั‚ะพ-ั‚ะพ, ั‡ั‚ะพ ะผะพะถะฝะพ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ ะฟะพ ัะตั‚ะธ. ะะฐะฟั€ะธะผะตั€, ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะพะฑัŠะตะบั‚ะฐ ั ะดะฐะฝะฝั‹ะผะธ ะธะท ะฑะฐะทั‹ ะฒ JSON-ะพะฑัŠะตะบั‚. ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะพะฑัŠะตะบั‚ะพะฒ `datetime` ะฒ ัั‚ั€ะพะบะธ ะธ ั‚. ะฟ. +ะžะดะฝะฐ ะธะท ะพัะฝะพะฒะฝั‹ั… ะฒะพะทะผะพะถะฝะพัั‚ะตะน, ะฝัƒะถะฝั‹ั… ัะธัั‚ะตะผะฐะผ API, โ€” ยซัะตั€ะธะฐะปะธะทะฐั†ะธัยป ะดะฐะฝะฝั‹ั…, ั‚ะพ ะตัั‚ัŒ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั… ะธะท ะบะพะดะฐ (Python) ะฒะพ ั‡ั‚ะพ-ั‚ะพ, ั‡ั‚ะพ ะผะพะถะฝะพ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ ะฟะพ ัะตั‚ะธ. ะะฐะฟั€ะธะผะตั€, ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะพะฑัŠะตะบั‚ะฐ ั ะดะฐะฝะฝั‹ะผะธ ะธะท ะฑะฐะทั‹ ะฒ JSON-ะพะฑัŠะตะบั‚. ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะพะฑัŠะตะบั‚ะพะฒ `datetime` ะฒ ัั‚ั€ะพะบะธ ะธ ั‚. ะฟ. ะ•ั‰ั‘ ะพะดะฝะฐ ะฒะฐะถะฝะฐั ะฒะพะทะผะพะถะฝะพัั‚ัŒ, ะฒะพัั‚ั€ะตะฑะพะฒะฐะฝะฝะฐั API, โ€” ะฒะฐะปะธะดะฐั†ะธั ะดะฐะฝะฝั‹ั…: ัƒะฑะตะถะดะฐั‚ัŒัั, ั‡ั‚ะพ ะดะฐะฝะฝั‹ะต ะฒะฐะปะธะดะฝั‹ ั ัƒั‡ั‘ั‚ะพะผ ะทะฐะดะฐะฝะฝั‹ั… ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ. ะะฐะฟั€ะธะผะตั€, ั‡ั‚ะพ ะบะฐะบะพะต-ั‚ะพ ะฟะพะปะต โ€” `int`, ะฐ ะฝะต ะฟั€ะพะธะทะฒะพะปัŒะฝะฐั ัั‚ั€ะพะบะฐ. ะญั‚ะพ ะพัะพะฑะตะฝะฝะพ ะฟะพะปะตะทะฝะพ ะดะปั ะฒั…ะพะดัั‰ะธั… ะดะฐะฝะฝั‹ั…. @@ -145,7 +145,7 @@ def read_url(): ะ˜ะผะตะฝะฝะพ ะดะปั ัั‚ะธั… ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะธ ะฑั‹ะป ัะพะทะดะฐะฝ Marshmallow. ะญั‚ะพ ะพั‚ะปะธั‡ะฝะฐั ะฑะธะฑะปะธะพั‚ะตะบะฐ, ั ะผะฝะพะณะพ ะตะน ะฟะพะปัŒะทะพะฒะฐะปัั ั€ะฐะฝัŒัˆะต. -ะะพ ะพะฝะฐ ะฟะพัะฒะธะปะฐััŒ ะดะพ ั‚ะพะณะพ, ะบะฐะบ ะฒ Python ะฟะพัะฒะธะปะธััŒ ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ. ะŸะพัั‚ะพะผัƒ ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะบะฐะถะดะพะน ัั…ะตะผั‹ ะฝัƒะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัะฟะตั†ะธะฐะปัŒะฝั‹ะต ัƒั‚ะธะปะธั‚ั‹ ะธ ะบะปะฐััั‹, ะฟั€ะตะดะพัั‚ะฐะฒะปัะตะผั‹ะต Marshmallow. +ะะพ ะพะฝะฐ ะฟะพัะฒะธะปะฐััŒ ะดะพ ั‚ะพะณะพ, ะบะฐะบ ะฒ Python ะฟะพัะฒะธะปะธััŒ ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ. ะŸะพัั‚ะพะผัƒ ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะบะฐะถะดะพะน ัั…ะตะผั‹ ะฝัƒะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัะฟะตั†ะธะฐะปัŒะฝั‹ะต ัƒั‚ะธะปะธั‚ั‹ ะธ ะบะปะฐััั‹, ะฟั€ะตะดะพัั‚ะฐะฒะปัะตะผั‹ะต Marshmallow. /// check | ะ’ะดะพั…ะฝะพะฒะธะปะพ **FastAPI** ะฝะฐ @@ -155,7 +155,7 @@ def read_url(): ### Webargs { #webargs } -ะ•ั‰ั‘ ะพะดะฝะฐ ะฒะฐะถะฝะฐั ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะปั API โ€” ะฟะฐั€ัะธะฝะณ ะดะฐะฝะฝั‹ั… ะธะท ะฒั…ะพะดัั‰ะธั… HTTP-ะทะฐะฟั€ะพัะพะฒ. +ะ•ั‰ั‘ ะพะดะฝะฐ ะฒะฐะถะฝะฐั ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะปั API โ€” ะฟะฐั€ัะธะฝะณ ะดะฐะฝะฝั‹ั… ะธะท ะฒั…ะพะดัั‰ะธั… HTTP-ะทะฐะฟั€ะพัะพะฒ. Webargs โ€” ัั‚ะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚, ัะพะทะดะฐะฝะฝั‹ะน ะดะปั ัั‚ะพะณะพ ะฟะพะฒะตั€ั… ะฝะตัะบะพะปัŒะบะธั… ั„ั€ะตะนะผะฒะพั€ะบะพะฒ, ะฒะบะปัŽั‡ะฐั Flask. @@ -245,7 +245,7 @@ Flask-apispec ะฑั‹ะป ัะพะทะดะฐะฝ ั‚ะตะผะธ ะถะต ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะฐะผะธ, ั‡ ะ’ ะฝั‘ะผ ะฒัั‚ั€ะพะตะฝะฐ ัะธัั‚ะตะผะฐ ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน, ะฒะดะพั…ะฝะพะฒะปั‘ะฝะฝะฐั Angular 2. ะขั€ะตะฑัƒะตั‚ัั ะฟั€ะตะดะฒะฐั€ะธั‚ะตะปัŒะฝะฐั ั€ะตะณะธัั‚ั€ะฐั†ะธั ยซะธะฝะถะตะบั‚ะธั€ัƒะตะผั‹ั…ยป ะบะพะผะฟะพะฝะตะฝั‚ะพะฒ (ะบะฐะบ ะธ ะฒะพ ะฒัะตั… ะธะทะฒะตัั‚ะฝั‹ั… ะผะฝะต ัะธัั‚ะตะผะฐั… ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน), ั‡ั‚ะพ ะดะพะฑะฐะฒะปัะตั‚ ะผะฝะพะณะพัะปะพะฒะฝะพัั‚ะธ ะธ ะฟะพะฒั‚ะพั€ัะตะผะพัั‚ะธ ะบะพะดะฐ. -ะŸะพัะบะพะปัŒะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะพะฟะธัั‹ะฒะฐัŽั‚ัั ั ะฟะพะผะพั‰ัŒัŽ ั‚ะธะฟะพะฒ TypeScript (ะฐะฝะฐะปะพะณ ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ ะฒ Python), ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะฒะตััŒะผะฐ ั…ะพั€ะพัˆะฐ. +ะŸะพัะบะพะปัŒะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะพะฟะธัั‹ะฒะฐัŽั‚ัั ั ะฟะพะผะพั‰ัŒัŽ ั‚ะธะฟะพะฒ TypeScript (ะฐะฝะฐะปะพะณ ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ ะฒ Python), ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ ะฒะตััŒะผะฐ ั…ะพั€ะพัˆะฐ. ะะพ ั‚ะฐะบ ะบะฐะบ ะดะฐะฝะฝั‹ะต ะพ ั‚ะธะฟะฐั… TypeScript ะฝะต ัะพั…ั€ะฐะฝััŽั‚ัั ะฟะพัะปะต ะบะพะผะฟะธะปัั†ะธะธ ะฒ JavaScript, ะพะฝ ะฝะต ะผะพะถะตั‚ ะฟะพะปะฐะณะฐั‚ัŒัั ะฝะฐ ั‚ะธะฟั‹ ะดะปั ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพะณะพ ะพะฟั€ะตะดะตะปะตะฝะธั ะฒะฐะปะธะดะฐั†ะธะธ, ัะตั€ะธะฐะปะธะทะฐั†ะธะธ ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. ะ˜ะทโ€‘ะทะฐ ัั‚ะพะณะพ ะธ ะฝะตะบะพั‚ะพั€ั‹ั… ะฟั€ะพะตะบั‚ะฝั‹ั… ั€ะตัˆะตะฝะธะน ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะฒะฐะปะธะดะฐั†ะธะธ, ัะตั€ะธะฐะปะธะทะฐั†ะธะธ ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะณะตะฝะตั€ะฐั†ะธะธ ัั…ะตะผ ะฟั€ะธั…ะพะดะธั‚ัั ะดะพะฑะฐะฒะปัั‚ัŒ ะดะตะบะพั€ะฐั‚ะพั€ั‹ ะฒะพ ะผะฝะพะณะธั… ะผะตัั‚ะฐั…. ะ’ ะธั‚ะพะณะต ัั‚ะพ ัั‚ะฐะฝะพะฒะธั‚ัั ะดะพะฒะพะปัŒะฝะพ ะผะฝะพะณะพัะปะพะฒะฝั‹ะผ. @@ -359,7 +359,7 @@ Hug ะฒะดะพั…ะฝะพะฒะธะป **FastAPI** ะพะฑัŠัะฒะปัั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `response ะ’ ะฝั‘ะผ ะฑั‹ะปะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะต ะฒะฐะปะธะดะฐั†ะธั ะดะฐะฝะฝั‹ั…, ัะตั€ะธะฐะปะธะทะฐั†ะธั ะดะฐะฝะฝั‹ั… ะธ ะณะตะฝะตั€ะฐั†ะธั ัั…ะตะผั‹ OpenAPI ะฝะฐ ะพัะฝะพะฒะต ั‚ะตั… ะถะต ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะผะตัั‚ะฐั…. -ะžะฟั€ะตะดะตะปะตะฝะธะต ัั…ะตะผั‹ ั‚ะตะปะฐ ะทะฐะฟั€ะพัะฐ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐะปะพ ั‚ะต ะถะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ Python, ะบะฐะบ ะฒ Pydantic, โ€” ัั‚ะพ ะฑั‹ะปะพ ะฑะปะธะถะต ะบ Marshmallow, ะฟะพัั‚ะพะผัƒ ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะฑั‹ะปะฐ ะฑั‹ ั…ัƒะถะต, ะฝะพ ะฒัั‘ ั€ะฐะฒะฝะพ APIStar ะพัั‚ะฐะฒะฐะปัั ะปัƒั‡ัˆะธะผ ะดะพัั‚ัƒะฟะฝั‹ะผ ะฒะฐั€ะธะฐะฝั‚ะพะผ. +ะžะฟั€ะตะดะตะปะตะฝะธะต ัั…ะตะผั‹ ั‚ะตะปะฐ ะทะฐะฟั€ะพัะฐ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐะปะพ ั‚ะต ะถะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ Python, ะบะฐะบ ะฒ Pydantic, โ€” ัั‚ะพ ะฑั‹ะปะพ ะฑะปะธะถะต ะบ Marshmallow, ะฟะพัั‚ะพะผัƒ ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ ะฑั‹ะปะฐ ะฑั‹ ั…ัƒะถะต, ะฝะพ ะฒัั‘ ั€ะฐะฒะฝะพ APIStar ะพัั‚ะฐะฒะฐะปัั ะปัƒั‡ัˆะธะผ ะดะพัั‚ัƒะฟะฝั‹ะผ ะฒะฐั€ะธะฐะฝั‚ะพะผ. ะะฐ ั‚ะพั‚ ะผะพะผะตะฝั‚ ัƒ ะฝะตะณะพ ะฑั‹ะปะธ ะปัƒั‡ัˆะธะต ะฟะพะบะฐะทะฐั‚ะตะปะธ ะฒ ะฑะตะฝั‡ะผะฐั€ะบะฐั… (ะตะณะพ ะฟั€ะตะฒะพัั…ะพะดะธะป ั‚ะพะปัŒะบะพ Starlette). @@ -419,7 +419,7 @@ Pydantic โ€” ัั‚ะพ ะฑะธะฑะปะธะพั‚ะตะบะฐ ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะฒะฐะปะธ ### Starlette { #starlette } -Starlette โ€” ัั‚ะพ ะปั‘ะณะบะธะน ASGI ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑะพั€ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะธะดะตะฐะปัŒะฝะพ ะฟะพะดั…ะพะดัั‰ะธะน ะดะปั ัะพะทะดะฐะฝะธั ะฒั‹ัะพะบะพะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝั‹ั… asyncioโ€‘ัะตั€ะฒะธัะพะฒ. +Starlette โ€” ัั‚ะพ ะปั‘ะณะบะธะน ASGI ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑะพั€ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะธะดะตะฐะปัŒะฝะพ ะฟะพะดั…ะพะดัั‰ะธะน ะดะปั ัะพะทะดะฐะฝะธั ะฒั‹ัะพะบะพะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝั‹ั… asyncioโ€‘ัะตั€ะฒะธัะพะฒ. ะžะฝ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพะน ะธ ะธะฝั‚ัƒะธั‚ะธะฒะฝั‹ะน. ะกะฟั€ะพะตะบั‚ะธั€ะพะฒะฐะฝ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะตะณะพ ะฑั‹ะปะพ ะปะตะณะบะพ ั€ะฐััˆะธั€ัั‚ัŒ, ะธ ั‡ั‚ะพะฑั‹ ะบะพะผะฟะพะฝะตะฝั‚ั‹ ะฑั‹ะปะธ ะผะพะดัƒะปัŒะฝั‹ะผะธ. diff --git a/docs/ru/docs/async.md b/docs/ru/docs/async.md index 15d4e108ab..bff32aaf49 100644 --- a/docs/ru/docs/async.md +++ b/docs/ru/docs/async.md @@ -4,7 +4,7 @@ ## ะะตั‚ ะฒั€ะตะผะตะฝะธ? { #in-a-hurry } -TL;DR: +TL;DR: ะ•ัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ัั‚ะพั€ะพะฝะฝะธะต ะฑะธะฑะปะธะพั‚ะตะบะธ, ะบะพั‚ะพั€ั‹ะต ะฝัƒะถะฝะพ ะฒั‹ะทั‹ะฒะฐั‚ัŒ ั `await`, ะฝะฐะฟั€ะธะผะตั€: @@ -68,13 +68,13 @@ def results(): ะัะธะฝั…ั€ะพะฝะฝั‹ะน ะบะพะด ะทะฝะฐั‡ะธั‚, ั‡ั‚ะพ ะฒ ัะทั‹ะบะต ๐Ÿ’ฌ ะตัั‚ัŒ ัะฟะพัะพะฑ ัะบะฐะทะฐั‚ัŒ ะบะพะผะฟัŒัŽั‚ะตั€ัƒ/ะฟั€ะพะณั€ะฐะผะผะต ๐Ÿค–, ั‡ั‚ะพ ะฒ ะฝะตะบะพั‚ะพั€ั‹ะน ะผะพะผะตะฝั‚ ะบะพะดะฐ ะตะผัƒ ๐Ÿค– ะฟั€ะธะดั‘ั‚ัั ะฟะพะดะพะถะดะฐั‚ัŒ, ะฟะพะบะฐ *ั‡ั‚ะพ-ั‚ะพ ะตั‰ั‘* ะณะดะต-ั‚ะพ ะฒ ะดั€ัƒะณะพะผ ะผะตัั‚ะต ะทะฐะฒะตั€ัˆะธั‚ัั. ะะฐะทะพะฒั‘ะผ ัั‚ะพ *ั‡ั‚ะพ-ั‚ะพ ะตั‰ั‘* ยซะผะตะดะปะตะฝะฝั‹ะน ั„ะฐะนะปยป ๐Ÿ“. -ะ˜ ะฟะพะบะฐ ะผั‹ ะถะดั‘ะผ ะทะฐะฒะตั€ัˆะตะฝะธั ั€ะฐะฑะพั‚ั‹ ั ยซะผะตะดะปะตะฝะฝั‹ะธ ั„ะฐะนะปะพะผยป ๐Ÿ“, ะบะพะผะฟัŒัŽั‚ะตั€ ะผะพะถะตั‚ ะทะฐะฝัั‚ัŒัั ะดั€ัƒะณะพะน ั€ะฐะฑะพั‚ะพะน. +ะ˜ ะฟะพะบะฐ ะผั‹ ะถะดั‘ะผ ะทะฐะฒะตั€ัˆะตะฝะธั ั€ะฐะฑะพั‚ั‹ ั ยซะผะตะดะปะตะฝะฝั‹ะผ ั„ะฐะนะปะพะผยป ๐Ÿ“, ะบะพะผะฟัŒัŽั‚ะตั€ ะผะพะถะตั‚ ะทะฐะฝัั‚ัŒัั ะดั€ัƒะณะพะน ั€ะฐะฑะพั‚ะพะน. ะ—ะฐั‚ะตะผ ะบะพะผะฟัŒัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะผะฐ ๐Ÿค– ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒัั ะบะฐะถะดั‹ะน ั€ะฐะท, ะบะพะณะดะฐ ะฟะพัะฒะธั‚ัั ะฒะพะทะผะพะถะฝะพัั‚ัŒ (ะฟะพะบะฐ ัะฝะพะฒะฐ ะณะดะต-ั‚ะพ ะธะดั‘ั‚ ะพะถะธะดะฐะฝะธะต), ะธะปะธ ะบะพะณะดะฐ ๐Ÿค– ะทะฐะฒะตั€ัˆะธั‚ ะฒััŽ ั‚ะตะบัƒั‰ัƒัŽ ั€ะฐะฑะพั‚ัƒ. ะ˜ ะพะฝ ๐Ÿค– ะฟั€ะพะฒะตั€ะธั‚, ะฝะต ะทะฐะฒะตั€ัˆะธะปะฐััŒ ะปะธ ะบะฐะบะฐั-ะปะธะฑะพ ะธะท ะทะฐะดะฐั‡, ะบะพั‚ะพั€ั‹ั… ะพะฝ ะถะดะฐะป, ะธ ัะดะตะปะฐะตั‚ ั‚ะพ, ั‡ั‚ะพ ะฝัƒะถะฝะพ. ะ”ะฐะปะตะต ะพะฝ ๐Ÿค– ะฒะพะทัŒะผั‘ั‚ ะฟะตั€ะฒัƒัŽ ะทะฐะฒะตั€ัˆะธะฒัˆัƒัŽัั ะทะฐะดะฐั‡ัƒ (ัะบะฐะถะตะผ, ะฝะฐัˆ ยซะผะตะดะปะตะฝะฝั‹ะน ั„ะฐะนะปยป ๐Ÿ“) ะธ ะฟั€ะพะดะพะปะถะธั‚ ะดะตะปะฐั‚ัŒ ั ะฝะตะน ั‚ะพ, ั‡ั‚ะพ ั‚ั€ะตะฑัƒะตั‚ัั. -ะญั‚ะพ ยซะพะถะธะดะฐะฝะธะต ั‡ะตะณะพ-ั‚ะพ ะตั‰ั‘ยป ะพะฑั‹ั‡ะฝะพ ะพั‚ะฝะพัะธั‚ัั ะบ ะพะฟะตั€ะฐั†ะธัะผ I/O, ะบะพั‚ะพั€ั‹ะต ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพ ยซะผะตะดะปะตะฝะฝั‹ะตยป (ะฟะพ ัั€ะฐะฒะฝะตะฝะธัŽ ัะพ ัะบะพั€ะพัั‚ัŒัŽ ะฟั€ะพั†ะตััะพั€ะฐ ะธ ะพะฟะตั€ะฐั‚ะธะฒะฝะพะน ะฟะฐะผัั‚ะธ), ะฝะฐะฟั€ะธะผะตั€ ะพะถะธะดะฐะฝะธะต: +ะญั‚ะพ ยซะพะถะธะดะฐะฝะธะต ั‡ะตะณะพ-ั‚ะพ ะตั‰ั‘ยป ะพะฑั‹ั‡ะฝะพ ะพั‚ะฝะพัะธั‚ัั ะบ ะพะฟะตั€ะฐั†ะธัะผ I/O, ะบะพั‚ะพั€ั‹ะต ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพ ยซะผะตะดะปะตะฝะฝั‹ะตยป (ะฟะพ ัั€ะฐะฒะฝะตะฝะธัŽ ัะพ ัะบะพั€ะพัั‚ัŒัŽ ะฟั€ะพั†ะตััะพั€ะฐ ะธ ะพะฟะตั€ะฐั‚ะธะฒะฝะพะน ะฟะฐะผัั‚ะธ), ะฝะฐะฟั€ะธะผะตั€ ะพะถะธะดะฐะฝะธะต: * ะพั‚ะฟั€ะฐะฒะบะธ ะดะฐะฝะฝั‹ั… ะบะปะธะตะฝั‚ะพะผ ะฟะพ ัะตั‚ะธ * ะฟะพะปัƒั‡ะตะฝะธั ะบะปะธะตะฝั‚ะพะผ ะดะฐะฝะฝั‹ั…, ะพั‚ะฟั€ะฐะฒะปะตะฝะฝั‹ั… ะฒะฐัˆะตะน ะฟั€ะพะณั€ะฐะผะผะพะน ะฟะพ ัะตั‚ะธ @@ -85,7 +85,7 @@ def results(): * ะฒะพะทะฒั€ะฐั‚ะฐ ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะฒ ะทะฐะฟั€ะพัะฐ ะบ ะฑะฐะทะต ะดะฐะฝะฝั‹ั… * ะธ ั‚.ะด. -ะŸะพัะบะพะปัŒะบัƒ ะพัะฝะพะฒะฝะพะต ะฒั€ะตะผั ะฒั‹ะฟะพะปะฝะตะฝะธั ัƒั…ะพะดะธั‚ ะฝะฐ ะพะถะธะดะฐะฝะธะต ะพะฟะตั€ะฐั†ะธะน I/O, ะธั… ะฝะฐะทั‹ะฒะฐัŽั‚ ะพะฟะตั€ะฐั†ะธัะผะธ, ยซะพะณั€ะฐะฝะธั‡ะตะฝะฝั‹ะผะธ ะฒะฒะพะดะพะผ-ะฒั‹ะฒะพะดะพะผยป (I/O bound). +ะŸะพัะบะพะปัŒะบัƒ ะพัะฝะพะฒะฝะพะต ะฒั€ะตะผั ะฒั‹ะฟะพะปะฝะตะฝะธั ัƒั…ะพะดะธั‚ ะฝะฐ ะพะถะธะดะฐะฝะธะต ะพะฟะตั€ะฐั†ะธะน I/O, ะธั… ะฝะฐะทั‹ะฒะฐัŽั‚ ะพะฟะตั€ะฐั†ะธัะผะธ, ยซะพะณั€ะฐะฝะธั‡ะตะฝะฝั‹ะผะธ ะฒะฒะพะดะพะผ-ะฒั‹ะฒะพะดะพะผยป (I/O bound). ะญั‚ะพ ะฝะฐะทั‹ะฒะฐะตั‚ัั ยซะฐัะธะฝั…ั€ะพะฝะฝั‹ะผยป, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ะบะพะผะฟัŒัŽั‚ะตั€ัƒ/ะฟั€ะพะณั€ะฐะผะผะต ะฝะต ะฝัƒะถะฝะพ ยซัะธะฝั…ั€ะพะฝะธะทะธั€ะพะฒะฐั‚ัŒััยป ั ะผะตะดะปะตะฝะฝะพะน ะทะฐะดะฐั‡ะตะน, ะฟั€ะพัั‚ะฐะธะฒะฐั ะธ ะฒั‹ะถะธะดะฐั ั‚ะพั‡ะฝั‹ะน ะผะพะผะตะฝั‚ ะตั‘ ะทะฐะฒะตั€ัˆะตะฝะธั, ั‡ั‚ะพะฑั‹ ะทะฐะฑั€ะฐั‚ัŒ ั€ะตะทัƒะปัŒั‚ะฐั‚ ะธ ะฟั€ะพะดะพะปะถะธั‚ัŒ ั€ะฐะฑะพั‚ัƒ. @@ -277,7 +277,7 @@ def results(): ะ’ ัั‚ะพะผ ัั†ะตะฝะฐั€ะธะธ ะบะฐะถะดั‹ะน ัƒะฑะพั€ั‰ะธะบ (ะฒะบะปัŽั‡ะฐั ะฒะฐั) ะฑั‹ะป ะฑั‹ ะฟั€ะพั†ะตััะพั€ะพะผ, ะฒั‹ะฟะพะปะฝััŽั‰ะธะผ ัะฒะพัŽ ั‡ะฐัั‚ัŒ ั€ะฐะฑะพั‚ั‹. -ะ˜ ั‚ะฐะบ ะบะฐะบ ะพัะฝะพะฒะฝะพะต ะฒั€ะตะผั ะฒั‹ะฟะพะปะฝะตะฝะธั ัƒั…ะพะดะธั‚ ะฝะฐ ั€ะตะฐะปัŒะฝัƒัŽ ั€ะฐะฑะพั‚ัƒ (ะฐ ะฝะต ะพะถะธะดะฐะฝะธะต), ะฐ ั€ะฐะฑะพั‚ัƒ ะฒ ะบะพะผะฟัŒัŽั‚ะตั€ะต ะฒั‹ะฟะพะปะฝัะตั‚ CPU, ั‚ะฐะบะธะต ะทะฐะดะฐั‡ะธ ะฝะฐะทั‹ะฒะฐัŽั‚ ยซะพะณั€ะฐะฝะธั‡ะตะฝะฝั‹ะผะธ ะฟั€ะพั†ะตััะพั€ะพะผยป (CPU bound). +ะ˜ ั‚ะฐะบ ะบะฐะบ ะพัะฝะพะฒะฝะพะต ะฒั€ะตะผั ะฒั‹ะฟะพะปะฝะตะฝะธั ัƒั…ะพะดะธั‚ ะฝะฐ ั€ะตะฐะปัŒะฝัƒัŽ ั€ะฐะฑะพั‚ัƒ (ะฐ ะฝะต ะพะถะธะดะฐะฝะธะต), ะฐ ั€ะฐะฑะพั‚ัƒ ะฒ ะบะพะผะฟัŒัŽั‚ะตั€ะต ะฒั‹ะฟะพะปะฝัะตั‚ CPU, ั‚ะฐะบะธะต ะทะฐะดะฐั‡ะธ ะฝะฐะทั‹ะฒะฐัŽั‚ ยซะพะณั€ะฐะฝะธั‡ะตะฝะฝั‹ะผะธ ะฟั€ะพั†ะตััะพั€ะพะผยป (CPU bound). --- @@ -417,7 +417,7 @@ Starlette (ะธ **FastAPI**) ะพัะฝะพะฒะฐะฝั‹ ะฝะฐ I/O. +ะ•ัะปะธ ะฒั‹ ะฟั€ะธัˆะปะธ ะธะท ะดั€ัƒะณะพะณะพ async-ั„ั€ะตะนะผะฒะพั€ะบะฐ, ะบะพั‚ะพั€ั‹ะน ั€ะฐะฑะพั‚ะฐะตั‚ ะธะฝะฐั‡ะต, ะธ ะฟั€ะธะฒั‹ะบะปะธ ะพะฑัŠัะฒะปัั‚ัŒ ั‚ั€ะธะฒะธะฐะปัŒะฝั‹ะต *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ*, ะฒั‹ะฟะพะปะฝััŽั‰ะธะต ั‚ะพะปัŒะบะพ ะฒั‹ั‡ะธัะปะตะฝะธั, ั‡ะตั€ะตะท ะฟั€ะพัั‚ะพะน `def` ั€ะฐะดะธ ะบั€ะพัˆะตั‡ะฝะพะน ะฒั‹ะณะพะดั‹ ะฒ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ (ะพะบะพะปะพ 100 ะฝะฐะฝะพัะตะบัƒะฝะด), ะพะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต: ะฒ **FastAPI** ัั„ั„ะตะบั‚ ะฑัƒะดะตั‚ ะฟั€ะพั‚ะธะฒะพะฟะพะปะพะถะฝั‹ะผ. ะ’ ั‚ะฐะบะธั… ัะปัƒั‡ะฐัั… ะปัƒั‡ัˆะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `async def`, ะตัะปะธ ั‚ะพะปัŒะบะพ ะฒะฐัˆะธ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ* ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ ะบะพะด, ะฒั‹ะฟะพะปะฝััŽั‰ะธะน ะฑะปะพะบะธั€ัƒัŽั‰ะธะน I/O. ะขะตะผ ะฝะต ะผะตะฝะตะต, ะฒ ะพะฑะพะธั… ัะปัƒั‡ะฐัั… ะฒะตะปะธะบะฐ ะฒะตั€ะพัั‚ะฝะพัั‚ัŒ, ั‡ั‚ะพ **FastAPI** [ะฒัั‘ ั€ะฐะฒะฝะพ ะฑัƒะดะตั‚ ะฑั‹ัั‚ั€ะตะต](index.md#performance){.internal-link target=_blank} (ะธะปะธ ะบะฐะบ ะผะธะฝะธะผัƒะผ ัะพะฟะพัั‚ะฐะฒะธะผ) ั ะฒะฐัˆะธะผ ะฟั€ะตะดั‹ะดัƒั‰ะธะผ ั„ั€ะตะนะผะฒะพั€ะบะพะผ. diff --git a/docs/ru/docs/benchmarks.md b/docs/ru/docs/benchmarks.md index 612b39f708..c8cacae5f3 100644 --- a/docs/ru/docs/benchmarks.md +++ b/docs/ru/docs/benchmarks.md @@ -16,19 +16,19 @@ * **Uvicorn**: ASGI-ัะตั€ะฒะตั€ * **Starlette**: (ะธัะฟะพะปัŒะทัƒะตั‚ Uvicorn) ะฒะตะฑ-ะผะธะบั€ะพั„ั€ะตะนะผะฒะพั€ะบ - * **FastAPI**: (ะธัะฟะพะปัŒะทัƒะตั‚ Starlette) API-ะผะธะบั€ะพั„ั€ะตะนะผะฒะพั€ะบ ั ั€ัะดะพะผ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะดะปั ัะพะทะดะฐะฝะธั API, ะฒะบะปัŽั‡ะฐั ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… ะธ ั‚. ะฟ. + * **FastAPI**: (ะธัะฟะพะปัŒะทัƒะตั‚ Starlette) API-ะผะธะบั€ะพั„ั€ะตะนะผะฒะพั€ะบ ั ั€ัะดะพะผ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะดะปั ัะพะทะดะฐะฝะธั API, ะฒะบะปัŽั‡ะฐั ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะฟ. * **Uvicorn**: * ะ‘ัƒะดะตั‚ ะธะผะตั‚ัŒ ะฝะฐะธะปัƒั‡ัˆัƒัŽ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ, ั‚ะฐะบ ะบะฐะบ ะฟะพะผะธะผะพ ัะฐะผะพะณะพ ัะตั€ะฒะตั€ะฐ ัƒ ะฝะตะณะพ ะฝะตะผะฝะพะณะพ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะพะณะพ ะบะพะดะฐ. * ะ’ั‹ ะฝะต ะฑัƒะดะตั‚ะต ะฟะธัะฐั‚ัŒ ะฟั€ะธะปะพะถะตะฝะธะต ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฝะฐ Uvicorn. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะปะพ ะฑั‹, ั‡ั‚ะพ ะ’ะฐัˆ ะบะพะด ะดะพะปะถะตะฝ ะฒะบะปัŽั‡ะฐั‚ัŒ ะบะฐะบ ะผะธะฝะธะผัƒะผ ะฒะตััŒ ะบะพะด, ะฟั€ะตะดะพัั‚ะฐะฒะปัะตะผั‹ะน Starlette (ะธะปะธ **FastAPI**). ะ˜ ะตัะปะธ ะ’ั‹ ั‚ะฐะบ ัะดะตะปะฐะตั‚ะต, ั‚ะพ ะฒ ะบะพะฝะตั‡ะฝะพะผ ะธั‚ะพะณะต ะ’ะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ั‚ะต ะถะต ะฝะฐะบะปะฐะดะฝั‹ะต ั€ะฐัั…ะพะดั‹, ั‡ั‚ะพ ะธ ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ั„ั€ะตะนะผะฒะพั€ะบะฐ, ะผะธะฝะธะผะธะทะธั€ัƒัŽั‰ะตะณะพ ะบะพะด ะ’ะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั ะธ ะ’ะฐัˆะธ ะพัˆะธะฑะบะธ. - * ะ•ัะปะธ ะ’ั‹ ัั€ะฐะฒะฝะธะฒะฐะตั‚ะต Uvicorn, ัั€ะฐะฒะฝะธะฒะฐะนั‚ะต ะตะณะพ ั Daphne, Hypercorn, uWSGI ะธ ั‚. ะด. โ€” ัะตั€ะฒะตั€ะฐะผะธ ะฟั€ะธะปะพะถะตะฝะธะน. + * ะ•ัะปะธ ะ’ั‹ ัั€ะฐะฒะฝะธะฒะฐะตั‚ะต Uvicorn, ัั€ะฐะฒะฝะธะฒะฐะนั‚ะต ะตะณะพ ั Daphne, Hypercorn, uWSGI ะธ ั‚.ะด. โ€” ัะตั€ะฒะตั€ะฐะผะธ ะฟั€ะธะปะพะถะตะฝะธะน. * **Starlette**: * ะ‘ัƒะดะตั‚ ะฝะฐ ัะปะตะดัƒัŽั‰ะตะผ ะผะตัั‚ะต ะฟะพ ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ะธ ะฟะพัะปะต Uvicorn. ะคะฐะบั‚ะธั‡ะตัะบะธ Starlette ะทะฐะฟัƒัะบะฐะตั‚ัั ะฟะพะด ัƒะฟั€ะฐะฒะปะตะฝะธะตะผ Uvicorn, ะฟะพัั‚ะพะผัƒ ะพะฝ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั‚ะพะปัŒะบะพ ยซะผะตะดะปะตะฝะฝะตะตยป Uvicorn ะธะทโ€‘ะทะฐ ะฒั‹ะฟะพะปะฝะตะฝะธั ะฑะพะปัŒัˆะตะณะพ ะพะฑัŠั‘ะผะฐ ะบะพะดะฐ. - * ะ—ะฐั‚ะพ ะพะฝ ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะ’ะฐะผ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะดะปั ัะพะทะดะฐะฝะธั ะฟั€ะพัั‚ั‹ั… ะฒะตะฑโ€‘ะฟั€ะธะปะพะถะตะฝะธะน ั ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั†ะธะตะน ะฟะพ ะฟัƒั‚ัะผ ะธ ั‚. ะฟ. - * ะ•ัะปะธ ะ’ั‹ ัั€ะฐะฒะฝะธะฒะฐะตั‚ะต Starlette, ัั€ะฐะฒะฝะธะฒะฐะนั‚ะต ะตะณะพ ั Sanic, Flask, Django ะธ ั‚. ะด. โ€” ะฒะตะฑโ€‘ั„ั€ะตะนะผะฒะพั€ะบะฐะผะธ (ะธะปะธ ะผะธะบั€ะพั„ั€ะตะนะผะฒะพั€ะบะฐะผะธ). + * ะ—ะฐั‚ะพ ะพะฝ ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะ’ะฐะผ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะดะปั ัะพะทะดะฐะฝะธั ะฟั€ะพัั‚ั‹ั… ะฒะตะฑโ€‘ะฟั€ะธะปะพะถะตะฝะธะน ั ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั†ะธะตะน ะฟะพ ะฟัƒั‚ัะผ ะธ ั‚.ะฟ. + * ะ•ัะปะธ ะ’ั‹ ัั€ะฐะฒะฝะธะฒะฐะตั‚ะต Starlette, ัั€ะฐะฒะฝะธะฒะฐะนั‚ะต ะตะณะพ ั Sanic, Flask, Django ะธ ั‚.ะด. โ€” ะฒะตะฑโ€‘ั„ั€ะตะนะผะฒะพั€ะบะฐะผะธ (ะธะปะธ ะผะธะบั€ะพั„ั€ะตะนะผะฒะพั€ะบะฐะผะธ). * **FastAPI**: * ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ Starlette ะธัะฟะพะปัŒะทัƒะตั‚ Uvicorn ะธ ะฝะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑั‹ัั‚ั€ะตะต ะฝะตะณะพ, **FastAPI** ะธัะฟะพะปัŒะทัƒะตั‚ Starlette, ะฟะพัั‚ะพะผัƒ ะฝะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑั‹ัั‚ั€ะตะต ะตะณะพ. * FastAPI ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฑะพะปัŒัˆะต ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะฟะพะฒะตั€ั… Starlette โ€” ั‚ะต, ะบะพั‚ะพั€ั‹ะต ะฟะพั‡ั‚ะธ ะฒัะตะณะดะฐ ะฝัƒะถะฝั‹ ะฟั€ะธ ัะพะทะดะฐะฝะธะธ API, ั‚ะฐะบะธะต ะบะฐะบ ะฒะฐะปะธะดะฐั†ะธั ะธ ัะตั€ะธะฐะปะธะทะฐั†ะธั ะดะฐะฝะฝั‹ั…. ะ’ ะดะพะฒะตัะพะบ ะ’ั‹ ะตั‰ั‘ ะธ ะฟะพะปัƒั‡ะฐะตั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ (ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั ะดะฐะถะต ะฝะต ัƒะฒะตะปะธั‡ะธะฒะฐะตั‚ ะฝะฐะบะปะฐะดะฝั‹ะต ั€ะฐัั…ะพะดั‹ ะฟั€ะธ ั€ะฐะฑะพั‚ะต ะฟั€ะธะปะพะถะตะฝะธั, ั‚ะฐะบ ะบะฐะบ ะพะฝะฐ ัะพะทะดะฐั‘ั‚ัั ะฟั€ะธ ะทะฐะฟัƒัะบะต). - * ะ•ัะปะธ ะฑั‹ ะ’ั‹ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐะปะธ FastAPI, ะฐ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ Starlette ะฝะฐะฟั€ัะผัƒัŽ (ะธะปะธ ะดั€ัƒะณะพะน ะธะฝัั‚ั€ัƒะผะตะฝั‚ ะฒั€ะพะดะต Sanic, Flask, Responder ะธ ั‚. ะด.), ะ’ะฐะผ ะฟั€ะธัˆะปะพััŒ ะฑั‹ ัะฐะผะพัั‚ะพัั‚ะตะปัŒะฝะพ ั€ะตะฐะปะธะทะพะฒะฐั‚ัŒ ะฒะฐะปะธะดะฐั†ะธัŽ ะธ ัะตั€ะธะฐะปะธะทะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…. ะขะพ ะตัั‚ัŒ, ะฒ ะธั‚ะพะณะต, ะ’ะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะธะผะตะปะพ ะฑั‹ ั‚ะฐะบะธะต ะถะต ะฝะฐะบะปะฐะดะฝั‹ะต ั€ะฐัั…ะพะดั‹, ะบะฐะบ ะตัะปะธ ะฑั‹ ะพะฝะพ ะฑั‹ะปะพ ัะพะทะดะฐะฝะพ ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ FastAPI. ะ˜ ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฒะฐะปะธะดะฐั†ะธั ะธ ัะตั€ะธะฐะปะธะทะฐั†ะธั ะดะฐะฝะฝั‹ั… ะฟั€ะตะดัั‚ะฐะฒะปััŽั‚ ัะพะฑะพะน ัะฐะผั‹ะน ะฑะพะปัŒัˆะพะน ะพะฑัŠั‘ะผ ะบะพะดะฐ, ะฝะฐะฟะธัะฐะฝะฝะพะณะพ ะฒ ะฟั€ะธะปะพะถะตะฝะธัั…. + * ะ•ัะปะธ ะฑั‹ ะ’ั‹ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐะปะธ FastAPI, ะฐ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ Starlette ะฝะฐะฟั€ัะผัƒัŽ (ะธะปะธ ะดั€ัƒะณะพะน ะธะฝัั‚ั€ัƒะผะตะฝั‚ ะฒั€ะพะดะต Sanic, Flask, Responder ะธ ั‚.ะด.), ะ’ะฐะผ ะฟั€ะธัˆะปะพััŒ ะฑั‹ ัะฐะผะพัั‚ะพัั‚ะตะปัŒะฝะพ ั€ะตะฐะปะธะทะพะฒะฐั‚ัŒ ะฒะฐะปะธะดะฐั†ะธัŽ ะธ ัะตั€ะธะฐะปะธะทะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…. ะขะพ ะตัั‚ัŒ, ะฒ ะธั‚ะพะณะต, ะ’ะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะธะผะตะปะพ ะฑั‹ ั‚ะฐะบะธะต ะถะต ะฝะฐะบะปะฐะดะฝั‹ะต ั€ะฐัั…ะพะดั‹, ะบะฐะบ ะตัะปะธ ะฑั‹ ะพะฝะพ ะฑั‹ะปะพ ัะพะทะดะฐะฝะพ ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ FastAPI. ะ˜ ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฒะฐะปะธะดะฐั†ะธั ะธ ัะตั€ะธะฐะปะธะทะฐั†ะธั ะดะฐะฝะฝั‹ั… ะฟั€ะตะดัั‚ะฐะฒะปััŽั‚ ัะพะฑะพะน ัะฐะผั‹ะน ะฑะพะปัŒัˆะพะน ะพะฑัŠั‘ะผ ะบะพะดะฐ, ะฝะฐะฟะธัะฐะฝะฝะพะณะพ ะฒ ะฟั€ะธะปะพะถะตะฝะธัั…. * ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะธัะฟะพะปัŒะทัƒั FastAPI, ะ’ั‹ ัะบะพะฝะพะผะธั‚ะต ะฒั€ะตะผั ั€ะฐะทั€ะฐะฑะพั‚ะบะธ, ัƒะผะตะฝัŒัˆะฐะตั‚ะต ะบะพะปะธั‡ะตัั‚ะฒะพ ะพัˆะธะฑะพะบ, ัั‚ั€ะพะบ ะบะพะดะฐ ะธ, ะฒะตั€ะพัั‚ะฝะพ, ะฟะพะปัƒั‡ะธั‚ะต ั‚ัƒ ะถะต ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ (ะธะปะธ ะปัƒั‡ัˆะต), ะบะฐะบ ะธ ะตัะปะธ ะฑั‹ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐะปะธ ะตะณะพ (ะฟะพัะบะพะปัŒะบัƒ ะ’ะฐะผ ะฟั€ะธัˆะปะพััŒ ะฑั‹ ั€ะตะฐะปะธะทะพะฒะฐั‚ัŒ ะฒัะต ะตะณะพ ะฒะพะทะผะพะถะฝะพัั‚ะธ ะฒ ัะฒะพั‘ะผ ะบะพะดะต). * ะ•ัะปะธ ะ’ั‹ ัั€ะฐะฒะฝะธะฒะฐะตั‚ะต FastAPI, ัั€ะฐะฒะฝะธะฒะฐะนั‚ะต ะตะณะพ ั ั„ั€ะตะนะผะฒะพั€ะบะพะผ ะฒะตะฑโ€‘ะฟั€ะธะปะพะถะตะฝะธะน (ะธะปะธ ะฝะฐะฑะพั€ะพะผ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ), ะบะพั‚ะพั€ั‹ะน ะพะฑะตัะฟะตั‡ะธะฒะฐะตั‚ ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…, ัะตั€ะธะฐะปะธะทะฐั†ะธัŽ ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ, ั‚ะฐะบะธะผะธ ะบะฐะบ Flask-apispec, NestJS, Molten ะธ ะธะผ ะฟะพะดะพะฑะฝั‹ะต. ะคั€ะตะนะผะฒะพั€ะบะธ ั ะธะฝั‚ะตะณั€ะธั€ะพะฒะฐะฝะฝะพะน ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะฒะฐะปะธะดะฐั†ะธะตะน ะดะฐะฝะฝั‹ั…, ัะตั€ะธะฐะปะธะทะฐั†ะธะตะน ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน. diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 207d1604d7..173dbb962d 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -27,13 +27,13 @@ ะ’ [ะฟั€ะตะดั‹ะดัƒั‰ะตะน ะณะปะฐะฒะต ะฟั€ะพ HTTPS](https.md){.internal-link target=_blank} ะผั‹ ั€ะฐะทะพะฑั€ะฐะปะธััŒ, ะบะฐะบ HTTPS ะพะฑะตัะฟะตั‡ะธะฒะฐะตั‚ ัˆะธั„ั€ะพะฒะฐะฝะธะต ะดะปั ะฒะฐัˆะตะณะพ API. -ะขะฐะบะถะต ะผั‹ ัƒะฒะธะดะตะปะธ, ั‡ั‚ะพ HTTPS ะพะฑั‹ั‡ะฝะพ ะพะฑะตัะฟะตั‡ะธะฒะฐะตั‚ ะบะพะผะฟะพะฝะตะฝั‚, **ะฒะฝะตัˆะฝะธะน** ะฟะพ ะพั‚ะฝะพัˆะตะฝะธัŽ ะบ ัะตั€ะฒะตั€ัƒ ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั โ€” **TLS Termination Proxy**. +ะขะฐะบะถะต ะผั‹ ัƒะฒะธะดะตะปะธ, ั‡ั‚ะพ HTTPS ะพะฑั‹ั‡ะฝะพ ะพะฑะตัะฟะตั‡ะธะฒะฐะตั‚ ะบะพะผะฟะพะฝะตะฝั‚, **ะฒะฝะตัˆะฝะธะน** ะฟะพ ะพั‚ะฝะพัˆะตะฝะธัŽ ะบ ัะตั€ะฒะตั€ัƒ ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั โ€” **ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ**. ะ˜ ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ ะบะพะผะฟะพะฝะตะฝั‚, ะพั‚ะฒะตั‡ะฐัŽั‰ะธะน ะทะฐ **ะพะฑะฝะพะฒะปะตะฝะธะต HTTPSโ€‘ัะตั€ั‚ะธั„ะธะบะฐั‚ะพะฒ** โ€” ัั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั‚ะพั‚ ะถะต ัะฐะผั‹ะน ะบะพะผะฟะพะฝะตะฝั‚ ะธะปะธ ะพั‚ะดะตะปัŒะฝั‹ะน. ### ะŸั€ะธะผะตั€ั‹ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ะดะปั HTTPS { #example-tools-for-https } -ะะตะบะพั‚ะพั€ั‹ะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะบะพั‚ะพั€ั‹ะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะฐะบ TLS Termination Proxy: +ะะตะบะพั‚ะพั€ั‹ะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะบะพั‚ะพั€ั‹ะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะฐะบ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ: * Traefik * ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑะฝะพะฒะปัะตั‚ ัะตั€ั‚ะธั„ะธะบะฐั‚ั‹ โœจ @@ -47,7 +47,7 @@ * ะก ะฒะฝะตัˆะฝะธะผ ะบะพะผะฟะพะฝะตะฝั‚ะพะผ (ะฝะฐะฟั€ะธะผะตั€, cert-manager) ะดะปั ะพะฑะฝะพะฒะปะตะฝะธั ัะตั€ั‚ะธั„ะธะบะฐั‚ะพะฒ * ะžะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ัั ะฒะฝัƒั‚ั€ะธ ะพะฑะปะฐั‡ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะบะฐะบ ั‡ะฐัั‚ัŒ ะตะณะพ ัƒัะปัƒะณ (ัะผ. ะฝะธะถะต ๐Ÿ‘‡) -ะ”ั€ัƒะณะพะน ะฒะฐั€ะธะฐะฝั‚ โ€” ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **ะพะฑะปะฐั‡ะฝั‹ะน ัะตั€ะฒะธั**, ะบะพั‚ะพั€ั‹ะน ะฒะพะทัŒะผั‘ั‚ ะฝะฐ ัะตะฑั ะฑะพะปัŒัˆะต ะทะฐะดะฐั‡, ะฒะบะปัŽั‡ะฐั ะฝะฐัั‚ั€ะพะนะบัƒ HTTPS. ะขะฐะผ ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะพะณั€ะฐะฝะธั‡ะตะฝะธั ะธะปะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ัั‚ะพะธะผะพัั‚ัŒ ะธ ั‚.ะฟ., ะฝะพ ะฒ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฒะฐะผ ะฝะต ะฟั€ะธะดั‘ั‚ัั ัะฐะผะธะผ ะฝะฐัั‚ั€ะฐะธะฒะฐั‚ัŒ TLS Termination Proxy. +ะ”ั€ัƒะณะพะน ะฒะฐั€ะธะฐะฝั‚ โ€” ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **ะพะฑะปะฐั‡ะฝั‹ะน ัะตั€ะฒะธั**, ะบะพั‚ะพั€ั‹ะน ะฒะพะทัŒะผั‘ั‚ ะฝะฐ ัะตะฑั ะฑะพะปัŒัˆะต ะทะฐะดะฐั‡, ะฒะบะปัŽั‡ะฐั ะฝะฐัั‚ั€ะพะนะบัƒ HTTPS. ะขะฐะผ ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะพะณั€ะฐะฝะธั‡ะตะฝะธั ะธะปะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ัั‚ะพะธะผะพัั‚ัŒ ะธ ั‚.ะฟ., ะฝะพ ะฒ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะฒะฐะผ ะฝะต ะฟั€ะธะดั‘ั‚ัั ัะฐะผะธะผ ะฝะฐัั‚ั€ะฐะธะฒะฐั‚ัŒ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ. ะ’ ัะปะตะดัƒัŽั‰ะธั… ะณะปะฐะฒะฐั… ั ะฟะพะบะฐะถัƒ ะบะพะฝะบั€ะตั‚ะฝั‹ะต ะฟั€ะธะผะตั€ั‹. @@ -214,7 +214,7 @@ ะŸั€ะพั†ะตััโ€‘ะผะตะฝะตะดะถะตั€, ะฒะตั€ะพัั‚ะฝะพ, ะฑัƒะดะตั‚ ั‚ะตะผ, ะบั‚ะพ ัะปัƒัˆะฐะตั‚ **ะฟะพั€ั‚** ะฝะฐ IP. ะ˜ ะพะฝ ะฑัƒะดะตั‚ ะฟะตั€ะตะดะฐะฒะฐั‚ัŒ ะฒััŽ ะบะพะผะผัƒะฝะธะบะฐั†ะธัŽ ะฒะพั€ะบะตั€โ€‘ะฟั€ะพั†ะตััะฐะผ. -ะญั‚ะธ ะฒะพั€ะบะตั€ั‹ ะฑัƒะดัƒั‚ ะทะฐะฟัƒัะบะฐั‚ัŒ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต, ะฒั‹ะฟะพะปะฝัั‚ัŒ ะพัะฝะพะฒะฝั‹ะต ะฒั‹ั‡ะธัะปะตะฝะธั ะดะปั ะฟะพะปัƒั‡ะตะฝะธั **ะทะฐะฟั€ะพัะฐ** ะธ ะฒะพะทะฒั€ะฐั‚ะฐ **ะพั‚ะฒะตั‚ะฐ**, ะธ ะทะฐะณั€ัƒะถะฐั‚ัŒ ะฒัั‘, ั‡ั‚ะพ ะฒั‹ ะบะปะฐะดั‘ั‚ะต ะฒ ะฟะตั€ะตะผะตะฝะฝั‹ะต, ะฒ RAM. +ะญั‚ะธ ะฒะพั€ะบะตั€ั‹ ะฑัƒะดัƒั‚ ะทะฐะฟัƒัะบะฐั‚ัŒ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต, ะฒั‹ะฟะพะปะฝัั‚ัŒ ะพัะฝะพะฒะฝั‹ะต ะฒั‹ั‡ะธัะปะตะฝะธั ะดะปั ะฟะพะปัƒั‡ะตะฝะธั **HTTPโ€‘ะทะฐะฟั€ะพัะฐ** ะธ ะฒะพะทะฒั€ะฐั‚ะฐ **HTTPโ€‘ะพั‚ะฒะตั‚ะฐ**, ะธ ะทะฐะณั€ัƒะถะฐั‚ัŒ ะฒัั‘, ั‡ั‚ะพ ะฒั‹ ะบะปะฐะดั‘ั‚ะต ะฒ ะฟะตั€ะตะผะตะฝะฝั‹ะต, ะฒ RAM. @@ -289,7 +289,7 @@ ะ’ะฐัˆ ัะตั€ะฒะตั€(ะฐ) โ€” ัั‚ะพ **ั€ะตััƒั€ั**, ะบะพั‚ะพั€ั‹ะน ะฒะฐัˆะธ ะฟั€ะพะณั€ะฐะผะผั‹ ะผะพะณัƒั‚ ะฟะพั‚ั€ะตะฑะปัั‚ัŒ ะธะปะธ **ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ**: ะฒั€ะตะผั ะฒั‹ั‡ะธัะปะตะฝะธะน ะฝะฐ CPU ะธ ะดะพัั‚ัƒะฟะฝัƒัŽ ะพะฟะตั€ะฐั‚ะธะฒะฝัƒัŽ ะฟะฐะผัั‚ัŒ (RAM). -ะšะฐะบัƒัŽ ะดะพะปัŽ ัะธัั‚ะตะผะฝั‹ั… ั€ะตััƒั€ัะพะฒ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพั‚ั€ะตะฑะปัั‚ัŒ/ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ? ะœะพะถะฝะพ ะฟะพะดัƒะผะฐั‚ัŒ ยซะฝะตะผะฝะพะณะพยป, ะฝะพ ะฝะฐ ะฟั€ะฐะบั‚ะธะบะต ะฒั‹, ัะบะพั€ะตะต ะฒัะตะณะพ, ะทะฐั…ะพั‚ะธั‚ะต ะฟะพั‚ั€ะตะฑะปัั‚ัŒ **ะผะฐะบัะธะผัƒะผ ะฑะตะท ะฟะฐะดะตะฝะธะน**. +ะšะฐะบัƒัŽ ะดะพะปัŽ ัะธัั‚ะตะผะฝั‹ั… ั€ะตััƒั€ัะพะฒ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพั‚ั€ะตะฑะปัั‚ัŒ/ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ? ะœะพะถะฝะพ ะฟะพะดัƒะผะฐั‚ัŒ ยซะฝะตะผะฝะพะณะพยป, ะฝะพ ะฝะฐ ะฟั€ะฐะบั‚ะธะบะต ะฒั‹, ะฒะตั€ะพัั‚ะฝะพ, ะทะฐั…ะพั‚ะธั‚ะต ะฟะพั‚ั€ะตะฑะปัั‚ัŒ **ะผะฐะบัะธะผัƒะผ ะฑะตะท ะฟะฐะดะตะฝะธะน**. ะ•ัะปะธ ะฒั‹ ะฟะปะฐั‚ะธั‚ะต ะทะฐ 3 ัะตั€ะฒะตั€ะฐ, ะฝะพ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะปะธัˆัŒ ะผะฐะปัƒัŽ ั‡ะฐัั‚ัŒ ะธั… RAM ะธ CPU, ะฒั‹, ะฒะตั€ะพัั‚ะฝะพ, **ั‚ั€ะฐั‚ะธั‚ะต ะดะตะฝัŒะณะธ ะฒะฟัƒัั‚ัƒัŽ** ๐Ÿ’ธ ะธ **ัะปะตะบั‚ั€ะพัะฝะตั€ะณะธัŽ ัะตั€ะฒะตั€ะพะฒ** ๐ŸŒŽ ะธ ั‚.ะฟ. diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 9e8562be70..791057fe56 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -14,7 +14,7 @@ ะŸั€ะตะดะฟั€ะพัะผะพั‚ั€ Dockerfile ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -273,9 +273,9 @@ CMD fastapi run app/main.py --port 80 โ””โ”€โ”€ requirements.txt ``` -#### ะ—ะฐ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ะพะผ TLS ั‚ะตั€ะผะธะฝะฐั†ะธะธ { #behind-a-tls-termination-proxy } +#### ะ—ะฐ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ะพะผ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ { #behind-a-tls-termination-proxy } -ะ•ัะปะธ ะฒั‹ ะทะฐะฟัƒัะบะฐะตั‚ะต ะบะพะฝั‚ะตะนะฝะตั€ ะทะฐ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ะพะผ ะทะฐะฒะตั€ัˆะตะฝะธั TLS (ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะพะผ ะฝะฐะณั€ัƒะทะบะธ), ั‚ะฐะบะธะผ ะบะฐะบ Nginx ะธะปะธ Traefik, ะดะพะฑะฐะฒัŒั‚ะต ะพะฟั†ะธัŽ `--proxy-headers`. ะญั‚ะพ ัะพะพะฑั‰ะธั‚ Uvicorn (ั‡ะตั€ะตะท FastAPI CLI), ั‡ั‚ะพ ะฟั€ะธะปะพะถะตะฝะธะต ั€ะฐะฑะพั‚ะฐะตั‚ ะทะฐ HTTPS ะธ ะผะพะถะฝะพ ะดะพะฒะตั€ัั‚ัŒ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ. +ะ•ัะปะธ ะฒั‹ ะทะฐะฟัƒัะบะฐะตั‚ะต ะบะพะฝั‚ะตะนะฝะตั€ ะทะฐ ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ะพะผ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ (ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะพะผ ะฝะฐะณั€ัƒะทะบะธ), ั‚ะฐะบะธะผ ะบะฐะบ Nginx ะธะปะธ Traefik, ะดะพะฑะฐะฒัŒั‚ะต ะพะฟั†ะธัŽ `--proxy-headers`. ะญั‚ะพ ัะพะพะฑั‰ะธั‚ Uvicorn (ั‡ะตั€ะตะท FastAPI CLI), ั‡ั‚ะพ ะฟั€ะธะปะพะถะตะฝะธะต ั€ะฐะฑะพั‚ะฐะตั‚ ะทะฐ HTTPS ะธ ะผะพะถะฝะพ ะดะพะฒะตั€ัั‚ัŒ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -390,7 +390,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ะขะพะณะดะฐ ะฒ `Dockerfile` ะฝัƒะถะฝะพ ะธะทะผะตะฝะธั‚ัŒ ะฟัƒั‚ะธ ะบะพะฟะธั€ะพะฒะฐะฝะธั: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## ะ ะตะฟะปะธะบะฐั†ะธั โ€” ะบะพะปะธั‡ะตัั‚ะฒะพ ะฟั€ะพั†ะตััะพะฒ { #replication-number-of-processes } -ะ•ัะปะธ ัƒ ะฒะฐั ะตัั‚ัŒ ะบะปะฐัั‚ะตั€ ะผะฐัˆะธะฝ ั **Kubernetes**, Docker Swarm Mode, Nomad ะธะปะธ ะดั€ัƒะณะพะน ะฟะพั…ะพะถะตะน ัะธัั‚ะตะผะพะน ะดะปั ัƒะฟั€ะฐะฒะปะตะฝะธั ั€ะฐัะฟั€ะตะดะตะปั‘ะฝะฝั‹ะผะธ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ะฝะฐ ะฝะตัะบะพะปัŒะบะธั… ะผะฐัˆะธะฝะฐั…, ัะบะพั€ะตะต ะฒัะตะณะพ ะฒั‹ ะฑัƒะดะตั‚ะต **ัƒะฟั€ะฐะฒะปัั‚ัŒ ั€ะตะฟะปะธะบะฐั†ะธะตะน** ะฝะฐ **ัƒั€ะพะฒะฝะต ะบะปะฐัั‚ะตั€ะฐ**, ะฐ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **ะผะตะฝะตะดะถะตั€ ะฟั€ะพั†ะตััะพะฒ** (ะฝะฐะฟั€ะธะผะตั€, Uvicorn ั ะฒะพั€ะบะตั€ะฐะผะธ) ะฒ ะบะฐะถะดะพะผ ะบะพะฝั‚ะตะนะฝะตั€ะต. +ะ•ัะปะธ ัƒ ะฒะฐั ะตัั‚ัŒ ะบะปะฐัั‚ะตั€ ะผะฐัˆะธะฝ ั **Kubernetes**, Docker Swarm Mode, Nomad ะธะปะธ ะดั€ัƒะณะพะน ะฟะพั…ะพะถะตะน ัะธัั‚ะตะผะพะน ะดะปั ัƒะฟั€ะฐะฒะปะตะฝะธั ั€ะฐัะฟั€ะตะดะตะปั‘ะฝะฝั‹ะผะธ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ะฝะฐ ะฝะตัะบะพะปัŒะบะธั… ะผะฐัˆะธะฝะฐั…, ัะบะพั€ะตะต ะฒัะตะณะพ ะฒั‹ ะฑัƒะดะตั‚ะต **ัƒะฟั€ะฐะฒะปัั‚ัŒ ั€ะตะฟะปะธะบะฐั†ะธะตะน** ะฝะฐ **ัƒั€ะพะฒะฝะต ะบะปะฐัั‚ะตั€ะฐ**, ะฐ ะฝะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **ะผะตะฝะตะดะถะตั€ ะฟั€ะพั†ะตััะพะฒ** (ะฝะฐะฟั€ะธะผะตั€, Uvicorn ั ะฒะพั€ะบะตั€ะฐะผะธ) ะฒ ะบะฐะถะดะพะผ ะบะพะฝั‚ะตะนะฝะตั€ะต. ะžะดะฝะฐ ะธะท ั‚ะฐะบะธั… ัะธัั‚ะตะผ ัƒะฟั€ะฐะฒะปะตะฝะธั ั€ะฐัะฟั€ะตะดะตะปั‘ะฝะฝั‹ะผะธ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ, ะบะฐะบ Kubernetes, ะพะฑั‹ั‡ะฝะพ ะธะผะตะตั‚ ะฒัั‚ั€ะพะตะฝะฝั‹ะน ัะฟะพัะพะฑ ัƒะฟั€ะฐะฒะปัั‚ัŒ **ั€ะตะฟะปะธะบะฐั†ะธะตะน ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ**, ะฟะพะดะดะตั€ะถะธะฒะฐั **ะฑะฐะปะฐะฝัะธั€ะพะฒะบัƒ ะฝะฐะณั€ัƒะทะบะธ** ะดะปั ะฒั…ะพะดัั‰ะธั… ะทะฐะฟั€ะพัะพะฒ โ€” ะฒัั‘ ัั‚ะพ ะฝะฐ **ัƒั€ะพะฒะฝะต ะบะปะฐัั‚ะตั€ะฐ**. @@ -462,17 +462,17 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ### ะ‘ะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบ ะฝะฐะณั€ัƒะทะบะธ { #load-balancer } -ะŸั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ ะพะฑั‹ั‡ะฝะพ ะตัั‚ัŒ ะบะพะผะฟะพะฝะตะฝั‚, **ัะปัƒัˆะฐัŽั‰ะธะน ะณะปะฐะฒะฝั‹ะน ะฟะพั€ั‚**. ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะดั€ัƒะณะพะน ะบะพะฝั‚ะตะนะฝะตั€ โ€” **ะฟั€ะพะบัะธ ะทะฐะฒะตั€ัˆะตะฝะธั TLS** ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ **HTTPS** ะธะปะธ ะฟะพั…ะพะถะธะน ะธะฝัั‚ั€ัƒะผะตะฝั‚. +ะŸั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ ะพะฑั‹ั‡ะฝะพ ะตัั‚ัŒ ะบะพะผะฟะพะฝะตะฝั‚, **ัะปัƒัˆะฐัŽั‰ะธะน ะณะปะฐะฒะฝั‹ะน ะฟะพั€ั‚**. ะญั‚ะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะดั€ัƒะณะพะน ะบะพะฝั‚ะตะนะฝะตั€ โ€” **ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ** ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ **HTTPS** ะธะปะธ ะฟะพั…ะพะถะธะน ะธะฝัั‚ั€ัƒะผะตะฝั‚. ะŸะพัะบะพะปัŒะบัƒ ัั‚ะพั‚ ะบะพะผะฟะพะฝะตะฝั‚ ะฟั€ะธะฝะธะผะฐะตั‚ **ะฝะฐะณั€ัƒะทะบัƒ** ะทะฐะฟั€ะพัะพะฒ ะธ ั€ะฐัะฟั€ะตะดะตะปัะตั‚ ะตั‘ ะผะตะถะดัƒ ะฒะพั€ะบะตั€ะฐะผะธ **ัะฑะฐะปะฐะฝัะธั€ะพะฒะฐะฝะฝะพ**, ะตะณะพ ั‡ะฐัั‚ะพ ะฝะฐะทั‹ะฒะฐัŽั‚ **ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะพะผ ะฝะฐะณั€ัƒะทะบะธ**. /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะขะพั‚ ะถะต ะบะพะผะฟะพะฝะตะฝั‚ **ะฟั€ะพะบัะธ ะทะฐะฒะตั€ัˆะตะฝะธั TLS**, ะบะพั‚ะพั€ั‹ะน ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ HTTPS, ัะบะพั€ะตะต ะฒัะตะณะพ ั‚ะฐะบะถะต ะฑัƒะดะตั‚ **ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะพะผ ะฝะฐะณั€ัƒะทะบะธ**. +ะขะพั‚ ะถะต ะบะพะผะฟะพะฝะตะฝั‚ **ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ**, ะบะพั‚ะพั€ั‹ะน ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ HTTPS, ัะบะพั€ะตะต ะฒัะตะณะพ ั‚ะฐะบะถะต ะฑัƒะดะตั‚ **ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะพะผ ะฝะฐะณั€ัƒะทะบะธ**. /// -ะŸั€ะธ ั€ะฐะฑะพั‚ะต ั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ัะธัั‚ะตะผะฐ, ะบะพั‚ะพั€ัƒัŽ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะดะปั ะทะฐะฟัƒัะบะฐ ะธ ัƒะฟั€ะฐะฒะปะตะฝะธั ะธะผะธ, ัƒะถะต ะธะผะตะตั‚ ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ัั€ะตะดัั‚ะฒะฐ ะดะปั ะฟะตั€ะตะดะฐั‡ะธ **ัะตั‚ะตะฒะพะณะพ ะฒะทะฐะธะผะพะดะตะนัั‚ะฒะธั** (ะฝะฐะฟั€ะธะผะตั€, HTTP-ะทะฐะฟั€ะพัะพะฒ) ะพั‚ **ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะฐ ะฝะฐะณั€ัƒะทะบะธ** (ะบะพั‚ะพั€ั‹ะน ั‚ะฐะบะถะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ **ะฟั€ะพะบัะธ ะทะฐะฒะตั€ัˆะตะฝะธั TLS**) ะบ ะบะพะฝั‚ะตะนะฝะตั€ัƒ(-ะฐะผ) ั ะฒะฐัˆะธะผ ะฟั€ะธะปะพะถะตะฝะธะตะผ. +ะŸั€ะธ ั€ะฐะฑะพั‚ะต ั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ัะธัั‚ะตะผะฐ, ะบะพั‚ะพั€ัƒัŽ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะดะปั ะทะฐะฟัƒัะบะฐ ะธ ัƒะฟั€ะฐะฒะปะตะฝะธั ะธะผะธ, ัƒะถะต ะธะผะตะตั‚ ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ัั€ะตะดัั‚ะฒะฐ ะดะปั ะฟะตั€ะตะดะฐั‡ะธ **ัะตั‚ะตะฒะพะณะพ ะฒะทะฐะธะผะพะดะตะนัั‚ะฒะธั** (ะฝะฐะฟั€ะธะผะตั€, HTTP-ะทะฐะฟั€ะพัะพะฒ) ะพั‚ **ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบะฐ ะฝะฐะณั€ัƒะทะบะธ** (ะบะพั‚ะพั€ั‹ะน ั‚ะฐะบะถะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ **ะฟั€ะพะบัะธ-ัะตั€ะฒะตั€ะพะผ TSL-ั‚ะตั€ะผะธะฝะฐั†ะธะธ**) ะบ ะบะพะฝั‚ะตะนะฝะตั€ัƒ(-ะฐะผ) ั ะฒะฐัˆะธะผ ะฟั€ะธะปะพะถะตะฝะธะตะผ. ### ะžะดะธะฝ ะฑะฐะปะฐะฝัะธั€ะพะฒั‰ะธะบ โ€” ะฝะตัะบะพะปัŒะบะพ ะบะพะฝั‚ะตะนะฝะตั€ะพะฒ-ะฒะพั€ะบะตั€ะพะฒ { #one-load-balancer-multiple-worker-containers } @@ -499,7 +499,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ะ’ ั‚ะฐะบะธั… ัะปัƒั‡ะฐัั… ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฟั†ะธัŽ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ `--workers`, ั‡ั‚ะพะฑั‹ ัƒะบะฐะทะฐั‚ัŒ ะฝัƒะถะฝะพะต ะบะพะปะธั‡ะตัั‚ะฒะพ ะฒะพั€ะบะตั€ะพะฒ: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 05a03255e8..ffeccfd7da 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -65,7 +65,7 @@ ะงะฐั‰ะต ะฒัะตะณะพ ะฒัั‘ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั **ะฟั€ะธะพะฑั€ะตั‚ะตะฝะธั** **ะธะผะตะฝะธ ะดะพะผะตะฝะฐ**. ะ—ะฐั‚ะตะผ ะฒั‹ ะฝะฐัั‚ั€ะฐะธะฒะฐะตั‚ะต ะตะณะพ ะฝะฐ DNSโ€‘ัะตั€ะฒะตั€ะต (ะฒะพะทะผะพะถะฝะพ, ัƒ ั‚ะพะณะพ ะถะต ะพะฑะปะฐั‡ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ). -ะกะบะพั€ะตะต ะฒัะตะณะพ, ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะพะฑะปะฐั‡ะฝั‹ะน ัะตั€ะฒะตั€ (ะฒะธั€ั‚ัƒะฐะปัŒะฝัƒัŽ ะผะฐัˆะธะฝัƒ) ะธะปะธ ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต, ะธ ัƒ ะฝะตะณะพ ะฑัƒะดะตั‚ ะฟะพัั‚ะพัะฝะฝั‹ะน **ะฟัƒะฑะปะธั‡ะฝั‹ะน IP-ะฐะดั€ะตั**. +ะกะบะพั€ะตะต ะฒัะตะณะพ, ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะพะฑะปะฐั‡ะฝั‹ะน ัะตั€ะฒะตั€ (ะฒะธั€ั‚ัƒะฐะปัŒะฝัƒัŽ ะผะฐัˆะธะฝัƒ) ะธะปะธ ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต, ะธ ัƒ ะฝะตะณะพ ะฑัƒะดะตั‚ ะฟะพัั‚ะพัะฝะฝั‹ะน **ะฟัƒะฑะปะธั‡ะฝั‹ะน IP-ะฐะดั€ะตั**. ะะฐ DNSโ€‘ัะตั€ะฒะตั€ะต(ะฐั…) ะฒั‹ ะฝะฐัั‚ั€ะพะธั‚ะต ะทะฐะฟะธััŒ (ยซ`A record`ยป - ะทะฐะฟะธััŒ ั‚ะธะฟะฐ A), ัƒะบะฐะทั‹ะฒะฐัŽั‰ัƒัŽ, ั‡ั‚ะพ **ะฒะฐัˆ ะดะพะผะตะฝ** ะดะพะปะถะตะฝ ัƒะบะฐะทั‹ะฒะฐั‚ัŒ ะฝะฐ ะฟัƒะฑะปะธั‡ะฝั‹ะน **IPโ€‘ะฐะดั€ะตั ะฒะฐัˆะตะณะพ ัะตั€ะฒะตั€ะฐ**. diff --git a/docs/ru/docs/deployment/index.md b/docs/ru/docs/deployment/index.md index ffb77641dd..7e735593be 100644 --- a/docs/ru/docs/deployment/index.md +++ b/docs/ru/docs/deployment/index.md @@ -18,6 +18,6 @@ ะะฐะฟั€ะธะผะตั€, ะผั‹, ะบะพะผะฐะฝะดะฐ, ัั‚ะพัั‰ะฐั ะทะฐ FastAPI, ัะพะทะดะฐะปะธ **FastAPI Cloud**, ั‡ั‚ะพะฑั‹ ัะดะตะปะฐั‚ัŒ ั€ะฐะทะฒั‘ั€ั‚ั‹ะฒะฐะฝะธะต ะฟั€ะธะปะพะถะตะฝะธะน FastAPI ะฒ ะพะฑะปะฐะบะต ะบะฐะบ ะผะพะถะฝะพ ะฑะพะปะตะต ะฟั€ะพัั‚ั‹ะผ ะธ ะฟั€ัะผะพะปะธะฝะตะนะฝั‹ะผ, ั ั‚ะตะผ ะถะต ัƒะดะพะฑัั‚ะฒะพะผ ะดะปั ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะฐ, ั‡ั‚ะพ ะธ ะฟั€ะธ ั€ะฐะฑะพั‚ะต ั FastAPI. -ะ’ ัั‚ะพะผ ะฑะปะพะบะต ั ะฟะพะบะฐะถัƒ ะฒะฐะผ ะฝะตะบะพั‚ะพั€ั‹ะต ะธะท ะพัะฝะพะฒะฝั‹ั… ะบะพะฝั†ะตะฟั†ะธะน, ะบะพั‚ะพั€ั‹ะต ะฒั‹, ะฒะตั€ะพัั‚ะฝะพ, ะดะพะปะถะฝั‹ ะธะผะตั‚ัŒ ะฒ ะฒะธะดัƒ ะฟั€ะธ ั€ะฐะทะฒะตั€ั‚ั‹ะฒะฐะฝะธะธ ะฟั€ะธะปะพะถะตะฝะธั **FastAPI** (ั…ะพั‚ั ะฑะพะปัŒัˆะธะฝัั‚ะฒะพ ะธะท ะฝะธั… ะฟั€ะธะผะตะฝะธะผะพ ะบ ะปัŽะฑะพะผัƒ ะดั€ัƒะณะพะผัƒ ั‚ะธะฟัƒ ะฒะตะฑ-ะฟั€ะธะปะพะถะตะฝะธะน). +ะฏ ะฟะพะบะฐะถัƒ ะฒะฐะผ ะฝะตะบะพั‚ะพั€ั‹ะต ะธะท ะพัะฝะพะฒะฝั‹ั… ะบะพะฝั†ะตะฟั†ะธะน, ะบะพั‚ะพั€ั‹ะต ะฒั‹, ะฒะตั€ะพัั‚ะฝะพ, ะดะพะปะถะฝั‹ ะธะผะตั‚ัŒ ะฒ ะฒะธะดัƒ ะฟั€ะธ ั€ะฐะทะฒะตั€ั‚ั‹ะฒะฐะฝะธะธ ะฟั€ะธะปะพะถะตะฝะธั **FastAPI** (ั…ะพั‚ั ะฑะพะปัŒัˆะธะฝัั‚ะฒะพ ะธะท ะฝะธั… ะฟั€ะธะผะตะฝะธะผะพ ะบ ะปัŽะฑะพะผัƒ ะดั€ัƒะณะพะผัƒ ั‚ะธะฟัƒ ะฒะตะฑ-ะฟั€ะธะปะพะถะตะฝะธะน). ะ’ ะฟะพัะปะตะดัƒัŽั‰ะธั… ั€ะฐะทะดะตะปะฐั… ะฒั‹ ัƒะทะฝะฐะตั‚ะต ะฑะพะปัŒัˆะต ะดะตั‚ะฐะปะตะน ะธ ะผะตั‚ะพะดะพะฒ, ะฝะตะพะฑั…ะพะดะธะผั‹ั… ะดะปั ัั‚ะพะณะพ. โœจ diff --git a/docs/ru/docs/deployment/versions.md b/docs/ru/docs/deployment/versions.md index 58d5aa110d..4195d689fe 100644 --- a/docs/ru/docs/deployment/versions.md +++ b/docs/ru/docs/deployment/versions.md @@ -1,12 +1,12 @@ # ะž ะฒะตั€ัะธัั… FastAPI { #about-fastapi-versions } -**FastAPI** ัƒะถะต ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฒ ะฟั€ะพะดะฐะบัˆะตะฝะต ะฒะพ ะผะฝะพะณะธั… ะฟั€ะธะปะพะถะตะฝะธัั… ะธ ัะธัั‚ะตะผะฐั…. ะŸะพะบั€ั‹ั‚ะธะต ั‚ะตัั‚ะฐะผะธ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั ะฝะฐ ัƒั€ะพะฒะฝะต 100%. ะะพ ะตะณะพ ั€ะฐะทั€ะฐะฑะพั‚ะบะฐ ะฒัั‘ ะตั‰ั‘ ะดะฒะธะถะตั‚ัั ะฑั‹ัั‚ั€ั‹ะผะธ ั‚ะตะผะฟะฐะผะธ. +**FastAPI** ัƒะถะต ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฒ ะฟั€ะพะดะฐะบัˆะฝ ะฒะพ ะผะฝะพะณะธั… ะฟั€ะธะปะพะถะตะฝะธัั… ะธ ัะธัั‚ะตะผะฐั…. ะŸะพะบั€ั‹ั‚ะธะต ั‚ะตัั‚ะฐะผะธ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั ะฝะฐ ัƒั€ะพะฒะฝะต 100%. ะะพ ะตะณะพ ั€ะฐะทั€ะฐะฑะพั‚ะบะฐ ะฒัั‘ ะตั‰ั‘ ะดะฒะธะถะตั‚ัั ะฑั‹ัั‚ั€ั‹ะผะธ ั‚ะตะผะฟะฐะผะธ. ะงะฐัั‚ะพ ะดะพะฑะฐะฒะปััŽั‚ัั ะฝะพะฒั‹ะต ั„ัƒะฝะบั†ะธะธ, ั€ะตะณัƒะปัั€ะฝะพ ะธัะฟั€ะฐะฒะปััŽั‚ัั ะฑะฐะณะธ, ะบะพะด ะฟั€ะพะดะพะปะถะฐะตั‚ ะฟะพัั‚ะพัะฝะฝะพ ัะพะฒะตั€ัˆะตะฝัั‚ะฒะพะฒะฐั‚ัŒัั. ะŸะพ ัƒะบะฐะทะฐะฝะฝั‹ะผ ะฟั€ะธั‡ะธะฝะฐะผ ั‚ะตะบัƒั‰ะธะต ะฒะตั€ัะธะธ ะดะพ ัะธั… ะฟะพั€ `0.x.x`. ะญั‚ะพ ะณะพะฒะพั€ะธั‚ ะพ ั‚ะพะผ, ั‡ั‚ะพ ะบะฐะถะดะฐั ะฒะตั€ัะธั ะผะพะถะตั‚ ัะพะดะตั€ะถะฐั‚ัŒ ะพะฑั€ะฐั‚ะฝะพ ะฝะตัะพะฒะผะตัั‚ะธะผั‹ะต ะธะทะผะตะฝะตะฝะธั, ัะปะตะดัƒั ะกะตะผะฐะฝั‚ะธั‡ะตัะบะพะผัƒ ะฒะตั€ัะธะพะฝะธั€ะพะฒะฐะฝะธัŽ. -ะฃะถะต ัะตะนั‡ะฐั ะฒั‹ ะผะพะถะตั‚ะต ัะพะทะดะฐะฒะฐั‚ัŒ ะฟั€ะธะปะพะถะตะฝะธั ะฒ ะฟั€ะพะดะฐะบัˆะตะฝะต, ะธัะฟะพะปัŒะทัƒั **FastAPI** (ะธ ัะบะพั€ะตะต ะฒัะตะณะพ ั‚ะฐะบ ะธ ะดะตะปะฐะตั‚ะต), ะณะปะฐะฒะฝะพะต ัƒะฑะตะดะธั‚ัŒัั ะฒ ั‚ะพะผ, ั‡ั‚ะพ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะฒะตั€ัะธัŽ, ะบะพั‚ะพั€ะฐั ะบะพั€ั€ะตะบั‚ะฝะพ ั€ะฐะฑะพั‚ะฐะตั‚ ั ะฒะฐัˆะธะผ ะบะพะดะพะผ. +ะฃะถะต ัะตะนั‡ะฐั ะฒั‹ ะผะพะถะตั‚ะต ัะพะทะดะฐะฒะฐั‚ัŒ ะฟั€ะธะปะพะถะตะฝะธั ะฒ ะฟั€ะพะดะฐะบัˆะฝ, ะธัะฟะพะปัŒะทัƒั **FastAPI** (ะธ ัะบะพั€ะตะต ะฒัะตะณะพ ั‚ะฐะบ ะธ ะดะตะปะฐะตั‚ะต), ะณะปะฐะฒะฝะพะต ัƒะฑะตะดะธั‚ัŒัั ะฒ ั‚ะพะผ, ั‡ั‚ะพ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะฒะตั€ัะธัŽ, ะบะพั‚ะพั€ะฐั ะบะพั€ั€ะตะบั‚ะฝะพ ั€ะฐะฑะพั‚ะฐะตั‚ ั ะฒะฐัˆะธะผ ะบะพะดะพะผ. ## ะ—ะฐะบั€ะตะฟะธั‚ะต ะฒะฐัˆัƒ ะฒะตั€ัะธัŽ `fastapi` { #pin-your-fastapi-version } diff --git a/docs/ru/docs/environment-variables.md b/docs/ru/docs/environment-variables.md index 6291b79d26..759127420f 100644 --- a/docs/ru/docs/environment-variables.md +++ b/docs/ru/docs/environment-variables.md @@ -161,7 +161,7 @@ Hello World from Python ะญั‚ะธ ะฟะตั€ะตะผะตะฝะฝั‹ะต ะพะบั€ัƒะถะตะฝะธั ะผะพะณัƒั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะพะปัŒะบะพ ั **ั‚ะตะบัั‚ะพะฒั‹ะผะธ ัั‚ั€ะพะบะฐะผะธ**, ะฟะพัะบะพะปัŒะบัƒ ะพะฝะธ ัะฒะปััŽั‚ัั ะฒะฝะตัˆะฝะธะผะธ ะฟะพ ะพั‚ะฝะพัˆะตะฝะธัŽ ะบ Python ะธ ะดะพะปะถะฝั‹ ะฑั‹ั‚ัŒ ัะพะฒะผะตัั‚ะธะผั‹ ั ะดั€ัƒะณะธะผะธ ะฟั€ะพะณั€ะฐะผะผะฐะผะธ ะธ ะพัั‚ะฐะปัŒะฝะพะน ัะธัั‚ะตะผะพะน (ะธ ะดะฐะถะต ั ั€ะฐะทะปะธั‡ะฝั‹ะผะธ ะพะฟะตั€ะฐั†ะธะพะฝะฝั‹ะผะธ ัะธัั‚ะตะผะฐะผะธ, ั‚ะฐะบะธะผะธ ะบะฐะบ Linux, Windows, macOS). -ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ **ะปัŽะฑะพะต ะทะฝะฐั‡ะตะฝะธะต**, ัั‡ะธั‚ะฐะฝะฝะพะต ะฒ Python ะธะท ะฟะตั€ะตะผะตะฝะฝะพะน ะพะบั€ัƒะถะตะฝะธั, **ะฑัƒะดะตั‚ `str`**, ะธ ะปัŽะฑะพะต ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะบ ะดั€ัƒะณะพะผัƒ ั‚ะธะฟัƒ ะธะปะธ ะปัŽะฑะฐั ะฟั€ะพะฒะตั€ะบะฐ ะดะพะปะถะฝั‹ ะฑั‹ั‚ัŒ ะฒั‹ะฟะพะปะฝะตะฝั‹ ะฒ ะบะพะดะต. +ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ **ะปัŽะฑะพะต ะทะฝะฐั‡ะตะฝะธะต**, ัั‡ะธั‚ะฐะฝะฝะพะต ะฒ Python ะธะท ะฟะตั€ะตะผะตะฝะฝะพะน ะพะบั€ัƒะถะตะฝะธั, **ะฑัƒะดะตั‚ `str`**, ะธ ะปัŽะฑะพะต ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะบ ะดั€ัƒะณะพะผัƒ ั‚ะธะฟัƒ ะธะปะธ ะปัŽะฑะฐั ะฒะฐะปะธะดะฐั†ะธั ะดะพะปะถะฝั‹ ะฑั‹ั‚ัŒ ะฒั‹ะฟะพะปะฝะตะฝั‹ ะฒ ะบะพะดะต. ะŸะพะดั€ะพะฑะฝะตะต ะพะฑ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ะฟะตั€ะตะผะตะฝะฝั‹ั… ะพะบั€ัƒะถะตะฝะธั ะดะปั ั€ะฐะฑะพั‚ั‹ ั **ะฝะฐัั‚ั€ะพะนะบะฐะผะธ ะฟั€ะธะปะพะถะตะฝะธั** ะฒั‹ ัƒะทะฝะฐะตั‚ะต ะฒ [ะ ะฐััˆะธั€ะตะฝะฝะพะต ั€ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั - ะะฐัั‚ั€ะพะนะบะธ ะธ ะฟะตั€ะตะผะตะฝะฝั‹ะต ัั€ะตะดั‹](./advanced/settings.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/fastapi-cli.md b/docs/ru/docs/fastapi-cli.md index 72cf55e7b0..a46e0053ee 100644 --- a/docs/ru/docs/fastapi-cli.md +++ b/docs/ru/docs/fastapi-cli.md @@ -52,7 +52,7 @@ FastAPI CLI ะฑะตั€ะตั‚ ะฟัƒั‚ัŒ ะบ ะฒะฐัˆะตะน Python-ะฟั€ะพะณั€ะฐะผะผะต (ะฝะฐะฟ ะ”ะปั ั€ะฐะฑะพั‚ั‹ ะฒ ั€ะตะถะธะผะต ะฟั€ะพะดะฐะบัˆะฝ ะฒะผะตัั‚ะพ `fastapi dev` ะฝัƒะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `fastapi run`. ๐Ÿš€ -ะ’ะฝัƒั‚ั€ะธ **FastAPI CLI** ะธัะฟะพะปัŒะทัƒะตั‚ัั Uvicorn, ะฒั‹ัะพะบะพะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝั‹ะน, ะณะพั‚ะพะฒั‹ะน ะบ ั€ะฐะฑะพั‚ะต ะฒ ะฟั€ะพะดะฐะบัˆะฝะต ASGI-ัะตั€ะฒะตั€. ๐Ÿ˜Ž +ะ’ะฝัƒั‚ั€ะธ **FastAPI CLI** ะธัะฟะพะปัŒะทัƒะตั‚ัั Uvicorn, ะฒั‹ัะพะบะพะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝั‹ะน, ะณะพั‚ะพะฒั‹ะน ะบ ั€ะฐะฑะพั‚ะต ะฒ ะฟั€ะพะดะฐะบัˆะฝ ASGI-ัะตั€ะฒะตั€. ๐Ÿ˜Ž ## `fastapi dev` { #fastapi-dev } diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md index 703ff951ef..0bc3dbb2d1 100644 --- a/docs/ru/docs/features.md +++ b/docs/ru/docs/features.md @@ -6,7 +6,7 @@ ### ะžัะฝะพะฒะฐะฝะพ ะฝะฐ ะพั‚ะบั€ั‹ั‚ั‹ั… ัั‚ะฐะฝะดะฐั€ั‚ะฐั… { #based-on-open-standards } -* OpenAPI ะดะปั ัะพะทะดะฐะฝะธั API, ะฒะบะปัŽั‡ะฐั ะพะฑัŠัะฒะปะตะฝะธั ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ, ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ั‚ะตะป ะทะฐะฟั€ะพัะพะฒ, ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะธ ั‚. ะด. +* OpenAPI ะดะปั ัะพะทะดะฐะฝะธั API, ะฒะบะปัŽั‡ะฐั ะพะฑัŠัะฒะปะตะฝะธั ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ, ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ั‚ะตะป ะทะฐะฟั€ะพัะพะฒ, ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะธ ั‚.ะด. * ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั ะผะพะดะตะปะตะน ะดะฐะฝะฝั‹ั… ั ะฟะพะผะพั‰ัŒัŽ JSON Schema (ั‚ะฐะบ ะบะฐะบ ัะฐะผะฐ ัะฟะตั†ะธั„ะธะบะฐั†ะธั OpenAPI ะพัะฝะพะฒะฐะฝะฐ ะฝะฐ JSON Schema). * ะ ะฐะทั€ะฐะฑะพั‚ะฐะฝ ะฒะพะบั€ัƒะณ ัั‚ะธั… ัั‚ะฐะฝะดะฐั€ั‚ะพะฒ, ะฟะพัะปะต ั‚ั‰ะฐั‚ะตะปัŒะฝะพะณะพ ะธั… ะธะทัƒั‡ะตะฝะธั. ะญั‚ะพ ะฝะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะฝะฐะดัั‚ั€ะพะนะบะฐ ะฟะพะฒะตั€ั…. * ะญั‚ะพ ั‚ะฐะบะถะต ะฟะพะทะฒะพะปัะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ **ะณะตะฝะตั€ะฐั†ะธัŽ ะบะปะธะตะฝั‚ัะบะพะณะพ ะบะพะดะฐ** ะฝะฐ ะผะฝะพะณะธั… ัะทั‹ะบะฐั…. @@ -107,7 +107,7 @@ FastAPI ะธะผะตะตั‚ ะฟั€ะพะดัƒะผะฐะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั **ะฟะพ ัƒะผะพะปั‡ะฐะฝ * ะžะฑัŠะตะบั‚ั‹ JSON (`dict`). * ะœะฐััะธะฒ JSON (`list`) ั ะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ะผะธ ั‚ะธะฟะฐะผะธ ัะปะตะผะตะฝั‚ะพะฒ. * ะกั‚ั€ะพะบะพะฒั‹ะต (`str`) ะฟะพะปั ั ะพะณั€ะฐะฝะธั‡ะตะฝะธะตะผ ะผะธะฝะธะผะฐะปัŒะฝะพะน ะธ ะผะฐะบัะธะผะฐะปัŒะฝะพะน ะดะปะธะฝั‹. - * ะงะธัะปะฐ (`int`, `float`) ั ะผะธะฝะธะผะฐะปัŒะฝั‹ะผะธ ะธ ะผะฐะบัะธะผะฐะปัŒะฝั‹ะผะธ ะทะฝะฐั‡ะตะฝะธัะผะธ ะธ ั‚. ะฟ. + * ะงะธัะปะฐ (`int`, `float`) ั ะผะธะฝะธะผะฐะปัŒะฝั‹ะผะธ ะธ ะผะฐะบัะธะผะฐะปัŒะฝั‹ะผะธ ะทะฝะฐั‡ะตะฝะธัะผะธ ะธ ั‚.ะฟ. * ะŸั€ะพะฒะตั€ะบะฐ ะดะปั ะฑะพะปะตะต ัะบะทะพั‚ะธั‡ะตัะบะธั… ั‚ะธะฟะพะฒ, ั‚ะฐะบะธั… ะบะฐะบ: * URL. @@ -126,24 +126,24 @@ FastAPI ะธะผะตะตั‚ ะฟั€ะพะดัƒะผะฐะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั **ะฟะพ ัƒะผะพะปั‡ะฐะฝ * HTTP Basic. * **OAuth2** (ั‚ะฐะบะถะต ั **ั‚ะพะบะตะฝะฐะผะธ JWT**). ะžะทะฝะฐะบะพะผัŒั‚ะตััŒ ั ั€ัƒะบะพะฒะพะดัั‚ะฒะพะผ [OAuth2 ั JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. * ะšะปัŽั‡ะธ API ะฒ: - * ะ—ะฐะณะพะปะพะฒะบะฐั…. + * HTTP-ะทะฐะณะพะปะพะฒะบะฐั…. * ะŸะฐั€ะฐะผะตั‚ั€ะฐั… ะทะฐะฟั€ะพัะพะฒ. * Cookies ะธ ั‚.ะฟ. ะ’ะดะพะฑะฐะฒะพะบ ะฒัะต ั„ัƒะฝะบั†ะธะธ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะพั‚ Starlette (ะฒะบะปัŽั‡ะฐั **ัะตััะธะพะฝะฝั‹ะต cookies**). -ะ’ัะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะธ ะบะพะผะฟะพะฝะตะฝั‚ั‹ ัะฟั€ะพะตะบั‚ะธั€ะพะฒะฐะฝั‹ ะดะปั ะผะฝะพะณะพะบั€ะฐั‚ะฝะพะณะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะธ ะปะตะณะบะพ ะธะฝั‚ะตะณั€ะธั€ัƒัŽั‚ัั ั ะฒะฐัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ั…ั€ะฐะฝะธะปะธั‰ะฐะผะธ ะดะฐะฝะฝั‹ั…, ั€ะตะปัั†ะธะพะฝะฝั‹ะผะธ ะธ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั… ะธ ั‚. ะด. +ะ’ัะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ะธ ะบะพะผะฟะพะฝะตะฝั‚ั‹ ัะฟั€ะพะตะบั‚ะธั€ะพะฒะฐะฝั‹ ะดะปั ะผะฝะพะณะพะบั€ะฐั‚ะฝะพะณะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะธ ะปะตะณะบะพ ะธะฝั‚ะตะณั€ะธั€ัƒัŽั‚ัั ั ะฒะฐัˆะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ั…ั€ะฐะฝะธะปะธั‰ะฐะผะธ ะดะฐะฝะฝั‹ั…, ั€ะตะปัั†ะธะพะฝะฝั‹ะผะธ ะธ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั… ะธ ั‚.ะด. ### ะ’ะฝะตะดั€ะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะตะน { #dependency-injection } -FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ, ะฝะพ ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะผะพั‰ะฝัƒัŽ ัะธัั‚ะตะผัƒ ะ’ะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน. +FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ, ะฝะพ ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะผะพั‰ะฝัƒัŽ ัะธัั‚ะตะผัƒ ะ’ะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน. * ะ”ะฐะถะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะผะพะณัƒั‚ ะธะผะตั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ะธ, ัะพะทะดะฐะฒะฐั ะธะตั€ะฐั€ั…ะธัŽ ะธะปะธ **ยซะณั€ะฐั„ยป ะทะฐะฒะธัะธะผะพัั‚ะตะน**. * ะ’ัั‘ **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ัั** ั„ั€ะตะนะผะฒะพั€ะบะพะผ. * ะ’ัะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะผะพะณัƒั‚ ะทะฐะฟั€ะฐัˆะธะฒะฐั‚ัŒ ะดะฐะฝะฝั‹ะต ะธะท ะทะฐะฟั€ะพัะพะฒ ะธ **ะดะพะฟะพะปะฝัั‚ัŒ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ** ะพะณั€ะฐะฝะธั‡ะตะฝะธัะผะธ ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน. * **ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ะฟั€ะพะฒะตั€ะบะฐ** ะดะฐะถะต ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*, ะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ั… ะฒ ะทะฐะฒะธัะธะผะพัั‚ัั…. -* ะŸะพะดะดะตั€ะถะบะฐ ัะปะพะถะฝั‹ั… ัะธัั‚ะตะผ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน, **ัะพะตะดะธะฝะตะฝะธะน ั ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั…** ะธ ั‚. ะด. -* **ะะธะบะฐะบะธั… ะบะพะผะฟั€ะพะผะธััะพะฒ** ั ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั…, ะธะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะธ ั‚. ะด. ะะพ ะฟั€ะธ ัั‚ะพะผ โ€” ะปั‘ะณะบะฐั ะธะฝั‚ะตะณั€ะฐั†ะธั ัะพ ะฒัะตะผะธ ะฝะธะผะธ. +* ะŸะพะดะดะตั€ะถะบะฐ ัะปะพะถะฝั‹ั… ัะธัั‚ะตะผ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน, **ัะพะตะดะธะฝะตะฝะธะน ั ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั…** ะธ ั‚.ะด. +* **ะะธะบะฐะบะธั… ะบะพะผะฟั€ะพะผะธััะพะฒ** ั ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั…, ะธะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะธ ั‚.ะด. ะะพ ะฟั€ะธ ัั‚ะพะผ โ€” ะปั‘ะณะบะฐั ะธะฝั‚ะตะณั€ะฐั†ะธั ัะพ ะฒัะตะผะธ ะฝะธะผะธ. ### ะะตั‚ ะพะณั€ะฐะฝะธั‡ะตะฝะธะน ะฝะฐ "ะŸะปะฐะณะธะฝั‹" { #unlimited-plug-ins } @@ -153,8 +153,8 @@ FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธ ### ะŸั€ะพะฒะตั€ะตะฝ { #tested } -* 100% ะฟะพะบั€ั‹ั‚ะธะต ั‚ะตัั‚ะฐะผะธ. -* 100% ะฐะฝะฝะพั‚ะธั€ะพะฒะฐะฝะธะต ั‚ะธะฟะพะฒ ะฒ ะบะพะดะพะฒะพะน ะฑะฐะทะต. +* 100% ะฟะพะบั€ั‹ั‚ะธะต ั‚ะตัั‚ะฐะผะธ. +* 100% ะฐะฝะฝะพั‚ะธั€ะพะฒะฐะฝะธะต ั‚ะธะฟะพะฒ ะฒ ะบะพะดะพะฒะพะน ะฑะฐะทะต. * ะ˜ัะฟะพะปัŒะทัƒะตั‚ัั ะฒ ะฟั€ะพะดะฐะบัˆะฝโ€‘ะฟั€ะธะปะพะถะตะฝะธัั…. ## ะ’ะพะทะผะพะถะฝะพัั‚ะธ Starlette { #starlette-features } @@ -179,7 +179,7 @@ FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธ **FastAPI** ะฟะพะปะฝะพัั‚ัŒัŽ ัะพะฒะผะตัั‚ะธะผ ั (ะธ ะพัะฝะพะฒะฐะฝ ะฝะฐ) Pydantic. ะŸะพัั‚ะพะผัƒ ะปัŽะฑะพะน ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะน ะบะพะด Pydantic, ะบะพั‚ะพั€ั‹ะน ัƒ ะฒะฐั ะตัั‚ัŒ, ั‚ะฐะบะถะต ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ. -ะ’ะบะปัŽั‡ะฐั ะฒะฝะตัˆะฝะธะต ะฑะธะฑะปะธะพั‚ะตะบะธ, ั‚ะฐะบะถะต ะพัะฝะพะฒะฐะฝะฝั‹ะต ะฝะฐ Pydantic, ั‚ะฐะบะธะต ะบะฐะบ ORMโ€™ั‹, ODMโ€™ั‹ ะดะปั ะฑะฐะท ะดะฐะฝะฝั‹ั…. +ะ’ะบะปัŽั‡ะฐั ะฒะฝะตัˆะฝะธะต ะฑะธะฑะปะธะพั‚ะตะบะธ, ั‚ะฐะบะถะต ะพัะฝะพะฒะฐะฝะฝั‹ะต ะฝะฐ Pydantic, ั‚ะฐะบะธะต ะบะฐะบ ORMโ€™ั‹, ODMโ€™ั‹ ะดะปั ะฑะฐะท ะดะฐะฝะฝั‹ั…. ะญั‚ะพ ั‚ะฐะบะถะต ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฒั‹ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐะฒะฐั‚ัŒ ั‚ะพั‚ ะถะต ะพะฑัŠะตะบั‚, ะบะพั‚ะพั€ั‹ะน ะฟะพะปัƒั‡ะธะปะธ ะธะท ะทะฐะฟั€ะพัะฐ, **ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ะฑะฐะทัƒ ะดะฐะฝะฝั‹ั…**, ั‚ะฐะบ ะบะฐะบ ะฒัั‘ ะฟั€ะพะฒะตั€ัะตั‚ัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ. @@ -190,10 +190,10 @@ FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ั‡ั€ะตะทะฒั‹ั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธ * **ะะธะบะฐะบะพะน ะฝะตั€ะฒะพั‚ั€ั‘ะฟะบะธ**: * ะะต ะฝัƒะถะฝะพ ะธะทัƒั‡ะฐั‚ัŒ ะฝะพะฒั‹ะต ัั…ะตะผั‹ ะฒ ะผะธะบั€ะพัะทั‹ะบะฐั…. * ะ•ัะปะธ ะฒั‹ ะทะฝะฐะตั‚ะต ั‚ะธะฟั‹ ะฒ Python, ะฒั‹ ะทะฝะฐะตั‚ะต, ะบะฐะบ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Pydantic. -* ะŸั€ะตะบั€ะฐัะฝะพ ัะพั‡ะตั‚ะฐะตั‚ัั ั ะฒะฐัˆะธะผ **IDE/linter/ะผะพะทะณะพะผ**: +* ะŸั€ะตะบั€ะฐัะฝะพ ัะพั‡ะตั‚ะฐะตั‚ัั ั ะฒะฐัˆะธะผ **IDE/ะปะธะฝั‚ะตั€/ะผะพะทะณะพะผ**: * ะŸะพั‚ะพะผัƒ ั‡ั‚ะพ ัั‚ั€ัƒะบั‚ัƒั€ั‹ ะดะฐะฝะฝั‹ั… pydantic โ€” ัั‚ะพ ะฒัะตะณะพ ะปะธัˆัŒ ัะบะทะตะผะฟะปัั€ั‹ ะบะปะฐััะพะฒ, ะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ั… ะฒะฐะผะธ; ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต, ะฟั€ะพะฒะตั€ะบะฐ ะบะพะดะฐ, mypy ะธ ะฒะฐัˆะฐ ะธะฝั‚ัƒะธั†ะธั โ€” ะฒัั‘ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั ะฒะฐัˆะธะผะธ ะฒะฐะปะธะดะธั€ะพะฒะฐะฝะฝั‹ะผะธ ะดะฐะฝะฝั‹ะผะธ. * ะ’ะฐะปะธะดะฐั†ะธั **ัะปะพะถะฝั‹ั… ัั‚ั€ัƒะบั‚ัƒั€**: - * ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะธะตั€ะฐั€ั…ะธั‡ะตัะบะธั… ะผะพะดะตะปะตะน Pydantic; `List`, `Dict` ะธ ั‚. ะฟ. ะธะท ะผะพะดัƒะปั `typing` (ะฒั…ะพะดะธั‚ ะฒ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒัŽ ะฑะธะฑะปะธะพั‚ะตะบัƒ Python). + * ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะธะตั€ะฐั€ั…ะธั‡ะตัะบะธั… ะผะพะดะตะปะตะน Pydantic; `List`, `Dict` ะธ ั‚.ะฟ. ะธะท ะผะพะดัƒะปั `typing` (ะฒั…ะพะดะธั‚ ะฒ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒัŽ ะฑะธะฑะปะธะพั‚ะตะบัƒ Python). * ะ’ะฐะปะธะดะฐั‚ะพั€ั‹ ะฟะพะทะฒะพะปััŽั‚ ั‡ั‘ั‚ะบะพ ะธ ะปะตะณะบะพ ะพะฟั€ะตะดะตะปัั‚ัŒ, ะฟั€ะพะฒะตั€ัั‚ัŒ ะธ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐั‚ัŒ ัะปะพะถะฝั‹ะต ัั…ะตะผั‹ ะดะฐะฝะฝั‹ั… ะฒ ะฒะธะดะต JSON Schema. * ะฃ ะฒะฐั ะผะพะณัƒั‚ ะฑั‹ั‚ัŒ ะณะปัƒะฑะพะบะพ **ะฒะปะพะถะตะฝะฝั‹ะต ะพะฑัŠะตะบั‚ั‹ JSON**, ะธ ะฒัะต ะพะฝะธ ะฑัƒะดัƒั‚ ะฟั€ะพะฒะตั€ะตะฝั‹ ะธ ะฐะฝะฝะพั‚ะธั€ะพะฒะฐะฝั‹. * **ะ ะฐััˆะธั€ัะตะผะพัั‚ัŒ**: diff --git a/docs/ru/docs/history-design-future.md b/docs/ru/docs/history-design-future.md index 9cdd53376d..e2395fe8b9 100644 --- a/docs/ru/docs/history-design-future.md +++ b/docs/ru/docs/history-design-future.md @@ -30,7 +30,7 @@ ## ะ˜ััะปะตะดะพะฒะฐะฝะธั { #investigation } -ะ‘ะปะฐะณะพะดะฐั€ั ะพะฟั‹ั‚ัƒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ััƒั‰ะตัั‚ะฒัƒัŽั‰ะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, ะผั‹ ั ะบะพะปะปะตะณะฐะผะธ ะธะทัƒั‡ะธะปะธ ะธั… ะพัะฝะพะฒะฝั‹ะต ะธะดะตะธ ะธ ัะบะพะผะฑะธะฝะธั€ะพะฒะฐะปะธ ัะพะฑั€ะฐะฝะฝั‹ะต ะทะฝะฐะฝะธั ะฝะฐะธะปัƒั‡ัˆะธะผ ะพะฑั€ะฐะทะพะผ. +ะ˜ัะฟะพะปัŒะทัƒั ะฒัะต ััƒั‰ะตัั‚ะฒะพะฒะฐะฒัˆะธะต ั€ะฐะฝะตะต ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒั‹, ั ะฟะพะปัƒั‡ะธะป ะฒะพะทะผะพะถะฝะพัั‚ัŒ ัƒ ะบะฐะถะดะพะน ะธะท ะฝะธั… ั‡ะตะผัƒ-ั‚ะพ ะฝะฐัƒั‡ะธั‚ัŒัั, ะฟะพะทะฐะธะผัั‚ะฒะพะฒะฐั‚ัŒ ะธะดะตะธ ะธ ะพะฑัŠะตะดะธะฝะธั‚ัŒ ะธั… ะฝะฐะธะปัƒั‡ัˆะธะผ ะพะฑั€ะฐะทะพะผ ะดะปั ัะตะฑั ะธ ะดะปั ะบะพะผะฐะฝะด ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะฒ, ั ะบะพั‚ะพั€ั‹ะผะธ ั ั€ะฐะฑะพั‚ะฐะป. ะะฐะฟั€ะธะผะตั€, ัั‚ะฐะปะพ ััะฝะพ, ั‡ั‚ะพ ะฝะตะพะฑั…ะพะดะธะผะพ ะฑั€ะฐั‚ัŒ ะทะฐ ะพัะฝะพะฒัƒ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ Python. @@ -44,13 +44,13 @@ ะฏ ะฟั€ะพะฒะตั€ะธะป ะฝะตัะบะพะปัŒะบะพ ะธะดะตะน ะฝะฐ ัะฐะผั‹ั… ะฟะพะฟัƒะปัั€ะฝั‹ั… ั€ะตะดะฐะบั‚ะพั€ะฐั… ะบะพะดะฐ: PyCharm, VS Code, ั€ะตะดะฐะบั‚ะพั€ั‹ ะฝะฐ ะฑะฐะทะต Jedi. -ะ”ะฐะฝะฝั‹ะต ะฟะพ ั€ะตะดะฐะบั‚ะพั€ะฐะผ ั ะฒะทัะป ะธะท ะพะฟั€ะพัะฐ Python-ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะฒ, ะบะพั‚ะพั€ั‹ะน ะพั…ะฒะฐั‚ั‹ะฒะฐะตั‚ ะพะบะพะปะพ 80% ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน. +ะกะพะณะปะฐัะฝะพ ะฟะพัะปะตะดะฝะตะผัƒ ะพะฟั€ะพััƒ Python-ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะฒ, ะบะพั‚ะพั€ั‹ะน ะพั…ะฒะฐั‚ั‹ะฒะฐะตั‚ ะพะบะพะปะพ 80% ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน. ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ **FastAPI** ะฑั‹ะป ัะฟะตั†ะธะฐะปัŒะฝะพ ะฟั€ะพะฒะตั€ะตะฝ ะฝะฐ ั€ะตะดะฐะบั‚ะพั€ะฐั…, ะธัะฟะพะปัŒะทัƒะตะผั‹ั… 80% Python-ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะฐะผะธ. ะ˜ ะฟะพัะบะพะปัŒะบัƒ ะฑะพะปัŒัˆะธะฝัั‚ะฒะพ ะดั€ัƒะณะธั… ั€ะตะดะฐะบั‚ะพั€ะพะฒ, ะบะฐะบ ะฟั€ะฐะฒะธะปะพ, ั€ะฐะฑะพั‚ะฐัŽั‚ ะฐะฝะฐะปะพะณะธั‡ะฝั‹ะผ ะพะฑั€ะฐะทะพะผ, ะฒัะต ะตะณะพ ะฟั€ะตะธะผัƒั‰ะตัั‚ะฒะฐ ะดะพะปะถะฝั‹ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะฟั€ะฐะบั‚ะธั‡ะตัะบะธ ะดะปั ะฒัะตั… ั€ะตะดะฐะบั‚ะพั€ะพะฒ. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ั ัะผะพะณ ะฝะฐะนั‚ะธ ะฝะฐะธะปัƒั‡ัˆะธะต ัะฟะพัะพะฑั‹ ัะพะบั€ะฐั‚ะธั‚ัŒ ะดัƒะฑะปะธั€ะพะฒะฐะฝะธะต ะบะพะดะฐ, ะพะฑะตัะฟะตั‡ะธั‚ัŒ ะฟะพะฒัะตะผะตัั‚ะฝะพะต ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต, ะฟั€ะพะฒะตั€ะบัƒ ั‚ะธะฟะพะฒ ะธ ะพัˆะธะฑะพะบ ะธ ั‚.ะด. -ะ˜ ะฒัะต ัั‚ะพ, ั‡ั‚ะพะฑั‹ ะฒัะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะธ ะผะพะณะปะธ ะฟะพะปัƒั‡ะฐั‚ัŒ ะฝะฐะธะปัƒั‡ัˆะธะน ะพะฟั‹ั‚ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ. +ะ˜ ะฒัะต ัั‚ะพ, ั‡ั‚ะพะฑั‹ ะฒัะต ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะธ ะผะพะณะปะธ ะฟะพะปัƒั‡ะฐั‚ัŒ ะฝะฐะธะปัƒั‡ัˆะธะน ะพะฟั‹ั‚ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ. ## ะ—ะฐะฒะธัะธะผะพัั‚ะธ { #requirements } @@ -58,7 +58,7 @@ ะŸะพ ะผะพะธะผ ะฟั€ะตะดะปะพะถะตะฝะธัะผ ะฑั‹ะป ะธะทะผะตะฝั‘ะฝ ะบะพะด ัั‚ะพะณะพ ั„ั€ะตะนะผะฒะพั€ะบะฐ, ั‡ั‚ะพะฑั‹ ัะดะตะปะฐั‚ัŒ ะตะณะพ ะฟะพะปะฝะพัั‚ัŒัŽ ัะพะฒะผะตัั‚ะธะผั‹ะผ ั JSON Schema, ะฟะพะดะดะตั€ะถะฐั‚ัŒ ั€ะฐะทะปะธั‡ะฝั‹ะต ัะฟะพัะพะฑั‹ ะพะฟั€ะตะดะตะปะตะฝะธั ะพะณั€ะฐะฝะธั‡ะตะฝะธะน ะธ ัƒะปัƒั‡ัˆะธั‚ัŒ ะฟะพะดะดะตั€ะถะบัƒ ะฒ ั€ะตะดะฐะบั‚ะพั€ะฐั… ะบะพะดะฐ (ะฟั€ะพะฒะตั€ะบะธ ั‚ะธะฟะพะฒ, ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต) ะฝะฐ ะพัะฝะพะฒะต ั‚ะตัั‚ะพะฒ ะฒ ะฝะตัะบะพะปัŒะบะธั… ั€ะตะดะฐะบั‚ะพั€ะฐั…. -ะ’ ั‚ะพ ะถะต ะฒั€ะตะผั, ั ะฟั€ะธะฝะธะผะฐะป ัƒั‡ะฐัั‚ะธะต ะฒ ั€ะฐะทั€ะฐะฑะพั‚ะบะต **Starlette**, ะตั‰ั‘ ะพะดะธะฝ ะธะท ะพัะฝะพะฒะฝั‹ั… ะบะพะผะฟะพะฝะตะฝั‚ะพะฒ FastAPI. +ะ’ะพ ะฒั€ะตะผั ั€ะฐะทั€ะฐะฑะพั‚ะบะธ ั ั‚ะฐะบะถะต ะฒะฝะตั ะฒะบะปะฐะด ะฒ **Starlette**, ะดั€ัƒะณัƒัŽ ะบะปัŽั‡ะตะฒัƒัŽ ะทะฐะฒะธัะธะผะพัั‚ัŒ. ## ะ ะฐะทั€ะฐะฑะพั‚ะบะฐ { #development } diff --git a/docs/ru/docs/how-to/authentication-error-status-code.md b/docs/ru/docs/how-to/authentication-error-status-code.md index 5675cecc52..596563c541 100644 --- a/docs/ru/docs/how-to/authentication-error-status-code.md +++ b/docs/ru/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ัะพะทะดะฐั‚ัŒ ะฟะพะดะบะปะฐัั `HTTPBearer`, ะบะพั‚ะพั€ั‹ะน ะฑัƒะดะตั‚ ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ ะพัˆะธะฑะบัƒ `403 Forbidden` ะฒะผะตัั‚ะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะน `401 Unauthorized`: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/how-to/conditional-openapi.md b/docs/ru/docs/how-to/conditional-openapi.md index d0845b91e2..6efa30608e 100644 --- a/docs/ru/docs/how-to/conditional-openapi.md +++ b/docs/ru/docs/how-to/conditional-openapi.md @@ -4,9 +4,9 @@ ## ะž ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ, API ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #about-security-apis-and-docs } -ะกะบั€ั‹ั‚ะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… ะธะฝั‚ะตั€ั„ะตะนัะพะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฒ ะฟั€ะพะดะฐะบัˆะฝ *ะฝะต ะดะพะปะถะฝะพ* ะฑั‹ั‚ัŒ ัะฟะพัะพะฑะพะผ ะทะฐั‰ะธั‚ั‹ ะฒะฐัˆะตะณะพ API. +ะกะบั€ั‹ั‚ะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… ะธะฝั‚ะตั€ั„ะตะนัะพะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฒ ะฟั€ะพะดะฐะบัˆะฝ ะฝะต ะดะพะปะถะฝะพ ะฑั‹ั‚ัŒ ัะฟะพัะพะฑะพะผ ะทะฐั‰ะธั‚ั‹ ะฒะฐัˆะตะณะพ API. -ะญั‚ะพ ะฝะต ะดะพะฑะฐะฒะปัะตั‚ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะพะน ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะฒะฐัˆะตะผัƒ API, *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ) ะฒัั‘ ั€ะฐะฒะฝะพ ะฑัƒะดัƒั‚ ะดะพัั‚ัƒะฟะฝั‹ ะฟะพ ัะฒะพะธะผ ะฟัƒั‚ัะผ. +ะญั‚ะพ ะฝะต ะดะพะฑะฐะฒะปัะตั‚ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะพะน ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะฒะฐัˆะตะผัƒ API, ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ (ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะฟัƒั‚ะธ) ะฒัั‘ ั€ะฐะฒะฝะพ ะฑัƒะดัƒั‚ ะดะพัั‚ัƒะฟะฝั‹ ะฟะพ ัะฒะพะธะผ ะฟัƒั‚ัะผ. ะ•ัะปะธ ะฒ ะฒะฐัˆะตะผ ะบะพะดะต ะตัั‚ัŒ ัƒัะทะฒะธะผะพัั‚ัŒ, ะพะฝะฐ ะฒัั‘ ั€ะฐะฒะฝะพ ะพัั‚ะฐะฝะตั‚ัั. @@ -29,7 +29,7 @@ ะะฐะฟั€ะธะผะตั€: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} ะ—ะดะตััŒ ะผั‹ ะพะฑัŠัะฒะปัะตะผ ะฝะฐัั‚ั€ะพะนะบัƒ `openapi_url` ั ั‚ะตะผ ะถะต ะทะฝะฐั‡ะตะฝะธะตะผ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ โ€” `"/openapi.json"`. diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md index b3b1c1ba62..f4f2a0e549 100644 --- a/docs/ru/docs/how-to/configure-swagger-ui.md +++ b/docs/ru/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ FastAPI ะฟั€ะตะพะฑั€ะฐะทัƒะตั‚ ัั‚ะธ ะฝะฐัั‚ั€ะพะนะบะธ ะฒ **JSON**, ั‡ั‚ะพะฑั‹ ะะพ ะฒั‹ ะผะพะถะตั‚ะต ะพั‚ะบะปัŽั‡ะธั‚ัŒ ะตั‘, ัƒัั‚ะฐะฝะพะฒะธะฒ `syntaxHighlight` ะฒ `False`: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} โ€ฆะธ ะฟะพัะปะต ัั‚ะพะณะพ Swagger UI ะฑะพะปัŒัˆะต ะฝะต ะฑัƒะดะตั‚ ะฟะพะบะฐะทั‹ะฒะฐั‚ัŒ ะฟะพะดัะฒะตั‚ะบัƒ ัะธะฝั‚ะฐะบัะธัะฐ: @@ -28,7 +28,7 @@ FastAPI ะฟั€ะตะพะฑั€ะฐะทัƒะตั‚ ัั‚ะธ ะฝะฐัั‚ั€ะพะนะบะธ ะฒ **JSON**, ั‡ั‚ะพะฑั‹ ะะฝะฐะปะพะณะธั‡ะฝะพ ะฒั‹ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ัŒ ั‚ะตะผัƒ ะฟะพะดัะฒะตั‚ะบะธ ัะธะฝั‚ะฐะบัะธัะฐ ั ะบะปัŽั‡ะพะผ "syntaxHighlight.theme" (ะพะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ะฟะพัะตั€ะตะดะธะฝะต ัั‚ะพะธั‚ ั‚ะพั‡ะบะฐ): -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} ะญั‚ะฐ ะฝะฐัั‚ั€ะพะนะบะฐ ะธะทะผะตะฝะธั‚ ั†ะฒะตั‚ะพะฒัƒัŽ ั‚ะตะผัƒ ะฟะพะดัะฒะตั‚ะบะธ ัะธะฝั‚ะฐะบัะธัะฐ: @@ -46,7 +46,7 @@ FastAPI ะฒะบะปัŽั‡ะฐะตั‚ ะฝะตะบะพั‚ะพั€ั‹ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะบะพะฝั„ะธะณัƒั€ ะะฐะฟั€ะธะผะตั€, ั‡ั‚ะพะฑั‹ ะพั‚ะบะปัŽั‡ะธั‚ัŒ `deepLinking`, ะผะพะถะฝะพ ะฟะตั€ะตะดะฐั‚ัŒ ั‚ะฐะบะธะต ะฝะฐัั‚ั€ะพะนะบะธ ะฒ `swagger_ui_parameters`: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## ะ”ั€ัƒะณะธะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ Swagger UI { #other-swagger-ui-parameters } diff --git a/docs/ru/docs/how-to/custom-docs-ui-assets.md b/docs/ru/docs/how-to/custom-docs-ui-assets.md index f524911e65..e3c31b32c5 100644 --- a/docs/ru/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ru/docs/how-to/custom-docs-ui-assets.md @@ -18,7 +18,7 @@ ะงั‚ะพะฑั‹ ะพั‚ะบะปัŽั‡ะธั‚ัŒ ะตั‘, ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะธั… URL ะฒ ะทะฝะฐั‡ะตะฝะธะต `None` ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### ะŸะพะดะบะปัŽั‡ะธั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ { #include-the-custom-docs } @@ -34,7 +34,7 @@ ะะฝะฐะปะพะณะธั‡ะฝะพ ะธ ะดะปั ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | ะกะพะฒะตั‚ @@ -50,7 +50,7 @@ Swagger UI ัะดะตะปะฐะตั‚ ัั‚ะพ ะทะฐ ะฒะฐั ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะฝะพ ะด ะงั‚ะพะฑั‹ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚, ัะพะทะดะฐะนั‚ะต *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ*: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### ะขะตัั‚ะธั€ะพะฒะฐะฝะธะต { #test-it } @@ -118,7 +118,7 @@ Swagger UI ัะดะตะปะฐะตั‚ ัั‚ะพ ะทะฐ ะฒะฐั ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะฝะพ ะด * ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `StaticFiles`. * ะกะผะพะฝั‚ะธั€ัƒะนั‚ะต ัะบะทะตะผะฟะปัั€ `StaticFiles()` ะฒ ะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ะน ะฟัƒั‚ัŒ. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### ะŸั€ะพั‚ะตัั‚ะธั€ัƒะนั‚ะต ัั‚ะฐั‚ะธั‡ะตัะบะธะต ั„ะฐะนะปั‹ { #test-the-static-files } @@ -144,7 +144,7 @@ Swagger UI ัะดะตะปะฐะตั‚ ัั‚ะพ ะทะฐ ะฒะฐั ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะฝะพ ะด ะงั‚ะพะฑั‹ ะพั‚ะบะปัŽั‡ะธั‚ัŒ ะตั‘, ัƒัั‚ะฐะฝะพะฒะธั‚ะต ะธั… URL ะฒ ะทะฝะฐั‡ะตะฝะธะต `None` ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะฒะฐัˆะตะณะพ ะฟั€ะธะปะพะถะตะฝะธั `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### ะŸะพะดะบะปัŽั‡ะธั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ัะพ ัั‚ะฐั‚ะธั‡ะตัะบะธะผะธ ั„ะฐะนะปะฐะผะธ { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Swagger UI ัะดะตะปะฐะตั‚ ัั‚ะพ ะทะฐ ะฒะฐั ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะฝะพ ะด ะะฝะฐะปะพะณะธั‡ะฝะพ ะธ ะดะปั ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | ะกะพะฒะตั‚ @@ -176,7 +176,7 @@ Swagger UI ัะดะตะปะฐะตั‚ ัั‚ะพ ะทะฐ ะฒะฐั ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะฝะพ ะด ะงั‚ะพะฑั‹ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ะฒัั‘ ั€ะฐะฑะพั‚ะฐะตั‚, ัะพะทะดะฐะนั‚ะต *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ*: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### ะขะตัั‚ะธั€ะพะฒะฐะฝะธะต UI ัะพ ัั‚ะฐั‚ะธั‡ะตัะบะธะผะธ ั„ะฐะนะปะฐะผะธ { #test-static-files-ui } diff --git a/docs/ru/docs/how-to/extending-openapi.md b/docs/ru/docs/how-to/extending-openapi.md index 1d69cbdb3a..197a1790a2 100644 --- a/docs/ru/docs/how-to/extending-openapi.md +++ b/docs/ru/docs/how-to/extending-openapi.md @@ -24,7 +24,7 @@ * `version`: ะ’ะตั€ัะธั ะฒะฐัˆะตะณะพ API, ะฝะฐะฟั€ะธะผะตั€ `2.5.0`. * `openapi_version`: ะ’ะตั€ัะธั ะธัะฟะพะปัŒะทัƒะตะผะพะน ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OpenAPI. ะŸะพ ัƒะผะพะปั‡ะฐะฝะธัŽ โ€” ะฟะพัะปะตะดะฝัั: `3.1.0`. * `summary`: ะšั€ะฐั‚ะบะพะต ะพะฟะธัะฐะฝะธะต API. -* `description`: ะžะฟะธัะฐะฝะธะต ะฒะฐัˆะตะณะพ API; ะผะพะถะตั‚ ะฒะบะปัŽั‡ะฐั‚ัŒ Markdown ะธ ะฑัƒะดะตั‚ ะพั‚ะพะฑั€ะฐะถะฐะตั‚ัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. +* `description`: ะžะฟะธัะฐะฝะธะต ะฒะฐัˆะตะณะพ API; ะผะพะถะตั‚ ะฒะบะปัŽั‡ะฐั‚ัŒ Markdown ะธ ะฑัƒะดะตั‚ ะพั‚ะพะฑั€ะฐะถะฐั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. * `routes`: ะกะฟะธัะพะบ ะผะฐั€ัˆั€ัƒั‚ะพะฒ โ€” ัั‚ะพ ะบะฐะถะดะฐั ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝะฐั *ะพะฟะตั€ะฐั†ะธั ะฟัƒั‚ะธ*. ะ‘ะตั€ัƒั‚ัั ะธะท `app.routes`. /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั @@ -43,19 +43,19 @@ ะกะฝะฐั‡ะฐะปะฐ ะฝะฐะฟะธัˆะธั‚ะต ะฟั€ะธะปะพะถะตะฝะธะต **FastAPI** ะบะฐะบ ะพะฑั‹ั‡ะฝะพ: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} ### ะกะณะตะฝะตั€ะธั€ัƒะนั‚ะต ัั…ะตะผัƒ OpenAPI { #generate-the-openapi-schema } ะ—ะฐั‚ะตะผ ะธัะฟะพะปัŒะทัƒะนั‚ะต ั‚ัƒ ะถะต ะฒัะฟะพะผะพะณะฐั‚ะตะปัŒะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ ะดะปั ะณะตะฝะตั€ะฐั†ะธะธ ัั…ะตะผั‹ OpenAPI ะฒะฝัƒั‚ั€ะธ ั„ัƒะฝะบั†ะธะธ `custom_openapi()`: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} ### ะ˜ะทะผะตะฝะธั‚ะต ัั…ะตะผัƒ OpenAPI { #modify-the-openapi-schema } ะขะตะฟะตั€ัŒ ะผะพะถะฝะพ ะดะพะฑะฐะฒะธั‚ัŒ ั€ะฐััˆะธั€ะตะฝะธะต ReDoc, ะดะพะฑะฐะฒะธะฒ ะบะฐัั‚ะพะผะฝั‹ะน `x-logo` ะฒ ยซะพะฑัŠะตะบั‚ยป `info` ะฒ ัั…ะตะผะต OpenAPI: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} ### ะšััˆะธั€ัƒะนั‚ะต ัั…ะตะผัƒ OpenAPI { #cache-the-openapi-schema } @@ -65,13 +65,13 @@ ะžะฝะฐ ะฑัƒะดะตั‚ ัะพะทะดะฐะฝะฐ ะพะดะธะฝ ั€ะฐะท, ะฐ ะทะฐั‚ะตะผ ั‚ะพั‚ ะถะต ะบััˆะธั€ะพะฒะฐะฝะฝั‹ะน ะฒะฐั€ะธะฐะฝั‚ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะดะปั ะฟะพัะปะตะดัƒัŽั‰ะธั… ะทะฐะฟั€ะพัะพะฒ. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} ### ะŸะตั€ะตะพะฟั€ะตะดะตะปะธั‚ะต ะผะตั‚ะพะด { #override-the-method } ะขะตะฟะตั€ัŒ ะฒั‹ ะผะพะถะตั‚ะต ะทะฐะผะตะฝะธั‚ัŒ ะผะตั‚ะพะด `.openapi()` ะฝะฐ ะฒะฐัˆัƒ ะฝะพะฒัƒัŽ ั„ัƒะฝะบั†ะธัŽ. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} ### ะŸั€ะพะฒะตั€ัŒั‚ะต { #check-it } diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md index 50c321e7dd..9e28d61822 100644 --- a/docs/ru/docs/how-to/graphql.md +++ b/docs/ru/docs/how-to/graphql.md @@ -35,7 +35,7 @@ ะ’ะพั‚ ะฝะตะฑะพะปัŒัˆะพะน ะฟั€ะธะผะตั€ ั‚ะพะณะพ, ะบะฐะบ ะผะพะถะฝะพ ะธะฝั‚ะตะณั€ะธั€ะพะฒะฐั‚ัŒ Strawberry ั FastAPI: -{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} ะŸะพะดั€ะพะฑะฝะตะต ะพ Strawberry ะผะพะถะฝะพ ัƒะทะฝะฐั‚ัŒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Strawberry. diff --git a/docs/ru/docs/how-to/index.md b/docs/ru/docs/how-to/index.md index 228c125dde..75e7fff265 100644 --- a/docs/ru/docs/how-to/index.md +++ b/docs/ru/docs/how-to/index.md @@ -1,13 +1,13 @@ # ะšะฐะบ ัะดะตะปะฐั‚ัŒ โ€” ะ ะตั†ะตะฟั‚ั‹ { #how-to-recipes } -ะ—ะดะตััŒ ะฒั‹ ะฝะฐะนะดะตั‚ะต ั€ะฐะทะฝั‹ะต ั€ะตั†ะตะฟั‚ั‹ ะธ ั€ัƒะบะพะฒะพะดัั‚ะฒะฐ ยซะบะฐะบ ัะดะตะปะฐั‚ัŒยป ะฟะพ ั€ะฐะทะปะธั‡ะฝั‹ะผ ั‚ะตะผะฐะผ. +ะ—ะดะตััŒ ะฒั‹ ะฝะฐะนะดะตั‚ะต ั€ะฐะทะฝั‹ะต ั€ะตั†ะตะฟั‚ั‹ ะธ ั€ัƒะบะพะฒะพะดัั‚ะฒะฐ ยซะบะฐะบ ัะดะตะปะฐั‚ัŒยป ะฟะพ **ั€ะฐะทะปะธั‡ะฝั‹ะผ ั‚ะตะผะฐะผ**. -ะ‘ะพะปัŒัˆะธะฝัั‚ะฒะพ ะธะท ัั‚ะธั… ะธะดะตะน ะฑะพะปะตะต-ะผะตะฝะตะต ะฝะตะทะฐะฒะธัะธะผั‹, ะธ ะฒ ะฑะพะปัŒัˆะธะฝัั‚ะฒะต ัะปัƒั‡ะฐะตะฒ ะฒะฐะผ ัั‚ะพะธั‚ ะธะทัƒั‡ะฐั‚ัŒ ะธั… ั‚ะพะปัŒะบะพ ะตัะปะธ ะพะฝะธ ะฝะฐะฟั€ัะผัƒัŽ ะพั‚ะฝะพััั‚ัั ะบ ะฒะฐัˆะตะผัƒ ะฟั€ะพะตะบั‚ัƒ. +ะ‘ะพะปัŒัˆะธะฝัั‚ะฒะพ ะธะท ัั‚ะธั… ะธะดะตะน ะฑะพะปะตะต-ะผะตะฝะตะต **ะฝะตะทะฐะฒะธัะธะผั‹**, ะธ ะฒ ะฑะพะปัŒัˆะธะฝัั‚ะฒะต ัะปัƒั‡ะฐะตะฒ ะฒะฐะผ ัั‚ะพะธั‚ ะธะทัƒั‡ะฐั‚ัŒ ะธั… ั‚ะพะปัŒะบะพ ะตัะปะธ ะพะฝะธ ะฝะฐะฟั€ัะผัƒัŽ ะพั‚ะฝะพััั‚ัั ะบ **ะฒะฐัˆะตะผัƒ ะฟั€ะพะตะบั‚ัƒ**. ะ•ัะปะธ ั‡ั‚ะพ-ั‚ะพ ะบะฐะถะตั‚ัั ะธะฝั‚ะตั€ะตัะฝั‹ะผ ะธ ะฟะพะปะตะทะฝั‹ะผ ะดะปั ะฒะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ, ัะผะตะปะพ ะธะทัƒั‡ะฐะนั‚ะต; ะฒ ะฟั€ะพั‚ะธะฒะฝะพะผ ัะปัƒั‡ะฐะต, ะฒะตั€ะพัั‚ะฝะพ, ะผะพะถะฝะพ ะฟั€ะพัั‚ะพ ะฟั€ะพะฟัƒัั‚ะธั‚ัŒ. /// tip | ะกะพะฒะตั‚ -ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธะทัƒั‡ะธั‚ัŒ FastAPI ัั‚ั€ัƒะบั‚ัƒั€ะธั€ะพะฒะฐะฝะฝะพ (ั€ะตะบะพะผะตะฝะดัƒะตั‚ัั), ะฒะผะตัั‚ะพ ัั‚ะพะณะพ ั‡ะธั‚ะฐะนั‚ะต [ะฃั‡ะตะฑะฝะธะบ โ€” ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](../tutorial/index.md){.internal-link target=_blank} ะฟะพ ะณะปะฐะฒะฐะผ. +ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต **ะธะทัƒั‡ะธั‚ัŒ FastAPI** ัั‚ั€ัƒะบั‚ัƒั€ะธั€ะพะฒะฐะฝะฝะพ (ั€ะตะบะพะผะตะฝะดัƒะตั‚ัั), ะฒะผะตัั‚ะพ ัั‚ะพะณะพ ั‡ะธั‚ะฐะนั‚ะต [ะฃั‡ะตะฑะฝะธะบ โ€” ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](../tutorial/index.md){.internal-link target=_blank} ะฟะพ ะณะปะฐะฒะฐะผ. /// diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index b1a0c9a2e9..877014a086 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -40,7 +40,7 @@ FastAPI โ€” ัั‚ะพ ัะพะฒั€ะตะผะตะฝะฝั‹ะน, ะฑั‹ัั‚ั€ั‹ะน (ะฒั‹ัะพะบะพะฟั€ะพะธ * **ะกะบะพั€ะพัั‚ัŒ**: ะžั‡ะตะฝัŒ ะฒั‹ัะพะบะฐั ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝะพัั‚ัŒ, ะฝะฐ ัƒั€ะพะฒะฝะต **NodeJS** ะธ **Go** (ะฑะปะฐะณะพะดะฐั€ั Starlette ะธ Pydantic). [ะžะดะธะฝ ะธะท ัะฐะผั‹ั… ะฑั‹ัั‚ั€ั‹ั… ะดะพัั‚ัƒะฟะฝั‹ั… ั„ั€ะตะนะผะฒะพั€ะบะพะฒ Python](#performance). * **ะ‘ั‹ัั‚ั€ะพั‚ะฐ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ**: ะฃะฒะตะปะธั‡ัŒั‚ะต ัะบะพั€ะพัั‚ัŒ ั€ะฐะทั€ะฐะฑะพั‚ะบะธ ั„ะธั‡ ะฟั€ะธะผะตั€ะฝะพ ะฝะฐ 200โ€“300%. * * **ะœะตะฝัŒัˆะต ะพัˆะธะฑะพะบ**: ะกะพะบั€ะฐั‚ะธั‚ะต ะฟั€ะธะผะตั€ะฝะพ ะฝะฐ 40% ะบะพะปะธั‡ะตัั‚ะฒะพ ะพัˆะธะฑะพะบ, ะฒั‹ะทะฒะฐะฝะฝั‹ั… ั‡ะตะปะพะฒะตะบะพะผ (ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะผ). * -* **ะ˜ะฝั‚ัƒะธั‚ะธะฒะฝะพัั‚ัŒ**: ะžั‚ะปะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ. ะะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะฒะตะทะดะต. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ะพั‚ะปะฐะดะบัƒ. +* **ะ˜ะฝั‚ัƒะธั‚ะธะฒะฝะพัั‚ัŒ**: ะžั‚ะปะธั‡ะฝะฐั ะฟะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ. ะะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะฒะตะทะดะต. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ะพั‚ะปะฐะดะบัƒ. * **ะŸั€ะพัั‚ะพั‚ะฐ**: ะ ะฐะทั€ะฐะฑะพั‚ะฐะฝ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะตะณะพ ะฑั‹ะปะพ ะปะตะณะบะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธ ะพัะฒะฐะธะฒะฐั‚ัŒ. ะœะตะฝัŒัˆะต ะฒั€ะตะผะตะฝะธ ะฝะฐ ั‡ั‚ะตะฝะธะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. * **ะšั€ะฐั‚ะบะพัั‚ัŒ**: ะœะธะฝะธะผะธะทะธั€ัƒะนั‚ะต ะดัƒะฑะปะธั€ะพะฒะฐะฝะธะต ะบะพะดะฐ. ะะตัะบะพะปัŒะบะพ ะฒะพะทะผะพะถะฝะพัั‚ะตะน ะธะท ะบะฐะถะดะพะณะพ ะพะฑัŠัะฒะปะตะฝะธั ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ. ะœะตะฝัŒัˆะต ะพัˆะธะฑะพะบ. * **ะะฐะดะตะถะฝะพัั‚ัŒ**: ะŸะพะปัƒั‡ะธั‚ะต ะบะพะด, ะณะพั‚ะพะฒั‹ะน ะบ ะฟั€ะพะดะฐะบัˆะฝ. ะก ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน. @@ -127,7 +127,7 @@ FastAPI โ€” ัั‚ะพ ัะพะฒั€ะตะผะตะฝะฝั‹ะน, ะฑั‹ัั‚ั€ั‹ะน (ะฒั‹ัะพะบะพะฟั€ะพะธ -ะ•ัะปะธ ะฒั‹ ัะพะทะดะฐั‘ั‚ะต ะฟั€ะธะปะพะถะตะฝะธะต CLI ะดะปั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะฒ ั‚ะตั€ะผะธะฝะฐะปะต ะฒะผะตัั‚ะพ ะฒะตะฑ-API, ะฟะพัะผะพั‚ั€ะธั‚ะต **Typer**. +ะ•ัะปะธ ะฒั‹ ัะพะทะดะฐั‘ั‚ะต ะฟั€ะธะปะพะถะตะฝะธะต CLI ะดะปั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ะฒ ั‚ะตั€ะผะธะฝะฐะปะต ะฒะผะตัั‚ะพ ะฒะตะฑ-API, ะฟะพัะผะพั‚ั€ะธั‚ะต **Typer**. **Typer** โ€” ะผะปะฐะดัˆะธะน ะฑั€ะฐั‚ FastAPI. ะ˜ ะพะฝ ะทะฐะดัƒะผะฐะฝ ะบะฐะบ **FastAPI ะดะปั CLI**. โŒจ๏ธ ๐Ÿš€ @@ -368,7 +368,7 @@ item: Item * ะ’ะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…: * ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะต ะธ ะฟะพะฝัั‚ะฝั‹ะต ะพัˆะธะฑะบะธ, ะบะพะณะดะฐ ะดะฐะฝะฝั‹ะต ะฝะตะบะพั€ั€ะตะบั‚ะฝั‹. * ะ’ะฐะปะธะดะฐั†ะธัŽ ะดะฐะถะต ะดะปั ะณะปัƒะฑะพะบะพ ะฒะปะพะถะตะฝะฝั‹ั… ะพะฑัŠะตะบั‚ะพะฒ JSON. -* ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะฒั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…: ะธะท ัะตั‚ะธ ะฒ ะดะฐะฝะฝั‹ะต ะธ ั‚ะธะฟั‹ Python. ะงั‚ะตะฝะธะต ะธะท: +* ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะฒั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…: ะธะท ัะตั‚ะธ ะฒ ะดะฐะฝะฝั‹ะต ะธ ั‚ะธะฟั‹ Python. ะงั‚ะตะฝะธะต ะธะท: * JSON. * ะŸะฐั€ะฐะผะตั‚ั€ะพะฒ ะฟัƒั‚ะธ. * ะŸะฐั€ะฐะผะตั‚ั€ะพะฒ ะทะฐะฟั€ะพัะฐ. @@ -376,7 +376,7 @@ item: Item * HTTP-ะทะฐะณะพะปะพะฒะบะพะฒ. * ะคะพั€ะผ. * ะคะฐะนะปะพะฒ. -* ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะฒั‹ั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…: ะธะท ะดะฐะฝะฝั‹ั… ะธ ั‚ะธะฟะพะฒ Python ะฒ ะดะฐะฝะฝั‹ะต ัะตั‚ะธ (ะฝะฐะฟั€ะธะผะตั€, JSON): +* ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะฒั‹ั…ะพะดะฝั‹ั… ะดะฐะฝะฝั‹ั…: ะธะท ะดะฐะฝะฝั‹ั… ะธ ั‚ะธะฟะพะฒ Python ะฒ ะดะฐะฝะฝั‹ะต ัะตั‚ะธ (ะฝะฐะฟั€ะธะผะตั€, JSON): * ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ั‚ะธะฟะพะฒ Python (`str`, `int`, `float`, `bool`, `list` ะธ ั‚.ะด.). * ะžะฑัŠะตะบั‚ั‹ `datetime`. * ะžะฑัŠะตะบั‚ั‹ `UUID`. @@ -439,7 +439,7 @@ item: Item * ะžะฑัŠัะฒะปะตะฝะธะต **ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ** ะธะท ะดั€ัƒะณะธั… ะธัั‚ะพั‡ะฝะธะบะพะฒ: **HTTP-ะทะฐะณะพะปะพะฒะบะธ**, **cookies**, **ะฟะพะปั ั„ะพั€ะผั‹** ะธ **ั„ะฐะนะปั‹**. * ะšะฐะบ ะทะฐะดะฐั‚ัŒ **ะพะณั€ะฐะฝะธั‡ะตะฝะธั ะฒะฐะปะธะดะฐั†ะธะธ** ะฒั€ะพะดะต `maximum_length` ะธะปะธ `regex`. -* ะžั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ ะธ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ัะธัั‚ะตะผัƒ **ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. +* ะžั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ ะธ ะฟั€ะพัั‚ัƒัŽ ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ัะธัั‚ะตะผัƒ **ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. * ะ‘ะตะทะพะฟะฐัะฝะพัั‚ัŒ ะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธัŽ, ะฒะบะปัŽั‡ะฐั ะฟะพะดะดะตั€ะถะบัƒ **OAuth2** ั **JWT ั‚ะพะบะตะฝะฐะผะธ** ะธ **HTTP Basic** ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธัŽ. * ะ‘ะพะปะตะต ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ะต (ะฝะพ ัั‚ะพะปัŒ ะถะต ะฟั€ะพัั‚ั‹ะต) ะฟั€ะธั‘ะผั‹ ะพะฑัŠัะฒะปะตะฝะธั **ะณะปัƒะฑะพะบะพ ะฒะปะพะถะตะฝะฝั‹ั… JSON-ะผะพะดะตะปะตะน** (ัะฟะฐัะธะฑะพ Pydantic). * ะ˜ะฝั‚ะตะณั€ะฐั†ะธัŽ **GraphQL** ั Strawberry ะธ ะดั€ัƒะณะธะผะธ ะฑะธะฑะปะธะพั‚ะตะบะฐะผะธ. @@ -524,7 +524,7 @@ FastAPI ะทะฐะฒะธัะธั‚ ะพั‚ Pydantic ะธ Starlette. * httpx โ€” ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `TestClient`. * jinja2 โ€” ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะพะฝั„ะธะณัƒั€ะฐั†ะธัŽ ัˆะฐะฑะปะพะฝะพะฒ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. -* python-multipart - ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ยซะฟะฐั€ัะธะฝะณยป ั„ะพั€ะผ ั‡ะตั€ะตะท `request.form()`. +* python-multipart - ะพะฑัะทะฐั‚ะตะปะตะฝ, ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ยซะฟะฐั€ัะธะฝะณยป ั„ะพั€ะผ ั‡ะตั€ะตะท `request.form()`. ะ˜ัะฟะพะปัŒะทัƒะตั‚ัั FastAPI: diff --git a/docs/ru/docs/project-generation.md b/docs/ru/docs/project-generation.md index dbedf76fe3..8155457e38 100644 --- a/docs/ru/docs/project-generation.md +++ b/docs/ru/docs/project-generation.md @@ -18,7 +18,7 @@ - ๐Ÿค– ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน ั„ั€ะพะฝั‚ะตะฝะดโ€‘ะบะปะธะตะฝั‚. - ๐Ÿงช [Playwright](https://playwright.dev) ะดะปั Endโ€‘toโ€‘End ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั. - ๐Ÿฆ‡ ะŸะพะดะดะตั€ะถะบะฐ ั‚ั‘ะผะฝะพะน ั‚ะตะผั‹. -- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ะดะปั ั€ะฐะทั€ะฐะฑะพั‚ะบะธ ะธ ะฟั€ะพะดะฐะบัˆะฝะฐ. +- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ะดะปั ั€ะฐะทั€ะฐะฑะพั‚ะบะธ ะธ ะฟั€ะพะดะฐะบัˆะฝ. - ๐Ÿ”’ ะ‘ะตะทะพะฟะฐัะฝะพะต ั…ััˆะธั€ะพะฒะฐะฝะธะต ะฟะฐั€ะพะปะตะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. - ๐Ÿ”‘ ะัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธั ะฟะพ JWTโ€‘ั‚ะพะบะตะฝะฐะผ. - ๐Ÿ“ซ ะ’ะพััั‚ะฐะฝะพะฒะปะตะฝะธะต ะฟะฐั€ะพะปั ะฟะพ ัะปะตะบั‚ั€ะพะฝะฝะพะน ะฟะพั‡ั‚ะต. diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md index ae4a1e2b79..95153c3882 100644 --- a/docs/ru/docs/python-types.md +++ b/docs/ru/docs/python-types.md @@ -2,7 +2,7 @@ Python ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะต ยซะฟะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒยป (ะธั… ั‚ะฐะบะถะต ะฝะฐะทั‹ะฒะฐัŽั‚ ยซะฐะฝะฝะพั‚ะฐั†ะธัะผะธ ั‚ะธะฟะพะฒยป). -ะญั‚ะธ **ยซะฟะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒยป** ะธะปะธ ะฐะฝะฝะพั‚ะฐั†ะธะธ โ€” ัั‚ะพ ัะฟะตั†ะธะฐะปัŒะฝั‹ะน ัะธะฝั‚ะฐะบัะธั, ะฟะพะทะฒะพะปััŽั‰ะธะน ะพะฑัŠัะฒะปัั‚ัŒ ั‚ะธะฟ ะฟะตั€ะตะผะตะฝะฝะพะน. +ะญั‚ะธ **ยซะฟะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒยป** ะธะปะธ ะฐะฝะฝะพั‚ะฐั†ะธะธ โ€” ัั‚ะพ ัะฟะตั†ะธะฐะปัŒะฝั‹ะน ัะธะฝั‚ะฐะบัะธั, ะฟะพะทะฒะพะปััŽั‰ะธะน ะพะฑัŠัะฒะปัั‚ัŒ ั‚ะธะฟ ะฟะตั€ะตะผะตะฝะฝะพะน. ะžะฑัŠัะฒะปัั ั‚ะธะฟั‹ ะดะปั ะฒะฐัˆะธั… ะฟะตั€ะตะผะตะฝะฝั‹ั…, ั€ะตะดะฐะบั‚ะพั€ั‹ ะบะพะดะฐ ะธ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹ ัะผะพะณัƒั‚ ะปัƒั‡ัˆะต ะฒะฐั ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ. @@ -22,7 +22,7 @@ Python ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะต ยซะฟะพะดัะบะฐะทะบ ะ”ะฐะฒะฐะนั‚ะต ะฝะฐั‡ะฝะตะผ ั ะฟั€ะพัั‚ะพะณะพ ะฟั€ะธะผะตั€ะฐ: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} ะ’ั‹ะทะพะฒ ัั‚ะพะน ะฟั€ะพะณั€ะฐะผะผั‹ ะฒั‹ะฒะพะดะธั‚: @@ -34,9 +34,9 @@ John Doe * ะŸั€ะธะฝะธะผะฐะตั‚ `first_name` ะธ `last_name`. * ะŸั€ะตะพะฑั€ะฐะทัƒะตั‚ ะฟะตั€ะฒัƒัŽ ะฑัƒะบะฒัƒ ะบะฐะถะดะพะณะพ ะทะฝะฐั‡ะตะฝะธั ะฒ ะฒะตั€ั…ะฝะธะน ั€ะตะณะธัั‚ั€ ั ะฟะพะผะพั‰ัŒัŽ `title()`. -* ะกะพะตะดะธะฝัะตั‚ ะธั… ะฟั€ะพะฑะตะปะพะผ ะฟะพัะตั€ะตะดะธะฝะต. +* ะกะพะตะดะธะฝัะตั‚ ะธั… ะฟั€ะพะฑะตะปะพะผ ะฟะพัะตั€ะตะดะธะฝะต. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### ะžั‚ั€ะตะดะฐะบั‚ะธั€ัƒะตะผ ะฟั€ะธะผะตั€ { #edit-it } @@ -78,7 +78,7 @@ John Doe ะญั‚ะพ ะธ ะตัั‚ัŒ ยซะฟะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒยป: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} ะญั‚ะพ ะฝะต ั‚ะพ ะถะต ัะฐะผะพะต, ั‡ั‚ะพ ะพะฑัŠัะฒะปะตะฝะธะต ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะบะฐะบ, ะฝะฐะฟั€ะธะผะตั€: @@ -106,7 +106,7 @@ John Doe ะŸะพัะผะพั‚ั€ะธั‚ะต ะฝะฐ ัั‚ัƒ ั„ัƒะฝะบั†ะธัŽ โ€” ัƒ ะฝะตั‘ ัƒะถะต ะตัั‚ัŒ ะฟะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒ: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} ะขะฐะบ ะบะฐะบ ั€ะตะดะฐะบั‚ะพั€ ะบะพะดะฐ ะทะฝะฐะตั‚ ั‚ะธะฟั‹ ะฟะตั€ะตะผะตะฝะฝั‹ั…, ะฒั‹ ะฟะพะปัƒั‡ะฐะตั‚ะต ะฝะต ั‚ะพะปัŒะบะพ ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต, ะฝะพ ะธ ะฟั€ะพะฒะตั€ะบะธ ะพัˆะธะฑะพะบ: @@ -114,7 +114,7 @@ John Doe ะขะตะฟะตั€ัŒ ะฒั‹ ะทะฝะฐะตั‚ะต, ั‡ั‚ะพ ะฝัƒะถะฝะพ ะธัะฟั€ะฐะฒะธั‚ัŒ โ€” ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ `age` ะฒ ัั‚ั€ะพะบัƒ ั ะฟะพะผะพั‰ัŒัŽ `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## ะžะฑัŠัะฒะปะตะฝะธะต ั‚ะธะฟะพะฒ { #declaring-types } @@ -133,29 +133,32 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Generic-ั‚ะธะฟั‹ ั ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ั‚ะธะฟะพะฒ { #generic-types-with-type-parameters } +### ะœะพะดัƒะปัŒ `typing` { #typing-module } -ะ•ัั‚ัŒ ัั‚ั€ัƒะบั‚ัƒั€ั‹ ะดะฐะฝะฝั‹ั…, ะบะพั‚ะพั€ั‹ะต ะผะพะณัƒั‚ ัะพะดะตั€ะถะฐั‚ัŒ ะดั€ัƒะณะธะต ะทะฝะฐั‡ะตะฝะธั, ะฝะฐะฟั€ะธะผะตั€, `dict`, `list`, `set` ะธ `tuple`. ะ˜ ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ะทะฝะฐั‡ะตะฝะธั ั‚ะพะถะต ะผะพะณัƒั‚ ะธะผะตั‚ัŒ ัะฒะพะน ั‚ะธะฟ. +ะ”ะปั ะฝะตะบะพั‚ะพั€ั‹ั… ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ัั†ะตะฝะฐั€ะธะตะฒ ะผะพะถะตั‚ ะฟะพะฝะฐะดะพะฑะธั‚ัŒัั ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ั‡ั‚ะพ-ั‚ะพ ะธะท ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะณะพ ะผะพะดัƒะปั `typing`. ะะฐะฟั€ะธะผะตั€, ะบะพะณะดะฐ ะฒั‹ ั…ะพั‚ะธั‚ะต ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ ั‡ั‚ะพ-ั‚ะพ ะธะผะตะตั‚ ยซะปัŽะฑะพะน ั‚ะธะฟยป, ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Any` ะธะท `typing`: -ะขะฐะบะธะต ั‚ะธะฟั‹, ะบะพั‚ะพั€ั‹ะต ัะพะดะตั€ะถะฐั‚ ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ั‚ะธะฟั‹, ะฝะฐะทั‹ะฒะฐัŽั‚ ยซ**generic**ยป-ั‚ะธะฟะฐะผะธ. ะ˜ ะธั… ะผะพะถะฝะพ ะพะฑัŠัะฒะปัั‚ัŒ, ะฒ ั‚ะพะผ ั‡ะธัะปะต ั ัƒะบะฐะทะฐะฝะธะตะผ ะฒะฝัƒั‚ั€ะตะฝะฝะธั… ั‚ะธะฟะพะฒ. +```python +from typing import Any -ะงั‚ะพะฑั‹ ะพะฑัŠัะฒะปัั‚ัŒ ัั‚ะธ ั‚ะธะฟั‹ ะธ ะธั… ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ั‚ะธะฟั‹, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะน ะผะพะดัƒะปัŒ Python `typing`. ะžะฝ ััƒั‰ะตัั‚ะฒัƒะตั‚ ัะฟะตั†ะธะฐะปัŒะฝะพ ะดะปั ะฟะพะดะดะตั€ะถะบะธ ะฟะพะดัะบะฐะทะพะบ ั‚ะธะฟะพะฒ. -#### ะะพะฒั‹ะต ะฒะตั€ัะธะธ Python { #newer-versions-of-python } - -ะกะธะฝั‚ะฐะบัะธั ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ `typing` **ัะพะฒะผะตัั‚ะธะผ** ัะพ ะฒัะตะผะธ ะฒะตั€ัะธัะผะธ, ะพั‚ Python 3.6 ะดะพ ัะฐะผั‹ั… ะฝะพะฒั‹ั…, ะฒะบะปัŽั‡ะฐั Python 3.9, Python 3.10 ะธ ั‚.ะด. +def some_function(data: Any): + print(data) +``` -ะŸะพ ะผะตั€ะต ั€ะฐะทะฒะธั‚ะธั Python **ะฝะพะฒั‹ะต ะฒะตั€ัะธะธ** ะฟะพะปัƒั‡ะฐัŽั‚ ัƒะปัƒั‡ัˆะตะฝะฝัƒัŽ ะฟะพะดะดะตั€ะถะบัƒ ัั‚ะธั… ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ, ะธ ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะฒะฐะผ ะดะฐะถะต ะฝะต ะฝัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะผะพะดัƒะปัŒ `typing`, ั‡ั‚ะพะฑั‹ ะพะฑัŠัะฒะปัั‚ัŒ ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ. +### Generic-ั‚ะธะฟั‹ { #generic-types } -ะ•ัะปะธ ะฒั‹ ะผะพะถะตั‚ะต ะฒั‹ะฑั€ะฐั‚ัŒ ะฑะพะปะตะต ัะฒะตะถัƒัŽ ะฒะตั€ัะธัŽ Python ะดะปั ะฟั€ะพะตะบั‚ะฐ, ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝัƒัŽ ะฟั€ะพัั‚ะพั‚ัƒ. +ะะตะบะพั‚ะพั€ั‹ะต ั‚ะธะฟั‹ ะผะพะณัƒั‚ ะฟั€ะธะฝะธะผะฐั‚ัŒ ยซะฟะฐั€ะฐะผะตั‚ั€ั‹ ั‚ะธะฟะพะฒยป ะฒ ะบะฒะฐะดั€ะฐั‚ะฝั‹ั… ัะบะพะฑะบะฐั…, ั‡ั‚ะพะฑั‹ ะพะฟั€ะตะดะตะปะธั‚ัŒ ะธั… ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ั‚ะธะฟั‹. ะะฐะฟั€ะธะผะตั€, ยซัะฟะธัะพะบ ัั‚ั€ะพะบยป ะพะฑัŠัะฒะปัะตั‚ัั ะบะฐะบ `list[str]`. -ะ’ะพ ะฒัะตะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะตัั‚ัŒ ะฟั€ะธะผะตั€ั‹, ัะพะฒะผะตัั‚ะธะผั‹ะต ั ะบะฐะถะดะพะน ะฒะตั€ัะธะตะน Python (ะบะพะณะดะฐ ะตัั‚ัŒ ั€ะฐะทะปะธั‡ะธั). +ะขะฐะบะธะต ั‚ะธะฟั‹, ะบะพั‚ะพั€ั‹ะต ะฟั€ะธะฝะธะผะฐัŽั‚ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั‚ะธะฟะพะฒ, ะฝะฐะทั‹ะฒะฐัŽั‚ัั **Generic-ั‚ะธะฟะฐะผะธ** ะธะปะธ **Generics**. -ะะฐะฟั€ะธะผะตั€, ยซ**Python 3.6+**ยป ะพะทะฝะฐั‡ะฐะตั‚ ัะพะฒะผะตัั‚ะธะผะพัั‚ัŒ ั Python 3.6 ะธ ะฒั‹ัˆะต (ะฒะบะปัŽั‡ะฐั 3.7, 3.8, 3.9, 3.10 ะธ ั‚.ะด.). ะ ยซ**Python 3.9+**ยป โ€” ัะพะฒะผะตัั‚ะธะผะพัั‚ัŒ ั Python 3.9 ะธ ะฒั‹ัˆะต (ะฒะบะปัŽั‡ะฐั 3.10 ะธ ั‚.ะฟ.). +ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะต ะถะต ะฒัั‚ั€ะพะตะฝะฝั‹ะต ั‚ะธะฟั‹ ะบะฐะบ generics (ั ะบะฒะฐะดั€ะฐั‚ะฝั‹ะผะธ ัะบะพะฑะบะฐะผะธ ะธ ั‚ะธะฟะฐะผะธ ะฒะฝัƒั‚ั€ะธ): -ะ•ัะปะธ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **ะฟะพัะปะตะดะฝะธะต ะฒะตั€ัะธะธ Python**, ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฟั€ะธะผะตั€ั‹ ะดะปั ัะฐะผะพะน ะฝะพะฒะพะน ะฒะตั€ัะธะธ โ€” ัƒ ะฝะธั… ะฑัƒะดะตั‚ **ัะฐะผั‹ะน ะปัƒั‡ัˆะธะน ะธ ะฟั€ะพัั‚ะพะน ัะธะฝั‚ะฐะบัะธั**, ะฝะฐะฟั€ะธะผะตั€, ยซ**Python 3.10+**ยป. +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -167,7 +170,7 @@ John Doe ะขะฐะบ ะบะฐะบ ัะฟะธัะพะบ โ€” ัั‚ะพ ั‚ะธะฟ, ัะพะดะตั€ะถะฐั‰ะธะน ะฒะฝัƒั‚ั€ะตะฝะฝะธะต ั‚ะธะฟั‹, ัƒะบะฐะถะธั‚ะต ะธั… ะฒ ะบะฒะฐะดั€ะฐั‚ะฝั‹ั… ัะบะพะฑะบะฐั…: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั @@ -193,7 +196,7 @@ John Doe ะะฝะฐะปะพะณะธั‡ะฝะพ ะฒั‹ ะฑั‹ ะพะฑัŠัะฒะธะปะธ `tuple` ะธ `set`: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚: @@ -208,7 +211,7 @@ John Doe ะ’ั‚ะพั€ะพะน ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟะฐ โ€” ะดะปั ะทะฝะฐั‡ะตะฝะธะน `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚: @@ -220,44 +223,20 @@ John Doe ะ’ั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ ะฟะตั€ะตะผะตะฝะฝะฐั ะผะพะถะตั‚ ะฑั‹ั‚ัŒ **ะพะดะฝะธะผ ะธะท ะฝะตัะบะพะปัŒะบะธั… ั‚ะธะฟะพะฒ**, ะฝะฐะฟั€ะธะผะตั€, `int` ะธะปะธ `str`. -ะ’ Python 3.6 ะธ ะฒั‹ัˆะต (ะฒะบะปัŽั‡ะฐั Python 3.10) ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะธะฟ `Union` ะธะท `typing` ะธ ะฟะตั€ะตั‡ะธัะปะธั‚ัŒ ะฒ ะบะฒะฐะดั€ะฐั‚ะฝั‹ั… ัะบะพะฑะบะฐั… ะฒัะต ะดะพะฟัƒัั‚ะธะผั‹ะต ั‚ะธะฟั‹. - -ะ’ Python 3.10 ั‚ะฐะบะถะต ะฟะพัะฒะธะปัั **ะฝะพะฒั‹ะน ัะธะฝั‚ะฐะบัะธั**, ะณะดะต ะดะพะฟัƒัั‚ะธะผั‹ะต ั‚ะธะฟั‹ ะผะพะถะฝะพ ัƒะบะฐะทะฐั‚ัŒ ั‡ะตั€ะตะท ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒัŽ ั‡ะตั€ั‚ัƒ (`|`). +ะงั‚ะพะฑั‹ ัั‚ะพ ะพะฟั€ะตะดะตะปะธั‚ัŒ, ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒัŽ ั‡ะตั€ั‚ัƒ (`|`) ะดะปั ั€ะฐะทะดะตะปะตะฝะธั ะพะฑะพะธั… ั‚ะธะฟะพะฒ. -//// tab | Python 3.10+ +ะญั‚ะพ ะฝะฐะทั‹ะฒะฐะตั‚ัั ยซะพะฑัŠะตะดะธะฝะตะฝะธะตยป (union), ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ะฟะตั€ะตะผะตะฝะฝะฐั ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั‡ะตะผ ัƒะณะพะดะฝะพ ะธะท ะพะฑัŠะตะดะธะฝะตะฝะธั ัั‚ะธั… ะดะฒัƒั… ะผะฝะพะถะตัั‚ะฒ ั‚ะธะฟะพะฒ. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -ะ’ ะพะฑะพะธั… ัะปัƒั‡ะฐัั… ัั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ `item` ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `int` ะธะปะธ `str`. +ะญั‚ะพ ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ `item` ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `int` ะธะปะธ `str`. #### ะ’ะพะทะผะพะถะฝะพ `None` { #possibly-none } ะ’ั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะผะพะถะตั‚ ะธะผะตั‚ัŒ ะพะฟั€ะตะดะตะปั‘ะฝะฝั‹ะน ั‚ะธะฟ, ะฝะฐะฟั€ะธะผะตั€ `str`, ะฝะพ ั‚ะฐะบะถะต ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะธ `None`. -ะ’ Python 3.6 ะธ ะฒั‹ัˆะต (ะฒะบะปัŽั‡ะฐั Python 3.10) ัั‚ะพ ะผะพะถะฝะพ ะพะฑัŠัะฒะธั‚ัŒ, ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐะฒ ะธ ะธัะฟะพะปัŒะทัƒั `Optional` ะธะท ะผะพะดัƒะปั `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `Optional[str]` ะฒะผะตัั‚ะพ ะฟั€ะพัั‚ะพ `str` ะฟะพะทะฒะพะปะธั‚ ั€ะตะดะฐะบั‚ะพั€ัƒ ะบะพะดะฐ ะฟะพะผะพั‡ัŒ ะฒะฐะผ ะพะฑะฝะฐั€ัƒะถะธั‚ัŒ ะพัˆะธะฑะบะธ, ะบะพะณะดะฐ ะฒั‹ ะฟั€ะตะดะฟะพะปะฐะณะฐะตั‚ะต, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะฒัะตะณะดะฐ `str`, ั…ะพั‚ั ะฝะฐ ัะฐะผะพะผ ะดะตะปะต ะพะฝะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะธ `None`. - -`Optional[Something]` โ€” ัั‚ะพ ะฝะฐ ัะฐะผะพะผ ะดะตะปะต ัะพะบั€ะฐั‰ะตะฝะธะต ะดะปั `Union[Something, None]`, ะพะฝะธ ัะบะฒะธะฒะฐะปะตะฝั‚ะฝั‹. - -ะญั‚ะพ ั‚ะฐะบะถะต ะพะทะฝะฐั‡ะฐะตั‚, ั‡ั‚ะพ ะฒ Python 3.10 ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ John Doe //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝั‹ะน ะฒะฐั€ะธะฐะฝั‚ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### ะ˜ัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Union` ะธะปะธ `Optional` { #using-union-or-optional } - -ะ•ัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต ะฒะตั€ัะธัŽ Python ะฝะธะถะต 3.10, ะฒะพั‚ ัะพะฒะตั‚ ั ะผะพะตะน ะฒะตััŒะผะฐ **ััƒะฑัŠะตะบั‚ะธะฒะฝะพะน** ั‚ะพั‡ะบะธ ะทั€ะตะฝะธั: - -* ๐Ÿšจ ะ˜ะทะฑะตะณะฐะนั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั `Optional[SomeType]` -* ะ’ะผะตัั‚ะพ ัั‚ะพะณะพ โœจ **ะธัะฟะพะปัŒะทัƒะนั‚ะต `Union[SomeType, None]`** โœจ. - -ะžะฑะฐ ะฒะฐั€ะธะฐะฝั‚ะฐ ัะบะฒะธะฒะฐะปะตะฝั‚ะฝั‹ ะธ ะฒะฝัƒั‚ั€ะธ ะพะดะธะฝะฐะบะพะฒั‹, ะฝะพ ั ะฑั‹ ั€ะตะบะพะผะตะฝะดะพะฒะฐะป `Union` ะฒะผะตัั‚ะพ `Optional`, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัะปะพะฒะพ ยซ**optional**ยป (ยซะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะนยป) ะผะพะถะตั‚ ะฝะฐะฒะตัั‚ะธ ะฝะฐ ะผั‹ัะปัŒ, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝะพะต, ั…ะพั‚ั ะฝะฐ ัะฐะผะพะผ ะดะตะปะต ะพะฝะพ ะพะทะฝะฐั‡ะฐะตั‚ ยซะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None`ยป, ะดะฐะถะต ะตัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ัะฒะปัะตั‚ัั ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ ะธ ะฒัั‘ ะตั‰ั‘ ะพะฑัะทะฐั‚ะตะปะตะฝ. - -ะœะฝะต ะบะฐะถะตั‚ัั, `Union[SomeType, None]` ะฑะพะปะตะต ัะฒะฝะพ ะฒั‹ั€ะฐะถะฐะตั‚ ัะผั‹ัะป. - -ะ ะตั‡ัŒ ั‚ะพะปัŒะบะพ ะพ ัะปะพะฒะฐั… ะธ ะฝะฐะทะฒะฐะฝะธัั…. ะะพ ัั‚ะธ ัะปะพะฒะฐ ะผะพะณัƒั‚ ะฒะปะธัั‚ัŒ ะฝะฐ ั‚ะพ, ะบะฐะบ ะฒั‹ ะธ ะฒะฐัˆะธ ะบะพะปะปะตะณะธ ะดัƒะผะฐะตั‚ะต ะพ ะบะพะดะต. - -ะ’ ะบะฐั‡ะตัั‚ะฒะต ะฟั€ะธะผะตั€ะฐ ะฒะพะทัŒะผั‘ะผ ัั‚ัƒ ั„ัƒะฝะบั†ะธัŽ: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -ะŸะฐั€ะฐะผะตั‚ั€ `name` ะพะฟั€ะตะดะตะปั‘ะฝ ะบะฐะบ `Optional[str]`, ะฝะพ ะพะฝ **ะฝะต ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะน** โ€” ะฒั‹ ะฝะต ะผะพะถะตั‚ะต ะฒั‹ะทะฒะฐั‚ัŒ ั„ัƒะฝะบั†ะธัŽ ะฑะตะท ัั‚ะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ: - -```Python -say_hi() # ะž ะฝะตั‚, ัั‚ะพ ะฒั‹ะทั‹ะฒะฐะตั‚ ะพัˆะธะฑะบัƒ! ๐Ÿ˜ฑ -``` - -ะŸะฐั€ะฐะผะตั‚ั€ `name` ะฒัั‘ ะตั‰ั‘ **ะพะฑัะทะฐั‚ะตะปะตะฝ** (ะฝะต *optional*), ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัƒ ะฝะตะณะพ ะฝะตั‚ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. ะŸั€ะธ ัั‚ะพะผ `name` ะฟั€ะธะฝะธะผะฐะตั‚ `None` ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต: - -```Python -say_hi(name=None) # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, None ะดะพะฟัƒัั‚ะธะผ ๐ŸŽ‰ -``` - -ะฅะพั€ะพัˆะฐั ะฝะพะฒะพัั‚ัŒ: ะบะฐะบ ั‚ะพะปัŒะบะพ ะฒั‹ ะฟะตั€ะตะนะดั‘ั‚ะต ะฝะฐ Python 3.10, ะพะฑ ัั‚ะพะผ ะผะพะถะฝะพ ะฝะต ะฟะตั€ะตะถะธะฒะฐั‚ัŒ โ€” ะฒั‹ ัะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `|` ะดะปั ะพะฑัŠะตะดะธะฝะตะฝะธั ั‚ะธะฟะพะฒ: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -ะ˜ ั‚ะพะณะดะฐ ะฒะฐะผ ะฝะต ะฟั€ะธะดั‘ั‚ัั ะทะฐะดัƒะผั‹ะฒะฐั‚ัŒัั ะพ ะฝะฐะทะฒะฐะฝะธัั… ะฒั€ะพะดะต `Optional` ะธ `Union`. ๐Ÿ˜Ž - -#### Generic-ั‚ะธะฟั‹ { #generic-types } - -ะขะธะฟั‹, ะบะพั‚ะพั€ั‹ะต ะฟั€ะธะฝะธะผะฐัŽั‚ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั‚ะธะฟะพะฒ ะฒ ะบะฒะฐะดั€ะฐั‚ะฝั‹ั… ัะบะพะฑะบะฐั…, ะฝะฐะทั‹ะฒะฐัŽั‚ัั **Generic-ั‚ะธะฟะฐะผะธ** ะธะปะธ **Generics**, ะฝะฐะฟั€ะธะผะตั€: - -//// tab | Python 3.10+ - -ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะต ะถะต ะฒัั‚ั€ะพะตะฝะฝั‹ะต ั‚ะธะฟั‹ ะบะฐะบ generics (ั ะบะฒะฐะดั€ะฐั‚ะฝั‹ะผะธ ัะบะพะฑะบะฐะผะธ ะธ ั‚ะธะฟะฐะผะธ ะฒะฝัƒั‚ั€ะธ): - -* `list` -* `tuple` -* `set` -* `dict` - -ะ˜, ะบะฐะบ ะธ ะฒ ะฟั€ะตะดั‹ะดัƒั‰ะธั… ะฒะตั€ัะธัั… Python, ะธะท ะผะพะดัƒะปั `typing`: - -* `Union` -* `Optional` -* ...ะธ ะดั€ัƒะณะธะต. - -ะ’ Python 3.10, ะบะฐะบ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒัƒ generics `Union` ะธ `Optional`, ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒัŽ ั‡ะตั€ั‚ัƒ (`|`) ะดะปั ะพะฑัŠัะฒะปะตะฝะธั ะพะฑัŠะตะดะธะฝะตะฝะธะน ั‚ะธะฟะพะฒ โ€” ัั‚ะพ ะณะพั€ะฐะทะดะพ ะปัƒั‡ัˆะต ะธ ะฟั€ะพั‰ะต. - -//// - -//// tab | Python 3.9+ - -ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะต ะถะต ะฒัั‚ั€ะพะตะฝะฝั‹ะต ั‚ะธะฟั‹ ะบะฐะบ generics (ั ะบะฒะฐะดั€ะฐั‚ะฝั‹ะผะธ ัะบะพะฑะบะฐะผะธ ะธ ั‚ะธะฟะฐะผะธ ะฒะฝัƒั‚ั€ะธ): - -* `list` -* `tuple` -* `set` -* `dict` - -ะ˜ generics ะธะท ะผะพะดัƒะปั `typing`: - -* `Union` -* `Optional` -* ...ะธ ะดั€ัƒะณะธะต. - -//// +ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `str | None` ะฒะผะตัั‚ะพ ะฟั€ะพัั‚ะพ `str` ะฟะพะทะฒะพะปะธั‚ ั€ะตะดะฐะบั‚ะพั€ัƒ ะบะพะดะฐ ะฟะพะผะพั‡ัŒ ะฒะฐะผ ะพะฑะฝะฐั€ัƒะถะธั‚ัŒ ะพัˆะธะฑะบะธ, ะบะพะณะดะฐ ะฒั‹ ะฟั€ะตะดะฟะพะปะฐะณะฐะตั‚ะต, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ะฒัะตะณะดะฐ `str`, ั…ะพั‚ั ะฝะฐ ัะฐะผะพะผ ะดะตะปะต ะพะฝะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะธ `None`. ### ะšะปะฐััั‹ ะบะฐะบ ั‚ะธะฟั‹ { #classes-as-types } @@ -363,11 +253,11 @@ say_hi(name=None) # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, None ะดะพะฟัƒัั‚ะธะผ ๐ŸŽ‰ ะ”ะพะฟัƒัั‚ะธะผ, ัƒ ะฒะฐั ะตัั‚ัŒ ะบะปะฐัั `Person` ั ะธะผะตะฝะตะผ: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} ะขะพะณะดะฐ ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะฟะตั€ะตะผะตะฝะฝัƒัŽ ั‚ะธะฟะฐ `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} ะ˜ ัะฝะพะฒะฐ ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะฟะพะปะฝัƒัŽ ะฟะพะดะดะตั€ะถะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ: @@ -401,21 +291,15 @@ say_hi(name=None) # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, None ะดะพะฟัƒัั‚ะธะผ ๐ŸŽ‰ **FastAPI** ั†ะตะปะธะบะพะผ ะพัะฝะพะฒะฐะฝ ะฝะฐ Pydantic. -ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฝะฐะผะฝะพะณะพ ะฑะพะปัŒัˆะต ะฒัะตะณะพ ัั‚ะพะณะพ ะฝะฐ ะฟั€ะฐะบั‚ะธะบะต ะฒ [ะ ัƒะบะพะฒะพะดัั‚ะฒะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](tutorial/index.md){.internal-link target=_blank}. - -/// tip | ะกะพะฒะตั‚ - -ะฃ Pydantic ะตัั‚ัŒ ะพัะพะฑะพะต ะฟะพะฒะตะดะตะฝะธะต, ะบะพะณะดะฐ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต `Optional` ะธะปะธ `Union[Something, None]` ะฑะตะท ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. ะŸะพะดั€ะพะฑะฝะตะต ั‡ะธั‚ะฐะนั‚ะต ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ Pydantic: Required Optional fields. - -/// +ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฝะฐะผะฝะพะณะพ ะฑะพะปัŒัˆะต ะฒัะตะณะพ ัั‚ะพะณะพ ะฝะฐ ะฟั€ะฐะบั‚ะธะบะต ะฒ [ะฃั‡ะตะฑะฝะธะบ - ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](tutorial/index.md){.internal-link target=_blank}. ## ะŸะพะดัะบะฐะทะบะธ ั‚ะธะฟะพะฒ ั ะฐะฝะฝะพั‚ะฐั†ะธัะผะธ ะผะตั‚ะฐะดะฐะฝะฝั‹ั… { #type-hints-with-metadata-annotations } -ะ’ Python ั‚ะฐะบะถะต ะตัั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะพะฑะฐะฒะปัั‚ัŒ **ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะผะตั‚ะฐะดะฐะฝะฝั‹ะต** ะบ ะฟะพะดัะบะฐะทะบะฐะผ ั‚ะธะฟะพะฒ ั ะฟะพะผะพั‰ัŒัŽ `Annotated`. +ะ’ Python ั‚ะฐะบะถะต ะตัั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะพะฑะฐะฒะปัั‚ัŒ **ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะผะตั‚ะฐะดะฐะฝะฝั‹ะต** ะบ ะฟะพะดัะบะฐะทะบะฐะผ ั‚ะธะฟะพะฒ ั ะฟะพะผะพั‰ัŒัŽ `Annotated`. -ะะฐั‡ะธะฝะฐั ั Python 3.9, `Annotated` ะฒั…ะพะดะธั‚ ะฒ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒัŽ ะฑะธะฑะปะธะพั‚ะตะบัƒ, ะฟะพัั‚ะพะผัƒ ะฒั‹ ะผะพะถะตั‚ะต ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะตะณะพ ะธะท `typing`. +ะ’ั‹ ะผะพะถะตั‚ะต ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ `Annotated` ะธะท `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} ะกะฐะผ Python ะฝะธั‡ะตะณะพ ะฝะต ะดะตะปะฐะตั‚ ั `Annotated`. ะ ะดะปั ั€ะตะดะฐะบั‚ะพั€ะพะฒ ะบะพะดะฐ ะธ ะดั€ัƒะณะธั… ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ั‚ะธะฟ ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ `str`. @@ -453,7 +337,7 @@ say_hi(name=None) # ะญั‚ะพ ั€ะฐะฑะพั‚ะฐะตั‚, None ะดะพะฟัƒัั‚ะธะผ ๐ŸŽ‰ * **ะ”ะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธั** API ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ OpenAPI: * ั‡ั‚ะพ ะทะฐั‚ะตะผ ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะผะธ ะธะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. -ะ’ัั‘ ัั‚ะพ ะผะพะถะตั‚ ะทะฒัƒั‡ะฐั‚ัŒ ะฐะฑัั‚ั€ะฐะบั‚ะฝะพ. ะะต ะฒะพะปะฝัƒะนั‚ะตััŒ. ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฒัั‘ ัั‚ะพ ะฒ ะดะตะนัั‚ะฒะธะธ ะฒ [ะ ัƒะบะพะฒะพะดัั‚ะฒะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](tutorial/index.md){.internal-link target=_blank}. +ะ’ัั‘ ัั‚ะพ ะผะพะถะตั‚ ะทะฒัƒั‡ะฐั‚ัŒ ะฐะฑัั‚ั€ะฐะบั‚ะฝะพ. ะะต ะฒะพะปะฝัƒะนั‚ะตััŒ. ะ’ั‹ ัƒะฒะธะดะธั‚ะต ะฒัั‘ ัั‚ะพ ะฒ ะดะตะนัั‚ะฒะธะธ ะฒ [ะฃั‡ะตะฑะฝะธะบ - ะ ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั](tutorial/index.md){.internal-link target=_blank}. ะ’ะฐะถะฝะพ ั‚ะพ, ั‡ั‚ะพ, ะธัะฟะพะปัŒะทัƒั ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ั‚ะธะฟั‹ Python ะฒ ะพะดะฝะพะผ ะผะตัั‚ะต (ะฒะผะตัั‚ะพ ะดะพะฑะฐะฒะปะตะฝะธั ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะบะปะฐััะพะฒ, ะดะตะบะพั€ะฐั‚ะพั€ะพะฒ ะธ ั‚.ะด.), **FastAPI** ัะดะตะปะฐะตั‚ ะทะฐ ะฒะฐั ะฑะพะปัŒัˆัƒัŽ ั‡ะฐัั‚ัŒ ั€ะฐะฑะพั‚ั‹. diff --git a/docs/ru/docs/tutorial/background-tasks.md b/docs/ru/docs/tutorial/background-tasks.md index 8d7b7442f9..9fa7a85029 100644 --- a/docs/ru/docs/tutorial/background-tasks.md +++ b/docs/ru/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ ะกะฝะฐั‡ะฐะปะฐ ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `BackgroundTasks` ะธ ะพะฑัŠัะฒะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ ะฒ ะฒะฐัˆะตะน ั„ัƒะฝะบั†ะธะธโ€‘ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ ั ั‚ะธะฟะพะผ `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** ัะพะทะดะฐัั‚ ะพะฑัŠะตะบั‚ ั‚ะธะฟะฐ `BackgroundTasks` ะดะปั ะฒะฐั ะธ ะฟะตั€ะตะดะฐัั‚ ะตะณะพ ั‡ะตั€ะตะท ัั‚ะพั‚ ะฟะฐั€ะฐะผะตั‚ั€. @@ -31,13 +31,13 @@ ะขะฐะบ ะบะฐะบ ะพะฟะตั€ะฐั†ะธั ะทะฐะฟะธัะธ ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ `async` ะธ `await`, ะผั‹ ะพะฟั€ะตะดะตะปะธะผ ั„ัƒะฝะบั†ะธัŽ ะบะฐะบ ะพะฑั‹ั‡ะฝัƒัŽ `def`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## ะ”ะพะฑะฐะฒะปะตะฝะธะต ั„ะพะฝะพะฒะพะน ะทะฐะดะฐั‡ะธ { #add-the-background-task } ะ’ะฝัƒั‚ั€ะธ ะฒะฐัˆะตะน ั„ัƒะฝะบั†ะธะธโ€‘ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ ะฟะตั€ะตะดะฐะนั‚ะต ั„ัƒะฝะบั†ะธัŽ ะทะฐะดะฐั‡ะธ ะพะฑัŠะตะบั‚ัƒ ั„ะพะฝะพะฒั‹ั… ะทะฐะดะฐั‡ ะผะตั‚ะพะดะพะผ `.add_task()`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` ะฟั€ะธะฝะธะผะฐะตั‚ ัะปะตะดัƒัŽั‰ะธะต ะฐั€ะณัƒะผะตะฝั‚ั‹: @@ -47,7 +47,7 @@ ## ะ’ัั‚ั€ะฐะธะฒะฐะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะตะน { #dependency-injection } -ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `BackgroundTasks` ั‚ะฐะบะถะต ั€ะฐะฑะพั‚ะฐะตั‚ ั ัะธัั‚ะตะผะพะน ะฒัั‚ั€ะฐะธะฒะฐะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟะฐ `BackgroundTasks` ะฝะฐ ะฝะตัะบะพะปัŒะบะธั… ัƒั€ะพะฒะฝัั…: ะฒ ั„ัƒะฝะบั†ะธะธโ€‘ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ, ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ (dependable), ะฒ ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ะธ ะธ ั‚. ะด. +ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `BackgroundTasks` ั‚ะฐะบะถะต ั€ะฐะฑะพั‚ะฐะตั‚ ั ัะธัั‚ะตะผะพะน ะฒัั‚ั€ะฐะธะฒะฐะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟะฐ `BackgroundTasks` ะฝะฐ ะฝะตัะบะพะปัŒะบะธั… ัƒั€ะพะฒะฝัั…: ะฒ ั„ัƒะฝะบั†ะธะธโ€‘ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะต ะฟัƒั‚ะธ, ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ (dependable), ะฒ ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ะธ ะธ ั‚.ะด. **FastAPI** ะทะฝะฐะตั‚, ั‡ั‚ะพ ะดะตะปะฐั‚ัŒ ะฒ ะบะฐะถะดะพะผ ัะปัƒั‡ะฐะต ะธ ะบะฐะบ ะฟะตั€ะตะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะดะธะฝ ะธ ั‚ะพั‚ ะถะต ะพะฑัŠะตะบั‚, ั‚ะฐะบ ั‡ั‚ะพะฑั‹ ะฒัะต ั„ะพะฝะพะฒั‹ะต ะทะฐะดะฐั‡ะธ ะฑั‹ะปะธ ะพะฑัŠะตะดะธะฝะตะฝั‹ ะธ ะทะฐั‚ะตะผ ะฒั‹ะฟะพะปะฝะตะฝั‹ ะฒ ั„ะพะฝะต: @@ -73,7 +73,7 @@ ## ะŸั€ะตะดะพัั‚ะตั€ะตะถะตะฝะธะต { #caveat } -ะ•ัะปะธ ะฒะฐะผ ะฝัƒะถะฝะพ ะฒั‹ะฟะพะปะฝัั‚ัŒ ั‚ัะถะตะปั‹ะต ะฒั‹ั‡ะธัะปะตะฝะธั ะฒ ั„ะพะฝะต, ะธ ะฟั€ะธ ัั‚ะพะผ ะพะฝะธ ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ ะดะพะปะถะฝั‹ ะทะฐะฟัƒัะบะฐั‚ัŒัั ั‚ะตะผ ะถะต ะฟั€ะพั†ะตััะพะผ (ะฝะฐะฟั€ะธะผะตั€, ะฒะฐะผ ะฝะต ะฝัƒะถะฝะพ ะดะตะปะธั‚ัŒัั ะฟะฐะผัั‚ัŒัŽ, ะฟะตั€ะตะผะตะฝะฝั‹ะผะธ ะธ ั‚. ะฟ.), ะฒะฐะผ ะผะพะณัƒั‚ ะฟะพะดะพะนั‚ะธ ะฑะพะปะตะต ะผะพั‰ะฝั‹ะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ั‚ะฐะบะธะต ะบะฐะบ Celery. +ะ•ัะปะธ ะฒะฐะผ ะฝัƒะถะฝะพ ะฒั‹ะฟะพะปะฝัั‚ัŒ ั‚ัะถะตะปั‹ะต ะฒั‹ั‡ะธัะปะตะฝะธั ะฒ ั„ะพะฝะต, ะธ ะฟั€ะธ ัั‚ะพะผ ะพะฝะธ ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ ะดะพะปะถะฝั‹ ะทะฐะฟัƒัะบะฐั‚ัŒัั ั‚ะตะผ ะถะต ะฟั€ะพั†ะตััะพะผ (ะฝะฐะฟั€ะธะผะตั€, ะฒะฐะผ ะฝะต ะฝัƒะถะฝะพ ะดะตะปะธั‚ัŒัั ะฟะฐะผัั‚ัŒัŽ, ะฟะตั€ะตะผะตะฝะฝั‹ะผะธ ะธ ั‚.ะฟ.), ะฒะฐะผ ะผะพะณัƒั‚ ะฟะพะดะพะนั‚ะธ ะฑะพะปะตะต ะผะพั‰ะฝั‹ะต ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ั‚ะฐะบะธะต ะบะฐะบ Celery. ะžะฝะธ ะพะฑั‹ั‡ะฝะพ ั‚ั€ะตะฑัƒัŽั‚ ะฑะพะปะตะต ัะปะพะถะฝะพะน ะบะพะฝั„ะธะณัƒั€ะฐั†ะธะธ, ะผะตะฝะตะดะถะตั€ะฐ ะพั‡ะตั€ะตะดะธ ัะพะพะฑั‰ะตะฝะธะน/ะทะฐะดะฐะฝะธะน (ะฝะฐะฟั€ะธะผะตั€, RabbitMQ ะธะปะธ Redis), ะฝะพ ะฟะพะทะฒะพะปััŽั‚ ะทะฐะฟัƒัะบะฐั‚ัŒ ั„ะพะฝะพะฒั‹ะต ะทะฐะดะฐั‡ะธ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพั†ะตััะฐั… ะธ, ั‡ั‚ะพ ะพัะพะฑะตะฝะฝะพ ะฒะฐะถะฝะพ, ะฝะฐ ะฝะตัะบะพะปัŒะบะธั… ัะตั€ะฒะตั€ะฐั…. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 76304523c9..3fb36d5a22 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ from app.routers import items ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั ะบะปะฐััะพะผ `FastAPI`, ะฒะฐะผ ะฝัƒะถะฝะพ ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ัะพะทะดะฐั‚ัŒ ะตะณะพ ยซัะบะทะตะผะฟะปัั€ยป: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### *ะžะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ั `APIRouter` { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ from app.routers import items ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะตะณะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ะธัะฟะพะปัŒะทะพะฒะฐะปะธ ะฑั‹ ะบะปะฐัั `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} ะ’ั‹ ะผะพะถะตั‚ะต ะดัƒะผะฐั‚ัŒ ะพะฑ `APIRouter` ะบะฐะบ ะพะฑ ยซะผะธะฝะธ-ะบะปะฐััะต `FastAPI`ยป. @@ -117,7 +117,7 @@ from app.routers import items ะขะตะฟะตั€ัŒ ะผั‹ ะฒะพัะฟะพะปัŒะทัƒะตะผัั ะฟั€ะพัั‚ะพะน ะทะฐะฒะธัะธะผะพัั‚ัŒัŽ, ั‡ั‚ะพะฑั‹ ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ ะบะฐัั‚ะพะผะฝั‹ะน HTTP-ะทะฐะณะพะปะพะฒะพะบ `X-Token`: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -149,7 +149,7 @@ from app.routers import items ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะดะพะฑะฐะฒะปัั‚ัŒ ะฒัั‘ ัั‚ะพ ะฒ ะบะฐะถะดัƒัŽ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ*, ะผั‹ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ ัั‚ะพ ะฒ `APIRouter`. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} ะขะฐะบ ะบะฐะบ ะฟัƒั‚ัŒ ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะดะพะปะถะตะฝ ะฝะฐั‡ะธะฝะฐั‚ัŒัั ั `/`, ะบะฐะบ ะทะดะตััŒ: @@ -208,7 +208,7 @@ async def read_item(item_id: str): ะŸะพัั‚ะพะผัƒ ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚ ั `..` ะดะปั ะทะฐะฒะธัะธะผะพัั‚ะตะน: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### ะšะฐะบ ั€ะฐะฑะพั‚ะฐะตั‚ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚ { #how-relative-imports-work } @@ -279,7 +279,7 @@ from ...dependencies import get_token_header ะะพ ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ะผะพะถะตะผ ะดะพะฑะฐะฒะธั‚ัŒ _ะตั‰ั‘_ `tags`, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะฟั€ะธะผะตะฝัั‚ัŒัั ะบ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะฐ ั‚ะฐะบะถะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต `responses`, ัะฟะตั†ะธั„ะธั‡ะฝั‹ะต ะดะปั ัั‚ะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -305,13 +305,13 @@ from ...dependencies import get_token_header ะ˜ ะผั‹ ะดะฐะถะต ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ [ะณะปะพะฑะฐะปัŒะฝั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ](dependencies/global-dependencies.md){.internal-link target=_blank}, ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะพะฑัŠะตะดะธะฝะตะฝั‹ ั ะทะฐะฒะธัะธะผะพัั‚ัะผะธ ะดะปั ะบะฐะถะดะพะณะพ `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### ะ˜ะผะฟะพั€ั‚ `APIRouter` { #import-the-apirouter } ะขะตะฟะตั€ัŒ ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะดั€ัƒะณะธะต ะฟะพะดะผะพะดัƒะปะธ, ัะพะดะตั€ะถะฐั‰ะธะต `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} ะขะฐะบ ะบะฐะบ ั„ะฐะนะปั‹ `app/routers/users.py` ะธ `app/routers/items.py` ัะฒะปััŽั‚ัั ะฟะพะดะผะพะดัƒะปัะผะธ, ะฒั…ะพะดัั‰ะธะผะธ ะฒ ะพะดะธะฝ ะธ ั‚ะพั‚ ะถะต Python-ะฟะฐะบะตั‚ `app`, ะผั‹ ะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะดะฝัƒ ั‚ะพั‡ะบัƒ `.` ะดะปั ะธะผะฟะพั€ั‚ะฐ ั‡ะตั€ะตะท ยซะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะต ะธะผะฟะพั€ั‚ั‹ยป. @@ -374,13 +374,13 @@ from .routers.users import router ะŸะพัั‚ะพะผัƒ, ั‡ั‚ะพะฑั‹ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฑะต ะฒ ะพะดะฝะพะผ ั„ะฐะนะปะต, ะผั‹ ะธะผะฟะพั€ั‚ะธั€ัƒะตะผ ะฟะพะดะผะพะดัƒะปะธ ะฝะฐะฟั€ัะผัƒัŽ: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### ะŸะพะดะบะปัŽั‡ะตะฝะธะต `APIRouter` ะดะปั `users` ะธ `items` { #include-the-apirouters-for-users-and-items } ะขะตะฟะตั€ัŒ ะดะฐะฒะฐะนั‚ะต ะฟะพะดะบะปัŽั‡ะธะผ `router` ะธะท ะฟะพะดะผะพะดัƒะปะตะน `users` ะธ `items`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -420,13 +420,13 @@ from .routers.users import router ะ”ะปั ัั‚ะพะณะพ ะฟั€ะธะผะตั€ะฐ ะฒัั‘ ะฑัƒะดะตั‚ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพ. ะะพ ะดะพะฟัƒัั‚ะธะผ, ั‡ั‚ะพ ะฟะพัะบะพะปัŒะบัƒ ะพะฝ ะธัะฟะพะปัŒะทัƒะตั‚ัั ัะพะฒะผะตัั‚ะฝะพ ั ะดั€ัƒะณะธะผะธ ะฟั€ะพะตะบั‚ะฐะผะธ ะฒ ะพั€ะณะฐะฝะธะทะฐั†ะธะธ, ะผั‹ ะฝะต ะผะพะถะตะผ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐั‚ัŒ ะตะณะพ ะธ ะดะพะฑะฐะฒะธั‚ัŒ `prefix`, `dependencies`, `tags` ะธ ั‚.ะด. ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ะะพ ะผั‹ ะฒัั‘ ั€ะฐะฒะฝะพ ั…ะพั‚ะธะผ ะทะฐะดะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน `prefix` ะฟั€ะธ ะฟะพะดะบะปัŽั‡ะตะฝะธะธ `APIRouter`, ั‡ั‚ะพะฑั‹ ะฒัะต ะตะณะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฝะฐั‡ะธะฝะฐะปะธััŒ ั `/admin`, ั…ะพั‚ะธะผ ะทะฐั‰ะธั‚ะธั‚ัŒ ะตะณะพ ั ะฟะพะผะพั‰ัŒัŽ `dependencies`, ะบะพั‚ะพั€ั‹ะต ัƒ ะฝะฐั ัƒะถะต ะตัั‚ัŒ ะดะปั ัั‚ะพะณะพ ะฟั€ะพะตะบั‚ะฐ, ะธ ั…ะพั‚ะธะผ ะฒะบะปัŽั‡ะธั‚ัŒ `tags` ะธ `responses`. ะœั‹ ะผะพะถะตะผ ะพะฑัŠัะฒะธั‚ัŒ ะฒัั‘ ัั‚ะพ, ะฝะต ะธะทะผะตะฝัั ะธัั…ะพะดะฝั‹ะน `APIRouter`, ะฟะตั€ะตะดะฐะฒ ัั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฒ `app.include_router()`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะธัั…ะพะดะฝั‹ะน `APIRouter` ะฝะต ะฑัƒะดะตั‚ ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐะฝ, ะธ ะผั‹ ัะผะพะถะตะผ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั„ะฐะนะป `app/internal/admin.py` ัั€ะฐะทัƒ ะฒ ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะพะตะบั‚ะฐั… ะพั€ะณะฐะฝะธะทะฐั†ะธะธ. @@ -447,7 +447,7 @@ from .routers.users import router ะ—ะดะตััŒ ะผั‹ ะดะตะปะฐะตะผ ัั‚ะพ... ะฟั€ะพัั‚ะพ ั‡ั‚ะพะฑั‹ ะฟะพะบะฐะทะฐั‚ัŒ, ั‡ั‚ะพ ะผะพะถะตะผ ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} ะธ ัั‚ะพ ะฑัƒะดะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ะบะพั€ั€ะตะบั‚ะฝะพ ะฒะผะตัั‚ะต ัะพ ะฒัะตะผะธ ะดั€ัƒะณะธะผะธ *ะพะฟะตั€ะฐั†ะธัะผะธ ะฟัƒั‚ะธ*, ะดะพะฑะฐะฒะปะตะฝะฝั‹ะผะธ ั‡ะตั€ะตะท `app.include_router()`. diff --git a/docs/ru/docs/tutorial/body-multiple-params.md b/docs/ru/docs/tutorial/body-multiple-params.md index 9d94004947..ddd9c6fdd9 100644 --- a/docs/ru/docs/tutorial/body-multiple-params.md +++ b/docs/ru/docs/tutorial/body-multiple-params.md @@ -52,7 +52,7 @@ } ``` -/// note | ะ’ะฝะธะผะฐะฝะธะต +/// note | ะ—ะฐะผะตั‚ะบะฐ ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ั…ะพั‚ั ะฟะฐั€ะฐะผะตั‚ั€ `item` ะฑั‹ะป ะพะฑัŠัะฒะปะตะฝ ั‚ะฐะบะธะผ ะถะต ัะฟะพัะพะฑะพะผ, ะบะฐะบ ะธ ั€ะฐะฝัŒัˆะต, ั‚ะตะฟะตั€ัŒ ะฟั€ะตะดะฟะพะปะฐะณะฐะตั‚ัั, ั‡ั‚ะพ ะพะฝ ะฝะฐั…ะพะดะธั‚ัั ะฒะฝัƒั‚ั€ะธ ั‚ะตะปะฐ ั ะบะปัŽั‡ะพะผ `item`. @@ -104,12 +104,6 @@ q: str | None = None ``` -ะ˜ะปะธ ะฒ Python 3.9: - -```Python -q: Union[str, None] = None -``` - ะะฐะฟั€ะธะผะตั€: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md index 4c914b97f0..6610b209c2 100644 --- a/docs/ru/docs/tutorial/body-nested-models.md +++ b/docs/ru/docs/tutorial/body-nested-models.md @@ -163,7 +163,7 @@ images: list[Image] ะฝะฐะฟั€ะธะผะตั€ ั‚ะฐะบ: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## ะŸะพะดะดะตั€ะถะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ ะฒะตะทะดะต { #editor-support-everywhere } @@ -193,7 +193,7 @@ images: list[Image] ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะฟั€ะธะฝะธะผะฐะตั‚ะต ะปัŽะฑะพะน `dict`, ะฟะพะบะฐ ัƒ ะฝะตะณะพ ะตัั‚ัŒ ะบะปัŽั‡ะธ ั‚ะธะฟะฐ `int` ัะพ ะทะฝะฐั‡ะตะฝะธัะผะธ ั‚ะธะฟะฐ `float`: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ะกะพะฒะตั‚ diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md index 537d7ebc96..3e55607da5 100644 --- a/docs/ru/docs/tutorial/body.md +++ b/docs/ru/docs/tutorial/body.md @@ -72,7 +72,7 @@ * ะŸั€ะพะฒะตะดั‘ั‚ ะฒะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั…. * ะ•ัะปะธ ะดะฐะฝะฝั‹ะต ะฝะตะบะพั€ั€ะตะบั‚ะฝั‹, ะฒะตั€ะฝั‘ั‚ ะฟะพะฝัั‚ะฝัƒัŽ ะธ ะฝะฐะณะปัะดะฝัƒัŽ ะพัˆะธะฑะบัƒ, ัƒะบะฐะทั‹ะฒะฐัŽั‰ัƒัŽ, ะณะดะต ะธะผะตะฝะฝะพ ะธ ั‡ั‚ะพ ะฑั‹ะปะพ ะฝะตะบะพั€ั€ะตะบั‚ะฝะพ. * ะŸะตั€ะตะดะฐัั‚ ะฟะพะปัƒั‡ะตะฝะฝั‹ะต ะดะฐะฝะฝั‹ะต ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `item`. - * ะŸะพัะบะพะปัŒะบัƒ ะฒะฝัƒั‚ั€ะธ ั„ัƒะฝะบั†ะธะธ ะฒั‹ ะพะฑัŠัะฒะธะปะธ ะตะณะพ ั ั‚ะธะฟะพะผ `Item`, ัƒ ะฒะฐั ะฑัƒะดะตั‚ ะฟะพะดะดะตั€ะถะบะฐ ัะพ ัั‚ะพั€ะพะฝั‹ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ (ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะธ ั‚. ะฟ.) ะดะปั ะฒัะตั… ะฐั‚ั€ะธะฑัƒั‚ะพะฒ ะธ ะธั… ั‚ะธะฟะพะฒ. + * ะŸะพัะบะพะปัŒะบัƒ ะฒะฝัƒั‚ั€ะธ ั„ัƒะฝะบั†ะธะธ ะฒั‹ ะพะฑัŠัะฒะธะปะธ ะตะณะพ ั ั‚ะธะฟะพะผ `Item`, ัƒ ะฒะฐั ะฑัƒะดะตั‚ ะฟะพะดะดะตั€ะถะบะฐ ัะพ ัั‚ะพั€ะพะฝั‹ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ (ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะธ ั‚.ะฟ.) ะดะปั ะฒัะตั… ะฐั‚ั€ะธะฑัƒั‚ะพะฒ ะธ ะธั… ั‚ะธะฟะพะฒ. * ะกะณะตะฝะตั€ะธั€ัƒะตั‚ ะพะฟั€ะตะดะตะปะตะฝะธั JSON Schema ะดะปั ะฒะฐัˆะตะน ะผะพะดะตะปะธ; ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะธ ะฒ ะดั€ัƒะณะธั… ะผะตัั‚ะฐั…, ะตัะปะธ ัั‚ะพ ะธะผะตะตั‚ ัะผั‹ัะป ะดะปั ะฒะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ. * ะญั‚ะธ ัั…ะตะผั‹ ะฑัƒะดัƒั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะน ัั…ะตะผั‹ OpenAPI ะธ ะฑัƒะดัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน UIs. @@ -148,14 +148,14 @@ JSON Schema ะฒะฐัˆะธั… ะผะพะดะตะปะตะน ะฑัƒะดะตั‚ ั‡ะฐัั‚ัŒัŽ ัะณะตะฝะตั€ะธั€ะพ ะŸะฐั€ะฐะผะตั‚ั€ั‹ ั„ัƒะฝะบั†ะธะธ ะฑัƒะดัƒั‚ ั€ะฐัะฟะพะทะฝะฐะฝั‹ ัะปะตะดัƒัŽั‰ะธะผ ะพะฑั€ะฐะทะพะผ: * ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะฐะบะถะต ะพะฑัŠัะฒะปะตะฝ ะฒ **ะฟัƒั‚ะธ**, ะพะฝ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะบะฐะบ path-ะฟะฐั€ะฐะผะตั‚ั€. -* ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะธะผะตะตั‚ **ัะบะฐะปัั€ะฝั‹ะน ั‚ะธะฟ** (ะฝะฐะฟั€ะธะผะตั€, `int`, `float`, `str`, `bool` ะธ ั‚. ะฟ.), ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ **ะทะฐะฟั€ะพัะฐ**. +* ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะธะผะตะตั‚ **ัะบะฐะปัั€ะฝั‹ะน ั‚ะธะฟ** (ะฝะฐะฟั€ะธะผะตั€, `int`, `float`, `str`, `bool` ะธ ั‚.ะฟ.), ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะบะฐะบ ะฟะฐั€ะฐะผะตั‚ั€ **ะทะฐะฟั€ะพัะฐ**. * ะ•ัะปะธ ะฟะฐั€ะฐะผะตั‚ั€ ะพะฑัŠัะฒะปะตะฝ ะบะฐะบ ั‚ะธะฟ **ะผะพะดะตะปะธ Pydantic**, ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะบะฐะบ **ั‚ะตะปะพ** ะทะฐะฟั€ะพัะฐ. /// note | ะ—ะฐะผะตั‚ะบะฐ FastAPI ะฟะพะฝะธะผะฐะตั‚, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต `q` ะฝะต ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ ะธะท-ะทะฐ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. -ะะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ `str | None` (Python 3.10+) ะธะปะธ `Union` ะฒ `Union[str, None]` (Python 3.9+) ะฝะต ะธัะฟะพะปัŒะทัƒัŽั‚ัั FastAPI ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะพะฑัะทะฐั‚ะตะปัŒะฝะพัั‚ะธ; ะพะฝ ัƒะทะฝะฐะตั‚, ั‡ั‚ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัƒ ะฝะตะณะพ ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. +ะะฝะฝะพั‚ะฐั†ะธั ั‚ะธะฟะพะฒ `str | None` ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ัั FastAPI ะดะปั ะพะฟั€ะตะดะตะปะตะฝะธั ะพะฑัะทะฐั‚ะตะปัŒะฝะพัั‚ะธ; ะพะฝ ัƒะทะฝะฐะตั‚, ั‡ั‚ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ะพะฑัะทะฐั‚ะตะปะตะฝ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ัƒ ะฝะตะณะพ ะตัั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `= None`. ะะพ ะดะพะฑะฐะฒะปะตะฝะธะต ะฐะฝะฝะพั‚ะฐั†ะธะน ั‚ะธะฟะพะฒ ะฟะพะทะฒะพะปะธั‚ ะฒะฐัˆะตะผัƒ ั€ะตะดะฐะบั‚ะพั€ัƒ ะบะพะดะฐ ะปัƒั‡ัˆะต ะฒะฐั ะฟะพะดะดะตั€ะถะธะฒะฐั‚ัŒ ะธ ะพะฑะฝะฐั€ัƒะถะธะฒะฐั‚ัŒ ะพัˆะธะฑะบะธ. diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md index 182813afdf..9b34cf0300 100644 --- a/docs/ru/docs/tutorial/cookie-param-models.md +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ ะ’ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปัƒั‡ะฐัั… (ะฝะต ะพัะพะฑะพ ั‡ะฐัั‚ะพ ะฒัั‚ั€ะตั‡ะฐัŽั‰ะธั…ัั) ะฒะฐะผ ะผะพะถะตั‚ ะฟะพะฝะฐะดะพะฑะธั‚ัŒัั **ะพะณั€ะฐะฝะธั‡ะธั‚ัŒ** cookies, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะปัƒั‡ะฐั‚ัŒ. -ะขะตะฟะตั€ัŒ ะฒะฐัˆ API ัะฐะผ ั€ะตัˆะฐะตั‚, ะฟั€ะธะฝะธะผะฐั‚ัŒ ะปะธ cookies. ๐Ÿคช๐Ÿช +ะขะตะฟะตั€ัŒ ัƒ ะฒะฐัˆะตะณะพ API ะตัั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะบะพะฝั‚ั€ะพะปะธั€ะพะฒะฐั‚ัŒ ัะฒะพั‘ ัะพะณะปะฐัะธะต ะฝะฐ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต cookie. ๐Ÿคช๐Ÿช ะ’ั‹ ะผะพะถะตั‚ะต ัะบะพะฝั„ะธะณัƒั€ะธั€ะพะฒะฐั‚ัŒ Pydantic-ะผะพะดะตะปัŒ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะทะฐะฟั€ะตั‚ะธั‚ัŒ (`forbid`) ะปัŽะฑั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต (`extra`) ะฟะพะปั: @@ -54,9 +54,9 @@ ะ•ัะปะธ ะบะปะธะตะฝั‚ ะฟะพะฟั€ะพะฑัƒะตั‚ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ **ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต cookies**, ั‚ะพ ะฒ ะพั‚ะฒะตั‚ ะพะฝ ะฟะพะปัƒั‡ะธั‚ **ะพัˆะธะฑะบัƒ**. -ะ‘ะตะดะฝั‹ะต ะฑะฐะฝะฝะตั€ั‹ cookies, ะพะฝะธ ะฒัะตะผะธ ัะธะปะฐะผะธ ะฟั‹ั‚ะฐัŽั‚ัั ะฟะพะปัƒั‡ะธั‚ัŒ ะฒะฐัˆะต ัะพะณะปะฐัะธะต โ€” ะธ ะฒัั‘ ั€ะฐะดะธ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ API ะตะณะพ ะพั‚ะบะปะพะฝะธะป. ๐Ÿช +ะ‘ะตะดะฝั‹ะต ะฑะฐะฝะฝะตั€ั‹ cookies, ะพะฝะธ ะฒัะตะผะธ ัะธะปะฐะผะธ ะฟั‹ั‚ะฐัŽั‚ัั ะฟะพะปัƒั‡ะธั‚ัŒ ะฒะฐัˆะต ัะพะณะปะฐัะธะต โ€” ะธ ะฒัั‘ ั€ะฐะดะธ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ API ะตะณะพ ะพั‚ะบะปะพะฝะธะป. ๐Ÿช -ะะฐะฟั€ะธะผะตั€, ะตัะปะธ ะบะปะธะตะฝั‚ ะฟะพะฟั‹ั‚ะฐะตั‚ัั ะพั‚ะฟั€ะฐะฒะธั‚ัŒ cookie `santa_tracker` ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ `good-list-please`, ั‚ะพ ะฒ ะพั‚ะฒะตั‚ ะพะฝ ะฟะพะปัƒั‡ะธั‚ **ะพัˆะธะฑะบัƒ**, ัะพะพะฑั‰ะฐัŽั‰ัƒัŽ ะตะผัƒ, ั‡ั‚ะพ cookie `santa_tracker` ะฝะต ั€ะฐะทั€ะตัˆั‘ะฝ: +ะะฐะฟั€ะธะผะตั€, ะตัะปะธ ะบะปะธะตะฝั‚ ะฟะพะฟั‹ั‚ะฐะตั‚ัั ะพั‚ะฟั€ะฐะฒะธั‚ัŒ cookie `santa_tracker` ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ `good-list-please`, ั‚ะพ ะฒ ะพั‚ะฒะตั‚ ะพะฝ ะฟะพะปัƒั‡ะธั‚ **ะพัˆะธะฑะบัƒ**, ัะพะพะฑั‰ะฐัŽั‰ัƒัŽ ะตะผัƒ, ั‡ั‚ะพ `santa_tracker` cookie ะฝะต ั€ะฐะทั€ะตัˆั‘ะฝ: ```json { @@ -73,4 +73,4 @@ ## ะ—ะฐะบะปัŽั‡ะตะฝะธะต { #summary } -ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **Pydantic-ะผะพะดะตะปะธ** ะดะปั ะพะฑัŠัะฒะปะตะฝะธั **cookies** ะฒ **FastAPI**. ๐Ÿ˜Ž +ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **Pydantic-ะผะพะดะตะปะธ** ะดะปั ะพะฑัŠัะฒะปะตะฝะธั **cookies** ะฒ **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/ru/docs/tutorial/cookie-params.md b/docs/ru/docs/tutorial/cookie-params.md index 2d2eff8d7c..8dad3873e4 100644 --- a/docs/ru/docs/tutorial/cookie-params.md +++ b/docs/ru/docs/tutorial/cookie-params.md @@ -32,11 +32,11 @@ /// info | ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั -ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ, ะฟะพัะบะพะปัŒะบัƒ ะฑั€ะฐัƒะทะตั€ั‹ ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐัŽั‚ cookies ะพัะพะฑั‹ะผ ะพะฑั€ะฐะทะพะผ ะธ ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะพะฝะธ ะฝะต ะฟะพะทะฒะพะปััŽั‚ JavaScript ะฟั€ะพัั‚ะพ ั‚ะฐะบ ะฟะพะปัƒั‡ะฐั‚ัŒ ะบ ะฝะธะผ ะดะพัั‚ัƒะฟ. +ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ, ะฟะพัะบะพะปัŒะบัƒ **ะฑั€ะฐัƒะทะตั€ั‹ ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐัŽั‚ cookies** ะพัะพะฑั‹ะผ ะพะฑั€ะฐะทะพะผ ะธ ยซะทะฐ ะบัƒะปะธัะฐะผะธยป, ะพะฝะธ **ะฝะต** ะฟะพะทะฒะพะปััŽั‚ **JavaScript** ะฟั€ะพัั‚ะพ ั‚ะฐะบ ะฟะพะปัƒั‡ะฐั‚ัŒ ะบ ะฝะธะผ ะดะพัั‚ัƒะฟ. -ะ•ัะปะธ ะฒั‹ ะพั‚ะบั€ะพะตั‚ะต ะธะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API ะฝะฐ `/docs`, ะฒั‹ ัะผะพะถะตั‚ะต ัƒะฒะธะดะตั‚ัŒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ ะฟะพ cookies ะดะปั ะฒะฐัˆะธั… ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ. +ะ•ัะปะธ ะฒั‹ ะพั‚ะบั€ะพะตั‚ะต **ะธะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ API** ะฝะฐ `/docs`, ะฒั‹ ัะผะพะถะตั‚ะต ัƒะฒะธะดะตั‚ัŒ **ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ** ะฟะพ cookies ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. -ะะพ ะดะฐะถะต ะตัะปะธ ะฒั‹ ะทะฐะฟะพะปะฝะธั‚ะต ะดะฐะฝะฝั‹ะต ะธ ะฝะฐะถะผั‘ั‚ะต ยซExecuteยป, ะฟะพัะบะพะปัŒะบัƒ UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ั€ะฐะฑะพั‚ะฐะตั‚ ั JavaScript, cookies ะพั‚ะฟั€ะฐะฒะปะตะฝั‹ ะฝะต ะฑัƒะดัƒั‚, ะธ ะฒั‹ ัƒะฒะธะดะธั‚ะต ัะพะพะฑั‰ะตะฝะธะต ะพะฑ ะพัˆะธะฑะบะต, ะบะฐะบ ะฑัƒะดั‚ะพ ะฒั‹ ะฝะต ัƒะบะฐะทะฐะปะธ ะฝะธะบะฐะบะธั… ะทะฝะฐั‡ะตะฝะธะน. +ะะพ ะดะฐะถะต ะตัะปะธ ะฒั‹ **ะทะฐะฟะพะปะฝะธั‚ะต ะดะฐะฝะฝั‹ะต** ะธ ะฝะฐะถะผั‘ั‚ะต ยซExecuteยป, ะฟะพัะบะพะปัŒะบัƒ UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ั€ะฐะฑะพั‚ะฐะตั‚ ั **JavaScript**, cookies ะพั‚ะฟั€ะฐะฒะปะตะฝั‹ ะฝะต ะฑัƒะดัƒั‚, ะธ ะฒั‹ ัƒะฒะธะดะธั‚ะต ัะพะพะฑั‰ะตะฝะธะต ะพะฑ **ะพัˆะธะฑะบะต**, ะบะฐะบ ะฑัƒะดั‚ะพ ะฒั‹ ะฝะต ัƒะบะฐะทะฐะปะธ ะฝะธะบะฐะบะธั… ะทะฝะฐั‡ะตะฝะธะน. /// diff --git a/docs/ru/docs/tutorial/cors.md b/docs/ru/docs/tutorial/cors.md index d09a31e2c3..feaa159683 100644 --- a/docs/ru/docs/tutorial/cors.md +++ b/docs/ru/docs/tutorial/cors.md @@ -46,7 +46,7 @@ * ะžั‚ะดะตะปัŒะฝั‹ั… HTTP-ะผะตั‚ะพะดะพะฒ (`POST`, `PUT`) ะธะปะธ ะฒัะตั… ะฒะผะตัั‚ะต, ะธัะฟะพะปัŒะทัƒั `"*"`. * ะžั‚ะดะตะปัŒะฝั‹ั… HTTP-ะทะฐะณะพะปะพะฒะบะพะฒ ะธะปะธ ะฒัะตั… ะฒะผะตัั‚ะต, ะธัะฟะพะปัŒะทัƒั `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} `CORSMiddleware` ะธัะฟะพะปัŒะทัƒะตั‚ "ะทะฐะฟั€ะตั‰ะฐัŽั‰ะธะต" ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ะฟะพัั‚ะพะผัƒ ะฒะฐะผ ะฝัƒะถะฝะพ ัะฒะฝั‹ะผ ะพะฑั€ะฐะทะพะผ ั€ะฐะทั€ะตัˆะธั‚ัŒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ะพั‚ะดะตะปัŒะฝั‹ั… ะธัั‚ะพั‡ะฝะธะบะพะฒ, ะผะตั‚ะพะดะพะฒ ะธะปะธ ะทะฐะณะพะปะพะฒะบะพะฒ, ั‡ั‚ะพะฑั‹ ะฑั€ะฐัƒะทะตั€ั‹ ะผะพะณะปะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธั… ะฒ ะบั€ะพัั-ะดะพะผะตะฝะฝะพะผ ะบะพะฝั‚ะตะบัั‚ะต. @@ -77,7 +77,7 @@ ## ะ‘ะพะปัŒัˆะต ะธะฝั„ะพั€ะผะฐั†ะธะธ { #more-info } -ะ”ะปั ะฟะพะปัƒั‡ะตะฝะธั ะฑะพะปะตะต ะฟะพะดั€ะพะฑะฝะพะน ะธะฝั„ะพั€ะผะฐั†ะธะธ ะพ CORS ะพะฑั€ะฐั‚ะธั‚ะตััŒ ะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ CORS ะพั‚ Mozilla. +ะ”ะปั ะฟะพะปัƒั‡ะตะฝะธั ะฑะพะปะตะต ะฟะพะดั€ะพะฑะฝะพะน ะธะฝั„ะพั€ะผะฐั†ะธะธ ะพ CORS ะพะฑั€ะฐั‚ะธั‚ะตััŒ ะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ CORS ะพั‚ Mozilla. /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md index 51955835e6..483fe80869 100644 --- a/docs/ru/docs/tutorial/debugging.md +++ b/docs/ru/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ ะ’ ะฒะฐัˆะตะผ FastAPI ะฟั€ะธะปะพะถะตะฝะธะธ, ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต ะธ ะฒั‹ะทะพะฒะธั‚ะต `uvicorn` ะฝะฐะฟั€ัะผัƒัŽ: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### ะžะฟะธัะฐะฝะธะต `__name__ == "__main__"` { #about-name-main } @@ -42,7 +42,7 @@ $ python myapp.py ั‚ะพ ะฒัั‚ั€ะพะตะฝะฝะฐั ะฟะตั€ะตะผะตะฝะฝะฐั `__name__`, ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ัะพะทะดะฐะฒะฐะตะผะฐั Python ะฒ ะฒะฐัˆะตะผ ั„ะฐะนะปะต, ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ัั‚ั€ะพะบะพะฒะพะณะพ ั‚ะธะฟะฐ `"__main__"`. -ะขะพะณะดะฐ ะฒั‹ะฟะพะปะฝะธั‚ัั ัƒัะปะพะฒะธะต ะธ ัั‚ะฐ ั‡ะฐัั‚ัŒ ะบะพะดะฐ: +ะขะพะณะดะฐ ัั‚ะฐ ั‡ะฐัั‚ัŒ ะบะพะดะฐ: ```Python uvicorn.run(app, host="0.0.0.0", port=8000) @@ -59,7 +59,7 @@ $ python myapp.py ```Python from myapp import app -# Some more code +# ะ•ั‰ะต ะฝะตะผะฝะพะณะพ ะบะพะดะฐ ``` ั‚ะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ัะพะทะดะฐะฒะฐะตะผะฐั ะฒะฝัƒั‚ั€ะธ ั„ะฐะนะปะฐ `myapp.py` ะฟะตั€ะตะผะตะฝะฝะฐั `__name__` ะฑัƒะดะตั‚ ะธะผะตั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะพั‚ะปะธั‡ะฐัŽั‰ะตะตัั ะพั‚ `"__main__"`. @@ -99,7 +99,7 @@ from myapp import app --- -ะ•ัะปะธ ะธัะฟะพะปัŒะทัƒะตั‚ะต Pycharm, ะฒั‹ ะผะพะถะตั‚ะต ะฒั‹ะฟะพะปะฝะธั‚ัŒ ัะปะตะดัƒัŽั‰ะธะต ัˆะฐะณะธ: +ะ•ัะปะธ ะธัะฟะพะปัŒะทัƒะตั‚ะต PyCharm, ะฒั‹ ะผะพะถะตั‚ะต ะฒั‹ะฟะพะปะฝะธั‚ัŒ ัะปะตะดัƒัŽั‰ะธะต ัˆะฐะณะธ: * ะžั‚ะบั€ั‹ั‚ัŒ "Run" ะผะตะฝัŽ. * ะ’ั‹ะฑั€ะฐั‚ัŒ ะพะฟั†ะธัŽ "Debug...". diff --git a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md index a38e885d43..9a3171e9f1 100644 --- a/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md @@ -4,7 +4,7 @@ ## `dict` ะธะท ะฟั€ะตะดั‹ะดัƒั‰ะตะณะพ ะฟั€ะธะผะตั€ะฐ { #a-dict-from-the-previous-example } -ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะตะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะฒะพะทะฒั€ะฐั‰ะฐะปะธ `dict` ะธะท ะฝะฐัˆะตะน ะทะฐะฒะธัะธะผะพัั‚ะธ: +ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะตะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะฒะพะทะฒั€ะฐั‰ะฐะปะธ `dict` ะธะท ะฝะฐัˆะตะน ะทะฐะฒะธัะธะผะพัั‚ะธ (ยซdependableยป): {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} @@ -67,7 +67,7 @@ fluffy = Cat(name="Mr Fluffy") ะญั‚ะพ ะพั‚ะฝะพัะธั‚ัั ะธ ะบ ะฒั‹ะทั‹ะฒะฐะตะผั‹ะผ ะพะฑัŠะตะบั‚ะฐะผ ะฑะตะท ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ. ะ ะฐะฑะพั‚ะฐ ั ะฝะธะผะธ ะฟั€ะพะธัั…ะพะดะธั‚ ั‚ะพั‡ะฝะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะดะปั *ั„ัƒะฝะบั†ะธะน-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะพะฒ ะฟัƒั‚ะธ* ะฑะตะท ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ. -ะขะตะฟะตั€ัŒ ะผั‹ ะผะพะถะตะผ ะธะทะผะตะฝะธั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ `common_parameters`, ัƒะบะฐะทะฐะฝะฝัƒัŽ ะฒั‹ัˆะต, ะฝะฐ ะบะปะฐัั `CommonQueryParams`: +ะขะตะฟะตั€ัŒ ะผั‹ ะผะพะถะตะผ ะธะทะผะตะฝะธั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ (ยซdependableยป) `common_parameters`, ัƒะบะฐะทะฐะฝะฝัƒัŽ ะฒั‹ัˆะต, ะฝะฐ ะบะปะฐัั `CommonQueryParams`: {* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} @@ -101,7 +101,7 @@ fluffy = Cat(name="Mr Fluffy") ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ะฒ ะฟั€ะธะฒะตะดะตะฝะฝะพะผ ะฒั‹ัˆะต ะบะพะดะต ะผั‹ ะดะฒะฐ ั€ะฐะทะฐ ะฟะธัˆะตะผ `CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -137,7 +137,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฟะตั€ะฒั‹ะน `CommonQueryParams`, ะฒ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -163,7 +163,7 @@ commons: CommonQueryParams ... ะะฐ ัะฐะผะพะผ ะดะตะปะต ะผะพะถะฝะพ ะฝะฐะฟะธัะฐั‚ัŒ ะฟั€ะพัั‚ะพ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams) ะะพ ะฒั‹ ะฒะธะดะธั‚ะต, ั‡ั‚ะพ ะทะดะตััŒ ะผั‹ ะธะผะตะตะผ ะฝะตะบะพั‚ะพั€ะพะต ะฟะพะฒั‚ะพั€ะตะฝะธะต ะบะพะดะฐ, ะดะฒะฐะถะดั‹ ะฝะฐะฟะธัะฐะฒ `CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ะ’ะผะตัั‚ะพ ั‚ะพะณะพ ั‡ั‚ะพะฑั‹ ะฟะธัะฐั‚ัŒ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...ัะปะตะดัƒะตั‚ ะฝะฐะฟะธัะฐั‚ัŒ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index ef56644485..4cfc4e699f 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ ะญั‚ะพ ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ `list` ัะพัั‚ะพัั‰ะธะน ะธะท `Depends()`: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} ะ—ะฐะฒะธัะธะผะพัั‚ะธ ะธะท dependencies ะฒั‹ะฟะพะปะฝัั‚ัั ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะพะฑั‹ั‡ะฝั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ. ะะพ ะธั… ะทะฝะฐั‡ะตะฝะธั (ะตัะปะธ ะพะฝะธ ะฑั‹ะปะธ) ะฝะต ะฑัƒะดัƒั‚ ะฟะตั€ะตะดะฐะฝั‹ ะฒ *ั„ัƒะฝะบั†ะธัŽ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. @@ -30,7 +30,7 @@ /// info | ะŸั€ะธะผะตั‡ะฐะฝะธะต -ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะฒั‹ะดัƒะผะฐะฝะฝั‹ะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะทะฐะณะพะปะพะฒะบะธ `X-Key` ะธ `X-Token`. +ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ะฒั‹ะดัƒะผะฐะฝะฝั‹ะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต HTTP-ะทะฐะณะพะปะพะฒะบะธ `X-Key` ะธ `X-Token`. ะะพ ะฒ ั€ะตะฐะปัŒะฝั‹ั… ะฟั€ะพะตะบั‚ะฐั…, ะฟั€ะธ ะฒะฝะตะดั€ะตะฝะธะธ ัะธัั‚ะตะผั‹ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ, ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ะฑะพะปัŒัˆะต ะฟะพะปัŒะทั‹ ะธัะฟะพะปัŒะทัƒั ะธะฝั‚ะตะณั€ะธั€ะพะฒะฐะฝะฝั‹ะต [ัั€ะตะดัั‚ะฒะฐ ะทะฐั‰ะธั‚ั‹ (ัะปะตะดัƒัŽั‰ะฐั ะณะปะฐะฒะฐ)](../security/index.md){.internal-link target=_blank}. @@ -42,15 +42,15 @@ ### ะขั€ะตะฑะพะฒะฐะฝะธั ะบ ะทะฐะฒะธัะธะผะพัั‚ัะผ { #dependency-requirements } -ะžะฝะธ ะผะพะณัƒั‚ ะพะฑัŠัะฒะปัั‚ัŒ ั‚ั€ะตะฑะพะฒะฐะฝะธั ะบ ะทะฐะฟั€ะพััƒ (ะฝะฐะฟั€ะธะผะตั€ ะทะฐะณะพะปะพะฒะบะธ) ะธะปะธ ะดั€ัƒะณะธะต ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ะธ: +ะžะฝะธ ะผะพะณัƒั‚ ะพะฑัŠัะฒะปัั‚ัŒ ั‚ั€ะตะฑะพะฒะฐะฝะธั ะบ ะทะฐะฟั€ะพััƒ (ะฝะฐะฟั€ะธะผะตั€ HTTP-ะทะฐะณะพะปะพะฒะบะธ) ะธะปะธ ะดั€ัƒะณะธะต ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ะธ: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### ะ’ั‹ะทะพะฒ ะธัะบะปัŽั‡ะตะฝะธะน { #raise-exceptions } ะ—ะฐะฒะธัะธะผะพัั‚ะธ ะธะท dependencies ะผะพะณัƒั‚ ะฒั‹ะทั‹ะฒะฐั‚ัŒ ะธัะบะปัŽั‡ะตะฝะธั ั ะฟะพะผะพั‰ัŒัŽ `raise`, ะบะฐะบ ะธ ะพะฑั‹ั‡ะฝั‹ะต ะทะฐะฒะธัะธะผะพัั‚ะธ: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### ะ’ะพะทะฒั€ะฐั‰ะฐะตะผั‹ะต ะทะฝะฐั‡ะตะฝะธั { #return-values } @@ -58,7 +58,7 @@ ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒั‹ ะผะพะถะตั‚ะต ะฟะตั€ะตะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฑั‹ั‡ะฝัƒัŽ ะทะฐะฒะธัะธะผะพัั‚ัŒ (ะฒะพะทะฒั€ะฐั‰ะฐัŽั‰ัƒัŽ ะทะฝะฐั‡ะตะฝะธะต), ะบะพั‚ะพั€ัƒัŽ ะฒั‹ ัƒะถะต ะธัะฟะพะปัŒะทัƒะตั‚ะต ะณะดะต-ั‚ะพ ะฒ ะดั€ัƒะณะพะผ ะผะตัั‚ะต, ะธ ั…ะพั‚ั ะทะฝะฐั‡ะตะฝะธะต ะฝะต ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั, ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝะตะฝะฐ: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## ะ—ะฐะฒะธัะธะผะพัั‚ะธ ะดะปั ะณั€ัƒะฟะฟั‹ *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะตะน* { #dependencies-for-a-group-of-path-operations } diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md index dc202db616..03a7c083c4 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # ะ—ะฐะฒะธัะธะผะพัั‚ะธ ั yield { #dependencies-with-yield } -FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพะปะฝััŽั‚ ะฝะตะบะพั‚ะพั€ั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ัˆะฐะณะธ ะฟะพัะปะต ะทะฐะฒะตั€ัˆะตะฝะธั. +FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพะปะฝััŽั‚ ะฝะตะบะพั‚ะพั€ั‹ะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ัˆะฐะณะธ ะฟะพัะปะต ะทะฐะฒะตั€ัˆะตะฝะธั. ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต `yield` ะฒะผะตัั‚ะพ `return`, ะฐ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ัˆะฐะณะธ (ะบะพะด) ะฝะฐะฟะธัˆะธั‚ะต ะฟะพัะปะต ะฝะตะณะพ. @@ -29,15 +29,15 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะŸะตั€ะตะด ัะพะทะดะฐะฝะธะตะผ ะพั‚ะฒะตั‚ะฐ ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝะตะฝ ั‚ะพะปัŒะบะพ ะบะพะด ะดะพ ะธ ะฒะบะปัŽั‡ะฐั ะพะฟะตั€ะฐั‚ะพั€ `yield`: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} ะ—ะฝะฐั‡ะตะฝะธะต, ะฟะพะปัƒั‡ะตะฝะฝะพะต ะธะท `yield`, ะฒะฝะตะดั€ัะตั‚ัั ะฒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะธ ะดั€ัƒะณะธะต ะทะฐะฒะธัะธะผะพัั‚ะธ: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} ะšะพะด, ัะปะตะดัƒัŽั‰ะธะน ะทะฐ ะพะฟะตั€ะฐั‚ะพั€ะพะผ `yield`, ะฒั‹ะฟะพะปะฝัะตั‚ัั ะฟะพัะปะต ะพั‚ะฒะตั‚ะฐ: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -57,7 +57,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `finally`, ั‡ั‚ะพะฑั‹ ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะต ัˆะฐะณะธ ะฟั€ะธ ะฒั‹ั…ะพะดะต ะฒั‹ะฟะพะปะฝะตะฝั‹ ะฝะตะทะฐะฒะธัะธะผะพ ะพั‚ ั‚ะพะณะพ, ะฑั‹ะปะพ ะปะธ ะธัะบะปัŽั‡ะตะฝะธะต ะธะปะธ ะฝะตั‚. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## ะŸะพะดะทะฐะฒะธัะธะผะพัั‚ะธ ั `yield` { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะะฐะฟั€ะธะผะตั€, `dependency_c` ะผะพะถะตั‚ ะทะฐะฒะธัะตั‚ัŒ ะพั‚ `dependency_b`, ะฐ `dependency_b` โ€” ะพั‚ `dependency_a`: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} ะ˜ ะฒัะต ะพะฝะธ ะผะพะณัƒั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `yield`. @@ -75,7 +75,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะ˜, ะฒ ัะฒะพัŽ ะพั‡ะตั€ะตะดัŒ, `dependency_b` ะฝัƒะถะดะฐะตั‚ัั ะฒ ั‚ะพะผ, ั‡ั‚ะพะฑั‹ ะทะฝะฐั‡ะตะฝะธะต ะธะท `dependency_a` (ะทะดะตััŒ `dep_a`) ะฑั‹ะปะพ ะดะพัั‚ัƒะฟะฝะพ ะดะปั ะตั‘ ะบะพะดะฐ ะฒั‹ั…ะพะดะฐ. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต ะผะพะถะฝะพ ะธะผะตั‚ัŒ ั‡ะฐัั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ะตะน ั `yield`, ั‡ะฐัั‚ัŒ โ€” ั `return`, ะธ ะบะฐะบะธะต-ั‚ะพ ะธะท ะฝะธั… ะผะพะณัƒั‚ ะทะฐะฒะธัะตั‚ัŒ ะดั€ัƒะณ ะพั‚ ะดั€ัƒะณะฐ. @@ -109,7 +109,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะตั€ะตั…ะฒะฐั‚ั‹ะฒะฐั‚ัŒ ะธัะบะปัŽั‡ะตะฝะธั ะธ ั„ะพั€ะผะธั€ะพะฒะฐั‚ัŒ ะฝะฐ ะธั… ะพัะฝะพะฒะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน ะพั‚ะฒะตั‚, ัะพะทะดะฐะนั‚ะต [ะŸะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะน ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ะธัะบะปัŽั‡ะตะฝะธะน](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. @@ -117,7 +117,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะ•ัะปะธ ะฒั‹ ะปะพะฒะธั‚ะต ะธัะบะปัŽั‡ะตะฝะธะต ั ะฟะพะผะพั‰ัŒัŽ `except` ะฒ ะทะฐะฒะธัะธะผะพัั‚ะธ ั `yield` ะธ ะฝะต ะฒั‹ะทั‹ะฒะฐะตั‚ะต ะตะณะพ ัะฝะพะฒะฐ (ะธะปะธ ะฝะต ะฒั‹ะทั‹ะฒะฐะตั‚ะต ะฝะพะฒะพะต ะธัะบะปัŽั‡ะตะฝะธะต), FastAPI ะฝะต ัะผะพะถะตั‚ ะทะฐะผะตั‚ะธั‚ัŒ, ั‡ั‚ะพ ะฑั‹ะปะพ ะธัะบะปัŽั‡ะตะฝะธะต โ€” ั‚ะฐะบ ะถะต, ะบะฐะบ ัั‚ะพ ะฟั€ะพะธัั…ะพะดะธั‚ ะฒ ะพะฑั‹ั‡ะฝะพะผ Python: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะบะปะธะตะฝั‚ ะฟะพะปัƒั‡ะธั‚ *HTTP 500 Internal Server Error*, ะบะฐะบ ะธ ะดะพะปะถะฝะพ ะฑั‹ั‚ัŒ, ะฟะพัะบะพะปัŒะบัƒ ะผั‹ ะฝะต ะฒั‹ะทั‹ะฒะฐะตะผ `HTTPException` ะธะปะธ ั‡ั‚ะพ-ั‚ะพ ะฟะพะดะพะฑะฝะพะต, ะฝะพ ะฝะฐ ัะตั€ะฒะตั€ะต **ะฝะต ะฑัƒะดะตั‚ ะฝะธะบะฐะบะธั… ะปะพะณะพะฒ** ะธะปะธ ะดั€ัƒะณะธั… ัƒะบะฐะทะฐะฝะธะน ะฝะฐ ั‚ะพ, ะบะฐะบะฐั ะฑั‹ะปะฐ ะพัˆะธะฑะบะฐ. ๐Ÿ˜ฑ @@ -127,7 +127,7 @@ FastAPI ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะทะฐะฒะธัะธะผะพัั‚ะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ะฟะพ ะ’ั‹ ะผะพะถะตั‚ะต ะฟะพะฒั‚ะพั€ะฝะพ ะฒั‹ะทะฒะฐั‚ัŒ ั‚ะพ ะถะต ัะฐะผะพะต ะธัะบะปัŽั‡ะตะฝะธะต ั ะฟะพะผะพั‰ัŒัŽ `raise`: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} ะขะตะฟะตั€ัŒ ะบะปะธะตะฝั‚ ะฟะพะปัƒั‡ะธั‚ ั‚ะพั‚ ะถะต *HTTP 500 Internal Server Error*, ะฝะพ ะฝะฐ ัะตั€ะฒะตั€ะต ะฒ ะปะพะณะฐั… ะฑัƒะดะตั‚ ะฝะฐัˆะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะพะต `InternalError`. ๐Ÿ˜Ž @@ -190,7 +190,7 @@ participant tasks as Background tasks ะะพ ะตัะปะธ ะฒั‹ ะทะฝะฐะตั‚ะต, ั‡ั‚ะพ ะฝะต ะฑัƒะดะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฟะพัะปะต ะฒะพะทะฒั€ะฐั‚ะฐ ะธะท *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Depends(scope="function")`, ั‡ั‚ะพะฑั‹ ัะพะพะฑั‰ะธั‚ัŒ FastAPI, ั‡ั‚ะพ ะพะฝ ะดะพะปะถะตะฝ ะทะฐะบั€ั‹ั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฟะพัะปะต ะฒะพะทะฒั€ะฐั‚ะฐ ะธะท *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*, ะฝะพ **ะดะพ ั‚ะพะณะพ**, ะบะฐะบ **ะพั‚ะฒะตั‚ ะฑัƒะดะตั‚ ะพั‚ะฟั€ะฐะฒะปะตะฝ**. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` ะฟั€ะธะฝะธะผะฐะตั‚ ะฟะฐั€ะฐะผะตั‚ั€ `scope`, ะบะพั‚ะพั€ั‹ะน ะผะพะถะตั‚ ะฑั‹ั‚ัŒ: @@ -269,7 +269,7 @@ with open("./somefile.txt") as f: ะ˜ั… ั‚ะฐะบะถะต ะผะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒะฝัƒั‚ั€ะธ ะทะฐะฒะธัะธะผะพัั‚ะตะน **FastAPI** ั `yield`, ะฟั€ะธะผะตะฝัั ะพะฟะตั€ะฐั‚ะพั€ั‹ `with` ะธะปะธ `async with` ะฒะฝัƒั‚ั€ะธ ั„ัƒะฝะบั†ะธะธ ะทะฐะฒะธัะธะผะพัั‚ะธ: -{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *} +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ diff --git a/docs/ru/docs/tutorial/dependencies/global-dependencies.md b/docs/ru/docs/tutorial/dependencies/global-dependencies.md index 2347c6dd83..f488322a9e 100644 --- a/docs/ru/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/global-dependencies.md @@ -6,10 +6,10 @@ ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะพะฝะธ ะฑัƒะดัƒั‚ ะฟั€ะธะผะตะฝัั‚ัŒัั ะบะพ ะฒัะตะผ *ะพะฟะตั€ะฐั†ะธัะผ ะฟัƒั‚ะธ* ะฒ ะฟั€ะธะปะพะถะตะฝะธะธ: -{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} ะ’ัะต ัะฟะพัะพะฑั‹ [ะดะพะฑะฐะฒะปะตะฝะธั `dependencies` (ะทะฐะฒะธัะธะผะพัั‚ะตะน) ะฒ *ะดะตะบะพั€ะฐั‚ะพั€ะฐั… ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ะฟั€ะธะผะตะฝะธะผั‹, ะฝะพ ะฒ ะดะฐะฝะฝะพะผ ัะปัƒั‡ะฐะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะฟั€ะธะผะตะฝััŽั‚ัั ะบะพ ะฒัะตะผ *ะพะฟะตั€ะฐั†ะธัะผ ะฟัƒั‚ะธ* ะฟั€ะธะปะพะถะตะฝะธั. ## ะ—ะฐะฒะธัะธะผะพัั‚ะธ ะดะปั ะณั€ัƒะฟะฟ *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ* { #dependencies-for-groups-of-path-operations } -ะŸะพะทะดะฝะตะต, ั‡ะธั‚ะฐั ะพ ั‚ะพะผ, ะบะฐะบ ัั‚ั€ัƒะบั‚ัƒั€ะธั€ะพะฒะฐั‚ัŒ ะฑะพะปะตะต ะบั€ัƒะฟะฝั‹ะต [ะฟั€ะธะปะพะถะตะฝะธั, ัะพะดะตั€ะถะฐั‰ะธะต ะผะฝะพะณะพ ั„ะฐะนะปะพะฒ](../../tutorial/bigger-applications.md){.internal-link target=_blank}, ะฒั‹ ัƒะทะฝะฐะตั‚ะต, ะบะฐะบ ะพะฑัŠัะฒะธั‚ัŒ ะพะดะธะฝ ะฟะฐั€ะฐะผะตั‚ั€ `dependencies` ะดะปั ั†ะตะปะพะน ะณั€ัƒะฟะฟั‹ *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*. +ะŸะพะทะดะฝะตะต, ั‡ะธั‚ะฐั ะพ ั‚ะพะผ, ะบะฐะบ ัั‚ั€ัƒะบั‚ัƒั€ะธั€ะพะฒะฐั‚ัŒ ะฑะพะปะตะต ะบั€ัƒะฟะฝั‹ะต ะฟั€ะธะปะพะถะตะฝะธั ([ะฟั€ะธะปะพะถะตะฝะธั, ัะพะดะตั€ะถะฐั‰ะธะต ะผะฝะพะณะพ ั„ะฐะนะปะพะฒ](../../tutorial/bigger-applications.md){.internal-link target=_blank}), ะฒะพะทะผะพะถะฝะพ, ัะพัั‚ะพัั‰ะธะต ะธะท ะฝะตัะบะพะปัŒะบะธั… ั„ะฐะนะปะพะฒ, ะฒั‹ ัƒะทะฝะฐะตั‚ะต, ะบะฐะบ ะพะฑัŠัะฒะธั‚ัŒ ะพะดะธะฝ ะฟะฐั€ะฐะผะตั‚ั€ `dependencies` ะดะปั ั†ะตะปะพะน ะณั€ัƒะฟะฟั‹ *ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*. diff --git a/docs/ru/docs/tutorial/dependencies/index.md b/docs/ru/docs/tutorial/dependencies/index.md index 98b0d59c6a..29f735ab61 100644 --- a/docs/ru/docs/tutorial/dependencies/index.md +++ b/docs/ru/docs/tutorial/dependencies/index.md @@ -1,6 +1,6 @@ # ะ—ะฐะฒะธัะธะผะพัั‚ะธ { #dependencies } -**FastAPI** ะธะผะตะตั‚ ะพั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ, ะฝะพ ะธะฝั‚ัƒะธั‚ะธะฒะฝัƒัŽ ัะธัั‚ะตะผัƒ **ะ˜ะฝัŠะตะบั†ะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. +**FastAPI** ะธะผะตะตั‚ ะพั‡ะตะฝัŒ ะผะพั‰ะฝัƒัŽ, ะฝะพ ะธะฝั‚ัƒะธั‚ะธะฒะฝัƒัŽ ัะธัั‚ะตะผัƒ **ะ˜ะฝัŠะตะบั†ะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน**. ะžะฝะฐ ัะฟั€ะพะตะบั‚ะธั€ะพะฒะฐะฝะฐ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะฑั‹ั‚ัŒ ะพั‡ะตะฝัŒ ะฟั€ะพัั‚ะพะน ะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ ะธ ะพะฑะปะตะณั‡ะฐั‚ัŒ ะปัŽะฑะพะผัƒ ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบัƒ ะธะฝั‚ะตะณั€ะฐั†ะธัŽ ะดั€ัƒะณะธั… ะบะพะผะฟะพะฝะตะฝั‚ะพะฒ ั **FastAPI**. diff --git a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md index da31a6682f..3c71defd89 100644 --- a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query ะ•ัะปะธ ะพะดะฝะฐ ะธะท ะฒะฐัˆะธั… ะทะฐะฒะธัะธะผะพัั‚ะตะน ะพะฑัŠัะฒะปะตะฝะฐ ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ะดะปั ะพะดะฝะพะน ะธ ั‚ะพะน ะถะต *ั„ัƒะฝะบั†ะธะธ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*, ะฝะฐะฟั€ะธะผะตั€, ะฝะตัะบะพะปัŒะบะพ ะทะฐะฒะธัะธะผะพัั‚ะตะน ะธะผะตัŽั‚ ะพะฑั‰ัƒัŽ ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ัŒ, **FastAPI** ะฑัƒะดะตั‚ ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะฒั‹ะทั‹ะฒะฐั‚ัŒ ัั‚ัƒ ะฟะพะดะทะฐะฒะธัะธะผะพัั‚ัŒ ะฝัƒะถะฝะพ ั‚ะพะปัŒะบะพ ะพะดะธะฝ ั€ะฐะท ะทะฐ ะทะฐะฟั€ะพั. -ะŸั€ะธ ัั‚ะพะผ ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะต ะทะฝะฐั‡ะตะฝะธะต ะฑัƒะดะตั‚ ัะพั…ั€ะฐะฝะตะฝะพ ะฒ "ะบััˆ" ะธ ะฑัƒะดะตั‚ ะฟะตั€ะตะดะฐะฝะพ ะฒัะตะผ "ะทะฐะฒะธัะธะผั‹ะผ" ั„ัƒะฝะบั†ะธัะผ, ะบะพั‚ะพั€ั‹ะต ะฝัƒะถะดะฐัŽั‚ัั ะฒ ะฝะตะผ ะฒะฝัƒั‚ั€ะธ ัั‚ะพะณะพ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะทะฐะฟั€ะพัะฐ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ ะฒั‹ะทั‹ะฒะฐั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ะดะปั ะพะดะฝะพะณะพ ะธ ั‚ะพะณะพ ะถะต ะทะฐะฟั€ะพัะฐ. +ะŸั€ะธ ัั‚ะพะผ ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะต ะทะฝะฐั‡ะตะฝะธะต ะฑัƒะดะตั‚ ัะพั…ั€ะฐะฝะตะฝะพ ะฒ ยซะบััˆยป ะธ ะฑัƒะดะตั‚ ะฟะตั€ะตะดะฐะฝะพ ะฒัะตะผ "ะทะฐะฒะธัะธะผั‹ะผ" ั„ัƒะฝะบั†ะธัะผ, ะบะพั‚ะพั€ั‹ะต ะฝัƒะถะดะฐัŽั‚ัั ะฒ ะฝะตะผ ะฒะฝัƒั‚ั€ะธ ัั‚ะพะณะพ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะทะฐะฟั€ะพัะฐ, ะฒะผะตัั‚ะพ ั‚ะพะณะพ, ั‡ั‚ะพะฑั‹ ะฒั‹ะทั‹ะฒะฐั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท ะดะปั ะพะดะฝะพะณะพ ะธ ั‚ะพะณะพ ะถะต ะทะฐะฟั€ะพัะฐ. ะ’ ั€ะฐััˆะธั€ะตะฝะฝะพะผ ัั†ะตะฝะฐั€ะธะธ, ะบะพะณะดะฐ ะฒั‹ ะทะฝะฐะตั‚ะต, ั‡ั‚ะพ ะฒะฐะผ ะฝัƒะถะฝะพ, ั‡ั‚ะพะฑั‹ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฒั‹ะทั‹ะฒะฐะปะฐััŒ ะฝะฐ ะบะฐะถะดะพะผ ัˆะฐะณะต (ะฒะพะทะผะพะถะฝะพ, ะฝะตัะบะพะปัŒะบะพ ั€ะฐะท) ะฒ ะพะดะฝะพะผ ะธ ั‚ะพะผ ะถะต ะทะฐะฟั€ะพัะต, ะฒะผะตัั‚ะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั "ะบััˆะธั€ะพะฒะฐะฝะฝะพะณะพ" ะทะฝะฐั‡ะตะฝะธั, ะฒั‹ ะผะพะถะตั‚ะต ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `use_cache=False` ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ `Depends`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ ะฑะตะท Annotated +//// tab | Python 3.10+ ะฑะตะท Annotated /// tip | ะŸะพะดัะบะฐะทะบะฐ diff --git a/docs/ru/docs/tutorial/encoder.md b/docs/ru/docs/tutorial/encoder.md index 16981f79de..28e2a49c0a 100644 --- a/docs/ru/docs/tutorial/encoder.md +++ b/docs/ru/docs/tutorial/encoder.md @@ -10,9 +10,9 @@ ะŸั€ะตะดัั‚ะฐะฒะธะผ, ั‡ั‚ะพ ัƒ ะฒะฐั ะตัั‚ัŒ ะฑะฐะทะฐ ะดะฐะฝะฝั‹ั… `fake_db`, ะบะพั‚ะพั€ะฐั ะฟั€ะธะฝะธะผะฐะตั‚ ั‚ะพะปัŒะบะพ JSON-ัะพะฒะผะตัั‚ะธะผั‹ะต ะดะฐะฝะฝั‹ะต. -ะะฐะฟั€ะธะผะตั€, ะพะฝ ะฝะต ะฟั€ะธะฝะธะผะฐะตั‚ ะพะฑัŠะตะบั‚ั‹ `datetime`, ั‚ะฐะบ ะบะฐะบ ะพะฝะธ ะฝะต ัะพะฒะผะตัั‚ะธะผั‹ ั JSON. +ะะฐะฟั€ะธะผะตั€, ะพะฝะฐ ะฝะต ะฟั€ะธะฝะธะผะฐะตั‚ ะพะฑัŠะตะบั‚ั‹ `datetime`, ั‚ะฐะบ ะบะฐะบ ะพะฝะธ ะฝะต ัะพะฒะผะตัั‚ะธะผั‹ ั JSON. -ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะพะฑัŠะตะบั‚ `datetime` ัะปะตะดัƒะตั‚ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะฒ ัั‚ั€ะพะบัƒ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ัƒัŽ ั„ะพั€ะผะฐั‚ัƒ ISO. +ะ’ ั‚ะฐะบะพะผ ัะปัƒั‡ะฐะต ะพะฑัŠะตะบั‚ `datetime` ัะปะตะดัƒะตั‚ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐั‚ัŒ ะฒ ัั‚ั€ะพะบัƒ, ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ัƒัŽ ั„ะพั€ะผะฐั‚ัƒ ISO. ะขะพั‡ะฝะพ ั‚ะฐะบ ะถะต ัั‚ะฐ ะฑะฐะทะฐ ะดะฐะฝะฝั‹ั… ะฝะต ะผะพะถะตั‚ ะฟั€ะธะฝัั‚ัŒ Pydantic-ะผะพะดะตะปัŒ (ะพะฑัŠะตะบั‚ ั ะฐั‚ั€ะธะฑัƒั‚ะฐะผะธ), ะฐ ั‚ะพะปัŒะบะพ `dict`. diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md index 03156f2b4e..f9b63ca70e 100644 --- a/docs/ru/docs/tutorial/extra-models.md +++ b/docs/ru/docs/tutorial/extra-models.md @@ -190,9 +190,9 @@ some_variable: PlaneItem | CarItem ะขะฐะบะธะผ ะถะต ะพะฑั€ะฐะทะพะผ ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะปัั‚ัŒ HTTP-ะพั‚ะฒะตั‚ั‹, ะฒะพะทะฒั€ะฐั‰ะฐัŽั‰ะธะต ัะฟะธัะบะธ ะพะฑัŠะตะบั‚ะพะฒ. -ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะน `typing.List` ะฒ Python (ะธะปะธ ะฟั€ะพัั‚ะพ `list` ะฒ Python 3.9 ะธ ะฒั‹ัˆะต): +ะ”ะปั ัั‚ะพะณะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะน `list` ะฒ Python: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## ะžั‚ะฒะตั‚ ั ะฟั€ะพะธะทะฒะพะปัŒะฝั‹ะผ `dict` { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ some_variable: PlaneItem | CarItem ะญั‚ะพ ะฟะพะปะตะทะฝะพ, ะตัะปะธ ะฒั‹ ะทะฐั€ะฐะฝะตะต ะฝะต ะทะฝะฐะตั‚ะต ะบะพั€ั€ะตะบั‚ะฝั‹ั… ะฝะฐะทะฒะฐะฝะธะน ะฟะพะปะตะน/ะฐั‚ั€ะธะฑัƒั‚ะพะฒ (ะบะพั‚ะพั€ั‹ะต ะฑัƒะดัƒั‚ ะฝัƒะถะฝั‹ ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ Pydantic-ะผะพะดะตะปะธ). -ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `typing.Dict` (ะธะปะธ ะฟั€ะพัั‚ะพ `dict` ะฒ Python 3.9 ะธ ะฒั‹ัˆะต): +ะ’ ัั‚ะพะผ ัะปัƒั‡ะฐะต ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `dict`: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## ะ ะตะทัŽะผะต { #recap } diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md index 798c03d517..cee264ff46 100644 --- a/docs/ru/docs/tutorial/first-steps.md +++ b/docs/ru/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ ะกะฐะผั‹ะน ะฟั€ะพัั‚ะพะน ั„ะฐะนะป FastAPI ะผะพะถะตั‚ ะฒั‹ะณะปัะดะตั‚ัŒ ั‚ะฐะบ: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} ะกะบะพะฟะธั€ัƒะนั‚ะต ัั‚ะพ ะฒ ั„ะฐะนะป `main.py`. @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### ะจะฐะณ 1: ะธะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` โ€” ัั‚ะพ ะบะปะฐัั ะฝะฐ Python, ะบะพั‚ะพั€ั‹ะน ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฒััŽ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ ะดะปั ะฒะฐัˆะตะณะพ API. @@ -197,7 +197,7 @@ Deploying to FastAPI Cloud... ### ะจะฐะณ 2: ัะพะทะดะฐะนั‚ะต ัะบะทะตะผะฟะปัั€ `FastAPI` { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} ะ—ะดะตััŒ ะฟะตั€ะตะผะตะฝะฝะฐั `app` ะฑัƒะดะตั‚ ัะบะทะตะผะฟะปัั€ะพะผ ะบะปะฐััะฐ `FastAPI`. @@ -266,12 +266,12 @@ https://example.com/items/foo #### ะžะฟั€ะตะดะตะปะธั‚ะต *ะดะตะบะพั€ะฐั‚ะพั€ ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ (path operation decorator)* { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} `@app.get("/")` ัะพะพะฑั‰ะฐะตั‚ **FastAPI**, ั‡ั‚ะพ ั„ัƒะฝะบั†ะธั ะฟั€ัะผะพ ะฟะพะด ะฝะธะผ ะพั‚ะฒะตั‡ะฐะตั‚ ะทะฐ ะพะฑั€ะฐะฑะพั‚ะบัƒ ะทะฐะฟั€ะพัะพะฒ, ะฟะพัั‚ัƒะฟะฐัŽั‰ะธั…: * ะฟะพ ะฟัƒั‚ะธ `/` -* ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ get ะพะฟะตั€ะฐั†ะธะธ +* ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ get ะพะฟะตั€ะฐั†ะธะธ /// info | ะ˜ะฝั„ะพั€ะผะฐั†ะธั ะพ `@decorator` @@ -320,7 +320,7 @@ https://example.com/items/foo * **ะพะฟะตั€ะฐั†ะธั**: `get`. * **ั„ัƒะฝะบั†ะธั**: ั„ัƒะฝะบั†ะธั ะฝะธะถะต ยซะดะตะบะพั€ะฐั‚ะพั€ะฐยป (ะฝะธะถะต `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} ะญั‚ะพ ั„ัƒะฝะบั†ะธั ะฝะฐ Python. @@ -332,7 +332,7 @@ https://example.com/items/foo ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะตั‘ ะบะฐะบ ะพะฑั‹ั‡ะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ ะฒะผะตัั‚ะพ `async def`: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -342,7 +342,7 @@ https://example.com/items/foo ### ะจะฐะณ 5: ะฒะตั€ะฝะธั‚ะต ัะพะดะตั€ะถะธะผะพะต { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} ะ’ั‹ ะผะพะถะตั‚ะต ะฒะตั€ะฝัƒั‚ัŒ `dict`, `list`, ะพั‚ะดะตะปัŒะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั `str`, `int` ะธ ั‚.ะด. diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md index 2e00d70759..fbd82cf28a 100644 --- a/docs/ru/docs/tutorial/handling-errors.md +++ b/docs/ru/docs/tutorial/handling-errors.md @@ -11,7 +11,7 @@ * ะญะปะตะผะตะฝั‚, ะบ ะบะพั‚ะพั€ะพะผัƒ ะบะปะธะตะฝั‚ ะฟั‹ั‚ะฐะปัั ะฟะพะปัƒั‡ะธั‚ัŒ ะดะพัั‚ัƒะฟ, ะฝะต ััƒั‰ะตัั‚ะฒัƒะตั‚. * ะธ ั‚.ะด. -ะ’ ั‚ะฐะบะธั… ัะปัƒั‡ะฐัั… ะพะฑั‹ั‡ะฝะพ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ัั **HTTP-ะบะพะด ัั‚ะฐั‚ัƒัะฐ ะพั‚ะฒะตั‚ะฐ** ะฒ ะดะธะฐะฟะฐะทะพะฝะต **400** (ะพั‚ 400 ะดะพ 499). +ะ’ ั‚ะฐะบะธั… ัะปัƒั‡ะฐัั… ะพะฑั‹ั‡ะฝะพ ะฒะพะทะฒั€ะฐั‰ะฐัŽั‚ **HTTP ัั‚ะฐั‚ัƒั-ะบะพะด** ะฒ ะดะธะฐะฟะฐะทะพะฝะต **400** (ะพั‚ 400 ะดะพ 499). ะžะฝะธ ะฟะพั…ะพะถะธ ะฝะฐ ะดะฒัƒั…ัะพั‚ั‹ะต HTTP ัั‚ะฐั‚ัƒั-ะบะพะดั‹ (ะพั‚ 200 ะดะพ 299), ะบะพั‚ะพั€ั‹ะต ะพะทะฝะฐั‡ะฐัŽั‚, ั‡ั‚ะพ ะทะฐะฟั€ะพั ะพะฑั€ะฐะฑะพั‚ะฐะฝ ัƒัะฟะตัˆะฝะพ. @@ -25,7 +25,7 @@ ### ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### ะ’ั‹ะทะพะฒะธั‚ะต `HTTPException` ะฒ ัะฒะพะตะผ ะบะพะดะต { #raise-an-httpexception-in-your-code } @@ -39,7 +39,7 @@ ะ’ ะดะฐะฝะฝะพะผ ะฟั€ะธะผะตั€ะต, ะบะพะณะดะฐ ะบะปะธะตะฝั‚ ะทะฐะฟั€ะฐัˆะธะฒะฐะตั‚ ัะปะตะผะตะฝั‚ ะฟะพ ะฝะตััƒั‰ะตัั‚ะฒัƒัŽั‰ะตะผัƒ ID, ะฒะพะทะฝะธะบะฐะตั‚ ะธัะบะปัŽั‡ะตะฝะธะต ัะพ ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ `404`: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### ะ’ะพะทะฒั€ะฐั‰ะฐะตะผั‹ะน ะพั‚ะฒะตั‚ { #the-resulting-response } @@ -71,13 +71,13 @@ ## ะ”ะพะฑะฐะฒะปะตะฝะธะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… ะทะฐะณะพะปะพะฒะบะพะฒ { #add-custom-headers } -ะ’ ะฝะตะบะพั‚ะพั€ั‹ั… ัะธั‚ัƒะฐั†ะธัั… ะฟะพะปะตะทะฝะพ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะพะฑะฐะฒะปัั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะทะฐะณะพะปะพะฒะบะธ ะบ ะพัˆะธะฑะบะต HTTP. ะะฐะฟั€ะธะผะตั€, ะดะปั ะฝะตะบะพั‚ะพั€ั‹ั… ั‚ะธะฟะพะฒ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. +ะ’ ะฝะตะบะพั‚ะพั€ั‹ั… ัะธั‚ัƒะฐั†ะธัั… ะฟะพะปะตะทะฝะพ ะธะผะตั‚ัŒ ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะดะพะฑะฐะฒะปัั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต HTTP-ะทะฐะณะพะปะพะฒะบะธ ะบ ะพัˆะธะฑะบะต HTTP. ะะฐะฟั€ะธะผะตั€, ะดะปั ะฝะตะบะพั‚ะพั€ั‹ั… ั‚ะธะฟะพะฒ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. ะกะบะพั€ะตะต ะฒัะตะณะพ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ะตะฑัƒะตั‚ัั ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะตะณะพ ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ะบะพะดะต. ะะพ ะฒ ัะปัƒั‡ะฐะต, ะตัะปะธ ัั‚ะพ ะฝะตะพะฑั…ะพะดะธะผะพ ะดะปั ะฟั€ะพะดะฒะธะฝัƒั‚ะพะณะพ ัั†ะตะฝะฐั€ะธั, ะผะพะถะฝะพ ะดะพะฑะฐะฒะธั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะทะฐะณะพะปะพะฒะบะธ: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## ะฃัั‚ะฐะฝะพะฒะบะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธั… ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะพะฒ ะธัะบะปัŽั‡ะตะฝะธะน { #install-custom-exception-handlers } @@ -89,7 +89,7 @@ ะœะพะถะฝะพ ะดะพะฑะฐะฒะธั‚ัŒ ัะพะฑัั‚ะฒะตะฝะฝั‹ะน ะพะฑั€ะฐะฑะพั‚ั‡ะธะบ ะธัะบะปัŽั‡ะตะฝะธะน ั ะฟะพะผะพั‰ัŒัŽ `@app.exception_handler()`: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} ะ—ะดะตััŒ, ะตัะปะธ ะทะฐะฟั€ะพัะธั‚ัŒ `/unicorns/yolo`, ั‚ะพ *ะพะฟะตั€ะฐั†ะธั ะฟัƒั‚ะธ* ะฒั‹ะทะพะฒะตั‚ `UnicornException`. @@ -127,7 +127,7 @@ ะžะฑั€ะฐะฑะพั‚ั‡ะธะบ ะธัะบะปัŽั‡ะตะฝะธั ะฟะพะปัƒั‡ะธั‚ ะพะฑัŠะตะบั‚ `Request` ะธ ะธัะบะปัŽั‡ะตะฝะธะต. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} ะขะตะฟะตั€ัŒ, ะตัะปะธ ะฟะตั€ะตะนั‚ะธ ะบ `/items/foo`, ั‚ะพ ะฒะผะตัั‚ะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะน JSON-ะพัˆะธะฑะบะธ ั: @@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ะะฐะฟั€ะธะผะตั€, ะดะปั ัั‚ะธั… ะพัˆะธะฑะพะบ ะผะพะถะฝะพ ะฒะตั€ะฝัƒั‚ัŒ ะพะฑั‹ั‡ะฝั‹ะน ั‚ะตะบัั‚ะพะฒั‹ะน ะพั‚ะฒะตั‚ ะฒะผะตัั‚ะพ JSON: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ @@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะตะณะพ ะฟั€ะธ ั€ะฐะทั€ะฐะฑะพั‚ะบะต ะฟั€ะธะปะพะถะตะฝะธั ะดะปั ั€ะตะณะธัั‚ั€ะฐั†ะธะธ ั‚ะตะปะฐ ะธ ะตะณะพ ะพั‚ะปะฐะดะบะธ, ะฒะพะทะฒั€ะฐั‚ะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŽ ะธ ั‚.ะด. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} ะขะตะฟะตั€ัŒ ะฟะพะฟั€ะพะฑัƒะนั‚ะต ะพั‚ะฟั€ะฐะฒะธั‚ัŒ ะฝะตะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝั‹ะน ัะปะตะผะตะฝั‚, ะฝะฐะฟั€ะธะผะตั€: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธัะบะปัŽั‡ะตะฝะธะต ะฒะผะตัั‚ะต ั ั‚ะตะผะธ ะถะต ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐะผะธ ะธัะบะปัŽั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะธะท **FastAPI**, ะฒั‹ ะผะพะถะตั‚ะต ะธะผะฟะพั€ั‚ะธั€ะพะฒะฐั‚ัŒ ะธ ะฟะพะฒั‚ะพั€ะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะธัะบะปัŽั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะธะท `fastapi.exception_handlers`: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะฒั‹ ะฟั€ะพัั‚ะพ `ะฒั‹ะฒะพะดะธั‚ะต ะฒ ั‚ะตั€ะผะธะฝะฐะป` ะพัˆะธะฑะบัƒ ั ะพั‡ะตะฝัŒ ะฒั‹ั€ะฐะทะธั‚ะตะปัŒะฝั‹ะผ ัะพะพะฑั‰ะตะฝะธะตะผ, ะฝะพ ะธะดะตั ะฒะฐะผ ะฟะพะฝัั‚ะฝะฐ. ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธัะบะปัŽั‡ะตะฝะธะต, ะฐ ะทะฐั‚ะตะผ ะฟั€ะพัั‚ะพ ะฟะพะฒั‚ะพั€ะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะธ ะธัะบะปัŽั‡ะตะฝะธะน. diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md index e4fe5fb544..221655aa5d 100644 --- a/docs/ru/docs/tutorial/metadata.md +++ b/docs/ru/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ัŒ ะธั… ัะปะตะดัƒัŽั‰ะธะผ ะพะฑั€ะฐะทะพะผ: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -36,7 +36,7 @@ ะš ะฟั€ะธะผะตั€ัƒ: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## ะœะตั‚ะฐะดะฐะฝะฝั‹ะต ะดะปั ั‚ะตะณะพะฒ { #metadata-for-tags } @@ -58,7 +58,7 @@ ะกะพะทะดะฐะนั‚ะต ะผะตั‚ะฐะดะฐะฝะฝั‹ะต ะดะปั ะฒะฐัˆะธั… ั‚ะตะณะพะฒ ะธ ะฟะตั€ะตะดะฐะนั‚ะต ะธั… ะฒ ะฟะฐั€ะฐะผะตั‚ั€ะต `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Markdown ะฒะฝัƒั‚ั€ะธ ะพะฟะธัะฐะฝะธั, ะบ ะฟั€ะธะผะตั€ัƒ "login" ะฑัƒะดะตั‚ ะพั‚ะพะฑั€ะฐะถะตะฝ ะถะธั€ะฝั‹ะผ ัˆั€ะธั„ั‚ะพะผ (**login**) ะธ "fancy" ะฑัƒะดะตั‚ ะพั‚ะพะฑั€ะฐะถะฐั‚ัŒัั ะบัƒั€ัะธะฒะพะผ (_fancy_). @@ -72,7 +72,7 @@ ะ˜ัะฟะพะปัŒะทัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `tags` ั ะฒะฐัˆะธะผะธ *ะพะฟะตั€ะฐั†ะธัะผะธ ะฟัƒั‚ะธ* (ะธ `APIRouter`ะฐะผะธ), ั‡ั‚ะพะฑั‹ ะฟั€ะธัะฒะพะธั‚ัŒ ะธะผ ั€ะฐะทะปะธั‡ะฝั‹ะต ั‚ะตะณะธ: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั @@ -100,7 +100,7 @@ ะš ะฟั€ะธะผะตั€ัƒ, ั‡ั‚ะพะฑั‹ ะทะฐะดะฐั‚ัŒ ะตั‘ ะพั‚ะพะฑั€ะฐะถะตะฝะธะต ะฟะพ ะฐะดั€ะตััƒ `/api/v1/openapi.json`: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ะพั‚ะบะปัŽั‡ะธั‚ัŒ ัั…ะตะผัƒ OpenAPI ะฟะพะปะฝะพัั‚ัŒัŽ, ะฒั‹ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ัŒ `openapi_url=None`, ัั‚ะพ ั‚ะฐะบะถะต ะพั‚ะบะปัŽั‡ะธั‚ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะธะฝั‚ะตั€ั„ะตะนัั‹ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะบะพั‚ะพั€ั‹ะต ะตั‘ ะธัะฟะพะปัŒะทัƒัŽั‚. @@ -117,4 +117,4 @@ ะš ะฟั€ะธะผะตั€ัƒ, ั‡ั‚ะพะฑั‹ ะทะฐะดะฐั‚ัŒ ะพั‚ะพะฑั€ะฐะถะตะฝะธะต Swagger UI ะฟะพ ะฐะดั€ะตััƒ `/documentation` ะธ ะพั‚ะบะปัŽั‡ะธั‚ัŒ ReDoc: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/ru/docs/tutorial/middleware.md b/docs/ru/docs/tutorial/middleware.md index a83d3c0111..734545cd8b 100644 --- a/docs/ru/docs/tutorial/middleware.md +++ b/docs/ru/docs/tutorial/middleware.md @@ -1,10 +1,8 @@ # Middleware (ะŸั€ะพะผะตะถัƒั‚ะพั‡ะฝั‹ะน ัะปะพะน) { #middleware } -ะ’ั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะฟั€ะพะผะตะถัƒั‚ะพั‡ะฝั‹ะน ัะปะพะน (middleware) ะฒ **FastAPI** ะฟั€ะธะปะพะถะตะฝะธะต. - -"Middleware" ัั‚ะพ ั„ัƒะฝะบั†ะธั, ะบะพั‚ะพั€ะฐั ะฒั‹ะฟะพะปะฝัะตั‚ัั ั ะบะฐะถะดั‹ะผ ะทะฐะฟั€ะพัะพะผ ะดะพ ะตะณะพ ะพะฑั€ะฐะฑะพั‚ะบะธ ะบะฐะบะพะน-ะปะธะฑะพ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะตะน ะฟัƒั‚ะธ*. -ะ ั‚ะฐะบะถะต ั ะบะฐะถะดั‹ะผ ะพั‚ะฒะตั‚ะพะผ ะฟะตั€ะตะด ะตะณะพ ะฒะพะทะฒั€ะฐั‰ะตะฝะธะตะผ. +ะ’ั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ middleware (ะฟั€ะพะผะตะถัƒั‚ะพั‡ะฝั‹ะน ัะปะพะน) ะฒ **FastAPI** ะฟั€ะธะปะพะถะตะฝะธะต. +"Middleware" - ัั‚ะพ ั„ัƒะฝะบั†ะธั, ะบะพั‚ะพั€ะฐั ะฒั‹ะฟะพะปะฝัะตั‚ัั ั ะบะฐะถะดั‹ะผ **ะทะฐะฟั€ะพัะพะผ** ะดะพ ะตะณะพ ะพะฑั€ะฐะฑะพั‚ะบะธ ะบะฐะบะพะน-ะปะธะฑะพ ะบะพะฝะบั€ะตั‚ะฝะพะน *ะพะฟะตั€ะฐั†ะธะตะน ะฟัƒั‚ะธ*. ะ ั‚ะฐะบะถะต ั ะบะฐะถะดั‹ะผ **ะพั‚ะฒะตั‚ะพะผ** ะฟะตั€ะตะด ะตะณะพ ะฒะพะทะฒั€ะฐั‰ะตะฝะธะตะผ. * ะžะฝะฐ ะฟั€ะธะฝะธะผะฐะตั‚ ะบะฐะถะดั‹ะน ะฟะพัั‚ัƒะฟะฐัŽั‰ะธะน **ะทะฐะฟั€ะพั**. * ะœะพะถะตั‚ ั‡ั‚ะพ-ั‚ะพ ัะดะตะปะฐั‚ัŒ ั ัั‚ะธะผ **ะทะฐะฟั€ะพัะพะผ** ะธะปะธ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ะปัŽะฑะพะน ะฝัƒะถะฝั‹ะน ะบะพะด. @@ -23,23 +21,23 @@ ## ะกะพะทะดะฐะฝะธะต middleware { #create-a-middleware } -ะ”ะปั ัะพะทะดะฐะฝะธั middleware ะธัะฟะพะปัŒะทัƒะนั‚ะต ะดะตะบะพั€ะฐั‚ะพั€ `@app.middleware("http")`. +ะ”ะปั ัะพะทะดะฐะฝะธั middleware ะธัะฟะพะปัŒะทัƒะนั‚ะต ะดะตะบะพั€ะฐั‚ะพั€ `@app.middleware("http")` ะฟะพะฒะตั€ั… ั„ัƒะฝะบั†ะธะธ. ะคัƒะฝะบั†ะธั middleware ะฟะพะปัƒั‡ะฐะตั‚: -* `request` (ะพะฑัŠะตะบั‚ ะทะฐะฟั€ะพัะฐ). +* `request`. * ะคัƒะฝะบั†ะธัŽ `call_next`, ะบะพั‚ะพั€ะฐั ะฟะพะปัƒั‡ะฐะตั‚ `request` ะฒ ะบะฐั‡ะตัั‚ะฒะต ะฟะฐั€ะฐะผะตั‚ั€ะฐ. * ะญั‚ะฐ ั„ัƒะฝะบั†ะธั ะฟะตั€ะตะดะฐั‘ั‚ `request` ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะตะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. - * ะ—ะฐั‚ะตะผ ะพะฝะฐ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ ะพั‚ะฒะตั‚ `response`, ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน *ะพะฟะตั€ะฐั†ะธะตะน ะฟัƒั‚ะธ*. -* ะขะฐะบะถะต ะธะผะตะตั‚ัั ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะฒะธะดะพะธะทะผะตะฝะธั‚ัŒ `response`, ะฟะตั€ะตะด ั‚ะตะผ ะบะฐะบ ะตะณะพ ะฒะตั€ะฝัƒั‚ัŒ. + * ะ—ะฐั‚ะตะผ ะพะฝะฐ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ `response`, ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ะน ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะตะน *ะพะฟะตั€ะฐั†ะธะตะน ะฟัƒั‚ะธ*. +* ะขะฐะบะถะต ะธะผะตะตั‚ัั ะฒะพะทะผะพะถะฝะพัั‚ัŒ ะฒะธะดะพะธะทะผะตะฝะธั‚ัŒ `response` ะฟะตั€ะตะด ั‚ะตะผ ะบะฐะบ ะตะณะพ ะฒะตั€ะฝัƒั‚ัŒ. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} -/// tip | ะŸั€ะธะผะตั‡ะฐะฝะธะต +/// tip | ะกะพะฒะตั‚ -ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ะผะพะถะฝะพ ะดะพะฑะฐะฒะปัั‚ัŒ ัะฒะพะธ ัะพะฑัั‚ะฒะตะฝะฝั‹ะต ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะธ ะฟะพะผะพั‰ะธ ะฟั€ะตั„ะธะบัะฐ 'X-'. +ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ะผะพะถะฝะพ ะดะพะฑะฐะฒะปัั‚ัŒ ะฟั€ะพะฟั€ะธะตั‚ะฐั€ะฝั‹ะต HTTP-ะทะฐะณะพะปะพะฒะบะธ ั ะฟั€ะตั„ะธะบัะพะผ `X-`. -ะ•ัะปะธ ะถะต ะฒั‹ ั…ะพั‚ะธั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ัะพะฑัั‚ะฒะตะฝะฝั‹ะต ะทะฐะณะพะปะพะฒะบะธ, ะบะพั‚ะพั€ั‹ะต ะบะปะธะตะฝั‚ ัะผะพะถะตั‚ ัƒะฒะธะดะตั‚ัŒ ะฒ ะฑั€ะฐัƒะทะตั€ะต, ั‚ะพ ะฒะฐะผ ะฟะพั‚ั€ะตะฑัƒะตั‚ัั ะดะพะฑะฐะฒะธั‚ัŒ ะธั… ะฒ ะฝะฐัั‚ั€ะพะนะบะธ CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), ะธัะฟะพะปัŒะทัƒั ะฟะฐั€ะฐะผะตั‚ั€ `expose_headers`, ัะผ. ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Starlette's CORS docs. +ะะพ ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต, ั‡ั‚ะพะฑั‹ ะบะปะธะตะฝั‚ ะฒ ะฑั€ะฐัƒะทะตั€ะต ะผะพะณ ะฒะธะดะตั‚ัŒ ะฒะฐัˆะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒัะบะธะต ะทะฐะณะพะปะพะฒะบะธ, ะฝะตะพะฑั…ะพะดะธะผะพ ะดะพะฑะฐะฒะธั‚ัŒ ะธั… ะฒ ะฝะฐัั‚ั€ะพะนะบะธ CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), ะธัะฟะพะปัŒะทัƒั ะฟะฐั€ะฐะผะตั‚ั€ `expose_headers`, ะพะฟะธัะฐะฝะฝั‹ะน ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฟะพ CORS Starlette. /// @@ -53,17 +51,17 @@ ### ะ”ะพ ะธ ะฟะพัะปะต `response` { #before-and-after-the-response } -ะ’ั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะบะพะด, ะธัะฟะพะปัŒะทัƒัŽั‰ะธะน `request` ะดะพ ะฟะตั€ะตะดะฐั‡ะธ ะตะณะพ ะบะฐะบะพะน-ะปะธะฑะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. +ะ’ั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ะบะพะด, ะธัะฟะพะปัŒะทัƒัŽั‰ะธะน `request`, ะดะพ ะฟะตั€ะตะดะฐั‡ะธ ะตะณะพ ะบะฐะบะพะน-ะปะธะฑะพ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ*. ะ ั‚ะฐะบะถะต ะฟะพัะปะต ั„ะพั€ะผะธั€ะพะฒะฐะฝะธั `response`, ะดะพ ั‚ะพะณะพ, ะบะฐะบ ะฒั‹ ะตะณะพ ะฒะตั€ะฝั‘ั‚ะต. ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ะดะพะฑะฐะฒะธั‚ัŒ ัะพะฑัั‚ะฒะตะฝะฝั‹ะน ะทะฐะณะพะปะพะฒะพะบ `X-Process-Time`, ัะพะดะตั€ะถะฐั‰ะธะน ะฒั€ะตะผั ะฒ ัะตะบัƒะฝะดะฐั…, ะฝะตะพะฑั…ะพะดะธะผะพะต ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ ะทะฐะฟั€ะพัะฐ ะธ ะณะตะฝะตั€ะฐั†ะธะธ ะพั‚ะฒะตั‚ะฐ: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} -/// tip | ะŸั€ะธะผะตั‡ะฐะฝะธะต +/// tip | ะกะพะฒะตั‚ -ะœั‹ ะธัะฟะพะปัŒะทัƒะตะผ `time.perf_counter()` ะฒะผะตัั‚ะพ `time.time()` ะดะปั ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะพะปัŒัˆะตะน ั‚ะพั‡ะฝะพัั‚ะธ ะฝะฐัˆะธั… ะฟั€ะธะผะตั€ะพะฒ. ๐Ÿค“ +ะœั‹ ะธัะฟะพะปัŒะทัƒะตะผ `time.perf_counter()` ะฒะผะตัั‚ะพ `time.time()` ะดะปั ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะพะปัŒัˆะตะน ั‚ะพั‡ะฝะพัั‚ะธ ะฒ ั‚ะฐะบะธั… ัะปัƒั‡ะฐัั…. ๐Ÿค“ /// @@ -94,4 +92,4 @@ app.add_middleware(MiddlewareB) ะž ะดั€ัƒะณะธั… middleware ะฒั‹ ะผะพะถะตั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะฒ ั€ะฐะทะดะตะปะต [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. -ะ’ ัะปะตะดัƒัŽั‰ะตะผ ั€ะฐะทะดะตะปะต ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ, ะบะฐะบ ะฝะฐัั‚ั€ะพะธั‚ัŒ CORS ั ะฟะพะผะพั‰ัŒัŽ middleware. +ะ’ ัะปะตะดัƒัŽั‰ะตะผ ั€ะฐะทะดะตะปะต ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ, ะบะฐะบ ะฝะฐัั‚ั€ะพะธั‚ัŒ CORS ั ะฟะพะผะพั‰ัŒัŽ middleware. diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md index 112a1efca5..31531c67f1 100644 --- a/docs/ru/docs/tutorial/path-operation-configuration.md +++ b/docs/ru/docs/tutorial/path-operation-configuration.md @@ -4,7 +4,7 @@ /// warning | ะ’ะฝะธะผะฐะฝะธะต -ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ัั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟะตั€ะตะดะฐัŽั‚ัั ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ *ะดะตะบะพั€ะฐั‚ะพั€ัƒ ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*, ะฐ ะฝะต ะฒะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบัƒ ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*. +ะŸะพะผะฝะธั‚ะต, ั‡ั‚ะพ ัั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟะตั€ะตะดะฐัŽั‚ัั ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ *ะดะตะบะพั€ะฐั‚ะพั€ัƒ ะพะฟะตั€ะฐั†ะธะน ะฟัƒั‚ะธ*, ะฐ ะฝะต ะฒะฐัˆะตะน *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบัƒ ะฟัƒั‚ะธ*. /// @@ -46,7 +46,7 @@ **FastAPI** ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ัั‚ะพ ั‚ะฐะบ ะถะต, ะบะฐะบ ะธ ะฒ ัะปัƒั‡ะฐะต ั ะพะฑั‹ั‡ะฝั‹ะผะธ ัั‚ั€ะพะบะฐะผะธ: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## ะšั€ะฐั‚ะบะพะต ะธ ั€ะฐะทะฒั‘ั€ะฝัƒั‚ะพะต ัะพะดะตั€ะถะฐะฝะธะต { #summary-and-description } @@ -56,7 +56,7 @@ ## ะžะฟะธัะฐะฝะธะต ะธะท ัั‚ั€ะพะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ { #description-from-docstring } -ะขะฐะบ ะบะฐะบ ะพะฟะธัะฐะฝะธั ะพะฑั‹ั‡ะฝะพ ะดะปะธะฝะฝั‹ะต ะธ ัะพะดะตั€ะถะฐั‚ ะผะฝะพะณะพ ัั‚ั€ะพะบ, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะพะฟะธัะฐะฝะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฒ ั„ัƒะฝะบั†ะธะธ ัั‚ั€ะพะบะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะธ **FastAPI** ะฟั€ะพั‡ะธั‚ะฐะตั‚ ะตั‘ ะพั‚ััŽะดะฐ. +ะขะฐะบ ะบะฐะบ ะพะฟะธัะฐะฝะธั ะพะฑั‹ั‡ะฝะพ ะดะปะธะฝะฝั‹ะต ะธ ัะพะดะตั€ะถะฐั‚ ะผะฝะพะณะพ ัั‚ั€ะพะบ, ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ะพะฟะธัะฐะฝะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฒ ัั‚ั€ะพะบะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ั„ัƒะฝะบั†ะธะธ, ะธ **FastAPI** ะฟั€ะพั‡ะธั‚ะฐะตั‚ ะตั‘ ะพั‚ั‚ัƒะดะฐ. ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ Markdown ะฒ ัั‚ั€ะพะบะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะธ ะพะฝ ะฑัƒะดะตั‚ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ะพะฒะฐะฝ ะธ ะพั‚ะพะฑั€ะฐะถั‘ะฝ ะบะพั€ั€ะตะบั‚ะฝะพ (ั ัƒั‡ะตั‚ะพะผ ะพั‚ัั‚ัƒะฟะฐ ะฒ ัั‚ั€ะพะบะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ). @@ -90,9 +90,9 @@ OpenAPI ัƒะบะฐะทั‹ะฒะฐะตั‚, ั‡ั‚ะพ ะบะฐะถะดะพะน *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฝะต ## ะžะฑะพะทะฝะฐั‡ะตะฝะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะตะน { #deprecate-a-path-operation } -ะ•ัะปะธ ะฒะฐะผ ะฝะตะพะฑั…ะพะดะธะผะพ ะฟะพะผะตั‚ะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆัƒัŽ, ะฟั€ะธ ัั‚ะพะผ ะฝะต ัƒะดะฐะปัั ะตั‘, ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `deprecated`: +ะ•ัะปะธ ะฒะฐะผ ะฝะตะพะฑั…ะพะดะธะผะพ ะฟะพะผะตั‚ะธั‚ัŒ *ะพะฟะตั€ะฐั†ะธัŽ ะฟัƒั‚ะธ* ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆัƒัŽ, ะฟั€ะธ ัั‚ะพะผ ะฝะต ัƒะดะฐะปัั ะตั‘, ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `deprecated`: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} ะžะฝ ะฑัƒะดะตั‚ ั‡ะตั‚ะบะพ ะฟะพะผะตั‡ะตะฝ ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน ะฒ ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ: diff --git a/docs/ru/docs/tutorial/path-params-numeric-validations.md b/docs/ru/docs/tutorial/path-params-numeric-validations.md index f0fe788051..6c1148b60c 100644 --- a/docs/ru/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ru/docs/tutorial/path-params-numeric-validations.md @@ -44,7 +44,7 @@ Path-ะฟะฐั€ะฐะผะตั‚ั€ ะฒัะตะณะดะฐ ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ, ะฟ ะ˜ ะตัะปะธ ะฒะฐะผ ะฑะพะปัŒัˆะต ะฝะธั‡ะตะณะพ ะฝะต ะฝัƒะถะฝะพ ัƒะบะฐะทั‹ะฒะฐั‚ัŒ ะดะปั ัั‚ะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ, ั‚ะพ ะฝะตั‚ ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Query`. -ะะพ ะฒะฐะผ ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ะฝัƒะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Path` ะดะปั path-ะฟะฐั€ะฐะผะตั‚ั€ะฐ `item_id`. ะ˜ ะตัะปะธ ะฟะพ ะบะฐะบะพะน-ะปะธะฑะพ ะฟั€ะธั‡ะธะฝะต ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Annotated`, ั‚ะพ ะผะพะณัƒั‚ ะฒะพะทะฝะธะบะฝัƒั‚ัŒ ะฝะตะฑะพะปัŒัˆะธะต ัะปะพะถะฝะพัั‚ะธ. +ะะพ ะฒะฐะผ ะฟะพ-ะฟั€ะตะถะฝะตะผัƒ ะฝัƒะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Path` ะดะปั path-ะฟะฐั€ะฐะผะตั‚ั€ะฐ `item_id`. ะ˜ ะฟะพ ะบะฐะบะพะน-ะปะธะฑะพ ะฟั€ะธั‡ะธะฝะต ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Annotated`. ะ•ัะปะธ ะฒั‹ ะฟะพะผะตัั‚ะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฟะตั€ะตะด ะดั€ัƒะณะธะผ ะฟะฐั€ะฐะผะตั‚ั€ะพะผ, ัƒ ะบะพั‚ะพั€ะพะณะพ ะฝะตั‚ ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ, ั‚ะพ Python ัƒะบะฐะถะตั‚ ะฝะฐ ะพัˆะธะฑะบัƒ. @@ -54,11 +54,11 @@ Path-ะฟะฐั€ะฐะผะตั‚ั€ ะฒัะตะณะดะฐ ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ, ะฟ ะŸะพัั‚ะพะผัƒ ะฒั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ั„ัƒะฝะบั†ะธัŽ ั‚ะฐะบ: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} ะะพ ะธะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต `Annotated`, ะฒั‹ ะฝะต ัั‚ะพะปะบะฝั‘ั‚ะตััŒ ั ัั‚ะพะน ะฟั€ะพะฑะปะตะผะพะน, ั‚ะฐะบ ะบะฐะบ ะฒั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ะต ะทะฝะฐั‡ะตะฝะธั ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ ั„ัƒะฝะบั†ะธะธ ะดะปั `Query()` ะธะปะธ `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## ะ—ะฐะดะฐะนั‚ะต ะฝัƒะถะฝั‹ะน ะฒะฐะผ ะฟะพั€ัะดะพะบ ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ะฟะพะปะตะทะฝั‹ะต ะฟั€ะธั‘ะผั‹ { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ Path-ะฟะฐั€ะฐะผะตั‚ั€ ะฒัะตะณะดะฐ ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ, ะฟ Python ะฝะต ะฑัƒะดะตั‚ ะฝะธั‡ะตะณะพ ะดะตะปะฐั‚ัŒ ั `*`, ะฝะพ ะพะฝ ะฑัƒะดะตั‚ ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะฒัะต ัะปะตะดัƒัŽั‰ะธะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ัะฒะปััŽั‚ัั ะธะผะตะฝะพะฒะฐะฝะฝั‹ะผะธ ะฐั€ะณัƒะผะตะฝั‚ะฐะผะธ (ะฟะฐั€ะฐะผะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะธะต), ั‚ะฐะบะถะต ะธะทะฒะตัั‚ะฝั‹ะผะธ ะบะฐะบ kwargs, ะดะฐะถะต ะตัะปะธ ัƒ ะฝะธั… ะฝะตั‚ ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### ะ›ัƒั‡ัˆะต ั `Annotated` { #better-with-annotated } ะ˜ะผะตะนั‚ะต ะฒ ะฒะธะดัƒ, ั‡ั‚ะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต `Annotated`, ั‚ะพ, ะฟะพัะบะพะปัŒะบัƒ ะฒั‹ ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ะต ะทะฝะฐั‡ะตะฝะธะน ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ ั„ัƒะฝะบั†ะธะธ, ัƒ ะฒะฐั ะฝะต ะฒะพะทะฝะธะบะฝะตั‚ ะฟะพะดะพะฑะฝะพะน ะฟั€ะพะฑะปะตะผั‹ ะธ ะฒะฐะผ, ะฒะตั€ะพัั‚ะฝะพ, ะฝะต ะฟั€ะธะดั‘ั‚ัั ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## ะ’ะฐะปะธะดะฐั†ะธั ั‡ะธัะปะพะฒั‹ั… ะดะฐะฝะฝั‹ั…: ะฑะพะปัŒัˆะต ะธะปะธ ั€ะฐะฒะฝะพ { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Python ะฝะต ะฑัƒะดะตั‚ ะฝะธั‡ะตะณะพ ะดะตะปะฐั‚ัŒ ั `*`, ะฝะพ ะพะฝ ะฑัƒะดะตั‚ ะท ะ’ ัั‚ะพะผ ะฟั€ะธะผะตั€ะต ะฟั€ะธ ัƒะบะฐะทะฐะฝะธะธ `ge=1`, ะฟะฐั€ะฐะผะตั‚ั€ `item_id` ะดะพะปะถะตะฝ ะฑั‹ั‚ัŒ ั†ะตะปั‹ะผ ั‡ะธัะปะพะผ "`g`reater than or `e`qual" โ€” ะฑะพะปัŒัˆะต ะธะปะธ ั€ะฐะฒะฝะพ `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## ะ’ะฐะปะธะดะฐั†ะธั ั‡ะธัะปะพะฒั‹ั… ะดะฐะฝะฝั‹ั…: ะฑะพะปัŒัˆะต ะธ ะผะตะฝัŒัˆะต ะธะปะธ ั€ะฐะฒะฝะพ { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ Python ะฝะต ะฑัƒะดะตั‚ ะฝะธั‡ะตะณะพ ะดะตะปะฐั‚ัŒ ั `*`, ะฝะพ ะพะฝ ะฑัƒะดะตั‚ ะท * `gt`: ะฑะพะปัŒัˆะต (`g`reater `t`han) * `le`: ะผะตะฝัŒัˆะต ะธะปะธ ั€ะฐะฒะฝะพ (`l`ess than or `e`qual) -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## ะ’ะฐะปะธะดะฐั†ะธั ั‡ะธัะปะพะฒั‹ั… ะดะฐะฝะฝั‹ั…: ั‡ะธัะปะฐ ั ะฟะปะฐะฒะฐัŽั‰ะตะน ั‚ะพั‡ะบะพะน, ะฑะพะปัŒัˆะต ะธ ะผะตะฝัŒัˆะต { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Python ะฝะต ะฑัƒะดะตั‚ ะฝะธั‡ะตะณะพ ะดะตะปะฐั‚ัŒ ั `*`, ะฝะพ ะพะฝ ะฑัƒะดะตั‚ ะท ะขะพ ะถะต ัะฐะผะพะต ัะฟั€ะฐะฒะตะดะปะธะฒะพ ะธ ะดะปั lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ะ ะตะทัŽะผะต { #recap } diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md index 83a7ed3ffe..7295697487 100644 --- a/docs/ru/docs/tutorial/path-params.md +++ b/docs/ru/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ "ะฟะฐั€ะฐะผะตั‚ั€ั‹" ะธะปะธ "ะฟะตั€ะตะผะตะฝะฝั‹ะต" ะฟัƒั‚ะธ, ะธัะฟะพะปัŒะทัƒั ัะธะฝั‚ะฐะบัะธั ั„ะพั€ะผะฐั‚ะธั€ะพะฒะฐะฝะฝั‹ั… ัั‚ั€ะพะบ Python: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} ะ—ะฝะฐั‡ะตะฝะธะต ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะฟัƒั‚ะธ `item_id` ะฑัƒะดะตั‚ ะฟะตั€ะตะดะฐะฝะพ ะฒ ั„ัƒะฝะบั†ะธัŽ ะฒ ะบะฐั‡ะตัั‚ะฒะต ะฐั€ะณัƒะผะตะฝั‚ะฐ `item_id`. @@ -16,7 +16,7 @@ ะ’ั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ั‚ะธะฟ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะฟัƒั‚ะธ ะฒ ั„ัƒะฝะบั†ะธะธ, ะธัะฟะพะปัŒะทัƒั ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะพะฒ Python: -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} ะ—ะดะตััŒ, `item_id` ะพะฑัŠัะฒะปะตะฝ ั‚ะธะฟะพะผ `int`. @@ -26,7 +26,7 @@ /// -## ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั… { #data-conversion } +## ะŸั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธะต ะดะฐะฝะฝั‹ั… { #data-conversion } ะ•ัะปะธ ะทะฐะฟัƒัั‚ะธั‚ะต ัั‚ะพั‚ ะฟั€ะธะผะตั€ ะธ ะฟะตั€ะตะนะดั‘ั‚ะต ะฟะพ ะฐะดั€ะตััƒ: http://127.0.0.1:8000/items/3, ั‚ะพ ัƒะฒะธะดะธั‚ะต ะพั‚ะฒะตั‚: @@ -38,7 +38,7 @@ ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต ะฝะฐ ะทะฝะฐั‡ะตะฝะธะต `3`, ะบะพั‚ะพั€ะพะต ะฟะพะปัƒั‡ะธะปะฐ (ะธ ะฒะตั€ะฝัƒะปะฐ) ั„ัƒะฝะบั†ะธั. ะญั‚ะพ ั†ะตะปะพั‡ะธัะปะตะฝะฝั‹ะน Python `int`, ะฐ ะฝะต ัั‚ั€ะพะบะฐ `"3"`. -ะ˜ัะฟะพะปัŒะทัƒั ั‚ะฐะบะพะต ะพะฑัŠัะฒะปะตะฝะธะต ั‚ะธะฟะพะฒ, **FastAPI** ะฒั‹ะฟะพะปะฝัะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะน "ะฟะฐั€ัะธะฝะณ" ะทะฐะฟั€ะพัะพะฒ. +ะ˜ัะฟะพะปัŒะทัƒั ั‚ะฐะบะพะต ะพะฑัŠัะฒะปะตะฝะธะต ั‚ะธะฟะพะฒ, **FastAPI** ะฒั‹ะฟะพะปะฝัะตั‚ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธะน HTTP-ะทะฐะฟั€ะพั "ะฟะฐั€ัะธะฝะณ". /// @@ -118,13 +118,13 @@ ะŸะพัะบะพะปัŒะบัƒ *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ะฒั‹ะฟะพะปะฝััŽั‚ัั ะฒ ะฟะพั€ัะดะบะต ะธั… ะพะฑัŠัะฒะปะตะฝะธั, ะฝะตะพะฑั…ะพะดะธะผะพ, ั‡ั‚ะพะฑั‹ ะฟัƒั‚ัŒ ะดะปั `/users/me` ะฑั‹ะป ะพะฑัŠัะฒะปะตะฝ ั€ะฐะฝัŒัˆะต, ั‡ะตะผ ะฟัƒั‚ัŒ ะดะปั `/users/{user_id}`: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} ะ˜ะฝะฐั‡ะต ะฟัƒั‚ัŒ ะดะปั `/users/{user_id}` ั‚ะฐะบะถะต ะฑัƒะดะตั‚ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ `/users/me`, "ะฟะพะดั€ะฐะทัƒะผะตะฒะฐั", ั‡ั‚ะพ ะพะฝ ะฟะพะปัƒั‡ะฐะตั‚ ะฟะฐั€ะฐะผะตั‚ั€ `user_id` ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ `"me"`. ะะฝะฐะปะพะณะธั‡ะฝะพ, ะฒั‹ ะฝะต ะผะพะถะตั‚ะต ะฟะตั€ะตะพะฟั€ะตะดะตะปะธั‚ัŒ ะพะฟะตั€ะฐั†ะธัŽ ั ะฟัƒั‚ะตะผ: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} ะŸะตั€ะฒั‹ะน ะฑัƒะดะตั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒัั ะฒัะตะณะดะฐ, ั‚ะฐะบ ะบะฐะบ ะฟัƒั‚ัŒ ัะพะฒะฟะฐะดะฐะตั‚ ะฟะตั€ะฒั‹ะผ. @@ -140,11 +140,11 @@ ะ—ะฐั‚ะตะผ ัะพะทะดะฐะนั‚ะต ะฐั‚ั€ะธะฑัƒั‚ั‹ ะบะปะฐััะฐ ั ั„ะธะบัะธั€ะพะฒะฐะฝะฝั‹ะผะธ ะดะพะฟัƒัั‚ะธะผั‹ะผะธ ะทะฝะฐั‡ะตะฝะธัะผะธ: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ•ัะปะธ ะธะฝั‚ะตั€ะตัะฝะพ, ั‚ะพ "AlexNet", "ResNet" ะธ "LeNet" - ัั‚ะพ ะฝะฐะทะฒะฐะฝะธั ะผะพะดะตะปะตะน ะœะฐัˆะธะฝะฝะพะณะพ ะพะฑัƒั‡ะตะฝะธั. +ะ•ัะปะธ ะธะฝั‚ะตั€ะตัะฝะพ, ั‚ะพ "AlexNet", "ResNet" ะธ "LeNet" - ัั‚ะพ ะฝะฐะทะฒะฐะฝะธั ะผะพะดะตะปะตะน ะœะฐัˆะธะฝะฝะพะณะพ ะพะฑัƒั‡ะตะฝะธั. /// @@ -152,7 +152,7 @@ ะžะฟั€ะตะดะตะปะธั‚ะต *ะฟะฐั€ะฐะผะตั‚ั€ ะฟัƒั‚ะธ*, ะธัะฟะพะปัŒะทัƒั ะฒ ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะฐ ะบะปะฐัั ะฟะตั€ะตั‡ะธัะปะตะฝะธั (`ModelName`), ัะพะทะดะฐะฝะฝั‹ะน ั€ะฐะฝะตะต: -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### ะŸั€ะพะฒะตั€ัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ { #check-the-docs } @@ -168,13 +168,13 @@ ะ’ั‹ ะผะพะถะตั‚ะต ัั€ะฐะฒะฝะธั‚ัŒ ัั‚ะพ ะทะฝะฐั‡ะตะฝะธะต ั *ัะปะตะผะตะฝั‚ะพะผ ะฟะตั€ะตั‡ะธัะปะตะฝะธั* ะบะปะฐััะฐ `ModelName`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### ะŸะพะปัƒั‡ะตะฝะธะต *ะทะฝะฐั‡ะตะฝะธั ะฟะตั€ะตั‡ะธัะปะตะฝะธั* { #get-the-enumeration-value } ะœะพะถะฝะพ ะฟะพะปัƒั‡ะธั‚ัŒ ั„ะฐะบั‚ะธั‡ะตัะบะพะต ะทะฝะฐั‡ะตะฝะธะต (ะฒ ะดะฐะฝะฝะพะผ ัะปัƒั‡ะฐะต - `str`) ั ะฟะพะผะพั‰ัŒัŽ `model_name.value` ะธะปะธ ะฒ ะพะฑั‰ะตะผ ัะปัƒั‡ะฐะต `your_enum_member.value`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -188,8 +188,8 @@ ะžะฝะธ ะฑัƒะดัƒั‚ ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝั‹ ะฒ ัะพะพั‚ะฒะตั‚ัั‚ะฒัƒัŽั‰ะธะต ะทะฝะฐั‡ะตะฝะธั (ะฒ ะดะฐะฝะฝะพะผ ัะปัƒั‡ะฐะต - ัั‚ั€ะพะบะธ) ะฟะตั€ะตะด ะธั… ะฒะพะทะฒั€ะฐั‚ะพะผ ะบะปะธะตะฝั‚ัƒ: -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} -ะ’ั‹ ะพั‚ะฟั€ะฐะฒะธั‚ะต ะบะปะธะตะฝั‚ัƒ ั‚ะฐะบะพะน JSON-ะพั‚ะฒะตั‚: +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} +ะะฐ ัั‚ะพั€ะพะฝะต ะบะปะธะตะฝั‚ะฐ ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ั‚ะฐะบะพะน JSON-ะพั‚ะฒะตั‚: ```JSON { @@ -226,7 +226,7 @@ OpenAPI ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ัะฟะพัะพะฑะพะฒ ะพะฑัŠัะฒะปะตะฝะธั *ะฟ ะœะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ั‚ะฐะบ: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -241,7 +241,7 @@ OpenAPI ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ัะฟะพัะพะฑะพะฒ ะพะฑัŠัะฒะปะตะฝะธั *ะฟ ะ˜ัะฟะพะปัŒะทัƒั **FastAPI** ะฒะผะตัั‚ะต ัะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะผะธ ะพะฑัŠัะฒะปะตะฝะธัะผะธ ั‚ะธะฟะพะฒ Python (ะบะพั€ะพั‚ะบะธะผะธ ะธ ะธะฝั‚ัƒะธั‚ะธะฒะฝะพ ะฟะพะฝัั‚ะฝั‹ะผะธ), ะฒั‹ ะฟะพะปัƒั‡ะฐะตั‚ะต: * ะŸะพะดะดะตั€ะถะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ (ะฟั€ะพะฒะตั€ะบัƒ ะพัˆะธะฑะพะบ, ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ะธ ั‚.ะฟ.) -* "ะŸะฐั€ัะธะฝะณ" ะดะฐะฝะฝั‹ั… +* "ะŸะฐั€ัะธะฝะณ" ะดะฐะฝะฝั‹ั… * ะ’ะฐะปะธะดะฐั†ะธัŽ ะดะฐะฝะฝั‹ั… * ะะฝะฝะพั‚ะฐั†ะธะธ API ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบัƒัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ diff --git a/docs/ru/docs/tutorial/query-param-models.md b/docs/ru/docs/tutorial/query-param-models.md index 5ad7f1d99d..7f29740acc 100644 --- a/docs/ru/docs/tutorial/query-param-models.md +++ b/docs/ru/docs/tutorial/query-param-models.md @@ -6,7 +6,7 @@ /// note | ะ—ะฐะผะตั‚ะบะฐ -ะญั‚ะพั‚ ั„ัƒะฝะบั†ะธะพะฝะฐะป ะดะพัั‚ัƒะฟะตะฝ ั ะฒะตั€ัะธะธ `0.115.0`. ๐Ÿค“ +ะญั‚ะพ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ัั ะฝะฐั‡ะธะฝะฐั ั ะฒะตั€ัะธะธ FastAPI `0.115.0`. ๐Ÿค“ /// diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 2bc2fb22c5..43cbcad03c 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -47,40 +47,16 @@ FastAPI ะฟะพะนะผั‘ั‚, ั‡ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต `q` ะฝะต ะพะฑัะทะฐั‚ะตะปัŒะฝะพ, ะฃ ะฝะฐั ะฑั‹ะปะฐ ั‚ะฐะบะฐั ะฐะฝะฝะพั‚ะฐั†ะธั ั‚ะธะฟะฐ: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ะœั‹ ยซะพะฑะตั€ะฝั‘ะผยป ัั‚ะพ ะฒ `Annotated`, ะธ ะฟะพะปัƒั‡ะธั‚ัั: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - ะžะฑะต ะฒะตั€ัะธะธ ะพะทะฝะฐั‡ะฐัŽั‚ ะพะดะฝะพ ะธ ั‚ะพ ะถะต: `q` โ€” ะฟะฐั€ะฐะผะตั‚ั€, ะบะพั‚ะพั€ั‹ะน ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `str` ะธะปะธ `None`, ะธ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ั€ะฐะฒะตะฝ `None`. ะ ั‚ะตะฟะตั€ัŒ ะบ ัะฐะผะพะผัƒ ะธะฝั‚ะตั€ะตัะฝะพะผัƒ. ๐ŸŽ‰ @@ -109,7 +85,7 @@ q: Annotated[Union[str, None]] = None ## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฐ (ัƒัั‚ะฐั€ะตะฒัˆะตะต): `Query` ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ { #alternative-old-query-as-the-default-value } -ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะธั… ะฒะตั€ัะธัั… FastAPI (ะดะพ 0.95.0) ั‚ั€ะตะฑะพะฒะฐะปะพััŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Query` ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะฒะผะตัั‚ะพ ะฟะพะผะตั‰ะตะฝะธั ะตะณะพ ะฒ `Annotated`. ะกะบะพั€ะตะต ะฒัะตะณะพ ะฒั‹ ะตั‰ั‘ ะฒัั‚ั€ะตั‚ะธั‚ะต ั‚ะฐะบะพะน ะบะพะด, ะฟะพัั‚ะพะผัƒ ะฟะพััะฝัŽ. +ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะธั… ะฒะตั€ัะธัั… FastAPI (ะดะพ 0.95.0) ั‚ั€ะตะฑะพะฒะฐะปะพััŒ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `Query` ะบะฐะบ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะฒะผะตัั‚ะพ ะฟะพะผะตั‰ะตะฝะธั ะตะณะพ ะฒ `Annotated`. ะกะบะพั€ะตะต ะฒัะตะณะพ ะฒั‹ ะตั‰ั‘ ะฒัั‚ั€ะตั‚ะธั‚ะต ั‚ะฐะบะพะน ะบะพะด, ะฟะพัั‚ะพะผัƒ ะฟะพััะฝัŽ. /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -191,7 +167,7 @@ q: str = Query(default="rick") ## ะ ะตะณัƒะปัั€ะฝั‹ะต ะฒั‹ั€ะฐะถะตะฝะธั { #add-regular-expressions } -ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ั€ะตะณัƒะปัั€ะฝะพะต ะฒั‹ั€ะฐะถะตะฝะธะต `pattern`, ะบะพั‚ะพั€ะพะผัƒ ะดะพะปะถะตะฝ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€: +ะ’ั‹ ะผะพะถะตั‚ะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ั€ะตะณัƒะปัั€ะฝะพะต ะฒั‹ั€ะฐะถะตะฝะธะต `pattern`, ะบะพั‚ะพั€ะพะผัƒ ะดะพะปะถะตะฝ ัะพะพั‚ะฒะตั‚ัั‚ะฒะพะฒะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +187,7 @@ q: str = Query(default="rick") ะ”ะพะฟัƒัั‚ะธะผ, ะฒั‹ ั…ะพั‚ะธั‚ะต ะพะฑัŠัะฒะธั‚ัŒ, ั‡ั‚ะพ query-ะฟะฐั€ะฐะผะตั‚ั€ `q` ะดะพะปะถะตะฝ ะธะผะตั‚ัŒ `min_length` ั€ะฐะฒะฝั‹ะน `3` ะธ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None ะŸะพัั‚ะพะผัƒ, ะบะพะณะดะฐ ะฒะฐะผ ะฝัƒะถะฝะพ ะพะฑัŠัะฒะธั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะบะฐะบ ะพะฑัะทะฐั‚ะตะปัŒะฝะพะต ะฟั€ะธ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะธ `Query`, ะฟั€ะพัั‚ะพ ะฝะต ัƒะบะฐะทั‹ะฒะฐะนั‚ะต ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### ะžะฑัะทะฐั‚ะตะปัŒะฝั‹ะน, ะฝะพ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ `None` { #required-can-be-none } @@ -292,7 +268,7 @@ http://localhost:8000/items/?q=foo&q=bar ะœะพะถะฝะพ ั‚ะฐะบะถะต ะพะฟั€ะตะดะตะปะธั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะบะฐะบ `list`, ะตัะปะธ ะฝะธั‡ะตะณะพ ะฝะต ะฟะตั€ะตะดะฐะฝะพ: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ะ•ัะปะธ ะฒั‹ ะฟะตั€ะตะนะดั‘ั‚ะต ะฟะพ ะฐะดั€ะตััƒ: @@ -315,7 +291,7 @@ http://localhost:8000/items/ ะœะพะถะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `list` ะฝะฐะฟั€ัะผัƒัŽ ะฒะผะตัั‚ะพ `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -371,7 +347,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ะŸั€ะตะดะฟะพะปะพะถะธะผ, ัั‚ะพั‚ ะฟะฐั€ะฐะผะตั‚ั€ ะฒะฐะผ ะฑะพะปัŒัˆะต ะฝะต ะฝั€ะฐะฒะธั‚ัั. -ะ•ะณะพ ะฝัƒะถะฝะพ ะพัั‚ะฐะฒะธั‚ัŒ ะฝะฐ ะบะฐะบะพะตโ€‘ั‚ะพ ะฒั€ะตะผั, ั‚ะฐะบ ะบะฐะบ ะบะปะธะตะฝั‚ั‹ ะตะณะพ ะธัะฟะพะปัŒะทัƒัŽั‚, ะฝะพ ะฒั‹ ั…ะพั‚ะธั‚ะต, ั‡ั‚ะพะฑั‹ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะพะฝ ัะฒะฝะพ ะพั‚ะพะฑั€ะฐะถะฐะปัั ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน. +ะ•ะณะพ ะฝัƒะถะฝะพ ะพัั‚ะฐะฒะธั‚ัŒ ะฝะฐ ะบะฐะบะพะตโ€‘ั‚ะพ ะฒั€ะตะผั, ั‚ะฐะบ ะบะฐะบ ะบะปะธะตะฝั‚ั‹ ะตะณะพ ะธัะฟะพะปัŒะทัƒัŽั‚, ะฝะพ ะฒั‹ ั…ะพั‚ะธั‚ะต, ั‡ั‚ะพะฑั‹ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะพะฝ ัะฒะฝะพ ะพั‚ะพะฑั€ะฐะถะฐะปัั ะบะฐะบ ัƒัั‚ะฐั€ะตะฒัˆะธะน. ะขะพะณะดะฐ ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `deprecated=True` ะฒ `Query`: @@ -401,7 +377,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems /// -ะะฐะฟั€ะธะผะตั€, ัั‚ะฐ ะบะฐัั‚ะพะผะฝะฐั ะฟั€ะพะฒะตั€ะบะฐ ัƒะฑะตะถะดะฐะตั‚ัั, ั‡ั‚ะพ ID ัะปะตะผะตะฝั‚ะฐ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั `isbn-` ะดะปั ะฝะพะผะตั€ะฐ ะบะฝะธะณะธ ISBN ะธะปะธ ั `imdb-` ะดะปั ID URL ั„ะธะปัŒะผะฐ ะฝะฐ IMDB: +ะะฐะฟั€ะธะผะตั€, ัั‚ะฐ ะบะฐัั‚ะพะผะฝะฐั ะฟั€ะพะฒะตั€ะบะฐ ัƒะฑะตะถะดะฐะตั‚ัั, ั‡ั‚ะพ ID ัะปะตะผะตะฝั‚ะฐ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั `isbn-` ะดะปั ะฝะพะผะตั€ะฐ ะบะฝะธะณะธ ISBN ะธะปะธ ั `imdb-` ะดะปั ID URL ั„ะธะปัŒะผะฐ ะฝะฐ IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,7 +411,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems #### ะกะปัƒั‡ะฐะนะฝั‹ะน ัะปะตะผะตะฝั‚ { #a-random-item } -ะก ะฟะพะผะพั‰ัŒัŽ `data.items()` ะผั‹ ะฟะพะปัƒั‡ะฐะตะผ ะธั‚ะตั€ะธั€ัƒะตะผั‹ะน ะพะฑัŠะตะบั‚ ั ะบะพั€ั‚ะตะถะฐะผะธ, ัะพะดะตั€ะถะฐั‰ะธะผะธ ะบะปัŽั‡ ะธ ะทะฝะฐั‡ะตะฝะธะต ะดะปั ะบะฐะถะดะพะณะพ ัะปะตะผะตะฝั‚ะฐ ัะปะพะฒะฐั€ั. +ะก ะฟะพะผะพั‰ัŒัŽ `data.items()` ะผั‹ ะฟะพะปัƒั‡ะฐะตะผ ะธั‚ะตั€ะธั€ัƒะตะผั‹ะน ะพะฑัŠะตะบั‚ ั ะบะพั€ั‚ะตะถะฐะผะธ, ัะพะดะตั€ะถะฐั‰ะธะผะธ ะบะปัŽั‡ ะธ ะทะฝะฐั‡ะตะฝะธะต ะดะปั ะบะฐะถะดะพะณะพ ัะปะตะผะตะฝั‚ะฐ ัะปะพะฒะฐั€ั. ะœั‹ ะฟั€ะตะฒั€ะฐั‰ะฐะตะผ ัั‚ะพั‚ ะธั‚ะตั€ะธั€ัƒะตะผั‹ะน ะพะฑัŠะตะบั‚ ะฒ ะพะฑั‹ั‡ะฝั‹ะน `list` ั‡ะตั€ะตะท `list(data.items())`. diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md index be1c0e46e1..cbacb129c5 100644 --- a/docs/ru/docs/tutorial/query-params.md +++ b/docs/ru/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ ะšะพะณะดะฐ ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั„ัƒะฝะบั†ะธะธ, ะบะพั‚ะพั€ั‹ะต ะฝะต ัะฒะปััŽั‚ัั ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ะฟัƒั‚ะธ, ะพะฝะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะธะฝั‚ะตั€ะฟั€ะตั‚ะธั€ัƒัŽั‚ัั ะบะฐะบ "query"-ะฟะฐั€ะฐะผะตั‚ั€ั‹. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} Query-ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะฟั€ะตะดัั‚ะฐะฒะปััŽั‚ ะธะท ัะตะฑั ะฝะฐะฑะพั€ ะฟะฐั€ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะธะต, ะบะพั‚ะพั€ั‹ะต ะธะดัƒั‚ ะฟะพัะปะต ะทะฝะฐะบะฐ `?` ะฒ URL-ะฐะดั€ะตัะต, ั€ะฐะทะดะตะปะตะฝะฝั‹ะต ัะธะผะฒะพะปะฐะผะธ `&`. @@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ะ’ัะต ั‚ะต ะถะต ะฟั€ะฐะฒะธะปะฐ, ะบะพั‚ะพั€ั‹ะต ะฟั€ะธะผะตะฝััŽั‚ัั ะบ path-ะฟะฐั€ะฐะผะตั‚ั€ะฐะผ, ั‚ะฐะบะถะต ะฟั€ะธะผะตะฝััŽั‚ัั ะธ query-ะฟะฐั€ะฐะผะตั‚ั€ะฐะผ: * ะŸะพะดะดะตั€ะถะบะฐ ะพั‚ ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ (ะพั‡ะตะฒะธะดะฝะพ) -* "ะŸะฐั€ัะธะฝะณ" ะดะฐะฝะฝั‹ั… +* "ะŸะฐั€ัะธะฝะณ" ะดะฐะฝะฝั‹ั… * ะŸั€ะพะฒะตั€ะบะฐ ะฝะฐ ัะพะพั‚ะฒะตั‚ัั‚ะฒะธะต ะดะฐะฝะฝั‹ั… (ะ’ะฐะปะธะดะฐั†ะธั) * ะะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะฐั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธั @@ -121,13 +121,13 @@ http://127.0.0.1:8000/items/foo?short=yes ## ะžะฑัะทะฐั‚ะตะปัŒะฝั‹ะต query-ะฟะฐั€ะฐะผะตั‚ั€ั‹ { #required-query-parameters } -ะšะพะณะดะฐ ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะฐ, ะบะพั‚ะพั€ั‹ะน ะฝะต ัะฒะปัะตั‚ัั path-ะฟะฐั€ะฐะผะตั‚ั€ะพะผ (ะฒ ัั‚ะพะผ ั€ะฐะทะดะตะปะต, ะผั‹ ะฟะพะบะฐ ั‡ั‚ะพ ะฟะพะทะฝะฐะบะพะผะธะปะธััŒ ั‚ะพะปัŒะบะพ ั path-ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ), ั‚ะพ ะพะฝ ะฝะต ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ. +ะšะพะณะดะฐ ะฒั‹ ะพะฑัŠัะฒะปัะตั‚ะต ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ะฐ, ะบะพั‚ะพั€ั‹ะน ะฝะต ัะฒะปัะตั‚ัั path-ะฟะฐั€ะฐะผะตั‚ั€ะพะผ (ะฒ ัั‚ะพะผ ั€ะฐะทะดะตะปะต ะผั‹ ะฟะพะบะฐ ั‡ั‚ะพ ั€ะฐััะผะพั‚ั€ะตะปะธ ั‚ะพะปัŒะบะพ query-ะฟะฐั€ะฐะผะตั‚ั€ั‹), ั‚ะพ ะพะฝ ะฝะต ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ. ะ•ัะปะธ ะฒั‹ ะฝะต ั…ะพั‚ะธั‚ะต ะทะฐะดะฐะฒะฐั‚ัŒ ะบะพะฝะบั€ะตั‚ะฝะพะต ะทะฝะฐั‡ะตะฝะธะต, ะฝะพ ั…ะพั‚ะธั‚ะต ัะดะตะปะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะตะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ, ะฒั‹ ะผะพะถะตั‚ะต ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ ั€ะฐะฒะฝั‹ะผ `None`. ะะพ ะตัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ัะดะตะปะฐั‚ัŒ query-ะฟะฐั€ะฐะผะตั‚ั€ ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ, ะฒั‹ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฝะต ัƒะบะฐะทั‹ะฒะฐั‚ัŒ ะทะฝะฐั‡ะตะฝะธะต ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} ะ—ะดะตััŒ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟั€ะพัะฐ `needy` ัะฒะปัะตั‚ัั ะพะฑัะทะฐั‚ะตะปัŒะฝั‹ะผ ะฟะฐั€ะฐะผะตั‚ั€ะพะผ ั ั‚ะธะฟะพะผ ะดะฐะฝะฝั‹ั… `str`. diff --git a/docs/ru/docs/tutorial/request-files.md b/docs/ru/docs/tutorial/request-files.md index 9cfbd53dfe..41922333f8 100644 --- a/docs/ru/docs/tutorial/request-files.md +++ b/docs/ru/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ $ pip install python-multipart ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `File` ะธ `UploadFile` ะธะท ะผะพะดัƒะปั `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## ะžะฟั€ะตะดะตะปะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ `File` { #define-file-parameters } ะกะพะทะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ `File` ั‚ะฐะบ ะถะต, ะบะฐะบ ะฒั‹ ัั‚ะพ ะดะตะปะฐะตั‚ะต ะดะปั `Body` ะธะปะธ `Form`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั @@ -54,7 +54,7 @@ $ pip install python-multipart ะžะฟั€ะตะดะตะปะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ ั„ะฐะนะปะฐ ั ั‚ะธะฟะพะผ `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} ะ˜ัะฟะพะปัŒะทะพะฒะฐะฝะธะต `UploadFile` ะธะผะตะตั‚ ั€ัะด ะฟั€ะตะธะผัƒั‰ะตัั‚ะฒ ะฟะตั€ะตะด `bytes`: @@ -122,7 +122,7 @@ contents = myfile.file.read() ะะพ ะบะพะณะดะฐ ั„ะพั€ะผะฐ ะฒะบะปัŽั‡ะฐะตั‚ ั„ะฐะนะปั‹, ะพะฝะฐ ะบะพะดะธั€ัƒะตั‚ัั ะบะฐะบ multipart/form-data. ะ•ัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต `File`, **FastAPI** ะฑัƒะดะตั‚ ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะตะผัƒ ะฝัƒะถะฝะพ ะฟะพะปัƒั‡ะธั‚ัŒ ั„ะฐะนะปั‹ ะธะท ะฝัƒะถะฝะพะน ั‡ะฐัั‚ะธ ั‚ะตะปะฐ. -ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพะฑ ัั‚ะธั… ะบะพะดะธั€ะพะฒะบะฐั… ะธ ะฟะพะปัั… ั„ะพั€ะผ, ะฟะตั€ะตะนะดะธั‚ะต ะฟะพ ััั‹ะปะบะต MDN web docs for POST. +ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพะฑ ัั‚ะธั… ะบะพะดะธั€ะพะฒะบะฐั… ะธ ะฟะพะปัั… ั„ะพั€ะผ, ะฟะตั€ะตะนะดะธั‚ะต ะฟะพ ััั‹ะปะบะต MDN web docs for POST. /// @@ -144,7 +144,7 @@ contents = myfile.file.read() ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `File()` ะฒะผะตัั‚ะต ั `UploadFile`, ะฝะฐะฟั€ะธะผะตั€, ะดะปั ัƒัั‚ะฐะฝะพะฒะบะธ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะผะตั‚ะฐะดะฐะฝะฝั‹ั…: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## ะ—ะฐะณั€ัƒะทะบะฐ ะฝะตัะบะพะปัŒะบะธั… ั„ะฐะนะปะพะฒ { #multiple-file-uploads } @@ -154,7 +154,7 @@ contents = myfile.file.read() ะ”ะปั ัั‚ะพะณะพ ะฝะตะพะฑั…ะพะดะธะผะพ ะพะฑัŠัะฒะธั‚ัŒ ัะฟะธัะพะบ `bytes` ะธะปะธ `UploadFile`: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} ะ’ั‹ ะฟะพะปัƒั‡ะธั‚ะต, ะบะฐะบ ะธ ะฑั‹ะปะพ ะพะฑัŠัะฒะปะตะฝะพ, ัะฟะธัะพะบ `list` ะธะท `bytes` ะธะปะธ `UploadFile`. @@ -170,7 +170,7 @@ contents = myfile.file.read() ะขะฐะบ ะถะต, ะบะฐะบ ะธ ั€ะฐะฝัŒัˆะต, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `File()` ะดะปั ะทะฐะดะฐะฝะธั ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ั… ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ, ะดะฐะถะต ะดะปั `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## ะ ะตะทัŽะผะต { #recap } diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md index f8c58356cb..f4411a27bc 100644 --- a/docs/ru/docs/tutorial/request-form-models.md +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ $ pip install python-multipart ะ’ะฐะผ ะฟั€ะพัั‚ะพ ะฝัƒะถะฝะพ ะพะฑัŠัะฒะธั‚ัŒ **Pydantic-ะผะพะดะตะปัŒ** ั ะฟะพะปัะผะธ, ะบะพั‚ะพั€ั‹ะต ะฒั‹ ั…ะพั‚ะธั‚ะต ะฟะพะปัƒั‡ะธั‚ัŒ ะบะฐะบ **ะฟะพะปั ั„ะพั€ะผั‹**, ะฐ ะทะฐั‚ะตะผ ะพะฑัŠัะฒะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ะบะฐะบ `Form`: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** **ะธะทะฒะปะตั‡ั‘ั‚** ะดะฐะฝะฝั‹ะต ะดะปั **ะบะฐะถะดะพะณะพ ะฟะพะปั** ะธะท **ะดะฐะฝะฝั‹ั… ั„ะพั€ะผั‹** ะฒ ะทะฐะฟั€ะพัะต ะธ ะฒั‹ะดะฐัั‚ ะฒะฐะผ ะพะฑัŠัะฒะปะตะฝะฝัƒัŽ Pydantic-ะผะพะดะตะปัŒ. @@ -48,7 +48,7 @@ $ pip install python-multipart ะ’ั‹ ะผะพะถะตั‚ะต ัะบะพะฝั„ะธะณัƒั€ะธั€ะพะฒะฐั‚ัŒ Pydantic-ะผะพะดะตะปัŒ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะทะฐะฟั€ะตั‚ะธั‚ัŒ (`forbid`) ะฒัะต ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต (`extra`) ะฟะพะปั: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} ะ•ัะปะธ ะบะปะธะตะฝั‚ ะฟะพะฟั€ะพะฑัƒะตั‚ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝั‹ะต ะดะฐะฝะฝั‹ะต, ั‚ะพ ะฒ ะพั‚ะฒะตั‚ ะพะฝ ะฟะพะปัƒั‡ะธั‚ **ะพัˆะธะฑะบัƒ**. diff --git a/docs/ru/docs/tutorial/request-forms-and-files.md b/docs/ru/docs/tutorial/request-forms-and-files.md index 691dc75ba3..10836d74fd 100644 --- a/docs/ru/docs/tutorial/request-forms-and-files.md +++ b/docs/ru/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `File` ะธ `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## ะžะฟั€ะตะดะตะปะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ `File` ะธ `Form` { #define-file-and-form-parameters } ะกะพะทะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั„ะฐะนะปะฐ ะธ ั„ะพั€ะผั‹ ั‚ะฐะบะธะผ ะถะต ะพะฑั€ะฐะทะพะผ, ะบะฐะบ ะดะปั `Body` ะธะปะธ `Query`: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} ะคะฐะนะปั‹ ะธ ะฟะพะปั ั„ะพั€ะผั‹ ะฑัƒะดัƒั‚ ะทะฐะณั€ัƒะถะตะฝั‹ ะฒ ะฒะธะดะต ะดะฐะฝะฝั‹ั… ั„ะพั€ะผั‹, ะธ ะฒั‹ ะฟะพะปัƒั‡ะธั‚ะต ั„ะฐะนะปั‹ ะธ ะฟะพะปั ั„ะพั€ะผั‹. diff --git a/docs/ru/docs/tutorial/request-forms.md b/docs/ru/docs/tutorial/request-forms.md index e257652b61..01f71ac2fc 100644 --- a/docs/ru/docs/tutorial/request-forms.md +++ b/docs/ru/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `Form` ะธะท `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## ะžะฟั€ะตะดะตะปะตะฝะธะต ะฟะฐั€ะฐะผะตั‚ั€ะพะฒ `Form` { #define-form-parameters } ะกะพะทะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ั‹ ั„ะพั€ะผั‹ ั‚ะฐะบ ะถะต, ะบะฐะบ ัั‚ะพ ะดะตะปะฐะตั‚ัั ะดะปั `Body` ะธะปะธ `Query`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} -ะะฐะฟั€ะธะผะตั€, ะฒ ะพะดะฝะพะผ ะธะท ัะฟะพัะพะฑะพะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OAuth2 (ะฝะฐะทั‹ะฒะฐะตะผะพะผ ยซะฟะพั‚ะพะบะพะผ ะฟะฐั€ะพะปัยป) ั‚ั€ะตะฑัƒะตั‚ัั ะพั‚ะฟั€ะฐะฒะธั‚ัŒ `username` ะธ `password` ะฒ ะฒะธะดะต ะฟะพะปะตะน ั„ะพั€ะผั‹. +ะะฐะฟั€ะธะผะตั€, ะฒ ะพะดะฝะพะผ ะธะท ัะฟะพัะพะฑะพะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OAuth2 (ะฝะฐะทั‹ะฒะฐะตะผะพะผ ยซpassword flowยป - ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธั ะฟะพ ะฟะฐั€ะพะปัŽ) ั‚ั€ะตะฑัƒะตั‚ัั ะพั‚ะฟั€ะฐะฒะธั‚ัŒ `username` ะธ `password` ะฒ ะฒะธะดะต ะฟะพะปะตะน ั„ะพั€ะผั‹. -spec ั‚ั€ะตะฑัƒะตั‚, ั‡ั‚ะพะฑั‹ ะฟะพะปั ะฑั‹ะปะธ ัั‚ั€ะพะณะพ ะฝะฐะทะฒะฐะฝั‹ `username` ะธ `password` ะธ ะพั‚ะฟั€ะฐะฒะปัะปะธััŒ ะบะฐะบ ะฟะพะปั ั„ะพั€ะผั‹, ะฐ ะฝะต JSON. +ัะฟะตั†ะธั„ะธะบะฐั†ะธั ั‚ั€ะตะฑัƒะตั‚, ั‡ั‚ะพะฑั‹ ะฟะพะปั ะฑั‹ะปะธ ัั‚ั€ะพะณะพ ะฝะฐะทะฒะฐะฝั‹ `username` ะธ `password` ะธ ะพั‚ะฟั€ะฐะฒะปัะปะธััŒ ะบะฐะบ ะฟะพะปั ั„ะพั€ะผั‹, ะฐ ะฝะต JSON. ะก ะฟะพะผะพั‰ัŒัŽ `Form` ะฒั‹ ะผะพะถะตั‚ะต ะพะฑัŠัะฒะธั‚ัŒ ั‚ะต ะถะต ะฝะฐัั‚ั€ะพะนะบะธ, ั‡ั‚ะพ ะธ ั `Body` (ะธ `Query`, `Path`, `Cookie`), ะฒะบะปัŽั‡ะฐั ะฒะฐะปะธะดะฐั†ะธัŽ, ะฟั€ะธะผะตั€ั‹, ะฟัะตะฒะดะพะฝะธะผ (ะฝะฐะฟั€ะธะผะตั€, `user-name` ะฒะผะตัั‚ะพ `username`) ะธ ั‚.ะด. @@ -56,7 +56,7 @@ $ pip install python-multipart ะะพ ะบะพะณะดะฐ ั„ะพั€ะผะฐ ัะพะดะตั€ะถะธั‚ ั„ะฐะนะปั‹, ะพะฝะฐ ะบะพะดะธั€ัƒะตั‚ัั ะบะฐะบ `multipart/form-data`. ะž ั€ะฐะฑะพั‚ะต ั ั„ะฐะนะปะฐะผะธ ะฒั‹ ะฟั€ะพั‡ั‚ั‘ั‚ะต ะฒ ัะปะตะดัƒัŽั‰ะตะน ะณะปะฐะฒะต. -ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะฟั€ะพ ัั‚ะธ ะบะพะดะธั€ะพะฒะบะธ ะธ ะฟะพะปั ั„ะพั€ะผั‹, ะพะฑั€ะฐั‚ะธั‚ะตััŒ ะบ MDN ะฒะตะฑ-ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะดะปั `POST`. +ะ•ัะปะธ ะฒั‹ ั…ะพั‚ะธั‚ะต ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะฟั€ะพ ัั‚ะธ ะบะพะดะธั€ะพะฒะบะธ ะธ ะฟะพะปั ั„ะพั€ะผั‹, ะพะฑั€ะฐั‚ะธั‚ะตััŒ ะบ MDN ะฒะตะฑ-ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะดะปั `POST`. /// diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md index 22a811cd57..cd99ce28c7 100644 --- a/docs/ru/docs/tutorial/response-model.md +++ b/docs/ru/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั ะกะฐะผั‹ะน ั€ะฐัะฟั€ะพัั‚ั€ะฐะฝั‘ะฝะฝั‹ะน ัะปัƒั‡ะฐะน โ€” [ะฒะพะทะฒั€ะฐั‰ะฐั‚ัŒ Response ะฝะฐะฟั€ัะผัƒัŽ, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะดะฐะปะตะต ะฒ ั€ะฐะทะดะตะปะฐั… ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะดะปั ะฟั€ะพะดะฒะธะฝัƒั‚ั‹ั…](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} ะญั‚ะพั‚ ะฟั€ะพัั‚ะพะน ัะปัƒั‡ะฐะน ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ัั FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ, ะฟะพั‚ะพะผัƒ ั‡ั‚ะพ ะฐะฝะฝะพั‚ะฐั†ะธั ะฒะพะทะฒั€ะฐั‰ะฐะตะผะพะณะพ ั‚ะธะฟะฐ โ€” ัั‚ะพ ะบะปะฐัั (ะธะปะธ ะฟะพะดะบะปะฐัั) `Response`. @@ -193,7 +193,7 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะพะดะบะปะฐัั `Response` ะฒ ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะฐ: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} ะญั‚ะพ ั‚ะพะถะต ัั€ะฐะฑะพั‚ะฐะตั‚, ั‚ะฐะบ ะบะฐะบ `RedirectResponse` โ€” ะฟะพะดะบะปะฐัั `Response`, ะธ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑั€ะฐะฑะพั‚ะฐะตั‚ ัั‚ะพั‚ ะฟั€ะพัั‚ะพะน ัะปัƒั‡ะฐะน. @@ -201,7 +201,7 @@ FastAPI ะดะตะปะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ะฒะตั‰ะตะน ะฒะฝัƒั‚ั€ะธ ะฒะผะตัั‚ะต ั ะะพ ะบะพะณะดะฐ ะฒั‹ ะฒะพะทะฒั€ะฐั‰ะฐะตั‚ะต ะฟั€ะพะธะทะฒะพะปัŒะฝั‹ะน ะพะฑัŠะตะบั‚, ะฝะต ัะฒะปััŽั‰ะธะนัั ะฒะฐะปะธะดะฝั‹ะผ ั‚ะธะฟะพะผ Pydantic (ะฝะฐะฟั€ะธะผะตั€, ะพะฑัŠะตะบั‚ ะฑะฐะทั‹ ะดะฐะฝะฝั‹ั…), ะธ ะฐะฝะฝะพั‚ะธั€ัƒะตั‚ะต ะตะณะพ ั‚ะฐะบะธะผ ะพะฑั€ะฐะทะพะผ ะฒ ั„ัƒะฝะบั†ะธะธ, FastAPI ะฟะพะฟั‹ั‚ะฐะตั‚ัั ัะพะทะดะฐั‚ัŒ ะผะพะดะตะปัŒ ะพั‚ะฒะตั‚ะฐ Pydantic ะธะท ัั‚ะพะน ะฐะฝะฝะพั‚ะฐั†ะธะธ ั‚ะธะฟะฐ ะธ ะฟะพั‚ะตั€ะฟะธั‚ ะฝะตัƒะดะฐั‡ัƒ. -ะขะพ ะถะต ะฟั€ะพะธะทะพะนะดั‘ั‚, ะตัะปะธ ัƒ ะฒะฐั ะฑัƒะดะตั‚ ั‡ั‚ะพ-ั‚ะพ ะฒั€ะพะดะต union ั€ะฐะทะฝั‹ั… ั‚ะธะฟะพะฒ, ะณะดะต ะพะดะธะฝ ะธะปะธ ะฝะตัะบะพะปัŒะบะพ ะฝะต ัะฒะปััŽั‚ัั ะฒะฐะปะธะดะฝั‹ะผะธ ั‚ะธะฟะฐะผะธ Pydantic, ะฝะฐะฟั€ะธะผะตั€, ัั‚ะพ ะฟั€ะธะฒะตะดั‘ั‚ ะบ ะพัˆะธะฑะบะต ๐Ÿ’ฅ: +ะขะพ ะถะต ะฟั€ะพะธะทะพะนะดั‘ั‚, ะตัะปะธ ัƒ ะฒะฐั ะฑัƒะดะตั‚ ั‡ั‚ะพ-ั‚ะพ ะฒั€ะพะดะต union ั€ะฐะทะฝั‹ั… ั‚ะธะฟะพะฒ, ะณะดะต ะพะดะธะฝ ะธะปะธ ะฝะตัะบะพะปัŒะบะพ ะฝะต ัะฒะปััŽั‚ัั ะฒะฐะปะธะดะฝั‹ะผะธ ั‚ะธะฟะฐะผะธ Pydantic, ะฝะฐะฟั€ะธะผะตั€, ัั‚ะพ ะฟั€ะธะฒะตะดั‘ั‚ ะบ ะพัˆะธะฑะบะต ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md index 30f642b643..13d982e803 100644 --- a/docs/ru/docs/tutorial/response-status-code.md +++ b/docs/ru/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * ะธ ะดั€ัƒะณะธั…. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | ะŸั€ะธะผะตั‡ะฐะฝะธะต @@ -66,7 +66,7 @@ FastAPI ะทะฝะฐะตั‚ ะพะฑ ัั‚ะพะผ ะธ ัะพะทะดะฐัั‚ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Open /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะงั‚ะพะฑั‹ ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพ HTTP ะบะพะดะฐั… ัั‚ะฐั‚ัƒัะฐ ะธ ะพ ั‚ะพะผ, ะดะปั ั‡ะตะณะพ ะบะฐะถะดั‹ะน ะธะท ะฝะธั… ะฟั€ะตะดะฝะฐะทะฝะฐั‡ะตะฝ, ะพะทะฝะฐะบะพะผัŒั‚ะตััŒ ั MDN ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน ะพะฑ HTTP ัั‚ะฐั‚ัƒั-ะบะพะดะฐั…. +ะงั‚ะพะฑั‹ ัƒะทะฝะฐั‚ัŒ ะฑะพะปัŒัˆะต ะพ HTTP ะบะพะดะฐั… ัั‚ะฐั‚ัƒัะฐ ะธ ะพ ั‚ะพะผ, ะดะปั ั‡ะตะณะพ ะบะฐะถะดั‹ะน ะธะท ะฝะธั… ะฟั€ะตะดะฝะฐะทะฝะฐั‡ะตะฝ, ะพะทะฝะฐะบะพะผัŒั‚ะตััŒ ั MDN ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน ะพะฑ HTTP ัั‚ะฐั‚ัƒั-ะบะพะดะฐั…. /// @@ -74,7 +74,7 @@ FastAPI ะทะฝะฐะตั‚ ะพะฑ ัั‚ะพะผ ะธ ัะพะทะดะฐัั‚ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Open ะ ะฐััะผะพั‚ั€ะธะผ ะฟั€ะตะดั‹ะดัƒั‰ะธะน ะฟั€ะธะผะตั€ ะตั‰ะต ั€ะฐะท: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` โ€“ ัั‚ะพ ะบะพะด ัั‚ะฐั‚ัƒัะฐ "ะกะพะทะดะฐะฝะพ". @@ -82,7 +82,7 @@ FastAPI ะทะฝะฐะตั‚ ะพะฑ ัั‚ะพะผ ะธ ัะพะทะดะฐัั‚ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Open ะ”ะปั ัƒะดะพะฑัั‚ะฒะฐ ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฟะตั€ะตะผะตะฝะฝั‹ะต ะธะท `fastapi.status`. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} ะžะฝะธ ัะพะดะตั€ะถะฐั‚ ั‚ะต ะถะต ั‡ะธัะปะพะฒั‹ะต ะทะฝะฐั‡ะตะฝะธั, ะฝะพ ะฟะพะทะฒะพะปััŽั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฐะฒั‚ะพะทะฐะฒะตั€ัˆะตะฝะธะต ั€ะตะดะฐะบั‚ะพั€ะฐ ะบะพะดะฐ ะดะปั ะฒั‹ะฑะพั€ะฐ ะบะพะดะฐ ัั‚ะฐั‚ัƒัะฐ: @@ -90,7 +90,7 @@ FastAPI ะทะฝะฐะตั‚ ะพะฑ ัั‚ะพะผ ะธ ัะพะทะดะฐัั‚ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธัŽ Open /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ -ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `from starlette import status` ะฒะผะตัั‚ะพ `from fastapi import status`. +ะ’ั‹ ั‚ะฐะบะถะต ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ `from starlette import status`. **FastAPI** ะฟะพะทะฒะพะปัะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะบะฐะบ `starlette.status`, ั‚ะฐะบ ะธ `fastapi.status` ะธัะบะปัŽั‡ะธั‚ะตะปัŒะฝะพ ะดะปั ัƒะดะพะฑัั‚ะฒะฐ ั€ะฐะทั€ะฐะฑะพั‚ั‡ะธะบะพะฒ. ะะพ ะฟะพัั‚ะฐะฒะปัะตั‚ัั fastapi.status ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะธะท Starlette. diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md index e4a97c8801..c7381aae25 100644 --- a/docs/ru/docs/tutorial/schema-extra-example.md +++ b/docs/ru/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ OpenAPI 3.1.0 (ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฝะฐั‡ะธะฝะฐั ั FastAPI 0.99.0) ะดะพะฑ ะšะพะณะดะฐ ะฒั‹ ะดะตะปะฐะตั‚ะต ัั‚ะพ, ะฟั€ะธะผะตั€ั‹ ัั‚ะฐะฝะพะฒัั‚ัั ั‡ะฐัั‚ัŒัŽ ะฒะฝัƒั‚ั€ะตะฝะฝะตะน **JSON Schema** ะดะปั ะดะฐะฝะฝั‹ั… ั‚ะตะปะฐ ะทะฐะฟั€ะพัะฐ. -ะขะตะผ ะฝะต ะผะตะฝะตะต, ะฝะฐ ะผะพะผะตะฝั‚ ะฝะฐะฟะธัะฐะฝะธั ัั‚ะพะณะพ Swagger UI, ะธะฝัั‚ั€ัƒะผะตะฝั‚, ะพั‚ะฒะตั‡ะฐัŽั‰ะธะน ะทะฐ ะพั‚ะพะฑั€ะฐะถะตะฝะธะต UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฟะพะบะฐะท ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะธะผะตั€ะพะฒ ะดะปั ะดะฐะฝะฝั‹ั… ะฒ **JSON Schema**. ะะพ ะฝะธะถะต ะตัั‚ัŒ ะพะฑั…ะพะดะฝะพะน ะฟัƒั‚ัŒ. +ะขะตะผ ะฝะต ะผะตะฝะตะต, ะฝะฐ ะผะพะผะตะฝั‚ ะฝะฐะฟะธัะฐะฝะธั ัั‚ะพะณะพ Swagger UI, ะธะฝัั‚ั€ัƒะผะตะฝั‚, ะพั‚ะฒะตั‡ะฐัŽั‰ะธะน ะทะฐ ะพั‚ะพะฑั€ะฐะถะตะฝะธะต UI ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฟะพะบะฐะท ะฝะตัะบะพะปัŒะบะธั… ะฟั€ะธะผะตั€ะพะฒ ะดะปั ะดะฐะฝะฝั‹ั… ะฒ **JSON Schema**. ะะพ ะฝะธะถะต ะตัั‚ัŒ ะพะฑั…ะพะดะฝะพะน ะฟัƒั‚ัŒ. ### ะกะฟะตั†ะธั„ะธั‡ะตัะบะธะต ะดะปั OpenAPI `examples` { #openapi-specific-examples } diff --git a/docs/ru/docs/tutorial/security/first-steps.md b/docs/ru/docs/tutorial/security/first-steps.md index 983e85e661..9b9673b842 100644 --- a/docs/ru/docs/tutorial/security/first-steps.md +++ b/docs/ru/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ ะกะบะพะฟะธั€ัƒะนั‚ะต ะฟั€ะธะผะตั€ ะฒ ั„ะฐะนะป `main.py`: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## ะ—ะฐะฟัƒัะบ { #run-it } @@ -132,7 +132,7 @@ OAuth2 ะฑั‹ะป ัะฟั€ะพะตะบั‚ะธั€ะพะฒะฐะฝ ั‚ะฐะบ, ั‡ั‚ะพะฑั‹ ะฑัะบะตะฝะด ะธะปะธ ะŸั€ะธ ัะพะทะดะฐะฝะธะธ ัะบะทะตะผะฟะปัั€ะฐ ะบะปะฐััะฐ `OAuth2PasswordBearer` ะผั‹ ะฟะตั€ะตะดะฐะตะผ ะฟะฐั€ะฐะผะตั‚ั€ `tokenUrl`. ะญั‚ะพั‚ ะฟะฐั€ะฐะผะตั‚ั€ ัะพะดะตั€ะถะธั‚ URL, ะบะพั‚ะพั€ั‹ะน ะบะปะธะตะฝั‚ (ั„ั€ะพะฝั‚ะตะฝะด, ั€ะฐะฑะพั‚ะฐัŽั‰ะธะน ะฒ ะฑั€ะฐัƒะทะตั€ะต ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั) ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะดะปั ะพั‚ะฟั€ะฐะฒะบะธ `username` ะธ `password`, ั‡ั‚ะพะฑั‹ ะฟะพะปัƒั‡ะธั‚ัŒ ั‚ะพะบะตะฝ. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -170,7 +170,7 @@ oauth2_scheme(some, parameters) ะขะตะฟะตั€ัŒ ะฒั‹ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ัŒ `oauth2_scheme` ะบะฐะบ ะทะฐะฒะธัะธะผะพัั‚ัŒ ั `Depends`. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ะญั‚ะฐ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฟั€ะตะดะพัั‚ะฐะฒะธั‚ `str`, ะบะพั‚ะพั€ั‹ะน ะฑัƒะดะตั‚ ะฟั€ะธัะฒะพะตะฝ ะฟะฐั€ะฐะผะตั‚ั€ัƒ `token` *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ ะฟัƒั‚ะธ*. diff --git a/docs/ru/docs/tutorial/security/get-current-user.md b/docs/ru/docs/tutorial/security/get-current-user.md index c6bc07cc16..8388b672c7 100644 --- a/docs/ru/docs/tutorial/security/get-current-user.md +++ b/docs/ru/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ ะ’ ะฟั€ะตะดั‹ะดัƒั‰ะตะน ะณะปะฐะฒะต ัะธัั‚ะตะผะฐ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ (ะพัะฝะพะฒะฐะฝะฝะฐั ะฝะฐ ัะธัั‚ะตะผะต ะฒะฝะตะดั€ะตะฝะธั ะทะฐะฒะธัะธะผะพัั‚ะตะน) ะฟะตั€ะตะดะฐะฒะฐะปะฐ *ั„ัƒะฝะบั†ะธะธ-ะพะฑั€ะฐะฑะพั‚ั‡ะธะบัƒ ะฟัƒั‚ะธ* `token` ั‚ะธะฟะฐ `str`: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ะะพ ัั‚ะพ ะฒัั‘ ะตั‰ั‘ ะฝะต ัะปะธัˆะบะพะผ ะฟะพะปะตะทะฝะพ. diff --git a/docs/ru/docs/tutorial/security/index.md b/docs/ru/docs/tutorial/security/index.md index ebac013b6c..bd8da824b3 100644 --- a/docs/ru/docs/tutorial/security/index.md +++ b/docs/ru/docs/tutorial/security/index.md @@ -1,56 +1,56 @@ -# ะะฐัั‚ั€ะพะนะบะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ { #security } +# ะ‘ะตะทะพะฟะฐัะฝะพัั‚ัŒ { #security } ะกัƒั‰ะตัั‚ะฒัƒะตั‚ ะผะฝะพะถะตัั‚ะฒะพ ัะฟะพัะพะฑะพะฒ ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ, ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะธ ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ. -ะžะฑั‹ั‡ะฝะพ ัั‚ะฐ ั‚ะตะผะฐ ัะฒะปัะตั‚ัั ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ัะปะพะถะฝะพะน ะธ ั‚ั€ัƒะดะฝะพะน. +ะžะฑั‹ั‡ะฝะพ ัั‚ะฐ ั‚ะตะผะฐ ัะฒะปัะตั‚ัั ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ัะปะพะถะฝะพะน ะธ ยซั‚ั€ัƒะดะฝะพะนยป. -ะ’ะพ ะผะฝะพะณะธั… ั„ั€ะตะนะผะฒะพั€ะบะฐั… ะธ ัะธัั‚ะตะผะฐั… ั‚ะพะปัŒะบะพ ั€ะฐะฑะพั‚ะฐ ั ะพะฟั€ะตะดะตะปะตะฝะธะตะผ ะดะพัั‚ัƒะฟะพะฒ ะบ ะฟั€ะธะปะพะถะตะฝะธัŽ ะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะตะน ั‚ั€ะตะฑัƒะตั‚ ะทะฝะฐั‡ะธั‚ะตะปัŒะฝั‹ั… ะทะฐั‚ั€ะฐั‚ ัƒัะธะปะธะน ะธ ะฝะฐะฟะธัะฐะฝะธั ะผะฝะพะถะตัั‚ะฒะฐ ะบะพะดะฐ (ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะตะณะพ ะพะฑัŠั‘ะผ ะผะพะถะตั‚ ัะพัั‚ะฐะฒะปัั‚ัŒ ะฑะพะปะตะต 50% ะพั‚ ะฒัะตะณะพ ะฝะฐะฟะธัะฐะฝะฝะพะณะพ ะบะพะดะฐ). +ะ’ะพ ะผะฝะพะณะธั… ั„ั€ะตะนะผะฒะพั€ะบะฐั… ะธ ัะธัั‚ะตะผะฐั… ั‚ะพะปัŒะบะพ ั€ะฐะฑะพั‚ะฐ ั ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒัŽ ะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะตะน ั‚ั€ะตะฑัƒะตั‚ ะทะฝะฐั‡ะธั‚ะตะปัŒะฝั‹ั… ะทะฐั‚ั€ะฐั‚ ัƒัะธะปะธะน ะธ ะฝะฐะฟะธัะฐะฝะธั ะผะฝะพะถะตัั‚ะฒะฐ ะบะพะดะฐ (ะฒะพ ะผะฝะพะณะธั… ัะปัƒั‡ะฐัั… ะตะณะพ ะพะฑัŠั‘ะผ ะผะพะถะตั‚ ัะพัั‚ะฐะฒะปัั‚ัŒ 50% ะธะปะธ ะฑะพะปะตะต ะพั‚ ะฒัะตะณะพ ะฝะฐะฟะธัะฐะฝะฝะพะณะพ ะบะพะดะฐ). -**FastAPI** ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะบะพั‚ะพั€ั‹ะต ะฟะพะผะพะณัƒั‚ ะฒะฐะผ ะฝะฐัั‚ั€ะพะธั‚ัŒ **ะะฒั‚ะพั€ะธะทะฐั†ะธัŽ** ะปะตะณะบะพ, ะฑั‹ัั‚ั€ะพ, ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะผ ัะฟะพัะพะฑะพะผ, ะฑะตะท ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ ะธะทัƒั‡ะฐั‚ัŒ ะฒัะต ะตั‘ ั‚ะพะฝะบะพัั‚ะธ. +**FastAPI** ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะบะพั‚ะพั€ั‹ะต ะฟะพะผะพะณัƒั‚ ะฒะฐะผ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั **ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒัŽ** ะปะตะณะบะพ, ะฑั‹ัั‚ั€ะพ, ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะผ ัะฟะพัะพะฑะพะผ, ะฑะตะท ะฝะตะพะฑั…ะพะดะธะผะพัั‚ะธ ะธะทัƒั‡ะฐั‚ัŒ ะธ ั€ะฐะทะฑะธั€ะฐั‚ัŒัั ะฒะพ ะฒัะตั… ัะฟะตั†ะธั„ะธะบะฐั†ะธัั… ะฟะพ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. -ะะพ ัะฝะฐั‡ะฐะปะฐ ะดะฐะฒะฐะนั‚ะต ั€ะฐััะผะพั‚ั€ะธะผ ะฝะตะบะพั‚ะพั€ั‹ะต ะฝะตะฑะพะปัŒัˆะธะต ะบะพะฝั†ะตะฟั†ะธะธ. +ะะพ ัะฝะฐั‡ะฐะปะฐ ะดะฐะฒะฐะนั‚ะต ั€ะฐััะผะพั‚ั€ะธะผ ะฝะตัะบะพะปัŒะบะพ ะฝะตะฑะพะปัŒัˆะธั… ะบะพะฝั†ะตะฟั†ะธะน. -## ะšัƒะดะฐ-ั‚ะพ ั‚ะพั€ะพะฟะธัˆัŒัั? { #in-a-hurry } +## ะะตั‚ ะฒั€ะตะผะตะฝะธ? { #in-a-hurry } -ะ•ัะปะธ ะฒะฐะผ ะฝะต ะฝัƒะถะฝะฐ ะธะฝั„ะพั€ะผะฐั†ะธั ะพ ะบะฐะบะธั…-ะปะธะฑะพ ะธะท ัะปะตะดัƒัŽั‰ะธั… ั‚ะตั€ะผะธะฝะพะฒ ะธ ะฒะฐะผ ะฟั€ะพัั‚ะพ ะฝัƒะถะฝะพ ะดะพะฑะฐะฒะธั‚ัŒ ะทะฐั‰ะธั‚ัƒ ั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะตะน ะฝะฐ ะพัะฝะพะฒะต ะปะพะณะธะฝะฐ ะธ ะฟะฐั€ะพะปั *ะฟั€ัะผะพ ัะตะนั‡ะฐั*, ะฟะตั€ะตั…ะพะดะธั‚ะต ะบ ัะปะตะดัƒัŽั‰ะธะผ ะณะปะฐะฒะฐะผ. +ะ•ัะปะธ ะฒะฐะผ ะฝะต ะฒะฐะถะฝั‹ ะบะฐะบะธะต-ะปะธะฑะพ ะธะท ัั‚ะธั… ั‚ะตั€ะผะธะฝะพะฒ ะธ ะฒะฐะผ ะฟั€ะพัั‚ะพ ะฝัƒะถะฝะพ ะดะพะฑะฐะฒะธั‚ัŒ ะทะฐั‰ะธั‚ัƒ ั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะตะน ะฝะฐ ะพัะฝะพะฒะต ะธะผะตะฝะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะธ ะฟะฐั€ะพะปั ะฟั€ัะผะพ ัะตะนั‡ะฐั, ะฟะตั€ะตั…ะพะดะธั‚ะต ะบ ัะปะตะดัƒัŽั‰ะธะผ ะณะปะฐะฒะฐะผ. ## OAuth2 { #oauth2 } -OAuth2 - ัั‚ะพ ะฟั€ะพั‚ะพะบะพะป, ะบะพั‚ะพั€ั‹ะน ะพะฟั€ะตะดะตะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ัะฟะพัะพะฑะพะฒ ะพะฑั€ะฐะฑะพั‚ะบะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะธ ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ. +OAuth2 - ัั‚ะพ ัะฟะตั†ะธั„ะธะบะฐั†ะธั, ะบะพั‚ะพั€ะฐั ะพะฟั€ะตะดะตะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ัะฟะพัะพะฑะพะฒ ะพะฑั€ะฐะฑะพั‚ะบะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะธ ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ. -ะžะฝ ะดะพะฒะพะปัŒะฝะพ ะพะฑัˆะธั€ะตะฝ ะธ ะพั…ะฒะฐั‚ั‹ะฒะฐะตั‚ ะฝะตัะบะพะปัŒะบะพ ัะปะพะถะฝั‹ั… ะฒะฐั€ะธะฐะฝั‚ะพะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั. +ะญั‚ะพ ะดะพะฒะพะปัŒะฝะพ ะพะฑัˆะธั€ะฝะฐั ัะฟะตั†ะธั„ะธะบะฐั†ะธั, ะพั…ะฒะฐั‚ั‹ะฒะฐัŽั‰ะฐั ะฝะตัะบะพะปัŒะบะพ ัะปะพะถะฝั‹ั… ะฒะฐั€ะธะฐะฝั‚ะพะฒ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธั. -OAuth2 ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั ัะฟะพัะพะฑั‹ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ "ั‚ั€ะตั‚ัŒะตะน ัั‚ะพั€ะพะฝั‹". +ะžะฝะฐ ะฒะบะปัŽั‡ะฐะตั‚ ัะฟะพัะพะฑั‹ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ ยซั‚ั€ะตั‚ัŒะตะน ัั‚ะพั€ะพะฝั‹ยป. -ะญั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะธัะฟะพะปัŒะทัƒัŽั‚ ะฟะพะด ัะพะฑะพะน ะฒัะต ะบะฝะพะฟะบะธ "ะฒั…ะพะด ั ะฟะพะผะพั‰ัŒัŽ Facebook, Google, X (Twitter), GitHub" ะฝะฐ ัั‚ั€ะฐะฝะธั†ะฐั… ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ. +ะ˜ะผะตะฝะฝะพ ัั‚ะพ ะธัะฟะพะปัŒะทัƒะตั‚ัั ะฒะพ ะฒัะตั… ัะธัั‚ะตะผะฐั… ั ะบะฝะพะฟะบะฐะผะธ ยซะฒะพะนั‚ะธ ั ะฟะพะผะพั‰ัŒัŽ Facebook, Google, X (Twitter), GitHubยป. ### OAuth 1 { #oauth-1 } -ะ ะฐะฝะตะต ะธัะฟะพะปัŒะทะพะฒะฐะปัั ะฟั€ะพั‚ะพะบะพะป OAuth 1, ะบะพั‚ะพั€ั‹ะน ัะธะปัŒะฝะพ ะพั‚ะปะธั‡ะฐะตั‚ัั ะพั‚ OAuth2 ะธ ัะฒะปัะตั‚ัั ะฑะพะปะตะต ัะปะพะถะฝั‹ะผ, ะฟะพัะบะพะปัŒะบัƒ ะพะฝ ะฒะบะปัŽั‡ะฐะป ะฟั€ัะผั‹ะต ะพะฟะธัะฐะฝะธั ั‚ะพะณะพ, ะบะฐะบ ัˆะธั„ั€ะพะฒะฐั‚ัŒ ัะพะพะฑั‰ะตะฝะธะต. +ะ ะฐะฝะตะต ะธัะฟะพะปัŒะทะพะฒะฐะปัั OAuth 1, ะบะพั‚ะพั€ั‹ะน ัะธะปัŒะฝะพ ะพั‚ะปะธั‡ะฐะตั‚ัั ะพั‚ OAuth2 ะธ ัะฒะปัะตั‚ัั ะฑะพะปะตะต ัะปะพะถะฝั‹ะผ, ะฟะพัะบะพะปัŒะบัƒ ะพะฝ ะฒะบะปัŽั‡ะฐะป ะฟั€ัะผั‹ะต ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ ั‚ะพะณะพ, ะบะฐะบ ัˆะธั„ั€ะพะฒะฐั‚ัŒ ะพะฑะผะตะฝ ะดะฐะฝะฝั‹ะผะธ. ะ’ ะฝะฐัั‚ะพัั‰ะตะต ะฒั€ะตะผั ะพะฝ ะฝะต ะพั‡ะตะฝัŒ ะฟะพะฟัƒะปัั€ะตะฝ ะธ ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ัั. -OAuth2 ะฝะต ัƒะบะฐะทั‹ะฒะฐะตั‚, ะบะฐะบ ัˆะธั„ั€ะพะฒะฐั‚ัŒ ัะพะพะฑั‰ะตะฝะธะต, ะพะฝ ะพะถะธะดะฐะตั‚, ั‡ั‚ะพ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะฑัƒะดะตั‚ ะพะฑัะปัƒะถะธะฒะฐั‚ัŒัั ะฟะพ ะฟั€ะพั‚ะพะบะพะปัƒ HTTPS. +OAuth2 ะฝะต ัƒะบะฐะทั‹ะฒะฐะตั‚, ะบะฐะบ ัˆะธั„ั€ะพะฒะฐั‚ัŒ ะพะฑะผะตะฝ ะดะฐะฝะฝั‹ะผะธ, ะพะฝ ะพะถะธะดะฐะตั‚, ั‡ั‚ะพ ะฒะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต ะฑัƒะดะตั‚ ะพะฑัะปัƒะถะธะฒะฐั‚ัŒัั ะฟะพ ะฟั€ะพั‚ะพะบะพะปัƒ HTTPS. /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ’ ั€ะฐะทะดะตะปะต **ะ ะฐะทะฒะตั€ั‚ั‹ะฒะฐะฝะธะต** ะฒั‹ ัƒะฒะธะดะธั‚ะต ะบะฐะบ ะฝะฐัั‚ั€ะพะธั‚ัŒ ะฟั€ะพั‚ะพะบะพะป HTTPS ะฑะตัะฟะปะฐั‚ะฝะพ, ะธัะฟะพะปัŒะทัƒั Traefik ะธ Let's Encrypt. +ะ’ ั€ะฐะทะดะตะปะต ะพ **ั€ะฐะทะฒะตั€ั‚ั‹ะฒะฐะฝะธะธ** ะฒั‹ ัƒะฒะธะดะธั‚ะต, ะบะฐะบ ะฝะฐัั‚ั€ะพะธั‚ัŒ HTTPS ะฑะตัะฟะปะฐั‚ะฝะพ, ะธัะฟะพะปัŒะทัƒั Traefik ะธ Let's Encrypt. /// ## OpenID Connect { #openid-connect } -OpenID Connect - ัั‚ะพ ะตั‰ะต ะพะดะธะฝ ะฟั€ะพั‚ะพะบะพะป, ะพัะฝะพะฒะฐะฝะฝั‹ะน ะฝะฐ **OAuth2**. +OpenID Connect โ€” ัั‚ะพ ะตั‰ั‘ ะพะดะฝะฐ ัะฟะตั†ะธั„ะธะบะฐั†ะธั, ะพัะฝะพะฒะฐะฝะฝะฐั ะฝะฐ **OAuth2**. -ะžะฝ ะฟั€ะพัั‚ะพ ั€ะฐััˆะธั€ัะตั‚ OAuth2, ัƒั‚ะพั‡ะฝัั ะฝะตะบะพั‚ะพั€ั‹ะต ะฒะตั‰ะธ, ะฝะต ะธะผะตัŽั‰ะธะต ะพะดะฝะพะทะฝะฐั‡ะฝะพะณะพ ะพะฟั€ะตะดะตะปะตะฝะธั ะฒ OAuth2, ะฒ ะฟะพะฟั‹ั‚ะบะต ัะดะตะปะฐั‚ัŒ ะตะณะพ ะฑะพะปะตะต ัะพะฒะผะตัั‚ะธะผั‹ะผ. +ะžะฝะฐ ะฟั€ะพัั‚ะพ ั€ะฐััˆะธั€ัะตั‚ OAuth2, ัƒั‚ะพั‡ะฝัั ะฝะตะบะพั‚ะพั€ั‹ะต ะฒะตั‰ะธ, ะบะพั‚ะพั€ั‹ะต ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพ ะฝะตะพะดะฝะพะทะฝะฐั‡ะฝั‹ ะฒ OAuth2, ัั‚ะฐั€ะฐัััŒ ัะดะตะปะฐั‚ัŒ ะตะณะพ ะฑะพะปะตะต ัะพะฒะผะตัั‚ะธะผั‹ะผ. -ะะฐะฟั€ะธะผะตั€, ะดะปั ะฒั…ะพะดะฐ ะฒ Google ะธัะฟะพะปัŒะทัƒะตั‚ัั OpenID Connect (ะบะพั‚ะพั€ั‹ะน ะฟะพะด ัะพะฑะพะน ะธัะฟะพะปัŒะทัƒะตั‚ OAuth2). +ะะฐะฟั€ะธะผะตั€, ะดะปั ะฒั…ะพะดะฐ ะฒ Google ะธัะฟะพะปัŒะทัƒะตั‚ัั OpenID Connect (ะบะพั‚ะพั€ั‹ะน ะฟะพะด ะบะฐะฟะพั‚ะพะผ ะธัะฟะพะปัŒะทัƒะตั‚ OAuth2). ะะพ ะฒั…ะพะด ะฒ Facebook ะฝะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ OpenID Connect. ะฃ ะฝะตะณะพ ะตัั‚ัŒ ัะพะฑัั‚ะฒะตะฝะฝะฐั ะฒะฐั€ะธะฐั†ะธั OAuth2. -### OpenID (ะฝะต "OpenID Connect") { #openid-not-openid-connect } +### OpenID (ะฝะต ยซOpenID Connectยป) { #openid-not-openid-connect } -ะขะฐะบะถะต ั€ะฐะฝะตะต ะธัะฟะพะปัŒะทะพะฒะฐะปัั ัั‚ะฐะฝะดะฐั€ั‚ "OpenID", ะบะพั‚ะพั€ั‹ะน ะฟั‹ั‚ะฐะปัั ั€ะตัˆะธั‚ัŒ ั‚ัƒ ะถะต ะฟั€ะพะฑะปะตะผัƒ, ั‡ั‚ะพ ะธ **OpenID Connect**, ะฝะพ ะฝะต ะฑั‹ะป ะพัะฝะพะฒะฐะฝ ะฝะฐ OAuth2. +ะขะฐะบะถะต ั€ะฐะฝะตะต ะธัะฟะพะปัŒะทะพะฒะฐะปะฐััŒ ัะฟะตั†ะธั„ะธะบะฐั†ะธั ยซOpenIDยป, ะบะพั‚ะพั€ะฐั ะฟั‹ั‚ะฐะปะฐััŒ ั€ะตัˆะธั‚ัŒ ั‚ัƒ ะถะต ะทะฐะดะฐั‡ัƒ, ั‡ั‚ะพ ะธ **OpenID Connect**, ะฝะพ ะฝะต ะฑั‹ะปะฐ ะพัะฝะพะฒะฐะฝะฐ ะฝะฐ OAuth2. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ัั‚ะพ ะฑั‹ะปะฐ ะฟะพะปะฝะพั†ะตะฝะฝะฐั ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ัะธัั‚ะตะผะฐ. @@ -62,45 +62,45 @@ OpenAPI (ั€ะฐะฝะตะต ะธะทะฒะตัั‚ะฝั‹ะน ะบะฐะบ Swagger) - ัั‚ะพ ะพั‚ะบั€ั‹ั‚ะฐั **FastAPI** ะพัะฝะพะฒะฐะฝ ะฝะฐ **OpenAPI**. -ะญั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะดะตะปะฐะตั‚ ะฒะพะทะผะพะถะฝั‹ะผ ะฝะฐะปะธั‡ะธะต ะผะฝะพะถะตัั‚ะฒะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธั… ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั‹ั… ะธะฝั‚ะตั€ั„ะตะนัะพะฒ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธั, ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝะพะณะพ ะบะพะดะฐ ะธ ั‚.ะด. +ะญั‚ะพ ั‚ะพ, ั‡ั‚ะพ ะดะตะปะฐะตั‚ ะฒะพะทะผะพะถะฝั‹ะผะธ ะฝะตัะบะพะปัŒะบะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธั… ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั‹ั… ะธะฝั‚ะตั€ั„ะตะนัะพะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ, ะณะตะฝะตั€ะฐั†ะธัŽ ะบะพะดะฐ ะธ ั‚.ะด. -ะ’ OpenAPI ะตัั‚ัŒ ัะฟะพัะพะฑ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฝะตัะบะพะปัŒะบะพ "ัั…ะตะผ" ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. +ะ’ OpenAPI ะตัั‚ัŒ ัะฟะพัะพะฑ ะพะฟั€ะตะดะตะปะธั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ยซัั…ะตะผยป ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. -ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒั‹ ะผะพะถะตั‚ะต ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฟั€ะตะธะผัƒั‰ะตัั‚ะฒะฐะผะธ ะ’ัะตั… ัั‚ะธั… ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ั… ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะฒะบะปัŽั‡ะฐั ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั‹ะต ัะธัั‚ะตะผั‹ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธั. +ะ˜ัะฟะพะปัŒะทัƒั ะธั…, ะฒั‹ ะผะพะถะตั‚ะต ะฒะพัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะฟั€ะตะธะผัƒั‰ะตัั‚ะฒะฐะผะธ ะฒัะตั… ัั‚ะธั… ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ, ะพัะฝะพะฒะฐะฝะฝั‹ั… ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฐั…, ะฒะบะปัŽั‡ะฐั ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั‹ะต ัะธัั‚ะตะผั‹ ะดะพะบัƒะผะตะฝั‚ะธั€ะพะฒะฐะฝะธั. -OpenAPI ะผะพะถะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ัะปะตะดัƒัŽั‰ะธะต ัั…ะตะผั‹ ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ: +OpenAPI ะพะฟั€ะตะดะตะปัะตั‚ ัะปะตะดัƒัŽั‰ะธะต ัั…ะตะผั‹ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ: -* `apiKey`: ัƒะฝะธะบะฐะปัŒะฝั‹ะน ะธะดะตะฝั‚ะธั„ะธะบะฐั‚ะพั€ ะดะปั ะฟั€ะธะปะพะถะตะฝะธั, ะบะพั‚ะพั€ั‹ะน ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฟะพะปัƒั‡ะตะฝ ะธะท: - * ะŸะฐั€ะฐะผะตั‚ั€ะพะฒ ะทะฐะฟั€ะพัะฐ. - * ะ—ะฐะณะพะปะพะฒะบะฐ. - * Cookies. -* `http`: ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ัะธัั‚ะตะผั‹ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฟะพ ะฟั€ะพั‚ะพะบะพะปัƒ HTTP, ะฒะบะปัŽั‡ะฐั: - * `bearer`: ะทะฐะณะพะปะพะฒะพะบ `Authorization` ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ `Bearer {ัƒะฝะธะบะฐะปัŒะฝั‹ะน ั‚ะพะบะตะฝ}`. ะญั‚ะพ ัƒะฝะฐัะปะตะดะพะฒะฐะฝะพ ะพั‚ OAuth2. - * ะ‘ะฐะทะพะฒะฐั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธั ะฟะพ ะฟั€ะพั‚ะพะบะพะปัƒ HTTP. +* `apiKey`: ัะฟะตั†ะธั„ะธั‡ะฝั‹ะน ะดะปั ะฟั€ะธะปะพะถะตะฝะธั ะบะปัŽั‡, ะบะพั‚ะพั€ั‹ะน ะผะพะถะตั‚ ะฟะพัั‚ัƒะฟะฐั‚ัŒ ะธะท: + * ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะทะฐะฟั€ะพัะฐ. + * HTTP-ะทะฐะณะพะปะพะฒะบะฐ. + * cookie. +* `http`: ัั‚ะฐะฝะดะฐั€ั‚ะฝั‹ะต ัะธัั‚ะตะผั‹ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฟะพ HTTP, ะฒะบะปัŽั‡ะฐั: + * `bearer`: HTTP-ะทะฐะณะพะปะพะฒะพะบ `Authorization` ัะพ ะทะฝะฐั‡ะตะฝะธะตะผ `Bearer ` ะฟะปัŽั ั‚ะพะบะตะฝ. ะญั‚ะพ ัƒะฝะฐัะปะตะดะพะฒะฐะฝะพ ะพั‚ OAuth2. + * ะ‘ะฐะทะพะฒะฐั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธั ะฟะพ HTTP. * HTTP Digest ะธ ั‚.ะด. -* `oauth2`: ะฒัะต ัะฟะพัะพะฑั‹ ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ OAuth2 ะฝะฐะทั‹ะฒะฐะตะผั‹ะต "ะฟะพั‚ะพะบะธ" (ะฐะฝะณะป. "flows"). - * ะะตะบะพั‚ะพั€ั‹ะต ะธะท ัั‚ะธั… "ะฟะพั‚ะพะบะพะฒ" ะฟะพะดั…ะพะดัั‚ ะดะปั ั€ะตะฐะปะธะทะฐั†ะธะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ั‡ะตั€ะตะท ัั‚ะพั€ะพะฝะฝะธะน ัะตั€ะฒะธั ะธัะฟะพะปัŒะทัƒัŽั‰ะธะน OAuth 2.0 (ะฝะฐะฟั€ะธะผะตั€, Google, Facebook, X (Twitter), GitHub ะธ ั‚.ะด.): +* `oauth2`: ะฒัะต ัะฟะพัะพะฑั‹ OAuth2 ะดะปั ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ (ะฝะฐะทั‹ะฒะฐัŽั‚ัั ยซะฟะพั‚ะพะบะฐะผะธยป). + * ะะตัะบะพะปัŒะบะพ ะธะท ัั‚ะธั… ยซะฟะพั‚ะพะบะพะฒยป ะฟะพะดั…ะพะดัั‚ ะดะปั ะฟะพัั‚ั€ะพะตะฝะธั ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ OAuth 2.0 (ะฝะฐะฟั€ะธะผะตั€, Google, Facebook, X (Twitter), GitHub ะธ ั‚.ะด.): * `implicit` * `clientCredentials` * `authorizationCode` - * ะะพ ะตัั‚ัŒ ะพะดะธะฝ ะบะพะฝะบั€ะตั‚ะฝั‹ะน "ะฟะพั‚ะพะบ", ะบะพั‚ะพั€ั‹ะน ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะธะดะตะฐะปัŒะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝ ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ั‚ะพะผ ะถะต ะฟั€ะธะปะพะถะตะฝะธะธ: - * `password`: ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปะตะดัƒัŽั‰ะธั… ะณะปะฐะฒะฐั… ะฑัƒะดัƒั‚ ั€ะฐััะผะพั‚ั€ะตะฝั‹ ะฟั€ะธะผะตั€ั‹ ัั‚ะพะณะพ. -* `openIdConnect`: ัะฟะพัะพะฑ ะพะฟั€ะตะดะตะปะธั‚ัŒ, ะบะฐะบ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑะฝะฐั€ัƒะถะธะฒะฐั‚ัŒ ะดะฐะฝะฝั‹ะต ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ OAuth2. - * ะญั‚ะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะต ะพะฑะฝะฐั€ัƒะถะตะฝะธะต ะพะฟั€ะตะดะตะปะตะฝะพ ะฒ ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OpenID Connect. + * ะะพ ะตัั‚ัŒ ะพะดะธะฝ ะบะพะฝะบั€ะตั‚ะฝั‹ะน ยซะฟะพั‚ะพะบยป, ะบะพั‚ะพั€ั‹ะน ะผะพะถะฝะพ ะธะดะตะฐะปัŒะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะดะปั ะพะฑั€ะฐะฑะพั‚ะบะธ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ัั‚ะพะผ ะถะต ะฟั€ะธะปะพะถะตะฝะธะธ: + * `password`: ะฒ ะฝะตะบะพั‚ะพั€ั‹ั… ัะปะตะดัƒัŽั‰ะธั… ะณะปะฐะฒะฐั… ะฑัƒะดัƒั‚ ะฟั€ะธะฒะตะดะตะฝั‹ ะฟั€ะธะผะตั€ั‹. +* `openIdConnect`: ะธะผะตะตั‚ ัะฟะพัะพะฑ ะพะฟั€ะตะดะตะปะธั‚ัŒ, ะบะฐะบ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะพะฑะฝะฐั€ัƒะถะธะฒะฐั‚ัŒ ะดะฐะฝะฝั‹ะต ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ OAuth2. + * ะ˜ะผะตะฝะฝะพ ัั‚ะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะพะต ะพะฑะฝะฐั€ัƒะถะตะฝะธะต ะพะฟั€ะตะดะตะปะตะฝะพ ะฒ ัะฟะตั†ะธั„ะธะบะฐั†ะธะธ OpenID Connect. /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ˜ะฝั‚ะตะณั€ะฐั†ะธั ัั‚ะพั€ะพะฝะฝะธั… ัะตั€ะฒะธัะพะฒ ะดะปั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ/ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ ั‚ะฐะบะธั… ะบะฐะบ Google, Facebook, X (Twitter), GitHub ะธ ั‚.ะด. ะพััƒั‰ะตัั‚ะฒะปัะตั‚ัั ะดะพัั‚ะฐั‚ะพั‡ะฝะพ ะปะตะณะบะพ. +ะ˜ะฝั‚ะตะณั€ะฐั†ะธั ัั‚ะพั€ะพะฝะฝะธั… ะฟั€ะพะฒะฐะนะดะตั€ะพะฒ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ/ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ, ั‚ะฐะบะธั… ะบะฐะบ Google, Facebook, X (Twitter), GitHub ะธ ั‚.ะด., ั‚ะฐะบะถะต ะฒะพะทะผะพะถะฝะฐ ะธ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝะพ ะฟั€ะพัั‚ะฐ. -ะกะฐะผะพะน ัะปะพะถะฝะพะน ะฟั€ะพะฑะปะตะผะพะน ัะฒะปัะตั‚ัั ัะพะทะดะฐะฝะธะต ั‚ะฐะบะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ/ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ, ะฝะพ **FastAPI** ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฒะฐะผ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะฟะพะทะฒะพะปััŽั‰ะธะต ะปะตะณะบะพ ัั‚ะพ ัะดะตะปะฐั‚ัŒ, ะฒั‹ะฟะพะปะฝัั ะฟั€ะธ ัั‚ะพะผ ะฒััŽ ั‚ัะถะตะปัƒัŽ ั€ะฐะฑะพั‚ัƒ ะทะฐ ะฒะฐั. +ะกะฐะผะพะน ัะปะพะถะฝะพะน ะทะฐะดะฐั‡ะตะน ัะฒะปัะตั‚ัั ัะพะทะดะฐะฝะธะต ั‚ะฐะบะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ/ะฐะฒั‚ะพั€ะธะทะฐั†ะธะธ, ะฝะพ **FastAPI** ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฒะฐะผ ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะฟะพะทะฒะพะปััŽั‰ะธะต ะปะตะณะบะพ ัั‚ะพ ัะดะตะปะฐั‚ัŒ, ะฒั‹ะฟะพะปะฝัั ะฟั€ะธ ัั‚ะพะผ ะฒััŽ ั‚ัะถั‘ะปัƒัŽ ั€ะฐะฑะพั‚ัƒ ะทะฐ ะฒะฐั. /// -## ะŸั€ะตะธะผัƒั‰ะตัั‚ะฒะฐ **FastAPI** { #fastapi-utilities } +## ะ˜ะฝัั‚ั€ัƒะผะตะฝั‚ั‹ **FastAPI** { #fastapi-utilities } -Fast API ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ะดะปั ะบะฐะถะดะพะน ะธะท ัั‚ะธั… ัั…ะตะผ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะฒ ะผะพะดัƒะปะต `fastapi.security`, ะบะพั‚ะพั€ั‹ะต ัƒะฟั€ะพั‰ะฐัŽั‚ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ัั‚ะธั… ะผะตั…ะฐะฝะธะทะผะพะฒ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. +FastAPI ะฟั€ะตะดะพัั‚ะฐะฒะปัะตั‚ ะฝะตัะบะพะปัŒะบะพ ะธะฝัั‚ั€ัƒะผะตะฝั‚ะพะฒ ะดะปั ะบะฐะถะดะพะน ะธะท ัั‚ะธั… ัั…ะตะผ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ ะฒ ะผะพะดัƒะปะต `fastapi.security`, ะบะพั‚ะพั€ั‹ะต ัƒะฟั€ะพั‰ะฐัŽั‚ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต ัั‚ะธั… ะผะตั…ะฐะฝะธะทะผะพะฒ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ. -ะ’ ัะปะตะดัƒัŽั‰ะธั… ะณะปะฐะฒะฐั… ะฒั‹ ัƒะฒะธะดะธั‚ะต, ะบะฐะบ ะพะฑะตะทะพะฟะฐัะธั‚ัŒ ัะฒะพะน API, ะธัะฟะพะปัŒะทัƒั ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะฟั€ะตะดะพัั‚ะฐะฒะปัะตะผั‹ะต **FastAPI**. +ะ’ ัะปะตะดัƒัŽั‰ะธั… ะณะปะฐะฒะฐั… ะฒั‹ ัƒะฒะธะดะธั‚ะต, ะบะฐะบ ะดะพะฑะฐะฒะธั‚ัŒ ะฑะตะทะพะฟะฐัะฝะพัั‚ัŒ ะฒ ะฒะฐัˆ API, ะธัะฟะพะปัŒะทัƒั ะธะฝัั‚ั€ัƒะผะตะฝั‚ั‹, ะฟั€ะตะดะพัั‚ะฐะฒะปัะตะผั‹ะต **FastAPI**. -ะ˜ ะฒั‹ ั‚ะฐะบะถะต ัƒะฒะธะดะธั‚ะต, ะบะฐะบ ะพะฝ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะธะฝั‚ะตะณั€ะธั€ัƒะตั‚ัั ะฒ ัะธัั‚ะตะผัƒ ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. +ะ˜ ะฒั‹ ั‚ะฐะบะถะต ัƒะฒะธะดะธั‚ะต, ะบะฐะบ ัั‚ะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะตัะบะธ ะธะฝั‚ะตะณั€ะธั€ัƒะตั‚ัั ะฒ ัะธัั‚ะตะผัƒ ะธะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพะน ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ. diff --git a/docs/ru/docs/tutorial/security/oauth2-jwt.md b/docs/ru/docs/tutorial/security/oauth2-jwt.md index 803491f539..7838b07df4 100644 --- a/docs/ru/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ru/docs/tutorial/security/oauth2-jwt.md @@ -1,10 +1,10 @@ # OAuth2 ั ะฟะฐั€ะพะปะตะผ (ะธ ั…ะตัˆะธั€ะพะฒะฐะฝะธะตะผ), Bearer ั JWT-ั‚ะพะบะตะฝะฐะผะธ { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -ะขะตะฟะตั€ัŒ, ะบะพะณะดะฐ ัƒ ะฝะฐั ะพะฟั€ะตะดะตะปะตะฝ ะฟั€ะพั†ะตัั ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ, ะดะฐะฒะฐะนั‚ะต ัะดะตะปะฐะตะผ ะฟั€ะธะปะพะถะตะฝะธะต ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ ะฑะตะทะพะฟะฐัะฝั‹ะผ, ะธัะฟะพะปัŒะทัƒั ั‚ะพะบะตะฝั‹ JWT ะธ ะฑะตะทะพะฟะฐัะฝะพะต ั…ะตัˆะธั€ะพะฒะฐะฝะธะต ะฟะฐั€ะพะปะตะน. +ะขะตะฟะตั€ัŒ, ะบะพะณะดะฐ ัƒ ะฝะฐั ะพะฟั€ะตะดะตะปะตะฝ ะฟั€ะพั†ะตัั ะพะฑะตัะฟะตั‡ะตะฝะธั ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ, ะดะฐะฒะฐะนั‚ะต ัะดะตะปะฐะตะผ ะฟั€ะธะปะพะถะตะฝะธะต ะดะตะนัั‚ะฒะธั‚ะตะปัŒะฝะพ ะฑะตะทะพะฟะฐัะฝั‹ะผ, ะธัะฟะพะปัŒะทัƒั ั‚ะพะบะตะฝั‹ JWT ะธ ะฑะตะทะพะฟะฐัะฝะพะต ั…ะตัˆะธั€ะพะฒะฐะฝะธะต ะฟะฐั€ะพะปะตะน. ะญั‚ะพั‚ ะบะพะด ะผะพะถะฝะพ ั€ะตะฐะปัŒะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฒ ัะฒะพะตะผ ะฟั€ะธะปะพะถะตะฝะธะธ, ัะพั…ั€ะฐะฝัั‚ัŒ ั…ััˆะธ ะฟะฐั€ะพะปะตะน ะฒ ะฑะฐะทะต ะดะฐะฝะฝั‹ั… ะธ ั‚.ะด. -ะœั‹ ะฟั€ะพะดะพะปะถะธะผ ั€ะฐะทะฑะธั€ะฐั‚ัŒัั, ะฝะฐั‡ะธะฝะฐั ั ั‚ะพะณะพ ะผะตัั‚ะฐ, ะฝะฐ ะบะพั‚ะพั€ะพะผ ะพัั‚ะฐะฝะพะฒะธะปะธััŒ ะฒ ะฟั€ะตะดั‹ะดัƒั‰ะตะน ะณะปะฐะฒะต. +ะœั‹ ะฟั€ะพะดะพะปะถะธะผ ั€ะฐะทะฑะธั€ะฐั‚ัŒัั, ะฝะฐั‡ะธะฝะฐั ั ั‚ะพะณะพ ะผะตัั‚ะฐ, ะฝะฐ ะบะพั‚ะพั€ะพะผ ะพัั‚ะฐะฝะพะฒะธะปะธััŒ ะฒ ะฟั€ะตะดั‹ะดัƒั‰ะตะน ะณะปะฐะฒะต, ะธ ั€ะฐััˆะธั€ะธะผ ะตะณะพ. ## ะŸั€ะพ JWT { #about-jwt } @@ -43,9 +43,11 @@ $ pip install pyjwt /// info | ะ”ะพะฟะพะปะฝะธั‚ะตะปัŒะฝะฐั ะธะฝั„ะพั€ะผะฐั†ะธั + ะ•ัะปะธ ะฒั‹ ะฟะปะฐะฝะธั€ัƒะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฐะปะณะพั€ะธั‚ะผั‹ ั†ะธั„ั€ะพะฒะพะน ะฟะพะดะฟะธัะธ, ั‚ะฐะบะธะต ะบะฐะบ RSA ะธะปะธ ECDSA, ะฒะฐะผ ัะปะตะดัƒะตั‚ ัƒัั‚ะฐะฝะพะฒะธั‚ัŒ ะทะฐะฒะธัะธะผะพัั‚ัŒ ะฑะธะฑะปะธะพั‚ะตะบะธ ะบั€ะธะฟั‚ะพะณั€ะฐั„ะธะธ `pyjwt[crypto]`. ะŸะพะดั€ะพะฑะฝะตะต ะพะฑ ัั‚ะพะผ ะผะพะถะฝะพ ะฟั€ะพั‡ะธั‚ะฐั‚ัŒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ ะฟะพ ัƒัั‚ะฐะฝะพะฒะบะต PyJWT. + /// ## ะฅะตัˆะธั€ะพะฒะฐะฝะธะต ะฟะฐั€ะพะปะตะน { #password-hashing } @@ -83,11 +85,13 @@ $ pip install "pwdlib[argon2]" /// tip | ะŸะพะดัะบะฐะทะบะฐ + ะก ะฟะพะผะพั‰ัŒัŽ `pwdlib` ะผะพะถะฝะพ ะดะฐะถะต ะฝะฐัั‚ั€ะพะธั‚ัŒ ะตะณะพ ะฝะฐ ั‡ั‚ะตะฝะธะต ะฟะฐั€ะพะปะตะน, ัะพะทะดะฐะฝะฝั‹ั… **Django**, ะฟะปะฐะณะธะฝะพะผ ะฑะตะทะพะฟะฐัะฝะพัั‚ะธ **Flask** ะธะปะธ ะผะฝะพะณะธะผะธ ะดั€ัƒะณะธะผะธ ะฑะธะฑะปะธะพั‚ะตะบะฐะผะธ. ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะฒั‹ ัะผะพะถะตั‚ะต, ะฝะฐะฟั€ะธะผะตั€, ัะพะฒะผะตัั‚ะฝะพ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพะดะฝะธ ะธ ั‚ะต ะถะต ะดะฐะฝะฝั‹ะต ะธะท ะฟั€ะธะปะพะถะตะฝะธั Django ะฒ ะฑะฐะทะต ะดะฐะฝะฝั‹ั… ั ะฟั€ะธะปะพะถะตะฝะธะตะผ FastAPI. ะ˜ะปะธ ะฟะพัั‚ะตะฟะตะฝะฝะพ ะผะธะณั€ะธั€ะพะฒะฐั‚ัŒ Django-ะฟั€ะธะปะพะถะตะฝะธะต, ะธัะฟะพะปัŒะทัƒั ั‚ัƒ ะถะต ะฑะฐะทัƒ ะดะฐะฝะฝั‹ั…. ะŸั€ะธ ัั‚ะพะผ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะธ ัะผะพะณัƒั‚ ะพะดะฝะพะฒั€ะตะผะตะฝะฝะพ ะฒั…ะพะดะธั‚ัŒ ะฒ ัะธัั‚ะตะผัƒ ะบะฐะบ ะธะท ะฟั€ะธะปะพะถะตะฝะธั Django, ั‚ะฐะบ ะธ ะธะท ะฟั€ะธะปะพะถะตะฝะธั **FastAPI**. + /// ## ะฅะตัˆะธั€ะพะฒะฐะฝะธะต ะธ ะฟั€ะพะฒะตั€ะบะฐ ะฟะฐั€ะพะปะตะน { #hash-and-verify-the-passwords } @@ -97,11 +101,13 @@ $ pip install "pwdlib[argon2]" ะกะพะทะดะฐะนั‚ะต ัะบะทะตะผะฟะปัั€ PasswordHash ั ั€ะตะบะพะผะตะฝะดะพะฒะฐะฝะฝั‹ะผะธ ะฝะฐัั‚ั€ะพะนะบะฐะผะธ โ€” ะพะฝ ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะดะปั ั…ััˆะธั€ะพะฒะฐะฝะธั ะธ ะฟั€ะพะฒะตั€ะบะธ ะฟะฐั€ะพะปะตะน. /// tip | ะŸะพะดัะบะฐะทะบะฐ + pwdlib ั‚ะฐะบะถะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฐะปะณะพั€ะธั‚ะผ ั…ะตัˆะธั€ะพะฒะฐะฝะธั bcrypt, ะฝะพ ะฝะต ะฒะบะปัŽั‡ะฐะตั‚ ัƒัั‚ะฐั€ะตะฒัˆะธะต ะฐะปะณะพั€ะธั‚ะผั‹ โ€” ะดะปั ั€ะฐะฑะพั‚ั‹ ั ัƒัั‚ะฐั€ะตะฒัˆะธะผะธ ั…ััˆะฐะผะธ ั€ะตะบะพะผะตะฝะดัƒะตั‚ัั ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะฑะธะฑะปะธะพั‚ะตะบัƒ passlib. ะะฐะฟั€ะธะผะตั€, ะฒั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะตะต ะดะปั ั‡ั‚ะตะฝะธั ะธ ะฟั€ะพะฒะตั€ะบะธ ะฟะฐั€ะพะปะตะน, ัะณะตะฝะตั€ะธั€ะพะฒะฐะฝะฝั‹ั… ะดั€ัƒะณะพะน ัะธัั‚ะตะผะพะน (ะฝะฐะฟั€ะธะผะตั€, Django), ะฝะพ ั…ััˆะธั€ะพะฒะฐั‚ัŒ ะฒัะต ะฝะพะฒั‹ะต ะฟะฐั€ะพะปะธ ะดั€ัƒะณะธะผ ะฐะปะณะพั€ะธั‚ะผะพะผ, ะฝะฐะฟั€ะธะผะตั€ Argon2 ะธะปะธ Bcrypt. ะ˜ ะฟั€ะธ ัั‚ะพะผ ะฑั‹ั‚ัŒ ัะพะฒะผะตัั‚ะธะผั‹ะผ ัะพ ะฒัะตะผะธ ัั‚ะธะผะธ ัะธัั‚ะตะผะฐะผะธ. + /// ะกะพะทะดะฐะนั‚ะต ัะปัƒะถะตะฑะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ ะดะปั ั…ััˆะธั€ะพะฒะฐะฝะธั ะฟะฐั€ะพะปั, ะฟะพัั‚ัƒะฟะฐัŽั‰ะตะณะพ ะพั‚ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั. @@ -110,10 +116,16 @@ pwdlib ั‚ะฐะบะถะต ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚ ะฐะปะณะพั€ะธั‚ะผ ั…ะตัˆะธั€ะพะฒะฐะฝะธ ะ˜ ะตั‰ะต ะพะดะฝัƒ โ€” ะดะปั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ะธ ะฒะพะทะฒั€ะฐั‚ะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +ะšะพะณะดะฐ `authenticate_user` ะฒั‹ะทั‹ะฒะฐะตั‚ัั ั ะธะผะตะฝะตะผ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั, ะบะพั‚ะพั€ะพะณะพ ะฝะตั‚ ะฒ ะฑะฐะทะต ะดะฐะฝะฝั‹ั…, ะผั‹ ะฒัะต ั€ะฐะฒะฝะพ ะทะฐะฟัƒัะบะฐะตะผ `verify_password` ั ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะตะผ ั„ะธะบั‚ะธะฒะฝะพะณะพ ั…ััˆะฐ. + +ะญั‚ะพ ะณะฐั€ะฐะฝั‚ะธั€ัƒะตั‚, ั‡ั‚ะพ ัะฝะดะฟะพะธะฝั‚ ะพั‚ะฒะตั‡ะฐะตั‚ ะฟั€ะธะผะตั€ะฝะพ ะทะฐ ะพะดะฝะพ ะธ ั‚ะพ ะถะต ะฒั€ะตะผั ะฒะฝะต ะทะฐะฒะธัะธะผะพัั‚ะธ ะพั‚ ั‚ะพะณะพ, ััƒั‰ะตัั‚ะฒัƒะตั‚ ะธะผั ะฟะพะปัŒะทะพะฒะฐั‚ะตะปั ะธะปะธ ะฝะตั‚, ะฟั€ะตะดะพั‚ะฒั€ะฐั‰ะฐั ั‚ะฐะนะผะธะฝะณะพะฒั‹ะต ะฐั‚ะฐะบะธ (ะฐั‚ะฐะบะฐ ะฟะพ ะฒั€ะตะผะตะฝะธ), ั ะฟะพะผะพั‰ัŒัŽ ะบะพั‚ะพั€ั‹ั… ะผะพะถะฝะพ ะฑั‹ะปะพ ะฑั‹ ะฟะตั€ะตั‡ะธัะปัั‚ัŒ ััƒั‰ะตัั‚ะฒัƒัŽั‰ะธะต ะธะผะตะฝะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปะตะน. /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ + ะ•ัะปะธ ะฟั€ะพะฒะตั€ะธั‚ัŒ ะฝะพะฒัƒัŽ (ั„ะฐะปัŒัˆะธะฒัƒัŽ) ะฑะฐะทัƒ ะดะฐะฝะฝั‹ั… `fake_users_db`, ั‚ะพ ะผะพะถะฝะพ ัƒะฒะธะดะตั‚ัŒ, ะบะฐะบ ั‚ะตะฟะตั€ัŒ ะฒั‹ะณะปัะดะธั‚ ั…ััˆะธั€ะพะฒะฐะฝะฝั‹ะน ะฟะฐั€ะพะปัŒ: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + /// ## ะ ะฐะฑะพั‚ะฐ ั JWT ั‚ะพะบะตะฝะฐะผะธ { #handle-jwt-tokens } @@ -144,7 +156,7 @@ $ openssl rand -hex 32 ะกะพะทะดะฐะนั‚ะต ัะปัƒะถะตะฑะฝัƒัŽ ั„ัƒะฝะบั†ะธัŽ ะดะปั ะณะตะฝะตั€ะฐั†ะธะธ ะฝะพะฒะพะณะพ ั‚ะพะบะตะฝะฐ ะดะพัั‚ัƒะฟะฐ. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## ะžะฑะฝะพะฒะปะตะฝะธะต ะทะฐะฒะธัะธะผะพัั‚ะตะน { #update-the-dependencies } @@ -154,7 +166,7 @@ $ openssl rand -hex 32 ะ•ัะปะธ ั‚ะพะบะตะฝ ะฝะตะดะตะนัั‚ะฒะธั‚ะตะปะตะฝ, ั‚ะพ ัั€ะฐะทัƒ ะถะต ะฒะตั€ะฝะธั‚ะต HTTP-ะพัˆะธะฑะบัƒ. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## ะžะฑะฝะพะฒะปะตะฝะธะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* `/token` { #update-the-token-path-operation } @@ -162,7 +174,7 @@ $ openssl rand -hex 32 ะกะพะทะดะฐะนั‚ะต ั€ะตะฐะปัŒะฝั‹ะน ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟะฐ JWT ะธ ะฒะตั€ะฝะธั‚ะต ะตะณะพ -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### ะขะตั…ะฝะธั‡ะตัะบะธะต ะฟะพะดั€ะพะฑะฝะพัั‚ะธ ะพ JWT ะบะปัŽั‡ะต `sub` { #technical-details-about-the-jwt-subject-sub } @@ -202,7 +214,9 @@ Username: `johndoe` Password: `secret` /// check | ะŸั€ะพะฒะตั€ะบะฐ + ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต, ั‡ั‚ะพ ะฝะธะณะดะต ะฒ ะบะพะดะต ะฝะต ะธัะฟะพะปัŒะทัƒะตั‚ัั ะพั‚ะบั€ั‹ั‚ั‹ะน ั‚ะตะบัั‚ ะฟะฐั€ะพะปั "`secret`", ะผั‹ ะธัะฟะพะปัŒะทัƒะตะผ ั‚ะพะปัŒะบะพ ะตะณะพ ั…ััˆะธั€ะพะฒะฐะฝะฝัƒัŽ ะฒะตั€ัะธัŽ. + /// @@ -225,7 +239,9 @@ Password: `secret` /// note | ะขะตั…ะฝะธั‡ะตัะบะฐั ะธะฝั„ะพั€ะผะฐั†ะธั + ะžะฑั€ะฐั‚ะธั‚ะต ะฒะฝะธะผะฐะฝะธะต ะฝะฐ HTTP-ะทะฐะณะพะปะพะฒะพะบ `Authorization`, ะทะฝะฐั‡ะตะฝะธะต ะบะพั‚ะพั€ะพะณะพ ะฝะฐั‡ะธะฝะฐะตั‚ัั ั `Bearer `. + /// ## ะŸั€ะพะดะฒะธะฝัƒั‚ะพะต ะธัะฟะพะปัŒะทะพะฒะฐะฝะธะต `scopes` { #advanced-usage-with-scopes } diff --git a/docs/ru/docs/tutorial/security/simple-oauth2.md b/docs/ru/docs/tutorial/security/simple-oauth2.md index 36ff32c8ef..4b86a40139 100644 --- a/docs/ru/docs/tutorial/security/simple-oauth2.md +++ b/docs/ru/docs/tutorial/security/simple-oauth2.md @@ -236,7 +236,7 @@ UserInDB( -ะ•ัะปะธ ั‰ั‘ะปะบะฝัƒั‚ัŒ ะฝะฐ ะทะฝะฐั‡ะบะต ะทะฐะผะบะฐ ะธ ะฒั‹ะนั‚ะธ ะธะท ัะธัั‚ะตะผั‹, ะฐ ะทะฐั‚ะตะผ ะฟะพะฟั‹ั‚ะฐั‚ัŒัั ะฒั‹ะฟะพะปะฝะธั‚ัŒ ั‚ัƒ ะถะต ะพะฟะตั€ะฐั†ะธัŽ ะตั‰ั‘ ั€ะฐะท, ะฑัƒะดะตั‚ ะฒั‹ะดะฐะฝะฐ ะพัˆะธะฑะบะฐ HTTP 401: +ะ•ัะปะธ ั‰ั‘ะปะบะฝัƒั‚ัŒ ะฝะฐ ะทะฝะฐั‡ะบะต ะทะฐะผะบะฐ ะธ ะฒั‹ะนั‚ะธ ะธะท ัะธัั‚ะตะผั‹, ะฐ ะทะฐั‚ะตะผ ะฟะพะฟั€ะพะฑะพะฒะฐั‚ัŒ ะฒั‹ะฟะพะปะฝะธั‚ัŒ ั‚ัƒ ะถะต ะพะฟะตั€ะฐั†ะธัŽ ะตั‰ั‘ ั€ะฐะท, ะฑัƒะดะตั‚ ะฒั‹ะดะฐะฝะฐ ะพัˆะธะฑะบะฐ HTTP 401: ```JSON { diff --git a/docs/ru/docs/tutorial/sql-databases.md b/docs/ru/docs/tutorial/sql-databases.md index 1d03465337..ed67739cc9 100644 --- a/docs/ru/docs/tutorial/sql-databases.md +++ b/docs/ru/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ /// tip | ะŸะพะดัะบะฐะทะบะฐ -ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะปัŽะฑัƒัŽ ะดั€ัƒะณัƒัŽ ะฑะธะฑะปะธะพั‚ะตะบัƒ ะดะปั ั€ะฐะฑะพั‚ั‹ ั SQL ะธะปะธ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั… (ะธะฝะพะณะดะฐ ะธั… ะฝะฐะทั‹ะฒะฐัŽั‚ "ORMs"), FastAPI ะฝะธั‡ะตะณะพ ะฝะต ะฝะฐะฒัะทั‹ะฒะฐะตั‚. ๐Ÿ˜Ž +ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะปัŽะฑัƒัŽ ะดั€ัƒะณัƒัŽ ะฑะธะฑะปะธะพั‚ะตะบัƒ ะดะปั ั€ะฐะฑะพั‚ั‹ ั SQL ะธะปะธ NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะฝั‹ั… (ะธะฝะพะณะดะฐ ะธั… ะฝะฐะทั‹ะฒะฐัŽั‚ "ORMs"), FastAPI ะฝะธั‡ะตะณะพ ะฝะต ะฝะฐะฒัะทั‹ะฒะฐะตั‚. ๐Ÿ˜Ž /// @@ -344,7 +344,7 @@ $ fastapi dev main.py -ะ•ัะปะธ ะฒั‹ ะฟะตั€ะตะนะดั‘ั‚ะต ะฒ UI API `/docs`, ะฒั‹ ัƒะฒะธะดะธั‚ะต, ั‡ั‚ะพ ะพะฝ ะพะฑะฝะพะฒะธะปัั: ั‚ะตะฟะตั€ัŒ ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะณะตั€ะพั ะพะฝ ะฝะต ะพะถะธะดะฐะตั‚ ะฟะพะปัƒั‡ะธั‚ัŒ `id` ะพั‚ ะบะปะธะตะฝั‚ะฐ ะธ ั‚. ะด. +ะ•ัะปะธ ะฒั‹ ะฟะตั€ะตะนะดั‘ั‚ะต ะฒ UI API `/docs`, ะฒั‹ ัƒะฒะธะดะธั‚ะต, ั‡ั‚ะพ ะพะฝ ะพะฑะฝะพะฒะธะปัั: ั‚ะตะฟะตั€ัŒ ะฟั€ะธ ัะพะทะดะฐะฝะธะธ ะณะตั€ะพั ะพะฝ ะฝะต ะพะถะธะดะฐะตั‚ ะฟะพะปัƒั‡ะธั‚ัŒ `id` ะพั‚ ะบะปะธะตะฝั‚ะฐ ะธ ั‚.ะด.
@@ -354,4 +354,4 @@ $ fastapi dev main.py ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ **SQLModel** ะดะปั ะฒะทะฐะธะผะพะดะตะนัั‚ะฒะธั ั SQL ะฑะฐะทะพะน ะดะฐะฝะฝั‹ั… ะธ ัƒะฟั€ะพัั‚ะธั‚ัŒ ะบะพะด ั ะฟะพะผะพั‰ัŒัŽ *ะผะพะดะตะปะตะน ะดะฐะฝะฝั‹ั…* ะธ *ะผะพะดะตะปะตะน-ั‚ะฐะฑะปะธั†*. -ะ“ะพั€ะฐะทะดะพ ะฑะพะปัŒัˆะต ะฒั‹ ะผะพะถะตั‚ะต ัƒะทะฝะฐั‚ัŒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ **SQLModel**, ั‚ะฐะผ ะตัั‚ัŒ ะฑะพะปะตะต ะฟะพะดั€ะพะฑะฝั‹ะน ะผะธะฝะธ-ั‚ัƒั‚ะพั€ะธะฐะป ะฟะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธัŽ SQLModel ั **FastAPI**. ๐Ÿš€ +ะ“ะพั€ะฐะทะดะพ ะฑะพะปัŒัˆะต ะฒั‹ ะผะพะถะตั‚ะต ัƒะทะฝะฐั‚ัŒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะธ **SQLModel**, ั‚ะฐะผ ะตัั‚ัŒ ะฑะพะปะตะต ะฟะพะดั€ะพะฑะฝะพะต ะผะธะฝะธ-ั€ัƒะบะพะฒะพะดัั‚ะฒะพ ะฟะพ ะธัะฟะพะปัŒะทะพะฒะฐะฝะธัŽ SQLModel ั **FastAPI**. ๐Ÿš€ diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md index f40cfe9b04..3b0cab8313 100644 --- a/docs/ru/docs/tutorial/static-files.md +++ b/docs/ru/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * ะ˜ะผะฟะพั€ั‚ะธั€ัƒะนั‚ะต `StaticFiles`. * "ะŸั€ะธะผะพะฝั‚ะธั€ัƒะนั‚ะต" ัะบะทะตะผะฟะปัั€ `StaticFiles()` ะบ ะพะฟั€ะตะดะตะปั‘ะฝะฝะพะผัƒ ะฟัƒั‚ะธ. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | ะขะตั…ะฝะธั‡ะตัะบะธะต ะดะตั‚ะฐะปะธ diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md index ab58429c51..6dd2fe579a 100644 --- a/docs/ru/docs/tutorial/testing.md +++ b/docs/ru/docs/tutorial/testing.md @@ -30,7 +30,7 @@ $ pip install httpx ะะฐะฟะธัˆะธั‚ะต ะฟั€ะพัั‚ะพะต ัƒั‚ะฒะตั€ะถะดะตะฝะธะต ั `assert` ะดะฐะฑั‹ ะฟั€ะพะฒะตั€ะธั‚ัŒ ะธัั‚ะธะฝะฝะพัั‚ัŒ Python-ะฒั‹ั€ะฐะถะตะฝะธั (ัั‚ะพ ั‚ะพะถะต ัั‚ะฐะฝะดะฐั€ั‚ `pytest`). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -76,7 +76,7 @@ $ pip install httpx ะ’ ั„ะฐะนะปะต `main.py` ะฝะฐั…ะพะดะธั‚ัั ะ’ะฐัˆะต ะฟั€ะธะปะพะถะตะฝะธะต **FastAPI**: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### ะคะฐะนะป ั‚ะตัั‚ะพะฒ { #testing-file } @@ -92,7 +92,7 @@ $ pip install httpx ะขะฐะบ ะบะฐะบ ะพะฑะฐ ั„ะฐะนะปะฐ ะฝะฐั…ะพะดัั‚ัั ะฒ ะพะดะฝะพะน ะดะธั€ะตะบั‚ะพั€ะธะธ, ะดะปั ะธะผะฟะพั€ั‚ะฐ ะพะฑัŠะตะบั‚ะฐ ะฟั€ะธะปะพะถะตะฝะธั ะธะท ั„ะฐะนะปะฐ `main` ะฒ ั„ะฐะนะป `test_main` ะ’ั‹ ะผะพะถะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะพั‚ะฝะพัะธั‚ะตะปัŒะฝั‹ะน ะธะผะฟะพั€ั‚: -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...ะธ ะฟะธัะฐั‚ัŒ ะดะฐะปัŒัˆะต ั‚ะตัั‚ั‹, ะบะฐะบ ะธ ั€ะฐะฝัŒัˆะต. @@ -119,7 +119,7 @@ $ pip install httpx ะ•ั‰ั‘ ะตัั‚ัŒ ะพะฟะตั€ะฐั†ะธั `POST`, ะธ ะพะฝะฐ ะผะพะถะตั‚ ะฒะตั€ะฝัƒั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ะพัˆะธะฑะพะบ. -ะžะฑะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ั‚ั€ะตะฑัƒัŽั‚ ะฝะฐะปะธั‡ะธั ะฒ ะทะฐะฟั€ะพัะต ะทะฐะณะพะปะพะฒะบะฐ `X-Token`. +ะžะฑะต *ะพะฟะตั€ะฐั†ะธะธ ะฟัƒั‚ะธ* ั‚ั€ะตะฑัƒัŽั‚ ะฝะฐะปะธั‡ะธั ะฒ ะทะฐะฟั€ะพัะต HTTP-ะทะฐะณะพะปะพะฒะบะฐ `X-Token`. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -139,7 +139,7 @@ $ pip install httpx * ะŸะตั€ะตะดะฐั‘ั‚ะต *path*-ะฟะฐั€ะฐะผะตั‚ั€ั‹ ะธะปะธ *query*-ะฟะฐั€ะฐะผะตั‚ั€ั‹, ะฒะฟะธัะฐะฒ ะธั… ะฝะตะฟะพัั€ะตะดัั‚ะฒะตะฝะฝะพ ะฒ ัั‚ั€ะพะบัƒ URL. * ะŸะตั€ะตะดะฐั‘ั‚ะต JSON ะฒ ั‚ะตะปะต ะทะฐะฟั€ะพัะฐ, ะฟะตั€ะตะดะฐะฒ Python-ะพะฑัŠะตะบั‚ (ะฝะฐะฟั€ะธะผะตั€: `dict`) ั‡ะตั€ะตะท ะธะผะตะฝะพะฒะฐะฝะฝั‹ะน ะฟะฐั€ะฐะผะตั‚ั€ `json`. * ะ•ัะปะธ ะถะต ะ’ะฐะผ ะฝะตะพะฑั…ะพะดะธะผะพ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ *ั„ะพั€ะผัƒ ั ะดะฐะฝะฝั‹ะผะธ* ะฒะผะตัั‚ะพ JSON, ั‚ะพ ะธัะฟะพะปัŒะทัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `data` ะฒะผะตัั‚ะพ `json`. -* ะ”ะปั ะฟะตั€ะตะดะฐั‡ะธ *ะทะฐะณะพะปะพะฒะบะพะฒ*, ะฟะตั€ะตะดะฐะนั‚ะต ะพะฑัŠะตะบั‚ `dict` ั‡ะตั€ะตะท ะฟะฐั€ะฐะผะตั‚ั€ `headers`. +* ะ”ะปั ะฟะตั€ะตะดะฐั‡ะธ *HTTP-ะทะฐะณะพะปะพะฒะบะพะฒ*, ะฟะตั€ะตะดะฐะนั‚ะต ะพะฑัŠะตะบั‚ `dict` ั‡ะตั€ะตะท ะฟะฐั€ะฐะผะตั‚ั€ `headers`. * ะ”ะปั ะฟะตั€ะตะดะฐั‡ะธ *cookies* ั‚ะฐะบะถะต ะฟะตั€ะตะดะฐะนั‚ะต `dict`, ะฝะพ ั‡ะตั€ะตะท ะฟะฐั€ะฐะผะตั‚ั€ `cookies`. ะ”ะปั ะฟะพะปัƒั‡ะตะฝะธั ะดะพะฟะพะปะฝะธั‚ะตะปัŒะฝะพะน ะธะฝั„ะพั€ะผะฐั†ะธะธ ะพ ะฟะตั€ะตะดะฐั‡ะต ะดะฐะฝะฝั‹ั… ะฝะฐ ะฑัะบะตะฝะด ั ะฟะพะผะพั‰ัŒัŽ `httpx` ะธะปะธ `TestClient` ะพะทะฝะฐะบะพะผัŒั‚ะตััŒ ั ะดะพะบัƒะผะตะฝั‚ะฐั†ะธะตะน HTTPX. diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md index 43136298a3..f931cc3c82 100644 --- a/docs/ru/docs/virtual-environments.md +++ b/docs/ru/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## ะกะพะทะดะฐะฝะธะต ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะณะพ ะพะบั€ัƒะถะตะฝะธั { #create-a-virtual-environment } -ะšะพะณะดะฐ ะฒั‹ ะฝะฐั‡ะธะฝะฐะตั‚ะต ั€ะฐะฑะพั‚ะฐั‚ัŒ ะฝะฐะด Pythonโ€‘ะฟั€ะพะตะบั‚ะพะผ **ะฒะฟะตั€ะฒั‹ะต**, ัะพะทะดะฐะนั‚ะต ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะต ะพะบั€ัƒะถะตะฝะธะต **ะฒะฝัƒั‚ั€ะธ ะฒะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ**. +ะšะพะณะดะฐ ะฒั‹ ะฝะฐั‡ะธะฝะฐะตั‚ะต ั€ะฐะฑะพั‚ะฐั‚ัŒ ะฝะฐะด Pythonโ€‘ะฟั€ะพะตะบั‚ะพะผ **ะฒะฟะตั€ะฒั‹ะต**, ัะพะทะดะฐะนั‚ะต ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะต ะพะบั€ัƒะถะตะฝะธะต **ะฒะฝัƒั‚ั€ะธ ะฒะฐัˆะตะณะพ ะฟั€ะพะตะบั‚ะฐ**. /// tip | ะŸะพะดัะบะฐะทะบะฐ @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate ะšะฐะถะดั‹ะน ั€ะฐะท, ะบะพะณะดะฐ ะฒั‹ ัƒัั‚ะฐะฝะฐะฒะปะธะฒะฐะตั‚ะต **ะฝะพะฒั‹ะน ะฟะฐะบะตั‚** ะฒ ัั‚ะพ ะพะบั€ัƒะถะตะฝะธะต, **ะฐะบั‚ะธะฒะธั€ัƒะนั‚ะต** ะพะบั€ัƒะถะตะฝะธะต ัะฝะพะฒะฐ. -ะญั‚ะพ ะณะฐั€ะฐะฝั‚ะธั€ัƒะตั‚, ั‡ั‚ะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต **ะฟั€ะพะณั€ะฐะผะผัƒ ั‚ะตั€ะผะธะฝะฐะปะฐ (CLI)**, ัƒัั‚ะฐะฝะพะฒะปะตะฝะฝัƒัŽ ัั‚ะธะผ ะฟะฐะบะตั‚ะพะผ, ะฒั‹ ะฑัƒะดะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธะผะตะฝะฝะพ ั‚ัƒ, ั‡ั‚ะพ ะธะท ะฒะฐัˆะตะณะพ ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะณะพ ะพะบั€ัƒะถะตะฝะธั, ะฐ ะฝะต ะบะฐะบัƒัŽโ€‘ั‚ะพ ะณะปะพะฑะฐะปัŒะฝะพ ัƒัั‚ะฐะฝะพะฒะปะตะฝะฝัƒัŽ, ะฒะพะทะผะพะถะฝะพ ะดั€ัƒะณะพะน ะฒะตั€ัะธะธ, ั‡ะตะผ ะฒะฐะผ ะฝัƒะถะฝะฐ. +ะญั‚ะพ ะณะฐั€ะฐะฝั‚ะธั€ัƒะตั‚, ั‡ั‚ะพ ะตัะปะธ ะฒั‹ ะธัะฟะพะปัŒะทัƒะตั‚ะต **ะฟั€ะพะณั€ะฐะผะผัƒ ั‚ะตั€ะผะธะฝะฐะปะฐ (CLI)**, ัƒัั‚ะฐะฝะพะฒะปะตะฝะฝัƒัŽ ัั‚ะธะผ ะฟะฐะบะตั‚ะพะผ, ะฒั‹ ะฑัƒะดะตั‚ะต ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒ ะธะผะตะฝะฝะพ ั‚ัƒ, ั‡ั‚ะพ ะธะท ะฒะฐัˆะตะณะพ ะฒะธั€ั‚ัƒะฐะปัŒะฝะพะณะพ ะพะบั€ัƒะถะตะฝะธั, ะฐ ะฝะต ะบะฐะบัƒัŽโ€‘ั‚ะพ ะณะปะพะฑะฐะปัŒะฝะพ ัƒัั‚ะฐะฝะพะฒะปะตะฝะฝัƒัŽ, ะฒะพะทะผะพะถะฝะพ ะดั€ัƒะณะพะน ะฒะตั€ัะธะธ, ั‡ะตะผ ะฒะฐะผ ะฝัƒะถะฝะฐ. /// From 6fa573ce0bc16fe445f93db413d20146dd9ff35d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 12 Feb 2026 19:58:08 +0000 Subject: [PATCH 218/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d8bc3a26f6..dfa4eb4897 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * ๐Ÿ“ Update docs for JWT to prevent timing attacks. PR [#14908](https://github.com/fastapi/fastapi/pull/14908) by [@tiangolo](https://github.com/tiangolo). +### Translations + +* ๐ŸŒ Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.129.0 ### Breaking Changes From db328270aaf74bc512dca9e02dc463fab92ccd97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 07:56:30 +0100 Subject: [PATCH 219/367] =?UTF-8?q?=E2=AC=86=20Bump=20pillow=20from=2012.1?= =?UTF-8?q?.0=20to=2012.1.1=20(#14899)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.1.0 to 12.1.1. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/12.1.0...12.1.1) --- updated-dependencies: - dependency-name: pillow dependency-version: 12.1.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 188 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/uv.lock b/uv.lock index 736b0e1457..78026fa67f 100644 --- a/uv.lock +++ b/uv.lock @@ -3511,100 +3511,100 @@ wheels = [ [[package]] name = "pillow" -version = "12.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/41/f73d92b6b883a579e79600d391f2e21cb0df767b2714ecbd2952315dfeef/pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd", size = 5304089, upload-time = "2026-01-02T09:10:24.953Z" }, - { url = "https://files.pythonhosted.org/packages/94/55/7aca2891560188656e4a91ed9adba305e914a4496800da6b5c0a15f09edf/pillow-12.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cad302dc10fac357d3467a74a9561c90609768a6f73a1923b0fd851b6486f8b0", size = 4657815, upload-time = "2026-01-02T09:10:27.063Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d2/b28221abaa7b4c40b7dba948f0f6a708bd7342c4d47ce342f0ea39643974/pillow-12.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a40905599d8079e09f25027423aed94f2823adaf2868940de991e53a449e14a8", size = 6222593, upload-time = "2026-01-02T09:10:29.115Z" }, - { url = "https://files.pythonhosted.org/packages/71/b8/7a61fb234df6a9b0b479f69e66901209d89ff72a435b49933f9122f94cac/pillow-12.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92a7fe4225365c5e3a8e598982269c6d6698d3e783b3b1ae979e7819f9cd55c1", size = 8027579, upload-time = "2026-01-02T09:10:31.182Z" }, - { url = "https://files.pythonhosted.org/packages/ea/51/55c751a57cc524a15a0e3db20e5cde517582359508d62305a627e77fd295/pillow-12.1.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f10c98f49227ed8383d28174ee95155a675c4ed7f85e2e573b04414f7e371bda", size = 6335760, upload-time = "2026-01-02T09:10:33.02Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7c/60e3e6f5e5891a1a06b4c910f742ac862377a6fe842f7184df4a274ce7bf/pillow-12.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8637e29d13f478bc4f153d8daa9ffb16455f0a6cb287da1b432fdad2bfbd66c7", size = 7027127, upload-time = "2026-01-02T09:10:35.009Z" }, - { url = "https://files.pythonhosted.org/packages/06/37/49d47266ba50b00c27ba63a7c898f1bb41a29627ced8c09e25f19ebec0ff/pillow-12.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:21e686a21078b0f9cb8c8a961d99e6a4ddb88e0fc5ea6e130172ddddc2e5221a", size = 6449896, upload-time = "2026-01-02T09:10:36.793Z" }, - { url = "https://files.pythonhosted.org/packages/f9/e5/67fd87d2913902462cd9b79c6211c25bfe95fcf5783d06e1367d6d9a741f/pillow-12.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2415373395a831f53933c23ce051021e79c8cd7979822d8cc478547a3f4da8ef", size = 7151345, upload-time = "2026-01-02T09:10:39.064Z" }, - { url = "https://files.pythonhosted.org/packages/bd/15/f8c7abf82af68b29f50d77c227e7a1f87ce02fdc66ded9bf603bc3b41180/pillow-12.1.0-cp310-cp310-win32.whl", hash = "sha256:e75d3dba8fc1ddfec0cd752108f93b83b4f8d6ab40e524a95d35f016b9683b09", size = 6325568, upload-time = "2026-01-02T09:10:41.035Z" }, - { url = "https://files.pythonhosted.org/packages/d4/24/7d1c0e160b6b5ac2605ef7d8be537e28753c0db5363d035948073f5513d7/pillow-12.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:64efdf00c09e31efd754448a383ea241f55a994fd079866b92d2bbff598aad91", size = 7032367, upload-time = "2026-01-02T09:10:43.09Z" }, - { url = "https://files.pythonhosted.org/packages/f4/03/41c038f0d7a06099254c60f618d0ec7be11e79620fc23b8e85e5b31d9a44/pillow-12.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f188028b5af6b8fb2e9a76ac0f841a575bd1bd396e46ef0840d9b88a48fdbcea", size = 2452345, upload-time = "2026-01-02T09:10:44.795Z" }, - { url = "https://files.pythonhosted.org/packages/43/c4/bf8328039de6cc22182c3ef007a2abfbbdab153661c0a9aa78af8d706391/pillow-12.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:a83e0850cb8f5ac975291ebfc4170ba481f41a28065277f7f735c202cd8e0af3", size = 5304057, upload-time = "2026-01-02T09:10:46.627Z" }, - { url = "https://files.pythonhosted.org/packages/43/06/7264c0597e676104cc22ca73ee48f752767cd4b1fe084662620b17e10120/pillow-12.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b6e53e82ec2db0717eabb276aa56cf4e500c9a7cec2c2e189b55c24f65a3e8c0", size = 4657811, upload-time = "2026-01-02T09:10:49.548Z" }, - { url = "https://files.pythonhosted.org/packages/72/64/f9189e44474610daf83da31145fa56710b627b5c4c0b9c235e34058f6b31/pillow-12.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40a8e3b9e8773876d6e30daed22f016509e3987bab61b3b7fe309d7019a87451", size = 6232243, upload-time = "2026-01-02T09:10:51.62Z" }, - { url = "https://files.pythonhosted.org/packages/ef/30/0df458009be6a4caca4ca2c52975e6275c387d4e5c95544e34138b41dc86/pillow-12.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800429ac32c9b72909c671aaf17ecd13110f823ddb7db4dfef412a5587c2c24e", size = 8037872, upload-time = "2026-01-02T09:10:53.446Z" }, - { url = "https://files.pythonhosted.org/packages/e4/86/95845d4eda4f4f9557e25381d70876aa213560243ac1a6d619c46caaedd9/pillow-12.1.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b022eaaf709541b391ee069f0022ee5b36c709df71986e3f7be312e46f42c84", size = 6345398, upload-time = "2026-01-02T09:10:55.426Z" }, - { url = "https://files.pythonhosted.org/packages/5c/1f/8e66ab9be3aaf1435bc03edd1ebdf58ffcd17f7349c1d970cafe87af27d9/pillow-12.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f345e7bc9d7f368887c712aa5054558bad44d2a301ddf9248599f4161abc7c0", size = 7034667, upload-time = "2026-01-02T09:10:57.11Z" }, - { url = "https://files.pythonhosted.org/packages/f9/f6/683b83cb9b1db1fb52b87951b1c0b99bdcfceaa75febf11406c19f82cb5e/pillow-12.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d70347c8a5b7ccd803ec0c85c8709f036e6348f1e6a5bf048ecd9c64d3550b8b", size = 6458743, upload-time = "2026-01-02T09:10:59.331Z" }, - { url = "https://files.pythonhosted.org/packages/9a/7d/de833d63622538c1d58ce5395e7c6cb7e7dce80decdd8bde4a484e095d9f/pillow-12.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fcc52d86ce7a34fd17cb04e87cfdb164648a3662a6f20565910a99653d66c18", size = 7159342, upload-time = "2026-01-02T09:11:01.82Z" }, - { url = "https://files.pythonhosted.org/packages/8c/40/50d86571c9e5868c42b81fe7da0c76ca26373f3b95a8dd675425f4a92ec1/pillow-12.1.0-cp311-cp311-win32.whl", hash = "sha256:3ffaa2f0659e2f740473bcf03c702c39a8d4b2b7ffc629052028764324842c64", size = 6328655, upload-time = "2026-01-02T09:11:04.556Z" }, - { url = "https://files.pythonhosted.org/packages/6c/af/b1d7e301c4cd26cd45d4af884d9ee9b6fab893b0ad2450d4746d74a6968c/pillow-12.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:806f3987ffe10e867bab0ddad45df1148a2b98221798457fa097ad85d6e8bc75", size = 7031469, upload-time = "2026-01-02T09:11:06.538Z" }, - { url = "https://files.pythonhosted.org/packages/48/36/d5716586d887fb2a810a4a61518a327a1e21c8b7134c89283af272efe84b/pillow-12.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9f5fefaca968e700ad1a4a9de98bf0869a94e397fe3524c4c9450c1445252304", size = 2452515, upload-time = "2026-01-02T09:11:08.226Z" }, - { url = "https://files.pythonhosted.org/packages/20/31/dc53fe21a2f2996e1b7d92bf671cdb157079385183ef7c1ae08b485db510/pillow-12.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a332ac4ccb84b6dde65dbace8431f3af08874bf9770719d32a635c4ef411b18b", size = 5262642, upload-time = "2026-01-02T09:11:10.138Z" }, - { url = "https://files.pythonhosted.org/packages/ab/c1/10e45ac9cc79419cedf5121b42dcca5a50ad2b601fa080f58c22fb27626e/pillow-12.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:907bfa8a9cb790748a9aa4513e37c88c59660da3bcfffbd24a7d9e6abf224551", size = 4657464, upload-time = "2026-01-02T09:11:12.319Z" }, - { url = "https://files.pythonhosted.org/packages/ad/26/7b82c0ab7ef40ebede7a97c72d473bda5950f609f8e0c77b04af574a0ddb/pillow-12.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efdc140e7b63b8f739d09a99033aa430accce485ff78e6d311973a67b6bf3208", size = 6234878, upload-time = "2026-01-02T09:11:14.096Z" }, - { url = "https://files.pythonhosted.org/packages/76/25/27abc9792615b5e886ca9411ba6637b675f1b77af3104710ac7353fe5605/pillow-12.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bef9768cab184e7ae6e559c032e95ba8d07b3023c289f79a2bd36e8bf85605a5", size = 8044868, upload-time = "2026-01-02T09:11:15.903Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ea/f200a4c36d836100e7bc738fc48cd963d3ba6372ebc8298a889e0cfc3359/pillow-12.1.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:742aea052cf5ab5034a53c3846165bc3ce88d7c38e954120db0ab867ca242661", size = 6349468, upload-time = "2026-01-02T09:11:17.631Z" }, - { url = "https://files.pythonhosted.org/packages/11/8f/48d0b77ab2200374c66d344459b8958c86693be99526450e7aee714e03e4/pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6dfc2af5b082b635af6e08e0d1f9f1c4e04d17d4e2ca0ef96131e85eda6eb17", size = 7041518, upload-time = "2026-01-02T09:11:19.389Z" }, - { url = "https://files.pythonhosted.org/packages/1d/23/c281182eb986b5d31f0a76d2a2c8cd41722d6fb8ed07521e802f9bba52de/pillow-12.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:609e89d9f90b581c8d16358c9087df76024cf058fa693dd3e1e1620823f39670", size = 6462829, upload-time = "2026-01-02T09:11:21.28Z" }, - { url = "https://files.pythonhosted.org/packages/25/ef/7018273e0faac099d7b00982abdcc39142ae6f3bd9ceb06de09779c4a9d6/pillow-12.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43b4899cfd091a9693a1278c4982f3e50f7fb7cff5153b05174b4afc9593b616", size = 7166756, upload-time = "2026-01-02T09:11:23.559Z" }, - { url = "https://files.pythonhosted.org/packages/8f/c8/993d4b7ab2e341fe02ceef9576afcf5830cdec640be2ac5bee1820d693d4/pillow-12.1.0-cp312-cp312-win32.whl", hash = "sha256:aa0c9cc0b82b14766a99fbe6084409972266e82f459821cd26997a488a7261a7", size = 6328770, upload-time = "2026-01-02T09:11:25.661Z" }, - { url = "https://files.pythonhosted.org/packages/a7/87/90b358775a3f02765d87655237229ba64a997b87efa8ccaca7dd3e36e7a7/pillow-12.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d70534cea9e7966169ad29a903b99fc507e932069a881d0965a1a84bb57f6c6d", size = 7033406, upload-time = "2026-01-02T09:11:27.474Z" }, - { url = "https://files.pythonhosted.org/packages/5d/cf/881b457eccacac9e5b2ddd97d5071fb6d668307c57cbf4e3b5278e06e536/pillow-12.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:65b80c1ee7e14a87d6a068dd3b0aea268ffcabfe0498d38661b00c5b4b22e74c", size = 2452612, upload-time = "2026-01-02T09:11:29.309Z" }, - { url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" }, - { url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" }, - { url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" }, - { url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" }, - { url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" }, - { url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" }, - { url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" }, - { url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" }, - { url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" }, - { url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" }, - { url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" }, - { url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" }, - { url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" }, - { url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" }, - { url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" }, - { url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" }, - { url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" }, - { url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" }, - { url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" }, - { url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" }, - { url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" }, - { url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" }, - { url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" }, - { url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" }, - { url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" }, - { url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" }, - { url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" }, - { url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" }, - { url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" }, - { url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" }, - { url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" }, - { url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" }, - { url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" }, - { url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" }, - { url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" }, - { url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" }, - { url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" }, - { url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" }, - { url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" }, - { url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" }, - { url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" }, - { url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" }, - { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/8b/bc/224b1d98cffd7164b14707c91aac83c07b047fbd8f58eba4066a3e53746a/pillow-12.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ca94b6aac0d7af2a10ba08c0f888b3d5114439b6b3ef39968378723622fed377", size = 5228605, upload-time = "2026-01-02T09:13:14.084Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ca/49ca7769c4550107de049ed85208240ba0f330b3f2e316f24534795702ce/pillow-12.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:351889afef0f485b84078ea40fe33727a0492b9af3904661b0abbafee0355b72", size = 4622245, upload-time = "2026-01-02T09:13:15.964Z" }, - { url = "https://files.pythonhosted.org/packages/73/48/fac807ce82e5955bcc2718642b94b1bd22a82a6d452aea31cbb678cddf12/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb0984b30e973f7e2884362b7d23d0a348c7143ee559f38ef3eaab640144204c", size = 5247593, upload-time = "2026-01-02T09:13:17.913Z" }, - { url = "https://files.pythonhosted.org/packages/d2/95/3e0742fe358c4664aed4fd05d5f5373dcdad0b27af52aa0972568541e3f4/pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84cabc7095dd535ca934d57e9ce2a72ffd216e435a84acb06b2277b1de2689bd", size = 6989008, upload-time = "2026-01-02T09:13:20.083Z" }, - { url = "https://files.pythonhosted.org/packages/5a/74/fe2ac378e4e202e56d50540d92e1ef4ff34ed687f3c60f6a121bcf99437e/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53d8b764726d3af1a138dd353116f774e3862ec7e3794e0c8781e30db0f35dfc", size = 5313824, upload-time = "2026-01-02T09:13:22.405Z" }, - { url = "https://files.pythonhosted.org/packages/f3/77/2a60dee1adee4e2655ac328dd05c02a955c1cd683b9f1b82ec3feb44727c/pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5da841d81b1a05ef940a8567da92decaa15bc4d7dedb540a8c219ad83d91808a", size = 5963278, upload-time = "2026-01-02T09:13:24.706Z" }, - { url = "https://files.pythonhosted.org/packages/2d/71/64e9b1c7f04ae0027f788a248e6297d7fcc29571371fe7d45495a78172c0/pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19", size = 7029809, upload-time = "2026-01-02T09:13:26.541Z" }, +version = "12.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/42/5c74462b4fd957fcd7b13b04fb3205ff8349236ea74c7c375766d6c82288/pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4", size = 46980264, upload-time = "2026-02-11T04:23:07.146Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/30/5bd3d794762481f8c8ae9c80e7b76ecea73b916959eb587521358ef0b2f9/pillow-12.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f1625b72740fdda5d77b4def688eb8fd6490975d06b909fd19f13f391e077e0", size = 5304099, upload-time = "2026-02-11T04:20:06.13Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c1/aab9e8f3eeb4490180e357955e15c2ef74b31f64790ff356c06fb6cf6d84/pillow-12.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:178aa072084bd88ec759052feca8e56cbb14a60b39322b99a049e58090479713", size = 4657880, upload-time = "2026-02-11T04:20:09.291Z" }, + { url = "https://files.pythonhosted.org/packages/f1/0a/9879e30d56815ad529d3985aeff5af4964202425c27261a6ada10f7cbf53/pillow-12.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b66e95d05ba806247aaa1561f080abc7975daf715c30780ff92a20e4ec546e1b", size = 6222587, upload-time = "2026-02-11T04:20:10.82Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5f/a1b72ff7139e4f89014e8d451442c74a774d5c43cd938fb0a9f878576b37/pillow-12.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89c7e895002bbe49cdc5426150377cbbc04767d7547ed145473f496dfa40408b", size = 8027678, upload-time = "2026-02-11T04:20:12.455Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c2/c7cb187dac79a3d22c3ebeae727abee01e077c8c7d930791dc592f335153/pillow-12.1.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a5cbdcddad0af3da87cb16b60d23648bc3b51967eb07223e9fed77a82b457c4", size = 6335777, upload-time = "2026-02-11T04:20:14.441Z" }, + { url = "https://files.pythonhosted.org/packages/0c/7b/f9b09a7804ec7336effb96c26d37c29d27225783dc1501b7d62dcef6ae25/pillow-12.1.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f51079765661884a486727f0729d29054242f74b46186026582b4e4769918e4", size = 7027140, upload-time = "2026-02-11T04:20:16.387Z" }, + { url = "https://files.pythonhosted.org/packages/98/b2/2fa3c391550bd421b10849d1a2144c44abcd966daadd2f7c12e19ea988c4/pillow-12.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:99c1506ea77c11531d75e3a412832a13a71c7ebc8192ab9e4b2e355555920e3e", size = 6449855, upload-time = "2026-02-11T04:20:18.554Z" }, + { url = "https://files.pythonhosted.org/packages/96/ff/9caf4b5b950c669263c39e96c78c0d74a342c71c4f43fd031bb5cb7ceac9/pillow-12.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36341d06738a9f66c8287cf8b876d24b18db9bd8740fa0672c74e259ad408cff", size = 7151329, upload-time = "2026-02-11T04:20:20.646Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f8/4b24841f582704da675ca535935bccb32b00a6da1226820845fac4a71136/pillow-12.1.1-cp310-cp310-win32.whl", hash = "sha256:6c52f062424c523d6c4db85518774cc3d50f5539dd6eed32b8f6229b26f24d40", size = 6325574, upload-time = "2026-02-11T04:20:22.43Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f9/9f6b01c0881d7036063aa6612ef04c0e2cad96be21325a1e92d0203f8e91/pillow-12.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6008de247150668a705a6338156efb92334113421ceecf7438a12c9a12dab23", size = 7032347, upload-time = "2026-02-11T04:20:23.932Z" }, + { url = "https://files.pythonhosted.org/packages/79/13/c7922edded3dcdaf10c59297540b72785620abc0538872c819915746757d/pillow-12.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:1a9b0ee305220b392e1124a764ee4265bd063e54a751a6b62eff69992f457fa9", size = 2453457, upload-time = "2026-02-11T04:20:25.392Z" }, + { url = "https://files.pythonhosted.org/packages/2b/46/5da1ec4a5171ee7bf1a0efa064aba70ba3d6e0788ce3f5acd1375d23c8c0/pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32", size = 5304084, upload-time = "2026-02-11T04:20:27.501Z" }, + { url = "https://files.pythonhosted.org/packages/78/93/a29e9bc02d1cf557a834da780ceccd54e02421627200696fcf805ebdc3fb/pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38", size = 4657866, upload-time = "2026-02-11T04:20:29.827Z" }, + { url = "https://files.pythonhosted.org/packages/13/84/583a4558d492a179d31e4aae32eadce94b9acf49c0337c4ce0b70e0a01f2/pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5", size = 6232148, upload-time = "2026-02-11T04:20:31.329Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e2/53c43334bbbb2d3b938978532fbda8e62bb6e0b23a26ce8592f36bcc4987/pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090", size = 8038007, upload-time = "2026-02-11T04:20:34.225Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/3d0e79c8a9d58150dd98e199d7c1c56861027f3829a3a60b3c2784190180/pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af", size = 6345418, upload-time = "2026-02-11T04:20:35.858Z" }, + { url = "https://files.pythonhosted.org/packages/a2/c8/46dfeac5825e600579157eea177be43e2f7ff4a99da9d0d0a49533509ac5/pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b", size = 7034590, upload-time = "2026-02-11T04:20:37.91Z" }, + { url = "https://files.pythonhosted.org/packages/af/bf/e6f65d3db8a8bbfeaf9e13cc0417813f6319863a73de934f14b2229ada18/pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5", size = 6458655, upload-time = "2026-02-11T04:20:39.496Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c2/66091f3f34a25894ca129362e510b956ef26f8fb67a0e6417bc5744e56f1/pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d", size = 7159286, upload-time = "2026-02-11T04:20:41.139Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5a/24bc8eb526a22f957d0cec6243146744966d40857e3d8deb68f7902ca6c1/pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c", size = 6328663, upload-time = "2026-02-11T04:20:43.184Z" }, + { url = "https://files.pythonhosted.org/packages/31/03/bef822e4f2d8f9d7448c133d0a18185d3cce3e70472774fffefe8b0ed562/pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563", size = 7031448, upload-time = "2026-02-11T04:20:44.696Z" }, + { url = "https://files.pythonhosted.org/packages/49/70/f76296f53610bd17b2e7d31728b8b7825e3ac3b5b3688b51f52eab7c0818/pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80", size = 2453651, upload-time = "2026-02-11T04:20:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/d3/8df65da0d4df36b094351dce696f2989bec731d4f10e743b1c5f4da4d3bf/pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052", size = 5262803, upload-time = "2026-02-11T04:20:47.653Z" }, + { url = "https://files.pythonhosted.org/packages/d6/71/5026395b290ff404b836e636f51d7297e6c83beceaa87c592718747e670f/pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984", size = 4657601, upload-time = "2026-02-11T04:20:49.328Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2e/1001613d941c67442f745aff0f7cc66dd8df9a9c084eb497e6a543ee6f7e/pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79", size = 6234995, upload-time = "2026-02-11T04:20:51.032Z" }, + { url = "https://files.pythonhosted.org/packages/07/26/246ab11455b2549b9233dbd44d358d033a2f780fa9007b61a913c5b2d24e/pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293", size = 8045012, upload-time = "2026-02-11T04:20:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/b2/8b/07587069c27be7535ac1fe33874e32de118fbd34e2a73b7f83436a88368c/pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397", size = 6349638, upload-time = "2026-02-11T04:20:54.444Z" }, + { url = "https://files.pythonhosted.org/packages/ff/79/6df7b2ee763d619cda2fb4fea498e5f79d984dae304d45a8999b80d6cf5c/pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0", size = 7041540, upload-time = "2026-02-11T04:20:55.97Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5e/2ba19e7e7236d7529f4d873bdaf317a318896bac289abebd4bb00ef247f0/pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3", size = 6462613, upload-time = "2026-02-11T04:20:57.542Z" }, + { url = "https://files.pythonhosted.org/packages/03/03/31216ec124bb5c3dacd74ce8efff4cc7f52643653bad4825f8f08c697743/pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35", size = 7166745, upload-time = "2026-02-11T04:20:59.196Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e7/7c4552d80052337eb28653b617eafdef39adfb137c49dd7e831b8dc13bc5/pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a", size = 6328823, upload-time = "2026-02-11T04:21:01.385Z" }, + { url = "https://files.pythonhosted.org/packages/3d/17/688626d192d7261bbbf98846fc98995726bddc2c945344b65bec3a29d731/pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6", size = 7033367, upload-time = "2026-02-11T04:21:03.536Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fe/a0ef1f73f939b0eca03ee2c108d0043a87468664770612602c63266a43c4/pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523", size = 2453811, upload-time = "2026-02-11T04:21:05.116Z" }, + { url = "https://files.pythonhosted.org/packages/d5/11/6db24d4bd7685583caeae54b7009584e38da3c3d4488ed4cd25b439de486/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e", size = 4062689, upload-time = "2026-02-11T04:21:06.804Z" }, + { url = "https://files.pythonhosted.org/packages/33/c0/ce6d3b1fe190f0021203e0d9b5b99e57843e345f15f9ef22fcd43842fd21/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9", size = 4138535, upload-time = "2026-02-11T04:21:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c6/d5eb6a4fb32a3f9c21a8c7613ec706534ea1cf9f4b3663e99f0d83f6fca8/pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6", size = 3601364, upload-time = "2026-02-11T04:21:10.194Z" }, + { url = "https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60", size = 5262561, upload-time = "2026-02-11T04:21:11.742Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2", size = 4657460, upload-time = "2026-02-11T04:21:13.786Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/f1a4ea9a895b5732152789326202a82464d5254759fbacae4deea3069334/pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850", size = 6232698, upload-time = "2026-02-11T04:21:15.949Z" }, + { url = "https://files.pythonhosted.org/packages/95/f4/86f51b8745070daf21fd2e5b1fe0eb35d4db9ca26e6d58366562fb56a743/pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289", size = 8041706, upload-time = "2026-02-11T04:21:17.723Z" }, + { url = "https://files.pythonhosted.org/packages/29/9b/d6ecd956bb1266dd1045e995cce9b8d77759e740953a1c9aad9502a0461e/pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e", size = 6346621, upload-time = "2026-02-11T04:21:19.547Z" }, + { url = "https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717", size = 7038069, upload-time = "2026-02-11T04:21:21.378Z" }, + { url = "https://files.pythonhosted.org/packages/94/0e/58cb1a6bc48f746bc4cb3adb8cabff73e2742c92b3bf7a220b7cf69b9177/pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a", size = 6460040, upload-time = "2026-02-11T04:21:23.148Z" }, + { url = "https://files.pythonhosted.org/packages/6c/57/9045cb3ff11eeb6c1adce3b2d60d7d299d7b273a2e6c8381a524abfdc474/pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029", size = 7164523, upload-time = "2026-02-11T04:21:25.01Z" }, + { url = "https://files.pythonhosted.org/packages/73/f2/9be9cb99f2175f0d4dbadd6616ce1bf068ee54a28277ea1bf1fbf729c250/pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b", size = 6332552, upload-time = "2026-02-11T04:21:27.238Z" }, + { url = "https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1", size = 7040108, upload-time = "2026-02-11T04:21:29.462Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7d/fc09634e2aabdd0feabaff4a32f4a7d97789223e7c2042fd805ea4b4d2c2/pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a", size = 2453712, upload-time = "2026-02-11T04:21:31.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/b9d62794fc8a0dd14c1943df68347badbd5511103e0d04c035ffe5cf2255/pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da", size = 5264880, upload-time = "2026-02-11T04:21:32.865Z" }, + { url = "https://files.pythonhosted.org/packages/26/9d/e03d857d1347fa5ed9247e123fcd2a97b6220e15e9cb73ca0a8d91702c6e/pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc", size = 4660616, upload-time = "2026-02-11T04:21:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ec/8a6d22afd02570d30954e043f09c32772bfe143ba9285e2fdb11284952cd/pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c", size = 6269008, upload-time = "2026-02-11T04:21:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/3d/1d/6d875422c9f28a4a361f495a5f68d9de4a66941dc2c619103ca335fa6446/pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8", size = 8073226, upload-time = "2026-02-11T04:21:38.585Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cd/134b0b6ee5eda6dc09e25e24b40fdafe11a520bc725c1d0bbaa5e00bf95b/pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20", size = 6380136, upload-time = "2026-02-11T04:21:40.562Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a9/7628f013f18f001c1b98d8fffe3452f306a70dc6aba7d931019e0492f45e/pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13", size = 7067129, upload-time = "2026-02-11T04:21:42.521Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f8/66ab30a2193b277785601e82ee2d49f68ea575d9637e5e234faaa98efa4c/pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf", size = 6491807, upload-time = "2026-02-11T04:21:44.22Z" }, + { url = "https://files.pythonhosted.org/packages/da/0b/a877a6627dc8318fdb84e357c5e1a758c0941ab1ddffdafd231983788579/pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524", size = 7190954, upload-time = "2026-02-11T04:21:46.114Z" }, + { url = "https://files.pythonhosted.org/packages/83/43/6f732ff85743cf746b1361b91665d9f5155e1483817f693f8d57ea93147f/pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986", size = 6336441, upload-time = "2026-02-11T04:21:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/3b/44/e865ef3986611bb75bfabdf94a590016ea327833f434558801122979cd0e/pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c", size = 7045383, upload-time = "2026-02-11T04:21:50.015Z" }, + { url = "https://files.pythonhosted.org/packages/a8/c6/f4fb24268d0c6908b9f04143697ea18b0379490cb74ba9e8d41b898bd005/pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3", size = 2456104, upload-time = "2026-02-11T04:21:51.633Z" }, + { url = "https://files.pythonhosted.org/packages/03/d0/bebb3ffbf31c5a8e97241476c4cf8b9828954693ce6744b4a2326af3e16b/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af", size = 4062652, upload-time = "2026-02-11T04:21:53.19Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c0/0e16fb0addda4851445c28f8350d8c512f09de27bbb0d6d0bbf8b6709605/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f", size = 4138823, upload-time = "2026-02-11T04:22:03.088Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fb/6170ec655d6f6bb6630a013dd7cf7bc218423d7b5fa9071bf63dc32175ae/pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642", size = 3601143, upload-time = "2026-02-11T04:22:04.909Z" }, + { url = "https://files.pythonhosted.org/packages/59/04/dc5c3f297510ba9a6837cbb318b87dd2b8f73eb41a43cc63767f65cb599c/pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd", size = 5266254, upload-time = "2026-02-11T04:22:07.656Z" }, + { url = "https://files.pythonhosted.org/packages/05/30/5db1236b0d6313f03ebf97f5e17cda9ca060f524b2fcc875149a8360b21c/pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202", size = 4657499, upload-time = "2026-02-11T04:22:09.613Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/008d2ca0eb612e81968e8be0bbae5051efba24d52debf930126d7eaacbba/pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f", size = 6232137, upload-time = "2026-02-11T04:22:11.434Z" }, + { url = "https://files.pythonhosted.org/packages/70/f1/f14d5b8eeb4b2cd62b9f9f847eb6605f103df89ef619ac68f92f748614ea/pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f", size = 8042721, upload-time = "2026-02-11T04:22:13.321Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d6/17824509146e4babbdabf04d8171491fa9d776f7061ff6e727522df9bd03/pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f", size = 6347798, upload-time = "2026-02-11T04:22:15.449Z" }, + { url = "https://files.pythonhosted.org/packages/d1/ee/c85a38a9ab92037a75615aba572c85ea51e605265036e00c5b67dfafbfe2/pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e", size = 7039315, upload-time = "2026-02-11T04:22:17.24Z" }, + { url = "https://files.pythonhosted.org/packages/ec/f3/bc8ccc6e08a148290d7523bde4d9a0d6c981db34631390dc6e6ec34cacf6/pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0", size = 6462360, upload-time = "2026-02-11T04:22:19.111Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ab/69a42656adb1d0665ab051eec58a41f169ad295cf81ad45406963105408f/pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb", size = 7165438, upload-time = "2026-02-11T04:22:21.041Z" }, + { url = "https://files.pythonhosted.org/packages/02/46/81f7aa8941873f0f01d4b55cc543b0a3d03ec2ee30d617a0448bf6bd6dec/pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f", size = 6431503, upload-time = "2026-02-11T04:22:22.833Z" }, + { url = "https://files.pythonhosted.org/packages/40/72/4c245f7d1044b67affc7f134a09ea619d4895333d35322b775b928180044/pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15", size = 7176748, upload-time = "2026-02-11T04:22:24.64Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ad/8a87bdbe038c5c698736e3348af5c2194ffb872ea52f11894c95f9305435/pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f", size = 2544314, upload-time = "2026-02-11T04:22:26.685Z" }, + { url = "https://files.pythonhosted.org/packages/6c/9d/efd18493f9de13b87ede7c47e69184b9e859e4427225ea962e32e56a49bc/pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8", size = 5268612, upload-time = "2026-02-11T04:22:29.884Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f1/4f42eb2b388eb2ffc660dcb7f7b556c1015c53ebd5f7f754965ef997585b/pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9", size = 4660567, upload-time = "2026-02-11T04:22:31.799Z" }, + { url = "https://files.pythonhosted.org/packages/01/54/df6ef130fa43e4b82e32624a7b821a2be1c5653a5fdad8469687a7db4e00/pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60", size = 6269951, upload-time = "2026-02-11T04:22:33.921Z" }, + { url = "https://files.pythonhosted.org/packages/a9/48/618752d06cc44bb4aae8ce0cd4e6426871929ed7b46215638088270d9b34/pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7", size = 8074769, upload-time = "2026-02-11T04:22:35.877Z" }, + { url = "https://files.pythonhosted.org/packages/c3/bd/f1d71eb39a72fa088d938655afba3e00b38018d052752f435838961127d8/pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f", size = 6381358, upload-time = "2026-02-11T04:22:37.698Z" }, + { url = "https://files.pythonhosted.org/packages/64/ef/c784e20b96674ed36a5af839305f55616f8b4f8aa8eeccf8531a6e312243/pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586", size = 7068558, upload-time = "2026-02-11T04:22:39.597Z" }, + { url = "https://files.pythonhosted.org/packages/73/cb/8059688b74422ae61278202c4e1ad992e8a2e7375227be0a21c6b87ca8d5/pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce", size = 6493028, upload-time = "2026-02-11T04:22:42.73Z" }, + { url = "https://files.pythonhosted.org/packages/c6/da/e3c008ed7d2dd1f905b15949325934510b9d1931e5df999bb15972756818/pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8", size = 7191940, upload-time = "2026-02-11T04:22:44.543Z" }, + { url = "https://files.pythonhosted.org/packages/01/4a/9202e8d11714c1fc5951f2e1ef362f2d7fbc595e1f6717971d5dd750e969/pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36", size = 6438736, upload-time = "2026-02-11T04:22:46.347Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ca/cbce2327eb9885476b3957b2e82eb12c866a8b16ad77392864ad601022ce/pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b", size = 7182894, upload-time = "2026-02-11T04:22:48.114Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d2/de599c95ba0a973b94410477f8bf0b6f0b5e67360eb89bcb1ad365258beb/pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334", size = 2546446, upload-time = "2026-02-11T04:22:50.342Z" }, + { url = "https://files.pythonhosted.org/packages/56/11/5d43209aa4cb58e0cc80127956ff1796a68b928e6324bbf06ef4db34367b/pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f", size = 5228606, upload-time = "2026-02-11T04:22:52.106Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d5/3b005b4e4fda6698b371fa6c21b097d4707585d7db99e98d9b0b87ac612a/pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9", size = 4622321, upload-time = "2026-02-11T04:22:53.827Z" }, + { url = "https://files.pythonhosted.org/packages/df/36/ed3ea2d594356fd8037e5a01f6156c74bc8d92dbb0fa60746cc96cabb6e8/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e", size = 5247579, upload-time = "2026-02-11T04:22:56.094Z" }, + { url = "https://files.pythonhosted.org/packages/54/9a/9cc3e029683cf6d20ae5085da0dafc63148e3252c2f13328e553aaa13cfb/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9", size = 6989094, upload-time = "2026-02-11T04:22:58.288Z" }, + { url = "https://files.pythonhosted.org/packages/00/98/fc53ab36da80b88df0967896b6c4b4cd948a0dc5aa40a754266aa3ae48b3/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3", size = 5313850, upload-time = "2026-02-11T04:23:00.554Z" }, + { url = "https://files.pythonhosted.org/packages/30/02/00fa585abfd9fe9d73e5f6e554dc36cc2b842898cbfc46d70353dae227f8/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735", size = 5963343, upload-time = "2026-02-11T04:23:02.934Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/c56ce33ca856e358d27fda9676c055395abddb82c35ac0f593877ed4562e/pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e", size = 7029880, upload-time = "2026-02-11T04:23:04.783Z" }, ] [[package]] From 7c4b134464f1a795c799e766583a5886c4a33315 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 06:56:53 +0000 Subject: [PATCH 220/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dfa4eb4897..6eadcc162d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,10 @@ hide: * ๐ŸŒ Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). +### Internal + +* โฌ† Bump pillow from 12.1.0 to 12.1.1. PR [#14899](https://github.com/fastapi/fastapi/pull/14899) by [@dependabot[bot]](https://github.com/apps/dependabot). + ## 0.129.0 ### Breaking Changes From b93c964d7fc6ab44015e9a0da4af98c101417a83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 08:04:40 +0100 Subject: [PATCH 221/367] =?UTF-8?q?=E2=AC=86=20Bump=20cryptography=20from?= =?UTF-8?q?=2046.0.4=20to=2046.0.5=20(#14892)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.4 to 46.0.5. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.4...46.0.5) --- updated-dependencies: - dependency-name: cryptography dependency-version: 46.0.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- uv.lock | 102 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/uv.lock b/uv.lock index 78026fa67f..aa8c558c7d 100644 --- a/uv.lock +++ b/uv.lock @@ -843,62 +843,62 @@ wheels = [ [[package]] name = "cryptography" -version = "46.0.4" +version = "46.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/19/f748958276519adf6a0c1e79e7b8860b4830dda55ccdf29f2719b5fc499c/cryptography-46.0.4.tar.gz", hash = "sha256:bfd019f60f8abc2ed1b9be4ddc21cfef059c841d86d710bb69909a688cbb8f59", size = 749301, upload-time = "2026-01-28T00:24:37.379Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/99/157aae7949a5f30d51fcb1a9851e8ebd5c74bf99b5285d8bb4b8b9ee641e/cryptography-46.0.4-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:281526e865ed4166009e235afadf3a4c4cba6056f99336a99efba65336fd5485", size = 7173686, upload-time = "2026-01-28T00:23:07.515Z" }, - { url = "https://files.pythonhosted.org/packages/87/91/874b8910903159043b5c6a123b7e79c4559ddd1896e38967567942635778/cryptography-46.0.4-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f14fba5bf6f4390d7ff8f086c566454bff0411f6d8aa7af79c88b6f9267aecc", size = 4275871, upload-time = "2026-01-28T00:23:09.439Z" }, - { url = "https://files.pythonhosted.org/packages/c0/35/690e809be77896111f5b195ede56e4b4ed0435b428c2f2b6d35046fbb5e8/cryptography-46.0.4-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:47bcd19517e6389132f76e2d5303ded6cf3f78903da2158a671be8de024f4cd0", size = 4423124, upload-time = "2026-01-28T00:23:11.529Z" }, - { url = "https://files.pythonhosted.org/packages/1a/5b/a26407d4f79d61ca4bebaa9213feafdd8806dc69d3d290ce24996d3cfe43/cryptography-46.0.4-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:01df4f50f314fbe7009f54046e908d1754f19d0c6d3070df1e6268c5a4af09fa", size = 4277090, upload-time = "2026-01-28T00:23:13.123Z" }, - { url = "https://files.pythonhosted.org/packages/0c/d8/4bb7aec442a9049827aa34cee1aa83803e528fa55da9a9d45d01d1bb933e/cryptography-46.0.4-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5aa3e463596b0087b3da0dbe2b2487e9fc261d25da85754e30e3b40637d61f81", size = 4947652, upload-time = "2026-01-28T00:23:14.554Z" }, - { url = "https://files.pythonhosted.org/packages/2b/08/f83e2e0814248b844265802d081f2fac2f1cbe6cd258e72ba14ff006823a/cryptography-46.0.4-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0a9ad24359fee86f131836a9ac3bffc9329e956624a2d379b613f8f8abaf5255", size = 4455157, upload-time = "2026-01-28T00:23:16.443Z" }, - { url = "https://files.pythonhosted.org/packages/0a/05/19d849cf4096448779d2dcc9bb27d097457dac36f7273ffa875a93b5884c/cryptography-46.0.4-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:dc1272e25ef673efe72f2096e92ae39dea1a1a450dd44918b15351f72c5a168e", size = 3981078, upload-time = "2026-01-28T00:23:17.838Z" }, - { url = "https://files.pythonhosted.org/packages/e6/89/f7bac81d66ba7cde867a743ea5b37537b32b5c633c473002b26a226f703f/cryptography-46.0.4-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:de0f5f4ec8711ebc555f54735d4c673fc34b65c44283895f1a08c2b49d2fd99c", size = 4276213, upload-time = "2026-01-28T00:23:19.257Z" }, - { url = "https://files.pythonhosted.org/packages/da/9f/7133e41f24edd827020ad21b068736e792bc68eecf66d93c924ad4719fb3/cryptography-46.0.4-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:eeeb2e33d8dbcccc34d64651f00a98cb41b2dc69cef866771a5717e6734dfa32", size = 4912190, upload-time = "2026-01-28T00:23:21.244Z" }, - { url = "https://files.pythonhosted.org/packages/a6/f7/6d43cbaddf6f65b24816e4af187d211f0bc536a29961f69faedc48501d8e/cryptography-46.0.4-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3d425eacbc9aceafd2cb429e42f4e5d5633c6f873f5e567077043ef1b9bbf616", size = 4454641, upload-time = "2026-01-28T00:23:22.866Z" }, - { url = "https://files.pythonhosted.org/packages/9e/4f/ebd0473ad656a0ac912a16bd07db0f5d85184924e14fc88feecae2492834/cryptography-46.0.4-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91627ebf691d1ea3976a031b61fb7bac1ccd745afa03602275dda443e11c8de0", size = 4405159, upload-time = "2026-01-28T00:23:25.278Z" }, - { url = "https://files.pythonhosted.org/packages/d1/f7/7923886f32dc47e27adeff8246e976d77258fd2aa3efdd1754e4e323bf49/cryptography-46.0.4-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2d08bc22efd73e8854b0b7caff402d735b354862f1145d7be3b9c0f740fef6a0", size = 4666059, upload-time = "2026-01-28T00:23:26.766Z" }, - { url = "https://files.pythonhosted.org/packages/eb/a7/0fca0fd3591dffc297278a61813d7f661a14243dd60f499a7a5b48acb52a/cryptography-46.0.4-cp311-abi3-win32.whl", hash = "sha256:82a62483daf20b8134f6e92898da70d04d0ef9a75829d732ea1018678185f4f5", size = 3026378, upload-time = "2026-01-28T00:23:28.317Z" }, - { url = "https://files.pythonhosted.org/packages/2d/12/652c84b6f9873f0909374864a57b003686c642ea48c84d6c7e2c515e6da5/cryptography-46.0.4-cp311-abi3-win_amd64.whl", hash = "sha256:6225d3ebe26a55dbc8ead5ad1265c0403552a63336499564675b29eb3184c09b", size = 3478614, upload-time = "2026-01-28T00:23:30.275Z" }, - { url = "https://files.pythonhosted.org/packages/b9/27/542b029f293a5cce59349d799d4d8484b3b1654a7b9a0585c266e974a488/cryptography-46.0.4-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:485e2b65d25ec0d901bca7bcae0f53b00133bf3173916d8e421f6fddde103908", size = 7116417, upload-time = "2026-01-28T00:23:31.958Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f5/559c25b77f40b6bf828eabaf988efb8b0e17b573545edb503368ca0a2a03/cryptography-46.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:078e5f06bd2fa5aea5a324f2a09f914b1484f1d0c2a4d6a8a28c74e72f65f2da", size = 4264508, upload-time = "2026-01-28T00:23:34.264Z" }, - { url = "https://files.pythonhosted.org/packages/49/a1/551fa162d33074b660dc35c9bc3616fefa21a0e8c1edd27b92559902e408/cryptography-46.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dce1e4f068f03008da7fa51cc7abc6ddc5e5de3e3d1550334eaf8393982a5829", size = 4409080, upload-time = "2026-01-28T00:23:35.793Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/4d8d129a755f5d6df1bbee69ea2f35ebfa954fa1847690d1db2e8bca46a5/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2067461c80271f422ee7bdbe79b9b4be54a5162e90345f86a23445a0cf3fd8a2", size = 4270039, upload-time = "2026-01-28T00:23:37.263Z" }, - { url = "https://files.pythonhosted.org/packages/4c/f5/ed3fcddd0a5e39321e595e144615399e47e7c153a1fb8c4862aec3151ff9/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:c92010b58a51196a5f41c3795190203ac52edfd5dc3ff99149b4659eba9d2085", size = 4926748, upload-time = "2026-01-28T00:23:38.884Z" }, - { url = "https://files.pythonhosted.org/packages/43/ae/9f03d5f0c0c00e85ecb34f06d3b79599f20630e4db91b8a6e56e8f83d410/cryptography-46.0.4-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:829c2b12bbc5428ab02d6b7f7e9bbfd53e33efd6672d21341f2177470171ad8b", size = 4442307, upload-time = "2026-01-28T00:23:40.56Z" }, - { url = "https://files.pythonhosted.org/packages/8b/22/e0f9f2dae8040695103369cf2283ef9ac8abe4d51f68710bec2afd232609/cryptography-46.0.4-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:62217ba44bf81b30abaeda1488686a04a702a261e26f87db51ff61d9d3510abd", size = 3959253, upload-time = "2026-01-28T00:23:42.827Z" }, - { url = "https://files.pythonhosted.org/packages/01/5b/6a43fcccc51dae4d101ac7d378a8724d1ba3de628a24e11bf2f4f43cba4d/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:9c2da296c8d3415b93e6053f5a728649a87a48ce084a9aaf51d6e46c87c7f2d2", size = 4269372, upload-time = "2026-01-28T00:23:44.655Z" }, - { url = "https://files.pythonhosted.org/packages/17/b7/0f6b8c1dd0779df2b526e78978ff00462355e31c0a6f6cff8a3e99889c90/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9b34d8ba84454641a6bf4d6762d15847ecbd85c1316c0a7984e6e4e9f748ec2e", size = 4891908, upload-time = "2026-01-28T00:23:46.48Z" }, - { url = "https://files.pythonhosted.org/packages/83/17/259409b8349aa10535358807a472c6a695cf84f106022268d31cea2b6c97/cryptography-46.0.4-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:df4a817fa7138dd0c96c8c8c20f04b8aaa1fac3bbf610913dcad8ea82e1bfd3f", size = 4441254, upload-time = "2026-01-28T00:23:48.403Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fe/e4a1b0c989b00cee5ffa0764401767e2d1cf59f45530963b894129fd5dce/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b1de0ebf7587f28f9190b9cb526e901bf448c9e6a99655d2b07fff60e8212a82", size = 4396520, upload-time = "2026-01-28T00:23:50.26Z" }, - { url = "https://files.pythonhosted.org/packages/b3/81/ba8fd9657d27076eb40d6a2f941b23429a3c3d2f56f5a921d6b936a27bc9/cryptography-46.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9b4d17bc7bd7cdd98e3af40b441feaea4c68225e2eb2341026c84511ad246c0c", size = 4651479, upload-time = "2026-01-28T00:23:51.674Z" }, - { url = "https://files.pythonhosted.org/packages/00/03/0de4ed43c71c31e4fe954edd50b9d28d658fef56555eba7641696370a8e2/cryptography-46.0.4-cp314-cp314t-win32.whl", hash = "sha256:c411f16275b0dea722d76544a61d6421e2cc829ad76eec79280dbdc9ddf50061", size = 3001986, upload-time = "2026-01-28T00:23:53.485Z" }, - { url = "https://files.pythonhosted.org/packages/5c/70/81830b59df7682917d7a10f833c4dab2a5574cd664e86d18139f2b421329/cryptography-46.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:728fedc529efc1439eb6107b677f7f7558adab4553ef8669f0d02d42d7b959a7", size = 3468288, upload-time = "2026-01-28T00:23:55.09Z" }, - { url = "https://files.pythonhosted.org/packages/56/f7/f648fdbb61d0d45902d3f374217451385edc7e7768d1b03ff1d0e5ffc17b/cryptography-46.0.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a9556ba711f7c23f77b151d5798f3ac44a13455cc68db7697a1096e6d0563cab", size = 7169583, upload-time = "2026-01-28T00:23:56.558Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cc/8f3224cbb2a928de7298d6ed4790f5ebc48114e02bdc9559196bfb12435d/cryptography-46.0.4-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bf75b0259e87fa70bddc0b8b4078b76e7fd512fd9afae6c1193bcf440a4dbef", size = 4275419, upload-time = "2026-01-28T00:23:58.364Z" }, - { url = "https://files.pythonhosted.org/packages/17/43/4a18faa7a872d00e4264855134ba82d23546c850a70ff209e04ee200e76f/cryptography-46.0.4-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3c268a3490df22270955966ba236d6bc4a8f9b6e4ffddb78aac535f1a5ea471d", size = 4419058, upload-time = "2026-01-28T00:23:59.867Z" }, - { url = "https://files.pythonhosted.org/packages/ee/64/6651969409821d791ba12346a124f55e1b76f66a819254ae840a965d4b9c/cryptography-46.0.4-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:812815182f6a0c1d49a37893a303b44eaac827d7f0d582cecfc81b6427f22973", size = 4278151, upload-time = "2026-01-28T00:24:01.731Z" }, - { url = "https://files.pythonhosted.org/packages/20/0b/a7fce65ee08c3c02f7a8310cc090a732344066b990ac63a9dfd0a655d321/cryptography-46.0.4-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:a90e43e3ef65e6dcf969dfe3bb40cbf5aef0d523dff95bfa24256be172a845f4", size = 4939441, upload-time = "2026-01-28T00:24:03.175Z" }, - { url = "https://files.pythonhosted.org/packages/db/a7/20c5701e2cd3e1dfd7a19d2290c522a5f435dd30957d431dcb531d0f1413/cryptography-46.0.4-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a05177ff6296644ef2876fce50518dffb5bcdf903c85250974fc8bc85d54c0af", size = 4451617, upload-time = "2026-01-28T00:24:05.403Z" }, - { url = "https://files.pythonhosted.org/packages/00/dc/3e16030ea9aa47b63af6524c354933b4fb0e352257c792c4deeb0edae367/cryptography-46.0.4-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:daa392191f626d50f1b136c9b4cf08af69ca8279d110ea24f5c2700054d2e263", size = 3977774, upload-time = "2026-01-28T00:24:06.851Z" }, - { url = "https://files.pythonhosted.org/packages/42/c8/ad93f14118252717b465880368721c963975ac4b941b7ef88f3c56bf2897/cryptography-46.0.4-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e07ea39c5b048e085f15923511d8121e4a9dc45cee4e3b970ca4f0d338f23095", size = 4277008, upload-time = "2026-01-28T00:24:08.926Z" }, - { url = "https://files.pythonhosted.org/packages/00/cf/89c99698151c00a4631fbfcfcf459d308213ac29e321b0ff44ceeeac82f1/cryptography-46.0.4-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d5a45ddc256f492ce42a4e35879c5e5528c09cd9ad12420828c972951d8e016b", size = 4903339, upload-time = "2026-01-28T00:24:12.009Z" }, - { url = "https://files.pythonhosted.org/packages/03/c3/c90a2cb358de4ac9309b26acf49b2a100957e1ff5cc1e98e6c4996576710/cryptography-46.0.4-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:6bb5157bf6a350e5b28aee23beb2d84ae6f5be390b2f8ee7ea179cda077e1019", size = 4451216, upload-time = "2026-01-28T00:24:13.975Z" }, - { url = "https://files.pythonhosted.org/packages/96/2c/8d7f4171388a10208671e181ca43cdc0e596d8259ebacbbcfbd16de593da/cryptography-46.0.4-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:dd5aba870a2c40f87a3af043e0dee7d9eb02d4aff88a797b48f2b43eff8c3ab4", size = 4404299, upload-time = "2026-01-28T00:24:16.169Z" }, - { url = "https://files.pythonhosted.org/packages/e9/23/cbb2036e450980f65c6e0a173b73a56ff3bccd8998965dea5cc9ddd424a5/cryptography-46.0.4-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:93d8291da8d71024379ab2cb0b5c57915300155ad42e07f76bea6ad838d7e59b", size = 4664837, upload-time = "2026-01-28T00:24:17.629Z" }, - { url = "https://files.pythonhosted.org/packages/0a/21/f7433d18fe6d5845329cbdc597e30caf983229c7a245bcf54afecc555938/cryptography-46.0.4-cp38-abi3-win32.whl", hash = "sha256:0563655cb3c6d05fb2afe693340bc050c30f9f34e15763361cf08e94749401fc", size = 3009779, upload-time = "2026-01-28T00:24:20.198Z" }, - { url = "https://files.pythonhosted.org/packages/3a/6a/bd2e7caa2facffedf172a45c1a02e551e6d7d4828658c9a245516a598d94/cryptography-46.0.4-cp38-abi3-win_amd64.whl", hash = "sha256:fa0900b9ef9c49728887d1576fd8d9e7e3ea872fa9b25ef9b64888adc434e976", size = 3466633, upload-time = "2026-01-28T00:24:21.851Z" }, - { url = "https://files.pythonhosted.org/packages/59/e0/f9c6c53e1f2a1c2507f00f2faba00f01d2f334b35b0fbfe5286715da2184/cryptography-46.0.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:766330cce7416c92b5e90c3bb71b1b79521760cdcfc3a6a1a182d4c9fab23d2b", size = 3476316, upload-time = "2026-01-28T00:24:24.144Z" }, - { url = "https://files.pythonhosted.org/packages/27/7a/f8d2d13227a9a1a9fe9c7442b057efecffa41f1e3c51d8622f26b9edbe8f/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c236a44acfb610e70f6b3e1c3ca20ff24459659231ef2f8c48e879e2d32b73da", size = 4216693, upload-time = "2026-01-28T00:24:25.758Z" }, - { url = "https://files.pythonhosted.org/packages/c5/de/3787054e8f7972658370198753835d9d680f6cd4a39df9f877b57f0dd69c/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8a15fb869670efa8f83cbffbc8753c1abf236883225aed74cd179b720ac9ec80", size = 4382765, upload-time = "2026-01-28T00:24:27.577Z" }, - { url = "https://files.pythonhosted.org/packages/8a/5f/60e0afb019973ba6a0b322e86b3d61edf487a4f5597618a430a2a15f2d22/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:fdc3daab53b212472f1524d070735b2f0c214239df131903bae1d598016fa822", size = 4216066, upload-time = "2026-01-28T00:24:29.056Z" }, - { url = "https://files.pythonhosted.org/packages/81/8e/bf4a0de294f147fee66f879d9bae6f8e8d61515558e3d12785dd90eca0be/cryptography-46.0.4-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:44cc0675b27cadb71bdbb96099cca1fa051cd11d2ade09e5cd3a2edb929ed947", size = 4382025, upload-time = "2026-01-28T00:24:30.681Z" }, - { url = "https://files.pythonhosted.org/packages/79/f4/9ceb90cfd6a3847069b0b0b353fd3075dc69b49defc70182d8af0c4ca390/cryptography-46.0.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be8c01a7d5a55f9a47d1888162b76c8f49d62b234d88f0ff91a9fbebe32ffbc3", size = 3406043, upload-time = "2026-01-28T00:24:32.236Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, + { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, + { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, + { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, + { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, + { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, + { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" }, + { url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" }, + { url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" }, + { url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" }, + { url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" }, + { url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" }, + { url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" }, + { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, + { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, + { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, + { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, + { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, + { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, + { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, + { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, + { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, + { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, + { url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" }, + { url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" }, + { url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, ] [[package]] From fdbbf7490835c83b8e8c1d881e1989acc8cb4fda Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 07:05:05 +0000 Subject: [PATCH 222/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6eadcc162d..5eec22e0b3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* โฌ† Bump cryptography from 46.0.4 to 46.0.5. PR [#14892](https://github.com/fastapi/fastapi/pull/14892) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pillow from 12.1.0 to 12.1.1. PR [#14899](https://github.com/fastapi/fastapi/pull/14899) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.129.0 From ea8db708f10e3e966062eeafdcfc95e83b1003d5 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:41:38 +0100 Subject: [PATCH 223/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-all)=20(#14913)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/tr/docs/_llm-test.md | 46 +-- docs/tr/docs/advanced/additional-responses.md | 4 +- .../tr/docs/advanced/advanced-dependencies.md | 8 +- .../tr/docs/advanced/advanced-python-types.md | 61 +++ docs/tr/docs/advanced/async-tests.md | 8 +- docs/tr/docs/advanced/behind-a-proxy.md | 20 +- docs/tr/docs/advanced/custom-response.md | 32 +- docs/tr/docs/advanced/dataclasses.md | 2 +- docs/tr/docs/advanced/events.md | 16 +- docs/tr/docs/advanced/generate-clients.md | 8 +- docs/tr/docs/advanced/index.md | 4 +- docs/tr/docs/advanced/middleware.md | 6 +- docs/tr/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 20 +- .../advanced/response-change-status-code.md | 2 +- docs/tr/docs/advanced/response-cookies.md | 6 +- docs/tr/docs/advanced/response-directly.md | 6 +- docs/tr/docs/advanced/response-headers.md | 4 +- .../docs/advanced/security/http-basic-auth.md | 8 +- docs/tr/docs/advanced/security/index.md | 4 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/tr/docs/advanced/settings.md | 20 +- docs/tr/docs/advanced/sub-applications.md | 8 +- docs/tr/docs/advanced/templates.md | 6 +- docs/tr/docs/advanced/testing-dependencies.md | 1 + docs/tr/docs/advanced/testing-events.md | 6 +- docs/tr/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/tr/docs/advanced/websockets.md | 8 +- docs/tr/docs/advanced/wsgi.md | 2 +- docs/tr/docs/alternatives.md | 8 +- docs/tr/docs/async.md | 377 ++++++++++-------- docs/tr/docs/deployment/concepts.md | 30 +- docs/tr/docs/deployment/docker.md | 10 +- docs/tr/docs/deployment/https.md | 2 +- docs/tr/docs/deployment/index.md | 6 +- docs/tr/docs/deployment/manually.md | 4 +- docs/tr/docs/environment-variables.md | 4 +- docs/tr/docs/features.md | 195 +++++---- docs/tr/docs/history-design-future.md | 2 +- .../authentication-error-status-code.md | 2 +- docs/tr/docs/how-to/conditional-openapi.md | 6 +- docs/tr/docs/how-to/configure-swagger-ui.md | 8 +- docs/tr/docs/how-to/custom-docs-ui-assets.md | 14 +- docs/tr/docs/how-to/extending-openapi.md | 24 +- docs/tr/docs/how-to/general.md | 2 +- docs/tr/docs/how-to/graphql.md | 2 +- docs/tr/docs/how-to/index.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 2 +- docs/tr/docs/index.md | 14 +- docs/tr/docs/python-types.md | 198 ++------- docs/tr/docs/translation-banner.md | 2 +- docs/tr/docs/tutorial/background-tasks.md | 6 +- docs/tr/docs/tutorial/bigger-applications.md | 26 +- docs/tr/docs/tutorial/body-multiple-params.md | 6 - docs/tr/docs/tutorial/body-nested-models.md | 6 +- docs/tr/docs/tutorial/body.md | 2 +- docs/tr/docs/tutorial/cookie-param-models.md | 20 +- docs/tr/docs/tutorial/cookie-params.md | 12 +- docs/tr/docs/tutorial/cors.md | 4 +- docs/tr/docs/tutorial/debugging.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +- ...pendencies-in-path-operation-decorators.md | 8 +- .../dependencies/dependencies-with-yield.md | 27 +- .../dependencies/global-dependencies.md | 2 +- docs/tr/docs/tutorial/dependencies/index.md | 2 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/tr/docs/tutorial/extra-data-types.md | 16 +- docs/tr/docs/tutorial/extra-models.md | 14 +- docs/tr/docs/tutorial/first-steps.md | 16 +- docs/tr/docs/tutorial/handling-errors.md | 16 +- docs/tr/docs/tutorial/index.md | 2 +- docs/tr/docs/tutorial/metadata.md | 12 +- docs/tr/docs/tutorial/middleware.md | 6 +- .../tutorial/path-operation-configuration.md | 10 +- .../path-params-numeric-validations.md | 20 +- docs/tr/docs/tutorial/path-params.md | 28 +- .../tutorial/query-params-str-validations.md | 51 +-- docs/tr/docs/tutorial/query-params.md | 8 +- docs/tr/docs/tutorial/request-files.md | 14 +- docs/tr/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/tr/docs/tutorial/request-forms.md | 10 +- docs/tr/docs/tutorial/response-model.md | 8 +- docs/tr/docs/tutorial/response-status-code.md | 8 +- docs/tr/docs/tutorial/schema-extra-example.md | 2 +- docs/tr/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/tr/docs/tutorial/security/oauth2-jwt.md | 12 +- docs/tr/docs/tutorial/sql-databases.md | 30 +- docs/tr/docs/tutorial/static-files.md | 4 +- docs/tr/docs/tutorial/testing.md | 16 +- docs/tr/docs/virtual-environments.md | 2 +- 93 files changed, 832 insertions(+), 882 deletions(-) create mode 100644 docs/tr/docs/advanced/advanced-python-types.md diff --git a/docs/tr/docs/_llm-test.md b/docs/tr/docs/_llm-test.md index 0ca218e6e9..0ba5cca752 100644 --- a/docs/tr/docs/_llm-test.md +++ b/docs/tr/docs/_llm-test.md @@ -27,7 +27,7 @@ Bu bir code snippet: `foo`. Bu da baลŸka bir code snippet: `bar`. Bir tane daha: Code snippet'lerin iรงeriฤŸi olduฤŸu gibi bฤฑrakฤฑlmalฤฑdฤฑr. -`script/translate.py` iรงindeki genel prompt'ta `### Content of code snippets` bรถlรผmรผne bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### Content of code snippets` bรถlรผmรผne bakฤฑn. //// @@ -116,7 +116,7 @@ works(foo="bar") # This works ๐ŸŽ‰ Code block'larฤฑn iรงindeki code deฤŸiลŸtirilmemelidir; tek istisna yorumlardฤฑr (comments). -`script/translate.py` iรงindeki genel prompt'ta `### Content of code blocks` bรถlรผmรผne bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### Content of code blocks` bรถlรผmรผne bakฤฑn. //// @@ -125,31 +125,31 @@ Code block'larฤฑn iรงindeki code deฤŸiลŸtirilmemelidir; tek istisna yorumlardฤฑr //// tab | Test /// info | Bilgi -Some text +Bazฤฑ metin /// /// note | Not -Some text +Bazฤฑ metin /// /// note | Teknik Detaylar -Some text +Bazฤฑ metin /// /// check | Ek bilgi -Some text +Bazฤฑ metin /// /// tip | ฤฐpucu -Some text +Bazฤฑ metin /// /// warning | Uyarฤฑ -Some text +Bazฤฑ metin /// /// danger | Tehlike -Some text +Bazฤฑ metin /// //// @@ -158,7 +158,7 @@ Some text Sekmelerin ve `Info`/`Note`/`Warning`/vb. bloklarฤฑn baลŸlฤฑฤŸฤฑ, dikey รงizgiden (`|`) sonra รงeviri olarak eklenmelidir. -`script/translate.py` iรงindeki genel prompt'ta `### Special blocks` ve `### Tab blocks` bรถlรผmlerine bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### Special blocks` ve `### Tab blocks` bรถlรผmlerine bakฤฑn. //// @@ -170,10 +170,10 @@ Link metni รงevrilmelidir, link adresi deฤŸiลŸmeden kalmalฤฑdฤฑr: * [Yukarฤฑdaki baลŸlฤฑฤŸa link](#code-snippets) * [Internal link](index.md#installation){.internal-link target=_blank} -* External link -* Link to a style -* Link to a script -* Link to an image +* Harici link +* Bir stile baฤŸlantฤฑ +* Bir betiฤŸe baฤŸlantฤฑ +* Bir gรถrsele baฤŸlantฤฑ Link metni รงevrilmelidir, link adresi รงeviriye iลŸaret etmelidir: @@ -185,7 +185,7 @@ Link metni รงevrilmelidir, link adresi รงeviriye iลŸaret etmelidir: Link'ler รงevrilmelidir, ancak adresleri deฤŸiลŸmeden kalmalฤฑdฤฑr. Bir istisna, FastAPI dokรผmantasyonunun sayfalarฤฑna verilen mutlak link'lerdir. Bu durumda link, รงeviriye iลŸaret etmelidir. -`script/translate.py` iรงindeki genel prompt'ta `### Links` bรถlรผmรผne bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### Links` bรถlรผmรผne bakฤฑn. //// @@ -199,14 +199,9 @@ Burada HTML "abbr" รถฤŸeleriyle sarฤฑlmฤฑลŸ bazฤฑ ลŸeyler var (bazฤฑlarฤฑ uydurm * GTD * lt -* XWT +* XWT * PSGI -### abbr bir aรงฤฑklama verir { #the-abbr-gives-an-explanation } - -* cluster -* Deep Learning - ### abbr tam bir ifade ve bir aรงฤฑklama verir { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN @@ -220,10 +215,15 @@ Burada HTML "abbr" รถฤŸeleriyle sarฤฑlmฤฑลŸ bazฤฑ ลŸeyler var (bazฤฑlarฤฑ uydurm ร‡eviriler, LLM'nin kaldฤฑrmamasฤฑ gereken kendi "abbr" รถฤŸelerini ekleyebilir. ร–rneฤŸin ฤฐngilizce kelimeleri aรงฤฑklamak iรงin. -`script/translate.py` iรงindeki genel prompt'ta `### HTML abbr elements` bรถlรผmรผne bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### HTML abbr elements` bรถlรผmรผne bakฤฑn. //// +## HTML "dfn" รถฤŸeleri { #html-dfn-elements } + +* kรผme +* Derin ร–ฤŸrenme + ## BaลŸlฤฑklar { #headings } //// tab | Test @@ -246,7 +246,7 @@ Tekrar merhaba. BaลŸlฤฑklarla ilgili tek katฤฑ kural, LLM'nin sรผslรผ parantezler iรงindeki hash kฤฑsmฤฑnฤฑ deฤŸiลŸtirmemesidir; bรถylece link'ler bozulmaz. -`script/translate.py` iรงindeki genel prompt'ta `### Headings` bรถlรผmรผne bakฤฑn. +`scripts/translate.py` iรงindeki genel prompt'ta `### Headings` bรถlรผmรผne bakฤฑn. Dile รถzel bazฤฑ talimatlar iรงin รถrneฤŸin `docs/de/llm-prompt.md` iรงindeki `### Headings` bรถlรผmรผne bakฤฑn. diff --git a/docs/tr/docs/advanced/additional-responses.md b/docs/tr/docs/advanced/additional-responses.md index c8e372775c..3a066af407 100644 --- a/docs/tr/docs/advanced/additional-responses.md +++ b/docs/tr/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ Bu response `dict`'lerinin her birinde, `response_model`'e benzer ลŸekilde bir P ร–rneฤŸin, `404` status code'u ve `Message` Pydantic model'i ile baลŸka bir response tanฤฑmlamak iรงin ลŸunu yazabilirsiniz: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Not @@ -203,7 +203,7 @@ Varsayฤฑlan `200` status code'unu (ya da gerekiyorsa รถzel bir tane) kullanarak Ayrฤฑca `response_model`'inizi kullanan, ancak รถzel bir `example` iรงeren `200` status code'lu bir response da tanฤฑmlayabilirsiniz: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Bunlarฤฑn hepsi OpenAPI'nize birleลŸtirilerek dahil edilir ve API dokรผmanlarฤฑnda gรถsterilir: diff --git a/docs/tr/docs/advanced/advanced-dependencies.md b/docs/tr/docs/advanced/advanced-dependencies.md index 8afb544bdd..8be92a6ac7 100644 --- a/docs/tr/docs/advanced/advanced-dependencies.md +++ b/docs/tr/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Class'ฤฑn kendisini deฤŸil (zaten callable'dฤฑr), o class'ฤฑn bir instance'ฤฑnฤฑ Bunu yapmak iรงin `__call__` adฤฑnda bir method tanฤฑmlarฤฑz: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} Bu durumda, ek parametreleri ve alt-dependency'leri kontrol etmek iรงin **FastAPI**'nin kullanacaฤŸฤฑ ลŸey bu `__call__` olacaktฤฑr; ayrฤฑca daha sonra *path operation function* iรงindeki parametreye bir deฤŸer geรงmek iรงin รงaฤŸrฤฑlacak olan da budur. @@ -26,7 +26,7 @@ Bu durumda, ek parametreleri ve alt-dependency'leri kontrol etmek iรงin **FastAP Ve ลŸimdi, dependency'yi "parametreleลŸtirmek" iรงin kullanacaฤŸฤฑmฤฑz instance parametrelerini tanฤฑmlamak รผzere `__init__` kullanabiliriz: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} Bu durumda **FastAPI**, `__init__` ile asla uฤŸraลŸmaz veya onu รถnemsemez; onu doฤŸrudan kendi kodumuzda kullanฤฑrฤฑz. @@ -34,7 +34,7 @@ Bu durumda **FastAPI**, `__init__` ile asla uฤŸraลŸmaz veya onu รถnemsemez; onu Bu class'tan bir instance'ฤฑ ลŸรถyle oluลŸturabiliriz: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} Bรถylece dependency'mizi "parametreleลŸtirmiลŸ" oluruz; artฤฑk iรงinde `"bar"` vardฤฑr ve bu deฤŸer `checker.fixed_content` attribute'u olarak durur. @@ -50,7 +50,7 @@ checker(q="somequery") ...ve bunun dรถndรผrdรผฤŸรผ her ลŸeyi, *path operation function* iรงinde `fixed_content_included` parametresine dependency deฤŸeri olarak geรงirir: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | ฤฐpucu diff --git a/docs/tr/docs/advanced/advanced-python-types.md b/docs/tr/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..91fe1d5e09 --- /dev/null +++ b/docs/tr/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# GeliลŸmiลŸ Python Tipleri { #advanced-python-types } + +Python tipleriyle รงalฤฑลŸฤฑrken iลŸinize yarayabilecek bazฤฑ ek fikirler. + +## `Union` veya `Optional` Kullanฤฑmฤฑ { #using-union-or-optional } + +Kodunuz herhangi bir nedenle `|` kullanamฤฑyorsa โ€” รถrneฤŸin bir tip aรงฤฑklamasฤฑnda (type annotation) deฤŸil de `response_model=` gibi bir yerdeyse โ€” dikey รงizgi (`|`) yerine `typing` iรงindeki `Union`'ฤฑ kullanabilirsiniz. + +ร–rneฤŸin, bir ลŸeyin `str` ya da `None` olabileceฤŸini ลŸรถyle belirtebilirsiniz: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing`, bir ลŸeyin `None` olabileceฤŸini belirtmek iรงin `Optional` ile bir kฤฑsayol da sunar. + +Benim oldukรงa รถznel bakฤฑลŸ aรงฤฑma gรถre kรผรงรผk bir ipucu: + +- ๐Ÿšจ `Optional[SomeType]` kullanmaktan kaรงฤฑnฤฑn +- Bunun yerine โœจ **`Union[SomeType, None]` kullanฤฑn** โœจ. + +ฤฐkisi de eลŸdeฤŸer ve temelde aynฤฑdฤฑr; ancak "**optional**" kelimesi deฤŸerin isteฤŸe baฤŸlฤฑ olduฤŸunu ima eder. Oysa aslฤฑnda " `None` olabilir" demektir; deฤŸer isteฤŸe baฤŸlฤฑ olmasa ve hรขlรข zorunlu olsa bile. + +Bence `Union[SomeType, None]` ne demek istediฤŸini daha aรงฤฑk anlatฤฑr. + +Burada mesele sadece kelimeler ve isimler. Ancak bu kelimeler sizin ve ekip arkadaลŸlarฤฑnฤฑzฤฑn koda bakฤฑลŸฤฑnฤฑ etkileyebilir. + +ร–rnek olarak ลŸu fonksiyona bakalฤฑm: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +`name` parametresi `Optional[str]` olarak tanฤฑmlฤฑdฤฑr; ancak isteฤŸe baฤŸlฤฑ deฤŸildir, parametre olmadan fonksiyonu รงaฤŸฤฑramazsฤฑnฤฑz: + +```Python +say_hi() # Ah hayฤฑr, bu hata fฤฑrlatฤฑr! ๐Ÿ˜ฑ +``` + +`name` parametresi varsayฤฑlan bir deฤŸeri olmadฤฑฤŸฤฑ iรงin hรขlรข zorunludur (yani *optional* deฤŸildir). Yine de `name`, deฤŸer olarak `None` kabul eder: + +```Python +say_hi(name=None) # Bu รงalฤฑลŸฤฑr, None geรงerlidir ๐ŸŽ‰ +``` + +ฤฐyi haber ลŸu ki, รงoฤŸu durumda tip birliklerini (union) tanฤฑmlamak iรงin doฤŸrudan `|` kullanabilirsiniz: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Dolayฤฑsฤฑyla, normalde `Optional` ve `Union` gibi isimler iรงin endiลŸelenmenize gerek yok. ๐Ÿ˜Ž diff --git a/docs/tr/docs/advanced/async-tests.md b/docs/tr/docs/advanced/async-tests.md index 82349bbec4..1e5b37a3d6 100644 --- a/docs/tr/docs/advanced/async-tests.md +++ b/docs/tr/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ Basit bir รถrnek iรงin, [Bigger Applications](../tutorial/bigger-applications.md `main.py` dosyasฤฑ ลŸรถyle olur: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} `test_main.py` dosyasฤฑnda `main.py` iรงin testler yer alฤฑr, artฤฑk ลŸรถyle gรถrรผnebilir: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## ร‡alฤฑลŸtฤฑrma { #run-it } @@ -56,7 +56,7 @@ $ pytest `@pytest.mark.anyio` marker'ฤฑ, pytest'e bu test fonksiyonunun asenkron olarak รงaฤŸrฤฑlmasฤฑ gerektiฤŸini sรถyler: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | ฤฐpucu @@ -66,7 +66,7 @@ Test fonksiyonu artฤฑk `TestClient` kullanฤฑrken eskiden olduฤŸu gibi sadece `de Ardฤฑndan app ile bir `AsyncClient` oluลŸturup `await` kullanarak ona async request'ler gรถnderebiliriz. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} Bu, ลŸu kullanฤฑma denktir: diff --git a/docs/tr/docs/advanced/behind-a-proxy.md b/docs/tr/docs/advanced/behind-a-proxy.md index e70b16960f..5cf9a534dd 100644 --- a/docs/tr/docs/advanced/behind-a-proxy.md +++ b/docs/tr/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" ร–rneฤŸin `/items/` adฤฑnda bir *path operation* tanฤฑmladฤฑฤŸฤฑnฤฑzฤฑ dรผลŸรผnelim: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} Client `/items`'a gitmeye รงalฤฑลŸฤฑrsa, varsayฤฑlan olarak `/items/`'a redirect edilir. @@ -115,7 +115,7 @@ Bu durumda, orijinal `/app` path'i aslฤฑnda `/api/v1/app` altฤฑnda servis edilir Kodunuzun tamamฤฑ sadece `/app` varmฤฑลŸ gibi yazฤฑlmฤฑลŸ olsa bile. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} Proxy, request'i app server'a (muhtemelen FastAPI CLI รผzerinden Uvicorn) iletmeden รถnce **path prefix**'i anlฤฑk olarak **"kฤฑrpar"** (strip). Bรถylece uygulamanฤฑz hรขlรข `/app` altฤฑnda servis ediliyormuลŸ gibi davranฤฑr ve tรผm kodunuzu `/api/v1` prefix'ini iรงerecek ลŸekilde gรผncellemeniz gerekmez. @@ -149,14 +149,14 @@ Docs UI'nin, bu API `server`'ฤฑnฤฑn (proxy arkasฤฑnda) `/api/v1` altฤฑnda bulund ```JSON hl_lines="4-8" { "openapi": "3.1.0", - // More stuff here + // Burada daha fazla ลŸey var "servers": [ { "url": "/api/v1" } ], "paths": { - // More stuff here + // Burada daha fazla ลŸey var } } ``` @@ -193,7 +193,7 @@ Uygulamanฤฑzฤฑn her request iรงin kullandฤฑฤŸฤฑ mevcut `root_path` deฤŸerini ala Burada sadece gรถstermek iรงin bunu mesaja dahil ediyoruz. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Ardฤฑndan Uvicorn'u ลŸu ลŸekilde baลŸlatฤฑrsanฤฑz: @@ -220,7 +220,7 @@ Response ลŸรถyle bir ลŸey olur: Alternatif olarak, `--root-path` gibi bir komut satฤฑrฤฑ seรงeneฤŸi (veya muadili) saฤŸlayamฤฑyorsanฤฑz, FastAPI uygulamanฤฑzฤฑ oluลŸtururken `root_path` parametresini ayarlayabilirsiniz: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} `FastAPI`'ye `root_path` vermek, Uvicorn veya Hypercorn'a `--root-path` komut satฤฑrฤฑ seรงeneฤŸini vermekle eลŸdeฤŸerdir. @@ -400,14 +400,14 @@ Ancak baลŸka alternatif `servers` da saฤŸlayabilirsiniz; รถrneฤŸin *aynฤฑ* docs ร–rneฤŸin: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} ลžรถyle bir OpenAPI ลŸemasฤฑ รผretir: ```JSON hl_lines="5-7" { "openapi": "3.1.0", - // More stuff here + // Burada daha fazla ลŸey var "servers": [ { "url": "/api/v1" @@ -422,7 +422,7 @@ Ancak baลŸka alternatif `servers` da saฤŸlayabilirsiniz; รถrneฤŸin *aynฤฑ* docs } ], "paths": { - // More stuff here + // Burada daha fazla ลŸey var } } ``` @@ -455,7 +455,7 @@ OpenAPI spesifikasyonunda `servers` รถzelliฤŸi opsiyoneldir. **FastAPI**'nin `root_path` kullanarak otomatik bir server eklemesini istemiyorsanฤฑz, `root_path_in_servers=False` parametresini kullanabilirsiniz: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} Bรถylece OpenAPI ลŸemasฤฑna dahil etmez. diff --git a/docs/tr/docs/advanced/custom-response.md b/docs/tr/docs/advanced/custom-response.md index c5148f4287..218a5de5cb 100644 --- a/docs/tr/docs/advanced/custom-response.md +++ b/docs/tr/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ Bรผyรผk response'larda, doฤŸrudan bir `Response` dรถndรผrmek bir dictionary dรถn Ancak dรถndรผrdรผฤŸรผnรผz iรงeriฤŸin **JSON ile serialize edilebilir** olduฤŸundan eminseniz, onu doฤŸrudan response classโ€™ฤฑna verebilir ve FastAPIโ€™nin response classโ€™ฤฑna vermeden รถnce dรถnรผลŸ iรงeriฤŸinizi `jsonable_encoder` iรงinden geรงirirken oluลŸturacaฤŸฤฑ ek yรผkten kaรงฤฑnabilirsiniz. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | Bilgi @@ -55,7 +55,7 @@ Ve OpenAPIโ€™de de bu ลŸekilde dokรผmante edilir. * `HTMLResponse` import edin. * *path operation decorator*โ€™ฤฑnฤฑzฤฑn `response_class` parametresi olarak `HTMLResponse` verin. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | Bilgi @@ -73,7 +73,7 @@ Ve OpenAPIโ€™de de bu ลŸekilde dokรผmante edilir. Yukarฤฑdaki รถrneฤŸin aynฤฑsฤฑ, bu sefer bir `HTMLResponse` dรถndรผrerek, ลŸรถyle gรถrรผnebilir: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | Uyarฤฑ @@ -97,7 +97,7 @@ Bu durumda `response_class` sadece OpenAPI *path operation*โ€™ฤฑnฤฑ dokรผmante e ร–rneฤŸin ลŸรถyle bir ลŸey olabilir: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} Bu รถrnekte `generate_html_response()` fonksiyonu, HTMLโ€™i bir `str` olarak dรถndรผrmek yerine zaten bir `Response` รผretip dรถndรผrmektedir. @@ -136,7 +136,7 @@ Bunu doฤŸrudan dรถndรผrebilirsiniz. FastAPI (aslฤฑnda Starlette) otomatik olarak bir Content-Length headerโ€™ฤฑ ekler. Ayrฤฑca `media_type`โ€™a gรถre bir Content-Type headerโ€™ฤฑ ekler ve text tรผrleri iรงin sona bir charset ekler. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ Yukarฤฑda okuduฤŸunuz gibi, bir miktar text veya bytes alฤฑr ve HTML response d Bir miktar text veya bytes alฤฑr ve dรผz metin response dรถndรผrรผr. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ Bunun iรงin `ujson` kurulmalฤฑdฤฑr; รถrneฤŸin `pip install ujson`. /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | ฤฐpucu @@ -194,13 +194,13 @@ HTTP redirect dรถndรผrรผr. Varsayฤฑlan olarak 307 status code (Temporary Redirec `RedirectResponse`โ€™u doฤŸrudan dรถndรผrebilirsiniz: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- Veya `response_class` parametresi iรงinde kullanabilirsiniz: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} Bunu yaparsanฤฑz, *path operation* functionโ€™ฤฑnฤฑzdan doฤŸrudan URL dรถndรผrebilirsiniz. @@ -210,13 +210,13 @@ Bu durumda kullanฤฑlan `status_code`, `RedirectResponse` iรงin varsayฤฑlan olan Ayrฤฑca `status_code` parametresini `response_class` parametresiyle birlikte kullanabilirsiniz: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } Bir async generator veya normal generator/iterator alฤฑr ve response bodyโ€™yi stream eder. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### `StreamingResponse`โ€™u file-like objelerle kullanma { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ Bรถylece รถnce hepsini memoryโ€™ye okumak zorunda kalmazsฤฑnฤฑz; bu generator fu Buna cloud storage ile etkileลŸime giren, video iลŸleyen ve benzeri birรงok kรผtรผphane dahildir. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. Bu generator functionโ€™dฤฑr. ฤฐรงinde `yield` ifadeleri olduฤŸu iรงin "generator function" denir. 2. Bir `with` bloฤŸu kullanarak, generator function bittiฤŸinde file-like objenin kapandฤฑฤŸฤฑndan emin oluruz. Yani response gรถndermeyi bitirdikten sonra kapanฤฑr. @@ -255,11 +255,11 @@ DiฤŸer response tรผrlerine gรถre instantiate ederken farklฤฑ argรผmanlar alฤฑr: File response'larฤฑ uygun `Content-Length`, `Last-Modified` ve `ETag` headerโ€™larฤฑnฤฑ iรงerir. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} `response_class` parametresini de kullanabilirsiniz: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} Bu durumda *path operation* functionโ€™ฤฑnฤฑzdan doฤŸrudan dosya path'ini dรถndรผrebilirsiniz. @@ -273,7 +273,7 @@ Diyelim ki girintili ve biรงimlendirilmiลŸ JSON dรถndรผrmek istiyorsunuz; bunun Bir `CustomORJSONResponse` oluลŸturabilirsiniz. Burada yapmanฤฑz gereken temel ลŸey, contentโ€™i `bytes` olarak dรถndรผren bir `Response.render(content)` metodu yazmaktฤฑr: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} Artฤฑk ลŸunu dรถndรผrmek yerine: @@ -299,7 +299,7 @@ Bunu tanฤฑmlayan parametre `default_response_class`โ€™tฤฑr. AลŸaฤŸฤฑdaki รถrnekte **FastAPI**, tรผm *path operations* iรงin varsayฤฑlan olarak `JSONResponse` yerine `ORJSONResponse` kullanฤฑr. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | ฤฐpucu diff --git a/docs/tr/docs/advanced/dataclasses.md b/docs/tr/docs/advanced/dataclasses.md index 2639760070..ed70a6a946 100644 --- a/docs/tr/docs/advanced/dataclasses.md +++ b/docs/tr/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ Bu durumda standart `dataclasses` yerine, drop-in replacement olan `pydantic.dat 6. Burada `items` iรงeren bir dictionary dรถndรผrรผyoruz; `items` bir dataclass listesi. - FastAPI, veriyi JSON'a serializing etmeyi yine baลŸarฤฑr. + FastAPI, veriyi JSON'a serileลŸtirmeyi yine baลŸarฤฑr. 7. Burada `response_model`, `Author` dataclass'larฤฑndan oluลŸan bir listenin type annotation'ฤฑnฤฑ kullanฤฑyor. diff --git a/docs/tr/docs/advanced/events.md b/docs/tr/docs/advanced/events.md index 257b952f95..cef8b42a53 100644 --- a/docs/tr/docs/advanced/events.md +++ b/docs/tr/docs/advanced/events.md @@ -30,7 +30,7 @@ Bu *startup* ve *shutdown* mantฤฑฤŸฤฑnฤฑ, `FastAPI` uygulamasฤฑnฤฑn `lifespan` p AลŸaฤŸฤฑdaki gibi `yield` kullanan async bir `lifespan()` fonksiyonu oluลŸturuyoruz: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} Burada, `yield` รถncesinde (sahte) model fonksiyonunu machine learning modellerini iรงeren dictionaryโ€™e koyarak, modeli yรผkleme gibi maliyetli bir *startup* iลŸlemini simรผle ediyoruz. Bu kod, *startup* sฤฑrasฤฑnda, uygulama **request almaya baลŸlamadan รถnce** รงalฤฑลŸtฤฑrฤฑlฤฑr. @@ -48,7 +48,7 @@ Belki yeni bir sรผrรผm baลŸlatmanฤฑz gerekiyordur, ya da รงalฤฑลŸtฤฑrmaktan sฤฑk Dikkat edilmesi gereken ilk ลŸey, `yield` iรงeren async bir fonksiyon tanฤฑmlฤฑyor olmamฤฑz. Bu, `yield` kullanan Dependenciesโ€™e oldukรงa benzer. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} Fonksiyonun `yield`โ€™den รถnceki kฤฑsmฤฑ, uygulama baลŸlamadan **รถnce** รงalฤฑลŸฤฑr. @@ -60,7 +60,7 @@ Bakarsanฤฑz, fonksiyon `@asynccontextmanager` ile dekore edilmiลŸ. Bu da fonksiyonu "**async context manager**" denen ลŸeye dรถnรผลŸtรผrรผr. -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} Pythonโ€™da **context manager**, `with` ifadesi iรงinde kullanabildiฤŸiniz bir yapฤฑdฤฑr. ร–rneฤŸin `open()` bir context manager olarak kullanฤฑlabilir: @@ -82,7 +82,7 @@ Yukarฤฑdaki kod รถrneฤŸimizde bunu doฤŸrudan kullanmฤฑyoruz; bunun yerine FastAP `FastAPI` uygulamasฤฑnฤฑn `lifespan` parametresi bir **async context manager** alฤฑr; dolayฤฑsฤฑyla oluลŸturduฤŸumuz yeni `lifespan` async context managerโ€™ฤฑnฤฑ buraya geรงebiliriz. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Alternatif Events (kullanฤฑmdan kaldฤฑrฤฑldฤฑ) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ Bu fonksiyonlar `async def` ile veya normal `def` ile tanฤฑmlanabilir. Uygulama baลŸlamadan รถnce รงalฤฑลŸtฤฑrฤฑlacak bir fonksiyon eklemek iรงin, `"startup"` eventโ€™i ile tanฤฑmlayฤฑn: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} Bu durumda `startup` event handler fonksiyonu, "database" รถฤŸesini (sadece bir `dict`) bazฤฑ deฤŸerlerle baลŸlatฤฑr. @@ -116,7 +116,7 @@ Ve tรผm `startup` event handlerโ€™larฤฑ tamamlanmadan uygulamanฤฑz request almay Uygulama kapanฤฑrken รงalฤฑลŸtฤฑrฤฑlacak bir fonksiyon eklemek iรงin, `"shutdown"` eventโ€™i ile tanฤฑmlayฤฑn: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Burada `shutdown` event handler fonksiyonu, `log.txt` dosyasฤฑna `"Application shutdown"` satฤฑrฤฑnฤฑ yazar. @@ -150,11 +150,11 @@ Bu nedenle artฤฑk bunun yerine, yukarฤฑda aรงฤฑklandฤฑฤŸฤฑ gibi `lifespan` kulla Meraklฤฑ nerdโ€™ler iรงin kรผรงรผk bir teknik detay. ๐Ÿค“ -Altta, ASGI teknik spesifikasyonunda bu, Lifespan Protocolโ€™รผn bir parรงasฤฑdฤฑr ve `startup` ile `shutdown` adฤฑnda eventโ€™ler tanฤฑmlar. +Altta, ASGI teknik spesifikasyonunda bu, Lifespan Protokolรผโ€™nรผn bir parรงasฤฑdฤฑr ve `startup` ile `shutdown` adฤฑnda eventโ€™ler tanฤฑmlar. /// info | Bilgi -Starlette `lifespan` handlerโ€™larฤฑ hakkฤฑnda daha fazlasฤฑnฤฑ Starlette's Lifespan docs iรงinde okuyabilirsiniz. +Starlette `lifespan` handlerโ€™larฤฑ hakkฤฑnda daha fazlasฤฑnฤฑ Starlette Lifespan dokรผmanlarฤฑ iรงinde okuyabilirsiniz. Ayrฤฑca kodunuzun baลŸka bรถlgelerinde de kullanฤฑlabilecek lifespan stateโ€™i nasฤฑl yรถneteceฤŸinizi de kapsar. diff --git a/docs/tr/docs/advanced/generate-clients.md b/docs/tr/docs/advanced/generate-clients.md index af278f2fef..f3d6038a8f 100644 --- a/docs/tr/docs/advanced/generate-clients.md +++ b/docs/tr/docs/advanced/generate-clients.md @@ -40,7 +40,7 @@ Bu รงรถzรผmlerin bazฤฑlarฤฑ aรงฤฑk kaynak olabilir veya รผcretsiz katman sunabil Basit bir FastAPI uygulamasฤฑyla baลŸlayalฤฑm: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} *Path operation*'larฤฑn, request payload ve response payload iรงin kullandฤฑklarฤฑ modelleri `Item` ve `ResponseMessage` modelleriyle tanฤฑmladฤฑklarฤฑna dikkat edin. @@ -98,7 +98,7 @@ Birรงok durumda FastAPI uygulamanฤฑz daha bรผyรผk olacaktฤฑr ve farklฤฑ *path op ร–rneฤŸin **items** iรงin bir bรถlรผm, **users** iรงin baลŸka bir bรถlรผm olabilir ve bunlarฤฑ tag'lerle ayฤฑrabilirsiniz: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Tag'lerle TypeScript Client รœretme { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ Bu fonksiyonu รถzelleลŸtirebilirsiniz. Bir `APIRoute` alฤฑr ve string dรถndรผrรผ Sonrasฤฑnda bu รถzel fonksiyonu `generate_unique_id_function` parametresiyle **FastAPI**'ye geรงebilirsiniz: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### ร–zel Operation ID'lerle TypeScript Client รœretme { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ Ancak รผretilen client iรงin, client'larฤฑ รผretmeden hemen รถnce OpenAPI operat OpenAPI JSON'u `openapi.json` diye bir dosyaya indirip, ลŸu tarz bir script ile **รถndeki tag'i kaldฤฑrabiliriz**: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/tr/docs/advanced/index.md b/docs/tr/docs/advanced/index.md index 3995109e25..ec43da6b3b 100644 --- a/docs/tr/docs/advanced/index.md +++ b/docs/tr/docs/advanced/index.md @@ -2,7 +2,7 @@ ## Ek ร–zellikler { #additional-features } -Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑ, **FastAPI**'ฤฑn tรผm temel รถzelliklerini tanฤฑmanฤฑz iรงin yeterli olmalฤฑdฤฑr. +Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑ, **FastAPI**'nin tรผm temel รถzelliklerini tanฤฑmanฤฑz iรงin yeterli olmalฤฑdฤฑr. Sonraki bรถlรผmlerde diฤŸer seรงenekleri, konfigรผrasyonlarฤฑ ve ek รถzellikleri gรถreceksiniz. @@ -16,6 +16,6 @@ Ve kullanฤฑm amacฤฑnฤฑza baฤŸlฤฑ olarak, รงรถzรผm bunlardan birinde olabilir. ## ร–nce Tutorial'ฤฑ Okuyun { #read-the-tutorial-first } -Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑndaki bilgilerle **FastAPI**'nฤฑn รงoฤŸu รถzelliฤŸini yine de kullanabilirsiniz. +Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasฤฑndaki bilgilerle **FastAPI**'nin รงoฤŸu รถzelliฤŸini yine de kullanabilirsiniz. Ve sonraki bรถlรผmler, onu zaten okuduฤŸunuzu ve bu temel fikirleri bildiฤŸinizi varsayar. diff --git a/docs/tr/docs/advanced/middleware.md b/docs/tr/docs/advanced/middleware.md index a22644a090..7c1fb54f6a 100644 --- a/docs/tr/docs/advanced/middleware.md +++ b/docs/tr/docs/advanced/middleware.md @@ -57,13 +57,13 @@ Gelen tรผm request'lerin `https` veya `wss` olmasฤฑnฤฑ zorunlu kฤฑlar. `http` veya `ws` olarak gelen herhangi bir request, bunun yerine gรผvenli ลŸemaya redirect edilir. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } HTTP Host Header saldฤฑrฤฑlarฤฑna karลŸฤฑ korunmak iรงin, gelen tรผm request'lerde `Host` header'ฤฑnฤฑn doฤŸru ayarlanmฤฑลŸ olmasฤฑnฤฑ zorunlu kฤฑlar. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} AลŸaฤŸฤฑdaki argรผmanlar desteklenir: @@ -78,7 +78,7 @@ Gelen bir request doฤŸru ลŸekilde doฤŸrulanmazsa `400` response gรถnderilir. Middleware hem standart hem de streaming response'larฤฑ ele alฤฑr. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} AลŸaฤŸฤฑdaki argรผmanlar desteklenir: diff --git a/docs/tr/docs/advanced/openapi-webhooks.md b/docs/tr/docs/advanced/openapi-webhooks.md index dd9e9bbe73..68b7e6f8d9 100644 --- a/docs/tr/docs/advanced/openapi-webhooks.md +++ b/docs/tr/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Webhook'lar OpenAPI 3.1.0 ve รผzeri sรผrรผmlerde mevcuttur; FastAPI `0.99.0` ve Bir **FastAPI** uygulamasฤฑ oluลŸturduฤŸunuzda, *webhook*'larฤฑ tanฤฑmlamak iรงin kullanabileceฤŸiniz bir `webhooks` attribute'u vardฤฑr; *path operation* tanฤฑmlar gibi, รถrneฤŸin `@app.webhooks.post()` ile. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} TanฤฑmladฤฑฤŸฤฑnฤฑz webhook'lar **OpenAPI** ลŸemasฤฑnda ve otomatik **docs UI**'da yer alฤฑr. diff --git a/docs/tr/docs/advanced/path-operation-advanced-configuration.md b/docs/tr/docs/advanced/path-operation-advanced-configuration.md index e326842d67..ad2c460955 100644 --- a/docs/tr/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/tr/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ OpenAPI konusunda "uzman" deฤŸilseniz, muhtemelen buna ihtiyacฤฑnฤฑz yok. Bunun her operation iรงin benzersiz olduฤŸundan emin olmanฤฑz gerekir. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### operationId olarak *path operation function* adฤฑnฤฑ kullanma { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ APIโ€™lerinizin function adlarฤฑnฤฑ `operationId` olarak kullanmak istiyorsanฤฑz Bunu, tรผm *path operation*โ€™larฤฑ ekledikten sonra yapmalฤฑsฤฑnฤฑz. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | ฤฐpucu @@ -40,7 +40,7 @@ Farklฤฑ modรผllerde (Python dosyalarฤฑnda) olsalar bile. Bir *path operation*โ€™ฤฑ รผretilen OpenAPI ลŸemasฤฑndan (dolayฤฑsฤฑyla otomatik dokรผmantasyon sistemlerinden) hariรง tutmak iรงin `include_in_schema` parametresini kullanฤฑn ve `False` yapฤฑn: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Docstringโ€™den ฤฐleri Dรผzey Aรงฤฑklama { #advanced-description-from-docstring } @@ -68,7 +68,7 @@ Uygulamanฤฑzda bir *path operation* tanฤฑmladฤฑฤŸฤฑnฤฑzda, **FastAPI** OpenAPI /// note | Teknik Detaylar -OpenAPI spesifikasyonunda buna Operation Object denir. +OpenAPI spesifikasyonunda buna Operation Nesnesi denir. /// @@ -90,9 +90,9 @@ Bir *path operation* iรงin OpenAPI ลŸemasฤฑnฤฑ `openapi_extra` parametresiyle ge ### OpenAPI Extensions { #openapi-extensions } -ร–rneฤŸin bu `openapi_extra`, [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) tanฤฑmlamak iรงin faydalฤฑ olabilir: +ร–rneฤŸin bu `openapi_extra`, [OpenAPI Uzantฤฑlarฤฑ](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) tanฤฑmlamak iรงin faydalฤฑ olabilir: -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Otomatik API dokรผmanlarฤฑnฤฑ aรงtฤฑฤŸฤฑnฤฑzda, extensionโ€™ฤฑnฤฑz ilgili *path operation*โ€™ฤฑn en altฤฑnda gรถrรผnรผr. @@ -139,9 +139,9 @@ Bรถylece otomatik รผretilen ลŸemaya ek veri ekleyebilirsiniz. Bunu `openapi_extra` ile yapabilirsiniz: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -Bu รถrnekte herhangi bir Pydantic model tanฤฑmlamadฤฑk. Hatta request body JSON olarak parsed bile edilmiyor; doฤŸrudan `bytes` olarak okunuyor ve `magic_data_reader()` fonksiyonu bunu bir ลŸekilde parse etmekten sorumlu oluyor. +Bu รถrnekte herhangi bir Pydantic model tanฤฑmlamadฤฑk. Hatta request body JSON olarak ayrฤฑลŸtฤฑrฤฑlmฤฑyor; doฤŸrudan `bytes` olarak okunuyor ve `magic_data_reader()` fonksiyonu bunu bir ลŸekilde parse etmekten sorumlu oluyor. Buna raฤŸmen, request body iรงin beklenen ลŸemayฤฑ tanฤฑmlayabiliriz. @@ -153,7 +153,7 @@ Ve bunu, request iรงindeki veri tipi JSON olmasa bile yapabilirsiniz. ร–rneฤŸin bu uygulamada, FastAPIโ€™nin Pydantic modellerinden JSON Schema รงฤฑkarmaya yรถnelik entegre iลŸlevselliฤŸini ve JSON iรงin otomatik doฤŸrulamayฤฑ kullanmฤฑyoruz. Hatta request content typeโ€™ฤฑnฤฑ JSON deฤŸil, YAML olarak tanฤฑmlฤฑyoruz: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Buna raฤŸmen, varsayฤฑlan entegre iลŸlevselliฤŸi kullanmasak da, YAML olarak almak istediฤŸimiz veri iรงin JSON Schemaโ€™yฤฑ manuel รผretmek รผzere bir Pydantic model kullanmaya devam ediyoruz. @@ -161,7 +161,7 @@ Ardฤฑndan requestโ€™i doฤŸrudan kullanฤฑp bodyโ€™yi `bytes` olarak รงฤฑkarฤฑyoru Sonrasฤฑnda kodumuzda bu YAML iรงeriฤŸini doฤŸrudan parse ediyor, ardฤฑndan YAML iรงeriฤŸini doฤŸrulamak iรงin yine aynฤฑ Pydantic modeli kullanฤฑyoruz: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | ฤฐpucu diff --git a/docs/tr/docs/advanced/response-change-status-code.md b/docs/tr/docs/advanced/response-change-status-code.md index 239c0dddd4..cc86cc0e3a 100644 --- a/docs/tr/docs/advanced/response-change-status-code.md +++ b/docs/tr/docs/advanced/response-change-status-code.md @@ -20,7 +20,7 @@ Bu tรผr durumlarda bir `Response` parametresi kullanabilirsiniz. Ardฤฑndan bu *geรงici (temporal)* `Response` nesnesi รผzerinde `status_code` deฤŸerini ayarlayabilirsiniz. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} Sonrasฤฑnda, normalde yaptฤฑฤŸฤฑnฤฑz gibi ihtiyacฤฑnฤฑz olan herhangi bir nesneyi dรถndรผrebilirsiniz (`dict`, bir veritabanฤฑ modeli, vb.). diff --git a/docs/tr/docs/advanced/response-cookies.md b/docs/tr/docs/advanced/response-cookies.md index d00bfc4cd0..526d6d3c67 100644 --- a/docs/tr/docs/advanced/response-cookies.md +++ b/docs/tr/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ Ardฤฑndan bu *geรงici* response nesnesi รผzerinde cookie'leri set edebilirsiniz. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} Sonrasฤฑnda normalde yaptฤฑฤŸฤฑnฤฑz gibi ihtiyaรง duyduฤŸunuz herhangi bir nesneyi dรถndรผrebilirsiniz (bir `dict`, bir veritabanฤฑ modeli vb.). @@ -24,9 +24,9 @@ Bunu yapmak iรงin, [DoฤŸrudan Response Dรถndรผrme](response-directly.md){.intern Sonra bunun iรงinde Cookie'leri set edin ve response'u dรถndรผrรผn: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip | ฤฐpucu +/// tip `Response` parametresini kullanmak yerine doฤŸrudan bir response dรถndรผrรผrseniz, FastAPI onu olduฤŸu gibi (doฤŸrudan) dรถndรผrรผr. diff --git a/docs/tr/docs/advanced/response-directly.md b/docs/tr/docs/advanced/response-directly.md index 332f1224fc..cadefbdde0 100644 --- a/docs/tr/docs/advanced/response-directly.md +++ b/docs/tr/docs/advanced/response-directly.md @@ -2,7 +2,7 @@ **FastAPI** ile bir *path operation* oluลŸturduฤŸunuzda, normalde ondan herhangi bir veri dรถndรผrebilirsiniz: bir `dict`, bir `list`, bir Pydantic model, bir veritabanฤฑ modeli vb. -Varsayฤฑlan olarak **FastAPI**, dรถndรผrdรผฤŸรผnรผz bu deฤŸeri [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑlan `jsonable_encoder` ile otomatik olarak JSON'a รงevirir. +Varsayฤฑlan olarak **FastAPI**, dรถndรผrdรผฤŸรผnรผz bu deฤŸeri [JSON Uyumlu Encoder](../tutorial/encoder.md){.internal-link target=_blank} bรถlรผmรผnde anlatฤฑlan `jsonable_encoder` ile otomatik olarak JSON'a รงevirir. Ardฤฑndan perde arkasฤฑnda, JSON-uyumlu bu veriyi (รถr. bir `dict`) client'a response gรถndermek iรงin kullanฤฑlacak bir `JSONResponse` iรงine yerleลŸtirir. @@ -54,12 +54,12 @@ Diyelim ki Marshmallow { #marshmallow } -API sistemlerinin ihtiyaรง duyduฤŸu temel รถzelliklerden biri, koddan (Python) veriyi alฤฑp aฤŸ รผzerinden gรถnderilebilecek bir ลŸeye dรถnรผลŸtรผrmek, yani veri โ€œdรถnรผลŸรผmโ€รผdรผr. ร–rneฤŸin, bir veritabanฤฑndan gelen verileri iรงeren bir objeyi JSON objesine dรถnรผลŸtรผrmek, `datetime` objelerini stringโ€™e รงevirmek vb. +API sistemlerinin ihtiyaรง duyduฤŸu temel รถzelliklerden biri, koddan (Python) veriyi alฤฑp aฤŸ รผzerinden gรถnderilebilecek bir ลŸeye dรถnรผลŸtรผrmek, yani veri โ€œdรถnรผลŸรผmโ€รผdรผr. ร–rneฤŸin, bir veritabanฤฑndan gelen verileri iรงeren bir objeyi JSON objesine dรถnรผลŸtรผrmek, `datetime` objelerini stringโ€™e รงevirmek vb. APIโ€™larฤฑn ihtiyaรง duyduฤŸu bir diฤŸer รถnemli รถzellik, veri doฤŸrulamadฤฑr; belirli parametreler gรถz รถnรผne alฤฑndฤฑฤŸฤฑnda verinin geรงerli olduฤŸundan emin olmak. ร–rneฤŸin, bir alanฤฑn `int` olmasฤฑ ve rastgele bir metin olmamasฤฑ. Bu รถzellikle dฤฑลŸarฤฑdan gelen veriler iรงin kullanฤฑลŸlฤฑdฤฑr. @@ -145,7 +145,7 @@ Bir veri doฤŸrulama sistemi olmadan, tรผm bu kontrolleri kod iรงinde el ile yapm Marshmallow, bu รถzellikleri saฤŸlamak iรงin inลŸa edildi. Harika bir kรผtรผphanedir ve geรงmiลŸte รงok kullandฤฑm. -Ancak Python tip belirteรงlerinden รถnce yazฤฑlmฤฑลŸtฤฑr. Dolayฤฑsฤฑyla her ลŸemayฤฑ tanฤฑmlamak iรงin Marshmallowโ€™un saฤŸladฤฑฤŸฤฑ belirli yardฤฑmcฤฑlar ve sฤฑnฤฑflar kullanฤฑlฤฑr. +Ancak Python tip belirteรงlerinden รถnce yazฤฑlmฤฑลŸtฤฑr. Dolayฤฑsฤฑyla her ลŸemayฤฑ tanฤฑmlamak iรงin Marshmallowโ€™un saฤŸladฤฑฤŸฤฑ belirli yardฤฑmcฤฑlar ve sฤฑnฤฑflar kullanฤฑlฤฑr. /// check | **FastAPI**'a ilham olan @@ -155,7 +155,7 @@ Kodla, veri tiplerini ve doฤŸrulamayฤฑ otomatik saฤŸlayan โ€œลŸemalarโ€ tanฤฑml ### Webargs { #webargs } -APIโ€™larฤฑn ihtiyaรง duyduฤŸu bir diฤŸer bรผyรผk รถzellik, gelen isteklerden veriyi ayrฤฑลŸtฤฑrmadฤฑr. +APIโ€™larฤฑn ihtiyaรง duyduฤŸu bir diฤŸer bรผyรผk รถzellik, gelen isteklerden veriyi ayrฤฑลŸtฤฑrmadฤฑr. Webargs, Flask dahil birkaรง frameworkโ€™รผn รผzerinde bunu saฤŸlamak iรงin geliลŸtirilmiลŸ bir araรงtฤฑr. @@ -417,7 +417,7 @@ Tรผm veri doฤŸrulama, veri dรถnรผลŸรผmรผ ve JSON Schema tabanlฤฑ otomatik model ### Starlette { #starlette } -Starlette, yรผksek performanslฤฑ asyncio servisleri oluลŸturmak iรงin ideal, hafif bir ASGI frameworkโ€™รผ/araรง takฤฑmฤฑdฤฑr. +Starlette, yรผksek performanslฤฑ asyncio servisleri oluลŸturmak iรงin ideal, hafif bir ASGI frameworkโ€™รผ/araรง takฤฑmฤฑdฤฑr. ร‡ok basit ve sezgiseldir. Kolayca geniลŸletilebilir ve modรผler bileลŸenlere sahip olacak ลŸekilde tasarlanmฤฑลŸtฤฑr. diff --git a/docs/tr/docs/async.md b/docs/tr/docs/async.md index 88fd763fce..c788d60a86 100644 --- a/docs/tr/docs/async.md +++ b/docs/tr/docs/async.md @@ -1,18 +1,18 @@ -# Concurrency ve async / await +# EลŸzamanlฤฑlฤฑk ve async / await { #concurrency-and-async-await } -*path operasyon fonksiyonu* iรงin `async def `sรถzdizimi, asenkron kod, eลŸzamanlฤฑlฤฑk ve paralellik hakkฤฑnda bazฤฑ ayrฤฑntฤฑlar. +*path operasyon fonksiyonlarฤฑ* iรงin `async def` sรถzdizimi hakkฤฑnda detaylar ve asenkron kod, eลŸzamanlฤฑlฤฑk (concurrency) ve paralellik รผzerine arka plan bilgisi. -## Aceleniz mi var? +## Aceleniz mi var? { #in-a-hurry } -TL;DR: +TL;DR: -EฤŸer `await` ile รงaฤŸrฤฑlmasฤฑ gerektiฤŸini belirten รผรงรผncรผ taraf kรผtรผphaneleri kullanฤฑyorsanฤฑz, รถrneฤŸin: +EฤŸer `await` ile รงaฤŸฤฑrmanฤฑz gerektiฤŸini sรถyleyen รผรงรผncรผ taraf kรผtรผphaneler kullanฤฑyorsanฤฑz, รถrneฤŸin: ```Python results = await some_library() ``` -O zaman *path operasyon fonksiyonunu* `async def` ile tanฤฑmlayฤฑn รถrneฤŸin: +O zaman *path operasyon fonksiyonlarฤฑnฤฑzฤฑ* aลŸaฤŸฤฑdaki gibi `async def` ile tanฤฑmlayฤฑn: ```Python hl_lines="2" @app.get('/') @@ -23,13 +23,13 @@ async def read_results(): /// note | Not -Sadece `async def` ile tanฤฑmlanan fonksiyonlar iรงinde `await` kullanabilirsiniz. +`await` yalnฤฑzca `async def` ile oluลŸturulan fonksiyonlarฤฑn iรงinde kullanฤฑlabilir. /// --- -EฤŸer bir veritabanฤฑ, bir API, dosya sistemi vb. ile iletiลŸim kuran bir รผรงรผncรผ taraf bir kรผtรผphane kullanฤฑyorsanฤฑz ve `await` kullanฤฑmฤฑnฤฑ desteklemiyorsa, (bu ลŸu anda รงoฤŸu veritabanฤฑ kรผtรผphanesi iรงin geรงerli bir durumdur), o zaman *path operasyon fonksiyonunuzu* `def` kullanarak normal bir ลŸekilde tanฤฑmlayฤฑn, รถrneฤŸin: +EฤŸer bir veritabanฤฑ, bir API, dosya sistemi vb. ile iletiลŸim kuran ve `await` desteฤŸi olmayan bir รผรงรผncรผ taraf kรผtรผphane kullanฤฑyorsanฤฑz (bu ลŸu anda รงoฤŸu veritabanฤฑ kรผtรผphanesi iรงin geรงerlidir), o zaman *path operasyon fonksiyonlarฤฑnฤฑzฤฑ* normal olarak `def` ile tanฤฑmlayฤฑn: ```Python hl_lines="2" @app.get('/') @@ -40,279 +40,307 @@ def results(): --- -EฤŸer uygulamanฤฑz (bir ลŸekilde) baลŸka bir ลŸeyle iletiลŸim kurmak ve onun cevap vermesini beklemek zorunda deฤŸilse, `async def` kullanฤฑn. +Uygulamanฤฑz (bir ลŸekilde) baลŸka bir ลŸeyle iletiลŸim kurmak ve onun yanฤฑtฤฑnฤฑ beklemek zorunda deฤŸilse, iรงinde `await` kullanmanฤฑz gerekmese bile `async def` kullanฤฑn. --- -Sadece bilmiyorsanฤฑz, normal `def` kullanฤฑn. +Emin deฤŸilseniz, normal `def` kullanฤฑn. --- -**Not**: *path operasyon fonksiyonlarฤฑnฤฑzda* `def` ve `async def`'i ihtiyaรง duyduฤŸunuz gibi karฤฑลŸtฤฑrabilir ve her birini sizin iรงin en iyi seรงeneฤŸi kullanarak tanฤฑmlayabilirsiniz. FastAPI onlarla doฤŸru olanฤฑ yapacaktฤฑr. +Not: *path operasyon fonksiyonlarฤฑnฤฑzda* `def` ve `async def`'i ihtiyacฤฑnฤฑz kadar karฤฑลŸtฤฑrabilirsiniz, her birini sizin iรงin en iyi seรงenekle tanฤฑmlayฤฑn. FastAPI onlar iรงin doฤŸru olanฤฑ yapacaktฤฑr. -Her neyse, yukarฤฑdaki durumlardan herhangi birinde, FastAPI yine de asenkron olarak รงalฤฑลŸacak ve son derece hฤฑzlฤฑ olacaktฤฑr. +Yukarฤฑdaki durumlarฤฑn herhangi birinde FastAPI yine de asenkron olarak รงalฤฑลŸฤฑr ve son derece hฤฑzlฤฑdฤฑr. -Ancak yukarฤฑdaki adฤฑmlarฤฑ takip ederek, bazฤฑ performans optimizasyonlarฤฑ yapฤฑlabilecektir. +Ancak yukarฤฑdaki adฤฑmlarฤฑ izleyerek bazฤฑ performans optimizasyonlarฤฑ mรผmkรผn olur. -## Teknik Detaylar +## Teknik Detaylar { #technical-details } -Python'un modern versiyonlarฤฑnda **`async` ve `await`** sรถzdizimi ile **"coroutines"** kullanan **"asenkron kod"** desteฤŸine sahiptir. +Pythonโ€™un modern sรผrรผmleri, **`async` ve `await`** sรถzdizimiyle, **"coroutines"** denilen bir yapฤฑyฤฑ kullanarak **"asenkron kod"** desteฤŸine sahiptir. -Bu ifadeyi aลŸaฤŸฤฑdaki bรถlรผmlerde daha da ayrฤฑntฤฑlฤฑ aรงฤฑklayalฤฑm: +AลŸaฤŸฤฑdaki bรถlรผmlerde bu ifadeyi parรงa parรงa ele alalฤฑm: -* **Asenkron kod** +* **Asenkron Kod** * **`async` ve `await`** -* **Coroutines** +* **Coroutine'ler** -## Asenkron kod +## Asenkron Kod { #asynchronous-code } -Asenkron kod programlama dilinin ๐Ÿ’ฌ bilgisayara / programa ๐Ÿค– kodun bir noktasฤฑnda, *baลŸka bir kodun* bir yerde bitmesini ๐Ÿค– beklemesi gerektiฤŸini sรถylemenin bir yoludur. Bu *baลŸka koda* "slow-file" denir ๐Ÿ“. +Asenkron kod, dilin ๐Ÿ’ฌ bilgisayara / programa ๐Ÿค– kodun bir noktasฤฑnda, bir yerde *baลŸka bir ลŸeyin* bitmesini beklemesi gerektiฤŸini sรถylemesinin bir yoludur. Diyelim ki bu *baลŸka ลŸeye* "slow-file" ๐Ÿ“ diyoruz. -Bรถylece, bu sรผreรงte bilgisayar "slow-file" ๐Ÿ“ tamamlanฤฑrken gidip baลŸka iลŸler yapabilir. +Bu sฤฑrada bilgisayar, "slow-file" ๐Ÿ“ biterken gidip baลŸka iลŸler yapabilir. -Sonra bilgisayar / program ๐Ÿค– her fฤฑrsatฤฑ olduฤŸunda o noktada yaptฤฑฤŸฤฑ tรผm iลŸleri ๐Ÿค– bitirene kadar geri dรถnรผcek. Ve ๐Ÿค– yapmasฤฑ gerekeni yaparak, beklediฤŸi gรถrevlerden herhangi birinin bitip bitmediฤŸini gรถrecek. +Sonra bilgisayar / program ๐Ÿค–, ya tekrar beklediฤŸi iรงin ya da o anda elindeki tรผm iลŸleri bitirdiฤŸinde fฤฑrsat buldukรงa geri gelir. Ve beklediฤŸi gรถrevlerden herhangi biri bittiyse, yapฤฑlmasฤฑ gerekenleri yapar. -Ardฤฑndan, ๐Ÿค– bitirmek iรงin ilk gรถrevi alฤฑr ("slow-file" ๐Ÿ“) ve onunla ne yapmasฤฑ gerekiyorsa onu devam ettirir. +Ardฤฑndan, ๐Ÿค– ilk biten gรถrevi alฤฑr (รถrneฤŸin bizim "slow-file" ๐Ÿ“) ve onunla yapmasฤฑ gerekenlere devam eder. -Bu "baลŸka bir ลŸey iรงin bekle" normalde, aลŸaฤŸฤฑdakileri beklemek gibi (iลŸlemcinin ve RAM belleฤŸinin hฤฑzฤฑna kฤฑyasla) nispeten "yavaลŸ" olan I/O iลŸlemlerine atฤฑfta bulunur: +Bu "baลŸka bir ลŸeyi beklemek" genelde iลŸlemci ve RAM hฤฑzฤฑna kฤฑyasla nispeten "yavaลŸ" olan I/O iลŸlemlerine atฤฑfta bulunur, รถrneฤŸin ลŸunlarฤฑ beklemek gibi: -* istemci tarafฤฑndan aฤŸ รผzerinden veri gรถndermek -* aฤŸ รผzerinden istemciye gรถnderilen veriler -* sistem tarafฤฑndan okunacak ve programฤฑnฤฑza verilecek bir dosya iรงeriฤŸi -* programฤฑnฤฑzฤฑn diske yazฤฑlmak รผzere sisteme verdiฤŸi dosya iรงerikleri +* istemciden verinin aฤŸ รผzerinden gelmesi +* programฤฑnฤฑzฤฑn gรถnderdiฤŸi verinin aฤŸ รผzerinden istemciye ulaลŸmasฤฑ +* diskteki bir dosyanฤฑn iรงeriฤŸinin sistem tarafฤฑndan okunup programฤฑnฤฑza verilmesi +* programฤฑnฤฑzฤฑn sisteme verdiฤŸi iรงeriฤŸin diske yazฤฑlmasฤฑ * uzak bir API iลŸlemi -* bir veritabanฤฑ bitirme iลŸlemi -* sonuรงlarฤฑ dรถndรผrmek iรงin bir veritabanฤฑ sorgusu +* bir veritabanฤฑ iลŸleminin bitmesi +* bir veritabanฤฑ sorgusunun sonuรง dรถndรผrmesi * vb. -Yรผrรผtme sรผresi รงoฤŸunlukla I/O iลŸlemleri beklenerek tรผketildiฤŸinden bunlara "I/O baฤŸlantฤฑlฤฑ" iลŸlemler denir. +ร‡alฤฑลŸma sรผresi รงoฤŸunlukla I/O iลŸlemlerini beklemekle geรงtiฤŸinden, bunlara "I/O bound" iลŸlemler denir. -Buna "asenkron" denir, รงรผnkรผ bilgisayar/program yavaลŸ gรถrevle "senkronize" olmak zorunda deฤŸildir, gรถrevin tam olarak biteceฤŸi anฤฑ bekler, hiรงbir ลŸey yapmadan, gรถrev sonucunu alabilmek ve รงalฤฑลŸmaya devam edebilmek iรงin . +"Bunun" asenkron" denmesinin sebebi, bilgisayarฤฑn / programฤฑn yavaลŸ gรถrevle "senkronize" olmak, gรถrev tam bittiฤŸi anda orada olup gรถrev sonucunu almak ve iลŸe devam etmek iรงin hiรงbir ลŸey yapmadan beklemek zorunda olmamasฤฑdฤฑr. -Bunun yerine, "asenkron" bir sistem olarak, bir kez bittiฤŸinde, bilgisayarฤฑn / programฤฑn yapmasฤฑ gerekeni bitirmesi iรงin biraz (birkaรง mikrosaniye) sฤฑrada bekleyebilir ve ardฤฑndan sonuรงlarฤฑ almak iรงin geri gelebilir ve onlarla รงalฤฑลŸmaya devam edebilir. +Bunun yerine "asenkron" bir sistem olarak, gรถrev bittiฤŸinde, bilgisayarฤฑn / programฤฑn o sฤฑrada yaptฤฑฤŸฤฑ iลŸi bitirmesi iรงin biraz (birkaรง mikrosaniye) sฤฑrada bekleyebilir ve sonra sonuรงlarฤฑ almak รผzere geri dรถnรผp onlarla รงalฤฑลŸmaya devam edebilir. -"Senkron" ("asenkron"un aksine) iรงin genellikle "sฤฑralฤฑ" terimini de kullanฤฑrlar, รงรผnkรผ bilgisayar/program, bu adฤฑmlar beklemeyi iรงerse bile, farklฤฑ bir gรถreve geรงmeden รถnce tรผm adฤฑmlarฤฑ sฤฑrayla izler. +"Senkron" (asenkronun tersi) iรงin genelde "sฤฑralฤฑ" terimi de kullanฤฑlฤฑr; รงรผnkรผ bilgisayar / program, farklฤฑ bir gรถreve geรงmeden รถnce tรผm adฤฑmlarฤฑ sฤฑrayla izler, bu adฤฑmlar beklemeyi iรงerse bile. +### EลŸzamanlฤฑlฤฑk ve Burgerler { #concurrency-and-burgers } -### EลŸzamanlฤฑlฤฑk (Concurrency) ve Burgerler +Yukarฤฑda anlatฤฑlan **asenkron** kod fikrine bazen **"eลŸzamanlฤฑlฤฑk"** (concurrency) da denir. **"Paralellik"**ten (parallelism) farklฤฑdฤฑr. +**EลŸzamanlฤฑlฤฑk** ve **paralellik**, "aynฤฑ anda az รงok birden fazla ลŸeyin olmasฤฑ" ile ilgilidir. -Yukarฤฑda aรงฤฑklanan bu **asenkron** kod fikrine bazen **"eลŸzamanlฤฑlฤฑk"** da denir. **"Paralellikten"** farklฤฑdฤฑr. +Ama *eลŸzamanlฤฑlฤฑk* ve *paralellik* arasฤฑndaki ayrฤฑntฤฑlar oldukรงa farklฤฑdฤฑr. -**EลŸzamanlฤฑlฤฑk** ve **paralellik**, "aynฤฑ anda az ya da รงok olan farklฤฑ iลŸler" ile ilgilidir. +Farkฤฑ gรถrmek iรงin burgerlerle ilgili ลŸu hikayeyi hayal edin: -Ancak *eลŸzamanlฤฑlฤฑk* ve *paralellik* arasฤฑndaki ayrฤฑntฤฑlar oldukรงa farklฤฑdฤฑr. +### EลŸzamanlฤฑ Burgerler { #concurrent-burgers } +AลŸkฤฑnla fast food almaya gidiyorsun, kasiyer senden รถnceki insanlarฤฑn sipariลŸlerini alฤฑrken sฤฑraya giriyorsun. ๐Ÿ˜ -Farkฤฑ gรถrmek iรงin burgerlerle ilgili aลŸaฤŸฤฑdaki hikayeyi hayal edin: + -### EลŸzamanlฤฑ Burgerler +Sonra sฤฑra size geliyor, sen ve aลŸkฤฑn iรงin 2 รงok havalฤฑ burger sipariลŸ ediyorsun. ๐Ÿ”๐Ÿ” - + -AลŸkฤฑnla beraber ๐Ÿ˜ dฤฑลŸarฤฑ hamburger yemeye รงฤฑktฤฑnฤฑz ๐Ÿ”, kasiyer ๐Ÿ’ รถndeki insanlardan sipariลŸ alฤฑrken siz sฤฑraya girdiniz. +Kasiyer, mutfaktaki aลŸรงฤฑya burgerlerini hazฤฑrlamalarฤฑ gerektiฤŸini sรถylรผyor (o an รถnceki mรผลŸterilerin burgerlerini hazฤฑrlฤฑyor olsalar bile). -Sฤฑra sizde ve sen aลŸkฤฑn ๐Ÿ˜ ve kendin iรงin 2 รงฤฑlgฤฑn hamburger ๐Ÿ” sรถylรผyorsun. + -ร–demeyi yaptฤฑn ๐Ÿ’ธ. +ร–deme yapฤฑyorsun. ๐Ÿ’ธ -Kasiyer ๐Ÿ’ mutfakdaki aลŸรงฤฑya ๐Ÿ‘จโ€๐Ÿณ hamburgerleri ๐Ÿ” hazฤฑrlamasฤฑ gerektiฤŸini sรถyler ve aลŸรงฤฑ bunu bilir (o an รถnceki mรผลŸterilerin sipariลŸlerini hazฤฑrlฤฑyor olsa bile). +Kasiyer sana sฤฑra numaranฤฑ veriyor. -Kasiyer ๐Ÿ’ size bir sฤฑra numarasฤฑ verir. + -Beklerken askฤฑnla ๐Ÿ˜ bir masaya oturur ve uzun bir sรผre konuลŸursunuz(Burgerleriniz รงok รงฤฑlgฤฑn olduฤŸundan ve hazฤฑrlanmasฤฑ biraz zaman alฤฑyor โœจ๐Ÿ”โœจ). +Beklerken aลŸkฤฑnla bir masa seรงip oturuyorsunuz, uzun uzun sohbet ediyorsunuz (burgerler baya havalฤฑ ve hazฤฑrlanmasฤฑ biraz zaman alฤฑyor). -Hamburgeri beklerkenki zamanฤฑ ๐Ÿ”, aลŸkฤฑnฤฑn ne kadar zeki ve tatlฤฑ olduฤŸuna hayran kalarak harcayabilirsin โœจ๐Ÿ˜โœจ. +Masada aลŸkฤฑnla otururken, burgerleri beklerken, o zamanฤฑ aลŸkฤฑnฤฑn ne kadar harika, tatlฤฑ ve zeki olduฤŸuna hayran kalarak geรงirebilirsin โœจ๐Ÿ˜โœจ. -AลŸkฤฑnla ๐Ÿ˜ konuลŸurken arada sฤฑranฤฑn size gelip gelmediฤŸini kontrol ediyorsun. + -Nihayet sฤฑra size geldi. Tezgaha gidip hamburgerleri ๐Ÿ”kapฤฑp masaya geri dรถnรผyorsun. +Bekler ve sohbet ederken, ara ara tezgรขhtaki numaraya bakฤฑp sฤฑranฤฑn size gelip gelmediฤŸini kontrol ediyorsun. -AลŸkฤฑnla hamburgerlerinizi yiyor ๐Ÿ” ve iyi vakit geรงiriyorsunuz โœจ. +Bir noktada, nihayet sฤฑra size geliyor. Tezgรขha gidiyor, burgerleri alฤฑp masaya dรถnรผyorsun. + + + +AลŸkฤฑnla burgerleri yiyip gรผzel vakit geรงiriyorsunuz. โœจ + + + +/// info | Bilgi + +Harika รงizimler: Ketrina Thompson. ๐ŸŽจ + +/// --- -Bu hikayedeki bilgisayar / program ๐Ÿค– olduฤŸunuzu hayal edin. +Bu hikรขyede bilgisayar / program ๐Ÿค– olduฤŸunu hayal et. -Sฤฑrada beklerken boลŸtasฤฑn ๐Ÿ˜ด, sฤฑranฤฑ beklerken herhangi bir "รผretim" yapmฤฑyorsun. Ama bu sฤฑra hฤฑzlฤฑ รงรผnkรผ kasiyer sadece sipariลŸleri alฤฑyor (onlarฤฑ hazฤฑrlamฤฑyor), burada bir sฤฑknฤฑtฤฑ yok. +Sฤฑradayken sadece boลŸtasฤฑn ๐Ÿ˜ด, sฤฑranฤฑ bekliyorsun, รงok "รผretken" bir ลŸey yapmฤฑyorsun. Ama sorun yok, รงรผnkรผ kasiyer sadece sipariลŸ alฤฑyor (hazฤฑrlamฤฑyor), bu yรผzden sฤฑra hฤฑzlฤฑ ilerliyor. -Sonra sฤฑra size geldiฤŸinde gerรงekten "รผretken" iลŸler yapabilirsiniz ๐Ÿค“, menรผyรผ oku, ne istediฤŸine larar ver, aลŸkฤฑnฤฑn seรงimini al ๐Ÿ˜, รถde ๐Ÿ’ธ, doฤŸru kartฤฑ รงฤฑkart, รถdemeyi kontrol et, faturayฤฑ kontrol et, sipariลŸin doฤŸru olup olmadฤฑฤŸฤฑnฤฑ kontrol et, vb. +Sฤฑra sana geldiฤŸinde gerรงekten "รผretken" iลŸler yapฤฑyorsun: menรผyรผ iลŸliyorsun, ne istediฤŸine karar veriyorsun, aลŸkฤฑnฤฑn seรงimini alฤฑyorsun, รถdรผyorsun, doฤŸru para ya da kartฤฑ verdiฤŸini kontrol ediyorsun, doฤŸru รผcretlendirildiฤŸini kontrol ediyorsun, sipariลŸ kalemlerinin doฤŸru olduฤŸunu kontrol ediyorsun, vb. -Ama hamburgerler ๐Ÿ” hazฤฑr olmamasฤฑna raฤŸmen Kasiyer ๐Ÿ’ ile iลŸiniz "duraklฤฑyor" โธ, รงรผnkรผ hamburgerlerin hazฤฑr olmasฤฑnฤฑ bekliyoruz ๐Ÿ•™. +Ama sonra, burgerlerin hรขlรข gelmemiลŸ olsa da, kasiyerle olan iลŸin "duraklatฤฑlฤฑyor" โธ, รงรผnkรผ burgerlerin hazฤฑr olmasฤฑnฤฑ ๐Ÿ•™ beklemen gerekiyor. -Ama tezgahtan uzaklaลŸฤฑp sฤฑranฤฑz gelene kadarmasanฤฑza dรถnebilir ๐Ÿ”€ ve dikkatinizi aลŸkฤฑnฤฑza ๐Ÿ˜ verebilirsiniz vr bunun รผzerine "รงalฤฑลŸabilirsiniz" โฏ ๐Ÿค“. Artฤฑk "รผretken" birลŸey yapฤฑyorsunuz ๐Ÿค“, sevgilinle ๐Ÿ˜ flรถrt eder gibi. +Fakat tezgรขhtan uzaklaลŸฤฑp masada sฤฑra numaranla oturduฤŸun iรงin, dikkatinizi ๐Ÿ”€ aลŸkฤฑna รงevirebilir, onunla "รงalฤฑลŸmaya" โฏ ๐Ÿค“ odaklanabilirsin. Yani yine รงok "รผretken" bir ลŸey yapฤฑyorsun, aลŸkฤฑnla flรถrt etmek gibi ๐Ÿ˜. -Kasiyer ๐Ÿ’ "Hamburgerler hazฤฑr !" ๐Ÿ” dediฤŸinde ve gรถrรผntรผlenen numara sizin numaranฤฑz olduฤŸunda hemen koลŸup hamburgerlerinizi almaya รงalฤฑลŸmฤฑyorsunuz. Biliyorsunuzki kimse sizin hamburgerlerinizi ๐Ÿ” รงalmayacak รงรผnkรผ sฤฑra sizin. +Ardฤฑndan kasiyer ๐Ÿ’, tezgรขh ekranฤฑna numaranฤฑ koyarak "burgerleri bitirdim" diyor; ama numara seninki olduฤŸunda รงฤฑlgฤฑnca sฤฑรงramฤฑyorsun. Sฤฑra numaran sende, herkesin kendi numarasฤฑ var; kimse burgerlerini รงalamaz. -Yani AลŸkฤฑnฤฑzฤฑn๐Ÿ˜ hikayeyi bitirmesini bekliyorsunuz (รงalฤฑลŸmayฤฑ bitir โฏ / gรถrev iลŸleniyor.. ๐Ÿค“), nazikรงe gรผlรผmseyin ve hamburger yemeye gittiฤŸinizi sรถyleyin โธ. +Bu yรผzden aลŸkฤฑnฤฑn hikรขyeyi bitirmesini (mevcut iลŸi โฏ / iลŸlenen gรถrevi ๐Ÿค“ bitirmesini) bekliyor, nazikรงe gรผlรผmsรผyor ve burgerleri almaya gittiฤŸini sรถylรผyorsun โธ. -Ardฤฑndan tezgaha ๐Ÿ”€, ลŸimdi biten ilk gรถreve โฏ gidin, Hamburgerleri ๐Ÿ” alฤฑn, teลŸekkรผr edin ve masaya gรถtรผrรผn. sayacฤฑn bu adฤฑmฤฑ tamamlanฤฑr โน. Bu da yeni bir gรถrev olan "hamburgerleri ye" ๐Ÿ”€ โฏ gรถrevini baลŸlatฤฑrken "hamburgerleri al" โน gรถrevini bitirir. +Sonra tezgรขha ๐Ÿ”€ gidip artฤฑk bitmiลŸ olan ilk gรถreve โฏ dรถnรผyor, burgerleri alฤฑyor, teลŸekkรผr ediyor ve masaya getiriyorsun. Tezgรขhla etkileลŸimin bu adฤฑmฤฑ / gรถrevi bรถylece bitiyor โน. Bu da yeni bir gรถrev olan "burgerleri yemek" ๐Ÿ”€ โฏ gรถrevini oluลŸturuyor, ama "burgerleri almak" gรถrevi tamamlandฤฑ โน. -### Parallel Hamburgerler +### Paralel Burgerler { #parallel-burgers } -ลžimdi bunlarฤฑn "EลŸzamanlฤฑ Hamburger" deฤŸil, "Paralel Hamburger" olduฤŸunu dรผลŸรผnelim. +ลžimdi bunlarฤฑn "EลŸzamanlฤฑ Burgerler" deฤŸil, "Paralel Burgerler" olduฤŸunu hayal edelim. -Hamburger ๐Ÿ” almak iรงin ๐Ÿ˜ aลŸkฤฑnla Paralel fast food'a gidiyorsun. +AลŸkฤฑnla paralel fast food almaya gidiyorsun. -Birden fazla kasiyer varken (varsayalฤฑm 8) sฤฑraya girdiniz๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ve sฤฑranฤฑz gelene kadar bekliyorsunuz. +Aynฤฑ anda aลŸรงฤฑ da olan birden fazla (8 diyelim) kasiyerin, senden รถnceki insanlarฤฑn sipariลŸlerini aldฤฑฤŸฤฑ bir sฤฑrada bekliyorsun. -Sizden รถnceki herkez ayrฤฑlmadan รถnce hamburgerlerinin ๐Ÿ” hazฤฑr olmasฤฑnฤฑ bekliyor ๐Ÿ•™. ร‡รผnkรผ kasiyerlerin her biri bir hamburger hazฤฑrlanmadan รถnce bir sonraki sipariลŸe geรงmiiyor. +Senden รถnceki herkes, tezgรขhtan ayrฤฑlmadan รถnce burgerlerinin hazฤฑrlanmasฤฑnฤฑ bekliyor; รงรผnkรผ 8 kasiyerin her biri bir sonraki sipariลŸe geรงmeden รถnce burgeri hemen gidip hazฤฑrlฤฑyor. -Sonunda senin sฤฑran, aลŸkฤฑn ๐Ÿ˜ ve kendin iรงin 2 hamburger ๐Ÿ” sipariลŸi verdiniz. + -ร–demeyi yaptฤฑnฤฑz ๐Ÿ’ธ. +Sonunda sฤฑra size geliyor, sen ve aลŸkฤฑn iรงin 2 รงok havalฤฑ burger sipariลŸi veriyorsun. -Kasiyer mutfaฤŸa gider ๐Ÿ‘จโ€๐Ÿณ. +ร–dรผyorsun ๐Ÿ’ธ. -Sฤฑrada bekliyorsunuz ๐Ÿ•™, kimse sizin burgerinizi ๐Ÿ” almaya รงalฤฑลŸmฤฑyor รงรผnkรผ sฤฑra sizin. + -Sen ve aลŸkฤฑn ๐Ÿ˜ sฤฑranฤฑzฤฑ korumak ve hamburgerleri almakla o kadar meลŸgulsรผnรผz ki birbirinize vakit ๐Ÿ•™ ayฤฑramฤฑyorsunuz ๐Ÿ˜ž. +Kasiyer mutfaฤŸa gidiyor. -ฤฐลŸte bu "senkron" รงalฤฑลŸmadฤฑr. Kasiyer/aลŸรงฤฑ ๐Ÿ‘จโ€๐Ÿณile senkron hareket ediyorsunuz. Bu yรผzden beklemek ๐Ÿ•™ ve kasiyer/aลŸรงฤฑ burgeri ๐Ÿ”bitirip size getirdiฤŸinde orda olmak zorundasฤฑnฤฑz yoksa baลŸka biri alabilir. +Tezgรขhฤฑn รถnรผnde ayakta ๐Ÿ•™ bekliyorsun; sฤฑra numarasฤฑ olmadฤฑฤŸฤฑndan, burgerlerini senden รถnce kimsenin almamasฤฑ iรงin orada durman gerekiyor. -Sonra kasiyeri/aลŸรงฤฑ ๐Ÿ‘จโ€๐Ÿณ nihayet hamburgerlerinizle ๐Ÿ”, uzun bir sรผre sonra ๐Ÿ•™ tezgaha geri geliyor. + -Burgerlerinizi ๐Ÿ” al ve aลŸkฤฑnla masanฤฑza doฤŸru ilerle ๐Ÿ˜. +Sen ve aลŸkฤฑn, kimsenin รถnรผnรผze geรงip burgerler gelince almamasฤฑ iรงin meลŸgul olduฤŸunuzdan, aลŸkฤฑna dikkatini veremiyorsun. ๐Ÿ˜ž -Sadece burgerini yiyorsun ๐Ÿ” ve bitti โน. +Bu "senkron" bir iลŸtir; kasiyer/aลŸรงฤฑ ๐Ÿ‘จโ€๐Ÿณ ile "senkronize"sin. ๐Ÿ•™ Beklemen ve kasiyer/aลŸรงฤฑ ๐Ÿ‘จโ€๐Ÿณ burgerleri bitirip sana verdiฤŸi anda tam orada olman gerekir; yoksa bir baลŸkasฤฑ alabilir. -Bekleyerek รงok fazla zaman geรงtiฤŸinden ๐Ÿ•™ konuลŸmaya รงok fazla vakit kalmadฤฑ ๐Ÿ˜ž. + ---- +Sonra kasiyer/aลŸรงฤฑ ๐Ÿ‘จโ€๐Ÿณ, uzun sรผre tezgรขhฤฑn รถnรผnde ๐Ÿ•™ bekledikten sonra nihayet burgerlerinle geri geliyor. + + + +Burgerleri alฤฑyor ve aลŸkฤฑnla masaya gidiyorsun. + +Sadece yiyorsunuz ve iลŸ bitiyor. โน -Paralel burger senaryosunda ise, siz iki iลŸlemcili birer robotsunuz ๐Ÿค– (sen ve sevgilin ๐Ÿ˜), Beklฤฑyorsunuz ๐Ÿ•™ hem konuลŸarak gรผzel vakit geรงirirken โฏ hem de sฤฑranฤฑzฤฑ bekliyorsunuz ๐Ÿ•™. + -MaฤŸazada ise 8 iลŸlemci bulunuyor (Kasiyer/aลŸรงฤฑ) ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ. EลŸzamanlฤฑ burgerde yalnฤฑzca 2 kiลŸi olabiliyordu (bir kasiyer ve bir aลŸรงฤฑ) ๐Ÿ’ ๐Ÿ‘จโ€๐Ÿณ. +Vaktin รงoฤŸu tezgรขhฤฑn รถnรผnde ๐Ÿ•™ beklemekle geรงtiฤŸinden, pek konuลŸma ya da flรถrt olmadฤฑ. ๐Ÿ˜ž -Ama yine de bu en iyisi deฤŸil ๐Ÿ˜ž. +/// info | Bilgi + +Harika รงizimler: Ketrina Thompson. ๐ŸŽจ + +/// --- -Bu hikaye burgerler ๐Ÿ” iรงin paralel. +Bu paralel burger senaryosunda, ikiniz (sen ve aลŸkฤฑn) iki iลŸlemcili bir bilgisayar / programsฤฑnฤฑz ๐Ÿค–; ikiniz de uzun sรผre tezgรขhta "bekleme" iลŸine ๐Ÿ•™ dikkat โฏ ayฤฑrฤฑyorsunuz. + +Fast food dรผkkรขnฤฑnda 8 iลŸlemci var (kasiyer/aลŸรงฤฑlar). EลŸzamanlฤฑ burger dรผkkรขnฤฑnda yalnฤฑzca 2 kiลŸi olabilir (bir kasiyer ve bir aลŸรงฤฑ). + +Ama yine de nihai deneyim pek iyi deฤŸil. ๐Ÿ˜ž -Bir gerรงek hayat รถrneฤŸi verelim. Bir banka hayal edin. +--- -Bankalarฤฑn รงoฤŸunda birkaรง kasiyer ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ve uzun bir sฤฑra var ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™. +Bu, burgerler iรงin paralel karลŸฤฑlฤฑk gelen hikรขye olurdu. ๐Ÿ” -Tรผm iลŸi sฤฑrayla bir mรผลŸteri ile yapan tรผm kasiyerler ๐Ÿ‘จโ€๐Ÿ’ผโฏ. +Daha "gerรงek hayat" bir รถrnek iรงin, bir banka hayal edin. -Ve uzun sรผre kuyrukta beklemek ๐Ÿ•™ zorundasฤฑn yoksa sฤฑranฤฑ kaybedersin. +Yakฤฑn zamana kadar, bankalarฤฑn รงoฤŸunda birden รงok giลŸe memuru ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ve uzun bir sฤฑra ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™ vardฤฑ. -Muhtemelen ayak iลŸlerฤฑ yaparken sevgilini ๐Ÿ˜ bankaya ๐Ÿฆ getirmezsin. +Tรผm giลŸe memurlarฤฑ bir mรผลŸteriyle tรผm iลŸi yapar, sonra sฤฑradakiyle ๐Ÿ‘จโ€๐Ÿ’ผโฏ. -### Burger Sonucu +Ve sฤฑranฤฑ kaybetmemek iรงin uzun sรผre ๐Ÿ•™ kuyrukta beklemen gerekir. -Bu "aลŸkฤฑnla fast food burgerleri" senaryosunda, รงok fazla bekleme olduฤŸu iรงin ๐Ÿ•™, eลŸzamanlฤฑ bir sisteme sahip olmak รงok daha mantฤฑklฤฑ โธ๐Ÿ”€โฏ. +Muhtemelen, bankada ๐Ÿฆ iลŸlerini hallederken aลŸkฤฑnฤฑ ๐Ÿ˜ yanฤฑnda gรถtรผrmek istemezsin. -Web uygulamalarฤฑnฤฑn รงoฤŸu iรงin durum bรถyledir. +### Burger Sonucu { #burger-conclusion } -Pek รงok kullanฤฑcฤฑ var, ama sunucunuz pek de iyi olmayan bir baฤŸlantฤฑ ile istek atmalarฤฑnฤฑ bekliyor. +"Fast food burgerleri ve aลŸkฤฑn" senaryosunda, รงok fazla bekleme ๐Ÿ•™ olduฤŸundan, eลŸzamanlฤฑ bir sistem โธ๐Ÿ”€โฏ รงok daha mantฤฑklฤฑdฤฑr. -Ve sonra yanฤฑtlarฤฑn geri gelmesi iรงin tekrar ๐Ÿ•™ bekliyor +Bu, รงoฤŸu web uygulamasฤฑ iรงin de geรงerlidir. -Bu "bekleme" ๐Ÿ•™ mikrosaniye cinsinden รถlรงรผlรผr, yine de, hepsini toplarsak รงok fazla bekleme var. +ร‡ok fazla kullanฤฑcฤฑ vardฤฑr; ancak sunucunuz, iyi olmayan baฤŸlantฤฑlarฤฑndan gelen istekleri ๐Ÿ•™ bekler. -Bu nedenle, web API'leri iรงin asenkron โธ๐Ÿ”€โฏ kod kullanmak รงok daha mantฤฑklฤฑ. +Ve sonra yanฤฑtlarฤฑn geri gelmesini yine ๐Ÿ•™ bekler. -Mevcut popรผler Python frameworklerinin รงoฤŸu (Flask ve Django gibi), Python'daki yeni asenkron รถzellikler mevcut olmadan รถnce yazฤฑldฤฑ. Bu nedenle, daฤŸฤฑtฤฑlma biรงimleri paralel yรผrรผtmeyi ve yenisi kadar gรผรงlรผ olmayan eski bir eลŸzamansฤฑz yรผrรผtme biรงimini destekler. +Bu "beklemeler" ๐Ÿ•™ mikrosaniyelerle รถlรงรผlรผr; ama hepsi toplandฤฑฤŸฤฑnda sonuรงta oldukรงa fazla bekleme olur. -Asenkron web (ASGI) รถzelliฤŸi, WebSockets iรงin destek eklemek iรงin Django'ya eklenmiลŸ olsa da. +Bu yรผzden web APIโ€™leri iรงin asenkron โธ๐Ÿ”€โฏ kod kullanmak รงok mantฤฑklฤฑdฤฑr. -Asenkron รงalฤฑลŸabilme NodeJS in popรผler olmasฤฑnฤฑn sebebi (paralel olamasa bile) ve Go dilini gรผรงlรผ yapan รถzelliktir. +Bu tรผr asenkronluk, NodeJSโ€™i popรผler yapan ลŸeydir (NodeJS paralel olmasa bile) ve Go dilinin gรผcรผdรผr. -Ve bu **FastAPI** ile elde ettiฤŸiniz performans dรผzeyiyle aynฤฑdฤฑr. +Ve **FastAPI** ile elde ettiฤŸiniz performans seviyesi de budur. -Aynฤฑ anda paralellik ve asenkronluฤŸa sahip olabildiฤŸiniz iรงin, test edilen NodeJS รงerรงevelerinin รงoฤŸundan daha yรผksek performans elde edersiniz ve C'ye daha yakฤฑn derlenmiลŸ bir dil olan Go ile eลŸit bir performans elde edersiniz (bรผtรผn teลŸekkรผrler Starlette'e ). +Ayrฤฑca, aynฤฑ anda hem paralellik hem de asenkronluk kullanabildiฤŸiniz iรงin, test edilen รงoฤŸu NodeJS frameworkโ€™รผnden daha yรผksek ve Cโ€™ye daha yakฤฑn derlenen bir dil olan Go ile baลŸa baลŸ performans elde edersiniz (hepsi Starlette sayesinde). -### EลŸzamanlฤฑlฤฑk paralellikten daha mฤฑ iyi? +### EลŸzamanlฤฑlฤฑk paralellikten daha mฤฑ iyi? { #is-concurrency-better-than-parallelism } -Hayฤฑr! Hikayenin ahlakฤฑ bu deฤŸil. +Hayฤฑr! Hikรขyenin รถzรผ bu deฤŸil. -EลŸzamanlฤฑlฤฑk paralellikten farklฤฑdฤฑr. Ve รงok fazla bekleme iรงeren **belirli** senaryolarda daha iyidir. Bu nedenle, genellikle web uygulamalarฤฑ iรงin paralellikten รงok daha iyidir. Ama her ลŸey iรงin deฤŸil. +EลŸzamanlฤฑlฤฑk paralellikten farklฤฑdฤฑr. Ve รงok fazla bekleme iรงeren **belirli** senaryolarda daha iyidir. Bu nedenle, genellikle web uygulamasฤฑ geliลŸtirme iรงin paralellikten รงok daha iyidir. Ama her ลŸey iรงin deฤŸil. -Yanฤฑ, bunu aklฤฑnฤฑzda oturtmak iรงin aลŸaฤŸฤฑdaki kฤฑsa hikayeyi hayal edin: +Bunu dengelemek iรงin, ลŸu kฤฑsa hikรขyeyi hayal edin: -> Bรผyรผk, kirli bir evi temizlemelisin. +> Bรผyรผk, kirli bir evi temizlemen gerekiyor. -*Evet, tรผm hikaye bu*. +*Evet, tรผm hikรขye bu kadar*. --- -Beklemek yok ๐Ÿ•™. Hiรงbir yerde. Sadece evin birden fazla yerinde yapฤฑlacak fazlasฤฑyla iลŸ var. +Hiรงbir yerde ๐Ÿ•™ bekleme yok; sadece evin birden fazla yerinde yapฤฑlacak รงok iลŸ var. -You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting ๐Ÿ•™ for anything, just cleaning and cleaning, the turns wouldn't affect anything. -Hamburger รถrneฤŸindeki gibi dรถnรผลŸleriniz olabilir, รถnce oturma odasฤฑ, sonra mutfak, ama hiรงbir ลŸey iรงin ๐Ÿ•™ beklemediฤŸinizden, sadece temizlik, temizlik ve temizlik, dรถnรผลŸler hiรงbir ลŸeyi etkilemez. +Hamburger รถrneฤŸindeki gibi dรถnรผลŸlerle ilerleyebilirsin, รถnce salon, sonra mutfak; ama hiรงbir ลŸey ๐Ÿ•™ beklemediฤŸin iรงin, sadece temizlik yaptฤฑฤŸฤฑndan, dรถnรผลŸlerin hiรงbir etkisi olmaz. -Sฤฑralฤฑ veya sฤฑrasฤฑz (eลŸzamanlฤฑlฤฑk) bitirmek aynฤฑ zaman alฤฑr ve aynฤฑ miktarda iลŸi yaparsฤฑnฤฑz. +DรถnรผลŸlerle ya da dรถnรผลŸsรผz (eลŸzamanlฤฑlฤฑk) bitirmek aynฤฑ zaman alฤฑr ve aynฤฑ miktarda iลŸ yapmฤฑลŸ olursun. -Ama bu durumda, 8 eski kasiyer/aลŸรงฤฑ - yeni temizlikรงiyi getirebilseydiniz ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ve her birini (artฤฑ siz) evin bir bรถlgesini temizlemek iรงin gรถrevlendirseydiniz, ekstra yardฤฑmla tรผm iลŸleri **paralel** olarak yapabilir ve รงok daha erken bitirebilirdiniz. +Ama bu durumda, 8 eski kasiyer/aลŸรงฤฑโ€”yeni temizlikรงiyi getirip her birine (artฤฑ sana) evin bir bรถlรผmรผnรผ versen, fazladan yardฤฑmla tรผm iลŸleri **paralel** yaparak รงok daha รงabuk bitirebilirdin. -Bu senaryoda, temizlikรงilerin her biri (siz dahil) birer iลŸlemci olacak ve รผzerine dรผลŸeni yapacaktฤฑr. +Bu senaryoda, her bir temizlikรงi (sen dรขhil) birer iลŸlemci olur ve kendi iลŸ payฤฑnฤฑ yapar. -Yรผrรผtme sรผresinin รงoฤŸu (beklemek yerine) iลŸ yapฤฑldฤฑฤŸฤฑndan ve bilgisayardaki iลŸ bir CPU tarafฤฑndan yapฤฑldฤฑฤŸฤฑndan, bu sorunlara "CPU bound" diyorlar". +Ve yรผrรผtme sรผresinin รงoฤŸu gerรงek iลŸten (bekleme yerine) oluลŸtuฤŸu ve bilgisayardaki iลŸi bir CPU yaptฤฑฤŸฤฑ iรงin, bu sorunlara "CPU bound" denir. --- -CPU'ya baฤŸlฤฑ iลŸlemlerin yaygฤฑn รถrnekleri, karmaลŸฤฑk matematik iลŸlemleri gerektiren iลŸlerdir. +CPUโ€™ya baฤŸlฤฑ iลŸlemlerin yaygฤฑn รถrnekleri, karmaลŸฤฑk matematiksel iลŸlem gerektiren iลŸ yรผkleridir. ร–rneฤŸin: * **Ses** veya **gรถrรผntรผ iลŸleme**. -* **Bilgisayar gรถrรผsรผ**: bir gรถrรผntรผ milyonlarca pikselden oluลŸur, her pikselin 3 deฤŸeri / rengi vardฤฑr, bu pikseller รผzerinde aynฤฑ anda bir ลŸeyler hesaplamayฤฑ gerektiren iลŸleme. -* **Makine ร–ฤŸrenimi**: ร‡ok sayฤฑda "matris" ve "vektรถr" รงarpฤฑmฤฑ gerektirir. Sayฤฑlarฤฑ olan ve hepsini aynฤฑ anda รงarpan bรผyรผk bir elektronik tablo dรผลŸรผnรผn. -* **Derin ร–ฤŸrenme**: Bu, Makine ร–ฤŸreniminin bir alt alanฤฑdฤฑr, dolayฤฑsฤฑyla aynฤฑsฤฑ geรงerlidir. Sadece รงarpฤฑlacak tek bir sayฤฑ tablosu deฤŸil, bรผyรผk bir sayฤฑ kรผmesi vardฤฑr ve รงoฤŸu durumda bu modelleri oluลŸturmak ve/veya kullanmak iรงin รถzel iลŸlemciler kullanฤฑrsฤฑnฤฑz. +* **Bilgisayar gรถrรผsรผ**: bir gรถrรผntรผ milyonlarca pikselden oluลŸur, her pikselin 3 deฤŸeri / rengi vardฤฑr; iลŸleme genellikle bu pikseller รผzerinde aynฤฑ anda bir ลŸeyler hesaplamayฤฑ gerektirir. +* **Makine ร–ฤŸrenimi**: genellikle รงok sayฤฑda "matris" ve "vektรถr" รงarpฤฑmฤฑ gerekir. Sayฤฑlar iรงeren devasa bir elektronik tabloyu ve hepsini aynฤฑ anda รงarpmayฤฑ dรผลŸรผnรผn. +* **Derin ร–ฤŸrenme**: Makine ร–ฤŸreniminin bir alt alanฤฑdฤฑr, dolayฤฑsฤฑyla aynฤฑsฤฑ geรงerlidir. Sadece รงarpฤฑlacak tek bir sayฤฑ tablosu deฤŸil, kocaman bir sayฤฑ kรผmesi vardฤฑr ve รงoฤŸu durumda bu modelleri kurmak ve/veya kullanmak iรงin รถzel iลŸlemciler kullanฤฑrsฤฑnฤฑz. -### EลŸzamanlฤฑlฤฑk + Paralellik: Web + Makine ร–ฤŸrenimi +### EลŸzamanlฤฑlฤฑk + Paralellik: Web + Makine ร–ฤŸrenimi { #concurrency-parallelism-web-machine-learning } -**FastAPI** ile web geliลŸtirme iรงin รงok yaygฤฑn olan eลŸzamanlฤฑlฤฑktan yararlanabilirsiniz (NodeJS'in aynฤฑ รงekiciliฤŸi). +**FastAPI** ile web geliลŸtirmede รงok yaygฤฑn olan eลŸzamanlฤฑlฤฑktan (NodeJSโ€™in baลŸlฤฑca cazibesiyle aynฤฑ) yararlanabilirsiniz. -Ancak, Makine ร–ฤŸrenimi sistemlerindekile gibi **CPU'ya baฤŸlฤฑ** iลŸ yรผkleri iรงin paralellik ve รงoklu iลŸlemenin (birden รงok iลŸlemin paralel olarak รงalฤฑลŸmasฤฑ) avantajlarฤฑndan da yararlanabilirsiniz. +Ama ayrฤฑca **CPUโ€™ya baฤŸlฤฑ** iลŸ yรผkleri (Makine ร–ฤŸrenimi sistemlerindeki gibi) iรงin paralellik ve รงoklu iลŸlemden (paralel รงalฤฑลŸan birden รงok iลŸlem) de yararlanabilirsiniz. -Buna ek olarak Python'un **Veri Bilimi**, Makine ร–ฤŸrenimi ve รถzellikle Derin ร–ฤŸrenme iรงin ana dil olduฤŸu gerรงeฤŸi, FastAPI'yi Veri Bilimi / Makine ร–ฤŸrenimi web API'leri ve uygulamalarฤฑ iรงin รงok iyi bir seรงenek haline getirir. +Buna ek olarak Pythonโ€™un **Veri Bilimi**, Makine ร–ฤŸrenimi ve รถzellikle Derin ร–ฤŸrenme iรงin ana dil olmasฤฑ, FastAPIโ€™yi Veri Bilimi / Makine ร–ฤŸrenimi web APIโ€™leri ve uygulamalarฤฑ iรงin รงok iyi bir seรงenek yapar. -Production'da nasฤฑl oldugunu gรถrmek iรงin ลŸu bรถlรผme bakฤฑn [Deployment](deployment/index.md){.internal-link target=_blank}. +Productionโ€™da bu paralelliฤŸi nasฤฑl saฤŸlayacaฤŸฤฑnฤฑzฤฑ gรถrmek iรงin [Deployment](deployment/index.md){.internal-link target=_blank} bรถlรผmรผne bakฤฑn. -## `async` ve `await` +## `async` ve `await` { #async-and-await } -Python'un modern sรผrรผmleri, asenkron kodu tanฤฑmlamanฤฑn รงok sezgisel bir yoluna sahiptir. Bu, normal "sequentฤฑal" (sฤฑralฤฑ) kod gibi gรถrรผnmesini ve doฤŸru anlarda sizin iรงin "awaฤฑt" ile bekleme yapmasฤฑnฤฑ saฤŸlar. +Pythonโ€™un modern sรผrรผmleri, asenkron kodu tanฤฑmlamak iรงin oldukรงa sezgisel bir yol sunar. Bu sayede kod normal "sฤฑralฤฑ" kod gibi gรถrรผnรผr ve doฤŸru anlarda sizin yerinize "beklemeyi" yapar. -Sonuรงlarฤฑ vermeden รถnce beklemeyi gerektirecek ve yeni Python รถzelliklerini destekleyen bir iลŸlem olduฤŸunda aลŸaฤŸฤฑdaki gibi kodlayabilirsiniz: +Sonuรงlarฤฑ vermeden รถnce bekleme gerektiren ve bu yeni Python รถzelliklerini destekleyen bir iลŸlem olduฤŸunda, ลŸรถyle kodlayabilirsiniz: ```Python burgers = await get_burgers(2) ``` -Buradaki `await` anahtari Python'a, sonuรงlarฤฑ `burgers` degiskenine atamadan รถnce `get_burgers(2)` kodunun iลŸini bitirmesini ๐Ÿ•™ beklemesi gerektiฤŸini sรถyler. Bununla Python, bu ara zamanda baลŸka bir ลŸey ๐Ÿ”€ โฏ yapabileceฤŸini bilecektir (baลŸka bir istek almak gibi). +Buradaki kilit nokta `await`. Pythonโ€™a, sonuรงlarฤฑ `burgers` deฤŸiลŸkenine koymadan รถnce `get_burgers(2)` รงalฤฑลŸmasฤฑnฤฑn bitmesini ๐Ÿ•™ beklemesi โธ gerektiฤŸini sรถyler. Bรถylece Python, bu arada baลŸka bir ลŸey ๐Ÿ”€ โฏ yapabileceฤŸini bilir (รถr. baลŸka bir request almak gibi). - `await`kodunun รงalฤฑลŸmasฤฑ iรงin, eลŸzamansฤฑzlฤฑฤŸฤฑ destekleyen bir fonksiyonun iรงinde olmasฤฑ gerekir. Bunu da yapmak iรงin fonksiyonu `async def` ile tanฤฑmlamamฤฑz yeterlidir: +`await`โ€™in รงalฤฑลŸabilmesi iรงin, bu asenkronluฤŸu destekleyen bir fonksiyonun iรงinde olmasฤฑ gerekir. Bunu yapmak iรงin fonksiyonu `async def` ile tanฤฑmlayฤฑn: ```Python hl_lines="1" async def get_burgers(number: int): - # burgerleri oluลŸturmak iรงin asenkron birkaรง iลŸ + # Burgerleri yaratmak iรงin bazฤฑ asenkron iลŸler yap return burgers ``` ...`def` yerine: ```Python hl_lines="2" -# bu kod asenkron deฤŸil +# Bu asenkron deฤŸildir def get_sequential_burgers(number: int): - # burgerleri oluลŸturmak iรงin senkron bฤฑrkaรง iลŸ + # Burgerleri yaratmak iรงin bazฤฑ sฤฑralฤฑ iลŸler yap return burgers ``` -`async def` ile Python, bu fonksฤฑyonun iรงinde, `await` ifadelerinin farkฤฑnda olmasฤฑ gerektiฤŸini ve รงalฤฑลŸma zamanฤฑ gelmeden รถnce bu iลŸlevin yรผrรผtรผlmesini "duraklatabileceฤŸini" ve baลŸka bir ลŸey yapabileceฤŸini ๐Ÿ”€ bilir. +`async def` ile Python, bu fonksiyonun iรงinde `await` ifadelerinin olabileceฤŸini bilir ve bu fonksiyonun yรผrรผtรผlmesini "duraklatฤฑp" โธ baลŸka bir ลŸey yapabileceฤŸini ๐Ÿ”€, sonra geri dรถnebileceฤŸini anlar. -`async def` fonksiyonunu รงaฤŸฤฑrmak istediฤŸinizde, onu "awaฤฑt" ฤฑle kullanmanฤฑz gerekir. Yani, bu iลŸe yaramaz: +`async def` fonksiyonunu รงaฤŸฤฑrmak istediฤŸinizde, onu "await" etmeniz gerekir. Yani ลŸu รงalฤฑลŸmaz: ```Python -# Bu iลŸe yaramaz, รงรผnkรผ get_burgers, ลŸu ลŸekilde tanฤฑmlandฤฑ: async def +# Bu รงalฤฑลŸmaz, รงรผnkรผ get_burgers ลŸรถyle tanฤฑmlandฤฑ: async def burgers = get_burgers(2) ``` --- -Bu nedenle, size onu `await` ile รงaฤŸฤฑrabileceฤŸinizi sรถyleyen bir kitaplฤฑk kullanฤฑyorsanฤฑz, onu `async def` ile tanฤฑmlanan *path fonksiyonu* iรงerisinde kullanmanฤฑz gerekir, รถrneฤŸin: +Dolayฤฑsฤฑyla, `await` ile รงaฤŸrฤฑlabileceฤŸini sรถyleyen bir kรผtรผphane kullanฤฑyorsanฤฑz, onu kullanan *path operasyon fonksiyonunu* `async def` ile oluลŸturmanฤฑz gerekir, รถrneฤŸin: ```Python hl_lines="2-3" @app.get('/burgers') @@ -321,87 +349,96 @@ async def read_burgers(): return burgers ``` -### Daha fazla teknik detay +### Daha teknik detaylar { #more-technical-details } + +`await`โ€™in yalnฤฑzca `async def` ile tanฤฑmlanan fonksiyonlarฤฑn iรงinde kullanฤฑlabildiฤŸini fark etmiลŸ olabilirsiniz. + +Aynฤฑ zamanda, `async def` ile tanฤฑmlanan fonksiyonlarฤฑn da "await" edilmesi gerekir. Yani `async def` ile tanฤฑmlanan fonksiyonlar yalnฤฑzca `async def` ile tanฤฑmlanan fonksiyonlarฤฑn iรงinde รงaฤŸrฤฑlabilir. + +Peki, tavuk-yumurta meselesi: ilk `async` fonksiyon nasฤฑl รงaฤŸrฤฑlฤฑr? + +**FastAPI** ile รงalฤฑลŸฤฑyorsanฤฑz bunu dert etmenize gerek yok; รงรผnkรผ o "ilk" fonksiyon sizin *path operasyon fonksiyonunuz* olacaktฤฑr ve FastAPI doฤŸru olanฤฑ yapmasฤฑnฤฑ bilir. -`await` in yalnฤฑzca `async def` ile tanฤฑmlanan fonksฤฑyonlarฤฑn iรงinde kullanฤฑlabileceฤŸini fark etmiลŸsinizdir. +Ama FastAPI olmadan da `async` / `await` kullanmak isterseniz, bunu da yapabilirsiniz. -Ama aynฤฑ zamanda, `async def` ile tanฤฑmlanan fonksiyonlarฤฑn "await" ile beklenmesi gerekir. Bu nedenle, "`async def` iรงeren fonksiyonlar yalnฤฑzca "`async def` ile tanฤฑmlanan fonksiyonlarฤฑn iรงinde รงaฤŸrฤฑlabilir. +### Kendi async kodunuzu yazฤฑn { #write-your-own-async-code } +Starlette (ve **FastAPI**) AnyIO รผzerine kuruludur; bu sayede Python standart kรผtรผphanesindeki asyncio ve Trio ile uyumludur. -Yani yumurta mฤฑ tavukdan, tavuk mu yumurtadan gibi ilk `async` fonksiyonu nasฤฑl รงaฤŸฤฑrฤฑlฤฑr? +ร–zellikle, kendi kodunuzda daha geliลŸmiลŸ desenler gerektiren ileri seviye eลŸzamanlฤฑlฤฑk kullanฤฑm senaryolarฤฑ iรงin doฤŸrudan AnyIO kullanabilirsiniz. -**FastAPI** ile รงalฤฑลŸฤฑyorsanฤฑz bunun iรงin endiลŸelenmenize gerek yok, รงรผnkรผ bu "ilk" fonksiyon sizin *path fonksiyonunuz* olacak ve FastAPI doฤŸru olanฤฑ nasฤฑl yapacaฤŸฤฑnฤฑ bilecek. +Hatta FastAPI kullanmฤฑyor olsanฤฑz bile, yรผksek uyumluluk ve avantajlarฤฑ (รถr. *structured concurrency*) iรงin AnyIO ile kendi async uygulamalarฤฑnฤฑzฤฑ yazabilirsiniz. -Ancak FastAPI olmadan `async` / `await` kullanmak istiyorsanฤฑz, resmi Python belgelerini kontrol edin. +AnyIOโ€™nun รผzerine, tรผr aรงฤฑklamalarฤฑnฤฑ biraz iyileลŸtirmek ve daha iyi **otomatik tamamlama**, **satฤฑr iรงi hatalar** vb. elde etmek iรงin ince bir katman olarak baลŸka bir kรผtรผphane daha oluลŸturdum. Ayrฤฑca **kendi async kodunuzu** anlamanฤฑza ve yazmanฤฑza yardฤฑmcฤฑ olacak dostรงa bir giriลŸ ve eฤŸitim iรงerir: Asyncer. ร–zellikle **async kodu normal** (bloklayan/senkron) **kodla birleลŸtirmeniz** gerektiฤŸinde faydalฤฑ olacaktฤฑr. -### Asenkron kodun diฤŸer biรงimleri +### Asenkron kodun diฤŸer biรงimleri { #other-forms-of-asynchronous-code } -Bu `async` ve `await` kullanimi oldukรงa yenidir. +`async` ve `await` kullanma tarzฤฑ, dilde nispeten yenidir. -Ancak asenkron kodla รงalฤฑลŸmayฤฑ รงok daha kolay hale getirir. +Ama asenkron kodla รงalฤฑลŸmayฤฑ รงok daha kolaylaลŸtฤฑrฤฑr. -Aynฤฑ sรถzdizimi (hemen hemen aynฤฑ) son zamanlarda JavaScript'in modern sรผrรผmlerine de dahil edildi (Tarayฤฑcฤฑ ve NodeJS'de). +Aynฤฑ (ya da neredeyse aynฤฑ) sรถzdizimi yakฤฑn zamanda modern JavaScript sรผrรผmlerine (Tarayฤฑcฤฑ ve NodeJS) de eklendi. -Ancak bundan รถnce, asenkron kodu iลŸlemek oldukรงa karmaลŸฤฑk ve zordu. +Bundan รถnce, asenkron kodu ele almak oldukรงa daha karmaลŸฤฑk ve zordu. -Python'un รถnceki sรผrรผmlerinde, threadlerฤฑ veya Gevent kullanฤฑyor olabilirdin. Ancak kodu anlamak, hata ayฤฑklamak ve dรผลŸรผnmek รงok daha karmaลŸฤฑk olurdu. +Pythonโ€™un รถnceki sรผrรผmlerinde threadโ€™ler veya Gevent kullanabilirdiniz. Ama kodu anlamak, hata ayฤฑklamak ve รผzerine dรผลŸรผnmek รงok daha zordu. -NodeJS / Browser JavaScript'in รถnceki sรผrรผmlerinde, "callback" kullanฤฑrdฤฑnฤฑz. Bu da "callbacks cehennemine" yol aรงar. +NodeJS / Tarayฤฑcฤฑ JavaScriptโ€™in รถnceki sรผrรผmlerinde "callback" kullanฤฑrdฤฑnฤฑz. Bu da "callback cehennemi"ne yol aรงardฤฑ. -## Coroutine'ler +## Coroutine'ler { #coroutines } -**Coroutine**, bir `async def` fonksiyonu tarafฤฑndan dรถndรผrรผlen deฤŸer iรงin รงok sรผslรผ bir terimdir. Python bunun bir fonksiyon gibi bir noktada baลŸlayฤฑp biteceฤŸini bilir, ancak iรงinde bir `await` olduฤŸunda dahili olarak da duraklatฤฑlabilir โธ. +**Coroutine**, bir `async def` fonksiyonunun dรถndรผrdรผฤŸรผ ลŸeye verilen sรผslรผ isimdir. Python bunun bir fonksiyona benzer bir ลŸey olduฤŸunu, bir noktada baลŸlayฤฑp biteceฤŸini bilir; ama iรงinde bir `await` olduฤŸunda dahili olarak duraklatฤฑlabileceฤŸini โธ de bilir. -Ancak, `async` ve `await` ile asenkron kod kullanmanฤฑn tรผm bu iลŸlevselliฤŸi, รงoฤŸu zaman "Coroutine" kullanmak olarak adlandฤฑrฤฑlฤฑr. Go'nun ana รถzelliฤŸi olan "Goroutines" ile karลŸฤฑlaลŸtฤฑrฤฑlabilir. +`async` ve `await` ile asenkron kod kullanmanฤฑn bu iลŸlevselliฤŸi รงoฤŸu zaman "coroutine" kullanmak olarak รถzetlenir. Goโ€™nun ana kilit รถzelliฤŸi olan "Goroutines" ile karลŸฤฑlaลŸtฤฑrฤฑlabilir. -## Sonuรง +## Sonuรง { #conclusion } -Aynฤฑ ifadeyi yukarฤฑdan gรถrelim: +Yukarฤฑdaki cรผmleyi tekrar gรถrelim: -> Python'ฤฑn modern sรผrรผmleri, **"async" ve "await"** sรถzdizimi ile birlikte **"coroutines"** adlฤฑ bir รถzelliฤŸi kullanan **"asenkron kod"** desteฤŸine sahiptir. +> Pythonโ€™un modern sรผrรผmleri, **`async` ve `await`** sรถzdizimiyle, **"coroutines"** denilen bir yapฤฑyฤฑ kullanarak **"asenkron kod"** desteฤŸine sahiptir. -ลžimdi daha mantฤฑklฤฑ gelmeli. โœจ +Artฤฑk daha anlamlฤฑ gelmeli. โœจ -FastAPI'ye (Starlette aracฤฑlฤฑฤŸฤฑyla) gรผรง veren ve bu kadar etkileyici bir performansa sahip olmasฤฑnฤฑ saฤŸlayan ลŸey budur. +Bunlarฤฑn hepsi, FastAPIโ€™ye (Starlette aracฤฑlฤฑฤŸฤฑyla) gรผรง verir ve bรถylesine etkileyici bir performansa sahip olmasฤฑnฤฑ saฤŸlar. -## ร‡ok Teknik Detaylar +## ร‡ok Teknik Detaylar { #very-technical-details } -/// warning +/// warning | Uyarฤฑ -Muhtemelen burayฤฑ atlayabilirsiniz. +Bรผyรผk ihtimalle burayฤฑ atlayabilirsiniz. -Bunlar, **FastAPI**'nin altta nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna dair รงok teknik ayrฤฑntฤฑlardฤฑr. +Bunlar, **FastAPI**โ€™nin altฤฑnda nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑna dair oldukรงa teknik ayrฤฑntฤฑlardฤฑr. -Biraz teknik bilginiz varsa (co-routines, threads, blocking, vb)ve FastAPI'nin "async def" ile normal "def" arasฤฑndaki farkฤฑ nasฤฑl iลŸlediฤŸini merak ediyorsanฤฑz, devam edin. +Coroutineโ€™ler, threadโ€™ler, blocking vb. hakkฤฑnda teknik bilginiz varsa ve FastAPIโ€™nin `async def` ile normal `def` arasฤฑndaki farkฤฑ nasฤฑl ele aldฤฑฤŸฤฑnฤฑ merak ediyorsanฤฑz, devam edin. /// -### Path fonksiyonu +### Path Operasyon Fonksiyonlarฤฑ { #path-operation-functions } -"async def" yerine normal "def" ile bir *yol iลŸlem iลŸlevi* bildirdiฤŸinizde, doฤŸrudan รงaฤŸrฤฑlmak yerine (sunucuyu bloke edeceฤŸinden) daha sonra beklenen harici bir iลŸ parรงacฤฑฤŸฤฑ havuzunda รงalฤฑลŸtฤฑrฤฑlฤฑr. +Bir *path operasyon fonksiyonunu* `async def` yerine normal `def` ile tanฤฑmladฤฑฤŸฤฑnฤฑzda, (sunucuyu bloklayacaฤŸฤฑndan) doฤŸrudan รงaฤŸrฤฑlmak yerine, harici bir thread poolโ€™da รงalฤฑลŸtฤฑrฤฑlฤฑr ve ardฤฑndan beklenir. -Yukarฤฑda aรงฤฑklanan ลŸekilde รงalฤฑลŸmayan baลŸka bir asenkron framework'den geliyorsanฤฑz ve kรผรงรผk bir performans kazancฤฑ (yaklaลŸฤฑk 100 nanosaniye) iรงin "def" ile *path fonksiyonu* tanฤฑmlamaya alฤฑลŸkฤฑnsanฤฑz, **FastAPI**'de tam tersi olacaฤŸฤฑnฤฑ unutmayฤฑn. Bu durumlarda, *path fonksiyonu* G/ร‡ engelleyen durum oluลŸturmadฤฑkรงa "async def" kullanmak daha iyidir. +Yukarฤฑda aรงฤฑklanan ลŸekilde รงalฤฑลŸmayan baลŸka bir async frameworkโ€™ten geliyorsanฤฑz ve ufak bir performans kazancฤฑ (yaklaลŸฤฑk 100 nanosaniye) iรงin yalnฤฑzca hesaplama yapan basit *path operasyon fonksiyonlarฤฑnฤฑ* dรผz `def` ile tanฤฑmlamaya alฤฑลŸkฤฑnsanฤฑz, **FastAPI**โ€™de etkinin tam tersi olacaฤŸฤฑnฤฑ unutmayฤฑn. Bu durumlarda, *path operasyon fonksiyonlarฤฑnฤฑz* bloklayan I/O yapan kod kullanmadฤฑkรงa `async def` kullanmak daha iyidir. -Yine de, her iki durumda da, **FastAPI**'nin รถnceki frameworkden [hala daha hฤฑzlฤฑ](index.md#performans){.internal-link target=_blank} (veya en azฤฑndan karลŸฤฑlaลŸtฤฑrฤฑlabilir) olma olasฤฑlฤฑฤŸฤฑ vardฤฑr. +Yine de her iki durumda da, **FastAPI**โ€™nin รถnceki frameworkโ€™รผnรผzden [hala daha hฤฑzlฤฑ](index.md#performance){.internal-link target=_blank} (ya da en azฤฑndan karลŸฤฑlaลŸtฤฑrฤฑlabilir) olmasฤฑ muhtemeldir. -### Bagฤฑmlฤฑlฤฑklar +### BaฤŸฤฑmlฤฑlฤฑklar { #dependencies } -Aynฤฑsฤฑ baฤŸฤฑmlฤฑlฤฑklar iรงin de geรงerlidir. Bir baฤŸฤฑmlฤฑlฤฑk, "async def" yerine standart bir "def" iลŸleviyse, harici iลŸ parรงacฤฑฤŸฤฑ havuzunda รงalฤฑลŸtฤฑrฤฑlฤฑr. +Aynฤฑsฤฑ [baฤŸฤฑmlฤฑlฤฑklar](tutorial/dependencies/index.md){.internal-link target=_blank} iรงin de geรงerlidir. Bir baฤŸฤฑmlฤฑlฤฑk `async def` yerine standart bir `def` fonksiyonuysa, harici thread poolโ€™da รงalฤฑลŸtฤฑrฤฑlฤฑr. -### Alt-baฤŸฤฑmlฤฑklar +### Alt-baฤŸฤฑmlฤฑlฤฑklar { #sub-dependencies } -Birbirini gerektiren (fonksiyonlarin parametreleri olarak) birden fazla baฤŸฤฑmlฤฑlฤฑk ve alt baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑz olabilir, bazฤฑlarฤฑ 'async def' ve bazฤฑlarฤฑ normal 'def' ile oluลŸturulabilir. Yine de normal 'def' ile oluลŸturulanlar, "await" kulanilmadan harici bir iลŸ parรงacฤฑฤŸฤฑnda (iลŸ parรงacฤฑฤŸฤฑ havuzundan) รงaฤŸrฤฑlฤฑr. +Birbirini gerektiren birden รงok baฤŸฤฑmlฤฑlฤฑk ve [alt-baฤŸฤฑmlฤฑlฤฑk](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} olabilir (fonksiyon tanฤฑmlarฤฑnฤฑn parametreleri olarak). Bazฤฑlarฤฑ `async def` ile, bazฤฑlarฤฑ normal `def` ile oluลŸturulmuลŸ olabilir. Yine de รงalฤฑลŸฤฑr ve normal `def` ile oluลŸturulanlar "await" edilmek yerine harici bir threadโ€™de (thread poolโ€™dan) รงaฤŸrฤฑlฤฑr. -### DiฤŸer yardฤฑmcฤฑ fonksiyonlar +### DiฤŸer yardฤฑmcฤฑ fonksiyonlar { #other-utility-functions } -DoฤŸrudan รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑz diฤŸer herhangi bir yardฤฑmcฤฑ fonksiyonu, normal "def" veya "async def" ile tanimlayabilirsiniz. FastAPI onu รงaฤŸฤฑrma ลŸeklinizi etkilemez. +DoฤŸrudan รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑz diฤŸer yardฤฑmcฤฑ fonksiyonlarฤฑ normal `def` veya `async def` ile tanฤฑmlayabilirsiniz ve FastAPI onlarฤฑ รงaฤŸฤฑrma biรงiminizi etkilemez. -Bu, FastAPI'nin sizin iรงin รงaฤŸฤฑrdฤฑฤŸฤฑ fonksiyonlarin tam tersidir: *path fonksiyonu* ve baฤŸฤฑmlฤฑlฤฑklar. +Bu, FastAPIโ€™nin sizin iรงin รงaฤŸฤฑrdฤฑฤŸฤฑ fonksiyonlarฤฑn tersidir: *path operasyon fonksiyonlarฤฑ* ve baฤŸฤฑmlฤฑlฤฑklar. -Yardฤฑmcฤฑ program fonksiyonunuz 'def' ile normal bir iลŸlevse, bir iลŸ parรงacฤฑฤŸฤฑ havuzunda deฤŸil doฤŸrudan (kodunuzda yazdฤฑฤŸฤฑnฤฑz gibi) รงaฤŸrฤฑlฤฑr, iลŸlev 'async def' ile oluลŸturulmuลŸsa รงaฤŸฤฑrฤฑldฤฑฤŸฤฑ yerde 'await' ile beklemelisiniz. +Yardฤฑmcฤฑ fonksiyonunuz `def` ile tanฤฑmlฤฑ normal bir fonksiyonsa, bir thread poolโ€™da deฤŸil doฤŸrudan (kodunuzda yazdฤฑฤŸฤฑnฤฑz gibi) รงaฤŸrฤฑlฤฑr; fonksiyon `async def` ile tanฤฑmlฤฑysa kodunuzda รงaฤŸฤฑrฤฑrken onu `await` etmelisiniz. --- -Yeniden, bunlar, onlarฤฑ aramaya geldiฤŸinizde muhtemelen iลŸinize yarayacak รงok teknik ayrฤฑntฤฑlardฤฑr. +Yine, bunlar muhtemelen รถzellikle aradฤฑฤŸฤฑnฤฑzda iลŸinize yarayacak รงok teknik ayrฤฑntฤฑlardฤฑr. -Aksi takdirde, yukarฤฑdaki bรถlรผmdeki yรถnergeleri iyi bilmelisiniz: Aceleniz mi var?. +Aksi hรขlde, yukarฤฑdaki bรถlรผmdeki yรถnergeler yeterlidir: Aceleniz mi var?. diff --git a/docs/tr/docs/deployment/concepts.md b/docs/tr/docs/deployment/concepts.md index d0f5681469..f5ee988c9a 100644 --- a/docs/tr/docs/deployment/concepts.md +++ b/docs/tr/docs/deployment/concepts.md @@ -13,7 +13,7 @@ Bir **FastAPI** uygulamasฤฑnฤฑ (hatta genel olarak herhangi bir web API'yi) depl Bunlarฤฑn **deployment**'larฤฑ nasฤฑl etkilediฤŸine bakalฤฑm. -Nihai hedef, **API client**'larฤฑnฤฑza **gรผvenli** bir ลŸekilde hizmet verebilmek, **kesintileri** รถnlemek ve **hesaplama kaynaklarฤฑnฤฑ** (รถr. uzak server'lar/sanal makineler) olabildiฤŸince verimli kullanmaktฤฑr. +Nihai hedef, **API client**'larฤฑnฤฑza **gรผvenli** bir ลŸekilde hizmet verebilmek, **kesintileri** รถnlemek ve **hesaplama kaynaklarฤฑnฤฑ** (รถr. uzak server'lar/sanal makineler) olabildiฤŸince verimli kullanmaktฤฑr. ๐Ÿš€ Burada bu **kavramlar** hakkฤฑnda biraz daha bilgi vereceฤŸim. Bรถylece, รงok farklฤฑ ortamlardaโ€”hatta bugรผn var olmayan **gelecekteki** ortamlarda bileโ€”API'nizi nasฤฑl deploy edeceฤŸinize karar verirken ihtiyaรง duyacaฤŸฤฑnฤฑz **sezgiyi** kazanmฤฑลŸ olursunuz. @@ -21,7 +21,7 @@ Bu kavramlarฤฑ dikkate alarak, **kendi API**'leriniz iรงin en iyi deployment yak Sonraki bรถlรผmlerde, FastAPI uygulamalarฤฑnฤฑ deploy etmek iรงin daha **somut tarifler** (recipes) paylaลŸacaฤŸฤฑm. -Ama ลŸimdilik, bu รถnemli **kavramsal fikirleri** inceleyelim. Bu kavramlar diฤŸer tรผm web API tรผrleri iรงin de geรงerlidir. +Ama ลŸimdilik, bu รถnemli **kavramsal fikirleri** inceleyelim. Bu kavramlar diฤŸer tรผm web API tรผrleri iรงin de geรงerlidir. ๐Ÿ’ก ## Gรผvenlik - HTTPS { #security-https } @@ -36,16 +36,16 @@ Ve **HTTPS sertifikalarฤฑnฤฑ yenilemekten** sorumlu bir ลŸey olmalฤฑdฤฑr; bu ayn TLS Termination Proxy olarak kullanabileceฤŸiniz bazฤฑ araรงlar: * Traefik - * Sertifika yenilemelerini otomatik yรถnetir + * Sertifika yenilemelerini otomatik yรถnetir โœจ * Caddy - * Sertifika yenilemelerini otomatik yรถnetir + * Sertifika yenilemelerini otomatik yรถnetir โœจ * Nginx * Sertifika yenilemeleri iรงin Certbot gibi harici bir bileลŸenle * HAProxy * Sertifika yenilemeleri iรงin Certbot gibi harici bir bileลŸenle * Nginx gibi bir Ingress Controller ile Kubernetes * Sertifika yenilemeleri iรงin cert-manager gibi harici bir bileลŸenle -* Bir cloud provider tarafฤฑndan servislerinin parรงasฤฑ olarak iรงeride yรถnetilmesi (aลŸaฤŸฤฑyฤฑ okuyun) +* Bir cloud provider tarafฤฑndan servislerinin parรงasฤฑ olarak iรงeride yรถnetilmesi (aลŸaฤŸฤฑyฤฑ okuyun ๐Ÿ‘‡) Bir diฤŸer seรงenek de, HTTPS kurulumunu da dahil olmak รผzere iลŸin daha bรผyรผk kฤฑsmฤฑnฤฑ yapan bir **cloud service** kullanmaktฤฑr. Bunun bazฤฑ kฤฑsฤฑtlarฤฑ olabilir veya daha pahalฤฑ olabilir vb. Ancak bu durumda TLS Termination Proxy'yi kendiniz kurmak zorunda kalmazsฤฑnฤฑz. @@ -100,7 +100,7 @@ Bu yรถntem รงalฤฑลŸฤฑr ve **geliลŸtirme sฤฑrasฤฑnda** faydalฤฑdฤฑr. Ancak server'a olan baฤŸlantฤฑnฤฑz koparsa, **รงalฤฑลŸan process** muhtemelen รถlรผr. -Ve server yeniden baลŸlatฤฑlฤฑrsa (รถrneฤŸin update'lerden sonra ya da cloud provider'ฤฑn migration'larฤฑndan sonra) bunu muhtemelen **fark etmezsiniz**. Dolayฤฑsฤฑyla process'i manuel yeniden baลŸlatmanฤฑz gerektiฤŸini de bilmezsiniz. Sonuรงta API'niz รถlรผ kalฤฑr. +Ve server yeniden baลŸlatฤฑlฤฑrsa (รถrneฤŸin update'lerden sonra ya da cloud provider'ฤฑn migration'larฤฑndan sonra) bunu muhtemelen **fark etmezsiniz**. Dolayฤฑsฤฑyla process'i manuel yeniden baลŸlatmanฤฑz gerektiฤŸini de bilmezsiniz. Sonuรงta API'niz รถlรผ kalฤฑr. ๐Ÿ˜ฑ ### Startup'ta Otomatik ร‡alฤฑลŸtฤฑrma { #run-automatically-on-startup } @@ -131,19 +131,19 @@ Uygulamanฤฑzฤฑn startup'ta รงalฤฑลŸtฤฑฤŸฤฑndan emin olmaya benzer ลŸekilde, hata ### Hata Yaparฤฑz { #we-make-mistakes } -Biz insanlar sรผrekli **hata** yaparฤฑz. Yazฤฑlฤฑmฤฑn neredeyse *her zaman* farklฤฑ yerlerinde gizli **bug**'lar vardฤฑr. +Biz insanlar sรผrekli **hata** yaparฤฑz. Yazฤฑlฤฑmฤฑn neredeyse *her zaman* farklฤฑ yerlerinde gizli **bug**'lar vardฤฑr. ๐Ÿ› -Ve biz geliลŸtiriciler bu bug'larฤฑ buldukรงa ve yeni รถzellikler ekledikรงe code'u iyileลŸtiririz (muhtemelen yeni bug'lar da ekleyerek). +Ve biz geliลŸtiriciler bu bug'larฤฑ buldukรงa ve yeni รถzellikler ekledikรงe code'u iyileลŸtiririz (muhtemelen yeni bug'lar da ekleyerek ๐Ÿ˜…). ### Kรผรงรผk Hatalar Otomatik Yรถnetilir { #small-errors-automatically-handled } -FastAPI ile web API geliลŸtirirken, code'umuzda bir hata olursa FastAPI genellikle bunu hatayฤฑ tetikleyen tek request ile sฤฑnฤฑrlar. +FastAPI ile web API geliลŸtirirken, code'umuzda bir hata olursa FastAPI genellikle bunu hatayฤฑ tetikleyen tek request ile sฤฑnฤฑrlar. ๐Ÿ›ก Client o request iรงin **500 Internal Server Error** alฤฑr; ancak uygulama tamamen รงรถkรผp durmak yerine sonraki request'ler iรงin รงalฤฑลŸmaya devam eder. ### Daha Bรผyรผk Hatalar - ร‡รถkmeler { #bigger-errors-crashes } -Yine de bazฤฑ durumlarda, yazdฤฑฤŸฤฑmฤฑz bir code **tรผm uygulamayฤฑ รงรถkertip** Uvicorn ve Python'ฤฑn crash olmasฤฑna neden olabilir. +Yine de bazฤฑ durumlarda, yazdฤฑฤŸฤฑmฤฑz bir code **tรผm uygulamayฤฑ รงรถkertip** Uvicorn ve Python'ฤฑn crash olmasฤฑna neden olabilir. ๐Ÿ’ฅ Bรถyle bir durumda, tek bir noktadaki hata yรผzรผnden uygulamanฤฑn รถlรผ kalmasฤฑnฤฑ istemezsiniz; bozuk olmayan *path operations* en azฤฑndan รงalฤฑลŸmaya devam etsin istersiniz. @@ -206,7 +206,7 @@ Ve birden fazla process normalde **belleฤŸi paylaลŸmaz**. Yani her รงalฤฑลŸan pr ร–rneฤŸin code'unuz **1 GB** boyutunda bir Machine Learning modelini yรผklรผyorsa, API'niz tek process ile รงalฤฑลŸฤฑrken en az 1 GB RAM tรผketir. **4 process** (4 worker) baลŸlatฤฑrsanฤฑz her biri 1 GB RAM tรผketir. Yani toplamda API'niz **4 GB RAM** tรผketir. -Uzak server'ฤฑnฤฑz veya sanal makineniz yalnฤฑzca 3 GB RAM'e sahipse, 4 GB'tan fazla RAM yรผklemeye รงalฤฑลŸmak sorun รงฤฑkarฤฑr. +Uzak server'ฤฑnฤฑz veya sanal makineniz yalnฤฑzca 3 GB RAM'e sahipse, 4 GB'tan fazla RAM yรผklemeye รงalฤฑลŸmak sorun รงฤฑkarฤฑr. ๐Ÿšจ ### Birden Fazla Process - Bir ร–rnek { #multiple-processes-an-example } @@ -265,7 +265,7 @@ Elbette bazฤฑ durumlarda รถn adฤฑmlarฤฑ birden fazla kez รงalฤฑลŸtฤฑrmak sorun d Ayrฤฑca, kurulumunuza baฤŸlฤฑ olarak bazฤฑ durumlarda uygulamanฤฑzฤฑ baลŸlatmadan รถnce **hiรง รถn adฤฑma ihtiyaรง duymayabilirsiniz**. -Bu durumda bunlarฤฑn hiรงbirini dรผลŸรผnmeniz gerekmez. +Bu durumda bunlarฤฑn hiรงbirini dรผลŸรผnmeniz gerekmez. ๐Ÿคท /// @@ -291,7 +291,7 @@ Server(lar)ฤฑnฤฑz bir **kaynaktฤฑr**. Programlarฤฑnฤฑzla CPU'lardaki hesaplama z Sistem kaynaklarฤฑnฤฑn ne kadarฤฑnฤฑ tรผketmek/kullanmak istersiniz? "Az" demek kolaydฤฑr; ancak pratikte hedef genellikle **รงรถkmeden mรผmkรผn olduฤŸunca fazla** kullanmaktฤฑr. -3 server iรงin para รถdรผyor ama onlarฤฑn RAM ve CPU'sunun yalnฤฑzca kรผรงรผk bir kฤฑsmฤฑnฤฑ kullanฤฑyorsanฤฑz, muhtemelen **para israf ediyorsunuz** ve muhtemelen **elektrik tรผketimini** de gereksiz yere artฤฑrฤฑyorsunuz vb. +3 server iรงin para รถdรผyor ama onlarฤฑn RAM ve CPU'sunun yalnฤฑzca kรผรงรผk bir kฤฑsmฤฑnฤฑ kullanฤฑyorsanฤฑz, muhtemelen **para israf ediyorsunuz** ๐Ÿ’ธ ve muhtemelen **elektrik tรผketimini** de gereksiz yere artฤฑrฤฑyorsunuz ๐ŸŒŽ vb. Bu durumda 2 server ile devam edip onlarฤฑn kaynaklarฤฑnฤฑ (CPU, bellek, disk, aฤŸ bant geniลŸliฤŸi vb.) daha yรผksek oranlarda kullanmak daha iyi olabilir. @@ -316,6 +316,6 @@ Uygulamanฤฑzฤฑ nasฤฑl deploy edeceฤŸinize karar verirken aklฤฑnฤฑzda tutmanฤฑz g * Bellek * BaลŸlatmadan รถnceki adฤฑmlar -Bu fikirleri ve nasฤฑl uygulayacaฤŸฤฑnฤฑzฤฑ anlamak, deployment'larฤฑnฤฑzฤฑ yapฤฑlandฤฑrฤฑrken ve ince ayar yaparken ihtiyaรง duyacaฤŸฤฑnฤฑz sezgiyi kazanmanฤฑzฤฑ saฤŸlamalฤฑdฤฑr. +Bu fikirleri ve nasฤฑl uygulayacaฤŸฤฑnฤฑzฤฑ anlamak, deployment'larฤฑnฤฑzฤฑ yapฤฑlandฤฑrฤฑrken ve ince ayar yaparken ihtiyaรง duyacaฤŸฤฑnฤฑz sezgiyi kazanmanฤฑzฤฑ saฤŸlamalฤฑdฤฑr. ๐Ÿค“ -Sonraki bรถlรผmlerde, izleyebileceฤŸiniz stratejilere dair daha somut รถrnekler paylaลŸacaฤŸฤฑm. +Sonraki bรถlรผmlerde, izleyebileceฤŸiniz stratejilere dair daha somut รถrnekler paylaลŸacaฤŸฤฑm. ๐Ÿš€ diff --git a/docs/tr/docs/deployment/docker.md b/docs/tr/docs/deployment/docker.md index 6c8f74c778..6d38a2ce13 100644 --- a/docs/tr/docs/deployment/docker.md +++ b/docs/tr/docs/deployment/docker.md @@ -14,7 +14,7 @@ Aceleniz var ve bunlarฤฑ zaten biliyor musunuz? AลŸaฤŸฤฑdaki [`Dockerfile`'a atl Dockerfile ร–nizleme ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ FastAPI uygulamanฤฑz tek bir dosyaysa; รถrneฤŸin `./app` dizini olmadan sadece ` Bu durumda `Dockerfile` iรงinde dosyayฤฑ kopyaladฤฑฤŸฤฑnฤฑz path'leri buna gรถre deฤŸiลŸtirmeniz yeterlidir: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Container kullanmadan, uygulamalarฤฑ startup'ta รงalฤฑลŸtฤฑrmak ve restart mekan ## Replication - Process Sayฤฑsฤฑ { #replication-number-of-processes } -Kubernetes, Docker Swarm Mode, Nomad veya benzeri, birden fazla makinede daฤŸฤฑtฤฑk container'larฤฑ yรถneten karmaลŸฤฑk bir sistemle kurulmuลŸ bir cluster'ฤฑnฤฑz varsa, replication'ฤฑ her container iรงinde bir **process manager** (รถr. worker'lฤฑ Uvicorn) kullanarak yรถnetmek yerine, muhtemelen **cluster seviyesinde** ele almak istersiniz. +EฤŸer bir kรผme (cluster) olarak yapฤฑlandฤฑrฤฑlmฤฑลŸ makineler grubunuz varsa ve bunlarฤฑ **Kubernetes**, Docker Swarm Mode, Nomad veya benzeri, birden รงok makinede daฤŸฤฑtฤฑk container'larฤฑ yรถneten karmaลŸฤฑk bir sistemle yรถnetiyorsanฤฑz, replication'ฤฑ her container iรงinde bir **process manager** (รถr. worker'lฤฑ Uvicorn) kullanarak yรถnetmek yerine, muhtemelen **kรผme seviyesinde (cluster level)** ele almak istersiniz. Kubernetes gibi daฤŸฤฑtฤฑk container yรถnetim sistemleri, gelen request'ler iรงin **load balancing** desteฤŸi sunarken aynฤฑ zamanda **container replication**'ฤฑnฤฑ yรถnetmek iรงin entegre mekanizmalara sahiptir. Hepsi **cluster seviyesinde**. @@ -499,7 +499,7 @@ Elbette bazฤฑ **รถzel durumlarda** bir container iรงinde birden fazla **Uvicorn Bu durumlarda รงalฤฑลŸtฤฑrmak istediฤŸiniz worker sayฤฑsฤฑnฤฑ `--workers` komut satฤฑrฤฑ seรงeneฤŸiyle ayarlayabilirsiniz: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/tr/docs/deployment/https.md b/docs/tr/docs/deployment/https.md index bb70883aa7..de9716520e 100644 --- a/docs/tr/docs/deployment/https.md +++ b/docs/tr/docs/deployment/https.md @@ -65,7 +65,7 @@ Burada, bir HTTPS APIโ€™nin adฤฑm adฤฑm nasฤฑl gรถrรผnebileceฤŸine dair, รถzelli Muhtemelen her ลŸey, bir **domain adฤฑ** **temin etmenizle** baลŸlar. Sonra bunu bir DNS serverโ€™ฤฑnda (muhtemelen aynฤฑ cloud providerโ€™ฤฑnฤฑzda) yapฤฑlandฤฑrฤฑrsฤฑnฤฑz. -Muhtemelen bir cloud server (virtual machine) ya da benzeri bir ลŸey alฤฑrsฤฑnฤฑz ve bunun fixed bir **public IP adresi** olur. +Muhtemelen bir cloud server (virtual machine) ya da benzeri bir ลŸey alฤฑrsฤฑnฤฑz ve bunun sabit bir **public IP adresi** olur. DNS server(lar)ฤฑnda, bir kaydฤฑ ("`A record`") **domain**โ€™inizi serverโ€™ฤฑnฤฑzฤฑn **public IP adresine** yรถnlendirecek ลŸekilde yapฤฑlandฤฑrฤฑrsฤฑnฤฑz. diff --git a/docs/tr/docs/deployment/index.md b/docs/tr/docs/deployment/index.md index 055d999294..c9efcef991 100644 --- a/docs/tr/docs/deployment/index.md +++ b/docs/tr/docs/deployment/index.md @@ -1,8 +1,8 @@ -# Deployment { #deployment } +# DaฤŸฤฑtฤฑm { #deployment } **FastAPI** uygulamasฤฑnฤฑ deploy etmek nispeten kolaydฤฑr. -## Deployment Ne Anlama Gelir? { #what-does-deployment-mean } +## DaฤŸฤฑtฤฑm Ne Anlama Gelir? { #what-does-deployment-mean } Bir uygulamayฤฑ **deploy** etmek, onu **kullanฤฑcฤฑlara eriลŸilebilir hale getirmek** iรงin gerekli adฤฑmlarฤฑ gerรงekleลŸtirmek anlamฤฑna gelir. @@ -10,7 +10,7 @@ Bir **web API** iรงin bu sรผreรง normalde uygulamayฤฑ **uzak bir makineye** yerl Bu, kodu sรผrekli olarak deฤŸiลŸtirdiฤŸiniz, bozup dรผzelttiฤŸiniz, geliลŸtirme sunucusunu durdurup yeniden baลŸlattฤฑฤŸฤฑnฤฑz vb. **geliลŸtirme** aลŸamalarฤฑnฤฑn tam tersidir. -## Deployment Stratejileri { #deployment-strategies } +## DaฤŸฤฑtฤฑm Stratejileri { #deployment-strategies } Kullanฤฑm durumunuza ve kullandฤฑฤŸฤฑnฤฑz araรงlara baฤŸlฤฑ olarak bunu yapmanฤฑn birkaรง yolu vardฤฑr. diff --git a/docs/tr/docs/deployment/manually.md b/docs/tr/docs/deployment/manually.md index 561ba86772..8c7fd990e7 100644 --- a/docs/tr/docs/deployment/manually.md +++ b/docs/tr/docs/deployment/manually.md @@ -46,7 +46,7 @@ Bu, รงoฤŸu durumda iลŸinizi gรถrรผr. ๐Ÿ˜Ž ลžimdi biraz daha detaya inelim. -FastAPI, Python web framework'leri ve sunucularฤฑnฤฑ inลŸa etmek iรงin kullanฤฑlan ASGI adlฤฑ bir standardฤฑ kullanฤฑr. FastAPI bir ASGI web framework'รผdรผr. +FastAPI, Python web framework'leri ve sunucularฤฑnฤฑ inลŸa etmek iรงin kullanฤฑlan ASGI adlฤฑ bir standardฤฑ kullanฤฑr. FastAPI bir ASGI web framework'รผdรผr. Uzak bir sunucu makinesinde **FastAPI** uygulamasฤฑnฤฑ (veya herhangi bir ASGI uygulamasฤฑnฤฑ) รงalฤฑลŸtฤฑrmak iรงin gereken ana ลŸey, **Uvicorn** gibi bir ASGI server programฤฑdฤฑr. `fastapi` komutuyla varsayฤฑlan olarak gelen de budur. @@ -74,7 +74,7 @@ FastAPI'yi kurduฤŸunuzda, production sunucusu olarak Uvicorn da beraberinde geli Ancak bir ASGI server'ฤฑ manuel olarak da kurabilirsiniz. -Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, etkinleลŸtirdiฤŸinizden emin olun; ardฤฑndan server uygulamasฤฑnฤฑ kurabilirsiniz. +Bir [sanal ortam](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, etkinleลŸtirdiฤŸinizden emin olun; ardฤฑndan server uygulamasฤฑnฤฑ kurabilirsiniz. ร–rneฤŸin Uvicorn'u kurmak iรงin: diff --git a/docs/tr/docs/environment-variables.md b/docs/tr/docs/environment-variables.md index e4f769a16e..8b546c77a7 100644 --- a/docs/tr/docs/environment-variables.md +++ b/docs/tr/docs/environment-variables.md @@ -153,7 +153,7 @@ Hello World from Python /// tip | ฤฐpucu -Bu konuyla ilgili daha fazlasฤฑnฤฑ The Twelve-Factor App: Config bรถlรผmรผnde okuyabilirsiniz. +Bu konuyla ilgili daha fazlasฤฑnฤฑ Twelve-Factor Uygulamasฤฑ: Config bรถlรผmรผnde okuyabilirsiniz. /// @@ -291,7 +291,7 @@ Bu bilgiler, [Virtual Environments](virtual-environments.md){.internal-link targ Buraya kadar **ortam deฤŸiลŸkenleri**nin ne olduฤŸuna ve Pythonโ€™da nasฤฑl kullanฤฑlacaฤŸฤฑna dair temel bir fikir edinmiลŸ olmalฤฑsฤฑnฤฑz. -Ayrฤฑca Wikipedia for Environment Variable sayfasฤฑndan daha fazlasฤฑnฤฑ da okuyabilirsiniz. +Ayrฤฑca Ortam DeฤŸiลŸkeni iรงin Wikipedia sayfasฤฑndan daha fazlasฤฑnฤฑ da okuyabilirsiniz. ร‡oฤŸu zaman ortam deฤŸiลŸkenlerinin hemen nasฤฑl iลŸe yarayacaฤŸฤฑ ilk bakฤฑลŸta รงok net olmayabilir. Ancak geliลŸtirme yaparken birรงok farklฤฑ senaryoda tekrar tekrar karลŸฤฑnฤฑza รงฤฑkarlar; bu yรผzden bunlarฤฑ bilmek faydalฤฑdฤฑr. diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md index 86085c5e93..5c651e4917 100644 --- a/docs/tr/docs/features.md +++ b/docs/tr/docs/features.md @@ -1,59 +1,55 @@ -# ร–zelikler +# ร–zellikler { #features } -## FastAPI รถzellikleri +## FastAPI ร–zellikleri { #fastapi-features } -**FastAPI** sana bunlarฤฑ saฤŸlฤฑyor +**FastAPI** size ลŸunlarฤฑ saฤŸlar: -### Aรงฤฑk standartlarฤฑ temel alฤฑr +### Aรงฤฑk Standartlara Dayalฤฑ { #based-on-open-standards } -* API oluลŸturma iลŸlemlerinde OpenAPI buna path operasyonlarฤฑ parametreleri, body talebi, gรผvenlik gibi ลŸeyler dahil olmak รผzere deklare bunlarฤฑn deklare edilmesi. -* Otomatik olarak data modelinin JSON Schema ile beraber dokรผmante edilmesi (OpenAPI'n kendisi zaten JSON Schema'ya dayanฤฑyor). -* Titiz bir รงalฤฑลŸmanฤฑn sonucunda yukarฤฑdaki standartlara uygun bir framework oluลŸturduk. Standartlarฤฑ pastanฤฑn รผzerine sonradan eklenmiลŸ bir รงilek olarak gรถrmedik. -* Ayrฤฑca bu bir รงok dilde kullanฤฑlabilecek **client code generator** kullanฤฑmฤฑna da izin veriyor. +* API oluลŸturmada OpenAPI, buna path operasyonlarฤฑ, parametreler, request body'leri, gรผvenlik vb. deklarasyonlarฤฑ dahildir. +* JSON Schema ile otomatik veri modeli dokรผmantasyonu (OpenAPI zaten JSON Schema'ya dayanฤฑr). +* Bu standartlar etrafฤฑnda, titiz bir รงalฤฑลŸmanฤฑn ardฤฑndan tasarlandฤฑ; sonradan eklenmiลŸ bir katman deฤŸil. +* Bu sayede birรงok dilde otomatik **client code generation** da kullanฤฑlabilir. -### Otomatik dokรผmantasyon +### Otomatik Dokรผmantasyon { #automatic-docs } +EtkileลŸimli API dokรผmantasyonu ve keลŸif iรงin web arayรผzleri. Framework OpenAPIโ€™ye dayandฤฑฤŸฤฑndan, birden fazla seรงenek vardฤฑr; varsayฤฑlan olarak 2โ€™si dahildir. -OpenAPI standartlarฤฑna dayalฤฑ olan bir framework olarak, geliลŸtiricilerin birden รงok seรงeneฤŸi var, varsayฤฑlan olarak gelen 2 farklฤฑ interaktif API dokรผmantasyonu ve web kullanฤฑcฤฑ arayรผzรผ var. - - -* Swagger UI interaktif olarak API'ฤฑnฤฑzฤฑ tarayฤฑcฤฑ รผzerinden รงaฤŸฤฑrฤฑp test edebilmenize olanak saฤŸlฤฑyor. +* Swagger UI ile etkileลŸimli keลŸif; APIโ€™nizi tarayฤฑcฤฑdan doฤŸrudan รงaฤŸฤฑrฤฑp test edin. ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDoc ile beraber alternatif API dokรผmantasyonu. +* ReDoc ile alternatif API dokรผmantasyonu. ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### Sadece modern Python +### Sadece Modern Python { #just-modern-python } -Tamamiyle standartlar **Python 3.8**'nฤฑn type hintlerine dayanฤฑyor (Pydantic'in sayesinde). Yeni bir syntax รถฤŸrenmene gerek yok. Sadece modern Python. +Her ลŸey standart **Python type** deklarasyonlarฤฑna dayanฤฑr (Pydantic sayesinde). ร–ฤŸrenilecek yeni bir sรถz dizimi yok. Sadece standart, modern Python. +Python typeโ€™larฤฑnฤฑ nasฤฑl kullanacaฤŸฤฑnฤฑza dair 2 dakikalฤฑk bir hatฤฑrlatmaya ihtiyacฤฑnฤฑz varsa (FastAPI kullanmasanฤฑz bile) kฤฑsa eฤŸitime gรถz atฤฑn: [Python Types](python-types.md){.internal-link target=_blank}. -EฤŸer Python type hintlerini bilmiyorsan veya bir hatฤฑrlatmaya ihtiyacฤฑn var ise(FastAPI kullanmasan bile) ลŸu iki dakikalฤฑk kรผรงรผk bilgilendirici iรงeriฤŸe bir gรถz at: [Python Types](python-types.md){.internal-link target=_blank}. - -Standart Python'u typelarฤฑnฤฑ belirterek yazฤฑyorsun: +Tรผrleriyle standart Python yazarsฤฑnฤฑz: ```Python -from typing import List, Dict from datetime import date from pydantic import BaseModel -# DeฤŸiลŸkeni str olarak belirt -# ve o fonksiyon iรงin harika bir editรถr desteฤŸi al +# Bir deฤŸiลŸkeni str olarak belirt +# ve fonksiyon iรงinde editรถr desteฤŸi al def main(user_id: str): return user_id -# Pydantic modeli +# Bir Pydantic modeli class User(BaseModel): id: int name: str joined: date ``` -Sonrasฤฑnda bu ลŸekilde kullanabilirsin +Sonra ลŸรถyle kullanabilirsiniz: ```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") @@ -67,25 +63,26 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` + /// info -`**second_user_data` ลŸu anlama geliyor: +`**second_user_data` ลŸu anlama gelir: -Key-Value รงiftini direkt olarak `second_user_data` dictionarysine kaydet , yaptฤฑฤŸฤฑn ลŸey buna eลŸit olacak: `User(id=4, name="Mary", joined="2018-11-30")` +`second_user_data` dictโ€™indeki anahtar ve deฤŸerleri doฤŸrudan anahtar-deฤŸer argรผmanlarฤฑ olarak geรง; ลŸu ifadeye eลŸdeฤŸerdir: `User(id=4, name="Mary", joined="2018-11-30")` /// -### Editor desteฤŸi +### Editรถr DesteฤŸi { #editor-support } -Bรผtรผn framework kullanฤฑlmasฤฑ kolay ve sezgileri gรผรงlรผ olmasฤฑ iรงin tasarlandฤฑ, verilen bรผtรผn kararlar geliลŸtiricilere en iyi geliลŸtirme deneyimini yaลŸatmak รผzere, bir รงok editรถr รผzerinde test edildi. +Tรผm framework, kullanฤฑmฤฑ kolay ve sezgisel olacak ลŸekilde tasarlandฤฑ; en iyi geliลŸtirme deneyimini saฤŸlamak iรงin geliลŸtirmeye baลŸlamadan รถnce bile alฤฑnan kararlar birden รงok editรถrde test edildi. -Son yapฤฑlan Python geliลŸtiricileri anketinde, aรงฤฑk ara en รงok kullanฤฑlan รถzellik "oto-tamamlama" idi.. +Python geliลŸtirici anketlerinde aรงฤฑkรงa gรถrรผlรผyor ki en รงok kullanฤฑlan รถzelliklerden biri "otomatik tamamlama". -Bรผtรผn **FastAPI** frameworkรผ oto-tamamlama aรงฤฑsฤฑndan geliลŸtiriciyi tatmin etmek รผzerine tasarlandฤฑ. Otomatik tamamlama her yerde รงalฤฑลŸฤฑyor. +Tรผm **FastAPI** bunun tatmin edilmesi รผzerine kuruldu. Otomatik tamamlama her yerde รงalฤฑลŸฤฑr. -Dokรผmantasyona tekrardan รงok nadir olarak geleceksin. +Dokรผmana geri dรถnmeniz nadiren gerekecek. -Editรถrรผn sana nasฤฑl yardฤฑm ettiฤŸine bir bak: +Editรถrรผnรผz ลŸรถyle yardฤฑmcฤฑ olabilir: * Visual Studio Code ile: @@ -95,115 +92,111 @@ Editรถrรผn sana nasฤฑl yardฤฑm ettiฤŸine bir bak: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +Daha รถnce imkรขnsฤฑz olduฤŸunu dรผลŸรผnebileceฤŸiniz yerlerde bile tamamlama alฤฑrsฤฑnฤฑz. ร–rneฤŸin, bir requestโ€™ten gelen (iรง iรงe de olabilir) JSON body iรงindeki `price` anahtarฤฑ iรงin. -Daha รถnceden dรผลŸรผnรผp en imkansฤฑz diyebileceฤŸin durumlarda bile otomatik tamamlama alacaksฤฑn, รถrnek olarak `price` JSON body iรงerisinde (nested bir JSON body de olabilirdi.) direkt olarak istekten geliyor, bu durumda bile oto-tammalama saฤŸlฤฑyor. +Artฤฑk anahtar adlarฤฑnฤฑ yanlฤฑลŸ yazmak, dokรผmana gidip gelmek ya da sonunda `username` mi `user_name` mi kullandฤฑฤŸฤฑnฤฑzฤฑ bulmak iรงin sayfayฤฑ yukarฤฑ aลŸaฤŸฤฑ kaydฤฑrmak yok. -Artฤฑk key isimlerini yanlฤฑลŸ yazma, dokรผmantasyona dรถnรผp deliler gibi yukarฤฑ aลŸaฤŸฤฑ sayfada gezmek ve en sonunda `username` mi yoksa `user_name` mi kullandฤฑm gibi sorular yok. +### Kฤฑsa { #short } -### Kฤฑsa +Her ลŸey iรงin mantฤฑklฤฑ **varsayฤฑlanlar** ve her yerde isteฤŸe baฤŸlฤฑ yapฤฑlandฤฑrmalar vardฤฑr. Tรผm parametreler, ihtiyacฤฑnฤฑzฤฑ karลŸฤฑlayacak ลŸekilde ince ayar yapฤฑlarak tanฤฑmlamak istediฤŸiniz APIโ€™yi oluลŸturabilir. -Her ลŸey iรงin mantฤฑklฤฑ bir **varsayฤฑlanฤฑ** var. Parametrelerini opsiyonel olarak tanฤฑmlayฤฑp API'nฤฑ istediฤŸin gibi modifiye edebilirsin. +Ancak varsayฤฑlan hรขliyle hepsi **โ€œhemen รงalฤฑลŸฤฑrโ€**. -Hepsi varsayฤฑlan olarak **รงalฤฑลŸฤฑyor**. +### DoฤŸrulama { #validation } +* ร‡oฤŸu (veya hepsi?) Python **veri tipi** iรงin doฤŸrulama, ลŸunlar dรขhil: + * JSON nesneleri (`dict`). + * Eleman tipleri tanฤฑmlanan JSON dizileri (`list`). + * Minimum ve maksimum uzunluklarฤฑ tanฤฑmlanan String (`str`) alanlarฤฑ. + * Min ve max deฤŸerleri olan sayฤฑlar (`int`, `float`) vb. -### DoฤŸrulama - -* Neredeyse bรผtรผn (ya da hepsi?) Python **data typelarฤฑ** iรงin doฤŸrulama, kapsadฤฑklarฤฑ: - * JSON objeleri (`dict`). - * JSON array (`list`) item type'ฤฑ belirtirken. - * String (`str`) parametresi, minimum ve maksimum uzunluk gibi sฤฑnฤฑrlandฤฑrmalar yaparken. - * Numaralar (`int`, `float`) maksimum ve minimum gibi sฤฑnฤฑrlandฤฑrmalar yaparken. - -* Bunlar gibi en egzotik typelarla bile doฤŸrulama yapabiliyorsunuz.: +* Daha โ€œegzotikโ€ tipler iรงin doฤŸrulama: * URL. * Email. * UUID. * ...ve diฤŸerleri. -Bรผtรผn doฤŸrulama olaylarฤฑ รงok gรผรงlรผ bir kรผtรผphane sayesinde yapฤฑlฤฑyor, **Pydantic**. +Tรผm doฤŸrulama kรถklรผ ve saฤŸlam **Pydantic** tarafฤฑndan yapฤฑlฤฑr. -### Gรผvenlik ve kimlik doฤŸrulama +### Gรผvenlik ve Kimlik DoฤŸrulama { #security-and-authentication } -Gรผvenlik ve doฤŸrulama database ve data modellerinden taviz vermeden entegre edilebilir durumda. +Gรผvenlik ve kimlik doฤŸrulama entegredir. Veritabanlarฤฑ veya veri modelleriyle ilgili hiรงbir taviz yoktur. -Bรผtรผn gรผvenlik ลŸemalarฤฑ OpenAPI'da tanฤฑmlanmฤฑลŸ durumda, kapsadฤฑklarฤฑ: +OpenAPIโ€™da tanฤฑmlanan tรผm gรผvenlik ลŸemalarฤฑ, ลŸunlar dรขhil: * HTTP Basic. -* **OAuth2** (ve **JWT tokenleriyle** beraber). Bu รถฤŸretici iรงeriฤŸe gรถz atabilirsin [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. +* **OAuth2** (ayrฤฑca **JWT token**โ€™larla). ลžu eฤŸitime gรถz atฤฑn: [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. * API anahtarlarฤฑ: - * Headerlar. - * Query parametreleri. - * Cookies, vs. - -Bรผtรผn gรผvenlik รถzellikleri Starlette'den geliyor (**session cookies'de** dahil olmak รผzere). + * Headerโ€™larda. + * Query parametrelerinde. + * Cookieโ€™lerde vb. -Bรผtรผn hepsi tekrardan kullanฤฑlabilir aletler ve bileลŸenler olarak, kolayca sistemlerinize, data depolarฤฑnฤฑza, iliลŸkisel ve NoSQL databaselerinize entegre edebileceฤŸiniz ลŸekilde yapฤฑldฤฑ. +Buna ek olarak Starletteโ€™in tรผm gรผvenlik รถzellikleri (**session cookies** dรขhil). -### Dependency injection +Tรผmรผ, sistemleriniz, veri depolarฤฑnฤฑz, iliลŸkisel ve NoSQL veritabanlarฤฑnฤฑz vb. ile kolayca entegre edilebilen, yeniden kullanฤฑlabilir araรงlar ve bileลŸenler olarak inลŸa edilmiลŸtir. -FastAPI'ฤฑn inanฤฑlmaz derecede kullanฤฑmฤฑ kolay, fakat inanฤฑlmaz derecede gรผรงlรผ Dependency Injection sistemi var. +### Dependency Injection { #dependency-injection } -* Dependencylerin bile dependencies'i olabiliyor, FastAPI bunun iรงin **graph of "dependency"** yaratฤฑyor. -* Hepsi **otomatik olarak** FastAPI tarafฤฑndan hallediliyor. -* Bรผtรผn zorunluluklarฤฑn gelen datalara baฤŸlฤฑ olarak farklฤฑ gereksinimleri olabiliyor, ilave path operasyonlarฤฑnฤฑn kฤฑsฤฑtlamalarฤฑ ve otomatik dokรผmantasyonu da ayrฤฑca yapฤฑlฤฑyor . -* Path operasyonu parametreleri iรงerisinde belirtilen gereksinimler iรงin bile **Otomatik doฤŸrulama** yapฤฑlabiliyor. -* Kompleks kimlik doฤŸrulama sistemleri iรงin destek, **database baฤŸlantฤฑlarฤฑ**, vs. -* **Taviz yok** hiรงbir ลŸeyden taviz vermeden, database frontend vs. Bรผtรผn hepsinin kolayca entegre edilebiliyor. +FastAPI, son derece kolay kullanฤฑmlฤฑ ama son derece gรผรงlรผ bir Dependency Injection sistemine sahiptir. -### Sฤฑnฤฑrsฤฑz "plug-inler" +* BaฤŸฤฑmlฤฑlฤฑklarฤฑn da kendi baฤŸฤฑmlฤฑlฤฑklarฤฑ olabilir; bรถylece bir hiyerarลŸi veya **baฤŸฤฑmlฤฑlฤฑklar "grafฤฑ"** oluลŸur. +* Tรผm sรผreรง framework tarafฤฑndan **otomatik olarak yรถnetilir**. +* Tรผm baฤŸฤฑmlฤฑlฤฑklar, requestโ€™lerden veri talep edebilir ve *path operation* kฤฑsฤฑtlarฤฑnฤฑ ve otomatik dokรผmantasyonu **zenginleลŸtirebilir**. +* BaฤŸฤฑmlฤฑlฤฑklarda tanฤฑmlanan *path operation* parametreleri iรงin bile **otomatik doฤŸrulama**. +* KarmaลŸฤฑk kullanฤฑcฤฑ kimlik doฤŸrulama sistemleri, **veritabanฤฑ baฤŸlantฤฑlarฤฑ** vb. iรงin destek. +* Veritabanlarฤฑ, frontendโ€™ler vb. ile **taviz yok**; ancak hepsiyle kolay entegrasyon. -BaลŸka bir deyiลŸle, plug-inlere ihtiyacฤฑmฤฑz yok, import edip direkt olarak kullanmaya baลŸlayabiliriz. +### Sฤฑnฤฑrsฤฑz "Plug-in" { #unlimited-plug-ins } -Bรผtรผn entegrasyonlar kullanฤฑmฤฑ kolay olmak รผzere (zorunluluklar ile beraber) tasarlandฤฑ, sen bir "plug-in" yaratฤฑp 2 satฤฑr kod ile, *path operasyonlarฤฑnda* kullandฤฑฤŸฤฑmฤฑz syntax ve aynฤฑ yapฤฑ ile koduna entregre edebilirsin. +BaลŸka bir deyiลŸle, onlara gerek yok; ihtiyaรง duyduฤŸunuz kodu import edin ve kullanฤฑn. +Her entegrasyon (baฤŸฤฑmlฤฑlฤฑklar ile) o kadar basit olacak ลŸekilde tasarlanmฤฑลŸtฤฑr ki, uygulamanฤฑz iรงin, *path operations* ile kullandฤฑฤŸฤฑnฤฑz aynฤฑ yapฤฑ ve sรถz dizimiyle sadece 2 satฤฑrda bir โ€œplug-inโ€ yazabilirsiniz. -### Test edildi +### Test Edildi { #tested } -* 100% test coverage. -* 100% typelarฤฑ belirtilmiลŸ codebase. -* FastAPI ile yapฤฑlan bir รงok proje insanlar tarafฤฑndan kullanฤฑlฤฑyor. +* %100 test kapsayฤฑcฤฑlฤฑฤŸฤฑ. +* %100 type annotated kod tabanฤฑ. +* รœretimde kullanฤฑlan uygulamalarda kullanฤฑlฤฑyor. -## Starlette รถzellikleri +## Starlette ร–zellikleri { #starlette-features } -**FastAPI**, Starlette ile tamamiyle uyumlu ve รผzerine kurulu. Yani FastAPI รผzerine ekleme yapacaฤŸฤฑnฤฑz herhangi bir Starlette kodu da รงalฤฑลŸacaktฤฑr. +**FastAPI**, Starlette ile tamamen uyumludur (ve onun รผzerine kuruludur). Dolayฤฑsฤฑyla elinizdeki ek Starlette kodlarฤฑ da รงalฤฑลŸฤฑr. -`FastAPI` aslฤฑnda `Starlette`'nin bir sub-class'ฤฑ. EฤŸer Starlette'nin nasฤฑl kullanฤฑlacaฤŸฤฑnฤฑ biliyor isen, รงoฤŸu iลŸlevini aynฤฑ ลŸekilde yapฤฑyor. +`FastAPI` aslฤฑnda `Starlette`โ€™in bir alt sฤฑnฤฑfฤฑdฤฑr. Starletteโ€™i zaten biliyor veya kullanฤฑyorsanฤฑz, iลŸlevlerin รงoฤŸu aynฤฑ ลŸekilde รงalฤฑลŸฤฑr. -**FastAPI** ile beraber **Starlette**'nin bรผtรผn รถzelliklerine de sahip olacaksฤฑnฤฑz (FastAPI aslฤฑnda Starlette'nin steroid basmฤฑลŸ hali): +**FastAPI** ile **Starlette**โ€™in tรผm รถzelliklerini elde edersiniz (FastAPI, steroid basฤฑlmฤฑลŸ Starlette gibidir): -* Gerรงekten etkileyici bir performansa sahip.Python'un ise en hฤฑzlฤฑ frameworklerinden bir tanesi, **NodeJS** ve **Go** ile ise eลŸdeฤŸer performansa sahip.. +* Cidden etkileyici performans. Mevcut en hฤฑzlฤฑ Python frameworklerinden biridir; **NodeJS** ve **Go** ile aynฤฑ seviyededir. * **WebSocket** desteฤŸi. -* **GraphQL** desteฤŸi. -* Kullanฤฑm halinde arka plan iลŸlevleri. -* BaลŸlatma ve kapatma eventleri(startup and shutdown). -* Test sunucusu HTTPX รผzerine kurulu. -* **CORS**, GZip, Static dosyalar, Streaming responselarฤฑ. -* **Session and Cookie** desteฤŸi. -* 100% test kapsayฤฑcฤฑlฤฑฤŸฤฑ. -* 100% typelarฤฑ belirtilmiลŸ codebase. +* Sรผreรง iรงi arka plan gรถrevleri. +* BaลŸlatma ve kapatma olaylarฤฑ. +* HTTPX รผzerine kurulu test istemcisi. +* **CORS**, GZip, Static Files, Streaming responseโ€™lar. +* **Session** ve **Cookie** desteฤŸi. +* %100 test kapsayฤฑcฤฑlฤฑฤŸฤฑ. +* %100 type annotated kod tabanฤฑ. -## Pydantic รถzellikleri +## Pydantic ร–zellikleri { #pydantic-features } -**FastAPI** ile Pydantic tamamiyle uyumlu ve รผzerine kurulu. Yani FastAPI รผzerine ekleme yapacaฤŸฤฑnฤฑz herhangi bir Pydantic kodu da รงalฤฑลŸacaktฤฑr. +**FastAPI**, Pydantic ile tamamen uyumludur (ve onun รผzerine kuruludur). Dolayฤฑsฤฑyla elinizdeki ek Pydantic kodlarฤฑ da รงalฤฑลŸฤฑr. -Bunlara Pydantic รผzerine kurulu ORM databaseler ve , ODM kรผtรผphaneler de dahil olmak รผzere. +Pydanticโ€™e dayanan harici kรผtรผphaneler de dรขhildir; veritabanlarฤฑ iรงin ORMโ€™ler, ODMโ€™ler gibi. -Bu ayrฤฑca ลŸu anlama da geliyor, bir รงok durumda requestten gelen objeyi **direkt olarak database**'e her ลŸeyi otomatik olarak doฤŸrulanmฤฑลŸ bir biรงimde aktarabilirisin. +Bu aynฤฑ zamanda, birรงok durumda requestโ€™ten aldฤฑฤŸฤฑnฤฑz nesneyi **doฤŸrudan veritabanฤฑna** iletebileceฤŸiniz anlamฤฑna gelir; zira her ลŸey otomatik olarak doฤŸrulanฤฑr. -Aynฤฑ ลŸekilde, databaseden gelen objeyi de **direkt olarak isteฤŸe** de tamamiyle doฤŸrulanmฤฑลŸ bir biรงimde gรถnderebilirsiniz. +Tersi yรถnde de geรงerlidir; birรงok durumda veritabanฤฑndan aldฤฑฤŸฤฑnฤฑz nesneyi **doฤŸrudan client**โ€™a gรถnderebilirsiniz. -**FastAPI** ile beraber **Pydantic**'in bรผtรผn รถzelliklerine sahip olacaksฤฑnฤฑz (FastAPI data kontrolรผnรผ Pydantic'in รผzerine kurduฤŸu iรงin): +**FastAPI** ile **Pydantic**โ€™in tรผm รถzelliklerini elde edersiniz (FastAPI, tรผm veri iลŸlemede Pydanticโ€™e dayanฤฑr): * **Kafa karฤฑลŸtฤฑrmaz**: - * Farklฤฑ bir syntax รถฤŸrenmenize gerek kalmaz, - * EฤŸer Python typelarฤฑnฤฑ nasฤฑl kullanacaฤŸฤฑnฤฑ biliyorsan Pydantic kullanmayฤฑ da biliyorsundur. -* KullandฤฑฤŸฤฑn geliลŸtirme araรงlarฤฑ ile iyi รงalฤฑลŸฤฑr **IDE/linter/brain**: - * Pydantic'in veri yapฤฑlarฤฑ aslฤฑnda sadece senin tanฤฑmladฤฑฤŸฤฑn classlar; Bu yรผzden doฤŸrulanmฤฑลŸ datalarฤฑn ile otomatik tamamlama, linting ve mypy'ฤฑ kullanarak sorunsuz bir ลŸekilde รงalฤฑลŸabilirsin -* **En kompleks** yapฤฑlarฤฑ bile doฤŸrula: - * HiyerarลŸik Pydantic modellerinin kullanฤฑmฤฑ ile beraber, Python `typing`โ€™s `List` and `Dict`, vs gibi ลŸeyleri doฤŸrula. - * DoฤŸrulayฤฑcฤฑlar en kompleks data ลŸemalarฤฑnฤฑn bile temiz ve kolay bir ลŸekilde tanฤฑmlanmasฤฑna izin veriyor, ve hepsi JSON ลŸemasฤฑ olarak dokรผmante ediliyor - * Pydantic, JSON objen ne kadar derin (nested) olursa olsun doฤŸrulamasฤฑnฤฑ ve gรถsterimini yapฤฑyor + * ร–ฤŸrenmeniz gereken yeni bir ลŸema tanฤฑmlama mikro-dili yok. + * Python typeโ€™larฤฑnฤฑ biliyorsanฤฑz Pydanticโ€™i nasฤฑl kullanacaฤŸฤฑnฤฑzฤฑ da biliyorsunuz. +* **IDE/linter/beyin**โ€™inizle iyi anlaลŸฤฑr: + * Pydantic veri yapฤฑlarฤฑ, sizin tanฤฑmladฤฑฤŸฤฑnฤฑz sฤฑnฤฑflarฤฑn รถrnekleridir; bu nedenle doฤŸrulanmฤฑลŸ verilerinizle otomatik tamamlama, linting ve mypy sorunsuz รงalฤฑลŸฤฑr, sezgileriniz de yol gรถsterir. +* **KarmaลŸฤฑk yapฤฑlarฤฑ** doฤŸrulayฤฑn: + * HiyerarลŸik Pydantic modelleri, Python `typing`โ€™in `List` ve `Dict`โ€™i vb. kullanฤฑmฤฑ. + * DoฤŸrulayฤฑcฤฑlar (validators), karmaลŸฤฑk veri ลŸemalarฤฑnฤฑn net ve kolay ลŸekilde tanฤฑmlanmasฤฑnฤฑ, kontrol edilmesini ve JSON Schema olarak dokรผmante edilmesini saฤŸlar. + * Derinlemesine iรง iรงe **JSON** nesnelerine sahip olabilir, hepsinin doฤŸrulanmasฤฑnฤฑ ve anotasyonlanmasฤฑnฤฑ saฤŸlayabilirsiniz. * **GeniลŸletilebilir**: - * Pydantic รถzelleลŸtirilmiลŸ data tiplerinin tanฤฑmlanmasฤฑnฤฑn yapฤฑlmasฤฑna izin veriyor ayrฤฑca validator decoratorรผ ile senin doฤŸrulamalarฤฑ geniลŸletip, kendi doฤŸrulayฤฑcฤฑlarฤฑnฤฑ yazmana izin veriyor. -* 100% test kapsayฤฑcฤฑlฤฑฤŸฤฑ. + * Pydantic, รถzel veri tiplerinin tanฤฑmlanmasฤฑna izin verir; ayrฤฑca validator decoratorโ€™รผyle bir modeldeki metodlarla doฤŸrulamayฤฑ geniลŸletebilirsiniz. +* %100 test kapsayฤฑcฤฑlฤฑฤŸฤฑ. diff --git a/docs/tr/docs/history-design-future.md b/docs/tr/docs/history-design-future.md index 764a519571..d70e45104b 100644 --- a/docs/tr/docs/history-design-future.md +++ b/docs/tr/docs/history-design-future.md @@ -44,7 +44,7 @@ Sonrasฤฑnda, (**FastAPI** kullanan bir geliลŸtirici olarak) sahip olmak istediฤŸ ร‡eลŸitli fikirleri en popรผler Python editรถrlerinde test ettim: PyCharm, VS Code, Jedi tabanlฤฑ editรถrler. -Bu test, en son Python Developer Survey'ine gรถre, kullanฤฑcฤฑlarฤฑn yaklaลŸฤฑk %80'inin kullandฤฑฤŸฤฑ editรถrleri kapsฤฑyor. +Bu test, en son Python GeliลŸtirici Anketi'ine gรถre, kullanฤฑcฤฑlarฤฑn yaklaลŸฤฑk %80'inin kullandฤฑฤŸฤฑ editรถrleri kapsฤฑyor. Bu da demek oluyor ki **FastAPI**, Python geliลŸtiricilerinin %80'inin kullandฤฑฤŸฤฑ editรถrlerle test edildi. Ve diฤŸer editรถrlerin รงoฤŸu benzer ลŸekilde รงalฤฑลŸtฤฑฤŸฤฑndan, avantajlarฤฑ neredeyse tรผm editรถrlerde รงalฤฑลŸacaktฤฑr. diff --git a/docs/tr/docs/how-to/authentication-error-status-code.md b/docs/tr/docs/how-to/authentication-error-status-code.md index 579673624b..a22bef1cb1 100644 --- a/docs/tr/docs/how-to/authentication-error-status-code.md +++ b/docs/tr/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ Ancak herhangi bir nedenle client'larฤฑnฤฑz eski davranฤฑลŸa baฤŸlฤฑysa, securit ร–rneฤŸin, varsayฤฑlan `401 Unauthorized` hatasฤฑ yerine `403 Forbidden` hatasฤฑ dรถndรผren bir `HTTPBearer` alt sฤฑnฤฑfฤฑ oluลŸturabilirsiniz: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | ฤฐpucu diff --git a/docs/tr/docs/how-to/conditional-openapi.md b/docs/tr/docs/how-to/conditional-openapi.md index 9562637c47..32b799fa7c 100644 --- a/docs/tr/docs/how-to/conditional-openapi.md +++ b/docs/tr/docs/how-to/conditional-openapi.md @@ -4,9 +4,9 @@ Gerekirse, ayarlar ve environment variable'larฤฑ kullanarak OpenAPI'yi ortama g ## Gรผvenlik, API'ler ve dokรผmantasyon hakkฤฑnda { #about-security-apis-and-docs } -Production ortamฤฑnda dokรผmantasyon arayรผzlerini gizlemek, API'nizi korumanฤฑn yolu *olmamalฤฑdฤฑr*. +Production ortamฤฑnda dokรผmantasyon arayรผzlerini gizlemek, API'nizi korumanฤฑn yolu olmamalฤฑdฤฑr. -Bu, API'nize ekstra bir gรผvenlik katmanฤฑ eklemez; *path operation*'lar bulunduklarฤฑ yerde yine eriลŸilebilir olacaktฤฑr. +Bu, API'nize ekstra bir gรผvenlik katmanฤฑ eklemez; path operation'lar bulunduklarฤฑ yerde yine eriลŸilebilir olacaktฤฑr. Kodunuzda bir gรผvenlik aรงฤฑฤŸฤฑ varsa, o aรงฤฑk yine var olmaya devam eder. @@ -29,7 +29,7 @@ Yine de, bazฤฑ ortamlarda (รถrn. production) veya environment variable'lardan ge ร–rneฤŸin: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} Burada `openapi_url` ayarฤฑnฤฑ, varsayฤฑlanฤฑ `"/openapi.json"` olacak ลŸekilde tanฤฑmlฤฑyoruz. diff --git a/docs/tr/docs/how-to/configure-swagger-ui.md b/docs/tr/docs/how-to/configure-swagger-ui.md index 6c051a1215..54e27d5dcc 100644 --- a/docs/tr/docs/how-to/configure-swagger-ui.md +++ b/docs/tr/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ Ayarlarฤฑ deฤŸiลŸtirmeden bฤฑrakฤฑrsanฤฑz, syntax highlighting varsayฤฑlan olara Ancak `syntaxHighlight` deฤŸerini `False` yaparak devre dฤฑลŸฤฑ bฤฑrakabilirsiniz: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ...ve ardฤฑndan Swagger UI artฤฑk syntax highlighting'i gรถstermeyecektir: @@ -28,7 +28,7 @@ Ancak `syntaxHighlight` deฤŸerini `False` yaparak devre dฤฑลŸฤฑ bฤฑrakabilirsini Aynฤฑ ลŸekilde, `"syntaxHighlight.theme"` anahtarฤฑyla (ortasฤฑnda bir nokta olduฤŸuna dikkat edin) syntax highlighting temasฤฑnฤฑ ayarlayabilirsiniz: -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} Bu yapฤฑlandฤฑrma, syntax highlighting renk temasฤฑnฤฑ deฤŸiลŸtirir: @@ -46,13 +46,13 @@ FastAPI, รงoฤŸu kullanฤฑm senaryosu iรงin uygun bazฤฑ varsayฤฑlan yapฤฑlandฤฑrma ร–rneฤŸin `deepLinking`'i devre dฤฑลŸฤฑ bฤฑrakmak iรงin `swagger_ui_parameters`'a ลŸu ayarlarฤฑ geรงebilirsiniz: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## DiฤŸer Swagger UI Parametreleri { #other-swagger-ui-parameters } KullanabileceฤŸiniz diฤŸer tรผm olasฤฑ yapฤฑlandฤฑrmalarฤฑ gรถrmek iรงin, resmi Swagger UI parametreleri dokรผmantasyonunu okuyun. -## Yalnฤฑzca JavaScript ayarlarฤฑ { #javascript-only-settings } +## Yalnฤฑzca JavaScript Ayarlarฤฑ { #javascript-only-settings } Swagger UI ayrฤฑca bazฤฑ yapฤฑlandฤฑrmalarฤฑn **yalnฤฑzca JavaScript** nesneleri olmasฤฑna izin verir (รถrneฤŸin JavaScript fonksiyonlarฤฑ). diff --git a/docs/tr/docs/how-to/custom-docs-ui-assets.md b/docs/tr/docs/how-to/custom-docs-ui-assets.md index bdd2d02440..4a843b40f4 100644 --- a/docs/tr/docs/how-to/custom-docs-ui-assets.md +++ b/docs/tr/docs/how-to/custom-docs-ui-assets.md @@ -18,7 +18,7 @@ Bu, รถrneฤŸin bazฤฑ URL'leri kฤฑsฤฑtlayan bir รผlkede yaลŸฤฑyorsanฤฑz faydalฤฑ o Bunlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmak iรงin `FastAPI` uygulamanฤฑzฤฑ oluลŸtururken URL'lerini `None` olarak ayarlayฤฑn: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### ร–zel dokรผmanlarฤฑ ekleyin { #include-the-custom-docs } @@ -34,7 +34,7 @@ Dokรผmanlar iรงin HTML sayfalarฤฑnฤฑ รผretmek รผzere FastAPI'nin dahili fonksiyo ReDoc iรงin de benzer ลŸekilde... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | ฤฐpucu @@ -50,7 +50,7 @@ Swagger UI bunu arka planda sizin iรงin yรถnetir, ancak bu "redirect" yardฤฑmcฤฑ ลžimdi her ลŸeyin รงalฤฑลŸtฤฑฤŸฤฑnฤฑ test edebilmek iรงin bir *path operation* oluลŸturun: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### Test edin { #test-it } @@ -118,7 +118,7 @@ Bundan sonra dosya yapฤฑnฤฑz ลŸรถyle gรถrรผnebilir: * `StaticFiles` iรงe aktarฤฑn. * Belirli bir path'te bir `StaticFiles()` instance'ฤฑnฤฑ "mount" edin. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### Statik dosyalarฤฑ test edin { #test-the-static-files } @@ -144,7 +144,7 @@ Bu, uygulamanฤฑzdan statik dosyalarฤฑ servis edebildiฤŸinizi ve dokรผmanlar iรงi Bunlarฤฑ devre dฤฑลŸฤฑ bฤฑrakmak iรงin `FastAPI` uygulamanฤฑzฤฑ oluลŸtururken URL'lerini `None` olarak ayarlayฤฑn: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### Statik dosyalar iรงin รถzel dokรผmanlarฤฑ ekleyin { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Yine FastAPI'nin dahili fonksiyonlarฤฑnฤฑ kullanarak dokรผmanlar iรงin HTML sayf ReDoc iรงin de benzer ลŸekilde... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | ฤฐpucu @@ -176,7 +176,7 @@ Swagger UI bunu arka planda sizin iรงin yรถnetir, ancak bu "redirect" yardฤฑmcฤฑ ลžimdi her ลŸeyin รงalฤฑลŸtฤฑฤŸฤฑnฤฑ test edebilmek iรงin bir *path operation* oluลŸturun: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### Statik Dosyalar UI'ฤฑnฤฑ Test Edin { #test-static-files-ui } diff --git a/docs/tr/docs/how-to/extending-openapi.md b/docs/tr/docs/how-to/extending-openapi.md index 99691946c2..9998f0bacd 100644 --- a/docs/tr/docs/how-to/extending-openapi.md +++ b/docs/tr/docs/how-to/extending-openapi.md @@ -4,7 +4,7 @@ OluลŸturulan OpenAPI ลŸemasฤฑnฤฑ deฤŸiลŸtirmeniz gereken bazฤฑ durumlar olabilir Bu bรถlรผmde bunun nasฤฑl yapฤฑlacaฤŸฤฑnฤฑ gรถreceksiniz. -## Normal sรผreรง { #the-normal-process } +## Normal Sรผreรง { #the-normal-process } Normal (varsayฤฑlan) sรผreรง ลŸรถyledir. @@ -33,7 +33,7 @@ Ve `get_openapi()` fonksiyonu ลŸu parametreleri alฤฑr: /// -## Varsayฤฑlanlarฤฑ ezme { #overriding-the-defaults } +## Varsayฤฑlanlarฤฑ Ezme { #overriding-the-defaults } Yukarฤฑdaki bilgileri kullanarak aynฤฑ yardฤฑmcฤฑ fonksiyonla OpenAPI ลŸemasฤฑnฤฑ รผretebilir ve ihtiyacฤฑnฤฑz olan her parรงayฤฑ override edebilirsiniz. @@ -43,21 +43,21 @@ Yukarฤฑdaki bilgileri kullanarak aynฤฑ yardฤฑmcฤฑ fonksiyonla OpenAPI ลŸemasฤฑn ร–nce, tรผm **FastAPI** uygulamanฤฑzฤฑ her zamanki gibi yazฤฑn: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} -### OpenAPI ลŸemasฤฑnฤฑ รผretme { #generate-the-openapi-schema } +### OpenAPI ลžemasฤฑnฤฑ รœretme { #generate-the-openapi-schema } Ardฤฑndan, bir `custom_openapi()` fonksiyonunun iรงinde aynฤฑ yardฤฑmcฤฑ fonksiyonu kullanarak OpenAPI ลŸemasฤฑnฤฑ รผretin: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} -### OpenAPI ลŸemasฤฑnฤฑ deฤŸiลŸtirme { #modify-the-openapi-schema } +### OpenAPI ลžemasฤฑnฤฑ DeฤŸiลŸtirme { #modify-the-openapi-schema } Artฤฑk OpenAPI ลŸemasฤฑndaki `info` "object"'ine รถzel bir `x-logo` ekleyerek ReDoc extension'ฤฑnฤฑ ekleyebilirsiniz: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} -### OpenAPI ลŸemasฤฑnฤฑ cache'leme { #cache-the-openapi-schema } +### OpenAPI ลžemasฤฑnฤฑ Cache'leme { #cache-the-openapi-schema } รœrettiฤŸiniz ลŸemayฤฑ saklamak iรงin `.openapi_schema` รถzelliฤŸini bir "cache" gibi kullanabilirsiniz. @@ -65,15 +65,15 @@ Bรถylece bir kullanฤฑcฤฑ API docs'larฤฑnฤฑzฤฑ her aรงtฤฑฤŸฤฑnda uygulamanฤฑz ลŸe ลžema yalnฤฑzca bir kez รผretilecektir; sonraki request'ler iรงin de aynฤฑ cache'lenmiลŸ ลŸema kullanฤฑlacaktฤฑr. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} -### Metodu override etme { #override-the-method } +### Metodu Override Etme { #override-the-method } ลžimdi `.openapi()` metodunu yeni fonksiyonunuzla deฤŸiลŸtirebilirsiniz. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} -### Kontrol edin { #check-it } +### Kontrol Edin { #check-it } http://127.0.0.1:8000/redoc adresine gittiฤŸinizde, รถzel logonuzu kullandฤฑฤŸฤฑnฤฑzฤฑ gรถreceksiniz (bu รถrnekte **FastAPI**'nin logosu): diff --git a/docs/tr/docs/how-to/general.md b/docs/tr/docs/how-to/general.md index e3154921a4..ad1ed3fbcc 100644 --- a/docs/tr/docs/how-to/general.md +++ b/docs/tr/docs/how-to/general.md @@ -14,7 +14,7 @@ Dรถndรผrmeniz gerekenden daha fazla veri dรถndรผrmediฤŸinizden emin olmak iรงin, *path operation*'larฤฑnฤฑza รถzet ve aรงฤฑklama eklemek ve bunlarฤฑ dokรผmantasyon arayรผzรผnde gรถstermek iรงin, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} dokรผmantasyonunu okuyun. -## Dokรผmantasyon Yanฤฑt Aรงฤฑklamasฤฑ - OpenAPI { #documentation-response-description-openapi } +## Dokรผmantasyon Response Aรงฤฑklamasฤฑ - OpenAPI { #documentation-response-description-openapi } Dokรผmantasyon arayรผzรผnde gรถsterilen response aรงฤฑklamasฤฑnฤฑ tanฤฑmlamak iรงin, [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} dokรผmantasyonunu okuyun. diff --git a/docs/tr/docs/how-to/graphql.md b/docs/tr/docs/how-to/graphql.md index fbf0188740..99123cf2a3 100644 --- a/docs/tr/docs/how-to/graphql.md +++ b/docs/tr/docs/how-to/graphql.md @@ -35,7 +35,7 @@ Kullanฤฑm senaryonuza gรถre farklฤฑ bir kรผtรผphaneyi tercih edebilirsiniz; anca Strawberry'yi FastAPI ile nasฤฑl entegre edebileceฤŸinize dair kรผรงรผk bir รถn izleme: -{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Strawberry hakkฤฑnda daha fazlasฤฑnฤฑ Strawberry dokรผmantasyonunda รถฤŸrenebilirsiniz. diff --git a/docs/tr/docs/how-to/index.md b/docs/tr/docs/how-to/index.md index 5ec2e0268f..928911c0e8 100644 --- a/docs/tr/docs/how-to/index.md +++ b/docs/tr/docs/how-to/index.md @@ -8,6 +8,6 @@ Projeniz iรงin ilginรง ve yararlฤฑ gรถrรผnen bir ลŸey varsa devam edin ve incele /// tip | ฤฐpucu -**FastAPI**'ฤฑ yapฤฑlandฤฑrฤฑlmฤฑลŸ bir ลŸekilde (รถnerilir) **รถฤŸrenmek** istiyorsanฤฑz bunun yerine [ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bรถlรผm bรถlรผm okuyun. +**FastAPI**'yi yapฤฑlandฤฑrฤฑlmฤฑลŸ bir ลŸekilde (รถnerilir) **รถฤŸrenmek** istiyorsanฤฑz bunun yerine [ร–ฤŸretici - Kullanฤฑcฤฑ Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bรถlรผm bรถlรผm okuyun. /// diff --git a/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 275ac5fd17..6d732c1dfa 100644 --- a/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/tr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -88,7 +88,7 @@ graph TB style V2Field fill:#f9fff3 ``` -...ancak aynฤฑ uygulamada Pydantic v1 ve v2 kullanarak **ayrฤฑ (separated)** modeller tanฤฑmlayabilirsiniz. +...ancak aynฤฑ uygulamada Pydantic v1 ve v2 kullanarak **ayrฤฑ** modeller tanฤฑmlayabilirsiniz. ```mermaid graph TB diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index 16c425f5d7..f240a96914 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -40,7 +40,7 @@ Temel รถzellikleri ลŸunlardฤฑr: * **Hฤฑzlฤฑ**: ร‡ok yรผksek performanslฤฑ, **NodeJS** ve **Go** ile eลŸit dรผzeyde (Starlette ve Pydantic sayesinde). [Mevcut en hฤฑzlฤฑ Python framework'lerinden biri](#performance). * **Kodlamasฤฑ Hฤฑzlฤฑ**: ร–zellik geliลŸtirme hฤฑzฤฑnฤฑ yaklaลŸฤฑk %200 ile %300 aralฤฑฤŸฤฑnda artฤฑrฤฑr. * * **Daha az hata**: ฤฐnsan (geliลŸtirici) kaynaklฤฑ hatalarฤฑ yaklaลŸฤฑk %40 azaltฤฑr. * -* **Sezgisel**: Harika bir editรถr desteฤŸi. Her yerde Completion. Hata ayฤฑklamaya daha az zaman. +* **Sezgisel**: Harika bir editรถr desteฤŸi. Her yerde Tamamlama. Hata ayฤฑklamaya daha az zaman. * **Kolay**: Kullanฤฑmฤฑ ve รถฤŸrenmesi kolay olacak ลŸekilde tasarlandฤฑ. Dokรผman okumaya daha az zaman. * **Kฤฑsa**: Kod tekrarฤฑnฤฑ minimize eder. Her parametre tanฤฑmฤฑndan birden fazla รถzellik. Daha az hata. * **SaฤŸlam**: Production'a hazฤฑr kod elde edersiniz. Otomatik etkileลŸimli dokรผmantasyon ile birlikte. @@ -127,7 +127,7 @@ Temel รถzellikleri ลŸunlardฤฑr: -Web API yerine terminalde kullanฤฑlacak bir CLI uygulamasฤฑ geliลŸtiriyorsanฤฑz **Typer**'a gรถz atฤฑn. +Web API yerine terminalde kullanฤฑlacak bir CLI uygulamasฤฑ geliลŸtiriyorsanฤฑz **Typer**'a gรถz atฤฑn. **Typer**, FastAPI'ฤฑn kรผรงรผk kardeลŸi. Ve hedefi CLI'larฤฑn **FastAPI'ฤฑ** olmak. โŒจ๏ธ ๐Ÿš€ @@ -368,7 +368,7 @@ item: Item * Verinin doฤŸrulanmasฤฑ: * Veri geรงersiz olduฤŸunda otomatik ve anlaลŸฤฑlฤฑr hatalar. * ร‡ok derin iรง iรงe JSON nesneleri iรงin bile doฤŸrulama. -* Girdi verisinin DรถnรผลŸรผmรผ: network'ten gelen veriyi Python verisine ve type'larฤฑna รงevirir. ลžunlardan okur: +* Girdi verisinin DรถnรผลŸรผmรผ: network'ten gelen veriyi Python verisine ve type'larฤฑna รงevirir. ลžunlardan okur: * JSON. * Path parameter'lar. * Query parameter'lar. @@ -376,7 +376,7 @@ item: Item * Header'lar. * Form'lar. * File'lar. -* ร‡ฤฑktฤฑ verisinin DรถnรผลŸรผmรผ: Python verisini ve type'larฤฑnฤฑ network verisine รงevirir (JSON olarak): +* ร‡ฤฑktฤฑ verisinin DรถnรผลŸรผmรผ: Python verisini ve type'larฤฑnฤฑ network verisine รงevirir (JSON olarak): * Python type'larฤฑnฤฑ dรถnรผลŸtรผrรผr (`str`, `int`, `float`, `bool`, `list`, vb.). * `datetime` nesneleri. * `UUID` nesneleri. @@ -439,7 +439,7 @@ Daha fazla รถzellik iรงeren daha kapsamlฤฑ bir รถrnek iรงin Dependency Injection** sistemi. +* ร‡ok gรผรงlรผ ve kullanฤฑmฤฑ kolay bir **BaฤŸฤฑmlฤฑlฤฑk Enjeksiyonu** sistemi. * **JWT tokens** ve **HTTP Basic** auth ile **OAuth2** desteฤŸi dahil gรผvenlik ve kimlik doฤŸrulama. * **ร‡ok derin iรง iรงe JSON modelleri** tanฤฑmlamak iรงin daha ileri (ama aynฤฑ derecede kolay) teknikler (Pydantic sayesinde). * Strawberry ve diฤŸer kรผtรผphaneler ile **GraphQL** entegrasyonu. @@ -524,7 +524,7 @@ Starlette tarafฤฑndan kullanฤฑlanlar: * httpx - `TestClient` kullanmak istiyorsanฤฑz gereklidir. * jinja2 - varsayฤฑlan template yapฤฑlandฤฑrmasฤฑnฤฑ kullanmak istiyorsanฤฑz gereklidir. -* python-multipart - `request.form()` ile, form "parsing" desteฤŸi istiyorsanฤฑz gereklidir. +* python-multipart - `request.form()` ile, form "ayrฤฑลŸtฤฑrma" desteฤŸi istiyorsanฤฑz gereklidir. FastAPI tarafฤฑndan kullanฤฑlanlar: @@ -534,7 +534,7 @@ FastAPI tarafฤฑndan kullanฤฑlanlar: ### `standard` BaฤŸฤฑmlฤฑlฤฑklarฤฑ Olmadan { #without-standard-dependencies } -`standard` opsiyonel baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ dahil etmek istemiyorsanฤฑz, `pip install "fastapi[standard]"` yerine `pip install fastapi` ile kurabilirsiniz. +`standard` opsiyonel baฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑ dahil etmek istemiyorsanฤฑz, `pip install fastapi` ile kurabilirsiniz. ### `fastapi-cloud-cli` Olmadan { #without-fastapi-cloud-cli } diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md index 01a3efe98c..9477e4fabc 100644 --- a/docs/tr/docs/python-types.md +++ b/docs/tr/docs/python-types.md @@ -2,9 +2,9 @@ Python, isteฤŸe baฤŸlฤฑ "type hints" (diฤŸer adฤฑyla "type annotations") desteฤŸine sahiptir. -Bu **"type hints"** veya annotations, bir deฤŸiลŸkenin type'ฤฑnฤฑ bildirmeye yarayan รถzel bir sรถzdizimidir. +Bu **"type hints"** veya annotations, bir deฤŸiลŸkenin tip'ini bildirmeye yarayan รถzel bir sรถzdizimidir. -DeฤŸiลŸkenleriniz iรงin type bildirerek, editรถrler ve araรงlar size daha iyi destek saฤŸlayabilir. +DeฤŸiลŸkenleriniz iรงin tip bildirerek, editรถrler ve araรงlar size daha iyi destek saฤŸlayabilir. Bu, Python type hints hakkฤฑnda sadece **hฤฑzlฤฑ bir eฤŸitim / bilgi tazeleme** dokรผmanฤฑdฤฑr. **FastAPI** ile kullanmak iรงin gereken minimum bilgiyi kapsar... ki aslฤฑnda bu รงok azdฤฑr. @@ -22,7 +22,7 @@ EฤŸer bir Python uzmanฤฑysanฤฑz ve type hints hakkฤฑnda her ลŸeyi zaten biliyors Basit bir รถrnekle baลŸlayalฤฑm: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Bu programฤฑ รงalฤฑลŸtฤฑrฤฑnca ลŸu รงฤฑktฤฑyฤฑ alฤฑrsฤฑnฤฑz: @@ -34,9 +34,9 @@ Fonksiyon ลŸunlarฤฑ yapar: * `first_name` ve `last_name` deฤŸerlerini alฤฑr. * `title()` ile her birinin ilk harfini bรผyรผk harfe รงevirir. -* Ortada bir boลŸluk olacak ลŸekilde Concatenates eder. +* Ortada bir boลŸluk olacak ลŸekilde BirleลŸtirir. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Dรผzenleyelim { #edit-it } @@ -78,7 +78,7 @@ Bu kadar. Bunlar "type hints": -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Bu, aลŸaฤŸฤฑdaki gibi default deฤŸerler bildirmekle aynฤฑ ลŸey deฤŸildir: @@ -106,7 +106,7 @@ Bununla birlikte, seรงenekleri gรถrerek kaydฤฑrabilirsiniz; ta ki "tanฤฑdฤฑk gel ลžu fonksiyona bakฤฑn, zaten type hints iรงeriyor: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Editรถr deฤŸiลŸkenlerin tiplerini bildiฤŸi iรงin, sadece completion deฤŸil, aynฤฑ zamanda hata kontrolleri de alฤฑrsฤฑnฤฑz: @@ -114,9 +114,9 @@ Editรถr deฤŸiลŸkenlerin tiplerini bildiฤŸi iรงin, sadece completion deฤŸil, ayn Artฤฑk bunu dรผzeltmeniz gerektiฤŸini, `age`'i `str(age)` ile string'e รงevirmeniz gerektiฤŸini biliyorsunuz: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} -## Tipleri bildirmek { #declaring-types } +## Tipleri Bildirmek { #declaring-types } Type hints bildirmek iรงin ana yeri az รถnce gรถrdรผnรผz: fonksiyon parametreleri. @@ -133,29 +133,32 @@ Sadece `str` deฤŸil, tรผm standart Python tiplerini bildirebilirsiniz. * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Tip parametreleri ile Generic tipler { #generic-types-with-type-parameters } +### `typing` modรผlรผ { #typing-module } -`dict`, `list`, `set` ve `tuple` gibi, baลŸka deฤŸerler iรงerebilen bazฤฑ veri yapฤฑlarฤฑ vardฤฑr. Ve iรง deฤŸerlerin kendi tipi de olabilir. +Bazฤฑ ek kullanฤฑm durumlarฤฑ iรงin standart kรผtรผphanedeki `typing` modรผlรผnden bazฤฑ ลŸeyleri import etmeniz gerekebilir. ร–rneฤŸin bir ลŸeyin "herhangi bir tip" olabileceฤŸini bildirmek istediฤŸinizde, `typing` iรงindeki `Any`'yi kullanabilirsiniz: -ฤฐรง tipleri olan bu tiplere "**generic**" tipler denir. Ve bunlarฤฑ, iรง tipleriyle birlikte bildirmek mรผmkรผndรผr. +```python +from typing import Any -Bu tipleri ve iรง tipleri bildirmek iรงin standart Python modรผlรผ `typing`'i kullanabilirsiniz. Bu modรผl, รถzellikle bu type hints desteฤŸi iรงin vardฤฑr. -#### Python'un daha yeni sรผrรผmleri { #newer-versions-of-python } - -`typing` kullanan sรถzdizimi, Python 3.6'dan en yeni sรผrรผmlere kadar (Python 3.9, Python 3.10, vb. dahil) tรผm sรผrรผmlerle **uyumludur**. +def some_function(data: Any): + print(data) +``` -Python geliลŸtikรงe, **daha yeni sรผrรผmler** bu type annotations iรงin daha iyi destekle gelir ve รงoฤŸu durumda type annotations bildirmek iรงin `typing` modรผlรผnรผ import edip kullanmanฤฑz bile gerekmez. +### Generic tipler { #generic-types } -Projeniz iรงin daha yeni bir Python sรผrรผmรผ seรงebiliyorsanฤฑz, bu ek sadelikten yararlanabilirsiniz. +Bazฤฑ tipler, kรถลŸeli parantez iรงinde "type parameters" alarak iรง tiplerini tanฤฑmlayabilir; รถrneฤŸin "string listesi" `list[str]` olarak bildirilir. -Tรผm dokรผmanlarda her Python sรผrรผmรผyle uyumlu รถrnekler vardฤฑr (fark olduฤŸunda). +Bu ลŸekilde type parameter alabilen tiplere **Generic types** veya **Generics** denir. -ร–rneฤŸin "**Python 3.6+**", Python 3.6 veya รผstรผyle (3.7, 3.8, 3.9, 3.10, vb. dahil) uyumludur. "**Python 3.9+**" ise Python 3.9 veya รผstรผyle (3.10 vb. dahil) uyumludur. +Aynฤฑ builtin tipleri generics olarak kullanabilirsiniz (kรถลŸeli parantez ve iรงinde tiplerle): -EฤŸer **Python'un en gรผncel sรผrรผmlerini** kullanabiliyorsanฤฑz, en gรผncel sรผrรผme ait รถrnekleri kullanฤฑn; bunlar **en iyi ve en basit sรถzdizimine** sahip olur, รถrneฤŸin "**Python 3.10+**". +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -163,11 +166,11 @@ EฤŸer **Python'un en gรผncel sรผrรผmlerini** kullanabiliyorsanฤฑz, en gรผncel s DeฤŸiลŸkeni, aynฤฑ iki nokta (`:`) sรถzdizimiyle bildirin. -Type olarak `list` yazฤฑn. +Tip olarak `list` yazฤฑn. `list`, bazฤฑ iรง tipleri barฤฑndฤฑran bir tip olduฤŸundan, bunlarฤฑ kรถลŸeli parantez iรงine yazarsฤฑnฤฑz: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | Bilgi @@ -193,7 +196,7 @@ Ve yine de editรถr bunun bir `str` olduฤŸunu bilir ve buna gรถre destek saฤŸlar. `tuple`'larฤฑ ve `set`'leri bildirmek iรงin de aynฤฑsฤฑnฤฑ yaparsฤฑnฤฑz: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} Bu ลŸu anlama gelir: @@ -208,7 +211,7 @@ Bir `dict` tanฤฑmlamak iรงin, virgรผlle ayrฤฑlmฤฑลŸ 2 type parameter verirsiniz. ฤฐkinci type parameter, `dict`'in value'larฤฑ iรงindir: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Bu ลŸu anlama gelir: @@ -220,44 +223,20 @@ Bu ลŸu anlama gelir: Bir deฤŸiลŸkenin **birkaรง tipten herhangi biri** olabileceฤŸini bildirebilirsiniz; รถrneฤŸin bir `int` veya bir `str`. -Python 3.6 ve รผzeri sรผrรผmlerde (Python 3.10 dahil), `typing` iรงinden `Union` tipini kullanabilir ve kรถลŸeli parantez iรงine kabul edilecek olasฤฑ tipleri yazabilirsiniz. - -Python 3.10'da ayrฤฑca, olasฤฑ tipleri vertical bar (`|`) ile ayฤฑrabildiฤŸiniz **yeni bir sรถzdizimi** de vardฤฑr. +Bunu tanฤฑmlamak iรงin, her iki tipi ayฤฑrmak รผzere dikey รงizgi (`|`) kullanฤฑrsฤฑnฤฑz. -//// tab | Python 3.10+ +Buna "union" denir, รงรผnkรผ deฤŸiลŸken bu iki tip kรผmesinin birleลŸimindeki herhangi bir ลŸey olabilir. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -Her iki durumda da bu, `item`'ฤฑn `int` veya `str` olabileceฤŸi anlamฤฑna gelir. +Bu, `item`'ฤฑn `int` veya `str` olabileceฤŸi anlamฤฑna gelir. #### Muhtemelen `None` { #possibly-none } Bir deฤŸerin `str` gibi bir tipi olabileceฤŸini ama aynฤฑ zamanda `None` da olabileceฤŸini bildirebilirsiniz. -Python 3.6 ve รผzeri sรผrรผmlerde (Python 3.10 dahil), `typing` modรผlรผnden `Optional` import edip kullanarak bunu bildirebilirsiniz. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Sadece `str` yerine `Optional[str]` kullanmak, aslฤฑnda deฤŸer `None` olabilecekken her zaman `str` olduฤŸunu varsaydฤฑฤŸฤฑnฤฑz hatalarฤฑ editรถrรผn yakalamanฤฑza yardฤฑmcฤฑ olmasฤฑnฤฑ saฤŸlar. - -`Optional[Something]`, aslฤฑnda `Union[Something, None]` iรงin bir kฤฑsayoldur; eลŸdeฤŸerdirler. - -Bu aynฤฑ zamanda Python 3.10'da `Something | None` kullanabileceฤŸiniz anlamฤฑna gelir: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ Bu aynฤฑ zamanda Python 3.10'da `Something | None` kullanabileceฤŸiniz anlamฤฑna //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternatif - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### `Union` veya `Optional` kullanmak { #using-union-or-optional } - -Python sรผrรผmรผnรผz 3.10'un altฤฑndaysa, benim oldukรงa **รถznel** bakฤฑลŸ aรงฤฑma gรถre kรผรงรผk bir ipucu: - -* ๐Ÿšจ `Optional[SomeType]` kullanmaktan kaรงฤฑnฤฑn -* Bunun yerine โœจ **`Union[SomeType, None]` kullanฤฑn** โœจ. - -ฤฐkisi eลŸdeฤŸerdir ve altta aynฤฑ ลŸeydir; ama ben `Optional` yerine `Union` รถnermeyi tercih ederim. ร‡รผnkรผ "**optional**" kelimesi deฤŸerin optional olduฤŸunu ima ediyor gibi durur; ama gerรงekte anlamฤฑ "deฤŸer `None` olabilir"dir. DeฤŸer optional olmasa ve hรขlรข required olsa bile. - -Bence `Union[SomeType, None]` ne anlama geldiฤŸini daha aรงฤฑk ลŸekilde ifade ediyor. - -Bu, tamamen kelimeler ve isimlendirmelerle ilgili. Ancak bu kelimeler, sizin ve ekip arkadaลŸlarฤฑnฤฑzฤฑn kod hakkฤฑnda nasฤฑl dรผลŸรผndรผฤŸรผnรผ etkileyebilir. - -ร–rnek olarak ลŸu fonksiyonu ele alalฤฑm: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -`name` parametresi `Optional[str]` olarak tanฤฑmlanmฤฑลŸ, ama **optional deฤŸil**; parametre olmadan fonksiyonu รงaฤŸฤฑramazsฤฑnฤฑz: - -```Python -say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ -``` - -`name` parametresi **hรขlรข required**'dฤฑr (*optional* deฤŸildir) รงรผnkรผ bir default deฤŸeri yoktur. Yine de `name`, deฤŸer olarak `None` kabul eder: - -```Python -say_hi(name=None) # This works, None is valid ๐ŸŽ‰ -``` - -ฤฐyi haber ลŸu ki, Python 3.10'a geรงtiฤŸinizde bununla uฤŸraลŸmanฤฑz gerekmeyecek; รงรผnkรผ tiplerin union'larฤฑnฤฑ tanฤฑmlamak iรงin doฤŸrudan `|` kullanabileceksiniz: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -Ve bรถylece `Optional` ve `Union` gibi isimlerle de uฤŸraลŸmanฤฑz gerekmeyecek. ๐Ÿ˜Ž - -#### Generic tipler { #generic-types } - -KรถลŸeli parantez iรงinde type parameter alan bu tiplere **Generic types** veya **Generics** denir, รถrneฤŸin: - -//// tab | Python 3.10+ - -Aynฤฑ builtin tipleri generics olarak kullanabilirsiniz (kรถลŸeli parantez ve iรงindeki tiplerle): - -* `list` -* `tuple` -* `set` -* `dict` - -Ve รถnceki Python sรผrรผmlerinde olduฤŸu gibi `typing` modรผlรผnden: - -* `Union` -* `Optional` -* ...and others. - -Python 3.10'da, `Union` ve `Optional` generics'lerini kullanmaya alternatif olarak, tip union'larฤฑnฤฑ bildirmek iรงin vertical bar (`|`) kullanabilirsiniz; bu รงok daha iyi ve daha basittir. - -//// - -//// tab | Python 3.9+ - -Aynฤฑ builtin tipleri generics olarak kullanabilirsiniz (kรถลŸeli parantez ve iรงindeki tiplerle): - -* `list` -* `tuple` -* `set` -* `dict` - -Ve `typing` modรผlรผnden gelen generics: - -* `Union` -* `Optional` -* ...and others. - -//// +Sadece `str` yerine `str | None` kullanmak, aslฤฑnda deฤŸer `None` olabilecekken her zaman `str` olduฤŸunu varsaydฤฑฤŸฤฑnฤฑz hatalarฤฑ editรถrรผn yakalamanฤฑza yardฤฑmcฤฑ olur. ### Tip olarak sฤฑnฤฑflar { #classes-as-types } @@ -363,11 +253,11 @@ Bir sฤฑnฤฑfฤฑ da bir deฤŸiลŸkenin tipi olarak bildirebilirsiniz. ร–rneฤŸin, adฤฑ olan bir `Person` sฤฑnฤฑfฤฑnฤฑz olsun: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Sonra bir deฤŸiลŸkeni `Person` tipinde olacak ลŸekilde bildirebilirsiniz: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} Ve sonra, yine tรผm editรถr desteฤŸini alฤฑrsฤฑnฤฑz: @@ -401,21 +291,15 @@ Daha fazlasฤฑnฤฑ รถฤŸrenmek iรงin Required Optional fields bรถlรผmรผnde okuyabilirsiniz. - -/// +Bunlarฤฑn pratikte nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ [EฤŸitim - Kullanฤฑm Kฤฑlavuzu](tutorial/index.md){.internal-link target=_blank} iรงinde รงok daha fazla gรถreceksiniz. ## Metadata Annotations ile Type Hints { #type-hints-with-metadata-annotations } -Python'da ayrฤฑca, `Annotated` kullanarak bu type hints iรงine **ek metadata** koymayฤฑ saฤŸlayan bir รถzellik de vardฤฑr. +Python'da ayrฤฑca, `Annotated` kullanarak bu type hints iรงine **ek รผstveri** koymayฤฑ saฤŸlayan bir รถzellik de vardฤฑr. -Python 3.9'dan itibaren `Annotated`, standart kรผtรผphanenin bir parรงasฤฑdฤฑr; bu yรผzden `typing` iรงinden import edebilirsiniz. +`Annotated`'ฤฑ `typing` iรงinden import edebilirsiniz. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Python'un kendisi bu `Annotated` ile bir ลŸey yapmaz. Editรถrler ve diฤŸer araรงlar iรงin tip hรขlรข `str`'dir. @@ -446,14 +330,14 @@ Ayrฤฑca kodunuzun pek รงok baลŸka Python aracฤฑ ve kรผtรผphanesiyle รงok uyumlu ...ve **FastAPI** aynฤฑ bildirimleri ลŸunlar iรงin de kullanฤฑr: -* **Gereksinimleri tanฤฑmlamak**: request path parameters, query parameters, headers, bodies, dependencies, vb. +* **Gereksinimleri tanฤฑmlamak**: request path parameters, query parameters, headers, bodies, baฤŸฤฑmlฤฑlฤฑklar (dependencies), vb. * **Veriyi dรถnรผลŸtรผrmek**: request'ten gerekli tipe. * **Veriyi doฤŸrulamak**: her request'ten gelen veriyi: * Veri geรงersiz olduฤŸunda client'a dรถnen **otomatik hatalar** รผretmek. * OpenAPI kullanarak API'yi **dokรผmante etmek**: * bu, daha sonra otomatik etkileลŸimli dokรผmantasyon kullanฤฑcฤฑ arayรผzleri tarafฤฑndan kullanฤฑlฤฑr. -Bunlarฤฑn hepsi kulaฤŸa soyut gelebilir. Merak etmeyin. Tรผm bunlarฤฑ [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank} iรงinde รงalฤฑลŸฤฑrken gรถreceksiniz. +Bunlarฤฑn hepsi kulaฤŸa soyut gelebilir. Merak etmeyin. Tรผm bunlarฤฑ [EฤŸitim - Kullanฤฑm Kฤฑlavuzu](tutorial/index.md){.internal-link target=_blank} iรงinde รงalฤฑลŸฤฑrken gรถreceksiniz. ร–nemli olan, standart Python tiplerini tek bir yerde kullanarak (daha fazla sฤฑnฤฑf, decorator vb. eklemek yerine), **FastAPI**'nin sizin iรงin iลŸin bรผyรผk kฤฑsmฤฑnฤฑ yapmasฤฑdฤฑr. diff --git a/docs/tr/docs/translation-banner.md b/docs/tr/docs/translation-banner.md index b52578f71d..7491e61b8d 100644 --- a/docs/tr/docs/translation-banner.md +++ b/docs/tr/docs/translation-banner.md @@ -4,7 +4,7 @@ Bu รงeviri, insanlar tarafฤฑndan yรถnlendirilen bir yapay zekรข ile oluลŸturuldu Orijinal anlamฤฑn yanlฤฑลŸ anlaลŸฤฑlmasฤฑ ya da kulaฤŸa doฤŸal gelmeme gibi hatalar iรงerebilir. ๐Ÿค– -[Yapay zekรขyฤฑ daha iyi yรถnlendirmemize yardฤฑmcฤฑ olarak](https://fastapi.tiangolo.com/tr/contributing/#translations) bu รงeviriyi iyileลŸtirebilirsiniz. +[Yapay zekรข LLM'ini daha iyi yรถnlendirmemize yardฤฑmcฤฑ olarak](https://fastapi.tiangolo.com/tr/contributing/#translations) bu รงeviriyi iyileลŸtirebilirsiniz. [ฤฐngilizce sรผrรผm](ENGLISH_VERSION_URL) diff --git a/docs/tr/docs/tutorial/background-tasks.md b/docs/tr/docs/tutorial/background-tasks.md index 4cb67d8224..a6dfbe5ea8 100644 --- a/docs/tr/docs/tutorial/background-tasks.md +++ b/docs/tr/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ Bu, requestโ€™ten sonra yapฤฑlmasฤฑ gereken; ancak clientโ€™ฤฑn responseโ€™u alm ร–nce `BackgroundTasks`โ€™i import edin ve *path operation function*โ€™ฤฑnฤฑzda `BackgroundTasks` tip bildirimi olan bir parametre tanฤฑmlayฤฑn: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI**, sizin iรงin `BackgroundTasks` tipinde bir obje oluลŸturur ve onu ilgili parametre olarak geรงirir. @@ -31,13 +31,13 @@ Bu รถrnekte gรถrev fonksiyonu bir dosyaya yazacaktฤฑr (email gรถndermeyi simรผle Ve yazma iลŸlemi `async` ve `await` kullanmadฤฑฤŸฤฑ iรงin fonksiyonu normal `def` ile tanฤฑmlarฤฑz: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Arka Plan Gรถrevini Ekleyin { #add-the-background-task } *Path operation function*โ€™ฤฑnฤฑzฤฑn iรงinde, gรถrev fonksiyonunuzu `.add_task()` metodu ile *background tasks* objesine ekleyin: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` ลŸu argรผmanlarฤฑ alฤฑr: diff --git a/docs/tr/docs/tutorial/bigger-applications.md b/docs/tr/docs/tutorial/bigger-applications.md index d8a4b8208b..9dbaae601d 100644 --- a/docs/tr/docs/tutorial/bigger-applications.md +++ b/docs/tr/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ Bu module iรงin *path operation*โ€™larฤฑ `APIRouter` kullanarak oluลŸturabilirsi `FastAPI` classโ€™ฤฑnda yaptฤฑฤŸฤฑnฤฑz gibi import edip bir "instance" oluลŸturursunuz: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### `APIRouter` ile *Path Operations* { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ Sonra bunu kullanarak *path operation*โ€™larฤฑnฤฑzฤฑ tanฤฑmlarsฤฑnฤฑz. `FastAPI` classโ€™ฤฑnฤฑ nasฤฑl kullanฤฑyorsanฤฑz aynฤฑ ลŸekilde kullanฤฑn: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} `APIRouter`โ€™ฤฑ "mini bir `FastAPI`" classโ€™ฤฑ gibi dรผลŸรผnebilirsiniz. @@ -117,7 +117,7 @@ Bu yรผzden onlarฤฑ ayrฤฑ bir `dependencies` moduleโ€™รผne koyuyoruz (`app/depend ลžimdi, รถzel bir `X-Token` header'ฤฑnฤฑ okumak iรงin basit bir dependency kullanalฤฑm: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | ฤฐpucu @@ -149,7 +149,7 @@ Bu moduleโ€™deki tรผm *path operation*โ€™larฤฑn ลŸu ortak รถzelliklere sahip old Dolayฤฑsฤฑyla bunlarฤฑ her *path operation*โ€™a tek tek eklemek yerine `APIRouter`โ€™a ekleyebiliriz. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} Her *path operation*โ€™ฤฑn pathโ€™i aลŸaฤŸฤฑdaki gibi `/` ile baลŸlamak zorunda olduฤŸundan: @@ -208,7 +208,7 @@ Dependency functionโ€™ฤฑnฤฑ ise `app.dependencies` moduleโ€™รผnden, yani `app/de Bu yรผzden dependencyโ€™ler iรงin `..` ile relative import kullanฤฑyoruz: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### Relative Import Nasฤฑl ร‡alฤฑลŸฤฑr { #how-relative-imports-work } @@ -279,7 +279,7 @@ Artฤฑk nasฤฑl รงalฤฑลŸtฤฑฤŸฤฑnฤฑ bildiฤŸinize gรถre, uygulamalarฤฑnฤฑz ne kadar Ama yine de belirli bir *path operation*โ€™a uygulanacak _ek_ `tags` tanฤฑmlayabilir, ayrฤฑca o *path operation*โ€™a รถzel `responses` ekleyebiliriz: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | ฤฐpucu @@ -305,13 +305,13 @@ Normal ลŸekilde bir `FastAPI` classโ€™ฤฑ oluลŸturursunuz. Hatta her `APIRouter` iรงin olan dependencyโ€™lerle birleลŸtirilecek [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank} bile tanฤฑmlayabilirsiniz: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### `APIRouter` Import Edin { #import-the-apirouter } ลžimdi `APIRouter` iรงeren diฤŸer submoduleโ€™leri import ediyoruz: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} `app/routers/users.py` ve `app/routers/items.py` dosyalarฤฑ aynฤฑ Python packageโ€™i olan `app`โ€™in parรงasฤฑ olan submoduleโ€™ler olduฤŸu iรงin, onlarฤฑ "relative import" ile tek bir nokta `.` kullanarak import edebiliriz. @@ -374,13 +374,13 @@ from .routers.users import router Bu yรผzden ikisini de aynฤฑ dosyada kullanabilmek iรงin submoduleโ€™leri doฤŸrudan import ediyoruz: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### `users` ve `items` iรงin `APIRouter`โ€™larฤฑ Dahil Edin { #include-the-apirouters-for-users-and-items } ลžimdi `users` ve `items` submoduleโ€™lerindeki `router`โ€™larฤฑ dahil edelim: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | Bilgi @@ -420,13 +420,13 @@ Bu dosyada, kurumunuzun birden fazla proje arasฤฑnda paylaลŸtฤฑฤŸฤฑ bazฤฑ admin Bu รถrnekte รงok basit olacak. Ancak kurum iรงinde baลŸka projelerle paylaลŸฤฑldฤฑฤŸฤฑ iรงin, bunu deฤŸiลŸtirip `prefix`, `dependencies`, `tags` vs. doฤŸrudan `APIRouter`โ€™a ekleyemediฤŸimizi varsayalฤฑm: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Yine de bu `APIRouter`โ€™ฤฑ dahil ederken รถzel bir `prefix` ayarlamak istiyoruz ki tรผm *path operation*โ€™larฤฑ `/admin` ile baลŸlasฤฑn; ayrฤฑca bu projede hรขlihazฤฑrda kullandฤฑฤŸฤฑmฤฑz `dependencies` ile gรผvene almak, `tags` ve `responses` eklemek istiyoruz. Orijinal `APIRouter`โ€™ฤฑ deฤŸiลŸtirmeden, bu parametreleri `app.include_router()`โ€™a vererek hepsini tanฤฑmlayabiliriz: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} Bรถylece orijinal `APIRouter` deฤŸiลŸmeden kalฤฑr; yani aynฤฑ `app/internal/admin.py` dosyasฤฑnฤฑ kurum iรงindeki diฤŸer projelerle de paylaลŸmaya devam edebiliriz. @@ -447,7 +447,7 @@ Dolayฤฑsฤฑyla รถrneฤŸin diฤŸer projeler aynฤฑ `APIRouter`โ€™ฤฑ farklฤฑ bir authe Burada bunu yapฤฑyoruz... sadece yapabildiฤŸimizi gรถstermek iรงin ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} ve `app.include_router()` ile eklenen diฤŸer tรผm *path operation*โ€™larla birlikte doฤŸru ลŸekilde รงalฤฑลŸฤฑr. diff --git a/docs/tr/docs/tutorial/body-multiple-params.md b/docs/tr/docs/tutorial/body-multiple-params.md index 29970ca40e..4cd381b869 100644 --- a/docs/tr/docs/tutorial/body-multiple-params.md +++ b/docs/tr/docs/tutorial/body-multiple-params.md @@ -106,12 +106,6 @@ Varsayฤฑlan olarak tekil deฤŸerler query parametresi olarak yorumlandฤฑฤŸฤฑ iรงi q: str | None = None ``` -Ya da Python 3.9'da: - -```Python -q: Union[str, None] = None -``` - ร–rneฤŸin: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/tr/docs/tutorial/body-nested-models.md b/docs/tr/docs/tutorial/body-nested-models.md index b4ffef3f15..b661d175d6 100644 --- a/docs/tr/docs/tutorial/body-nested-models.md +++ b/docs/tr/docs/tutorial/body-nested-models.md @@ -95,7 +95,7 @@ Yine, sadece bu tanฤฑmฤฑ yaparak **FastAPI** ile ลŸunlarฤฑ elde edersiniz: `str`, `int`, `float` vb. normal tekil tiplerin yanฤฑnda, `str`โ€™den tรผreyen daha karmaลŸฤฑk tekil tipleri de kullanabilirsiniz. -Tรผm seรงenekleri gรถrmek iรงin Pydantic Type Overview sayfasฤฑna gรถz atฤฑn. Sonraki bรถlรผmde bazฤฑ รถrnekleri gรถreceksiniz. +Tรผm seรงenekleri gรถrmek iรงin Pydantic Tรผrlerine Genel BakฤฑลŸ sayfasฤฑna gรถz atฤฑn. Sonraki bรถlรผmde bazฤฑ รถrnekleri gรถreceksiniz. ร–rneฤŸin `Image` modelinde bir `url` alanฤฑmฤฑz olduฤŸuna gรถre, bunu `str` yerine Pydanticโ€™in `HttpUrl` tipinden bir instance olacak ลŸekilde tanฤฑmlayabiliriz: @@ -163,7 +163,7 @@ images: list[Image] ลŸu รถrnekte olduฤŸu gibi: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Her yerde editรถr desteฤŸi { #editor-support-everywhere } @@ -193,7 +193,7 @@ Burada gรถreceฤŸimiz ลŸey de bu. Bu durumda, `int` keyโ€™lere ve `float` valueโ€™lara sahip olduฤŸu sรผrece herhangi bir `dict` kabul edersiniz: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ฤฐpucu diff --git a/docs/tr/docs/tutorial/body.md b/docs/tr/docs/tutorial/body.md index 0557ef737a..47fee67014 100644 --- a/docs/tr/docs/tutorial/body.md +++ b/docs/tr/docs/tutorial/body.md @@ -155,7 +155,7 @@ Fonksiyon parametreleri ลŸu ลŸekilde tanฤฑnฤฑr: FastAPI, `q` deฤŸerinin zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` default deฤŸerinden anlayacaktฤฑr. -`str | None` (Python 3.10+) veya `Union[str, None]` (Python 3.9+) iรงindeki `Union`, FastAPI tarafฤฑndan bu deฤŸerin zorunlu olmadฤฑฤŸฤฑnฤฑ belirlemek iรงin kullanฤฑlmaz; FastAPI bunun zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` default deฤŸeri olduฤŸu iรงin bilir. +`str | None`, FastAPI tarafฤฑndan bu deฤŸerin zorunlu olmadฤฑฤŸฤฑnฤฑ belirlemek iรงin kullanฤฑlmaz; FastAPI bunun zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` default deฤŸeri olduฤŸu iรงin bilir. Ancak type annotation'larฤฑnฤฑ eklemek, editor'รผnรผzรผn size daha iyi destek vermesini ve hatalarฤฑ yakalamasฤฑnฤฑ saฤŸlar. diff --git a/docs/tr/docs/tutorial/cookie-param-models.md b/docs/tr/docs/tutorial/cookie-param-models.md index a5bf515609..0fa399c6ae 100644 --- a/docs/tr/docs/tutorial/cookie-param-models.md +++ b/docs/tr/docs/tutorial/cookie-param-models.md @@ -1,18 +1,18 @@ -# Cookie Parameter Models { #cookie-parameter-models } +# Cookie Parametre Modelleri { #cookie-parameter-models } -Birbirleriyle iliลŸkili bir **cookie** grubunuz varsa, bunlarฤฑ tanฤฑmlamak iรงin bir **Pydantic model** oluลŸturabilirsiniz. +Birbirleriyle iliลŸkili bir **cookie** grubunuz varsa, bunlarฤฑ tanฤฑmlamak iรงin bir **Pydantic model** oluลŸturabilirsiniz. ๐Ÿช -Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tรผm parametreler iรงin validation ve metadata'yฤฑ tek seferde tanฤฑmlayabilirsiniz. +Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tรผm parametreler iรงin validation ve metadata'yฤฑ tek seferde tanฤฑmlayabilirsiniz. ๐Ÿ˜Ž /// note | Not -Bu รถzellik FastAPI `0.115.0` sรผrรผmรผnden beri desteklenmektedir. +This is supported since FastAPI version `0.115.0`. ๐Ÿค“ /// /// tip | ฤฐpucu -Aynฤฑ teknik `Query`, `Cookie` ve `Header` iรงin de geรงerlidir. +Aynฤฑ teknik `Query`, `Cookie` ve `Header` iรงin de geรงerlidir. ๐Ÿ˜Ž /// @@ -42,11 +42,11 @@ Ancak verileri **doldurup** "Execute" dรผฤŸmesine tฤฑklasanฤฑz bile, docs UI **J /// -## Fazladan Cookies'leri Yasaklayฤฑn { #forbid-extra-cookies } +## Fazladan Cookie'leri Yasaklayฤฑn { #forbid-extra-cookies } Bazฤฑ รถzel kullanฤฑm senaryolarฤฑnda (muhtemelen รงok yaygฤฑn deฤŸildir) almak istediฤŸiniz cookie'leri **kฤฑsฤฑtlamak** isteyebilirsiniz. -API'niz artฤฑk kendi cookie consent'ฤฑnฤฑ kontrol etme gรผcรผne sahip. +API'niz artฤฑk kendi cookie onayฤฑ'nฤฑ kontrol etme gรผcรผne sahip. ๐Ÿคช๐Ÿช Pydantic'in model configuration'ฤฑnฤฑ kullanarak `extra` olan herhangi bir field'ฤฑ `forbid` edebilirsiniz: @@ -54,9 +54,9 @@ Pydantic'in model configuration'ฤฑnฤฑ kullanarak `extra` olan herhangi bir field Bir client **fazladan cookie** gรถndermeye รงalฤฑลŸฤฑrsa, bir **error** response alฤฑr. -Onayฤฑnฤฑzฤฑ almak iรงin bunca รงaba harcayan zavallฤฑ cookie banner'larฤฑ... API'nin bunu reddetmesi iรงin. +Onayฤฑnฤฑzฤฑ almak iรงin bunca รงaba harcayan zavallฤฑ cookie banner'larฤฑ... API'nin bunu reddetmesi iรงin. ๐Ÿช -ร–rneฤŸin client, deฤŸeri `good-list-please` olan bir `santa_tracker` cookie'si gรถndermeye รงalฤฑลŸฤฑrsa, client `santa_tracker` cookie is not allowed diyen bir **error** response alฤฑr: +ร–rneฤŸin client, deฤŸeri `good-list-please` olan bir `santa_tracker` cookie'si gรถndermeye รงalฤฑลŸฤฑrsa, client `santa_tracker` cookie'ye izin verilmiyor diyen bir **error** response alฤฑr: ```json { @@ -73,4 +73,4 @@ Onayฤฑnฤฑzฤฑ almak iรงin bunca รงaba harcayan zavallฤฑ cookie banner'larฤฑ... **cookies** tanฤฑmlamak iรงin **Pydantic model**'lerini kullanabilirsiniz. ๐Ÿ˜Ž +**FastAPI**'de **cookie** tanฤฑmlamak iรงin **Pydantic model**'lerini kullanabilirsiniz. ๐Ÿ˜Ž diff --git a/docs/tr/docs/tutorial/cookie-params.md b/docs/tr/docs/tutorial/cookie-params.md index 18eedab7f0..28b57fd7e1 100644 --- a/docs/tr/docs/tutorial/cookie-params.md +++ b/docs/tr/docs/tutorial/cookie-params.md @@ -1,4 +1,4 @@ -# ร‡erez (Cookie) Parametreleri { #cookie-parameters } +# Cookie (ร‡erez) Parametreleri { #cookie-parameters } `Query` ve `Path` parametrelerini tanฤฑmladฤฑฤŸฤฑnฤฑz ลŸekilde Cookie parametreleri tanฤฑmlayabilirsiniz. @@ -26,20 +26,20 @@ Ancak `fastapi`'dan `Query`, `Path`, `Cookie` ve diฤŸerlerini import ettiฤŸinizd /// info | Bilgi -ร‡erezleri tanฤฑmlamak iรงin `Cookie` kullanmanฤฑz gerekir, aksi halde parametreler query parametreleri olarak yorumlanฤฑr. +Cookie'leri tanฤฑmlamak iรงin `Cookie` kullanmanฤฑz gerekir, aksi halde parametreler query parametreleri olarak yorumlanฤฑr. /// /// info | Bilgi -**Tarayฤฑcฤฑlar รงerezleri** รถzel ลŸekillerde ve arka planda iลŸlediฤŸi iรงin, **JavaScript**'in onlara dokunmasฤฑna kolayca izin **vermezler**. +**Tarayฤฑcฤฑlar cookie'leri** รถzel ลŸekillerde ve arka planda iลŸlediฤŸi iรงin, **JavaScript**'in onlara dokunmasฤฑna kolayca izin **vermezler**. -`/docs` adresindeki **API docs UI**'a giderseniz, *path operation*'larฤฑnฤฑz iรงin รงerezlerin **dokรผmantasyonunu** gรถrebilirsiniz. +`/docs` adresindeki **API docs UI**'a giderseniz, *path operation*'larฤฑnฤฑz iรงin cookie'lerin **dokรผmantasyonunu** gรถrebilirsiniz. -Ancak **veriyi doldurup** "Execute" dรผฤŸmesine tฤฑklasanฤฑz bile, docs UI **JavaScript** ile รงalฤฑลŸtฤฑฤŸฤฑ iรงin รงerezler gรถnderilmez ve herhangi bir deฤŸer yazmamฤฑลŸsฤฑnฤฑz gibi bir **hata** mesajฤฑ gรถrรผrsรผnรผz. +Ancak **veriyi doldurup** "Execute" dรผฤŸmesine tฤฑklasanฤฑz bile, docs UI **JavaScript** ile รงalฤฑลŸtฤฑฤŸฤฑ iรงin cookie'ler gรถnderilmez ve herhangi bir deฤŸer yazmamฤฑลŸsฤฑnฤฑz gibi bir **hata** mesajฤฑ gรถrรผrsรผnรผz. /// ## ร–zet { #recap } -`Query` ve `Path` ile aynฤฑ ortak deseni kullanarak, รงerezleri `Cookie` ile tanฤฑmlayฤฑn. +`Query` ve `Path` ile aynฤฑ ortak deseni kullanarak, cookie'leri `Cookie` ile tanฤฑmlayฤฑn. diff --git a/docs/tr/docs/tutorial/cors.md b/docs/tr/docs/tutorial/cors.md index aae560022a..c3c853fddf 100644 --- a/docs/tr/docs/tutorial/cors.md +++ b/docs/tr/docs/tutorial/cors.md @@ -46,7 +46,7 @@ Ayrฤฑca backendโ€™in ลŸunlara izin verip vermediฤŸini de belirtebilirsiniz: * Belirli HTTP methodโ€™larฤฑ (`POST`, `PUT`) veya wildcard `"*"` ile hepsini. * Belirli HTTP headerโ€™larฤฑ veya wildcard `"*"` ile hepsini. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} `CORSMiddleware` implementasyonu tarafฤฑndan kullanฤฑlan varsayฤฑlan parametreler kฤฑsฤฑtlayฤฑcฤฑdฤฑr; bu nedenle tarayฤฑcฤฑlarฤฑn Cross-Domain baฤŸlamฤฑnda kullanmasฤฑna izin vermek iรงin belirli originโ€™leri, methodโ€™larฤฑ veya headerโ€™larฤฑ aรงฤฑkรงa etkinleลŸtirmeniz gerekir. @@ -78,7 +78,7 @@ Bu durumda middleware gelen requestโ€™i intercept eder ve uygun CORS headerโ€™la ## Daha Fazla Bilgi { #more-info } -CORS hakkฤฑnda daha fazla bilgi iรงin Mozilla CORS dokรผmantasyonuna bakฤฑn. +CORS hakkฤฑnda daha fazla bilgi iรงin Mozilla CORS dokรผmantasyonuna bakฤฑn. /// note | Teknik Detaylar diff --git a/docs/tr/docs/tutorial/debugging.md b/docs/tr/docs/tutorial/debugging.md index 54d5c9252a..839277b6db 100644 --- a/docs/tr/docs/tutorial/debugging.md +++ b/docs/tr/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Visual Studio Code veya PyCharm gibi editรถrรผnรผzde debugger'ฤฑ baฤŸlayabilirsi FastAPI uygulamanฤฑzda `uvicorn`'ฤฑ import edip doฤŸrudan รงalฤฑลŸtฤฑrฤฑn: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### `__name__ == "__main__"` Hakkฤฑnda { #about-name-main } diff --git a/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md index 9ee57cb291..989e93b406 100644 --- a/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/tr/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ Artฤฑk bu class'ฤฑ kullanarak dependency'nizi tanฤฑmlayabilirsiniz. Yukarฤฑdaki kodda `CommonQueryParams`'ฤฑ iki kez yazdฤฑฤŸฤฑmฤฑza dikkat edin: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu @@ -137,7 +137,7 @@ FastAPI tanฤฑmlanan parametreleri buradan รงฤฑkarฤฑr ve aslฤฑnda รงaฤŸฤฑracaฤŸฤฑ Bu durumda, ลŸuradaki ilk `CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu @@ -163,7 +163,7 @@ commons: CommonQueryParams ... Hatta ลŸunu bile yazabilirsiniz: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu @@ -197,7 +197,7 @@ Ancak type'ฤฑ belirtmeniz รถnerilir; bรถylece editor'รผnรผz `commons` parametres Ama burada bir miktar kod tekrarฤฑmฤฑz olduฤŸunu gรถrรผyorsunuz; `CommonQueryParams`'ฤฑ iki kez yazฤฑyoruz: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu @@ -225,7 +225,7 @@ Bu รถzel durumlarda ลŸunu yapabilirsiniz: ลžunu yazmak yerine: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...ลŸunu yazarsฤฑnฤฑz: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ Annotated Olmadan +//// tab | Python 3.10+ Annotated Olmadan /// tip | ฤฐpucu diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 4903aec4a4..cbb6363424 100644 --- a/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ Bu gibi durumlarda, `Depends` ile bir *path operation function* parametresi tan Bu, `Depends()` รถฤŸelerinden oluลŸan bir `list` olmalฤฑdฤฑr: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} Bu dependency'ler normal dependency'lerle aynฤฑ ลŸekilde รงalฤฑลŸtฤฑrฤฑlฤฑr/รงรถzรผlรผr. Ancak (eฤŸer bir deฤŸer dรถndรผrรผyorlarsa) bu deฤŸer *path operation function*'ฤฑnฤฑza aktarฤฑlmaz. @@ -44,13 +44,13 @@ Normalde kullandฤฑฤŸฤฑnฤฑz aynฤฑ dependency *function*'larฤฑnฤฑ burada da kullan Request gereksinimleri (header'lar gibi) veya baลŸka alt dependency'ler tanฤฑmlayabilirler: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### Exception Fฤฑrlatmak { #raise-exceptions } Bu dependency'ler, normal dependency'lerde olduฤŸu gibi `raise` ile exception fฤฑrlatabilir: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### Return DeฤŸerleri { #return-values } @@ -58,7 +58,7 @@ Ayrฤฑca deฤŸer dรถndรผrebilirler ya da dรถndรผrmeyebilirler; dรถnen deฤŸer kulla Yani baลŸka bir yerde zaten kullandฤฑฤŸฤฑnฤฑz, deฤŸer dรถndรผren normal bir dependency'yi tekrar kullanabilirsiniz; deฤŸer kullanฤฑlmasa bile dependency รงalฤฑลŸtฤฑrฤฑlacaktฤฑr: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## Bir *Path Operation* Grubu ฤฐรงin Dependency'ler { #dependencies-for-a-group-of-path-operations } diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md index bd025f799b..445110ae02 100644 --- a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,12 +1,12 @@ # `yield` ile Dependency'ler { #dependencies-with-yield } -FastAPI, iลŸini bitirdikten sonra ek adฤฑmlar รงalฤฑลŸtฤฑran dependency'leri destekler. +FastAPI, iลŸini bitirdikten sonra ek adฤฑmlar รงalฤฑลŸtฤฑran dependency'leri destekler. Bunu yapmak iรงin `return` yerine `yield` kullanฤฑn ve ek adฤฑmlarฤฑ (kodu) `yield` satฤฑrฤฑndan sonra yazฤฑn. /// tip | ฤฐpucu -Her dependency iรงin yalnฤฑzca **bir kez** `yield` kullandฤฑฤŸฤฑnฤฑzdan emin olun. +Her dependency iรงin yalnฤฑzca bir kez `yield` kullandฤฑฤŸฤฑnฤฑzdan emin olun. /// @@ -29,15 +29,15 @@ Hatta FastAPI bu iki decorator'ฤฑ iรงeride (internally) kullanฤฑr. Response oluลŸturulmadan รถnce yalnฤฑzca `yield` satฤฑrฤฑna kadar olan (ve `yield` dahil) kod รงalฤฑลŸtฤฑrฤฑlฤฑr: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} `yield` edilen deฤŸer, *path operation*'lara ve diฤŸer dependency'lere enjekte edilen (injected) deฤŸerdir: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} Response'dan sonra `yield` satฤฑrฤฑnฤฑ takip eden kod รงalฤฑลŸtฤฑrฤฑlฤฑr: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | ฤฐpucu @@ -57,7 +57,7 @@ Dolayฤฑsฤฑyla `except SomeException` ile dependency iรงinde o spesifik exception Aynฤฑ ลŸekilde, exception olsun ya da olmasฤฑn รงฤฑkฤฑลŸ (exit) adฤฑmlarฤฑnฤฑn รงalฤฑลŸtฤฑrฤฑlmasฤฑnฤฑ garanti etmek iรงin `finally` kullanabilirsiniz. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## `yield` ile Alt Dependency'ler { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ Her boyutta ve ลŸekilde alt dependency'ler ve alt dependency "aฤŸaรงlarฤฑ" (tree ร–rneฤŸin, `dependency_c`, `dependency_b`'ye; `dependency_b` de `dependency_a`'ya baฤŸlฤฑ olabilir: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} Ve hepsi `yield` kullanabilir. @@ -75,7 +75,7 @@ Bu durumda `dependency_c`, exit code'unu รงalฤฑลŸtฤฑrabilmek iรงin `dependency_b Aynฤฑ ลŸekilde `dependency_b` de exit code'u iรงin `dependency_a`'dan gelen deฤŸerin (burada `dep_a`) eriลŸilebilir olmasฤฑna ihtiyaรง duyar. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} Benzer ลŸekilde, bazฤฑ dependency'ler `yield`, bazฤฑlarฤฑ `return` kullanabilir ve bunlarฤฑn bazฤฑlarฤฑ diฤŸerlerine baฤŸlฤฑ olabilir. @@ -109,7 +109,7 @@ Ama ihtiyaรง duyarsanฤฑz diye burada. ๐Ÿค“ /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} Exception yakalayฤฑp buna gรถre รถzel bir response oluลŸturmak istiyorsanฤฑz bir [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} oluลŸturun. @@ -117,7 +117,7 @@ Exception yakalayฤฑp buna gรถre รถzel bir response oluลŸturmak istiyorsanฤฑz bir `yield` kullanan bir dependency iรงinde `except` ile bir exception yakalar ve bunu tekrar fฤฑrlatmazsanฤฑz (ya da yeni bir exception fฤฑrlatmazsanฤฑz), FastAPI normal Python'da olduฤŸu gibi bir exception olduฤŸunu fark edemez: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} Bu durumda client, biz `HTTPException` veya benzeri bir ลŸey fฤฑrlatmadฤฑฤŸฤฑmฤฑz iรงin olmasฤฑ gerektiฤŸi gibi *HTTP 500 Internal Server Error* response'u gรถrรผr; ancak server **hiรง log รผretmez** ve hatanฤฑn ne olduฤŸuna dair baลŸka bir iลŸaret de olmaz. ๐Ÿ˜ฑ @@ -127,7 +127,7 @@ Bu durumda client, biz `HTTPException` veya benzeri bir ลŸey fฤฑrlatmadฤฑฤŸฤฑmฤฑ Aynฤฑ exception'ฤฑ `raise` ile tekrar fฤฑrlatabilirsiniz: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Artฤฑk client yine aynฤฑ *HTTP 500 Internal Server Error* response'unu alฤฑr, ama server log'larda bizim รถzel `InternalError`'ฤฑmฤฑzฤฑ gรถrรผr. ๐Ÿ˜Ž @@ -190,7 +190,7 @@ Normalde `yield` kullanan dependency'lerin exit code'u, client'a response gรถnde Ama *path operation function*'dan dรถndรผkten sonra dependency'yi kullanmayacaฤŸฤฑnฤฑzฤฑ biliyorsanฤฑz, `Depends(scope="function")` kullanarak FastAPI'ye dependency'yi *path operation function* dรถndรผkten sonra kapatmasฤฑnฤฑ, ancak **response gรถnderilmeden รถnce** kapatmasฤฑnฤฑ sรถyleyebilirsiniz. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` ลŸu deฤŸerleri alabilen bir `scope` parametresi alฤฑr: @@ -234,7 +234,6 @@ participant operation as Path Operation `yield` kullanan dependency'ler, zaman iรงinde farklฤฑ kullanฤฑm senaryolarฤฑnฤฑ kapsamak ve bazฤฑ sorunlarฤฑ dรผzeltmek iรงin geliลŸti. FastAPI'nin farklฤฑ sรผrรผmlerinde nelerin deฤŸiลŸtiฤŸini gรถrmek isterseniz, advanced guide'da ลŸu bรถlรผmรผ okuyabilirsiniz: [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}. - ## Context Managers { #context-managers } ### "Context Managers" Nedir? { #what-are-context-managers } @@ -269,7 +268,7 @@ Python'da Context Manager'larฤฑ, Dependency Injection** sistemine sahiptir. +**FastAPI**, รงok gรผรงlรผ ama aynฤฑ zamanda sezgisel bir **BaฤŸฤฑmlฤฑlฤฑk Enjeksiyonu** sistemine sahiptir. Kullanฤฑmฤฑ รงok basit olacak ลŸekilde tasarlanmฤฑลŸtฤฑr ve herhangi bir geliลŸtiricinin diฤŸer bileลŸenleri **FastAPI** ile entegre etmesini kolaylaลŸtฤฑrฤฑr. diff --git a/docs/tr/docs/tutorial/dependencies/sub-dependencies.md b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md index 184db839bc..ab196d829f 100644 --- a/docs/tr/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query BaฤŸฤฑmlฤฑlฤฑklarฤฑnฤฑzdan biri aynฤฑ *path operation* iรงin birden fazla kez tanฤฑmlanฤฑrsa (รถrneฤŸin birden fazla baฤŸฤฑmlฤฑlฤฑฤŸฤฑn ortak bir alt baฤŸฤฑmlฤฑlฤฑฤŸฤฑ varsa), **FastAPI** o alt baฤŸฤฑmlฤฑlฤฑฤŸฤฑ request baลŸฤฑna yalnฤฑzca bir kez รงaฤŸฤฑracaฤŸฤฑnฤฑ bilir. -Dรถnen deฤŸeri bir "cache" iรงinde saklar ve aynฤฑ request iรงinde buna ihtiyaรง duyan tรผm "dependant"lara aktarฤฑr; bรถylece aynฤฑ request iรงin baฤŸฤฑmlฤฑlฤฑฤŸฤฑ tekrar tekrar รงaฤŸฤฑrmaz. +Dรถnen deฤŸeri bir "รถnbellek" iรงinde saklar ve aynฤฑ request iรงinde buna ihtiyaรง duyan tรผm "dependant"lara aktarฤฑr; bรถylece aynฤฑ request iรงin baฤŸฤฑmlฤฑlฤฑฤŸฤฑ tekrar tekrar รงaฤŸฤฑrmaz. Daha ileri bir senaryoda, "cached" deฤŸeri kullanmak yerine aynฤฑ request iรงinde her adฤฑmda (muhtemelen birden fazla kez) baฤŸฤฑmlฤฑlฤฑฤŸฤฑn รงaฤŸrฤฑlmasฤฑ gerektiฤŸini biliyorsanฤฑz, `Depends` kullanฤฑrken `use_cache=False` parametresini ayarlayabilirsiniz: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ Annotated olmayan +//// tab | Python 3.10+ Annotated olmayan /// tip | ฤฐpucu diff --git a/docs/tr/docs/tutorial/extra-data-types.md b/docs/tr/docs/tutorial/extra-data-types.md index 464d3a82a9..534efefc49 100644 --- a/docs/tr/docs/tutorial/extra-data-types.md +++ b/docs/tr/docs/tutorial/extra-data-types.md @@ -23,32 +23,32 @@ KullanabileceฤŸiniz ek veri tiplerinden bazฤฑlarฤฑ ลŸunlardฤฑr: * `UUID`: * Birรงok veritabanฤฑ ve sistemde ID olarak yaygฤฑn kullanฤฑlan, standart bir "Universally Unique Identifier". - * request ve response'larda `str` olarak temsil edilir. + * request'lerde ve response'larda `str` olarak temsil edilir. * `datetime.datetime`: * Python `datetime.datetime`. - * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15T15:53:00+05:00`. + * request'lerde ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15T15:53:00+05:00`. * `datetime.date`: * Python `datetime.date`. - * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15`. + * request'lerde ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `2008-09-15`. * `datetime.time`: * Python `datetime.time`. - * request ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `14:23:55.003`. + * request'lerde ve response'larda ISO 8601 formatฤฑnda bir `str` olarak temsil edilir, รถrn: `14:23:55.003`. * `datetime.timedelta`: * Python `datetime.timedelta`. - * request ve response'larda toplam saniye sayฤฑsฤฑnฤฑ ifade eden bir `float` olarak temsil edilir. + * request'lerde ve response'larda toplam saniye sayฤฑsฤฑnฤฑ ifade eden bir `float` olarak temsil edilir. * Pydantic, bunu ayrฤฑca bir "ISO 8601 time diff encoding" olarak temsil etmeye de izin verir, daha fazla bilgi iรงin dokรผmanlara bakฤฑn. * `frozenset`: - * request ve response'larda, `set` ile aynฤฑ ลŸekilde ele alฤฑnฤฑr: + * request'lerde ve response'larda, `set` ile aynฤฑ ลŸekilde ele alฤฑnฤฑr: * request'lerde bir list okunur, tekrarlar kaldฤฑrฤฑlฤฑr ve `set`'e dรถnรผลŸtรผrรผlรผr. * response'larda `set`, `list`'e dรถnรผลŸtรผrรผlรผr. * รœretilen schema, `set` deฤŸerlerinin benzersiz olduฤŸunu belirtir (JSON Schema'nฤฑn `uniqueItems` รถzelliฤŸini kullanarak). * `bytes`: * Standart Python `bytes`. - * request ve response'larda `str` gibi ele alฤฑnฤฑr. + * request'lerde ve response'larda `str` gibi ele alฤฑnฤฑr. * รœretilen schema, bunun `binary` "format"ฤฑna sahip bir `str` olduฤŸunu belirtir. * `Decimal`: * Standart Python `Decimal`. - * request ve response'larda `float` ile aynฤฑ ลŸekilde iลŸlenir. + * request'lerde ve response'larda `float` ile aynฤฑ ลŸekilde iลŸlenir. * Geรงerli tรผm Pydantic veri tiplerini burada gรถrebilirsiniz: Pydantic data types. ## ร–rnek { #example } diff --git a/docs/tr/docs/tutorial/extra-models.md b/docs/tr/docs/tutorial/extra-models.md index 9aae28e05f..f2bcf7a010 100644 --- a/docs/tr/docs/tutorial/extra-models.md +++ b/docs/tr/docs/tutorial/extra-models.md @@ -8,7 +8,7 @@ Bu durum รถzellikle kullanฤฑcฤฑ modellerinde sฤฑk gรถrรผlรผr, รงรผnkรผ: * **output modeli** `password` iรงermemelidir. * **database modeli** bรผyรผk ihtimalle hash'lenmiลŸ bir `password` tutmalฤฑdฤฑr. -/// danger +/// danger | Tehlike Kullanฤฑcฤฑnฤฑn dรผz metin (plaintext) `password`'รผnรผ asla saklamayฤฑn. Her zaman sonradan doฤŸrulayabileceฤŸiniz "gรผvenli bir hash" saklayฤฑn. @@ -132,7 +132,7 @@ UserInDB( ) ``` -/// warning +/// warning | Uyarฤฑ Ek destek fonksiyonlarฤฑ olan `fake_password_hasher` ve `fake_save_user` sadece verinin olasฤฑ bir akฤฑลŸฤฑnฤฑ gรถstermek iรงindir; elbette gerรงek bir gรผvenlik saฤŸlamazlar. @@ -164,7 +164,7 @@ OpenAPI'de bu `anyOf` ile tanฤฑmlanฤฑr. Bunu yapmak iรงin standart Python type hint'i olan `typing.Union`'ฤฑ kullanฤฑn: -/// note +/// note | Not Bir `Union` tanฤฑmlarken en spesifik type'ฤฑ รถnce, daha az spesifik olanฤฑ sonra ekleyin. AลŸaฤŸฤฑdaki รถrnekte daha spesifik olan `PlaneItem`, `Union[PlaneItem, CarItem]` iรงinde `CarItem`'dan รถnce gelir. @@ -190,9 +190,9 @@ Ancak bunu `response_model=PlaneItem | CarItem` atamasฤฑna koyarsak hata alฤฑrฤฑ Aynฤฑ ลŸekilde, nesne listesi dรถndรผren response'larฤฑ da tanฤฑmlayabilirsiniz. -Bunun iรงin standart Python `typing.List`'i (ya da Python 3.9 ve รผzeri iรงin sadece `list`) kullanฤฑn: +Bunun iรงin standart Python `list`'i kullanฤฑn: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## Rastgele `dict` ile Response { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ Bir Pydantic modeli kullanmadan, sadece key ve value type'larฤฑnฤฑ belirterek d Bu, geรงerli field/attribute adlarฤฑnฤฑ (Pydantic modeli iรงin gerekli olurdu) รถnceden bilmiyorsanฤฑz kullanฤฑลŸlฤฑdฤฑr. -Bu durumda `typing.Dict` (ya da Python 3.9 ve รผzeri iรงin sadece `dict`) kullanabilirsiniz: +Bu durumda `dict` kullanabilirsiniz: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## ร–zet { #recap } diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md index 332f5c5590..4b645778f7 100644 --- a/docs/tr/docs/tutorial/first-steps.md +++ b/docs/tr/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ En sade FastAPI dosyasฤฑ ลŸu ลŸekilde gรถrรผnรผr: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Yukarฤฑdakini `main.py` adlฤฑ bir dosyaya kopyalayฤฑn. @@ -183,7 +183,7 @@ Bu kadar! Artฤฑk uygulamanฤฑza o URL รผzerinden eriลŸebilirsiniz. โœจ ### Adฤฑm 1: `FastAPI` import edin { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI`, API'nฤฑz iรงin tรผm iลŸlevselliฤŸi saฤŸlayan bir Python class'ฤฑdฤฑr. @@ -197,7 +197,7 @@ Bu kadar! Artฤฑk uygulamanฤฑza o URL รผzerinden eriลŸebilirsiniz. โœจ ### Adฤฑm 2: bir `FastAPI` "instance"ฤฑ oluลŸturun { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} Burada `app` deฤŸiลŸkeni `FastAPI` class'ฤฑnฤฑn bir "instance"ฤฑ olacaktฤฑr. @@ -266,12 +266,12 @@ Biz de bunlara "**operation**" diyeceฤŸiz. #### Bir *path operation decorator* tanฤฑmlayฤฑn { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} `@app.get("/")`, **FastAPI**'a hemen altฤฑndaki fonksiyonun ลŸuraya giden request'leri ele almakla sorumlu olduฤŸunu sรถyler: * path `/` -* get operation kullanarak +* get operation kullanarak /// info | `@decorator` Bilgisi @@ -320,7 +320,7 @@ Bu bizim "**path operation function**"ฤฑmฤฑz: * **operation**: `get`. * **function**: "decorator"รผn altฤฑndaki fonksiyondur (`@app.get("/")`'in altฤฑndaki). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Bu bir Python fonksiyonudur. @@ -332,7 +332,7 @@ Bu durumda, bu bir `async` fonksiyondur. Bunu `async def` yerine normal bir fonksiyon olarak da tanฤฑmlayabilirsiniz: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | Not @@ -342,7 +342,7 @@ EฤŸer farkฤฑ bilmiyorsanฤฑz, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurr ### Adฤฑm 5: iรงeriฤŸi dรถndรผrรผn { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Bir `dict`, `list`, `str`, `int` vb. tekil deฤŸerler dรถndรผrebilirsiniz. diff --git a/docs/tr/docs/tutorial/handling-errors.md b/docs/tr/docs/tutorial/handling-errors.md index a4d6937922..a74e1a76ad 100644 --- a/docs/tr/docs/tutorial/handling-errors.md +++ b/docs/tr/docs/tutorial/handling-errors.md @@ -25,7 +25,7 @@ Clientโ€™a hata iรงeren HTTP responseโ€™larฤฑ dรถndรผrmek iรงin `HTTPException` ### `HTTPException`โ€™ฤฑ Import Etme { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### Kodunuzda Bir `HTTPException` Raise Etme { #raise-an-httpexception-in-your-code } @@ -39,7 +39,7 @@ Bir deฤŸer dรถndรผrmek yerine exception raise etmenin faydasฤฑ, Dependencies ve Bu รถrnekte, client var olmayan bir ID ile bir item istediฤŸinde, `404` status codeโ€™u ile bir exception raise edelim: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### Ortaya ร‡ฤฑkan Response { #the-resulting-response } @@ -77,7 +77,7 @@ Muhtemelen bunu doฤŸrudan kendi kodunuzda kullanmanฤฑz gerekmeyecek. Ama ileri seviye bir senaryo iรงin ihtiyaรง duyarsanฤฑz, รถzel headerโ€™lar ekleyebilirsiniz: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## ร–zel Exception Handlerโ€™larฤฑ Kurmak { #install-custom-exception-handlers } @@ -89,7 +89,7 @@ Ve bu exceptionโ€™ฤฑ FastAPI ile global olarak handle etmek istiyorsunuz. `@app.exception_handler()` ile รถzel bir exception handler ekleyebilirsiniz: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} Burada `/unicorns/yolo` iรงin request atarsanฤฑz, *path operation* bir `UnicornException` `raise` eder. @@ -127,7 +127,7 @@ Override etmek iรงin `RequestValidationError`โ€™ฤฑ import edin ve exception hand Exception handler, bir `Request` ve exceptionโ€™ฤฑ alฤฑr. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} Artฤฑk `/items/foo`โ€™ya giderseniz, ลŸu varsayฤฑlan JSON hatasฤฑ yerine: @@ -159,7 +159,7 @@ Benzer ลŸekilde `HTTPException` handlerโ€™ฤฑnฤฑ da override edebilirsiniz. ร–rneฤŸin bu hatalar iรงin JSON yerine plain text response dรถndรผrmek isteyebilirsiniz: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | Teknik Detaylar @@ -183,7 +183,7 @@ Ancak bu, eฤŸer sadece stringโ€™e รงevirip bu bilgiyi doฤŸrudan response olarak Uygulamanฤฑzฤฑ geliลŸtirirken bodyโ€™yi logโ€™lamak, debug etmek, kullanฤฑcฤฑya dรถndรผrmek vb. iรงin bunu kullanabilirsiniz. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} ลžimdi ลŸu gibi geรงersiz bir item gรถndermeyi deneyin: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException Exceptionโ€™ฤฑ, **FastAPI**โ€™nin aynฤฑ varsayฤฑlan exception handlerโ€™larฤฑyla birlikte kullanmak isterseniz, varsayฤฑlan exception handlerโ€™larฤฑ `fastapi.exception_handlers` iรงinden import edip yeniden kullanabilirsiniz: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} Bu รถrnekte sadece oldukรงa aรงฤฑklayฤฑcฤฑ bir mesajla hatayฤฑ yazdฤฑrฤฑyorsunuz; ama fikir anlaลŸฤฑlฤฑyor. Exceptionโ€™ฤฑ kullanฤฑp ardฤฑndan varsayฤฑlan exception handlerโ€™larฤฑ olduฤŸu gibi yeniden kullanabilirsiniz. diff --git a/docs/tr/docs/tutorial/index.md b/docs/tr/docs/tutorial/index.md index f672c9e20b..6047e83ca4 100644 --- a/docs/tr/docs/tutorial/index.md +++ b/docs/tr/docs/tutorial/index.md @@ -62,7 +62,7 @@ Editรถrรผnรผzde kullanmak FastAPI'nin avantajlarฤฑnฤฑ gerรงekten gรถsterir: ne k ฤฐlk adฤฑm FastAPI'yi kurmaktฤฑr. -Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, etkinleลŸtirin ve ardฤฑndan **FastAPI'yi kurun**: +Bir [sanal ortam](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan emin olun, etkinleลŸtirin ve ardฤฑndan **FastAPI'yi kurun**:
diff --git a/docs/tr/docs/tutorial/metadata.md b/docs/tr/docs/tutorial/metadata.md index dacd68cf56..0cc5adee4e 100644 --- a/docs/tr/docs/tutorial/metadata.md +++ b/docs/tr/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ OpenAPI spesifikasyonunda ve otomatik API dokรผman arayรผzlerinde kullanฤฑlan ลŸ ลžu ลŸekilde ayarlayabilirsiniz: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | ฤฐpucu @@ -36,7 +36,7 @@ OpenAPI 3.1.0 ve FastAPI 0.99.0 sรผrรผmรผnden itibaren, `license_info` iรงinde ` ร–rneฤŸin: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## Tag'ler iรงin Metadata { #metadata-for-tags } @@ -58,7 +58,7 @@ Her sรถzlรผk ลŸunlarฤฑ iรงerebilir: Tag'leriniz iรงin metadata oluลŸturup `openapi_tags` parametresine geรงin: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} Aรงฤฑklamalarฤฑn iรงinde Markdown kullanabileceฤŸinizi unutmayฤฑn; รถrneฤŸin "login" kalฤฑn (**login**) ve "fancy" italik (_fancy_) olarak gรถsterilecektir. @@ -72,7 +72,7 @@ KullandฤฑฤŸฤฑnฤฑz tรผm tag'ler iรงin metadata eklemek zorunda deฤŸilsiniz. *path operation*'larฤฑnฤฑzฤฑ (ve `APIRouter`'larฤฑ) farklฤฑ tag'lere atamak iรงin `tags` parametresini kullanฤฑn: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | Bilgi @@ -100,7 +100,7 @@ Ancak bunu `openapi_url` parametresiyle yapฤฑlandฤฑrabilirsiniz. ร–rneฤŸin `/api/v1/openapi.json` adresinden sunulacak ลŸekilde ayarlamak iรงin: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} OpenAPI ลŸemasฤฑnฤฑ tamamen kapatmak isterseniz `openapi_url=None` ayarlayabilirsiniz; bu, onu kullanan dokรผmantasyon arayรผzlerini de devre dฤฑลŸฤฑ bฤฑrakฤฑr. @@ -117,4 +117,4 @@ Dahil gelen iki dokรผmantasyon arayรผzรผnรผ yapฤฑlandฤฑrabilirsiniz: ร–rneฤŸin Swagger UI'yi `/documentation` adresinden sunup ReDoc'u kapatmak iรงin: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/tr/docs/tutorial/middleware.md b/docs/tr/docs/tutorial/middleware.md index 68222265e7..7ee0ef2491 100644 --- a/docs/tr/docs/tutorial/middleware.md +++ b/docs/tr/docs/tutorial/middleware.md @@ -31,7 +31,7 @@ Middleware fonksiyonu ลŸunlarฤฑ alฤฑr: * Ardฤฑndan ilgili *path operation* tarafฤฑndan รผretilen `response`'u dรถndรผrรผr. * Sonrasฤฑnda `response`'u dรถndรผrmeden รถnce ayrฤฑca deฤŸiลŸtirebilirsiniz. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} /// tip | ฤฐpucu @@ -57,7 +57,7 @@ Ayrฤฑca `response` รผretildikten sonra, geri dรถndรผrmeden รถnce de kod รงalฤฑลŸ ร–rneฤŸin, request'i iลŸleyip response รผretmenin kaรง saniye sรผrdรผฤŸรผnรผ iรงeren `X-Process-Time` adlฤฑ รถzel bir header ekleyebilirsiniz: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} /// tip | ฤฐpucu @@ -92,4 +92,4 @@ Bu stack davranฤฑลŸฤฑ, middleware'lerin รถngรถrรผlebilir ve kontrol edilebilir b DiฤŸer middleware'ler hakkฤฑnda daha fazlasฤฑnฤฑ daha sonra [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank} bรถlรผmรผnde okuyabilirsiniz. -Bir sonraki bรถlรผmde, middleware ile CORS'un nasฤฑl ele alฤฑnacaฤŸฤฑnฤฑ gรถreceksiniz. +Bir sonraki bรถlรผmde, middleware ile CORS'un nasฤฑl ele alฤฑnacaฤŸฤฑnฤฑ gรถreceksiniz. diff --git a/docs/tr/docs/tutorial/path-operation-configuration.md b/docs/tr/docs/tutorial/path-operation-configuration.md index 3fe24dc0a4..c65d3696f8 100644 --- a/docs/tr/docs/tutorial/path-operation-configuration.md +++ b/docs/tr/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ Bu durumlarda tagโ€™leri bir `Enum` iรงinde tutmak mantฤฑklฤฑ olabilir. **FastAPI** bunu dรผz stringโ€™lerde olduฤŸu gibi aynฤฑ ลŸekilde destekler: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## ร–zet ve aรงฤฑklama { #summary-and-description } @@ -54,9 +54,9 @@ Bir `summary` ve `description` ekleyebilirsiniz: {* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} -## Docstringโ€™den Description { #description-from-docstring } +## Docstringโ€™den Aรงฤฑklama { #description-from-docstring } -Aรงฤฑklamalar genelde uzun olur ve birden fazla satฤฑra yayฤฑlฤฑr; bu yรผzden *path operation* aรงฤฑklamasฤฑnฤฑ, fonksiyonun iรงinde docstring olarak tanฤฑmlayabilirsiniz; **FastAPI** de onu buradan okur. +Aรงฤฑklamalar genelde uzun olur ve birden fazla satฤฑra yayฤฑlฤฑr; bu yรผzden *path operation* aรงฤฑklamasฤฑnฤฑ, fonksiyonun iรงinde docstring olarak tanฤฑmlayabilirsiniz; **FastAPI** de onu buradan okur. Docstring iรงinde Markdown yazabilirsiniz; doฤŸru ลŸekilde yorumlanฤฑr ve gรถsterilir (docstring girintisi dikkate alฤฑnarak). @@ -90,9 +90,9 @@ Bu yรผzden siz saฤŸlamazsanฤฑz, **FastAPI** otomatik olarak "Successful response ## Bir *path operation*โ€™ฤฑ Deprecate Etmek { #deprecate-a-path-operation } -Bir *path operation*โ€™ฤฑ kaldฤฑrmadan, deprecated olarak iลŸaretlemeniz gerekiyorsa `deprecated` parametresini verin: +Bir *path operation*โ€™ฤฑ kaldฤฑrmadan, deprecated olarak iลŸaretlemeniz gerekiyorsa `deprecated` parametresini verin: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} Interactive docsโ€™ta deprecated olduฤŸu net ลŸekilde iลŸaretlenecektir: diff --git a/docs/tr/docs/tutorial/path-params-numeric-validations.md b/docs/tr/docs/tutorial/path-params-numeric-validations.md index e0118d71da..63506a1f24 100644 --- a/docs/tr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/tr/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Bu **FastAPI** iรงin รถnemli deฤŸildir. FastAPI parametreleri isimlerine, tipler Dolayฤฑsฤฑyla fonksiyonunuzu ลŸรถyle tanฤฑmlayabilirsiniz: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Ancak ลŸunu unutmayฤฑn: `Annotated` kullanฤฑrsanฤฑz bu problem olmaz; รงรผnkรผ `Query()` veya `Path()` iรงin fonksiyon parametresi default deฤŸerlerini kullanmฤฑyorsunuz. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Parametreleri ฤฐhtiyacฤฑnฤฑza Gรถre Sฤฑralayฤฑn: Kรผรงรผk Hileler { #order-the-parameters-as-you-need-tricks } @@ -81,15 +81,15 @@ Ancak ลŸunu unutmayฤฑn: `Annotated` kullanฤฑrsanฤฑz bu problem olmaz; รงรผnkรผ ` Fonksiyonun ilk parametresi olarak `*` geรงin. -Python bu `*` ile bir ลŸey yapmaz; ama bundan sonraki tรผm parametrelerin keyword argument (anahtar-deฤŸer รงiftleri) olarak รงaฤŸrฤฑlmasฤฑ gerektiฤŸini bilir; buna kwargs da denir. Default deฤŸerleri olmasa bile. +Python bu `*` ile bir ลŸey yapmaz; ama bundan sonraki tรผm parametrelerin keyword argument (anahtar-deฤŸer รงiftleri) olarak รงaฤŸrฤฑlmasฤฑ gerektiฤŸini bilir; buna kwargs da denir. Default deฤŸerleri olmasa bile. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### `Annotated` ile Daha ฤฐyi { #better-with-annotated } ลžunu da unutmayฤฑn: `Annotated` kullanฤฑrsanฤฑz, fonksiyon parametresi default deฤŸerlerini kullanmadฤฑฤŸฤฑnฤฑz iรงin bu sorun ortaya รงฤฑkmaz ve muhtemelen `*` kullanmanฤฑz da gerekmez. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Sayฤฑ DoฤŸrulamalarฤฑ: Bรผyรผk EลŸit { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Python bu `*` ile bir ลŸey yapmaz; ama bundan sonraki tรผm parametrelerin keywor Burada `ge=1` ile, `item_id` deฤŸerinin `1`'den "`g`reater than or `e`qual" olacak ลŸekilde bir tam sayฤฑ olmasฤฑ gerekir. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Sayฤฑ DoฤŸrulamalarฤฑ: Bรผyรผk ve Kรผรงรผk EลŸit { #number-validations-greater-than-and-less-than-or-equal } @@ -106,19 +106,19 @@ Aynฤฑsฤฑ ลŸunlar iรงin de geรงerlidir: * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Sayฤฑ DoฤŸrulamalarฤฑ: `float` DeฤŸerler, Bรผyรผk ve Kรผรงรผk { #number-validations-floats-greater-than-and-less-than } Sayฤฑ doฤŸrulamalarฤฑ `float` deฤŸerler iรงin de รงalฤฑลŸฤฑr. -Burada gt tanฤฑmlayabilmek (sadece ge deฤŸil) รถnemli hale gelir. ร‡รผnkรผ รถrneฤŸin bir deฤŸerin `0`'dan bรผyรผk olmasฤฑnฤฑ isteyebilirsiniz; `1`'den kรผรงรผk olsa bile. +Burada gt tanฤฑmlayabilmek (sadece ge deฤŸil) รถnemli hale gelir. ร‡รผnkรผ รถrneฤŸin bir deฤŸerin `0`'dan bรผyรผk olmasฤฑnฤฑ isteyebilirsiniz; `1`'den kรผรงรผk olsa bile. Bu durumda `0.5` geรงerli bir deฤŸer olur. Ancak `0.0` veya `0` geรงerli olmaz. -Aynฤฑsฤฑ lt iรงin de geรงerlidir. +Aynฤฑsฤฑ lt iรงin de geรงerlidir. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ร–zet { #recap } diff --git a/docs/tr/docs/tutorial/path-params.md b/docs/tr/docs/tutorial/path-params.md index db676f1eed..cbcec05d4c 100644 --- a/docs/tr/docs/tutorial/path-params.md +++ b/docs/tr/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Python string biรงimlemede kullanฤฑlan sรถzdizimiyle path "parametreleri"ni veya "deฤŸiลŸkenleri"ni tanฤฑmlayabilirsiniz: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} Path parametresi `item_id`'nin deฤŸeri, fonksiyonunuza `item_id` argรผmanฤฑ olarak aktarฤฑlacaktฤฑr. @@ -16,7 +16,7 @@ Yani, bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp conversion { #data-conversion } +## Veri dรถnรผลŸtรผrme { #data-conversion } Bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp tarayฤฑcฤฑnฤฑzda http://127.0.0.1:8000/items/3 adresini aรงarsanฤฑz, ลŸรถyle bir response gรถrรผrsรผnรผz: @@ -38,7 +38,7 @@ Bu รถrneฤŸi รงalฤฑลŸtฤฑrฤฑp tarayฤฑcฤฑnฤฑzda "parsing" saฤŸlar. +Yani, bu tip tanฤฑmฤฑyla birlikte **FastAPI** size otomatik request "ayrฤฑลŸtฤฑrma" saฤŸlar. /// @@ -118,13 +118,13 @@ Sonra belirli bir kullanฤฑcฤฑ hakkฤฑnda, kullanฤฑcฤฑ ID'si ile veri almak iรงin *Path operation*'lar sฤฑrayla deฤŸerlendirildiฤŸi iรงin, `/users/me` iรงin olan path'in `/users/{user_id}` olandan รถnce tanฤฑmlandฤฑฤŸฤฑndan emin olmanฤฑz gerekir: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} Aksi halde, `/users/{user_id}` iรงin olan path, `"me"` deฤŸerini `user_id` parametresi olarak aldฤฑฤŸฤฑnฤฑ "dรผลŸรผnerek" `/users/me` iรงin de eลŸleลŸir. Benzer ลŸekilde, bir path operation'ฤฑ yeniden tanฤฑmlayamazsฤฑnฤฑz: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} Path รถnce eลŸleลŸtiฤŸi iรงin her zaman ilk olan kullanฤฑlฤฑr. @@ -140,11 +140,11 @@ Bir *path operation*'ฤฑnฤฑz *path parameter* alฤฑyorsa ama olasฤฑ geรงerli *path Sonra, kullanฤฑlabilir geรงerli deฤŸerler olacak sabit deฤŸerli class attribute'larฤฑ oluลŸturun: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | ฤฐpucu -Merak ediyorsanฤฑz: "AlexNet", "ResNet" ve "LeNet", Makine ร–ฤŸrenmesi modellerinin sadece isimleridir. +Merak ediyorsanฤฑz: "AlexNet", "ResNet" ve "LeNet", Makine ร–ฤŸrenmesi modellerinin sadece isimleridir. /// @@ -152,7 +152,7 @@ Merak ediyorsanฤฑz: "AlexNet", "ResNet" ve "LeNet", Makine ร–ฤŸrenmesi parsing" +* Veri "ayrฤฑลŸtฤฑrma" * Veri doฤŸrulama * API annotation ve otomatik dokรผmantasyon diff --git a/docs/tr/docs/tutorial/query-params-str-validations.md b/docs/tr/docs/tutorial/query-params-str-validations.md index 18f0249e54..3bdbd7aae7 100644 --- a/docs/tr/docs/tutorial/query-params-str-validations.md +++ b/docs/tr/docs/tutorial/query-params-str-validations.md @@ -16,7 +16,7 @@ FastAPI, `q`โ€™nun zorunlu olmadฤฑฤŸฤฑnฤฑ `= None` varsayฤฑlan deฤŸerinden anlar /// -## Ek doฤŸrulama { #additional-validation } +## Ek DoฤŸrulama { #additional-validation } `q` opsiyonel olsa bile, verildiฤŸi durumda **uzunluฤŸunun 50 karakteri geรงmemesini** zorlayacaฤŸฤฑz. @@ -47,40 +47,16 @@ Daha eski bir sรผrรผm kullanฤฑyorsanฤฑz `Annotated` kullanmaya รงalฤฑลŸฤฑrken ha ลžu tip anotasyonuna sahiptik: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ลžimdi bunu `Annotated` ile saracaฤŸฤฑz; ลŸรถyle olacak: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Bu iki sรผrรผm de aynฤฑ anlama gelir: `q`, `str` veya `None` olabilen bir parametredir ve varsayฤฑlan olarak `None`โ€™dฤฑr. ลžimdi iลŸin eฤŸlenceli kฤฑsmฤฑna geรงelim. ๐ŸŽ‰ @@ -109,7 +85,7 @@ FastAPI artฤฑk ลŸunlarฤฑ yapacak: ## Alternatif (eski): Varsayฤฑlan deฤŸer olarak `Query` { #alternative-old-query-as-the-default-value } -FastAPIโ€™nin รถnceki sรผrรผmlerinde (0.95.0 รถncesi) `Query`โ€™yi `Annotated` iรงine koymak yerine, parametrenizin varsayฤฑlan deฤŸeri olarak kullanmanฤฑz gerekiyordu. Etrafta bu ลŸekilde yazฤฑlmฤฑลŸ kod gรถrme ihtimaliniz yรผksek; bu yรผzden aรงฤฑklayalฤฑm. +FastAPIโ€™nin รถnceki sรผrรผmlerinde ( 0.95.0 รถncesi) `Query`โ€™yi `Annotated` iรงine koymak yerine, parametrenizin varsayฤฑlan deฤŸeri olarak kullanmanฤฑz gerekiyordu. Etrafta bu ลŸekilde yazฤฑlmฤฑลŸ kod gรถrme ihtimaliniz yรผksek; bu yรผzden aรงฤฑklayalฤฑm. /// tip | ฤฐpucu @@ -131,6 +107,7 @@ q: str | None = Query(default=None) ...parametreyi `None` varsayฤฑlan deฤŸeriyle opsiyonel yapar; ลŸununla aynฤฑ: + ```Python q: str | None = None ``` @@ -179,7 +156,7 @@ Fonksiyon parametrelerindeki varsayฤฑlan deฤŸer stiline gรถre **`Annotated` kull Aynฤฑ fonksiyonu FastAPI olmadan **baลŸka yerlerde** de **รงaฤŸฤฑrabilirsiniz** ve **beklendiฤŸi gibi รงalฤฑลŸฤฑr**. EฤŸer **zorunlu** bir parametre varsa (varsayฤฑlan deฤŸer yoksa) editรถrรผnรผz hata ile bunu belirtir; ayrฤฑca gerekli parametreyi vermeden รงalฤฑลŸtฤฑrฤฑrsanฤฑz **Python** da ลŸikayet eder. -`Annotated` kullanmayฤฑp bunun yerine **(eski) varsayฤฑlan deฤŸer stilini** kullanฤฑrsanฤฑz, o fonksiyonu FastAPI olmadan **baลŸka yerlerde** รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑzda doฤŸru รงalฤฑลŸmasฤฑ iรงin argรผmanlarฤฑ geรงmeniz gerektiฤŸini **hatฤฑrlamak** zorunda kalฤฑrsฤฑnฤฑz; yoksa deฤŸerler beklediฤŸinizden farklฤฑ olur (รถr. `str` yerine `QueryInfo` veya benzeri). รœstelik editรถrรผnรผz de ลŸikayet etmez ve Python da fonksiyonu รงalฤฑลŸtฤฑrฤฑrken ลŸikayet etmez; ancak iรงerideki operasyonlar hata verince ortaya รงฤฑkar. +`Annotated` kullanmayฤฑp bunun yerine **(eski) varsayฤฑlan deฤŸer stilini** kullanฤฑrsanฤฑz, o fonksiyonu FastAPI olmadan **baลŸka yerlerde** รงaฤŸฤฑrdฤฑฤŸฤฑnฤฑzda doฤŸru รงalฤฑลŸmasฤฑ iรงin argรผmanlarฤฑ geรงmeniz gerektiฤŸini **hatฤฑrlamak** zorunda kalฤฑrsฤฑnฤฑz; yoksa deฤŸerler beklediฤŸinizden farklฤฑ olur (รถr. `QueryInfo` veya benzeri). รœstelik editรถrรผnรผz de ลŸikayet etmez ve Python da fonksiyonu รงalฤฑลŸtฤฑrฤฑrken ลŸikayet etmez; ancak iรงerideki operasyonlar hata verince ortaya รงฤฑkar. `Annotated` birden fazla metadata anotasyonu alabildiฤŸi iรงin, artฤฑk aynฤฑ fonksiyonu Typer gibi baลŸka araรงlarla da kullanabilirsiniz. ๐Ÿš€ @@ -191,7 +168,7 @@ Aynฤฑ fonksiyonu FastAPI olmadan **baลŸka yerlerde** de **รงaฤŸฤฑrabilirsiniz** ## Regular expression ekleyin { #add-regular-expressions } -Parametrenin eลŸleลŸmesi gereken bir `pattern` regular expression tanฤฑmlayabilirsiniz: +Parametrenin eลŸleลŸmesi gereken bir `pattern` dรผzenli ifade tanฤฑmlayabilirsiniz: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +188,7 @@ Elbette `None` dฤฑลŸฤฑnda varsayฤฑlan deฤŸerler de kullanabilirsiniz. ร–rneฤŸin `q` query parametresi iรงin `min_length` deฤŸerini `3` yapmak ve varsayฤฑlan deฤŸer olarak `"fixedquery"` vermek istediฤŸinizi dรผลŸรผnelim: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Not @@ -233,7 +210,7 @@ q: str q: str | None = None ``` -Ancak biz artฤฑk `Query` ile tanฤฑmlฤฑyoruz; รถrneฤŸin ลŸรถyle: +Acak biz artฤฑk `Query` ile tanฤฑmlฤฑyoruz; รถrneฤŸin ลŸรถyle: ```Python q: Annotated[str | None, Query(min_length=3)] = None @@ -241,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Dolayฤฑsฤฑyla `Query` kullanฤฑrken bir deฤŸeri zorunlu yapmak istediฤŸinizde, varsayฤฑlan deฤŸer tanฤฑmlamamanฤฑz yeterlidir: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Zorunlu ama `None` olabilir { #required-can-be-none } @@ -292,7 +269,7 @@ EtkileลŸimli API dokรผmanlarฤฑ da buna gรถre gรผncellenir ve birden fazla deฤŸer Hiรง deฤŸer verilmezse varsayฤฑlan bir `list` de tanฤฑmlayabilirsiniz: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ลžu adrese giderseniz: @@ -315,7 +292,7 @@ http://localhost:8000/items/ `list[str]` yerine doฤŸrudan `list` de kullanabilirsiniz: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Not @@ -371,7 +348,7 @@ O zaman bir `alias` tanฤฑmlayabilirsiniz; bu alias, parametre deฤŸerini bulmak i Diyelim ki artฤฑk bu parametreyi istemiyorsunuz. -Bazฤฑ clientโ€™lar hรขlรข kullandฤฑฤŸฤฑ iรงin bir sรผre tutmanฤฑz gerekiyor, ama dokรผmanlarฤฑn bunu aรงฤฑkรงa deprecated olarak gรถstermesini istiyorsunuz. +Bazฤฑ clientโ€™lar hรขlรข kullandฤฑฤŸฤฑ iรงin bir sรผre tutmanฤฑz gerekiyor, ama dokรผmanlarฤฑn bunu aรงฤฑkรงa deprecated olarak gรถstermesini istiyorsunuz. O zaman `Query`โ€™ye `deprecated=True` parametresini geรงin: @@ -401,7 +378,7 @@ Pydanticโ€™te ISBN kitap numarasฤฑ iรงin `isbn-` ile veya IMDB film URL IDโ€™si iรงin `imdb-` ile baลŸladฤฑฤŸฤฑnฤฑ kontrol eder: +ร–rneฤŸin bu custom validator, bir item IDโ€™sinin ISBN kitap numarasฤฑ iรงin `isbn-` ile veya IMDB film URL IDโ€™si iรงin `imdb-` ile baลŸladฤฑฤŸฤฑnฤฑ kontrol eder: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,9 +412,9 @@ Fark ettiniz mi? `value.startswith()` ile bir string, tuple alabilir ve tuple i #### Rastgele Bir Item { #a-random-item } -`data.items()` ile, her dictionary รถฤŸesi iรงin key ve value iรงeren tupleโ€™lardan oluลŸan bir iterable object elde ederiz. +`data.items()` ile, her dictionary รถฤŸesi iรงin key ve value iรงeren tupleโ€™lardan oluลŸan bir yinelemeli nesne elde ederiz. -Bu iterable objectโ€™i `list(data.items())` ile dรผzgรผn bir `list`โ€™e รงeviririz. +Bu yinelemeli nesneyi `list(data.items())` ile dรผzgรผn bir `list`โ€™e รงeviririz. Ardฤฑndan `random.choice()` ile listโ€™ten **rastgele bir deฤŸer** alฤฑrฤฑz; yani `(id, name)` iรงeren bir tuple elde ederiz. ลžuna benzer: `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md index 89cfa3fb35..4a9f688ca3 100644 --- a/docs/tr/docs/tutorial/query-params.md +++ b/docs/tr/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Fonksiyonda path parametrelerinin parรงasฤฑ olmayan diฤŸer parametreleri tanฤฑmladฤฑฤŸฤฑnฤฑzda, bunlar otomatik olarak "query" parametreleri olarak yorumlanฤฑr. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} Query, bir URL'de `?` iลŸaretinden sonra gelen ve `&` karakterleriyle ayrฤฑlan anahtar-deฤŸer รงiftlerinin kรผmesidir. @@ -24,7 +24,7 @@ Ancak, bunlarฤฑ Python tipleriyle (yukarฤฑdaki รถrnekte `int` olarak) tanฤฑmlad Path parametreleri iรงin geรงerli olan aynฤฑ sรผreรง query parametreleri iรงin de geรงerlidir: * Editรถr desteฤŸi (tabii ki) -* Veri "parsing" +* Veri "ayrฤฑลŸtฤฑrma" * Veri doฤŸrulama * Otomatik dokรผmantasyon @@ -46,7 +46,7 @@ http://127.0.0.1:8000/items/ http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -Ancak รถrneฤŸin ลŸuraya giderseniz: +Namunak รถrneฤŸin ลŸuraya giderseniz: ``` http://127.0.0.1:8000/items/?skip=20 @@ -128,7 +128,7 @@ Belirli bir deฤŸer eklemek istemiyor ama sadece opsiyonel olmasฤฑnฤฑ istiyorsan Ancak bir query parametresini zorunlu yapmak istediฤŸinizde, herhangi bir varsayฤฑlan deฤŸer tanฤฑmlamamanฤฑz yeterlidir: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Burada query parametresi `needy`, `str` tipinde zorunlu bir query parametresidir. diff --git a/docs/tr/docs/tutorial/request-files.md b/docs/tr/docs/tutorial/request-files.md index 0bbc557e01..8ebef15e2f 100644 --- a/docs/tr/docs/tutorial/request-files.md +++ b/docs/tr/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ Bunun nedeni, upload edilen dosyalarฤฑn "form data" olarak gรถnderilmesidir. `fastapi` iรงinden `File` ve `UploadFile` import edin: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## `File` Parametrelerini Tanฤฑmlayฤฑn { #define-file-parameters } `Body` veya `Form` iรงin yaptฤฑฤŸฤฑnฤฑz gibi dosya parametreleri oluลŸturun: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | Bilgi @@ -54,7 +54,7 @@ Ancak bazฤฑ durumlarda `UploadFile` kullanmak size fayda saฤŸlayabilir. Tipi `UploadFile` olan bir dosya parametresi tanฤฑmlayฤฑn: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} `UploadFile` kullanmanฤฑn `bytes`โ€™a gรถre birkaรง avantajฤฑ vardฤฑr: @@ -121,7 +121,7 @@ Formlardan gelen veri, dosya iรงermiyorsa normalde "media type" olarak `applicat Ancak form dosya iรงeriyorsa `multipart/form-data` olarak encode edilir. `File` kullanฤฑrsanฤฑz, **FastAPI** dosyalarฤฑ bodyโ€™nin doฤŸru kฤฑsmฤฑndan almasฤฑ gerektiฤŸini bilir. -Bu encodingโ€™ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz MDN web dokรผmanlarฤฑndaki POST sayfasฤฑna bakฤฑn. +Bu encodingโ€™ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz MDN web dokรผmanlarฤฑndaki POST sayfasฤฑna bakฤฑn. /// @@ -143,7 +143,7 @@ Standart type annotationโ€™larฤฑ kullanฤฑp varsayฤฑlan deฤŸeri `None` yaparak bi Ek metadata ayarlamak iรงin `UploadFile` ile birlikte `File()` da kullanabilirsiniz. ร–rneฤŸin: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## Birden Fazla Dosya Upload { #multiple-file-uploads } @@ -153,7 +153,7 @@ Bu dosyalar, "form data" ile gรถnderilen aynฤฑ "form field" ile iliลŸkilendirili Bunu kullanmak iรงin `bytes` veya `UploadFile` listesini tanฤฑmlayฤฑn: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} TanฤฑmladฤฑฤŸฤฑnฤฑz gibi, `bytes` veya `UploadFile`โ€™lardan oluลŸan bir `list` alฤฑrsฤฑnฤฑz. @@ -169,7 +169,7 @@ TanฤฑmladฤฑฤŸฤฑnฤฑz gibi, `bytes` veya `UploadFile`โ€™lardan oluลŸan bir `list` Daha รถnce olduฤŸu gibi, `UploadFile` iรงin bile ek parametreler ayarlamak amacฤฑyla `File()` kullanabilirsiniz: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## ร–zet { #recap } diff --git a/docs/tr/docs/tutorial/request-form-models.md b/docs/tr/docs/tutorial/request-form-models.md index c35f956fce..75693190f4 100644 --- a/docs/tr/docs/tutorial/request-form-models.md +++ b/docs/tr/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ Bu รถzellik FastAPI `0.113.0` sรผrรผmรผnden itibaren desteklenmektedir. ๐Ÿค“ Sadece, **form field** olarak almak istediฤŸiniz alanlarla bir **Pydantic model** tanฤฑmlayฤฑn ve ardฤฑndan parametreyi `Form` olarak bildirin: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI**, request iรงindeki **form data**'dan **her bir field** iรงin veriyi **รงฤฑkarฤฑr** ve size tanฤฑmladฤฑฤŸฤฑnฤฑz Pydantic model'ini verir. @@ -48,7 +48,7 @@ Bu รถzellik FastAPI `0.114.0` sรผrรผmรผnden itibaren desteklenmektedir. ๐Ÿค“ Herhangi bir `extra` field'ฤฑ `forbid` etmek iรงin Pydantic'in model konfigรผrasyonunu kullanabilirsiniz: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} Bir client fazladan veri gรถndermeye รงalฤฑลŸฤฑrsa, bir **error** response alฤฑr. diff --git a/docs/tr/docs/tutorial/request-forms-and-files.md b/docs/tr/docs/tutorial/request-forms-and-files.md index 86d26b4989..69926af5e1 100644 --- a/docs/tr/docs/tutorial/request-forms-and-files.md +++ b/docs/tr/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## `File` ve `Form` Import Edin { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## `File` ve `Form` Parametrelerini Tanฤฑmlayฤฑn { #define-file-and-form-parameters } Dosya ve form parametrelerini, `Body` veya `Query` iรงin yaptฤฑฤŸฤฑnฤฑz ลŸekilde oluลŸturun: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} Dosyalar ve form alanlarฤฑ form data olarak upload edilir ve siz de dosyalarฤฑ ve form alanlarฤฑnฤฑ alฤฑrsฤฑnฤฑz. diff --git a/docs/tr/docs/tutorial/request-forms.md b/docs/tr/docs/tutorial/request-forms.md index 4608a6b79b..1a5303b3e0 100644 --- a/docs/tr/docs/tutorial/request-forms.md +++ b/docs/tr/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart `Form`'u `fastapi`'den import edin: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## `Form` Parametrelerini Tanฤฑmlayฤฑn { #define-form-parameters } Form parametrelerini `Body` veya `Query` iรงin yaptฤฑฤŸฤฑnฤฑz gibi oluลŸturun: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} ร–rneฤŸin OAuth2 spesifikasyonunun kullanฤฑlabileceฤŸi ("password flow" olarak adlandฤฑrฤฑlan) yollardan birinde, form alanlarฤฑ olarak bir `username` ve `password` gรถndermek zorunludur. -spec, alanlarฤฑn adฤฑnฤฑn tam olarak `username` ve `password` olmasฤฑnฤฑ ve JSON deฤŸil form alanlarฤฑ olarak gรถnderilmesini gerektirir. +Spesifikasyon, alanlarฤฑn adฤฑnฤฑn tam olarak `username` ve `password` olmasฤฑnฤฑ ve JSON deฤŸil form alanlarฤฑ olarak gรถnderilmesini gerektirir. `Form` ile `Body` (ve `Query`, `Path`, `Cookie`) ile yaptฤฑฤŸฤฑnฤฑz aynฤฑ konfigรผrasyonlarฤฑ tanฤฑmlayabilirsiniz; validasyon, รถrnekler, alias (รถrn. `username` yerine `user-name`) vb. dahil. @@ -56,13 +56,13 @@ Formlardan gelen veri normalde "media type" `application/x-www-form-urlencoded` Ancak form dosyalar iรงerdiฤŸinde `multipart/form-data` olarak encode edilir. Dosyalarฤฑ ele almayฤฑ bir sonraki bรถlรผmde okuyacaksฤฑnฤฑz. -Bu encoding'ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz, MDN web docs for POST sayfasฤฑna gidin. +Bu encoding'ler ve form alanlarฤฑ hakkฤฑnda daha fazla okumak isterseniz, MDN web docs for POST sayfasฤฑna gidin. /// /// warning | Uyarฤฑ -Bir *path operation* iรงinde birden fazla `Form` parametresi tanฤฑmlayabilirsiniz, ancak JSON olarak almayฤฑ beklediฤŸiniz `Body` alanlarฤฑnฤฑ da ayrฤฑca tanฤฑmlayamazsฤฑnฤฑz; รงรผnkรผ bu durumda request'in body'si `application/json` yerine `application/x-www-form-urlencoded` ile encode edilmiลŸ olur. +Bir *path operation* iรงinde birden fazla `Form` parametresi tanฤฑmlayabilirsiniz, ancak JSON olarak almayฤฑ beklediฤŸiniz `Body` alanlarฤฑnฤฑ da ayrฤฑca tanฤฑmlayamazsฤฑnฤฑz; รงรผnkรผ bu durumda request'in body'si `application/x-www-form-urlencoded` ile encode edilmiลŸ olur. Bu **FastAPI**'ฤฑn bir kฤฑsฤฑtlamasฤฑ deฤŸildir, HTTP protokolรผnรผn bir parรงasฤฑdฤฑr. diff --git a/docs/tr/docs/tutorial/response-model.md b/docs/tr/docs/tutorial/response-model.md index f1d1f7d15e..2bf04bd9ec 100644 --- a/docs/tr/docs/tutorial/response-model.md +++ b/docs/tr/docs/tutorial/response-model.md @@ -97,7 +97,7 @@ Artฤฑk bir browser password ile user oluลŸturduฤŸunda, API response iรงinde ayn Bu รถrnekte sorun olmayabilir; รงรผnkรผ passwordโ€™รผ gรถnderen kullanฤฑcฤฑ zaten aynฤฑ kiลŸi. -Ancak aynฤฑ modeli baลŸka bir *path operation* iรงin kullanฤฑrsak, kullanฤฑcฤฑnฤฑn passwordโ€™lerini her clientโ€™a gรถnderiyor olabiliriz. +Namun ancak aynฤฑ modeli baลŸka bir *path operation* iรงin kullanฤฑrsak, kullanฤฑcฤฑnฤฑn passwordโ€™lerini her clientโ€™a gรถnderiyor olabiliriz. /// danger @@ -183,7 +183,7 @@ Bazฤฑ durumlarda Pydantic field olarak geรงerli olmayan bir ลŸey dรถndรผrebilir En yaygฤฑn durum, [ileri seviye dokรผmanlarda daha sonra anlatฤฑldฤฑฤŸฤฑ gibi doฤŸrudan bir Response dรถndรผrmektir](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} Bu basit durum FastAPI tarafฤฑndan otomatik olarak ele alฤฑnฤฑr; รงรผnkรผ dรถnรผลŸ tipi annotationโ€™ฤฑ `Response` classโ€™ฤฑdฤฑr (veya onun bir subclassโ€™ฤฑ). @@ -193,7 +193,7 @@ Araรงlar da memnun olur; รงรผnkรผ hem `RedirectResponse` hem `JSONResponse`, `Re Type annotation iรงinde `Response`โ€™un bir subclassโ€™ฤฑnฤฑ da kullanabilirsiniz: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} Bu da รงalฤฑลŸฤฑr; รงรผnkรผ `RedirectResponse`, `Response`โ€™un subclassโ€™ฤฑdฤฑr ve FastAPI bu basit durumu otomatik olarak yรถnetir. @@ -201,7 +201,7 @@ Bu da รงalฤฑลŸฤฑr; รงรผnkรผ `RedirectResponse`, `Response`โ€™un subclassโ€™ฤฑdฤฑ Ancak geรงerli bir Pydantic tipi olmayan baลŸka rastgele bir obje (รถr. bir veritabanฤฑ objesi) dรถndรผrรผr ve fonksiyonu da รถyle annotate ederseniz, FastAPI bu type annotationโ€™dan bir Pydantic response model oluลŸturmaya รงalฤฑลŸฤฑr ve baลŸarฤฑsฤฑz olur. -Aynฤฑ ลŸey, farklฤฑ tipler arasฤฑnda bir union kullandฤฑฤŸฤฑnฤฑzda ve bu tiplerden biri veya birkaรงฤฑ geรงerli bir Pydantic tipi deฤŸilse de olur; รถrneฤŸin ลŸu kullanฤฑm patlar ๐Ÿ’ฅ: +Aynฤฑ ลŸey, farklฤฑ tipler arasฤฑnda bir birleลŸim kullandฤฑฤŸฤฑnฤฑzda ve bu tiplerden biri veya birkaรงฤฑ geรงerli bir Pydantic tipi deฤŸilse de olur; รถrneฤŸin ลŸu kullanฤฑm patlar ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/tr/docs/tutorial/response-status-code.md b/docs/tr/docs/tutorial/response-status-code.md index 57ae7bde34..d2270a3343 100644 --- a/docs/tr/docs/tutorial/response-status-code.md +++ b/docs/tr/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ Bir response model tanฤฑmlayabildiฤŸiniz gibi, herhangi bir *path operation* iรง * `@app.delete()` * vb. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | Not @@ -66,7 +66,7 @@ Kฤฑsaca: /// tip | ฤฐpucu -Her bir status code hakkฤฑnda daha fazla bilgi almak ve hangi kodun ne iรงin kullanฤฑldฤฑฤŸฤฑnฤฑ gรถrmek iรงin HTTP status code'lar hakkฤฑnda MDN dokรผmantasyonuna gรถz atฤฑn. +Her bir status code hakkฤฑnda daha fazla bilgi almak ve hangi kodun ne iรงin kullanฤฑldฤฑฤŸฤฑnฤฑ gรถrmek iรงin MDN dokรผmantasyonu: HTTP status code'lar hakkฤฑnda gรถz atฤฑn. /// @@ -74,7 +74,7 @@ Her bir status code hakkฤฑnda daha fazla bilgi almak ve hangi kodun ne iรงin kul ร–nceki รถrneฤŸe tekrar bakalฤฑm: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201`, "Created" iรงin kullanฤฑlan status code'dur. @@ -82,7 +82,7 @@ Ancak bu kodlarฤฑn her birinin ne anlama geldiฤŸini ezberlemek zorunda deฤŸilsin `fastapi.status` iรงindeki kolaylฤฑk deฤŸiลŸkenlerini (convenience variables) kullanabilirsiniz. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} Bunlar sadece kolaylฤฑk saฤŸlar; aynฤฑ sayฤฑyฤฑ taลŸฤฑrlar. Ancak bu ลŸekilde editรถrรผn autocomplete รถzelliฤŸiyle kolayca bulabilirsiniz: diff --git a/docs/tr/docs/tutorial/schema-extra-example.md b/docs/tr/docs/tutorial/schema-extra-example.md index a91dda8924..7e29b2309e 100644 --- a/docs/tr/docs/tutorial/schema-extra-example.md +++ b/docs/tr/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Elbette birden fazla `examples` da geรงebilirsiniz: Bunu yaptฤฑฤŸฤฑnฤฑzda, รถrnekler bu body verisi iรงin dahili **JSON Schema**โ€™nฤฑn bir parรงasฤฑ olur. -Buna raฤŸmen, time of writing this, dokรผman arayรผzรผnรผ gรถsteren araรง olan Swagger UI, **JSON Schema** iรงindeki veriler iรงin birden fazla รถrneฤŸi gรถstermeyi desteklemiyor. Ancak aลŸaฤŸฤฑda bir รงรถzรผm yolu var. +Buna raฤŸmen, bu yazฤฑ yazฤฑlฤฑrken, dokรผman arayรผzรผnรผ gรถsteren araรง olan Swagger UI, **JSON Schema** iรงindeki veriler iรงin birden fazla รถrneฤŸi gรถstermeyi desteklemiyor. Ancak aลŸaฤŸฤฑda bir รงรถzรผm yolu var. ### OpenAPIโ€™ye รถzel `examples` { #openapi-specific-examples } diff --git a/docs/tr/docs/tutorial/security/first-steps.md b/docs/tr/docs/tutorial/security/first-steps.md index 7e0a70a02c..0f72d0c830 100644 --- a/docs/tr/docs/tutorial/security/first-steps.md +++ b/docs/tr/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ GรผvenliฤŸi yรถnetmek iรงin **FastAPI**โ€™nin sunduฤŸu araรงlarฤฑ kullanalฤฑm. ร–rneฤŸi `main.py` adlฤฑ bir dosyaya kopyalayฤฑn: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## ร‡alฤฑลŸtฤฑrฤฑn { #run-it } @@ -132,7 +132,7 @@ Bu durumda bile **FastAPI**, onu oluลŸturabilmeniz iรงin gereken araรงlarฤฑ suna `OAuth2PasswordBearer` sฤฑnฤฑfฤฑnฤฑn bir instanceโ€™ฤฑnฤฑ oluลŸtururken `tokenUrl` parametresini veririz. Bu parametre, clientโ€™ฤฑn (kullanฤฑcฤฑnฤฑn browserโ€™ฤฑnda รงalฤฑลŸan frontendโ€™in) token almak iรงin `username` ve `password` gรถndereceฤŸi URLโ€™yi iรงerir. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | ฤฐpucu @@ -170,7 +170,7 @@ Dolayฤฑsฤฑyla `Depends` ile kullanฤฑlabilir. Artฤฑk `Depends` ile bir dependency olarak `oauth2_scheme`โ€™i geรงebilirsiniz. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Bu dependency, *path operation function* iรงindeki `token` parametresine atanacak bir `str` saฤŸlar. diff --git a/docs/tr/docs/tutorial/security/get-current-user.md b/docs/tr/docs/tutorial/security/get-current-user.md index 9f56c76289..cc7f7a51b9 100644 --- a/docs/tr/docs/tutorial/security/get-current-user.md +++ b/docs/tr/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ ร–nceki bรถlรผmde gรผvenlik sistemi (dependency injection sistemine dayanฤฑr) *path operation function*'a `str` olarak bir `token` veriyordu: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Ancak bu hรขlรข pek kullanฤฑลŸlฤฑ deฤŸil. diff --git a/docs/tr/docs/tutorial/security/oauth2-jwt.md b/docs/tr/docs/tutorial/security/oauth2-jwt.md index 716761157c..ad991d322a 100644 --- a/docs/tr/docs/tutorial/security/oauth2-jwt.md +++ b/docs/tr/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ Sonra, alฤฑnan password'รผn kayฤฑttaki hash ile eลŸleลŸip eลŸleลŸmediฤŸini doฤŸr Bir tane de kullanฤฑcฤฑyฤฑ authenticate edip geri dรถndรผren bir yardฤฑmcฤฑ fonksiyon ekleyelim. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +`authenticate_user`, veritabanฤฑnda var olmayan bir username ile รงaฤŸrฤฑldฤฑฤŸฤฑnda, yine de sahte (dummy) bir hash'e karลŸฤฑ `verify_password` รงalฤฑลŸtฤฑrฤฑyoruz. + +Bu, username geรงerli olsun ya da olmasฤฑn endpoint'in yaklaลŸฤฑk aynฤฑ sรผrede yanฤฑt vermesini saฤŸlar; bรถylece mevcut username'leri saymaya yarayabilecek zamanlama saldฤฑrฤฑlarฤฑnฤฑ (timing attacks) engeller. /// note | Not @@ -152,7 +156,7 @@ Response iรงin token endpoint'inde kullanฤฑlacak bir Pydantic Model tanฤฑmlayฤฑn Yeni bir access token รผretmek iรงin bir yardฤฑmcฤฑ fonksiyon oluลŸturun. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## Dependency'leri gรผncelleme { #update-the-dependencies } @@ -162,7 +166,7 @@ Gelen token'ฤฑ decode edin, doฤŸrulayฤฑn ve mevcut kullanฤฑcฤฑyฤฑ dรถndรผrรผn. Token geรงersizse, hemen bir HTTP hatasฤฑ dรถndรผrรผn. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## `/token` *path operation*'ฤฑnฤฑ gรผncelleme { #update-the-token-path-operation } @@ -170,7 +174,7 @@ Token'ฤฑn sรผre sonu iรงin bir `timedelta` oluลŸturun. Gerรงek bir JWT access token รผretip dรถndรผrรผn. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### JWT "subject" `sub` Hakkฤฑnda Teknik Detaylar { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/tr/docs/tutorial/sql-databases.md b/docs/tr/docs/tutorial/sql-databases.md index e1638cb04f..0a02b47aec 100644 --- a/docs/tr/docs/tutorial/sql-databases.md +++ b/docs/tr/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Burada "ORMs" olarak adlandฤฑrฤฑlฤฑr). FastAPI sizi hiรงbir ลŸeye zorlamaz. +ฤฐstediฤŸiniz baลŸka bir SQL veya NoSQL veritabanฤฑ kรผtรผphanesini kullanabilirsiniz (bazฤฑ durumlarda "ORMs" olarak adlandฤฑrฤฑlฤฑr). FastAPI sizi hiรงbir ลŸeye zorlamaz. ๐Ÿ˜Ž /// @@ -49,7 +49,7 @@ $ pip install sqlmodel ร–nce, tek bir **SQLModel** modeliyle uygulamanฤฑn en basit ilk sรผrรผmรผnรผ oluลŸturacaฤŸฤฑz. -AลŸaฤŸฤฑda, **birden fazla model** kullanarak gรผvenliฤŸi ve esnekliฤŸi artฤฑrฤฑp geliลŸtireceฤŸiz. +AลŸaฤŸฤฑda, **birden fazla model** kullanarak gรผvenliฤŸi ve esnekliฤŸi artฤฑrฤฑp geliลŸtireceฤŸiz. ๐Ÿค“ ### Modelleri OluลŸturma { #create-models } @@ -93,7 +93,7 @@ Sonra `SQLModel.metadata.create_all(engine)` kullanan bir fonksiyon ekleyerek t Bir **`Session`**, **nesneleri memoryโ€™de** tutar ve verideki gerekli deฤŸiลŸiklikleri takip eder; ardฤฑndan veritabanฤฑyla iletiลŸim kurmak iรงin **`engine` kullanฤฑr**. -`yield` ile, her request iรงin yeni bir `Session` saฤŸlayacak bir FastAPI **dependency** oluลŸturacaฤŸฤฑz. Bu da her requestโ€™te tek session kullanmamฤฑzฤฑ garanti eder. +`yield` ile, her request iรงin yeni bir `Session` saฤŸlayacak bir FastAPI **dependency** oluลŸturacaฤŸฤฑz. Bu da her requestโ€™te tek session kullanmamฤฑzฤฑ garanti eder. ๐Ÿค“ Ardฤฑndan bu dependencyโ€™yi kullanacak kodun geri kalanฤฑnฤฑ sadeleลŸtirmek iรงin `Annotated` ile `SessionDep` dependencyโ€™sini oluลŸtururuz. @@ -107,7 +107,7 @@ Uygulama baลŸlarken veritabanฤฑ tableโ€™larฤฑnฤฑ oluลŸturacaฤŸฤฑz. Burada bir uygulama startup eventโ€™inde tableโ€™larฤฑ oluลŸturuyoruz. -Productionโ€™da bรผyรผk ihtimalle uygulamayฤฑ baลŸlatmadan รถnce รงalฤฑลŸan bir migration scriptโ€™i kullanฤฑrsฤฑnฤฑz. +Productionโ€™da bรผyรผk ihtimalle uygulamayฤฑ baลŸlatmadan รถnce รงalฤฑลŸan bir migration scriptโ€™i kullanฤฑrsฤฑnฤฑz. ๐Ÿค“ /// tip | ฤฐpucu @@ -169,19 +169,19 @@ Sonra `/docs` arayรผzรผne gidin; **FastAPI**โ€™nin APIโ€™yi **dokรผmante etmek** ลžimdi bu uygulamayฤฑ biraz **refactor** edelim ve **gรผvenliฤŸi** ile **esnekliฤŸi** artฤฑralฤฑm. -ร–nceki uygulamaya bakarsanฤฑz, UIโ€™da ลŸu ana kadar clientโ€™ฤฑn oluลŸturulacak `Hero`โ€™nun `id` deฤŸerini belirlemesine izin verdiฤŸini gรถrebilirsiniz. +ร–nceki uygulamaya bakarsanฤฑz, UIโ€™da ลŸu ana kadar clientโ€™ฤฑn oluลŸturulacak `Hero`โ€™nun `id` deฤŸerini belirlemesine izin verdiฤŸini gรถrebilirsiniz. ๐Ÿ˜ฑ Buna izin vermemeliyiz; DBโ€™de zaten atanmฤฑลŸ bir `id`โ€™yi ezebilirler. `id` belirlemek **client** tarafฤฑndan deฤŸil, **backend** veya **veritabanฤฑ** tarafฤฑndan yapฤฑlmalฤฑdฤฑr. -Ayrฤฑca hero iรงin bir `secret_name` oluลŸturuyoruz ama ลŸimdiye kadar her yerde geri dรถndรผrรผyoruz; bu pek de **secret** sayฤฑlmaz... +Ayrฤฑca hero iรงin bir `secret_name` oluลŸturuyoruz ama ลŸimdiye kadar her yerde geri dรถndรผrรผyoruz; bu pek de **secret** sayฤฑlmaz... ๐Ÿ˜… -Bunlarฤฑ birkaรง **ek model** ekleyerek dรผzelteceฤŸiz. SQLModelโ€™in parlayacaฤŸฤฑ yer de burasฤฑ. +Bunlarฤฑ birkaรง **ek model** ekleyerek dรผzelteceฤŸiz. SQLModelโ€™in parlayacaฤŸฤฑ yer de burasฤฑ. โœจ ### Birden Fazla Model OluลŸturma { #create-multiple-models } **SQLModel**โ€™de, `table=True` olan herhangi bir model sฤฑnฤฑfฤฑ bir **table model**โ€™dir. -`table=True` olmayan her model sฤฑnฤฑfฤฑ ise bir **data model**โ€™dir; bunlar aslฤฑnda sadece Pydantic modelleridir (bazฤฑ kรผรงรผk ek รถzelliklerle). +`table=True` olmayan her model sฤฑnฤฑfฤฑ ise bir **data model**โ€™dir; bunlar aslฤฑnda sadece Pydantic modelleridir (bazฤฑ kรผรงรผk ek รถzelliklerle). ๐Ÿค“ SQLModel ile **inheritance** kullanarak her durumda tรผm alanlarฤฑ tekrar tekrar yazmaktan **kaรงฤฑnabiliriz**. @@ -216,7 +216,7 @@ Sonraki adฤฑmda `HeroPublic` modelini oluลŸtururuz; bu model API clientโ€™larฤฑn `HeroBase` ile aynฤฑ alanlara sahiptir; dolayฤฑsฤฑyla `secret_name` iรงermez. -Sonunda kahramanlarฤฑmฤฑzฤฑn kimliฤŸi korunmuลŸ oldu! +Sonunda kahramanlarฤฑmฤฑzฤฑn kimliฤŸi korunmuลŸ oldu! ๐Ÿฅท Ayrฤฑca `id: int` alanฤฑnฤฑ yeniden tanฤฑmlar. Bunu yaparak API clientโ€™larฤฑyla bir **contract** (sรถzleลŸme) oluลŸturmuลŸ oluruz; bรถylece `id` alanฤฑnฤฑn her zaman var olacaฤŸฤฑnฤฑ ve `int` olacaฤŸฤฑnฤฑ (asla `None` olmayacaฤŸฤฑnฤฑ) bilirler. @@ -224,7 +224,7 @@ Ayrฤฑca `id: int` alanฤฑnฤฑ yeniden tanฤฑmlar. Bunu yaparak API clientโ€™larฤฑyl Return modelโ€™in bir deฤŸerin her zaman mevcut olduฤŸunu ve her zaman `int` olduฤŸunu (`None` deฤŸil) garanti etmesi API clientโ€™larฤฑ iรงin รงok faydalฤฑdฤฑr; bu kesinlik sayesinde daha basit kod yazabilirler. -Ayrฤฑca **otomatik รผretilen client**โ€™larฤฑn arayรผzleri de daha basit olur; bรถylece APIโ€™nizle รงalฤฑลŸan geliลŸtiriciler iรงin sรผreรง รงok daha rahat olur. +Ayrฤฑca **otomatik รผretilen client**โ€™larฤฑn arayรผzleri de daha basit olur; bรถylece APIโ€™nizle รงalฤฑลŸan geliลŸtiriciler iรงin sรผreรง รงok daha rahat olur. ๐Ÿ˜Ž /// @@ -262,13 +262,13 @@ Ayrฤฑca password deฤŸerlerini saklamadan รถnce **hash** etmelisiniz; **asla plai #### `HeroUpdate` - hero gรผncellemek iรงin *data model* { #heroupdate-the-data-model-to-update-a-hero } -Uygulamanฤฑn รถnceki sรผrรผmรผnde bir heroโ€™yu **gรผncellemenin** bir yolu yoktu; ancak artฤฑk **birden fazla model** ile bunu yapabiliriz. +Uygulamanฤฑn รถnceki sรผrรผmรผnde bir heroโ€™yu **gรผncellemenin** bir yolu yoktu; ancak artฤฑk **birden fazla model** ile bunu yapabiliriz. ๐ŸŽ‰ `HeroUpdate` *data model* biraz รถzeldir: yeni bir hero oluลŸturmak iรงin gereken alanlarฤฑn **tamamฤฑna** sahiptir, ancak tรผm alanlar **opsiyoneldir** (hepsinin bir default deฤŸeri vardฤฑr). Bu sayede hero gรผncellerken sadece gรผncellemek istediฤŸiniz alanlarฤฑ gรถnderebilirsiniz. Tรผm **alanlar aslฤฑnda deฤŸiลŸtiฤŸi** iรงin (tip artฤฑk `None` iรงeriyor ve default deฤŸerleri `None` oluyor), onlarฤฑ **yeniden tanฤฑmlamamฤฑz** gerekir. -Aslฤฑnda `HeroBase`โ€™ten miras almamฤฑz gerekmiyor; รงรผnkรผ tรผm alanlarฤฑ yeniden tanฤฑmlฤฑyoruz. Tutarlฤฑlฤฑk iรงin miras almayฤฑ bฤฑrakฤฑyorum ama bu gerekli deฤŸil. Daha รงok kiลŸisel tercih meselesi. +Aslฤฑnda `HeroBase`โ€™ten miras almamฤฑz gerekmiyor; รงรผnkรผ tรผm alanlarฤฑ yeniden tanฤฑmlฤฑyoruz. Tutarlฤฑlฤฑk iรงin miras almayฤฑ bฤฑrakฤฑyorum ama bu gerekli deฤŸil. Daha รงok kiลŸisel tercih meselesi. ๐Ÿคท `HeroUpdate` alanlarฤฑ: @@ -316,7 +316,7 @@ Tek bir heroโ€™yu **okuyabiliriz**: Bir heroโ€™yu **gรผncelleyebiliriz**. Bunun iรงin HTTP `PATCH` operasyonu kullanฤฑrฤฑz. -Kodda, clientโ€™ฤฑn gรถnderdiฤŸi tรผm verilerle bir `dict` alฤฑrฤฑz; **yalnฤฑzca clientโ€™ฤฑn gรถnderdiฤŸi veriler**, yani sadece default deฤŸer olduklarฤฑ iรงin orada bulunan deฤŸerler hariรง. Bunu yapmak iรงin `exclude_unset=True` kullanฤฑrฤฑz. Asฤฑl numara bu. +Kodda, clientโ€™ฤฑn gรถnderdiฤŸi tรผm verilerle bir `dict` alฤฑrฤฑz; **yalnฤฑzca clientโ€™ฤฑn gรถnderdiฤŸi veriler**, yani sadece default deฤŸer olduklarฤฑ iรงin orada bulunan deฤŸerler hariรง. Bunu yapmak iรงin `exclude_unset=True` kullanฤฑrฤฑz. Asฤฑl numara bu. ๐Ÿช„ Sonra `hero_db.sqlmodel_update(hero_data)` ile `hero_db`โ€™yi `hero_data` iรงindeki verilerle gรผncelleriz. @@ -326,7 +326,7 @@ Sonra `hero_db.sqlmodel_update(hero_data)` ile `hero_db`โ€™yi `hero_data` iรงind Bir heroโ€™yu **silmek** bรผyรผk รถlรงรผde aynฤฑ kalฤฑyor. -Bu รถrnekte her ลŸeyi refactor etme isteฤŸimizi bastฤฑracaฤŸฤฑz. +Bu รถrnekte her ลŸeyi refactor etme isteฤŸimizi bastฤฑracaฤŸฤฑz. ๐Ÿ˜… {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} @@ -354,4 +354,4 @@ $ fastapi dev main.py Bir SQL veritabanฤฑyla etkileลŸim kurmak iรงin **SQLModel** kullanabilir ve *data model* ile *table model* yaklaลŸฤฑmฤฑyla kodu sadeleลŸtirebilirsiniz. -**SQLModel** dokรผmantasyonunda รงok daha fazlasฤฑnฤฑ รถฤŸrenebilirsiniz; **FastAPI** ile SQLModel kullanฤฑmฤฑ iรงin daha uzun bir mini tutorial da bulunuyor. +**SQLModel** dokรผmantasyonunda รงok daha fazlasฤฑnฤฑ รถฤŸrenebilirsiniz; **FastAPI** ile SQLModel kullanฤฑmฤฑ iรงin daha uzun bir mini tutorial da bulunuyor. ๐Ÿš€ diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md index d30b4389d0..e49b14bd86 100644 --- a/docs/tr/docs/tutorial/static-files.md +++ b/docs/tr/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * `StaticFiles`'ฤฑ import edin. * Belirli bir path'te bir `StaticFiles()` รถrneฤŸini "mount" edin. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | Teknik Detaylar @@ -23,7 +23,7 @@ Bu, bir `APIRouter` kullanmaktan farklฤฑdฤฑr; รงรผnkรผ mount edilen uygulama tamamen baฤŸฤฑmsฤฑzdฤฑr. Ana uygulamanฤฑzฤฑn OpenAPI ve docs'larฤฑ, mount edilen uygulamadan hiรงbir ลŸey iรงermez, vb. -Bununla ilgili daha fazla bilgiyi [Advanced User Guide](../advanced/index.md){.internal-link target=_blank} iรงinde okuyabilirsiniz. +Bununla ilgili daha fazla bilgiyi [GeliลŸmiลŸ Kullanฤฑcฤฑ Kฤฑlavuzu](../advanced/index.md){.internal-link target=_blank} iรงinde okuyabilirsiniz. ## Detaylar { #details } diff --git a/docs/tr/docs/tutorial/testing.md b/docs/tr/docs/tutorial/testing.md index 8871566066..18e0dd96c0 100644 --- a/docs/tr/docs/tutorial/testing.md +++ b/docs/tr/docs/tutorial/testing.md @@ -12,7 +12,7 @@ Bununla birlikte **FastAPI** ile `httpx`'i kurun. -Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin: +Bir [Sanal Ortam](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin: ```console $ pip install httpx @@ -30,7 +30,7 @@ Adฤฑ `test_` ile baลŸlayan fonksiyonlar oluลŸturun (bu, `pytest`'in standart kon Kontrol etmeniz gereken ลŸeyler iรงin standart Python ifadeleriyle basit `assert` satฤฑrlarฤฑ yazฤฑn (bu da `pytest` standardฤฑdฤฑr). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ฤฐpucu @@ -52,7 +52,7 @@ Bu sayede `pytest`'i ek bir karmaลŸฤฑklฤฑk olmadan doฤŸrudan kullanabilirsiniz. /// tip | ฤฐpucu -FastAPI uygulamanฤฑza request gรถndermenin dฤฑลŸฤฑnda testlerinizde `async` fonksiyonlar รงaฤŸฤฑrmak istiyorsanฤฑz (รถrn. asenkron veritabanฤฑ fonksiyonlarฤฑ), ileri seviye bรถlรผmdeki [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} dokรผmanฤฑna gรถz atฤฑn. +FastAPI uygulamanฤฑza request gรถndermenin dฤฑลŸฤฑnda testlerinizde `async` fonksiyonlar รงaฤŸฤฑrmak istiyorsanฤฑz (รถrn. asenkron veritabanฤฑ fonksiyonlarฤฑ), ileri seviye bรถlรผmdeki [Asenkron Testler](../advanced/async-tests.md){.internal-link target=_blank} dokรผmanฤฑna gรถz atฤฑn. /// @@ -64,7 +64,7 @@ Ayrฤฑca **FastAPI** uygulamanฤฑz birden fazla dosya/modรผl vb. ile de oluลŸturul ### **FastAPI** Uygulama Dosyasฤฑ { #fastapi-app-file } -[Bigger Applications](bigger-applications.md){.internal-link target=_blank}'te anlatฤฑlan ลŸekilde bir dosya yapฤฑnฤฑz olduฤŸunu varsayalฤฑm: +[Daha Bรผyรผk Uygulamalar](bigger-applications.md){.internal-link target=_blank}'te anlatฤฑlan ลŸekilde bir dosya yapฤฑnฤฑz olduฤŸunu varsayalฤฑm: ``` . @@ -75,7 +75,7 @@ Ayrฤฑca **FastAPI** uygulamanฤฑz birden fazla dosya/modรผl vb. ile de oluลŸturul `main.py` dosyasฤฑnda **FastAPI** uygulamanฤฑz bulunuyor olsun: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### Test Dosyasฤฑ { #testing-file } @@ -91,7 +91,7 @@ Sonra testlerinizin olduฤŸu bir `test_main.py` dosyanฤฑz olabilir. Bu dosya ayn Bu dosya aynฤฑ package iรงinde olduฤŸu iรงin, `main` modรผlรผnden (`main.py`) `app` nesnesini import etmek รผzere relative import kullanabilirsiniz: -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...ve test kodunu da รถncekiyle aynฤฑ ลŸekilde yazabilirsiniz. @@ -145,7 +145,7 @@ Backend'e veri geรงme hakkฤฑnda daha fazla bilgi iรงin (`httpx` veya `TestClient `TestClient`'ฤฑn Pydantic model'lerini deฤŸil, JSON'a dรถnรผลŸtรผrรผlebilen verileri aldฤฑฤŸฤฑnฤฑ unutmayฤฑn. -Testinizde bir Pydantic model'iniz varsa ve test sฤฑrasฤฑnda verisini uygulamaya gรถndermek istiyorsanฤฑz, [JSON Compatible Encoder](encoder.md){.internal-link target=_blank} iรงinde aรงฤฑklanan `jsonable_encoder`'ฤฑ kullanabilirsiniz. +Testinizde bir Pydantic model'iniz varsa ve test sฤฑrasฤฑnda verisini uygulamaya gรถndermek istiyorsanฤฑz, [JSON Uyumlu Encoder](encoder.md){.internal-link target=_blank} iรงinde aรงฤฑklanan `jsonable_encoder`'ฤฑ kullanabilirsiniz. /// @@ -153,7 +153,7 @@ Testinizde bir Pydantic model'iniz varsa ve test sฤฑrasฤฑnda verisini uygulamaya Bundan sonra yapmanฤฑz gereken tek ลŸey `pytest`'i kurmaktฤฑr. -Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin: +Bir [Sanal Ortam](../virtual-environments.md){.internal-link target=_blank} oluลŸturduฤŸunuzdan, onu aktifleลŸtirdiฤŸinizden ve sonra kurulumu yaptฤฑฤŸฤฑnฤฑzdan emin olun; รถrneฤŸin:
diff --git a/docs/tr/docs/virtual-environments.md b/docs/tr/docs/virtual-environments.md index cf7fab778b..668a3d5a95 100644 --- a/docs/tr/docs/virtual-environments.md +++ b/docs/tr/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Virtual Environment OluลŸturun { #create-a-virtual-environment } -Bir Python projesi รผzerinde **ilk kez** รงalฤฑลŸmaya baลŸladฤฑฤŸฤฑnฤฑzda, projenizin iรงinde **virtual environment** oluลŸturun. +Bir Python projesi รผzerinde **ilk kez** รงalฤฑลŸmaya baลŸladฤฑฤŸฤฑnฤฑzda, **virtual environment**'i projenizin iรงinde oluลŸturun. /// tip | ฤฐpucu From 685cc0de17a1f5af0c7ad0936f066aef5a64cd37 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:42:01 +0100 Subject: [PATCH 224/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(update-all)=20(#14914)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/uk/docs/alternatives.md | 66 +++--- docs/uk/docs/features.md | 10 +- docs/uk/docs/index.md | 12 +- docs/uk/docs/learn/index.md | 2 +- docs/uk/docs/python-types.md | 202 ++++-------------- docs/uk/docs/tutorial/background-tasks.md | 26 +-- docs/uk/docs/tutorial/body-multiple-params.md | 9 +- docs/uk/docs/tutorial/body-nested-models.md | 6 +- docs/uk/docs/tutorial/body.md | 14 +- docs/uk/docs/tutorial/cookie-param-models.md | 22 +- docs/uk/docs/tutorial/cookie-params.md | 16 +- docs/uk/docs/tutorial/cors.md | 31 ++- docs/uk/docs/tutorial/debugging.md | 2 +- docs/uk/docs/tutorial/first-steps.md | 22 +- docs/uk/docs/tutorial/handling-errors.md | 16 +- docs/uk/docs/tutorial/header-param-models.md | 12 +- docs/uk/docs/tutorial/header-params.md | 2 +- docs/uk/docs/tutorial/index.md | 8 +- docs/uk/docs/tutorial/metadata.md | 12 +- docs/uk/docs/tutorial/middleware.md | 10 +- .../path-params-numeric-validations.md | 20 +- docs/uk/docs/tutorial/path-params.md | 38 ++-- docs/uk/docs/tutorial/query-param-models.md | 22 +- .../tutorial/query-params-str-validations.md | 85 +++----- docs/uk/docs/tutorial/query-params.md | 10 +- docs/uk/docs/tutorial/request-files.md | 14 +- docs/uk/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 8 +- docs/uk/docs/tutorial/request-forms.md | 18 +- docs/uk/docs/tutorial/response-model.md | 8 +- docs/uk/docs/tutorial/response-status-code.md | 8 +- docs/uk/docs/tutorial/schema-extra-example.md | 4 +- docs/uk/docs/tutorial/security/index.md | 6 +- docs/uk/docs/tutorial/static-files.md | 2 +- docs/uk/docs/tutorial/testing.md | 8 +- 35 files changed, 303 insertions(+), 452 deletions(-) diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md index d44ca794f8..5dbf8a96ba 100644 --- a/docs/uk/docs/alternatives.md +++ b/docs/uk/docs/alternatives.md @@ -58,9 +58,9 @@ Flask โ€” ั†ะต ยซะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบยป, ะฒั–ะฝ ะฝะต ะฒะบะปัŽั‡ะฐั” ั–ะฝ /// check | ะะฐะดะธั…ะฝัƒะปะพ **FastAPI** ะฝะฐ -ะ‘ัƒั‚ะธ ะผั–ะบั€ะพั„ั€ะตะนะผะพะฒะพั€ะบะพะผ. ะ—ั€ะพะฑะธั‚ะธ ะปะตะณะบะธะผ ะบะพะผะฑั–ะฝัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะพั”ะดะฝะฐะฝะฝั ะฝะตะพะฑั…ั–ะดะฝะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั‚ะฐ ั‡ะฐัั‚ะธะฝ. +ะ‘ัƒั‚ะธ ะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบะพะผ. ะ—ั€ะพะฑะธั‚ะธ ะปะตะณะบะธะผ ะบะพะผะฑั–ะฝัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะพั”ะดะฝะฐะฝะฝั ะฝะตะพะฑั…ั–ะดะฝะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั‚ะฐ ั‡ะฐัั‚ะธะฝ. - ะœะฐั‚ะธ ะฟั€ะพัั‚ัƒ ั‚ะฐ ะปะตะณะบัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ัะธัั‚ะตะผัƒ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั†ั–ั—. +ะœะฐั‚ะธ ะฟั€ะพัั‚ัƒ ั‚ะฐ ะปะตะณะบัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ัะธัั‚ะตะผัƒ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั†ั–ั—. /// @@ -100,9 +100,9 @@ def read_url(): /// check | ะะฐะดะธั…ะฝัƒะปะพ **FastAPI** ะฝะฐ -* ะœะฐะนั‚ะต ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะน API. -* ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั–ะผะตะฝะฐ (ะพะฟะตั€ะฐั†ั–ั—) ะผะตั‚ะพะดั–ะฒ HTTP ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฟั€ะพัั‚ะธะผ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะผ ัะฟะพัะพะฑะพะผ. -* ะ ะพะทัƒะผะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฐะปะต ะฟะพั‚ัƒะถะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. +* ะœะฐั‚ะธ ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะน API. +* ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะผะตะฝะฐ (ะพะฟะตั€ะฐั†ั–ั—) ะผะตั‚ะพะดั–ะฒ HTTP ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฟั€ะพัั‚ะธะผ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะผ ัะฟะพัะพะฑะพะผ. +* ะœะฐั‚ะธ ั€ะพะทัƒะผะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฐะปะต ะฟะพั‚ัƒะถะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. /// @@ -122,12 +122,12 @@ def read_url(): ะŸั€ะธะนะฝัั‚ะธ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะบั€ะธั‚ะธะน ัั‚ะฐะฝะดะฐั€ั‚ ะดะปั ัะฟะตั†ะธั„ั–ะบะฐั†ั–ะน API ะทะฐะผั–ัั‚ัŒ ัะฟะตั†ั–ะฐะปัŒะฝะพั— ัั…ะตะผะธ. - ะ†ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะฝะฐ ะพัะฝะพะฒั– ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ: +ะ†ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะฝะฐ ะพัะฝะพะฒั– ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ: * ะ†ะฝั‚ะตั€ั„ะตะนั Swagger * ReDoc - ะฆั– ะดะฒะฐ ะฑัƒะปะพ ะพะฑั€ะฐะฝะพ ั‡ะตั€ะตะท ั‚ะต, ั‰ะพ ะฒะพะฝะธ ะดะพัะธั‚ัŒ ะฟะพะฟัƒะปัั€ะฝั– ั‚ะฐ ัั‚ะฐะฑั–ะปัŒะฝั–, ะฐะปะต, ะฒะธะบะพะฝะฐะฒัˆะธ ัˆะฒะธะดะบะธะน ะฟะพัˆัƒะบ, ะฒะธ ะผะพะถะตั‚ะต ะทะฝะฐะนั‚ะธ ะดะตััั‚ะบะธ ะดะพะดะฐั‚ะบะพะฒะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะดะปั OpenAPI (ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท **FastAPI**). +ะฆั– ะดะฒะฐ ะฑัƒะปะพ ะพะฑั€ะฐะฝะพ ั‡ะตั€ะตะท ั‚ะต, ั‰ะพ ะฒะพะฝะธ ะดะพัะธั‚ัŒ ะฟะพะฟัƒะปัั€ะฝั– ั‚ะฐ ัั‚ะฐะฑั–ะปัŒะฝั–, ะฐะปะต, ะฒะธะบะพะฝะฐะฒัˆะธ ัˆะฒะธะดะบะธะน ะฟะพัˆัƒะบ, ะฒะธ ะผะพะถะตั‚ะต ะทะฝะฐะนั‚ะธ ะดะตััั‚ะบะธ ะดะพะดะฐั‚ะบะพะฒะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะดะปั OpenAPI (ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท **FastAPI**). /// @@ -137,7 +137,7 @@ def read_url(): ### Marshmallow { #marshmallow } -ะžะดะฝั–ั”ัŽ ะท ะณะพะปะพะฒะฝะธั… ั„ัƒะฝะบั†ั–ะน, ะฝะตะพะฑั…ั–ะดะฝะธั… ะดะปั ัะธัั‚ะตะผ API, ั” "ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั", ัะบะฐ ะฑะตั€ะต ะดะฐะฝั– ะท ะบะพะดัƒ (Python) ั– ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั—ั… ะฝะฐ ั‰ะพััŒ, ั‰ะพ ะผะพะถะฝะฐ ะฝะฐะดั–ัะปะฐั‚ะธ ั‡ะตั€ะตะท ะผะตั€ะตะถัƒ. ะะฐะฟั€ะธะบะปะฐะด, ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ะฐ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะดะฐะฝั– ะท ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะฐ ะพะฑโ€™ั”ะบั‚ JSON. ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ั–ะฒ `datetime` ะฝะฐ ัั‚ั€ะพะบะธ ั‚ะพั‰ะพ. +ะžะดะฝั–ั”ัŽ ะท ะณะพะปะพะฒะฝะธั… ั„ัƒะฝะบั†ั–ะน, ะฝะตะพะฑั…ั–ะดะฝะธั… ะดะปั ัะธัั‚ะตะผ API, ั” "ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั", ัะบะฐ ะฑะตั€ะต ะดะฐะฝั– ะท ะบะพะดัƒ (Python) ั– ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั—ั… ะฝะฐ ั‰ะพััŒ, ั‰ะพ ะผะพะถะฝะฐ ะฝะฐะดั–ัะปะฐั‚ะธ ั‡ะตั€ะตะท ะผะตั€ะตะถัƒ. ะะฐะฟั€ะธะบะปะฐะด, ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ะฐ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะดะฐะฝั– ะท ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะฐ ะพะฑโ€™ั”ะบั‚ JSON. ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ั–ะฒ `datetime` ะฝะฐ ัั‚ั€ะพะบะธ ั‚ะพั‰ะพ. ะ†ะฝัˆะพัŽ ะฒะฐะถะปะธะฒะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ, ะฝะตะพะฑั…ั–ะดะฝะพัŽ ะดะปั API, ั” ะฟะตั€ะตะฒั–ั€ะบะฐ ะดะฐะฝะธั…, ัะบะฐ ะทะฐะฑะตะทะฟะตั‡ัƒั” ะดั–ะนัะฝั–ัั‚ัŒ ะดะฐะฝะธั… ะทะฐ ะฟะตะฒะฝะธะผะธ ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ. ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพ ะดะตัะบะต ะฟะพะปะต ั” `int`, ะฐ ะฝะต ะดะตัะบะฐ ะฒะธะฟะฐะดะบะพะฒะฐ ัั‚ั€ะพะบะฐ. ะฆะต ะพัะพะฑะปะธะฒะพ ะบะพั€ะธัะฝะพ ะดะปั ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…. @@ -145,7 +145,7 @@ def read_url(): Marshmallow ัั‚ะฒะพั€ะตะฝะพ ะดะปั ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั ั†ะธั… ั„ัƒะฝะบั†ั–ะน. ะฆะต ั‡ัƒะดะพะฒะฐ ะฑั–ะฑะปั–ะพั‚ะตะบะฐ, ั– ั ั‡ะฐัั‚ะพ ะฝะตัŽ ะบะพั€ะธัั‚ัƒะฒะฐะฒัั ั€ะฐะฝั–ัˆะต. -ะะปะต ะฒั–ะฝ ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ะดะพ ั‚ะพะณะพ, ัะบ ั–ัะฝัƒะฒะฐะปะธ ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟัƒ Python. ะžั‚ะถะต, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะบะพะถะฝัƒ ัั…ะตะผัƒ, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะฟะตั†ั–ะฐะปัŒะฝั– ัƒั‚ะธะปั–ั‚ะธ ั‚ะฐ ะบะปะฐัะธ, ะฝะฐะดะฐะฝั– Marshmallow. +ะะปะต ะฒั–ะฝ ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ะดะพ ั‚ะพะณะพ, ัะบ ั–ัะฝัƒะฒะฐะปะธ ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟัƒ Python. ะžั‚ะถะต, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะบะพะถะฝัƒ ัั…ะตะผัƒ, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะฟะตั†ั–ะฐะปัŒะฝั– ัƒั‚ะธะปั–ั‚ะธ ั‚ะฐ ะบะปะฐัะธ, ะฝะฐะดะฐะฝั– Marshmallow. /// check | ะะฐะดะธั…ะฝัƒะปะพ **FastAPI** ะฝะฐ @@ -155,7 +155,7 @@ Marshmallow ัั‚ะฒะพั€ะตะฝะพ ะดะปั ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั ั†ะธั… ั„ัƒะฝะบั†ั– ### Webargs { #webargs } -ะ†ะฝัˆะพัŽ ะฒะฐะถะปะธะฒะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ, ะฝะตะพะฑั…ั–ะดะฝะพัŽ ะดะปั API, ั” ะฐะฝะฐะปั–ะท ะดะฐะฝะธั… ั–ะท ะฒั…ั–ะดะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. +ะ†ะฝัˆะพัŽ ะฒะฐะถะปะธะฒะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ, ะฝะตะพะฑั…ั–ะดะฝะพัŽ ะดะปั API, ั” ะฐะฝะฐะปั–ะท ะดะฐะฝะธั… ั–ะท ะฒั…ั–ะดะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. Webargs โ€” ั†ะต ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ัั‚ะฒะพั€ะตะฝะธะน, ั‰ะพะฑ ะทะฐะฑะตะทะฟะตั‡ะธั‚ะธ ั†ะต ะฟะพะฒะตั€ั… ะบั–ะปัŒะบะพั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ, ะฒะบะปัŽั‡ะฐัŽั‡ะธ Flask. @@ -217,7 +217,7 @@ APISpec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Marshmall ะฆั ะบะพะผะฑั–ะฝะฐั†ั–ั Flask, Flask-apispec ั–ะท Marshmallow ั– Webargs ะฑัƒะปะฐ ะผะพั—ะผ ัƒะปัŽะฑะปะตะฝะธะผ ะฑะตะบะตะฝะด-ัั‚ะตะบะพะผ ะดะพ ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. -ะ‡ั– ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั€ะธะทะฒะตะปะพ ะดะพ ัั‚ะฒะพั€ะตะฝะฝั ะบั–ะปัŒะบะพั… ะณะตะฝะตั€ะฐั‚ะพั€ั–ะฒ ะฟะพะฒะฝะพะณะพ ัั‚ะตะบะฐ Flask. ะฆะต ะพัะฝะพะฒะฝะธะน ัั‚ะตะบ, ัะบะธะน ั (ั‚ะฐ ะบั–ะปัŒะบะฐ ะทะพะฒะฝั–ัˆะฝั–ั… ะบะพะผะฐะฝะด) ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะฒ ะดะพัั–: +ะ‡ั— ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั€ะธะทะฒะตะปะพ ะดะพ ัั‚ะฒะพั€ะตะฝะฝั ะบั–ะปัŒะบะพั… ะณะตะฝะตั€ะฐั‚ะพั€ั–ะฒ ะฟะพะฒะฝะพะณะพ ัั‚ะตะบะฐ Flask. ะฆะต ะพัะฝะพะฒะฝะธะน ัั‚ะตะบ, ัะบะธะน ั (ั‚ะฐ ะบั–ะปัŒะบะฐ ะทะพะฒะฝั–ัˆะฝั–ั… ะบะพะผะฐะฝะด) ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะฒ ะดะพัั–: * https://github.com/tiangolo/full-stack * https://github.com/tiangolo/full-stack-flask-couchbase @@ -255,7 +255,7 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะธะฟะธ Python, ั‰ะพะฑ ะผะฐั‚ะธ ั‡ัƒะดะพะฒัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ. - ะœะฐั‚ะธ ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. ะ—ะฝะฐะนะดั–ั‚ัŒ ัะฟะพัั–ะฑ ะทะฒะตัั‚ะธ ะดะพ ะผั–ะฝั–ะผัƒะผัƒ ะฟะพะฒั‚ะพั€ะตะฝะฝั ะบะพะดัƒ. +ะœะฐั‚ะธ ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. ะ—ะฝะฐะนะดั–ั‚ัŒ ัะฟะพัั–ะฑ ะทะฒะตัั‚ะธ ะดะพ ะผั–ะฝั–ะผัƒะผัƒ ะฟะพะฒั‚ะพั€ะตะฝะฝั ะบะพะดัƒ. /// @@ -267,7 +267,7 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar ะ’ั–ะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะฒ `uvloop` ะทะฐะผั–ัั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะณะพ ั†ะธะบะปัƒ Python `asyncio`. ะžััŒ ั‰ะพ ะทั€ะพะฑะธะปะพ ะนะพะณะพ ั‚ะฐะบะธะผ ัˆะฒะธะดะบะธะผ. - ะฆะต ัะฒะฝะพ ะฝะฐะดะธั…ะฝัƒะปะพ Uvicorn ั– Starlette, ัะบั– ะทะฐั€ะฐะท ัˆะฒะธะดัˆั– ะทะฐ Sanic ัƒ ะฒั–ะดะบั€ะธั‚ะธั… ั‚ะตัั‚ะฐั…. +ะฆะต ัะฒะฝะพ ะฝะฐะดะธั…ะฝัƒะปะพ Uvicorn ั– Starlette, ัะบั– ะทะฐั€ะฐะท ัˆะฒะธะดัˆั– ะทะฐ Sanic ัƒ ะฒั–ะดะบั€ะธั‚ะธั… ั‚ะตัั‚ะฐั…. /// @@ -275,7 +275,7 @@ Flask-apispec ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั‚ะธะผะธ ะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผะธ Mar ะ—ะฝะฐะนั‚ะธ ัะฟะพัั–ะฑ ะพั‚ั€ะธะผะฐั‚ะธ ะฑะพะถะตะฒั–ะปัŒะฝัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. - ะžััŒ ั‡ะพะผัƒ **FastAPI** ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Starlette, ะพัะบั–ะปัŒะบะธ ั†ะต ะฝะฐะนัˆะฒะธะดัˆะฐ ะดะพัั‚ัƒะฟะฝะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ (ะฟะตั€ะตะฒั–ั€ะตะฝะฐ ั‚ะตัั‚ะฐะผะธ ัั‚ะพั€ะพะฝะฝั–ั… ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ). +ะžััŒ ั‡ะพะผัƒ **FastAPI** ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Starlette, ะพัะบั–ะปัŒะบะธ ั†ะต ะฝะฐะนัˆะฒะธะดัˆะฐ ะดะพัั‚ัƒะฟะฝะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ (ะฟะตั€ะตะฒั–ั€ะตะฝะฐ ั‚ะตัั‚ะฐะผะธ ัั‚ะพั€ะพะฝะฝั–ั… ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ). /// @@ -291,9 +291,9 @@ Falcon โ€” ั‰ะต ะพะดะธะฝ ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ั„ั€ะตะนะผะฒะพั€ะบ ะ—ะฝะฐะนั‚ะธ ัะฟะพัะพะฑะธ ะพั‚ั€ะธะผะฐั‚ะธ ั‡ัƒะดะพะฒัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. - ะ ะฐะทะพะผ ั–ะท Hug (ะพัะบั–ะปัŒะบะธ Hug ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Falcon) ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response` ัƒ ั„ัƒะฝะบั†ั–ัั…. +ะ ะฐะทะพะผ ั–ะท Hug (ะพัะบั–ะปัŒะบะธ Hug ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Falcon) ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response` ัƒ ั„ัƒะฝะบั†ั–ัั…. - ะฅะพั‡ะฐ ัƒ FastAPI ั†ะต ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะพ, ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒ ะพัะฝะพะฒะฝะพะผัƒ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ, ั„ะฐะนะปั–ะฒ cookie ั‚ะฐ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธั… ะบะพะดั–ะฒ ัั‚ะฐะฝัƒ. +ะฅะพั‡ะฐ ัƒ FastAPI ั†ะต ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะพ, ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒ ะพัะฝะพะฒะฝะพะผัƒ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ, ั„ะฐะนะปั–ะฒ cookie ั‚ะฐ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธั… ะบะพะดั–ะฒ ัั‚ะฐั‚ัƒััƒ. /// @@ -317,7 +317,7 @@ Falcon โ€” ั‰ะต ะพะดะธะฝ ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ั„ั€ะตะนะผะฒะพั€ะบ ะ’ะธะทะฝะฐั‡ะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฟะตั€ะตะฒั–ั€ะบะธ ะดะปั ั‚ะธะฟั–ะฒ ะดะฐะฝะธั…, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะทะฝะฐั‡ะตะฝะฝั "ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ" ะฐั‚ั€ะธะฑัƒั‚ั–ะฒ ะผะพะดะตะปั–. ะฆะต ะฟะพะบั€ะฐั‰ัƒั” ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ, ะฐ ั€ะฐะฝั–ัˆะต ะฒะพะฝะฐ ะฑัƒะปะฐ ะฝะตะดะพัั‚ัƒะฟะฝะฐ ะฒ Pydantic. - ะฆะต ั„ะฐะบั‚ะธั‡ะฝะพ ะฝะฐะดะธั…ะฝัƒะปะพ ะพะฝะพะฒะธั‚ะธ ั‡ะฐัั‚ะธะฝะธ Pydantic, ั‰ะพะฑ ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ัั‚ะธะปัŒ ะพะณะพะปะพัˆะตะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ (ะฒัั– ั†ั– ั„ัƒะฝะบั†ั–ั— ะฒะถะต ะดะพัั‚ัƒะฟะฝั– ะฒ Pydantic). +ะฆะต ั„ะฐะบั‚ะธั‡ะฝะพ ะฝะฐะดะธั…ะฝัƒะปะพ ะพะฝะพะฒะธั‚ะธ ั‡ะฐัั‚ะธะฝะธ Pydantic, ั‰ะพะฑ ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ัั‚ะธะปัŒ ะพะณะพะปะพัˆะตะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ (ะฒัั– ั†ั– ั„ัƒะฝะบั†ั–ั— ะฒะถะต ะดะพัั‚ัƒะฟะฝั– ะฒ Pydantic). /// @@ -341,13 +341,13 @@ Hug ัั‚ะฒะพั€ะธะฒ ะขั–ะผะพั‚ั– ะšั€ะพัะปั–, ั‚ะพะน ัะฐะผะธะน ั‚ะฒะพั€ะตั†ัŒ < /// -/// check | ะะฐะดะธั…ะฝัƒะปะพ **FastAPI** ะฝะฐ +/// check | ะ†ะดะตั—, ั‰ะพ ะฝะฐะดะธั…ะฝัƒะปะธ **FastAPI** Hug ะฝะฐะดะธั…ะฝัƒะฒ ั‡ะฐัั‚ะธะฝัƒ APIStar ั– ะฑัƒะฒ ะพะดะฝะธะผ ั–ะท ะฝะฐะนะฑั–ะปัŒัˆ ะฟะตั€ัะฟะตะบั‚ะธะฒะฝะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ะฟะพั€ัะด ั–ะท APIStar. - Hug ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะณะพ ัั‚ะฒะพั€ะตะฝะฝั ัั…ะตะผะธ, ั‰ะพ ะฒะธะทะฝะฐั‡ะฐั” API. +Hug ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะณะพ ัั‚ะฒะพั€ะตะฝะฝั ัั…ะตะผะธ, ั‰ะพ ะฒะธะทะฝะฐั‡ะฐั” API. - Hug ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response` ัƒ ั„ัƒะฝะบั†ั–ัั… ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั– ั„ะฐะนะปั–ะฒ cookie. +Hug ะฝะฐะดะธั…ะฝัƒะฒ **FastAPI** ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response` ัƒ ั„ัƒะฝะบั†ั–ัั… ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั– ั„ะฐะนะปั–ะฒ cookie. /// @@ -389,13 +389,13 @@ APIStar ัั‚ะฒะพั€ะธะฒ ะขะพะผ ะšั€ั–ัั‚ั–. ะขะพะน ัะฐะผะธะน ั…ะปะพะฟะตั†ัŒ, ั ะ†ัะฝัƒะฒะฐั‚ะธ. - ะ†ะดะตัŽ ะพะณะพะปะพัˆะตะฝะฝั ะบั–ะปัŒะบะพั… ั€ะตั‡ะตะน (ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—) ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะธั… ัะฐะผะธั… ั‚ะธะฟั–ะฒ Python, ัะบั– ะฒ ั‚ะพะน ะถะต ั‡ะฐั ะทะฐะฑะตะทะฟะตั‡ัƒะฒะฐะปะธ ั‡ัƒะดะพะฒัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ, ั ะฒะฒะฐะถะฐะฒ ะณะตะฝั–ะฐะปัŒะฝะพัŽ ั–ะดะตั”ัŽ. +ะ†ะดะตัŽ ะพะณะพะปะพัˆะตะฝะฝั ะบั–ะปัŒะบะพั… ั€ะตั‡ะตะน (ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—) ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะธั… ัะฐะผะธั… ั‚ะธะฟั–ะฒ Python, ัะบั– ะฒ ั‚ะพะน ะถะต ั‡ะฐั ะทะฐะฑะตะทะฟะตั‡ัƒะฒะฐะปะธ ั‡ัƒะดะพะฒัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ, ั ะฒะฒะฐะถะฐะฒ ะณะตะฝั–ะฐะปัŒะฝะพัŽ ั–ะดะตั”ัŽ. - ะ† ะฟั–ัะปั ั‚ั€ะธะฒะฐะปะพะณะพ ะฟะพัˆัƒะบัƒ ะฟะพะดั–ะฑะฝะพั— ัั‚ั€ัƒะบั‚ัƒั€ะธ ั‚ะฐ ั‚ะตัั‚ัƒะฒะฐะฝะฝั ะฑะฐะณะฐั‚ัŒะพั… ั€ั–ะทะฝะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, APIStar ัั‚ะฐะฒ ะฝะฐะนะบั€ะฐั‰ะธะผ ะดะพัั‚ัƒะฟะฝะธะผ ะฒะฐั€ั–ะฐะฝั‚ะพะผ. +ะ† ะฟั–ัะปั ั‚ั€ะธะฒะฐะปะพะณะพ ะฟะพัˆัƒะบัƒ ะฟะพะดั–ะฑะฝะพั— ัั‚ั€ัƒะบั‚ัƒั€ะธ ั‚ะฐ ั‚ะตัั‚ัƒะฒะฐะฝะฝั ะฑะฐะณะฐั‚ัŒะพั… ั€ั–ะทะฝะธั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, APIStar ัั‚ะฐะฒ ะฝะฐะนะบั€ะฐั‰ะธะผ ะดะพัั‚ัƒะฟะฝะธะผ ะฒะฐั€ั–ะฐะฝั‚ะพะผ. - ะŸะพั‚ั–ะผ APIStar ะฟะตั€ะตัั‚ะฐะฒ ั–ัะฝัƒะฒะฐั‚ะธ ัะบ ัะตั€ะฒะตั€, ั– ะฑัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ Starlette, ัะบะธะน ัั‚ะฐะฒ ะฝะพะฒะพัŽ ะบั€ะฐั‰ะพัŽ ะพัะฝะพะฒะพัŽ ะดะปั ั‚ะฐะบะพั— ัะธัั‚ะตะผะธ. ะฆะต ัั‚ะฐะปะพ ะพัั‚ะฐะฝะฝั–ะผ ะดะถะตั€ะตะปะพะผ ะฝะฐั‚ั…ะฝะตะฝะฝั ะดะปั ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. +ะŸะพั‚ั–ะผ APIStar ะฟะตั€ะตัั‚ะฐะฒ ั–ัะฝัƒะฒะฐั‚ะธ ัะบ ัะตั€ะฒะตั€, ั– ะฑัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ Starlette, ัะบะธะน ัั‚ะฐะฒ ะฝะพะฒะพัŽ ะบั€ะฐั‰ะพัŽ ะพัะฝะพะฒะพัŽ ะดะปั ั‚ะฐะบะพั— ัะธัั‚ะตะผะธ. ะฆะต ัั‚ะฐะปะพ ะพัั‚ะฐะฝะฝั–ะผ ะดะถะตั€ะตะปะพะผ ะฝะฐั‚ั…ะฝะตะฝะฝั ะดะปั ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**. - ะฏ ะฒะฒะฐะถะฐัŽ **FastAPI** ยซะดัƒั…ะพะฒะฝะธะผ ัะฟะฐะดะบะพั”ะผั†ะตะผยป APIStar, ัƒะดะพัะบะพะฝะฐะปัŽัŽั‡ะธ ั‚ะฐ ั€ะพะทัˆะธั€ัŽัŽั‡ะธ ั„ัƒะฝะบั†ั–ั—, ัะธัั‚ะตะผัƒ ั‚ะธะฟั–ะทะฐั†ั–ั— ั‚ะฐ ั–ะฝัˆั– ั‡ะฐัั‚ะธะฝะธ ะฝะฐ ะพัะฝะพะฒั– ะดะพัะฒั–ะดัƒ, ะพั‚ั€ะธะผะฐะฝะพะณะพ ะฒั–ะด ัƒัั–ั… ั†ะธั… ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. +ะฏ ะฒะฒะฐะถะฐัŽ **FastAPI** ยซะดัƒั…ะพะฒะฝะธะผ ัะฟะฐะดะบะพั”ะผั†ะตะผยป APIStar, ัƒะดะพัะบะพะฝะฐะปัŽัŽั‡ะธ ั‚ะฐ ั€ะพะทัˆะธั€ัŽัŽั‡ะธ ั„ัƒะฝะบั†ั–ั—, ัะธัั‚ะตะผัƒ ั‚ะธะฟั–ะทะฐั†ั–ั— ั‚ะฐ ั–ะฝัˆั– ั‡ะฐัั‚ะธะฝะธ ะฝะฐ ะพัะฝะพะฒั– ะดะพัะฒั–ะดัƒ, ะพั‚ั€ะธะผะฐะฝะพะณะพ ะฒั–ะด ัƒัั–ั… ั†ะธั… ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. /// @@ -403,7 +403,7 @@ APIStar ัั‚ะฒะพั€ะธะฒ ะขะพะผ ะšั€ั–ัั‚ั–. ะขะพะน ัะฐะผะธะน ั…ะปะพะฟะตั†ัŒ, ั ### Pydantic { #pydantic } -Pydantic โ€” ั†ะต ะฑั–ะฑะปั–ะพั‚ะตะบะฐ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ัั…ะตะผะธ JSON) ะฝะฐ ะพัะฝะพะฒั– ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python. +Pydantic โ€” ั†ะต ะฑั–ะฑะปั–ะพั‚ะตะบะฐ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะกั…ะตะผะธ JSON) ะฝะฐ ะพัะฝะพะฒั– ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟัƒ Python. ะฆะต ั€ะพะฑะธั‚ัŒ ะนะพะณะพ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะธะผ. @@ -411,15 +411,15 @@ Pydantic โ€” ั†ะต ะฑั–ะฑะปั–ะพั‚ะตะบะฐ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะฒั– /// check | **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะนะพะณะพ ะดะปั -ะ’ะธะบะพะฝะฐะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ ะฒัั–ั… ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ะดะฐะฝะธั… ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะผะพะดะตะปั– (ะฝะฐ ะพัะฝะพะฒั– ัั…ะตะผะธ JSON). +ะ’ะธะบะพะฝะฐะฝะฝั ะฟะตั€ะตะฒั–ั€ะบะธ ะฒัั–ั… ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ะดะฐะฝะธั… ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะผะพะดะตะปั– (ะฝะฐ ะพัะฝะพะฒั– ะกั…ะตะผะธ JSON). - ะŸะพั‚ั–ะผ **FastAPI** ะฑะตั€ะต ั†ั– ะดะฐะฝั– ัั…ะตะผะธ JSON ั– ั€ะพะทะผั–ั‰ัƒั” ั—ั… ัƒ OpenAPI, ะพะบั€ะตะผะพ ะฒั–ะด ัƒัั–ั… ั–ะฝัˆะธั… ั€ะตั‡ะตะน, ัะบั– ะฒั–ะฝ ั€ะพะฑะธั‚ัŒ. +ะŸะพั‚ั–ะผ **FastAPI** ะฑะตั€ะต ั†ั– ะดะฐะฝั– ะกั…ะตะผะธ JSON ั– ั€ะพะทะผั–ั‰ัƒั” ั—ั… ัƒ OpenAPI, ะพะบั€ะตะผะพ ะฒั–ะด ัƒัั–ั… ั–ะฝัˆะธั… ั€ะตั‡ะตะน, ัะบั– ะฒั–ะฝ ั€ะพะฑะธั‚ัŒ. /// ### Starlette { #starlette } -Starlette โ€” ั†ะต ะปะตะณะบะธะน ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑั–ั€ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ASGI, ัะบะธะน ั–ะดะตะฐะปัŒะฝะพ ะฟั–ะดั…ะพะดะธั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธั… asyncio ัะตั€ะฒั–ัั–ะฒ. +Starlette โ€” ั†ะต ะปะตะณะบะธะน ั„ั€ะตะนะผะฒะพั€ะบ/ะฝะฐะฑั–ั€ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ASGI, ัะบะธะน ั–ะดะตะฐะปัŒะฝะพ ะฟั–ะดั…ะพะดะธั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธั… asyncio ัะตั€ะฒั–ัั–ะฒ. ะ’ั–ะฝ ะดัƒะถะต ะฟั€ะพัั‚ะธะน ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปะธะน. ะ™ะพะณะพ ั€ะพะทั€ะพะฑะปะตะฝะพ ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ, ั‰ะพะฑ ะนะพะณะพ ะผะพะถะฝะฐ ะฑัƒะปะพ ะปะตะณะบะพ ั€ะพะทัˆะธั€ัŽะฒะฐั‚ะธ ั‚ะฐ ะผะฐั‚ะธ ะผะพะดัƒะปัŒะฝั– ะบะพะผะฟะพะฝะตะฝั‚ะธ. @@ -448,7 +448,7 @@ Starlette ะฝะฐะดะฐั” ะฒัั– ะพัะฝะพะฒะฝั– ั„ัƒะฝะบั†ั–ั— ะฒะตะฑ-ะผั–ะบั€ะพั„ั€ ASGI โ€” ั†ะต ะฝะพะฒะธะน ยซัั‚ะฐะฝะดะฐั€ั‚ยป, ัะบะธะน ั€ะพะทั€ะพะฑะปัั”ั‚ัŒัั ั‡ะปะตะฝะฐะผะธ ะพัะฝะพะฒะฝะพั— ะบะพะผะฐะฝะดะธ Django. ะฆะต ั‰ะต ะฝะต ยซัั‚ะฐะฝะดะฐั€ั‚ Pythonยป (PEP), ั…ะพั‡ะฐ ะฒะพะฝะธ ะฒ ะฟั€ะพั†ะตัั– ั†ัŒะพะณะพ. - ะขะธะผ ะฝะต ะผะตะฝัˆ, ะฒั–ะฝ ัƒะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัะบ ยซัั‚ะฐะฝะดะฐั€ั‚ยป ะบั–ะปัŒะบะพะผะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ. ะฆะต ะทะฝะฐั‡ะฝะพ ะฟะพะบั€ะฐั‰ัƒั” ััƒะผั–ัะฝั–ัั‚ัŒ, ะพัะบั–ะปัŒะบะธ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะบะปัŽั‡ะธั‚ะธ Uvicorn ะฝะฐ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ัะตั€ะฒะตั€ ASGI (ะฝะฐะฟั€ะธะบะปะฐะด, Daphne ะฐะฑะพ Hypercorn), ะฐะฑะพ ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ััƒะผั–ัะฝั– ะท ASGI, ัะบ-ะพั‚ `python-socketio`. +ะขะธะผ ะฝะต ะผะตะฝัˆ, ะฒั–ะฝ ัƒะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัะบ ยซัั‚ะฐะฝะดะฐั€ั‚ยป ะบั–ะปัŒะบะพะผะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ. ะฆะต ะทะฝะฐั‡ะฝะพ ะฟะพะบั€ะฐั‰ัƒั” ััƒะผั–ัะฝั–ัั‚ัŒ, ะพัะบั–ะปัŒะบะธ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะบะปัŽั‡ะธั‚ะธ Uvicorn ะฝะฐ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ัะตั€ะฒะตั€ ASGI (ะฝะฐะฟั€ะธะบะปะฐะด, Daphne ะฐะฑะพ Hypercorn), ะฐะฑะพ ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ััƒะผั–ัะฝั– ะท ASGI, ัะบ-ะพั‚ `python-socketio`. /// @@ -456,9 +456,9 @@ ASGI โ€” ั†ะต ะฝะพะฒะธะน ยซัั‚ะฐะฝะดะฐั€ั‚ยป, ัะบะธะน ั€ะพะทั€ะพะฑะปัั”ั‚ัŒั ะšะตั€ัƒะฒะฐะฝะฝั ะฒัั–ะผะฐ ะพัะฝะพะฒะฝะธะผะธ ะฒะตะฑ-ั‡ะฐัั‚ะธะฝะฐะผะธ. ะ”ะพะดะฐะฒะฐะฝะฝั ั„ัƒะฝะบั†ั–ะน ะทะฒะตั€ั…ัƒ. - ะกะฐะผ ะบะปะฐั `FastAPI` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒัะฟะฐะดะบะพะฒัƒั” ะบะปะฐั `Starlette`. +ะกะฐะผ ะบะปะฐั `FastAPI` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒัะฟะฐะดะบะพะฒัƒั” ะบะปะฐั `Starlette`. - ะžั‚ะถะต, ัƒัะต, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ั€ะพะฑะธั‚ะธ ะทั– Starlette, ะฒะธ ะผะพะถะตั‚ะต ั€ะพะฑะธั‚ะธ ั†ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ **FastAPI**, ะพัะบั–ะปัŒะบะธ ั†ะต, ะฟะพ ััƒั‚ั–, Starlette ะฝะฐ ัั‚ะตั€ะพั—ะดะฐั…. +ะžั‚ะถะต, ัƒัะต, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ั€ะพะฑะธั‚ะธ ะทั– Starlette, ะฒะธ ะผะพะถะตั‚ะต ั€ะพะฑะธั‚ะธ ั†ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ **FastAPI**, ะพัะบั–ะปัŒะบะธ ั†ะต, ะฟะพ ััƒั‚ั–, Starlette ะฝะฐ ัั‚ะตั€ะพั—ะดะฐั…. /// @@ -474,9 +474,9 @@ Uvicorn โ€” ั†ะต ะฑะปะธัะบะฐะฒะธั‡ะฝะธะน ัะตั€ะฒะตั€ ASGI, ะฟะพะฑัƒะดะพะฒะฐะฝ ะžัะฝะพะฒะฝะธะน ะฒะตะฑ-ัะตั€ะฒะตั€ ะดะปั ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผ **FastAPI**. - ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`, ั‰ะพะฑ ะผะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะฝะธะน ัะตั€ะฒะตั€. +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`, ั‰ะพะฑ ะผะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะฝะธะน ัะตั€ะฒะตั€. - ะ”ะพะดะฐั‚ะบะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะดะธะฒ. ัƒ ั€ะพะทะดั–ะปั– [ะ ะพะทะณะพั€ั‚ะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. +ะ”ะพะดะฐั‚ะบะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะดะธะฒ. ัƒ ั€ะพะทะดั–ะปั– [ะ ะพะทะณะพั€ั‚ะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. /// diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md index d8233115fd..db044bf947 100644 --- a/docs/uk/docs/features.md +++ b/docs/uk/docs/features.md @@ -6,7 +6,7 @@ ### ะะฐ ะพัะฝะพะฒั– ะฒั–ะดะบั€ะธั‚ะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ { #based-on-open-standards } -* OpenAPI ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ะฒะบะปัŽั‡ะฐัŽั‡ะธ ะพะณะพะปะพัˆะตะฝะฝั ัˆะปัั…ั–ะฒ, ะพะฟะตั€ะฐั†ั–ะน, ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ, ะฑะตะทะฟะตะบะธ ั‚ะพั‰ะพ. +* OpenAPI ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ะฒะบะปัŽั‡ะฐัŽั‡ะธ ะพะณะพะปะพัˆะตะฝะฝั ัˆะปัั…ั–ะฒ, ะพะฟะตั€ะฐั†ั–ะน, ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ, ะฑะตะทะฟะตะบะธ ั‚ะพั‰ะพ. * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะผะพะดะตะปะตะน ะดะฐะฝะธั… ะทะฐ ะดะพะฟะพะผะพะณะพัŽ JSON Schema (ะพัะบั–ะปัŒะบะธ OpenAPI ะฑะฐะทัƒั”ั‚ัŒัั ัะฐะผะต ะฝะฐ JSON Schema). * ะ ะพะทั€ะพะฑะปะตะฝะพ ะฝะฐ ะพัะฝะพะฒั– ั†ะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ ะฟั–ัะปั ั€ะตั‚ะตะปัŒะฝะพะณะพ ะฐะฝะฐะปั–ะทัƒ, ะฐ ะฝะต ัะบ ะดะพะดะฐั‚ะบะพะฒะธะน ั€ั–ะฒะตะฝัŒ ะฟะพะฒะตั€ั… ะพัะฝะพะฒะฝะพั— ะฐั€ั…ั–ั‚ะตะบั‚ัƒั€ะธ. * ะฆะต ั‚ะฐะบะพะถ ะดะฐั” ะทะผะพะณัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ **ะณะตะฝะตั€ะฐั†ั–ัŽ ะบะปั–ั”ะฝั‚ััŒะบะพะณะพ ะบะพะดัƒ** ะฑะฐะณะฐั‚ัŒะผะฐ ะผะพะฒะฐะผะธ. @@ -136,7 +136,7 @@ FastAPI ะผะฐั” ั€ะพะทัƒะผะฝั– **ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐ ### ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน { #dependency-injection } -FastAPI ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั–, ะฐะปะต ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ Dependency Injection. +FastAPI ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั–, ะฐะปะต ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟะพั‚ัƒะถะฝัƒ ัะธัั‚ะตะผัƒ ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. * ะะฐะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะปะตะถะฝะพัั‚ั–, ัƒั‚ะฒะพั€ัŽัŽั‡ะธ ั–ั”ั€ะฐั€ั…ั–ัŽ ะฐะฑะพ **ยซะณั€ะฐั„ยป ะทะฐะปะตะถะฝะพัั‚ะตะน**. * ะฃัะต **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั”ั‚ัŒัั** ั„ั€ะตะนะผะฒะพั€ะบะพะผ. @@ -153,8 +153,8 @@ FastAPI ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐ ### ะŸั€ะพั‚ะตัั‚ะพะฒะฐะฝะพ { #tested } -* 100% ะฟะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ. -* 100% ะฐะฝะพั‚ะพะฒะฐะฝะฐ ั‚ะธะฟะฐะผะธ ะบะพะดะพะฒะฐ ะฑะฐะทะฐ. +* 100% ะฟะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ. +* 100% ะฐะฝะพั‚ะพะฒะฐะฝะฐ ั‚ะธะฟะฐะผะธ ะบะพะดะพะฒะฐ ะฑะฐะทะฐ. * ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒ production-ะทะฐัั‚ะพััƒะฝะบะฐั…. ## ะœะพะถะปะธะฒะพัั‚ั– Starlette { #starlette-features } @@ -190,7 +190,7 @@ FastAPI ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐ * **ะั–ัะบะพั— ะฟะปัƒั‚ะฐะฝะธะฝะธ**: * ะะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒั‡ะธั‚ะธ ะฝะพะฒัƒ ะผั–ะบั€ะพะผะพะฒัƒ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ัั…ะตะผ. * ะฏะบั‰ะพ ะฒะธ ะทะฝะฐั”ั‚ะต ั‚ะธะฟะธ Python, ะฒะธ ะทะฝะฐั”ั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Pydantic. -* ะ›ะตะณะบะพ ะฟั€ะฐั†ัŽั” ะท ะฒะฐัˆะธะผ **IDE/linter/ะผะพะทะบะพะผ**: +* ะ›ะตะณะบะพ ะฟั€ะฐั†ัŽั” ะท ะฒะฐัˆะธะผ **IDE/linter/ะผะพะทะบะพะผ**: * ะžัะบั–ะปัŒะบะธ ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั… pydantic ั” ะฟั€ะพัั‚ะพ ะตะบะทะตะผะฟะปัั€ะฐะผะธ ะบะปะฐัั–ะฒ, ัะบั– ะฒะธ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต; ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั, ะปั–ะฝั‚ะธะฝะณ, mypy ั– ะฒะฐัˆะฐ ั–ะฝั‚ัƒั—ั†ั–ั ะฟะพะฒะธะฝะฝั– ะดะพะฑั€ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท ะฒะฐัˆะธะผะธ ะฟะตั€ะตะฒั–ั€ะตะฝะธะผะธ ะดะฐะฝะธะผะธ. * ะ’ะฐะปั–ะดัƒั” **ัะบะปะฐะดะฝั– ัั‚ั€ัƒะบั‚ัƒั€ะธ**: * ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั–ั”ั€ะฐั€ั…ั–ั‡ะฝะธั… ะผะพะดะตะปะตะน Pydantic, Python `typing`โ€™s `List` ั– `Dict` ั‚ะพั‰ะพ. diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 4f089c4e1a..0a6788502a 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -40,7 +40,7 @@ FastAPI - ั†ะต ััƒั‡ะฐัะฝะธะน, ัˆะฒะธะดะบะธะน (ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒ * **ะจะฒะธะดะบะธะน**: ะดัƒะถะต ะฒะธัะพะบะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะฝะฐ ั€ั–ะฒะฝั– ะท **NodeJS** ั‚ะฐ **Go** (ะทะฐะฒะดัะบะธ Starlette ั‚ะฐ Pydantic). [ะžะดะธะฝ ั–ะท ะฝะฐะนัˆะฒะธะดัˆะธั… Python-ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ](#performance). * **ะจะฒะธะดะบะต ะฝะฐะฟะธัะฐะฝะฝั ะบะพะดัƒ**: ะฟั€ะธัˆะฒะธะดัˆัƒั” ั€ะพะทั€ะพะฑะบัƒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัƒ ะฟั€ะธะฑะปะธะทะฝะพ ะฝะฐ 200%โ€“300%. * * **ะœะตะฝัˆะต ะฟะพะผะธะปะพะบ**: ะทะผะตะฝัˆัƒั” ะฟั€ะธะฑะปะธะทะฝะพ ะฝะฐ 40% ะบั–ะปัŒะบั–ัั‚ัŒ ะฟะพะผะธะปะพะบ, ัะฟั€ะธั‡ะธะฝะตะฝะธั… ะปัŽะดะธะฝะพัŽ (ั€ะพะทั€ะพะฑะฝะธะบะพะผ). * -* **ะ†ะฝั‚ัƒั—ั‚ะธะฒะฝะธะน**: ั‡ัƒะดะพะฒะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐะผะธ ะบะพะดัƒ. ะะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั. +* **ะ†ะฝั‚ัƒั—ั‚ะธะฒะฝะธะน**: ั‡ัƒะดะพะฒะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ ั€ะตะดะฐะบั‚ะพั€ะฐะผะธ ะบะพะดัƒ. ะะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั. * **ะŸั€ะพัั‚ะธะน**: ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะธะน ั‚ะฐะบ, ั‰ะพะฑ ะฑัƒั‚ะธ ะฟั€ะพัั‚ะธะผ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ั‚ะฐ ะฒะธะฒั‡ะตะฝะฝั–. ะœะตะฝัˆะต ั‡ะฐััƒ ะฝะฐ ั‡ะธั‚ะฐะฝะฝั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. * **ะšะพั€ะพั‚ะบะธะน**: ะผั–ะฝั–ะผั–ะทัƒั” ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ. ะšั–ะปัŒะบะฐ ะผะพะถะปะธะฒะพัั‚ะตะน ะท ะบะพะถะฝะพะณะพ ะพะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ะฐ. ะœะตะฝัˆะต ะฟะพะผะธะปะพะบ. * **ะะฐะดั–ะนะฝะธะน**: ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะบะพะด, ะณะพั‚ะพะฒะธะน ะดะพ ะฟั€ะพะดะฐะบัˆะธะฝัƒ. ะ— ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ. @@ -127,7 +127,7 @@ FastAPI - ั†ะต ััƒั‡ะฐัะฝะธะน, ัˆะฒะธะดะบะธะน (ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒ -ะฏะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ CLI ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒ ั‚ะตั€ะผั–ะฝะฐะปั– ะทะฐะผั–ัั‚ัŒ ะฒะตะฑ-API, ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ **Typer**. +ะฏะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ CLI ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒ ั‚ะตั€ะผั–ะฝะฐะปั– ะทะฐะผั–ัั‚ัŒ ะฒะตะฑ-API, ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ **Typer**. **Typer** - ะผะพะปะพะดัˆะธะน ะฑั€ะฐั‚ FastAPI. ะ† ะนะพะณะพ ะทะฐะดัƒะผะฐะฝะพ ัะบ **FastAPI ะดะปั CLI**. โŒจ๏ธ ๐Ÿš€ @@ -368,7 +368,7 @@ item: Item * ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…: * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝั– ั‚ะฐ ะทั€ะพะทัƒะผั–ะปั– ะฟะพะผะธะปะบะธ, ะบะพะปะธ ะดะฐะฝั– ะฝะตะบะพั€ะตะบั‚ะฝั–. * ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะฝะฐะฒั–ั‚ัŒ ะดะปั ะณะปะธะฑะพะบะพ ะฒะบะปะฐะดะตะฝะธั… JSON-ะพะฑสผั”ะบั‚ั–ะฒ. -* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะท ะผะตั€ะตะถั– ะดะพ ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python. ะงะธั‚ะฐะฝะฝั ะท: +* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะท ะผะตั€ะตะถั– ะดะพ ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python. ะงะธั‚ะฐะฝะฝั ะท: * JSON. * ะŸะฐั€ะฐะผะตั‚ั€ั–ะฒ ัˆะปัั…ัƒ. * ะŸะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ. @@ -376,7 +376,7 @@ item: Item * Headers. * Forms. * Files. -* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒะธั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะท ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python ัƒ ะผะตั€ะตะถะตะฒั– ะดะฐะฝั– (ัะบ JSON): +* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒะธั…ั–ะดะฝะธั… ะดะฐะฝะธั…: ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะท ะดะฐะฝะธั… ั– ั‚ะธะฟั–ะฒ Python ัƒ ะผะตั€ะตะถะตะฒั– ะดะฐะฝั– (ัะบ JSON): * ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ั‚ะธะฟั–ะฒ Python (`str`, `int`, `float`, `bool`, `list`, ั‚ะพั‰ะพ). * ะžะฑสผั”ะบั‚ั–ะฒ `datetime`. * ะžะฑสผั”ะบั‚ั–ะฒ `UUID`. @@ -439,7 +439,7 @@ item: Item * ะžะณะพะปะพัˆะตะฝะฝั **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ** ะท ั–ะฝัˆะธั… ั€ั–ะทะฝะธั… ะผั–ัั†ัŒ, ัะบ-ะพั‚: **headers**, **cookies**, **form fields** ั‚ะฐ **files**. * ะฏะบ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ **ะพะฑะผะตะถะตะฝะฝั ะฒะฐะปั–ะดะฐั†ั–ั—** ัะบ `maximum_length` ะฐะฑะพ `regex`. -* ะ”ัƒะถะต ะฟะพั‚ัƒะถะฝัƒ ั– ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ัะธัั‚ะตะผัƒ **Dependency Injection**. +* ะ”ัƒะถะต ะฟะพั‚ัƒะถะฝัƒ ั– ะฟั€ะพัั‚ัƒ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ัะธัั‚ะตะผัƒ **ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**. * ะ‘ะตะทะฟะตะบัƒ ั‚ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ, ะฒะบะปัŽั‡ะฝะพ ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ **OAuth2** ะท **JWT tokens** ั‚ะฐ **HTTP Basic** auth. * ะ”ะพัะบะพะฝะฐะปั–ัˆั– (ะฐะปะต ะพะดะฝะฐะบะพะฒะพ ะฟั€ะพัั‚ั–) ั‚ะตั…ะฝั–ะบะธ ะดะปั ะพะณะพะปะพัˆะตะฝะฝั **ะณะปะธะฑะพะบะพ ะฒะบะปะฐะดะตะฝะธั… ะผะพะดะตะปะตะน JSON** (ะทะฐะฒะดัะบะธ Pydantic). * ะ†ะฝั‚ะตะณั€ะฐั†ั–ัŽ **GraphQL** ะท Strawberry ั‚ะฐ ั–ะฝัˆะธะผะธ ะฑั–ะฑะปั–ะพั‚ะตะบะฐะผะธ. @@ -524,7 +524,7 @@ FastAPI ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด Pydantic ั– Starlette. * httpx - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `TestClient`. * jinja2 - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ ัˆะฐะฑะปะพะฝั–ะฒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. -* python-multipart - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ยซparsingยป ั„ะพั€ะผ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `request.form()`. +* python-multipart - ะฟะพั‚ั€ั–ะฑะฝะพ, ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ั„ะพั€ะผะธ ะท ยซะฟะฐั€ัะธะฝะณะพะผยป ั‡ะตั€ะตะท `request.form()`. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั FastAPI: diff --git a/docs/uk/docs/learn/index.md b/docs/uk/docs/learn/index.md index 6e28d414ad..ad468fea18 100644 --- a/docs/uk/docs/learn/index.md +++ b/docs/uk/docs/learn/index.md @@ -1,5 +1,5 @@ # ะะฐะฒั‡ะฐะฝะฝั { #learn } -ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฝะฐะดะฐะฝั– ะฒัั‚ัƒะฟะฝั– ั€ะพะทะดั–ะปะธ ั‚ะฐ ะฝะฐะฒั‡ะฐะปัŒะฝั– ะผะฐั‚ะตั€ั–ะฐะปะธ ะดะปั ะฒะธะฒั‡ะตะฝะฝั **FastAPI**. +ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฝะฐะดะฐะฝั– ะฒัั‚ัƒะฟะฝั– ั€ะพะทะดั–ะปะธ ั‚ะฐ ะฝะฐะฒั‡ะฐะปัŒะฝั– ะฟะพัั–ะฑะฝะธะบะธ ะดะปั ะฒะธะฒั‡ะตะฝะฝั **FastAPI**. ะฆะต ะผะพะถะฝะฐ ั€ะพะทะณะปัะดะฐั‚ะธ ัะบ **ะบะฝะธะณัƒ**, **ะบัƒั€ั**, ะฐะฑะพ **ะพั„ั–ั†ั–ะนะฝะธะน** ั‚ะฐ ั€ะตะบะพะผะตะฝะดะพะฒะฐะฝะธะน ัะฟะพัั–ะฑ ะพัะฒะพั—ั‚ะธ FastAPI. ๐Ÿ˜Ž diff --git a/docs/uk/docs/python-types.md b/docs/uk/docs/python-types.md index a82d13a285..deeeb2f9c5 100644 --- a/docs/uk/docs/python-types.md +++ b/docs/uk/docs/python-types.md @@ -2,11 +2,11 @@ Python ะฟั–ะดั‚ั€ะธะผัƒั” ะดะพะดะฐั‚ะบะพะฒั– ยซะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒยป (ั‚ะฐะบะพะถ ะทะฒะฐะฝั– ยซะฐะฝะพั‚ะฐั†ั–ัะผะธ ั‚ะธะฟั–ะฒยป). -ะฆั– **ยซะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒยป** ะฐะฑะพ ะฐะฝะพั‚ะฐั†ั–ั— โ€” ั†ะต ัะฟะตั†ั–ะฐะปัŒะฝะธะน ัะธะฝั‚ะฐะบัะธั, ั‰ะพ ะดะพะทะฒะพะปัั” ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั‚ะธะฟ ะทะผั–ะฝะฝะพั—. +ะฆั– **ยซะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒยป** ะฐะฑะพ ะฐะฝะพั‚ะฐั†ั–ั— โ€” ั†ะต ัะฟะตั†ั–ะฐะปัŒะฝะธะน ัะธะฝั‚ะฐะบัะธั, ั‰ะพ ะดะพะทะฒะพะปัั” ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั‚ะธะฟ ะทะผั–ะฝะฝะพั—. ะ—ะฐ ะดะพะฟะพะผะพะณะพัŽ ะพะณะพะปะพัˆะตะฝะฝั ั‚ะธะฟั–ะฒ ะดะปั ะฒะฐัˆะธั… ะทะผั–ะฝะฝะธั… ั€ะตะดะฐะบั‚ะพั€ะธ ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะผะพะถัƒั‚ัŒ ะฝะฐะดะฐั‚ะธ ะฒะฐะผ ะบั€ะฐั‰ัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ. -ะฆะต ะปะธัˆะต **ัˆะฒะธะดะบะธะน ั‚ัƒั‚ะพั€ั–ะฐะป / ะฝะฐะณะฐะดัƒะฒะฐะฝะฝั** ะฟั€ะพ ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ัƒ Python. ะ’ั–ะฝ ะฟะพะบั€ะธะฒะฐั” ะปะธัˆะต ะผั–ะฝั–ะผัƒะผ, ะฝะตะพะฑั…ั–ะดะฝะธะน ั‰ะพะฑ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะท **FastAPI**... ั‰ะพ ะฝะฐัะฟั€ะฐะฒะดั– ะดัƒะถะต ะผะฐะปะพ. +ะฆะต ะปะธัˆะต **ัˆะฒะธะดะบะธะน ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ / ะฝะฐะณะฐะดัƒะฒะฐะฝะฝั** ะฟั€ะพ ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ัƒ Python. ะ’ั–ะฝ ะฟะพะบั€ะธะฒะฐั” ะปะธัˆะต ะผั–ะฝั–ะผัƒะผ, ะฝะตะพะฑั…ั–ะดะฝะธะน ั‰ะพะฑ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะท **FastAPI**... ั‰ะพ ะฝะฐัะฟั€ะฐะฒะดั– ะดัƒะถะต ะผะฐะปะพ. **FastAPI** ะฟะพะฒะฝั–ัั‚ัŽ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ั†ะธั… ะฟั–ะดะบะฐะทะบะฐั… ั‚ะธะฟั–ะฒ, ะฒะพะฝะธ ะดะฐัŽั‚ัŒ ะนะพะผัƒ ะฑะฐะณะฐั‚ะพ ะฟะตั€ะตะฒะฐะณ ั– ะบะพั€ะธัั‚ั–. @@ -22,7 +22,7 @@ Python ะฟั–ะดั‚ั€ะธะผัƒั” ะดะพะดะฐั‚ะบะพะฒั– ยซะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒยป (ั‚ ะ”ะฐะฒะฐะนั‚ะต ะฟะพั‡ะฝะตะผะพ ะท ะฟั€ะพัั‚ะพะณะพ ะฟั€ะธะบะปะฐะดัƒ: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} ะ’ะธะบะปะธะบ ั†ั–ั”ั— ะฟั€ะพะณั€ะฐะผะธ ะฒะธะฒะพะดะธั‚ัŒ: @@ -34,9 +34,9 @@ John Doe * ะ‘ะตั€ะต `first_name` ั‚ะฐ `last_name`. * ะŸะตั€ะตั‚ะฒะพั€ัŽั” ะฟะตั€ัˆัƒ ะปั–ั‚ะตั€ัƒ ะบะพะถะฝะพะณะพ ะท ะฝะธั… ัƒ ะฒะตั€ั…ะฝั–ะน ั€ะตะณั–ัั‚ั€ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `title()`. -* ะšะพะฝะบะฐั‚ะตะฝัƒั” ั—ั… ั€ะฐะทะพะผ ั–ะท ะฟั€ะพะฑั–ะปะพะผ ะฟะพ ัะตั€ะตะดะธะฝั–. +* ะšะพะฝะบะฐั‚ะตะฝัƒั” ั—ั… ั€ะฐะทะพะผ ั–ะท ะฟั€ะพะฑั–ะปะพะผ ะฟะพ ัะตั€ะตะดะธะฝั–. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### ะ ะตะดะฐะณัƒะนั‚ะต ั†ะต { #edit-it } @@ -78,7 +78,7 @@ John Doe ะฆะต ยซะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒยป: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} ะฆะต ะฝะต ั‚ะต ัะฐะผะต, ั‰ะพ ะพะณะพะปะพัˆะตะฝะฝั ะทะฝะฐั‡ะตะฝัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ัะบ ั†ะต ะฑัƒะปะพ ะฑ ะท: @@ -106,15 +106,15 @@ John Doe ะŸะตั€ะตะฒั–ั€ั‚ะต ั†ัŽ ั„ัƒะฝะบั†ั–ัŽ, ะฒะพะฝะฐ ะฒะถะต ะผะฐั” ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} ะžัะบั–ะปัŒะบะธ ั€ะตะดะฐะบั‚ะพั€ ะทะฝะฐั” ั‚ะธะฟะธ ะทะผั–ะฝะฝะธั…, ะฒะธ ะฝะต ั‚ั–ะปัŒะบะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฐะฒั‚ะพะทะฐะฟะพะฒะฝะตะฝะฝั, ะฒะธ ั‚ะฐะบะพะถ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะตั€ะตะฒั–ั€ะบัƒ ะฟะพะผะธะปะพะบ: -ะขะตะฟะตั€ ะฒะธ ะทะฝะฐั”ั‚ะต, ั‰ะพะฑ ะฒะธะฟั€ะฐะฒะธั‚ะธ ั†ะต, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ `age` ัƒ ั€ัะดะพะบ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `str(age)`: +ะขะตะฟะตั€ ะฒะธ ะทะฝะฐั”ั‚ะต, ั‰ะพะฑ ะฒะธะฟั€ะฐะฒะธั‚ะธ ั†ะต, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ `age` ัƒ ัั‚ั€ะพะบัƒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## ะžะณะพะปะพัˆะตะฝะฝั ั‚ะธะฟั–ะฒ { #declaring-types } @@ -133,29 +133,32 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Generic-ั‚ะธะฟะธ ะท ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ั‚ะธะฟั–ะฒ { #generic-types-with-type-parameters } +### ะœะพะดัƒะปัŒ `typing` { #typing-module } -ะ†ัะฝัƒัŽั‚ัŒ ะดะตัะบั– ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั…, ัะบั– ะผะพะถัƒั‚ัŒ ะผั–ัั‚ะธั‚ะธ ั–ะฝัˆั– ะทะฝะฐั‡ะตะฝะฝั, ะฝะฐะฟั€ะธะบะปะฐะด `dict`, `list`, `set` ั‚ะฐ `tuple`. ะ† ะฒะฝัƒั‚ั€ั–ัˆะฝั– ะทะฝะฐั‡ะตะฝะฝั ั‚ะฐะบะพะถ ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ัะฒั–ะน ั‚ะธะฟ. +ะ”ะปั ะดะตัะบะธั… ะดะพะดะฐั‚ะบะพะฒะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะตะปะตะผะตะฝั‚ะธ ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะพั— ะฑั–ะฑะปั–ะพั‚ะตะบะธ, ะผะพะดัƒะปั `typing`. ะะฐะฟั€ะธะบะปะฐะด, ะบะพะปะธ ะฒะธ ั…ะพั‡ะตั‚ะต ะพะณะพะปะพัะธั‚ะธ, ั‰ะพ ั‰ะพััŒ ะผะฐั” ยซะฑัƒะดัŒ-ัะบะธะน ั‚ะธะฟยป, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `Any` ะท `typing`: -ะฆั– ั‚ะธะฟะธ, ัะบั– ะผะฐัŽั‚ัŒ ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั‚ะธะฟะธ, ะฝะฐะทะธะฒะฐัŽั‚ัŒัั ยซ**generic**ยป ั‚ะธะฟะฐะผะธ. ะ† ะพะณะพะปะพัะธั‚ะธ ั—ั… ะผะพะถะฝะฐ ะฝะฐะฒั–ั‚ัŒ ั–ะท ะฒะฝัƒั‚ั€ั–ัˆะฝั–ะผะธ ั‚ะธะฟะฐะผะธ. +```python +from typing import Any -ะฉะพะฑ ะพะณะพะปะพัะธั‚ะธ ั†ั– ั‚ะธะฟะธ ั‚ะฐ ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั‚ะธะฟะธ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน ะผะพะดัƒะปัŒ Python `typing`. ะ’ั–ะฝ ั–ัะฝัƒั” ัะฟะตั†ั–ะฐะปัŒะฝะพ ะดะปั ะฟั–ะดั‚ั€ะธะผะบะธ ั†ะธั… ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟั–ะฒ. -#### ะะพะฒั–ัˆั– ะฒะตั€ัั–ั— Python { #newer-versions-of-python } - -ะกะธะฝั‚ะฐะบัะธั ั–ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ `typing` **ััƒะผั–ัะฝะธะน** ะท ัƒัั–ะผะฐ ะฒะตั€ัั–ัะผะธ, ะฒั–ะด Python 3.6 ะดะพ ะพัั‚ะฐะฝะฝั–ั…, ะฒะบะปัŽั‡ะฐัŽั‡ะธ Python 3.9, Python 3.10 ั‚ะพั‰ะพ. +def some_function(data: Any): + print(data) +``` -ะฃ ะผั–ั€ัƒ ั€ะพะทะฒะธั‚ะบัƒ Python **ะฝะพะฒั–ัˆั– ะฒะตั€ัั–ั—** ะผะฐัŽั‚ัŒ ะฟะพะบั€ะฐั‰ะตะฝัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ ั†ะธั… ะฐะฝะพั‚ะฐั†ั–ะน ั‚ะธะฟั–ะฒ ั– ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะฐะผ ะฝะฐะฒั–ั‚ัŒ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะดะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดัƒะปัŒ `typing` ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะฐะฝะพั‚ะฐั†ั–ะน ั‚ะธะฟั–ะฒ. +### Generic ั‚ะธะฟะธ { #generic-types } -ะฏะบั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะฑั€ะฐั‚ะธ ะฝะพะฒั–ัˆัƒ ะฒะตั€ัั–ัŽ Python ะดะปั ัะฒะพะณะพ ะฟั€ะพะตะบั‚ัƒ, ะฒะธ ะทะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ั†ั–ั”ัŽ ะดะพะดะฐั‚ะบะพะฒะพัŽ ะฟั€ะพัั‚ะพั‚ะพัŽ. +ะ”ะตัะบั– ั‚ะธะฟะธ ะผะพะถัƒั‚ัŒ ะฟั€ะธะนะผะฐั‚ะธ ยซะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ะธะฟั–ะฒยป ัƒ ะบะฒะฐะดั€ะฐั‚ะฝะธั… ะดัƒะถะบะฐั…, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ั—ั… ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั‚ะธะฟะธ. ะะฐะฟั€ะธะบะปะฐะด, ยซlist ัั‚ั€ะพะบยป ะฑัƒะดะต ะพะณะพะปะพัˆะตะฝะธะน ัะบ `list[str]`. -ะฃ ะฒัั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั” ะฟั€ะธะบะปะฐะดะธ, ััƒะผั–ัะฝั– ะท ะบะพะถะฝะพัŽ ะฒะตั€ัั–ั”ัŽ Python (ะบะพะปะธ ั” ั€ั–ะทะฝะธั†ั). +ะฆั– ั‚ะธะฟะธ, ัะบั– ะผะพะถัƒั‚ัŒ ะฟั€ะธะนะผะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ะธะฟั–ะฒ, ะฝะฐะทะธะฒะฐัŽั‚ัŒัั **generic ั‚ะธะฟะฐะผะธ** ะฐะฑะพ **generics**. -ะะฐะฟั€ะธะบะปะฐะด, ยซ**Python 3.6+**ยป ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ั†ะต ััƒะผั–ัะฝะพ ะท Python 3.6 ะฐะฑะพ ะฒะธั‰ะต (ะฒะบะปัŽั‡ะฝะพ ะท 3.7, 3.8, 3.9, 3.10 ั‚ะพั‰ะพ). ะ ยซ**Python 3.9+**ยป ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ั†ะต ััƒะผั–ัะฝะพ ะท Python 3.9 ะฐะฑะพ ะฒะธั‰ะต (ะฒะบะปัŽั‡ะฐัŽั‡ะธ 3.10 ั‚ะพั‰ะพ). +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ะฒะฑัƒะดะพะฒะฐะฝั– ั‚ะธะฟะธ ัะบ generics (ะท ะบะฒะฐะดั€ะฐั‚ะฝะธะผะธ ะดัƒะถะบะฐะผะธ ั‚ะฐ ั‚ะธะฟะฐะผะธ ะฒัะตั€ะตะดะธะฝั–): -ะฏะบั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **ะพัั‚ะฐะฝะฝั– ะฒะตั€ัั–ั— Python**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฟั€ะธะบะปะฐะดะธ ะดะปั ะพัั‚ะฐะฝะฝัŒะพั— ะฒะตั€ัั–ั— โ€” ะฒะพะฝะธ ะผะฐั‚ะธะผัƒั‚ัŒ **ะฝะฐะนะบั€ะฐั‰ะธะน ั– ะฝะฐะนะฟั€ะพัั‚ั–ัˆะธะน ัะธะฝั‚ะฐะบัะธั**, ะฝะฐะฟั€ะธะบะปะฐะด, ยซ**Python 3.10+**ยป. +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -167,7 +170,7 @@ John Doe ะžัะบั–ะปัŒะบะธ ัะฟะธัะพะบ ั” ั‚ะธะฟะพะผ, ัะบะธะน ะผั–ัั‚ะธั‚ัŒ ะดะตัะบั– ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั‚ะธะฟะธ, ะฒะธ ะฟะพะผั–ั‰ะฐั”ั‚ะต ั—ั… ัƒ ะบะฒะฐะดั€ะฐั‚ะฝั– ะดัƒะถะบะธ: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั @@ -193,7 +196,7 @@ John Doe ะ’ะธ ะฟะพะฒะธะฝะฝั– ะทั€ะพะฑะธั‚ะธ ั‚ะต ะถ ัะฐะผะต, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ `tuple` ั– `set`: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} ะฆะต ะพะทะฝะฐั‡ะฐั”: @@ -208,56 +211,32 @@ John Doe ะ”ั€ัƒะณะธะน ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ ะดะปั ะทะฝะฐั‡ะตะฝัŒ ัƒ `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} ะฆะต ะพะทะฝะฐั‡ะฐั”: * ะ—ะผั–ะฝะฝะฐ `prices` โ€” ั†ะต `dict`: - * ะšะปัŽั‡ั– ั†ัŒะพะณะพ `dict` ะผะฐัŽั‚ัŒ ั‚ะธะฟ `str` (ัะบะฐะถั–ะผะพ, ะฝะฐะทะฒะฐ ะบะพะถะฝะพะณะพ ะตะปะตะผะตะฝั‚ัƒ). - * ะ—ะฝะฐั‡ะตะฝะฝั ั†ัŒะพะณะพ `dict` ะผะฐัŽั‚ัŒ ั‚ะธะฟ `float` (ัะบะฐะถั–ะผะพ, ั†ั–ะฝะฐ ะบะพะถะฝะพะณะพ ะตะปะตะผะตะฝั‚ัƒ). + * ะšะปัŽั‡ั– ั†ัŒะพะณะพ `dict` ะผะฐัŽั‚ัŒ ั‚ะธะฟ `str` (ัะบะฐะถั–ะผะพ, ะฝะฐะทะฒะฐ ะบะพะถะฝะพะณะพ ะฟั€ะตะดะผะตั‚ะฐ). + * ะ—ะฝะฐั‡ะตะฝะฝั ั†ัŒะพะณะพ `dict` ะผะฐัŽั‚ัŒ ั‚ะธะฟ `float` (ัะบะฐะถั–ะผะพ, ั†ั–ะฝะฐ ะบะพะถะฝะพะณะพ ะฟั€ะตะดะผะตั‚ะฐ). #### Union { #union } ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ, ั‰ะพ ะทะผั–ะฝะฝะฐ ะผะพะถะต ะฑัƒั‚ะธ ะฑัƒะดัŒ-ัะบะธะผ ั–ะท **ะบั–ะปัŒะบะพั… ั‚ะธะฟั–ะฒ**, ะฝะฐะฟั€ะธะบะปะฐะด `int` ะฐะฑะพ `str`. -ะฃ Python 3.6 ั– ะฒะธั‰ะต (ะฒะบะปัŽั‡ะฐัŽั‡ะธ Python 3.10) ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะธะฟ `Union` ะท `typing` ั– ะฒัั‚ะฐะฒะปัั‚ะธ ะฒ ะบะฒะฐะดั€ะฐั‚ะฝั– ะดัƒะถะบะธ ะผะพะถะปะธะฒั– ั‚ะธะฟะธ, ัะบั– ะผะพะถะฝะฐ ะฟั€ะธะนะฝัั‚ะธ. - -ะฃ Python 3.10 ั‚ะฐะบะพะถ ั” **ะฝะพะฒะธะน ัะธะฝั‚ะฐะบัะธั**, ัƒ ัะบะพะผัƒ ะฒะธ ะผะพะถะตั‚ะต ั€ะพะทะดั–ะปะธั‚ะธ ะผะพะถะปะธะฒั– ั‚ะธะฟะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฒะตั€ั‚ะธะบะฐะปัŒะฝะพั— ัะผัƒะณะธ (`|`). +ะฉะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ั†ะต, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒ ั€ะธัะบัƒ (`|`), ั‰ะพะฑ ั€ะพะทะดั–ะปะธั‚ะธ ะพะฑะธะดะฒะฐ ั‚ะธะฟะธ. -//// tab | Python 3.10+ +ะฆะต ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซunionยป, ั‚ะพะผัƒ ั‰ะพ ะทะผั–ะฝะฝะฐ ะผะพะถะต ะฑัƒั‚ะธ ั‡ะธะผะพััŒ ั–ะท ะพะฑโ€™ั”ะดะฝะฐะฝะฝั ั†ะธั… ะดะฒะพั… ะผะฝะพะถะธะฝ ั‚ะธะฟั–ะฒ. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -ะ’ ะพะฑะพั… ะฒะธะฟะฐะดะบะฐั… ั†ะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ `item` ะผะพะถะต ะฑัƒั‚ะธ `int` ะฐะฑะพ `str`. +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ `item` ะผะพะถะต ะฑัƒั‚ะธ `int` ะฐะฑะพ `str`. #### ะœะพะถะปะธะฒะพ `None` { #possibly-none } ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะผะพะถะต ะผะฐั‚ะธ ั‚ะธะฟ, ะฝะฐะฟั€ะธะบะปะฐะด `str`, ะฐะปะต ั‚ะฐะบะพะถ ะผะพะถะต ะฑัƒั‚ะธ `None`. -ะฃ Python 3.6 ั– ะฒะธั‰ะต (ะฒะบะปัŽั‡ะฐัŽั‡ะธ Python 3.10) ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะนะพะณะพ, ั–ะผะฟะพั€ั‚ัƒะฒะฐะฒัˆะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `Optional` ะท ะผะพะดัƒะปั `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `Optional[str]` ะทะฐะผั–ัั‚ัŒ ะฟั€ะพัั‚ะพ `str` ะดะพะทะฒะพะปะธั‚ัŒ ั€ะตะดะฐะบั‚ะพั€ัƒ ะดะพะฟะพะผะพะณั‚ะธ ะฒะฐะผ ะฒะธัะฒะธั‚ะธ ะฟะพะผะธะปะบะธ, ะบะพะปะธ ะฒะธ ะผะพะณะปะธ ะฑ ะฒะฒะฐะถะฐั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐะฒะถะดะธ ั” `str`, ั…ะพั‡ะฐ ะฝะฐัะฟั€ะฐะฒะดั– ะฒะพะฝะพ ั‚ะฐะบะพะถ ะผะพะถะต ะฑัƒั‚ะธ `None`. - -`Optional[Something]` ะฝะฐัะฟั€ะฐะฒะดั– ั” ัะบะพั€ะพั‡ะตะฝะฝัะผ ะดะปั `Union[Something, None]`, ะฒะพะฝะธ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝั–. - -ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒ Python 3.10 ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ John Doe //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `Union` ะฐะฑะพ `Optional` { #using-union-or-optional } - -ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฒะตั€ัั–ัŽ Python ะฝะธะถั‡ะต 3.10, ะพััŒ ะฟะพั€ะฐะดะฐ ะท ะผะพั”ั— ะดัƒะถะต **ััƒะฑโ€™ั”ะบั‚ะธะฒะฝะพั—** ั‚ะพั‡ะบะธ ะทะพั€ัƒ: - -* ๐Ÿšจ ะฃะฝะธะบะฐะนั‚ะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `Optional[SomeType]` -* ะะฐั‚ะพะผั–ัั‚ัŒ โœจ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `Union[SomeType, None]`** โœจ. - -ะžะฑะธะดะฒะฐ ะฒะฐั€ั–ะฐะฝั‚ะธ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝั– ะน ยซะฟั–ะด ะบะฐะฟะพั‚ะพะผยป ั†ะต ะพะดะฝะต ะน ั‚ะต ัะฐะผะต, ะฐะปะต ั ั€ะตะบะพะผะตะฝะดัƒัŽ `Union` ะทะฐะผั–ัั‚ัŒ `Optional`, ั‚ะพะผัƒ ั‰ะพ ัะปะพะฒะพ ยซ**optional**ยป ะผะพะถะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฒั€ะฐะถะตะฝะฝั, ะฝั–ะฑะธ ะทะฝะฐั‡ะตะฝะฝั ั” ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ั…ะพั‡ะฐ ะฝะฐัะฟั€ะฐะฒะดั– ั†ะต ะพะทะฝะฐั‡ะฐั” ยซะฒะพะฝะพ ะผะพะถะต ะฑัƒั‚ะธ `None`ยป, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะพ ะฝะต ั” ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ ั– ะฒัะต ะพะดะฝะพ ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ. - -ะฏ ะฒะฒะฐะถะฐัŽ, ั‰ะพ `Union[SomeType, None]` ะฑั–ะปัŒัˆ ัะฒะฝะพ ะฟะพะบะฐะทัƒั”, ั‰ะพ ัะฐะผะต ะผะฐั”ั‚ัŒัั ะฝะฐ ัƒะฒะฐะทั–. - -ะฆะต ะปะธัˆะต ะฟั€ะพ ัะปะพะฒะฐ ะน ะฝะฐะทะฒะธ. ะะปะต ั†ั– ัะปะพะฒะฐ ะผะพะถัƒั‚ัŒ ะฒะฟะปะธะฒะฐั‚ะธ ะฝะฐ ั‚ะต, ัะบ ะฒะธ ั‚ะฐ ะฒะฐัˆะฐ ะบะพะผะฐะฝะดะฐ ะดัƒะผะฐั”ั‚ะต ะฟั€ะพ ะบะพะด. - -ะฏะบ ะฟั€ะธะบะปะฐะด, ั€ะพะทะณะปัะฝัŒะผะพ ั†ัŽ ั„ัƒะฝะบั†ั–ัŽ: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -ะŸะฐั€ะฐะผะตั‚ั€ `name` ะฒะธะทะฝะฐั‡ะตะฝะพ ัะบ `Optional[str]`, ะฐะปะต ะฒั–ะฝ **ะฝะต ั” ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ**, ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฒะธะบะปะธะบะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ ะฑะตะท ะฟะฐั€ะฐะผะตั‚ั€ะฐ: - -```Python -say_hi() # ะžะน, ะฝั–, ั†ะต ะฒะธะบะปะธะบะฐั” ะฟะพะผะธะปะบัƒ! ๐Ÿ˜ฑ -``` - -ะŸะฐั€ะฐะผะตั‚ั€ `name` **ะฒัะต ั‰ะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ** (ะฝะต *optional*), ั‚ะพะผัƒ ั‰ะพ ะฒั–ะฝ ะฝะต ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. ะ’ะพะดะฝะพั‡ะฐั `name` ะฟั€ะธะนะผะฐั” `None` ัะบ ะทะฝะฐั‡ะตะฝะฝั: - -```Python -say_hi(name=None) # ะฆะต ะฟั€ะฐั†ัŽั”, None ั” ะฒะฐะปั–ะดะฝะธะผ ๐ŸŽ‰ -``` - -ะ”ะพะฑั€ะฐ ะฝะพะฒะธะฝะฐ: ั‰ะพะนะฝะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะฝะฐ Python 3.10, ะฒะฐะผ ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ะฟั€ะพ ั†ะต ั…ะฒะธะปัŽะฒะฐั‚ะธัั, ะฐะดะถะต ะฒะธ ะทะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `|` ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะพะฑโ€™ั”ะดะฝะฐะฝัŒ ั‚ะธะฟั–ะฒ: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -ะ† ั‚ะพะดั– ะฒะฐะผ ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ั…ะฒะธะปัŽะฒะฐั‚ะธัั ะฟั€ะพ ะฝะฐะทะฒะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ `Optional` ั– `Union`. ๐Ÿ˜Ž - -#### Generic ั‚ะธะฟะธ { #generic-types } - -ะฆั– ั‚ะธะฟะธ, ัะบั– ะฟั€ะธะนะผะฐัŽั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ะธะฟัƒ ัƒ ะบะฒะฐะดั€ะฐั‚ะฝะธั… ะดัƒะถะบะฐั…, ะฝะฐะทะธะฒะฐัŽั‚ัŒัั **Generic types** or **Generics**, ะฝะฐะฟั€ะธะบะปะฐะด: - -//// tab | Python 3.10+ - -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ะฒะฑัƒะดะพะฒะฐะฝั– ั‚ะธะฟะธ ัะบ generic (ะท ะบะฒะฐะดั€ะฐั‚ะฝะธะผะธ ะดัƒะถะบะฐะผะธ ั‚ะฐ ั‚ะธะฟะฐะผะธ ะฒัะตั€ะตะดะธะฝั–): - -* `list` -* `tuple` -* `set` -* `dict` - -ะ† ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะฒ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั… Python, ะท ะผะพะดัƒะปั `typing`: - -* `Union` -* `Optional` -* ...ั‚ะฐ ั–ะฝัˆั–. - -ะฃ Python 3.10 ัะบ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัŽ generic `Union` ั‚ะฐ `Optional` ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒ ัะผัƒะณัƒ (`|`) ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะพะฑโ€™ั”ะดะฝะฐะฝัŒ ั‚ะธะฟั–ะฒ โ€” ั†ะต ะทะฝะฐั‡ะฝะพ ะบั€ะฐั‰ะต ะน ะฟั€ะพัั‚ั–ัˆะต. - -//// - -//// tab | Python 3.9+ - -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ะฒะฑัƒะดะพะฒะฐะฝั– ั‚ะธะฟะธ ัะบ generic (ะท ะบะฒะฐะดั€ะฐั‚ะฝะธะผะธ ะดัƒะถะบะฐะผะธ ั‚ะฐ ั‚ะธะฟะฐะผะธ ะฒัะตั€ะตะดะธะฝั–): - -* `list` -* `tuple` -* `set` -* `dict` - -ะ† generic ะท ะผะพะดัƒะปั `typing`: - -* `Union` -* `Optional` -* ...ั‚ะฐ ั–ะฝัˆั–. - -//// +ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `str | None` ะทะฐะผั–ัั‚ัŒ ะฟั€ะพัั‚ะพ `str` ะดะพะทะฒะพะปะธั‚ัŒ ั€ะตะดะฐะบั‚ะพั€ัƒ ะดะพะฟะพะผะพะณั‚ะธ ะฒะฐะผ ะฒะธัะฒะธั‚ะธ ะฟะพะผะธะปะบะธ, ะบะพะปะธ ะฒะธ ะผะพะณะปะธ ะฑ ะฒะฒะฐะถะฐั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐะฒะถะดะธ ั” `str`, ั…ะพั‡ะฐ ะฝะฐัะฟั€ะฐะฒะดั– ะฒะพะฝะพ ั‚ะฐะบะพะถ ะผะพะถะต ะฑัƒั‚ะธ `None`. ### ะšะปะฐัะธ ัะบ ั‚ะธะฟะธ { #classes-as-types } @@ -363,11 +253,11 @@ say_hi(name=None) # ะฆะต ะฟั€ะฐั†ัŽั”, None ั” ะฒะฐะปั–ะดะฝะธะผ ๐ŸŽ‰ ะกะบะฐะถั–ะผะพ, ัƒ ะฒะฐั ั” ะบะปะฐั `Person` ะท ั–ะผสผัะผ: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะทะผั–ะฝะฝัƒ ั‚ะธะฟัƒ `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} ะ† ะทะฝะพะฒัƒ ะถ ั‚ะฐะบะธ, ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฒััŽ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ: @@ -401,21 +291,15 @@ say_hi(name=None) # ะฆะต ะฟั€ะฐั†ัŽั”, None ั” ะฒะฐะปั–ะดะฝะธะผ ๐ŸŽ‰ **FastAPI** ะฟะพะฒะฝั–ัั‚ัŽ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Pydantic. -ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฝะฐะฑะฐะณะฐั‚ะพ ะฑั–ะปัŒัˆะต ั†ัŒะพะณะพ ะฒััŒะพะณะพ ะฝะฐ ะฟั€ะฐะบั‚ะธั†ั– ะฒ [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}. - -/// tip | ะŸะพั€ะฐะดะฐ - -Pydantic ะผะฐั” ัะฟะตั†ั–ะฐะปัŒะฝัƒ ะฟะพะฒะตะดั–ะฝะบัƒ, ะบะพะปะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Optional` ะฐะฑะพ `Union[Something, None]` ะฑะตะท ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ; ะดะตั‚ะฐะปัŒะฝั–ัˆะต ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Pydantic ะฟั€ะพ Required Optional fields. - -/// +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฝะฐะฑะฐะณะฐั‚ะพ ะฑั–ะปัŒัˆะต ั†ัŒะพะณะพ ะฒััŒะพะณะพ ะฝะฐ ะฟั€ะฐะบั‚ะธั†ั– ะฒ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ](tutorial/index.md){.internal-link target=_blank}. ## ะŸั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ะท ะฐะฝะพั‚ะฐั†ั–ัะผะธ ะผะตั‚ะฐะดะฐะฝะธั… { #type-hints-with-metadata-annotations } -ะฃ Python ั‚ะฐะบะพะถ ั” ะผะพะถะปะธะฒั–ัั‚ัŒ ะดะพะดะฐะฒะฐั‚ะธ **ะดะพะดะฐั‚ะบะพะฒั– ะผะตั‚ะฐะดะฐะฝั–** ะดะพ ั†ะธั… ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `Annotated`. +ะฃ Python ั‚ะฐะบะพะถ ั” ะผะพะถะปะธะฒั–ัั‚ัŒ ะดะพะดะฐะฒะฐั‚ะธ **ะดะพะดะฐั‚ะบะพะฒั– ะผะตั‚ะฐะดะฐะฝั–** ะดะพ ั†ะธั… ะฟั–ะดะบะฐะทะพะบ ั‚ะธะฟั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `Annotated`. -ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะท Python 3.9, `Annotated` ั” ั‡ะฐัั‚ะธะฝะพัŽ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพั— ะฑั–ะฑะปั–ะพั‚ะตะบะธ, ั‚ะพะถ ะฒะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ะท `typing`. +ะ’ะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ `Annotated` ะท `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} ะกะฐะผ Python ะฝั–ั‡ะพะณะพ ะฝะต ั€ะพะฑะธั‚ัŒ ั–ะท ั†ะธะผ `Annotated`. ะ ะดะปั ั€ะตะดะฐะบั‚ะพั€ั–ะฒ ั‚ะฐ ั–ะฝัˆะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั‚ะธะฟ ัƒัะต ั‰ะต ั” `str`. @@ -435,7 +319,7 @@ Pydantic ะผะฐั” ัะฟะตั†ั–ะฐะปัŒะฝัƒ ะฟะพะฒะตะดั–ะฝะบัƒ, ะบะพะปะธ ะฒะธ ะฒะธะบะพ /// -## ะะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟั–ะฒ ัƒ **FastAPI** { #type-hints-in-fastapi } +## ะŸั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ัƒ **FastAPI** { #type-hints-in-fastapi } **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั†ั– ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ะดะปั ะฒะธะบะพะฝะฐะฝะฝั ะบั–ะปัŒะบะพั… ั€ะตั‡ะตะน. @@ -453,12 +337,12 @@ Pydantic ะผะฐั” ัะฟะตั†ั–ะฐะปัŒะฝัƒ ะฟะพะฒะตะดั–ะฝะบัƒ, ะบะพะปะธ ะฒะธ ะฒะธะบะพ * **ะ”ะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั** API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ OpenAPI: * ัะบะธะน ะฟะพั‚ั–ะผ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะบะพั€ะธัั‚ัƒะฒะฐะปัŒะฝะธั†ัŒะบะธั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ. -ะ’ัะต ั†ะต ะผะพะถะต ะทะดะฐั‚ะธัั ะฐะฑัั‚ั€ะฐะบั‚ะฝะธะผ. ะะต ั…ะฒะธะปัŽะนั‚ะตัั. ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฒัะต ั†ะต ะฒ ะดั–ั— ะฒ [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}. +ะ’ัะต ั†ะต ะผะพะถะต ะทะดะฐั‚ะธัั ะฐะฑัั‚ั€ะฐะบั‚ะฝะธะผ. ะะต ั…ะฒะธะปัŽะนั‚ะตัั. ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฒัะต ั†ะต ะฒ ะดั–ั— ะฒ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ](tutorial/index.md){.internal-link target=_blank}. ะ’ะฐะถะปะธะฒะพ ั‚ะต, ั‰ะพ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… ั‚ะธะฟั–ะฒ Python ะฒ ะพะดะฝะพะผัƒ ะผั–ัั†ั– (ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะดะพะดะฐะฒะฐั‚ะธ ะฑั–ะปัŒัˆะต ะบะปะฐัั–ะฒ, ะดะตะบะพั€ะฐั‚ะพั€ั–ะฒ ั‚ะพั‰ะพ), **FastAPI** ะทั€ะพะฑะธั‚ัŒ ะฑะฐะณะฐั‚ะพ ั€ะพะฑะพั‚ะธ ะทะฐ ะฒะฐั. /// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั -ะฏะบั‰ะพ ะฒะธ ะฒะถะต ะฟั€ะพะนัˆะปะธ ะฒะตััŒ ั‚ัƒั‚ะพั€ั–ะฐะป ั– ะฟะพะฒะตั€ะฝัƒะปะธัั, ั‰ะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั‚ะธะฟะธ, ะพััŒ ั…ะพั€ะพัˆะธะน ั€ะตััƒั€ั: ยซัˆะฟะฐั€ะณะฐะปะบะฐยป ะฒั–ะด `mypy`. +ะฏะบั‰ะพ ะฒะธ ะฒะถะต ะฟั€ะพะนัˆะปะธ ะฒะตััŒ ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ ั– ะฟะพะฒะตั€ะฝัƒะปะธัั, ั‰ะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั‚ะธะฟะธ, ะพััŒ ั…ะพั€ะพัˆะธะน ั€ะตััƒั€ั: ยซัˆะฟะฐั€ะณะฐะปะบะฐยป ะฒั–ะด `mypy`. /// diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md index 6d7804195e..71266a8b10 100644 --- a/docs/uk/docs/tutorial/background-tasks.md +++ b/docs/uk/docs/tutorial/background-tasks.md @@ -1,6 +1,6 @@ # ะคะพะฝะพะฒั– ะทะฐะดะฐั‡ั– { #background-tasks } -ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั–, ัะบั– ะฑัƒะดัƒั‚ัŒ ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั *ะฟั–ัะปั* ะฟะพะฒะตั€ะฝะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั–, ัะบั– ะฑัƒะดัƒั‚ัŒ ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั ะฟั–ัะปั ะฟะพะฒะตั€ะฝะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. ะฆะต ะบะพั€ะธัะฝะพ ะดะปั ะพะฟะตั€ะฐั†ั–ะน, ัะบั– ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝะฐั‚ะธ ะฟั–ัะปั ะพะฑั€ะพะฑะบะธ ะทะฐะฟะธั‚ัƒ, ะฐะปะต ะบะปั–ั”ะฝั‚ัƒ ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ั‡ะตะบะฐั‚ะธ ะทะฐะฒะตั€ัˆะตะฝะฝั ั†ั–ั”ั— ะพะฟะตั€ะฐั†ั–ั— ะฟะตั€ะตะด ะพั‚ั€ะธะผะฐะฝะฝัะผ ะฒั–ะดะฟะพะฒั–ะดั–. @@ -13,9 +13,9 @@ ## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `BackgroundTasks` { #using-backgroundtasks } -ะกะฟะพั‡ะฐั‚ะบัƒ ั–ะผะฟะพั€ั‚ัƒะนั‚ะต `BackgroundTasks` ั– ะพะณะพะปะพัั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะท ะฐะฝะพั‚ะฐั†ั–ั”ัŽ ั‚ะธะฟัƒ `BackgroundTasks`: +ะกะฟะพั‡ะฐั‚ะบัƒ ั–ะผะฟะพั€ั‚ัƒะนั‚ะต `BackgroundTasks` ั– ะพะณะพะปะพัั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ะฒะฐัˆั–ะน ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะท ะฐะฝะพั‚ะฐั†ั–ั”ัŽ ั‚ะธะฟัƒ `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** ัั‚ะฒะพั€ะธั‚ัŒ ะดะปั ะฒะฐั ะพะฑโ€™ั”ะบั‚ ั‚ะธะฟัƒ `BackgroundTasks` ั– ะฟะตั€ะตะดะฐัั‚ัŒ ะนะพะณะพ ัะบ ั†ะตะน ะฟะฐั€ะฐะผะตั‚ั€. @@ -31,13 +31,13 @@ ะ† ะพัะบั–ะปัŒะบะธ ะพะฟะตั€ะฐั†ั–ั ะทะฐะฟะธััƒ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `async` ั‚ะฐ `await`, ะผะธ ะฒะธะทะฝะฐั‡ะฐั”ะผะพ ั„ัƒะฝะบั†ั–ัŽ ัะบ ะทะฒะธั‡ะฐะนะฝัƒ `def`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## ะ”ะพะดะฐะฒะฐะฝะฝั ั„ะพะฝะพะฒะพั— ะทะฐะดะฐั‡ั– { #add-the-background-task } -ะฃัะตั€ะตะดะธะฝั– ะฒะฐัˆะพั— *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฟะตั€ะตะดะฐะนั‚ะต ั„ัƒะฝะบั†ั–ัŽ ะทะฐะดะฐั‡ั– ะฒ ะพะฑ'ั”ะบั‚ *background tasks*, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะตั‚ะพะด `.add_task()`: +ะฃัะตั€ะตะดะธะฝั– ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฟะตั€ะตะดะฐะนั‚ะต ั„ัƒะฝะบั†ั–ัŽ ะทะฐะดะฐั‡ั– ะฒ ะพะฑ'ั”ะบั‚ background tasks, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะตั‚ะพะด `.add_task()`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` ะฟั€ะธะนะผะฐั” ะฐั€ะณัƒะผะตะฝั‚ะธ: @@ -47,17 +47,17 @@ ## ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน { #dependency-injection } -ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `BackgroundTasks` ั‚ะฐะบะพะถ ะฟั€ะฐั†ัŽั” ะท ัะธัั‚ะตะผะพัŽ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `BackgroundTasks` ะฝะฐ ั€ั–ะทะฝะธั… ั€ั–ะฒะฝัั…: ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ัƒ ะทะฐะปะตะถะฝะพัั‚ั– (dependable), ัƒ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั– ั‚ะพั‰ะพ. +ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `BackgroundTasks` ั‚ะฐะบะพะถ ะฟั€ะฐั†ัŽั” ะท ัะธัั‚ะตะผะพัŽ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `BackgroundTasks` ะฝะฐ ั€ั–ะทะฝะธั… ั€ั–ะฒะฝัั…: ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ัƒ ะทะฐะปะตะถะฝะพัั‚ั– (ะทะฐะปะตะถะฝะธะน), ัƒ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั– ั‚ะพั‰ะพ. -**FastAPI** ะทะฝะฐั”, ัะบ ะดั–ัั‚ะธ ะฒ ะบะพะถะฝะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั– ัะบ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะดะธะฝ ั– ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚, ั‰ะพะฑ ัƒัั– ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั– ะฑัƒะปะธ ะพะฑโ€™ั”ะดะฝะฐะฝั– ั‚ะฐ ะฒะธะบะพะฝัƒะฒะฐะปะธัั ัƒ ั„ะพะฝะพะฒะพะผัƒ ั€ะตะถะธะผั– ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ะพัะฝะพะฒะฝะพะณะพ ะทะฐะฟะธั‚ัƒ: +**FastAPI** ะทะฝะฐั”, ัะบ ะดั–ัั‚ะธ ะฒ ะบะพะถะฝะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั– ัะบ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะดะธะฝ ั– ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚, ั‰ะพะฑ ัƒัั– ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั– ะฑัƒะปะธ ะพะฑโ€™ั”ะดะฝะฐะฝั– ั‚ะฐ ะฒะธะบะพะฝัƒะฒะฐะปะธัั ัƒ ั„ะพะฝะพะฒะพะผัƒ ั€ะตะถะธะผั– ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ะพัะฝะพะฒะฝะพะณะพ ะทะฐะฟะธั‚ัƒ: {* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} -ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฑัƒะดัƒั‚ัŒ ะทะฐะฟะธัะฐะฝั– ัƒ ั„ะฐะนะป `log.txt` *ะฟั–ัะปั* ั‚ะพะณะพ, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะฐ. +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฑัƒะดัƒั‚ัŒ ะทะฐะฟะธัะฐะฝั– ัƒ ั„ะฐะนะป `log.txt` ะฟั–ัะปั ั‚ะพะณะพ, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะฐ. -ะฏะบั‰ะพ ัƒ ะทะฐะฟะธั‚ั– ะฑัƒะฒ ะฟะตั€ะตะดะฐะฝะธะน query, ะฒั–ะฝ ะฑัƒะดะต ะทะฐะฟะธัะฐะฝะธะน ัƒ ะปะพะณ ัƒ ั„ะพะฝะพะฒั–ะน ะทะฐะดะฐั‡ั–. +ะฏะบั‰ะพ ัƒ ะทะฐะฟะธั‚ั– ะฑัƒะฒ ะฟะตั€ะตะดะฐะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ, ะฒั–ะฝ ะฑัƒะดะต ะทะฐะฟะธัะฐะฝะธะน ัƒ ะปะพะณ ัƒ ั„ะพะฝะพะฒั–ะน ะทะฐะดะฐั‡ั–. -ะ ะฟะพั‚ั–ะผ ั–ะฝัˆะฐ ั„ะพะฝะพะฒะฐ ะทะฐะดะฐั‡ะฐ, ะทะณะตะฝะตั€ะพะฒะฐะฝะฐ ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะทะฐะฟะธัˆะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ path ะฟะฐั€ะฐะผะตั‚ั€ะฐ `email`. +ะ ะฟะพั‚ั–ะผ ั–ะฝัˆะฐ ั„ะพะฝะพะฒะฐ ะทะฐะดะฐั‡ะฐ, ะทะณะตะฝะตั€ะพะฒะฐะฝะฐ ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะทะฐะฟะธัˆะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัˆะปัั…ัƒ `email`. ## ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #technical-details } @@ -65,7 +65,7 @@ ะ’ั–ะฝ ั–ะผะฟะพั€ั‚ัƒั”ั‚ัŒัั/ะฒะบะปัŽั‡ะฐั”ั‚ัŒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ FastAPI, ั‰ะพะฑ ะฒะธ ะผะพะณะปะธ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ะท `fastapi` ั– ะฒะธะฟะฐะดะบะพะฒะพ ะฝะต ั–ะผะฟะพั€ั‚ัƒะฒะฐะปะธ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธะน `BackgroundTask` (ะฑะตะท `s` ะฒ ะบั–ะฝั†ั–) ะท `starlette.background`. -ะฏะบั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะปะธัˆะต `BackgroundTasks` (ะฐ ะฝะต `BackgroundTask`), ั‚ะพ ะนะพะณะพ ะผะพะถะฝะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ัะบ ะฟะฐั€ะฐะผะตั‚ั€ ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั– **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะฒัะต ั–ะฝัˆะต, ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะฟั€ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะพะฑ'ั”ะบั‚ะฐ `Request`. +ะฏะบั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะปะธัˆะต `BackgroundTasks` (ะฐ ะฝะต `BackgroundTask`), ั‚ะพ ะนะพะณะพ ะผะพะถะฝะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ัะบ ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ั– **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะฒัะต ั–ะฝัˆะต, ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะฟั€ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะพะฑ'ั”ะบั‚ะฐ `Request`. ะขะฐะบะพะถ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `BackgroundTask` ะพะบั€ะตะผะพ ะฒ FastAPI, ะฐะปะต ะดะปั ั†ัŒะพะณะพ ะฒะฐะผ ะดะพะฒะตะดะตั‚ัŒัั ัั‚ะฒะพั€ะธั‚ะธ ะพะฑ'ั”ะบั‚ ัƒ ะบะพะดั– ั‚ะฐ ะฟะพะฒะตั€ะฝัƒั‚ะธ Starlette `Response`, ะฒะบะปัŽั‡ะฐัŽั‡ะธ ะนะพะณะพ. @@ -81,4 +81,4 @@ ## ะŸั–ะดััƒะผะพะบ { #recap } -ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `BackgroundTasks` ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ัƒ *ั„ัƒะฝะบั†ั–ัั… ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ั‚ะฐ ะทะฐะปะตะถะฝะพัั‚ัั…, ั‰ะพะฑ ะดะพะดะฐะฒะฐั‚ะธ ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั–. +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `BackgroundTasks` ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ัƒ ั„ัƒะฝะบั†ั–ัั… ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั‚ะฐ ะทะฐะปะตะถะฝะพัั‚ัั…, ั‰ะพะฑ ะดะพะดะฐะฒะฐั‚ะธ ั„ะพะฝะพะฒั– ะทะฐะดะฐั‡ั–. diff --git a/docs/uk/docs/tutorial/body-multiple-params.md b/docs/uk/docs/tutorial/body-multiple-params.md index f541beea76..a0db2b1865 100644 --- a/docs/uk/docs/tutorial/body-multiple-params.md +++ b/docs/uk/docs/tutorial/body-multiple-params.md @@ -18,7 +18,7 @@ ## ะ”ะตะบั–ะปัŒะบะฐ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั‚ั–ะปะฐ { #multiple-body-parameters } -ะฃ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะพั‡ั–ะบัƒะฒะฐะปะธ ะฑ JSON-ั‚ั–ะปะพ ะท ะฐั‚ั€ะธะฑัƒั‚ะฐะผะธ `Item`, ะฝะฐะฟั€ะธะบะปะฐะด: +ะฃ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ะฟั€ะธะบะปะฐะดi *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะพั‡ั–ะบัƒะฒะฐะปะธ ะฑ JSON-ั‚ั–ะปะพ ะท ะฐั‚ั€ะธะฑัƒั‚ะฐะผะธ `Item`, ะฝะฐะฟั€ะธะบะปะฐะด: ```JSON { @@ -106,13 +106,6 @@ q: str | None = None ``` -ะะฑะพ ะฒ Python 3.9: - -```Python -q: Union[str, None] = None -``` - - ะะฐะฟั€ะธะบะปะฐะด: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md index 6d0669358a..a56ae484df 100644 --- a/docs/uk/docs/tutorial/body-nested-models.md +++ b/docs/uk/docs/tutorial/body-nested-models.md @@ -164,7 +164,7 @@ images: list[Image] ะฝะฐะฟั€ะธะบะปะฐะด: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## ะŸั–ะดั‚ั€ะธะผะบะฐ ะฒ ั€ะตะดะฐะบั‚ะพั€ั– ะฒััŽะดะธ { #editor-support-everywhere } @@ -194,7 +194,7 @@ images: list[Image] ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะธะนะผะฐั‚ะธ ะฑัƒะดัŒ-ัะบะธะน `dict`, ัะบั‰ะพ ะนะพะณะพ ะบะปัŽั‡ั– โ€” ั†ะต `int`, ะฐ ะทะฝะฐั‡ะตะฝะฝั โ€” `float`: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ะŸะพั€ะฐะดะฐ @@ -216,6 +216,6 @@ images: list[Image] * ะŸั–ะดั‚ั€ะธะผะบะฐ ะฒ ั€ะตะดะฐะบั‚ะพั€ั– (ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ!) * ะšะพะฝะฒะตั€ั‚ะฐั†ั–ั ะดะฐะฝะธั… (ะฟะฐั€ัะธะฝะณ/ัะตั€ะธะฐะปั–ะทะฐั†ั–ั) -* ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั… +* ะ’ะฐะปั–ะดะฐั†ั–ั ะดะฐะฝะธั… * ะ”ะพะบัƒะผะตะฝั‚ะฐั†ั–ั ัั…ะตะผ * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ัั‚ะฒะพั€ะตะฝะฝั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— diff --git a/docs/uk/docs/tutorial/body.md b/docs/uk/docs/tutorial/body.md index ca1f308ab5..615f0274cc 100644 --- a/docs/uk/docs/tutorial/body.md +++ b/docs/uk/docs/tutorial/body.md @@ -8,7 +8,7 @@ ะฉะพะฑ ะพะณะพะปะพัะธั‚ะธ ั‚ั–ะปะพ **ะทะฐะฟะธั‚ัƒ**, ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Pydantic ะผะพะดะตะปั– ะท ัƒัั–ั”ัŽ ั—ั… ะฟะพั‚ัƒะถะฝั–ัั‚ัŽ ั‚ะฐ ะฟะตั€ะตะฒะฐะณะฐะผะธ. -/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั +/// info ะฉะพะฑ ะฝะฐะดั–ัะปะฐั‚ะธ ะดะฐะฝั–, ะฒะธ ะฟะพะฒะธะฝะฝั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะดะธะฝ ั–ะท: `POST` (ะฑั–ะปัŒัˆ ะฟะพัˆะธั€ะตะฝะธะน), `PUT`, `DELETE` ะฐะฑะพ `PATCH`. @@ -73,8 +73,8 @@ * ะฏะบั‰ะพ ะดะฐะฝั– ะฝะตะดั–ะนัะฝั–, ะฒั–ะฝ ะฟะพะฒะตั€ะฝะต ะณะฐั€ะฝัƒ ั‚ะฐ ั‡ั–ั‚ะบัƒ ะฟะพะผะธะปะบัƒ, ะฒะบะฐะทัƒัŽั‡ะธ, ะดะต ัะฐะผะต ั– ัะบั– ะดะฐะฝั– ะฑัƒะปะธ ะฝะตะฟั€ะฐะฒะธะปัŒะฝะธะผะธ. * ะะฐะดะฐะฒะฐั‚ะธ ะพั‚ั€ะธะผะฐะฝั– ะดะฐะฝั– ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– `item`. * ะžัะบั–ะปัŒะบะธ ะฒะธ ะพะณะพะปะพัะธะปะธ ะนะพะณะพ ัƒ ั„ัƒะฝะบั†ั–ั— ัะบ ั‚ะธะฟ `Item`, ะฒะธ ั‚ะฐะบะพะถ ะผะฐั‚ะธะผะตั‚ะต ะฒััŽ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ (ะฐะฒั‚ะพะทะฐะฟะพะฒะฝะตะฝะฝั, ั‚ะพั‰ะพ) ะดะปั ะฒัั–ั… ะฐั‚ั€ะธะฑัƒั‚ั–ะฒ ั‚ะฐ ั—ั… ั‚ะธะฟั–ะฒ. -* ะ“ะตะฝะตั€ัƒะฒะฐั‚ะธ JSON Schema ะฒะธะทะฝะฐั‡ะตะฝะฝั ะดะปั ะฒะฐัˆะพั— ะผะพะดะตะปั–, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะดะต ะทะฐะฒะณะพะดะฝะพ, ัะบั‰ะพ ั†ะต ะผะฐั” ัะตะฝั ะดะปั ะฒะฐัˆะพะณะพ ะฟั€ะพะตะบั‚ัƒ. -* ะฆั– ัั…ะตะผะธ ะฑัƒะดัƒั‚ัŒ ั‡ะฐัั‚ะธะฝะพัŽ ะทะณะตะฝะตั€ะพะฒะฐะฝะพั— ัั…ะตะผะธ OpenAPI ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ UIs. +* ะ“ะตะฝะตั€ัƒะฒะฐั‚ะธ ะฒะธะทะฝะฐั‡ะตะฝะฝั ะกั…ะตะผะธ JSON ะดะปั ะฒะฐัˆะพั— ะผะพะดะตะปั–, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะดะต ะทะฐะฒะณะพะดะฝะพ, ัะบั‰ะพ ั†ะต ะผะฐั” ัะตะฝั ะดะปั ะฒะฐัˆะพะณะพ ะฟั€ะพะตะบั‚ัƒ. +* ะฆั– ัั…ะตะผะธ ะฑัƒะดัƒั‚ัŒ ั‡ะฐัั‚ะธะฝะพัŽ ะทะณะตะฝะตั€ะพะฒะฐะฝะพั— ัั…ะตะผะธ OpenAPI ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ UIs. ## ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั { #automatic-docs } @@ -108,7 +108,7 @@ -/// tip | ะŸะพั€ะฐะดะฐ +/// tip ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต PyCharm ัะบ ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ Pydantic PyCharm Plugin. @@ -151,11 +151,11 @@ * ะฏะบั‰ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะผะฐั” **ัะธะฝะณัƒะปัั€ะฝะธะน ั‚ะธะฟ** (ะฝะฐะฟั€ะธะบะปะฐะด, `int`, `float`, `str`, `bool` ั‚ะพั‰ะพ), ะฒั–ะฝ ะฑัƒะดะต ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒะฒะฐั‚ะธัั ัะบ ะฟะฐั€ะฐะผะตั‚ั€ **ะทะฐะฟะธั‚ัƒ**. * ะฏะบั‰ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะพะณะพะปะพัˆัƒั”ั‚ัŒัั ัะบ ั‚ะธะฟ **Pydantic ะผะพะดะตะปั–**, ะฒั–ะฝ ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒั”ั‚ัŒัั ัะบ **ั‚ั–ะปะพ** **ะทะฐะฟะธั‚ัƒ**. -/// note | ะŸั€ะธะผั–ั‚ะบะฐ +/// note FastAPI ะฑัƒะดะต ะทะฝะฐั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั `q` ะฝะต ั” ะพะฑะพะฒ'ัะทะบะพะฒะธะผ ั‡ะตั€ะตะท ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `= None`. -`str | None` (Python 3.10+) ะฐะฑะพ `Union` ัƒ `Union[str, None]` (Python 3.9+) FastAPI ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ โ€” ะฒั–ะฝ ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฒะพะฝะพ ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ั‚ะพะผัƒ ั‰ะพ ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `= None`. +`str | None` FastAPI ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ - ะฒั–ะฝ ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฒะพะฝะพ ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ั‚ะพะผัƒ ั‰ะพ ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `= None`. ะะปะต ะดะพะดะฐะฒะฐะฝะฝั ะฐะฝะพั‚ะฐั†ั–ะน ั‚ะธะฟั–ะฒ ะดะพะทะฒะพะปะธั‚ัŒ ะฒะฐัˆะพะผัƒ ั€ะตะดะฐะบั‚ะพั€ัƒ ะฝะฐะดะฐั‚ะธ ะฒะฐะผ ะบั€ะฐั‰ัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ ั‚ะฐ ะฒะธัะฒะปัั‚ะธ ะฟะพะผะธะปะบะธ. @@ -163,4 +163,4 @@ FastAPI ะฑัƒะดะต ะทะฝะฐั‚ะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั `q` ะฝะต ั” ะพะฑะพะฒ'ัะทะบะพ ## ะ‘ะตะท Pydantic { #without-pydantic } -ะฏะบั‰ะพ ะฒะธ ะฝะต ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปั– Pydantic, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ **Body**. ะŸะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. +ะฏะบั‰ะพ ะฒะธ ะฝะต ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปั– Pydantic, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ **Body**. ะŸะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั [ะขั–ะปะพ - ะšั–ะปัŒะบะฐ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ: ะžะบั€ะตะผั– ะทะฝะฐั‡ะตะฝะฝั ะฒ ั‚ั–ะปั–](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/uk/docs/tutorial/cookie-param-models.md b/docs/uk/docs/tutorial/cookie-param-models.md index 3c6407716e..dab57c5365 100644 --- a/docs/uk/docs/tutorial/cookie-param-models.md +++ b/docs/uk/docs/tutorial/cookie-param-models.md @@ -1,8 +1,8 @@ # ะœะพะดะตะปั– ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ Cookie { #cookie-parameter-models } -ะฏะบั‰ะพ ัƒ ะ’ะฐั ั” ะณั€ัƒะฟะฐ **cookies**, ัะบั– ะฟะพะฒ'ัะทะฐะฝั– ะผั–ะถ ัะพะฑะพัŽ, ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic-ะผะพะดะตะปัŒ**, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ ั—ั…. ๐Ÿช +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” ะณั€ัƒะฟะฐ **cookies**, ัะบั– ะฟะพะฒ'ัะทะฐะฝั– ะผั–ะถ ัะพะฑะพัŽ, ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic-ะผะพะดะตะปัŒ**, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ ั—ั…. ๐Ÿช -ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะ’ะฐะผ ะฟะพะฒั‚ะพั€ะฝะพ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ** ัƒ **ั€ั–ะทะฝะธั… ะผั–ัั†ัั…**, ะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ัŽ ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ะฒัั–ั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. ๐Ÿ˜Ž +ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะฒะฐะผ ะฟะพะฒั‚ะพั€ะฝะพ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ** ัƒ **ั€ั–ะทะฝะธั… ะผั–ัั†ัั…**, ะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ัŽ ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ะฒัั–ั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. ๐Ÿ˜Ž /// note | ะŸั€ะธะผั–ั‚ะบะฐ @@ -18,11 +18,11 @@ ## Cookie ะท Pydantic-ะผะพะดะตะปะปัŽ { #cookies-with-a-pydantic-model } -ะžะณะพะปะพัั–ั‚ัŒ **cookie**-ะฟะฐั€ะฐะผะตั‚ั€ะธ, ัะบั– ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–, ัƒ **Pydantic-ะผะพะดะตะปั–**, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ัะบ `Cookie`: +ะžะณะพะปะพัั–ั‚ัŒ **cookie**-ะฟะฐั€ะฐะผะตั‚ั€ะธ, ัะบั– ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–, ัƒ **Pydantic-ะผะพะดะตะปั–**, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ัะบ `Cookie`: {* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} -**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **cookies**, ะพั‚ั€ะธะผะฐะฝะธั… ัƒ ะทะฐะฟะธั‚ั–, ั– ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ะ’ะฐะผ Pydantic-ะผะพะดะตะปัŒ, ัะบัƒ ะ’ะธ ะฒะธะทะฝะฐั‡ะธะปะธ. +**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **cookies**, ะพั‚ั€ะธะผะฐะฝะธั… ัƒ ะทะฐะฟะธั‚ั–, ั– ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ะฒะฐะผ Pydantic-ะผะพะดะตะปัŒ, ัะบัƒ ะฒะธ ะฒะธะทะฝะฐั‡ะธะปะธ. ## ะŸะตั€ะตะฒั–ั€ะบะฐ ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #check-the-docs } @@ -36,17 +36,17 @@ ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ **ะฑั€ะฐัƒะทะตั€ะธ ะพะฑั€ะพะฑะปััŽั‚ัŒ cookies** ะพัะพะฑะปะธะฒะธะผ ั‡ะธะฝะพะผ ั– ยซะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธยป, ะฒะพะฝะธ **ะฝะต** ะดะพะทะฒะพะปััŽั‚ัŒ **JavaScript** ะปะตะณะบะพ ะท ะฝะธะผะธ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ. -ะฏะบั‰ะพ ะ’ะธ ะทะฐะนะดะตั‚ะต ะดะพ **ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API** ะทะฐ ะฐะดั€ะตัะพัŽ `/docs`, ะ’ะธ ะทะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ **ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ** ะดะปั cookies ัƒ ะ’ะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ*. +ะฏะบั‰ะพ ะฒะธ ะทะฐะนะดะตั‚ะต ะดะพ **ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API** ะทะฐ ะฐะดั€ะตัะพัŽ `/docs`, ะฒะธ ะทะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ **ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ** ะดะปั cookies ัƒ ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ*. -ะะปะต ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะ’ะธ ะทะฐะฟะพะฒะฝะธั‚ะต ะดะฐะฝั– ะน ะฝะฐั‚ะธัะฝะตั‚ะต "Execute", ะพัะบั–ะปัŒะบะธ ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะฐั†ัŽั” ะท **JavaScript**, cookies ะฝะต ะฑัƒะดัƒั‚ัŒ ะฒั–ะดะฟั€ะฐะฒะปะตะฝั–, ั– ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต **ะฟะพะผะธะปะบัƒ**, ะฝั–ะฑะธ ะ’ะธ ะฝะต ะฒะฒะตะปะธ ะถะพะดะฝะธั… ะทะฝะฐั‡ะตะฝัŒ. +ะะปะต ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะทะฐะฟะพะฒะฝะธั‚ะต ะดะฐะฝั– ะน ะฝะฐั‚ะธัะฝะตั‚ะต "Execute", ะพัะบั–ะปัŒะบะธ ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะฐั†ัŽั” ะท **JavaScript**, cookies ะฝะต ะฑัƒะดัƒั‚ัŒ ะฒั–ะดะฟั€ะฐะฒะปะตะฝั–, ั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต **ะฟะพะผะธะปะบัƒ**, ะฝั–ะฑะธ ะฒะธ ะฝะต ะฒะฒะตะปะธ ะถะพะดะฝะธั… ะทะฝะฐั‡ะตะฝัŒ. /// ## ะ—ะฐะฑะพั€ะพะฝะฐ ะดะพะดะฐั‚ะบะพะฒะธั… cookie { #forbid-extra-cookies } -ะฃ ะดะตัะบะธั… ัะฟะตั†ั–ะฐะปัŒะฝะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** cookies, ัะบั– ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ. +ะฃ ะดะตัะบะธั… ัะฟะตั†ั–ะฐะปัŒะฝะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** cookies, ัะบั– ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ. -ะ’ะฐัˆะฐ API ั‚ะตะฟะตั€ ะผะฐั” ะผะพะถะปะธะฒั–ัั‚ัŒ ะบะพะฝั‚ั€ะพะปัŽะฒะฐั‚ะธ ะฒะปะฐัะฝัƒ ะทะณะพะดัƒ ะฝะฐ cookie. ๐Ÿคช๐Ÿช +ะ’ะฐัˆ API ั‚ะตะฟะตั€ ะผะฐั” ะผะพะถะปะธะฒั–ัั‚ัŒ ะบะพะฝั‚ั€ะพะปัŽะฒะฐั‚ะธ ะฒะปะฐัะฝัƒ ะทะณะพะดัƒ ะฝะฐ cookies. ๐Ÿคช๐Ÿช ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะผะพะดะตะปั– Pydantic, ั‰ะพะฑ `forbid` ะฑัƒะดัŒ-ัะบั– `extra` ะฟะพะปั: @@ -54,9 +54,9 @@ ะฏะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ ัะบั–ััŒ **ะดะพะดะฐั‚ะบะพะฒั– cookies**, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะท **ะฟะพะผะธะปะบะพัŽ**. -ะ‘ั–ะดะฝั– ะฑะฐะฝะตั€ะธ cookie, ัะบั– ั‚ะฐะบ ัั‚ะฐั€ะฐะฝะฝะพ ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะพั‚ั€ะธะผะฐั‚ะธ ะ’ะฐัˆัƒ ะทะณะพะดัƒ, ั‰ะพะฑ API ั—ั— ะฒั–ะดั…ะธะปะธะปะฐ. ๐Ÿช +ะ‘ั–ะดะฝั– ะฑะฐะฝะตั€ะธ cookie, ัะบั– ั‚ะฐะบ ัั‚ะฐั€ะฐะฝะฝะพ ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะพั‚ั€ะธะผะฐั‚ะธ ะฒะฐัˆัƒ ะทะณะพะดัƒ, ั‰ะพะฑ API ั—ั— ะฒั–ะดั…ะธะปะธะปะฐ. ๐Ÿช -ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ cookie `santa_tracker` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `good-list-please`, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฟะพะผะธะปะบะพัŽ, ัะบะฐ ะฟะพะฒั–ะดะพะผะธั‚ัŒ, ั‰ะพ `santa_tracker` cookie ะฝะต ะดะพะทะฒะพะปะตะฝะพ: +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ cookie `santa_tracker` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `good-list-please`, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฟะพะผะธะปะบะพัŽ, ัะบะฐ ะฟะพะฒั–ะดะพะผะธั‚ัŒ, ั‰ะพ `santa_tracker` cookie ะฝะต ะดะพะทะฒะพะปะตะฝะพ: ```json { @@ -73,4 +73,4 @@ ## ะŸั–ะดััƒะผะพะบ { #summary } -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **Pydantic-ะผะพะดะตะปั–** ะดะปั ะพะณะพะปะพัˆะตะฝะฝั **cookies** ัƒ **FastAPI**. ๐Ÿ˜Ž +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **Pydantic-ะผะพะดะตะปั–** ะดะปั ะพะณะพะปะพัˆะตะฝะฝั **cookies** ัƒ **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/uk/docs/tutorial/cookie-params.md b/docs/uk/docs/tutorial/cookie-params.md index 8a5b44e8aa..3a2e6fa24e 100644 --- a/docs/uk/docs/tutorial/cookie-params.md +++ b/docs/uk/docs/tutorial/cookie-params.md @@ -1,6 +1,6 @@ -# ะŸะฐั€ะฐะผะตั‚ั€ะธ Cookie { #cookie-parameters } +# ะŸะฐั€ะฐะผะตั‚ั€ะธ ะบัƒะบั– { #cookie-parameters } -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ Cookie ั‚ะฐะบะธะผ ะถะต ั‡ะธะฝะพะผ, ัะบ ะฒะธะทะฝะฐั‡ะฐัŽั‚ัŒัั ะฟะฐั€ะฐะผะตั‚ั€ะธ `Query` ั– `Path`. +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะบัƒะบั– ั‚ะฐะบะธะผ ะถะต ั‡ะธะฝะพะผ, ัะบ ะฒะธะทะฝะฐั‡ะฐัŽั‚ัŒัั ะฟะฐั€ะฐะผะตั‚ั€ะธ `Query` ั– `Path`. ## ะ†ะผะฟะพั€ั‚ `Cookie` { #import-cookie } @@ -10,7 +10,7 @@ ## ะ’ะธะทะฝะฐั‡ะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ `Cookie` { #declare-cookie-parameters } -ะŸะพั‚ั–ะผ ะฒะธะทะฝะฐั‡ั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ะธ cookie, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะฐะบัƒ ะถ ะบะพะฝัั‚ั€ัƒะบั†ั–ัŽ ัะบ ะดะปั `Path` ั– `Query`. +ะŸะพั‚ั–ะผ ะฒะธะทะฝะฐั‡ั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ะธ ะบัƒะบั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะฐะบัƒ ะถ ะบะพะฝัั‚ั€ัƒะบั†ั–ัŽ ัะบ ะดะปั `Path` ั– `Query`. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฐ ั‚ะฐะบะพะถ ัƒัั– ะดะพะดะฐั‚ะบะพะฒั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฒะฐะปั–ะดะฐั†ั–ั— ั‡ะธ ะฐะฝะพั‚ะฐั†ั–ั—: @@ -26,20 +26,20 @@ /// info -ะ”ะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั cookies ะฒะธ ะผะฐั”ั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Cookie`, ั‚ะพะผัƒ ั‰ะพ ะฒ ั–ะฝัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฑัƒะดัƒั‚ัŒ ั–ะฝั‚ะตั€ะฟั€ะธั‚ะพะฒะฐะฝั–, ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ. +ะ”ะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะบัƒะบั– ะฒะธ ะผะฐั”ั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Cookie`, ั‚ะพะผัƒ ั‰ะพ ะฒ ั–ะฝัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฑัƒะดัƒั‚ัŒ ั–ะฝั‚ะตั€ะฟั€ะตั‚ะพะฒะฐะฝั– ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ. /// /// info -ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ **ะฑั€ะฐัƒะทะตั€ะธ ะพะฑั€ะพะฑะปััŽั‚ัŒ cookies** ัะฟะตั†ั–ะฐะปัŒะฝะธะผ ั‡ะธะฝะพะผ ั– ะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธ, ะฒะพะฝะธ **ะฝะต** ะดะพะทะฒะพะปััŽั‚ัŒ **JavaScript** ะปะตะณะบะพ ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฝะธะผะธ. +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ **ะฑั€ะฐัƒะทะตั€ะธ ะพะฑั€ะพะฑะปััŽั‚ัŒ ะบัƒะบั–** ัะฟะตั†ั–ะฐะปัŒะฝะธะผ ั‡ะธะฝะพะผ ั– ะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธ, ะฒะพะฝะธ **ะฝะต** ะดะพะทะฒะพะปััŽั‚ัŒ **JavaScript** ะปะตะณะบะพ ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฝะธะผะธ. -ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะดะพ **ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API** ะทะฐ ะฐะดั€ะตัะพัŽ `/docs`, ะฒะธ ะทะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ **ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ** ะดะปั cookies ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะดะพ **ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API** ะทะฐ ะฐะดั€ะตัะพัŽ `/docs`, ะฒะธ ะทะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ **ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ** ะดะปั ะบัƒะบั– ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. -ะะปะต ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ **ะทะฐะฟะพะฒะฝะธั‚ะต ะดะฐะฝั–** ั– ะฝะฐั‚ะธัะฝะตั‚ะต "Execute", ะพัะบั–ะปัŒะบะธ ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะฐั†ัŽั” ะท **JavaScript**, cookies ะฝะต ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะพ, ั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฟั€ะพ **ะฟะพะผะธะปะบัƒ**, ะฝั–ะฑะธ ะฒะธ ะฝะต ะฒะฒะตะปะธ ะถะพะดะฝะธั… ะทะฝะฐั‡ะตะฝัŒ. +ะะปะต ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ **ะทะฐะฟะพะฒะฝะธั‚ะต ะดะฐะฝั–** ั– ะฝะฐั‚ะธัะฝะตั‚ะต "Execute", ะพัะบั–ะปัŒะบะธ ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะฐั†ัŽั” ะท **JavaScript**, ะบัƒะบั– ะฝะต ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะพ, ั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฟั€ะพ **ะฟะพะผะธะปะบัƒ**, ะฝั–ะฑะธ ะฒะธ ะฝะต ะฒะฒะตะปะธ ะถะพะดะฝะธั… ะทะฝะฐั‡ะตะฝัŒ. /// ## ะŸั–ะดััƒะผะบะธ { #recap } -ะ’ะธะทะฝะฐั‡ะฐะนั‚ะต cookies ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `Cookie`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ะถะต ัะฟั–ะปัŒะฝะธะน ัˆะฐะฑะปะพะฝ, ั‰ะพ ั– `Query` ั‚ะฐ `Path`. +ะ’ะธะทะฝะฐั‡ะฐะนั‚ะต ะบัƒะบั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `Cookie`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ะถะต ัะฟั–ะปัŒะฝะธะน ัˆะฐะฑะปะพะฝ, ั‰ะพ ั– `Query` ั‚ะฐ `Path`. diff --git a/docs/uk/docs/tutorial/cors.md b/docs/uk/docs/tutorial/cors.md index f3ed8a7d94..5c959cef18 100644 --- a/docs/uk/docs/tutorial/cors.md +++ b/docs/uk/docs/tutorial/cors.md @@ -1,6 +1,6 @@ # CORS (ะžะฑะผั–ะฝ ั€ะตััƒั€ัะฐะผะธ ะผั–ะถ ั€ั–ะทะฝะธะผะธ ะดะถะตั€ะตะปะฐะผะธ) { #cors-cross-origin-resource-sharing } -CORS ะฐะฑะพ "Cross-Origin Resource Sharing" ั” ัะธั‚ัƒะฐั†ั–ั, ะบะพะปะธ ั„ั€ะพะฝั‚ะตะฝะด, ั‰ะพ ะฟั€ะฐั†ัŽั” ะฒ ะฑั€ะฐัƒะทะตั€ั–, ะผั–ัั‚ะธั‚ัŒ JavaScript-ะบะพะด, ัะบะธะน ะฒะทะฐั”ะผะพะดั–ั” ะท ะฑะตะบะตะฝะดะพะผ, ั€ะพะทั‚ะฐัˆะพะฒะฐะฝะธะผ ะฒ ั–ะฝัˆะพะผัƒ "ะดะถะตั€ะตะปั–" (origin). +CORS ะฐะฑะพ ยซCross-Origin Resource Sharingยป ั” ัะธั‚ัƒะฐั†ั–ั, ะบะพะปะธ ั„ั€ะพะฝั‚ะตะฝะด, ั‰ะพ ะฟั€ะฐั†ัŽั” ะฒ ะฑั€ะฐัƒะทะตั€ั–, ะผั–ัั‚ะธั‚ัŒ JavaScript-ะบะพะด, ัะบะธะน ะฒะทะฐั”ะผะพะดั–ั” ะท ะฑะตะบะตะฝะดะพะผ, ั€ะพะทั‚ะฐัˆะพะฒะฐะฝะธะผ ะฒ ั–ะฝัˆะพะผัƒ ยซะดะถะตั€ะตะปั–ยป (origin). ## ะ”ะถะตั€ะตะปะพ (Origin) { #origin } @@ -13,50 +13,49 @@ * `https://localhost` * `http://localhost:8080` -ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะธ ะฒัั– ะผั–ัั‚ัั‚ัŒ `localhost`, ะฒะพะฝะธ ะผะฐัŽั‚ัŒ ั€ั–ะทะฝั– ะฟั€ะพั‚ะพะบะพะปะธ ะฐะฑะพ ะฟะพั€ั‚ะธ, ั‰ะพ ั€ะพะฑะธั‚ัŒ ั—ั… ะพะบั€ะตะผะธะผะธ "ะดะถะตั€ะตะปะฐะผะธ". +ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะธ ะฒัั– ะผั–ัั‚ัั‚ัŒ `localhost`, ะฒะพะฝะธ ะผะฐัŽั‚ัŒ ั€ั–ะทะฝั– ะฟั€ะพั‚ะพะบะพะปะธ ะฐะฑะพ ะฟะพั€ั‚ะธ, ั‰ะพ ั€ะพะฑะธั‚ัŒ ั—ั… ะพะบั€ะตะผะธะผะธ ยซะดะถะตั€ะตะปะฐะผะธยป. ## ะšั€ะพะบะธ { #steps } -ะŸั€ะธะฟัƒัั‚ะธะผะพ, ั‰ะพ ะ’ะฐัˆ ั„ั€ะพะฝั‚ะตะฝะด ะฟั€ะฐั†ัŽั” ะฒ ะฑั€ะฐัƒะทะตั€ั– ะฝะฐ `http://localhost:8080`, ะฐ ะนะพะณะพ JavaScript ะฝะฐะผะฐะณะฐั”ั‚ัŒัั ะฒั–ะดะฟั€ะฐะฒะธั‚ะธ ะทะฐะฟะธั‚ ะดะพ ะฑะตะบะตะฝะดัƒ, ัะบะธะน ะฟั€ะฐั†ัŽั” ะฝะฐ `http://localhost` (ะžัะบั–ะปัŒะบะธ ะผะธ ะฝะต ะฒะบะฐะทัƒั”ะผะพ ะฟะพั€ั‚, ะฑั€ะฐัƒะทะตั€ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟั€ะธะฟัƒัะบะฐั” ะฟะพั€ั‚ `80`). +ะŸั€ะธะฟัƒัั‚ะธะผะพ, ั‰ะพ ะฒะฐัˆ ั„ั€ะพะฝั‚ะตะฝะด ะฟั€ะฐั†ัŽั” ะฒ ะฑั€ะฐัƒะทะตั€ั– ะฝะฐ `http://localhost:8080`, ะฐ ะนะพะณะพ JavaScript ะฝะฐะผะฐะณะฐั”ั‚ัŒัั ะฒั–ะดะฟั€ะฐะฒะธั‚ะธ ะทะฐะฟะธั‚ ะดะพ ะฑะตะบะตะฝะดัƒ, ัะบะธะน ะฟั€ะฐั†ัŽั” ะฝะฐ `http://localhost` (ะžัะบั–ะปัŒะบะธ ะผะธ ะฝะต ะฒะบะฐะทัƒั”ะผะพ ะฟะพั€ั‚, ะฑั€ะฐัƒะทะตั€ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟั€ะธะฟัƒัะบะฐั” ะฟะพั€ั‚ `80`). ะŸะพั‚ั–ะผ ะฑั€ะฐัƒะทะตั€ ะฝะฐะดั–ัˆะปะต HTTP-ะทะฐะฟะธั‚ `OPTIONS` ะดะพ ะฑะตะบะตะฝะดัƒ ะฝะฐ ะฟะพั€ั‚ัƒ `:80`, ั– ัะบั‰ะพ ะฑะตะบะตะฝะด ะฝะฐะดั–ัˆะปะต ะฒั–ะดะฟะพะฒั–ะดะฝั– ะทะฐะณะพะปะพะฒะบะธ, ั‰ะพ ะดะพะทะฒะพะปััŽั‚ัŒ ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ะท ั†ัŒะพะณะพ ั–ะฝัˆะพะณะพ ะดะถะตั€ะตะปะฐ (`http://localhost:8080`), ั‚ะพะดั– ะฑั€ะฐัƒะทะตั€ ะฝะฐ ะฟะพั€ั‚ัƒ `:8080` ะดะพะทะฒะพะปะธั‚ัŒ JavaScript ัƒ ั„ั€ะพะฝั‚ะตะฝะดั– ะฝะฐะดั–ัะปะฐั‚ะธ ัะฒั–ะน ะทะฐะฟะธั‚ ะดะพ ะฑะตะบะตะฝะดัƒ ะฝะฐ ะฟะพั€ั‚ัƒ `:80`. -ะฉะพะฑ ะดะพััะณั‚ะธ ั†ัŒะพะณะพ, ะฑะตะบะตะฝะด ะฝะฐ ะฟะพั€ั‚ัƒ `:80` ะฟะพะฒะธะฝะตะฝ ะผะฐั‚ะธ ัะฟะธัะพะบ "ะดะพะทะฒะพะปะตะฝะธั… ะดะถะตั€ะตะป". +ะฉะพะฑ ะดะพััะณั‚ะธ ั†ัŒะพะณะพ, ะฑะตะบะตะฝะด ะฝะฐ ะฟะพั€ั‚ัƒ `:80` ะฟะพะฒะธะฝะตะฝ ะผะฐั‚ะธ ัะฟะธัะพะบ ยซะดะพะทะฒะพะปะตะฝะธั… ะดะถะตั€ะตะปยป. ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ัะฟะธัะพะบ ะผะฐั” ะผั–ัั‚ะธั‚ะธ `http://localhost:8080`, ั‰ะพะฑ ั„ั€ะพะฝั‚ะตะฝะด ะฝะฐ ะฟะพั€ั‚ัƒ `:8080` ะฟั€ะฐั†ัŽะฒะฐะฒ ะบะพั€ะตะบั‚ะฝะพ. -## ะกะธะผะฒะพะปัŒะฝะต ะฟั–ะดัั‚ะฐะฒะปัะฝะฝั { #wildcards } +## ะ”ะธะบั– ะบะฐั€ั‚ะธ { #wildcards } -ะœะพะถะฝะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ัะฟะธัะพะบ ัะบ `"*"` ("ัะธะผะฒะพะปัŒะฝะต ะฟั–ะดัั‚ะฐะฒะปัะฝะฝั"), ั‰ะพ ะพะทะฝะฐั‡ะฐั” ะดะพะทะฒั–ะป ะดะปั ะฒัั–ั… ะดะถะตั€ะตะป. +ะœะพะถะฝะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ัะฟะธัะพะบ ัะบ `"*"` (ะดะธะบะฐ ะบะฐั€ั‚ะฐ), ั‰ะพ ะพะทะฝะฐั‡ะฐั” ะดะพะทะฒั–ะป ะดะปั ะฒัั–ั… ะดะถะตั€ะตะป. -ะžะดะฝะฐะบ ั†ะต ะดะพะทะฒะพะปะธั‚ัŒ ะปะธัˆะต ะฟะตะฒะฝั– ั‚ะธะฟะธ ะบะพะผัƒะฝั–ะบะฐั†ั–ั—, ะฒะธะบะปัŽั‡ะฐัŽั‡ะธ ะฒัะต, ั‰ะพ ะฟะพะฒ'ัะทะฐะฝะต ะท ะพะฑะปั–ะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ: Cookies, ะทะฐะณะพะปะพะฒะบะธ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั—, ั‚ะฐะบั– ัะบ ั‚ั–, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะท Bearer Tokens, ั‚ะพั‰ะพ. +ะžะดะฝะฐะบ ั†ะต ะดะพะทะฒะพะปะธั‚ัŒ ะปะธัˆะต ะฟะตะฒะฝั– ั‚ะธะฟะธ ะบะพะผัƒะฝั–ะบะฐั†ั–ั—, ะฒะธะบะปัŽั‡ะฐัŽั‡ะธ ะฒัะต, ั‰ะพ ะฟะพะฒ'ัะทะฐะฝะต ะท ะพะฑะปั–ะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ: Cookies, ะทะฐะณะพะปะพะฒะบะธ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั—, ัะบ-ะพั‚ ั‚ั–, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะท ั‚ะพะบะตะฝะฐะผะธ ะฝะพัั–ั, ั‚ะพั‰ะพ. ะขะพะผัƒ ะดะปั ะบะพั€ะตะบั‚ะฝะพั— ั€ะพะฑะพั‚ะธ ะบั€ะฐั‰ะต ัะฒะฝะพ ะฒะบะฐะทัƒะฒะฐั‚ะธ ะดะพะทะฒะพะปะตะฝั– ะดะถะตั€ะตะปะฐ. ## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `CORSMiddleware` { #use-corsmiddleware } -ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั†ะต ัƒ ะ’ะฐัˆะพะผัƒ ะดะพะดะฐั‚ะบัƒ **FastAPI** ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `CORSMiddleware`. +ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั†ะต ัƒ ะฒะฐัˆะพะผัƒ ะดะพะดะฐั‚ะบัƒ **FastAPI** ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `CORSMiddleware`. * ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `CORSMiddleware`. * ะกั‚ะฒะพั€ั–ั‚ัŒ ัะฟะธัะพะบ ะดะพะทะฒะพะปะตะฝะธั… ะดะถะตั€ะตะป (ัƒ ะฒะธะณะปัะดั– ั€ัะดะบั–ะฒ). -* ะ”ะพะดะฐะนั‚ะต ะนะพะณะพ ัะบ "middleware" ัƒ ะ’ะฐัˆ ะดะพะดะฐั‚ะพะบ **FastAPI**. +* ะ”ะพะดะฐะนั‚ะต ะนะพะณะพ ัะบ ยซะฟั€ะพะผั–ะถะฝะต ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝัยป ัƒ ะฒะฐัˆ ะดะพะดะฐั‚ะพะบ **FastAPI**. - -ะขะฐะบะพะถ ะผะพะถะฝะฐ ะฒะบะฐะทะฐั‚ะธ, ั‡ะธ ะดะพะทะฒะพะปัั” ะ’ะฐัˆ ะฑะตะบะตะฝะด: +ะขะฐะบะพะถ ะผะพะถะฝะฐ ะฒะบะฐะทะฐั‚ะธ, ั‡ะธ ะดะพะทะฒะพะปัั” ะฒะฐัˆ ะฑะตะบะตะฝะด: * ะžะฑะปั–ะบะพะฒั– ะดะฐะฝั– (ะทะฐะณะพะปะพะฒะบะธ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั—, Cookies, ั‚ะพั‰ะพ). * ะšะพะฝะบั€ะตั‚ะฝั– HTTP-ะผะตั‚ะพะดะธ (`POST`, `PUT`) ะฐะฑะพ ะฒัั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `"*"` * ะšะพะฝะบั€ะตั‚ะฝั– HTTP-ะทะฐะณะพะปะพะฒะบะธ ะฐะฑะพ ะฒัั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} -ะŸะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ัƒ ั€ะตะฐะปั–ะทะฐั†ั–ั— `CORSMiddleware` ั” ะดะพัะธั‚ัŒ ะพะฑะผะตะถะตะฝะธะผะธ, ั‚ะพะผัƒ ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ัะฒะฝะพ ัƒะฒั–ะผะบะฝัƒั‚ะธ ะบะพะฝะบั€ะตั‚ะฝั– ะดะถะตั€ะตะปะฐ, ะผะตั‚ะพะดะธ ะฐะฑะพ ะทะฐะณะพะปะพะฒะบะธ, ั‰ะพะฑ ะฑั€ะฐัƒะทะตั€ะฐะผ ะฑัƒะปะพ ะดะพะทะฒะพะปะตะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ัƒ ะผั–ะถะดะพะผะตะฝะฝะพะผัƒ ะบะพะฝั‚ะตะบัั‚ั–. +ะŸะฐั€ะฐะผะตั‚ั€ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ัƒ ั€ะตะฐะปั–ะทะฐั†ั–ั— `CORSMiddleware` ั” ะดะพัะธั‚ัŒ ะพะฑะผะตะถะตะฝะธะผะธ, ั‚ะพะผัƒ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ัะฒะฝะพ ัƒะฒั–ะผะบะฝัƒั‚ะธ ะบะพะฝะบั€ะตั‚ะฝั– ะดะถะตั€ะตะปะฐ, ะผะตั‚ะพะดะธ ะฐะฑะพ ะทะฐะณะพะปะพะฒะบะธ, ั‰ะพะฑ ะฑั€ะฐัƒะทะตั€ะฐะผ ะฑัƒะปะพ ะดะพะทะฒะพะปะตะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ัƒ ะผั–ะถะดะพะผะตะฝะฝะพะผัƒ ะบะพะฝั‚ะตะบัั‚ั–. ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ั‚ะฐะบั– ะฐั€ะณัƒะผะตะฝั‚ะธ: -* `allow_origins` - ะกะฟะธัะพะบ ะดะถะตั€ะตะป, ัะบะธะผ ะดะพะทะฒะพะปะตะฝะพ ะทะดั–ะนัะฝัŽะฒะฐั‚ะธ ะผั–ะถะดะพะผะตะฝะฝั– ะทะฐะฟะธั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด `['https://example.org', 'https://www.example.org']`. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `['*']`, ั‰ะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฑัƒะดัŒ-ัะบะต ะดะถะตั€ะตะปะพ. +* `allow_origins` - ะกะฟะธัะพะบ ะดะถะตั€ะตะป, ัะบะธะผ ะดะพะทะฒะพะปะตะฝะพ ะทะดั–ะนัะฝัŽะฒะฐั‚ะธ ะผั–ะถะดะพะผะตะฝะฝั– ะทะฐะฟะธั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด `['https://example.org', 'https://www.example.org']`. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `['*']`, ั‰ะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฑัƒะดัŒ-ัะบะต ะดะถะตั€ะตะปะพ. * `allow_origin_regex` - ะ ัะดะพะบ ั€ะตะณัƒะปัั€ะฝะพะณะพ ะฒะธั€ะฐะทัƒ ะดะปั ะฒั–ะดะฟะพะฒั–ะดะฝะพัั‚ั– ะดะถะตั€ะตะปะฐะผ, ัะบะธะผ ะดะพะทะฒะพะปะตะฝะพ ะทะดั–ะนัะฝัŽะฒะฐั‚ะธ ะผั–ะถะดะพะผะตะฝะฝั– ะทะฐะฟะธั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด, `'https://.*\.example\.org'`. * `allow_methods` - ะกะฟะธัะพะบ HTTP-ะผะตั‚ะพะดั–ะฒ, ะดะพะทะฒะพะปะตะฝะธั… ะดะปั ะผั–ะถะดะพะผะตะฝะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `['GET']`. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `['*']`, ั‰ะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฒัั– ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะผะตั‚ะพะดะธ. * `allow_headers` - ะกะฟะธัะพะบ HTTP-ะทะฐะณะพะปะพะฒะบั–ะฒ ะทะฐะฟะธั‚ัƒ, ัะบั– ะฟั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ะดะปั ะผั–ะถะดะพะผะตะฝะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `[]`. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `['*']`, ั‰ะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฒัั– ะทะฐะณะพะปะพะฒะบะธ. ะ—ะฐะณะพะปะพะฒะบะธ `Accept`, `Accept-Language`, `Content-Language` ั– `Content-Type` ะทะฐะฒะถะดะธ ะดะพะทะฒะพะปะตะฝั– ะดะปั ะฟั€ะพัั‚ะธั… CORS-ะทะฐะฟะธั‚ั–ะฒ. @@ -67,7 +66,7 @@ * `expose_headers` - ะ’ะบะฐะทัƒั”, ัะบั– ะทะฐะณะพะปะพะฒะบะธ ะฒั–ะดะฟะพะฒั–ะดั– ะฟะพะฒะธะฝะฝั– ะฑัƒั‚ะธ ะดะพัั‚ัƒะฟะฝั– ะดะปั ะฑั€ะฐัƒะทะตั€ะฐ. ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `[]`. * `max_age` - ะ’ัั‚ะฐะฝะพะฒะปัŽั” ะผะฐะบัะธะผะฐะปัŒะฝะธะน ั‡ะฐั (ัƒ ัะตะบัƒะฝะดะฐั…) ะดะปั ะบะตัˆัƒะฒะฐะฝะฝั CORS-ะฒั–ะดะฟะพะฒั–ะดะตะน ัƒ ะฑั€ะฐัƒะทะตั€ะฐั…. ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `600`. -ะฆะตะน middleware ะพะฑั€ะพะฑะปัั” ะดะฒะฐ ั‚ะธะฟะธ HTTP-ะทะฐะฟะธั‚ั–ะฒ... +ะฆะต ะฟั€ะพะผั–ะถะฝะต ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั ะพะฑั€ะพะฑะปัั” ะดะฒะฐ ั‚ะธะฟะธ HTTP-ะทะฐะฟะธั‚ั–ะฒ... ### ะŸะพะฟะตั€ะตะดะฝั– CORS-ะทะฐะฟะธั‚ะธ { #cors-preflight-requests } @@ -81,7 +80,7 @@ ## ะ”ะพะดะฐั‚ะบะพะฒะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั { #more-info } -ะ‘ั–ะปัŒัˆะต ะฟั€ะพ CORS ะผะพะถะฝะฐ ะดั–ะทะฝะฐั‚ะธัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Mozilla ะฟั€ะพ CORS. +ะ‘ั–ะปัŒัˆะต ะฟั€ะพ CORS ะผะพะถะฝะฐ ะดั–ะทะฝะฐั‚ะธัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Mozilla ะฟั€ะพ CORS. /// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– diff --git a/docs/uk/docs/tutorial/debugging.md b/docs/uk/docs/tutorial/debugging.md index 0db418dcc9..679018cc2f 100644 --- a/docs/uk/docs/tutorial/debugging.md +++ b/docs/uk/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ ะฃ ะฒะฐัˆะพะผัƒ FastAPI-ะดะพะดะฐั‚ะบัƒ ั–ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ะทะฐะฟัƒัั‚ั–ั‚ัŒ `uvicorn` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### ะŸั€ะพ `__name__ == "__main__"` { #about-name-main } diff --git a/docs/uk/docs/tutorial/first-steps.md b/docs/uk/docs/tutorial/first-steps.md index 5f3750010c..f03a120a09 100644 --- a/docs/uk/docs/tutorial/first-steps.md +++ b/docs/uk/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ ะะฐะนะฟั€ะพัั‚ั–ัˆะธะน ั„ะฐะนะป FastAPI ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} ะกะบะพะฟั–ัŽะนั‚ะต ั†ะต ะดะพ ั„ะฐะนะปัƒ `main.py`. @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### ะšั€ะพะบ 1: ั–ะผะฟะพั€ั‚ัƒั”ะผะพ `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` โ€” ั†ะต ะบะปะฐั ัƒ Python, ัะบะธะน ะฝะฐะดะฐั” ะฒััŽ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ ะดะปั ะฒะฐัˆะพะณะพ API. @@ -197,7 +197,7 @@ Deploying to FastAPI Cloud... ### ะšั€ะพะบ 2: ัั‚ะฒะพั€ัŽั”ะผะพ ยซะตะบะทะตะผะฟะปัั€ยป `FastAPI` { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} ะขัƒั‚ ะทะผั–ะฝะฝะฐ `app` ะฑัƒะดะต ยซะตะบะทะตะผะฟะปัั€ะพะผยป ะบะปะฐััƒ `FastAPI`. @@ -221,7 +221,7 @@ https://example.com/items/foo /items/foo ``` -/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั +/// info ยซะจะปัั…ยป ั‚ะฐะบะพะถ ะทะฐะทะฒะธั‡ะฐะน ะฝะฐะทะธะฒะฐัŽั‚ัŒ ยซะตะฝะดะฟะพั–ะฝั‚ะพะผยป ะฐะฑะพ ยซะผะฐั€ัˆั€ัƒั‚ะพะผยป. @@ -266,12 +266,12 @@ https://example.com/items/foo #### ะ’ะธะทะฝะฐั‡ั‚ะต *ะดะตะบะพั€ะฐั‚ะพั€ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} ะ”ะตะบะพั€ะฐั‚ะพั€ `@app.get("/")` ะฟะพะฒั–ะดะพะผะปัั” **FastAPI**, ั‰ะพ ั„ัƒะฝะบั†ั–ั ะพะดั€ะฐะทัƒ ะฝะธะถั‡ะต ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ ะพะฑั€ะพะฑะบัƒ ะทะฐะฟะธั‚ั–ะฒ, ัะบั– ะฝะฐะดั…ะพะดัั‚ัŒ ะดะพ: * ัˆะปัั…ัƒ `/` -* ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ get ะพะฟะตั€ะฐั†ั–ัŽ +* ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ get ะพะฟะตั€ะฐั†ั–ั /// info | `@decorator` ะ†ะฝั„ะพั€ะผะฐั†ั–ั @@ -300,7 +300,7 @@ https://example.com/items/foo * `@app.patch()` * `@app.trace()` -/// tip | ะŸะพั€ะฐะดะฐ +/// tip ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะพะถะฝัƒ ะพะฟะตั€ะฐั†ั–ัŽ (HTTP-ะผะตั‚ะพะด) ัะบ ะทะฐะฑะฐะถะฐั”ั‚ะต. @@ -320,7 +320,7 @@ https://example.com/items/foo * **ะพะฟะตั€ะฐั†ั–ั**: ั†ะต `get`. * **ั„ัƒะฝะบั†ั–ั**: ั†ะต ั„ัƒะฝะบั†ั–ั ะฝะธะถั‡ะต ยซะดะตะบะพั€ะฐั‚ะพั€ะฐยป (ะฝะธะถั‡ะต `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} ะฆะต ั„ัƒะฝะบั†ั–ั Python. @@ -332,9 +332,9 @@ https://example.com/items/foo ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ั—ั— ัะบ ะทะฒะธั‡ะฐะนะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะทะฐะผั–ัั‚ัŒ `async def`: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} -/// note | ะŸั€ะธะผั–ั‚ะบะฐ +/// note ะฏะบั‰ะพ ะฒะธ ะฝะต ะทะฝะฐั”ั‚ะต ั€ั–ะทะฝะธั†ัŽ, ะฟะพะดะธะฒั–ั‚ัŒัั [ะัะธะฝั…ั€ะพะฝะฝั–ัั‚ัŒ: *ยซะŸะพัะฟั–ัˆะฐั”ั‚ะต?ยป*](../async.md#in-a-hurry){.internal-link target=_blank}. @@ -342,7 +342,7 @@ https://example.com/items/foo ### ะšั€ะพะบ 5: ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะฒะผั–ัั‚ { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ `dict`, `list`, ะฐ ั‚ะฐะบะพะถ ะพะบั€ะตะผั– ะทะฝะฐั‡ะตะฝะฝั `str`, `int` ั‚ะพั‰ะพ. diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md index 53b8b12f61..28a83127ff 100644 --- a/docs/uk/docs/tutorial/handling-errors.md +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -25,7 +25,7 @@ ### ะ†ะผะฟะพั€ั‚ `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### ะ—ะณะตะฝะตั€ัƒะนั‚ะต `HTTPException` ัƒ ัะฒะพั”ะผัƒ ะบะพะดั– { #raise-an-httpexception-in-your-code } @@ -39,7 +39,7 @@ ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั–, ะบะพะปะธ ะบะปั–ั”ะฝั‚ ะทะฐะฟะธั‚ัƒั” ะตะปะตะผะตะฝั‚ ะทะฐ ID, ัะบะพะณะพ ะฝะต ั–ัะฝัƒั”, ะทะณะตะฝะตั€ัƒะนั‚ะต ะฒะธะบะปัŽั‡ะตะฝะฝั ะทั– ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ `404`: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### ะžั‚ั€ะธะผะฐะฝะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ { #the-resulting-response } @@ -77,7 +77,7 @@ ะะปะต ัะบั‰ะพ ะฒะฐะผ ะทะฝะฐะดะพะฑะธั‚ัŒัั ั†ะต ะดะปั ัะบะปะฐะดะฝะพะณะพ ัั†ะตะฝะฐั€ั–ัŽ, ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะณะพะปะพะฒะบะธ: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## ะ’ัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฒะปะฐัะฝะธั… ะพะฑั€ะพะฑะฝะธะบั–ะฒ ะฒะธะบะปัŽั‡ะตะฝัŒ { #install-custom-exception-handlers } @@ -89,7 +89,7 @@ ะ’ะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะฒะปะฐัะฝะธะน ะพะฑั€ะพะฑะฝะธะบ ะฒะธะบะปัŽั‡ะตะฝัŒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `@app.exception_handler()`: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} ะขัƒั‚, ัะบั‰ะพ ะฒะธ ะทะฒะตั€ะฝะตั‚ะตัั ะดะพ `/unicorns/yolo`, *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะทะณะตะฝะตั€ัƒั” (`raise`) `UnicornException`. @@ -127,7 +127,7 @@ ะžะฑั€ะพะฑะฝะธะบ ะฒะธะบะปัŽั‡ะตะฝัŒ ะพั‚ั€ะธะผะฐั” `Request` ั– ัะฐะผะต ะฒะธะบะปัŽั‡ะตะฝะฝั. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} ะขะตะฟะตั€, ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะทะฐ ะฟะพัะธะปะฐะฝะฝัะผ `/items/foo`, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒ JSON-ะฟะพะผะธะปะบัƒ: @@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ัƒ ะฒะธะณะปัะดั– ะฟั€ะพัั‚ะพะณะพ ั‚ะตะบัั‚ัƒ ะทะฐะผั–ัั‚ัŒ JSON ะดะปั ั†ะธั… ะฟะพะผะธะปะพะบ: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– @@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ะต ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ ัะฒะพะณะพ ะดะพะดะฐั‚ะบะฐ, ั‰ะพะฑ ะปะพะณัƒะฒะฐั‚ะธ ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ ั‚ะฐ ะฝะฐะปะฐะณะพะดะถัƒะฒะฐั‚ะธ ะนะพะณะพ, ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะตะฒั– ั‚ะพั‰ะพ. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} ะขะตะฟะตั€ ัะฟั€ะพะฑัƒะนั‚ะต ะฝะฐะดั–ัะปะฐั‚ะธ ะฝะตะบะพั€ะตะบั‚ะฝะธะน ะตะปะตะผะตะฝั‚, ะฝะฐะฟั€ะธะบะปะฐะด: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะธะบะปัŽั‡ะตะฝะฝั ั€ะฐะทะพะผ ั–ะท ั‚ะฐะบะธะผะธ ะถ ะพะฑั€ะพะฑะฝะธะบะฐะผะธ ะฒะธะบะปัŽั‡ะตะฝัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ัะบ ัƒ **FastAPI**, ะฒะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั‚ะฐ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฑั€ะพะฑะฝะธะบะธ ะฒะธะบะปัŽั‡ะตะฝัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ั–ะท `fastapi.exception_handlers`: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะฒะธ ะฟั€ะพัั‚ะพ ะดั€ัƒะบัƒั”ั‚ะต ะฟะพะผะธะปะบัƒ ะท ะดัƒะถะต ะฒะธั€ะฐะทะฝะธะผ ะฟะพะฒั–ะดะพะผะปะตะฝะฝัะผ, ะฐะปะต ะฒะธ ะทั€ะพะทัƒะผั–ะปะธ ะพัะฝะพะฒะฝัƒ ั–ะดะตัŽ. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะธะบะปัŽั‡ะตะฝะฝั, ะฐ ะฟะพั‚ั–ะผ ะฟั€ะพัั‚ะพ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฑั€ะพะฑะฝะธะบะธ ะฒะธะบะปัŽั‡ะตะฝัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. diff --git a/docs/uk/docs/tutorial/header-param-models.md b/docs/uk/docs/tutorial/header-param-models.md index c080c19f06..dd734eaee7 100644 --- a/docs/uk/docs/tutorial/header-param-models.md +++ b/docs/uk/docs/tutorial/header-param-models.md @@ -1,8 +1,8 @@ # ะœะพะดะตะปั– ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะณะพะปะพะฒะบั–ะฒ { #header-parameter-models } -ะฏะบั‰ะพ ัƒ ะ’ะฐั ั” ะณั€ัƒะฟะฐ ะฟะพะฒโ€™ัะทะฐะฝะธั… **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะณะพะปะพะฒะบั–ะฒ**, ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic ะผะพะดะตะปัŒ** ะดะปั ั—ั… ะพะณะพะปะพัˆะตะฝะฝั. +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” ะณั€ัƒะฟะฐ ะฟะพะฒโ€™ัะทะฐะฝะธั… **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะณะพะปะพะฒะบั–ะฒ**, ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic ะผะพะดะตะปัŒ** ะดะปั ั—ั… ะพะณะพะปะพัˆะตะฝะฝั. -ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะ’ะฐะผ ะฟะพะฒั‚ะพั€ะฝะพ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ** ะฒ **ั€ั–ะทะฝะธั… ะผั–ัั†ัั…**, ะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ั— ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ะฒัั–ั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. ๐Ÿ˜Ž +ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะฒะฐะผ ะฟะพะฒั‚ะพั€ะฝะพ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ** ะฒ **ั€ั–ะทะฝะธั… ะผั–ัั†ัั…**, ะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะธ ะฒะฐะปั–ะดะฐั†ั–ั— ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ะฒัั–ั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. ๐Ÿ˜Ž /// note | ะŸั€ะธะผั–ั‚ะบะฐ @@ -16,7 +16,7 @@ {* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} -**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **ะทะฐะณะพะปะพะฒะบั–ะฒ** ัƒ ะทะฐะฟะธั‚ั– ั‚ะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ั—ั… ัƒ ัั‚ะฒะพั€ะตะฝัƒ ะ’ะฐะผะธ Pydantic ะผะพะดะตะปัŒ. +**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **ะทะฐะณะพะปะพะฒะบั–ะฒ** ัƒ ะทะฐะฟะธั‚ั– ั‚ะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ั—ั… ัƒ ัั‚ะฒะพั€ะตะฝัƒ ะฒะฐะผะธ Pydantic ะผะพะดะตะปัŒ. ## ะŸะตั€ะตะฒั–ั€ะบะฐ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #check-the-docs } @@ -28,7 +28,7 @@ ## ะ—ะฐะฑะพั€ะพะฝะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะทะฐะณะพะปะพะฒะบะธ { #forbid-extra-headers } -ะฃ ะดะตัะบะธั… ะพัะพะฑะปะธะฒะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** ะทะฐะณะพะปะพะฒะบะธ, ัะบั– ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ. +ะฃ ะดะตัะบะธั… ะพัะพะฑะปะธะฒะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** ะทะฐะณะพะปะพะฒะบะธ, ัะบั– ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ ะผะพะดะตะปั– Pydantic, ั‰ะพะฑ `ะทะฐะฑะพั€ะพะฝะธั‚ะธ` ะฑัƒะดัŒ-ัะบั– `ะดะพะดะฐั‚ะบะพะฒั–` ะฟะพะปั: @@ -55,9 +55,9 @@ ะขะฐะบ ัะฐะผะพ, ัะบ ั– ะทั– ะทะฒะธั‡ะฐะนะฝะธะผะธ ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ะทะฐะณะพะปะพะฒะบั–ะฒ, ะบะพะปะธ ัƒ ะฝะฐะทะฒะฐั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั” ัะธะผะฒะพะปะธ ะฟั–ะดะบั€ะตัะปะตะฝะฝั, ะฒะพะฝะธ **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตั‚ะฒะพั€ัŽัŽั‚ัŒัั ะฝะฐ ะดะตั„ั–ัะธ**. -ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัƒ ะบะพะดั– ัƒ ะ’ะฐั ั” ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะณะพะปะพะฒะบะฐ `save_data`, ะพั‡ั–ะบัƒะฒะฐะฝะธะน HTTP-ะทะฐะณะพะปะพะฒะพะบ ะฑัƒะดะต `save-data`, ั– ะฒั–ะฝ ั‚ะฐะบ ัะฐะผะพ ะฒั–ะดะพะฑั€ะฐะถะฐั‚ะธะผะตั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัƒ ะบะพะดั– ัƒ ะฒะฐั ั” ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะณะพะปะพะฒะบะฐ `save_data`, ะพั‡ั–ะบัƒะฒะฐะฝะธะน HTTP-ะทะฐะณะพะปะพะฒะพะบ ะฑัƒะดะต `save-data`, ั– ะฒั–ะฝ ั‚ะฐะบ ัะฐะผะพ ะฒั–ะดะพะฑั€ะฐะถะฐั‚ะธะผะตั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. -ะฏะบั‰ะพ ะท ัะบะพั—ััŒ ะฟั€ะธั‡ะธะฝะธ ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะผะบะฝัƒั‚ะธ ั†ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั, ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะดะปั Pydantic ะผะพะดะตะปะตะน ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะณะพะปะพะฒะบั–ะฒ. +ะฏะบั‰ะพ ะท ัะบะพั—ััŒ ะฟั€ะธั‡ะธะฝะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะผะบะฝัƒั‚ะธ ั†ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะดะปั Pydantic ะผะพะดะตะปะตะน ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะณะพะปะพะฒะบั–ะฒ. {* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} diff --git a/docs/uk/docs/tutorial/header-params.md b/docs/uk/docs/tutorial/header-params.md index f5a4ea18d1..9e564d27ab 100644 --- a/docs/uk/docs/tutorial/header-params.md +++ b/docs/uk/docs/tutorial/header-params.md @@ -50,7 +50,7 @@ /// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั -ะŸะตั€ะตะด ั‚ะธะผ ัะบ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `convert_underscores` ะฒ `False`, ะฟะฐะผโ€™ัั‚ะฐะนั‚ะต, ั‰ะพ ะดะตัะบั– HTTP-ะฟั€ะพะบัั– ั‚ะฐ ัะตั€ะฒะตั€ะธ ะทะฐะฑะพั€ะพะฝััŽั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั–ะท ะฟั–ะดะบั€ะตัะปะตะฝะฝัะผะธ. +ะŸะตั€ะตะด ั‚ะธะผ ัะบ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `convert_underscores` ะฒ `False`, ะฟะฐะผโ€™ัั‚ะฐะนั‚ะต, ั‰ะพ ะดะตัะบั– HTTP-ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะธ ั‚ะฐ ัะตั€ะฒะตั€ะธ ะทะฐะฑะพั€ะพะฝััŽั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั–ะท ะฟั–ะดะบั€ะตัะปะตะฝะฝัะผะธ. /// diff --git a/docs/uk/docs/tutorial/index.md b/docs/uk/docs/tutorial/index.md index 6848090ecc..ed53ac7728 100644 --- a/docs/uk/docs/tutorial/index.md +++ b/docs/uk/docs/tutorial/index.md @@ -84,12 +84,12 @@ $ pip install "fastapi[standard]" /// -## ะ ะพะทัˆะธั€ะตะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #advanced-user-guide } +## ะŸั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #advanced-user-guide } -ะ†ัะฝัƒั” ั‚ะฐะบะพะถ **ะ ะพะทัˆะธั€ะตะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**, ัะบะธะน ะฒะธ ะทะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฟั–ะทะฝั–ัˆะต ะฟั–ัะปั ั†ัŒะพะณะพ **ะขัƒั‚ะพั€ั–ะฐะป - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**. +ะ†ัะฝัƒั” ั‚ะฐะบะพะถ **ะŸั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**, ัะบะธะน ะฒะธ ะทะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฟั–ะทะฝั–ัˆะต ะฟั–ัะปั ั†ัŒะพะณะพ **ะขัƒั‚ะพั€ั–ะฐะป - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**. -**ะ ะพะทัˆะธั€ะตะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ** ะทะฐัะฝะพะฒะฐะฝะพ ะฝะฐ ั†ัŒะพะผัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั‚ั– ัะฐะผั– ะบะพะฝั†ะตะฟั†ั–ั— ั‚ะฐ ะฝะฐะฒั‡ะฐั” ะฒะฐั ะดะตัะบะธะผ ะดะพะดะฐั‚ะบะพะฒะธะผ ั„ัƒะฝะบั†ั–ัะผ. +**ะŸั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ** ะทะฐัะฝะพะฒะฐะฝะพ ะฝะฐ ั†ัŒะพะผัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั‚ั– ัะฐะผั– ะบะพะฝั†ะตะฟั†ั–ั— ั‚ะฐ ะฝะฐะฒั‡ะฐั” ะฒะฐั ะดะตัะบะธะผ ะดะพะดะฐั‚ะบะพะฒะธะผ ั„ัƒะฝะบั†ั–ัะผ. ะะปะต ะฒะฐะผ ัะปั–ะด ัะฟะพั‡ะฐั‚ะบัƒ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ **ะขัƒั‚ะพั€ั–ะฐะป - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ** (ั‚ะต, ั‰ะพ ะฒะธ ะทะฐั€ะฐะท ั‡ะธั‚ะฐั”ั‚ะต). -ะ’ั–ะฝ ั€ะพะทั€ะพะฑะปะตะฝะธะน ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฟะพะฒะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ ะปะธัˆะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ **ะขัƒั‚ะพั€ั–ะฐะป - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**, ะฐ ะฟะพั‚ั–ะผ ั€ะพะทัˆะธั€ะธั‚ะธ ั—ั— ั€ั–ะทะฝะธะผะธ ัะฟะพัะพะฑะฐะผะธ, ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะธั… ะฟะพั‚ั€ะตะฑ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะดะตัะบั– ะท ะดะพะดะฐั‚ะบะพะฒะธั… ั–ะดะตะน ะท **ะ ะพะทัˆะธั€ะตะฝะพะณะพ ะฟะพัั–ะฑะฝะธะบะฐ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**. +ะ’ั–ะฝ ั€ะพะทั€ะพะฑะปะตะฝะธะน ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฟะพะฒะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ ะปะธัˆะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ **ะขัƒั‚ะพั€ั–ะฐะป - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**, ะฐ ะฟะพั‚ั–ะผ ั€ะพะทัˆะธั€ะธั‚ะธ ั—ั— ั€ั–ะทะฝะธะผะธ ัะฟะพัะพะฑะฐะผะธ, ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะธั… ะฟะพั‚ั€ะตะฑ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะดะตัะบั– ะท ะดะพะดะฐั‚ะบะพะฒะธั… ั–ะดะตะน ะท **ะŸั€ะพััƒะฝัƒั‚ะพะณะพ ะฟะพัั–ะฑะฝะธะบะฐ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**. diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md index cf17045628..ebe8dc40e1 100644 --- a/docs/uk/docs/tutorial/metadata.md +++ b/docs/uk/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั—ั… ะฝะฐัั‚ัƒะฟะฝะธะผ ั‡ะธะฝะพะผ: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | ะŸะพั€ะฐะดะฐ @@ -36,7 +36,7 @@ ะะฐะฟั€ะธะบะปะฐะด: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## ะœะตั‚ะฐะดะฐะฝั– ะดะปั ั‚ะตะณั–ะฒ { #metadata-for-tags } @@ -58,7 +58,7 @@ ะกั‚ะฒะพั€ั–ั‚ัŒ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ัะฒะพั—ั… ั‚ะตะณั–ะฒ ั– ะฟะตั€ะตะดะฐะนั‚ะต ั—ั… ัƒ ะฟะฐั€ะฐะผะตั‚ั€ `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒ ะพะฟะธัะฐั… ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Markdown, ะฝะฐะฟั€ะธะบะปะฐะด, "login" ะฑัƒะดะต ะฟะพะบะฐะทะฐะฝะพ ะถะธั€ะฝะธะผ ัˆั€ะธั„ั‚ะพะผ (**login**), ะฐ "fancy" ะฑัƒะดะต ะฟะพะบะฐะทะฐะฝะพ ะบัƒั€ัะธะฒะพะผ (_fancy_). @@ -72,7 +72,7 @@ ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `tags` ะทั– ัะฒะพั—ะผะธ *ะพะฟะตั€ะฐั†ั–ัะผะธ ัˆะปัั…ัƒ* (ั– `APIRouter`s), ั‰ะพะฑ ะฟั€ะธะทะฝะฐั‡ะธั‚ะธ ั—ั… ะดะพ ั€ั–ะทะฝะธั… ั‚ะตะณั–ะฒ: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั @@ -100,7 +100,7 @@ ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ะฝะฐ `/api/v1/openapi.json`: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} ะฏะบั‰ะพ ะ’ะธ ั…ะพั‡ะตั‚ะต ะฟะพะฒะฝั–ัั‚ัŽ ะฒะธะผะบะฝัƒั‚ะธ ัั…ะตะผัƒ OpenAPI, ะ’ะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `openapi_url=None`, ั†ะต ั‚ะฐะบะพะถ ะฒะธะผะบะฝะต ั–ะฝั‚ะตั€ั„ะตะนัะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ัะบั– ั—ั— ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ. @@ -117,4 +117,4 @@ ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ Swagger UI ะฝะฐ `/documentation` ั– ะฒะธะผะบะฝัƒั‚ะธ ReDoc: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md index 2d1580e49e..961fb179e7 100644 --- a/docs/uk/docs/tutorial/middleware.md +++ b/docs/uk/docs/tutorial/middleware.md @@ -31,9 +31,9 @@ * ะŸะพั‚ั–ะผ ะฒะพะฝะฐ ะฟะพะฒะตั€ะฝะต `response`, ะทะณะตะฝะตั€ะพะฒะฐะฝัƒ ะฒั–ะดะฟะพะฒั–ะดะฝะพัŽ *ะพะฟะตั€ะฐั†ั–ั”ัŽ ัˆะปัั…ัƒ*. * ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะบะพะฒะพ ะทะผั–ะฝะธั‚ะธ `response` ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะฟะพะฒะตั€ะฝัƒั‚ะธ ั—ั—. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} -/// tip | ะŸะพั€ะฐะดะฐ +/// tip ะŸะฐะผโ€™ัั‚ะฐะนั‚ะต, ั‰ะพ ะฒะปะฐัะฝั– ะฟั€ะพะฟั€ั–ั”ั‚ะฐั€ะฝั– ะทะฐะณะพะปะพะฒะบะธ ะผะพะถะฝะฐ ะดะพะดะฐะฒะฐั‚ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟั€ะตั„ั–ะบั `X-`. @@ -57,9 +57,9 @@ ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะฒะปะฐัะฝะธะน ะทะฐะณะพะปะพะฒะพะบ `X-Process-Time`, ัะบะธะน ะผั–ัั‚ะธั‚ะธะผะต ั‡ะฐั ัƒ ัะตะบัƒะฝะดะฐั…, ัะบะธะน ะฒะธั‚ั€ะฐั‚ะธะฒัั ะฝะฐ ะพะฑั€ะพะฑะบัƒ ะทะฐะฟะธั‚ัƒ ั‚ะฐ ะณะตะฝะตั€ะฐั†ั–ัŽ ะฒั–ะดะฟะพะฒั–ะดั–: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} -/// tip | ะŸะพั€ะฐะดะฐ +/// tip ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `time.perf_counter()` ะทะฐะผั–ัั‚ัŒ `time.time()` ะพัะบั–ะปัŒะบะธ ะฒั–ะฝ ะผะพะถะต ะฑัƒั‚ะธ ะฑั–ะปัŒัˆ ั‚ะพั‡ะฝะธะผ ะดะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ. ๐Ÿค“ @@ -92,4 +92,4 @@ app.add_middleware(MiddlewareB) ะ’ะธ ะผะพะถะตั‚ะต ะฟั–ะทะฝั–ัˆะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฑั–ะปัŒัˆะต ะฟั€ะพ ั–ะฝัˆั– middlewares ะฒ [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. -ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตััŒ, ัะบ ะพะฑั€ะพะฑะปัั‚ะธ CORS ะทะฐ ะดะพะฟะพะผะพะณะพัŽ middleware ะฒ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั–. +ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตััŒ, ัะบ ะพะฑั€ะพะฑะปัั‚ะธ CORS ะทะฐ ะดะพะฟะพะผะพะณะพัŽ middleware ะฒ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั–. diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md index f6aa920193..9458436fd3 100644 --- a/docs/uk/docs/tutorial/path-params-numeric-validations.md +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Python ะฒะธะดะฐัั‚ัŒ ะฟะพะผะธะปะบัƒ, ัะบั‰ะพ ั€ะพะทะผั–ัั‚ะธั‚ะธ ะทะฝะฐั‡ะตะฝ ะขะพะผัƒ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฒะฐัˆัƒ ั„ัƒะฝะบั†ั–ัŽ ั‚ะฐะบ: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} ะะปะต ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Annotated`, ั†ั–ั”ั— ะฟั€ะพะฑะปะตะผะธ ะฝะต ะฑัƒะดะต, ั†ะต ะฝะต ะผะฐั‚ะธะผะต ะทะฝะฐั‡ะตะฝะฝั, ะพัะบั–ะปัŒะบะธ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั„ัƒะฝะบั†ั–ั— ะดะปั `Query()` ะฐะฑะพ `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## ะฃะฟะพั€ัะดะบะพะฒัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ะธ, ัะบ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ: ั…ะธั‚ั€ะพั‰ั– { #order-the-parameters-as-you-need-tricks } @@ -81,15 +81,15 @@ Python ะฒะธะดะฐัั‚ัŒ ะฟะพะผะธะปะบัƒ, ัะบั‰ะพ ั€ะพะทะผั–ัั‚ะธั‚ะธ ะทะฝะฐั‡ะตะฝ ะŸะตั€ะตะดะฐะนั‚ะต `*` ัะบ ะฟะตั€ัˆะธะน ะฟะฐั€ะฐะผะตั‚ั€ ั„ัƒะฝะบั†ั–ั—. -Python ะฝั–ั‡ะพะณะพ ะฝะต ะทั€ะพะฑะธั‚ัŒ ั–ะท ั†ั–ั”ัŽ `*`, ะฐะปะต ั€ะพะทะฟั–ะทะฝะฐั”, ั‰ะพ ะฒัั– ะฝะฐัั‚ัƒะฟะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ัะปั–ะด ะฒะธะบะปะธะบะฐั‚ะธ ัะบ ะฐั€ะณัƒะผะตะฝั‚ะธ ะทะฐ ะบะปัŽั‡ะพะฒะธะผ ัะปะพะฒะพะผ (ะฟะฐั€ะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั), ั‚ะฐะบะพะถ ะฒั–ะดะพะผั– ัะบ kwargs. ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะธ ะฝะต ะผะฐัŽั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +Python ะฝั–ั‡ะพะณะพ ะฝะต ะทั€ะพะฑะธั‚ัŒ ั–ะท ั†ั–ั”ัŽ `*`, ะฐะปะต ั€ะพะทะฟั–ะทะฝะฐั”, ั‰ะพ ะฒัั– ะฝะฐัั‚ัƒะฟะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ัะปั–ะด ะฒะธะบะปะธะบะฐั‚ะธ ัะบ ะฐั€ะณัƒะผะตะฝั‚ะธ ะทะฐ ะบะปัŽั‡ะพะฒะธะผ ัะปะพะฒะพะผ (ะฟะฐั€ะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั), ั‚ะฐะบะพะถ ะฒั–ะดะพะผั– ัะบ kwargs. ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะธ ะฝะต ะผะฐัŽั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### ะšั€ะฐั‰ะต ะท `Annotated` { #better-with-annotated } ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Annotated`, ะพัะบั–ะปัŒะบะธ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั„ัƒะฝะบั†ั–ั—, ั†ั–ั”ั— ะฟั€ะพะฑะปะตะผะธ ะฝะต ะฑัƒะดะต, ั–, ะนะผะพะฒั–ั€ะฝะพ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## ะ’ะฐะปั–ะดะฐั†ั–ั ั‡ะธัะปะพะฒะธั… ะดะฐะฝะธั…: ะฑั–ะปัŒัˆะต ะฐะฑะพ ะดะพั€ั–ะฒะฝัŽั” { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Python ะฝั–ั‡ะพะณะพ ะฝะต ะทั€ะพะฑะธั‚ัŒ ั–ะท ั†ั–ั”ัŽ `*`, ะฐะปะต ั€ะพะทะฟั–ะทะฝ ะขัƒั‚, ะทะฐะฒะดัะบะธ `ge=1`, `item_id` ะผะฐั” ะฑัƒั‚ะธ ั†ั–ะปะธะผ ั‡ะธัะปะพะผ, ัะบะต "`g`reater than or `e`qual" (ะฑั–ะปัŒัˆะต ะฐะฑะพ ะดะพั€ั–ะฒะฝัŽั”) `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## ะ’ะฐะปั–ะดะฐั†ั–ั ั‡ะธัะปะพะฒะธั… ะดะฐะฝะธั…: ะฑั–ะปัŒัˆะต ะฝั–ะถ ั– ะผะตะฝัˆะต ะฐะฑะพ ะดะพั€ั–ะฒะฝัŽั” { #number-validations-greater-than-and-less-than-or-equal } @@ -106,19 +106,19 @@ Python ะฝั–ั‡ะพะณะพ ะฝะต ะทั€ะพะฑะธั‚ัŒ ั–ะท ั†ั–ั”ัŽ `*`, ะฐะปะต ั€ะพะทะฟั–ะทะฝ * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## ะ’ะฐะปั–ะดะฐั†ั–ั ั‡ะธัะปะพะฒะธั… ะดะฐะฝะธั…: float, ะฑั–ะปัŒัˆะต ะฝั–ะถ ั– ะผะตะฝัˆะต ะฝั–ะถ { #number-validations-floats-greater-than-and-less-than } ะ’ะฐะปั–ะดะฐั†ั–ั ั‡ะธัะตะป ั‚ะฐะบะพะถ ะฟั€ะฐั†ัŽั” ะดะปั ะทะฝะฐั‡ะตะฝัŒ ั‚ะธะฟัƒ `float`. -ะžััŒ ะดะต ัั‚ะฐั” ะฒะฐะถะปะธะฒะพ ะผะฐั‚ะธ ะผะพะถะปะธะฒั–ัั‚ัŒ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ gt, ะฐ ะฝะต ั‚ั–ะปัŒะบะธ ge. ะฆะต ะดะพะทะฒะพะปัั”, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะธะผะฐะณะฐั‚ะธ, ั‰ะพะฑ ะทะฝะฐั‡ะตะฝะฝั ะฑัƒะปะพ ะฑั–ะปัŒัˆะต `0`, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะพ ะผะตะฝัˆะต `1`. +ะžััŒ ะดะต ัั‚ะฐั” ะฒะฐะถะปะธะฒะพ ะผะฐั‚ะธ ะผะพะถะปะธะฒั–ัั‚ัŒ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ gt, ะฐ ะฝะต ั‚ั–ะปัŒะบะธ ge. ะฆะต ะดะพะทะฒะพะปัั”, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะธะผะฐะณะฐั‚ะธ, ั‰ะพะฑ ะทะฝะฐั‡ะตะฝะฝั ะฑัƒะปะพ ะฑั–ะปัŒัˆะต `0`, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะพ ะผะตะฝัˆะต `1`. ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะทะฝะฐั‡ะตะฝะฝั `0.5` ะฑัƒะดะต ะดะพะฟัƒัั‚ะธะผะธะผ. ะะปะต `0.0` ะฐะฑะพ `0` โ€” ะฝั–. -ะขะต ัะฐะผะต ัั‚ะพััƒั”ั‚ัŒัั lt. +ะขะต ัะฐะผะต ัั‚ะพััƒั”ั‚ัŒัั lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ะŸั–ะดััƒะผะพะบ { #recap } diff --git a/docs/uk/docs/tutorial/path-params.md b/docs/uk/docs/tutorial/path-params.md index 0598905495..17b99cf39a 100644 --- a/docs/uk/docs/tutorial/path-params.md +++ b/docs/uk/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ยซะฟะฐั€ะฐะผะตั‚ั€ะธยป ะฐะฑะพ ยซะทะผั–ะฝะฝั–ยป ัˆะปัั…ัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ัะฐะผะธะน ัะธะฝั‚ะฐะบัะธั, ั‰ะพ ะน ัƒ ั„ะพั€ะผะฐั‚ะพะฒะฐะฝะธั… ั€ัะดะบะฐั… Python: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} ะ—ะฝะฐั‡ะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัˆะปัั…ัƒ `item_id` ะฑัƒะดะต ะฟะตั€ะตะดะฐะฝะพ ัƒ ะฒะฐัˆัƒ ั„ัƒะฝะบั†ั–ัŽ ัะบ ะฐั€ะณัƒะผะตะฝั‚ `item_id`. @@ -16,17 +16,17 @@ ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ั‚ะธะฟ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัˆะปัั…ัƒ ัƒ ั„ัƒะฝะบั†ั–ั—, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟั–ะฒ Python: -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `item_id` ะพะณะพะปะพัˆะตะฝะพ ัะบ `int`. -/// check | ะŸั€ะธะผั–ั‚ะบะฐ +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต ะฆะต ะดะฐัั‚ัŒ ะฒะฐะผ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— ะท ะฟะตั€ะตะฒั–ั€ะบะฐะผะธ ะฟะพะผะธะปะพะบ, ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัะผ ั‚ะพั‰ะพ. /// -## ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั… { #data-conversion } +## ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั… { #data-conversion } ะฏะบั‰ะพ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต ั†ะตะน ะฟั€ะธะบะปะฐะด ั– ะฒั–ะดะบั€ะธั”ั‚ะต ัƒ ะฑั€ะฐัƒะทะตั€ั– http://127.0.0.1:8000/items/3, ั‚ะพ ะฟะพะฑะฐั‡ะธั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ: @@ -34,11 +34,11 @@ {"item_id":3} ``` -/// check | ะŸั€ะธะผั–ั‚ะบะฐ +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะพั‚ั€ะธะผะฐะปะฐ (ั– ะฟะพะฒะตั€ะฝัƒะปะฐ) ะฒะฐัˆะฐ ั„ัƒะฝะบั†ั–ั, โ€” ั†ะต `3`, ัะบ Python `int`, ะฐ ะฝะต ั€ัะดะพะบ `"3"`. -ะžั‚ะถะต, ะท ั‚ะฐะบะธะผ ะพะณะพะปะพัˆะตะฝะฝัะผ ั‚ะธะฟัƒ **FastAPI** ะฝะฐะดะฐั” ะฒะฐะผ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธะน ยซparsingยป ะทะฐะฟะธั‚ัƒ. +ะžั‚ะถะต, ะท ั‚ะฐะบะธะผ ะพะณะพะปะพัˆะตะฝะฝัะผ ั‚ะธะฟัƒ **FastAPI** ะฝะฐะดะฐั” ะฒะฐะผ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธะน ะทะฐะฟะธั‚ ยซะฟะฐั€ัะธะฝะณยป. /// @@ -66,7 +66,7 @@ ะขะฐ ัะฐะผะฐ ะฟะพะผะธะปะบะฐ ะทโ€™ัะฒะธั‚ัŒัั, ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะดะฐัั‚ะต `float` ะทะฐะผั–ัั‚ัŒ `int`, ัะบ ัƒ: http://127.0.0.1:8000/items/4.2 -/// check | ะŸั€ะธะผั–ั‚ะบะฐ +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต ะžั‚ะถะต, ะท ั‚ะธะผ ัะฐะผะธะผ ะพะณะพะปะพัˆะตะฝะฝัะผ ั‚ะธะฟัƒ ะฒ Python **FastAPI** ะฝะฐะดะฐั” ะฒะฐะผ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…. @@ -82,7 +82,7 @@ -/// check | ะŸั€ะธะผั–ั‚ะบะฐ +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต ะ—ะฝะพะฒัƒ ะถ ั‚ะฐะบะธ, ะปะธัˆะต ะท ั‚ะธะผ ัะฐะผะธะผ ะพะณะพะปะพัˆะตะฝะฝัะผ ั‚ะธะฟัƒ ะฒ Python **FastAPI** ะฝะฐะดะฐั” ะฒะฐะผ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ, ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ (ะท ั–ะฝั‚ะตะณั€ะฐั†ั–ั”ัŽ Swagger UI). @@ -118,19 +118,19 @@ ะžัะบั–ะปัŒะบะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะพั†ั–ะฝัŽัŽั‚ัŒัั ะฟะพ ั‡ะตั€ะทั–, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ัˆะปัั… ะดะปั `/users/me` ะพะณะพะปะพัˆะตะฝะพ ะฟะตั€ะตะด ัˆะปัั…ะพะผ ะดะปั `/users/{user_id}`: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} ะ†ะฝะฐะบัˆะต ัˆะปัั… ะดะปั `/users/{user_id}` ั‚ะฐะบะพะถ ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธะผะต `/users/me`, ยซะฒะฒะฐะถะฐัŽั‡ะธยป, ั‰ะพ ะพั‚ั€ะธะผัƒั” ะฟะฐั€ะฐะผะตั‚ั€ `user_id` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `"me"`. ะขะฐะบ ัะฐะผะพ ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะทะฝะฐั‡ะธั‚ะธ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} ะ—ะฐะฒะถะดะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ัŒัั ะฟะตั€ัˆะฐ, ะพัะบั–ะปัŒะบะธ ัˆะปัั… ะทะฑั–ะณะฐั”ั‚ัŒัั ะฟะตั€ัˆะธะผ. ## ะŸะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝั– ะทะฝะฐั‡ะตะฝะฝั { #predefined-values } -ะฏะบั‰ะพ ัƒ ะฒะฐั ั” *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ*, ัะบะฐ ะพั‚ั€ะธะผัƒั” *ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ*, ะฐะปะต ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะผะพะถะปะธะฒั– ะบะพั€ะตะบั‚ะฝั– ะทะฝะฐั‡ะตะฝะฝั *ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัˆะปัั…ัƒ* ะฑัƒะปะธ ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝั–, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน Python `Enum`. +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ*, ัะบะฐ ะพั‚ั€ะธะผัƒั” *ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ*, ะฐะปะต ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะผะพะถะปะธะฒั– ะบะพั€ะตะบั‚ะฝั– ะทะฝะฐั‡ะตะฝะฝั *ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัˆะปัั…ัƒ* ะฑัƒะปะธ ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝั–, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน Python `Enum`. ### ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะปะฐั `Enum` { #create-an-enum-class } @@ -140,11 +140,11 @@ ะŸั–ัะปั ั†ัŒะพะณะพ ัั‚ะฒะพั€ั–ั‚ัŒ ะฐั‚ั€ะธะฑัƒั‚ะธ ะบะปะฐััƒ ะท ั„ั–ะบัะพะฒะฐะฝะธะผะธ ะทะฝะฐั‡ะตะฝะฝัะผะธ, ัะบั– ะฑัƒะดัƒั‚ัŒ ะดะพัั‚ัƒะฟะฝะธะผะธ ะบะพั€ะตะบั‚ะฝะธะผะธ ะทะฝะฐั‡ะตะฝะฝัะผะธ: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | ะŸะพั€ะฐะดะฐ -ะฏะบั‰ะพ ะฒะฐะผ ั†ั–ะบะฐะฒะพ, ยซAlexNetยป, ยซResNetยป ั‚ะฐ ยซLeNetยป โ€” ั†ะต ะฟั€ะพัั‚ะพ ะฝะฐะทะฒะธ Machine Learning models. +ะฏะบั‰ะพ ะฒะฐะผ ั†ั–ะบะฐะฒะพ, ยซAlexNetยป, ยซResNetยป ั‚ะฐ ยซLeNetยป โ€” ั†ะต ะฟั€ะพัั‚ะพ ะฝะฐะทะฒะธ ะผะพะดะตะปะตะน ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั ะผะพะดะตะปั–. /// @@ -152,7 +152,7 @@ ะŸะพั‚ั–ะผ ัั‚ะฒะพั€ั–ั‚ัŒ *ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ* ะท ะฐะฝะพั‚ะฐั†ั–ั”ัŽ ั‚ะธะฟัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัั‚ะฒะพั€ะตะฝะธะน ะฒะฐะผะธ ะบะปะฐั enum (`ModelName`): -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### ะŸะตั€ะตะฒั–ั€ั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #check-the-docs } @@ -168,13 +168,13 @@ ะ’ะธ ะผะพะถะตั‚ะต ะฟะพั€ั–ะฒะฝัŽะฒะฐั‚ะธ ะนะพะณะพ ะท *ะตะปะตะผะตะฝั‚ะพะผ ะฟะตั€ะตะปั–ั‡ัƒะฒะฐะฝะฝั* ัƒ ัั‚ะฒะพั€ะตะฝะพะผัƒ ะฒะฐะผะธ enum `ModelName`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### ะžั‚ั€ะธะผะฐะนั‚ะต *ะทะฝะฐั‡ะตะฝะฝั ะฟะตั€ะตะปั–ั‡ัƒะฒะฐะฝะฝั* { #get-the-enumeration-value } ะ’ะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะบั‚ะธั‡ะฝะต ะทะฝะฐั‡ะตะฝะฝั (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั†ะต `str`), ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `model_name.value`, ะฐะฑะพ ะทะฐะณะฐะปะพะผ `your_enum_member.value`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | ะŸะพั€ะฐะดะฐ @@ -188,7 +188,7 @@ ะ’ะพะฝะธ ะฑัƒะดัƒั‚ัŒ ะฟะตั€ะตั‚ะฒะพั€ะตะฝั– ะฝะฐ ะฒั–ะดะฟะพะฒั–ะดะฝั– ะทะฝะฐั‡ะตะฝะฝั (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั€ัะดะบะธ) ะฟะตั€ะตะด ะฟะพะฒะตั€ะฝะตะฝะฝัะผ ะบะปั–ั”ะฝั‚ัƒ: -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} ะะฐ ัั‚ะพั€ะพะฝั– ะบะปั–ั”ะฝั‚ะฐ ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ ัƒ ั„ะพั€ะผะฐั‚ั– JSON, ะฝะฐะฟั€ะธะบะปะฐะด: @@ -227,7 +227,7 @@ OpenAPI ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ัะฟะพัั–ะฑ ะพะณะพะปะพัˆะตะฝะฝั *ะฟะฐั€ะฐะผะต ะžั‚ะถะต, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะนะพะณะพ ั‚ะฐะบ: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | ะŸะพั€ะฐะดะฐ @@ -242,7 +242,7 @@ OpenAPI ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ัะฟะพัั–ะฑ ะพะณะพะปะพัˆะตะฝะฝั *ะฟะฐั€ะฐะผะต ะ— **FastAPI**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะบะพั€ะพั‚ะบั–, ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ ะทั€ะพะทัƒะผั–ะปั– ั‚ะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะพะณะพะปะพัˆะตะฝะฝั ั‚ะธะฟั–ะฒ Python, ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต: * ะŸั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ะฐ: ะฟะตั€ะตะฒั–ั€ะบะฐ ะฟะพะผะธะปะพะบ, ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ั‚ะพั‰ะพ. -* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั… ยซparsingยป +* ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั… ยซะฟะฐั€ัะธะฝะณยป * ะ’ะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั… * ะะฝะพั‚ะฐั†ั–ัŽ API ั‚ะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ diff --git a/docs/uk/docs/tutorial/query-param-models.md b/docs/uk/docs/tutorial/query-param-models.md index a28bf6c27c..5affc8a6c2 100644 --- a/docs/uk/docs/tutorial/query-param-models.md +++ b/docs/uk/docs/tutorial/query-param-models.md @@ -1,6 +1,6 @@ # ะœะพะดะตะปั– ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ { #query-parameter-models } -ะฏะบั‰ะพ ัƒ ะ’ะฐั ั” ะณั€ัƒะฟะฐ **query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ**, ัะบั– ะฟะพะฒโ€™ัะทะฐะฝั– ะผั–ะถ ัะพะฑะพัŽ, ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic-ะผะพะดะตะปัŒ** ะดะปั ั—ั… ะพะณะพะปะพัˆะตะฝะฝั. +ะฏะบั‰ะพ ัƒ ะ’ะฐั ั” ะณั€ัƒะฟะฐ **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ**, ัะบั– ะฟะพะฒโ€™ัะทะฐะฝั– ะผั–ะถ ัะพะฑะพัŽ, ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ **Pydantic-ะผะพะดะตะปัŒ** ะดะปั ั—ั… ะพะณะพะปะพัˆะตะฝะฝั. ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะ’ะฐะผ **ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ** ัƒ **ั€ั–ะทะฝะธั… ะผั–ัั†ัั…**, ะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั– ะดะปั ะฒัั–ั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. ๐Ÿ˜Ž @@ -10,13 +10,13 @@ /// -## Query ะฟะฐั€ะฐะผะตั‚ั€ะธ ะท Pydantic-ะผะพะดะตะปะปัŽ { #query-parameters-with-a-pydantic-model } +## ะŸะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ ะท Pydantic-ะผะพะดะตะปะปัŽ { #query-parameters-with-a-pydantic-model } -ะžะณะพะปะพัั–ั‚ัŒ **query ะฟะฐั€ะฐะผะตั‚ั€ะธ**, ัะบั– ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–, ัƒ **Pydantic-ะผะพะดะตะปั–**, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัั–ั‚ัŒ ั†ะตะน ะฟะฐั€ะฐะผะตั‚ั€ ัะบ `Query`: +ะžะณะพะปะพัั–ั‚ัŒ **ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ**, ัะบั– ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–, ัƒ **Pydantic-ะผะพะดะตะปั–**, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัั–ั‚ัŒ ั†ะตะน ะฟะฐั€ะฐะผะตั‚ั€ ัะบ `Query`: {* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} -**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ** ัƒ ะทะฐะฟะธั‚ั– ั‚ะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ั—ั… ัƒ ะฒะธะทะฝะฐั‡ะตะฝัƒ ะฒะฐะผะธ Pydantic-ะผะพะดะตะปัŒ. +**FastAPI** ะฑัƒะดะต **ะฒะธั‚ัะณัƒะฒะฐั‚ะธ** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ** ัƒ ะทะฐะฟะธั‚ั– ั‚ะฐ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ั—ั… ัƒ ะฒะธะทะฝะฐั‡ะตะฝัƒ ะฒะฐะผะธ Pydantic-ะผะพะดะตะปัŒ. ## ะŸะตั€ะตะฒั–ั€ั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #check-the-docs } @@ -26,23 +26,23 @@
-## ะ—ะฐะฑะพั€ะพะฝะฐ ะทะฐะนะฒะธั… Query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ { #forbid-extra-query-parameters } +## ะ—ะฐะฑะพั€ะพะฝะฐ ะทะฐะนะฒะธั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ { #forbid-extra-query-parameters } -ะฃ ะดะตัะบะธั… ะพัะพะฑะปะธะฒะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** query ะฟะฐั€ะฐะผะตั‚ั€ะธ, ัะบั– ะดะพะทะฒะพะปะตะฝะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ. +ะฃ ะดะตัะบะธั… ะพัะพะฑะปะธะฒะธั… ะฒะธะฟะฐะดะบะฐั… (ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะธั…) ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ **ะพะฑะผะตะถะธั‚ะธ** ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะฟะธั‚ัƒ, ัะบั– ะดะพะทะฒะพะปะตะฝะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ ะผะพะดะตะปั– Pydantic, ั‰ะพะฑ ะทะฐะฑะพั€ะพะฝะธั‚ะธ (`forbid`) ะฑัƒะดัŒ-ัะบั– ะทะฐะนะฒั– (`extra`) ะฟะพะปั: {* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} -ะฏะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ **ะทะฐะนะฒั–** ะดะฐะฝั– ัƒ **query ะฟะฐั€ะฐะผะตั‚ั€ะฐั…**, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” **ะฟะพะผะธะปะบัƒ** ะฒั–ะดะฟะพะฒั–ะดัŒ. +ะฏะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ **ะทะฐะนะฒั–** ะดะฐะฝั– ัƒ **ะฟะฐั€ะฐะผะตั‚ั€ะฐั… ะทะฐะฟะธั‚ัƒ**, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” **ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฟะพะผะธะปะบะพัŽ**. -ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ query ะฟะฐั€ะฐะผะตั‚ั€ `tool` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `plumbus`, ัะบ ัƒ ั†ัŒะพะผัƒ ะทะฐะฟะธั‚ั–: +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `tool` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `plumbus`, ัะบ ัƒ ั†ัŒะพะผัƒ ะทะฐะฟะธั‚ั–: ```http https://example.com/items/?limit=10&tool=plumbus ``` -ะ’ั–ะฝ ะพั‚ั€ะธะผะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะท **ะฟะพะผะธะปะบะพัŽ**, ัะบะฐ ะฟะพะฒั–ะดะพะผะธั‚ัŒ, ั‰ะพ query ะฟะฐั€ะฐะผะตั‚ั€ `tool ` ะฝะต ะดะพะทะฒะพะปะตะฝะพ: +ะ’ั–ะฝ ะพั‚ั€ะธะผะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะท **ะฟะพะผะธะปะบะพัŽ**, ัะบะฐ ะฟะพะฒั–ะดะพะผะธั‚ัŒ, ั‰ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `tool` ะฝะต ะดะพะทะฒะพะปะตะฝะพ: ```json { @@ -59,10 +59,10 @@ https://example.com/items/?limit=10&tool=plumbus ## ะŸั–ะดััƒะผะพะบ { #summary } -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **Pydantic-ะผะพะดะตะปั–** ะดะปั ะพะณะพะปะพัˆะตะฝะฝั **query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ** ัƒ **FastAPI**. ๐Ÿ˜Ž +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **Pydantic-ะผะพะดะตะปั–** ะดะปั ะพะณะพะปะพัˆะตะฝะฝั **ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ะทะฐะฟะธั‚ัƒ** ัƒ **FastAPI**. ๐Ÿ˜Ž /// tip | ะŸะพั€ะฐะดะฐ -ะกะฟะพะนะปะตั€: ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Pydantic-ะผะพะดะตะปั– ะดะปั ะพะณะพะปะพัˆะตะฝะฝั cookie ั‚ะฐ ะทะฐะณะพะปะพะฒะบั–ะฒ, ะฐะปะต ะฟั€ะพ ั†ะต ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตัั ะฟั–ะทะฝั–ัˆะต ะฒ ั†ัŒะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ. ๐Ÿคซ +ะกะฟะพะนะปะตั€: ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Pydantic-ะผะพะดะตะปั– ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะบัƒะบั– ั‚ะฐ ะทะฐะณะพะปะพะฒะบั–ะฒ, ะฐะปะต ะฟั€ะพ ั†ะต ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตัั ะฟั–ะทะฝั–ัˆะต ะฒ ั†ัŒะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ. ๐Ÿคซ /// diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md index 414987880b..706dc670aa 100644 --- a/docs/uk/docs/tutorial/query-params-str-validations.md +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ FastAPI ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั `q` ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒ ## ะ”ะพะดะฐั‚ะบะพะฒะฐ ะฒะฐะปั–ะดะฐั†ั–ั { #additional-validation } -ะœะธ ั…ะพั‡ะตะผะพ, ั‰ะพะฑ ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ `q` ั” ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ะบะพะปะธ ะนะพะณะพ ะฟะตั€ะตะดะฐัŽั‚ัŒ, **ะนะพะณะพ ะดะพะฒะถะธะฝะฐ ะฝะต ะฟะตั€ะตะฒะธั‰ัƒะฒะฐะปะฐ 50 ัะธะผะฒะพะปั–ะฒ**. +ะœะธ ั…ะพั‡ะตะผะพ, ั‰ะพะฑ ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ `q` ั” ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ะบะพะปะธ ะนะพะณะพ ะฟะตั€ะตะดะฐัŽั‚ัŒ, ะนะพะณะพ ะดะพะฒะถะธะฝะฐ ะฝะต ะฟะตั€ะตะฒะธั‰ัƒะฒะฐะปะฐ 50 ัะธะผะฒะพะปั–ะฒ. ### ะ†ะผะฟะพั€ั‚ `Query` ั‚ะฐ `Annotated` { #import-query-and-annotated } @@ -47,40 +47,16 @@ FastAPI ะดะพะดะฐะฒ ะฟั–ะดั‚ั€ะธะผะบัƒ `Annotated` (ั– ะฟะพั‡ะฐะฒ ั€ะตะบะพะผะตะฝ ะ ะฐะฝั–ัˆะต ะผะธ ะผะฐะปะธ ั‚ะฐะบัƒ ะฐะฝะพั‚ะฐั†ั–ัŽ ั‚ะธะฟัƒ: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ะขะตะฟะตั€ ะผะธ ะทะฐะณะพั€ะฝะตะผะพ ั—ั— ัƒ `Annotated`, ั– ะพั‚ั€ะธะผะฐั”ะผะพ: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - ะžะฑะธะดะฒั– ั†ั– ะฒะตั€ัั–ั— ะพะทะฝะฐั‡ะฐัŽั‚ัŒ ะพะดะฝะต ะน ั‚ะต ัะฐะผะต: `q` โ€” ั†ะต ะฟะฐั€ะฐะผะตั‚ั€, ัะบะธะน ะผะพะถะต ะฑัƒั‚ะธ `str` ะฐะฑะพ `None`, ั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั `None`. ะ ั‚ะตะฟะตั€ ะฟะตั€ะตั…ะพะดะธะผะพ ะดะพ ั†ั–ะบะฐะฒะพะณะพ! ๐ŸŽ‰ @@ -93,23 +69,23 @@ q: Annotated[Union[str, None]] = None ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ัƒัะต ั‰ะต `None`, ั‚ะพะผัƒ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะปะธัˆะฐั”ั‚ัŒัั ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ. -ะะปะต ั‚ะตะฟะตั€, ะดะพะดะฐะฒัˆะธ `Query(max_length=50)` ะฒัะตั€ะตะดะธะฝัƒ `Annotated`, ะผะธ ะฟะพะฒั–ะดะพะผะปัั”ะผะพ FastAPI, ั‰ะพ ั…ะพั‡ะตะผะพ **ะดะพะดะฐั‚ะบะพะฒัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ** ะดะปั ั†ัŒะพะณะพ ะทะฝะฐั‡ะตะฝะฝั: ะผะธ ั…ะพั‡ะตะผะพ, ั‰ะพะฑ ะฒะพะฝะพ ะผะฐะปะพ ะผะฐะบัะธะผัƒะผ 50 ัะธะผะฒะพะปั–ะฒ. ๐Ÿ˜Ž +ะะปะต ั‚ะตะฟะตั€, ะดะพะดะฐะฒัˆะธ `Query(max_length=50)` ะฒัะตั€ะตะดะธะฝัƒ `Annotated`, ะผะธ ะฟะพะฒั–ะดะพะผะปัั”ะผะพ FastAPI, ั‰ะพ ั…ะพั‡ะตะผะพ ะดะพะดะฐั‚ะบะพะฒัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะปั ั†ัŒะพะณะพ ะทะฝะฐั‡ะตะฝะฝั: ะผะธ ั…ะพั‡ะตะผะพ, ั‰ะพะฑ ะฒะพะฝะพ ะผะฐะปะพ ะผะฐะบัะธะผัƒะผ 50 ัะธะผะฒะพะปั–ะฒ. ๐Ÿ˜Ž /// tip | ะŸะพั€ะฐะดะฐ -ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `Query()`, ะพัะบั–ะปัŒะบะธ ั†ะต **query ะฟะฐั€ะฐะผะตั‚ั€**. ะ”ะฐะปั– ะผะธ ั€ะพะทะณะปัะฝะตะผะพ ั–ะฝัˆั– ะฒะฐั€ั–ะฐะฝั‚ะธ, ัะบ-ะพั‚ `Path()`, `Body()`, `Header()` ั‚ะฐ `Cookie()`, ัะบั– ะฟั€ะธะนะผะฐัŽั‚ัŒ ั‚ั– ัะฐะผั– ะฐั€ะณัƒะผะตะฝั‚ะธ, ั‰ะพ ะน `Query()`. +ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `Query()`, ะพัะบั–ะปัŒะบะธ ั†ะต query ะฟะฐั€ะฐะผะตั‚ั€. ะ”ะฐะปั– ะผะธ ั€ะพะทะณะปัะฝะตะผะพ ั–ะฝัˆั– ะฒะฐั€ั–ะฐะฝั‚ะธ, ัะบ-ะพั‚ `Path()`, `Body()`, `Header()` ั‚ะฐ `Cookie()`, ัะบั– ะฟั€ะธะนะผะฐัŽั‚ัŒ ั‚ั– ัะฐะผั– ะฐั€ะณัƒะผะตะฝั‚ะธ, ั‰ะพ ะน `Query()`. /// ะขะตะฟะตั€ FastAPI: -* **ะŸะตั€ะตะฒั–ั€ะธั‚ัŒ** ะดะฐะฝั–, ั‰ะพะฑ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ั—ั…ะฝั ะผะฐะบัะธะผะฐะปัŒะฝะฐ ะดะพะฒะถะธะฝะฐ โ€” 50 ัะธะผะฒะพะปั–ะฒ -* ะŸะพะบะฐะถe **ั‡ั–ั‚ะบัƒ ะฟะพะผะธะปะบัƒ** ะบะปั–ั”ะฝั‚ัƒ, ัะบั‰ะพ ะดะฐะฝั– ะฝะตะดั–ะนัะฝั– -* **ะ—ะฐะดะพะบัƒะผะตะฝั‚ัƒั”** ะฟะฐั€ะฐะผะตั‚ั€ ะฒ OpenAPI-ัั…ะตะผั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* (ั‰ะพ ะฒั–ะดะพะฑั€ะฐะทะธั‚ัŒัั ะฒ **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—**) +* ะŸะตั€ะตะฒั–ั€ะธั‚ัŒ ะดะฐะฝั–, ั‰ะพะฑ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ั—ั…ะฝั ะผะฐะบัะธะผะฐะปัŒะฝะฐ ะดะพะฒะถะธะฝะฐ โ€” 50 ัะธะผะฒะพะปั–ะฒ +* ะŸะพะบะฐะถe ั‡ั–ั‚ะบัƒ ะฟะพะผะธะปะบัƒ ะบะปั–ั”ะฝั‚ัƒ, ัะบั‰ะพ ะดะฐะฝั– ะฝะตะดั–ะนัะฝั– +* ะ—ะฐะดะพะบัƒะผะตะฝั‚ัƒั” ะฟะฐั€ะฐะผะตั‚ั€ ะฒ OpenAPI-ัั…ะตะผั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ (ั‰ะพ ะฒั–ะดะพะฑั€ะฐะทะธั‚ัŒัั ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—) ## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธะน (ะทะฐัั‚ะฐั€ั–ะปะธะน) ะผะตั‚ะพะด: `Query` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ { #alternative-old-query-as-the-default-value } -ะฃ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั… FastAPI (ะดะพ 0.95.0) ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะปะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Query` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟะฐั€ะฐะผะตั‚ั€ะฐ, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะดะพะดะฐะฒะฐั‚ะธ ะนะพะณะพ ะฒ `Annotated`. ะ„ ะฒะธัะพะบะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ ะฒะธ ะทัƒัั‚ั€ั–ะฝะตั‚ะต ะบะพะด ั–ะท ั‚ะฐะบะธะผ ะฟั–ะดั…ะพะดะพะผ, ั‚ะพะถ ั ะฟะพััะฝัŽ ะนะพะณะพ. +ะฃ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั… FastAPI (ะดะพ 0.95.0) ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะปะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Query` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟะฐั€ะฐะผะตั‚ั€ะฐ, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะดะพะดะฐะฒะฐั‚ะธ ะนะพะณะพ ะฒ `Annotated`. ะ„ ะฒะธัะพะบะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ ะฒะธ ะทัƒัั‚ั€ั–ะฝะตั‚ะต ะบะพะด ั–ะท ั‚ะฐะบะธะผ ะฟั–ะดั…ะพะดะพะผ, ั‚ะพะถ ั ะฟะพััะฝัŽ ะนะพะณะพ. /// tip | ะŸะพั€ะฐะดะฐ @@ -131,7 +107,6 @@ q: str | None = Query(default=None) ...ั€ะพะฑะธั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `None`, ั‰ะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ: - ```Python q: str | None = None ``` @@ -144,7 +119,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -ะฆะต ะทะฐะฑะตะทะฟะตั‡ะธั‚ัŒ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…, ะฒะธะฒะตะดะต ะทั€ะพะทัƒะผั–ะปัƒ ะฟะพะผะธะปะบัƒ ัƒ ั€ะฐะทั– ะฝะตะดั–ะนัะฝะธั… ะดะฐะฝะธั… ั– ะทะฐะดะพะบัƒะผะตะฝั‚ัƒั” ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ัั…ะตะผั– OpenAPI *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. +ะฆะต ะทะฐะฑะตะทะฟะตั‡ะธั‚ัŒ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…, ะฒะธะฒะตะดะต ะทั€ะพะทัƒะผั–ะปัƒ ะฟะพะผะธะปะบัƒ ัƒ ั€ะฐะทั– ะฝะตะดั–ะนัะฝะธั… ะดะฐะฝะธั… ั– ะทะฐะดะพะบัƒะผะตะฝั‚ัƒั” ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ัั…ะตะผั– OpenAPI ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. ### `Query` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฐะฑะพ ะฒัะตั€ะตะดะธะฝั– `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -174,13 +149,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. ๐Ÿš€ @@ -192,7 +167,7 @@ q: str = Query(default="rick") ## ะ”ะพะดะฐะฒะฐะฝะฝั ั€ะตะณัƒะปัั€ะฝะธั… ะฒะธั€ะฐะทั–ะฒ { #add-regular-expressions } -ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ regular expression `pattern`, ัะบะพะผัƒ ะผะฐั” ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€: +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ั€ะตะณัƒะปัั€ะฝะธะน ะฒะธั€ะฐะท `pattern`, ัะบะพะผัƒ ะผะฐั” ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -212,7 +187,7 @@ q: str = Query(default="rick") ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะพะณะพะปะพัะธั‚ะธ query ะฟะฐั€ะฐะผะตั‚ั€ `q` ะท `min_length` `3` ั– ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | ะŸั€ะธะผั–ั‚ะบะฐ @@ -242,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None ะขะพะผัƒ, ัะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพะณะพะปะพัะธั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ัะบ ะพะฑะพะฒโ€™ัะทะบะพะฒะต ะฟั–ะด ั‡ะฐั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `Query`, ะฟั€ะพัั‚ะพ ะฝะต ะฒะบะฐะทัƒะนั‚ะต ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### ะžะฑะพะฒโ€™ัะทะบะพะฒะธะน, ะผะพะถะต ะฑัƒั‚ะธ `None` { #required-can-be-none } @@ -266,7 +241,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะบั–ะปัŒะบะฐ ะทะฝะฐั‡ะตะฝัŒ `q` *query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ* (`foo` ั– `bar`) ัƒ ะฒะธะณะปัะดั– Python `list` ัƒ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ัƒ *ะฟะฐั€ะฐะผะตั‚ั€ั– ั„ัƒะฝะบั†ั–ั—* `q`. +ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะบั–ะปัŒะบะฐ ะทะฝะฐั‡ะตะฝัŒ `q` query ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ (`foo` ั– `bar`) ัƒ ะฒะธะณะปัะดั– Python `list` ัƒ ะฒะฐัˆั–ะน ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– ั„ัƒะฝะบั†ั–ั— `q`. ะžั‚ะถะต, ะฒั–ะดะฟะพะฒั–ะดัŒ ะฝะฐ ั†ะตะน URL ะฑัƒะดะต: @@ -293,7 +268,7 @@ http://localhost:8000/items/?q=foo&q=bar ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `list`, ัะบั‰ะพ ะถะพะดะฝะต ะทะฝะฐั‡ะตะฝะฝั ะฝะต ะฑัƒะปะพ ะฟะตั€ะตะดะฐะฝะต: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะทะฐ ะฟะพัะธะปะฐะฝะฝัะผ: @@ -316,7 +291,7 @@ http://localhost:8000/items/ ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `list` ะฝะฐะฟั€ัะผัƒ ะทะฐะผั–ัั‚ัŒ `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | ะŸั€ะธะผั–ั‚ะบะฐ @@ -372,7 +347,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ะฒะฐะผ ะฑั–ะปัŒัˆะต ะฝะต ะฟะพะดะพะฑะฐั”ั‚ัŒัั ั†ะตะน ะฟะฐั€ะฐะผะตั‚ั€. -ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะทะฐะปะธัˆะธั‚ะธ ะนะพะณะพ ะฝะฐ ะดะตัะบะธะน ั‡ะฐั, ะพัะบั–ะปัŒะบะธ ะฝะธะผ ะบะพั€ะธัั‚ัƒัŽั‚ัŒัั ะบะปั–ั”ะฝั‚ะธ, ะฐะปะต ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ั‡ั–ั‚ะบะพ ะฟะพะบะฐะทัƒะฒะฐะปะฐ, ั‰ะพ ะฒั–ะฝ ั” deprecated. +ะ’ะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะทะฐะปะธัˆะธั‚ะธ ะนะพะณะพ ะฝะฐ ะดะตัะบะธะน ั‡ะฐั, ะพัะบั–ะปัŒะบะธ ะฝะธะผ ะบะพั€ะธัั‚ัƒัŽั‚ัŒัั ะบะปั–ั”ะฝั‚ะธ, ะฐะปะต ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ั‡ั–ั‚ะบะพ ะฟะพะบะฐะทัƒะฒะฐะปะฐ, ั‰ะพ ะฒั–ะฝ ั” ะทะฐัั‚ะฐั€ั–ะปะธะน. ะขะพะดั– ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `deprecated=True` ะดะพ `Query`: @@ -390,9 +365,9 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## ะšะฐัั‚ะพะผะฝะฐ ะฒะฐะปั–ะดะฐั†ั–ั { #custom-validation } -ะœะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั€ะพะฒะตัั‚ะธ **ะบะฐัั‚ะพะผะฝัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ**, ัะบัƒ ะฝะต ะผะพะถะฝะฐ ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ะฟะพะบะฐะทะฐะฝะธั… ะฒะธั‰ะต. +ะœะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั€ะพะฒะตัั‚ะธ ะบะฐัั‚ะพะผะฝัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ, ัะบัƒ ะฝะต ะผะพะถะฝะฐ ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ะฟะพะบะฐะทะฐะฝะธั… ะฒะธั‰ะต. -ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ **ะบะฐัั‚ะพะผะฝัƒ ั„ัƒะฝะบั†ั–ัŽ-ะฒะฐะปั–ะดะฐั‚ะพั€**, ัะบะฐ ะฑัƒะดะต ะทะฐัั‚ะพัะพะฒะฐะฝะฐ ะฟั–ัะปั ะทะฒะธั‡ะฐะนะฝะพั— ะฒะฐะปั–ะดะฐั†ั–ั— (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั–ัะปั ะฟะตั€ะตะฒั–ั€ะบะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ั” ั‚ะธะฟะพะผ `str`). +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะฐัั‚ะพะผะฝัƒ ั„ัƒะฝะบั†ั–ัŽ-ะฒะฐะปั–ะดะฐั‚ะพั€, ัะบะฐ ะฑัƒะดะต ะทะฐัั‚ะพัะพะฒะฐะฝะฐ ะฟั–ัะปั ะทะฒะธั‡ะฐะนะฝะพั— ะฒะฐะปั–ะดะฐั†ั–ั— (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั–ัะปั ะฟะตั€ะตะฒั–ั€ะบะธ, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ั” ั‚ะธะฟะพะผ `str`). ะฆะต ะผะพะถะฝะฐ ะดะพััะณั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Pydantic's `AfterValidator` ะฒ ัะตั€ะตะดะธะฝั– `Annotated`. @@ -402,7 +377,7 @@ Pydantic ั‚ะฐะบะพะถ ะผะฐั” ISBN ะฐะฑะพ ะท `imdb-` ะดะปั ID URL ั„ั–ะปัŒะผัƒ ะฝะฐ IMDB: +ะะฐะฟั€ะธะบะปะฐะด, ั†ะตะน ะบะฐัั‚ะพะผะฝะธะน ะฒะฐะปั–ะดะฐั‚ะพั€ ะฟะตั€ะตะฒั–ั€ัั”, ั‡ะธ ะฟะพั‡ะธะฝะฐั”ั‚ัŒัั ID ะตะปะตะผะตะฝั‚ะฐ ะท `isbn-` ะดะปั ะฝะพะผะตั€ะฐ ะบะฝะธะณะธ ISBN ะฐะฑะพ ะท `imdb-` ะดะปั ID URL ั„ั–ะปัŒะผัƒ ะฝะฐ IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -414,15 +389,15 @@ Pydantic ั‚ะฐะบะพะถ ะผะฐั” iterable object ั–ะท ะบะพั€ั‚ะตะถะฐะผะธ, ั‰ะพ ะผั–ัั‚ัั‚ัŒ ะบะปัŽั‡ ั– ะทะฝะฐั‡ะตะฝะฝั ะดะปั ะบะพะถะฝะพะณะพ ะตะปะตะผะตะฝั‚ะฐ ัะปะพะฒะฝะธะบะฐ. +ะ—ะฐ ะดะพะฟะพะผะพะณะพัŽ `data.items()` ะผะธ ะพั‚ั€ะธะผัƒั”ะผะพ ั–ั‚ะตั€ะฐะฑะตะปัŒะฝะธะน ะพะฑ'ั”ะบั‚ ั–ะท ะบะพั€ั‚ะตะถะฐะผะธ, ั‰ะพ ะผั–ัั‚ัั‚ัŒ ะบะปัŽั‡ ั– ะทะฝะฐั‡ะตะฝะฝั ะดะปั ะบะพะถะฝะพะณะพ ะตะปะตะผะตะฝั‚ะฐ ัะปะพะฒะฝะธะบะฐ. -ะœะธ ะฟะตั€ะตั‚ะฒะพั€ัŽั”ะผะพ ั†ะตะน iterable object ัƒ ะทะฒะธั‡ะฐะนะฝะธะน `list` ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `list(data.items())`. +ะœะธ ะฟะตั€ะตั‚ะฒะพั€ัŽั”ะผะพ ั†ะตะน ั–ั‚ะตั€ะฐะฑะตะปัŒะฝะธะน ะพะฑ'ั”ะบั‚ ัƒ ะทะฒะธั‡ะฐะนะฝะธะน `list` ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `list(data.items())`. -ะŸะพั‚ั–ะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `random.choice()`, ะผะธ ะผะพะถะตะผะพ ะพั‚ั€ะธะผะฐั‚ะธ **ะฒะธะฟะฐะดะบะพะฒะต ะทะฝะฐั‡ะตะฝะฝั** ะทั– ัะฟะธัะบัƒ, ั‚ะพะฑั‚ะพ ะพั‚ั€ะธะผัƒั”ะผะพ ะบะพั€ั‚ะตะถ ั–ะท `(id, name)`. ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ั‰ะพััŒ ะฝะฐ ะทั€ะฐะทะพะบ `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +ะŸะพั‚ั–ะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `random.choice()`, ะผะธ ะผะพะถะตะผะพ ะพั‚ั€ะธะผะฐั‚ะธ ะฒะธะฟะฐะดะบะพะฒะต ะทะฝะฐั‡ะตะฝะฝั ะทั– ัะฟะธัะบัƒ, ั‚ะพะฑั‚ะพ ะพั‚ั€ะธะผัƒั”ะผะพ ะบะพั€ั‚ะตะถ ั–ะท `(id, name)`. ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ั‰ะพััŒ ะฝะฐ ะทั€ะฐะทะพะบ `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -ะ”ะฐะปั– ะผะธ **ะฟั€ะธัะฒะพัŽั”ะผะพ ั†ั– ะดะฒะฐ ะทะฝะฐั‡ะตะฝะฝั** ะบะพั€ั‚ะตะถัƒ ะทะผั–ะฝะฝะธะผ `id` ั– `name`. +ะ”ะฐะปั– ะผะธ ะฟั€ะธัะฒะพัŽั”ะผะพ ั†ั– ะดะฒะฐ ะทะฝะฐั‡ะตะฝะฝั ะบะพั€ั‚ะตะถัƒ ะทะผั–ะฝะฝะธะผ `id` ั– `name`. ะขะพะถ, ัะบั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฝะต ะฒะบะฐะทะฐะฒ ID ะตะปะตะผะตะฝั‚ะฐ, ะฒั–ะฝ ะฒัะต ะพะดะฝะพ ะพั‚ั€ะธะผะฐั” ะฒะธะฟะฐะดะบะพะฒัƒ ั€ะตะบะพะผะตะฝะดะฐั†ั–ัŽ. -...ะผะธ ั€ะพะฑะธะผะพ ะฒัะต ั†ะต ะฒ **ะพะดะฝะพะผัƒ ะฟั€ะพัั‚ะพะผัƒ ั€ัะดะบัƒ**. ๐Ÿคฏ ะฅั–ะฑะฐ ะฒะธ ะฝะต ะปัŽะฑะธั‚ะต Python? ๐Ÿ +...ะผะธ ั€ะพะฑะธะผะพ ะฒัะต ั†ะต ะฒ ะพะดะฝะพะผัƒ ะฟั€ะพัั‚ะพะผัƒ ั€ัะดะบัƒ. ๐Ÿคฏ ะฅั–ะฑะฐ ะฒะธ ะฝะต ะปัŽะฑะธั‚ะต Python? ๐Ÿ {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} diff --git a/docs/uk/docs/tutorial/query-params.md b/docs/uk/docs/tutorial/query-params.md index a9068aa8f9..4888f4c461 100644 --- a/docs/uk/docs/tutorial/query-params.md +++ b/docs/uk/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ ะšะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ั–ะฝัˆั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั„ัƒะฝะบั†ั–ั—, ัะบั– ะฝะต ั” ั‡ะฐัั‚ะธะฝะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ัˆะปัั…ัƒ, ะฒะพะฝะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒัŽั‚ัŒัั ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ยซqueryยป. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} Query โ€” ั†ะต ะฝะฐะฑั–ั€ ะฟะฐั€ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั, ั‰ะพ ะนะดัƒั‚ัŒ ะฟั–ัะปั ัะธะผะฒะพะปัƒ `?` ะฒ URL, ั€ะพะทะดั–ะปะตะฝั– ัะธะผะฒะพะปะฐะผะธ `&`. @@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ะฃะฒะตััŒ ั‚ะพะน ัะฐะผะธะน ะฟั€ะพั†ะตั, ัะบะธะน ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั ะดะพ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ัˆะปัั…ัƒ, ั‚ะฐะบะพะถ ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั ะดะพ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ query: * ะŸั–ะดั‚ั€ะธะผะบะฐ ะฒ ั€ะตะดะฐะบั‚ะพั€ั– (ะพั‡ะตะฒะธะดะฝะพ) -* ยซparsingยป ะดะฐะฝะธั… +* ยซะฟะฐั€ัะธะฝะณยป ะดะฐะฝะธั… * ะ’ะฐะปั–ะดะฐั†ั–ั ะดะฐะฝะธั… * ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั @@ -65,7 +65,7 @@ http://127.0.0.1:8000/items/?skip=20 ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะฐั€ะฐะผะตั‚ั€ ั„ัƒะฝะบั†ั–ั— `q` ะฑัƒะดะต ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ ั– ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะผะฐั‚ะธะผะต ะทะฝะฐั‡ะตะฝะฝั `None`. -/// check | ะŸั€ะธะผั–ั‚ะบะฐ +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต ะขะฐะบะพะถ ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ **FastAPI** ะดะพัั‚ะฐั‚ะฝัŒะพ ั€ะพะทัƒะผะฝะธะน, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ, ั‰ะพ ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ `item_id` ั” ะฟะฐั€ะฐะผะตั‚ั€ะพะผ ัˆะปัั…ัƒ, ะฐ `q` โ€” ะฝั–, ะพั‚ะถะต, ั†ะต ะฟะฐั€ะฐะผะตั‚ั€ query. @@ -128,7 +128,7 @@ http://127.0.0.1:8000/items/foo?short=yes ะะปะต ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะทั€ะพะฑะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ query ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ, ะฟั€ะพัั‚ะพ ะฝะต ะฒะบะฐะทัƒะนั‚ะต ะดะปั ะฝัŒะพะณะพ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} ะขัƒั‚ ะฟะฐั€ะฐะผะตั‚ั€ query `needy` โ€” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ query ั‚ะธะฟัƒ `str`. @@ -183,6 +183,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip | ะŸะพั€ะฐะดะฐ -ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Enum` ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะท [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}. +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Enum` ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะท [ะŸะฐั€ะฐะผะตั‚ั€ะธ ัˆะปัั…ัƒ](path-params.md#predefined-values){.internal-link target=_blank}. /// diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md index a6ff70dc09..8e64b12c38 100644 --- a/docs/uk/docs/tutorial/request-files.md +++ b/docs/uk/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ $ pip install python-multipart ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `File` ั‚ะฐ `UploadFile` ะท `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## ะ’ะธะทะฝะฐั‡ะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ `File` { #define-file-parameters } ะกั‚ะฒะพั€ั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ะธ ั„ะฐะนะปั–ะฒ ั‚ะฐะบ ัะฐะผะพ ัะบ ะฒะธ ะฑ ัั‚ะฒะพั€ัŽะฒะฐะปะธ `Body` ะฐะฑะพ `Form`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั @@ -54,7 +54,7 @@ $ pip install python-multipart ะ’ะธะทะฝะฐั‡ั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ ั„ะฐะนะปัƒ ะท ั‚ะธะฟะพะผ `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `UploadFile` ะผะฐั” ะบั–ะปัŒะบะฐ ะฟะตั€ะตะฒะฐะณ ะฟะตั€ะตะด `bytes`: @@ -121,7 +121,7 @@ contents = myfile.file.read() ะะปะต ัะบั‰ะพ ั„ะพั€ะผะฐ ะผั–ัั‚ะธั‚ัŒ ั„ะฐะนะปะธ, ะฒะพะฝะฐ ะบะพะดัƒั”ั‚ัŒัั ัะบ `multipart/form-data`. ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `File`, **FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะนะปะธ ะท ะฟั€ะฐะฒะธะปัŒะฝะพั— ั‡ะฐัั‚ะธะฝะธ ั‚ั–ะปะฐ. -ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ั– ั‚ะธะฟะธ ะบะพะดัƒะฒะฐะฝะฝั ั‚ะฐ ั„ะพั€ะผะพะฒั– ะฟะพะปั, ะพะทะฝะฐะนะพะผั‚ะตัั ะท MDN web docs ะดะปั POST. +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ั– ั‚ะธะฟะธ ะบะพะดัƒะฒะฐะฝะฝั ั‚ะฐ ั„ะพั€ะผะพะฒั– ะฟะพะปั, ะพะทะฝะฐะนะพะผั‚ะตัั ะท MDN web docs ะดะปั POST. /// @@ -143,7 +143,7 @@ contents = myfile.file.read() ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `File()` ั€ะฐะทะพะผ ั–ะท `UploadFile`, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะผะตั‚ะฐะดะฐะฝั–: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## ะ—ะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะบั–ะปัŒะบะพั… ั„ะฐะนะปั–ะฒ { #multiple-file-uploads } @@ -153,7 +153,7 @@ contents = myfile.file.read() ะฉะพะฑ ั†ะต ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ, ะฟะพั‚ั€ั–ะฑะฝะพ ะพะณะพะปะพัะธั‚ะธ ัะฟะธัะพะบ `bytes` ะฐะฑะพ `UploadFile`: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} ะ’ะธ ะพั‚ั€ะธะผะฐั”ั‚ะต, ัะบ ั– ะฑัƒะปะพ ะพะณะพะปะพัˆะตะฝะพ, `list` ั–ะท `bytes` ะฐะฑะพ `UploadFile`. @@ -169,7 +169,7 @@ contents = myfile.file.read() ะขะฐะบ ัะฐะผะพ ัะบ ั– ั€ะฐะฝั–ัˆะต, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `File()`, ั‰ะพะฑ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฝะฐะฒั–ั‚ัŒ ะดะปั `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## ะŸั–ะดััƒะผะพะบ { #recap } diff --git a/docs/uk/docs/tutorial/request-form-models.md b/docs/uk/docs/tutorial/request-form-models.md index 1bfd368d60..86510be589 100644 --- a/docs/uk/docs/tutorial/request-form-models.md +++ b/docs/uk/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ $ pip install python-multipart ะ’ะฐะผ ะฟั€ะพัั‚ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะพะณะพะปะพัะธั‚ะธ **Pydantic-ะผะพะดะตะปัŒ** ะท ะฟะพะปัะผะธ, ัะบั– ะฒะธ ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ัะบ **ะฟะพะปั ั„ะพั€ะผะธ**, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ัะบ `Form`: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** **ะฒะธั‚ัะณะฝะต** ะดะฐะฝั– ะดะปั **ะบะพะถะฝะพะณะพ ะฟะพะปั** ะท **ั„ะพั€ะผะพะฒะธั… ะดะฐะฝะธั…** ัƒ ะทะฐะฟะธั‚ั– ั‚ะฐ ะฝะฐะดะฐัั‚ัŒ ะฒะฐะผ Pydantic-ะผะพะดะตะปัŒ, ัะบัƒ ะฒะธ ะฒะธะทะฝะฐั‡ะธะปะธ. @@ -48,7 +48,7 @@ $ pip install python-multipart ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ Pydantic-ะผะพะดะตะปั–, ั‰ะพะฑ ะทะฐะฑะพั€ะพะฝะธั‚ะธ `forbid` ะฑัƒะดัŒ-ัะบั– ะดะพะดะฐั‚ะบะพะฒั– `extra` ะฟะพะปั: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} ะฏะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฝะฐะดั–ัะปะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะดะฐะฝั–, ะฒั–ะฝ ะพั‚ั€ะธะผะฐั” **ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฟะพะผะธะปะบะพัŽ**. diff --git a/docs/uk/docs/tutorial/request-forms-and-files.md b/docs/uk/docs/tutorial/request-forms-and-files.md index e809bee225..817769b714 100644 --- a/docs/uk/docs/tutorial/request-forms-and-files.md +++ b/docs/uk/docs/tutorial/request-forms-and-files.md @@ -6,7 +6,7 @@ ะฉะพะฑ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ั„ะฐะนะปะธ ั‚ะฐ/ะฐะฑะพ ะดะฐะฝั– ั„ะพั€ะผะธ, ัะฟะพั‡ะฐั‚ะบัƒ ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ `python-multipart`. -ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะ’ะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ, ะฐ ะฟะพั‚ั–ะผ ะฒัั‚ะฐะฝะพะฒะธะปะธ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ, ะฐ ะฟะพั‚ั–ะผ ะฒัั‚ะฐะฝะพะฒะธะปะธ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: ```console $ pip install python-multipart @@ -16,15 +16,15 @@ $ pip install python-multipart ## ะ†ะผะฟะพั€ั‚ `File` ั‚ะฐ `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## ะžะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ `File` ั‚ะฐ `Form` { #define-file-and-form-parameters } ะกั‚ะฒะพั€ั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ะธ ั„ะฐะนะปั–ะฒ ั‚ะฐ ั„ะพั€ะผะธ ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะดะปั `Body` ะฐะฑะพ `Query`: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} -ะคะฐะนะปะธ ั‚ะฐ ะฟะพะปั ั„ะพั€ะผะธ ะฑัƒะดัƒั‚ัŒ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ัะบ ั„ะพั€ะผะพะฒั– ะดะฐะฝั–, ั– ะ’ะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ั„ะฐะนะปะธ ั‚ะฐ ะฟะพะปั ั„ะพั€ะผะธ. +ะคะฐะนะปะธ ั‚ะฐ ะฟะพะปั ั„ะพั€ะผะธ ะฑัƒะดัƒั‚ัŒ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ัะบ ั„ะพั€ะผะพะฒั– ะดะฐะฝั–, ั– ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ั„ะฐะนะปะธ ั‚ะฐ ะฟะพะปั ั„ะพั€ะผะธ. ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะดะตัะบั– ั„ะฐะนะปะธ ัะบ `bytes`, ะฐ ะดะตัะบั– ัะบ `UploadFile`. diff --git a/docs/uk/docs/tutorial/request-forms.md b/docs/uk/docs/tutorial/request-forms.md index 2a22ad922a..7f0c6e9bb3 100644 --- a/docs/uk/docs/tutorial/request-forms.md +++ b/docs/uk/docs/tutorial/request-forms.md @@ -1,6 +1,6 @@ # ะ”ะฐะฝั– ั„ะพั€ะผะธ { #form-data } -ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฟะพะปั ั„ะพั€ะผะธ ะทะฐะผั–ัั‚ัŒ JSON, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Form`. +ะšะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฟะพะปั ั„ะพั€ะผะธ ะทะฐะผั–ัั‚ัŒ JSON, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Form`. /// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั @@ -18,17 +18,17 @@ $ pip install python-multipart ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `Form` ะท `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## ะžะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ `Form` { #define-form-parameters } ะกั‚ะฒะพั€ัŽะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ะธ ั„ะพั€ะผะธ ั‚ะฐะบ ัะฐะผะพ ัะบ ะฒะธ ะฑ ัั‚ะฒะพั€ัŽะฒะฐะปะธ `Body` ะฐะฑะพ `Query`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} -ะะฐะฟั€ะธะบะปะฐะด, ะพะดะธะฝ ะทั– ัะฟะพัะพะฑั–ะฒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OAuth2 (ั‚ะฐะบ ะทะฒะฐะฝะธะน "password flow") ะฒะธะผะฐะณะฐั” ะฝะฐะดัะธะปะฐั‚ะธ `username` ั‚ะฐ `password` ัะบ ะฟะพะปั ั„ะพั€ะผะธ. +ะะฐะฟั€ะธะบะปะฐะด, ะพะดะธะฝ ะทั– ัะฟะพัะพะฑั–ะฒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OAuth2 (ั‚ะฐะบ ะทะฒะฐะฝะธะน ยซpassword flowยป) ะฒะธะผะฐะณะฐั” ะฝะฐะดัะธะปะฐั‚ะธ `username` ั‚ะฐ `password` ัะบ ะฟะพะปั ั„ะพั€ะผะธ. -spec ะฒะธะผะฐะณะฐั”, ั‰ะพะฑ ั†ั– ะฟะพะปั ะผะฐะปะธ ั‚ะพั‡ะฝั– ะฝะฐะทะฒะธ `username` ั– `password` ั‚ะฐ ะฝะฐะดัะธะปะฐะปะธัั ัƒ ะฒะธะณะปัะดั– ะฟะพะปั–ะฒ ั„ะพั€ะผะธ, ะฐ ะฝะต JSON. +ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั ะฒะธะผะฐะณะฐั”, ั‰ะพะฑ ั†ั– ะฟะพะปั ะผะฐะปะธ ั‚ะพั‡ะฝั– ะฝะฐะทะฒะธ `username` ั– `password` ั‚ะฐ ะฝะฐะดัะธะปะฐะปะธัั ัƒ ะฒะธะณะปัะดั– ะฟะพะปั–ะฒ ั„ะพั€ะผะธ, ะฐ ะฝะต JSON. ะ— `Form` ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั‚ั– ะถ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั—, ั‰ะพ ั– ะท `Body` (ั‚ะฐ `Query`, `Path`, `Cookie`), ะฒะบะปัŽั‡ะฐัŽั‡ะธ ะฒะฐะปั–ะดะฐั†ั–ัŽ, ะฟั€ะธะบะปะฐะดะธ, ะฟัะตะฒะดะพะฝั–ะผะธ (ะฝะฐะฟั€ะธะบะปะฐะด, `user-name` ะทะฐะผั–ัั‚ัŒ `username`) ั‚ะพั‰ะพ. @@ -44,19 +44,19 @@ $ pip install python-multipart /// -## ะŸั€ะพ "ะฟะพะปั ั„ะพั€ะผะธ" { #about-form-fields } +## ะŸั€ะพ ยซะฟะพะปั ั„ะพั€ะผะธยป { #about-form-fields } -HTML-ั„ะพั€ะผะธ (`
`) ะฝะฐะดัะธะปะฐัŽั‚ัŒ ะดะฐะฝั– ะฝะฐ ัะตั€ะฒะตั€ ัƒ "ัะฟะตั†ั–ะฐะปัŒะฝะพะผัƒ" ะบะพะดัƒะฒะฐะฝะฝั–, ัะบะต ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด JSON. +HTML-ั„ะพั€ะผะธ (`
`) ะฝะฐะดัะธะปะฐัŽั‚ัŒ ะดะฐะฝั– ะฝะฐ ัะตั€ะฒะตั€ ัƒ ยซัะฟะตั†ั–ะฐะปัŒะฝะพะผัƒยป ะบะพะดัƒะฒะฐะฝะฝั–, ัะบะต ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด JSON. **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ั‚ะต, ั‰ะพะฑ ะทั‡ะธั‚ะฐั‚ะธ ั†ั– ะดะฐะฝั– ะท ะฟั€ะฐะฒะธะปัŒะฝะพะณะพ ะผั–ัั†ั, ะฐ ะฝะต ะท JSON. /// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– -ะ”ะฐะฝั– ะท ั„ะพั€ะผ ะทะฐะทะฒะธั‡ะฐะน ะบะพะดัƒัŽั‚ัŒัั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ "ั‚ะธะฟัƒ ะผะตะดั–ะฐ" `application/x-www-form-urlencoded`. +ะ”ะฐะฝั– ะท ั„ะพั€ะผ ะทะฐะทะฒะธั‡ะฐะน ะบะพะดัƒัŽั‚ัŒัั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ยซั‚ะธะฟัƒ ะผะตะดั–ะฐยป `application/x-www-form-urlencoded`. ะะปะต ัะบั‰ะพ ั„ะพั€ะผะฐ ะผั–ัั‚ะธั‚ัŒ ั„ะฐะนะปะธ, ะฒะพะฝะฐ ะบะพะดัƒั”ั‚ัŒัั ัะบ `multipart/form-data`. ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตัั ะฟั€ะพ ะพะฑั€ะพะฑะบัƒ ั„ะฐะนะปั–ะฒ ัƒ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั–. -ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ั– ะบะพะดัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะพะปั ั„ะพั€ะผ, ะทะฒะตั€ะฝั–ั‚ัŒัั ะดะพ MDN ะฒะตะฑะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะดะปั POST. +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ั– ะบะพะดัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะพะปั ั„ะพั€ะผ, ะทะฒะตั€ะฝั–ั‚ัŒัั ะดะพ MDN ะฒะตะฑะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะดะปั POST. /// diff --git a/docs/uk/docs/tutorial/response-model.md b/docs/uk/docs/tutorial/response-model.md index 2fcad94387..fcf765c9da 100644 --- a/docs/uk/docs/tutorial/response-model.md +++ b/docs/uk/docs/tutorial/response-model.md @@ -81,7 +81,7 @@ FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต ั†ะตะน `response_model` ะดะปั ะฒะธะบ $ pip install email-validator ``` -or with: +ะฐะฑะพ ั‚ะฐะบ: ```console $ pip install "pydantic[email]" @@ -183,7 +183,7 @@ FastAPI ะฒะธะบะพะฝัƒั” ะบั–ะปัŒะบะฐ ะฒะฝัƒั‚ั€ั–ัˆะฝั–ั… ะพะฟะตั€ะฐั†ั–ะน ะท Pyd ะะฐะนะฟะพัˆะธั€ะตะฝั–ัˆะธะผ ะฒะธะฟะฐะดะบะพะผ ะฑัƒะดะต [ะฟะพะฒะตั€ะฝะตะฝะฝั Response ะฝะฐะฟั€ัะผัƒ, ัะบ ะฟะพััะฝัŽั”ั‚ัŒัั ะฟั–ะทะฝั–ัˆะต ัƒ ั€ะพะทัˆะธั€ะตะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} ะฆะตะน ะฟั€ะพัั‚ะธะน ะฒะธะฟะฐะดะพะบ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั”ั‚ัŒัั FastAPI, ั‚ะพะผัƒ ั‰ะพ ะฐะฝะพั‚ะฐั†ั–ั ั‚ะธะฟัƒ ะฟะพะฒะตั€ะฝะตะฝะฝั โ€” ั†ะต ะบะปะฐั (ะฐะฑะพ ะฟั–ะดะบะปะฐั) `Response`. @@ -193,7 +193,7 @@ FastAPI ะฒะธะบะพะฝัƒั” ะบั–ะปัŒะบะฐ ะฒะฝัƒั‚ั€ั–ัˆะฝั–ั… ะพะฟะตั€ะฐั†ั–ะน ะท Pyd ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟั–ะดะบะปะฐั `Response` ะฒ ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟัƒ: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} ะฆะต ั‚ะตะถ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต, ะฑะพ `RedirectResponse` โ€” ะฟั–ะดะบะปะฐั `Response`, ั– FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะธั‚ัŒ ั†ะตะน ะฟั€ะพัั‚ะธะน ะฒะธะฟะฐะดะพะบ. @@ -201,7 +201,7 @@ FastAPI ะฒะธะบะพะฝัƒั” ะบั–ะปัŒะบะฐ ะฒะฝัƒั‚ั€ั–ัˆะฝั–ั… ะพะฟะตั€ะฐั†ั–ะน ะท Pyd ะะปะต ะบะพะปะธ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ัะบะธะนััŒ ั–ะฝัˆะธะน ะดะพะฒั–ะปัŒะฝะธะน ะพะฑโ€™ั”ะบั‚, ั‰ะพ ะฝะต ั” ะฒะฐะปั–ะดะฝะธะผ ั‚ะธะฟะพะผ Pydantic (ะฝะฐะฟั€ะธะบะปะฐะด, ะพะฑโ€™ั”ะบั‚ ะฑะฐะทะธ ะดะฐะฝะธั…), ั– ะฐะฝะพั‚ัƒั”ั‚ะต ะนะพะณะพ ั‚ะฐะบ ัƒ ั„ัƒะฝะบั†ั–ั—, FastAPI ัะฟั€ะพะฑัƒั” ัั‚ะฒะพั€ะธั‚ะธ ะผะพะดะตะปัŒ ะฒั–ะดะฟะพะฒั–ะดั– Pydantic ะฝะฐ ะพัะฝะพะฒั– ั†ั–ั”ั— ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟัƒ ั– ั†ะต ะทะฐะฒะตั€ัˆะธั‚ัŒัั ะฟะพะผะธะปะบะพัŽ. -ะขะต ัะฐะผะต ัั‚ะฐะฝะตั‚ัŒัั, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะฐั”ั‚ะต union ะผั–ะถ ั€ั–ะทะฝะธะผะธ ั‚ะธะฟะฐะผะธ, ะดะต ะพะดะธะฝ ะฐะฑะพ ะฑั–ะปัŒัˆะต ะฝะต ั” ะฒะฐะปั–ะดะฝะธะผะธ ั‚ะธะฟะฐะผะธ Pydantic, ะฝะฐะฟั€ะธะบะปะฐะด, ั†ะต ะทะฐะฒะตั€ัˆะธั‚ัŒัั ะฟะพะผะธะปะบะพัŽ ๐Ÿ’ฅ: +ะขะต ัะฐะผะต ัั‚ะฐะฝะตั‚ัŒัั, ัะบั‰ะพ ัƒ ะฒะฐั ะฑัƒะดะต ะพะฑ'ั”ะดะฝะฐะฝะฝั ะผั–ะถ ั€ั–ะทะฝะธะผะธ ั‚ะธะฟะฐะผะธ, ะดะต ะพะดะธะฝ ะฐะฑะพ ะฑั–ะปัŒัˆะต ะฝะต ั” ะฒะฐะปั–ะดะฝะธะผะธ ั‚ะธะฟะฐะผะธ Pydantic, ะฝะฐะฟั€ะธะบะปะฐะด, ั†ะต ะทะฐะฒะตั€ัˆะธั‚ัŒัั ะฟะพะผะธะปะบะพัŽ ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md index 5a08ee46b5..c9ceb8f508 100644 --- a/docs/uk/docs/tutorial/response-status-code.md +++ b/docs/uk/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * ั‚ะพั‰ะพ. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | ะŸั€ะธะผั–ั‚ะบะฐ @@ -66,7 +66,7 @@ FastAPI ะทะฝะฐั” ะฟั€ะพ ั†ะต ั– ัั‚ะฒะพั€ะธั‚ัŒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ OpenAP /// tip | ะŸะพั€ะฐะดะฐ -ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะบะพะถะตะฝ ะบะพะด ัั‚ะฐั‚ัƒััƒ ั– ะดะปั ั‡ะพะณะพ ะฟั€ะธะทะฝะฐั‡ะตะฝะธะน ะบะพะถะตะฝ ั–ะท ะฝะธั…, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ MDN ะฟั€ะพ HTTP ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ. +ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะบะพะถะตะฝ ะบะพะด ัั‚ะฐั‚ัƒััƒ ั– ะดะปั ั‡ะพะณะพ ะฟั€ะธะทะฝะฐั‡ะตะฝะธะน ะบะพะถะตะฝ ั–ะท ะฝะธั…, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ MDN ะฟั€ะพ HTTP ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ. /// @@ -74,7 +74,7 @@ FastAPI ะทะฝะฐั” ะฟั€ะพ ั†ะต ั– ัั‚ะฒะพั€ะธั‚ัŒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ OpenAP ะ ะพะทะณะปัะฝะตะผะพ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฟั€ะธะบะปะฐะด ั‰ะต ั€ะฐะท: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` โ€” ั†ะต ะบะพะด ัั‚ะฐั‚ัƒััƒ ะดะปั ยซCreatedยป. @@ -82,7 +82,7 @@ FastAPI ะทะฝะฐั” ะฟั€ะพ ั†ะต ั– ัั‚ะฒะพั€ะธั‚ัŒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ OpenAP ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทั€ัƒั‡ะฝั– ะทะผั–ะฝะฝั– ะท `fastapi.status`. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} ะ’ะพะฝะธ โ€” ะฟั€ะพัั‚ะพ ะดะปั ะทั€ัƒั‡ะฝะพัั‚ั–, ะผั–ัั‚ัั‚ัŒ ั‚ะต ัะฐะผะต ั‡ะธัะปะพ, ะฐะปะต ั‚ะฐะบ ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ะฐะฒั‚ะพะทะฐะฟะพะฒะฝะตะฝะฝัะผ ั€ะตะดะฐะบั‚ะพั€ะฐ, ั‰ะพะฑ ะทะฝะฐะนั‚ะธ ั—ั…: diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md index 54608c2ab1..38ce0eb303 100644 --- a/docs/uk/docs/tutorial/schema-extra-example.md +++ b/docs/uk/docs/tutorial/schema-extra-example.md @@ -40,7 +40,7 @@ OpenAPI 3.1.0 (ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท F {* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} -## `examples` ัƒ JSON-ัั…ะตะผั– โ€” OpenAPI { #examples-in-json-schema-openapi } +## `examples` ัƒ JSON-ัั…ะตะผั– - OpenAPI { #examples-in-json-schema-openapi } ะŸั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ะฑัƒะดัŒ-ะบะพะณะพ ะท ะฝะฐัั‚ัƒะฟะฝะพะณะพ: @@ -74,7 +74,7 @@ OpenAPI 3.1.0 (ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท F ะšะพะปะธ ะ’ะธ ั†ะต ั€ะพะฑะธั‚ะต, ะฟั€ะธะบะปะฐะดะธ ะฑัƒะดัƒั‚ัŒ ั‡ะฐัั‚ะธะฝะพัŽ ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพั— **JSON-ัั…ะตะผะธ** ะดะปั ั†ะธั… ะดะฐะฝะธั… ั‚ั–ะปะฐ. -ะ’ั‚ั–ะผ, ะฝะฐ ะผะพะผะตะฝั‚ ะฝะฐะฟะธัะฐะฝะฝั ั†ัŒะพะณะพ (ั‡ะฐั ะฝะฐะฟะธัะฐะฝะฝั ั†ัŒะพะณะพ), Swagger UI โ€” ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ัะบะธะน ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ ะฒั–ะดะพะฑั€ะฐะถะตะฝะฝั UI ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— โ€” ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ะฟะพะบะฐะท ะบั–ะปัŒะบะพั… ะฟั€ะธะบะปะฐะดั–ะฒ ะดะปั ะดะฐะฝะธั… ัƒ **JSON-ัั…ะตะผั–**. ะะปะต ะฝะธะถั‡ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฟั€ะพ ะพะฑั…ั–ะดะฝะธะน ัˆะปัั…. +ะ’ั‚ั–ะผ, ะฝะฐ ั‡ะฐั ะฝะฐะฟะธัะฐะฝะฝั ั†ัŒะพะณะพ, Swagger UI โ€” ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ัะบะธะน ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ ะฒั–ะดะพะฑั€ะฐะถะตะฝะฝั UI ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— โ€” ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ะฟะพะบะฐะท ะบั–ะปัŒะบะพั… ะฟั€ะธะบะปะฐะดั–ะฒ ะดะปั ะดะฐะฝะธั… ัƒ **JSON-ัั…ะตะผั–**. ะะปะต ะฝะธะถั‡ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฟั€ะพ ะพะฑั…ั–ะดะฝะธะน ัˆะปัั…. ### ะกะฟะตั†ะธั„ั–ั‡ะฝั– ะดะปั OpenAPI `examples` { #openapi-specific-examples } diff --git a/docs/uk/docs/tutorial/security/index.md b/docs/uk/docs/tutorial/security/index.md index f1fb25178d..de09c728bc 100644 --- a/docs/uk/docs/tutorial/security/index.md +++ b/docs/uk/docs/tutorial/security/index.md @@ -73,11 +73,11 @@ OpenAPI ะฒะธะทะฝะฐั‡ะฐั” ั‚ะฐะบั– ัั…ะตะผะธ ะฑะตะทะฟะตะบะธ: * `apiKey`: ัะฟะตั†ะธั„ั–ั‡ะฝะธะน ะดะปั ะทะฐัั‚ะพััƒะฝะบัƒ ะบะปัŽั‡, ัะบะธะน ะผะพะถะต ะฟะตั€ะตะดะฐะฒะฐั‚ะธัั ั‡ะตั€ะตะท: * ะŸะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ. * ะ—ะฐะณะพะปะพะฒะพะบ. - * Cookie. + * ะšัƒะบั–. * `http`: ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ัะธัั‚ะตะผะธ HTTP-ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—, ะฒะบะปัŽั‡ะฐัŽั‡ะธ: * `bearer`: ะทะฐะณะพะปะพะฒะพะบ `Authorization` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `Bearer ` ั‚ะฐ ั‚ะพะบะตะฝะพะผ. ะฆะต ัƒัะฟะฐะดะบะพะฒะฐะฝะพ ะท OAuth2. - * HTTP Basic ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ. - * HTTP Digest ั‚ะพั‰ะพ. + * ะฑะฐะทะพะฒัƒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ HTTP. + * HTTP ะดะฐะนะดะถะตัั‚ ั‚ะพั‰ะพ. * `oauth2`: ัƒัั– ัะฟะพัะพะฑะธ ะพะฑั€ะพะฑะบะธ ะฑะตะทะฟะตะบะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ OAuth2 (ั‚ะฐะบ ะทะฒะฐะฝั– ยซะฟะพั‚ะพะบะธยป). * ะ”ะตะบั–ะปัŒะบะฐ ะท ั†ะธั… ะฟะพั‚ะพะบั–ะฒ ะฟั–ะดั…ะพะดัั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— OAuth 2.0 (ะฝะฐะฟั€ะธะบะปะฐะด, Google, Facebook, X (Twitter), GitHub ั‚ะพั‰ะพ): * `implicit` diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md index 32ca1311d2..7f45973df3 100644 --- a/docs/uk/docs/tutorial/static-files.md +++ b/docs/uk/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `StaticFiles`. * ยซะŸั–ะด'ั”ะดะฝะฐั‚ะธยป ะตะบะทะตะผะฟะปัั€ `StaticFiles()` ะท ะฒะบะฐะทะฐะฝะฝัะผ ะฝะตะพะฑั…ั–ะดะฝะพะณะพ ัˆะปัั…ัƒ. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md index 462592829f..ff32e9fb66 100644 --- a/docs/uk/docs/tutorial/testing.md +++ b/docs/uk/docs/tutorial/testing.md @@ -30,7 +30,7 @@ $ pip install httpx ะ—ะฐะฟะธััƒะนั‚ะต ะฟั€ะพัั‚ั– `assert`-ะฒะธั€ะฐะทะธ ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะผะธ ะฒะธั€ะฐะทะฐะผะธ Python, ัะบั– ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ (ั†ะต ั‚ะฐะบะพะถ ัั‚ะฐะฝะดะฐั€ั‚ ะดะปั `pytest`). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ะŸะพั€ะฐะดะฐ @@ -76,7 +76,7 @@ $ pip install httpx ะฃ ั„ะฐะนะปั– `main.py` ะทะฝะฐั…ะพะดะธั‚ัŒัั ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI**: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### ะคะฐะนะป ั‚ะตัั‚ัƒะฒะฐะฝะฝั { #testing-file } @@ -90,9 +90,9 @@ $ pip install httpx โ”‚ย ย  โ””โ”€โ”€ test_main.py ``` -ะžัะบั–ะปัŒะบะธ ั†ะตะน ั„ะฐะนะป ะทะฝะฐั…ะพะดะธั‚ัŒัั ะฒ ั‚ะพะผัƒ ะถ ะฟะฐะบะตั‚ั–, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะฝะพัะฝะธะน ั–ะผะฟะพั€ั‚, ั‰ะพะฑ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะพะฑ'ั”ะบั‚ `app` ั–ะท ะผะพะดัƒะปั `main` (`main.py`): +ะžัะบั–ะปัŒะบะธ ั†ะตะน ั„ะฐะนะป ะทะฝะฐั…ะพะดะธั‚ัŒัั ะฒ ั‚ะพะผัƒ ะถ ะฟะฐะบะตั‚ั–, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะฝะพัะฝะธะน ั–ะผะฟะพั€ั‚, ั‰ะพะฑ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะพะฑ'ั”ะบั‚ `app` ั–ะท ะผะพะดัƒะปั `main` (`main.py`): -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...ั– ะฝะฐะฟะธัะฐั‚ะธ ะบะพะด ะดะปั ั‚ะตัั‚ั–ะฒ ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ั€ะฐะฝั–ัˆะต. From 54e29fbad85d7875800b86205ad47981f41b4faa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 12:42:05 +0000 Subject: [PATCH 225/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5eec22e0b3..4f4492f7b0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for tr (update-all). PR [#14913](https://github.com/fastapi/fastapi/pull/14913) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). ### Internal From 149ef6264e822490dfbf2986abbbcb7f6645ac35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 12:42:31 +0000 Subject: [PATCH 226/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4f4492f7b0..ae5bef77fe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for uk (update-all). PR [#14914](https://github.com/fastapi/fastapi/pull/14914) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-all). PR [#14913](https://github.com/fastapi/fastapi/pull/14913) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). From eada361fa2c15b4f5f178062d89291440d651139 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 14:37:57 +0100 Subject: [PATCH 227/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(update-all)=20(#14917)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format * Add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/zh/docs/_llm-test.md | 755 ++++++++++++++++++ docs/zh/docs/about/index.md | 3 + docs/zh/docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 4 +- .../zh/docs/advanced/advanced-dependencies.md | 8 +- .../zh/docs/advanced/advanced-python-types.md | 61 ++ docs/zh/docs/advanced/async-tests.md | 10 +- docs/zh/docs/advanced/behind-a-proxy.md | 12 +- docs/zh/docs/advanced/custom-response.md | 34 +- docs/zh/docs/advanced/dataclasses.md | 2 +- docs/zh/docs/advanced/events.md | 12 +- docs/zh/docs/advanced/generate-clients.md | 10 +- docs/zh/docs/advanced/middleware.md | 8 +- docs/zh/docs/advanced/openapi-callbacks.md | 2 +- docs/zh/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 6 +- docs/zh/docs/advanced/response-cookies.md | 6 +- docs/zh/docs/advanced/response-directly.md | 4 +- docs/zh/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 6 +- docs/zh/docs/advanced/settings.md | 26 +- docs/zh/docs/advanced/sub-applications.md | 6 +- docs/zh/docs/advanced/templates.md | 2 +- docs/zh/docs/advanced/testing-dependencies.md | 1 - docs/zh/docs/advanced/testing-events.md | 4 +- docs/zh/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/zh/docs/advanced/websockets.md | 8 +- docs/zh/docs/advanced/wsgi.md | 2 +- docs/zh/docs/alternatives.md | 482 +++++++++++ docs/zh/docs/async.md | 4 +- docs/zh/docs/benchmarks.md | 2 +- docs/zh/docs/deployment/concepts.md | 2 +- docs/zh/docs/deployment/docker.md | 10 +- docs/zh/docs/deployment/fastapicloud.md | 65 ++ docs/zh/docs/deployment/https.md | 8 +- docs/zh/docs/deployment/manually.md | 6 +- docs/zh/docs/features.md | 12 +- docs/zh/docs/help-fastapi.md | 2 +- .../authentication-error-status-code.md | 17 + docs/zh/docs/how-to/conditional-openapi.md | 56 ++ docs/zh/docs/how-to/configure-swagger-ui.md | 6 +- docs/zh/docs/how-to/custom-docs-ui-assets.md | 185 +++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/zh/docs/how-to/extending-openapi.md | 80 ++ docs/zh/docs/how-to/general.md | 2 +- docs/zh/docs/how-to/graphql.md | 60 ++ ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 ++++ .../docs/how-to/separate-openapi-schemas.md | 102 +++ docs/zh/docs/how-to/testing-database.md | 7 + docs/zh/docs/index.md | 10 +- docs/zh/docs/python-types.md | 188 +---- docs/zh/docs/resources/index.md | 3 + docs/zh/docs/translation-banner.md | 11 + docs/zh/docs/tutorial/background-tasks.md | 8 +- docs/zh/docs/tutorial/bigger-applications.md | 28 +- docs/zh/docs/tutorial/body-multiple-params.md | 6 - docs/zh/docs/tutorial/body-nested-models.md | 4 +- docs/zh/docs/tutorial/body.md | 2 +- docs/zh/docs/tutorial/cookie-param-models.md | 10 +- docs/zh/docs/tutorial/cors.md | 4 +- docs/zh/docs/tutorial/debugging.md | 4 +- .../dependencies/classes-as-dependencies.md | 28 +- ...pendencies-in-path-operation-decorators.md | 12 +- .../dependencies/dependencies-with-yield.md | 24 +- .../dependencies/global-dependencies.md | 2 +- docs/zh/docs/tutorial/dependencies/index.md | 6 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/zh/docs/tutorial/encoder.md | 4 +- docs/zh/docs/tutorial/extra-models.md | 14 +- docs/zh/docs/tutorial/first-steps.md | 18 +- docs/zh/docs/tutorial/handling-errors.md | 16 +- docs/zh/docs/tutorial/metadata.md | 12 +- docs/zh/docs/tutorial/middleware.md | 4 +- .../tutorial/path-operation-configuration.md | 12 +- .../path-params-numeric-validations.md | 14 +- docs/zh/docs/tutorial/path-params.md | 30 +- .../tutorial/query-params-str-validations.md | 42 +- docs/zh/docs/tutorial/query-params.md | 13 +- docs/zh/docs/tutorial/request-files.md | 22 +- docs/zh/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 6 +- docs/zh/docs/tutorial/request-forms.md | 6 +- docs/zh/docs/tutorial/response-model.md | 6 +- docs/zh/docs/tutorial/response-status-code.md | 6 +- docs/zh/docs/tutorial/schema-extra-example.md | 2 +- docs/zh/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/zh/docs/tutorial/security/index.md | 2 +- docs/zh/docs/tutorial/security/oauth2-jwt.md | 12 +- .../docs/tutorial/security/simple-oauth2.md | 12 +- docs/zh/docs/tutorial/sql-databases.md | 2 +- docs/zh/docs/tutorial/static-files.md | 4 +- docs/zh/docs/tutorial/testing.md | 6 +- docs/zh/docs/virtual-environments.md | 10 +- 96 files changed, 2504 insertions(+), 515 deletions(-) create mode 100644 docs/zh/docs/_llm-test.md create mode 100644 docs/zh/docs/about/index.md create mode 100644 docs/zh/docs/advanced/advanced-python-types.md create mode 100644 docs/zh/docs/alternatives.md create mode 100644 docs/zh/docs/deployment/fastapicloud.md create mode 100644 docs/zh/docs/how-to/authentication-error-status-code.md create mode 100644 docs/zh/docs/how-to/conditional-openapi.md create mode 100644 docs/zh/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/zh/docs/how-to/custom-request-and-route.md create mode 100644 docs/zh/docs/how-to/extending-openapi.md create mode 100644 docs/zh/docs/how-to/graphql.md create mode 100644 docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/zh/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/zh/docs/how-to/testing-database.md create mode 100644 docs/zh/docs/resources/index.md create mode 100644 docs/zh/docs/translation-banner.md diff --git a/docs/zh/docs/_llm-test.md b/docs/zh/docs/_llm-test.md new file mode 100644 index 0000000000..05c512e99b --- /dev/null +++ b/docs/zh/docs/_llm-test.md @@ -0,0 +1,755 @@ +# LLM ๆต‹่ฏ•ๆ–‡ไปถ { #llm-test-file } + +ๆœฌๆ–‡็”จไบŽๆต‹่ฏ•็”จไบŽ็ฟป่ฏ‘ๆ–‡ๆกฃ็š„ LLM ๆ˜ฏๅฆ็†่งฃ `scripts/translate.py` ไธญ็š„ `general_prompt` ไปฅๅŠ `docs/{language code}/llm-prompt.md` ไธญ็š„่ฏญ่จ€็‰นๅฎšๆ็คบใ€‚่ฏญ่จ€็‰นๅฎšๆ็คบไผš่ฟฝๅŠ ๅˆฐ `general_prompt` ไน‹ๅŽใ€‚ + +่ฟ™้‡ŒๆทปๅŠ ็š„ๆต‹่ฏ•ไผš่ขซๆ‰€ๆœ‰่ฏญ่จ€็‰นๅฎšๆ็คบ็š„่ฎพ่ฎก่€…็œ‹ๅˆฐใ€‚ + +็”จๆณ•ๅฆ‚ไธ‹๏ผš + +* ๅ‡†ๅค‡่ฏญ่จ€็‰นๅฎšๆ็คบโ€”โ€”`docs/{language code}/llm-prompt.md`ใ€‚ +* ๅฐ†ๆœฌๆ–‡้‡ๆ–ฐ็ฟป่ฏ‘ไธบไฝ ็š„็›ฎๆ ‡่ฏญ่จ€๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ `translate.py` ็š„ `translate-page` ๅ‘ฝไปค๏ผ‰ใ€‚่ฟ™ไผšๅœจ `docs/{language code}/docs/_llm-test.md` ไธ‹ๅˆ›ๅปบ็ฟป่ฏ‘ใ€‚ +* ๆฃ€ๆŸฅ็ฟป่ฏ‘ๆ˜ฏๅฆๆญฃ็กฎใ€‚ +* ๅฆ‚ๆœ‰้œ€่ฆ๏ผŒๆ”น่ฟ›ไฝ ็š„่ฏญ่จ€็‰นๅฎšๆ็คบใ€้€š็”จๆ็คบ๏ผŒๆˆ–่‹ฑๆ–‡ๆ–‡ๆกฃใ€‚ +* ็„ถๅŽๆ‰‹ๅŠจไฟฎๆญฃ็ฟป่ฏ‘ไธญๅ‰ฉไฝ™็š„้—ฎ้ข˜๏ผŒ็กฎไฟ่ฟ™ๆ˜ฏไธ€ไธชไผ˜็ง€็š„่ฏ‘ๆ–‡ใ€‚ +* ้‡ๆ–ฐ็ฟป่ฏ‘๏ผŒๅœจๅทฒๆœ‰็š„ไผ˜็ง€่ฏ‘ๆ–‡ๅŸบ็ก€ไธŠ่ฟ›่กŒใ€‚็†ๆƒณๆƒ…ๅ†ตๆ˜ฏ LLM ไธๅ†ๅฏน่ฏ‘ๆ–‡ๅšไปปไฝ•ๆ›ดๆ”นใ€‚่ฟ™ๆ„ๅ‘ณ็€้€š็”จๆ็คบๅ’Œไฝ ็š„่ฏญ่จ€็‰นๅฎšๆ็คบๅทฒ็ปๅฐฝๅฏ่ƒฝๅฎŒๅ–„๏ผˆๆœ‰ๆ—ถๅฎƒไปไผšๅšไธ€ไบ›็œ‹ไผผ้šๆœบ็š„ๆ”นๅŠจ๏ผŒๅŽŸๅ› ๆ˜ฏLLM ไธๆ˜ฏ็กฎๅฎšๆ€ง็ฎ—ๆณ•๏ผ‰ใ€‚ + +ๆต‹่ฏ•ๅฆ‚ไธ‹๏ผš + +## ไปฃ็ ็‰‡ๆฎต { #code-snippets } + +//// tab | ๆต‹่ฏ• + +่ฟ™ๆ˜ฏไธ€ไธชไปฃ็ ็‰‡ๆฎต๏ผš`foo`ใ€‚่ฟ™ๆ˜ฏๅฆไธ€ไธชไปฃ็ ็‰‡ๆฎต๏ผš`bar`ใ€‚่ฟ˜ๆœ‰ไธ€ไธช๏ผš`baz quux`ใ€‚ + +//// + +//// tab | ไฟกๆฏ + +ไปฃ็ ็‰‡ๆฎต็š„ๅ†…ๅฎนๅบ”ไฟๆŒไธๅ˜ใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Content of code snippets` ้ƒจๅˆ†ใ€‚ + +//// + +## ๅผ•ๅท { #quotes } + +//// tab | ๆต‹่ฏ• + +ๆ˜จๅคฉ๏ผŒๆˆ‘็š„ๆœ‹ๅ‹ๅ†™้“๏ผš"ๅฆ‚ๆžœไฝ ๆŠŠ incorrectly ๆ‹ผๅฏนไบ†๏ผŒไฝ ๅฐฑๆŠŠๅฎƒๆ‹ผ้”™ไบ†"ใ€‚ๆˆ‘ๅ›ž็ญ”๏ผš"ๆฒก้”™๏ผŒไฝ† 'incorrectly' ้”™็š„ไธๆ˜ฏ '"incorrectly"'"ใ€‚ + +/// note | ๆณจๆ„ + +LLM ๅพˆๅฏ่ƒฝไผšๆŠŠ่ฟ™ๆฎต็ฟป้”™ใ€‚ๆˆ‘ไปฌๅชๅ…ณๅฟƒๅœจ้‡ๆ–ฐ็ฟป่ฏ‘ๆ—ถๅฎƒๆ˜ฏๅฆ่ƒฝไฟๆŒไฟฎๆญฃๅŽ็š„่ฏ‘ๆ–‡ใ€‚ + +/// + +//// + +//// tab | ไฟกๆฏ + +ๆ็คบ่ฏ่ฎพ่ฎก่€…ๅฏไปฅ้€‰ๆ‹ฉๆ˜ฏๅฆๅฐ†ไธญๆ€งๅผ•ๅท่ฝฌๆขไธบๆŽ’็‰ˆๅผ•ๅทใ€‚ไนŸๅฏไปฅไฟๆŒไธๅ˜ใ€‚ + +ไพ‹ๅฆ‚ๅ‚่ง `docs/de/llm-prompt.md` ไธญ็š„ `### Quotes` ้ƒจๅˆ†ใ€‚ + +//// + +## ไปฃ็ ็‰‡ๆฎตไธญ็š„ๅผ•ๅท { #quotes-in-code-snippets } + +//// tab | ๆต‹่ฏ• + +`pip install "foo[bar]"` + +ไปฃ็ ็‰‡ๆฎตไธญ็š„ๅญ—็ฌฆไธฒๅญ—้ข้‡็คบไพ‹๏ผš`"this"`๏ผŒ`'that'`ใ€‚ + +ไธ€ไธช่พƒ้šพ็š„ๅญ—็ฌฆไธฒๅญ—้ข้‡็คบไพ‹๏ผš`f"I like {'oranges' if orange else "apples"}"` + +็กฌๆ ธ๏ผš`Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | ไฟกๆฏ + +... ไฝ†ๆ˜ฏ๏ผŒไปฃ็ ็‰‡ๆฎตๅ†…็š„ๅผ•ๅทๅฟ…้กปไฟๆŒไธๅ˜ใ€‚ + +//// + +## ไปฃ็ ๅ— { #code-blocks } + +//// tab | ๆต‹่ฏ• + +ไธ€ไธช Bash ไปฃ็ ็คบไพ‹... + +```bash +# ๅ‘ๅฎ‡ๅฎ™ๆ‰“ๅฐ้—ฎๅ€™ +echo "Hello universe" +``` + +...ไปฅๅŠไธ€ไธชๆŽงๅˆถๅฐไปฃ็ ็คบไพ‹... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...ไปฅๅŠๅฆไธ€ไธชๆŽงๅˆถๅฐไปฃ็ ็คบไพ‹... + +```console +// ๅˆ›ๅปบ็›ฎๅฝ• "code" +$ mkdir code +// ๅˆ‡ๆขๅˆฐ่ฏฅ็›ฎๅฝ• +$ cd code +``` + +...ไปฅๅŠไธ€ไธช Python ไปฃ็ ็คบไพ‹... + +```Python +wont_work() # ่ฟ™ไธไผš่ตทไฝœ็”จ ๐Ÿ˜ฑ +works(foo="bar") # ่ฟ™ๅฏ่กŒ ๐ŸŽ‰ +``` + +...ๅฐฑ่ฟ™ไบ›ใ€‚ + +//// + +//// tab | ไฟกๆฏ + +ไปฃ็ ๅ—ไธญ็š„ไปฃ็ ไธๅบ”่ขซไฟฎๆ”น๏ผŒๆณจ้‡Š้™คๅค–ใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Content of code blocks` ้ƒจๅˆ†ใ€‚ + +//// + +## ้€‰้กนๅกไธŽๅฝฉ่‰ฒๆ็คบๆก† { #tabs-and-colored-boxes } + +//// tab | ๆต‹่ฏ• + +/// info | ไฟกๆฏ +Some text +/// + +/// note | ๆณจๆ„ +Some text +/// + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ +Some text +/// + +/// check | ๆฃ€ๆŸฅ +Some text +/// + +/// tip | ๆ็คบ +Some text +/// + +/// warning | ่ญฆๅ‘Š +Some text +/// + +/// danger | ๅฑ้™ฉ +Some text +/// + +//// + +//// tab | ไฟกๆฏ + +้€‰้กนๅกไปฅๅŠ `Info`/`Note`/`Warning`/็ญ‰ๆ็คบๅ—๏ผŒๅบ”ๅœจ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๅŽๆทปๅŠ ๅ…ถๆ ‡้ข˜็š„็ฟป่ฏ‘ใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Special blocks` ไธŽ `### Tab blocks` ้ƒจๅˆ†ใ€‚ + +//// + +## Web ไธŽๅ†…้ƒจ้“พๆŽฅ { #web-and-internal-links } + +//// tab | ๆต‹่ฏ• + +้“พๆŽฅๆ–‡ๆœฌๅบ”่ขซ็ฟป่ฏ‘๏ผŒ้“พๆŽฅๅœฐๅ€ๅบ”ไฟๆŒไธๅ˜๏ผš + +* [้“พๆŽฅๅˆฐไธŠ้ข็š„ๆ ‡้ข˜](#code-snippets) +* [ๅ†…้ƒจ้“พๆŽฅ](index.md#installation){.internal-link target=_blank} +* ๅค–้ƒจ้“พๆŽฅ +* ๆ ทๅผ้“พๆŽฅ +* ่„šๆœฌ้“พๆŽฅ +* ๅ›พ็‰‡้“พๆŽฅ + +้“พๆŽฅๆ–‡ๆœฌๅบ”่ขซ็ฟป่ฏ‘๏ผŒไธ”้“พๆŽฅๅœฐๅ€ๅบ”ๆŒ‡ๅ‘ๅฏนๅบ”็š„่ฏ‘ๆ–‡้กต้ข๏ผš + +* FastAPI ้“พๆŽฅ + +//// + +//// tab | ไฟกๆฏ + +้“พๆŽฅ็š„ๆ–‡ๆœฌๅบ”่ขซ็ฟป่ฏ‘๏ผŒไฝ†ๅœฐๅ€ไฟๆŒไธๅ˜ใ€‚ๅ”ฏไธ€็š„ไพ‹ๅค–ๆ˜ฏๆŒ‡ๅ‘ FastAPI ๆ–‡ๆกฃ้กต้ข็š„็ปๅฏน้“พๆŽฅ๏ผŒๆญคๆ—ถๅบ”ๆŒ‡ๅ‘ๅฏนๅบ”่ฏญ่จ€็š„่ฏ‘ๆ–‡ใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Links` ้ƒจๅˆ†ใ€‚ + +//// + +## HTML "abbr" ๅ…ƒ็ด  { #html-abbr-elements } + +//// tab | ๆต‹่ฏ• + +่ฟ™้‡Œๆœ‰ไธ€ไบ›ๅŒ…่ฃนๅœจ HTML "abbr" ๅ…ƒ็ด ไธญ็š„ๅ†…ๅฎน๏ผˆๆœ‰ไบ›ๆ˜ฏ่™šๆž„็š„๏ผ‰๏ผš + +### abbr ๆไพ›ไบ†ๅฎŒๆ•ด็Ÿญ่ฏญ { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr ๆไพ›ไบ†ๅฎŒๆ•ด็Ÿญ่ฏญไธŽ่งฃ้‡Š { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | ไฟกๆฏ + +"abbr" ๅ…ƒ็ด ็š„ "title" ๅฑžๆ€ง้œ€่ฆๆŒ‰็…ง็‰นๅฎš่ง„ๅˆ™่ฟ›่กŒ็ฟป่ฏ‘ใ€‚ + +่ฏ‘ๆ–‡ๅฏไปฅ่‡ช่กŒๆทปๅŠ  "abbr" ๅ…ƒ็ด ไปฅ่งฃ้‡Š่‹ฑ่ฏญๅ•่ฏ๏ผŒLLM ไธๅบ”ๅˆ ้™ค่ฟ™ไบ›ๅ…ƒ็ด ใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### HTML abbr elements` ้ƒจๅˆ†ใ€‚ + +//// + +## HTML "dfn" ๅ…ƒ็ด  { #html-dfn-elements } + +* ้›†็พค +* ๆทฑๅบฆๅญฆไน  + +## ๆ ‡้ข˜ { #headings } + +//// tab | ๆต‹่ฏ• + +### ๅผ€ๅ‘ Web ๅบ”็”จโ€”โ€”ๆ•™็จ‹ { #develop-a-webapp-a-tutorial } + +Hello. + +### ็ฑปๅž‹ๆ็คบไธŽๆณจ่งฃ { #type-hints-and-annotations } + +Hello again. + +### ่ถ…็ฑปไธŽๅญ็ฑป { #super-and-subclasses } + +Hello again. + +//// + +//// tab | ไฟกๆฏ + +ๅ…ณไบŽๆ ‡้ข˜็š„ๅ”ฏไธ€็กฌๆ€ง่ง„ๅˆ™ๆ˜ฏ๏ผšLLM ๅฟ…้กปไฟๆŒ่Šฑๆ‹ฌๅทๅ†…็š„ๅ“ˆๅธŒ้ƒจๅˆ†ไธๅ˜๏ผŒไปฅ็กฎไฟ้“พๆŽฅไธไผšๅคฑๆ•ˆใ€‚ + +ๅ‚่ง `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Headings` ้ƒจๅˆ†ใ€‚ + +่ฏญ่จ€็‰นๅฎš็š„่ฏดๆ˜Žๅฏๅ‚่งไพ‹ๅฆ‚ `docs/de/llm-prompt.md` ไธญ็š„ `### Headings` ้ƒจๅˆ†ใ€‚ + +//// + +## ๆ–‡ๆกฃไธญไฝฟ็”จ็š„ๆœฏ่ฏญ { #terms-used-in-the-docs } + +//// tab | ๆต‹่ฏ• + +* you +* your + +* e.g. +* etc. + +* `foo` as an `int` +* `bar` as a `str` +* `baz` as a `list` + +* the Tutorial - User guide +* the Advanced User Guide +* the SQLModel docs +* the API docs +* the automatic docs + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO format +* the JSON Schema standard +* the JSON schema +* the schema definition +* Password Flow +* Mobile + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* to serve the application +* to serve the page + +* the app +* the application + +* the request +* the response +* the error response + +* the path operation +* the path operation decorator +* the path operation function + +* the body +* the request body +* the response body +* the JSON body +* the form body +* the file body +* the function body + +* the parameter +* the body parameter +* the path parameter +* the query parameter +* the cookie parameter +* the header parameter +* the form parameter +* the function parameter + +* the event +* the startup event +* the startup of the server +* the shutdown event +* the lifespan event + +* the handler +* the event handler +* the exception handler +* to handle + +* the model +* the Pydantic model +* the data model +* the database model +* the form model +* the model object + +* the class +* the base class +* the parent class +* the subclass +* the child class +* the sibling class +* the class method + +* the header +* the headers +* the authorization header +* the `Authorization` header +* the forwarded header + +* the dependency injection system +* the dependency +* the dependable +* the dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* the env var +* the environment variable +* the `PATH` +* the `PATH` variable + +* the authentication +* the authentication provider +* the authorization +* the authorization form +* the authorization provider +* the user authenticates +* the system authenticates the user + +* the CLI +* the command line interface + +* the server +* the client + +* the cloud provider +* the cloud service + +* the development +* the development stages + +* the dict +* the dictionary +* the enumeration +* the enum +* the enum member + +* the encoder +* the decoder +* to encode +* to decode + +* the exception +* to raise + +* the expression +* the statement + +* the frontend +* the backend + +* the GitHub discussion +* the GitHub issue + +* the performance +* the performance optimization + +* the return type +* the return value + +* the security +* the security scheme + +* the task +* the background task +* the task function + +* the template +* the template engine + +* the type annotation +* the type hint + +* the server worker +* the Uvicorn worker +* the Gunicorn Worker +* the worker process +* the worker class +* the workload + +* the deployment +* to deploy + +* the SDK +* the software development kit + +* the `APIRouter` +* the `requirements.txt` +* the Bearer Token +* the breaking change +* the bug +* the button +* the callable +* the code +* the commit +* the context manager +* the coroutine +* the database session +* the disk +* the domain +* the engine +* the fake X +* the HTTP GET method +* the item +* the library +* the lifespan +* the lock +* the middleware +* the mobile application +* the module +* the mounting +* the network +* the origin +* the override +* the payload +* the processor +* the property +* the proxy +* the pull request +* the query +* the RAM +* the remote machine +* the status code +* the string +* the tag +* the web framework +* the wildcard +* to return +* to validate + +//// + +//// tab | ไฟกๆฏ + +่ฟ™ๆ˜ฏไธ€ไปฝไธๅฎŒๆ•ดไธ”้ž่ง„่Œƒๆ€ง็š„๏ผˆไธป่ฆๆ˜ฏ๏ผ‰ๆŠ€ๆœฏๆœฏ่ฏญๆธ…ๅ•๏ผŒๅ–่‡ชๆ–‡ๆกฃไธญๅธธ่ง็š„่ฏๆฑ‡ใ€‚ๅฎƒๅฏ่ƒฝๆœ‰ๅŠฉไบŽๆ็คบ่ฏ่ฎพ่ฎก่€…ๅˆคๆ–ญๅ“ชไบ›ๆœฏ่ฏญ้œ€่ฆๅฏน LLM ๆไพ›้ขๅค–ๆŒ‡ๅผ•ใ€‚ไพ‹ๅฆ‚ๅฝ“ๅฎƒๆ€ปๆ˜ฏๆŠŠไธ€ไธชๅฅฝ็š„่ฏ‘ๆณ•ๆ”นๅ›žๆฌกไผ˜่ฏ‘ๆณ•๏ผŒๆˆ–ๅœจไฝ ็š„่ฏญ่จ€ไธญๅฏนๆŸไธชๆœฏ่ฏญ็š„่ฏๅฝขๅ˜ๅŒ–ๆœ‰ๅ›ฐ้šพๆ—ถใ€‚ + +ๅ‚่งไพ‹ๅฆ‚ `docs/de/llm-prompt.md` ไธญ็š„ `### List of English terms and their preferred German translations` ้ƒจๅˆ†ใ€‚ + +//// + +//// + +็ฟป่ฏ‘๏ผˆๆœฏ่ฏญ๏ผ‰ๅฏน็…ง๏ผš + +//// tab | ๆต‹่ฏ•๏ผˆ่ฏ‘ๆ–‡๏ผ‰ + +* ไฝ  +* ไฝ ็š„ + +* ไพ‹ๅฆ‚ +* ็ญ‰็ญ‰ + +* ๅฐ† `foo` ไฝœไธบ `int` +* ๅฐ† `bar` ไฝœไธบ `str` +* ๅฐ† `baz` ไฝœไธบ `list` + +* ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ— +* ้ซ˜็บง็”จๆˆทๆŒ‡ๅ— +* SQLModel ๆ–‡ๆกฃ +* API ๆ–‡ๆกฃ +* ่‡ชๅŠจๆ–‡ๆกฃ + +* ๆ•ฐๆฎ็ง‘ๅญฆ +* ๆทฑๅบฆๅญฆไน  +* ๆœบๅ™จๅญฆไน  +* ไพ่ต–ๆณจๅ…ฅ +* HTTP ๅŸบๆœฌ่ฎค่ฏ +* HTTP ๆ‘˜่ฆ่ฎค่ฏ +* ISO ๆ ผๅผ +* JSON Schema ๆ ‡ๅ‡† +* JSON ๆจกๅผ +* ๆจกๅผๅฎšไน‰ +* ๅฏ†็ ๆต +* ็งปๅŠจ็ซฏ + +* ๅทฒๅผƒ็”จ +* ่ฎพ่ฎก็š„ +* ๆ— ๆ•ˆ +* ๅณๆ—ถ +* ๆ ‡ๅ‡†็š„ +* ้ป˜่ฎค็š„ +* ๅŒบๅˆ†ๅคงๅฐๅ†™ +* ไธๅŒบๅˆ†ๅคงๅฐๅ†™ + +* ไธบๅบ”็”จๆไพ›ๆœๅŠก +* ไธบ้กต้ขๆไพ›ๆœๅŠก + +* ๅบ”็”จ +* ๅบ”็”จ็จ‹ๅบ + +* ่ฏทๆฑ‚ +* ๅ“ๅบ” +* ้”™่ฏฏๅ“ๅบ” + +* ่ทฏๅพ„ๆ“ไฝœ +* ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ +* ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ + +* ไธปไฝ“ +* ่ฏทๆฑ‚ไฝ“ +* ๅ“ๅบ”ไฝ“ +* JSON ไฝ“ +* ่กจๅ•ไฝ“ +* ๆ–‡ไปถไฝ“ +* ๅ‡ฝๆ•ฐไฝ“ + +* ๅ‚ๆ•ฐ +* ่ฏทๆฑ‚ไฝ“ๅ‚ๆ•ฐ +* ่ทฏๅพ„ๅ‚ๆ•ฐ +* ๆŸฅ่ฏขๅ‚ๆ•ฐ +* Cookie ๅ‚ๆ•ฐ +* Header ๅ‚ๆ•ฐ +* ่กจๅ•ๅ‚ๆ•ฐ +* ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ + +* ไบ‹ไปถ +* ๅฏๅŠจไบ‹ไปถ +* ๆœๅŠกๅ™จ็š„ๅฏๅŠจ +* ๅ…ณ้—ญไบ‹ไปถ +* ็”Ÿๅ‘ฝๅ‘จๆœŸไบ‹ไปถ + +* ๅค„็†ๅ™จ +* ไบ‹ไปถๅค„็†ๅ™จ +* ๅผ‚ๅธธๅค„็†ๅ™จ +* ๅค„็† + +* ๆจกๅž‹ +* Pydantic ๆจกๅž‹ +* ๆ•ฐๆฎๆจกๅž‹ +* ๆ•ฐๆฎๅบ“ๆจกๅž‹ +* ่กจๅ•ๆจกๅž‹ +* ๆจกๅž‹ๅฏน่ฑก + +* ็ฑป +* ๅŸบ็ฑป +* ็ˆถ็ฑป +* ๅญ็ฑป +* ๅญ็ฑป +* ๅ…„ๅผŸ็ฑป +* ็ฑปๆ–นๆณ• + +* ่ฏทๆฑ‚ๅคด +* ่ฏทๆฑ‚ๅคด +* ๆŽˆๆƒๅคด +* `Authorization` ๅคด +* ่ฝฌๅ‘ๅคด + +* ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ +* ไพ่ต– +* ๅฏไพ่ต–ๅฏน่ฑก +* ไพ่ต–้กน + +* I/O ๅ—้™ +* CPU ๅ—้™ +* ๅนถๅ‘ +* ๅนถ่กŒ +* ๅคš่ฟ›็จ‹ + +* ็Žฏๅขƒๅ˜้‡ +* ็Žฏๅขƒๅ˜้‡ +* `PATH` +* `PATH` ๅ˜้‡ + +* ่ฎค่ฏ +* ่ฎค่ฏๆไพ›ๆ–น +* ๆŽˆๆƒ +* ๆŽˆๆƒ่กจๅ• +* ๆŽˆๆƒๆไพ›ๆ–น +* ็”จๆˆท่ฟ›่กŒ่ฎค่ฏ +* ็ณป็ปŸๅฏน็”จๆˆท่ฟ›่กŒ่ฎค่ฏ + +* CLI +* ๅ‘ฝไปค่กŒ็•Œ้ข + +* ๆœๅŠกๅ™จ +* ๅฎขๆˆท็ซฏ + +* ไบ‘ๆœๅŠกๆไพ›ๅ•† +* ไบ‘ๆœๅŠก + +* ๅผ€ๅ‘ +* ๅผ€ๅ‘้˜ถๆฎต + +* dict +* ๅญ—ๅ…ธ +* ๆžšไธพ +* ๆžšไธพ +* ๆžšไธพๆˆๅ‘˜ + +* ็ผ–็ ๅ™จ +* ่งฃ็ ๅ™จ +* ็ผ–็  +* ่งฃ็  + +* ๅผ‚ๅธธ +* ๆŠ›ๅ‡บ + +* ่กจ่พพๅผ +* ่ฏญๅฅ + +* ๅ‰็ซฏ +* ๅŽ็ซฏ + +* GitHub ่ฎจ่ฎบ +* GitHub Issue + +* ๆ€ง่ƒฝ +* ๆ€ง่ƒฝไผ˜ๅŒ– + +* ่ฟ”ๅ›ž็ฑปๅž‹ +* ่ฟ”ๅ›žๅ€ผ + +* ๅฎ‰ๅ…จ +* ๅฎ‰ๅ…จๆ–นๆกˆ + +* ไปปๅŠก +* ๅŽๅฐไปปๅŠก +* ไปปๅŠกๅ‡ฝๆ•ฐ + +* ๆจกๆฟ +* ๆจกๆฟๅผ•ๆ“Ž + +* ็ฑปๅž‹ๆณจ่งฃ +* ็ฑปๅž‹ๆ็คบ + +* ๆœๅŠกๅ™จ worker +* Uvicorn worker +* Gunicorn worker +* worker ่ฟ›็จ‹ +* worker ็ฑป +* ๅทฅไฝœ่ดŸ่ฝฝ + +* ้ƒจ็ฝฒ +* ้ƒจ็ฝฒ + +* SDK +* ่ฝฏไปถๅผ€ๅ‘ๅทฅๅ…ทๅŒ… + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* ็ ดๅๆ€งๅ˜ๆ›ด +* Bug +* ๆŒ‰้’ฎ +* ๅฏ่ฐƒ็”จๅฏน่ฑก +* ไปฃ็  +* ๆไบค +* ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ +* ๅ็จ‹ +* ๆ•ฐๆฎๅบ“ไผš่ฏ +* ็ฃ็›˜ +* ๅŸŸๅ +* ๅผ•ๆ“Ž +* ๅ‡ X +* HTTP GET ๆ–นๆณ• +* ้กน +* ๅบ“ +* ็”Ÿๅ‘ฝๅ‘จๆœŸ +* ้” +* ไธญ้—ดไปถ +* ็งปๅŠจๅบ”็”จ +* ๆจกๅ— +* ๆŒ‚่ฝฝ +* ็ฝ‘็ปœ +* ๆบ +* ่ฆ†็›– +* ่ดŸ่ฝฝ +* ๅค„็†ๅ™จ +* ๅฑžๆ€ง +* ไปฃ็† +* Pull Request +* ๆŸฅ่ฏข +* RAM +* ่ฟœ็จ‹ๆœบๅ™จ +* ็Šถๆ€็  +* ๅญ—็ฌฆไธฒ +* ๆ ‡็ญพ +* Web ๆก†ๆžถ +* ้€š้…็ฌฆ +* ่ฟ”ๅ›ž +* ๆ ก้ชŒ + +//// + +//// tab | ไฟกๆฏ๏ผˆ่ฏ‘ๆ–‡๏ผ‰ + +ๆญคๆธ…ๅ•ๆ˜ฏไธๅฎŒๆ•ดไธ”้ž่ง„่Œƒๆ€ง็š„๏ผŒๅˆ—ๅ‡บ๏ผˆไธป่ฆๆ˜ฏ๏ผ‰ๆ–‡ๆกฃไธญๅ‡บ็Žฐ็š„ๆŠ€ๆœฏๆœฏ่ฏญใ€‚ๅฎƒๆœ‰ๅŠฉไบŽๆ็คบ่ฏ่ฎพ่ฎก่€…็กฎๅฎšๅ“ชไบ›ๆœฏ่ฏญ้œ€่ฆ้ขๅค–็š„ๆŒ‡ๅผ•ใ€‚ไพ‹ๅฆ‚ๅฝ“ LLM ๆ€ปๆ˜ฏๆŠŠๆ›ดๅฅฝ็š„่ฏ‘ๆณ•ๆ”นๅ›žๆฌกไผ˜่ฏ‘ๆณ•๏ผŒๆˆ–ๅœจไฝ ็š„่ฏญ่จ€ไธญ้šพไปฅๆญฃ็กฎๅ˜ๅฝขๆ—ถใ€‚ + +ไนŸๅฏๅ‚่ง `docs/de/llm-prompt.md` ไธญ็š„ `### List of English terms and their preferred German translations` ้ƒจๅˆ†ใ€‚ + +//// diff --git a/docs/zh/docs/about/index.md b/docs/zh/docs/about/index.md new file mode 100644 index 0000000000..9b73533f7f --- /dev/null +++ b/docs/zh/docs/about/index.md @@ -0,0 +1,3 @@ +# ๅ…ณไบŽ { #about } + +ๅ…ณไบŽ FastAPIใ€ๅ…ถ่ฎพ่ฎกใ€็ตๆ„Ÿ็ญ‰ใ€‚๐Ÿค“ diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md index bc197280ab..aa3d22d1c7 100644 --- a/docs/zh/docs/advanced/additional-responses.md +++ b/docs/zh/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ ไพ‹ๅฆ‚๏ผŒ่ฆๅฃฐๆ˜Žๅฆไธ€ไธช็Šถๆ€็ ไธบ `404` ไธ”ๅ…ทๆœ‰ Pydantic ๆจกๅž‹ `Message` ็š„ๅ“ๅบ”๏ผŒไฝ ๅฏไปฅ่ฟ™ๆ ทๅ†™๏ผš -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | ๆณจๆ„ @@ -203,7 +203,7 @@ ไปฅๅŠไธ€ไธช็Šถๆ€็ ไธบ `200` ็š„ๅ“ๅบ”๏ผŒๅฎƒไฝฟ็”จไฝ ็š„ `response_model`๏ผŒไฝ†ๅŒ…ๅซ่‡ชๅฎšไน‰็š„ `example`๏ผš -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} ๆ‰€ๆœ‰่ฟ™ไบ›้ƒฝไผš่ขซๅˆๅนถๅนถๅŒ…ๅซๅˆฐไฝ ็š„ OpenAPI ไธญ๏ผŒๅนถๆ˜พ็คบๅœจ API ๆ–‡ๆกฃ้‡Œ๏ผš diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index 23ceab4e87..7eeffaf532 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning +/// warning | ่ญฆๅ‘Š ๅฝ“ไฝ ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธชๅƒไธŠ้ขไพ‹ๅญไธญ็š„ `Response` ๅฏน่ฑกๆ—ถ๏ผŒๅฎƒไผš็›ดๆŽฅ่ฟ”ๅ›žใ€‚ @@ -26,7 +26,7 @@ /// -/// note | ๆŠ€ๆœฏ็ป†่Š‚ +/// note | ๆณจๆ„ ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import JSONResponse`ใ€‚ใ€€ diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md index 3efca89442..a547e88814 100644 --- a/docs/zh/docs/advanced/advanced-dependencies.md +++ b/docs/zh/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ ไธบๆญค๏ผŒๅฃฐๆ˜Žไธ€ไธช `__call__` ๆ–นๆณ•๏ผš -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒ**FastAPI** ไผšไฝฟ็”จ่ฟ™ไธช `__call__` ๆฅๆฃ€ๆŸฅ้™„ๅŠ ๅ‚ๆ•ฐๅ’Œๅญไพ่ต–๏ผŒๅนถไธ”็จๅŽไผš่ฐƒ็”จๅฎƒ๏ผŒๆŠŠ่ฟ”ๅ›žๅ€ผไผ ้€’็ป™ไฝ ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅ‚ๆ•ฐใ€‚ @@ -26,7 +26,7 @@ ็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅฏไปฅ็”จ `__init__` ๅฃฐๆ˜Žๅฎžไพ‹็š„ๅ‚ๆ•ฐ๏ผŒ็”จๆฅโ€œๅ‚ๆ•ฐๅŒ–โ€่ฟ™ไธชไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} ๅœจๆœฌไพ‹ไธญ๏ผŒ**FastAPI** ไธไผšๆŽฅ่งฆๆˆ–ๅ…ณๅฟƒ `__init__`๏ผŒๆˆ‘ไปฌไผšๅœจ่‡ชๅทฑ็š„ไปฃ็ ไธญ็›ดๆŽฅไฝฟ็”จๅฎƒใ€‚ @@ -34,7 +34,7 @@ ๆˆ‘ไปฌๅฏไปฅ่ฟ™ๆ ทๅˆ›ๅปบ่ฏฅ็ฑป็š„ๅฎžไพ‹๏ผš -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} ่ฟ™ๆ ทๅฐฑๆŠŠไพ่ต–้กนโ€œๅ‚ๆ•ฐๅŒ–โ€ไบ†๏ผŒ็Žฐๅœจๅฎƒๅ†…้ƒจๅธฆๆœ‰ๅฑžๆ€ง `checker.fixed_content` ็š„ๅ€ผ `"bar"`ใ€‚ @@ -50,7 +50,7 @@ checker(q="somequery") ...ๅนถๅฐ†ๅ…ถ่ฟ”ๅ›žๅ€ผไฝœไธบไพ่ต–้กน็š„ๅ€ผ๏ผŒไผ ็ป™ๆˆ‘ไปฌ็š„*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไธญ็š„ๅ‚ๆ•ฐ `fixed_content_included`๏ผš -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | ๆ็คบ diff --git a/docs/zh/docs/advanced/advanced-python-types.md b/docs/zh/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..bbc9302e86 --- /dev/null +++ b/docs/zh/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ้ซ˜็บง Python ็ฑปๅž‹ { #advanced-python-types } + +่ฟ™้‡Œๆœ‰ไธ€ไบ›ๅœจไฝฟ็”จ Python ็ฑปๅž‹ๆ—ถๅฏ่ƒฝๆœ‰็”จ็š„้ขๅค–ๆƒณๆณ•ใ€‚ + +## ไฝฟ็”จ `Union` ๆˆ– `Optional` { #using-union-or-optional } + +ๅฆ‚ๆžœไฝ ็š„ไปฃ็ ๅ› ไธบๆŸไบ›ๅŽŸๅ› ไธ่ƒฝไฝฟ็”จ `|`๏ผŒไพ‹ๅฆ‚ๅฎƒไธๆ˜ฏๅœจ็ฑปๅž‹ๆณจ่งฃ้‡Œ๏ผŒ่€Œๆ˜ฏๅœจ `response_model=` ไน‹็ฑป็š„ๅ‚ๆ•ฐไธญ๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅไฝฟ็”จ `typing` ไธญ็š„ `Union` ๆฅไปฃๆ›ฟ็ซ–็บฟ๏ผˆ`|`๏ผ‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฃฐๆ˜ŽๆŸไธชๅ€ผๅฏไปฅๆ˜ฏ `str` ๆˆ– `None`๏ผš + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` ไนŸๆไพ›ไบ†ไธ€ไธชๅฃฐๆ˜Žโ€œๅฏ่ƒฝไธบ `None`โ€็š„ๅฟซๆทๆ–นๅผ๏ผš`Optional`ใ€‚ + +ไปŽๆˆ‘้žๅธธไธป่ง‚็š„่ง’ๅบฆ็ป™ไธชๅฐๅปบ่ฎฎ๏ผš + +- ๐Ÿšจ ้ฟๅ…ไฝฟ็”จ `Optional[SomeType]` +- ๆ”น็”จ โœจ`Union[SomeType, None]`โœจใ€‚ + +ไธค่€…ๆ˜ฏ็ญ‰ไปท็š„๏ผŒๅบ•ๅฑ‚ๅ…ถๅฎžไนŸๆ˜ฏไธ€ๆ ท็š„ใ€‚ไฝ†ๆˆ‘ๆ›ดๆŽจ่ไฝฟ็”จ `Union` ่€Œไธๆ˜ฏ `Optional`๏ผŒๅ› ไธบๅ•่ฏโ€œoptionalโ€๏ผˆๅฏ้€‰๏ผ‰็œ‹่ตทๆฅไผšๆš—็คบ่ฏฅๅ€ผๆ˜ฏๅฏ้€‰็š„๏ผŒ่€Œๅฎƒ็œŸๆญฃ็š„ๅซไน‰ๆ˜ฏโ€œๅฎƒๅฏไปฅๆ˜ฏ `None`โ€๏ผŒๅณไฝฟๅฎƒๅนถไธๆ˜ฏๅฏ้€‰็š„๏ผŒไป็„ถๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ + +ๆˆ‘่ฎคไธบ `Union[SomeType, None]` ๆ›ด่ƒฝๆ˜Ž็กฎ่กจ่พพๅ…ถๅซไน‰ใ€‚ + +่ฟ™ๅชๆ˜ฏๅ…ณไบŽ่ฏ่ฏญๅ’Œๅ‘ฝๅ็š„้—ฎ้ข˜๏ผŒไฝ†่ฟ™ไบ›่ฏ่ฏญไผšๅฝฑๅ“ไฝ ๅ’Œไฝ ็š„้˜Ÿๅ‹ๅฆ‚ไฝ•็œ‹ๅพ…ไปฃ็ ใ€‚ + +ไธพไธชไพ‹ๅญ๏ผŒ็œ‹่ฟ™ๆฎตๅ‡ฝๆ•ฐ๏ผš + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +ๅ‚ๆ•ฐ `name` ่ขซๅฎšไน‰ไธบ `Optional[str]`๏ผŒไฝ†ๅฎƒๅนถไธๆ˜ฏโ€œๅฏ้€‰โ€็š„๏ผŒไฝ ไธ่ƒฝไธไผ ่ฟ™ไธชๅ‚ๆ•ฐๅฐฑ่ฐƒ็”จๅ‡ฝๆ•ฐ๏ผš + +```Python +say_hi() # ๅ“Žๅ‘€๏ผŒ่ฟ™ไผšๆŠฅ้”™๏ผ๐Ÿ˜ฑ +``` + +ๅ‚ๆ•ฐ `name` ไป็„ถๆ˜ฏๅฟ…ๅกซ็š„๏ผˆไธๆ˜ฏโ€œๅฏ้€‰โ€๏ผ‰๏ผŒๅ› ไธบๅฎƒๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ไธ่ฟ‡๏ผŒ`name` ๆŽฅๅ— `None` ไฝœไธบๅ–ๅ€ผ๏ผš + +```Python +say_hi(name=None) # ่ฟ™ๆ ทๅฏไปฅ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆ็š„ ๐ŸŽ‰ +``` + +ๅฅฝๆถˆๆฏๆ˜ฏ๏ผŒๅœจๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `|` ๆฅๅฎšไน‰็ฑปๅž‹่”ๅˆ๏ผš + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +ๅ› ๆญค๏ผŒ้€šๅธธไฝ ไธๅฟ…ไธบๅƒ `Optional` ๅ’Œ `Union` ่ฟ™ๆ ท็š„ๅๅญ—่€Œๆ“ๅฟƒใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md index 6803358d25..16b8a8c813 100644 --- a/docs/zh/docs/advanced/async-tests.md +++ b/docs/zh/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ ๆ–‡ไปถ `main.py` ๅฐ†ๅŒ…ๅซ: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} ๆ–‡ไปถ `test_main.py` ๅฐ†ๅŒ…ๅซ้’ˆๅฏน `main.py` ็š„ๆต‹่ฏ•๏ผŒ็Žฐๅœจๅฎƒๅฏ่ƒฝ็œ‹่ตทๆฅๅฆ‚ไธ‹๏ผš -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## ่ฟ่กŒๆต‹่ฏ• { #run-it } @@ -56,7 +56,7 @@ $ pytest ่ฟ™ไธชๆ ‡่ฎฐ `@pytest.mark.anyio` ไผšๅ‘Š่ฏ‰ pytest ่ฏฅๆต‹่ฏ•ๅ‡ฝๆ•ฐๅบ”่ฏฅ่ขซๅผ‚ๆญฅ่ฐƒ็”จ๏ผš -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | ๆ็คบ @@ -66,7 +66,7 @@ $ pytest ๆˆ‘ไปฌ็Žฐๅœจๅฏไปฅไฝฟ็”จๅบ”็”จ็จ‹ๅบๅˆ›ๅปบไธ€ไธช `AsyncClient` ๏ผŒๅนถไฝฟ็”จ `await` ๅ‘ๅ…ถๅ‘้€ๅผ‚ๆญฅ่ฏทๆฑ‚ใ€‚ -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} ่ฟ™็›ธๅฝ“ไบŽ๏ผš @@ -74,7 +74,7 @@ $ pytest response = client.get('/') ``` -ๆˆ‘ไปฌๆ›พ็ป้€š่ฟ‡ๅฎƒๅ‘ `TestClient` ๅ‘ๅ‡บ่ฏทๆฑ‚ใ€‚ +...ๆˆ‘ไปฌๆ›พ็ป้€š่ฟ‡ๅฎƒๅ‘ `TestClient` ๅ‘ๅ‡บ่ฏทๆฑ‚ใ€‚ /// tip | ๆ็คบ diff --git a/docs/zh/docs/advanced/behind-a-proxy.md b/docs/zh/docs/advanced/behind-a-proxy.md index b44b0b5ac5..3ccc65f292 100644 --- a/docs/zh/docs/advanced/behind-a-proxy.md +++ b/docs/zh/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" ไพ‹ๅฆ‚๏ผŒๅ‡่ฎพไฝ ๅฎšไน‰ไบ†ไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ* `/items/`๏ผš -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} ๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•่ฎฟ้—ฎ `/items`๏ผŒ้ป˜่ฎคไผš่ขซ้‡ๅฎšๅ‘ๅˆฐ `/items/`ใ€‚ @@ -115,7 +115,7 @@ sequenceDiagram ๅณไฝฟไฝ ็š„ๆ‰€ๆœ‰ไปฃ็ ้ƒฝๅ‡่ฎพๅชๆœ‰ `/app`ใ€‚ -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} ไปฃ็†ไผšๅœจๅฐ†่ฏทๆฑ‚ไผ ้€’็ป™ๅบ”็”จๆœๅŠกๅ™จ๏ผˆๅฏ่ƒฝๆ˜ฏ้€š่ฟ‡ FastAPI CLI ่ฟ่กŒ็š„ Uvicorn๏ผ‰ไน‹ๅ‰๏ผŒๅฎžๆ—ถ**โ€œ็งป้™คโ€**่ฟ™ไธช**่ทฏๅพ„ๅ‰็ผ€**๏ผŒ่ฎฉไฝ ็š„ๅบ”็”จ่ฎคไธบๅฎƒๆ˜ฏๅœจ `/app` ่ขซๆœๅŠก๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑไธ้œ€่ฆๆ›ดๆ–ฐๆ‰€ๆœ‰ไปฃ็ ๅŽปๅŒ…ๅซ `/api/v1` ๅ‰็ผ€ใ€‚ @@ -193,7 +193,7 @@ ASGI ่ง„่Œƒไธบ่ฟ™็ง็”จไพ‹ๅฎšไน‰ไบ† `root_path`ใ€‚ ่ฟ™้‡Œๆˆ‘ไปฌๆŠŠๅฎƒๅŒ…ๅซๅœจๅ“ๅบ”ๆถˆๆฏไธญไป…็”จไบŽๆผ”็คบใ€‚ -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} ็„ถๅŽ๏ผŒๅฆ‚ๆžœไฝ ่ฟ™ๆ ทๅฏๅŠจ Uvicorn๏ผš @@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ๆˆ–่€…๏ผŒๅฆ‚ๆžœไฝ ๆ— ๆณ•ๆไพ›็ฑปไผผ `--root-path` ็š„ๅ‘ฝไปค่กŒ้€‰้กน๏ผŒไฝ ๅฏไปฅๅœจๅˆ›ๅปบ FastAPI ๅบ”็”จๆ—ถ่ฎพ็ฝฎๅ‚ๆ•ฐ `root_path`๏ผš -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} ๆŠŠ `root_path` ไผ ็ป™ `FastAPI` ็ญ‰ๅŒไบŽๆŠŠๅ‘ฝไปค่กŒ้€‰้กน `--root-path` ไผ ็ป™ Uvicorn ๆˆ– Hypercornใ€‚ @@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ไพ‹ๅฆ‚๏ผš -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} ไผš็”Ÿๆˆๅฆ‚ไธ‹็š„ OpenAPI ๆจกๅผ๏ผš @@ -455,7 +455,7 @@ OpenAPI ่ง„่Œƒไธญ็š„ `servers` ๅฑžๆ€งๆ˜ฏๅฏ้€‰็š„ใ€‚ ๅฆ‚ๆžœไฝ ไธๅธŒๆœ› **FastAPI** ๅŒ…ๅซไธ€ไธชไฝฟ็”จ `root_path` ็š„่‡ชๅŠจๆœๅŠกๅ™จ๏ผŒๅฏไปฅไฝฟ็”จๅ‚ๆ•ฐ `root_path_in_servers=False`๏ผš -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} ่ฟ™ๆ ทๅฎƒๅฐฑไธไผš่ขซๅŒ…ๅซๅˆฐ OpenAPI ๆจกๅผไธญใ€‚ diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md index f5bec5fdcf..7c19b73fbc 100644 --- a/docs/zh/docs/advanced/custom-response.md +++ b/docs/zh/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ ไฝ†ๅฆ‚ๆžœไฝ ็กฎๅฎšไฝ ่ฟ”ๅ›ž็š„ๅ†…ๅฎนๆ˜ฏใ€Œๅฏไปฅ็”จ JSON ๅบๅˆ—ๅŒ–ใ€็š„๏ผŒไฝ ๅฏไปฅๅฐ†ๅฎƒ็›ดๆŽฅไผ ็ป™ๅ“ๅบ”็ฑป๏ผŒไปŽ่€Œ้ฟๅ…ๅœจไผ ็ป™ๅ“ๅบ”็ฑปไน‹ๅ‰ๅ…ˆ้€š่ฟ‡ `jsonable_encoder` ๅธฆๆฅ็š„้ขๅค–ๅผ€้”€ใ€‚ -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | ไฟกๆฏ @@ -55,7 +55,7 @@ * ๅฏผๅ…ฅ `HTMLResponse`ใ€‚ * ๅฐ† `HTMLResponse` ไฝœไธบไฝ ็š„ *่ทฏๅพ„ๆ“ไฝœ* ็š„ `response_class` ๅ‚ๆ•ฐไผ ๅ…ฅใ€‚ -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | ไฟกๆฏ @@ -73,7 +73,7 @@ ๅ’ŒไธŠ้ขไธ€ๆ ท็š„ไพ‹ๅญ๏ผŒ่ฟ”ๅ›žไธ€ไธช `HTMLResponse` ็œ‹่ตทๆฅๅฏ่ƒฝๆ˜ฏ่ฟ™ๆ ท๏ผš -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | ่ญฆๅ‘Š @@ -97,7 +97,7 @@ ๆฏ”ๅฆ‚ๅƒ่ฟ™ๆ ท๏ผš -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} ๅœจ่ฟ™ไธชไพ‹ๅญไธญ๏ผŒๅ‡ฝๆ•ฐ `generate_html_response()` ๅทฒ็ป็”Ÿๆˆๅนถ่ฟ”ๅ›ž `Response` ๅฏน่ฑก่€Œไธๆ˜ฏๅœจ `str` ไธญ่ฟ”ๅ›ž HTMLใ€‚ @@ -136,7 +136,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ่ฟ˜ๅฐ†ๅŒ…ๅซไธ€ไธชๅŸบไบŽ `media_type` ็š„ Content-Type ๅคด๏ผŒๅนถไธบๆ–‡ๆœฌ็ฑปๅž‹้™„ๅŠ ไธ€ไธชๅญ—็ฌฆ้›†ใ€‚ -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ๆŽฅๅ—ๆ–‡ๆœฌๆˆ–ๅญ—่Š‚ๅนถ่ฟ”ๅ›ž็บฏๆ–‡ๆœฌๅ“ๅบ”ใ€‚ -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | ๆ็คบ @@ -194,13 +194,13 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ไฝ ๅฏไปฅ็›ดๆŽฅ่ฟ”ๅ›žไธ€ไธช `RedirectResponse`๏ผš -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- ๆˆ–่€…ไฝ ๅฏไปฅๆŠŠๅฎƒ็”จไบŽ `response_class` ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} ๅฆ‚ๆžœไฝ ่ฟ™ไนˆๅš๏ผŒ้‚ฃไนˆไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ* ๅ‡ฝๆ•ฐไธญ็›ดๆŽฅ่ฟ”ๅ›ž URLใ€‚ @@ -210,13 +210,13 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ไฝ ไนŸๅฏไปฅๅฐ† `status_code` ๅ‚ๆ•ฐๅ’Œ `response_class` ๅ‚ๆ•ฐ็ป“ๅˆไฝฟ็”จ๏ผš -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } ้‡‡็”จๅผ‚ๆญฅ็”Ÿๆˆๅ™จๆˆ–ๆ™ฎ้€š็”Ÿๆˆๅ™จ/่ฟญไปฃๅ™จ๏ผŒ็„ถๅŽๆตๅผไผ ่พ“ๅ“ๅบ”ไธปไฝ“ใ€‚ -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### ๅฏน็ฑปไผผๆ–‡ไปถ็š„ๅฏน่ฑกไฝฟ็”จ `StreamingResponse` { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ่ฟ™ไนŸๅŒ…ๆ‹ฌ่ฎธๅคšไธŽไบ‘ๅญ˜ๅ‚จใ€่ง†้ข‘ๅค„็†็ญ‰ไบคไบ’็š„ๅบ“ใ€‚ -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. ่ฟ™ๆ˜ฏ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐใ€‚ไน‹ๆ‰€ไปฅๆ˜ฏใ€Œ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐใ€๏ผŒๆ˜ฏๅ› ไธบๅฎƒๅ†…้ƒจๅŒ…ๅซ `yield` ่ฏญๅฅใ€‚ 2. ้€š่ฟ‡ไฝฟ็”จ `with` ไปฃ็ ๅ—๏ผŒๆˆ‘ไปฌๅฏไปฅ็กฎไฟๅœจ็”Ÿๆˆๅ™จๅ‡ฝๆ•ฐๅฎŒๆˆๅŽๅ…ณ้—ญ็ฑปๆ–‡ไปถๅฏน่ฑกใ€‚ๅ› ๆญค๏ผŒๅœจๅฎƒๅฎŒๆˆๅ‘้€ๅ“ๅบ”ไน‹ๅŽไผš่ขซๅ…ณ้—ญใ€‚ @@ -255,11 +255,11 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ๆ–‡ไปถๅ“ๅบ”ๅฐ†ๅŒ…ๅซ้€‚ๅฝ“็š„ `Content-Length`ใ€`Last-Modified` ๅ’Œ `ETag` ๅ“ๅบ”ๅคดใ€‚ -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} ไฝ ไนŸๅฏไปฅไฝฟ็”จ `response_class` ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœ* ๅ‡ฝๆ•ฐไธญ็›ดๆŽฅ่ฟ”ๅ›žๆ–‡ไปถ่ทฏๅพ„ใ€‚ @@ -273,7 +273,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช `CustomORJSONResponse`ใ€‚ไฝ ้œ€่ฆๅš็š„ไธป่ฆไบ‹ๆƒ…ๆ˜ฏๅฎž็Žฐไธ€ไธช่ฟ”ๅ›ž `bytes` ็š„ `Response.render(content)` ๆ–นๆณ•๏ผš -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} ็Žฐๅœจ๏ผŒไธๅ†ๆ˜ฏ่ฟ”ๅ›ž๏ผš @@ -281,7 +281,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ {"message": "Hello World"} ``` -โ€ฆ่ฟ™ไธชๅ“ๅบ”ๅฐ†่ฟ”ๅ›ž๏ผš +...่ฟ™ไธชๅ“ๅบ”ๅฐ†่ฟ”ๅ›ž๏ผš ```json { @@ -299,7 +299,7 @@ FastAPI๏ผˆๅฎž้™…ไธŠๆ˜ฏ Starlette๏ผ‰ๅฐ†่‡ชๅŠจๅŒ…ๅซ Content-Length ็š„ๅคดใ€‚ๅฎƒ ๅœจไธ‹้ข็š„็คบไพ‹ไธญ๏ผŒ**FastAPI** ไผšๅœจๆ‰€ๆœ‰ *่ทฏๅพ„ๆ“ไฝœ* ไธญ้ป˜่ฎคไฝฟ็”จ `ORJSONResponse`๏ผŒ่€Œไธๆ˜ฏ `JSONResponse`ใ€‚ -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | ๆ็คบ diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md index d62aef8f39..f552d779fb 100644 --- a/docs/zh/docs/advanced/dataclasses.md +++ b/docs/zh/docs/advanced/dataclasses.md @@ -59,7 +59,7 @@ FastAPI ๅŸบไบŽ **Pydantic** ๆž„ๅปบ๏ผŒๆˆ‘ๅทฒ็ปๅ‘ไฝ ๅฑ•็คบ่ฟ‡ๅฆ‚ไฝ•ไฝฟ็”จ Pydant ๅœจๆœฌไพ‹ไธญ๏ผŒๅฎƒๆ˜ฏไธ€ไธช `Item` ๆ•ฐๆฎ็ฑปๅˆ—่กจใ€‚ 6. ่ฟ™้‡Œๆˆ‘ไปฌ่ฟ”ๅ›žไธ€ไธชๅญ—ๅ…ธ๏ผŒ้‡Œ้ข็š„ `items` ๆ˜ฏไธ€ไธชๆ•ฐๆฎ็ฑปๅˆ—่กจใ€‚ - FastAPI ไป็„ถ่ƒฝๅคŸๅฐ†ๆ•ฐๆฎๅบๅˆ—ๅŒ–ไธบ JSONใ€‚ + FastAPI ไป็„ถ่ƒฝๅคŸๅฐ†ๆ•ฐๆฎๅบๅˆ—ๅŒ–ไธบ JSONใ€‚ 7. ่ฟ™้‡Œ็š„ `response_model` ไฝฟ็”จไบ† โ€œ`Author` ๆ•ฐๆฎ็ฑปๅˆ—่กจโ€ ็š„็ฑปๅž‹ๆณจ่งฃใ€‚ ๅŒๆ ท๏ผŒไฝ ๅฏไปฅๅฐ† `dataclasses` ไธŽๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃ็ป„ๅˆไฝฟ็”จใ€‚ diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md index 7b49931a4c..71ad1ae383 100644 --- a/docs/zh/docs/advanced/events.md +++ b/docs/zh/docs/advanced/events.md @@ -30,7 +30,7 @@ ๆˆ‘ไปฌไฝฟ็”จ `yield` ๅˆ›ๅปบไบ†ไธ€ไธชๅผ‚ๆญฅๅ‡ฝๆ•ฐ `lifespan()` ๅƒ่ฟ™ๆ ท๏ผš -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} ๅœจ่ฟ™้‡Œ๏ผŒๆˆ‘ไปฌๅœจ `yield` ไน‹ๅ‰ๅฐ†๏ผˆ่™šๆ‹Ÿ็š„๏ผ‰ๆจกๅž‹ๅ‡ฝๆ•ฐๆ”พๅ…ฅๆœบๅ™จๅญฆไน ๆจกๅž‹็š„ๅญ—ๅ…ธไธญ๏ผŒไปฅๆญคๆจกๆ‹ŸๅŠ ่ฝฝๆจกๅž‹็š„่€—ๆ—ถ**ๅฏๅŠจ**ๆ“ไฝœใ€‚่ฟ™ๆฎตไปฃ็ ๅฐ†ๅœจๅบ”็”จ็จ‹ๅบ**ๅผ€ๅง‹ๅค„็†่ฏทๆฑ‚ไน‹ๅ‰**ๆ‰ง่กŒ๏ผŒๅณ**ๅฏๅŠจ**ๆœŸ้—ดใ€‚ @@ -48,7 +48,7 @@ ้ฆ–ๅ…ˆ่ฆๆณจๆ„็š„ๆ˜ฏ๏ผŒๆˆ‘ไปฌๅฎšไน‰ไบ†ไธ€ไธชๅธฆๆœ‰ `yield` ็š„ๅผ‚ๆญฅๅ‡ฝๆ•ฐใ€‚่ฟ™ไธŽๅธฆๆœ‰ `yield` ็š„ไพ่ต–้กน้žๅธธ็›ธไผผใ€‚ -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} ่ฟ™ไธชๅ‡ฝๆ•ฐๅœจ `yield` ไน‹ๅ‰็š„้ƒจๅˆ†๏ผŒไผšๅœจๅบ”็”จๅฏๅŠจๅ‰ๆ‰ง่กŒใ€‚ @@ -60,7 +60,7 @@ ๅฎƒๅฐ†ๅ‡ฝๆ•ฐ่ฝฌๅŒ–ไธบๆ‰€่ฐ“็š„โ€œ**ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**โ€ใ€‚ -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} ๅœจ Python ไธญ๏ผŒ**ไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**ๆ˜ฏไธ€ไธชไฝ ๅฏไปฅๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ็š„ไธœ่ฅฟ๏ผŒไพ‹ๅฆ‚๏ผŒ`open()` ๅฏไปฅไฝœไธบไธŠไธ‹ๆ–‡็ฎก็†ๅ™จไฝฟ็”จใ€‚ @@ -82,7 +82,7 @@ async with lifespan(app): `FastAPI` ็š„ `lifespan` ๅ‚ๆ•ฐๆŽฅๅ—ไธ€ไธช**ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ**๏ผŒๆ‰€ไปฅๆˆ‘ไปฌๅฏไปฅๆŠŠๆˆ‘ไปฌๆ–ฐๅฎšไน‰็š„ๅผ‚ๆญฅไธŠไธ‹ๆ–‡็ฎก็†ๅ™จ `lifespan` ไผ ็ป™ๅฎƒใ€‚ -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## ๆ›ฟไปฃไบ‹ไปถ๏ผˆๅผƒ็”จ๏ผ‰ { #alternative-events-deprecated } @@ -104,7 +104,7 @@ async with lifespan(app): ไฝฟ็”จไบ‹ไปถ `"startup"` ๅฃฐๆ˜Žไธ€ไธชๅœจๅบ”็”จๅฏๅŠจๅ‰่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} ๆœฌไพ‹ไธญ๏ผŒ`startup` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐไธบ้กน็›ฎโ€œๆ•ฐๆฎๅบ“โ€๏ผˆๅชๆ˜ฏไธ€ไธช `dict`๏ผ‰ๆไพ›ไบ†ไธ€ไบ›ๅˆๅง‹ๅ€ผใ€‚ @@ -116,7 +116,7 @@ async with lifespan(app): ไฝฟ็”จไบ‹ไปถ `"shutdown"` ๅฃฐๆ˜Žไธ€ไธชๅœจๅบ”็”จๅ…ณ้—ญๆ—ถ่ฟ่กŒ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} ๆญคๅค„๏ผŒ`shutdown` ไบ‹ไปถๅค„็†ๅ™จๅ‡ฝๆ•ฐไผšๅ‘ๆ–‡ไปถ `log.txt` ๅ†™ๅ…ฅไธ€่กŒๆ–‡ๆœฌ `"Application shutdown"`ใ€‚ diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index 48a4ba07aa..e8a3b20558 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -40,7 +40,7 @@ FastAPI ไผš่‡ชๅŠจ็”Ÿๆˆ **OpenAPI 3.1** ่ง„่Œƒ๏ผŒๅ› ๆญคไฝ ไฝฟ็”จ็š„ไปปไฝ•ๅทฅๅ…ท ๅ…ˆไปŽไธ€ไธช็ฎ€ๅ•็š„ FastAPI ๅบ”็”จๅผ€ๅง‹๏ผš -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} ่ฏทๆณจๆ„๏ผŒ่ฟ™ไบ›*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จ `Item` ๅ’Œ `ResponseMessage` ๆจกๅž‹ๆฅๅฎšไน‰ๅฎƒไปฌ็š„่ฏทๆฑ‚่ฝฝ่ทๅ’Œๅ“ๅบ”่ฝฝ่ทใ€‚ @@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆœ‰ไธ€ไธช **items** ็›ธๅ…ณ็š„้ƒจๅˆ†ๅ’Œๅฆไธ€ไธช **users** ็›ธๅ…ณ็š„้ƒจๅˆ†๏ผŒๅฎƒไปฌๅฏไปฅ็”จๆ ‡็ญพๆฅๅˆ†้š”๏ผš -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### ็”Ÿๆˆๅธฆๆ ‡็ญพ็š„ TypeScript ๅฎขๆˆท็ซฏ { #generate-a-typescript-client-with-tags } @@ -121,7 +121,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -โ€ฆโ€ฆ่ฟ™ๆ˜ฏๅ› ไธบๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จไผšๆŠŠๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„ OpenAPI ๅ†…้ƒจ**ๆ“ไฝœ ID๏ผˆoperation ID๏ผ‰**็”จไฝœๆ–นๆณ•ๅ็š„ไธ€้ƒจๅˆ†ใ€‚ +...่ฟ™ๆ˜ฏๅ› ไธบๅฎขๆˆท็ซฏ็”Ÿๆˆๅ™จไผšๆŠŠๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„ OpenAPI ๅ†…้ƒจ**ๆ“ไฝœ ID๏ผˆoperation ID๏ผ‰**็”จไฝœๆ–นๆณ•ๅ็š„ไธ€้ƒจๅˆ†ใ€‚ OpenAPI ่ฆๆฑ‚ๆฏไธชๆ“ไฝœ ID ๅœจๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ไธญ้ƒฝๆ˜ฏๅ”ฏไธ€็š„๏ผŒๅ› ๆญค FastAPI ไผšไฝฟ็”จ**ๅ‡ฝๆ•ฐๅ**ใ€**่ทฏๅพ„**ๅ’Œ**HTTP ๆ–นๆณ•/ๆ“ไฝœ**ๆฅ็”Ÿๆˆๆ“ไฝœ ID๏ผŒไปฅ็กฎไฟๅ…ถๅ”ฏไธ€ๆ€งใ€‚ @@ -145,7 +145,7 @@ FastAPI ไธบๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จไธ€ไธช**ๅ”ฏไธ€ ID**๏ผŒๅฎƒๆ—ข็”จไบŽ**ๆ“ไฝœ ็„ถๅŽไฝ ๅฏไปฅๆŠŠ่ฟ™ไธช่‡ชๅฎšไน‰ๅ‡ฝๆ•ฐ้€š่ฟ‡ `generate_unique_id_function` ๅ‚ๆ•ฐไผ ็ป™ **FastAPI**๏ผš -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### ไฝฟ็”จ่‡ชๅฎšไน‰ๆ“ไฝœ ID ็”Ÿๆˆ TypeScript ๅฎขๆˆท็ซฏ { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ FastAPI ไธบๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*ไฝฟ็”จไธ€ไธช**ๅ”ฏไธ€ ID**๏ผŒๅฎƒๆ—ข็”จไบŽ**ๆ“ไฝœ ๆˆ‘ไปฌๅฏไปฅๆŠŠ OpenAPI JSON ไธ‹่ฝฝๅˆฐ `openapi.json` ๆ–‡ไปถไธญ๏ผŒ็„ถๅŽ็”จๅฆ‚ไธ‹่„šๆœฌ**็งป้™ค่ฟ™ไธชๆ ‡็ญพๅ‰็ผ€**๏ผš -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md index 108bbbb5c1..de4a3fcb13 100644 --- a/docs/zh/docs/advanced/middleware.md +++ b/docs/zh/docs/advanced/middleware.md @@ -43,7 +43,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") **FastAPI** ไธบๅธธ่ง็”จไพ‹ๆไพ›ไบ†ไธ€ไบ›ไธญ้—ดไปถ๏ผŒไธ‹้ขไป‹็ปๆ€Žไนˆไฝฟ็”จ่ฟ™ไบ›ไธญ้—ดไปถใ€‚ -/// note | ๆณจๆ„ +/// note | ๆŠ€ๆœฏ็ป†่Š‚ ไปฅไธ‹ๅ‡ ไธช็คบไพ‹ไธญไนŸๅฏไปฅไฝฟ็”จ `from starlette.middleware.something import SomethingMiddleware`ใ€‚ @@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ไปปไฝ•ไผ ๅ‘ `http` ๆˆ– `ws` ็š„่ฏทๆฑ‚้ƒฝไผš่ขซ้‡ๅฎšๅ‘่‡ณๅฎ‰ๅ…จๆ–นๆกˆใ€‚ -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } ๅผบๅˆถๆ‰€ๆœ‰ไผ ๅ…ฅ่ฏทๆฑ‚้ƒฝๅฟ…้กปๆญฃ็กฎ่ฎพ็ฝฎ `Host` ่ฏทๆฑ‚ๅคด๏ผŒไปฅ้˜ฒ HTTP ไธปๆœบๅคดๆ”ปๅ‡ปใ€‚ -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} ๆ”ฏๆŒไปฅไธ‹ๅ‚ๆ•ฐ๏ผš @@ -78,7 +78,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ไธญ้—ดไปถไผšๅค„็†ๆ ‡ๅ‡†ๅ“ๅบ”ไธŽๆตๅ“ๅบ”ใ€‚ -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} ๆ”ฏๆŒไปฅไธ‹ๅ‚ๆ•ฐ๏ผš diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md index 6e8df68aef..cc9f5c28e1 100644 --- a/docs/zh/docs/advanced/openapi-callbacks.md +++ b/docs/zh/docs/advanced/openapi-callbacks.md @@ -179,7 +179,7 @@ JSON ่ฏทๆฑ‚ไฝ“ๅŒ…ๅซๅฆ‚ไธ‹ๅ†…ๅฎน๏ผš ### ๆŸฅ็œ‹ๆ–‡ๆกฃ { #check-the-docs } -็Žฐๅœจ๏ผŒไฝฟ็”จ Uvicorn ๅฏๅŠจๅบ”็”จ๏ผŒๆ‰“ๅผ€ http://127.0.0.1:8000/docsใ€‚ +็Žฐๅœจ๏ผŒๅฏๅŠจๅบ”็”จๅนถๆ‰“ๅผ€ http://127.0.0.1:8000/docsใ€‚ ๅฐฑ่ƒฝ็œ‹ๅˆฐๆ–‡ๆกฃ็š„*่ทฏๅพ„ๆ“ไฝœ*ๅทฒ็ปๅŒ…ๅซไบ†**ๅ›ž่ฐƒ**็š„ๅ†…ๅฎนไปฅๅŠ*ๅค–้ƒจ API*๏ผš diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md index 9e64ed4e3c..d23fbcf888 100644 --- a/docs/zh/docs/advanced/openapi-webhooks.md +++ b/docs/zh/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ ๅฝ“ๆ‚จๅˆ›ๅปบไธ€ไธช **FastAPI** ๅบ”็”จ็จ‹ๅบๆ—ถ๏ผŒๆœ‰ไธ€ไธช `webhooks` ๅฑžๆ€งๅฏไปฅ็”จๆฅๅฎšไน‰็ฝ‘็ปœ้’ฉๅญ๏ผŒๆ–นๅผไธŽๆ‚จๅฎšไน‰*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ—ถๅ€™็›ธๅŒ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `@app.webhooks.post()` ใ€‚ -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} ๆ‚จๅฎšไน‰็š„็ฝ‘็ปœ้’ฉๅญๅฐ†่ขซๅŒ…ๅซๅœจ `OpenAPI` ็š„ๆžถๆž„ไธญ๏ผŒๅนถๅ‡บ็Žฐๅœจ่‡ชๅŠจ็”Ÿๆˆ็š„**ๆ–‡ๆกฃ UI** ไธญใ€‚ diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md index 6c9928ffce..588d4f09c5 100644 --- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ ๅŠกๅฟ…็กฎไฟๆฏไธชๆ“ไฝœ็š„ `operation_id` ้ƒฝๆ˜ฏๅ”ฏไธ€็š„ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### ไฝฟ็”จ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ็š„ๅ‡ฝๆ•ฐๅไฝœไธบ operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ ไฝ ๅบ”่ฏฅๅœจๆทปๅŠ ไบ†ๆ‰€ๆœ‰ *่ทฏๅพ„ๆ“ไฝœ* ไน‹ๅŽๆ‰ง่กŒๆญคๆ“ไฝœใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip @@ -40,7 +40,7 @@ ไฝฟ็”จๅ‚ๆ•ฐ `include_in_schema` ๅนถๅฐ†ๅ…ถ่ฎพ็ฝฎไธบ `False`๏ผŒๆฅไปŽ็”Ÿๆˆ็š„ OpenAPI ๆ–นๆกˆไธญๆŽ’้™คไธ€ไธช *่ทฏๅพ„ๆ“ไฝœ*๏ผˆ่ฟ™ๆ ทไธ€ๆฅ๏ผŒๅฐฑไปŽ่‡ชๅŠจๅŒ–ๆ–‡ๆกฃ็ณป็ปŸไธญๆŽ’้™คๆމไบ†๏ผ‰๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## ๆฅ่‡ช docstring ็š„้ซ˜็บงๆ่ฟฐ { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ ไพ‹ๅฆ‚๏ผŒ่ฟ™ไธช `openapi_extra` ๅฏ็”จไบŽๅฃฐๆ˜Ž [OpenAPI ๆ‰ฉๅฑ•](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} ๅฝ“ไฝ ๆ‰“ๅผ€่‡ชๅŠจ API ๆ–‡ๆกฃๆ—ถ๏ผŒไฝ ็š„ๆ‰ฉๅฑ•ไผšๆ˜พ็คบๅœจ่ฏฅ *่ทฏๅพ„ๆ“ไฝœ* ็š„ๅบ•้ƒจใ€‚ @@ -139,9 +139,9 @@ ไฝ ๅฏไปฅ็”จ `openapi_extra` ๆฅๅšๅˆฐ๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -ๅœจ่ฟ™ไธช็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ• Pydantic ๆจกๅž‹ใ€‚ไบ‹ๅฎžไธŠ๏ผŒ่ฏทๆฑ‚ไฝ“็”š่‡ณๆฒกๆœ‰่ขซ ่งฃๆž ไธบ JSON๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅไปฅ `bytes` ่ฏปๅ–๏ผŒๅนถ็”ฑๅ‡ฝๆ•ฐ `magic_data_reader()` ไปฅๆŸ็งๆ–นๅผ่ดŸ่ดฃ่งฃๆžใ€‚ +ๅœจ่ฟ™ไธช็คบไพ‹ไธญ๏ผŒๆˆ‘ไปฌๆฒกๆœ‰ๅฃฐๆ˜Žไปปไฝ• Pydantic ๆจกๅž‹ใ€‚ไบ‹ๅฎžไธŠ๏ผŒ่ฏทๆฑ‚ไฝ“็”š่‡ณๆฒกๆœ‰่ขซ ่งฃๆž ไธบ JSON๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅไปฅ `bytes` ่ฏปๅ–๏ผŒๅนถ็”ฑๅ‡ฝๆ•ฐ `magic_data_reader()` ไปฅๆŸ็งๆ–นๅผ่ดŸ่ดฃ่งฃๆžใ€‚ ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒๆˆ‘ไปฌไป็„ถๅฏไปฅๅฃฐๆ˜Ž่ฏทๆฑ‚ไฝ“็š„้ข„ๆœŸๆ–นๆกˆใ€‚ @@ -153,7 +153,7 @@ ไพ‹ๅฆ‚๏ผŒๅœจ่ฟ™ไธชๅบ”็”จไธญๆˆ‘ไปฌไธไฝฟ็”จ FastAPI ้›†ๆˆ็š„ไปŽ Pydantic ๆจกๅž‹ๆๅ– JSON Schema ็š„ๅŠŸ่ƒฝ๏ผŒไนŸไธไฝฟ็”จๅฏน JSON ็š„่‡ชๅŠจๆ ก้ชŒใ€‚ๅฎž้™…ไธŠ๏ผŒๆˆ‘ไปฌๅฐ†่ฏทๆฑ‚็š„ๅ†…ๅฎน็ฑปๅž‹ๅฃฐๆ˜Žไธบ YAML๏ผŒ่€Œไธๆ˜ฏ JSON๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} ๅฐฝ็ฎกๆˆ‘ไปฌๆฒกๆœ‰ไฝฟ็”จ้ป˜่ฎค็š„้›†ๆˆๅŠŸ่ƒฝ๏ผŒๆˆ‘ไปฌไป็„ถไฝฟ็”จ Pydantic ๆจกๅž‹ๆ‰‹ๅŠจ็”Ÿๆˆๆˆ‘ไปฌๆƒณไปฅ YAML ๆŽฅๆ”ถ็š„ๆ•ฐๆฎ็š„ JSON Schemaใ€‚ @@ -161,7 +161,7 @@ ๆŽฅ็€ๅœจๆˆ‘ไปฌ็š„ไปฃ็ ไธญ๏ผŒๆˆ‘ไปฌ็›ดๆŽฅ่งฃๆž่ฏฅ YAML ๅ†…ๅฎน๏ผŒ็„ถๅŽๅ†ๆฌกไฝฟ็”จๅŒไธ€ไธช Pydantic ๆจกๅž‹ๆฅ้ชŒ่ฏ่ฏฅ YAML ๅ†…ๅฎน๏ผš -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md index cdcd39f50c..0b004bf4e5 100644 --- a/docs/zh/docs/advanced/response-change-status-code.md +++ b/docs/zh/docs/advanced/response-change-status-code.md @@ -20,9 +20,11 @@ ็„ถๅŽไฝ ๅฏไปฅๅœจ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎ`status_code`ใ€‚ -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} -็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช`dict`ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช`response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ +็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช`dict`ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช`response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ **FastAPI**ๅฐ†ไฝฟ็”จ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๆฅๆๅ–็Šถๆ€็ ๏ผˆไนŸๅŒ…ๆ‹ฌcookiesๅ’Œๅคด้ƒจ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ•`response_model`่ฟ‡ๆปคใ€‚ diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md index cc311a2708..c618cd0f0a 100644 --- a/docs/zh/docs/advanced/response-cookies.md +++ b/docs/zh/docs/advanced/response-cookies.md @@ -4,7 +4,7 @@ ไฝ ๅฏไปฅๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญๅฎšไน‰ไธ€ไธช็ฑปๅž‹ไธบ `Response` ็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅœจ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎcookieไบ†ใ€‚ -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} ่€Œไธ”ไฝ ่ฟ˜ๅฏไปฅๆ นๆฎไฝ ็š„้œ€่ฆๅ“ๅบ”ไธๅŒ็š„ๅฏน่ฑก๏ผŒๆฏ”ๅฆ‚ๅธธ็”จ็š„ `dict`๏ผŒๆ•ฐๆฎๅบ“model็ญ‰ใ€‚ @@ -22,9 +22,9 @@ ็„ถๅŽ่ฎพ็ฝฎCookies๏ผŒๅนถ่ฟ”ๅ›ž๏ผš -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | ๆ็คบ ้œ€่ฆๆณจๆ„๏ผŒๅฆ‚ๆžœไฝ ็›ดๆŽฅๅ้ฆˆไธ€ไธชresponseๅฏน่ฑก๏ผŒ่€Œไธๆ˜ฏไฝฟ็”จ`Response`ๅ…ฅๅ‚๏ผŒFastAPIๅˆ™ไผš็›ดๆŽฅๅ้ฆˆไฝ ๅฐ่ฃ…็š„responseๅฏน่ฑกใ€‚ diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md index 8a9cf6ab89..a97992d249 100644 --- a/docs/zh/docs/advanced/response-directly.md +++ b/docs/zh/docs/advanced/response-directly.md @@ -36,7 +36,7 @@ {* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} -/// note | ๆณจๆ„ +/// note | ๆŠ€ๆœฏ็ป†่Š‚ ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import JSONResponse`ใ€‚ @@ -54,7 +54,7 @@ ไฝ ๅฏไปฅๆŠŠไฝ ็š„ XML ๅ†…ๅฎนๆ”พๅˆฐไธ€ไธชๅญ—็ฌฆไธฒไธญ๏ผŒๆ”พๅˆฐไธ€ไธช `Response` ไธญ๏ผŒ็„ถๅŽ่ฟ”ๅ›ž๏ผš -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ## ่ฏดๆ˜Ž { #notes } diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md index fa02f53bea..01bde56d2a 100644 --- a/docs/zh/docs/advanced/response-headers.md +++ b/docs/zh/docs/advanced/response-headers.md @@ -6,13 +6,13 @@ ็„ถๅŽไฝ ๅฏไปฅๅœจ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๅฏน่ฑกไธญ่ฎพ็ฝฎๅคด้ƒจใ€‚ -{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} ็„ถๅŽไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆ ท่ฟ”ๅ›žไปปไฝ•ไฝ ้œ€่ฆ็š„ๅฏน่ฑก๏ผˆไพ‹ๅฆ‚ไธ€ไธช `dict` ๆˆ–่€…ไธ€ไธชๆ•ฐๆฎๅบ“ๆจกๅž‹๏ผ‰ใ€‚ ๅฆ‚ๆžœไฝ ๅฃฐๆ˜Žไบ†ไธ€ไธช `response_model`๏ผŒๅฎƒไป็„ถไผš่ขซ็”จๆฅ่ฟ‡ๆปคๅ’Œ่ฝฌๆขไฝ ่ฟ”ๅ›ž็š„ๅฏน่ฑกใ€‚ -**FastAPI** ๅฐ†ไฝฟ็”จ่ฟ™ไธชไธดๆ—ถๅ“ๅบ”ๆฅๆๅ–ๅคด้ƒจ๏ผˆไนŸๅŒ…ๆ‹ฌ cookies ๅ’Œ็Šถๆ€็ ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ• `response_model` ่ฟ‡ๆปคใ€‚ +**FastAPI** ๅฐ†ไฝฟ็”จ่ฟ™ไธช*ไธดๆ—ถ*ๅ“ๅบ”ๆฅๆๅ–ๅคด้ƒจ๏ผˆไนŸๅŒ…ๆ‹ฌ cookies ๅ’Œ็Šถๆ€็ ๏ผ‰๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅ…ฅๅŒ…ๅซไฝ ่ฟ”ๅ›ž็š„ๅ€ผ็š„ๆœ€็ปˆๅ“ๅบ”ไธญ๏ผŒ่ฏฅๅ“ๅบ”็”ฑไปปไฝ• `response_model` ่ฟ‡ๆปคใ€‚ ไฝ ไนŸๅฏไปฅๅœจไพ่ต–้กนไธญๅฃฐๆ˜Ž `Response` ๅ‚ๆ•ฐ๏ผŒๅนถๅœจๅ…ถไธญ่ฎพ็ฝฎๅคด้ƒจ๏ผˆๅ’Œ cookies๏ผ‰ใ€‚ @@ -22,7 +22,7 @@ ๆŒ‰็…ง[็›ดๆŽฅ่ฟ”ๅ›žๅ“ๅบ”](response-directly.md){.internal-link target=_blank}ไธญๆ‰€่ฟฐๅˆ›ๅปบๅ“ๅบ”๏ผŒๅนถๅฐ†ๅคด้ƒจไฝœไธบ้™„ๅŠ ๅ‚ๆ•ฐไผ ้€’๏ผš -{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} /// note | ๆŠ€ๆœฏ็ป†่Š‚ diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md index 55479d8e34..9128a49753 100644 --- a/docs/zh/docs/advanced/security/http-basic-auth.md +++ b/docs/zh/docs/advanced/security/http-basic-auth.md @@ -20,7 +20,7 @@ HTTP ๅŸบ็ก€ๆŽˆๆƒ่ฎฉๆต่งˆๅ™จๆ˜พ็คบๅ†…็ฝฎ็š„็”จๆˆทๅไธŽๅฏ†็ ๆ็คบใ€‚ * ่ฟ”ๅ›ž็ฑปๅž‹ไธบ `HTTPBasicCredentials` ็š„ๅฏน่ฑก๏ผš * ๅŒ…ๅซๅ‘้€็š„ `username` ไธŽ `password` -{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} ็ฌฌไธ€ๆฌกๆ‰“ๅผ€ URL๏ผˆๆˆ–ๅœจ API ๆ–‡ๆกฃไธญ็‚นๅ‡ป **Execute** ๆŒ‰้’ฎ๏ผ‰ๆ—ถ๏ผŒๆต่งˆๅ™จ่ฆๆฑ‚่พ“ๅ…ฅ็”จๆˆทๅไธŽๅฏ†็ ๏ผš @@ -40,7 +40,7 @@ HTTP ๅŸบ็ก€ๆŽˆๆƒ่ฎฉๆต่งˆๅ™จๆ˜พ็คบๅ†…็ฝฎ็š„็”จๆˆทๅไธŽๅฏ†็ ๆ็คบใ€‚ ็„ถๅŽๆˆ‘ไปฌๅฏไปฅไฝฟ็”จ `secrets.compare_digest()` ๆฅ็กฎไฟ `credentials.username` ๆ˜ฏ `"stanleyjobson"`๏ผŒไธ” `credentials.password` ๆ˜ฏ`"swordfish"`ใ€‚ -{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} ่ฟ™็ฑปไผผไบŽ๏ผš @@ -104,4 +104,4 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": ๆฃ€ๆต‹ๅˆฐๅ‡ญ่ฏไธๆญฃ็กฎๅŽ๏ผŒ่ฟ”ๅ›ž `HTTPException` ๅŠ็Šถๆ€็  401๏ผˆไธŽๆ— ๅ‡ญ่ฏๆ—ถ่ฟ”ๅ›ž็š„ๅ†…ๅฎนไธ€ๆ ท๏ผ‰๏ผŒๅนถๆทปๅŠ ๅ“ๅบ”ๅคด `WWW-Authenticate`๏ผŒ่ฎฉๆต่งˆๅ™จๅ†ๆฌกๆ˜พ็คบ็™ปๅฝ•ๆ็คบ๏ผš -{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md index adf2644915..b4def73eb5 100644 --- a/docs/zh/docs/advanced/settings.md +++ b/docs/zh/docs/advanced/settings.md @@ -54,7 +54,7 @@ $ pip install "fastapi[all]" ไฝ ๅฏไปฅไฝฟ็”จไธŽ Pydantic ๆจกๅž‹็›ธๅŒ็š„้ชŒ่ฏๅŠŸ่ƒฝๅ’Œๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ไธๅŒ็š„ๆ•ฐๆฎ็ฑปๅž‹๏ผŒไปฅๅŠไฝฟ็”จ `Field()` ่ฟ›่กŒ้™„ๅŠ ้ชŒ่ฏใ€‚ -{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} /// tip | ๆ็คบ @@ -70,7 +70,7 @@ $ pip install "fastapi[all]" ็„ถๅŽไฝ ๅฏไปฅๅœจๅบ”็”จไธญไฝฟ็”จๆ–ฐ็š„ `settings` ๅฏน่ฑก๏ผš -{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} ### ่ฟ่กŒๆœๅŠกๅ™จ { #run-the-server } @@ -100,19 +100,19 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## ๅœจๅฆไธ€ไธชๆจกๅ—ไธญๆ”พ็ฝฎ่ฎพ็ฝฎ { #settings-in-another-module } -ไฝ ๅฏไปฅๆŠŠ่ฟ™ไบ›่ฎพ็ฝฎๆ”พๅœจๅฆไธ€ไธชๆจกๅ—ๆ–‡ไปถไธญ๏ผŒๅฐฑๅƒไฝ ๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ +ไฝ ๅฏไปฅๆŠŠ่ฟ™ไบ›่ฎพ็ฝฎๆ”พๅœจๅฆไธ€ไธชๆจกๅ—ๆ–‡ไปถไธญ๏ผŒๅฐฑๅƒไฝ ๅœจ[ๆ›ดๅคง็š„ๅบ”็”จ - ๅคšไธชๆ–‡ไปถ](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ ไพ‹ๅฆ‚๏ผŒๅฏไปฅๆœ‰ไธ€ไธช `config.py` ๆ–‡ไปถ๏ผš -{* ../../docs_src/settings/app01_py39/config.py *} +{* ../../docs_src/settings/app01_py310/config.py *} ็„ถๅŽๅœจ `main.py` ๆ–‡ไปถไธญไฝฟ็”จๅฎƒ๏ผš -{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} /// tip | ๆ็คบ -ไฝ ่ฟ˜้œ€่ฆไธ€ไธช `__init__.py` ๆ–‡ไปถ๏ผŒๅฐฑๅƒไฝ ๅœจ[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ +ไฝ ่ฟ˜้œ€่ฆไธ€ไธช `__init__.py` ๆ–‡ไปถ๏ผŒๅฐฑๅƒไฝ ๅœจ[ๆ›ดๅคง็š„ๅบ”็”จ - ๅคšไธชๆ–‡ไปถ](../tutorial/bigger-applications.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐ็š„้‚ฃๆ ทใ€‚ /// @@ -126,7 +126,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ๅปถ็ปญไธŠไธ€ไธช็คบไพ‹๏ผŒไฝ ็š„ `config.py` ๆ–‡ไปถๅฏ่ƒฝๅฆ‚ไธ‹ๆ‰€็คบ๏ผš -{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} ๆณจๆ„๏ผŒ็Žฐๅœจๆˆ‘ไปฌไธๅ†ๅˆ›ๅปบ้ป˜่ฎคๅฎžไพ‹ `settings = Settings()`ใ€‚ @@ -134,7 +134,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ็Žฐๅœจๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธชไพ่ต–้กน๏ผŒ่ฟ”ๅ›žไธ€ไธชๆ–ฐ็š„ `config.Settings()`ใ€‚ -{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} /// tip | ๆ็คบ @@ -144,15 +144,15 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// -็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅœจโ€œ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐโ€ไธญๅฐ†ๅ…ถไฝœไธบไพ่ต–้กนๅผ•ๅ…ฅ๏ผŒๅนถๅœจ้œ€่ฆ็š„ไปปไฝ•ๅœฐๆ–นไฝฟ็”จๅฎƒใ€‚ +็„ถๅŽๆˆ‘ไปฌๅฏไปฅๅœจ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไธญๅฐ†ๅ…ถไฝœไธบไพ่ต–้กนๅผ•ๅ…ฅ๏ผŒๅนถๅœจ้œ€่ฆ็š„ไปปไฝ•ๅœฐๆ–นไฝฟ็”จๅฎƒใ€‚ -{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} ### ่ฎพ็ฝฎไธŽๆต‹่ฏ• { #settings-and-testing } ๆŽฅ็€๏ผŒๅœจๆต‹่ฏ•ๆœŸ้—ด๏ผŒ้€š่ฟ‡ไธบ `get_settings` ๅˆ›ๅปบไพ่ต–้กน่ฆ†็›–๏ผŒๅฐฑๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐๆไพ›ไธ€ไธชไธๅŒ็š„่ฎพ็ฝฎๅฏน่ฑก๏ผš -{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} ๅœจไพ่ต–้กน่ฆ†็›–ไธญ๏ผŒๆˆ‘ไปฌๅœจๅˆ›ๅปบๆ–ฐ็š„ `Settings` ๅฏน่ฑกๆ—ถไธบ `admin_email` ่ฎพ็ฝฎไบ†ไธ€ไธชๆ–ฐๅ€ผ๏ผŒ็„ถๅŽ่ฟ”ๅ›ž่ฏฅๆ–ฐๅฏน่ฑกใ€‚ @@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" ็„ถๅŽๆ›ดๆ–ฐ `config.py`๏ผš -{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} /// tip | ๆ็คบ @@ -226,7 +226,7 @@ def get_settings(): ไฝ†็”ฑไบŽๆˆ‘ไปฌๅœจ้กถ้ƒจไฝฟ็”จไบ† `@lru_cache` ่ฃ…้ฅฐๅ™จ๏ผŒ`Settings` ๅฏน่ฑกๅชไผšๅœจ็ฌฌไธ€ๆฌก่ฐƒ็”จๆ—ถๅˆ›ๅปบไธ€ๆฌกใ€‚ โœ”๏ธ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} ๆŽฅ็€๏ผŒๅฏนไบŽๅŽ็ปญ่ฏทๆฑ‚ไธญไพ่ต–้กน้‡Œๅฏน `get_settings()` ็š„ไปปไฝ•่ฐƒ็”จ๏ผŒๅฎƒไธไผšๅ†ๆฌกๆ‰ง่กŒ `get_settings()` ็š„ๅ†…้ƒจไปฃ็ ๅนถๅˆ›ๅปบๆ–ฐ็š„ `Settings` ๅฏน่ฑก๏ผŒ่€Œๆ˜ฏไผšไธ€้ๅˆไธ€้ๅœฐ่ฟ”ๅ›ž็ฌฌไธ€ๆฌก่ฐƒ็”จๆ—ถ่ฟ”ๅ›ž็š„้‚ฃไธช็›ธๅŒๅฏน่ฑกใ€‚ diff --git a/docs/zh/docs/advanced/sub-applications.md b/docs/zh/docs/advanced/sub-applications.md index fe1fcd1211..3e61610a37 100644 --- a/docs/zh/docs/advanced/sub-applications.md +++ b/docs/zh/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ ้ฆ–ๅ…ˆ๏ผŒๅˆ›ๅปบไธป๏ผˆ้กถๅฑ‚๏ผ‰**FastAPI** ๅบ”็”จๅŠๅ…ถ*่ทฏๅพ„ๆ“ไฝœ*๏ผš -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### ๅญๅบ”็”จ { #sub-application } @@ -18,7 +18,7 @@ ๅญๅบ”็”จๅชๆ˜ฏๅฆไธ€ไธชๆ ‡ๅ‡† FastAPI ๅบ”็”จ๏ผŒไฝ†่ฟ™ไธชๅบ”็”จๆ˜ฏ่ขซ**ๆŒ‚่ฝฝ**็š„ๅบ”็”จ๏ผš -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### ๆŒ‚่ฝฝๅญๅบ”็”จ { #mount-the-sub-application } @@ -26,7 +26,7 @@ ๆœฌไพ‹็š„ๅญๅบ”็”จๆŒ‚่ฝฝๅœจ `/subapi` ่ทฏๅพ„ไธ‹๏ผš -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### ๆŸฅ็œ‹่‡ชๅŠจ API ๆ–‡ๆกฃ { #check-the-automatic-api-docs } diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md index f2e5c21cf3..37575aff29 100644 --- a/docs/zh/docs/advanced/templates.md +++ b/docs/zh/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 * ๅœจ่ฟ”ๅ›žๆจกๆฟ็š„*่ทฏๅพ„ๆ“ไฝœ*ไธญๅฃฐๆ˜Ž `Request` ๅ‚ๆ•ฐ * ไฝฟ็”จ `templates` ๆธฒๆŸ“ๅนถ่ฟ”ๅ›ž `TemplateResponse`๏ผŒไผ ้€’ๆจกๆฟ็š„ๅ็งฐใ€request ๅฏน่ฑกไปฅๅŠไธ€ไธชๅŒ…ๅซๅคšไธช้”ฎๅ€ผๅฏน๏ผˆ็”จไบŽ Jinja2 ๆจกๆฟ๏ผ‰็š„ "context" ๅญ—ๅ…ธใ€‚ -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note diff --git a/docs/zh/docs/advanced/testing-dependencies.md b/docs/zh/docs/advanced/testing-dependencies.md index db0b39483d..3291cfc256 100644 --- a/docs/zh/docs/advanced/testing-dependencies.md +++ b/docs/zh/docs/advanced/testing-dependencies.md @@ -46,7 +46,6 @@ FastAPI ๅฏไปฅ่ฆ†็›–่ฟ™ไบ›ไฝ็ฝฎ็š„ไพ่ต–้กนใ€‚ app.dependency_overrides = {} ``` - /// tip | ๆ็คบ ๅฆ‚ๆžœๅชๅœจๆŸไบ›ๆต‹่ฏ•ๆ—ถ่ฆ†็›–ไพ่ต–้กน๏ผŒๆ‚จๅฏไปฅๅœจๆต‹่ฏ•ๅผ€ๅง‹ๆ—ถ๏ผˆๅœจๆต‹่ฏ•ๅ‡ฝๆ•ฐๅ†…๏ผ‰่ฎพ็ฝฎ่ฆ†็›–ไพ่ต–้กน๏ผŒๅนถๅœจ็ป“ๆŸๆ—ถ๏ผˆๅœจๆต‹่ฏ•ๅ‡ฝๆ•ฐ็ป“ๅฐพ๏ผ‰้‡็ฝฎ่ฆ†็›–ไพ่ต–้กนใ€‚ diff --git a/docs/zh/docs/advanced/testing-events.md b/docs/zh/docs/advanced/testing-events.md index 221984e906..90cbbda131 100644 --- a/docs/zh/docs/advanced/testing-events.md +++ b/docs/zh/docs/advanced/testing-events.md @@ -2,10 +2,10 @@ ๅฝ“ไฝ ้œ€่ฆๅœจๆต‹่ฏ•ไธญ่ฟ่กŒ `lifespan` ๆ—ถ๏ผŒๅฏไปฅๅฐ† `TestClient` ไธŽ `with` ่ฏญๅฅไธ€่ตทไฝฟ็”จ๏ผš -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} ไฝ ๅฏไปฅๅœจ[ๅฎ˜ๆ–น Starlette ๆ–‡ๆกฃ็ซ™็‚น็š„โ€œๅœจๆต‹่ฏ•ไธญ่ฟ่กŒ lifespanโ€](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)้˜…่ฏปๆ›ดๅคš็ป†่Š‚ใ€‚ ๅฏนไบŽๅทฒๅผƒ็”จ็š„ `startup` ๅ’Œ `shutdown` ไบ‹ไปถ๏ผŒๅฏไปฅๆŒ‰ๅฆ‚ไธ‹ๆ–นๅผไฝฟ็”จ `TestClient`๏ผš -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/zh/docs/advanced/testing-websockets.md b/docs/zh/docs/advanced/testing-websockets.md index 64e1d3005f..e435e41e23 100644 --- a/docs/zh/docs/advanced/testing-websockets.md +++ b/docs/zh/docs/advanced/testing-websockets.md @@ -4,7 +4,7 @@ ไธบๆญค๏ผŒๅœจ `with` ่ฏญๅฅไธญไฝฟ็”จ `TestClient` ่ฟžๆŽฅๅˆฐ WebSocket๏ผš -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | ๆณจๆ„ diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md index 64ba8da1b4..8cfad4203a 100644 --- a/docs/zh/docs/advanced/using-request-directly.md +++ b/docs/zh/docs/advanced/using-request-directly.md @@ -29,7 +29,7 @@ ๆญคๆ—ถ๏ผŒ้œ€่ฆ็›ดๆŽฅ่ฎฟ้—ฎ่ฏทๆฑ‚ใ€‚ -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} ๆŠŠ*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ็ฑปๅž‹ๅฃฐๆ˜Žไธบ `Request`๏ผŒ**FastAPI** ๅฐฑ่ƒฝๆŠŠ `Request` ไผ ้€’ๅˆฐๅ‚ๆ•ฐ้‡Œใ€‚ diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md index 4486a2e69f..513e1aaecd 100644 --- a/docs/zh/docs/advanced/websockets.md +++ b/docs/zh/docs/advanced/websockets.md @@ -38,13 +38,13 @@ $ pip install websockets ไฝ†่ฟ™ๆ˜ฏไธ€็งไธ“ๆณจไบŽ WebSockets ็š„ๆœๅŠกๅ™จ็ซฏๅนถๆไพ›ไธ€ไธชๅทฅไฝœ็คบไพ‹็š„ๆœ€็ฎ€ๅ•ๆ–นๅผ๏ผš -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## ๅˆ›ๅปบ `websocket` { #create-a-websocket } ๅœจๆ‚จ็š„ **FastAPI** ๅบ”็”จ็จ‹ๅบไธญ๏ผŒๅˆ›ๅปบไธ€ไธช `websocket`๏ผš -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | ๆŠ€ๆœฏ็ป†่Š‚ @@ -58,7 +58,7 @@ $ pip install websockets ๅœจๆ‚จ็š„ WebSocket ่ทฏ็”ฑไธญ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ `await` ็ญ‰ๅพ…ๆถˆๆฏๅนถๅ‘้€ๆถˆๆฏใ€‚ -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} ๆ‚จๅฏไปฅๆŽฅๆ”ถๅ’Œๅ‘้€ไบŒ่ฟ›ๅˆถใ€ๆ–‡ๆœฌๅ’Œ JSON ๆ•ฐๆฎใ€‚ @@ -154,7 +154,7 @@ $ fastapi dev main.py ๅฝ“ WebSocket ่ฟžๆŽฅๅ…ณ้—ญๆ—ถ๏ผŒ`await websocket.receive_text()` ๅฐ†ๅผ•ๅ‘ `WebSocketDisconnect` ๅผ‚ๅธธ๏ผŒๆ‚จๅฏไปฅๆ•่Žทๅนถๅค„็†่ฏฅๅผ‚ๅธธ๏ผŒๅฐฑๅƒๆœฌ็คบไพ‹ไธญ็š„็คบไพ‹ไธ€ๆ ทใ€‚ -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} ๅฐ่ฏ•ไปฅไธ‹ๆ“ไฝœ๏ผš diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md index 73fcb32196..487fbf8ddb 100644 --- a/docs/zh/docs/advanced/wsgi.md +++ b/docs/zh/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ ไน‹ๅŽๅฐ†ๅ…ถๆŒ‚่ฝฝๅˆฐๆŸไธ€ไธช่ทฏๅพ„ไธ‹ใ€‚ -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | ๆณจๆ„ diff --git a/docs/zh/docs/alternatives.md b/docs/zh/docs/alternatives.md new file mode 100644 index 0000000000..8a552c91d4 --- /dev/null +++ b/docs/zh/docs/alternatives.md @@ -0,0 +1,482 @@ +# ๆ›ฟไปฃๆ–นๆกˆใ€็ตๆ„ŸไธŽๅฏนๆฏ” { #alternatives-inspiration-and-comparisons } + +ๆ˜ฏไป€ไนˆๅฏๅ‘ไบ† **FastAPI**๏ผŒๅฎƒไธŽๆ›ฟไปฃๆ–นๆกˆ็š„ๆฏ”่พƒ๏ผŒไปฅๅŠๅฎƒไปŽไธญๅญฆๅˆฐ็š„ไธœ่ฅฟใ€‚ + +## ไป‹็ป { #intro } + +ๆฒกๆœ‰ๅ‰ไบบ็š„ๅทฅไฝœ๏ผŒๅฐฑไธไผšๆœ‰ **FastAPI**ใ€‚ + +ๅœจๅฎƒ่ฏž็”Ÿไน‹ๅ‰๏ผŒๅทฒ็ปๆœ‰่ฎธๅคšๅทฅๅ…ทไธบๅ…ถๆไพ›ไบ†็ตๆ„Ÿใ€‚ + +ๆˆ‘ๆ›พ็ปๅคšๅนด้ฟๅ…ๅˆ›ๅปบไธ€ไธชๆ–ฐๆก†ๆžถใ€‚่ตทๅˆ๏ผŒๆˆ‘ๅฐ่ฏ•็”จ่ฎธๅคšไธๅŒ็š„ๆก†ๆžถใ€ๆ’ไปถๅ’Œๅทฅๅ…ทๆฅ่งฃๅ†ณ **FastAPI** ๆ‰€่ฆ†็›–็š„ๅ…จ้ƒจๅŠŸ่ƒฝใ€‚ + +ไฝ†ๅœจๆŸไธชๆ—ถๅˆป๏ผŒ้™คไบ†ๅˆ›้€ ไธ€ไธช่ƒฝๆไพ›ๆ‰€ๆœ‰่ฟ™ไบ›ๅŠŸ่ƒฝ็š„ไธœ่ฅฟไน‹ๅค–๏ผŒๅˆซๆ— ้€‰ๆ‹ฉ๏ผ›ๅฎƒ่ฆๅธๆ”ถไปฅๅพ€ๅทฅๅ…ท็š„ๆœ€ไฝณ็†ๅฟต๏ผŒๅนถไปฅๅฐฝๅฏ่ƒฝๅฅฝ็š„ๆ–นๅผ็ป„ๅˆ่ตทๆฅ๏ผŒๅˆฉ็”จไน‹ๅ‰้ƒฝไธๅญ˜ๅœจ็š„่ฏญ่จ€็‰นๆ€ง๏ผˆPython 3.6+ ็ฑปๅž‹ๆ็คบ๏ผ‰ใ€‚ + +## ๅ…ˆๅ‰็š„ๅทฅๅ…ท { #previous-tools } + +### Django { #django } + +ๅฎƒๆ˜ฏๆœ€ๆต่กŒไธ”่ขซๅนฟๆณ›ไฟกไปป็š„ Python ๆก†ๆžถใ€‚่ขซ็”จไบŽๆž„ๅปบ Instagram ็ญ‰็ณป็ปŸใ€‚ + +ๅฎƒไธŽๅ…ณ็ณปๅž‹ๆ•ฐๆฎๅบ“๏ผˆๅฆ‚ MySQLใ€PostgreSQL๏ผ‰่€ฆๅˆ็›ธๅฏน็ดงๅฏ†๏ผŒๅ› ๆญค่‹ฅ่ฆไปฅ NoSQL ๆ•ฐๆฎๅบ“๏ผˆๅฆ‚ Couchbaseใ€MongoDBใ€Cassandra ็ญ‰๏ผ‰ไฝœไธบไธป่ฆๅญ˜ๅ‚จๅผ•ๆ“Žๅนถไธๅฎนๆ˜“ใ€‚ + +ๅฎƒๆœ€ๅˆ็”จไบŽๅœจๅŽ็ซฏ็”Ÿๆˆ HTML๏ผŒ่€Œไธๆ˜ฏๅˆ›ๅปบ็”ฑ็Žฐไปฃๅ‰็ซฏ๏ผˆๅฆ‚ Reactใ€Vue.jsใ€Angular๏ผ‰ๆˆ–ไธŽไน‹้€šไฟก็š„ๅ…ถไป–็ณป็ปŸ๏ผˆๅฆ‚ IoT ่ฎพๅค‡๏ผ‰ไฝฟ็”จ็š„ APIใ€‚ + +### Django REST Framework { #django-rest-framework } + +Django REST framework ไฝœไธบไธ€ไธช็ตๆดปๅทฅๅ…ท็ฎฑ่€Œๅˆ›ๅปบ๏ผŒ็”จไบŽๅœจๅบ•ๅฑ‚ไฝฟ็”จ Django ๆž„ๅปบ Web API๏ผŒไปŽ่€Œๅขžๅผบๅ…ถ API ่ƒฝๅŠ›ใ€‚ + +ๅฎƒ่ขซๅŒ…ๆ‹ฌ Mozillaใ€Red Hatใ€Eventbrite ๅœจๅ†…็š„่ฎธๅคšๅ…ฌๅธไฝฟ็”จใ€‚ + +ๅฎƒๆ˜ฏๆœ€ๆ—ฉ็š„โ€œ่‡ชๅŠจ API ๆ–‡ๆกฃโ€็š„่Œƒไพ‹ไน‹ไธ€๏ผŒ่ฟ™ๆญฃๆ˜ฏๅฏๅ‘โ€œๅฏปๆ‰พโ€ **FastAPI** ็š„ๆœ€ๅˆๆƒณๆณ•ไน‹ไธ€ใ€‚ + +/// note | ๆณจๆ„ + +Django REST Framework ็”ฑ Tom Christie ๅˆ›ๅปบใ€‚ไป–ไนŸๆ˜ฏ Starlette ๅ’Œ Uvicorn ็š„ไฝœ่€…๏ผŒ**FastAPI** ๅฐฑๆ˜ฏๅŸบไบŽๅฎƒไปฌๆž„ๅปบ็š„ใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ๆไพ›่‡ชๅŠจๅŒ–็š„ API ๆ–‡ๆกฃ Web ็•Œ้ขใ€‚ + +/// + +### Flask { #flask } + +Flask ๆ˜ฏไธ€ไธชโ€œๅพฎๆก†ๆžถโ€๏ผŒๅฎƒไธๅŒ…ๅซๆ•ฐๆฎๅบ“้›†ๆˆ๏ผŒไนŸๆฒกๆœ‰ๅƒ Django ้‚ฃๆ ท็š„่ฎธๅคš้ป˜่ฎคๅ†…ๅปบๅŠŸ่ƒฝใ€‚ + +่ฟ™็ง็ฎ€ๅ•ไธŽ็ตๆดปไฝฟๅพ—ๅฏไปฅๅฐ† NoSQL ๆ•ฐๆฎๅบ“ไฝœไธบไธป่ฆ็š„ๆ•ฐๆฎๅญ˜ๅ‚จ็ณป็ปŸใ€‚ + +็”ฑไบŽ้žๅธธ็ฎ€ๅ•๏ผŒๅฎƒ็›ธๅฏน็›ด่ง‚ๆ˜“ๅญฆ๏ผŒๅฐฝ็ฎกๆ–‡ๆกฃๅœจๆŸไบ›้ƒจๅˆ†็•ฅๆ˜พๅๆŠ€ๆœฏใ€‚ + +ๅฎƒไนŸๅธธ็”จไบŽไธไธ€ๅฎš้œ€่ฆๆ•ฐๆฎๅบ“ใ€็”จๆˆท็ฎก็†๏ผŒๆˆ–ไปปไฝ• Django ้ข„ๆž„ๅปบๅŠŸ่ƒฝ็š„ๅบ”็”จ๏ผ›ๅฝ“็„ถ๏ผŒ่ฎธๅคš่ฟ™็ฑปๅŠŸ่ƒฝๅฏไปฅ้€š่ฟ‡ๆ’ไปถๆทปๅŠ ใ€‚ + +่ฟ™็ง็ป„ไปถ่งฃ่€ฆใ€ๅฏๆŒ‰้œ€ๆ‰ฉๅฑ•็š„โ€œๅพฎๆก†ๆžถโ€็‰นๆ€ง๏ผŒๆ˜ฏๆˆ‘ๆƒณไฟ็•™็š„ๅ…ณ้”ฎ็‚นใ€‚ + +้‰ดไบŽ Flask ็š„็ฎ€ๆด๏ผŒๅฎƒไผผไนŽ้žๅธธ้€‚ๅˆๆž„ๅปบ APIใ€‚ๆŽฅไธ‹ๆฅ่ฆๆ‰พ็š„๏ผŒๅฐฑๆ˜ฏ Flask ็‰ˆ็š„ โ€œDjango REST Frameworkโ€ใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +- ๆˆไธบๅพฎๆก†ๆžถ๏ผŒไพฟไบŽๆŒ‰้œ€็ป„ๅˆๆ‰€้œ€็š„ๅทฅๅ…ทไธŽ็ป„ไปถใ€‚ +- ๆไพ›็ฎ€ๅ•ๆ˜“็”จ็š„่ทฏ็”ฑ็ณป็ปŸใ€‚ + +/// + +### Requests { #requests } + +**FastAPI** ๅฎž้™…ไธŠไธๆ˜ฏ **Requests** ็š„ๆ›ฟไปฃๅ“ใ€‚ๅฎƒไปฌ็š„ไฝœ็”จ่Œƒๅ›ดๅฎŒๅ…จไธๅŒใ€‚ + +ๅœจ FastAPI ๅบ”็”จ็จ‹ๅบๅ†…้ƒจไฝฟ็”จ Requests ๅ…ถๅฎž้žๅธธๅธธ่งใ€‚ + +ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒFastAPI ไพ็„ถไปŽ Requests ไธญ่Žทๅพ—ไบ†ไธๅฐ‘็ตๆ„Ÿใ€‚ + +**Requests** ๆ˜ฏไธ€ไธช็”จไบŽไธŽ API ไบคไบ’๏ผˆไฝœไธบๅฎขๆˆท็ซฏ๏ผ‰็š„ๅบ“๏ผŒ่€Œ **FastAPI** ๆ˜ฏไธ€ไธช็”จไบŽๆž„ๅปบ API๏ผˆไฝœไธบๆœๅŠก็ซฏ๏ผ‰็š„ๅบ“ใ€‚ + +ๅฎƒไปฌๅค„ๅœจๆŸ็งๆ„ไน‰ไธŠ็š„โ€œๅฏน็ซ‹็ซฏโ€๏ผŒๅฝผๆญคไบ’่กฅใ€‚ + +Requests ่ฎพ่ฎก้žๅธธ็ฎ€ๅ•็›ด่ง‚๏ผŒๆ˜“ไบŽไฝฟ็”จ๏ผŒไธ”ๆœ‰ๅˆ็†็š„้ป˜่ฎคๅ€ผใ€‚ๅŒๆ—ถๅฎƒไนŸ้žๅธธๅผบๅคงใ€ๅฏๅฎšๅˆถใ€‚ + +่ฟ™ๅฐฑๆ˜ฏไธบไป€ไนˆ๏ผŒๆญฃๅฆ‚ๅ…ถๅฎ˜็ฝ‘ๆ‰€่ฏด๏ผš + +> Requests ๆ˜ฏๆœ‰ๅฒไปฅๆฅไธ‹่ฝฝ้‡ๆœ€้ซ˜็š„ Python ๅŒ…ไน‹ไธ€ + +ๅฎƒ็š„็”จๆณ•้žๅธธ็ฎ€ๅ•ใ€‚ไพ‹ๅฆ‚๏ผŒ่ฟ›่กŒไธ€ๆฌก `GET` ่ฏทๆฑ‚๏ผŒไฝ ไผš่ฟ™ๆ ทๅ†™๏ผš + +```Python +response = requests.get("http://example.com/some/url") +``` + +ๅฏนๅบ”ๅœฐ๏ผŒFastAPI ็š„ API ่ทฏๅพ„ๆ“ไฝœๅฏ่ƒฝ็œ‹่ตทๆฅๆ˜ฏ่ฟ™ๆ ท็š„๏ผš + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +ๅฏไปฅ็œ‹ๅˆฐ `requests.get(...)` ไธŽ `@app.get(...)` ็š„็›ธไผผไน‹ๅค„ใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +- ๆไพ›็ฎ€ๅ•็›ด่ง‚็š„ APIใ€‚ +- ็›ดๆŽฅใ€่‡ช็„ถๅœฐไฝฟ็”จ HTTP ๆ–นๆณ•ๅ๏ผˆๆ“ไฝœ๏ผ‰ใ€‚ +- ๅ…ทๅค‡ๅˆ็†้ป˜่ฎคๅ€ผ๏ผŒๅŒๆ—ถๆ”ฏๆŒๅผบๅคงๅฎšๅˆถ่ƒฝๅŠ›ใ€‚ + +/// + +### Swagger / OpenAPI { #swagger-openapi } + +ๆˆ‘ๆƒณไปŽ Django REST Framework ๅพ—ๅˆฐ็š„ไธป่ฆ็‰นๆ€งไน‹ไธ€ๆ˜ฏ่‡ชๅŠจ API ๆ–‡ๆกฃใ€‚ + +้šๅŽๆˆ‘ๅ‘็Žฐๆœ‰ไธ€ไธช็”จไบŽ็”จ JSON๏ผˆๆˆ– YAML๏ผŒJSON ็š„ๆ‰ฉๅฑ•๏ผ‰ๆฅๆ่ฟฐ API ็š„ๆ ‡ๅ‡†๏ผŒ็งฐไธบ Swaggerใ€‚ + +ๅนถไธ”ๅทฒ็ปๆœ‰ไบ†็”จไบŽ Swagger API ็š„ Web ็”จๆˆท็•Œ้ขใ€‚ๅ› ๆญค๏ผŒๅช่ฆ่ƒฝไธบ API ็”Ÿๆˆ Swagger ๆ–‡ๆกฃ๏ผŒๅฐฑ่ƒฝ่‡ชๅŠจไฝฟ็”จ่ฟ™ไธช Web ็•Œ้ขใ€‚ + +ๅŽๆฅ๏ผŒSwagger ไบค็”ฑ Linux ๅŸบ้‡‘ไผš็ฎก็†๏ผŒๅนถๆ›ดๅไธบ OpenAPIใ€‚ + +ๅ› ๆญค๏ผŒๅœจ่ฐˆๅˆฐ 2.0 ็‰ˆๆœฌๆ—ถไบบไปฌๅธธ่ฏด โ€œSwaggerโ€๏ผŒ่€Œ 3+ ็‰ˆๆœฌๅˆ™็งฐไธบ โ€œOpenAPIโ€ใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +้‡‡็”จๅนถไฝฟ็”จๅผ€ๆ”พ็š„ API ่ง„่Œƒๆ ‡ๅ‡†๏ผŒ่€Œ้ž่‡ชๅฎšไน‰ๆจกๅผใ€‚ + +ๅนถ้›†ๆˆๅŸบไบŽๆ ‡ๅ‡†็š„็”จๆˆท็•Œ้ขๅทฅๅ…ท๏ผš + +- Swagger UI +- ReDoc + +้€‰ๆ‹ฉ่ฟ™ไธค่€…ๆ˜ฏๅ› ไธบๅฎƒไปฌ็›ธๅฝ“ๆต่กŒไธ”็จณๅฎš๏ผ›ไฝ†็จไฝœๆœ็ดข๏ผŒไฝ ๅฐฑ่ƒฝๆ‰พๅˆฐๆ•ฐๅ็ง OpenAPI ็š„ๆ›ฟไปฃ็”จๆˆท็•Œ้ข๏ผˆ้ƒฝๅฏไปฅไธŽ **FastAPI** ๆญ้…ไฝฟ็”จ๏ผ‰ใ€‚ + +/// + +### Flask REST ๆก†ๆžถ { #flask-rest-frameworks } + +ๆœ‰่‹ฅๅนฒๅŸบไบŽ Flask ็š„ REST ๆก†ๆžถ๏ผŒไฝ†ๅœจๆŠ•ๅ…ฅๆ—ถ้—ด็ฒพๅŠ›ๆทฑๅ…ฅ่ฐƒ็ ”ๅŽ๏ผŒๆˆ‘ๅ‘็Žฐ่ฎธๅคšๅทฒๅœๆญข็ปดๆŠคๆˆ–่ขซๅผƒ็”จ๏ผŒๅนถๅญ˜ๅœจๅคšๅค„ๆœช่งฃๅ†ณ้—ฎ้ข˜๏ผŒไธๅคช้€‚ๅˆ้‡‡็”จใ€‚ + +### Marshmallow { #marshmallow } + +API ็ณป็ปŸๆ‰€้œ€็š„ไธป่ฆ็‰นๆ€งไน‹ไธ€ๆ˜ฏๆ•ฐๆฎโ€œๅบๅˆ—ๅŒ–โ€๏ผŒๅณๅฐ†ไปฃ็ ๏ผˆPython๏ผ‰ไธญ็š„ๆ•ฐๆฎ่ฝฌๆขไธบๅฏ้€š่ฟ‡็ฝ‘็ปœๅ‘้€็š„ๅฝขๅผใ€‚ไพ‹ๅฆ‚๏ผŒๅฐ†ๅŒ…ๅซๆ•ฐๆฎๅบ“ๆ•ฐๆฎ็š„ๅฏน่ฑก่ฝฌๆขไธบ JSON ๅฏน่ฑกใ€ๅฐ† `datetime` ๅฏน่ฑก่ฝฌๆขไธบๅญ—็ฌฆไธฒ็ญ‰ใ€‚ + +API ็š„ๅฆไธ€ไธช้‡่ฆ็‰นๆ€งๆ˜ฏๆ•ฐๆฎๆ ก้ชŒ๏ผŒ็กฎไฟๆ•ฐๆฎๅœจ็ป™ๅฎš็บฆๆŸไธ‹ๆ˜ฏๆœ‰ๆ•ˆ็š„ใ€‚ไพ‹ๅฆ‚๏ผŒๆŸไธชๅญ—ๆฎตๅฟ…้กปๆ˜ฏ `int` ่€Œไธๆ˜ฏไปปๆ„ๅญ—็ฌฆไธฒใ€‚่ฟ™ๅฏนไผ ๅ…ฅๆ•ฐๆฎๅฐคๅ…ถๆœ‰็”จใ€‚ + +ๆฒกๆœ‰ๆ•ฐๆฎๆ ก้ชŒ็ณป็ปŸ็š„่ฏ๏ผŒไฝ ๅฐฑๅพ—ๅœจไปฃ็ ้‡Œๆ‰‹ๅ†™ๆ‰€ๆœ‰ๆฃ€ๆŸฅใ€‚ + +่ฟ™ไบ›ๆญฃๆ˜ฏ Marshmallow ่ฆๆไพ›็š„ๅŠŸ่ƒฝใ€‚ๅฎƒๆ˜ฏไธชๅพˆๆฃ’็š„ๅบ“๏ผŒๆˆ‘ไน‹ๅ‰ๅคง้‡ไฝฟ็”จ่ฟ‡ใ€‚ + +ไฝ†ๅฎƒ่ฏž็”ŸไบŽ Python ็ฑปๅž‹ๆ็คบๅ‡บ็Žฐไน‹ๅ‰ใ€‚ๅ› ๆญค๏ผŒๅฎšไน‰ๆฏไธชๆจกๅผ้ƒฝ้œ€่ฆไฝฟ็”จ Marshmallow ๆไพ›็š„็‰นๅฎšๅทฅๅ…ทๅ’Œ็ฑปใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ไฝฟ็”จไปฃ็ ๅฎšไน‰โ€œๆจกๅผโ€๏ผŒ่‡ชๅŠจๆไพ›ๆ•ฐๆฎ็ฑปๅž‹ไธŽๆ ก้ชŒใ€‚ + +/// + +### Webargs { #webargs } + +API ็š„ๅฆไธ€ไธช้‡่ฆ้œ€ๆฑ‚ๆ˜ฏไปŽไผ ๅ…ฅ่ฏทๆฑ‚ไธญ่งฃๆžๆ•ฐๆฎใ€‚ + +Webargs ๆ˜ฏไธ€ไธชๅœจๅคšไธชๆก†ๆžถ๏ผˆๅŒ…ๆ‹ฌ Flask๏ผ‰ไน‹ไธŠๆไพ›่ฏฅๅŠŸ่ƒฝ็š„ๅทฅๅ…ทใ€‚ + +ๅฎƒๅœจๅบ•ๅฑ‚ไฝฟ็”จ Marshmallow ่ฟ›่กŒๆ•ฐๆฎๆ ก้ชŒ๏ผŒๅนถไธ”็”ฑ็›ธๅŒ็š„ๅผ€ๅ‘่€…ๅˆ›ๅปบใ€‚ + +ๅœจๆ‹ฅๆœ‰ **FastAPI** ไน‹ๅ‰๏ผŒๆˆ‘ไนŸๅคง้‡ไฝฟ็”จ่ฟ‡ๅฎƒ๏ผŒ่ฟ™ๆ˜ฏไธชๅพˆๆฃ’็š„ๅทฅๅ…ทใ€‚ + +/// info | ไฟกๆฏ + +Webargs ็”ฑไธŽ Marshmallow ็›ธๅŒ็š„ๅผ€ๅ‘่€…ๅˆ›ๅปบใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ๅฏนไผ ๅ…ฅ่ฏทๆฑ‚ๆ•ฐๆฎ่ฟ›่กŒ่‡ชๅŠจๆ ก้ชŒใ€‚ + +/// + +### APISpec { #apispec } + +Marshmallow ไธŽ Webargs ้€š่ฟ‡ๆ’ไปถๆไพ›ไบ†ๆ ก้ชŒใ€่งฃๆžไธŽๅบๅˆ—ๅŒ–ใ€‚ + +ไฝ†ๆ–‡ๆกฃไป็„ถ็ผบๅคฑ๏ผŒไบŽๆ˜ฏๅ‡บ็Žฐไบ† APISpecใ€‚ + +ๅฎƒไธบ่ฎธๅคšๆก†ๆžถๆไพ›ๆ’ไปถ๏ผˆStarlette ไนŸๆœ‰ๆ’ไปถ๏ผ‰ใ€‚ + +ๅฎƒ็š„ๅทฅไฝœๆ–นๅผๆ˜ฏ๏ผšไฝ ๅœจๅค„็†่ทฏ็”ฑ็š„ๆฏไธชๅ‡ฝๆ•ฐ็š„ๆ–‡ๆกฃๅญ—็ฌฆไธฒ้‡Œ๏ผŒ็”จ YAML ๆ ผๅผ็ผ–ๅ†™ๆจกๅผๅฎšไน‰ใ€‚ + +็„ถๅŽๅฎƒไผš็”Ÿๆˆ OpenAPI ๆจกๅผใ€‚ + +่ฟ™ๆญฃๆ˜ฏๅฎƒๅœจ Flaskใ€Starletteใ€Responder ็ญ‰ๆก†ๆžถ้‡Œ็š„ๅทฅไฝœๆ–นๅผใ€‚ + +ไฝ†่ฟ™ๆ ทๆˆ‘ไปฌๅˆๅ›žๅˆฐไบ†ๅœจ Python ๅญ—็ฌฆไธฒไธญ็ปดๆŠคไธ€ๅฅ—โ€œๅพฎ่ฏญๆณ•โ€๏ผˆไธ€ๅคงๆฎต YAML๏ผ‰็š„้—ฎ้ข˜ไธŠใ€‚ + +็ผ–่พ‘ๅ™จๅพˆ้šพไธบๆญคๆไพ›ๅธฎๅŠฉ๏ผ›่€Œไธ”ๅฆ‚ๆžœๆˆ‘ไปฌไฟฎๆ”นไบ†ๅ‚ๆ•ฐๆˆ– Marshmallow ๆจกๅผ๏ผŒๅดๅฟ˜ไบ†ๅŒๆญฅๆ›ดๆ–ฐ้‚ฃไธช YAML ๆ–‡ๆกฃๅญ—็ฌฆไธฒ๏ผŒ็”Ÿๆˆ็š„ๆจกๅผๅฐฑไผš่ฟ‡ๆ—ถใ€‚ + +/// info | ไฟกๆฏ + +APISpec ็”ฑไธŽ Marshmallow ็›ธๅŒ็š„ๅผ€ๅ‘่€…ๅˆ›ๅปบใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ๆ”ฏๆŒๅผ€ๆ”พ็š„ API ๆ ‡ๅ‡† OpenAPIใ€‚ + +/// + +### Flask-apispec { #flask-apispec } + +่ฟ™ๆ˜ฏไธ€ไธช Flask ๆ’ไปถ๏ผŒๅฐ† Webargsใ€Marshmallow ไธŽ APISpec ็ป“ๅˆๅœจไธ€่ตทใ€‚ + +ๅฎƒๅˆฉ็”จ Webargs ไธŽ Marshmallow ็š„ไฟกๆฏ๏ผŒ้€š่ฟ‡ APISpec ่‡ชๅŠจ็”Ÿๆˆ OpenAPI ๆจกๅผใ€‚ + +่ฟ™ๆ˜ฏไธชๅพˆๆฃ’ๅด่ขซไฝŽไผฐ็š„ๅทฅๅ…ท๏ผ›ๅฎƒ็†ๅบ”ๆฏ”่ฎธๅคš Flask ๆ’ไปถๆ›ดๆต่กŒใ€‚ๆˆ–่ฎธๆ˜ฏๅ› ไธบๅฎƒ็š„ๆ–‡ๆกฃ่ฟ‡ไบŽ็ฎ€ๆดไธŽๆŠฝ่ฑกใ€‚ + +่ฟ™่งฃๅ†ณไบ†ๅœจ Python ๆ–‡ๆกฃๅญ—็ฌฆไธฒ้‡Œไนฆๅ†™ YAML๏ผˆๅฆไธ€ๅฅ—่ฏญๆณ•๏ผ‰็š„้—ฎ้ข˜ใ€‚ + +ๅœจๆž„ๅปบ **FastAPI** ไน‹ๅ‰๏ผŒFlask + Flask-apispec + Marshmallow + Webargs ็š„็ป„ๅˆๆ˜ฏๆˆ‘ๆœ€ๅ–œๆฌข็š„ๅŽ็ซฏๆŠ€ๆœฏๆ ˆใ€‚ + +ไฝฟ็”จๅฎƒไฟƒๆˆไบ†่‹ฅๅนฒ Flask ๅ…จๆ ˆ่„šๆ‰‹ๆžถ็š„่ฏž็”Ÿใ€‚ไปฅไธ‹ๆ˜ฏๆˆ‘๏ผˆไปฅๅŠ่‹ฅๅนฒๅค–้ƒจๅ›ข้˜Ÿ๏ผ‰่‡ณไปŠไฝฟ็”จ็š„ไธป่ฆๆŠ€ๆœฏๆ ˆ๏ผš + +* https://github.com/tiangolo/full-stack +* https://github.com/tiangolo/full-stack-flask-couchbase +* https://github.com/tiangolo/full-stack-flask-couchdb + +่ฟ™ไบ›ๅ…จๆ ˆ่„šๆ‰‹ๆžถไนŸๆˆไธบไบ†[**FastAPI** ้กน็›ฎ่„šๆ‰‹ๆžถ](project-generation.md){.internal-link target=_blank}็š„ๅŸบ็ก€ใ€‚ + +/// info | ไฟกๆฏ + +Flask-apispec ็”ฑไธŽ Marshmallow ็›ธๅŒ็š„ๅผ€ๅ‘่€…ๅˆ›ๅปบใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ไปŽๅฎšไน‰ๅบๅˆ—ๅŒ–ไธŽๆ ก้ชŒ็š„ๅŒไธ€ไปฝไปฃ็ ่‡ชๅŠจ็”Ÿๆˆ OpenAPI ๆจกๅผใ€‚ + +/// + +### NestJS๏ผˆไปฅๅŠ Angular๏ผ‰ { #nestjs-and-angular } + +่ฟ™็”š่‡ณไธๆ˜ฏ Pythonใ€‚NestJS ๆ˜ฏไธ€ไธช JavaScript๏ผˆTypeScript๏ผ‰็š„ NodeJS ๆก†ๆžถ๏ผŒๅ— Angular ๅฏๅ‘ใ€‚ + +ๅฎƒๅฎž็Žฐไบ†ไธŽ Flask-apispec ๆœ‰ไบ›็ฑปไผผ็š„ๆ•ˆๆžœใ€‚ + +ๅฎƒ้›†ๆˆไบ†ๅ— Angular 2 ๅฏๅ‘็š„ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ไธŽๆˆ‘ๆ‰€็Ÿฅ็š„ๅ…ถไป–ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸไธ€ๆ ท๏ผŒ้œ€่ฆ้ข„ๅ…ˆๆณจๅ†Œโ€œๅฏๆณจๅ…ฅ้กนโ€๏ผŒๅ› ๆญคไผšๅขžๅŠ ๅ†—้•ฟไธŽ้‡ๅคใ€‚ + +็”ฑไบŽๅ‚ๆ•ฐ็”จ TypeScript ็ฑปๅž‹ๆ่ฟฐ๏ผˆ็ฑปไผผ Python ็ฑปๅž‹ๆ็คบ๏ผ‰๏ผŒ็ผ–่พ‘ๅ™จๆ”ฏๆŒ็›ธๅฝ“ๅฅฝใ€‚ + +ไฝ†็”ฑไบŽ TypeScript ็š„็ฑปๅž‹ๅœจ็ผ–่ฏ‘ไธบ JavaScript ๅŽไธไผšไฟ็•™๏ผŒๆ— ๆณ•ๅชไพ่ต–่ฟ™ไบ›็ฑปๅž‹ๅŒๆ—ถๅฎšไน‰ๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽๆ–‡ๆกฃใ€‚ๅ—ๆญคไปฅๅŠไธ€ไบ›่ฎพ่ฎกๅ†ณ็ญ–ๅฝฑๅ“๏ผŒไธบไบ†่Žทๅพ—ๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽ่‡ชๅŠจ schema ็”Ÿๆˆ๏ผŒ้œ€่ฆๅœจ่ฎธๅคšไฝ็ฝฎๆทปๅŠ ่ฃ…้ฅฐๅ™จ๏ผŒๅ› ๆญคไปฃ็ ไผš็›ธๅฝ“ๅ†—้•ฟใ€‚ + +ๅฎƒๅฏนๅตŒๅฅ—ๆจกๅž‹็š„ๆ”ฏๆŒๅนถไธๅฅฝใ€‚ๅฆ‚ๆžœ่ฏทๆฑ‚็š„ JSON ไฝ“ๆ˜ฏๅŒ…ๅซๅตŒๅฅ— JSON ๅฏน่ฑก็š„ JSON ๅฏน่ฑก๏ผŒๅˆ™ๆ— ๆณ•่ขซๆญฃ็กฎๆ–‡ๆกฃๅŒ–ๅ’Œๆ ก้ชŒใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ไฝฟ็”จ Python ็ฑปๅž‹ไปฅ่Žทๅพ—ๅ‡บ่‰ฒ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ + +ๆ‹ฅๆœ‰ๅผบๅคง็š„ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ๏ผŒๅนถ่ฎพๆณ•ๅฐฝ้‡ๅ‡ๅฐ‘ไปฃ็ ้‡ๅคใ€‚ + +/// + +### Sanic { #sanic } + +ๅฎƒๆ˜ฏๆœ€ๆ—ฉ็š„ไธ€ๆ‰นๅŸบไบŽ `asyncio` ็š„ๆž้€Ÿ Python ๆก†ๆžถไน‹ไธ€๏ผŒไธ”ๅšๅพ—ไธŽ Flask ๅพˆ็›ธไผผใ€‚ + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +ๅฎƒไฝฟ็”จไบ† `uvloop` ๆฅๆ›ฟไปฃ Python ้ป˜่ฎค็š„ `asyncio` ๅพช็Žฏใ€‚่ฟ™ๆญฃๆ˜ฏๅฎƒๅฆ‚ๆญคไน‹ๅฟซ็š„ๅŽŸๅ› ใ€‚ + +ๅฎƒๆ˜พ็„ถๅฏๅ‘ไบ† Uvicorn ๅ’Œ Starlette๏ผ›ๅœจๅ…ฌๅผ€็š„ๅŸบๅ‡†ๆต‹่ฏ•ไธญ๏ผŒๅฎƒไปฌ็›ฎๅ‰ๆฏ” Sanic ๆ›ดๅฟซใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ๆ‰พๅˆฐๅฎž็Žฐ็–ฏ็‹‚ๆ€ง่ƒฝ็š„่ทฏๅพ„ใ€‚ + +่ฟ™ๅฐฑๆ˜ฏ **FastAPI** ๅŸบไบŽ Starlette ็š„ๅŽŸๅ› ๏ผŒๅ› ไธบๅฎƒๆ˜ฏ็›ฎๅ‰ๅฏ็”จ็š„ๆœ€ๅฟซๆก†ๆžถ๏ผˆ็”ฑ็ฌฌไธ‰ๆ–นๅŸบๅ‡†ๆต‹่ฏ•้ชŒ่ฏ๏ผ‰ใ€‚ + +/// + +### Falcon { #falcon } + +Falcon ๆ˜ฏๅฆไธ€ไธช้ซ˜ๆ€ง่ƒฝ Python ๆก†ๆžถ๏ผŒๅฎƒ่ขซ่ฎพ่ฎกไธบ็ฒพ็ฎ€ไธ”ๅฏไฝœไธบ Hug ็ญ‰ๅ…ถไป–ๆก†ๆžถ็š„ๅŸบ็ก€ใ€‚ + +ๅฎƒ่ฎพ่ฎกไธบๆŽฅๆ”ถไธคไธชๅ‚ๆ•ฐ็š„ๅ‡ฝๆ•ฐ๏ผšไธ€ไธชโ€œrequestโ€ๅ’Œไธ€ไธชโ€œresponseโ€ใ€‚็„ถๅŽไปŽ request ไธญโ€œ่ฏปๅ–โ€๏ผŒๅ‘ response ไธญโ€œๅ†™ๅ…ฅโ€ใ€‚็”ฑไบŽ่ฟ™็ง่ฎพ่ฎก๏ผŒๆ— ๆณ•็”จๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹ๆ็คบๅฐ†่ฏทๆฑ‚ๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚ไฝ“ๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐๅฝขๅ‚ใ€‚ + +ๅ› ๆญค๏ผŒๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽๆ–‡ๆกฃ่ฆไนˆ้œ€่ฆๆ‰‹ๅ†™ๅฎŒๆˆ๏ผŒๆ— ๆณ•่‡ชๅŠจๅŒ–๏ผ›่ฆไนˆ้œ€่ฆๅœจ Falcon ไน‹ไธŠๅฎž็Žฐไธ€ไธชๆก†ๆžถ๏ผŒไพ‹ๅฆ‚ Hugใ€‚ๅ…ถไป–ๅ— Falcon ่ฎพ่ฎกๅฏๅ‘ใ€้‡‡็”จโ€œไธ€ไธช request ๅฏน่ฑก + ไธ€ไธช response ๅฏน่ฑกไฝœไธบๅ‚ๆ•ฐโ€็š„ๆก†ๆžถไนŸๆœ‰ๅŒๆ ท็š„ๅŒบๅˆซใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +ๅฏปๆ‰พ่Žทๅพ—ๅ“่ถŠๆ€ง่ƒฝ็š„ๆ–นๆณ•ใ€‚ + +ไธŽ Hug๏ผˆHug ๅŸบไบŽ Falcon๏ผ‰ไธ€่ตท๏ผŒๅฏๅ‘ **FastAPI** ๅœจๅ‡ฝๆ•ฐไธญๅฃฐๆ˜Žไธ€ไธช `response` ๅ‚ๆ•ฐใ€‚ๅฐฝ็ฎกๅœจ FastAPI ไธญๅฎƒๆ˜ฏๅฏ้€‰็š„๏ผŒไธป่ฆ็”จไบŽ่ฎพ็ฝฎ headersใ€cookies ๅ’Œๅฏ้€‰็š„็Šถๆ€็ ใ€‚ + +/// + +### Molten { #molten } + +ๆˆ‘ๅœจๆž„ๅปบ **FastAPI** ็š„ๆ—ฉๆœŸ้˜ถๆฎตๅ‘็Žฐไบ† Moltenใ€‚ๅฎƒๆœ‰ไธๅฐ‘็›ธไผผ็š„ๆƒณๆณ•๏ผš + +* ๅŸบไบŽ Python ็ฑปๅž‹ๆ็คบใ€‚ +* ไปŽ่ฟ™ไบ›็ฑปๅž‹่Žทๅพ—ๆ ก้ชŒไธŽๆ–‡ๆกฃใ€‚ +* ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ + +ๅฎƒๆฒกๆœ‰ไฝฟ็”จๅƒ Pydantic ่ฟ™ๆ ท็š„็ฌฌไธ‰ๆ–นๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽๆ–‡ๆกฃๅบ“๏ผŒ่€Œๆ˜ฏๆœ‰่‡ชๅทฑ็š„ๅฎž็Žฐใ€‚ๅ› ๆญค่ฟ™ไบ›ๆ•ฐๆฎ็ฑปๅž‹ๅฎšไน‰ไธๅคชๅฎนๆ˜“ๅœจๅ…ถไป–ๅœฐๆ–นๅค็”จใ€‚ + +ๅฎƒ้œ€่ฆ็จๅพฎๅ†—้•ฟไธ€ไบ›็š„้…็ฝฎใ€‚ๅนถไธ”็”ฑไบŽๅŸบไบŽ WSGI๏ผˆ่€Œ้ž ASGI๏ผ‰๏ผŒๅฎƒๅนถๆœช่ฎพ่ฎกไธบๅ……ๅˆ†ๅˆฉ็”จ Uvicornใ€Starletteใ€Sanic ็ญ‰ๅทฅๅ…ทๆ‰€ๆไพ›็š„้ซ˜ๆ€ง่ƒฝใ€‚ + +ๅ…ถไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ้œ€่ฆ้ข„ๅ…ˆๆณจๅ†Œไพ่ต–๏ผŒไธ”ไพ่ต–ๆ นๆฎๅฃฐๆ˜Ž็š„็ฑปๅž‹ๆฅ่งฃๆžใ€‚ๅ› ๆญคๆ— ๆณ•ไธบๅŒไธ€็ฑปๅž‹ๅฃฐๆ˜ŽๅคšไบŽไธ€ไธชโ€œ็ป„ไปถโ€ใ€‚ + +่ทฏ็”ฑๅœจไธ€ไธชๅœฐๆ–น้›†ไธญๅฃฐๆ˜Ž๏ผŒไฝฟ็”จๅœจๅ…ถไป–ๅœฐๆ–นๅฃฐๆ˜Ž็š„ๅ‡ฝๆ•ฐ๏ผˆ่€Œไธๆ˜ฏไฝฟ็”จๅฏไปฅ็›ดๆŽฅๆ”พๅœจๅค„็†็ซฏ็‚นๅ‡ฝๆ•ฐไน‹ไธŠ็š„่ฃ…้ฅฐๅ™จ๏ผ‰ใ€‚่ฟ™ๆ›ดๆŽฅ่ฟ‘ Django ็š„ๅšๆณ•๏ผŒ่€Œไธๆ˜ฏ Flask๏ผˆๅ’Œ Starlette๏ผ‰ใ€‚ๅฎƒๅœจไปฃ็ ไธญๅ‰ฒ่ฃ‚ไบ†็›ธๅฏน็ดง่€ฆๅˆ็š„ๅ†…ๅฎนใ€‚ + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +้€š่ฟ‡ๆจกๅž‹ๅฑžๆ€ง็š„โ€œ้ป˜่ฎคๅ€ผโ€ไธบๆ•ฐๆฎ็ฑปๅž‹ๅฎšไน‰้ขๅค–ๆ ก้ชŒใ€‚่ฟ™ๆๅ‡ไบ†็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผŒ่€Œ่ฟ™ๅœจๅฝ“ๆ—ถ็š„ Pydantic ไธญๅฐšไธๅฏ็”จใ€‚ + +่ฟ™ๅฎž้™…ไธŠไฟƒๆˆไบ†ๅฏน Pydantic ็š„้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒไปฅๆ”ฏๆŒ่ฟ™็งๆ ก้ชŒๅฃฐๆ˜Ž้ฃŽๆ ผ๏ผˆ่ฟ™ไบ›ๅŠŸ่ƒฝ็Žฐๅทฒๅœจ Pydantic ไธญๅฏ็”จ๏ผ‰ใ€‚ + +/// + +### Hug { #hug } + +Hug ๆ˜ฏๆœ€ๆ—ฉไฝฟ็”จ Python ็ฑปๅž‹ๆ็คบๆฅๅฃฐๆ˜Ž API ๅ‚ๆ•ฐ็ฑปๅž‹็š„ๆก†ๆžถไน‹ไธ€ใ€‚่ฟ™ไธ€็ปๅฆ™ๆƒณๆณ•ไนŸๅฏๅ‘ไบ†ๅ…ถไป–ๅทฅๅ…ทใ€‚ + +ๅฎƒๅœจๅฃฐๆ˜Žไธญไฝฟ็”จ่‡ชๅฎšไน‰็ฑปๅž‹่€Œไธๆ˜ฏๆ ‡ๅ‡†็š„ Python ็ฑปๅž‹๏ผŒไฝ†่ฟ™ไพ็„ถๆ˜ฏๅทจๅคง็š„่ฟ›ๆญฅใ€‚ + +ๅฎƒไนŸๆ˜ฏๆœ€ๆ—ฉ็”Ÿๆˆไธ€ไธช่‡ชๅฎšไน‰ JSON ๆจกๅผๆฅๅฃฐๆ˜Žๆ•ดไธช API ็š„ๆก†ๆžถไน‹ไธ€ใ€‚ + +ๅฎƒๅนถไธๅŸบไบŽ OpenAPI ไธŽ JSON Schema ่ฟ™็ฑปๆ ‡ๅ‡†ใ€‚ๅ› ๆญคไธŽๅ…ถไป–ๅทฅๅ…ท๏ผˆๅฆ‚ Swagger UI๏ผ‰็š„้›†ๆˆๅนถ้žไธ€ๅธ†้ฃŽ้กบใ€‚ไฝ†ๅฎƒไปๆ˜ฏ้žๅธธๆœ‰ๅˆ›ๆ–ฐๆ€ง็š„ๆƒณๆณ•ใ€‚ + +ๅฎƒๆœ‰ไธ€ไธชๆœ‰่ถฃไธ”ๅฐ‘่ง็š„็‰นๆ€ง๏ผšไฝฟ็”จๅŒไธ€ๆก†ๆžถ๏ผŒๅฏไปฅๅŒๆ—ถๅˆ›ๅปบ API ไธŽ CLIใ€‚ + +็”ฑไบŽๅŸบไบŽๅŒๆญฅ Python Web ๆก†ๆžถ็š„ไธŠไธ€ไปฃๆ ‡ๅ‡†๏ผˆWSGI๏ผ‰๏ผŒๅฎƒๆ— ๆณ•ๅค„็† WebSocket ็ญ‰๏ผŒๅฐฝ็ฎกๅฎƒ็š„ๆ€ง่ƒฝไป็„ถๅพˆ้ซ˜ใ€‚ + +/// info | ไฟกๆฏ + +Hug ็”ฑ Timothy Crosley ๅˆ›ๅปบ๏ผŒไป–ไนŸๆ˜ฏ `isort` ็š„ไฝœ่€…๏ผŒ่ฟ™ๆ˜ฏไธ€ไธช่ƒฝ่‡ชๅŠจๆŽ’ๅบ Python ๆ–‡ไปถไธญๅฏผๅ…ฅ็š„ไผ˜็ง€ๅทฅๅ…ทใ€‚ + +/// + +/// check | ๅฏๅ‘ **FastAPI** ็š„ๆƒณๆณ•๏ผš + +Hug ๅฏๅ‘ไบ† APIStar ็š„้ƒจๅˆ†่ฎพ่ฎก๏ผŒไนŸๆ˜ฏๆˆ‘ๅฝ“ๆ—ถๆœ€็œ‹ๅฅฝ็š„ๅทฅๅ…ทไน‹ไธ€๏ผŒไธŽ APIStar ๅนถๅˆ—ใ€‚ + +Hug ไฟƒไฝฟ **FastAPI** ไฝฟ็”จ Python ็ฑปๅž‹ๆ็คบๆฅๅฃฐๆ˜Žๅ‚ๆ•ฐ๏ผŒๅนถ่‡ชๅŠจ็”Ÿๆˆๅฎšไน‰ๆ•ดไธช API ็š„ๆจกๅผใ€‚ + +Hug ๅฏๅ‘ **FastAPI** ๅœจๅ‡ฝๆ•ฐไธญๅฃฐๆ˜Ž `response` ๅ‚ๆ•ฐ๏ผŒ็”จไบŽ่ฎพ็ฝฎ headers ไธŽ cookiesใ€‚ + +/// + +### APIStar (<= 0.5) { #apistar-0-5 } + +ๅฐฑๅœจๅ†ณๅฎšๅŠจๆ‰‹ๆž„ๅปบ **FastAPI** ไน‹ๅ‰๏ผŒๆˆ‘ๆ‰พๅˆฐไบ† **APIStar** ๆœๅŠกๅ™จใ€‚ๅฎƒๅ‡ ไนŽๅ…ทๅค‡ๆˆ‘ๆƒณ่ฆ็š„ไธ€ๅˆ‡๏ผŒ่ฎพ่ฎกไนŸๅพˆๅ‡บ่‰ฒใ€‚ + +ๅœจๆˆ‘่ง่ฟ‡็š„ๆก†ๆžถไธญ๏ผŒๅฎƒๆ˜ฏๆœ€ๆ—ฉไฝฟ็”จ Python ็ฑปๅž‹ๆ็คบๆฅๅฃฐๆ˜Žๅ‚ๆ•ฐๅ’Œ่ฏทๆฑ‚็š„ๅฎž็Žฐไน‹ไธ€๏ผˆๆ—ฉไบŽ NestJS ไธŽ Molten๏ผ‰ใ€‚ๆˆ‘ไธŽ Hug ๅ‡ ไนŽๅŒๆ—ถๅ‘็Žฐไบ†ๅฎƒใ€‚ไฝ† APIStar ไฝฟ็”จไบ† OpenAPI ๆ ‡ๅ‡†ใ€‚ + +ๅฎƒๅŸบไบŽ็›ธๅŒ็š„็ฑปๅž‹ๆ็คบ๏ผŒๅœจๅคšๅค„่‡ชๅŠจ่ฟ›่กŒๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ๅนถ็”Ÿๆˆ OpenAPI ๆจกๅผใ€‚ + +่ฏทๆฑ‚ไฝ“ๆจกๅผๅฎšไน‰ๅนถๆœชไฝฟ็”จไธŽ Pydantic ็›ธๅŒ็š„ Python ็ฑปๅž‹ๆ็คบ๏ผŒๅฎƒๆ›ดๆŽฅ่ฟ‘ Marshmallow๏ผŒๅ› ๆญค็ผ–่พ‘ๅ™จๆ”ฏๆŒไธๅฆ‚ Pydantic ๅฅฝ๏ผŒไฝ†ๅณไพฟๅฆ‚ๆญค๏ผŒAPIStar ไปๆ˜ฏๅฝ“ๆ—ถๅฏ็”จ็š„ๆœ€ไฝณ้€‰ๆ‹ฉใ€‚ + +ๅฎƒๅœจๅฝ“ๆ—ถๆ‹ฅๆœ‰ๆœ€ๅฅฝ็š„ๆ€ง่ƒฝๅŸบๅ‡†๏ผˆไป…่ขซ Starlette ่ถ…่ถŠ๏ผ‰ใ€‚ + +่ตทๅˆๅฎƒๆฒกๆœ‰่‡ชๅŠจ API ๆ–‡ๆกฃ Web ็•Œ้ข๏ผŒไฝ†ๆˆ‘็Ÿฅ้“ๆˆ‘ๅฏไปฅๆŠŠ Swagger UI ๅŠ ่ฟ›ๅŽปใ€‚ + +ๅฎƒๆœ‰ไธ€ไธชไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ไธŽไธŠๆ–‡ๆๅˆฐ็š„ๅ…ถไป–ๅทฅๅ…ทไธ€ๆ ท๏ผŒ้œ€่ฆ้ข„ๅ…ˆๆณจๅ†Œ็ป„ไปถใ€‚ไฝ†่ฟ™ไพ็„ถๆ˜ฏๅพˆๆฃ’็š„็‰นๆ€งใ€‚ + +ๆˆ‘ไปŽๆœชๅœจๅฎŒๆ•ด้กน็›ฎไธญไฝฟ็”จ่ฟ‡ๅฎƒ๏ผŒๅ› ไธบๅฎƒๆฒกๆœ‰ๅฎ‰ๅ…จ้›†ๆˆ๏ผŒๅ› ๆญคๆˆ‘ๆ— ๆณ•็”จๅฎƒๆ›ฟไปฃๅŸบไบŽ Flask-apispec ็š„ๅ…จๆ ˆ่„šๆ‰‹ๆžถๆ‰€ๅ…ทๅค‡็š„ๅ…จ้ƒจๅŠŸ่ƒฝใ€‚ๆˆ‘ๆ›พๆŠŠโ€œๆไบคไธ€ไธชๅขžๅŠ ่ฏฅๅŠŸ่ƒฝ็š„ PRโ€ๆ”พๅœจไบ†ๅพ…ๅŠž้‡Œใ€‚ + +ไฝ†้šๅŽ๏ผŒ้กน็›ฎ็š„้‡ๅฟƒๅ‘็”Ÿไบ†ๅ˜ๅŒ–ใ€‚ + +ๅฎƒไธๅ†ๆ˜ฏไธ€ไธช API Web ๆก†ๆžถ๏ผŒๅ› ไธบไฝœ่€…้œ€่ฆไธ“ๆณจไบŽ Starletteใ€‚ + +็Žฐๅœจ APIStar ๆ˜ฏไธ€็ป„็”จไบŽๆ ก้ชŒ OpenAPI ่ง„่Œƒ็š„ๅทฅๅ…ท๏ผŒ่€Œไธๆ˜ฏ Web ๆก†ๆžถใ€‚ + +/// info | ไฟกๆฏ + +APIStar ็”ฑ Tom Christie ๅˆ›ๅปบใ€‚ไป–่ฟ˜ๅˆ›ๅปบไบ†๏ผš + +* Django REST Framework +* Starlette๏ผˆ**FastAPI** ๅŸบไบŽๅ…ถไน‹ไธŠ๏ผ‰ +* Uvicorn๏ผˆ่ขซ Starlette ไธŽ **FastAPI** ไฝฟ็”จ๏ผ‰ + +/// + +/// check | ๅฏๅ‘ **FastAPI**๏ผš + +่ฏž็”Ÿใ€‚ + +็”จๅŒไธ€ๅฅ— Python ็ฑปๅž‹ๅŒๆ—ถๅฃฐๆ˜Žๅคšไปถไบ‹๏ผˆๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽๆ–‡ๆกฃ๏ผ‰๏ผŒๅนถไธ”่ฟ˜่ƒฝๆไพ›ๅ‡บ่‰ฒ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒโ€”โ€”ๆˆ‘่ฎคไธบ่ฟ™ๆ˜ฏไธชๆžๅ…ถๅทงๅฆ™็š„ๆƒณๆณ•ใ€‚ + +ๅœจ้•ฟๆ—ถ้—ดๅฏปๆ‰พไธŽๆต‹่ฏ•ๅคš็งๆ›ฟไปฃไน‹ๅŽ๏ผŒAPIStar ๆ˜ฏๅฝ“ๆ—ถๆœ€ๅฅฝ็š„้€‰ๆ‹ฉใ€‚ + +้šๅŽ APIStar ไธๅ†ไฝœไธบๆœๅŠกๅ™จๅญ˜ๅœจ๏ผŒ่€Œ Starlette ๅ‡บ็Žฐ๏ผŒๆˆไธบๅฎž็Žฐ่ฏฅไฝ“็ณป็š„ๆ›ดไฝณๅŸบ็ก€ใ€‚่ฟ™ๆˆไธบๆž„ๅปบ **FastAPI** ็š„ๆœ€็ปˆ็ตๆ„Ÿๆฅๆบใ€‚ + +ๆˆ‘ๆŠŠ **FastAPI** ่ง†ไธบ APIStar ็š„โ€œ็ฒพ็ฅž็ปญไฝœโ€๏ผŒๅนถๅœจๆญคๅŸบ็ก€ไธŠ๏ผŒ็ป“ๅˆๅ‰่ฟฐๅทฅๅ…ท็š„็ป้ชŒ๏ผŒๆ”น่ฟ›ๅนถๅขžๅผบไบ†ๅŠŸ่ƒฝใ€็ฑปๅž‹็ณป็ปŸๅŠๅ…ถไป–ๅ„ๆ–น้ขใ€‚ + +/// + +## **FastAPI** ๆ‰€ไฝฟ็”จ็š„็ป„ไปถ { #used-by-fastapi } + +### Pydantic { #pydantic } + +Pydantic ๆ˜ฏไธ€ไธชๅŸบไบŽ Python ็ฑปๅž‹ๆ็คบๆฅๅฎšไน‰ๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ไธŽๆ–‡ๆกฃ๏ผˆไฝฟ็”จ JSON Schema๏ผ‰็š„ๅบ“ใ€‚ + +่ฟ™ไฝฟๅพ—ๅฎƒๆžๅ…ถ็›ด่ง‚ใ€‚ + +ๅฎƒๅฏไธŽ Marshmallow ็ฑปๆฏ”ใ€‚ๅฐฝ็ฎกๅœจๅŸบๅ‡†ๆต‹่ฏ•ไธญๅฎƒๆฏ” Marshmallow ๆ›ดๅฟซใ€‚ๅนถไธ”็”ฑไบŽๅŒๆ ทๅŸบไบŽ Python ็ฑปๅž‹ๆ็คบ๏ผŒ็ผ–่พ‘ๅ™จๆ”ฏๆŒไผ˜็ง€ใ€‚ + +/// check | **FastAPI** ็”จๅฎƒๆฅ๏ผš + +ๅค„็†ๆ‰€ๆœ‰ๆ•ฐๆฎๆ ก้ชŒใ€ๆ•ฐๆฎๅบๅˆ—ๅŒ–ไธŽ่‡ชๅŠจๆจกๅž‹ๆ–‡ๆกฃ๏ผˆๅŸบไบŽ JSON Schema๏ผ‰ใ€‚ + +้šๅŽ **FastAPI** ไผšๆŠŠ่ฟ™ไบ› JSON Schema ๆ•ฐๆฎ็บณๅ…ฅ OpenAPI๏ผˆไปฅๅŠๅฎŒๆˆๅ…ถไป–ๆ‰€ๆœ‰ๅทฅไฝœ๏ผ‰ใ€‚ + +/// + +### Starlette { #starlette } + +Starlette ๆ˜ฏไธ€ไธช่ฝป้‡็บง็š„ ASGI ๆก†ๆžถ/ๅทฅๅ…ท้›†๏ผŒ้žๅธธ้€‚ๅˆๆž„ๅปบ้ซ˜ๆ€ง่ƒฝ็š„ asyncio ๆœๅŠกใ€‚ + +ๅฎƒ้žๅธธ็ฎ€ๅ•็›ด่ง‚ใ€‚่ขซ่ฎพ่ฎกไธบๆ˜“ไบŽๆ‰ฉๅฑ•๏ผŒไธ”ๅ…ทๆœ‰ๆจกๅ—ๅŒ–็ป„ไปถใ€‚ + +ๅฎƒๅ…ทๅค‡๏ผš + +* ๆ€ง่ƒฝๆžๅ…ถๅ‡บ่‰ฒใ€‚ +* ๆ”ฏๆŒ WebSocketใ€‚ +* ่ฟ›็จ‹ๅ†…ๅŽๅฐไปปๅŠกใ€‚ +* ๅฏๅŠจไธŽๅœๆญขไบ‹ไปถใ€‚ +* ๅŸบไบŽ HTTPX ็š„ๆต‹่ฏ•ๅฎขๆˆท็ซฏใ€‚ +* CORSใ€GZipใ€้™ๆ€ๆ–‡ไปถใ€ๆตๅผๅ“ๅบ”ใ€‚ +* ไผš่ฏไธŽ Cookie ๆ”ฏๆŒใ€‚ +* 100% ๆต‹่ฏ•่ฆ†็›–็އใ€‚ +* 100% ็ฑปๅž‹ๆณจ่งฃ็š„ไปฃ็ ๅบ“ใ€‚ +* ๆžๅฐ‘็š„ๅผบไพ่ต–ใ€‚ + +Starlette ็›ฎๅ‰ๆ˜ฏๆต‹่ฏ•ไธญๆœ€ๅฟซ็š„ Python ๆก†ๆžถใ€‚ไป…ๆฌกไบŽ Uvicorn๏ผŒๅฎƒไธๆ˜ฏๆก†ๆžถ๏ผŒ่€Œๆ˜ฏๆœๅŠกๅ™จใ€‚ + +Starlette ๆไพ›ไบ† Web ๅพฎๆก†ๆžถ็š„ๅ…จ้ƒจๅŸบ็ก€่ƒฝๅŠ›ใ€‚ + +ไฝ†ๅฎƒไธๆไพ›่‡ชๅŠจ็š„ๆ•ฐๆฎๆ ก้ชŒใ€ๅบๅˆ—ๅŒ–ๆˆ–ๆ–‡ๆกฃใ€‚ + +่ฟ™ๆญฃๆ˜ฏ **FastAPI** ๅœจๅ…ถไน‹ไธŠๅขžๅŠ ็š„ไธป่ฆๅ†…ๅฎนไน‹ไธ€๏ผŒๅ…จ้ƒจๅŸบไบŽ Python ็ฑปๅž‹ๆ็คบ๏ผˆ้€š่ฟ‡ Pydantic๏ผ‰ใ€‚ๆญคๅค–่ฟ˜ๆœ‰ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€ๅฎ‰ๅ…จๅทฅๅ…ทใ€OpenAPI ๆจกๅผ็”Ÿๆˆ็ญ‰ใ€‚ + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +ASGI ๆ˜ฏ็”ฑ Django ๆ ธๅฟƒๅ›ข้˜Ÿๆˆๅ‘˜ๆŽจๅŠจ็š„ๆ–ฐโ€œๆ ‡ๅ‡†โ€ใ€‚ๅฎƒๅฐšไธๆ˜ฏๆญฃๅผ็š„โ€œPython ๆ ‡ๅ‡†โ€๏ผˆPEP๏ผ‰๏ผŒๅฐฝ็ฎกๆญฃๆœๆญคๆ–นๅ‘ๆŽจ่ฟ›ใ€‚ + +ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒๅทฒๆœ‰ๅคš็งๅทฅๅ…ทๅฐ†ๅ…ถไฝœไธบโ€œๆ ‡ๅ‡†โ€ไฝฟ็”จใ€‚่ฟ™ๆžๅคงๆๅ‡ไบ†ไบ’ๆ“ไฝœๆ€ง๏ผšไฝ ๅฏไปฅๆŠŠ Uvicorn ๆขๆˆๅ…ถไป– ASGI ๆœๅŠกๅ™จ๏ผˆๅฆ‚ Daphne ๆˆ– Hypercorn๏ผ‰๏ผŒๆˆ–ๆทปๅŠ  ASGI ๅ…ผๅฎน็š„ๅทฅๅ…ท๏ผŒๅฆ‚ `python-socketio`ใ€‚ + +/// + +/// check | **FastAPI** ็”จๅฎƒๆฅ๏ผš + +ๅค„็†ๆ‰€ๆœ‰ๆ ธๅฟƒ Web ้ƒจๅˆ†๏ผŒๅนถๅœจๅ…ถไน‹ไธŠๆ‰ฉๅฑ•ๅŠŸ่ƒฝใ€‚ + +`FastAPI` ็ฑปๆœฌ่บซ็›ดๆŽฅ็ปงๆ‰ฟ่‡ช `Starlette`ใ€‚ + +ๅ› ๆญค๏ผŒๅ‡กๆ˜ฏไฝ ่ƒฝ็”จ Starlette ๅฎŒๆˆ็š„ไบ‹๏ผŒไนŸ่ƒฝ็›ดๆŽฅ็”จ **FastAPI** ๅฎŒๆˆ๏ผ›ๅฏไปฅๆŠŠๅฎƒ็œ‹ไฝœโ€œๅŠ ้€Ÿ็‰ˆโ€็š„ Starletteใ€‚ + +/// + +### Uvicorn { #uvicorn } + +Uvicorn ๆ˜ฏไธ€ไธชๅŸบไบŽ uvloop ไธŽ httptools ๆž„ๅปบ็š„ๆž้€Ÿ ASGI ๆœๅŠกๅ™จใ€‚ + +ๅฎƒไธๆ˜ฏ Web ๆก†ๆžถ๏ผŒ่€Œๆ˜ฏๆœๅŠกๅ™จใ€‚ไพ‹ๅฆ‚ๅฎƒไธๆไพ›ๆŒ‰่ทฏๅพ„่ทฏ็”ฑ็š„ๅทฅๅ…ทโ€”โ€”่ฟ™ๆ˜ฏ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰่ฟ™็ฑปๆก†ๆžถๅœจๅ…ถไน‹ไธŠๆไพ›็š„ๅŠŸ่ƒฝใ€‚ + +ๅฎƒๆ˜ฏ Starlette ไธŽ **FastAPI** ๆŽจ่็š„ๆœๅŠกๅ™จใ€‚ + +/// check | **FastAPI** ๆŽจ่ๅฐ†ๅ…ถไฝœไธบ๏ผš + +่ฟ่กŒ **FastAPI** ๅบ”็”จ็š„ไธป่ฆ Web ๆœๅŠกๅ™จใ€‚ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนไปฅ่Žทๅพ—ๅผ‚ๆญฅ็š„ๅคš่ฟ›็จ‹ๆœๅŠกๅ™จใ€‚ + +ๆ›ดๅคš็ป†่Š‚่ง[้ƒจ็ฝฒ](deployment/index.md){.internal-link target=_blank}ไธ€่Š‚ใ€‚ + +/// + +## ๅŸบๅ‡†ไธŽ้€Ÿๅบฆ { #benchmarks-and-speed } + +่ฆ็†่งฃใ€ๆฏ”่พƒๅนถๆŸฅ็œ‹ Uvicornใ€Starlette ไธŽ FastAPI ไน‹้—ด็š„ๅทฎๅผ‚๏ผŒ่ฏทๆŸฅ็œ‹[ๅŸบๅ‡†](benchmarks.md){.internal-link target=_blank}ไธ€่Š‚ใ€‚ diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index c94c907873..36d875f515 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -298,7 +298,7 @@ CPU ๅฏ†้›†ๅž‹ๆ“ไฝœ็š„ๅธธ่ง็คบไพ‹ๆ˜ฏ้œ€่ฆๅคๆ‚็š„ๆ•ฐๅญฆๅค„็†ใ€‚ ่ฟ™ไธ€็‚น๏ผŒๅ†ๅŠ ไธŠ Python ๆ˜ฏ**ๆ•ฐๆฎ็ง‘ๅญฆ**ใ€ๆœบๅ™จๅญฆไน ๏ผˆๅฐคๅ…ถๆ˜ฏๆทฑๅบฆๅญฆไน ๏ผ‰็š„ไธป่ฆ่ฏญ่จ€่ฟ™ไธ€็ฎ€ๅ•ไบ‹ๅฎž๏ผŒไฝฟๅพ— **FastAPI** ไธŽๆ•ฐๆฎ็ง‘ๅญฆ/ๆœบๅ™จๅญฆไน  Web API ๅ’Œๅบ”็”จ็จ‹ๅบ๏ผˆไปฅๅŠๅ…ถไป–่ฎธๅคšๅบ”็”จ็จ‹ๅบ๏ผ‰้žๅธธๅŒน้…ใ€‚ -ไบ†่งฃๅฆ‚ไฝ•ๅœจ็”Ÿไบง็Žฏๅขƒไธญๅฎž็Žฐ่ฟ™็งๅนถ่กŒๆ€ง๏ผŒๅฏๆŸฅ็œ‹ๆญคๆ–‡ [Deployment](deployment/index.md){.internal-link target=_blank}ใ€‚ +ไบ†่งฃๅฆ‚ไฝ•ๅœจ็”Ÿไบง็Žฏๅขƒไธญๅฎž็Žฐ่ฟ™็งๅนถ่กŒๆ€ง๏ผŒๅฏๆŸฅ็œ‹ๆญคๆ–‡ [้ƒจ็ฝฒ](deployment/index.md){.internal-link target=_blank}ใ€‚ ## `async` ๅ’Œ `await` { #async-and-await } @@ -369,7 +369,7 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบไบŽ AnyIO ็ผ–ๅ†™่‡ชๅทฑ็š„ๅผ‚ๆญฅ็จ‹ๅบ๏ผŒไฝฟๅ…ถๆ‹ฅๆœ‰่พƒ้ซ˜็š„ๅ…ผๅฎนๆ€งๅนถ่Žทๅพ—ไธ€ไบ›ๅฅฝๅค„๏ผˆไพ‹ๅฆ‚๏ผŒ ็ป“ๆž„ๅŒ–ๅนถๅ‘๏ผ‰ใ€‚ -ๆˆ‘๏ผˆๆŒ‡ๅŽŸไฝœ่€… โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰ๅŸบไบŽ AnyIO ๆ–ฐๅปบไบ†ไธ€ไธชๅบ“๏ผŒไฝœไธบไธ€ไธช่ฝป้‡็บง็š„ๅฐ่ฃ…ๅฑ‚๏ผŒ็”จๆฅไผ˜ๅŒ–็ฑปๅž‹ๆณจ่งฃ๏ผŒๅŒๆ—ถๆไพ›ไบ†ๆ›ดๅฅฝ็š„**่‡ชๅŠจ่กฅๅ…จ**ใ€**ๅ†…่”้”™่ฏฏๆ็คบ**็ญ‰ๅŠŸ่ƒฝใ€‚่ฟ™ไธชๅบ“่ฟ˜้™„ๅธฆไบ†ไธ€ไธชๅ‹ๅฅฝ็š„ๅ…ฅ้—จๆŒ‡ๅ—ๅ’Œๆ•™็จ‹๏ผŒ่ƒฝๅธฎๅŠฉไฝ **็†่งฃ**ๅนถ็ผ–ๅ†™**่‡ชๅทฑ็š„ๅผ‚ๆญฅไปฃ็ **๏ผšAsyncerใ€‚ๅฆ‚ๆžœไฝ ๆœ‰**็ป“ๅˆไฝฟ็”จๅผ‚ๆญฅไปฃ็ ๅ’Œๅธธ่ง„**๏ผˆ้˜ปๅกž/ๅŒๆญฅ๏ผ‰ไปฃ็ ็š„้œ€ๆฑ‚๏ผŒ่ฟ™ไธชๅบ“ไผš็‰นๅˆซๆœ‰็”จใ€‚ +ๆˆ‘ๅŸบไบŽ AnyIO ๆ–ฐๅปบไบ†ไธ€ไธชๅบ“๏ผŒไฝœไธบไธ€ไธช่ฝป้‡็บง็š„ๅฐ่ฃ…ๅฑ‚๏ผŒ็”จๆฅไผ˜ๅŒ–็ฑปๅž‹ๆณจ่งฃ๏ผŒๅŒๆ—ถๆไพ›ไบ†ๆ›ดๅฅฝ็š„**่‡ชๅŠจ่กฅๅ…จ**ใ€**ๅ†…่”้”™่ฏฏๆ็คบ**็ญ‰ๅŠŸ่ƒฝใ€‚่ฟ™ไธชๅบ“่ฟ˜้™„ๅธฆไบ†ไธ€ไธชๅ‹ๅฅฝ็š„ๅ…ฅ้—จๆŒ‡ๅ—ๅ’Œๆ•™็จ‹๏ผŒ่ƒฝๅธฎๅŠฉไฝ **็†่งฃ**ๅนถ็ผ–ๅ†™**่‡ชๅทฑ็š„ๅผ‚ๆญฅไปฃ็ **๏ผšAsyncerใ€‚ๅฆ‚ๆžœไฝ ๆœ‰**็ป“ๅˆไฝฟ็”จๅผ‚ๆญฅไปฃ็ ๅ’Œๅธธ่ง„**๏ผˆ้˜ปๅกž/ๅŒๆญฅ๏ผ‰ไปฃ็ ็š„้œ€ๆฑ‚๏ผŒ่ฟ™ไธชๅบ“ไผš็‰นๅˆซๆœ‰็”จใ€‚ ### ๅ…ถไป–ๅฝขๅผ็š„ๅผ‚ๆญฅไปฃ็  { #other-forms-of-asynchronous-code } diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md index 1a4b4a3de8..a6e706dfaa 100644 --- a/docs/zh/docs/benchmarks.md +++ b/docs/zh/docs/benchmarks.md @@ -23,7 +23,7 @@ * ไฝ ไธไผš็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบใ€‚่ฟ™ๆ„ๅ‘ณ็€ไฝ ็š„ไปฃ็ ่‡ณๅฐ‘ๅฟ…้กปๅŒ…ๅซ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰ๆไพ›็š„ไปฃ็ ใ€‚ๅฆ‚ๆžœไฝ ่ฟ™ๆ ทๅšไบ†๏ผˆๅณ็›ดๆŽฅๅœจ Uvicorn ไธญ็ผ–ๅ†™ๅบ”็”จ็จ‹ๅบ๏ผ‰๏ผŒๆœ€็ปˆ็š„ๅบ”็”จ็จ‹ๅบไผšๅ’Œไฝฟ็”จไบ†ๆก†ๆžถๅนถไธ”ๆœ€ๅฐๅŒ–ไบ†ๅบ”็”จไปฃ็ ๅ’Œ bug ็š„ๆƒ…ๅ†ตๅ…ทๆœ‰็›ธๅŒ็š„ๆ€ง่ƒฝๆŸ่€—ใ€‚ * ๅฆ‚ๆžœไฝ ่ฆๅฏนๆฏ” Uvicorn๏ผŒ่ฏทๅฐ†ๅ…ถไธŽ Daphne๏ผŒHypercorn๏ผŒuWSGI ็ญ‰ๅบ”็”จๆœๅŠกๅ™จ่ฟ›่กŒๆฏ”่พƒใ€‚ * **Starlette**: - * ๅœจ Uvicorn ๅŽไฝฟ็”จ Starlette๏ผŒๆ€ง่ƒฝไผš็•ฅๆœ‰ไธ‹้™ใ€‚ๅฎž้™…ไธŠ๏ผŒStarlette ไฝฟ็”จ Uvicorn ่ฟ่กŒใ€‚ๅ› ๆญค๏ผŒ็”ฑไบŽๅฟ…้กปๆ‰ง่กŒๆ›ดๅคš็š„ไปฃ็ ๏ผŒๅฎƒๅชไผšๆฏ” Uvicorn ๆ›ดๆ…ขใ€‚ + * ๆ€ง่ƒฝไป…ๆฌกไบŽ Uvicornใ€‚ๅฎž้™…ไธŠ๏ผŒStarlette ไฝฟ็”จ Uvicorn ่ฟ่กŒใ€‚ๅ› ๆญค๏ผŒ็”ฑไบŽๅฟ…้กปๆ‰ง่กŒๆ›ดๅคš็š„ไปฃ็ ๏ผŒๅฎƒๅชไผšๆฏ” Uvicorn ๆ›ดๆ…ขใ€‚ * ไฝ†ๅฎƒไธบไฝ ๆไพ›ไบ†ๆž„ๅปบ็ฎ€ๅ•็š„็ฝ‘็ปœ็จ‹ๅบ็š„ๅทฅๅ…ท๏ผŒๅนถๅ…ทๆœ‰ๅŸบไบŽ่ทฏๅพ„็š„่ทฏ็”ฑ็ญ‰ๅŠŸ่ƒฝใ€‚ * ๅฆ‚ๆžœๆƒณๅฏนๆฏ”ไธŽ Starlette ๅฏนๆ ‡็š„ๅผ€ๅ‘ๆก†ๆžถ๏ผŒ่ฏทๅฐ†ๅ…ถไธŽ Sanic๏ผŒFlask๏ผŒDjango ็ญ‰็ฝ‘็ปœๆก†ๆžถ๏ผˆๆˆ–ๅพฎๆก†ๆžถ๏ผ‰่ฟ›่กŒๆฏ”่พƒใ€‚ * **FastAPI**: diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index 66d32629cb..76e967d7de 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -190,7 +190,7 @@ ### ๅทฅไฝœ่ฟ›็จ‹ๅ’Œ็ซฏๅฃ { #worker-processes-and-ports } -่ฟ˜่ฎฐๅพ—ๆ–‡ๆกฃ [About HTTPS](https.md){.internal-link target=_blank} ไธญๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ๅฏไปฅไพฆๅฌๆœๅŠกๅ™จไธญ็š„็ซฏๅฃๅ’Œ IP ๅœฐๅ€็š„ไธ€็ง็ป„ๅˆๅ—๏ผŸ +่ฟ˜่ฎฐๅพ—ๆ–‡ๆกฃ [ๅ…ณไบŽ HTTPS](https.md){.internal-link target=_blank} ไธญๅชๆœ‰ไธ€ไธช่ฟ›็จ‹ๅฏไปฅไพฆๅฌๆœๅŠกๅ™จไธญ็š„็ซฏๅฃๅ’Œ IP ๅœฐๅ€็š„ไธ€็ง็ป„ๅˆๅ—๏ผŸ ็Žฐๅœจไป็„ถๆ˜ฏๅฏน็š„ใ€‚ diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md index 3d0c19903b..4e7410587e 100644 --- a/docs/zh/docs/deployment/docker.md +++ b/docs/zh/docs/deployment/docker.md @@ -14,7 +14,7 @@ Dockerfile ้ข„่งˆ ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ็„ถๅŽไฝ ๅช้œ€่ฆๅœจ `Dockerfile` ไธญไฟฎๆ”น็›ธๅบ”่ทฏๅพ„ๆฅๅคๅˆถ่ฏฅๆ–‡ไปถ๏ผš ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Traefik ไธŽ Dockerใ€Kubernetes ็ญ‰้ƒฝๆœ‰้›†ๆˆ๏ผŒๅ› ๆญคไธบๅฎนๅ™จ่ฎพ็ฝฎๅ’Œ้…็ฝฎ ## ๅคๅˆถ - ่ฟ›็จ‹ๆ•ฐ { #replication-number-of-processes } -ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช็”ฑ **Kubernetes**ใ€Docker Swarm Modeใ€Nomad ๆˆ–ๅ…ถไป–็ฑปไผผ็š„ๅคๆ‚็ณป็ปŸ็ฎก็†็š„ใ€ๅœจๅคšๅฐๆœบๅ™จไธŠ่ฟ่กŒ็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ้›†็พค๏ผŒ้‚ฃไนˆไฝ ๅพˆๅฏ่ƒฝไผšๅธŒๆœ›ๅœจ**้›†็พคๅฑ‚้ข**ๆฅ**ๅค„็†ๅคๅˆถ**๏ผŒ่€Œไธๆ˜ฏๅœจๆฏไธชๅฎนๅ™จไธญไฝฟ็”จ**่ฟ›็จ‹็ฎก็†**๏ผˆๆฏ”ๅฆ‚่ฎฉ Uvicorn ่ฟ่กŒๅคšไธช workers๏ผ‰ใ€‚ +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช็”ฑ **Kubernetes**ใ€Docker Swarm Modeใ€Nomad ๆˆ–ๅ…ถไป–็ฑปไผผ็š„ๅคๆ‚็ณป็ปŸ็ฎก็†็š„ใ€ๅœจๅคšๅฐๆœบๅ™จไธŠ่ฟ่กŒ็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ้›†็พค๏ผŒ้‚ฃไนˆไฝ ๅพˆๅฏ่ƒฝไผšๅธŒๆœ›ๅœจ**้›†็พคๅฑ‚้ข**ๆฅ**ๅค„็†ๅคๅˆถ**๏ผŒ่€Œไธๆ˜ฏๅœจๆฏไธชๅฎนๅ™จไธญไฝฟ็”จ**่ฟ›็จ‹็ฎก็†**๏ผˆๆฏ”ๅฆ‚่ฎฉ Uvicorn ่ฟ่กŒๅคšไธช workers๏ผ‰ใ€‚ ๅƒ Kubernetes ่ฟ™ๆ ท็š„ๅˆ†ๅธƒๅผๅฎนๅ™จ็ฎก็†็ณป็ปŸ้€šๅธธ้ƒฝๆœ‰ๆŸ็งๅ†…็ฝฎๆ–นๅผๆฅๅค„็†**ๅฎนๅ™จๅคๅˆถ**๏ผŒๅŒๆ—ถๅฏนไผ ๅ…ฅ่ฏทๆฑ‚่ฟ›่กŒ**่ดŸ่ฝฝๅ‡่กก**ใ€‚่ฟ™ไธ€ๅˆ‡้ƒฝๅœจ**้›†็พคๅฑ‚้ข**ๅฎŒๆˆใ€‚ @@ -499,7 +499,7 @@ Traefik ไธŽ Dockerใ€Kubernetes ็ญ‰้ƒฝๆœ‰้›†ๆˆ๏ผŒๅ› ๆญคไธบๅฎนๅ™จ่ฎพ็ฝฎๅ’Œ้…็ฝฎ ๅœจ่ฟ™ไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `--workers` ๅ‘ฝไปค่กŒ้€‰้กนๆฅ่ฎพ็ฝฎ่ฆ่ฟ่กŒ็š„ worker ๆ•ฐ้‡๏ผš ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/zh/docs/deployment/fastapicloud.md b/docs/zh/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..0239a15128 --- /dev/null +++ b/docs/zh/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +ไฝ ๅฏไปฅ็”จ**ไธ€ๆกๅ‘ฝไปค**ๅฐ†ไฝ ็š„ FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐ FastAPI Cloud๏ผŒๅฆ‚ๆžœ่ฟ˜ๆฒกๆœ‰๏ผŒๅŽปๅŠ ๅ…ฅๅ€™่กฅๅๅ•ๅงใ€‚๐Ÿš€ + +## ็™ปๅฝ• { #login } + +่ฏท็กฎไฟไฝ ๅทฒๆœ‰ **FastAPI Cloud** ่ดฆๅท๏ผˆๆˆ‘ไปฌๅทฒไปŽๅ€™่กฅๅๅ•ๅ‘ไฝ ๅ‘ๅ‡บ้‚€่ฏท ๐Ÿ˜‰๏ผ‰ใ€‚ + +็„ถๅŽ็™ปๅฝ•๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## ้ƒจ็ฝฒ { #deploy } + +็Žฐๅœจ็”จ**ไธ€ๆกๅ‘ฝไปค**้ƒจ็ฝฒไฝ ็š„ๅบ”็”จ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ่ฟ™ๆ ท๏ผ็Žฐๅœจไฝ ๅฏไปฅ้€š่ฟ‡่ฏฅ URL ่ฎฟ้—ฎไฝ ็š„ๅบ”็”จใ€‚โœจ + +## ๅ…ณไบŽ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ่ƒŒๅŽ็š„ไฝœ่€…ไธŽๅ›ข้˜Ÿๆ‰“้€ ใ€‚ + +ๅฎƒ่ฎฉไฝ ไปฅๆœ€ๅฐ็š„ๆŠ•ๅ…ฅๅฎŒๆˆ API ็š„**ๆž„ๅปบ**ใ€**้ƒจ็ฝฒ**ไธŽ**่ฎฟ้—ฎ**ใ€‚ + +ๅฎƒๆŠŠไฝฟ็”จ FastAPI ๆž„ๅปบๅบ”็”จๆ—ถ็š„**ๅผ€ๅ‘่€…ไฝ“้ชŒ**๏ผŒๅŒๆ ทๅธฆๅˆฐๅฐ†ๅบ”็”จ**้ƒจ็ฝฒ**ๅˆฐไบ‘ไธŠ็š„่ฟ‡็จ‹ใ€‚๐ŸŽ‰ + +ๅฎƒ่ฟ˜ไผšๆ›ฟไฝ ๅค„็†้ƒจ็ฝฒๅบ”็”จๆ—ถๅคงๅคšๆ•ฐ้œ€่ฆ็š„ไบ‹้กน๏ผŒไพ‹ๅฆ‚๏ผš + +* HTTPS +* ๅ‰ฏๆœฌใ€ๅŸบไบŽ่ฏทๆฑ‚็š„่‡ชๅŠจไผธ็ผฉ +* ็ญ‰็ญ‰ + +FastAPI Cloud ๆ˜ฏ *FastAPI and friends* ๅผ€ๆบ้กน็›ฎ็š„ไธป่ฆ่ตžๅŠฉๆ–นไธŽ่ต„้‡‘ๆไพ›่€…ใ€‚โœจ + +## ้ƒจ็ฝฒๅˆฐๅ…ถไป–ไบ‘ๆœๅŠกๅ•† { #deploy-to-other-cloud-providers } + +FastAPI ๆ˜ฏๅผ€ๆบ็š„๏ผŒๅนถๅŸบไบŽๆ ‡ๅ‡†ใ€‚ไฝ ๅฏไปฅๅฐ† FastAPI ๅบ”็”จ้ƒจ็ฝฒๅˆฐไฝ ้€‰ๆ‹ฉ็š„ไปปๆ„ไบ‘ๆœๅŠกๅ•†ใ€‚ + +ๆŒ‰็…งไฝ ๆ‰€้€‰ไบ‘ๆœๅŠกๅ•†็š„ๆŒ‡ๅ—้ƒจ็ฝฒ FastAPI ๅบ”็”จๅณๅฏใ€‚๐Ÿค“ + +## ้ƒจ็ฝฒๅˆฐไฝ ่‡ชๅทฑ็š„ๆœๅŠกๅ™จ { #deploy-your-own-server } + +ๅœจๅŽ้ข็š„**้ƒจ็ฝฒ**ๆŒ‡ๅ—ไธญ๏ผŒๆˆ‘ไนŸไผš่ฎฒ่งฃๆ‰€ๆœ‰็ป†่Š‚๏ผŒๅธฎๅŠฉไฝ ็†่งฃๅน•ๅŽๅ‘็”Ÿไบ†ไป€ไนˆใ€้œ€่ฆๅšไป€ไนˆ๏ผŒไปฅๅŠๅฆ‚ไฝ•่‡ช่กŒ้ƒจ็ฝฒ FastAPI ๅบ”็”จ๏ผŒๅŒ…ๆ‹ฌ้ƒจ็ฝฒๅˆฐไฝ ่‡ชๅทฑ็š„ๆœๅŠกๅ™จใ€‚๐Ÿค“ diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 4f60b7bca7..591707f6dd 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -65,13 +65,13 @@ ็ฌฌไธ€ๆญฅๆˆ‘ไปฌ่ฆๅ…ˆ**่Žทๅ–**ไธ€ไบ›**ๅŸŸๅ(Domain Name)**ใ€‚ ็„ถๅŽๅฏไปฅๅœจ DNS ๆœๅŠกๅ™จ๏ผˆๅฏ่ƒฝๆ˜ฏไฝ ็š„ๅŒไธ€ๅฎถไบ‘ๆœๅŠกๅ•†ๆไพ›็š„๏ผ‰ไธญ้…็ฝฎๅฎƒใ€‚ -ไฝ ๅฏ่ƒฝๆ‹ฅๆœ‰ไธ€ไธชไบ‘ๆœๅŠกๅ™จ๏ผˆ่™šๆ‹Ÿๆœบ๏ผ‰ๆˆ–็ฑปไผผ็š„ไธœ่ฅฟ๏ผŒๅนถไธ”ๅฎƒไผšๆœ‰ไธ€ไธชๅ›บๅฎš **ๅ…ฌๅ…ฑIPๅœฐๅ€**ใ€‚ +ไฝ ๅฏ่ƒฝๆ‹ฅๆœ‰ไธ€ไธชไบ‘ๆœๅŠกๅ™จ๏ผˆ่™šๆ‹Ÿๆœบ๏ผ‰ๆˆ–็ฑปไผผ็š„ไธœ่ฅฟ๏ผŒๅนถไธ”ๅฎƒไผšๆœ‰ไธ€ไธชๅ›บๅฎš **ๅ…ฌๅ…ฑIPๅœฐๅ€**ใ€‚ ๅœจ DNS ๆœๅŠกๅ™จไธญ๏ผŒไฝ ๅฏไปฅ้…็ฝฎไธ€ๆก่ฎฐๅฝ•๏ผˆโ€œA ่ฎฐๅฝ•โ€๏ผ‰ไปฅๅฐ† **ไฝ ็š„ๅŸŸๅ** ๆŒ‡ๅ‘ไฝ ๆœๅŠกๅ™จ็š„ๅ…ฌๅ…ฑ **IP ๅœฐๅ€**ใ€‚ ่ฟ™ไธชๆ“ไฝœไธ€่ˆฌๅช้œ€่ฆๅœจๆœ€ๅผ€ๅง‹ๆ‰ง่กŒไธ€ๆฌกใ€‚ -/// tip +/// tip | ๆ็คบ ๅŸŸๅ่ฟ™้ƒจๅˆ†ๅ‘็”Ÿๅœจ HTTPS ไน‹ๅ‰๏ผŒ็”ฑไบŽ่ฟ™ไธ€ๅˆ‡้ƒฝไพ่ต–ไบŽๅŸŸๅๅ’Œ IP ๅœฐๅ€๏ผŒๆ‰€ไปฅๅ…ˆๅœจ่ฟ™้‡Œๆไธ€ไธ‹ใ€‚ @@ -121,7 +121,7 @@ TLS ็ปˆๆญขไปฃ็†ๅฏไปฅ่ฎฟ้—ฎไธ€ไธชๆˆ–ๅคšไธช **TLS ่ฏไนฆ**๏ผˆHTTPS ่ฏไนฆ๏ผ‰ใ€‚ ่ฟ™ๅฐฑๆ˜ฏ **HTTPS**๏ผŒๅฎƒๅชๆ˜ฏ **ๅฎ‰ๅ…จ TLS ่ฟžๆŽฅ** ๅ†…็š„ๆ™ฎ้€š **HTTP**๏ผŒ่€Œไธๆ˜ฏ็บฏ็ฒน็š„๏ผˆๆœชๅŠ ๅฏ†็š„๏ผ‰TCP ่ฟžๆŽฅใ€‚ -/// tip +/// tip | ๆ็คบ ่ฏทๆณจๆ„๏ผŒ้€šไฟกๅŠ ๅฏ†ๅ‘็”Ÿๅœจ **TCP ๅฑ‚**๏ผŒ่€Œไธๆ˜ฏ HTTP ๅฑ‚ใ€‚ @@ -217,7 +217,7 @@ TLS ็ปˆๆญขไปฃ็†ๅฐ†ไฝฟ็”จๅๅ•†ๅฅฝ็š„ๅŠ ๅฏ†็ฎ—ๆณ•**่งฃๅฏ†่ฏทๆฑ‚**๏ผŒๅนถๅฐ†**๏ผˆ ่ฟ™ๅœจ้œ€่ฆๆญฃ็กฎๅค„็†้‡ๅฎšๅ‘็ญ‰ๅœบๆ™ฏๆ—ถๅพˆๆœ‰็”จใ€‚ -/// tip +/// tip | ๆ็คบ ไฝ ๅฏไปฅๅœจๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคš๏ผš[ๅœจไปฃ็†ไน‹ๅŽ - ๅฏ็”จไปฃ็†่ฝฌๅ‘่ฏทๆฑ‚ๅคด](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index 6f2ad27b2f..f519c1e87a 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -90,7 +90,7 @@ $ pip install "uvicorn[standard]" ็ฑปไผผ็š„ๆต็จ‹ไนŸ้€‚็”จไบŽไปปไฝ•ๅ…ถไป– ASGI ๆœๅŠกๅ™จ็จ‹ๅบใ€‚ -/// tip +/// tip | ๆ็คบ ้€š่ฟ‡ๆทปๅŠ  `standard` ้€‰้กน๏ผŒUvicorn ๅฐ†ๅฎ‰่ฃ…ๅนถไฝฟ็”จไธ€ไบ›ๆŽจ่็š„้ขๅค–ไพ่ต–้กนใ€‚ @@ -114,7 +114,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
-/// note +/// note | ๆณจๆ„ ๅ‘ฝไปค `uvicorn main:app` ็š„ๅซไน‰ๅฆ‚ไธ‹๏ผš @@ -131,7 +131,7 @@ from main import app ๆฏ็ง ASGI ๆœๅŠกๅ™จ็จ‹ๅบ้€šๅธธ้ƒฝไผšๆœ‰็ฑปไผผ็š„ๅ‘ฝไปค๏ผŒๆ‚จๅฏไปฅๅœจๅฎƒไปฌ็š„ๅฎ˜ๆ–นๆ–‡ๆกฃไธญๆ‰พๅˆฐๆ›ดๅคšไฟกๆฏใ€‚ -/// warning +/// warning | ่ญฆๅ‘Š Uvicorn ๅ’Œๅ…ถไป–ๆœๅŠกๅ™จๆ”ฏๆŒ `--reload` ้€‰้กน๏ผŒ่ฏฅ้€‰้กนๅœจๅผ€ๅ‘่ฟ‡็จ‹ไธญ้žๅธธๆœ‰็”จใ€‚ diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 7d7aa19c06..1414f7c6fc 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -6,7 +6,7 @@ ### ๅŸบไบŽๅผ€ๆ”พๆ ‡ๅ‡† { #based-on-open-standards } -* ็”จไบŽๅˆ›ๅปบ API ็š„ OpenAPI๏ผŒๅŒ…ๅซๅฏน่ทฏๅพ„ ๆ“ไฝœใ€ๅ‚ๆ•ฐใ€่ฏทๆฑ‚ไฝ“ใ€ๅฎ‰ๅ…จ็ญ‰็š„ๅฃฐๆ˜Žใ€‚ +* ็”จไบŽๅˆ›ๅปบ API ็š„ OpenAPI๏ผŒๅŒ…ๅซๅฏน่ทฏๅพ„ ๆ“ไฝœใ€ๅ‚ๆ•ฐใ€่ฏทๆฑ‚ไฝ“ใ€ๅฎ‰ๅ…จ็ญ‰็š„ๅฃฐๆ˜Žใ€‚ * ไฝฟ็”จ JSON Schema ่‡ชๅŠจ็”Ÿๆˆๆ•ฐๆฎๆจกๅž‹ๆ–‡ๆกฃ๏ผˆๅ› ไธบ OpenAPI ๆœฌ่บซๅฐฑๆ˜ฏๅŸบไบŽ JSON Schema ็š„๏ผ‰ใ€‚ * ็ป่ฟ‡ไบ†็ผœๅฏ†็š„็ ”็ฉถๅŽๅ›ด็ป•่ฟ™ไบ›ๆ ‡ๅ‡†่€Œ่ฎพ่ฎกใ€‚ๅนถ้ž็‹—ๅฐพ็ปญ่ฒ‚ใ€‚ * ่ฟ™ไนŸๅ…่ฎธไบ†ๅœจๅพˆๅคš่ฏญ่จ€ไธญ่‡ชๅŠจ**็”Ÿๆˆๅฎขๆˆท็ซฏไปฃ็ **ใ€‚ @@ -137,7 +137,7 @@ OpenAPI ไธญๅฎšไน‰็š„ๅฎ‰ๅ…จๆจกๅผ๏ผŒๅŒ…ๆ‹ฌ๏ผš ### ไพ่ต–ๆณจๅ…ฅ { #dependency-injection } -FastAPI ๆœ‰ไธ€ไธชไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผบๅคง็š„ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ +FastAPI ๆœ‰ไธ€ไธชไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผบๅคง็š„ไพ่ต–ๆณจๅ…ฅ็ณป็ปŸใ€‚ * ็”š่‡ณไพ่ต–ไนŸๅฏไปฅๆœ‰ไพ่ต–๏ผŒๅˆ›ๅปบไธ€ไธชๅฑ‚็บงๆˆ–่€…**โ€œๅ›พโ€ไพ่ต–**ใ€‚ * ๆ‰€ๆœ‰**่‡ชๅŠจๅŒ–ๅค„็†**้ƒฝ็”ฑๆก†ๆžถๅฎŒๆˆใ€‚ @@ -154,8 +154,8 @@ FastAPI ๆœ‰ไธ€ไธชไฝฟ็”จ้žๅธธ็ฎ€ๅ•๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผบๅคง็š„IDE/linter/brain** ้€‚้…: +* ๅ’Œไฝ  **IDE/linter/brain** ้€‚้…: * ๅ› ไธบ pydantic ๆ•ฐๆฎ็ป“ๆž„ไป…ไป…ๆ˜ฏไฝ ๅฎšไน‰็š„็ฑป็š„ๅฎžไพ‹๏ผ›่‡ชๅŠจ่กฅๅ…จ๏ผŒlinting๏ผŒmypy ไปฅๅŠไฝ ็š„็›ด่ง‰ๅบ”่ฏฅๅฏไปฅๅ’Œไฝ ้ชŒ่ฏ็š„ๆ•ฐๆฎไธ€่ตทๆญฃๅธธๅทฅไฝœใ€‚ * ้ชŒ่ฏ**ๅคๆ‚็ป“ๆž„**: * ไฝฟ็”จๅˆ†ๅฑ‚็š„ Pydantic ๆจกๅž‹๏ผŒPython `typing` ็š„ `List` ๅ’Œ `Dict` ็ญ‰็ญ‰ใ€‚ diff --git a/docs/zh/docs/help-fastapi.md b/docs/zh/docs/help-fastapi.md index 5a5157b5d3..1be60d9d55 100644 --- a/docs/zh/docs/help-fastapi.md +++ b/docs/zh/docs/help-fastapi.md @@ -59,7 +59,7 @@ ## ๅ‘ๆŽจ่ฐˆ่ฐˆ **FastAPI** { #tweet-about-fastapi } -Tweet about **FastAPI**๏ผŒๅ‘Š่ฏ‰ๆˆ‘ๅ’Œๅคงๅฎถไฝ ไธบไป€ไนˆๅ–œๆฌขๅฎƒใ€‚๐ŸŽ‰ +ๅ‘ๆŽจ่ฐˆ่ฐˆ **FastAPI**๏ผŒๅ‘Š่ฏ‰ๆˆ‘ๅ’Œๅคงๅฎถไฝ ไธบไป€ไนˆๅ–œๆฌขๅฎƒใ€‚๐ŸŽ‰ ๆˆ‘ๅพˆ้ซ˜ๅ…ดๅฌๅˆฐ **FastAPI** ็š„ไฝฟ็”จๆƒ…ๅ†ตใ€ไฝ ๅ–œๆฌขๅฎƒ็š„ๅ“ชไบ›็‚นใ€ไฝ ๅœจๅ“ชไธช้กน็›ฎ/ๅ…ฌๅธไฝฟ็”จๅฎƒ๏ผŒ็ญ‰็ญ‰ใ€‚ diff --git a/docs/zh/docs/how-to/authentication-error-status-code.md b/docs/zh/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..466b90e15a --- /dev/null +++ b/docs/zh/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# ไฝฟ็”จๆ—ง็š„ 403 ่ฎค่ฏ้”™่ฏฏ็Šถๆ€็  { #use-old-403-authentication-error-status-codes } + +ๅœจ FastAPI `0.122.0` ็‰ˆๆœฌไน‹ๅ‰๏ผŒๅฝ“ๅ†…็ฝฎ็š„ๅฎ‰ๅ…จๅทฅๅ…ทๅœจ่ฎค่ฏๅคฑ่ดฅๅŽๅ‘ๅฎขๆˆท็ซฏ่ฟ”ๅ›ž้”™่ฏฏๆ—ถ๏ผŒไผšไฝฟ็”จ HTTP ็Šถๆ€็  `403 Forbidden`ใ€‚ + +ไปŽ FastAPI `0.122.0` ็‰ˆๆœฌๅผ€ๅง‹๏ผŒๅฎƒไปฌๆ”น็”จๆ›ดๅˆ้€‚็š„ HTTP ็Šถๆ€็  `401 Unauthorized`๏ผŒๅนถๅœจๅ“ๅบ”ไธญ่ฟ”ๅ›žๅˆ็†็š„ `WWW-Authenticate` ๅคด๏ผŒ้ตๅพช HTTP ่ง„่Œƒ๏ผŒRFC 7235ใ€RFC 9110ใ€‚ + +ไฝ†ๅฆ‚ๆžœ็”ฑไบŽๆŸไบ›ๅŽŸๅ› ไฝ ็š„ๅฎขๆˆท็ซฏไพ่ต–ๆ—ง่กŒไธบ๏ผŒไฝ ๅฏไปฅๅœจไฝ ็š„ๅฎ‰ๅ…จ็ฑปไธญ้‡ๅ†™ๆ–นๆณ• `make_not_authenticated_error` ๆฅๅ›ž้€€ๅˆฐๆ—ง่กŒไธบใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅˆ›ๅปบไธ€ไธช `HTTPBearer` ็š„ๅญ็ฑป๏ผŒไฝฟๅ…ถ่ฟ”ๅ›ž `403 Forbidden` ้”™่ฏฏ๏ผŒ่€Œไธๆ˜ฏ้ป˜่ฎค็š„ `401 Unauthorized` ้”™่ฏฏ๏ผš + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | ๆ็คบ + +ๆณจๆ„่ฏฅๅ‡ฝๆ•ฐ่ฟ”ๅ›ž็š„ๆ˜ฏๅผ‚ๅธธๅฎžไพ‹๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๆŠ›ๅ‡บๅฎƒใ€‚ๆŠ›ๅ‡บๆ“ไฝœ็”ฑๅ…ถไฝ™็š„ๅ†…้ƒจไปฃ็ ๅฎŒๆˆใ€‚ + +/// diff --git a/docs/zh/docs/how-to/conditional-openapi.md b/docs/zh/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000..d26b5f3bd0 --- /dev/null +++ b/docs/zh/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# ๆŒ‰ๆกไปถ้…็ฝฎ OpenAPI { #conditional-openapi } + +ๅฆ‚ๆžœ้œ€่ฆ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡๏ผŒๆŒ‰็Žฏๅขƒๆœ‰ๆกไปถๅœฐ้…็ฝฎ OpenAPI๏ผŒ็”š่‡ณๅฎŒๅ…จ็ฆ็”จๅฎƒใ€‚ + +## ๅ…ณไบŽๅฎ‰ๅ…จใ€API ๅ’Œๆ–‡ๆกฃ { #about-security-apis-and-docs } + +ๅœจ็”Ÿไบง็Žฏๅขƒ้š่—ๆ–‡ๆกฃ็•Œ้ขๅนถไธๅบ”่ฏฅๆˆไธบไฟๆŠค API ็š„ๆ–นๅผใ€‚ + +่ฟ™ๅนถไธไผš็ป™ไฝ ็š„ API ๅขžๅŠ ไปปไฝ•้ขๅค–็š„ๅฎ‰ๅ…จๆ€ง๏ผŒ*่ทฏๅพ„ๆ“ไฝœ* ไป็„ถไผšๅœจๅŽŸๆฅ็š„ไฝ็ฝฎๅฏ็”จใ€‚ + +ๅฆ‚ๆžœไฝ ็š„ไปฃ็ ้‡Œๆœ‰ๅฎ‰ๅ…จๆผๆดž๏ผŒๅฎƒไป็„ถๅญ˜ๅœจใ€‚ + +้š่—ๆ–‡ๆกฃๅชไผš่ฎฉ็†่งฃๅฆ‚ไฝ•ไธŽ API ไบคไบ’ๅ˜ๅพ—ๆ›ดๅ›ฐ้šพ๏ผŒไนŸๅฏ่ƒฝ่ฎฉไฝ ๅœจ็”Ÿไบง็Žฏๅขƒไธญ่ฐƒ่ฏ•ๆ›ดๅ›ฐ้šพใ€‚่ฟ™ๅคงไฝ“ไธŠๅฏไปฅ่ขซ่ง†ไธบไธ€็ง ้€š่ฟ‡้š่—ๅฎž็Žฐๅฎ‰ๅ…จ ็š„ๅšๆณ•ใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณไฟๆŠคไฝ ็š„ API๏ผŒๆœ‰ๅพˆๅคšๆ›ดๅฅฝ็š„ๆŽชๆ–ฝ๏ผŒไพ‹ๅฆ‚๏ผš + +- ็กฎไฟไธบ่ฏทๆฑ‚ไฝ“ๅ’Œๅ“ๅบ”ๅฎšไน‰ๅฎŒๅ–„็š„ Pydantic ๆจกๅž‹ใ€‚ +- ไฝฟ็”จไพ่ต–้…็ฝฎๆ‰€้œ€็š„ๆƒ้™ๅ’Œ่ง’่‰ฒใ€‚ +- ็ปไธ่ฆๅญ˜ๅ‚จๆ˜Žๆ–‡ๅฏ†็ ๏ผŒๅชๅญ˜ๅ‚จๅฏ†็ ๅ“ˆๅธŒใ€‚ +- ๅฎž็Žฐๅนถไฝฟ็”จๆˆ็†Ÿ็š„ๅฏ†็ ๅญฆๅทฅๅ…ท๏ผŒๆฏ”ๅฆ‚ pwdlib ๅ’Œ JWT ไปค็‰Œ็ญ‰ใ€‚ +- ๅœจ้œ€่ฆ็š„ๅœฐๆ–นไฝฟ็”จ OAuth2 ไฝœ็”จๅŸŸๆทปๅŠ ๆ›ด็ป†็ฒ’ๅบฆ็š„ๆƒ้™ๆŽงๅˆถใ€‚ +- ...็ญ‰ใ€‚ + +ๅฐฝ็ฎกๅฆ‚ๆญค๏ผŒไฝ ๅฏ่ƒฝ็กฎๅฎžๆœ‰้žๅธธ็‰นๅฎš็š„็”จไพ‹๏ผŒ้œ€่ฆๅœจๆŸไบ›็Žฏๅขƒ๏ผˆไพ‹ๅฆ‚็”Ÿไบง็Žฏๅขƒ๏ผ‰็ฆ็”จ API ๆ–‡ๆกฃ๏ผŒๆˆ–ๆ นๆฎ็Žฏๅขƒๅ˜้‡็š„้…็ฝฎๆฅๅ†ณๅฎšใ€‚ + +## ๅŸบไบŽ่ฎพ็ฝฎๅ’Œ็Žฏๅขƒๅ˜้‡็š„ๆกไปถๅผ OpenAPI { #conditional-openapi-from-settings-and-env-vars } + +ไฝ ๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐไฝฟ็”จ็›ธๅŒ็š„ Pydantic ่ฎพ็ฝฎๆฅ้…็ฝฎ็”Ÿๆˆ็š„ OpenAPI ๅ’Œๆ–‡ๆกฃ UIใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +่ฟ™้‡Œๆˆ‘ไปฌๅฃฐๆ˜Žไบ†่ฎพ็ฝฎ้กน `openapi_url`๏ผŒๅ…ถ้ป˜่ฎคๅ€ผๅŒๆ ทๆ˜ฏ `"/openapi.json"`ใ€‚ + +็„ถๅŽๅœจๅˆ›ๅปบ `FastAPI` ๅบ”็”จๆ—ถไฝฟ็”จๅฎƒใ€‚ + +ๆŽฅ็€๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ๆŠŠ็Žฏๅขƒๅ˜้‡ `OPENAPI_URL` ่ฎพไธบ็ฉบๅญ—็ฌฆไธฒๆฅ็ฆ็”จ OpenAPI๏ผˆๅŒ…ๆ‹ฌๆ–‡ๆกฃ UI๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +็„ถๅŽๅฆ‚ๆžœไฝ ่ฎฟ้—ฎ `/openapi.json`ใ€`/docs` ๆˆ– `/redoc`๏ผŒๅฐฑไผšๅพ—ๅˆฐไธ€ไธช `404 Not Found` ้”™่ฏฏ๏ผŒไพ‹ๅฆ‚๏ผš + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md index 104baff4bd..bf26246573 100644 --- a/docs/zh/docs/how-to/configure-swagger-ui.md +++ b/docs/zh/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ FastAPIไผšๅฐ†่ฟ™ไบ›้…็ฝฎ่ฝฌๆขไธบ **JSON**๏ผŒไฝฟๅ…ถไธŽ JavaScript ๅ…ผๅฎน๏ผŒๅ›  ไฝ†ๆ˜ฏไฝ ๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ `syntaxHighlight` ไธบ `False` ๆฅ็ฆ็”จ Swagger UI ไธญ็š„่ฏญๆณ•้ซ˜ไบฎ๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ...ๅœจๆญคไน‹ๅŽ๏ผŒSwagger UI ๅฐ†ไธไผš้ซ˜ไบฎไปฃ็ : @@ -28,7 +28,7 @@ FastAPIไผšๅฐ†่ฟ™ไบ›้…็ฝฎ่ฝฌๆขไธบ **JSON**๏ผŒไฝฟๅ…ถไธŽ JavaScript ๅ…ผๅฎน๏ผŒๅ›  ๅŒๆ ทๅœฐ๏ผŒไฝ ไนŸๅฏไปฅ้€š่ฟ‡่ฎพ็ฝฎ้”ฎ `"syntaxHighlight.theme"` ๆฅ่ฎพ็ฝฎ่ฏญๆณ•้ซ˜ไบฎไธป้ข˜๏ผˆๆณจๆ„ไธญ้—ดๆœ‰ไธ€ไธช็‚น๏ผ‰๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} ่ฟ™ไธช้…็ฝฎไผšๆ”นๅ˜่ฏญๆณ•้ซ˜ไบฎไธป้ข˜๏ผš @@ -46,7 +46,7 @@ FastAPI ๅŒ…ๅซไบ†ไธ€ไบ›้ป˜่ฎค้…็ฝฎๅ‚ๆ•ฐ๏ผŒ้€‚็”จไบŽๅคงๅคšๆ•ฐ็”จไพ‹ใ€‚ ๆฏ”ๅฆ‚๏ผŒๅฆ‚ๆžœ่ฆ็ฆ็”จ `deepLinking`๏ผŒไฝ ๅฏไปฅๅƒ่ฟ™ๆ ทไผ ้€’่ฎพ็ฝฎๅˆฐ `swagger_ui_parameters` ไธญ๏ผš -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## ๅ…ถไป– Swagger UI ๅ‚ๆ•ฐ { #other-swagger-ui-parameters } diff --git a/docs/zh/docs/how-to/custom-docs-ui-assets.md b/docs/zh/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..9e6e5a66b8 --- /dev/null +++ b/docs/zh/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ่‡ชๆ‰˜็ฎก่‡ชๅฎšไน‰ๆ–‡ๆกฃ UI ้™ๆ€่ต„ๆบ { #custom-docs-ui-static-assets-self-hosting } + +API ๆ–‡ๆกฃไฝฟ็”จ Swagger UI ๅ’Œ ReDoc๏ผŒๅฎƒไปฌๅ„่‡ช้œ€่ฆไธ€ไบ› JavaScript ๅ’Œ CSS ๆ–‡ไปถใ€‚ + +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ่ฟ™ไบ›ๆ–‡ไปถไปŽไธ€ไธช CDN ๆไพ›ใ€‚ + +ไธ่ฟ‡ไฝ ๅฏไปฅ่‡ชๅฎšไน‰๏ผšๅฏไปฅๆŒ‡ๅฎš็‰นๅฎš็š„ CDN๏ผŒๆˆ–่‡ช่กŒๆไพ›่ฟ™ไบ›ๆ–‡ไปถใ€‚ + +## ไธบ JavaScript ๅ’Œ CSS ่‡ชๅฎšไน‰ CDN { #custom-cdn-for-javascript-and-css } + +ๅ‡่ฎพไฝ ๆƒณไฝฟ็”จไธๅŒ็š„ CDN๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `https://unpkg.com/`ใ€‚ + +ๅฆ‚ๆžœไฝ ๆ‰€ๅœจ็š„ๅ›ฝๅฎถ/ๅœฐๅŒบๅฑ่”ฝไบ†ๆŸไบ› URL๏ผŒ่ฟ™ไผšๅพˆๆœ‰็”จใ€‚ + +### ๅ…ณ้—ญ่‡ชๅŠจๆ–‡ๆกฃ { #disable-the-automatic-docs } + +็ฌฌไธ€ๆญฅๆ˜ฏๅ…ณ้—ญ่‡ชๅŠจๆ–‡ๆกฃ๏ผŒๅ› ไธบ้ป˜่ฎคๅฎƒไปฌไผšไฝฟ็”จ้ป˜่ฎค็š„ CDNใ€‚ + +่ฆๅ…ณ้—ญๅฎƒไปฌ๏ผŒๅœจๅˆ›ๅปบ `FastAPI` ๅบ”็”จๆ—ถๅฐ†ๅ…ถ URL ่ฎพไธบ `None`๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### ๅŒ…ๅซ่‡ชๅฎšไน‰ๆ–‡ๆกฃ { #include-the-custom-docs } + +็Žฐๅœจไฝ ๅฏไปฅไธบ่‡ชๅฎšไน‰ๆ–‡ๆกฃๅˆ›ๅปบ*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ + +ไฝ ๅฏไปฅๅค็”จ FastAPI ็š„ๅ†…้ƒจๅ‡ฝๆ•ฐๆฅๅˆ›ๅปบๆ–‡ๆกฃ็š„ HTML ้กต้ข๏ผŒๅนถไผ ๅ…ฅๆ‰€้œ€ๅ‚ๆ•ฐ๏ผš + +- `openapi_url`๏ผšๆ–‡ๆกฃ HTML ้กต้ข่Žทๅ–ไฝ ็š„ API ็š„ OpenAPI ๆจกๅผ็š„ URLใ€‚่ฟ™้‡Œๅฏไปฅไฝฟ็”จ `app.openapi_url` ๅฑžๆ€งใ€‚ +- `title`๏ผšไฝ ็š„ API ๆ ‡้ข˜ใ€‚ +- `oauth2_redirect_url`๏ผš่ฟ™้‡Œๅฏไปฅไฝฟ็”จ `app.swagger_ui_oauth2_redirect_url` ๆฅไฝฟ็”จ้ป˜่ฎคๅ€ผใ€‚ +- `swagger_js_url`๏ผšไฝ ็š„ Swagger UI ๆ–‡ๆกฃ HTML ่Žทๅ–**JavaScript** ๆ–‡ไปถ็š„ URLใ€‚่ฟ™้‡Œๆ˜ฏ่‡ชๅฎšไน‰็š„ CDN URLใ€‚ +- `swagger_css_url`๏ผšไฝ ็š„ Swagger UI ๆ–‡ๆกฃ HTML ่Žทๅ–**CSS** ๆ–‡ไปถ็š„ URLใ€‚่ฟ™้‡Œๆ˜ฏ่‡ชๅฎšไน‰็š„ CDN URLใ€‚ + +ReDoc ไนŸ็ฑปไผผ... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | ๆ็คบ + +`swagger_ui_redirect` ็š„*่ทฏๅพ„ๆ“ไฝœ*ๆ˜ฏๅœจไฝ ไฝฟ็”จ OAuth2 ๆ—ถ็š„ไธ€ไธช่พ…ๅŠฉใ€‚ + +ๅฆ‚ๆžœไฝ ๆŠŠ API ไธŽๆŸไธช OAuth2 ๆไพ›ๆ–น้›†ๆˆ๏ผŒไฝ ๅฐฑๅฏไปฅๅฎŒๆˆ่ฎค่ฏๅนถๅธฆ็€่Žทๅ–ๅˆฐ็š„ๅ‡ญๆฎๅ›žๅˆฐ API ๆ–‡ๆกฃ้‡Œใ€‚็„ถๅŽไฝฟ็”จ็œŸๅฎž็š„ OAuth2 ่ฎค่ฏไธŽไน‹ไบคไบ’ใ€‚ + +Swagger UI ไผšๅœจๅน•ๅŽไธบไฝ ๅค„็†่ฟ™ไบ›๏ผŒไฝ†ๅฎƒ้œ€่ฆ่ฟ™ไธชโ€œ้‡ๅฎšๅ‘โ€่พ…ๅŠฉ่ทฏๅพ„ใ€‚ + +/// + +### ๅˆ›ๅปบไธ€ไธช่ทฏๅพ„ๆ“ไฝœ่ฟ›่กŒๆต‹่ฏ• { #create-a-path-operation-to-test-it } + +็Žฐๅœจ๏ผŒไธบไบ†ๆต‹่ฏ•ไธ€ๅˆ‡ๆ˜ฏๅฆๆญฃๅธธ๏ผŒๅˆ›ๅปบไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### ๆต‹่ฏ• { #test-it } + +็Žฐๅœจ๏ผŒไฝ ๅบ”่ฏฅๅฏไปฅ่ฎฟ้—ฎ http://127.0.0.1:8000/docs๏ผŒๅนถๅˆทๆ–ฐ้กต้ข๏ผŒ้กต้ขไผšไปŽๆ–ฐ็š„ CDN ๅŠ ่ฝฝ่ฟ™ไบ›่ต„ๆบใ€‚ + +## ไธบๆ–‡ๆกฃ่‡ชๆ‰˜็ฎก JavaScript ๅ’Œ CSS { #self-hosting-javascript-and-css-for-docs } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅœจ็ฆป็บฟใ€ๆ— ๆณ•่ฎฟ้—ฎไบ’่”็ฝ‘ๆˆ–ไป…ๅœจๅฑ€ๅŸŸ็ฝ‘ๅ†…ๆ—ถ๏ผŒๅบ”็”จไป่ƒฝๅทฅไฝœ๏ผŒ้‚ฃไนˆ่‡ชๆ‰˜็ฎก JavaScript ๅ’Œ CSS ไผšๅพˆๆœ‰็”จใ€‚ + +่ฟ™้‡Œไฝ ๅฐ†็œ‹ๅˆฐๅฆ‚ไฝ•ๅœจๅŒไธ€ไธช FastAPI ๅบ”็”จไธญ่‡ช่กŒๆไพ›่ฟ™ไบ›ๆ–‡ไปถ๏ผŒๅนถ้…็ฝฎๆ–‡ๆกฃไฝฟ็”จๅฎƒไปฌใ€‚ + +### ้กน็›ฎๆ–‡ไปถ็ป“ๆž„ { #project-file-structure } + +ๅ‡่ฎพไฝ ็š„้กน็›ฎๆ–‡ไปถ็ป“ๆž„ๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +็Žฐๅœจๅˆ›ๅปบไธ€ไธช็›ฎๅฝ•ๆฅๅญ˜ๆ”พ่ฟ™ไบ›้™ๆ€ๆ–‡ไปถใ€‚ + +ไฝ ็š„ๆ–ฐๆ–‡ไปถ็ป“ๆž„ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### ไธ‹่ฝฝๆ–‡ไปถ { #download-the-files } + +ไธ‹่ฝฝๆ–‡ๆกฃ้œ€่ฆ็š„้™ๆ€ๆ–‡ไปถ๏ผŒๅนถๅฐ†ๅฎƒไปฌๆ”พๅˆฐ `static/` ็›ฎๅฝ•ไธญใ€‚ + +ไฝ ้€šๅธธๅฏไปฅๅณ้”ฎ็‚นๅ‡ปๆฏไธช้“พๆŽฅ๏ผŒ้€‰ๆ‹ฉ็ฑปไผผโ€œๅฐ†้“พๆŽฅๅฆๅญ˜ไธบ...โ€็š„้€‰้กนใ€‚ + +Swagger UI ไฝฟ็”จไปฅไธ‹ๆ–‡ไปถ๏ผš + +- `swagger-ui-bundle.js` +- `swagger-ui.css` + +่€Œ ReDoc ไฝฟ็”จไปฅไธ‹ๆ–‡ไปถ๏ผš + +- `redoc.standalone.js` + +ไน‹ๅŽ๏ผŒไฝ ็š„ๆ–‡ไปถ็ป“ๆž„ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### ๆไพ›้™ๆ€ๆ–‡ไปถ { #serve-the-static-files } + +- ๅฏผๅ…ฅ `StaticFiles`ใ€‚ +- ๅœจ็‰นๅฎš่ทฏๅพ„ไธŠโ€œๆŒ‚่ฝฝโ€ไธ€ไธช `StaticFiles()` ๅฎžไพ‹ใ€‚ + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### ๆต‹่ฏ•้™ๆ€ๆ–‡ไปถ { #test-the-static-files } + +ๅฏๅŠจไฝ ็š„ๅบ”็”จ๏ผŒๅนถ่ฎฟ้—ฎ http://127.0.0.1:8000/static/redoc.standalone.jsใ€‚ + +ไฝ ๅบ”่ฏฅไผš็œ‹ๅˆฐไธ€ไธช้žๅธธ้•ฟ็š„ **ReDoc** ็š„ JavaScript ๆ–‡ไปถใ€‚ + +ๅฎƒๅฏ่ƒฝไปฅๅฆ‚ไธ‹ๅ†…ๅฎนๅผ€ๅคด๏ผš + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +่ฟ™ๅฐฑ็กฎ่ฎคไบ†ไฝ ็š„ๅบ”็”จ่ƒฝๅคŸๆไพ›้™ๆ€ๆ–‡ไปถ๏ผŒๅนถไธ”ไฝ ๆŠŠๆ–‡ๆกฃๆ‰€้œ€็š„้™ๆ€ๆ–‡ไปถๆ”พๅœจไบ†ๆญฃ็กฎ็š„ไฝ็ฝฎใ€‚ + +็Žฐๅœจๆˆ‘ไปฌๅฏไปฅ้…็ฝฎๅบ”็”จ๏ผŒ่ฎฉๆ–‡ๆกฃไฝฟ็”จ่ฟ™ไบ›้™ๆ€ๆ–‡ไปถใ€‚ + +### ไธบ้™ๆ€ๆ–‡ไปถๅ…ณ้—ญ่‡ชๅŠจๆ–‡ๆกฃ { #disable-the-automatic-docs-for-static-files } + +ๅ’Œไฝฟ็”จ่‡ชๅฎšไน‰ CDN ไธ€ๆ ท๏ผŒ็ฌฌไธ€ๆญฅๆ˜ฏๅ…ณ้—ญ่‡ชๅŠจๆ–‡ๆกฃ๏ผŒๅ› ไธบ้ป˜่ฎคๆƒ…ๅ†ตไธ‹ๅฎƒไปฌไผšไฝฟ็”จ CDNใ€‚ + +่ฆๅ…ณ้—ญๅฎƒไปฌ๏ผŒๅœจๅˆ›ๅปบ `FastAPI` ๅบ”็”จๆ—ถๅฐ†ๅ…ถ URL ่ฎพไธบ `None`๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### ไธบ้™ๆ€ๆ–‡ไปถๅŒ…ๅซ่‡ชๅฎšไน‰ๆ–‡ๆกฃ { #include-the-custom-docs-for-static-files } + +ๅŒๆ ทๅœฐ๏ผŒ็Žฐๅœจไฝ ๅฏไปฅไธบ่‡ชๅฎšไน‰ๆ–‡ๆกฃๅˆ›ๅปบ*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ + +ไฝ ๅฏไปฅๅ†ๆฌกๅค็”จ FastAPI ็š„ๅ†…้ƒจๅ‡ฝๆ•ฐๆฅๅˆ›ๅปบๆ–‡ๆกฃ็š„ HTML ้กต้ข๏ผŒๅนถไผ ๅ…ฅๆ‰€้œ€ๅ‚ๆ•ฐ๏ผš + +- `openapi_url`๏ผšๆ–‡ๆกฃ HTML ้กต้ข่Žทๅ–ไฝ ็š„ API ็š„ OpenAPI ๆจกๅผ็š„ URLใ€‚่ฟ™้‡Œๅฏไปฅไฝฟ็”จ `app.openapi_url` ๅฑžๆ€งใ€‚ +- `title`๏ผšไฝ ็š„ API ๆ ‡้ข˜ใ€‚ +- `oauth2_redirect_url`๏ผš่ฟ™้‡Œๅฏไปฅไฝฟ็”จ `app.swagger_ui_oauth2_redirect_url` ๆฅไฝฟ็”จ้ป˜่ฎคๅ€ผใ€‚ +- `swagger_js_url`๏ผšไฝ ็š„ Swagger UI ๆ–‡ๆกฃ HTML ่Žทๅ–**JavaScript** ๆ–‡ไปถ็š„ URLใ€‚**่ฟ™ๆ˜ฏ็Žฐๅœจ็”ฑไฝ ็š„ๅบ”็”จ่‡ชๅทฑๆไพ›็š„้‚ฃไธช**ใ€‚ +- `swagger_css_url`๏ผšไฝ ็š„ Swagger UI ๆ–‡ๆกฃ HTML ่Žทๅ–**CSS** ๆ–‡ไปถ็š„ URLใ€‚**่ฟ™ๆ˜ฏ็Žฐๅœจ็”ฑไฝ ็š„ๅบ”็”จ่‡ชๅทฑๆไพ›็š„้‚ฃไธช**ใ€‚ + +ReDoc ไนŸ็ฑปไผผ... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | ๆ็คบ + +`swagger_ui_redirect` ็š„*่ทฏๅพ„ๆ“ไฝœ*ๆ˜ฏๅœจไฝ ไฝฟ็”จ OAuth2 ๆ—ถ็š„ไธ€ไธช่พ…ๅŠฉใ€‚ + +ๅฆ‚ๆžœไฝ ๆŠŠ API ไธŽๆŸไธช OAuth2 ๆไพ›ๆ–น้›†ๆˆ๏ผŒไฝ ๅฐฑๅฏไปฅๅฎŒๆˆ่ฎค่ฏๅนถๅธฆ็€่Žทๅ–ๅˆฐ็š„ๅ‡ญๆฎๅ›žๅˆฐ API ๆ–‡ๆกฃ้‡Œใ€‚็„ถๅŽไฝฟ็”จ็œŸๅฎž็š„ OAuth2 ่ฎค่ฏไธŽไน‹ไบคไบ’ใ€‚ + +Swagger UI ไผšๅœจๅน•ๅŽไธบไฝ ๅค„็†่ฟ™ไบ›๏ผŒไฝ†ๅฎƒ้œ€่ฆ่ฟ™ไธชโ€œ้‡ๅฎšๅ‘โ€่พ…ๅŠฉ่ทฏๅพ„ใ€‚ + +/// + +### ๅˆ›ๅปบไธ€ไธช่ทฏๅพ„ๆ“ไฝœๆต‹่ฏ•้™ๆ€ๆ–‡ไปถ { #create-a-path-operation-to-test-static-files } + +็Žฐๅœจ๏ผŒไธบไบ†ๆต‹่ฏ•ไธ€ๅˆ‡ๆ˜ฏๅฆๆญฃๅธธ๏ผŒๅˆ›ๅปบไธ€ไธช*่ทฏๅพ„ๆ“ไฝœ*๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### ๆต‹่ฏ•้™ๆ€ๆ–‡ไปถ UI { #test-static-files-ui } + +็Žฐๅœจ๏ผŒไฝ ๅฏไปฅๆ–ญๅผ€ WiFi๏ผŒ่ฎฟ้—ฎ http://127.0.0.1:8000/docs๏ผŒๅนถๅˆทๆ–ฐ้กต้ขใ€‚ + +ๅณไฝฟๆฒกๆœ‰ไบ’่”็ฝ‘๏ผŒไฝ ไนŸ่ƒฝ็œ‹ๅˆฐ API ็š„ๆ–‡ๆกฃๅนถไธŽไน‹ไบคไบ’ใ€‚ diff --git a/docs/zh/docs/how-to/custom-request-and-route.md b/docs/zh/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..8b365987ce --- /dev/null +++ b/docs/zh/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ่‡ชๅฎšไน‰ Request ๅ’Œ APIRoute ็ฑป { #custom-request-and-apiroute-class } + +ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆ้‡ๅ†™ `Request` ๅ’Œ `APIRoute` ็ฑปไฝฟ็”จ็š„้€ป่พ‘ใ€‚ + +ๅฐคๅ…ถๆ˜ฏ๏ผŒๅฝ“ไฝ ๆœฌๆฅไผšๆŠŠ่ฟ™ไบ›้€ป่พ‘ๆ”พๅˆฐไธญ้—ดไปถ้‡Œๆ—ถ๏ผŒ่ฟ™ๆ˜ฏไธ€ไธชไธ้”™็š„ๆ›ฟไปฃๆ–นๆกˆใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๆƒณๅœจๅบ”็”จๅค„็†ไน‹ๅ‰่ฏปๅ–ๆˆ–ๆ“ไฝœ่ฏทๆฑ‚ไฝ“ใ€‚ + +/// danger | ๅฑ้™ฉ + +่ฟ™ๆ˜ฏไธ€ไธชโ€œ้ซ˜็บงโ€็‰นๆ€งใ€‚ + +ๅฆ‚ๆžœไฝ ๅˆšๅผ€ๅง‹ไฝฟ็”จ **FastAPI**๏ผŒๅฏไปฅๅ…ˆ่ทณ่ฟ‡ๆœฌ่Š‚ใ€‚ + +/// + +## ไฝฟ็”จๅœบๆ™ฏ { #use-cases } + +ไธ€ไบ›ไฝฟ็”จๅœบๆ™ฏๅŒ…ๆ‹ฌ๏ผš + +* ๅฐ†้ž JSON ็š„่ฏทๆฑ‚ไฝ“่ฝฌๆขไธบ JSON๏ผˆไพ‹ๅฆ‚ `msgpack`๏ผ‰ใ€‚ +* ่งฃๅŽ‹็ผฉไฝฟ็”จ gzip ๅŽ‹็ผฉ็š„่ฏทๆฑ‚ไฝ“ใ€‚ +* ่‡ชๅŠจ่ฎฐๅฝ•ๆ‰€ๆœ‰่ฏทๆฑ‚ไฝ“ๆ—ฅๅฟ—ใ€‚ + +## ๅค„็†่‡ชๅฎšไน‰่ฏทๆฑ‚ไฝ“็ผ–็  { #handling-custom-request-body-encodings } + +ๆฅ็œ‹ๅฆ‚ไฝ•็”จ่‡ชๅฎšไน‰็š„ `Request` ๅญ็ฑปๆฅ่งฃๅŽ‹ gzip ่ฏทๆฑ‚ใ€‚ + +ไปฅๅŠไธ€ไธช `APIRoute` ๅญ็ฑปๆฅไฝฟ็”จ่ฏฅ่‡ชๅฎšไน‰่ฏทๆฑ‚็ฑปใ€‚ + +### ๅˆ›ๅปบ่‡ชๅฎšไน‰ `GzipRequest` ็ฑป { #create-a-custom-gziprequest-class } + +/// tip | ๆ็คบ + +่ฟ™ๆ˜ฏไธ€ไธชๆผ”็คบๅทฅไฝœๅŽŸ็†็š„็คบไพ‹ใ€‚ๅฆ‚ๆžœไฝ ้œ€่ฆ Gzip ๆ”ฏๆŒ๏ผŒๅฏไปฅ็›ดๆŽฅไฝฟ็”จๆไพ›็š„ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}ใ€‚ + +/// + +้ฆ–ๅ…ˆ๏ผŒๆˆ‘ไปฌๅˆ›ๅปบไธ€ไธช `GzipRequest` ็ฑป๏ผŒๅฎƒไผš้‡ๅ†™ `Request.body()` ๆ–นๆณ•๏ผšๅฝ“่ฏทๆฑ‚ๅคดไธญๅญ˜ๅœจ็›ธๅบ”ๆ ‡่ฎฐๆ—ถๅฏน่ฏทๆฑ‚ไฝ“่ฟ›่กŒ่งฃๅŽ‹ใ€‚ + +ๅฆ‚ๆžœ่ฏทๆฑ‚ๅคดไธญๆฒกๆœ‰ `gzip`๏ผŒๅˆ™ไธไผšๅฐ่ฏ•่งฃๅŽ‹ใ€‚ + +่ฟ™ๆ ท๏ผŒๅŒไธ€ไธช่ทฏ็”ฑ็ฑปๅณๅฏๅŒๆ—ถๅค„็† gzip ๅŽ‹็ผฉๅ’ŒๆœชๅŽ‹็ผฉ็š„่ฏทๆฑ‚ใ€‚ + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ๅˆ›ๅปบ่‡ชๅฎšไน‰ `GzipRoute` ็ฑป { #create-a-custom-gziproute-class } + +ๆŽฅ็€๏ผŒๆˆ‘ไปฌๅˆ›ๅปบ `fastapi.routing.APIRoute` ็š„่‡ชๅฎšไน‰ๅญ็ฑปๆฅไฝฟ็”จ `GzipRequest`ใ€‚ + +่ฟ™ๆฌก๏ผŒๆˆ‘ไปฌไผš้‡ๅ†™ `APIRoute.get_route_handler()` ๆ–นๆณ•ใ€‚ + +่ฏฅๆ–นๆณ•่ฟ”ๅ›žไธ€ไธชๅ‡ฝๆ•ฐ๏ผŒ่ฟ™ไธชๅ‡ฝๆ•ฐ่ดŸ่ดฃๆŽฅๆ”ถ่ฏทๆฑ‚ๅนถ่ฟ”ๅ›žๅ“ๅบ”ใ€‚ + +่ฟ™้‡Œๆˆ‘ไปฌ็”จๅฎƒๆŠŠๅŽŸๅง‹่ฏทๆฑ‚ๅŒ…่ฃ…ไธบ `GzipRequest`ใ€‚ + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | ๆŠ€ๆœฏ็ป†่Š‚ + +`Request` ๆ‹ฅๆœ‰ `request.scope` ๅฑžๆ€ง๏ผŒๅฎƒๅฐฑๆ˜ฏไธ€ไธช Python `dict`๏ผŒๅŒ…ๅซไธŽ่ฏทๆฑ‚็›ธๅ…ณ็š„ๅ…ƒๆ•ฐๆฎใ€‚ + +`Request` ่ฟ˜ๅŒ…ๅซ `request.receive`๏ผŒๅฎƒๆ˜ฏไธ€ไธช็”จไบŽโ€œๆŽฅๆ”ถโ€่ฏทๆฑ‚ไฝ“็š„ๅ‡ฝๆ•ฐใ€‚ + +`scope` ๅญ—ๅ…ธๅ’Œ `receive` ๅ‡ฝๆ•ฐ้ƒฝๆ˜ฏ ASGI ่ง„่Œƒ็š„ไธ€้ƒจๅˆ†ใ€‚ + +ๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ `Request` ๅฎžไพ‹้œ€่ฆ่ฟ™ไธคๆ ท๏ผš`scope` ๅ’Œ `receive`ใ€‚ + +ๆƒณไบ†่งฃๆ›ดๅคšๅ…ณไบŽ `Request` ็š„ไฟกๆฏ๏ผŒ่ฏทๆŸฅ็œ‹ Starlette ็š„ Request ๆ–‡ๆกฃใ€‚ + +/// + +็”ฑ `GzipRequest.get_route_handler` ่ฟ”ๅ›ž็š„ๅ‡ฝๆ•ฐๅ”ฏไธ€ไธๅŒไน‹ๅค„ๆ˜ฏๆŠŠ `Request` ่ฝฌๆขไธบ `GzipRequest`ใ€‚ + +่ฟ™ๆ ท๏ผŒๅœจไผ ็ป™ๆˆ‘ไปฌ็š„่ทฏๅพ„ๆ“ไฝœไน‹ๅ‰๏ผŒ`GzipRequest` ไผš๏ผˆๅœจ้œ€่ฆๆ—ถ๏ผ‰่ดŸ่ดฃ่งฃๅŽ‹ๆ•ฐๆฎใ€‚ + +ไน‹ๅŽ๏ผŒๅ…ถไฝ™ๅค„็†้€ป่พ‘ๅฎŒๅ…จ็›ธๅŒใ€‚ + +ไฝ†็”ฑไบŽๆˆ‘ไปฌไฟฎๆ”นไบ† `GzipRequest.body`๏ผŒๅœจ **FastAPI** ้œ€่ฆ่ฏปๅ–ๆ—ถ๏ผŒ่ฏทๆฑ‚ไฝ“ไผš่ขซ่‡ชๅŠจ่งฃๅŽ‹ใ€‚ + +## ๅœจๅผ‚ๅธธๅค„็†ๅ™จไธญ่ฎฟ้—ฎ่ฏทๆฑ‚ไฝ“ { #accessing-the-request-body-in-an-exception-handler } + +/// tip | ๆ็คบ + +่ฆ่งฃๅ†ณ็ฑปไผผ้—ฎ้ข˜๏ผŒไฝฟ็”จ `RequestValidationError` ็š„่‡ชๅฎšไน‰ๅค„็†ๅ™จไธญ็š„ `body` ๅพ€ๅพ€ๆ›ด็ฎ€ๅ•๏ผˆ[ๅค„็†้”™่ฏฏ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}๏ผ‰ใ€‚ + +ไฝ†ๆœฌ็คบไพ‹ๅŒๆ ทๆœ‰ๆ•ˆ๏ผŒๅนถๅฑ•็คบไบ†ๅฆ‚ไฝ•ไธŽๅ†…้ƒจ็ป„ไปถไบคไบ’ใ€‚ + +/// + +ๆˆ‘ไปฌไนŸๅฏไปฅ็”จ็›ธๅŒ็š„ๆ–นๆณ•ๅœจๅผ‚ๅธธๅค„็†ๅ™จไธญ่ฎฟ้—ฎ่ฏทๆฑ‚ไฝ“ใ€‚ + +ๆ‰€้œ€ไป…ๆ˜ฏๅœจ `try`/`except` ๅ—ไธญๅค„็†่ฏทๆฑ‚๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +ๅฆ‚ๆžœๅ‘็”Ÿๅผ‚ๅธธ๏ผŒ`Request` ๅฎžไพ‹ไปๅœจไฝœ็”จๅŸŸๅ†…๏ผŒๅ› ๆญคๆˆ‘ไปฌๅฏไปฅๅœจๅค„็†้”™่ฏฏๆ—ถ่ฏปๅ–ๅนถไฝฟ็”จ่ฏทๆฑ‚ไฝ“๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## ๅœจ่ทฏ็”ฑๅ™จไธญ่‡ชๅฎšไน‰ `APIRoute` ็ฑป { #custom-apiroute-class-in-a-router } + +ไฝ ไนŸๅฏไปฅ่ฎพ็ฝฎ `APIRouter` ็š„ `route_class` ๅ‚ๆ•ฐ๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +ๅœจๆญค็คบไพ‹ไธญ๏ผŒ`router` ไธ‹็š„่ทฏๅพ„ๆ“ไฝœๅฐ†ไฝฟ็”จ่‡ชๅฎšไน‰็š„ `TimedRoute` ็ฑป๏ผŒๅ“ๅบ”ไธญไผšๅคšไธ€ไธช `X-Response-Time` ๅคด๏ผŒๅŒ…ๅซ็”Ÿๆˆๅ“ๅบ”ๆ‰€็”จ็š„ๆ—ถ้—ด๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh/docs/how-to/extending-openapi.md b/docs/zh/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..ad8a1d6981 --- /dev/null +++ b/docs/zh/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# ๆ‰ฉๅฑ• OpenAPI { #extending-openapi } + +ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆไฟฎๆ”น็”Ÿๆˆ็š„ OpenAPI ๆžถๆž„๏ผˆschema๏ผ‰ใ€‚ + +ๆœฌ่Š‚ๅฐ†ไป‹็ปๅฆ‚ไฝ•ๅฎž็Žฐใ€‚ + +## ๅธธ่ง„ๆต็จ‹ { #the-normal-process } + +ๅธธ่ง„๏ผˆ้ป˜่ฎค๏ผ‰ๆต็จ‹ๅฆ‚ไธ‹ใ€‚ + +`FastAPI` ๅบ”็”จ๏ผˆๅฎžไพ‹๏ผ‰ๆœ‰ไธ€ไธช `.openapi()` ๆ–นๆณ•๏ผŒ้ข„ๆœŸ่ฟ”ๅ›ž OpenAPI ๆžถๆž„ใ€‚ + +ๅœจๅˆ›ๅปบๅบ”็”จๅฏน่ฑกๆ—ถ๏ผŒไผšๆณจๅ†Œไธ€ไธช็”จไบŽ `/openapi.json`๏ผˆๆˆ–ไฝ ๅœจ `openapi_url` ไธญ่ฎพ็ฝฎ็š„่ทฏๅพ„๏ผ‰็š„่ทฏๅพ„ๆ“ไฝœใ€‚ + +ๅฎƒๅชไผš่ฟ”ๅ›žไธ€ไธช JSON ๅ“ๅบ”๏ผŒๅ†…ๅฎนๆ˜ฏๅบ”็”จ `.openapi()` ๆ–นๆณ•็š„็ป“ๆžœใ€‚ + +้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ`.openapi()` ๆ–นๆณ•ไผšๆฃ€ๆŸฅๅฑžๆ€ง `.openapi_schema` ๆ˜ฏๅฆๅทฒๆœ‰ๅ†…ๅฎน๏ผŒ่‹ฅๆœ‰ๅˆ™็›ดๆŽฅ่ฟ”ๅ›žใ€‚ + +ๅฆ‚ๆžœๆฒกๆœ‰๏ผŒๅˆ™ไฝฟ็”จ `fastapi.openapi.utils.get_openapi` ๅทฅๅ…ทๅ‡ฝๆ•ฐ็”Ÿๆˆใ€‚ + +่ฏฅ `get_openapi()` ๅ‡ฝๆ•ฐๆŽฅๆ”ถไปฅไธ‹ๅ‚ๆ•ฐ๏ผš + +- `title`๏ผšOpenAPI ๆ ‡้ข˜๏ผŒๆ˜พ็คบๅœจๆ–‡ๆกฃไธญใ€‚ +- `version`๏ผšไฝ ็š„ API ็‰ˆๆœฌ๏ผŒไพ‹ๅฆ‚ `2.5.0`ใ€‚ +- `openapi_version`๏ผšไฝฟ็”จ็š„ OpenAPI ่ง„่Œƒ็‰ˆๆœฌใ€‚้ป˜่ฎคๆ˜ฏๆœ€ๆ–ฐ็š„ `3.1.0`ใ€‚ +- `summary`๏ผšAPI ็š„็ฎ€็Ÿญๆ‘˜่ฆใ€‚ +- `description`๏ผšAPI ็š„ๆ่ฟฐ๏ผŒๅฏๅŒ…ๅซ Markdown๏ผŒๅนถไผšๅฑ•็คบๅœจๆ–‡ๆกฃไธญใ€‚ +- `routes`๏ผš่ทฏ็”ฑๅˆ—่กจ๏ผŒๅณๅทฒๆณจๅ†Œ็š„ๆฏไธช่ทฏๅพ„ๆ“ไฝœใ€‚ๆฅ่‡ช `app.routes`ใ€‚ + +/// info | ไฟกๆฏ + +ๅ‚ๆ•ฐ `summary` ไป…ๅœจ OpenAPI 3.1.0 ๅŠๆ›ด้ซ˜็‰ˆๆœฌไธญๅฏ็”จ๏ผŒFastAPI 0.99.0 ๅŠไปฅไธŠ็‰ˆๆœฌๆ”ฏๆŒใ€‚ + +/// + +## ่ฆ†็›–้ป˜่ฎคๅ€ผ { #overriding-the-defaults } + +ๅŸบไบŽไปฅไธŠไฟกๆฏ๏ผŒไฝ ๅฏไปฅ็”จๅŒไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐ็”Ÿๆˆ OpenAPI ๆžถๆž„๏ผŒๅนถๆŒ‰้œ€่ฆ†็›–ๅ…ถไธญ็š„ๅ„ไธช้ƒจๅˆ†ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฎฉๆˆ‘ไปฌๆทปๅŠ  ReDoc ็š„ OpenAPI ๆ‰ฉๅฑ•ไปฅๅŒ…ๅซ่‡ชๅฎšไน‰ Logoใ€‚ + +### ๅธธ่ง„ **FastAPI** { #normal-fastapi } + +้ฆ–ๅ…ˆ๏ผŒๅƒๅนณๅธธไธ€ๆ ท็ผ–ๅ†™ไฝ ็š„ **FastAPI** ๅบ”็”จ๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### ็”Ÿๆˆ OpenAPI ๆžถๆž„ { #generate-the-openapi-schema } + +็„ถๅŽ๏ผŒๅœจไธ€ไธช `custom_openapi()` ๅ‡ฝๆ•ฐไธญไฝฟ็”จๅŒไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐ็”Ÿๆˆ OpenAPI ๆžถๆž„๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### ไฟฎๆ”น OpenAPI ๆžถๆž„ { #modify-the-openapi-schema } + +็Žฐๅœจไฝ ๅฏไปฅๆทปๅŠ  ReDoc ๆ‰ฉๅฑ•๏ผŒๅœจ OpenAPI ๆžถๆž„็š„ `info` โ€œๅฏน่ฑกโ€ไธญๅŠ ๅ…ฅ่‡ชๅฎšไน‰ `x-logo`๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### ็ผ“ๅญ˜ OpenAPI ๆžถๆž„ { #cache-the-openapi-schema } + +ไฝ ๅฏไปฅๆŠŠ `.openapi_schema` ๅฑžๆ€งๅฝ“ไฝœโ€œ็ผ“ๅญ˜โ€๏ผŒ็”จๆฅๅญ˜ๅ‚จๅทฒ็”Ÿๆˆ็š„ๆžถๆž„ใ€‚ + +่ฟ™ๆ ทไธ€ๆฅ๏ผŒ็”จๆˆทๆฏๆฌกๆ‰“ๅผ€ API ๆ–‡ๆกฃๆ—ถ๏ผŒๅบ”็”จๅฐฑไธๅฟ…้‡ๆ–ฐ็”Ÿๆˆๆžถๆž„ใ€‚ + +ๅฎƒๅชไผš็”Ÿๆˆไธ€ๆฌก๏ผŒๅŽ็ปญ่ฏทๆฑ‚้ƒฝไผšไฝฟ็”จๅŒไธ€ไปฝ็ผ“ๅญ˜็š„ๆžถๆž„ใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### ่ฆ†็›–ๆ–นๆณ• { #override-the-method } + +็Žฐๅœจไฝ ๅฏไปฅ็”จไฝ ็š„ๆ–ฐๅ‡ฝๆ•ฐๆ›ฟๆข `.openapi()` ๆ–นๆณ•ใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### ้ชŒ่ฏ { #check-it } + +ๅฝ“ไฝ ่ฎฟ้—ฎ http://127.0.0.1:8000/redoc ๆ—ถ๏ผŒไฝ ไผš็œ‹ๅˆฐๅทฒไฝฟ็”จไฝ ็š„่‡ชๅฎšไน‰ Logo๏ผˆๆœฌไพ‹ไธญไธบ **FastAPI** ็š„ Logo๏ผ‰๏ผš + + diff --git a/docs/zh/docs/how-to/general.md b/docs/zh/docs/how-to/general.md index e75ad6c79d..2c9f781791 100644 --- a/docs/zh/docs/how-to/general.md +++ b/docs/zh/docs/how-to/general.md @@ -36,4 +36,4 @@ ## OpenAPI ๆ–‡ๆกฃ URL { #openapi-docs-urls } -่ฆๆ›ดๆ”น็”จไบŽ่‡ชๅŠจ็”Ÿๆˆๆ–‡ๆกฃ็š„ URL๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}ใ€‚ +่ฆๆ›ดๆ”น่‡ชๅŠจ็”Ÿๆˆ็š„ๆ–‡ๆกฃ็”จๆˆท็•Œ้ขๆ‰€ไฝฟ็”จ็š„ URL๏ผŒ่ฏท้˜…่ฏป [ๆ•™็จ‹ - ๅ…ƒๆ•ฐๆฎๅ’Œๆ–‡ๆกฃ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh/docs/how-to/graphql.md b/docs/zh/docs/how-to/graphql.md new file mode 100644 index 0000000000..5384f15137 --- /dev/null +++ b/docs/zh/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +็”ฑไบŽ **FastAPI** ๅŸบไบŽ **ASGI** ๆ ‡ๅ‡†๏ผŒๅ› ๆญคๅพˆๅฎนๆ˜“้›†ๆˆไปปไฝ•ไนŸๅ…ผๅฎน ASGI ็š„ **GraphQL** ๅบ“ใ€‚ + +ไฝ ๅฏไปฅๅœจๅŒไธ€ไธชๅบ”็”จไธญๅฐ†ๅธธ่ง„็š„ FastAPI ่ทฏๅพ„ๆ“ไฝœไธŽ GraphQL ็ป“ๅˆไฝฟ็”จใ€‚ + +/// tip | ๆ็คบ + +**GraphQL** ่งฃๅ†ณไธ€ไบ›้žๅธธ็‰นๅฎš็š„็”จไพ‹ใ€‚ + +ไธŽๅธธ่ง็š„ **Web API** ็›ธๆฏ”๏ผŒๅฎƒๆœ‰ๅ„่‡ช็š„**ไผ˜็‚น**ๅ’Œ**็ผบ็‚น**ใ€‚ + +่ฏท็กฎไฟ่ฏ„ไผฐๅœจไฝ ็š„็”จไพ‹ไธญ๏ผŒ่ฟ™ไบ›**ๅฅฝๅค„**ๆ˜ฏๅฆ่ถณไปฅๅผฅ่กฅ่ฟ™ไบ›**็ผบ็‚น**ใ€‚ ๐Ÿค“ + +/// + +## GraphQL ๅบ“ { #graphql-libraries } + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๆ”ฏๆŒ **ASGI** ็š„ **GraphQL** ๅบ“ใ€‚ไฝ ๅฏไปฅๅฐ†ๅฎƒไปฌไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จ๏ผš + +* Strawberry ๐Ÿ“ + * ๆไพ› ้ขๅ‘ FastAPI ็š„ๆ–‡ๆกฃ +* Ariadne + * ๆไพ› ้ขๅ‘ FastAPI ็š„ๆ–‡ๆกฃ +* Tartiflette + * ๆไพ›็”จไบŽ ASGI ้›†ๆˆ็š„ Tartiflette ASGI +* Graphene + * ๅฏ้…ๅˆ starlette-graphene3 ไฝฟ็”จ + +## ไฝฟ็”จ Strawberry ็š„ GraphQL { #graphql-with-strawberry } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๆˆ–ๆƒณ่ฆไฝฟ็”จ **GraphQL**๏ผŒ**Strawberry** ๆ˜ฏ**ๆŽจ่**็š„ๅบ“๏ผŒๅ› ไธบๅฎƒ็š„่ฎพ่ฎกไธŽ **FastAPI** ๆœ€ไธบๆŽฅ่ฟ‘๏ผŒๅ…จ้ƒจๅŸบไบŽ**็ฑปๅž‹ๆณจ่งฃ**ใ€‚ + +ๆ นๆฎไฝ ็š„็”จไพ‹๏ผŒไฝ ๅฏ่ƒฝไผšๆ›ดๅ–œๆฌขๅ…ถไป–ๅบ“๏ผŒไฝ†ๅฆ‚ๆžœไฝ ้—ฎๆˆ‘๏ผŒๆˆ‘ๅคงๆฆ‚็އไผšๅปบ่ฎฎไฝ ๅ…ˆ่ฏ•่ฏ• **Strawberry**ใ€‚ + +ไธ‹้ขๆ˜ฏไธ€ไธชๅฐ† Strawberry ไธŽ FastAPI ้›†ๆˆ็š„ๅฐ้ข„่งˆ๏ผš + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +ไฝ ๅฏไปฅๅœจ Strawberry ๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšไฟกๆฏใ€‚ + +่ฟ˜ๆœ‰ๅ…ณไบŽ ๅฐ† Strawberry ไธŽ FastAPI ็ป“ๅˆไฝฟ็”จ็š„ๆ–‡ๆกฃใ€‚ + +## Starlette ไธญ่พƒๆ—ฉ็š„ `GraphQLApp` { #older-graphqlapp-from-starlette } + +ๆ—ฉๆœŸ็‰ˆๆœฌ็š„ Starlette ๅŒ…ๅซไธ€ไธช `GraphQLApp` ็ฑป๏ผŒ็”จไบŽไธŽ Graphene ้›†ๆˆใ€‚ + +ๅฎƒๅทฒๅœจ Starlette ไธญ่ขซๅผƒ็”จ๏ผŒไฝ†ๅฆ‚ๆžœไฝ ็š„ไปฃ็ ไฝฟ็”จไบ†ๅฎƒ๏ผŒไฝ ๅฏไปฅ่ฝปๆพ**่ฟ็งป**ๅˆฐ starlette-graphene3๏ผŒๅฎƒ่ฆ†็›–็›ธๅŒ็š„็”จไพ‹๏ผŒไธ”ๆŽฅๅฃ**ๅ‡ ไนŽๅฎŒๅ…จไธ€่‡ด**ใ€‚ + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ้œ€่ฆ GraphQL๏ผŒๆˆ‘ไป็„ถๅปบ่ฎฎ็œ‹็œ‹ Strawberry๏ผŒๅ› ไธบๅฎƒๅŸบไบŽ็ฑปๅž‹ๆณจ่งฃ่€Œไธๆ˜ฏ่‡ชๅฎšไน‰็ฑปๅ’Œ็ฑปๅž‹ใ€‚ + +/// + +## ไบ†่งฃๆ›ดๅคš { #learn-more } + +ไฝ ๅฏไปฅๅœจ GraphQL ๅฎ˜ๆ–นๆ–‡ๆกฃไธญไบ†่งฃๆ›ดๅคšๅ…ณไบŽ **GraphQL** ็š„ๅ†…ๅฎนใ€‚ + +ไฝ ไนŸๅฏไปฅ้€š่ฟ‡ไธŠ้ข็š„้“พๆŽฅ้˜…่ฏปๅ„ไธชๅบ“็š„ๆ›ดๅคšไฟกๆฏใ€‚ diff --git a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..2e5445200a --- /dev/null +++ b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# ไปŽ Pydantic v1 ่ฟ็งปๅˆฐ Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธช่พƒๆ—ง็š„ FastAPI ๅบ”็”จ๏ผŒๅฏ่ƒฝๅœจไฝฟ็”จ Pydantic v1ใ€‚ + +FastAPI 0.100.0 ๅŒๆ—ถๆ”ฏๆŒ Pydantic v1 ๅ’Œ v2๏ผŒไผšไฝฟ็”จไฝ ๅทฒๅฎ‰่ฃ…็š„ไปปไธ€็‰ˆๆœฌใ€‚ + +FastAPI 0.119.0 ๅผ•ๅ…ฅไบ†ๅœจ Pydantic v2 ๅ†…้ƒจไปฅ `pydantic.v1` ๅฝขๅผๅฏน Pydantic v1 ็š„้ƒจๅˆ†ๆ”ฏๆŒ๏ผŒไปฅไพฟไบŽ่ฟ็งปๅˆฐ v2ใ€‚ + +FastAPI 0.126.0 ็งป้™คไบ†ๅฏน Pydantic v1 ็š„ๆ”ฏๆŒ๏ผŒไฝ†ๅœจไธ€ๆฎตๆ—ถ้—ดๅ†…ไปๆ”ฏๆŒ `pydantic.v1`ใ€‚ + +/// warning | ่ญฆๅ‘Š + +ไปŽ Python 3.14 ๅผ€ๅง‹๏ผŒPydantic ๅ›ข้˜Ÿไธๅ†ไธบๆœ€ๆ–ฐ็š„ Python ็‰ˆๆœฌๆไพ› Pydantic v1 ็š„ๆ”ฏๆŒใ€‚ + +่ฟ™ไนŸๅŒ…ๆ‹ฌ `pydantic.v1`๏ผŒๅœจ Python 3.14 ๅŠๆ›ด้ซ˜็‰ˆๆœฌไธญไธๅ†ๅ—ๆ”ฏๆŒใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณไฝฟ็”จ Python ็š„ๆœ€ๆ–ฐ็‰นๆ€ง๏ผŒ้œ€่ฆ็กฎไฟไฝฟ็”จ Pydantic v2ใ€‚ + +/// + +ๅฆ‚ๆžœไฝ ็š„ๆ—ง FastAPI ๅบ”็”จๅœจ็”จ Pydantic v1๏ผŒ่ฟ™้‡Œๅฐ†ๅ‘ไฝ ๅฑ•็คบๅฆ‚ไฝ•่ฟ็งปๅˆฐ Pydantic v2๏ผŒไปฅๅŠ FastAPI 0.119.0 ไธญๅฏๅธฎๅŠฉไฝ ๆธ่ฟ›ๅผ่ฟ็งป็š„ๅŠŸ่ƒฝใ€‚ + +## ๅฎ˜ๆ–นๆŒ‡ๅ— { #official-guide } + +Pydantic ๆœ‰ไธ€ไปฝไปŽ v1 ่ฟ็งปๅˆฐ v2 ็š„ๅฎ˜ๆ–น ่ฟ็งปๆŒ‡ๅ—ใ€‚ + +ๅ…ถไธญๅŒ…ๅซๅ˜ๆ›ดๅ†…ๅฎนใ€ๆ ก้ชŒๅฆ‚ไฝ•ๆ›ดๅ‡†็กฎๆ›ดไธฅๆ ผใ€ๅฏ่ƒฝ็š„ๆณจๆ„ไบ‹้กน็ญ‰ใ€‚ + +ไฝ ๅฏไปฅ้˜…่ฏปไปฅๆ›ดๅฅฝๅœฐไบ†่งฃๅ˜ๆ›ดใ€‚ + +## ๆต‹่ฏ• { #tests } + +่ฏท็กฎไฟไฝ ็š„ๅบ”็”จๆœ‰[ๆต‹่ฏ•](../tutorial/testing.md){.internal-link target=_blank}๏ผŒๅนถๅœจๆŒ็ปญ้›†ๆˆ๏ผˆCI๏ผ‰ไธญ่ฟ่กŒๅฎƒไปฌใ€‚ + +่ฟ™ๆ ทไฝ ๅฐฑๅฏไปฅๅ‡็บงๅนถ็กฎไฟไธ€ๅˆ‡ไปๆŒ‰้ข„ๆœŸๅทฅไฝœใ€‚ + +## `bump-pydantic` { #bump-pydantic } + +ๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏๆœชๅš่‡ชๅฎšไน‰็š„ๅธธ่ง„ Pydantic ๆจกๅž‹๏ผŒๅฏไปฅๅฐ†ไปŽ Pydantic v1 ่ฟ็งปๅˆฐ v2 ็š„ๅคง้ƒจๅˆ†่ฟ‡็จ‹่‡ชๅŠจๅŒ–ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จๅŒไธ€ Pydantic ๅ›ข้˜Ÿๆไพ›็š„ `bump-pydantic`ใ€‚ + +่ฏฅๅทฅๅ…ทไผšๅธฎๅŠฉไฝ ่‡ชๅŠจไฟฎๆ”นๅคง้ƒจๅˆ†้œ€่ฆๅ˜ๆ›ด็š„ไปฃ็ ใ€‚ + +ไน‹ๅŽ่ฟ่กŒๆต‹่ฏ•ๆฃ€ๆŸฅๆ˜ฏๅฆไธ€ๅˆ‡ๆญฃๅธธใ€‚ๅฆ‚ๆžœๆญฃๅธธ๏ผŒไฝ ๅฐฑๅฎŒๆˆไบ†ใ€‚๐Ÿ˜Ž + +## v2 ไธญ็š„ Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2 ไปฅๅญๆจกๅ— `pydantic.v1` ็š„ๅฝขๅผๅŒ…ๅซไบ† Pydantic v1 ็š„ๅ…จ้ƒจๅ†…ๅฎนใ€‚ไฝ†ๅœจ Python 3.13 ไปฅไธŠ็š„็‰ˆๆœฌไธญไธๅ†ๅ—ๆ”ฏๆŒใ€‚ + +่ฟ™ๆ„ๅ‘ณ็€ไฝ ๅฏไปฅๅฎ‰่ฃ…ๆœ€ๆ–ฐ็š„ Pydantic v2๏ผŒๅนถไปŽ่ฏฅๅญๆจกๅ—ๅฏผๅ…ฅๅนถไฝฟ็”จๆ—ง็š„ Pydantic v1 ็ป„ไปถ๏ผŒๅฐฑๅƒๅฎ‰่ฃ…ไบ†ๆ—ง็‰ˆ Pydantic v1 ไธ€ๆ ทใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### FastAPI ๅฏน v2 ไธญ Pydantic v1 ็š„ๆ”ฏๆŒ { #fastapi-support-for-pydantic-v1-in-v2 } + +่‡ช FastAPI 0.119.0 ่ตท๏ผŒFastAPI ไนŸๅฏน Pydantic v2 ๅ†…็š„ Pydantic v1 ๆไพ›ไบ†้ƒจๅˆ†ๆ”ฏๆŒ๏ผŒไปฅไพฟ่ฟ็งปๅˆฐ v2ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅฐ† Pydantic ๅ‡็บงๅˆฐๆœ€ๆ–ฐ็š„ v2๏ผŒๅนถๅฐ†ๅฏผๅ…ฅๆ”นไธบไฝฟ็”จ `pydantic.v1` ๅญๆจกๅ—๏ผŒๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹ๅฐฑ่ƒฝ็›ดๆŽฅๅทฅไฝœใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | ่ญฆๅ‘Š + +่ฏทๆณจๆ„๏ผŒ็”ฑไบŽ Pydantic ๅ›ข้˜Ÿ่‡ช Python 3.14 ่ตทไธๅ†ๅœจ่พƒๆ–ฐ็š„ Python ็‰ˆๆœฌไธญๆ”ฏๆŒ Pydantic v1๏ผŒไฝฟ็”จ `pydantic.v1` ๅœจ Python 3.14 ๅŠๆ›ด้ซ˜็‰ˆๆœฌไธญไนŸไธๅ—ๆ”ฏๆŒใ€‚ + +/// + +### ๅŒไธ€ๅบ”็”จไธญๅŒๆ—ถไฝฟ็”จ Pydantic v1 ไธŽ v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic ไธๆ”ฏๆŒๅœจไธ€ไธช Pydantic v2 ๆจกๅž‹็š„ๅญ—ๆฎตไธญๅฎšไน‰ Pydantic v1 ๆจกๅž‹๏ผŒๅไน‹ไบฆ็„ถใ€‚ + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...ไฝ†ๆ˜ฏ๏ผŒไฝ ๅฏไปฅๅœจๅŒไธ€ไธชๅบ”็”จไธญๅˆ†ๅˆซไฝฟ็”จ Pydantic v1 ๅ’Œ v2 ็š„็‹ฌ็ซ‹ๆจกๅž‹ใ€‚ + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +ๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒ็”š่‡ณๅฏไปฅๅœจ FastAPI ๅบ”็”จ็š„ๅŒไธ€ไธช่ทฏๅพ„ๆ“ไฝœไธญๅŒๆ—ถไฝฟ็”จ Pydantic v1 ๅ’Œ v2 ๆจกๅž‹๏ผš + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ๅœจไธŠ้ข็š„็คบไพ‹ไธญ๏ผŒ่พ“ๅ…ฅๆจกๅž‹ๆ˜ฏ Pydantic v1 ๆจกๅž‹๏ผŒ่พ“ๅ‡บๆจกๅž‹๏ผˆๅœจ `response_model=ItemV2` ไธญๅฎšไน‰๏ผ‰ๆ˜ฏ Pydantic v2 ๆจกๅž‹ใ€‚ + +### Pydantic v1 ๅ‚ๆ•ฐ { #pydantic-v1-parameters } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅœจ Pydantic v1 ๆจกๅž‹ไธญไฝฟ็”จ FastAPI ็‰นๆœ‰็š„ๅ‚ๆ•ฐๅทฅๅ…ท๏ผŒๅฆ‚ `Body`ใ€`Query`ใ€`Form` ็ญ‰๏ผŒๅœจๅฎŒๆˆๅ‘ Pydantic v2 ็š„่ฟ็งปๅ‰๏ผŒๅฏไปฅไปŽ `fastapi.temp_pydantic_v1_params` ๅฏผๅ…ฅๅฎƒไปฌ๏ผš + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### ๅˆ†ๆญฅ่ฟ็งป { #migrate-in-steps } + +/// tip | ๆ็คบ + +ไผ˜ๅ…ˆๅฐ่ฏ• `bump-pydantic`๏ผŒๅฆ‚ๆžœๆต‹่ฏ•้€š่ฟ‡ไธ”ๅฏ่กŒ๏ผŒ้‚ฃไนˆไฝ ๅฐฑ็”จไธ€ไธชๅ‘ฝไปคๅฎŒๆˆไบ†ใ€‚โœจ + +/// + +ๅฆ‚ๆžœ `bump-pydantic` ไธ้€‚็”จไบŽไฝ ็š„ๅœบๆ™ฏ๏ผŒไฝ ๅฏไปฅๅœจๅŒไธ€ๅบ”็”จไธญๅŒๆ—ถๆ”ฏๆŒ Pydantic v1 ๅ’Œ v2 ๆจกๅž‹๏ผŒ้€ๆญฅ่ฟ็งปๅˆฐ Pydantic v2ใ€‚ + +ไฝ ๅฏไปฅ้ฆ–ๅ…ˆๅฐ† Pydantic ๅ‡็บงๅˆฐๆœ€ๆ–ฐ็š„ v2๏ผŒๅนถๅฐ†ๆ‰€ๆœ‰ๆจกๅž‹็š„ๅฏผๅ…ฅๆ”นไธบไฝฟ็”จ `pydantic.v1`ใ€‚ + +็„ถๅŽๆŒ‰ๆจกๅ—ๆˆ–ๅˆ†็ป„๏ผŒ้€ๆญฅๆŠŠๆจกๅž‹ไปŽ Pydantic v1 ่ฟ็งปๅˆฐ v2ใ€‚๐Ÿšถ diff --git a/docs/zh/docs/how-to/separate-openapi-schemas.md b/docs/zh/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..c3efe5f1a4 --- /dev/null +++ b/docs/zh/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# ๆ˜ฏๅฆไธบ่พ“ๅ…ฅๅ’Œ่พ“ๅ‡บๅˆ†ๅˆซ็”Ÿๆˆ OpenAPI JSON Schema { #separate-openapi-schemas-for-input-and-output-or-not } + +่‡ชไปŽๅ‘ๅธƒไบ† **Pydantic v2**๏ผŒ็”Ÿๆˆ็š„ OpenAPI ๆฏ”ไน‹ๅ‰ๆ›ด็ฒพ็กฎใ€ๆ›ด**ๆญฃ็กฎ**ไบ†ใ€‚๐Ÿ˜Ž + +ไบ‹ๅฎžไธŠ๏ผŒๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒๅฏนไบŽๅŒไธ€ไธช Pydantic ๆจกๅž‹๏ผŒOpenAPI ไธญไผšๆ นๆฎๆ˜ฏๅฆๅธฆๆœ‰**้ป˜่ฎคๅ€ผ**๏ผŒไธบ่พ“ๅ…ฅๅ’Œ่พ“ๅ‡บๅˆ†ๅˆซ็”Ÿๆˆ**ไธคไธช JSON Schema**ใ€‚ + +ๆˆ‘ไปฌๆฅ็œ‹็œ‹ๅฎƒๅฆ‚ไฝ•ๅทฅไฝœ๏ผŒไปฅๅŠๅœจ้œ€่ฆๆ—ถๅฆ‚ไฝ•ไฟฎๆ”นใ€‚ + +## ็”จไบŽ่พ“ๅ…ฅๅ’Œ่พ“ๅ‡บ็š„ Pydantic ๆจกๅž‹ { #pydantic-models-for-input-and-output } + +ๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๅธฆๆœ‰้ป˜่ฎคๅ€ผ็š„ Pydantic ๆจกๅž‹๏ผŒไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### ่พ“ๅ…ฅ็”จ็š„ๆจกๅž‹ { #model-for-input } + +ๅฆ‚ๆžœไฝ ๅƒไธ‹้ข่ฟ™ๆ ทๆŠŠ่ฏฅๆจกๅž‹็”จไฝœ่พ“ๅ…ฅ๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...้‚ฃไนˆ `description` ๅญ—ๆฎตๅฐ†**ไธๆ˜ฏๅฟ…ๅกซ้กน**๏ผŒๅ› ไธบๅฎƒ็š„้ป˜่ฎคๅ€ผๆ˜ฏ `None`ใ€‚ + +### ๆ–‡ๆกฃไธญ็š„่พ“ๅ…ฅๆจกๅž‹ { #input-model-in-docs } + +ไฝ ๅฏไปฅๅœจๆ–‡ๆกฃไธญ็กฎ่ฎค๏ผŒ`description` ๅญ—ๆฎตๆฒกๆœ‰**็บข่‰ฒๆ˜Ÿๅท**๏ผŒไนŸๅฐฑๆ˜ฏๆœช่ขซๆ ‡่ฎฐไธบๅฟ…ๅกซ๏ผš + +
+ +
+ +### ่พ“ๅ‡บ็”จ็š„ๆจกๅž‹ { #model-for-output } + +ไฝ†ๅฆ‚ๆžœไฝ ๆŠŠๅŒไธ€ไธชๆจกๅž‹็”จไฝœ่พ“ๅ‡บ๏ผŒไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...้‚ฃไนˆๅ› ไธบ `description` ๆœ‰้ป˜่ฎคๅ€ผ๏ผŒๅณไฝฟไฝ **ไธ่ฟ”ๅ›ž่ฏฅๅญ—ๆฎต**๏ผŒๅฎƒไป็„ถไผšๆœ‰่ฟ™ไธช**้ป˜่ฎคๅ€ผ**ใ€‚ + +### ่พ“ๅ‡บๅ“ๅบ”ๆ•ฐๆฎ็š„ๆจกๅž‹ { #model-for-output-response-data } + +ๅฆ‚ๆžœไฝ ๅœจๆ–‡ๆกฃไธญไบคไบ’ๅนถๆŸฅ็œ‹ๅ“ๅบ”๏ผŒๅณไฝฟไปฃ็ ๆฒกๆœ‰็ป™ๆŸไธช `description` ๅญ—ๆฎต่ต‹ๅ€ผ๏ผŒJSON ๅ“ๅบ”ไธญไปๅŒ…ๅซ้ป˜่ฎคๅ€ผ๏ผˆ`null`๏ผ‰๏ผš + +
+ +
+ +่ฟ™ๆ„ๅ‘ณ็€ๅฎƒ**ๆ€ปไผšๆœ‰ๅ€ผ**๏ผŒๅชๆ˜ฏๆœ‰ๆ—ถ่ฏฅๅ€ผๅฏ่ƒฝไธบ `None`๏ผˆๅœจ JSON ไธญๆ˜ฏ `null`๏ผ‰ใ€‚ + +่ฟ™ไนŸๆ„ๅ‘ณ็€๏ผŒไฝฟ็”จไฝ ็š„ API ็š„ๅฎขๆˆท็ซฏๆ— ้œ€ๆฃ€ๆŸฅ่ฏฅๅ€ผๆ˜ฏๅฆๅญ˜ๅœจ๏ผŒไป–ไปฌๅฏไปฅ**ๅ‡่ฎพ่ฏฅๅญ—ๆฎตๆ€ปไผšๅญ˜ๅœจ**๏ผŒๅชๆ˜ฏๆœ‰ๆ—ถๅฎƒไผšๆ˜ฏ้ป˜่ฎคๅ€ผ `None`ใ€‚ + +ๅœจ OpenAPI ไธญๆ่ฟฐ่ฟ™ไธ€็‚น็š„ๆ–นๅผ๏ผŒๆ˜ฏๆŠŠ่ฏฅๅญ—ๆฎตๆ ‡่ฎฐไธบ**ๅฟ…ๅกซ**๏ผŒๅ› ไธบๅฎƒๆ€ปไผšๅญ˜ๅœจใ€‚ + +ๅ› ๆญค๏ผŒไธ€ไธชๆจกๅž‹็š„ JSON Schema ไผšๆ นๆฎๅฎƒ็”จไบŽ**่พ“ๅ…ฅ่ฟ˜ๆ˜ฏ่พ“ๅ‡บ**่€Œๆœ‰ๆ‰€ไธๅŒ๏ผš + +- ็”จไบŽ**่พ“ๅ…ฅ**ๆ—ถ๏ผŒ`description` **ไธๆ˜ฏๅฟ…ๅกซ** +- ็”จไบŽ**่พ“ๅ‡บ**ๆ—ถ๏ผŒๅฎƒๆ˜ฏ**ๅฟ…ๅกซ**๏ผˆๅนถไธ”ๅฏ่ƒฝไธบ `None`๏ผŒๅœจ JSON ไธญไธบ `null`๏ผ‰ + +### ๆ–‡ๆกฃไธญ็š„่พ“ๅ‡บๆจกๅž‹ { #model-for-output-in-docs } + +ไฝ ไนŸๅฏไปฅๅœจๆ–‡ๆกฃไธญๆŸฅ็œ‹่พ“ๅ‡บๆจกๅž‹๏ผŒ`name` ๅ’Œ `description` **้ƒฝ**่ขซ**็บข่‰ฒๆ˜Ÿๅท**ๆ ‡่ฎฐไธบ**ๅฟ…ๅกซ**๏ผš + +
+ +
+ +### ๆ–‡ๆกฃไธญ็š„่พ“ๅ…ฅ/่พ“ๅ‡บๆจกๅž‹ { #model-for-input-and-output-in-docs } + +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ OpenAPI ไธญๅฏ็”จ็š„ๆ‰€ๆœ‰ Schema๏ผˆJSON Schema๏ผ‰๏ผŒไฝ ไผš็œ‹ๅˆฐๆœ‰ไธคไธช๏ผŒไธ€ไธชๆ˜ฏ `Item-Input`๏ผŒไธ€ไธชๆ˜ฏ `Item-Output`ใ€‚ + +ๅฏนไบŽ `Item-Input`๏ผŒ`description` **ไธๆ˜ฏๅฟ…ๅกซ**๏ผŒๆฒกๆœ‰็บข่‰ฒๆ˜Ÿๅทใ€‚ + +ไฝ†ๅฏนไบŽ `Item-Output`๏ผŒ`description` ๆ˜ฏ**ๅฟ…ๅกซ**๏ผŒๅธฆๆœ‰็บข่‰ฒๆ˜Ÿๅทใ€‚ + +
+ +
+ +ๅ€ŸๅŠฉ **Pydantic v2** ็š„่ฟ™ไธช็‰นๆ€ง๏ผŒไฝ ็š„ API ๆ–‡ๆกฃไผšๆ›ด**็ฒพ็กฎ**๏ผŒๅฆ‚ๆžœไฝ ๆœ‰่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏๅ’Œ SDK๏ผŒๅฎƒไปฌไนŸไผšๆ›ด็ฒพ็กฎ๏ผŒๅธฆๆฅๆ›ดๅฅฝ็š„**ๅผ€ๅ‘่€…ไฝ“้ชŒ**ๅ’Œไธ€่‡ดๆ€งใ€‚๐ŸŽ‰ + +## ไธ่ฆๅˆ†็ฆป Schema { #do-not-separate-schemas } + +ๅฝ“็„ถ๏ผŒๅœจๆŸไบ›ๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›**่พ“ๅ…ฅๅ’Œ่พ“ๅ‡บไฝฟ็”จๅŒไธ€ไธช schema**ใ€‚ + +ๆœ€ๅธธ่ง็š„ๆƒ…ๅฝขๆ˜ฏ๏ผšไฝ ๅทฒ็ปๆœ‰ไธ€ไบ›่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏไปฃ็ /SDK๏ผŒไฝ ๆš‚ๆ—ถไธๆƒณๆ›ดๆ–ฐๆ‰€ๆœ‰่ฟ™ไบ›่‡ชๅŠจ็”Ÿๆˆ็š„ๅฎขๆˆท็ซฏไปฃ็ /SDK๏ผˆไนŸ่ฎธๆœชๆฅไผš๏ผŒไฝ†ไธๆ˜ฏ็Žฐๅœจ๏ผ‰ใ€‚ + +่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไฝ ๅฏไปฅๅœจ **FastAPI** ไธญ้€š่ฟ‡ๅ‚ๆ•ฐ `separate_input_output_schemas=False` ็ฆ็”จ่ฏฅ็‰นๆ€งใ€‚ + +/// info | ไฟกๆฏ + +ๅฏน `separate_input_output_schemas` ็š„ๆ”ฏๆŒๆ˜ฏๅœจ FastAPI `0.102.0` ไธญๆทปๅŠ ็š„ใ€‚๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### ๆ–‡ๆกฃไธญ่พ“ๅ…ฅ/่พ“ๅ‡บไฝฟ็”จๅŒไธ€ Schema ็š„ๆจกๅž‹ { #same-schema-for-input-and-output-models-in-docs } + +็Žฐๅœจ่ฏฅๆจกๅž‹็š„่พ“ๅ…ฅๅ’Œ่พ“ๅ‡บๅฐ†ๅชไฝฟ็”จไธ€ไธช schema๏ผŒๅณ `Item`๏ผŒๅนถไธ”ๅ…ถไธญ็š„ `description` **ไธๆ˜ฏๅฟ…ๅกซ**๏ผš + +
+ +
diff --git a/docs/zh/docs/how-to/testing-database.md b/docs/zh/docs/how-to/testing-database.md new file mode 100644 index 0000000000..e4a20d8436 --- /dev/null +++ b/docs/zh/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# ๆต‹่ฏ•ๆ•ฐๆฎๅบ“ { #testing-a-database } + +ไฝ ๅฏไปฅๅœจ SQLModel ๆ–‡ๆกฃ ไธญๅญฆไน ๆ•ฐๆฎๅบ“ใ€SQL ๅ’Œ SQLModelใ€‚๐Ÿค“ + +่ฟ™้‡Œๆœ‰ไธ€ไธชๅ…ณไบŽๅœจ FastAPI ไธญไฝฟ็”จ SQLModel ็š„ๅฐๆ•™็จ‹๏ผšไฝฟ็”จ SQLModel ๆญ้… FastAPI ็š„ๆ•™็จ‹ใ€‚โœจ + +่ฏฅๆ•™็จ‹ๅŒ…ๅซไธ€ไธชๅ…ณไบŽ ๆต‹่ฏ• SQL ๆ•ฐๆฎๅบ“ ็š„็ซ ่Š‚ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 1c2aea3285..38e128bf14 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -40,7 +40,7 @@ FastAPI ๆ˜ฏไธ€ไธช็”จไบŽๆž„ๅปบ API ็š„็Žฐไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ€ง่ƒฝ๏ผ‰็š„ Web ๆก† * **ๅฟซ้€Ÿ**๏ผšๆž้ซ˜ๆ€ง่ƒฝ๏ผŒๅฏไธŽ **NodeJS** ๅ’Œ **Go** ๅนถ่‚ฉ๏ผˆๅฝ’ๅŠŸไบŽ Starlette ๅ’Œ Pydantic๏ผ‰ใ€‚[ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€](#performance)ใ€‚ * **้ซ˜ๆ•ˆ็ผ–็ **๏ผšๅŠŸ่ƒฝๅผ€ๅ‘้€Ÿๅบฆๆๅ‡็บฆ 200% ๏ฝž 300%ใ€‚* * **ๆ›ดๅฐ‘ bug**๏ผšไบบไธบ๏ผˆๅผ€ๅ‘่€…๏ผ‰้”™่ฏฏๅ‡ๅฐ‘็บฆ 40%ใ€‚* -* **็›ด่ง‚**๏ผšๆžไฝณ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ๅค„ๅค„็š†ๅฏ่‡ชๅŠจ่กฅๅ…จใ€‚ๆ›ดๅฐ‘็š„่ฐƒ่ฏ•ๆ—ถ้—ดใ€‚ +* **็›ด่ง‚**๏ผšๆžไฝณ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒใ€‚ๅค„ๅค„็š†ๅฏ่‡ชๅŠจ่กฅๅ…จใ€‚ๆ›ดๅฐ‘็š„่ฐƒ่ฏ•ๆ—ถ้—ดใ€‚ * **ๆ˜“็”จ**๏ผšไธบๆ˜“็”จๅ’Œๆ˜“ๅญฆ่€Œ่ฎพ่ฎกใ€‚ๆ›ดๅฐ‘็š„ๆ–‡ๆกฃ้˜…่ฏปๆ—ถ้—ดใ€‚ * **็ฎ€็Ÿญ**๏ผšๆœ€ๅฐๅŒ–ไปฃ็ ้‡ๅคใ€‚ไธ€ๆฌกๅ‚ๆ•ฐๅฃฐๆ˜Žๅณๅฏ่Žทๅพ—ๅคš็งๅŠŸ่ƒฝใ€‚ๆ›ดๅฐ‘็š„ bugใ€‚ * **ๅฅๅฃฎ**๏ผš็”Ÿไบงๅฏ็”จ็บงไปฃ็ ใ€‚ๅนถๅธฆๆœ‰่‡ชๅŠจ็”Ÿๆˆ็š„ไบคไบ’ๅผๆ–‡ๆกฃใ€‚ @@ -368,7 +368,7 @@ item: Item * ๆ•ฐๆฎๆ ก้ชŒ๏ผš * ๅฝ“ๆ•ฐๆฎๆ— ๆ•ˆๆ—ถ่‡ชๅŠจ็”Ÿๆˆๆธ…ๆ™ฐ็š„้”™่ฏฏไฟกๆฏใ€‚ * ๅณไพฟๆ˜ฏๅคšๅฑ‚ๅตŒๅฅ—็š„ JSON ๅฏน่ฑกไนŸไผš่ฟ›่กŒๆ ก้ชŒใ€‚ -* ่พ“ๅ…ฅๆ•ฐๆฎ็š„่ฝฌๆข๏ผšไปŽ็ฝ‘็ปœ่ฏปๅ–ๅˆฐ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹ใ€‚่ฏปๅ–ๆฅๆบ๏ผš +* ่ฝฌๆข่พ“ๅ…ฅๆ•ฐๆฎ๏ผšไปŽ็ฝ‘็ปœ่ฏปๅ–ๅˆฐ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹ใ€‚่ฏปๅ–ๆฅๆบ๏ผš * JSONใ€‚ * ่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ * ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ @@ -376,7 +376,7 @@ item: Item * Headersใ€‚ * Formsใ€‚ * Filesใ€‚ -* ่พ“ๅ‡บๆ•ฐๆฎ็š„่ฝฌๆข๏ผšไปŽ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹่ฝฌๆขไธบ็ฝ‘็ปœๆ•ฐๆฎ๏ผˆJSON๏ผ‰๏ผš +* ่ฝฌๆข่พ“ๅ‡บๆ•ฐๆฎ๏ผšไปŽ Python ๆ•ฐๆฎๅ’Œ็ฑปๅž‹่ฝฌๆขไธบ็ฝ‘็ปœๆ•ฐๆฎ๏ผˆJSON๏ผ‰๏ผš * ่ฝฌๆข Python ็ฑปๅž‹๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ็ญ‰๏ผ‰ใ€‚ * `datetime` ๅฏน่ฑกใ€‚ * `UUID` ๅฏน่ฑกใ€‚ @@ -439,7 +439,7 @@ item: Item * ๆฅ่‡ชไธๅŒไฝ็ฝฎ็š„**ๅ‚ๆ•ฐ**ๅฃฐๆ˜Ž๏ผš**headers**ใ€**cookies**ใ€**form ๅญ—ๆฎต**ๅ’Œ**ๆ–‡ไปถ**ใ€‚ * ๅฆ‚ไฝ•่ฎพ็ฝฎ**ๆ ก้ชŒ็บฆๆŸ**๏ผŒๅฆ‚ `maximum_length` ๆˆ– `regex`ใ€‚ -* ๅŠŸ่ƒฝๅผบๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ต–ๆณจๅ…ฅ** ็ณป็ปŸใ€‚ +* ๅŠŸ่ƒฝๅผบๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ต–ๆณจๅ…ฅ** ็ณป็ปŸใ€‚ * ๅฎ‰ๅ…จไธŽ่ฎค่ฏ๏ผŒๅŒ…ๆ‹ฌๅฏน **OAuth2**ใ€**JWT tokens** ๅ’Œ **HTTP Basic** ่ฎค่ฏ็š„ๆ”ฏๆŒใ€‚ * ๆ›ด้ซ˜็บง๏ผˆไฝ†ๅŒๆ ท็ฎ€ๅ•๏ผ‰็š„ **ๅคšๅฑ‚ๅตŒๅฅ— JSON ๆจกๅž‹** ๅฃฐๆ˜ŽๆŠ€ๅทง๏ผˆๅพ—็›ŠไบŽ Pydantic๏ผ‰ใ€‚ * ้€š่ฟ‡ Strawberry ็ญ‰ๅบ“่ฟ›่กŒ **GraphQL** ้›†ๆˆใ€‚ @@ -524,7 +524,7 @@ Starlette ไฝฟ็”จ๏ผš * httpx - ไฝฟ็”จ `TestClient` ๆ—ถ้œ€่ฆใ€‚ * jinja2 - ไฝฟ็”จ้ป˜่ฎคๆจกๆฟ้…็ฝฎๆ—ถ้œ€่ฆใ€‚ -* python-multipart - ไฝฟ็”จ `request.form()` ๆ”ฏๆŒ่กจๅ•ใ€Œ่งฃๆžใ€ๆ—ถ้œ€่ฆใ€‚ +* python-multipart - ไฝฟ็”จ `request.form()` ๆ”ฏๆŒ่กจๅ•ใ€Œ่งฃๆžใ€ๆ—ถ้œ€่ฆใ€‚ FastAPI ไฝฟ็”จ๏ผš diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 3e1c593c11..4824b7558d 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -2,11 +2,11 @@ Python ๆ”ฏๆŒๅฏ้€‰็š„โ€œ็ฑปๅž‹ๆ็คบโ€๏ผˆไนŸๅซโ€œ็ฑปๅž‹ๆณจ่งฃโ€๏ผ‰ใ€‚ -่ฟ™ไบ›โ€œ็ฑปๅž‹ๆ็คบโ€ๆˆ–ๆณจ่งฃๆ˜ฏไธ€็ง็‰นๆฎŠ่ฏญๆณ•๏ผŒ็”จๆฅๅฃฐๆ˜Žๅ˜้‡็š„็ฑปๅž‹ใ€‚ +่ฟ™ไบ›โ€œ็ฑปๅž‹ๆ็คบโ€ๆˆ–ๆณจ่งฃๆ˜ฏไธ€็ง็‰นๆฎŠ่ฏญๆณ•๏ผŒ็”จๆฅๅฃฐๆ˜Žๅ˜้‡็š„็ฑปๅž‹ใ€‚ ้€š่ฟ‡ไธบๅ˜้‡ๅฃฐๆ˜Ž็ฑปๅž‹๏ผŒ็ผ–่พ‘ๅ™จๅ’Œๅทฅๅ…ทๅฏไปฅไธบไฝ ๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒใ€‚ -่ฟ™ๅชๆ˜ฏไธ€ไธชๅ…ณไบŽ Python ็ฑปๅž‹ๆ็คบ็š„ๅฟซ้€Ÿๅ…ฅ้—จ/ๅคไน ใ€‚ๅฎƒๅชๆถต็›–ไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จๆ‰€้œ€็š„ๆœ€ๅฐ‘้ƒจๅˆ†โ€ฆโ€ฆๅฎž้™…ไธŠ้žๅธธๅฐ‘ใ€‚ +่ฟ™ๅชๆ˜ฏไธ€ไธชๅ…ณไบŽ Python ็ฑปๅž‹ๆ็คบ็š„ๅฟซ้€Ÿๅ…ฅ้—จ/ๅคไน ใ€‚ๅฎƒๅชๆถต็›–ไธŽ **FastAPI** ไธ€่ตทไฝฟ็”จๆ‰€้œ€็š„ๆœ€ๅฐ‘้ƒจๅˆ†...ๅฎž้™…ไธŠ้žๅธธๅฐ‘ใ€‚ **FastAPI** ๅฎŒๅ…จๅŸบไบŽ่ฟ™ไบ›็ฑปๅž‹ๆ็คบๆž„ๅปบ๏ผŒๅฎƒไปฌๅธฆๆฅไบ†่ฎธๅคšไผ˜ๅŠฟๅ’Œๅฅฝๅค„ใ€‚ @@ -22,7 +22,7 @@ Python ๆ”ฏๆŒๅฏ้€‰็š„โ€œ็ฑปๅž‹ๆ็คบโ€๏ผˆไนŸๅซโ€œ็ฑปๅž‹ๆณจ่งฃโ€๏ผ‰ใ€‚ ่ฎฉๆˆ‘ไปฌไปŽไธ€ไธช็ฎ€ๅ•็š„ไพ‹ๅญๅผ€ๅง‹๏ผš -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} ่ฟ่กŒ่ฟ™ไธช็จ‹ๅบไผš่พ“ๅ‡บ๏ผš @@ -34,9 +34,9 @@ John Doe * ๆŽฅๆ”ถ `first_name` ๅ’Œ `last_name`ใ€‚ * ้€š่ฟ‡ `title()` ๅฐ†ๆฏไธชๅ‚ๆ•ฐ็š„็ฌฌไธ€ไธชๅญ—ๆฏ่ฝฌๆขไธบๅคงๅ†™ใ€‚ -* ็”จไธ€ไธช็ฉบๆ ผๅฐ†ๅฎƒไปฌๆ‹ผๆŽฅ่ตทๆฅใ€‚ +* ็”จไธ€ไธช็ฉบๆ ผๅฐ†ๅฎƒไปฌๆ‹ผๆŽฅ่ตทๆฅใ€‚ -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### ไฟฎๆ”นๅฎƒ { #edit-it } @@ -78,7 +78,7 @@ John Doe ่ฟ™ไบ›ๅฐฑๆ˜ฏโ€œ็ฑปๅž‹ๆ็คบโ€๏ผš -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} ่ฟ™ๅ’Œๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผไธๅŒ๏ผŒๆฏ”ๅฆ‚๏ผš @@ -106,7 +106,7 @@ John Doe ็œ‹่ฟ™ไธชๅทฒ็ปๅธฆๆœ‰็ฑปๅž‹ๆ็คบ็š„ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} ๅ› ไธบ็ผ–่พ‘ๅ™จ็Ÿฅ้“ๅ˜้‡็š„็ฑปๅž‹๏ผŒไฝ ไธไป…่ƒฝๅพ—ๅˆฐ่กฅๅ…จ๏ผŒ่ฟ˜่ƒฝ่Žทๅพ—้”™่ฏฏๆฃ€ๆŸฅ๏ผš @@ -114,7 +114,7 @@ John Doe ็Žฐๅœจไฝ ็Ÿฅ้“้œ€่ฆไฟฎๅคๅฎƒ๏ผŒ็”จ `str(age)` ๆŠŠ `age` ่ฝฌๆˆๅญ—็ฌฆไธฒ๏ผš -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## ๅฃฐๆ˜Ž็ฑปๅž‹ { #declaring-types } @@ -133,29 +133,32 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### ๅธฆ็ฑปๅž‹ๅ‚ๆ•ฐ็š„ๆณ›ๅž‹็ฑปๅž‹ { #generic-types-with-type-parameters } +### typing ๆจกๅ— { #typing-module } -ๆœ‰ไบ›ๆ•ฐๆฎ็ป“ๆž„ๅฏไปฅๅŒ…ๅซๅ…ถไป–ๅ€ผ๏ผŒๆฏ”ๅฆ‚ `dict`ใ€`list`ใ€`set` ๅ’Œ `tuple`ใ€‚่€Œๅ†…้ƒจ็š„ๅ€ผไนŸไผšๆœ‰่‡ชๅทฑ็š„็ฑปๅž‹ใ€‚ +ๅœจไธ€ไบ›้ขๅค–็š„็”จไพ‹ไธญ๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆไปŽๆ ‡ๅ‡†ๅบ“็š„ `typing` ๆจกๅ—ๅฏผๅ…ฅๅ†…ๅฎนใ€‚ๆฏ”ๅฆ‚ๅฝ“ไฝ ๆƒณๅฃฐๆ˜Žโ€œไปปๆ„็ฑปๅž‹โ€ๆ—ถ๏ผŒๅฏไปฅไฝฟ็”จ `typing` ไธญ็š„ `Any`๏ผš -่ฟ™ไบ›ๅธฆๆœ‰ๅ†…้ƒจ็ฑปๅž‹็š„็ฑปๅž‹็งฐไธบโ€œๆณ›ๅž‹โ€๏ผˆgeneric๏ผ‰็ฑปๅž‹ใ€‚ๅฏไปฅๆŠŠๅฎƒไปฌ่ฟžๅŒๅ†…้ƒจ็ฑปๅž‹ไธ€่ตทๅฃฐๆ˜Žๅ‡บๆฅใ€‚ +```python +from typing import Any -่ฆๅฃฐๆ˜Ž่ฟ™ไบ›็ฑปๅž‹ไปฅๅŠๅ†…้ƒจ็ฑปๅž‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Python ๆ ‡ๅ‡†ๅบ“ๆจกๅ— `typing`ใ€‚ๅฎƒๅฐฑๆ˜ฏไธบๆ”ฏๆŒ่ฟ™ไบ›็ฑปๅž‹ๆ็คบ่€Œๅญ˜ๅœจ็š„ใ€‚ -#### ๆ›ดๆ–ฐ็š„ Python ็‰ˆๆœฌ { #newer-versions-of-python } - -ไฝฟ็”จ `typing` ็š„่ฏญๆณ•ไธŽๆ‰€ๆœ‰็‰ˆๆœฌๅ…ผๅฎน๏ผŒไปŽ Python 3.6 ๅˆฐๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผˆๅŒ…ๆ‹ฌ Python 3.9ใ€Python 3.10 ็ญ‰๏ผ‰ใ€‚ +def some_function(data: Any): + print(data) +``` -้š็€ Python ็š„ๅ‘ๅฑ•๏ผŒๆ›ดๆ–ฐ็š„็‰ˆๆœฌๅฏน่ฟ™ไบ›็ฑปๅž‹ๆณจ่งฃ็š„ๆ”ฏๆŒๆ›ดๅฅฝ๏ผŒๅœจๅพˆๅคšๆƒ…ๅ†ตไธ‹ไฝ ็”š่‡ณไธ้œ€่ฆๅฏผๅ…ฅๅ’Œไฝฟ็”จ `typing` ๆจกๅ—ๆฅๅฃฐๆ˜Ž็ฑปๅž‹ๆณจ่งฃใ€‚ +### ๆณ›ๅž‹็ฑปๅž‹ { #generic-types } -ๅฆ‚ๆžœไฝ ๅฏไปฅไธบ้กน็›ฎ้€‰ๆ‹ฉๆ›ด้ซ˜็‰ˆๆœฌ็š„ Python๏ผŒไฝ ๅฐ†่ƒฝไบซๅ—ๅˆฐ่ฟ™็ง้ขๅค–็š„็ฎ€ๅŒ–ใ€‚ +ๆœ‰ไบ›็ฑปๅž‹ๅฏไปฅๅœจๆ–นๆ‹ฌๅทไธญๆŽฅๆ”ถโ€œ็ฑปๅž‹ๅ‚ๆ•ฐโ€๏ผˆtype parameters๏ผ‰๏ผŒ็”จไบŽๅฃฐๆ˜Žๅ…ถๅ†…้ƒจๅ€ผ็š„็ฑปๅž‹ใ€‚ๆฏ”ๅฆ‚โ€œๅญ—็ฌฆไธฒๅˆ—่กจโ€ๅฏไปฅๅ†™ไธบ `list[str]`ใ€‚ -ๅœจๆ•ดไธชๆ–‡ๆกฃไธญ๏ผŒไผšๆ นๆฎไธๅŒ Python ็‰ˆๆœฌๆไพ›็›ธๅบ”็š„็คบไพ‹๏ผˆๅฝ“ๅญ˜ๅœจๅทฎๅผ‚ๆ—ถ๏ผ‰ใ€‚ +่ฟ™ไบ›่ƒฝๆŽฅๆ”ถ็ฑปๅž‹ๅ‚ๆ•ฐ็š„็ฑปๅž‹็งฐไธบโ€œๆณ›ๅž‹็ฑปๅž‹โ€๏ผˆGeneric types๏ผ‰ๆˆ–โ€œๆณ›ๅž‹โ€๏ผˆGenerics๏ผ‰ใ€‚ -ๆฏ”ๅฆ‚โ€œPython 3.6+โ€่กจ็คบๅ…ผๅฎน Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ 3.7ใ€3.8ใ€3.9ใ€3.10 ็ญ‰๏ผ‰ใ€‚่€Œโ€œPython 3.9+โ€่กจ็คบๅ…ผๅฎน Python 3.9 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ 3.10 ็ญ‰๏ผ‰ใ€‚ +ไฝ ๅฏไปฅๆŠŠ็›ธๅŒ็š„ๅ†…ๅปบ็ฑปๅž‹ไฝœไธบๆณ›ๅž‹ไฝฟ็”จ๏ผˆๅธฆๆ–นๆ‹ฌๅทๅ’Œๅ†…้ƒจ็ฑปๅž‹๏ผ‰๏ผš -ๅฆ‚ๆžœไฝ ๅฏไปฅไฝฟ็”จๆœ€ๆ–ฐ็š„ Python ็‰ˆๆœฌ๏ผŒ่ฏทไฝฟ็”จๆœ€ๆ–ฐ็‰ˆๆœฌ็š„็คบไพ‹๏ผŒๅฎƒไปฌๅฐ†ๆ‹ฅๆœ‰ๆœ€็ฎ€ๆด็š„่ฏญๆณ•๏ผŒไพ‹ๅฆ‚โ€œPython 3.10+โ€ใ€‚ +* `list` +* `tuple` +* `set` +* `dict` #### ๅˆ—่กจ { #list } @@ -167,7 +170,7 @@ John Doe ๅ› ไธบ list ๆ˜ฏไธ€็งๅŒ…ๅซๅ†…้ƒจ็ฑปๅž‹็š„็ฑปๅž‹๏ผŒๆŠŠๅ†…้ƒจ็ฑปๅž‹ๅ†™ๅœจๆ–นๆ‹ฌๅท้‡Œ๏ผš -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | ไฟกๆฏ @@ -193,7 +196,7 @@ John Doe ๅฃฐๆ˜Ž `tuple` ๅ’Œ `set` ็š„ๆ–นๅผ็ฑปไผผ๏ผš -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} ่ฟ™่กจ็คบ๏ผš @@ -208,7 +211,7 @@ John Doe ็ฌฌไบŒไธช็ฑปๅž‹ๅ‚ๆ•ฐ็”จไบŽๅญ—ๅ…ธ็š„ๅ€ผ๏ผš -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} ่ฟ™่กจ็คบ๏ผš @@ -220,44 +223,20 @@ John Doe ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ˜้‡ๅฏไปฅๆ˜ฏ่‹ฅๅนฒ็ง็ฑปๅž‹ไธญ็š„ไปปๆ„ไธ€็ง๏ผŒๆฏ”ๅฆ‚ๆ—ขๅฏไปฅๆ˜ฏ `int` ไนŸๅฏไปฅๆ˜ฏ `str`ใ€‚ -ๅœจ Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ Python 3.10๏ผ‰๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `typing` ไธญ็š„ `Union`๏ผŒๆŠŠๅฏ่ƒฝ็š„็ฑปๅž‹ๆ”พๅˆฐๆ–นๆ‹ฌๅท้‡Œใ€‚ - -ๅœจ Python 3.10 ไธญ่ฟ˜ๆœ‰ไธ€็งๆ–ฐ็š„่ฏญๆณ•๏ผŒๅฏไปฅ็”จ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๆŠŠๅฏ่ƒฝ็š„็ฑปๅž‹ๅˆ†้š”ๅผ€ใ€‚ +ๅฎšไน‰ๆ—ถไฝฟ็”จ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๆŠŠไธค็ง็ฑปๅž‹ๅˆ†ๅผ€ใ€‚ -//// tab | Python 3.10+ +่ฟ™็งฐไธบโ€œ่”ๅˆ็ฑปๅž‹โ€๏ผˆunion๏ผ‰๏ผŒๅ› ไธบๅ˜้‡ๅฏไปฅๆ˜ฏ่ฟ™ไธค็ฑป็ฑปๅž‹้›†ๅˆ็š„ๅนถ้›†ไธญ็š„ไปปๆ„ไธ€ไธชใ€‚ ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -ไธค็งๆ–นๅผ็š„ๅซไน‰ไธ€่‡ด๏ผš`item` ๅฏไปฅๆ˜ฏ `int` ๆˆ– `str`ใ€‚ +่ฟ™่กจ็คบ `item` ๅฏไปฅๆ˜ฏ `int` ๆˆ– `str`ใ€‚ #### ๅฏ่ƒฝไธบ `None` { #possibly-none } ไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ€ผ็š„็ฑปๅž‹ๆ˜ฏๆŸ็ง็ฑปๅž‹๏ผˆๆฏ”ๅฆ‚ `str`๏ผ‰๏ผŒไฝ†ๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`ใ€‚ -ๅœจ Python 3.6 ๅŠไปฅไธŠ๏ผˆๅŒ…ๆ‹ฌ Python 3.10๏ผ‰๏ผŒไฝ ๅฏไปฅ้€š่ฟ‡ไปŽ `typing` ๆจกๅ—ๅฏผๅ…ฅๅนถไฝฟ็”จ `Optional` ๆฅๅฃฐๆ˜Ž๏ผš - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -ไฝฟ็”จ `Optional[str]` ่€Œไธๆ˜ฏไป…ไป… `str`๏ผŒๅฏไปฅ่ฎฉ็ผ–่พ‘ๅ™จๅธฎๅŠฉไฝ ๅ‘็ŽฐๆŠŠๅ€ผๅฝ“ๆˆๆ€ปๆ˜ฏ `str` ็š„้”™่ฏฏ๏ผˆๅฎž้™…ไธŠๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`๏ผ‰ใ€‚ - -`Optional[Something]` ๅฎž้™…ไธŠๆ˜ฏ `Union[Something, None]` ็š„็ฎ€ๅ†™๏ผŒๅฎƒไปฌ็ญ‰ไปทใ€‚ - -่ฟ™ไนŸๆ„ๅ‘ณ็€ๅœจ Python 3.10 ไธญ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Something | None`๏ผš - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ John Doe //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ ๅฆไธ€็งๅ†™ๆณ• - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### ไฝฟ็”จ `Union` ๆˆ– `Optional` { #using-union-or-optional } - -ๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏ 3.10 ไปฅไธ‹็š„ Python ็‰ˆๆœฌ๏ผŒ่ฟ™้‡Œๆœ‰ไธชๆฅ่‡ชๆˆ‘้žๅธธไธป่ง‚็š„ๅปบ่ฎฎ๏ผš - -* ๐Ÿšจ ้ฟๅ…ไฝฟ็”จ `Optional[SomeType]` -* ๆ”น็”จ โœจ**`Union[SomeType, None]`**โœจ - -ไธค่€…็ญ‰ไปท๏ผŒๅบ•ๅฑ‚็›ธๅŒ๏ผŒไฝ†ๆˆ‘ๆ›ดๆŽจ่ `Union` ่€Œไธๆ˜ฏ `Optional`๏ผŒๅ› ไธบโ€œoptional๏ผˆๅฏ้€‰๏ผ‰โ€่ฟ™ไธช่ฏ็œ‹่ตทๆฅๅƒๆ˜ฏๅœจ่ฏดโ€œๅ‚ๆ•ฐๅฏ้€‰โ€๏ผŒ่€Œๅฎƒๅฎž้™…ไธŠ่กจ็คบโ€œๅฎƒๅฏไปฅๆ˜ฏ `None`โ€๏ผŒๅณไฝฟๅฎƒๅนถไธๆ˜ฏๅฏ้€‰็š„๏ผŒไป็„ถๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ - -ๆˆ‘่ฎคไธบ `Union[SomeType, None]` ๆ›ดๆ˜Ž็กฎๅœฐ่กจ่พพไบ†ๅฎƒ็š„ๆ„ๆ€ใ€‚ - -่ฟ™ๅชๆ˜ฏๅ…ณไบŽ่ฏ่ฏญๅ’Œๅๅญ—ใ€‚ไฝ†่ฟ™ไบ›่ฏไผšๅฝฑๅ“ไฝ ๅ’Œไฝ ็š„้˜Ÿๅ‹ๅฆ‚ไฝ•็†่งฃไปฃ็ ใ€‚ - -ไพ‹ๅฆ‚๏ผŒ็œ‹ไธ‹้ข่ฟ™ไธชๅ‡ฝๆ•ฐ๏ผš - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -ๅ‚ๆ•ฐ `name` ่ขซๅฎšไน‰ไธบ `Optional[str]`๏ผŒไฝ†ๅฎƒๅนถไธๆ˜ฏโ€œๅฏ้€‰โ€็š„๏ผŒไฝ ไธ่ƒฝไธไผ ่ฟ™ไธชๅ‚ๆ•ฐๅฐฑ่ฐƒ็”จๅ‡ฝๆ•ฐ๏ผš - -```Python -say_hi() # ๅ“ฆไธ๏ผŒ่ฟ™ไผšๆŠ›้”™๏ผ๐Ÿ˜ฑ -``` - -ๅ‚ๆ•ฐ `name` ไป็„ถๆ˜ฏๅฟ…ๅกซ็š„๏ผˆไธๆ˜ฏโ€œๅฏ้€‰โ€๏ผ‰๏ผŒๅ› ไธบๅฎƒๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ไธ่ฟ‡๏ผŒ`name` ๆŽฅๅ— `None` ไฝœไธบๅ€ผ๏ผš - -```Python -say_hi(name=None) # ่ฟ™ๆ ทๅฏไปฅ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆๅ€ผ ๐ŸŽ‰ -``` - -ๅฅฝๆถˆๆฏๆ˜ฏ๏ผŒไธ€ๆ—ฆไฝ ไฝฟ็”จ Python 3.10๏ผŒๅฐฑๆ— ้œ€ๅ†ไธบๆญคๆ“ๅฟƒ๏ผŒๅ› ไธบไฝ ๅฏไปฅ็›ดๆŽฅ็”จ `|` ๆฅๅฎšไน‰็ฑปๅž‹่”ๅˆ๏ผš - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -่ฟ™ๆ ทไฝ ๅฐฑไธๅฟ…ๅ†่€ƒ่™‘ `Optional` ๅ’Œ `Union` ่ฟ™ไบ›ๅๅญ—ไบ†ใ€‚๐Ÿ˜Ž - -#### ๆณ›ๅž‹็ฑปๅž‹ { #generic-types } - -่ฟ™ไบ›ๅœจๆ–นๆ‹ฌๅทไธญๆŽฅๆ”ถ็ฑปๅž‹ๅ‚ๆ•ฐ็š„็ฑปๅž‹็งฐไธบโ€œๆณ›ๅž‹็ฑปๅž‹โ€๏ผˆGeneric types๏ผ‰ๆˆ–โ€œๆณ›ๅž‹โ€๏ผˆGenerics๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš - -//// tab | Python 3.10+ - -ไฝ ๅฏไปฅๆŠŠๅŒๆ ท็š„ๅ†…ๅปบ็ฑปๅž‹ไฝœไธบๆณ›ๅž‹ไฝฟ็”จ๏ผˆๅธฆๆ–นๆ‹ฌๅทๅ’Œๅ†…้ƒจ็ฑปๅž‹๏ผ‰๏ผš - -* `list` -* `tuple` -* `set` -* `dict` - -ไปฅๅŠไธŽไน‹ๅ‰็š„ Python ็‰ˆๆœฌไธ€ๆ ท๏ผŒๆฅ่‡ช `typing` ๆจกๅ—็š„๏ผš - -* `Union` -* `Optional` -* โ€ฆโ€ฆไปฅๅŠๅ…ถไป–ใ€‚ - -ๅœจ Python 3.10 ไธญ๏ผŒไฝœไธบไฝฟ็”จๆณ›ๅž‹ `Union` ๅ’Œ `Optional` ็š„ๆ›ฟไปฃ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ็ซ–็บฟ๏ผˆ`|`๏ผ‰ๆฅๅฃฐๆ˜Ž็ฑปๅž‹่”ๅˆ๏ผŒ่ฟ™ๆ›ดๅฅฝไนŸๆ›ด็ฎ€ๅ•ใ€‚ - -//// - -//// tab | Python 3.9+ - -ไฝ ๅฏไปฅๆŠŠๅŒๆ ท็š„ๅ†…ๅปบ็ฑปๅž‹ไฝœไธบๆณ›ๅž‹ไฝฟ็”จ๏ผˆๅธฆๆ–นๆ‹ฌๅทๅ’Œๅ†…้ƒจ็ฑปๅž‹๏ผ‰๏ผš - -* `list` -* `tuple` -* `set` -* `dict` - -ไปฅๅŠๆฅ่‡ช `typing` ๆจกๅ—็š„ๆณ›ๅž‹๏ผš - -* `Union` -* `Optional` -* โ€ฆโ€ฆไปฅๅŠๅ…ถไป–ใ€‚ - -//// +ไฝฟ็”จ `str | None` ่€Œไธๆ˜ฏไป…ไป… `str`๏ผŒๅฏไปฅ่ฎฉ็ผ–่พ‘ๅ™จๅธฎๅŠฉไฝ ๅ‘็ŽฐๆŠŠๅ€ผๅฝ“ๆˆๆ€ปๆ˜ฏ `str` ็š„้”™่ฏฏ๏ผˆๅฎž้™…ไธŠๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`๏ผ‰ใ€‚ ### ็ฑปไฝœไธบ็ฑปๅž‹ { #classes-as-types } @@ -363,11 +253,11 @@ say_hi(name=None) # ่ฟ™ๆ ทๅฏไปฅ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆๅ€ผ ๐ŸŽ‰ ๅ‡่ฎพไฝ ๆœ‰ไธ€ไธชๅไธบ `Person` ็š„็ฑป๏ผŒๅธฆๆœ‰ name๏ผš -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} ็„ถๅŽไฝ ๅฏไปฅๅฃฐๆ˜Žไธ€ไธชๅ˜้‡ๆ˜ฏ `Person` ็ฑปๅž‹๏ผš -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} ๆŽฅ็€๏ผŒไฝ ไผšๅ†ๆฌก่Žทๅพ—ๆ‰€ๆœ‰็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ๏ผš @@ -403,19 +293,13 @@ say_hi(name=None) # ่ฟ™ๆ ทๅฏไปฅ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆๅ€ผ ๐ŸŽ‰ ไฝ ไผšๅœจ[ๆ•™็จ‹ - ็”จๆˆทๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐๆ›ดๅคš็š„ๅฎžๆˆ˜็คบไพ‹ใ€‚ -/// tip | ๆ็คบ - -ๅฝ“ไฝ ๅœจๆฒกๆœ‰้ป˜่ฎคๅ€ผ็š„ๆƒ…ๅ†ตไธ‹ไฝฟ็”จ `Optional` ๆˆ– `Union[Something, None]` ๆ—ถ๏ผŒPydantic ๆœ‰ไธ€ไธช็‰นๆฎŠ่กŒไธบ๏ผŒไฝ ๅฏไปฅๅœจ Pydantic ๆ–‡ๆกฃ็š„ ๅฟ…ๅกซ็š„ Optional ๅญ—ๆฎต ไธญไบ†่งฃๆ›ดๅคšใ€‚ - -/// - ## ๅธฆๅ…ƒๆ•ฐๆฎๆณจ่งฃ็š„็ฑปๅž‹ๆ็คบ { #type-hints-with-metadata-annotations } -Python ่ฟ˜ๆไพ›ไบ†ไธ€ไธช็‰นๆ€ง๏ผŒๅฏไปฅไฝฟ็”จ `Annotated` ๅœจ่ฟ™ไบ›็ฑปๅž‹ๆ็คบไธญๆ”พๅ…ฅ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎใ€‚ +Python ่ฟ˜ๆไพ›ไบ†ไธ€ไธช็‰นๆ€ง๏ผŒๅฏไปฅไฝฟ็”จ `Annotated` ๅœจ่ฟ™ไบ›็ฑปๅž‹ๆ็คบไธญๆ”พๅ…ฅ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎใ€‚ -ไปŽ Python 3.9 ่ตท๏ผŒ`Annotated` ๆ˜ฏๆ ‡ๅ‡†ๅบ“็š„ไธ€้ƒจๅˆ†๏ผŒๅ› ๆญคๅฏไปฅไปŽ `typing` ๅฏผๅ…ฅใ€‚ +ไฝ ๅฏไปฅไปŽ `typing` ๅฏผๅ…ฅ `Annotated`ใ€‚ -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Python ๆœฌ่บซไธไผšๅฏน่ฟ™ไธช `Annotated` ๅšไปปไฝ•ๅค„็†ใ€‚ๅฏนไบŽ็ผ–่พ‘ๅ™จๅ’Œๅ…ถไป–ๅทฅๅ…ท๏ผŒ็ฑปๅž‹ไป็„ถๆ˜ฏ `str`ใ€‚ diff --git a/docs/zh/docs/resources/index.md b/docs/zh/docs/resources/index.md new file mode 100644 index 0000000000..2f55ac06f6 --- /dev/null +++ b/docs/zh/docs/resources/index.md @@ -0,0 +1,3 @@ +# ่ต„ๆบ { #resources } + +ๆ›ดๅคš่ต„ๆบใ€ๅค–้ƒจ้“พๆŽฅ็ญ‰ใ€‚โœˆ๏ธ diff --git a/docs/zh/docs/translation-banner.md b/docs/zh/docs/translation-banner.md new file mode 100644 index 0000000000..76db203b0b --- /dev/null +++ b/docs/zh/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ ็”ฑ AI ไธŽไบบ็ฑปๅไฝœ็ฟป่ฏ‘ + +ๆœฌ็ฟป่ฏ‘็”ฑไบบ็ฑปๅผ•ๅฏผ็š„ AI ็”Ÿๆˆใ€‚๐Ÿค + +ๅฏ่ƒฝๅญ˜ๅœจ่ฏฏ่งฃๅŽŸๆ„ๆˆ–ไธๅคŸ่‡ช็„ถ็ญ‰้—ฎ้ข˜ใ€‚๐Ÿค– + +ไฝ ๅฏไปฅ้€š่ฟ‡[ๅธฎๅŠฉๆˆ‘ไปฌๆ›ดๅฅฝๅœฐๅผ•ๅฏผ AI LLM](https://fastapi.tiangolo.com/zh/contributing/#translations)ๆฅๆ”น่ฟ›ๆญค็ฟป่ฏ‘ใ€‚ + +[่‹ฑๆ–‡็‰ˆๆœฌ](ENGLISH_VERSION_URL) + +/// diff --git a/docs/zh/docs/tutorial/background-tasks.md b/docs/zh/docs/tutorial/background-tasks.md index 8398472c37..d73fee4299 100644 --- a/docs/zh/docs/tutorial/background-tasks.md +++ b/docs/zh/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ ้ฆ–ๅ…ˆๅฏผๅ…ฅ `BackgroundTasks` ๅนถๅœจ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ไธญไฝฟ็”จ็ฑปๅž‹ๅฃฐๆ˜Ž `BackgroundTasks` ๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** ไผšๅˆ›ๅปบไธ€ไธช `BackgroundTasks` ็ฑปๅž‹็š„ๅฏน่ฑกๅนถไฝœไธบ่ฏฅๅ‚ๆ•ฐไผ ๅ…ฅใ€‚ @@ -31,13 +31,13 @@ ็”ฑไบŽๅ†™ๆ“ไฝœไธไฝฟ็”จ `async` ๅ’Œ `await`๏ผŒๆˆ‘ไปฌ็”จๆ™ฎ้€š็š„ `def` ๅฎšไน‰ๅ‡ฝๆ•ฐ๏ผš -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## ๆทปๅŠ ๅŽๅฐไปปๅŠก { #add-the-background-task } ๅœจไฝ ็š„ *่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ* ้‡Œ๏ผŒ็”จ `.add_task()` ๆ–นๆณ•ๅฐ†ไปปๅŠกๅ‡ฝๆ•ฐไผ ๅˆฐ *ๅŽๅฐไปปๅŠก* ๅฏน่ฑกไธญ๏ผš -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` ๆŽฅๆ”ถไปฅไธ‹ๅ‚ๆ•ฐ๏ผš @@ -69,7 +69,7 @@ ๅœจFastAPIไธญไป็„ถๅฏไปฅๅ•็‹ฌไฝฟ็”จ `BackgroundTask`๏ผŒไฝ†ๆ‚จๅฟ…้กปๅœจไปฃ็ ไธญๅˆ›ๅปบๅฏน่ฑก๏ผŒๅนถ่ฟ”ๅ›žๅŒ…ๅซๅฎƒ็š„Starlette `Response`ใ€‚ -ๆ›ดๅคš็ป†่Š‚ๆŸฅ็œ‹ Starlette's official docs for Background Tasks. +ๆ›ดๅคš็ป†่Š‚ๆŸฅ็œ‹ Starlette ๅŽๅฐไปปๅŠก็š„ๅฎ˜ๆ–นๆ–‡ๆกฃ. ## ๅ‘Š่ฏซ { #caveat } diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index 1ced002dc3..a667d596f8 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ from app.routers import items ไฝ ๅฏไปฅๅฏผๅ…ฅๅฎƒๅนถ้€š่ฟ‡ไธŽ `FastAPI` ็ฑป็›ธๅŒ็š„ๆ–นๅผๅˆ›ๅปบไธ€ไธชใ€Œๅฎžไพ‹ใ€๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### ไฝฟ็”จ `APIRouter` ็š„*่ทฏๅพ„ๆ“ไฝœ* { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ from app.routers import items ไฝฟ็”จๆ–นๅผไธŽ `FastAPI` ็ฑป็›ธๅŒ๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} ไฝ ๅฏไปฅๅฐ† `APIRouter` ่ง†ไธบไธ€ไธชใ€Œ่ฟทไฝ  `FastAPI`ใ€็ฑปใ€‚ @@ -117,7 +117,7 @@ from app.routers import items ็Žฐๅœจๆˆ‘ไปฌๅฐ†ไฝฟ็”จไธ€ไธช็ฎ€ๅ•็š„ไพ่ต–้กนๆฅ่ฏปๅ–ไธ€ไธช่‡ชๅฎšไน‰็š„ `X-Token` ่ฏทๆฑ‚้ฆ–้ƒจ๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | ๆ็คบ @@ -149,7 +149,7 @@ from app.routers import items ๅ› ๆญค๏ผŒๆˆ‘ไปฌๅฏไปฅๅฐ†ๅ…ถๆทปๅŠ ๅˆฐ `APIRouter` ไธญ๏ผŒ่€Œไธๆ˜ฏๅฐ†ๅ…ถๆทปๅŠ ๅˆฐๆฏไธช่ทฏๅพ„ๆ“ไฝœไธญใ€‚ -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} ็”ฑไบŽๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*็š„่ทฏๅพ„้ƒฝๅฟ…้กปไปฅ `/` ๅผ€ๅคด๏ผŒไพ‹ๅฆ‚๏ผš @@ -208,7 +208,7 @@ async def read_item(item_id: str): ๅ› ๆญค๏ผŒๆˆ‘ไปฌ้€š่ฟ‡ `..` ๅฏนไพ่ต–้กนไฝฟ็”จไบ†็›ธๅฏนๅฏผๅ…ฅ๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### ็›ธๅฏนๅฏผๅ…ฅๅฆ‚ไฝ•ๅทฅไฝœ { #how-relative-imports-work } @@ -279,11 +279,11 @@ from ...dependencies import get_token_header ไฝ†ๆ˜ฏๆˆ‘ไปฌไป็„ถๅฏไปฅๆทปๅŠ *ๆ›ดๅคš*ๅฐ†ไผšๅบ”็”จไบŽ็‰นๅฎš็š„*่ทฏๅพ„ๆ“ไฝœ*็š„ `tags`๏ผŒไปฅๅŠไธ€ไบ›็‰นๅฎšไบŽ่ฏฅ*่ทฏๅพ„ๆ“ไฝœ*็š„้ขๅค– `responses`๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | ๆ็คบ -ๆœ€ๅŽ็š„่ฟ™ไธช่ทฏๅพ„ๆ“ไฝœๅฐ†ๅŒ…ๅซๆ ‡็ญพ็š„็ป„ๅˆ๏ผš`["items"๏ผŒ"custom"]`ใ€‚ +ๆœ€ๅŽ็š„่ฟ™ไธช่ทฏๅพ„ๆ“ไฝœๅฐ†ๅŒ…ๅซๆ ‡็ญพ็š„็ป„ๅˆ๏ผš`["items", "custom"]`ใ€‚ ๅนถไธ”ๅœจๆ–‡ๆกฃไธญไนŸไผšๆœ‰ไธคไธชๅ“ๅบ”๏ผŒไธ€ไธช็”จไบŽ `404`๏ผŒไธ€ไธช็”จไบŽ `403`ใ€‚ @@ -305,13 +305,13 @@ from ...dependencies import get_token_header ๆˆ‘ไปฌ็”š่‡ณๅฏไปฅๅฃฐๆ˜Ž[ๅ…จๅฑ€ไพ่ต–้กน](dependencies/global-dependencies.md){.internal-link target=_blank}๏ผŒๅฎƒไผšๅ’Œๆฏไธช `APIRouter` ็š„ไพ่ต–้กน็ป„ๅˆๅœจไธ€่ตท๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### ๅฏผๅ…ฅ `APIRouter` { #import-the-apirouter } ็Žฐๅœจ๏ผŒๆˆ‘ไปฌๅฏผๅ…ฅๅ…ทๆœ‰ `APIRouter` ็š„ๅ…ถไป–ๅญๆจกๅ—๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} ็”ฑไบŽๆ–‡ไปถ `app/routers/users.py` ๅ’Œ `app/routers/items.py` ๆ˜ฏๅŒไธ€ Python ๅŒ… `app` ไธ€ไธช้ƒจๅˆ†็š„ๅญๆจกๅ—๏ผŒๅ› ๆญคๆˆ‘ไปฌๅฏไปฅไฝฟ็”จๅ•ไธช็‚น ` .` ้€š่ฟ‡ใ€Œ็›ธๅฏนๅฏผๅ…ฅใ€ๆฅๅฏผๅ…ฅๅฎƒไปฌใ€‚ @@ -374,13 +374,13 @@ from .routers.users import router ๅ› ๆญค๏ผŒไธบไบ†่ƒฝๅคŸๅœจๅŒไธ€ไธชๆ–‡ไปถไธญไฝฟ็”จๅฎƒไปฌ๏ผŒๆˆ‘ไปฌ็›ดๆŽฅๅฏผๅ…ฅๅญๆจกๅ—๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### ๅŒ…ๅซ `users` ๅ’Œ `items` ็š„ `APIRouter` { #include-the-apirouters-for-users-and-items } ็Žฐๅœจ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅๅŒ…ๅซๆฅ่‡ช `users` ๅ’Œ `items` ๅญๆจกๅ—็š„ `router`ใ€‚ -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | ไฟกๆฏ @@ -420,13 +420,13 @@ from .routers.users import router ๅฏนไบŽๆญค็คบไพ‹๏ผŒๅฎƒๅฐ†้žๅธธ็ฎ€ๅ•ใ€‚ไฝ†ๆ˜ฏๅ‡่ฎพ็”ฑไบŽๅฎƒๆ˜ฏไธŽ็ป„็ป‡ไธญ็š„ๅ…ถไป–้กน็›ฎๆ‰€ๅ…ฑไบซ็š„๏ผŒๅ› ๆญคๆˆ‘ไปฌๆ— ๆณ•ๅฏนๅ…ถ่ฟ›่กŒไฟฎๆ”น๏ผŒไปฅๅŠ็›ดๆŽฅๅœจ `APIRouter` ไธญๆทปๅŠ  `prefix`ใ€`dependencies`ใ€`tags` ็ญ‰๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ไฝ†ๆ˜ฏๆˆ‘ไปฌไป็„ถๅธŒๆœ›ๅœจๅŒ…ๅซ `APIRouter` ๆ—ถ่ฎพ็ฝฎไธ€ไธช่‡ชๅฎšไน‰็š„ `prefix`๏ผŒไปฅไพฟๅ…ถๆ‰€ๆœ‰*่ทฏๅพ„ๆ“ไฝœ*ไปฅ `/admin` ๅผ€ๅคด๏ผŒๆˆ‘ไปฌๅธŒๆœ›ไฝฟ็”จๆœฌ้กน็›ฎๅทฒ็ปๆœ‰็š„ `dependencies` ไฟๆŠคๅฎƒ๏ผŒๅนถไธ”ๆˆ‘ไปฌๅธŒๆœ›ๅฎƒๅŒ…ๅซ่‡ชๅฎšไน‰็š„ `tags` ๅ’Œ `responses`ใ€‚ ๆˆ‘ไปฌๅฏไปฅ้€š่ฟ‡ๅฐ†่ฟ™ไบ›ๅ‚ๆ•ฐไผ ้€’็ป™ `app.include_router()` ๆฅๅฎŒๆˆๆ‰€ๆœ‰็š„ๅฃฐๆ˜Ž๏ผŒ่€Œไธๅฟ…ไฟฎๆ”นๅŽŸๅง‹็š„ `APIRouter`๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} ่ฟ™ๆ ท๏ผŒๅŽŸๅง‹็š„ `APIRouter` ๅฐ†ไฟๆŒไธๅ˜๏ผŒๅ› ๆญคๆˆ‘ไปฌไป็„ถๅฏไปฅไธŽ็ป„็ป‡ไธญ็š„ๅ…ถไป–้กน็›ฎๅ…ฑไบซ็›ธๅŒ็š„ `app/internal/admin.py` ๆ–‡ไปถใ€‚ @@ -447,7 +447,7 @@ from .routers.users import router ่ฟ™้‡Œๆˆ‘ไปฌ่ฟ™ๆ ทๅšไบ†...ๅชๆ˜ฏไธบไบ†่กจๆ˜Žๆˆ‘ไปฌๅฏไปฅๅšๅˆฐ๐Ÿคท๏ผš -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} ๅฎƒๅฐ†ไธŽ้€š่ฟ‡ `app.include_router()` ๆทปๅŠ ็š„ๆ‰€ๆœ‰ๅ…ถไป–*่ทฏๅพ„ๆ“ไฝœ*ไธ€่ตทๆญฃๅธธ่ฟ่กŒใ€‚ diff --git a/docs/zh/docs/tutorial/body-multiple-params.md b/docs/zh/docs/tutorial/body-multiple-params.md index 7d0ddfc1ec..39b84904fc 100644 --- a/docs/zh/docs/tutorial/body-multiple-params.md +++ b/docs/zh/docs/tutorial/body-multiple-params.md @@ -104,12 +104,6 @@ q: str | None = None ``` -ๆˆ–่€…ๅœจ Python 3.9 ไธญ๏ผš - -```Python -q: Union[str, None] = None -``` - ๆฏ”ๅฆ‚๏ผš {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md index 242aa5822c..fe6902e83f 100644 --- a/docs/zh/docs/tutorial/body-nested-models.md +++ b/docs/zh/docs/tutorial/body-nested-models.md @@ -163,7 +163,7 @@ images: list[Image] ไพ‹ๅฆ‚๏ผš -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## ๆ— ๅค„ไธๅœจ็š„็ผ–่พ‘ๅ™จๆ”ฏๆŒ { #editor-support-everywhere } @@ -193,7 +193,7 @@ images: list[Image] ๅœจไธ‹้ข็š„ไพ‹ๅญไธญ๏ผŒไฝ ๅฐ†ๆŽฅๅ—ไปปๆ„้”ฎไธบ `int` ็ฑปๅž‹ๅนถไธ”ๅ€ผไธบ `float` ็ฑปๅž‹็š„ `dict`๏ผš -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ๆ็คบ diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md index 60088a0482..4a72ba17c5 100644 --- a/docs/zh/docs/tutorial/body.md +++ b/docs/zh/docs/tutorial/body.md @@ -153,7 +153,7 @@ FastAPI ไผšๆ นๆฎ้ป˜่ฎคๅ€ผ `= None` ็Ÿฅ้“ `q` ็š„ๅ€ผไธๆ˜ฏๅฟ…ๅกซ็š„ใ€‚ -`str | None`๏ผˆPython 3.10+๏ผ‰ๆˆ– `Union[str, None]`๏ผˆPython 3.9+ ไธญ็š„ `Union`๏ผ‰ๅนถไธๆ˜ฏ FastAPI ็”จๆฅๅˆคๆ–ญๆ˜ฏๅฆๅฟ…ๅกซ็š„ไพๆฎ๏ผ›ๆ˜ฏๅฆๅฟ…ๅกซ็”ฑๆ˜ฏๅฆๆœ‰้ป˜่ฎคๅ€ผ `= None` ๅ†ณๅฎšใ€‚ +`str | None` ๅนถไธๆ˜ฏ FastAPI ็”จๆฅๅˆคๆ–ญๆ˜ฏๅฆๅฟ…ๅกซ็š„ไพๆฎ๏ผ›ๆ˜ฏๅฆๅฟ…ๅกซ็”ฑๆ˜ฏๅฆๆœ‰้ป˜่ฎคๅ€ผ `= None` ๅ†ณๅฎšใ€‚ ไฝ†ๆทปๅŠ ่ฟ™ไบ›็ฑปๅž‹ๆณจ่งฃๅฏไปฅ่ฎฉไฝ ็š„็ผ–่พ‘ๅ™จๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆŒๅนถๆฃ€ๆต‹้”™่ฏฏใ€‚ diff --git a/docs/zh/docs/tutorial/cookie-param-models.md b/docs/zh/docs/tutorial/cookie-param-models.md index 707a6a9c79..8e094c7d3f 100644 --- a/docs/zh/docs/tutorial/cookie-param-models.md +++ b/docs/zh/docs/tutorial/cookie-param-models.md @@ -46,17 +46,17 @@ ๅœจๆŸไบ›็‰นๆฎŠไฝฟ็”จๆƒ…ๅ†ตไธ‹๏ผˆๅฏ่ƒฝๅนถไธๅธธ่ง๏ผ‰๏ผŒๆ‚จๅฏ่ƒฝๅธŒๆœ›**้™ๅˆถ**ๆ‚จๆƒณ่ฆๆŽฅๆ”ถ็š„ cookieใ€‚ -ๆ‚จ็š„ API ็ŽฐๅœจๅฏไปฅๆŽงๅˆถ่‡ชๅทฑ็š„ cookie ๅŒๆ„ใ€‚๐Ÿคช๐Ÿช +ๆ‚จ็š„ API ็ŽฐๅœจๅฏไปฅๆŽงๅˆถ่‡ชๅทฑ็š„ cookie ๅŒๆ„ใ€‚๐Ÿคช๐Ÿช ๆ‚จๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ็ฆๆญข๏ผˆ `forbid` ๏ผ‰ไปปไฝ•้ขๅค–๏ผˆ `extra` ๏ผ‰ๅญ—ๆฎต๏ผš {* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} -ๅฆ‚ๆžœๅฎขๆˆทๅฐ่ฏ•ๅ‘้€ไธ€ไบ›**้ขๅค–็š„ cookie**๏ผŒไป–ไปฌๅฐ†ๆ”ถๅˆฐ**้”™่ฏฏ**ๅ“ๅบ”ใ€‚ +ๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ไธ€ไบ›**้ขๅค–็š„ cookie**๏ผŒไป–ไปฌๅฐ†ๆ”ถๅˆฐ**้”™่ฏฏ**ๅ“ๅบ”ใ€‚ -ๅฏๆ€œ็š„ cookie ้€š็Ÿฅๆก๏ผŒ่ดนๅฐฝๅฟƒๆ€ไธบไบ†่Žทๅพ—ๆ‚จ็š„ๅŒๆ„๏ผŒๅด่ขซAPI ๆ‹’็ปไบ†ใ€‚๐Ÿช +ๅฏๆ€œ็š„ cookie ้€š็Ÿฅๆก๏ผŒ่ดนๅฐฝๅฟƒๆ€ไธบไบ†่Žทๅพ—ๆ‚จ็š„ๅŒๆ„๏ผŒๅด่ขซAPI ๆ‹’็ปไบ†ใ€‚๐Ÿช -ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ไธ€ไธชๅ€ผไธบ `good-list-please` ็š„ `santa_tracker` cookie๏ผŒๅฎขๆˆท็ซฏๅฐ†ๆ”ถๅˆฐไธ€ไธช**้”™่ฏฏ**ๅ“ๅบ”๏ผŒๅ‘Š็Ÿฅไป–ไปฌ `santa_tracker` cookie ๆ˜ฏไธๅ…่ฎธ็š„๏ผš +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ไธ€ไธชๅ€ผไธบ `good-list-please` ็š„ `santa_tracker` cookie๏ผŒๅฎขๆˆท็ซฏๅฐ†ๆ”ถๅˆฐไธ€ไธช**้”™่ฏฏ**ๅ“ๅบ”๏ผŒๅ‘Š็Ÿฅไป–ไปฌ `santa_tracker` cookie ๆ˜ฏไธๅ…่ฎธ็š„๏ผš ```json { @@ -73,4 +73,4 @@ ## ๆ€ป็ป“ { #summary } -ๆ‚จๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญๅฃฐๆ˜Ž **cookie**ใ€‚๐Ÿ˜Ž +ๆ‚จๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹**ๅœจ **FastAPI** ไธญๅฃฐๆ˜Ž **cookie**ใ€‚๐Ÿ˜Ž diff --git a/docs/zh/docs/tutorial/cors.md b/docs/zh/docs/tutorial/cors.md index 3a296ca723..2e271ec758 100644 --- a/docs/zh/docs/tutorial/cors.md +++ b/docs/zh/docs/tutorial/cors.md @@ -46,7 +46,7 @@ * ็‰นๅฎš็š„ HTTP ๆ–นๆณ•๏ผˆ`POST`๏ผŒ`PUT`๏ผ‰ๆˆ–่€…ไฝฟ็”จ้€š้…็ฌฆ `"*"` ๅ…่ฎธๆ‰€ๆœ‰ๆ–นๆณ•ใ€‚ * ็‰นๅฎš็š„ HTTP ่ฏทๆฑ‚ๅคดๆˆ–่€…ไฝฟ็”จ้€š้…็ฌฆ `"*"` ๅ…่ฎธๆ‰€ๆœ‰่ฏทๆฑ‚ๅคดใ€‚ -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} ้ป˜่ฎคๆƒ…ๅ†ตไธ‹๏ผŒ่ฟ™ไธช `CORSMiddleware` ๅฎž็Žฐๆ‰€ไฝฟ็”จ็š„้ป˜่ฎคๅ‚ๆ•ฐ่พƒไธบไฟๅฎˆ๏ผŒๆ‰€ไปฅไฝ ้œ€่ฆๆ˜พๅผๅœฐๅฏ็”จ็‰นๅฎš็š„ๆบใ€ๆ–นๆณ•ๆˆ–่€… headers๏ผŒไปฅไพฟๆต่งˆๅ™จ่ƒฝๅคŸๅœจ่ทจๅŸŸไธŠไธ‹ๆ–‡ไธญไฝฟ็”จๅฎƒไปฌใ€‚ @@ -63,7 +63,7 @@ * `expose_headers` - ๆŒ‡็คบๅฏไปฅ่ขซๆต่งˆๅ™จ่ฎฟ้—ฎ็š„ๅ“ๅบ”ๅคดใ€‚้ป˜่ฎคไธบ `[]`ใ€‚ * `max_age` - ่ฎพๅฎšๆต่งˆๅ™จ็ผ“ๅญ˜ CORS ๅ“ๅบ”็š„ๆœ€้•ฟๆ—ถ้—ด๏ผŒๅ•ไฝๆ˜ฏ็ง’ใ€‚้ป˜่ฎคไธบ `600`ใ€‚ -ไธญ้—ดไปถๅ“ๅบ”ไธค็ง็‰นๅฎš็ฑปๅž‹็š„ HTTP ่ฏทๆฑ‚โ€ฆโ€ฆ +ไธญ้—ดไปถๅ“ๅบ”ไธค็ง็‰นๅฎš็ฑปๅž‹็š„ HTTP ่ฏทๆฑ‚... ### CORS ้ข„ๆฃ€่ฏทๆฑ‚ { #cors-preflight-requests } diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md index 6e0cefe5b5..1ff7d61275 100644 --- a/docs/zh/docs/tutorial/debugging.md +++ b/docs/zh/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ ๅœจไฝ ็š„ FastAPI ๅบ”็”จไธญ็›ดๆŽฅๅฏผๅ…ฅ `uvicorn` ๅนถ่ฟ่กŒ๏ผš -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### ๅ…ณไบŽ `__name__ == "__main__"` { #about-name-main } @@ -68,7 +68,7 @@ from myapp import app uvicorn.run(app, host="0.0.0.0", port=8000) ``` -/// info +/// info | ไฟกๆฏ ๆ›ดๅคšไฟกๆฏ่ฏทๆฃ€ๆŸฅ Python ๅฎ˜ๆ–นๆ–‡ๆกฃ. diff --git a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md index d83321ddd6..43bd7a6807 100644 --- a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md @@ -14,7 +14,7 @@ ๅฏนๆญค๏ผŒๆˆ‘ไปฌๅฏไปฅๅš็š„ๆ›ดๅฅฝ... -## ไป€ไนˆๆž„ๆˆไบ†ไพ่ต–้กน๏ผŸ { #what-makes-a-dependency } +## ไป€ไนˆๆž„ๆˆไบ†ไพ่ต–้กน { #what-makes-a-dependency } ๅˆฐ็›ฎๅ‰ไธบๆญข๏ผŒไฝ ็œ‹ๅˆฐ็š„ไพ่ต–้กน้ƒฝ่ขซๅฃฐๆ˜Žไธบๅ‡ฝๆ•ฐใ€‚ @@ -101,7 +101,7 @@ fluffy = Cat(name="Mr Fluffy") ๆณจๆ„๏ผŒๆˆ‘ไปฌๅœจไธŠ้ข็š„ไปฃ็ ไธญ็ผ–ๅ†™ไบ†ไธคๆฌก`CommonQueryParams`๏ผš -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ @@ -129,7 +129,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ... Depends(CommonQueryParams) ``` -...ๅฎž้™…ไธŠๆ˜ฏ **Fastapi** ็”จๆฅ็Ÿฅ้“ไพ่ต–้กนๆ˜ฏไป€ไนˆ็š„ใ€‚ +...ๅฎž้™…ไธŠๆ˜ฏ **FastAPI** ็”จๆฅ็Ÿฅ้“ไพ่ต–้กนๆ˜ฏไป€ไนˆ็š„ใ€‚ FastAPI ๅฐ†ไปŽไพ่ต–้กนไธญๆๅ–ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ‰ๆ˜ฏ FastAPI ๅฎž้™…่ฐƒ็”จ็š„ใ€‚ @@ -137,7 +137,7 @@ FastAPI ๅฐ†ไปŽไพ่ต–้กนไธญๆๅ–ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐ๏ผŒ่ฟ™ๆ‰ๆ˜ฏ FastAPI ๅฎž้™…่ฐƒ็”จ ๅœจๆœฌไพ‹ไธญ๏ผŒ็ฌฌไธ€ไธช `CommonQueryParams` ๏ผš -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ @@ -163,7 +163,7 @@ commons: CommonQueryParams ... ไฝ ๅฎž้™…ไธŠๅฏไปฅๅช่ฟ™ๆ ท็ผ–ๅ†™: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ @@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams) ไฝ†ๆ˜ฏไฝ ๅฏไปฅ็œ‹ๅˆฐ๏ผŒๆˆ‘ไปฌๅœจ่ฟ™้‡Œๆœ‰ไธ€ไบ›ไปฃ็ ้‡ๅคไบ†๏ผŒ็ผ–ๅ†™ไบ†`CommonQueryParams`ไธคๆฌก๏ผš -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ @@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ไธๆ˜ฏๅ†™ๆˆ่ฟ™ๆ ท๏ผš -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...่€Œๆ˜ฏ่ฟ™ๆ ทๅ†™: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ ๆœชไฝฟ็”จ Annotated +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated /// tip | ๆ็คบ diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 02fcf62a0a..23412e4650 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ ่ฏฅๅ‚ๆ•ฐ็š„ๅ€ผๆ˜ฏ็”ฑ `Depends()` ็ป„ๆˆ็š„ `list`๏ผš -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} ่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จไพ่ต–้กน็š„ๆ‰ง่กŒๆˆ–่งฃๆžๆ–นๅผๅ’Œๆ™ฎ้€šไพ่ต–้กนไธ€ๆ ท๏ผŒไฝ†ๅฐฑ็ฎ—่ฟ™ไบ›ไพ่ต–้กนไผš่ฟ”ๅ›žๅ€ผ๏ผŒๅฎƒไปฌ็š„ๅ€ผไนŸไธไผšไผ ้€’็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ใ€‚ @@ -22,13 +22,13 @@ ๆœ‰ไบ›็ผ–่พ‘ๅ™จไผšๆฃ€ๆŸฅไปฃ็ ไธญๆฒกไฝฟ็”จ่ฟ‡็š„ๅ‡ฝๆ•ฐๅ‚ๆ•ฐ๏ผŒๅนถๆ˜พ็คบ้”™่ฏฏๆ็คบใ€‚ -ๅœจ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญไฝฟ็”จ `dependencies` ๅ‚ๆ•ฐ๏ผŒๅฏไปฅ็กฎไฟๅœจๆ‰ง่กŒไพ่ต–้กน็š„ๅŒๆ—ถ๏ผŒ้ฟๅ…็ผ–่พ‘ๅ™จๆ˜พ็คบ้”™่ฏฏๆ็คบใ€‚ +ๅœจ*่ทฏๅพ„ๆ“ไฝœ่ฃ…้ฅฐๅ™จ*ไธญไฝฟ็”จ `dependencies` ๅ‚ๆ•ฐ๏ผŒๅฏไปฅ็กฎไฟๅœจๆ‰ง่กŒไพ่ต–้กน็š„ๅŒๆ—ถ๏ผŒ้ฟๅ…็ผ–่พ‘ๅ™จ/ๅทฅๅ…ทๆŠฅ้”™ใ€‚ ไฝฟ็”จ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กน่ฟ˜ๅฏไปฅ้ฟๅ…ๅผ€ๅ‘ๆ–ฐไบบ่ฏฏไผšไปฃ็ ไธญๅŒ…ๅซๆ— ็”จ็š„ๆœชไฝฟ็”จๅ‚ๆ•ฐใ€‚ /// -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ ๆœฌไพ‹ไธญ๏ผŒไฝฟ็”จ็š„ๆ˜ฏ่‡ชๅฎšไน‰ๅ“ๅบ”ๅคด `X-Key` ๅ’Œ `X-Token`ใ€‚ @@ -44,13 +44,13 @@ ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนๅฏไปฅๅฃฐๆ˜Ž่ฏทๆฑ‚็š„้œ€ๆฑ‚้กน๏ผˆๆฏ”ๅฆ‚ๅ“ๅบ”ๅคด๏ผ‰ๆˆ–ๅ…ถไป–ๅญไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### ่งฆๅ‘ๅผ‚ๅธธ { #raise-exceptions } ่ทฏๅพ„่ฃ…้ฅฐๅ™จไพ่ต–้กนไธŽๆญฃๅธธ็š„ไพ่ต–้กนไธ€ๆ ท๏ผŒๅฏไปฅ `raise` ๅผ‚ๅธธ๏ผš -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### ่ฟ”ๅ›žๅ€ผ { #return-values } @@ -58,7 +58,7 @@ ๅ› ๆญค๏ผŒๅฏไปฅๅค็”จๅœจๅ…ถไป–ไฝ็ฝฎไฝฟ็”จ่ฟ‡็š„ใ€๏ผˆ่ƒฝ่ฟ”ๅ›žๅ€ผ็š„๏ผ‰ๆ™ฎ้€šไพ่ต–้กน๏ผŒๅณไฝฟๆฒกๆœ‰ไฝฟ็”จ่ฟ™ไธชๅ€ผ๏ผŒไนŸไผšๆ‰ง่กŒ่ฏฅไพ่ต–้กน๏ผš -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## ไธบไธ€็ป„่ทฏๅพ„ๆ“ไฝœๅฎšไน‰ไพ่ต–้กน { #dependencies-for-a-group-of-path-operations } diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index bf495c9f39..413dedb96b 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # ไฝฟ็”จ yield ็š„ไพ่ต–้กน { #dependencies-with-yield } -FastAPI ๆ”ฏๆŒ้‚ฃไบ›ๅœจๅฎŒๆˆๅŽๆ‰ง่กŒไธ€ไบ›้ขๅค–ๆญฅ้ชค็š„ไพ่ต–้กนใ€‚ +FastAPI ๆ”ฏๆŒ้‚ฃไบ›ๅœจๅฎŒๆˆๅŽๆ‰ง่กŒไธ€ไบ›้ขๅค–ๆญฅ้ชค็š„ไพ่ต–้กนใ€‚ ไธบๆญค๏ผŒไฝฟ็”จ `yield` ่€Œไธๆ˜ฏ `return`๏ผŒๅนถๆŠŠ่ฟ™ไบ›้ขๅค–ๆญฅ้ชค๏ผˆไปฃ็ ๏ผ‰ๅ†™ๅœจๅŽ้ขใ€‚ @@ -29,15 +29,15 @@ FastAPI ๆ”ฏๆŒ้‚ฃไบ›ๅœจๅฎŒๆˆๅŽๆ‰ง่กŒไธ€ไบ›docstring ไธญๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ่ฟฐ๏ผŒ**FastAPI** ไผšไปŽไธญ่ฏปๅ–ใ€‚ +ๆ่ฟฐๅ†…ๅฎนๆฏ”่พƒ้•ฟไธ”ๅ ็”จๅคš่กŒๆ—ถ๏ผŒๅฏไปฅๅœจๅ‡ฝๆ•ฐ็š„ docstring ไธญๅฃฐๆ˜Ž*่ทฏๅพ„ๆ“ไฝœ*็š„ๆ่ฟฐ๏ผŒ**FastAPI** ไผšไปŽไธญ่ฏปๅ–ใ€‚ ๆ–‡ๆกฃๅญ—็ฌฆไธฒๆ”ฏๆŒ Markdown๏ผŒ่ƒฝๆญฃ็กฎ่งฃๆžๅ’Œๆ˜พ็คบ Markdown ็š„ๅ†…ๅฎน๏ผŒไฝ†่ฆๆณจๆ„ๆ–‡ๆกฃๅญ—็ฌฆไธฒ็š„็ผฉ่ฟ›ใ€‚ {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} -ไธ‹ๅ›พไธบ Markdown ๆ–‡ๆœฌๅœจ API ๆ–‡ๆกฃไธญ็š„ๆ˜พ็คบๆ•ˆๆžœ๏ผš +ๅฎƒไผšๅœจไบคไบ’ๅผๆ–‡ๆกฃไธญไฝฟ็”จ๏ผš @@ -72,7 +72,7 @@ OpenAPI ๆฆ‚ๅ›พไผš่‡ชๅŠจๆทปๅŠ ๆ ‡็ญพ๏ผŒไพ› API ๆ–‡ๆกฃๆŽฅๅฃไฝฟ็”จ๏ผš {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | ่ฏดๆ˜Ž +/// info | ไฟกๆฏ ๆณจๆ„๏ผŒ`response_description` ๅช็”จไบŽๆ่ฟฐๅ“ๅบ”๏ผŒ`description` ไธ€่ˆฌๅˆ™็”จไบŽๆ่ฟฐ*่ทฏๅพ„ๆ“ไฝœ*ใ€‚ @@ -90,9 +90,9 @@ OpenAPI ่ง„ๅฎšๆฏไธช*่ทฏๅพ„ๆ“ไฝœ*้ƒฝ่ฆๆœ‰ๅ“ๅบ”ๆ่ฟฐใ€‚ ## ๅผƒ็”จ*่ทฏๅพ„ๆ“ไฝœ* { #deprecate-a-path-operation } -`deprecated` ๅ‚ๆ•ฐๅฏไปฅๆŠŠ*่ทฏๅพ„ๆ“ไฝœ*ๆ ‡่ฎฐไธบๅผƒ็”จ๏ผŒๆ— ้œ€็›ดๆŽฅๅˆ ้™ค๏ผš +ๅฆ‚ๆžœ้œ€่ฆๆŠŠ*่ทฏๅพ„ๆ“ไฝœ*ๆ ‡่ฎฐไธบๅผƒ็”จ๏ผŒไฝ†ไธๅˆ ้™คๅฎƒ๏ผŒๅฏไปฅไผ ๅ…ฅ `deprecated` ๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} API ๆ–‡ๆกฃไผšๆŠŠ่ฏฅ่ทฏๅพ„ๆ“ไฝœๆ ‡่ฎฐไธบๅผƒ็”จ๏ผš diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md index ff8b1762cf..608aa69a1d 100644 --- a/docs/zh/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌๆทปๅŠ ไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ไฝฟ ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅฐ†ๅ‡ฝๆ•ฐๅฃฐๆ˜Žไธบ๏ผš -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} ไฝ†่ฏท่ฎฐไฝ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒไฝ ๅฐฑไธไผš้‡ๅˆฐ่ฟ™ไธช้—ฎ้ข˜๏ผŒๅ› ไธบไฝ ๆฒกๆœ‰ไฝฟ็”จ `Query()` ๆˆ– `Path()` ไฝœไธบๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## ๆŒ‰้œ€ๅฏนๅ‚ๆ•ฐๆŽ’ๅบ็š„ๆŠ€ๅทง { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌๆทปๅŠ ไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ไฝฟ Python ไธไผšๅฏน่ฟ™ไธช `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒไผš็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ้ƒฝๅบ”่ฏฅไฝœไธบๅ…ณ้”ฎๅญ—ๅ‚ๆ•ฐ๏ผˆ้”ฎๅ€ผๅฏน๏ผ‰ๆฅ่ฐƒ็”จ๏ผŒไนŸ่ขซ็งฐไธบ kwargsใ€‚ๅณไฝฟๅฎƒไปฌๆฒกๆœ‰้ป˜่ฎคๅ€ผใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### ไฝฟ็”จ `Annotated` ๆ›ดๅฅฝ { #better-with-annotated } ่ฏท่ฎฐไฝ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒๅ› ไธบไฝ ๆฒกๆœ‰ไฝฟ็”จๅ‡ฝๆ•ฐๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒๆ‰€ไปฅไฝ ไธไผšๆœ‰่ฟ™ไธช้—ฎ้ข˜๏ผŒไฝ ๅคงๆฆ‚็އไนŸไธ้œ€่ฆไฝฟ็”จ `*`ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽ็ญ‰ไบŽ { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Python ไธไผšๅฏน่ฟ™ไธช `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒไผš็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ ๅœจ่ฟ™้‡Œ๏ผŒไฝฟ็”จ `ge=1` ๅŽ๏ผŒ`item_id` ๅฟ…้กปๆ˜ฏไธ€ไธชๆ•ดๆ•ฐ๏ผŒๅ€ผ่ฆใ€Œ`g`reater than or `e`qualใ€1ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๅคงไบŽๅ’ŒๅฐไบŽ็ญ‰ไบŽ { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ Python ไธไผšๅฏน่ฟ™ไธช `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒไผš็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ * `gt`๏ผšๅคงไบŽ๏ผˆ`g`reater `t`han๏ผ‰ * `le`๏ผšๅฐไบŽ็ญ‰ไบŽ๏ผˆ`l`ess than or `e`qual๏ผ‰ -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## ๆ•ฐๅ€ผๆ ก้ชŒ๏ผšๆตฎ็‚นๆ•ฐใ€ๅคงไบŽๅ’ŒๅฐไบŽ { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Python ไธไผšๅฏน่ฟ™ไธช `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒไผš็Ÿฅ้“ไน‹ๅŽ็š„ๆ‰€ๆœ‰ๅ‚ๆ•ฐ ๅฏนไบŽ lt ไนŸๆ˜ฏไธ€ๆ ท็š„ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ๆ€ป็ป“ { #recap } diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md index fa4c9514a9..06a9f1b442 100644 --- a/docs/zh/docs/tutorial/path-params.md +++ b/docs/zh/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ ไฝ ๅฏไปฅไฝฟ็”จไธŽ Python ๅญ—็ฌฆไธฒๆ ผๅผๅŒ–็›ธๅŒ็š„่ฏญๆณ•ๅฃฐๆ˜Ž่ทฏๅพ„โ€œๅ‚ๆ•ฐโ€ๆˆ–โ€œๅ˜้‡โ€๏ผš -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} ่ทฏๅพ„ๅ‚ๆ•ฐ `item_id` ็š„ๅ€ผไผšไฝœไธบๅ‚ๆ•ฐ `item_id` ไผ ้€’็ป™ไฝ ็š„ๅ‡ฝๆ•ฐใ€‚ @@ -16,7 +16,7 @@ ไฝฟ็”จ Python ๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃ๏ผŒๅฃฐๆ˜Ž่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไธญ่ทฏๅพ„ๅ‚ๆ•ฐ็š„็ฑปๅž‹๏ผš -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} ๆœฌไพ‹ๆŠŠ `item_id` ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `int`ใ€‚ @@ -26,7 +26,7 @@ /// -## ๆ•ฐๆฎ่ฝฌๆข { #data-conversion } +## ๆ•ฐๆฎ่ฝฌๆข { #data-conversion } ่ฟ่กŒ็คบไพ‹ๅนถ่ฎฟ้—ฎ http://127.0.0.1:8000/items/3๏ผŒ่ฟ”ๅ›ž็š„ๅ“ๅบ”ๅฆ‚ไธ‹๏ผš @@ -38,7 +38,7 @@ ๆณจๆ„๏ผŒๅ‡ฝๆ•ฐๆŽฅๆ”ถๅนถ่ฟ”ๅ›ž็š„ๅ€ผๆ˜ฏ `3`๏ผˆ `int`๏ผ‰๏ผŒไธๆ˜ฏ `"3"`๏ผˆ`str`๏ผ‰ใ€‚ -**FastAPI** ้€š่ฟ‡็ฑปๅž‹ๅฃฐๆ˜Ž่‡ชๅŠจ**่งฃๆž**่ฏทๆฑ‚ไธญ็š„ๆ•ฐๆฎใ€‚ +**FastAPI** ้€š่ฟ‡็ฑปๅž‹ๅฃฐๆ˜Ž่‡ชๅŠจ่ฟ›่กŒ่ฏทๆฑ‚็š„่งฃๆžใ€‚ /// @@ -118,19 +118,19 @@ FastAPI ๅ……ๅˆ†ๅœฐๅˆฉ็”จไบ† `Enum` ็ฑปๅž‹ๆŽฅๆ”ถ้ข„่ฎพ็š„่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ +่ทฏๅพ„ๆ“ไฝœไฝฟ็”จ Python ็š„ `Enum` ็ฑปๅž‹ๆŽฅๆ”ถ้ข„่ฎพ็š„่ทฏๅพ„ๅ‚ๆ•ฐใ€‚ ### ๅˆ›ๅปบ `Enum` ็ฑป { #create-an-enum-class } @@ -140,11 +140,11 @@ FastAPI ๅ……ๅˆ†ๅœฐๅˆฉ็”จไบ† ๆจกๅž‹็š„ๅๅญ—ใ€‚ +**AlexNet**ใ€**ResNet**ใ€**LeNet** ๆ˜ฏๆœบๅ™จๅญฆไน ๆจกๅž‹็š„ๅๅญ—ใ€‚ /// @@ -152,7 +152,7 @@ FastAPI ๅ……ๅˆ†ๅœฐๅˆฉ็”จไบ† ่งฃๆž" +- ๆ•ฐๆฎ "่งฃๆž" - ๆ•ฐๆฎๆ ก้ชŒ - API ๆณจ่งฃๅ’Œ่‡ชๅŠจๆ–‡ๆกฃ diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index 62552e6d08..d41f302267 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -47,40 +47,16 @@ FastAPI ๅœจ 0.95.0 ็‰ˆๆœฌไธญๆทปๅŠ ไบ†ๅฏน `Annotated` ็š„ๆ”ฏๆŒ๏ผˆๅนถๅผ€ๅง‹ๆŽจ่ ๆˆ‘ไปฌไน‹ๅ‰็š„็ฑปๅž‹ๆ ‡ๆณจๆ˜ฏ๏ผš -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ๆˆ‘ไปฌ่ฆๅš็š„ๆ˜ฏ็”จ `Annotated` ๆŠŠๅฎƒๅŒ…่ตทๆฅ๏ผŒๅ˜ๆˆ๏ผš -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - ่ฟ™ไธค็งๅ†™ๆณ•ๅซไน‰็›ธๅŒ๏ผŒ`q` ๆ˜ฏไธ€ไธชๅฏไปฅๆ˜ฏ `str` ๆˆ– `None` ็š„ๅ‚ๆ•ฐ๏ผŒ้ป˜่ฎคๆ˜ฏ `None`ใ€‚ ็Žฐๅœจ่ฟ›ๅ…ฅๆ›ดๆœ‰่ถฃ็š„้ƒจๅˆ†ใ€‚๐ŸŽ‰ @@ -109,7 +85,7 @@ FastAPI ็Žฐๅœจไผš๏ผš ## ๅฆไธ€็ง๏ผˆๆ—ง็š„๏ผ‰ๆ–นๅผ๏ผšๆŠŠ `Query` ไฝœไธบ้ป˜่ฎคๅ€ผ { #alternative-old-query-as-the-default-value } -ๆ—ฉๆœŸ็‰ˆๆœฌ็š„ FastAPI๏ผˆ0.95.0 ไน‹ๅ‰๏ผ‰่ฆๆฑ‚ไฝ ๆŠŠ `Query` ไฝœไธบๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆ”พๅœจ `Annotated` ้‡Œใ€‚ไฝ ๅพˆๅฏ่ƒฝไผšๅœจๅˆซๅค„็œ‹ๅˆฐ่ฟ™็งๅ†™ๆณ•๏ผŒๆ‰€ไปฅๆˆ‘ไนŸ็ป™ไฝ ่งฃ้‡Šไธ€ไธ‹ใ€‚ +ๆ—ฉๆœŸ็‰ˆๆœฌ็š„ FastAPI๏ผˆ0.95.0 ไน‹ๅ‰๏ผ‰่ฆๆฑ‚ไฝ ๆŠŠ `Query` ไฝœไธบๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆ”พๅœจ `Annotated` ้‡Œใ€‚ไฝ ๅพˆๅฏ่ƒฝไผšๅœจๅˆซๅค„็œ‹ๅˆฐ่ฟ™็งๅ†™ๆณ•๏ผŒๆ‰€ไปฅๆˆ‘ไนŸ็ป™ไฝ ่งฃ้‡Šไธ€ไธ‹ใ€‚ /// tip | ๆ็คบ @@ -191,7 +167,7 @@ q: str = Query(default="rick") ## ๆทปๅŠ ๆญฃๅˆ™่กจ่พพๅผ { #add-regular-expressions } -ไฝ ๅฏไปฅๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐๅฟ…้กปๅŒน้…็š„ ๆญฃๅˆ™่กจ่พพๅผ `pattern`๏ผš +ไฝ ๅฏไปฅๅฎšไน‰ไธ€ไธชๅ‚ๆ•ฐๅฟ…้กปๅŒน้…็š„ ๆญฃๅˆ™่กจ่พพๅผ `pattern`๏ผš {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +187,7 @@ q: str = Query(default="rick") ๅ‡่ฎพไฝ ๆƒณ่ฆๅฃฐๆ˜ŽๆŸฅ่ฏขๅ‚ๆ•ฐ `q` ็š„ `min_length` ไธบ `3`๏ผŒๅนถไธ”้ป˜่ฎคๅ€ผไธบ `"fixedquery"`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | ๆณจๆ„ @@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None ๅ› ๆญค๏ผŒๅœจไฝฟ็”จ `Query` ็š„ๅŒๆ—ถ้œ€่ฆๆŠŠๆŸไธชๅ€ผๅฃฐๆ˜Žไธบๅฟ…ๅกซๆ—ถ๏ผŒๅช้œ€ไธๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผš -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### ๅฟ…ๅกซ๏ผŒไฝ†ๅฏไปฅไธบ `None` { #required-can-be-none } @@ -292,7 +268,7 @@ http://localhost:8000/items/?q=foo&q=bar ไฝ ่ฟ˜ๅฏไปฅๅฎšไน‰ๅœจๆฒกๆœ‰็ป™ๅฎšๅ€ผๆ—ถ็š„้ป˜่ฎค `list`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ๅฆ‚ๆžœไฝ ่ฎฟ้—ฎ๏ผš @@ -315,7 +291,7 @@ http://localhost:8000/items/ ไฝ ไนŸๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `list`๏ผŒ่€Œไธๆ˜ฏ `list[str]`๏ผš -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | ๆณจๆ„ @@ -371,7 +347,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ็Žฐๅœจๅ‡่ฎพไฝ ไธๅ†ๅ–œๆฌข่ฟ™ไธชๅ‚ๆ•ฐไบ†ใ€‚ -็”ฑไบŽ่ฟ˜ๆœ‰ๅฎขๆˆท็ซฏๅœจไฝฟ็”จๅฎƒ๏ผŒไฝ ไธๅพ—ไธไฟ็•™ไธ€ๆฎตๆ—ถ้—ด๏ผŒไฝ†ไฝ ๅธŒๆœ›ๆ–‡ๆกฃๆธ…ๆฅšๅœฐๅฐ†ๅ…ถๅฑ•็คบไธบๅทฒๅผƒ็”จใ€‚ +็”ฑไบŽ่ฟ˜ๆœ‰ๅฎขๆˆท็ซฏๅœจไฝฟ็”จๅฎƒ๏ผŒไฝ ไธๅพ—ไธไฟ็•™ไธ€ๆฎตๆ—ถ้—ด๏ผŒไฝ†ไฝ ๅธŒๆœ›ๆ–‡ๆกฃๆธ…ๆฅšๅœฐๅฐ†ๅ…ถๅฑ•็คบไธบๅทฒๅผƒ็”จใ€‚ ้‚ฃไนˆๅฐ†ๅ‚ๆ•ฐ `deprecated=True` ไผ ็ป™ `Query`๏ผš @@ -401,7 +377,7 @@ Pydantic ่ฟ˜ๆœ‰ ISBN ไนฆๅท๏ผ‰ๆˆ– `imdb-`๏ผˆ็”จไบŽ IMDB ็”ตๅฝฑ URL ็š„ ID๏ผ‰ๅผ€ๅคด๏ผš +ไพ‹ๅฆ‚๏ผŒ่ฟ™ไธช่‡ชๅฎšไน‰ๆ ก้ชŒๅ™จไผšๆฃ€ๆŸฅๆก็›ฎ ID ๆ˜ฏๅฆไปฅ `isbn-`๏ผˆ็”จไบŽ ISBN ไนฆๅท๏ผ‰ๆˆ– `imdb-`๏ผˆ็”จไบŽ IMDB ็”ตๅฝฑ URL ็š„ ID๏ผ‰ๅผ€ๅคด๏ผš {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,7 +411,7 @@ Pydantic ่ฟ˜ๆœ‰ ๅฏ่ฟญไปฃๅฏน่ฑกใ€‚ +ไฝฟ็”จ `data.items()` ๆˆ‘ไปฌไผšๅพ—ๅˆฐไธ€ไธชๅŒ…ๅซๆฏไธชๅญ—ๅ…ธ้กน้”ฎๅ’Œๅ€ผ็š„ๅ…ƒ็ป„็š„ ๅฏ่ฟญไปฃๅฏน่ฑกใ€‚ ๆˆ‘ไปฌ็”จ `list(data.items())` ๆŠŠ่ฟ™ไธชๅฏ่ฟญไปฃๅฏน่ฑก่ฝฌๆขๆˆไธ€ไธช็œŸๆญฃ็š„ `list`ใ€‚ diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md index 9ef998731a..4ea37d7e0c 100644 --- a/docs/zh/docs/tutorial/query-params.md +++ b/docs/zh/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ ๅฃฐๆ˜Ž็š„ๅ‚ๆ•ฐไธๆ˜ฏ่ทฏๅพ„ๅ‚ๆ•ฐๆ—ถ๏ผŒ่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐไผšๆŠŠ่ฏฅๅ‚ๆ•ฐ่‡ชๅŠจ่งฃ้‡Šไธบ**ๆŸฅ่ฏข**ๅ‚ๆ•ฐใ€‚ -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} ๆŸฅ่ฏขๅญ—็ฌฆไธฒๆ˜ฏ้”ฎๅ€ผๅฏน็š„้›†ๅˆ๏ผŒ่ฟ™ไบ›้”ฎๅ€ผๅฏนไฝไบŽ URL ็š„ `?` ไน‹ๅŽ๏ผŒไปฅ `&` ๅˆ†้š”ใ€‚ @@ -12,7 +12,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -โ€ฆโ€ฆๆŸฅ่ฏขๅ‚ๆ•ฐไธบ๏ผš +...ๆŸฅ่ฏขๅ‚ๆ•ฐไธบ๏ผš * `skip`๏ผšๅ€ผไธบ `0` * `limit`๏ผšๅ€ผไธบ `10` @@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ๆ‰€ๆœ‰ๅบ”็”จไบŽ่ทฏๅพ„ๅ‚ๆ•ฐ็š„ๆต็จ‹ไนŸ้€‚็”จไบŽๆŸฅ่ฏขๅ‚ๆ•ฐ๏ผš * ๏ผˆๆ˜พ่€Œๆ˜“่ง็š„๏ผ‰็ผ–่พ‘ๅ™จๆ”ฏๆŒ -* ๆ•ฐๆฎ**่งฃๆž** +* ๆ•ฐๆฎ"่งฃๆž" * ๆ•ฐๆฎๆ ก้ชŒ * ่‡ชๅŠจๆ–‡ๆกฃ @@ -75,7 +75,6 @@ http://127.0.0.1:8000/items/?skip=20 ๅ‚ๆ•ฐ่ฟ˜ๅฏไปฅๅฃฐๆ˜Žไธบ `bool` ็ฑปๅž‹๏ผŒFastAPI ไผš่‡ชๅŠจ่ฝฌๆขๅ‚ๆ•ฐ็ฑปๅž‹๏ผš - {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} ๆœฌไพ‹ไธญ๏ผŒ่ฎฟ้—ฎ๏ผš @@ -129,7 +128,7 @@ FastAPI ้€š่ฟ‡ๅ‚ๆ•ฐๅ่ฟ›่กŒๆฃ€ๆต‹๏ผš ๅฆ‚ๆžœ่ฆๆŠŠๆŸฅ่ฏขๅ‚ๆ•ฐ่ฎพ็ฝฎไธบ**ๅฟ…้€‰**๏ผŒๅฐฑไธ่ฆๅฃฐๆ˜Ž้ป˜่ฎคๅ€ผ๏ผš -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} ่ฟ™้‡Œ็š„ๆŸฅ่ฏขๅ‚ๆ•ฐ `needy` ๆ˜ฏ็ฑปๅž‹ไธบ `str` ็š„ๅฟ…้€‰ๆŸฅ่ฏขๅ‚ๆ•ฐใ€‚ @@ -139,7 +138,7 @@ FastAPI ้€š่ฟ‡ๅ‚ๆ•ฐๅ่ฟ›่กŒๆฃ€ๆต‹๏ผš http://127.0.0.1:8000/items/foo-item ``` -โ€ฆโ€ฆๅ› ไธบ่ทฏๅพ„ไธญๆฒกๆœ‰ๅฟ…้€‰ๅ‚ๆ•ฐ `needy`๏ผŒ่ฟ”ๅ›ž็š„ๅ“ๅบ”ไธญไผšๆ˜พ็คบๅฆ‚ไธ‹้”™่ฏฏไฟกๆฏ๏ผš +...ๅ› ไธบ่ทฏๅพ„ไธญๆฒกๆœ‰ๅฟ…้€‰ๅ‚ๆ•ฐ `needy`๏ผŒ่ฟ”ๅ›ž็š„ๅ“ๅบ”ไธญไผšๆ˜พ็คบๅฆ‚ไธ‹้”™่ฏฏไฟกๆฏ๏ผš ```JSON { @@ -163,7 +162,7 @@ http://127.0.0.1:8000/items/foo-item http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ``` -โ€ฆโ€ฆ่ฟ™ๆ ทๅฐฑๆญฃๅธธไบ†๏ผš +...่ฟ™ๆ ทๅฐฑๆญฃๅธธไบ†๏ผš ```JSON { diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md index 927bd093b0..e3b5435392 100644 --- a/docs/zh/docs/tutorial/request-files.md +++ b/docs/zh/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ $ pip install python-multipart ไปŽ `fastapi` ๅฏผๅ…ฅ `File` ๅ’Œ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## ๅฎšไน‰ `File` ๅ‚ๆ•ฐ { #define-file-parameters } ๅƒไธบ `Body` ๆˆ– `Form` ไธ€ๆ ทๅˆ›ๅปบๆ–‡ไปถๅ‚ๆ•ฐ๏ผš -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | ไฟกๆฏ @@ -54,7 +54,7 @@ $ pip install python-multipart ๅฐ†ๆ–‡ไปถๅ‚ๆ•ฐ็š„็ฑปๅž‹ๅฃฐๆ˜Žไธบ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} ไธŽ `bytes` ็›ธๆฏ”๏ผŒไฝฟ็”จ `UploadFile` ๆœ‰ๅคš้กนไผ˜ๅŠฟ๏ผš @@ -76,9 +76,9 @@ $ pip install python-multipart `UploadFile` ๅ…ทๆœ‰ไปฅไธ‹ `async` ๆ–นๆณ•ใ€‚ๅฎƒไปฌ้ƒฝไผšๅœจๅบ•ๅฑ‚่ฐƒ็”จๅฏนๅบ”็š„ๆ–‡ไปถๆ–นๆณ•๏ผˆไฝฟ็”จๅ†…้ƒจ็š„ `SpooledTemporaryFile`๏ผ‰ใ€‚ -* `write(data)`๏ผšๅฐ† `data`๏ผˆ`str` ๆˆ– `bytes`๏ผ‰ๅ†™ๅ…ฅๆ–‡ไปถใ€‚ -* `read(size)`๏ผš่ฏปๅ–ๆ–‡ไปถไธญ `size`๏ผˆ`int`๏ผ‰ไธชๅญ—่Š‚/ๅญ—็ฌฆใ€‚ -* `seek(offset)`๏ผš็งปๅŠจๅˆฐๆ–‡ไปถไธญๅญ—่Š‚ไฝ็ฝฎ `offset`๏ผˆ`int`๏ผ‰ใ€‚ +* `write(data)`๏ผšๅฐ† `data` (`str` ๆˆ– `bytes`) ๅ†™ๅ…ฅๆ–‡ไปถใ€‚ +* `read(size)`๏ผš่ฏปๅ–ๆ–‡ไปถไธญ `size` (`int`) ไธชๅญ—่Š‚/ๅญ—็ฌฆใ€‚ +* `seek(offset)`๏ผš็งปๅŠจๅˆฐๆ–‡ไปถไธญๅญ—่Š‚ไฝ็ฝฎ `offset` (`int`)ใ€‚ * ไพ‹ๅฆ‚๏ผŒ`await myfile.seek(0)` ไผš็งปๅŠจๅˆฐๆ–‡ไปถๅผ€ๅคดใ€‚ * ๅฆ‚ๆžœไฝ ๅ…ˆ่ฟ่กŒ่ฟ‡ `await myfile.read()`๏ผŒ็„ถๅŽ้œ€่ฆๅ†ๆฌก่ฏปๅ–ๅ†…ๅฎนๆ—ถ๏ผŒ่ฟ™ๅฐคๅ…ถๆœ‰็”จใ€‚ * `close()`๏ผšๅ…ณ้—ญๆ–‡ไปถใ€‚ @@ -121,7 +121,7 @@ HTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ็š„ๆ–นๅผ้€šๅธธไผšๅฏนๆ•ฐ ไฝ†ๅฝ“่กจๅ•ๅŒ…ๅซๆ–‡ไปถๆ—ถ๏ผŒไผš็ผ–็ ไธบ `multipart/form-data`ใ€‚ๅฆ‚ๆžœไฝ ไฝฟ็”จ `File`๏ผŒ**FastAPI** ไผš็Ÿฅ้“้œ€่ฆไปŽ่ฏทๆฑ‚ไฝ“็š„ๆญฃ็กฎไฝ็ฝฎ่Žทๅ–ๆ–‡ไปถใ€‚ -ๅฆ‚ๆžœไฝ ๆƒณ่ฟ›ไธ€ๆญฅไบ†่งฃ่ฟ™ไบ›็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต๏ผŒ่ฏทๅ‚้˜…
MDN web docs for POSTใ€‚ +ๅฆ‚ๆžœไฝ ๆƒณ่ฟ›ไธ€ๆญฅไบ†่งฃ่ฟ™ไบ›็ผ–็ ๅ’Œ่กจๅ•ๅญ—ๆฎต๏ผŒ่ฏทๅ‚้˜… MDN ๅ…ณไบŽ POST ็š„ Web ๆ–‡ๆกฃใ€‚ /// @@ -135,7 +135,7 @@ HTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ็š„ๆ–นๅผ้€šๅธธไผšๅฏนๆ•ฐ ## ๅฏ้€‰ๆ–‡ไปถไธŠไผ  { #optional-file-upload } -ๆ‚จๅฏไปฅ้€š่ฟ‡ไฝฟ็”จๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃๅนถๅฐ† None ไฝœไธบ้ป˜่ฎคๅ€ผ็š„ๆ–นๅผๅฐ†ไธ€ไธชๆ–‡ไปถๅ‚ๆ•ฐ่ฎพไธบๅฏ้€‰: +ๆ‚จๅฏไปฅ้€š่ฟ‡ไฝฟ็”จๆ ‡ๅ‡†็ฑปๅž‹ๆณจ่งฃๅนถๅฐ† `None` ไฝœไธบ้ป˜่ฎคๅ€ผ็š„ๆ–นๅผๅฐ†ไธ€ไธชๆ–‡ไปถๅ‚ๆ•ฐ่ฎพไธบๅฏ้€‰: {* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} @@ -143,7 +143,7 @@ HTML ่กจๅ•๏ผˆ`
`๏ผ‰ๅ‘ๆœๅŠกๅ™จๅ‘้€ๆ•ฐๆฎ็š„ๆ–นๅผ้€šๅธธไผšๅฏนๆ•ฐ ๆ‚จไนŸๅฏไปฅๅฐ† `File()` ไธŽ `UploadFile` ไธ€่ตทไฝฟ็”จ๏ผŒไพ‹ๅฆ‚๏ผŒ่ฎพ็ฝฎ้ขๅค–็š„ๅ…ƒๆ•ฐๆฎ: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## ๅคšๆ–‡ไปถไธŠไผ  { #multiple-file-uploads } @@ -153,7 +153,7 @@ FastAPI ๆ”ฏๆŒๅŒๆ—ถไธŠไผ ๅคšไธชๆ–‡ไปถใ€‚ ่ฆๅฎž็Žฐ่ฟ™ไธ€็‚น๏ผŒๅฃฐๆ˜Žไธ€ไธช็”ฑ `bytes` ๆˆ– `UploadFile` ็ป„ๆˆ็š„ๅˆ—่กจ๏ผˆ`List`๏ผ‰๏ผš -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} ๆŽฅๆ”ถ็š„ไนŸๆ˜ฏๅซ `bytes` ๆˆ– `UploadFile` ็š„ๅˆ—่กจ๏ผˆ`list`๏ผ‰ใ€‚ @@ -169,7 +169,7 @@ FastAPI ๆ”ฏๆŒๅŒๆ—ถไธŠไผ ๅคšไธชๆ–‡ไปถใ€‚ ๅ’Œไน‹ๅ‰็š„ๆ–นๅผไธ€ๆ ท๏ผŒไฝ ๅฏไปฅไธบ `File()` ่ฎพ็ฝฎ้ขๅค–ๅ‚ๆ•ฐ๏ผŒๅณไฝฟๆ˜ฏ `UploadFile`๏ผš -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## ๅฐ็ป“ { #recap } diff --git a/docs/zh/docs/tutorial/request-form-models.md b/docs/zh/docs/tutorial/request-form-models.md index 4eb98ea225..63759df086 100644 --- a/docs/zh/docs/tutorial/request-form-models.md +++ b/docs/zh/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ $ pip install python-multipart ไฝ ๅช้œ€ๅฃฐๆ˜Žไธ€ไธช **Pydantic ๆจกๅž‹**๏ผŒๅ…ถไธญๅŒ…ๅซไฝ ๅธŒๆœ›ๆŽฅๆ”ถ็š„**่กจๅ•ๅญ—ๆฎต**๏ผŒ็„ถๅŽๅฐ†ๅ‚ๆ•ฐๅฃฐๆ˜Žไธบ `Form`๏ผš -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** ๅฐ†ไปŽ่ฏทๆฑ‚ไธญ็š„**่กจๅ•ๆ•ฐๆฎ**ไธญ**ๆๅ–**ๅ‡บ**ๆฏไธชๅญ—ๆฎต**็š„ๆ•ฐๆฎ๏ผŒๅนถๆไพ›ไฝ ๅฎšไน‰็š„ Pydantic ๆจกๅž‹ใ€‚ @@ -48,7 +48,7 @@ $ pip install python-multipart ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹้…็ฝฎๆฅ `forbid` ไปปไฝ• `extra` ๅญ—ๆฎต๏ผš -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} ๅฆ‚ๆžœๅฎขๆˆท็ซฏๅฐ่ฏ•ๅ‘้€ไธ€ไบ›้ขๅค–็š„ๆ•ฐๆฎ๏ผŒไป–ไปฌๅฐ†ๆ”ถๅˆฐ**้”™่ฏฏ**ๅ“ๅบ”ใ€‚ diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md index 3c809868b2..484fcd5d6d 100644 --- a/docs/zh/docs/tutorial/request-forms-and-files.md +++ b/docs/zh/docs/tutorial/request-forms-and-files.md @@ -16,17 +16,17 @@ $ pip install python-multipart ## ๅฏผๅ…ฅ `File` ไธŽ `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## ๅฎšไน‰ `File` ไธŽ `Form` ๅ‚ๆ•ฐ { #define-file-and-form-parameters } ๅˆ›ๅปบๆ–‡ไปถๅ’Œ่กจๅ•ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๅ’Œ `Query` ไธ€ๆ ท๏ผš -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} ๆ–‡ไปถๅ’Œ่กจๅ•ๅญ—ๆฎตไฝœไธบ่กจๅ•ๆ•ฐๆฎไธŠไผ ไธŽๆŽฅๆ”ถใ€‚ -ๅฃฐๆ˜Žๆ–‡ไปถๅฏไปฅไฝฟ็”จ `bytes` ๆˆ– `UploadFile` ใ€‚ +ๅนถไธ”ไฝ ๅฏไปฅๅฐ†้ƒจๅˆ†ๆ–‡ไปถๅฃฐๆ˜Žไธบ `bytes`๏ผŒๅฐ†้ƒจๅˆ†ๆ–‡ไปถๅฃฐๆ˜Žไธบ `UploadFile`ใ€‚ /// warning | ่ญฆๅ‘Š diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md index 70eb93a260..1fc305a69c 100644 --- a/docs/zh/docs/tutorial/request-forms.md +++ b/docs/zh/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart ไปŽ `fastapi` ๅฏผๅ…ฅ `Form`๏ผš -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## ๅฎšไน‰ `Form` ๅ‚ๆ•ฐ { #define-form-parameters } ๅˆ›ๅปบ่กจๅ•ๅ‚ๆ•ฐ็š„ๆ–นๅผไธŽ `Body` ๆˆ– `Query` ็›ธๅŒ๏ผš -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} ไพ‹ๅฆ‚๏ผŒๅœจ OAuth2 ่ง„่Œƒ็š„ไธ€็งไฝฟ็”จๆ–นๅผ๏ผˆ็งฐไธบโ€œๅฏ†็ ๆตโ€๏ผ‰ไธญ๏ผŒ่ฆๆฑ‚ๅฐ† `username` ๅ’Œ `password` ไฝœไธบ่กจๅ•ๅญ—ๆฎตๅ‘้€ใ€‚ -spec ่ฆๆฑ‚่ฟ™ไบ›ๅญ—ๆฎตๅฟ…้กป็ฒพ็กฎๅ‘ฝๅไธบ `username` ๅ’Œ `password`๏ผŒๅนถไธ”ไฝœไธบ่กจๅ•ๅญ—ๆฎตๅ‘้€๏ผŒ่€Œไธๆ˜ฏ JSONใ€‚ +่ง„่Œƒ ่ฆๆฑ‚่ฟ™ไบ›ๅญ—ๆฎตๅฟ…้กป็ฒพ็กฎๅ‘ฝๅไธบ `username` ๅ’Œ `password`๏ผŒๅนถไธ”ไฝœไธบ่กจๅ•ๅญ—ๆฎตๅ‘้€๏ผŒ่€Œไธๆ˜ฏ JSONใ€‚ ไฝฟ็”จ `Form` ๅฏไปฅๅƒไฝฟ็”จ `Body`๏ผˆไปฅๅŠ `Query`ใ€`Path`ใ€`Cookie`๏ผ‰ไธ€ๆ ทๅฃฐๆ˜Ž็›ธๅŒ็š„้…็ฝฎ๏ผŒๅŒ…ๆ‹ฌๆ ก้ชŒใ€็คบไพ‹ใ€ๅˆซๅ๏ผˆไพ‹ๅฆ‚ๅฐ† `username` ๅ†™ๆˆ `user-name`๏ผ‰็ญ‰ใ€‚ diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md index 791eb66fb7..df0afa66f8 100644 --- a/docs/zh/docs/tutorial/response-model.md +++ b/docs/zh/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ FastAPI ๅœจๅ†…้ƒจ้…ๅˆ Pydantic ๅšไบ†ๅคš้กนๅค„็†๏ผŒ็กฎไฟไธไผšๆŠŠ็ฑป็ปงๆ‰ฟ ๆœ€ๅธธ่ง็š„ๆƒ…ๅ†ตๆ˜ฏ[็›ดๆŽฅ่ฟ”ๅ›ž Response๏ผŒ่ฏฆ่ง่ฟ›้˜ถๆ–‡ๆกฃ](../advanced/response-directly.md){.internal-link target=_blank}ใ€‚ -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} ่ฟ™ไธช็ฎ€ๅ•ๅœบๆ™ฏ FastAPI ไผš่‡ชๅŠจๅค„็†๏ผŒๅ› ไธบ่ฟ”ๅ›ž็ฑปๅž‹ๆณจ่งฃๆ˜ฏ `Response`๏ผˆๆˆ–ๅ…ถๅญ็ฑป๏ผ‰ใ€‚ @@ -193,7 +193,7 @@ FastAPI ๅœจๅ†…้ƒจ้…ๅˆ Pydantic ๅšไบ†ๅคš้กนๅค„็†๏ผŒ็กฎไฟไธไผšๆŠŠ็ฑป็ปงๆ‰ฟ ไฝ ไนŸๅฏไปฅๅœจ็ฑปๅž‹ๆณจ่งฃไธญไฝฟ็”จ `Response` ็š„ๅญ็ฑป๏ผš -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} ่ฟ™ๅŒๆ ทๅฏ่กŒ๏ผŒๅ› ไธบ `RedirectResponse` ๆ˜ฏ `Response` ็š„ๅญ็ฑป๏ผŒFastAPI ไผš่‡ชๅŠจๅค„็†่ฟ™ไธช็ฎ€ๅ•ๅœบๆ™ฏใ€‚ @@ -201,7 +201,7 @@ FastAPI ๅœจๅ†…้ƒจ้…ๅˆ Pydantic ๅšไบ†ๅคš้กนๅค„็†๏ผŒ็กฎไฟไธไผšๆŠŠ็ฑป็ปงๆ‰ฟ ไฝ†ๅฝ“ไฝ ่ฟ”ๅ›žๅ…ถไป–ไปปๆ„ๅฏน่ฑก๏ผˆๅฆ‚ๆ•ฐๆฎๅบ“ๅฏน่ฑก๏ผ‰่€Œๅฎƒไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ็ฑปๅž‹๏ผŒๅนถๅœจๅ‡ฝๆ•ฐไธญๆŒ‰ๆญค่ฟ›่กŒไบ†ๆณจ่งฃๆ—ถ๏ผŒFastAPI ไผšๅฐ่ฏ•ๅŸบไบŽ่ฏฅ็ฑปๅž‹ๆณจ่งฃๅˆ›ๅปบไธ€ไธช Pydantic ๅ“ๅบ”ๆจกๅž‹๏ผŒไฝ†ไผšๅคฑ่ดฅใ€‚ -ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธชๅœจๅคšไธช็ฑปๅž‹ไน‹้—ด็š„่”ๅˆ็ฑปๅž‹๏ผŒๅ…ถไธญไธ€ไธชๆˆ–ๅคšไธชไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ็ฑปๅž‹๏ผŒไนŸไผšๅ‘็”ŸๅŒๆ ท็š„ๆƒ…ๅ†ต๏ผŒไพ‹ๅฆ‚่ฟ™ไธชไผšๅคฑ่ดฅ ๐Ÿ’ฅ๏ผš +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ไธชๅœจๅคšไธช็ฑปๅž‹ไน‹้—ด็š„่”ๅˆ็ฑปๅž‹๏ผŒๅ…ถไธญไธ€ไธชๆˆ–ๅคšไธชไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ็ฑปๅž‹๏ผŒไนŸไผšๅ‘็”ŸๅŒๆ ท็š„ๆƒ…ๅ†ต๏ผŒไพ‹ๅฆ‚่ฟ™ไธชไผšๅคฑ่ดฅ ๐Ÿ’ฅ๏ผš {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md index 3630de2803..266f919ba1 100644 --- a/docs/zh/docs/tutorial/response-status-code.md +++ b/docs/zh/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * ็ญ‰... -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | ๆณจๆ„ @@ -74,7 +74,7 @@ FastAPI ๅฏไปฅ่ฟ›่กŒ่ฏ†ๅˆซ๏ผŒๅนถ็”Ÿๆˆ่กจๆ˜Žๆ— ๅ“ๅบ”ไฝ“็š„ OpenAPI ๆ–‡ๆกฃใ€‚ ๅ†็œ‹ไธ‹ไน‹ๅ‰็š„ไพ‹ๅญ๏ผš -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` ่กจ็คบโ€œๅทฒๅˆ›ๅปบโ€็š„็Šถๆ€็ ใ€‚ @@ -82,7 +82,7 @@ FastAPI ๅฏไปฅ่ฟ›่กŒ่ฏ†ๅˆซ๏ผŒๅนถ็”Ÿๆˆ่กจๆ˜Žๆ— ๅ“ๅบ”ไฝ“็š„ OpenAPI ๆ–‡ๆกฃใ€‚ ๅฏไปฅไฝฟ็”จ `fastapi.status` ไธญ็š„ๅฟซๆทๅ˜้‡ใ€‚ -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} ่ฟ™ๅชๆ˜ฏไธ€็งๅฟซๆทๆ–นๅผ๏ผŒๅ…ทๆœ‰็›ธๅŒ็š„ๆ•ฐๅญ—ไปฃ็ ๏ผŒไฝ†ๅฎƒๅฏไปฅไฝฟ็”จ็ผ–่พ‘ๅ™จ็š„่‡ชๅŠจ่กฅๅ…จๅŠŸ่ƒฝ๏ผš diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md index 818ff5087b..ec1fc29e55 100644 --- a/docs/zh/docs/tutorial/schema-extra-example.md +++ b/docs/zh/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ OpenAPI 3.1.0๏ผˆ่‡ช FastAPI 0.99.0 ่ตทไฝฟ็”จ๏ผ‰ๅขžๅŠ ไบ†ๅฏน `examples` ็š„ๆ”ฏๆŒ ่ฟ™ๆ ทๅšๆ—ถ๏ผŒ่ฟ™ไบ›็คบไพ‹ไผšๆˆไธบ่ฏฅ่ฏทๆฑ‚ไฝ“ๆ•ฐๆฎๅ†…้ƒจ JSON Schema ็š„ไธ€้ƒจๅˆ†ใ€‚ -ไธ่ฟ‡๏ผŒๅœจๆ’ฐๅ†™ๆœฌๆ–‡ๆ—ถ๏ผŒ็”จไบŽๅฑ•็คบๆ–‡ๆกฃ UI ็š„ Swagger UI ๅนถไธๆ”ฏๆŒๆ˜พ็คบ JSON Schema ไธญๆ•ฐๆฎ็š„ๅคšไธช็คบไพ‹ใ€‚ไฝ†่ฏท็ปง็ปญ้˜…่ฏป๏ผŒไธ‹้ขๆœ‰ไธ€็งๅ˜้€šๆ–นๆณ•ใ€‚ +ไธ่ฟ‡๏ผŒๅœจๆ’ฐๅ†™ๆœฌๆ–‡ๆ—ถ๏ผŒ็”จไบŽๅฑ•็คบๆ–‡ๆกฃ UI ็š„ Swagger UI ๅนถไธๆ”ฏๆŒๆ˜พ็คบ JSON Schema ไธญๆ•ฐๆฎ็š„ๅคšไธช็คบไพ‹ใ€‚ไฝ†่ฏท็ปง็ปญ้˜…่ฏป๏ผŒไธ‹้ขๆœ‰ไธ€็งๅ˜้€šๆ–นๆณ•ใ€‚ ### OpenAPI ็‰นๅฎš็š„ `examples` { #openapi-specific-examples } diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md index 43b7c66579..8b1aeb70b3 100644 --- a/docs/zh/docs/tutorial/security/first-steps.md +++ b/docs/zh/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ ๆŠŠไธ‹้ข็š„็คบไพ‹ไปฃ็ ๅคๅˆถๅˆฐ `main.py`๏ผš -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## ่ฟ่กŒ { #run-it } @@ -132,7 +132,7 @@ OAuth2 ็š„่ฎพ่ฎก็›ฎๆ ‡ๆ˜ฏ่ฎฉๅŽ็ซฏๆˆ– API ไธŽ่ดŸ่ดฃ็”จๆˆท่ฎค่ฏ็š„ๆœๅŠกๅ™จ่งฃ ๅˆ›ๅปบ `OAuth2PasswordBearer` ็ฑปๅฎžไพ‹ๆ—ถ๏ผŒ้œ€่ฆไผ ๅ…ฅ `tokenUrl` ๅ‚ๆ•ฐใ€‚่ฏฅๅ‚ๆ•ฐๅŒ…ๅซๅฎขๆˆท็ซฏ๏ผˆ่ฟ่กŒๅœจ็”จๆˆทๆต่งˆๅ™จไธญ็š„ๅ‰็ซฏ๏ผ‰็”จๆฅๅ‘้€ `username` ๅ’Œ `password` ไปฅ่Žทๅ–ไปค็‰Œ็š„ URLใ€‚ -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | ๆ็คบ @@ -170,7 +170,7 @@ oauth2_scheme(some, parameters) ็Žฐๅœจไฝ ๅฏไปฅ้€š่ฟ‡ `Depends` ๅฐ† `oauth2_scheme` ไฝœไธบไพ่ต–ไผ ๅ…ฅใ€‚ -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ่ฏฅไพ่ต–ไผšๆไพ›ไธ€ไธช `str`๏ผŒ่ต‹ๅ€ผ็ป™*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*็š„ๅ‚ๆ•ฐ `token`ใ€‚ diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md index c14bba28af..814ff2c822 100644 --- a/docs/zh/docs/tutorial/security/get-current-user.md +++ b/docs/zh/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ ไธŠไธ€็ซ ไธญ๏ผŒ๏ผˆๅŸบไบŽไพ่ต–ๆณจๅ…ฅ็ณป็ปŸ็š„๏ผ‰ๅฎ‰ๅ…จ็ณป็ปŸๅ‘*่ทฏๅพ„ๆ“ไฝœๅ‡ฝๆ•ฐ*ไผ ้€’ไบ† `str` ็ฑปๅž‹็š„ `token`๏ผš -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ไฝ†่ฟ™ๅนถไธๅฎž็”จใ€‚ diff --git a/docs/zh/docs/tutorial/security/index.md b/docs/zh/docs/tutorial/security/index.md index 589f93c3e9..a4c3521105 100644 --- a/docs/zh/docs/tutorial/security/index.md +++ b/docs/zh/docs/tutorial/security/index.md @@ -10,7 +10,7 @@ ไฝ†้ฆ–ๅ…ˆ๏ผŒ่ฎฉๆˆ‘ไปฌๆฅ็œ‹ไธ€ไบ›ๅฐ็š„ๆฆ‚ๅฟตใ€‚ -## ๆฒกๆœ‰ๆ—ถ้—ด๏ผŸ { #in-a-hurry } +## ่ตถๆ—ถ้—ด { #in-a-hurry } ๅฆ‚ๆžœไฝ ไธๅ…ณๅฟƒ่ฟ™ไบ›ๆœฏ่ฏญ๏ผŒ่€Œๅช้œ€่ฆ*็ซ‹ๅณ*้€š่ฟ‡ๅŸบไบŽ็”จๆˆทๅๅ’Œๅฏ†็ ็š„่บซไปฝ่ฎค่ฏๆฅๅขžๅŠ ๅฎ‰ๅ…จๆ€ง๏ผŒ่ฏท่ทณ่ฝฌๅˆฐๆŽฅไธ‹ๆฅ็š„็ซ ่Š‚ใ€‚ diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index c7eb9bd907..b5ccfd3e3f 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ pwdlib ไนŸๆ”ฏๆŒ bcrypt ๅ“ˆๅธŒ็ฎ—ๆณ•๏ผŒไฝ†ไธๅŒ…ๅซ้—็•™็ฎ—ๆณ•โ€”โ€”ๅฆ‚ๆžœ้œ€ ๅ†ๅˆ›ๅปบไธ€ไธชๅทฅๅ…ทๅ‡ฝๆ•ฐๆฅ่ฟ›่กŒ่บซไปฝ้ชŒ่ฏๅนถ่ฟ”ๅ›ž็”จๆˆทใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +ๅฝ“ไฝฟ็”จไธ€ไธชๅœจๆ•ฐๆฎๅบ“ไธญไธๅญ˜ๅœจ็š„็”จๆˆทๅ่ฐƒ็”จ `authenticate_user` ๆ—ถ๏ผŒๆˆ‘ไปฌไป็„ถไผš้’ˆๅฏนไธ€ไธช่™šๆ‹Ÿๅ“ˆๅธŒ่ฟ่กŒ `verify_password`ใ€‚ + +่ฟ™ๅฏไปฅ็กฎไฟๆ— ่ฎบ็”จๆˆทๅๆ˜ฏๅฆๆœ‰ๆ•ˆ๏ผŒ็ซฏ็‚น็š„ๅ“ๅบ”ๆ—ถ้—ดๅคง่‡ด็›ธๅŒ๏ผŒไปŽ่€Œ้˜ฒๆญขๅฏ็”จไบŽๆžšไธพๅทฒๅญ˜ๅœจ็”จๆˆทๅ็š„โ€œๆ—ถ้—ดๆ”ปๅ‡ปโ€๏ผˆtiming attacks๏ผ‰ใ€‚ /// note | ๆณจๆ„ @@ -152,7 +156,7 @@ $ openssl rand -hex 32 ๅˆ›ๅปบไธ€ไธช็”Ÿๆˆๆ–ฐ่ฎฟ้—ฎไปค็‰Œ็š„ๅทฅๅ…ทๅ‡ฝๆ•ฐใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## ๆ›ดๆ–ฐไพ่ต–้กน { #update-the-dependencies } @@ -162,7 +166,7 @@ $ openssl rand -hex 32 ๅฆ‚ๆžœไปค็‰Œๆ— ๆ•ˆ๏ผŒ็ซ‹ๅณ่ฟ”ๅ›žไธ€ไธช HTTP ้”™่ฏฏใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## ๆ›ดๆ–ฐ `/token` ่ทฏๅพ„ๆ“ไฝœ { #update-the-token-path-operation } @@ -170,7 +174,7 @@ $ openssl rand -hex 32 ๅˆ›ๅปบไธ€ไธช็œŸๆญฃ็š„ JWT ่ฎฟ้—ฎไปค็‰Œๅนถ่ฟ”ๅ›žๅฎƒใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### ๅ…ณไบŽ JWT โ€œไธป้ข˜โ€ `sub` ็š„ๆŠ€ๆœฏ็ป†่Š‚ { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md index 3037a983b3..95f708ae6a 100644 --- a/docs/zh/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh/docs/tutorial/security/simple-oauth2.md @@ -6,9 +6,9 @@ ้ฆ–ๅ…ˆ๏ผŒไฝฟ็”จ **FastAPI** ๅฎ‰ๅ…จๅทฅๅ…ท่Žทๅ– `username` ๅ’Œ `password`ใ€‚ -OAuth2 ่ง„่Œƒ่ฆๆฑ‚ไฝฟ็”จ**ๅฏ†็ ๆต**ๆ—ถ๏ผŒๅฎขๆˆท็ซฏๆˆ–็”จๆˆทๅฟ…้กปไปฅ่กจๅ•ๆ•ฐๆฎๅฝขๅผๅ‘้€ `username` ๅ’Œ `password` ๅญ—ๆฎตใ€‚ +OAuth2 ่ง„่Œƒ่ฆๆฑ‚ไฝฟ็”จโ€œๅฏ†็ ๆตโ€ๆ—ถ๏ผŒๅฎขๆˆท็ซฏๆˆ–็”จๆˆทๅฟ…้กปไปฅ่กจๅ•ๆ•ฐๆฎๅฝขๅผๅ‘้€ `username` ๅ’Œ `password` ๅญ—ๆฎตใ€‚ -ๅนถไธ”๏ผŒ่ฟ™ไธคไธชๅญ—ๆฎตๅฟ…้กปๅ‘ฝๅไธบ `username` ๅ’Œ `password` ๏ผŒไธ่ƒฝไฝฟ็”จ `user-name` ๆˆ– `email` ็ญ‰ๅ…ถๅฎƒๅ็งฐใ€‚ +ๅนถไธ”๏ผŒ่ฟ™ไธคไธชๅญ—ๆฎตๅฟ…้กปๅ‘ฝๅไธบ `username` ๅ’Œ `password`๏ผŒไธ่ƒฝไฝฟ็”จ `user-name` ๆˆ– `email` ็ญ‰ๅ…ถๅฎƒๅ็งฐใ€‚ ไธ่ฟ‡ไนŸไธ็”จๆ‹…ๅฟƒ๏ผŒๅ‰็ซฏไปๅฏไปฅๆ˜พ็คบ็ปˆ็ซฏ็”จๆˆทๆ‰€้œ€็š„ๅ็งฐใ€‚ @@ -74,7 +74,7 @@ OAuth2 ไธญ๏ผŒ**ไฝœ็”จๅŸŸ**ๅชๆ˜ฏๅฃฐๆ˜ŽๆŒ‡ๅฎšๆƒ้™็š„ๅญ—็ฌฆไธฒใ€‚ /// info | ไฟกๆฏ -`OAuth2PasswordRequestForm` ไธŽ `OAuth2PasswordBearer` ไธ€ๆ ท๏ผŒ้ƒฝไธๆ˜ฏ FastAPI ็š„็‰นๆฎŠ็ฑปใ€‚ +`OAuth2PasswordRequestForm` ๅนถไธๅƒ `OAuth2PasswordBearer` ้‚ฃๆ ทๆ˜ฏ **FastAPI** ็š„็‰นๆฎŠ็ฑปใ€‚ **FastAPI** ๆŠŠ `OAuth2PasswordBearer` ่ฏ†ๅˆซไธบๅฎ‰ๅ…จๆ–นๆกˆใ€‚ๅ› ๆญค๏ผŒๅฏไปฅ้€š่ฟ‡่ฟ™็งๆ–นๅผๆŠŠๅฎƒๆทปๅŠ ่‡ณ OpenAPIใ€‚ @@ -200,7 +200,7 @@ UserInDB( ๆญคๅค„่ฟ”ๅ›žๅ€ผไธบ `Bearer` ็š„ๅ“ๅบ”ๅคด `WWW-Authenticate` ไนŸๆ˜ฏ่ง„่Œƒ็š„ไธ€้ƒจๅˆ†ใ€‚ -ไปปไฝ• 401**UNAUTHORIZED**HTTP๏ผˆ้”™่ฏฏ๏ผ‰็Šถๆ€็ ้ƒฝๅบ”่ฟ”ๅ›ž `WWW-Authenticate` ๅ“ๅบ”ๅคดใ€‚ +ไปปไฝ• 401โ€œUNAUTHORIZEDโ€HTTP๏ผˆ้”™่ฏฏ๏ผ‰็Šถๆ€็ ้ƒฝๅบ”่ฟ”ๅ›ž `WWW-Authenticate` ๅ“ๅบ”ๅคดใ€‚ ๆœฌไพ‹ไธญ๏ผŒๅ› ไธบไฝฟ็”จ็š„ๆ˜ฏ Bearer Token๏ผŒ่ฏฅๅ“ๅบ”ๅคด็š„ๅ€ผๅบ”ไธบ `Bearer`ใ€‚ @@ -220,7 +220,7 @@ UserInDB( ### ่บซไปฝ้ชŒ่ฏ { #authenticate } -็‚นๅ‡ป**Authorize**ๆŒ‰้’ฎใ€‚ +็‚นๅ‡ปโ€œAuthorizeโ€ๆŒ‰้’ฎใ€‚ ไฝฟ็”จไปฅไธ‹ๅ‡ญ่ฏ๏ผš @@ -286,4 +286,4 @@ UserInDB( ๅ”ฏไธ€ๆฌ ็ผบ็š„ๆ˜ฏ๏ผŒๅฎƒไป็„ถไธๆ˜ฏ็œŸ็š„**ๅฎ‰ๅ…จ**ใ€‚ -ไธ‹ไธ€็ซ ๏ผŒไป‹็ปไฝฟ็”จๅฏ†็ ๅ“ˆๅธŒๆ”ฏๆŒๅบ“ไธŽ JWT ไปค็‰Œๅฎž็Žฐ็œŸๆญฃ็š„ๅฎ‰ๅ…จๆœบๅˆถใ€‚ +ไธ‹ไธ€็ซ ไฝ ๅฐ†็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จๅฎ‰ๅ…จ็š„ๅฏ†็ ๅ“ˆๅธŒๅบ“ๅ’Œ JWT ไปค็‰Œใ€‚ diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md index 944e960a76..ef0b7c4601 100644 --- a/docs/zh/docs/tutorial/sql-databases.md +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -216,7 +216,7 @@ $ fastapi dev main.py ๅฎƒๅŒ…ๅซไธŽ `HeroBase` ็›ธๅŒ็š„ๅญ—ๆฎต๏ผŒๅ› ๆญคไธไผšๅŒ…ๆ‹ฌ `secret_name`ใ€‚ -็ปˆไบŽ๏ผŒๆˆ‘ไปฌ่‹ฑ้›„๏ผˆhero๏ผ‰็š„่บซไปฝๅพ—ๅˆฐไบ†ไฟๆŠค๏ผ๐Ÿฅท +็ปˆไบŽ๏ผŒๆˆ‘ไปฌ่‹ฑ้›„็š„่บซไปฝๅพ—ๅˆฐไบ†ไฟๆŠค๏ผ๐Ÿฅท ๅฎƒ่ฟ˜้‡ๆ–ฐๅฃฐๆ˜Žไบ† `id: int`ใ€‚่ฟ™ๆ ทๆˆ‘ไปฌไพฟไธŽ API ๅฎขๆˆท็ซฏๅปบ็ซ‹ไบ†ไธ€็ง**็บฆๅฎš**๏ผŒไฝฟไป–ไปฌๅง‹็ปˆๅฏไปฅๆœŸๅพ… `id` ๅญ˜ๅœจๅนถไธ”ๆ˜ฏไธ€ไธชๆ•ดๆ•ฐ `int`๏ผˆๆฐธ่ฟœไธไผšๆ˜ฏ `None`๏ผ‰ใ€‚ diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index 5b2f920b2c..1f4ebae9ab 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -7,9 +7,9 @@ * ๅฏผๅ…ฅ `StaticFiles`ใ€‚ * ๅฐ†ไธ€ไธช `StaticFiles()` ๅฎžไพ‹โ€œๆŒ‚่ฝฝโ€๏ผˆMount๏ผ‰ๅˆฐๆŒ‡ๅฎš่ทฏๅพ„ใ€‚ -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} -/// note | ๆณจๆ„ +/// note | ๆŠ€ๆœฏ็ป†่Š‚ ไฝ ไนŸๅฏไปฅ็”จ `from starlette.staticfiles import StaticFiles`ใ€‚ diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 1aff9f799c..7eb32f19e6 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -30,7 +30,7 @@ $ pip install httpx ไธบไฝ ้œ€่ฆๆฃ€ๆŸฅ็š„ๅœฐๆ–น็”จๆ ‡ๅ‡†็š„Python่กจ่พพๅผๅ†™ไธช็ฎ€ๅ•็š„ `assert` ่ฏญๅฅ๏ผˆ้‡็”ณ๏ผŒๆ ‡ๅ‡†็š„`pytest`๏ผ‰ใ€‚ -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ๆ็คบ @@ -76,7 +76,7 @@ $ pip install httpx ๅœจ `main.py` ๆ–‡ไปถไธญไฝ ๆœ‰ไธ€ไธช **FastAPI** app: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### ๆต‹่ฏ•ๆ–‡ไปถ { #testing-file } @@ -92,7 +92,7 @@ $ pip install httpx ๅ› ไธบ่ฟ™ๆ–‡ไปถๅœจๅŒไธ€ไธชๅŒ…ไธญ๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅ้€š่ฟ‡็›ธๅฏนๅฏผๅ…ฅไปŽ `main` ๆจกๅ—๏ผˆ`main.py`๏ผ‰ๅฏผๅ…ฅ`app`ๅฏน่ฑก๏ผš -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...็„ถๅŽๆต‹่ฏ•ไปฃ็ ๅ’Œไน‹ๅ‰ไธ€ๆ ท็š„ใ€‚ diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index 29e272b59a..60fb9e23f6 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -30,7 +30,7 @@ ้ฆ–ๅ…ˆ๏ผŒไธบไฝ ็š„ๅทฅ็จ‹ๅˆ›ๅปบไธ€ไธช็›ฎๅฝ•ใ€‚ -ๆˆ‘ (ๆŒ‡ๅŽŸไฝœ่€… โ€”โ€” ่ฏ‘่€…ๆณจ) ้€šๅธธไผšๅœจๆˆ‘็š„ไธป็›ฎๅฝ•ไธ‹ๅˆ›ๅปบไธ€ไธชๅไธบ `code` ็š„็›ฎๅฝ•ใ€‚ +ๆˆ‘้€šๅธธไผšๅœจๆˆ‘็š„ไธป็›ฎๅฝ•ไธ‹ๅˆ›ๅปบไธ€ไธชๅไธบ `code` ็š„็›ฎๅฝ•ใ€‚ ๅœจ่ฟ™ไธช็›ฎๅฝ•ไธ‹๏ผŒๆˆ‘ๅ†ไธบๆฏไธชๅทฅ็จ‹ๅˆ›ๅปบไธ€ไธช็›ฎๅฝ•ใ€‚ @@ -53,7 +53,7 @@ $ cd awesome-project ## ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒ { #create-a-virtual-environment } -ๅœจๅผ€ๅง‹ไธ€ไธช Python ๅทฅ็จ‹็š„**็ฌฌไธ€ๆ—ถ้—ด**๏ผŒ**ๅœจไฝ ็š„ๅทฅ็จ‹ๅ†…้ƒจ**ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒใ€‚ +ๅœจๅผ€ๅง‹ไธ€ไธช Python ๅทฅ็จ‹็š„**็ฌฌไธ€ๆ—ถ้—ด**๏ผŒ**ๅœจไฝ ็š„ๅทฅ็จ‹ๅ†…้ƒจ**ๅˆ›ๅปบไธ€ไธช่™šๆ‹Ÿ็Žฏๅขƒใ€‚ /// tip | ๆ็คบ @@ -316,7 +316,7 @@ $ echo "*" > .venv/.gitignore ### ็›ดๆŽฅๅฎ‰่ฃ…ๅŒ… { #install-packages-directly } -ๅฆ‚ๆžœไฝ ๆ€ฅไบŽๅฎ‰่ฃ…๏ผŒไธๆƒณไฝฟ็”จๆ–‡ไปถๆฅๅฃฐๆ˜Žๅทฅ็จ‹็š„่ฝฏไปถๅŒ…ไพ่ต–๏ผŒๆ‚จๅฏไปฅ็›ดๆŽฅๅฎ‰่ฃ…ๅฎƒไปฌใ€‚ +ๅฆ‚ๆžœไฝ ๆ€ฅไบŽๅฎ‰่ฃ…๏ผŒไธๆƒณไฝฟ็”จๆ–‡ไปถๆฅๅฃฐๆ˜Žๅทฅ็จ‹็š„่ฝฏไปถๅŒ…ไพ่ต–๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅฎ‰่ฃ…ๅฎƒไปฌใ€‚ /// tip | ๆ็คบ @@ -412,7 +412,7 @@ Hello World ## ้…็ฝฎ็ผ–่พ‘ๅ™จ { #configure-your-editor } -ไฝ ๅฏ่ƒฝไผš็”จๅˆฐ็ผ–่พ‘ๅ™จ๏ผˆๅณ IDE โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰๏ผŒ่ฏท็กฎไฟ้…็ฝฎๅฎƒไฝฟ็”จไธŽไฝ ๅˆ›ๅปบ็š„็›ธๅŒ็š„่™šๆ‹Ÿ็Žฏๅขƒ๏ผˆๅฎƒๅฏ่ƒฝไผš่‡ชๅŠจๆฃ€ๆต‹ๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ่Žทๅพ—่‡ชๅŠจ่กฅๅ…จๅ’Œๅ†…่”้”™่ฏฏๆ็คบใ€‚ +ไฝ ๅฏ่ƒฝไผš็”จๅˆฐ็ผ–่พ‘ๅ™จ๏ผŒ่ฏท็กฎไฟ้…็ฝฎๅฎƒไฝฟ็”จไธŽไฝ ๅˆ›ๅปบ็š„็›ธๅŒ็š„่™šๆ‹Ÿ็Žฏๅขƒ๏ผˆๅฎƒๅฏ่ƒฝไผš่‡ชๅŠจๆฃ€ๆต‹ๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ่Žทๅพ—่‡ชๅŠจ่กฅๅ…จๅ’Œๅ†…่”้”™่ฏฏๆ็คบใ€‚ ไพ‹ๅฆ‚๏ผš @@ -437,7 +437,7 @@ $ deactivate
-่ฟ™ๆ ท๏ผŒๅฝ“ไฝ ่ฟ่กŒ `python` ๆ—ถ๏ผŒๅฎƒไธไผšๅฐ่ฏ•ไปŽๅฎ‰่ฃ…ไบ†่ฝฏไปถๅŒ…็š„่™šๆ‹Ÿ็Žฏๅขƒไธญ่ฟ่กŒใ€‚๏ผˆๅณ๏ผŒๅฎƒๅฐ†ไธๅ†ไผšๅฐ่ฏ•ไปŽ่™šๆ‹Ÿ็Žฏๅขƒไธญ่ฟ่กŒ๏ผŒไนŸไธไผšไฝฟ็”จๅ…ถไธญๅฎ‰่ฃ…็š„่ฝฏไปถๅŒ…ใ€‚โ€”โ€” ่ฏ‘่€…ๆณจ๏ผ‰ +่ฟ™ๆ ท๏ผŒๅฝ“ไฝ ่ฟ่กŒ `python` ๆ—ถ๏ผŒๅฎƒไธไผšๅฐ่ฏ•ไปŽ้‚ฃไธช่™šๆ‹Ÿ็ŽฏๅขƒๅŠๅ…ถๅทฒๅฎ‰่ฃ…็š„่ฝฏไปถๅŒ…ไธญ่ฟ่กŒใ€‚ ## ๅผ€ๅง‹ๅทฅไฝœ { #ready-to-work } From 7dbdb11fb08fc6d379e591a7d4d65e7125d5aaaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 13:38:24 +0000 Subject: [PATCH 228/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ae5bef77fe..af7e7f27d1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for uk (update-all). PR [#14914](https://github.com/fastapi/fastapi/pull/14914) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-all). PR [#14913](https://github.com/fastapi/fastapi/pull/14913) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). From dd50de120582d1fe56cdb51ef0808ffc918c49d5 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 14:41:41 +0100 Subject: [PATCH 229/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(update-all=20and=20add-missing)=20(#14911)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/es/docs/advanced/additional-responses.md | 4 +- .../es/docs/advanced/advanced-dependencies.md | 8 +- .../es/docs/advanced/advanced-python-types.md | 61 ++++++ docs/es/docs/advanced/async-tests.md | 8 +- docs/es/docs/advanced/behind-a-proxy.md | 12 +- docs/es/docs/advanced/custom-response.md | 34 ++-- docs/es/docs/advanced/dataclasses.md | 2 +- docs/es/docs/advanced/events.md | 12 +- docs/es/docs/advanced/generate-clients.md | 10 +- docs/es/docs/advanced/middleware.md | 8 +- docs/es/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 4 +- docs/es/docs/advanced/response-cookies.md | 4 +- docs/es/docs/advanced/response-directly.md | 2 +- docs/es/docs/advanced/response-headers.md | 4 +- .../docs/advanced/security/http-basic-auth.md | 6 +- docs/es/docs/advanced/settings.md | 20 +- docs/es/docs/advanced/sub-applications.md | 6 +- docs/es/docs/advanced/templates.md | 4 +- docs/es/docs/advanced/testing-dependencies.md | 6 +- docs/es/docs/advanced/testing-events.md | 4 +- docs/es/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/es/docs/advanced/websockets.md | 8 +- docs/es/docs/advanced/wsgi.md | 2 +- docs/es/docs/alternatives.md | 16 +- docs/es/docs/async.md | 10 +- docs/es/docs/deployment/cloud.md | 2 +- docs/es/docs/deployment/concepts.md | 2 +- docs/es/docs/deployment/docker.md | 10 +- docs/es/docs/deployment/fastapicloud.md | 4 +- docs/es/docs/deployment/https.md | 2 +- docs/es/docs/deployment/manually.md | 2 +- docs/es/docs/features.md | 16 +- docs/es/docs/help-fastapi.md | 6 +- .../authentication-error-status-code.md | 2 +- docs/es/docs/how-to/conditional-openapi.md | 2 +- docs/es/docs/how-to/configure-swagger-ui.md | 12 +- docs/es/docs/how-to/custom-docs-ui-assets.md | 14 +- docs/es/docs/how-to/extending-openapi.md | 10 +- docs/es/docs/how-to/graphql.md | 2 +- .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/es/docs/how-to/testing-database.md | 4 +- docs/es/docs/index.md | 10 +- docs/es/docs/project-generation.md | 2 +- docs/es/docs/python-types.md | 188 ++++-------------- docs/es/docs/translation-banner.md | 11 + docs/es/docs/tutorial/background-tasks.md | 6 +- docs/es/docs/tutorial/bigger-applications.md | 26 +-- docs/es/docs/tutorial/body-multiple-params.md | 6 - docs/es/docs/tutorial/body-nested-models.md | 4 +- docs/es/docs/tutorial/body.md | 6 +- docs/es/docs/tutorial/cookie-param-models.md | 8 +- docs/es/docs/tutorial/cors.md | 3 +- docs/es/docs/tutorial/debugging.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +-- ...pendencies-in-path-operation-decorators.md | 8 +- .../dependencies/dependencies-with-yield.md | 25 ++- .../dependencies/global-dependencies.md | 2 +- docs/es/docs/tutorial/dependencies/index.md | 2 +- .../tutorial/dependencies/sub-dependencies.md | 8 +- docs/es/docs/tutorial/encoder.md | 2 +- docs/es/docs/tutorial/extra-models.md | 8 +- docs/es/docs/tutorial/first-steps.md | 18 +- docs/es/docs/tutorial/handling-errors.md | 16 +- docs/es/docs/tutorial/metadata.md | 12 +- docs/es/docs/tutorial/middleware.md | 4 +- .../tutorial/path-operation-configuration.md | 8 +- .../path-params-numeric-validations.md | 26 +-- docs/es/docs/tutorial/path-params.md | 28 +-- .../tutorial/query-params-str-validations.md | 78 +++----- docs/es/docs/tutorial/query-params.md | 6 +- docs/es/docs/tutorial/request-files.md | 16 +- docs/es/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/es/docs/tutorial/request-forms.md | 8 +- docs/es/docs/tutorial/response-model.md | 8 +- docs/es/docs/tutorial/response-status-code.md | 8 +- docs/es/docs/tutorial/schema-extra-example.md | 2 +- docs/es/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/es/docs/tutorial/security/oauth2-jwt.md | 12 +- docs/es/docs/tutorial/sql-databases.md | 4 +- docs/es/docs/tutorial/static-files.md | 2 +- docs/es/docs/tutorial/testing.md | 6 +- docs/es/docs/virtual-environments.md | 8 +- 87 files changed, 468 insertions(+), 538 deletions(-) create mode 100644 docs/es/docs/advanced/advanced-python-types.md create mode 100644 docs/es/docs/translation-banner.md diff --git a/docs/es/docs/advanced/additional-responses.md b/docs/es/docs/advanced/additional-responses.md index d0baa97a45..030f8dcc5a 100644 --- a/docs/es/docs/advanced/additional-responses.md +++ b/docs/es/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ Cada uno de esos `dict`s de response puede tener una clave `model`, conteniendo Por ejemplo, para declarar otro response con un cรณdigo de estado `404` y un modelo Pydantic `Message`, puedes escribir: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Nota @@ -203,7 +203,7 @@ Por ejemplo, puedes declarar un response con un cรณdigo de estado `404` que usa Y un response con un cรณdigo de estado `200` que usa tu `response_model`, pero incluye un `example` personalizado: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Todo se combinarรก e incluirรก en tu OpenAPI, y se mostrarรก en la documentaciรณn de la API: diff --git a/docs/es/docs/advanced/advanced-dependencies.md b/docs/es/docs/advanced/advanced-dependencies.md index 622a2caa26..81d8d19bbe 100644 --- a/docs/es/docs/advanced/advanced-dependencies.md +++ b/docs/es/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ No la clase en sรญ (que ya es un callable), sino una instance de esa clase. Para hacer eso, declaramos un mรฉtodo `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} En este caso, este `__call__` es lo que **FastAPI** usarรก para comprobar parรกmetros adicionales y sub-dependencias, y es lo que llamarรก para pasar un valor al parรกmetro en tu *path operation function* mรกs adelante. @@ -26,7 +26,7 @@ En este caso, este `__call__` es lo que **FastAPI** usarรก para comprobar parรกm Y ahora, podemos usar `__init__` para declarar los parรกmetros de la instance que podemos usar para "parametrizar" la dependencia: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} En este caso, **FastAPI** nunca tocarรก ni se preocuparรก por `__init__`, lo usaremos directamente en nuestro cรณdigo. @@ -34,7 +34,7 @@ En este caso, **FastAPI** nunca tocarรก ni se preocuparรก por `__init__`, lo usa Podrรญamos crear una instance de esta clase con: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} Y de esa manera podemos "parametrizar" nuestra dependencia, que ahora tiene `"bar"` dentro de ella, como el atributo `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") ...y pasarรก lo que eso retorne como el valor de la dependencia en nuestra *path operation function* como el parรกmetro `fixed_content_included`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | Consejo diff --git a/docs/es/docs/advanced/advanced-python-types.md b/docs/es/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..a18c5d6cc8 --- /dev/null +++ b/docs/es/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Tipos avanzados de Python { #advanced-python-types } + +Aquรญ tienes algunas ideas adicionales que podrรญan ser รบtiles al trabajar con tipos de Python. + +## Usar `Union` u `Optional` { #using-union-or-optional } + +Si por alguna razรณn tu cรณdigo no puede usar `|`, por ejemplo si no estรก en una anotaciรณn de tipos sino en algo como `response_model=`, en lugar de usar la barra vertical (`|`) puedes usar `Union` de `typing`. + +Por ejemplo, podrรญas declarar que algo podrรญa ser un `str` o `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` tambiรฉn tiene un atajo para declarar que algo podrรญa ser `None`, con `Optional`. + +Aquรญ va un Consejo desde mi punto de vista muy subjetivo: + +* ๐Ÿšจ Evita usar `Optional[SomeType]` +* En su lugar โœจ **usa `Union[SomeType, None]`** โœจ. + +Ambas son equivalentes y por debajo son lo mismo, pero recomendarรญa `Union` en lugar de `Optional` porque la palabra "**optional**" parecerรญa implicar que el valor es opcional, y en realidad significa "puede ser `None`", incluso si no es opcional y sigue siendo requerido. + +Creo que `Union[SomeType, None]` es mรกs explรญcito respecto a lo que significa. + +Se trata solo de palabras y nombres. Pero esas palabras pueden afectar cรณmo tรบ y tu equipo piensan sobre el cรณdigo. + +Como ejemplo, tomemos esta funciรณn: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +El parรกmetro `name` estรก definido como `Optional[str]`, pero **no es opcional**, no puedes llamar a la funciรณn sin el parรกmetro: + +```Python +say_hi() # ยกOh, no, esto lanza un error! ๐Ÿ˜ฑ +``` + +El parรกmetro `name` **sigue siendo requerido** (no es *opcional*) porque no tiene un valor por defecto. Aun asรญ, `name` acepta `None` como valor: + +```Python +say_hi(name=None) # Esto funciona, None es vรกlido ๐ŸŽ‰ +``` + +La buena noticia es que, en la mayorรญa de los casos, podrรกs simplemente usar `|` para definir uniones de tipos: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Asรญ que, normalmente no tienes que preocuparte por nombres como `Optional` y `Union`. ๐Ÿ˜Ž diff --git a/docs/es/docs/advanced/async-tests.md b/docs/es/docs/advanced/async-tests.md index 4627e9bd18..3485536cef 100644 --- a/docs/es/docs/advanced/async-tests.md +++ b/docs/es/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ Para un ejemplo simple, consideremos una estructura de archivos similar a la des El archivo `main.py` tendrรญa: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} El archivo `test_main.py` tendrรญa los tests para `main.py`, podrรญa verse asรญ ahora: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## Ejecรบtalo { #run-it } @@ -56,7 +56,7 @@ $ pytest El marcador `@pytest.mark.anyio` le dice a pytest que esta funciรณn de test debe ser llamada asรญncronamente: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | Consejo @@ -66,7 +66,7 @@ Nota que la funciรณn de test ahora es `async def` en lugar de solo `def` como an Luego podemos crear un `AsyncClient` con la app y enviar requests asรญncronos a ella, usando `await`. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} Esto es equivalente a: diff --git a/docs/es/docs/advanced/behind-a-proxy.md b/docs/es/docs/advanced/behind-a-proxy.md index f81c16ee81..40729ee03d 100644 --- a/docs/es/docs/advanced/behind-a-proxy.md +++ b/docs/es/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" Por ejemplo, digamos que defines una *path operation* `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} Si el cliente intenta ir a `/items`, por defecto, serรญa redirigido a `/items/`. @@ -115,7 +115,7 @@ En este caso, el path original `/app` realmente serรญa servido en `/api/v1/app`. Aunque todo tu cรณdigo estรฉ escrito asumiendo que solo existe `/app`. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} Y el proxy estarรญa **"eliminando"** el **prefijo del path** sobre la marcha antes de transmitir el request al servidor de aplicaciones (probablemente Uvicorn a travรฉs de FastAPI CLI), manteniendo a tu aplicaciรณn convencida de que estรก siendo servida en `/app`, asรญ que no tienes que actualizar todo tu cรณdigo para incluir el prefijo `/api/v1`. @@ -193,7 +193,7 @@ Puedes obtener el `root_path` actual utilizado por tu aplicaciรณn para cada requ Aquรญ lo estamos incluyendo en el mensaje solo con fines de demostraciรณn. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Luego, si inicias Uvicorn con: @@ -220,7 +220,7 @@ El response serรญa algo como: Alternativamente, si no tienes una forma de proporcionar una opciรณn de lรญnea de comandos como `--root-path` o su equivalente, puedes configurar el parรกmetro `root_path` al crear tu app de FastAPI: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} Pasar el `root_path` a `FastAPI` serรญa el equivalente a pasar la opciรณn de lรญnea de comandos `--root-path` a Uvicorn o Hypercorn. @@ -400,7 +400,7 @@ Si pasas una lista personalizada de `servers` y hay un `root_path` (porque tu AP Por ejemplo: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} Generarรก un esquema de OpenAPI como: @@ -455,7 +455,7 @@ Si no especificas el parรกmetro `servers` y `root_path` es igual a `/`, la propi Si no quieres que **FastAPI** incluya un server automรกtico usando el `root_path`, puedes usar el parรกmetro `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} y entonces no lo incluirรก en el esquema de OpenAPI. diff --git a/docs/es/docs/advanced/custom-response.md b/docs/es/docs/advanced/custom-response.md index 0884c41a74..a58f290d6e 100644 --- a/docs/es/docs/advanced/custom-response.md +++ b/docs/es/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ Esto se debe a que, por defecto, FastAPI inspeccionarรก cada elemento dentro y s Pero si estรกs seguro de que el contenido que estรกs devolviendo es **serializable con JSON**, puedes pasarlo directamente a la clase de response y evitar la sobrecarga extra que FastAPI tendrรญa al pasar tu contenido de retorno a travรฉs de `jsonable_encoder` antes de pasarlo a la clase de response. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | Informaciรณn @@ -55,7 +55,7 @@ Para devolver un response con HTML directamente desde **FastAPI**, usa `HTMLResp * Importa `HTMLResponse`. * Pasa `HTMLResponse` como parรกmetro `response_class` de tu *path operation decorator*. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | Informaciรณn @@ -73,7 +73,7 @@ Como se ve en [Devolver una Response directamente](response-directly.md){.intern El mismo ejemplo de arriba, devolviendo una `HTMLResponse`, podrรญa verse asรญ: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | Advertencia @@ -97,7 +97,7 @@ El `response_class` solo se usarรก para documentar el OpenAPI *path operation*, Por ejemplo, podrรญa ser algo asรญ: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} En este ejemplo, la funciรณn `generate_html_response()` ya genera y devuelve una `Response` en lugar de devolver el HTML en un `str`. @@ -136,7 +136,7 @@ Acepta los siguientes parรกmetros: FastAPI (de hecho Starlette) incluirรก automรกticamente un header Content-Length. Tambiรฉn incluirรก un header Content-Type, basado en el `media_type` y aรฑadiendo un conjunto de caracteres para tipos de texto. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ Toma algรบn texto o bytes y devuelve un response HTML, como leรญste arriba. Toma algรบn texto o bytes y devuelve un response de texto plano. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ Esto requiere instalar `ujson`, por ejemplo, con `pip install ujson`. /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | Consejo @@ -194,15 +194,15 @@ Devuelve una redirecciรณn HTTP. Usa un cรณdigo de estado 307 (Redirecciรณn Tempo Puedes devolver un `RedirectResponse` directamente: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- O puedes usarlo en el parรกmetro `response_class`: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} -Si haces eso, entonces puedes devolver la URL directamente desde tu *path operation function*. +Si haces eso, entonces puedes devolver la URL directamente desde tu *path operation* function. En este caso, el `status_code` utilizado serรก el por defecto para `RedirectResponse`, que es `307`. @@ -210,13 +210,13 @@ En este caso, el `status_code` utilizado serรก el por defecto para `RedirectResp Tambiรฉn puedes usar el parรกmetro `status_code` combinado con el parรกmetro `response_class`: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } Toma un generador `async` o un generador/iterador normal y transmite el cuerpo del response. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### Usando `StreamingResponse` con objetos similares a archivos { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ De esa manera, no tienes que leerlo todo primero en memoria, y puedes pasar esa Esto incluye muchos paquetes para interactuar con almacenamiento en la nube, procesamiento de video y otros. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. Esta es la funciรณn generadora. Es una "funciรณn generadora" porque contiene declaraciones `yield` dentro. 2. Al usar un bloque `with`, nos aseguramos de que el objeto similar a un archivo se cierre despuรฉs de que la funciรณn generadora termine. Asรญ, despuรฉs de que termina de enviar el response. @@ -255,11 +255,11 @@ Toma un conjunto diferente de argumentos para crear un instance que los otros ti Los responses de archivos incluirรกn los headers apropiados `Content-Length`, `Last-Modified` y `ETag`. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} Tambiรฉn puedes usar el parรกmetro `response_class`: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} En este caso, puedes devolver la path del archivo directamente desde tu *path operation* function. @@ -273,7 +273,7 @@ Digamos que quieres que devuelva JSON con sangrรญa y formato, por lo que quieres Podrรญas crear un `CustomORJSONResponse`. Lo principal que tienes que hacer es crear un mรฉtodo `Response.render(content)` que devuelva el contenido como `bytes`: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} Ahora en lugar de devolver: @@ -299,7 +299,7 @@ El parรกmetro que define esto es `default_response_class`. En el ejemplo a continuaciรณn, **FastAPI** usarรก `ORJSONResponse` por defecto, en todas las *path operations*, en lugar de `JSONResponse`. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | Consejo diff --git a/docs/es/docs/advanced/dataclasses.md b/docs/es/docs/advanced/dataclasses.md index 3a07482ad1..d586d3a270 100644 --- a/docs/es/docs/advanced/dataclasses.md +++ b/docs/es/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ En ese caso, simplemente puedes intercambiar los `dataclasses` estรกndar con `py 6. Aquรญ estamos regresando un diccionario que contiene `items`, que es una lista de dataclasses. - FastAPI todavรญa es capaz de serializar los datos a JSON. + FastAPI todavรญa es capaz de serializar los datos a JSON. 7. Aquรญ el `response_model` estรก usando una anotaciรณn de tipo de una lista de dataclasses `Author`. diff --git a/docs/es/docs/advanced/events.md b/docs/es/docs/advanced/events.md index c2002a6f53..4adb464d3b 100644 --- a/docs/es/docs/advanced/events.md +++ b/docs/es/docs/advanced/events.md @@ -30,7 +30,7 @@ Comencemos con un ejemplo y luego veรกmoslo en detalle. Creamos una funciรณn asรญncrona `lifespan()` con `yield` asรญ: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} Aquรญ estamos simulando la operaciรณn costosa de *startup* de cargar el modelo poniendo la funciรณn del (falso) modelo en el diccionario con modelos de machine learning antes del `yield`. Este cรณdigo serรก ejecutado **antes** de que la aplicaciรณn **comience a tomar requests**, durante el *startup*. @@ -48,7 +48,7 @@ Quizรกs necesites iniciar una nueva versiรณn, o simplemente te cansaste de ejecu Lo primero que hay que notar es que estamos definiendo una funciรณn asรญncrona con `yield`. Esto es muy similar a las Dependencias con `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} La primera parte de la funciรณn, antes del `yield`, serรก ejecutada **antes** de que la aplicaciรณn comience. @@ -60,7 +60,7 @@ Si revisas, la funciรณn estรก decorada con un `@asynccontextmanager`. Eso convierte a la funciรณn en algo llamado un "**async context manager**". -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} Un **context manager** en Python es algo que puedes usar en un statement `with`, por ejemplo, `open()` puede ser usado como un context manager: @@ -82,7 +82,7 @@ En nuestro ejemplo de cรณdigo arriba, no lo usamos directamente, pero se lo pasa El parรกmetro `lifespan` de la app de `FastAPI` toma un **async context manager**, por lo que podemos pasar nuestro nuevo `lifespan` async context manager a รฉl. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Eventos Alternativos (obsoleto) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ Estas funciones pueden ser declaradas con `async def` o `def` normal. Para aรฑadir una funciรณn que deberรญa ejecutarse antes de que la aplicaciรณn inicie, declรกrala con el evento `"startup"`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} En este caso, la funciรณn manejadora del evento `startup` inicializarรก los รญtems de la "base de datos" (solo un `dict`) con algunos valores. @@ -116,7 +116,7 @@ Y tu aplicaciรณn no comenzarรก a recibir requests hasta que todos los manejadore Para aรฑadir una funciรณn que deberรญa ejecutarse cuando la aplicaciรณn se estรฉ cerrando, declรกrala con el evento `"shutdown"`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Aquรญ, la funciรณn manejadora del evento `shutdown` escribirรก una lรญnea de texto `"Application shutdown"` a un archivo `log.txt`. diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index daf6cefed3..a079c41aa5 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -2,7 +2,7 @@ Como **FastAPI** estรก basado en la especificaciรณn **OpenAPI**, sus APIs se pueden describir en un formato estรกndar que muchas herramientas entienden. -Esto facilita generar **documentaciรณn** actualizada, paquetes de cliente (**SDKs**) en mรบltiples lenguajes y **escribir pruebas** o **flujos de automatizaciรณn** que se mantengan sincronizados con tu cรณdigo. +Esto facilita generar **documentaciรณn** actualizada, paquetes de cliente (**SDKs**) en mรบltiples lenguajes y **escribir pruebas** o **flujos de automatizaciรณn** que se mantengan sincronizados con tu cรณdigo. En esta guรญa, aprenderรกs a generar un **SDK de TypeScript** para tu backend con FastAPI. @@ -40,7 +40,7 @@ Algunas de estas soluciones tambiรฉn pueden ser open source u ofrecer niveles gr Empecemos con una aplicaciรณn simple de FastAPI: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} Nota que las *path operations* definen los modelos que usan para el payload del request y el payload del response, usando los modelos `Item` y `ResponseMessage`. @@ -98,7 +98,7 @@ En muchos casos tu app de FastAPI serรก mรกs grande, y probablemente usarรกs tag Por ejemplo, podrรญas tener una secciรณn para **items** y otra secciรณn para **users**, y podrรญan estar separadas por tags: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Genera un Cliente TypeScript con tags { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ Por ejemplo, aquรญ estรก usando el primer tag (probablemente tendrรกs solo un ta Puedes entonces pasar esa funciรณn personalizada a **FastAPI** como el parรกmetro `generate_unique_id_function`: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### Genera un Cliente TypeScript con operation IDs personalizados { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ Pero para el cliente generado podrรญamos **modificar** los operation IDs de Open Podrรญamos descargar el JSON de OpenAPI a un archivo `openapi.json` y luego podrรญamos **remover ese tag prefijado** con un script como este: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/es/docs/advanced/middleware.md b/docs/es/docs/advanced/middleware.md index 7eead8ae14..ed582c4655 100644 --- a/docs/es/docs/advanced/middleware.md +++ b/docs/es/docs/advanced/middleware.md @@ -8,7 +8,7 @@ En esta secciรณn veremos cรณmo usar otros middlewares. ## Agregando middlewares ASGI { #adding-asgi-middlewares } -Como **FastAPI** estรก basado en Starlette e implementa la especificaciรณn ASGI, puedes usar cualquier middleware ASGI. +Como **FastAPI** estรก basado en Starlette e implementa la especificaciรณn ASGI, puedes usar cualquier middleware ASGI. Un middleware no tiene que estar hecho para FastAPI o Starlette para funcionar, siempre que siga la especificaciรณn ASGI. @@ -57,13 +57,13 @@ Impone que todas las requests entrantes deben ser `https` o `wss`. Cualquier request entrante a `http` o `ws` serรก redirigida al esquema seguro. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } Impone que todas las requests entrantes tengan correctamente configurado el header `Host`, para proteger contra ataques de HTTP Host Header. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} Se soportan los siguientes argumentos: @@ -78,7 +78,7 @@ Maneja responses GZip para cualquier request que incluya `"gzip"` en el header ` El middleware manejarรก tanto responses estรกndar como en streaming. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} Se soportan los siguientes argumentos: diff --git a/docs/es/docs/advanced/openapi-webhooks.md b/docs/es/docs/advanced/openapi-webhooks.md index c358a14008..4f657ad53e 100644 --- a/docs/es/docs/advanced/openapi-webhooks.md +++ b/docs/es/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Los webhooks estรกn disponibles en OpenAPI 3.1.0 y superiores, soportados por Fa Cuando creas una aplicaciรณn de **FastAPI**, hay un atributo `webhooks` que puedes usar para definir *webhooks*, de la misma manera que definirรญas *path operations*, por ejemplo con `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} Los webhooks que defines terminarรกn en el esquema de **OpenAPI** y en la interfaz automรกtica de **documentaciรณn**. diff --git a/docs/es/docs/advanced/path-operation-advanced-configuration.md b/docs/es/docs/advanced/path-operation-advanced-configuration.md index ea58a300ad..0ba586c1c1 100644 --- a/docs/es/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/es/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ Puedes establecer el `operationId` de OpenAPI para ser usado en tu *path operati Tendrรญas que asegurarte de que sea รบnico para cada operaciรณn. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Usar el nombre de la *path operation function* como el operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ Si quieres usar los nombres de las funciones de tus APIs como `operationId`s, pu Deberรญas hacerlo despuรฉs de agregar todas tus *path operations*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | Consejo @@ -40,7 +40,7 @@ Incluso si estรกn en diferentes mรณdulos (archivos de Python). Para excluir una *path operation* del esquema OpenAPI generado (y por lo tanto, de los sistemas de documentaciรณn automรกtica), utiliza el parรกmetro `include_in_schema` y configรบralo en `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Descripciรณn avanzada desde el docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ Puedes extender el esquema de OpenAPI para una *path operation* usando el parรกm Este `openapi_extra` puede ser รบtil, por ejemplo, para declarar [Extensiones de OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Si abres la documentaciรณn automรกtica de la API, tu extensiรณn aparecerรก en la parte inferior de la *path operation* especรญfica. @@ -139,9 +139,9 @@ Por ejemplo, podrรญas decidir leer y validar el request con tu propio cรณdigo, s Podrรญas hacer eso con `openapi_extra`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -En este ejemplo, no declaramos ningรบn modelo Pydantic. De hecho, el request body ni siquiera se parse como JSON, se lee directamente como `bytes`, y la funciรณn `magic_data_reader()` serรญa la encargada de parsearlo de alguna manera. +En este ejemplo, no declaramos ningรบn modelo Pydantic. De hecho, el request body ni siquiera es parseado como JSON, se lee directamente como `bytes`, y la funciรณn `magic_data_reader()` serรญa la encargada de parsearlo de alguna manera. Sin embargo, podemos declarar el esquema esperado para el request body. @@ -153,7 +153,7 @@ Y podrรญas hacer esto incluso si el tipo de datos en el request no es JSON. Por ejemplo, en esta aplicaciรณn no usamos la funcionalidad integrada de FastAPI para extraer el JSON Schema de los modelos Pydantic ni la validaciรณn automรกtica para JSON. De hecho, estamos declarando el tipo de contenido del request como YAML, no JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Sin embargo, aunque no estamos usando la funcionalidad integrada por defecto, aรบn estamos usando un modelo Pydantic para generar manualmente el JSON Schema para los datos que queremos recibir en YAML. @@ -161,7 +161,7 @@ Luego usamos el request directamente, y extraemos el cuerpo como `bytes`. Esto s Y luego en nuestro cรณdigo, parseamos ese contenido YAML directamente, y nuevamente estamos usando el mismo modelo Pydantic para validar el contenido YAML: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | Consejo diff --git a/docs/es/docs/advanced/response-change-status-code.md b/docs/es/docs/advanced/response-change-status-code.md index 940f1dd3ff..622001291f 100644 --- a/docs/es/docs/advanced/response-change-status-code.md +++ b/docs/es/docs/advanced/response-change-status-code.md @@ -20,9 +20,9 @@ Puedes declarar un parรกmetro de tipo `Response` en tu *path operation function* Y luego puedes establecer el `status_code` en ese objeto de response *temporal*. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} -Y luego puedes devolver cualquier objeto que necesites, como lo harรญas normalmente (un `dict`, un modelo de base de datos, etc.). +Y luego puedes devolver cualquier objeto que necesites, como lo harรญas normalmente (un `dict`, un modelo de base de datos, etc). Y si declaraste un `response_model`, todavรญa se utilizarรก para filtrar y convertir el objeto que devolviste. diff --git a/docs/es/docs/advanced/response-cookies.md b/docs/es/docs/advanced/response-cookies.md index 550a5d97a7..e451d89390 100644 --- a/docs/es/docs/advanced/response-cookies.md +++ b/docs/es/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ Puedes declarar un parรกmetro de tipo `Response` en tu *path operation function* Y luego puedes establecer cookies en ese objeto de response *temporal*. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} Y entonces puedes devolver cualquier objeto que necesites, como normalmente lo harรญas (un `dict`, un modelo de base de datos, etc). @@ -24,7 +24,7 @@ Para hacer eso, puedes crear un response como se describe en [Devolver un Respon Luego establece Cookies en ella, y luego devuรฉlvela: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | Consejo diff --git a/docs/es/docs/advanced/response-directly.md b/docs/es/docs/advanced/response-directly.md index 2da4e84e70..b9b1df447a 100644 --- a/docs/es/docs/advanced/response-directly.md +++ b/docs/es/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ Digamos que quieres devolver un response en IoT) comunicรกndose con รฉl. +Fue creado para generar el HTML en el backend, no para crear APIs utilizadas por un frontend moderno (como React, Vue.js y Angular) o por otros sistemas (como dispositivos del IoT) comunicรกndose con รฉl. ### Django REST Framework { #django-rest-framework } @@ -76,7 +76,7 @@ Aun asรญ, FastAPI se inspirรณ bastante en Requests. Estรกn, mรกs o menos, en extremos opuestos, complementรกndose entre sรญ. -Requests tiene un diseรฑo muy simple e intuitivo, es muy fรกcil de usar, con valores predeterminados sensatos. Pero al mismo tiempo, es muy poderoso y personalizable. +Requests tiene un diseรฑo muy simple e intuitivo, es muy fรกcil de usar, con valores por defecto sensatos. Pero al mismo tiempo, es muy poderoso y personalizable. Por eso, como se dice en el sitio web oficial: @@ -102,7 +102,7 @@ Mira las similitudes entre `requests.get(...)` y `@app.get(...)`. * Tener un API simple e intuitivo. * Usar nombres de mรฉtodos HTTP (operaciones) directamente, de una manera sencilla e intuitiva. -* Tener valores predeterminados sensatos, pero personalizaciones poderosas. +* Tener valores por defecto sensatos, pero personalizaciones poderosas. /// @@ -137,7 +137,7 @@ Existen varios frameworks REST para Flask, pero despuรฉs de invertir tiempo y tr ### Marshmallow { #marshmallow } -Una de las principales funcionalidades necesitadas por los sistemas API es la "serializaciรณn" de datos, que consiste en tomar datos del cรณdigo (Python) y convertirlos en algo que pueda ser enviado a travรฉs de la red. Por ejemplo, convertir un objeto que contiene datos de una base de datos en un objeto JSON. Convertir objetos `datetime` en strings, etc. +Una de las principales funcionalidades necesitadas por los sistemas API es la "serializaciรณn" de datos, que consiste en tomar datos del cรณdigo (Python) y convertirlos en algo que pueda ser enviado a travรฉs de la red. Por ejemplo, convertir un objeto que contiene datos de una base de datos en un objeto JSON. Convertir objetos `datetime` en strings, etc. Otra gran funcionalidad necesaria por las APIs es la validaciรณn de datos, asegurarse de que los datos sean vรกlidos, dados ciertos parรกmetros. Por ejemplo, que algรบn campo sea un `int`, y no algรบn string aleatorio. Esto es especialmente รบtil para los datos entrantes. @@ -145,7 +145,7 @@ Sin un sistema de validaciรณn de datos, tendrรญas que hacer todas las comprobaci Estas funcionalidades son para lo que fue creado Marshmallow. Es un gran paquete, y lo he usado mucho antes. -Pero fue creado antes de que existieran las anotaciones de tipos en Python. Asรญ que, para definir cada esquema necesitas usar utilidades y clases especรญficas proporcionadas por Marshmallow. +Pero fue creado antes de que existieran las anotaciones de tipos en Python. Asรญ que, para definir cada esquema necesitas usar utilidades y clases especรญficas proporcionadas por Marshmallow. /// check | Inspirรณ a **FastAPI** a @@ -155,7 +155,7 @@ Usar cรณdigo para definir "esquemas" que proporcionen tipos de datos y validaci ### Webargs { #webargs } -Otra gran funcionalidad requerida por las APIs es el parse de datos de las requests entrantes. +Otra gran funcionalidad requerida por las APIs es el parsing de datos de las requests entrantes. Webargs es una herramienta que fue creada para proporcionar esa funcionalidad sobre varios frameworks, incluido Flask. @@ -177,7 +177,7 @@ Tener validaciรณn automรกtica de datos entrantes en una request. ### APISpec { #apispec } -Marshmallow y Webargs proporcionan validaciรณn, parse y serializaciรณn como plug-ins. +Marshmallow y Webargs proporcionan validaciรณn, parsing y serializaciรณn como plug-ins. Pero la documentaciรณn todavรญa falta. Entonces APISpec fue creado. @@ -419,7 +419,7 @@ Manejar toda la validaciรณn de datos, serializaciรณn de datos y documentaciรณn a ### Starlette { #starlette } -Starlette es un framework/toolkit ASGI liviano, ideal para construir servicios asyncio de alto rendimiento. +Starlette es un framework/toolkit ASGI liviano, ideal para construir servicios asyncio de alto rendimiento. Es muy simple e intuitivo. Estรก diseรฑado para ser fรกcilmente extensible y tener componentes modulares. diff --git a/docs/es/docs/async.md b/docs/es/docs/async.md index a1c8f0fb9d..a06d3e979d 100644 --- a/docs/es/docs/async.md +++ b/docs/es/docs/async.md @@ -4,7 +4,7 @@ Detalles sobre la sintaxis `async def` para *path operation functions* y algunos ## ยฟCon prisa? { #in-a-hurry } -TL;DR: +TL;DR: Si estรกs usando paquetes de terceros que te dicen que los llames con `await`, como: @@ -74,7 +74,7 @@ Luego la computadora / programa ๐Ÿค– volverรก cada vez que tenga una oportunidad Despuรฉs, ๐Ÿค– toma la primera tarea que termine (digamos, nuestro "archivo-lento" ๐Ÿ“) y continรบa con lo que tenรญa que hacer con ella. -Ese "esperar otra cosa" normalmente se refiere a las operaciones de I/O que son relativamente "lentas" (comparadas con la velocidad del procesador y la memoria RAM), como esperar: +Ese "esperar otra cosa" normalmente se refiere a las operaciones de I/O que son relativamente "lentas" (comparadas con la velocidad del procesador y la memoria RAM), como esperar: * que los datos del cliente se envรญen a travรฉs de la red * que los datos enviados por tu programa sean recibidos por el cliente a travรฉs de la red @@ -85,7 +85,7 @@ Ese "esperar otra cosa" normalmente se refiere a las operaciones de I/O, las llaman operaciones "I/O bound". +Como el tiempo de ejecuciรณn se consume principalmente esperando operaciones de I/O, las llaman operaciones "I/O bound". Se llama "asรญncrono" porque la computadora / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que la tarea termine, sin hacer nada, para poder tomar el resultado de la tarea y continuar el trabajo. @@ -277,7 +277,7 @@ Pero en este caso, si pudieras traer a los 8 ex-cajeros/cocineros/ahora-limpiado En este escenario, cada uno de los limpiadores (incluyรฉndote) serรญa un procesador, haciendo su parte del trabajo. -Y como la mayor parte del tiempo de ejecuciรณn se dedica al trabajo real (en lugar de esperar), y el trabajo en una computadora lo realiza una CPU, llaman a estos problemas "CPU bound". +Y como la mayor parte del tiempo de ejecuciรณn se dedica al trabajo real (en lugar de esperar), y el trabajo en una computadora lo realiza una CPU, llaman a estos problemas "CPU bound". --- @@ -417,7 +417,7 @@ Si tienes bastante conocimiento tรฉcnico (coroutines, hilos, bloqueo, etc.) y ti Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es esperado, en lugar de ser llamado directamente (ya que bloquearรญa el servidor). -Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estรกs acostumbrado a definir funciones de *path operation* solo de cรณmputo trivial con `def` normal para una pequeรฑa ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto serรญa bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen cรณdigo que realice I/O de bloqueo. +Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estรกs acostumbrado a definir funciones de *path operation* solo de cรณmputo trivial con `def` normal para una pequeรฑa ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto serรญa bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen cรณdigo que realice I/O de bloqueo. Aun asรญ, en ambas situaciones, es probable que **FastAPI** [siga siendo mรกs rรกpida](index.md#performance){.internal-link target=_blank} que (o al menos comparable a) tu framework anterior. diff --git a/docs/es/docs/deployment/cloud.md b/docs/es/docs/deployment/cloud.md index f3c951d989..a3531b97a7 100644 --- a/docs/es/docs/deployment/cloud.md +++ b/docs/es/docs/deployment/cloud.md @@ -10,7 +10,7 @@ En la mayorรญa de los casos, los principales proveedores de nube tienen guรญas p Simplifica el proceso de **construir**, **desplegar** y **acceder** a una API con un esfuerzo mรญnimo. -Trae la misma experiencia de desarrollador de construir aplicaciones con FastAPI a desplegarlas en la nube. ๐ŸŽ‰ +Trae la misma **experiencia de desarrollador** de construir aplicaciones con FastAPI a **desplegarlas** en la nube. ๐ŸŽ‰ FastAPI Cloud es el sponsor principal y proveedor de financiamiento de los proyectos open source *FastAPI and friends*. โœจ diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md index c42ced70bc..2ec7af19ba 100644 --- a/docs/es/docs/deployment/concepts.md +++ b/docs/es/docs/deployment/concepts.md @@ -318,4 +318,4 @@ Has estado leyendo aquรญ algunos de los conceptos principales que probablemente Comprender estas ideas y cรณmo aplicarlas deberรญa darte la intuiciรณn necesaria para tomar decisiones al configurar y ajustar tus implementaciones. ๐Ÿค“ -En las prรณximas secciones, te darรฉ ejemplos mรกs concretos de posibles estrategias que puedes seguir. ๐Ÿš€ +En las prรณximas secciones, te darรฉ mรกs ejemplos concretos de posibles estrategias que puedes seguir. ๐Ÿš€ diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index 9a0b889559..105a5902b7 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -14,7 +14,7 @@ Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **re Vista previa del Dockerfile ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ Ahora, en el mismo directorio del proyecto, crea un archivo `Dockerfile` con: ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ Si tu FastAPI es un solo archivo, por ejemplo, `main.py` sin un directorio `./ap Entonces solo tendrรญas que cambiar las rutas correspondientes para copiar el archivo dentro del `Dockerfile`: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Sin usar contenedores, hacer que las aplicaciones se ejecuten al inicio y con re ## Replicaciรณn - Nรบmero de Procesos { #replication-number-of-processes } -Si tienes un cluster de mรกquinas con **Kubernetes**, Docker Swarm Mode, Nomad, u otro sistema complejo similar para gestionar contenedores distribuidos en varias mรกquinas, entonces probablemente querrรกs manejar la **replicaciรณn** a nivel de **cluster** en lugar de usar un **gestor de procesos** (como Uvicorn con workers) en cada contenedor. +Si tienes un clรบster de mรกquinas con **Kubernetes**, Docker Swarm Mode, Nomad, u otro sistema complejo similar para gestionar contenedores distribuidos en varias mรกquinas, entonces probablemente querrรกs manejar la **replicaciรณn** a nivel de **cluster** en lugar de usar un **gestor de procesos** (como Uvicorn con workers) en cada contenedor. Uno de esos sistemas de gestiรณn de contenedores distribuidos como Kubernetes normalmente tiene alguna forma integrada de manejar la **replicaciรณn de contenedores** mientras aรบn soporta el **load balancing** para las requests entrantes. Todo a nivel de **cluster**. @@ -499,7 +499,7 @@ Por supuesto, hay **casos especiales** donde podrรญas querer tener **un contened En esos casos, puedes usar la opciรณn de lรญnea de comandos `--workers` para establecer el nรบmero de workers que deseas ejecutar: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/es/docs/deployment/fastapicloud.md b/docs/es/docs/deployment/fastapicloud.md index af3e7ce680..9763af48c5 100644 --- a/docs/es/docs/deployment/fastapicloud.md +++ b/docs/es/docs/deployment/fastapicloud.md @@ -1,6 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Puedes desplegar tu app de FastAPI en FastAPI Cloud con un solo comando; ve y รบnete a la lista de espera si aรบn no lo has hecho. ๐Ÿš€ +Puedes desplegar tu app de FastAPI en FastAPI Cloud con **un solo comando**; ve y รบnete a la lista de espera si aรบn no lo has hecho. ๐Ÿš€ ## Iniciar sesiรณn { #login } @@ -20,7 +20,7 @@ You are logged in to FastAPI Cloud ๐Ÿš€ ## Desplegar { #deploy } -Ahora despliega tu app, con un solo comando: +Ahora despliega tu app, con **un solo comando**:
diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md index e62bf8b153..d7a244107c 100644 --- a/docs/es/docs/deployment/https.md +++ b/docs/es/docs/deployment/https.md @@ -65,7 +65,7 @@ Aquรญ tienes un ejemplo de cรณmo podrรญa ser una API HTTPS, paso a paso, prestan Probablemente todo comenzarรญa adquiriendo un **nombre de dominio**. Luego, lo configurarรญas en un servidor DNS (posiblemente tu mismo proveedor de la nube). -Probablemente conseguirรญas un servidor en la nube (una mรกquina virtual) o algo similar, y tendrรญa una **direcciรณn IP pรบblica** fija. +Probablemente conseguirรญas un servidor en la nube (una mรกquina virtual) o algo similar, y tendrรญa una **direcciรณn IP pรบblica** fija. En el/los servidor(es) DNS configurarรญas un registro (un "`A record`") para apuntar **tu dominio** a la **direcciรณn IP pรบblica de tu servidor**. diff --git a/docs/es/docs/deployment/manually.md b/docs/es/docs/deployment/manually.md index 50ba79c228..3c597ff69e 100644 --- a/docs/es/docs/deployment/manually.md +++ b/docs/es/docs/deployment/manually.md @@ -46,7 +46,7 @@ Podrรญas usar ese comando, por ejemplo, para iniciar tu app **FastAPI** en un co Vamos a profundizar un poquito en los detalles. -FastAPI usa un estรกndar para construir frameworks de web y servidores de Python llamado ASGI. FastAPI es un framework web ASGI. +FastAPI usa un estรกndar para construir frameworks de web y servidores de Python llamado ASGI. FastAPI es un framework web ASGI. Lo principal que necesitas para ejecutar una aplicaciรณn **FastAPI** (o cualquier otra aplicaciรณn ASGI) en una mรกquina de servidor remota es un programa de servidor ASGI como **Uvicorn**, que es el que viene por defecto en el comando `fastapi`. diff --git a/docs/es/docs/features.md b/docs/es/docs/features.md index 9902b21fa5..947ef312db 100644 --- a/docs/es/docs/features.md +++ b/docs/es/docs/features.md @@ -6,7 +6,7 @@ ### Basado en estรกndares abiertos { #based-on-open-standards } -* OpenAPI para la creaciรณn de APIs, incluyendo declaraciones de path operations, parรกmetros, request bodies, seguridad, etc. +* OpenAPI para la creaciรณn de APIs, incluyendo declaraciones de path operations, parรกmetros, request bodies, seguridad, etc. * Documentaciรณn automรกtica de modelos de datos con JSON Schema (ya que OpenAPI en sรญ mismo estรก basado en JSON Schema). * Diseรฑado alrededor de estos estรกndares, tras un estudio meticuloso. En lugar de ser una capa adicional. * Esto tambiรฉn permite el uso de **generaciรณn de cรณdigo cliente automรกtica** en muchos idiomas. @@ -105,8 +105,8 @@ Pero por defecto, todo **"simplemente funciona"**. * Validaciรณn para la mayorรญa (ยฟo todas?) de los **tipos de datos** de Python, incluyendo: * Objetos JSON (`dict`). - * Array JSON (`list`) definiendo tipos de elementos. - * Campos de cadena de caracteres (`str`), definiendo longitudes mรญnimas y mรกximas. + * array JSON (`list`) definiendo tipos de elementos. + * Campos de string (`str`), definiendo longitudes mรญnimas y mรกximas. * Nรบmeros (`int`, `float`) con valores mรญnimos y mรกximos, etc. * Validaciรณn para tipos mรกs exรณticos, como: @@ -136,7 +136,7 @@ Todo construido como herramientas y componentes reutilizables que son fรกciles d ### Inyecciรณn de dependencias { #dependency-injection } -FastAPI incluye un sistema de Inyecciรณn de Dependencias extremadamente fรกcil de usar, pero extremadamente potente. +FastAPI incluye un sistema de Inyecciรณn de Dependencias extremadamente fรกcil de usar, pero extremadamente potente. * Incluso las dependencias pueden tener dependencias, creando una jerarquรญa o **"grafo de dependencias"**. * Todo **manejado automรกticamente** por el framework. @@ -153,8 +153,8 @@ Cualquier integraciรณn estรก diseรฑada para ser tan simple de usar (con dependen ### Probado { #tested } -* 100% de cobertura de tests. -* 100% anotada con tipos code base. +* 100% de cobertura de tests. +* 100% anotada con tipos code base. * Usado en aplicaciones en producciรณn. ## Funcionalidades de Starlette { #starlette-features } @@ -173,7 +173,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Starlette** (ya que Fast * **CORS**, GZip, archivos estรกticos, responses en streaming. * Soporte para **Session y Cookie**. * Cobertura de tests del 100%. -* code base completamente anotada con tipos. +* code base 100% anotada con tipos. ## Funcionalidades de Pydantic { #pydantic-features } @@ -190,7 +190,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Pydantic** (ya que FastA * **Sin complicaciones**: * Sin micro-lenguaje de definiciรณn de esquemas nuevo que aprender. * Si conoces los tipos en Python sabes cรณmo usar Pydantic. -* Se lleva bien con tu **IDE/linter/cerebro**: +* Se lleva bien con tu **IDE/linter/cerebro**: * Porque las estructuras de datos de pydantic son solo instances de clases que defines; autocompletado, linting, mypy y tu intuiciรณn deberรญan funcionar correctamente con tus datos validados. * Valida **estructuras complejas**: * Uso de modelos jerรกrquicos de Pydantic, `List` y `Dict` de `typing` de Python, etc. diff --git a/docs/es/docs/help-fastapi.md b/docs/es/docs/help-fastapi.md index cef9562249..9b727dab08 100644 --- a/docs/es/docs/help-fastapi.md +++ b/docs/es/docs/help-fastapi.md @@ -110,7 +110,7 @@ En muchos casos solo copiarรกn un fragmento del cรณdigo, pero eso no es suficien ### Sugerir soluciones { #suggest-solutions } -* Despuรฉs de poder entender la pregunta, puedes darles un posible **respuesta**. +* Despuรฉs de poder entender la pregunta, puedes darles una posible **respuesta**. * En muchos casos, es mejor entender su **problema subyacente o caso de uso**, porque podrรญa haber una mejor manera de resolverlo que lo que estรกn intentando hacer. @@ -247,9 +247,9 @@ Las conversaciones en los sistemas de chat tampoco son tan fรกcilmente buscables Por otro lado, hay miles de usuarios en los sistemas de chat, por lo que hay muchas posibilidades de que encuentres a alguien con quien hablar allรญ, casi todo el tiempo. ๐Ÿ˜„ -## Patrocina al autor { #sponsor-the-author } +## Hazte sponsor del autor { #sponsor-the-author } -Si tu **producto/empresa** depende de o estรก relacionado con **FastAPI** y quieres llegar a sus usuarios, puedes patrocinar al autor (a mรญ) a travรฉs de GitHub sponsors. Segรบn el nivel, podrรญas obtener algunos beneficios extra, como una insignia en la documentaciรณn. ๐ŸŽ +Si tu **producto/empresa** depende de o estรก relacionado con **FastAPI** y quieres llegar a sus usuarios, puedes hacerte sponsor del autor (de mรญ) a travรฉs de GitHub sponsors. Segรบn el nivel, podrรญas obtener algunos beneficios extra, como una insignia en la documentaciรณn. ๐ŸŽ --- diff --git a/docs/es/docs/how-to/authentication-error-status-code.md b/docs/es/docs/how-to/authentication-error-status-code.md index 9fff6c93d3..54afcec8cb 100644 --- a/docs/es/docs/how-to/authentication-error-status-code.md +++ b/docs/es/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ Pero si por alguna razรณn tus clientes dependen del comportamiento anterior, pue Por ejemplo, puedes crear una subclase de `HTTPBearer` que devuelva un error `403 Forbidden` en lugar del `401 Unauthorized` por defecto: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | Consejo diff --git a/docs/es/docs/how-to/conditional-openapi.md b/docs/es/docs/how-to/conditional-openapi.md index a06ad95489..671100cf8b 100644 --- a/docs/es/docs/how-to/conditional-openapi.md +++ b/docs/es/docs/how-to/conditional-openapi.md @@ -29,7 +29,7 @@ Puedes usar fรกcilmente las mismas configuraciones de Pydantic para configurar t Por ejemplo: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} Aquรญ declaramos la configuraciรณn `openapi_url` con el mismo valor por defecto de `"/openapi.json"`. diff --git a/docs/es/docs/how-to/configure-swagger-ui.md b/docs/es/docs/how-to/configure-swagger-ui.md index b2865d77d5..092c310011 100644 --- a/docs/es/docs/how-to/configure-swagger-ui.md +++ b/docs/es/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ Sin cambiar la configuraciรณn, el resaltado de sintaxis estรก activado por defec Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ...y entonces Swagger UI ya no mostrarรก el resaltado de sintaxis: @@ -28,17 +28,17 @@ Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`: De la misma manera, podrรญas configurar el tema del resaltado de sintaxis con la clave `"syntaxHighlight.theme"` (ten en cuenta que tiene un punto en el medio): -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} Esa configuraciรณn cambiarรญa el tema de color del resaltado de sintaxis: -## Cambiar los parรกmetros predeterminados de Swagger UI { #change-default-swagger-ui-parameters } +## Cambiar los parรกmetros por defecto de Swagger UI { #change-default-swagger-ui-parameters } -FastAPI incluye algunos parรกmetros de configuraciรณn predeterminados apropiados para la mayorรญa de los casos de uso. +FastAPI incluye algunos parรกmetros de configuraciรณn por defecto apropiados para la mayorรญa de los casos de uso. -Incluye estas configuraciones predeterminadas: +Incluye estas configuraciones por defecto: {* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} @@ -46,7 +46,7 @@ Puedes sobrescribir cualquiera de ellos estableciendo un valor diferente en el a Por ejemplo, para desactivar `deepLinking` podrรญas pasar estas configuraciones a `swagger_ui_parameters`: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## Otros parรกmetros de Swagger UI { #other-swagger-ui-parameters } diff --git a/docs/es/docs/how-to/custom-docs-ui-assets.md b/docs/es/docs/how-to/custom-docs-ui-assets.md index acd3f8d6d6..faddab0d83 100644 --- a/docs/es/docs/how-to/custom-docs-ui-assets.md +++ b/docs/es/docs/how-to/custom-docs-ui-assets.md @@ -18,7 +18,7 @@ El primer paso es desactivar la documentaciรณn automรกtica, ya que por defecto, Para desactivarlos, establece sus URLs en `None` cuando crees tu aplicaciรณn de `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### Incluye la documentaciรณn personalizada { #include-the-custom-docs } @@ -34,7 +34,7 @@ Puedes reutilizar las funciones internas de FastAPI para crear las pรกginas HTML Y de manera similar para ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | Consejo @@ -50,7 +50,7 @@ Swagger UI lo manejarรก detrรกs de escena para ti, pero necesita este auxiliar d Ahora, para poder probar que todo funciona, crea una *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### Pruรฉbalo { #test-it } @@ -118,7 +118,7 @@ Despuรฉs de eso, tu estructura de archivos podrรญa verse asรญ: * Importa `StaticFiles`. * "Monta" una instance de `StaticFiles()` en un path especรญfico. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### Prueba los archivos estรกticos { #test-the-static-files } @@ -144,7 +144,7 @@ Igual que cuando usas un CDN personalizado, el primer paso es desactivar la docu Para desactivarlos, establece sus URLs en `None` cuando crees tu aplicaciรณn de `FastAPI`: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### Incluye la documentaciรณn personalizada para archivos estรกticos { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Nuevamente, puedes reutilizar las funciones internas de FastAPI para crear las p Y de manera similar para ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | Consejo @@ -176,7 +176,7 @@ Swagger UI lo manejarรก detrรกs de escena para ti, pero necesita este auxiliar d Ahora, para poder probar que todo funciona, crea una *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### Prueba la UI de Archivos Estรกticos { #test-static-files-ui } diff --git a/docs/es/docs/how-to/extending-openapi.md b/docs/es/docs/how-to/extending-openapi.md index 2611b6e1b6..d08fae073a 100644 --- a/docs/es/docs/how-to/extending-openapi.md +++ b/docs/es/docs/how-to/extending-openapi.md @@ -43,19 +43,19 @@ Por ejemplo, vamos a aรฑadir documentaciรณn de Strawberry. diff --git a/docs/es/docs/how-to/separate-openapi-schemas.md b/docs/es/docs/how-to/separate-openapi-schemas.md index 903313599d..db9b46ddbe 100644 --- a/docs/es/docs/how-to/separate-openapi-schemas.md +++ b/docs/es/docs/how-to/separate-openapi-schemas.md @@ -85,7 +85,7 @@ Probablemente el caso principal para esto es si ya tienes algรบn cรณdigo cliente En ese caso, puedes desactivar esta funcionalidad en **FastAPI**, con el parรกmetro `separate_input_output_schemas=False`. -/// info +/// info | Informaciรณn El soporte para `separate_input_output_schemas` fue agregado en FastAPI `0.102.0`. ๐Ÿค“ diff --git a/docs/es/docs/how-to/testing-database.md b/docs/es/docs/how-to/testing-database.md index 2fa2603123..0717ea5ff7 100644 --- a/docs/es/docs/how-to/testing-database.md +++ b/docs/es/docs/how-to/testing-database.md @@ -1,7 +1,7 @@ -# Probando una Base de Datos { #testing-a-database } +# Escribiendo pruebas para una base de datos { #testing-a-database } Puedes estudiar sobre bases de datos, SQL y SQLModel en la documentaciรณn de SQLModel. ๐Ÿค“ Hay un mini tutorial sobre el uso de SQLModel con FastAPI. โœจ -Ese tutorial incluye una secciรณn sobre cรณmo probar bases de datos SQL. ๐Ÿ˜Ž +Ese tutorial incluye una secciรณn sobre escribir pruebas para bases de datos SQL. ๐Ÿ˜Ž diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index ffea0ed546..0544eb9ba4 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -40,7 +40,7 @@ Las funcionalidades clave son: * **Rรกpido**: Muy alto rendimiento, a la par con **NodeJS** y **Go** (gracias a Starlette y Pydantic). [Uno de los frameworks Python mรกs rรกpidos disponibles](#performance). * **Rรกpido de programar**: Aumenta la velocidad para desarrollar funcionalidades en aproximadamente un 200% a 300%. * * **Menos bugs**: Reduce en aproximadamente un 40% los errores inducidos por humanos (desarrolladores). * -* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. +* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. * **Fรกcil**: Diseรฑado para ser fรกcil de usar y aprender. Menos tiempo leyendo documentaciรณn. * **Corto**: Minimiza la duplicaciรณn de cรณdigo. Mรบltiples funcionalidades desde cada declaraciรณn de parรกmetro. Menos bugs. * **Robusto**: Obtรฉn cรณdigo listo para producciรณn. Con documentaciรณn interactiva automรกtica. @@ -368,7 +368,7 @@ item: Item * Validaciรณn de datos: * Errores automรกticos y claros cuando los datos son invรกlidos. * Validaciรณn incluso para objetos JSON profundamente anidados. -* Conversiรณn de datos de entrada: de la red a los datos y tipos de Python. Leyendo desde: +* Conversiรณn de datos de entrada: de la red a los datos y tipos de Python. Leyendo desde: * JSON. * Parรกmetros de path. * Parรกmetros de query. @@ -376,7 +376,7 @@ item: Item * Headers. * Forms. * Archivos. -* Conversiรณn de datos de salida: convirtiendo de datos y tipos de Python a datos de red (como JSON): +* Conversiรณn de datos de salida: convirtiendo de datos y tipos de Python a datos de red (como JSON): * Convertir tipos de Python (`str`, `int`, `float`, `bool`, `list`, etc). * Objetos `datetime`. * Objetos `UUID`. @@ -439,7 +439,7 @@ Para un ejemplo mรกs completo incluyendo mรกs funcionalidades, ve al Inyecciรณn de Dependencias** muy poderoso y fรกcil de usar. +* Un sistema de **Inyecciรณn de Dependencias** muy poderoso y fรกcil de usar. * Seguridad y autenticaciรณn, incluyendo soporte para **OAuth2** con **tokens JWT** y autenticaciรณn **HTTP Basic**. * Tรฉcnicas mรกs avanzadas (pero igualmente fรกciles) para declarar **modelos JSON profundamente anidados** (gracias a Pydantic). * Integraciรณn con **GraphQL** usando Strawberry y otros paquetes. @@ -524,7 +524,7 @@ Usadas por Starlette: * httpx - Requerido si deseas usar el `TestClient`. * jinja2 - Requerido si deseas usar la configuraciรณn de plantilla por defecto. -* python-multipart - Requerido si deseas soportar "parsing" de forms, con `request.form()`. +* python-multipart - Requerido si deseas soportar form "parsing", con `request.form()`. Usadas por FastAPI: diff --git a/docs/es/docs/project-generation.md b/docs/es/docs/project-generation.md index b4aa11d0dd..6d48d0be54 100644 --- a/docs/es/docs/project-generation.md +++ b/docs/es/docs/project-generation.md @@ -6,7 +6,7 @@ Puedes usar esta plantilla para comenzar, ya que incluye gran parte de la config Repositorio de GitHub: Plantilla Full Stack FastAPI -## Plantilla Full Stack FastAPI - Tecnologรญa y Funcionalidades { #full-stack-fastapi-template-technology-stack-and-features } +## Plantilla Full Stack FastAPI - Stack de tecnologรญa y funcionalidades { #full-stack-fastapi-template-technology-stack-and-features } - โšก [**FastAPI**](https://fastapi.tiangolo.com/es) para la API del backend en Python. - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM). diff --git a/docs/es/docs/python-types.md b/docs/es/docs/python-types.md index 60b50a08ff..28e2953d35 100644 --- a/docs/es/docs/python-types.md +++ b/docs/es/docs/python-types.md @@ -2,7 +2,7 @@ Python tiene soporte para "anotaciones de tipos" opcionales (tambiรฉn llamadas "type hints"). -Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el tipo de una variable. +Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el tipo de una variable. Al declarar tipos para tus variables, los editores y herramientas te pueden proporcionar un mejor soporte. @@ -22,7 +22,7 @@ Si eres un experto en Python, y ya sabes todo sobre las anotaciones de tipos, sa Comencemos con un ejemplo simple: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Llamar a este programa genera: @@ -34,9 +34,9 @@ La funciรณn hace lo siguiente: * Toma un `first_name` y `last_name`. * Convierte la primera letra de cada uno a mayรบsculas con `title()`. -* Concatena ambos con un espacio en el medio. +* Concatena ambos con un espacio en el medio. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Edรญtalo { #edit-it } @@ -78,7 +78,7 @@ Eso es todo. Esas son las "anotaciones de tipos": -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Eso no es lo mismo que declarar valores predeterminados como serรญa con: @@ -106,7 +106,7 @@ Con eso, puedes desplazarte, viendo las opciones, hasta que encuentres la que "t Revisa esta funciรณn, ya tiene anotaciones de tipos: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Porque el editor conoce los tipos de las variables, no solo obtienes autocompletado, tambiรฉn obtienes chequeo de errores: @@ -114,7 +114,7 @@ Porque el editor conoce los tipos de las variables, no solo obtienes autocomplet Ahora sabes que debes corregirlo, convertir `age` a un string con `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## Declaraciรณn de tipos { #declaring-types } @@ -133,29 +133,32 @@ Puedes usar, por ejemplo: * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Tipos genรฉricos con parรกmetros de tipo { #generic-types-with-type-parameters } +### Mรณdulo `typing` { #typing-module } -Hay algunas estructuras de datos que pueden contener otros valores, como `dict`, `list`, `set` y `tuple`. Y los valores internos tambiรฉn pueden tener su propio tipo. +Para algunos casos adicionales, podrรญas necesitar importar algunas cosas del mรณdulo `typing` de la standard library, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`: -Estos tipos que tienen tipos internos se denominan tipos "**genรฉricos**". Y es posible declararlos, incluso con sus tipos internos. +```python +from typing import Any -Para declarar esos tipos y los tipos internos, puedes usar el mรณdulo estรกndar de Python `typing`. Existe especรญficamente para soportar estas anotaciones de tipos. -#### Versiones mรกs recientes de Python { #newer-versions-of-python } - -La sintaxis que utiliza `typing` es **compatible** con todas las versiones, desde Python 3.6 hasta las versiones mรกs recientes, incluyendo Python 3.9, Python 3.10, etc. +def some_function(data: Any): + print(data) +``` -A medida que avanza Python, las **versiones mรกs recientes** vienen con soporte mejorado para estas anotaciones de tipos y en muchos casos ni siquiera necesitarรกs importar y usar el mรณdulo `typing` para declarar las anotaciones de tipos. +### Tipos genรฉricos { #generic-types } -Si puedes elegir una versiรณn mรกs reciente de Python para tu proyecto, podrรกs aprovechar esa simplicidad adicional. +Algunos tipos pueden tomar "parรกmetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "lista de strings" se declararรญa `list[str]`. -En toda la documentaciรณn hay ejemplos compatibles con cada versiรณn de Python (cuando hay una diferencia). +Estos tipos que pueden tomar parรกmetros de tipo se llaman **Tipos Genรฉricos** o **Genรฉricos**. -Por ejemplo, "**Python 3.6+**" significa que es compatible con Python 3.6 o superior (incluyendo 3.7, 3.8, 3.9, 3.10, etc). Y "**Python 3.9+**" significa que es compatible con Python 3.9 o superior (incluyendo 3.10, etc). +Puedes usar los mismos tipos integrados como genรฉricos (con corchetes y tipos dentro): -Si puedes usar las **รบltimas versiones de Python**, utiliza los ejemplos para la รบltima versiรณn, esos tendrรกn la **mejor y mรกs simple sintaxis**, por ejemplo, "**Python 3.10+**". +* `list` +* `tuple` +* `set` +* `dict` #### Lista { #list } @@ -167,7 +170,7 @@ Como tipo, pon `list`. Como la lista es un tipo que contiene algunos tipos internos, los pones entre corchetes: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | Informaciรณn @@ -193,7 +196,7 @@ Y aรบn asรญ, el editor sabe que es un `str` y proporciona soporte para eso. Harรญas lo mismo para declarar `tuple`s y `set`s: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} Esto significa: @@ -208,7 +211,7 @@ El primer parรกmetro de tipo es para las claves del `dict`. El segundo parรกmetro de tipo es para los valores del `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Esto significa: @@ -218,46 +221,22 @@ Esto significa: #### Union { #union } -Puedes declarar que una variable puede ser cualquier de **varios tipos**, por ejemplo, un `int` o un `str`. - -En Python 3.6 y posterior (incluyendo Python 3.10) puedes usar el tipo `Union` de `typing` y poner dentro de los corchetes los posibles tipos a aceptar. +Puedes declarar que una variable puede ser cualquiera de **varios tipos**, por ejemplo, un `int` o un `str`. -En Python 3.10 tambiรฉn hay una **nueva sintaxis** donde puedes poner los posibles tipos separados por una barra vertical (`|`). +Para definirlo usas la barra vertical (`|`) para separar ambos tipos. -//// tab | Python 3.10+ +Esto se llama una "uniรณn", porque la variable puede ser cualquiera en la uniรณn de esos dos conjuntos de tipos. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -En ambos casos, esto significa que `item` podrรญa ser un `int` o un `str`. +Esto significa que `item` podrรญa ser un `int` o un `str`. #### Posiblemente `None` { #possibly-none } Puedes declarar que un valor podrรญa tener un tipo, como `str`, pero que tambiรฉn podrรญa ser `None`. -En Python 3.6 y posteriores (incluyendo Python 3.10) puedes declararlo importando y usando `Optional` del mรณdulo `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Usar `Optional[str]` en lugar de solo `str` te permitirรก al editor ayudarte a detectar errores donde podrรญas estar asumiendo que un valor siempre es un `str`, cuando en realidad tambiรฉn podrรญa ser `None`. - -`Optional[Something]` es realmente un atajo para `Union[Something, None]`, son equivalentes. - -Esto tambiรฉn significa que en Python 3.10, puedes usar `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ Esto tambiรฉn significa que en Python 3.10, puedes usar `Something | None`: //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternativa - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### Uso de `Union` u `Optional` { #using-union-or-optional } - -Si estรกs usando una versiรณn de Python inferior a 3.10, aquรญ tienes un consejo desde mi punto de vista muy **subjetivo**: - -* ๐Ÿšจ Evita usar `Optional[SomeType]` -* En su lugar โœจ **usa `Union[SomeType, None]`** โœจ. - -Ambos son equivalentes y debajo son lo mismo, pero recomendarรญa `Union` en lugar de `Optional` porque la palabra "**opcional**" parecerรญa implicar que el valor es opcional, y en realidad significa "puede ser `None`", incluso si no es opcional y aรบn es requerido. - -Creo que `Union[SomeType, None]` es mรกs explรญcito sobre lo que significa. - -Se trata solo de las palabras y nombres. Pero esas palabras pueden afectar cรณmo tรบ y tus compaรฑeros de equipo piensan sobre el cรณdigo. - -Como ejemplo, tomemos esta funciรณn: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -El parรกmetro `name` estรก definido como `Optional[str]`, pero **no es opcional**, no puedes llamar a la funciรณn sin el parรกmetro: - -```Python -say_hi() # ยกOh, no, esto lanza un error! ๐Ÿ˜ฑ -``` - -El parรกmetro `name` sigue siendo **requerido** (no *opcional*) porque no tiene un valor predeterminado. Aรบn asรญ, `name` acepta `None` como valor: - -```Python -say_hi(name=None) # Esto funciona, None es vรกlido ๐ŸŽ‰ -``` - -La buena noticia es que, una vez que estรฉs en Python 3.10, no tendrรกs que preocuparte por eso, ya que podrรกs simplemente usar `|` para definir uniones de tipos: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -Y entonces no tendrรกs que preocuparte por nombres como `Optional` y `Union`. ๐Ÿ˜Ž - -#### Tipos genรฉricos { #generic-types } - -Estos tipos que toman parรกmetros de tipo en corchetes se llaman **Tipos Genรฉricos** o **Genรฉricos**, por ejemplo: - -//// tab | Python 3.10+ - -Puedes usar los mismos tipos integrados como genรฉricos (con corchetes y tipos dentro): - -* `list` -* `tuple` -* `set` -* `dict` - -Y, como con versiones anteriores de Python, desde el mรณdulo `typing`: - -* `Union` -* `Optional` -* ...y otros. - -En Python 3.10, como alternativa a usar los genรฉricos `Union` y `Optional`, puedes usar la barra vertical (`|`) para declarar uniones de tipos, eso es mucho mejor y mรกs simple. - -//// - -//// tab | Python 3.9+ - -Puedes usar los mismos tipos integrados como genรฉricos (con corchetes y tipos dentro): - -* `list` -* `tuple` -* `set` -* `dict` - -Y generics desde el mรณdulo `typing`: - -* `Union` -* `Optional` -* ...y otros. - -//// +Usar `str | None` en lugar de solo `str` te permitirรก al editor ayudarte a detectar errores donde podrรญas estar asumiendo que un valor siempre es un `str`, cuando en realidad tambiรฉn podrรญa ser `None`. ### Clases como tipos { #classes-as-types } @@ -363,11 +253,11 @@ Tambiรฉn puedes declarar una clase como el tipo de una variable. Digamos que tienes una clase `Person`, con un nombre: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Luego puedes declarar una variable para que sea de tipo `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} Y luego, nuevamente, obtienes todo el soporte del editor: @@ -403,19 +293,13 @@ Para saber mรกs sobre Required Optional fields. - -/// - ## Anotaciones de tipos con metadata { #type-hints-with-metadata-annotations } -Python tambiรฉn tiene una funcionalidad que permite poner **metadatos adicional** en estas anotaciones de tipos usando `Annotated`. +Python tambiรฉn tiene una funcionalidad que permite poner **metadata adicional** en estas anotaciones de tipos usando `Annotated`. -Desde Python 3.9, `Annotated` es parte de la standard library, asรญ que puedes importarlo desde `typing`. +Puedes importar `Annotated` desde `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Python en sรญ no hace nada con este `Annotated`. Y para los editores y otras herramientas, el tipo sigue siendo `str`. diff --git a/docs/es/docs/translation-banner.md b/docs/es/docs/translation-banner.md new file mode 100644 index 0000000000..e38f20cbbd --- /dev/null +++ b/docs/es/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ Traducciรณn por IA y humanos + +Esta traducciรณn fue hecha por IA guiada por humanos. ๐Ÿค + +Podrรญa tener errores al interpretar el significado original, o sonar poco natural, etc. ๐Ÿค– + +Puedes mejorar esta traducciรณn [ayudรกndonos a guiar mejor al LLM de IA](https://fastapi.tiangolo.com/es/contributing/#translations). + +[Versiรณn en inglรฉs](ENGLISH_VERSION_URL) + +/// diff --git a/docs/es/docs/tutorial/background-tasks.md b/docs/es/docs/tutorial/background-tasks.md index cc8a2c9cbe..10ad4b5ebb 100644 --- a/docs/es/docs/tutorial/background-tasks.md +++ b/docs/es/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ Esto incluye, por ejemplo: Primero, importa `BackgroundTasks` y define un parรกmetro en tu *path operation function* con una declaraciรณn de tipo de `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** crearรก el objeto de tipo `BackgroundTasks` por ti y lo pasarรก como ese parรกmetro. @@ -31,13 +31,13 @@ En este caso, la funciรณn de tarea escribirรก en un archivo (simulando el envรญo Y como la operaciรณn de escritura no usa `async` y `await`, definimos la funciรณn con un `def` normal: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Agregar la tarea en segundo plano { #add-the-background-task } Dentro de tu *path operation function*, pasa tu funciรณn de tarea al objeto de *background tasks* con el mรฉtodo `.add_task()`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` recibe como argumentos: diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md index 7938a12158..96b58a7207 100644 --- a/docs/es/docs/tutorial/bigger-applications.md +++ b/docs/es/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ Puedes crear las *path operations* para ese mรณdulo usando `APIRouter`. Lo importas y creas una "instance" de la misma manera que lo harรญas con la clase `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### *Path operations* con `APIRouter` { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ Y luego lo usas para declarar tus *path operations*. รšsalo de la misma manera que usarรญas la clase `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} Puedes pensar en `APIRouter` como una clase "mini `FastAPI`". @@ -117,7 +117,7 @@ Asรญ que las ponemos en su propio mรณdulo `dependencies` (`app/dependencies.py`) Ahora utilizaremos una dependencia simple para leer un header `X-Token` personalizado: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | Consejo @@ -149,7 +149,7 @@ Sabemos que todas las *path operations* en este mรณdulo tienen el mismo: Entonces, en lugar de agregar todo eso a cada *path operation*, podemos agregarlo al `APIRouter`. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} Como el path de cada *path operation* tiene que empezar con `/`, como en: @@ -208,7 +208,7 @@ Y necesitamos obtener la funciรณn de dependencia del mรณdulo `app.dependencies`, Asรญ que usamos un import relativo con `..` para las dependencias: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### Cรณmo funcionan los imports relativos { #how-relative-imports-work } @@ -279,7 +279,7 @@ No estamos agregando el prefijo `/items` ni los `tags=["items"]` a cada *path op Pero aรบn podemos agregar _mรกs_ `tags` que se aplicarรกn a una *path operation* especรญfica, y tambiรฉn algunas `responses` extra especรญficas para esa *path operation*: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | Consejo @@ -305,13 +305,13 @@ Importas y creas una clase `FastAPI` como normalmente. Y podemos incluso declarar [dependencias globales](dependencies/global-dependencies.md){.internal-link target=_blank} que se combinarรกn con las dependencias para cada `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### Importar el `APIRouter` { #import-the-apirouter } Ahora importamos los otros submรณdulos que tienen `APIRouter`s: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} Como los archivos `app/routers/users.py` y `app/routers/items.py` son submรณdulos que son parte del mismo paquete de Python `app`, podemos usar un solo punto `.` para importarlos usando "imports relativos". @@ -374,13 +374,13 @@ el `router` de `users` sobrescribirรญa el de `items` y no podrรญamos usarlos al Asรญ que, para poder usar ambos en el mismo archivo, importamos los submรณdulos directamente: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### Incluir los `APIRouter`s para `users` y `items` { #include-the-apirouters-for-users-and-items } Ahora, incluyamos los `router`s de los submรณdulos `users` y `items`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | Informaciรณn @@ -420,13 +420,13 @@ Contiene un `APIRouter` con algunas *path operations* de administraciรณn que tu Para este ejemplo serรก sรบper simple. Pero digamos que porque estรก compartido con otros proyectos en la organizaciรณn, no podemos modificarlo y agregar un `prefix`, `dependencies`, `tags`, etc. directamente al `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Pero aรบn queremos configurar un `prefix` personalizado al incluir el `APIRouter` para que todas sus *path operations* comiencen con `/admin`, queremos asegurarlo con las `dependencies` que ya tenemos para este proyecto, y queremos incluir `tags` y `responses`. Podemos declarar todo eso sin tener que modificar el `APIRouter` original pasando esos parรกmetros a `app.include_router()`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} De esa manera, el `APIRouter` original permanecerรก sin modificar, por lo que aรบn podemos compartir ese mismo archivo `app/internal/admin.py` con otros proyectos en la organizaciรณn. @@ -447,7 +447,7 @@ Tambiรฉn podemos agregar *path operations* directamente a la app de `FastAPI`. Aquรญ lo hacemos... solo para mostrar que podemos ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} y funcionarรก correctamente, junto con todas las otras *path operations* aรฑadidas con `app.include_router()`. diff --git a/docs/es/docs/tutorial/body-multiple-params.md b/docs/es/docs/tutorial/body-multiple-params.md index c52486f9b8..c78dd28812 100644 --- a/docs/es/docs/tutorial/body-multiple-params.md +++ b/docs/es/docs/tutorial/body-multiple-params.md @@ -104,12 +104,6 @@ Como, por defecto, los valores singulares se interpretan como parรกmetros de que q: str | None = None ``` -O en Python 3.9: - -```Python -q: Union[str, None] = None -``` - Por ejemplo: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/es/docs/tutorial/body-nested-models.md b/docs/es/docs/tutorial/body-nested-models.md index 0dfd6576f1..5f723e4c9f 100644 --- a/docs/es/docs/tutorial/body-nested-models.md +++ b/docs/es/docs/tutorial/body-nested-models.md @@ -164,7 +164,7 @@ images: list[Image] como en: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Soporte de editor en todas partes { #editor-support-everywhere } @@ -194,7 +194,7 @@ Eso es lo que vamos a ver aquรญ. En este caso, aceptarรญas cualquier `dict` siempre que tenga claves `int` con valores `float`: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Consejo diff --git a/docs/es/docs/tutorial/body.md b/docs/es/docs/tutorial/body.md index dde39f78c1..3adf2e65c5 100644 --- a/docs/es/docs/tutorial/body.md +++ b/docs/es/docs/tutorial/body.md @@ -74,7 +74,7 @@ Con solo esa declaraciรณn de tipo en Python, **FastAPI** harรก lo siguiente: * Proporcionar los datos recibidos en el parรกmetro `item`. * Como lo declaraste en la funciรณn como de tipo `Item`, tambiรฉn tendrรกs todo el soporte del editor (autocompletado, etc.) para todos los atributos y sus tipos. * Generar definiciones de JSON Schema para tu modelo, que tambiรฉn puedes usar en cualquier otro lugar si tiene sentido para tu proyecto. -* Esos esquemas serรกn parte del esquema de OpenAPI generado y usados por las UIs de documentaciรณn automรกtica. +* Esos esquemas serรกn parte del esquema de OpenAPI generado y usados por las UIs de documentaciรณn automรกtica. ## Documentaciรณn automรกtica { #automatic-docs } @@ -155,7 +155,7 @@ Los parรกmetros de la funciรณn se reconocerรกn de la siguiente manera: FastAPI sabrรก que el valor de `q` no es requerido debido al valor por defecto `= None`. -El `str | None` (Python 3.10+) o `Union` en `Union[str, None]` (Python 3.9+) no es utilizado por FastAPI para determinar que el valor no es requerido, sabrรก que no es requerido porque tiene un valor por defecto de `= None`. +El `str | None` no es utilizado por FastAPI para determinar que el valor no es requerido, sabrรก que no es requerido porque tiene un valor por defecto de `= None`. Pero agregar las anotaciones de tipos permitirรก que tu editor te brinde un mejor soporte y detecte errores. @@ -163,4 +163,4 @@ Pero agregar las anotaciones de tipos permitirรก que tu editor te brinde un mejo ## Sin Pydantic { #without-pydantic } -Si no quieres usar modelos de Pydantic, tambiรฉn puedes usar parรกmetros **Body**. Consulta la documentaciรณn para [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. +Si no quieres usar modelos de Pydantic, tambiรฉn puedes usar parรกmetros **Body**. Consulta la documentaciรณn para [Body - Mรบltiples parรกmetros: Valores singulares en el body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/es/docs/tutorial/cookie-param-models.md b/docs/es/docs/tutorial/cookie-param-models.md index dab7d8c0a2..4e6038a46b 100644 --- a/docs/es/docs/tutorial/cookie-param-models.md +++ b/docs/es/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ Pero incluso si **rellenas los datos** y haces clic en "Execute", como la UI de En algunos casos de uso especiales (probablemente no muy comunes), podrรญas querer **restringir** las cookies que deseas recibir. -Tu API ahora tiene el poder de controlar su propio consentimiento de cookies. ๐Ÿคช๐Ÿช +Tu API ahora tiene el poder de controlar su propio consentimiento de cookies. ๐Ÿคช๐Ÿช Puedes usar la configuraciรณn del modelo de Pydantic para `prohibir` cualquier campo `extra`: @@ -54,9 +54,9 @@ Puedes usar la configuraciรณn del modelo de Pydantic para `prohibir` cualquier c Si un cliente intenta enviar algunas **cookies extra**, recibirรกn un response de **error**. -Pobres banners de cookies con todo su esfuerzo para obtener tu consentimiento para que la API lo rechace. ๐Ÿช +Pobres banners de cookies con todo su esfuerzo para obtener tu consentimiento para que la API lo rechace. ๐Ÿช -Por ejemplo, si el cliente intenta enviar una cookie `santa_tracker` con un valor de `good-list-please`, el cliente recibirรก un response de **error** que le informa que la cookie `santa_tracker` no estรก permitida: +Por ejemplo, si el cliente intenta enviar una cookie `santa_tracker` con un valor de `good-list-please`, el cliente recibirรก un response de **error** que le informa que la `santa_tracker` cookie no estรก permitida: ```json { @@ -73,4 +73,4 @@ Por ejemplo, si el cliente intenta enviar una cookie `santa_tracker` con un valo ## Resumen { #summary } -Puedes usar **modelos de Pydantic** para declarar **cookies** en **FastAPI**. ๐Ÿ˜Ž +Puedes usar **modelos de Pydantic** para declarar **cookies** en **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/es/docs/tutorial/cors.md b/docs/es/docs/tutorial/cors.md index c1a23295e1..a118d814b0 100644 --- a/docs/es/docs/tutorial/cors.md +++ b/docs/es/docs/tutorial/cors.md @@ -46,7 +46,8 @@ Tambiรฉn puedes especificar si tu backend permite: * Mรฉtodos HTTP especรญficos (`POST`, `PUT`) o todos ellos con el comodรญn `"*"`. * Headers HTTP especรญficos o todos ellos con el comodรญn `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + Los parรกmetros predeterminados utilizados por la implementaciรณn de `CORSMiddleware` son restrictivos por defecto, por lo que necesitarรกs habilitar explรญcitamente orรญgenes, mรฉtodos o headers particulares para que los navegadores estรฉn permitidos de usarlos en un contexto de Cross-Domain. diff --git a/docs/es/docs/tutorial/debugging.md b/docs/es/docs/tutorial/debugging.md index c31daf40f4..a2d47f2da7 100644 --- a/docs/es/docs/tutorial/debugging.md +++ b/docs/es/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Puedes conectar el depurador en tu editor, por ejemplo con Visual Studio Code o En tu aplicaciรณn de FastAPI, importa y ejecuta `uvicorn` directamente: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### Acerca de `__name__ == "__main__"` { #about-name-main } diff --git a/docs/es/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/es/docs/tutorial/dependencies/classes-as-dependencies.md index a3a75efcd9..7506bda470 100644 --- a/docs/es/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/es/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ Ahora puedes declarar tu dependencia usando esta clase. Nota cรณmo escribimos `CommonQueryParams` dos veces en el cรณdigo anterior: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo @@ -137,7 +137,7 @@ Es a partir de este que **FastAPI** extraerรก los parรกmetros declarados y es lo En este caso, el primer `CommonQueryParams`, en: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo @@ -163,7 +163,7 @@ commons: CommonQueryParams ... De hecho, podrรญas escribir simplemente: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo @@ -197,7 +197,7 @@ Pero declarar el tipo es recomendable, ya que de esa manera tu editor sabrรก lo Pero ves que estamos teniendo algo de repeticiรณn de cรณdigo aquรญ, escribiendo `CommonQueryParams` dos veces: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo @@ -225,7 +225,7 @@ Para esos casos especรญficos, puedes hacer lo siguiente: En lugar de escribir: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...escribes: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ sin `Annotated` +//// tab | Python 3.10+ sin `Annotated` /// tip | Consejo diff --git a/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 60baa93a90..5eadbe7e1f 100644 --- a/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ El decorador de *path operation* recibe un argumento opcional `dependencies`. Debe ser una `list` de `Depends()`: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} Estas dependencias serรกn ejecutadas/resueltas de la misma manera que las dependencias normales. Pero su valor (si devuelven alguno) no serรก pasado a tu *path operation function*. @@ -44,13 +44,13 @@ Puedes usar las mismas *funciones* de dependencia que usas normalmente. Pueden declarar requisitos de request (como headers) u otras sub-dependencias: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### Lanzar excepciones { #raise-exceptions } Estas dependencias pueden `raise` excepciones, igual que las dependencias normales: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### Valores de retorno { #return-values } @@ -58,7 +58,7 @@ Y pueden devolver valores o no, los valores no serรกn usados. Asรญ que, puedes reutilizar una dependencia normal (que devuelve un valor) que ya uses en otro lugar, y aunque el valor no se use, la dependencia serรก ejecutada: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## Dependencias para un grupo de *path operations* { #dependencies-for-a-group-of-path-operations } diff --git a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md index aa645daa47..2cd68eddd2 100644 --- a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Dependencias con yield { #dependencies-with-yield } -FastAPI admite dependencias que realizan algunos pasos adicionales despuรฉs de finalizar. +FastAPI admite dependencias que realizan algunos pasos adicionales despuรฉs de finalizar. Para hacer esto, usa `yield` en lugar de `return`, y escribe los pasos adicionales (cรณdigo) despuรฉs. @@ -29,15 +29,15 @@ Por ejemplo, podrรญas usar esto para crear una sesiรณn de base de datos y cerrar Solo el cรณdigo anterior e incluyendo la declaraciรณn `yield` se ejecuta antes de crear un response: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} El valor generado es lo que se inyecta en *path operations* y otras dependencias: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} El cรณdigo posterior a la declaraciรณn `yield` se ejecuta despuรฉs del response: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | Consejo @@ -57,7 +57,7 @@ Por lo tanto, puedes buscar esa excepciรณn especรญfica dentro de la dependencia Del mismo modo, puedes usar `finally` para asegurarte de que los pasos de salida se ejecuten, sin importar si hubo una excepciรณn o no. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## Sub-dependencias con `yield` { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ Puedes tener sub-dependencias y "รกrboles" de sub-dependencias de cualquier tama Por ejemplo, `dependency_c` puede tener una dependencia de `dependency_b`, y `dependency_b` de `dependency_a`: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} Y todas ellas pueden usar `yield`. @@ -75,7 +75,7 @@ En este caso, `dependency_c`, para ejecutar su cรณdigo de salida, necesita que e Y, a su vez, `dependency_b` necesita que el valor de `dependency_a` (aquรญ llamado `dep_a`) estรฉ disponible para su cรณdigo de salida. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} De la misma manera, podrรญas tener algunas dependencias con `yield` y otras dependencias con `return`, y hacer que algunas de esas dependan de algunas de las otras. @@ -109,7 +109,7 @@ Pero estรก ahรญ para ti si la necesitas. ๐Ÿค“ /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} Si quieres capturar excepciones y crear un response personalizado en base a eso, crea un [Manejador de Excepciones Personalizado](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. @@ -117,7 +117,7 @@ Si quieres capturar excepciones y crear un response personalizado en base a eso, Si capturas una excepciรณn usando `except` en una dependencia con `yield` y no la lanzas nuevamente (o lanzas una nueva excepciรณn), FastAPI no podrรก notar que hubo una excepciรณn, al igual que sucederรญa con Python normal: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} En este caso, el cliente verรก un response *HTTP 500 Internal Server Error* como deberรญa, dado que no estamos lanzando una `HTTPException` o similar, pero el servidor **no tendrรก ningรบn registro** ni ninguna otra indicaciรณn de cuรกl fue el error. ๐Ÿ˜ฑ @@ -127,7 +127,7 @@ Si capturas una excepciรณn en una dependencia con `yield`, a menos que estรฉs la Puedes volver a lanzar la misma excepciรณn usando `raise`: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Ahora el cliente obtendrรก el mismo response *HTTP 500 Internal Server Error*, pero el servidor tendrรก nuestro `InternalError` personalizado en los registros. ๐Ÿ˜Ž @@ -190,7 +190,7 @@ Normalmente, el cรณdigo de salida de las dependencias con `yield` se ejecuta **d Pero si sabes que no necesitarรกs usar la dependencia despuรฉs de regresar de la *path operation function*, puedes usar `Depends(scope="function")` para decirle a FastAPI que debe cerrar la dependencia despuรฉs de que la *path operation function* regrese, pero **antes** de que se envรญe el **response**. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` recibe un parรกmetro `scope` que puede ser: @@ -234,7 +234,6 @@ participant operation as Path Operation Las dependencias con `yield` han evolucionado con el tiempo para cubrir diferentes casos de uso y corregir algunos problemas. Si quieres ver quรฉ ha cambiado en diferentes versiones de FastAPI, puedes leer mรกs al respecto en la guรญa avanzada, en [Dependencias avanzadas - Dependencias con `yield`, `HTTPException`, `except` y Tareas en Background](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}. - ## Context Managers { #context-managers } ### Quรฉ son los "Context Managers" { #what-are-context-managers } @@ -270,7 +269,7 @@ En Python, puedes crear Context Managers Inyecciรณn de Dependencias** muy poderoso pero intuitivo. +**FastAPI** tiene un sistema de **Inyecciรณn de Dependencias** muy poderoso pero intuitivo. Estรก diseรฑado para ser muy simple de usar, y para hacer que cualquier desarrollador integre otros componentes con **FastAPI** de forma muy sencilla. diff --git a/docs/es/docs/tutorial/dependencies/sub-dependencies.md b/docs/es/docs/tutorial/dependencies/sub-dependencies.md index e74d65d7e9..95f3fe8174 100644 --- a/docs/es/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/es/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query Si una de tus dependencias se declara varias veces para la misma *path operation*, por ejemplo, mรบltiples dependencias tienen una sub-dependencia comรบn, **FastAPI** sabrรก llamar a esa sub-dependencia solo una vez por request. -Y guardarรก el valor devuelto en un "cache" y lo pasarรก a todos los "dependants" que lo necesiten en ese request especรญfico, en lugar de llamar a la dependencia varias veces para el mismo request. +Y guardarรก el valor devuelto en un "cachรฉ" y lo pasarรก a todos los "dependants" que lo necesiten en ese request especรญfico, en lugar de llamar a la dependencia varias veces para el mismo request. -En un escenario avanzado donde sabes que necesitas que la dependencia se llame en cada paso (posiblemente varias veces) en el mismo request en lugar de usar el valor "cache", puedes establecer el parรกmetro `use_cache=False` al usar `Depends`: +En un escenario avanzado donde sabes que necesitas que la dependencia se llame en cada paso (posiblemente varias veces) en el mismo request en lugar de usar el valor "en cachรฉ", puedes establecer el parรกmetro `use_cache=False` al usar `Depends`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ sin Anotaciones +//// tab | Python 3.10+ sin Anotaciones /// tip | Consejo diff --git a/docs/es/docs/tutorial/encoder.md b/docs/es/docs/tutorial/encoder.md index 319ae1bde8..df6099a8b9 100644 --- a/docs/es/docs/tutorial/encoder.md +++ b/docs/es/docs/tutorial/encoder.md @@ -26,7 +26,7 @@ En este ejemplo, convertirรญa el modelo de Pydantic a un `dict`, y el `datetime` El resultado de llamarlo es algo que puede ser codificado con la funciรณn estรกndar de Python `json.dumps()`. -No devuelve un gran `str` que contenga los datos en formato JSON (como una cadena de texto). Devuelve una estructura de datos estรกndar de Python (por ejemplo, un `dict`) con valores y sub-valores que son todos compatibles con JSON. +No devuelve un gran `str` que contenga los datos en formato JSON (como un string). Devuelve una estructura de datos estรกndar de Python (por ejemplo, un `dict`) con valores y sub-valores que son todos compatibles con JSON. /// note | Nota diff --git a/docs/es/docs/tutorial/extra-models.md b/docs/es/docs/tutorial/extra-models.md index d72c73e245..4621b2db2e 100644 --- a/docs/es/docs/tutorial/extra-models.md +++ b/docs/es/docs/tutorial/extra-models.md @@ -190,9 +190,9 @@ Pero si ponemos eso en la asignaciรณn `response_model=PlaneItem | CarItem` obten De la misma manera, puedes declarar responses de listas de objetos. -Para eso, usa el `typing.List` estรกndar de Python (o simplemente `list` en Python 3.9 y posteriores): +Para eso, usa la `list` estรกndar de Python: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## Response con `dict` arbitrario { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ Tambiรฉn puedes declarar un response usando un `dict` arbitrario plano, declaran Esto es รบtil si no conoces los nombres de los campos/atributos vรกlidos (que serรญan necesarios para un modelo Pydantic) de antemano. -En este caso, puedes usar `typing.Dict` (o solo `dict` en Python 3.9 y posteriores): +En este caso, puedes usar `dict`: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## Recapitulaciรณn { #recap } diff --git a/docs/es/docs/tutorial/first-steps.md b/docs/es/docs/tutorial/first-steps.md index 789b2a0110..b7ffd2c2ab 100644 --- a/docs/es/docs/tutorial/first-steps.md +++ b/docs/es/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ El archivo FastAPI mรกs simple podrรญa verse asรญ: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Copia eso en un archivo `main.py`. @@ -56,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) Esa lรญnea muestra la URL donde tu aplicaciรณn estรก siendo servida, en tu mรกquina local. -### Compruรฉbalo { #check-it } +### Revisa { #check-it } Abre tu navegador en http://127.0.0.1:8000. @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### Paso 1: importa `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` es una clase de Python que proporciona toda la funcionalidad para tu API. @@ -197,7 +197,7 @@ Puedes usar toda la funcionalidad de get operation +* usando una get operaciรณn /// info | Informaciรณn sobre `@decorator` @@ -320,7 +320,7 @@ Esta es nuestra "**path operation function**": * **operation**: es `get`. * **function**: es la funciรณn debajo del "decorador" (debajo de `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Esta es una funciรณn de Python. @@ -332,7 +332,7 @@ En este caso, es una funciรณn `async`. Tambiรฉn podrรญas definirla como una funciรณn normal en lugar de `async def`: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | Nota @@ -342,7 +342,7 @@ Si no sabes la diferencia, Revisa la secciรณn [Async: *"ยฟTienes prisa?"*](../as ### Paso 5: retorna el contenido { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Puedes retornar un `dict`, `list`, valores singulares como `str`, `int`, etc. diff --git a/docs/es/docs/tutorial/handling-errors.md b/docs/es/docs/tutorial/handling-errors.md index 71e0563203..265269e874 100644 --- a/docs/es/docs/tutorial/handling-errors.md +++ b/docs/es/docs/tutorial/handling-errors.md @@ -25,7 +25,7 @@ Para devolver responses HTTP con errores al cliente, usa `HTTPException`. ### Importa `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### Lanza un `HTTPException` en tu cรณdigo { #raise-an-httpexception-in-your-code } @@ -39,7 +39,7 @@ El beneficio de lanzar una excepciรณn en lugar de `return`ar un valor serรก mรกs En este ejemplo, cuando el cliente solicita un รญtem por un ID que no existe, lanza una excepciรณn con un cรณdigo de estado de `404`: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### El response resultante { #the-resulting-response } @@ -77,7 +77,7 @@ Probablemente no necesitarรกs usarlos directamente en tu cรณdigo. Pero en caso de que los necesites para un escenario avanzado, puedes agregar headers personalizados: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## Instalar manejadores de excepciones personalizados { #install-custom-exception-handlers } @@ -89,7 +89,7 @@ Y quieres manejar esta excepciรณn globalmente con FastAPI. Podrรญas agregar un manejador de excepciones personalizado con `@app.exception_handler()`: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} Aquรญ, si solicitas `/unicorns/yolo`, la *path operation* lanzarรก un `UnicornException`. @@ -127,7 +127,7 @@ Para sobrescribirlo, importa el `RequestValidationError` y รบsalo con `@app.exce El manejador de excepciones recibirรก un `Request` y la excepciรณn. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} Ahora, si vas a `/items/foo`, en lugar de obtener el error JSON por defecto con: @@ -159,7 +159,7 @@ De la misma manera, puedes sobrescribir el manejador de `HTTPException`. Por ejemplo, podrรญas querer devolver un response de texto plano en lugar de JSON para estos errores: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | Nota Tรฉcnica @@ -183,7 +183,7 @@ El `RequestValidationError` contiene el `body` que recibiรณ con datos invรกlidos Podrรญas usarlo mientras desarrollas tu aplicaciรณn para registrar el body y depurarlo, devolverlo al usuario, etc. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} Ahora intenta enviar un รญtem invรกlido como: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException Si quieres usar la excepciรณn junto con los mismos manejadores de excepciones predeterminados de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones predeterminados de `fastapi.exception_handlers`: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} En este ejemplo solo estรกs `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepciรณn y luego simplemente reutilizar los manejadores de excepciones predeterminados. diff --git a/docs/es/docs/tutorial/metadata.md b/docs/es/docs/tutorial/metadata.md index a5d9b5eadc..2163a1cb22 100644 --- a/docs/es/docs/tutorial/metadata.md +++ b/docs/es/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ Puedes establecer los siguientes campos que se usan en la especificaciรณn OpenAP Puedes configurarlos de la siguiente manera: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | Consejo @@ -36,7 +36,7 @@ Desde OpenAPI 3.1.0 y FastAPI 0.99.0, tambiรฉn puedes establecer la `license_inf Por ejemplo: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## Metadata para etiquetas { #metadata-for-tags } @@ -58,7 +58,7 @@ Probemos eso en un ejemplo con etiquetas para `users` y `items`. Crea metadata para tus etiquetas y pรกsala al parรกmetro `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} Nota que puedes utilizar Markdown dentro de las descripciones, por ejemplo "login" se mostrarรก en negrita (**login**) y "fancy" se mostrarรก en cursiva (_fancy_). @@ -72,7 +72,7 @@ No tienes que agregar metadata para todas las etiquetas que uses. Usa el parรกmetro `tags` con tus *path operations* (y `APIRouter`s) para asignarlas a diferentes etiquetas: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | Informaciรณn @@ -100,7 +100,7 @@ Pero puedes configurarlo con el parรกmetro `openapi_url`. Por ejemplo, para configurarlo para que se sirva en `/api/v1/openapi.json`: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} Si quieres deshabilitar el esquema OpenAPI completamente, puedes establecer `openapi_url=None`, eso tambiรฉn deshabilitarรก las interfaces de usuario de documentaciรณn que lo usan. @@ -117,4 +117,4 @@ Puedes configurar las dos interfaces de usuario de documentaciรณn incluidas: Por ejemplo, para configurar Swagger UI para que se sirva en `/documentation` y deshabilitar ReDoc: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/es/docs/tutorial/middleware.md b/docs/es/docs/tutorial/middleware.md index de636a4854..766e30cad6 100644 --- a/docs/es/docs/tutorial/middleware.md +++ b/docs/es/docs/tutorial/middleware.md @@ -31,7 +31,7 @@ La funciรณn middleware recibe: * Luego devuelve la `response` generada por la correspondiente *path operation*. * Puedes entonces modificar aรบn mรกs la `response` antes de devolverla. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} /// tip | Consejo @@ -57,7 +57,7 @@ Y tambiรฉn despuรฉs de que se genere la `response`, antes de devolverla. Por ejemplo, podrรญas aรฑadir un custom header `X-Process-Time` que contenga el tiempo en segundos que tomรณ procesar la request y generar una response: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} /// tip | Consejo diff --git a/docs/es/docs/tutorial/path-operation-configuration.md b/docs/es/docs/tutorial/path-operation-configuration.md index f57b322fbb..90e4335b3b 100644 --- a/docs/es/docs/tutorial/path-operation-configuration.md +++ b/docs/es/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ En estos casos, podrรญa tener sentido almacenar las tags en un `Enum`. **FastAPI** soporta eso de la misma manera que con strings normales: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## Resumen y Descripciรณn { #summary-and-description } @@ -56,7 +56,7 @@ Puedes aรฑadir un `summary` y `description`: ## Descripciรณn desde docstring { #description-from-docstring } -Como las descripciones tienden a ser largas y cubrir mรบltiples lรญneas, puedes declarar la descripciรณn de la *path operation* en la docstring de la funciรณn y **FastAPI** la leerรก desde allรญ. +Como las descripciones tienden a ser largas y cubrir mรบltiples lรญneas, puedes declarar la descripciรณn de la *path operation* en la docstring de la funciรณn y **FastAPI** la leerรก desde allรญ. Puedes escribir Markdown en el docstring, se interpretarรก y mostrarรก correctamente (teniendo en cuenta la indentaciรณn del docstring). @@ -90,9 +90,9 @@ Entonces, si no proporcionas una, **FastAPI** generarรก automรกticamente una de ## Deprecar una *path operation* { #deprecate-a-path-operation } -Si necesitas marcar una *path operation* como deprecated, pero sin eliminarla, pasa el parรกmetro `deprecated`: +Si necesitas marcar una *path operation* como deprecated, pero sin eliminarla, pasa el parรกmetro `deprecated`: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} Se marcarรก claramente como deprecado en la documentaciรณn interactiva: diff --git a/docs/es/docs/tutorial/path-params-numeric-validations.md b/docs/es/docs/tutorial/path-params-numeric-validations.md index 569dd03dd0..3a38d1d63c 100644 --- a/docs/es/docs/tutorial/path-params-numeric-validations.md +++ b/docs/es/docs/tutorial/path-params-numeric-validations.md @@ -2,7 +2,7 @@ De la misma manera que puedes declarar mรกs validaciones y metadatos para los parรกmetros de query con `Query`, puedes declarar el mismo tipo de validaciones y metadatos para los parรกmetros de path con `Path`. -## Importar Path { #import-path } +## Importar `Path` { #import-path } Primero, importa `Path` de `fastapi`, e importa `Annotated`: @@ -46,19 +46,19 @@ Y no necesitas declarar nada mรกs para ese parรกmetro, asรญ que realmente no nec Pero aรบn necesitas usar `Path` para el parรกmetro de path `item_id`. Y no quieres usar `Annotated` por alguna razรณn. -Python se quejarรก si pones un valor con un "default" antes de un valor que no tenga un "default". +Python se quejarรก si pones un valor con "por defecto" antes de un valor que no tenga "por defecto". -Pero puedes reordenarlos y poner el valor sin un default (el parรกmetro de query `q`) primero. +Pero puedes reordenarlos y poner el valor sin un valor por defecto (el parรกmetro de query `q`) primero. -No importa para **FastAPI**. Detectarรก los parรกmetros por sus nombres, tipos y declaraciones por defecto (`Query`, `Path`, etc.), no le importa el orden. +No importa para **FastAPI**. Detectarรก los parรกmetros por sus nombres, tipos y declaraciones por defecto (`Query`, `Path`, etc), no le importa el orden. Asรญ que puedes declarar tu funciรณn como: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Pero ten en cuenta que si usas `Annotated`, no tendrรกs este problema, no importarรก ya que no estรกs usando los valores por defecto de los parรกmetros de la funciรณn para `Query()` o `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Ordena los parรกmetros como necesites, trucos { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ Pasa `*`, como el primer parรกmetro de la funciรณn. Python no harรก nada con ese `*`, pero sabrรก que todos los parรกmetros siguientes deben ser llamados como argumentos de palabras clave (parejas key-value), tambiรฉn conocidos como kwargs. Incluso si no tienen un valor por defecto. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Mejor con `Annotated` { #better-with-annotated } Ten en cuenta que si usas `Annotated`, como no estรกs usando valores por defecto de los parรกmetros de la funciรณn, no tendrรกs este problema y probablemente no necesitarรกs usar `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Validaciones numรฉricas: mayor o igual { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Con `Query` y `Path` (y otros que verรกs mรกs adelante) puedes declarar restricc Aquรญ, con `ge=1`, `item_id` necesitarรก ser un nรบmero entero "`g`reater than or `e`qual" a `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Validaciones numรฉricas: mayor que y menor o igual { #number-validations-greater-than-and-less-than-or-equal } @@ -106,19 +106,19 @@ Lo mismo aplica para: * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Validaciones numรฉricas: flotantes, mayor y menor { #number-validations-floats-greater-than-and-less-than } Las validaciones numรฉricas tambiรฉn funcionan para valores `float`. -Aquรญ es donde se convierte en importante poder declarar gt y no solo ge. Ya que con esto puedes requerir, por ejemplo, que un valor sea mayor que `0`, incluso si es menor que `1`. +Aquรญ es donde se convierte en importante poder declarar gt y no solo ge. Ya que con esto puedes requerir, por ejemplo, que un valor sea mayor que `0`, incluso si es menor que `1`. Asรญ, `0.5` serรญa un valor vรกlido. Pero `0.0` o `0` no lo serรญan. -Y lo mismo para lt. +Y lo mismo para lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Resumen { #recap } diff --git a/docs/es/docs/tutorial/path-params.md b/docs/es/docs/tutorial/path-params.md index 7ba49f3b0b..8dc3db351d 100644 --- a/docs/es/docs/tutorial/path-params.md +++ b/docs/es/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Puedes declarar "parรกmetros" o "variables" de path con la misma sintaxis que se usa en los format strings de Python: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} El valor del parรกmetro de path `item_id` se pasarรก a tu funciรณn como el argumento `item_id`. @@ -16,7 +16,7 @@ Asรญ que, si ejecutas este ejemplo y vas a Conversiรณn de datos { #data-conversion } +## Conversiรณn de datos { #data-conversion } Si ejecutas este ejemplo y abres tu navegador en http://127.0.0.1:8000/items/3, verรกs un response de: @@ -38,7 +38,7 @@ Si ejecutas este ejemplo y abres tu navegador en "parsing" automรกtico de request. +Entonces, con esa declaraciรณn de tipo, **FastAPI** te ofrece "parsing" automรกtico de request. /// @@ -118,13 +118,13 @@ Y luego tambiรฉn puedes tener un path `/users/{user_id}` para obtener datos sobr Debido a que las *path operations* se evalรบan en orden, necesitas asegurarte de que el path para `/users/me` se declara antes que el de `/users/{user_id}`: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} De lo contrario, el path para `/users/{user_id}` tambiรฉn coincidirรญa para `/users/me`, "pensando" que estรก recibiendo un parรกmetro `user_id` con un valor de `"me"`. De manera similar, no puedes redefinir una path operation: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} La primera siempre serรก utilizada ya que el path coincide primero. @@ -140,11 +140,11 @@ Al heredar de `str`, la documentaciรณn de la API podrรก saber que los valores de Luego crea atributos de clase con valores fijos, que serรกn los valores vรกlidos disponibles: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | Consejo -Si te estรกs preguntando, "AlexNet", "ResNet" y "LeNet" son solo nombres de modelos de Machine Learning. +Si te estรกs preguntando, "AlexNet", "ResNet" y "LeNet" son solo nombres de modelos de Machine Learning. /// @@ -152,7 +152,7 @@ Si te estรกs preguntando, "AlexNet", "ResNet" y "LeNet" son solo nombres de parsing" de datos +* " parsing " de datos * Validaciรณn de datos * Anotaciรณn de API y documentaciรณn automรกtica diff --git a/docs/es/docs/tutorial/query-params-str-validations.md b/docs/es/docs/tutorial/query-params-str-validations.md index 4af4782f83..b4339e1931 100644 --- a/docs/es/docs/tutorial/query-params-str-validations.md +++ b/docs/es/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Tener `str | None` permitirรก que tu editor te dรฉ un mejor soporte y detecte er ## Validaciones adicionales { #additional-validation } -Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, **su longitud no exceda los 50 caracteres**. +Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, su longitud no exceda los 50 caracteres. ### Importar `Query` y `Annotated` { #import-query-and-annotated } @@ -47,40 +47,16 @@ Ahora es el momento de usarlo con FastAPI. ๐Ÿš€ Tenรญamos esta anotaciรณn de tipo: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - Lo que haremos es envolver eso con `Annotated`, para que se convierta en: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Ambas versiones significan lo mismo, `q` es un parรกmetro que puede ser un `str` o `None`, y por defecto, es `None`. Ahora vamos a lo divertido. ๐ŸŽ‰ @@ -93,7 +69,7 @@ Ahora que tenemos este `Annotated` donde podemos poner mรกs informaciรณn (en est Nota que el valor por defecto sigue siendo `None`, por lo que el parรกmetro sigue siendo opcional. -Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga **validaciรณn adicional** para este valor, queremos que tenga un mรกximo de 50 caracteres. ๐Ÿ˜Ž +Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga validaciรณn adicional para este valor, queremos que tenga un mรกximo de 50 caracteres. ๐Ÿ˜Ž /// tip | Consejo @@ -103,13 +79,13 @@ Aquรญ estamos usando `Query()` porque este es un **parรกmetro de query**. Mรกs a FastAPI ahora: -* **Validarรก** los datos asegurรกndose de que la longitud mรกxima sea de 50 caracteres -* Mostrarรก un **error claro** para el cliente cuando los datos no sean vรกlidos -* **Documentarรก** el parรกmetro en el OpenAPI esquema *path operation* (asรญ aparecerรก en la **UI de documentaciรณn automรกtica**) +* Validarรก los datos asegurรกndose de que la longitud mรกxima sea de 50 caracteres +* Mostrarรก un error claro para el cliente cuando los datos no sean vรกlidos +* Documentarรก el parรกmetro en el OpenAPI esquema *path operation* (asรญ aparecerรก en la UI de documentaciรณn automรกtica) ## Alternativa (antigua): `Query` como valor por defecto { #alternative-old-query-as-the-default-value } -Versiones anteriores de FastAPI (antes de 0.95.0) requerรญan que usaras `Query` como el valor por defecto de tu parรกmetro, en lugar de ponerlo en `Annotated`, hay una alta probabilidad de que veas cรณdigo usรกndolo alrededor, asรญ que te lo explicarรฉ. +Versiones anteriores de FastAPI (antes de 0.95.0) requerรญan que usaras `Query` como el valor por defecto de tu parรกmetro, en lugar de ponerlo en `Annotated`, hay una alta probabilidad de que veas cรณdigo usรกndolo alrededor, asรญ que te lo explicarรฉ. /// tip | Consejo @@ -174,13 +150,13 @@ q: str = Query(default="rick") ### Ventajas de `Annotated` { #advantages-of-annotated } -**Usar `Annotated` es recomendado** en lugar del valor por defecto en los parรกmetros de funciรณn, es **mejor** por mรบltiples razones. ๐Ÿค“ +Usar `Annotated` es recomendado en lugar del valor por defecto en los parรกmetros de funciรณn, es mejor por mรบltiples razones. ๐Ÿค“ -El valor **por defecto** del **parรกmetro de funciรณn** es el valor **real por defecto**, eso es mรกs intuitivo con Python en general. ๐Ÿ˜Œ +El valor por defecto del parรกmetro de funciรณn es el valor real por defecto, eso es mรกs intuitivo con Python en general. ๐Ÿ˜Œ -Podrรญas **llamar** a esa misma funciรณn en **otros lugares** sin FastAPI, y **funcionarรญa como se espera**. Si hay un parรกmetro **requerido** (sin un valor por defecto), tu **editor** te avisarรก con un error, **Python** tambiรฉn se quejarรก si lo ejecutas sin pasar el parรกmetro requerido. +Podrรญas llamar a esa misma funciรณn en otros lugares sin FastAPI, y funcionarรญa como se espera. Si hay un parรกmetro requerido (sin un valor por defecto), tu editor te avisarรก con un error, Python tambiรฉn se quejarรก si lo ejecutas sin pasar el parรกmetro requerido. -Cuando no usas `Annotated` y en su lugar usas el estilo de valor por defecto **(antiguo)**, si llamas a esa funciรณn sin FastAPI en **otros lugares**, tienes que **recordar** pasar los argumentos a la funciรณn para que funcione correctamente, de lo contrario, los valores serรกn diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejarรก, y Python no se quejarรก al ejecutar esa funciรณn, solo cuando los errores dentro de las operaciones hagan que funcione incorrectamente. +Cuando no usas `Annotated` y en su lugar usas el estilo de valor por defecto (antiguo), si llamas a esa funciรณn sin FastAPI en otros lugares, tienes que recordar pasar los argumentos a la funciรณn para que funcione correctamente, de lo contrario, los valores serรกn diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejarรก, y Python no se quejarรก al ejecutar esa funciรณn, solo cuando los errores dentro de las operaciones hagan que funcione incorrectamente. Dado que `Annotated` puede tener mรกs de una anotaciรณn de metadato, ahora podrรญas incluso usar la misma funciรณn con otras herramientas, como Typer. ๐Ÿš€ @@ -192,7 +168,7 @@ Tambiรฉn puedes agregar un parรกmetro `min_length`: ## Agregar expresiones regulares { #add-regular-expressions } -Puedes definir una expresiรณn regular `pattern` que el parรกmetro debe coincidir: +Puedes definir una expresiรณn regular `pattern` que el parรกmetro debe coincidir: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -202,7 +178,7 @@ Este patrรณn especรญfico de expresiรณn regular comprueba que el valor recibido d * `fixedquery`: tiene el valor exacto `fixedquery`. * `$`: termina allรญ, no tiene mรกs caracteres despuรฉs de `fixedquery`. -Si te sientes perdido con todas estas ideas de **"expresiรณn regular"**, no te preocupes. Son un tema difรญcil para muchas personas. Aรบn puedes hacer muchas cosas sin necesitar expresiones regulares todavรญa. +Si te sientes perdido con todas estas ideas de "expresiรณn regular", no te preocupes. Son un tema difรญcil para muchas personas. Aรบn puedes hacer muchas cosas sin necesitar expresiones regulares todavรญa. Ahora sabes que cuando las necesites puedes usarlas en **FastAPI**. @@ -212,7 +188,7 @@ Puedes, por supuesto, usar valores por defecto diferentes de `None`. Digamos que quieres declarar el parรกmetro de query `q` para que tenga un `min_length` de `3`, y para que tenga un valor por defecto de `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Nota @@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Asรญ que, cuando necesites declarar un valor como requerido mientras usas `Query`, simplemente puedes no declarar un valor por defecto: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Requerido, puede ser `None` { #required-can-be-none } @@ -293,7 +269,7 @@ La documentaciรณn interactiva de API se actualizarรก en consecuencia, para permi Tambiรฉn puedes definir un valor por defecto `list` de valores si no se proporciona ninguno: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Si vas a: @@ -316,7 +292,7 @@ el valor por defecto de `q` serรก: `["foo", "bar"]` y tu response serรก: Tambiรฉn puedes usar `list` directamente en lugar de `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Nota @@ -372,7 +348,7 @@ Entonces puedes declarar un `alias`, y ese alias serรก usado para encontrar el v Ahora digamos que ya no te gusta este parรกmetro. -Tienes que dejarlo allรญ por un tiempo porque hay clientes usรกndolo, pero quieres que la documentaciรณn lo muestre claramente como deprecated. +Tienes que dejarlo allรญ por un tiempo porque hay clientes usรกndolo, pero quieres que la documentaciรณn lo muestre claramente como obsoleto. Luego pasa el parรกmetro `deprecated=True` a `Query`: @@ -390,9 +366,9 @@ Para excluir un parรกmetro de query del esquema de OpenAPI generado (y por lo ta ## Validaciรณn personalizada { #custom-validation } -Podrรญa haber casos donde necesites hacer alguna **validaciรณn personalizada** que no puede hacerse con los parรกmetros mostrados arriba. +Podrรญa haber casos donde necesites hacer alguna validaciรณn personalizada que no puede hacerse con los parรกmetros mostrados arriba. -En esos casos, puedes usar una **funciรณn validadora personalizada** que se aplique despuรฉs de la validaciรณn normal (por ejemplo, despuรฉs de validar que el valor es un `str`). +En esos casos, puedes usar una funciรณn validadora personalizada que se aplique despuรฉs de la validaciรณn normal (por ejemplo, despuรฉs de validar que el valor es un `str`). Puedes lograr eso usando `AfterValidator` de Pydantic dentro de `Annotated`. @@ -402,7 +378,7 @@ Pydantic tambiรฉn tiene ISBN o con `imdb-` para un ID de URL de pelรญcula de IMDB: +Por ejemplo, este validador personalizado comprueba que el ID del รญtem empiece con `isbn-` para un nรบmero de libro ISBN o con `imdb-` para un ID de URL de pelรญcula de IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -414,15 +390,15 @@ Esto estรก disponible con Pydantic versiรณn 2 o superior. ๐Ÿ˜Ž /// tip | Consejo -Si necesitas hacer cualquier tipo de validaciรณn que requiera comunicarte con algรบn **componente externo**, como una base de datos u otra API, deberรญas usar **Dependencias de FastAPI**, las aprenderรกs mรกs adelante. +Si necesitas hacer cualquier tipo de validaciรณn que requiera comunicarte con algรบn componente externo, como una base de datos u otra API, deberรญas usar Dependencias de FastAPI, las aprenderรกs mรกs adelante. -Estos validadores personalizados son para cosas que pueden comprobarse **solo** con los **mismos datos** provistos en el request. +Estos validadores personalizados son para cosas que pueden comprobarse solo con los mismos datos provistos en el request. /// ### Entiende ese cรณdigo { #understand-that-code } -El punto importante es solo usar **`AfterValidator` con una funciรณn dentro de `Annotated`**. Si quieres, sรกltate esta parte. ๐Ÿคธ +El punto importante es solo usar `AfterValidator` con una funciรณn dentro de `Annotated`. Si quieres, sรกltate esta parte. ๐Ÿคธ --- @@ -436,17 +412,17 @@ Pero si te da curiosidad este ejemplo de cรณdigo especรญfico y sigues entretenid #### Un รญtem aleatorio { #a-random-item } -Con `data.items()` obtenemos un objeto iterable con tuplas que contienen la clave y el valor para cada elemento del diccionario. +Con `data.items()` obtenemos un objeto iterable con tuplas que contienen la clave y el valor para cada elemento del diccionario. Convertimos este objeto iterable en una `list` propiamente dicha con `list(data.items())`. -Luego con `random.choice()` podemos obtener un **valor aleatorio** de la lista, asรญ que obtenemos una tupla con `(id, name)`. Serรก algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +Luego con `random.choice()` podemos obtener un valor aleatorio de la lista, asรญ que obtenemos una tupla con `(id, name)`. Serรก algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -Luego **asignamos esos dos valores** de la tupla a las variables `id` y `name`. +Luego asignamos esos dos valores de la tupla a las variables `id` y `name`. Asรญ, si el usuario no proporcionรณ un ID de รญtem, aรบn recibirรก una sugerencia aleatoria. -...hacemos todo esto en una **sola lรญnea simple**. ๐Ÿคฏ ยฟNo te encanta Python? ๐Ÿ +...hacemos todo esto en una sola lรญnea simple. ๐Ÿคฏ ยฟNo te encanta Python? ๐Ÿ {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} diff --git a/docs/es/docs/tutorial/query-params.md b/docs/es/docs/tutorial/query-params.md index 2b58a2b4b6..edbe51a0ea 100644 --- a/docs/es/docs/tutorial/query-params.md +++ b/docs/es/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Cuando declaras otros parรกmetros de funciรณn que no son parte de los parรกmetros de path, son automรกticamente interpretados como parรกmetros de "query". -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} La query es el conjunto de pares clave-valor que van despuรฉs del `?` en una URL, separados por caracteres `&`. @@ -24,7 +24,7 @@ Pero cuando los declaras con tipos de Python (en el ejemplo anterior, como `int` Todo el mismo proceso que se aplica para los parรกmetros de path tambiรฉn se aplica para los parรกmetros de query: * Soporte del editor (obviamente) -* "parsing" de datos +* "parsing" de datos * Validaciรณn de datos * Documentaciรณn automรกtica @@ -127,7 +127,7 @@ Si no quieres agregar un valor especรญfico pero solo hacer que sea opcional, est Pero cuando quieres hacer un parรกmetro de query requerido, simplemente no declares ningรบn valor por defecto: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Aquรญ el parรกmetro de query `needy` es un parรกmetro de query requerido de tipo `str`. diff --git a/docs/es/docs/tutorial/request-files.md b/docs/es/docs/tutorial/request-files.md index cc99deb2e3..717968d741 100644 --- a/docs/es/docs/tutorial/request-files.md +++ b/docs/es/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ Esto es porque los archivos subidos se envรญan como "form data". Importa `File` y `UploadFile` desde `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## Definir Parรกmetros `File` { #define-file-parameters } Crea parรกmetros de archivo de la misma manera que lo harรญas para `Body` o `Form`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | Informaciรณn @@ -54,7 +54,7 @@ Pero hay varios casos en los que podrรญas beneficiarte de usar `UploadFile`. Define un parรกmetro de archivo con un tipo de `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} Usar `UploadFile` tiene varias ventajas sobre `bytes`: @@ -121,7 +121,7 @@ Los datos de los forms normalmente se codifican usando el "media type" `applicat Pero cuando el formulario incluye archivos, se codifica como `multipart/form-data`. Si usas `File`, **FastAPI** sabrรก que tiene que obtener los archivos de la parte correcta del cuerpo. -Si deseas leer mรกs sobre estas codificaciones y campos de formularios, dirรญgete a la MDN web docs para POST. +Si deseas leer mรกs sobre estas codificaciones y campos de formularios, dirรญgete a la MDN web docs para POST. /// @@ -143,7 +143,7 @@ Puedes hacer un archivo opcional utilizando anotaciones de tipos estรกndar y est Tambiรฉn puedes usar `File()` con `UploadFile`, por ejemplo, para establecer metadatos adicionales: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## Subidas de Mรบltiples Archivos { #multiple-file-uploads } @@ -151,9 +151,9 @@ Es posible subir varios archivos al mismo tiempo. Estarรญan asociados al mismo "campo de formulario" enviado usando "form data". -Para usar eso, declara una lista de `bytes` o `UploadFile`: +Para usar eso, declara una `list` de `bytes` o `UploadFile`: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} Recibirรกs, como se declarรณ, una `list` de `bytes` o `UploadFile`s. @@ -169,7 +169,7 @@ Tambiรฉn podrรญas usar `from starlette.responses import HTMLResponse`. Y de la misma manera que antes, puedes usar `File()` para establecer parรกmetros adicionales, incluso para `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## Recapitulaciรณn { #recap } diff --git a/docs/es/docs/tutorial/request-form-models.md b/docs/es/docs/tutorial/request-form-models.md index 1f4668c840..9afadf0b2e 100644 --- a/docs/es/docs/tutorial/request-form-models.md +++ b/docs/es/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ Esto es compatible desde la versiรณn `0.113.0` de FastAPI. ๐Ÿค“ Solo necesitas declarar un **modelo de Pydantic** con los campos que quieres recibir como **campos de formulario**, y luego declarar el parรกmetro como `Form`: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** **extraerรก** los datos de **cada campo** de los **form data** en el request y te darรก el modelo de Pydantic que definiste. @@ -48,7 +48,7 @@ Esto es compatible desde la versiรณn `0.114.0` de FastAPI. ๐Ÿค“ Puedes usar la configuraciรณn del modelo de Pydantic para `forbid` cualquier campo `extra`: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} Si un cliente intenta enviar datos extra, recibirรก un response de **error**. diff --git a/docs/es/docs/tutorial/request-forms-and-files.md b/docs/es/docs/tutorial/request-forms-and-files.md index 363553e862..738a2bc4b4 100644 --- a/docs/es/docs/tutorial/request-forms-and-files.md +++ b/docs/es/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## Importa `File` y `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## Define parรกmetros `File` y `Form` { #define-file-and-form-parameters } Crea parรกmetros de archivo y formulario de la misma manera que lo harรญas para `Body` o `Query`: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} Los archivos y campos de formulario se subirรกn como form data y recibirรกs los archivos y campos de formulario. diff --git a/docs/es/docs/tutorial/request-forms.md b/docs/es/docs/tutorial/request-forms.md index 33061e6a1b..cc29296eed 100644 --- a/docs/es/docs/tutorial/request-forms.md +++ b/docs/es/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart Importar `Form` desde `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## Definir parรกmetros de `Form` { #define-form-parameters } Crea parรกmetros de formulario de la misma manera que lo harรญas para `Body` o `Query`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} Por ejemplo, en una de las formas en las que se puede usar la especificaciรณn OAuth2 (llamada "password flow") se requiere enviar un `username` y `password` como campos de formulario. -La spec requiere que los campos se llamen exactamente `username` y `password`, y que se envรญen como campos de formulario, no JSON. +La especificaciรณn requiere que los campos se llamen exactamente `username` y `password`, y que se envรญen como campos de formulario, no JSON. Con `Form` puedes declarar las mismas configuraciones que con `Body` (y `Query`, `Path`, `Cookie`), incluyendo validaciรณn, ejemplos, un alias (por ejemplo, `user-name` en lugar de `username`), etc. @@ -56,7 +56,7 @@ Los datos de formularios normalmente se codifican usando el "media type" `applic Pero cuando el formulario incluye archivos, se codifica como `multipart/form-data`. Leerรกs sobre la gestiรณn de archivos en el prรณximo capรญtulo. -Si quieres leer mรกs sobre estas codificaciones y campos de formulario, dirรญgete a la MDN web docs para POST. +Si quieres leer mรกs sobre estas codificaciones y campos de formulario, dirรญgete a la MDN web docs para POST. /// diff --git a/docs/es/docs/tutorial/response-model.md b/docs/es/docs/tutorial/response-model.md index 8cfe69e782..c9e931d477 100644 --- a/docs/es/docs/tutorial/response-model.md +++ b/docs/es/docs/tutorial/response-model.md @@ -51,7 +51,7 @@ FastAPI usarรก este `response_model` para hacer toda la documentaciรณn de datos, /// tip | Consejo -Si tienes chequeos estrictos de tipos en tu editor, mypy, etc., puedes declarar el tipo de retorno de la funciรณn como `Any`. +Si tienes chequeo de tipos estricto en tu editor, mypy, etc., puedes declarar el tipo de retorno de la funciรณn como `Any`. De esa manera le dices al editor que intencionalmente estรกs devolviendo cualquier cosa. Pero FastAPI todavรญa harรก la documentaciรณn de datos, validaciรณn, filtrado, etc. con `response_model`. @@ -183,7 +183,7 @@ Podrรญa haber casos en los que devuelvas algo que no es un campo vรกlido de Pyda El caso mรกs comรบn serรญa [devolver un Response directamente como se explica mรกs adelante en la documentaciรณn avanzada](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} Este caso simple es manejado automรกticamente por FastAPI porque la anotaciรณn del tipo de retorno es la clase (o una subclase de) `Response`. @@ -193,7 +193,7 @@ Y las herramientas tambiรฉn estarรกn felices porque tanto `RedirectResponse` com Tambiรฉn puedes usar una subclase de `Response` en la anotaciรณn del tipo: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} Esto tambiรฉn funcionarรก porque `RedirectResponse` es una subclase de `Response`, y FastAPI manejarรก automรกticamente este caso simple. @@ -201,7 +201,7 @@ Esto tambiรฉn funcionarรก porque `RedirectResponse` es una subclase de `Response Pero cuando devuelves algรบn otro objeto arbitrario que no es un tipo vรกlido de Pydantic (por ejemplo, un objeto de base de datos) y lo anotas asรญ en la funciรณn, FastAPI intentarรก crear un modelo de response de Pydantic a partir de esa anotaciรณn de tipo, y fallarรก. -Lo mismo sucederรญa si tuvieras algo como un union entre diferentes tipos donde uno o mรกs de ellos no son tipos vรกlidos de Pydantic, por ejemplo esto fallarรญa ๐Ÿ’ฅ: +Lo mismo sucederรญa si tuvieras algo como una uniรณn entre diferentes tipos donde uno o mรกs de ellos no son tipos vรกlidos de Pydantic, por ejemplo esto fallarรญa ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/es/docs/tutorial/response-status-code.md b/docs/es/docs/tutorial/response-status-code.md index dce69f9bce..35235eb883 100644 --- a/docs/es/docs/tutorial/response-status-code.md +++ b/docs/es/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ De la misma manera que puedes especificar un modelo de response, tambiรฉn puedes * `@app.delete()` * etc. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | Nota @@ -66,7 +66,7 @@ En breve: /// tip | Consejo -Para saber mรกs sobre cada cรณdigo de estado y quรฉ cรณdigo es para quรฉ, revisa la documentaciรณn de MDN sobre cรณdigos de estado HTTP. +Para saber mรกs sobre cada cรณdigo de estado y quรฉ cรณdigo es para quรฉ, revisa la documentaciรณn de MDN sobre cรณdigos de estado HTTP. /// @@ -74,7 +74,7 @@ Para saber mรกs sobre cada cรณdigo de estado y quรฉ cรณdigo es para quรฉ, revisa Veamos de nuevo el ejemplo anterior: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` es el cรณdigo de estado para "Created". @@ -82,7 +82,7 @@ Pero no tienes que memorizar lo que significa cada uno de estos cรณdigos. Puedes usar las variables de conveniencia de `fastapi.status`. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} Son solo una conveniencia, mantienen el mismo nรบmero, pero de esa manera puedes usar el autocompletado del editor para encontrarlos: diff --git a/docs/es/docs/tutorial/schema-extra-example.md b/docs/es/docs/tutorial/schema-extra-example.md index 396a2a6bf5..9af8261380 100644 --- a/docs/es/docs/tutorial/schema-extra-example.md +++ b/docs/es/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Por supuesto, tambiรฉn puedes pasar mรบltiples `examples`: Cuando haces esto, los ejemplos serรกn parte del **JSON Schema** interno para esos datos del body. -Sin embargo, al momento de escribir esto, Swagger UI, la herramienta encargada de mostrar la interfaz de documentaciรณn, no soporta mostrar mรบltiples ejemplos para los datos en **JSON Schema**. Pero lee mรกs abajo para una soluciรณn alternativa. +Sin embargo, al momento de escribir esto, Swagger UI, la herramienta encargada de mostrar la interfaz de documentaciรณn, no soporta mostrar mรบltiples ejemplos para los datos en **JSON Schema**. Pero lee mรกs abajo para una soluciรณn alternativa. ### `examples` especรญficos de OpenAPI { #openapi-specific-examples } diff --git a/docs/es/docs/tutorial/security/first-steps.md b/docs/es/docs/tutorial/security/first-steps.md index 604adedad7..909f14765c 100644 --- a/docs/es/docs/tutorial/security/first-steps.md +++ b/docs/es/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ Primero solo usemos el cรณdigo y veamos cรณmo funciona, y luego volveremos para Copia el ejemplo en un archivo `main.py`: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## Ejecรบtalo { #run-it } @@ -132,7 +132,7 @@ En ese caso, **FastAPI** tambiรฉn te proporciona las herramientas para construir Cuando creamos una instance de la clase `OAuth2PasswordBearer` pasamos el parรกmetro `tokenUrl`. Este parรกmetro contiene la URL que el cliente (el frontend corriendo en el navegador del usuario) usarรก para enviar el `username` y `password` a fin de obtener un token. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | Consejo @@ -170,7 +170,7 @@ Asรญ que, puede usarse con `Depends`. Ahora puedes pasar ese `oauth2_scheme` en una dependencia con `Depends`. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Esta dependencia proporcionarรก un `str` que se asigna al parรกmetro `token` de la *path operation function*. diff --git a/docs/es/docs/tutorial/security/get-current-user.md b/docs/es/docs/tutorial/security/get-current-user.md index ced002f597..67b6c58359 100644 --- a/docs/es/docs/tutorial/security/get-current-user.md +++ b/docs/es/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ En el capรญtulo anterior, el sistema de seguridad (que se basa en el sistema de inyecciรณn de dependencias) le estaba dando a la *path operation function* un `token` como un `str`: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Pero eso aรบn no es tan รบtil. Vamos a hacer que nos dรฉ el usuario actual. diff --git a/docs/es/docs/tutorial/security/oauth2-jwt.md b/docs/es/docs/tutorial/security/oauth2-jwt.md index f7004ffb2d..e481fb6462 100644 --- a/docs/es/docs/tutorial/security/oauth2-jwt.md +++ b/docs/es/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ Y otra utilidad para verificar si una contraseรฑa recibida coincide con el hash Y otra mรกs para autenticar y devolver un usuario. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Cuando `authenticate_user` se llama con un nombre de usuario que no existe en la base de datos, aun asรญ ejecutamos `verify_password` contra un hash ficticio. + +Esto asegura que el endpoint tarda aproximadamente la misma cantidad de tiempo en responder tanto si el nombre de usuario es vรกlido como si no, previniendo los **timing attacks** que podrรญan usarse para enumerar nombres de usuario existentes. /// note | Nota @@ -152,7 +156,7 @@ Define un Modelo de Pydantic que se usarรก en el endpoint de token para el respo Crea una funciรณn de utilidad para generar un nuevo token de acceso. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## Actualizar las dependencias { #update-the-dependencies } @@ -162,7 +166,7 @@ Decodifica el token recibido, verifรญcalo y devuelve el usuario actual. Si el token es invรกlido, devuelve un error HTTP de inmediato. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## Actualizar la *path operation* `/token` { #update-the-token-path-operation } @@ -170,7 +174,7 @@ Crea un `timedelta` con el tiempo de expiraciรณn del token. Crea un verdadero token de acceso JWT y devuรฉlvelo. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### Detalles tรฉcnicos sobre el "sujeto" `sub` de JWT { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/es/docs/tutorial/sql-databases.md b/docs/es/docs/tutorial/sql-databases.md index 6273c7059a..b57ebdbbe5 100644 --- a/docs/es/docs/tutorial/sql-databases.md +++ b/docs/es/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Aquรญ veremos un ejemplo usando "ORMs"), FastAPI no te obliga a usar nada. ๐Ÿ˜Ž +Puedes usar cualquier otro paquete de bases de datos SQL o NoSQL que quieras (en algunos casos llamadas "ORMs"), FastAPI no te obliga a usar nada. ๐Ÿ˜Ž /// @@ -354,4 +354,4 @@ Si vas a la interfaz de `/docs` de la API, verรกs que ahora estรก actualizada, y Puedes usar **SQLModel** para interactuar con una base de datos SQL y simplificar el cรณdigo con *modelos de datos* y *modelos de tablas*. -Puedes aprender mucho mรกs en la documentaciรณn de **SQLModel**, hay un mini tutorial sobre el uso de SQLModel con **FastAPI**. ๐Ÿš€ +Puedes aprender mucho mรกs en la documentaciรณn de **SQLModel**, hay un mini tutorial mรกs largo sobre el uso de SQLModel con **FastAPI**. ๐Ÿš€ diff --git a/docs/es/docs/tutorial/static-files.md b/docs/es/docs/tutorial/static-files.md index f1badd2af6..84d2e94a97 100644 --- a/docs/es/docs/tutorial/static-files.md +++ b/docs/es/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ Puedes servir archivos estรกticos automรกticamente desde un directorio utilizand * Importa `StaticFiles`. * "Monta" una instance de `StaticFiles()` en un path especรญfico. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | Detalles Tรฉcnicos diff --git a/docs/es/docs/tutorial/testing.md b/docs/es/docs/tutorial/testing.md index 555da55bf6..c477129035 100644 --- a/docs/es/docs/tutorial/testing.md +++ b/docs/es/docs/tutorial/testing.md @@ -30,7 +30,7 @@ Usa el objeto `TestClient` de la misma manera que con `httpx`. Escribe declaraciones `assert` simples con las expresiones estรกndar de Python que necesites revisar (otra vez, estรกndar de `pytest`). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | Consejo @@ -75,7 +75,7 @@ Digamos que tienes una estructura de archivos como se describe en [Aplicaciones En el archivo `main.py` tienes tu aplicaciรณn de **FastAPI**: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### Archivo de prueba { #testing-file } @@ -91,7 +91,7 @@ Entonces podrรญas tener un archivo `test_main.py` con tus pruebas. Podrรญa estar Debido a que este archivo estรก en el mismo paquete, puedes usar importaciones relativas para importar el objeto `app` desde el mรณdulo `main` (`main.py`): -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...y tener el cรณdigo para las pruebas tal como antes. diff --git a/docs/es/docs/virtual-environments.md b/docs/es/docs/virtual-environments.md index 8c90c28f0b..f8839ac6c3 100644 --- a/docs/es/docs/virtual-environments.md +++ b/docs/es/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Crea un Entorno Virtual { #create-a-virtual-environment } -Cuando empiezas a trabajar en un proyecto de Python **por primera vez**, crea un entorno virtual **dentro de tu proyecto**. +Cuando empiezas a trabajar en un proyecto de Python **por primera vez**, crea un entorno virtual **dentro de tu proyecto**. /// tip | Consejo @@ -170,9 +170,9 @@ Esto asegura que si usas un programa de **terminal ( Date: Fri, 13 Feb 2026 13:42:06 +0000 Subject: [PATCH 230/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index af7e7f27d1..deee633c2f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for uk (update-all). PR [#14914](https://github.com/fastapi/fastapi/pull/14914) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for tr (update-all). PR [#14913](https://github.com/fastapi/fastapi/pull/14913) by [@YuriiMotov](https://github.com/YuriiMotov). From 0d1f4d935b43628c966903d1e213d1bffa860953 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 14:48:53 +0100 Subject: [PATCH 231/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-all)=20(#14912)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/pt/docs/_llm-test.md | 8 +- docs/pt/docs/advanced/additional-responses.md | 8 +- .../pt/docs/advanced/advanced-dependencies.md | 8 +- .../pt/docs/advanced/advanced-python-types.md | 61 +++++ docs/pt/docs/advanced/async-tests.md | 8 +- docs/pt/docs/advanced/behind-a-proxy.md | 18 +- docs/pt/docs/advanced/custom-response.md | 32 +-- docs/pt/docs/advanced/dataclasses.md | 2 +- docs/pt/docs/advanced/events.md | 18 +- docs/pt/docs/advanced/generate-clients.md | 10 +- docs/pt/docs/advanced/index.md | 2 +- docs/pt/docs/advanced/middleware.md | 8 +- docs/pt/docs/advanced/openapi-callbacks.md | 4 +- docs/pt/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 4 +- docs/pt/docs/advanced/response-cookies.md | 4 +- docs/pt/docs/advanced/response-directly.md | 4 +- docs/pt/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 2 +- docs/pt/docs/advanced/settings.md | 20 +- docs/pt/docs/advanced/sub-applications.md | 6 +- docs/pt/docs/advanced/templates.md | 2 +- docs/pt/docs/advanced/testing-dependencies.md | 3 +- docs/pt/docs/advanced/testing-events.md | 4 +- docs/pt/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 4 +- docs/pt/docs/advanced/websockets.md | 8 +- docs/pt/docs/advanced/wsgi.md | 2 +- docs/pt/docs/alternatives.md | 10 +- docs/pt/docs/benchmarks.md | 2 +- docs/pt/docs/deployment/cloud.md | 2 +- docs/pt/docs/deployment/docker.md | 12 +- docs/pt/docs/deployment/https.md | 8 +- docs/pt/docs/deployment/index.md | 2 +- docs/pt/docs/deployment/manually.md | 2 +- docs/pt/docs/deployment/versions.md | 4 +- docs/pt/docs/fastapi-cli.md | 2 +- docs/pt/docs/features.md | 12 +- docs/pt/docs/history-design-future.md | 4 +- .../authentication-error-status-code.md | 2 +- docs/pt/docs/how-to/conditional-openapi.md | 4 +- docs/pt/docs/how-to/configure-swagger-ui.md | 6 +- docs/pt/docs/how-to/custom-docs-ui-assets.md | 18 +- docs/pt/docs/how-to/extending-openapi.md | 10 +- docs/pt/docs/how-to/general.md | 2 +- docs/pt/docs/how-to/graphql.md | 2 +- docs/pt/docs/how-to/index.md | 4 +- docs/pt/docs/index.md | 10 +- docs/pt/docs/python-types.md | 222 +++++------------- docs/pt/docs/translation-banner.md | 11 + docs/pt/docs/tutorial/background-tasks.md | 6 +- docs/pt/docs/tutorial/bigger-applications.md | 48 ++-- docs/pt/docs/tutorial/body-multiple-params.md | 6 - docs/pt/docs/tutorial/body-nested-models.md | 4 +- docs/pt/docs/tutorial/body.md | 8 +- docs/pt/docs/tutorial/cookie-param-models.md | 10 +- docs/pt/docs/tutorial/cors.md | 3 +- docs/pt/docs/tutorial/debugging.md | 4 +- .../dependencies/classes-as-dependencies.md | 24 +- ...pendencies-in-path-operation-decorators.md | 10 +- .../dependencies/dependencies-with-yield.md | 24 +- .../dependencies/global-dependencies.md | 2 +- docs/pt/docs/tutorial/dependencies/index.md | 12 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/pt/docs/tutorial/extra-models.md | 8 +- docs/pt/docs/tutorial/first-steps.md | 16 +- docs/pt/docs/tutorial/handling-errors.md | 20 +- docs/pt/docs/tutorial/header-params.md | 2 +- docs/pt/docs/tutorial/metadata.md | 16 +- docs/pt/docs/tutorial/middleware.md | 6 +- .../tutorial/path-operation-configuration.md | 8 +- .../path-params-numeric-validations.md | 16 +- docs/pt/docs/tutorial/path-params.md | 32 +-- docs/pt/docs/tutorial/query-param-models.md | 11 +- .../tutorial/query-params-str-validations.md | 88 +++---- docs/pt/docs/tutorial/query-params.md | 6 +- docs/pt/docs/tutorial/request-files.md | 16 +- docs/pt/docs/tutorial/request-form-models.md | 6 +- .../docs/tutorial/request-forms-and-files.md | 8 +- docs/pt/docs/tutorial/request-forms.md | 6 +- docs/pt/docs/tutorial/response-model.md | 8 +- docs/pt/docs/tutorial/response-status-code.md | 8 +- docs/pt/docs/tutorial/schema-extra-example.md | 2 +- docs/pt/docs/tutorial/security/first-steps.md | 8 +- .../tutorial/security/get-current-user.md | 2 +- docs/pt/docs/tutorial/security/index.md | 3 +- docs/pt/docs/tutorial/security/oauth2-jwt.md | 12 +- docs/pt/docs/tutorial/static-files.md | 2 +- docs/pt/docs/tutorial/testing.md | 6 +- docs/pt/docs/virtual-environments.md | 12 +- 92 files changed, 529 insertions(+), 599 deletions(-) create mode 100644 docs/pt/docs/advanced/advanced-python-types.md create mode 100644 docs/pt/docs/translation-banner.md diff --git a/docs/pt/docs/_llm-test.md b/docs/pt/docs/_llm-test.md index 3a2801fdda..9f03c4b886 100644 --- a/docs/pt/docs/_llm-test.md +++ b/docs/pt/docs/_llm-test.md @@ -104,8 +104,8 @@ $ cd code ...e um exemplo de cรณdigo Python... ```Python -wont_work() # This won't work ๐Ÿ˜ฑ -works(foo="bar") # This works ๐ŸŽ‰ +wont_work() # Isto nรฃo vai funcionar ๐Ÿ˜ฑ +works(foo="bar") # Isto funciona ๐ŸŽ‰ ``` ...e รฉ isso. @@ -204,8 +204,8 @@ Aqui estรฃo algumas coisas envolvidas em elementos HTML "abbr" (algumas sรฃo inv ### O abbr fornece uma frase completa e uma explicaรงรฃo { #the-abbr-gives-a-full-phrase-and-an-explanation } -* MDN -* I/O. +* MDN +* I/O. //// diff --git a/docs/pt/docs/advanced/additional-responses.md b/docs/pt/docs/advanced/additional-responses.md index 688bc16967..2e277ac104 100644 --- a/docs/pt/docs/advanced/additional-responses.md +++ b/docs/pt/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ O **FastAPI** pegarรก este modelo, gerarรก o esquema JSON dele e incluirรก no lo Por exemplo, para declarar um outro retorno com o status code `404` e um modelo do Pydantic chamado `Message`, vocรช pode escrever: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Nota @@ -203,7 +203,7 @@ Por exemplo, vocรช pode declarar um retorno com o cรณdigo de status `404` que ut E um retorno com o cรณdigo de status `200` que utiliza o seu `response_model`, porรฉm inclui um `example` customizado: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Isso serรก combinado e incluรญdo em seu OpenAPI, e disponibilizado na documentaรงรฃo da sua API: @@ -243,5 +243,5 @@ Por exemplo: Para verificar exatamente o que vocรช pode incluir nos retornos, vocรช pode conferir estas seรงรตes na especificaรงรฃo do OpenAPI: -* Objeto de Retorno OpenAPI, inclui o `Response Object`. -* Objeto de Retorno OpenAPI, vocรช pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parรขmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que vocรช declara diferentes media types e esquemas JSON), e `links`. +* Objeto de Retornos do OpenAPI, inclui o `Response Object`. +* Objeto de Retorno do OpenAPI, vocรช pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parรขmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que vocรช declara diferentes media types e esquemas JSON), e `links`. diff --git a/docs/pt/docs/advanced/advanced-dependencies.md b/docs/pt/docs/advanced/advanced-dependencies.md index 959a7f3c2b..419a092c80 100644 --- a/docs/pt/docs/advanced/advanced-dependencies.md +++ b/docs/pt/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Nรฃo propriamente a classe (que jรก รฉ um chamรกvel), mas a instรขncia desta cla Para fazer isso, nรณs declaramos o mรฉtodo `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} Neste caso, o `__call__` รฉ o que o **FastAPI** utilizarรก para verificar parรขmetros adicionais e sub dependรชncias, e isso รฉ o que serรก chamado para passar o valor ao parรขmetro na sua *funรงรฃo de operaรงรฃo de rota* posteriormente. @@ -26,7 +26,7 @@ Neste caso, o `__call__` รฉ o que o **FastAPI** utilizarรก para verificar parรขm E agora, nรณs podemos utilizar o `__init__` para declarar os parรขmetros da instรขncia que podemos utilizar para "parametrizar" a dependรชncia: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} Neste caso, o **FastAPI** nunca tocarรก ou se importarรก com o `__init__`, nรณs vamos utilizar diretamente em nosso cรณdigo. @@ -34,7 +34,7 @@ Neste caso, o **FastAPI** nunca tocarรก ou se importarรก com o `__init__`, nรณs Nรณs poderรญamos criar uma instรขncia desta classe com: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} E deste modo nรณs podemos "parametrizar" a nossa dependรชncia, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") ...e passar o que quer que isso retorne como valor da dependรชncia em nossa *funรงรฃo de operaรงรฃo de rota* como o parรขmetro `fixed_content_included`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | Dica diff --git a/docs/pt/docs/advanced/advanced-python-types.md b/docs/pt/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..f92a20bd46 --- /dev/null +++ b/docs/pt/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Tipos Avanรงados de Python { #advanced-python-types } + +Aqui estรฃo algumas ideias adicionais que podem ser รบteis ao trabalhar com tipos em Python. + +## Usando `Union` ou `Optional` { #using-union-or-optional } + +Se, por algum motivo, seu cรณdigo nรฃo puder usar `|`, por exemplo, se nรฃo for em uma anotaรงรฃo de tipo, mas em algo como `response_model=`, em vez de usar a barra vertical (`|`) vocรช pode usar `Union` do `typing`. + +Por exemplo, vocรช poderia declarar que algo pode ser `str` ou `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +O `typing` tambรฉm tem um atalho para declarar que algo pode ser `None`, com `Optional`. + +Aqui vai uma dica do meu ponto de vista bem subjetivo: + +* ๐Ÿšจ Evite usar `Optional[SomeType]` +* Em vez disso โœจ use **`Union[SomeType, None]`** โœจ. + +Ambos sรฃo equivalentes e, por baixo, sรฃo a mesma coisa, mas eu recomendaria `Union` em vez de `Optional` porque a palavra "opcional" sugere que o valor รฉ opcional; na verdade, significa "pode ser `None`", mesmo quando nรฃo รฉ opcional e continua sendo obrigatรณrio. + +Acho que `Union[SomeType, None]` รฉ mais explรญcito quanto ao significado. + +ร‰ apenas uma questรฃo de palavras e nomes. Mas essas palavras podem influenciar como vocรช e sua equipe pensam sobre o cรณdigo. + +Como exemplo, veja esta funรงรฃo: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +O parรขmetro `name` รฉ definido como `Optional[str]`, mas nรฃo รฉ opcional; nรฃo รฉ possรญvel chamar a funรงรฃo sem o parรขmetro: + +```Python +say_hi() # Ah, nรฃo, isso gera um erro! ๐Ÿ˜ฑ +``` + +O parรขmetro `name` continua obrigatรณrio (nรฃo รฉ opcional) porque nรฃo tem valor padrรฃo. Ainda assim, `name` aceita `None` como valor: + +```Python +say_hi(name=None) # Isso funciona, None รฉ vรกlido ๐ŸŽ‰ +``` + +A boa notรญcia รฉ que, na maioria dos casos, vocรช poderรก simplesmente usar `|` para definir uniรตes de tipos: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Entรฃo, normalmente vocรช nรฃo precisa se preocupar com nomes como `Optional` e `Union`. ๐Ÿ˜Ž diff --git a/docs/pt/docs/advanced/async-tests.md b/docs/pt/docs/advanced/async-tests.md index 953ebedd9c..2fe678adb9 100644 --- a/docs/pt/docs/advanced/async-tests.md +++ b/docs/pt/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante O arquivo `main.py` teria: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} O arquivo `test_main.py` teria os testes para para o arquivo `main.py`, ele poderia ficar assim: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## Executรก-lo { #run-it } @@ -56,7 +56,7 @@ $ pytest O marcador `@pytest.mark.anyio` informa ao pytest que esta funรงรฃo de teste deve ser invocada de maneira assรญncrona: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | Dica @@ -66,7 +66,7 @@ Note que a funรงรฃo de teste รฉ `async def` agora, no lugar de apenas `def` como Entรฃo podemos criar um `AsyncClient` com a aplicaรงรฃo, e enviar requisiรงรตes assรญncronas para ela utilizando `await`. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} Isso รฉ equivalente a: diff --git a/docs/pt/docs/advanced/behind-a-proxy.md b/docs/pt/docs/advanced/behind-a-proxy.md index bf0d124289..1581415156 100644 --- a/docs/pt/docs/advanced/behind-a-proxy.md +++ b/docs/pt/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" Por exemplo, suponha que vocรช defina uma *operaรงรฃo de rota* `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} Se o cliente tentar ir para `/items`, por padrรฃo, ele seria redirecionado para `/items/`. @@ -91,9 +91,9 @@ O **proxy** intercepta a requisiรงรฃo original do cliente e adiciona os headers Esses headers preservam informaรงรตes sobre a requisiรงรฃo original que, de outra forma, seriam perdidas: -* X-Forwarded-For: o endereรงo IP original do cliente -* X-Forwarded-Proto: o protocolo original (`https`) -* X-Forwarded-Host: o host original (`mysuperapp.com`) +* **X-Forwarded-For**: o endereรงo IP original do cliente +* **X-Forwarded-Proto**: o protocolo original (`https`) +* **X-Forwarded-Host**: o host original (`mysuperapp.com`) Quando a **CLI do FastAPI** รฉ configurada com `--forwarded-allow-ips`, ela confia nesses headers e os utiliza, por exemplo, para gerar as URLs corretas em redirecionamentos. @@ -115,7 +115,7 @@ Nesse caso, o path original `/app` seria servido em `/api/v1/app`. Embora todo o seu cรณdigo esteja escrito assumindo que existe apenas `/app`. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} E o proxy estaria **"removendo"** o **prefixo de path** dinamicamente antes de transmitir a solicitaรงรฃo para o servidor da aplicaรงรฃo (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicaรงรฃo convencida de que estรก sendo servida em `/app`, para que vocรช nรฃo precise atualizar todo o seu cรณdigo para incluir o prefixo `/api/v1`. @@ -193,7 +193,7 @@ Vocรช pode obter o `root_path` atual usado pela sua aplicaรงรฃo para cada solici Aqui estamos incluindo-o na mensagem apenas para fins de demonstraรงรฃo. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Entรฃo, se vocรช iniciar o Uvicorn com: @@ -220,7 +220,7 @@ A resposta seria algo como: Alternativamente, se vocรช nรฃo tiver uma maneira de fornecer uma opรงรฃo de linha de comando como `--root-path` ou equivalente, vocรช pode definir o parรขmetro `root_path` ao criar sua aplicaรงรฃo FastAPI: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} Passar o `root_path` para `FastAPI` seria o equivalente a passar a opรงรฃo de linha de comando `--root-path` para Uvicorn ou Hypercorn. @@ -400,7 +400,7 @@ Se vocรช passar uma lista personalizada de `servers` e houver um `root_path` (po Por exemplo: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} Gerarรก um OpenAPI schema como: @@ -455,7 +455,7 @@ Se vocรช nรฃo especificar o parรขmetro `servers` e `root_path` for igual a `/`, Se vocรช nรฃo quiser que o **FastAPI** inclua um servidor automรกtico usando o `root_path`, vocรช pode usar o parรขmetro `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} e entรฃo ele nรฃo serรก incluรญdo no OpenAPI schema. diff --git a/docs/pt/docs/advanced/custom-response.md b/docs/pt/docs/advanced/custom-response.md index 5f26390c28..a409f1dc85 100644 --- a/docs/pt/docs/advanced/custom-response.md +++ b/docs/pt/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ Isso ocorre por que, por padrรฃo, o FastAPI irรก verificar cada item dentro do d Mas se vocรช tem certeza que o conteรบdo que vocรช estรก retornando รฉ **serializรกvel com JSON**, vocรช pode passรก-lo diretamente para a classe de resposta e evitar o trabalho extra que o FastAPI teria ao passar o conteรบdo pelo `jsonable_encoder` antes de passar para a classe de resposta. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | Informaรงรฃo @@ -55,7 +55,7 @@ Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLRes * Importe `HTMLResponse` * Passe `HTMLResponse` como o parรขmetro de `response_class` do seu *decorador de operaรงรฃo de rota*. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | Informaรงรฃo @@ -73,7 +73,7 @@ Como visto em [Retornando uma Resposta Diretamente](response-directly.md){.inter O mesmo exemplo de antes, retornando uma `HTMLResponse`, poderia parecer com: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | Atenรงรฃo @@ -97,7 +97,7 @@ A `response_class` serรก usada apenas para documentar o OpenAPI da *operaรงรฃo d Por exemplo, poderia ser algo como: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} Neste exemplo, a funรงรฃo `generate_html_response()` jรก cria e retorna uma `Response` em vez de retornar o HTML em uma `str`. @@ -136,7 +136,7 @@ Ela aceita os seguintes parรขmetros: O FastAPI (Starlette, na verdade) irรก incluir o cabeรงalho Content-Length automaticamente. Ele tambรฉm irรก incluir o cabeรงalho Content-Type, baseado no `media_type` e acrescentando uma codificaรงรฃo para tipos textuais. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ Usa algum texto ou sequรชncia de bytes e retorna uma resposta HTML. Como vocรช l Usa algum texto ou sequรชncia de bytes para retornar uma resposta de texto nรฃo formatado. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ Essa resposta requer a instalaรงรฃo do pacote `ujson`, com o comando `pip instal /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | Dica @@ -194,13 +194,13 @@ Retorna um redirecionamento HTTP. Utiliza o cรณdigo de status 307 (Redirecioname Vocรช pode retornar uma `RedirectResponse` diretamente: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- Ou vocรช pode utilizรก-la no parรขmetro `response_class`: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} Se vocรช fizer isso, entรฃo vocรช pode retornar a URL diretamente da sua *funรงรฃo de operaรงรฃo de rota* @@ -210,13 +210,13 @@ Neste caso, o `status_code` utilizada serรก o padrรฃo de `RedirectResponse`, que Vocรช tambรฉm pode utilizar o parรขmetro `status_code` combinado com o parรขmetro `response_class`: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } Recebe um gerador assรญncrono ou um gerador/iterador comum e retorna o corpo da resposta de forma contรญnua (stream). -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### Utilizando `StreamingResponse` com objetos semelhantes a arquivos { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ Dessa forma, vocรช nรฃo precisa ler todo o arquivo na memรณria primeiro, e vocรช Isso inclui muitas bibliotecas que interagem com armazenamento em nuvem, processamento de vรญdeos, entre outras. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. Essa รฉ a funรงรฃo geradora. ร‰ definida como "funรงรฃo geradora" porque contรฉm declaraรงรตes `yield` nela. 2. Ao utilizar o bloco `with`, nรณs garantimos que o objeto semelhante a um arquivo รฉ fechado apรณs a funรงรฃo geradora ser finalizada. Isto รฉ, apรณs a resposta terminar de ser enviada. @@ -255,11 +255,11 @@ Recebe um conjunto de argumentos do construtor diferente dos outros tipos de res Respostas de Arquivos incluem o tamanho do arquivo, data da รบltima modificaรงรฃo e ETags apropriados, nos cabeรงalhos `Content-Length`, `Last-Modified` e `ETag`, respectivamente. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} Vocรช tambรฉm pode usar o parรขmetro `response_class`: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} Nesse caso, vocรช pode retornar o caminho do arquivo diretamente da sua *funรงรฃo de operaรงรฃo de rota*. @@ -273,7 +273,7 @@ Vamos supor tambรฉm que vocรช queira retornar um JSON indentado e formatado, ent Vocรช poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita รฉ sobrecarregar o mรฉtodo render da classe Response, `Response.render(content)`, que retorna o conteรบdo em bytes: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} Agora em vez de retornar: @@ -299,7 +299,7 @@ O padrรฃo que define isso รฉ o `default_response_class`. No exemplo abaixo, o **FastAPI** irรก utilizar `ORJSONResponse` por padrรฃo, em todas as *operaรงรตes de rota*, em vez de `JSONResponse`. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | Dica diff --git a/docs/pt/docs/advanced/dataclasses.md b/docs/pt/docs/advanced/dataclasses.md index 6dc9feb299..c2af6fac6d 100644 --- a/docs/pt/docs/advanced/dataclasses.md +++ b/docs/pt/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ Nesse caso, vocรช pode simplesmente trocar as `dataclasses` padrรฃo por `pydanti 6. Aqui estamos retornando um dicionรกrio que contรฉm `items`, que รฉ uma lista de dataclasses. - O FastAPI ainda รฉ capaz de serializar os dados para JSON. + O FastAPI ainda รฉ capaz de serializar os dados para JSON. 7. Aqui o `response_model` estรก usando uma anotaรงรฃo de tipo de uma lista de dataclasses `Author`. diff --git a/docs/pt/docs/advanced/events.md b/docs/pt/docs/advanced/events.md index 8cdc358289..551053508d 100644 --- a/docs/pt/docs/advanced/events.md +++ b/docs/pt/docs/advanced/events.md @@ -6,13 +6,13 @@ Da mesma forma, vocรช pode definir a lรณgica (cรณdigo) que deve ser executada qu Como esse cรณdigo รฉ executado antes de a aplicaรงรฃo **comeรงar** a receber requisiรงรตes e logo depois que ela **termina** de lidar com as requisiรงรตes, ele cobre todo o **lifespan** da aplicaรงรฃo (a palavra "lifespan" serรก importante em um segundo ๐Ÿ˜‰). -Isso pode ser muito รบtil para configurar **recursos** que vocรช precisa usar por toda a aplicaรงรฃo, e que sรฃo **compartilhados** entre as requisiรงรตes e/ou que vocรช precisa **limpar** depois. Por exemplo, um pool de conexรตes com o banco de dados ou o carregamento de um modelo de machine learning compartilhado. +Isso pode ser muito รบtil para configurar **recursos** que vocรช precisa usar por toda a aplicaรงรฃo, e que sรฃo **compartilhados** entre as requisiรงรตes e/ou que vocรช precisa **limpar** depois. Por exemplo, um pool de conexรตes com o banco de dados ou o carregamento de um modelo de Aprendizado de Mรกquina compartilhado. ## Caso de uso { #use-case } Vamos comeรงar com um exemplo de **caso de uso** e entรฃo ver como resolvรช-lo com isso. -Vamos imaginar que vocรช tem alguns **modelos de machine learning** que deseja usar para lidar com as requisiรงรตes. ๐Ÿค– +Vamos imaginar que vocรช tem alguns **modelos de Aprendizado de Mรกquina** que deseja usar para lidar com as requisiรงรตes. ๐Ÿค– Os mesmos modelos sรฃo compartilhados entre as requisiรงรตes, entรฃo nรฃo รฉ um modelo por requisiรงรฃo, ou um por usuรกrio, ou algo parecido. @@ -30,9 +30,9 @@ Vamos comeรงar com um exemplo e depois ver em detalhes. Nรณs criamos uma funรงรฃo assรญncrona `lifespan()` com `yield` assim: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Aqui estamos simulando a operaรงรฃo de *inicializaรงรฃo* custosa de carregar o modelo, colocando a (falsa) funรงรฃo do modelo no dicionรกrio com modelos de machine learning antes do `yield`. Esse cรณdigo serรก executado **antes** de a aplicaรงรฃo **comeรงar a receber requisiรงรตes**, durante a *inicializaรงรฃo*. +Aqui estamos simulando a operaรงรฃo de *inicializaรงรฃo* custosa de carregar o modelo, colocando a (falsa) funรงรฃo do modelo no dicionรกrio com modelos de Aprendizado de Mรกquina antes do `yield`. Esse cรณdigo serรก executado **antes** de a aplicaรงรฃo **comeรงar a receber requisiรงรตes**, durante a *inicializaรงรฃo*. E entรฃo, logo apรณs o `yield`, descarregamos o modelo. Esse cรณdigo serรก executado **depois** de a aplicaรงรฃo **terminar de lidar com as requisiรงรตes**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memรณria ou uma GPU. @@ -48,7 +48,7 @@ Talvez vocรช precise iniciar uma nova versรฃo, ou apenas cansou de executรก-la. A primeira coisa a notar รฉ que estamos definindo uma funรงรฃo assรญncrona com `yield`. Isso รฉ muito semelhante a Dependรชncias com `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} A primeira parte da funรงรฃo, antes do `yield`, serรก executada **antes** de a aplicaรงรฃo iniciar. @@ -60,7 +60,7 @@ Se vocรช verificar, a funรงรฃo estรก decorada com um `@asynccontextmanager`. Isso converte a funรงรฃo em algo chamado "**gerenciador de contexto assรญncrono**". -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} Um **gerenciador de contexto** em Python รฉ algo que vocรช pode usar em uma declaraรงรฃo `with`, por exemplo, `open()` pode ser usado como um gerenciador de contexto: @@ -82,7 +82,7 @@ No nosso exemplo de cรณdigo acima, nรฃo o usamos diretamente, mas passamos para O parรขmetro `lifespan` da aplicaรงรฃo `FastAPI` aceita um **gerenciador de contexto assรญncrono**, entรฃo podemos passar para ele nosso novo gerenciador de contexto assรญncrono `lifespan`. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Eventos alternativos (descontinuados) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ Essas funรงรตes podem ser declaradas com `async def` ou `def` normal. Para adicionar uma funรงรฃo que deve rodar antes de a aplicaรงรฃo iniciar, declare-a com o evento `"startup"`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} Nesse caso, a funรงรฃo de manipulador do evento `startup` inicializarรก os itens do "banco de dados" (apenas um `dict`) com alguns valores. @@ -116,7 +116,7 @@ E sua aplicaรงรฃo nรฃo comeรงarรก a receber requisiรงรตes atรฉ que todos os mani Para adicionar uma funรงรฃo que deve ser executada quando a aplicaรงรฃo estiver encerrando, declare-a com o evento `"shutdown"`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Aqui, a funรงรฃo de manipulador do evento `shutdown` escreverรก uma linha de texto `"Application shutdown"` no arquivo `log.txt`. diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index 5134bc7cb5..c6c7785a01 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -40,7 +40,7 @@ Algumas dessas soluรงรตes tambรฉm podem ser open source ou oferecer planos gratu Vamos comeรงar com uma aplicaรงรฃo FastAPI simples: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} Note que as *operaรงรตes de rota* definem os modelos que usam para o corpo da requisiรงรฃo e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`. @@ -98,7 +98,7 @@ Em muitos casos, sua aplicaรงรฃo FastAPI serรก maior, e vocรช provavelmente usar Por exemplo, vocรช poderia ter uma seรงรฃo para **items** e outra seรงรฃo para **users**, e elas poderiam ser separadas por tags: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Gere um cliente TypeScript com Tags { #generate-a-typescript-client-with-tags } @@ -141,11 +141,11 @@ O FastAPI usa um **ID exclusivo** para cada *operaรงรฃo de rota*, ele รฉ usado p Vocรช pode personalizar essa funรงรฃo. Ela recebe uma `APIRoute` e retorna uma string. -Por exemplo, aqui estรก usando a primeira tag (vocรช provavelmente terรก apenas uma tag) e o nome da *operaรงรฃo de rota* (o nome da funรงรฃo). +Por exemplo, aqui estรก usando a primeira tag (Vocรช provavelmente terรก apenas uma tag) e o nome da *operaรงรฃo de rota* (o nome da funรงรฃo). Vocรช pode entรฃo passar essa funรงรฃo personalizada para o **FastAPI** como o parรขmetro `generate_unique_id_function`: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### Gere um cliente TypeScript com IDs de operaรงรฃo personalizados { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ Mas para o cliente gerado, poderรญamos **modificar** os IDs de operaรงรฃo do Ope Poderรญamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e entรฃo poderรญamos **remover essa tag prefixada** com um script como este: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/pt/docs/advanced/index.md b/docs/pt/docs/advanced/index.md index 23e5510743..d2727be43f 100644 --- a/docs/pt/docs/advanced/index.md +++ b/docs/pt/docs/advanced/index.md @@ -8,7 +8,7 @@ Nas prรณximas seรงรตes vocรช verรก outras opรงรตes, configuraรงรตes, e recursos /// tip | Dica -As prรณximas seรงรตes **nรฃo sรฃo necessรกriamente "avanรงadas"** +As prรณximas seรงรตes **nรฃo sรฃo necessariamente "avanรงadas"**. E รฉ possรญvel que para seu caso de uso, a soluรงรฃo esteja em uma delas. diff --git a/docs/pt/docs/advanced/middleware.md b/docs/pt/docs/advanced/middleware.md index 30c1834790..6bc4bfd2f0 100644 --- a/docs/pt/docs/advanced/middleware.md +++ b/docs/pt/docs/advanced/middleware.md @@ -57,13 +57,13 @@ Garante que todas as requisiรงรตes devem ser `https` ou `wss`. Qualquer requisiรงรฃo para `http` ou `ws` serรก redirecionada para o esquema seguro. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } Garante que todas as requisiรงรตes recebidas tenham um cabeรงalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeรงalho de host HTTP. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} Os seguintes argumentos sรฃo suportados: @@ -78,7 +78,7 @@ Gerencia respostas GZip para qualquer requisiรงรฃo que inclua `"gzip"` no cabeรง O middleware lidarรก com respostas padrรฃo e de streaming. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} Os seguintes argumentos sรฃo suportados: @@ -91,7 +91,7 @@ Hรก muitos outros middlewares ASGI. Por exemplo: -* Uvicorn's `ProxyHeadersMiddleware` +* `ProxyHeadersMiddleware` do Uvicorn * MessagePack Para checar outros middlewares disponรญveis, confira Documentaรงรฃo de Middlewares do Starlette e a Lista Incrรญvel do ASGI. diff --git a/docs/pt/docs/advanced/openapi-callbacks.md b/docs/pt/docs/advanced/openapi-callbacks.md index 57c8c5e81d..653c26d99c 100644 --- a/docs/pt/docs/advanced/openapi-callbacks.md +++ b/docs/pt/docs/advanced/openapi-callbacks.md @@ -106,11 +106,11 @@ Ela deve parecer exatamente como uma *operaรงรฃo de rota* normal do FastAPI: Hรก 2 diferenรงas principais de uma *operaรงรฃo de rota* normal: * Ela nรฃo necessita ter nenhum cรณdigo real, porque seu aplicativo nunca chamarรก esse cรณdigo. Ele รฉ usado apenas para documentar a *API externa*. Entรฃo, a funรงรฃo poderia ter apenas `pass`. -* O *path* pode conter uma expressรฃo OpenAPI 3 (veja mais abaixo) em que pode usar variรกveis com parรขmetros e partes da solicitaรงรฃo original enviada para *sua API*. +* O *path* pode conter uma expressรฃo OpenAPI 3 (veja mais abaixo) em que pode usar variรกveis com parรขmetros e partes do request original enviado para *sua API*. ### A expressรฃo do path do callback { #the-callback-path-expression } -O *path* do callback pode ter uma expressรฃo OpenAPI 3 que pode conter partes da solicitaรงรฃo original enviada para *sua API*. +O *path* do callback pode ter uma expressรฃo OpenAPI 3 que pode conter partes do request original enviado para *sua API*. Nesse caso, รฉ a `str`: diff --git a/docs/pt/docs/advanced/openapi-webhooks.md b/docs/pt/docs/advanced/openapi-webhooks.md index 011898e8cd..ed0d702b2b 100644 --- a/docs/pt/docs/advanced/openapi-webhooks.md +++ b/docs/pt/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Webhooks estรฃo disponรญveis a partir do OpenAPI 3.1.0, e possui suporte do Fast Quando vocรช cria uma aplicaรงรฃo com o **FastAPI**, existe um atributo chamado `webhooks`, que vocรช utilizar para defini-los da mesma maneira que vocรช definiria as suas **operaรงรตes de rotas**, utilizando por exemplo `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} Os webhooks que vocรช define aparecerรฃo no esquema do **OpenAPI** e na **pรกgina de documentaรงรฃo** gerada automaticamente. diff --git a/docs/pt/docs/advanced/path-operation-advanced-configuration.md b/docs/pt/docs/advanced/path-operation-advanced-configuration.md index b3af116a28..c4dd3cbe78 100644 --- a/docs/pt/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/pt/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ Vocรช pode definir o `operationId` do OpenAPI que serรก utilizado na sua *opera Vocรช deveria ter certeza que ele รฉ รบnico para cada operaรงรฃo. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Utilizando o nome da *funรงรฃo de operaรงรฃo de rota* como o operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ Se vocรช quiser utilizar o nome das funรงรตes da sua API como `operationId`s, vo Vocรช deveria fazer isso depois de adicionar todas as suas *operaรงรตes de rota*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | Dica @@ -40,7 +40,7 @@ Mesmo que elas estejam em mรณdulos (arquivos Python) diferentes. Para excluir uma *operaรงรฃo de rota* do esquema OpenAPI gerado (e por consequรชncia, dos sistemas de documentaรงรฃo automรกticos), utilize o parรขmetro `include_in_schema` e defina ele como `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Descriรงรฃo avanรงada a partir de docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ Vocรช pode estender o esquema do OpenAPI para uma *operaรงรฃo de rota* utilizand Esse parรขmetro `openapi_extra` pode ser รบtil, por exemplo, para declarar [Extensรตes do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Se vocรช abrir os documentos criados automaticamente para a API, sua extensรฃo aparecerรก no final da *operaรงรฃo de rota* especรญfica. @@ -139,9 +139,9 @@ Por exemplo, vocรช poderia decidir ler e validar a requisiรงรฃo com seu prรณprio Vocรช pode fazer isso com `openapi_extra`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -Nesse exemplo, nรณs nรฃo declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisiรงรฃo nรฃo estรก nem mesmo analisado como JSON, ele รฉ lido diretamente como `bytes`, e a funรงรฃo `magic_data_reader()` seria a responsรกvel por analisar ele de alguma forma. +Nesse exemplo, nรณs nรฃo declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisiรงรฃo nรฃo estรก nem mesmo analisado como JSON, ele รฉ lido diretamente como `bytes`, e a funรงรฃo `magic_data_reader()` seria a responsรกvel por analisรก-lo de alguma forma. De toda forma, nรณs podemos declarar o esquema esperado para o corpo da requisiรงรฃo. @@ -153,7 +153,7 @@ E vocรช pode fazer isso atรฉ mesmo quando o tipo de dados na requisiรงรฃo nรฃo Por exemplo, nesta aplicaรงรฃo nรณs nรฃo usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validaรงรฃo automรกtica para JSON. Na verdade, estamos declarando o tipo de conteรบdo da requisiรงรฃo como YAML, em vez de JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Entretanto, mesmo que nรฃo utilizemos a funcionalidade integrada por padrรฃo, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber em YAML. @@ -161,7 +161,7 @@ Entรฃo utilizamos a requisiรงรฃo diretamente e extraรญmos o corpo como `bytes`. E entรฃo no nosso cรณdigo, nรณs analisamos o conteรบdo YAML diretamente e, em seguida, estamos usando novamente o mesmo modelo Pydantic para validar o conteรบdo YAML: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | Dica diff --git a/docs/pt/docs/advanced/response-change-status-code.md b/docs/pt/docs/advanced/response-change-status-code.md index ee81f0bfc8..76d9462a87 100644 --- a/docs/pt/docs/advanced/response-change-status-code.md +++ b/docs/pt/docs/advanced/response-change-status-code.md @@ -18,9 +18,9 @@ Para estes casos, vocรช pode utilizar um parรขmetro `Response`. Vocรช pode declarar um parรขmetro do tipo `Response` em sua *funรงรฃo de operaรงรฃo de rota* (assim como vocรช pode fazer para cookies e headers). -E entรฃo vocรช pode definir o `status_code` neste objeto de retorno temporal. +E entรฃo vocรช pode definir o `status_code` neste objeto de retorno *temporal*. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} E entรฃo vocรช pode retornar qualquer objeto que vocรช precise, como vocรช faria normalmente (um `dict`, um modelo de banco de dados, etc.). diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md index 67820b433b..ae9660743a 100644 --- a/docs/pt/docs/advanced/response-cookies.md +++ b/docs/pt/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ Vocรช pode declarar um parรขmetro do tipo `Response` na sua *funรงรฃo de operaรง E entรฃo vocรช pode definir cookies nesse objeto de resposta *temporรกrio*. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} Em seguida, vocรช pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc). @@ -24,7 +24,7 @@ Para fazer isso, vocรช pode criar uma resposta como descrito em [Retorne uma Res Entรฃo, defina os cookies nela e a retorne: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | Dica diff --git a/docs/pt/docs/advanced/response-directly.md b/docs/pt/docs/advanced/response-directly.md index bbbef2f913..311aba56ce 100644 --- a/docs/pt/docs/advanced/response-directly.md +++ b/docs/pt/docs/advanced/response-directly.md @@ -2,7 +2,7 @@ Quando vocรช cria uma *operaรงรฃo de rota* no **FastAPI** vocรช pode retornar qualquer dado nela: um dicionรกrio (`dict`), uma lista (`list`), um modelo do Pydantic ou do seu banco de dados, etc. -Por padrรฃo, o **FastAPI** irรก converter automaticamente o valor do retorno para JSON utilizando o `jsonable_encoder` explicado em [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. +Por padrรฃo, o **FastAPI** irรก converter automaticamente o valor do retorno para JSON utilizando o `jsonable_encoder` explicado em [Codificador Compatรญvel com JSON](../tutorial/encoder.md){.internal-link target=_blank}. Entรฃo, por baixo dos panos, ele incluiria esses dados compatรญveis com JSON (e.g. um `dict`) dentro de uma `JSONResponse` que รฉ utilizada para enviar uma resposta para o cliente. @@ -54,7 +54,7 @@ Vamos dizer que vocรช quer retornar uma resposta usando o prefixo `X-`. -Porรฉm, se voce tiver cabeรงalhos personalizados que deseja que um cliente no navegador possa ver, vocรช precisa adicionรก-los ร s suas configuraรงรตes de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parรขmetro `expose_headers` descrito na documentaรงรฃo de CORS do Starlette. +Porรฉm, se vocรช tiver cabeรงalhos personalizados que deseja que um cliente no navegador possa ver, vocรช precisa adicionรก-los ร s suas configuraรงรตes de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parรขmetro `expose_headers` descrito na documentaรงรฃo de CORS do Starlette. diff --git a/docs/pt/docs/advanced/security/http-basic-auth.md b/docs/pt/docs/advanced/security/http-basic-auth.md index bd572217b2..0ebdb1eb93 100644 --- a/docs/pt/docs/advanced/security/http-basic-auth.md +++ b/docs/pt/docs/advanced/security/http-basic-auth.md @@ -20,7 +20,7 @@ Entรฃo, quando vocรช digitar o usuรกrio e senha, o navegador os envia automatica * Isso retorna um objeto do tipo `HTTPBasicCredentials`: * Isto contรฉm o `username` e o `password` enviado. -{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} Quando vocรช tentar abrir a URL pela primeira vez (ou clicar no botรฃo "Executar" na documentaรงรฃo) o navegador vai pedir pelo seu usuรกrio e senha: @@ -40,7 +40,7 @@ Para lidar com isso, primeiramente nรณs convertemos o `username` e o `password` Entรฃo nรณs podemos utilizar o `secrets.compare_digest()` para garantir que o `credentials.username` รฉ `"stanleyjobson"`, e que o `credentials.password` รฉ `"swordfish"`. -{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} Isso seria parecido com: @@ -104,4 +104,4 @@ Deste modo, ao utilizar `secrets.compare_digest()` no cรณdigo de sua aplicaรงรฃo Apรณs detectar que as credenciais estรฃo incorretas, retorne um `HTTPException` com o status 401 (o mesmo retornado quando nenhuma credencial foi informada) e adicione o cabeรงalho `WWW-Authenticate` para fazer com que o navegador mostre o prompt de login novamente: -{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/pt/docs/advanced/security/oauth2-scopes.md b/docs/pt/docs/advanced/security/oauth2-scopes.md index 591ac9b4aa..0a0c785a01 100644 --- a/docs/pt/docs/advanced/security/oauth2-scopes.md +++ b/docs/pt/docs/advanced/security/oauth2-scopes.md @@ -94,7 +94,7 @@ E nรณs retornamos os escopos como parte do token JWT. Para manter as coisas simples, aqui nรณs estamos apenas adicionando os escopos recebidos diretamente ao token. -Porรฉm em sua aplicaรงรฃo, por seguranรงa, vocรช deve garantir que vocรช apenas adiciona os escopos que o usuรกrio possui permissรฃo de fato, ou aqueles que vocรช predefiniu. +Porรฉm em sua aplicaรงรฃo, por seguranรงa, vocรช deveria garantir que vocรช apenas adiciona os escopos que o usuรกrio possui permissรฃo de fato, ou aqueles que vocรช predefiniu. /// diff --git a/docs/pt/docs/advanced/settings.md b/docs/pt/docs/advanced/settings.md index 28411269bb..88e7f591c3 100644 --- a/docs/pt/docs/advanced/settings.md +++ b/docs/pt/docs/advanced/settings.md @@ -54,7 +54,7 @@ Da mesma forma que com modelos do Pydantic, vocรช declara atributos de classe co Vocรช pode usar as mesmas funcionalidades e ferramentas de validaรงรฃo que usa em modelos do Pydantic, como diferentes tipos de dados e validaรงรตes adicionais com `Field()`. -{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} /// tip | Dica @@ -70,7 +70,7 @@ Em seguida, ele converterรก e validarรก os dados. Assim, quando vocรช usar esse Depois vocรช pode usar o novo objeto `settings` na sua aplicaรงรฃo: -{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} ### Executar o servidor { #run-the-server } @@ -104,11 +104,11 @@ Vocรช pode colocar essas configuraรงรตes em outro arquivo de mรณdulo como visto Por exemplo, vocรช poderia ter um arquivo `config.py` com: -{* ../../docs_src/settings/app01_py39/config.py *} +{* ../../docs_src/settings/app01_py310/config.py *} E entรฃo usรก-lo em um arquivo `main.py`: -{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} /// tip | Dica @@ -126,7 +126,7 @@ Isso pode ser especialmente รบtil durante os testes, pois รฉ muito fรกcil sobres Vindo do exemplo anterior, seu arquivo `config.py` poderia ser assim: -{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} Perceba que agora nรฃo criamos uma instรขncia padrรฃo `settings = Settings()`. @@ -134,7 +134,7 @@ Perceba que agora nรฃo criamos uma instรขncia padrรฃo `settings = Settings()`. Agora criamos uma dependรชncia que retorna um novo `config.Settings()`. -{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} /// tip | Dica @@ -146,13 +146,13 @@ Por enquanto, vocรช pode assumir que `get_settings()` รฉ uma funรงรฃo normal. E entรฃo podemos exigi-la na *funรงรฃo de operaรงรฃo de rota* como dependรชncia e usรก-la onde for necessรกrio. -{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} ### Configuraรงรตes e testes { #settings-and-testing } Entรฃo seria muito fรกcil fornecer um objeto de configuraรงรตes diferente durante os testes criando uma sobrescrita de dependรชncia para `get_settings`: -{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} Na sobrescrita da dependรชncia definimos um novo valor para `admin_email` ao criar o novo objeto `Settings`, e entรฃo retornamos esse novo objeto. @@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" E entรฃo atualizar seu `config.py` com: -{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} /// tip | Dica @@ -226,7 +226,7 @@ criarรญamos esse objeto para cada requisiรงรฃo e lerรญamos o arquivo `.env` para Mas como estamos usando o decorador `@lru_cache` por cima, o objeto `Settings` serรก criado apenas uma vez, na primeira vez em que for chamado. โœ”๏ธ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} Em qualquer chamada subsequente de `get_settings()` nas dependรชncias das prรณximas requisiรงรตes, em vez de executar o cรณdigo interno de `get_settings()` e criar um novo objeto `Settings`, ele retornarรก o mesmo objeto que foi retornado na primeira chamada, repetidamente. diff --git a/docs/pt/docs/advanced/sub-applications.md b/docs/pt/docs/advanced/sub-applications.md index c61d1e92a0..7f176e98d9 100644 --- a/docs/pt/docs/advanced/sub-applications.md +++ b/docs/pt/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ Se vocรช precisar ter duas aplicaรงรตes FastAPI independentes, cada uma com seu Primeiro, crie a aplicaรงรฃo principal, de nรญvel superior, **FastAPI**, e suas *operaรงรตes de rota*: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### Sub-aplicaรงรฃo { #sub-application } @@ -18,7 +18,7 @@ Em seguida, crie sua sub-aplicaรงรฃo e suas *operaรงรตes de rota*. Essa sub-aplicaรงรฃo รฉ apenas outra aplicaรงรฃo FastAPI padrรฃo, mas esta รฉ a que serรก "montada": -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### Monte a sub-aplicaรงรฃo { #mount-the-sub-application } @@ -26,7 +26,7 @@ Na sua aplicaรงรฃo de nรญvel superior, `app`, monte a sub-aplicaรงรฃo, `subapi`. Neste caso, ela serรก montada no path `/subapi`: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### Verifique a documentaรงรฃo automรกtica da API { #check-the-automatic-api-docs } diff --git a/docs/pt/docs/advanced/templates.md b/docs/pt/docs/advanced/templates.md index eb64e72bb8..843727f4f8 100644 --- a/docs/pt/docs/advanced/templates.md +++ b/docs/pt/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 * Declare um parรขmetro `Request` no *path operation* que retornarรก um template. * Use o `templates` que vocรช criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o objeto `request` e um dicionรกrio "context" com pares chave-valor a serem usados dentro do template do Jinja2. -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note | Nota diff --git a/docs/pt/docs/advanced/testing-dependencies.md b/docs/pt/docs/advanced/testing-dependencies.md index 52b12dddbc..f68cdc3a41 100644 --- a/docs/pt/docs/advanced/testing-dependencies.md +++ b/docs/pt/docs/advanced/testing-dependencies.md @@ -36,7 +36,7 @@ Vocรช pode definir uma sobreposiรงรฃo de dependรชncia para uma dependรชncia que A dependรชncia original pode estar sendo utilizada em uma *funรงรฃo de operaรงรฃo de rota*, um *decorador de operaรงรฃo de rota* (quando vocรช nรฃo utiliza o valor retornado), uma chamada ao `.include_router()`, etc. -O FastAPI ainda poderรก sobrescrevรช-lo. +O FastAPI ainda poderรก sobrescrevรช-la. /// @@ -46,6 +46,7 @@ E entรฃo vocรช pode redefinir as suas sobreposiรงรตes (removรช-las) definindo o app.dependency_overrides = {} ``` + /// tip | Dica Se vocรช quer sobrepor uma dependรชncia apenas para alguns testes, vocรช pode definir a sobreposiรงรฃo no inรญcio do teste (dentro da funรงรฃo de teste) e reiniciรก-la ao final (no final da funรงรฃo de teste). diff --git a/docs/pt/docs/advanced/testing-events.md b/docs/pt/docs/advanced/testing-events.md index 971b437630..56c5d45c83 100644 --- a/docs/pt/docs/advanced/testing-events.md +++ b/docs/pt/docs/advanced/testing-events.md @@ -2,10 +2,10 @@ Quando vocรช precisa que o `lifespan` seja executado em seus testes, vocรช pode utilizar o `TestClient` com a instruรงรฃo `with`: -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} Vocรช pode ler mais detalhes sobre o ["Executando lifespan em testes no site oficial da documentaรงรฃo do Starlette."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) Para os eventos `startup` e `shutdown` descontinuados, vocรช pode usar o `TestClient` da seguinte forma: -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/pt/docs/advanced/testing-websockets.md b/docs/pt/docs/advanced/testing-websockets.md index d9d1723a64..ffb0ba3383 100644 --- a/docs/pt/docs/advanced/testing-websockets.md +++ b/docs/pt/docs/advanced/testing-websockets.md @@ -4,7 +4,7 @@ Vocรช pode usar o mesmo `TestClient` para testar WebSockets. Para isso, vocรช utiliza o `TestClient` dentro de uma instruรงรฃo `with`, conectando com o WebSocket: -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | Nota diff --git a/docs/pt/docs/advanced/using-request-directly.md b/docs/pt/docs/advanced/using-request-directly.md index ab1ef9ff4d..283a831d9a 100644 --- a/docs/pt/docs/advanced/using-request-directly.md +++ b/docs/pt/docs/advanced/using-request-directly.md @@ -5,7 +5,7 @@ Atรฉ agora vocรช declarou as partes da requisiรงรฃo que vocรช precisa utilizando Obtendo dados de: * O path como parรขmetros. -* Cabeรงalhos (*Headers*). +* Cabeรงalhos. * Cookies. * etc. @@ -29,7 +29,7 @@ Vamos imaginar que vocรช deseja obter o endereรงo de IP/host do cliente dentro d Para isso vocรช precisa acessar a requisiรงรฃo diretamente. -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} Ao declarar o parรขmetro com o tipo sendo um `Request` em sua *funรงรฃo de operaรงรฃo de rota*, o **FastAPI** saberรก como passar o `Request` neste parรขmetro. diff --git a/docs/pt/docs/advanced/websockets.md b/docs/pt/docs/advanced/websockets.md index 021a73bed3..c294b7603e 100644 --- a/docs/pt/docs/advanced/websockets.md +++ b/docs/pt/docs/advanced/websockets.md @@ -38,13 +38,13 @@ Na produรงรฃo, vocรช teria uma das opรงรตes acima. Mas รฉ a maneira mais simples de focar no lado do servidor de WebSockets e ter um exemplo funcional: -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## Crie um `websocket` { #create-a-websocket } Em sua aplicaรงรฃo **FastAPI**, crie um `websocket`: -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | Detalhes Tรฉcnicos @@ -58,7 +58,7 @@ A **FastAPI** fornece o mesmo `WebSocket` diretamente apenas como uma conveniรชn Em sua rota WebSocket vocรช pode esperar (`await`) por mensagens e enviar mensagens. -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} Vocรช pode receber e enviar dados binรกrios, de texto e JSON. @@ -154,7 +154,7 @@ Com isso vocรช pode conectar o WebSocket e entรฃo enviar e receber mensagens: Quando uma conexรฃo WebSocket รฉ fechada, o `await websocket.receive_text()` levantarรก uma exceรงรฃo `WebSocketDisconnect`, que vocรช pode entรฃo capturar e lidar como neste exemplo. -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} Para testar: diff --git a/docs/pt/docs/advanced/wsgi.md b/docs/pt/docs/advanced/wsgi.md index 99b783cdbe..3178b85eb0 100644 --- a/docs/pt/docs/advanced/wsgi.md +++ b/docs/pt/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ Em seguida, encapsule a aplicaรงรฃo WSGI (e.g. Flask) com o middleware. E entรฃo monte isso sob um path. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | Nota diff --git a/docs/pt/docs/alternatives.md b/docs/pt/docs/alternatives.md index fd992ec951..17ef260dd4 100644 --- a/docs/pt/docs/alternatives.md +++ b/docs/pt/docs/alternatives.md @@ -20,7 +20,7 @@ Mas em algum momento, nรฃo havia outra opรงรฃo senรฃo criar algo que fornecesse ร‰ relativamente bem acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), entรฃo, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento nรฃo รฉ muito fรกcil. -Foi criado para gerar o HTML no backend, nรฃo para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos IoT) comunicando com ele. +Foi criado para gerar o HTML no backend, nรฃo para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos IoT) comunicando com ele. ### Django REST Framework { #django-rest-framework } @@ -137,7 +137,7 @@ Existem vรกrios Flask REST frameworks, mas depois de investir tempo e trabalho i ### Marshmallow { #marshmallow } -Uma das principais funcionalidades necessรกrias em sistemas de API รฉ a "serializaรงรฃo" de dados, que รฉ pegar dados do cรณdigo (Python) e convertรช-los em algo que possa ser enviado pela rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings, etc. +Uma das principais funcionalidades necessรกrias em sistemas de API รฉ a "serializaรงรฃo" de dados, que รฉ pegar dados do cรณdigo (Python) e convertรช-los em algo que possa ser enviado pela rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings, etc. Outra grande funcionalidade necessรกria pelas APIs รฉ a validaรงรฃo de dados, garantindo que os dados sรฃo vรกlidos, dados certos parรขmetros. Por exemplo, que algum campo seja `int`, e nรฃo alguma string aleatรณria. Isso รฉ especialmente รบtil para dados de entrada. @@ -145,7 +145,7 @@ Sem um sistema de validaรงรฃo de dados, vocรช teria que realizar todas as verifi Essas funcionalidades sรฃo o que o Marshmallow foi construรญdo para fornecer. ร‰ uma รณtima biblioteca, e eu a utilizei bastante antes. -Mas ele foi criado antes de existirem as anotaรงรตes de tipo do Python. Entรฃo, para definir cada schema vocรช precisa utilizar utilitรกrios e classes especรญficos fornecidos pelo Marshmallow. +Mas ele foi criado antes de existirem as anotaรงรตes de tipo do Python. Entรฃo, para definir cada schema vocรช precisa utilizar utilitรกrios e classes especรญficos fornecidos pelo Marshmallow. /// check | **FastAPI** inspirado para @@ -155,7 +155,7 @@ Usar cรณdigo para definir "schemas" que forneรงam, automaticamente, tipos de dad ### Webargs { #webargs } -Outra grande funcionalidade requerida pelas APIs รฉ o parsing de dados vindos de requisiรงรตes de entrada. +Outra grande funcionalidade requerida pelas APIs รฉ o parsing de dados vindos de requisiรงรตes de entrada. Webargs รฉ uma ferramenta feita para fornecer isso no topo de vรกrios frameworks, inclusive Flask. @@ -419,7 +419,7 @@ Controlar toda a validaรงรฃo de dados, serializaรงรฃo de dados e documentaรงรฃo ### Starlette { #starlette } -Starlette รฉ um framework/caixa de ferramentas ASGI leve, o que รฉ ideal para construir serviรงos asyncio de alta performance. +Starlette รฉ um framework/caixa de ferramentas ASGI leve, o que รฉ ideal para construir serviรงos asyncio de alta performance. Ele รฉ muito simples e intuitivo. ร‰ projetado para ser facilmente extensรญvel, e ter componentes modulares. diff --git a/docs/pt/docs/benchmarks.md b/docs/pt/docs/benchmarks.md index c0b0c4c466..a54df3d9d5 100644 --- a/docs/pt/docs/benchmarks.md +++ b/docs/pt/docs/benchmarks.md @@ -29,6 +29,6 @@ A hierarquia segue assim: * **FastAPI**: * Do mesmo modo que Starlette utiliza Uvicorn e nรฃo pode ser mais rรกpido que ele, **FastAPI** utiliza o Starlette, entรฃo nรฃo tem como ser mais rรกpido do que o Starlette. * FastAPI fornece mais recursos acima do Starlette. Recursos que vocรช quase sempre precisarรก quando construir APIs, como validaรงรฃo de dados e serializaรงรฃo. E utilizando eles, vocรช terรก uma documentaรงรฃo automรกtica de graรงa (a documentaรงรฃo automรกtica nem sequer adiciona peso para rodar as aplicaรงรตes, ela รฉ gerada na inicializaรงรฃo). - * Se vocรช nunca utilizou FastAPI mas utilizou diretamente o Starlette (ou outra ferramenta, como Sanic, Flask, Responder, etc) vocรช teria que implementar toda validaรงรฃo de dados e serializaรงรฃo por conta. Entรฃo, sua aplicaรงรฃo final poderia ainda ter a mesma sobrecarga como se fosse desenvolvida com FastAPI. Em muitos casos, a validaรงรฃo de dados e serializaรงรฃo รฉ o maior pedaรงo de cรณdigo escrito em aplicaรงรตes. + * Se vocรช nรฃo utilizasse o FastAPI e utilizasse diretamente o Starlette (ou outra ferramenta, como Sanic, Flask, Responder, etc), vocรช teria que implementar toda a validaรงรฃo de dados e serializaรงรฃo por conta. Entรฃo, sua aplicaรงรฃo final poderia ainda ter a mesma sobrecarga como se fosse desenvolvida com FastAPI. Em muitos casos, a validaรงรฃo de dados e serializaรงรฃo รฉ o maior pedaรงo de cรณdigo escrito em aplicaรงรตes. * Entรฃo, ao utilizar o FastAPI vocรช estarรก economizando tempo de desenvolvimento, evitarรก _bugs_, linhas de cรณdigo, e vocรช provavelmente terรก a mesma performance (ou melhor) do que nรฃo utilizรก-lo (jรก que vocรช teria que implementar tudo isso em seu cรณdigo). * Se vocรช quer fazer comparaรงรตes com o FastAPI, compare com um _framework_ (ou conjunto de ferramentas) para aplicaรงรตes _web_ que forneรงa validaรงรฃo de dados, serializaรงรฃo e documentaรงรฃo, como Flask-apispec, NestJS, Molten, etc. _Frameworks_ com validaรงรฃo de dados automรกtica, serializaรงรฃo e documentaรงรฃo integradas. diff --git a/docs/pt/docs/deployment/cloud.md b/docs/pt/docs/deployment/cloud.md index 419fd76265..2e181146ba 100644 --- a/docs/pt/docs/deployment/cloud.md +++ b/docs/pt/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # Implantar FastAPI em provedores de nuvem { #deploy-fastapi-on-cloud-providers } -Vocรช pode usar praticamente **qualquer provedor de nuvem** para implantar seu aplicativo FastAPI. +Vocรช pode usar praticamente **qualquer provedor de nuvem** para implantar sua aplicaรงรฃo FastAPI. Na maioria dos casos, os principais provedores de nuvem tรชm tutoriais para implantar o FastAPI com eles. diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md index d47a153946..4663e96a11 100644 --- a/docs/pt/docs/deployment/docker.md +++ b/docs/pt/docs/deployment/docker.md @@ -14,7 +14,7 @@ Estรก com pressa e jรก sabe dessas coisas? Pode ir direto para o [`Dockerfile` a Visualizaรงรฃo do Dockerfile ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ Agora, no mesmo diretรณrio do projeto, crie um arquivo `Dockerfile` com: ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ Se seu FastAPI for um รบnico arquivo, por exemplo, `main.py` sem um diretรณrio ` Entรฃo vocรช sรณ teria que alterar os caminhos correspondentes para copiar o arquivo dentro do `Dockerfile`: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Sem usar contรชineres, fazer aplicativos executarem na inicializaรงรฃo e com rei ## Replicaรงรฃo - Nรบmero de Processos { #replication-number-of-processes } -Se vocรช tiver um cluster de mรกquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contรชineres distribuรญdos em vรกrias mรกquinas, entรฃo provavelmente desejarรก **lidar com a replicaรงรฃo** no **nรญvel do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contรชiner. +Se vocรช tiver um cluster de mรกquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contรชineres distribuรญdos em vรกrias mรกquinas, entรฃo provavelmente desejarรก **lidar com a replicaรงรฃo** no **nรญvel do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contรชiner. Um desses sistemas de gerenciamento de contรชineres distribuรญdos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicaรงรฃo de contรชineres** enquanto ainda oferece **balanceamento de carga** para as solicitaรงรตes recebidas. Tudo no **nรญvel do cluster**. @@ -499,7 +499,7 @@ Claro, existem **casos especiais** em que vocรช pode querer ter **um contรชiner* Nesses casos, vocรช pode usar a opรงรฃo de linha de comando `--workers` para definir o nรบmero de workers que deseja executar: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -570,7 +570,7 @@ Se vocรช tiver uma configuraรงรฃo simples, com um **รบnico contรชiner** que ent ### Imagem Docker base { #base-docker-image } -Antes havia uma imagem oficial do FastAPI para Docker: tiangolo/uvicorn-gunicorn-fastapi-docker. Mas agora ela estรก descontinuada. โ›”๏ธ +Antes havia uma imagem oficial do FastAPI para Docker: tiangolo/uvicorn-gunicorn-fastapi. Mas agora ela estรก descontinuada. โ›”๏ธ Vocรช provavelmente **nรฃo** deve usar essa imagem base do Docker (ou qualquer outra semelhante). diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md index 6195cefab2..ccd842adbc 100644 --- a/docs/pt/docs/deployment/https.md +++ b/docs/pt/docs/deployment/https.md @@ -28,7 +28,7 @@ Agora, a partir de uma perspectiva do desenvolvedor, aqui estรฃo algumas coisas * Por padrรฃo, isso significa que vocรช sรณ pode ter um certificado HTTPS por endereรงo IP. * Nรฃo importa o tamanho do seu servidor ou quรฃo pequeno cada aplicativo que vocรช tem nele possa ser. * No entanto, existe uma soluรงรฃo para isso. -* Hรก uma extensรฃo para o protocolo TLS (aquele que lida com a criptografia no nรญvel TCP, antes do HTTP) chamada SNI. +* Hรก uma extensรฃo para o protocolo TLS (aquele que lida com a criptografia no nรญvel TCP, antes do HTTP) chamada SNI. * Esta extensรฃo SNI permite que um รบnico servidor (com um รบnico endereรงo IP) tenha vรกrios certificados HTTPS e atenda a vรกrios domรญnios / aplicativos HTTPS. * Para que isso funcione, um รบnico componente (programa) em execuรงรฃo no servidor, ouvindo no endereรงo IP pรบblico, deve ter todos os certificados HTTPS no servidor. * Depois de obter uma conexรฃo segura, o protocolo de comunicaรงรฃo ainda รฉ HTTP. @@ -65,7 +65,7 @@ Aqui estรก um exemplo de como uma API HTTPS poderia ser estruturada, passo a pas A etapa inicial provavelmente seria adquirir algum nome de domรญnio. Entรฃo, vocรช iria configurรก-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). -Vocรช provavelmente usaria um servidor em nuvem (mรกquina virtual) ou algo parecido, e ele teria um fixo Endereรงo IP pรบblico. +Vocรช provavelmente usaria um servidor em nuvem (mรกquina virtual) ou algo parecido, e ele teria um fixo Endereรงo IP pรบblico. No(s) servidor(es) DNS, vocรช configuraria um registro (um `A record`) para apontar seu domรญnio para o endereรงo IP pรบblico do seu servidor. @@ -135,7 +135,7 @@ Entรฃo, o cliente envia uma solicitaรงรฃo HTTPS. Que รฉ apenas uma solicitaรงรฃo -### Desencriptando a Solicitaรงรฃo { #decrypt-the-request } +### Desencripte a Solicitaรงรฃo { #decrypt-the-request } O Proxy de Terminaรงรฃo TLS entรฃo usaria a encriptaรงรฃo combinada para desencriptar a solicitaรงรฃo, e transmitiria a solicitaรงรฃo bรกsica (desencriptada) para o processo executando a aplicaรงรฃo (por exemplo, um processo com Uvicorn executando a aplicaรงรฃo FastAPI). @@ -186,7 +186,7 @@ Para fazer isso, e acomodar as necessidades de diferentes aplicaรงรตes, existem * Executar como um servidor (ao menos durante o processo de aquisiรงรฃo do certificado) no endereรงo IP pรบblico associado com o domรญnio. * Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP especรญficos. * Essa รฉ uma dos motivos que fazem utilizar o mesmo Proxy de Terminaรงรฃo TLS para gerenciar a renovaรงรฃo de certificados ser tรฃo รบtil. - * Caso contrรกrio, vocรช pode ter que parar a execuรงรฃo do Proxy de Terminaรงรฃo TLS momentaneamente, inicializar o programa de renovaรงรฃo para renovar os certificados, e entรฃo reiniciar o Proxy de Terminaรงรฃo TLS. Isso nรฃo รฉ o ideal, jรก que sua(s) aplicaรงรฃo(รตes) nรฃo vรฃo estar disponรญveis enquanto o Proxy de Terminaรงรฃo TLS estiver desligado. + * Caso contrรกrio, vocรช pode ter que parar a execuรงรฃo do Proxy de Terminaรงรฃo TLS momentaneamente, inicializar o programa de renovaรงรฃo para adquirir os certificados, depois configurรก-los com o Proxy de Terminaรงรฃo TLS, e entรฃo reiniciar o Proxy de Terminaรงรฃo TLS. Isso nรฃo รฉ o ideal, jรก que sua(s) aplicaรงรฃo(รตes) nรฃo vรฃo estar disponรญveis enquanto o Proxy de Terminaรงรฃo TLS estiver desligado. Todo esse processo de renovaรงรฃo, enquanto o aplicativo ainda funciona, รฉ uma das principais razรตes para preferir um sistema separado para gerenciar HTTPS com um Proxy de Terminaรงรฃo TLS em vez de usar os certificados TLS no servidor da aplicaรงรฃo diretamente (e.g. com o Uvicorn). diff --git a/docs/pt/docs/deployment/index.md b/docs/pt/docs/deployment/index.md index 6a6c21804d..d9755d0a2b 100644 --- a/docs/pt/docs/deployment/index.md +++ b/docs/pt/docs/deployment/index.md @@ -4,7 +4,7 @@ Implantar uma aplicaรงรฃo **FastAPI** รฉ relativamente fรกcil. ## O que significa Implantaรงรฃo { #what-does-deployment-mean } -Implantar uma aplicaรงรฃo significa executar as etapas necessรกrias para tornรก-la disponรญvel para os usuรกrios. +**Implantar** uma aplicaรงรฃo significa executar as etapas necessรกrias para tornรก-la **disponรญvel para os usuรกrios**. Para uma **web API**, isso normalmente envolve colocรก-la em uma **mรกquina remota**, com um **programa de servidor** que ofereรงa bom desempenho, estabilidade, etc., de modo que seus **usuรกrios** possam **acessar** a aplicaรงรฃo com eficiรชncia e sem interrupรงรตes ou problemas. diff --git a/docs/pt/docs/deployment/manually.md b/docs/pt/docs/deployment/manually.md index 21d0f44cdf..da3a52cf3a 100644 --- a/docs/pt/docs/deployment/manually.md +++ b/docs/pt/docs/deployment/manually.md @@ -46,7 +46,7 @@ Vocรช pode utilizar esse comando, por exemplo, para iniciar sua aplicaรงรฃo **Fa Vamos nos aprofundar um pouco mais em detalhes. -FastAPI utiliza um padrรฃo para construir frameworks e servidores web em Python chamado ASGI. FastAPI รฉ um framework web ASGI. +FastAPI utiliza um padrรฃo para construir frameworks e servidores web em Python chamado ASGI. FastAPI รฉ um framework web ASGI. A principal coisa que vocรช precisa para executar uma aplicaรงรฃo **FastAPI** (ou qualquer outra aplicaรงรฃo ASGI) em uma mรกquina de servidor remoto รฉ um programa de servidor ASGI como o **Uvicorn**, que รฉ o que vem por padrรฃo no comando `fastapi`. diff --git a/docs/pt/docs/deployment/versions.md b/docs/pt/docs/deployment/versions.md index a2aca5a17e..32676da236 100644 --- a/docs/pt/docs/deployment/versions.md +++ b/docs/pt/docs/deployment/versions.md @@ -64,9 +64,9 @@ O "MINOR" รฉ o nรบmero do meio, por exemplo, em `0.2.3`, a versรฃo MINOR รฉ `2`. ## Atualizando as versรตes do FastAPI { #upgrading-the-fastapi-versions } -Vocรช deve adicionar testes para a sua aplicaรงรฃo. +Vocรช deveria adicionar testes para a sua aplicaรงรฃo. -Com **FastAPI** isso รฉ muito fรกcil (graรงas ao Starlette), veja a documentaรงรฃo: [Testing](../tutorial/testing.md){.internal-link target=_blank} +Com **FastAPI** isso รฉ muito fรกcil (graรงas ao Starlette), veja a documentaรงรฃo: [Testes](../tutorial/testing.md){.internal-link target=_blank} Depois que vocรช tiver testes, vocรช pode atualizar a sua versรฃo do **FastAPI** para uma mais recente e se certificar de que todo o seu cรณdigo estรก funcionando corretamente executando seus testes. diff --git a/docs/pt/docs/fastapi-cli.md b/docs/pt/docs/fastapi-cli.md index 0bd7bcd21e..f1e633a236 100644 --- a/docs/pt/docs/fastapi-cli.md +++ b/docs/pt/docs/fastapi-cli.md @@ -58,7 +58,7 @@ Internamente, o **FastAPI CLI** usa o OpenAPI para criaรงรฃo de APIs, incluindo declaraรงรตes de caminho operaรงรตes, parรขmetros, requisiรงรตes de corpo, seguranรงa etc. +* OpenAPI para criaรงรฃo de APIs, incluindo declaraรงรตes de caminho operaรงรตes, parรขmetros, requisiรงรตes de corpo, seguranรงa etc. * Modelo de documentaรงรฃo automรกtica com JSON Schema (jรก que o OpenAPI em si รฉ baseado no JSON Schema). * Projetado em cima desses padrรตes apรณs um estudo meticuloso, em vez de uma reflexรฃo breve. * Isso tambรฉm permite o uso de **geraรงรฃo de cรณdigo do cliente** automaticamente em muitas linguagens. @@ -136,7 +136,7 @@ Tudo construรญdo como ferramentas e componentes reutilizรกveis que sรฃo fรกceis ### Injeรงรฃo de dependรชncia { #dependency-injection } -FastAPI inclui um sistema de injeรงรฃo de dependรชncia extremamente fรกcil de usar, mas extremamente poderoso. +FastAPI inclui um sistema de injeรงรฃo de dependรชncia extremamente fรกcil de usar, mas extremamente poderoso. * Mesmo dependรชncias podem ter dependรชncias, criando uma hierarquia ou **"grafo" de dependรชncias**. * Tudo **automaticamente controlado** pelo framework. @@ -153,8 +153,8 @@ Qualquer integraรงรฃo รฉ projetada para ser tรฃo simples de usar (com dependรชnc ### Testado { #tested } -* 100% de cobertura de testes. -* 100% do cรณdigo com anotaรงรตes de tipo. +* 100% de cobertura de testes. +* 100% do cรณdigo com anotaรงรตes de tipo. * Usado para aplicaรงรตes em produรงรฃo. ## Recursos do Starlette { #starlette-features } @@ -179,7 +179,7 @@ Com **FastAPI**, vocรช terรก todos os recursos do **Starlette** (jรก que FastAPI **FastAPI** รฉ totalmente compatรญvel com (e baseado no) Pydantic. Entรฃo, qualquer cรณdigo Pydantic adicional que vocรช tiver, tambรฉm funcionarรก. -Incluindo bibliotecas externas tambรฉm baseadas no Pydantic, como ORMs e ODMs para bancos de dados. +Incluindo bibliotecas externas tambรฉm baseadas no Pydantic, como ORMs e ODMs para bancos de dados. Isso tambรฉm significa que em muitos casos vocรช poderรก passar o mesmo objeto que vocรช receber de uma requisiรงรฃo **diretamente para o banco de dados**, jรก que tudo รฉ validado automaticamente. @@ -190,7 +190,7 @@ Com **FastAPI** vocรช terรก todos os recursos do **Pydantic** (jรก que FastAPI u * **Sem pegadinhas**: * Sem novas definiรงรตes de esquema de micro-linguagem para aprender. * Se vocรช conhece os tipos do Python, vocรช sabe como usar o Pydantic. -* Vai bem com o/a seu/sua **IDE/linter/cรฉrebro**: +* Vai bem com o/a seu/sua **IDE/linter/cรฉrebro**: * Como as estruturas de dados do Pydantic sรฃo apenas instรขncias de classes que vocรช define, o preenchimento automรกtico, linting, mypy e a sua intuiรงรฃo devem funcionar corretamente com seus dados validados. * Valida **estruturas complexas**: * Use modelos hierรกrquicos do Pydantic, `List` e `Dict` do `typing` do Python, etc. diff --git a/docs/pt/docs/history-design-future.md b/docs/pt/docs/history-design-future.md index 6995287391..fb90d1e1c3 100644 --- a/docs/pt/docs/history-design-future.md +++ b/docs/pt/docs/history-design-future.md @@ -24,7 +24,7 @@ Hรก muitas ferramentas criadas antes que ajudaram a inspirar sua criaรงรฃo. Eu estive evitando a criaรงรฃo de um novo _framework_ por vรกrios anos. Primeiro tentei resolver todas as funcionalidades cobertas por **FastAPI** usando muitos _frameworks_, _plug-ins_ e ferramentas diferentes. -Mas em algum ponto, nรฃo havia outra opรงรฃo senรฃo criar algo que oferecia todas as funcionalidades, aproveitando as melhores ideias de ferramentas anteriores, e combinando-as da melhor maneira possรญvel, usando funcionalidades da linguagem que nem estavam disponรญveis antes (_type hints_ do Python 3.6+). +Mas em algum ponto, nรฃo havia outra opรงรฃo senรฃo criar algo que oferecia todas as funcionalidades, aproveitando as melhores ideias de ferramentas anteriores, e combinando-as da melhor maneira possรญvel, usando funcionalidades da linguagem que nem estavam disponรญveis antes (anotaรงรตes de tipo do Python 3.6+). @@ -32,7 +32,7 @@ Mas em algum ponto, nรฃo havia outra opรงรฃo senรฃo criar algo que oferecia toda Ao usar todas as alternativas anteriores, eu tive a chance de aprender com todas elas, aproveitar ideias e combinรก-las da melhor maneira que encontrei para mim e para os times de desenvolvedores com os quais trabalhava. -Por exemplo, estava claro que idealmente ele deveria ser baseado nos _type hints_ padrรตes do Python. +Por exemplo, estava claro que idealmente ele deveria ser baseado nas anotaรงรตes de tipo padrรฃo do Python. Tambรฉm, a melhor abordagem era usar padrรตes jรก existentes. diff --git a/docs/pt/docs/how-to/authentication-error-status-code.md b/docs/pt/docs/how-to/authentication-error-status-code.md index 878a1ca1ac..40790f180d 100644 --- a/docs/pt/docs/how-to/authentication-error-status-code.md +++ b/docs/pt/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ Mas, se por algum motivo seus clientes dependem do comportamento antigo, vocรช p Por exemplo, vocรช pode criar uma subclasse de `HTTPBearer` que retorne um erro `403 Forbidden` em vez do erro padrรฃo `401 Unauthorized`: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | Dica diff --git a/docs/pt/docs/how-to/conditional-openapi.md b/docs/pt/docs/how-to/conditional-openapi.md index b475dae6d6..b77600a7bc 100644 --- a/docs/pt/docs/how-to/conditional-openapi.md +++ b/docs/pt/docs/how-to/conditional-openapi.md @@ -29,13 +29,13 @@ Vocรช pode usar facilmente as mesmas configuraรงรตes do Pydantic para configurar Por exemplo: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} Aqui declaramos a configuraรงรฃo `openapi_url` com o mesmo padrรฃo de `"/openapi.json"`. E entรฃo a usamos ao criar a aplicaรงรฃo `FastAPI`. -Entรฃo vocรช pode desabilitar o OpenAPI (incluindo a documentaรงรฃo da interface do usuรกrio) definindo a variรกvel de ambiente `OPENAPI_URL` como uma string vazia, como: +Entรฃo vocรช pode desabilitar o OpenAPI (incluindo a documentaรงรฃo da interface do usuรกrio) definindo a variรกvel de ambiente `OPENAPI_URL` como a string vazia, como:
diff --git a/docs/pt/docs/how-to/configure-swagger-ui.md b/docs/pt/docs/how-to/configure-swagger-ui.md index 2d1863c64c..a8f9bed476 100644 --- a/docs/pt/docs/how-to/configure-swagger-ui.md +++ b/docs/pt/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ Sem alterar as configuraรงรตes, o destaque de sintaxe รฉ habilitado por padrรฃo: Mas vocรช pode desabilitรก-lo definindo `syntaxHighlight` como `False`: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ...e entรฃo o Swagger UI nรฃo mostrarรก mais o destaque de sintaxe: @@ -28,7 +28,7 @@ Mas vocรช pode desabilitรก-lo definindo `syntaxHighlight` como `False`: Da mesma forma que vocรช pode definir o tema de destaque de sintaxe com a chave `"syntaxHighlight.theme"` (observe que hรก um ponto no meio): -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} Essa configuraรงรฃo alteraria o tema de cores de destaque de sintaxe: @@ -46,7 +46,7 @@ Vocรช pode substituir qualquer um deles definindo um valor diferente no argument Por exemplo, para desabilitar `deepLinking` vocรช pode passar essas configuraรงรตes para `swagger_ui_parameters`: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## Outros parรขmetros da UI do Swagger { #other-swagger-ui-parameters } diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md index adda9eca50..c7a62aefdf 100644 --- a/docs/pt/docs/how-to/custom-docs-ui-assets.md +++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md @@ -2,13 +2,13 @@ A documentaรงรฃo da API usa **Swagger UI** e **ReDoc**, e cada um deles precisa de alguns arquivos JavaScript e CSS. -Por padrรฃo, esses arquivos sรฃo fornecidos por um CDN. +Por padrรฃo, esses arquivos sรฃo fornecidos por um CDN. Mas รฉ possรญvel personalizรก-los, vocรช pode definir um CDN especรญfico ou providenciar os arquivos vocรช mesmo. ## CDN Personalizado para JavaScript e CSS { #custom-cdn-for-javascript-and-css } -Vamos supor que vocรช deseja usar um CDN diferente, por exemplo, vocรช deseja usar `https://unpkg.com/`. +Vamos supor que vocรช deseja usar um CDN diferente, por exemplo, vocรช deseja usar `https://unpkg.com/`. Isso pode ser รบtil se, por exemplo, vocรช mora em um paรญs que restringe algumas URLs. @@ -18,7 +18,7 @@ O primeiro passo รฉ desativar a documentaรงรฃo automรกtica, pois por padrรฃo, el Para desativรก-los, defina suas URLs como `None` ao criar sua aplicaรงรฃo FastAPI: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### Incluir a documentaรงรฃo personalizada { #include-the-custom-docs } @@ -34,7 +34,7 @@ Vocรช pode reutilizar as funรงรตes internas do FastAPI para criar as pรกginas HT E de forma semelhante para o ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | Dica @@ -50,7 +50,7 @@ Swagger UI lidarรก com isso nos bastidores para vocรช, mas ele precisa desse aux Agora, para poder testar se tudo funciona, crie uma *operaรงรฃo de rota*: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### Teste { #test-it } @@ -118,7 +118,7 @@ Depois disso, sua estrutura de arquivos deve se parecer com: * Importe `StaticFiles`. * "Monte" a instรขncia `StaticFiles()` em um caminho especรญfico. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### Teste os arquivos estรกticos { #test-the-static-files } @@ -144,7 +144,7 @@ Da mesma forma que ao usar um CDN personalizado, o primeiro passo รฉ desativar a Para desativรก-los, defina suas URLs como `None` ao criar sua aplicaรงรฃo FastAPI: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### Incluir a documentaรงรฃo personalizada para arquivos estรกticos { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Novamente, vocรช pode reutilizar as funรงรตes internas do FastAPI para criar as E de forma semelhante para o ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | Dica @@ -176,7 +176,7 @@ Swagger UI lidarรก com isso nos bastidores para vocรช, mas ele precisa desse aux Agora, para poder testar se tudo funciona, crie uma *operaรงรฃo de rota*: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### Teste a UI de Arquivos Estรกticos { #test-static-files-ui } diff --git a/docs/pt/docs/how-to/extending-openapi.md b/docs/pt/docs/how-to/extending-openapi.md index b1b50ce654..b8277c1c4b 100644 --- a/docs/pt/docs/how-to/extending-openapi.md +++ b/docs/pt/docs/how-to/extending-openapi.md @@ -43,19 +43,19 @@ Por exemplo, vamos adicionar documentaรงรฃo do Strawberry. diff --git a/docs/pt/docs/how-to/index.md b/docs/pt/docs/how-to/index.md index a3d16380fe..91df638d7a 100644 --- a/docs/pt/docs/how-to/index.md +++ b/docs/pt/docs/how-to/index.md @@ -2,9 +2,9 @@ Aqui vocรช encontrarรก diferentes exemplos prรกticos ou tutoriais de "como fazer" para **vรกrios tรณpicos**. -A maioria dessas ideias serรก mais ou menos **independente**, e na maioria dos casos vocรช sรณ precisarรก estudรก-las se elas se aplicarem diretamente ao **seu projeto**. +A maioria dessas ideias serรก mais ou menos **independente**, e na maioria dos casos vocรช deveria estudรก-las apenas se elas se aplicarem diretamente ao **seu projeto**. -Se algo parecer interessante e รบtil para o seu projeto, vรก em frente e dรช uma olhada. Caso contrรกrio, vocรช pode simplesmente ignorรก-lo. +Se algo parecer interessante e รบtil para o seu projeto, vรก em frente e dรช uma olhada. Caso contrรกrio, vocรช pode simplesmente ignorรก-las. /// tip | Dica diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index e61cc2e2f4..c337f6d3ac 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -40,7 +40,7 @@ Os recursos chave sรฃo: * **Rรกpido**: alta performance, equivalente a **NodeJS** e **Go** (graรงas ao Starlette e Pydantic). [Um dos frameworks mais rรกpidos disponรญveis](#performance). * **Rรกpido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. * * **Poucos bugs**: Reduz cerca de 40% de erros induzidos por humanos (desenvolvedores). * -* **Intuitivo**: Grande suporte a editores. Completaรงรฃo em todos os lugares. Menos tempo debugando. +* **Intuitivo**: Grande suporte a editores. Completaรงรฃo em todos os lugares. Menos tempo debugando. * **Fรกcil**: Projetado para ser fรกcil de aprender e usar. Menos tempo lendo docs. * **Enxuto**: Minimize duplicaรงรฃo de cรณdigo. Mรบltiplas funcionalidades para cada declaraรงรฃo de parรขmetro. Menos bugs. * **Robusto**: Tenha cรณdigo pronto para produรงรฃo. E com documentaรงรฃo interativa automรกtica. @@ -368,7 +368,7 @@ item: Item * Validaรงรฃo de dados: * Erros automรกticos e claros quando o dado รฉ invรกlido. * Validaรงรฃo atรฉ para objetos JSON profundamente aninhados. -* Conversรฃo de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler: +* Conversรฃo de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler: * JSON. * Parรขmetros de path. * Parรขmetros query. @@ -376,7 +376,7 @@ item: Item * Cabeรงalhos. * Formulรกrios. * Arquivos. -* Conversรฃo de dados de saรญda: convertendo de tipos e dados Python para dados de rede (como JSON): +* Conversรฃo de dados de saรญda: convertendo de tipos e dados Python para dados de rede (como JSON): * Converte tipos Python (`str`, `int`, `float`, `bool`, `list` etc). * Objetos `datetime`. * Objetos `UUID`. @@ -439,7 +439,7 @@ Para um exemplo mais completo incluindo mais recursos, veja Injeรงรฃo de Dependรชncia**. +* Um poderoso e fรกcil de usar sistema de **Injeรงรฃo de Dependรชncia**. * Seguranรงa e autenticaรงรฃo, incluindo suporte para **OAuth2** com autenticaรงรฃo com **JWT tokens** e **HTTP Basic**. * Tรฉcnicas mais avanรงadas (mas igualmente fรกceis) para declaraรงรฃo de **modelos JSON profundamente aninhados** (graรงas ao Pydantic). * Integraรงรตes **GraphQL** com o Strawberry e outras bibliotecas. @@ -524,7 +524,7 @@ Utilizado pelo Starlette: * httpx - Obrigatรณrio caso vocรช queira utilizar o `TestClient`. * jinja2 - Obrigatรณrio se vocรช quer utilizar a configuraรงรฃo padrรฃo de templates. -* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. +* python-multipart - Obrigatรณrio se vocรช deseja suporte a "parsing" de formulรกrio, com `request.form()`. Utilizado pelo FastAPI: diff --git a/docs/pt/docs/python-types.md b/docs/pt/docs/python-types.md index fc983d1df1..bc3f47858c 100644 --- a/docs/pt/docs/python-types.md +++ b/docs/pt/docs/python-types.md @@ -1,14 +1,14 @@ # Introduรงรฃo aos tipos Python { #python-types-intro } -O Python possui suporte para "dicas de tipo" ou "type hints" (tambรฉm chamado de "anotaรงรตes de tipo" ou "type annotations") +O Python possui suporte para "type hints" opcionais (tambรฉm chamados de "type annotations"). -Esses **"type hints"** sรฃo uma sintaxe especial que permite declarar o tipo de uma variรกvel. +Esses **"type hints"** ou anotaรงรตes sรฃo uma sintaxe especial que permite declarar o tipo de uma variรกvel. Ao declarar tipos para suas variรกveis, editores e ferramentas podem oferecer um melhor suporte. Este รฉ apenas um **tutorial rรกpido / atualizaรงรฃo** sobre type hints do Python. Ele cobre apenas o mรญnimo necessรกrio para usรก-los com o **FastAPI**... que รฉ realmente muito pouco. -O **FastAPI** รฉ baseado nesses type hints, eles oferecem muitas vantagens e benefรญcios. +O **FastAPI** รฉ todo baseado nesses type hints, eles oferecem muitas vantagens e benefรญcios. Mas mesmo que vocรช nunca use o **FastAPI**, vocรช se beneficiaria de aprender um pouco sobre eles. @@ -22,7 +22,7 @@ Se vocรช รฉ um especialista em Python e jรก sabe tudo sobre type hints, pule par Vamos comeรงar com um exemplo simples: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} A chamada deste programa gera: @@ -34,9 +34,9 @@ A funรงรฃo faz o seguinte: * Pega um `first_name` e `last_name`. * Converte a primeira letra de cada uma em maiรบsculas com `title()`. -* Concatena com um espaรงo no meio. +* Concatena com um espaรงo no meio. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Edite-o { #edit-it } @@ -52,7 +52,7 @@ Era `upper`? Era `uppercase`? `first_uppercase`? `capitalize`? Em seguida, tente com o velho amigo do programador, o preenchimento automรกtico do editor. -Vocรช digita o primeiro parรขmetro da funรงรฃo, `first_name`, depois um ponto (`.`) e, em seguida, pressiona `Ctrl + Space` para acionar a conclusรฃo. +Vocรช digita o primeiro parรขmetro da funรงรฃo, `first_name`, depois um ponto (`.`) e, em seguida, pressiona `Ctrl+Space` para acionar o preenchimento automรกtico. Mas, infelizmente, vocรช nรฃo obtรฉm nada รบtil: @@ -78,7 +78,7 @@ para: Esses sรฃo os "type hints": -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Isso nรฃo รฉ o mesmo que declarar valores padrรฃo como seria com: @@ -88,7 +88,7 @@ Isso nรฃo รฉ o mesmo que declarar valores padrรฃo como seria com: ร‰ uma coisa diferente. -Estamos usando dois pontos (`:`), nรฃo รฉ igual a (`=`). +Estamos usando dois pontos (`:`), nรฃo sinal de igual (`=`). E adicionar type hints normalmente nรฃo muda o que acontece do que aconteceria sem eles. @@ -106,17 +106,17 @@ Com isso, vocรช pode rolar, vendo as opรงรตes, atรฉ encontrar o que "soa familia Verifique esta funรงรฃo, ela jรก possui type hints: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} -Como o editor conhece os tipos de variรกveis, vocรช nรฃo obtรฉm apenas o preenchimento automรกtico, mas tambรฉm as verificaรงรตes de erro: +Como o editor conhece os tipos das variรกveis, vocรช nรฃo obtรฉm apenas o preenchimento automรกtico, mas tambรฉm as verificaรงรตes de erro: -Agora vocรช sabe que precisa corrigรญ-lo, converta `age` em uma string com `str(age)`: +Agora vocรช sabe que precisa corrigi-la, convertendo `age` em uma string com `str(age)`: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} -## Declarando Tipos { #declaring-types } +## Declarando tipos { #declaring-types } Vocรช acabou de ver o local principal para declarar type hints. Como parรขmetros de funรงรฃo. @@ -133,29 +133,32 @@ Vocรช pode usar, por exemplo: * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Tipos genรฉricos com parรขmetros de tipo { #generic-types-with-type-parameters } +### Mรณdulo `typing` { #typing-module } -Existem algumas estruturas de dados que podem conter outros valores, como `dict`, `list`, `set` e `tuple`. E os valores internos tambรฉm podem ter seu prรณprio tipo. +Para alguns casos adicionais, vocรช pode precisar importar alguns itens do mรณdulo padrรฃo `typing`, por exemplo, quando quiser declarar que algo pode ter "qualquer tipo", vocรช pode usar `Any` de `typing`: -Estes tipos que possuem tipos internos sรฃo chamados de tipos "**genรฉricos**". E รฉ possรญvel declarรก-los mesmo com os seus tipos internos. +```python +from typing import Any -Para declarar esses tipos e os tipos internos, vocรช pode usar o mรณdulo Python padrรฃo `typing`. Ele existe especificamente para suportar esses type hints. -#### Versรตes mais recentes do Python { #newer-versions-of-python } - -A sintaxe utilizando `typing` รฉ **compatรญvel** com todas as versรตes, desde o Python 3.6 atรฉ as รบltimas, incluindo o Python 3.9, 3.10, etc. +def some_function(data: Any): + print(data) +``` -Conforme o Python evolui, **novas versรตes** chegam com suporte melhorado para esses type annotations, e em muitos casos, vocรช nรฃo precisarรก nem importar e utilizar o mรณdulo `typing` para declarar os type annotations. +### Tipos genรฉricos { #generic-types } -Se vocรช pode escolher uma versรฃo mais recente do Python para o seu projeto, vocรช poderรก aproveitar isso ao seu favor. +Alguns tipos podem receber "parรขmetros de tipo" entre colchetes, para definir seus tipos internos, por exemplo, uma "lista de strings" seria declarada como `list[str]`. -Em todos os documentos existem exemplos compatรญveis com cada versรฃo do Python (quando existem diferenรงas). +Esses tipos que podem receber parรขmetros de tipo sรฃo chamados **tipos genรฉricos** ou **genรฉricos**. -Por exemplo, "**Python 3.6+**" significa que รฉ compatรญvel com o Python 3.6 ou superior (incluindo o 3.7, 3.8, 3.9, 3.10, etc). E "**Python 3.9+**" significa que รฉ compatรญvel com o Python 3.9 ou mais recente (incluindo o 3.10, etc). +Vocรช pode usar os mesmos tipos internos como genรฉricos (com colchetes e tipos dentro): -Se vocรช pode utilizar a **versรฃo mais recente do Python**, utilize os exemplos para as รบltimas versรตes. Eles terรฃo as **melhores e mais simples sintaxes**, como por exemplo, "**Python 3.10+**". +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -167,11 +170,11 @@ Como o tipo, coloque `list`. Como a lista รฉ um tipo que contรฉm tipos internos, vocรช os coloca entre colchetes: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | Informaรงรฃo -Estes tipos internos dentro dos colchetes sรฃo chamados "parรขmetros de tipo" (type parameters). +Esses tipos internos dentro dos colchetes sรฃo chamados de "parรขmetros de tipo". Neste caso, `str` รฉ o parรขmetro de tipo passado para `list`. @@ -193,9 +196,9 @@ E, ainda assim, o editor sabe que รฉ um `str` e fornece suporte para isso. Vocรช faria o mesmo para declarar `tuple`s e `set`s: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} -Isso significa que: +Isso significa: * A variรกvel `items_t` รฉ uma `tuple` com 3 itens, um `int`, outro `int` e uma `str`. * A variรกvel `items_s` รฉ um `set`, e cada um de seus itens รฉ do tipo `bytes`. @@ -208,7 +211,7 @@ O primeiro parรขmetro de tipo รฉ para as chaves do `dict`. O segundo parรขmetro de tipo รฉ para os valores do `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Isso significa que: @@ -218,46 +221,22 @@ Isso significa que: #### Union { #union } -Vocรช pode declarar que uma variรกvel pode ser de qualquer um dentre **diversos tipos**. Por exemplo, um `int` ou um `str`. - -No Python 3.6 e superior (incluindo o Python 3.10), vocรช pode utilizar o tipo `Union` de `typing`, e colocar dentro dos colchetes os possรญveis tipos aceitรกveis. +Vocรช pode declarar que uma variรกvel pode ser de qualquer um dentre **vรกrios tipos**, por exemplo, um `int` ou um `str`. -No Python 3.10 tambรฉm existe uma **nova sintaxe** onde vocรช pode colocar os possรญveis tipos separados por uma barra vertical (`|`). +Para defini-la, vocรช usa a barra vertical (`|`) para separar ambos os tipos. -//// tab | Python 3.10+ +Isso รฉ chamado de "uniรฃo", porque a variรกvel pode ser qualquer coisa na uniรฃo desses dois conjuntos de tipos. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -Em ambos os casos, isso significa que `item` poderia ser um `int` ou um `str`. +Isso significa que `item` pode ser um `int` ou um `str`. #### Possivelmente `None` { #possibly-none } Vocรช pode declarar que um valor pode ter um tipo, como `str`, mas que ele tambรฉm pode ser `None`. -No Python 3.6 e superior (incluindo o Python 3.10) vocรช pode declarรก-lo importando e utilizando `Optional` do mรณdulo `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -O uso de `Optional[str]` em vez de apenas `str` permitirรก que o editor o ajude a detectar erros, onde vocรช pode estar assumindo que um valor รฉ sempre um `str`, quando na verdade tambรฉm pode ser `None`. - -`Optional[Something]` รฉ na verdade um atalho para `Union[Something, None]`, eles sรฃo equivalentes. - -Isso tambรฉm significa que no Python 3.10, vocรช pode utilizar `Something | None`: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ Isso tambรฉm significa que no Python 3.10, vocรช pode utilizar `Something | None //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternativa - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### Utilizando `Union` ou `Optional` { #using-union-or-optional } - -Se vocรช estรก utilizando uma versรฃo do Python abaixo da 3.10, aqui vai uma dica do meu ponto de vista bem **subjetivo**: - -* ๐Ÿšจ Evite utilizar `Optional[SomeType]` -* No lugar, โœจ **use `Union[SomeType, None]`** โœจ. - -Ambos sรฃo equivalentes, e no final das contas, eles sรฃo o mesmo. Mas eu recomendaria o `Union` ao invรฉs de `Optional` porque a palavra **Optional** parece implicar que o valor รฉ opcional, quando na verdade significa "isso pode ser `None`", mesmo que ele nรฃo seja opcional e ainda seja obrigatรณrio. - -Eu penso que `Union[SomeType, None]` รฉ mais explรญcito sobre o que ele significa. - -Isso รฉ apenas sobre palavras e nomes. Mas estas palavras podem afetar como os seus colegas de trabalho pensam sobre o cรณdigo. - -Por exemplo, vamos pegar esta funรงรฃo: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -O parรขmetro `name` รฉ definido como `Optional[str]`, mas ele **nรฃo รฉ opcional**, vocรช nรฃo pode chamar a funรงรฃo sem o parรขmetro: - -```Python -say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ -``` - -O parรขmetro `name` **ainda รฉ obrigatรณrio** (nรฃo *opcional*) porque ele nรฃo possui um valor padrรฃo. Mesmo assim, `name` aceita `None` como valor: - -```Python -say_hi(name=None) # This works, None is valid ๐ŸŽ‰ -``` - -A boa notรญcia รฉ, quando vocรช estiver no Python 3.10 vocรช nรฃo precisarรก se preocupar mais com isso, pois vocรช poderรก simplesmente utilizar o `|` para definir uniรตes de tipos: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -E entรฃo vocรช nรฃo precisarรก mais se preocupar com nomes como `Optional` e `Union`. ๐Ÿ˜Ž - -#### Tipos genรฉricos { #generic-types } - -Esses tipos que usam parรขmetros de tipo entre colchetes sรฃo chamados **tipos genรฉricos** ou **genรฉricos**. Por exemplo: - -//// tab | Python 3.10+ - -Vocรช pode utilizar os mesmos tipos internos como genรฉricos (com colchetes e tipos dentro): - -* `list` -* `tuple` -* `set` -* `dict` - -E o mesmo que com versรตes anteriores do Python, do mรณdulo `typing`: - -* `Union` -* `Optional` -* ...entre outros. - -No Python 3.10, como uma alternativa para a utilizaรงรฃo dos genรฉricos `Union` e `Optional`, vocรช pode usar a barra vertical (`|`) para declarar uniรตes de tipos. Isso รฉ muito melhor e mais simples. - -//// - -//// tab | Python 3.9+ - -Vocรช pode utilizar os mesmos tipos internos como genรฉricos (com colchetes e tipos dentro): - -* `list` -* `tuple` -* `set` -* `dict` - -E genรฉricos do mรณdulo `typing`: - -* `Union` -* `Optional` -* ...entre outros. - -//// +Usar `str | None` em vez de apenas `str` permitirรก que o editor o ajude a detectar erros em que vocรช poderia estar assumindo que um valor รฉ sempre um `str`, quando na verdade ele tambรฉm pode ser `None`. ### Classes como tipos { #classes-as-types } @@ -363,13 +253,13 @@ Vocรช tambรฉm pode declarar uma classe como o tipo de uma variรกvel. Digamos que vocรช tenha uma classe `Person`, com um nome: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Entรฃo vocรช pode declarar que uma variรกvel รฉ do tipo `Person`: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} -E entรฃo, novamente, vocรช recebe todo o apoio do editor: +E entรฃo, novamente, vocรช recebe todo o suporte do editor: @@ -379,7 +269,7 @@ Isso nรฃo significa que "`one_person` รฉ a **classe** chamada `Person`". ## Modelos Pydantic { #pydantic-models } -O Pydantic รฉ uma biblioteca Python para executar a validaรงรฃo de dados. +Pydantic รฉ uma biblioteca Python para executar a validaรงรฃo de dados. Vocรช declara a "forma" dos dados como classes com atributos. @@ -403,23 +293,17 @@ O **FastAPI** รฉ todo baseado em Pydantic. Vocรช verรก muito mais disso na prรกtica no [Tutorial - Guia do usuรกrio](tutorial/index.md){.internal-link target=_blank}. -/// tip | Dica - -O Pydantic tem um comportamento especial quando vocรช usa `Optional` ou `Union[Something, None]` sem um valor padrรฃo. Vocรช pode ler mais sobre isso na documentaรงรฃo do Pydantic sobre campos Opcionais Obrigatรณrios. - -/// - ## Type Hints com Metadados de Anotaรงรตes { #type-hints-with-metadata-annotations } -O Python possui uma funcionalidade que nos permite incluir **metadados adicionais** nos type hints utilizando `Annotated`. +O Python tambรฉm possui uma funcionalidade que permite incluir **metadados adicionais** nesses type hints utilizando `Annotated`. -Desde o Python 3.9, `Annotated` faz parte da biblioteca padrรฃo, entรฃo vocรช pode importรก-lo de `typing`. +Vocรช pode importar `Annotated` de `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} O Python em si nรฃo faz nada com este `Annotated`. E para editores e outras ferramentas, o tipo ainda รฉ `str`. -Mas vocรช pode utilizar este espaรงo dentro do `Annotated` para fornecer ao **FastAPI** metadata adicional sobre como vocรช deseja que a sua aplicaรงรฃo se comporte. +Mas vocรช pode utilizar este espaรงo dentro do `Annotated` para fornecer ao **FastAPI** metadados adicionais sobre como vocรช deseja que a sua aplicaรงรฃo se comporte. O importante aqui de se lembrar รฉ que **o primeiro *type parameter*** que vocรช informar ao `Annotated` รฉ o **tipo de fato**. O resto รฉ apenas metadado para outras ferramentas. @@ -446,12 +330,12 @@ Com o **FastAPI**, vocรช declara parรขmetros com type hints e obtรฉm: ... e o **FastAPI** usa as mesmas declaraรงรตes para: -* **Definir requisitos**: dos parรขmetros de rota, parรขmetros da consulta, cabeรงalhos, corpos, dependรชncias, etc. -* **Converter dados**: da solicitaรงรฃo para o tipo necessรกrio. -* **Validar dados**: provenientes de cada solicitaรงรฃo: +* **Definir requisitos**: dos parรขmetros de path da request, parรขmetros da query, cabeรงalhos, corpos, dependรชncias, etc. +* **Converter dados**: da request para o tipo necessรกrio. +* **Validar dados**: provenientes de cada request: * Gerando **erros automรกticos** retornados ao cliente quando os dados sรฃo invรกlidos. * **Documentar** a API usando OpenAPI: - * que รฉ usado pelas interfaces de usuรกrio da documentaรงรฃo interativa automรกtica. + * que รฉ usada pelas interfaces de usuรกrio da documentaรงรฃo interativa automรกtica. Tudo isso pode parecer abstrato. Nรฃo se preocupe. Vocรช verรก tudo isso em aรงรฃo no [Tutorial - Guia do usuรกrio](tutorial/index.md){.internal-link target=_blank}. @@ -459,6 +343,6 @@ O importante รฉ que, usando tipos padrรฃo de Python, em um รบnico local (em vez /// info | Informaรงรฃo -Se vocรช jรก passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso รฉ a "cheat sheet" do `mypy` . +Se vocรช jรก passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso รฉ a "cheat sheet" do `mypy`. /// diff --git a/docs/pt/docs/translation-banner.md b/docs/pt/docs/translation-banner.md new file mode 100644 index 0000000000..f3069ddd77 --- /dev/null +++ b/docs/pt/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ Traduรงรฃo por IA e humanos + +Esta traduรงรฃo foi feita por IA orientada por humanos. ๐Ÿค + +Ela pode conter erros de interpretaรงรฃo do significado original ou soar pouco natural, etc. ๐Ÿค– + +Vocรช pode melhorar esta traduรงรฃo [ajudando-nos a orientar melhor o LLM de IA](https://fastapi.tiangolo.com/pt/contributing/#translations). + +[Versรฃo em inglรชs](ENGLISH_VERSION_URL) + +/// diff --git a/docs/pt/docs/tutorial/background-tasks.md b/docs/pt/docs/tutorial/background-tasks.md index 34805364b4..462fb00dcb 100644 --- a/docs/pt/docs/tutorial/background-tasks.md +++ b/docs/pt/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ Isso inclui, por exemplo: Primeiro, importe `BackgroundTasks` e defina um parรขmetro na sua *funรงรฃo de operaรงรฃo de rota* com uma declaraรงรฃo de tipo `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} O **FastAPI** criarรก o objeto do tipo `BackgroundTasks` para vocรช e o passarรก como esse parรขmetro. @@ -31,13 +31,13 @@ Neste caso, a funรงรฃo da tarefa escreverรก em um arquivo (simulando o envio de E como a operaรงรฃo de escrita nรฃo usa `async` e `await`, definimos a funรงรฃo com um `def` normal: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Adicione a tarefa em segundo plano { #add-the-background-task } Dentro da sua *funรงรฃo de operaรงรฃo de rota*, passe sua funรงรฃo de tarefa para o objeto de *tarefas em segundo plano* com o mรฉtodo `.add_task()`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} O `.add_task()` recebe como argumentos: diff --git a/docs/pt/docs/tutorial/bigger-applications.md b/docs/pt/docs/tutorial/bigger-applications.md index 87bd13375a..ad758988f7 100644 --- a/docs/pt/docs/tutorial/bigger-applications.md +++ b/docs/pt/docs/tutorial/bigger-applications.md @@ -58,17 +58,17 @@ A mesma estrutura de arquivos com comentรกrios: ```bash . -โ”œโ”€โ”€ app # "app" is a Python package -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # this file makes "app" a "Python package" -โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module, e.g. import app.main -โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module, e.g. import app.dependencies -โ”‚ย ย  โ””โ”€โ”€ routers # "routers" is a "Python subpackage" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # makes "routers" a "Python subpackage" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule, e.g. import app.routers.items -โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule, e.g. import app.routers.users -โ”‚ย ย  โ””โ”€โ”€ internal # "internal" is a "Python subpackage" -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # makes "internal" a "Python subpackage" -โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule, e.g. import app.internal.admin +โ”œโ”€โ”€ app # "app" รฉ um pacote Python +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # este arquivo torna "app" um "pacote Python" +โ”‚ย ย  โ”œโ”€โ”€ main.py # mรณdulo "main", p.ex., import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # mรณdulo "dependencies", p.ex., import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" รฉ um "subpacote Python" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # torna "routers" um "subpacote Python" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # submรณdulo "items", p.ex., import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # submรณdulo "users", p.ex., import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" รฉ um "subpacote Python" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # torna "internal" um "subpacote Python" +โ”‚ย ย  โ””โ”€โ”€ admin.py # submรณdulo "admin", p.ex., import app.internal.admin ``` ## `APIRouter` { #apirouter } @@ -85,7 +85,7 @@ Vocรช pode criar as *operaรงรตes de rota* para esse mรณdulo usando o `APIRouter` Vocรช o importa e cria uma "instรขncia" da mesma maneira que faria com a classe `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### *Operaรงรตes de Rota* com `APIRouter` { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ E entรฃo vocรช o utiliza para declarar suas *operaรงรตes de rota*. Utilize-o da mesma maneira que utilizaria a classe `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} Vocรช pode pensar em `APIRouter` como uma classe "mini `FastAPI`". @@ -117,7 +117,7 @@ Entรฃo, as colocamos em seu prรณprio mรณdulo de `dependencies` (`app/dependencie Agora usaremos uma dependรชncia simples para ler um cabeรงalho `X-Token` personalizado: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | Dica @@ -149,7 +149,7 @@ Sabemos que todas as *operaรงรตes de rota* neste mรณdulo tรชm o mesmo: Entรฃo, em vez de adicionar tudo isso a cada *operaรงรฃo de rota*, podemos adicionรก-lo ao `APIRouter`. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} Como o path de cada *operaรงรฃo de rota* tem que comeรงar com `/`, como em: @@ -208,7 +208,7 @@ E precisamos obter a funรงรฃo de dependรชncia do mรณdulo `app.dependencies`, o a Entรฃo usamos uma importaรงรฃo relativa com `..` para as dependรชncias: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### Como funcionam as importaรงรตes relativas { #how-relative-imports-work } @@ -279,7 +279,7 @@ Nรฃo estamos adicionando o prefixo `/items` nem `tags=["items"]` a cada *operaรง Mas ainda podemos adicionar _mais_ `tags` que serรฃo aplicadas a uma *operaรงรฃo de rota* especรญfica, e tambรฉm algumas `responses` extras especรญficas para essa *operaรงรฃo de rota*: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | Dica @@ -305,13 +305,13 @@ Vocรช importa e cria uma classe `FastAPI` normalmente. E podemos atรฉ declarar [dependรชncias globais](dependencies/global-dependencies.md){.internal-link target=_blank} que serรฃo combinadas com as dependรชncias para cada `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### Importe o `APIRouter` { #import-the-apirouter } Agora importamos os outros submรณdulos que possuem `APIRouter`s: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} Como os arquivos `app/routers/users.py` e `app/routers/items.py` sรฃo submรณdulos que fazem parte do mesmo pacote Python `app`, podemos usar um รบnico ponto `.` para importรก-los usando "importaรงรตes relativas". @@ -374,13 +374,13 @@ o `router` de `users` sobrescreveria o de `items` e nรฃo poderรญamos usรก-los ao Entรฃo, para poder usar ambos no mesmo arquivo, importamos os submรณdulos diretamente: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### Inclua os `APIRouter`s para `users` e `items` { #include-the-apirouters-for-users-and-items } Agora, vamos incluir os `router`s dos submรณdulos `users` e `items`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | Informaรงรฃo @@ -420,13 +420,13 @@ Ele contรฉm um `APIRouter` com algumas *operaรงรตes de rota* de administraรงรฃo Para este exemplo, serรก super simples. Mas digamos que, como ele รฉ compartilhado com outros projetos na organizaรงรฃo, nรฃo podemos modificรก-lo e adicionar um `prefix`, `dependencies`, `tags`, etc. diretamente ao `APIRouter`: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Mas ainda queremos definir um `prefix` personalizado ao incluir o `APIRouter` para que todas as suas *operaรงรตes de rota* comecem com `/admin`, queremos protegรช-lo com as `dependencies` que jรก temos para este projeto e queremos incluir `tags` e `responses`. Podemos declarar tudo isso sem precisar modificar o `APIRouter` original passando esses parรขmetros para `app.include_router()`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} Dessa forma, o `APIRouter` original permanecerรก inalterado, para que possamos compartilhar o mesmo arquivo `app/internal/admin.py` com outros projetos na organizaรงรฃo. @@ -447,7 +447,7 @@ Tambรฉm podemos adicionar *operaรงรตes de rota* diretamente ao aplicativo `FastA Aqui fazemos isso... sรณ para mostrar que podemos ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} e funcionarรก corretamente, junto com todas as outras *operaรงรตes de rota* adicionadas com `app.include_router()`. diff --git a/docs/pt/docs/tutorial/body-multiple-params.md b/docs/pt/docs/tutorial/body-multiple-params.md index 24f35b2105..828cde633a 100644 --- a/docs/pt/docs/tutorial/body-multiple-params.md +++ b/docs/pt/docs/tutorial/body-multiple-params.md @@ -104,12 +104,6 @@ Dado que, por padrรฃo, valores singulares sรฃo interpretados como parรขmetros de q: str | None = None ``` -Ou em Python 3.9: - -```Python -q: Union[str, None] = None -``` - Por exemplo: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/pt/docs/tutorial/body-nested-models.md b/docs/pt/docs/tutorial/body-nested-models.md index f2bec19a2f..d53d3f649a 100644 --- a/docs/pt/docs/tutorial/body-nested-models.md +++ b/docs/pt/docs/tutorial/body-nested-models.md @@ -164,7 +164,7 @@ images: list[Image] como em: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Suporte de editor em todo canto { #editor-support-everywhere } @@ -194,7 +194,7 @@ Outro caso รบtil รฉ quando vocรช deseja ter chaves de outro tipo, por exemplo, ` Neste caso, vocรช aceitaria qualquer `dict`, desde que tenha chaves` int` com valores `float`: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Dica diff --git a/docs/pt/docs/tutorial/body.md b/docs/pt/docs/tutorial/body.md index 669334439a..bec553e215 100644 --- a/docs/pt/docs/tutorial/body.md +++ b/docs/pt/docs/tutorial/body.md @@ -72,9 +72,9 @@ Apenas com essa declaraรงรฃo de tipos do Python, o **FastAPI** irรก: * Validar os dados. * Se algum dado for invรกlido, irรก retornar um erro bem claro, indicando exatamente onde e o que estava incorreto. * Entregar a vocรช a informaรงรฃo recebida no parรขmetro `item`. - * Como vocรช o declarou na funรงรฃo como do tipo `Item`, vocรช tambรฉm terรก o suporte do editor (completaรงรฃo, etc) para todos os atributos e seus tipos. + * Como vocรช o declarou na funรงรฃo como do tipo `Item`, vocรช tambรฉm terรก o suporte do editor (preenchimento automรกtico, etc) para todos os atributos e seus tipos. * Gerar definiรงรตes de JSON Schema para o seu modelo; vocรช tambรฉm pode usรก-las em qualquer outro lugar se fizer sentido para o seu projeto. -* Esses schemas farรฃo parte do esquema OpenAPI gerado, e serรฃo usados pelas UIs de documentaรงรฃo automรกtica. +* Esses schemas farรฃo parte do esquema OpenAPI gerado, e serรฃo usados pelas UIs de documentaรงรฃo automรกtica. ## Documentaรงรฃo automรกtica { #automatic-docs } @@ -88,7 +88,7 @@ E tambรฉm serรฃo utilizados na documentaรงรฃo da API dentro de cada *operaรงรฃo ## Suporte do editor { #editor-support } -No seu editor, dentro da funรงรฃo vocรช receberรก dicas de tipos e completaรงรฃo em todo lugar (isso nรฃo aconteceria se vocรช recebesse um `dict` em vez de um modelo Pydantic): +No seu editor, dentro da funรงรฃo vocรช receberรก dicas de tipos e preenchimento automรกtico em todo lugar (isso nรฃo aconteceria se vocรช recebesse um `dict` em vez de um modelo Pydantic): @@ -155,7 +155,7 @@ Os parรขmetros da funรงรฃo serรฃo reconhecidos conforme abaixo: O FastAPI saberรก que o valor de `q` nรฃo รฉ obrigatรณrio por causa do valor padrรฃo `= None`. -O `str | None` (Python 3.10+) ou o `Union` em `Union[str, None]` (Python 3.9+) nรฃo รฉ utilizado pelo FastAPI para determinar que o valor nรฃo รฉ obrigatรณrio, ele saberรก que nรฃo รฉ obrigatรณrio porque tem um valor padrรฃo `= None`. +O `str | None` nรฃo รฉ utilizado pelo FastAPI para determinar que o valor nรฃo รฉ obrigatรณrio, ele saberรก que nรฃo รฉ obrigatรณrio porque tem um valor padrรฃo `= None`. Mas adicionar as anotaรงรตes de tipo permitirรก ao seu editor oferecer um suporte melhor e detectar erros. diff --git a/docs/pt/docs/tutorial/cookie-param-models.md b/docs/pt/docs/tutorial/cookie-param-models.md index 73c94050fb..f125314c8b 100644 --- a/docs/pt/docs/tutorial/cookie-param-models.md +++ b/docs/pt/docs/tutorial/cookie-param-models.md @@ -18,7 +18,7 @@ Essa mesma tรฉcnica se aplica para `Query`, `Cookie`, e `Header`. ๐Ÿ˜Ž ## Cookies com Modelos Pydantic { #cookies-with-a-pydantic-model } -Declare o parรขmetro de **cookie** que vocรช precisa em um **modelo Pydantic**, e depois declare o parรขmetro como um `Cookie`: +Declare os parรขmetros de **cookie** de que vocรช precisa em um **modelo Pydantic**, e depois declare o parรขmetro como `Cookie`: {* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} @@ -46,7 +46,7 @@ Mas mesmo que vocรช **adicionar os dados** e clicar em "Executar", pelo motivo d Em alguns casos especiais (provavelmente nรฃo muito comuns), vocรช pode querer **restringir** os cookies que vocรช deseja receber. -Agora a sua API possui o poder de controlar o seu prรณprio consentimento de cookie. ๐Ÿคช๐Ÿช +Agora a sua API possui o poder de controlar o seu prรณprio consentimento de cookie. ๐Ÿคช๐Ÿช Vocรช pode utilizar a configuraรงรฃo do modelo Pydantic para `proibir` qualquer campo `extra`: @@ -54,9 +54,9 @@ Vocรช pode utilizar a configuraรงรฃo do modelo Pydantic para `proibir` qualquer Se o cliente tentar enviar alguns **cookies extras**, eles receberรฃo um retorno de **erro**. -Coitados dos banners de cookies com todo o seu esforรงo para obter o seu consentimento para a API rejeitรก-lo. ๐Ÿช +Coitados dos banners de cookies com todo o seu esforรงo para obter o seu consentimento para a API rejeitรก-lo. ๐Ÿช -Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de `good-list-please`, o cliente receberรก uma resposta de **erro** informando que o `santa_tracker` cookie nรฃo รฉ permitido: +Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de `good-list-please`, o cliente receberรก uma resposta de **erro** informando que o `santa_tracker` cookie nรฃo รฉ permitido: ```json { @@ -73,4 +73,4 @@ Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de ## Resumo { #summary } -Vocรช consegue utilizar **modelos Pydantic** para declarar **cookies** no **FastAPI**. ๐Ÿ˜Ž +Vocรช consegue utilizar **modelos Pydantic** para declarar **cookies** no **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/pt/docs/tutorial/cors.md b/docs/pt/docs/tutorial/cors.md index 0f99db888e..055cfeacad 100644 --- a/docs/pt/docs/tutorial/cors.md +++ b/docs/pt/docs/tutorial/cors.md @@ -46,7 +46,8 @@ Vocรช tambรฉm pode especificar se o seu backend permite: * Mรฉtodos HTTP especรญficos (`POST`, `PUT`) ou todos eles com o curinga `"*"`. * Cabeรงalhos HTTP especรญficos ou todos eles com o curinga `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + Os parรขmetros padrรฃo usados โ€‹โ€‹pela implementaรงรฃo `CORSMiddleware` sรฃo restritivos por padrรฃo, entรฃo vocรช precisarรก habilitar explicitamente as origens, mรฉtodos ou cabeรงalhos especรญficos para que os navegadores tenham permissรฃo para usรก-los em um contexto cross domain. diff --git a/docs/pt/docs/tutorial/debugging.md b/docs/pt/docs/tutorial/debugging.md index e39c7d1280..773921bb3c 100644 --- a/docs/pt/docs/tutorial/debugging.md +++ b/docs/pt/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Vocรช pode conectar o depurador no seu editor, por exemplo, com o Visual Studio Em sua aplicaรงรฃo FastAPI, importe e execute `uvicorn` diretamente: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### Sobre `__name__ == "__main__"` { #about-name-main } @@ -62,7 +62,7 @@ from myapp import app # Mais um pouco de cรณdigo ``` -nesse caso, a variรกvel criada automaticamente dentro de `myapp.py` nรฃo terรก a variรกvel `__name__` com o valor `"__main__"`. +nesse caso, a variรกvel `__name__` criada automaticamente dentro de `myapp.py` nรฃo terรก o valor `"__main__"`. Entรฃo, a linha: diff --git a/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md index c30d0b5f08..7231373a72 100644 --- a/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ O **FastAPI** chama a classe `CommonQueryParams`. Isso cria uma "instรขncia" des Perceba como escrevemos `CommonQueryParams` duas vezes no cรณdigo abaixo: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica @@ -137,7 +137,7 @@ O รบltimo `CommonQueryParams`, em: Nesse caso, o primeiro `CommonQueryParams`, em: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica @@ -163,7 +163,7 @@ commons: CommonQueryParams ... Na verdade vocรช poderia escrever apenas: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica @@ -197,7 +197,7 @@ Mas declarar o tipo รฉ encorajado por que รฉ a forma que o seu editor de texto s Mas vocรช pode ver que temos uma repetiรงรฃo do cรณdigo neste exemplo, escrevendo `CommonQueryParams` duas vezes: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica @@ -225,7 +225,7 @@ Para esses casos especรญficos, vocรช pode fazer o seguinte: Em vez de escrever: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...escreva: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica diff --git a/docs/pt/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/pt/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index ee8a58dc24..4a99091d11 100644 --- a/docs/pt/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/pt/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -1,6 +1,6 @@ # Dependรชncias em decoradores de operaรงรตes de rota { #dependencies-in-path-operation-decorators } -Em alguns casos vocรช nรฃo precisa necessariamente retornar o valor de uma dependรชncia dentro de uma *funรงรฃo de operaรงรฃo de rota*. +Em alguns casos vocรช nรฃo precisa necessariamente do valor de retorno de uma dependรชncia dentro de uma *funรงรฃo de operaรงรฃo de rota*. Ou a dependรชncia nรฃo retorna nenhum valor. @@ -14,7 +14,7 @@ O *decorador da operaรงรฃo de rota* recebe um argumento opcional `dependencies`. Ele deve ser uma lista de `Depends()`: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} Essas dependรชncias serรฃo executadas/resolvidas da mesma forma que dependรชncias comuns. Mas o valor delas (se existir algum) nรฃo serรก passado para a sua *funรงรฃo de operaรงรฃo de rota*. @@ -44,13 +44,13 @@ Vocรช pode utilizar as mesmas *funรงรตes* de dependรชncias que vocรช usaria norm Dependรชncias podem declarar requisitos de requisiรงรตes (como cabeรงalhos) ou outras subdependรชncias: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### Levantar exceรงรตes { #raise-exceptions } Essas dependรชncias podem `raise` exceรงรตes, da mesma forma que dependรชncias comuns: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### Valores de retorno { #return-values } @@ -58,7 +58,7 @@ E elas tambรฉm podem ou nรฃo retornar valores, eles nรฃo serรฃo utilizados. Entรฃo, vocรช pode reutilizar uma dependรชncia comum (que retorna um valor) que jรก seja utilizada em outro lugar, e mesmo que o valor nรฃo seja utilizado, a dependรชncia serรก executada: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## Dependรชncias para um grupo de *operaรงรตes de rota* { #dependencies-for-a-group-of-path-operations } diff --git a/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md index 3678730139..dd9d9fbe6d 100644 --- a/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Dependรชncias com yield { #dependencies-with-yield } -O **FastAPI** possui suporte para dependรชncias que realizam alguns passos extras ao finalizar. +O **FastAPI** possui suporte para dependรชncias que realizam alguns passos extras ao finalizar. Para fazer isso, utilize `yield` em vez de `return`, e escreva os passos extras (cรณdigo) depois. @@ -29,15 +29,15 @@ Por exemplo, vocรช poderia utilizar isso para criar uma sessรฃo do banco de dado Apenas o cรณdigo anterior ร  declaraรงรฃo com `yield` e o cรณdigo contendo essa declaraรงรฃo sรฃo executados antes de criar uma resposta: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} O valor gerado (yielded) รฉ o que รฉ injetado nas *operaรงรตes de rota* e outras dependรชncias: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} O cรณdigo apรณs o `yield` รฉ executado apรณs a resposta: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | Dica @@ -57,7 +57,7 @@ Entรฃo, vocรช pode procurar por essa exceรงรฃo especรญfica dentro da dependรชnci Da mesma forma, vocรช pode utilizar `finally` para garantir que os passos de saรญda sรฃo executados, com ou sem exceรงรตes. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## Subdependรชncias com `yield` { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ O **FastAPI** garantirรก que o "cรณdigo de saรญda" em cada dependรชncia com `yie Por exemplo, `dependency_c` pode depender de `dependency_b`, e `dependency_b` depender de `dependency_a`: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} E todas elas podem utilizar `yield`. @@ -75,7 +75,7 @@ Neste caso, `dependency_c`, para executar seu cรณdigo de saรญda, precisa que o v E, por outro lado, `dependency_b` precisa que o valor de `dependency_a` (nomeado de `dep_a`) esteja disponรญvel para executar seu cรณdigo de saรญda. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} Da mesma forma, vocรช pode ter algumas dependรชncias com `yield` e outras com `return` e ter uma relaรงรฃo de dependรชncia entre algumas das duas. @@ -109,7 +109,7 @@ Mas ela existe para ser utilizada caso vocรช precise. ๐Ÿค“ /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} Se vocรช quiser capturar exceรงรตes e criar uma resposta personalizada com base nisso, crie um [Manipulador de Exceรงรตes Customizado](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. @@ -117,7 +117,7 @@ Se vocรช quiser capturar exceรงรตes e criar uma resposta personalizada com base Se vocรช capturar uma exceรงรฃo com `except` em uma dependรชncia que utilize `yield` e ela nรฃo for levantada novamente (ou uma nova exceรงรฃo for levantada), o FastAPI nรฃo serรก capaz de identificar que houve uma exceรงรฃo, da mesma forma que aconteceria com Python puro: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} Neste caso, o cliente irรก ver uma resposta *HTTP 500 Internal Server Error* como deveria acontecer, jรก que nรฃo estamos levantando nenhuma `HTTPException` ou coisa parecida, mas o servidor **nรฃo terรก nenhum log** ou qualquer outra indicaรงรฃo de qual foi o erro. ๐Ÿ˜ฑ @@ -127,7 +127,7 @@ Se vocรช capturar uma exceรงรฃo em uma dependรชncia com `yield`, a menos que voc Vocรช pode relanรงar a mesma exceรงรฃo utilizando `raise`: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Agora o cliente irรก receber a mesma resposta *HTTP 500 Internal Server Error*, mas o servidor terรก nosso `InternalError` personalizado nos logs. ๐Ÿ˜Ž @@ -190,7 +190,7 @@ Normalmente, o cรณdigo de saรญda das dependรชncias com `yield` รฉ executado **ap Mas se vocรช sabe que nรฃo precisarรก usar a dependรชncia depois de retornar da *funรงรฃo de operaรงรฃo de rota*, vocรช pode usar `Depends(scope="function")` para dizer ao FastAPI que deve fechar a dependรชncia depois que a *funรงรฃo de operaรงรฃo de rota* retornar, mas **antes** de a **resposta ser enviada**. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` recebe um parรขmetro `scope` que pode ser: @@ -269,7 +269,7 @@ Em Python, vocรช pode criar Gerenciadores de Contexto ao Injeรงรฃo de Dependรชncia**. +O **FastAPI** possui um poderoso, mas intuitivo sistema de **Injeรงรฃo de Dependรชncia**. Esse sistema foi pensado para ser fรกcil de usar, e permitir que qualquer desenvolvedor possa integrar facilmente outros componentes ao **FastAPI**. @@ -25,7 +25,7 @@ Vamos ver um exemplo simples. Tรฃo simples que nรฃo serรก muito รบtil, por enqua Mas dessa forma podemos focar em como o sistema de **Injeรงรฃo de Dependรชncia** funciona. -### Criando uma dependรชncia, ou "injetรกvel" { #create-a-dependency-or-dependable } +### Criando uma dependรชncia, ou "dependable" { #create-a-dependency-or-dependable } Primeiro vamos focar na dependรชncia. @@ -89,7 +89,7 @@ Vocรช verรก quais outras "coisas", alรฉm de funรงรตes, podem ser usadas como dep Sempre que uma nova requisiรงรฃo for realizada, o **FastAPI** se encarrega de: -* Chamar sua dependรชncia ("injetรกvel") com os parรขmetros corretos. +* Chamar sua dependรชncia ("dependable") com os parรขmetros corretos. * Obter o resultado da funรงรฃo. * Atribuir esse resultado para o parรขmetro em sua *funรงรฃo de operaรงรฃo de rota*. @@ -186,7 +186,7 @@ Outros termos comuns para essa mesma ideia de "injeรงรฃo de dependรชncia" sรฃo: Integraรงรตes e "plug-ins" podem ser construรญdos com o sistema de **Injeรงรฃo de Dependรชncia**. Mas na verdade, **nรฃo hรก necessidade de criar "plug-ins"**, jรก que utilizando dependรชncias รฉ possรญvel declarar um nรบmero infinito de integraรงรตes e interaรงรตes que se tornam disponรญveis para as suas *funรงรตes de operaรงรฃo de rota*. -E as dependรชncias pode ser criadas de uma forma bastante simples e intuitiva que permite que vocรช importe apenas os pacotes Python que forem necessรกrios, e integrรก-los com as funรงรตes de sua API em algumas linhas de cรณdigo, *literalmente*. +E as dependรชncias podem ser criadas de uma forma bastante simples e intuitiva que permite que vocรช importe apenas os pacotes Python que forem necessรกrios, e integrรก-los com as funรงรตes de sua API em algumas linhas de cรณdigo, *literalmente*. Vocรช verรก exemplos disso nos prรณximos capรญtulos, acerca de bancos de dados relacionais e NoSQL, seguranรงa, etc. @@ -199,7 +199,7 @@ A simplicidade do sistema de injeรงรฃo de dependรชncia do **FastAPI** faz ele co * pacotes externos * APIs externas * sistemas de autenticaรงรฃo e autorizaรงรฃo -* istemas de monitoramento de uso para APIs +* sistemas de monitoramento de uso para APIs * sistemas de injeรงรฃo de dados de resposta * etc. @@ -209,7 +209,7 @@ Mesmo que o sistema hierรกrquico de injeรงรฃo de dependรชncia seja simples de de Vocรช pode definir dependรชncias que por sua vez definem suas prรณprias dependรชncias. -No fim, uma รกrvore hierรกrquica de dependรชncias รฉ criadas, e o sistema de **Injeรงรฃo de Dependรชncia** toma conta de resolver todas essas dependรชncias (e as sub-dependรชncias delas) para vocรช, e provรช (injeta) os resultados em cada passo. +Por fim, uma รกrvore hierรกrquica de dependรชncias รฉ criada, e o sistema de **Injeรงรฃo de Dependรชncia** toma conta de resolver todas essas dependรชncias (e as sub-dependรชncias delas) para vocรช, e provรช (injeta) os resultados em cada passo. Por exemplo, vamos supor que vocรช possua 4 endpoints na sua API (*operaรงรตes de rota*): diff --git a/docs/pt/docs/tutorial/dependencies/sub-dependencies.md b/docs/pt/docs/tutorial/dependencies/sub-dependencies.md index e2dc9bbf9a..63ed0e48ad 100644 --- a/docs/pt/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/pt/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query Se uma de suas dependรชncias รฉ declarada vรกrias vezes para a mesma *operaรงรฃo de rota*, por exemplo, mรบltiplas dependรชncias com uma mesma subdependรชncia, o **FastAPI** irรก chamar essa subdependรชncia uma รบnica vez para cada requisiรงรฃo. -E o valor retornado รฉ salvo em um "cache" e repassado para todos os "dependentes" que precisam dele em uma requisiรงรฃo especรญfica, em vez de chamar a dependรชncia mรบltiplas vezes para uma mesma requisiรงรฃo. +E o valor retornado รฉ salvo em um "cache" e repassado para todos os "dependentes" que precisam dele em uma requisiรงรฃo especรญfica, em vez de chamar a dependรชncia mรบltiplas vezes para uma mesma requisiรงรฃo. Em um cenรกrio avanรงado onde vocรช precise que a dependรชncia seja calculada em cada passo (possivelmente vรกrias vezes) de uma requisiรงรฃo em vez de utilizar o valor em "cache", vocรช pode definir o parรขmetro `use_cache=False` em `Depends`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ non-Annotated /// tip | Dica diff --git a/docs/pt/docs/tutorial/extra-models.md b/docs/pt/docs/tutorial/extra-models.md index 24eafce015..3136597417 100644 --- a/docs/pt/docs/tutorial/extra-models.md +++ b/docs/pt/docs/tutorial/extra-models.md @@ -190,9 +190,9 @@ Mas se colocarmos isso na atribuiรงรฃo `response_model=PlaneItem | CarItem`, ter Da mesma forma, vocรช pode declarar respostas de listas de objetos. -Para isso, use o padrรฃo Python `typing.List` (ou simplesmente `list` no Python 3.9 e superior): +Para isso, use o padrรฃo Python `list`: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## Resposta com `dict` arbitrรกrio { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ Vocรช tambรฉm pode declarar uma resposta usando um simples `dict` arbitrรกrio, d Isso รฉ รบtil se vocรช nรฃo souber os nomes de campo / atributo vรกlidos (que seriam necessรกrios para um modelo Pydantic) antecipadamente. -Neste caso, vocรช pode usar `typing.Dict` (ou simplesmente `dict` no Python 3.9 e superior): +Neste caso, vocรช pode usar `dict`: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## Recapitulaรงรฃo { #recap } diff --git a/docs/pt/docs/tutorial/first-steps.md b/docs/pt/docs/tutorial/first-steps.md index 86cddde5da..4ccc7cf040 100644 --- a/docs/pt/docs/tutorial/first-steps.md +++ b/docs/pt/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ O arquivo FastAPI mais simples pode se parecer com: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Copie o conteรบdo para um arquivo `main.py`. @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### Passo 1: importe `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` รฉ uma classe Python que fornece todas as funcionalidades para sua API. @@ -197,7 +197,7 @@ Vocรช pode usar todas as funcionalidades do operaรงรฃo get +* usando uma get operaรงรฃo /// info | Informaรงรตes sobre `@decorator` @@ -320,7 +320,7 @@ Esta รฉ a nossa "**funรงรฃo de operaรงรฃo de rota**": * **operaรงรฃo**: รฉ `get`. * **funรงรฃo**: รฉ a funรงรฃo abaixo do "decorador" (abaixo do `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Esta รฉ uma funรงรฃo Python. @@ -332,7 +332,7 @@ Neste caso, รฉ uma funรงรฃo `async`. Vocรช tambรฉm pode defini-la como uma funรงรฃo normal em vez de `async def`: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | Nota @@ -342,7 +342,7 @@ Se vocรช nรฃo sabe a diferenรงa, verifique o [Async: *"Com pressa?"*](../async.m ### Passo 5: retorne o conteรบdo { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Vocรช pode retornar um `dict`, `list` e valores singulares como `str`, `int`, etc. diff --git a/docs/pt/docs/tutorial/handling-errors.md b/docs/pt/docs/tutorial/handling-errors.md index 1c162c205f..252dbb06fb 100644 --- a/docs/pt/docs/tutorial/handling-errors.md +++ b/docs/pt/docs/tutorial/handling-errors.md @@ -25,7 +25,7 @@ Para retornar ao cliente *responses* HTTP com erros, use o `HTTPException`. ### Import `HTTPException` { #import-httpexception } -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} ### Lance o `HTTPException` no seu cรณdigo { #raise-an-httpexception-in-your-code } @@ -33,13 +33,13 @@ Para retornar ao cliente *responses* HTTP com erros, use o `HTTPException`. E porque รฉ uma exceรงรฃo do Python, vocรช nรฃo **retorna** (return) o `HTTPException`, vocรช lanรงa o (raise) no seu cรณdigo. -Isso tambรฉm significa que, se vocรช estรก escrevendo uma funรงรฃo de utilidade, a qual vocรช estรก chamando dentro da sua funรงรฃo de operaรงรตes de caminhos, e vocรช lanรงa o `HTTPException` dentro da funรงรฃo de utilidade, o resto do seu cรณdigo nรฃo serรก executado dentro da funรงรฃo de operaรงรตes de caminhos. Ao contrรกrio, o `HTTPException` irรก finalizar a requisiรงรฃo no mesmo instante e enviarรก o erro HTTP oriundo do `HTTPException` para o cliente. +Isso tambรฉm significa que, se vocรช estรก escrevendo uma funรงรฃo de utilidade, a qual vocรช estรก chamando dentro da sua funรงรฃo de operaรงรฃo de rota, e vocรช lanรงa o `HTTPException` dentro da funรงรฃo de utilidade, o resto do seu cรณdigo nรฃo serรก executado dentro da funรงรฃo de operaรงรฃo de rota. Ao contrรกrio, o `HTTPException` irรก finalizar a requisiรงรฃo no mesmo instante e enviarรก o erro HTTP oriundo do `HTTPException` para o cliente. O benefรญcio de lanรงar uma exceรงรฃo em vez de retornar um valor ficarรก mais evidente na seรงรฃo sobre Dependรชncias e Seguranรงa. Neste exemplo, quando o cliente pede, na requisiรงรฃo, por um item cujo ID nรฃo existe, a exceรงรฃo com o status code `404` รฉ lanรงada: -{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *} +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### A response resultante { #the-resulting-response } @@ -77,7 +77,7 @@ Vocรช provavelmente nรฃo precisarรก utilizar esses headers diretamente no seu c Mas caso vocรช precise, para um cenรกrio mais complexo, vocรช pode adicionar headers customizados: -{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} ## Instale manipuladores de exceรงรตes customizados { #install-custom-exception-handlers } @@ -87,9 +87,9 @@ Digamos que vocรช tenha uma exceรงรฃo customizada `UnicornException` que vocรช ( Nesse cenรกrio, se vocรช precisa manipular essa exceรงรฃo de modo global com o FastAPI, vocรช pode adicionar um manipulador de exceรงรฃo customizada com `@app.exception_handler()`. -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} -Nesse cenรกrio, se vocรช fizer uma requisiรงรฃo para `/unicorns/yolo`, a *operaรงรฃo de caminho* vai lanรงar (`raise`) o `UnicornException`. +Nesse cenรกrio, se vocรช fizer uma requisiรงรฃo para `/unicorns/yolo`, a *operaรงรฃo de rota* vai lanรงar (`raise`) o `UnicornException`. Essa exceรงรฃo serรก manipulada, contudo, pelo `unicorn_exception_handler`. @@ -125,7 +125,7 @@ Para sobrescrevรช-lo, importe o `RequestValidationError` e use-o com o `@app.exc O manipulador de exceรงรตes receberรก um `Request` e a exceรงรฃo. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} Se vocรช for ao `/items/foo`, em vez de receber o JSON padrรฃo com o erro: @@ -157,7 +157,7 @@ Do mesmo modo, vocรช pode sobrescrever o `HTTPException`. Por exemplo, vocรช pode querer retornar uma *response* em *plain text* ao invรฉs de um JSON para os seguintes erros: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | Detalhes Tรฉcnicos @@ -181,7 +181,7 @@ O `RequestValidationError` contรฉm o `body` que ele recebeu de dados invรกlidos. Vocรช pode utilizรก-lo enquanto desenvolve seu app para registrar o *body* e debugรก-lo, e assim retornรก-lo ao usuรกrio, etc. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} Tente enviar um item invรกlido como este: @@ -237,6 +237,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException Se vocรช quer usar a exceรงรฃo em conjunto com o mesmo manipulador de exceรงรฃo *default* do **FastAPI**, vocรช pode importar e re-usar esses manipuladores de exceรงรฃo do `fastapi.exception_handlers`: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} Nesse exemplo vocรช apenas imprime (`print`) o erro com uma mensagem expressiva. Mesmo assim, dรก para pegar a ideia. Vocรช pode usar a exceรงรฃo e entรฃo apenas re-usar o manipulador de exceรงรฃo *default*. diff --git a/docs/pt/docs/tutorial/header-params.md b/docs/pt/docs/tutorial/header-params.md index a0deb98bee..a56f5805e0 100644 --- a/docs/pt/docs/tutorial/header-params.md +++ b/docs/pt/docs/tutorial/header-params.md @@ -12,7 +12,7 @@ Primeiro importe `Header`: Entรฃo declare os paramรชtros de cabeรงalho usando a mesma estrutura que em `Path`, `Query` e `Cookie`. -O primeiro valor รฉ o valor padrรฃo, vocรช pode passar todas as validaรงรตes adicionais ou parรขmetros de anotaรงรฃo: +Vocรช pode definir o valor padrรฃo, assim como todas as validaรงรตes extras ou parรขmetros de anotaรงรฃo: {* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} diff --git a/docs/pt/docs/tutorial/metadata.md b/docs/pt/docs/tutorial/metadata.md index df77e56484..476b5c806e 100644 --- a/docs/pt/docs/tutorial/metadata.md +++ b/docs/pt/docs/tutorial/metadata.md @@ -1,4 +1,4 @@ -# Metadados e Urls de Documentos { #metadata-and-docs-urls } +# Metadados e URLs da Documentaรงรฃo { #metadata-and-docs-urls } Vocรช pode personalizar vรกrias configuraรงรตes de metadados na sua aplicaรงรฃo **FastAPI**. @@ -18,7 +18,7 @@ Vocรช pode definir os seguintes campos que sรฃo usados na especificaรงรฃo OpenAP Vocรช pode defini-los da seguinte maneira: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | Dica @@ -32,11 +32,11 @@ Com essa configuraรงรฃo, a documentaรงรฃo automรกtica da API se pareceria com: ## Identificador de Licenรงa { #license-identifier } -Desde o OpenAPI 3.1.0 e FastAPI 0.99.0, vocรช tambรฉm pode definir o license_info com um identifier em vez de uma url. +Desde o OpenAPI 3.1.0 e FastAPI 0.99.0, vocรช tambรฉm pode definir o `license_info` com um `identifier` em vez de uma `url`. Por exemplo: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## Metadados para tags { #metadata-for-tags } @@ -58,7 +58,7 @@ Vamos tentar isso em um exemplo com tags para `users` e `items`. Crie metadados para suas tags e passe-os para o parรขmetro `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} Observe que vocรช pode usar Markdown dentro das descriรงรตes. Por exemplo, "login" serรก exibido em negrito (**login**) e "fancy" serรก exibido em itรกlico (_fancy_). @@ -72,7 +72,7 @@ Vocรช nรฃo precisa adicionar metadados para todas as tags que vocรช usa. Use o parรขmetro `tags` com suas *operaรงรตes de rota* (e `APIRouter`s) para atribuรญ-los a diferentes tags: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | Informaรงรฃo @@ -100,7 +100,7 @@ Mas vocรช pode configurรก-lo com o parรขmetro `openapi_url`. Por exemplo, para defini-lo para ser servido em `/api/v1/openapi.json`: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} Se vocรช quiser desativar completamente o esquema OpenAPI, pode definir `openapi_url=None`, o que tambรฉm desativarรก as interfaces de documentaรงรฃo que o utilizam. @@ -117,4 +117,4 @@ Vocรช pode configurar as duas interfaces de documentaรงรฃo incluรญdas: Por exemplo, para definir o Swagger UI para ser servido em `/documentation` e desativar o ReDoc: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/pt/docs/tutorial/middleware.md b/docs/pt/docs/tutorial/middleware.md index b49c1eaa11..7cccfcb6ac 100644 --- a/docs/pt/docs/tutorial/middleware.md +++ b/docs/pt/docs/tutorial/middleware.md @@ -31,13 +31,13 @@ A funรงรฃo middleware recebe: * Entรฃo ela retorna a `response` gerada pela *operaรงรฃo de rota* correspondente. * Vocรช pode entรฃo modificar ainda mais o `response` antes de retornรก-lo. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} /// tip | Dica Tenha em mente que cabeรงalhos proprietรกrios personalizados podem ser adicionados usando o prefixo `X-`. -Mas se vocรช tiver cabeรงalhos personalizados desejando que um cliente em um navegador esteja apto a ver, vocรช precisa adicionรก-los ร s suas configuraรงรตes CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando o parรขmetro `expose_headers` documentado em Documentos CORS da Starlette. +Mas se vocรช tiver cabeรงalhos personalizados desejando que um cliente em um navegador esteja apto a ver, vocรช precisa adicionรก-los ร s suas configuraรงรตes CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando o parรขmetro `expose_headers` documentado em Documentaรงรฃo CORS da Starlette. /// @@ -57,7 +57,7 @@ E tambรฉm depois que a `response` รฉ gerada, antes de retornรก-la. Por exemplo, vocรช pode adicionar um cabeรงalho personalizado `X-Process-Time` contendo o tempo em segundos que levou para processar a solicitaรงรฃo e gerar uma resposta: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} /// tip | Dica diff --git a/docs/pt/docs/tutorial/path-operation-configuration.md b/docs/pt/docs/tutorial/path-operation-configuration.md index 2527c28922..c17b12e2bd 100644 --- a/docs/pt/docs/tutorial/path-operation-configuration.md +++ b/docs/pt/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ Nestes casos, pode fazer sentido armazenar as tags em um `Enum`. **FastAPI** suporta isso da mesma maneira que com strings simples: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## Resumo e descriรงรฃo { #summary-and-description } @@ -56,7 +56,7 @@ Vocรช pode adicionar um `summary` e uma `description`: ## Descriรงรฃo do docstring { #description-from-docstring } -Como as descriรงรตes tendem a ser longas e cobrir vรกrias linhas, vocรช pode declarar a descriรงรฃo da *operaรงรฃo de rota* na docstring da funรงรฃo e o **FastAPI** irรก lรช-la de lรก. +Como as descriรงรตes tendem a ser longas e cobrir vรกrias linhas, vocรช pode declarar a descriรงรฃo da *operaรงรฃo de rota* na docstring da funรงรฃo e o **FastAPI** irรก lรช-la de lรก. Vocรช pode escrever Markdown na docstring, ele serรก interpretado e exibido corretamente (levando em conta a indentaรงรฃo da docstring). @@ -90,9 +90,9 @@ Entรฃo, se vocรช nรฃo fornecer uma, o **FastAPI** irรก gerar automaticamente uma ## Descontinuar uma *operaรงรฃo de rota* { #deprecate-a-path-operation } -Se vocรช precisar marcar uma *operaรงรฃo de rota* como descontinuada, mas sem removรช-la, passe o parรขmetro `deprecated`: +Se vocรช precisar marcar uma *operaรงรฃo de rota* como descontinuada, mas sem removรช-la, passe o parรขmetro `deprecated`: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} Ela serรก claramente marcada como descontinuada nas documentaรงรตes interativas: diff --git a/docs/pt/docs/tutorial/path-params-numeric-validations.md b/docs/pt/docs/tutorial/path-params-numeric-validations.md index 9f12ba38fe..bb2e154f43 100644 --- a/docs/pt/docs/tutorial/path-params-numeric-validations.md +++ b/docs/pt/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Isso nรฃo faz diferenรงa para o **FastAPI**. Ele vai detectar os parรขmetros pel Entรฃo, vocรช pode declarar sua funรงรฃo assim: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Mas tenha em mente que, se vocรช usar `Annotated`, vocรช nรฃo terรก esse problema, nรฃo farรก diferenรงa, pois vocรช nรฃo estรก usando valores padrรฃo de parรขmetros de funรงรฃo para `Query()` ou `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Ordene os parรขmetros de acordo com sua necessidade, truques { #order-the-parameters-as-you-need-tricks } @@ -81,15 +81,15 @@ Se vocรช quiser: Passe `*`, como o primeiro parรขmetro da funรงรฃo. -O Python nรฃo farรก nada com esse `*`, mas saberรก que todos os parรขmetros seguintes devem ser chamados como argumentos nomeados (pares chave-valor), tambรฉm conhecidos como kwargs. Mesmo que eles nรฃo tenham um valor padrรฃo. +O Python nรฃo farรก nada com esse `*`, mas saberรก que todos os parรขmetros seguintes devem ser chamados como argumentos nomeados (pares chave-valor), tambรฉm conhecidos como kwargs. Mesmo que eles nรฃo tenham um valor padrรฃo. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Melhor com `Annotated` { #better-with-annotated } Tenha em mente que, se vocรช usar `Annotated`, como vocรช nรฃo estรก usando valores padrรฃo de parรขmetros de funรงรฃo, vocรช nรฃo terรก esse problema e provavelmente nรฃo precisarรก usar `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Validaรงรตes numรฉricas: maior que ou igual { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Com `Query` e `Path` (e outras que vocรช verรก depois) vocรช pode declarar restr Aqui, com `ge=1`, `item_id` precisarรก ser um nรบmero inteiro โ€œ`g`reater than or `e`qualโ€ a `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Validaรงรตes numรฉricas: maior que e menor que ou igual { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ O mesmo se aplica a: * `gt`: maior que (`g`reater `t`han) * `le`: menor que ou igual (`l`ess than or `e`qual) -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Validaรงรตes numรฉricas: floats, maior que e menor que { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Assim, `0.5` seria um valor vรกlido. Mas `0.0` ou `0` nรฃo seriam. E o mesmo para lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Recapitulando { #recap } diff --git a/docs/pt/docs/tutorial/path-params.md b/docs/pt/docs/tutorial/path-params.md index 1f47ca6e59..e8e420ad0d 100644 --- a/docs/pt/docs/tutorial/path-params.md +++ b/docs/pt/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Vocรช pode declarar "parรขmetros" ou "variรกveis" de path com a mesma sintaxe usada por strings de formataรงรฃo do Python: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} O valor do parรขmetro de path `item_id` serรก passado para a sua funรงรฃo como o argumento `item_id`. @@ -16,7 +16,7 @@ Entรฃo, se vocรช executar este exemplo e acessar conversรฃo { #data-conversion } +## Dados conversรฃo { #data-conversion } Se vocรช executar este exemplo e abrir seu navegador em http://127.0.0.1:8000/items/3, vocรช verรก uma resposta: @@ -35,7 +35,7 @@ Se vocรช executar este exemplo e abrir seu navegador em "parsing" automรกtico do request. +Entรฃo, com essa declaraรงรฃo de tipo, o **FastAPI** fornece "parsing" automรกtico do request. /// ## Validaรงรฃo de dados { #data-validation } @@ -110,19 +110,19 @@ E entรฃo vocรช tambรฉm pode ter um path `/users/{user_id}` para obter dados sobr Como as *operaรงรตes de rota* sรฃo avaliadas em ordem, vocรช precisa garantir que o path para `/users/me` seja declarado antes do de `/users/{user_id}`: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} Caso contrรกrio, o path para `/users/{user_id}` tambรฉm corresponderia a `/users/me`, "achando" que estรก recebendo um parรขmetro `user_id` com o valor `"me"`. Da mesma forma, vocรช nรฃo pode redefinir uma operaรงรฃo de rota: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} A primeira sempre serรก usada, jรก que o path corresponde primeiro. ## Valores predefinidos { #predefined-values } -Se vocรช tem uma *operaรงรฃo de rota* que recebe um *parรขmetro de path*, mas quer que os valores vรกlidos possรญveis do *parรขmetro de path* sejam predefinidos, vocรช pode usar um `Enum` padrรฃo do Python. +Se vocรช tem uma *operaรงรฃo de rota* que recebe um *parรขmetro de path*, mas quer que os valores vรกlidos possรญveis do *parรขmetro de path* sejam predefinidos, vocรช pode usar um `Enum` padrรฃo do Python. ### Crie uma classe `Enum` { #create-an-enum-class } @@ -132,17 +132,17 @@ Ao herdar de `str`, a documentaรงรฃo da API saberรก que os valores devem ser do Em seguida, crie atributos de classe com valores fixos, que serรฃo os valores vรกlidos disponรญveis: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | Dica -Se vocรช estรก se perguntando, "AlexNet", "ResNet" e "LeNet" sรฃo apenas nomes de modelos de Aprendizado de Mรกquina. +Se vocรช estรก se perguntando, "AlexNet", "ResNet" e "LeNet" sรฃo apenas nomes de modelos de Aprendizado de Mรกquina modelos. /// ### Declare um parรขmetro de path { #declare-a-path-parameter } Em seguida, crie um *parรขmetro de path* com anotaรงรฃo de tipo usando a classe enum que vocรช criou (`ModelName`): -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### Verifique a documentaรงรฃo { #check-the-docs } @@ -158,13 +158,13 @@ O valor do *parรขmetro de path* serรก um *membro de enumeraรงรฃo*. Vocรช pode comparรก-lo com o *membro de enumeraรงรฃo* no seu enum `ModelName` criado: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### Obtenha o valor da enumeraรงรฃo { #get-the-enumeration-value } Vocรช pode obter o valor real (um `str` neste caso) usando `model_name.value`, ou, em geral, `your_enum_member.value`: -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | Dica Vocรช tambรฉm pode acessar o valor `"lenet"` com `ModelName.lenet.value`. @@ -176,7 +176,7 @@ Vocรช pode retornar *membros de enum* da sua *operaรงรฃo de rota*, atรฉ mesmo an Eles serรฃo convertidos para seus valores correspondentes (strings neste caso) antes de serem retornados ao cliente: -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} No seu cliente, vocรช receberรก uma resposta JSON como: @@ -215,7 +215,7 @@ Nesse caso, o nome do parรขmetro รฉ `file_path`, e a รบltima parte, `:path`, diz Entรฃo, vocรช pode usรก-lo com: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | Dica Vocรช pode precisar que o parรขmetro contenha `/home/johndoe/myfile.txt`, com uma barra inicial (`/`). @@ -227,8 +227,8 @@ Nesse caso, a URL seria: `/files//home/johndoe/myfile.txt`, com uma barra dupla Com o **FastAPI**, ao usar declaraรงรตes de tipo do Python curtas, intuitivas e padrรฃo, vocรช obtรฉm: -- Suporte no editor: verificaรงรตes de erro, autocompletar, etc. -- "Parsing" de dados +- Suporte no editor: verificaรงรตes de erro, preenchimento automรกtico, etc. +- "parsing" de dados - Validaรงรฃo de dados - Anotaรงรฃo da API e documentaรงรฃo automรกtica diff --git a/docs/pt/docs/tutorial/query-param-models.md b/docs/pt/docs/tutorial/query-param-models.md index 42d2604cd4..7fc59c0335 100644 --- a/docs/pt/docs/tutorial/query-param-models.md +++ b/docs/pt/docs/tutorial/query-param-models.md @@ -18,10 +18,9 @@ Declare os **parรขmetros de consulta** que vocรช precisa em um **modelo Pydantic O **FastAPI** **extrairรก** os dados para **cada campo** dos **parรขmetros de consulta** presentes na requisiรงรฃo, e fornecerรก o modelo Pydantic que vocรช definiu. +## Verifique a Documentaรงรฃo { #check-the-docs } -## Verifique os Documentos { #check-the-docs } - -Vocรช pode ver os parรขmetros de consulta nos documentos de IU em `/docs`: +Vocรช pode ver os parรขmetros de consulta na IU da documentaรงรฃo em `/docs`:
@@ -29,9 +28,9 @@ Vocรช pode ver os parรขmetros de consulta nos documentos de IU em `/docs`: ## Restrinja Parรขmetros de Consulta Extras { #forbid-extra-query-parameters } -Em alguns casos especiais (provavelmente nรฃo muito comuns), vocรช queira **restrinjir** os parรขmetros de consulta que deseja receber. +Em alguns casos especiais (provavelmente nรฃo muito comuns), vocรช queira **restringir** os parรขmetros de consulta que deseja receber. -Vocรช pode usar a configuraรงรฃo do modelo Pydantic para `forbid` (proibir) qualquer campo `extra`: +Vocรช pode usar a configuraรงรฃo do modelo Pydantic para `forbid` qualquer campo `extra`: {* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} @@ -43,7 +42,7 @@ Por exemplo, se o cliente tentar enviar um parรขmetro de consulta `tool` com o v https://example.com/items/?limit=10&tool=plumbus ``` -Eles receberรฃo um retorno de **erro** informando-os que o parรขmentro de consulta `tool` nรฃo รฉ permitido: +Eles receberรฃo um retorno de **erro** informando-os que o parรขmetro de consulta `tool` nรฃo รฉ permitido: ```json { diff --git a/docs/pt/docs/tutorial/query-params-str-validations.md b/docs/pt/docs/tutorial/query-params-str-validations.md index c93a941e52..b76b76a268 100644 --- a/docs/pt/docs/tutorial/query-params-str-validations.md +++ b/docs/pt/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Ter `str | None` permitirรก que seu editor lhe ofereรงa melhor suporte e detecte ## Validaรงรฃo adicional { #additional-validation } -Vamos impor que, embora `q` seja opcional, sempre que for fornecido, **seu comprimento nรฃo exceda 50 caracteres**. +Vamos impor que, embora `q` seja opcional, sempre que for fornecido, seu comprimento nรฃo exceda 50 caracteres. ### Importe `Query` e `Annotated` { #import-query-and-annotated } @@ -47,40 +47,16 @@ Agora รฉ a hora de usรก-lo com FastAPI. ๐Ÿš€ Tรญnhamos esta anotaรงรฃo de tipo: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - O que faremos รฉ envolver isso com `Annotated`, para que fique assim: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Ambas as versรตes significam a mesma coisa, `q` รฉ um parรขmetro que pode ser `str` ou `None`, e por padrรฃo รฉ `None`. Agora vamos pular para a parte divertida. ๐ŸŽ‰ @@ -93,23 +69,23 @@ Agora que temos esse `Annotated` onde podemos colocar mais informaรงรตes (neste Perceba que o valor padrรฃo continua sendo `None`, entรฃo o parรขmetro ainda รฉ opcional. -Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos **validaรงรฃo adicional** para este valor, queremos que tenha no mรกximo 50 caracteres. ๐Ÿ˜Ž +Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos validaรงรฃo adicional para este valor, queremos que tenha no mรกximo 50 caracteres. ๐Ÿ˜Ž /// tip | Dica -Aqui estamos usando `Query()` porque este รฉ um **parรขmetro de consulta**. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que tambรฉm aceitam os mesmos argumentos que `Query()`. +Aqui estamos usando `Query()` porque este รฉ um parรขmetro de consulta. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que tambรฉm aceitam os mesmos argumentos que `Query()`. /// Agora o FastAPI vai: -* **Validar** os dados garantindo que o comprimento mรกximo seja de 50 caracteres -* Mostrar um **erro claro** para o cliente quando os dados nรฃo forem vรกlidos -* **Documentar** o parรขmetro na *operaรงรฃo de rota* do esquema OpenAPI (entรฃo ele aparecerรก na **UI de docs automรกtica**) +* Validar os dados garantindo que o comprimento mรกximo seja de 50 caracteres +* Mostrar um erro claro para o cliente quando os dados nรฃo forem vรกlidos +* Documentar o parรขmetro na operaรงรฃo de rota do esquema OpenAPI (entรฃo ele aparecerรก na UI de docs automรกtica) ## Alternativa (antiga): `Query` como valor padrรฃo { #alternative-old-query-as-the-default-value } -Versรตes anteriores do FastAPI (antes de 0.95.0) exigiam que vocรช usasse `Query` como valor padrรฃo do seu parรขmetro, em vez de colocรก-lo em `Annotated`, hรก uma grande chance de vocรช ver cรณdigo usando isso por aรญ, entรฃo vou explicar. +Versรตes anteriores do FastAPI (antes de 0.95.0) exigiam que vocรช usasse `Query` como valor padrรฃo do seu parรขmetro, em vez de colocรก-lo em `Annotated`, hรก uma grande chance de vocรช ver cรณdigo usando isso por aรญ, entรฃo vou explicar. /// tip | Dica @@ -144,7 +120,7 @@ Entรฃo, podemos passar mais parรขmetros para `Query`. Neste caso, o parรขmetro ` q: str | None = Query(default=None, max_length=50) ``` -Isso validarรก os dados, mostrarรก um erro claro quando os dados nรฃo forem vรกlidos e documentarรก o parรขmetro na *operaรงรฃo de rota* do esquema OpenAPI. +Isso validarรก os dados, mostrarรก um erro claro quando os dados nรฃo forem vรกlidos e documentarรก o parรขmetro na operaรงรฃo de rota do esquema OpenAPI. ### `Query` como valor padrรฃo ou em `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -174,13 +150,13 @@ q: str = Query(default="rick") ### Vantagens de `Annotated` { #advantages-of-annotated } -**Usar `Annotated` รฉ recomendado** em vez do valor padrรฃo nos parรขmetros da funรงรฃo, รฉ **melhor** por vรกrios motivos. ๐Ÿค“ +Usar `Annotated` รฉ recomendado em vez do valor padrรฃo nos parรขmetros da funรงรฃo, รฉ melhor por vรกrios motivos. ๐Ÿค“ -O valor **padrรฃo** do **parรขmetro da funรงรฃo** รฉ o **valor padrรฃo real**, isso รฉ mais intuitivo com Python em geral. ๐Ÿ˜Œ +O valor padrรฃo do parรขmetro da funรงรฃo รฉ o valor padrรฃo real, isso รฉ mais intuitivo com Python em geral. ๐Ÿ˜Œ -Vocรช poderia **chamar** essa mesma funรงรฃo em **outros lugares** sem FastAPI, e ela **funcionaria como esperado**. Se houver um parรขmetro **obrigatรณrio** (sem valor padrรฃo), seu **editor** vai avisar com um erro, e o **Python** tambรฉm reclamarรก se vocรช executรก-la sem passar o parรขmetro obrigatรณrio. +Vocรช poderia chamar essa mesma funรงรฃo em outros lugares sem FastAPI, e ela funcionaria como esperado. Se houver um parรขmetro obrigatรณrio (sem valor padrรฃo), seu editor vai avisar com um erro, e o Python tambรฉm reclamarรก se vocรช executรก-la sem passar o parรขmetro obrigatรณrio. -Quando vocรช nรฃo usa `Annotated` e em vez disso usa o estilo de **valor padrรฃo (antigo)**, se vocรช chamar essa funรงรฃo sem FastAPI em **outros lugares**, terรก que **lembrar** de passar os argumentos para a funรงรฃo para que funcione corretamente, caso contrรกrio os valores serรฃo diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor nรฃo vai avisar, e o Python tambรฉm nรฃo vai reclamar ao executar a funรงรฃo, apenas quando as operaรงรตes internas falharem. +Quando vocรช nรฃo usa `Annotated` e em vez disso usa o estilo de valor padrรฃo (antigo), se vocรช chamar essa funรงรฃo sem FastAPI em outros lugares, terรก que lembrar de passar os argumentos para a funรงรฃo para que funcione corretamente, caso contrรกrio os valores serรฃo diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor nรฃo vai avisar, e o Python tambรฉm nรฃo vai reclamar ao executar a funรงรฃo, apenas quando as operaรงรตes internas falharem. Como `Annotated` pode ter mais de uma anotaรงรฃo de metadados, vocรช agora pode atรฉ usar a mesma funรงรฃo com outras ferramentas, como o Typer. ๐Ÿš€ @@ -192,7 +168,7 @@ Vocรช tambรฉm pode adicionar um parรขmetro `min_length`: ## Adicione expressรตes regulares { #add-regular-expressions } -Vocรช pode definir um `pattern` de expressรฃo regular que o parรขmetro deve corresponder: +Vocรช pode definir um `pattern` de expressรฃo regular que o parรขmetro deve corresponder: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -202,9 +178,9 @@ Esse padrรฃo especรญfico de expressรฃo regular verifica se o valor recebido no p * `fixedquery`: tem exatamente o valor `fixedquery`. * `$`: termina ali, nรฃo tem mais caracteres depois de `fixedquery`. -Se vocรช se sentir perdido com essas ideias de **"expressรฃo regular"**, nรฃo se preocupe. Esse รฉ um assunto difรญcil para muitas pessoas. Vocรช ainda pode fazer muitas coisas sem precisar de expressรตes regulares por enquanto. +Se vocรช se sentir perdido com essas ideias de "expressรฃo regular", nรฃo se preocupe. Esse รฉ um assunto difรญcil para muitas pessoas. Vocรช ainda pode fazer muitas coisas sem precisar de expressรตes regulares por enquanto. -Agora vocรช sabe que, sempre que precisar delas, pode usรก-las no **FastAPI**. +Agora vocรช sabe que, sempre que precisar delas, pode usรก-las no FastAPI. ## Valores padrรฃo { #default-values } @@ -212,7 +188,7 @@ Vocรช pode, claro, usar valores padrรฃo diferentes de `None`. Digamos que vocรช queira declarar o parรขmetro de consulta `q` com `min_length` de `3` e ter um valor padrรฃo de `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Nota @@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Entรฃo, quando vocรช precisa declarar um valor como obrigatรณrio usando `Query`, vocรช pode simplesmente nรฃo declarar um valor padrรฃo: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Obrigatรณrio, pode ser `None` { #required-can-be-none } @@ -266,7 +242,7 @@ Entรฃo, com uma URL como: http://localhost:8000/items/?q=foo&q=bar ``` -vocรช receberia os mรบltiplos valores dos *parรขmetros de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *funรงรฃo de operaรงรฃo de rota*, no *parรขmetro da funรงรฃo* `q`. +vocรช receberia os mรบltiplos valores dos parรขmetros de consulta `q` (`foo` e `bar`) em uma `list` Python dentro da sua funรงรฃo de operaรงรฃo de rota, no parรขmetro da funรงรฃo `q`. Assim, a resposta para essa URL seria: @@ -293,7 +269,7 @@ A documentaรงรฃo interativa da API serรก atualizada de acordo, permitindo mรบlti Vocรช tambรฉm pode definir uma `list` de valores padrรฃo caso nenhum seja fornecido: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Se vocรช for atรฉ: @@ -316,13 +292,13 @@ o valor padrรฃo de `q` serรก: `["foo", "bar"]` e sua resposta serรก: Vocรช tambรฉm pode usar `list` diretamente em vez de `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Nota Tenha em mente que, neste caso, o FastAPI nรฃo verificarรก o conteรบdo da lista. -Por exemplo, `list[int]` verificaria (e documentaria) que os conteรบdos da lista sรฃo inteiros. Mas `list` sozinho nรฃo. +Por exemplo, `list[int]` verificaria (and documentaria) que os conteรบdos da lista sรฃo inteiros. Mas `list` sozinho nรฃo. /// @@ -372,7 +348,7 @@ Entรฃo vocรช pode declarar um `alias`, e esse alias serรก usado para encontrar o Agora digamos que vocรช nรฃo gosta mais desse parรขmetro. -Vocรช tem que deixรก-lo por um tempo, pois hรก clientes usando-o, mas quer que a documentaรงรฃo mostre claramente que ele estรก deprecated. +Vocรช tem que deixรก-lo por um tempo, pois hรก clientes usando-o, mas quer que a documentaรงรฃo mostre claramente que ele estรก descontinuado. Entรฃo passe o parรขmetro `deprecated=True` para `Query`: @@ -390,9 +366,9 @@ Para excluir um parรขmetro de consulta do OpenAPI gerado (e portanto, dos sistem ## Validaรงรฃo personalizada { #custom-validation } -Podem existir casos em que vocรช precise fazer alguma **validaรงรฃo personalizada** que nรฃo pode ser feita com os parรขmetros mostrados acima. +Podem existir casos em que vocรช precise fazer alguma validaรงรฃo personalizada que nรฃo pode ser feita com os parรขmetros mostrados acima. -Nesses casos, vocรช pode usar uma **funรงรฃo validadora personalizada** que รฉ aplicada apรณs a validaรงรฃo normal (por exemplo, depois de validar que o valor รฉ uma `str`). +Nesses casos, vocรช pode usar uma funรงรฃo validadora personalizada que รฉ aplicada apรณs a validaรงรฃo normal (por exemplo, depois de validar que o valor รฉ uma `str`). Vocรช pode fazer isso usando o `AfterValidator` do Pydantic dentro de `Annotated`. @@ -402,7 +378,7 @@ O Pydantic tambรฉm tem ISBN ou com `imdb-` para um ID de URL de filme IMDB: +Por exemplo, este validador personalizado verifica se o ID do item comeรงa com `isbn-` para um nรบmero de livro ISBN ou com `imdb-` para um ID de URL de filme IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -414,15 +390,15 @@ Isso estรก disponรญvel com a versรฃo 2 do Pydantic ou superior. ๐Ÿ˜Ž /// tip | Dica -Se vocรช precisar fazer qualquer tipo de validaรงรฃo que exija comunicaรงรฃo com algum **componente externo**, como um banco de dados ou outra API, vocรช deveria usar **Dependรชncias do FastAPI** em vez disso; vocรช aprenderรก sobre elas mais adiante. +Se vocรช precisar fazer qualquer tipo de validaรงรฃo que exija comunicaรงรฃo com algum componente externo, como um banco de dados ou outra API, vocรช deveria usar Dependรชncias do FastAPI em vez disso; vocรช aprenderรก sobre elas mais adiante. -Esses validadores personalizados sรฃo para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisiรงรฃo. +Esses validadores personalizados sรฃo para coisas que podem ser verificadas apenas com os mesmos dados fornecidos na requisiรงรฃo. /// ### Entenda esse cรณdigo { #understand-that-code } -O ponto importante รฉ apenas usar **`AfterValidator` com uma funรงรฃo dentro de `Annotated`**. Sinta-se ร  vontade para pular esta parte. ๐Ÿคธ +O ponto importante รฉ apenas usar `AfterValidator` com uma funรงรฃo dentro de `Annotated`. Sinta-se ร  vontade para pular esta parte. ๐Ÿคธ --- @@ -436,17 +412,17 @@ Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verif #### Um item aleatรณrio { #a-random-item } -Com `data.items()` obtemos um objeto iterรกvel com tuplas contendo a chave e o valor de cada item do dicionรกrio. +Com `data.items()` obtemos um objeto iterรกvel com tuplas contendo a chave e o valor de cada item do dicionรกrio. Convertimos esse objeto iterรกvel em uma `list` adequada com `list(data.items())`. -Em seguida, com `random.choice()` podemos obter um **valor aleatรณrio** da lista, entรฃo obtemos uma tupla com `(id, name)`. Serรก algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +Em seguida, com `random.choice()` podemos obter um valor aleatรณrio da lista, entรฃo obtemos uma tupla com `(id, name)`. Serรก algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -Depois **atribuรญmos esses dois valores** da tupla ร s variรกveis `id` e `name`. +Depois atribuรญmos esses dois valores da tupla ร s variรกveis `id` e `name`. Assim, se o usuรกrio nรฃo fornecer um ID de item, ele ainda receberรก uma sugestรฃo aleatรณria. -...fazemos tudo isso em **uma รบnica linha simples**. ๐Ÿคฏ Vocรช nรฃo ama Python? ๐Ÿ +...fazemos tudo isso em uma รบnica linha simples. ๐Ÿคฏ Vocรช nรฃo ama Python? ๐Ÿ {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} diff --git a/docs/pt/docs/tutorial/query-params.md b/docs/pt/docs/tutorial/query-params.md index 8826602a25..f429885660 100644 --- a/docs/pt/docs/tutorial/query-params.md +++ b/docs/pt/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Quando vocรช declara outros parรขmetros na funรงรฃo que nรฃo fazem parte dos parรขmetros da rota, esses parรขmetros sรฃo automaticamente interpretados como parรขmetros de "consulta". -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} A consulta รฉ o conjunto de pares chave-valor que vai depois de `?` na URL, separado pelo caractere `&`. @@ -24,7 +24,7 @@ Mas quando vocรช declara eles com os tipos do Python (no exemplo acima, como `in Todo o processo que era aplicado para parรขmetros de rota tambรฉm รฉ aplicado para parรขmetros de consulta: * Suporte do editor (obviamente) -* "Parsing" de dados +* "anรกlise" de dados * Validaรงรฃo de dados * Documentaรงรฃo automรกtica @@ -127,7 +127,7 @@ Caso vocรช nรฃo queira adicionar um valor especรญfico mas queira apenas tornรก-l Porรฉm, quando vocรช quiser fazer com que o parรขmetro de consulta seja obrigatรณrio, vocรช pode simplesmente nรฃo declarar nenhum valor como padrรฃo. -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Aqui o parรขmetro de consulta `needy` รฉ um valor obrigatรณrio, do tipo `str`. diff --git a/docs/pt/docs/tutorial/request-files.md b/docs/pt/docs/tutorial/request-files.md index 5d0891163a..1364a1dd46 100644 --- a/docs/pt/docs/tutorial/request-files.md +++ b/docs/pt/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ Isso รฉ necessรกrio, visto que os arquivos enviados sรฃo enviados como "dados de Importe `File` e `UploadFile` de `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## Definir Parรขmetros `File` { #define-file-parameters } Crie parรขmetros de arquivo da mesma forma que vocรช faria para `Body` ou `Form`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | Informaรงรฃo @@ -54,7 +54,7 @@ Mas hรก muitos casos em que vocรช pode se beneficiar do uso de `UploadFile`. Defina um parรขmetro de arquivo com um tipo de `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} Utilizar `UploadFile` tem vรกrias vantagens sobre `bytes`: @@ -121,7 +121,7 @@ Dados de formulรกrios normalmente sรฃo codificados usando o "media type" `applic Mas quando o formulรกrio inclui arquivos, ele รฉ codificado como `multipart/form-data`. Se vocรช usar `File`, o **FastAPI** saberรก que tem que pegar os arquivos da parte correta do corpo da requisiรงรฃo. -Se vocรช quiser ler mais sobre essas codificaรงรตes e campos de formulรกrio, vรก para a MDN web docs para POST. +Se vocรช quiser ler mais sobre essas codificaรงรตes e campos de formulรกrio, vรก para a MDN web docs para POST. /// @@ -143,7 +143,7 @@ Vocรช pode tornar um arquivo opcional usando anotaรงรตes de tipo padrรฃo e defin Vocรช tambรฉm pode usar `File()` com `UploadFile`, por exemplo, para definir metadados adicionais: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## Uploads de Mรบltiplos Arquivos { #multiple-file-uploads } @@ -153,13 +153,13 @@ Eles serรฃo associados ao mesmo "campo de formulรกrio" enviado usando "dados de Para usar isso, declare uma lista de `bytes` ou `UploadFile`: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} Vocรช receberรก, tal como declarado, uma `list` de `bytes` ou `UploadFile`. /// note | Detalhes Tรฉcnicos -Vocรช pode tambรฉm pode usar `from starlette.responses import HTMLResponse`. +Vocรช tambรฉm pode usar `from starlette.responses import HTMLResponse`. **FastAPI** providencia o mesmo `starlette.responses` que `fastapi.responses` apenas como uma conveniรชncia para vocรช, o desenvolvedor. Mas a maioria das respostas disponรญveis vem diretamente do Starlette. @@ -169,7 +169,7 @@ Vocรช pode tambรฉm pode usar `from starlette.responses import HTMLResponse`. Da mesma forma de antes, vocรช pode usar `File()` para definir parรขmetros adicionais, mesmo para `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## Recapitulando { #recap } diff --git a/docs/pt/docs/tutorial/request-form-models.md b/docs/pt/docs/tutorial/request-form-models.md index 8eeffac2ad..38f160aa83 100644 --- a/docs/pt/docs/tutorial/request-form-models.md +++ b/docs/pt/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ Isto รฉ suportado desde a versรฃo `0.113.0` do FastAPI. ๐Ÿค“ Vocรช precisa apenas declarar um **modelo Pydantic** com os campos que deseja receber como **campos de formulรกrios**, e entรฃo declarar o parรขmetro como um `Form`: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} O **FastAPI** irรก **extrair** as informaรงรตes para **cada campo** dos **dados do formulรกrio** na requisiรงรฃo e dar para vocรช o modelo Pydantic que vocรช definiu. @@ -42,13 +42,13 @@ Em alguns casos de uso especiais (provavelmente nรฃo muito comum), vocรช pode de /// note | Nota -Isso รฉ suportado deste a versรฃo `0.114.0` do FastAPI. ๐Ÿค“ +Isso รฉ suportado desde a versรฃo `0.114.0` do FastAPI. ๐Ÿค“ /// Vocรช pode utilizar a configuraรงรฃo de modelo do Pydantic para `proibir` qualquer campo `extra`: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} Caso um cliente tente enviar informaรงรตes adicionais, ele receberรก um retorno de **erro**. diff --git a/docs/pt/docs/tutorial/request-forms-and-files.md b/docs/pt/docs/tutorial/request-forms-and-files.md index 277fc2f600..8b5f034e9e 100644 --- a/docs/pt/docs/tutorial/request-forms-and-files.md +++ b/docs/pt/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## Importe `File` e `Form` { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## Defina parรขmetros de `File` e `Form` { #define-file-and-form-parameters } Crie parรขmetros de arquivo e formulรกrio da mesma forma que vocรช faria para `Body` ou `Query`: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} Os arquivos e campos de formulรกrio serรฃo carregados como dados de formulรกrio e vocรช receberรก os arquivos e campos de formulรกrio. @@ -30,7 +30,7 @@ E vocรช pode declarar alguns dos arquivos como `bytes` e alguns como `UploadFile /// warning | Atenรงรฃo -Vocรช pode declarar vรกrios parรขmetros `File` e `Form` em uma *operaรงรฃo de caminho*, mas nรฃo รฉ possรญvel declarar campos `Body` para receber como JSON, pois a requisiรงรฃo terรก o corpo codificado usando `multipart/form-data` ao invรฉs de `application/json`. +Vocรช pode declarar vรกrios parรขmetros `File` e `Form` em uma *operaรงรฃo de rota*, mas nรฃo รฉ possรญvel declarar campos `Body` para receber como JSON, pois a requisiรงรฃo terรก o corpo codificado usando `multipart/form-data` ao invรฉs de `application/json`. Isso nรฃo รฉ uma limitaรงรฃo do **FastAPI**, รฉ parte do protocolo HTTP. @@ -38,4 +38,4 @@ Isso nรฃo รฉ uma limitaรงรฃo do **FastAPI**, รฉ parte do protocolo HTTP. ## Recapitulando { #recap } -Usar `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisiรงรฃo. +Use `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisiรงรฃo. diff --git a/docs/pt/docs/tutorial/request-forms.md b/docs/pt/docs/tutorial/request-forms.md index faa50bcbfe..d255d0f9be 100644 --- a/docs/pt/docs/tutorial/request-forms.md +++ b/docs/pt/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart Importe `Form` de `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## Defina parรขmetros de `Form` { #define-form-parameters } Crie parรขmetros de formulรกrio da mesma forma que vocรช faria para `Body` ou `Query`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} Por exemplo, em uma das maneiras que a especificaรงรฃo OAuth2 pode ser usada (chamada "fluxo de senha"), รฉ necessรกrio enviar um `username` e uma `password` como campos do formulรกrio. -A spec exige que os campos sejam exatamente nomeados como `username` e `password` e sejam enviados como campos de formulรกrio, nรฃo JSON. +A especificaรงรฃo exige que os campos sejam exatamente nomeados como `username` e `password` e sejam enviados como campos de formulรกrio, nรฃo JSON. Com `Form` vocรช pode declarar as mesmas configuraรงรตes que com `Body` (e `Query`, `Path`, `Cookie`), incluindo validaรงรฃo, exemplos, um alias (por exemplo, `user-name` em vez de `username`), etc. diff --git a/docs/pt/docs/tutorial/response-model.md b/docs/pt/docs/tutorial/response-model.md index 8a7a712488..e3b97b630f 100644 --- a/docs/pt/docs/tutorial/response-model.md +++ b/docs/pt/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ Pode haver casos em que vocรช retorna algo que nรฃo รฉ um campo Pydantic vรกlido O caso mais comum seria [retornar uma Response diretamente, conforme explicado posteriormente na documentaรงรฃo avanรงada](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} Este caso simples รฉ tratado automaticamente pelo FastAPI porque a anotaรงรฃo do tipo de retorno รฉ a classe (ou uma subclasse de) `Response`. @@ -193,7 +193,7 @@ E as ferramentas tambรฉm ficarรฃo felizes porque `RedirectResponse` e โ€‹โ€‹`JSO Vocรช tambรฉm pode usar uma subclasse de `Response` na anotaรงรฃo de tipo: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} Isso tambรฉm funcionarรก porque `RedirectResponse` รฉ uma subclasse de `Response`, e o FastAPI tratarรก automaticamente este caso simples. @@ -201,7 +201,7 @@ Isso tambรฉm funcionarรก porque `RedirectResponse` รฉ uma subclasse de `Response Mas quando vocรช retorna algum outro objeto arbitrรกrio que nรฃo รฉ um tipo Pydantic vรกlido (por exemplo, um objeto de banco de dados) e vocรช o anota dessa forma na funรงรฃo, o FastAPI tentarรก criar um modelo de resposta Pydantic a partir dessa anotaรงรฃo de tipo e falharรก. -O mesmo aconteceria se vocรช tivesse algo como uma uniรฃo entre tipos diferentes onde um ou mais deles nรฃo sรฃo tipos Pydantic vรกlidos, por exemplo, isso falharia ๐Ÿ’ฅ: +O mesmo aconteceria se vocรช tivesse algo como uma uniรฃo entre tipos diferentes onde um ou mais deles nรฃo sรฃo tipos Pydantic vรกlidos, por exemplo, isso falharia ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} @@ -290,7 +290,7 @@ Se os dados tiverem os mesmos valores que os padrรตes, como o item com ID `baz`: } ``` -O FastAPI รฉ inteligente o suficiente (na verdade, o Pydantic รฉ inteligente o suficiente) para perceber que, embora `description`, `tax` e `tags` tenham os mesmos valores que os padrรตes, eles foram definidos explicitamente (em vez de retirados dos padrรตes). +O FastAPI รฉ inteligente o suficiente (na verdade, o Pydantic รฉ inteligente o suficiente) para perceber que, embora `description`, `tax` e `tags` tenham os mesmos valores que os padrรตes, eles foram definidos explรญcita e diretamente (em vez de retirados dos padrรตes). Portanto, eles serรฃo incluรญdos na resposta JSON. diff --git a/docs/pt/docs/tutorial/response-status-code.md b/docs/pt/docs/tutorial/response-status-code.md index 756c86dada..a3f8d8a568 100644 --- a/docs/pt/docs/tutorial/response-status-code.md +++ b/docs/pt/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ Da mesma forma que vocรช pode especificar um modelo de resposta, vocรช tambรฉm p * `@app.delete()` * etc. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | Nota @@ -66,7 +66,7 @@ Resumidamente: /// tip | Dica -Para saber mais sobre cada cรณdigo de status e qual cรณdigo serve para quรช, verifique a documentaรงรฃo do MDN sobre cรณdigos de status HTTP. +Para saber mais sobre cada cรณdigo de status e qual cรณdigo serve para quรช, verifique a documentaรงรฃo do MDN sobre cรณdigos de status HTTP. /// @@ -74,7 +74,7 @@ Para saber mais sobre cada cรณdigo de status e qual cรณdigo serve para quรช, ver Vamos ver o exemplo anterior novamente: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` รฉ o cรณdigo de status para "Criado". @@ -82,7 +82,7 @@ Mas vocรช nรฃo precisa memorizar o que cada um desses cรณdigos significa. Vocรช pode usar as variรกveis de conveniรชncia de `fastapi.status`. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} Eles sรฃo apenas uma conveniรชncia, eles possuem o mesmo nรบmero, mas dessa forma vocรช pode usar o preenchimento automรกtico do editor para encontrรก-los: diff --git a/docs/pt/docs/tutorial/schema-extra-example.md b/docs/pt/docs/tutorial/schema-extra-example.md index 2d62ffd851..560fda908e 100644 --- a/docs/pt/docs/tutorial/schema-extra-example.md +++ b/docs/pt/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Vocรช tambรฉm pode, รฉ claro, passar vรกrios `examples`: Quando fizer isso, os exemplos farรฃo parte do **JSON Schema** interno para esses dados do body. -No entanto, no momento em que isto foi escrito, o Swagger UI, a ferramenta responsรกvel por exibir a UI da documentaรงรฃo, nรฃo suporta mostrar vรกrios exemplos para os dados no **JSON Schema**. Mas leia abaixo para uma soluรงรฃo alternativa. +No entanto, no momento em que isto foi escrito, o Swagger UI, a ferramenta responsรกvel por exibir a UI da documentaรงรฃo, nรฃo suporta mostrar vรกrios exemplos para os dados no **JSON Schema**. Mas leia abaixo para uma soluรงรฃo alternativa. ### `examples` especรญficos do OpenAPI { #openapi-specific-examples } diff --git a/docs/pt/docs/tutorial/security/first-steps.md b/docs/pt/docs/tutorial/security/first-steps.md index 715a21b6ef..f0edd57533 100644 --- a/docs/pt/docs/tutorial/security/first-steps.md +++ b/docs/pt/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ Vamos primeiro usar o cรณdigo e ver como funciona, e depois voltaremos para ente Copie o exemplo em um arquivo `main.py`: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## Execute-o { #run-it } @@ -132,7 +132,7 @@ Nesse caso, o **FastAPI** tambรฉm fornece as ferramentas para construรญ-la. Quando criamos uma instรขncia da classe `OAuth2PasswordBearer`, passamos o parรขmetro `tokenUrl`. Esse parรขmetro contรฉm a URL que o client (o frontend rodando no navegador do usuรกrio) usarรก para enviar o `username` e o `password` para obter um token. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | Dica @@ -156,7 +156,7 @@ Isso ocorre porque ele usa o mesmo nome da especificaรงรฃo do OpenAPI. Assim, se /// -A variรกvel `oauth2_scheme` รฉ uma instรขncia de `OAuth2PasswordBearer`, mas tambรฉm รฉ "chamรกvel" (callable). +A variรกvel `oauth2_scheme` รฉ uma instรขncia de `OAuth2PasswordBearer`, mas tambรฉm รฉ um "callable". Ela pode ser chamada como: @@ -170,7 +170,7 @@ Entรฃo, pode ser usada com `Depends`. Agora vocรช pode passar esse `oauth2_scheme` em uma dependรชncia com `Depends`. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Essa dependรชncia fornecerรก uma `str` que รฉ atribuรญda ao parรขmetro `token` da funรงรฃo de operaรงรฃo de rota. diff --git a/docs/pt/docs/tutorial/security/get-current-user.md b/docs/pt/docs/tutorial/security/get-current-user.md index 2135ae236d..4c6397c31f 100644 --- a/docs/pt/docs/tutorial/security/get-current-user.md +++ b/docs/pt/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ No capรญtulo anterior, o sistema de seguranรงa (que รฉ baseado no sistema de injeรงรฃo de dependรชncias) estava fornecendo ร  *funรงรฃo de operaรงรฃo de rota* um `token` como uma `str`: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Mas isso ainda nรฃo รฉ tรฃo รบtil. diff --git a/docs/pt/docs/tutorial/security/index.md b/docs/pt/docs/tutorial/security/index.md index d3de3e0509..f4c92ea567 100644 --- a/docs/pt/docs/tutorial/security/index.md +++ b/docs/pt/docs/tutorial/security/index.md @@ -88,7 +88,6 @@ OpenAPI define os seguintes esquemas de seguranรงa: * `openIdConnect`: tem uma forma para definir como descobrir automaticamente o dado da autenticaรงรฃo OAuth2. * Essa descoberta automรกtica รฉ o que รฉ definido na especificaรงรฃo OpenID Connect. - /// tip | Dica Integraรงรฃo com outros provedores de autenticaรงรฃo/autorizaรงรฃo como Google, Facebook, X (Twitter), GitHub, etc. รฉ bem possรญvel e relativamente fรกcil. @@ -99,7 +98,7 @@ O problema mais complexo รฉ criar um provedor de autenticaรงรฃo/autorizaรงรฃo co ## **FastAPI** utilitรกrios { #fastapi-utilities } -**FastAPI** fornece vรกrias ferramentas para cada um desses esquemas de seguranรงa no mรณdulo `fastapi.security` que simplesmente usa esses mecanismos de seguranรงa. +**FastAPI** fornece vรกrias ferramentas para cada um desses esquemas de seguranรงa no mรณdulo `fastapi.security` que simplificam o uso desses mecanismos de seguranรงa. Nos prรณximos capรญtulos vocรช irรก ver como adicionar seguranรงa ร  sua API usando essas ferramentas disponibilizadas pelo **FastAPI**. diff --git a/docs/pt/docs/tutorial/security/oauth2-jwt.md b/docs/pt/docs/tutorial/security/oauth2-jwt.md index f68b8c39ea..4ba38b9f04 100644 --- a/docs/pt/docs/tutorial/security/oauth2-jwt.md +++ b/docs/pt/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ E outra funรงรฃo utilitรกria para verificar se uma senha recebida corresponde ao E outra para autenticar e retornar um usuรกrio. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Quando `authenticate_user` รฉ chamado com um nome de usuรกrio que nรฃo existe no banco de dados, ainda executamos `verify_password` contra um hash fictรญcio. + +Isso garante que o endpoint leve aproximadamente o mesmo tempo para responder, seja o nome de usuรกrio vรกlido ou nรฃo, prevenindo **timing attacks** que poderiam ser usados para enumerar nomes de usuรกrio existentes. /// note | Nota @@ -152,7 +156,7 @@ Defina um modelo Pydantic que serรก usado no endpoint de token para a resposta. Crie uma funรงรฃo utilitรกria para gerar um novo token de acesso. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## Atualize as dependรชncias { #update-the-dependencies } @@ -162,7 +166,7 @@ Decodifique o token recebido, verifique-o e retorne o usuรกrio atual. Se o token for invรกlido, retorne um erro HTTP imediatamente. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## Atualize a *operaรงรฃo de rota* `/token` { #update-the-token-path-operation } @@ -170,7 +174,7 @@ Crie um `timedelta` com o tempo de expiraรงรฃo do token. Crie um token de acesso JWT real e o retorne. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### Detalhes tรฉcnicos sobre o "sujeito" `sub` do JWT { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/pt/docs/tutorial/static-files.md b/docs/pt/docs/tutorial/static-files.md index 04a02c7f96..0b2d0718f2 100644 --- a/docs/pt/docs/tutorial/static-files.md +++ b/docs/pt/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ Vocรช pode servir arquivos estรกticos automaticamente a partir de um diretรณrio * Importe `StaticFiles`. * "Monte" uma instรขncia de `StaticFiles()` em um path especรญfico. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | Detalhes Tรฉcnicos diff --git a/docs/pt/docs/tutorial/testing.md b/docs/pt/docs/tutorial/testing.md index e56edcb8c2..44dc2d2257 100644 --- a/docs/pt/docs/tutorial/testing.md +++ b/docs/pt/docs/tutorial/testing.md @@ -30,7 +30,7 @@ Use o objeto `TestClient` da mesma forma que vocรช faz com `httpx`. Escreva instruรงรตes `assert` simples com as expressรตes Python padrรฃo que vocรช precisa verificar (novamente, `pytest` padrรฃo). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | Dica @@ -76,7 +76,7 @@ Digamos que vocรช tenha uma estrutura de arquivo conforme descrito em [Aplicaรง No arquivo `main.py` vocรช tem sua aplicaรงรฃo **FastAPI**: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### Arquivo de teste { #testing-file } @@ -92,7 +92,7 @@ Entรฃo vocรช poderia ter um arquivo `test_main.py` com seus testes. Ele poderia Como esse arquivo estรก no mesmo pacote, vocรช pode usar importaรงรตes relativas para importar o objeto `app` do mรณdulo `main` (`main.py`): -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...e ter o cรณdigo para os testes como antes. diff --git a/docs/pt/docs/virtual-environments.md b/docs/pt/docs/virtual-environments.md index 5736f71095..e222c61ad6 100644 --- a/docs/pt/docs/virtual-environments.md +++ b/docs/pt/docs/virtual-environments.md @@ -1,6 +1,6 @@ # Ambientes Virtuais { #virtual-environments } -Ao trabalhar em projetos Python, vocรช provavelmente deve usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que vocรช instala para cada projeto. +Ao trabalhar em projetos Python, vocรช provavelmente deveria usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que vocรช instala para cada projeto. /// info | Informaรงรฃo @@ -53,7 +53,7 @@ $ cd awesome-project ## Crie um ambiente virtual { #create-a-virtual-environment } -Ao comeรงar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **dentro do seu projeto**. +Ao comeรงar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **dentro do seu projeto**. /// tip | Dica @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate Toda vez que vocรช instalar um **novo pacote** naquele ambiente, **ative** o ambiente novamente. -Isso garante que, se vocรช usar um **programa de terminal (CLI)** instalado por esse pacote, vocรช usarรก aquele do seu ambiente virtual e nรฃo qualquer outro que possa ser instalado globalmente, provavelmente com uma versรฃo diferente do que vocรช precisa. +Isso garante que, se vocรช usar um **programa de terminal (CLI)** instalado por esse pacote, vocรช usarรก aquele do seu ambiente virtual e nรฃo qualquer outro que possa ser instalado globalmente, provavelmente com uma versรฃo diferente do que vocรช precisa. /// @@ -176,7 +176,7 @@ Verifique se o ambiente virtual estรก ativo (o comando anterior funcionou). /// tip | Dica -Isso รฉ **opcional**, mas รฉ uma boa maneira de **verificar** se tudo estรก funcionando conforme o esperado e se vocรช estรก usando o ambiente virtual intendido. +Isso รฉ **opcional**, mas รฉ uma boa maneira de **verificar** se tudo estรก funcionando conforme o esperado e se vocรช estรก usando o ambiente virtual pretendido. /// @@ -220,7 +220,7 @@ Se vocรช usar From d213dd363d28fcc63ec61b5e206b5a7a71b3337f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 13:49:19 +0000 Subject: [PATCH 232/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index deee633c2f..152f684e73 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for uk (update-all). PR [#14914](https://github.com/fastapi/fastapi/pull/14914) by [@YuriiMotov](https://github.com/YuriiMotov). From 5ad9d258e4f50e8830d0b08601a88e9eb6ae1aaf Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:24:30 +0100 Subject: [PATCH 233/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(update-all)=20(#14916)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format * Add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/ja/docs/_llm-test.md | 503 +++++++++++++++++ docs/ja/docs/about/index.md | 3 + docs/ja/docs/advanced/additional-responses.md | 247 +++++++++ .../docs/advanced/additional-status-codes.md | 4 +- .../ja/docs/advanced/advanced-dependencies.md | 163 ++++++ .../ja/docs/advanced/advanced-python-types.md | 61 +++ docs/ja/docs/advanced/async-tests.md | 99 ++++ docs/ja/docs/advanced/behind-a-proxy.md | 466 ++++++++++++++++ docs/ja/docs/advanced/custom-response.md | 32 +- docs/ja/docs/advanced/dataclasses.md | 95 ++++ docs/ja/docs/advanced/events.md | 165 ++++++ docs/ja/docs/advanced/generate-clients.md | 208 ++++++++ docs/ja/docs/advanced/middleware.md | 97 ++++ docs/ja/docs/advanced/openapi-callbacks.md | 186 +++++++ docs/ja/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 31 ++ docs/ja/docs/advanced/response-cookies.md | 51 ++ docs/ja/docs/advanced/response-directly.md | 2 +- docs/ja/docs/advanced/response-headers.md | 41 ++ .../docs/advanced/security/http-basic-auth.md | 107 ++++ docs/ja/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++++++ docs/ja/docs/advanced/settings.md | 302 +++++++++++ docs/ja/docs/advanced/sub-applications.md | 67 +++ docs/ja/docs/advanced/templates.md | 126 +++++ docs/ja/docs/advanced/testing-dependencies.md | 53 ++ docs/ja/docs/advanced/testing-events.md | 11 + docs/ja/docs/advanced/testing-websockets.md | 13 + .../docs/advanced/using-request-directly.md | 56 ++ docs/ja/docs/advanced/websockets.md | 8 +- docs/ja/docs/advanced/wsgi.md | 51 ++ docs/ja/docs/alternatives.md | 73 ++- docs/ja/docs/async.md | 379 +++++++------ docs/ja/docs/deployment/cloud.md | 24 + docs/ja/docs/deployment/concepts.md | 2 - docs/ja/docs/deployment/docker.md | 10 +- docs/ja/docs/deployment/fastapicloud.md | 65 +++ docs/ja/docs/deployment/https.md | 4 +- docs/ja/docs/deployment/manually.md | 138 +++-- docs/ja/docs/environment-variables.md | 4 +- docs/ja/docs/fastapi-cli.md | 75 +++ docs/ja/docs/features.md | 207 ++++--- docs/ja/docs/help-fastapi.md | 264 +++++++-- docs/ja/docs/history-design-future.md | 21 +- .../authentication-error-status-code.md | 17 + docs/ja/docs/how-to/conditional-openapi.md | 4 +- docs/ja/docs/how-to/configure-swagger-ui.md | 70 +++ docs/ja/docs/how-to/custom-docs-ui-assets.md | 185 +++++++ .../docs/how-to/custom-request-and-route.md | 109 ++++ docs/ja/docs/how-to/extending-openapi.md | 80 +++ docs/ja/docs/how-to/general.md | 39 ++ docs/ja/docs/how-to/graphql.md | 60 +++ docs/ja/docs/how-to/index.md | 13 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 +++++ .../docs/how-to/separate-openapi-schemas.md | 102 ++++ docs/ja/docs/how-to/testing-database.md | 7 + docs/ja/docs/index.md | 12 +- docs/ja/docs/python-types.md | 286 +++------- docs/ja/docs/resources/index.md | 3 + docs/ja/docs/translation-banner.md | 11 + docs/ja/docs/tutorial/background-tasks.md | 6 +- docs/ja/docs/tutorial/bigger-applications.md | 504 ++++++++++++++++++ docs/ja/docs/tutorial/body-multiple-params.md | 6 - docs/ja/docs/tutorial/body-nested-models.md | 4 +- docs/ja/docs/tutorial/body-updates.md | 2 +- docs/ja/docs/tutorial/body.md | 4 +- docs/ja/docs/tutorial/cookie-param-models.md | 8 +- docs/ja/docs/tutorial/cors.md | 2 +- docs/ja/docs/tutorial/debugging.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +- ...pendencies-in-path-operation-decorators.md | 8 +- .../dependencies/dependencies-with-yield.md | 24 +- .../dependencies/global-dependencies.md | 15 + docs/ja/docs/tutorial/dependencies/index.md | 2 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/ja/docs/tutorial/extra-models.md | 28 +- docs/ja/docs/tutorial/first-steps.md | 18 +- docs/ja/docs/tutorial/handling-errors.md | 16 +- docs/ja/docs/tutorial/header-param-models.md | 72 +++ docs/ja/docs/tutorial/metadata.md | 12 +- docs/ja/docs/tutorial/middleware.md | 6 +- .../tutorial/path-operation-configuration.md | 8 +- .../path-params-numeric-validations.md | 16 +- docs/ja/docs/tutorial/path-params.md | 28 +- .../tutorial/query-params-str-validations.md | 42 +- docs/ja/docs/tutorial/query-params.md | 6 +- docs/ja/docs/tutorial/request-files.md | 176 ++++++ docs/ja/docs/tutorial/request-form-models.md | 78 +++ .../docs/tutorial/request-forms-and-files.md | 4 +- docs/ja/docs/tutorial/request-forms.md | 10 +- docs/ja/docs/tutorial/response-model.md | 8 +- docs/ja/docs/tutorial/response-status-code.md | 6 +- docs/ja/docs/tutorial/schema-extra-example.md | 2 +- docs/ja/docs/tutorial/security/first-steps.md | 8 +- .../tutorial/security/get-current-user.md | 2 +- docs/ja/docs/tutorial/security/index.md | 16 +- docs/ja/docs/tutorial/security/oauth2-jwt.md | 14 +- .../docs/tutorial/security/simple-oauth2.md | 289 ++++++++++ docs/ja/docs/tutorial/sql-databases.md | 357 +++++++++++++ docs/ja/docs/tutorial/static-files.md | 2 +- docs/ja/docs/tutorial/testing.md | 6 +- docs/ja/docs/virtual-environments.md | 4 +- 103 files changed, 7009 insertions(+), 853 deletions(-) create mode 100644 docs/ja/docs/_llm-test.md create mode 100644 docs/ja/docs/about/index.md create mode 100644 docs/ja/docs/advanced/additional-responses.md create mode 100644 docs/ja/docs/advanced/advanced-dependencies.md create mode 100644 docs/ja/docs/advanced/advanced-python-types.md create mode 100644 docs/ja/docs/advanced/async-tests.md create mode 100644 docs/ja/docs/advanced/behind-a-proxy.md create mode 100644 docs/ja/docs/advanced/dataclasses.md create mode 100644 docs/ja/docs/advanced/events.md create mode 100644 docs/ja/docs/advanced/generate-clients.md create mode 100644 docs/ja/docs/advanced/middleware.md create mode 100644 docs/ja/docs/advanced/openapi-callbacks.md create mode 100644 docs/ja/docs/advanced/openapi-webhooks.md create mode 100644 docs/ja/docs/advanced/response-change-status-code.md create mode 100644 docs/ja/docs/advanced/response-cookies.md create mode 100644 docs/ja/docs/advanced/response-headers.md create mode 100644 docs/ja/docs/advanced/security/http-basic-auth.md create mode 100644 docs/ja/docs/advanced/security/index.md create mode 100644 docs/ja/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/ja/docs/advanced/settings.md create mode 100644 docs/ja/docs/advanced/sub-applications.md create mode 100644 docs/ja/docs/advanced/templates.md create mode 100644 docs/ja/docs/advanced/testing-dependencies.md create mode 100644 docs/ja/docs/advanced/testing-events.md create mode 100644 docs/ja/docs/advanced/testing-websockets.md create mode 100644 docs/ja/docs/advanced/using-request-directly.md create mode 100644 docs/ja/docs/advanced/wsgi.md create mode 100644 docs/ja/docs/deployment/cloud.md create mode 100644 docs/ja/docs/deployment/fastapicloud.md create mode 100644 docs/ja/docs/fastapi-cli.md create mode 100644 docs/ja/docs/how-to/authentication-error-status-code.md create mode 100644 docs/ja/docs/how-to/configure-swagger-ui.md create mode 100644 docs/ja/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/ja/docs/how-to/custom-request-and-route.md create mode 100644 docs/ja/docs/how-to/extending-openapi.md create mode 100644 docs/ja/docs/how-to/general.md create mode 100644 docs/ja/docs/how-to/graphql.md create mode 100644 docs/ja/docs/how-to/index.md create mode 100644 docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/ja/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/ja/docs/how-to/testing-database.md create mode 100644 docs/ja/docs/resources/index.md create mode 100644 docs/ja/docs/translation-banner.md create mode 100644 docs/ja/docs/tutorial/bigger-applications.md create mode 100644 docs/ja/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/ja/docs/tutorial/header-param-models.md create mode 100644 docs/ja/docs/tutorial/request-files.md create mode 100644 docs/ja/docs/tutorial/request-form-models.md create mode 100644 docs/ja/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/ja/docs/tutorial/sql-databases.md diff --git a/docs/ja/docs/_llm-test.md b/docs/ja/docs/_llm-test.md new file mode 100644 index 0000000000..b3d9fc28cd --- /dev/null +++ b/docs/ja/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM ใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ { #llm-test-file } + +ใ“ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ฟป่จณใ™ใ‚‹ LLM ใŒใ€`scripts/translate.py` ใฎ `general_prompt` ใจใ€`docs/{language code}/llm-prompt.md` ใฎ่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใ‚’็†่งฃใ—ใฆใ„ใ‚‹ใ‹ใ‚’ใƒ†ใ‚นใƒˆใ—ใพใ™ใ€‚่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใฏ `general_prompt` ใฎๆœซๅฐพใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ“ใซ่ฟฝๅŠ ใ—ใŸใƒ†ใ‚นใƒˆใฏใ€ใ™ในใฆใฎ่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใฎ่จญ่จˆ่€…ใŒๅ‚็…งใ—ใพใ™ใ€‚ + +ไฝฟใ„ๆ–น: + +* ่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใ‚’็”จๆ„ใ—ใพใ™ - `docs/{language code}/llm-prompt.md`ใ€‚ +* ใ“ใฎๆ–‡ๆ›ธใ‚’ๅธŒๆœ›ใ™ใ‚‹ใ‚ฟใƒผใ‚ฒใƒƒใƒˆ่จ€่ชžใซๆ–ฐ่ฆใง็ฟป่จณใ—ใพใ™๏ผˆไพ‹: `translate.py` ใฎ `translate-page` ใ‚ณใƒžใƒณใƒ‰๏ผ‰ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Š `docs/{language code}/docs/_llm-test.md` ใซ็ฟป่จณใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ +* ็ฟป่จณใŒๅ•้กŒใชใ„ใ‹็ขบ่ชใ—ใพใ™ใ€‚ +* ๅฟ…่ฆใงใ‚ใ‚Œใฐใ€่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใ€general ใƒ—ใƒญใƒณใƒ—ใƒˆใ€ใพใŸใฏ่‹ฑ่ชžใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๆ”นๅ–„ใ—ใพใ™ใ€‚ +* ใใฎๅพŒใ€็ฟป่จณใซๆฎ‹ใฃใฆใ„ใ‚‹ๅ•้กŒใ‚’ๆ‰‹ๅ‹•ใงไฟฎๆญฃใ—ใ€่‰ฏใ„็ฟป่จณใซใ—ใพใ™ใ€‚ +* ่‰ฏใ„็ฟป่จณใ‚’็”จๆ„ใ—ใŸ็Šถๆ…‹ใงใ‚‚ใ†ไธ€ๅบฆ็ฟป่จณใ—ใพใ™ใ€‚็†ๆƒณ็š„ใช็ตๆžœใฏใ€LLM ใŒ็ฟป่จณใซไธ€ๅˆ‡ๅค‰ๆ›ดใ‚’ๅŠ ใˆใชใ„ใ“ใจใงใ™ใ€‚ใคใพใ‚Š general ใƒ—ใƒญใƒณใƒ—ใƒˆใจ่จ€่ชžๅ›บๆœ‰ใƒ—ใƒญใƒณใƒ—ใƒˆใŒๆœ€่‰ฏใงใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™๏ผˆๆ™‚ใ€…ใ„ใใคใ‹ใƒฉใƒณใƒ€ใƒ ใซ่ฆ‹ใˆใ‚‹ๅค‰ๆ›ดใ‚’่กŒใ†ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚็†็”ฑใฏ LLM ใฏๆฑบๅฎš่ซ–็š„ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใงใฏใชใ„ ใŸใ‚ใงใ™๏ผ‰ใ€‚ + +ใƒ†ใ‚นใƒˆๅ†…ๅฎน: + +## ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆ { #code-snippets } + +//// tab | ใƒ†ใ‚นใƒˆ + +ใ“ใ‚Œใฏใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆใงใ™: `foo`ใ€‚ใใ—ใฆใ“ใ‚Œใ‚‚ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆใงใ™: `bar`ใ€‚ใ•ใ‚‰ใซใ‚‚ใ†ไธ€ใค: `baz quux`ใ€‚ + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆใฎๅ†…ๅฎนใฏใใฎใพใพใซใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### Content of code snippetsใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## ๅผ•็”จ { #quotes } + +//// tab | ใƒ†ใ‚นใƒˆ + +ๆ˜จๆ—ฅใ€ๅ‹ไบบใฏใ“ใ†ๆ›ธใใพใ—ใŸใ€‚ใ€Œincorrectly ใ‚’ๆญฃใ—ใ็ถดใ‚Œใฐใ€ใ‚ใชใŸใฏใใ‚Œใ‚’้–“้•ใฃใฆ็ถดใฃใŸใ“ใจใซใชใ‚‹ใ€ใ€‚ใใ‚Œใซๅฏพใ—ใฆ็งใฏใ“ใ†็ญ”ใˆใพใ—ใŸใ€‚ใ€ŒใใฎใจใŠใ‚Šใ€‚ใŸใ ใ—ใ€Žincorrectlyใ€ใฏ่ชคใ‚Šใงใ€ใ€Ž"incorrectly"ใ€ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€ใ€‚ + +/// note | ๅ‚™่€ƒ + +LLM ใฏใŠใใ‚‰ใใ“ใ“ใ‚’่ชคใฃใฆ็ฟป่จณใ—ใพใ™ใ€‚้‡่ฆใชใฎใฏใ€ๅ†็ฟป่จณๆ™‚ใซไฟฎๆญฃๆธˆใฟใฎ็ฟป่จณใ‚’็ถญๆŒใงใใ‚‹ใ‹ใฉใ†ใ‹ใ ใ‘ใงใ™ใ€‚ + +/// + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใƒ—ใƒญใƒณใƒ—ใƒˆ่จญ่จˆ่€…ใฏใ€ใ‚นใƒˆใƒฌใƒผใƒˆใ‚ฏใ‚ฉใƒผใƒˆใ‚’ใ‚ฟใ‚คใƒใ‚ฐใƒฉใƒ•ใ‚ฃใƒƒใ‚ฏใชๅผ•็”จ็ฌฆใซๅค‰ๆ›ใ™ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’้ธในใพใ™ใ€‚ใใฎใพใพใงใ‚‚ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ไพ‹ใจใ—ใฆ `docs/de/llm-prompt.md` ใฎใ€Œ### Quotesใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆๅ†…ใฎๅผ•็”จ { #quotes-in-code-snippets } + +//// tab | ใƒ†ใ‚นใƒˆ + +`pip install "foo[bar]"` + +ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆไธญใฎๆ–‡ๅญ—ๅˆ—ใƒชใƒ†ใƒฉใƒซใฎไพ‹: `"this"`, `'that'`. + +้›ฃใ—ใ„ๆ–‡ๅญ—ๅˆ—ใƒชใƒ†ใƒฉใƒซใฎไพ‹: `f"I like {'oranges' if orange else "apples"}"` + +ใƒใƒผใƒ‰ใ‚ณใ‚ข: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | ๆƒ…ๅ ฑ + +... ใŸใ ใ—ใ€ใ‚ณใƒผใƒ‰ใ‚นใƒ‹ใƒšใƒƒใƒˆๅ†…ใฎๅผ•็”จ็ฌฆใฏใใฎใพใพใซใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +//// + +## ใ‚ณใƒผใƒ‰ใƒ–ใƒญใƒƒใ‚ฏ { #code-blocks } + +//// tab | ใƒ†ใ‚นใƒˆ + +Bash ใฎใ‚ณใƒผใƒ‰ไพ‹ใงใ™... + +```bash +# ๅฎ‡ๅฎ™ใซใ‚ใ„ใ•ใคใ‚’่กจ็คบ +echo "Hello universe" +``` + +...ใใ—ใฆใ‚ณใƒณใ‚ฝใƒผใƒซใฎใ‚ณใƒผใƒ‰ไพ‹ใงใ™... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...ใ•ใ‚‰ใซๅˆฅใฎใ‚ณใƒณใ‚ฝใƒผใƒซใฎใ‚ณใƒผใƒ‰ไพ‹ใงใ™... + +```console +// ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช "code" ใ‚’ไฝœๆˆ +$ mkdir code +// ใใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ็งปๅ‹• +$ cd code +``` + +...ใใ—ใฆ Python ใฎใ‚ณใƒผใƒ‰ไพ‹ใงใ™... + +```Python +wont_work() # ใ“ใ‚Œใฏๅ‹•ไฝœใ—ใพใ›ใ‚“ ๐Ÿ˜ฑ +works(foo="bar") # ใ“ใ‚Œใฏๅ‹•ไฝœใ—ใพใ™ ๐ŸŽ‰ +``` + +...ไปฅไธŠใงใ™ใ€‚ + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใ‚ณใƒผใƒ‰ใƒ–ใƒญใƒƒใ‚ฏๅ†…ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ณใƒกใƒณใƒˆใ‚’้™คใใ€ๅค‰ๆ›ดใ—ใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### Content of code blocksใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## ใ‚ฟใƒ–ใจ่‰ฒไป˜ใใƒœใƒƒใ‚ฏใ‚น { #tabs-and-colored-boxes } + +//// tab | ใƒ†ใ‚นใƒˆ + +/// info | ๆƒ…ๅ ฑ +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// note | ๅ‚™่€ƒ +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// note | ๆŠ€่ก“่ฉณ็ดฐ +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// check | ็ขบ่ช +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// tip | ่ฑ†็Ÿฅ่ญ˜ +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// warning | ๆณจๆ„ +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +/// danger | ่ญฆๅ‘Š +ใ„ใใคใ‹ใฎใƒ†ใ‚ญใ‚นใƒˆ +/// + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใ‚ฟใƒ–ใŠใ‚ˆใณ `Info`/`Note`/`Warning` ใชใฉใฎใƒ–ใƒญใƒƒใ‚ฏใซใฏใ€ใ‚ฟใ‚คใƒˆใƒซใฎ็ฟป่จณใ‚’็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใฎๅพŒใ‚ใซ่ฟฝๅŠ ใ—ใพใ™ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### Special blocksใ€ใจใ€Œ### Tab blocksใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## Web ใƒชใƒณใ‚ฏใจๅ†…้ƒจใƒชใƒณใ‚ฏ { #web-and-internal-links } + +//// tab | ใƒ†ใ‚นใƒˆ + +ใƒชใƒณใ‚ฏใฎใƒ†ใ‚ญใ‚นใƒˆใฏ็ฟป่จณใ—ใ€ใƒชใƒณใ‚ฏๅ…ˆใฎใ‚ขใƒ‰ใƒฌใ‚นใฏๅค‰ๆ›ดใ—ใชใ„ใงใใ ใ•ใ„: + +* [ไธŠใฎ่ฆ‹ๅ‡บใ—ใธใฎใƒชใƒณใ‚ฏ](#code-snippets) +* [ๅ†…้ƒจใƒชใƒณใ‚ฏ](index.md#installation){.internal-link target=_blank} +* ๅค–้ƒจใƒชใƒณใ‚ฏ +* ใ‚นใ‚ฟใ‚คใƒซใธใฎใƒชใƒณใ‚ฏ +* ใ‚นใ‚ฏใƒชใƒ—ใƒˆใธใฎใƒชใƒณใ‚ฏ +* ็”ปๅƒใธใฎใƒชใƒณใ‚ฏ + +ใƒชใƒณใ‚ฏใฎใƒ†ใ‚ญใ‚นใƒˆใฏ็ฟป่จณใ—ใ€ใƒชใƒณใ‚ฏๅ…ˆใฎใ‚ขใƒ‰ใƒฌใ‚นใฏ็ฟป่จณ็‰ˆใ‚’ๆŒ‡ใ™ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„: + +* FastAPI ใƒชใƒณใ‚ฏ + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใƒชใƒณใ‚ฏใฎใƒ†ใ‚ญใ‚นใƒˆใฏ็ฟป่จณใ—ใ€ใ‚ขใƒ‰ใƒฌใ‚นใฏๅค‰ๆ›ดใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ไพ‹ๅค–ใฏใ€FastAPI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒšใƒผใ‚ธใธใฎ็ตถๅฏพ URL ใงใ™ใ€‚ใใฎๅ ดๅˆใฏ็ฟป่จณ็‰ˆใธใฎใƒชใƒณใ‚ฏใซใ—ใพใ™ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### Linksใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## HTML "abbr" ่ฆ็ด  { #html-abbr-elements } + +//// tab | ใƒ†ใ‚นใƒˆ + +ใ“ใ“ใงใฏ HTML ใฎ "abbr" ่ฆ็ด ใงๅŒ…ใพใ‚ŒใŸใ‚‚ใฎใ‚’ใ„ใใคใ‹็คบใ—ใพใ™๏ผˆใ„ใใคใ‹ใฏๆžถ็ฉบใงใ™๏ผ‰: + +### abbr ใŒๅฎŒๅ…จใช่ชžๅฅใ‚’็คบใ™ { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr ใŒๅฎŒๅ…จใช่ชžๅฅใจ่ชฌๆ˜Žใ‚’็คบใ™ { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | ๆƒ…ๅ ฑ + +"abbr" ่ฆ็ด ใฎ "title" ๅฑžๆ€งใฏ็‰นๅฎšใฎๆŒ‡็คบใซๅพ“ใฃใฆ็ฟป่จณใ—ใพใ™ใ€‚ + +็ฟป่จณใฏใ€่‹ฑ่ชžใฎ่ชžใ‚’่ชฌๆ˜Žใ™ใ‚‹ใŸใ‚ใซ็‹ฌ่‡ชใฎ "abbr" ่ฆ็ด ใ‚’่ฟฝๅŠ ใ—ใฆใ‚‚ใ‚ˆใใ€LLM ใฏใใ‚Œใ‚‰ใ‚’ๅ‰Š้™คใ—ใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### HTML abbr elementsใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## HTML "dfn" ่ฆ็ด  { #html-dfn-elements } + +* ใ‚ฏใƒฉใ‚นใ‚ฟใƒผ +* ใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐ + +## ่ฆ‹ๅ‡บใ— { #headings } + +//// tab | ใƒ†ใ‚นใƒˆ + +### Web ใ‚ขใƒ—ใƒชใ‚’้–‹็™บใ™ใ‚‹ - ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ { #develop-a-webapp-a-tutorial } + +ใ“ใ‚“ใซใกใฏใ€‚ + +### ๅž‹ใƒ’ใƒณใƒˆใจใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ { #type-hints-and-annotations } + +ใพใŸใ“ใ‚“ใซใกใฏใ€‚ + +### ใ‚นใƒผใƒ‘ใƒผใ‚ฏใƒฉใ‚นใจใ‚ตใƒ–ใ‚ฏใƒฉใ‚น { #super-and-subclasses } + +ใพใŸใ“ใ‚“ใซใกใฏใ€‚ + +//// + +//// tab | ๆƒ…ๅ ฑ + +่ฆ‹ๅ‡บใ—ใซ้–ขใ™ใ‚‹ๅ”ฏไธ€ใฎๅŽณๆ ผใชใƒซใƒผใƒซใฏใ€ใƒชใƒณใ‚ฏใŒๅฃŠใ‚Œใชใ„ใ‚ˆใ†ใซใ€LLM ใŒไธญๆ‹ฌๅผงๅ†…ใฎใƒใƒƒใ‚ทใƒฅ้ƒจๅˆ†ใ‚’ๅค‰ๆ›ดใ—ใชใ„ใ“ใจใงใ™ใ€‚ + +`scripts/translate.py` ใฎ general ใƒ—ใƒญใƒณใƒ—ใƒˆๅ†…ใ€Œ### Headingsใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +่จ€่ชžๅ›บๆœ‰ใฎๆŒ‡็คบใซใคใ„ใฆใฏใ€ไพ‹ใจใ—ใฆ `docs/de/llm-prompt.md` ใฎใ€Œ### Headingsใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงไฝฟใ†็”จ่ชž { #terms-used-in-the-docs } + +//// tab | ใƒ†ใ‚นใƒˆ + +* you +* your + +* e.g. +* etc. + +* `foo` ใ‚’ `int` ใจใ—ใฆ +* `bar` ใ‚’ `str` ใจใ—ใฆ +* `baz` ใ‚’ `list` ใจใ—ใฆ + +* ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ +* ไธŠ็ดšใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰ +* SQLModel ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +* API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ +* ่‡ชๅ‹•็”Ÿๆˆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ + +* ใƒ‡ใƒผใ‚ฟใ‚ตใ‚คใ‚จใƒณใ‚น +* ใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐ +* ๆฉŸๆขฐๅญฆ็ฟ’ +* ไพๅญ˜ๆ€งๆณจๅ…ฅ +* HTTP Basic ่ช่จผ +* HTTP Digest +* ISO ๅฝขๅผ +* JSON Schema ่ฆๆ ผ +* JSON ใ‚นใ‚ญใƒผใƒž +* ใ‚นใ‚ญใƒผใƒžๅฎš็พฉ +* Password Flow +* ใƒขใƒใ‚คใƒซ + +* ้žๆŽจๅฅจ +* ่จญ่จˆใ•ใ‚ŒใŸ +* ็„กๅŠน +* ใ‚ชใƒณใ‚ถใƒ•ใƒฉใ‚ค +* ๆจ™ๆบ– +* ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ +* ๅคงๆ–‡ๅญ—ๅฐๆ–‡ๅญ—ใ‚’ๅŒบๅˆฅ +* ๅคงๆ–‡ๅญ—ๅฐๆ–‡ๅญ—ใ‚’ๅŒบๅˆฅใ—ใชใ„ + +* ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆไพ›ใ™ใ‚‹ +* ใƒšใƒผใ‚ธใ‚’้…ไฟกใ™ใ‚‹ + +* ใ‚ขใƒ—ใƒช +* ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ + +* ใƒชใ‚ฏใ‚จใ‚นใƒˆ +* ใƒฌใ‚นใƒใƒณใ‚น +* ใ‚จใƒฉใƒผใƒฌใ‚นใƒใƒณใ‚น + +* path operation +* path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ +* path operation ้–ขๆ•ฐ + +* ใƒœใƒ‡ใ‚ฃ +* ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃ +* ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃ +* JSON ใƒœใƒ‡ใ‚ฃ +* ใƒ•ใ‚ฉใƒผใƒ ใƒœใƒ‡ใ‚ฃ +* ใƒ•ใ‚กใ‚คใƒซใƒœใƒ‡ใ‚ฃ +* ้–ขๆ•ฐๆœฌไฝ“ + +* ใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ใƒœใƒ‡ใ‚ฃใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* Cookie ใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ใƒ˜ใƒƒใƒ€ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ใƒ•ใ‚ฉใƒผใƒ ใƒ‘ใƒฉใƒกใƒผใ‚ฟ +* ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟ + +* ใ‚คใƒ™ใƒณใƒˆ +* ่ตทๅ‹•ใ‚คใƒ™ใƒณใƒˆ +* ใ‚ตใƒผใƒใƒผใฎ่ตทๅ‹• +* ใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ‚คใƒ™ใƒณใƒˆ +* lifespan ใ‚คใƒ™ใƒณใƒˆ + +* ใƒใƒณใƒ‰ใƒฉ +* ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ +* ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ +* ๅ‡ฆ็†ใ™ใ‚‹ + +* ใƒขใƒ‡ใƒซ +* Pydantic ใƒขใƒ‡ใƒซ +* ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซ +* ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซ +* ใƒ•ใ‚ฉใƒผใƒ ใƒขใƒ‡ใƒซ +* ใƒขใƒ‡ใƒซใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ + +* ใ‚ฏใƒฉใ‚น +* ๅŸบๅบ•ใ‚ฏใƒฉใ‚น +* ่ฆชใ‚ฏใƒฉใ‚น +* ใ‚ตใƒ–ใ‚ฏใƒฉใ‚น +* ๅญใ‚ฏใƒฉใ‚น +* ๅ…„ๅผŸใ‚ฏใƒฉใ‚น +* ใ‚ฏใƒฉใ‚นใƒกใ‚ฝใƒƒใƒ‰ + +* ใƒ˜ใƒƒใƒ€ใƒผ +* ใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ่ค‡ๆ•ฐ๏ผ‰ +* ่ชๅฏใƒ˜ใƒƒใƒ€ใƒผ +* `Authorization` ใƒ˜ใƒƒใƒ€ใƒผ +* Forwarded ใƒ˜ใƒƒใƒ€ใƒผ + +* ไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ  +* ไพๅญ˜้–ขไฟ‚ +* dependable +* dependant + +* I/O ใƒใ‚ฆใƒณใƒ‰ +* CPU ใƒใ‚ฆใƒณใƒ‰ +* ๅŒๆ™‚ๅฎŸ่กŒๆ€ง +* ไธฆๅˆ—ๆ€ง +* ใƒžใƒซใƒใƒ—ใƒญใ‚ปใƒƒใ‚ทใƒณใ‚ฐ + +* env var +* ็’ฐๅขƒๅค‰ๆ•ฐ +* `PATH` +* `PATH` ็’ฐๅขƒๅค‰ๆ•ฐ + +* ่ช่จผ +* ่ช่จผใƒ—ใƒญใƒใ‚คใƒ€ +* ่ชๅฏ +* ่ชๅฏใƒ•ใ‚ฉใƒผใƒ  +* ่ชๅฏใƒ—ใƒญใƒใ‚คใƒ€ +* ใƒฆใƒผใ‚ถใƒผใŒ่ช่จผใ™ใ‚‹ +* ใ‚ทใ‚นใƒ†ใƒ ใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ + +* CLI +* ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚น + +* ใ‚ตใƒผใƒใƒผ +* ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ + +* ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ +* ใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒ“ใ‚น + +* ้–‹็™บ +* ้–‹็™บๆฎต้šŽ + +* dict +* ่พžๆ›ธ +* ๅˆ—ๆŒ™ๅž‹ +* Enum +* ๅˆ—ๆŒ™ใƒกใƒณใƒใƒผ + +* ใ‚จใƒณใ‚ณใƒผใƒ€ใƒผ +* ใƒ‡ใ‚ณใƒผใƒ€ใƒผ +* ใ‚จใƒณใ‚ณใƒผใƒ‰ใ™ใ‚‹ +* ใƒ‡ใ‚ณใƒผใƒ‰ใ™ใ‚‹ + +* ไพ‹ๅค– +* ้€ๅ‡บใ™ใ‚‹ + +* ๅผ +* ๆ–‡ + +* ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ +* ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ + +* GitHub ใƒ‡ใ‚ฃใ‚นใ‚ซใƒƒใ‚ทใƒงใƒณ +* GitHub Issue + +* ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น +* ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๆœ€้ฉๅŒ– + +* ๆˆปใ‚Šๅ€คใฎๅž‹ +* ๆˆปใ‚Šๅ€ค + +* ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ +* ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ  + +* ใ‚ฟใ‚นใ‚ฏ +* ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ +* ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐ + +* ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ +* ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚จใƒณใ‚ธใƒณ + +* ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ +* ๅž‹ใƒ’ใƒณใƒˆ + +* ใ‚ตใƒผใƒใƒผใƒฏใƒผใ‚ซใƒผ +* Uvicorn ใƒฏใƒผใ‚ซใƒผ +* Gunicorn ใƒฏใƒผใ‚ซใƒผ +* ใƒฏใƒผใ‚ซใƒผใƒ—ใƒญใ‚ปใ‚น +* ใƒฏใƒผใ‚ซใƒผใ‚ฏใƒฉใ‚น +* ใƒฏใƒผใ‚ฏใƒญใƒผใƒ‰ + +* ใƒ‡ใƒ—ใƒญใ‚ค +* ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ + +* SDK +* ใ‚ฝใƒ•ใƒˆใ‚ฆใ‚งใ‚ข้–‹็™บใ‚ญใƒƒใƒˆ + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* ็ ดๅฃŠ็š„ๅค‰ๆ›ด +* ใƒใ‚ฐ +* ใƒœใ‚ฟใƒณ +* ๅ‘ผใณๅ‡บใ—ๅฏ่ƒฝ +* ใ‚ณใƒผใƒ‰ +* ใ‚ณใƒŸใƒƒใƒˆ +* ใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ +* ใ‚ณใƒซใƒผใƒใƒณ +* ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณ +* ใƒ‡ใ‚ฃใ‚นใ‚ฏ +* ใƒ‰ใƒกใ‚คใƒณ +* ใ‚จใƒณใ‚ธใƒณ +* ใƒ•ใ‚งใ‚คใ‚ฏใฎ X +* HTTP GET ใƒกใ‚ฝใƒƒใƒ‰ +* ใ‚ขใ‚คใƒ†ใƒ  +* ใƒฉใ‚คใƒ–ใƒฉใƒช +* ใƒฉใ‚คใƒ•ใ‚นใƒ‘ใƒณ +* ใƒญใƒƒใ‚ฏ +* ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข +* ใƒขใƒใ‚คใƒซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ +* ใƒขใ‚ธใƒฅใƒผใƒซ +* ใƒžใ‚ฆใƒณใƒˆ +* ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ +* ใ‚ชใƒชใ‚ธใƒณ +* ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ +* ใƒšใ‚คใƒญใƒผใƒ‰ +* ใƒ—ใƒญใ‚ปใƒƒใ‚ต +* ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃ +* ใƒ—ใƒญใ‚ญใ‚ท +* ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆ +* ใ‚ฏใ‚จใƒช +* RAM +* ใƒชใƒขใƒผใƒˆใƒžใ‚ทใƒณ +* ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ +* ๆ–‡ๅญ—ๅˆ— +* ใ‚ฟใ‚ฐ +* Web ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ +* ใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ +* ่ฟ”ใ™ +* ๆคœ่จผใ™ใ‚‹ + +//// + +//// tab | ๆƒ…ๅ ฑ + +ใ“ใ‚Œใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ฆ‹ใ‚‰ใ‚Œใ‚‹๏ผˆไธปใซ๏ผ‰ๆŠ€่ก“็”จ่ชžใฎไธๅฎŒๅ…จใ‹ใค่ฆ็ฏ„็š„ใงใชใ„ไธ€่ฆงใงใ™ใ€‚ใƒ—ใƒญใƒณใƒ—ใƒˆ่จญ่จˆ่€…ใŒใ€LLM ใŒใฉใฎ็”จ่ชžใงๆ‰‹ๅŠฉใ‘ใ‚’ๅฟ…่ฆใจใ—ใฆใ„ใ‚‹ใ‹ใ‚’ๆŠŠๆกใ™ใ‚‹ใฎใซๅฝน็ซ‹ใคใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ไพ‹ใˆใฐใ€่‰ฏใ„็ฟป่จณใ‚’ๆœ€้ฉใงใชใ„็ฟป่จณใซๆˆปใ—ใฆใ—ใพใ†ๅ ดๅˆใ‚„ใ€ใ‚ใชใŸใฎ่จ€่ชžใงใฎๆดป็”จใƒปๆ ผๅค‰ๅŒ–ใซๅ•้กŒใŒใ‚ใ‚‹ๅ ดๅˆใชใฉใงใ™ใ€‚ + +`docs/de/llm-prompt.md` ใฎใ€Œ### List of English terms and their preferred German translationsใ€ใฎ็ฏ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +//// diff --git a/docs/ja/docs/about/index.md b/docs/ja/docs/about/index.md new file mode 100644 index 0000000000..b099df7fab --- /dev/null +++ b/docs/ja/docs/about/index.md @@ -0,0 +1,3 @@ +# ๆฆ‚่ฆ { #about } + +FastAPI ใฎๆฆ‚่ฆใ€ใใฎ่จญ่จˆใ‚„ใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใชใฉใซใคใ„ใฆ่งฃ่ชฌใ—ใพใ™ใ€‚๐Ÿค“ diff --git a/docs/ja/docs/advanced/additional-responses.md b/docs/ja/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..4c44257885 --- /dev/null +++ b/docs/ja/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI ใฎ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚น { #additional-responses-in-openapi } + +/// warning | ๆณจๆ„ + +ใ“ใ‚Œใฏๆฏ”่ผƒ็š„้ซ˜ๅบฆใชใƒˆใƒ”ใƒƒใ‚ฏใงใ™ใ€‚ + +FastAPI ใ‚’ไฝฟใ„ๅง‹ใ‚ใŸใฐใ‹ใ‚Šใงใ‚ใ‚Œใฐใ€ใ“ใ‚Œใฏไธ่ฆใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +/// + +่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ€ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€่ชฌๆ˜Žใชใฉใ‚’ไผดใ†่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +ใใ‚Œใ‚‰ใฎ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚นใฏ OpenAPI ใ‚นใ‚ญใƒผใƒžใซๅซใพใ‚Œใ€API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚‚่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +ใŸใ ใ—ใ€ใใ‚Œใ‚‰ใฎ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚นใซใคใ„ใฆใฏใ€ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ๆŒ‡ๅฎšใ—ใฆ `JSONResponse` ใชใฉใฎ `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +## `model` ใ‚’ไฝฟใฃใŸ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚น { #additional-response-with-model } + +*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใซ `responses` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ›ใพใ™ใ€‚ + +ใ“ใ‚Œใฏ `dict` ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใ‚ญใƒผใฏๅ„ใƒฌใ‚นใƒใƒณใ‚นใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰๏ผˆไพ‹: `200`๏ผ‰ใ€ๅ€คใฏๅ„ใƒฌใ‚นใƒใƒณใ‚นใฎๆƒ…ๅ ฑใ‚’ๅซใ‚€ๅˆฅใฎ `dict` ใงใ™ใ€‚ + +ใใ‚Œใžใ‚Œใฎใƒฌใ‚นใƒใƒณใ‚น `dict` ใซใฏใ€`response_model` ใจๅŒๆง˜ใซ Pydantic ใƒขใƒ‡ใƒซใ‚’ๆ ผ็ดใ™ใ‚‹ `model` ใ‚ญใƒผใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚ + +FastAPI ใฏใใฎใƒขใƒ‡ใƒซใ‹ใ‚‰ JSON Schema ใ‚’็”Ÿๆˆใ—ใ€OpenAPI ใฎ้ฉๅˆ‡ใชๅ ดๆ‰€ใซๅซใ‚ใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `404` ใจ Pydantic ใƒขใƒ‡ใƒซ `Message` ใ‚’ๆŒใคๅˆฅใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€ๆฌกใฎใ‚ˆใ†ใซๆ›ธใ‘ใพใ™: + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note | ๅ‚™่€ƒ + +`JSONResponse` ใ‚’็›ดๆŽฅ่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +/// info | ๆƒ…ๅ ฑ + +`model` ใ‚ญใƒผใฏ OpenAPI ใฎไธ€้ƒจใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +FastAPI ใฏใใ“ใ‹ใ‚‰ Pydantic ใƒขใƒ‡ใƒซใ‚’ๅ–ๅพ—ใ—ใฆ JSON Schema ใ‚’็”Ÿๆˆใ—ใ€้ฉๅˆ‡ใชๅ ดๆ‰€ใซ้…็ฝฎใ—ใพใ™ใ€‚ + +้ฉๅˆ‡ใชๅ ดๆ‰€ใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +- `content` ใ‚ญใƒผใฎไธญใ€‚ใ“ใ‚Œใฏๅ€คใจใ—ใฆๅˆฅใฎ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆ`dict`๏ผ‰ใ‚’ๆŒใกใ€ใใฎไธญใซๆฌกใŒๅซใพใ‚Œใพใ™: + - ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—๏ผˆไพ‹: `application/json`๏ผ‰ใ‚’ใ‚ญใƒผใจใ—ใ€ๅ€คใจใ—ใฆใ•ใ‚‰ใซๅˆฅใฎ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆŒใกใ€ใใฎไธญใซๆฌกใŒๅซใพใ‚Œใพใ™: + - `schema` ใ‚ญใƒผใ€‚ๅ€คใจใ—ใฆใƒขใƒ‡ใƒซ็”ฑๆฅใฎ JSON Schema ใ‚’ๆŒใกใ€ใ“ใ“ใŒๆญฃใ—ใ„้…็ฝฎๅ ดๆ‰€ใงใ™ใ€‚ + - FastAPI ใฏใ“ใ“ใซใ€ใ‚นใ‚ญใƒผใƒžใ‚’็›ดๆŽฅๅŸ‹ใ‚่พผใ‚€ไปฃใ‚ใ‚Šใซ OpenAPI ๅ†…ใฎใ‚ฐใƒญใƒผใƒใƒซใช JSON Schema ใธใฎๅ‚็…งใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ไป–ใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚„ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใใ‚Œใ‚‰ใฎ JSON Schema ใ‚’็›ดๆŽฅๅˆฉ็”จใ—ใ€ใ‚ˆใ‚Š่‰ฏใ„ใ‚ณใƒผใƒ‰็”Ÿๆˆใƒ„ใƒผใƒซ็ญ‰ใ‚’ๆไพ›ใงใใพใ™ใ€‚ + +/// + +ใ“ใฎ *path operation* ใฎใŸใ‚ใซ OpenAPI ใซ็”Ÿๆˆใ•ใ‚Œใ‚‹ใƒฌใ‚นใƒใƒณใ‚นใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +ใ‚นใ‚ญใƒผใƒžใฏ OpenAPI ใ‚นใ‚ญใƒผใƒžๅ†…ใฎๅˆฅใฎๅ ดๆ‰€ใธใฎๅ‚็…งใซใชใ‚Šใพใ™: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## ใƒกใ‚คใƒณใฎใƒฌใ‚นใƒใƒณใ‚นใซ่ฟฝๅŠ ใฎใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ— { #additional-media-types-for-the-main-response } + +ๅŒใ˜ `responses` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใฃใฆใ€ๅŒไธ€ใฎใƒกใ‚คใƒณใƒฌใ‚นใƒใƒณใ‚นใซๅˆฅใฎใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`image/png` ใฎ่ฟฝๅŠ ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’ๅŠ ใˆใ€ใ‚ใชใŸใฎ *path operation* ใŒ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ— `application/json`๏ผ‰ใพใŸใฏ PNG ็”ปๅƒใ‚’่ฟ”ใ›ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | ๅ‚™่€ƒ + +็”ปๅƒใฏ `FileResponse` ใ‚’ไฝฟใฃใฆ็›ดๆŽฅ่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +/// info | ๆƒ…ๅ ฑ + +`responses` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงๆ˜Ž็คบ็š„ใซๅˆฅใฎใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚’ๆŒ‡ๅฎšใ—ใชใ„้™ใ‚Šใ€FastAPI ใฏใƒฌใ‚นใƒใƒณใ‚นใŒใƒกใ‚คใƒณใฎใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใจๅŒใ˜ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `application/json`๏ผ‰ใงใ‚ใ‚‹ใจใฟใชใ—ใพใ™ใ€‚ + +ใŸใ ใ—ใ€ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใŒ `None` ใฎใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ใƒขใƒ‡ใƒซใŒ้–ข้€ฃไป˜ใ‘ใ‚‰ใ‚ŒใŸ่ฟฝๅŠ ใƒฌใ‚นใƒใƒณใ‚นใซใฏ FastAPI ใฏ `application/json` ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ + +/// + +## ๆƒ…ๅ ฑใฎ็ตๅˆ { #combining-information } + +`response_model`ใ€`status_code`ใ€`responses` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใฉใ€่ค‡ๆ•ฐใฎๅ ดๆ‰€ใ‹ใ‚‰ใฎใƒฌใ‚นใƒใƒณใ‚นๆƒ…ๅ ฑใ‚’็ต„ใฟๅˆใ‚ใ›ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +`response_model` ใ‚’ๅฎฃ่จ€ใ—ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `200`๏ผˆๅฟ…่ฆใชใ‚‰ไปปๆ„ใฎใ‚ณใƒผใƒ‰๏ผ‰ใ‚’ไฝฟใ„ใ€ใใฎๅŒใ˜ใƒฌใ‚นใƒใƒณใ‚นใซๅฏพใ™ใ‚‹่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’ `responses` ใง OpenAPI ใ‚นใ‚ญใƒผใƒžใซ็›ดๆŽฅ่จ˜่ฟฐใงใใพใ™ใ€‚ + +FastAPI ใฏ `responses` ใซใ‚ใ‚‹่ฟฝๅŠ ๆƒ…ๅ ฑใ‚’ไฟๆŒใ—ใ€ใƒขใƒ‡ใƒซใฎ JSON Schema ใจ็ตๅˆใ—ใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€Pydantic ใƒขใƒ‡ใƒซใ‚’็”จใ„ใ€็‹ฌ่‡ชใฎ `description` ใ‚’ๆŒใคใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `404` ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +ใ•ใ‚‰ใซใ€`response_model` ใ‚’ไฝฟใ†ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `200` ใฎใƒฌใ‚นใƒใƒณใ‚นใซ็‹ฌ่‡ชใฎ `example` ใ‚’ๅซใ‚ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +ใ“ใ‚Œใ‚‰ใฏใ™ในใฆ็ตๅˆใ•ใ‚Œใฆ OpenAPI ใซๅซใพใ‚Œใ€API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™: + + + +## ไบ‹ๅ‰ๅฎš็พฉใƒฌใ‚นใƒใƒณใ‚นใจใ‚ซใ‚นใ‚ฟใƒ ใฎ็ต„ใฟๅˆใ‚ใ› { #combine-predefined-responses-and-custom-ones } + +ๅคšใใฎ *path operations* ใซ้ฉ็”จใงใใ‚‹ไบ‹ๅ‰ๅฎš็พฉใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’็”จๆ„ใ—ใคใคใ€ๅ„ *path operation* ใ”ใจใซๅฟ…่ฆใชใ‚ซใ‚นใ‚ฟใƒ ใƒฌใ‚นใƒใƒณใ‚นใจ็ต„ใฟๅˆใ‚ใ›ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€Python ใฎ `**dict_to_unpack` ใซใ‚ˆใ‚‹ `dict` ใฎใ€Œใ‚ขใƒณใƒ‘ใƒƒใ‚ฏใ€ใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใ‚’ไฝฟใˆใพใ™: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +ใ“ใ“ใงใฏใ€`new_dict` ใซใฏ `old_dict` ใฎใ™ในใฆใฎใ‚ญใƒผใจๅ€คใซๅŠ ใˆใ€ๆ–ฐใ—ใ„ใ‚ญใƒผใจๅ€คใŒๅซใพใ‚Œใพใ™: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +ใ“ใฎใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใ‚’ไฝฟใ†ใจใ€*path operations* ใงไบ‹ๅ‰ๅฎš็พฉใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ†ๅˆฉ็”จใ—ใ€ใ•ใ‚‰ใซใ‚ซใ‚นใ‚ฟใƒ ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’็ต„ใฟๅˆใ‚ใ›ใ‚‰ใ‚Œใพใ™ใ€‚ + +ไพ‹ใˆใฐ: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## OpenAPI ใƒฌใ‚นใƒใƒณใ‚นใฎ่ฉณ็ดฐ { #more-information-about-openapi-responses } + +ใƒฌใ‚นใƒใƒณใ‚นใซๆญฃ็ขบใซไฝ•ใ‚’ๅซใ‚ใ‚‰ใ‚Œใ‚‹ใ‹ใฏใ€OpenAPI ไป•ๆง˜ใฎๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„: + +- OpenAPI ใฎ Responses Objectใ€‚ใ“ใ“ใซใฏ `Response Object` ใŒๅซใพใ‚Œใพใ™ใ€‚ +- OpenAPI ใฎ Response Objectใ€‚`responses` ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅ†…ใฎๅ„ใƒฌใ‚นใƒใƒณใ‚นใซใ€ใ“ใ“ใงๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹่ฆ็ด ใ‚’็›ดๆŽฅๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚`description`ใ€`headers`ใ€`content`๏ผˆใ“ใ“ใง็•ฐใชใ‚‹ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ‚„ JSON Schema ใ‚’ๅฎฃ่จ€ใ—ใพใ™๏ผ‰ใ€`links` ใชใฉใ€‚ diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index 14b7e8ba87..fdac52e837 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning | ๆณจๆ„ +/// warning ไธŠใฎไพ‹ใฎใ‚ˆใ†ใซ `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ใจใ€ใใ‚Œใฏใใฎใพใพ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ @@ -38,4 +38,4 @@ ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใจใƒฌใ‚นใƒใƒณใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใ€ใใ‚Œใ‚‰ใฏ OpenAPI ใ‚นใ‚ญใƒผใƒž๏ผˆAPI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ๏ผ‰ใซใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚FastAPI ใซใฏใ€ไบ‹ๅ‰ใซไฝ•ใŒ่ฟ”ใ•ใ‚Œใ‚‹ใ‹ใ‚’็Ÿฅใ‚‹ๆ–นๆณ•ใŒใชใ„ใ‹ใ‚‰ใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€[Additional Responses](additional-responses.md){.internal-link target=_blank} ใ‚’ไฝฟใฃใฆใ‚ณใƒผใƒ‰ๅ†…ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใงใใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€[่ฟฝๅŠ ใฎใƒฌใ‚นใƒใƒณใ‚น](additional-responses.md){.internal-link target=_blank} ใ‚’ไฝฟใฃใฆใ‚ณใƒผใƒ‰ๅ†…ใซใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/advanced-dependencies.md b/docs/ja/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000..d38ce548d1 --- /dev/null +++ b/docs/ja/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# ้ซ˜ๅบฆใชไพๅญ˜้–ขไฟ‚ { #advanced-dependencies } + +## ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅŒ–ใ•ใ‚ŒใŸไพๅญ˜้–ขไฟ‚ { #parameterized-dependencies } + +ใ“ใ‚Œใพใง่ฆ‹ใฆใใŸไพๅญ˜้–ขไฟ‚ใฏใ€ๅ›บๅฎšใฎ้–ขๆ•ฐใพใŸใฏใ‚ฏใƒฉใ‚นใงใ—ใŸใ€‚ + +ใ—ใ‹ใ—ใ€ๅคšใใฎ็•ฐใชใ‚‹้–ขๆ•ฐใ‚„ใ‚ฏใƒฉใ‚นใ‚’ๅฎฃ่จ€ใ›ใšใซใ€ใใฎไพๅญ˜้–ขไฟ‚ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใŸใจใˆใฐใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใซใ€ใ‚ใ‚‹ๅ›บๅฎšใฎๅ†…ๅฎนใŒๅซใพใ‚Œใฆใ„ใ‚‹ใ‹ใ‚’ๆคœๆŸปใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ใŒๆฌฒใ—ใ„ใจใ—ใพใ™ใ€‚ + +ใŸใ ใ—ใ€ใใฎๅ›บๅฎšใฎๅ†…ๅฎนใฏใƒ‘ใƒฉใƒกใƒผใ‚ฟๅŒ–ใงใใ‚‹ใ‚ˆใ†ใซใ—ใŸใ„ใงใ™ใ€‚ + +## "callable" ใชใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น { #a-callable-instance } + +Python ใซใฏใ€ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ "callable" ใซใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ‚ฏใƒฉใ‚น่‡ชไฝ“๏ผˆใ“ใ‚Œใฏใ™ใงใซ callable ใงใ™๏ผ‰ใงใฏใชใใ€ใใฎใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใงใ™ใ€‚ + +ใใฎใŸใ‚ใซใฏใ€`__call__` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๅฎฃ่จ€ใ—ใพใ™: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +ใ“ใฎๅ ดๅˆใ€ใ“ใฎ `__call__` ใŒใ€**FastAPI** ใŒ่ฟฝๅŠ ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’็ขบ่ชใ™ใ‚‹ใŸใ‚ใซไฝฟใ†ใ‚‚ใฎใซใชใ‚Šใ€ๅพŒใงใ‚ใชใŸใฎ *path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๅ€คใ‚’ๆธกใ™ใŸใ‚ใซๅ‘ผใณๅ‡บใ•ใ‚Œใ‚‹ใ‚‚ใฎใซใชใ‚Šใพใ™ใ€‚ + +## ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟๅŒ– { #parameterize-the-instance } + +ใใ—ใฆใ€`__init__` ใ‚’ไฝฟใฃใฆใ€ไพๅญ˜้–ขไฟ‚ใ‚’ใ€Œใƒ‘ใƒฉใƒกใƒผใ‚ฟๅŒ–ใ€ใ™ใ‚‹ใŸใ‚ใซๅˆฉ็”จใงใใ‚‹ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใงใใพใ™: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +ใ“ใฎๅ ดๅˆใ€**FastAPI** ใฏ `__init__` ใซ่งฆใ‚ŒใŸใ‚Šๆฐ—ใซใ‹ใ‘ใŸใ‚Šใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚็งใŸใกใŒใ‚ณใƒผใƒ‰ๅ†…ใง็›ดๆŽฅไฝฟใ„ใพใ™ใ€‚ + +## ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฎไฝœๆˆ { #create-an-instance } + +ใ“ใฎใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฏๆฌกใฎใ‚ˆใ†ใซไฝœๆˆใงใใพใ™: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +ใ“ใฎใ‚ˆใ†ใซใ—ใฆไพๅญ˜้–ขไฟ‚ใ‚’ใ€Œใƒ‘ใƒฉใƒกใƒผใ‚ฟๅŒ–ใ€ใงใใพใ™ใ€‚ใ„ใพใ‚„ `"bar"` ใŒๅฑžๆ€ง `checker.fixed_content` ใจใ—ใฆไธญใซไฟๆŒใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +## ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไพๅญ˜้–ขไฟ‚ใจใ—ใฆไฝฟใ† { #use-the-instance-as-a-dependency } + +ใใฎๅพŒใ€`Depends(FixedContentQueryChecker)` ใฎไปฃใ‚ใ‚Šใซ `Depends(checker)` ใงใ“ใฎ `checker` ใ‚’ไฝฟใˆใพใ™ใ€‚ไพๅญ˜้–ขไฟ‚ใฏใ‚ฏใƒฉใ‚นใใฎใ‚‚ใฎใงใฏใชใใ€ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใงใ‚ใ‚‹ `checker` ใ ใ‹ใ‚‰ใงใ™ใ€‚ + +ไพๅญ˜้–ขไฟ‚ใ‚’่งฃๆฑบใ™ใ‚‹ใจใใ€**FastAPI** ใฏใ“ใฎ `checker` ใ‚’ๆฌกใฎใ‚ˆใ†ใซๅ‘ผใณๅ‡บใ—ใพใ™: + +```Python +checker(q="somequery") +``` + +...ใใ—ใฆใ€ใใฎๆˆปใ‚Šๅ€คใ‚’ *path operation ้–ขๆ•ฐ* ๅ†…ใฎไพๅญ˜้–ขไฟ‚ใฎๅ€คใจใ—ใฆใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `fixed_content_included` ใซๆธกใ—ใพใ™: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ“ใพใงใฎๅ†…ๅฎนใฏๅ›žใ‚Šใใฉใๆ„Ÿใ˜ใ‚‰ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใพใ ใฉใฎใ‚ˆใ†ใซๅฝน็ซ‹ใคใ‹ใŒๆ˜Ž็ขบใงใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎไพ‹ใฏๆ„ๅ›ณ็š„ใซๅ˜็ด”ใงใ™ใŒใ€ไป•็ต„ใฟใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚ + +ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎ็ซ ใงใฏใ€ๅŒใ˜ใ‚„ใ‚Šๆ–นใงๅฎŸ่ฃ…ใ•ใ‚ŒใŸใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ“ใพใงใ‚’็†่งฃใงใใฆใ„ใ‚Œใฐใ€ใใ†ใ—ใŸใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ็”จใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใŒๅ†…้ƒจใงใฉใฎใ‚ˆใ†ใซๅ‹•ใ„ใฆใ„ใ‚‹ใ‹ใ‚‚็†่งฃใงใใฆใ„ใพใ™ใ€‚ + +/// + +## `yield`ใ€`HTTPException`ใ€`except` ใจใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ‚’ไผดใ†ไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | ๆณจๆ„ + +ใ“ใ‚Œใ‚‰ใฎๆŠ€่ก“็š„่ฉณ็ดฐใฏใ€ใปใจใ‚“ใฉใฎๅ ดๅˆใฏไธ่ฆใงใ™ใ€‚ + +ไธปใซใ€0.121.0 ใ‚ˆใ‚Šๅ‰ใฎ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใ€`yield` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ใงๅ•้กŒใŒ็™บ็”Ÿใ—ใฆใ„ใ‚‹ๅ ดๅˆใซๆœ‰็”จใงใ™ใ€‚ + +/// + +`yield` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ใฏใ€ใ•ใพใ–ใพใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซๅฏพๅฟœใ—ใ€ใ„ใใคใ‹ใฎๅ•้กŒใ‚’ไฟฎๆญฃใ™ใ‚‹ใŸใ‚ใซๆ™‚้–“ใจใจใ‚‚ใซ้€ฒๅŒ–ใ—ใฆใใพใ—ใŸใ€‚ใ“ใ“ใงใฏๅค‰ๆ›ด็‚นใฎๆฆ‚่ฆใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +### `yield` ใจ `scope` ใ‚’ไผดใ†ไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield-and-scope } + +ใƒใƒผใ‚ธใƒงใƒณ 0.121.0 ใงใ€`yield` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ใซๅฏพใ—ใฆ `Depends(scope="function")` ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ—ใŸใ€‚ + +`Depends(scope="function")` ใ‚’ไฝฟใ†ใจใ€`yield` ใฎๅพŒใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใธใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใ‚‹ๅ‰ใ€*path operation ้–ขๆ•ฐ* ใŒ็ต‚ไบ†ใ—ใŸ็›ดๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ใใ—ใฆใ€`Depends(scope="request")`๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ๏ผ‰ใ‚’ไฝฟใ†ๅ ดๅˆใ€`yield` ใฎๅพŒใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใƒฌใ‚นใƒใƒณใ‚น้€ไฟกๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +่ฉณใ—ใใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ€Œ[`yield` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ - ๆ—ฉๆœŸ็ต‚ไบ†ใจ `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope)ใ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +### `yield` ใจ `StreamingResponse` ใ‚’ไผดใ†ไพๅญ˜้–ขไฟ‚ใ€ๆŠ€่ก“่ฉณ็ดฐ { #dependencies-with-yield-and-streamingresponse-technical-details } + +FastAPI 0.118.0 ใ‚ˆใ‚Šๅ‰ใงใฏใ€`yield` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€*path operation ้–ขๆ•ฐ* ใŒๆˆปใฃใฆใ‹ใ‚‰ใƒฌใ‚นใƒใƒณใ‚น้€ไฟก็›ดๅ‰ใซ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใŒๅฎŸ่กŒใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ + +ใ“ใ‚Œใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใŒใƒใƒƒใƒˆใƒฏใƒผใ‚ฏไธŠใ‚’็งปๅ‹•ใ™ใ‚‹ใฎใ‚’ๅพ…ใฃใฆใ„ใ‚‹้–“ใซใ€ไธ่ฆใซใƒชใ‚ฝใƒผใ‚นใ‚’ไฟๆŒใ—ใชใ„ใ‚ˆใ†ใซใ™ใ‚‹ๆ„ๅ›ณใงใ—ใŸใ€‚ + +ใ“ใฎๅค‰ๆ›ดใซใ‚ˆใ‚Šใ€`StreamingResponse` ใ‚’่ฟ”ใ™ๅ ดๅˆใ€`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใ™ใงใซๅฎŸ่กŒใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใซใชใ‚Šใพใ—ใŸใ€‚ + +ใŸใจใˆใฐใ€`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎไธญใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ๆŒใฃใฆใ„ใŸๅ ดๅˆใ€`StreamingResponse` ใฏใƒ‡ใƒผใ‚ฟใ‚’ใ‚นใƒˆใƒชใƒผใƒŸใƒณใ‚ฐใ—ใฆใ„ใ‚‹้–“ใซใใฎใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝฟใˆใพใ›ใ‚“ใ€‚ใจใ„ใ†ใฎใ‚‚ใ€`yield` ใฎๅพŒใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใงใใฎใ‚ปใƒƒใ‚ทใƒงใƒณใŒใ™ใงใซใ‚ฏใƒญใƒผใ‚บใ•ใ‚Œใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ + +ใ“ใฎๆŒ™ๅ‹•ใฏ 0.118.0 ใงๅ…ƒใซๆˆปใ•ใ‚Œใ€`yield` ใฎๅพŒใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใƒฌใ‚นใƒใƒณใ‚น้€ไฟกๅพŒใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ—ใŸใ€‚ + +/// info | ๆƒ…ๅ ฑ + +ไปฅไธ‹ใง่ฆ‹ใ‚‹ใ‚ˆใ†ใซใ€ใ“ใ‚Œใฏใƒใƒผใ‚ธใƒงใƒณ 0.106.0 ใ‚ˆใ‚Šๅ‰ใฎๆŒ™ๅ‹•ใจใจใฆใ‚‚ไผผใฆใ„ใพใ™ใŒใ€ใ„ใใคใ‹ใฎใ‚ณใƒผใƒŠใƒผใ‚ฑใƒผใ‚นใซๅฏพใ™ใ‚‹ๆ”น่‰ฏใจใƒใ‚ฐไฟฎๆญฃใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +/// + +#### ๆ—ฉๆœŸ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น { #use-cases-with-early-exit-code } + +็‰นๅฎšใฎๆกไปถใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚น้€ไฟกๅ‰ใซ `yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ€ๅคใ„ๆŒ™ๅ‹•ใฎๆฉๆตใ‚’ๅ—ใ‘ใ‚‰ใ‚Œใ‚‹ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝฟใฃใฆใƒฆใƒผใ‚ถๆคœ่จผใ ใ‘ใ‚’่กŒใ„ใ€ใใฎๅพŒใฏ *path operation ้–ขๆ•ฐ* ๅ†…ใงใฏใใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไธ€ๅˆ‡ไฝฟใ‚ใชใ„ใ€ใ‹ใคใƒฌใ‚นใƒใƒณใ‚น้€ไฟกใซ้•ทใ„ๆ™‚้–“ใŒใ‹ใ‹ใ‚‹๏ผˆไพ‹ใˆใฐใƒ‡ใƒผใ‚ฟใ‚’ใ‚†ใฃใใ‚Š้€ใ‚‹ `StreamingResponse`๏ผ‰ใŒใ€ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฏไฝฟใ‚ใชใ„ใ€ใจใ„ใ†ใ‚ฑใƒผใ‚นใงใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใ€ใƒฌใ‚นใƒใƒณใ‚นใฎ้€ไฟกใŒ็ต‚ใ‚ใ‚‹ใพใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใŒไฟๆŒใ•ใ‚Œใพใ™ใŒใ€ไฝฟใ‚ใชใ„ใฎใงใ‚ใ‚ŒใฐไฟๆŒใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +็ต‚ไบ†ใ‚ณใƒผใƒ‰ใ€ใ™ใชใ‚ใก `Session` ใฎ่‡ชๅ‹•ใ‚ฏใƒญใƒผใ‚บใฏ: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...ใฎ้ƒจๅˆ†ใงๅฎš็พฉใ•ใ‚ŒใฆใŠใ‚Šใ€้…ใ„ใƒ‡ใƒผใ‚ฟ้€ไฟกใŒ็ต‚ใ‚ใฃใŸๅพŒใซๅฎŸ่กŒใ•ใ‚Œใพใ™: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +ใ—ใ‹ใ—ใ€`generate_stream()` ใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝฟใ‚ใชใ„ใŸใ‚ใ€ใƒฌใ‚นใƒใƒณใ‚น้€ไฟกไธญใซใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’้–‹ใ„ใŸใพใพใซใ—ใฆใŠใๅฟ…่ฆใฏๅฎŸ้š›ใซใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +SQLModel๏ผˆใพใŸใฏ SQLAlchemy๏ผ‰ใงใ“ใฎ็‰นๅฎšใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ไธ่ฆใซใชใฃใŸๆ™‚็‚นใงใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ๆ˜Ž็คบ็š„ใซใ‚ฏใƒญใƒผใ‚บใงใใพใ™: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +ใ“ใฎใ‚ˆใ†ใซใ™ใ‚‹ใจใ€ใ‚ปใƒƒใ‚ทใƒงใƒณใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆŽฅ็ถšใ‚’่งฃๆ”พใ™ใ‚‹ใŸใ‚ใ€ไป–ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใŒใใ‚Œใ‚’ไฝฟใˆใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ + +`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใงๆ—ฉๆœŸ็ต‚ไบ†ใŒๅฟ…่ฆใชๅˆฅใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใ‚ใชใŸใฎๅ…ทไฝ“็š„ใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใจใ€ใชใœ `yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎๆ—ฉๆœŸใ‚ฏใƒญใƒผใ‚บใŒๆœ‰็›Šใ‹ใ‚’่ชฌๆ˜Žใ—ใฆใ€GitHub Discussion ใฎ่ณชๅ•ใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ + +`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎๆ—ฉๆœŸใ‚ฏใƒญใƒผใ‚บใซ็ดๅพ—ใงใใ‚‹ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๆ—ฉๆœŸใ‚ฏใƒญใƒผใ‚บใซใ‚ชใƒ—ใƒˆใ‚คใƒณใ™ใ‚‹ๆ–ฐใ—ใ„ๆ–นๆณ•ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใ‚’ๆคœ่จŽใ—ใพใ™ใ€‚ + +### `yield` ใจ `except` ใ‚’ไผดใ†ไพๅญ˜้–ขไฟ‚ใ€ๆŠ€่ก“่ฉณ็ดฐ { #dependencies-with-yield-and-except-technical-details } + +FastAPI 0.110.0 ใ‚ˆใ‚Šๅ‰ใงใฏใ€`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ„ใ€ใใฎไพๅญ˜้–ขไฟ‚ๅ†…ใง `except` ใซใ‚ˆใฃใฆไพ‹ๅค–ใ‚’ๆ•ๆ‰ใ—ใ€ๅ†ๅบฆใใฎไพ‹ๅค–ใ‚’้€ๅ‡บใ—ใชใ‹ใฃใŸๅ ดๅˆใงใ‚‚ใ€ใใฎไพ‹ๅค–ใฏ่‡ชๅ‹•็š„ใซ้€ๅ‡บ๏ผˆใƒ•ใ‚ฉใƒฏใƒผใƒ‰๏ผ‰ใ•ใ‚Œใ€ไปปๆ„ใฎไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใพใŸใฏๅ†…้ƒจใ‚ตใƒผใƒใ‚จใƒฉใƒผใƒใƒณใƒ‰ใƒฉใซๆธกใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ + +ใ“ใ‚Œใฏใ€ใƒใƒณใƒ‰ใƒฉใฎใชใ„ใƒ•ใ‚ฉใƒฏใƒผใƒ‰ใ•ใ‚ŒใŸไพ‹ๅค–๏ผˆๅ†…้ƒจใ‚ตใƒผใƒใ‚จใƒฉใƒผ๏ผ‰ใซใ‚ˆใ‚‹ๆœชๅ‡ฆ็†ใฎใƒกใƒขใƒชๆถˆ่ฒปใ‚’ไฟฎๆญฃใ—ใ€้€šๅธธใฎ Python ใ‚ณใƒผใƒ‰ใฎๆŒ™ๅ‹•ใจไธ€่ฒซๆ€งใ‚’ๆŒใŸใ›ใ‚‹ใŸใ‚ใ€ใƒใƒผใ‚ธใƒงใƒณ 0.110.0 ใงๅค‰ๆ›ดใ•ใ‚Œใพใ—ใŸใ€‚ + +### ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใจ `yield` ใ‚’ไผดใ†ไพๅญ˜้–ขไฟ‚ใ€ๆŠ€่ก“่ฉณ็ดฐ { #background-tasks-and-dependencies-with-yield-technical-details } + +FastAPI 0.106.0 ใ‚ˆใ‚Šๅ‰ใงใฏใ€`yield` ใฎๅพŒใงไพ‹ๅค–ใ‚’้€ๅ‡บใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใงใ—ใŸใ€‚`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎ็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใƒฌใ‚นใƒใƒณใ‚น้€ไฟกใ€ŒๅพŒใ€ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใŸใ‚ใ€[ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} ใฏใ™ใงใซๅฎŸ่กŒๆธˆใฟใงใ—ใŸใ€‚ + +ใ“ใ‚Œใฏไธปใซใ€ไพๅญ˜้–ขไฟ‚ใŒ "yield" ใ—ใŸๅŒใ˜ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏๅ†…ใงๅˆฉ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใฎ่จญ่จˆใงใ—ใŸใ€‚็ต‚ไบ†ใ‚ณใƒผใƒ‰ใฏใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏๅฎŒไบ†ๅพŒใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใŒใƒใƒƒใƒˆใƒฏใƒผใ‚ฏไธŠใ‚’็งปๅ‹•ใ™ใ‚‹ใฎใ‚’ๅพ…ใฃใฆใ„ใ‚‹้–“ใซใƒชใ‚ฝใƒผใ‚นใ‚’ไฟๆŒใ—ใชใ„ใ‚ˆใ†ใซใ™ใ‚‹ๆ„ๅ›ณใงใ€FastAPI 0.106.0 ใงๅค‰ๆ›ดใ•ใ‚Œใพใ—ใŸใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅŠ ใˆใฆใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฏ้€šๅธธใ€็‹ฌ็ซ‹ใ—ใŸใƒญใ‚ธใƒƒใ‚ฏใฎ้›†ๅˆใงใ‚ใ‚Šใ€๏ผˆไพ‹ใˆใฐๅฐ‚็”จใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆŽฅ็ถšใชใฉ๏ผ‰ใใ‚Œ่‡ช่บซใฎใƒชใ‚ฝใƒผใ‚นใงๅ€‹ๅˆฅใซๆ‰ฑใ†ในใใงใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใ“ใฎใ‚„ใ‚Šๆ–นใฎๆ–นใŒใ‚ณใƒผใƒ‰ใฏใŠใใ‚‰ใใ‚ˆใ‚Šใ‚ฏใƒชใƒผใƒณใซใชใ‚Šใพใ™ใ€‚ + +/// + +ใ“ใฎๆŒ™ๅ‹•ใซไพๅญ˜ใ—ใฆใ„ใŸๅ ดๅˆใฏใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ็”จใฎใƒชใ‚ฝใƒผใ‚นใ‚’ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏๅ†…้ƒจใงไฝœๆˆใ—ใ€`yield` ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ใฎใƒชใ‚ฝใƒผใ‚นใซไพๅญ˜ใ—ใชใ„ใƒ‡ใƒผใ‚ฟใ ใ‘ใ‚’ๅ†…้ƒจใงไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ + +ไพ‹ใˆใฐใ€ๅŒใ˜ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝฟใ†ใฎใงใฏใชใใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏๅ†…ใงๆ–ฐใ—ใ„ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝœๆˆใ—ใ€ใ“ใฎๆ–ฐใ—ใ„ใ‚ปใƒƒใ‚ทใƒงใƒณใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ใใ—ใฆใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใฎๅผ•ๆ•ฐใจใ—ใฆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ่‡ชไฝ“ใ‚’ๆธกใ™ใฎใงใฏใชใใ€ใใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎ ID ใ‚’ๆธกใ—ใ€ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐๅ†…ใงใ‚‚ใ†ไธ€ๅบฆใใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/advanced-python-types.md b/docs/ja/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..b4409bcf66 --- /dev/null +++ b/docs/ja/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ้ซ˜ๅบฆใช Python ใฎๅž‹ { #advanced-python-types } + +Python ใฎๅž‹ใ‚’ๆ‰ฑใ†ใจใใซๅฝน็ซ‹ใค่ฟฝๅŠ ใฎใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ใ„ใใคใ‹็ดนไป‹ใ—ใพใ™ใ€‚ + +## `Union` ใพใŸใฏ `Optional` ใฎๅˆฉ็”จ { #using-union-or-optional } + +ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใง `|` ใŒไฝฟใˆใชใ„ๅ ดๅˆใ€ใŸใจใˆใฐๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใงใฏใชใ `response_model=` ใฎใ‚ˆใ†ใชๅ ดๆ‰€ใงใฏใ€็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใฎไปฃใ‚ใ‚Šใซ `typing` ใฎ `Union` ใ‚’ไฝฟใˆใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`str` ใพใŸใฏ `None` ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` ใซใฏใ€`None` ใ‚’ๅ–ใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎ็Ÿญ็ธฎๅฝขใจใ—ใฆ `Optional` ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ“ใ‹ใ‚‰ใฏ็งใฎใจใฆใ‚‚ไธป่ฆณ็š„ใชๆๆกˆใงใ™: + +- ๐Ÿšจ `Optional[SomeType]` ใฎไฝฟ็”จใฏ้ฟใ‘ใพใ—ใ‚‡ใ† +- ไปฃใ‚ใ‚Šใซ โœจ **`Union[SomeType, None]` ใ‚’ไฝฟใ„ใพใ—ใ‚‡ใ†** โœจใ€‚ + +ใฉใกใ‚‰ใ‚‚็ญ‰ไพกใงๅ†…้ƒจ็š„ใซใฏๅŒไธ€ใงใ™ใŒใ€ใ€Œoptional๏ผˆไปปๆ„๏ผ‰ใ€ใจใ„ใ†่ชžใŒๅ€คใŒไปปๆ„ใ ใจ่ชค่งฃใ•ใ›ใ‚„ใ™ใใ€ๅฎŸ้š›ใฎๆ„ๅ‘ณใฏใ€Œ`None` ใ‚’ๅ–ใ‚Šๅพ—ใ‚‹ใ€ใงใ‚ใ‚Šใ€ไปปๆ„ใงใฏใชใไพ็„ถใจใ—ใฆๅฟ…้ ˆใงใ‚ใ‚‹ๅ ดๅˆใงใ‚‚ใใ†ใงใ™ใ€‚ใใฎใŸใ‚ `Optional` ใ‚ˆใ‚Š `Union` ใ‚’ๅ‹งใ‚ใพใ™ใ€‚ + +`Union[SomeType, None]` ใฎๆ–นใŒๆ„ๅ‘ณใŒใ‚ˆใ‚Šๆ˜Ž็ขบใ ใจๆ€ใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใฏ็”จ่ชžใ‚„ๅๅ‰ไป˜ใ‘ใฎ่ฉฑใซ้ŽใŽใพใ›ใ‚“ใŒใ€ใใฎ่จ€่‘‰ใŒใ‚ใชใŸใ‚„ใƒใƒผใƒ ใƒกใ‚คใƒˆใฎใ‚ณใƒผใƒ‰ใฎๆ‰ใˆๆ–นใซๅฝฑ้Ÿฟใ—ใพใ™ใ€‚ + +ไพ‹ใจใ—ใฆๆฌกใฎ้–ขๆ•ฐใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `name` ใฏ `Optional[str]` ใจๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใŒใ€ไปปๆ„ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใ—ใง้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ™ใ“ใจใฏใงใใพใ›ใ‚“: + +```Python +say_hi() # ใ‚ใฃใ€ใ“ใ‚Œใฏใ‚จใƒฉใƒผใซใชใ‚Šใพใ™๏ผ๐Ÿ˜ฑ +``` + +`name` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใ„ใŸใ‚ใ€ไพ็„ถใจใ—ใฆๅฟ…้ ˆ๏ผˆไปปๆ„ใงใฏใชใ„๏ผ‰ใงใ™ใ€‚ใŸใ ใ—ใ€`name` ใฏๅ€คใจใ—ใฆ `None` ใ‚’ๅ—ใ‘ไป˜ใ‘ใพใ™: + +```Python +say_hi(name=None) # ใ“ใ‚Œใฏๅ‹•ไฝœใ—ใพใ™ใ€‚None ใฏๆœ‰ๅŠนใงใ™ ๐ŸŽ‰ +``` + +ๆœ—ๅ ฑใจใ—ใฆใ€ๅคšใใฎๅ ดๅˆใฏๅ˜็ด”ใซ `|` ใ‚’ไฝฟใฃใฆๅž‹ใฎ Union ใ‚’ๅฎš็พฉใงใใพใ™: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +ใ—ใŸใŒใฃใฆใ€้€šๅธธใฏ `Optional` ใ‚„ `Union` ใจใ„ใฃใŸๅๅ‰ใ‚’ๆฐ—ใซใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/advanced/async-tests.md b/docs/ja/docs/advanced/async-tests.md new file mode 100644 index 0000000000..067e9cc9a2 --- /dev/null +++ b/docs/ja/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# ้žๅŒๆœŸใƒ†ใ‚นใƒˆ { #async-tests } + +ใ“ใ‚Œใพใงใซใ€ๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ `TestClient` ใ‚’ไฝฟใฃใฆ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒ†ใ‚นใƒˆใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใใพใ—ใŸใ€‚ใ“ใ“ใพใงใฏใ€`async` ้–ขๆ•ฐใ‚’ไฝฟใ‚ใชใ„ๅŒๆœŸใƒ†ใ‚นใƒˆใฎใฟใงใ—ใŸใ€‚ + +ใƒ†ใ‚นใƒˆใง้žๅŒๆœŸ้–ขๆ•ฐใ‚’ไฝฟใˆใ‚‹ใจใ€ใŸใจใˆใฐใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใธ้žๅŒๆœŸใซใ‚ฏใ‚จใƒชใ™ใ‚‹ๅ ดๅˆใชใฉใซไพฟๅˆฉใงใ™ใ€‚้žๅŒๆœŸใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟใ„ใชใŒใ‚‰ใ€FastAPI ใ‚ขใƒ—ใƒชใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚Šใ€ใใฎๅพŒใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใŒๆญฃใ—ใ„ใƒ‡ใƒผใ‚ฟใ‚’ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซๆ›ธใ่พผใ‚ใŸใ‹ใ‚’ๆคœ่จผใ—ใŸใ„ใ€ใจใ„ใฃใŸใ‚ฑใƒผใ‚นใ‚’ๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚ + +ใใฎๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +## pytest.mark.anyio { #pytest-mark-anyio } + +ใƒ†ใ‚นใƒˆๅ†…ใง้žๅŒๆœŸ้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ—ใŸใ„ๅ ดๅˆใ€ใƒ†ใ‚นใƒˆ้–ขๆ•ฐ่‡ชไฝ“ใ‚‚้žๅŒๆœŸใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚AnyIO ใฏใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใŸใ‚ใฎไพฟๅˆฉใชใƒ—ใƒฉใ‚ฐใ‚คใƒณใ‚’ๆไพ›ใ—ใฆใŠใ‚Šใ€็‰นๅฎšใฎใƒ†ใ‚นใƒˆ้–ขๆ•ฐใ‚’้žๅŒๆœŸใงๅ‘ผใณๅ‡บใ™ใ“ใจใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ + +## HTTPX { #httpx } + +**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ้€šๅธธใฎ `def` ้–ขๆ•ฐใ‚’ไฝฟใฃใฆใ„ใฆใ‚‚ใ€ใใฎๅ†…ๅดใฏไพ็„ถใจใ—ใฆ `async` ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ™ใ€‚ + +`TestClient` ใฏใ€ๆจ™ๆบ–ใฎ pytest ใ‚’ไฝฟใฃใฆ้€šๅธธใฎ `def` ใฎใƒ†ใ‚นใƒˆ้–ขๆ•ฐใ‹ใ‚‰้žๅŒๆœŸใฎ FastAPI ใ‚ขใƒ—ใƒชใ‚’ๅ‘ผใณๅ‡บใ™ใŸใ‚ใฎใ€ŒใŠใพใ˜ใชใ„ใ€ใ‚’ๅ†…้ƒจใง่กŒใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใฎใ€ŒใŠใพใ˜ใชใ„ใ€ใฏใƒ†ใ‚นใƒˆ้–ขๆ•ฐ่‡ชไฝ“ใŒ้žๅŒๆœŸใฎๅ ดๅˆใซใฏๆฉŸ่ƒฝใ—ใพใ›ใ‚“ใ€‚ใƒ†ใ‚นใƒˆใ‚’้žๅŒๆœŸใงๅฎŸ่กŒใ™ใ‚‹ใจใ€ใƒ†ใ‚นใƒˆ้–ขๆ•ฐๅ†…ใง `TestClient` ใฏไฝฟใˆใชใใชใ‚Šใพใ™ใ€‚ + +`TestClient` ใฏ HTTPX ใ‚’ๅŸบใซไฝœใ‚‰ใ‚ŒใฆใŠใ‚Šใ€ๅนธใ„ใชใ“ใจใซ API ใฎใƒ†ใ‚นใƒˆใซใฏ HTTPX ใ‚’็›ดๆŽฅๅˆฉ็”จใงใใพใ™ใ€‚ + +## ไพ‹ { #example } + +็ฐกๅ˜ใชไพ‹ใจใ—ใฆใ€[ๅคงใใชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ](../tutorial/bigger-applications.md){.internal-link target=_blank} ใจ [ใƒ†ใ‚นใƒˆ](../tutorial/testing.md){.internal-link target=_blank} ใง่ชฌๆ˜Žใ—ใŸใ‚‚ใฎใซไผผใŸใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใ‚’่€ƒใˆใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +`main.py` ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +`test_main.py` ใฏ `main.py` ใฎใƒ†ใ‚นใƒˆใ‚’ๆŒใกใ€ๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## ๅฎŸ่กŒ { #run-it } + +ใƒ†ใ‚นใƒˆใฏใ„ใคใ‚‚้€šใ‚ŠๆฌกใงๅฎŸ่กŒใงใใพใ™: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## ่ฉณ็ดฐ { #in-detail } + +ใƒžใƒผใ‚ซใƒผ `@pytest.mark.anyio` ใฏใ€ใ“ใฎใƒ†ใ‚นใƒˆ้–ขๆ•ฐใ‚’้žๅŒๆœŸใงๅ‘ผใณๅ‡บใ™ในใใงใ‚ใ‚‹ใ“ใจใ‚’ pytest ใซไผใˆใพใ™: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`TestClient` ใ‚’ไฝฟใฃใฆใ„ใŸใจใใจ็•ฐใชใ‚Šใ€ใƒ†ใ‚นใƒˆ้–ขๆ•ฐใฏ `def` ใงใฏใชใ `async def` ใซใชใฃใฆใ„ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +ๆฌกใซใ€ใ‚ขใƒ—ใƒชใ‚’ๆธกใ—ใฆ `AsyncClient` ใ‚’ไฝœๆˆใ—ใ€`await` ใ‚’ไฝฟใฃใฆ้žๅŒๆœŸใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ไฟกใงใใพใ™ใ€‚ + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +ใ“ใ‚ŒใฏๆฌกใจๅŒ็ญ‰ใงใ™: + +```Python +response = client.get('/') +``` + +...ใ“ใ‚Œใพใงใฏ `TestClient` ใงใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใฃใฆใ„ใพใ—ใŸใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆ–ฐใ—ใ„ `AsyncClient` ใงใฏ async/await ใ‚’ไฝฟใฃใฆใ„ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใƒชใ‚ฏใ‚จใ‚นใƒˆใฏ้žๅŒๆœŸใงใ™ใ€‚ + +/// + +/// warning | ๆณจๆ„ + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ lifespan ใ‚คใƒ™ใƒณใƒˆใซไพๅญ˜ใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€`AsyncClient` ใฏใใ‚Œใ‚‰ใฎใ‚คใƒ™ใƒณใƒˆใ‚’ใƒˆใƒชใ‚ฌใƒผใ—ใพใ›ใ‚“ใ€‚็ขบๅฎŸใซใƒˆใƒชใ‚ฌใƒผใ™ใ‚‹ใซใฏใ€florimondmanca/asgi-lifespan ใฎ `LifespanManager` ใ‚’ไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ใใฎไป–ใฎ้žๅŒๆœŸ้–ขๆ•ฐๅ‘ผใณๅ‡บใ— { #other-asynchronous-function-calls } + +ใƒ†ใ‚นใƒˆ้–ขๆ•ฐใŒ้žๅŒๆœŸใซใชใฃใŸใฎใงใ€FastAPI ใ‚ขใƒ—ใƒชใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆ้€ไฟกไปฅๅค–ใฎ `async` ้–ขๆ•ฐใ‚‚ใ€ใ‚ณใƒผใƒ‰ใฎไป–ใฎๅ ดๆ‰€ใจๅŒๆง˜ใซๅ‘ผใณๅ‡บใ—ใฆ๏ผˆ`await` ใ—ใฆ๏ผ‰ไฝฟใˆใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ†ใ‚นใƒˆใซ้žๅŒๆœŸ้–ขๆ•ฐๅ‘ผใณๅ‡บใ—ใ‚’็ตฑๅˆใ—ใŸ้š›ใซ๏ผˆไพ‹: MongoDB ใฎ MotorClient ไฝฟ็”จๆ™‚๏ผ‰ใ€`RuntimeError: Task attached to a different loop` ใซ้ญ้‡ใ—ใŸๅ ดๅˆใฏใ€ใ‚คใƒ™ใƒณใƒˆใƒซใƒผใƒ—ใ‚’ๅฟ…่ฆใจใ™ใ‚‹ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏ้žๅŒๆœŸ้–ขๆ•ฐๅ†…ใงใฎใฟใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นๅŒ–ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ไพ‹ใˆใฐ `@app.on_event("startup")` ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏๅ†…ใง่กŒใ„ใพใ™ใ€‚ + +/// diff --git a/docs/ja/docs/advanced/behind-a-proxy.md b/docs/ja/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..67eaa99092 --- /dev/null +++ b/docs/ja/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# ใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒ { #behind-a-proxy } + +ๅคšใใฎ็Šถๆณใงใ€FastAPI ใ‚ขใƒ—ใƒชใฎๅ‰ๆฎตใซ **Traefik** ใ‚„ **Nginx** ใฎใ‚ˆใ†ใช**ใƒ—ใƒญใ‚ญใ‚ท**ใ‚’็ฝฎใใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใƒ—ใƒญใ‚ญใ‚ทใฏ HTTPS ่จผๆ˜Žๆ›ธใชใฉใฎๅ‡ฆ็†ใ‚’ๆ‹…ใ„ใพใ™ใ€‚ + +## ใƒ—ใƒญใ‚ญใ‚ทใฎ่ปข้€ใƒ˜ใƒƒใƒ€ใƒผ { #proxy-forwarded-headers } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ‰ๆฎตใซใ‚ใ‚‹ **ใƒ—ใƒญใ‚ญใ‚ท** ใฏ้€šๅธธใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ **ใ‚ตใƒผใƒใƒผ** ใซ้€ใ‚‹ๅ‰ใซใ€ใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใŒใƒ—ใƒญใ‚ญใ‚ทใซใ‚ˆใฃใฆ่ปข้€ใ•ใ‚ŒใŸใ“ใจใ‚’็Ÿฅใ‚‰ใ›ใ‚‹ใŸใ‚ใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅ‹•็š„ใซไป˜ไธŽใ—ใ€ไฝฟ็”จไธญใฎๅ…ƒใฎ๏ผˆๅ…ฌ้–‹๏ผ‰URL๏ผˆใƒ‰ใƒกใ‚คใƒณใ‚’ๅซใ‚€๏ผ‰ใ‚„ HTTPS ไฝฟ็”จใชใฉใฎๆƒ…ๅ ฑใ‚’ไผใˆใพใ™ใ€‚ + +**ใ‚ตใƒผใƒใƒผ** ใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆไพ‹ใˆใฐ **FastAPI CLI** ็ตŒ็”ฑใฎ **Uvicorn**๏ผ‰ใฏใ“ใ‚Œใ‚‰ใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’่งฃ้‡ˆใ—ใ€ใใฎๆƒ…ๅ ฑใ‚’ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃไธŠใ€ใ‚ตใƒผใƒใƒผใฏ่‡ชๅˆ†ใŒไฟก้ ผใงใใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒใซใ‚ใ‚‹ใจๅˆ†ใ‹ใ‚‰ใชใ„ใŸใ‚ใ€ใ“ใ‚Œใ‚‰ใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’่งฃ้‡ˆใ—ใพใ›ใ‚“ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ใƒ—ใƒญใ‚ญใ‚ทใฎใƒ˜ใƒƒใƒ€ใƒผใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### ใƒ—ใƒญใ‚ญใ‚ท่ปข้€ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆœ‰ๅŠนๅŒ– { #enable-proxy-forwarded-headers } + +FastAPI CLI ใ‚’ *CLI ใ‚ชใƒ—ใ‚ทใƒงใƒณ* `--forwarded-allow-ips` ไป˜ใใง่ตทๅ‹•ใ—ใ€่ปข้€ใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฟก้ ผใ—ใฆ่ชญใ‚“ใงใ‚ˆใ„ IP ใ‚ขใƒ‰ใƒฌใ‚นใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ + +`--forwarded-allow-ips="*"` ใจใ™ใ‚‹ใจใ€ใ™ในใฆใฎ้€ไฟกๅ…ƒ IP ใ‚’ไฟก้ ผใ—ใพใ™ใ€‚ + +**ใ‚ตใƒผใƒใƒผ** ใŒไฟก้ ผใงใใ‚‹ **ใƒ—ใƒญใ‚ญใ‚ท** ใฎ่ƒŒๅพŒใซใ‚ใ‚Šใ€ใใฎใƒ—ใƒญใ‚ญใ‚ทใ‹ใ‚‰ใฎใฟๆŽฅ็ถšใ•ใ‚Œใ‚‹ๅ ดๅˆใ€ใƒ—ใƒญใ‚ญใ‚ทใฎ IP ใ‚’ๅ—ใ‘ๅ…ฅใ‚Œใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### HTTPS ใ‚’ไผดใ†ใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆ { #redirects-with-https } + +ไพ‹ใˆใฐใ€*path operation* `/items/` ใ‚’ๅฎš็พฉใ—ใฆใ„ใ‚‹ใจใ—ใพใ™: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ `/items` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ๆ—ขๅฎšใงใฏ `/items/` ใซใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ•ใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€*CLI ใ‚ชใƒ—ใ‚ทใƒงใƒณ* `--forwarded-allow-ips` ใ‚’่จญๅฎšใ™ใ‚‹ๅ‰ใฏใ€`http://localhost:8000/items/` ใซใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ•ใ‚Œใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใงใ™ใŒใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏ `https://mysuperapp.com` ใงๅ…ฌ้–‹ใ•ใ‚ŒใฆใŠใ‚Šใ€`https://mysuperapp.com/items/` ใซใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ•ใ‚Œใ‚‹ในใใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +`--proxy-headers` ใ‚’่จญๅฎšใ™ใ‚‹ใจใ€FastAPI ใฏๆญฃใ—ใ„ๅ ดๆ‰€ใซใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +HTTPS ใซใคใ„ใฆ่ฉณใ—ใ็Ÿฅใ‚ŠใŸใ„ๅ ดๅˆใฏใ€[HTTPS ใซใคใ„ใฆ](../deployment/https.md){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +### ใƒ—ใƒญใ‚ญใ‚ท่ปข้€ใƒ˜ใƒƒใƒ€ใƒผใฎไป•็ต„ใฟ { #how-proxy-forwarded-headers-work } + +ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใจ **ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ** ใฎ้–“ใงใ€**ใƒ—ใƒญใ‚ญใ‚ท** ใŒใฉใฎใ‚ˆใ†ใซ่ปข้€ใƒ˜ใƒƒใƒ€ใƒผใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ‹ใ‚’ๅ›ณ็คบใ—ใพใ™: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**ใƒ—ใƒญใ‚ญใ‚ท** ใฏๅ…ƒใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใƒผ** ใซๆธกใ™ๅ‰ใซ็‰นๅˆฅใชใ€Œ่ปข้€ใ€ใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ`X-Forwarded-*`๏ผ‰ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใƒ˜ใƒƒใƒ€ใƒผใฏใ€้€šๅธธใฏๅคฑใ‚ใ‚Œใ‚‹ๅ…ƒใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๆƒ…ๅ ฑใ‚’ไฟๆŒใ—ใพใ™: + +* **X-Forwarded-For**: ๅ…ƒใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎ IP ใ‚ขใƒ‰ใƒฌใ‚น +* **X-Forwarded-Proto**: ๅ…ƒใฎใƒ—ใƒญใƒˆใ‚ณใƒซ๏ผˆ`https`๏ผ‰ +* **X-Forwarded-Host**: ๅ…ƒใฎใƒ›ใ‚นใƒˆ๏ผˆ`mysuperapp.com`๏ผ‰ + +**FastAPI CLI** ใ‚’ `--forwarded-allow-ips` ใง่จญๅฎšใ™ใ‚‹ใจใ€ใ“ใ‚Œใ‚‰ใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฟก้ ผใ—ใฆไฝฟ็”จใ—ใ€ใŸใจใˆใฐใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใงๆญฃใ—ใ„ URL ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ + +## ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ท { #proxy-with-a-stripped-path-prefix } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไป˜ไธŽใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใ‚’ไฝฟใ†ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใฎใ‚ˆใ†ใชๅ ดๅˆใฏ `root_path` ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่จญๅฎšใงใใพใ™ใ€‚ + +`root_path` ใฏ๏ผˆFastAPI ใŒ Starlette ใ‚’้€šใ—ใฆๅŸบใฅใ„ใฆใ„ใ‚‹๏ผ‰ASGI ไป•ๆง˜ใงๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ไป•็ต„ใฟใงใ™ใ€‚ + +`root_path` ใฏใ“ใฎ็จฎใฎใ‚ฑใƒผใ‚นใ‚’ๆ‰ฑใ†ใŸใ‚ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆใ™ใ‚‹้š›ใซใ‚‚ๅ†…้ƒจ็š„ใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ“ใงใ„ใ†ใ€Œใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใ€ใจใฏใ€ใ‚ณใƒผใƒ‰ไธŠใงใฏ `/app` ใจใ„ใ†ใƒ‘ใ‚นใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใฆใ‚‚ใ€ใใฎไธŠใซใƒ—ใƒญใ‚ญใ‚ทๅฑคใ‚’่ฟฝๅŠ ใ—ใฆ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ `/api/v1` ใฎใ‚ˆใ†ใชใƒ‘ใ‚นใฎไธ‹ใซ้…็ฝฎใ™ใ‚‹ใ“ใจใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใ€ๅ…ƒใฎใƒ‘ใ‚น `/app` ใฏๅฎŸ้š›ใซใฏ `/api/v1/app` ใงๆไพ›ใ•ใ‚Œใพใ™ใ€‚ + +ใ™ในใฆใฎใ‚ณใƒผใƒ‰ใฏ `/app` ใ ใ‘ใ‚’ๅ‰ๆใซๆ›ธใ‹ใ‚Œใฆใ„ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€ใงใ™ใ€‚ + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +ใใ—ใฆใƒ—ใƒญใ‚ญใ‚ทใฏใ€ใ‚ขใƒ—ใƒชใ‚ตใƒผใƒใƒผ๏ผˆใŠใใ‚‰ใ FastAPI CLI ็ตŒ็”ฑใฎ Uvicorn๏ผ‰ใซ่ปข้€ใ™ใ‚‹ๅ‰ใซใ€ใใฎๅ ดใง **ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚น** ใ‚’**ใ€Œๅ‰Š้™คใ€**ใ—ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅดใซใฏ่‡ชๅˆ†ใŒ `/app` ใงๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใ›ใ‹ใ‘ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ณใƒผใƒ‰ใฎใ™ในใฆใ‚’ `/api/v1` ใฎใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นไป˜ใใซๆ›ธใๆ›ใˆใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใ“ใพใงใฏ้€šๅธธใฉใŠใ‚Šใซๅ‹•ไฝœใ—ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€็ตฑๅˆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI๏ผˆใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰๏ผ‰ใ‚’้–‹ใใจใ€OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’ `/api/v1/openapi.json` ใงใฏใชใ `/openapi.json` ใ‹ใ‚‰ๅ–ๅพ—ใ—ใ‚ˆใ†ใจใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰๏ผˆใƒ–ใƒฉใ‚ฆใ‚ถใงๅ‹•ไฝœ๏ผ‰ใฏ `/openapi.json` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใ‚ˆใ†ใจใ—ใฆใ€OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’ๅ–ๅพ—ใงใใพใ›ใ‚“ใ€‚ + +ใ“ใฎใ‚ขใƒ—ใƒชใซใฏ `/api/v1` ใฎใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไป˜ไธŽใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใŒใ‚ใ‚‹ใŸใ‚ใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใฏ `/api/v1/openapi.json` ใ‹ใ‚‰ๅ–ๅพ—ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +IP `0.0.0.0` ใฏใ€ใใฎใƒžใ‚ทใƒณ/ใ‚ตใƒผใƒใƒผใงๅˆฉ็”จๅฏ่ƒฝใชใ™ในใฆใฎ IP ใงๅพ…ใกๅ—ใ‘ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ™ใ‚‹่กจ็พใจใ—ใฆไธ€่ˆฌ็š„ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +/// + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใงใฏใ€ใ“ใฎ API ใฎ `server` ใŒ๏ผˆใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒใง๏ผ‰`/api/v1` ใซใ‚ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใ™ใ‚‹ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚‚ๅฟ…่ฆใงใ™ใ€‚ไพ‹ใˆใฐ: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // ใปใ‹ใฎ้ …็›ฎ + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // ใปใ‹ใฎ้ …็›ฎ + } +} +``` + +ใ“ใฎไพ‹ใงใฏใ€ŒProxyใ€ใฏ **Traefik** ใฎใ‚ˆใ†ใชใ‚‚ใฎใ€ใ‚ตใƒผใƒใƒผใฏ **Uvicorn** ใจ FastAPI CLI ใง FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ—ใฆใ„ใ‚‹ใ‚‚ใฎใ‚’ๆƒณๅฎšใ—ใฆใ„ใพใ™ใ€‚ + +### `root_path` ใฎๆŒ‡ๅฎš { #providing-the-root-path } + +ใ“ใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ€ๆฌกใฎใ‚ˆใ†ใซใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณ `--root-path` ใ‚’ไฝฟ็”จใ—ใพใ™: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Hypercorn ใ‚’ไฝฟใ†ๅ ดๅˆใ‚‚ใ€ๅŒๆง˜ใซ `--root-path` ใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ใ“ใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นๅ‘ใ‘ใซใ€ASGI ไป•ๆง˜ใฏ `root_path` ใ‚’ๅฎš็พฉใ—ใฆใ„ใพใ™ใ€‚ + +ใใ—ใฆ `--root-path` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใฏใ€ใใฎ `root_path` ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + +/// + +### ็พๅœจใฎ `root_path` ใฎ็ขบ่ช { #checking-the-current-root-path } + +ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒไฝฟ็”จใ—ใฆใ„ใ‚‹็พๅœจใฎ `root_path` ใฏๅ–ๅพ—ใงใใพใ™ใ€‚ใ“ใ‚Œใฏ๏ผˆASGI ไป•ๆง˜ใฎไธ€้ƒจใงใ‚ใ‚‹๏ผ‰`scope` ่พžๆ›ธใซๅซใพใ‚Œใพใ™ใ€‚ + +ใ“ใ“ใงใฏใƒ‡ใƒขใฎใŸใ‚ใ€ใƒกใƒƒใ‚ปใƒผใ‚ธใซๅซใ‚ใฆใ„ใพใ™ใ€‚ + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +ใใฎใ†ใˆใงใ€ๆฌกใฎใ‚ˆใ†ใซ Uvicorn ใ‚’่ตทๅ‹•ใ™ใ‚‹ใจ: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ใƒฌใ‚นใƒใƒณใ‚นใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### FastAPI ใ‚ขใƒ—ใƒชใงใฎ `root_path` ่จญๅฎš { #setting-the-root-path-in-the-fastapi-app } + +ใ‚ใ‚‹ใ„ใฏใ€`--root-path` ใฎใ‚ˆใ†ใชใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ๆธกใ›ใชใ„ๅ ดๅˆใฏใ€FastAPI ใ‚ขใƒ—ใƒชไฝœๆˆๆ™‚ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟ `root_path` ใ‚’่จญๅฎšใงใใพใ™: + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +`FastAPI` ใซ `root_path` ใ‚’ๆธกใ™ใฎใฏใ€Uvicorn ใ‚„ Hypercorn ใซใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณ `--root-path` ใ‚’ๆธกใ™ใฎใจๅŒ็ญ‰ใงใ™ใ€‚ + +### `root_path` ใซใคใ„ใฆ { #about-root-path } + +ใ‚ตใƒผใƒใƒผ๏ผˆUvicorn๏ผ‰ใฏใ€ใใฎ `root_path` ใ‚’ใ‚ขใƒ—ใƒชใซๆธกใ™ไปฅๅค–ใฎ็”จ้€”ใงใฏไฝฟ็”จใ—ใชใ„็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +ใ—ใ‹ใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/app ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€้€šๅธธใฉใŠใ‚Šใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ใคใพใ‚Šใ€`http://127.0.0.1:8000/api/v1/app` ใงใ‚ขใ‚ฏใ‚ปใ‚นใ•ใ‚Œใ‚‹ใ“ใจใฏๆƒณๅฎšใ—ใฆใ„ใพใ›ใ‚“ใ€‚ + +Uvicorn ใฏใ€ใƒ—ใƒญใ‚ญใ‚ทใŒ `http://127.0.0.1:8000/app` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใใ‚‹ใ“ใจใ‚’ๆƒณๅฎšใ—ใฆใŠใ‚Šใ€ใใฎไธŠใซ่ฟฝๅŠ ใฎ `/api/v1` ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไป˜ใ‘ใ‚‹ใฎใฏใƒ—ใƒญใ‚ญใ‚ทใฎ่ฒฌๅ‹™ใงใ™ใ€‚ + +## ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใซใคใ„ใฆ { #about-proxies-with-a-stripped-path-prefix } + +ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ™ใ‚‹ใƒ—ใƒญใ‚ญใ‚ทใฏใ€่จญๅฎšๆ–นๆณ•ใฎไธ€ไพ‹ใซใ™ใŽใชใ„็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +ๅคšใใฎๅ ดๅˆใ€ใƒ—ใƒญใ‚ญใ‚ทใฏใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ—ใชใ„่จญๅฎšใŒๆ—ขๅฎšใงใ—ใ‚‡ใ†ใ€‚ + +ใใฎใ‚ˆใ†ใชๅ ดๅˆ๏ผˆใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ—ใชใ„ๅ ดๅˆ๏ผ‰ใฏใ€ใƒ—ใƒญใ‚ญใ‚ทใฏ `https://myawesomeapp.com` ใฎใ‚ˆใ†ใชใ‚ขใƒ‰ใƒฌใ‚นใงๅพ…ใกๅ—ใ‘ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใŒ `https://myawesomeapp.com/api/v1/app` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใ€ใ‚ตใƒผใƒใƒผ๏ผˆไพ‹: Uvicorn๏ผ‰ใŒ `http://127.0.0.1:8000` ใงๅพ…ใกๅ—ใ‘ใฆใ„ใ‚‹ใชใ‚‰ใ€ใƒ—ใƒญใ‚ญใ‚ท๏ผˆใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ—ใชใ„๏ผ‰ใฏๅŒใ˜ใƒ‘ใ‚น `http://127.0.0.1:8000/api/v1/app` ใง Uvicorn ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ + +## Traefik ใ‚’ไฝฟใฃใŸใƒญใƒผใ‚ซใƒซๆคœ่จผ { #testing-locally-with-traefik } + +Traefik ใ‚’ไฝฟใˆใฐใ€ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ๅ‰Š้™คใ™ใ‚‹ๆง‹ๆˆใ‚’ใƒญใƒผใ‚ซใƒซใง็ฐกๅ˜ใซ่ฉฆใ›ใพใ™ใ€‚ + +Traefik ใ‚’ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ ใ—ใฆใใ ใ•ใ„ใ€‚ๅ˜ไธ€ใƒใ‚คใƒŠใƒชใชใฎใงใ€ๅœง็ธฎใƒ•ใ‚กใ‚คใƒซใ‚’ๅฑ•้–‹ใ—ใฆ็ซฏๆœซใ‹ใ‚‰็›ดๆŽฅๅฎŸ่กŒใงใใพใ™ใ€‚ + +ๆฌกใฎๅ†…ๅฎนใง `traefik.toml` ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใพใ™: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +ใ“ใ‚Œใฏ Traefik ใซใƒใƒผใƒˆ 9999 ใงๅพ…ใกๅ—ใ‘ใ€ๅˆฅใฎใƒ•ใ‚กใ‚คใƒซ `routes.toml` ใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ๆŒ‡็คบใ—ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆจ™ๆบ–ใฎ HTTP ใƒใƒผใƒˆ 80 ใงใฏใชใ 9999 ใ‚’ไฝฟใ†ใฎใฏใ€็ฎก็†่€…๏ผˆ`sudo`๏ผ‰ๆจฉ้™ใงๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใ‚’ใชใใ™ใŸใ‚ใงใ™ใ€‚ + +/// + +ๆฌกใซใ€ใใฎ `routes.toml` ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝœๆˆใ—ใพใ™: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏ Traefik ใซ `/api/v1` ใฎใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไฝฟใ†ใ‚ˆใ†่จญๅฎšใ—ใพใ™ใ€‚ + +ใใ—ใฆ Traefik ใฏใ€`http://127.0.0.1:8000` ใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹ Uvicorn ใธใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’่ปข้€ใ—ใพใ™ใ€‚ + +ใงใฏ Traefik ใ‚’่ตทๅ‹•ใ—ใพใ™: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +ๆฌกใซใ€`--root-path` ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ๆŒ‡ๅฎšใ—ใฆใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ—ใพใ™: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ใƒฌใ‚นใƒใƒณใ‚นใฎ็ขบ่ช { #check-the-responses } + +ใ“ใ“ใงใ€Uvicorn ใฎใƒใƒผใƒˆใฎ URL http://127.0.0.1:8000/app ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€้€šๅธธใฉใŠใ‚Šใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`http://127.0.0.1:8000/app` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใ„ใ‚‹ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณ `--root-path` ใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸ `root_path` ใŒ `/api/v1` ใจ่กจ็คบใ•ใ‚Œใฆใ„ใ‚‹็‚นใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +ๆฌกใซใ€Traefik ใฎใƒใƒผใƒˆใงใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นไป˜ใใฎ URL http://127.0.0.1:9999/api/v1/app ใ‚’้–‹ใใพใ™ใ€‚ + +ๅŒใ˜ใƒฌใ‚นใƒใƒณใ‚นใŒๅพ—ใ‚‰ใ‚Œใพใ™: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ใŸใ ใ—ไปŠๅ›žใฏใ€ใƒ—ใƒญใ‚ญใ‚ทใŒไป˜ไธŽใ—ใŸใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚น `/api/v1` ใฎไป˜ใ„ใŸ URL ใงใ™ใ€‚ + +ใ‚‚ใกใ‚ใ‚“ใ€ใ“ใ“ใงใฎๆƒณๅฎšใฏๅ…จๅ“กใŒใƒ—ใƒญใ‚ญใ‚ท็ตŒ็”ฑใงใ‚ขใƒ—ใƒชใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใ“ใจใงใ™ใ€‚ใ—ใŸใŒใฃใฆใ€ใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚น `/api/v1` ใฎใ‚ใ‚‹็‰ˆใŒใ€Œๆญฃใ—ใ„ใ€ใ‚ขใ‚ฏใ‚ปใ‚นๆ–นๆณ•ใซใชใ‚Šใพใ™ใ€‚ + +ไธ€ๆ–นใ€ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใฎใชใ„็‰ˆ๏ผˆ`http://127.0.0.1:8000/app`ใ€‚Uvicorn ใŒ็›ดๆŽฅๆไพ›๏ผ‰ใฏใ€_ใƒ—ใƒญใ‚ญใ‚ท_๏ผˆTraefik๏ผ‰ๅฐ‚็”จใฎๆŽฅ็ถšๅ…ˆใซใชใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒ—ใƒญใ‚ญใ‚ท๏ผˆTraefik๏ผ‰ใŒใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ใฉใฎใ‚ˆใ†ใซ็”จใ„ใ€ใ‚ตใƒผใƒใƒผ๏ผˆUvicorn๏ผ‰ใŒ `--root-path` ใฎ `root_path` ใ‚’ใฉใฎใ‚ˆใ†ใซๅˆฉ็”จใ™ใ‚‹ใ‹ใŒๅˆ†ใ‹ใ‚Šใพใ™ใ€‚ + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใฎ็ขบ่ช { #check-the-docs-ui } + +ใ“ใ“ใŒใƒใ‚คใƒณใƒˆใงใ™ใ€‚โœจ + +ใ€Œๅ…ฌๅผใชใ€ใ‚ขใ‚ฏใ‚ปใ‚นๆ–นๆณ•ใฏใ€ๅฎš็พฉใ—ใŸใƒ‘ใ‚นใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นไป˜ใใฎใƒ—ใƒญใ‚ญใ‚ท็ตŒ็”ฑใงใ™ใ€‚ใ—ใŸใŒใฃใฆๆƒณๅฎšใฉใŠใ‚Šใ€ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใชใ—ใฎ URL ใง Uvicorn ใŒ็›ดๆŽฅๆไพ›ใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจๅ‹•ไฝœใ—ใพใ›ใ‚“ใ€‚ใƒ—ใƒญใ‚ญใ‚ท็ตŒ็”ฑใงใ‚ขใ‚ฏใ‚ปใ‚นใ•ใ‚Œใ‚‹ใ“ใจใ‚’ๅ‰ๆใจใ—ใฆใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +http://127.0.0.1:8000/docs ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„: + + + +ใ—ใ‹ใ—ใ€ใƒ—ใƒญใ‚ญใ‚ท๏ผˆใƒใƒผใƒˆ `9999`๏ผ‰ใ‚’ไฝฟใฃใŸใ€Œๅ…ฌๅผใ€URL `/api/v1/docs` ใงใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ๆญฃใ—ใๅ‹•ไฝœใ—ใพใ™๏ผ๐ŸŽ‰ + +http://127.0.0.1:9999/api/v1/docs ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„: + + + +ใญใ‚‰ใ„ใฉใŠใ‚Šใงใ™ใ€‚โœ”๏ธ + +ใ“ใ‚Œใฏใ€FastAPI ใŒ `root_path` ใ‚’ไฝฟใฃใฆใ€OpenAPI ใฎๆ—ขๅฎšใฎ `server` ใ‚’ `root_path` ใฎ URL ใง็”Ÿๆˆใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +## ่ฟฝๅŠ ใฎใ‚ตใƒผใƒใƒผ { #additional-servers } + +/// warning | ๆณจๆ„ + +ใ“ใ‚Œใฏ้ซ˜ๅบฆใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใ™ใ€‚่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +/// + +ๆ—ขๅฎšใงใฏใ€**FastAPI** ใฏ OpenAPI ใ‚นใ‚ญใƒผใƒžๅ†…ใซ `root_path` ใฎ URL ใ‚’ๆŒใค `server` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใ‚นใƒ†ใƒผใ‚ธใƒณใ‚ฐใจๆœฌ็•ชใฎไธกๆ–นใจๅŒใ˜ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใงๅฏพ่ฉฑใ•ใ›ใŸใ„ๅ ดๅˆใชใฉใ€ๅˆฅใฎ `servers` ใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใ‚ซใ‚นใ‚ฟใƒ ใฎ `servers` ใƒชใ‚นใƒˆใ‚’ๆธกใ—ใฆใ„ใฆใ€ใ‹ใค `root_path`๏ผˆAPI ใŒใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒใซใ‚ใ‚‹ใŸใ‚๏ผ‰ใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€**FastAPI** ใฏใ“ใฎ `root_path` ใ‚’็”จใ„ใŸใ€Œserverใ€ใ‚’ใƒชใ‚นใƒˆใฎๅ…ˆ้ ญใซๆŒฟๅ…ฅใ—ใพใ™ใ€‚ + +ไพ‹ใˆใฐ: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +ๆฌกใฎใ‚ˆใ†ใช OpenAPI ใ‚นใ‚ญใƒผใƒžใŒ็”Ÿๆˆใ•ใ‚Œใพใ™: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // ใปใ‹ใฎ้ …็›ฎ + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // ใปใ‹ใฎ้ …็›ฎ + } +} +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`root_path` ใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸ `url` ๅ€ค `/api/v1` ใ‚’ๆŒใค server ใŒ่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใฆใ„ใ‚‹็‚นใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI๏ผˆhttp://127.0.0.1:9999/api/v1/docs๏ผ‰ใงใฏๆฌกใฎใ‚ˆใ†ใซ่กจ็คบใ•ใ‚Œใพใ™: + + + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใฏใ€้ธๆŠžใ—ใŸ server ใจๅฏพ่ฉฑใ—ใพใ™ใ€‚ + +/// + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +OpenAPI ไป•ๆง˜ใฎ `servers` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃใฏไปปๆ„ใงใ™ใ€‚ + +`servers` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒ‡ๅฎšใ›ใšใ€ใ‹ใค `root_path` ใŒ `/` ใฎๅ ดๅˆใ€็”Ÿๆˆใ•ใ‚Œใ‚‹ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‹ใ‚‰ใฏ `servers` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃใŒๆ—ขๅฎšใงๅฎŒๅ…จใซ็œ็•ฅใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏใ€`url` ใŒ `/` ใฎ server ใŒ 1 ใคใ‚ใ‚‹ใฎใจๅŒ็ญ‰ใงใ™ใ€‚ + +/// + +### `root_path` ็”ฑๆฅใฎ่‡ชๅ‹• server ใ‚’็„กๅŠนๅŒ– { #disable-automatic-server-from-root-path } + +`root_path` ใ‚’็”จใ„ใŸ่‡ชๅ‹•็š„ใช server ใ‚’ **FastAPI** ใซๅซใ‚ใฆใปใ—ใใชใ„ๅ ดๅˆใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `root_path_in_servers=False` ใ‚’ไฝฟ็”จใ—ใพใ™: + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +ใ™ใ‚‹ใจใ€OpenAPI ใ‚นใ‚ญใƒผใƒžใซใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚ + +## ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒžใ‚ฆใƒณใƒˆ { #mounting-a-sub-application } + +`root_path` ใ‚’ไผดใ†ใƒ—ใƒญใ‚ญใ‚ทใ‚’ไฝฟ็”จใ—ใคใคใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใงใ‚‚๏ผˆ[ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒžใ‚ฆใƒณใƒˆ](sub-applications.md){.internal-link target=_blank} ๅ‚็…ง๏ผ‰ใ€้€šๅธธใฉใŠใ‚Šใซ่กŒใˆใพใ™ใ€‚ + +FastAPI ใฏๅ†…้ƒจใง `root_path` ใ‚’้ฉๅˆ‡ใซๆ‰ฑใ†ใŸใ‚ใ€ใใฎใพใพๅ‹•ไฝœใ—ใพใ™ใ€‚โœจ diff --git a/docs/ja/docs/advanced/custom-response.md b/docs/ja/docs/advanced/custom-response.md index 9d881c013c..50a7891658 100644 --- a/docs/ja/docs/advanced/custom-response.md +++ b/docs/ja/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ ใ—ใ‹ใ—ใ€่ฟ”ใใ†ใจใ—ใฆใ„ใ‚‹ใ‚ณใƒณใƒ†ใƒณใƒ„ใŒ **JSONใงใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บๅฏ่ƒฝ**ใงใ‚ใ‚‹ใ“ใจใŒ็ขบๅฎŸใชใ‚‰ใ€ใใ‚Œใ‚’็›ดๆŽฅใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใซๆธกใ—ใฆใ€FastAPIใŒใƒฌใ‚นใƒใƒณใ‚นใ‚ฏใƒฉใ‚นใธๆธกใ™ๅ‰ใซ่ฟ”ๅดใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ `jsonable_encoder` ใซ้€šใ™ใ“ใจใง็™บ็”Ÿใ™ใ‚‹่ฟฝๅŠ ใฎใ‚ชใƒผใƒใƒผใƒ˜ใƒƒใƒ‰ใ‚’ๅ›ž้ฟใงใใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | ๆƒ…ๅ ฑ @@ -55,7 +55,7 @@ * `HTMLResponse` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ€‚ * *path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `response_class` ใซ `HTMLResponse` ใ‚’ๆธกใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | ๆƒ…ๅ ฑ @@ -73,7 +73,7 @@ ไธŠ่จ˜ใจๅŒใ˜ไพ‹ใซใŠใ„ใฆใ€ `HTMLResponse` ใ‚’่ฟ”ใ™ใจใ€ใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | ๆณจๆ„ @@ -97,7 +97,7 @@ ไพ‹ใˆใฐใ€ใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} ใ“ใฎไพ‹ใงใฏใ€้–ขๆ•ฐ `generate_html_response()` ใฏใ€`str` ใฎHTMLใ‚’่ฟ”ใ™ใฎใงใฏใชใใ€`Response` ใ‚’็”Ÿๆˆใ—ใฆ่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ @@ -136,7 +136,7 @@ FastAPI๏ผˆๅฎŸ้š›ใซใฏStarlette๏ผ‰ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใพใ™ใ€‚ใพใŸใ€`media_type` ใซๅŸบใฅใ„ใŸContent-Typeใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใฟใ€ใƒ†ใ‚ญใ‚นใƒˆใ‚ฟใ‚คใƒ—ใฎใŸใ‚ใซcharsetใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ FastAPI๏ผˆๅฎŸ้š›ใซใฏStarlette๏ผ‰ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ ใƒ†ใ‚ญใ‚นใƒˆใ‚„ใƒใ‚คใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒ—ใƒฌใƒผใƒณใƒ†ใ‚ญใ‚นใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ FastAPI๏ผˆๅฎŸ้š›ใซใฏStarlette๏ผ‰ใฏ่‡ชๅ‹•็š„ใซContent-Lengthใƒ˜ใƒƒใƒ€ใƒผใ‚’ /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -194,13 +194,13 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น `RedirectResponse` ใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™: -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- ใพใŸใฏใ€`response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงไฝฟ็”จใงใใพใ™: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} ใใฎๅ ดๅˆใ€*path operation*้–ขๆ•ฐใ‹ใ‚‰URLใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™ใ€‚ @@ -210,13 +210,13 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น ใพใŸใ€`status_code` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจ็ต„ใฟๅˆใ‚ใ›ใฆไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } ้žๅŒๆœŸใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใ€ใพใŸใฏ้€šๅธธใฎใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ/ใ‚คใƒ†ใƒฌใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใƒœใƒ‡ใ‚ฃใ‚’ใ‚นใƒˆใƒชใƒผใƒ ใ—ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### ใƒ•ใ‚กใ‚คใƒซใƒฉใ‚คใ‚ฏใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใง `StreamingResponse` ใ‚’ไฝฟใ† { #using-streamingresponse-with-file-like-objects } @@ -226,7 +226,7 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น ใ“ใ‚Œใซใฏใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚นใƒˆใƒฌใƒผใ‚ธใจใฎ้€ฃๆบใ€ๆ˜ ๅƒๅ‡ฆ็†ใชใฉใ€ๅคšใใฎใƒฉใ‚คใƒ–ใƒฉใƒชใŒๅซใพใ‚Œใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. ใ“ใ‚Œใฏใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใงใ™ใ€‚ๅ†…้ƒจใซ `yield` ๆ–‡ใ‚’ๅซใ‚€ใŸใ‚ใ€Œใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใ€ใงใ™ใ€‚ 2. `with` ใƒ–ใƒญใƒƒใ‚ฏใ‚’ไฝฟใ†ใ“ใจใงใ€ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ้–ขๆ•ฐใŒ็ต‚ใ‚ใฃใŸๅพŒ๏ผˆใคใพใ‚Šใƒฌใ‚นใƒใƒณใ‚นใฎ้€ไฟกใŒๅฎŒไบ†ใ—ใŸๅพŒ๏ผ‰ใซfile-likeใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒ็ขบๅฎŸใซใ‚ฏใƒญใƒผใ‚บใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ @@ -255,11 +255,11 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น ใƒ•ใ‚กใ‚คใƒซใƒฌใ‚นใƒใƒณใ‚นใซใฏใ€้ฉๅˆ‡ใช `Content-Length`ใ€`Last-Modified`ใ€`ETag` ใƒ˜ใƒƒใƒ€ใƒผใŒๅซใพใ‚Œใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} `response_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} ใ“ใฎๅ ดๅˆใ€*path operation*้–ขๆ•ฐใ‹ใ‚‰ใƒ•ใ‚กใ‚คใƒซใƒ‘ใ‚นใ‚’็›ดๆŽฅ่ฟ”ใ›ใพใ™ใ€‚ @@ -273,7 +273,7 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น `CustomORJSONResponse` ใ‚’ไฝœใ‚Œใพใ™ใ€‚ไธปใซๅฟ…่ฆใชใฎใฏใ€ใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ `bytes` ใจใ—ใฆ่ฟ”ใ™ `Response.render(content)` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝœใ‚‹ใ“ใจใงใ™: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} ใ“ใ‚Œใพใงใฏๆฌกใฎใ‚ˆใ†ใซ่ฟ”ใ—ใฆใ„ใŸใ‚‚ใฎใŒ: @@ -299,7 +299,7 @@ HTTPใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ307ใ‚นใƒ†ใƒผใ‚ฟใ‚น ไปฅไธ‹ใฎไพ‹ใงใฏใ€**FastAPI** ใฏใ™ในใฆใฎ*path operation*ใงใ€`JSONResponse` ใฎไปฃใ‚ใ‚Šใซ `ORJSONResponse` ใ‚’ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใจใ—ใฆไฝฟใ„ใพใ™ใ€‚ -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ diff --git a/docs/ja/docs/advanced/dataclasses.md b/docs/ja/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..74f479f072 --- /dev/null +++ b/docs/ja/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Dataclasses ใฎไฝฟ็”จ { #using-dataclasses } + +FastAPI ใฏ **Pydantic** ใฎไธŠใซๆง‹็ฏ‰ใ•ใ‚ŒใฆใŠใ‚Šใ€ใ“ใ‚Œใพใงใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚„ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟใ†ๆ–นๆณ•ใ‚’็ดนไป‹ใ—ใฆใใพใ—ใŸใ€‚ + +ใ—ใ‹ใ— FastAPI ใฏใ€ๅŒๆง˜ใฎๆ–นๆณ•ใง `dataclasses` ใ‚‚ใ‚ตใƒใƒผใƒˆใ—ใพใ™: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +ใ“ใ‚Œใฏ **Pydantic** ใซใ‚ˆใฃใฆๅผ•ใ็ถšใใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚Pydantic ใซใฏ `dataclasses` ใฎๅ†…้ƒจใ‚ตใƒใƒผใƒˆ ใŒใ‚ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใใฎใŸใ‚ใ€ไธŠ่จ˜ใฎใ‚ˆใ†ใซๆ˜Ž็คบ็š„ใซ Pydantic ใ‚’ไฝฟใฃใฆใ„ใชใ„ใ‚ณใƒผใƒ‰ใงใ‚‚ใ€FastAPI ใฏๆจ™ๆบ–ใฎ dataclass ใ‚’ Pydantic ็‹ฌ่‡ชใฎ dataclass ใซๅค‰ๆ›ใ™ใ‚‹ใŸใ‚ใซ Pydantic ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + +ใใ—ใฆๅฝ“็„ถใชใŒใ‚‰ใ€ๆฌกใฎ็‚นใ‚‚ๅŒๆง˜ใซใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ™: + +- ใƒ‡ใƒผใ‚ฟๆคœ่จผ +- ใƒ‡ใƒผใ‚ฟใฎใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บ +- ใƒ‡ใƒผใ‚ฟใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ– ใชใฉ + +ใ“ใ‚Œใฏ Pydantic ใƒขใƒ‡ใƒซใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ๅ†…้ƒจ็š„ใซใ‚‚ๅŒๆง˜ใซ Pydantic ใ‚’ไฝฟใฃใฆๅฎŸ็พใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +dataclasses ใฏใ€Pydantic ใƒขใƒ‡ใƒซใŒใงใใ‚‹ใ“ใจใ‚’ใ™ในใฆใฏ่กŒใˆใชใ„็‚นใซ็•™ๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +ใใฎใŸใ‚ใ€Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +ใ—ใ‹ใ—ๆ—ขๅญ˜ใฎ dataclass ใŒๅคšๆ•ฐใ‚ใ‚‹ใชใ‚‰ใ€FastAPI ใง Web API ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹้š›ใซใใ‚Œใ‚‰ใ‚’ๆดป็”จใ™ใ‚‹ใกใ‚‡ใฃใจใ—ใŸใƒ†ใ‚ฏใƒ‹ใƒƒใ‚ฏใซใชใ‚Šใพใ™ใ€‚๐Ÿค“ + +/// + +## `response_model` ใงใฎ dataclasses { #dataclasses-in-response-model } + +`response_model` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚‚ `dataclasses` ใ‚’ไฝฟ็”จใงใใพใ™: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +dataclass ใฏ่‡ชๅ‹•็š„ใซ Pydantic ใฎ dataclass ใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใฎใŸใ‚ใ€ใใฎใ‚นใ‚ญใƒผใƒžใฏ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ UI ใซ่กจ็คบใ•ใ‚Œใพใ™: + + + +## ใƒใ‚นใƒˆใ—ใŸใƒ‡ใƒผใ‚ฟๆง‹้€ ใงใฎ dataclasses { #dataclasses-in-nested-data-structures } + +`dataclasses` ใ‚’ไป–ใฎๅž‹ๆณจ้‡ˆใจ็ต„ใฟๅˆใ‚ใ›ใฆใ€ใƒใ‚นใƒˆใ—ใŸใƒ‡ใƒผใ‚ฟๆง‹้€ ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ + +ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ™ใ‚‹ใชใฉใฎ็†็”ฑใงใ€Pydantic ็‰ˆใฎ `dataclasses` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใใฎๅ ดๅˆใฏใ€ๆจ™ๆบ–ใฎ `dataclasses` ใ‚’ `pydantic.dataclasses` ใซ็ฝฎใๆ›ใˆใ‚‹ใ ใ‘ใงๆธˆใฟใพใ™ใ€‚ใ“ใ‚Œใฏใƒ‰ใƒญใƒƒใƒ—ใ‚คใƒณ็ฝฎๆ›ใงใ™: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. ไพ็„ถใจใ—ใฆๆจ™ๆบ–ใฎ `dataclasses` ใ‹ใ‚‰ `field` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ + +2. `pydantic.dataclasses` ใฏ `dataclasses` ใฎใƒ‰ใƒญใƒƒใƒ—ใ‚คใƒณ็ฝฎๆ›ใงใ™ใ€‚ + +3. `Author` dataclass ใฏ `Item` dataclass ใฎใƒชใ‚นใƒˆใ‚’ๅซใฟใพใ™ใ€‚ + +4. `Author` dataclass ใ‚’ `response_model` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + +5. ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใจใ—ใฆใฎ dataclass ใจไฝตใ›ใฆใ€ไป–ใฎๆจ™ๆบ–ใฎๅž‹ๆณจ้‡ˆใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + + ใ“ใฎไพ‹ใงใฏใ€`Item` dataclass ใฎใƒชใ‚นใƒˆใงใ™ใ€‚ + +6. ใ“ใ“ใงใฏใ€dataclass ใฎใƒชใ‚นใƒˆใงใ‚ใ‚‹ `items` ใ‚’ๅซใ‚€่พžๆ›ธใ‚’่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ + + FastAPI ใฏใƒ‡ใƒผใ‚ฟใ‚’ JSON ใซ ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บ ใงใใพใ™ใ€‚ + +7. ใ“ใ“ใงใฏ `response_model` ใซ `Author` dataclass ใฎใƒชใ‚นใƒˆใจใ„ใ†ๅž‹ๆณจ้‡ˆใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + + ใ“ใฎใ‚ˆใ†ใซใ€`dataclasses` ใฏๆจ™ๆบ–ใฎๅž‹ๆณจ้‡ˆใจ็ต„ใฟๅˆใ‚ใ›ใ‚‰ใ‚Œใพใ™ใ€‚ + +8. ใ“ใฎ *path operation ้–ขๆ•ฐ* ใฏใ€`async def` ใงใฏใชใ้€šๅธธใฎ `def` ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + + ใ„ใคใ‚‚ใฉใŠใ‚Šใ€FastAPI ใงใฏๅฟ…่ฆใซๅฟœใ˜ใฆ `def` ใจ `async def` ใ‚’็ต„ใฟๅˆใ‚ใ›ใ‚‰ใ‚Œใพใ™ใ€‚ + + ใฉใกใ‚‰ใ‚’ใ„ใคไฝฟใ†ใ‹ใฎๅพฉ็ฟ’ใŒๅฟ…่ฆใชๅ ดๅˆใฏใ€[`async` ใจ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ _"In a hurry?"_ ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +9. ใ“ใฎ *path operation ้–ขๆ•ฐ* ใฏ๏ผˆๅฏ่ƒฝใงใฏใ‚ใ‚Šใพใ™ใŒ๏ผ‰dataclass ่‡ชไฝ“ใฏ่ฟ”ใ•ใšใ€ๅ†…้ƒจใƒ‡ใƒผใ‚ฟใ‚’ๆŒใค่พžๆ›ธใฎใƒชใ‚นใƒˆใ‚’่ฟ”ใ—ใฆใ„ใพใ™ใ€‚ + + FastAPI ใฏ dataclass ใ‚’ๅซใ‚€ `response_model` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใฃใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅค‰ๆ›ใ—ใพใ™ใ€‚ + +`dataclasses` ใฏไป–ใฎๅž‹ๆณจ้‡ˆใจๅคšๆง˜ใช็ต„ใฟๅˆใ‚ใ›ใŒๅฏ่ƒฝใงใ€่ค‡้›‘ใชใƒ‡ใƒผใ‚ฟๆง‹้€ ใ‚’ๆง‹ๆˆใงใใพใ™ใ€‚ + +ไธŠ่จ˜ใฎใ‚ณใƒผใƒ‰ๅ†…ใ‚ณใƒกใƒณใƒˆใฎใƒ’ใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใ€ใ‚ˆใ‚Šๅ…ทไฝ“็š„ใช่ฉณ็ดฐใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใ•ใ‚‰ใซๅญฆใถ { #learn-more } + +`dataclasses` ใ‚’ไป–ใฎ Pydantic ใƒขใƒ‡ใƒซใจ็ต„ใฟๅˆใ‚ใ›ใŸใ‚Šใ€็ถ™ๆ‰ฟใ—ใŸใ‚Šใ€่‡ชๅˆ†ใฎใƒขใƒ‡ใƒซใซๅซใ‚ใŸใ‚Šใ‚‚ใงใใพใ™ใ€‚ + +่ฉณใ—ใใฏใ€dataclasses ใซ้–ขใ™ใ‚‹ Pydantic ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใƒใƒผใ‚ธใƒงใƒณ { #version } + +ใ“ใ‚Œใฏ FastAPI ใƒใƒผใ‚ธใƒงใƒณ `0.67.0` ไปฅ้™ใงๅˆฉ็”จๅฏ่ƒฝใงใ™ใ€‚๐Ÿ”– diff --git a/docs/ja/docs/advanced/events.md b/docs/ja/docs/advanced/events.md new file mode 100644 index 0000000000..fb79062fa8 --- /dev/null +++ b/docs/ja/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan ใ‚คใƒ™ใƒณใƒˆ { #lifespan-events } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่ตทๅ‹•ใ™ใ‚‹ๅ‰ใซไธ€ๅบฆใ ใ‘ๅฎŸ่กŒใ™ในใใƒญใ‚ธใƒƒใ‚ฏ๏ผˆใ‚ณใƒผใƒ‰๏ผ‰ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šๅง‹ใ‚ใ‚‹ๅ‰ใซใ€ใใฎใ‚ณใƒผใƒ‰ใŒไธ€ๅบฆใ ใ‘ๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใ™ใ€‚ + +ๅŒๆง˜ใซใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ™ใ‚‹ใจใใซๅฎŸ่กŒใ™ในใใƒญใ‚ธใƒƒใ‚ฏ๏ผˆใ‚ณใƒผใƒ‰๏ผ‰ใ‚‚ๅฎš็พฉใงใใพใ™ใ€‚ใ“ใฎๅ ดๅˆใ€ใใฎใ‚ณใƒผใƒ‰ใฏใ€๏ผˆๅคšใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ—ใŸ๏ผ‰ๅพŒใซไธ€ๅบฆใ ใ‘ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ—ใ‘ไป˜ใ‘ใ‚’ใ€Œ้–‹ๅง‹ใ€ใ™ใ‚‹ๅ‰ใ€ใใ—ใฆๅ‡ฆ็†ใ‚’ใ€Œ็ต‚ไบ†ใ€ใ—ใŸ็›ดๅพŒใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใŸใ‚ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ…จไฝ“ใฎใ€ŒLifespanใ€๏ผˆใ“ใฎใ€Œlifespanใ€ใจใ„ใ†่จ€่‘‰ใฏใ™ใๅพŒใง้‡่ฆใซใชใ‚Šใพใ™ ๐Ÿ˜‰๏ผ‰ใ‚’ใ‚ซใƒใƒผใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใ‚ขใƒ—ใƒชๅ…จไฝ“ใงไฝฟ็”จใ—ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆ้–“ใงใ€Œๅ…ฑๆœ‰ใ€ใ—ใ€ใ‹ใคๅพŒใงใ€Œใ‚ฏใƒชใƒผใƒณใ‚ขใƒƒใƒ—ใ€ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‚ˆใ†ใชใ€Œใƒชใ‚ฝใƒผใ‚นใ€ใ‚’ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ™ใ‚‹ใฎใซใจใฆใ‚‚ไพฟๅˆฉใงใ™ใ€‚ใŸใจใˆใฐใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆŽฅ็ถšใƒ—ใƒผใƒซใ‚„ใ€ๅ…ฑๆœ‰ใฎๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใฎ่ชญใฟ่พผใฟใชใฉใงใ™ใ€‚ + +## ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น { #use-case } + +ใพใšใฏใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใฎไพ‹ใ‹ใ‚‰ๅง‹ใ‚ใฆใ€ใ“ใ‚Œใ‚’ใฉใฎใ‚ˆใ†ใซ่งฃๆฑบใ™ใ‚‹ใ‹ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ—ใŸใ„ใ€ŒๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใ€ใŒใ„ใใคใ‹ใ‚ใ‚‹ใจๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚๐Ÿค– + +ๅŒใ˜ใƒขใƒ‡ใƒซใ‚’ใƒชใ‚ฏใ‚จใ‚นใƒˆ้–“ใงๅ…ฑๆœ‰ใ™ใ‚‹ใฎใงใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใ‚„ใƒฆใƒผใ‚ถใƒผใ”ใจใซๅˆฅใ€…ใฎใƒขใƒ‡ใƒซใ‚’ไฝฟใ†ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใƒขใƒ‡ใƒซใฎ่ชญใฟ่พผใฟใซใฏใƒ‡ใ‚ฃใ‚นใ‚ฏใ‹ใ‚‰ๅคง้‡ใฎใƒ‡ใƒผใ‚ฟใ‚’่ชญใ‚€ๅฟ…่ฆใŒใ‚ใ‚Šใ€ใ‹ใชใ‚Šๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ—ใŸใŒใฃใฆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ่ชญใฟ่พผใฟใŸใใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใƒขใ‚ธใƒฅใƒผใƒซ/ใƒ•ใ‚กใ‚คใƒซใฎใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซใง่ชญใฟ่พผใ‚€ใ“ใจใ‚‚ใงใใพใ™ใŒใ€ใใฎๅ ดๅˆใฏใ€ใŸใจใˆ็ฐกๅ˜ใช่‡ชๅ‹•ใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ™ใ‚‹ใ ใ‘ใงใ‚‚ใ€Œใƒขใƒ‡ใƒซใ‚’่ชญใฟ่พผใ‚€ใ€ใ“ใจใซใชใ‚Šใ€ใใฎใƒขใƒ‡ใƒซใฎ่ชญใฟ่พผใฟใ‚’ๅพ…ใคๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€็‹ฌ็ซ‹ใ—ใŸใ‚ณใƒผใƒ‰้ƒจๅˆ†ใ‚’่ตฐใ‚‰ใ›ใ‚‹ใ ใ‘ใฎใƒ†ใ‚นใƒˆใงใ‚‚ใ€Œ้…ใใ€ใชใฃใฆใ—ใพใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚’่งฃๆฑบใ—ใพใ—ใ‚‡ใ†ใ€‚ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹ๅ‰ใซใƒขใƒ‡ใƒซใ‚’่ชญใฟ่พผใฟใพใ™ใŒใ€ใ‚ณใƒผใƒ‰ใŒใƒญใƒผใƒ‰ใ•ใ‚Œใฆใ„ใ‚‹ๆœ€ไธญใงใฏใชใใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ—ใ‘ไป˜ใ‘ใ‚’้–‹ๅง‹ใ™ใ‚‹็›ดๅ‰ใ ใ‘ใซใ—ใพใ™ใ€‚ + +## Lifespan { #lifespan } + +ใ“ใฎใ€Œ่ตทๅ‹•ๆ™‚ใ€ใจใ€Œใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณๆ™‚ใ€ใฎใƒญใ‚ธใƒƒใ‚ฏใฏใ€`FastAPI` ใ‚ขใƒ—ใƒชใฎ `lifespan` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ€Œใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€๏ผˆใ“ใ‚ŒใŒไฝ•ใ‹ใฏใ™ใใซ็คบใ—ใพใ™๏ผ‰ใ‚’ไฝฟใฃใฆๅฎš็พฉใงใใพใ™ใ€‚ + +ใพใšใฏไพ‹ใ‚’่ฆ‹ใฆใ‹ใ‚‰ใ€่ฉณ็ดฐใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใซใ€`yield` ใ‚’ไฝฟใ†้žๅŒๆœŸ้–ขๆ•ฐ `lifespan()` ใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +ใ“ใ“ใงใฏใ€`yield` ใฎๅ‰ใงๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใฎ่พžๆ›ธใซ๏ผˆใƒ€ใƒŸใƒผใฎ๏ผ‰ใƒขใƒ‡ใƒซ้–ขๆ•ฐใ‚’ๅ…ฅใ‚Œใ‚‹ใ“ใจใงใ€้ซ˜ใ‚ณใ‚นใƒˆใชใ€Œ่ตทๅ‹•ๆ™‚ใ€ใฎใƒขใƒ‡ใƒซ่ชญใฟ่พผใฟใ‚’ใ‚ทใƒŸใƒฅใƒฌใƒผใ‚ทใƒงใƒณใ—ใฆใ„ใพใ™ใ€‚ใ“ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใ€Œๅ—ใ‘ไป˜ใ‘ๅง‹ใ‚ใ‚‹ๅ‰ใ€ใซใ€ใ™ใชใ‚ใก่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ใใ—ใฆ `yield` ใฎ็›ดๅพŒใงใƒขใƒ‡ใƒซใ‚’ใ‚ขใƒณใƒญใƒผใƒ‰ใ—ใพใ™ใ€‚ใ“ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใƒชใ‚ฏใ‚จใ‚นใƒˆๅ‡ฆ็†ใ‚’ใ€Œ็ต‚ไบ†ใ€ใ—ใŸๅพŒใ€ใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณ็›ดๅ‰ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ใŸใจใˆใฐใƒกใƒขใƒชใ‚„ GPU ใฎใ‚ˆใ†ใชใƒชใ‚ฝใƒผใ‚นใ‚’่งฃๆ”พใงใใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`shutdown` ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใ€Œๅœๆญขใ€ใ™ใ‚‹ใจใใซ็™บ็”Ÿใ—ใพใ™ใ€‚ + +ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณใ‚’้–‹ๅง‹ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ€ๅ˜ใซๅฎŸ่กŒใ‚’ใ‚„ใ‚ใŸใใชใฃใŸใฎใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿคท + +/// + +### Lifespan ้–ขๆ•ฐ { #lifespan-function } + +ใพใšๆณจ็›ฎใ™ในใใฏใ€`yield` ใ‚’ไฝฟใ†้žๅŒๆœŸ้–ขๆ•ฐใ‚’ๅฎš็พฉใ—ใฆใ„ใ‚‹ใ“ใจใงใ™ใ€‚ใ“ใ‚Œใฏใ€Œyield ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚๏ผˆDependencies๏ผ‰ใ€ใซใจใฆใ‚‚ใ‚ˆใไผผใฆใ„ใพใ™ใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +`yield` ใฎๅ‰ใฎๅ‰ๅŠใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ้–‹ๅง‹ใ•ใ‚Œใ‚‹ใ€Œๅ‰ใ€ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +`yield` ใฎๅพŒๅŠใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎๅ‡ฆ็†ใŒใ€Œ็ต‚ไบ†ใ€ใ—ใŸใ€ŒๅพŒใ€ใซๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +### ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ { #async-context-manager } + +ใ“ใฎ้–ขๆ•ฐใซใฏ `@asynccontextmanager` ใŒใƒ‡ใ‚ณใƒฌใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ“ใฎ้–ขๆ•ฐใฏใ€Œ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใซใชใ‚Šใพใ™ใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Python ใฎใ€Œใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใฏใ€`with` ๆ–‡ใงไฝฟใˆใ‚‹ใ‚‚ใฎใงใ™ใ€‚ใŸใจใˆใฐใ€`open()` ใฏใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใจใ—ใฆไฝฟใˆใพใ™: + +```Python +with open("file.txt") as file: + file.read() +``` + +ๆœ€่ฟ‘ใฎ Python ใซใฏใ€Œ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚`async with` ใงไฝฟใ„ใพใ™: + +```Python +async with lifespan(app): + await do_stuff() +``` + +ใ“ใฎใ‚ˆใ†ใซใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ๏ผˆใพใŸใฏ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃ๏ผ‰ใ‚’ไฝœใ‚‹ใจใ€`with` ใƒ–ใƒญใƒƒใ‚ฏใซๅ…ฅใ‚‹ๅ‰ใซ `yield` ใ‚ˆใ‚Šๅ‰ใฎใ‚ณใƒผใƒ‰ใŒๅฎŸ่กŒใ•ใ‚Œใ€`with` ใƒ–ใƒญใƒƒใ‚ฏใ‚’ๅ‡บใŸๅพŒใซ `yield` ใ‚ˆใ‚ŠๅพŒใ‚ใฎใ‚ณใƒผใƒ‰ใŒๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + +ไธŠใฎใ‚ณใƒผใƒ‰ไพ‹ใงใฏ็›ดๆŽฅใใ‚Œใ‚’ไฝฟใฃใฆใฏใ„ใพใ›ใ‚“ใŒใ€FastAPI ใซๆธกใ—ใฆๅ†…้ƒจใงไฝฟใฃใฆใ‚‚ใ‚‰ใ„ใพใ™ใ€‚ + +`FastAPI` ใ‚ขใƒ—ใƒชใฎ `lifespan` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€Œ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ€ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใฎใงใ€ๆ–ฐใ—ใไฝœใฃใŸ `lifespan` ้žๅŒๆœŸใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใƒžใƒใƒผใ‚ธใƒฃใ‚’ๆธกใ›ใพใ™ใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## ไปฃๆ›ฟใฎใ‚คใƒ™ใƒณใƒˆ๏ผˆ้žๆŽจๅฅจ๏ผ‰ { #alternative-events-deprecated } + +/// warning | ๆณจๆ„ + +ๆŽจๅฅจใ•ใ‚Œใ‚‹ๆ–นๆณ•ใฏใ€ไธŠใง่ชฌๆ˜Žใ—ใŸใจใŠใ‚Š `FastAPI` ใ‚ขใƒ—ใƒชใฎ `lifespan` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใฃใฆใ€Œ่ตทๅ‹•ใ€ใจใ€Œใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ€ใ‚’ๆ‰ฑใ†ใ“ใจใงใ™ใ€‚`lifespan` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใจใ€`startup` ใจ `shutdown` ใฎใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉใฏๅ‘ผใณๅ‡บใ•ใ‚Œใชใใชใ‚Šใพใ™ใ€‚`lifespan` ใ‹ใ‚คใƒ™ใƒณใƒˆใ‹ใ€ใฉใกใ‚‰ใ‹ไธ€ๆ–นใงใ‚ใ‚Šใ€ไธกๆ–นๅŒๆ™‚ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใฎ็ฏ€ใฏ่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ใ‹ใพใ„ใพใ›ใ‚“ใ€‚ + +/// + +่ตทๅ‹•ๆ™‚ใจใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณๆ™‚ใซๅฎŸ่กŒใ•ใ‚Œใ‚‹ใƒญใ‚ธใƒƒใ‚ฏใ‚’ๅฎš็พฉใ™ใ‚‹ๅˆฅใฎๆ–นๆณ•ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่ตทๅ‹•ใ™ใ‚‹ๅ‰ใ€ใพใŸใฏใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ™ใ‚‹ใจใใซๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ๏ผˆ้–ขๆ•ฐ๏ผ‰ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎ้–ขๆ•ฐใฏ `async def` ใงใ‚‚ใ€้€šๅธธใฎ `def` ใงใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +### `startup` ใ‚คใƒ™ใƒณใƒˆ { #startup-event } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ้–‹ๅง‹ใ•ใ‚Œใ‚‹ๅ‰ใซๅฎŸ่กŒใ™ในใ้–ขๆ•ฐใ‚’่ฟฝๅŠ ใ™ใ‚‹ใซใฏใ€ใ‚คใƒ™ใƒณใƒˆ `"startup"` ใงๅฎฃ่จ€ใ—ใพใ™: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +ใ“ใฎๅ ดๅˆใ€`startup` ใฎใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ้–ขๆ•ฐใฏ items ใฎใ€Œใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€๏ผˆๅ˜ใชใ‚‹ `dict`๏ผ‰ใ‚’ใ„ใใคใ‹ใฎๅ€คใงๅˆๆœŸๅŒ–ใ—ใพใ™ใ€‚ + +ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ้–ขๆ•ฐใฏ่ค‡ๆ•ฐ่ฟฝๅŠ ใงใใพใ™ใ€‚ + +ใ™ในใฆใฎ `startup` ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉใŒๅฎŒไบ†ใ™ใ‚‹ใพใงใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ—ใ‘ไป˜ใ‘ใ‚’้–‹ๅง‹ใ—ใพใ›ใ‚“ใ€‚ + +### `shutdown` ใ‚คใƒ™ใƒณใƒˆ { #shutdown-event } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ™ใ‚‹ใจใใซๅฎŸ่กŒใ™ในใ้–ขๆ•ฐใ‚’่ฟฝๅŠ ใ™ใ‚‹ใซใฏใ€ใ‚คใƒ™ใƒณใƒˆ `"shutdown"` ใงๅฎฃ่จ€ใ—ใพใ™: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +ใ“ใ“ใงใฏใ€`shutdown` ใฎใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ้–ขๆ•ฐใŒใ€ใƒ†ใ‚ญใ‚นใƒˆ่กŒ `"Application shutdown"` ใ‚’ใƒ•ใ‚กใ‚คใƒซ `log.txt` ใซๆ›ธใ่พผใฟใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +`open()` ้–ขๆ•ฐใฎ `mode="a"` ใฏใ€Œ่ฟฝๅŠ ใ€๏ผˆappend๏ผ‰ใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใคใพใ‚Šใ€ใใฎใƒ•ใ‚กใ‚คใƒซใซๆ—ขใซใ‚ใ‚‹ๅ†…ๅฎนใ‚’ไธŠๆ›ธใใ›ใšใ€่กŒใŒๅพŒใ‚ใซ่ฟฝ่จ˜ใ•ใ‚Œใพใ™ใ€‚ + +/// + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎไพ‹ใงใฏใ€ใƒ•ใ‚กใ‚คใƒซใ‚’ๆ‰ฑใ†ๆจ™ๆบ–ใฎ Python ้–ขๆ•ฐ `open()` ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใƒ‡ใ‚ฃใ‚นใ‚ฏใธใฎๆ›ธใ่พผใฟใ‚’ใ€Œๅพ…ใคใ€ๅฟ…่ฆใŒใ‚ใ‚‹ I/O๏ผˆๅ…ฅๅŠ›/ๅ‡บๅŠ›๏ผ‰ใŒ้–ขใ‚ใ‚Šใพใ™ใ€‚ + +ใ—ใ‹ใ— `open()` ่‡ชไฝ“ใฏ `async` ใ‚„ `await` ใ‚’ไฝฟใ„ใพใ›ใ‚“ใ€‚ + +ใ—ใŸใŒใฃใฆใ€ใ‚คใƒ™ใƒณใƒˆใƒใƒณใƒ‰ใƒฉ้–ขๆ•ฐใฏ `async def` ใงใฏใชใ้€šๅธธใฎ `def` ใงๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +### `startup` ใจ `shutdown` ใ‚’ใพใจใ‚ใฆ { #startup-and-shutdown-together } + +่ตทๅ‹•ๆ™‚ใจใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณๆ™‚ใฎใƒญใ‚ธใƒƒใ‚ฏใฏ้–ข้€ฃใ—ใฆใ„ใ‚‹ใ“ใจใŒๅคšใ„ใงใ™ใ€‚ไฝ•ใ‹ใ‚’้–‹ๅง‹ใ—ใฆใ‹ใ‚‰็ต‚ไบ†ใ—ใŸใ„ใ€ใƒชใ‚ฝใƒผใ‚นใ‚’็ฒๅพ—ใ—ใฆใ‹ใ‚‰่งฃๆ”พใ—ใŸใ„ใ€ใชใฉใงใ™. + +ๅ…ฑๆœ‰ใ™ใ‚‹ใƒญใ‚ธใƒƒใ‚ฏใ‚„ๅค‰ๆ•ฐใฎใชใ„ๅˆฅใ€…ใฎ้–ขๆ•ฐใงใใ‚Œใ‚’่กŒใ†ใฎใฏ้›ฃใ—ใใ€ใ‚ฐใƒญใƒผใƒใƒซๅค‰ๆ•ฐใชใฉใซๅ€คใ‚’ไฟๅญ˜ใ™ใ‚‹ๅฟ…่ฆใŒๅ‡บใฆใใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€็พๅœจใฏไธŠใง่ชฌๆ˜Žใ—ใŸใจใŠใ‚Š `lifespan` ใ‚’ไฝฟใ†ใ“ใจใŒๆŽจๅฅจใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +## ๆŠ€่ก“่ฉณ็ดฐ { #technical-details } + +ๆŠ€่ก“ใŒๆฐ—ใซใชใ‚‹ๆ–นใธใฎ็ดฐใ‹ใช่ฉณ็ดฐใงใ™ใ€‚๐Ÿค“ + +ๅ†…้ƒจ็š„ใซใฏใ€ASGI ใฎๆŠ€่ก“ไป•ๆง˜ใซใŠใ„ใฆใ€ใ“ใ‚Œใฏ Lifespan ใƒ—ใƒญใƒˆใ‚ณใƒซ ใฎไธ€้ƒจใงใ‚ใ‚Šใ€`startup` ใจ `shutdown` ใจใ„ใ†ใ‚คใƒ™ใƒณใƒˆใŒๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +Starlette ใฎ `lifespan` ใƒใƒณใƒ‰ใƒฉใซใคใ„ใฆใฏใ€Starlette ใฎ Lifespan ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ฉณใ—ใ่ชญใ‚€ใ“ใจใŒใงใใพใ™ใ€‚ + +ใ‚ณใƒผใƒ‰ใฎไป–ใฎ้ ˜ๅŸŸใงไฝฟใˆใ‚‹ lifespan ใฎ็Šถๆ…‹ใ‚’ใฉใฎใ‚ˆใ†ใซๆ‰ฑใ†ใ‹ใ‚‚ๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +/// + +## ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ { #sub-applications } + +๐Ÿšจ ใ“ใ‚Œใ‚‰ใฎ lifespan ใ‚คใƒ™ใƒณใƒˆ๏ผˆstartup ใจ shutdown๏ผ‰ใฏใƒกใ‚คใƒณใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฏพใ—ใฆใฎใฟๅฎŸ่กŒใ•ใ‚Œใ€[ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒžใ‚ฆใƒณใƒˆ](sub-applications.md){.internal-link target=_blank} ใซใฏๅฎŸ่กŒใ•ใ‚Œใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/advanced/generate-clients.md b/docs/ja/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..7b9f820544 --- /dev/null +++ b/docs/ja/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# SDK ใฎ็”Ÿๆˆ { #generating-sdks } + +**FastAPI** ใฏ **OpenAPI** ไป•ๆง˜ใซๅŸบใฅใ„ใฆใ„ใ‚‹ใŸใ‚ใ€ใใฎ API ใฏๅคšใใฎใƒ„ใƒผใƒซใŒ็†่งฃใงใใ‚‹ๆจ™ๆบ–ๅฝขๅผใง่จ˜่ฟฐใงใใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๆœ€ๆ–ฐใฎ**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ**ใ€่ค‡ๆ•ฐ่จ€่ชžใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใƒฉใ‚คใƒ–ใƒฉใƒช๏ผˆ**SDKs**๏ผ‰ใ€ใใ—ใฆใ‚ณใƒผใƒ‰ใจๅŒๆœŸใ—็ถšใ‘ใ‚‹**ใƒ†ใ‚นใƒˆ**ใ‚„**่‡ชๅ‹•ๅŒ–ใƒฏใƒผใ‚ฏใƒ•ใƒญใƒผ**ใ‚’ๅฎนๆ˜“ใซ็”Ÿๆˆใงใใพใ™ใ€‚ + +ๆœฌใ‚ฌใ‚คใƒ‰ใงใฏใ€FastAPI ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ๅ‘ใ‘ใฎ **TypeScript SDK** ใ‚’็”Ÿๆˆใ™ใ‚‹ๆ–นๆณ•ใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +## ใ‚ชใƒผใƒ—ใ‚ฝใƒผใ‚นใฎ SDK ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ { #open-source-sdk-generators } + +ๅคš็”จ้€”ใช้ธๆŠž่‚ขใจใ—ใฆ OpenAPI Generator ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏ**ๅคšๆ•ฐใฎใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐ่จ€่ชž**ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใ€OpenAPI ไป•ๆง˜ใ‹ใ‚‰ SDK ใ‚’็”Ÿๆˆใงใใพใ™ใ€‚ + +**TypeScript ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ**ๅ‘ใ‘ใซใฏใ€Hey API ใŒ็›ฎ็š„็‰นๅŒ–ใฎใ‚ฝใƒชใƒฅใƒผใ‚ทใƒงใƒณใงใ€TypeScript ใ‚จใ‚ณใ‚ทใ‚นใƒ†ใƒ ใซๆœ€้ฉๅŒ–ใ•ใ‚ŒใŸไฝ“้จ“ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + +ไป–ใฎ SDK ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใฏ OpenAPI.Tools ใงใ‚‚่ฆ‹ใคใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +FastAPI ใฏ่‡ชๅ‹•็š„ใซ **OpenAPI 3.1** ใฎไป•ๆง˜ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ใ—ใŸใŒใฃใฆใ€ไฝฟ็”จใ™ใ‚‹ใƒ„ใƒผใƒซใฏใ“ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// + +## FastAPI ใ‚นใƒใƒณใ‚ตใƒผใซใ‚ˆใ‚‹ SDK ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟ { #sdk-generators-from-fastapi-sponsors } + +ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€FastAPI ใ‚’ใ‚นใƒใƒณใ‚ตใƒผใ—ใฆใ„ใ‚‹ไผๆฅญใซใ‚ˆใ‚‹ใ€**ใƒ™ใƒณใƒใƒฃใƒผๆ”ฏๆด**ใŠใ‚ˆใณ**ไผๆฅญๆ”ฏๆด**ใฎใ‚ฝใƒชใƒฅใƒผใ‚ทใƒงใƒณใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎ่ฃฝๅ“ใฏใ€้ซ˜ๅ“่ณชใช็”Ÿๆˆ SDK ใซๅŠ ใˆใฆใ€**่ฟฝๅŠ ๆฉŸ่ƒฝ**ใ‚„**็ตฑๅˆ**ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + +โœจ [**FastAPI ใ‚’ใ‚นใƒใƒณใ‚ตใƒผใ™ใ‚‹**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ ใ“ใจใงใ€ใ“ใ‚Œใ‚‰ใฎไผๆฅญใฏใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใจใใฎ**ใ‚จใ‚ณใ‚ทใ‚นใƒ†ใƒ **ใฎๅฅๅ…จๆ€งใจ**ๆŒ็ถšๅฏ่ƒฝๆ€ง**ใ‚’ๆ”ฏๆดใ—ใฆใ„ใพใ™ใ€‚ + +ใ“ใฎๆ”ฏๆดใฏใ€FastAPI ใฎ**ใ‚ณใƒŸใƒฅใƒ‹ใƒ†ใ‚ฃ**๏ผˆ็š†ใ•ใ‚“๏ผ‰ใธใฎๅผทใ„ใ‚ณใƒŸใƒƒใƒˆใƒกใƒณใƒˆใฎ่กจๆ˜Žใงใ‚‚ใ‚ใ‚Šใ€**ๅ„ชใ‚ŒใŸใ‚ตใƒผใƒ“ใ‚น**ใฎๆไพ›ใ ใ‘ใงใชใใ€ๅ …็‰ขใง็™บๅฑ•ใ™ใ‚‹ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ FastAPI ใ‚’ๆ”ฏใˆใ‚‹ๅงฟๅ‹ขใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚๐Ÿ™‡ + +ไพ‹ใˆใฐใ€ๆฌกใฎใ‚ˆใ†ใชใ‚‚ใฎใŒใ‚ใ‚Šใพใ™: + +* Speakeasy +* Stainless +* liblab + +ใ“ใ‚Œใ‚‰ใฎใ‚ฝใƒชใƒฅใƒผใ‚ทใƒงใƒณใฎไธญใซใฏใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใ‚„็„กๆ–™ๆž ใ‚’ๆไพ›ใ™ใ‚‹ใ‚‚ใฎใ‚‚ใ‚ใ‚Šใ€้‡‘้Šญ็š„ใ‚ณใƒŸใƒƒใƒˆใƒกใƒณใƒˆใชใ—ใง่ฉฆใ™ใ“ใจใŒใงใใพใ™ใ€‚ไป–ใฎๅ•†็”จ SDK ใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใ‚‚ๅญ˜ๅœจใ—ใ€ใ‚ชใƒณใƒฉใ‚คใƒณใง่ฆ‹ใคใ‘ใ‚‰ใ‚Œใพใ™ใ€‚๐Ÿค“ + +## TypeScript SDK ใ‚’ไฝœๆˆใ™ใ‚‹ { #create-a-typescript-sdk } + +ใพใšใฏ็ฐกๅ˜ใช FastAPI ใ‚ขใƒ—ใƒชใ‹ใ‚‰ๅง‹ใ‚ใพใ™: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +ใ“ใ“ใงใ€*path operation* ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใจใƒฌใ‚นใƒใƒณใ‚นใฎใƒšใ‚คใƒญใƒผใƒ‰ใซไฝฟ็”จใ™ใ‚‹ใƒขใƒ‡ใƒซใ‚’ๅฎš็พฉใ—ใฆใŠใ‚Šใ€`Item` ใจ `ResponseMessage` ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ + +### API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #api-docs } + +`/docs` ใซ็งปๅ‹•ใ™ใ‚‹ใจใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใง้€ไฟกใƒปใƒฌใ‚นใƒใƒณใ‚นใงๅ—ไฟกใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใฎ**ใ‚นใ‚ญใƒผใƒž**ใŒ่กจ็คบใ•ใ‚Œใพใ™: + + + +ใ“ใ‚Œใ‚‰ใฎใ‚นใ‚ญใƒผใƒžใฏใ€ใ‚ขใƒ—ใƒชๅ†…ใงใƒขใƒ‡ใƒซใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใŸใ‚่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +ใใฎๆƒ…ๅ ฑใฏใ‚ขใƒ—ใƒชใฎ **OpenAPI ใ‚นใ‚ญใƒผใƒž**ใซๅซใพใ‚Œใ€API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +OpenAPI ใซๅซใพใ‚Œใ‚‹ใ“ใ‚Œใ‚‰ใฎใƒขใƒ‡ใƒซๆƒ…ๅ ฑใ‚’ไฝฟใฃใฆใ€**ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰ใ‚’็”Ÿๆˆ**ใงใใพใ™ใ€‚ + +### Hey API { #hey-api } + +ใƒขใƒ‡ใƒซใ‚’ๅ‚™ใˆใŸ FastAPI ใ‚ขใƒ—ใƒชใŒใ‚ใ‚Œใฐใ€Hey API ใง TypeScript ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆใงใใพใ™ใ€‚ๆœ€ใ‚‚ๆ‰‹ๆ—ฉใ„ๆ–นๆณ•ใฏ npx ใ‚’ไฝฟใ†ใ“ใจใงใ™ใ€‚ + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +ใ“ใ‚Œใง TypeScript SDK ใŒ `./src/client` ใซ็”Ÿๆˆใ•ใ‚Œใพใ™ใ€‚ + +`@hey-api/openapi-ts` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซๆ–นๆณ•ใ‚„ใ€็”Ÿๆˆ็‰ฉใฎ่ฉณ็ดฐใฏๅ…ฌๅผใ‚ตใ‚คใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +### SDK ใฎๅˆฉ็”จ { #using-the-sdk } + +ใ“ใ‚Œใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰ใ‚’ import ใ—ใฆๅˆฉ็”จใงใใพใ™ใ€‚ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใ€ใƒกใ‚ฝใƒƒใƒ‰ใซๅฏพใ—ใฆ่ฃœๅฎŒใŒๅŠนใใพใ™: + + + +้€ไฟกใ™ใ‚‹ใƒšใ‚คใƒญใƒผใƒ‰ใซใ‚‚่ฃœๅฎŒใŒ้ฉ็”จใ•ใ‚Œใพใ™: + + + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +FastAPI ใ‚ขใƒ—ใƒชใฎ `Item` ใƒขใƒ‡ใƒซใงๅฎš็พฉใ—ใŸ `name` ใจ `price` ใซ่ฃœๅฎŒใŒๅŠนใ„ใฆใ„ใ‚‹็‚นใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +้€ไฟกใƒ‡ใƒผใ‚ฟใซๅฏพใ™ใ‚‹ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผใ‚‚่กจ็คบใ•ใ‚Œใพใ™: + + + +ใƒฌใ‚นใƒใƒณใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซใ‚‚่ฃœๅฎŒใŒใ‚ใ‚Šใพใ™: + + + +## ใ‚ฟใ‚ฐไป˜ใใฎ FastAPI ใ‚ขใƒ—ใƒช { #fastapi-app-with-tags } + +ๅฎŸ้‹็”จใงใฏใ‚ขใƒ—ใƒชใฏๅคงใใใชใ‚Šใ€*path operation* ใฎใ‚ฐใƒซใƒผใƒ—ๅˆ†ใ‘ใซใ‚ฟใ‚ฐใ‚’ไฝฟใ†ใ“ใจใŒๅคšใ„ใงใ—ใ‚‡ใ†ใ€‚ + +ไพ‹ใˆใฐ **items** ็”จใจ **users** ็”จใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใŒใ‚ใ‚Šใ€ใ‚ฟใ‚ฐใงๅˆ†ใ‘ใ‚‰ใ‚Œใพใ™: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### ใ‚ฟใ‚ฐไป˜ใ TypeScript ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎ็”Ÿๆˆ { #generate-a-typescript-client-with-tags } + +ใ‚ฟใ‚ฐใ‚’็”จใ„ใŸ FastAPI ใ‚ขใƒ—ใƒชใ‹ใ‚‰ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆใ™ใ‚‹ใจใ€้€šๅธธใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆๅดใฎใ‚ณใƒผใƒ‰ใ‚‚ใ‚ฟใ‚ฐใ”ใจใซๅˆ†ๅ‰ฒใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰ใ‚‚ๆญฃใ—ใๆ•ด็†ใƒปใ‚ฐใƒซใƒผใƒ”ใƒณใ‚ฐใ•ใ‚Œใพใ™: + + + +ใ“ใฎไพ‹ใงใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +* `ItemsService` +* `UsersService` + +### ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎใƒกใ‚ฝใƒƒใƒ‰ๅ { #client-method-names } + +็พ็Šถใงใฏใ€็”Ÿๆˆใ•ใ‚Œใ‚‹ใƒกใ‚ฝใƒƒใƒ‰ๅ๏ผˆ`createItemItemsPost` ใชใฉ๏ผ‰ใฏใ‚ใพใ‚Šใใ‚Œใ„ใงใฏใ‚ใ‚Šใพใ›ใ‚“: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +ใ“ใ‚Œใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใŒๅ„ *path operation* ใฎ OpenAPI ๅ†…้ƒจใฎ **operation ID** ใ‚’็”จใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +OpenAPI ใงใฏ operation ID ใฏๅ…จใฆใฎ *path operation* ใ‚’้€šใ—ใฆไธ€ๆ„ใงใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใฎใŸใ‚ FastAPI ใฏ**้–ขๆ•ฐๅ**ใ€**ใƒ‘ใ‚น**ใ€**HTTP ใƒกใ‚ฝใƒƒใƒ‰/ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณ**ใ‚’็ต„ใฟๅˆใ‚ใ›ใฆ operation ID ใ‚’็”Ÿๆˆใ—ใ€ไธ€ๆ„ๆ€งใ‚’ไฟ่จผใ—ใพใ™ใ€‚ + +ๆฌกใซใ“ใ‚Œใ‚’ๆ”นๅ–„ใ™ใ‚‹ๆ–นๆณ•ใ‚’็คบใ—ใพใ™ใ€‚๐Ÿค“ + +## ใ‚ซใ‚นใ‚ฟใƒ  operation ID ใจใ‚ˆใ‚Š่‰ฏใ„ใƒกใ‚ฝใƒƒใƒ‰ๅ { #custom-operation-ids-and-better-method-names } + +operation ID ใฎ**็”Ÿๆˆๆ–นๆณ•**ใ‚’**ๅค‰ๆ›ด**ใ—ใฆ็ฐกๆฝ”ใซใ—ใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆๅดใฎ**ใƒกใ‚ฝใƒƒใƒ‰ๅใ‚’ใ‚ทใƒณใƒ—ใƒซ**ใซใงใใพใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใงใ‚‚ๅ„ operation ID ใŒ**ไธ€ๆ„**ใงใ‚ใ‚‹ใ“ใจใฏๅˆฅใฎๆ–นๆณ•ใงไฟ่จผใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ๅ„ *path operation* ใซใ‚ฟใ‚ฐใ‚’ไป˜ใ‘ใ€**ใ‚ฟใ‚ฐ**ใจ *path operation* ใฎ**ๅๅ‰**๏ผˆ้–ขๆ•ฐๅ๏ผ‰ใ‹ใ‚‰ operation ID ใ‚’็”Ÿๆˆใงใใพใ™ใ€‚ + +### ไธ€ๆ„ ID ็”Ÿๆˆ้–ขๆ•ฐใฎใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บ { #custom-generate-unique-id-function } + +FastAPI ใฏๅ„ *path operation* ใซ**ไธ€ๆ„ ID**ใ‚’็”จใ„ใฆใŠใ‚Šใ€ใ“ใ‚Œใฏ **operation ID** ใฎใปใ‹ใ€ๅฟ…่ฆใซๅฟœใ˜ใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚„ใƒฌใ‚นใƒใƒณใ‚นใฎใ‚ซใ‚นใ‚ฟใƒ ใƒขใƒ‡ใƒซๅใซใ‚‚ไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +ใ“ใฎ้–ขๆ•ฐใฏใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บๅฏ่ƒฝใงใ™ใ€‚`APIRoute` ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ๆ–‡ๅญ—ๅˆ—ใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ไพ‹ใˆใฐใ“ใ“ใงใฏใ€ๆœ€ๅˆใฎใ‚ฟใ‚ฐ๏ผˆ้€šๅธธใฏ 1 ใค๏ผ‰ใจ *path operation* ๅ๏ผˆ้–ขๆ•ฐๅ๏ผ‰ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +ใใฎใ‚ซใ‚นใ‚ฟใƒ ้–ขๆ•ฐใ‚’ **FastAPI** ใฎ `generate_unique_id_function` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆธกใ—ใพใ™: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### ใ‚ซใ‚นใ‚ฟใƒ  operation ID ใง TypeScript ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆ { #generate-a-typescript-client-with-custom-operation-ids } + +ใ“ใฎ็Šถๆ…‹ใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’ๅ†็”Ÿๆˆใ™ใ‚‹ใจใ€ใƒกใ‚ฝใƒƒใƒ‰ๅใŒๆ”นๅ–„ใ•ใ‚Œใฆใ„ใพใ™: + + + +ใ”่ฆงใฎใจใŠใ‚Šใ€ใƒกใ‚ฝใƒƒใƒ‰ๅใฏใ‚ฟใ‚ฐๅใจ้–ขๆ•ฐๅใฎใฟใซใชใ‚Šใ€URL ใƒ‘ใ‚นใ‚„ HTTP ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใฎๆƒ…ๅ ฑใฏๅซใพใ‚Œใพใ›ใ‚“ใ€‚ + +### ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ็”Ÿๆˆๅ‘ใ‘ใฎ OpenAPI ไป•ๆง˜ใฎๅ‰ๅ‡ฆ็† { #preprocess-the-openapi-specification-for-the-client-generator } + +ใใ‚Œใงใ‚‚็”Ÿๆˆใ‚ณใƒผใƒ‰ใซใฏ**้‡่ค‡ๆƒ…ๅ ฑ**ใŒๆฎ‹ใฃใฆใ„ใพใ™ใ€‚ + +`ItemsService`๏ผˆใ‚ฟใ‚ฐ็”ฑๆฅ๏ผ‰ใ‹ใ‚‰ items ้–ข้€ฃใงใ‚ใ‚‹ใ“ใจใฏใ™ใงใซๅˆ†ใ‹ใ‚‹ใฎใซใ€ใƒกใ‚ฝใƒƒใƒ‰ๅใซใ‚‚ใ‚ฟใ‚ฐๅใŒๅ‰็ฝฎใ•ใ‚Œใฆใ„ใพใ™ใ€‚๐Ÿ˜• + +OpenAPI ๅ…จไฝ“ใจใ—ใฆใฏ operation ID ใฎ**ไธ€ๆ„ๆ€ง**ใฎใŸใ‚ใซใ€ใ“ใฎใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’็ถญๆŒใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +ใ—ใ‹ใ—็”Ÿๆˆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ็”จใซใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆใ™ใ‚‹็›ดๅ‰ใซ OpenAPI ใฎ operation ID ใ‚’**ๅŠ ๅทฅ**ใ—ใฆใ€ใƒกใ‚ฝใƒƒใƒ‰ๅใ‚’ใ‚ˆใ‚Š**่ฆ‹ใ‚„ใ™ใ**ใ€**ใ‚ฏใƒชใƒผใƒณ**ใซใงใใพใ™ใ€‚ + +OpenAPI ใฎ JSON ใ‚’ `openapi.json` ใจใ—ใฆไฟๅญ˜ใ—ใ€ๆฌกใฎใ‚ˆใ†ใชใ‚นใ‚ฏใƒชใƒ—ใƒˆใง**ใใฎใ‚ฟใ‚ฐใฎใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’้™คๅŽป**ใงใใพใ™: + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +ใ“ใ‚Œใซใ‚ˆใ‚Š operation ID ใฏ `items-get_items` ใฎใ‚ˆใ†ใชๅฝขใ‹ใ‚‰ๅ˜ใชใ‚‹ `get_items` ใซ็ฝฎใๆ›ใ‚ใ‚Šใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใฏใ‚ˆใ‚Š็ฐกๆฝ”ใชใƒกใ‚ฝใƒƒใƒ‰ๅใ‚’็”Ÿๆˆใงใใพใ™ใ€‚ + +### ๅ‰ๅ‡ฆ็†ๆธˆใฟ OpenAPI ใ‹ใ‚‰ TypeScript ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆ { #generate-a-typescript-client-with-the-preprocessed-openapi } + +็”Ÿๆˆๅ…ƒใŒ `openapi.json` ใซใชใฃใŸใฎใงใ€ๅ…ฅๅŠ›ใฎๅ ดๆ‰€ใ‚’ๆ›ดๆ–ฐใ—ใพใ™: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +ๆ–ฐใ—ใ„ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’็”Ÿๆˆใ™ใ‚‹ใจใ€**ใ‚ฏใƒชใƒผใƒณใชใƒกใ‚ฝใƒƒใƒ‰ๅ**ใซใชใ‚Šใ€**่ฃœๅฎŒ**ใ‚„**ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผ**ใชใฉใ‚‚ใใฎใพใพๅˆฉ็”จใงใใพใ™: + + + +## ๅˆฉ็‚น { #benefits } + +่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’ไฝฟใ†ใจใ€ๆฌกใฎใ‚ˆใ†ใชๅฏพ่ฑกใง**่ฃœๅฎŒ**ใŒๅพ—ใ‚‰ใ‚Œใพใ™: + +* ใƒกใ‚ฝใƒƒใƒ‰ +* ๆœฌไฝ“ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใƒšใ‚คใƒญใƒผใƒ‰ใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ็ญ‰ +* ใƒฌใ‚นใƒใƒณใ‚นใฎใƒšใ‚คใƒญใƒผใƒ‰ + +ใพใŸใ€ใ‚ใ‚‰ใ‚†ใ‚‹็ฎ‡ๆ‰€ใง**ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผ**ใ‚‚ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ + +ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚ณใƒผใƒ‰ใ‚’ๆ›ดๆ–ฐใ—ใฆใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚’**ๅ†็”Ÿๆˆ**ใ™ใ‚Œใฐใ€ๆ–ฐใ—ใ„ *path operation* ใฏใƒกใ‚ฝใƒƒใƒ‰ใจใ—ใฆ่ฟฝๅŠ ใ•ใ‚Œใ€ๅคใ„ใ‚‚ใฎใฏๅ‰Š้™คใ•ใ‚Œใ€ใใฎไป–ใฎๅค‰ๆ›ดใ‚‚็”Ÿๆˆใ‚ณใƒผใƒ‰ใซๅๆ˜ ใ•ใ‚Œใพใ™ใ€‚๐Ÿค“ + +ใคใพใ‚Šใ€ๅค‰ๆ›ดใŒใ‚ใ‚Œใฐ่‡ชๅ‹•็š„ใซใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰ใซ**ๅๆ˜ **ใ•ใ‚Œใพใ™ใ€‚ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚’**ใƒ“ใƒซใƒ‰**ใ™ใ‚Œใฐใ€ไฝฟ็”จใƒ‡ใƒผใ‚ฟใซ**ไธๆ•ดๅˆ**ใŒใ‚ใ‚Œใฐใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚ + +ใใฎ็ตๆžœใ€ๅคšใใฎใ‚จใƒฉใƒผใ‚’้–‹็™บใฎๅˆๆœŸๆฎต้šŽใง**ๆ—ฉๆœŸ็™บ่ฆ‹**ใงใใ€ๆœฌ็•ชใงๆœ€็ต‚ใƒฆใƒผใ‚ถใƒผใซไธๅ…ทๅˆใŒ็พใ‚Œใฆใ‹ใ‚‰ๅŽŸๅ› ใ‚’ใƒ‡ใƒใƒƒใ‚ฐใ™ใ‚‹ๅฟ…่ฆใŒใชใใชใ‚Šใพใ™ใ€‚โœจ diff --git a/docs/ja/docs/advanced/middleware.md b/docs/ja/docs/advanced/middleware.md new file mode 100644 index 0000000000..2883d53d82 --- /dev/null +++ b/docs/ja/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# ้ซ˜ๅบฆใชใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข { #advanced-middleware } + +ใƒกใ‚คใƒณใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซ[ใ‚ซใ‚นใ‚ฟใƒ ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข](../tutorial/middleware.md){.internal-link target=_blank}ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๆ–นๆณ•ใ‚’ๅญฆใณใพใ—ใŸใ€‚ + +ใใ—ใฆใ€[`CORSMiddleware` ใ‚’ไฝฟใฃใŸ CORS ใฎๆ‰ฑใ„ๆ–น](../tutorial/cors.md){.internal-link target=_blank}ใ‚‚ๅญฆใณใพใ—ใŸใ€‚ + +ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใใฎไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎไฝฟใ„ๆ–นใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +## ASGI ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ่ฟฝๅŠ  { #adding-asgi-middlewares } + +**FastAPI** ใฏ Starlette ใ‚’ๅŸบ็›คใจใ—ใฆใŠใ‚Šใ€ASGI ไป•ๆง˜ใ‚’ๅฎŸ่ฃ…ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ไปปๆ„ใฎ ASGI ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ + +ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏ ASGI ไป•ๆง˜ใซๅพ“ใฃใฆใ„ใ‚Œใฐใ€FastAPI ใ‚„ Starlette ๅฐ‚็”จใซไฝœใ‚‰ใ‚Œใฆใ„ใชใใฆใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚ + +ไธ€่ˆฌใซใ€ASGI ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏๆœ€ๅˆใฎๅผ•ๆ•ฐใจใ—ใฆ ASGI ใ‚ขใƒ—ใƒชใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใฎ ASGI ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฏใ€ใŠใใ‚‰ใๆฌกใฎใ‚ˆใ†ใซๆ›ธใ‹ใ‚Œใฆใ„ใ‚‹ใงใ—ใ‚‡ใ†: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +ใ—ใ‹ใ— FastAPI๏ผˆๆญฃ็ขบใซใฏ Starlette๏ผ‰ใฏใ€ๅ†…้ƒจใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒใ‚ตใƒผใƒใƒผใ‚จใƒฉใƒผใ‚’ๅ‡ฆ็†ใ—ใ€ใ‚ซใ‚นใ‚ฟใƒ ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใŒๆญฃใ—ใๅ‹•ไฝœใ™ใ‚‹ใ“ใจใ‚’ไฟ่จผใ™ใ‚‹ใ€ใ‚ˆใ‚Š็ฐกๅ˜ใชๆ–นๆณ•ใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใฏ๏ผˆCORS ใฎไพ‹ใจๅŒๆง˜ใซ๏ผ‰`app.add_middleware()` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` ใฏใ€ๆœ€ๅˆใฎๅผ•ๆ•ฐใซใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎใ‚ฏใƒฉใ‚นใ‚’ๅ–ใ‚Šใ€ใใ‚Œไปฅๅค–ใฎ่ฟฝๅŠ ๅผ•ๆ•ฐใฏใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใซๆธกใ•ใ‚Œใพใ™ใ€‚ + +## ็ต„ใฟ่พผใฟใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข { #integrated-middlewares } + +**FastAPI** ใฏไธ€่ˆฌ็š„ใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซๅฏพๅฟœใ™ใ‚‹ใ„ใใคใ‹ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ๅซใ‚“ใงใ„ใพใ™ใ€‚ไปฅไธ‹ใงใใฎไฝฟใ„ๆ–นใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ไปฅไธ‹ใฎไพ‹ใงใฏใ€`from starlette.middleware.something import SomethingMiddleware` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +**FastAPI** ใฏ้–‹็™บ่€…ใงใ‚ใ‚‹ใ‚ใชใŸใฎไพฟๅฎœใฎใŸใ‚ใซ `fastapi.middleware` ใซใ„ใใคใ‹ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎๅคšใใฏ Starlette ใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +ใ™ในใฆใฎๅ—ไฟกใƒชใ‚ฏใ‚จใ‚นใƒˆใŒ `https` ใพใŸใฏ `wss` ใงใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ‚ˆใ†ใซๅผทๅˆถใ—ใพใ™ใ€‚ + +`http` ใพใŸใฏ `ws` ใธใฎๅ—ไฟกใƒชใ‚ฏใ‚จใ‚นใƒˆใฏใ€ๅฎ‰ๅ…จใชใ‚นใ‚ญใƒผใƒ ใซใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ•ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +HTTP Host Header ๆ”ปๆ’ƒใ‚’้˜ฒใใŸใ‚ใ€ใ™ในใฆใฎๅ—ไฟกใƒชใ‚ฏใ‚จใ‚นใƒˆใซๆญฃใ—ใ่จญๅฎšใ•ใ‚ŒใŸ `Host` ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅผทๅˆถใ—ใพใ™ใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +ใ‚ตใƒใƒผใƒˆใ•ใ‚Œใ‚‹ๅผ•ๆ•ฐใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +- `allowed_hosts` - ่จฑๅฏใ™ใ‚‹ใƒ›ใ‚นใƒˆๅใฎใƒ‰ใƒกใ‚คใƒณๅใƒชใ‚นใƒˆใ€‚`*.example.com` ใฎใ‚ˆใ†ใชใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ใƒ‰ใƒกใ‚คใƒณใงใ‚ตใƒ–ใƒ‰ใƒกใ‚คใƒณใฎใƒžใƒƒใƒใƒณใ‚ฐใ‚‚ใ‚ตใƒใƒผใƒˆใ—ใพใ™ใ€‚ไปปๆ„ใฎใƒ›ใ‚นใƒˆๅใ‚’่จฑๅฏใ™ใ‚‹ใซใฏใ€`allowed_hosts=["*"]` ใ‚’ไฝฟใ†ใ‹ใ€ใ“ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’็œ็•ฅใ—ใพใ™ใ€‚ +- `www_redirect` - True ใซ่จญๅฎšใ™ใ‚‹ใจใ€่จฑๅฏใ•ใ‚ŒใŸใƒ›ใ‚นใƒˆใฎ้ž www ็‰ˆใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ www ็‰ˆใธใƒชใƒ€ใ‚คใƒฌใ‚ฏใƒˆใ—ใพใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `True` ใงใ™ใ€‚ + +ๅ—ไฟกใƒชใ‚ฏใ‚จใ‚นใƒˆใŒๆญฃใ—ใๆคœ่จผใ•ใ‚Œใชใ„ๅ ดๅˆใ€`400` ใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ + +## `GZipMiddleware` { #gzipmiddleware } + +`Accept-Encoding` ใƒ˜ใƒƒใƒ€ใƒผใซ "gzip" ใ‚’ๅซใ‚€ใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅฏพใ—ใฆ GZip ใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ‡ฆ็†ใ—ใพใ™ใ€‚ + +ใ“ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฏใ€้€šๅธธใฎใƒฌใ‚นใƒใƒณใ‚นใจใ‚นใƒˆใƒชใƒผใƒŸใƒณใ‚ฐใƒฌใ‚นใƒใƒณใ‚นใฎไธกๆ–นใ‚’ๅ‡ฆ็†ใ—ใพใ™ใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +ใ‚ตใƒใƒผใƒˆใ•ใ‚Œใ‚‹ๅผ•ๆ•ฐใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +- `minimum_size` - ใ“ใฎใƒใ‚คใƒˆๆ•ฐใฎๆœ€ๅฐใ‚ตใ‚คใ‚บๆœชๆบ€ใฎใƒฌใ‚นใƒใƒณใ‚นใฏ GZip ๅœง็ธฎใ—ใพใ›ใ‚“ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `500` ใงใ™ใ€‚ +- `compresslevel` - GZip ๅœง็ธฎๆ™‚ใซไฝฟ็”จใ—ใพใ™ใ€‚1 ใ‹ใ‚‰ 9 ใพใงใฎๆ•ดๆ•ฐใงใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏ `9`ใ€‚ๅ€คใŒๅฐใ•ใ„ใปใฉๅœง็ธฎใฏ้€Ÿใใชใ‚Šใพใ™ใŒใƒ•ใ‚กใ‚คใƒซใ‚ตใ‚คใ‚บใฏๅคงใใใชใ‚Šใ€ๅ€คใŒๅคงใใ„ใปใฉๅœง็ธฎใฏ้…ใใชใ‚Šใพใ™ใŒใƒ•ใ‚กใ‚คใƒซใ‚ตใ‚คใ‚บใฏๅฐใ•ใใชใ‚Šใพใ™ใ€‚ + +## ใใฎไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข { #other-middlewares } + +ไป–ใซใ‚‚ๅคšใใฎ ASGI ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใŒใ‚ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐ: + +- Uvicorn ใฎ `ProxyHeadersMiddleware` +- MessagePack + +ไป–ใซๅˆฉ็”จๅฏ่ƒฝใชใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใซใคใ„ใฆใฏใ€Starlette ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚„ ASGI Awesome List ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/advanced/openapi-callbacks.md b/docs/ja/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..283a80b210 --- /dev/null +++ b/docs/ja/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ { #openapi-callbacks } + +ใ‚ใชใŸใฏใ€*path operation* ใ‚’ๆŒใค API ใ‚’ไฝœๆˆใ—ใ€ไป–่€…๏ผˆๅคšใใฎๅ ดๅˆใ€ใ‚ใชใŸใฎ API ใ‚’ใ€Œๅˆฉ็”จใ™ใ‚‹ใ€ๅŒไธ€ใฎ้–‹็™บ่€…๏ผ‰ใŒไฝœๆˆใ—ใŸ *ๅค–้ƒจ API* ใธใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใƒˆใƒชใ‚ฌใƒผใงใใ‚‹ใ‚ˆใ†ใซใงใใพใ™ใ€‚ + +ใ‚ใชใŸใฎ API ใ‚ขใƒ—ใƒชใŒ *ๅค–้ƒจ API* ใ‚’ๅ‘ผใณๅ‡บใ™ใจใใซ่ตทใใ‚‹ๅ‡ฆ็†ใฏใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ€ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ใชใœใชใ‚‰ใ€ๅค–้ƒจ้–‹็™บ่€…ใŒไฝœๆˆใ—ใŸใ‚ฝใƒ•ใƒˆใ‚ฆใ‚งใ‚ขใŒใ‚ใชใŸใฎ API ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚Šใ€ใใฎๅพŒใงใ‚ใชใŸใฎ API ใŒใ€Œๅ‘ผใณ่ฟ”ใ—ใ€ใ€*ๅค–้ƒจ API*๏ผˆใŠใใ‚‰ใๅŒใ˜้–‹็™บ่€…ใŒไฝœๆˆ๏ผ‰ใธใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใ€ใใฎ *ๅค–้ƒจ API* ใŒใฉใฎใ‚ˆใ†ใงใ‚ใ‚‹ใ€Œในใใ€ใ‹ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ—ใŸใใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใฉใ‚“ใช *path operation* ใ‚’ๆŒใกใ€ใฉใ‚“ใชใƒœใƒ‡ใ‚ฃใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใฉใ‚“ใชใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ™ใ‹ใ€ใชใฉใงใ™ใ€‚ + +## ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใ‚ใ‚‹ใ‚ขใƒ—ใƒช { #an-app-with-callbacks } + +ไพ‹ใง่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +ใ‚ใชใŸใŒ่ซ‹ๆฑ‚ๆ›ธใ‚’ไฝœๆˆใงใใ‚‹ใ‚ขใƒ—ใƒชใ‚’้–‹็™บใ—ใฆใ„ใ‚‹ใจๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎ่ซ‹ๆฑ‚ๆ›ธใฏ `id`ใ€`title`๏ผˆไปปๆ„๏ผ‰ใ€`customer`ใ€`total` ใ‚’ๆŒใกใพใ™ใ€‚ + +ใ‚ใชใŸใฎ API ใฎๅˆฉ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™บ่€…๏ผ‰ใฏใ€POST ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ‚ใชใŸใฎ API ใซ่ซ‹ๆฑ‚ๆ›ธใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใใฎๅพŒใ€ใ‚ใชใŸใฎ API ใฏ๏ผˆไปฎใซใ“ใ†ใ—ใพใ—ใ‚‡ใ†๏ผ‰: + +* ๅค–้ƒจ้–‹็™บ่€…ใฎ้กงๅฎขใซ่ซ‹ๆฑ‚ๆ›ธใ‚’้€ใ‚Šใพใ™ใ€‚ +* ไปฃ้‡‘ใ‚’ๅ›žๅŽใ—ใพใ™ใ€‚ +* API ๅˆฉ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™บ่€…๏ผ‰ใซ้€š็Ÿฅใ‚’้€ใ‚Š่ฟ”ใ—ใพใ™ใ€‚ + * ใ“ใ‚Œใฏ๏ผˆใ‚ใชใŸใฎ API ใ‹ใ‚‰๏ผ‰ๅค–้ƒจ้–‹็™บ่€…ใŒๆไพ›ใ™ใ‚‹ *ๅค–้ƒจ API* ใซ POST ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใ“ใจใง่กŒใ‚ใ‚Œใพใ™๏ผˆใ“ใ‚ŒใŒใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ€ใงใ™๏ผ‰ใ€‚ + +## ้€šๅธธใฎ FastAPI ใ‚ขใƒ—ใƒช { #the-normal-fastapi-app } + +ใพใšใ€ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅ‰ใฎ้€šๅธธใฎ API ใ‚ขใƒ—ใƒชใŒใฉใ†ใชใ‚‹ใ‹่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ + +`Invoice` ใƒœใƒ‡ใ‚ฃใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `callback_url` ใซใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ็”จใฎ URL ใ‚’ๅซใ‚ใ‚‹ *path operation* ใ‚’ๆŒใกใพใ™ใ€‚ + +ใ“ใฎ้ƒจๅˆ†ใฏใจใฆใ‚‚ๆ™ฎ้€šใงใ€ใปใจใ‚“ใฉใฎใ‚ณใƒผใƒ‰ใฏใ™ใงใซ่ฆ‹่ฆšใˆใŒใ‚ใ‚‹ใฏใšใงใ™: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`callback_url` ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€Pydantic ใฎ Url ๅž‹ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ + +/// + +ๅ”ฏไธ€ใฎๆ–ฐใ—ใ„็‚นใฏใ€*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฎๅผ•ๆ•ฐใจใ—ใฆ `callbacks=invoices_callback_router.routes` ใ‚’ๆธกใ™ใ“ใจใงใ™ใ€‚ใ“ใ‚ŒใŒไฝ•ใ‹ใฏๆฌกใง่ฆ‹ใพใ™ใ€‚ + +## ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ– { #documenting-the-callback } + +ๅฎŸ้š›ใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ใชใŸ่‡ช่บซใฎ API ใ‚ขใƒ—ใƒชใซๅคงใใไพๅญ˜ใ—ใพใ™ใ€‚ + +ใใ—ใฆใ‚ขใƒ—ใƒชใ”ใจใซๅคงใใ็•ฐใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +ใใ‚Œใฏๆฌกใฎใ‚ˆใ†ใซ 1ใ€2 ่กŒใฎใ‚ณใƒผใƒ‰ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +ใ—ใ‹ใ—ใ€ใŠใใ‚‰ใใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใงๆœ€ใ‚‚้‡่ฆใช็‚นใฏใ€ใ‚ใชใŸใฎ API ๅˆฉ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™บ่€…๏ผ‰ใŒใ€*ใ‚ใชใŸใฎ API* ใŒใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใชใฉใง้€ใ‚‹ใƒ‡ใƒผใ‚ฟใซๅพ“ใฃใฆใ€*ๅค–้ƒจ API* ใ‚’ๆญฃใ—ใๅฎŸ่ฃ…ใ™ใ‚‹ใ“ใจใ‚’็ขบๅฎŸใซใ™ใ‚‹ใ“ใจใงใ™ใ€‚ + +ใใ“ใงๆฌกใซ่กŒใ†ใฎใฏใ€*ใ‚ใชใŸใฎ API* ใ‹ใ‚‰ใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใซใ€ใใฎ *ๅค–้ƒจ API* ใŒใฉใ†ใ‚ใ‚‹ในใใ‹ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚‹ใ‚ณใƒผใƒ‰ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ + +ใใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏใ‚ใชใŸใฎ API ใฎ `/docs` ใฎ Swagger UI ใซ่กจ็คบใ•ใ‚Œใ€ๅค–้ƒจ้–‹็™บ่€…ใซ *ๅค–้ƒจ API* ใฎไฝœใ‚Šๆ–นใ‚’็Ÿฅใ‚‰ใ›ใพใ™ใ€‚ + +ใ“ใฎไพ‹ใงใฏใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ่‡ชไฝ“ใฏๅฎŸ่ฃ…ใ—ใพใ›ใ‚“๏ผˆใใ‚Œใฏ 1 ่กŒใฎใ‚ณใƒผใƒ‰ใงใ‚‚ใ‚ˆใ„ใงใ—ใ‚‡ใ†๏ผ‰ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ้ƒจๅˆ†ใฎใฟใงใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅฎŸ้š›ใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฏๅ˜ใชใ‚‹ HTTP ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ™ใ€‚ + +่‡ชๅˆ†ใงใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹ๅ ดๅˆใฏใ€HTTPX ใ‚„ Requests ใฎใ‚ˆใ†ใชใ‚‚ใฎใ‚’ไฝฟใˆใพใ™ใ€‚ + +/// + +## ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ { #write-the-callback-documentation-code } + +ใ“ใฎใ‚ณใƒผใƒ‰ใฏใ‚ใชใŸใฎใ‚ขใƒ—ใƒชใงๅฎŸ่กŒใ•ใ‚Œใพใ›ใ‚“ใ€‚*ๅค–้ƒจ API* ใŒใฉใ†ใ‚ใ‚‹ในใใ‹ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚‹ใŸใ‚ใ ใ‘ใซๅฟ…่ฆใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใ‚ใชใŸใฏใ™ใงใซ **FastAPI** ใง API ใฎ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ฐกๅ˜ใซไฝœใ‚‹ๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใพใ™ใ€‚ + +ใใฎ็Ÿฅ่ญ˜ใ‚’ไฝฟใฃใฆใ€*ๅค–้ƒจ API* ใŒใฉใ†ใ‚ใ‚‹ในใใ‹ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ—ใพใ™โ€ฆโ€ฆใคใพใ‚Šใ€ๅค–้ƒจ API ใŒๅฎŸ่ฃ…ใ™ในใ *path operation(s)*๏ผˆใ‚ใชใŸใฎ API ใŒๅ‘ผใณๅ‡บใ™ใ‚‚ใฎ๏ผ‰ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚‹ใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใใจใใฏใ€ใ‚ใชใŸใŒใใฎใ€Œๅค–้ƒจ้–‹็™บ่€…ใ€ใ ใจๆƒณๅƒใ™ใ‚‹ใฎใŒๅฝนใซ็ซ‹ใคใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ใ„ใพๅฎŸ่ฃ…ใ—ใฆใ„ใ‚‹ใฎใฏใ€Œใ‚ใชใŸใฎ APIใ€ใงใฏใชใใ€*ๅค–้ƒจ API* ใงใ™ใ€‚ + +ใ“ใฎ๏ผˆๅค–้ƒจ้–‹็™บ่€…ใฎ๏ผ‰่ฆ–็‚นใ‚’ไธ€ๆ™‚็š„ใซๆŽก็”จใ™ใ‚‹ใจใ€ใใฎ *ๅค–้ƒจ API* ใซๅฏพใ—ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒœใƒ‡ใ‚ฃ็”จใฎ Pydantic ใƒขใƒ‡ใƒซใ€ใƒฌใ‚นใƒใƒณใ‚นใชใฉใ‚’ใฉใ“ใซ็ฝฎใใฎใŒ่‡ช็„ถใ‹ใŒใ‚ˆใ‚Šๆ˜Ž็ขบใซๆ„Ÿใ˜ใ‚‰ใ‚Œใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +/// + +### ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ็”จ APIRouter ใ‚’ไฝœๆˆ { #create-a-callback-apirouter } + +ใพใšใ€1 ใคไปฅไธŠใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ‚’ๅซใ‚€ๆ–ฐใ—ใ„ `APIRouter` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎ path operation ใ‚’ไฝœๆˆ { #create-the-callback-path-operation } + +ไธŠใงไฝœๆˆใ—ใŸใฎใจๅŒใ˜ `APIRouter` ใ‚’ไฝฟใฃใฆใ€ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎ *path operation* ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +่ฆ‹ใŸ็›ฎใฏ้€šๅธธใฎ FastAPI ใฎ *path operation* ใจๅŒใ˜ใงใ™: + +* ๅ—ใ‘ๅ–ใ‚‹ใƒœใƒ‡ใ‚ฃใฎๅฎฃ่จ€๏ผˆไพ‹: `body: InvoiceEvent`๏ผ‰ใŒๅฟ…่ฆใงใ—ใ‚‡ใ†ใ€‚ +* ่ฟ”ใ™ใƒฌใ‚นใƒใƒณใ‚นใฎๅฎฃ่จ€๏ผˆไพ‹: `response_model=InvoiceEventReceived`๏ผ‰ใ‚‚ๆŒใฆใพใ™ใ€‚ + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +้€šๅธธใฎ *path operation* ใจ็•ฐใชใ‚‹ไธปใช็‚นใŒ 2 ใคใ‚ใ‚Šใพใ™: + +* ๅฎŸ้š›ใฎใ‚ณใƒผใƒ‰ใฏไธ่ฆใงใ™ใ€‚ใ‚ใชใŸใฎใ‚ขใƒ—ใƒชใฏใ“ใฎใ‚ณใƒผใƒ‰ใ‚’ๆฑบใ—ใฆๅ‘ผใณใพใ›ใ‚“ใ€‚ใ“ใ‚Œใฏ *ๅค–้ƒจ API* ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ™ใ‚‹ใŸใ‚ใ ใ‘ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ใ—ใŸใŒใฃใฆใ€้–ขๆ•ฐๆœฌไฝ“ใฏ `pass` ใงๆง‹ใ„ใพใ›ใ‚“ใ€‚ +* *ใƒ‘ใ‚น* ใซใฏใ€*ใ‚ใชใŸใฎ API* ใซ้€ใ‚‰ใ‚ŒใŸๅ…ƒใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ไธ€้ƒจใ‚’ๅค‰ๆ•ฐใจใ—ใฆไฝฟใˆใ‚‹ OpenAPI 3 ใฎๅผ๏ผˆๅพŒ่ฟฐ๏ผ‰ใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚ + +### ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใƒ‘ใ‚นๅผ { #the-callback-path-expression } + +ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎ *ใƒ‘ใ‚น* ใซใฏใ€*ใ‚ใชใŸใฎ API* ใซ้€ใ‚‰ใ‚ŒใŸๅ…ƒใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎไธ€้ƒจใ‚’ๅซใ‚ใ‚‰ใ‚Œใ‚‹ OpenAPI 3 ใฎๅผใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +ใ“ใฎไพ‹ใงใฏใ€`str` ใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +ใคใพใ‚Šใ€ใ‚ใชใŸใฎ API ๅˆฉ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™บ่€…๏ผ‰ใŒ *ใ‚ใชใŸใฎ API* ใซๆฌกใฎใ‚ˆใ†ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใฃใŸๅ ดๅˆ: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +JSON ใƒœใƒ‡ใ‚ฃใฏ: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +ใใฎๅพŒ *ใ‚ใชใŸใฎ API* ใฏ่ซ‹ๆฑ‚ๆ›ธใ‚’ๅ‡ฆ็†ใ—ใ€ใฎใกใปใฉ `callback_url`๏ผˆ*ๅค–้ƒจ API*๏ผ‰ใธใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚Šใพใ™: + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +JSON ใƒœใƒ‡ใ‚ฃใฏๆฌกใฎใ‚ˆใ†ใชๅ†…ๅฎนใงใ™: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +ใใ—ใฆ *ๅค–้ƒจ API* ใ‹ใ‚‰ใฏๆฌกใฎใ‚ˆใ†ใช JSON ใƒœใƒ‡ใ‚ฃใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๆœŸๅพ…ใ—ใพใ™: + +```JSON +{ + "ok": true +} +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ URL ใซใฏใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `callback_url`๏ผˆ`https://www.external.org/events`๏ผ‰ใงๅ—ใ‘ๅ–ใฃใŸ URL ใจใ€JSON ใƒœใƒ‡ใ‚ฃๅ†…ใฎ่ซ‹ๆฑ‚ๆ›ธ `id`๏ผˆ`2expen51ve`๏ผ‰ใŒๅซใพใ‚Œใฆใ„ใ‚‹็‚นใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +### ใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ็”จใƒซใƒผใ‚ฟใƒผใ‚’่ฟฝๅŠ  { #add-the-callback-router } + +ใ“ใ‚Œใงใ€ไธŠใงไฝœๆˆใ—ใŸใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ็”จใƒซใƒผใ‚ฟใƒผๅ†…ใซใ€ๅฟ…่ฆใชใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใฎ *path operation(s)*๏ผˆ*ๅค–้ƒจ้–‹็™บ่€…* ใŒ *ๅค–้ƒจ API* ใซๅฎŸ่ฃ…ใ™ในใใ‚‚ใฎ๏ผ‰ใŒ็”จๆ„ใงใใพใ—ใŸใ€‚ + +ๆฌกใซใ€*ใ‚ใชใŸใฎ API ใฎ path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฎ `callbacks` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใ€ใใฎใ‚ณใƒผใƒซใƒใƒƒใ‚ฏ็”จใƒซใƒผใ‚ฟใƒผใฎๅฑžๆ€ง `.routes`๏ผˆๅฎŸไฝ“ใฏใƒซใƒผใƒˆ/*path operations* ใฎ `list`๏ผ‰ใ‚’ๆธกใ—ใพใ™: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`callback=` ใซๆธกใ™ใฎใฏใƒซใƒผใ‚ฟใƒผๆœฌไฝ“๏ผˆ`invoices_callback_router`๏ผ‰ใงใฏใชใใ€ๅฑžๆ€ง `.routes`๏ผˆ`invoices_callback_router.routes`๏ผ‰ใงใ‚ใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็ขบ่ช { #check-the-docs } + +ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ—ใฆ http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ + +ใ‚ใชใŸใฎ *path operation* ใซใ€ŒCallbacksใ€ใ‚ปใ‚ฏใ‚ทใƒงใƒณใŒๅซใพใ‚Œใ€*ๅค–้ƒจ API* ใŒใฉใ†ใ‚ใ‚‹ในใใ‹ใŒ่กจ็คบใ•ใ‚Œใฆใ„ใ‚‹ใฎใŒ็ขบ่ชใงใใพใ™: + + diff --git a/docs/ja/docs/advanced/openapi-webhooks.md b/docs/ja/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..368cfddd82 --- /dev/null +++ b/docs/ja/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI ใฎ Webhook { #openapi-webhooks } + +ใ‚ขใƒ—ใƒชใŒใ‚ใ‚‹็จฎใฎ**ใ‚คใƒ™ใƒณใƒˆ**ใ‚’**้€š็Ÿฅ**ใ™ใ‚‹ใŸใ‚ใซใ€ใƒ‡ใƒผใ‚ฟไป˜ใใง็›ธๆ‰‹ใฎใ‚ขใƒ—ใƒช๏ผˆใƒชใ‚ฏใ‚จใ‚นใƒˆ้€ไฟก๏ผ‰ใ‚’ๅ‘ผใณๅ‡บใ™ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’ใ€API ใฎ**ใƒฆใƒผใ‚ถใƒผ**ใซไผใˆใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€้€šๅธธใฎใ‚ˆใ†ใซใƒฆใƒผใ‚ถใƒผใŒใ‚ใชใŸใฎ API ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใฎใงใฏใชใใ€**ใ‚ใชใŸใฎ API๏ผˆใ‚ใชใŸใฎใ‚ขใƒ—ใƒช๏ผ‰**ใŒ**็›ธๆ‰‹ใฎใ‚ทใ‚นใƒ†ใƒ **๏ผˆ็›ธๆ‰‹ใฎ APIใ€ใ‚ขใƒ—ใƒช๏ผ‰ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใ€ใจใ„ใ†ใ“ใจใงใ™ใ€‚ + +ใ“ใ‚Œใฏไธ€่ˆฌใซ**Webhook**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ + +## Webhook ใฎๆ‰‹้ † { #webhooks-steps } + +้€šๅธธใฎๆตใ‚Œใจใ—ใฆใ€ใพใšใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ๅ†…ใงใ€้€ไฟกใ™ใ‚‹ใƒกใƒƒใ‚ปใƒผใ‚ธใ€ใ™ใชใ‚ใกใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ๆœฌๆ–‡๏ผˆใƒœใƒ‡ใ‚ฃ๏ผ‰**ใ‚’**ๅฎš็พฉ**ใ—ใพใ™ใ€‚ + +ๅŠ ใˆใฆใ€ใ‚ขใƒ—ใƒชใŒใใ‚Œใ‚‰ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆ๏ผˆใ‚คใƒ™ใƒณใƒˆ๏ผ‰ใ‚’้€ไฟกใ™ใ‚‹**ใ‚ฟใ‚คใƒŸใƒณใ‚ฐ**ใ‚‚ไฝ•ใ‚‰ใ‹ใฎๅฝขใงๅฎš็พฉใ—ใพใ™ใ€‚ + +ใใ—ใฆ**ใƒฆใƒผใ‚ถใƒผ**ใฏใ€ใ‚ขใƒ—ใƒชใŒใใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ในใ**URL**ใ‚’๏ผˆใŸใจใˆใฐใฉใ“ใ‹ใฎ Web ใƒ€ใƒƒใ‚ทใƒฅใƒœใƒผใƒ‰ใง๏ผ‰ๅฎš็พฉใ—ใพใ™ใ€‚ + +Webhook ใฎ URL ใ‚’็™ป้Œฒใ™ใ‚‹ๆ–นๆณ•ใ‚„ๅฎŸ้š›ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚‹ใ‚ณใƒผใƒ‰ใชใฉใ€ใ“ใ‚Œใ‚‰ใฎ**ใƒญใ‚ธใƒƒใ‚ฏ**ใฏใ™ในใฆใ‚ใชใŸๆฌก็ฌฌใงใ™ใ€‚**ใ‚ใชใŸ่‡ช่บซใฎใ‚ณใƒผใƒ‰**ใงๅฅฝใใชใ‚ˆใ†ใซๅฎŸ่ฃ…ใ—ใพใ™ใ€‚ + +## FastAPI ใจ OpenAPI ใซใ‚ˆใ‚‹ Webhook ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ– { #documenting-webhooks-with-fastapi-and-openapi } + +**FastAPI** ใจ OpenAPI ใ‚’ไฝฟใ†ใจใ€Webhook ใฎๅๅ‰ใ€ใ‚ขใƒ—ใƒชใŒ้€ไฟกใงใใ‚‹ HTTP ใฎๆ“ไฝœ๏ผˆไพ‹: `POST`, `PUT` ใชใฉ๏ผ‰ใ€ใ‚ขใƒ—ใƒชใŒ้€ใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใƒœใƒ‡ใ‚ฃ**ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒฆใƒผใ‚ถใƒผใŒใ‚ใชใŸใฎ **Webhook** ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚‹ใŸใ‚ใฎ**API ใ‚’ๅฎŸ่ฃ…**ใ™ใ‚‹ใฎใŒๅคงๅน…ใซ็ฐกๅ˜ใซใชใ‚Šใพใ™ใ€‚ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€ใƒฆใƒผใ‚ถใƒผใŒ่‡ชๅˆ†ใŸใกใฎ API ใ‚ณใƒผใƒ‰ใ‚’่‡ชๅ‹•็”Ÿๆˆใงใใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +Webhook ใฏ OpenAPI 3.1.0 ไปฅไธŠใงๅˆฉ็”จๅฏ่ƒฝใงใ€FastAPI `0.99.0` ไปฅไธŠใŒๅฏพๅฟœใ—ใฆใ„ใพใ™ใ€‚ + +/// + +## Webhook ใ‚’ๆŒใคใ‚ขใƒ—ใƒช { #an-app-with-webhooks } + +**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€`webhooks` ใจใ„ใ†ๅฑžๆ€งใŒใ‚ใ‚Šใ€ใ“ใ“ใง *path operations* ใจๅŒๆง˜ใซ๏ผˆไพ‹: `@app.webhooks.post()`๏ผ‰*webhook* ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +ๅฎš็พฉใ—ใŸ webhook ใฏ **OpenAPI** ใ‚นใ‚ญใƒผใƒžใŠใ‚ˆใณ่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใ‚‹ **ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI** ใซๅๆ˜ ใ•ใ‚Œใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +`app.webhooks` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏๅฎŸ้š›ใซใฏๅ˜ใชใ‚‹ `APIRouter` ใงใ€่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซใงใ‚ขใƒ—ใƒชใ‚’ๆง‹ๆˆใ™ใ‚‹้š›ใซไฝฟใ†ใ‚‚ใฎใจๅŒใ˜ๅž‹ใงใ™ใ€‚ + +/// + +Webhook ใงใฏ๏ผˆ`/items/` ใฎใ‚ˆใ†ใช๏ผ‰*ใƒ‘ใ‚น*ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใชใ„็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใ“ใงๆธกใ™ๆ–‡ๅญ—ๅˆ—ใฏ webhook ใฎ**่ญ˜ๅˆฅๅญ**๏ผˆใ‚คใƒ™ใƒณใƒˆๅ๏ผ‰ใงใ™ใ€‚ใŸใจใˆใฐ `@app.webhooks.post("new-subscription")` ใงใฎ webhook ๅใฏ `new-subscription` ใงใ™ใ€‚ + +ใ“ใ‚Œใฏใ€**ใƒฆใƒผใ‚ถใƒผ**ใŒๅฎŸ้š›ใซ Webhook ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚ŠใŸใ„**URL ใƒ‘ใ‚น**ใ‚’ใ€ๅˆฅใฎๆ–นๆณ•๏ผˆไพ‹: Web ใƒ€ใƒƒใ‚ทใƒฅใƒœใƒผใƒ‰๏ผ‰ใงๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚’ๆƒณๅฎšใ—ใฆใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } + +ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ—ใ€http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏ้€šๅธธใฎ *path operations* ใซๅŠ ใˆใฆใ€**webhooks** ใ‚‚่กจ็คบใ•ใ‚Œใพใ™: + + diff --git a/docs/ja/docs/advanced/path-operation-advanced-configuration.md b/docs/ja/docs/advanced/path-operation-advanced-configuration.md index a78c3cb026..f7e3406171 100644 --- a/docs/ja/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ja/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ OpenAPIใฎใ€Œใ‚จใ‚ญใ‚นใƒ‘ใƒผใƒˆใ€ใงใชใ‘ใ‚Œใฐใ€ใ“ใ‚ŒใฏใŠใใ‚‰ใๅฟ…่ฆ ๅ„ใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใงไธ€ๆ„ใซใชใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### *path operation้–ขๆ•ฐ* ใฎๅๅ‰ใ‚’operationIdใจใ—ใฆไฝฟ็”จใ™ใ‚‹ { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ APIใฎ้–ขๆ•ฐๅใ‚’ `operationId` ใจใ—ใฆๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใ€ใ™ในใฆใฎAP ใ™ในใฆใฎ *path operation* ใ‚’่ฟฝๅŠ ใ—ใŸๅพŒใซ่กŒใ†ในใใงใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -40,7 +40,7 @@ APIใฎ้–ขๆ•ฐๅใ‚’ `operationId` ใจใ—ใฆๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใ€ใ™ในใฆใฎAP ็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒž๏ผˆใคใพใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆใฎไป•็ต„ใฟ๏ผ‰ใ‹ใ‚‰ *path operation* ใ‚’้™คๅค–ใ™ใ‚‹ใซใฏใ€`include_in_schema` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆ `False` ใซ่จญๅฎšใ—ใพใ™ใ€‚ -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## docstringใซใ‚ˆใ‚‹่ชฌๆ˜Žใฎ้ซ˜ๅบฆใช่จญๅฎš { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ OpenAPIไป•ๆง˜ใงใฏ parsed ใ•ใ‚Œใšใ€็›ดๆŽฅ `bytes` ใจใ—ใฆ่ชญใฟๅ–ใ‚‰ใ‚Œใพใ™ใ€‚ใใ—ใฆ `magic_data_reader()` ้–ขๆ•ฐใŒใ€ไฝ•ใ‚‰ใ‹ใฎๆ–นๆณ•ใงใใ‚Œใ‚’ใƒ‘ใƒผใ‚นใ™ใ‚‹่ฒฌๅ‹™ใ‚’ๆ‹…ใ„ใพใ™ใ€‚ +ใ“ใฎไพ‹ใงใฏใ€Pydanticใƒขใƒ‡ใƒซใ‚’ไธ€ๅˆ‡ๅฎฃ่จ€ใ—ใฆใ„ใพใ›ใ‚“ใ€‚ๅฎŸ้š›ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฏJSONใจใ—ใฆ ใƒ‘ใƒผใ‚น ใ•ใ‚Œใšใ€็›ดๆŽฅ `bytes` ใจใ—ใฆ่ชญใฟๅ–ใ‚‰ใ‚Œใพใ™ใ€‚ใใ—ใฆ `magic_data_reader()` ้–ขๆ•ฐใŒใ€ไฝ•ใ‚‰ใ‹ใฎๆ–นๆณ•ใงใใ‚Œใ‚’ใƒ‘ใƒผใ‚นใ™ใ‚‹่ฒฌๅ‹™ใ‚’ๆ‹…ใ„ใพใ™ใ€‚ ใใ‚Œใงใ‚‚ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใซๆœŸๅพ…ใ•ใ‚Œใ‚‹ใ‚นใ‚ญใƒผใƒžใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ @@ -153,7 +153,7 @@ OpenAPIไป•ๆง˜ใงใฏ Starlette ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/advanced/response-directly.md b/docs/ja/docs/advanced/response-directly.md index 7e83b9ffb2..103e84c385 100644 --- a/docs/ja/docs/advanced/response-directly.md +++ b/docs/ja/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ XMLใ‚’ๆ–‡ๅญ—ๅˆ—ใซใ—ใ€`Response` ใซๅซใ‚ใ€ใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ## ๅ‚™่€ƒ { #notes } diff --git a/docs/ja/docs/advanced/response-headers.md b/docs/ja/docs/advanced/response-headers.md new file mode 100644 index 0000000000..10aec78452 --- /dev/null +++ b/docs/ja/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# ใƒฌใ‚นใƒใƒณใ‚นใƒ˜ใƒƒใƒ€ใƒผ { #response-headers } + +## `Response` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟใ† { #use-a-response-parameter } + +๏ผˆCookie ใจๅŒๆง˜ใซ๏ผ‰*path operation ้–ขๆ•ฐ*ใง `Response` ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ + +ใใ—ใฆใ€ใใฎ*ไธ€ๆ™‚็š„*ใชใƒฌใ‚นใƒใƒณใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซใƒ˜ใƒƒใƒ€ใƒผใ‚’่จญๅฎšใงใใพใ™ใ€‚ + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +ใใฎๅพŒใฏ้€šๅธธใฉใŠใ‚Šใ€ๅฟ…่ฆใชไปปๆ„ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆ`dict`ใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซใชใฉ๏ผ‰ใ‚’่ฟ”ใ›ใพใ™ใ€‚ + +`response_model` ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€่ฟ”ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎใƒ•ใ‚ฃใƒซใ‚ฟใจๅค‰ๆ›ใซๅผ•ใ็ถšใไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +**FastAPI** ใฏใใฎ*ไธ€ๆ™‚็š„*ใชใƒฌใ‚นใƒใƒณใ‚นใ‹ใ‚‰ใƒ˜ใƒƒใƒ€ใƒผ๏ผˆCookie ใ‚„ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚‚ๅซใ‚€๏ผ‰ใ‚’ๅ–ใ‚Šๅ‡บใ—ใ€`response_model` ใซใ‚ˆใฃใฆใƒ•ใ‚ฃใƒซใ‚ฟใ•ใ‚ŒใŸ่ฟ”ๅดๅ€คใ‚’ๅซใ‚€ๆœ€็ต‚็š„ใชใƒฌใ‚นใƒใƒณใ‚นใซๅๆ˜ ใ—ใพใ™ใ€‚ + +ใพใŸใ€ไพๅญ˜้–ขไฟ‚ใฎไธญใง `Response` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใ€ใใฎไธญใงใƒ˜ใƒƒใƒ€ใƒผ๏ผˆใ‚„ Cookie๏ผ‰ใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +## `Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ { #return-a-response-directly } + +`Response` ใ‚’็›ดๆŽฅ่ฟ”ใ™ๅ ดๅˆใซใ‚‚ใƒ˜ใƒƒใƒ€ใƒผใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ + +[Response ใ‚’็›ดๆŽฅ่ฟ”ใ™](response-directly.md){.internal-link target=_blank} ใง่ชฌๆ˜Žใ—ใŸใ‚ˆใ†ใซใƒฌใ‚นใƒใƒณใ‚นใ‚’ไฝœๆˆใ—ใ€ใƒ˜ใƒƒใƒ€ใƒผใ‚’่ฟฝๅŠ ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆๆธกใ—ใพใ™: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +`from starlette.responses import Response` ใ‚„ `from starlette.responses import JSONResponse` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +**FastAPI** ใฏใ€้–‹็™บ่€…ใงใ‚ใ‚‹ใ‚ใชใŸใธใฎไพฟๅฎœใจใ—ใฆใ€`starlette.responses` ใจๅŒใ˜ใ‚‚ใฎใ‚’ `fastapi.responses` ใจใ—ใฆๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎๅคงๅŠใฏ็›ดๆŽฅ Starlette ใ‹ใ‚‰ๆฅใฆใ„ใพใ™ใ€‚ + +ใพใŸใ€`Response` ใฏใƒ˜ใƒƒใƒ€ใƒผใ‚„ Cookie ใ‚’่จญๅฎšใ™ใ‚‹ใฎใซใ‚ˆใไฝฟใ‚ใ‚Œใ‚‹ใŸใ‚ใ€**FastAPI** ใฏ `fastapi.Response` ใงใ‚‚ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +## ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผ { #custom-headers } + +็‹ฌ่‡ชใฎใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใฏใ€`X-` ใƒ—ใƒฌใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚’ไฝฟใฃใฆ่ฟฝๅŠ ใงใใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +ใŸใ ใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฆ‹ใˆใ‚‹ใ‚ˆใ†ใซใ—ใŸใ„ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€CORS ่จญๅฎšใซใใ‚Œใ‚‰ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™๏ผˆ[CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank} ใ‚’ๅ‚็…ง๏ผ‰ใ€‚ใ“ใฎใจใใ€Starlette ใฎ CORS ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่จ˜่ผ‰ใฎ `expose_headers` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/security/http-basic-auth.md b/docs/ja/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..7ee56a039b --- /dev/null +++ b/docs/ja/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic ่ช่จผ { #http-basic-auth } + +ๆœ€ใ‚‚ใ‚ทใƒณใƒ—ใƒซใชใ‚ฑใƒผใ‚นใงใฏใ€HTTP Basic ่ช่จผใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ + +HTTP Basic ่ช่จผใงใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅซใ‚€ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆœŸๅพ…ใ—ใพใ™ใ€‚ + +ใใ‚Œใ‚’ๅ—ใ‘ๅ–ใ‚Œใชใ„ๅ ดๅˆใ€HTTP 401 "Unauthorized" ใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใใ—ใฆใ€ๅ€คใŒ `Basic` ใฎใƒ˜ใƒƒใƒ€ใƒผ `WWW-Authenticate` ใ‚’ใ€ไปปๆ„ใฎ `realm` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใจใ‚‚ใซ่ฟ”ใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏ็ต„ใฟ่พผใฟใฎใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ๅ…ฅๅŠ›ใƒ—ใƒญใƒณใƒ—ใƒˆใ‚’่กจ็คบใ—ใพใ™ใ€‚ + +ใใฎๅพŒใ€ใใฎใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅ…ฅๅŠ›ใ™ใ‚‹ใจใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏใใ‚Œใ‚‰ใ‚’ใƒ˜ใƒƒใƒ€ใƒผใซ่‡ชๅ‹•็š„ใซไป˜ไธŽใ—ใฆ้€ไฟกใ—ใพใ™ใ€‚ + +## ใ‚ทใƒณใƒ—ใƒซใช HTTP Basic ่ช่จผ { #simple-http-basic-auth } + +- `HTTPBasic` ใจ `HTTPBasicCredentials` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ +- `HTTPBasic` ใ‚’ไฝฟใฃใฆใ€Œ`security` ใ‚นใ‚ญใƒผใƒ ใ€ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +- ใใฎ `security` ใ‚’ไพๅญ˜้–ขไฟ‚ใจใ—ใฆ path operation ใซไฝฟ็”จใ—ใพใ™ใ€‚ +- `HTTPBasicCredentials` ๅž‹ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒ่ฟ”ใ‚Šใพใ™: + - ้€ไฟกใ•ใ‚ŒใŸ `username` ใจ `password` ใ‚’ๅซใฟใพใ™ใ€‚ + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +URL ใ‚’ๆœ€ๅˆใซ้–‹ใ“ใ†ใจใ—ใŸใจใ๏ผˆใพใŸใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ€ŒExecuteใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใŸใจใ๏ผ‰ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใฏใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎๅ…ฅๅŠ›ใ‚’ๆฑ‚ใ‚ใพใ™: + + + +## ใƒฆใƒผใ‚ถใƒผๅใฎ็ขบ่ช { #check-the-username } + +ใ‚ˆใ‚ŠๅฎŒๅ…จใชไพ‹ใงใ™ใ€‚ + +ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใฃใฆใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆญฃใ—ใ„ใ‹ใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใซใฏใ€Python ๆจ™ๆบ–ใƒขใ‚ธใƒฅใƒผใƒซ `secrets` ใ‚’็”จใ„ใฆใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆคœ่จผใ—ใพใ™ใ€‚ + +`secrets.compare_digest()` ใฏ `bytes` ใ‹ใ€ASCII ๆ–‡ๅญ—๏ผˆ่‹ฑ่ชžใฎๆ–‡ๅญ—๏ผ‰ใฎใฟใ‚’ๅซใ‚€ `str` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใคใพใ‚Šใ€`Sebastiรกn` ใฎใ‚ˆใ†ใซ `รก` ใ‚’ๅซใ‚€ๆ–‡ๅญ—ใงใฏใใฎใพใพใงใฏๅ‹•ไฝœใ—ใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใซๅฏพๅ‡ฆใ™ใ‚‹ใŸใ‚ใ€ใพใš `username` ใจ `password` ใ‚’ UTF-8 ใงใ‚จใƒณใ‚ณใƒผใƒ‰ใ—ใฆ `bytes` ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ + +ใใฎใ†ใˆใงใ€`secrets.compare_digest()` ใ‚’ไฝฟใฃใฆใ€`credentials.username` ใŒ `"stanleyjobson"` ใงใ‚ใ‚Šใ€`credentials.password` ใŒ `"swordfish"` ใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +ใ“ใ‚Œใฏๆฌกใฎใ‚ˆใ†ใชใ‚ณใƒผใƒ‰ใซ็›ธๅฝ“ใ—ใพใ™: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Return some error + ... +``` + +ใ—ใ‹ใ— `secrets.compare_digest()` ใ‚’ไฝฟใ†ใ“ใจใงใ€ใ€Œใ‚ฟใ‚คใƒŸใƒณใ‚ฐๆ”ปๆ’ƒใ€ใจๅ‘ผใฐใ‚Œใ‚‹็จฎ้กžใฎๆ”ปๆ’ƒใซๅฏพใ—ใฆๅฎ‰ๅ…จใซใชใ‚Šใพใ™ใ€‚ + +### ใ‚ฟใ‚คใƒŸใƒณใ‚ฐๆ”ปๆ’ƒ { #timing-attacks } + +ใ€Œใ‚ฟใ‚คใƒŸใƒณใ‚ฐๆ”ปๆ’ƒใ€ใจใฏไฝ•ใงใ—ใ‚‡ใ†ใ‹๏ผŸ + +ๆ”ปๆ’ƒ่€…ใŒใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŽจๆธฌใ—ใ‚ˆใ†ใจใ—ใฆใ„ใ‚‹ใจๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚ + +ใใ—ใฆใ€ใƒฆใƒผใ‚ถใƒผๅ `johndoe`ใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ `love123` ใ‚’ไฝฟใฃใฆใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’้€ใ‚Šใพใ™ใ€‚ + +ใใฎๅ ดๅˆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ†…ใฎ Python ใ‚ณใƒผใƒ‰ใฏๆฌกใฎใ‚ˆใ†ใชใ‚‚ใฎใจ็ญ‰ไพกใซใชใ‚Šใพใ™: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +ใ—ใ‹ใ—ใ€Python ใฏ `johndoe` ใฎๆœ€ๅˆใฎ `j` ใจ `stanleyjobson` ใฎๆœ€ๅˆใฎ `s` ใ‚’ๆฏ”่ผƒใ—ใŸๆ™‚็‚นใงใ€ไธก่€…ใฎๆ–‡ๅญ—ๅˆ—ใŒๅŒใ˜ใงใชใ„ใจๅˆคๆ–ญใ—ใฆใ™ใใซ `False` ใ‚’่ฟ”ใ—ใพใ™ใ€‚ใคใพใ‚Šใ€Œๆฎ‹ใ‚Šใฎๆ–‡ๅญ—ใ‚’ๆฏ”่ผƒใ—ใฆ่จˆ็ฎ—่ณ‡ๆบใ‚’็„ก้ง„ใซใ™ใ‚‹ๅฟ…่ฆใฏใชใ„ใ€ใจ่€ƒใˆใ‚‹ใ‚ใ‘ใงใ™ใ€‚ใใ—ใฆใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€Œใƒฆใƒผใ‚ถใƒผๅใพใŸใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆญฃใ—ใใ‚ใ‚Šใพใ›ใ‚“ใ€ใจ่ฟ”ใ—ใพใ™ใ€‚ + +ๆฌกใซใ€ๆ”ปๆ’ƒ่€…ใŒใƒฆใƒผใ‚ถใƒผๅ `stanleyjobsox`ใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ `love123` ใง่ฉฆใ™ใจใ—ใพใ™ใ€‚ + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ‚ณใƒผใƒ‰ใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +ใ“ใฎๅ ดๅˆใ€Python ใฏ `stanleyjobsox` ใจ `stanleyjobson` ใฎไธกๆ–นใง `stanleyjobso` ๅ…จไฝ“ใ‚’ๆฏ”่ผƒใ—ใฆใ‹ใ‚‰ใ€ๆ–‡ๅญ—ๅˆ—ใŒๅŒใ˜ใงใชใ„ใจๆฐ—ใฅใใพใ™ใ€‚ใ—ใŸใŒใฃใฆใ€ใ€Œใƒฆใƒผใ‚ถใƒผๅใพใŸใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆญฃใ—ใใ‚ใ‚Šใพใ›ใ‚“ใ€ใจๅฟœ็ญ”ใ™ใ‚‹ใพใงใซไฝ™ๅˆ†ใซๆ•ฐใƒžใ‚คใ‚ฏใƒญ็ง’ใ‹ใ‹ใ‚Šใพใ™ใ€‚ + +#### ๅฟœ็ญ”ๆ™‚้–“ใŒๆ”ปๆ’ƒ่€…ใ‚’ๅŠฉใ‘ใ‚‹ { #the-time-to-answer-helps-the-attackers } + +ใ“ใ“ใงใ€ใ‚ตใƒผใƒใƒผใŒใ€Œใƒฆใƒผใ‚ถใƒผๅใพใŸใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒๆญฃใ—ใใ‚ใ‚Šใพใ›ใ‚“ใ€ใจใ„ใ†ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ™ใพใงใซใ€ใ‚ใšใ‹ใซ้•ทใ„ๆ™‚้–“ใŒใ‹ใ‹ใฃใŸใ“ใจใซๆฐ—ใฅใ‘ใฐใ€ๆ”ปๆ’ƒ่€…ใฏไฝ•ใ‹ใ—ใ‚‰ๆญฃ่งฃใซ่ฟ‘ใฅใ„ใŸใ€ใ™ใชใ‚ใกๅ…ˆ้ ญใฎใ„ใใคใ‹ใฎๆ–‡ๅญ—ใŒๆญฃใ—ใ‹ใฃใŸใ“ใจใ‚’็Ÿฅใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ + +ใ™ใ‚‹ใจใ€`johndoe` ใ‚ˆใ‚Šใ‚‚ `stanleyjobsox` ใซ่ฟ‘ใ„ใ‚‚ใฎใ‚’็‹™ใฃใฆๅ†่ฉฆ่กŒใงใใพใ™ใ€‚ + +#### ใ€Œใƒ—ใƒญใ€ใƒฌใƒ™ใƒซใฎๆ”ปๆ’ƒ { #a-professional-attack } + +ใ‚‚ใกใ‚ใ‚“ใ€ๆ”ปๆ’ƒ่€…ใฏใ“ใ‚Œใ‚‰ใ‚’ๆ‰‹ไฝœๆฅญใงใฏ่กŒใ‚ใšใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๆ›ธใ„ใฆใ€1 ็ง’้–“ใซๆ•ฐๅƒใ€œๆ•ฐ็™พไธ‡ๅ›žใฎใƒ†ใ‚นใƒˆใ‚’่กŒใ†ใงใ—ใ‚‡ใ†ใ€‚ใใ—ใฆ 1 ๅ›žใซ 1 ๆ–‡ๅญ—ใšใคๆญฃใ—ใ„ๆ–‡ๅญ—ใ‚’่ฆ‹ใคใ‘ใฆใ„ใใพใ™ใ€‚ + +ใใ†ใ™ใ‚‹ใ“ใจใงใ€ๆ•ฐๅˆ†ใ‹ใ‚‰ๆ•ฐๆ™‚้–“ใฎใ†ใกใซใ€ๆ”ปๆ’ƒ่€…ใฏ็งใŸใกใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ€ŒๅŠฉใ‘ใ€๏ผˆๅฟœ็ญ”ใซใ‹ใ‹ใฃใŸๆ™‚้–“๏ผ‰ใ ใ‘ใ‚’ๅˆฉ็”จใ—ใฆใ€ๆญฃใ—ใ„ใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆŽจๆธฌใงใใฆใ—ใพใ„ใพใ™ใ€‚ + +#### `secrets.compare_digest()` ใงๅฏพ็ญ– { #fix-it-with-secrets-compare-digest } + +ใ—ใ‹ใ—ใ€็งใŸใกใฎใ‚ณใƒผใƒ‰ใงใฏๅฎŸ้š›ใซ `secrets.compare_digest()` ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + +่ฆใ™ใ‚‹ใซใ€`stanleyjobsox` ใจ `stanleyjobson` ใ‚’ๆฏ”่ผƒใ™ใ‚‹ใฎใซใ‹ใ‹ใ‚‹ๆ™‚้–“ใฏใ€`johndoe` ใจ `stanleyjobson` ใ‚’ๆฏ”่ผƒใ™ใ‚‹ใฎใซใ‹ใ‹ใ‚‹ๆ™‚้–“ใจๅŒใ˜ใซใชใ‚Šใพใ™ใ€‚ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใงใ‚‚ๅŒๆง˜ใงใ™ใ€‚ + +ใ“ใฎใ‚ˆใ†ใซใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ณใƒผใƒ‰ใง `secrets.compare_digest()` ใ‚’ไฝฟใ†ใจใ€ใ“ใฎ็จฎใฎไธ€้€ฃใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆ”ปๆ’ƒใซๅฏพใ—ใฆๅฎ‰ๅ…จใซใชใ‚Šใพใ™ใ€‚ + +### ใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ { #return-the-error } + +่ช่จผๆƒ…ๅ ฑใŒไธๆญฃใงใ‚ใ‚‹ใ“ใจใ‚’ๆคœๅ‡บใ—ใŸใ‚‰ใ€ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ 401๏ผˆ่ช่จผๆƒ…ๅ ฑใŒๆไพ›ใ•ใ‚Œใชใ„ๅ ดๅˆใจๅŒใ˜๏ผ‰ใง `HTTPException` ใ‚’่ฟ”ใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใซๅ†ๅบฆใƒญใ‚ฐใ‚คใƒณใƒ—ใƒญใƒณใƒ—ใƒˆใ‚’่กจ็คบใ•ใ›ใ‚‹ใŸใ‚ใซใƒ˜ใƒƒใƒ€ใƒผ `WWW-Authenticate` ใ‚’่ฟฝๅŠ ใ—ใพใ™: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/ja/docs/advanced/security/index.md b/docs/ja/docs/advanced/security/index.md new file mode 100644 index 0000000000..069e2686cb --- /dev/null +++ b/docs/ja/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# ้ซ˜ๅบฆใชใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ { #advanced-security } + +## ่ฟฝๅŠ ๆฉŸ่ƒฝ { #additional-features } + +[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰: ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ](../../tutorial/security/index.md){.internal-link target=_blank}ใงๆ‰ฑใฃใŸใ‚‚ใฎไปฅๅค–ใซใ‚‚ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๆ‰ฑใ†ใŸใ‚ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆฌกใฎ็ฏ€ใฏๅฟ…ใšใ—ใ‚‚ใ€Œ้ซ˜ๅบฆใ€ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ‚ใชใŸใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใฏใ€ใใฎไธญใฎใ„ใšใ‚Œใ‹ใซ่งฃๆฑบ็ญ–ใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +/// + +## ใพใšใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’่ชญใ‚€ { #read-the-tutorial-first } + +ไปฅไธ‹ใฎ็ฏ€ใฏใ€ใ™ใงใซใƒกใ‚คใƒณใฎ[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰: ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ](../../tutorial/security/index.md){.internal-link target=_blank}ใ‚’่ชญใ‚“ใงใ„ใ‚‹ใ“ใจใ‚’ๅ‰ๆใจใ—ใพใ™ใ€‚ + +ใ„ใšใ‚Œใ‚‚ๅŒใ˜ๆฆ‚ๅฟตใซๅŸบใฅใ„ใฆใ„ใพใ™ใŒใ€ใ„ใใคใ‹ใฎ่ฟฝๅŠ ๆฉŸ่ƒฝใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/security/oauth2-scopes.md b/docs/ja/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..7c6cfdbf03 --- /dev/null +++ b/docs/ja/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 ใฎใ‚นใ‚ณใƒผใƒ— { #oauth2-scopes } + +OAuth2 ใฎใ‚นใ‚ณใƒผใƒ—ใฏ **FastAPI** ใง็›ดๆŽฅๅˆฉ็”จใงใใ€ใ‚ทใƒผใƒ ใƒฌใ‚นใซ็ตฑๅˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€OAuth2 ๆจ™ๆบ–ใซๅพ“ใฃใŸใ€ใ‚ˆใ‚Šใใ‚็ดฐใ‹ใชๆจฉ้™ใ‚ทใ‚นใƒ†ใƒ ใ‚’ใ€OpenAPI ๅฏพๅฟœใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใŠใ‚ˆใณ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ๏ผ‰ใซ็ตฑๅˆใงใใพใ™ใ€‚ + +ใ‚นใ‚ณใƒผใƒ—ไป˜ใใฎ OAuth2 ใฏใ€Facebookใ€Googleใ€GitHubใ€Microsoftใ€X (Twitter) ใชใฉใ€ๅคšใใฎๅคงๆ‰‹่ช่จผใƒ—ใƒญใƒใ‚คใƒ€ใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ไป•็ต„ใฟใงใ™ใ€‚ใƒฆใƒผใ‚ถใƒผใ‚„ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซ็‰นๅฎšใฎๆจฉ้™ใ‚’ไป˜ไธŽใ™ใ‚‹ใŸใ‚ใซๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใ€ŒFacebook ใงใƒญใ‚ฐใ‚คใƒณใ€ใ€ŒGoogle ใงใƒญใ‚ฐใ‚คใƒณใ€ใ€ŒGitHub ใงใƒญใ‚ฐใ‚คใƒณใ€ใ€ŒMicrosoft ใงใƒญใ‚ฐใ‚คใƒณใ€ใ€ŒX (Twitter) ใงใƒญใ‚ฐใ‚คใƒณใ€ใ™ใ‚‹ใŸใณใซใ€ใใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ‚นใ‚ณใƒผใƒ—ไป˜ใใฎ OAuth2 ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ + +ใ“ใฎ็ฏ€ใงใฏใ€ๅŒใ˜ใ‚นใ‚ณใƒผใƒ—ไป˜ใ OAuth2 ใ‚’ไฝฟใฃใฆใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใง่ช่จผใจ่ชๅฏใ‚’็ฎก็†ใ™ใ‚‹ๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +/// warning | ๆณจๆ„ + +ใ“ใ‚Œใฏใ‚„ใ‚„้ซ˜ๅบฆใชๅ†…ๅฎนใงใ™ใ€‚ใฏใ˜ใ‚ใŸใฐใ‹ใ‚Šใงใ‚ใ‚Œใฐ่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +OAuth2 ใฎใ‚นใ‚ณใƒผใƒ—ใฏๅฟ…ใšใ—ใ‚‚ๅฟ…่ฆใงใฏใชใใ€่ช่จผใจ่ชๅฏใฏๅฅฝใใชใ‚„ใ‚Šๆ–นใงๅฎŸ่ฃ…ใงใใพใ™ใ€‚ + +ใŸใ ใ—ใ€ใ‚นใ‚ณใƒผใƒ—ไป˜ใใฎ OAuth2 ใฏใ€API๏ผˆOpenAPI๏ผ‰ใ‚„ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใใ‚Œใ„ใซ็ตฑๅˆใงใใพใ™ใ€‚ + +ใจใฏใ„ใˆใ€ใ“ใ‚Œใ‚‰ใฎใ‚นใ‚ณใƒผใƒ—ใ‚„ใใฎไป–ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ๏ผ่ชๅฏ่ฆไปถใฎ้ฉ็”จใฏใ€ๅฟ…่ฆใซๅฟœใ˜ใฆใ‚ณใƒผใƒ‰ใฎไธญใง่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ๅคšใใฎๅ ดๅˆใ€ใ‚นใ‚ณใƒผใƒ—ไป˜ใ OAuth2 ใฏใ‚ชใƒผใƒใƒผใ‚นใƒšใƒƒใ‚ฏใซใชใ‚Šใˆใพใ™ใ€‚ + +ใใ‚Œใงใ‚‚ๅฟ…่ฆใ ใจๅˆ†ใ‹ใฃใฆใ„ใ‚‹ๅ ดๅˆใ‚„ใ€่ˆˆๅ‘ณใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใ“ใฎใพใพ่ชญใฟ้€ฒใ‚ใฆใใ ใ•ใ„ใ€‚ + +/// + +## OAuth2 ใฎใ‚นใ‚ณใƒผใƒ—ใจ OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 ไป•ๆง˜ใงใฏใ€ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใฏ็ฉบ็™ฝใงๅŒบๅˆ‡ใ‚‰ใ‚ŒใŸๆ–‡ๅญ—ๅˆ—ใฎไธ€่ฆงใจใ—ใฆๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ๅ„ๆ–‡ๅญ—ๅˆ—ใฎๅ†…ๅฎนใฏไปปๆ„ใงใ™ใŒใ€็ฉบ็™ฝใฏๅซใ‚ใ‚‰ใ‚Œใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใ‚นใ‚ณใƒผใƒ—ใฏใ€Œๆจฉ้™ใ€ใ‚’่กจใ—ใพใ™ใ€‚ + +OpenAPI๏ผˆไพ‹: API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ๏ผ‰ใงใฏใ€ใ€Œใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ€ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใฎไธ€ใคใŒ OAuth2 ใ‚’ไฝฟใ†ๅ ดๅˆใ€ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฎฃ่จ€ใ—ใฆๅˆฉ็”จใงใใพใ™ใ€‚ + +ๅ„ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใฏใ€ใŸใ ใฎๆ–‡ๅญ—ๅˆ—๏ผˆ็ฉบ็™ฝใชใ—๏ผ‰ใงใ™ใ€‚ + +้€šๅธธใ€็‰นๅฎšใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆจฉ้™ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐ: + +- `users:read` ใ‚„ `users:write` ใฏไธ€่ˆฌ็š„ใชไพ‹ใงใ™ใ€‚ +- `instagram_basic` ใฏ Facebook / Instagram ใงไฝฟใ‚ใ‚Œใฆใ„ใพใ™ใ€‚ +- `https://www.googleapis.com/auth/drive` ใฏ Google ใงไฝฟใ‚ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +OAuth2 ใซใŠใ„ใฆใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใฏใ€ๅฟ…่ฆใช็‰นๅฎšใฎๆจฉ้™ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ + +`:` ใฎใ‚ˆใ†ใชไป–ใฎๆ–‡ๅญ—ใŒๅซใพใ‚Œใฆใ„ใฆใ‚‚ใ€URL ใงใ‚ใฃใฆใ‚‚ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใใ‚Œใ‚‰ใฎ่ฉณ็ดฐใฏๅฎŸ่ฃ…ไพๅญ˜ใงใ™ใ€‚ + +OAuth2 ใซใจใฃใฆใฏใ€ๅ˜ใซๆ–‡ๅญ—ๅˆ—ใซ้ŽใŽใพใ›ใ‚“ใ€‚ + +/// + +## ๅ…จไฝ“ๅƒ { #global-view } + +ใพใšใ€ใƒกใ‚คใƒณใฎ**ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰**ใซใ‚ใ‚‹ [OAuth2๏ผˆใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผปใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚ใ‚Š๏ผฝ๏ผ‰ใ€Bearer ใจ JWT ใƒˆใƒผใ‚ฏใƒณ](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ใฎไพ‹ใ‹ใ‚‰ๅค‰ๆ›ดใ•ใ‚Œใ‚‹้ƒจๅˆ†ใ‚’ใ€ใ‚นใ‚ณใƒผใƒ—ไป˜ใ OAuth2 ใ‚’ไฝฟใฃใฆๆ‰‹ๆ—ฉใ่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +ใงใฏใ€ใ“ใ‚Œใ‚‰ใฎๅค‰ๆ›ดใ‚’ไธ€ใคใšใค็ขบ่ชใ—ใฆใ„ใใพใ™ใ€‚ + +## OAuth2 ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ  { #oauth2-security-scheme } + +ๆœ€ๅˆใฎๅค‰ๆ›ด็‚นใฏใ€`me` ใจ `items` ใฎ 2 ใคใฎใ‚นใ‚ณใƒผใƒ—ใ‚’ๆŒใค OAuth2 ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ใ“ใจใงใ™ใ€‚ + +`scopes` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€ๅ„ใ‚นใ‚ณใƒผใƒ—ใ‚’ใ‚ญใƒผใ€ใใฎ่ชฌๆ˜Žใ‚’ๅ€คใจใ™ใ‚‹ `dict` ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +ใ“ใ‚Œใ‚‰ใฎใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใƒญใ‚ฐใ‚คใƒณ๏ผ่ชๅฏๆ™‚ใซ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +ใใ—ใฆใ€ไป˜ไธŽใ™ใ‚‹ใ‚นใ‚ณใƒผใƒ—๏ผˆ`me`ใ€`items`๏ผ‰ใ‚’้ธๆŠžใงใใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€Facebookใ€Googleใ€GitHub ใชใฉใงใƒญใ‚ฐใ‚คใƒณๆ™‚ใซๆจฉ้™ใ‚’ไป˜ไธŽใ™ใ‚‹้š›ใจๅŒใ˜ไป•็ต„ใฟใงใ™: + + + +## ใ‚นใ‚ณใƒผใƒ—ไป˜ใใฎ JWT ใƒˆใƒผใ‚ฏใƒณ { #jwt-token-with-scopes } + +ๆฌกใซใ€ใƒˆใƒผใ‚ฏใƒณใฎ path operation ใ‚’ไฟฎๆญฃใ—ใฆใ€่ฆๆฑ‚ใ•ใ‚ŒใŸใ‚นใ‚ณใƒผใƒ—ใ‚’่ฟ”ใ™ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ + +ๅผ•ใ็ถšใๅŒใ˜ `OAuth2PasswordRequestForm` ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใงๅ—ใ‘ๅ–ใฃใŸๅ„ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅซใ‚€ใ€`str` ใฎ `list` ใงใ‚ใ‚‹ `scopes` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃใŒๅซใพใ‚Œใพใ™ใ€‚ + +ใใ—ใฆใ€ใใฎใ‚นใ‚ณใƒผใƒ—ใ‚’ JWT ใƒˆใƒผใ‚ฏใƒณใฎไธ€้ƒจใจใ—ใฆ่ฟ”ใ—ใพใ™ใ€‚ + +/// danger | ่ญฆๅ‘Š + +็ฐกๅ˜ใฎใŸใ‚ใ€ใ“ใ“ใงใฏๅ—ใ‘ๅ–ใฃใŸใ‚นใ‚ณใƒผใƒ—ใ‚’ใใฎใพใพใƒˆใƒผใ‚ฏใƒณใซ่ฟฝๅŠ ใ—ใฆใ„ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ๆœฌ็•ชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎใŸใ‚ใ€ใƒฆใƒผใ‚ถใƒผใŒๅฎŸ้š›ใซๆŒใคใ“ใจใŒใงใใ‚‹ใ‚นใ‚ณใƒผใƒ—ใ€ใพใŸใฏไบ‹ๅ‰ใซๅฎš็พฉใ—ใŸใ‚นใ‚ณใƒผใƒ—ใ ใ‘ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## path operation ใจไพๅญ˜้–ขไฟ‚ใงใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฎฃ่จ€ { #declare-scopes-in-path-operations-and-dependencies } + +ใ“ใ“ใงใฏใ€`/users/me/items/` ใฎ path operation ใŒ `items` ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฟ…่ฆใจใ™ใ‚‹ใ‚ˆใ†ใซๅฎฃ่จ€ใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใ€`fastapi` ใ‹ใ‚‰ `Security` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ„ใพใ™ใ€‚ + +`Security` ใฏ๏ผˆ`Depends` ใจๅŒๆง˜ใซ๏ผ‰ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใงใใพใ™ใŒใ€ใ•ใ‚‰ใซใ‚นใ‚ณใƒผใƒ—๏ผˆๆ–‡ๅญ—ๅˆ—๏ผ‰ใฎใƒชใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚‹ `scopes` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚ๆŒใกใพใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใ€`Security` ใซไพๅญ˜้–ขๆ•ฐ `get_current_active_user` ใ‚’ๆธกใ—ใพใ™๏ผˆ`Depends` ใจๅŒๆง˜ใงใ™๏ผ‰ใ€‚ + +ๅŠ ใˆใฆใ€`items` ใจใ„ใ† 1 ใคใฎใ‚นใ‚ณใƒผใƒ—๏ผˆ่ค‡ๆ•ฐใงใ‚‚ๅฏ๏ผ‰ใ‚’ๅซใ‚€ `list` ใ‚‚ๆธกใ—ใพใ™ใ€‚ + +ไพๅญ˜้–ขๆ•ฐ `get_current_active_user` ใฏใ€`Depends` ใ ใ‘ใงใชใ `Security` ใงใ‚‚ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚่‡ช่บซใฎใ‚ตใƒ–ไพๅญ˜้–ขๆ•ฐ๏ผˆ`get_current_user`๏ผ‰ใ‚’ๅฎฃ่จ€ใ—ใ€ใ•ใ‚‰ใซใ‚นใ‚ณใƒผใƒ—่ฆไปถใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ + +ใ“ใฎๅ ดๅˆใ€`me` ใ‚นใ‚ณใƒผใƒ—ใ‚’่ฆๆฑ‚ใ—ใพใ™๏ผˆ่ค‡ๆ•ฐใฎใ‚นใ‚ณใƒผใƒ—ใ‚‚ๅฏ๏ผ‰ใ€‚ + +/// note | ๅ‚™่€ƒ + +็•ฐใชใ‚‹ๅ ดๆ‰€ใง็•ฐใชใ‚‹ใ‚นใ‚ณใƒผใƒ—ใ‚’่ฟฝๅŠ ใ™ใ‚‹ๅฟ…่ฆใฏๅฟ…ใšใ—ใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใ“ใงใฏใ€**FastAPI** ใŒ็•ฐใชใ‚‹ใƒฌใƒ™ใƒซใงๅฎฃ่จ€ใ•ใ‚ŒใŸใ‚นใ‚ณใƒผใƒ—ใ‚’ใฉใฎใ‚ˆใ†ใซๆ‰ฑใ†ใ‹ใ‚’็คบใ™ใŸใ‚ใซใใ†ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | ๆŠ€่ก“่ฉณ็ดฐ + +`Security` ใฏๅฎŸ้š›ใซใฏ `Depends` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ€ๅพŒ่ฟฐใ™ใ‚‹่ฟฝๅŠ ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒ 1 ใคใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ + +ใ—ใ‹ใ— `Depends` ใฎไปฃใ‚ใ‚Šใซ `Security` ใ‚’ไฝฟใ†ใ“ใจใงใ€**FastAPI** ใฏใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฎฃ่จ€ใƒปๅ†…้ƒจๅˆฉ็”จใงใใ€OpenAPI ใง API ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใงใใ‚‹ใจๅˆคๆ–ญใ—ใพใ™ใ€‚ + +ใชใŠใ€`fastapi` ใ‹ใ‚‰ `Query`ใ€`Path`ใ€`Depends`ใ€`Security` ใชใฉใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹้š›ใ€ใใ‚Œใ‚‰ใฏๅฎŸ้š›ใซใฏ็‰นๆฎŠใชใ‚ฏใƒฉใ‚นใ‚’่ฟ”ใ™้–ขๆ•ฐใงใ™ใ€‚ + +/// + +## `SecurityScopes` ใ‚’ไฝฟใ† { #use-securityscopes } + +ๆฌกใซใ€ไพๅญ˜้–ขๆ•ฐ `get_current_user` ใ‚’ๆ›ดๆ–ฐใ—ใพใ™ใ€‚ + +ใ“ใ‚ŒใฏไธŠ่จ˜ใฎไพๅญ˜้–ขไฟ‚ใ‹ใ‚‰ไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ“ใงใ€ๅ…ˆใปใฉไฝœๆˆใ—ใŸๅŒใ˜ OAuth2 ใ‚นใ‚ญใƒผใƒ ใ‚’ไพๅญ˜้–ขไฟ‚๏ผˆ`oauth2_scheme`๏ผ‰ใจใ—ใฆๅฎฃ่จ€ใ—ใฆไฝฟใ„ใพใ™ใ€‚ + +ใ“ใฎไพๅญ˜้–ขๆ•ฐ่‡ชไฝ“ใฏใ‚นใ‚ณใƒผใƒ—่ฆไปถใ‚’ๆŒใŸใชใ„ใŸใ‚ใ€`oauth2_scheme` ใซใฏ `Depends` ใ‚’ไฝฟใˆใพใ™ใ€‚ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ณใƒผใƒ—ใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ๅ ดๅˆใฏ `Security` ใ‚’ไฝฟใ†ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ•ใ‚‰ใซใ€`fastapi.security` ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹็‰นๅˆฅใชๅž‹ `SecurityScopes` ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ + +ใ“ใฎ `SecurityScopes` ใ‚ฏใƒฉใ‚นใฏ `Request` ใซไผผใฆใ„ใพใ™๏ผˆ`Request` ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็›ดๆŽฅๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซไฝฟใ„ใพใ—ใŸ๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## `scopes` ใ‚’ไฝฟใ† { #use-the-scopes } + +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `security_scopes` ใฏ `SecurityScopes` ๅž‹ใซใชใ‚Šใพใ™ใ€‚ + +ใ“ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏใ€่‡ช่บซใŠใ‚ˆใณใ“ใ‚Œใ‚’ใ‚ตใƒ–ไพๅญ˜ใจใ—ใฆไฝฟใ†ใ™ในใฆใฎไพๅญ˜้–ขไฟ‚ใง่ฆๆฑ‚ใ•ใ‚Œใ‚‹ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅซใ‚€ `scopes` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃ๏ผˆใƒชใ‚นใƒˆ๏ผ‰ใ‚’ๆŒใกใพใ™ใ€‚ใคใพใ‚Šใ€ใ™ในใฆใฎใ€Œไพๅญ˜ๅ…ƒใ€... ๅฐ‘ใ—ๅˆ†ใ‹ใ‚Šใซใใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใŒใ€ๅพŒใงๅ†ๅบฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +`security_scopes`๏ผˆ`SecurityScopes` ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น๏ผ‰ใฏใ€่ฆๆฑ‚ใ•ใ‚ŒใŸใ‚นใ‚ณใƒผใƒ—ใ‚’็ฉบ็™ฝใง้€ฃ็ตใ—ใŸ 1 ใคใฎๆ–‡ๅญ—ๅˆ—ใ‚’่ฟ”ใ™ `scope_str` ใ‚‚ๆไพ›ใ—ใพใ™๏ผˆใ“ใ‚Œใ‚’ไฝฟใ„ใพใ™๏ผ‰ใ€‚ + +ๅพŒใง่ค‡ๆ•ฐ็ฎ‡ๆ‰€ใงๅ†ๅˆฉ็”จ๏ผˆraise๏ผ‰ใงใใ‚‹ใ‚ˆใ†ใซใ€`HTTPException` ใ‚’ 1 ใคไฝœๆˆใ—ใพใ™ใ€‚ + +ใ“ใฎไพ‹ๅค–ใซใฏใ€่ฆๆฑ‚ใ•ใ‚ŒใŸใ‚นใ‚ณใƒผใƒ—ใŒใ‚ใ‚Œใฐใใ‚Œใ‚‰ใ‚’็ฉบ็™ฝๅŒบๅˆ‡ใ‚Šใฎๆ–‡ๅญ—ๅˆ—๏ผˆ`scope_str` ใ‚’ไฝฟ็”จ๏ผ‰ใจใ—ใฆๅซใ‚ใพใ™ใ€‚ใ“ใฎใ‚นใ‚ณใƒผใƒ—ๆ–‡ๅญ—ๅˆ—ใฏ `WWW-Authenticate` ใƒ˜ใƒƒใƒ€ใซๅ…ฅใ‚Œใพใ™๏ผˆไป•ๆง˜ใฎไธ€้ƒจใงใ™๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## `username` ใจใƒ‡ใƒผใ‚ฟๆง‹้€ ใฎๆคœ่จผ { #verify-the-username-and-data-shape } + +`username` ใ‚’ๅ–ๅพ—ใงใใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใ€ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅ–ใ‚Šๅ‡บใ—ใพใ™ใ€‚ + +ใใ—ใฆใ€ใใฎใƒ‡ใƒผใ‚ฟใ‚’ Pydantic ใƒขใƒ‡ใƒซใงๆคœ่จผใ—ใพใ™๏ผˆ`ValidationError` ไพ‹ๅค–ใ‚’ๆ•ๆ‰๏ผ‰ใ€‚JWT ใƒˆใƒผใ‚ฏใƒณใฎ่ชญใฟๅ–ใ‚Šใ‚„ Pydantic ใซใ‚ˆใ‚‹ใƒ‡ใƒผใ‚ฟๆคœ่จผใงใ‚จใƒฉใƒผใŒ็™บ็”Ÿใ—ใŸๅ ดๅˆใฏใ€ๅ…ˆใปใฉไฝœๆˆใ—ใŸ `HTTPException` ใ‚’้€ๅ‡บใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใ€Pydantic ใƒขใƒ‡ใƒซ `TokenData` ใซๆ–ฐใ—ใ„ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃ `scopes` ใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ + +Pydantic ใงใƒ‡ใƒผใ‚ฟใ‚’ๆคœ่จผใ™ใ‚‹ใ“ใจใงใ€ไพ‹ใˆใฐใ‚นใ‚ณใƒผใƒ—ใฏ `str` ใฎ `list`ใ€`username` ใฏ `str` ใจใ„ใฃใŸใ€ๆญฃ็ขบใชๅž‹ใซใชใฃใฆใ„ใ‚‹ใ“ใจใ‚’ไฟ่จผใงใใพใ™ใ€‚ + +ใใ†ใ—ใฆใŠใ‘ใฐใ€ไพ‹ใˆใฐ่ชคใฃใฆ `dict` ใชใฉใŒๅ…ฅใฃใฆๅพŒใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’็ ดๅฃŠใ—ใฆใ—ใพใ„ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒชใ‚นใ‚ฏใซใชใ‚‹ใ€ใจใ„ใฃใŸไบ‹ๆ…‹ใ‚’้ฟใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ + +ใพใŸใ€ใใฎ `username` ใ‚’ๆŒใคใƒฆใƒผใ‚ถใƒผใŒๅญ˜ๅœจใ™ใ‚‹ใ“ใจใ‚‚็ขบ่ชใ—ใ€ๅญ˜ๅœจใ—ใชใ‘ใ‚Œใฐใ€ใ‚„ใฏใ‚Šๅ…ˆใปใฉใฎไพ‹ๅค–ใ‚’้€ๅ‡บใ—ใพใ™ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## `scopes` ใฎๆคœ่จผ { #verify-the-scopes } + +ใ“ใฎไพๅญ˜้–ขๆ•ฐใŠใ‚ˆใณใ™ในใฆใฎไพๅญ˜ๅ…ƒ๏ผˆpath operation ใ‚’ๅซใ‚€๏ผ‰ใŒ่ฆๆฑ‚ใ™ใ‚‹ใ™ในใฆใฎใ‚นใ‚ณใƒผใƒ—ใŒใ€ๅ—ใ‘ๅ–ใฃใŸใƒˆใƒผใ‚ฏใƒณใซๅซใพใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’ๆคœ่จผใ—ใ€ๅซใพใ‚Œใฆใ„ใชใ‘ใ‚Œใฐ `HTTPException` ใ‚’้€ๅ‡บใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใ€ใ“ใ‚Œใ‚‰ใ™ในใฆใฎใ‚นใ‚ณใƒผใƒ—ใ‚’ `str` ใฎ `list` ใจใ—ใฆๅซใ‚€ `security_scopes.scopes` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## ไพๅญ˜้–ขไฟ‚ใƒ„ใƒชใƒผใจใ‚นใ‚ณใƒผใƒ— { #dependency-tree-and-scopes } + +ไพๅญ˜้–ขไฟ‚ใƒ„ใƒชใƒผใจใ‚นใ‚ณใƒผใƒ—ใ‚’ใ‚‚ใ†ไธ€ๅบฆ่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ + +`get_current_active_user` ไพๅญ˜้–ขไฟ‚ใฏ `get_current_user` ใ‚’ใ‚ตใƒ–ไพๅญ˜ใจใ—ใฆๆŒใคใŸใ‚ใ€`get_current_active_user` ใงๅฎฃ่จ€ใ•ใ‚ŒใŸ `"me"` ใ‚นใ‚ณใƒผใƒ—ใฏใ€`get_current_user` ใซๆธกใ•ใ‚Œใ‚‹ `security_scopes.scopes` ใฎๅฟ…้ ˆใ‚นใ‚ณใƒผใƒ—ไธ€่ฆงใซๅซใพใ‚Œใพใ™ใ€‚ + +path operation ่‡ชไฝ“ใ‚‚ `"items"` ใ‚นใ‚ณใƒผใƒ—ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใ€ใ“ใ‚Œใ‚‚ `get_current_user` ใซๆธกใ•ใ‚Œใ‚‹ `security_scopes.scopes` ใซๅซใพใ‚Œใพใ™ใ€‚ + +ไพๅญ˜้–ขไฟ‚ใจใ‚นใ‚ณใƒผใƒ—ใฎ้šŽๅฑคใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +- *path operation* `read_own_items` ใซใฏ: + - ไพๅญ˜้–ขไฟ‚ใซๅฏพใ—ใฆๅฟ…้ ˆใ‚นใ‚ณใƒผใƒ— `["items"]` ใŒใ‚ใ‚‹: + - `get_current_active_user`: + - ไพๅญ˜้–ขๆ•ฐ `get_current_active_user` ใซใฏ: + - ไพๅญ˜้–ขไฟ‚ใซๅฏพใ—ใฆๅฟ…้ ˆใ‚นใ‚ณใƒผใƒ— `["me"]` ใŒใ‚ใ‚‹: + - `get_current_user`: + - ไพๅญ˜้–ขๆ•ฐ `get_current_user` ใซใฏ: + - ่‡ช่บซใซๅฟ…้ ˆใ‚นใ‚ณใƒผใƒ—ใฏใชใ„ใ€‚ + - `oauth2_scheme` ใ‚’ไฝฟใ†ไพๅญ˜้–ขไฟ‚ใŒใ‚ใ‚‹ใ€‚ + - `SecurityScopes` ๅž‹ใฎ `security_scopes` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ใ‚‹: + - ใ“ใฎ `security_scopes` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ€ไธŠใงๅฎฃ่จ€ใ•ใ‚ŒใŸใ™ในใฆใฎใ‚นใ‚ณใƒผใƒ—ใ‚’ๅซใ‚€ `list` ใ‚’ๆŒใค `scopes` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃใ‚’ๆŒใคใ€‚ใ—ใŸใŒใฃใฆ: + - *path operation* `read_own_items` ใงใฏใ€`security_scopes.scopes` ใฏ `["me", "items"]` ใ‚’ๅซใ‚€ใ€‚ + - *path operation* `read_users_me` ใงใฏใ€`security_scopes.scopes` ใฏ `["me"]` ใ‚’ๅซใ‚€ใ€‚ใ“ใ‚Œใฏไพๅญ˜้–ขไฟ‚ `get_current_active_user` ใซๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใŸใ‚ใ€‚ + - *path operation* `read_system_status` ใงใฏใ€`security_scopes.scopes` ใฏ `[]`๏ผˆ็ฉบ๏ผ‰ใซใชใ‚‹ใ€‚`scopes` ใ‚’ๆŒใค `Security` ใ‚’ๅฎฃ่จ€ใ—ใฆใŠใ‚‰ใšใ€ใใฎไพๅญ˜้–ขไฟ‚ `get_current_user` ใ‚‚ `scopes` ใ‚’ๅฎฃ่จ€ใ—ใฆใ„ใชใ„ใŸใ‚ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +้‡่ฆใงใ€Œ้ญ”ๆณ•ใฎใ‚ˆใ†ใ€ใช็‚นใฏใ€`get_current_user` ใŒ path operation ใ”ใจใซ็•ฐใชใ‚‹ `scopes` ใฎใƒชใ‚นใƒˆใ‚’ใƒใ‚งใƒƒใ‚ฏใ™ใ‚‹ใ“ใจใซใชใ‚‹ใ€ใจใ„ใ†ใ“ใจใงใ™ใ€‚ + +ใใ‚Œใฏใ€ใใ‚Œใžใ‚Œใฎ path operation ใจใ€ใใฎ path operation ใฎไพๅญ˜้–ขไฟ‚ใƒ„ใƒชใƒผๅ†…ใฎๅ„ไพๅญ˜้–ขไฟ‚ใงๅฎฃ่จ€ใ•ใ‚ŒใŸ `scopes` ใซใ‚ˆใฃใฆๆฑบใพใ‚Šใพใ™ใ€‚ + +/// + +## `SecurityScopes` ใฎ่ฉณ็ดฐ { #more-details-about-securityscopes } + +`SecurityScopes` ใฏใฉใฎๅœฐ็‚นใงใ‚‚ใ€่ค‡ๆ•ฐ็ฎ‡ๆ‰€ใงใ‚‚ไฝฟใˆใพใ™ใ€‚ใ€Œใƒซใƒผใƒˆใ€ใฎไพๅญ˜้–ขไฟ‚ใงใ‚ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ๅธธใซใ€ใใฎๆ™‚็‚นใฎ `Security` ไพๅญ˜้–ขไฟ‚ใจใ€**ใใฎ็‰นๅฎšใฎ** path operation ใจ **ใใฎ็‰นๅฎšใฎ** ไพๅญ˜้–ขไฟ‚ใƒ„ใƒชใƒผใซใŠใ‘ใ‚‹ใ€ใ™ในใฆใฎไพๅญ˜ๅ…ƒใงๅฎฃ่จ€ใ•ใ‚ŒใŸใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ณใƒผใƒ—ใ‚’ๆŒใกใพใ™ใ€‚ + +`SecurityScopes` ใซใฏไพๅญ˜ๅ…ƒใงๅฎฃ่จ€ใ•ใ‚ŒใŸใ™ในใฆใฎใ‚นใ‚ณใƒผใƒ—ใŒๅ…ฅใ‚‹ใŸใ‚ใ€ใƒˆใƒผใ‚ฏใƒณใŒๅฟ…่ฆใชใ‚นใ‚ณใƒผใƒ—ใ‚’ๆŒใฃใฆใ„ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’ไธญๅคฎใฎไพๅญ˜้–ขๆ•ฐใงๆคœ่จผใ—ใ€path operation ใ”ใจใซ็•ฐใชใ‚‹ใ‚นใ‚ณใƒผใƒ—่ฆไปถใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ€ใจใ„ใฃใŸไฝฟใ„ๆ–นใŒใงใใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฏ path operation ใ”ใจใซ็‹ฌ็ซ‹ใ—ใฆๆคœ่จผใ•ใ‚Œใพใ™ใ€‚ + +## ใƒใ‚งใƒƒใ‚ฏ { #check-it } + +API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’้–‹ใใจใ€่ช่จผใ—ใฆใ€่จฑๅฏใ™ใ‚‹ใ‚นใ‚ณใƒผใƒ—ใ‚’ๆŒ‡ๅฎšใงใใพใ™ใ€‚ + + + +ใฉใฎใ‚นใ‚ณใƒผใƒ—ใ‚‚้ธๆŠžใ—ใชใ„ๅ ดๅˆใฏใ€Œ่ช่จผๆธˆใฟใ€ใซใฏใชใ‚Šใพใ™ใŒใ€`/users/me/` ใ‚„ `/users/me/items/` ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใ‚ˆใ†ใจใ™ใ‚‹ใจใ€ๆจฉ้™ใŒไธ่ถณใ—ใฆใ„ใ‚‹ใจใ„ใ†ใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚`/status/` ใซใฏๅผ•ใ็ถšใใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ + +`me` ใ‚นใ‚ณใƒผใƒ—ใ ใ‘ใ‚’้ธๆŠžใ—ใ€`items` ใ‚นใ‚ณใƒผใƒ—ใ‚’้ธๆŠžใ—ใชใ„ๅ ดๅˆใฏใ€`/users/me/` ใซใฏใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใŒใ€`/users/me/items/` ใซใฏใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใฏใ€ใƒฆใƒผใ‚ถใƒผใŒใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซไธŽใˆใŸๆจฉ้™ใฎ็ฏ„ๅ›ฒใซๅฟœใ˜ใฆใ€ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒใ“ใ‚Œใ‚‰ใฎ path operation ใฎใ„ใšใ‚Œใ‹ใซใ€ใƒฆใƒผใ‚ถใƒผใ‹ใ‚‰ๆไพ›ใ•ใ‚ŒใŸใƒˆใƒผใ‚ฏใƒณใงใ‚ขใ‚ฏใ‚ปใ‚นใ—ใ‚ˆใ†ใจใ—ใŸใจใใซ่ตทใ“ใ‚‹ๅ‹•ไฝœใงใ™ใ€‚ + +## ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃ็ตฑๅˆใซใคใ„ใฆ { #about-third-party-integrations } + +ใ“ใฎไพ‹ใงใฏใ€OAuth2 ใฎใ€Œpasswordใ€ใƒ•ใƒญใƒผใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€๏ผˆใŠใใ‚‰ใ่‡ชๅ‰ใฎใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใง๏ผ‰่‡ชๅˆ†ใŸใกใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใƒญใ‚ฐใ‚คใƒณใ™ใ‚‹ๅ ดๅˆใซ้ฉใ—ใฆใ„ใพใ™ใ€‚ + +่‡ชๅˆ†ใŸใกใง็ฎก็†ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€`username` ใจ `password` ใ‚’ๅ—ใ‘ๅ–ใ‚‹็›ธๆ‰‹ใ‚’ไฟก้ ผใงใใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ไป–่€…ใŒๆŽฅ็ถšใ™ใ‚‹ OAuth2 ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆFacebookใ€Googleใ€GitHub ใชใฉใซ็›ธๅฝ“ใ™ใ‚‹่ช่จผใƒ—ใƒญใƒใ‚คใƒ€๏ผ‰ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๅ ดๅˆใฏใ€ไป–ใฎใ„ใšใ‚Œใ‹ใฎใƒ•ใƒญใƒผใ‚’ไฝฟ็”จใ™ในใใงใ™ใ€‚ + +ๆœ€ใ‚‚ไธ€่ˆฌ็š„ใชใฎใฏ implicit ใƒ•ใƒญใƒผใงใ™ใ€‚ + +ๆœ€ใ‚‚ๅฎ‰ๅ…จใชใฎใฏ code ใƒ•ใƒญใƒผใงใ™ใŒใ€ๆ‰‹้ †ใŒๅคšใๅฎŸ่ฃ…ใŒใ‚ˆใ‚Š่ค‡้›‘ใงใ™ใ€‚่ค‡้›‘ใชใŸใ‚ใ€ๅคšใใฎใƒ—ใƒญใƒใ‚คใƒ€ใฏ็ตๅฑ€ implicit ใƒ•ใƒญใƒผใ‚’ๆŽจๅฅจใ™ใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// note | ๅ‚™่€ƒ + +ๅ„่ช่จผใƒ—ใƒญใƒใ‚คใƒ€ใŒใƒ•ใƒญใƒผใซ็‹ฌ่‡ชใฎๅ็งฐใ‚’ไป˜ใ‘ใ€่‡ช็คพใฎใƒ–ใƒฉใƒณใƒ‰ใฎไธ€้ƒจใซใ™ใ‚‹ใฎใฏไธ€่ˆฌ็š„ใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ๆœ€็ต‚็š„ใซใฏๅŒใ˜ OAuth2 ๆจ™ๆบ–ใ‚’ๅฎŸ่ฃ…ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +**FastAPI** ใซใฏใ€ใ“ใ‚Œใ‚‰ใ™ในใฆใฎ OAuth2 ่ช่จผใƒ•ใƒญใƒผๅ‘ใ‘ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใŒ `fastapi.security.oauth2` ใซๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +## ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ `dependencies` ใงใฎ `Security` { #security-in-decorator-dependencies } + +ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใฎ `dependencies` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ `Depends` ใฎ `list` ใ‚’ๅฎš็พฉใงใใ‚‹ใฎใจๅŒๆง˜๏ผˆ[path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใงใฎไพๅญ˜้–ขไฟ‚](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ๅ‚็…ง๏ผ‰ใ€ใ“ใ“ใง `scopes` ใ‚’ๆŒ‡ๅฎšใ—ใŸ `Security` ใ‚‚ไฝฟ็”จใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/settings.md b/docs/ja/docs/advanced/settings.md new file mode 100644 index 0000000000..5508ad6d91 --- /dev/null +++ b/docs/ja/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# ่จญๅฎšใจ็’ฐๅขƒๅค‰ๆ•ฐ { #settings-and-environment-variables } + +ๅคšใใฎๅ ดๅˆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏๅค–้ƒจใฎ่จญๅฎšใ‚„ๆง‹ๆˆใ‚’ๅฟ…่ฆใจใ—ใพใ™ใ€‚ใŸใจใˆใฐใ€ใ‚ทใƒผใ‚ฏใƒฌใƒƒใƒˆใ‚ญใƒผใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น่ช่จผๆƒ…ๅ ฑใ€ใƒกใƒผใƒซใ‚ตใƒผใƒ“ใ‚นใฎ่ช่จผๆƒ…ๅ ฑใชใฉใงใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎ่จญๅฎšใฎๅคšใใฏๅฏๅค‰๏ผˆๅค‰ๆ›ดใ•ใ‚Œใ†ใ‚‹๏ผ‰ใงใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎURLใฎใ‚ˆใ†ใชใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ใพใŸใ€ๅคšใใฏใ‚ทใƒผใ‚ฏใƒฌใƒƒใƒˆใฎใ‚ˆใ†ใซๆฉŸๅพฎใชๆƒ…ๅ ฑใงใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่ชญใฟๅ–ใ‚‹็’ฐๅขƒๅค‰ๆ•ฐใงๆไพ›ใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +็’ฐๅขƒๅค‰ๆ•ฐใซใคใ„ใฆ็†่งฃใ™ใ‚‹ใซใฏใ€[็’ฐๅขƒๅค‰ๆ•ฐ](../environment-variables.md){.internal-link target=_blank}ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ๅž‹ใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ { #types-and-validation } + +ใ“ใ‚Œใ‚‰ใฎ็’ฐๅขƒๅค‰ๆ•ฐใฏ Python ใฎๅค–้ƒจใซใ‚ใ‚Šใ€ไป–ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚„ใ‚ทใ‚นใƒ†ใƒ ๅ…จไฝ“๏ผˆLinuxใ€Windowsใ€macOS ใจใ„ใฃใŸ็•ฐใชใ‚‹OSใ‚’ๅซใ‚€๏ผ‰ใจไบ’ๆ›ๆ€งใŒๅฟ…่ฆใชใŸใ‚ใ€ๆ–‡ๅญ—ๅˆ—ใƒ†ใ‚ญใ‚นใƒˆใฎใฟใ‚’ๆ‰ฑใˆใพใ™ใ€‚ + +ใคใพใ‚Šใ€Python ใง็’ฐๅขƒๅค‰ๆ•ฐใ‹ใ‚‰่ชญใฟๅ–ใ‚‰ใ‚Œใ‚‹ๅ€คใฏใ™ในใฆ `str` ใซใชใ‚Šใ€ไป–ใฎๅž‹ใธใฎๅค‰ๆ›ใ‚„ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใฏใ‚ณใƒผใƒ‰ใง่กŒใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +## Pydantic ใฎ `Settings` { #pydantic-settings } + +ๅนธใ„ใชใ“ใจใซใ€Pydantic ใซใฏ็’ฐๅขƒๅค‰ๆ•ฐใ‹ใ‚‰ๆฅใ‚‹่จญๅฎšใ‚’ๆ‰ฑใ†ใŸใ‚ใฎๅ„ชใ‚ŒใŸใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใŒใ‚ใ‚Šใ€Pydantic: Settings management ใงๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +### `pydantic-settings` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-pydantic-settings } + +ใพใšใ€[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€`pydantic-settings` ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +ใพใŸใ€ๆฌกใฎใ‚ˆใ†ใซ `all` ใ‚จใ‚ฏใ‚นใƒˆใƒฉใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจไป˜ๅฑžใ—ใพใ™: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### `Settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆ { #create-the-settings-object } + +Pydantic ใ‹ใ‚‰ `BaseSettings` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆใ€ใใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ Pydantic ใƒขใƒ‡ใƒซใจใปใผๅŒใ˜ใงใ™ใ€‚ + +Pydantic ใƒขใƒ‡ใƒซใจๅŒๆง˜ใซใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจ๏ผˆๅฟ…่ฆใชใ‚‰๏ผ‰ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใคใ‚ฏใƒฉใ‚นๅฑžๆ€งใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ + +`Field()` ใซใ‚ˆใ‚‹่ฟฝๅŠ ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใชใฉใ€Pydantic ใƒขใƒ‡ใƒซใงไฝฟใˆใ‚‹ใฎใจๅŒใ˜ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณๆฉŸ่ƒฝใ‚’ใ™ในใฆๅˆฉ็”จใงใใพใ™ใ€‚ + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ‚ณใƒ”ใƒš็”จใซๆ‰‹ๆ—ฉใไฝฟใ„ใŸใ„ๅ ดๅˆใฏใ€ใ“ใฎไพ‹ใงใฏใชใใ€ไธ‹ใฎๆœ€ๅพŒใฎไพ‹ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ + +/// + +ใใฎๅพŒใ€ใใฎ `Settings` ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น๏ผˆใ“ใฎไพ‹ใงใฏ `settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใ‚’ไฝœๆˆใ™ใ‚‹ใจใ€Pydantic ใฏ็’ฐๅขƒๅค‰ๆ•ฐใ‚’ๅคงๆ–‡ๅญ—ๅฐๆ–‡ๅญ—ใ‚’ๅŒบๅˆฅใ›ใšใซ่ชญใฟๅ–ใ‚Šใพใ™ใ€‚ใคใพใ‚Šใ€ๅคงๆ–‡ๅญ—ใฎ `APP_NAME` ใจใ„ใ†ๅค‰ๆ•ฐใฏใ€ๅฑžๆ€ง `app_name` ใซๅฏพใ—ใฆใ‚‚่ชญใฟๅ–ใ‚‰ใ‚Œใพใ™ใ€‚ + +ๆฌกใซใ€ใƒ‡ใƒผใ‚ฟใŒๅค‰ๆ›ใƒปใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ•ใ‚Œใพใ™ใ€‚ใ—ใŸใŒใฃใฆใ€`settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝฟใ†ใจใ€ๅฎฃ่จ€ใ—ใŸๅž‹ใฎใƒ‡ใƒผใ‚ฟ๏ผˆไพ‹: `items_per_user` ใฏ `int`๏ผ‰ใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ + +### `settings` ใฎไฝฟ็”จ { #use-the-settings } + +ๆฌกใซใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๆ–ฐใ—ใ„ `settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝฟ็”จใงใใพใ™: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### ใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒ { #run-the-server } + +ๆฌกใซใ€่จญๅฎšใ‚’็’ฐๅขƒๅค‰ๆ•ฐใจใ—ใฆๆธกใ—ใฆใ‚ตใƒผใƒใƒผใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ใŸใจใˆใฐใ€`ADMIN_EMAIL` ใจ `APP_NAME` ใ‚’ๆฌกใฎใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +1ใคใฎใ‚ณใƒžใƒณใƒ‰ใซ่ค‡ๆ•ฐใฎ็’ฐๅขƒๅค‰ๆ•ฐใ‚’่จญๅฎšใ™ใ‚‹ใซใฏใ€ใ‚นใƒšใƒผใ‚นใงๅŒบๅˆ‡ใฃใฆใ‚ณใƒžใƒณใƒ‰ใฎๅ‰ใซไธฆในใพใ™ใ€‚ + +/// + +ใ™ใ‚‹ใจใ€`admin_email` ใฎ่จญๅฎšใฏ `"deadpool@example.com"` ใซ่จญๅฎšใ•ใ‚Œใพใ™ใ€‚ + +`app_name` ใฏ `"ChimichangApp"` ใซใชใ‚Šใพใ™ใ€‚ + +`items_per_user` ใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฎ `50` ใฎใพใพใงใ™ใ€‚ + +## ๅˆฅใƒขใ‚ธใƒฅใƒผใƒซใงใฎ่จญๅฎš { #settings-in-another-module } + +[ๅคง่ฆๆจกใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซ](../tutorial/bigger-applications.md){.internal-link target=_blank} ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€ใ“ใ‚Œใ‚‰ใฎ่จญๅฎšใ‚’ๅˆฅใฎใƒขใ‚ธใƒฅใƒผใƒซใƒ•ใ‚กใ‚คใƒซใซ็ฝฎใใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใŸใจใˆใฐใ€`config.py` ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใซๆฌกใฎใ‚ˆใ†ใซๆ›ธใ‘ใพใ™: + +{* ../../docs_src/settings/app01_py310/config.py *} + +ใใ—ใฆใ€`main.py` ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใงใใ‚Œใ‚’ไฝฟใ„ใพใ™: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +[ๅคง่ฆๆจกใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซ](../tutorial/bigger-applications.md){.internal-link target=_blank} ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€`__init__.py` ใƒ•ใ‚กใ‚คใƒซใ‚‚ๅฟ…่ฆใงใ™ใ€‚ + +/// + +## ไพๅญ˜้–ขไฟ‚ใงใฎ่จญๅฎš { #settings-in-a-dependency } + +ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€ใฉใ“ใงใ‚‚ไฝฟใ†ใ‚ฐใƒญใƒผใƒใƒซใช `settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆŒใคไปฃใ‚ใ‚Šใซใ€ไพๅญ˜้–ขไฟ‚ใ‹ใ‚‰่จญๅฎšใ‚’ๆไพ›ใ™ใ‚‹ใจไพฟๅˆฉใชใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏ็‰นใซใƒ†ใ‚นใƒˆๆ™‚ใซๆœ‰็”จใงใ€ไพๅญ˜้–ขไฟ‚ใ‚’็‹ฌ่‡ชใฎใ‚ซใ‚นใ‚ฟใƒ ่จญๅฎšใง็ฐกๅ˜ใซใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ + +### ่จญๅฎšใƒ•ใ‚กใ‚คใƒซ { #the-config-file } + +ๅ‰ใฎไพ‹ใ‹ใ‚‰็ถšใ‘ใ‚‹ใจใ€`config.py` ใƒ•ใ‚กใ‚คใƒซใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +ใ“ใ“ใงใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น `settings = Settings()` ใ‚’ไฝœๆˆใ—ใฆใ„ใชใ„ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +### ใƒกใ‚คใƒณใ‚ขใƒ—ใƒชใƒ•ใ‚กใ‚คใƒซ { #the-main-app-file } + +ใ“ใ“ใงใฏใ€ๆ–ฐใ—ใ„ `config.Settings()` ใ‚’่ฟ”ใ™ไพๅญ˜้–ขไฟ‚ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`@lru_cache` ใซใคใ„ใฆใฏๅพŒใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +ไปŠใฏ `get_settings()` ใŒๆ™ฎ้€šใฎ้–ขๆ•ฐใ ใจ่€ƒใˆใฆใใ ใ•ใ„ใ€‚ + +/// + +ใใ—ใฆใ€*path operation ้–ขๆ•ฐ*ใ‹ใ‚‰ไพๅญ˜้–ขไฟ‚ใจใ—ใฆ่ฆๆฑ‚ใ—ใ€ๅฟ…่ฆใชๅ ดๆ‰€ใงใฉใ“ใงใ‚‚ไฝฟใˆใพใ™ใ€‚ + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### ่จญๅฎšใจใƒ†ใ‚นใƒˆ { #settings-and-testing } + +ๆฌกใซใ€`get_settings` ใฎไพๅญ˜้–ขไฟ‚ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ‚’ไฝœใ‚‹ใ“ใจใงใ€ใƒ†ใ‚นใƒˆไธญใซๅˆฅใฎ่จญๅฎšใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆไพ›ใ™ใ‚‹ใฎใŒใจใฆใ‚‚็ฐกๅ˜ใซใชใ‚Šใพใ™: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +ไพๅญ˜้–ขไฟ‚ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใฏใ€ๆ–ฐใ—ใ„ `Settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœใ‚‹้š›ใซ `admin_email` ใซๆ–ฐใ—ใ„ๅ€คใ‚’่จญๅฎšใ—ใ€ใใฎๆ–ฐใ—ใ„ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใใ—ใฆใ€ใใ‚ŒใŒไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’ใƒ†ใ‚นใƒˆใงใใพใ™ใ€‚ + +## `.env` ใƒ•ใ‚กใ‚คใƒซใฎ่ชญใฟ่พผใฟ { #reading-a-env-file } + +ๅค‰ๆ›ดใŒๅคšใใชใ‚Šใใ†ใช่จญๅฎšใŒๅคšๆ•ฐใ‚ใ‚‹ๅ ดๅˆใ€็’ฐๅขƒใ”ใจใซใƒ•ใ‚กใ‚คใƒซใซๅ…ฅใ‚Œใฆใ€็’ฐๅขƒๅค‰ๆ•ฐใจใ—ใฆใใ“ใ‹ใ‚‰่ชญใฟ่พผใ‚€ใจไพฟๅˆฉใชใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใฎใƒ—ใƒฉใ‚ฏใƒ†ใ‚ฃใ‚นใฏๅๅˆ†ใซไธ€่ˆฌ็š„ใงๅๅ‰ใ‚‚ใ‚ใ‚Šใ€ใ“ใ‚Œใ‚‰ใฎ็’ฐๅขƒๅค‰ๆ•ฐใฏ้€šๅธธ `.env` ใจใ„ใ†ใƒ•ใ‚กใ‚คใƒซใซ็ฝฎใ‹ใ‚Œใ€ใใฎใƒ•ใ‚กใ‚คใƒซใฏใ€Œdotenvใ€ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ‰ใƒƒใƒˆ๏ผˆ`.`๏ผ‰ใงๅง‹ใพใ‚‹ใƒ•ใ‚กใ‚คใƒซใฏใ€Linux ใ‚„ macOS ใฎใ‚ˆใ†ใช Unix ็ณปใ‚ทใ‚นใƒ†ใƒ ใงใฏ้š ใ—ใƒ•ใ‚กใ‚คใƒซใงใ™ใ€‚ + +ใŸใ ใ—ใ€dotenv ใƒ•ใ‚กใ‚คใƒซใฏๅฟ…ใšใ—ใ‚‚ใใฎๆญฃ็ขบใชใƒ•ใ‚กใ‚คใƒซๅใงใ‚ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +/// + +Pydantic ใฏๅค–้ƒจใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟใฃใฆใ“ใฎ็จฎใฎใƒ•ใ‚กใ‚คใƒซใ‹ใ‚‰ใฎ่ชญใฟ่พผใฟใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚่ฉณ็ดฐใฏ Pydantic Settings: Dotenv (.env) support ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚Œใ‚’ๆฉŸ่ƒฝใ•ใ›ใ‚‹ใซใฏใ€`pip install python-dotenv` ใŒๅฟ…่ฆใงใ™ใ€‚ + +/// + +### `.env` ใƒ•ใ‚กใ‚คใƒซ { #the-env-file } + +ๆฌกใฎใ‚ˆใ†ใช `.env` ใƒ•ใ‚กใ‚คใƒซใ‚’็”จๆ„ใงใใพใ™: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### `.env` ใ‹ใ‚‰่จญๅฎšใ‚’่ชญใ‚€ { #read-settings-from-env } + +ใใ—ใฆใ€`config.py` ใ‚’ๆฌกใฎใ‚ˆใ†ใซๆ›ดๆ–ฐใ—ใพใ™: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`model_config` ๅฑžๆ€งใฏ Pydantic ใฎ่จญๅฎšๅฐ‚็”จใงใ™ใ€‚่ฉณใ—ใใฏ Pydantic: Concepts: Configuration ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +ใ“ใ“ใงใฏใ€Pydantic ใฎ `Settings` ใ‚ฏใƒฉใ‚นๅ†…ใง่จญๅฎš `env_file` ใ‚’ๅฎš็พฉใ—ใ€ไฝฟ็”จใ—ใŸใ„ dotenv ใƒ•ใ‚กใ‚คใƒซใฎใƒ•ใ‚กใ‚คใƒซๅใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใพใ™ใ€‚ + +### `lru_cache` ใง `Settings` ใ‚’ไธ€ๅบฆใ ใ‘ไฝœๆˆ { #creating-the-settings-only-once-with-lru-cache } + +ใƒ‡ใ‚ฃใ‚นใ‚ฏใ‹ใ‚‰ใƒ•ใ‚กใ‚คใƒซใ‚’่ชญใ‚€ใฎใฏ้€šๅธธใ‚ณใ‚นใƒˆ๏ผˆ้…ๅปถ๏ผ‰ใŒ้ซ˜ใ„ๅ‡ฆ็†ใชใฎใงใ€1ๅ›žใ ใ‘ๅฎŸ่กŒใ—ใฆๅŒใ˜่จญๅฎšใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ†ๅˆฉ็”จใ—ใ€ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ่ชญใฟ็›ดใ•ใชใ„ใฎใŒๆœ›ใพใ—ใ„ใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ๆฌกใฎใ‚ˆใ†ใซใ™ใ‚‹ใŸใณใซ: + +```Python +Settings() +``` + +ๆ–ฐใ—ใ„ `Settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใŒไฝœๆˆใ•ใ‚Œใ€ใใฎไฝœๆˆๆ™‚ใซ `.env` ใƒ•ใ‚กใ‚คใƒซใŒๅ†ๅบฆ่ชญใฟ่พผใพใ‚Œใพใ™ใ€‚ + +ไพๅญ˜้–ขๆ•ฐใŒๆฌกใฎใ‚ˆใ†ใงใ‚ใ‚Œใฐ: + +```Python +def get_settings(): + return Settings() +``` + +ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซใใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ `.env` ใƒ•ใ‚กใ‚คใƒซใ‚’่ชญใฟ่พผใ‚€ใ“ใจใซใชใ‚Šใพใ™ใ€‚โš ๏ธ + +ใ—ใ‹ใ—ใ€ไธŠใซ `@lru_cache` ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ‚’ไฝฟใฃใฆใ„ใ‚‹ใฎใงใ€`Settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏๆœ€ๅˆใซๅ‘ผใณๅ‡บใ•ใ‚ŒใŸใจใใซไธ€ๅบฆใ ใ‘ไฝœๆˆใ•ใ‚Œใพใ™ใ€‚โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +ใใฎๅพŒใฎใƒชใ‚ฏใ‚จใ‚นใƒˆ็”จใฎไพๅญ˜้–ขไฟ‚ใง `get_settings()` ใŒๅ‘ผใฐใ‚Œใ‚‹ใŸใณใซใ€`get_settings()` ใฎๅ†…้ƒจใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ—ใฆๆ–ฐใ—ใ„ `Settings` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœใ‚‹ใฎใงใฏใชใใ€ๆœ€ๅˆใฎๅ‘ผใณๅ‡บใ—ใง่ฟ”ใ•ใ‚ŒใŸใฎใจๅŒใ˜ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝ•ๅบฆใงใ‚‚่ฟ”ใ—ใพใ™ใ€‚ + +#### `lru_cache` ใฎๆŠ€่ก“่ฉณ็ดฐ { #lru-cache-technical-details } + +`@lru_cache` ใฏใ€ๆฏŽๅ›ž้–ขๆ•ฐใฎใ‚ณใƒผใƒ‰ใ‚’ๅฎŸ่กŒใ—ใฆๅ†่จˆ็ฎ—ใ™ใ‚‹ใฎใงใฏใชใใ€ๆœ€ๅˆใซ่ฟ”ใ—ใŸๅ€คใ‚’่ฟ”ใ™ใ‚ˆใ†ใซใ€ไฟฎ้ฃพใ™ใ‚‹้–ขๆ•ฐใ‚’ๅค‰ๆ›ดใ—ใพใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใ€ใใฎไธ‹ใฎ้–ขๆ•ฐใฏๅผ•ๆ•ฐใฎ็ต„ใฟๅˆใ‚ใ›ใ”ใจใซไธ€ๅบฆใ ใ‘ๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ใใ—ใฆใ€ใใฎๅ„ๅผ•ๆ•ฐใฎ็ต„ใฟๅˆใ‚ใ›ใง่ฟ”ใ•ใ‚ŒใŸๅ€คใฏใ€ใพใฃใŸใๅŒใ˜ๅผ•ๆ•ฐใฎ็ต„ใฟๅˆใ‚ใ›ใงๅ‘ผใณๅ‡บใ•ใ‚ŒใŸใจใใซไฝ•ๅบฆใงใ‚‚ๅ†ๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ + +ใŸใจใˆใฐใ€ๆฌกใฎใ‚ˆใ†ใช้–ขๆ•ฐใŒใ‚ใ‚‹ใจใ—ใพใ™: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +ใƒ—ใƒญใ‚ฐใƒฉใƒ ใฏๆฌกใฎใ‚ˆใ†ใซๅฎŸ่กŒใ•ใ‚Œใพใ™: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +ไปŠๅ›žใฎไพๅญ˜้–ขๆ•ฐ `get_settings()` ใฎๅ ดๅˆใ€้–ขๆ•ฐใฏๅผ•ๆ•ฐใ‚’ไธ€ๅˆ‡ๅ–ใ‚Šใพใ›ใ‚“ใ€‚ใใฎใŸใ‚ใ€ๅธธใซๅŒใ˜ๅ€คใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใ“ใฎๆ–นๆณ•ใฏใ€ใปใจใ‚“ใฉใ‚ฐใƒญใƒผใƒใƒซๅค‰ๆ•ฐใฎใ‚ˆใ†ใซๆŒฏใ‚‹่ˆžใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ไพๅญ˜้–ขๆ•ฐใ‚’ไฝฟใฃใฆใ„ใ‚‹ใฎใงใ€ใƒ†ใ‚นใƒˆใฎใŸใ‚ใซ็ฐกๅ˜ใซใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ + +`@lru_cache` ใฏ Python ๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎ `functools` ใฎไธ€้ƒจใงใ™ใ€‚่ฉณ็ดฐใฏ Python ใฎ `@lru_cache` ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใพใจใ‚ { #recap } + +Pydantic Settings ใ‚’ไฝฟใ†ใ“ใจใงใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่จญๅฎšใ‚„ๆง‹ๆˆใ‚’ใ€Pydantic ใƒขใƒ‡ใƒซใฎๅŠ›ใ‚’ๆดปใ‹ใ—ใฆๆ‰ฑใˆใพใ™ใ€‚ + +* ไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ†ใ“ใจใงใ€ใƒ†ใ‚นใƒˆใ‚’็ฐก็ด ๅŒ–ใงใใพใ™ใ€‚ +* `.env` ใƒ•ใ‚กใ‚คใƒซใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ +* `@lru_cache` ใ‚’ไฝฟใ†ใจใ€ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ dotenv ใƒ•ใ‚กใ‚คใƒซใ‚’็นฐใ‚Š่ฟ”ใ—่ชญใฟ่พผใ‚€ใฎใ‚’้ฟใ‘ใคใคใ€ใƒ†ใ‚นใƒˆๆ™‚ใซใฏใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/sub-applications.md b/docs/ja/docs/advanced/sub-applications.md new file mode 100644 index 0000000000..f38da1423e --- /dev/null +++ b/docs/ja/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒžใ‚ฆใƒณใƒˆ { #sub-applications-mounts } + +ใใ‚Œใžใ‚Œ็‹ฌ็ซ‹ใ—ใŸ OpenAPI ใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใ‚’ๆŒใค2ใคใฎ็‹ฌ็ซ‹ใ—ใŸ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅฟ…่ฆใชๅ ดๅˆใ€ใƒกใ‚คใƒณใ‚ขใƒ—ใƒชใซ1ใค๏ผˆไปฅไธŠ๏ผ‰ใฎใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใงใใพใ™ใ€‚ + +## FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒžใ‚ฆใƒณใƒˆ { #mounting-a-fastapi-application } + +ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใจใฏใ€็‰นๅฎšใฎใƒ‘ใ‚นใซๅฎŒๅ…จใซใ€Œ็‹ฌ็ซ‹ใ—ใŸใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ—ใ€ใใฎใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๅฎฃ่จ€ใ•ใ‚ŒใŸ path operation ใซใ‚ˆใฃใฆใ€ใใฎใƒ‘ใ‚นไปฅไธ‹ใฎใ™ในใฆใ‚’ๅ‡ฆ็†ใ•ใ›ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ + +### ใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ { #top-level-application } + +ใพใšใ€ใƒกใ‚คใƒณใฎใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใจใ€ใใฎ path operation ใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ { #sub-application } + +ๆฌกใซใ€ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใจใใฎ path operation ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใ“ใฎใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏ้€šๅธธใฎ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ™ใŒใ€ใ“ใ‚Œใ‚’ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ—ใพใ™: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆ { #mount-the-sub-application } + +ใƒˆใƒƒใƒ—ใƒฌใƒ™ใƒซใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ `app` ใซใ€ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ `subapi` ใ‚’ใƒžใ‚ฆใƒณใƒˆใ—ใพใ™ใ€‚ + +ใ“ใฎไพ‹ใงใฏใ€ใƒ‘ใ‚น `/subapi` ใซใƒžใ‚ฆใƒณใƒˆใ•ใ‚Œใพใ™: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### ่‡ชๅ‹• API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-automatic-api-docs } + +ใงใฏใ€`fastapi` ใ‚ณใƒžใƒณใƒ‰ใงใ“ใฎใƒ•ใ‚กใ‚คใƒซใ‚’ๅฎŸ่กŒใ—ใพใ™: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ใใ—ใฆใ€http://127.0.0.1:8000/docs ใ‚’้–‹ใใพใ™ใ€‚ + +ใƒกใ‚คใƒณใ‚ขใƒ—ใƒช็”จใฎ่‡ชๅ‹• API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใ€ใใฎใ‚ขใƒ—ใƒช่‡ช่บซใฎ path operation ใฎใฟใŒๅซใพใ‚Œใพใ™: + + + +ๆฌกใซใ€ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ http://127.0.0.1:8000/subapi/docs ใ‚’้–‹ใใพใ™ใ€‚ + +ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ็”จใฎ่‡ชๅ‹• API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใ€ใใฎใ‚ขใƒ—ใƒช่‡ช่บซใฎ path operation ใฎใฟใŒใ€ๆญฃใ—ใ„ใ‚ตใƒ–ใƒ‘ใ‚นๆŽฅ้ ญ่พž `/subapi` ใฎไธ‹ใง่กจ็คบใ•ใ‚Œใพใ™: + + + +ใฉใกใ‚‰ใฎ UI ใงใ‚‚ๆ“ไฝœใ™ใ‚Œใฐๆญฃใ—ใๅ‹•ไฝœใ—ใพใ™ใ€‚ใƒ–ใƒฉใ‚ฆใ‚ถใŒใใ‚Œใžใ‚Œใฎใ‚ขใƒ—ใƒช๏ผใ‚ตใƒ–ใ‚ขใƒ—ใƒชใจ้€šไฟกใงใใ‚‹ใŸใ‚ใงใ™ใ€‚ + +### ๆŠ€่ก“่ฉณ็ดฐ: `root_path` { #technical-details-root-path } + +ไธŠ่จ˜ใฎใ‚ˆใ†ใซใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆใ™ใ‚‹ใจใ€FastAPI ใฏ ASGI ไป•ๆง˜ใฎ `root_path` ใจๅ‘ผใฐใ‚Œใ‚‹ไป•็ต„ใฟใ‚’ไฝฟใฃใฆใ€ใใฎใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธใฎใƒžใ‚ฆใƒณใƒˆใƒ‘ใ‚นใ‚’ไผๆ’ญใ—ใพใ™ใ€‚ + +ใ“ใฎใŸใ‚ใ€ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใงใใฎใƒ‘ใ‚นๆŽฅ้ ญ่พžใ‚’ไฝฟ็”จใ™ในใใ“ใจใ‚’่ช่ญ˜ใงใใพใ™ใ€‚ + +ใ•ใ‚‰ใซใ€ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ่‡ช่บซใŒๅˆฅใฎใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆใ—ใฆใ„ใฆใ‚‚ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚FastAPI ใŒใ“ใ‚Œใ‚‰ใฎ `root_path` ใ‚’ใ™ในใฆ่‡ชๅ‹•็š„ใซๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +`root_path` ใฎ่ฉณ็ดฐใ‚„ๆ˜Ž็คบ็š„ใชๆŒ‡ๅฎšๆ–นๆณ•ใซใคใ„ใฆใฏใ€[ใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒใง](behind-a-proxy.md){.internal-link target=_blank} ใฎ็ฏ€ใงๅญฆในใพใ™ใ€‚ diff --git a/docs/ja/docs/advanced/templates.md b/docs/ja/docs/advanced/templates.md new file mode 100644 index 0000000000..3c4827b88e --- /dev/null +++ b/docs/ja/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ { #templates } + +**FastAPI** ใงใฏไปปๆ„ใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚จใƒณใ‚ธใƒณใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +Flask ใชใฉใงใ‚‚ไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ Jinja2 ใŒไธ€่ˆฌ็š„ใช้ธๆŠž่‚ขใงใ™ใ€‚ + +Starlette ใซใ‚ˆใฃใฆๆไพ›ใ•ใ‚Œใ€**FastAPI** ใ‚ขใƒ—ใƒชใง็›ดๆŽฅไฝฟใˆใ‚‹ใ€็ฐกๅ˜ใซ่จญๅฎšใงใใ‚‹ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใŒใ‚ใ‚Šใพใ™ใ€‚ + +## ไพๅญ˜้–ขไฟ‚ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-dependencies } + +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€`jinja2` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## `Jinja2Templates` ใฎไฝฟ็”จ { #using-jinja2templates } + +* `Jinja2Templates` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ +* ๅพŒใงๅ†ๅˆฉ็”จใงใใ‚‹ `templates` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ +* ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚’่ฟ”ใ™ path operation ใซ `Request` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +* ไฝœๆˆใ—ใŸ `templates` ใ‚’ไฝฟใฃใฆ `TemplateResponse` ใ‚’ใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใ—ใฆ่ฟ”ใ—ใพใ™ใ€‚ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆๅใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€Jinja2 ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆๅ†…ใงไฝฟ็”จใ™ใ‚‹ใ‚ญใƒผใจๅ€คใฎใƒšใ‚ขใ‹ใ‚‰ใชใ‚‹ "context" ใฎ่พžๆ›ธใ‚’ๆธกใ—ใพใ™ใ€‚ + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | ๅ‚™่€ƒ + +FastAPI 0.108.0ใ€Starlette 0.29.0 ไปฅๅ‰ใงใฏใ€`name` ใฏๆœ€ๅˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ—ใŸใ€‚ + +ใพใŸใใ‚Œไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใงใฏใ€`request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฏ Jinja2 ็”จใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆๅ†…ใฎใ‚ญใƒผใจๅ€คใฎใƒšใ‚ขใฎไธ€้ƒจใจใ—ใฆๆธกใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ + +/// + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`response_class=HTMLResponse` ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใŒใƒฌใ‚นใƒใƒณใ‚นใŒ HTML ใงใ‚ใ‚‹ใ“ใจใ‚’่ช่ญ˜ใงใใพใ™ใ€‚ + +/// + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +`from starlette.templating import Jinja2Templates` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +**FastAPI** ใฏใ€้–‹็™บ่€…ใงใ‚ใ‚‹ใ‚ใชใŸใฎๅˆฉไพฟๆ€งใฎใŸใ‚ใซใ€`starlette.templating` ใจๅŒใ˜ใ‚‚ใฎใ‚’ `fastapi.templating` ใจใ—ใฆๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎใปใจใ‚“ใฉใฏ Starlette ใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚`Request` ใ‚„ `StaticFiles` ใ‚‚ๅŒๆง˜ใงใ™ใ€‚ + +/// + +## ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎไฝœๆˆ { #writing-templates } + +ไพ‹ใˆใฐใ€`templates/item.html` ใซๆฌกใฎใ‚ˆใ†ใชใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใ‚’ๆ›ธใใพใ™: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆๅ€ค { #template-context-values } + +ๆฌกใฎใ‚ˆใ†ใช HTML ๅ†…ใง: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...ๆธกใ—ใŸ "context" ใฎ `dict` ใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸ `id` ใŒ่กจ็คบใ•ใ‚Œใพใ™: + +```Python +{"id": id} +``` + +ไพ‹ใˆใฐใ€ID ใŒ `42` ใฎๅ ดๅˆใฏๆฌกใฎใ‚ˆใ†ใซใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใ•ใ‚Œใพใ™: + +```html +Item ID: 42 +``` + +### ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎ `url_for` ใฎๅผ•ๆ•ฐ { #template-url-for-arguments } + +ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆๅ†…ใงใ‚‚ `url_for()` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ๅผ•ๆ•ฐใซใฏใ€ๅฏพๅฟœใ™ใ‚‹ path operation ้–ขๆ•ฐใงไฝฟใ‚ใ‚Œใ‚‹ใฎใจๅŒใ˜ๅผ•ๆ•ฐใ‚’ๅ–ใ‚Šใพใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใ€ๆฌกใฎ้ƒจๅˆ†ใฏ: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...path operation ้–ขๆ•ฐ `read_item(id=id)` ใŒๅ‡ฆ็†ใ™ใ‚‹ใฎใจๅŒใ˜ URL ใธใฎใƒชใƒณใ‚ฏใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ID ใŒ `42` ใฎๅ ดๅˆใฏๆฌกใฎใ‚ˆใ†ใซใƒฌใƒณใƒ€ใƒชใƒณใ‚ฐใ•ใ‚Œใพใ™: + +```html + +``` + +## ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใจ้™็š„ใƒ•ใ‚กใ‚คใƒซ { #templates-and-static-files } + +ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆๅ†…ใง `url_for()` ใ‚’ไฝฟ็”จใ—ใ€ไพ‹ใˆใฐ `name="static"` ใงใƒžใ‚ฆใƒณใƒˆใ—ใŸ `StaticFiles` ใซๅฏพใ—ใฆๅˆฉ็”จใงใใพใ™ใ€‚ + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +ใ“ใฎไพ‹ใงใฏใ€`static/styles.css` ใฎ CSS ใƒ•ใ‚กใ‚คใƒซใซใƒชใƒณใ‚ฏใ—ใพใ™: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +ใพใŸใ€`StaticFiles` ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใใฎ CSS ใƒ•ใ‚กใ‚คใƒซใฏ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‹ใ‚‰ URL `/static/styles.css` ใง่‡ชๅ‹•็š„ใซ้…ไฟกใ•ใ‚Œใพใ™ใ€‚ + +## ใ•ใ‚‰ใซ่ฉณใ—ใ { #more-details } + +ใ‚ˆใ‚Š่ฉณใ—ใ„ๅ†…ๅฎน๏ผˆใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎใƒ†ใ‚นใƒˆๆ–นๆณ•ใชใฉ๏ผ‰ใซใคใ„ใฆใฏใ€Starlette ใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/advanced/testing-dependencies.md b/docs/ja/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000..78478a7751 --- /dev/null +++ b/docs/ja/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# ไพๅญ˜้–ขไฟ‚ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใซใ‚ˆใ‚‹ใƒ†ใ‚นใƒˆ { #testing-dependencies-with-overrides } + +## ใƒ†ใ‚นใƒˆๆ™‚ใฎไพๅญ˜้–ขไฟ‚ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ { #overriding-dependencies-during-testing } + +ใƒ†ใ‚นใƒˆไธญใซไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใŸใ„ๅ ด้ขใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ + +ๅ…ƒใฎไพๅญ˜้–ขไฟ‚๏ผˆใŠใ‚ˆใณใใ‚Œใซใถใ‚‰ไธ‹ใŒใ‚‹ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚๏ผ‰ใ‚’ๅฎŸ่กŒใ—ใŸใใชใ„ๅ ดๅˆใงใ™ใ€‚ + +ไปฃใ‚ใ‚Šใซใ€ใƒ†ใ‚นใƒˆใฎ้–“ใ ใ‘๏ผˆ็‰นๅฎšใฎใƒ†ใ‚นใƒˆใ ใ‘ใงใ‚‚๏ผ‰ไฝฟใ‚ใ‚Œใ‚‹ๅˆฅใฎไพๅญ˜้–ขไฟ‚ใ‚’ๆไพ›ใ—ใ€ๅ…ƒใฎไพๅญ˜้–ขไฟ‚ใฎๅ€คใŒไฝฟใ‚ใ‚Œใฆใ„ใŸ็ฎ‡ๆ‰€ใงๅˆฉ็”จใงใใ‚‹ๅ€คใ‚’่ฟ”ใ—ใŸใ„ใฎใงใ™ใ€‚ + +### ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น: ๅค–้ƒจใ‚ตใƒผใƒ“ใ‚น { #use-cases-external-service } + +ไพ‹ใจใ—ใฆใ€ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚‹ๅค–้ƒจใฎ่ช่จผใƒ—ใƒญใƒใ‚คใƒ€ใŒใ‚ใ‚‹ใจใ—ใพใ™ใ€‚ + +ใƒˆใƒผใ‚ฏใƒณใ‚’้€ใ‚‹ใจใ€่ช่จผๆธˆใฟใƒฆใƒผใ‚ถใƒผใŒ่ฟ”ใฃใฆใใพใ™ใ€‚ + +ใ“ใฎใƒ—ใƒญใƒใ‚คใƒ€ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซ่ชฒ้‡‘ใ•ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใšใ€ใƒ†ใ‚นใƒˆ็”จใซๅ›บๅฎšใฎใƒขใƒƒใ‚ฏใƒฆใƒผใ‚ถใƒผใ‚’ไฝฟใ†ๅ ดๅˆใซๆฏ”ในใฆๅ‘ผใณๅ‡บใ—ใซไฝ™ๅˆ†ใชๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ๅค–้ƒจใƒ—ใƒญใƒใ‚คใƒ€่‡ชไฝ“ใฎๅ‹•ไฝœใฏไธ€ๅบฆใฏใƒ†ใ‚นใƒˆใ—ใŸใ„ใงใ—ใ‚‡ใ†ใŒใ€ๅฎŸ่กŒใ•ใ‚Œใ‚‹ใ™ในใฆใฎใƒ†ใ‚นใƒˆใงๆฏŽๅ›žๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใฎๅ ดๅˆใ€ใใฎใƒ—ใƒญใƒใ‚คใƒ€ใ‚’ๅ‘ผใณๅ‡บใ™ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใ€ใƒ†ใ‚นใƒˆใฎใจใใ ใ‘ใƒขใƒƒใ‚ฏใƒฆใƒผใ‚ถใƒผใ‚’่ฟ”ใ™ใ‚ซใ‚นใ‚ฟใƒ ใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใˆใพใ™ใ€‚ + +### app.dependency_overrides ๅฑžๆ€งใ‚’ไฝฟใ† { #use-the-app-dependency-overrides-attribute } + +ใ“ใฎใ‚ˆใ†ใชๅ ดๅˆใฎใŸใ‚ใซใ€**FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใฏ `app.dependency_overrides` ใจใ„ใ†ๅฑžๆ€งใŒใ‚ใ‚Šใ€ใ“ใ‚Œใฏๅ˜็ด”ใช `dict` ใงใ™ใ€‚ + +ใƒ†ใ‚นใƒˆ็”จใซไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใซใฏใ€ใ‚ญใƒผใซๅ…ƒใฎไพๅญ˜้–ขไฟ‚๏ผˆ้–ขๆ•ฐ๏ผ‰ใ‚’ใ€ๅ€คใซใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ไพๅญ˜้–ขไฟ‚๏ผˆๅˆฅใฎ้–ขๆ•ฐ๏ผ‰ใ‚’่จญๅฎšใ—ใพใ™ใ€‚ + +ใ™ใ‚‹ใจ **FastAPI** ใฏๅ…ƒใฎไพๅญ˜้–ขไฟ‚ใฎไปฃใ‚ใ‚Šใซใใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ†…ใฎใฉใ“ใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ไพๅญ˜้–ขไฟ‚ใซๅฏพใ—ใฆใ‚‚ใ€ไพๅญ˜้–ขไฟ‚ใฎใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ‚’่จญๅฎšใงใใพใ™ใ€‚ + +ๅ…ƒใฎไพๅญ˜้–ขไฟ‚ใฏใ€*path operation ้–ขๆ•ฐ*ใ€*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*๏ผˆๆˆปใ‚Šๅ€คใ‚’ไฝฟใ‚ใชใ„ๅ ดๅˆ๏ผ‰ใ€`.include_router()` ใฎๅ‘ผใณๅ‡บใ—ใชใฉใ€ใ•ใพใ–ใพใชๅ ดๆ‰€ใงไฝฟใ‚ใ‚Œใฆใ„ใฆใ‚‚ใ‹ใพใ„ใพใ›ใ‚“ใ€‚ + +FastAPI ใฏใใ‚Œใงใ‚‚ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใงใใพใ™ใ€‚ + +/// + +ใใฎๅพŒใ€`app.dependency_overrides` ใ‚’็ฉบใฎ `dict` ใซ่จญๅฎšใ™ใ‚‹ใ“ใจใงใ€ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ‚’ใƒชใ‚ปใƒƒใƒˆ๏ผˆๅ‰Š้™ค๏ผ‰ใงใใพใ™: + +```Python +app.dependency_overrides = {} +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไธ€้ƒจใฎใƒ†ใ‚นใƒˆใฎ้–“ใ ใ‘ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใŸใ„ๅ ดๅˆใฏใ€ใƒ†ใ‚นใƒˆใฎ้–‹ๅง‹ๆ™‚๏ผˆใƒ†ใ‚นใƒˆ้–ขๆ•ฐๅ†…๏ผ‰ใซใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ‚’่จญๅฎšใ—ใ€็ต‚ไบ†ๆ™‚๏ผˆใƒ†ใ‚นใƒˆ้–ขๆ•ฐใฎๆœซๅฐพ๏ผ‰ใซใƒชใ‚ปใƒƒใƒˆใ™ใ‚‹ใจใ‚ˆใ„ใงใ™ใ€‚ + +/// diff --git a/docs/ja/docs/advanced/testing-events.md b/docs/ja/docs/advanced/testing-events.md new file mode 100644 index 0000000000..98e97fed81 --- /dev/null +++ b/docs/ja/docs/advanced/testing-events.md @@ -0,0 +1,11 @@ +# ใ‚คใƒ™ใƒณใƒˆใฎใƒ†ใ‚นใƒˆ: lifespan ใจ startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +ใƒ†ใ‚นใƒˆใง `lifespan` ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€`with` ๆ–‡ใจไฝต็”จใ—ใฆ `TestClient` ใ‚’ไฝฟ็”จใงใใพใ™: + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + +ใ‚ˆใ‚Š่ฉณใ—ใ„ๅ†…ๅฎนใฏใ€[ๅ…ฌๅผ Starlette ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ€Œใƒ†ใ‚นใƒˆใงใฎ lifespan ใฎๅฎŸ่กŒใ€](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +้žๆŽจๅฅจใฎ `startup` ใŠใ‚ˆใณ `shutdown` ใ‚คใƒ™ใƒณใƒˆใซใคใ„ใฆใฏใ€ๆฌกใฎใ‚ˆใ†ใซ `TestClient` ใ‚’ไฝฟ็”จใงใใพใ™: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/ja/docs/advanced/testing-websockets.md b/docs/ja/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000..7f708ea1a2 --- /dev/null +++ b/docs/ja/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# WebSocket ใฎใƒ†ใ‚นใƒˆ { #testing-websockets } + +WebSocket ใ‚’ใƒ†ใ‚นใƒˆใ™ใ‚‹ใฎใซใ‚‚ๅŒใ˜ `TestClient` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใ€`with` ๆ–‡ใฎไธญใง `TestClient` ใ‚’ไฝฟ็”จใ—ใ€WebSocket ใซๆŽฅ็ถšใ—ใพใ™: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | ๅ‚™่€ƒ + +่ฉณ็ดฐใซใคใ„ใฆใฏใ€Starlette ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ€ŒWebSocket ใฎใƒ†ใ‚นใƒˆใ€ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// diff --git a/docs/ja/docs/advanced/using-request-directly.md b/docs/ja/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000..1e564f5945 --- /dev/null +++ b/docs/ja/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Request ใ‚’็›ดๆŽฅไฝฟใ† { #using-the-request-directly } + +ใ“ใ‚Œใพใงใ€ๅฟ…่ฆใชใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ„้ƒจๅˆ†ใ‚’ใ€ใใฎๅž‹ใจใจใ‚‚ใซๅฎฃ่จ€ใ—ใฆใใพใ—ใŸใ€‚ + +ๆฌกใฎๅ ดๆ‰€ใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใ—ใพใ™: + +- ใƒ‘ใ‚นใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ +- ใƒ˜ใƒƒใƒ€ใƒผ +- ใ‚ฏใƒƒใ‚ญใƒผ +- ใชใฉ + +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€**FastAPI** ใฏใใฎใƒ‡ใƒผใ‚ฟใ‚’ๆคœ่จผใ—ใ€ๅค‰ๆ›ใ—ใ€API ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่‡ชๅ‹•็”Ÿๆˆใ—ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€`Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซ็›ดๆŽฅใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ด้ขใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +## `Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎ่ฉณ็ดฐ { #details-about-the-request-object } + +**FastAPI** ใฏๅ†…้ƒจ็š„ใซใฏ **Starlette** ใฎไธŠใซใ„ใใคใ‹ใฎใƒ„ใƒผใƒซๅฑคใ‚’่ผ‰ใ›ใŸใ‚‚ใฎใชใฎใงใ€ๅฟ…่ฆใซๅฟœใ˜ใฆ Starlette ใฎ `Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็›ดๆŽฅไฝฟใˆใพใ™ใ€‚ + +ใพใŸใ€`Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‹ใ‚‰็›ดๆŽฅใƒ‡ใƒผใ‚ฟ๏ผˆไพ‹: ใƒœใƒ‡ใ‚ฃ๏ผ‰ใ‚’ๅ–ๅพ—ใ™ใ‚‹ๅ ดๅˆใ€ใใฎใƒ‡ใƒผใ‚ฟใฏ FastAPI ใซใ‚ˆใฃใฆๆคœ่จผใƒปๅค‰ๆ›ใƒปใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–๏ผˆOpenAPI ใซใ‚ˆใ‚‹่‡ชๅ‹• API ใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นๅ‘ใ‘๏ผ‰ใ•ใ‚Œใพใ›ใ‚“ใ€‚ + +ใŸใ ใ—ใ€้€šๅธธใฉใŠใ‚Šใซๅฎฃ่จ€ใ•ใ‚ŒใŸไป–ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ๏ผˆไพ‹: Pydantic ใƒขใƒ‡ใƒซใฎใƒœใƒ‡ใ‚ฃ๏ผ‰ใฏๅผ•ใ็ถšใๆคœ่จผใƒปๅค‰ๆ›ใƒปๆณจ้‡ˆไป˜ใ‘ใชใฉใŒ่กŒใ‚ใ‚Œใพใ™ใ€‚ + +ใใ‚Œใงใ‚‚ใ€`Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ–ๅพ—ใ™ใ‚‹ใฎใŒๆœ‰็”จใช็‰นๅฎšใฎใ‚ฑใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ + +## `Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’็›ดๆŽฅไฝฟใ† { #use-the-request-object-directly } + +ใŸใจใˆใฐใ€path operation ้–ขๆ•ฐๅ†…ใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎ IP ใ‚ขใƒ‰ใƒฌใ‚น๏ผใƒ›ใ‚นใƒˆใ‚’ๅ–ๅพ—ใ—ใŸใ„ใจใ—ใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใฏใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใซ็›ดๆŽฅใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +path operation ้–ขๆ•ฐใฎๅผ•ๆ•ฐใจใ—ใฆ `Request` ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€**FastAPI** ใฏใใฎๅผ•ๆ•ฐใซ `Request` ใ‚’ๆธกใ—ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎไพ‹ใงใฏใ€`Request` ๅž‹ใฎๅผ•ๆ•ฐใซๅŠ ใˆใฆใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚ๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏๅ–ใ‚Šๅ‡บใ•ใ‚Œใ€ๆคœ่จผใ•ใ‚Œใ€ๆŒ‡ๅฎšใ—ใŸๅž‹ใซๅค‰ๆ›ใ•ใ‚Œใ€OpenAPI ใงๆณจ้‡ˆ๏ผˆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–๏ผ‰ใ•ใ‚Œใพใ™ใ€‚ + +ๅŒๆง˜ใซใ€้€šๅธธใฉใŠใ‚Šไปปๆ„ใฎไป–ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ—ใคใคใ€่ฟฝๅŠ ใง `Request` ใ‚‚ๅ—ใ‘ๅ–ใ‚Œใพใ™ใ€‚ + +/// + +## `Request` ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #request-documentation } + +ใ‚ˆใ‚Š่ฉณใ—ใใฏใ€ๅ…ฌๅผ Starlette ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ตใ‚คใƒˆใฎ `Request` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +`from starlette.requests import Request` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +**FastAPI** ใฏ้–‹็™บ่€…ใงใ‚ใ‚‹็š†ใ•ใ‚“ใฎไพฟๅฎœใฎใŸใ‚ใซ็›ดๆŽฅๆไพ›ใ—ใฆใ„ใพใ™ใŒใ€ใ“ใ‚Œใฏ Starlette ใ‹ใ‚‰ใใฎใพใพๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ใ‚‚ใฎใงใ™ใ€‚ + +/// diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md index 6c68c9f0b1..cb5e376de6 100644 --- a/docs/ja/docs/advanced/websockets.md +++ b/docs/ja/docs/advanced/websockets.md @@ -38,13 +38,13 @@ $ pip install websockets ใ—ใ‹ใ—ใ€ใ“ใ‚ŒใฏWebSocketsใฎใ‚ตใƒผใƒใƒผใ‚ตใ‚คใƒ‰ใซ็„ฆ็‚นใ‚’ๅฝ“ใฆใ€ๅ‹•ไฝœใ™ใ‚‹ไพ‹ใ‚’็คบใ™ๆœ€ใ‚‚็ฐกๅ˜ใชๆ–นๆณ•ใงใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## `websocket` ใ‚’ไฝœๆˆใ™ใ‚‹ { #create-a-websocket } **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใ€`websocket` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ @@ -58,7 +58,7 @@ $ pip install websockets WebSocketใƒซใƒผใƒˆใงใฏใ€ใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ๅพ…ๆฉŸใ—ใฆ้€ไฟกใ™ใ‚‹ใŸใ‚ใซ `await` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} ใƒใ‚คใƒŠใƒชใ‚„ใƒ†ใ‚ญใ‚นใƒˆใƒ‡ใƒผใ‚ฟใ€JSONใƒ‡ใƒผใ‚ฟใ‚’้€ๅ—ไฟกใงใใพใ™ใ€‚ @@ -154,7 +154,7 @@ $ fastapi dev main.py WebSocketๆŽฅ็ถšใŒ้–‰ใ˜ใ‚‰ใ‚Œใ‚‹ใจใ€ `await websocket.receive_text()` ใฏไพ‹ๅค– `WebSocketDisconnect` ใ‚’็™บ็”Ÿใ•ใ›ใ€ใ“ใฎไพ‹ใฎใ‚ˆใ†ใซใ‚ญใƒฃใƒƒใƒใ—ใฆๅ‡ฆ็†ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} ่ฉฆใ—ใฆใฟใ‚‹ใซใฏใ€ diff --git a/docs/ja/docs/advanced/wsgi.md b/docs/ja/docs/advanced/wsgi.md new file mode 100644 index 0000000000..b06b4a3299 --- /dev/null +++ b/docs/ja/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# WSGI ใฎ็ต„ใฟ่พผใฟ - Flaskใ€Django ใชใฉ { #including-wsgi-flask-django-others } + +[ใ‚ตใƒ–ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒžใ‚ฆใƒณใƒˆ](sub-applications.md){.internal-link target=_blank}ใ€[ใƒ—ใƒญใ‚ญใ‚ทใฎ่ƒŒๅพŒ](behind-a-proxy.md){.internal-link target=_blank} ใง่ฆ‹ใŸใ‚ˆใ†ใซใ€WSGI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใƒžใ‚ฆใƒณใƒˆใงใใพใ™ใ€‚ + +ใใฎใŸใ‚ใซ `WSGIMiddleware` ใ‚’ไฝฟ็”จใ—ใฆใ€Flask ใ‚„ Django ใชใฉใฎ WSGI ใ‚ขใƒ—ใƒชใ‚’ใƒฉใƒƒใƒ—ใงใใพใ™ใ€‚ + +## `WSGIMiddleware` ใฎไฝฟ็”จ { #using-wsgimiddleware } + +/// info | ๆƒ…ๅ ฑ + +ใ“ใ‚Œใซใฏ `a2wsgi` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซใŒๅฟ…่ฆใงใ™ใ€‚ไพ‹: `pip install a2wsgi`ใ€‚ + +/// + +`a2wsgi` ใ‹ใ‚‰ `WSGIMiddleware` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ + +ๆฌกใซใ€ใใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใง WSGI๏ผˆไพ‹: Flask๏ผ‰ใ‚ขใƒ—ใƒชใ‚’ใƒฉใƒƒใƒ—ใ—ใพใ™ใ€‚ + +ใใ—ใฆใ€ใใ‚Œใ‚’ใ‚ใ‚‹ใƒ‘ใ‚นใฎไธ‹ใซใƒžใ‚ฆใƒณใƒˆใ—ใพใ™ใ€‚ + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | ๅ‚™่€ƒ + +ไปฅๅ‰ใฏ `fastapi.middleware.wsgi` ใฎ `WSGIMiddleware` ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใŒๆŽจๅฅจใ•ใ‚Œใฆใ„ใพใ—ใŸใŒใ€็พๅœจใฏ้žๆŽจๅฅจใงใ™ใ€‚ + +ไปฃใ‚ใ‚Šใซ `a2wsgi` ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚ไฝฟใ„ๆ–นใฏๅŒใ˜ใงใ™ใ€‚ + +`a2wsgi` ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใ€`a2wsgi` ใ‹ใ‚‰ `WSGIMiddleware` ใ‚’ๆญฃใ—ใใ‚คใƒณใƒใƒผใƒˆใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ใƒใ‚งใƒƒใ‚ฏ { #check-it } + +ใ“ใ‚Œใงใ€ใƒ‘ใ‚น `/v1/` ้…ไธ‹ใธใฎใ™ในใฆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฏ Flask ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒๅ‡ฆ็†ใ—ใพใ™ใ€‚ + +ใใ‚Œไปฅๅค–ใฏ **FastAPI** ใŒๅ‡ฆ็†ใ—ใพใ™ใ€‚ + +ๅฎŸ่กŒใ—ใฆ http://localhost:8000/v1/ ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€Flask ใ‹ใ‚‰ใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: + +```txt +Hello, World from Flask! +``` + +ใ•ใ‚‰ใซ http://localhost:8000/v2 ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€FastAPI ใ‹ใ‚‰ใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index 9f5152c08a..8b1ec072d6 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -1,8 +1,8 @@ -# ไปฃๆ›ฟใƒ„ใƒผใƒซใ‹ใ‚‰ๅ—ใ‘ใŸใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใจๆฏ”่ผƒ +# ไปฃๆ›ฟใƒ„ใƒผใƒซใ‹ใ‚‰ๅ—ใ‘ใŸใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใจๆฏ”่ผƒ { #alternatives-inspiration-and-comparisons } ไฝ•ใŒ**FastAPI**ใซใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใ‚’ไธŽใˆใŸใฎใ‹ใ€ไป–ใฎไปฃๆ›ฟใƒ„ใƒผใƒซใจๆฏ”่ผƒใ—ใฆใฉใ†ใ‹ใ€ใใ—ใฆใใ“ใ‹ใ‚‰ไฝ•ใ‚’ๅญฆใ‚“ใ ใฎใ‹ใซใคใ„ใฆใ€‚ -## ใฏใ˜ใ‚ใซ +## ใฏใ˜ใ‚ใซ { #intro } **FastAPI**ใฏใ€ไปฃๆ›ฟใƒ„ใƒผใƒซใฎใ“ใ‚ŒใพใงใฎๅƒใใŒใชใ‘ใ‚Œใฐๅญ˜ๅœจใ—ใชใ‹ใฃใŸใงใ—ใ‚‡ใ†ใ€‚ @@ -12,17 +12,17 @@ ใ—ใ‹ใ—ใ€ใใฎๆ™‚็‚นใงใฏใ€ใ“ใ‚Œใ‚‰ใฎๆฉŸ่ƒฝใ‚’ใ™ในใฆๆไพ›ใ—ใ€ไปฅๅ‰ใฎใƒ„ใƒผใƒซใ‹ใ‚‰ๅ„ชใ‚ŒใŸใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ๅ–ใ‚Šๅ…ฅใ‚Œใ€ๅฏ่ƒฝใช้™ใ‚Šๆœ€้ซ˜ใฎๆ–นๆณ•ใงใใ‚Œใ‚‰ใ‚’็ต„ใฟๅˆใ‚ใ›ใ€ใใ‚Œใพใงๅˆฉ็”จใงใใชใ‹ใฃใŸ่จ€่ชžๆฉŸ่ƒฝ (Python 3.6ไปฅ้™ใฎๅž‹ใƒ’ใƒณใƒˆ) ใ‚’ๅˆฉ็”จใ—ใŸใ‚‚ใฎใ‚’ไฝœใ‚‹ไปฅๅค–ใซ้ธๆŠž่‚ขใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ -## ไปฅๅ‰ใฎใƒ„ใƒผใƒซ +## ไปฅๅ‰ใฎใƒ„ใƒผใƒซ { #previous-tools } -### Django +### Django { #django } Pythonใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธญใงๆœ€ใ‚‚ใƒใƒ”ใƒฅใƒฉใƒผใงใ€ๅบƒใไฟก้ ผใ•ใ‚Œใฆใ„ใพใ™ใ€‚Instagramใฎใ‚ˆใ†ใชใ‚ทใ‚นใƒ†ใƒ ใฎๆง‹็ฏ‰ใซไฝฟใ‚ใ‚Œใฆใ„ใพใ™ใ€‚ ใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น (MySQLใ‚„PostgreSQLใชใฉ) ใจๆฏ”่ผƒ็š„ๅผทๅ›บใซ็ตๅˆใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น (Couchbaseใ€MongoDBใ€Cassandraใชใฉ) ใ‚’ใƒกใ‚คใƒณใซๅˆฉ็”จใ™ใ‚‹ใ“ใจใฏ็ฐกๅ˜ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใงHTMLใ‚’็”Ÿๆˆใ™ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใ‚ใ‚Šใ€็พไปฃ็š„ใชใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ (Reactใ‚„Vue.jsใ€Angularใชใฉ) ใ‚„ใ€ไป–ใฎใ‚ทใ‚นใƒ†ใƒ  (IoTใƒ‡ใƒใ‚คใ‚นใชใฉ) ใจ้€šไฟกใ™ใ‚‹APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใงHTMLใ‚’็”Ÿๆˆใ™ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใ‚ใ‚Šใ€็พไปฃ็š„ใชใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ (Reactใ‚„Vue.jsใ€Angularใชใฉ) ใ‚„ใ€ไป–ใฎใ‚ทใ‚นใƒ†ใƒ  (IoTใƒ‡ใƒใ‚คใ‚นใชใฉ) ใจ้€šไฟกใ™ใ‚‹APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -### Django REST Framework +### Django REST Framework { #django-rest-framework } Django REST Frameworkใฏใ€Djangoใ‚’ไธ‹ๆ•ทใใซใ—ใฆWeb APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๆŸ”่ปŸใชใƒ„ใƒผใƒซใ‚ญใƒƒใƒˆใจใ—ใฆใ€APIใฎๆฉŸ่ƒฝใ‚’ๅ‘ไธŠใ•ใ›ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚Œใพใ—ใŸใ€‚ @@ -42,7 +42,7 @@ Django REST Framework ใฏ Tom Christie ใซใ‚ˆใฃใฆไฝœๆˆใ•ใ‚Œใพใ—ใŸใ€‚Starl /// -### Flask +### Flask { #flask } Flask ใฏใ€Œใƒžใ‚คใ‚ฏใƒญใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ€ใงใ‚ใ‚Šใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใจใฎ็ตฑๅˆใฎใ‚ˆใ†ใชDjangoใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๆŒใคๅคšใใฎๆฉŸ่ƒฝใฏๅซใพใ‚Œใฆใ„ใพใ›ใ‚“ใ€‚ @@ -64,7 +64,7 @@ Flaskใฎใ‚ทใƒณใƒ—ใƒซใ•ใ‚’่€ƒใˆใ‚‹ใจใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใฎใซ้ฉใ—ใฆใ„ใ‚‹ /// -### Requests +### Requests { #requests } **FastAPI**ใฏๅฎŸ้š›ใซใฏ**Requests**ใฎไปฃๆ›ฟใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใ‚Œใ‚‰ใฎใ‚นใ‚ณใƒผใƒ—ใฏๅคงใใ็•ฐใชใ‚Šใพใ™ใ€‚ @@ -80,7 +80,7 @@ Requestsใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใ‹ใค็›ดๆ„Ÿ็š„ใชใƒ‡ใ‚ถใ‚คใƒณใงไฝฟใ„ใ‚„ใ™ใ ๅ…ฌๅผใ‚ตใ‚คใƒˆใงไปฅไธ‹ใฎใ‚ˆใ†ใซ่จ€ใ‚ใ‚Œใฆใ„ใ‚‹ใฎใฏใ€ใใ‚ŒใŒ็†็”ฑใงใ™ใ€‚ -> RequestsใฏไปŠใพใงใงๆœ€ใ‚‚ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ•ใ‚ŒใŸPythonใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใงใ‚ใ‚‹ +> RequestsใฏๅฒไธŠๆœ€ใ‚‚ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ•ใ‚ŒใŸPythonใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใฒใจใคใงใ™ ไฝฟใ„ๆ–นใฏใจใฆใ‚‚็ฐกๅ˜ใงใ™ใ€‚ไพ‹ใˆใฐใ€`GET`ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅฎŸ่กŒใ™ใ‚‹ใซใฏใ€ใ“ใฎใ‚ˆใ†ใซๆ›ธใ‘ใฐ่‰ฏใ„ใงใ™: @@ -88,7 +88,7 @@ Requestsใฏ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใ‹ใค็›ดๆ„Ÿ็š„ใชใƒ‡ใ‚ถใ‚คใƒณใงไฝฟใ„ใ‚„ใ™ใ response = requests.get("http://example.com/some/url") ``` -ๅฏพๅฟœใ™ใ‚‹FastAPIใฎใƒ‘ใ‚นใ‚ชใƒšใƒฌใƒผใ‚ทใƒงใƒณใฏใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: +ๅฏพๅฟœใ™ใ‚‹FastAPIใฎAPIใฎpath operationใฏใ“ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: ```Python hl_lines="1" @app.get("/some/url") @@ -106,7 +106,7 @@ def read_url(): /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } ็งใŒDjango REST Frameworkใซๆฑ‚ใ‚ใฆใ„ใŸไธปใชๆฉŸ่ƒฝใฏใ€APIใฎ่‡ชๅ‹•็š„ใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆใงใ—ใŸใ€‚ @@ -131,13 +131,13 @@ def read_url(): /// -### Flask REST ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ +### Flask REST ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ { #flask-rest-frameworks } ใ„ใใคใ‹ใฎFlask RESTใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใŒใ‚ใ‚Šใพใ™ใŒใ€ใใ‚Œใ‚‰ใ‚’่ชฟๆŸปใ—ใฆใฟใŸใจใ“ใ‚ใ€ๅคšใใฎใ‚‚ใฎใŒไธ้ฉๅˆ‡ใชๅ•้กŒใŒๆฎ‹ใฃใŸใพใพใ€ไธญๆ–ญใ•ใ‚ŒใŸใ‚Šๆ”พ็ฝฎใ•ใ‚Œใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ—ใŸใ€‚ -### Marshmallow +### Marshmallow { #marshmallow } -APIใ‚ทใ‚นใƒ†ใƒ ใงๅฟ…่ฆใจใ•ใ‚Œใ‚‹ไธปใชๆฉŸ่ƒฝใฎไธ€ใคใซใ€ใ‚ณใƒผใƒ‰ (Python) ใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ใ‚Šๅ‡บใ—ใฆใ€ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‚’ไป‹ใ—ใฆ้€ใ‚Œใ‚‹ใ‚‚ใฎใซๅค‰ๆ›ใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใฎใ€Œใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ใŒใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’JSONใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๅค‰ๆ›ใ—ใŸใ‚Šใ€`datetime` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ™ใ‚‹ใชใฉใงใ™ใ€‚ +APIใ‚ทใ‚นใƒ†ใƒ ใงๅฟ…่ฆใจใ•ใ‚Œใ‚‹ไธปใชๆฉŸ่ƒฝใฎไธ€ใคใซใ€ใ‚ณใƒผใƒ‰ (Python) ใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ใ‚Šๅ‡บใ—ใฆใ€ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‚’ไป‹ใ—ใฆ้€ใ‚Œใ‚‹ใ‚‚ใฎใซๅค‰ๆ›ใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใฎใ€Œใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ใŒใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’JSONใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๅค‰ๆ›ใ—ใŸใ‚Šใ€`datetime` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ™ใ‚‹ใชใฉใงใ™ใ€‚ APIใŒๅฟ…่ฆใจใ™ใ‚‹ใ‚‚ใ†ไธ€ใคใฎๅคงใใชๆฉŸ่ƒฝใฏใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใงใ‚ใ‚Šใ€็‰นๅฎšใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒไธŽใˆใ‚‰ใ‚ŒใŸๅ ดๅˆใซใƒ‡ใƒผใ‚ฟใŒๆœ‰ๅŠนใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ใ“ใจใงใ™ใ€‚ไพ‹ใˆใฐใ€ใ‚ใ‚‹ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใƒฉใƒณใƒ€ใƒ ใชๆ–‡ๅญ—ๅˆ—ใงใฏใชใ `int` ใงใ‚ใ‚‹ใ“ใจใชใฉใงใ™ใ€‚ใ“ใ‚Œใฏ็‰นใซๅ—ไฟกใ™ใ‚‹ใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆไพฟๅˆฉใงใ™ใ€‚ @@ -145,7 +145,7 @@ APIใŒๅฟ…่ฆใจใ™ใ‚‹ใ‚‚ใ†ไธ€ใคใฎๅคงใใชๆฉŸ่ƒฝใฏใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผ ใ“ใ‚Œใ‚‰ใฎๆฉŸ่ƒฝใฏใ€MarshmallowใŒๆไพ›ใ™ใ‚‹ใ‚‚ใฎใงใ™ใ€‚Marshmallowใฏ็ด ๆ™ดใ‚‰ใ—ใ„ใƒฉใ‚คใƒ–ใƒฉใƒชใงใ€็งใ‚‚ไปฅๅ‰ใซไฝ•ๅบฆใ‚‚ไฝฟใฃใŸใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใใ‚ŒใฏPythonใฎๅž‹ใƒ’ใƒณใƒˆใŒๅญ˜ๅœจใ™ใ‚‹ๅ‰ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใ™ใ€‚ใใฎใŸใ‚ใ€ใ™ในใฆใฎใ‚นใ‚ญใƒผใƒžใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซใฏใ€MarshmallowใŒๆไพ›ใ™ใ‚‹็‰นๅฎšใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚„ใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใใ‚ŒใฏPythonใฎๅž‹ใƒ’ใƒณใƒˆใŒๅญ˜ๅœจใ™ใ‚‹ๅ‰ใซไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใงใ™ใ€‚ใใฎใŸใ‚ใ€ใ™ในใฆใฎใ‚นใ‚ญใƒผใƒžใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซใฏใ€MarshmallowใŒๆไพ›ใ™ใ‚‹็‰นๅฎšใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚„ใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ /// check | **FastAPI**ใธไธŽใˆใŸใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณ @@ -153,9 +153,9 @@ APIใŒๅฟ…่ฆใจใ™ใ‚‹ใ‚‚ใ†ไธ€ใคใฎๅคงใใชๆฉŸ่ƒฝใฏใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผ /// -### Webargs +### Webargs { #webargs } -APIใซๆฑ‚ใ‚ใ‚‰ใ‚Œใ‚‹ไป–ใฎๅคงใใชๆฉŸ่ƒฝใจใ—ใฆใ€ๅ—ไฟกใ—ใŸใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ‡ใƒผใ‚ฟใฎใƒ‘ใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ +APIใซๆฑ‚ใ‚ใ‚‰ใ‚Œใ‚‹ไป–ใฎๅคงใใชๆฉŸ่ƒฝใจใ—ใฆใ€ๅ—ไฟกใ—ใŸใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ‡ใƒผใ‚ฟใฎใƒ‘ใƒผใ‚นใŒใ‚ใ‚Šใพใ™ใ€‚ WebargsใฏFlaskใ‚’ใฏใ˜ใ‚ใจใ™ใ‚‹ใ„ใใคใ‹ใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธŠใซใใ‚Œใ‚’ๆไพ›ใ™ใ‚‹ใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸใƒ„ใƒผใƒซใงใ™ใ€‚ @@ -175,7 +175,7 @@ Webargsใฏใ€MarshmallowใจๅŒใ˜้–‹็™บ่€…ใซใ‚ˆใ‚Šไฝœใ‚‰ใ‚Œใพใ—ใŸใ€‚ /// -### APISpec +### APISpec { #apispec } MarshmallowใจWebargsใฏใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใƒ‘ใƒผใ‚นใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ‚’ใƒ—ใƒฉใ‚ฐใ‚คใƒณใจใ—ใฆๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ @@ -205,7 +205,7 @@ OpenAPIใจใ„ใ†ใ€APIใซใคใ„ใฆใฎใ‚ชใƒผใƒ—ใƒณใชๆจ™ๆบ–ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆ /// -### Flask-apispec +### Flask-apispec { #flask-apispec } Webargsใ€Marshmallowใ€APISpecใ‚’้€ฃๆบใ•ใ›ใŸFlaskใƒ—ใƒฉใ‚ฐใ‚คใƒณใงใ™ใ€‚ @@ -237,7 +237,7 @@ Flask-apispecใฏMarshmallowใจๅŒใ˜้–‹็™บ่€…ใซใ‚ˆใ‚Šไฝœๆˆใ•ใ‚Œใพใ—ใŸใ€‚ /// -### NestJS (ใจAngular) +### NestJS (ใจAngular) { #nestjs-and-angular } NestJSใฏAngularใซใ‚คใƒณใ‚นใƒ‘ใ‚คใ‚ขใ•ใ‚ŒใŸJavaScript (TypeScript) NodeJSใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ€Pythonใงใ™ใ‚‰ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ @@ -259,13 +259,13 @@ Angular 2ใซใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๅ—ใ‘ใŸใ€็ตฑๅˆใ•ใ‚ŒใŸไพๅญ˜ๆ€ง /// -### Sanic +### Sanic { #sanic } `asyncio`ใซๅŸบใฅใ„ใŸใ€Pythonใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธญใงใ‚‚้žๅธธใซ้ซ˜้€Ÿใชใ‚‚ใฎใฎไธ€ใคใงใ™ใ€‚Flaskใจ้žๅธธใซไผผใŸไฝœใ‚Šใซใชใฃใฆใ„ใพใ™ใ€‚ /// note | ๆŠ€่ก“่ฉณ็ดฐ -Pythonใฎ`asyncio`ใƒซใƒผใƒ—ใฎไปฃใ‚ใ‚Šใซใ€`uvloop`ใŒๅˆฉ็”จใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใใ‚Œใซใ‚ˆใ‚Šใ€้žๅธธใซ้ซ˜้€Ÿใงใ™ใ€‚ +Pythonใฎ`asyncio`ใƒซใƒผใƒ—ใฎไปฃใ‚ใ‚Šใซใ€`uvloop`ใŒๅˆฉ็”จใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใใ‚Œใซใ‚ˆใ‚Šใ€้žๅธธใซ้ซ˜้€Ÿใงใ™ใ€‚ `Uvicorn`ใจ`Starlette`ใซๆ˜Žใ‚‰ใ‹ใชใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใ‚’ไธŽใˆใฆใŠใ‚Šใ€ใใ‚Œใ‚‰ใฏ็พๅœจใ‚ชใƒผใƒ—ใƒณใชใƒ™ใƒณใƒใƒžใƒผใ‚ฏใซใŠใ„ใฆSanicใ‚ˆใ‚Š้ซ˜้€Ÿใงใ™ใ€‚ @@ -279,12 +279,10 @@ Pythonใฎ`asyncio`ใƒซใƒผใƒ—ใฎไปฃใ‚ใ‚Šใซใ€`uvloop`ใŒๅˆฉ็”จใ•ใ‚Œใฆใ„ใพใ™ /// -### Falcon +### Falcon { #falcon } Falconใฏใ‚‚ใ†ไธ€ใคใฎ้ซ˜ๆ€ง่ƒฝPythonใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ€ใƒŸใƒ‹ใƒžใƒ ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€Hugใฎใ‚ˆใ†ใชไป–ใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎๅŸบ็›คใจใ—ใฆๅ‹•ไฝœใ—ใพใ™ใ€‚ -Pythonใฎใ‚ฆใ‚งใƒ–ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏๆจ™ๆบ–่ฆๆ ผ (WSGI) ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ™ใŒใ€ใใ‚ŒใฏๅŒๆœŸ็š„ใงใ‚ใ‚‹ใŸใ‚WebSocketใชใฉใฎๅˆฉ็”จใซใฏๅฏพๅฟœใ—ใฆใ„ใพใ›ใ‚“ใ€‚ใจใฏใ„ใˆใ€ใใ‚Œใงใ‚‚้žๅธธใซ้ซ˜ใ„ๆ€ง่ƒฝใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ - ใ“ใ‚Œใฏใ€ใ€Œใƒชใ‚ฏใ‚จใ‚นใƒˆใ€ใจใ€Œใƒฌใ‚นใƒใƒณใ‚นใ€ใฎ2ใคใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ—ใ‘ๅ–ใ‚‹้–ขๆ•ฐใ‚’ๆŒใคใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใใ—ใฆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’ใ€Œ่ชญใฟ่พผใฟใ€ใ€ใƒฌใ‚นใƒใƒณใ‚นใซใƒ‡ใƒผใ‚ฟใ‚’ใ€Œๆ›ธใ่พผใฟใ€ใพใ™ใ€‚ใ“ใฎ่จญ่จˆใฎใŸใ‚ใ€Pythonๆจ™ๆบ–ใฎๅž‹ใƒ’ใƒณใƒˆใงใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใ‚’้–ขๆ•ฐใฎๅผ•ๆ•ฐใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ ใใฎใŸใ‚ใ€ใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใฏใ€่‡ชๅ‹•็š„ใซใงใใšใ‚ณใƒผใƒ‰ใฎไธญใง่กŒใ‚ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใ‚ใ‚‹ใ„ใฏใ€Hugใฎใ‚ˆใ†ใซFalconใฎไธŠใซใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใจใ—ใฆๅฎŸ่ฃ…ใ•ใ‚Œใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใ“ใฎใ‚ˆใ†ใชๅˆ†ๆ–ญใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ1ใคใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใจ1ใคใฎใƒฌใ‚นใƒใƒณใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆŒใคใจใ„ใ†Falconใฎใƒ‡ใ‚ถใ‚คใƒณใซใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๅ—ใ‘ใŸไป–ใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ‚‚่ตทใ“ใ‚Šใพใ™ใ€‚ @@ -299,7 +297,7 @@ Hug (HugใฏFalconใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใพใ™) ใจไธ€็ท’ใซใ€**FastAPI**ใŒ`r /// -### Molten +### Molten { #molten } **FastAPI**ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๆœ€ๅˆใฎๆฎต้šŽใงMoltenใ‚’็™บ่ฆ‹ใ—ใพใ—ใŸใ€‚ใใ—ใฆใ€ใใ‚Œใฏ้žๅธธใซไผผใŸใ‚ˆใ†ใชใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ @@ -323,7 +321,7 @@ Pydanticใฎใ‚ˆใ†ใชใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ท /// -### Hug +### Hug { #hug } Hugใฏใ€Pythonใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ๅˆฉ็”จใ—ใฆAPIใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ๅฎฃ่จ€ใ‚’ๅฎŸ่ฃ…ใ—ใŸๆœ€ๅˆใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎ1ใคใงใ™ใ€‚ใ“ใ‚Œใฏ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚ขใ‚คใƒ‡ใ‚ขใงใ€ไป–ใฎใƒ„ใƒผใƒซใŒๅŒใ˜ใ“ใจใ‚’ใ™ใ‚‹ใใฃใ‹ใ‘ใจใชใ‚Šใพใ—ใŸใ€‚ @@ -353,7 +351,7 @@ Hugใฏใ€**FastAPI**ใŒใƒ˜ใƒƒใƒ€ใƒผใ‚„ใ‚ฏใƒƒใ‚ญใƒผใ‚’่จญๅฎšใ™ใ‚‹ใŸใ‚ใซ้–ขๆ•ฐ /// -### APIStar (<= 0.5) +### APIStar (<= 0.5) { #apistar-0-5 } **FastAPI**ใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใ“ใจใ‚’ๆฑบใ‚ใ‚‹็›ดๅ‰ใซใ€**APIStar**ใ‚ตใƒผใƒใƒผใ‚’่ฆ‹ใคใ‘ใพใ—ใŸใ€‚ใใ‚Œใฏ็งใŒๆŽขใ—ใฆใ„ใŸใ‚‚ใฎใŒใปใผใ™ในใฆๅซใพใ‚ŒใฆใŠใ‚Šใ€็ด ๆ™ดใ‚‰ใ—ใ„ใƒ‡ใ‚ถใ‚คใƒณใงใ—ใŸใ€‚ @@ -401,9 +399,9 @@ APIStarใฏTom Christieใซใ‚ˆใ‚Š้–‹็™บใ•ใ‚Œใพใ—ใŸใ€‚ไปฅไธ‹ใฎ้–‹็™บ่€…ใงใ‚‚ /// -## **FastAPI**ใŒๅˆฉ็”จใ—ใฆใ„ใ‚‹ใ‚‚ใฎ +## **FastAPI**ใŒๅˆฉ็”จใ—ใฆใ„ใ‚‹ใ‚‚ใฎ { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } Pydanticใฏใ€Pythonใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ๅ…ƒใซใƒ‡ใƒผใ‚ฟใฎใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚ผใƒผใ‚ทใƒงใƒณใ€ (JSON Schemaใ‚’ไฝฟ็”จใ—ใŸ) ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅฎš็พฉใ™ใ‚‹ใƒฉใ‚คใƒ–ใƒฉใƒชใงใ™ใ€‚ @@ -419,9 +417,9 @@ MarshmallowใซๅŒนๆ•ตใ—ใพใ™ใŒใ€ใƒ™ใƒณใƒใƒžใƒผใ‚ฏใงใฏMarshmallowใ‚ˆใ‚Šใ‚‚ /// -### Starlette +### Starlette { #starlette } -Starletteใฏใ€่ปฝ้‡ใชASGIใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ/ใƒ„ใƒผใƒซใ‚ญใƒƒใƒˆใงใ€้ซ˜ๆ€ง่ƒฝใช้žๅŒๆœŸใ‚ตใƒผใƒ“ใ‚นใฎๆง‹็ฏ‰ใซๆœ€้ฉใงใ™ใ€‚ +Starletteใฏใ€่ปฝ้‡ใชASGIใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ/ใƒ„ใƒผใƒซใ‚ญใƒƒใƒˆใงใ€้ซ˜ๆ€ง่ƒฝใช้žๅŒๆœŸใ‚ตใƒผใƒ“ใ‚นใฎๆง‹็ฏ‰ใซๆœ€้ฉใงใ™ใ€‚ ้žๅธธใซใ‚ทใƒณใƒ—ใƒซใง็›ดๆ„Ÿ็š„ใงใ™ใ€‚็ฐกๅ˜ใซๆ‹กๅผตใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€ใƒขใ‚ธใƒฅใƒผใƒซๅŒ–ใ•ใ‚ŒใŸใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ @@ -429,15 +427,14 @@ Starletteใฏใ€่ปฝ้‡ใชUvicorn +### Uvicorn { #uvicorn } Uvicornใฏ้žๅธธใซ้ซ˜้€ŸใชASGIใ‚ตใƒผใƒใƒผใงใ€uvloopใจhttptoolsใซใ‚ˆใ‚Šๆง‹ๆˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -477,12 +474,12 @@ Starletteใ‚„**FastAPI**ใฎใ‚ตใƒผใƒใƒผใจใ—ใฆๆŽจๅฅจใ•ใ‚Œใฆใ„ใพใ™ใ€‚ **FastAPI**ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒใ™ใ‚‹ใƒกใ‚คใƒณใฎใ‚ฆใ‚งใƒ–ใ‚ตใƒผใƒใƒผใงใ‚ใ‚‹็‚นใ€‚ -Gunicornใจ็ต„ใฟๅˆใ‚ใ›ใ‚‹ใ“ใจใงใ€้žๅŒๆœŸใงใƒžใƒซใƒใƒ—ใƒญใ‚ปใ‚นใชใ‚ตใƒผใƒใƒผใ‚’ๆŒใคใ“ใจใŒใใพใ™ใ€‚ +ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณ `--workers` ใ‚’ไฝฟใฃใฆใ€้žๅŒๆœŸใฎใƒžใƒซใƒใƒ—ใƒญใ‚ปใ‚นใ‚ตใƒผใƒใƒผใซใงใใพใ™ใ€‚ ่ฉณ็ดฐใฏ[ใƒ‡ใƒ—ใƒญใ‚ค](deployment/index.md){.internal-link target=_blank}ใฎ้ …็›ฎใง็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ /// -## ใƒ™ใƒณใƒใƒžใƒผใ‚ฏ ใจ ใ‚นใƒ”ใƒผใƒ‰ +## ใƒ™ใƒณใƒใƒžใƒผใ‚ฏ ใจ ใ‚นใƒ”ใƒผใƒ‰ { #benchmarks-and-speed } Uvicornใ€Starletteใ€FastAPIใฎ้•ใ„ใ‚’็†่งฃใ€ๆฏ”่ผƒใ€็ขบ่ชใ™ใ‚‹ใซใฏใ€[ใƒ™ใƒณใƒใƒžใƒผใ‚ฏ](benchmarks.md){.internal-link target=_blank}ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/async.md b/docs/ja/docs/async.md index 90a2e2ee55..bf4acda3f7 100644 --- a/docs/ja/docs/async.md +++ b/docs/ja/docs/async.md @@ -1,18 +1,18 @@ -# ไธฆ่กŒๅ‡ฆ็†ใจ async / await +# ไธฆ่กŒๅ‡ฆ็†ใจ async / await { #concurrency-and-async-await } -*path operation ้–ขๆ•ฐ*ใฎใŸใ‚ใฎ `async def` ใซ้–ขใ™ใ‚‹่ฉณ็ดฐใจ้žๅŒๆœŸ (asynchronous) ใ‚ณใƒผใƒ‰ใ€ไธฆ่กŒๅ‡ฆ็† (Concurrency)ใ€ใใ—ใฆใ€ไธฆๅˆ—ๅ‡ฆ็† (Parallelism) ใฎ่ƒŒๆ™ฏใซใคใ„ใฆใ€‚ +*path operation ้–ขๆ•ฐ*ใฎใŸใ‚ใฎ `async def` ๆง‹ๆ–‡ใซ้–ขใ™ใ‚‹่ฉณ็ดฐใจใ€้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ€ไธฆ่กŒๅ‡ฆ็†ใ€ไธฆๅˆ—ๅ‡ฆ็†ใฎ่ƒŒๆ™ฏใซใคใ„ใฆใงใ™ใ€‚ -## ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸ +## ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸ { #in-a-hurry } -TL;DR: +TL;DR: -ๆฌกใฎใ‚ˆใ†ใชใ€`await` ใ‚’ไฝฟ็”จใ—ใฆๅ‘ผใณๅ‡บใ™ในใใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆ: +ๆฌกใฎใ‚ˆใ†ใซ `await` ใงๅ‘ผใณๅ‡บใ™ใ‚ˆใ†ๆŒ‡็คบใ•ใ‚Œใฆใ„ใ‚‹ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟใฃใฆใ„ใ‚‹ใชใ‚‰: ```Python results = await some_library() ``` -ไปฅไธ‹ใฎๆง˜ใซ `async def` ใ‚’ไฝฟ็”จใ—ใฆ*path operation ้–ขๆ•ฐ*ใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ +*path operation ้–ขๆ•ฐ*ใฏๆฌกใฎใ‚ˆใ†ใซ `async def` ใงๅฎฃ่จ€ใ—ใพใ™: ```Python hl_lines="2" @app.get('/') @@ -23,13 +23,13 @@ async def read_results(): /// note | ๅ‚™่€ƒ -`async def` ใ‚’ไฝฟ็”จใ—ใฆไฝœๆˆใ•ใ‚ŒใŸ้–ขๆ•ฐใฎๅ†…้ƒจใงใ—ใ‹ `await` ใฏไฝฟ็”จใงใใพใ›ใ‚“ใ€‚ +`await` ใฏ `async def` ใงไฝœใ‚‰ใ‚ŒใŸ้–ขๆ•ฐใฎๅ†…้ƒจใงใ—ใ‹ไฝฟใˆใพใ›ใ‚“ใ€‚ /// --- -ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€APIใ€ใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ใชใฉใจ้€šไฟกใ—ใ€`await` ใฎไฝฟ็”จใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ„ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใƒฉใ‚คใƒ–ใƒฉใƒช (็พๅœจใฎใปใจใ‚“ใฉใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒฉใ‚คใƒ–ใƒฉใƒชใซๅฝ“ใฆใฏใพใ‚Šใพใ™) ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ๆฌกใฎๆง˜ใซใ€ๅ˜ใซ `def` ใ‚’ไฝฟ็”จใ—ใฆ้€šๅธธ้€šใ‚Š *path operation ้–ขๆ•ฐ* ใ‚’ๅฎฃ่จ€ใ—ใฆใใ ใ•ใ„: +ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€APIใ€ใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ใชใฉใจ้€šไฟกใ—ใคใค `await` ใฎไฝฟ็”จใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใชใ„ใ‚ตใƒผใƒ‰ใƒ‘ใƒผใƒ†ใ‚ฃใƒฉใ‚คใƒ–ใƒฉใƒช (็พๅœจใฎใจใ“ใ‚ๅคšใใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒฉใ‚คใƒ–ใƒฉใƒชใŒ่ฉฒๅฝ“ใ—ใพใ™) ใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใ€*path operation ้–ขๆ•ฐ*ใฏ้€šๅธธใฉใŠใ‚Š `def` ใงๅฎฃ่จ€ใ—ใฆใใ ใ•ใ„: ```Python hl_lines="2" @app.get('/') @@ -40,272 +40,307 @@ def results(): --- -ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ (ใฉใ†ใ„ใ†ใ‚ใ‘ใ‹) ไป–ใฎไฝ•ใจใ‚‚้€šไฟกใ›ใšใ€ๅฟœ็ญ”ใ‚’ๅพ…ใคๅฟ…่ฆใŒใชใ„ๅ ดๅˆใฏใ€`async def` ใ‚’ไฝฟ็”จใ—ใฆไธ‹ใ•ใ„ใ€‚ +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ (ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใง) ใปใ‹ใฎไฝ•ใจใ‚‚้€šไฟกใ›ใšๅฟœ็ญ”ใ‚’ๅพ…ใคๅฟ…่ฆใŒใชใ„ใชใ‚‰ใ€`await` ใ‚’ๅ†…้ƒจใงไฝฟใ‚ใชใใฆใ‚‚ `async def` ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ --- -ใ‚ˆใๅˆ†ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€้€šๅธธใฎ `def` ใ‚’ไฝฟ็”จใ—ใฆไธ‹ใ•ใ„ใ€‚ +ใ‚ˆใๅˆ†ใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€้€šๅธธใฎ `def` ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ --- -**ๅ‚™่€ƒ**: *path operation ้–ขๆ•ฐ*ใซๅฟ…่ฆใชใ ใ‘ `def` ใจ `async def` ใ‚’ๆททๅœจใ•ใ›ใ€ใใ‚Œใžใ‚Œใซๆœ€้ฉใชใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟ็”จใ—ใฆๅฎš็พฉใงใใพใ™ใ€‚ใใ‚Œใซๅฟœใ˜ใฆFastAPIใฏๆญฃใ—ใ„ๅ‡ฆ็†ใ‚’่กŒใ„ใพใ™ใ€‚ +**ๅ‚™่€ƒ**: ๅฟ…่ฆใซๅฟœใ˜ใฆ *path operation ้–ขๆ•ฐ* ใงใฏ `def` ใจ `async def` ใ‚’ๆททๅœจใ•ใ›ใ€ใใ‚Œใžใ‚Œใซๆœ€้ฉใช้ธๆŠž่‚ขใงๅฎš็พฉใงใใพใ™ใ€‚FastAPI ใฏ้ฉๅˆ‡ใซๅ‡ฆ็†ใ—ใพใ™ใ€‚ -ใจใซใ‹ใใ€ไธŠ่จ˜ใฎใ„ใšใ‚Œใฎๅ ดๅˆใงใ‚‚FastAPIใฏ้žๅŒๆœŸใงๅ‹•ไฝœใ—ใ€้žๅธธใซ้ซ˜้€Ÿใงใ™ใ€‚ +ใ„ใšใ‚Œใฎๅ ดๅˆใงใ‚‚ใ€FastAPI ใฏ้žๅŒๆœŸใงๅ‹•ไฝœใ—้žๅธธใซ้ซ˜้€Ÿใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€ไธŠ่จ˜ใฎใ‚นใƒ†ใƒƒใƒ—ใซๅพ“ใ†ใ“ใจใงใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใฎๆœ€้ฉๅŒ–ใ‚’่กŒใˆใพใ™ใ€‚ +ใŸใ ใ—ไธŠ่จ˜ใฎๆ‰‹้ †ใซๅพ“ใ†ใ“ใจใงใ€ใ•ใ‚‰ใซใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๆœ€้ฉๅŒ–ใŒๅฏ่ƒฝใซใชใ‚Šใพใ™ใ€‚ -## ๆŠ€่ก“่ฉณ็ดฐ +## ๆŠ€่ก“่ฉณ็ดฐ { #technical-details } -็พไปฃ็‰ˆใฎPythonใฏใ€Œ**้žๅŒๆœŸใ‚ณใƒผใƒ‰**ใ€ใ‚’ใ€ใ€Œ**ใ‚ณใƒซใƒผใƒใƒณ**ใ€ใจ็งฐใ•ใ‚Œใ‚‹ใ‚‚ใฎใ‚’ๅˆฉ็”จใ—ใฆใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใฏ **`async` ใจ `await`** ๆง‹ๆ–‡ใ‚’็”จใ„ใพใ™ใ€‚ +ใƒขใƒ€ใƒณใช Python ใฏ **ใ€Œ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ€** ใ‚’ **ใ€Œใ‚ณใƒซใƒผใƒใƒณใ€** ใจๅ‘ผใฐใ‚Œใ‚‹ไป•็ต„ใฟใงใ‚ตใƒใƒผใƒˆใ—ใฆใŠใ‚Šใ€ๆง‹ๆ–‡ใฏ **`async` ใจ `await`** ใงใ™ใ€‚ -ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใ€ใƒ•ใƒฌใƒผใ‚บๅ†…ใฎใƒ‘ใƒผใƒ„ใ‚’้ †ใซ่ฆ‹ใฆใ„ใใพใ—ใ‚‡ใ†: +ไปฅไธ‹ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใ€ใ“ใฎใƒ•ใƒฌใƒผใ‚บใ‚’ใƒ‘ใƒผใƒ„ใ”ใจใซ่ฆ‹ใฆใ„ใใพใ™: * **้žๅŒๆœŸใ‚ณใƒผใƒ‰** * **`async` ใจ `await`** * **ใ‚ณใƒซใƒผใƒใƒณ** -## ้žๅŒๆœŸใ‚ณใƒผใƒ‰ +## ้žๅŒๆœŸใ‚ณใƒผใƒ‰ { #asynchronous-code } -้žๅŒๆœŸใ‚ณใƒผใƒ‰ใจใฏใ€่จ€่ชž๐Ÿ’ฌใŒใ‚ณใƒผใƒ‰ๅ†…ใฎใฉใ“ใ‹ใงใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ๐Ÿค–ใซ *ไป–ใฎไฝ•ใ‹* ใŒใฉใ“ใ‹ๅˆฅใฎ็ฎ‡ๆ‰€ใง็ต‚ไบ†ใ™ใ‚‹ใฎใ‚’ๅพ…ใคใ‚ˆใ†ใซไผใˆใ‚‹ๆ‰‹ๆฎตใ‚’ๆŒใฃใฆใ„ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚*ไป–ใฎไฝ•ใ‹* ใฏใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซ๐Ÿ“ใ€ใจๅ‘ผใฐใ‚Œใฆใ„ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†. +้žๅŒๆœŸใ‚ณใƒผใƒ‰ใจใฏใ€่จ€่ชž ๐Ÿ’ฌ ใŒใ‚ณใƒผใƒ‰ใฎใฉใ“ใ‹ใฎๆ™‚็‚นใงใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ  ๐Ÿค– ใซใ€Œใฉใ“ใ‹ๅˆฅใฎใจใ“ใ‚ใง็ต‚ใ‚ใ‚‹ใพใงใ€ๅˆฅใฎไฝ•ใ‹ใ€ใ‚’ๅพ…ใคๅฟ…่ฆใŒใ‚ใ‚‹ใจไผใˆใ‚‹ๆ‰‹ๆฎตใ‚’ๆŒใฃใฆใ„ใ‚‹ใ€ใจใ„ใ†ใ“ใจใงใ™ใ€‚ใใฎใ€Œๅˆฅใฎไฝ•ใ‹ใ€ใ‚’ใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซใ€๐Ÿ“ ใจๅ‘ผใถใ“ใจใซใ—ใพใ—ใ‚‡ใ†ใ€‚ -ใ—ใŸใŒใฃใฆใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใฏใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซ๐Ÿ“ใ€ใŒ็ต‚ไบ†ใ™ใ‚‹ใพใงใ€ไป–ใฎๅ‡ฆ็†ใŒใงใใพใ™ใ€‚ +ใใฎ้–“ใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใฏใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซใ€๐Ÿ“ ใŒ็ต‚ใ‚ใ‚‹ใพใงใ€ไป–ใฎไฝœๆฅญใ‚’้€ฒใ‚ใ‚‰ใ‚Œใพใ™ใ€‚ -ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ๐Ÿค–ใฏๅ†ใณๅพ…ๆฉŸใ™ใ‚‹ๆฉŸไผšใŒใ‚ใ‚‹ใจใใ‚„ใ€ใใฎๆ™‚็‚นใง่กŒใฃใฆใ„ใŸใ™ในใฆใฎไฝœๆฅญใŒๅฎŒไบ†ใ™ใ‚‹ใŸใณใซๆˆปใฃใฆใใพใ™ใ€‚ใใ—ใฆใ€ๅฟ…่ฆใชๅ‡ฆ็†ใ‚’ใ—ใชใŒใ‚‰ใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ๐Ÿค–ใŒๅพ…ใฃใฆใ„ใŸๅ‡ฆ็†ใฎใฉใ‚Œใ‹ใŒ็ต‚ใ‚ใฃใฆใ„ใ‚‹ใ‹ใฉใ†ใ‹็ขบ่ชใ—ใพใ™ใ€‚ +ใใฎๅพŒใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ  ๐Ÿค– ใฏใ€ใพใŸๅพ…ใคๆฉŸไผšใŒๆฅใŸใจใใ‚„ใ€ใใฎๆ™‚็‚นใงๆŠฑใˆใฆใ„ใŸไฝœๆฅญใ‚’ใ™ในใฆ็ต‚ใˆใŸใจใใซๆˆปใฃใฆใใพใ™ใ€‚ใใ—ใฆใ€ๅพ…ใฃใฆใ„ใŸใ‚ฟใ‚นใ‚ฏใฎใฉใ‚Œใ‹ใŒ็ต‚ใ‚ใฃใฆใ„ใชใ„ใ‹็ขบ่ชใ—ใ€ๅฟ…่ฆใชๅ‡ฆ็†ใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ -ๆฌกใซใ€ใใ‚Œ๐Ÿค–ใŒๆœ€ๅˆใฎใ‚ฟใ‚นใ‚ฏ (่ฆใ™ใ‚‹ใซใ€ๅ…ˆ็จ‹ใฎใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซ๐Ÿ“ใ€)ใ‚’็ต‚ใ‚ใ‚‰ใ›ใฆใ€ใใฎใ‚ฟใ‚นใ‚ฏใฎ็ตๆžœใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅ‡ฆ็†ใ‚’็ถšใ‘ใพใ™ใ€‚ +ๆฌกใซใ€ๆœ€ๅˆใซ็ต‚ใ‚ใฃใŸใ‚ฟใ‚นใ‚ฏ (ใŸใจใˆใฐใ€Œ้…ใ„ใƒ•ใ‚กใ‚คใƒซใ€๐Ÿ“) ใ‚’ๅ–ใ‚Šใ€็ถšใใฎๅ‡ฆ็†ใ‚’่กŒใ„ใพใ™ใ€‚ -ใ“ใฎใ€Œไป–ใฎไฝ•ใ‹ใ‚’ๅพ…ใคใ€ใจใฏใ€้€šๅธธไปฅไธ‹ใฎๆง˜ใชใ‚‚ใฎใ‚’ๅพ…ใคใ‚ˆใ†ใช (ใƒ—ใƒญใ‚ปใƒƒใ‚ตใจRAMใƒกใƒขใƒชใฎ้€Ÿๅบฆใซๆฏ”ในใฆ) ็›ธๅฏพ็š„ใซใ€Œ้…ใ„ใ€I/O ๆ“ไฝœใ‚’ๆŒ‡ใ—ใพใ™: +ใ“ใฎใ€Œๅˆฅใฎไฝ•ใ‹ใ‚’ๅพ…ใคใ€ใฏใ€้€šๅธธ I/O ๆ“ไฝœใ‚’ๆŒ‡ใ—ใ€(ใƒ—ใƒญใ‚ปใƒƒใ‚ตใ‚„ RAM ใฎ้€Ÿๅบฆใซๆฏ”ในใฆ) ็›ธๅฏพ็š„ใซใ€Œ้…ใ„ใ€ๅพ…ๆฉŸใ‚’ไผดใ„ใพใ™ใ€‚ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใชใ‚‚ใฎใงใ™: -* ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ็ตŒ็”ฑใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰้€ไฟกใ•ใ‚Œใ‚‹ใƒ‡ใƒผใ‚ฟ -* ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ็ตŒ็”ฑใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅ—ไฟกใ™ใ‚‹ใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‹ใ‚‰้€ไฟกใ•ใ‚ŒใŸใƒ‡ใƒผใ‚ฟ -* ใ‚ทใ‚นใƒ†ใƒ ใซใ‚ˆใฃใฆ่ชญใฟๅ–ใ‚‰ใ‚Œใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใซๆธกใ•ใ‚Œใ‚‹ใƒ‡ใ‚ฃใ‚นใ‚ฏๅ†…ใฎใƒ•ใ‚กใ‚คใƒซๅ†…ๅฎน -* ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใ‚ทใ‚นใƒ†ใƒ ใซๆธกใ—ใฆใ€ใƒ‡ใ‚ฃใ‚นใ‚ฏใซๆ›ธใ่พผใ‚€ๅ†…ๅฎน -* ใƒชใƒขใƒผใƒˆAPIๆ“ไฝœ +* ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ็ตŒ็”ฑใงใƒ‡ใƒผใ‚ฟใŒ้€ใ‚‰ใ‚Œใฆใใ‚‹ใฎใ‚’ๅพ…ใค +* ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒ้€ไฟกใ—ใŸใƒ‡ใƒผใ‚ฟใ‚’ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใƒใƒƒใƒˆใƒฏใƒผใ‚ฏ็ตŒ็”ฑใงๅ—ใ‘ๅ–ใ‚‹ใฎใ‚’ๅพ…ใค +* ใƒ‡ใ‚ฃใ‚นใ‚ฏไธŠใฎใƒ•ใ‚กใ‚คใƒซๅ†…ๅฎนใŒใ‚ทใ‚นใƒ†ใƒ ใซใ‚ˆใ‚Š่ชญใฟๅ–ใ‚‰ใ‚Œใ€ใƒ—ใƒญใ‚ฐใƒฉใƒ ใซๆธกใ•ใ‚Œใ‚‹ใฎใ‚’ๅพ…ใค +* ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใ‚ทใ‚นใƒ†ใƒ ใซๆธกใ—ใŸๅ†…ๅฎนใŒใƒ‡ใ‚ฃใ‚นใ‚ฏใซๆ›ธใ่พผใพใ‚Œใ‚‹ใฎใ‚’ๅพ…ใค +* ใƒชใƒขใƒผใƒˆ API ๆ“ไฝœ * ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆ“ไฝœใฎๅฎŒไบ† -* ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ฏใ‚จใƒชใŒ็ตๆžœใ‚’่ฟ”ใ™ใ“ใจ -* ใชใฉใ€‚ +* ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ฏใ‚จใƒชใŒ็ตๆžœใ‚’่ฟ”ใ™ใฎใ‚’ๅพ…ใค +* ใชใฉ -ๅฎŸ่กŒๆ™‚้–“ใฎใปใจใ‚“ใฉใŒI/O ๆ“ไฝœใฎๅพ…ใกๆ™‚้–“ใŒๅ ใ‚ใ‚‹ใŸใ‚ใ€ใ“ใฎใ‚ˆใ†ใชๆ“ไฝœใ‚’ใ€ŒI/O ใƒใ‚ฆใƒณใƒ‰ใ€ๆ“ไฝœใจ่จ€ใ„ใพใ™ใ€‚ +ๅฎŸ่กŒๆ™‚้–“ใฎๅคงๅŠใŒ I/O ๆ“ไฝœใฎๅพ…ใกๆ™‚้–“ใซ่ฒปใ‚„ใ•ใ‚Œใ‚‹ใŸใ‚ใ€ใ“ใ‚Œใ‚‰ใฏใ€ŒI/O ใƒใ‚ฆใƒณใƒ‰ใ€ใชๆ“ไฝœใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ -ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใ“ใฎใ‚ˆใ†ใช้…ใ„ใ‚ฟใ‚นใ‚ฏใจใ€ŒๅŒๆœŸ (ใ‚ฟใ‚นใ‚ฏใฎ็ตๆžœใ‚’ๅ–ๅพ—ใ—ใฆไฝœๆฅญใ‚’็ถš่กŒใ™ใ‚‹ใŸใ‚ใซใ€ไฝ•ใ‚‚ใ›ใšใซใ€ใ‚ฟใ‚นใ‚ฏใŒๅฎŒไบ†ใ™ใ‚‹็žฌ้–“ใ‚’ๆญฃ็ขบใซๅพ…ใค)ใ€ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ใŸใ‚ใ€ใ€Œ้žๅŒๆœŸใ€ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ +ใ€Œ้žๅŒๆœŸใ€ใจๅ‘ผใฐใ‚Œใ‚‹ใฎใฏใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใใฎ้…ใ„ใ‚ฟใ‚นใ‚ฏใจใ€ŒๅŒๆœŸใ€(ใ‚ฟใ‚นใ‚ฏใŒใกใ‚‡ใ†ใฉ็ต‚ใ‚ใ‚‹็žฌ้–“ใ‚’ใ€ไฝ•ใ‚‚ใ›ใšใซๅพ…ใค) ใ™ใ‚‹ๅฟ…่ฆใŒใชใ„ใ‹ใ‚‰ใงใ™ใ€‚็ตๆžœใ‚’ๅ—ใ‘ๅ–ใฃใฆๅ‡ฆ็†ใ‚’็ถšใ‘ใ‚‹ใŸใ‚ใซใ€็ฉบๅพ…ใกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใใฎไปฃใ‚ใ‚Šใซใ€ใ€Œ้žๅŒๆœŸใ€ใ‚ทใ‚นใƒ†ใƒ ใงใ‚ใ‚‹ใ“ใจใซใ‚ˆใ‚Šใ€ใ„ใฃใŸใ‚“็ต‚ไบ†ใ™ใ‚‹ใจใ€ใ‚ฟใ‚นใ‚ฏใฏใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒๆ—ขใซ้–‹ๅง‹ใ—ใŸๅ‡ฆ็†ใŒใ™ในใฆๅฎŒไบ†ใ™ใ‚‹ใฎใ‚’ใปใ‚“ใฎๅฐ‘ใ— (ๆ•ฐใƒžใ‚คใ‚ฏใƒญ็ง’) ๅพ…ใฃใฆใ€็ตๆžœใ‚’ๅ—ใ‘ๅ–ใ‚Šใซๆˆปใฃใฆใใพใ™ใ€‚ใใ—ใฆใ€ๅ‡ฆ็†ใ‚’็ถ™็ถšใ—ใพใ™ใ€‚ +ไปฃใ‚ใ‚Šใซใ€Œ้žๅŒๆœŸใ€ใ‚ทใ‚นใƒ†ใƒ ใงใฏใ€ใ‚ฟใ‚นใ‚ฏใŒ็ต‚ใ‚ใฃใŸใ‚‰ใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒๅ–ใ‚Šใ‹ใ‹ใฃใฆใ„ใ‚‹ไฝœๆฅญใŒ็ต‚ใ‚ใ‚‹ใพใง (ๆ•ฐใƒžใ‚คใ‚ฏใƒญ็ง’ใปใฉ) ๅฐ‘ใ—ๅพ…ใกใ€็ตๆžœใ‚’ๅ—ใ‘ๅ–ใ‚Šใซๆˆปใฃใฆๅ‡ฆ็†ใ‚’็ถšใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ -ใ€ŒๅŒๆœŸใ€ใฎๅ ดๅˆ (ใ€Œ้žๅŒๆœŸใ€ใจใฏ็•ฐใชใ‚Š)ใ€ใ€Œใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใ€ใจใ„ใ†็”จ่ชžใ‚‚ใ‚ˆใไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใ™ในใฆใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’ (ๅพ…ๆฉŸใŒไผดใ†ๅ ดๅˆใงใ‚‚ๅˆฅใฎใ‚ฟใ‚นใ‚ฏใซๅˆ‡ใ‚Šๆ›ฟใˆใ‚‹ใ“ใจใชใ) ้ †็•ชใซๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ +ใ€Œ้žๅŒๆœŸใ€ใจๅฏพใซใชใ‚‹ใ€ŒๅŒๆœŸใ€ใฏใ€ใ€Œใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใ€ใจๅ‘ผใฐใ‚Œใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ๅพ…ๆฉŸใŒๅซใพใ‚Œใฆใ„ใฆใ‚‚ใ€ๅˆฅใฎใ‚ฟใ‚นใ‚ฏใซๅˆ‡ใ‚Šๆ›ฟใˆใ‚‹ๅ‰ใซใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒๆ‰‹้ †ใ‚’้ †็•ชใซๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ -### ไธฆ่กŒๅ‡ฆ็†ใจใƒใƒณใƒใƒผใ‚ฌใƒผ +### ไธฆ่กŒๅ‡ฆ็†ใจใƒใƒณใƒใƒผใ‚ฌใƒผ { #concurrency-and-burgers } -ไธŠ่จ˜ใฎ**้žๅŒๆœŸ**ใ‚ณใƒผใƒ‰ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฏใ€**ใ€Œไธฆ่กŒๅ‡ฆ็†ใ€**ใจๅ‘ผใฐใ‚Œใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ **ใ€Œไธฆๅˆ—ๅ‡ฆ็†ใ€**ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ +ไธŠใง่ชฌๆ˜Žใ—ใŸ**้žๅŒๆœŸ**ใ‚ณใƒผใƒ‰ใฎ่€ƒใˆๆ–นใฏใ€**ใ€Œไธฆ่กŒๅ‡ฆ็†ใ€** ใจๅ‘ผใฐใ‚Œใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏ **ใ€Œไธฆๅˆ—ๅ‡ฆ็†ใ€** ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ -**ไธฆ่กŒๅ‡ฆ็†**ใจ**ไธฆๅˆ—ๅ‡ฆ็†**ใฏใฉใกใ‚‰ใ‚‚ใ€Œๅคšใ‹ใ‚Œๅฐ‘ใชใ‹ใ‚ŒๅŒๆ™‚ใซ็™บ็”Ÿใ™ใ‚‹ใ•ใพใ–ใพใชใ“ใจใ€ใซ้–ข้€ฃใ—ใฆใ„ใพใ™ใ€‚ +**ไธฆ่กŒๅ‡ฆ็†** ใ‚‚ **ไธฆๅˆ—ๅ‡ฆ็†** ใ‚‚ใ€ใ€Œ่ค‡ๆ•ฐใฎใ“ใจใŒใ ใ„ใŸใ„ๅŒๆ™‚ใซ่ตทใใ‚‹ใ€ใ“ใจใซ้–ขไฟ‚ใ—ใพใ™ใ€‚ -ใŸใ ใ—ใ€*ไธฆ่กŒๅ‡ฆ็†*ใจ*ไธฆๅˆ—ๅ‡ฆ็†*ใฎ่ฉณ็ดฐใฏใพใฃใŸใ็•ฐใชใ‚Šใพใ™ใ€‚ +ใŸใ ใ—ใ€*ไธฆ่กŒๅ‡ฆ็†* ใจ *ไธฆๅˆ—ๅ‡ฆ็†* ใฎ่ฉณ็ดฐใฏใ‹ใชใ‚Š็•ฐใชใ‚Šใพใ™ใ€‚ -้•ใ„ใ‚’็ขบ่ชใ™ใ‚‹ใซใฏใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใซ้–ขใ™ใ‚‹ๆฌกใฎ็‰ฉ่ชžใ‚’ๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„: +้•ใ„ใ‚’่ฆ‹ใ‚‹ใŸใ‚ใซใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใซ้–ขใ™ใ‚‹ๆฌกใฎ็‰ฉ่ชžใ‚’ๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ -### ไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผ +### ไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผ { #concurrent-burgers } -ใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰๐Ÿ”ใ‚’้ฃŸในใ‚ˆใ†ใจใ€ๅฅฝใใชไบบ๐Ÿ˜ใจใƒฌใ‚ธใซไธฆใ‚“ใงใŠใ‚Šใ€ใƒฌใ‚ธไฟ‚๐Ÿ’ใŒใ‚ใชใŸใฎๅ‰ใซใ„ใ‚‹ไบบ้”ใฎๆณจๆ–‡ใ‚’ๅ—ใ‘ใคใ‘ใฆใ„ใพใ™ใ€‚ +ใ‚ใชใŸใฏๅฅฝใใชไบบใจใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ใ‚’่ฒทใ„ใซ่กŒใใ€ๅ‰ใฎไบบใŸใกใฎๆณจๆ–‡ใ‚’ใƒฌใ‚ธไฟ‚ใŒๅ—ใ‘ใ‚‹้–“ใ€ๅˆ—ใซไธฆใณใพใ™ใ€‚๐Ÿ˜ -ใใ‚Œใ‹ใ‚‰ใ‚ใชใŸใฎ็•ชใซใชใ‚Šใ€ๅฅฝใใชไบบ๐Ÿ˜ใจ่‡ชๅˆ†ใฎใŸใ‚ใซใ€2ใคใฎ้žๅธธใซ่ฑช่ฏใชใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๆณจๆ–‡ใ—ใพใ™ใ€‚ + -ๆ–™้‡‘ใ‚’ๆ”ฏๆ‰•ใ„ใพใ™๐Ÿ’ธใ€‚ +ใ‚„ใŒใฆใ‚ใชใŸใฎ็•ชใซใชใ‚Šใ€ๅฅฝใใชไบบใจ่‡ชๅˆ†ใฎใŸใ‚ใซใ€ใจใฆใ‚‚่ฑช่ฏใชใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’2ใคๆณจๆ–‡ใ—ใพใ™ใ€‚๐Ÿ”๐Ÿ” -ใƒฌใ‚ธไฟ‚๐Ÿ’ใฏใ‚ญใƒƒใƒใƒณใฎ็”ท๐Ÿ‘จโ€๐Ÿณใซๅ‘ใ‹ใฃใฆใ€ใ‚ใชใŸใฎใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๆบ–ๅ‚™ใ—ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใจไผใˆใ‚‹ใŸใ‚ใซไฝ•ใ‹่จ€ใ„ใพใ—ใŸ (ๅฝผใฏ็พๅœจใ€ๅ‰ใฎใŠๅฎขใ•ใ‚“ใฎๅ•†ๅ“ใ‚’ๆบ–ๅ‚™ใ—ใฆใ„ใพใ™ใŒ)ใ€‚ + -ใƒฌใ‚ธไฟ‚๐Ÿ’ใฏใ‚ใชใŸใซ็•ชๅทๆœญใ‚’ๆธกใ—ใพใ™ใ€‚ +ใƒฌใ‚ธไฟ‚ใฏใ‚ญใƒƒใƒใƒณใฎๆ–™็†ไบบใซใ€ใ‚ใชใŸใฎใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’็”จๆ„ใ™ใ‚‹ใ‚ˆใ†ๅฃฐใ‚’ใ‹ใ‘ใพใ™ (ๆ–™็†ไบบใฏใ„ใพๅ‰ใฎใŠๅฎขใ•ใ‚“ใฎๅˆ†ใ‚’ไฝœใฃใฆใ„ใพใ™)ใ€‚ -ๅพ…ใฃใฆใ„ใ‚‹้–“ใ€ๅฅฝใใชไบบ๐Ÿ˜ใจไธ€็ท’ใซใƒ†ใƒผใƒ–ใƒซใ‚’้ธใ‚“ใงๅบงใ‚Šใ€ๅฅฝใใชไบบ๐Ÿ˜ใจ้•ทใ„้–“่ฉฑใ‚’ใ—ใพใ™ (ๆณจๆ–‡ใ—ใŸใƒใƒณใƒใƒผใ‚ฌใƒผใฏ้žๅธธใซ่ฑช่ฏใงใ€ๆบ–ๅ‚™ใซๅฐ‘ใ—ๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใฎใงโœจ๐Ÿ”โœจ)ใ€‚ + -ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๅพ…ใกใชใŒใ‚‰ๅฅฝใใชไบบ๐Ÿ˜ใจใƒ†ใƒผใƒ–ใƒซใซๅบงใฃใฆใ„ใ‚‹้–“ใ€ใ‚ใชใŸใฎๅฅฝใใชไบบใŒใชใ‚“ใฆ็ด ๆ™ดใ‚‰ใ—ใใ€ใ‹ใ‚ใ„ใใฆ้ ญใŒใ„ใ„ใ‚“ใ ใจโœจ๐Ÿ˜โœจๆƒšใ‚Œๆƒšใ‚Œใ—ใชใŒใ‚‰ๆ™‚้–“ใ‚’่ฒปใ‚„ใ™ใ“ใจใŒใงใใพใ™ใ€‚ +ๆ”ฏๆ‰•ใ„ใ‚’ใ—ใพใ™ใ€‚๐Ÿ’ธ -ๅฅฝใใชไบบ๐Ÿ˜ใจ่ฉฑใ—ใชใŒใ‚‰ๅพ…ใฃใฆใ„ใ‚‹้–“ใ€ใจใใฉใใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใซ่กจ็คบใ•ใ‚Œใฆใ„ใ‚‹็•ชๅทใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ€่‡ชๅˆ†ใฎ็•ชใ‹ใฉใ†ใ‹ใ‚’็ขบ่ชใ—ใพใ™ใ€‚ +ใƒฌใ‚ธไฟ‚ใฏใ‚ใชใŸใซ็•ชๅทๆœญใ‚’ๆธกใ—ใพใ™ใ€‚ -ใใฎๅพŒใ€ใคใ„ใซใ‚ใชใŸใฎ็•ชใซใชใ‚Šใพใ—ใŸใ€‚ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใซ่กŒใใ€ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๆ‰‹ใซๅ…ฅใ‚Œใฆใƒ†ใƒผใƒ–ใƒซใซๆˆปใ‚Šใพใ™ใ€‚ + -ใ‚ใชใŸใจใ‚ใชใŸใฎๅฅฝใใชไบบ๐Ÿ˜ใฏใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’้ฃŸในใฆใ€ๆฅฝใ—ใ„ๆ™‚้–“ใ‚’้Žใ”ใ—ใพใ™โœจใ€‚ +ๅพ…ใฃใฆใ„ใ‚‹้–“ใ€ๅฅฝใใชไบบใจใƒ†ใƒผใƒ–ใƒซใซ็งปๅ‹•ใ—ใฆๅบงใ‚Šใ€(่ฑช่ฏใชใƒใƒณใƒใƒผใ‚ฌใƒผใฏๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใฎใง) ใ—ใฐใ‚‰ใ่ฉฑใ—ใพใ™ใ€‚ + +ใƒ†ใƒผใƒ–ใƒซใงๅพ…ใฃใฆใ„ใ‚‹้–“ใ€ๅฅฝใใชไบบใŒใฉใ‚Œใ ใ‘็ด ๆ•ตใงใ€ใ‹ใ‚ใ„ใใฆใ€้ ญใŒ่‰ฏใ„ใ‹ใ‚’็œบใ‚ใฆๆ™‚้–“ใ‚’้Žใ”ใ›ใพใ™ โœจ๐Ÿ˜โœจใ€‚ + + + +ๆ™‚ใ€…ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎ่กจ็คบใ‚’่ฆ‹ใฆใ€่‡ชๅˆ†ใฎ็•ชๅทใซใชใฃใฆใ„ใ‚‹ใ‹็ขบ่ชใ—ใพใ™ใ€‚ + +ใ‚„ใŒใฆใ‚ใชใŸใฎ็•ชใซใชใ‚Šใพใ™ใ€‚ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใซ่กŒใใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒ†ใƒผใƒ–ใƒซใซๆˆปใ‚Šใพใ™ใ€‚ + + + +ใ‚ใชใŸใจๅฅฝใใชไบบใฏใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’้ฃŸในใฆใ€ๆฅฝใ—ใ„ๆ™‚้–“ใ‚’้Žใ”ใ—ใพใ™ใ€‚โœจ + + + +/// info | ๆƒ…ๅ ฑ + +็พŽใ—ใ„ใ‚คใƒฉใ‚นใƒˆใฏ Ketrina Thompson ใซใ‚ˆใ‚‹ใ‚‚ใฎใงใ™ใ€‚๐ŸŽจ + +/// --- -ไธŠ่จ˜ใฎใ‚นใƒˆใƒผใƒชใƒผใงใ€ใ‚ใชใŸใŒใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ๐Ÿค–ใ ใจๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ +ใ“ใฎ็‰ฉ่ชžใงใ€ใ‚ใชใŸ่‡ช่บซใŒใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ  ๐Ÿค– ใ ใจๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ -ๅˆ—ใซใ„ใ‚‹้–“ใ€ใ‚ใชใŸใฏใ‚ขใ‚คใƒ‰ใƒซ็Šถๆ…‹ใงใ™๐Ÿ˜ดใ€‚ไฝ•ใ‚‚ใ€Œ็”Ÿ็”ฃ็š„ใ€ใชใ“ใจใ‚’ใ›ใšใ€ใŸใ ่‡ชๅˆ†ใฎ็•ชใ‚’ๅพ…ใฃใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใƒฌใ‚ธไฟ‚๐Ÿ’ใฏๆณจๆ–‡ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ ใ‘ใชใฎใง (ๅ•†ๅ“ใฎๆบ–ๅ‚™ใ‚’ใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใชใ„)ใ€ๅˆ—ใฏ้ซ˜้€Ÿใงใ™ใ€‚ใ—ใŸใŒใฃใฆใ€ไฝ•ใ‚‚ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ๅˆ—ใซใ„ใ‚‹้–“ใฏใ€ไฝ•ใ‚‚ใ€Œ็”Ÿ็”ฃ็š„ใ€ใชใ“ใจใ‚’ใ›ใšใ€่‡ชๅˆ†ใฎ็•ชใ‚’ๅพ…ใคใ ใ‘ใฎใ‚ขใ‚คใƒ‰ใƒซ็Šถๆ…‹ ๐Ÿ˜ด ใงใ™ใ€‚ใŸใ ใ—ใƒฌใ‚ธไฟ‚ใฏๆณจๆ–‡ใ‚’ๅ–ใ‚‹ใ ใ‘ (ไฝœใ‚Šใฏใ—ใชใ„) ใชใฎใงๅˆ—ใฏ้€Ÿใ้€ฒใฟใ€ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใใ‚Œใ‹ใ‚‰ใ€ใ‚ใชใŸใฎ็•ชใซใชใฃใŸใ‚‰ใ€ๅฎŸใซใ€Œ็”Ÿ็”ฃ็š„ใชใ€ไฝœๆฅญใ‚’่กŒใ„ใพใ™๐Ÿค“ใ€ใƒกใƒ‹ใƒฅใƒผใ‚’็ขบ่ชใ—ใ€ๆฌฒใ—ใ„ใ‚‚ใฎใ‚’ๆฑบใ‚ใ€ๅฅฝใใชไบบ๐Ÿ˜ใฎๆฌฒใ—ใ„ใ‚‚ใฎใ‚’่žใใ€ๆ–™้‡‘ใ‚’ๆ”ฏๆ‰•ใ„๐Ÿ’ธใ€็พ้‡‘ใพใŸใฏใ‚ซใƒผใƒ‰ใ‚’ๆญฃใ—ใๆธกใ—ใŸใ‹็ขบ่ชใ—ใ€ๆญฃใ—ใๆธ…็ฎ—ใ•ใ‚ŒใŸใ“ใจใ‚’็ขบ่ชใ—ใ€ๆณจๆ–‡ใŒๆญฃใ—ใ้€šใฃใฆใ„ใ‚‹ใ‹ใชใฉใ‚’็ขบ่ชใ—ใพใ™ใ€‚ +ใ‚ใชใŸใฎ็•ชใซใชใ‚‹ใจใ€ๅฎŸ้š›ใซใ€Œ็”Ÿ็”ฃ็š„ใ€ใชไฝœๆฅญใ‚’ใ—ใพใ™ใ€‚ใƒกใƒ‹ใƒฅใƒผใ‚’่ฆ‹ใฆๆณจๆ–‡ใ‚’ๆฑบใ‚ใ€ๅฅฝใใชไบบใฎๅˆ†ใ‚‚็ขบ่ชใ—ใ€ๆ”ฏๆ‰•ใ„ใ€ๆญฃใ—ใ„็ด™ๅนฃ/ใ‚ซใƒผใƒ‰ใ‚’ๆธกใ—ใŸใ‹ใ€ๆญฃใ—ใๆฑบๆธˆใ•ใ‚ŒใŸใ‹ใ€ๆณจๆ–‡ๅ†…ๅฎนใŒๆญฃใ—ใ„ใ‹ใชใฉใ‚’็ขบ่ชใ—ใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ใพใ ใงใใฆใ„ใชใ„ใฎใงใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใฎๆบ–ๅ‚™ใŒใงใใ‚‹ใพใงๅพ…ๆฉŸ๐Ÿ•™ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚ใ€ใƒฌใ‚ธไฟ‚๐Ÿ’ใจใฎไฝœๆฅญใฏใ€Œไธ€ๆ™‚ๅœๆญขโธใ€ใซใชใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใฏใพใ ๅ‡บๆฅไธŠใŒใฃใฆใ„ใชใ„ใฎใงใ€ใƒฌใ‚ธไฟ‚ใจใฎใ‚„ใ‚Šๅ–ใ‚Šใฏใ€Œไธ€ๆ™‚ๅœๆญขใ€โธ ใซใชใ‚Šใพใ™ใ€‚ใƒใƒณใƒใƒผใ‚ฌใƒผใŒใงใใ‚‹ใพใงๅพ…ใค ๐Ÿ•™ ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใ‹ใ‚‰้›ขใ‚Œใฆใ€็•ชๅทๆœญใ‚’ๆŒใฃใฆใƒ†ใƒผใƒ–ใƒซใซๅบงใฃใฆใ„ใ‚‹ใจใใฏใ€ๆณจๆ„ใ‚’ๅฅฝใใชไบบ๐Ÿ˜ใซๅˆ‡ใ‚Šๆ›ฟใˆใฆ๐Ÿ”€ใ€ใใฎไธŠใงใ€Œไป•ไบ‹โฏ๐Ÿค“ใ€ใ‚’่กŒใชใˆใพใ™ใ€‚ใใฎๅพŒใ€ๅฅฝใใชไบบ๐Ÿ˜ใจใ„ใกใ‚ƒใคใใ‹ใฎใ‚ˆใ†ใชใ€้žๅธธใซใ€Œ็”Ÿ็”ฃ็š„ใช๐Ÿค“ใ€ใ“ใจใ‚’ๅ†ใณ่กŒใ„ใพใ™ใ€‚ +ใŸใ ใ—ใ€็•ชๅทๆœญใ‚’ๆŒใฃใฆใ‚ซใ‚ฆใƒณใ‚ฟใƒผใ‹ใ‚‰้›ขใ‚Œใƒ†ใƒผใƒ–ใƒซใซๅบงใ‚Œใฐใ€ๆณจๆ„ใ‚’ๅฅฝใใชไบบใซๅˆ‡ใ‚Šๆ›ฟใˆ ๐Ÿ”€ใ€ใ€Œใใฎไฝœๆฅญใ€โฏ ๐Ÿค“ ใซๅ–ใ‚Š็ต„ใ‚ใพใ™ใ€‚ๅฅฝใใชไบบใจใ„ใกใ‚ƒใคใใจใ„ใ†ใ€ใจใฆใ‚‚ใ€Œ็”Ÿ็”ฃ็š„ใ€๐Ÿค“ ใชใ“ใจใŒใพใŸใงใใพใ™ใ€‚ -ๆฌกใซใ€ใƒฌใ‚ธไฟ‚๐Ÿ’ใฏใ€ใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใฎๆบ–ๅ‚™ใŒใงใใพใ—ใŸ๐Ÿ”ใ€ใจ่จ€ใฃใฆใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎใƒ‡ใ‚ฃใ‚นใƒ—ใƒฌใ‚คใซ็•ชๅทใ‚’่กจ็คบใ—ใพใ™ใŒใ€่กจ็คบ็•ชๅทใŒใ‚ใชใŸใฎ็•ชๅทใซๅค‰ใ‚ใฃใฆใ‚‚ใ€ใ™ใใซ็‹‚ใฃใŸใ‚ˆใ†ใซ้ฃ›ใ‚“ใง่กŒใใ‚ˆใ†ใชใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ‚ใชใŸใฏ่‡ชๅˆ†ใฎ็•ชๅทๆœญใ‚’ๆŒใฃใฆใ„ใฃใฆใ€ไป–ใฎไบบใ‚‚่‡ชๅˆ†ใฎ็•ชๅทๆœญใŒใ‚ใ‚‹ใฎใงใ€ใ‚ใชใŸใฎใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’็›—ใ‚€ไบบใŒใ„ใชใ„ใ“ใจใฏ็Ÿฅใฃใฆใ„ใพใ™ใ€‚ +ใƒฌใ‚ธไฟ‚ ๐Ÿ’ ใŒใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎ่กจ็คบใซใ‚ใชใŸใฎ็•ชๅทใ‚’ๅ‡บใ—ใฆใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใŒใงใใพใ—ใŸใ€ใจ็Ÿฅใ‚‰ใ›ใฆใ‚‚ใ€ใ‚ใชใŸใฏ่กจ็คบใŒๅˆ‡ใ‚Šๆ›ฟใ‚ใฃใŸ็žฌ้–“ใซ้ฃ›ใณ่ทณใญใŸใ‚Šใ—ใพใ›ใ‚“ใ€‚่‡ชๅˆ†ใฎ็•ชๅทๆœญใŒใ‚ใ‚Šใ€ไป–ใฎไบบใซใ‚‚ใใ‚Œใžใ‚Œ็•ชๅทๆœญใŒใ‚ใ‚‹ใฎใงใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’็›—ใ‚‰ใ‚Œใ‚‹ใ“ใจใฏใชใ„ใจ็Ÿฅใฃใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ -ใชใฎใงใ€ใ‚ใชใŸใฏๅฅฝใใชไบบ๐Ÿ˜ใŒ่ฉฑใ—็ต‚ใˆใ‚‹ใฎใ‚’ๅพ…ใฃใฆ (็พๅœจใฎไป•ไบ‹โฏ / ๅ‡ฆ็†ไธญใฎใ‚ฟใ‚นใ‚ฏใ‚’็ต‚ไบ†ใ—ใพใ™๐Ÿค“)ใ€ๅ„ชใ—ใๅพฎ็ฌ‘ใ‚“ใงใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’่ฒฐใฃใฆใใ‚‹ใญใจ่จ€ใ„ใพใ™โธใ€‚ +ใ ใ‹ใ‚‰ใ€ๅฅฝใใชไบบใฎ่ฉฑใŒ็ต‚ใ‚ใ‚‹ใฎใ‚’ๅพ…ใก (็พๅœจใฎไฝœๆฅญ โฏ / ๅ‡ฆ็†ไธญใฎใ‚ฟใ‚นใ‚ฏใ‚’ๅฎŒไบ†ใ— ๐Ÿค“)ใ€ๅพฎ็ฌ‘ใ‚“ใงใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผๅ–ใฃใฆใใ‚‹ใญใ€ใจ่จ€ใ„ใพใ™ โธใ€‚ -ๆฌกใซใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใธใ€ใ„ใพใ‹ใ‚‰ๅฎŒไบ†ใ™ใ‚‹ๆœ€ๅˆใฎใ‚ฟใ‚นใ‚ฏโฏใธๅ‘ใ‹ใ„ใ€ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ๆ„Ÿ่ฌใฎๆ„ใ‚’่กจใ—ใฆใ€ใƒ†ใƒผใƒ–ใƒซใซๆŒใฃใฆใ„ใใพใ™ใ€‚ใ“ใ‚Œใงใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใจใฎใ‚„ใ‚Šๅ–ใ‚Šใฎใ‚นใƒ†ใƒƒใƒ—/ใ‚ฟใ‚นใ‚ฏใŒๅฎŒไบ†ใ—ใพใ—ใŸโนใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’้ฃŸในใ‚‹๐Ÿ”€โฏใ€ใจใ„ใ†ๆ–ฐใ—ใ„ใ‚ฟใ‚นใ‚ฏใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ใ—ใ‹ใ—ใ€ๅ‰ใฎใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๅ–ๅพ—ใ™ใ‚‹ใ€ใจใ„ใ†ใ‚ฟใ‚นใ‚ฏใฏ็ต‚ไบ†ใ—ใพใ—ใŸโนใ€‚ +ใใ‚Œใ‹ใ‚‰ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใธ่กŒใ ๐Ÿ”€ใ€ใ„ใพๅฎŒไบ†ใ—ใŸๅˆๆœŸใฎใ‚ฟใ‚นใ‚ฏ โฏ ใซๆˆปใฃใฆใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€็คผใ‚’่จ€ใฃใฆใƒ†ใƒผใƒ–ใƒซใซๆŒใฃใฆใ„ใใพใ™ใ€‚ใ“ใ‚Œใงใ‚ซใ‚ฆใƒณใ‚ฟใƒผใจใฎใ‚„ใ‚Šๅ–ใ‚Šใจใ„ใ†ใ‚นใƒ†ใƒƒใƒ—/ใ‚ฟใ‚นใ‚ฏใฏๅฎŒไบ† โน ใงใ™ใ€‚ใใฎ็ตๆžœใจใ—ใฆใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’้ฃŸในใ‚‹ใ€๐Ÿ”€ โฏ ใจใ„ใ†ๆ–ฐใ—ใ„ใ‚ฟใ‚นใ‚ฏใŒ็”Ÿใพใ‚Œใพใ™ใŒใ€ๅ…ˆใฎใ€Œใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ€ใ‚ฟใ‚นใ‚ฏใฏๅฎŒไบ† โน ใ—ใฆใ„ใพใ™ใ€‚ -### ไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผ +### ไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผ { #parallel-burgers } -ใ“ใ‚Œใ‚‰ใŒใ€Œไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใงใฏใชใใ€ใ€Œไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใงใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†ใ€‚ +ไปŠๅบฆใฏใ€ใ“ใ‚ŒใŒใ€Œไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใงใฏใชใใ€Œไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใ ใจๆƒณๅƒใ—ใพใ—ใ‚‡ใ†ใ€‚ -ใ‚ใชใŸใฏๅฅฝใใชไบบ๐Ÿ˜ใจไธฆๅˆ—ใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰๐Ÿ”ใ‚’่ฒทใŠใ†ใจใ—ใฆใ„ใพใ™ใ€‚ +ใ‚ใชใŸใฏๅฅฝใใชไบบใจใ€Œไธฆๅˆ—ใ€ใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ใ‚’่ฒทใ„ใซ่กŒใใพใ™ใ€‚ -ๅˆ—ใซไธฆใ‚“ใงใ„ใพใ™ใŒใ€ไฝ•ไบบใ‹ใฎๆ–™็†ไบบๅ…ผใ€ใƒฌใ‚ธไฟ‚ (8ไบบใจใ—ใพใ—ใ‚‡ใ†) ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐ŸณใŒใ‚ใชใŸใฎๅ‰ใซใ„ใ‚‹ไบบ้”ใฎๆณจๆ–‡ใ‚’ๅ—ใ‘ใคใ‘ใฆใ„ใพใ™ใ€‚ +่ค‡ๆ•ฐใฎใƒฌใ‚ธไฟ‚ (ไพ‹ใˆใฐ 8 ไบบ) ใŒๅŒๆ™‚ใซๆ–™็†ไบบใงใ‚‚ใ‚ใ‚Šใ€ๅ‰ใฎไบบใŸใกใฎๆณจๆ–‡ใ‚’ๅ—ใ‘ใฆใ„ใพใ™ใ€‚ -8ไบบใฎใƒฌใ‚ธไฟ‚ใŒใใ‚Œใžใ‚Œ่‡ชๅˆ†ใงๆณจๆ–‡ใ‚’ๅ—ใ‘ใ‚‹ใ‚„ๅฆใ‚„ใ€ๆฌกใฎๆณจๆ–‡ใ‚’ๅ—ใ‘ใ‚‹ๅ‰ใซใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๆบ–ๅ‚™ใ™ใ‚‹ใฎใงใ€ใ‚ใชใŸใฎๅ‰ใฎไบบ้”ใฏใ‚ซใ‚ฆใƒณใ‚ฟใƒผใ‚’้›ขใ‚Œใšใซใ€ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใŒใงใใ‚‹ใฎใ‚’ๅพ…ใฃใฆใ„ใพใ™๐Ÿ•™ใ€‚ +8 ไบบใฎใƒฌใ‚ธไฟ‚ใฏใใ‚Œใžใ‚Œใ€ๆฌกใฎๆณจๆ–‡ใ‚’ๅ–ใ‚‹ๅ‰ใซใ™ใใซ่ชฟ็†ใซๅ–ใ‚Šใ‹ใ‹ใ‚‹ใŸใ‚ใ€ใ‚ใชใŸใฎๅ‰ใฎไบบใŸใกใฏใ‚ซใ‚ฆใƒณใ‚ฟใƒผใ‚’้›ขใ‚Œใšใ€ใƒใƒณใƒใƒผใ‚ฌใƒผใŒใงใใ‚‹ใฎใ‚’ๅพ…ใฃใฆใ„ใพใ™ใ€‚ -ใใ‚Œใ‹ใ‚‰ใ„ใ‚ˆใ„ใ‚ˆใ‚ใชใŸใฎ็•ชใซใชใ‚Šใ€ๅฅฝใใชไบบ๐Ÿ˜ใจ่‡ชๅˆ†ใฎใŸใ‚ใซใ€2ใคใฎ้žๅธธใซ่ฑช่ฏใชใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๆณจๆ–‡ใ—ใพใ™ใ€‚ + -ๆ–™้‡‘ใ‚’ๆ”ฏๆ‰•ใ„ใพใ™๐Ÿ’ธใ€‚ +ใ‚ˆใ†ใ‚„ใใ‚ใชใŸใฎ็•ชใซใชใ‚Šใ€ๅฅฝใใชไบบใจ่‡ชๅˆ†ใฎใŸใ‚ใซ่ฑช่ฏใชใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ 2 ใคๆณจๆ–‡ใ—ใพใ™ใ€‚ -ใƒฌใ‚ธไฟ‚ใฏใ‚ญใƒƒใƒใƒณใซ่กŒใใพใ™๐Ÿ‘จโ€๐Ÿณใ€‚ +ๆ”ฏๆ‰•ใ„ใ‚’ใ—ใพใ™ ๐Ÿ’ธใ€‚ -ใ‚ใชใŸใฏใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎๅ‰ใซ็ซ‹ใฃใฆๅพ…ใกใพใ™๐Ÿ•™ใ€‚็•ชๅทๆœญใŒใชใ„ใฎใง่ชฐใ‚‚ใ‚ใชใŸใ‚ˆใ‚Šใ‚‚ๅ…ˆใซใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๅ–ใ‚‰ใชใ„ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ + -ใ‚ใชใŸใจๅฅฝใใชไบบ๐Ÿ˜ใฏๅฟ™ใ—ใ„ใฎใงใ€่ชฐใ‚‚ใ‚ใชใŸใฎๅ‰ใซๆฅใ•ใ›ใพใ›ใ‚“ใ—ใ€ใ‚ใชใŸใฎใƒใƒณใƒใƒผใ‚ฌใƒผใŒๅˆฐ็€ใ—ใŸใจใ๐Ÿ•™ใซ่ชฐใซใ‚‚ๅ–ใ‚‹ใ“ใจใ‚’่จฑใ—ใพใ›ใ‚“ใ€‚ใ‚ใชใŸใฏๅฅฝใใชไบบใซๆณจๆ„ใ‚’ๆ‰•ใˆใพใ›ใ‚“๐Ÿ˜žใ€‚ +ใƒฌใ‚ธไฟ‚ใฏใ‚ญใƒƒใƒใƒณใซๅ‘ใ‹ใ„ใพใ™ใ€‚ -ใ“ใ‚Œใฏใ€ŒๅŒๆœŸใ€ไฝœๆฅญใงใ‚ใ‚Šใ€ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ๐Ÿ‘จโ€๐Ÿณใจใ€ŒๅŒๆœŸใ€ใ—ใพใ™ใ€‚ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ๐Ÿ‘จโ€๐ŸณใŒใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๅฎŒๆˆใ•ใ›ใฆใ‚ใชใŸใซๆธกใ™ใพใงๅพ…ใค๐Ÿ•™ๅฟ…่ฆใŒใ‚ใ‚Šใ€ใกใ‚‡ใ†ใฉใใฎๅฎŒๆˆใฎ็žฌ้–“ใซใใ“ใซใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใ†ใงใชใ‘ใ‚Œใฐใ€ไป–ใฎ่ชฐใ‹ใซๅ–ใ‚‰ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +็•ชๅทๆœญใŒใชใ„ใŸใ‚ใ€ไป–ใฎ่ชฐใ‹ใซๅ…ˆใซๅ–ใ‚‰ใ‚Œใชใ„ใ‚ˆใ†ใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎๅ‰ใง็ซ‹ใฃใฆๅพ…ใกใพใ™ ๐Ÿ•™ใ€‚ -ใใฎๅพŒใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎๅ‰ใง้•ทใ„ๆ™‚้–“ๅพ…ใฃใฆใ‹ใ‚‰๐Ÿ•™ใ€ใคใ„ใซใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ๐Ÿ‘จโ€๐ŸณใŒใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๆธกใ—ใซๆˆปใฃใฆใใพใ™ใ€‚ + -ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใ‚’ๅ–ใ‚Šใ€ๅฅฝใใชไบบ๐Ÿ˜ใจใƒ†ใƒผใƒ–ใƒซใซ่กŒใใพใ™ใ€‚ +ใ‚ใชใŸใจๅฅฝใใชไบบใฏใ€่ชฐใซใ‚‚ๅ‰ฒใ‚Š่พผใพใ‚Œใšใƒใƒณใƒใƒผใ‚ฌใƒผใŒๆฅใŸใ‚‰ใ™ใๅ—ใ‘ๅ–ใ‚Œใ‚‹ใ‚ˆใ†่ฆ‹ๅผตใฃใฆใ„ใ‚‹ใฎใงใ€ๅฅฝใใชไบบใซๆณจๆ„ใ‚’ๅ‘ใ‘ใ‚‰ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿ˜ž -ใŸใ ้ฃŸในใ‚‹ใ ใ‘ใ€ใใ‚ŒใงใŠใ—ใพใ„ใงใ™ใ€‚๐Ÿ”โนใ€‚ +ใ“ใ‚Œใฏใ€ŒๅŒๆœŸใ€็š„ใชไฝœๆฅญใงใ™ใ€‚ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ ๐Ÿ‘จโ€๐Ÿณ ใจใ€ŒๅŒๆœŸใ€ใ—ใฆใ„ใพใ™ใ€‚ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ ๐Ÿ‘จโ€๐Ÿณ ใŒใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ไฝœใ‚Š็ต‚ใˆใฆๆ‰‹ๆธกใ™ใใฎ็žฌ้–“ใซใ€ๅพ…ใฃใฆ ๐Ÿ•™ ใใฎๅ ดใซใ„ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใใ†ใงใชใ„ใจไป–ใฎ่ชฐใ‹ใซๅ–ใ‚‰ใ‚Œใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ -ใปใจใ‚“ใฉใฎๆ™‚้–“ใ€ใ‚ซใ‚ฆใƒณใ‚ฟใƒผใฎๅ‰ใงๅพ…ใคใฎใซ่ฒปใ‚„ใ•ใ‚Œใฆใ„ใŸใฎใง๐Ÿ•™ใ€ใ‚ใพใ‚Š่ฉฑใ—ใŸใ‚Šใ„ใกใ‚ƒใคใใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸ๐Ÿ˜žใ€‚ + ---- +้•ทใ„ๆ™‚้–“ ๐Ÿ•™ ใ‚ซใ‚ฆใƒณใ‚ฟใƒผๅ‰ใงๅพ…ใฃใŸๅพŒใ€ใ‚ˆใ†ใ‚„ใใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ ๐Ÿ‘จโ€๐Ÿณ ใŒใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๆŒใฃใฆๆˆปใฃใฆใใพใ™ใ€‚ + + + +ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ๅฅฝใใชไบบใจใƒ†ใƒผใƒ–ใƒซใซ่กŒใใพใ™ใ€‚ + +้ฃŸในใฆใ€ใŠใ—ใพใ„ใงใ™ใ€‚โน -ใ“ใฎไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ใ‚ใชใŸใฏ2ใคใฎใƒ—ใƒญใ‚ปใƒƒใ‚ตใ‚’ๅ‚™ใˆใŸใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ ๐Ÿค– (ใ‚ใชใŸใจใ‚ใชใŸใฎๅฅฝใใชไบบ๐Ÿ˜) ใงใ‚ใ‚Šใ€ไธกๆ–นใจใ‚‚ๅพ…ๆฉŸ๐Ÿ•™ใ—ใฆใ„ใฆใ€ๅฝผใ‚‰ใฏใ€Œใ‚ซใ‚ฆใƒณใ‚ฟใƒผใงๅพ…ๆฉŸ๐Ÿ•™ใ€ใ™ใ‚‹ใ“ใจใซๅฐ‚ๅฟตใ—ใฆใ„ใพใ™โฏใ€‚ + -ใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ๅบ—ใซใฏ8ใคใฎใƒ—ใƒญใ‚ปใƒƒใ‚ต (ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ) ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐ŸณใŒใ‚ใ‚Šใพใ™ใ€‚ไธ€ๆ–นใ€ไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผๅบ—ใซใฏ2ไบบ (ใƒฌใ‚ธไฟ‚ใจๆ–™็†ไบบ) ๐Ÿ’๐Ÿ‘จโ€๐Ÿณใ—ใ‹ใ„ใชใ‹ใฃใŸใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใปใจใ‚“ใฉใฎๆ™‚้–“ใ‚’ใ‚ซใ‚ฆใƒณใ‚ฟใƒผๅ‰ใงๅพ…ใค ๐Ÿ•™ ใฎใซ่ฒปใ‚„ใ—ใŸใŸใ‚ใ€ใ‚ใพใ‚Š่ฉฑใ—ใŸใ‚Šใ€ใ„ใกใ‚ƒใคใ„ใŸใ‚Šใงใใพใ›ใ‚“ใงใ—ใŸใ€‚๐Ÿ˜ž -ใ—ใ‹ใ—ใ€ใใ‚Œใงใ‚‚ใ€ๆœ€็ต‚็š„ใชไฝ“้จ“ใฏๆœ€้ซ˜ใงใฏใ‚ใ‚Šใพใ›ใ‚“๐Ÿ˜žใ€‚ +/// info | ๆƒ…ๅ ฑ + +็พŽใ—ใ„ใ‚คใƒฉใ‚นใƒˆใฏ Ketrina Thompson ใซใ‚ˆใ‚‹ใ‚‚ใฎใงใ™ใ€‚๐ŸŽจ + +/// --- -ใ“ใ‚Œใฏใ€ใƒใƒณใƒใƒผใ‚ฌใƒผ๐Ÿ”ใฎ่ฉฑใจๅŒ็ญ‰ใช่ฉฑใซใชใ‚Šใพใ™ใ€‚ +ใ“ใฎใ€Œไธฆๅˆ—ใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ใ‚ใชใŸใฏ 2 ใคใฎใƒ—ใƒญใ‚ปใƒƒใ‚ต (ใ‚ใชใŸใจๅฅฝใใชไบบ) ใ‚’ๆŒใคใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ/ใƒ—ใƒญใ‚ฐใƒฉใƒ  ๐Ÿค– ใงใ€ใฉใกใ‚‰ใ‚‚้•ทใ„้–“ ๐Ÿ•™ใ€Œใ‚ซใ‚ฆใƒณใ‚ฟใƒผใงใฎๅพ…ๆฉŸใ€ใซๆณจๆ„ โฏ ใ‚’ๅฐ‚ๅฟตใ—ใฆใ„ใพใ™ใ€‚ -ใ‚ˆใ‚Šใ€Œ็พๅฎŸ็š„ใชใ€ไพ‹ใจใ—ใฆใ€้Š€่กŒใ‚’ๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ +ใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ๅบ—ใซใฏ 8 ๅ€‹ใฎใƒ—ใƒญใ‚ปใƒƒใ‚ต (ใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ) ใŒใ‚ใ‚Šใพใ™ใ€‚ไธ€ๆ–นใ€ไธฆ่กŒใƒใƒณใƒใƒผใ‚ฌใƒผใฎๅบ—ใซใฏ (ใƒฌใ‚ธไฟ‚ 1ใ€ไบบใ€ๆ–™็†ไบบ 1 ไบบใฎ) 2 ๅ€‹ใ—ใ‹ใชใ‹ใฃใŸใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใใ‚Œใงใ‚‚ใ€ๆœ€็ต‚็š„ใชไฝ“้จ“ใฏๆœ€่‰ฏใจใฏ่จ€ใˆใพใ›ใ‚“ใ€‚๐Ÿ˜ž + +--- -ๆœ€่ฟ‘ใพใงใ€ใปใจใ‚“ใฉใฎ้Š€่กŒใฏ่ค‡ๆ•ฐใฎ็ช“ๅฃ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผใซใ€่กŒๅˆ—๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™ใŒใงใใฆใ„ใพใ—ใŸใ€‚ +ใ“ใ‚Œใฏใƒใƒณใƒใƒผใ‚ฌใƒผใซใŠใ‘ใ‚‹ไธฆๅˆ—็‰ˆใฎ็‰ฉ่ชžใงใ™ใ€‚๐Ÿ” -ใ™ในใฆใฎ็ช“ๅฃใงใ€ๆฌกใ€…ใจใ€ไธ€ไบบใฎๅฎขใจใ™ในใฆใฎไฝœๆฅญใ‚’่กŒใ„ใพใ™๐Ÿ‘จโ€๐Ÿ’ผโฏ. +ใ‚ˆใ‚Šใ€Œ็พๅฎŸ็š„ใชใ€ไพ‹ใจใ—ใฆใ€้Š€่กŒใ‚’ๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ -ใใฎไธŠใ€้•ทๆ™‚้–“ใ€ๅˆ—ใซไธฆใฐใชใ‘ใ‚Œใฐใ„ใ‘ใพใ›ใ‚“๐Ÿ•™ใ€‚ใใ†ใ—ใชใ„ใจใ€้ †็•ชใŒๅ›žใฃใฆใใพใ›ใ‚“ใ€‚ +ใคใ„ๆœ€่ฟ‘ใพใงใ€ใปใจใ‚“ใฉใฎ้Š€่กŒใซใฏ่ค‡ๆ•ฐใฎ็ช“ๅฃไฟ‚ ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ใจ้•ทใ„่กŒๅˆ— ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™ ใŒใ‚ใ‚Šใพใ—ใŸใ€‚ -้Š€่กŒ๐Ÿฆใงใฎ็”จไบ‹ใซใ‚ใชใŸใฎๅฅฝใใชไบบ๐Ÿ˜ใ‚’้€ฃใ‚Œใฆ่กŒใใŸใใฏใชใ„ใงใ—ใ‚‡ใ†ใ€‚ +ๅ„็ช“ๅฃไฟ‚ใŒใ€ไธ€ไบบใšใคใ€ใ™ในใฆใฎไฝœๆฅญใ‚’้ †็•ชใซ่กŒใ„ใพใ™ ๐Ÿ‘จโ€๐Ÿ’ผโฏใ€‚ -### ใƒใƒณใƒใƒผใ‚ฌใƒผใฎใพใจใ‚ +ใใ—ใฆใ€้•ทๆ™‚้–“ ๐Ÿ•™ ่กŒๅˆ—ใงๅพ…ใŸใชใ‘ใ‚Œใฐ้ †็•ชใ‚’ๅคฑใ„ใพใ™ใ€‚ -ใ“ใฎใ€Œๅฅฝใใชไบบใจใฎใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ใƒใƒณใƒใƒผใ‚ฌใƒผใ€ใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ๅพ…ๆฉŸ๐Ÿ•™ใŒๅคšใ„ใŸใ‚ใ€ไธฆ่กŒใ‚ทใ‚นใƒ†ใƒ โธ๐Ÿ”€โฏใ‚’ไฝฟ็”จใ™ใ‚‹ๆ–นใŒใฏใ‚‹ใ‹ใซ็†ใซใ‹ใชใฃใฆใ„ใพใ™ใ€‚ +้Š€่กŒใฎ็”จไบ‹ ๐Ÿฆ ใซใ€ๅฅฝใใชไบบ ๐Ÿ˜ ใ‚’้€ฃใ‚Œใฆ่กŒใใŸใ„ใจใฏๆ€ใ‚ใชใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใ“ใ‚Œใฏใ€ใปใจใ‚“ใฉใฎWebใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅฝ“ใฆใฏใพใ‚Šใพใ™ใ€‚ +### ใƒใƒณใƒใƒผใ‚ฌใƒผใฎใพใจใ‚ { #burger-conclusion } -ๅคšใใฎใƒฆใƒผใ‚ถใƒผใŒใ„ใพใ™ใŒใ€ใ‚ตใƒผใƒใƒผใฏใ€ใ‚ใพใ‚Šๅผทใใชใ„ๅ›ž็ทšใงใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ้€ไฟกใ‚’ๅพ…ๆฉŸ๐Ÿ•™ใ—ใฆใ„ใพใ™ใ€‚ +ใ“ใฎใ€Œๅฅฝใใชไบบใจใƒ•ใ‚กใ‚นใƒˆใƒ•ใƒผใƒ‰ใ€ใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ๅพ…ใกๆ™‚้–“ ๐Ÿ•™ ใŒๅคšใ„ใŸใ‚ใ€ไธฆ่กŒใ‚ทใ‚นใƒ†ใƒ  โธ๐Ÿ”€โฏ ใ‚’ไฝฟใ†ๆ–นใŒใฏใ‚‹ใ‹ใซ็†ใซใ‹ใชใฃใฆใ„ใพใ™ใ€‚ -ใใ—ใฆใ€ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใฃใฆใใ‚‹ใฎใ‚’ใ‚‚ใ†ไธ€ๅบฆๅพ…ๆฉŸ๐Ÿ•™ใ—ใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€ใปใจใ‚“ใฉใฎ Web ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซใ‚‚ๅฝ“ใฆใฏใพใ‚Šใพใ™ใ€‚ -ใ“ใฎใ€Œๅพ…ๆฉŸ๐Ÿ•™ใ€ใฏใƒžใ‚คใ‚ฏใƒญ็ง’ๅ˜ไฝใงใ™ใŒใ€ใใ‚Œใงใ‚‚ใ€ใ™ในใฆๅˆ็ฎ—ใ™ใ‚‹ใจใ€ๆœ€็ต‚็š„ใซใฏใ‹ใชใ‚Šๅพ…ๆฉŸใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ใจใฆใ‚‚ๅคšใใฎใƒฆใƒผใ‚ถใƒผใŒใ„ใพใ™ใŒใ€ใ‚ตใƒผใƒใฏๅฝผใ‚‰ใฎใ‚ใพใ‚Š้€Ÿใใชใ„ๅ›ž็ทšใ‹ใ‚‰ใƒชใ‚ฏใ‚จใ‚นใƒˆใŒๅฑŠใใฎใ‚’ๅพ…ใก ๐Ÿ•™ใ€ -ใ“ใ‚ŒใŒใ€Web APIใธใฎ้žๅŒๆœŸโธ๐Ÿ”€โฏใ‚ณใƒผใƒ‰ใฎๅˆฉ็”จใŒ็†ใซใ‹ใชใฃใฆใ„ใ‚‹็†็”ฑใงใ™ใ€‚ +ใใฎๅพŒใ€ใƒฌใ‚นใƒใƒณใ‚นใŒๆˆปใฃใฆใใ‚‹ใฎใ‚’ใพใŸๅพ…ใกใพใ™ ๐Ÿ•™ใ€‚ -ใปใจใ‚“ใฉใฎๆ—ขๅญ˜ใฎไบบๆฐ—ใฎใ‚ใ‚‹Pythonใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ (Flaskใ‚„Djangoใ‚’ๅซใ‚€) ใฏใ€Pythonใฎๆ–ฐใ—ใ„้žๅŒๆœŸๆฉŸ่ƒฝใŒใงใใ‚‹ๅ‰ใซไฝœๆˆใ•ใ‚Œใพใ—ใŸใ€‚ใ—ใŸใŒใฃใฆใ€ใใ‚Œใ‚‰ใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๆ–นๆณ•ใฏใ€ไธฆๅˆ—ๅฎŸ่กŒใจใ€ๆ–ฐๆฉŸ่ƒฝใปใฉๅผทๅŠ›ใงใฏใชใ„ๅคใ„ๅฝขๅผใฎ้žๅŒๆœŸๅฎŸ่กŒใ‚’ใ‚ตใƒใƒผใƒˆใ—ใพใ™ใ€‚ +ใ“ใฎใ€Œๅพ…ใกใ€๐Ÿ•™ ใฏใƒžใ‚คใ‚ฏใƒญ็ง’ๅ˜ไฝใงๆธฌใ‚‰ใ‚Œใพใ™ใŒใ€ใ™ในใฆใ‚’ๅˆ่จˆใ™ใ‚‹ใจใ€็ตๅฑ€ใ‹ใชใ‚Šใฎๅพ…ใกใซใชใ‚Šใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€WebSocketใฎใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ ใ™ใ‚‹ใŸใ‚ใซใ€้žๅŒๆœŸWeb Python (ASGI) ใฎไธปใชไป•ๆง˜ใฏDjangoใง้–‹็™บใ•ใ‚Œใพใ—ใŸใ€‚ +ใ ใ‹ใ‚‰ใ“ใใ€Web API ใซใฏ้žๅŒๆœŸ โธ๐Ÿ”€โฏ ใ‚ณใƒผใƒ‰ใ‚’ไฝฟใ†ใฎใŒ็†ใซใ‹ใชใฃใฆใ„ใพใ™ใ€‚ -ใใฎใ‚ˆใ†ใช้žๅŒๆœŸๆ€งใŒNodeJSใ‚’ไบบๆฐ—ใซใ—ใŸ็†็”ฑใงใ™ (NodeJSใฏไธฆๅˆ—ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒ)ใ€‚ใใ—ใฆใ€ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐ่จ€่ชžใจใ—ใฆใฎGoใฎๅผทใฟใงใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ใ“ใ‚ŒใŒใ€NodeJS ใ‚’ไบบๆฐ—ใซใ—ใŸ่ฆๅ›  (NodeJS ่‡ชไฝ“ใฏไธฆๅˆ—ใงใฏใ‚ใ‚Šใพใ›ใ‚“) ใงใ‚ใ‚Šใ€ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐ่จ€่ชžใจใ—ใฆใฎ Go ใฎๅผทใฟใงใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -ใใ—ใฆใ€ใใ‚Œใฏ**FastAPI**ใงๅพ—ใ‚‰ใ‚Œใ‚‹ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใจๅŒใ˜ใƒฌใƒ™ใƒซใงใ™ใ€‚ +ใใ—ใฆใ€ใใ‚ŒใŒ **FastAPI** ใงๅพ—ใ‚‰ใ‚Œใ‚‹ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใฎๆฐดๆบ–ใงใ™ใ€‚ -ใพใŸใ€ไธฆๅˆ—ๅ‡ฆ็†ใจ้žๅŒๆœŸๅ‡ฆ็†ใ‚’ๅŒๆ™‚ใซๅฎŸ่กŒใงใใ‚‹ใŸใ‚ใ€ใƒ†ใ‚นใƒˆๆธˆใฟใฎใปใจใ‚“ใฉใฎNodeJSใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚ˆใ‚Šใ‚‚้ซ˜ใใ€GoใจๅŒ็ญ‰ใฎใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚Goใฏใ€Cใซ่ฟ‘ใ„ใ‚ณใƒณใƒ‘ใ‚คใƒซ่จ€่ชžใงใ™ (Starletteใซๆ„Ÿ่ฌใ—ใพใ™)ใ€‚ +ใ•ใ‚‰ใซใ€ไธฆๅˆ—ๆ€งใจ้žๅŒๆœŸๆ€งใ‚’ๅŒๆ™‚ใซๆดป็”จใงใใ‚‹ใŸใ‚ใ€ใƒ†ใ‚นใƒˆใ•ใ‚ŒใŸๅคšใใฎ NodeJS ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚ˆใ‚Š้ซ˜ใ„ๆ€ง่ƒฝใ‚’็™บๆฎใ—ใ€C ใซ่ฟ‘ใ„ใ‚ณใƒณใƒ‘ใ‚คใƒซ่จ€่ชžใงใ‚ใ‚‹ Go ใจๅŒ็ญ‰ใฎๆ€ง่ƒฝใซใชใ‚Šใพใ™ (ใ™ในใฆ Starlette ใฎใŠใ‹ใ’ใงใ™)ใ€‚ -### ไธฆ่กŒใฏไธฆๅˆ—ใ‚ˆใ‚Šใ‚‚ๅ„ชใ‚Œใฆใ„ใพใ™ใ‹๏ผŸ +### ไธฆ่กŒๅ‡ฆ็†ใฏไธฆๅˆ—ๅ‡ฆ็†ใ‚ˆใ‚Šๅ„ชใ‚Œใฆใ„ใ‚‹๏ผŸ { #is-concurrency-better-than-parallelism } -ใ„ใ‚„๏ผใใ‚Œใฏใ“ใฎ่ฉฑใฎๆ•™่จ“ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใ„ใ„ใˆ๏ผใใ‚ŒใŒใ“ใฎ่ฉฑใฎๆ•™่จ“ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ไธฆ่กŒๅ‡ฆ็†ใฏไธฆๅˆ—ๅ‡ฆ็†ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ๅคšใใฎๅพ…ๆฉŸใ‚’ไผดใ†**็‰นๅฎšใฎ**ใ‚ทใƒŠใƒชใ‚ชใซ้ฉใ—ใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ไธ€่ˆฌใซใ€Webใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ้–‹็™บใงใฏไธฆๅˆ—ๅ‡ฆ็†ใ‚ˆใ‚Šใ‚‚ใฏใ‚‹ใ‹ใซๅ„ชใ‚Œใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใ™ในใฆใซๅฏพใ—ใฆใ‚ˆใ‚Š่‰ฏใ„ใจใ„ใ†ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ไธฆ่กŒๅ‡ฆ็†ใฏไธฆๅˆ—ๅ‡ฆ็†ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ใใ—ใฆๅคšใใฎๅพ…ใกๆ™‚้–“ใ‚’ไผดใ†**็‰นๅฎšใฎ**ใ‚ทใƒŠใƒชใ‚ชใงใฏๅ„ชใ‚Œใฆใ„ใพใ™ใ€‚ใใฎใŸใ‚ใ€ไธ€่ˆฌใซ Web ใ‚ขใƒ—ใƒช้–‹็™บใงใฏไธฆๅˆ—ๅ‡ฆ็†ใ‚ˆใ‚Šใฏใ‚‹ใ‹ใซ้ฉใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใ™ในใฆใซๅฏพใ—ใฆๆœ€่‰ฏใจใ„ใ†ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใชใฎใงใ€ใƒใƒฉใƒณใ‚นใ‚’ใจใ‚‹ใŸใ‚ใซใ€ๆฌกใฎ็‰ฉ่ชžใ‚’ๆƒณๅƒใ—ใฆไธ‹ใ•ใ„: +ใƒใƒฉใƒณใ‚นใ‚’ๅ–ใ‚‹ใŸใ‚ใซใ€ๆฌกใฎ็Ÿญใ„็‰ฉ่ชžใ‚’ๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚ -> ใ‚ใชใŸใฏๅคงใใใฆๆฑšใ‚ŒใŸๅฎถใ‚’ๆŽƒ้™คใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +> ๅคงใใใฆๆฑšใ‚ŒใŸๅฎถใ‚’ๆŽƒ้™คใ—ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใ€‚ -*ใฏใ„ใ€ไปฅไธŠใงใ™*ใ€‚ +*ใฏใ„ใ€ใ“ใ‚Œใง็‰ฉ่ชžใฏๅ…จ้ƒจใงใ™*ใ€‚ --- -ๅพ…ๆฉŸ๐Ÿ•™ใ›ใšใ€ๅฎถใฎไธญใฎ่ค‡ๆ•ฐใฎๅ ดๆ‰€ใงใŸใใ•ใ‚“ใฎไป•ไบ‹ใ‚’ใ™ใ‚‹ใ ใ‘ใงใ™ใ€‚ +ใฉใ“ใซใ‚‚ๅพ…ใก ๐Ÿ•™ ใฏใชใใ€ๅฎถใฎ่ค‡ๆ•ฐ็ฎ‡ๆ‰€ใงๅคง้‡ใฎไฝœๆฅญใŒใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ -ใ‚ใชใŸใฏใƒใƒณใƒใƒผใ‚ฌใƒผใฎไพ‹ใฎใ‚ˆใ†ใซใ€ๆœ€ๅˆใฏใƒชใƒ“ใƒณใ‚ฐใƒซใƒผใƒ ใ€ๆฌกใซใ‚ญใƒƒใƒใƒณใฎใ‚ˆใ†ใซ้ †็•ชใซใ‚„ใฃใฆใ„ใใ“ใจใŒใงใใพใ™ใŒใ€ไฝ•ใ‹ใ‚’ๅพ…ๆฉŸ๐Ÿ•™ใ—ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใชใใ€ใŸใ ใฒใŸใ™ใ‚‰ใซๆŽƒ้™คใ‚’ใ™ใ‚‹ใ ใ‘ใงใ€้ †็•ชใฏไฝ•ใซใ‚‚ๅฝฑ้Ÿฟใ—ใพใ›ใ‚“ใ€‚ +ใƒใƒณใƒใƒผใ‚ฌใƒผใฎไพ‹ใฎใ‚ˆใ†ใซ้ †็•ชใ‚’ๆฑบใ‚ใฆใ€ใพใšใƒชใƒ“ใƒณใ‚ฐใ€ๆฌกใซใ‚ญใƒƒใƒใƒณใ€ใจ้€ฒใ‚ใฆใ‚‚ใ‚ˆใ„ใฎใงใ™ใŒใ€ไฝ•ใ‹ใ‚’ๅพ…ใค ๐Ÿ•™ ใ‚ใ‘ใงใฏใชใใ€ใฒใŸใ™ใ‚‰ๆŽƒ้™คใ™ใ‚‹ใ ใ‘ใชใฎใงใ€้ †็•ชใฏไฝ•ใ‚‚ๅฝฑ้Ÿฟใ—ใพใ›ใ‚“ใ€‚ -้ †็•ชใฎๆœ‰็„กใซ้–ขไฟ‚ใชใ (ไธฆ่กŒใซ) ๅŒใ˜ๆ™‚้–“ใŒใ‹ใ‹ใ‚Šใ€ๅŒใ˜้‡ใฎไฝœๆฅญใŒ่กŒใ‚ใ‚Œใ‚‹ใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +้ †็•ชใฎๆœ‰็„ก (ไธฆ่กŒๆ€งใฎๆœ‰็„ก) ใซ้–ขไฟ‚ใชใใ€็ต‚ไบ†ใพใงใซๅŒใ˜ๆ™‚้–“ใŒใ‹ใ‹ใ‚Šใ€ๅŒใ˜ไฝœๆฅญ้‡ใ‚’ใ“ใชใ™ใ“ใจใซใชใ‚Šใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€ใ“ใฎๅ ดๅˆใ€8ไบบใฎๅ…ƒใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ/็พๅฝนๆธ…ๆŽƒๅ“ก๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณใ‚’ๆ‰‹้…ใงใใฆใ€ใใ‚Œใžใ‚Œ (ใ•ใ‚‰ใซใ‚ใชใŸใ‚‚) ใŒๅฎถใฎๅˆฅใ€…ใฎๅ ดๆ‰€ใ‚’ๆŽƒ้™คใงใใ‚Œใฐใ€่ฟฝๅŠ ใฎๅŠฉใ‘ใ‚’ๅ€Ÿใ‚Šใฆใ€ใ™ในใฆใฎไฝœๆฅญใ‚’**ไธฆๅˆ—**ใซ่กŒใ„ใ€ใฏใ‚‹ใ‹ใซๆ—ฉใ็ต‚ไบ†ใงใใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใ—ใ‹ใ—ใ“ใฎๅ ดๅˆใ€8 ไบบใฎๅ…ƒใƒฌใ‚ธไฟ‚/ๆ–™็†ไบบ/็พๆธ…ๆŽƒๅ“กใ‚’้€ฃใ‚Œใฆใใฆใ€ใใ‚Œใžใ‚Œ (ใ‚ใชใŸใ‚‚ๅŠ ใˆใฆ) ๅฎถใฎๅˆฅใ€…ใฎใ‚จใƒชใ‚ขใ‚’ๆŽƒ้™คใงใใ‚Œใฐใ€**ไธฆๅˆ—** ใซไฝœๆฅญใงใใ€ใ‚ˆใ‚Šๆ—ฉใ็ต‚ใˆใ‚‰ใ‚Œใพใ™ใ€‚ -ใ“ใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ๆธ…ๆŽƒๅ“ก (ใ‚ใชใŸใ‚’ๅซใ‚€) ใฎใใ‚Œใžใ‚ŒใŒใƒ—ใƒญใ‚ปใƒƒใ‚ตใจใชใ‚Šใ€ใใ‚Œใžใ‚Œใฎๅฝนๅ‰ฒใ‚’ๆžœใŸใ—ใพใ™ใ€‚ +ใ“ใฎใ‚ทใƒŠใƒชใ‚ชใงใฏใ€ๅ„ๆธ…ๆŽƒๅ“ก (ใ‚ใชใŸใ‚’ๅซใ‚€) ใŒใƒ—ใƒญใ‚ปใƒƒใ‚ตใงใ‚ใ‚Šใ€ใใ‚Œใžใ‚ŒใŒ่‡ชๅˆ†ใฎๅฝนๅ‰ฒใ‚’ๆžœใŸใ—ใพใ™ใ€‚ -ใพใŸใ€ๅฎŸ่กŒๆ™‚้–“ใฎใปใจใ‚“ใฉใฏ (ๅพ…ๆฉŸใงใฏใชใ) ๅฎŸ้š›ใฎไฝœๆฅญใซ่ฒปใ‚„ใ•ใ‚Œใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใงใฎไฝœๆฅญใฏCPUใซใ‚ˆใฃใฆ่กŒใ‚ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎๅ•้กŒใฏใ€ŒCPUใƒใ‚ฆใƒณใƒ‰ใ€ใจ่จ€ใ„ใพใ™ใ€‚ +ใใ—ใฆๅฎŸ่กŒๆ™‚้–“ใฎๅคงๅŠใฏ (ๅพ…ใกใงใฏใชใ) ๅฎŸไฝœๆฅญใŒๅ ใ‚ใ€ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใงใฎไฝœๆฅญใฏ CPU ใซใ‚ˆใฃใฆ่กŒใ‚ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎๅ•้กŒใฏใ€ŒCPU ใƒใ‚ฆใƒณใƒ‰ใ€ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ --- -CPUใƒใ‚ฆใƒณใƒ‰ๆ“ไฝœใฎไธ€่ˆฌ็š„ใชไพ‹ใฏใ€่ค‡้›‘ใชๆ•ฐๅญฆๅ‡ฆ็†ใŒๅฟ…่ฆใชใ‚‚ใฎใงใ™ใ€‚ +CPU ใƒใ‚ฆใƒณใƒ‰ใชๆ“ไฝœใฎไธ€่ˆฌ็š„ใชไพ‹ใฏใ€่ค‡้›‘ใชๆ•ฐๅ€คๅ‡ฆ็†ใŒๅฟ…่ฆใชใ‚‚ใฎใงใ™ใ€‚ ไพ‹ใˆใฐ: * **ใ‚ชใƒผใƒ‡ใ‚ฃใ‚ช** ใ‚„ **็”ปๅƒๅ‡ฆ็†**ใ€‚ -* **ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใƒ“ใ‚ธใƒงใƒณ**: ็”ปๅƒใฏๆ•ฐ็™พไธ‡ใฎใƒ”ใ‚ฏใ‚ปใƒซใงๆง‹ๆˆใ•ใ‚Œใ€ๅ„ใƒ”ใ‚ฏใ‚ปใƒซใซใฏ3ใคใฎๅ€ค/่‰ฒใŒใ‚ใ‚Šใ€้€šๅธธใ€ใ“ใ‚Œใ‚‰ใฎใƒ”ใ‚ฏใ‚ปใƒซใงไฝ•ใ‹ใ‚’ๅŒๆ™‚ใซ่จˆ็ฎ—ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ‡ฆ็†ใ€‚ -* **ๆฉŸๆขฐๅญฆ็ฟ’**: ้€šๅธธใ€ๅคšใใฎใ€Œ่กŒๅˆ—ใ€ใจใ€Œใƒ™ใ‚ฏใƒˆใƒซใ€ใฎไน—็ฎ—ใŒๅฟ…่ฆใงใ™ใ€‚ๅทจๅคงใชใ‚นใƒ—ใƒฌใƒƒใƒ‰ใ‚ทใƒผใƒˆใซๆ•ฐๅญ—ใ‚’ๅ…ฅใ‚Œใฆใ€ใใ‚Œใ‚’ๅŒๆ™‚ใซๅ…จ้ƒจๆŽ›ใ‘ๅˆใ‚ใ›ใ‚‹ใ“ใจใ‚’่€ƒใˆใฆใฟใฆใใ ใ•ใ„ใ€‚ -* **ใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐ**: ใ“ใ‚ŒใฏๆฉŸๆขฐๅญฆ็ฟ’ใฎใ‚ตใƒ–ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใงใ‚ใ‚‹ใŸใ‚ใ€ๅŒใ˜ใ“ใจใŒๅฝ“ใฆใฏใพใ‚Šใพใ™ใ€‚ไน—็ฎ—ใ™ใ‚‹ๆ•ฐๅญ—ใŒใ‚ใ‚‹ๅ˜ไธ€ใฎใ‚นใƒ—ใƒฌใƒƒใƒ‰ใ‚ทใƒผใƒˆใงใฏใชใใ€ใใ‚Œใ‚‰ใฎ่†จๅคงใช้›†ๅˆใงใ€ๅคšใใฎๅ ดๅˆใ€ใใ‚Œใ‚‰ใฎใƒขใƒ‡ใƒซใ‚’ๆง‹็ฏ‰ใŠใ‚ˆใณ/ใพใŸใฏไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซ็‰นๅˆฅใชใƒ—ใƒญใ‚ปใƒƒใ‚ตใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ +* **ใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟใƒ“ใ‚ธใƒงใƒณ**: ็”ปๅƒใฏๆ•ฐ็™พไธ‡ใฎใƒ”ใ‚ฏใ‚ปใƒซใงๆง‹ๆˆใ•ใ‚Œใ€ๅ„ใƒ”ใ‚ฏใ‚ปใƒซใซใฏ 3 ใคใฎๅ€ค/่‰ฒใŒใ‚ใ‚Šใ€้€šๅธธใ€ใใ‚Œใ‚‰ใฎใƒ”ใ‚ฏใ‚ปใƒซไธŠใงๅŒๆ™‚ใซไฝ•ใ‹ใ‚’่จˆ็ฎ—ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +* **ๆฉŸๆขฐๅญฆ็ฟ’**: ๅคšใใฎใ€Œ่กŒๅˆ—ใ€ใ‚„ใ€Œใƒ™ใ‚ฏใƒˆใƒซใ€ใฎไน—็ฎ—ใŒๅฟ…่ฆใซใชใ‚Šใพใ™ใ€‚ๅทจๅคงใชใ‚นใƒ—ใƒฌใƒƒใƒ‰ใ‚ทใƒผใƒˆใซๆ•ฐๅญ—ใŒๅ…ฅใฃใฆใ„ใฆใ€ใใ‚Œใ‚‰ใ‚’ๅŒๆ™‚ใซใ™ในใฆๆŽ›ใ‘ๅˆใ‚ใ›ใ‚‹ใ“ใจใ‚’ๆƒณๅƒใ—ใฆใใ ใ•ใ„ใ€‚ +* **ใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐ**: ๆฉŸๆขฐๅญฆ็ฟ’ใฎใ‚ตใƒ–ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใชใฎใงๅŒๆง˜ใงใ™ใ€‚ๆŽ›ใ‘ๅˆใ‚ใ›ใ‚‹ๆ•ฐๅญ—ใŒ 1 ใคใฎใ‚นใƒ—ใƒฌใƒƒใƒ‰ใ‚ทใƒผใƒˆใงใฏใชใ่†จๅคงใช้›†ๅˆใงใ‚ใ‚Šใ€ๅคšใใฎๅ ดๅˆใ€ใใ‚Œใ‚‰ใฎใƒขใƒ‡ใƒซใ‚’ๆง‹็ฏ‰/ๅˆฉ็”จใ™ใ‚‹ใŸใ‚ใฎ็‰นๅˆฅใชใƒ—ใƒญใ‚ปใƒƒใ‚ตใ‚’ไฝฟใ„ใพใ™ใ€‚ -### ไธฆ่กŒๅ‡ฆ็† + ไธฆๅˆ—ๅ‡ฆ็†: Web + ๆฉŸๆขฐๅญฆ็ฟ’ +### ไธฆ่กŒๅ‡ฆ็† + ไธฆๅˆ—ๅ‡ฆ็†: Web + ๆฉŸๆขฐๅญฆ็ฟ’ { #concurrency-parallelism-web-machine-learning } -**FastAPI**ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€Web้–‹็™บใง้žๅธธใซไธ€่ˆฌ็š„ใชไธฆ่กŒๅ‡ฆ็† (NodeJSใฎไธปใช้ญ…ๅŠ›ใจๅŒใ˜ใ‚‚ใฎ) ใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ +**FastAPI** ใงใฏใ€Web ้–‹็™บใง้žๅธธใซไธ€่ˆฌ็š„ใชไธฆ่กŒๅ‡ฆ็† (NodeJS ใฎไธปใช้ญ…ๅŠ›ใจๅŒใ˜) ใ‚’ๆดป็”จใงใใพใ™ใ€‚ -ใŸใ ใ—ใ€ๆฉŸๆขฐๅญฆ็ฟ’ใ‚ทใ‚นใƒ†ใƒ ใฎใ‚ˆใ†ใช **CPUใƒใ‚ฆใƒณใƒ‰** ใƒฏใƒผใ‚ฏใƒญใƒผใƒ‰ใซๅฏพใ—ใฆใ€ไธฆๅˆ—ๅ‡ฆ็†ใจใƒžใƒซใƒใƒ—ใƒญใ‚ปใƒƒใ‚ทใƒณใ‚ฐ (่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚นใŒไธฆๅˆ—ใงๅฎŸ่กŒใ•ใ‚Œใ‚‹) ใฎๅˆฉ็‚นใ‚’ๆดป็”จใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +ๅŒๆ™‚ใซใ€ๆฉŸๆขฐๅญฆ็ฟ’ใ‚ทใ‚นใƒ†ใƒ ใฎใ‚ˆใ†ใช **CPU ใƒใ‚ฆใƒณใƒ‰** ใชใƒฏใƒผใ‚ฏใƒญใƒผใƒ‰ใซๅฏพใ—ใฆใ€ไธฆๅˆ—ๅ‡ฆ็†ใ‚„ใƒžใƒซใƒใƒ—ใƒญใ‚ปใƒƒใ‚ทใƒณใ‚ฐ (่ค‡ๆ•ฐใƒ—ใƒญใ‚ปใ‚นใฎไธฆๅˆ—ๅฎŸ่กŒ) ใฎๅˆฉ็‚นใ‚‚ๆดป็”จใงใใพใ™ใ€‚ -ใ•ใ‚‰ใซใ€PythonใŒ**ใƒ‡ใƒผใ‚ฟใ‚ตใ‚คใ‚จใƒณใ‚น**ใ€ๆฉŸๆขฐๅญฆ็ฟ’ใ€็‰นใซใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐใฎไธป่ฆ่จ€่ชžใงใ‚ใ‚‹ใจใ„ใ†ๅ˜็ด”ใชไบ‹ๅฎŸใซใ‚ˆใ‚Šใ€FastAPIใฏใƒ‡ใƒผใ‚ฟใ‚ตใ‚คใ‚จใƒณใ‚น/ๆฉŸๆขฐๅญฆ็ฟ’ใฎWeb APIใŠใ‚ˆใณใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ (ไป–ใฎๅคšใใฎใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใจใฎ) ใซ้žๅธธใซใ‚ˆใ้ฉๅˆใ—ใฆใ„ใพใ™ใ€‚ +ใ•ใ‚‰ใซใ€Python ใŒ **ใƒ‡ใƒผใ‚ฟใ‚ตใ‚คใ‚จใƒณใ‚น**ใ€ๆฉŸๆขฐๅญฆ็ฟ’ใ€็‰นใซใƒ‡ใ‚ฃใƒผใƒ—ใƒฉใƒผใƒ‹ใƒณใ‚ฐใฎไธป่ฆ่จ€่ชžใงใ‚ใ‚‹ใจใ„ใ†ไบ‹ๅฎŸใ‚‚็›ธใพใฃใฆใ€FastAPI ใฏใƒ‡ใƒผใ‚ฟใ‚ตใ‚คใ‚จใƒณใ‚น/ๆฉŸๆขฐๅญฆ็ฟ’ใฎ Web API ใ‚„ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ (ใปใ‹ๅคšๆ•ฐ) ใซ้žๅธธใซ้ฉใ—ใฆใ„ใพใ™ใ€‚ -ๆœฌ็•ช็’ฐๅขƒใงใ“ใฎไธฆๅˆ—ๅ‡ฆ็†ใ‚’ๅฎŸ็พใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆใฏใ€[ใƒ‡ใƒ—ใƒญใ‚ค](deployment/index.md){.internal-link target=_blank}ใซ้–ขใ™ใ‚‹ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +ๆœฌ็•ช็’ฐๅขƒใงใ“ใฎไธฆๅˆ—ๆ€งใ‚’ๅฎŸ็พใ™ใ‚‹ๆ–นๆณ•ใฏใ€[ใƒ‡ใƒ—ใƒญใ‚ค](deployment/index.md){.internal-link target=_blank} ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ -## `async` ใจ `await` +## `async` ใจ `await` { #async-and-await } -็พไปฃ็š„ใชใƒใƒผใ‚ธใƒงใƒณใฎPythonใซใฏใ€้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ‚’ๅฎš็พฉใ™ใ‚‹้žๅธธใซ็›ดๆ„Ÿ็š„ใชๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€้€šๅธธใฎใ€Œใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใ€ใ‚ณใƒผใƒ‰ใฎใ‚ˆใ†ใซ่ฆ‹ใˆใ€้ฉๅˆ‡ใชใ‚ฟใ‚คใƒŸใƒณใ‚ฐใงใ€Œๅพ…ๆฉŸใ€ใ—ใพใ™ใ€‚ +ใƒขใƒ€ใƒณใช Python ใซใฏใ€้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ‚’ใจใฆใ‚‚็›ดๆ„Ÿ็š„ใซๅฎš็พฉใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€้€šๅธธใฎใ€Œใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใ€ใชใ‚ณใƒผใƒ‰ใฎใ‚ˆใ†ใซๆ›ธใ‘ใฆใ€้ฉๅˆ‡ใชใ‚ฟใ‚คใƒŸใƒณใ‚ฐใงใ€Œๅพ…ใกใ€ใ‚’่กŒใฃใฆใใ‚Œใพใ™ใ€‚ -็ตๆžœใ‚’่ฟ”ใ™ๅ‰ใซๅพ…ๆฉŸใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใ€ใ“ใ‚Œใ‚‰ใฎๆ–ฐใ—ใ„PythonๆฉŸ่ƒฝใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ๆ“ไฝœใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎใ‚ˆใ†ใซใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใงใใพใ™ใ€‚ +็ตๆžœใ‚’่ฟ”ใ™ๅ‰ใซๅพ…ใกใŒๅฟ…่ฆใงใ€ใ“ใ‚Œใ‚‰ใฎๆ–ฐใ—ใ„ Python ๆฉŸ่ƒฝใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใ‚‹ๆ“ไฝœใŒใ‚ใ‚‹ๅ ดๅˆใ€ๆฌกใฎใ‚ˆใ†ใซๆ›ธใ‘ใพใ™ใ€‚ ```Python burgers = await get_burgers(2) ``` -ใ‚ซใ‚ฎใฏ `await` ใงใ™ใ€‚็ตๆžœใ‚’ `burgers`ใซไฟๅญ˜ใ™ใ‚‹ๅ‰ใซใ€`get_burgers(2)`ใฎๅ‡ฆ็†๐Ÿ•™ใฎๅฎŒไบ†ใ‚’ๅพ…ใคโธๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใ‚’Pythonใซไผใˆใพใ™ใ€‚ใ“ใ‚ŒใงPythonใฏใ€ใใฎ้–“ใซ (ๅˆฅใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ไฟกใ™ใ‚‹ใชใฉ) ไฝ•ใ‹ไป–ใฎใ“ใจใŒใงใใ‚‹๐Ÿ”€โฏใ“ใจใ‚’็Ÿฅใ‚Šใพใ™ใ€‚ +ใ“ใ“ใงใฎ้ตใฏ `await` ใงใ™ใ€‚`burgers` ใซ็ตๆžœใ‚’ไฟๅญ˜ใ™ใ‚‹ๅ‰ใซใ€`get_burgers(2)` ใŒใ‚„ใ‚‹ในใใ“ใจใ‚’็ต‚ใˆใ‚‹ใฎใ‚’ โธ ๅพ…ใค ๐Ÿ•™ ใ‚ˆใ†ใซ Python ใซไผใˆใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Š Python ใฏใ€ใใฎ้–“ใซ (ๅˆฅใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚‹ใชใฉ) ใปใ‹ใฎใ“ใจใ‚’ ๐Ÿ”€ โฏ ใงใใ‚‹ใจๅˆ†ใ‹ใ‚Šใพใ™ใ€‚ -`await` ใŒๆฉŸ่ƒฝใ™ใ‚‹ใŸใ‚ใซใฏใ€้žๅŒๆœŸๅ‡ฆ็†ใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹้–ขๆ•ฐๅ†…ใซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€`async def` ใง้–ขๆ•ฐใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ ใ‘ใงใ‚ˆใ„ใงใ™: +`await` ใŒๆฉŸ่ƒฝใ™ใ‚‹ใซใฏใ€ใ“ใฎ้žๅŒๆœŸๆ€งใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹้–ขๆ•ฐใฎๅ†…้ƒจใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใใฎใŸใ‚ใซใฏ `async def` ใงๅฎฃ่จ€ใ—ใพใ™: ```Python hl_lines="1" async def get_burgers(number: int): - # ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซ้žๅŒๆœŸๅ‡ฆ็†ใ‚’ๅฎŸ่กŒ + # ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ไฝœใ‚‹ใŸใ‚ใซ้žๅŒๆœŸใฎๅ‡ฆ็†ใ‚’่กŒใ† return burgers ``` -...`def` ใฎใ‹ใ‚ใ‚Šใซ: +...`def` ใฎไปฃใ‚ใ‚Šใซ: ```Python hl_lines="2" -# ้žๅŒๆœŸใงใฏใชใ„ +# ใ“ใ‚Œใฏ้žๅŒๆœŸใงใฏใชใ„ def get_sequential_burgers(number: int): - # ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใชๅ‡ฆ็†ใ‚’ๅฎŸ่กŒ + # ใƒใƒณใƒใƒผใ‚ฌใƒผใ‚’ไฝœใ‚‹ใŸใ‚ใซใ‚ทใƒผใ‚ฑใƒณใ‚ทใƒฃใƒซใชๅ‡ฆ็†ใ‚’่กŒใ† return burgers ``` -`async def` ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€Pythonใซใใฎ้–ขๆ•ฐๅ†…ใง `await` ๅผ (ใใฎ้–ขๆ•ฐใฎๅฎŸ่กŒใ‚’ใ€Œไธ€ๆ™‚ๅœๆญขโธใ€ใ—ใ€็ตๆžœใŒๆˆปใ‚‹ใพใงไป–ใฎไฝ•ใ‹ใ‚’ๅฎŸ่กŒ๐Ÿ”€ใ™ใ‚‹) ใ‚’่ช่ญ˜ใ—ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„ใจไผใˆใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -`async def` ้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ™ใจใใฏใ€ใ€Œawaitใ€ใ—ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใ—ใŸใŒใฃใฆใ€ใ“ใ‚ŒใฏๆฉŸ่ƒฝใ—ใพใ›ใ‚“: +`async def` ใ‚’ไฝฟใ†ใจใ€Python ใฏใใฎ้–ขๆ•ฐๅ†…ใง `await` ๅผใซๆณจๆ„ใ—ใ€้–ขๆ•ฐใฎๅฎŸ่กŒใ‚’ใ€Œไธ€ๆ™‚ๅœๆญขใ€โธ ใ—ใฆใปใ‹ใฎใ“ใจใ‚’ใ—ใซ่กŒใ ๐Ÿ”€ใ€ๆˆปใฃใฆใใ‚‹ใ“ใจใŒใงใใ‚‹ใจๅˆ†ใ‹ใ‚Šใพใ™ใ€‚ + +`async def` ใช้–ขๆ•ฐใ‚’ๅ‘ผใถใจใใฏใ€Œawaitใ€ใ—ใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใ—ใŸใŒใฃใฆใ€ๆฌกใฏๅ‹•ใใพใ›ใ‚“: ```Python -# get_burgersใฏasync defใงๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใฎใงๅ‹•ไฝœใ—ใชใ„ +# ๅ‹•ใใพใ›ใ‚“ใ€‚get_burgers ใฏ async def ใงๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ burgers = get_burgers(2) ``` --- -ใ—ใŸใŒใฃใฆใ€ `await` ใงๅ‘ผใณๅ‡บใ™ใ“ใจใŒใงใใ‚‹ใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎใ‚ˆใ†ใซ `async def` ใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹*path operation ้–ขๆ•ฐ*ใ‚’ไฝœๆˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: +ใใฎใŸใ‚ใ€`await` ใงๅ‘ผในใ‚‹ใจ่ฌณใฃใฆใ„ใ‚‹ใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใใ‚Œใ‚’ไฝฟใ† *path operation ้–ขๆ•ฐ* ใ‚’ `async def` ใงไฝœใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐ: ```Python hl_lines="2-3" @app.get('/burgers') @@ -314,86 +349,96 @@ async def read_burgers(): return burgers ``` -### ใ‚ˆใ‚Š็™บๅฑ•็š„ใชๆŠ€่ก“่ฉณ็ดฐ +### ใ‚ˆใ‚Š็™บๅฑ•็š„ใชๆŠ€่ก“่ฉณ็ดฐ { #more-technical-details } + +`await` ใฏ `async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐใฎๅ†…้ƒจใงใ—ใ‹ไฝฟใˆใชใ„ใ“ใจใซๆฐ—ใฅใ„ใŸใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ๅŒๆ™‚ใซใ€`async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐใฏใ€Œawaitใ€ใ•ใ‚Œใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใคใพใ‚Šใ€`async def` ใ‚’ๆŒใค้–ขๆ•ฐใฏใ€ใ‚„ใฏใ‚Š `async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐใฎๅ†…้ƒจใ‹ใ‚‰ใ—ใ‹ๅ‘ผในใพใ›ใ‚“ใ€‚ + +ใงใฏใ€ใƒ‹ใƒฏใƒˆใƒชใจๅตใฎ่ฉฑใฎใ‚ˆใ†ใซใ€ๆœ€ๅˆใฎ `async` ้–ขๆ•ฐใฏใฉใ†ๅ‘ผใถใฎใงใ—ใ‚‡ใ†ใ‹๏ผŸ + +**FastAPI** ใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใฏๅฟƒ้…ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใฎใ€Œๆœ€ๅˆใฎใ€้–ขๆ•ฐใฏ *path operation ้–ขๆ•ฐ* ใงใ€FastAPI ใŒ้ฉๅˆ‡ใซๅฎŸ่กŒใ—ใฆใใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€FastAPI ใ‚’ไฝฟใ‚ใšใซ `async` / `await` ใ‚’ไฝฟใ„ใŸใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -`await` ใฏ `async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐๅ†…ใงใฎใฟไฝฟ็”จใงใใ‚‹ใ“ใจใŒใ‚ใ‹ใฃใŸใ‹ใจๆ€ใ„ใพใ™ใ€‚ +### ่‡ชๅˆ†ใง async ใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ { #write-your-own-async-code } -ใ—ใ‹ใ—ๅŒๆ™‚ใซใ€`async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐใฏใ€Œawaitใ•ใ‚Œใ‚‹ใ€ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใชใฎใงใ€`async def` ใ‚’ๆŒใค้–ขๆ•ฐใฏใ€`async def` ใงๅฎš็พฉใ•ใ‚ŒใŸ้–ขๆ•ฐๅ†…ใงใฎใฟๅ‘ผใณๅ‡บใ›ใพใ™ใ€‚ +Starlette (**FastAPI** ใ‚‚) ใฏ AnyIO ใฎไธŠใซๆง‹็ฏ‰ใ•ใ‚ŒใฆใŠใ‚Šใ€ๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎ asyncio ใจ Trio ใฎไธกๆ–นใซๅฏพๅฟœใ—ใฆใ„ใพใ™ใ€‚ -ใงใฏใ€ใ“ใฎใƒ‹ใƒฏใƒˆใƒชใจๅตใฎๅ•้กŒใซใคใ„ใฆใ€ๆœ€ๅˆใฎ `async` ้–ขๆ•ฐใ‚’ใฉใฎใ‚ˆใ†ใซๅ‘ผใณๅ‡บใ™ใฎใงใ—ใ‚‡ใ†ใ‹๏ผŸ +็‰นใซใ€ใ‚ใชใŸ่‡ช่บซใฎใ‚ณใƒผใƒ‰ๅ†…ใงใ€ใ‚ˆใ‚Š้ซ˜ๅบฆใชใƒ‘ใ‚ฟใƒผใƒณใ‚’ๅฟ…่ฆใจใ™ใ‚‹็™บๅฑ•็š„ใชไธฆ่กŒๅ‡ฆ็†ใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซๅฏพใ—ใฆใ€AnyIO ใ‚’็›ดๆŽฅไฝฟใˆใพใ™ใ€‚ -**FastAPI**ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ใใฎใ€Œๆœ€ๅˆใฎใ€้–ขๆ•ฐใŒ*path operation ้–ขๆ•ฐ*ใงใ‚ใ‚Šใ€FastAPIใŒๆญฃใ—ใๅฎŸ่กŒใ™ใ‚‹ๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ€ๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ไปฎใซ FastAPI ใ‚’ไฝฟใฃใฆใ„ใชใใฆใ‚‚ใ€AnyIO ใง็‹ฌ่‡ชใฎ async ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆ›ธใ‘ใฐใ€้ซ˜ใ„ไบ’ๆ›ๆ€งใจๅˆฉ็‚น (ไพ‹: ๆง‹้€ ๅŒ–ไธฆ่กŒๆ€ง) ใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ -ใ—ใ‹ใ—ใ€FastAPIไปฅๅค–ใง `async` / `await` ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใฏใ€ๅ…ฌๅผPythonใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆไธ‹ใ•ใ„ใ€‚ +็งใฏ AnyIO ใฎไธŠใซ่–„ใ„ๅฑคใจใ—ใฆใ€ๅž‹ๆณจ้‡ˆใ‚’ๅฐ‘ใ—ๆ”นๅ–„ใ—ใ€ใ‚ˆใ‚Š่‰ฏใ„**่ฃœๅฎŒ**ใ‚„**ใ‚คใƒณใƒฉใ‚คใƒณใ‚จใƒฉใƒผ**ใชใฉใ‚’ๅพ—ใ‚‹ใŸใ‚ใฎๅˆฅใƒฉใ‚คใƒ–ใƒฉใƒชใ‚‚ไฝœใ‚Šใพใ—ใŸใ€‚ใพใŸใ€**็†่งฃ**ใ—ใฆ**่‡ชๅˆ†ใง async ใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ**ใฎใซๅฝน็ซ‹ใคใƒ•ใƒฌใƒณใƒ‰ใƒชใƒผใชใ‚คใƒณใƒˆใƒญ/ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚‚ใ‚ใ‚Šใพใ™: Asyncerใ€‚็‰นใซใ€**async ใ‚ณใƒผใƒ‰ใจ้€šๅธธใฎ** (ใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐ/ๅŒๆœŸ) **ใ‚ณใƒผใƒ‰ใ‚’็ต„ใฟๅˆใ‚ใ›ใ‚‹**ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใซๆœ‰็”จใงใ™ใ€‚ -### ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎไป–ใฎๅฝขๅผ +### ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎไป–ใฎๅฝขๅผ { #other-forms-of-asynchronous-code } -`async` ใจ `await` ใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚นใ‚ฟใ‚คใƒซใฏใ€ใ“ใฎ่จ€่ชžใงใฏๆฏ”่ผƒ็š„ๆ–ฐใ—ใ„ใ‚‚ใฎใงใ™ใ€‚ +`async` ใจ `await` ใ‚’ไฝฟใ†ใ“ใฎใ‚นใ‚ฟใ‚คใƒซใฏใ€่จ€่ชžใจใ—ใฆใฏๆฏ”่ผƒ็š„ๆ–ฐใ—ใ„ใ‚‚ใฎใงใ™ใ€‚ -้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎๆ“ไฝœใŒใฏใ‚‹ใ‹ใซ็ฐกๅ˜ใซใชใ‚Šใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€ใ“ใ‚Œใซใ‚ˆใ‚Š้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎๅ–ใ‚Šๆ‰ฑใ„ใฏๅคงๅน…ใซ็ฐกๅ˜ใซใชใ‚Šใพใ™ใ€‚ -็ญ‰ไพกใช (ใพใŸใฏใปใจใ‚“ใฉๅŒไธ€ใฎ) ๆง‹ๆ–‡ใŒใ€ๆœ€่ฟ‘ใฎใƒใƒผใ‚ธใƒงใƒณใฎJavaScript (ใƒ–ใƒฉใ‚ฆใ‚ถใŠใ‚ˆใณNodeJS) ใซใ‚‚ๆœ€่ฟ‘็ต„ใฟ่พผใพใ‚Œใพใ—ใŸใ€‚ +ๅŒ็ญ‰ (ใปใผๅŒไธ€) ใฎๆง‹ๆ–‡ใŒๆœ€่ฟ‘ใฎ JavaScript (ใƒ–ใƒฉใ‚ฆใ‚ถใจ NodeJS) ใซใ‚‚ๅฐŽๅ…ฅใ•ใ‚Œใพใ—ใŸใ€‚ -ใ—ใ‹ใ—ใ€ใใฎๅ‰ใฏใ€้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎๅ‡ฆ็†ใฏใ‹ใชใ‚Š่ค‡้›‘ใง้›ฃ่งฃใงใ—ใŸใ€‚ +ใใ‚Œไปฅๅ‰ใฏใ€้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎๆ‰ฑใ„ใฏใ‹ใชใ‚Š่ค‡้›‘ใง้›ฃ่งฃใงใ—ใŸใ€‚ -ไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใฎPythonใงใฏใ€ใ‚นใƒฌใƒƒใƒ‰ใ‚„GeventใŒๅˆฉ็”จใงใใพใ—ใŸใ€‚ใ—ใ‹ใ—ใ€ใ‚ณใƒผใƒ‰ใฏ็†่งฃใ€ใƒ‡ใƒใƒƒใ‚ฏใ€ใใ—ใฆใ€่€ƒๅฏŸใŒใฏใ‚‹ใ‹ใซ่ค‡้›‘ใงใ™ใ€‚ +ไปฅๅ‰ใฎ Python ใงใฏใ‚นใƒฌใƒƒใƒ‰ใ‚„ Gevent ใ‚’ไฝฟใˆใพใ—ใŸใŒใ€ใ‚ณใƒผใƒ‰ใฎ็†่งฃใƒปใƒ‡ใƒใƒƒใ‚ฐใƒปๆ€่€ƒใŒใฏใ‚‹ใ‹ใซ้›ฃใ—ใใชใ‚Šใพใ™ใ€‚ -ไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใฎNodeJS / ใƒ–ใƒฉใ‚ฆใ‚ถJavaScriptใงใฏใ€ใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ€ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ—ใŸใ€‚ใ“ใ‚Œใฏใ€ใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏๅœฐ็„ใ€ใซใคใชใŒใ‚Šใพใ™ใ€‚ +ไปฅๅ‰ใฎ NodeJS / ใƒ–ใƒฉใ‚ฆใ‚ถ JavaScript ใงใฏใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏใ€ใ‚’ไฝฟใฃใฆใŠใ‚Šใ€ใ€Œใ‚ณใƒผใƒซใƒใƒƒใ‚ฏๅœฐ็„ใ€ใ‚’ๆ‹›ใใพใ—ใŸใ€‚ -## ใ‚ณใƒซใƒผใƒใƒณ +## ใ‚ณใƒซใƒผใƒใƒณ { #coroutines } -**ใ‚ณใƒซใƒผใƒใƒณ**ใฏใ€`async def` ้–ขๆ•ฐใซใ‚ˆใฃใฆ่ฟ”ใ•ใ‚Œใ‚‹ใ‚‚ใฎใ‚’ๆŒ‡ใ™้žๅธธใซๆด’่ฝใŸ็”จ่ชžใงใ™ใ€‚ใ“ใ‚Œใฏใ€้–‹ๅง‹ใงใใฆใ€ใ„ใคใ‹็ต‚ไบ†ใ™ใ‚‹้–ขๆ•ฐใฎใ‚ˆใ†ใชใ‚‚ใฎใงใ‚ใ‚‹ใŒใ€ๅ†…้ƒจใซ `await` ใŒใ‚ใ‚‹ใจใใฏๅ†…้ƒจ็š„ใซไธ€ๆ™‚ๅœๆญขโธใ•ใ‚Œใ‚‹ใ“ใจใ‚‚ใ‚ใ‚‹ใ‚‚ใฎใ ใจPythonใฏ่ช่ญ˜ใ—ใฆใ„ใพใ™ใ€‚ +**ใ‚ณใƒซใƒผใƒใƒณ**ใฏใ€`async def` ้–ขๆ•ฐใŒ่ฟ”ใ™ใ‚‚ใฎใ‚’ๆŒ‡ใ™ใ€ใกใ‚‡ใฃใจๆด’่ฝใŸ็”จ่ชžใงใ™ใ€‚Python ใฏใใ‚Œใ‚’ใ€้–‹ๅง‹ใงใใฆใ„ใคใ‹็ต‚ไบ†ใ™ใ‚‹้–ขๆ•ฐใฎใ‚ˆใ†ใชใ‚‚ใฎใจใ—ใฆๆ‰ฑใ„ใพใ™ใŒใ€ๅ†…้ƒจใซ `await` ใŒใ‚ใ‚‹ใŸใณใซๅ†…้ƒจ็š„ใซไธ€ๆ™‚ๅœๆญข โธ ใ™ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ‚‚ใฎใจใ—ใฆ่ช่ญ˜ใ—ใพใ™ใ€‚ -`async` ใจ `await` ใ‚’็”จใ„ใŸ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใ™ในใฆใฎๆฉŸ่ƒฝใฏใ€ใ€Œใ‚ณใƒซใƒผใƒใƒณใ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚‚ใฎใจใ—ใฆไฝ•ๅบฆใ‚‚ใพใจใ‚ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚Goใฎไธป่ฆๆฉŸ่ƒฝใงใ‚ใ‚‹ใ€Œใ‚ดใƒซใƒผใƒใƒณใ€ใซ็›ธๅฝ“ใ—ใพใ™ใ€‚ +`async` ใจ `await` ใ‚’็”จใ„ใŸ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใฎๆฉŸ่ƒฝๅ…จไฝ“ใฏใ€ใ—ใฐใ—ใฐใ€Œใ‚ณใƒซใƒผใƒใƒณใ‚’ไฝฟใ†ใ€ใจ่ฆ็ด„ใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏ Go ใฎไธป่ฆๆฉŸ่ƒฝใ€ŒGoroutinesใ€ใซ็›ธๅฝ“ใ—ใพใ™ใ€‚ -## ใพใจใ‚ +## ใพใจใ‚ { #conclusion } -ไธŠ่ฟฐใ—ใŸใƒ•ใƒฌใƒผใ‚บใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: +ไธŠใฎใƒ•ใƒฌใƒผใ‚บใ‚’ใ‚‚ใ†ไธ€ๅบฆ่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: -> ็พไปฃ็‰ˆใฎPythonใฏใ€Œ**้žๅŒๆœŸใ‚ณใƒผใƒ‰**ใ€ใ‚’ใ€ใ€Œ**ใ‚ณใƒซใƒผใƒใƒณ**ใ€ใจ็งฐใ•ใ‚Œใ‚‹ใ‚‚ใฎใ‚’ๅˆฉ็”จใ—ใฆใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใฏ **`async` ใจ `await`** ๆง‹ๆ–‡ใ‚’็”จใ„ใพใ™ใ€‚ +> ใƒขใƒ€ใƒณใช Python ใฏ **ใ€Œ้žๅŒๆœŸใ‚ณใƒผใƒ‰ใ€** ใ‚’ **ใ€Œใ‚ณใƒซใƒผใƒใƒณใ€** ใจๅ‘ผใฐใ‚Œใ‚‹ไป•็ต„ใฟใงใ‚ตใƒใƒผใƒˆใ—ใฆใŠใ‚Šใ€ๆง‹ๆ–‡ใฏ **`async` ใจ `await`** ใงใ™ใ€‚ -ไปŠใงใฏใ€ใ“ใฎๆ„ๅ‘ณใŒใ‚ˆใ‚Š็†่งฃใงใใ‚‹ใฏใšใงใ™ใ€‚โœจ +ไปŠใชใ‚‰ใ€ใ‚ˆใ‚Šๆ„ๅ‘ณใŒๅˆ†ใ‹ใ‚‹ใฏใšใงใ™ใ€‚โœจ -(Starletteใ‚’ไป‹ใ—ใฆ) FastAPIใซๅŠ›ใ‚’ไธŽใˆใฆใ€ๅฐ่ฑก็š„ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’ๅฎŸ็พใ—ใฆใ„ใ‚‹ใ‚‚ใฎใฏใ“ใ‚ŒใŒใ™ในใฆใงใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใ™ในใฆใŒ (Starlette ใ‚’้€šใ˜ใฆ) FastAPI ใ‚’ๆ”ฏใˆใ€ๅฐ่ฑก็š„ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’ๅฎŸ็พใ—ใฆใ„ใพใ™ใ€‚ -## ้žๅธธใซ็™บๅฑ•็š„ใชๆŠ€่ก“็š„่ฉณ็ดฐ +## ้žๅธธใซ็™บๅฑ•็š„ใชๆŠ€่ก“็š„่ฉณ็ดฐ { #very-technical-details } /// warning | ๆณจๆ„ -ๆใ‚‰ใใ‚นใ‚ญใƒƒใƒ—ใ—ใฆใ‚‚่‰ฏใ„ใงใ—ใ‚‡ใ†ใ€‚ +ใŠใใ‚‰ใ่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ๅคงไธˆๅคซใงใ™ใ€‚ -ใ“ใฎ้ƒจๅˆ†ใฏ**FastAPI**ใฎไป•็ต„ใฟใซ้–ขใ™ใ‚‹้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ™ใ€‚ +ใ“ใ‚Œใฏ **FastAPI** ใฎๅ†…้ƒจๅ‹•ไฝœใซ้–ขใ™ใ‚‹ใ€ใจใฆใ‚‚ๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ™ใ€‚ -ใ‹ใชใ‚ŠใฎๆŠ€่ก“็Ÿฅ่ญ˜ (ใ‚ณใƒซใƒผใƒใƒณใ€ใ‚นใƒฌใƒƒใƒ‰ใ€ใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐใชใฉ) ใŒใ‚ใ‚Šใ€FastAPIใŒ `async def` ใจ้€šๅธธใฎ `def` ใ‚’ใฉใฎใ‚ˆใ†ใซๅ‡ฆ็†ใ™ใ‚‹ใ‹็Ÿฅใ‚ŠใŸใ„ๅ ดๅˆใฏใ€ๅ…ˆใซ้€ฒใ‚“ใงใใ ใ•ใ„ใ€‚ +(ใ‚ณใƒซใƒผใƒใƒณใ€ใ‚นใƒฌใƒƒใƒ‰ใ€ใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐ็ญ‰ใฎ) ๆŠ€่ก“็Ÿฅ่ญ˜ใŒใ‚ใ‚Šใ€FastAPI ใŒ `async def` ใจ้€šๅธธใฎ `def` ใ‚’ใฉใ†ๆ‰ฑใ†ใ‹ใซ่ˆˆๅ‘ณใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€่ชญใฟ้€ฒใ‚ใฆใใ ใ•ใ„ใ€‚ /// -### Path operation ้–ขๆ•ฐ +### Path operation ้–ขๆ•ฐ { #path-operation-functions } -*path operation ้–ขๆ•ฐ*ใ‚’ `async def` ใฎไปฃใ‚ใ‚Šใซ้€šๅธธใฎ `def` ใงๅฎฃ่จ€ใ™ใ‚‹ใจใ€(ใ‚ตใƒผใƒใƒผใ‚’ใƒ–ใƒญใƒƒใ‚ฏใ™ใ‚‹ใฎใง) ็›ดๆŽฅๅ‘ผใณๅ‡บใ™ไปฃใ‚ใ‚Šใซๅค–้ƒจใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซ (awaitใ•ใ‚Œใ‚‹) ใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +*path operation ้–ขๆ•ฐ* ใ‚’ `async def` ใงใฏใชใ้€šๅธธใฎ `def` ใงๅฎฃ่จ€ใ—ใŸๅ ดๅˆใ€(ใ‚ตใƒผใƒใ‚’ใƒ–ใƒญใƒƒใ‚ฏใ—ใฆใ—ใพใ†ใŸใ‚) ็›ดๆŽฅๅ‘ผใณๅ‡บใ•ใ‚Œใ‚‹ใฎใงใฏใชใใ€ๅค–้ƒจใฎใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงๅฎŸ่กŒใ•ใ‚Œใ€ใใ‚Œใ‚’ๅพ…ๆฉŸใ—ใพใ™ใ€‚ -ไธŠ่จ˜ใฎๆ–นๆณ•ใจ้•ใฃใŸๆ–นๆณ•ใฎๅˆฅใฎ้žๅŒๆœŸใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‹ใ‚‰ๆฅใฆใŠใ‚Šใ€ๅฐใ•ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๅ‘ไธŠ (็ด„100ใƒŠใƒŽ็ง’) ใฎใŸใ‚ใซ้€šๅธธใฎ `def` ใ‚’ไฝฟ็”จใ—ใฆไบ›็ดฐใชๆผ”็ฎ—ใฎใฟ่กŒใ† *path operation ้–ขๆ•ฐ* ใ‚’ๅฎš็พฉใ™ใ‚‹ใฎใซๆ…ฃใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใฏใ€**FastAPI**ใงใฏใพใฃใŸใ้€†ใฎๅŠนๆžœใซใชใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใฎใ‚ˆใ†ใชๅ ดๅˆใ€*path operation ้–ขๆ•ฐ* ใŒใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐI/Oใ‚’ๅฎŸ่กŒใ—ใชใ„ใฎใงใ‚ใ‚Œใฐใ€`async def` ใฎไฝฟ็”จใ‚’ใŠๅ‹งใ‚ใ—ใพใ™ใ€‚ +ไธŠ่จ˜ใจใฏ็•ฐใชใ‚‹ๅ‹•ไฝœใฎๅˆฅใฎ้žๅŒๆœŸใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‹ใ‚‰ๆฅใฆใŠใ‚Šใ€ใปใ‚“ใฎใ‚ใšใ‹ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๅ‘ไธŠ (็ด„ 100 ใƒŠใƒŽ็ง’) ใ‚’็‹™ใฃใฆใ€่จˆ็ฎ—ใฎใฟใฎไบ›็ดฐใช *path operation ้–ขๆ•ฐ* ใ‚’็ด ใฎ `def` ใงๅฎš็พฉใ™ใ‚‹ใ“ใจใซๆ…ฃใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใ€**FastAPI** ใงใฏๅŠนๆžœใŒใพใฃใŸใ้€†ใซใชใ‚‹็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใ‚Œใ‚‰ใฎๅ ดๅˆใ€*path operation ้–ขๆ•ฐ* ใŒใƒ–ใƒญใƒƒใ‚ญใƒณใ‚ฐใช I/O ใ‚’่กŒใ†ใ‚ณใƒผใƒ‰ใ‚’ไฝฟใฃใฆใ„ใชใ„้™ใ‚Šใ€`async def` ใ‚’ไฝฟใฃใŸๆ–นใŒ่‰ฏใ„ใงใ™ใ€‚ -ใใ‚Œใงใ‚‚ใ€ใฉใกใ‚‰ใฎ็Šถๆณใงใ‚‚ใ€**FastAPI**ใŒ้ŽๅŽปใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚ˆใ‚Šใ‚‚ (ใพใŸใฏใใ‚ŒใซๅŒนๆ•ตใ™ใ‚‹ใปใฉ) [้ซ˜้€Ÿใซใชใ‚‹](index.md#_10){.internal-link target=_blank}ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ +ใใ‚Œใงใ‚‚ใ€ใฉใกใ‚‰ใฎ็Šถๆณใงใ‚‚ใ€**FastAPI** ใฏใ‚ใชใŸใŒไปฅๅ‰ไฝฟใฃใฆใ„ใŸใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใ‚ˆใ‚Šใ‚‚ (ๅฐ‘ใชใใจใ‚‚ๅŒ็ญ‰ใซ) [้ซ˜้€Ÿใงใ‚ใ‚‹](index.md#performance){.internal-link target=_blank} ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใงใ™ใ€‚ -### ไพๅญ˜้–ขไฟ‚ +### ไพๅญ˜้–ขไฟ‚ { #dependencies } -ไพๅญ˜้–ขไฟ‚ใซใคใ„ใฆใ‚‚ๅŒๆง˜ใงใ™ใ€‚ไพๅญ˜้–ขไฟ‚ใŒ `async def` ใงใฏใชใๆจ™ๆบ–ใฎ `def` ้–ขๆ•ฐใงใ‚ใ‚‹ๅ ดๅˆใ€ๅค–้ƒจใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +[ไพๅญ˜้–ขไฟ‚](tutorial/dependencies/index.md){.internal-link target=_blank} ใซใคใ„ใฆใ‚‚ๅŒๆง˜ใงใ™ใ€‚ไพๅญ˜้–ขไฟ‚ใŒ `async def` ใงใฏใชใๆจ™ๆบ–ใฎ `def` ้–ขๆ•ฐใงใ‚ใ‚‹ๅ ดๅˆใ€ๅค–้ƒจใฎใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ -### ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ +### ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ { #sub-dependencies } -(้–ขๆ•ฐๅฎš็พฉใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใจใ—ใฆ) ็›ธไบ’ใซๅฟ…่ฆใช่ค‡ๆ•ฐใฎไพๅญ˜้–ขไฟ‚ใจใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’่จญๅฎšใงใใพใ™ใ€‚ไธ€้ƒจใฏ `async def` ใงไฝœๆˆใ•ใ‚Œใ€ไป–ใฎไธ€้ƒจใฏ้€šๅธธใฎ `def` ใงไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ใใ‚Œใงใ‚‚ๅ‹•ไฝœใ—ใ€้€šๅธธใฎ `def`ใงไฝœๆˆใ•ใ‚ŒใŸใ‚‚ใฎใฏใ€ใ€Œawaitใ•ใ‚Œใ‚‹ใ€ไปฃใ‚ใ‚Šใซ (ใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใ‹ใ‚‰) ๅค–้ƒจใ‚นใƒฌใƒƒใƒ‰ใงๅ‘ผใณๅ‡บใ•ใ‚Œใพใ™ใ€‚ +่ค‡ๆ•ฐใฎไพๅญ˜้–ขไฟ‚ใ‚„ [ใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} ใ‚’ (้–ขๆ•ฐๅฎš็พฉใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ) ็›ธไบ’ใซ่ฆๆฑ‚ใ•ใ›ใ‚‰ใ‚Œใพใ™ใ€‚ใใฎไธ€้ƒจใฏ `async def`ใ€ไป–ใฏ้€šๅธธใฎ `def` ใงไฝœใ‚‰ใ‚Œใฆใ„ใฆใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚้€šๅธธใฎ `def` ใงไฝœใ‚‰ใ‚ŒใŸใ‚‚ใฎใฏใ€Œawaitใ€ใ•ใ‚Œใ‚‹ไปฃใ‚ใ‚Šใซใ€ๅค–้ƒจใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใ‹ใ‚‰ใ‚นใƒฌใƒƒใƒ‰ไธŠใงๅ‘ผใณๅ‡บใ•ใ‚Œใพใ™ใ€‚ -### ใใฎไป–ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐ +### ใใฎไป–ใฎใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐ { #other-utility-functions } -ใ‚ใชใŸใŒ็›ดๆŽฅๅ‘ผใณๅ‡บใ™ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใฏ้€šๅธธใฎ `def` ใพใŸใฏ `async def` ใงไฝœๆˆใงใใ€FastAPIใฏๅ‘ผใณๅ‡บใ™ๆ–นๆณ•ใซๅฝฑ้Ÿฟใ‚’ไธŽใˆใพใ›ใ‚“ใ€‚ +ใ‚ใชใŸใŒ็›ดๆŽฅๅ‘ผใณๅ‡บใ™ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใฏใ€้€šๅธธใฎ `def` ใงใ‚‚ `async def` ใงใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚FastAPI ใฏใใฎๅ‘ผใณๅ‡บใ—ๆ–นใซๅฝฑ้Ÿฟใ‚’ไธŽใˆใพใ›ใ‚“ใ€‚ -ใ“ใ‚Œใฏใ€FastAPIใŒๅ‘ผใณๅ‡บใ™้–ขๆ•ฐใจๅฏพ็…ง็š„ใงใ™: *path operation ้–ขๆ•ฐ*ใจไพๅญ˜้–ขไฟ‚ใ€‚ +ใ“ใ‚Œใฏใ€FastAPI ใŒใ‚ใชใŸใฎไปฃใ‚ใ‚Šใซๅ‘ผใณๅ‡บใ™้–ขๆ•ฐ (ใ™ใชใ‚ใก *path operation ้–ขๆ•ฐ* ใจไพๅญ˜้–ขไฟ‚) ใจใฏๅฏพ็…ง็š„ใงใ™ใ€‚ -ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใŒ `def` ใ‚’ไฝฟ็”จใ—ใŸ้€šๅธธใฎ้–ขๆ•ฐใงใ‚ใ‚‹ๅ ดๅˆใ€ใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงใฏใชใ็›ดๆŽฅ (ใ‚ณใƒผใƒ‰ใง่จ˜่ฟฐใ—ใŸใจใŠใ‚Šใซ) ๅ‘ผใณๅ‡บใ•ใ‚Œใพใ™ใ€‚้–ขๆ•ฐใŒ `async def` ใ‚’ไฝฟ็”จใ—ใฆไฝœๆˆใ•ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๅ‘ผใณๅ‡บใ™้š›ใซ `await` ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ +ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใŒ `def` ใฎ้€šๅธธ้–ขๆ•ฐใงใ‚ใ‚Œใฐใ€(ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใซๆ›ธใ„ใŸใจใŠใ‚Šใซ) ็›ดๆŽฅๅ‘ผใณๅ‡บใ•ใ‚Œใ€ใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงใฏๅฎŸ่กŒใ•ใ‚Œใพใ›ใ‚“ใ€‚้–ขๆ•ฐใŒ `async def` ใงไฝœใ‚‰ใ‚Œใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใใฎ้–ขๆ•ฐใ‚’ๅ‘ผใถใจใใซ `await` ใ™ในใใงใ™ใ€‚ --- -็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€ใ“ใ‚Œใ‚‰ใฏ้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ‚ใ‚Šใ€ๆคœ็ดขใ—ใฆ่พฟใ‚Š็€ใ„ใŸๅ ดๅˆใฏๅฝน็ซ‹ใคใงใ—ใ‚‡ใ†ใ€‚ +็นฐใ‚Š่ฟ”ใ—ใซใชใ‚Šใพใ™ใŒใ€ใ“ใ‚Œใ‚‰ใฏ้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ€่ฉฒๅฝ“ไบ‹้ …ใ‚’ๆคœ็ดขใ—ใฆใ“ใ“ใซใŸใฉใ‚Š็€ใ„ใŸๅ ดๅˆใซใฏๅฝน็ซ‹ใคใงใ—ใ‚‡ใ†ใ€‚ -ใใ‚Œไปฅๅค–ใฎๅ ดๅˆใฏใ€ไธŠ่จ˜ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎใ‚ฌใ‚คใƒ‰ใƒฉใ‚คใƒณใงๅ•้กŒใชใ„ใฏใšใงใ™: ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸใ€‚ +ใใ‚Œไปฅๅค–ใฎๅ ดๅˆใฏใ€ไธŠใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎใ‚ฌใ‚คใƒ‰ใƒฉใ‚คใƒณใซๅพ“ใˆใฐๅๅˆ†ใงใ™: ๆ€ฅใ„ใงใ„ใพใ™ใ‹๏ผŸใ€‚ diff --git a/docs/ja/docs/deployment/cloud.md b/docs/ja/docs/deployment/cloud.md new file mode 100644 index 0000000000..17699cdca6 --- /dev/null +++ b/docs/ja/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใธใฎ FastAPI ใƒ‡ใƒ—ใƒญใ‚ค { #deploy-fastapi-on-cloud-providers } + +FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏใ€ๅฎŸ่ณช็š„ใซใฉใฎใ‚ˆใ†ใชใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใงใ‚‚ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ + +ๅคšใใฎๅ ดๅˆใ€ไธป่ฆใชใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใฏ FastAPI ใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใŸใ‚ใฎใ‚ฌใ‚คใƒ‰ใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ + +## FastAPI Cloud { #fastapi-cloud } + +**FastAPI Cloud** ใฏใ€**FastAPI** ใฎไฝœ่€…ใจๅŒใ˜ใƒใƒผใƒ ใซใ‚ˆใฃใฆไฝœใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ + +API ใฎ**ๆง‹็ฏ‰**ใ€**ใƒ‡ใƒ—ใƒญใ‚ค**ใ€**ใ‚ขใ‚ฏใ‚ปใ‚น**ใพใงใฎใƒ—ใƒญใ‚ปใ‚นใ‚’ใ€ๆœ€ๅฐ้™ใฎๆ‰‹้–“ใงๅŠน็އๅŒ–ใ—ใพใ™ใ€‚ + +FastAPI ใงใ‚ขใƒ—ใƒชใ‚’้–‹็™บใ™ใ‚‹ใจใใจๅŒใ˜**้–‹็™บ่€…ไฝ“้จ“**ใ‚’ใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใธใฎ**ใƒ‡ใƒ—ใƒญใ‚ค**ใซใ‚‚ใ‚‚ใŸใ‚‰ใ—ใพใ™ใ€‚๐ŸŽ‰ + +FastAPI Cloud ใฏใ€*FastAPI and friends* ใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎไธป่ฆใชใ‚นใƒใƒณใ‚ตใƒผใ‹ใค่ณ‡้‡‘ๆไพ›ๅ…ƒใงใ™ใ€‚โœจ + +## ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ - ใ‚นใƒใƒณใ‚ตใƒผ { #cloud-providers-sponsors } + +ไป–ใซใ‚‚ใ„ใใคใ‹ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใŒ โœจ [**FastAPI ใ‚’ใ‚นใƒใƒณใ‚ตใƒผใ—ใฆใ„ใพใ™**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจใ€‚๐Ÿ™‡ + +ใใ‚Œใ‚‰ใฎใ‚ฌใ‚คใƒ‰ใ‚’ๅ‚่€ƒใซใ—ใ€ใ‚ตใƒผใƒ“ใ‚นใ‚’่ฉฆใ—ใฆใฟใ‚‹ใฎใ‚‚ใ‚ˆใ„ใงใ—ใ‚‡ใ†: + +* Render +* Railway diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md index 787eb2e73f..501a90bc93 100644 --- a/docs/ja/docs/deployment/concepts.md +++ b/docs/ja/docs/deployment/concepts.md @@ -29,7 +29,6 @@ ## ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS { #security-https } - [ๅ‰ใƒใƒฃใƒ—ใ‚ฟใƒผใฎHTTPSใซใคใ„ใฆ](https.md){.internal-link target=_blank}ใงใฏใ€HTTPSใŒใฉใฎใ‚ˆใ†ใซAPIใ‚’ๆš—ๅทๅŒ–ใ™ใ‚‹ใฎใ‹ใซใคใ„ใฆๅญฆใณใพใ—ใŸใ€‚ ้€šๅธธใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ตใƒผใƒใซใจใฃใฆ**ๅค–้ƒจใฎ**ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใงใ‚ใ‚‹**TLS Termination Proxy**ใซใ‚ˆใฃใฆๆไพ›ใ•ใ‚Œใ‚‹ใ“ใจใŒไธ€่ˆฌ็š„ใงใ™ใ€‚ใ“ใฎใƒ—ใƒญใ‚ญใ‚ทใฏ้€šไฟกใฎๆš—ๅทๅŒ–ใ‚’ๆ‹…ๅฝ“ใ—ใพใ™ใ€‚ @@ -193,7 +192,6 @@ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงใฏใ€Uvicorn ใ‚’ๅฎŸ่กŒใ™ใ‚‹ `fastapi` ใ‚ณ ๅŒใ˜APIใƒ—ใƒญใ‚ฐใƒฉใƒ ใฎ**่ค‡ๆ•ฐใฎใƒ—ใƒญใ‚ปใ‚น**ใ‚’ๅฎŸ่กŒใ™ใ‚‹ๅ ดๅˆใ€ใใ‚Œใ‚‰ใฏไธ€่ˆฌ็š„ใซ**Worker๏ผใƒฏใƒผใ‚ซใƒผ**ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ ### ใƒฏใƒผใ‚ซใƒผใƒปใƒ—ใƒญใ‚ปใ‚น ใจ ใƒใƒผใƒˆ { #worker-processes-and-ports } - [HTTPSใซใคใ„ใฆ](https.md){.internal-link target=_blank}ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ€1ใคใฎใ‚ตใƒผใƒใƒผใง1ใคใฎใƒใƒผใƒˆใจIPใ‚ขใƒ‰ใƒฌใ‚นใฎ็ต„ใฟๅˆใ‚ใ›ใงใƒชใƒƒใ‚นใƒณใงใใ‚‹ใฎใฏ1ใคใฎใƒ—ใƒญใ‚ปใ‚นใ ใ‘ใงใ‚ใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใ„ใพใ™ใงใ—ใ‚‡ใ†ใ‹๏ผŸ diff --git a/docs/ja/docs/deployment/docker.md b/docs/ja/docs/deployment/docker.md index 6c182448c9..883f98c985 100644 --- a/docs/ja/docs/deployment/docker.md +++ b/docs/ja/docs/deployment/docker.md @@ -14,7 +14,7 @@ Linuxใ‚ณใƒณใƒ†ใƒŠใฎไฝฟ็”จใซใฏใ€**ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ**ใ€**ๅๅพฉๅฏ่ƒฝๆ€ง๏ผˆ Dockerfile Preview ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -392,7 +392,7 @@ FastAPI ใŒๅ˜ไธ€ใฎใƒ•ใ‚กใ‚คใƒซใ€ไพ‹ใˆใฐ `./app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฎใชใ„ ใใ†ใ™ใ‚Œใฐใ€`Dockerfile`ใฎไธญใซใƒ•ใ‚กใ‚คใƒซใ‚’ใ‚ณใƒ”ใƒผใ™ใ‚‹ใŸใ‚ใซใ€ๅฏพๅฟœใ™ใ‚‹ใƒ‘ใ‚นใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ ใ‘ใงใ‚ˆใ„ใงใ™๏ผš ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -456,7 +456,7 @@ TraefikใฏDockerใ‚„Kubernetesใชใฉใจ็ตฑๅˆใ•ใ‚Œใฆใ„ใ‚‹ใฎใงใ€ใ‚ณใƒณใƒ†ใƒŠ ## ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ใƒ—ใƒญใ‚ปใ‚นๆ•ฐ { #replication-number-of-processes } -**Kubernetes** ใ‚„ Docker Swarm ใƒขใƒผใƒ‰ใ€Nomadใ€ใ‚ใ‚‹ใ„ใฏ่ค‡ๆ•ฐใฎใƒžใ‚ทใƒณไธŠใงๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใฎๅŒๆง˜ใฎ่ค‡้›‘ใชใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆใƒžใ‚ทใƒณใฎclusterใ‚’ๆง‹ๆˆใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ ๅ„ใ‚ณใƒณใƒ†ใƒŠใง๏ผˆWorkerใ‚’ๆŒใคUvicornใฎใ‚ˆใ†ใช๏ผ‰**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใ‚’ไฝฟ็”จใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€**ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใƒปใƒฌใƒ™ใƒซ**ใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ—ใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ +**Kubernetes** ใ‚„ Docker Swarm ใƒขใƒผใƒ‰ใ€Nomadใ€ใ‚ใ‚‹ใ„ใฏ่ค‡ๆ•ฐใฎใƒžใ‚ทใƒณไธŠใงๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠใ‚’็ฎก็†ใ™ใ‚‹ใŸใ‚ใฎๅŒๆง˜ใฎ่ค‡้›‘ใชใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใฃใฆใƒžใ‚ทใƒณใฎใ‚ฏใƒฉใ‚นใ‚ฟใ‚’ๆง‹ๆˆใ—ใฆใ„ใ‚‹ๅ ดๅˆใ€ ๅ„ใ‚ณใƒณใƒ†ใƒŠใง๏ผˆWorkerใ‚’ๆŒใคUvicornใฎใ‚ˆใ†ใช๏ผ‰**ใƒ—ใƒญใ‚ปใ‚นใƒžใƒใƒผใ‚ธใƒฃ**ใ‚’ไฝฟ็”จใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€**ใ‚ฏใƒฉใ‚นใ‚ฟใƒผใƒปใƒฌใƒ™ใƒซ**ใง**ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ—ใŸใ„ใจๆ€ใ†ใงใ—ใ‚‡ใ†ใ€‚ Kubernetesใฎใ‚ˆใ†ใชๅˆ†ๆ•ฃใ‚ณใƒณใƒ†ใƒŠ็ฎก็†ใ‚ทใ‚นใƒ†ใƒ ใฎ1ใคใฏ้€šๅธธใ€ๅ…ฅใฃใฆใใ‚‹ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ**ใƒญใƒผใƒ‰ใƒใƒฉใƒณใ‚ทใƒณใ‚ฐ**ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใชใŒใ‚‰ใ€**ใ‚ณใƒณใƒ†ใƒŠใฎใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใ‚’ๅ‡ฆ็†ใ™ใ‚‹็ตฑๅˆใ•ใ‚ŒใŸๆ–นๆณ•ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ใ“ใฎใ“ใจใฏใ™ในใฆ**ใ‚ฏใƒฉใ‚นใ‚ฟใƒฌใƒ™ใƒซ**ใซใฆใงใ™ใ€‚ @@ -501,7 +501,7 @@ HTTPSใซไฝฟใ‚ใ‚Œใ‚‹ใ‚‚ใฎใจๅŒใ˜**TLS Termination Proxy**ใ‚ณใƒณใƒใƒผใƒใƒณ ใใฎใ‚ˆใ†ใชๅ ดๅˆใ€`--workers` ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ไฝฟใฃใฆใ€ๅฎŸ่กŒใ—ใŸใ„ใƒฏใƒผใ‚ซใƒผๆ•ฐใ‚’่จญๅฎšใงใใพใ™๏ผš ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/ja/docs/deployment/fastapicloud.md b/docs/ja/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..43d9ce0d02 --- /dev/null +++ b/docs/ja/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +FastAPI Cloud ใซ **ใ‚ณใƒžใƒณใƒ‰1ใค** ใงใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ใพใ ใชใ‚‰ใ‚ฆใ‚งใ‚คใƒ†ใ‚ฃใƒณใ‚ฐใƒชใ‚นใƒˆใซใ”็™ป้Œฒใใ ใ•ใ„ใ€‚๐Ÿš€ + +## ใƒญใ‚ฐใ‚คใƒณ { #login } + +ใ™ใงใซ **FastAPI Cloud** ใ‚ขใ‚ซใ‚ฆใƒณใƒˆใ‚’ใŠๆŒใกใงใ‚ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„๏ผˆใ‚ฆใ‚งใ‚คใƒ†ใ‚ฃใƒณใ‚ฐใƒชใ‚นใƒˆใ‹ใ‚‰ใ”ๆ‹›ๅพ…ใ—ใฆใ„ใพใ™ ๐Ÿ˜‰๏ผ‰ใ€‚ + +ๆฌกใซใƒญใ‚ฐใ‚คใƒณใ—ใพใ™: + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## ใƒ‡ใƒ—ใƒญใ‚ค { #deploy } + +ใงใฏใ€**ใ‚ณใƒžใƒณใƒ‰1ใค** ใงใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใพใ™: + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ไปฅไธŠใงใ™๏ผใใฎ URL ใ‹ใ‚‰ใ‚ขใƒ—ใƒชใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚โœจ + +## FastAPI Cloud ใซใคใ„ใฆ { #about-fastapi-cloud } + +**FastAPI Cloud** ใฏใ€**FastAPI** ใฎไฝœ่€…ใจใƒใƒผใƒ ใซใ‚ˆใฃใฆ้–‹็™บใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ๆœ€ๅฐ้™ใฎๆ‰‹้–“ใง API ใ‚’**ๆง‹็ฏ‰**ใƒป**ใƒ‡ใƒ—ใƒญใ‚ค**ใƒป**ๅˆฉ็”จ**ใงใใ‚‹ใ‚ˆใ†ใซๅทฅ็จ‹ใ‚’็ฐก็ด ๅŒ–ใ—ใพใ™ใ€‚ + +FastAPI ใงใฎ้–‹็™บใจๅŒใ˜**้–‹็™บ่€…ไฝ“้จ“**ใ‚’ใ€ใ‚ฏใƒฉใ‚ฆใƒ‰ใธใฎ**ใƒ‡ใƒ—ใƒญใ‚ค**ใซใ‚‚ใ‚‚ใŸใ‚‰ใ—ใพใ™ใ€‚๐ŸŽ‰ + +ใ•ใ‚‰ใซใ€ใ‚ขใƒ—ใƒชใฎใƒ‡ใƒ—ใƒญใ‚คๆ™‚ใซๅฟ…่ฆใจใชใ‚‹ๅคšใใฎไบ‹้ …ใ‚‚ไปปใ›ใ‚‰ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐ: + +* HTTPS +* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใƒชใ‚ฏใ‚จใ‚นใƒˆใซๅŸบใฅใใ‚ชใƒผใƒˆใ‚นใ‚ฑใƒผใƒชใƒณใ‚ฐไป˜ใ๏ผ‰ +* ใชใฉ + +FastAPI Cloud ใฏใ€*FastAPI and friends* ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซๅฏพใ™ใ‚‹ไธป่ฆใ‚นใƒใƒณใ‚ตใƒผใ‹ใค่ณ‡้‡‘ๆไพ›ๅ…ƒใงใ™ใ€‚โœจ + +## ไป–ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผใธใฎใƒ‡ใƒ—ใƒญใ‚ค { #deploy-to-other-cloud-providers } + +FastAPI ใฏใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใงๆจ™ๆบ–ใซๅŸบใฅใ„ใฆใ„ใพใ™ใ€‚ใŠๅฅฝใฟใฎไปปๆ„ใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผใซ FastAPI ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใงใใพใ™ใ€‚ + +ๅ„ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผใฎใ‚ฌใ‚คใƒ‰ใซๅพ“ใฃใฆ FastAPI ใ‚ขใƒ—ใƒชใ‚’ใƒ‡ใƒ—ใƒญใ‚คใ—ใฆใใ ใ•ใ„ใ€‚๐Ÿค“ + +## ่‡ชๅˆ†ใฎใ‚ตใƒผใƒใƒผใธใฎใƒ‡ใƒ—ใƒญใ‚ค { #deploy-your-own-server } + +ใ“ใฎ**ใƒ‡ใƒ—ใƒญใ‚ค**ใ‚ฌใ‚คใƒ‰ใฎๅพŒๅŠใงใฏ่ฉณ็ดฐใ‚‚่งฃ่ชฌใ—ใพใ™ใ€‚ไฝ•ใŒ่ตทใใฆใ„ใ‚‹ใฎใ‹ใ€ไฝ•ใŒๅฟ…่ฆใชใฎใ‹ใ€ใใ—ใฆ่‡ชๅˆ†ใฎใ‚ตใƒผใƒใƒผใ‚’ๅซใ‚ใฆ FastAPI ใ‚ขใƒ—ใƒชใ‚’่‡ชๅŠ›ใงใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๆ–นๆณ•ใŒๅˆ†ใ‹ใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚๐Ÿค“ diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index d5a6daf0c0..8e588aadc3 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -28,7 +28,7 @@ HTTPSใฏๅ˜ใซใ€Œๆœ‰ๅŠนใ€ใ‹ใ€Œ็„กๅŠนใ€ใ‹ใงๆฑบใพใ‚‹ใ‚‚ใฎใ ใจๆ€ใ„ใŒใก * **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ**ใ€**IPใ‚ขใƒ‰ใƒฌใ‚นใ”ใจใซ1ใคใฎHTTPS่จผๆ˜Žๆ›ธ**ใ—ใ‹ๆŒใฆใชใ„ใ“ใจใซใชใ‚Šใพใ™ใ€‚ * ใ“ใ‚Œใฏใ€ใ‚ตใƒผใƒใƒผใฎ่ฆๆจกใ‚„ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่ฆๆจกใซๅฏ„ใ‚Šใพใ›ใ‚“ใ€‚ * ใ—ใ‹ใ—ใ€ใ“ใ‚Œใซใฏ**่งฃๆฑบ็ญ–**ใŒใ‚ใ‚Šใพใ™ใ€‚ -* **TLS**ใƒ—ใƒญใƒˆใ‚ณใƒซ(HTTPใฎๅ‰ใซใ€TCPใƒฌใƒ™ใƒซใงๆš—ๅทๅŒ–ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ‚‚ใฎ)ใซใฏใ€**SNI**ใจๅ‘ผใฐใ‚Œใ‚‹**ๆ‹กๅผต**ใŒใ‚ใ‚Šใพใ™ใ€‚ +* **TLS**ใƒ—ใƒญใƒˆใ‚ณใƒซ(HTTPใฎๅ‰ใซใ€TCPใƒฌใƒ™ใƒซใงๆš—ๅทๅŒ–ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ‚‚ใฎ)ใซใฏใ€**SNI**ใจๅ‘ผใฐใ‚Œใ‚‹**ๆ‹กๅผต**ใŒใ‚ใ‚Šใพใ™ใ€‚ * ใ“ใฎSNIๆ‹กๅผตๆฉŸ่ƒฝใซใ‚ˆใ‚Šใ€1ใคใฎใ‚ตใƒผใƒใƒผ๏ผˆ**ๅ˜ไธ€ใฎIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใค๏ผ‰ใŒ**่ค‡ๆ•ฐใฎHTTPS่จผๆ˜Žๆ›ธ**ใ‚’ๆŒใกใ€**่ค‡ๆ•ฐใฎHTTPSใƒ‰ใƒกใ‚คใƒณ/ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ**ใซใ‚ตใƒผใƒ“ใ‚นใ‚’ๆไพ›ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ * ใ“ใ‚ŒใŒๆฉŸ่ƒฝใ™ใ‚‹ใŸใ‚ใซใฏใ€**ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใงใƒชใƒƒใ‚นใƒณใ—ใฆใ„ใ‚‹ใ€ใ‚ตใƒผใƒใƒผไธŠใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹**ๅ˜ไธ€ใฎ**ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ(ใƒ—ใƒญใ‚ฐใƒฉใƒ )ใŒใ€ใ‚ตใƒผใƒใƒผๅ†…ใฎ**ใ™ในใฆใฎHTTPS่จผๆ˜Žๆ›ธ**ใ‚’ๆŒใฃใฆใ„ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ * ใ‚ปใ‚ญใƒฅใ‚ขใชๆŽฅ็ถšใ‚’ๅ–ๅพ—ใ—ใŸ**ๅพŒ**ใงใ‚‚ใ€้€šไฟกใƒ—ใƒญใƒˆใ‚ณใƒซใฏ**HTTPใฎใพใพ**ใงใ™ใ€‚ @@ -66,7 +66,7 @@ Let's Encryptไปฅๅ‰ใฏใ€ใ“ใ‚Œใ‚‰ใฎ**HTTPS่จผๆ˜Žๆ›ธ**ใฏไฟก้ ผใงใใ‚‹็ฌฌไธ‰ ใ‚นใƒ†ใƒƒใƒ—ใฎๅˆใ‚ใฏใ€**ใƒ‰ใƒกใ‚คใƒณๅ**ใ‚’**ๅ–ๅพ—ใ™ใ‚‹ใ“ใจ**ใ‹ใ‚‰ๅง‹ใพใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใใฎๅพŒใ€DNSใ‚ตใƒผใƒใƒผ๏ผˆใŠใใ‚‰ใๅŒใ˜ใ‚ฏใƒฉใ‚ฆใƒ‰ใƒ—ใƒญใƒใ‚คใƒ€ใƒผ๏ผ‰ใซ่จญๅฎšใ—ใพใ™ใ€‚ -ใŠใใ‚‰ใใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผ๏ผˆไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‹ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใ‚’ๆ‰‹ใซๅ…ฅใ‚Œใ€fixed **ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใคใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใŠใใ‚‰ใใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚ตใƒผใƒใƒผ๏ผˆไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ‹ใใ‚Œใซ้กžใ™ใ‚‹ใ‚‚ใฎใ‚’ๆ‰‹ใซๅ…ฅใ‚Œใ€ๅ›บๅฎšใฎ **ใƒ‘ใƒ–ใƒชใƒƒใ‚ฏIPใ‚ขใƒ‰ใƒฌใ‚น**ใ‚’ๆŒใคใ“ใจใซใชใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ DNSใ‚ตใƒผใƒใƒผใงใฏใ€**ๅ–ๅพ—ใ—ใŸใƒ‰ใƒกใ‚คใƒณ**ใ‚’ใ‚ใชใŸใฎใ‚ตใƒผใƒใƒผใฎใƒ‘ใƒ—ใƒชใƒƒใ‚ฏ**IPใ‚ขใƒ‰ใƒฌใ‚น**ใซๅ‘ใ‘ใ‚‹ใƒฌใ‚ณใƒผใƒ‰๏ผˆใ€Œ`A record`ใ€๏ผ‰ใ‚’่จญๅฎšใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/deployment/manually.md b/docs/ja/docs/deployment/manually.md index da382a9c53..1931cd87e5 100644 --- a/docs/ja/docs/deployment/manually.md +++ b/docs/ja/docs/deployment/manually.md @@ -1,54 +1,108 @@ -# ๆ‰‹ๅ‹•ใƒ‡ใƒ—ใƒญใ‚ค +# ใ‚ตใƒผใƒใƒผใ‚’ๆ‰‹ๅ‹•ใงๅฎŸ่กŒใ™ใ‚‹ { #run-a-server-manually } -**FastAPI** ใ‚’ๆ‰‹ๅ‹•ใงใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ +## fastapi run ใ‚ณใƒžใƒณใƒ‰ใ‚’ไฝฟใ† { #use-the-fastapi-run-command } -ไปฅไธ‹ใฎๆง˜ใชASGIๅฏพๅฟœใฎใ‚ตใƒผใƒใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: - -//// tab | Uvicorn - -* Uvicorn, uvloopใจhttptoolsใ‚’ๅŸบใซใ—ใŸ้ซ˜้€ŸใชASGIใ‚ตใƒผใƒใ€‚ +็ต่ซ–ใจใ—ใฆใ€FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆไพ›ใ™ใ‚‹ใซใฏ `fastapi run` ใ‚’ไฝฟใ„ใพใ™:
```console -$ pip install "uvicorn[standard]" +$ fastapi run main.py ----> 100% + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) ```
-//// +ใ“ใ‚Œใงใปใจใ‚“ใฉใฎใ‚ฑใƒผใ‚นใฏๅ‹•ไฝœใ—ใพใ™ใ€‚๐Ÿ˜Ž -/// tip | ่ฑ†็Ÿฅ่ญ˜ +ใ“ใฎใ‚ณใƒžใƒณใƒ‰ใฏใ€ใŸใจใˆใฐใ‚ณใƒณใƒ†ใƒŠใ‚„ใ‚ตใƒผใƒใƒผๅ†…ใง **FastAPI** ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ™ใ‚‹ใฎใซไฝฟใˆใพใ™ใ€‚ -`standard` ใ‚’ๅŠ ใˆใ‚‹ใ“ใจใงใ€UvicornใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใ€ใ„ใใคใ‹ใฎๆŽจๅฅจใ•ใ‚Œใ‚‹ไพๅญ˜้–ขไฟ‚ใ‚’ๅˆฉ็”จใ™ใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ +## ASGIใ‚ตใƒผใƒใƒผ { #asgi-servers } -ใ“ใ‚Œใซใฏใ€`asyncio` ใฎ้ซ˜ๆ€ง่ƒฝใชๅฎŒๅ…จไบ’ๆ›ๅ“ใงใ‚ใ‚‹ `uvloop` ใŒๅซใพใ‚Œใ€ไธฆ่กŒๅ‡ฆ็†ใฎใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใŒๅคงๅน…ใซๅ‘ไธŠใ—ใพใ™ใ€‚ +ๅฐ‘ใ—่ฉณใ—ใ่ฆ‹ใฆใ„ใใพใ™ใ€‚ -/// +FastAPI ใฏใ€Python ใฎ Web ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใจใ‚ตใƒผใƒใƒผใฎใŸใ‚ใฎๆจ™ๆบ–ใงใ‚ใ‚‹ ASGI ใ‚’ไฝฟใ„ใพใ™ใ€‚FastAPI ใฏ ASGI Web ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ + +ใƒชใƒขใƒผใƒˆใฎใ‚ตใƒผใƒใƒผใƒžใ‚ทใƒณใง **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใ‚„ไป–ใฎ ASGI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผ‰ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใฎใซไธปใซๅฟ…่ฆใชใฎใฏ **Uvicorn** ใฎใ‚ˆใ†ใช ASGI ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ™ใ€‚ใ“ใ‚Œใฏ `fastapi` ใ‚ณใƒžใƒณใƒ‰ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +ไป–ใซใ‚‚ใ„ใใคใ‹ใฎ้ธๆŠž่‚ขใŒใ‚ใ‚Šใพใ™: + +* Uvicorn: ้ซ˜ๆ€ง่ƒฝใช ASGI ใ‚ตใƒผใƒใƒผใ€‚ +* Hypercorn: HTTP/2 ใ‚„ Trio ใซๅฏพๅฟœใ™ใ‚‹ ASGI ใ‚ตใƒผใƒใƒผใชใฉใ€‚ +* Daphne: Django Channels ใฎใŸใ‚ใซไฝœใ‚‰ใ‚ŒใŸ ASGI ใ‚ตใƒผใƒใƒผใ€‚ +* Granian: Python ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ‘ใ‘ใฎ Rust ่ฃฝ HTTP ใ‚ตใƒผใƒใƒผใ€‚ +* NGINX Unit: ่ปฝ้‡ใงๅคš็”จ้€”ใช Web ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใƒฉใƒณใ‚ฟใ‚คใƒ ใ€‚ + +## ใ‚ตใƒผใƒใƒผใƒžใ‚ทใƒณใจใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ  { #server-machine-and-server-program } + +ๅ็งฐใซ้–ขใ™ใ‚‹ๅฐใ•ใชๆณจๆ„็‚นใŒใ‚ใ‚Šใพใ™ใ€‚๐Ÿ’ก + +ใ€Œใ‚ตใƒผใƒใƒผใ€ใจใ„ใ†่จ€่‘‰ใฏใ€ใƒชใƒขใƒผใƒˆ/ใ‚ฏใƒฉใ‚ฆใƒ‰ไธŠใฎใ‚ณใƒณใƒ”ใƒฅใƒผใ‚ฟ๏ผˆ็‰ฉ็†/ไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใจใ€ใใฎใƒžใ‚ทใƒณไธŠใงๅ‹•ไฝœใ—ใฆใ„ใ‚‹ใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆไพ‹: Uvicorn๏ผ‰ใฎไธกๆ–นใ‚’ๆŒ‡ใ™ใฎใซไธ€่ˆฌ็š„ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +ไธ€่ˆฌใซใ€Œใ‚ตใƒผใƒใƒผใ€ใจๆ›ธใ‹ใ‚Œใฆใ„ใ‚‹ใจใใฏใ€ใใฎใฉใกใ‚‰ใ‹ใ‚’ๆŒ‡ใ—ใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚ + +ใƒชใƒขใƒผใƒˆใƒžใ‚ทใƒณใ‚’ๆŒ‡ใ™ๅ ดๅˆใ€ใ€Œใ‚ตใƒผใƒใƒผใ€ใฎใปใ‹ใ€Œใƒžใ‚ทใƒณใ€ใ€ŒVM๏ผˆไปฎๆƒณใƒžใ‚ทใƒณ๏ผ‰ใ€ใ€ŒใƒŽใƒผใƒ‰ใ€ใชใฉใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™ใ€‚ใ„ใšใ‚Œใ‚‚้€šๅธธ Linux ใ‚’ๅฎŸ่กŒใ—ใ€ใใ“ใงใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‹•ใ‹ใ™ใƒชใƒขใƒผใƒˆใƒžใ‚ทใƒณใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ -//// tab | Hypercorn +## ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-the-server-program } -* Hypercorn, HTTP/2ใซใ‚‚ๅฏพๅฟœใ—ใฆใ„ใ‚‹ASGIใ‚ตใƒผใƒใ€‚ +FastAPI ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจใ€ๆœฌ็•ชใ‚ตใƒผใƒใƒผใฎ Uvicorn ใŒๅŒๆขฑใ•ใ‚ŒใฆใŠใ‚Šใ€`fastapi run` ใ‚ณใƒžใƒณใƒ‰ใง่ตทๅ‹•ใงใใพใ™ใ€‚ + +ใŸใ ใ—ใ€ASGI ใ‚ตใƒผใƒใƒผใ‚’ๆ‰‹ๅ‹•ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ใ‚ตใƒผใƒใƒผใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚ + +ไพ‹ใจใ—ใฆใ€Uvicorn ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใซใฏ:
```console -$ pip install hypercorn +$ pip install "uvicorn[standard]" ---> 100% ```
-...ใพใŸใฏใ€ใ“ใ‚Œใ‚‰ไปฅๅค–ใฎASGIใ‚ตใƒผใƒใ€‚ +ไป–ใฎ ASGI ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ‚‚ๅŒๆง˜ใฎๆ‰‹้ †ใงใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ -//// +`standard` ใ‚’ไป˜ใ‘ใ‚‹ใจใ€Uvicorn ใฏๆŽจๅฅจใฎ่ฟฝๅŠ ไพๅญ˜้–ขไฟ‚ใ‚‚ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆไฝฟ็”จใ—ใพใ™ใ€‚ -ใใ—ใฆใ€ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใจๅŒๆง˜ใชๆ–นๆณ•ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ตทๅ‹•ใ—ใฆไธ‹ใ•ใ„ใ€‚ใŸใ ใ—ใ€ไปฅไธ‹ใฎๆง˜ใซ`--reload` ใ‚ชใƒ—ใ‚ทใƒงใƒณใฏไฝฟ็”จใ—ใชใ„ใงไธ‹ใ•ใ„: +ใใฎไธญใซใฏใ€`asyncio` ใฎ้ซ˜ๆ€ง่ƒฝใชใƒ‰ใƒญใƒƒใƒ—ใ‚คใƒณไปฃๆ›ฟใงใ‚ใ‚Šใ€ๅคงใใชไธฆ่กŒๅฎŸ่กŒๆ€ง่ƒฝใฎๅ‘ไธŠใ‚’ใ‚‚ใŸใ‚‰ใ™ `uvloop` ใ‚‚ๅซใพใ‚Œใพใ™ใ€‚ -//// tab | Uvicorn +`pip install "fastapi[standard]"` ใฎใ‚ˆใ†ใซ FastAPI ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸๅ ดๅˆใฏใ€ใ™ใงใซ `uvicorn[standard]` ใ‚‚ๅซใพใ‚Œใพใ™ใ€‚ + +/// + +## ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’่ตทๅ‹• { #run-the-server-program } + +ASGI ใ‚ตใƒผใƒใƒผใ‚’ๆ‰‹ๅ‹•ใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸๅ ดๅˆใ€้€šๅธธใฏ FastAPI ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใ‚คใƒณใƒใƒผใƒˆใ•ใ›ใ‚‹ใŸใ‚ใซใ€็‰นๅˆฅใชๅฝขๅผใฎใ‚คใƒณใƒใƒผใƒˆๆ–‡ๅญ—ๅˆ—ใ‚’ๆธกใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™:
@@ -60,26 +114,44 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
-//// +/// note | ๅ‚™่€ƒ -//// tab | Hypercorn +`uvicorn main:app` ใจใ„ใ†ใ‚ณใƒžใƒณใƒ‰ใฏๆฌกใ‚’ๆŒ‡ใ—ใพใ™: -
+* `main`: ใƒ•ใ‚กใ‚คใƒซ `main.py`๏ผˆPython ใฎใ€Œใƒขใ‚ธใƒฅใƒผใƒซใ€๏ผ‰ใ€‚ +* `app`: `main.py` ๅ†…ใง `app = FastAPI()` ใซใ‚ˆใ‚Šไฝœๆˆใ•ใ‚ŒใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€‚ -```console -$ hypercorn main:app --bind 0.0.0.0:80 +ใ“ใ‚Œใฏๆฌกใจ็ญ‰ไพกใงใ™: -Running on 0.0.0.0:8080 over http (CTRL + C to quit) +```Python +from main import app ``` -
+/// + +ไป–ใฎ ASGI ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ‚‚ๅŒๆง˜ใฎใ‚ณใƒžใƒณใƒ‰ใŒใ‚ใ‚Šใ€่ฉณ็ดฐใฏใใ‚Œใžใ‚Œใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// warning | ๆณจๆ„ + +Uvicorn ใชใฉใฎใ‚ตใƒผใƒใƒผใฏใ€้–‹็™บๆ™‚ใซไพฟๅˆฉใช `--reload` ใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ + +ใ—ใ‹ใ— `--reload` ใฏๅคšใใฎใƒชใ‚ฝใƒผใ‚นใ‚’ๆถˆ่ฒปใ—ใ€ไธๅฎ‰ๅฎšใซใชใ‚‹ใชใฉใฎๆ€ง่ณชใŒใ‚ใ‚Šใพใ™ใ€‚ + +้–‹็™บไธญใซใฏ้žๅธธใซๅฝน็ซ‹ใกใพใ™ใŒใ€ ๆœฌ็•ช็’ฐๅขƒใงใฏไฝฟ็”จใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +/// -//// +## ใƒ‡ใƒ—ใƒญใ‚คใฎๆฆ‚ๅฟต { #deployment-concepts } -ๅœๆญขใ—ใŸๅ ดๅˆใซ่‡ชๅ‹•็š„ใซๅ†่ตทๅ‹•ใ•ใ›ใ‚‹ใƒ„ใƒผใƒซใ‚’่จญๅฎšใ—ใŸใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใ“ใ‚Œใ‚‰ใฎไพ‹ใฏใ€ใ‚ตใƒผใƒใƒผใƒ—ใƒญใ‚ฐใƒฉใƒ ๏ผˆไพ‹: Uvicorn๏ผ‰ใ‚’ๅฎŸ่กŒใ—ใ€ไบ‹ๅ‰ใซๆฑบใ‚ใŸใƒใƒผใƒˆ๏ผˆไพ‹: `80`๏ผ‰ใงใ€ใ™ในใฆใฎ IP๏ผˆ`0.0.0.0`๏ผ‰ใ‚’ใƒชใƒƒใ‚นใƒณใ™ใ‚‹ใ€Œๅ˜ไธ€ใƒ—ใƒญใ‚ปใ‚นใ€ใ‚’่ตทๅ‹•ใ—ใพใ™ใ€‚ -ใ•ใ‚‰ใซใ€Gunicornใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆUvicornใฎใƒžใƒใƒผใ‚ธใƒฃใƒผใจใ—ใฆไฝฟ็”จใ—ใŸใ‚Šใ€่ค‡ๆ•ฐใฎใƒฏใƒผใ‚ซใƒผใงHypercornใ‚’ไฝฟ็”จใ—ใŸใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใ“ใ‚ŒใŒๅŸบๆœฌ็š„ใช่€ƒใˆๆ–นใงใ™ใ€‚ใŸใ ใ—ใ€ๆฌกใฎใ‚ˆใ†ใช่ฟฝๅŠ ไบ‹้ …ใซใ‚‚ๅฏพๅฟœใ—ใŸใใชใ‚‹ใงใ—ใ‚‡ใ†: -ใƒฏใƒผใ‚ซใƒผๆ•ฐใชใฉใฎๅพฎ่ชฟๆ•ดใ‚‚่กŒใ„ใŸใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +* ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ - HTTPS +* ่ตทๅ‹•ๆ™‚ใซๅฎŸ่กŒ +* ๅ†่ตทๅ‹• +* ใƒฌใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆๅฎŸ่กŒใƒ—ใƒญใ‚ปใ‚นๆ•ฐ๏ผ‰ +* ใƒกใƒขใƒช +* ่ตทๅ‹•ๅ‰ใฎไบ‹ๅ‰ใ‚นใƒ†ใƒƒใƒ— -ใ—ใ‹ใ—ใ“ใ‚Œใ‚‰ๅ…จใฆใ‚’ใ‚„ใ‚ใ†ใจใ™ใ‚‹ใจใ€่‡ชๅ‹•็š„ใซใ“ใ‚Œใ‚‰ใ‚’่กŒใ†Dockerใ‚คใƒกใƒผใ‚ธใ‚’ไฝฟใ†ๆ–นใŒๆฅฝใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +ใ“ใ‚Œใ‚‰ใฎๅ„ๆฆ‚ๅฟตใซใคใ„ใฆใฎ่€ƒใˆๆ–นใ‚„ใ€ๅฏพๅ‡ฆใ™ใ‚‹ใŸใ‚ใฎๅ…ทไฝ“ไพ‹ใƒปๆˆฆ็•ฅใ‚’ๆฌกใฎ็ซ ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚๐Ÿš€ diff --git a/docs/ja/docs/environment-variables.md b/docs/ja/docs/environment-variables.md index 45dbfc71fd..4deae70446 100644 --- a/docs/ja/docs/environment-variables.md +++ b/docs/ja/docs/environment-variables.md @@ -153,7 +153,7 @@ Hello World from Python /// tip | ่ฑ†็Ÿฅ่ญ˜ -่ฉณใ—ใใฏ The Twelve-Factor App: Config ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +่ฉณใ—ใใฏ The Twelve-Factor App: ่จญๅฎš ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -291,7 +291,7 @@ $ C:\opt\custompython\bin\python ใ“ใ‚Œใงใ€**็’ฐๅขƒๅค‰ๆ•ฐ**ใจใฏไฝ•ใ‹ใ€Pythonใงใฉใฎใ‚ˆใ†ใซไฝฟ็”จใ™ใ‚‹ใ‹ใซใคใ„ใฆใ€ๅŸบๆœฌ็š„ใช็†่งฃใŒๅพ—ใ‚‰ใ‚ŒใŸใฏใšใงใ™ใ€‚ -็’ฐๅขƒๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏใ€Wikipedia for Environment Variable ใ‚‚ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +็’ฐๅขƒๅค‰ๆ•ฐใซใคใ„ใฆใฎ่ฉณ็ดฐใฏใ€Wikipedia ใฎ็’ฐๅขƒๅค‰ๆ•ฐ ใ‚‚ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ ๅคšใใฎๅ ดๅˆใ€็’ฐๅขƒๅค‰ๆ•ฐใŒใฉใฎใ‚ˆใ†ใซๅฝน็ซ‹ใกใ€ใ™ใใซ้ฉ็”จใงใใ‚‹ใฎใ‹ใฏใ‚ใพใ‚Šๆ˜Ž็ขบใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€้–‹็™บไธญใฎใ•ใพใ–ใพใชใ‚ทใƒŠใƒชใ‚ชใงไฝ•ๅบฆใ‚‚็™ปๅ ดใ™ใ‚‹ใŸใ‚ใ€็ŸฅใฃใฆใŠใใจใ‚ˆใ„ใงใ—ใ‚‡ใ†ใ€‚ diff --git a/docs/ja/docs/fastapi-cli.md b/docs/ja/docs/fastapi-cli.md new file mode 100644 index 0000000000..20cc9c2fb8 --- /dev/null +++ b/docs/ja/docs/fastapi-cli.md @@ -0,0 +1,75 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** ใฏใ€FastAPI ใ‚ขใƒ—ใƒชใฎๆไพ›ใ€FastAPI ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎ็ฎก็†ใชใฉใซไฝฟ็”จใงใใ‚‹ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใƒ—ใƒญใ‚ฐใƒฉใƒ ใงใ™ใ€‚ + +FastAPI ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใจ๏ผˆไพ‹: `pip install "fastapi[standard]"`๏ผ‰ใ€`fastapi-cli` ใจใ„ใ†ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒๅซใพใ‚Œใพใ™ใ€‚ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚ฟใƒผใƒŸใƒŠใƒซใงไฝฟ็”จใ™ใ‚‹ `fastapi` ใ‚ณใƒžใƒณใƒ‰ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + +้–‹็™บ็”จใซ FastAPI ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ™ใ‚‹ใซใฏใ€`fastapi dev` ใ‚ณใƒžใƒณใƒ‰ใ‚’ไฝฟ็”จใงใใพใ™: + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +`fastapi` ใจใ„ใ†ใ‚ณใƒžใƒณใƒ‰ใƒฉใ‚คใƒณใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒ **FastAPI CLI** ใงใ™ใ€‚ + +FastAPI CLI ใฏใ€Python ใƒ—ใƒญใ‚ฐใƒฉใƒ ใธใฎใƒ‘ใ‚น๏ผˆไพ‹: `main.py`๏ผ‰ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€`FastAPI` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น๏ผˆ้€šๅธธใฏ `app`๏ผ‰ใ‚’่‡ชๅ‹•ๆคœๅ‡บใ—ใ€้ฉๅˆ‡ใช import ๆ–นๆณ•ใ‚’ๅˆคๆ–ญใ—ใฆๆไพ›ใ—ใพใ™ใ€‚ + +ๆœฌ็•ช็’ฐๅขƒใงใฏไปฃใ‚ใ‚Šใซ `fastapi run` ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚๐Ÿš€ + +ๅ†…้ƒจ็š„ใซใฏใ€**FastAPI CLI** ใฏ Uvicorn๏ผˆ้ซ˜ๆ€ง่ƒฝใงๆœฌ็•ช้‹็”จๅ‘ใ‘ใฎ ASGI ใ‚ตใƒผใƒใƒผ๏ผ‰ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚๐Ÿ˜Ž + +## `fastapi dev` { #fastapi-dev } + +`fastapi dev` ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€้–‹็™บใƒขใƒผใƒ‰ใŒๆœ‰ๅŠนใซใชใ‚Šใพใ™ใ€‚ + +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€**auto-reload** ใŒๆœ‰ๅŠนใงใ™ใ€‚ใ‚ณใƒผใƒ‰ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใจใ‚ตใƒผใƒใƒผใŒ่‡ชๅ‹•ใงๅ†่ชญใฟ่พผใฟใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏใƒชใ‚ฝใƒผใ‚นใ‚’ๅคšใๆถˆ่ฒปใ—ใ€็„กๅŠนๆ™‚ใ‚ˆใ‚Šๅฎ‰ๅฎšๆ€งใŒไฝŽใใชใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚้–‹็™บๆ™‚ใฎใฟใซไฝฟ็”จใ—ใฆใใ ใ•ใ„ใ€‚ใพใŸใ€IP ใ‚ขใƒ‰ใƒฌใ‚น `127.0.0.1`๏ผˆใƒžใ‚ทใƒณ่‡ช่บซใฎใฟใจ้€šไฟกใ™ใ‚‹ใŸใ‚ใฎ IPใ€`localhost`๏ผ‰ใงๅพ…ใกๅ—ใ‘ใพใ™ใ€‚ + +## `fastapi run` { #fastapi-run } + +`fastapi run` ใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๆœฌ็•ชใƒขใƒผใƒ‰ใง่ตทๅ‹•ใ—ใพใ™ใ€‚ + +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€**auto-reload** ใฏ็„กๅŠนใงใ™ใ€‚ใพใŸใ€IP ใ‚ขใƒ‰ใƒฌใ‚น `0.0.0.0`๏ผˆๅˆฉ็”จๅฏ่ƒฝใชใ™ในใฆใฎ IP ใ‚ขใƒ‰ใƒฌใ‚นใ‚’ๆ„ๅ‘ณใ—ใพใ™๏ผ‰ใงๅพ…ใกๅ—ใ‘ใ‚‹ใŸใ‚ใ€ใใฎใƒžใ‚ทใƒณใจ้€šไฟกใงใใ‚‹ไปปๆ„ใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰ๅ…ฌ้–‹ใ‚ขใ‚ฏใ‚ปใ‚นใŒๅฏ่ƒฝใซใชใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใŸใจใˆใฐใ‚ณใƒณใƒ†ใƒŠๅ†…ใชใฉใ€ๆœฌ็•ช็’ฐๅขƒใงไธ€่ˆฌ็š„ใชๅฎŸ่กŒๆ–นๆณ•ใงใ™ใ€‚ + +ๅคšใใฎๅ ดๅˆ๏ผˆใใ—ใฆๆŽจๅฅจใ•ใ‚Œใ‚‹ใฎใฏ๏ผ‰ใ€ไธŠไฝใซ HTTPS ใ‚’็ต‚็ซฏใ™ใ‚‹ใ€Œtermination proxyใ€ใ‚’็ฝฎใใพใ™ใ€‚ใ“ใ‚Œใฏใ‚ขใƒ—ใƒชใฎใƒ‡ใƒ—ใƒญใ‚คๆ–นๆณ•ใซไพๅญ˜ใ—ใ€ใƒ—ใƒญใƒใ‚คใƒ€ใŒไปฃ่กŒใ™ใ‚‹ๅ ดๅˆใ‚‚ใ‚ใ‚Œใฐใ€่‡ชๅˆ†ใง่จญๅฎšใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +่ฉณใ—ใใฏใ€[ใƒ‡ใƒ—ใƒญใ‚คใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ](deployment/index.md){.internal-link target=_blank}ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index f78eab4303..40a1d2e60d 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -1,54 +1,55 @@ -# ๆฉŸ่ƒฝ +# ๆฉŸ่ƒฝ { #features } -## FastAPIใฎๆฉŸ่ƒฝ +## FastAPIใฎๆฉŸ่ƒฝ { #fastapi-features } -**FastAPI** ใฏไปฅไธ‹ใฎๆฉŸ่ƒฝใ‚’ใ‚‚ใกใพใ™: +**FastAPI** ใฏๆฌกใฎใ‚‚ใฎใ‚’ๆไพ›ใ—ใพใ™: -### ใ‚ชใƒผใƒ—ใƒณใ‚นใ‚ฟใƒณใƒ€ใƒผใƒ‰ๆบ–ๆ‹  +### ใ‚ชใƒผใƒ—ใƒณใ‚นใ‚ฟใƒณใƒ€ใƒผใƒ‰ๆบ–ๆ‹  { #based-on-open-standards } -* APIไฝœๆˆใฎใŸใ‚ใฎOpenAPIใ€‚ใ“ใ‚Œใฏใ€path operationsใฎๅฎฃ่จ€ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒœใƒ‡ใ‚ฃใƒชใ‚ฏใ‚จใ‚นใƒˆใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใชใฉใ‚’ๅซใ‚“ใงใ„ใพใ™ใ€‚ -* JSONใ‚นใ‚ญใƒผใƒžใ‚’ไฝฟ็”จใ—ใŸใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ่‡ชๅ‹•็”Ÿๆˆ๏ผˆOpenAPIใฏJSONใ‚นใ‚ญใƒผใƒžใซๅŸบใฅใ„ใฆใ„ใ‚‹๏ผ‰ใ€‚ -* ็ถฟๅฏ†ใช่ชฟๆŸปใฎ็ตๆžœใ€ไธŠๅฑคใซๅพŒไป˜ใ‘ใ™ใ‚‹ใฎใงใฏใชใใ€ใ“ใ‚Œใ‚‰ใฎๅŸบๆบ–ใซๅŸบใฅใ„ใฆ่จญ่จˆใ•ใ‚Œใพใ—ใŸใ€‚ +* API ไฝœๆˆใฎใŸใ‚ใฎ OpenAPIใ€‚path operationsใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใชใฉใฎๅฎฃ่จ€ใ‚’ๅซใฟใพใ™ใ€‚ +* JSON Schema ใซใ‚ˆใ‚‹ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใฎ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–๏ผˆOpenAPI ่‡ชไฝ“ใŒ JSON Schema ใซๅŸบใฅใ„ใฆใ„ใพใ™๏ผ‰ใ€‚ +* ๅ…ฅๅฟตใช่ชฟๆŸปใฎใ†ใˆใ€ใ“ใ‚Œใ‚‰ใฎๆจ™ๆบ–ใ‚’ไธญๅฟƒใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ๅพŒไป˜ใ‘ใฎใƒฌใ‚คใƒคใƒผใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ * ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๅคšใใฎ่จ€่ชžใง่‡ชๅ‹• **ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰็”Ÿๆˆ** ใŒๅฏ่ƒฝใงใ™ใ€‚ -### ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆ -ๅฏพ่ฉฑ็š„ใชAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใจๆŽข็ดข็š„ใชwebใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚’ๆไพ›ใ—ใพใ™ใ€‚ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฏOpenAPIใ‚’ๅŸบใซใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใ„ใใคใ‹ใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง2ใคๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ +### ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #automatic-docs } -* Swagger UIใงใ€ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชๆŽข็ดขใ‚’ใ—ใชใŒใ‚‰ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใ‹ใ‚‰็›ดๆŽฅAPIใ‚’ๅ‘ผใณๅ‡บใ—ใฆใƒ†ใ‚นใƒˆใŒ่กŒใˆใพใ™ใ€‚ +ๅฏพ่ฉฑ็š„ใช API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใจๆŽข็ดข็š„ใช Web ใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ€‚ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฏ OpenAPI ใซๅŸบใฅใ„ใฆใ„ใ‚‹ใŸใ‚ใ€่ค‡ๆ•ฐใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ‚ใ‚Šใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง 2 ใคๅซใพใ‚Œใพใ™ใ€‚ + +* Swagger UIใ€‚ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใซๆŽข็ดขใ—ใคใคใ€ใƒ–ใƒฉใ‚ฆใ‚ถใ‹ใ‚‰็›ดๆŽฅ API ใ‚’ๅ‘ผใณๅ‡บใ—ใฆใƒ†ใ‚นใƒˆใงใใพใ™ใ€‚ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDocใ‚’ไฝฟ็”จใ—ใŸใ‚‚ใ†ไธ€ใคใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆใ€‚ +* ReDoc ใซใ‚ˆใ‚‹ไปฃๆ›ฟใฎ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ€‚ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### ็พไปฃ็š„ใชPython +### ็พไปฃ็š„ใชPythonใฎใฟ { #just-modern-python } -FastAPIใฎๆฉŸ่ƒฝใฏใ™ในใฆใ€ๆจ™ๆบ–ใฎPython 3.8ๅž‹ๅฎฃ่จ€ใซๅŸบใฅใ„ใฆใ„ใพใ™๏ผˆPydanticใฎๅŠŸ็ธพ๏ผ‰ใ€‚ๆ–ฐใ—ใ„ๆง‹ๆ–‡ใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใŸใ ใฎ็พไปฃ็š„ใชๆจ™ๆบ–ใฎPythonใงใ™ใ€‚ +ใ™ในใฆๆจ™ๆบ–ใฎ **Python ใฎๅž‹** ๅฎฃ่จ€๏ผˆPydantic ใซๆ„Ÿ่ฌ๏ผ‰ใซๅŸบใฅใ„ใฆใ„ใพใ™ใ€‚ๆ–ฐใ—ใ„ๆง‹ๆ–‡ใ‚’ๅญฆใถๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ๆจ™ๆบ–็š„ใงใƒขใƒ€ใƒณใช Python ใ ใ‘ใงใ™ใ€‚ -๏ผˆFastAPIใ‚’ไฝฟ็”จใ—ใชใ„ๅ ดๅˆใงใ‚‚๏ผ‰Pythonใฎๅž‹ใฎไฝฟ็”จๆ–นๆณ•ใซใคใ„ใฆ็ฐกๅ˜ใชๅพฉ็ฟ’ใŒๅฟ…่ฆใชๅ ดๅˆใฏใ€็Ÿญใ„ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ๏ผˆ[Python Types](python-types.md){.internal-link target=_blank}๏ผ‰ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +๏ผˆFastAPI ใ‚’ไฝฟใ‚ใชใ„ๅ ดๅˆใงใ‚‚๏ผ‰Python ใฎๅž‹ใฎไฝฟใ„ๆ–นใ‚’ 2 ๅˆ†ใงๅพฉ็ฟ’ใ—ใŸใ„ๅ ดๅˆใฏใ€็Ÿญใ„ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ [Python Types](python-types.md){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ -ๅž‹ใ‚’ไฝฟ็”จใ—ใŸๆจ™ๆบ–็š„ใชPythonใ‚’่จ˜่ฟฐใ—ใพใ™: +ๅž‹ใ‚’ไฝฟใฃใŸๆจ™ๆบ–็š„ใช Python ใ‚’่จ˜่ฟฐใ—ใพใ™: ```Python from datetime import date from pydantic import BaseModel -# Declare a variable as a str -# and get editor support inside the function +# ๅค‰ๆ•ฐใ‚’ str ใจใ—ใฆๅฎฃ่จ€ +# ใใ—ใฆ้–ขๆ•ฐๅ†…ใงใ‚จใƒ‡ใ‚ฃใ‚ฟๆ”ฏๆดใ‚’ๅ—ใ‘ใ‚‹ def main(user_id: str): return user_id -# A Pydantic model +# Pydantic ใƒขใƒ‡ใƒซ class User(BaseModel): id: int name: str joined: date ``` -ใ“ใ‚Œใฏไปฅไธ‹ใฎใ‚ˆใ†ใซ็”จใ„ใ‚‰ใ‚Œใพใ™: +ใ“ใ‚Œใฏๆฌกใฎใ‚ˆใ†ใซไฝฟใˆใพใ™: ```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") @@ -62,143 +63,139 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` -/// info | ๆƒ…ๅ ฑ +/// info -`**second_user_data` ใฏไปฅไธ‹ใ‚’ๆ„ๅ‘ณใ—ใพใ™๏ผš +`**second_user_data` ใฏๆฌกใฎๆ„ๅ‘ณใงใ™: -`second_user_data`่พžๆ›ธใฎใ‚ญใƒผใจๅ€คใ‚’็›ดๆŽฅใ€ใ‚ญใƒผใจๅ€คใฎๅผ•ๆ•ฐใจใ—ใฆๆธกใ—ใพใ™ใ€‚ใ“ใ‚Œใฏใ€`User(id=4, name="Mary", joined="2018-11-30")`ใจๅŒ็ญ‰ใงใ™ใ€‚ +`second_user_data` ่พžๆ›ธใฎใ‚ญใƒผใจๅ€คใ‚’ใ€ใใฎใพใพใ‚ญใƒผใƒใƒชใƒฅใƒผๅผ•ๆ•ฐใจใ—ใฆๆธกใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ `User(id=4, name="Mary", joined="2018-11-30")` ใจๅŒ็ญ‰ใงใ™ใ€‚ /// -### ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆ +### ใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆ { #editor-support } -ใ™ในใฆใฎใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฏไฝฟใ„ใ‚„ใ™ใ็›ดๆ„Ÿ็š„ใซไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€ใ™ในใฆใฎๆฑบๅฎšใฏ้–‹็™บใ‚’้–‹ๅง‹ใ™ใ‚‹ๅ‰ใงใ‚‚่ค‡ๆ•ฐใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใงใƒ†ใ‚นใƒˆใ•ใ‚Œใ€ๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“ใŒไฟ่จผใ•ใ‚Œใพใ™ใ€‚ +ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏๅ…จไฝ“ใŒไฝฟใ„ใ‚„ใ™ใ็›ดๆ„Ÿ็š„ใซใชใ‚‹ใ‚ˆใ†่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€ๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“ใ‚’็ขบไฟใ™ใ‚‹ใŸใ‚ใ€้–‹็™บ้–‹ๅง‹ๅ‰ใ‹ใ‚‰่ค‡ๆ•ฐใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ‚ใ‚‰ใ‚†ใ‚‹ๅˆคๆ–ญใŒๆคœ่จผใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -ๅ‰ๅ›žใฎPython้–‹็™บ่€…่ชฟๆŸปใงใฏใ€ๆœ€ใ‚‚ไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹ๆฉŸ่ƒฝใŒใ€Œใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใ€ใงใ‚ใ‚‹ใ“ใจใŒๆ˜Žใ‚‰ใ‹ใซใชใ‚Šใพใ—ใŸใ€‚ +Python ้–‹็™บ่€…่ชฟๆŸปใงใฏใ€ๆœ€ใ‚‚ใ‚ˆใไฝฟใ‚ใ‚Œใ‚‹ๆฉŸ่ƒฝใฎ 1 ใคใŒใ€Œใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใ€ใงใ‚ใ‚‹ใ“ใจใŒๆ˜Žใ‚‰ใ‹ใงใ™ใ€‚ -**FastAPI** ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฏใ€ใ“ใฎ่ฆๆฑ‚ใ‚’ๆบ€ใŸใ™ใ“ใจใ‚’ๅŸบๆœฌใจใ—ใฆใ„ใพใ™ใ€‚ใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใฏใฉใ“ใงใ‚‚ๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +**FastAPI** ใฏใใฎ่ฆๆฑ‚ใ‚’ๆบ€ใŸใ™ใ“ใจใ‚’ๅŸบ็›คใซใ—ใฆใ„ใพใ™ใ€‚ใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใฏใฉใ“ใงใ‚‚ๆฉŸ่ƒฝใ—ใพใ™ใ€‚ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซๆˆปใ‚‹ๅฟ…่ฆใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใŒใฉใฎใ‚ˆใ†ใซๅฝน็ซ‹ใคใ‹ใ‚’ไปฅไธ‹ใซ็คบใ—ใพใ™: +ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒใฉใฎใ‚ˆใ†ใซๅฝน็ซ‹ใคใ‹ใฎไพ‹ใงใ™: -* Visual Studio Codeใฎๅ ดๅˆ: +* Visual Studio Code ใฎๅ ดๅˆ: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* PyCharmใฎๅ ดๅˆ: +* PyCharm ใฎๅ ดๅˆ: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -ไปฅๅ‰ใฏไธๅฏ่ƒฝใ ใจ่€ƒใˆใฆใ„ใŸใ‚ณใƒผใƒ‰ใงใ•ใˆ่ฃœๅฎŒใ•ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใฎJSONใƒœใƒ‡ใ‚ฃ๏ผˆใƒใ‚นใƒˆใ•ใ‚Œใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹๏ผ‰ๅ†…ใฎ `price`ใ‚ญใƒผใงใ™ใ€‚ - -้–“้•ใฃใŸใ‚ญใƒผๅใ‚’ๅ…ฅๅŠ›ใ—ใŸใ‚Šใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ้–“ใ‚’่กŒใๆฅใ—ใŸใ‚Šใ€ไธŠไธ‹ใซใ‚นใ‚ฏใƒญใƒผใƒซใ—ใฆ`username`ใจ`user_name`ใฎใฉใกใ‚‰ใ‚’ไฝฟ็”จใ—ใŸใ‹่ชฟในใŸใ‚Šใ™ใ‚‹ๅฟ…่ฆใฏใ‚‚ใ†ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ - -### ็ฐกๆฝ” +ไปฅๅ‰ใฏไธๅฏ่ƒฝใ ใจๆ€ใฃใฆใ„ใŸใ‚ณใƒผใƒ‰ใงใ‚‚่ฃœๅฎŒใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๅฑŠใ๏ผˆใƒใ‚นใƒˆใ•ใ‚Œใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹๏ผ‰JSON ใƒœใƒ‡ใ‚ฃๅ†…ใฎ `price` ใ‚ญใƒผใชใฉใงใ™ใ€‚ -ใ™ในใฆใซ้ฉๅˆ‡ใช**ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ**ใŒใ‚ใ‚Šใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎๆง‹ๆˆใŒใงใใพใ™ใ€‚ๅฟ…่ฆใชใ“ใจใ‚’ๅฎŸ่กŒใ—ใ€ๅฟ…่ฆใชAPIใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’่ชฟๆ•ดใงใใพใ™ใ€‚ +ใ‚‚ใ†้–“้•ใฃใŸใ‚ญใƒผๅใ‚’ๅ…ฅๅŠ›ใ—ใŸใ‚Šใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่กŒใๆฅใ—ใŸใ‚Šใ€ไธŠไธ‹ใซใ‚นใ‚ฏใƒญใƒผใƒซใ—ใฆๆœ€็ต‚็š„ใซ `username` ใจ `user_name` ใฎใฉใกใ‚‰ใ‚’ไฝฟใฃใŸใฎใ‹ๆŽขใ™ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใŸใ ใ—ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใ‚‚ใ™ในใฆ **ใ†ใพใใ„ใใพใ™**ใ€‚ +### ็ฐกๆฝ” { #short } -### ๆคœ่จผ +ใ™ในใฆใซๅฆฅๅฝ“ใช **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ** ใŒใ‚ใ‚Šใ€ใฉใ“ใงใ‚‚ใ‚ชใƒ—ใ‚ทใƒงใƒณใงๆง‹ๆˆใงใใพใ™ใ€‚ๅฟ…่ฆใซๅฟœใ˜ใฆใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅพฎ่ชฟๆ•ดใ—ใฆใ€ๆฑ‚ใ‚ใ‚‹ API ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ -* ไปฅไธ‹ใฎๆง˜ใชใ€ใปใจใ‚“ใฉใฎ๏ผˆใ™ในใฆใฎ๏ผŸ๏ผ‰Python **ใƒ‡ใƒผใ‚ฟๅž‹**ใฎๆคœ่จผ: - * JSONใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆ`dict`๏ผ‰ - * ้ …็›ฎใฎๅž‹ใ‚’ๅฎš็พฉใ™ใ‚‹JSON้…ๅˆ—๏ผˆ`list`๏ผ‰ - * ๆœ€ๅฐ้•ทใจๆœ€ๅคง้•ทใฎใ‚ใ‚‹ๆ–‡ๅญ—ๅˆ—๏ผˆ`str`๏ผ‰ใƒ•ใ‚ฃใƒผใƒซใƒ‰ - * ๆœ€ๅฐๅ€คใจๆœ€ๅคงๅ€คใฎใ‚ใ‚‹ๆ•ฐๅ€ค๏ผˆ`int`ใ€` float`๏ผ‰ +ใ—ใ‹ใ—ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใพใพใงใ‚‚ใ€ใ™ในใฆ **ใ†ใพใๅ‹•ใใพใ™**ใ€‚ -* ใ‚ˆใ‚Šใ‚จใ‚ญใ‚พใƒใƒƒใ‚ฏใชๅž‹ใฎๆคœ่จผ๏ผš - * URL - * Eใƒกใƒผใƒซ - * UUID - * ...ใใฎไป– +### ๆคœ่จผ { #validation } -ใ™ในใฆใฎๆคœ่จผใฏใ€็ขบ็ซ‹ใ•ใ‚ŒใŸๅ …็‰ขใช **Pydantic** ใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใพใ™ใ€‚ +* ใปใจใ‚“ใฉ๏ผˆใ‚ใ‚‹ใ„ใฏใ™ในใฆ๏ผŸ๏ผ‰ใฎ Python ใฎ **ใƒ‡ใƒผใ‚ฟๅž‹** ใซๅฏพใ™ใ‚‹ๆคœ่จผ: + * JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆ`dict`๏ผ‰ใ€‚ + * ้ …็›ฎใฎๅž‹ใ‚’ๅฎš็พฉใ™ใ‚‹ JSON ้…ๅˆ—๏ผˆ`list`๏ผ‰ใ€‚ + * ๆ–‡ๅญ—ๅˆ—๏ผˆ`str`๏ผ‰ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๆœ€ๅฐ/ๆœ€ๅคง้•ทใ€‚ + * ๆ•ฐๅ€ค๏ผˆ`int`ใ€`float`๏ผ‰ใฎๆœ€ๅฐ/ๆœ€ๅคงๅ€คใ€ใชใฉใ€‚ -### ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผ +* ใ‚ˆใ‚Šใ‚จใ‚ญใ‚พใƒใƒƒใ‚ฏใชๅž‹ใฎๆคœ่จผ: + * URLใ€‚ + * Emailใ€‚ + * UUIDใ€‚ + * ...ใใฎไป–ใ€‚ -ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใŒ็ตฑๅˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใพใŸใฏใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใซใคใ„ใฆใ‚‚ๅฆฅๅ”ใ—ใฆใ„ใพใ›ใ‚“ใ€‚ +ใ™ในใฆใฎๆคœ่จผใฏใ€็ขบ็ซ‹ใ•ใ‚Œๅ …็‰ขใช **Pydantic** ใซใ‚ˆใฃใฆๅ‡ฆ็†ใ•ใ‚Œใพใ™ใ€‚ -ไปฅไธ‹ใฎOpenAPIใงๅฎš็พฉใ•ใ‚Œใฆใ„ใ‚‹ใ™ในใฆใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ‚’ๅซใ‚€: +### ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผ { #security-and-authentication } -* HTTPใƒ™ใƒผใ‚ทใƒƒใ‚ฏ -* **OAuth2**๏ผˆ**JWTใƒˆใƒผใ‚ฏใƒณ**ใ‚‚ไฝฟ็”จ๏ผ‰ใ€‚ JWTใ‚’ไฝฟ็”จใ—ใŸOAuth2ใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ๏ผˆ[OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}๏ผ‰ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ -* APIใ‚ญใƒผ๏ผš - * ใƒ˜ใƒƒใƒ€ใƒผ - * ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ - * ใ‚ฏใƒƒใ‚ญใƒผใ€็ญ‰ +ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใŒ็ตฑๅˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚„ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใจใฎๅฆฅๅ”ใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -ใ•ใ‚‰ใซใ€Starletteใฎใ™ในใฆใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆฉŸ่ƒฝใ‚‚ๅซใฟใพใ™๏ผˆ**ใ‚ปใƒƒใ‚ทใƒงใƒณCookie**ใ‚’ๅซใ‚€๏ผ‰ใ€‚ +OpenAPI ใงๅฎš็พฉใ•ใ‚ŒใŸใ™ในใฆใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใพใ™: -ใ“ใ‚Œใ‚‰ใฏใ€ใ‚ทใ‚นใƒ†ใƒ ใ€ใƒ‡ใƒผใ‚ฟใ‚นใƒˆใ‚ขใ€ใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใชใฉใจ็ฐกๅ˜ใซ็ตฑๅˆใงใใ‚‹ๅ†ๅˆฉ็”จๅฏ่ƒฝใชใƒ„ใƒผใƒซใจใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใจใ—ใฆๆง‹็ฏ‰ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +* HTTP Basicใ€‚ +* **OAuth2**๏ผˆ**JWT ใƒˆใƒผใ‚ฏใƒณ** ใ‚‚ๅฏ๏ผ‰ใ€‚ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ [JWT ใ‚’็”จใ„ใŸ OAuth2](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +* API ใ‚ญใƒผ๏ผˆไปฅไธ‹ใฎๅ ดๆ‰€๏ผ‰: + * ใƒ˜ใƒƒใƒ€ใƒผใ€‚ + * ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ + * ใ‚ฏใƒƒใ‚ญใƒผใ€ใชใฉใ€‚ -### ไพๅญ˜ๆ€งใฎๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰ +ใ•ใ‚‰ใซใ€Starlette ใฎใ™ในใฆใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆฉŸ่ƒฝ๏ผˆ**ใ‚ปใƒƒใ‚ทใƒงใƒณ Cookie** ใ‚’ๅซใ‚€๏ผ‰ใ‚‚ๅˆฉ็”จใงใใพใ™ใ€‚ -FastAPIใซใฏ้žๅธธใซไฝฟใ„ใ‚„ใ™ใใ€้žๅธธใซๅผทๅŠ›ใชไพๅญ˜ๆ€งใฎๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใ‚’ๅ‚™ใˆใฆใ„ใพใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฏใ™ในใฆๅ†ๅˆฉ็”จๅฏ่ƒฝใชใƒ„ใƒผใƒซใ‚„ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใจใ—ใฆๆง‹็ฏ‰ใ•ใ‚ŒใฆใŠใ‚Šใ€ใ‚ทใ‚นใƒ†ใƒ ใ€ใƒ‡ใƒผใ‚ฟใ‚นใƒˆใ‚ขใ€ใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซ/NoSQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น็ญ‰ใจๅฎนๆ˜“ใซ็ตฑๅˆใงใใพใ™ใ€‚ -* ไพๅญ˜้–ขไฟ‚ใงใ•ใˆใ‚‚ไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใคใ“ใจใŒใงใใ€้šŽๅฑคใพใŸใฏ **ไพๅญ˜้–ขไฟ‚ใฎ"ใ‚ฐใƒฉใƒ•"** ใ‚’ไฝœๆˆใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +### ไพๅญ˜ๆ€งใฎๆณจๅ…ฅ { #dependency-injection } -* ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใซใ‚ˆใฃใฆใ™ในใฆ**่‡ชๅ‹•็š„ใซๅ‡ฆ็†**ใ•ใ‚Œใพใ™ใ€‚ -* ใ™ในใฆใฎไพๅญ˜้–ขไฟ‚ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใฎใƒ‡ใƒผใ‚ฟใ‚’่ฆ่ซ‹ใงใใฆใ€**path operationsใฎๅˆถ็ด„ใจ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ๆ‹กๅผตใงใใพใ™**ใ€‚ -* ไพๅญ˜้–ขไฟ‚ใงๅฎš็พฉใ•ใ‚ŒใŸ *path operation* ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚‚**่‡ชๅ‹•ๆคœ่จผ**ใŒๅฏ่ƒฝใงใ™ใ€‚ -* ่ค‡้›‘ใชใƒฆใƒผใ‚ถใƒผ่ช่จผใ‚ทใ‚นใƒ†ใƒ ใ€**ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆŽฅ็ถš**ใชใฉใฎใ‚ตใƒใƒผใƒˆ -* **ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใชใฉใซๅฏพใ™ใ‚‹ๅฆฅๅ”ใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ใใ‚Œใ‚‰ใ™ในใฆใจ็ฐกๅ˜ใซ็ตฑๅˆใงใใพใ™ใ€‚ +FastAPI ใซใฏใ€้žๅธธใซไฝฟใ„ใ‚„ใ™ใใ€ใ‹ใค้žๅธธใซๅผทๅŠ›ใช ไพๅญ˜ๆ€งใฎๆณจๅ…ฅ ใ‚ทใ‚นใƒ†ใƒ ใŒใ‚ใ‚Šใพใ™ใ€‚ -### ็„กๅˆถ้™ใฎใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ +* ไพๅญ˜้–ขไฟ‚ใฏไพๅญ˜้–ขไฟ‚ใ‚’ๆŒใคใ“ใจใ‚‚ใงใใ€้šŽๅฑคใพใŸใฏ **ไพๅญ˜้–ขไฟ‚ใฎใ€Œใ‚ฐใƒฉใƒ•ใ€** ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ +* ใ™ในใฆใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใซใ‚ˆใฃใฆ**่‡ชๅ‹•็š„ใซๅ‡ฆ็†**ใ•ใ‚Œใพใ™ใ€‚ +* ใ™ในใฆใฎไพๅญ˜้–ขไฟ‚ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ใƒ‡ใƒผใ‚ฟใ‚’่ฆๆฑ‚ใงใใ€*path operation* ใฎๅˆถ็ด„ใจ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’**ๆ‹กๅผต**ใงใใพใ™ใ€‚ +* ไพๅญ˜้–ขไฟ‚ใงๅฎš็พฉใ•ใ‚ŒใŸ *path operation* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใคใ„ใฆใ‚‚**่‡ชๅ‹•ๆคœ่จผ**ใ•ใ‚Œใพใ™ใ€‚ +* ่ค‡้›‘ใชใƒฆใƒผใ‚ถใƒผ่ช่จผใ‚ทใ‚นใƒ†ใƒ ใ€**ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นๆŽฅ็ถš** ใชใฉใฎใ‚ตใƒใƒผใƒˆใ€‚ +* **ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚„ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰็ญ‰ใจใฎๅฆฅๅ”ใฏไธ่ฆ**ใ€‚ใ™ในใฆใจ็ฐกๅ˜ใซ็ตฑๅˆใงใใพใ™ใ€‚ -ไป–ใฎๆ–นๆณ•ใงใฏใ€ใใ‚Œใ‚‰ใ‚’ๅฟ…่ฆใจใ›ใšใ€ๅฟ…่ฆใชใ‚ณใƒผใƒ‰ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟ็”จใ—ใพใ™ใ€‚ +### ็„กๅˆถ้™ใฎใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ { #unlimited-plug-ins } -็ตฑๅˆใฏ้žๅธธใซ็ฐกๅ˜ใซไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซ่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Š๏ผˆไพๅญ˜้–ขไฟ‚ใ‚’็”จใ„ใฆ๏ผ‰ใ€*path operations* ใงไฝฟ็”จใ•ใ‚Œใฆใ„ใ‚‹ใฎใจๅŒใ˜ๆง‹้€ ใจๆง‹ๆ–‡ใ‚’ไฝฟ็”จใ—ใฆใ€2่กŒใฎใ‚ณใƒผใƒ‰ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ +ๅˆฅใฎ่จ€ใ„ๆ–นใ‚’ใ™ใ‚Œใฐใ€ใƒ—ใƒฉใ‚ฐใ‚คใƒณใฏไธ่ฆใงใ€ๅฟ…่ฆใชใ‚ณใƒผใƒ‰ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ†ใ ใ‘ใงใ™ใ€‚ +ใ‚ใ‚‰ใ‚†ใ‚‹็ตฑๅˆใฏ๏ผˆไพๅญ˜้–ขไฟ‚ใ‚’็”จใ„ใฆ๏ผ‰้žๅธธใซ็ฐกๅ˜ใซไฝฟใˆใ‚‹ใ‚ˆใ†่จญ่จˆใ•ใ‚ŒใฆใŠใ‚Šใ€*path operation* ใงไฝฟใ†ใฎใจๅŒใ˜ๆง‹้€ ใจๆง‹ๆ–‡ใงใ€2 ่กŒใฎใ‚ณใƒผใƒ‰ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ็”จใฎใ€Œใƒ—ใƒฉใ‚ฐใ‚คใƒณใ€ใ‚’ไฝœใ‚Œใพใ™ใ€‚ -### ใƒ†ใ‚นใƒˆ +### ใƒ†ใ‚นใƒˆๆธˆใฟ { #tested } -* ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธ 100% -* ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ100%ใฎใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚น -* ๆœฌ็•ชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงไฝฟ็”จใ•ใ‚Œใพใ™ +* 100% ใฎ ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธใ€‚ +* 100% ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณไป˜ใใฎใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚นใ€‚ +* ๆœฌ็•ชใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงไฝฟ็”จใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -## StarletteใฎๆฉŸ่ƒฝ +## StarletteใฎๆฉŸ่ƒฝ { #starlette-features } -**FastAPI**ใฏใ€Starlette ใจๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™๏ผˆใใ—ใฆใƒ™ใƒผใ‚นใซใชใฃใฆใ„ใพใ™๏ผ‰ใ€‚ใ—ใŸใŒใฃใฆใ€่ฟฝๅŠ ใฎStarletteใ‚ณใƒผใƒ‰ใŒใ‚ใ‚Œใฐใ€ใใ‚Œใ‚‚ๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +**FastAPI** ใฏ Starlette ใจๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Š๏ผˆใ‹ใคใใ‚ŒใซๅŸบใฅใ„ใฆใ„ใพใ™๏ผ‰ใ€‚ใใฎใŸใ‚ใ€ๆ‰‹ๅ…ƒใฎ Starlette ใฎ่ฟฝๅŠ ใ‚ณใƒผใƒ‰ใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚ -`FastAPI`ใฏๅฎŸ้š›ใซใฏ`Starlette`ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ใ—ใŸใŒใฃใฆใ€Starletteใ‚’ใ™ใงใซ็Ÿฅใฃใฆใ„ใ‚‹ใ‹ไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใปใจใ‚“ใฉใฎๆฉŸ่ƒฝใŒๅŒใ˜ใ‚ˆใ†ใซๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +`FastAPI` ใฏๅฎŸ้š›ใซใฏ `Starlette` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ™ใ€‚ใ™ใงใซ Starlette ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใ€ใ‚ใ‚‹ใ„ใฏไฝฟใฃใฆใ„ใ‚‹ใชใ‚‰ใ€ใปใจใ‚“ใฉใฎๆฉŸ่ƒฝใฏๅŒใ˜ใ‚ˆใ†ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ -**FastAPI**ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใ‚ˆใ†ใชใ€**Starlette**ใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๅˆฉ็”จใงใใพใ™๏ผˆFastAPIใฏStarletteใ‚’ๅผทๅŒ–ใ—ใŸใ‚‚ใฎใซใ™ใŽใชใ„ใŸใ‚๏ผ‰: +**FastAPI** ใงใฏ **Starlette** ใฎใ™ในใฆใฎๆฉŸ่ƒฝใŒๅˆฉ็”จใงใใพใ™๏ผˆFastAPI ใฏๅผทๅŒ–ใ•ใ‚ŒใŸ Starlette ใซใ™ใŽใพใ›ใ‚“๏ผ‰: -* ่ฆ‹ไบ‹ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ€‚ **NodeJS**ใŠใ‚ˆใณ**Go**ใซๅŒนๆ•ตใ™ใ‚‹ใ€ๆœ€้€ŸใฎPythonใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎ1ใคใงใ™ใ€‚ - -* **WebSocket**ใฎใ‚ตใƒใƒผใƒˆ -* **GraphQL**ใฎใ‚ตใƒใƒผใƒˆ -* ใƒ—ใƒญใ‚ปใ‚นๅ†…ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏ -* ่ตทๅ‹•ใŠใ‚ˆใณใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ‚คใƒ™ใƒณใƒˆ -* `httpx`ใซๅŸบใฅใ„ใฆๆง‹็ฏ‰ใ•ใ‚ŒใŸใƒ†ใ‚นใƒˆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ -* **CORS**ใ€GZipใ€้™็š„ใƒ•ใ‚กใ‚คใƒซใ€ใ‚นใƒˆใƒชใƒผใƒŸใƒณใ‚ฐๅฟœ็ญ” -* **ใ‚ปใƒƒใ‚ทใƒงใƒณใจCookie**ใฎใ‚ตใƒใƒผใƒˆ -* ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธ100% -* ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ100%ใฎใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚น +* ๅœงๅ€’็š„ใชใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ€‚ๅˆฉ็”จๅฏ่ƒฝใชๆœ€้€Ÿใ‚ฏใƒฉใ‚นใฎ Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎ 1 ใคใงใ€**NodeJS** ใ‚„ **Go** ใจๅŒ็ญ‰ใงใ™ใ€‚ +* **WebSocket** ใฎใ‚ตใƒใƒผใƒˆใ€‚ +* ใƒ—ใƒญใ‚ปใ‚นๅ†…ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใ€‚ +* ่ตทๅ‹•ใŠใ‚ˆใณใ‚ทใƒฃใƒƒใƒˆใƒ€ใ‚ฆใƒณใ‚คใƒ™ใƒณใƒˆใ€‚ +* HTTPX ใซๅŸบใฅใใƒ†ใ‚นใƒˆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ€‚ +* **CORS**ใ€GZipใ€้™็š„ใƒ•ใ‚กใ‚คใƒซใ€ใ‚นใƒˆใƒชใƒผใƒŸใƒณใ‚ฐใƒฌใ‚นใƒใƒณใ‚นใ€‚ +* **ใ‚ปใƒƒใ‚ทใƒงใƒณใจ Cookie** ใฎใ‚ตใƒใƒผใƒˆใ€‚ +* ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธ 100%ใ€‚ +* ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ 100% ใฎใ‚ณใƒผใƒ‰ใƒ™ใƒผใ‚นใ€‚ -## Pydanticใฎ็‰นๅพด +## PydanticใฎๆฉŸ่ƒฝ { #pydantic-features } -**FastAPI**ใฏPydantic ใจๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Šใพใ™๏ผˆใใ—ใฆใƒ™ใƒผใ‚นใซใชใฃใฆใ„ใพใ™๏ผ‰ใ€‚ใ—ใŸใŒใฃใฆใ€่ฟฝๅŠ ใฎPydanticใ‚ณใƒผใƒ‰ใŒใ‚ใ‚Œใฐใ€ใใ‚Œใ‚‚ๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +**FastAPI** ใฏ Pydantic ใจๅฎŒๅ…จใซไบ’ๆ›ๆ€งใŒใ‚ใ‚Š๏ผˆใ‹ใคใใ‚ŒใซๅŸบใฅใ„ใฆใ„ใพใ™๏ผ‰ใ€‚ใใฎใŸใ‚ใ€ๆ‰‹ๅ…ƒใฎ Pydantic ใฎ่ฟฝๅŠ ใ‚ณใƒผใƒ‰ใ‚‚ๅ‹•ไฝœใ—ใพใ™ใ€‚ -ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใŸใ‚ใซORMsใ‚„ใ€ODMsใชใฉใฎใ€PydanticใซๅŸบใฅใๅค–้ƒจใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’ๅ‚™ใˆใฆใ„ใพใ™ใ€‚ +Pydantic ใซๅŸบใฅใๅค–้ƒจใƒฉใ‚คใƒ–ใƒฉใƒช๏ผˆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น็”จใฎ ORMใ€ODM ใชใฉ๏ผ‰ใ‚‚ๅซใพใ‚Œใพใ™ใ€‚ -ใ“ใ‚Œใฏใ€ใ™ในใฆใŒ่‡ชๅ‹•็š„ใซๆคœ่จผใ•ใ‚Œใ‚‹ใŸใ‚ใ€ๅคšใใฎๅ ดๅˆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’**ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซ็›ดๆŽฅ**ๆธกใ™ใ“ใจใŒใงใใ‚‹ใจใ„ใ†ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใฆใ„ใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€ใ™ในใฆใŒ่‡ชๅ‹•็š„ใซๆคœ่จผใ•ใ‚Œใ‚‹ใŸใ‚ใ€ๅคšใใฎๅ ดๅˆใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ **ใใฎใพใพใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซ** ๆธกใ›ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -ๅŒใ˜ใ“ใจใŒใใฎ้€†ใซใ‚‚ๅฝ“ใฆใฏใพใ‚Šใ€ๅคšใใฎๅ ดๅˆใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’**ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ็›ดๆŽฅ**ๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ +้€†ๆ–นๅ‘ใ‚‚ๅŒๆง˜ใงใ€ๅคšใใฎๅ ดๅˆใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ๅ–ๅพ—ใ—ใŸใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ **ใใฎใพใพใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ** ๆธกใ›ใพใ™ใ€‚ -**FastAPI**ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€**Pydantic**ใฎใ™ในใฆใฎๆฉŸ่ƒฝใ‚’ๅˆฉ็”จใงใใพใ™๏ผˆFastAPIใŒPydanticใซๅŸบใฅใ„ใฆใ™ในใฆใฎใƒ‡ใƒผใ‚ฟๅ‡ฆ็†ใ‚’่กŒใฃใฆใ„ใ‚‹ใŸใ‚๏ผ‰ใ€‚ +**FastAPI** ใงใฏ **Pydantic** ใฎใ™ในใฆใฎๆฉŸ่ƒฝใŒๅˆฉ็”จใงใใพใ™๏ผˆFastAPI ใฏใƒ‡ใƒผใ‚ฟๅ‡ฆ็†ใฎใ™ในใฆใง Pydantic ใซๅŸบใฅใ„ใฆใ„ใพใ™๏ผ‰: -* **brainfuckใชใ—**๏ผš - * ใ‚นใ‚ญใƒผใƒžๅฎš็พฉใฎใŸใ‚ใฎใƒžใ‚คใ‚ฏใƒญ่จ€่ชžใ‚’ๆ–ฐใŸใซๅญฆ็ฟ’ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ - * Pythonใฎๅž‹ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆ—ขใซPydanticใฎไฝฟ็”จๆ–นๆณ•ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใซ็ญ‰ใ—ใ„ใงใ™ใ€‚ -* ใƒฆใƒผใ‚ถใƒผใฎ **IDE/ใƒชใƒณใ‚ฟใƒผ/ๆ€่€ƒ ใจใ†ใพใ้€ฃๆบใ—ใพใ™**๏ผš - * Pydanticใฎใƒ‡ใƒผใ‚ฟๆง‹้€ ใฏใ€ใƒฆใƒผใ‚ถใƒผใŒๅฎš็พฉใ™ใ‚‹ใ‚ฏใƒฉใ‚นใฎๅ˜ใชใ‚‹ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใงใ‚ใ‚‹ใŸใ‚ใ€ใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใ€ใƒชใƒณใƒ†ใ‚ฃใƒณใ‚ฐใ€mypyใ€ใŠใ‚ˆใณใƒฆใƒผใ‚ถใƒผใฎ็›ดๆ„Ÿใฏใ™ในใฆใ€ๆคœ่จผๆธˆใฟใฎใƒ‡ใƒผใ‚ฟใง้ฉๅˆ‡ใซๆฉŸ่ƒฝใ™ใ‚‹ใฏใšใงใ™ใ€‚ -* **่ค‡้›‘ใชๆง‹้€ **ใ‚’ๆคœ่จผ๏ผš - * ้šŽๅฑค็š„ใชPydanticใƒขใƒ‡ใƒซใ‚„ใ€Pythonใฎใ€Œ`typing`ใ€ใฎใ€Œ`list`ใ€ใจใ€Œ`dict`ใ€ใชใฉใฎๅˆฉ็”จใ€‚ - * ใƒใƒชใƒ‡ใƒผใ‚ฟใƒผใซใ‚ˆใ‚Šใ€่ค‡้›‘ใชใƒ‡ใƒผใ‚ฟใ‚นใ‚ญใƒผใƒžใ‚’ๆ˜Ž็ขบใ‹ใค็ฐกๅ˜ใซๅฎš็พฉใ€ใƒใ‚งใƒƒใ‚ฏใ—ใ€JSONใ‚นใ‚ญใƒผใƒžใจใ—ใฆๆ–‡ๆ›ธๅŒ–ใงใใพใ™ใ€‚ - * ๆทฑใ**ใƒใ‚นใƒˆใ•ใ‚ŒใŸJSON**ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚‰ใ™ในใฆใ‚’ๆคœ่จผใ—ใฆใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไป˜ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +* **brainfuck ใชใ—**๏ผš + * ใ‚นใ‚ญใƒผใƒžๅฎš็พฉใฎใŸใ‚ใฎๆ–ฐใ—ใ„ใƒžใ‚คใ‚ฏใƒญ่จ€่ชžใ‚’ๅญฆใถๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + * Python ใฎๅž‹ใ‚’็Ÿฅใฃใฆใ„ใ‚Œใฐใ€Pydantic ใฎไฝฟใ„ๆ–นใ‚‚ใ‚ใ‹ใ‚Šใพใ™ใ€‚ +* **IDE/ใƒชใƒณใ‚ฟใƒผ/ๆ€่€ƒ** ใจๆฐ—ๆŒใกใ‚ˆใ้€ฃๆบใ—ใพใ™๏ผš + * Pydantic ใฎใƒ‡ใƒผใ‚ฟๆง‹้€ ใฏใ€ใ‚ใชใŸใŒๅฎš็พฉใ™ใ‚‹ใ‚ฏใƒฉใ‚นใฎๅ˜ใชใ‚‹ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใชใฎใงใ€ใ‚ชใƒผใƒˆใ‚ณใƒณใƒ—ใƒชใƒผใƒˆใ€ใƒชใƒณใƒ†ใ‚ฃใƒณใ‚ฐใ€mypyใ€ใใ—ใฆใ‚ใชใŸใฎ็›ดๆ„ŸใŒใ€ๆคœ่จผๆธˆใฟใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆ้ฉๅˆ‡ใซๆฉŸ่ƒฝใ—ใพใ™ใ€‚ +* **่ค‡้›‘ใชๆง‹้€ ** ใ‚’ๆคœ่จผ๏ผš + * ้šŽๅฑค็š„ใช Pydantic ใƒขใƒ‡ใƒซใ‚„ใ€Python ใฎ `typing` ใซใ‚ใ‚‹ `List` ใ‚„ `Dict` ใชใฉใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ + * ใ•ใ‚‰ใซใƒใƒชใƒ‡ใƒผใ‚ฟใซใ‚ˆใ‚Šใ€่ค‡้›‘ใชใƒ‡ใƒผใ‚ฟใ‚นใ‚ญใƒผใƒžใ‚’ๆ˜Ž็ขบใ‹ใคๅฎนๆ˜“ใซๅฎš็พฉใƒปๆคœๆŸปใงใใ€JSON Schema ใจใ—ใฆๆ–‡ๆ›ธๅŒ–ใงใใพใ™ใ€‚ + * ๆทฑใ **ใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON** ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆ‰ฑใˆใ€ใใ‚Œใ‚‰ใ™ในใฆใ‚’ๆคœ่จผใ—ใฆใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไป˜ไธŽใงใใพใ™ใ€‚ * **ๆ‹กๅผตๅฏ่ƒฝ**๏ผš - * Pydanticใงใฏใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ใพใŸใฏใ€ใƒใƒชใƒ‡ใƒผใ‚ฟใƒผใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใƒผใง่ฃ…้ฃพใ•ใ‚ŒใŸใƒขใƒ‡ใƒซใฎใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ—ใฆๆคœ่จผใ‚’ๆ‹กๅผตใงใใพใ™ใ€‚ + * Pydantic ใงใฏใ‚ซใ‚นใ‚ฟใƒ ใƒ‡ใƒผใ‚ฟๅž‹ใ‚’ๅฎš็พฉใงใใพใ™ใ—ใ€ใƒใƒชใƒ‡ใƒผใ‚ฟใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใƒผใง่ฃ…้ฃพใ—ใŸใƒขใƒ‡ใƒซใƒกใ‚ฝใƒƒใƒ‰ใงๆคœ่จผใ‚’ๆ‹กๅผตใงใใพใ™ใ€‚ * ใƒ†ใ‚นใƒˆใ‚ซใƒใƒฌใƒƒใ‚ธ 100%ใ€‚ diff --git a/docs/ja/docs/help-fastapi.md b/docs/ja/docs/help-fastapi.md index 8cf0c21636..ed91bb19f6 100644 --- a/docs/ja/docs/help-fastapi.md +++ b/docs/ja/docs/help-fastapi.md @@ -1,101 +1,255 @@ -# FastAPIใ‚’ๅฟœๆด - ใƒ˜ใƒซใƒ—ใฎๅ…ฅๆ‰‹ +# FastAPIใ‚’ๅฟœๆด - ใƒ˜ใƒซใƒ—ใฎๅ…ฅๆ‰‹ { #help-fastapi-get-help } **FastAPI** ใฏๆฐ—ใซๅ…ฅใ‚Šใพใ—ใŸใ‹๏ผŸ -FastAPIใ‚„ใƒฆใƒผใ‚ถใƒผใ‚„้–‹็™บ่€…ใ‚’ๅฟœๆดใ—ใŸใ„ใงใ™ใ‹๏ผŸ +FastAPIใ‚„ไป–ใฎใƒฆใƒผใ‚ถใƒผใ€ไฝœ่€…ใ‚’ๅฟœๆดใ—ใŸใ„ใงใ™ใ‹๏ผŸ -ใ‚‚ใ—ใใฏใ€ **FastAPI** ใซใคใ„ใฆใƒ˜ใƒซใƒ—ใŒๅฟ…่ฆใงใ™ใ‹๏ผŸ +ใใ‚Œใจใ‚‚ **FastAPI** ใซใคใ„ใฆใƒ˜ใƒซใƒ—ใŒๅฟ…่ฆใงใ™ใ‹๏ผŸ -ใจใฆใ‚‚็ฐกๅ˜ใซๅฟœๆดใงใใพใ™ (ใŸใ 1ใ€2ๅ›žใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใ ใ‘ใฎใ‚‚ใฎใ‚‚ใ‚ใ‚Šใพใ™)ใ€‚ +ใจใฆใ‚‚็ฐกๅ˜ใซๅฟœๆดใงใใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™๏ผˆ1ใ€2ๅ›žใ‚ฏใƒชใƒƒใ‚ฏใ™ใ‚‹ใ ใ‘ใฎใ‚‚ใฎใ‚‚ใ‚ใ‚Šใพใ™๏ผ‰ใ€‚ -ใพใŸใ€ใƒ˜ใƒซใƒ—ใ‚’ๅ…ฅๆ‰‹ใ™ใ‚‹ๆ‰‹ๆฎตใŒใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ +ใƒ˜ใƒซใƒ—ใ‚’ๅพ—ใ‚‹ๆ–นๆณ•ใ‚‚ใ„ใใคใ‹ใ‚ใ‚Šใพใ™ใ€‚ -## GitHubใง **FastAPI** ใซStar +## ใƒ‹ใƒฅใƒผใ‚นใƒฌใ‚ฟใƒผใ‚’่ณผ่ชญ { #subscribe-to-the-newsletter } -GitHubใงFastAPIใซใ€ŒStarใ€ใ‚’ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ (ๅณไธŠ้ƒจใฎStarใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ): https://github.com/fastapi/fastapi. โญ๏ธ +[**FastAPI and friends** ใƒ‹ใƒฅใƒผใ‚นใƒฌใ‚ฟใƒผ](newsletter.md){.internal-link target=_blank}๏ผˆ้…ไฟกใฏใพใ‚Œใงใ™๏ผ‰ใ‚’่ณผ่ชญใ™ใ‚‹ใจใ€ๆฌกใฎๆƒ…ๅ ฑใ‚’ใ‚ญใƒฃใƒƒใƒใ‚ขใƒƒใƒ—ใงใใพใ™: -ใ‚นใ‚ฟใƒผใ‚’ๅข—ใ‚„ใ™ใ“ใจใงใ€ไป–ใฎใƒฆใƒผใ‚ถใƒผใฎ็›ฎใซใคใใ‚„ใ™ใใชใ‚Šใ€ๅคšใใฎไบบใซใจใฃใฆไพฟๅˆฉใชใ‚‚ใฎใงใ‚ใ‚‹ใ“ใจใ‚’็คบใ›ใพใ™ใ€‚ +* FastAPI ใจ้–ข้€ฃใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใƒ‹ใƒฅใƒผใ‚น ๐Ÿš€ +* ใ‚ฌใ‚คใƒ‰ ๐Ÿ“ +* ๆฉŸ่ƒฝ โœจ +* ไบ’ๆ›ๆ€งใซๅฝฑ้Ÿฟใ™ใ‚‹ๅค‰ๆ›ด ๐Ÿšจ +* ใƒ’ใƒณใƒˆใ‚„ใ‚ณใƒ„ โœ… -## GitHubใƒฌใƒใ‚ธใƒˆใƒชใฎใƒชใƒชใƒผใ‚นใ‚’Watch +## X (Twitter) ใง FastAPI ใ‚’ใƒ•ใ‚ฉใƒญใƒผ { #follow-fastapi-on-x-twitter } -GitHubใงFastAPIใ‚’ใ€ŒWatchใ€ใงใใพใ™ (ๅณไธŠ้ƒจใฎWatchใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ +**X (Twitter)** ใง @fastapi ใ‚’ใƒ•ใ‚ฉใƒญใƒผใ—ใฆใ€**FastAPI** ใฎๆœ€ๆ–ฐๆƒ…ๅ ฑใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ—ใ‚‡ใ†ใ€‚๐Ÿฆ + +## GitHubใง **FastAPI** ใซStar { #star-fastapi-in-github } + +GitHubใงFastAPIใซใ€ŒStarใ€ใ‚’ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™๏ผˆๅณไธŠ้ƒจใฎStarใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ๏ผ‰: https://github.com/fastapi/fastapiใ€‚โญ๏ธ + +ใ‚นใ‚ฟใƒผใ‚’ๅข—ใ‚„ใ™ใ“ใจใงใ€ไป–ใฎใƒฆใƒผใ‚ถใƒผใฎ็›ฎใซใคใใ‚„ใ™ใใชใ‚Šใ€ใ™ใงใซๅคšใใฎไบบใฎๅฝนใซ็ซ‹ใฃใฆใ„ใ‚‹ใ“ใจใŒไผใ‚ใ‚Šใพใ™ใ€‚ + +## GitHubใƒฌใƒใ‚ธใƒˆใƒชใฎใƒชใƒชใƒผใ‚นใ‚’Watch { #watch-the-github-repository-for-releases } + +GitHubใงFastAPIใ‚’ใ€ŒWatchใ€ใงใใพใ™๏ผˆๅณไธŠ้ƒจใฎใ€ŒWatchใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ๏ผ‰: https://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ ใใ“ใงใ€ŒReleases onlyใ€ใ‚’้ธๆŠžใงใใพใ™ใ€‚ -ใ“ใ‚Œใ‚’่กŒใ†ใจใ€**FastAPI** ใƒใ‚ฐไฟฎๆญฃใ‚„ๆ–ฐๆฉŸ่ƒฝใฎๅฎŸ่ฃ…ใชใฉใฎๆ–ฐใ—ใ„ใƒชใƒชใƒผใ‚น (ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ) ใŒใ‚ใ‚‹ใŸใณใซ (ใƒกใƒผใƒซใง) ้€š็Ÿฅใ‚’ๅ—ใ‘ๅ–ใ‚Œใพใ™ใ€‚ +ใ“ใ‚Œใ‚’่กŒใ†ใจใ€ใƒใ‚ฐไฟฎๆญฃใ‚„ๆ–ฐๆฉŸ่ƒฝใ‚’ๅซใ‚€ **FastAPI** ใฎๆ–ฐใ—ใ„ใƒชใƒชใƒผใ‚น๏ผˆๆ–ฐใƒใƒผใ‚ธใƒงใƒณ๏ผ‰ใŒใ‚ใ‚‹ใŸใณใซใ€๏ผˆใƒกใƒผใƒซใง๏ผ‰้€š็Ÿฅใ‚’ๅ—ใ‘ๅ–ใ‚Œใพใ™ใ€‚ -## ้–‹็™บ่€…ใจใคใชใŒใ‚‹ +## ้–‹็™บ่€…ใจใคใชใŒใ‚‹ { #connect-with-the-author } -ไปฅไธ‹ใงใ€้–‹็™บ่€… (Sebastiรกn Ramรญrez / `tiangolo`) ใจใ‚ณใƒณใ‚ฟใ‚ฏใƒˆใ‚’ใจใ‚Œใพใ™: +ไฝœ่€…ใงใ‚ใ‚‹็ง๏ผˆSebastiรกn Ramรญrez / `tiangolo`๏ผ‰ใจใคใชใŒใ‚Œใพใ™ใ€‚ + +ใงใใ‚‹ใ“ใจ: * **GitHub** ใงใƒ•ใ‚ฉใƒญใƒผใ€‚ - * ไป–ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’็ขบ่ชใงใใพใ™ใ€‚ไฝ•ใ‹ใฎๅŠฉใ‘ใซใชใ‚‹ใ‚‚ใฎใŒ่ฆ‹ใคใ‹ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ - * ๆ–ฐใŸใชใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใŸใจใใซ้€š็Ÿฅใ•ใ‚Œใพใ™ใ€‚ -* **X (Twitter)** ใงใƒ•ใ‚ฉใƒญใƒผใ€‚ - * FastAPIใฎไฝฟ็”จ็”จ้€”ใ‚’ๆ•™ใˆใฆใใ ใ•ใ„ (่žใ„ใฆใฟใŸใ„ใงใ™)ใ€‚ - * ๆ–ฐใŸใชใƒ„ใƒผใƒซใฎ็™บ่กจใ‚„ใƒชใƒชใƒผใ‚นใŒ่žใ‘ใพใ™ใ€‚ -* **Linkedin** ใงใคใชใŒใ‚‹ใ€‚ - * ๆ–ฐใŸใชใƒ„ใƒผใƒซใฎ็™บ่กจใ‚„ใƒชใƒชใƒผใ‚นใŒ่žใ‘ใพใ™ (ใŸใ ใ—X (Twitter)ใฎๆ–นใŒๅˆฉ็”จ้ ปๅบฆใŒ้ซ˜ใ„ใงใ™ใŒ ๐Ÿคทโ€โ™‚)ใ€‚ -* **Dev.to** ใ‚„ **Medium** ใง่‘—ไฝœ็‰ฉใ‚’่ชญใ‚€ (ใพใŸใฏใƒ•ใ‚ฉใƒญใƒผ)ใ€‚ - * ใ‚ขใ‚คใƒ‡ใ‚ขใ‚„ไฝœๆˆใƒ„ใƒผใƒซใซใคใ„ใฆใฎ่จ˜ไบ‹ใŒ่ชญใ‚ใพใ™ใ€‚ - * ๆ–ฐ่ฆ่จ˜ไบ‹ใฎๅŸท็ญ†ใ‚’้€š็Ÿฅใ—ใฆใใ‚Œใพใ™ใ€‚ + * ๅฝนใซ็ซ‹ใคใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€็งใŒไฝœๆˆใ—ใŸไป–ใฎใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’่ฆ‹ใ‚‰ใ‚Œใพใ™ใ€‚ + * ๆ–ฐใ—ใ„ใ‚ชใƒผใƒ—ใƒณใ‚ฝใƒผใ‚นใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใŸใจใใซใ‚ใ‹ใ‚Šใพใ™ใ€‚ +* **X (Twitter)** ใงใƒ•ใ‚ฉใƒญใƒผ ใพใŸใฏ Mastodonใ€‚ + * ใ‚ใชใŸใŒใฉใฎใ‚ˆใ†ใซFastAPIใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‹ๆ•™ใˆใฆใใ ใ•ใ„๏ผˆ่žใ‘ใ‚‹ใจๅฌ‰ใ—ใ„ใงใ™๏ผ‰ใ€‚ + * ๆ–ฐใ—ใ„ใƒ„ใƒผใƒซใฎๅ‘Š็Ÿฅใ‚„ใƒชใƒชใƒผใ‚นใ‚’่žใ‘ใพใ™ใ€‚ + * ใ•ใ‚‰ใซใ€X (Twitter) ใฎ @fastapi๏ผˆๅˆฅใ‚ขใ‚ซใ‚ฆใƒณใƒˆ๏ผ‰ใ‚‚ใƒ•ใ‚ฉใƒญใƒผใงใใพใ™ใ€‚ +* **LinkedIn** ใงใƒ•ใ‚ฉใƒญใƒผใ€‚ + * ๆ–ฐใ—ใ„ใƒ„ใƒผใƒซใฎๅ‘Š็Ÿฅใ‚„ใƒชใƒชใƒผใ‚นใ‚’่žใ‘ใพใ™๏ผˆใŸใ ใ—X (Twitter) ใฎๆ–นใ‚’ใ‚ˆใไฝฟใฃใฆใ„ใพใ™ ๐Ÿคทโ€โ™‚๏ผ‰ใ€‚ +* **Dev.to** ใ‚„ **Medium** ใงๅŸท็ญ†ๅ†…ๅฎนใ‚’่ชญใ‚€๏ผˆใพใŸใฏใƒ•ใ‚ฉใƒญใƒผ๏ผ‰ใ€‚ + * ็งใฎใ‚ขใ‚คใƒ‡ใ‚ขใ‚„ใ€ไฝœๆˆใ—ใŸใƒ„ใƒผใƒซใซ้–ขใ™ใ‚‹่จ˜ไบ‹ใ‚’่ชญใ‚ใพใ™ใ€‚ + * ๆ–ฐใ—ใ„่จ˜ไบ‹ใ‚’ๅ…ฌ้–‹ใ—ใŸใจใใซ่ชญใ‚ใพใ™ใ€‚ + +## **FastAPI** ใซใคใ„ใฆใƒ„ใ‚คใƒผใƒˆ { #tweet-about-fastapi } + +**FastAPI** ใซใคใ„ใฆใƒ„ใ‚คใƒผใƒˆใ—ใฆใ€ใชใœๆฐ—ใซๅ…ฅใฃใฆใ„ใ‚‹ใฎใ‹ใ‚’็งใ‚„ไป–ใฎไบบใซๆ•™ใˆใฆใใ ใ•ใ„ใ€‚๐ŸŽ‰ + +**FastAPI** ใŒใฉใฎใ‚ˆใ†ใซไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ใ‹ใ€ใฉใ“ใ‚’ๆฐ—ใซๅ…ฅใฃใฆใ„ใ‚‹ใ‹ใ€ใฉใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ/ไผš็คพใงไฝฟใฃใฆใ„ใ‚‹ใ‹็ญ‰ใ€่žใ‘ใ‚‹ใจๅฌ‰ใ—ใ„ใงใ™ใ€‚ + +## FastAPIใซๆŠ•็ฅจ { #vote-for-fastapi } + +* Slantใง **FastAPI** ใซๆŠ•็ฅจใ€‚ +* AlternativeToใง **FastAPI** ใซๆŠ•็ฅจใ€‚ +* StackShare ใง **FastAPI** ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจๅฎฃ่จ€ใ€‚ + +## GitHubใง่ณชๅ•ใซๅ›ฐใฃใฆใ„ใ‚‹ไบบใ‚’ๅŠฉใ‘ใ‚‹ { #help-others-with-questions-in-github } + +ๆฌกใฎๅ ดๆ‰€ใงใ€ไป–ใฎไบบใฎ่ณชๅ•ใ‚’ๆ‰‹ๅŠฉใ‘ใงใใพใ™: + +* GitHub Discussions +* GitHub Issues + +ๅคšใใฎๅ ดๅˆใ€ใใฎ่ณชๅ•ใฎ็ญ”ใˆใ‚’ใ™ใงใซ็Ÿฅใฃใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚๐Ÿค“ + +ใ‚‚ใ—ๅคšใใฎไบบใฎ่ณชๅ•ใซ็ญ”ใˆใฆๅŠฉใ‘ใฆใใ‚ŒใŸใชใ‚‰ใ€ใ‚ใชใŸใฏๅ…ฌๅผใฎ[FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}ใซใชใ‚Šใพใ™ใ€‚๐ŸŽ‰ + +ๆœ€ใ‚‚ๅคงไบ‹ใชใƒใ‚คใƒณใƒˆใฏใ€Œ่ฆชๅˆ‡ใงใ‚ใ‚‹ใ“ใจใ€ใ‚’ๅฟƒใŒใ‘ใ‚‹ใ“ใจใงใ™ใ€‚ไบบใฏใƒ•ใƒฉใ‚นใƒˆใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๆŠฑใˆใฆใ‚„ใฃใฆๆฅใ‚‹ใฎใงใ€ๅฟ…ใšใ—ใ‚‚ๆœ€่‰ฏใฎ่žใๆ–นใ‚’ใ—ใฆใ„ใ‚‹ใจใฏ้™ใ‚Šใพใ›ใ‚“ใŒใ€ใงใใ‚‹้™ใ‚Š่ฆชๅˆ‡ใซๅฏพๅฟœใ—ใพใ—ใ‚‡ใ†ใ€‚๐Ÿค— + +**FastAPI** ใ‚ณใƒŸใƒฅใƒ‹ใƒ†ใ‚ฃใฏ่ฆชๅˆ‡ใงๆญ“่ฟŽ็š„ใงใ‚ใ‚‹ใ“ใจใ‚’็›ฎๆŒ‡ใ—ใฆใ„ใพใ™ใ€‚ๅŒๆ™‚ใซใ€ใ„ใ˜ใ‚ใ‚„ไป–่€…ใธใฎ็„ก็คผใชๆŒฏใ‚‹่ˆžใ„ใฏๅ—ใ‘ๅ…ฅใ‚Œใชใ„ใงใใ ใ•ใ„ใ€‚ใŠไบ’ใ„ใ‚’ๅคงไบ‹ใซใ—ใพใ—ใ‚‡ใ†ใ€‚ + +--- + +ไปฅไธ‹ใฏ๏ผˆDiscussions ใ‚„ Issues ใง๏ผ‰ไป–ใฎไบบใฎ่ณชๅ•ใ‚’ๆ‰‹ๅŠฉใ‘ใ™ใ‚‹ๆ–นๆณ•ใงใ™: + +### ่ณชๅ•ใ‚’็†่งฃใ™ใ‚‹ { #understand-the-question } + +* ่ณชๅ•่€…ใฎใ€Œ็›ฎ็š„ใ€ใ‚„ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’็†่งฃใงใใ‚‹ใ‹็ขบ่ชใ—ใพใ™ใ€‚ + +* ๆฌกใซใ€่ณชๅ•๏ผˆๅคงๅŠใฏ่ณชๅ•ใงใ™๏ผ‰ใŒใ€Œๆ˜Ž็ขบใ€ใ‹็ขบ่ชใ—ใพใ™ใ€‚ + +* ๅคšใใฎๅ ดๅˆใ€ใƒฆใƒผใ‚ถใƒผใŒๆƒณๅƒใ—ใŸ่งฃๆฑบ็ญ–ใซใคใ„ใฆใฎ่ณชๅ•ใซใชใฃใฆใ„ใพใ™ใŒใ€ใ‚‚ใฃใจใ€Œ่‰ฏใ„ใ€ๆ–นๆณ•ใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ๅ•้กŒใ‚„ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’ใ‚ˆใ‚Šใ‚ˆใ็†่งฃใงใใ‚Œใฐใ€ใ‚ˆใ‚Š่‰ฏใ„ใ€Œไปฃๆ›ฟ่งฃๆฑบ็ญ–ใ€ใ‚’ๆๆกˆใงใใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +* ่ณชๅ•ใŒ็†่งฃใงใใชใ„ๅ ดๅˆใฏใ€ใ•ใ‚‰ใซใ€Œ่ฉณ็ดฐใ€ใ‚’ๅฐ‹ใญใพใ™ใ€‚ + +### ๅ•้กŒใ‚’ๅ†็พใ™ใ‚‹ { #reproduce-the-problem } + +ๅคšใใฎใ‚ฑใƒผใ‚นใ‚„่ณชๅ•ใฏใ€ใใฎไบบใฎใ€Œๅ…ƒใฎใ‚ณใƒผใƒ‰ใ€ใซ้–ขไฟ‚ใ—ใฆใ„ใพใ™ใ€‚ + +ใ—ใฐใ—ใฐใ‚ณใƒผใƒ‰ใฎๆ–ญ็‰‡ใ ใ‘ใŒๅ…ฑๆœ‰ใ•ใ‚Œใพใ™ใŒใ€ใใ‚Œใงใฏๅ•้กŒใ‚’ใ€Œๅ†็พใ€ใ™ใ‚‹ใซใฏไธๅๅˆ†ใงใ™ใ€‚ + +* ใƒญใƒผใ‚ซใƒซใงๅŒใ˜ใ‚จใƒฉใƒผใ‚„ๆŒ™ๅ‹•ใ‚’็ขบ่ชใงใใ‚‹ใ‚ˆใ†ใซใ€ใพใŸใฏใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’ใ‚ˆใ‚Šใ‚ˆใ็†่งฃใงใใ‚‹ใ‚ˆใ†ใซใ€**ใ‚ณใƒ”ใƒผ&ใƒšใƒผใ‚นใƒˆ**ใ—ใฆๅฎŸ่กŒใงใใ‚‹ๆœ€ๅฐใฎๅ†็พๅฏ่ƒฝใชไพ‹ใฎๆไพ›ใ‚’ไพ้ ผใงใใพใ™ใ€‚ + +* ใจใฆใ‚‚ๅฏ›ๅคงใชๆฐ—ๅˆ†ใชใ‚‰ใ€ๅ•้กŒใฎ่ชฌๆ˜Žใ ใ‘ใ‚’ใ‚‚ใจใซใ€ใ‚ใชใŸ่‡ช่บซใงใใฎใ‚ˆใ†ใช**ไพ‹ใ‚’ไฝœๆˆ**ใ—ใฆใฟใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ใŸใ ใ—ๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใฎใงใ€ใพใšใฏๅ•้กŒใฎๆ˜Ž็ขบๅŒ–ใ‚’ไพ้ ผใ—ใŸๆ–นใŒ่‰ฏใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +### ่งฃๆฑบ็ญ–ใ‚’ๆๆกˆใ™ใ‚‹ { #suggest-solutions } + +* ่ณชๅ•ใ‚’็†่งฃใงใใŸใ‚‰ใ€ๅฏ่ƒฝใช**ๅ›ž็ญ”**ใ‚’ๆ็คบใงใใพใ™ใ€‚ + +* ๅคšใใฎๅ ดๅˆใ€็›ธๆ‰‹ใฎใ€Œๆ นๆœฌ็š„ใชๅ•้กŒใ‚„ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ€ใ‚’็†่งฃใ™ใ‚‹ใ“ใจใŒ้‡่ฆใงใ™ใ€‚็›ธๆ‰‹ใŒ่ฉฆใ—ใฆใ„ใ‚‹ๆ–นๆณ•ใ‚ˆใ‚Š่‰ฏใ„่งฃๆฑบๆ–นๆณ•ใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ‹ใ‚‰ใงใ™ใ€‚ + +### ใ‚ฏใƒญใƒผใ‚บใ‚’ไพ้ ผใ™ใ‚‹ { #ask-to-close } + +ใ‚‚ใ—็›ธๆ‰‹ใŒ่ฟ”ไฟกใ—ใฆใใฆใ€ใ‚ใชใŸใŒๅ•้กŒใ‚’่งฃๆฑบใงใใŸใชใ‚‰ใ€ใŠใ‚ใงใจใ†ใ€**ใ‚ใชใŸใฏใƒ’ใƒผใƒญใƒผ**ใงใ™๏ผ๐Ÿฆธ + +* ใใฎๅ ดๅˆใ€ๆฌกใฎใ‚ˆใ†ใซไพ้ ผใงใใพใ™: + + * GitHub Discussions: ใ‚ณใƒกใƒณใƒˆใ‚’**ๅ›ž็ญ”**ใจใ—ใฆใƒžใƒผใ‚ฏใ—ใฆใ‚‚ใ‚‰ใ†ใ€‚ + * GitHub Issues: issue ใ‚’**ใ‚ฏใƒญใƒผใ‚บ**ใ—ใฆใ‚‚ใ‚‰ใ†ใ€‚ + +## GitHubใƒฌใƒใ‚ธใƒˆใƒชใ‚’Watch { #watch-the-github-repository } + +GitHubใงFastAPIใ‚’ใ€ŒWatchใ€ใงใใพใ™๏ผˆๅณไธŠ้ƒจใฎใ€ŒWatchใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ๏ผ‰: https://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ + +ใ€ŒReleases onlyใ€ใงใฏใชใใ€ŒWatchingใ€ใ‚’้ธๆŠžใ™ใ‚‹ใจใ€ๆ–ฐใ—ใ„ issue ใ‚„่ณชๅ•ใŒไฝœๆˆใ•ใ‚ŒใŸใจใใซ้€š็Ÿฅใ‚’ๅ—ใ‘ๅ–ใ‚Œใพใ™ใ€‚ๆ–ฐใ—ใ„ issue ใฎใฟใ€Discussions ใฎใฟใ€PR ใฎใฟใ€ใชใฉ้€š็Ÿฅๅฏพ่ฑกใ‚’็ตžใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใใฎไธŠใงใ€ใใ†ใ—ใŸ่ณชๅ•ใฎ่งฃๆฑบใ‚’ๆ‰‹ๅŠฉใ‘ใงใใพใ™ใ€‚ + +## ่ณชๅ•ใ™ใ‚‹ { #ask-questions } + +GitHubใƒฌใƒใ‚ธใƒˆใƒชใงๆ–ฐใ—ใ„่ณชๅ•ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ไพ‹ใˆใฐ: + +* **่ณชๅ•**ใ‚’ใ™ใ‚‹ใ€ใพใŸใฏ**ๅ•้กŒ**ใซใคใ„ใฆๅฐ‹ใญใ‚‹ใ€‚ +* ๆ–ฐใ—ใ„**ๆฉŸ่ƒฝ**ใ‚’ๆๆกˆใ™ใ‚‹ใ€‚ + +**Note**: ใ‚‚ใ—ใใ†ใ™ใ‚‹ใชใ‚‰ใ€ไป–ใฎไบบใฎๆ‰‹ๅŠฉใ‘ใ‚‚ใŠ้ก˜ใ„ใ—ใพใ™ใ€‚๐Ÿ˜‰ + +## ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใƒฌใƒ“ใƒฅใƒผ { #review-pull-requests } + +ไป–ใฎไบบใ‹ใ‚‰ใฎใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒฌใƒ“ใƒฅใƒผใ‚’ๆ‰‹ไผใฃใฆใ‚‚ใ‚‰ใˆใพใ™ใ€‚ + +ใ“ใ“ใงใ‚‚ใ€ใงใใ‚‹้™ใ‚Š่ฆชๅˆ‡ใงใ‚ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚๐Ÿค— + +--- + +ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใƒฌใƒ“ใƒฅใƒผใ™ใ‚‹ใจใใฎใƒใ‚คใƒณใƒˆใงใ™: + +### ๅ•้กŒใ‚’็†่งฃใ™ใ‚‹ { #understand-the-problem } + +* ใพใšใ€ใใฎใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใŒ่งฃๆฑบใ—ใ‚ˆใ†ใจใ—ใฆใ„ใ‚‹**ๅ•้กŒใ‚’็†่งฃ**ใ—ใฆใใ ใ•ใ„ใ€‚้•ทใ‚ใฎ่ญฐ่ซ–ใŒ GitHub Discussion ใ‚„ issue ใซใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +* ใใฎๅ•้กŒใฏๅฎŸใฏ**ๅˆฅใฎๆ–นๆณ•**ใง่งฃๆฑบใงใใ€ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆ่‡ชไฝ“ใŒไธ่ฆใชๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ใใฎๅ ดๅˆใฏใ€ใใฎๆๆกˆใ‚„่ณชๅ•ใ‚’ใ—ใฆใ‚‚่‰ฏใ„ใงใ—ใ‚‡ใ†ใ€‚ + +### ใ‚นใ‚ฟใ‚คใƒซใฏๆฐ—ใซใ—ใ™ใŽใชใ„ { #dont-worry-about-style } + +* ใ‚ณใƒŸใƒƒใƒˆใƒกใƒƒใ‚ปใƒผใ‚ธใฎใ‚นใ‚ฟใ‚คใƒซใชใฉใฏใ‚ใพใ‚Šๆฐ—ใซใ—ใชใใฆๅคงไธˆๅคซใงใ™ใ€‚็งใฏ squash and merge ใ‚’ไฝฟใ„ใ€ใ‚ณใƒŸใƒƒใƒˆใ‚’ๆ‰‹ๅ‹•ใง่ชฟๆ•ดใ—ใพใ™ใ€‚ + +* ใ‚นใ‚ฟใ‚คใƒซใƒซใƒผใƒซใซใคใ„ใฆใ‚‚ๅฟƒ้…็„ก็”จใงใ™ใ€‚่‡ชๅ‹•ๅŒ–ใƒ„ใƒผใƒซใŒใ™ใงใซใƒใ‚งใƒƒใ‚ฏใ—ใฆใ„ใพใ™ใ€‚ + +ใปใ‹ใซใ‚นใ‚ฟใ‚คใƒซใ‚„ไธ€่ฒซๆ€งใฎ่ฆไปถใŒใ‚ใ‚Œใฐใ€็งใ‹ใ‚‰็›ดๆŽฅไพ้ ผใ—ใพใ™ใ—ใ€ๅฟ…่ฆใชๅค‰ๆ›ดใ‚’ไธŠใซ็ฉใ‚€ๅฝขใงใ‚ณใƒŸใƒƒใƒˆใ‚’่ฟฝๅŠ ใ—ใพใ™ใ€‚ + +### ใ‚ณใƒผใƒ‰ใ‚’็ขบ่ช { #check-the-code } + +* ใ‚ณใƒผใƒ‰ใ‚’็ขบ่ชใ—ใฆ่ชญใฟใ€ๅฆฅๅฝ“ใ‹ใฉใ†ใ‹ใ‚’่ฆ‹ใฆใ€**ใƒญใƒผใ‚ซใƒซใงๅฎŸ่กŒ**ใ—ใ€ๆœฌๅฝ“ใซๅ•้กŒใ‚’่งฃๆฑบใ—ใฆใ„ใ‚‹ใ‹็ขบใ‹ใ‚ใฆใใ ใ•ใ„ใ€‚ + +* ใใฎใ†ใˆใงใ€ใใ‚Œใ‚’่กŒใฃใŸใ“ใจใ‚’**ใ‚ณใƒกใƒณใƒˆ**ใงไผใˆใฆใใ ใ•ใ„ใ€‚ใใ†ใ™ใ‚Œใฐใ€ๅฎŸ้š›ใซ็ขบ่ชใ—ใฆใใ‚ŒใŸใจใ‚ใ‹ใ‚Šใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +ๆฎ‹ๅฟตใชใŒใ‚‰ใ€ๆ‰ฟ่ชใŒ่ค‡ๆ•ฐใคใ„ใŸใ ใ‘ใฎPRใ‚’ใ€ใใฎใพใพไฟก้ ผใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ + +่ชฌๆ˜ŽใŒ้ญ…ๅŠ›็š„ใชใŸใ‚ใ‹ใ€3ไปถใ€5ไปถไปฅไธŠใฎๆ‰ฟ่ชใŒใคใ„ใฆใ„ใฆใ‚‚ใ€ๅฎŸ้š›ใซPRใ‚’็ขบ่ชใ™ใ‚‹ใจๅฃŠใ‚Œใฆใ„ใŸใ‚Šใ€ใƒใ‚ฐใŒใ‚ใฃใŸใ‚Šใ€ไธปๅผตใ™ใ‚‹ๅ•้กŒใ‚’่งฃๆฑบใ—ใฆใ„ใชใ‹ใฃใŸใ‚Šใ™ใ‚‹ใ“ใจใŒไฝ•ๅบฆใ‚‚ใ‚ใ‚Šใพใ—ใŸใ€‚๐Ÿ˜… + +ใงใ™ใฎใงใ€ๅฎŸ้š›ใซใ‚ณใƒผใƒ‰ใ‚’่ชญใฟใ€ๅฎŸ่กŒใ—ใฆ็ขบ่ชใ—ใ€ใใ‚Œใ‚’ใ‚ณใƒกใƒณใƒˆใง็Ÿฅใ‚‰ใ›ใฆใ‚‚ใ‚‰ใˆใ‚‹ใ“ใจใŒๆœฌๅฝ“ใซ้‡่ฆใงใ™ใ€‚๐Ÿค“ + +/// + +* ใ‚‚ใ—PRใ‚’็ฐก็ด ๅŒ–ใงใใใ†ใชใ‚‰ใ€ใใฎไพ้ ผใ‚’ใ—ใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใŒใ€็ดฐใ‹ใ„็‚นใซใ“ใ ใ‚ใ‚Š้ŽใŽใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ไธป่ฆณ็š„ใช่ฆ‹ๆ–นใŒๅคšใ๏ผˆ็งใซใ‚‚ใ‚ใ‚Šใพใ™ ๐Ÿ™ˆ๏ผ‰ใ€ๅŸบๆœฌ็š„ใช็‚นใซ้›†ไธญใงใใ‚‹ใจใ‚ˆใ‚Š่‰ฏใ„ใงใ—ใ‚‡ใ†ใ€‚ + +### ใƒ†ใ‚นใƒˆ { #tests } + +* PRใซ**ใƒ†ใ‚นใƒˆ**ใŒใ‚ใ‚‹ใ‹็ขบ่ชใ‚’ๆ‰‹ไผใฃใฆใใ ใ•ใ„ใ€‚ + +* PRๅ‰ใฏใƒ†ใ‚นใƒˆใŒ**ๅคฑๆ•—**ใ™ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚๐Ÿšจ + +* ใใ—ใฆPRๅพŒใซใƒ†ใ‚นใƒˆใŒ**ๆˆๅŠŸ**ใ™ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใพใ™ใ€‚โœ… -## **FastAPI** ใซ้–ขใ™ใ‚‹ใƒ„ใ‚คใƒผใƒˆ +* ๅคšใใฎPRใซใฏใƒ†ใ‚นใƒˆใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใƒ†ใ‚นใƒˆใฎ่ฟฝๅŠ ใ‚’**ใƒชใƒžใ‚คใƒณใƒ‰**ใ—ใŸใ‚Šใ€ใƒ†ใ‚นใƒˆใ‚’**ๆๆกˆ**ใ—ใŸใ‚Šใงใใพใ™ใ€‚ใ“ใ‚Œใฏๆœ€ใ‚‚ๆ™‚้–“ใ‚’ๆถˆ่ฒปใ™ใ‚‹้ƒจๅˆ†ใฎไธ€ใคใงใ€ๅคงใ„ใซๅŠฉใ‘ใซใชใ‚Šใพใ™ใ€‚ -**FastAPI** ใซใคใ„ใฆใƒ„ใ‚คใƒผใƒˆใ—ใ€้–‹็™บ่€…ใ‚„ไป–ใฎไบบใซใฉใ“ใŒๆฐ—ใซๅ…ฅใฃใŸใฎใ‹ๆ•™ใˆใฆใใ ใ•ใ„ใ€‚๐ŸŽ‰ +* ไฝ•ใ‚’่ฉฆใ—ใŸใ‹ใ‚‚ใ‚ณใƒกใƒณใƒˆใ—ใฆใใ ใ•ใ„ใ€‚ใใ†ใ™ใ‚Œใฐใ€็ขบ่ชใ—ใฆใใ‚ŒใŸใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚๐Ÿค“ -**FastAPI** ใŒใฉใฎใ‚ˆใ†ใซไฝฟใ‚ใ‚Œใ€ใฉใ“ใŒๆฐ—ใซๅ…ฅใ‚‰ใ‚Œใ€ใฉใ‚“ใชใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ/ไผš็คพใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ใ‹ใชใฉใซใคใ„ใฆ็Ÿฅใ‚ŠใŸใ„ใงใ™ใ€‚ +## ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ไฝœๆˆ { #create-a-pull-request } -## FastAPIใซๆŠ•็ฅจ +[่ฒข็Œฎ](contributing.md){.internal-link target=_blank}ใจใ—ใฆใ€ๆฌกใฎใ‚ˆใ†ใซใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใงใ‚ฝใƒผใ‚นใ‚ณใƒผใƒ‰ใซ่ฒข็Œฎใงใใพใ™: -* Slantใง **FastAPI** ใซๆŠ•็ฅจ -* AlternativeToใง **FastAPI** ใซๆŠ•็ฅจ -* awesome-restใง **FastAPI** ใซๆŠ•็ฅจ +* ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ฆ‹ใคใ‘ใŸใ‚ฟใ‚คใƒใฎไฟฎๆญฃใ€‚ +* ่‡ชๅˆ†ใŒไฝœๆˆ/็™บ่ฆ‹ใ—ใŸ FastAPI ใซ้–ขใ™ใ‚‹่จ˜ไบ‹ใƒปๅ‹•็”ปใƒปใƒใƒƒใƒ‰ใ‚ญใƒฃใ‚นใƒˆใ‚’ใ€ใ“ใฎใƒ•ใ‚กใ‚คใƒซใ‚’็ทจ้›†ใ—ใฆๅ…ฑๆœ‰ใ€‚ + * ่ฉฒๅฝ“ใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎๅ…ˆ้ ญใซใƒชใƒณใ‚ฏใ‚’่ฟฝๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ +* ่‡ชๅˆ†ใฎ่จ€่ชžใธใฎ[ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็ฟป่จณใ‚’ๆ‰‹ไผใ†](contributing.md#translations){.internal-link target=_blank}ใ€‚ + * ไป–ใฎไบบใŒไฝœๆˆใ—ใŸ็ฟป่จณใฎใƒฌใƒ“ใƒฅใƒผใ‚‚ๆ‰‹ไผใˆใพใ™ใ€‚ +* ๆ–ฐใ—ใ„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ปใ‚ฏใ‚ทใƒงใƒณใฎๆๆกˆใ€‚ +* ๆ—ขๅญ˜ใฎissue/ใƒใ‚ฐใฎไฟฎๆญฃใ€‚ + * ใƒ†ใ‚นใƒˆใ‚’่ฟฝๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ +* ๆ–ฐๆฉŸ่ƒฝใฎ่ฟฝๅŠ ใ€‚ + * ใƒ†ใ‚นใƒˆใ‚’่ฟฝๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ + * ้–ข้€ฃใŒใ‚ใ‚Œใฐใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚‚่ฟฝๅŠ ใ—ใฆใใ ใ•ใ„ใ€‚ -## GitHub issuesใงไป–ใฎไบบใ‚’ๅŠฉใ‘ใ‚‹ +## FastAPIใฎใƒกใƒณใƒ†ใƒŠใƒณใ‚นใ‚’ๆ‰‹ไผใ† { #help-maintain-fastapi } -ๆ—ขๅญ˜ใฎissuesใ‚’็ขบ่ชใ—ใฆใ€ไป–ใฎไบบใ‚’ๅŠฉใ‘ใฆใฟใฆใใ ใ•ใ„ใ€‚็š†ใ•ใ‚“ใŒๅ›ž็ญ”ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„่ณชๅ•ใŒใปใจใ‚“ใฉใงใ™ใ€‚๐Ÿค“ +**FastAPI** ใฎใƒกใƒณใƒ†ใƒŠใƒณใ‚นใ‚’ๆ‰‹ไผใฃใฆใใ ใ•ใ„๏ผ๐Ÿค“ -## GitHubใƒฌใƒใ‚ธใƒˆใƒชใ‚’Watch +ใ‚„ใ‚‹ใ“ใจใฏใŸใใ•ใ‚“ใ‚ใ‚Šใ€ใใฎๅคšใใฏ**ใ‚ใชใŸ**ใซใ‚‚ใงใใพใ™ใ€‚ -GitHubใงFastAPIใ‚’ใ€Œwatchใ€ใงใใพใ™ (ๅณไธŠ้ƒจใฎใ€Œwatchใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏ): https://github.com/fastapi/fastapi. ๐Ÿ‘€ +ไปŠใ™ใใงใใ‚‹ไธปใชใ‚ฟใ‚นใ‚ฏใฏๆฌกใฎใจใŠใ‚Šใงใ™: -ใ€ŒReleases onlyใ€ใงใฏใชใใ€ŒWatchingใ€ใ‚’้ธๆŠžใ™ใ‚‹ใจใ€ๆ–ฐใŸใชissueใŒ็ซ‹ใฆใ‚‰ใ‚ŒใŸ้š›ใซ้€š็Ÿฅใ•ใ‚Œใพใ™ใ€‚ +* [GitHubใง่ณชๅ•ใซๅ›ฐใฃใฆใ„ใ‚‹ไบบใ‚’ๅŠฉใ‘ใ‚‹](#help-others-with-questions-in-github){.internal-link target=_blank}๏ผˆไธŠใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…ง๏ผ‰ใ€‚ +* [ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใƒฌใƒ“ใƒฅใƒผ](#review-pull-requests){.internal-link target=_blank}๏ผˆไธŠใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๅ‚็…ง๏ผ‰ใ€‚ -ใใ—ใฆใ€issueใ‚’่งฃๆฑบใ—ไป–ใฎไบบใ‚’ๅŠฉใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ“ใฎ2ใคใŒ**ๆœ€ใ‚‚ๆ™‚้–“ใ‚’ๆถˆ่ฒป**ใ—ใพใ™ใ€‚FastAPI ใฎใƒกใƒณใƒ†ใƒŠใƒณใ‚นไฝœๆฅญใฎไธญๅฟƒใงใ™ใ€‚ -## issuesใ‚’็ซ‹ใฆใ‚‹ +ใ“ใ‚Œใ‚’ๆ‰‹ไผใฃใฆใ‚‚ใ‚‰ใˆใ‚‹ใจใ€**FastAPIใฎใƒกใƒณใƒ†ใƒŠใƒณใ‚นใซ่ฒข็Œฎ**ใ—ใ€**ใ‚ˆใ‚Š้€Ÿใใƒปใ‚ˆใ‚Š่‰ฏใๅ‰้€ฒ**ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚๐Ÿš€ -GitHubใƒฌใƒใ‚ธใƒˆใƒชใงๆ–ฐใŸใชissueใ‚’็ซ‹ใฆใ‚‰ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐ: +## ใƒใƒฃใƒƒใƒˆใซๅ‚ๅŠ  { #join-the-chat } -* ่ณชๅ•ใ€ใพใŸใฏใ€ๅ•้กŒใฎๅ ฑๅ‘Š -* ๆ–ฐๆฉŸ่ƒฝใฎๆๆกˆ +๐Ÿ‘ฅ Discord ใƒใƒฃใƒƒใƒˆใ‚ตใƒผใƒใƒผ ๐Ÿ‘ฅ ใซๅ‚ๅŠ ใ—ใ€FastAPI ใ‚ณใƒŸใƒฅใƒ‹ใƒ†ใ‚ฃใฎใฟใ‚“ใชใจไบคๆตใ—ใพใ—ใ‚‡ใ†ใ€‚ -**Note**: issueใ‚’็ซ‹ใฆใŸไบบใฏใ€ไป–ใฎไบบใฎๆ‰‹ๅŠฉใ‘ใ‚‚ใŠ้ก˜ใ„ใ—ใพใ™ใ€‚๐Ÿ˜‰ +/// tip | ่ฑ†็Ÿฅ่ญ˜ -## ใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ใ™ใ‚‹ +่ณชๅ•ใฏ GitHub Discussions ใซๆŠ•็จฟใ—ใฆใใ ใ•ใ„ใ€‚ใใ“ใชใ‚‰[FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}ใ‹ใ‚‰ๅŠฉใ‘ใฆใ‚‚ใ‚‰ใˆใ‚‹ๅฏ่ƒฝๆ€งใŒใšใฃใจ้ซ˜ใ„ใงใ™ใ€‚ -ไปฅไธ‹ใฎๆง˜ใชใƒ—ใƒซใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ไฝœๆˆใงใใพใ™: +ใƒใƒฃใƒƒใƒˆใฏไธ€่ˆฌ็š„ใชไผš่ฉฑใฎใฟใซไฝฟใ„ใพใ—ใ‚‡ใ†ใ€‚ -* ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ฟใ‚คใƒ—ใƒŸใ‚นใ‚’ไฟฎๆญฃใ€‚ -* ๆ–ฐใŸใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚’ๆๆกˆใ€‚ -* ๆ—ขๅญ˜ใฎissue/ใƒใ‚ฐใ‚’ไฟฎๆญฃใ€‚ -* ๆ–ฐๆฉŸ่ƒฝใ‚’่ฟฝๅŠ ใ€‚ +/// -## ้–‹็™บ่€…ใฎใ‚นใƒใƒณใ‚ตใƒผใซใชใ‚‹ +### ่ณชๅ•ใงใƒใƒฃใƒƒใƒˆใ‚’ไฝฟใ‚ใชใ„ { #dont-use-the-chat-for-questions } -GitHub sponsorsใ‚’้€šใ—ใฆ้–‹็™บ่€…ใ‚’็ตŒๆธˆ็š„ใซใ‚ตใƒใƒผใƒˆใงใใพใ™ใ€‚ +ใƒใƒฃใƒƒใƒˆใฏใ€Œ่‡ช็”ฑใชไผš่ฉฑใ€ใŒใ—ใ‚„ใ™ใ„ใŸใ‚ใ€ไธ€่ˆฌ็š„ใ™ใŽใฆ็ญ”ใˆใซใใ„่ณชๅ•ใซใชใ‚ŠใŒใกใงใ™ใ€‚ใใฎใŸใ‚ใ€ๅ›ž็ญ”ใŒๅพ—ใ‚‰ใ‚Œใชใ„ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใ“ใงใ€ๆ„Ÿ่ฌใฎๆฐ—ๆŒใกใ‚’ไผใˆใ‚‹ใŸใ‚ใซใ‚ณใƒผใƒ’ใƒผโ˜•๏ธใ‚’่ฒทใ†ใ“ใจใŒใงใใพใ™ ๐Ÿ˜„ใ€‚ +GitHub ใงใฏใ€ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใŒๆญฃใ—ใ„ๅฝขใง่ณชๅ•ใ‚’ๆ›ธใใฎใ‚’ๅŠฉใ‘ใฆใใ‚Œใ‚‹ใŸใ‚ใ€่‰ฏใ„ๅ›ž็ญ”ใ‚’ๅพ—ใ‚„ใ™ใใชใ‚Šใพใ™ใ—ใ€่ณชๅ•ใ™ใ‚‹ๅ‰ใซ่‡ชๅˆ†ใงๅ•้กŒใ‚’่งฃๆฑบใงใใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ใ•ใ‚‰ใซGitHubใชใ‚‰ใ€ๆ™‚้–“ใŒใ‹ใ‹ใฃใฆใ‚‚็งใŒๅฟ…ใšใ™ในใฆใซๅ›ž็ญ”ใงใใ‚‹ใ‚ˆใ†ใซใงใใพใ™ใ€‚ใƒใƒฃใƒƒใƒˆใงใฏ็งๅ€‹ไบบใซใฏใใ‚ŒใŒใงใใพใ›ใ‚“ใ€‚๐Ÿ˜… -## FastAPIใ‚’ๅผทๅŒ–ใ™ใ‚‹ใƒ„ใƒผใƒซใฎใ‚นใƒใƒณใ‚ตใƒผใซใชใ‚‹ +ใƒใƒฃใƒƒใƒˆใงใฎไผš่ฉฑใฏGitHubใปใฉๆคœ็ดขใ—ใ‚„ใ™ใใชใ„ใŸใ‚ใ€่ณชๅ•ใจๅ›ž็ญ”ใŒไผš่ฉฑใซๅŸ‹ใ‚‚ใ‚ŒใŒใกใงใ™ใ€‚ใใ—ใฆใ€[FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}ใซใชใ‚‹ใŸใ‚ใซใ‚ซใ‚ฆใƒณใƒˆใ•ใ‚Œใ‚‹ใฎใฏGitHubไธŠใฎๆดปๅ‹•ใ ใ‘ใงใ™ใ€‚ใงใ™ใ‹ใ‚‰ใ€GitHubใฎๆ–นใŒๆณจ็›ฎใ‚’้›†ใ‚ใ‚„ใ™ใ„ใงใ—ใ‚‡ใ†ใ€‚ -ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง่ฆ‹ใŸใ‚ˆใ†ใซใ€FastAPIใฏStarletteใจPydanticใจใ„ใ†ๅทจไบบใฎ่‚ฉใซไน—ใฃใฆใ„ใพใ™ใ€‚ +ไธ€ๆ–นใงใ€ใƒใƒฃใƒƒใƒˆใซใฏๆ•ฐๅƒไบบใฎใƒฆใƒผใ‚ถใƒผใŒใ„ใ‚‹ใŸใ‚ใ€ใปใผๅธธใซ่ชฐใ‹ใจไผš่ฉฑใงใใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใงใ™ใ€‚๐Ÿ˜„ -ไปฅไธ‹ใฎใ‚นใƒใƒณใ‚ตใƒผใซใชใ‚‹ใ“ใจใ‚‚ใงใใพใ™: +## ไฝœ่€…ใ‚’ใ‚นใƒใƒณใ‚ตใƒผ { #sponsor-the-author } -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +ใ‚ใชใŸใฎ**่ฃฝๅ“/ไผš็คพ**ใŒ **FastAPI** ใซไพๅญ˜ใ—ใฆใ„ใ‚‹ใ€ใพใŸใฏ้–ข้€ฃใ—ใฆใŠใ‚Šใ€ใใฎใƒฆใƒผใ‚ถใƒผใซใƒชใƒผใƒใ—ใŸใ„ๅ ดๅˆใฏใ€GitHub sponsors ใ‚’้€šใ˜ใฆไฝœ่€…๏ผˆ็ง๏ผ‰ใ‚’ๆ”ฏๆดใงใใพใ™ใ€‚ใƒ—ใƒฉใƒณใซๅฟœใ˜ใฆใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใƒใƒƒใ‚ธใŒ่กจ็คบใ•ใ‚Œใ‚‹ใชใฉใฎ็‰นๅ…ธใŒใ‚ใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚๐ŸŽ --- diff --git a/docs/ja/docs/history-design-future.md b/docs/ja/docs/history-design-future.md index 6cfd1894d8..1465557080 100644 --- a/docs/ja/docs/history-design-future.md +++ b/docs/ja/docs/history-design-future.md @@ -1,13 +1,12 @@ -# ๆญดๅฒใ€่จญ่จˆใ€ใใ—ใฆใ“ใ‚Œใ‹ใ‚‰ +# ๆญดๅฒใ€่จญ่จˆใ€ใใ—ใฆใ“ใ‚Œใ‹ใ‚‰ { #history-design-and-future } -ๅฐ‘ใ—ๅ‰ใซใ€**FastAPI** -ใฎใƒฆใƒผใ‚ถใƒผใซไปฅไธ‹ใฎๆง˜ใซๅฐ‹ใญใ‚‰ใ‚Œใพใ—ใŸ: +ๅฐ‘ใ—ๅ‰ใซใ€**FastAPI**ใฎใƒฆใƒผใ‚ถใƒผใซไปฅไธ‹ใฎๆง˜ใซๅฐ‹ใญใ‚‰ใ‚Œใพใ—ใŸ: > ใ“ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎๆญดๅฒใฏ๏ผŸไฝ•ใ‚‚ใชใ„ใจใ“ใ‚ใ‹ใ‚‰ใ€ๆ•ฐ้€ฑ้–“ใงใ™ใ”ใ„ใ‚‚ใฎใŒใงใใฆใ„ใ‚‹ใ‚ˆใ†ใงใ™ใ€‚ [...] ใ“ใ‚ŒใŒใใฎๆญดๅฒใฎใปใ‚“ใฎไธ€้ƒจใงใ™ใ€‚ -## ไปฃๆ›ฟๆ‰‹ๆฎต +## ไปฃๆ›ฟๆ‰‹ๆฎต { #alternatives } ๆ•ฐๅนดๅ‰ใ‹ใ‚‰ใ€็งใฏ่ค‡้›‘ใช่ฆไปถใ‚’ๆŒใคAPI (ๆฉŸๆขฐๅญฆ็ฟ’ใ€ๅˆ†ๆ•ฃใ‚ทใ‚นใƒ†ใƒ ใ€้žๅŒๆœŸใ‚ธใƒงใƒ–ใ€NoSQLใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใชใฉ) ใ‚’ไฝœๆˆใ—ใฆใŠใ‚Šใ€ใ„ใใคใ‹ใฎ้–‹็™บ่€…ใƒใƒผใƒ ใ‚’็އใ„ใฆใ„ใพใ™ใ€‚ @@ -19,7 +18,7 @@
-**FastAPI**ใฏใ€ไปฃๆ›ฟใƒ„ใƒผใƒซใฎใ“ใ‚ŒใพใงใฎๅƒใใŒใชใ‘ใ‚Œใฐๅญ˜ๅœจใ—ใชใ‹ใฃใŸใงใ—ใ‚‡ใ†ใ€‚ +**FastAPI**ใฏใ€ไป–ใฎไบบใ€…ใฎใ“ใ‚ŒใพใงใฎๅƒใใŒใชใ‘ใ‚Œใฐๅญ˜ๅœจใ—ใชใ‹ใฃใŸใงใ—ใ‚‡ใ†ใ€‚ ไปฅๅ‰ใซไฝœใ‚‰ใ‚ŒใŸๅคšใใฎใƒ„ใƒผใƒซใŒใ€ไฝœๆˆใซใŠใ‘ใ‚‹ๅˆบๆฟ€ใจใ—ใฆๅฝน็ซ‹ใฃใฆใใพใ—ใŸใ€‚ @@ -29,7 +28,7 @@
-## ่ชฟๆŸป +## ่ชฟๆŸป { #investigation } ใ™ในใฆๆ—ขๅญ˜ใฎไปฃๆ›ฟๆ‰‹ๆฎตใ‚’ไฝฟใ†ใ“ใจใงใ€ใใฎใ™ในใฆใ‚’ๅญฆใณใ€ใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ๅพ—ใฆใ€่‡ชๅˆ†ใ‚„ไธ€็ท’ใซไป•ไบ‹ใ‚’ใ—ใฆใใŸ้–‹็™บ่€…ใฎใƒใƒผใƒ ใซใจใฃใฆๆœ€่‰ฏใฎๆ–นๆณ•ใง็ต„ใฟๅˆใ‚ใ›ใ‚‹ๆฉŸไผšใ‚’ๅพ—ใพใ—ใŸใ€‚ @@ -39,7 +38,7 @@ ใใ“ใงใ€**FastAPI**ใฎใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใๅง‹ใ‚ใ‚‹ๅ‰ใซใ€OpenAPIใ€JSON Schemaใ€OAuth2ใชใฉใฎไป•ๆง˜ใ‚’ๆ•ฐใƒถๆœˆใ‹ใ‘ใฆๅ‹‰ๅผทใ—ใ€ใใ‚Œใ‚‰ใฎ้–ขไฟ‚ใ€้‡่ค‡ใ™ใ‚‹็ฎ‡ๆ‰€ใ€็›ธ้•็‚นใ‚’็†่งฃใ—ใพใ—ใŸใ€‚ -## ่จญ่จˆ +## ่จญ่จˆ { #design } ใใฎๅพŒใ€ (FastAPIใ‚’ไฝฟใ†้–‹็™บ่€…ใจใ—ใฆ) ใƒฆใƒผใ‚ถใƒผใŒๆฌฒใ—ใ„ใ€ŒAPIใ€ใฎ่จญ่จˆใซๆ™‚้–“ใ‚’่ฒปใ‚„ใ—ใพใ—ใŸใ€‚ @@ -53,19 +52,19 @@ ใ™ในใฆใฎ็ฎ‡ๆ‰€ใงใ€ใ™ในใฆใฎ้–‹็™บ่€…ใซๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“ใ‚’ๆไพ›ใ—ใพใ—ใŸใ€‚ -## ่ฆไปถ +## ่ฆไปถ { #requirements } ใ„ใใคใ‹ใฎไปฃๆ›ฟๆ‰‹ๆณ•ใ‚’่ฉฆใ—ใŸใ‚ใจใ€็งใฏ**Pydantic**ใฎๅผทใฟใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใ‚’ๆฑบใ‚ใพใ—ใŸใ€‚ ใใ—ใฆใ€JSON SchemaใซๅฎŒๅ…จใซๆบ–ๆ‹ ใ™ใ‚‹ใ‚ˆใ†ใซใ—ใŸใ‚Šใ€ๅˆถ็ด„ๅฎฃ่จ€ใ‚’ๅฎš็พฉใ™ใ‚‹ใ•ใพใ–ใพใชๆ–นๆณ•ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใŸใ‚Šใ€ใ„ใใคใ‹ใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใงใฎใƒ†ใ‚นใƒˆใซๅŸบใฅใ„ใฆใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใฎใ‚ตใƒใƒผใƒˆ (ๅž‹ใƒใ‚งใƒƒใ‚ฏใ€่‡ชๅ‹•่ฃœๅฎŒ) ใ‚’ๆ”นๅ–„ใ™ใ‚‹ใŸใ‚ใซ่ฒข็Œฎใ—ใพใ—ใŸใ€‚ -้–‹็™บไธญใ€ใ‚‚ใ†1ใคใฎ้‡่ฆใช้ตใจใชใ‚‹**Starlette**ใ€ใซใ‚‚่ฒข็Œฎใ—ใพใ—ใŸใ€‚ +้–‹็™บไธญใ€ใ‚‚ใ†1ใคใฎ้‡่ฆใช้ตใจใชใ‚‹**Starlette**ใซใ‚‚่ฒข็Œฎใ—ใพใ—ใŸใ€‚ -## ้–‹็™บ +## ้–‹็™บ { #development } ็งใŒ**FastAPI**่‡ชไฝ“ใฎไฝœๆˆใ‚’้–‹ๅง‹ใ—ใŸๆ™‚ใซใฏใ€ใปใจใ‚“ใฉใฎ้ƒจๅˆ†ใŒใ™ใงใซๆบ–ๅ‚™ใ•ใ‚ŒใฆใŠใ‚Šใ€่จญ่จˆใŒๅฎš็พฉใ•ใ‚Œใ€ๅฟ…่ฆใชๆกไปถใจใƒ„ใƒผใƒซใฎๆบ–ๅ‚™ใŒใงใใฆใ„ใพใ—ใŸใ€‚ใใ—ใฆ่ฆๆ ผใ‚„ไป•ๆง˜ใซ้–ขใ™ใ‚‹็Ÿฅ่ญ˜ใŒใ€ๆ˜Ž็ขบใซใชใ‚Šใ€ๆ›ดๆ–ฐใ•ใ‚Œใฆใ„ใพใ—ใŸใ€‚ -## ใ“ใ‚Œใ‹ใ‚‰ +## ใ“ใ‚Œใ‹ใ‚‰ { #future } ใ“ใฎๆ™‚็‚นใงใ™ใงใซใ€ใ“ใ‚Œใ‚‰ใฎใ‚ขใ‚คใƒ‡ใ‚ขใ‚’ๆŒใฃใŸ**FastAPI**ใŒๅคšใใฎไบบใฎๅฝนใซ็ซ‹ใฃใฆใ„ใ‚‹ใ“ใจใฏๆ˜Žใ‚‰ใ‹ใงใ™ใ€‚ diff --git a/docs/ja/docs/how-to/authentication-error-status-code.md b/docs/ja/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..9bef476444 --- /dev/null +++ b/docs/ja/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# ๅคใ„ 403 ่ช่จผใ‚จใƒฉใƒผใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใ‚’ไฝฟใ† { #use-old-403-authentication-error-status-codes } + +FastAPI ใƒใƒผใ‚ธใƒงใƒณ `0.122.0` ใ‚ˆใ‚Šๅ‰ใฏใ€็ตฑๅˆใ•ใ‚ŒใŸใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใŒ่ช่จผใซๅคฑๆ•—ใ—ใฆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใธใ‚จใƒฉใƒผใ‚’่ฟ”ใ™้š›ใ€HTTP ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `403 Forbidden` ใ‚’ไฝฟ็”จใ—ใฆใ„ใพใ—ใŸใ€‚ + +FastAPI ใƒใƒผใ‚ธใƒงใƒณ `0.122.0` ไปฅ้™ใงใฏใ€ใ‚ˆใ‚Š้ฉๅˆ‡ใช HTTP ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ `401 Unauthorized` ใ‚’ไฝฟ็”จใ—ใ€HTTP ไป•ๆง˜ใซๅพ“ใฃใฆใƒฌใ‚นใƒใƒณใ‚นใซๅฆฅๅฝ“ใช `WWW-Authenticate` ใƒ˜ใƒƒใƒ€ใƒผใ‚’ๅซใ‚ใพใ™ใ€‚RFC 7235ใ€RFC 9110ใ€‚ + +ใ—ใ‹ใ—ใ€ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅพ“ๆฅใฎๆŒ™ๅ‹•ใซไพๅญ˜ใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ฏใƒฉใ‚นใงใƒกใ‚ฝใƒƒใƒ‰ `make_not_authenticated_error` ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ™ใ‚‹ใ“ใจใงใ€ใใฎๆŒ™ๅ‹•ใซๆˆปใ›ใพใ™ใ€‚ + +ใŸใจใˆใฐใ€ๆ—ขๅฎšใฎ `401 Unauthorized` ใ‚จใƒฉใƒผใฎไปฃใ‚ใ‚Šใซ `403 Forbidden` ใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ `HTTPBearer` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใงใใพใ™: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎ้–ขๆ•ฐใฏไพ‹ๅค–ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’่ฟ”ใ™็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ“ใ“ใงใฏไพ‹ๅค–ใ‚’้€ๅ‡บใ—ใพใ›ใ‚“ใ€‚้€ๅ‡บใฏๅ†…้ƒจใฎไป–ใฎใ‚ณใƒผใƒ‰ใง่กŒใ‚ใ‚Œใพใ™ใ€‚ + +/// diff --git a/docs/ja/docs/how-to/conditional-openapi.md b/docs/ja/docs/how-to/conditional-openapi.md index 9478f5c032..0febe1ef67 100644 --- a/docs/ja/docs/how-to/conditional-openapi.md +++ b/docs/ja/docs/how-to/conditional-openapi.md @@ -10,7 +10,7 @@ ใ‚‚ใ—ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃไธŠใฎๆฌ ้™ฅใŒใ‚ฝใƒผใ‚นใ‚ณใƒผใƒ‰ใซใ‚ใ‚‹ใชใ‚‰ใฐใ€ใใ‚Œใฏๅญ˜ๅœจใ—ใŸใพใพใงใ™ใ€‚ -ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณใ‚’้ž่กจ็คบใซใ™ใ‚‹ใฎใฏใ€ๅ˜ใซใ‚ใชใŸใฎAPIใธใฎใ‚ขใ‚ฏใ‚ปใ‚นๆ–นๆณ•ใ‚’้›ฃ่งฃใซใ™ใ‚‹ใ ใ‘ใงใชใใ€ๅŒๆ™‚ใซใ‚ใชใŸ่‡ช่บซใฎๆœฌ็•ช็’ฐๅขƒใงใฎAPIใฎใƒ‡ใƒใƒƒใ‚ฐใ‚’ๅ›ฐ้›ฃใซใ—ใฆใ—ใพใ†ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ๅ˜็ด”ใซใ€ Security through obscurity ใฎไธ€ใคใฎๅฝขๆ…‹ใจใ—ใฆ่€ƒใˆใ‚‰ใ‚Œใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒ†ใƒผใ‚ทใƒงใƒณใ‚’้ž่กจ็คบใซใ™ใ‚‹ใฎใฏใ€ๅ˜ใซใ‚ใชใŸใฎAPIใธใฎใ‚ขใ‚ฏใ‚ปใ‚นๆ–นๆณ•ใ‚’้›ฃ่งฃใซใ™ใ‚‹ใ ใ‘ใงใชใใ€ๅŒๆ™‚ใซใ‚ใชใŸ่‡ช่บซใฎๆœฌ็•ช็’ฐๅขƒใงใฎAPIใฎใƒ‡ใƒใƒƒใ‚ฐใ‚’ๅ›ฐ้›ฃใซใ—ใฆใ—ใพใ†ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ๅ˜็ด”ใซใ€ ็ง˜ๅŒฟใซใ‚ˆใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ ใฎไธ€ใคใฎๅฝขๆ…‹ใจใ—ใฆ่€ƒใˆใ‚‰ใ‚Œใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ ใ‚‚ใ—ใ‚ใชใŸใฎAPIใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’ๅผทๅŒ–ใ—ใŸใ„ใชใ‚‰ใ€ใ„ใใคใ‹ใฎใ‚ˆใ‚Šใ‚ˆใ„ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ไพ‹ใ‚’็คบใ™ใจใ€ @@ -29,7 +29,7 @@ ไพ‹ใˆใฐใ€ -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} ใ“ใ“ใงใฏ `openapi_url` ใฎ่จญๅฎšใ‚’ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ `"/openapi.json"` ใฎใพใพๅฎฃ่จ€ใ—ใฆใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/how-to/configure-swagger-ui.md b/docs/ja/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000..8be7adc84c --- /dev/null +++ b/docs/ja/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Swagger UI ใฎ่จญๅฎš { #configure-swagger-ui } + +ใ„ใใคใ‹ใฎ่ฟฝๅŠ ใฎ Swagger UI ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใงใใพใ™ใ€‚ + +่จญๅฎšใ™ใ‚‹ใซใฏใ€`FastAPI()` ใฎใ‚ขใƒ—ใƒชใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ™ใ‚‹ใจใใ€ใพใŸใฏ `get_swagger_ui_html()` ้–ขๆ•ฐใซ `swagger_ui_parameters` ๅผ•ๆ•ฐใ‚’ๆธกใ—ใพใ™ใ€‚ + +`swagger_ui_parameters` ใฏใ€Swagger UI ใซ็›ดๆŽฅๆธกใ•ใ‚Œใ‚‹่จญๅฎšใ‚’ๅซใ‚€่พžๆ›ธใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ + +FastAPI ใฏใใ‚Œใ‚‰ใฎ่จญๅฎšใ‚’ **JSON** ใซๅค‰ๆ›ใ—ใ€JavaScript ใจไบ’ๆ›ใซใ—ใพใ™ใ€‚Swagger UI ใŒๅฟ…่ฆใจใ™ใ‚‹ใฎใฏใ“ใฎๅฝขๅผใงใ™ใ€‚ + +## ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใ‚’็„กๅŠนๅŒ– { #disable-syntax-highlighting } + +ไพ‹ใˆใฐใ€Swagger UI ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใ‚’็„กๅŠนๅŒ–ใงใใพใ™ใ€‚ + +่จญๅฎšใ‚’ๅค‰ๆ›ดใ—ใชใ‘ใ‚Œใฐใ€ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๆœ‰ๅŠนใงใ™: + + + +ใ—ใ‹ใ—ใ€`syntaxHighlight` ใ‚’ `False` ใซ่จญๅฎšใ™ใ‚‹ใจ็„กๅŠนๅŒ–ใงใใพใ™: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...ใใฎๅ ดๅˆใ€Swagger UI ใงใฏใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใŒ่กจ็คบใ•ใ‚Œใชใใชใ‚Šใพใ™: + + + +## ใƒ†ใƒผใƒžใฎๅค‰ๆ›ด { #change-the-theme } + +ๅŒๆง˜ใซใ€ใ‚ญใƒผ `"syntaxHighlight.theme"`๏ผˆ้€”ไธญใซใƒ‰ใƒƒใƒˆใŒๅซใพใ‚Œใฆใ„ใ‚‹็‚นใซๆณจๆ„๏ผ‰ใงใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใฎใƒ†ใƒผใƒžใ‚’่จญๅฎšใงใใพใ™: + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +ใ“ใฎ่จญๅฎšใซใ‚ˆใ‚Šใ€ใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใƒใ‚คใƒฉใ‚คใƒˆใฎ้…่‰ฒใƒ†ใƒผใƒžใŒๅค‰ใ‚ใ‚Šใพใ™: + + + +## ๆ—ขๅฎšใฎ Swagger UI ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅค‰ๆ›ด { #change-default-swagger-ui-parameters } + +FastAPI ใซใฏใ€ๅคšใใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซ้ฉใ—ใŸๆ—ขๅฎšใฎ่จญๅฎšใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +ๆ—ขๅฎšใงใฏๆฌกใฎ่จญๅฎšใŒๅซใพใ‚Œใพใ™: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +ๅผ•ๆ•ฐ `swagger_ui_parameters` ใซๅˆฅใฎๅ€คใ‚’ๆŒ‡ๅฎšใ™ใ‚‹ใ“ใจใงใ€ใ“ใ‚Œใ‚‰ใ‚’ไธŠๆ›ธใใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`deepLinking` ใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใซใฏใ€ๆฌกใฎ่จญๅฎšใ‚’ `swagger_ui_parameters` ใซๆธกใ—ใพใ™: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## ใใฎไป–ใฎ Swagger UI ใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #other-swagger-ui-parameters } + +ๅˆฉ็”จๅฏ่ƒฝใชไป–ใฎใ™ในใฆใฎ่จญๅฎšใซใคใ„ใฆใฏใ€ๅ…ฌๅผใฎ Swagger UI ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## JavaScript ๅฐ‚็”จใฎ่จญๅฎš { #javascript-only-settings } + +Swagger UI ใงใฏใ€ไป–ใซใ‚‚ **JavaScript ๅฐ‚็”จ** ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆไพ‹: JavaScript ใฎ้–ขๆ•ฐ๏ผ‰ใซใ‚ˆใ‚‹่จญๅฎšใŒๅฏ่ƒฝใงใ™ใ€‚ + +FastAPI ใซใฏใ€ๆฌกใฎ JavaScript ๅฐ‚็”จใฎ `presets` ่จญๅฎšใ‚‚ๅซใพใ‚Œใฆใ„ใพใ™: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +ใ“ใ‚Œใ‚‰ใฏๆ–‡ๅญ—ๅˆ—ใงใฏใชใ **JavaScript** ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ‚ใ‚‹ใŸใ‚ใ€Python ใฎใ‚ณใƒผใƒ‰ใ‹ใ‚‰็›ดๆŽฅๆธกใ™ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ + +ใใฎใ‚ˆใ†ใช JavaScript ๅฐ‚็”จใฎ่จญๅฎšใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ไธŠ่จ˜ใฎใ„ใšใ‚Œใ‹ใฎๆ–นๆณ•ใ‚’ไฝฟ็”จใ—ใ€Swagger UI ใฎ path operation ใ‚’ใ‚ชใƒผใƒใƒผใƒฉใ‚คใƒ‰ใ—ใฆใ€ๅฟ…่ฆใช JavaScript ใ‚’ๆ‰‹ๅ‹•ใง่จ˜่ฟฐใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/how-to/custom-docs-ui-assets.md b/docs/ja/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..c0c9745b28 --- /dev/null +++ b/docs/ja/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ใ‚ซใ‚นใ‚ฟใƒ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใฎ้™็š„ใ‚ขใ‚ปใƒƒใƒˆ๏ผˆใ‚ปใƒซใƒ•ใƒ›ใ‚นใƒ†ใ‚ฃใƒณใ‚ฐ๏ผ‰ { #custom-docs-ui-static-assets-self-hosting } + +API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏ **Swagger UI** ใจ **ReDoc** ใ‚’ไฝฟ็”จใ—ใฆใŠใ‚Šใ€ใใ‚Œใžใ‚Œใซใ„ใใคใ‹ใฎ JavaScript ใจ CSS ใƒ•ใ‚กใ‚คใƒซใŒๅฟ…่ฆใงใ™ใ€‚ + +ๆ—ขๅฎšใงใฏใ€ใ“ใ‚Œใ‚‰ใฎใƒ•ใ‚กใ‚คใƒซใฏ CDN ใ‹ใ‚‰้…ไฟกใ•ใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใ™ใ‚‹ใ“ใจใ‚‚ๅฏ่ƒฝใงใ€็‰นๅฎšใฎ CDN ใ‚’ๆŒ‡ๅฎšใ—ใŸใ‚Šใ€่‡ชๅˆ†ใงใƒ•ใ‚กใ‚คใƒซใ‚’้…ไฟกใ—ใŸใ‚Šใงใใพใ™ใ€‚ + +## JavaScript ใจ CSS ใฎใ‚ซใ‚นใ‚ฟใƒ  CDN { #custom-cdn-for-javascript-and-css } + +ๅˆฅใฎ CDN ใ‚’ไฝฟใ„ใŸใ„ใจใ—ใพใ™ใ€‚ไพ‹ใˆใฐ `https://unpkg.com/` ใ‚’ไฝฟใ„ใŸใ„ๅ ดๅˆใงใ™ใ€‚ + +ไพ‹ใˆใฐใ€ไธ€้ƒจใฎ URL ใŒๅˆถ้™ใ•ใ‚Œใฆใ„ใ‚‹ๅ›ฝใซไฝใ‚“ใงใ„ใ‚‹ๅ ดๅˆใซๅฝน็ซ‹ใกใพใ™ใ€‚ + +### ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็„กๅŠนๅŒ– { #disable-the-automatic-docs } + +ๆœ€ๅˆใฎๆ‰‹้ †ใฏ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใใ‚Œใ‚‰ใฏๆ—ขๅฎšใฎ CDN ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ + +็„กๅŠนๅŒ–ใ™ใ‚‹ใซใฏใ€`FastAPI` ใ‚ขใƒ—ใƒชไฝœๆˆๆ™‚ใซใใ‚Œใ‚‰ใฎ URL ใ‚’ `None` ใซ่จญๅฎšใ—ใพใ™: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### ใ‚ซใ‚นใ‚ฟใƒ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ่ฟฝๅŠ  { #include-the-custom-docs } + +ใ“ใ‚Œใงใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ *path operations* ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ + +FastAPI ใฎๅ†…้ƒจ้–ขๆ•ฐใ‚’ๅ†ๅˆฉ็”จใ—ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใƒšใƒผใ‚ธใ‚’็”Ÿๆˆใ—ใ€ๅฟ…่ฆใชๅผ•ๆ•ฐใ‚’ๆธกใ›ใพใ™: + +- `openapi_url`: ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ HTML ใƒšใƒผใ‚ธใŒ API ใฎ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’ๅ–ๅพ—ใ™ใ‚‹ URLใ€‚ใ“ใ“ใงใฏๅฑžๆ€ง `app.openapi_url` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ +- `title`: API ใฎใ‚ฟใ‚คใƒˆใƒซใ€‚ +- `oauth2_redirect_url`: ๆ—ขๅฎšๅ€คใ‚’ไฝฟใ†ใซใฏใ“ใ“ใง `app.swagger_ui_oauth2_redirect_url` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ +- `swagger_js_url`: Swagger UI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใŒๅ–ๅพ—ใ™ใ‚‹ JavaScript ใƒ•ใ‚กใ‚คใƒซใฎ URLใ€‚ใ“ใ‚Œใฏใ‚ซใ‚นใ‚ฟใƒ  CDN ใฎ URL ใงใ™ใ€‚ +- `swagger_css_url`: Swagger UI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใŒๅ–ๅพ—ใ™ใ‚‹ CSS ใƒ•ใ‚กใ‚คใƒซใฎ URLใ€‚ใ“ใ‚Œใฏใ‚ซใ‚นใ‚ฟใƒ  CDN ใฎ URL ใงใ™ใ€‚ + +ReDoc ใซใคใ„ใฆใ‚‚ๅŒๆง˜ใงใ™... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`swagger_ui_redirect` ็”จใฎ *path operation* ใฏใ€OAuth2 ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฎ่ฃœๅŠฉใงใ™ใ€‚ + +API ใ‚’ OAuth2 ใƒ—ใƒญใƒใ‚คใƒ€ใจ็ตฑๅˆใ™ใ‚‹ใจใ€่ช่จผใ‚’ๅฎŸ่กŒใ—ใฆๅ–ๅพ—ใ—ใŸใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซใ‚’ๆŒใฃใŸ็Šถๆ…‹ใง API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซๆˆปใ‚Œใพใ™ใ€‚ใใ—ใฆๅฎŸ้š›ใฎ OAuth2 ่ช่จผใ‚’็”จใ„ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆไธŠใ‹ใ‚‰ API ใจๅฏพ่ฉฑใงใใพใ™ใ€‚ + +Swagger UI ใŒใ“ใฎๅ‡ฆ็†ใ‚’่ฃๅดใง่กŒใ„ใพใ™ใŒใ€ใใฎใŸใ‚ใซใ“ใฎใ€Œredirectใ€ใฎ่ฃœๅŠฉใŒๅฟ…่ฆใงใ™ใ€‚ + +/// + +### ใƒ†ใ‚นใƒˆ็”จใฎ *path operation* ใ‚’ไฝœๆˆ { #create-a-path-operation-to-test-it } + +ใ™ในใฆใŒๅ‹•ไฝœใ™ใ‚‹ใ‹ใ‚’ใƒ†ใ‚นใƒˆใงใใ‚‹ใ‚ˆใ†ใซใ€*path operation* ใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### ใƒ†ใ‚นใƒˆ { #test-it } + +ใ“ใ‚Œใงใ€http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใƒšใƒผใ‚ธใ‚’ๅ†่ชญใฟ่พผใฟใ™ใ‚‹ใจใ€ๆ–ฐใ—ใ„ CDN ใ‹ใ‚‰ใใ‚Œใ‚‰ใฎใ‚ขใ‚ปใƒƒใƒˆใŒ่ชญใฟ่พผใพใ‚Œใ‚‹ใฏใšใงใ™ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จ JavaScript ใจ CSS ใฎใ‚ปใƒซใƒ•ใƒ›ใ‚นใƒ†ใ‚ฃใƒณใ‚ฐ { #self-hosting-javascript-and-css-for-docs } + +ใ‚ชใƒ•ใƒฉใ‚คใƒณ๏ผˆใ‚คใƒณใ‚ฟใƒผใƒใƒƒใƒˆ้žๆŽฅ็ถš๏ผ‰ใงใ‚‚ใ€ใ‚ใ‚‹ใ„ใฏใƒญใƒผใ‚ซใƒซใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใงใ€ใ‚ขใƒ—ใƒชใ‚’ๅ‹•ไฝœใ•ใ›ใŸใ„ๅ ดๅˆใชใฉใซใฏใ€JavaScript ใจ CSS ใ‚’ใ‚ปใƒซใƒ•ใƒ›ใ‚นใƒˆใ™ใ‚‹ใฎใŒๆœ‰็”จใงใ™ใ€‚ + +ใ“ใ“ใงใฏใ€ๅŒใ˜ FastAPI ใ‚ขใƒ—ใƒชๅ†…ใงใใ‚Œใ‚‰ใฎใƒ•ใ‚กใ‚คใƒซใ‚’้…ไฟกใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใใ‚Œใ‚‰ใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ™ใ‚‹ๆ–นๆณ•ใ‚’็คบใ—ใพใ™ใ€‚ + +### ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆ { #project-file-structure } + +ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใŒๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ใจใ—ใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +ใ“ใ‚Œใ‚‰ใฎ้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’ไฟๅญ˜ใ™ใ‚‹ใŸใ‚ใฎใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ๆ–ฐใ—ใ„ใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### ใƒ•ใ‚กใ‚คใƒซใฎใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ { #download-the-files } + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซๅฟ…่ฆใช้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ใ—ใ€`static/` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ้…็ฝฎใ—ใพใ™ใ€‚ + +ๅ„ใƒชใƒณใ‚ฏใ‚’ๅณใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใ€Œใƒชใƒณใ‚ฏๅ…ˆใ‚’ๅˆฅๅใงไฟๅญ˜...ใ€ใฎใ‚ˆใ†ใชใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’้ธในใพใ™ใ€‚ + +**Swagger UI** ใงใฏๆฌกใฎใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟ็”จใ—ใพใ™: + +- `swagger-ui-bundle.js` +- `swagger-ui.css` + +ใใ—ใฆ **ReDoc** ใงใฏๆฌกใฎใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟ็”จใ—ใพใ™: + +- `redoc.standalone.js` + +ใใฎๅพŒใ€ใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใฏๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซใฎ้…ไฟก { #serve-the-static-files } + +- `StaticFiles` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™ใ€‚ +- ็‰นๅฎšใฎใƒ‘ใ‚นใซ `StaticFiles()` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ—ใพใ™ใ€‚ + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซใฎใƒ†ใ‚นใƒˆ { #test-the-static-files } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’่ตทๅ‹•ใ—ใ€http://127.0.0.1:8000/static/redoc.standalone.js ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใพใ™ใ€‚ + +**ReDoc** ็”จใฎ้žๅธธใซ้•ทใ„ JavaScript ใƒ•ใ‚กใ‚คใƒซใŒ่กจ็คบใ•ใ‚Œใ‚‹ใฏใšใงใ™ใ€‚ + +ๅ…ˆ้ ญใฏๆฌกใฎใ‚ˆใ†ใซใชใฃใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +ใ“ใ‚Œใงใ€ใ‚ขใƒ—ใƒชใ‹ใ‚‰้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’้…ไฟกใงใใฆใ„ใ‚‹ใ“ใจใ€ใใ—ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’ๆญฃใ—ใ„ๅ ดๆ‰€ใซ้…็ฝฎใงใใฆใ„ใ‚‹ใ“ใจใŒ็ขบ่ชใงใใพใ™ใ€‚ + +ๆฌกใซใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใใ‚Œใ‚‰ใฎ้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟ็”จใ™ใ‚‹ใ‚ˆใ†ใซใ‚ขใƒ—ใƒชใ‚’่จญๅฎšใ—ใพใ™ใ€‚ + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซ็”จใซ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็„กๅŠนๅŒ– { #disable-the-automatic-docs-for-static-files } + +ใ‚ซใ‚นใ‚ฟใƒ  CDN ใ‚’ไฝฟใ†ๅ ดๅˆใจๅŒๆง˜ใ€ๆœ€ๅˆใฎๆ‰‹้ †ใฏ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ใ“ใจใงใ™ใ€‚ๆ—ขๅฎšใงใฏ CDN ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ + +็„กๅŠนๅŒ–ใ™ใ‚‹ใซใฏใ€`FastAPI` ใ‚ขใƒ—ใƒชไฝœๆˆๆ™‚ใซใใ‚Œใ‚‰ใฎ URL ใ‚’ `None` ใซ่จญๅฎšใ—ใพใ™: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซ็”จใฎใ‚ซใ‚นใ‚ฟใƒ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ฟฝๅŠ  { #include-the-custom-docs-for-static-files } + +ใ‚ซใ‚นใ‚ฟใƒ  CDN ใจๅŒๆง˜ใฎๆ–นๆณ•ใงใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ *path operations* ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ + +ๅ†ใณใ€FastAPI ใฎๅ†…้ƒจ้–ขๆ•ฐใ‚’ๅ†ๅˆฉ็”จใ—ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใƒšใƒผใ‚ธใ‚’็”Ÿๆˆใ—ใ€ๅฟ…่ฆใชๅผ•ๆ•ฐใ‚’ๆธกใ—ใพใ™: + +- `openapi_url`: ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ HTML ใƒšใƒผใ‚ธใŒ API ใฎ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’ๅ–ๅพ—ใ™ใ‚‹ URLใ€‚ใ“ใ“ใงใฏๅฑžๆ€ง `app.openapi_url` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ +- `title`: API ใฎใ‚ฟใ‚คใƒˆใƒซใ€‚ +- `oauth2_redirect_url`: ๆ—ขๅฎšๅ€คใ‚’ไฝฟใ†ใซใฏใ“ใ“ใง `app.swagger_ui_oauth2_redirect_url` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ +- `swagger_js_url`: Swagger UI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใŒๅ–ๅพ—ใ™ใ‚‹ **JavaScript** ใƒ•ใ‚กใ‚คใƒซใฎ URLใ€‚**ใ“ใ‚Œใฏใ‚ใชใŸใฎใ‚ขใƒ—ใƒช่‡ช่บซใŒใ„ใพ้…ไฟกใ—ใฆใ„ใ‚‹ใ‚‚ใฎใงใ™**ใ€‚ +- `swagger_css_url`: Swagger UI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”จใฎ HTML ใŒๅ–ๅพ—ใ™ใ‚‹ **CSS** ใƒ•ใ‚กใ‚คใƒซใฎ URLใ€‚**ใ“ใ‚Œใฏใ‚ใชใŸใฎใ‚ขใƒ—ใƒช่‡ช่บซใŒใ„ใพ้…ไฟกใ—ใฆใ„ใ‚‹ใ‚‚ใฎใงใ™**ใ€‚ + +ReDoc ใซใคใ„ใฆใ‚‚ๅŒๆง˜ใงใ™... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`swagger_ui_redirect` ็”จใฎ *path operation* ใฏใ€OAuth2 ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใฎ่ฃœๅŠฉใงใ™ใ€‚ + +API ใ‚’ OAuth2 ใƒ—ใƒญใƒใ‚คใƒ€ใจ็ตฑๅˆใ™ใ‚‹ใจใ€่ช่จผใ‚’ๅฎŸ่กŒใ—ใฆๅ–ๅพ—ใ—ใŸใ‚ฏใƒฌใƒ‡ใƒณใ‚ทใƒฃใƒซใ‚’ๆŒใฃใŸ็Šถๆ…‹ใง API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซๆˆปใ‚Œใพใ™ใ€‚ใใ—ใฆๅฎŸ้š›ใฎ OAuth2 ่ช่จผใ‚’็”จใ„ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆไธŠใ‹ใ‚‰ API ใจๅฏพ่ฉฑใงใใพใ™ใ€‚ + +Swagger UI ใŒใ“ใฎๅ‡ฆ็†ใ‚’่ฃๅดใง่กŒใ„ใพใ™ใŒใ€ใใฎใŸใ‚ใซใ“ใฎใ€Œredirectใ€ใฎ่ฃœๅŠฉใŒๅฟ…่ฆใงใ™ใ€‚ + +/// + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซใ‚’ใƒ†ใ‚นใƒˆใ™ใ‚‹ใŸใ‚ใฎ *path operation* ใ‚’ไฝœๆˆ { #create-a-path-operation-to-test-static-files } + +ใ™ในใฆใŒๅ‹•ไฝœใ™ใ‚‹ใ‹ใ‚’ใƒ†ใ‚นใƒˆใงใใ‚‹ใ‚ˆใ†ใซใ€*path operation* ใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### ้™็š„ใƒ•ใ‚กใ‚คใƒซ UI ใฎใƒ†ใ‚นใƒˆ { #test-static-files-ui } + +ใ“ใ‚Œใงใ€WiFi ใ‚’ๅˆ‡ๆ–ญใ—ใฆ http://127.0.0.1:8000/docs ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใ€ใƒšใƒผใ‚ธใ‚’ๅ†่ชญใฟ่พผใฟใงใใ‚‹ใฏใšใงใ™ใ€‚ + +ใ‚คใƒณใ‚ฟใƒผใƒใƒƒใƒˆใซๆŽฅ็ถšใ—ใฆใ„ใชใใฆใ‚‚ใ€API ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่กจ็คบใ—ใ€API ใจๅฏพ่ฉฑใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/how-to/custom-request-and-route.md b/docs/ja/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..ae64f31097 --- /dev/null +++ b/docs/ja/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ใ‚ซใ‚นใ‚ฟใƒ  Request ใจ APIRoute ใ‚ฏใƒฉใ‚น { #custom-request-and-apiroute-class } + +ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€`Request` ใ‚„ `APIRoute` ใ‚ฏใƒฉใ‚นใงไฝฟใ‚ใ‚Œใ‚‹ใƒญใ‚ธใƒƒใ‚ฏใ‚’ไธŠๆ›ธใใ—ใŸใ„ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ + +็‰นใซใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใงใฎใƒญใ‚ธใƒƒใ‚ฏใฎไปฃๆ›ฟใจใ—ใฆๆœ‰ๅŠนใชๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใŸใจใˆใฐใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๅ‡ฆ็†ใ•ใ‚Œใ‚‹ๅ‰ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‚’่ชญใฟๅ–ใฃใŸใ‚Šๆ“ไฝœใ—ใŸใ‚Šใ—ใŸใ„ๅ ดๅˆใงใ™ใ€‚ + +/// danger | ่ญฆๅ‘Š + +ใ“ใ‚Œใฏใ€ŒไธŠ็ดšใ€ๆฉŸ่ƒฝใงใ™ใ€‚ + +FastAPI ใ‚’ๅง‹ใ‚ใŸใฐใ‹ใ‚Šใฎๅ ดๅˆใฏใ€ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใฏ่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ใ‚ˆใ„ใงใ—ใ‚‡ใ†ใ€‚ + +/// + +## ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น { #use-cases } + +ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใฎไพ‹: + +* JSON ใงใฏใชใ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‚’ JSON ใซๅค‰ๆ›ใ™ใ‚‹๏ผˆไพ‹: `msgpack`๏ผ‰ใ€‚ +* gzip ๅœง็ธฎใ•ใ‚ŒใŸใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎ่งฃๅ‡ใ€‚ +* ใ™ในใฆใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎ่‡ชๅ‹•ใƒญใ‚ฎใƒณใ‚ฐใ€‚ + +## ใ‚ซใ‚นใ‚ฟใƒ ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใฎๅ‡ฆ็† { #handling-custom-request-body-encodings } + +gzip ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’่งฃๅ‡ใ™ใ‚‹ใŸใ‚ใซใ€ใ‚ซใ‚นใ‚ฟใƒ ใฎ `Request` ใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝฟใ†ๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +ใใ—ใฆใ€ใใฎใ‚ซใ‚นใ‚ฟใƒ ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚ฏใƒฉใ‚นใ‚’ไฝฟใ†ใŸใ‚ใฎ `APIRoute` ใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’็”จๆ„ใ—ใพใ™ใ€‚ + +### ใ‚ซใ‚นใ‚ฟใƒ  `GzipRequest` ใ‚ฏใƒฉใ‚นใฎไฝœๆˆ { #create-a-custom-gziprequest-class } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚Œใฏไป•็ต„ใฟใ‚’็คบใ™ใŸใ‚ใฎใ‚ตใƒณใƒ—ใƒซใงใ™ใ€‚Gzip ๅฏพๅฟœใŒๅฟ…่ฆใชๅ ดๅˆใฏใ€็”จๆ„ใ•ใ‚Œใฆใ„ใ‚‹ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +/// + +ใพใšใ€`GzipRequest` ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใฏ้ฉๅˆ‡ใชใƒ˜ใƒƒใƒ€ใƒผใŒใ‚ใ‚‹ๅ ดๅˆใซๆœฌไฝ“ใ‚’่งฃๅ‡ใ™ใ‚‹ใ‚ˆใ†ใ€`Request.body()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไธŠๆ›ธใใ—ใพใ™ใ€‚ + +ใƒ˜ใƒƒใƒ€ใƒผใซ `gzip` ใŒใชใ‘ใ‚Œใฐใ€่งฃๅ‡ใฏ่ฉฆใฟใพใ›ใ‚“ใ€‚ + +ใ“ใฎๆ–นๆณ•ใซใ‚ˆใ‚Šใ€ๅŒใ˜ใƒซใƒผใƒˆใ‚ฏใƒฉใ‚นใง gzip ๅœง็ธฎๆธˆใฟ๏ผๆœชๅœง็ธฎใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎไธกๆ–นใ‚’ๆ‰ฑใˆใพใ™ใ€‚ + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ใ‚ซใ‚นใ‚ฟใƒ  `GzipRoute` ใ‚ฏใƒฉใ‚นใฎไฝœๆˆ { #create-a-custom-gziproute-class } + +ๆฌกใซใ€`GzipRequest` ใ‚’ๅˆฉ็”จใ™ใ‚‹ `fastapi.routing.APIRoute` ใฎใ‚ซใ‚นใ‚ฟใƒ ใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใ“ใ“ใงใฏ `APIRoute.get_route_handler()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไธŠๆ›ธใใ—ใพใ™ใ€‚ + +ใ“ใฎใƒกใ‚ฝใƒƒใƒ‰ใฏ้–ขๆ•ฐใ‚’่ฟ”ใ—ใพใ™ใ€‚ใใ—ใฆใใฎ้–ขๆ•ฐใŒใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใ“ใ“ใงใฏใ€ๅ…ƒใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ `GzipRequest` ใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซๅˆฉ็”จใ—ใพใ™ใ€‚ + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +`Request` ใซใฏ `request.scope` ๅฑžๆ€งใŒใ‚ใ‚Šใ€ใ“ใ‚Œใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใซ้–ขใ™ใ‚‹ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅซใ‚€ Python ใฎ `dict` ใงใ™ใ€‚ + +`Request` ใซใฏ `request.receive` ใ‚‚ใ‚ใ‚Šใ€ใ“ใ‚Œใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๆœฌไฝ“ใ‚’ใ€Œๅ—ไฟกใ€ใ™ใ‚‹ใŸใ‚ใฎ้–ขๆ•ฐใงใ™ใ€‚ + +`scope` ใฎ `dict` ใจ `receive` ้–ขๆ•ฐใฏใ„ใšใ‚Œใ‚‚ ASGI ไป•ๆง˜ใฎไธ€้ƒจใงใ™ใ€‚ + +ใใ—ใฆใ“ใฎ 2 ใค๏ผˆ`scope` ใจ `receive`๏ผ‰ใŒใ€ๆ–ฐใ—ใ„ `Request` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชใ‚‚ใฎใงใ™ใ€‚ + +`Request` ใซใคใ„ใฆ่ฉณใ—ใใฏใ€Starlette ใฎ Requests ใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +`GzipRequest.get_route_handler` ใŒ่ฟ”ใ™้–ขๆ•ฐใŒ็•ฐใชใ‚‹ใฎใฏใ€`Request` ใ‚’ `GzipRequest` ใซๅค‰ๆ›ใ™ใ‚‹็‚นใ ใ‘ใงใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€`GzipRequest` ใฏๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‡ใƒผใ‚ฟใ‚’่งฃๅ‡ใ—ใฆใ‹ใ‚‰ *path operations* ใซๆธกใ—ใพใ™ใ€‚ + +ใใ‚Œไปฅ้™ใฎๅ‡ฆ็†ใƒญใ‚ธใƒƒใ‚ฏใฏใ™ในใฆๅŒใ˜ใงใ™ใ€‚ + +ใŸใ ใ—ใ€`GzipRequest.body` ใ‚’ๅค‰ๆ›ดใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ๅฟ…่ฆใซๅฟœใ˜ใฆ **FastAPI** ใซใ‚ˆใฃใฆ่ชญใฟ่พผใพใ‚Œใ‚‹้š›ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใŒ่‡ชๅ‹•็š„ใซ่งฃๅ‡ใ•ใ‚Œใพใ™ใ€‚ + +## ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉใงใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใธใฎใ‚ขใ‚ฏใ‚ปใ‚น { #accessing-the-request-body-in-an-exception-handler } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๅŒใ˜ๅ•้กŒใ‚’่งฃๆฑบใ™ใ‚‹ใซใฏใ€`RequestValidationError` ็”จใฎใ‚ซใ‚นใ‚ฟใƒ ใƒใƒณใƒ‰ใƒฉใง `body` ใ‚’ไฝฟใ†ๆ–นใŒใšใฃใจ็ฐกๅ˜ใงใ—ใ‚‡ใ†๏ผˆ[ใ‚จใƒฉใƒผๅ‡ฆ็†](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}๏ผ‰ใ€‚ + +ใŸใ ใ—ใ€ใ“ใฎไพ‹ใ‚‚ๆœ‰ๅŠนใงใ€ๅ†…้ƒจใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใจใฉใฎใ‚ˆใ†ใซใ‚„ใ‚Šๅ–ใ‚Šใ™ใ‚‹ใ‹ใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚ + +/// + +ๅŒใ˜ใ‚ขใƒ—ใƒญใƒผใƒใ‚’ไฝฟใฃใฆใ€ไพ‹ๅค–ใƒใƒณใƒ‰ใƒฉๅ†…ใงใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใ‚„ใ‚‹ใ“ใจใฏใ€`try`/`except` ใƒ–ใƒญใƒƒใ‚ฏใฎไธญใงใƒชใ‚ฏใ‚จใ‚นใƒˆใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใ ใ‘ใงใ™๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +ไพ‹ๅค–ใŒ็™บ็”Ÿใ—ใฆใ‚‚ใ€`Request` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฏใ‚นใ‚ณใƒผใƒ—ๅ†…ใซๆฎ‹ใ‚‹ใŸใ‚ใ€ใ‚จใƒฉใƒผๅ‡ฆ็†ๆ™‚ใซใƒชใ‚ฏใ‚จใ‚นใƒˆใƒœใƒ‡ใ‚ฃใ‚’่ชญใฟๅ–ใ‚Šใ€ๆดป็”จใงใใพใ™๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## ใƒซใƒผใ‚ฟใƒผใงใฎใ‚ซใ‚นใ‚ฟใƒ  `APIRoute` ใ‚ฏใƒฉใ‚น { #custom-apiroute-class-in-a-router } + +`APIRouter` ใฎ `route_class` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +ใ“ใฎไพ‹ใงใฏใ€`router` ้…ไธ‹ใฎ *path operations* ใฏใ‚ซใ‚นใ‚ฟใƒ ใฎ `TimedRoute` ใ‚ฏใƒฉใ‚นใ‚’ไฝฟ็”จใ—ใ€ใƒฌใ‚นใƒใƒณใ‚นใฎ็”Ÿๆˆใซใ‹ใ‹ใฃใŸๆ™‚้–“ใ‚’็คบใ™่ฟฝๅŠ ใฎ `X-Response-Time` ใƒ˜ใƒƒใƒ€ใƒผใŒใƒฌใ‚นใƒใƒณใ‚นใซๅซใพใ‚Œใพใ™๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/ja/docs/how-to/extending-openapi.md b/docs/ja/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..df5b3cd35a --- /dev/null +++ b/docs/ja/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# OpenAPI ใฎๆ‹กๅผต { #extending-openapi } + +็”Ÿๆˆใ•ใ‚ŒใŸ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’ๅค‰ๆ›ดใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใใฎๆ–นๆณ•ใ‚’่ชฌๆ˜Žใ—ใพใ™ใ€‚ + +## ้€šๅธธใฎใƒ—ใƒญใ‚ปใ‚น { #the-normal-process } + +้€šๅธธ๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ๏ผ‰ใฎใƒ—ใƒญใ‚ปใ‚นใฏๆฌกใฎใจใŠใ‚Šใงใ™ใ€‚ + +`FastAPI` ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ๏ผˆใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น๏ผ‰ใซใฏใ€OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’่ฟ”ใ™ใ“ใจใŒๆœŸๅพ…ใ•ใ‚Œใ‚‹ `.openapi()` ใƒกใ‚ฝใƒƒใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใฎไฝœๆˆๆ™‚ใซใ€`/openapi.json`๏ผˆใพใŸใฏ `openapi_url` ใซ่จญๅฎšใ—ใŸใƒ‘ใ‚น๏ผ‰ใธใฎ path operation ใŒ็™ป้Œฒใ•ใ‚Œใพใ™ใ€‚ + +ใ“ใ‚Œใฏๅ˜ใซใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ `.openapi()` ใƒกใ‚ฝใƒƒใƒ‰ใฎ็ตๆžœใ‚’ๅซใ‚€ JSON ใƒฌใ‚นใƒใƒณใ‚นใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใ€`.openapi()` ใƒกใ‚ฝใƒƒใƒ‰ใฏใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃ `.openapi_schema` ใซๅ†…ๅฎนใŒใ‚ใ‚‹ใ‹ใ‚’็ขบ่ชใ—ใ€ใ‚ใ‚Œใฐใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใชใ‘ใ‚Œใฐใ€`fastapi.openapi.utils.get_openapi` ใซใ‚ใ‚‹ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใ‚’ไฝฟใฃใฆ็”Ÿๆˆใ—ใพใ™ใ€‚ + +ใ“ใฎ้–ขๆ•ฐ `get_openapi()` ใฏๆฌกใฎๅผ•ๆ•ฐใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™: + +- `title`: ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใ‚‹ OpenAPI ใฎใ‚ฟใ‚คใƒˆใƒซใ€‚ +- `version`: API ใฎใƒใƒผใ‚ธใƒงใƒณใ€‚ไพ‹: `2.5.0`ใ€‚ +- `openapi_version`: ไฝฟ็”จใ™ใ‚‹ OpenAPI ไป•ๆง˜ใฎใƒใƒผใ‚ธใƒงใƒณใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฏๆœ€ๆ–ฐใฎ `3.1.0`ใ€‚ +- `summary`: API ใฎ็Ÿญใ„ๆฆ‚่ฆใ€‚ +- `description`: API ใฎ่ชฌๆ˜Žใ€‚Markdown ใ‚’ๅซใ‚ใ‚‹ใ“ใจใŒใงใใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ +- `routes`: ใƒซใƒผใƒˆใฎใƒชใ‚นใƒˆใ€‚็™ป้Œฒๆธˆใฟใฎๅ„ path operation ใงใ™ใ€‚`app.routes` ใ‹ใ‚‰ๅ–ๅพ—ใ•ใ‚Œใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `summary` ใฏ OpenAPI 3.1.0 ไปฅ้™ใงๅˆฉ็”จๅฏ่ƒฝใงใ€FastAPI 0.99.0 ไปฅ้™ใŒๅฏพๅฟœใ—ใฆใ„ใพใ™ใ€‚ + +/// + +## ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎไธŠๆ›ธใ { #overriding-the-defaults } + +ไธŠ่จ˜ใฎๆƒ…ๅ ฑใ‚’ไฝฟใฃใฆใ€ๅŒใ˜ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใง OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’็”Ÿๆˆใ—ใ€ๅฟ…่ฆใช้ƒจๅˆ†ใ‚’ไธŠๆ›ธใใงใใพใ™ใ€‚ + +ใŸใจใˆใฐใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒญใ‚ดใ‚’ๅซใ‚ใ‚‹ใŸใ‚ใฎ ReDoc ใฎ OpenAPI ๆ‹กๅผตใ‚’่ฟฝๅŠ ใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ + +### ้€šๅธธใฎ **FastAPI** { #normal-fastapi } + +ใพใšใ€้€šๅธธใฉใŠใ‚Šใซ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่ฃ…ใ—ใพใ™: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### OpenAPI ใ‚นใ‚ญใƒผใƒžใฎ็”Ÿๆˆ { #generate-the-openapi-schema } + +ๆฌกใซใ€`custom_openapi()` ้–ขๆ•ฐๅ†…ใงๅŒใ˜ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใ‚’ไฝฟใฃใฆ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚’็”Ÿๆˆใ—ใพใ™: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### OpenAPI ใ‚นใ‚ญใƒผใƒžใฎๅค‰ๆ›ด { #modify-the-openapi-schema } + +OpenAPI ใ‚นใ‚ญใƒผใƒžใฎ `info`ใ€Œใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€ใซใ‚ซใ‚นใ‚ฟใƒ ใฎ `x-logo` ใ‚’่ฟฝๅŠ ใ—ใฆใ€ReDoc ๆ‹กๅผตใ‚’ๅŠ ใˆใพใ™: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### OpenAPI ใ‚นใ‚ญใƒผใƒžใฎใ‚ญใƒฃใƒƒใ‚ทใƒฅ { #cache-the-openapi-schema } + +็”Ÿๆˆใ—ใŸใ‚นใ‚ญใƒผใƒžใ‚’ไฟๆŒใ™ใ‚‹ใ€Œใ‚ญใƒฃใƒƒใ‚ทใƒฅใ€ใจใ—ใฆ `.openapi_schema` ใƒ—ใƒญใƒ‘ใƒ†ใ‚ฃใ‚’ๅˆฉ็”จใงใใพใ™ใ€‚ + +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€ใƒฆใƒผใ‚ถใƒผใŒ API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’้–‹ใใŸใณใซใ‚นใ‚ญใƒผใƒžใ‚’็”Ÿๆˆใ™ใ‚‹ๅฟ…่ฆใŒใชใใชใ‚Šใพใ™ใ€‚ + +ๆœ€ๅˆใฎ1ๅ›žใ ใ‘็”Ÿๆˆใ•ใ‚Œใ€ใใฎๅพŒใฏๅŒใ˜ใ‚ญใƒฃใƒƒใ‚ทใƒฅๆธˆใฟใ‚นใ‚ญใƒผใƒžใŒไปฅ้™ใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### ใƒกใ‚ฝใƒƒใƒ‰ใฎไธŠๆ›ธใ { #override-the-method } + +ใ“ใ‚Œใงใ€`.openapi()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ๆ–ฐใ—ใ„้–ขๆ•ฐใซ็ฝฎใๆ›ใˆใ‚‰ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### ็ขบ่ช { #check-it } + +http://127.0.0.1:8000/redoc ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€ใ‚ซใ‚นใ‚ฟใƒ ใƒญใ‚ด๏ผˆใ“ใฎไพ‹ใงใฏ **FastAPI** ใฎใƒญใ‚ด๏ผ‰ใŒไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ใ“ใจใŒ็ขบ่ชใงใใพใ™: + + diff --git a/docs/ja/docs/how-to/general.md b/docs/ja/docs/how-to/general.md new file mode 100644 index 0000000000..8879c68eb9 --- /dev/null +++ b/docs/ja/docs/how-to/general.md @@ -0,0 +1,39 @@ +# ไธ€่ˆฌ - ใƒใ‚ฆใƒ„ใƒผ - ใƒฌใ‚ทใƒ” { #general-how-to-recipes } + +ใ“ใ“ใงใฏใ€ไธ€่ˆฌ็š„ใพใŸใฏใ‚ˆใใ‚ใ‚‹่ณชๅ•ใซๅฏพใ—ใฆใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅ†…ใฎไป–ใฎ็ฎ‡ๆ‰€ใธใฎๅ‚็…งใ‚’ใ„ใใคใ‹็คบใ—ใพใ™ใ€‚ + +## ใƒ‡ใƒผใ‚ฟใฎใƒ•ใ‚ฃใƒซใ‚ฟใƒชใƒณใ‚ฐ - ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃ { #filter-data-security } + +่ฟ”ใ™ในใไปฅไธŠใฎใƒ‡ใƒผใ‚ฟใ‚’่ฟ”ใ•ใชใ„ใ‚ˆใ†ใซใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซ - ๆˆปใ‚Šๅ€คใฎๅž‹](../tutorial/response-model.md){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใ‚ฟใ‚ฐ - OpenAPI { #documentation-tags-openapi } + +*path operations* ใซใ‚ฟใ‚ฐใ‚’่ฟฝๅŠ ใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใงใ‚ฐใƒซใƒผใƒ—ๅŒ–ใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - path operation ใฎ่จญๅฎš - ใ‚ฟใ‚ฐ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎๆฆ‚่ฆใจ่ชฌๆ˜Ž - OpenAPI { #documentation-summary-and-description-openapi } + +*path operations* ใซๆฆ‚่ฆใจ่ชฌๆ˜Žใ‚’่ฟฝๅŠ ใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใซ่กจ็คบใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - path operation ใฎ่จญๅฎš - ๆฆ‚่ฆใจ่ชฌๆ˜Ž](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒฌใ‚นใƒใƒณใ‚น่ชฌๆ˜Ž - OpenAPI { #documentation-response-description-openapi } + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใซ่กจ็คบใ•ใ‚Œใ‚‹ใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Žใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - path operation ใฎ่จญๅฎš - ใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Ž](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## *Path Operation* ใฎ้žๆŽจๅฅจๅŒ– - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +*path operation* ใ‚’้žๆŽจๅฅจใซใ—ใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใซ่กจ็คบใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - path operation ใฎ่จญๅฎš - ้žๆŽจๅฅจ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใ‚’ JSON ไบ’ๆ›ใซๅค‰ๆ› { #convert-any-data-to-json-compatible } + +ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใ‚’ JSON ไบ’ๆ›ใซๅค‰ๆ›ใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - JSON ไบ’ๆ›ใ‚จใƒณใ‚ณใƒผใƒ€](../tutorial/encoder.md){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## OpenAPI ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ - ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #openapi-metadata-docs } + +ใƒฉใ‚คใ‚ปใƒณใ‚นใ€ใƒใƒผใ‚ธใƒงใƒณใ€้€ฃ็ตกๅ…ˆใชใฉใ‚’ๅซใ‚€ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ OpenAPI ใ‚นใ‚ญใƒผใƒžใซ่ฟฝๅŠ ใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ URL](../tutorial/metadata.md){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## OpenAPI ใฎใ‚ซใ‚นใ‚ฟใƒ  URL { #openapi-custom-url } + +OpenAPI ใฎ URL ใ‚’ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บ๏ผˆใพใŸใฏๅ‰Š้™ค๏ผ‰ใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## OpenAPI ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ URL { #openapi-docs-urls } + +่‡ชๅ‹•็”Ÿๆˆใ•ใ‚Œใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใŒไฝฟ็”จใ™ใ‚‹ URL ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใซใฏใ€[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใจใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/how-to/graphql.md b/docs/ja/docs/how-to/graphql.md new file mode 100644 index 0000000000..bd0d223498 --- /dev/null +++ b/docs/ja/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +**FastAPI** ใฏ **ASGI** ๆจ™ๆบ–ใซๅŸบใฅใ„ใฆใ„ใ‚‹ใŸใ‚ใ€ASGI ใซๅฏพๅฟœใ—ใŸไปปๆ„ใฎ **GraphQL** ใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’็ฐกๅ˜ใซ็ตฑๅˆใงใใพใ™ใ€‚ + +ๅŒใ˜ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณๅ†…ใง้€šๅธธใฎ FastAPI ใฎ *path operation* ใจ GraphQL ใ‚’็ต„ใฟๅˆใ‚ใ›ใฆไฝฟใˆใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +**GraphQL** ใฏ้žๅธธใซ็‰นๅฎšใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’่งฃๆฑบใ—ใพใ™ใ€‚ + +ไธ€่ˆฌ็š„ใช **Web API** ใจๆฏ”ในใ‚‹ใจใ€**้•ทๆ‰€** ใจ **็Ÿญๆ‰€** ใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ”่‡ช่บซใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงๅพ—ใ‚‰ใ‚Œใ‚‹ **ๅˆฉ็‚น** ใŒ **ๆฌ ็‚น** ใ‚’่ฃœใ†ใ‹ใฉใ†ใ‹ใ‚’่ฉ•ไพกใ—ใฆใใ ใ•ใ„ใ€‚ ๐Ÿค“ + +/// + +## GraphQL ใƒฉใ‚คใƒ–ใƒฉใƒช { #graphql-libraries } + +**ASGI** ใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ **GraphQL** ใƒฉใ‚คใƒ–ใƒฉใƒชใฎไธ€้ƒจใ‚’ไปฅไธ‹ใซ็คบใ—ใพใ™ใ€‚**FastAPI** ใจ็ต„ใฟๅˆใ‚ใ›ใฆไฝฟ็”จใงใใพใ™: + +* Strawberry ๐Ÿ“ + * FastAPI ๅ‘ใ‘ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ใ‚Š +* Ariadne + * FastAPI ๅ‘ใ‘ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ใ‚Š +* Tartiflette + * ASGI ้€ฃๆบ็”จใฎ Tartiflette ASGI ใ‚ใ‚Š +* Graphene + * starlette-graphene3 ใ‚ใ‚Š + +## Strawberry ใง GraphQL { #graphql-with-strawberry } + +**GraphQL** ใŒๅฟ…่ฆใ€ใพใŸใฏๅˆฉ็”จใ—ใŸใ„ๅ ดๅˆใฏใ€**Strawberry** ใ‚’**ๆŽจๅฅจ**ใ—ใพใ™ใ€‚**FastAPI** ใฎ่จญ่จˆใซๆœ€ใ‚‚่ฟ‘ใใ€ใ™ในใฆใŒ**ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ**ใซๅŸบใฅใ„ใฆใ„ใพใ™ใ€‚ + +ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใซใ‚ˆใฃใฆใฏไป–ใฎใƒฉใ‚คใƒ–ใƒฉใƒชใ‚’้ธใถๆ–นใŒใ‚ˆใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใŒใ€็งใซๅฐ‹ใญใ‚‰ใ‚Œใ‚Œใฐใ€ใŠใใ‚‰ใ **Strawberry** ใ‚’่ฉฆใ™ใ“ใจใ‚’ๅ‹งใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ + +FastAPI ใจ Strawberry ใ‚’็ตฑๅˆใ™ใ‚‹ๆ–นๆณ•ใฎ็ฐกๅ˜ใชใƒ—ใƒฌใƒ“ใƒฅใƒผใงใ™: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +่ฉณ็ดฐใฏ Strawberry ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ + +ใพใŸใ€Strawberry ใจ FastAPI ใฎ้€ฃๆบใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +## Starlette ใฎๆ—ง `GraphQLApp` { #older-graphqlapp-from-starlette } + +ไปฅๅ‰ใฎ Starlette ใซใฏใ€Graphene ใจ็ตฑๅˆใ™ใ‚‹ใŸใ‚ใฎ `GraphQLApp` ใ‚ฏใƒฉใ‚นใŒๅซใพใ‚Œใฆใ„ใพใ—ใŸใ€‚ + +ใ“ใ‚Œใฏ Starlette ใ‹ใ‚‰ใฏ้žๆŽจๅฅจใซใชใ‚Šใพใ—ใŸใŒใ€ใ‚‚ใ—ใใ‚Œใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ‚ณใƒผใƒ‰ใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๅŒใ˜ใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใ‚’ใ‚ซใƒใƒผใ—ใ€**ใปใผๅŒไธ€ใฎใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚น**ใ‚’ๆŒใค starlette-graphene3 ใธๅฎนๆ˜“ใซ**็งป่กŒ**ใงใใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +GraphQL ใŒๅฟ…่ฆใงใ‚ใ‚Œใฐใ€ไพ็„ถใจใ—ใฆ Strawberry ใฎๅˆฉ็”จใ‚’ๆŽจๅฅจใ—ใพใ™ใ€‚็‹ฌ่‡ชใฎใ‚ฏใƒฉใ‚นใ‚„ๅž‹ใงใฏใชใใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใซๅŸบใฅใ„ใฆใ„ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +/// + +## ใ•ใ‚‰ใซๅญฆใถ { #learn-more } + +**GraphQL** ใซใคใ„ใฆใฏใ€ๅ…ฌๅผ GraphQL ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ•ใ‚‰ใซๅญฆในใพใ™ใ€‚ + +ไธŠ่จ˜ใฎๅ„ใƒฉใ‚คใƒ–ใƒฉใƒชใซใคใ„ใฆใฏใ€ใƒชใƒณใ‚ฏๅ…ˆใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”ๅ‚็…งใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/how-to/index.md b/docs/ja/docs/how-to/index.md new file mode 100644 index 0000000000..b1cd177852 --- /dev/null +++ b/docs/ja/docs/how-to/index.md @@ -0,0 +1,13 @@ +# ใƒใ‚ฆใƒ„ใƒผ - ใƒฌใ‚ทใƒ” { #how-to-recipes } + +ใ“ใ“ใงใฏใ€**่ค‡ๆ•ฐใฎใƒˆใƒ”ใƒƒใ‚ฏ**ใซ้–ขใ™ใ‚‹ใ•ใพใ–ใพใชใƒฌใ‚ทใƒ”ใ‚„ใ€Œใƒใ‚ฆใƒ„ใƒผใ€ใ‚ฌใ‚คใƒ‰ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใ‚ขใ‚คใƒ‡ใ‚ขใฎๅคšใใฏใŠใŠใ‚€ใญ**็‹ฌ็ซ‹**ใ—ใฆใŠใ‚Šใ€ใปใจใ‚“ใฉใฎๅ ดๅˆใ€**ใ‚ใชใŸใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ**ใซ็›ดๆŽฅๅฝ“ใฆใฏใพใ‚‹ใ‚‚ใฎใ ใ‘ใ‚’่ชญใ‚ใฐๅๅˆ†ใงใ™ใ€‚ + +ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซใจใฃใฆ่ˆˆๅ‘ณๆทฑใๆœ‰็”จใ ใจๆ€ใ†ใ‚‚ใฎใŒใ‚ใ‚Œใฐใ€ใœใฒ็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ใใ†ใงใชใ‘ใ‚Œใฐใ€่ชญใฟ้ฃ›ใฐใ—ใฆใ‚‚ๅ•้กŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +**FastAPI ใ‚’ๅญฆใถ**ใ“ใจใ‚’ไฝ“็ณป็š„ใซ้€ฒใ‚ใŸใ„ๅ ดๅˆ๏ผˆๆŽจๅฅจ๏ผ‰ใ€ไปฃใ‚ใ‚Šใซ [ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](../tutorial/index.md){.internal-link target=_blank} ใ‚’็ซ ใ”ใจใซ่ชญใ‚“ใงใใ ใ•ใ„ใ€‚ + +/// diff --git a/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..f1414ac281 --- /dev/null +++ b/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# Pydantic v1 ใ‹ใ‚‰ Pydantic v2 ใธใฎ็งป่กŒ { #migrate-from-pydantic-v1-to-pydantic-v2 } + +ๅคใ„ FastAPI ใ‚ขใƒ—ใƒชใŒใ‚ใ‚‹ๅ ดๅˆใ€Pydantic v1 ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +FastAPI 0.100.0 ใฏ Pydantic v1 / v2 ใฎใฉใกใ‚‰ใซใ‚‚ๅฏพๅฟœใ—ใฆใŠใ‚Šใ€ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ๆ–นใ‚’ไฝฟ็”จใ—ใพใ—ใŸใ€‚ + +FastAPI 0.119.0 ใงใฏใ€Pydantic v2 ๅ†…ใ‹ใ‚‰ใฎ Pydantic v1 ใฎ้ƒจๅˆ†็š„ใ‚ตใƒใƒผใƒˆ๏ผˆ`pydantic.v1`๏ผ‰ใŒๅฐŽๅ…ฅใ•ใ‚Œใ€v2 ใธใฎ็งป่กŒใŒๅฎนๆ˜“ใซใชใ‚Šใพใ—ใŸใ€‚ + +FastAPI 0.126.0 ใง Pydantic v1 ใฎใ‚ตใƒใƒผใƒˆใฏ็ต‚ไบ†ใ—ใพใ—ใŸใŒใ€ใ—ใฐใ‚‰ใใฎ้–“ใฏ `pydantic.v1` ใฏๅˆฉ็”จๅฏ่ƒฝใงใ—ใŸใ€‚ + +/// warning | ๆณจๆ„ + +Pydantic ใƒใƒผใƒ ใฏ Python ใฎๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใ€ใคใพใ‚Š **Python 3.14** ใ‹ใ‚‰ใ€Pydantic v1 ใฎใ‚ตใƒใƒผใƒˆใ‚’็ต‚ไบ†ใ—ใพใ—ใŸใ€‚ + +ใ“ใ‚Œใซใฏ `pydantic.v1` ใ‚‚ๅซใพใ‚Œใ€Python 3.14 ไปฅไธŠใงใฏใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ›ใ‚“ใ€‚ + +Python ใฎๆœ€ๆ–ฐๆฉŸ่ƒฝใ‚’ไฝฟใ„ใŸใ„ๅ ดๅˆใฏใ€Pydantic v2 ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// + +ๅคใ„ FastAPI ใ‚ขใƒ—ใƒชใง Pydantic v1 ใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใ€ใ“ใ“ใงใฏ Pydantic v2 ใธใฎ็งป่กŒๆ–นๆณ•ใจใ€ๆฎต้šŽ็š„็งป่กŒใ‚’ๅŠฉใ‘ใ‚‹ **FastAPI 0.119.0 ใฎๆฉŸ่ƒฝ** ใ‚’็ดนไป‹ใ—ใพใ™ใ€‚ + +## ๅ…ฌๅผใ‚ฌใ‚คใƒ‰ { #official-guide } + +Pydantic ใซใฏ v1 ใ‹ใ‚‰ v2 ใธใฎๅ…ฌๅผใฎ ็งป่กŒใ‚ฌใ‚คใƒ‰ ใŒใ‚ใ‚Šใพใ™ใ€‚ + +ๅค‰ๆ›ด็‚นใ€ๆคœ่จผใŒใ‚ˆใ‚Šๆญฃ็ขบใงๅŽณๅฏ†ใซใชใฃใŸ็‚นใ€ๆณจๆ„ไบ‹้ …ใชใฉใŒๅซใพใ‚Œใพใ™ใ€‚ + +ไฝ•ใŒๅค‰ใ‚ใฃใŸใ‹ใ‚’ใ‚ˆใ‚Šใ‚ˆใ็†่งฃใ™ใ‚‹ใŸใ‚ใซๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +## ใƒ†ใ‚นใƒˆ { #tests } + +ใ‚ขใƒ—ใƒชใซๅฏพใ™ใ‚‹[ใƒ†ใ‚นใƒˆ](../tutorial/testing.md){.internal-link target=_blank}ใ‚’็”จๆ„ใ—ใ€็ถ™็ถš็š„ใ‚คใƒณใƒ†ใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณ๏ผˆCI๏ผ‰ใงๅฎŸ่กŒใ™ใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ๅพŒใ‚‚ๆœŸๅพ…ใฉใŠใ‚Šๅ‹•ไฝœใ—ใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใงใใพใ™ใ€‚ + +## `bump-pydantic` { #bump-pydantic } + +ๅคšใใฎๅ ดๅˆใ€ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บใฎใชใ„้€šๅธธใฎ Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใฆใ„ใ‚Œใฐใ€v1 ใ‹ใ‚‰ v2 ใธใฎ็งป่กŒไฝœๆฅญใฎๅคงๅŠใ‚’่‡ชๅ‹•ๅŒ–ใงใใพใ™ใ€‚ + +ๅŒใ˜ Pydantic ใƒใƒผใƒ ใŒๆไพ›ใ™ใ‚‹ `bump-pydantic` ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +ใ“ใฎใƒ„ใƒผใƒซใฏๅฟ…่ฆใชใ‚ณใƒผใƒ‰ๅค‰ๆ›ดใฎใปใจใ‚“ใฉใ‚’่‡ชๅ‹•ใง่กŒใ„ใพใ™ใ€‚ + +ใใฎๅพŒใƒ†ใ‚นใƒˆใ‚’ๅฎŸ่กŒใ—ใ€ๅ•้กŒใชใ‘ใ‚ŒใฐๅฎŒไบ†ใงใ™ใ€‚๐Ÿ˜Ž + +## v2 ใซใŠใ‘ใ‚‹ Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2 ใซใฏใ€Pydantic v1 ใŒใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ `pydantic.v1` ใจใ—ใฆๅŒๆขฑใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใŸใ ใ—ใ€ใ“ใ‚Œใฏ Python 3.13 ใ‚’่ถ…ใˆใ‚‹ใƒใƒผใ‚ธใƒงใƒณใงใฏใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ›ใ‚“ใ€‚ + +ใคใพใ‚Šใ€Pydantic v2 ใฎๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใ€ใ“ใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰ๆ—ง Pydantic v1 ใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆใ€ใ‚ใŸใ‹ใ‚‚ v1 ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใ„ใ‚‹ใ‹ใฎใ‚ˆใ†ใซไฝฟ็”จใงใใพใ™ใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### v2 ๅ†…ใฎ Pydantic v1 ใซๅฏพใ™ใ‚‹ FastAPI ใฎใ‚ตใƒใƒผใƒˆ { #fastapi-support-for-pydantic-v1-in-v2 } + +FastAPI 0.119.0 ไปฅ้™ใงใฏใ€็งป่กŒใ‚’ๅฎนๆ˜“ใซใ™ใ‚‹ใŸใ‚ใ€Pydantic v2 ๅ†…ใฎ Pydantic v1 ใซๅฏพใ™ใ‚‹้ƒจๅˆ†็š„ใ‚ตใƒใƒผใƒˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€Pydantic ใ‚’ v2 ใฎๆœ€ๆ–ฐใซไธŠใ’ใ€ใ‚คใƒณใƒใƒผใƒˆใ‚’ `pydantic.v1` ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใซๅˆ‡ใ‚Šๆ›ฟใˆใ‚‹ใ ใ‘ใงใ€ๅคšใใฎๅ ดๅˆใใฎใพใพๅ‹•ไฝœใ—ใพใ™ใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | ๆณจๆ„ + +ๅ‰่ฟฐใฎใจใŠใ‚Šใ€Python ใฎๆœ€่ฟ‘ใฎใƒใƒผใ‚ธใƒงใƒณ๏ผˆPython 3.14 ไปฅ้™๏ผ‰ใงใฏ Pydantic v1 ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใชใ„ใŸใ‚ใ€`pydantic.v1` ใฎไฝฟ็”จใ‚‚ Python 3.14 ไปฅไธŠใงใฏใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ›ใ‚“ใ€‚ + +/// + +### ๅŒไธ€ใ‚ขใƒ—ใƒชใงใฎ Pydantic v1 ใจ v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic v2 ใฎใƒขใƒ‡ใƒซใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซ Pydantic v1 ใฎใƒขใƒ‡ใƒซใ‚’๏ผˆใพใŸใฏใใฎ้€†ใ‚’๏ผ‰ๅŸ‹ใ‚่พผใ‚€ใ“ใจใฏใ€Pydantic ใงใฏใ€Œใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ›ใ‚“ใ€ใ€‚ + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...but, you can have separated models using Pydantic v1 and v2 in the same app. + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +ๅ ดๅˆใซใ‚ˆใฃใฆใฏใ€ๅŒใ˜ FastAPI ใฎ path operation ๅ†…ใงใ€Pydantic v1 ใจ v2 ใฎไธกๆ–นใฎใƒขใƒ‡ใƒซใ‚’ๆ‰ฑใ†ใ“ใจใ‚‚ๅฏ่ƒฝใงใ™: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ไธŠใฎไพ‹ใงใฏใ€ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใฏ Pydantic v1ใ€ๅ‡บๅŠ›ใƒขใƒ‡ใƒซ๏ผˆ`response_model=ItemV2` ใงๅฎš็พฉ๏ผ‰ใฏ Pydantic v2 ใงใ™ใ€‚ + +### Pydantic v1 ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #pydantic-v1-parameters } + +Pydantic v1 ใฎใƒขใƒ‡ใƒซใง `Body`ใ€`Query`ใ€`Form` ใชใฉใฎ FastAPI ๅ›บๆœ‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ€v2 ใธใฎ็งป่กŒใŒๅฎŒไบ†ใ™ใ‚‹ใพใงใฎ้–“ใฏ `fastapi.temp_pydantic_v1_params` ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### ๆฎต้šŽ็š„ใซ็งป่กŒ { #migrate-in-steps } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใพใšใฏ `bump-pydantic` ใ‚’่ฉฆใ—ใฆใใ ใ•ใ„ใ€‚ใƒ†ใ‚นใƒˆใŒ้€šใ‚Šใ€ๅ•้กŒใชใ‘ใ‚Œใฐใ‚ณใƒžใƒณใƒ‰ไธ€็™บใงๅฎŒไบ†ใงใ™ใ€‚โœจ + +/// + +`bump-pydantic` ใŒ้ฉ็”จใงใใชใ„ๅ ดๅˆใฏใ€ๅŒไธ€ใ‚ขใƒ—ใƒชใง v1 ใจ v2 ใฎใƒขใƒ‡ใƒซใ‚’ไฝต็”จใงใใ‚‹ใ‚ตใƒใƒผใƒˆใ‚’ๅˆฉ็”จใ—ใฆใ€ๅพใ€…ใซ v2 ใธ็งป่กŒใงใใพใ™ใ€‚ + +ใพใš Pydantic ใ‚’ v2 ใฎๆœ€ๆ–ฐใซใ‚ขใƒƒใƒ—ใ‚ฐใƒฌใƒผใƒ‰ใ—ใ€ใ™ในใฆใฎใƒขใƒ‡ใƒซใฎใ‚คใƒณใƒใƒผใƒˆใ‚’ `pydantic.v1` ใซๅˆ‡ใ‚Šๆ›ฟใˆใพใ™ใ€‚ + +ใใฎๅพŒใ€ใƒขใƒ‡ใƒซใ‚’ใ‚ฐใƒซใƒผใƒ—ใ”ใจใซๅฐ‘ใ—ใšใค Pydantic v1 ใ‹ใ‚‰ v2 ใธ็งป่กŒใ—ใฆใ„ใใพใ™ใ€‚๐Ÿšถ diff --git a/docs/ja/docs/how-to/separate-openapi-schemas.md b/docs/ja/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..46df2aafba --- /dev/null +++ b/docs/ja/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# ๅ…ฅๅŠ›ใจๅ‡บๅŠ›ใงOpenAPIใฎใ‚นใ‚ญใƒผใƒžใ‚’ๅˆ†ใ‘ใ‚‹ใ‹ใฉใ†ใ‹ { #separate-openapi-schemas-for-input-and-output-or-not } + +**Pydantic v2** ใฎใƒชใƒชใƒผใ‚นไปฅ้™ใ€็”Ÿๆˆใ•ใ‚Œใ‚‹ OpenAPI ใฏไปฅๅ‰ใ‚ˆใ‚Šๅฐ‘ใ—ๆญฃ็ขบใงใ€ใ‚ˆใ‚Šๆญฃใ—ใ„ใ‚‚ใฎใซใชใ‚Šใพใ—ใŸใ€‚๐Ÿ˜Ž + +ๅฎŸ้š›ใซใฏใ€ๅ ดๅˆใซใ‚ˆใฃใฆใฏๅŒใ˜ Pydantic ใƒขใƒ‡ใƒซใซๅฏพใ—ใฆใ€ๅ…ฅๅŠ›็”จใจๅ‡บๅŠ›็”จใง OpenAPI ใซ **2 ใคใฎ JSON Schema** ใŒๅซใพใ‚Œใ‚‹ใ“ใจใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏ **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค** ใฎๆœ‰็„กใซไพๅญ˜ใ—ใพใ™ใ€‚ + +ใใฎๅ‹•ไฝœใจใ€ๅฟ…่ฆใซๅฟœใ˜ใฆใฎๅค‰ๆ›ดๆ–นๆณ•ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +## ๅ…ฅๅ‡บๅŠ›ใฎPydanticใƒขใƒ‡ใƒซ { #pydantic-models-for-input-and-output } + +ๆฌกใฎใ‚ˆใ†ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใค Pydantic ใƒขใƒ‡ใƒซใŒใ‚ใ‚‹ใจใ—ใพใ™ใ€‚ + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### ๅ…ฅๅŠ›็”จใƒขใƒ‡ใƒซ { #model-for-input } + +ใ“ใฎใƒขใƒ‡ใƒซใ‚’ๆฌกใฎใ‚ˆใ†ใซๅ…ฅๅŠ›ใจใ—ใฆไฝฟใ†ใจ: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...`description` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏ **ๅฟ…้ ˆใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `None` ใ ใ‹ใ‚‰ใงใ™ใ€‚ + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฎๅ…ฅๅŠ›ใƒขใƒ‡ใƒซ { #input-model-in-docs } + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง็ขบ่ชใ™ใ‚‹ใจใ€`description` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซใฏ **่ตคใ„ใ‚ขใ‚นใ‚ฟใƒชใ‚นใ‚ฏ** ใŒไป˜ใ„ใฆใŠใ‚‰ใšใ€ๅฟ…้ ˆใจใ—ใฆใฏใƒžใƒผใ‚ฏใ•ใ‚Œใฆใ„ใพใ›ใ‚“: + +
+ +
+ +### ๅ‡บๅŠ›็”จใƒขใƒ‡ใƒซ { #model-for-output } + +ใ—ใ‹ใ—ๅŒใ˜ใƒขใƒ‡ใƒซใ‚’ๆฌกใฎใ‚ˆใ†ใซๅ‡บๅŠ›ใจใ—ใฆไฝฟใ†ๅ ดๅˆ: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...`description` ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใ‚ใ‚‹ใŸใ‚ใ€ใใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซไฝ•ใ‚‚่ฟ”ใ•ใชใใฆใ‚‚ใ€ใใฎ **ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค** ใŒๅ…ฅใ‚Šใพใ™ใ€‚ + +### ๅ‡บๅŠ›ใฎใƒฌใ‚นใƒใƒณใ‚นใƒ‡ใƒผใ‚ฟ { #model-for-output-response-data } + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰่ฉฆใ—ใฆใƒฌใ‚นใƒใƒณใ‚นใ‚’็ขบ่ชใ™ใ‚‹ใจใ€ใ‚ณใƒผใƒ‰ใงใฏไธ€ๆ–นใฎ `description` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซไฝ•ใ‚‚่ฟฝๅŠ ใ—ใฆใ„ใชใ„ใซใ‚‚ใ‹ใ‹ใ‚ใ‚‰ใšใ€JSON ใƒฌใ‚นใƒใƒณใ‚นใซใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค๏ผˆ`null`๏ผ‰ใŒๅซใพใ‚Œใฆใ„ใพใ™: + +
+ +
+ +ใคใพใ‚Šใใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซใฏ **ๅธธใซๅ€คใŒใ‚ใ‚Šใพใ™**ใ€‚ๅ€คใŒ `None`๏ผˆJSON ใงใฏ `null`๏ผ‰ใซใชใ‚‹ใ“ใจใŒใ‚ใ‚‹ใ ใ‘ใงใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใ€ใ“ใฎ API ใ‚’ไฝฟใ†ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏๅ€คใฎๆœ‰็„กใ‚’็ขบ่ชใ™ใ‚‹ๅฟ…่ฆใŒใชใใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒ **ๅธธใซๅญ˜ๅœจใ™ใ‚‹** ใจไปฎๅฎšใงใใพใ™ใ€‚ๅ ดๅˆใซใ‚ˆใฃใฆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใฎ `None` ใซใชใ‚‹ใ ใ‘ใงใ™ใ€‚ + +ใ“ใ‚Œใ‚’ OpenAPI ใง่กจ็พใ™ใ‚‹ใซใฏใ€ใใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ **ๅฟ…้ ˆ** ใจใ—ใฆใƒžใƒผใ‚ฏใ—ใพใ™ใ€‚ๅธธใซๅญ˜ๅœจใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใ“ใฎใŸใ‚ใ€ใƒขใƒ‡ใƒซใฎ JSON Schema ใฏใ€**ๅ…ฅๅŠ›ใ‹ๅ‡บๅŠ›ใ‹** ใซใ‚ˆใฃใฆ็•ฐใชใ‚‹ๅ ดๅˆใŒใ‚ใ‚Šใพใ™: + +- **ๅ…ฅๅŠ›** ใงใฏ `description` ใฏ **ๅฟ…้ ˆใงใฏใชใ„** +- **ๅ‡บๅŠ›** ใงใฏ **ๅฟ…้ ˆ**๏ผˆๅ€คใฏ `None`ใ€JSON ใงใฏ `null` ใฎๅฏ่ƒฝๆ€งใ‚ใ‚Š๏ผ‰ + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฎๅ‡บๅŠ›ใƒขใƒ‡ใƒซ { #model-for-output-in-docs } + +ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงๅ‡บๅŠ›ใƒขใƒ‡ใƒซใ‚’่ฆ‹ใ‚‹ใจใ€`name` ใจ `description` ใฎ **ไธกๆ–น** ใŒ **่ตคใ„ใ‚ขใ‚นใ‚ฟใƒชใ‚นใ‚ฏ** ใง **ๅฟ…้ ˆ** ใจใ—ใฆใƒžใƒผใ‚ฏใ•ใ‚Œใฆใ„ใพใ™: + +
+ +
+ +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฎๅ…ฅๅŠ›ใƒปๅ‡บๅŠ›ใƒขใƒ‡ใƒซ { #model-for-input-and-output-in-docs } + +ใ•ใ‚‰ใซใ€OpenAPI ใซๅซใพใ‚Œใ‚‹ๅˆฉ็”จๅฏ่ƒฝใชใ‚นใ‚ญใƒผใƒž๏ผˆJSON Schema๏ผ‰ใ‚’็ขบ่ชใ™ใ‚‹ใจใ€`Item-Input` ใจ `Item-Output` ใฎ 2 ใคใŒใ‚ใ‚‹ใ“ใจใŒๅˆ†ใ‹ใ‚Šใพใ™ใ€‚ + +`Item-Input` ใงใฏใ€`description` ใฏ **ๅฟ…้ ˆใงใฏใ‚ใ‚Šใพใ›ใ‚“**๏ผˆ่ตคใ„ใ‚ขใ‚นใ‚ฟใƒชใ‚นใ‚ฏใชใ—๏ผ‰ใ€‚ + +ไธ€ๆ–นใ€`Item-Output` ใงใฏใ€`description` ใฏ **ๅฟ…้ ˆ**๏ผˆ่ตคใ„ใ‚ขใ‚นใ‚ฟใƒชใ‚นใ‚ฏใ‚ใ‚Š๏ผ‰ใงใ™ใ€‚ + +
+ +
+ +ใ“ใฎ **Pydantic v2** ใฎๆฉŸ่ƒฝใซใ‚ˆใ‚Šใ€API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฏใ‚ˆใ‚Š **ๆญฃ็ขบ** ใซใชใ‚Šใ€่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚„ SDK ใ‚‚ใ‚ˆใ‚Šๆญฃ็ขบใซใชใ‚Šใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ˆใ‚Š่‰ฏใ„ **้–‹็™บ่€…ใ‚จใ‚ฏใ‚นใƒšใƒชใ‚จใƒณใ‚น** ใจไธ€่ฒซๆ€งใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚๐ŸŽ‰ + +## ใ‚นใ‚ญใƒผใƒžใ‚’ๅˆ†ใ‘ใชใ„ { #do-not-separate-schemas } + +ไธ€ๆ–นใงใ€**ๅ…ฅๅŠ›ใจๅ‡บๅŠ›ใงๅŒใ˜ใ‚นใ‚ญใƒผใƒž** ใซใ—ใŸใ„ๅ ดๅˆใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ + +ไธปใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใฏใ€ใ™ใงใซ่‡ชๅ‹•็”Ÿๆˆใ•ใ‚ŒใŸใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‚ณใƒผใƒ‰ใ‚„ SDK ใŒใ‚ใ‚Šใ€ใพใ ใใ‚Œใ‚‰ใ‚’ใ™ในใฆๆ›ดๆ–ฐใ—ใŸใใชใ„ๅ ดๅˆใงใ™ใ€‚ใ„ใšใ‚Œใฏๆ›ดๆ–ฐใ—ใŸใ„ใจใ—ใฆใ‚‚ใ€ไปŠใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +ใใฎๅ ดๅˆใฏใ€**FastAPI** ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `separate_input_output_schemas=False` ใงใ“ใฎๆฉŸ่ƒฝใ‚’็„กๅŠนๅŒ–ใงใใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +`separate_input_output_schemas` ใฎใ‚ตใƒใƒผใƒˆใฏ FastAPI `0.102.0` ใง่ฟฝๅŠ ใ•ใ‚Œใพใ—ใŸใ€‚๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงๅ…ฅๅŠ›ใƒปๅ‡บๅŠ›ใซๅŒไธ€ใ‚นใ‚ญใƒผใƒžใ‚’ไฝฟ็”จ { #same-schema-for-input-and-output-models-in-docs } + +ใ“ใ‚Œใงใƒขใƒ‡ใƒซใฎๅ…ฅๅŠ›ใจๅ‡บๅŠ›ใฏๅ˜ไธ€ใฎใ‚นใ‚ญใƒผใƒžใ€`Item` ใฎใฟใซใชใ‚Šใ€`description` ใฏ **ๅฟ…้ ˆใงใฏใ‚ใ‚Šใพใ›ใ‚“**: + +
+ +
diff --git a/docs/ja/docs/how-to/testing-database.md b/docs/ja/docs/how-to/testing-database.md new file mode 100644 index 0000000000..af9ad75090 --- /dev/null +++ b/docs/ja/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ†ใ‚นใƒˆ { #testing-a-database } + +ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€SQLใ€SQLModel ใซใคใ„ใฆใฏใ€SQLModel ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงๅญฆในใพใ™ใ€‚๐Ÿค“ + +FastAPI ใจไธ€็ท’ใซ SQLModel ใ‚’ไฝฟใ†ใŸใ‚ใฎใƒŸใƒ‹ ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใŒใ‚ใ‚Šใพใ™ใ€‚โœจ + +ใใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใซใฏใ€SQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ†ใ‚นใƒˆใซ้–ขใ™ใ‚‹ใ‚ปใ‚ฏใ‚ทใƒงใƒณใ‚‚ๅซใพใ‚Œใฆใ„ใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index 67e01ed535..90368b4ae3 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -40,7 +40,7 @@ FastAPI ใฏใ€Python ใฎๆจ™ๆบ–ใงใ‚ใ‚‹ๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆ Python ใง AP * **้ซ˜้€Ÿ**: **NodeJS** ใ‚„ **Go** ไธฆใฟใฎใจใฆใ‚‚้ซ˜ใ„ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚น๏ผˆStarlette ใจ Pydantic ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ [ๅˆฉ็”จๅฏ่ƒฝใชๆœ€ใ‚‚้ซ˜้€Ÿใช Python ใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใฎไธ€ใคใงใ™](#performance)ใ€‚ * **้ซ˜้€Ÿใชใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐ**: ้–‹็™บ้€Ÿๅบฆใ‚’็ด„ 200%ใ€œ300% ๅ‘ไธŠใ•ใ›ใพใ™ใ€‚* * **ๅฐ‘ใชใ„ใƒใ‚ฐ**: ้–‹็™บ่€…่ตทๅ› ใฎใƒ’ใƒฅใƒผใƒžใƒณใ‚จใƒฉใƒผใ‚’็ด„ 40% ๅ‰Šๆธ›ใ—ใพใ™ใ€‚* -* **็›ดๆ„Ÿ็š„**: ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใ€‚ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใง ่ฃœๅฎŒ ใŒไฝฟใˆใพใ™ใ€‚ใƒ‡ใƒใƒƒใ‚ฐๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ +* **็›ดๆ„Ÿ็š„**: ็ด ๆ™ดใ‚‰ใ—ใ„ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆใ€‚่ฃœๅฎŒ ใŒใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงไฝฟใˆใพใ™ใ€‚ใƒ‡ใƒใƒƒใ‚ฐๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ * **็ฐกๅ˜**: ็ฐกๅ˜ใซๅˆฉ็”จใƒป็ฟ’ๅพ—ใงใใ‚‹ใ‚ˆใ†ใซใƒ‡ใ‚ถใ‚คใƒณใ•ใ‚Œใฆใ„ใพใ™ใ€‚ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’่ชญใ‚€ๆ™‚้–“ใ‚’ๅ‰Šๆธ›ใ—ใพใ™ใ€‚ * **็Ÿญใ„**: ใ‚ณใƒผใƒ‰ใฎ้‡่ค‡ใ‚’ๆœ€ๅฐ้™ใซใ—ใพใ™ใ€‚ๅ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅฎฃ่จ€ใ‹ใ‚‰่ค‡ๆ•ฐใฎๆฉŸ่ƒฝใ‚’ๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ใƒใ‚ฐใ‚‚ๆธ›ใ‚Šใพใ™ใ€‚ * **ๅ …็‰ขๆ€ง**: ่‡ชๅ‹•ๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใ‚ˆใ‚Šใ€ๆœฌ็•ช็’ฐๅขƒๅ‘ใ‘ใฎใ‚ณใƒผใƒ‰ใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ @@ -127,7 +127,7 @@ FastAPI ใฏใ€Python ใฎๆจ™ๆบ–ใงใ‚ใ‚‹ๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆ Python ใง AP -Web API ใฎไปฃใ‚ใ‚Šใซใ‚ฟใƒผใƒŸใƒŠใƒซใงไฝฟ็”จใ™ใ‚‹ CLI ใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๅ ดๅˆใฏใ€**Typer** ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ +Web API ใฎไปฃใ‚ใ‚Šใซใ‚ฟใƒผใƒŸใƒŠใƒซใงไฝฟ็”จใ™ใ‚‹ CLI ใ‚ขใƒ—ใƒชใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ๅ ดๅˆใฏใ€**Typer** ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ **Typer** ใฏ FastAPI ใฎๅผŸๅˆ†ใงใ™ใ€‚ใใ—ใฆใ€**CLI ็‰ˆ FastAPI** ใ‚’ๆ„ๅ›ณใ—ใฆใ„ใพใ™ใ€‚ โŒจ๏ธ ๐Ÿš€ @@ -368,7 +368,7 @@ item: Item * ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ: * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใซ่‡ชๅ‹•ใงๆ˜Ž็ขบใชใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ * ๆทฑใ„ๅ…ฅใ‚ŒๅญใซใชใฃใŸ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ‚‚ๆคœ่จผใŒๅฏ่ƒฝใงใ™ใ€‚ -* ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‹ใ‚‰ Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใธใ€‚ไปฅไธ‹ใ‹ใ‚‰่ชญใฟๅ–ใ‚Šใพใ™: +* ๅ…ฅๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใ‹ใ‚‰ Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใธใ€‚ไปฅไธ‹ใ‹ใ‚‰่ชญใฟๅ–ใ‚Šใพใ™: * JSONใ€‚ * ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ * ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€‚ @@ -376,7 +376,7 @@ item: Item * ใƒ˜ใƒƒใƒ€ใƒผใ€‚ * ใƒ•ใ‚ฉใƒผใƒ ใ€‚ * ใƒ•ใ‚กใ‚คใƒซใ€‚ -* ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใ‹ใ‚‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใƒ‡ใƒผใ‚ฟใธ๏ผˆJSON ใจใ—ใฆ๏ผ‰ๅค‰ๆ›ใ—ใพใ™: +* ๅ‡บๅŠ›ใƒ‡ใƒผใ‚ฟใฎ ๅค‰ๆ›: Python ใฎใƒ‡ใƒผใ‚ฟใ‚„ๅž‹ใ‹ใ‚‰ใƒใƒƒใƒˆใƒฏใƒผใ‚ฏใƒ‡ใƒผใ‚ฟใธ๏ผˆJSON ใจใ—ใฆ๏ผ‰ๅค‰ๆ›ใ—ใพใ™: * Python ใฎๅž‹๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ใชใฉ๏ผ‰ใฎๅค‰ๆ›ใ€‚ * `datetime` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€‚ * `UUID` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ€‚ @@ -439,7 +439,7 @@ item: Item * **ใƒ˜ใƒƒใƒ€ใƒผ**ใ€**Cookie**ใ€**ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰**ใ€**ใƒ•ใ‚กใ‚คใƒซ**ใชใฉใ€ไป–ใฎใ•ใพใ–ใพใชๅ ดๆ‰€ใ‹ใ‚‰ใฎ **ใƒ‘ใƒฉใƒกใƒผใ‚ฟ** ๅฎฃ่จ€ใ€‚ * `maximum_length` ใ‚„ `regex` ใฎใ‚ˆใ†ใช **ๆคœ่จผๅˆถ็ด„** ใ‚’่จญๅฎšใ™ใ‚‹ๆ–นๆณ•ใ€‚ -* ้žๅธธใซๅผทๅŠ›ใงไฝฟใ„ใ‚„ใ™ใ„ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ€‚ +* ้žๅธธใซๅผทๅŠ›ใงไฝฟใ„ใ‚„ใ™ใ„ **ไพๅญ˜ๆ€งๆณจๅ…ฅ** ใ‚ทใ‚นใƒ†ใƒ ใ€‚ * **JWT ใƒˆใƒผใ‚ฏใƒณ**ใ‚’็”จใ„ใŸ **OAuth2** ใ‚„ **HTTP Basic** ่ช่จผใฎใ‚ตใƒใƒผใƒˆใ‚’ๅซใ‚€ใ€ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจ่ช่จผใ€‚ * **ๆทฑใใƒใ‚นใƒˆใ•ใ‚ŒใŸ JSON ใƒขใƒ‡ใƒซ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใฎใ€ใ‚ˆใ‚Š้ซ˜ๅบฆใช๏ผˆใ—ใ‹ใ—ๅŒๆง˜ใซ็ฐกๅ˜ใช๏ผ‰ๆ‰‹ๆณ•๏ผˆPydantic ใฎใŠใ‹ใ’ใงใ™๏ผ‰ใ€‚ * Strawberry ใŠใ‚ˆใณไป–ใฎใƒฉใ‚คใƒ–ใƒฉใƒชใซใ‚ˆใ‚‹ **GraphQL** ็ตฑๅˆใ€‚ @@ -524,7 +524,7 @@ Starlette ใซใ‚ˆใฃใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: * httpx - `TestClient` ใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ * jinja2 - ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆ่จญๅฎšใ‚’ไฝฟ็”จใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ -* python-multipart - `request.form()` ใจใจใ‚‚ใซใ€ใƒ•ใ‚ฉใƒผใƒ ใฎ ใ€Œparsingใ€ ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ +* python-multipart - `request.form()` ใจใจใ‚‚ใซใ€ใƒ•ใ‚ฉใƒผใƒ ใฎ ใ€Œparsingใ€ ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใŸใ„ๅ ดๅˆใซๅฟ…่ฆใงใ™ใ€‚ FastAPI ใซใ‚ˆใฃใฆไฝฟ็”จใ•ใ‚Œใ‚‹ใ‚‚ใฎ: diff --git a/docs/ja/docs/python-types.md b/docs/ja/docs/python-types.md index 26a9e2193c..a6b46c256d 100644 --- a/docs/ja/docs/python-types.md +++ b/docs/ja/docs/python-types.md @@ -1,12 +1,12 @@ # Pythonใฎๅž‹ใฎ็ดนไป‹ { #python-types-intro } -Pythonใงใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ€Œๅž‹ใƒ’ใƒณใƒˆใ€๏ผˆใ€Œๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ€ใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™๏ผ‰ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ +Python ใซใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ€Œๅž‹ใƒ’ใƒณใƒˆใ€๏ผˆใ€Œๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ€ใจใ‚‚ๅ‘ผใฐใ‚Œใพใ™๏ผ‰ใŒใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎ **ใ€Œๅž‹ใƒ’ใƒณใƒˆใ€** ใพใŸใฏใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใฏใ€ๅค‰ๆ•ฐใฎๅž‹ใ‚’ๅฎฃ่จ€ใงใใ‚‹็‰นๅˆฅใชๆง‹ๆ–‡ใงใ™ใ€‚ +ใ“ใ‚Œใ‚‰ใฎ **ใ€Œๅž‹ใƒ’ใƒณใƒˆใ€** ใ‚„ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใฏใ€ๅค‰ๆ•ฐใฎๅž‹ใ‚’ๅฎฃ่จ€ใงใใ‚‹็‰นๅˆฅใชๆง‹ๆ–‡ใงใ™ใ€‚ ๅค‰ๆ•ฐใซๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚„ใƒ„ใƒผใƒซใŒใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใงใใพใ™ใ€‚ -ใ“ใ‚ŒใฏPythonใฎๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใฎ **ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ/ใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅ** ใซใ™ใŽใพใ›ใ‚“ใ€‚**FastAPI** ใงไฝฟ็”จใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใชๆœ€ไฝŽ้™ใฎใ“ใจใ ใ‘ใ‚’ใ‚ซใƒใƒผใ—ใฆใ„ใพใ™ใ€‚...ๅฎŸ้š›ใซใฏๆœฌๅฝ“ใซๅฐ‘ใชใ„ใงใ™ใ€‚ +ใ“ใ‚Œใฏ Python ใฎๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใฎ **ใ‚ฏใ‚คใƒƒใ‚ฏใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ/ใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅ** ใซใ™ใŽใพใ›ใ‚“ใ€‚**FastAPI** ใงไฝฟใ†ใŸใ‚ใซๅฟ…่ฆใชๆœ€ไฝŽ้™ใฎใ“ใจใ ใ‘ใ‚’ใ‚ซใƒใƒผใ—ใฆใ„ใพใ™ใ€‚...ๅฎŸ้š›ใซใฏๆœฌๅฝ“ใซๅฐ‘ใชใ„ใงใ™ใ€‚ **FastAPI** ใฏใ™ในใฆใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใซๅŸบใฅใ„ใฆใŠใ‚Šใ€ๅคšใใฎๅผทใฟใจๅˆฉ็‚นใ‚’ไธŽใˆใฆใใ‚Œใพใ™ใ€‚ @@ -14,7 +14,7 @@ Pythonใงใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ€Œๅž‹ใƒ’ใƒณใƒˆใ€๏ผˆใ€Œๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ /// note | ๅ‚™่€ƒ -ใ‚‚ใ—ใ‚ใชใŸใŒPythonใฎๅฐ‚้–€ๅฎถใงใ€ใ™ใงใซๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใ™ในใฆ็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ‚ใ‚Œใฐใ€ๆฌกใฎ็ซ ใพใง่ชญใฟ้ฃ›ใฐใ—ใฆใใ ใ•ใ„ใ€‚ +ใ‚‚ใ—ใ‚ใชใŸใŒ Python ใฎๅฐ‚้–€ๅฎถใงใ€ใ™ใงใซๅž‹ใƒ’ใƒณใƒˆใซใคใ„ใฆใ™ในใฆ็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ‚ใ‚Œใฐใ€ๆฌกใฎ็ซ ใพใง่ชญใฟ้ฃ›ใฐใ—ใฆใใ ใ•ใ„ใ€‚ /// @@ -22,7 +22,7 @@ Pythonใงใฏใ‚ชใƒ—ใ‚ทใƒงใƒณใฎใ€Œๅž‹ใƒ’ใƒณใƒˆใ€๏ผˆใ€Œๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ ็ฐกๅ˜ใชไพ‹ใ‹ใ‚‰ๅง‹ใ‚ใฆใฟใพใ—ใ‚‡ใ†: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} ใ“ใฎใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’ๅ‘ผใณๅ‡บใ™ใจใ€ไปฅไธ‹ใŒๅ‡บๅŠ›ใ•ใ‚Œใพใ™: @@ -32,11 +32,11 @@ John Doe ใ“ใฎ้–ขๆ•ฐใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใ“ใจใ‚’่กŒใ„ใพใ™: -* `first_name`ใจ`last_name`ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ -* `title()`ใ‚’็”จใ„ใฆใ€ใใ‚Œใžใ‚Œใฎๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ -* ็œŸใ‚“ไธญใซใ‚นใƒšใƒผใ‚นใ‚’ๅ…ฅใ‚Œใฆ้€ฃ็ตใ—ใพใ™ใ€‚ +* `first_name` ใจ `last_name` ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ +* `title()` ใ‚’็”จใ„ใฆใ€ใใ‚Œใžใ‚Œใฎๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ +* ็œŸใ‚“ไธญใซใ‚นใƒšใƒผใ‚นใ‚’ๅ…ฅใ‚Œใฆ้€ฃ็ตใ—ใพใ™ใ€‚ -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### ็ทจ้›† { #edit-it } @@ -48,11 +48,11 @@ John Doe ใ—ใ‹ใ—ใ€ใใ†ใ™ใ‚‹ใจใ€Œๆœ€ๅˆใฎๆ–‡ๅญ—ใ‚’ๅคงๆ–‡ๅญ—ใซๅค‰ๆ›ใ™ใ‚‹ใ‚ใฎใƒกใ‚ฝใƒƒใƒ‰ใ€ใ‚’ๅ‘ผใณๅ‡บใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -ใใ‚Œใฏ`upper`ใงใ—ใŸใ‹๏ผŸ`uppercase`ใงใ—ใŸใ‹๏ผŸ`first_uppercase`๏ผŸ`capitalize`๏ผŸ +ใใ‚Œใฏ `upper` ใงใ—ใŸใ‹๏ผŸ`uppercase` ใงใ—ใŸใ‹๏ผŸ`first_uppercase`๏ผŸ`capitalize`๏ผŸ ใใ—ใฆใ€ๅคใใ‹ใ‚‰ใƒ—ใƒญใ‚ฐใƒฉใƒžใƒผใฎๅ‹ไบบใงใ‚ใ‚‹ใ‚จใƒ‡ใ‚ฃใ‚ฟใง่‡ชๅ‹•่ฃœๅฎŒใ‚’่ฉฆใ—ใฆใฟใพใ™ใ€‚ -้–ขๆ•ฐใฎๆœ€ๅˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ`first_name`ใ‚’ๅ…ฅๅŠ›ใ—ใ€ใƒ‰ใƒƒใƒˆ(`.`)ใ‚’ๅ…ฅๅŠ›ใ—ใฆใ‹ใ‚‰ใ€`Ctrl+Space`ใ‚’ๆŠผใ™ใจ่ฃœๅฎŒใŒๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ +้–ขๆ•ฐใฎๆœ€ๅˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟ `first_name` ใ‚’ๅ…ฅๅŠ›ใ—ใ€ใƒ‰ใƒƒใƒˆ๏ผˆ`.`๏ผ‰ใ‚’ๅ…ฅๅŠ›ใ—ใฆใ‹ใ‚‰ใ€`Ctrl+Space` ใ‚’ๆŠผใ™ใจ่ฃœๅฎŒใŒๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ๆ‚ฒใ—ใ„ใ“ใจใซใ€ใ“ใ‚Œใฏใชใ‚“ใฎๅฝนใซใ‚‚็ซ‹ใกใพใ›ใ‚“: @@ -78,7 +78,7 @@ John Doe ใใ‚ŒใŒใ€Œๅž‹ใƒ’ใƒณใƒˆใ€ใงใ™: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} ใ“ใ‚Œใฏใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใฎใจๅŒใ˜ใงใฏใ‚ใ‚Šใพใ›ใ‚“: @@ -94,7 +94,7 @@ John Doe ใ—ใ‹ใ—ไปŠใ€ใ‚ใชใŸใŒๅ†ใณใใฎ้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใฆใ„ใ‚‹ๆœ€ไธญใซใ€ๅž‹ใƒ’ใƒณใƒˆใ‚’ไฝฟใฃใฆใ„ใ‚‹ใจๆƒณๅƒใ—ใฆใฟใฆใใ ใ•ใ„ใ€‚ -ๅŒใ˜ใ‚ฟใ‚คใƒŸใƒณใ‚ฐใง`Ctrl+Space`ใง่‡ชๅ‹•่ฃœๅฎŒใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: +ๅŒใ˜ใ‚ฟใ‚คใƒŸใƒณใ‚ฐใง `Ctrl+Space` ใง่‡ชๅ‹•่ฃœๅฎŒใ‚’ๅฎŸ่กŒใ™ใ‚‹ใจใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: @@ -106,15 +106,15 @@ John Doe ใ“ใฎ้–ขๆ•ฐใ‚’่ฆ‹ใฆใใ ใ•ใ„ใ€‚ใ™ใงใซๅž‹ใƒ’ใƒณใƒˆใ‚’ๆŒใฃใฆใ„ใพใ™: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏๅค‰ๆ•ฐใฎๅž‹ใ‚’็Ÿฅใฃใฆใ„ใ‚‹ใฎใงใ€่ฃœๅฎŒใ ใ‘ใงใชใใ€ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ‚’ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: -ใ“ใ‚Œใง`age`ใ‚’`str(age)`ใงๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ—ใฆไฟฎๆญฃใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™: +ใ“ใ‚Œใง `age` ใ‚’ `str(age)` ใงๆ–‡ๅญ—ๅˆ—ใซๅค‰ๆ›ใ—ใฆไฟฎๆญฃใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## ๅž‹ใฎๅฎฃ่จ€ { #declaring-types } @@ -124,7 +124,7 @@ John Doe ### ๅ˜็ด”ใชๅž‹ { #simple-types } -`str`ใ ใ‘ใงใชใใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ™ในใฆใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ +`str` ใ ใ‘ใงใชใใ€Python ใฎๆจ™ๆบ–็š„ใชๅž‹ใ™ในใฆใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ ไพ‹ใˆใฐใ€ไปฅไธ‹ใ‚’ไฝฟ็”จๅฏ่ƒฝใงใ™: @@ -133,51 +133,54 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆŒใคใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ { #generic-types-with-type-parameters } +### `typing` ใƒขใ‚ธใƒฅใƒผใƒซ { #typing-module } -ใƒ‡ใƒผใ‚ฟๆง‹้€ ใฎไธญใซใฏใ€`dict`ใ€`list`ใ€`set`ใ€`tuple`ใฎใ‚ˆใ†ใซไป–ใฎๅ€คใ‚’ๅซใ‚€ใ“ใจใŒใงใใ‚‹ใ‚‚ใฎใŒใ‚ใ‚Šใพใ™ใ€‚ใพใŸๅ†…้ƒจใฎๅ€คใ‚‚็‹ฌ่‡ชใฎๅž‹ใ‚’ๆŒใคใ“ใจใŒใงใใพใ™ใ€‚ +ใ„ใใคใ‹ใฎ่ฟฝๅŠ ใฎใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใงใฏใ€ๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎ `typing` ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰ไฝ•ใ‹ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ไพ‹ใˆใฐใ€Œไปปๆ„ใฎๅž‹ใ€ใ‚’ๅ—ใ‘ไป˜ใ‘ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใ—ใŸใ„ๅ ดๅˆใ€`typing` ใฎ `Any` ใ‚’ไฝฟใˆใพใ™: -ๅ†…้ƒจใฎๅž‹ใ‚’ๆŒใคใ“ใ‚Œใ‚‰ใฎๅž‹ใฏใ€Œ**generic**ใ€ๅž‹ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ใใ—ใฆใ€ๅ†…้ƒจใฎๅž‹ใ‚‚ๅซใ‚ใฆๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒๅฏ่ƒฝใงใ™ใ€‚ +```python +from typing import Any -ใ“ใ‚Œใ‚‰ใฎๅž‹ใ‚„ๅ†…้ƒจใฎๅž‹ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€Pythonใฎๆจ™ๆบ–ใƒขใ‚ธใƒฅใƒผใƒซ`typing`ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹ใŸใ‚ใซ็‰นๅˆฅใซๅญ˜ๅœจใ—ใฆใ„ใพใ™ใ€‚ -#### ๆ–ฐใ—ใ„Pythonใƒใƒผใ‚ธใƒงใƒณ { #newer-versions-of-python } - -`typing`ใ‚’ไฝฟใ†ๆง‹ๆ–‡ใฏใ€Python 3.6ใ‹ใ‚‰ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใพใง๏ผˆPython 3.9ใ€Python 3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใ™ในใฆใฎใƒใƒผใ‚ธใƒงใƒณใจ **ไบ’ๆ›ๆ€ง** ใŒใ‚ใ‚Šใพใ™ใ€‚ +def some_function(data: Any): + print(data) +``` -PythonใŒ้€ฒๅŒ–ใ™ใ‚‹ใซใคใ‚Œใ€**ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ** ใงใฏใ“ใ‚Œใ‚‰ใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใธใฎใ‚ตใƒใƒผใƒˆใŒๆ”นๅ–„ใ•ใ‚Œใ€ๅคšใใฎๅ ดๅˆใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ†ๅฟ…่ฆใ™ใ‚‰ใชใใชใ‚Šใพใ™ใ€‚ +### ใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ { #generic-types } -ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใ‚ˆใ‚Šๆ–ฐใ—ใ„Pythonใƒใƒผใ‚ธใƒงใƒณใ‚’้ธในใ‚‹ใชใ‚‰ใ€ใใฎ่ฟฝๅŠ ใฎใ‚ทใƒณใƒ—ใƒซใ•ใ‚’ๆดป็”จใงใใพใ™ใ€‚ +ไธ€้ƒจใฎๅž‹ใฏใ€่ง’ๆ‹ฌๅผงๅ†…ใงใ€Œๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ๅ†…้ƒจใฎๅž‹ใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€Œๆ–‡ๅญ—ๅˆ—ใฎใƒชใ‚นใƒˆใ€ใฏ `list[str]` ใจใ—ใฆๅฎฃ่จ€ใ—ใพใ™ใ€‚ -ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅ…จไฝ“ใงใ€Pythonใฎๅ„ใƒใƒผใ‚ธใƒงใƒณใจไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ไพ‹๏ผˆๅทฎๅˆ†ใŒใ‚ใ‚‹ๅ ดๅˆ๏ผ‰ใ‚’็คบใ—ใฆใ„ใพใ™ใ€‚ +ใ“ใฎใ‚ˆใ†ใซๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚Œใ‚‹ๅž‹ใฏ **Generic types**๏ผˆใ‚ธใ‚งใƒใƒชใ‚ฏใ‚น๏ผ‰ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ -ไพ‹ใˆใฐใ€Œ**Python 3.6+**ใ€ใฏPython 3.6ไปฅไธŠ๏ผˆ3.7ใ€3.8ใ€3.9ใ€3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใจไบ’ๆ›ๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ใพใŸใ€Œ**Python 3.9+**ใ€ใฏPython 3.9ไปฅไธŠ๏ผˆ3.10ใชใฉใ‚’ๅซใ‚€๏ผ‰ใจไบ’ๆ›ๆ€งใŒใ‚ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ +ๆฌกใฎ็ต„ใฟ่พผใฟๅž‹ใ‚’ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใจใ—ใฆ๏ผˆ่ง’ๆ‹ฌๅผงใจๅ†…้ƒจใฎๅž‹ใง๏ผ‰ไฝฟใˆใพใ™: -**ๆœ€ๆ–ฐใฎPythonใƒใƒผใ‚ธใƒงใƒณ** ใ‚’ไฝฟใˆใ‚‹ใชใ‚‰ใ€ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณๅ‘ใ‘ใฎไพ‹ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ไพ‹ใˆใฐใ€Œ**Python 3.10+**ใ€ใฎใ‚ˆใ†ใซใ€ใใ‚Œใ‚‰ใฏ **ๆœ€่‰ฏใ‹ใคๆœ€ใ‚‚ใ‚ทใƒณใƒ—ใƒซใชๆง‹ๆ–‡** ใซใชใ‚Šใพใ™ใ€‚ +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } -ไพ‹ใˆใฐใ€`str`ใฎ`list`ใฎๅค‰ๆ•ฐใ‚’ๅฎš็พฉใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +ไพ‹ใˆใฐใ€`str` ใฎ `list` ใฎๅค‰ๆ•ฐใ‚’ๅฎš็พฉใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ ๅŒใ˜ใ‚ณใƒญใƒณ๏ผˆ`:`๏ผ‰ใฎๆง‹ๆ–‡ใงๅค‰ๆ•ฐใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ -ๅž‹ใจใ—ใฆใ€`list`ใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ +ๅž‹ใจใ—ใฆใ€`list` ใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ ใƒชใ‚นใƒˆใฏใ„ใใคใ‹ใฎๅ†…้ƒจใฎๅž‹ใ‚’ๅซใ‚€ๅž‹ใชใฎใงใ€ใใ‚Œใ‚‰ใ‚’่ง’ๆ‹ฌๅผงใงๅ›ฒใฟใพใ™: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | ๆƒ…ๅ ฑ ่ง’ๆ‹ฌๅผงๅ†…ใฎๅ†…้ƒจใฎๅž‹ใฏใ€Œๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใจๅ‘ผใฐใ‚Œใฆใ„ใพใ™ใ€‚ -ใ“ใฎๅ ดๅˆใ€`str`ใฏ`list`ใซๆธกใ•ใ‚Œใ‚‹ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ +ใ“ใฎๅ ดๅˆใ€`str` ใฏ `list` ใซๆธกใ•ใ‚Œใ‚‹ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ /// -ใคใพใ‚Š: ๅค‰ๆ•ฐ`items`ใฏ`list`ใงใ‚ใ‚Šใ€ใ“ใฎใƒชใ‚นใƒˆใฎๅ„้ …็›ฎใฏ`str`ใงใ™ใ€‚ +ใคใพใ‚Š: ๅค‰ๆ•ฐ `items` ใฏ `list` ใงใ‚ใ‚Šใ€ใ“ใฎใƒชใ‚นใƒˆใฎๅ„้ …็›ฎใฏ `str` ใงใ™ใ€‚ ใใ†ใ™ใ‚‹ใ“ใจใงใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใƒชใ‚นใƒˆใฎ้ …็›ฎใ‚’ๅ‡ฆ็†ใ—ใฆใ„ใ‚‹้–“ใซใ‚‚ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใงใใพใ™ใ€‚ @@ -185,78 +188,54 @@ PythonใŒ้€ฒๅŒ–ใ™ใ‚‹ใซใคใ‚Œใ€**ๆ–ฐใ—ใ„ใƒใƒผใ‚ธใƒงใƒณ** ใงใฏใ“ใ‚Œใ‚‰ใฎ ๅž‹ใŒใชใ‘ใ‚Œใฐใ€ใใ‚Œใฏใปใผไธๅฏ่ƒฝใงใ™ใ€‚ -ๅค‰ๆ•ฐ`item`ใฏใƒชใ‚นใƒˆ`items`ใฎ่ฆ็ด ใฎไธ€ใคใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ +ๅค‰ๆ•ฐ `item` ใฏใƒชใ‚นใƒˆ `items` ใฎ่ฆ็ด ใฎไธ€ใคใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใใ‚Œใงใ‚‚ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใใ‚ŒใŒ`str`ใงใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใฃใฆใ„ใฆใ€ใใฎใŸใ‚ใฎใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ +ใใ‚Œใงใ‚‚ใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใฏใใ‚ŒใŒ `str` ใงใ‚ใ‚‹ใ“ใจใ‚’็Ÿฅใฃใฆใ„ใฆใ€ใใฎใŸใ‚ใฎใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ #### Tuple ใจ Set { #tuple-and-set } -`tuple`ใจ`set`ใฎๅฎฃ่จ€ใ‚‚ๅŒๆง˜ใงใ™: +`tuple` ใจ `set` ใฎๅฎฃ่จ€ใ‚‚ๅŒๆง˜ใงใ™: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} ใคใพใ‚Š: -* ๅค‰ๆ•ฐ`items_t`ใฏ`int`ใ€ๅˆฅใฎ`int`ใ€`str`ใฎ3ใคใฎ้ …็›ฎใ‚’ๆŒใค`tuple`ใงใ™ใ€‚ -* ๅค‰ๆ•ฐ`items_s`ใฏ`set`ใงใ‚ใ‚Šใ€ใใฎๅ„้ …็›ฎใฏ`bytes`ๅž‹ใงใ™ใ€‚ +* ๅค‰ๆ•ฐ `items_t` ใฏ `int`ใ€ๅˆฅใฎ `int`ใ€`str` ใฎ 3 ใคใฎ้ …็›ฎใ‚’ๆŒใค `tuple` ใงใ™ใ€‚ +* ๅค‰ๆ•ฐ `items_s` ใฏ `set` ใงใ‚ใ‚Šใ€ใใฎๅ„้ …็›ฎใฏ `bytes` ๅž‹ใงใ™ใ€‚ #### Dict { #dict } -`dict`ใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€ใ‚ซใƒณใƒžๅŒบๅˆ‡ใ‚Šใง2ใคใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™ใ€‚ +`dict` ใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€ใ‚ซใƒณใƒžๅŒบๅˆ‡ใ‚Šใง 2 ใคใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™ใ€‚ -ๆœ€ๅˆใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎใ‚ญใƒผใงใ™ใ€‚ +ๆœ€ๅˆใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ `dict` ใฎใ‚ญใƒผใงใ™ใ€‚ -2็•ช็›ฎใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`dict`ใฎๅ€คใงใ™: +2 ็•ช็›ฎใฎๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ `dict` ใฎๅ€คใงใ™: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} ใคใพใ‚Š: -* ๅค‰ๆ•ฐ`prices`ใฏ`dict`ใงใ™: - * ใ“ใฎ`dict`ใฎใ‚ญใƒผใฏ`str`ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎๅๅ‰๏ผ‰ใ€‚ - * ใ“ใฎ`dict`ใฎๅ€คใฏ`float`ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎไพกๆ ผ๏ผ‰ใ€‚ +* ๅค‰ๆ•ฐ `prices` ใฏ `dict` ใงใ™: + * ใ“ใฎ `dict` ใฎใ‚ญใƒผใฏ `str` ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎๅๅ‰๏ผ‰ใ€‚ + * ใ“ใฎ `dict` ใฎๅ€คใฏ `float` ๅž‹ใงใ™๏ผˆไพ‹ใˆใฐใ€ๅ„้ …็›ฎใฎไพกๆ ผ๏ผ‰ใ€‚ #### Union { #union } -ๅค‰ๆ•ฐใŒ**่ค‡ๆ•ฐใฎๅž‹ใฎใ„ใšใ‚Œใ‹**ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€`int`ใพใŸใฏ`str`ใงใ™ใ€‚ - -Python 3.6ไปฅไธŠ๏ผˆPython 3.10ใ‚’ๅซใ‚€๏ผ‰ใงใฏใ€`typing`ใฎ`Union`ๅž‹ใ‚’ไฝฟใ„ใ€่ง’ๆ‹ฌๅผงใฎไธญใซๅ—ใ‘ไป˜ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ๅž‹ใ‚’ๅ…ฅใ‚Œใ‚‰ใ‚Œใพใ™ใ€‚ +ๅค‰ๆ•ฐใŒ **่ค‡ๆ•ฐใฎๅž‹ใฎใ„ใšใ‚Œใ‹** ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ไพ‹ใˆใฐใ€`int` ใพใŸใฏ `str` ใงใ™ใ€‚ -Python 3.10ใงใฏใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใฎใ‚ใ‚‹ๅž‹ใ‚’็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใงๅŒบๅˆ‡ใฃใฆๆ›ธใ‘ใ‚‹ **ๆ–ฐใ—ใ„ๆง‹ๆ–‡** ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +ใใ‚Œใ‚’ๅฎš็พฉใ™ใ‚‹ใซใฏใ€ไธกๆ–นใฎๅž‹ใ‚’ๅŒบๅˆ‡ใ‚‹ใŸใ‚ใซ ็ธฆๆฃ’๏ผˆ`|`๏ผ‰ ใ‚’ไฝฟใ„ใพใ™ใ€‚ -//// tab | Python 3.10+ +ใ“ใ‚Œใฏใ€Œใƒฆใƒ‹ใ‚ชใƒณ๏ผˆunion๏ผ‰ใ€ใจๅ‘ผใฐใ‚Œใพใ™ใ€‚ๅค‰ๆ•ฐใŒใใ‚Œใ‚‰ 2 ใคใฎๅž‹ใฎ้›†ๅˆใฎๅ’Œ้›†ๅˆใฎใ„ใšใ‚Œใ‹ใซใชใ‚Šๅพ—ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -ใฉใกใ‚‰ใฎๅ ดๅˆใ‚‚ใ€`item`ใฏ`int`ใพใŸใฏ`str`ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ - -#### `None`ใฎๅฏ่ƒฝๆ€ง { #possibly-none } - -ๅ€คใŒ`str`ใฎใ‚ˆใ†ใชๅž‹ใ‚’ๆŒใคๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ไธ€ๆ–นใงใ€`None`ใซใ‚‚ใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ - -Python 3.6ไปฅไธŠ๏ผˆPython 3.10ใ‚’ๅซใ‚€๏ผ‰ใงใฏใ€`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰`Optional`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟใ†ใ“ใจใงๅฎฃ่จ€ใงใใพใ™ใ€‚ - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -ใŸใ ใฎ`str`ใฎไปฃใ‚ใ‚Šใซ`Optional[str]`ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ๅ€คใŒๅธธใซ`str`ใงใ‚ใ‚‹ใจไปฎๅฎšใ—ใฆใ„ใ‚‹ใจใใซใ€ๅฎŸ้š›ใซใฏ`None`ใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚‹ใจใ„ใ†ใ‚จใƒฉใƒผใ‚’ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒๆคœๅ‡บใ™ใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ +ใ“ใ‚Œใฏ `item` ใŒ `int` ใพใŸใฏ `str` ใซใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™. -`Optional[Something]`ใฏๅฎŸ้š›ใซใฏ`Union[Something, None]`ใฎใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆใงใ€ไธก่€…ใฏ็ญ‰ไพกใงใ™ใ€‚ +#### `None` ใฎๅฏ่ƒฝๆ€ง { #possibly-none } -ใ“ใ‚Œใฏใ€Python 3.10ใงใฏ`Something | None`ใ‚‚ไฝฟใˆใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™: +ๅ€คใŒ `str` ใฎใ‚ˆใ†ใชๅž‹ใ‚’ๆŒใคๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ไธ€ๆ–นใงใ€`None` ใซใ‚‚ใชใ‚Šๅพ—ใ‚‹ใ“ใจใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ //// tab | Python 3.10+ @@ -266,120 +245,31 @@ Python 3.6ไปฅไธŠ๏ผˆPython 3.10ใ‚’ๅซใ‚€๏ผ‰ใงใฏใ€`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰ //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### `Union`ใพใŸใฏ`Optional`ใฎไฝฟ็”จ { #using-union-or-optional } - -Python 3.10ๆœชๆบ€ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝฟใฃใฆใ„ใ‚‹ๅ ดๅˆใ€ใ“ใ‚Œใฏ็งใฎใจใฆใ‚‚ **ไธป่ฆณ็š„** ใช่ฆณ็‚นใ‹ใ‚‰ใฎใƒ’ใƒณใƒˆใงใ™: - -* ๐Ÿšจ `Optional[SomeType]`ใฏ้ฟใ‘ใฆใใ ใ•ใ„ -* ไปฃใ‚ใ‚Šใซ โœจ **`Union[SomeType, None]`ใ‚’ไฝฟใฃใฆใใ ใ•ใ„** โœจ - -ใฉใกใ‚‰ใ‚‚็ญ‰ไพกใงใ€ๅ†…้ƒจ็š„ใซใฏๅŒใ˜ใงใ™ใŒใ€`Optional`ใ‚ˆใ‚Š`Union`ใ‚’ใŠใ™ใ™ใ‚ใ—ใพใ™ใ€‚ใจใ„ใ†ใฎใ‚‚ใ€Œ**optional**ใ€ใจใ„ใ†ๅ˜่ชžใฏๅ€คใŒใ‚ชใƒ—ใ‚ทใƒงใƒณใงใ‚ใ‚‹ใ“ใจใ‚’็คบๅ”†ใ™ใ‚‹ใ‚ˆใ†ใซ่ฆ‹ใˆใพใ™ใŒใ€ๅฎŸ้š›ใซใฏใ€Œ`None`ใซใชใ‚Šๅพ—ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใ‚ใ‚Šใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใฏใชใๅฟ…้ ˆใงใ‚ใ‚‹ๅ ดๅˆใงใ‚‚ใใ†ใ ใ‹ใ‚‰ใงใ™ใ€‚ - -`Union[SomeType, None]`ใฎใปใ†ใŒๆ„ๅ‘ณใŒใ‚ˆใ‚Šๆ˜Ž็คบ็š„ใ ใจๆ€ใ„ใพใ™ใ€‚ - -ใ“ใ‚Œใฏ่จ€่‘‰ใ‚„ๅๅ‰ใฎ่ฉฑใซใ™ใŽใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ใใฎ่จ€่‘‰ใฏใ‚ใชใŸใ‚„ใƒใƒผใƒ ใƒกใ‚คใƒˆใŒใ‚ณใƒผใƒ‰ใ‚’ใฉใ†่€ƒใˆใ‚‹ใ‹ใซๅฝฑ้Ÿฟใ—ๅพ—ใพใ™ใ€‚ - -ไพ‹ใจใ—ใฆใ€ใ“ใฎ้–ขๆ•ฐใ‚’่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -ใƒ‘ใƒฉใƒกใƒผใ‚ฟ`name`ใฏ`Optional[str]`ใจใ—ใฆๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใŒใ€**ใ‚ชใƒ—ใ‚ทใƒงใƒณใงใฏใ‚ใ‚Šใพใ›ใ‚“**ใ€‚ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใชใ—ใง้–ขๆ•ฐใ‚’ๅ‘ผใณๅ‡บใ›ใพใ›ใ‚“: - -```Python -say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ -``` - -`name`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใ„ใŸใ‚ใ€**ไพ็„ถใจใ—ใฆๅฟ…้ ˆ**๏ผˆ*optional*ใงใฏใชใ„๏ผ‰ใงใ™ใ€‚ใใ‚Œใงใ‚‚ใ€`name`ใฏๅ€คใจใ—ใฆ`None`ใ‚’ๅ—ใ‘ไป˜ใ‘ใพใ™: - -```Python -say_hi(name=None) # This works, None is valid ๐ŸŽ‰ -``` - -่‰ฏใ„็Ÿฅใ‚‰ใ›ใจใ—ใฆใ€Python 3.10ใซใชใ‚Œใฐใใฎๅฟƒ้…ใฏไธ่ฆใงใ™ใ€‚ๅž‹ใฎใƒฆใƒ‹ใ‚ชใƒณใ‚’ๅฎš็พฉใ™ใ‚‹ใŸใ‚ใซ`|`ใ‚’ๅ˜็ด”ใซไฝฟใˆใ‚‹ใ‹ใ‚‰ใงใ™: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -ใใ—ใฆใ€`Optional`ใ‚„`Union`ใฎใ‚ˆใ†ใชๅๅ‰ใซใคใ„ใฆๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใ‚‚ใชใใชใ‚Šใพใ™ใ€‚๐Ÿ˜Ž - -#### ใ‚ธใ‚งใƒใƒชใƒƒใ‚ฏๅž‹ { #generic-types } - -่ง’ๆ‹ฌๅผงใงๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅ–ใ‚‹ใ“ใ‚Œใ‚‰ใฎๅž‹ใฏใ€ไพ‹ใˆใฐๆฌกใฎใ‚ˆใ†ใซ **Generic types** ใพใŸใฏ **Generics** ใจๅ‘ผใฐใ‚Œใพใ™: - -//// tab | Python 3.10+ - -ๅŒใ˜็ต„ใฟ่พผใฟๅž‹ใ‚’ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใจใ—ใฆ๏ผˆ่ง’ๆ‹ฌๅผงใจๅ†…้ƒจใฎๅž‹ใง๏ผ‰ไฝฟใˆใพใ™: - -* `list` -* `tuple` -* `set` -* `dict` - -ใพใŸใ€ใ“ใ‚ŒใพใงใฎPythonใƒใƒผใ‚ธใƒงใƒณใจๅŒๆง˜ใซใ€`typing`ใƒขใ‚ธใƒฅใƒผใƒซใ‹ใ‚‰: - -* `Union` -* `Optional` -* ...and others. - -Python 3.10ใงใฏใ€ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใฎ`Union`ใ‚„`Optional`ใ‚’ไฝฟใ†ไปฃๆ›ฟใจใ—ใฆใ€ๅž‹ใฎใƒฆใƒ‹ใ‚ชใƒณใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ็ธฆๆฃ’๏ผˆ`|`๏ผ‰ใ‚’ไฝฟใˆใพใ™ใ€‚ใ“ใ‚Œใฏใšใฃใจ่‰ฏใใ€ใ‚ˆใ‚Šใ‚ทใƒณใƒ—ใƒซใงใ™ใ€‚ - -//// - -//// tab | Python 3.9+ - -ๅŒใ˜็ต„ใฟ่พผใฟๅž‹ใ‚’ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใจใ—ใฆ๏ผˆ่ง’ๆ‹ฌๅผงใจๅ†…้ƒจใฎๅž‹ใง๏ผ‰ไฝฟใˆใพใ™: - -* `list` -* `tuple` -* `set` -* `dict` - -ใใ—ใฆ`typing`ใƒขใ‚ธใƒฅใƒผใƒซใฎใ‚ธใ‚งใƒใƒชใ‚ฏใ‚น: - -* `Union` -* `Optional` -* ...and others. - -//// +ใŸใ ใฎ `str` ใฎไปฃใ‚ใ‚Šใซ `str | None` ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ๅ€คใŒๅธธใซ `str` ใงใ‚ใ‚‹ใจไปฎๅฎšใ—ใฆใ„ใ‚‹ใจใใซใ€ๅฎŸ้š›ใซใฏ `None` ใงใ‚ใ‚‹ๅฏ่ƒฝๆ€งใ‚‚ใ‚ใ‚‹ใจใ„ใ†ใ‚จใƒฉใƒผใ‚’ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒๆคœๅ‡บใ™ใ‚‹ใฎใซๅฝน็ซ‹ใกใพใ™ใ€‚ ### ๅž‹ใจใ—ใฆใฎใ‚ฏใƒฉใ‚น { #classes-as-types } ๅค‰ๆ•ฐใฎๅž‹ใจใ—ใฆใ‚ฏใƒฉใ‚นใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -ๅๅ‰ใ‚’ๆŒใค`Person`ใ‚ฏใƒฉใ‚นใŒใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†: +ๅๅ‰ใ‚’ๆŒใค `Person` ใ‚ฏใƒฉใ‚นใŒใ‚ใ‚‹ใจใ—ใพใ—ใ‚‡ใ†: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} -ๅค‰ๆ•ฐใ‚’`Person`ๅž‹ใจใ—ใฆๅฎฃ่จ€ใงใใพใ™: +ๅค‰ๆ•ฐใ‚’ `Person` ๅž‹ใจใ—ใฆๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} ใใ—ใฆใ€ๅ†ใณใ€ใ™ในใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚’ๅพ—ใ‚‹ใ“ใจใŒใงใใพใ™: -ใ“ใ‚Œใฏใ€Œ`one_person`ใฏใ‚ฏใƒฉใ‚น`Person`ใฎ**ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น**ใงใ‚ใ‚‹ใ€ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ +ใ“ใ‚Œใฏใ€Œ`one_person` ใฏใ‚ฏใƒฉใ‚น `Person` ใฎ **ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚น** ใงใ‚ใ‚‹ใ€ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ -ใ€Œ`one_person`ใฏ`Person`ใจใ„ใ†ๅๅ‰ใฎ**ใ‚ฏใƒฉใ‚น**ใงใ‚ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +ใ€Œ`one_person` ใฏ `Person` ใจใ„ใ†ๅๅ‰ใฎ **ใ‚ฏใƒฉใ‚น** ใงใ‚ใ‚‹ใ€ใจใ„ใ†ๆ„ๅ‘ณใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -## Pydanticใฎใƒขใƒ‡ใƒซ { #pydantic-models } +## Pydantic ใฎใƒขใƒ‡ใƒซ { #pydantic-models } -Pydantic ใฏใƒ‡ใƒผใ‚ฟๆคœ่จผใ‚’่กŒใ†ใŸใ‚ใฎPythonใƒฉใ‚คใƒ–ใƒฉใƒชใงใ™ใ€‚ +Pydantic ใฏใƒ‡ใƒผใ‚ฟๆคœ่จผใ‚’่กŒใ†ใŸใ‚ใฎ Python ใƒฉใ‚คใƒ–ใƒฉใƒชใงใ™ใ€‚ ใƒ‡ใƒผใ‚ฟใฎใ€Œๅฝขใ€ใ‚’ๅฑžๆ€งไป˜ใใฎใ‚ฏใƒฉใ‚นใจใ—ใฆๅฎฃ่จ€ใ—ใพใ™ใ€‚ @@ -389,53 +279,47 @@ Python 3.10ใงใฏใ€ใ‚ธใ‚งใƒใƒชใ‚ฏใ‚นใฎ`Union`ใ‚„`Optional`ใ‚’ไฝฟใ†ไปฃๆ›ฟใจ ใพใŸใ€ใใฎ็ตๆžœใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ™ในใฆใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใฎใ‚ตใƒใƒผใƒˆใ‚’ๅ—ใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -Pydanticใฎๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰ใฎไพ‹: +Pydantic ใฎๅ…ฌๅผใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‹ใ‚‰ใฎไพ‹: {* ../../docs_src/python_types/tutorial011_py310.py *} /// info | ๆƒ…ๅ ฑ -Pydanticใฎ่ฉณ็ดฐใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +Pydantic ใฎ่ฉณ็ดฐใฏใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// -**FastAPI** ใฏใ™ในใฆPydanticใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใพใ™ใ€‚ +**FastAPI** ใฏใ™ในใฆ Pydantic ใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใพใ™ใ€‚ -ใ™ในใฆใฎใ“ใจใฏ[ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](tutorial/index.md){.internal-link target=_blank}ใงๅฎŸ้š›ใซ่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ - -/// tip | ่ฑ†็Ÿฅ่ญ˜ - -Pydanticใซใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใชใ—ใง`Optional`ใพใŸใฏ`Union[Something, None]`ใ‚’ไฝฟใฃใŸๅ ดๅˆใฎ็‰นๅˆฅใชๆŒ™ๅ‹•ใŒใ‚ใ‚Šใพใ™ใ€‚่ฉณ็ดฐใฏPydanticใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎRequired Optional fieldsใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ - -/// +ใ™ในใฆใฎใ“ใจใฏ [ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](tutorial/index.md){.internal-link target=_blank} ใงๅฎŸ้š›ใซ่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ ## ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณไป˜ใๅž‹ใƒ’ใƒณใƒˆ { #type-hints-with-metadata-annotations } -Pythonใซใฏใ€`Annotated`ใ‚’ไฝฟใฃใฆๅž‹ใƒ’ใƒณใƒˆใซ**่ฟฝๅŠ ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ**ใ‚’ไป˜ไธŽใงใใ‚‹ๆฉŸ่ƒฝใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ +Python ใซใฏใ€`Annotated` ใ‚’ไฝฟใฃใฆๅž‹ใƒ’ใƒณใƒˆใซ **่ฟฝๅŠ ใฎ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ** ใ‚’ไป˜ไธŽใงใใ‚‹ๆฉŸ่ƒฝใ‚‚ใ‚ใ‚Šใพใ™ใ€‚ -Python 3.9ไปฅ้™ใ€`Annotated`ใฏๆจ™ๆบ–ใƒฉใ‚คใƒ–ใƒฉใƒชใฎไธ€้ƒจใชใฎใงใ€`typing`ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™ใ€‚ +`Annotated` ใฏ `typing` ใ‹ใ‚‰ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™ใ€‚ -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} -Python่‡ชไฝ“ใฏใ€ใ“ใฎ`Annotated`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใพใŸใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ไป–ใฎใƒ„ใƒผใƒซใซใจใฃใฆใ‚‚ใ€ๅž‹ใฏไพ็„ถใจใ—ใฆ`str`ใงใ™ใ€‚ +Python ่‡ชไฝ“ใฏใ€ใ“ใฎ `Annotated` ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใพใŸใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ไป–ใฎใƒ„ใƒผใƒซใซใจใฃใฆใ‚‚ใ€ๅž‹ใฏไพ็„ถใจใ—ใฆ `str` ใงใ™ใ€‚ -ใ—ใ‹ใ—ใ€`Annotated`ๅ†…ใฎใ“ใฎใ‚นใƒšใƒผใ‚นใ‚’ไฝฟใฃใฆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใฉใฎใ‚ˆใ†ใซๅ‹•ไฝœใ•ใ›ใŸใ„ใ‹ใซใคใ„ใฆใฎ่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ **FastAPI** ใซๆไพ›ใงใใพใ™ใ€‚ +ใ—ใ‹ใ—ใ€`Annotated` ๅ†…ใฎใ“ใฎใ‚นใƒšใƒผใ‚นใ‚’ไฝฟใฃใฆใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ใฉใฎใ‚ˆใ†ใซๅ‹•ไฝœใ•ใ›ใŸใ„ใ‹ใซใคใ„ใฆใฎ่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ **FastAPI** ใซๆไพ›ใงใใพใ™ใ€‚ -่ฆšใˆใฆใŠใในใ้‡่ฆใช็‚นใฏใ€`Annotated`ใซๆธกใ™**ๆœ€ๅˆใฎ*ๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ***ใŒ**ๅฎŸ้š›ใฎๅž‹**ใงใ‚ใ‚‹ใ“ใจใงใ™ใ€‚ๆฎ‹ใ‚Šใฏใ€ไป–ใฎใƒ„ใƒผใƒซๅ‘ใ‘ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใซใ™ใŽใพใ›ใ‚“ใ€‚ +่ฆšใˆใฆใŠใในใ้‡่ฆใช็‚นใฏใ€`Annotated` ใซๆธกใ™ **ๆœ€ๅˆใฎใ€Œๅž‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€** ใŒ **ๅฎŸ้š›ใฎๅž‹** ใงใ‚ใ‚‹ใ“ใจใงใ™ใ€‚ๆฎ‹ใ‚Šใฏใ€ไป–ใฎใƒ„ใƒผใƒซๅ‘ใ‘ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใซใ™ใŽใพใ›ใ‚“ใ€‚ -ไปŠใฎใจใ“ใ‚ใฏใ€`Annotated`ใŒๅญ˜ๅœจใ—ใ€ใใ‚ŒใŒๆจ™ๆบ–ใฎPythonใงใ‚ใ‚‹ใ“ใจใ‚’็ŸฅใฃใฆใŠใ‘ใฐๅๅˆ†ใงใ™ใ€‚๐Ÿ˜Ž +ไปŠใฎใจใ“ใ‚ใฏใ€`Annotated` ใŒๅญ˜ๅœจใ—ใ€ใใ‚ŒใŒๆจ™ๆบ–ใฎ Python ใงใ‚ใ‚‹ใ“ใจใ‚’็ŸฅใฃใฆใŠใ‘ใฐๅๅˆ†ใงใ™ใ€‚๐Ÿ˜Ž -ๅพŒใงใ€ใ“ใ‚ŒใŒใฉใ‚Œใปใฉ**ๅผทๅŠ›**ใซใชใ‚Šๅพ—ใ‚‹ใ‹ใ‚’่ฆ‹ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ +ๅพŒใงใ€ใ“ใ‚ŒใŒใฉใ‚Œใปใฉ **ๅผทๅŠ›** ใซใชใ‚Šๅพ—ใ‚‹ใ‹ใ‚’่ฆ‹ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ -ใ“ใ‚ŒใŒ **ๆจ™ๆบ–ใฎPython** ใงใ‚ใ‚‹ใจใ„ใ†ไบ‹ๅฎŸใฏใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹ใƒ„ใƒผใƒซ๏ผˆใ‚ณใƒผใƒ‰ใฎ่งฃๆžใ‚„ใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐใชใฉ๏ผ‰ใจใจใ‚‚ใซใ€**ๅฏ่ƒฝใช้™ใ‚Šๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“**ใŒๅพ—ใ‚‰ใ‚Œใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ โœจ +ใ“ใ‚ŒใŒ **ๆจ™ๆบ–ใฎ Python** ใงใ‚ใ‚‹ใจใ„ใ†ไบ‹ๅฎŸใฏใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใงใ€ไฝฟ็”จใ—ใฆใ„ใ‚‹ใƒ„ใƒผใƒซ๏ผˆใ‚ณใƒผใƒ‰ใฎ่งฃๆžใ‚„ใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐใชใฉ๏ผ‰ใจใจใ‚‚ใซใ€**ๅฏ่ƒฝใช้™ใ‚Šๆœ€้ซ˜ใฎ้–‹็™บไฝ“้จ“** ใŒๅพ—ใ‚‰ใ‚Œใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ โœจ -ใพใŸใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใŒไป–ใฎๅคšใใฎPythonใƒ„ใƒผใƒซใ‚„ใƒฉใ‚คใƒ–ใƒฉใƒชใจใ‚‚้žๅธธใซไบ’ๆ›ๆ€งใŒ้ซ˜ใ„ใ“ใจใ‚‚ๆ„ๅ‘ณใ—ใพใ™ใ€‚ ๐Ÿš€ +ใพใŸใ€ใ‚ใชใŸใฎใ‚ณใƒผใƒ‰ใŒไป–ใฎๅคšใใฎ Python ใƒ„ใƒผใƒซใ‚„ใƒฉใ‚คใƒ–ใƒฉใƒชใจใ‚‚้žๅธธใซไบ’ๆ›ๆ€งใŒ้ซ˜ใ„ใ“ใจใ‚‚ๆ„ๅ‘ณใ—ใพใ™ใ€‚ ๐Ÿš€ /// -## **FastAPI**ใงใฎๅž‹ใƒ’ใƒณใƒˆ { #type-hints-in-fastapi } +## **FastAPI** ใงใฎๅž‹ใƒ’ใƒณใƒˆ { #type-hints-in-fastapi } **FastAPI** ใฏใ“ใ‚Œใ‚‰ใฎๅž‹ใƒ’ใƒณใƒˆใ‚’ๅˆฉ็”จใ—ใฆใ„ใใคใ‹ใฎใ“ใจใ‚’่กŒใ„ใพใ™ใ€‚ @@ -450,15 +334,15 @@ Python่‡ชไฝ“ใฏใ€ใ“ใฎ`Annotated`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ * **ใƒ‡ใƒผใ‚ฟใฎๅค‰ๆ›**: ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๅฟ…่ฆใชๅž‹ใซใƒ‡ใƒผใ‚ฟใ‚’ๅค‰ๆ›ใ—ใพใ™ใ€‚ * **ใƒ‡ใƒผใ‚ฟใฎๆคœ่จผ**: ๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ‹ใ‚‰ๆฅใ‚‹ใƒ‡ใƒผใ‚ฟใซใคใ„ใฆ: * ใƒ‡ใƒผใ‚ฟใŒ็„กๅŠนใชๅ ดๅˆใซใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ•ใ‚Œใ‚‹ **่‡ชๅ‹•ใ‚จใƒฉใƒผ** ใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ -* OpenAPIใ‚’ไฝฟ็”จใ—ใฆAPIใ‚’**ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–**ใ—ใพใ™: +* OpenAPI ใ‚’ไฝฟ็”จใ—ใฆ API ใ‚’ **ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–** ใ—ใพใ™: * ใ“ใ‚Œใฏ่‡ชๅ‹•ใฎๅฏพ่ฉฑๅž‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใ‚คใ‚นใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ -ใ™ในใฆใŒๆŠฝ่ฑก็š„ใซ่žใ“ใˆใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ ใ“ใฎๅ…จใฆใฎๅ‹•ไฝœใฏ [ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](tutorial/index.md){.internal-link target=_blank}ใง่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ +ใ™ในใฆใŒๆŠฝ่ฑก็š„ใซ่žใ“ใˆใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ๅฟƒ้…ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ ใ“ใฎๅ…จใฆใฎๅ‹•ไฝœใฏ [ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ - ใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰](tutorial/index.md){.internal-link target=_blank} ใง่ฆ‹ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -้‡่ฆใชใฎใฏใ€Pythonใฎๆจ™ๆบ–็š„ใชๅž‹ใ‚’ไฝฟใ†ใ“ใจใงใ€๏ผˆใ‚ฏใƒฉใ‚นใ‚„ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใชใฉใ‚’่ฟฝๅŠ ใ™ใ‚‹ใฎใงใฏใชใ๏ผ‰1ใคใฎๅ ดๆ‰€ใง **FastAPI** ใŒๅคšใใฎไฝœๆฅญใ‚’ไปฃใ‚ใ‚Šใซใ‚„ใฃใฆใใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ +้‡่ฆใชใฎใฏใ€Python ใฎๆจ™ๆบ–็š„ใชๅž‹ใ‚’ไฝฟใ†ใ“ใจใงใ€๏ผˆใ‚ฏใƒฉใ‚นใ‚„ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใชใฉใ‚’่ฟฝๅŠ ใ™ใ‚‹ใฎใงใฏใชใ๏ผ‰1 ใคใฎๅ ดๆ‰€ใง **FastAPI** ใŒๅคšใใฎไฝœๆฅญใ‚’ไปฃใ‚ใ‚Šใซใ‚„ใฃใฆใใ‚Œใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ /// info | ๆƒ…ๅ ฑ -ใ™ใงใซใ™ในใฆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’็ต‚ใˆใฆใ€ๅž‹ใซใคใ„ใฆใฎ่ฉณ็ดฐใ‚’่ฆ‹ใ‚‹ใŸใ‚ใซใ“ใฎใƒšใƒผใ‚ธใซๆˆปใฃใฆใใŸๅ ดๅˆใฏใ€่‰ฏใ„ใƒชใ‚ฝใƒผใ‚นใจใ—ใฆ`mypy`ใฎใ€Œใƒใƒผใƒˆใ‚ทใƒผใƒˆใ€ใŒใ‚ใ‚Šใพใ™ใ€‚ +ใ™ใงใซใ™ในใฆใฎใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใ‚’็ต‚ใˆใฆใ€ๅž‹ใซใคใ„ใฆใฎ่ฉณ็ดฐใ‚’่ฆ‹ใ‚‹ใŸใ‚ใซใ“ใฎใƒšใƒผใ‚ธใซๆˆปใฃใฆใใŸๅ ดๅˆใฏใ€่‰ฏใ„ใƒชใ‚ฝใƒผใ‚นใจใ—ใฆ `mypy` ใฎใ€Œใƒใƒผใƒˆใ‚ทใƒผใƒˆใ€ ใŒใ‚ใ‚Šใพใ™ใ€‚ /// diff --git a/docs/ja/docs/resources/index.md b/docs/ja/docs/resources/index.md new file mode 100644 index 0000000000..15a949e016 --- /dev/null +++ b/docs/ja/docs/resources/index.md @@ -0,0 +1,3 @@ +# ใƒชใ‚ฝใƒผใ‚น { #resources } + +่ฟฝๅŠ ใƒชใ‚ฝใƒผใ‚นใ€ๅค–้ƒจใƒชใƒณใ‚ฏใชใฉใ€‚โœˆ๏ธ diff --git a/docs/ja/docs/translation-banner.md b/docs/ja/docs/translation-banner.md new file mode 100644 index 0000000000..351a82a35a --- /dev/null +++ b/docs/ja/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ AI ใจไบบ้–“ใซใ‚ˆใ‚‹็ฟป่จณ + +ใ“ใฎ็ฟป่จณใฏใ€ไบบ้–“ใฎใ‚ฌใ‚คใƒ‰ใซๅŸบใฅใ„ใฆ AI ใซใ‚ˆใฃใฆไฝœๆˆใ•ใ‚Œใพใ—ใŸใ€‚๐Ÿค + +ๅŽŸๆ–‡ใฎๆ„ๅ›ณใ‚’ๅ–ใ‚Š้•ใˆใฆใ„ใŸใ‚Šใ€ไธ่‡ช็„ถใช่กจ็พใซใชใฃใฆใ„ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚๐Ÿค– + +[AI LLM ใ‚’ใ‚ˆใ‚Š้ฉๅˆ‡ใซ่ช˜ๅฐŽใ™ใ‚‹ใฎใ‚’ๆ‰‹ไผใ†](https://fastapi.tiangolo.com/ja/contributing/#translations) ใ“ใจใงใ€ใ“ใฎ็ฟป่จณใ‚’ๆ”นๅ–„ใงใใพใ™ใ€‚ + +[่‹ฑ่ชž็‰ˆ](ENGLISH_VERSION_URL) + +/// diff --git a/docs/ja/docs/tutorial/background-tasks.md b/docs/ja/docs/tutorial/background-tasks.md index 0ed41ce114..d32c141b5b 100644 --- a/docs/ja/docs/tutorial/background-tasks.md +++ b/docs/ja/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ ใพใšๅˆใ‚ใซใ€`BackgroundTasks` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€`BackgroundTasks` ใฎๅž‹ๅฎฃ่จ€ใจๅ…ฑใซใ€*path operation function* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใ‚’ๅฎš็พฉใ—ใพใ™: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** ใฏใ€`BackgroundTasks` ๅž‹ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ—ใ€ใใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซๆธกใ—ใพใ™ใ€‚ @@ -31,13 +31,13 @@ ใพใŸใ€ๆ›ธใ่พผใฟๆ“ไฝœใงใฏ `async` ใจ `await` ใ‚’ไฝฟ็”จใ—ใชใ„ใŸใ‚ใ€้€šๅธธใฎ `def` ใง้–ขๆ•ฐใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚ -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## ใƒใƒƒใ‚ฏใ‚ฐใƒฉใ‚ฆใƒณใƒ‰ใ‚ฟใ‚นใ‚ฏใฎ่ฟฝๅŠ  { #add-the-background-task } *path operation function* ๅ†…ใงใ€`.add_task()` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟ็”จใ—ใฆใ‚ฟใ‚นใ‚ฏ้–ขๆ•ฐใ‚’ *background tasks* ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใซๆธกใ—ใพใ™ใ€‚ -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` ใฏไปฅไธ‹ใฎๅผ•ๆ•ฐใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™: diff --git a/docs/ja/docs/tutorial/bigger-applications.md b/docs/ja/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..9c1cc0fe69 --- /dev/null +++ b/docs/ja/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# ๅคง่ฆๆจกใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ - ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซ { #bigger-applications-multiple-files } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚„ Web API ใ‚’ไฝœใ‚‹ๅ ดๅˆใ€ใ™ในใฆใ‚’1ใคใฎใƒ•ใ‚กใ‚คใƒซใซๅŽใ‚ใ‚‰ใ‚Œใ‚‹ใ“ใจใฏใปใจใ‚“ใฉใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +**FastAPI** ใฏใ€ๆŸ”่ปŸๆ€งใ‚’ไฟใฃใŸใพใพใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๆง‹้€ ๅŒ–ใงใใ‚‹ไพฟๅˆฉใชใƒ„ใƒผใƒซใ‚’ๆไพ›ใ—ใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +Flask ๅ‡บ่บซใงใ‚ใ‚Œใฐใ€Flask ใฎ Blueprint ใซ็›ธๅฝ“ใ—ใพใ™ใ€‚ + +/// + +## ไพ‹ใฎใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆ { #an-example-file-structure } + +ๆฌกใฎใ‚ˆใ†ใชใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใŒใ‚ใ‚‹ใจใ—ใพใ™: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +่ค‡ๆ•ฐใฎ `__init__.py` ใƒ•ใ‚กใ‚คใƒซใŒใ‚ใ‚Šใพใ™: ๅ„ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚„ใ‚ตใƒ–ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซ1ใคใšใคใงใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ใ‚‹ใƒ•ใ‚กใ‚คใƒซใ‹ใ‚‰ๅˆฅใฎใƒ•ใ‚กใ‚คใƒซใธใ‚ณใƒผใƒ‰ใ‚’ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`app/main.py` ใงใฏๆฌกใฎใ‚ˆใ†ใซๆ›ธใ‘ใพใ™: + +``` +from app.routers import items +``` + +/// + +* `app` ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใฏใ™ในใฆใ‚’ๅซใฟใพใ™ใ€‚ใใ—ใฆ็ฉบใฎใƒ•ใ‚กใ‚คใƒซ `app/__init__.py` ใŒใ‚ใ‚Šใ€ใ€ŒPython ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ€๏ผˆใ€ŒPython ใƒขใ‚ธใƒฅใƒผใƒซใ€ใฎ้›†ๅˆ๏ผ‰: `app` ใงใ™ใ€‚ +* `app/main.py` ใƒ•ใ‚กใ‚คใƒซใŒใ‚ใ‚Šใพใ™ใ€‚Python ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆ`__init__.py` ใฎใ‚ใ‚‹ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช๏ผ‰ใฎไธญใซใ‚ใ‚‹ใŸใ‚ใ€ใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใ€Œใƒขใ‚ธใƒฅใƒผใƒซใ€: `app.main` ใงใ™ใ€‚ +* `app/dependencies.py` ใƒ•ใ‚กใ‚คใƒซใ‚‚ใ‚ใ‚Šใ€`app/main.py` ใจๅŒๆง˜ใซใ€Œใƒขใ‚ธใƒฅใƒผใƒซใ€: `app.dependencies` ใงใ™ใ€‚ +* `app/routers/` ใ‚ตใƒ–ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซๅˆฅใฎ `__init__.py` ใŒใ‚ใ‚‹ใฎใงใ€ใ€ŒPython ใ‚ตใƒ–ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ€: `app.routers` ใงใ™ใ€‚ +* `app/routers/items.py` ใฏใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ `app/routers/` ๅ†…ใฎใƒ•ใ‚กใ‚คใƒซใชใฎใงใ€ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ: `app.routers.items` ใงใ™ใ€‚ +* `app/routers/users.py` ใ‚‚ๅŒๆง˜ใงใ€ๅˆฅใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ: `app.routers.users` ใงใ™ใ€‚ +* `app/internal/` ใ‚ตใƒ–ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใซใ‚‚ `__init__.py` ใŒใ‚ใ‚‹ใฎใงใ€ๅˆฅใฎใ€ŒPython ใ‚ตใƒ–ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ€: `app.internal` ใงใ™ใ€‚ +* `app/internal/admin.py` ใฏๅˆฅใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ: `app.internal.admin` ใงใ™ใ€‚ + + + +ๅŒใ˜ใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใซใ‚ณใƒกใƒณใƒˆใ‚’ไป˜ใ‘ใ‚‹ใจๆฌกใฎใจใŠใ‚Šใงใ™: + +```bash +. +โ”œโ”€โ”€ app # "app" is a Python package +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # this file makes "app" a "Python package" +โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module, e.g. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module, e.g. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" is a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # makes "routers" a "Python subpackage" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule, e.g. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule, e.g. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" is a "Python subpackage" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # makes "internal" a "Python subpackage" +โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule, e.g. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +ใƒฆใƒผใ‚ถใƒผใ ใ‘ใ‚’ๆ‰ฑใ†ใƒ•ใ‚กใ‚คใƒซใŒ `/app/routers/users.py` ใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใ ใจใ—ใพใ™ใ€‚ + +ใƒฆใƒผใ‚ถใƒผใซ้–ข้€ฃใ™ใ‚‹ *path operations* ใ‚’ใปใ‹ใฎใ‚ณใƒผใƒ‰ใ‹ใ‚‰ๅˆ†้›ขใ—ใฆๆ•ด็†ใ—ใŸใ„ใฏใšใงใ™ใ€‚ + +ใŸใ ใ—ใ€ๅŒใ˜ **FastAPI** ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณ / Web API๏ผˆๅŒใ˜ใ€ŒPython ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ€ใฎไธ€้ƒจ๏ผ‰ใงใ‚ใ‚‹็‚นใฏๅค‰ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใใฎใƒขใ‚ธใƒฅใƒผใƒซใง `APIRouter` ใ‚’ไฝฟใฃใฆ *path operations* ใ‚’ไฝœๆˆใงใใพใ™ใ€‚ + +### `APIRouter` ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-apirouter } + +ใ‚ฏใƒฉใ‚น `FastAPI` ใจๅŒๆง˜ใซใ‚คใƒณใƒใƒผใƒˆใ—ใ€ใ€Œใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ€ใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### `APIRouter` ใงใฎ *path operations* { #path-operations-with-apirouter } + +ใ“ใ‚Œใ‚’ไฝฟใฃใฆ *path operations* ใ‚’ๅฎฃ่จ€ใ—ใพใ™ใ€‚ + +ไฝฟใ„ๆ–นใฏ `FastAPI` ใ‚ฏใƒฉใ‚นใจๅŒใ˜ใงใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +`APIRouter` ใฏใ€ŒใƒŸใƒ‹ `FastAPI`ใ€ใฎใ‚ˆใ†ใชใ‚ฏใƒฉใ‚นใจ่€ƒใˆใ‚‰ใ‚Œใพใ™ใ€‚ + +ๅŒใ˜ใ‚ชใƒ—ใ‚ทใƒงใƒณใŒใ™ในใฆใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +ๅŒใ˜ `parameters`ใ€`responses`ใ€`dependencies`ใ€`tags` ใชใฉใŒไฝฟใˆใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎไพ‹ใงใฏๅค‰ๆ•ฐๅใฏ `router` ใงใ™ใŒใ€ไปปๆ„ใฎๅๅ‰ใ‚’ไป˜ใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ + +/// + +ใ“ใฎ `APIRouter` ใ‚’ใƒกใ‚คใƒณใฎ `FastAPI` ใ‚ขใƒ—ใƒชใซๅ–ใ‚Š่พผใฟใพใ™ใŒใ€ใใฎๅ‰ใซไพๅญ˜้–ขไฟ‚ใจๅˆฅใฎ `APIRouter` ใ‚’็ขบ่ชใ—ใพใ™ใ€‚ + +## ไพๅญ˜้–ขไฟ‚ { #dependencies } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่ค‡ๆ•ฐ็ฎ‡ๆ‰€ใงไฝฟใ†ไพๅญ˜้–ขไฟ‚ใŒๅฟ…่ฆใซใชใ‚Šใพใ™ใ€‚ + +ใใฎใŸใ‚ใ€ๅฐ‚็”จใฎ `dependencies` ใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆ`app/dependencies.py`๏ผ‰ใซ็ฝฎใใพใ™ใ€‚ + +ใ“ใ“ใงใฏใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผ `X-Token` ใ‚’่ชญใ‚€็ฐกๅ˜ใชไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ„ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎไพ‹ใ‚’็ฐกๅ˜ใซใ™ใ‚‹ใŸใ‚ใซๆžถ็ฉบใฎใƒ˜ใƒƒใƒ€ใƒผใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ + +ใ—ใ‹ใ—ๅฎŸ้š›ใซใฏใ€็ต„ใฟ่พผใฟใฎ [Security utilities](security/index.md){.internal-link target=_blank} ใ‚’ไฝฟใ†ๆ–นใŒ่‰ฏใ„็ตๆžœใซใชใ‚Šใพใ™ใ€‚ + +/// + +## ๅˆฅใƒขใ‚ธใƒฅใƒผใƒซใงใฎ `APIRouter` { #another-module-with-apirouter } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ€Œitemsใ€ใ‚’ๆ‰ฑใ†ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใŒ `app/routers/items.py` ใฎใƒขใ‚ธใƒฅใƒผใƒซใซใ‚ใ‚‹ใจใ—ใพใ™ใ€‚ + +ๆฌกใฎ *path operations* ใŒใ‚ใ‚Šใพใ™: + +* `/items/` +* `/items/{item_id}` + +ๆง‹้€ ใฏ `app/routers/users.py` ใจๅŒใ˜ใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใ‚‚ใ†ๅฐ‘ใ—่ณขใใ—ใฆใ‚ณใƒผใƒ‰ใ‚’ๅฐ‘ใ—็ฐกๆฝ”ใซใ—ใŸใ„ใจใ“ใ‚ใงใ™ใ€‚ + +ใ“ใฎใƒขใ‚ธใƒฅใƒผใƒซใฎใ™ในใฆใฎ *path operations* ใซใฏๅŒใ˜ใ‚‚ใฎใŒใ‚ใ‚‹ใจๅˆ†ใ‹ใฃใฆใ„ใพใ™: + +* ใƒ‘ใ‚นใฎ `prefix`: `/items` +* `tags`๏ผˆ1ใคใฎใ‚ฟใ‚ฐ: `items`๏ผ‰ +* ่ฟฝๅŠ ใฎ `responses` +* `dependencies`: ๅ…ˆใปใฉไฝœๆˆใ—ใŸ `X-Token` ใฎไพๅญ˜้–ขไฟ‚ใŒๅฟ…่ฆ + +ใใ“ใงใ€ๅ„ *path operation* ใซๅ€‹ๅˆฅใซ่ฟฝๅŠ ใ™ใ‚‹ไปฃใ‚ใ‚Šใซใ€ใ“ใ‚Œใ‚‰ใ‚’ `APIRouter` ใซ่ฟฝๅŠ ใงใใพใ™ใ€‚ + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +ๅ„ *path operation* ใฎใƒ‘ใ‚นใฏๆฌกใฎใ‚ˆใ†ใซ `/` ใงๅง‹ใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŸใ‚: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...prefix ใฎๆœซๅฐพใซ `/` ใ‚’ๅซใ‚ใฆใฏใ„ใ‘ใพใ›ใ‚“ใ€‚ + +ใ“ใฎๅ ดๅˆใฎ prefix ใฏ `/items` ใงใ™ใ€‚ + +ใพใŸใ€`tags` ใฎใƒชใ‚นใƒˆใ‚„่ฟฝๅŠ ใฎ `responses` ใ‚’ใ€ใ“ใฎใƒซใƒผใ‚ฟใƒผใซๅซใพใ‚Œใ‚‹ใ™ในใฆใฎ *path operations* ใซ้ฉ็”จใ™ใ‚‹ใ‚ˆใ†่ฟฝๅŠ ใงใใพใ™ใ€‚ + +ใ•ใ‚‰ใซ `dependencies` ใฎใƒชใ‚นใƒˆใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚ใ“ใ‚Œใฏใ“ใฎใƒซใƒผใ‚ฟใƒผๅ†…ใฎใ™ในใฆใฎ *path operations* ใซ่ฟฝๅŠ ใ•ใ‚Œใ€ใใ‚Œใ‚‰ใธใฎๅ„ใƒชใ‚ฏใ‚จใ‚นใƒˆใ”ใจใซๅฎŸ่กŒใƒป่งฃๆฑบใ•ใ‚Œใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +[*path operation ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟ*ใฎไพๅญ˜้–ขไฟ‚](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ใจๅŒๆง˜ใซใ€*path operation ้–ขๆ•ฐ*ใซใฏๅ€คใฏๆธกใ•ใ‚Œใชใ„็‚นใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +ๆœ€็ต‚็š„ใซใ€item ใฎใƒ‘ใ‚นใฏๆฌกใฎใจใŠใ‚Šใซใชใ‚Šใพใ™: + +* `/items/` +* `/items/{item_id}` + +...ๆ„ๅ›ณใ—ใŸใจใŠใ‚Šใงใ™ใ€‚ + +* ใ“ใ‚Œใ‚‰ใซใฏใ€ๆ–‡ๅญ—ๅˆ— `"items"` ใ‚’1ใคๅซใ‚€ใ‚ฟใ‚ฐใฎใƒชใ‚นใƒˆใŒไป˜ใใพใ™ใ€‚ + * ใ“ใ‚Œใ‚‰ใฎใ€Œใ‚ฟใ‚ฐใ€ใฏใ€๏ผˆOpenAPI ใ‚’ไฝฟใ†๏ผ‰่‡ชๅ‹•ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง็‰นใซๆœ‰็”จใงใ™ใ€‚ +* ใ™ในใฆใซไบ‹ๅ‰ๅฎš็พฉใ—ใŸ `responses` ใŒๅซใพใ‚Œใพใ™ใ€‚ +* ใ“ใ‚Œใ‚‰ใ™ในใฆใฎ *path operations* ใงใฏใ€ๅฎŸ่กŒๅ‰ใซ `dependencies` ใฎใƒชใ‚นใƒˆใŒ่ฉ•ไพกใƒปๅฎŸ่กŒใ•ใ‚Œใพใ™ใ€‚ + * ็‰นๅฎšใฎ *path operation* ใซไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใ—ใŸๅ ดๅˆใฏใ€**ใใ‚Œใ‚‰ใ‚‚ๅฎŸ่กŒใ•ใ‚Œใพใ™**ใ€‚ + * ใƒซใƒผใ‚ฟใƒผใฎไพๅญ˜้–ขไฟ‚ใŒๅ…ˆใซๅฎŸ่กŒใ•ใ‚Œใ€ใใฎๅพŒใซ[ใƒ‡ใ‚ณใƒฌใƒผใ‚ฟๅ†…ใฎ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}ใ€ๆฌกใซ้€šๅธธใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟไพๅญ˜้–ขไฟ‚ใŒ็ถšใใพใ™ใ€‚ + * [`scopes` ใ‚’ไผดใ† `Security` ไพๅญ˜้–ขไฟ‚](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} ใ‚’่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +`APIRouter` ใซ `dependencies` ใ‚’็ฝฎใใ“ใจใงใ€*path operations* ใฎใ‚ฐใƒซใƒผใƒ—ๅ…จไฝ“ใซ่ช่จผใ‚’่ฆๆฑ‚ใ™ใ‚‹ใ€ใจใ„ใฃใŸ็”จ้€”ใซไฝฟใˆใพใ™ใ€‚ๅ€‹ใ€…ใฎ *path operation* ใซไพๅญ˜้–ขไฟ‚ใ‚’่ฟฝๅŠ ใ—ใฆใ„ใชใใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +/// + +/// check | ็ขบ่ช + +`prefix`ใ€`tags`ใ€`responses`ใ€`dependencies` ใฎๅ„ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ๏ผˆใปใ‹ใฎๅคšใใฎใ‚ฑใƒผใ‚นใจๅŒๆง˜ใซ๏ผ‰ใ‚ณใƒผใƒ‰้‡่ค‡ใ‚’้ฟใ‘ใ‚‹ใŸใ‚ใฎ **FastAPI** ใฎๆฉŸ่ƒฝใงใ™ใ€‚ + +/// + +### ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #import-the-dependencies } + +ใ“ใฎใ‚ณใƒผใƒ‰ใฏใƒขใ‚ธใƒฅใƒผใƒซ `app.routers.items`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/routers/items.py`๏ผ‰ๅ†…ใซใ‚ใ‚Šใพใ™ใ€‚ + +ใใ—ใฆไพๅญ˜้–ขไฟ‚ใฎ้–ขๆ•ฐใฏใƒขใ‚ธใƒฅใƒผใƒซ `app.dependencies`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/dependencies.py`๏ผ‰ใ‹ใ‚‰ๅ–ๅพ—ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใใ“ใงใ€ไพๅญ˜้–ขไฟ‚ใซใฏ `..` ใ‚’ไฝฟใฃใŸ็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ‚’ไฝฟใ„ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### ็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใฎไป•็ต„ใฟ { #how-relative-imports-work } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ‚คใƒณใƒใƒผใƒˆใฎไป•็ต„ใฟใ‚’ๅๅˆ†็†่งฃใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎ็ฏ€ใซ้€ฒใ‚“ใงใใ ใ•ใ„ใ€‚ + +/// + +ใƒ‰ใƒƒใƒˆ1ใค `.` ใ‚’ไฝฟใ†ใจใ€ๆฌกใฎใ‚ˆใ†ใชๆ„ๅ‘ณใซใชใ‚Šใพใ™: + +```Python +from .dependencies import get_token_header +``` + +ๆ„ๅ‘ณ: + +* ใ“ใฎใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆ`app/routers/items.py`๏ผ‰ใŒๅญ˜ๅœจใ™ใ‚‹ๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/routers/`๏ผ‰ใ‹ใ‚‰้–‹ๅง‹ใ—... +* ใƒขใ‚ธใƒฅใƒผใƒซ `dependencies`๏ผˆไปฎๆƒณ็š„ใซใฏ `app/routers/dependencies.py`๏ผ‰ใ‚’ๆŽขใ—... +* ใใ“ใ‹ใ‚‰้–ขๆ•ฐ `get_token_header` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ€‚ + +ใ—ใ‹ใ—ใใฎใƒ•ใ‚กใ‚คใƒซใฏๅญ˜ๅœจใ›ใšใ€ๅฎŸ้š›ใฎไพๅญ˜้–ขไฟ‚ใฏ `app/dependencies.py` ใซใ‚ใ‚Šใพใ™ใ€‚ + +ใ‚ขใƒ—ใƒช๏ผใƒ•ใ‚กใ‚คใƒซๆง‹ๆˆใŒใฉใ†ใชใฃใฆใ„ใŸใ‹ใ‚’ๆ€ใ„ๅ‡บใ—ใฆใใ ใ•ใ„: + + + +--- + +ใƒ‰ใƒƒใƒˆ2ใค `..` ใ‚’ไฝฟใ†ใจใ€ๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +```Python +from ..dependencies import get_token_header +``` + +ๆ„ๅ‘ณ: + +* ใ“ใฎใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆ`app/routers/items.py`๏ผ‰ใŒๅญ˜ๅœจใ™ใ‚‹ๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/routers/`๏ผ‰ใ‹ใ‚‰้–‹ๅง‹ใ—... +* ่ฆชใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/`๏ผ‰ใซ็งปๅ‹•ใ—... +* ใใ“ใงใƒขใ‚ธใƒฅใƒผใƒซ `dependencies`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/dependencies.py`๏ผ‰ใ‚’ๆŽขใ—... +* ใใ“ใ‹ใ‚‰้–ขๆ•ฐ `get_token_header` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ€‚ + +ใ“ใ‚Œใฏๆญฃใ—ใๅ‹•ไฝœใ—ใพใ™๏ผ ๐ŸŽ‰ + +--- + +ๅŒๆง˜ใซใ€ใƒ‰ใƒƒใƒˆ3ใค `...` ใ‚’ไฝฟใ†ใจ: + +```Python +from ...dependencies import get_token_header +``` + +ๆ„ๅ‘ณ: + +* ใ“ใฎใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆ`app/routers/items.py`๏ผ‰ใŒๅญ˜ๅœจใ™ใ‚‹ๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/routers/`๏ผ‰ใ‹ใ‚‰้–‹ๅง‹ใ—... +* ่ฆชใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/`๏ผ‰ใซ็งปๅ‹•ใ—... +* ใ•ใ‚‰ใซใใฎ่ฆชใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใซ็งปๅ‹•ใ—ใ‚ˆใ†ใจใ—ใพใ™๏ผˆ`app` ใฏๆœ€ไธŠไฝใชใฎใง่ฆชใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏใ‚ใ‚Šใพใ›ใ‚“ ๐Ÿ˜ฑ๏ผ‰... +* ใใ“ใงใƒขใ‚ธใƒฅใƒผใƒซ `dependencies`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/dependencies.py`๏ผ‰ใ‚’ๆŽขใ—... +* ใใ“ใ‹ใ‚‰้–ขๆ•ฐ `get_token_header` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ€‚ + +ใ“ใ‚Œใฏ `app/` ใ‚ˆใ‚ŠไธŠไฝใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆ็‹ฌ่‡ชใฎ `__init__.py` ใ‚’ๆŒใค๏ผ‰ใ‚’ๅ‚็…งใ™ใ‚‹ใ“ใจใซใชใ‚Šใพใ™ใ€‚ใ—ใ‹ใ—ใใฎใ‚ˆใ†ใชใ‚‚ใฎใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใใฎใŸใ‚ใ€ใ“ใฎไพ‹ใงใฏใ‚จใƒฉใƒผใซใชใ‚Šใพใ™ใ€‚๐Ÿšจ + +ใ“ใ‚Œใงไป•็ต„ใฟใŒๅˆ†ใ‹ใฃใŸใฎใงใ€ใฉใ‚Œใปใฉ่ค‡้›‘ใงใ‚‚่‡ชๅˆ†ใฎใ‚ขใƒ—ใƒชใง็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ‚’ไฝฟใˆใพใ™ใ€‚๐Ÿค“ + +### ใ‚ซใ‚นใ‚ฟใƒ ใฎ `tags`ใ€`responses`ใ€`dependencies` ใ‚’่ฟฝๅŠ  { #add-some-custom-tags-responses-and-dependencies } + +`APIRouter` ใซ่ฟฝๅŠ ๆธˆใฟใชใฎใงใ€ๅ„ *path operation* ใซ `/items` ใฎ prefix ใ‚„ `tags=["items"]` ใ‚’ไป˜ใ‘ใฆใ„ใพใ›ใ‚“ใ€‚ + +ใ—ใ‹ใ—ใ€็‰นๅฎšใฎ *path operation* ใซ้ฉ็”จใ•ใ‚Œใ‚‹ _่ฟฝๅŠ ใฎ_ `tags` ใ‚„ใ€ใใฎ *path operation* ๅ›บๆœ‰ใฎ่ฟฝๅŠ ใฎ `responses` ใ‚’ๅŠ ใˆใ‚‹ใ“ใจใฏใงใใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใฎๆœ€ๅพŒใฎ *path operation* ใฏใ€`["items", "custom"]` ใฎใ‚ฟใ‚ฐใฎ็ต„ใฟๅˆใ‚ใ›ใ‚’ๆŒใกใพใ™ใ€‚ + +ใพใŸใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏ `404` ใจ `403` ใฎไธกๆ–นใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +/// + +## ใƒกใ‚คใƒณใฎ `FastAPI` { #the-main-fastapi } + +ๆฌกใซใ€`app/main.py` ใฎใƒขใ‚ธใƒฅใƒผใƒซใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +ใ“ใ“ใงใ‚ฏใƒฉใ‚น `FastAPI` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝฟ็”จใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ™ในใฆใ‚’ใพใจใ‚ใ‚‹ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใƒกใ‚คใƒณใƒ•ใ‚กใ‚คใƒซใซใชใ‚Šใพใ™ใ€‚ + +ใใ—ใฆๅคง้ƒจๅˆ†ใฎใƒญใ‚ธใƒƒใ‚ฏใฏใใ‚Œใžใ‚Œใฎๅฐ‚็”จใƒขใ‚ธใƒฅใƒผใƒซใซ็ฝฎใ‹ใ‚Œใ‚‹ใŸใ‚ใ€ใƒกใ‚คใƒณใƒ•ใ‚กใ‚คใƒซใฏใ‹ใชใ‚Šใ‚ทใƒณใƒ—ใƒซใซใชใ‚Šใพใ™ใ€‚ + +### `FastAPI` ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-fastapi } + +้€šๅธธใฉใŠใ‚Š `FastAPI` ใ‚ฏใƒฉใ‚นใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆไฝœๆˆใ—ใพใ™ใ€‚ + +ใ•ใ‚‰ใซใ€ๅ„ `APIRouter` ใฎไพๅญ˜้–ขไฟ‚ใจ็ต„ใฟๅˆใ‚ใ•ใ‚Œใ‚‹[ใ‚ฐใƒญใƒผใƒใƒซไพๅญ˜้–ขไฟ‚](dependencies/global-dependencies.md){.internal-link target=_blank}ใ‚‚ๅฎฃ่จ€ใงใใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### `APIRouter` ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-the-apirouter } + +ๆฌกใซใ€`APIRouter` ใ‚’ๆŒใคไป–ใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +`app/routers/users.py` ใจ `app/routers/items.py` ใฏๅŒใ˜ Python ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ `app` ใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใชใฎใงใ€1ใคใฎใƒ‰ใƒƒใƒˆ `.` ใ‚’ไฝฟใฃใŸใ€Œ็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ€ใงใ‚คใƒณใƒใƒผใƒˆใงใใพใ™ใ€‚ + +### ใ‚คใƒณใƒใƒผใƒˆใฎๅ‹•ไฝœ { #how-the-importing-works } + +ๆฌกใฎ้ƒจๅˆ†: + +```Python +from .routers import items, users +``` + +ใฏๆฌกใฎๆ„ๅ‘ณใงใ™: + +* ใ“ใฎใƒขใ‚ธใƒฅใƒผใƒซ๏ผˆ`app/main.py`๏ผ‰ใŒๅญ˜ๅœจใ™ใ‚‹ๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/`๏ผ‰ใ‹ใ‚‰้–‹ๅง‹ใ—... +* ใ‚ตใƒ–ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ `routers`๏ผˆใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒช `app/routers/`๏ผ‰ใ‚’ๆŽขใ—... +* ใใ“ใ‹ใ‚‰ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ `items`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/routers/items.py`๏ผ‰ใจ `users`๏ผˆใƒ•ใ‚กใ‚คใƒซ `app/routers/users.py`๏ผ‰ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹... + +ใƒขใ‚ธใƒฅใƒผใƒซ `items` ใซใฏๅค‰ๆ•ฐ `router`๏ผˆ`items.router`๏ผ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏ `app/routers/items.py` ใงไฝœๆˆใ—ใŸ `APIRouter` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใจๅŒใ˜ใ‚‚ใฎใงใ™ใ€‚ + +ใƒขใ‚ธใƒฅใƒผใƒซ `users` ใซใคใ„ใฆใ‚‚ๅŒๆง˜ใงใ™ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใซใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™: + +```Python +from app.routers import items, users +``` + +/// info | ๆƒ…ๅ ฑ + +ๆœ€ๅˆใฎใƒใƒผใ‚ธใƒงใƒณใฏใ€Œ็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ€ใงใ™: + +```Python +from .routers import items, users +``` + +2ใค็›ฎใฎใƒใƒผใ‚ธใƒงใƒณใฏใ€Œ็ตถๅฏพใ‚คใƒณใƒใƒผใƒˆใ€ใงใ™: + +```Python +from app.routers import items, users +``` + +Python ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใจใƒขใ‚ธใƒฅใƒผใƒซใซใคใ„ใฆ่ฉณใ—ใใฏใ€ๅ…ฌๅผใฎ Python ใƒขใ‚ธใƒฅใƒผใƒซใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ + +/// + +### ๅๅ‰่ก็ชใฎๅ›ž้ฟ { #avoid-name-collisions } + +ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ `items` ใฎๅค‰ๆ•ฐ `router` ใ ใ‘ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใฎใงใฏใชใใ€ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ่‡ชไฝ“ใ‚’็›ดๆŽฅใ‚คใƒณใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ€ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ `users` ใซใ‚‚ `router` ใจใ„ใ†ๅค‰ๆ•ฐใŒใ‚ใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใ‚‚ใ—ๆฌกใฎใ‚ˆใ†ใซ็ถšใ‘ใฆใ‚คใƒณใƒใƒผใƒˆใ—ใŸๅ ดๅˆ: + +```Python +from .routers.items import router +from .routers.users import router +``` + +`users` ใฎ `router` ใŒ `items` ใฎใ‚‚ใฎใ‚’ไธŠๆ›ธใใ—ใฆใ—ใพใ„ใ€ๅŒๆ™‚ใซไธกๆ–นใ‚’ไฝฟใˆใชใใชใ‚Šใพใ™ใ€‚ + +ๅŒใ˜ใƒ•ใ‚กใ‚คใƒซใงไธกๆ–นใ‚’ไฝฟใˆใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใŸใ‚ใ€ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซใ‚’็›ดๆŽฅใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### `users` ใจ `items` ใฎ `APIRouter` ใ‚’ๅ–ใ‚Š่พผใ‚€ { #include-the-apirouters-for-users-and-items } + +ใงใฏใ€ใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ `users` ใจ `items` ใ‹ใ‚‰ `router` ใ‚’ๅ–ใ‚Š่พผใฟใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// info | ๆƒ…ๅ ฑ + +`users.router` ใฏใ€ใƒ•ใ‚กใ‚คใƒซ `app/routers/users.py` ๅ†…ใฎ `APIRouter` ใ‚’ๅซใฟใพใ™ใ€‚ + +`items.router` ใฏใ€ใƒ•ใ‚กใ‚คใƒซ `app/routers/items.py` ๅ†…ใฎ `APIRouter` ใ‚’ๅซใฟใพใ™ใ€‚ + +/// + +`app.include_router()` ใ‚’ไฝฟใฃใฆใ€ๅ„ `APIRouter` ใ‚’ใƒกใ‚คใƒณใฎ `FastAPI` ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซ่ฟฝๅŠ ใงใใพใ™ใ€‚ + +ใใฎใƒซใƒผใ‚ฟใƒผใฎใ™ในใฆใฎใƒซใƒผใƒˆใŒใ‚ขใƒ—ใƒชใซๅซใพใ‚Œใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ๅฎŸ้š›ใซใฏใ€`APIRouter` ใงๅฎฃ่จ€ใ•ใ‚ŒใŸๅ„ *path operation* ใ”ใจใซๅ†…้ƒจ็š„ใซ *path operation* ใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ + +ใคใพใ‚Š่ฃๅดใงใฏใ€ใ™ในใฆใŒๅŒใ˜ๅ˜ไธ€ใฎใ‚ขใƒ—ใƒชใงใ‚ใ‚‹ใ‹ใฎใ‚ˆใ†ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ + +/// + +/// check | ็ขบ่ช + +ใƒซใƒผใ‚ฟใƒผใ‚’ๅ–ใ‚Š่พผใ‚“ใงใ‚‚ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใ‚’ๅฟƒ้…ใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใฏ่ตทๅ‹•ๆ™‚ใซใƒžใ‚คใ‚ฏใƒญ็ง’ใง่กŒใ‚ใ‚Œใพใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใซใฏๅฝฑ้Ÿฟใ—ใพใ›ใ‚“ใ€‚โšก + +/// + +### ใ‚ซใ‚นใ‚ฟใƒ ใฎ `prefix`ใ€`tags`ใ€`responses`ใ€`dependencies` ไป˜ใใง `APIRouter` ใ‚’ๅ–ใ‚Š่พผใ‚€ { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +ใ‚ใชใŸใฎ็ต„็น”ใ‹ใ‚‰ `app/internal/admin.py` ใƒ•ใ‚กใ‚คใƒซใŒๆไพ›ใ•ใ‚ŒใŸใจใ—ใพใ—ใ‚‡ใ†ใ€‚ + +ใใ“ใซใฏใ€็ต„็น”ใŒ่ค‡ๆ•ฐใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงๅ…ฑๆœ‰ใ—ใฆใ„ใ‚‹็ฎก็†็”จใฎ *path operations* ใ‚’ๆŒใค `APIRouter` ใŒๅซใพใ‚Œใฆใ„ใพใ™ใ€‚ + +ใ“ใฎไพ‹ใงใฏใจใฆใ‚‚ใ‚ทใƒณใƒ—ใƒซใงใ™ใŒใ€็ต„็น”ๅ†…ใฎไป–ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใจๅ…ฑๆœ‰ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€`APIRouter` ่‡ชไฝ“ใ‚’็›ดๆŽฅๅค‰ๆ›ดใ—ใฆ `prefix`ใ€`dependencies`ใ€`tags` ใชใฉใ‚’่ฟฝๅŠ ใงใใชใ„ใจใ—ใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +ใใ‚Œใงใ‚‚ใ€`APIRouter` ใ‚’ๅ–ใ‚Š่พผใ‚€้š›ใซใ‚ซใ‚นใ‚ฟใƒ ใฎ `prefix` ใ‚’่จญๅฎšใ—ใฆใ™ในใฆใฎ *path operations* ใ‚’ `/admin` ใงๅง‹ใ‚ใŸใ„ใ€ๆ—ขๅญ˜ใฎ `dependencies` ใงไฟ่ญทใ—ใŸใ„ใ€ใ•ใ‚‰ใซ `tags` ใจ `responses` ใ‚‚ๅซใ‚ใŸใ„ใจใ—ใพใ™ใ€‚ + +ๅ…ƒใฎ `APIRouter` ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใชใใ€`app.include_router()` ใซใ“ใ‚Œใ‚‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ™ใ“ใจใงๅฎฃ่จ€ใงใใพใ™: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +ใ“ใฎใ‚ˆใ†ใซใ™ใ‚‹ใจใ€ๅ…ƒใฎ `APIRouter` ใฏๆœชๅค‰ๆ›ดใฎใพใพใชใฎใงใ€ๅŒใ˜ `app/internal/admin.py` ใƒ•ใ‚กใ‚คใƒซใ‚’็ต„็น”ๅ†…ใฎไป–ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใจใ‚‚ๅผ•ใ็ถšใๅ…ฑๆœ‰ใงใใพใ™ใ€‚ + +็ตๆžœใจใ—ใฆใ€ใ“ใฎใ‚ขใƒ—ใƒชๅ†…ใงใฏ `admin` ใƒขใ‚ธใƒฅใƒผใƒซใฎๅ„ *path operation* ใŒๆฌกใฎใ‚ˆใ†ใซใชใ‚Šใพใ™: + +* prefix ใฏ `/admin` +* ใ‚ฟใ‚ฐใฏ `admin` +* ไพๅญ˜้–ขไฟ‚ใฏ `get_token_header` +* ใƒฌใ‚นใƒใƒณใ‚นใฏ `418` ๐Ÿต + +ใŸใ ใ—ใ€ใ“ใ‚Œใฏใ“ใฎใ‚ขใƒ—ใƒชๅ†…ใฎใใฎ `APIRouter` ใซใฎใฟๅฝฑ้Ÿฟใ—ใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ไป–ใฎใ‚ณใƒผใƒ‰ใซใฏๅฝฑ้Ÿฟใ—ใพใ›ใ‚“ใ€‚ + +ไพ‹ใˆใฐใ€ไป–ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฏๅŒใ˜ `APIRouter` ใ‚’ๅˆฅใฎ่ช่จผๆ–นๅผใงไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +### *path operation* ใ‚’่ฟฝๅŠ  { #include-a-path-operation } + +`FastAPI` ใ‚ขใƒ—ใƒชใซ *path operations* ใ‚’็›ดๆŽฅ่ฟฝๅŠ ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใ“ใ“ใงใฏ๏ผˆใงใใ‚‹ใ“ใจใ‚’็คบใ™ใŸใ‚ใ ใ‘ใซ๏ผ‰่ฟฝๅŠ ใ—ใพใ™ ๐Ÿคท: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +ใใ—ใฆใ€`app.include_router()` ใง่ฟฝๅŠ ใ—ใŸใปใ‹ใฎ *path operations* ใจไธ€็ท’ใซๆญฃใ—ใๅ‹•ไฝœใ—ใพใ™ใ€‚ + +/// info | ้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐ + +ๆณจ่จ˜: ใ“ใ‚Œใฏ้žๅธธใซๆŠ€่ก“็š„ใช่ฉณ็ดฐใงใ€**่ชญใฟ้ฃ›ใฐใ—ใฆๆง‹ใ„ใพใ›ใ‚“**ใ€‚ + +--- + +`APIRouter` ใฏใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ•ใ‚ŒใฆใŠใ‚‰ใšใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎไป–้ƒจๅˆ†ใ‹ใ‚‰ๅˆ†้›ขใ•ใ‚Œใฆใ„ใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใฏใ€ใใ‚Œใ‚‰ใฎ *path operations* ใ‚’ OpenAPI ใ‚นใ‚ญใƒผใƒžใ‚„ใƒฆใƒผใ‚ถใƒผใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใซๅซใ‚ใŸใ„ใ‹ใ‚‰ใงใ™ใ€‚ + +ๅฎŒๅ…จใซๅˆ†้›ขใ—ใฆ็‹ฌ็ซ‹ใซใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใงใใชใ„ใŸใ‚ใ€*path operations* ใฏ็›ดๆŽฅๅ–ใ‚Š่พผใพใ‚Œใ‚‹ใฎใงใฏใชใใ€Œใ‚ฏใƒญใƒผใƒณ๏ผˆๅ†ไฝœๆˆ๏ผ‰ใ€ใ•ใ‚Œใพใ™ใ€‚ + +/// + +## ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-automatic-api-docs } + +ใ‚ขใƒ—ใƒชใ‚’ๅฎŸ่กŒใ—ใพใ™: + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ใใ—ใฆ http://127.0.0.1:8000/docs ใ‚’้–‹ใใพใ™ใ€‚ + +ใ™ในใฆใฎใ‚ตใƒ–ใƒขใ‚ธใƒฅใƒผใƒซ็”ฑๆฅใฎใƒ‘ใ‚นใ‚’ๅซใ‚€่‡ชๅ‹• API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใŒ่กจ็คบใ•ใ‚Œใ€ๆญฃใ—ใ„ใƒ‘ใ‚น๏ผˆใŠใ‚ˆใณ prefix๏ผ‰ใจๆญฃใ—ใ„ใ‚ฟใ‚ฐใŒไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ใฎใŒๅˆ†ใ‹ใ‚Šใพใ™: + + + +## ๅŒใ˜ใƒซใƒผใ‚ฟใƒผใ‚’็•ฐใชใ‚‹ `prefix` ใง่ค‡ๆ•ฐๅ›žๅ–ใ‚Š่พผใ‚€ { #include-the-same-router-multiple-times-with-different-prefix } + +ๅŒใ˜ใƒซใƒผใ‚ฟใƒผใซๅฏพใ—ใฆใ€็•ฐใชใ‚‹ prefix ใง `.include_router()` ใ‚’่ค‡ๆ•ฐๅ›žไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ๅŒใ˜ API ใ‚’ `/api/v1` ใจ `/api/latest` ใฎใ‚ˆใ†ใซ็•ฐใชใ‚‹ prefix ใงๅ…ฌ้–‹ใ™ใ‚‹ๅ ดๅˆใซๅฝน็ซ‹ใกใพใ™ใ€‚ + +้ซ˜ๅบฆใชไฝฟใ„ๆ–นใชใฎใงไธ่ฆใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใŒใ€ๅฟ…่ฆใชๅ ดๅˆใซๅ‚™ใˆใฆ็”จๆ„ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +## `APIRouter` ใ‚’ๅˆฅใฎ `APIRouter` ใซๅ–ใ‚Š่พผใ‚€ { #include-an-apirouter-in-another } + +`APIRouter` ใ‚’ `FastAPI` ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใซๅ–ใ‚Š่พผใ‚ใ‚‹ใฎใจๅŒใ˜ใ‚ˆใ†ใซใ€`APIRouter` ใ‚’ๅˆฅใฎ `APIRouter` ใซๅ–ใ‚Š่พผใ‚€ใ“ใจใ‚‚ใงใใพใ™: + +```Python +router.include_router(other_router) +``` + +`router` ใ‚’ `FastAPI` ใ‚ขใƒ—ใƒชใซๅ–ใ‚Š่พผใ‚€ๅ‰ใซใ“ใ‚Œใ‚’ๅฎŸ่กŒใ—ใฆใ€`other_router` ใฎ *path operations* ใ‚‚ๅซใพใ‚Œใ‚‹ใ‚ˆใ†ใซใ—ใฆใใ ใ•ใ„ใ€‚ diff --git a/docs/ja/docs/tutorial/body-multiple-params.md b/docs/ja/docs/tutorial/body-multiple-params.md index 4ce77cc0dc..0f81f4c46a 100644 --- a/docs/ja/docs/tutorial/body-multiple-params.md +++ b/docs/ja/docs/tutorial/body-multiple-params.md @@ -106,12 +106,6 @@ q: str | None = None ``` -ใพใŸใฏPython 3.10ไปฅไธŠใงใฏ: - -```Python -q: Union[str, None] = None -``` - ไพ‹ใˆใฐ: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/ja/docs/tutorial/body-nested-models.md b/docs/ja/docs/tutorial/body-nested-models.md index 24eb302082..ab78b8f86a 100644 --- a/docs/ja/docs/tutorial/body-nested-models.md +++ b/docs/ja/docs/tutorial/body-nested-models.md @@ -164,7 +164,7 @@ images: list[Image] ไปฅไธ‹ใฎใ‚ˆใ†ใซ: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## ใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงใฎใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ { #editor-support-everywhere } @@ -194,7 +194,7 @@ Pydanticใƒขใƒ‡ใƒซใงใฏใชใใ€`dict`ใ‚’็›ดๆŽฅไฝฟ็”จใ—ใฆใ„ใ‚‹ๅ ดๅˆใฏใ“ใฎ ใ“ใฎๅ ดๅˆใ€`int`ใฎใ‚ญใƒผใจ`float`ใฎๅ€คใ‚’ๆŒใคใ‚‚ใฎใงใ‚ใ‚Œใฐใ€ใฉใ‚“ใช`dict`ใงใ‚‚ๅ—ใ‘ๅ…ฅใ‚Œใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ diff --git a/docs/ja/docs/tutorial/body-updates.md b/docs/ja/docs/tutorial/body-updates.md index e888d5a0d9..310530c690 100644 --- a/docs/ja/docs/tutorial/body-updates.md +++ b/docs/ja/docs/tutorial/body-updates.md @@ -68,7 +68,7 @@ ใพใจใ‚ใ‚‹ใจใ€้ƒจๅˆ†็š„ใชๆ›ดๆ–ฐใ‚’้ฉ็”จใ™ใ‚‹ใซใฏใ€ๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: -* (ใ‚ชใƒ—ใ‚ทใƒงใƒณใง)`PUT`ใฎไปฃใ‚ใ‚Šใซ`PATCH`ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ +* (ใ‚ชใƒ—ใ‚ทใƒงใƒณใง)`PATCH`ใฎไปฃใ‚ใ‚Šใซ`PUT`ใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ * ไฟๅญ˜ใ•ใ‚Œใฆใ„ใ‚‹ใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ * ใใฎใƒ‡ใƒผใ‚ฟใ‚’Pydanticใƒขใƒ‡ใƒซใซใ„ใ‚Œใพใ™ใ€‚ * ๅ…ฅๅŠ›ใƒขใƒ‡ใƒซใ‹ใ‚‰ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅซใพใชใ„`dict`ใ‚’็”Ÿๆˆใ—ใพใ™๏ผˆ`exclude_unset`ใ‚’ไฝฟ็”จใ—ใพใ™๏ผ‰ใ€‚ diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index a219faed04..7c939bdfa0 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -74,7 +74,7 @@ APIใฏใปใจใ‚“ใฉใฎๅ ดๅˆ **ใƒฌใ‚นใƒใƒณใ‚น** ใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆ * ๅ—ใ‘ๅ–ใฃใŸใƒ‡ใƒผใ‚ฟใ‚’ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item` ใซๆธกใ—ใพใ™ใ€‚ * ้–ขๆ•ฐๅ†…ใง `Item` ๅž‹ใจใ—ใฆๅฎฃ่จ€ใ—ใŸใŸใ‚ใ€ใ™ในใฆใฎๅฑžๆ€งใจใใฎๅž‹ใซใคใ„ใฆใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚ตใƒใƒผใƒˆ๏ผˆ่ฃœๅฎŒใชใฉ๏ผ‰ใ‚‚ๅˆฉ็”จใงใใพใ™ใ€‚ * ใƒขใƒ‡ใƒซๅ‘ใ‘ใฎ JSON Schema ๅฎš็พฉใ‚’็”Ÿๆˆใ—ใพใ™ใ€‚ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใซใจใฃใฆๆ„ๅ‘ณใŒใ‚ใ‚‹ใชใ‚‰ใ€ไป–ใฎๅ ดๆ‰€ใงใ‚‚ๅฅฝใใชใ‚ˆใ†ใซๅˆฉ็”จใงใใพใ™ใ€‚ -* ใใ‚Œใ‚‰ใฎใ‚นใ‚ญใƒผใƒžใฏ็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใจใชใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ UIs ใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ +* ใใ‚Œใ‚‰ใฎใ‚นใ‚ญใƒผใƒžใฏ็”Ÿๆˆใ•ใ‚Œใ‚‹OpenAPIใ‚นใ‚ญใƒผใƒžใฎไธ€้ƒจใจใชใ‚Šใ€่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ UIs ใงไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ ## ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ { #automatic-docs } @@ -155,7 +155,7 @@ APIใฏใปใจใ‚“ใฉใฎๅ ดๅˆ **ใƒฌใ‚นใƒใƒณใ‚น** ใƒœใƒ‡ใ‚ฃใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆ FastAPIใฏใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€ค `= None` ใŒใ‚ใ‚‹ใŸใ‚ใ€`q` ใฎๅ€คใŒๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ -`str | None`๏ผˆPython 3.10+๏ผ‰ใ‚„ `Union[str, None]`๏ผˆPython 3.9+๏ผ‰ใฎ `Union` ใฏใ€ๅ€คใŒๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’ๅˆคๆ–ญใ™ใ‚‹ใŸใ‚ใซFastAPIใงใฏไฝฟ็”จใ•ใ‚Œใพใ›ใ‚“ใ€‚`= None` ใจใ„ใ†ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ +`str | None` ใฏใ€ๅ€คใŒๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’ๅˆคๆ–ญใ™ใ‚‹ใŸใ‚ใซFastAPIใงใฏไฝฟ็”จใ•ใ‚Œใพใ›ใ‚“ใ€‚`= None` ใจใ„ใ†ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…้ ˆใงใฏใชใ„ใ“ใจใ‚’่ช่ญ˜ใ—ใพใ™ใ€‚ ใ—ใ‹ใ—ใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’่ฟฝๅŠ ใ™ใ‚‹ใจใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใŒใ‚ˆใ‚Š่‰ฏใ„ใ‚ตใƒใƒผใƒˆใ‚’ๆไพ›ใ—ใ€ใ‚จใƒฉใƒผใ‚’ๆคœๅ‡บใงใใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/cookie-param-models.md b/docs/ja/docs/tutorial/cookie-param-models.md index 10ffb2566e..89ae424388 100644 --- a/docs/ja/docs/tutorial/cookie-param-models.md +++ b/docs/ja/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ ็‰นๅฎšใฎ๏ผˆใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใชใ„ใ‹ใ‚‚ใ—ใ‚Œใชใ„๏ผ‰ใ‚ฑใƒผใ‚นใงใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ใ‚ฏใƒƒใ‚ญใƒผใ‚’**ๅˆถ้™**ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ -ใ‚ใชใŸใฎAPIใฏ็‹ฌ่‡ชใฎ ใ‚ฏใƒƒใ‚ญใƒผๅŒๆ„ ใ‚’็ฎก็†ใ™ใ‚‹่ƒฝๅŠ›ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ ๐Ÿคช๐Ÿช +ใ‚ใชใŸใฎAPIใฏ็‹ฌ่‡ชใฎ ใ‚ฏใƒƒใ‚ญใƒผๅŒๆ„ ใ‚’็ฎก็†ใ™ใ‚‹่ƒฝๅŠ›ใ‚’ๆŒใฃใฆใ„ใพใ™ใ€‚ ๐Ÿคช๐Ÿช Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใจใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -54,9 +54,9 @@ Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ ใ‚‚ใ—ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ**ไฝ™ๅˆ†ใชใ‚ฏใƒƒใ‚ญใƒผ**ใ‚’้€ใ‚ใ†ใจใ™ใ‚‹ใจใ€**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ -ใฉใ†ใ›APIใซๆ‹’ๅฆใ•ใ‚Œใ‚‹ใฎใซใ‚ใชใŸใฎๅŒๆ„ใ‚’ๅพ—ใ‚ˆใ†ใจ็ฒพไธ€ๆฏๅŠชๅŠ›ใ™ใ‚‹ๅฏๅ“€ๆƒณใชใ‚ฏใƒƒใ‚ญใƒผใƒใƒŠใƒผใŸใก... ๐Ÿช +ใฉใ†ใ›APIใซๆ‹’ๅฆใ•ใ‚Œใ‚‹ใฎใซใ‚ใชใŸใฎๅŒๆ„ใ‚’ๅพ—ใ‚ˆใ†ใจ็ฒพไธ€ๆฏๅŠชๅŠ›ใ™ใ‚‹ๅฏๅ“€ๆƒณใชใ‚ฏใƒƒใ‚ญใƒผใƒใƒŠใƒผใŸใก... ๐Ÿช -ไพ‹ใˆใฐใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ‚ฏใƒƒใ‚ญใƒผ `santa_tracker` ใ‚’ `good-list-please` ใจใ„ใ†ๅ€คใง้€ใ‚ใ†ใจใ™ใ‚‹ใจใ€`santa_tracker` ใจใ„ใ† ใ‚ฏใƒƒใ‚ญใƒผใŒ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ ใ“ใจใ‚’้€š็Ÿฅใ™ใ‚‹**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™: +ไพ‹ใˆใฐใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ‚ฏใƒƒใ‚ญใƒผ `santa_tracker` ใ‚’ `good-list-please` ใจใ„ใ†ๅ€คใง้€ใ‚ใ†ใจใ™ใ‚‹ใจใ€`santa_tracker` ใจใ„ใ† ใ‚ฏใƒƒใ‚ญใƒผใŒ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ ใ“ใจใ‚’้€š็Ÿฅใ™ใ‚‹**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™: ```json { @@ -73,4 +73,4 @@ Pydanticใฎใƒขใƒ‡ใƒซใฎ Configuration ใ‚’ๅˆฉ็”จใ—ใฆใ€ `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ ## ใพใจใ‚ { #summary } -**FastAPI**ใงใฏใ€**ใ‚ฏใƒƒใ‚ญใƒผ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚๐Ÿ˜Ž +**FastAPI**ใงใฏใ€**ใ‚ฏใƒƒใ‚ญใƒผ**ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซใ€**Pydanticใƒขใƒ‡ใƒซ**ใ‚’ไฝฟ็”จใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/cors.md b/docs/ja/docs/tutorial/cors.md index a1dfe8e624..5136a7fd5f 100644 --- a/docs/ja/docs/tutorial/cors.md +++ b/docs/ja/docs/tutorial/cors.md @@ -46,7 +46,7 @@ * ็‰นๅฎšใฎHTTPใƒกใ‚ฝใƒƒใƒ‰ (`POST`ใ€`PUT`) ใพใŸใฏใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ `"*"` ใ‚’ไฝฟ็”จใ—ใฆใ™ในใฆ่จฑๅฏใ€‚ * ็‰นๅฎšใฎHTTPใƒ˜ใƒƒใƒ€ใƒผใ€ใพใŸใฏใƒฏใ‚คใƒซใƒ‰ใ‚ซใƒผใƒ‰ `"*"`ใ‚’ไฝฟ็”จใ—ใฆใ™ในใฆ่จฑๅฏใ€‚ -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} `CORSMiddleware` ๅฎŸ่ฃ…ใงไฝฟ็”จใ•ใ‚Œใ‚‹ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงๅˆถ้™ใŒๅŽณใ—ใ„ใŸใ‚ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใŒใ‚ฏใƒญใ‚นใƒ‰ใƒกใ‚คใƒณใฎใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใงใใ‚Œใ‚‰ใ‚’ไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹ใซใฏใ€็‰นๅฎšใฎใ‚ชใƒชใ‚ธใƒณใ€ใƒกใ‚ฝใƒƒใƒ‰ใ€ใพใŸใฏใƒ˜ใƒƒใƒ€ใƒผใ‚’ๆ˜Ž็คบ็š„ใซๆœ‰ๅŠนใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/debugging.md b/docs/ja/docs/tutorial/debugging.md index 8fe5b2d5d3..9d88ba42b5 100644 --- a/docs/ja/docs/tutorial/debugging.md +++ b/docs/ja/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Visual Studio Codeใ‚„PyCharmใชใฉใ‚’ไฝฟ็”จใ—ใฆใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผไธŠใงใƒ‡ใƒ FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณไธŠใงใ€`uvicorn` ใ‚’็›ดๆŽฅใ‚คใƒณใƒใƒผใƒˆใ—ใฆๅฎŸ่กŒใ—ใพใ™: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### `__name__ == "__main__"` ใซใคใ„ใฆ { #about-name-main } diff --git a/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md index 3cb1fe73d9..21de5b9783 100644 --- a/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ FastAPIใŒๅฎŸ้š›ใซใƒใ‚งใƒƒใ‚ฏใ—ใฆใ„ใ‚‹ใฎใฏใ€ใใ‚ŒใŒใ€Œๅ‘ผใณๅ‡บใ—ๅฏ ไธŠใฎใ‚ณใƒผใƒ‰ใงใฏ`CommonQueryParams`ใ‚’๏ผ’ๅ›žๆ›ธใ„ใฆใ„ใ‚‹ใ“ใจใซๆณจ็›ฎใ—ใฆใใ ใ•ใ„: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -137,7 +137,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ใ“ใฎๅ ดๅˆใ€ไปฅไธ‹ใซใ‚ใ‚‹ๆœ€ๅˆใฎ`CommonQueryParams`: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -163,7 +163,7 @@ commons: CommonQueryParams ... ๅฎŸ้š›ใซใฏไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใ‘ใฐใ„ใ„ใ ใ‘ใงใ™: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams) ใ—ใ‹ใ—ใ€ใ“ใ“ใงใฏ`CommonQueryParams`ใ‚’๏ผ’ๅ›žๆ›ธใใจใ„ใ†ใ‚ณใƒผใƒ‰ใฎ็นฐใ‚Š่ฟ”ใ—ใŒ็™บ็”Ÿใ—ใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใไปฃใ‚ใ‚Šใซ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...ไปฅไธ‹ใฎใ‚ˆใ†ใซๆ›ธใใพใ™: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ ๆณจ้‡ˆใชใ— +//// tab | Python 3.10+ ๆณจ้‡ˆใชใ— /// tip | ่ฑ†็Ÿฅ่ญ˜ diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 2051afc05b..d0a2b16721 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -14,7 +14,7 @@ ใใ‚Œใฏ`Depends()`ใฎ`list`ใงใ‚ใ‚‹ในใใงใ™: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏใ€้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒๆง˜ใซๅฎŸ่กŒใƒป่งฃๆฑบใ•ใ‚Œใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใ‚Œใ‚‰ใฎๅ€ค๏ผˆไฝ•ใ‹ใ‚’่ฟ”ใ™ๅ ดๅˆ๏ผ‰ใฏ*path operation ้–ขๆ•ฐ*ใซใฏๆธกใ•ใ‚Œใพใ›ใ‚“ใ€‚ @@ -44,13 +44,13 @@ ใ“ใ‚Œใ‚‰ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ่ฆไปถ๏ผˆใƒ˜ใƒƒใƒ€ใƒผใฎใ‚ˆใ†ใชใ‚‚ใฎ๏ผ‰ใ‚„ใใฎไป–ใฎใ‚ตใƒ–ไพๅญ˜้–ขไฟ‚ใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### ไพ‹ๅค–ใฎ็™บ็”Ÿ { #raise-exceptions } ใ“ใ‚Œใ‚‰ใฎไพๅญ˜้–ขไฟ‚ใฏใ€้€šๅธธใฎไพๅญ˜้–ขไฟ‚ใจๅŒใ˜ใ‚ˆใ†ใซไพ‹ๅค–ใ‚’`raise`ใงใใพใ™: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### ๆˆปใ‚Šๅ€ค { #return-values } @@ -58,7 +58,7 @@ ใคใพใ‚Šใ€ใ™ใงใซใฉใ“ใ‹ใงไฝฟใฃใฆใ„ใ‚‹้€šๅธธใฎไพๅญ˜้–ขไฟ‚๏ผˆๅ€คใ‚’่ฟ”ใ™ใ‚‚ใฎ๏ผ‰ใ‚’ๅ†ๅˆฉ็”จใงใใ€ๅ€คใฏไฝฟใ‚ใ‚Œใชใใฆใ‚‚ไพๅญ˜้–ขไฟ‚ใฏๅฎŸ่กŒใ•ใ‚Œใพใ™: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## *path operation*ใฎใ‚ฐใƒซใƒผใƒ—ใซๅฏพใ™ใ‚‹ไพๅญ˜้–ขไฟ‚ { #dependencies-for-a-group-of-path-operations } diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md index 8095114c3f..380dcb536b 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # `yield`ใ‚’ๆŒใคไพๅญ˜้–ขไฟ‚ { #dependencies-with-yield } -FastAPIใฏใ€ใ„ใใคใ‹ใฎ็ต‚ไบ†ๅพŒใฎ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’่กŒใ†ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ +FastAPIใฏใ€ใ„ใใคใ‹ใฎ็ต‚ไบ†ๅพŒใฎ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—ใ‚’่กŒใ†ไพๅญ˜้–ขไฟ‚ใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใ€‚ ใ“ใ‚Œใ‚’่กŒใ†ใซใฏใ€`return`ใฎไปฃใ‚ใ‚Šใซ`yield`ใ‚’ไฝฟใ„ใ€ใใฎๅพŒใซ่ฟฝๅŠ ใฎใ‚นใƒ†ใƒƒใƒ—๏ผˆใ‚ณใƒผใƒ‰๏ผ‰ใ‚’ๆ›ธใใพใ™ใ€‚ @@ -29,15 +29,15 @@ FastAPIใฏใ€ใ„ใใคใ‹ใฎ + +
+ +## ไฝ™ๅˆ†ใชใƒ˜ใƒƒใƒ€ใƒผใ‚’็ฆๆญข { #forbid-extra-headers } + +็‰นๆฎŠใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น๏ผˆใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใ‚ใ‚Šใพใ›ใ‚“๏ผ‰ใงใฏใ€ๅ—ใ‘ไป˜ใ‘ใ‚‹ใƒ˜ใƒƒใƒ€ใƒผใ‚’**ๅˆถ้™**ใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +Pydantic ใฎใƒขใƒ‡ใƒซ่จญๅฎšใง `extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใซใ—ใฆ็ฆๆญขใงใใพใ™: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ**ไฝ™ๅˆ†ใชใƒ˜ใƒƒใƒ€ใƒผ**ใ‚’้€ไฟกใ—ใ‚ˆใ†ใจใ™ใ‚‹ใจใ€**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๅ€ค `plumbus` ใฎ `tool` ใƒ˜ใƒƒใƒ€ใƒผใ‚’้€ใ‚ใ†ใจใ™ใ‚‹ใจใ€ใƒ˜ใƒƒใƒ€ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟ `tool` ใฏ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ๆ—จใฎ**ใ‚จใƒฉใƒผ**ใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## ใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขๅค‰ๆ›ใฎ็„กๅŠนๅŒ– { #disable-convert-underscores } + +้€šๅธธใฎใƒ˜ใƒƒใƒ€ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟใจๅŒๆง˜ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟๅใซใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขใŒใ‚ใ‚‹ๅ ดๅˆใฏ**่‡ชๅ‹•็š„ใซใƒใ‚คใƒ•ใƒณใซๅค‰ๆ›**ใ•ใ‚Œใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ‚ณใƒผใƒ‰ไธŠใงใƒ˜ใƒƒใƒ€ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟ `save_data` ใ‚’ๅฎš็พฉใ™ใ‚‹ใจใ€ๆƒณๅฎšใ•ใ‚Œใ‚‹ HTTP ใƒ˜ใƒƒใƒ€ใƒผใฏ `save-data` ใจใชใ‚Šใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆไธŠใซใ‚‚ใใฎใ‚ˆใ†ใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +ไฝ•ใ‚‰ใ‹ใฎ็†็”ฑใงใ“ใฎ่‡ชๅ‹•ๅค‰ๆ›ใ‚’็„กๅŠนๅŒ–ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใ€ใƒ˜ใƒƒใƒ€ใƒผใƒ‘ใƒฉใƒกใƒผใ‚ฟ็”จใฎ Pydantic ใƒขใƒ‡ใƒซใงใ‚‚็„กๅŠนๅŒ–ใงใใพใ™ใ€‚ + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | ๆณจๆ„ + +`convert_underscores` ใ‚’ `False` ใซ่จญๅฎšใ™ใ‚‹ๅ‰ใซใ€ใ‚ขใƒณใƒ€ใƒผใ‚นใ‚ณใ‚ขใ‚’ๅซใ‚€ใƒ˜ใƒƒใƒ€ใƒผใฎไฝฟ็”จใ‚’็ฆๆญขใ—ใฆใ„ใ‚‹ HTTP ใƒ—ใƒญใ‚ญใ‚ทใ‚„ใ‚ตใƒผใƒใƒผใŒใ‚ใ‚‹ใ“ใจใซ็•™ๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ใพใจใ‚ { #summary } + +**Pydantic ใƒขใƒ‡ใƒซ**ใ‚’ไฝฟใฃใฆ **FastAPI** ใง **ใƒ˜ใƒƒใƒ€ใƒผ**ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/metadata.md b/docs/ja/docs/tutorial/metadata.md index 0ffb8f3505..3b70bf2f41 100644 --- a/docs/ja/docs/tutorial/metadata.md +++ b/docs/ja/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ OpenAPIไป•ๆง˜ใŠใ‚ˆใณ่‡ชๅ‹•APIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใงไฝฟ็”จใ•ใ‚Œใ‚‹ๆฌกใฎใƒ• ไปฅไธ‹ใฎใ‚ˆใ†ใซ่จญๅฎšใงใใพใ™: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -36,7 +36,7 @@ OpenAPI 3.1.0 ใŠใ‚ˆใณ FastAPI 0.99.0 ไปฅ้™ใงใฏใ€`license_info` ใ‚’ `url` ไพ‹: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ { #metadata-for-tags } @@ -58,7 +58,7 @@ OpenAPI 3.1.0 ใŠใ‚ˆใณ FastAPI 0.99.0 ไปฅ้™ใงใฏใ€`license_info` ใ‚’ `url` ใ‚ฟใ‚ฐใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’ `openapi_tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใซๆธกใ—ใพใ™: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} ่ชฌๆ˜ŽใฎไธญใงMarkdownใ‚’ไฝฟ็”จใงใใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใŸใจใˆใฐใ€Œloginใ€ใฏๅคชๅญ— (**login**) ใง่กจ็คบใ•ใ‚Œใ€ใ€Œfancyใ€ใฏๆ–œไฝ“ (_fancy_) ใง่กจ็คบใ•ใ‚Œใพใ™ใ€‚ @@ -72,7 +72,7 @@ OpenAPI 3.1.0 ใŠใ‚ˆใณ FastAPI 0.99.0 ไปฅ้™ใงใฏใ€`license_info` ใ‚’ `url` *path operation*๏ผˆใŠใ‚ˆใณ `APIRouter`๏ผ‰ใฎ `tags` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝฟ็”จใ—ใฆใ€ใใ‚Œใ‚‰ใ‚’็•ฐใชใ‚‹ใ‚ฟใ‚ฐใซๅ‰ฒใ‚Šๅฝ“ใฆใพใ™: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | ๆƒ…ๅ ฑ @@ -100,7 +100,7 @@ OpenAPI 3.1.0 ใŠใ‚ˆใณ FastAPI 0.99.0 ไปฅ้™ใงใฏใ€`license_info` ใ‚’ `url` ใŸใจใˆใฐใ€`/api/v1/openapi.json` ใงๆไพ›ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ™ใ‚‹ใซใฏ: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} OpenAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎŒๅ…จใซ็„กๅŠนใซใ™ใ‚‹ๅ ดๅˆใฏใ€`openapi_url=None` ใ‚’่จญๅฎšใงใใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใใ‚Œใ‚’ไฝฟ็”จใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใ‚‚็„กๅŠนใซใชใ‚Šใพใ™ใ€‚ @@ -117,4 +117,4 @@ OpenAPIใ‚นใ‚ญใƒผใƒžใ‚’ๅฎŒๅ…จใซ็„กๅŠนใซใ™ใ‚‹ๅ ดๅˆใฏใ€`openapi_url=None` ใ‚’ ใŸใจใˆใฐใ€`/documentation` ใงSwagger UIใŒๆไพ›ใ•ใ‚Œใ‚‹ใ‚ˆใ†ใซ่จญๅฎšใ—ใ€ReDocใ‚’็„กๅŠนใซใ™ใ‚‹ใซใฏ: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/ja/docs/tutorial/middleware.md b/docs/ja/docs/tutorial/middleware.md index 12fb57a640..103d6e2c06 100644 --- a/docs/ja/docs/tutorial/middleware.md +++ b/docs/ja/docs/tutorial/middleware.md @@ -31,7 +31,7 @@ * ๆฌกใซใ€ๅฏพๅฟœใ™ใ‚‹*path operation*ใซใ‚ˆใฃใฆ็”Ÿๆˆใ•ใ‚ŒใŸ `response` ใ‚’่ฟ”ใ—ใพใ™ใ€‚ * ใใฎๅพŒใ€`response` ใ‚’่ฟ”ใ™ๅ‰ใซใ•ใ‚‰ใซ `response` ใ‚’ๅค‰ๆ›ดใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -57,7 +57,7 @@ ไพ‹ใˆใฐใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎๅ‡ฆ็†ใจใƒฌใ‚นใƒใƒณใ‚นใฎ็”Ÿๆˆใซใ‹ใ‹ใฃใŸ็ง’ๆ•ฐใ‚’ๅซใ‚€ใ‚ซใ‚นใ‚ฟใƒ ใƒ˜ใƒƒใƒ€ใƒผ `X-Process-Time` ใ‚’่ฟฝๅŠ ใงใใพใ™: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -92,4 +92,4 @@ app.add_middleware(MiddlewareB) ไป–ใฎใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใฎ่ฉณ็ดฐใซใคใ„ใฆใฏใ€[้ซ˜ๅบฆใชใƒฆใƒผใ‚ถใƒผใ‚ฌใ‚คใƒ‰: ้ซ˜ๅบฆใชใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ข](../advanced/middleware.md){.internal-link target=_blank}ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ -ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ไฝฟ็”จใ—ใฆ CORS ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ +ๆฌกใฎใ‚ปใ‚ฏใ‚ทใƒงใƒณใงใฏใ€ใƒŸใƒ‰ใƒซใ‚ฆใ‚งใ‚ขใ‚’ไฝฟ็”จใ—ใฆ CORS ใ‚’ๅ‡ฆ็†ใ™ใ‚‹ๆ–นๆณ•ใซใคใ„ใฆ่ชฌๆ˜Žใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/path-operation-configuration.md b/docs/ja/docs/tutorial/path-operation-configuration.md index eb6b6b11a5..556cc6b148 100644 --- a/docs/ja/docs/tutorial/path-operation-configuration.md +++ b/docs/ja/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ **FastAPI** ใฏใ€ใƒ—ใƒฌใƒผใƒณใชๆ–‡ๅญ—ๅˆ—ใฎๅ ดๅˆใจๅŒใ˜ๆ–นๆณ•ใงใใ‚Œใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## ๆฆ‚่ฆใจ่ชฌๆ˜Ž { #summary-and-description } @@ -56,7 +56,7 @@ ## docstringใ‚’็”จใ„ใŸ่ชฌๆ˜Ž { #description-from-docstring } -่ชฌๆ˜Žๆ–‡ใฏ้•ทใใฆ่ค‡ๆ•ฐ่กŒใซใŠใ‚ˆใถๅ‚พๅ‘ใŒใ‚ใ‚‹ใฎใงใ€้–ขๆ•ฐdocstringๅ†…ใซ*path operation*ใฎ่ชฌๆ˜Žๆ–‡ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ใ™ใ‚‹ใจใ€**FastAPI** ใฏ่ชฌๆ˜Žๆ–‡ใ‚’่ชญใฟ่พผใ‚“ใงใใ‚Œใพใ™ใ€‚ +่ชฌๆ˜Žๆ–‡ใฏ้•ทใใฆ่ค‡ๆ•ฐ่กŒใซใŠใ‚ˆใถๅ‚พๅ‘ใŒใ‚ใ‚‹ใฎใงใ€้–ขๆ•ฐdocstringๅ†…ใซ*path operation*ใฎ่ชฌๆ˜Žๆ–‡ใ‚’ๅฎฃ่จ€ใงใใพใ™ใ€‚ใ™ใ‚‹ใจใ€**FastAPI** ใฏ่ชฌๆ˜Žๆ–‡ใ‚’่ชญใฟ่พผใ‚“ใงใใ‚Œใพใ™ใ€‚ docstringใซMarkdownใ‚’่จ˜่ฟฐใ™ใ‚Œใฐใ€ๆญฃใ—ใ่งฃ้‡ˆใ•ใ‚Œใฆ่กจ็คบใ•ใ‚Œใพใ™ใ€‚๏ผˆdocstringใฎใ‚คใƒณใƒ‡ใƒณใƒˆใ‚’่€ƒๆ…ฎใ—ใฆ๏ผ‰ @@ -90,9 +90,9 @@ OpenAPIใฏ*path operation*ใ”ใจใซใƒฌใ‚นใƒใƒณใ‚นใฎ่ชฌๆ˜Žใ‚’ๅฟ…่ฆใจใ—ใฆใ„ ## *path operation*ใ‚’้žๆŽจๅฅจใซใ™ใ‚‹ { #deprecate-a-path-operation } -*path operation*ใ‚’deprecatedใจใ—ใฆใƒžใƒผใ‚ฏใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŒใ€ใใ‚Œใ‚’ๅ‰Š้™คใ—ใชใ„ๅ ดๅˆใฏใ€`deprecated`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™: +*path operation*ใ‚’deprecatedใจใ—ใฆใƒžใƒผใ‚ฏใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ใŒใ€ใใ‚Œใ‚’ๅ‰Š้™คใ—ใชใ„ๅ ดๅˆใฏใ€`deprecated`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๆธกใ—ใพใ™: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} ๅฏพ่ฉฑ็š„ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใฏ้žๆŽจๅฅจใจๆ˜Ž่จ˜ใ•ใ‚Œใพใ™: diff --git a/docs/ja/docs/tutorial/path-params-numeric-validations.md b/docs/ja/docs/tutorial/path-params-numeric-validations.md index 6a9ecc4e7b..ab3240f042 100644 --- a/docs/ja/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ja/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Pythonใฏใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใคๅ€คใ‚’ใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใŸใช ใใฎใŸใ‚ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใซ้–ขๆ•ฐใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} ใŸใ ใ—ใ€`Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใฏใ“ใฎๅ•้กŒใฏ่ตทใใชใ„ใ“ใจใ‚’่ฆšใˆใฆใŠใ„ใฆใใ ใ•ใ„ใ€‚`Query()`ใ‚„`Path()`ใซ้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ไฝฟใ‚ใชใ„ใŸใ‚ใงใ™ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## ๅฟ…่ฆใซๅฟœใ˜ใฆใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไธฆใณๆ›ฟใˆใ‚‹ใƒˆใƒชใƒƒใ‚ฏ { #order-the-parameters-as-you-need-tricks } @@ -81,15 +81,15 @@ Pythonใฏใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใคๅ€คใ‚’ใ€Œใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใ€ใ‚’ๆŒใŸใช ้–ขๆ•ฐใฎๆœ€ๅˆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ`*`ใ‚’ๆธกใ—ใพใ™ใ€‚ -Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ใฎใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐ๏ผˆใ‚ญใƒผใจๅ€คใฎใƒšใ‚ข๏ผ‰ใจใ—ใฆๅ‘ผใฐใ‚Œใ‚‹ในใใ‚‚ใฎใงใ‚ใ‚‹ใจ็Ÿฅใฃใฆใ„ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใใ‚Œใฏkwargsใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ใŸใจใˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใใฆใ‚‚ใ€‚ +Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ใฎใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐ๏ผˆใ‚ญใƒผใจๅ€คใฎใƒšใ‚ข๏ผ‰ใจใ—ใฆๅ‘ผใฐใ‚Œใ‚‹ในใใ‚‚ใฎใงใ‚ใ‚‹ใจ็Ÿฅใฃใฆใ„ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ใใ‚Œใฏkwargsใจใ—ใฆใ‚‚็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ใŸใจใˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒใชใใฆใ‚‚ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### `Annotated`ใฎใปใ†ใŒใ‚ˆใ„ { #better-with-annotated } `Annotated`ใ‚’ไฝฟใ†ๅ ดๅˆใฏใ€้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ไฝฟใ‚ใชใ„ใŸใ‚ใ€ใ“ใฎๅ•้กŒใฏ่ตทใใšใ€ใŠใใ‚‰ใ`*`ใ‚’ไฝฟใ†ๅฟ…่ฆใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## ๆ•ฐๅ€คใฎๆคœ่จผ: ไปฅไธŠ { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ ใ“ใ“ใงใ€`ge=1`ใฎๅ ดๅˆใ€`item_id`ใฏ`1`ใ€Œใ‚ˆใ‚Šๅคงใใ„`g`ใ‹ใ€ๅŒใ˜`e`ใ€ๆ•ดๆ•ฐใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## ๆ•ฐๅ€คใฎๆคœ่จผ: ใ‚ˆใ‚Šๅคงใใ„ใจๅฐใชใ‚Šใ‚คใ‚ณใƒผใƒซ { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## ๆ•ฐๅ€คใฎๆคœ่จผ: ๆตฎๅ‹•ๅฐๆ•ฐ็‚นใ€ ๅคงใชใ‚Šๅฐใชใ‚Š { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Pythonใฏใใฎ`*`ใงไฝ•ใ‹ใ‚’ใ™ใ‚‹ใ“ใจใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใใ‚Œไปฅ้™ ใ“ใ‚Œใฏltใ‚‚ๅŒใ˜ใงใ™ใ€‚ -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ใพใจใ‚ { #recap } diff --git a/docs/ja/docs/tutorial/path-params.md b/docs/ja/docs/tutorial/path-params.md index 96a1fe9d10..5b78eb7b1f 100644 --- a/docs/ja/docs/tutorial/path-params.md +++ b/docs/ja/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใ€ใ‚„ใ€Œใƒ‘ใ‚นๅค‰ๆ•ฐใ€ใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ `item_id` ใฎๅ€คใฏใ€ๅผ•ๆ•ฐ `item_id` ใจใ—ใฆ้–ขๆ•ฐใซๆธกใ•ใ‚Œใพใ™ใ€‚ @@ -16,7 +16,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ๆจ™ๆบ–ใฎPythonใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไฝฟ็”จใ—ใฆใ€้–ขๆ•ฐๅ†…ใฎใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ใ‚’ๅฎฃ่จ€ใงใใพใ™: -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} ใ“ใ“ใงใฏใ€ `item_id` ใฏ `int` ใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -26,7 +26,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ /// -## ใƒ‡ใƒผใ‚ฟๅค‰ๆ› { #data-conversion } +## ใƒ‡ใƒผใ‚ฟๅค‰ๆ› { #data-conversion } ใ“ใฎไพ‹ใ‚’ๅฎŸ่กŒใ—ใ€ใƒ–ใƒฉใ‚ฆใ‚ถใง http://127.0.0.1:8000/items/3 ใ‚’้–‹ใใจใ€ๆฌกใฎใƒฌใ‚นใƒใƒณใ‚นใŒ่กจ็คบใ•ใ‚Œใพใ™: @@ -38,7 +38,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ้–ขๆ•ฐใŒๅ—ใ‘ๅ–ใฃใŸ๏ผˆใŠใ‚ˆใณ่ฟ”ใ—ใŸ๏ผ‰ๅ€คใฏใ€ๆ–‡ๅญ—ๅˆ—ใฎ `"3"` ใงใฏใชใใ€Pythonใฎ `int` ใจใ—ใฆใฎ `3` ใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ -ใ—ใŸใŒใฃใฆใ€ใใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟใ†ใจใ€**FastAPI**ใฏ่‡ชๅ‹•ใƒชใ‚ฏใ‚จใ‚นใƒˆ "่งฃๆž" ใ‚’่กŒใ„ใพใ™ใ€‚ +ใ—ใŸใŒใฃใฆใ€ใใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟใ†ใจใ€**FastAPI**ใฏ่‡ชๅ‹•ใƒชใ‚ฏใ‚จใ‚นใƒˆ "่งฃๆž" ใ‚’่กŒใ„ใพใ™ใ€‚ /// @@ -118,13 +118,13 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ *path operations* ใฏ้ †ใซ่ฉ•ไพกใ•ใ‚Œใ‚‹ใฎใงใ€ `/users/me` ใŒ `/users/{user_id}` ใ‚ˆใ‚Šใ‚‚ๅ…ˆใซๅฎฃ่จ€ใ•ใ‚Œใฆใ„ใ‚‹ใ‹็ขบ่ชใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} ใใ‚Œไปฅๅค–ใฎๅ ดๅˆใ€ `/users/{user_id}` ใฏ `/users/me` ใจใ—ใฆใ‚‚ใƒžใƒƒใƒใ—ใพใ™ใ€‚ๅ€คใŒ `"me"` ใงใ‚ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟ `user_id` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใจใ€Œ่€ƒใˆใ€ใพใ™ใ€‚ ๅŒๆง˜ใซใ€path operation ใ‚’ๅ†ๅฎš็พฉใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} ใƒ‘ใ‚นใฏๆœ€ๅˆใซใƒžใƒƒใƒใ—ใŸใ‚‚ใฎใŒๅธธใซไฝฟใ‚ใ‚Œใ‚‹ใŸใ‚ใ€ๆœ€ๅˆใฎใ‚‚ใฎใŒๅธธใซไฝฟ็”จใ•ใ‚Œใพใ™ใ€‚ @@ -140,11 +140,11 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ใใ—ใฆใ€ๅ›บๅฎšๅ€คใฎใ‚ฏใƒฉใ‚นๅฑžๆ€งใ‚’ไฝœใ‚Šใพใ™ใ€‚ใ™ใ‚‹ใจใ€ใใฎๅ€คใŒไฝฟ็”จๅฏ่ƒฝใชๅ€คใจใชใ‚Šใพใ™: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ -"AlexNet"ใ€"ResNet"ใใ—ใฆ"LeNet"ใฏๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใฎๅๅ‰ใงใ™ใ€‚ +"AlexNet"ใ€"ResNet"ใใ—ใฆ"LeNet"ใฏๆฉŸๆขฐๅญฆ็ฟ’ใƒขใƒ‡ใƒซใฎๅๅ‰ใงใ™ใ€‚ /// @@ -152,7 +152,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ๆฌกใซใ€ไฝœๆˆใ—ใŸenumใ‚ฏใƒฉใ‚นใงใ‚ใ‚‹`ModelName`ใ‚’ไฝฟ็”จใ—ใŸๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ใ‚‚ใค*ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟ*ใ‚’ไฝœๆˆใ—ใพใ™: -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ็ขบ่ช { #check-the-docs } @@ -168,13 +168,13 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ใ“ใ‚Œใฏใ€ไฝœๆˆใ—ใŸๅˆ—ๆŒ™ๅž‹ `ModelName` ใฎ*ๅˆ—ๆŒ™ๅž‹ใƒกใƒณใƒ*ใจๆฏ”่ผƒใงใใพใ™: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### *ๅˆ—ๆŒ™ๅ€ค*ใฎๅ–ๅพ— { #get-the-enumeration-value } `model_name.value` ใ€ใ‚‚ใ—ใใฏไธ€่ˆฌใซใ€ `your_enum_member.value` ใ‚’ไฝฟ็”จใ—ใฆๅฎŸ้š›ใฎๅ€ค (ใ“ใฎๅ ดๅˆใฏ `str`) ใ‚’ๅ–ๅพ—ใงใใพใ™ใ€‚ -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -188,7 +188,7 @@ Pythonใฎformatๆ–‡ๅญ—ๅˆ—ใจๅŒๆง˜ใฎใ‚ทใƒณใ‚ฟใƒƒใ‚ฏใ‚นใงใ€Œใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผ ใใ‚Œใ‚‰ใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ•ใ‚Œใ‚‹ๅ‰ใซ้ฉๅˆ‡ใชๅ€ค (ใ“ใฎๅ ดๅˆใฏๆ–‡ๅญ—ๅˆ—) ใซๅค‰ๆ›ใ•ใ‚Œใพใ™ใ€‚ -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏไปฅไธ‹ใฎๆง˜ใชJSONใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅพ—ใพใ™: @@ -227,7 +227,7 @@ Starletteใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ไปฅไธ‹ใฎURLใฎๆง˜ ใ—ใŸใŒใฃใฆใ€ไปฅไธ‹ใฎๆง˜ใซไฝฟ็”จใงใใพใ™: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -242,7 +242,7 @@ Starletteใฎใ‚ชใƒ—ใ‚ทใƒงใƒณใ‚’็›ดๆŽฅไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€ไปฅไธ‹ใฎURLใฎๆง˜ ็ฐกๆฝ”ใงใ€ๆœฌ่ณช็š„ใงใ€ๆจ™ๆบ–็š„ใชPythonใฎๅž‹ๅฎฃ่จ€ใ‚’ไฝฟ็”จใ™ใ‚‹ใ“ใจใงใ€**FastAPI**ใฏไปฅไธ‹ใ‚’่กŒใ„ใพใ™: * ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆ: ใ‚จใƒฉใƒผใƒใ‚งใƒƒใ‚ฏใ€่‡ชๅ‹•่ฃœๅฎŒใ€ใชใฉ -* ใƒ‡ใƒผใ‚ฟใ€Œ่งฃๆžใ€ +* ใƒ‡ใƒผใ‚ฟใ€Œ่งฃๆžใ€ * ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ * APIใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใจ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆ diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index e230ef29af..dda4e120bf 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -47,40 +47,16 @@ FastAPI ใฏใƒใƒผใ‚ธใƒงใƒณ 0.95.0 ใง `Annotated` ใฎใ‚ตใƒใƒผใƒˆใ‚’่ฟฝๅŠ ใ—๏ผˆ ๆฌกใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒใ‚ใ‚Šใพใ—ใŸ: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ใ“ใ‚Œใ‚’ `Annotated` ใงๅŒ…ใ‚“ใงใ€ๆฌกใฎใ‚ˆใ†ใซใ—ใพใ™: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - ใฉใกใ‚‰ใ‚‚ๅŒใ˜ๆ„ๅ‘ณใงใ€`q` ใฏ `str` ใพใŸใฏ `None` ใซใชใ‚Šๅพ—ใ‚‹ใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏ `None` ใงใ™ใ€‚ ใงใฏใ€้ข็™ฝใ„ใจใ“ใ‚ใซ้€ฒใฟใพใ—ใ‚‡ใ†ใ€‚ ๐ŸŽ‰ @@ -109,7 +85,7 @@ FastAPI ใฏๆฌกใ‚’่กŒใ„ใพใ™: ## ไปฃๆ›ฟ๏ผˆๅคใ„ๆ–นๆณ•๏ผ‰: ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆใฎ `Query` { #alternative-old-query-as-the-default-value } -FastAPI ใฎไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณ๏ผˆ0.95.0 ใ‚ˆใ‚Šๅ‰๏ผ‰ใงใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ `Query` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใ€`Annotated` ใฎไธญใซๅ…ฅใ‚Œใ‚‹ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ใ“ใ‚Œใ‚’ไฝฟใฃใŸใ‚ณใƒผใƒ‰ใ‚’่ฆ‹ใ‹ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใฎใงใ€่ชฌๆ˜Žใ—ใพใ™ใ€‚ +FastAPI ใฎไปฅๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณ๏ผˆ0.95.0 ใ‚ˆใ‚Šๅ‰๏ผ‰ใงใฏใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆ `Query` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใ€`Annotated` ใฎไธญใซๅ…ฅใ‚Œใ‚‹ใฎใงใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ใ“ใ‚Œใ‚’ไฝฟใฃใŸใ‚ณใƒผใƒ‰ใ‚’่ฆ‹ใ‹ใ‘ใ‚‹ๅฏ่ƒฝๆ€งใŒ้ซ˜ใ„ใฎใงใ€่ชฌๆ˜Žใ—ใพใ™ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -192,7 +168,7 @@ FastAPI ใชใ—ใงๅŒใ˜้–ขๆ•ฐใ‚’ **ๅˆฅใฎๅ ดๆ‰€** ใ‹ใ‚‰ **ๅ‘ผใณๅ‡บใ—ใฆใ‚‚** ## ๆญฃ่ฆ่กจ็พใฎ่ฟฝๅŠ  { #add-regular-expressions } -ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒไธ€่‡ดใ™ใ‚‹ในใ ๆญฃ่ฆ่กจ็พ `pattern` ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: +ใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒไธ€่‡ดใ™ใ‚‹ในใ ๆญฃ่ฆ่กจ็พ `pattern` ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใŒใงใใพใ™: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -212,7 +188,7 @@ FastAPI ใชใ—ใงๅŒใ˜้–ขๆ•ฐใ‚’ **ๅˆฅใฎๅ ดๆ‰€** ใ‹ใ‚‰ **ๅ‘ผใณๅ‡บใ—ใฆใ‚‚** ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `q` ใฎ `min_length` ใ‚’ `3` ใจใ—ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ `"fixedquery"` ใจใ—ใฆๅฎฃ่จ€ใ—ใŸใ„ใจใ—ใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | ๅ‚™่€ƒ @@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None ใใฎใŸใ‚ใ€`Query` ใ‚’ไฝฟใ„ใชใŒใ‚‰ๅ€คใ‚’ๅฟ…้ ˆใจใ—ใฆๅฎฃ่จ€ใ—ใŸใ„ๅ ดๅˆใฏใ€ๅ˜ใซใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใพใ›ใ‚“: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### ๅฟ…้ ˆใ€`None` ใซใงใใ‚‹ { #required-can-be-none } @@ -293,7 +269,7 @@ http://localhost:8000/items/?q=foo&q=bar ใพใŸใ€ๅ€คใŒๆŒ‡ๅฎšใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใฎ `list` ใ‚’ๅฎš็พฉใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ไปฅไธ‹ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจ: @@ -316,7 +292,7 @@ http://localhost:8000/items/ `list[str]` ใฎไปฃใ‚ใ‚Šใซ็›ดๆŽฅ `list` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | ๅ‚™่€ƒ @@ -372,7 +348,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ใ•ใฆใ€ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใŒๆฐ—ใซๅ…ฅใ‚‰ใชใใชใฃใŸใจใ—ใพใ—ใ‚‡ใ†ใ€‚ -ใใ‚Œใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใ‚‹ใฎใงใ€ใ—ใฐใ‚‰ใใฏๆฎ‹ใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใŒใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏdeprecatedใจๆ˜Ž่จ˜ใ—ใฆใŠใใŸใ„ใงใ™ใ€‚ +ใใ‚Œใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ„ใ‚‹ใฎใงใ€ใ—ใฐใ‚‰ใใฏๆฎ‹ใ—ใฆใŠใๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใŒใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใซใฏdeprecatedใจๆ˜Ž่จ˜ใ—ใฆใŠใใŸใ„ใงใ™ใ€‚ ใใฎๅ ดๅˆใ€`Query`ใซใƒ‘ใƒฉใƒกใƒผใ‚ฟ`deprecated=True`ใ‚’ๆธกใ—ใพใ™: @@ -402,7 +378,7 @@ Pydantic ใซใฏ ISBN ใฎๆ›ธ็ฑ็•ชๅทใชใ‚‰ item ID ใŒ `isbn-` ใงๅง‹ใพใ‚‹ใ“ใจใ€IMDB ใฎ movie URL ID ใชใ‚‰ `imdb-` ใงๅง‹ใพใ‚‹ใ“ใจใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: +ไพ‹ใˆใฐใ€ใ“ใฎใ‚ซใ‚นใ‚ฟใƒ ใƒใƒชใƒ‡ใƒผใ‚ฟใฏใ€ISBN ใฎๆ›ธ็ฑ็•ชๅทใชใ‚‰ item ID ใŒ `isbn-` ใงๅง‹ใพใ‚‹ใ“ใจใ€IMDB ใฎ movie URL ID ใชใ‚‰ `imdb-` ใงๅง‹ใพใ‚‹ใ“ใจใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใพใ™: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -436,7 +412,7 @@ Pydantic ใซใฏ ๅๅพฉๅฏ่ƒฝใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ +`data.items()` ใงใ€่พžๆ›ธใฎๅ„ใ‚ขใ‚คใƒ†ใƒ ใฎใ‚ญใƒผใจๅ€คใ‚’ๅซใ‚€ใ‚ฟใƒ—ใƒซใ‚’ๆŒใค ๅๅพฉๅฏ่ƒฝใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ ใ“ใฎๅๅพฉๅฏ่ƒฝใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ `list(data.items())` ใง้ฉๅˆ‡ใช `list` ใซๅค‰ๆ›ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 41e51ed782..d32c9822b8 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใชใ„้–ขๆ•ฐใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใใ‚Œใ‚‰ใฏ่‡ชๅ‹•็š„ใซใ€Œใ‚ฏใ‚จใƒชใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} ใ‚ฏใ‚จใƒชใฏURLๅ†…ใง `?` ใฎๅพŒใซ็ถšใใ‚ญใƒผใจใƒใƒชใƒฅใƒผใฎ็ต„ใงใ€ `&` ใงๅŒบๅˆ‡ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ @@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 ใƒ‘ใ‚นใƒ‘ใƒฉใƒกใƒผใ‚ฟใซ้ฉ็”จใ•ใ‚Œใ‚‹ๅ‡ฆ็†ใจๅฎŒๅ…จใซๅŒๆง˜ใชๅ‡ฆ็†ใŒใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใซใ‚‚ๆ–ฝใ•ใ‚Œใพใ™: * ใ‚จใƒ‡ใ‚ฃใ‚ฟใƒผใ‚ตใƒใƒผใƒˆ (ๆ˜Žใ‚‰ใ‹ใซ) -* ใƒ‡ใƒผใ‚ฟ ใ€Œ่งฃๆžใ€ +* ใƒ‡ใƒผใ‚ฟ ใ€Œ่งฃๆžใ€ * ใƒ‡ใƒผใ‚ฟใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณ * ่‡ชๅ‹•ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ็”Ÿๆˆ @@ -128,7 +128,7 @@ http://127.0.0.1:8000/items/foo?short=yes ใ—ใ‹ใ—ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฟ…้ ˆใซใ—ใŸใ„ๅ ดๅˆใฏใ€ใŸใ ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๅฎฃ่จ€ใ—ใชใ‘ใ‚Œใฐใ‚ˆใ„ใงใ™: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} ใ“ใ“ใงใ€ใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟ `needy` ใฏ `str` ๅž‹ใฎๅฟ…้ ˆใฎใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/request-files.md b/docs/ja/docs/tutorial/request-files.md new file mode 100644 index 0000000000..538cf64744 --- /dev/null +++ b/docs/ja/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# ใƒชใ‚ฏใ‚จใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ { #request-files } + +`File` ใ‚’ไฝฟใฃใฆใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซใ‚’ๅฎš็พฉใงใใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚ŒใŸใƒ•ใ‚กใ‚คใƒซใ‚’ๅ—ใ‘ๅ–ใ‚‹ใซใฏใ€ใพใš `python-multipart` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ + +[ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ๆฌกใฎใ‚ˆใ†ใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„: + +```console +$ pip install python-multipart +``` + +ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚ŒใŸใƒ•ใ‚กใ‚คใƒซใฏใ€Œform dataใ€ใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใŸใ‚ใงใ™ใ€‚ + +/// + +## `File` ใ‚’ใ‚คใƒณใƒใƒผใƒˆ { #import-file } + +`fastapi` ใ‹ใ‚‰ `File` ใจ `UploadFile` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} + +## `File` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ { #define-file-parameters } + +`Body` ใ‚„ `Form` ใจๅŒๆง˜ใฎๆ–นๆณ•ใงใƒ•ใ‚กใ‚คใƒซใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} + +/// info | ๆƒ…ๅ ฑ + +`File` ใฏ `Form` ใ‚’็›ดๆŽฅ็ถ™ๆ‰ฟใ—ใŸใ‚ฏใƒฉใ‚นใงใ™ใ€‚ + +ใŸใ ใ—ใ€`fastapi` ใ‹ใ‚‰ `Query`ใ€`Path`ใ€`File` ใชใฉใ‚’ใ‚คใƒณใƒใƒผใƒˆใ™ใ‚‹ใจใใ€ใใ‚Œใ‚‰ใฏๅฎŸ้š›ใซใฏ็‰นๆฎŠใชใ‚ฏใƒฉใ‚นใ‚’่ฟ”ใ™้–ขๆ•ฐใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ•ใ‚กใ‚คใƒซใฎใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏ `File` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใใ†ใ—ใชใ„ใจใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏใ‚ฏใ‚จใƒชใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃ๏ผˆJSON๏ผ‰ใƒ‘ใƒฉใƒกใƒผใ‚ฟใจใ—ใฆ่งฃ้‡ˆใ•ใ‚Œใพใ™ใ€‚ + +/// + +ใƒ•ใ‚กใ‚คใƒซใฏใ€Œform dataใ€ใจใ—ใฆใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚ + +*path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅž‹ใ‚’ `bytes` ใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใจใ€**FastAPI** ใŒใƒ•ใ‚กใ‚คใƒซใ‚’่ชญใฟๅ–ใ‚Šใ€ๅ†…ๅฎนใ‚’ `bytes` ใจใ—ใฆๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏๅ†…ๅฎนๅ…จไฝ“ใŒใƒกใƒขใƒชใซไฟๆŒใ•ใ‚Œใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚ๅฐใ•ใชใƒ•ใ‚กใ‚คใƒซใซใฏๆœ‰ๅŠนใงใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ๅคšใใฎๅ ดๅˆใฏ `UploadFile` ใ‚’ไฝฟใ†ๆ–นใŒๆœ‰ๅˆฉใงใ™ใ€‚ + +## `UploadFile` ใซใ‚ˆใ‚‹ใƒ•ใ‚กใ‚คใƒซใƒ‘ใƒฉใƒกใƒผใ‚ฟ { #file-parameters-with-uploadfile } + +ๅž‹ใ‚’ `UploadFile` ใซใ—ใฆใƒ•ใ‚กใ‚คใƒซใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎš็พฉใ—ใพใ™: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} + +`UploadFile` ใ‚’ไฝฟใ†ใ“ใจใซใฏ `bytes` ใซๅฏพใ™ใ‚‹ๆฌกใฎๅˆฉ็‚นใŒใ‚ใ‚Šใพใ™: + +- ใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใซ `File()` ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +- ใ€Œspooledใ€ใƒ•ใ‚กใ‚คใƒซใ‚’ไฝฟใ„ใพใ™: + - ๆœ€ๅคงใ‚ตใ‚คใ‚บใพใงใฏใƒกใƒขใƒชใซไฟๆŒใ—ใ€ใใ‚Œใ‚’่ถ…ใˆใ‚‹ใจใƒ‡ใ‚ฃใ‚นใ‚ฏใซๆ ผ็ดใ•ใ‚Œใ‚‹ใƒ•ใ‚กใ‚คใƒซใงใ™ใ€‚ +- ใใฎใŸใ‚ใ€็”ปๅƒใƒปๅ‹•็”ปใƒปๅคงใใชใƒใ‚คใƒŠใƒชใชใฉใฎๅคงใใชใƒ•ใ‚กใ‚คใƒซใงใ‚‚ใ€ใƒกใƒขใƒชใ‚’ไฝฟใ„ๆžœใŸใ™ใ“ใจใชใใ†ใพใๅ‹•ไฝœใ—ใพใ™ใ€‚ +- ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚ŒใŸใƒ•ใ‚กใ‚คใƒซใ‹ใ‚‰ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใงใใพใ™ใ€‚ +- file-like ใช `async` ใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚’ๆŒใกใพใ™ใ€‚ +- ๅฎŸ้š›ใฎ Python ใฎ `SpooledTemporaryFile` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ…ฌ้–‹ใ—ใฆใŠใ‚Šใ€file-like ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆœŸๅพ…ใ™ใ‚‹ไป–ใฎใƒฉใ‚คใƒ–ใƒฉใƒชใซใใฎใพใพๆธกใ›ใพใ™ใ€‚ + +### `UploadFile` { #uploadfile } + +`UploadFile` ใซใฏๆฌกใฎๅฑžๆ€งใŒใ‚ใ‚Šใพใ™: + +- `filename`: ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ๆ™‚ใฎๅ…ƒใฎใƒ•ใ‚กใ‚คใƒซๅใ‚’่กจใ™ `str`๏ผˆไพ‹: `myimage.jpg`๏ผ‰ +- `content_type`: ใ‚ณใƒณใƒ†ใƒณใƒˆใ‚ฟใ‚คใƒ—๏ผˆMIME ใ‚ฟใ‚คใƒ— / ใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—๏ผ‰ใ‚’่กจใ™ `str`๏ผˆไพ‹: `image/jpeg`๏ผ‰ +- `file`: `SpooledTemporaryFile`๏ผˆfile-like ใชใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใ€‚ใ“ใ‚ŒใฏๅฎŸ้š›ใฎ Python ใฎใƒ•ใ‚กใ‚คใƒซใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใ€ใ€Œfile-likeใ€ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๆœŸๅพ…ใ™ใ‚‹้–ขๆ•ฐใ‚„ใƒฉใ‚คใƒ–ใƒฉใƒชใซ็›ดๆŽฅๆธกใ›ใพใ™ใ€‚ + +`UploadFile` ใซใฏๆฌกใฎ `async` ใƒกใ‚ฝใƒƒใƒ‰ใŒใ‚ใ‚Šใพใ™ใ€‚ใ„ใšใ‚Œใ‚‚ๅ†…้ƒจใงๅฏพๅฟœใ™ใ‚‹ใƒ•ใ‚กใ‚คใƒซใƒกใ‚ฝใƒƒใƒ‰๏ผˆๅ†…้ƒจใฎ `SpooledTemporaryFile`๏ผ‰ใ‚’ๅ‘ผใณๅ‡บใ—ใพใ™ใ€‚ + +- `write(data)`: `data`๏ผˆ`str` ใพใŸใฏ `bytes`๏ผ‰ใ‚’ๆ›ธใ่พผใฟใพใ™ใ€‚ +- `read(size)`: `size`๏ผˆ`int`๏ผ‰ใƒใ‚คใƒˆ/ๆ–‡ๅญ—ใ‚’่ชญใฟ่พผใฟใพใ™ใ€‚ +- `seek(offset)`: ใƒ•ใ‚กใ‚คใƒซๅ†…ใฎใƒใ‚คใƒˆไฝ็ฝฎ `offset`๏ผˆ`int`๏ผ‰ใซ็งปๅ‹•ใ—ใพใ™ใ€‚ + - ไพ‹: `await myfile.seek(0)` ใฏใƒ•ใ‚กใ‚คใƒซใฎๅ…ˆ้ ญใซ็งปๅ‹•ใ—ใพใ™ใ€‚ + - ไธ€ๅบฆ `await myfile.read()` ใ‚’ๅฎŸ่กŒใ—ใฆใ€ใ‚‚ใ†ไธ€ๅบฆๅ†…ๅฎนใ‚’่ชญใฟใŸใ„ๅ ดๅˆใซ็‰นใซไพฟๅˆฉใงใ™ใ€‚ +- `close()`: ใƒ•ใ‚กใ‚คใƒซใ‚’้–‰ใ˜ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฏใ™ในใฆ `async` ใƒกใ‚ฝใƒƒใƒ‰ใชใฎใงใ€`await` ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`async` ใฎ *path operation ้–ขๆ•ฐ* ๅ†…ใงใฏๆฌกใฎใ‚ˆใ†ใซๅ†…ๅฎนใ‚’ๅ–ๅพ—ใงใใพใ™: + +```Python +contents = await myfile.read() +``` + +้€šๅธธใฎ `def` ใฎ *path operation ้–ขๆ•ฐ* ๅ†…ใซใ„ใ‚‹ๅ ดๅˆใฏใ€`UploadFile.file` ใซ็›ดๆŽฅใ‚ขใ‚ฏใ‚ปใ‚นใงใใพใ™ใ€‚ไพ‹ใˆใฐ: + +```Python +contents = myfile.file.read() +``` + +/// note | `async` ใฎๆŠ€่ก“่ฉณ็ดฐ + +`async` ใƒกใ‚ฝใƒƒใƒ‰ใ‚’ไฝฟใ†ใจใ€**FastAPI** ใฏใƒ•ใ‚กใ‚คใƒซใƒกใ‚ฝใƒƒใƒ‰ใ‚’ใ‚นใƒฌใƒƒใƒ‰ใƒ—ใƒผใƒซใงๅฎŸ่กŒใ—ใ€ใใฎๅฎŒไบ†ใ‚’ๅพ…ๆฉŸใ—ใพใ™ใ€‚ + +/// + +/// note | Starlette ใฎๆŠ€่ก“่ฉณ็ดฐ + +**FastAPI** ใฎ `UploadFile` ใฏ **Starlette** ใฎ `UploadFile` ใ‚’็›ดๆŽฅ็ถ™ๆ‰ฟใ—ใฆใ„ใพใ™ใŒใ€**Pydantic** ใ‚„ FastAPI ใฎไป–ใฎ้ƒจๅˆ†ใจไบ’ๆ›ใซใ™ใ‚‹ใŸใ‚ใซๅฟ…่ฆใช่ฆ็ด ใ‚’่ฟฝๅŠ ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +## ใ€ŒForm Dataใ€ใจใฏ { #what-is-form-data } + +HTML ใƒ•ใ‚ฉใƒผใƒ ๏ผˆ`
`๏ผ‰ใŒใ‚ตใƒผใƒใƒผใซใƒ‡ใƒผใ‚ฟใ‚’้€ใ‚‹ๆ–นๆณ•ใฏใ€ใใฎใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆ้€šๅธธใ€Œ็‰นๅˆฅใชใ€ใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใ‚’็”จใ„ใ€JSON ใจใฏ็•ฐใชใ‚Šใพใ™ใ€‚ + +**FastAPI** ใฏ JSON ใงใฏใชใใ€้ฉๅˆ‡ใชๅ ดๆ‰€ใ‹ใ‚‰ใใฎใƒ‡ใƒผใ‚ฟใ‚’่ชญใฟๅ–ใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +ใƒ•ใ‚กใ‚คใƒซใ‚’ๅซใพใชใ„ๅ ดๅˆใ€ใƒ•ใ‚ฉใƒผใƒ ใ‹ใ‚‰ใฎใƒ‡ใƒผใ‚ฟใฏ้€šๅธธใ€Œใƒกใƒ‡ใ‚ฃใ‚ขใ‚ฟใ‚คใƒ—ใ€`application/x-www-form-urlencoded` ใงใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚ + +ใŸใ ใ—ใƒ•ใ‚ฉใƒผใƒ ใซใƒ•ใ‚กใ‚คใƒซใŒๅซใพใ‚Œใ‚‹ๅ ดๅˆใฏใ€`multipart/form-data` ใจใ—ใฆใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚`File` ใ‚’ไฝฟใ†ใจใ€**FastAPI** ใฏใƒœใƒ‡ใ‚ฃๅ†…ใฎๆญฃใ—ใ„้ƒจๅˆ†ใ‹ใ‚‰ใƒ•ใ‚กใ‚คใƒซใ‚’ๅ–ๅพ—ใ™ในใใงใ‚ใ‚‹ใจ่ช่ญ˜ใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰ใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใ‚„ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎ่ฉณ็ดฐใฏใ€MDN Web Docs ใฎ POST ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +/// warning | ๆณจๆ„ + +1 ใคใฎ *path operation* ใซ่ค‡ๆ•ฐใฎ `File` ใŠใ‚ˆใณ `Form` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใงใใพใ™ใŒใ€ๅŒๆ™‚ใซ JSON ใจใ—ใฆๅ—ใ‘ๅ–ใ‚‹ใ“ใจใ‚’ๆœŸๅพ…ใ™ใ‚‹ `Body` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ใƒชใ‚ฏใ‚จใ‚นใƒˆใฎใƒœใƒ‡ใ‚ฃใฏ `application/json` ใงใฏใชใ `multipart/form-data` ใงใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚Œใ‚‹ใŸใ‚ใงใ™ใ€‚ + +ใ“ใ‚Œใฏ **FastAPI** ใฎๅˆถ้™ใงใฏใชใใ€HTTP ใƒ—ใƒญใƒˆใ‚ณใƒซใฎไป•ๆง˜ใงใ™ใ€‚ + +/// + +## ไปปๆ„ใฎใƒ•ใ‚กใ‚คใƒซใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ { #optional-file-upload } + +ๆจ™ๆบ–ใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚’ไฝฟใ„ใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ `None` ใซ่จญๅฎšใ™ใ‚‹ใ“ใจใงใ€ใƒ•ใ‚กใ‚คใƒซใ‚’ไปปๆ„ใซใงใใพใ™: + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## ่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใคใใฎ `UploadFile` { #uploadfile-with-additional-metadata } + +ไพ‹ใˆใฐ่ฟฝๅŠ ใฎใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใ‚’่จญๅฎšใ™ใ‚‹ใŸใ‚ใซใ€`UploadFile` ใจไฝตใ›ใฆ `File()` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: + +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} + +## ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซใฎใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ { #multiple-file-uploads } + +ๅŒๆ™‚ใซ่ค‡ๆ•ฐใฎใƒ•ใ‚กใ‚คใƒซใ‚’ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใงใใพใ™ใ€‚ + +ใใ‚Œใ‚‰ใฏใ€Œform dataใ€ใง้€ไฟกใ•ใ‚Œใ‚‹ๅŒใ˜ใ€Œใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ€ใซ้–ข้€ฃไป˜ใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ + +ใใฎใŸใ‚ใซใฏใ€`bytes` ใพใŸใฏ `UploadFile` ใฎใƒชใ‚นใƒˆใ‚’ๅฎฃ่จ€ใ—ใพใ™: + +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} + +ๅฎฃ่จ€ใฉใŠใ‚Šใ€`bytes` ใพใŸใฏ `UploadFile` ใฎ `list` ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ + +/// note | ๆŠ€่ก“่ฉณ็ดฐ + +`from starlette.responses import HTMLResponse` ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +**FastAPI** ใฏๅˆฉไพฟๆ€งใฎใŸใ‚ใ€`starlette.responses` ใจๅŒใ˜ใ‚‚ใฎใ‚’ `fastapi.responses` ใจใ—ใฆๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ใŸใ ใ—ใ€ๅˆฉ็”จๅฏ่ƒฝใชใƒฌใ‚นใƒใƒณใ‚นใฎๅคšใใฏ Starlette ใ‹ใ‚‰็›ดๆŽฅๆไพ›ใ•ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// + +### ่ฟฝๅŠ ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟใคใใฎ่ค‡ๆ•ฐใƒ•ใ‚กใ‚คใƒซใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ { #multiple-file-uploads-with-additional-metadata } + +ๅ…ˆใปใฉใจๅŒๆง˜ใซใ€`UploadFile` ใซๅฏพใ—ใฆใ‚‚ `File()` ใ‚’ไฝฟใฃใฆ่ฟฝๅŠ ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’่จญๅฎšใงใใพใ™: + +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} + +## ใพใจใ‚ { #recap } + +ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใƒ•ใ‚กใ‚คใƒซใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใซใฏใ€`File`ใ€`bytes`ใ€`UploadFile` ใ‚’ไฝฟใ„ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/request-form-models.md b/docs/ja/docs/tutorial/request-form-models.md new file mode 100644 index 0000000000..071867964b --- /dev/null +++ b/docs/ja/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# ใƒ•ใ‚ฉใƒผใƒ ใƒขใƒ‡ใƒซ { #form-models } + +FastAPI ใงใฏใ€ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +ใƒ•ใ‚ฉใƒผใƒ ใ‚’ไฝฟใ†ใซใฏใ€ใพใš `python-multipart` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™ใ€‚ + +ใพใš [ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใ—ใฆๆœ‰ๅŠนๅŒ–ใ—ใ€ใใฎใ†ใˆใงใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใฆใใ ใ•ใ„ใ€‚ไพ‹ใˆใฐ: + +```console +$ pip install python-multipart +``` + +/// + +/// note | ๅ‚™่€ƒ + +ใ“ใ‚Œใฏ FastAPI ใƒใƒผใ‚ธใƒงใƒณ `0.113.0` ไปฅ้™ใงใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚๐Ÿค“ + +/// + +## ใƒ•ใ‚ฉใƒผใƒ ็”จใฎ Pydantic ใƒขใƒ‡ใƒซ { #pydantic-models-for-forms } + +ๅ—ใ‘ๅ–ใ‚ŠใŸใ„ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ **ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰** ใจใ—ใฆๆŒใค **Pydantic ใƒขใƒ‡ใƒซ** ใ‚’ๅฎฃ่จ€ใ—ใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ `Form` ใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใ ใ‘ใงใ™: + +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} + +**FastAPI** ใฏใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ **ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟ** ใ‹ใ‚‰ **ๅ„ใƒ•ใ‚ฃใƒผใƒซใƒ‰** ใฎใƒ‡ใƒผใ‚ฟใ‚’ **ๆŠฝๅ‡บ** ใ—ใ€ๅฎš็พฉใ—ใŸ Pydantic ใƒขใƒ‡ใƒซใจใ—ใฆๆธกใ—ใพใ™ใ€‚ + +## ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใง็ขบ่ช { #check-the-docs } + +`/docs` ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ UI ใง็ขบ่ชใงใใพใ™: + +
+ +
+ +## ่ฟฝๅŠ ใฎใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’็ฆๆญข { #forbid-extra-form-fields } + +ไธ€้ƒจใฎ็‰นๆฎŠใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚น๏ผˆใŠใใ‚‰ใใ‚ใพใ‚Šไธ€่ˆฌ็š„ใงใฏใ‚ใ‚Šใพใ›ใ‚“๏ผ‰ใงใฏใ€ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ Pydantic ใƒขใƒ‡ใƒซใงๅฎฃ่จ€ใ—ใŸใ‚‚ใฎใฎใฟใซ**ๅˆถ้™**ใ—ใ€**่ฟฝๅŠ **ใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’**็ฆๆญข**ใ—ใŸใ„ๅ ดๅˆใŒใ‚ใ‚Šใพใ™ใ€‚ + +/// note | ๅ‚™่€ƒ + +ใ“ใ‚Œใฏ FastAPI ใƒใƒผใ‚ธใƒงใƒณ `0.114.0` ไปฅ้™ใงใ‚ตใƒใƒผใƒˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚๐Ÿค“ + +/// + +Pydantic ใฎใƒขใƒ‡ใƒซ่จญๅฎšใงใ€`extra` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ `forbid` ใซใงใใพใ™: + +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} + +ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒไฝ™ๅˆ†ใชใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ—ใ‚ˆใ†ใจใ™ใ‚‹ใจใ€**ใ‚จใƒฉใƒผ**ใฎใƒฌใ‚นใƒใƒณใ‚นใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๆฌกใฎใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’้€ใ‚ใ†ใจใ—ใŸๅ ดๅˆ: + +- `username`: `Rick` +- `password`: `Portal Gun` +- `extra`: `Mr. Poopybutthole` + +ใƒ•ใ‚ฃใƒผใƒซใƒ‰ `extra` ใฏ่จฑๅฏใ•ใ‚Œใฆใ„ใชใ„ๆ—จใฎใ‚จใƒฉใƒผใƒฌใ‚นใƒใƒณใ‚นใŒ่ฟ”ใ•ใ‚Œใพใ™: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## ใพใจใ‚ { #summary } + +FastAPI ใงใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซ Pydantic ใƒขใƒ‡ใƒซใ‚’ไฝฟ็”จใงใใพใ™ใ€‚๐Ÿ˜Ž diff --git a/docs/ja/docs/tutorial/request-forms-and-files.md b/docs/ja/docs/tutorial/request-forms-and-files.md index 09e1277c8c..9a4e299e91 100644 --- a/docs/ja/docs/tutorial/request-forms-and-files.md +++ b/docs/ja/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## `File`ใจ`Form`ใฎใ‚คใƒณใƒใƒผใƒˆ { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## `File`ใจ`Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ { #define-file-and-form-parameters } ใƒ•ใ‚กใ‚คใƒซใ‚„ใƒ•ใ‚ฉใƒผใƒ ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฏ`Body`ใ‚„`Query`ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซไฝœๆˆใ—ใพใ™: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} ใƒ•ใ‚กใ‚คใƒซใจใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใจใ—ใฆใ‚ขใƒƒใƒ—ใƒญใƒผใƒ‰ใ•ใ‚Œใ€ใƒ•ใ‚กใ‚คใƒซใจใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ—ใ‘ๅ–ใ‚Šใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index 1bdc28670b..dda2a4bf7f 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart `fastapi`ใ‹ใ‚‰`Form`ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใพใ™: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## `Form`ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใฎๅฎš็พฉ { #define-form-parameters } `Body`ใ‚„`Query`ใฎๅ ดๅˆใจๅŒใ˜ใ‚ˆใ†ใซใƒ•ใ‚ฉใƒผใƒ ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ไฝœๆˆใ—ใพใ™: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} ไพ‹ใˆใฐใ€OAuth2ไป•ๆง˜ใŒไฝฟ็”จใงใใ‚‹ๆ–นๆณ•ใฎ๏ผ‘ใค๏ผˆใ€Œใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒ•ใƒญใƒผใ€ใจๅ‘ผใฐใ‚Œใ‚‹๏ผ‰ใงใฏใ€ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ`username`ใจ`password`ใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ -specใงใฏใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅๅ‰ใŒ`username`ใจ`password`ใงใ‚ใ‚‹ใ“ใจใจใ€JSONใงใฏใชใใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใ“ใจใ‚’่ฆๆฑ‚ใ—ใฆใ„ใพใ™ใ€‚ +ไป•ๆง˜ใงใฏใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅๅ‰ใŒๆญฃ็ขบใซ`username`ใจ`password`ใงใ‚ใ‚‹ใ“ใจใจใ€JSONใงใฏใชใใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆ้€ไฟกใ•ใ‚Œใ‚‹ใ“ใจใ‚’่ฆๆฑ‚ใ—ใฆใ„ใพใ™ใ€‚ `Form`ใงใฏ`Body`๏ผˆใŠใ‚ˆใณ`Query`ใ‚„`Path`ใ€`Cookie`๏ผ‰ใจๅŒใ˜่จญๅฎšใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ใ“ใ‚Œใซใฏใ€ใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใ€ไพ‹ใ€ใ‚จใ‚คใƒชใ‚ขใ‚น๏ผˆไพ‹ใˆใฐ`username`ใฎไปฃใ‚ใ‚Šใซ`user-name`๏ผ‰ใชใฉใŒๅซใพใ‚Œใพใ™ใ€‚ @@ -56,13 +56,13 @@ HTMLใƒ•ใ‚ฉใƒผใƒ ๏ผˆ`
`๏ผ‰ใŒใ‚ตใƒผใƒใซใƒ‡ใƒผใ‚ฟใ‚’้€ไฟกใ™ใ‚‹ๆ–น ใ—ใ‹ใ—ใ€ใƒ•ใ‚ฉใƒผใƒ ใŒใƒ•ใ‚กใ‚คใƒซใ‚’ๅซใ‚€ๅ ดๅˆใฏใ€`multipart/form-data`ใจใ—ใฆใ‚จใƒณใ‚ณใƒผใƒ‰ใ•ใ‚Œใพใ™ใ€‚ใƒ•ใ‚กใ‚คใƒซใฎๆ‰ฑใ„ใซใคใ„ใฆใฏๆฌกใฎ็ซ ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚ -ใ“ใ‚Œใ‚‰ใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใ‚„ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎ่ฉณ็ดฐใซใคใ„ใฆใฏใ€MDNใฎPOSTใฎใ‚ฆใ‚งใƒ–ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ +ใ“ใ‚Œใ‚‰ใฎใ‚จใƒณใ‚ณใƒผใƒ‡ใ‚ฃใƒณใ‚ฐใ‚„ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎ่ฉณ็ดฐใซใคใ„ใฆใฏใ€MDNใฎPOSTใฎใ‚ฆใ‚งใƒ–ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ /// /// warning | ๆณจๆ„ -*path operation*ใง่ค‡ๆ•ฐใฎ`Form`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใŒใ€JSONใจใ—ใฆๅ—ใ‘ๅ–ใ‚‹ใ“ใจใ‚’ๆœŸๅพ…ใ—ใฆใ„ใ‚‹`Body`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ใชใœใชใ‚‰ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฏ`application/json`ใฎไปฃใ‚ใ‚Šใซ`application/x-www-form-urlencoded`ใ‚’ไฝฟใฃใฆใƒœใƒ‡ใ‚ฃใ‚’ใ‚จใƒณใ‚ณใƒผใƒ‰ใ™ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ +*path operation*ใง่ค‡ๆ•ฐใฎ`Form`ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใŒใ€JSONใจใ—ใฆๅ—ใ‘ๅ–ใ‚‹ใ“ใจใ‚’ๆœŸๅพ…ใ—ใฆใ„ใ‚‹`Body`ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ใชใœใชใ‚‰ใ€ใƒชใ‚ฏใ‚จใ‚นใƒˆใฏ`application/x-www-form-urlencoded`ใฎไปฃใ‚ใ‚Šใซ`application/json`ใ‚’ไฝฟใฃใฆใƒœใƒ‡ใ‚ฃใ‚’ใ‚จใƒณใ‚ณใƒผใƒ‰ใ™ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ ใ“ใ‚Œใฏ **FastAPI**ใฎๅˆถ้™ใงใฏใชใใ€HTTPใƒ—ใƒญใƒˆใ‚ณใƒซใฎไธ€้ƒจใงใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/response-model.md b/docs/ja/docs/tutorial/response-model.md index 258eac8e67..07dc201233 100644 --- a/docs/ja/docs/tutorial/response-model.md +++ b/docs/ja/docs/tutorial/response-model.md @@ -41,7 +41,7 @@ FastAPIใฏใ“ใฎๆˆปใ‚Šๅ€คใฎๅž‹ใ‚’ไฝฟใฃใฆไปฅไธ‹ใ‚’่กŒใ„ใพใ™: /// note | ๅ‚™่€ƒ -`response_model`ใฏใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใƒกใ‚ฝใƒƒใƒ‰๏ผˆ`get`ใ€`post`ใชใฉ๏ผ‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ‚ใ‚‹ใ“ใจใซๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚ใ™ในใฆใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใฎใ‚ˆใ†ใซใ€*path operation ้–ขๆ•ฐ* ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ +`response_model`ใฏใ€Œใƒ‡ใ‚ณใƒฌใƒผใ‚ฟใ€ใƒกใ‚ฝใƒƒใƒ‰๏ผˆ`get`ใ€`post`ใชใฉ๏ผ‰ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใ™ใ€‚้–ขๆ•ฐใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚„ใƒœใƒ‡ใ‚ฃใชใฉใจใฏ้•ใ„ใ€*path operation ้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ /// @@ -183,7 +183,7 @@ Pydanticใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ใ‚‚ใฎใ‚’่ฟ”ใ—ใ€ใƒ„ใƒผใƒซ๏ผˆ ๆœ€ใ‚‚ไธ€่ˆฌ็š„ใชใ‚ฑใƒผใ‚นใฏใ€[้ซ˜ๅบฆใชใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงๅพŒ่ฟฐใ™ใ‚‹ใ€ŒResponseใ‚’็›ดๆŽฅ่ฟ”ใ™ใ€](../advanced/response-directly.md){.internal-link target=_blank}ๅ ดๅˆใงใ™ใ€‚ -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} ใ“ใฎใ‚ทใƒณใƒ—ใƒซใชใ‚ฑใƒผใ‚นใฏใ€ๆˆปใ‚Šๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใŒ `Response` ใฎใ‚ฏใƒฉใ‚น๏ผˆใพใŸใฏใ‚ตใƒ–ใ‚ฏใƒฉใ‚น๏ผ‰ใงใ‚ใ‚‹ใŸใ‚ใ€FastAPIใŒ่‡ชๅ‹•็š„ใซๅ‡ฆ็†ใ—ใพใ™ใ€‚ @@ -193,7 +193,7 @@ Pydanticใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ใ‚‚ใฎใ‚’่ฟ”ใ—ใ€ใƒ„ใƒผใƒซ๏ผˆ ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใง `Response` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} ใ“ใ‚Œใฏ `RedirectResponse` ใŒ `Response` ใฎใ‚ตใƒ–ใ‚ฏใƒฉใ‚นใงใ‚ใ‚Šใ€FastAPIใŒใ“ใฎใ‚ทใƒณใƒ—ใƒซใชใ‚ฑใƒผใ‚นใ‚’่‡ชๅ‹•ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใ€ๅŒๆง˜ใซๅ‹•ไฝœใ—ใพใ™ใ€‚ @@ -201,7 +201,7 @@ Pydanticใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ใ‚‚ใฎใ‚’่ฟ”ใ—ใ€ใƒ„ใƒผใƒซ๏ผˆ ใ—ใ‹ใ—ใ€Pydanticๅž‹ใจใ—ใฆๆœ‰ๅŠนใงใฏใชใ„ๅˆฅใฎไปปๆ„ใฎใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผˆไพ‹: ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ๏ผ‰ใ‚’่ฟ”ใ—ใ€้–ขๆ•ฐใงใใฎใ‚ˆใ†ใซใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ™ใ‚‹ใจใ€FastAPIใฏใใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‹ใ‚‰Pydanticใƒฌใ‚นใƒใƒณใ‚นใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ—ใ‚ˆใ†ใจใ—ใฆๅคฑๆ•—ใ—ใพใ™ใ€‚ -ๅŒๆง˜ใซใ€unionใฎใ‚ˆใ†ใซใ€่ค‡ๆ•ฐใฎๅž‹ใฎใ†ใก1ใคไปฅไธŠใŒPydanticๅž‹ใจใ—ใฆๆœ‰ๅŠนใงใชใ„ใ‚‚ใฎใ‚’ๅซใ‚€ๅ ดๅˆใ‚‚่ตทใ“ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐๆฌกใฏๅคฑๆ•—ใ—ใพใ™ ๐Ÿ’ฅ: +ๅŒๆง˜ใซใ€ใƒฆใƒ‹ใ‚ชใƒณใฎใ‚ˆใ†ใซใ€่ค‡ๆ•ฐใฎๅž‹ใฎใ†ใก1ใคไปฅไธŠใŒPydanticๅž‹ใจใ—ใฆๆœ‰ๅŠนใงใชใ„ใ‚‚ใฎใ‚’ๅซใ‚€ๅ ดๅˆใ‚‚่ตทใ“ใ‚Šใพใ™ใ€‚ไพ‹ใˆใฐๆฌกใฏๅคฑๆ•—ใ—ใพใ™ ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/ja/docs/tutorial/response-status-code.md b/docs/ja/docs/tutorial/response-status-code.md index d3c2194162..d4ac45da65 100644 --- a/docs/ja/docs/tutorial/response-status-code.md +++ b/docs/ja/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * etc. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | ๅ‚™่€ƒ @@ -74,7 +74,7 @@ HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ3ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณ ๅ…ˆใปใฉใฎไพ‹ใ‚’ใ‚‚ใ†ไธ€ๅบฆ่ฆ‹ใฆใฟใพใ—ใ‚‡ใ†: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201`ใฏใ€ŒไฝœๆˆๅฎŒไบ†ใ€ใฎใŸใ‚ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ใงใ™ใ€‚ @@ -82,7 +82,7 @@ HTTPใงใฏใ€ใƒฌใ‚นใƒใƒณใ‚นใฎไธ€้ƒจใจใ—ใฆ3ๆกใฎๆ•ฐๅญ—ใฎใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณ `fastapi.status`ใฎไพฟๅˆฉใชๅค‰ๆ•ฐใ‚’ๅˆฉ็”จใ™ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} ใใ‚Œใ‚‰ใฏๅ˜ใชใ‚‹ไพฟๅˆฉใชใ‚‚ใฎใงใ‚ใ‚Šใ€ๅŒใ˜็•ชๅทใ‚’ไฟๆŒใ—ใฆใ„ใพใ™ใ€‚ใ—ใ‹ใ—ใ€ใใฎๆ–นๆณ•ใงใฏใ‚จใƒ‡ใ‚ฃใ‚ฟใฎ่‡ชๅ‹•่ฃœๅฎŒใ‚’ไฝฟ็”จใ—ใฆใใ‚Œใ‚‰ใ‚’่ฆ‹ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/schema-extra-example.md b/docs/ja/docs/tutorial/schema-extra-example.md index e526685c2f..76a6b0f949 100644 --- a/docs/ja/docs/tutorial/schema-extra-example.md +++ b/docs/ja/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Pydanticใƒขใƒ‡ใƒซใง`Field()`ใ‚’ไฝฟใ†ๅ ดๅˆใ€่ฟฝๅŠ ใฎ`examples`ใ‚‚ๅฎฃ่จ€ใง ใ“ใฎๅ ดๅˆใ€examplesใฏใใฎใƒœใƒ‡ใ‚ฃใƒ‡ใƒผใ‚ฟใฎๅ†…้ƒจ**JSON Schema**ใฎไธ€้ƒจใซใชใ‚Šใพใ™ใ€‚ -ใใ‚Œใงใ‚‚ใ€ๅŸท็ญ†ๆ™‚็‚นใงใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฎ่กจ็คบใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใƒ„ใƒผใƒซใงใ‚ใ‚‹Swagger UIใฏใ€**JSON Schema**ๅ†…ใฎใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆ่ค‡ๆ•ฐใฎไพ‹ใ‚’่กจ็คบใ™ใ‚‹ใ“ใจใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ๅ›ž้ฟ็ญ–ใซใคใ„ใฆใฏไปฅไธ‹ใ‚’่ชญใ‚“ใงใใ ใ•ใ„ใ€‚ +ใใ‚Œใงใ‚‚ใ€ๅŸท็ญ†ๆ™‚็‚นใงใฏใ€ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆUIใฎ่กจ็คบใ‚’ๆ‹…ๅฝ“ใ™ใ‚‹ใƒ„ใƒผใƒซใงใ‚ใ‚‹Swagger UIใฏใ€**JSON Schema**ๅ†…ใฎใƒ‡ใƒผใ‚ฟใซๅฏพใ—ใฆ่ค‡ๆ•ฐใฎไพ‹ใ‚’่กจ็คบใ™ใ‚‹ใ“ใจใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚ใ—ใ‹ใ—ใ€ๅ›ž้ฟ็ญ–ใซใคใ„ใฆใฏไปฅไธ‹ใ‚’่ชญใ‚“ใงใใ ใ•ใ„ใ€‚ ### OpenAPIๅ›บๆœ‰ใฎ`examples` { #openapi-specific-examples } diff --git a/docs/ja/docs/tutorial/security/first-steps.md b/docs/ja/docs/tutorial/security/first-steps.md index 76ef04db8d..5bf04386a8 100644 --- a/docs/ja/docs/tutorial/security/first-steps.md +++ b/docs/ja/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ `main.py`ใซใ€ไธ‹่จ˜ใฎไพ‹ใ‚’ใ‚ณใƒ”ใƒผใ—ใพใ™: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## ๅฎŸ่กŒ { #run-it } @@ -132,7 +132,7 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ `OAuth2PasswordBearer` ใ‚ฏใƒฉใ‚นใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ๆ™‚ใซใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`tokenUrl`ใ‚’ๆธกใ—ใพใ™ใ€‚ใ“ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผใซใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ (ใƒฆใƒผใ‚ถใƒผใฎใƒ–ใƒฉใ‚ฆใ‚ถใงๅ‹•ไฝœใ™ใ‚‹ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰) ใŒใƒˆใƒผใ‚ฏใƒณใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซ`username`ใจ`password`ใ‚’้€ไฟกใ™ใ‚‹URLใ‚’ๆŒ‡ๅฎšใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -150,7 +150,7 @@ OAuth2ใฏใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใ‚„APIใŒใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ™ใ‚‹ใ‚ตใƒผใƒใƒผ /// info | ๆƒ…ๅ ฑ -้žๅธธใซๅŽณๆ ผใชใ€ŒPythonistaใ€ใงใ‚ใ‚Œใฐใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผๅใฎใ‚นใ‚ฟใ‚คใƒซใŒ`token_url`ใงใฏใชใ`tokenUrl`ใงใ‚ใ‚‹ใ“ใจใ‚’ๆฐ—ใซๅ…ฅใ‚‰ใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ +้žๅธธใซๅŽณๆ ผใชใ€ŒPythonistaใ€ใงใ‚ใ‚Œใฐใ€ใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผๅใฎใ‚นใ‚ฟใ‚คใƒซใŒ`tokenUrl`ใงใฏใชใ`token_url`ใงใ‚ใ‚‹ใ“ใจใ‚’ๆฐ—ใซๅ…ฅใ‚‰ใชใ„ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ ใใ‚ŒใฏOpenAPIไป•ๆง˜ใจๅŒใ˜ๅๅ‰ใ‚’ไฝฟ็”จใ—ใฆใ„ใ‚‹ใ‹ใ‚‰ใงใ™ใ€‚ใใฎใŸใ‚ใ€ใ“ใ‚Œใ‚‰ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใซใคใ„ใฆใ‚‚ใฃใจ่ชฟในใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ใใ‚Œใ‚’ใ‚ณใƒ”ใƒผใ—ใฆ่ฒผใ‚Šไป˜ใ‘ใ‚Œใฐใ€ใใ‚Œใซใคใ„ใฆใฎ่ฉณ็ดฐใชๆƒ…ๅ ฑใ‚’่ฆ‹ใคใ‘ใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚ @@ -170,7 +170,7 @@ oauth2_scheme(some, parameters) ใ“ใ‚Œใง`oauth2_scheme`ใ‚’`Depends`ใงไพๅญ˜้–ขไฟ‚ใซๆธกใ™ใ“ใจใŒใงใใพใ™ใ€‚ -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ใ“ใฎไพๅญ˜้–ขไฟ‚ใฏใ€*path operation ้–ขๆ•ฐ*ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใƒผ`token`ใซไปฃๅ…ฅใ•ใ‚Œใ‚‹`str`ใ‚’ๆไพ›ใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/security/get-current-user.md b/docs/ja/docs/tutorial/security/get-current-user.md index 39b97cca52..60378fd981 100644 --- a/docs/ja/docs/tutorial/security/get-current-user.md +++ b/docs/ja/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ ไธ€ใคๅ‰ใฎ็ซ ใงใฏใ€๏ผˆไพๅญ˜ๆ€งๆณจๅ…ฅใ‚ทใ‚นใƒ†ใƒ ใซๅŸบใฅใ„ใŸ๏ผ‰ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใฏใ€ *path operation ้–ขๆ•ฐ* ใซ `str` ใจใ—ใฆ `token` ใ‚’ไธŽใˆใฆใ„ใพใ—ใŸ: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ใ—ใ‹ใ—ใ€ใใ‚Œใฏใพใ ใใ‚“ใชใซๆœ‰็”จใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ diff --git a/docs/ja/docs/tutorial/security/index.md b/docs/ja/docs/tutorial/security/index.md index 14f2c8f448..b96021b7ff 100644 --- a/docs/ja/docs/tutorial/security/index.md +++ b/docs/ja/docs/tutorial/security/index.md @@ -1,4 +1,4 @@ -# ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๅ…ฅ้–€ +# ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๅ…ฅ้–€ { #security } ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ€่ช่จผใ€่ชๅฏใ‚’ๆ‰ฑใ†ใซใฏๅคšใใฎๆ–นๆณ•ใŒใ‚ใ‚Šใพใ™ใ€‚ @@ -10,11 +10,11 @@ ใ—ใ‹ใ—ใ€ใใฎๅ‰ใซใ€ใ„ใใคใ‹ใฎๅฐใ•ใชๆฆ‚ๅฟตใ‚’็ขบ่ชใ—ใพใ—ใ‚‡ใ†ใ€‚ -## ใŠๆ€ฅใŽใงใ™ใ‹๏ผŸ +## ใŠๆ€ฅใŽใงใ™ใ‹๏ผŸ { #in-a-hurry } ใ‚‚ใ—ใ€ใ“ใ‚Œใ‚‰ใฎ็”จ่ชžใซ่ˆˆๅ‘ณใŒใชใใ€ใƒฆใƒผใ‚ถใƒผๅใจใƒ‘ใ‚นใƒฏใƒผใƒ‰ใซๅŸบใฅใ่ช่จผใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚’**ไปŠใ™ใ**็ขบไฟใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€ๆฌกใฎ็ซ ใซ้€ฒใ‚“ใงใใ ใ•ใ„ใ€‚ -## OAuth2 +## OAuth2 { #oauth2 } OAuth2ใฏใ€่ช่จผใจ่ชๅฏใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใฎใ„ใใคใ‹ใฎๆ–นๆณ•ใ‚’ๅฎš็พฉใ—ใŸไป•ๆง˜ใงใ™ใ€‚ @@ -24,7 +24,7 @@ OAuth2ใฏใ€่ช่จผใจ่ชๅฏใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใฎใ„ใใคใ‹ใฎๆ–นๆณ•ใ‚’ๅฎš ใ“ใ‚ŒใŒใ€ใ€ŒFacebookใ€Googleใ€X (Twitter)ใ€GitHubใ‚’ไฝฟใฃใฆใƒญใ‚ฐใ‚คใƒณใ€ใ‚’ไฝฟ็”จใ—ใŸใ™ในใฆใฎใ‚ทใ‚นใƒ†ใƒ ใฎ่ƒŒๅพŒใงไฝฟใ‚ใ‚Œใฆใ„ใ‚‹ไป•็ต„ใฟใงใ™ใ€‚ -### OAuth 1 +### OAuth 1 { #oauth-1 } OAuth 1ใจใ„ใ†ใ‚‚ใฎใ‚‚ใ‚ใ‚Šใพใ—ใŸใŒใ€ใ“ใ‚ŒใฏOAuth2ใจใฏๅ…จใ็•ฐใชใ‚Šใ€้€šไฟกใ‚’ใฉใฎใ‚ˆใ†ใซๆš—ๅทๅŒ–ใ™ใ‚‹ใ‹ใจใ„ใ†ไป•ๆง˜ใŒ็›ดๆŽฅ็š„ใซๅซใพใ‚ŒใฆใŠใ‚Šใ€ใ‚ˆใ‚Š่ค‡้›‘ใชใ‚‚ใฎใจใชใฃใฆใ„ใพใ™ใ€‚ @@ -38,7 +38,7 @@ OAuth2ใฏใ€้€šไฟกใ‚’ๆš—ๅทๅŒ–ใ™ใ‚‹ๆ–นๆณ•ใ‚’ๆŒ‡ๅฎšใ›ใšใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ท /// -## OpenID Connect +## OpenID Connect { #openid-connect } OpenID Connectใฏใ€**OAuth2**ใ‚’ใƒ™ใƒผใ‚นใซใ—ใŸๅˆฅใฎไป•ๆง˜ใงใ™ใ€‚ @@ -48,7 +48,7 @@ OpenID Connectใฏใ€**OAuth2**ใ‚’ใƒ™ใƒผใ‚นใซใ—ใŸๅˆฅใฎไป•ๆง˜ใงใ™ใ€‚ ใ—ใ‹ใ—ใ€Facebookใฎใƒญใ‚ฐใ‚คใƒณใฏOpenID Connectใ‚’ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ›ใ‚“ใ€‚OAuth2ใ‚’็‹ฌ่‡ชใซใ‚ขใƒฌใƒณใ‚ธใ—ใฆใ„ใพใ™ใ€‚ -### OpenID (ใ€ŒOpenID Connectใ€ใงใฏใชใ„) +### OpenID (ใ€ŒOpenID Connectใ€ใงใฏใชใ„) { #openid-not-openid-connect } ใพใŸใ€ใ€ŒOpenIDใ€ใจใ„ใ†ไป•ๆง˜ใ‚‚ใ‚ใ‚Šใพใ—ใŸใ€‚ใใ‚Œใฏใ€**OpenID Connect**ใจๅŒใ˜ใ“ใจใ‚’่งฃๆฑบใ—ใ‚ˆใ†ใจใ—ใŸใ‚‚ใฎใงใ™ใŒใ€OAuth2ใซๅŸบใฅใ„ใฆใ„ใ‚‹ใ‚ใ‘ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚ @@ -56,7 +56,7 @@ OpenID Connectใฏใ€**OAuth2**ใ‚’ใƒ™ใƒผใ‚นใซใ—ใŸๅˆฅใฎไป•ๆง˜ใงใ™ใ€‚ ็พๅœจใงใฏใ‚ใพใ‚Šๆ™ฎๅŠใ—ใฆใ„ใพใ›ใ‚“ใ—ใ€ไฝฟใ‚ใ‚Œใฆใ‚‚ใ„ใพใ›ใ‚“ใ€‚ -## OpenAPI +## OpenAPI { #openapi } OpenAPI๏ผˆไปฅๅ‰ใฏSwaggerใจใ—ใฆ็Ÿฅใ‚‰ใ‚Œใฆใ„ใพใ—ใŸ๏ผ‰ใฏใ€APIใ‚’ๆง‹็ฏ‰ใ™ใ‚‹ใŸใ‚ใฎใ‚ชใƒผใƒ—ใƒณใชไป•ๆง˜ใงใ™๏ผˆ็พๅœจใฏLinux Foundationใฎไธ€้ƒจใซใชใฃใฆใ„ใพใ™๏ผ‰ใ€‚ @@ -97,7 +97,7 @@ Googleใ€Facebookใ€X (Twitter)ใ€GitHubใชใฉใ€ไป–ใฎ่ช่จผ/่ชๅฏใƒ—ใƒญใƒใ‚ค /// -## **FastAPI** ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ +## **FastAPI** ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ { #fastapi-utilities } FastAPIใฏ `fastapi.security` ใƒขใ‚ธใƒฅใƒผใƒซใฎไธญใงใ€ใ“ใ‚Œใ‚‰ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใ”ใจใซใ„ใใคใ‹ใฎใƒ„ใƒผใƒซใ‚’ๆไพ›ใ—ใ€ใ“ใ‚Œใ‚‰ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒกใ‚ซใƒ‹ใ‚บใƒ ใ‚’็ฐกๅ˜ใซไฝฟ็”จใงใใ‚‹ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/security/oauth2-jwt.md b/docs/ja/docs/tutorial/security/oauth2-jwt.md index 186936f1ba..0d6be90a24 100644 --- a/docs/ja/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ja/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # ใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผˆใŠใ‚ˆใณใƒใƒƒใ‚ทใƒฅๅŒ–๏ผ‰ใซใ‚ˆใ‚‹OAuth2ใ€JWTใƒˆใƒผใ‚ฏใƒณใซใ‚ˆใ‚‹Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -ใ“ใ‚Œใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎๆตใ‚ŒใŒๅ…จใฆใ‚ใ‹ใฃใŸใฎใงใ€JWTใƒˆใƒผใ‚ฏใƒณใจๅฎ‰ๅ…จใชใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚’ไฝฟ็”จใ—ใฆใ€ๅฎŸ้š›ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎ‰ๅ…จใซใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ +ใ“ใ‚Œใงใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใฎๆตใ‚ŒใŒๅ…จใฆใ‚ใ‹ใฃใŸใฎใงใ€JWTใƒˆใƒผใ‚ฏใƒณใจๅฎ‰ๅ…จใชใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚’ไฝฟ็”จใ—ใฆใ€ๅฎŸ้š›ใซใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใ‚’ๅฎ‰ๅ…จใซใ—ใฆใฟใพใ—ใ‚‡ใ†ใ€‚ ใ“ใฎใ‚ณใƒผใƒ‰ใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใงๅฎŸ้š›ใซไฝฟ็”จใ—ใŸใ‚Šใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅใ‚’ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซไฟๅญ˜ใ™ใ‚‹ใจใ„ใฃใŸ็”จ้€”ใซๅˆฉ็”จใงใใพใ™ใ€‚ @@ -116,7 +116,11 @@ pwdlibใฏbcryptใƒใƒƒใ‚ทใƒฅใ‚ขใƒซใ‚ดใƒชใ‚บใƒ ใ‚‚ใ‚ตใƒใƒผใƒˆใ—ใฆใ„ใพใ™ใŒ ใ•ใ‚‰ใซใ€ใƒฆใƒผใ‚ถใƒผใ‚’่ช่จผใ—ใฆ่ฟ”ใ™้–ขๆ•ฐใ‚‚ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +`authenticate_user` ใŒใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซๅญ˜ๅœจใ—ใชใ„ใƒฆใƒผใ‚ถใƒผๅใงๅ‘ผใณๅ‡บใ•ใ‚ŒใŸๅ ดๅˆใงใ‚‚ใ€ใƒ€ใƒŸใƒผใฎใƒใƒƒใ‚ทใƒฅใ‚’ไฝฟใฃใฆ `verify_password` ใ‚’ๅฎŸ่กŒใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใƒฆใƒผใ‚ถใƒผๅใŒๆœ‰ๅŠนใ‹ใฉใ†ใ‹ใซ้–ขใ‚ใ‚‰ใšใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใฎๅฟœ็ญ”ๆ™‚้–“ใŒใŠใŠใ‚ˆใๅŒใ˜ใซใชใ‚Šใ€ๆ—ขๅญ˜ใฎใƒฆใƒผใ‚ถใƒผๅใ‚’ๅˆ—ๆŒ™ใ™ใ‚‹ใŸใ‚ใซๆ‚ช็”จใ•ใ‚Œใ†ใ‚‹ใ€Œใ‚ฟใ‚คใƒŸใƒณใ‚ฐๆ”ปๆ’ƒใ€ใ‚’้˜ฒๆญขใงใใพใ™ใ€‚ /// note | ๅ‚™่€ƒ @@ -152,7 +156,7 @@ JWTใƒˆใƒผใ‚ฏใƒณใฎ็ฝฒๅใซไฝฟ็”จใ™ใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ `"HS256"`ใ‚’ๆŒ‡ๅฎšใ— ๆ–ฐใ—ใ„ใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’็”Ÿๆˆใ™ใ‚‹ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ้–ขๆ•ฐใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## ไพๅญ˜้–ขไฟ‚ใฎๆ›ดๆ–ฐ { #update-the-dependencies } @@ -162,7 +166,7 @@ JWTใƒˆใƒผใ‚ฏใƒณใฎ็ฝฒๅใซไฝฟ็”จใ™ใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ `"HS256"`ใ‚’ๆŒ‡ๅฎšใ— ใƒˆใƒผใ‚ฏใƒณใŒ็„กๅŠนใชๅ ดๅˆใฏใ€ใ™ใใซHTTPใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## `/token` *path operation* ใฎๆ›ดๆ–ฐ { #update-the-token-path-operation } @@ -170,7 +174,7 @@ JWTใƒˆใƒผใ‚ฏใƒณใฎ็ฝฒๅใซไฝฟ็”จใ™ใ‚‹ใ‚ขใƒซใ‚ดใƒชใ‚บใƒ `"HS256"`ใ‚’ๆŒ‡ๅฎšใ— ๅฎŸ้š›ใฎJWTใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใ‚’ไฝœๆˆใ—ใ€ใใ‚Œใ‚’่ฟ”ใ—ใพใ™ใ€‚ -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### JWTใฎใ€Œsubjectใ€`sub` ใซใคใ„ใฆใฎๆŠ€่ก“็š„ใช่ฉณ็ดฐ { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/ja/docs/tutorial/security/simple-oauth2.md b/docs/ja/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000..c371b0acf6 --- /dev/null +++ b/docs/ja/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใจBearerใซใ‚ˆใ‚‹ใ‚ทใƒณใƒ—ใƒซใชOAuth2 { #simple-oauth2-with-password-and-bearer } + +ๅ‰็ซ ใ‹ใ‚‰็™บๅฑ•ใ•ใ›ใฆใ€ๅฎŒๅ…จใชใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒ•ใƒญใƒผใซๅฟ…่ฆใชไธ่ถณ้ƒจๅˆ†ใ‚’่ฟฝๅŠ ใ—ใฆใ„ใใพใ™ใ€‚ + +## `username` ใจ `password` ใ‚’ๅ–ๅพ—ใ™ใ‚‹ { #get-the-username-and-password } + +`username` ใจ `password` ใ‚’ๅ–ๅพ—ใ™ใ‚‹ใŸใ‚ใซ **FastAPI** ใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟใ„ใพใ™ใ€‚ + +OAuth2 ใงใฏใ€ใ€Œpassword flowใ€๏ผˆใ“ใ“ใงไฝฟ็”จใ™ใ‚‹ใƒ•ใƒญใƒผ๏ผ‰ใ‚’ไฝฟใ†ๅ ดๅˆใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ/ใƒฆใƒผใ‚ถใƒผใฏใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใจใ—ใฆ `username` ใจ `password` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’้€ไฟกใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ—ใ‹ใ‚‚ใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ๅใฏใ“ใฎ้€šใ‚Šใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ใคใพใ‚Šใ€`user-name` ใ‚„ `email` ใงใฏๅ‹•ไฝœใ—ใพใ›ใ‚“ใ€‚ + +ใŸใ ใ—ใ€ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใงๆœ€็ต‚ใƒฆใƒผใ‚ถใƒผใซใฉใ†่กจ็คบใ™ใ‚‹ใ‹ใฏ่‡ช็”ฑใงใ™ใ€‚ + +ใพใŸใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒขใƒ‡ใƒซใงใฏไปปๆ„ใฎๅˆฅๅใ‚’ไฝฟใฃใฆๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +ใ—ใ‹ใ—ใ€ใƒญใ‚ฐใ‚คใƒณ็”จใฎ path operation ใงใฏใ€ไป•ๆง˜ใจใฎไบ’ๆ›ๆ€งใ‚’ไฟใค๏ผˆใŸใจใˆใฐ็ต„ใฟ่พผใฟใฎAPIใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใˆใ‚‹ใ‚ˆใ†ใซใ™ใ‚‹๏ผ‰ใŸใ‚ใซใ€ใ“ใ‚Œใ‚‰ใฎๅๅ‰ใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใพใŸใ€ไป•ๆง˜ใงใฏ `username` ใจ `password` ใฏใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใจใ—ใฆ้€ใ‚‰ใชใ‘ใ‚Œใฐใชใ‚‰ใชใ„๏ผˆใคใพใ‚Šใ€ใ“ใ“ใงใฏJSONใฏไฝฟใ‚ใชใ„๏ผ‰ใ“ใจใ‚‚ๅฎšใ‚ใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ + +### `scope` { #scope } + +ไป•ๆง˜ใงใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฏ่ฟฝๅŠ ใฎใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ€Œ`scope`ใ€ใ‚’้€ใ‚‹ใ“ใจใŒใงใใ‚‹ใจใ‚‚ๆ›ธใ‹ใ‚Œใฆใ„ใพใ™ใ€‚ + +ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ๅใฏ `scope`๏ผˆๅ˜ๆ•ฐๅฝข๏ผ‰ใงใ™ใŒใ€ๅฎŸๆ…‹ใฏใ‚นใƒšใƒผใ‚นๅŒบๅˆ‡ใ‚Šใฎใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ๆ–‡ๅญ—ๅˆ—ใ‚’ไธฆในใŸ้•ทใ„ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ + +ๅ„ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใฏ๏ผˆใ‚นใƒšใƒผใ‚นใ‚’ๅซใพใชใ„๏ผ‰ๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ + +้€šๅธธใ€็‰นๅฎšใฎใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃๆจฉ้™ใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใŸใ‚ใซไฝฟใ‚ใ‚Œใพใ™ใ€‚ไพ‹ใˆใฐ: + +- `users:read` ใ‚„ `users:write` ใฏใ‚ˆใใ‚ใ‚‹ไพ‹ใงใ™ใ€‚ +- `instagram_basic` ใฏ Facebook / Instagram ใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ +- `https://www.googleapis.com/auth/drive` ใฏ Google ใงไฝฟใ‚ใ‚Œใพใ™ใ€‚ + +/// info | ๆƒ…ๅ ฑ + +OAuth2 ใซใŠใ‘ใ‚‹ใ€Œใ‚นใ‚ณใƒผใƒ—ใ€ใฏใ€่ฆๆฑ‚ใ•ใ‚Œใ‚‹็‰นๅฎšใฎๆจฉ้™ใ‚’่กจใ™ๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ + +`:` ใฎใ‚ˆใ†ใชไป–ใฎๆ–‡ๅญ—ใ‚’ๅซใ‚“ใงใ„ใฆใ‚‚ใ€URL ใงใ‚ใฃใฆใ‚‚ๆง‹ใ„ใพใ›ใ‚“ใ€‚ + +ใใ‚Œใ‚‰ใฎ่ฉณ็ดฐใฏๅฎŸ่ฃ…ไพๅญ˜ใงใ™ใ€‚ + +OAuth2 ใซใจใฃใฆใฏๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—ใงใ™ใ€‚ + +/// + +## `username` ใจ `password` ใ‚’ๅ–ๅพ—ใ™ใ‚‹ใ‚ณใƒผใƒ‰ { #code-to-get-the-username-and-password } + +ใงใฏใ€ใ“ใ‚Œใ‚’ๅ‡ฆ็†ใ™ใ‚‹ใŸใ‚ใซ **FastAPI** ใŒๆไพ›ใ™ใ‚‹ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ไฝฟใ„ใพใ—ใ‚‡ใ†ใ€‚ + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +ใพใšใ€`OAuth2PasswordRequestForm` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใ€`/token` ใฎ path operation ใซ `Depends` ใงไพๅญ˜้–ขไฟ‚ใจใ—ใฆไฝฟใ„ใพใ™: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` ใฏๆฌกใฎใƒ•ใ‚ฉใƒผใƒ ใƒœใƒ‡ใ‚ฃใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ‚ฏใƒฉใ‚นไพๅญ˜้–ขไฟ‚ใงใ™: + +- `username` +- `password` +- ใ‚นใƒšใƒผใ‚นๅŒบๅˆ‡ใ‚Šใฎๆ–‡ๅญ—ๅˆ—ใงๆง‹ๆˆใ•ใ‚Œใ‚‹ใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `scope` ใƒ•ใ‚ฃใƒผใƒซใƒ‰ +- ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `grant_type` + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +OAuth2 ใฎไป•ๆง˜ใงใฏใ€ๅ›บๅฎšๅ€ค `password` ใ‚’ๆŒใคใƒ•ใ‚ฃใƒผใƒซใƒ‰ `grant_type` ใŒๅฎŸ้š›ใซใฏๅฟ…้ ˆใงใ™ใŒใ€`OAuth2PasswordRequestForm` ใฏใใ‚Œใ‚’ๅผทๅˆถใ—ใพใ›ใ‚“ใ€‚ + +ๅผทๅˆถใ—ใŸใ„ๅ ดๅˆใฏใ€`OAuth2PasswordRequestForm` ใฎไปฃใ‚ใ‚Šใซ `OAuth2PasswordRequestFormStrict` ใ‚’ไฝฟใฃใฆใใ ใ•ใ„ใ€‚ + +/// + +- ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `client_id`๏ผˆใ“ใฎไพ‹ใงใฏไธ่ฆ๏ผ‰ +- ใ‚ชใƒ—ใ‚ทใƒงใƒณใฎ `client_secret`๏ผˆใ“ใฎไพ‹ใงใฏไธ่ฆ๏ผ‰ + +/// info | ๆƒ…ๅ ฑ + +`OAuth2PasswordRequestForm` ใฏใ€`OAuth2PasswordBearer` ใฎใ‚ˆใ†ใซ **FastAPI** ใซใจใฃใฆ็‰นๅˆฅใชใ‚ฏใƒฉใ‚นใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +`OAuth2PasswordBearer` ใฏ **FastAPI** ใซใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚นใ‚ญใƒผใƒ ใงใ‚ใ‚‹ใ“ใจใ‚’่ช่ญ˜ใ•ใ›ใพใ™ใ€‚ใใฎใŸใ‚ OpenAPI ใซใใฎใ‚ˆใ†ใซ่ฟฝๅŠ ใ•ใ‚Œใพใ™ใ€‚ + +ไธ€ๆ–นใ€`OAuth2PasswordRequestForm` ใฏใ€ใ‚ใชใŸ่‡ช่บซใงใ‚‚ๆ›ธใ‘ใ‚‹ใ‚ˆใ†ใชๅ˜ใชใ‚‹ใ‚ฏใƒฉใ‚นไพๅญ˜้–ขไฟ‚ใงใ‚ใ‚Šใ€็›ดๆŽฅ `Form` ใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +ใŸใ ใ—ไธ€่ˆฌ็š„ใชใƒฆใƒผใ‚นใ‚ฑใƒผใ‚นใชใฎใงใ€็ฐกๅ˜ใซไฝฟใˆใ‚‹ใ‚ˆใ† **FastAPI** ใŒ็›ดๆŽฅๆไพ›ใ—ใฆใ„ใพใ™ใ€‚ + +/// + +### ใƒ•ใ‚ฉใƒผใƒ ใƒ‡ใƒผใ‚ฟใฎๅˆฉ็”จ { #use-the-form-data } + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไพๅญ˜้–ขไฟ‚ใ‚ฏใƒฉใ‚น `OAuth2PasswordRequestForm` ใฎใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใฏใ€ใ‚นใƒšใƒผใ‚นๅŒบๅˆ‡ใ‚Šใฎ้•ทใ„ๆ–‡ๅญ—ๅˆ—ใ‚’ๆŒใค `scope` ๅฑžๆ€งใฏๆŒใกใพใ›ใ‚“ใ€‚ไปฃใ‚ใ‚Šใซใ€้€ใ‚‰ใ‚ŒใฆใใŸๅ„ใ‚นใ‚ณใƒผใƒ—ใฎๅฎŸ้š›ใฎๆ–‡ๅญ—ๅˆ—ใƒชใ‚นใƒˆใ‚’ๆ ผ็ดใ™ใ‚‹ `scopes` ๅฑžๆ€งใ‚’ๆŒใกใพใ™ใ€‚ + +ใ“ใฎไพ‹ใงใฏ `scopes` ใฏไฝฟใ„ใพใ›ใ‚“ใŒใ€ๅฟ…่ฆใชใ‚‰ใใฎๆฉŸ่ƒฝใŒๅˆฉ็”จใงใใพใ™ใ€‚ + +/// + +ๆฌกใซใ€ใƒ•ใ‚ฉใƒผใƒ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎ `username` ใ‚’ไฝฟใฃใฆ๏ผˆ็–‘ไผผใฎ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ใƒฆใƒผใ‚ถใƒผใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ + +ใใฎใƒฆใƒผใ‚ถใƒผใŒๅญ˜ๅœจใ—ใชใ„ๅ ดๅˆใฏใ€ใ€ŒIncorrect username or passwordใ€ใจใ„ใ†ใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +ใ‚จใƒฉใƒผใซใฏ `HTTPException` ไพ‹ๅค–ใ‚’ไฝฟใ„ใพใ™: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎใƒใ‚งใƒƒใ‚ฏ { #check-the-password } + +ใ“ใฎๆ™‚็‚นใงใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ใƒฆใƒผใ‚ถใƒผใƒ‡ใƒผใ‚ฟใฏๅ–ๅพ—ใงใใพใ—ใŸใŒใ€ใพใ ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’็ขบ่ชใ—ใฆใ„ใพใ›ใ‚“ใ€‚ + +ใพใšใ€ใใฎใƒ‡ใƒผใ‚ฟใ‚’ Pydantic ใฎ `UserInDB` ใƒขใƒ‡ใƒซใซๅ…ฅใ‚Œใพใ™ใ€‚ + +ใƒ—ใƒฌใƒผใƒณใƒ†ใ‚ญใ‚นใƒˆใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฟๅญ˜ใ—ใฆใฏใ„ใ‘ใชใ„ใฎใงใ€๏ผˆ็–‘ไผผใฎ๏ผ‰ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅๅŒ–ใ‚ทใ‚นใƒ†ใƒ ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใŒไธ€่‡ดใ—ใชใ‘ใ‚Œใฐใ€ๅŒใ˜ใ‚จใƒฉใƒผใ‚’่ฟ”ใ—ใพใ™ใ€‚ + +#### ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅๅŒ– { #password-hashing } + +ใ€Œใƒใƒƒใ‚ทใƒฅๅŒ–ใ€ใจใฏใ€ใ‚ใ‚‹ๅ†…ๅฎน๏ผˆใ“ใ“ใงใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผ‰ใ‚’ใ€ไนฑ้›‘ใซ่ฆ‹ใˆใ‚‹ใƒใ‚คใƒˆๅˆ—๏ผˆๅ˜ใชใ‚‹ๆ–‡ๅญ—ๅˆ—๏ผ‰ใซๅค‰ๆ›ใ™ใ‚‹ใ“ใจใ‚’ๆŒ‡ใ—ใพใ™ใ€‚ + +ใพใฃใŸใๅŒใ˜ๅ†…ๅฎน๏ผˆใพใฃใŸใๅŒใ˜ใƒ‘ใ‚นใƒฏใƒผใƒ‰๏ผ‰ใ‚’ๆธกใ™ใจใ€ๆฏŽๅ›žใพใฃใŸใๅŒใ˜ไนฑ้›‘ใชๆ–‡ๅญ—ๅˆ—ใŒๅพ—ใ‚‰ใ‚Œใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ใใฎไนฑ้›‘ใชๆ–‡ๅญ—ๅˆ—ใ‹ใ‚‰ๅ…ƒใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใซๆˆปใ™ใ“ใจใฏใงใใพใ›ใ‚“ใ€‚ + +##### ใชใœใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ใƒใƒƒใ‚ทใƒฅๅŒ–ใ™ใ‚‹ใฎใ‹ { #why-use-password-hashing } + +ใ‚‚ใ—ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใŒ็›—ใพใ‚Œใฆใ‚‚ใ€็›—ใ‚“ใ ๅดใŒๆ‰‹ใซใ™ใ‚‹ใฎใฏใƒฆใƒผใ‚ถใƒผใฎใƒ—ใƒฌใƒผใƒณใƒ†ใ‚ญใ‚นใƒˆใฎใƒ‘ใ‚นใƒฏใƒผใƒ‰ใงใฏใชใใ€ใƒใƒƒใ‚ทใƒฅใ ใ‘ใงใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใ€็›—ใ‚“ใ ๅดใฏๅŒใ˜ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๅˆฅใฎใ‚ทใ‚นใƒ†ใƒ ใง่ฉฆใ™ใ“ใจใŒใงใใพใ›ใ‚“๏ผˆๅคšใใฎใƒฆใƒผใ‚ถใƒผใŒใ‚ใ‚‰ใ‚†ใ‚‹ๅ ดๆ‰€ใงๅŒใ˜ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ไฝฟใฃใฆใ„ใ‚‹ใŸใ‚ใ€ใ“ใ‚Œใฏๅฑ้™บใซใชใ‚Šๅพ—ใพใ™๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### `**user_dict` ใซใคใ„ใฆ { #about-user-dict } + +`UserInDB(**user_dict)` ใฏๆฌกใ‚’ๆ„ๅ‘ณใ—ใพใ™: + +`user_dict` ใฎใ‚ญใƒผใจๅ€คใ‚’ใ€ใใฎใพใพใ‚ญใƒผใƒฏใƒผใƒ‰ๅผ•ๆ•ฐใจใ—ใฆๆธกใ—ใพใ™ใ€‚ใคใพใ‚ŠๆฌกใจๅŒ็ญ‰ใงใ™: + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// info | ๆƒ…ๅ ฑ + +`**user_dict` ใฎใ‚ˆใ‚ŠๅฎŒๅ…จใช่งฃ่ชฌใฏใ€[**่ฟฝๅŠ ใƒขใƒ‡ใƒซ**ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ](../extra-models.md#about-user-in-dict){.internal-link target=_blank}ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +/// + +## ใƒˆใƒผใ‚ฏใƒณใ‚’่ฟ”ใ™ { #return-the-token } + +`token` ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใฎใƒฌใ‚นใƒใƒณใ‚นใฏ JSON ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใงใชใ‘ใ‚Œใฐใชใ‚Šใพใ›ใ‚“ใ€‚ + +`token_type` ใ‚’ๅซใ‚ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ“ใงใฏใ€ŒBearerใ€ใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟใ†ใฎใงใ€ใƒˆใƒผใ‚ฏใƒณใ‚ฟใ‚คใƒ—ใฏใ€Œ`bearer`ใ€ใงใ™ใ€‚ + +ใใ—ใฆ `access_token` ใ‚’ๅซใ‚ใ€ใใฎไธญใซใ‚ขใ‚ฏใ‚ปใ‚นใƒˆใƒผใ‚ฏใƒณใฎๆ–‡ๅญ—ๅˆ—ใ‚’ๅ…ฅใ‚Œใพใ™ใ€‚ + +ใ“ใฎๅ˜็ด”ใชไพ‹ใงใฏใ€ๅฎŒๅ…จใซๅฎ‰ๅ…จใงใฏใ‚ใ‚Šใพใ›ใ‚“ใŒใ€ใƒˆใƒผใ‚ฏใƒณใจใ—ใฆๅŒใ˜ `username` ใ‚’ใใฎใพใพ่ฟ”ใ—ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆฌกใฎ็ซ ใงใฏใ€ใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅๅŒ–ใจ JWT ใƒˆใƒผใ‚ฏใƒณใ‚’ไฝฟใฃใŸๆœฌๅฝ“ใซๅฎ‰ๅ…จใชๅฎŸ่ฃ…ใ‚’่ฆ‹ใพใ™ใ€‚ + +ใ—ใ‹ใ—ไปŠใฏใ€ๅฟ…่ฆใช็‰นๅฎšใฎ่ฉณ็ดฐใซ้›†ไธญใ—ใพใ—ใ‚‡ใ†ใ€‚ + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไป•ๆง˜ใซๅพ“ใ†ใจใ€ใ“ใฎไพ‹ใจๅŒใ˜ใ `access_token` ใจ `token_type` ใ‚’ๅซใ‚€ JSON ใ‚’่ฟ”ใ™ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏใ‚ใชใŸ่‡ช่บซใฎใ‚ณใƒผใƒ‰ใงๅฎŸ่ฃ…ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใ€ใ“ใ‚Œใ‚‰ใฎJSONใ‚ญใƒผใ‚’ไฝฟใฃใฆใ„ใ‚‹ใ“ใจใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚ + +ไป•ๆง˜ใซๆบ–ๆ‹ ใ™ใ‚‹ใŸใ‚ใซใ€ใ‚ใชใŸ่‡ช่บซใŒๆญฃใ—ใ่ฆšใˆใฆๅฎŸ่ฃ…ใ™ในใใ“ใจใฏใ€ใปใผใ“ใ‚Œใ ใ‘ใงใ™ใ€‚ + +ใใ‚Œไปฅๅค–ใฏ **FastAPI** ใŒ้ขๅ€’ใ‚’่ฆ‹ใฆใใ‚Œใพใ™ใ€‚ + +/// + +## ไพๅญ˜้–ขไฟ‚ใฎๆ›ดๆ–ฐ { #update-the-dependencies } + +ใ“ใ“ใงไพๅญ˜้–ขไฟ‚ใ‚’ๆ›ดๆ–ฐใ—ใพใ™ใ€‚ + +ใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒฆใƒผใ‚ถใƒผใฎๅ ดๅˆใซใฎใฟ `current_user` ใ‚’ๅ–ๅพ—ใ—ใŸใ„ใจใ—ใพใ™ใ€‚ + +ใใ“ใงใ€`get_current_user` ใ‚’ไพๅญ˜้–ขไฟ‚ใจใ—ใฆๅˆฉ็”จใ™ใ‚‹่ฟฝๅŠ ใฎไพๅญ˜้–ขไฟ‚ `get_current_active_user` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใ“ใ‚Œใ‚‰2ใคใฎไพๅญ˜้–ขไฟ‚ใฏใ€ใƒฆใƒผใ‚ถใƒผใŒๅญ˜ๅœจใ—ใชใ„ใ€ใพใŸใฏ้žใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใงใ‚ใ‚‹ๅ ดๅˆใซใ€HTTPใ‚จใƒฉใƒผใ‚’่ฟ”ใ™ใ ใ‘ใงใ™ใ€‚ + +ใ—ใŸใŒใฃใฆใ€ใ‚จใƒณใƒ‰ใƒใ‚คใƒณใƒˆใงใฏใ€ใƒฆใƒผใ‚ถใƒผใŒๅญ˜ๅœจใ—ใ€ๆญฃใ—ใ่ช่จผใ•ใ‚Œใ€ใ‹ใคใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใงใ‚ใ‚‹ๅ ดๅˆใซใฎใฟใ€ใƒฆใƒผใ‚ถใƒผใ‚’ๅ–ๅพ—ใ—ใพใ™: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// info | ๆƒ…ๅ ฑ + +ใ“ใ“ใง่ฟ”ใ—ใฆใ„ใ‚‹ๅ€คใŒ `Bearer` ใฎ่ฟฝๅŠ ใƒ˜ใƒƒใƒ€ใƒผ `WWW-Authenticate` ใ‚‚ไป•ๆง˜ใฎไธ€้ƒจใงใ™ใ€‚ + +HTTP๏ผˆใ‚จใƒฉใƒผ๏ผ‰ใ‚นใƒ†ใƒผใ‚ฟใ‚นใ‚ณใƒผใƒ‰ 401ใ€ŒUNAUTHORIZEDใ€ใฏใ€`WWW-Authenticate` ใƒ˜ใƒƒใƒ€ใƒผใ‚‚่ฟ”ใ™ใ“ใจใซใชใฃใฆใ„ใพใ™ใ€‚ + +ใƒ™ใ‚ขใƒฉใƒผใƒˆใƒผใ‚ฏใƒณ๏ผˆไปŠๅ›žใฎใ‚ฑใƒผใ‚น๏ผ‰ใฎๅ ดๅˆใ€ใใฎใƒ˜ใƒƒใƒ€ใƒผใฎๅ€คใฏ `Bearer` ใงใ‚ใ‚‹ในใใงใ™ใ€‚ + +ๅฎŸ้š›ใฎใจใ“ใ‚ใ€ใ“ใฎ่ฟฝๅŠ ใƒ˜ใƒƒใƒ€ใƒผใ‚’็œ็•ฅใ—ใฆใ‚‚ๅ‹•ไฝœใฏใ—ใพใ™ใ€‚ + +ใ—ใ‹ใ—ใ€ไป•ๆง˜ใซๆบ–ๆ‹ ใ™ใ‚‹ใŸใ‚ใซใ“ใ“ใงใฏไป˜ไธŽใ—ใฆใ„ใพใ™ใ€‚ + +ใพใŸใ€๏ผˆไปŠใพใŸใฏๅฐ†ๆฅ๏ผ‰ใใ‚Œใ‚’ๆƒณๅฎšใ—ใฆๅˆฉ็”จใ™ใ‚‹ใƒ„ใƒผใƒซใŒใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใšใ€ใ‚ใชใŸใ‚„ใƒฆใƒผใ‚ถใƒผใซใจใฃใฆๆœ‰็”จใซใชใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ“ใ‚ŒใŒๆจ™ๆบ–ใฎๅˆฉ็‚นใงใ™โ€ฆใ€‚ + +/// + +## ๅ‹•ไฝœ็ขบ่ช { #see-it-in-action } + +ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’้–‹ใใพใ™: http://127.0.0.1:8000/docsใ€‚ + +### ่ช่จผ { #authenticate } + +ใ€ŒAuthorizeใ€ใƒœใ‚ฟใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใพใ™ใ€‚ + +ๆฌกใฎ่ช่จผๆƒ…ๅ ฑใ‚’ไฝฟใ„ใพใ™: + +User: `johndoe` + +Password: `secret` + + + +ใ‚ทใ‚นใƒ†ใƒ ใง่ช่จผใ•ใ‚Œใ‚‹ใจใ€ๆฌกใฎใ‚ˆใ†ใซ่กจ็คบใ•ใ‚Œใพใ™: + + + +### ่‡ชๅˆ†ใฎใƒฆใƒผใ‚ถใƒผใƒ‡ใƒผใ‚ฟใ‚’ๅ–ๅพ— { #get-your-own-user-data } + +`GET` ใฎ path `/users/me` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใชใƒฆใƒผใ‚ถใƒผใƒ‡ใƒผใ‚ฟใŒๅ–ๅพ—ใงใใพใ™: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +้Œ ๅ‰ใ‚ขใ‚คใ‚ณใƒณใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆใƒญใ‚ฐใ‚ขใ‚ฆใƒˆใ—ใ€ๅŒใ˜ๆ“ไฝœใ‚’ๅ†ๅบฆ่ฉฆใ™ใจใ€ๆฌกใฎใ‚ˆใ†ใช HTTP 401 ใ‚จใƒฉใƒผใซใชใ‚Šใพใ™: + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### ้žใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใƒฆใƒผใ‚ถใƒผ { #inactive-user } + +ไปŠๅบฆใฏ้žใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒฆใƒผใ‚ถใƒผใง่ฉฆใ—ใฆใฟใพใ™ใ€‚ๆฌกใง่ช่จผใ—ใฆใใ ใ•ใ„: + +User: `alice` + +Password: `secret2` + +ใใ—ใฆ `GET` ใฎ path `/users/me` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +ๆฌกใฎใ‚ˆใ†ใชใ€ŒInactive userใ€ใ‚จใƒฉใƒผใซใชใ‚Šใพใ™: + +```JSON +{ + "detail": "Inactive user" +} +``` + +## ใพใจใ‚ { #recap } + +ใ“ใ‚Œใงใ€API ใฎใŸใ‚ใซ `username` ใจ `password` ใซๅŸบใฅใๅฎŒๅ…จใชใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹ใŸใ‚ใฎ้“ๅ…ทใŒๆƒใ„ใพใ—ใŸใ€‚ + +ใ“ใ‚Œใ‚‰ใฎ้“ๅ…ทใ‚’ไฝฟใˆใฐใ€ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ€ไปปๆ„ใฎใƒฆใƒผใ‚ถใƒผ/ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใจไบ’ๆ›ๆ€งใฎใ‚ใ‚‹ใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใ‚ทใ‚นใƒ†ใƒ ใ‚’ๆง‹็ฏ‰ใงใใพใ™ใ€‚ + +ใŸใ ใ—ใ€ๅฎŸ้š›ใซใฏใพใ ใ€Œๅฎ‰ๅ…จใ€ใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ๆฌกใฎ็ซ ใงใฏใ€ๅฎ‰ๅ…จใชใƒ‘ใ‚นใƒฏใƒผใƒ‰ใƒใƒƒใ‚ทใƒฅใƒฉใ‚คใƒ–ใƒฉใƒชใจ JWT ใƒˆใƒผใ‚ฏใƒณใฎไฝฟใ„ๆ–นใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ diff --git a/docs/ja/docs/tutorial/sql-databases.md b/docs/ja/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..930e433de4 --- /dev/null +++ b/docs/ja/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL๏ผˆใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น { #sql-relational-databases } + +FastAPI ใฏ SQL๏ผˆใƒชใƒฌใƒผใ‚ทใƒงใƒŠใƒซ๏ผ‰ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎไฝฟ็”จใ‚’ๅฟ…้ ˆใซใฏใ—ใพใ›ใ‚“ใ€‚ๅฟ…่ฆใงใ‚ใ‚Œใฐใ€ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚’ไฝฟ็”จใงใใพใ™ใ€‚ + +ใ“ใ“ใงใฏ SQLModel ใ‚’ไฝฟใฃใŸไพ‹ใ‚’่ฆ‹ใฆใ„ใใพใ™ใ€‚ + +SQLModel ใฏ SQLAlchemy ใจ Pydantic ใฎไธŠใซๆง‹็ฏ‰ใ•ใ‚Œใฆใ„ใพใ™ใ€‚FastAPI ใจๅŒใ˜ไฝœ่€…ใซใ‚ˆใ‚Šใ€SQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚’ไฝฟใ†ๅฟ…่ฆใŒใ‚ใ‚‹ FastAPI ใ‚ขใƒ—ใƒชใซๆœ€้ฉใซใชใ‚‹ใ‚ˆใ†ใซไฝœใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไป–ใฎไปปๆ„ใฎ SQL ใ‚ใ‚‹ใ„ใฏ NoSQL ใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒฉใ‚คใƒ–ใƒฉใƒช๏ผˆๅ ดๅˆใซใ‚ˆใฃใฆใฏ "ORMs" ใจๅ‘ผใฐใ‚Œใพใ™๏ผ‰ใ‚’ไฝฟใ†ใ“ใจใ‚‚ใงใใพใ™ใ€‚FastAPI ใฏไฝ•ใ‚‚ๅผทๅˆถใ—ใพใ›ใ‚“ใ€‚๐Ÿ˜Ž + +/// + +SQLModel ใฏ SQLAlchemy ใ‚’ใƒ™ใƒผใ‚นใซใ—ใฆใ„ใ‚‹ใŸใ‚ใ€SQLAlchemy ใŒใ‚ตใƒใƒผใƒˆใ™ใ‚‹ไปปๆ„ใฎใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น๏ผˆSQLModel ใ‹ใ‚‰ใ‚‚ใ‚ตใƒใƒผใƒˆใ•ใ‚Œใพใ™๏ผ‰ใ‚’็ฐกๅ˜ใซไฝฟใˆใพใ™ใ€‚ไพ‹ใˆใฐ: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server ใชใฉ + +ใ“ใฎไพ‹ใงใฏใ€ๅ˜ไธ€ใƒ•ใ‚กใ‚คใƒซใงๅ‹•ไฝœใ—ใ€Python ใซ็ตฑๅˆใ‚ตใƒใƒผใƒˆใŒใ‚ใ‚‹ใŸใ‚ใ€SQLite ใ‚’ไฝฟใ„ใพใ™ใ€‚ใคใพใ‚Šใ€ใ“ใฎไพ‹ใ‚’ใใฎใพใพใ‚ณใƒ”ใƒผใ—ใฆๅฎŸ่กŒใงใใพใ™ใ€‚ + +ๆœฌ็•ชใ‚ขใƒ—ใƒชใงใฏใ€PostgreSQL ใฎใ‚ˆใ†ใชใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ตใƒผใƒใƒผใ‚’ไฝฟใ„ใŸใใชใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใพใ›ใ‚“ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใƒ•ใƒญใƒณใƒˆใ‚จใƒณใƒ‰ใ‚„ใใฎไป–ใฎใƒ„ใƒผใƒซใ‚’ๅซใ‚€ใ€FastAPI ใจ PostgreSQL ใฎๅ…ฌๅผใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใ‚ธใ‚งใƒใƒฌใƒผใ‚ฟใƒผใŒใ‚ใ‚Šใพใ™: https://github.com/fastapi/full-stack-fastapi-template + +/// + +ใ“ใ‚Œใฏใจใฆใ‚‚ใ‚ทใƒณใƒ—ใƒซใง็Ÿญใ„ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซใงใ™ใ€‚ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚„ SQLใ€ใ‚ˆใ‚Š้ซ˜ๅบฆใชๆฉŸ่ƒฝใซใคใ„ใฆๅญฆใณใŸใ„ๅ ดๅˆใฏใ€SQLModel ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚ + +## `SQLModel` ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ { #install-sqlmodel } + +ใพใšใฏ [ไปฎๆƒณ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank} ใ‚’ไฝœๆˆใƒปๆœ‰ๅŠนๅŒ–ใ—ใ€`sqlmodel` ใ‚’ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใพใ™: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## ๅ˜ไธ€ใƒขใƒ‡ใƒซใงใ‚ขใƒ—ใƒชไฝœๆˆ { #create-the-app-with-a-single-model } + +ใพใšใฏๆœ€ใ‚‚็ฐกๅ˜ใชใ€ๅ˜ไธ€ใฎ SQLModel ใƒขใƒ‡ใƒซใ ใ‘ใ‚’ไฝฟใ†ใƒใƒผใ‚ธใƒงใƒณใ‚’ไฝœใ‚Šใพใ™ใ€‚ + +ๅพŒใงใ€ไธ‹่จ˜ใฎใจใŠใ‚Š่ค‡ๆ•ฐใƒขใƒ‡ใƒซใซใ—ใฆใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจๆฑŽ็”จๆ€งใ‚’้ซ˜ใ‚ใพใ™ใ€‚๐Ÿค“ + +### ใƒขใƒ‡ใƒซใฎไฝœๆˆ { #create-models } + +`SQLModel` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ—ใฆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ—ใพใ™: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +`Hero` ใ‚ฏใƒฉใ‚นใฏ Pydantic ใƒขใƒ‡ใƒซใซใ‚ˆใไผผใฆใ„ใพใ™๏ผˆๅฎŸ้š›ใซใฏๅ†…้ƒจ็š„ใซ Pydantic ใƒขใƒ‡ใƒซใงใ‚‚ใ‚ใ‚Šใพใ™๏ผ‰ใ€‚ + +ใ„ใใคใ‹ใฎ้•ใ„ใŒใ‚ใ‚Šใพใ™: + +* `table=True` ใฏ SQLModel ใซๅฏพใ—ใฆใ€Œใ“ใ‚Œใฏใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซใงใ‚ใ‚Šใ€SQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ†ใƒผใƒ–ใƒซใ‚’่กจใ™ใ€‚ๅ˜ใชใ‚‹ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซ๏ผˆ้€šๅธธใฎ Pydantic ใ‚ฏใƒฉใ‚น๏ผ‰ใงใฏใชใ„ใ€ใจไผใˆใพใ™ใ€‚ + +* `Field(primary_key=True)` ใฏ `id` ใŒ SQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ—ใƒฉใ‚คใƒžใƒชใ‚ญใƒผใงใ‚ใ‚‹ใ“ใจใ‚’ SQLModel ใซไผใˆใพใ™๏ผˆSQL ใฎใƒ—ใƒฉใ‚คใƒžใƒชใ‚ญใƒผใซใคใ„ใฆใฏ SQLModel ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„๏ผ‰ใ€‚ + + ๆณจ: ใƒ—ใƒฉใ‚คใƒžใƒชใ‚ญใƒผใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซใฏ `int | None` ใ‚’ไฝฟใฃใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใฏ Python ใ‚ณใƒผใƒ‰ๅ†…ใง `id=None` ใฎใ‚ˆใ†ใซใ€Œ`id` ใชใ—ใงใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ไฝœๆˆใ€ใ—ใ€ไฟๅญ˜ๆ™‚ใซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใŒ็”Ÿๆˆใ™ใ‚‹ใ“ใจใ‚’ๆƒณๅฎšใ™ใ‚‹ใŸใ‚ใงใ™ใ€‚SQLModel ใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใŒ `id` ใ‚’ๆไพ›ใ™ใ‚‹ใ“ใจใ‚’็†่งฃใ—ใ€ใ‚นใ‚ญใƒผใƒžใงใฏใ€ŒNULL ไธๅฏใฎ `INTEGER` ๅˆ—ใ€ใ‚’ๅฎš็พฉใ—ใพใ™ใ€‚่ฉณ็ดฐใฏ SQLModel ใฎใƒ—ใƒฉใ‚คใƒžใƒชใ‚ญใƒผใซ้–ขใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ ใ‚’ๅ‚็…งใ—ใฆใใ ใ•ใ„ใ€‚ + +* `Field(index=True)` ใฏใ€ใ“ใฎๅˆ—ใซๅฏพใ—ใฆ SQL ใฎใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใ‚’ไฝœๆˆใ™ใ‚‹ใ‚ˆใ† SQLModel ใซๆŒ‡็คบใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ“ใฎๅˆ—ใงใƒ•ใ‚ฃใƒซใ‚ฟใ—ใฆใƒ‡ใƒผใ‚ฟใ‚’่ชญใ‚€ๅ ดๅˆใซๆคœ็ดขใŒ้ซ˜้€Ÿใซใชใ‚Šใพใ™ใ€‚ + + `str` ใจๅฎฃ่จ€ใ•ใ‚ŒใŸใ‚‚ใฎใฏใ€SQL ใฎ `TEXT`๏ผˆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซใ‚ˆใฃใฆใฏ `VARCHAR`๏ผ‰ๅž‹ใฎๅˆ—ใซใชใ‚‹ใ“ใจใ‚’ SQLModel ใฏ็†่งฃใ—ใพใ™ใ€‚ + +### Engine ใฎไฝœๆˆ { #create-an-engine } + +SQLModel ใฎ `engine`๏ผˆๅ†…้ƒจ็š„ใซใฏ SQLAlchemy ใฎ `engine`๏ผ‰ใฏใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใธใฎๆŽฅ็ถšใ‚’ไฟๆŒใ—ใพใ™ใ€‚ + +ๅŒใ˜ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซๆŽฅ็ถšใ™ใ‚‹ใŸใ‚ใซใ€ใ‚ณใƒผใƒ‰ๅ…จไฝ“ใง 1 ใคใฎ `engine` ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆใ‚’ๅ…ฑๆœ‰ใ—ใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +`check_same_thread=False` ใ‚’ไฝฟใ†ใจใ€FastAPI ใŒ็•ฐใชใ‚‹ใ‚นใƒฌใƒƒใƒ‰ใงๅŒใ˜ SQLite ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚’ไฝฟใˆใ‚‹ใ‚ˆใ†ใซใชใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€ไพๅญ˜้–ขไฟ‚ใชใฉใซใ‚ˆใ‚Š 1 ใคใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใŒ่ค‡ๆ•ฐใ‚นใƒฌใƒƒใƒ‰ใ‚’ไฝฟใ†ๅฏ่ƒฝๆ€งใŒใ‚ใ‚‹ใŸใ‚ใ€ๅฟ…่ฆใงใ™ใ€‚ + +ๅฟƒ้…ใฏใ„ใ‚Šใพใ›ใ‚“ใ€‚ใ“ใฎใ‚ณใƒผใƒ‰ใฎๆง‹ๆˆใงใฏใ€ๅพŒใงใ€Œ1 ใƒชใ‚ฏใ‚จใ‚นใƒˆใซใคใ 1 ใคใฎ SQLModel ใ‚ปใƒƒใ‚ทใƒงใƒณใ€ใ‚’็ขบๅฎŸใซไฝฟใ†ใ‚ˆใ†ใซใ—ใพใ™ใ€‚ๅฎŸ้š›ใ€`check_same_thread` ใฏใใ‚Œใ‚’ๅฎŸ็พใ—ใ‚ˆใ†ใจใ—ใฆใ„ใพใ™ใ€‚ + +### ใƒ†ใƒผใƒ–ใƒซใฎไฝœๆˆ { #create-the-tables } + +`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` ใ‚’ๆไพ›ใ™ใ‚‹ใ€`yield` ใ‚’ไฝฟใฃใŸ FastAPI ใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€1 ใƒชใ‚ฏใ‚จใ‚นใƒˆใซใคใ 1 ใคใฎใ‚ปใƒƒใ‚ทใƒงใƒณใ‚’ไฝฟใ†ใ“ใจใŒไฟ่จผใ•ใ‚Œใพใ™ใ€‚๐Ÿค“ + +็ถšใ„ใฆใ€ใ“ใฎไพๅญ˜้–ขไฟ‚ใ‚’ไฝฟใ†ใ‚ณใƒผใƒ‰ใ‚’็ฐกๆฝ”ใซใ™ใ‚‹ใŸใ‚ใซใ€`Annotated` ใซใ‚ˆใ‚‹ไพๅญ˜้–ขไฟ‚ `SessionDep` ใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### ่ตทๅ‹•ๆ™‚ใซใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœๆˆ { #create-database-tables-on-startup } + +ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่ตทๅ‹•ๆ™‚ใซใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +ใ“ใ“ใงใฏใ€ใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฎใ‚นใ‚ฟใƒผใƒˆใ‚ขใƒƒใƒ—ใ‚คใƒ™ใƒณใƒˆใงใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœๆˆใ—ใฆใ„ใพใ™ใ€‚ + +ๆœฌ็•ชใงใฏใ€ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ™ใ‚‹ๅ‰ใซใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ‚นใ‚ฏใƒชใƒ—ใƒˆใ‚’ๅฎŸ่กŒใ™ใ‚‹ใฎใŒไธ€่ˆฌ็š„ใงใ—ใ‚‡ใ†ใ€‚๐Ÿค“ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +SQLModel ใฏ Alembic ใ‚’ใƒฉใƒƒใƒ—ใ—ใŸใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใ‚’ๆไพ›ไบˆๅฎšใงใ™ใŒใ€็พๆ™‚็‚นใงใฏ Alembic ใ‚’็›ดๆŽฅไฝฟใˆใพใ™ใ€‚ + +/// + +### Hero ใฎไฝœๆˆ { #create-a-hero } + +ๅ„ SQLModel ใƒขใƒ‡ใƒซใฏ Pydantic ใƒขใƒ‡ใƒซใงใ‚‚ใ‚ใ‚‹ใŸใ‚ใ€Pydantic ใƒขใƒ‡ใƒซใจๅŒใ˜ใ‚ˆใ†ใซๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใงไฝฟใˆใพใ™ใ€‚ + +ไพ‹ใˆใฐใ€`Hero` ๅž‹ใฎใƒ‘ใƒฉใƒกใƒผใ‚ฟใ‚’ๅฎฃ่จ€ใ™ใ‚‹ใจใ€JSON ใƒœใƒ‡ใ‚ฃใ‹ใ‚‰่ชญใฟ่พผใพใ‚Œใพใ™ใ€‚ + +ๅŒๆง˜ใซใ€้–ขๆ•ฐใฎๆˆปใ‚Šๅ€คใฎๅž‹ใจใ—ใฆๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใใฎใƒ‡ใƒผใ‚ฟๅฝข็ŠถใŒ่‡ชๅ‹• API ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใฎ UI ใซ่กจ็คบใ•ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +ใ“ใ“ใงใฏ `SessionDep` ไพๅญ˜้–ขไฟ‚๏ผˆ`Session`๏ผ‰ใ‚’ไฝฟใฃใฆใ€ๆ–ฐใ—ใ„ `Hero` ใ‚’ `Session` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใซ่ฟฝๅŠ ใ—ใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซใ‚ณใƒŸใƒƒใƒˆใ—ใ€`hero` ใฎใƒ‡ใƒผใ‚ฟใ‚’ใƒชใƒ•ใƒฌใƒƒใ‚ทใƒฅใ—ใฆใ‹ใ‚‰่ฟ”ใ—ใพใ™ใ€‚ + +### Hero ใฎๅ–ๅพ— { #read-heroes } + +`select()` ใ‚’ไฝฟใฃใฆใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‹ใ‚‰ `Hero` ใ‚’ๅ–ๅพ—ใงใใพใ™ใ€‚็ตๆžœใฎใƒšใƒผใ‚ธใƒใƒผใ‚ทใƒงใƒณใฎใŸใ‚ใซ `limit` ใจ `offset` ใ‚’ๅซใ‚ใ‚‰ใ‚Œใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### ๅ˜ไธ€ใฎ Hero ใ‚’ๅ–ๅพ— { #read-one-hero } + +ๅ˜ไธ€ใฎ `Hero` ใ‚’ๅ–ๅพ—ใงใใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Hero ใฎๅ‰Š้™ค { #delete-a-hero } + +`Hero` ใ‚’ๅ‰Š้™คใ™ใ‚‹ใ“ใจใ‚‚ใงใใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### ใ‚ขใƒ—ใƒชใฎ่ตทๅ‹• { #run-the-app } + +ใ‚ขใƒ—ใƒชใ‚’่ตทๅ‹•ใ—ใพใ™: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ใใฎๅพŒ `/docs` ใฎ UI ใซใ‚ขใ‚ฏใ‚ปใ‚นใ™ใ‚‹ใจใ€FastAPI ใŒใ“ใ‚Œใ‚‰ใฎใƒขใƒ‡ใƒซใ‚’ไฝฟใฃใฆ API ใ‚’ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆๅŒ–ใ—ใ€ๅŒๆ™‚ใซใƒ‡ใƒผใ‚ฟใฎใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใจใƒใƒชใƒ‡ใƒผใ‚ทใƒงใƒณใซใ‚‚ไฝฟใฃใฆใ„ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚ + +
+ +
+ +## ่ค‡ๆ•ฐใƒขใƒ‡ใƒซใงใ‚ขใƒ—ใƒชใ‚’ๆ›ดๆ–ฐ { #update-the-app-with-multiple-models } + +ใ“ใ“ใงใ€ๅฐ‘ใ—ใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐใ—ใฆใ‚ปใ‚ญใƒฅใƒชใƒ†ใ‚ฃใจๆฑŽ็”จๆ€งใ‚’้ซ˜ใ‚ใพใ—ใ‚‡ใ†ใ€‚ + +ๅ‰ใฎใ‚ขใƒ—ใƒชใงใฏใ€UI ไธŠใงใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒไฝœๆˆใ™ใ‚‹ `Hero` ใฎ `id` ใ‚’่‡ชๅˆ†ใงๆฑบใ‚ใ‚‰ใ‚Œใฆใ—ใพใ„ใพใ™ใ€‚๐Ÿ˜ฑ + +ใใ‚Œใฏ่จฑๅฏใ™ในใใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใ™ใงใซ DB ใงๅ‰ฒใ‚Šๅฝ“ใฆๆธˆใฟใฎ `id` ใ‚’ไธŠๆ›ธใใ•ใ‚Œใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚`id` ใฎๆฑบๅฎšใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใงใฏใชใใ€ใƒใƒƒใ‚ฏใ‚จใƒณใƒ‰ใพใŸใฏใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใŒ่กŒใ†ในใใงใ™ใ€‚ + +ใ•ใ‚‰ใซใ€`secret_name` ใ‚’ไฝœใฃใฆใ„ใพใ™ใŒใ€็พ็Šถใงใฏใใ‚Œใ‚’ใฉใ“ใงใ‚‚่ฟ”ใ—ใฆใ—ใพใฃใฆใ„ใพใ™ใ€‚ใ“ใ‚Œใงใฏใ‚ใพใ‚Šใ€Œใ‚ทใƒผใ‚ฏใƒฌใƒƒใƒˆใ€ใงใฏใ‚ใ‚Šใพใ›ใ‚“... ๐Ÿ˜… + +ใ“ใ‚Œใ‚‰ใ‚’ใ€ใ„ใใคใ‹ใฎ่ฟฝๅŠ ใƒขใƒ‡ใƒซใงไฟฎๆญฃใ—ใพใ™ใ€‚ใ“ใ“ใง SQLModel ใฎ็œŸไพกใŒ็™บๆฎใ•ใ‚Œใพใ™ใ€‚โœจ + +### ่ค‡ๆ•ฐใƒขใƒ‡ใƒซใฎไฝœๆˆ { #create-multiple-models } + +SQLModel ใงใฏใ€`table=True` ใฎใ‚ใ‚‹ใƒขใƒ‡ใƒซใ‚ฏใƒฉใ‚นใŒใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซใงใ™ใ€‚ + +`table=True` ใฎใชใ„ใƒขใƒ‡ใƒซใ‚ฏใƒฉใ‚นใฏใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใงใ€ๅฎŸไฝ“ใฏ๏ผˆๅฐใ•ใชๆฉŸ่ƒฝใŒใ„ใใคใ‹่ฟฝๅŠ ใ•ใ‚ŒใŸ๏ผ‰Pydantic ใƒขใƒ‡ใƒซใงใ™ใ€‚๐Ÿค“ + +SQLModel ใงใฏ็ถ™ๆ‰ฟใ‚’ไฝฟใฃใฆใ€ใ‚ใ‚‰ใ‚†ใ‚‹ใ‚ฑใƒผใ‚นใงใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎ้‡่ค‡ใ‚’้ฟใ‘ใ‚‰ใ‚Œใพใ™ใ€‚ + +#### `HeroBase` - ใƒ™ใƒผใ‚นใ‚ฏใƒฉใ‚น { #herobase-the-base-class } + +ใพใšใ€ใ™ในใฆใฎใƒขใƒ‡ใƒซใงๅ…ฑๆœ‰ใ•ใ‚Œใ‚‹ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๆŒใค `HeroBase` ใƒขใƒ‡ใƒซใ‚’ไฝœใ‚Šใพใ™: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - ใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซ { #hero-the-table-model } + +ๆฌกใซใ€ๅฎŸ้š›ใฎใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซใงใ‚ใ‚‹ `Hero` ใ‚’ไฝœใ‚Šใพใ™ใ€‚ไป–ใฎใƒขใƒ‡ใƒซใซใฏๅธธใซๅซใพใ‚Œใชใ„่ฟฝๅŠ ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๆŒใกใพใ™: + +* `id` +* `secret_name` + +`Hero` ใฏ `HeroBase` ใ‚’็ถ™ๆ‰ฟใ—ใฆใ„ใ‚‹ใŸใ‚ใ€`HeroBase` ใงๅฎฃ่จ€ใ•ใ‚ŒใŸใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚‚ๆŒใกใพใ™ใ€‚ใคใพใ‚Šใ€`Hero` ใฎๅ…จใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏๆฌกใฎใจใŠใ‚Šใงใ™: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - ๅ…ฌ้–‹็”จใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซ { #heropublic-the-public-data-model } + +ๆฌกใซใ€API ใฎใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ™ `HeroPublic` ใƒขใƒ‡ใƒซใ‚’ไฝœใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏ `HeroBase` ใจๅŒใ˜ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๆŒใคใŸใ‚ใ€`secret_name` ใฏๅซใฟใพใ›ใ‚“ใ€‚ + +ใ“ใ‚Œใงใƒ’ใƒผใƒญใƒผใฎๆญฃไฝ“ใฏๅฎˆใ‚‰ใ‚Œใพใ™๏ผ๐Ÿฅท + +ใพใŸใ€`id: int` ใ‚’ๅ†ๅฎฃ่จ€ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€API ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใจใฎ้–“ใงใ€Œๅธธใซ `id` ใŒๅญ˜ๅœจใ—ใ€`int` ใงใ‚ใ‚‹๏ผˆ`None` ใซใฏใชใ‚‰ใชใ„๏ผ‰ใ€ใจใ„ใ†ๅฅ‘็ด„ใ‚’็ตใณใพใ™ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ๆˆปใ‚Šๅ€คใฎใƒขใƒ‡ใƒซใงใ€ๅ€คใŒๅธธใซๅญ˜ๅœจใ—ๅธธใซ `int`๏ผˆ`None` ใงใฏใชใ„๏ผ‰ใงใ‚ใ‚‹ใ“ใจใ‚’ไฟ่จผใ™ใ‚‹ใจใ€API ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆๅดใฎใ‚ณใƒผใƒ‰ใฏใฏใ‚‹ใ‹ใซใ‚ทใƒณใƒ—ใƒซใซๆ›ธใ‘ใพใ™ใ€‚ + +ๅŠ ใˆใฆใ€่‡ชๅ‹•็”Ÿๆˆใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใฎใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใ‚‚็ฐกๆฝ”ใซใชใ‚Šใ€ใ‚ใชใŸใฎ API ใจใ‚„ใ‚Šๅ–ใ‚Šใ™ใ‚‹้–‹็™บ่€…ไฝ“้จ“ใŒๅ‘ไธŠใ—ใพใ™ใ€‚๐Ÿ˜Ž + +/// + +`HeroPublic` ใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏ `HeroBase` ใจๅŒใ˜ใงใ€`id` ใฏ `int`๏ผˆ`None` ใงใฏใชใ„๏ผ‰ใจใ—ใฆๅฎฃ่จ€ใ•ใ‚Œใพใ™: + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - ไฝœๆˆ็”จใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซ { #herocreate-the-data-model-to-create-a-hero } + +ๆฌกใซใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰ใฎใƒ‡ใƒผใ‚ฟใ‚’ใƒใƒชใƒ‡ใƒผใƒˆใ™ใ‚‹ `HeroCreate` ใƒขใƒ‡ใƒซใ‚’ไฝœใ‚Šใพใ™ใ€‚ + +ใ“ใ‚Œใฏ `HeroBase` ใจๅŒใ˜ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใซๅŠ ใˆใ€`secret_name` ใ‚‚ๆŒใกใพใ™ใ€‚ + +ใ“ใ‚Œใงใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒๆ–ฐใ—ใ„ใƒ’ใƒผใƒญใƒผใ‚’ไฝœๆˆใ™ใ‚‹้š›ใซ `secret_name` ใ‚’้€ไฟกใ—ใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซไฟๅญ˜ใ•ใ‚Œใพใ™ใŒใ€ใใฎใ‚ทใƒผใ‚ฏใƒฌใƒƒใƒˆๅใฏ API ใงใฏใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใซ่ฟ”ใ•ใ‚Œใพใ›ใ‚“ใ€‚ + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ใ“ใ‚Œใฏใƒ‘ใ‚นใƒฏใƒผใƒ‰ใ‚’ๆ‰ฑใ†้š›ใฎๆ–นๆณ•ใจๅŒใ˜ใงใ™ใ€‚ๅ—ใ‘ๅ–ใ‚Šใพใ™ใŒใ€API ใงใฏ่ฟ”ใ—ใพใ›ใ‚“ใ€‚ + +ใพใŸใ€ไฟๅญ˜ๅ‰ใซใƒ‘ใ‚นใƒฏใƒผใƒ‰ใฎๅ€คใฏใƒใƒƒใ‚ทใƒฅๅŒ–ใ—ใ€ๅนณๆ–‡ใฎใพใพไฟๅญ˜ใ—ใชใ„ใงใใ ใ•ใ„ใ€‚ + +/// + +`HeroCreate` ใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - ๆ›ดๆ–ฐ็”จใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซ { #heroupdate-the-data-model-to-update-a-hero } + +ๅ‰ใฎใƒใƒผใ‚ธใƒงใƒณใฎใ‚ขใƒ—ใƒชใซใฏใƒ’ใƒผใƒญใƒผใ‚’ๆ›ดๆ–ฐใ™ใ‚‹ๆ–นๆณ•ใŒใ‚ใ‚Šใพใ›ใ‚“ใงใ—ใŸใŒใ€่ค‡ๆ•ฐใƒขใƒ‡ใƒซใ‚’ไฝฟใˆใฐๅฏ่ƒฝใงใ™ใ€‚๐ŸŽ‰ + +`HeroUpdate` ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใฏๅฐ‘ใ—็‰นๆฎŠใงใ€ๆ–ฐใ—ใ„ใƒ’ใƒผใƒญใƒผใ‚’ไฝœๆˆใ™ใ‚‹ใฎใซๅฟ…่ฆใชใƒ•ใ‚ฃใƒผใƒซใƒ‰ใจๅŒใ˜ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ใ™ในใฆๆŒใกใพใ™ใŒใ€ใ™ในใฆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใŒใ‚ชใƒ—ใ‚ทใƒงใƒŠใƒซ๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใ‚’ๆŒใค๏ผ‰ใงใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ๆ›ดๆ–ฐๆ™‚ใซใฏๅค‰ๆ›ดใ—ใŸใ„ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ ใ‘ใ‚’้€ใ‚Œใพใ™ใ€‚ + +ใ™ในใฆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅž‹ใŒๅฎŸ่ณช็š„ใซๅค‰ใ‚ใ‚‹๏ผˆ`None` ใ‚’ๅซใฟใ€ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใŒ `None` ใซใชใ‚‹๏ผ‰ใŸใ‚ใ€ใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฏๅ†ๅฎฃ่จ€ใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚ + +ใ™ในใฆใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๅ†ๅฎฃ่จ€ใ™ใ‚‹ใฎใงใ€ๅŽณๅฏ†ใซใฏ `HeroBase` ใ‚’็ถ™ๆ‰ฟใ™ใ‚‹ๅฟ…่ฆใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ไธ€่ฒซๆ€งใฎใŸใ‚ใซใ“ใ“ใงใฏ็ถ™ๆ‰ฟใ—ใฆใ„ใพใ™ใŒใ€ๅฟ…้ ˆใงใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ๅฅฝใฟใฎๅ•้กŒใงใ™ใ€‚๐Ÿคท + +`HeroUpdate` ใฎใƒ•ใ‚ฃใƒผใƒซใƒ‰: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### `HeroCreate` ใงไฝœๆˆใ— `HeroPublic` ใ‚’่ฟ”ใ™ { #create-with-herocreate-and-return-a-heropublic } + +่ค‡ๆ•ฐใƒขใƒ‡ใƒซใŒ็”จๆ„ใงใใŸใฎใงใ€ใใ‚Œใ‚‰ใ‚’ไฝฟใ†ใ‚ˆใ†ใซใ‚ขใƒ—ใƒชใฎ้ƒจๅˆ†ใ‚’ๆ›ดๆ–ฐใ—ใพใ™ใ€‚ + +ใƒชใ‚ฏใ‚จใ‚นใƒˆใงใฏ `HeroCreate` ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๅ—ใ‘ๅ–ใ‚Šใ€ใใ“ใ‹ใ‚‰ `Hero` ใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซใ‚’ไฝœๆˆใ—ใพใ™ใ€‚ + +ใ“ใฎๆ–ฐใ—ใ„ใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซ `Hero` ใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰้€ใ‚‰ใ‚ŒใŸใƒ•ใ‚ฃใƒผใƒซใƒ‰ใ‚’ๆŒใกใ€ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใซใ‚ˆใฃใฆ็”Ÿๆˆใ•ใ‚ŒใŸ `id` ใ‚‚ๆŒใกใพใ™ใ€‚ + +้–ขๆ•ฐใ‹ใ‚‰ใฏใ“ใฎใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซ `Hero` ใ‚’ใใฎใพใพ่ฟ”ใ—ใพใ™ใ€‚ใ—ใ‹ใ— `response_model` ใซ `HeroPublic` ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใ‚’ๆŒ‡ๅฎšใ—ใฆใ„ใ‚‹ใŸใ‚ใ€FastAPI ใŒ `HeroPublic` ใ‚’ไฝฟใฃใฆใƒ‡ใƒผใ‚ฟใ‚’ใƒใƒชใƒ‡ใƒผใƒˆใƒปใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใ—ใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | ่ฑ†็Ÿฅ่ญ˜ + +ไปŠๅ›žใฏ่ฟ”ๅดๅ€คใฎๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณ `-> HeroPublic` ใฎไปฃใ‚ใ‚Šใซ `response_model=HeroPublic` ใ‚’ไฝฟใ„ใพใ™ใ€‚่ฟ”ใ—ใฆใ„ใ‚‹ๅ€คใฏๅฎŸ้š›ใซใฏ `HeroPublic` ใงใฏใชใ„ใŸใ‚ใงใ™ใ€‚ + +ใ‚‚ใ— `-> HeroPublic` ใจๅฎฃ่จ€ใ™ใ‚‹ใจใ€ใ‚จใƒ‡ใ‚ฃใ‚ฟใ‚„ Linter ใฏ๏ผˆๆญฃใ—ใ๏ผ‰ใ€Œ`HeroPublic` ใงใฏใชใ `Hero` ใ‚’่ฟ”ใ—ใฆใ„ใ‚‹ใ€ใจ่ญฆๅ‘Šใ—ใพใ™ใ€‚ + +`response_model` ใซๆŒ‡ๅฎšใ™ใ‚‹ใ“ใจใงใ€ๅž‹ใ‚ขใƒŽใƒ†ใƒผใ‚ทใƒงใƒณใ‚„ใ‚จใƒ‡ใ‚ฃใ‚ฟ็ญ‰ใฎ่ฃœๅŠฉใ‚’ๅดฉใ•ใšใซใ€FastAPI ใซใ‚ทใƒชใ‚ขใƒฉใ‚คใ‚บใฎไป•ไบ‹ใ‚’ไปปใ›ใ‚‰ใ‚Œใพใ™ใ€‚ + +/// + +### `HeroPublic` ใง Hero ใ‚’ๅ–ๅพ— { #read-heroes-with-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 } + +ๅ˜ไธ€ใฎใƒ’ใƒผใƒญใƒผใ‚’ๅ–ๅพ—ใ—ใพใ™: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### `HeroUpdate` ใง Hero ใ‚’ๆ›ดๆ–ฐ { #update-a-hero-with-heroupdate } + +ใƒ’ใƒผใƒญใƒผใ‚’ๆ›ดๆ–ฐใงใใพใ™ใ€‚ใ“ใ“ใงใฏ HTTP ใฎ `PATCH` ใ‚’ไฝฟใ„ใพใ™ใ€‚ + +ใ‚ณใƒผใƒ‰ใงใฏใ€ใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใŒ้€ใฃใŸใƒ‡ใƒผใ‚ฟใฎใฟ๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆๅ€คใจใ—ใฆๅ…ฅใฃใฆใใ‚‹ๅ€คใฏ้™คๅค–๏ผ‰ใ‚’ๆŒใค `dict` ใ‚’ๅ–ๅพ—ใ—ใพใ™ใ€‚ใ“ใ‚Œใซใฏ `exclude_unset=True` ใ‚’ไฝฟใ„ใพใ™ใ€‚ใ“ใ‚ŒใŒไธปใชใ‚ณใƒ„ใงใ™ใ€‚๐Ÿช„ + +ใใฎๅพŒใ€`hero_db.sqlmodel_update(hero_data)` ใ‚’ไฝฟใฃใฆใ€`hero_db` ใ‚’ `hero_data` ใฎๅ†…ๅฎนใงๆ›ดๆ–ฐใ—ใพใ™ใ€‚ + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### ๅ†ๅบฆ Hero ใ‚’ๅ‰Š้™ค { #delete-a-hero-again } + +ใƒ’ใƒผใƒญใƒผใฎๅ‰Š้™คใฏใปใจใ‚“ใฉๅค‰ใ‚ใ‚Šใพใ›ใ‚“ใ€‚ + +ใ“ใ“ใฏใƒชใƒ•ใ‚กใ‚ฏใ‚ฟใƒชใƒณใ‚ฐๆฌฒๆฑ‚ใ‚’ๆบ€ใŸใ•ใชใ„ใพใพใซใ—ใฆใŠใใพใ™ใ€‚๐Ÿ˜… + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### ใ‚ขใƒ—ใƒชใฎๅ†่ตทๅ‹• { #run-the-app-again } + +ใ‚ขใƒ—ใƒชใ‚’ๅ†ๅบฆ่ตทๅ‹•ใ—ใพใ™: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +`/docs` ใฎ API UI ใซ่กŒใใจใ€ๅ†…ๅฎนใŒๆ›ดๆ–ฐใ•ใ‚ŒใฆใŠใ‚Šใ€ใƒ’ใƒผใƒญใƒผไฝœๆˆๆ™‚ใซใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆใ‹ใ‚‰ `id` ใ‚’ๅ—ใ‘ๅ–ใ‚‹ใ“ใจใฏๆœŸๅพ…ใ•ใ‚Œใฆใ„ใชใ„ใ€ใชใฉใŒ็ขบ่ชใงใใพใ™ใ€‚ + +
+ +
+ +## ใพใจใ‚ { #recap } + +SQLModel ใ‚’ไฝฟใฃใฆ SQL ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใจใ‚„ใ‚Šๅ–ใ‚Šใ—ใ€ใƒ‡ใƒผใ‚ฟใƒขใƒ‡ใƒซใจใƒ†ใƒผใƒ–ใƒซใƒขใƒ‡ใƒซใงใ‚ณใƒผใƒ‰ใ‚’็ฐกๆฝ”ใซใงใใพใ™ใ€‚ + +ใ•ใ‚‰ใซๅคšใใ‚’ๅญฆใถใซใฏ SQLModel ใฎใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใ‚’ใ”่ฆงใใ ใ•ใ„ใ€‚FastAPI ใจ SQLModel ใ‚’ไฝฟใ†ใƒใƒฅใƒผใƒˆใƒชใ‚ขใƒซ ใ‚‚ใ‚ใ‚Šใพใ™ใ€‚๐Ÿš€ diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index c79789494c..52e28d6b05 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * `StaticFiles` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใ€‚ * `StaticFiles()` ใ‚คใƒณใ‚นใ‚ฟใƒณใ‚นใ‚’็‰นๅฎšใฎใƒ‘ใ‚นใซใ€Œใƒžใ‚ฆใƒณใƒˆใ€ใ€‚ -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | ๆŠ€่ก“่ฉณ็ดฐ diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index 0ec6250f31..b09f1af723 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -30,7 +30,7 @@ $ pip install httpx ใƒใ‚งใƒƒใ‚ฏใ—ใŸใ„ Python ใฎๆจ™ๆบ–็š„ใชๅผใจๅ…ฑใซใ€ใ‚ทใƒณใƒ—ใƒซใซ `assert` ๆ–‡ใ‚’่จ˜่ฟฐใ—ใพใ™ (ใ“ใ‚Œใ‚‚ `pytest` ใฎๆจ™ๆบ–ใงใ™)ใ€‚ -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -76,7 +76,7 @@ FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ้€ไฟกใจใฏๅˆฅใซใ€ใƒ† ใƒ•ใ‚กใ‚คใƒซ `main.py` ใซ **FastAPI** ใ‚ขใƒ—ใƒชใŒใ‚ใ‚Šใพใ™: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### ใƒ†ใ‚นใƒˆใƒ•ใ‚กใ‚คใƒซ { #testing-file } @@ -92,7 +92,7 @@ FastAPIใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใธใฎใƒชใ‚ฏใ‚จใ‚นใƒˆใฎ้€ไฟกใจใฏๅˆฅใซใ€ใƒ† ใ“ใฎใƒ•ใ‚กใ‚คใƒซใฏๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธๅ†…ใซใ‚ใ‚‹ใŸใ‚ใ€็›ธๅฏพใ‚คใƒณใƒใƒผใƒˆใ‚’ไฝฟใฃใฆ `main` ใƒขใ‚ธใƒฅใƒผใƒซ (`main.py`) ใ‹ใ‚‰ใ‚ชใƒ–ใ‚ธใ‚งใ‚ฏใƒˆ `app` ใ‚’ใ‚คใƒณใƒใƒผใƒˆใงใใพใ™: -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...ใใ—ใฆใ€ใ“ใ‚ŒใพใงใจๅŒใ˜ใ‚ˆใ†ใซใƒ†ใ‚นใƒˆใ‚ณใƒผใƒ‰ใ‚’ๆ›ธใ‘ใพใ™ใ€‚ diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 6723230632..94af6ddae2 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -50,7 +50,7 @@ $ cd awesome-project ## ไปฎๆƒณ็’ฐๅขƒใฎไฝœๆˆ { #create-a-virtual-environment } -Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฎ**ๅˆใ‚ใฆใฎ**ไฝœๆฅญใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆๅ†…**ใซไปฎๆƒณ็’ฐๅขƒใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ +Pythonใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใงใฎ**ๅˆใ‚ใฆใฎ**ไฝœๆฅญใ‚’้–‹ๅง‹ใ™ใ‚‹้š›ใซใฏใ€**ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆๅ†…**ใซไปฎๆƒณ็’ฐๅขƒใ‚’ไฝœๆˆใ—ใฆใใ ใ•ใ„ใ€‚ /// tip | ่ฑ†็Ÿฅ่ญ˜ @@ -163,7 +163,7 @@ $ source .venv/Scripts/activate **ๆ–ฐใ—ใ„ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ**ใ‚’ไปฎๆƒณ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ™ใ‚‹ใŸใณใซใ€็’ฐๅขƒใ‚’ใ‚‚ใ†ไธ€ๅบฆ**ๆœ‰ๅŠนๅŒ–**ใ—ใฆใใ ใ•ใ„ใ€‚ -ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€ใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸ**ใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผˆCLI๏ผ‰ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใซใ€ไปฎๆƒณ็’ฐๅขƒๅ†…ใฎใ‚‚ใฎใŒ็ขบๅฎŸใซไฝฟใ‚ใ‚Œใ€ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ๅˆฅใฎใ‚‚ใฎ๏ผˆใŠใใ‚‰ใๅฟ…่ฆใชใ‚‚ใฎใจใฏ็•ฐใชใ‚‹ใƒใƒผใ‚ธใƒงใƒณ๏ผ‰ใ‚’่ชคใฃใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’้˜ฒใŽใพใ™ใ€‚ +ใ“ใ†ใ™ใ‚‹ใ“ใจใงใ€ใใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใŒใ‚คใƒณใ‚นใƒˆใƒผใƒซใ—ใŸ**ใ‚ฟใƒผใƒŸใƒŠใƒซ๏ผˆCLI๏ผ‰ใƒ—ใƒญใ‚ฐใƒฉใƒ **ใ‚’ไฝฟ็”จใ™ใ‚‹ๅ ดๅˆใซใ€ไปฎๆƒณ็’ฐๅขƒๅ†…ใฎใ‚‚ใฎใŒ็ขบๅฎŸใซไฝฟใ‚ใ‚Œใ€ใ‚ฐใƒญใƒผใƒใƒซ็’ฐๅขƒใซใ‚คใƒณใ‚นใƒˆใƒผใƒซใ•ใ‚Œใฆใ„ใ‚‹ๅˆฅใฎใ‚‚ใฎ๏ผˆใŠใใ‚‰ใๅฟ…่ฆใชใ‚‚ใฎใจใฏ็•ฐใชใ‚‹ใƒใƒผใ‚ธใƒงใƒณ๏ผ‰ใ‚’่ชคใฃใฆไฝฟ็”จใ™ใ‚‹ใ“ใจใ‚’้˜ฒใŽใพใ™ใ€‚ /// From 5420847d9fbdb442aa469b48d40bd61436bc5acc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Feb 2026 15:24:56 +0000 Subject: [PATCH 234/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 152f684e73..2f2d599dc9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov). From dca874c58cc36b1d98570d55df1127523cb2d1a8 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 14 Feb 2026 08:57:30 +0100 Subject: [PATCH 235/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-all)=20=20(#14910)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * ๐ŸŽจ Auto format * Apply suggestions from code review --------- Co-authored-by: github-actions[bot] --- docs/de/docs/advanced/additional-responses.md | 4 +- .../de/docs/advanced/advanced-dependencies.md | 8 +- .../de/docs/advanced/advanced-python-types.md | 61 ++++++ docs/de/docs/advanced/async-tests.md | 8 +- docs/de/docs/advanced/behind-a-proxy.md | 12 +- docs/de/docs/advanced/custom-response.md | 32 +-- docs/de/docs/advanced/dataclasses.md | 4 +- docs/de/docs/advanced/events.md | 12 +- docs/de/docs/advanced/generate-clients.md | 12 +- docs/de/docs/advanced/middleware.md | 8 +- docs/de/docs/advanced/openapi-webhooks.md | 6 +- .../path-operation-advanced-configuration.md | 20 +- .../advanced/response-change-status-code.md | 2 +- docs/de/docs/advanced/response-cookies.md | 4 +- docs/de/docs/advanced/response-directly.md | 2 +- docs/de/docs/advanced/response-headers.md | 4 +- .../docs/advanced/security/http-basic-auth.md | 6 +- docs/de/docs/advanced/settings.md | 26 +-- docs/de/docs/advanced/sub-applications.md | 6 +- docs/de/docs/advanced/templates.md | 2 +- docs/de/docs/advanced/testing-events.md | 4 +- docs/de/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 2 +- docs/de/docs/advanced/websockets.md | 8 +- docs/de/docs/advanced/wsgi.md | 2 +- docs/de/docs/alternatives.md | 14 +- docs/de/docs/benchmarks.md | 2 +- docs/de/docs/deployment/cloud.md | 2 +- docs/de/docs/deployment/docker.md | 12 +- docs/de/docs/deployment/https.md | 2 +- docs/de/docs/deployment/index.md | 2 +- docs/de/docs/deployment/server-workers.md | 2 +- docs/de/docs/features.md | 12 +- docs/de/docs/history-design-future.md | 2 +- .../authentication-error-status-code.md | 2 +- docs/de/docs/how-to/conditional-openapi.md | 2 +- docs/de/docs/how-to/configure-swagger-ui.md | 6 +- docs/de/docs/how-to/custom-docs-ui-assets.md | 14 +- docs/de/docs/how-to/extending-openapi.md | 10 +- docs/de/docs/how-to/graphql.md | 2 +- docs/de/docs/index.md | 12 +- docs/de/docs/project-generation.md | 2 +- docs/de/docs/python-types.md | 192 ++++-------------- docs/de/docs/translation-banner.md | 11 + docs/de/docs/tutorial/background-tasks.md | 6 +- docs/de/docs/tutorial/bigger-applications.md | 26 +-- docs/de/docs/tutorial/body-fields.md | 2 +- docs/de/docs/tutorial/body-multiple-params.md | 6 - docs/de/docs/tutorial/body-nested-models.md | 4 +- docs/de/docs/tutorial/body.md | 2 +- docs/de/docs/tutorial/cookie-param-models.md | 8 +- docs/de/docs/tutorial/cors.md | 2 +- docs/de/docs/tutorial/debugging.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +-- ...pendencies-in-path-operation-decorators.md | 12 +- .../dependencies/dependencies-with-yield.md | 24 +-- .../dependencies/global-dependencies.md | 3 +- docs/de/docs/tutorial/dependencies/index.md | 2 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/de/docs/tutorial/extra-models.md | 8 +- docs/de/docs/tutorial/first-steps.md | 16 +- docs/de/docs/tutorial/handling-errors.md | 18 +- docs/de/docs/tutorial/metadata.md | 12 +- docs/de/docs/tutorial/middleware.md | 4 +- .../tutorial/path-operation-configuration.md | 8 +- .../path-params-numeric-validations.md | 14 +- docs/de/docs/tutorial/path-params.md | 29 ++- .../tutorial/query-params-str-validations.md | 46 +---- docs/de/docs/tutorial/query-params.md | 6 +- docs/de/docs/tutorial/request-files.md | 12 +- docs/de/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/de/docs/tutorial/request-forms.md | 6 +- docs/de/docs/tutorial/response-model.md | 6 +- docs/de/docs/tutorial/response-status-code.md | 8 +- docs/de/docs/tutorial/schema-extra-example.md | 2 +- docs/de/docs/tutorial/security/first-steps.md | 8 +- .../tutorial/security/get-current-user.md | 2 +- docs/de/docs/tutorial/security/index.md | 2 +- docs/de/docs/tutorial/security/oauth2-jwt.md | 12 +- .../docs/tutorial/security/simple-oauth2.md | 2 +- docs/de/docs/tutorial/static-files.md | 2 +- docs/de/docs/tutorial/testing.md | 6 +- docs/de/docs/virtual-environments.md | 12 +- 84 files changed, 431 insertions(+), 507 deletions(-) create mode 100644 docs/de/docs/advanced/advanced-python-types.md create mode 100644 docs/de/docs/translation-banner.md diff --git a/docs/de/docs/advanced/additional-responses.md b/docs/de/docs/advanced/additional-responses.md index 0f9b122516..531702bf18 100644 --- a/docs/de/docs/advanced/additional-responses.md +++ b/docs/de/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ Jedes dieser Response-`dict`s kann einen Schlรผssel `model` haben, welcher ein P Um beispielsweise eine weitere Response mit dem Statuscode `404` und einem Pydantic-Modell `Message` zu deklarieren, kรถnnen Sie schreiben: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Hinweis @@ -203,7 +203,7 @@ Sie kรถnnen beispielsweise eine Response mit dem Statuscode `404` deklarieren, d Und eine Response mit dem Statuscode `200`, die Ihr `response_model` verwendet, aber ein benutzerdefiniertes Beispiel (`example`) enthรคlt: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Es wird alles kombiniert und in Ihre OpenAPI eingebunden und in der API-Dokumentation angezeigt: diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md index e60df28834..50b4e20ac0 100644 --- a/docs/de/docs/advanced/advanced-dependencies.md +++ b/docs/de/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Nicht die Klasse selbst (die bereits aufrufbar ist), sondern eine Instanz dieser Dazu deklarieren wir eine Methode `__call__`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zusรคtzlichen Parametern und Unterabhรคngigkeiten zu suchen, und das ist es auch, was spรคter aufgerufen wird, um einen Wert an den Parameter in Ihrer *Pfadoperation-Funktion* zu รผbergeben. @@ -26,7 +26,7 @@ In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zus Und jetzt kรถnnen wir `__init__` verwenden, um die Parameter der Instanz zu deklarieren, die wir zum โ€žParametrisierenโ€œ der Abhรคngigkeit verwenden kรถnnen: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} In diesem Fall wird **FastAPI** `__init__` nie berรผhren oder sich darum kรผmmern, wir werden es direkt in unserem Code verwenden. @@ -34,7 +34,7 @@ In diesem Fall wird **FastAPI** `__init__` nie berรผhren oder sich darum kรผmmer Wir kรถnnten eine Instanz dieser Klasse erstellen mit: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} Und auf diese Weise kรถnnen wir unsere Abhรคngigkeit โ€žparametrisierenโ€œ, die jetzt `"bar"` enthรคlt, als das Attribut `checker.fixed_content`. @@ -50,7 +50,7 @@ checker(q="somequery") ... und รผbergibt, was immer das als Wert dieser Abhรคngigkeit in unserer *Pfadoperation-Funktion* zurรผckgibt, als den Parameter `fixed_content_included`: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | Tipp diff --git a/docs/de/docs/advanced/advanced-python-types.md b/docs/de/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..aed859ceff --- /dev/null +++ b/docs/de/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Fortgeschrittene Python-Typen { #advanced-python-types } + +Hier sind einige zusรคtzliche Ideen, die beim Arbeiten mit Python-Typen nรผtzlich sein kรถnnten. + +## `Union` oder `Optional` verwenden { #using-union-or-optional } + +Wenn Ihr Code aus irgendeinem Grund nicht `|` verwenden kann, z. B. wenn es nicht in einer Typannotation ist, sondern in etwas wie `response_model=`, kรถnnen Sie anstelle des senkrechten Strichs (`|`) `Union` aus `typing` verwenden. + +Zum Beispiel kรถnnten Sie deklarieren, dass etwas ein `str` oder `None` sein kรถnnte: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` hat auรŸerdem eine Abkรผrzung, um zu deklarieren, dass etwas `None` sein kรถnnte, mit `Optional`. + +Hier ist ein Tipp aus meiner sehr **subjektiven** Perspektive: + +* ๐Ÿšจ Vermeiden Sie die Verwendung von `Optional[SomeType]` +* Verwenden Sie stattdessen โœจ **`Union[SomeType, None]`** โœจ. + +Beides ist รคquivalent und unter der Haube identisch, aber ich wรผrde `Union` statt `Optional` empfehlen, weil das Wort โ€ž**optional**โ€œ implizieren kรถnnte, dass der Wert optional ist; tatsรคchlich bedeutet es jedoch โ€žes kann `None` seinโ€œ, selbst wenn es nicht optional ist und weiterhin erforderlich bleibt. + +Ich finde, `Union[SomeType, None]` ist expliziter in dem, was es bedeutet. + +Es geht nur um Wรถrter und Namen. Aber diese Wรถrter kรถnnen beeinflussen, wie Sie und Ihr Team รผber den Code denken. + +Als Beispiel nehmen wir diese Funktion: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +Der Parameter `name` ist als `Optional[str]` definiert, aber er ist **nicht optional**, Sie kรถnnen die Funktion nicht ohne den Parameter aufrufen: + +```Python +say_hi() # Oh nein, das lรถst einen Fehler aus! ๐Ÿ˜ฑ +``` + +Der Parameter `name` ist **weiterhin erforderlich** (nicht *optional*), weil er keinen Defaultwert hat. Dennoch akzeptiert `name` den Wert `None`: + +```Python +say_hi(name=None) # Das funktioniert, None ist gรผltig ๐ŸŽ‰ +``` + +Die gute Nachricht ist: In den meisten Fรคllen kรถnnen Sie einfach `|` verwenden, um Unions von Typen zu definieren: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Sie mรผssen sich also normalerweise keine Gedanken รผber Namen wie `Optional` und `Union` machen. ๐Ÿ˜Ž diff --git a/docs/de/docs/advanced/async-tests.md b/docs/de/docs/advanced/async-tests.md index 7206f136fd..7702cc1c57 100644 --- a/docs/de/docs/advanced/async-tests.md +++ b/docs/de/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ Betrachten wir als einfaches Beispiel eine Dateistruktur รคhnlich der in [GrรถรŸ Die Datei `main.py` hรคtte als Inhalt: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} Die Datei `test_main.py` hรคtte die Tests fรผr `main.py`, das kรถnnte jetzt so aussehen: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## Es ausfรผhren { #run-it } @@ -56,7 +56,7 @@ $ pytest Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | Tipp @@ -66,7 +66,7 @@ Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wi Dann kรถnnen wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} Das ist das ร„quivalent zu: diff --git a/docs/de/docs/advanced/behind-a-proxy.md b/docs/de/docs/advanced/behind-a-proxy.md index 1c74590503..cbcdc59d4c 100644 --- a/docs/de/docs/advanced/behind-a-proxy.md +++ b/docs/de/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" Angenommen, Sie definieren eine *Pfadoperation* `/items/`: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} Wenn der Client versucht, zu `/items` zu gehen, wรผrde er standardmรครŸig zu `/items/` umgeleitet. @@ -115,7 +115,7 @@ In diesem Fall wรผrde der ursprรผngliche Pfad `/app` tatsรคchlich unter `/api/v1 Auch wenn Ihr gesamter Code unter der Annahme geschrieben ist, dass es nur `/app` gibt. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} Und der Proxy wรผrde das **Pfadprรคfix** on-the-fly **โ€žentfernenโ€œ**, bevor er den Request an den Anwendungsserver (wahrscheinlich Uvicorn via FastAPI CLI) รผbermittelt, dafรผr sorgend, dass Ihre Anwendung davon รผberzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren mรผssen, das Prรคfix `/api/v1` zu verwenden. @@ -193,7 +193,7 @@ Sie kรถnnen den aktuellen `root_path` abrufen, der von Ihrer Anwendung fรผr jede Hier fรผgen wir ihn, nur zu Demonstrationszwecken, in die Nachricht ein. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} Wenn Sie Uvicorn dann starten mit: @@ -220,7 +220,7 @@ wรคre die Requests und Responses zu deklarieren. @@ -64,7 +64,7 @@ In diesem Fall kรถnnen Sie einfach die Standard-`dataclasses` durch `pydantic.da 6. Hier geben wir ein Dictionary zurรผck, das `items` enthรคlt, welches eine Liste von Datenklassen ist. - FastAPI ist weiterhin in der Lage, die Daten nach JSON zu serialisieren. + FastAPI ist weiterhin in der Lage, die Daten nach JSON zu Serialisieren. 7. Hier verwendet das `response_model` als Typannotation eine Liste von `Author`-Datenklassen. diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md index 7e1191b55e..17d14d71c5 100644 --- a/docs/de/docs/advanced/events.md +++ b/docs/de/docs/advanced/events.md @@ -30,7 +30,7 @@ Beginnen wir mit einem Beispiel und sehen es uns dann im Detail an. Wir erstellen eine asynchrone Funktion `lifespan()` mit `yield` wie folgt: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} Hier simulieren wir den langsamen *Startup*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das Dictionary mit Modellen fรผr maschinelles Lernen einfรผgen. Dieser Code wird ausgefรผhrt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, wรคhrend des *Startups*. @@ -48,7 +48,7 @@ Mรถglicherweise mรผssen Sie eine neue Version starten, oder Sie haben es einfach Das Erste, was auffรคllt, ist, dass wir eine asynchrone Funktion mit `yield` definieren. Das ist sehr รคhnlich zu Abhรคngigkeiten mit `yield`. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} Der erste Teil der Funktion, vor dem `yield`, wird ausgefรผhrt **bevor** die Anwendung startet. @@ -60,7 +60,7 @@ Wie Sie sehen, ist die Funktion mit einem `@asynccontextmanager` versehen. Dadurch wird die Funktion in einen sogenannten โ€ž**asynchronen Kontextmanager**โ€œ umgewandelt. -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} Ein **Kontextmanager** in Python ist etwas, das Sie in einer `with`-Anweisung verwenden kรถnnen, zum Beispiel kann `open()` als Kontextmanager verwendet werden: @@ -82,7 +82,7 @@ In unserem obigen Codebeispiel verwenden wir ihn nicht direkt, sondern รผbergebe Der Parameter `lifespan` der `FastAPI`-App benรถtigt einen **asynchronen Kontextmanager**, wir kรถnnen ihm also unseren neuen asynchronen Kontextmanager `lifespan` รผbergeben. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## Alternative Events (deprecatet) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ Diese Funktionen kรถnnen mit `async def` oder normalem `def` deklariert werden. Um eine Funktion hinzuzufรผgen, die vor dem Start der Anwendung ausgefรผhrt werden soll, deklarieren Sie diese mit dem Event `startup`: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} In diesem Fall initialisiert die Eventhandler-Funktion `startup` die โ€žDatenbankโ€œ der Items (nur ein `dict`) mit einigen Werten. @@ -116,7 +116,7 @@ Und Ihre Anwendung empfรคngt erst dann Requests, wenn alle `startup`-Eventhandle Um eine Funktion hinzuzufรผgen, die beim Shutdown der Anwendung ausgefรผhrt werden soll, deklarieren Sie sie mit dem Event `shutdown`: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`. diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 659343f5bc..fcb5510029 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -2,7 +2,7 @@ Da **FastAPI** auf der **OpenAPI**-Spezifikation basiert, kรถnnen dessen APIs in einem standardisierten Format beschrieben werden, das viele Tools verstehen. -Dies vereinfacht es, aktuelle **Dokumentation** und Client-Bibliotheken (**SDKs**) in verschiedenen Sprachen zu generieren sowie **Test-** oder **Automatisierungs-Workflows**, die mit Ihrem Code synchron bleiben. +Dies vereinfacht es, aktuelle **Dokumentation** und Client-Bibliotheken (**SDKs**) in verschiedenen Sprachen zu generieren sowie **Test-** oder **Automatisierungs-Workflows**, die mit Ihrem Code synchron bleiben. In diesem Leitfaden erfahren Sie, wie Sie ein **TypeScript-SDK** fรผr Ihr FastAPI-Backend generieren. @@ -40,7 +40,7 @@ Einige dieser Lรถsungen sind mรถglicherweise auch Open Source oder bieten kosten Beginnen wir mit einer einfachen FastAPI-Anwendung: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} Beachten Sie, dass die *Pfadoperationen* die Modelle definieren, die sie fรผr die Request- und Response-Payload verwenden, indem sie die Modelle `Item` und `ResponseMessage` verwenden. @@ -98,7 +98,7 @@ In vielen Fรคllen wird Ihre FastAPI-App grรถรŸer sein und Sie werden wahrscheinl Zum Beispiel kรถnnten Sie einen Abschnitt fรผr **Items (Artikel)** und einen weiteren Abschnitt fรผr **Users (Benutzer)** haben, und diese kรถnnten durch Tags getrennt sein: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### Einen TypeScript-Client mit Tags generieren { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ Hier verwendet sie beispielsweise den ersten Tag (Sie werden wahrscheinlich nur AnschlieรŸend kรถnnen Sie diese benutzerdefinierte Funktion als `generate_unique_id_function`-Parameter an **FastAPI** รผbergeben: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### Einen TypeScript-Client mit benutzerdefinierten Operation-IDs generieren { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ Aber fรผr den generierten Client kรถnnten wir die OpenAPI-Operation-IDs direkt v Wir kรถnnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den prรคfixierten Tag entfernen**: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js @@ -179,7 +179,7 @@ Wir kรถnnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dan Damit wรผrden die Operation-IDs von Dingen wie `items-get_items` in `get_items` umbenannt, sodass der Client-Generator einfachere Methodennamen generieren kann. -### Einen TypeScript-Client mit der modifizierten OpenAPI generieren { #generate-a-typescript-client-with-the-preprocessed-openapi } +### Einen TypeScript-Client mit der vorverarbeiteten OpenAPI generieren { #generate-a-typescript-client-with-the-preprocessed-openapi } Da das Endergebnis nun in einer `openapi.json`-Datei vorliegt, mรผssen Sie Ihren Eingabeort aktualisieren: diff --git a/docs/de/docs/advanced/middleware.md b/docs/de/docs/advanced/middleware.md index ccc6a64c3b..4af583b5b1 100644 --- a/docs/de/docs/advanced/middleware.md +++ b/docs/de/docs/advanced/middleware.md @@ -57,13 +57,13 @@ Erzwingt, dass alle eingehenden hook* ## Webhooks-Schritte { #webhooks-steps } -Der Prozess besteht normalerweise darin, dass **Sie in Ihrem Code definieren**, welche Nachricht Sie senden mรถchten, den **Body des Requests**. +Der Prozess besteht normalerweise darin, dass **Sie in Ihrem Code definieren**, welche Nachricht Sie senden mรถchten, den **Requestbody**. Sie definieren auch auf irgendeine Weise, in welchen **Momenten** Ihre App diese Requests oder Events senden wird. @@ -18,7 +18,7 @@ Die gesamte **Logik** zur Registrierung der URLs fรผr Webhooks und der Code zum ## Webhooks mit **FastAPI** und OpenAPI dokumentieren { #documenting-webhooks-with-fastapi-and-openapi } -Mit **FastAPI**, mithilfe von OpenAPI, kรถnnen Sie die Namen dieser Webhooks, die Arten von HTTP-Operationen, die Ihre App senden kann (z. B. `POST`, `PUT`, usw.) und die Request**bodys** definieren, die Ihre App senden wรผrde. +Mit **FastAPI**, mithilfe von OpenAPI, kรถnnen Sie die Namen dieser Webhooks, die Arten von HTTP-Operationen, die Ihre App senden kann (z. B. `POST`, `PUT`, usw.) und die **Requestbodys** definieren, die Ihre App senden wรผrde. Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Mรถglicherweise kรถnnen diese sogar einen Teil ihres eigenen API-Codes automatisch generieren. @@ -32,7 +32,7 @@ Webhooks sind in OpenAPI 3.1.0 und hรถher verfรผgbar und werden von FastAPI `0.9 Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, das Sie verwenden kรถnnen, um *Webhooks* zu definieren, genauso wie Sie *Pfadoperationen* definieren wรผrden, zum Beispiel mit `@app.webhooks.post()`. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberflรคche**. diff --git a/docs/de/docs/advanced/path-operation-advanced-configuration.md b/docs/de/docs/advanced/path-operation-advanced-configuration.md index c7ac1cf61b..a2dd212a1a 100644 --- a/docs/de/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/de/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ Mit dem Parameter `operation_id` kรถnnen Sie die OpenAPI `operationId` festlegen Sie mรผssten sicherstellen, dass sie fรผr jede Operation eindeutig ist. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ Wenn Sie die Funktionsnamen Ihrer API als `operationId`s verwenden mรถchten, kรถ Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefรผgt haben. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | Tipp @@ -40,7 +40,7 @@ Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden. Um eine *Pfadoperation* aus dem generierten OpenAPI-Schema (und damit aus den automatischen Dokumentationssystemen) auszuschlieรŸen, verwenden Sie den Parameter `include_in_schema` und setzen Sie ihn auf `False`: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Fortgeschrittene Beschreibung mittels Docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ Sie kรถnnen das OpenAPI-Schema fรผr eine *Pfadoperation* erweitern, indem Sie de Dieses `openapi_extra` kann beispielsweise hilfreich sein, um [OpenAPI-Erweiterungen](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) zu deklarieren: -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Wenn Sie die automatische API-Dokumentation รถffnen, wird Ihre Erweiterung am Ende der spezifischen *Pfadoperation* angezeigt. @@ -135,13 +135,13 @@ Das Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne die automatischen Funktionen von FastAPI mit Pydantic zu verwenden, aber Sie kรถnnten den Request trotzdem im OpenAPI-Schema definieren wollen. +Sie kรถnnten sich beispielsweise dafรผr entscheiden, den Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne FastAPIs automatische Funktionen mit Pydantic zu verwenden, aber Sie kรถnnten den Request trotzdem im OpenAPI-Schema definieren wollen. Das kรถnnte man mit `openapi_extra` machen: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsรคchlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wรคre dafรผr verantwortlich, ihn in irgendeiner Weise zu parsen. +In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsรคchlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wรคre dafรผr verantwortlich, ihn in irgendeiner Weise zu parsen. Dennoch kรถnnen wir das zu erwartende Schema fรผr den Requestbody deklarieren. @@ -151,9 +151,9 @@ Mit demselben Trick kรถnnten Sie ein Pydantic-Modell verwenden, um das JSON-Sche Und Sie kรถnnten dies auch tun, wenn der Datentyp im Request nicht JSON ist. -In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Funktionalitรคt von FastAPI zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung fรผr JSON. Tatsรคchlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON: +In der folgenden Anwendung verwenden wir beispielsweise weder FastAPIs integrierte Funktionalitรคt zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung fรผr JSON. Tatsรคchlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Obwohl wir nicht die standardmรครŸig integrierte Funktionalitรคt verwenden, verwenden wir dennoch ein Pydantic-Modell, um das JSON-Schema fรผr die Daten, die wir in YAML empfangen mรถchten, manuell zu generieren. @@ -161,7 +161,7 @@ Dann verwenden wir den Request direkt und extrahieren den Body als `bytes`. Das Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann wieder dasselbe Pydantic-Modell, um den YAML-Inhalt zu validieren: -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | Tipp diff --git a/docs/de/docs/advanced/response-change-status-code.md b/docs/de/docs/advanced/response-change-status-code.md index b209c2d671..26308b8239 100644 --- a/docs/de/docs/advanced/response-change-status-code.md +++ b/docs/de/docs/advanced/response-change-status-code.md @@ -20,7 +20,7 @@ Sie kรถnnen einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* AnschlieรŸend kรถnnen Sie den `status_code` in diesem *vorรผbergehenden* Response-Objekt festlegen. -{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *} +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} Und dann kรถnnen Sie jedes benรถtigte Objekt zurรผckgeben, wie Sie es normalerweise tun wรผrden (ein `dict`, ein Datenbankmodell usw.). diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md index 87e636cfaf..bf6c40e61b 100644 --- a/docs/de/docs/advanced/response-cookies.md +++ b/docs/de/docs/advanced/response-cookies.md @@ -6,7 +6,7 @@ Sie kรถnnen einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* Und dann kรถnnen Sie Cookies in diesem *vorรผbergehenden* Response-Objekt setzen. -{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *} +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} AnschlieรŸend kรถnnen Sie wie gewohnt jedes gewรผnschte Objekt zurรผckgeben (ein `dict`, ein Datenbankmodell, usw.). @@ -24,7 +24,7 @@ Dazu kรถnnen Sie eine Response erstellen, wie unter [Eine Response direkt zurรผc Setzen Sie dann Cookies darin und geben Sie sie dann zurรผck: -{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | Tipp diff --git a/docs/de/docs/advanced/response-directly.md b/docs/de/docs/advanced/response-directly.md index 0a28a6d0e2..06bea4794d 100644 --- a/docs/de/docs/advanced/response-directly.md +++ b/docs/de/docs/advanced/response-directly.md @@ -54,7 +54,7 @@ Nehmen wir an, Sie mรถchten eine Response-Objekt festlegen. -{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *} +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} AnschlieรŸend kรถnnen Sie wie gewohnt jedes gewรผnschte Objekt zurรผckgeben (ein `dict`, ein Datenbankmodell, usw.). @@ -22,7 +22,7 @@ Sie kรถnnen auch Header hinzufรผgen, wenn Sie eine `Response` direkt zurรผckgebe Erstellen Sie eine Response wie in [Eine Response direkt zurรผckgeben](response-directly.md){.internal-link target=_blank} beschrieben und รผbergeben Sie die Header als zusรคtzlichen Parameter: -{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *} +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} /// note | Technische Details diff --git a/docs/de/docs/advanced/security/http-basic-auth.md b/docs/de/docs/advanced/security/http-basic-auth.md index f906ecd92b..2f66587b19 100644 --- a/docs/de/docs/advanced/security/http-basic-auth.md +++ b/docs/de/docs/advanced/security/http-basic-auth.md @@ -20,7 +20,7 @@ Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser di * Diese gibt ein Objekt vom Typ `HTTPBasicCredentials` zurรผck: * Es enthรคlt den gesendeten `username` und das gesendete `password`. -{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} Wenn Sie versuchen, die URL zum ersten Mal zu รถffnen (oder in der Dokumentation auf den Button โ€žExecuteโ€œ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen: @@ -40,7 +40,7 @@ Um dies zu lรถsen, konvertieren wir zunรคchst den `username` und das `password` Dann kรถnnen wir `secrets.compare_digest()` verwenden, um sicherzustellen, dass `credentials.username` `"stanleyjobson"` und `credentials.password` `"swordfish"` ist. -{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} Dies wรคre das gleiche wie: @@ -104,4 +104,4 @@ So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, v Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurรผck (derselbe, der auch zurรผckgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fรผgen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt: -{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *} +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/de/docs/advanced/settings.md b/docs/de/docs/advanced/settings.md index ea4540e10e..f83e635a78 100644 --- a/docs/de/docs/advanced/settings.md +++ b/docs/de/docs/advanced/settings.md @@ -46,12 +46,6 @@ $ pip install "fastapi[all]"
-/// info | Info - -In Pydantic v1 war es im Hauptpackage enthalten. Jetzt wird es als unabhรคngiges Package verteilt, sodass Sie wรคhlen kรถnnen, ob Sie es installieren mรถchten oder nicht, falls Sie die Funktionalitรคt nicht benรถtigen. - -/// - ### Das `Settings`-Objekt erstellen { #create-the-settings-object } Importieren Sie `BaseSettings` aus Pydantic und erstellen Sie eine Unterklasse, ganz รคhnlich wie bei einem Pydantic-Modell. @@ -60,7 +54,7 @@ Auf die gleiche Weise wie bei Pydantic-Modellen deklarieren Sie Klassenattribute Sie kรถnnen dieselben Validierungs-Funktionen und -Tools verwenden, die Sie fรผr Pydantic-Modelle verwenden, z. B. verschiedene Datentypen und zusรคtzliche Validierungen mit `Field()`. -{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} /// tip | Tipp @@ -76,7 +70,7 @@ Als Nรคchstes werden die Daten konvertiert und validiert. Wenn Sie also dieses ` Dann kรถnnen Sie das neue `settings`-Objekt in Ihrer Anwendung verwenden: -{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} ### Den Server ausfรผhren { #run-the-server } @@ -110,11 +104,11 @@ Sie kรถnnten diese Einstellungen in eine andere Moduldatei einfรผgen, wie Sie in Sie kรถnnten beispielsweise eine Datei `config.py` haben mit: -{* ../../docs_src/settings/app01_py39/config.py *} +{* ../../docs_src/settings/app01_py310/config.py *} Und dann verwenden Sie diese in einer Datei `main.py`: -{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} /// tip | Tipp @@ -132,7 +126,7 @@ Dies kรถnnte besonders beim Testen nรผtzlich sein, da es sehr einfach ist, eine Ausgehend vom vorherigen Beispiel kรถnnte Ihre Datei `config.py` so aussehen: -{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen. @@ -140,7 +134,7 @@ Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erste Jetzt erstellen wir eine Abhรคngigkeit, die ein neues `config.Settings()` zurรผckgibt. -{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} /// tip | Tipp @@ -152,13 +146,13 @@ Im Moment nehmen Sie an, dass `get_settings()` eine normale Funktion ist. Und dann kรถnnen wir das von der *Pfadoperation-Funktion* als Abhรคngigkeit einfordern und es รผberall dort verwenden, wo wir es brauchen. -{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} ### Einstellungen und Tests { #settings-and-testing } Dann wรคre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhรคngigkeitsรผberschreibung fรผr `get_settings` erstellt: -{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} Bei der Abhรคngigkeitsรผberschreibung legen wir einen neuen Wert fรผr `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurรผck. @@ -199,7 +193,7 @@ APP_NAME="ChimichangApp" Und dann aktualisieren Sie Ihre `config.py` mit: -{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} /// tip | Tipp @@ -232,7 +226,7 @@ wรผrden wir dieses Objekt fรผr jeden Request erstellen und die `.env`-Datei fรผr Da wir jedoch den `@lru_cache`-Dekorator oben verwenden, wird das `Settings`-Objekt nur einmal erstellt, nรคmlich beim ersten Aufruf. โœ”๏ธ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} Dann wird bei allen nachfolgenden Aufrufen von `get_settings()`, in den Abhรคngigkeiten fรผr darauffolgende Requests, dasselbe Objekt zurรผckgegeben, das beim ersten Aufruf zurรผckgegeben wurde, anstatt den Code von `get_settings()` erneut auszufรผhren und ein neues `Settings`-Objekt zu erstellen. diff --git a/docs/de/docs/advanced/sub-applications.md b/docs/de/docs/advanced/sub-applications.md index 081574d0a9..6b862b44e0 100644 --- a/docs/de/docs/advanced/sub-applications.md +++ b/docs/de/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ Wenn Sie zwei unabhรคngige FastAPI-Anwendungen mit deren eigenen unabhรคngigen O Erstellen Sie zunรคchst die Hauptanwendung **FastAPI** und deren *Pfadoperationen*: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### Unteranwendung { #sub-application } @@ -18,7 +18,7 @@ Erstellen Sie dann Ihre Unteranwendung und deren *Pfadoperationen*. Diese Unteranwendung ist nur eine weitere Standard-FastAPI-Anwendung, aber diese wird โ€žgemountetโ€œ: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### Die Unteranwendung mounten { #mount-the-sub-application } @@ -26,7 +26,7 @@ Mounten Sie in Ihrer Top-Level-Anwendung `app` die Unteranwendung `subapi`. In diesem Fall wird sie im Pfad `/subapi` gemountet: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### Die automatische API-Dokumentation testen { #check-the-automatic-api-docs } diff --git a/docs/de/docs/advanced/templates.md b/docs/de/docs/advanced/templates.md index 97a45e6126..87baba3594 100644 --- a/docs/de/docs/advanced/templates.md +++ b/docs/de/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 * Deklarieren Sie einen `Request`-Parameter in der *Pfadoperation*, welcher ein Template zurรผckgibt. * Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurรผckzugeben, รผbergeben Sie den Namen des Templates, das Requestobjekt und ein โ€žKontextโ€œ-Dictionary mit Schlรผssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen. -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note | Hinweis diff --git a/docs/de/docs/advanced/testing-events.md b/docs/de/docs/advanced/testing-events.md index 5b12f3f186..053aeffc8a 100644 --- a/docs/de/docs/advanced/testing-events.md +++ b/docs/de/docs/advanced/testing-events.md @@ -2,11 +2,11 @@ Wenn Sie `lifespan` in Ihren Tests ausfรผhren mรผssen, kรถnnen Sie den `TestClient` mit einer `with`-Anweisung verwenden: -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} Sie kรถnnen mehr Details unter [โ€žLifespan in Tests ausfรผhren in der offiziellen Starlette-Dokumentation.โ€œ](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) nachlesen. Fรผr die deprecateten Events `startup` und `shutdown` kรถnnen Sie den `TestClient` wie folgt verwenden: -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/de/docs/advanced/testing-websockets.md b/docs/de/docs/advanced/testing-websockets.md index 9ecca7a4f7..4bc46da3ea 100644 --- a/docs/de/docs/advanced/testing-websockets.md +++ b/docs/de/docs/advanced/testing-websockets.md @@ -4,7 +4,7 @@ Sie kรถnnen den schon bekannten `TestClient` zum Testen von WebSockets verwenden Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung zum WebSocket herstellend: -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | Hinweis diff --git a/docs/de/docs/advanced/using-request-directly.md b/docs/de/docs/advanced/using-request-directly.md index 36d73b8067..bed1cdbea3 100644 --- a/docs/de/docs/advanced/using-request-directly.md +++ b/docs/de/docs/advanced/using-request-directly.md @@ -29,7 +29,7 @@ Angenommen, Sie mรถchten auf die IP-Adresse/den Host des Clients in Ihrer *Pfado Dazu mรผssen Sie direkt auf den Request zugreifen. -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} Durch die Deklaration eines *Pfadoperation-Funktionsparameters*, dessen Typ der `Request` ist, weiรŸ **FastAPI**, dass es den `Request` diesem Parameter รผbergeben soll. diff --git a/docs/de/docs/advanced/websockets.md b/docs/de/docs/advanced/websockets.md index 05ae5a4b31..b1a49c5aad 100644 --- a/docs/de/docs/advanced/websockets.md +++ b/docs/de/docs/advanced/websockets.md @@ -38,13 +38,13 @@ In der Produktion hรคtten Sie eine der oben genannten Optionen. Aber es ist der einfachste Weg, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben: -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## Einen `websocket` erstellen { #create-a-websocket } Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`: -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | Technische Details @@ -58,7 +58,7 @@ Sie kรถnnten auch `from starlette.websockets import WebSocket` verwenden. In Ihrer WebSocket-Route kรถnnen Sie Nachrichten `await`en und Nachrichten senden. -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} Sie kรถnnen Binรคr-, Text- und JSON-Daten empfangen und senden. @@ -154,7 +154,7 @@ Damit kรถnnen Sie den WebSocket verbinden und dann Nachrichten senden und empfan Wenn eine WebSocket-Verbindung geschlossen wird, lรถst `await websocket.receive_text()` eine `WebSocketDisconnect`-Exception aus, die Sie dann wie in folgendem Beispiel abfangen und behandeln kรถnnen. -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} Zum Ausprobieren: diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md index 0090883cea..b2f170e80b 100644 --- a/docs/de/docs/advanced/wsgi.md +++ b/docs/de/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware. Und dann mounten Sie das auf einem Pfad. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | Hinweis diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md index 4dd127dbad..b6509ec09d 100644 --- a/docs/de/docs/alternatives.md +++ b/docs/de/docs/alternatives.md @@ -20,7 +20,7 @@ Es ist das beliebteste Python-Framework und genieรŸt groรŸes Vertrauen. Es wird Es ist relativ eng mit relationalen Datenbanken (wie MySQL oder PostgreSQL) gekoppelt, daher ist es nicht sehr einfach, eine NoSQL-Datenbank (wie Couchbase, MongoDB, Cassandra, usw.) als Hauptspeicherengine zu verwenden. -Es wurde erstellt, um den HTML-Code im Backend zu generieren, nicht um APIs zu erstellen, die von einem modernen Frontend (wie React, Vue.js und Angular) oder von anderen Systemen (wie IoT-Gerรคten) verwendet werden, um mit ihm zu kommunizieren. +Es wurde erstellt, um den HTML-Code im Backend zu generieren, nicht um APIs zu erstellen, die von einem modernen Frontend (wie React, Vue.js und Angular) oder von anderen Systemen (wie IoT-Gerรคten) verwendet werden, um mit ihm zu kommunizieren. ### Django REST Framework { #django-rest-framework } @@ -82,7 +82,7 @@ Aus diesem Grund heiรŸt es auf der offiziellen Website: > Requests ist eines der am hรคufigsten heruntergeladenen Python-Packages aller Zeiten -Die Art und Weise, wie Sie es verwenden, ist sehr einfach. Um beispielsweise einen `GET`-Request zu machen, wรผrden Sie schreiben: +Die Art und Weise, wie Sie es verwenden, ist sehr einfach. Um beispielsweise einen `GET`-Request zu machen, wรผrden Sie schreiben: ```Python response = requests.get("http://example.com/some/url") @@ -137,7 +137,7 @@ Es gibt mehrere Flask REST Frameworks, aber nachdem ich die Zeit und Arbeit inve ### Marshmallow { #marshmallow } -Eine der von API-Systemen benรถtigten Hauptfunktionen ist die Daten-โ€žSerialisierungโ€œ, welche Daten aus dem Code (Python) entnimmt und in etwas umwandelt, was durch das Netzwerk gesendet werden kann. Beispielsweise das Konvertieren eines Objekts, welches Daten aus einer Datenbank enthรคlt, in ein JSON-Objekt. Konvertieren von `datetime`-Objekten in Strings, usw. +Eine der von API-Systemen benรถtigten Hauptfunktionen ist die Daten-โ€žSerialisierungโ€œ, welche Daten aus dem Code (Python) entnimmt und in etwas umwandelt, was durch das Netzwerk gesendet werden kann. Beispielsweise das Konvertieren eines Objekts, welches Daten aus einer Datenbank enthรคlt, in ein JSON-Objekt. Konvertieren von `datetime`-Objekten in Strings, usw. Eine weitere wichtige Funktion, benรถtigt von APIs, ist die Datenvalidierung, welche sicherstellt, dass die Daten unter gegebenen Umstรคnden gรผltig sind. Zum Beispiel, dass ein Feld ein `int` ist und kein zufรคlliger String. Das ist besonders nรผtzlich fรผr hereinkommende Daten. @@ -145,7 +145,7 @@ Ohne ein Datenvalidierungssystem mรผssten Sie alle Prรผfungen manuell im Code du Fรผr diese Funktionen wurde Marshmallow entwickelt. Es ist eine groรŸartige Bibliothek und ich habe sie schon oft genutzt. -Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein Schema zu definieren, mรผssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden. +Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein Schema zu definieren, mรผssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden. /// check | Inspirierte **FastAPI** @@ -155,7 +155,7 @@ Code zu verwenden, um โ€žSchemasโ€œ zu definieren, welche Datentypen und Validie ### Webargs { #webargs } -Eine weitere wichtige Funktion, die von APIs benรถtigt wird, ist das Parsen von Daten aus eingehenden Requests. +Eine weitere wichtige Funktion, die von APIs benรถtigt wird, ist das Parsen von Daten aus eingehenden Requests. Webargs wurde entwickelt, um dieses fรผr mehrere Frameworks, einschlieรŸlich Flask, bereitzustellen. @@ -283,7 +283,7 @@ Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste ver Falcon ist ein weiteres leistungsstarkes Python-Framework. Es ist minimalistisch konzipiert und dient als Grundlage fรผr andere Frameworks wie Hug. -Es ist so konzipiert, dass es รผber Funktionen verfรผgt, welche zwei Parameter empfangen, einen โ€žRequestโ€œ und eine โ€žResponseโ€œ. Dann โ€žlesenโ€œ Sie Teile des Requests und โ€žschreibenโ€œ Teile der Response. Aufgrund dieses Designs ist es nicht mรถglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. +Es ist so konzipiert, dass es รผber Funktionen verfรผgt, welche zwei Parameter empfangen, einen โ€žRequestโ€œ und eine โ€žResponseโ€œ. Dann โ€žlesenโ€œ Sie Teile des Requests und โ€žschreibenโ€œ Teile der Response. Aufgrund dieses Designs ist es nicht mรถglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. Daher mรผssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie mรผssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben. @@ -419,7 +419,7 @@ Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumen ### Starlette { #starlette } -Starlette ist ein leichtgewichtiges ASGI-Framework/Toolkit, welches sich ideal fรผr die Erstellung hochperformanter asynchroner Dienste eignet. +Starlette ist ein leichtgewichtiges ASGI-Framework/Toolkit, welches sich ideal fรผr die Erstellung hochperformanter asynchroner Dienste eignet. Es ist sehr einfach und intuitiv. Es ist so konzipiert, dass es leicht erweiterbar ist und รผber modulare Komponenten verfรผgt. diff --git a/docs/de/docs/benchmarks.md b/docs/de/docs/benchmarks.md index 09126c5d99..285d35bf93 100644 --- a/docs/de/docs/benchmarks.md +++ b/docs/de/docs/benchmarks.md @@ -23,7 +23,7 @@ Die Hierarchie ist wie folgt: * Sie wรผrden eine Anwendung nicht direkt in Uvicorn schreiben. Das wรผrde bedeuten, dass Ihr Code zumindest mehr oder weniger den gesamten von Starlette (oder **FastAPI**) bereitgestellten Code enthalten mรผsste. Und wenn Sie das tรคten, hรคtte Ihre endgรผltige Anwendung den gleichen Overhead wie bei der Verwendung eines Frameworks und der Minimierung Ihres Anwendungscodes und der Fehler. * Wenn Sie Uvicorn vergleichen, vergleichen Sie es mit Anwendungsservern wie Daphne, Hypercorn, uWSGI, usw. * **Starlette**: - * Wird nach Uvicorn die nรคchstbeste Performanz erbringen. Tatsรคchlich verwendet Starlette intern Uvicorn, um zu laufen. Daher kann es wahrscheinlich nur โ€žlangsamerโ€œ als Uvicorn werden, weil mehr Code ausgefรผhrt werden muss. + * Wird nach Uvicorn die nรคchstbeste Performanz erbringen. Tatsรคchlich verwendet Starlette Uvicorn, um zu laufen. Daher kann es wahrscheinlich nur โ€žlangsamerโ€œ als Uvicorn werden, weil mehr Code ausgefรผhrt werden muss. * Aber es bietet Ihnen die Werkzeuge, um einfache Webanwendungen zu erstellen, mit Routing basierend auf Pfaden, usw. * Wenn Sie Starlette vergleichen, vergleichen Sie es mit Webframeworks (oder Mikroframeworks) wie Sanic, Flask, Django, usw. * **FastAPI**: diff --git a/docs/de/docs/deployment/cloud.md b/docs/de/docs/deployment/cloud.md index ad3ff76dbf..08a554b8d6 100644 --- a/docs/de/docs/deployment/cloud.md +++ b/docs/de/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # FastAPI bei Cloudanbietern deployen { #deploy-fastapi-on-cloud-providers } -Sie kรถnnen praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen. +Sie kรถnnen praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung zu deployen. In den meisten Fรคllen bieten die groรŸen Cloudanbieter Anleitungen zum Deployment von FastAPI an. diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md index 1e28efe521..704311b264 100644 --- a/docs/de/docs/deployment/docker.md +++ b/docs/de/docs/deployment/docker.md @@ -14,7 +14,7 @@ Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` u Dockerfile-Vorschau ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ Erstellen Sie nun im selben Projektverzeichnis eine Datei `Dockerfile` mit: ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ Wenn Ihr FastAPI eine einzelne Datei ist, zum Beispiel `main.py` ohne ein `./app Dann mรผssten Sie nur noch die entsprechenden Pfade รคndern, um die Datei im `Dockerfile` zu kopieren: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Ohne die Verwendung von Containern kann es umstรคndlich und schwierig sein, Anwe ## Replikation โ€“ Anzahl der Prozesse { #replication-number-of-processes } -Wenn Sie einen Cluster von Maschinen mit **Kubernetes**, Docker Swarm Mode, Nomad verwenden, oder einem anderen, รคhnlich komplexen System zur Verwaltung verteilter Container auf mehreren Maschinen, mรถchten Sie wahrscheinlich die **Replikation auf Cluster-Ebene abwickeln**, anstatt in jedem Container einen **Prozessmanager** (wie Uvicorn mit Workern) zu verwenden. +Wenn Sie einen Cluster von Maschinen mit **Kubernetes**, Docker Swarm Mode, Nomad verwenden, oder einem anderen, รคhnlich komplexen System zur Verwaltung verteilter Container auf mehreren Maschinen, mรถchten Sie wahrscheinlich die **Replikation auf Cluster-Ebene abwickeln**, anstatt in jedem Container einen **Prozessmanager** (wie Uvicorn mit Workern) zu verwenden. Diese verteilten Containerverwaltungssysteme wie Kubernetes verfรผgen normalerweise รผber eine integrierte Mรถglichkeit, die **Replikation von Containern** zu handhaben und gleichzeitig **Load Balancing** fรผr die eingehenden Requests zu unterstรผtzen. Alles auf **Cluster-Ebene**. @@ -499,7 +499,7 @@ Natรผrlich gibt es **Sonderfรคlle**, in denen Sie **einen Container** mit mehrer In diesen Fรคllen kรถnnen Sie die `--workers` Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -570,7 +570,7 @@ Wenn Sie ein einfaches Setup mit einem **einzelnen Container** haben, welcher da ### Docker-Basisimage { #base-docker-image } -Es gab ein offizielles FastAPI-Docker-Image: tiangolo/uvicorn-gunicorn-fastapi. Dieses ist jedoch jetzt veraltet. โ›”๏ธ +Es gab ein offizielles FastAPI-Docker-Image: tiangolo/uvicorn-gunicorn-fastapi. Dieses ist jedoch jetzt deprecatet. โ›”๏ธ Sie sollten wahrscheinlich **nicht** dieses Basis-Docker-Image (oder ein anderes รคhnliches) verwenden. diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index 1c4ce6b44f..08963306fb 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -65,7 +65,7 @@ Hier ist ein Beispiel, wie eine HTTPS-API aussehen kรถnnte, Schritt fรผr Schritt Alles beginnt wahrscheinlich damit, dass Sie einen **Domainnamen erwerben**. AnschlieรŸend konfigurieren Sie ihn in einem DNS-Server (wahrscheinlich beim selben Cloudanbieter). -Sie wรผrden wahrscheinlich einen Cloud-Server (eine virtuelle Maschine) oder etwas ร„hnliches bekommen, und dieser hรคtte eine feste **รถffentliche IP-Adresse**. +Sie wรผrden wahrscheinlich einen Cloud-Server (eine virtuelle Maschine) oder etwas ร„hnliches bekommen, und dieser hรคtte eine feste **รถffentliche IP-Adresse**. In dem oder den DNS-Server(n) wรผrden Sie einen Eintrag (einen โ€ž`A record`โ€œ) konfigurieren, um mit **Ihrer Domain** auf die รถffentliche **IP-Adresse Ihres Servers** zu verweisen. diff --git a/docs/de/docs/deployment/index.md b/docs/de/docs/deployment/index.md index cb3e537463..0c83cc529d 100644 --- a/docs/de/docs/deployment/index.md +++ b/docs/de/docs/deployment/index.md @@ -4,7 +4,7 @@ Das Deployment einer **FastAPI**-Anwendung ist relativ einfach. ## Was bedeutet Deployment { #what-does-deployment-mean } -**Deployment** bedeutet, die notwendigen Schritte durchzufรผhren, um die Anwendung **fรผr die Endbenutzer verfรผgbar** zu machen. +**Deployment** bedeutet, die notwendigen Schritte durchzufรผhren, um die Anwendung **fรผr die Benutzer verfรผgbar** zu machen. Bei einer **Web-API** bedeutet das normalerweise, diese auf einem **entfernten Rechner** zu platzieren, mit einem **Serverprogramm**, welches gute Leistung, Stabilitรคt, usw. bietet, damit Ihre **Benutzer** auf die Anwendung effizient und ohne Unterbrechungen oder Probleme **zugreifen** kรถnnen. diff --git a/docs/de/docs/deployment/server-workers.md b/docs/de/docs/deployment/server-workers.md index 7b68f1b1a6..fbc9f69067 100644 --- a/docs/de/docs/deployment/server-workers.md +++ b/docs/de/docs/deployment/server-workers.md @@ -119,7 +119,7 @@ In der Liste der Deployment-Konzepte von oben wรผrde die Verwendung von Workern * **Sicherheit โ€“ HTTPS** * **Beim Hochfahren ausfรผhren** -* **Neustarts** +* ***Neustarts*** * Replikation (die Anzahl der laufenden Prozesse) * **Arbeitsspeicher** * **Schritte vor dem Start** diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index 0b51e9737a..6b7b4c296e 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -6,7 +6,7 @@ ### Basiert auf offenen Standards { #based-on-open-standards } -* OpenAPI fรผr die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. +* OpenAPI fรผr die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. * Automatische Dokumentation der Datenmodelle mit JSON Schema (da OpenAPI selbst auf JSON Schema basiert). * Um diese Standards herum entworfen, nach sorgfรคltigem Studium. Statt einer nachtrรคglichen Schicht darรผber. * Dies ermรถglicht auch automatische **Client-Code-Generierung** in vielen Sprachen. @@ -136,7 +136,7 @@ Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Sy ### Dependency Injection { #dependency-injection } -FastAPI enthรคlt ein extrem einfach zu verwendendes, aber extrem mรคchtiges Dependency Injection System. +FastAPI enthรคlt ein extrem einfach zu verwendendes, aber extrem mรคchtiges Dependency Injection System. * Selbst Abhรคngigkeiten kรถnnen Abhรคngigkeiten haben, woraus eine Hierarchie oder ein **โ€žGraphโ€œ von Abhรคngigkeiten** entsteht. * Alles **automatisch gehandhabt** durch das Framework. @@ -153,8 +153,8 @@ Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abh ### Getestet { #tested } -* 100 % Testabdeckung. -* 100 % Typen annotiert. +* 100 % Testabdeckung. +* 100 % Typen annotiert. * Verwendet in Produktionsanwendungen. ## Starlette Merkmale { #starlette-features } @@ -179,7 +179,7 @@ Mit **FastAPI** bekommen Sie alles von **Starlette** (da FastAPI nur Starlette a **FastAPI** ist vollkommen kompatibel (und basiert auf) Pydantic. Das bedeutet, wenn Sie eigenen Pydantic Quellcode haben, funktioniert der. -Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs fรผr Datenbanken. +Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs fรผr Datenbanken. Daher kรถnnen Sie in vielen Fรคllen das Objekt eines Requests **direkt zur Datenbank** schicken, weil alles automatisch validiert wird. @@ -190,7 +190,7 @@ Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI fรผr d * **Kein Kopfzerbrechen**: * Keine neue Schemadefinition-Mikrosprache zu lernen. * Wenn Sie Pythons Typen kennen, wissen Sie, wie man Pydantic verwendet. -* Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: +* Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollstรคndigung, Linting, mypy und Ihre Intuition sollten alle einwandfrei mit Ihren validierten Daten funktionieren. * Validierung von **komplexen Strukturen**: * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, etc. diff --git a/docs/de/docs/history-design-future.md b/docs/de/docs/history-design-future.md index 45198ff1cb..0217f42768 100644 --- a/docs/de/docs/history-design-future.md +++ b/docs/de/docs/history-design-future.md @@ -58,7 +58,7 @@ Nachdem ich mehrere Alternativen getestet hatte, entschied ich, dass ich **Starlette** beigetragen, der anderen Schlรผsselanforderung. +Wรคhrend der Entwicklung habe ich auch zu **Starlette** beigetragen, die andere Schlรผsselanforderung. ## Entwicklung { #development } diff --git a/docs/de/docs/how-to/authentication-error-status-code.md b/docs/de/docs/how-to/authentication-error-status-code.md index c743b54d9e..2d54926ff8 100644 --- a/docs/de/docs/how-to/authentication-error-status-code.md +++ b/docs/de/docs/how-to/authentication-error-status-code.md @@ -8,7 +8,7 @@ Aber falls Ihre Clients aus irgendeinem Grund vom alten Verhalten abhรคngen, kรถ Sie kรถnnen beispielsweise eine Unterklasse von `HTTPBearer` erstellen, die einen Fehler `403 Forbidden` zurรผckgibt, statt des Default-`401 Unauthorized`-Fehlers: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | Tipp diff --git a/docs/de/docs/how-to/conditional-openapi.md b/docs/de/docs/how-to/conditional-openapi.md index 6e665cc4c0..07573f01f9 100644 --- a/docs/de/docs/how-to/conditional-openapi.md +++ b/docs/de/docs/how-to/conditional-openapi.md @@ -29,7 +29,7 @@ Sie kรถnnen problemlos dieselben Pydantic-Einstellungen verwenden, um Ihre gener Zum Beispiel: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} Hier deklarieren wir die Einstellung `openapi_url` mit dem gleichen Defaultwert `"/openapi.json"`. diff --git a/docs/de/docs/how-to/configure-swagger-ui.md b/docs/de/docs/how-to/configure-swagger-ui.md index 1c3f5c0c5a..efb57339c5 100644 --- a/docs/de/docs/how-to/configure-swagger-ui.md +++ b/docs/de/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ Ohne ร„nderung der Einstellungen ist die Syntaxhervorhebung standardmรครŸig akti Sie kรถnnen sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` setzen: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ... und dann zeigt die Swagger-Oberflรคche die Syntaxhervorhebung nicht mehr an: @@ -28,7 +28,7 @@ Sie kรถnnen sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` set Auf die gleiche Weise kรถnnten Sie das Theme der Syntaxhervorhebung mit dem Schlรผssel `"syntaxHighlight.theme"` festlegen (beachten Sie, dass er einen Punkt in der Mitte hat): -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} Obige Konfiguration wรผrde das Theme fรผr die Farbe der Syntaxhervorhebung รคndern: @@ -46,7 +46,7 @@ Sie kรถnnen jede davon รผberschreiben, indem Sie im Argument `swagger_ui_paramet Um beispielsweise `deepLinking` zu deaktivieren, kรถnnten Sie folgende Einstellungen an `swagger_ui_parameters` รผbergeben: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## Andere Parameter der Swagger-Oberflรคche { #other-swagger-ui-parameters } diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md index 6b1d654adf..a34a21a31d 100644 --- a/docs/de/docs/how-to/custom-docs-ui-assets.md +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -18,7 +18,7 @@ Der erste Schritt besteht darin, die automatischen Dokumentationen zu deaktivier Um diese zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### Die benutzerdefinierten Dokumentationen hinzufรผgen { #include-the-custom-docs } @@ -34,7 +34,7 @@ Sie kรถnnen die internen Funktionen von FastAPI wiederverwenden, um die HTML-Sei Und รคhnlich fรผr ReDoc ... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | Tipp @@ -50,7 +50,7 @@ Swagger UI erledigt das hinter den Kulissen fรผr Sie, benรถtigt aber diesen โ€žU Um nun testen zu kรถnnen, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### Es testen { #test-it } @@ -118,7 +118,7 @@ Danach kรถnnte Ihre Dateistruktur wie folgt aussehen: * Importieren Sie `StaticFiles`. * โ€žMountenโ€œ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### Die statischen Dateien testen { #test-the-static-files } @@ -144,7 +144,7 @@ Wie bei der Verwendung eines benutzerdefinierten CDN besteht der erste Schritt d Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### Die benutzerdefinierten Dokumentationen fรผr statische Dateien hinzufรผgen { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ Auch hier kรถnnen Sie die internen Funktionen von FastAPI wiederverwenden, um di Und รคhnlich fรผr ReDoc ... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | Tipp @@ -176,7 +176,7 @@ Swagger UI erledigt das hinter den Kulissen fรผr Sie, benรถtigt aber diesen โ€žU Um nun testen zu kรถnnen, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### Benutzeroberflรคche mit statischen Dateien testen { #test-static-files-ui } diff --git a/docs/de/docs/how-to/extending-openapi.md b/docs/de/docs/how-to/extending-openapi.md index c07ed2aa08..d23dc4df0d 100644 --- a/docs/de/docs/how-to/extending-openapi.md +++ b/docs/de/docs/how-to/extending-openapi.md @@ -43,19 +43,19 @@ Fรผgen wir beispielsweise Requests
verwendet. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} ### Die Methode รผberschreiben { #override-the-method } Jetzt kรถnnen Sie die Methode `.openapi()` durch Ihre neue Funktion ersetzen. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} ### Es testen { #check-it } diff --git a/docs/de/docs/how-to/graphql.md b/docs/de/docs/how-to/graphql.md index 5c908cec4a..1f0c96eef2 100644 --- a/docs/de/docs/how-to/graphql.md +++ b/docs/de/docs/how-to/graphql.md @@ -35,7 +35,7 @@ Abhรคngig von Ihrem Anwendungsfall kรถnnten Sie eine andere Bibliothek vorziehen Hier ist eine kleine Vorschau, wie Sie Strawberry mit FastAPI integrieren kรถnnen: -{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Weitere Informationen zu Strawberry finden Sie in der Strawberry-Dokumentation. diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index 3ce5cb27ff..bb28c68f70 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -40,7 +40,7 @@ Seine Schlรผssel-Merkmale sind: * **Schnell**: Sehr hohe Performanz, auf Augenhรถhe mit **NodeJS** und **Go** (dank Starlette und Pydantic). [Eines der schnellsten verfรผgbaren Python-Frameworks](#performance). * **Schnell zu entwickeln**: Erhรถhen Sie die Geschwindigkeit bei der Entwicklung von Features um etwa 200 % bis 300 %. * * **Weniger Bugs**: Verringern Sie die von Menschen (Entwicklern) verursachten Fehler um etwa 40 %. * -* **Intuitiv**: Hervorragende Editor-Unterstรผtzung. Code-Vervollstรคndigung รผberall. Weniger Zeit mit Debuggen verbringen. +* **Intuitiv**: Hervorragende Editor-Unterstรผtzung. Code-Vervollstรคndigung รผberall. Weniger Zeit mit Debuggen verbringen. * **Einfach**: So konzipiert, dass es einfach zu benutzen und zu erlernen ist. Weniger Zeit mit dem Lesen von Dokumentation verbringen. * **Kurz**: Minimieren Sie die Verdoppelung von Code. Mehrere Features aus jeder Parameterdeklaration. Weniger Bugs. * **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation. @@ -363,12 +363,12 @@ item: Item ... und mit dieser einen Deklaration erhalten Sie: * Editor-Unterstรผtzung, einschlieรŸlich: - * Code-Vervollstรคndigung. + * Vervollstรคndigung. * Typprรผfungen. * Validierung von Daten: * Automatische und eindeutige Fehler, wenn die Daten ungรผltig sind. * Validierung sogar fรผr tief verschachtelte JSON-Objekte. -* Konvertierung von Eingabedaten: Aus dem Netzwerk kommend, zu Python-Daten und -Typen. Lesen von: +* Konvertierung von Eingabedaten: Aus dem Netzwerk kommend, zu Python-Daten und -Typen. Lesen von: * JSON. * Pfad-Parametern. * Query-Parametern. @@ -376,7 +376,7 @@ item: Item * Headern. * Formularen. * Dateien. -* Konvertierung von Ausgabedaten: Konvertierung von Python-Daten und -Typen zu Netzwerkdaten (als JSON): +* Konvertierung von Ausgabedaten: Konvertierung von Python-Daten und -Typen zu Netzwerkdaten (als JSON): * Konvertieren von Python-Typen (`str`, `int`, `float`, `bool`, `list`, usw.). * `datetime`-Objekte. * `UUID`-Objekte. @@ -439,7 +439,7 @@ Fรผr ein vollstรคndigeres Beispiel, mit weiteren Funktionen, siehe das Dependency Injection**. +* Ein sehr leistungsfรคhiges und einfach zu bedienendes System fรผr **Dependency Injection**. * Sicherheit und Authentifizierung, einschlieรŸlich Unterstรผtzung fรผr **OAuth2** mit **JWT-Tokens** und **HTTP Basic** Authentifizierung. * Fortgeschrittenere (aber ebenso einfache) Techniken zur Deklaration **tief verschachtelter JSON-Modelle** (dank Pydantic). * **GraphQL**-Integration mit Strawberry und anderen Bibliotheken. @@ -524,7 +524,7 @@ Verwendet von Starlette: * httpx โ€“ erforderlich, wenn Sie den `TestClient` verwenden mรถchten. * jinja2 โ€“ erforderlich, wenn Sie die Default-Template-Konfiguration verwenden mรถchten. -* python-multipart โ€“ erforderlich, wenn Sie Formulare mittels `request.form()` โ€žparsenโ€œ mรถchten. +* python-multipart โ€“ erforderlich, wenn Sie Formulare mittels `request.form()` โ€žparsenโ€œ mรถchten. Verwendet von FastAPI: diff --git a/docs/de/docs/project-generation.md b/docs/de/docs/project-generation.md index 62702d8529..2c252933d9 100644 --- a/docs/de/docs/project-generation.md +++ b/docs/de/docs/project-generation.md @@ -20,7 +20,7 @@ GitHub-Repository: โ€žTyphinweiseโ€œ (auch โ€žTypannotationenโ€œ genannt). +Python hat Unterstรผtzung fรผr optionale โ€žTyphinweiseโ€œ (auch โ€žTypannotationenโ€œ genannt). -Diese **โ€žTyphinweiseโ€œ** oder -Annotationen sind eine spezielle Syntax, die es erlaubt, den Typ einer Variablen zu deklarieren. +Diese **โ€žTyphinweiseโ€œ** oder -Annotationen sind eine spezielle Syntax, die es erlaubt, den Typ einer Variablen zu deklarieren. Durch das Deklarieren von Typen fรผr Ihre Variablen kรถnnen Editoren und Tools bessere Unterstรผtzung bieten. @@ -22,7 +22,7 @@ Wenn Sie ein Python-Experte sind und bereits alles รผber Typhinweise wissen, รผb Fangen wir mit einem einfachen Beispiel an: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Dieses Programm gibt aus: @@ -34,9 +34,9 @@ Die Funktion macht Folgendes: * Nimmt einen `first_name` und `last_name`. * Schreibt den ersten Buchstaben eines jeden Wortes groรŸ, mithilfe von `title()`. -* Verkettet sie mit einem Leerzeichen in der Mitte. +* Verkettet sie mit einem Leerzeichen in der Mitte. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Es bearbeiten { #edit-it } @@ -78,7 +78,7 @@ Das war's. Das sind die โ€žTyphinweiseโ€œ: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Das ist nicht das gleiche wie das Deklarieren von Defaultwerten, wie es hier der Fall ist: @@ -106,7 +106,7 @@ Hier kรถnnen Sie durch die Optionen blรคttern, bis Sie diejenige finden, bei der Sehen Sie sich diese Funktion an, sie hat bereits Typhinweise: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervollstรคndigung, sondern auch eine Fehlerprรผfung: @@ -114,7 +114,7 @@ Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervoll Jetzt, da Sie wissen, dass Sie das reparieren mรผssen, konvertieren Sie `age` mittels `str(age)` in einen String: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## Deklarieren von Typen { #declaring-types } @@ -133,29 +133,32 @@ Zum Beispiel diese: * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Generische Typen mit Typ-Parametern { #generic-types-with-type-parameters } +### `typing`-Modul { #typing-module } -Es gibt Datenstrukturen, die andere Werte enthalten kรถnnen, wie etwa `dict`, `list`, `set` und `tuple`. Die inneren Werte kรถnnen auch ihren eigenen Typ haben. +Fรผr einige zusรคtzliche Anwendungsfรคlle mรผssen Sie mรถglicherweise Dinge aus dem Standardmodul `typing` importieren. Zum Beispiel, wenn Sie deklarieren mรถchten, dass etwas โ€žjeden Typโ€œ haben kann, kรถnnen Sie `Any` aus `typing` verwenden: -Diese Typen mit inneren Typen werden โ€ž**generische**โ€œ Typen genannt. Es ist mรถglich, sie mit ihren inneren Typen zu deklarieren. +```python +from typing import Any -Um diese Typen und die inneren Typen zu deklarieren, kรถnnen Sie Pythons Standardmodul `typing` verwenden. Es existiert speziell fรผr die Unterstรผtzung dieser Typhinweise. -#### Neuere Python-Versionen { #newer-versions-of-python } - -Die Syntax, welche `typing` verwendet, ist **kompatibel** mit allen Versionen, von Python 3.6 aufwรคrts zu den neuesten, inklusive Python 3.9, Python 3.10, usw. +def some_function(data: Any): + print(data) +``` -Mit der Weiterentwicklung von Python kommen **neuere Versionen** heraus, mit verbesserter Unterstรผtzung fรผr Typannotationen, und in vielen Fรคllen mรผssen Sie gar nicht mehr das `typing`-Modul importieren, um Typannotationen zu schreiben. +### Generische Typen { #generic-types } -Wenn Sie eine neuere Python-Version fรผr Ihr Projekt wรคhlen kรถnnen, werden Sie aus dieser zusรคtzlichen Vereinfachung Nutzen ziehen kรถnnen. +Einige Typen kรถnnen โ€žTyp-Parameterโ€œ in eckigen Klammern annehmen, um ihre inneren Typen zu definieren, z. B. eine โ€žListe von Stringsโ€œ wรผrde als `list[str]` deklariert. -In der gesamten Dokumentation gibt es Beispiele, welche kompatibel mit unterschiedlichen Python-Versionen sind (wenn es Unterschiede gibt). +Diese Typen, die Typ-Parameter annehmen kรถnnen, werden **generische Typen** oder **Generics** genannt. -Zum Beispiel bedeutet โ€ž**Python 3.6+**โ€œ, dass das Beispiel kompatibel mit Python 3.6 oder hรถher ist (inklusive 3.7, 3.8, 3.9, 3.10, usw.). Und โ€ž**Python 3.9+**โ€œ bedeutet, es ist kompatibel mit Python 3.9 oder hรถher (inklusive 3.10, usw.). +Sie kรถnnen dieselben eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin): -Wenn Sie รผber die **neueste Version von Python** verfรผgen, verwenden Sie die Beispiele fรผr die neueste Version, diese werden die **beste und einfachste Syntax** haben, zum Beispiel, โ€ž**Python 3.10+**โ€œ. +* `list` +* `tuple` +* `set` +* `dict` #### Liste { #list } @@ -167,7 +170,7 @@ Als Typ nehmen Sie `list`. Da die Liste ein Typ ist, welcher innere Typen enthรคlt, werden diese von eckigen Klammern umfasst: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | Info @@ -193,7 +196,7 @@ Und trotzdem weiรŸ der Editor, dass es sich um ein `str` handelt, und bietet ent Das Gleiche gilt fรผr die Deklaration eines Tupels โ€“ `tuple` โ€“ und einer Menge โ€“ `set`: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} Das bedeutet: @@ -208,7 +211,7 @@ Der erste Typ-Parameter ist fรผr die Schlรผssel des `dict`. Der zweite Typ-Parameter ist fรผr die Werte des `dict`: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Das bedeutet: @@ -216,47 +219,23 @@ Das bedeutet: * Die Schlรผssel dieses `dict` sind vom Typ `str` (z. B. die Namen der einzelnen Artikel). * Die Werte dieses `dict` sind vom Typ `float` (z. B. der Preis jedes Artikels). -#### Union { #union } +#### Union { #union } Sie kรถnnen deklarieren, dass eine Variable einer von **verschiedenen Typen** sein kann, zum Beispiel ein `int` oder ein `str`. -In Python 3.6 und hรถher (inklusive Python 3.10) kรถnnen Sie den `Union`-Typ von `typing` verwenden und die mรถglichen Typen innerhalb der eckigen Klammern auflisten. - -In Python 3.10 gibt es zusรคtzlich eine **neue Syntax**, die es erlaubt, die mรถglichen Typen getrennt von einem vertikalen Balken (`|`) aufzulisten. +Um das zu definieren, verwenden Sie den vertikalen Balken (`|`), um beide Typen zu trennen. -//// tab | Python 3.10+ +Das wird โ€žUnionโ€œ genannt, weil die Variable etwas aus der Vereinigung dieser beiden Typmengen sein kann. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -In beiden Fรคllen bedeutet das, dass `item` ein `int` oder ein `str` sein kann. +Das bedeutet, dass `item` ein `int` oder ein `str` sein kรถnnte. #### Vielleicht `None` { #possibly-none } -Sie kรถnnen deklarieren, dass ein Wert ein `str`, aber vielleicht auch `None` sein kann. - -In Python 3.6 und darรผber (inklusive Python 3.10) kรถnnen Sie das deklarieren, indem Sie `Optional` vom `typing` Modul importieren und verwenden. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Wenn Sie `Optional[str]` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen kรถnnten, dass ein Wert immer eine String (`str`) ist, obwohl er auch `None` sein kรถnnte. - -`Optional[Something]` ist tatsรคchlich eine Abkรผrzung fรผr `Union[Something, None]`, diese beiden sind รคquivalent. - -Das bedeutet auch, dass Sie in Python 3.10 `Something | None` verwenden kรถnnen: +Sie kรถnnen deklarieren, dass ein Wert einen Typ haben kรถnnte, wie `str`, dass er aber auch `None` sein kรถnnte. //// tab | Python 3.10+ @@ -266,96 +245,7 @@ Das bedeutet auch, dass Sie in Python 3.10 `Something | None` verwenden kรถnnen: //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ Alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### `Union` oder `Optional` verwenden? { #using-union-or-optional } - -Wenn Sie eine Python-Version unterhalb 3.10 verwenden, hier ist mein sehr **subjektiver** Standpunkt dazu: - -* ๐Ÿšจ Vermeiden Sie `Optional[SomeType]` -* Stattdessen โœจ **verwenden Sie `Union[SomeType, None]`** โœจ. - -Beide sind รคquivalent und im Hintergrund dasselbe, aber ich empfehle `Union` statt `Optional`, weil das Wort โ€ž**optional**โ€œ impliziert, dass dieser Wert, zum Beispiel als Funktionsparameter, optional ist. Tatsรคchlich bedeutet es aber nur โ€žDer Wert kann `None` seinโ€œ, selbst wenn der Wert nicht optional ist und benรถtigt wird. - -Ich denke, `Union[SomeType, None]` ist expliziter bezรผglich seiner Bedeutung. - -Es geht nur um Worte und Namen. Aber diese Worte kรถnnen beeinflussen, wie Sie und Ihre Teamkollegen รผber den Code denken. - -Nehmen wir zum Beispiel diese Funktion: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -Der Parameter `name` ist definiert als `Optional[str]`, aber er ist **nicht optional**, Sie kรถnnen die Funktion nicht ohne diesen Parameter aufrufen: - -```Python -say_hi() # Oh, nein, das lรถst einen Fehler aus! ๐Ÿ˜ฑ -``` - -Der `name` Parameter wird **immer noch benรถtigt** (nicht *optional*), weil er keinen Default-Wert hat. `name` akzeptiert aber dennoch `None` als Wert: - -```Python -say_hi(name=None) # Das funktioniert, None ist gรผltig ๐ŸŽ‰ -``` - -Die gute Nachricht ist, dass Sie sich darรผber keine Sorgen mehr machen mรผssen, wenn Sie Python 3.10 verwenden, da Sie einfach `|` verwenden kรถnnen, um Vereinigungen von Typen zu definieren: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -Und dann mรผssen Sie sich nicht mehr um Namen wie `Optional` und `Union` kรผmmern. ๐Ÿ˜Ž - -#### Generische Typen { #generic-types } - -Diese Typen, die Typ-Parameter in eckigen Klammern akzeptieren, werden **generische Typen** oder **Generics** genannt. - -//// tab | Python 3.10+ - -Sie kรถnnen die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin): - -* `list` -* `tuple` -* `set` -* `dict` - -Und ebenso wie bei frรผheren Python-Versionen, aus dem `typing`-Modul: - -* `Union` -* `Optional` -* ... und andere. - -In Python 3.10 kรถnnen Sie als Alternative zu den Generics `Union` und `Optional` den vertikalen Balken (`|`) verwenden, um Vereinigungen von Typen zu deklarieren, das ist besser und einfacher. - -//// - -//// tab | Python 3.9+ - -Sie kรถnnen die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin): - -* `list` -* `tuple` -* `set` -* `dict` - -Und Generics aus dem `typing`-Modul: - -* `Union` -* `Optional` -* ... und andere. - -//// +Wenn Sie `str | None` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen kรถnnten, dass ein Wert immer ein `str` ist, obwohl er auch `None` sein kรถnnte. ### Klassen als Typen { #classes-as-types } @@ -363,11 +253,11 @@ Sie kรถnnen auch eine Klasse als Typ einer Variablen deklarieren. Nehmen wir an, Sie haben eine Klasse `Person`, mit einem Namen: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Dann kรถnnen Sie eine Variable vom Typ `Person` deklarieren: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} Und wiederum bekommen Sie die volle Editor-Unterstรผtzung: @@ -403,19 +293,13 @@ Um mehr รผber Erforderliche optionale Felder mehr erfahren. - -/// - ## Typhinweise mit Metadaten-Annotationen { #type-hints-with-metadata-annotations } -Python bietet auch die Mรถglichkeit, **zusรคtzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`. +Python bietet auch die Mรถglichkeit, **zusรคtzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`. -Seit Python 3.9 ist `Annotated` ein Teil der Standardbibliothek, Sie kรถnnen es von `typing` importieren. +Sie kรถnnen `Annotated` von `typing` importieren. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Python selbst macht nichts mit `Annotated`. Fรผr Editoren und andere Tools ist der Typ immer noch `str`. diff --git a/docs/de/docs/translation-banner.md b/docs/de/docs/translation-banner.md new file mode 100644 index 0000000000..1801a01904 --- /dev/null +++ b/docs/de/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ รœbersetzung durch KI und Menschen + +Diese รœbersetzung wurde von KI erstellt, angeleitet von Menschen. ๐Ÿค + +Sie kรถnnte Fehler enthalten, etwa Missverstรคndnisse des ursprรผnglichen Sinns oder unnatรผrliche Formulierungen, usw. ๐Ÿค– + +Sie kรถnnen diese รœbersetzung verbessern, indem Sie [uns helfen, die KI-LLM besser anzuleiten](https://fastapi.tiangolo.com/de/contributing/#translations). + +[Englische Version](ENGLISH_VERSION_URL) + +/// diff --git a/docs/de/docs/tutorial/background-tasks.md b/docs/de/docs/tutorial/background-tasks.md index 1d34430dc6..950174d9cb 100644 --- a/docs/de/docs/tutorial/background-tasks.md +++ b/docs/de/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ Hierzu zรคhlen beispielsweise: Importieren Sie zunรคchst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** erstellt fรผr Sie das Objekt vom Typ `BackgroundTasks` und รผbergibt es als diesen Parameter. @@ -31,13 +31,13 @@ In diesem Fall schreibt die Taskfunktion in eine Datei (den Versand einer E-Mail Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir die Funktion mit normalem `def`: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Den Hintergrundtask hinzufรผgen { #add-the-background-task } รœbergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` erhรคlt als Argumente: diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index d478d77c27..97fa9b81ac 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -85,7 +85,7 @@ Sie kรถnnen die *Pfadoperationen* fรผr dieses Modul mit `APIRouter` erstellen. Sie importieren ihn und erstellen eine โ€žInstanzโ€œ auf die gleiche Weise wie mit der Klasse `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren. Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} Sie kรถnnen sich `APIRouter` als eine โ€žMini-`FastAPI`โ€œ-Klasse vorstellen. @@ -117,7 +117,7 @@ Also fรผgen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`) Wir werden nun eine einfache Abhรคngigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | Tipp @@ -149,7 +149,7 @@ Wir wissen, dass alle *Pfadoperationen* in diesem Modul folgendes haben: Anstatt also alles zu jeder *Pfadoperation* hinzuzufรผgen, kรถnnen wir es dem `APIRouter` hinzufรผgen. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in: @@ -208,7 +208,7 @@ Und wir mรผssen die Abhรคngigkeitsfunktion aus dem Modul `app.dependencies` impo Daher verwenden wir einen relativen Import mit `..` fรผr die Abhรคngigkeiten: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### Wie relative Importe funktionieren { #how-relative-imports-work } @@ -279,7 +279,7 @@ Wir fรผgen weder das Prรคfix `/items` noch `tags=["items"]` zu jeder *Pfadoperat Aber wir kรถnnen immer noch _mehr_ `tags` hinzufรผgen, die auf eine bestimmte *Pfadoperation* angewendet werden, sowie einige zusรคtzliche `responses`, die speziell fรผr diese *Pfadoperation* gelten: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | Tipp @@ -305,13 +305,13 @@ Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse. Und wir kรถnnen sogar [globale Abhรคngigkeiten](dependencies/global-dependencies.md){.internal-link target=_blank} deklarieren, die mit den Abhรคngigkeiten fรผr jeden `APIRouter` kombiniert werden: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### Den `APIRouter` importieren { #import-the-apirouter } Jetzt importieren wir die anderen Submodule, die `APIRouter` haben: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, kรถnnen wir einen einzelnen Punkt `.` verwenden, um sie mit โ€žrelativen Importsโ€œ zu importieren. @@ -374,13 +374,13 @@ wรผrde der `router` von `users` den von `items` รผberschreiben und wir kรถnnten Um also beide in derselben Datei verwenden zu kรถnnen, importieren wir die Submodule direkt: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### Die `APIRouter` fรผr `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items } Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | Info @@ -420,13 +420,13 @@ Sie enthรคlt einen `APIRouter` mit einigen administrativen *Pfadoperationen*, di In diesem Beispiel wird es ganz einfach sein. Nehmen wir jedoch an, dass wir, da sie mit anderen Projekten in der Organisation geteilt wird, sie nicht รคndern und kein `prefix`, `dependencies`, `tags`, usw. direkt zum `APIRouter` hinzufรผgen kรถnnen: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Aber wir mรถchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir mรถchten es mit den `dependencies` sichern, die wir bereits fรผr dieses Projekt haben, und wir mรถchten `tags` und `responses` hinzufรผgen. Wir kรถnnen das alles deklarieren, ohne den ursprรผnglichen `APIRouter` รคndern zu mรผssen, indem wir diese Parameter an `app.include_router()` รผbergeben: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} Auf diese Weise bleibt der ursprรผngliche `APIRouter` unverรคndert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen kรถnnen. @@ -447,7 +447,7 @@ Wir kรถnnen *Pfadoperationen* auch direkt zur `FastAPI`-App hinzufรผgen. Hier machen wir es ... nur um zu zeigen, dass wir es kรถnnen ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefรผgt wurden. diff --git a/docs/de/docs/tutorial/body-fields.md b/docs/de/docs/tutorial/body-fields.md index b73d57d2d8..4edb22478b 100644 --- a/docs/de/docs/tutorial/body-fields.md +++ b/docs/de/docs/tutorial/body-fields.md @@ -44,7 +44,7 @@ Beachten Sie, wie jedes Attribut eines Modells mit einem Typ, Defaultwert und `F Sie kรถnnen zusรคtzliche Information in `Field`, `Query`, `Body`, usw. deklarieren. Und es wird im generierten JSON-Schema untergebracht. -Sie werden spรคter mehr darรผber lernen, wie man zusรคtzliche Information unterbringt, wenn Sie lernen, Beispiele zu deklarieren. +Sie werden spรคter in der Dokumentation mehr darรผber lernen, wie man zusรคtzliche Information unterbringt, wenn Sie lernen, Beispiele zu deklarieren. /// warning | Achtung diff --git a/docs/de/docs/tutorial/body-multiple-params.md b/docs/de/docs/tutorial/body-multiple-params.md index daa48f23d1..60a0ceefe0 100644 --- a/docs/de/docs/tutorial/body-multiple-params.md +++ b/docs/de/docs/tutorial/body-multiple-params.md @@ -104,12 +104,6 @@ Da einfache Werte standardmรครŸig als Query-Parameter interpretiert werden, mรผs q: str | None = None ``` -Oder in Python 3.9: - -```Python -q: Union[str, None] = None -``` - Zum Beispiel: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/de/docs/tutorial/body-nested-models.md b/docs/de/docs/tutorial/body-nested-models.md index 65a5d7c1de..52b00e0369 100644 --- a/docs/de/docs/tutorial/body-nested-models.md +++ b/docs/de/docs/tutorial/body-nested-models.md @@ -163,7 +163,7 @@ images: list[Image] so wie in: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Editor-Unterstรผtzung รผberall { #editor-support-everywhere } @@ -193,7 +193,7 @@ Das schauen wir uns mal an. Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlรผssel und `float`-Werte hat: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Tipp diff --git a/docs/de/docs/tutorial/body.md b/docs/de/docs/tutorial/body.md index cdf3122f2f..e1214bc538 100644 --- a/docs/de/docs/tutorial/body.md +++ b/docs/de/docs/tutorial/body.md @@ -154,7 +154,7 @@ Die Funktionsparameter werden wie folgt erkannt: FastAPI weiรŸ, dass der Wert von `q` nicht erforderlich ist, aufgrund des definierten Defaultwertes `= None`. -Das `str | None` (Python 3.10+) oder `Union` in `Union[str, None]` (Python 3.9+) wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiรŸ, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat. +Das `str | None` wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiรŸ, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat. Das Hinzufรผgen der Typannotationen ermรถglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstรผtzung zu bieten und Fehler zu erkennen. diff --git a/docs/de/docs/tutorial/cookie-param-models.md b/docs/de/docs/tutorial/cookie-param-models.md index 25718bd33a..81f7abb7de 100644 --- a/docs/de/docs/tutorial/cookie-param-models.md +++ b/docs/de/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ Aber selbst wenn Sie die **Daten ausfรผllen** und auf โ€žAusfรผhrenโ€œ klicken, In einigen speziellen Anwendungsfรคllen (wahrscheinlich nicht sehr hรคufig) mรถchten Sie mรถglicherweise die Cookies, die Sie empfangen mรถchten, **einschrรคnken**. -Ihre API hat jetzt die Macht, ihre eigene Cookie-Einwilligung zu kontrollieren. ๐Ÿคช๐Ÿช +Ihre API hat jetzt die Macht, ihre eigene Cookie-Einwilligung zu kontrollieren. ๐Ÿคช๐Ÿช Sie kรถnnen die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`): @@ -54,9 +54,9 @@ Sie kรถnnen die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu Wenn ein Client versucht, einige **zusรคtzliche Cookies** zu senden, erhรคlt er eine **Error-Response**. -Arme Cookie-Banner, wie sie sich mรผhen, Ihre Einwilligung zu erhalten, dass die API sie ablehnen darf. ๐Ÿช +Arme Cookie-Banner, wie sie sich mรผhen, Ihre Einwilligung zu erhalten, dass die API sie ablehnen darf. ๐Ÿช -Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem Wert von `good-list-please` zu senden, erhรคlt der Client eine **Error-Response**, die ihm mitteilt, dass das `santa_tracker` Cookie nicht erlaubt ist: +Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem Wert von `good-list-please` zu senden, erhรคlt der Client eine **Error-Response**, die ihm mitteilt, dass das `santa_tracker` Cookie nicht erlaubt ist: ```json { @@ -73,4 +73,4 @@ Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem We ## Zusammenfassung { #summary } -Sie kรถnnen **Pydantic-Modelle** verwenden, um **Cookies** in **FastAPI** zu deklarieren. ๐Ÿ˜Ž +Sie kรถnnen **Pydantic-Modelle** verwenden, um **Cookies** in **FastAPI** zu deklarieren. ๐Ÿ˜Ž diff --git a/docs/de/docs/tutorial/cors.md b/docs/de/docs/tutorial/cors.md index 81f0f36051..4e714f215e 100644 --- a/docs/de/docs/tutorial/cors.md +++ b/docs/de/docs/tutorial/cors.md @@ -46,7 +46,7 @@ Sie kรถnnen auch angeben, ob Ihr Backend erlaubt: * Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`. * Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmรครŸig restriktiv, daher mรผssen Sie bestimmte Origins, Methoden oder Header ausdrรผcklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dรผrfen. diff --git a/docs/de/docs/tutorial/debugging.md b/docs/de/docs/tutorial/debugging.md index 0d12877c10..cabaf5a3a4 100644 --- a/docs/de/docs/tutorial/debugging.md +++ b/docs/de/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Sie kรถnnen den Debugger in Ihrem Editor verbinden, zum Beispiel mit Visual Stud Importieren und fรผhren Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### รœber `__name__ == "__main__"` { #about-name-main } diff --git a/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md index 7df0842eb1..4fd8d092fc 100644 --- a/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ Jetzt kรถnnen Sie Ihre Abhรคngigkeit mithilfe dieser Klasse deklarieren. Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp @@ -137,7 +137,7 @@ Aus diesem extrahiert FastAPI die deklarierten Parameter, und dieses ist es, was In diesem Fall hat das erste `CommonQueryParams` in: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp @@ -163,7 +163,7 @@ commons: CommonQueryParams ... Sie kรถnnten tatsรคchlich einfach schreiben: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp @@ -197,7 +197,7 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiรŸ, was al Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp @@ -225,7 +225,7 @@ In diesem speziellen Fall kรถnnen Sie Folgendes tun: Anstatt zu schreiben: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ... schreiben Sie: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp diff --git a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 59c9fcf48e..f63273f160 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -6,15 +6,15 @@ Oder die Abhรคngigkeit gibt keinen Wert zurรผck. Aber Sie mรผssen sie trotzdem ausfรผhren/auflรถsen. -In diesen Fรคllen kรถnnen Sie, anstatt einen Parameter der *Pfadoperation-Funktion* mit `Depends` zu deklarieren, eine `list`e von `dependencies` zum *Pfadoperation-Dekorator* hinzufรผgen. +In diesen Fรคllen kรถnnen Sie, anstatt einen Parameter der *Pfadoperation-Funktion* mit `Depends` zu deklarieren, eine `list` von `dependencies` zum *Pfadoperation-Dekorator* hinzufรผgen. ## `dependencies` zum *Pfadoperation-Dekorator* hinzufรผgen { #add-dependencies-to-the-path-operation-decorator } Der *Pfadoperation-Dekorator* erhรคlt ein optionales Argument `dependencies`. -Es sollte eine `list`e von `Depends()` sein: +Es sollte eine `list` von `Depends()` sein: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} Diese Abhรคngigkeiten werden auf die gleiche Weise wie normale Abhรคngigkeiten ausgefรผhrt/aufgelรถst. Aber ihr Wert (falls sie einen zurรผckgeben) wird nicht an Ihre *Pfadoperation-Funktion* รผbergeben. @@ -44,13 +44,13 @@ Sie kรถnnen dieselben Abhรคngigkeits-*Funktionen* verwenden, die Sie normalerwei Sie kรถnnen Anforderungen fรผr einen Request (wie Header) oder andere Unterabhรคngigkeiten deklarieren: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### Exceptions auslรถsen { #raise-exceptions } Die Abhรคngigkeiten kรถnnen Exceptions `raise`n, genau wie normale Abhรคngigkeiten: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### Rรผckgabewerte { #return-values } @@ -58,7 +58,7 @@ Und sie kรถnnen Werte zurรผckgeben oder nicht, die Werte werden nicht verwendet. Sie kรถnnen also eine normale Abhรคngigkeit (die einen Wert zurรผckgibt), die Sie bereits an anderer Stelle verwenden, wiederverwenden, und auch wenn der Wert nicht verwendet wird, wird die Abhรคngigkeit ausgefรผhrt: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} ## Abhรคngigkeiten fรผr eine Gruppe von *Pfadoperationen* { #dependencies-for-a-group-of-path-operations } diff --git a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md index 0083e7e7ea..c5f2acbae5 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Abhรคngigkeiten mit `yield` { #dependencies-with-yield } -FastAPI unterstรผtzt Abhรคngigkeiten, die nach Abschluss einige zusรคtzliche Schritte ausfรผhren. +FastAPI unterstรผtzt Abhรคngigkeiten, die einige zusรคtzliche Schritte nach Abschluss ausfรผhren. Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusรคtzlichen Schritte / den zusรคtzlichen Code danach. @@ -29,15 +29,15 @@ Sie kรถnnten damit beispielsweise eine Datenbanksession erstellen und diese nach Nur der Code vor und einschlieรŸlich der `yield`-Anweisung wird ausgefรผhrt, bevor eine Response erzeugt wird: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhรคngigkeiten eingefรผgt wird: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} Der auf die `yield`-Anweisung folgende Code wird nach der Response ausgefรผhrt: -{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | Tipp @@ -57,7 +57,7 @@ Sie kรถnnen also mit `except SomeException` diese bestimmte Exception innerhalb Auf die gleiche Weise kรถnnen Sie `finally` verwenden, um sicherzustellen, dass die Exit-Schritte ausgefรผhrt werden, unabhรคngig davon, ob eine Exception geworfen wurde oder nicht. -{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *} +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## Unterabhรคngigkeiten mit `yield` { #sub-dependencies-with-yield } @@ -67,7 +67,7 @@ Sie kรถnnen Unterabhรคngigkeiten und โ€žBรคumeโ€œ von Unterabhรคngigkeiten belie Beispielsweise kann `dependency_c` von `dependency_b` und `dependency_b` von `dependency_a` abhรคngen: -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} Und alle kรถnnen `yield` verwenden. @@ -75,7 +75,7 @@ In diesem Fall benรถtigt `dependency_c` zum Ausfรผhren seines Exit-Codes, dass d Und wiederum benรถtigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` genannt) fรผr seinen Exit-Code. -{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} Auf die gleiche Weise kรถnnten Sie einige Abhรคngigkeiten mit `yield` und einige andere Abhรคngigkeiten mit `return` haben, und alle kรถnnen beliebig voneinander abhรคngen. @@ -109,7 +109,7 @@ Aber es ist fรผr Sie da, wenn Sie es brauchen. ๐Ÿค“ /// -{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} Wenn Sie Exceptions abfangen und darauf basierend eine benutzerdefinierte Response erstellen mรถchten, erstellen Sie einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. @@ -117,7 +117,7 @@ Wenn Sie Exceptions abfangen und darauf basierend eine benutzerdefinierte Respon Wenn Sie eine Exception mit `except` in einer Abhรคngigkeit mit `yield` abfangen und sie nicht erneut auslรถsen (oder eine neue Exception auslรถsen), kann FastAPI nicht feststellen, dass es eine Exception gab, genau so wie es bei normalem Python der Fall wรคre: -{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} In diesem Fall sieht der Client eine *HTTP 500 Internal Server Error*-Response, wie es sein sollte, da wir keine `HTTPException` oder ร„hnliches auslรถsen, aber der Server hat **keine Logs** oder einen anderen Hinweis darauf, was der Fehler war. ๐Ÿ˜ฑ @@ -127,7 +127,7 @@ Wenn Sie eine Exception in einer Abhรคngigkeit mit `yield` abfangen, sollten Sie Sie kรถnnen dieselbe Exception mit `raise` erneut auslรถsen: -{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Jetzt erhรคlt der Client dieselbe *HTTP 500 Internal Server Error*-Response, aber der Server enthรคlt unseren benutzerdefinierten `InternalError` in den Logs. ๐Ÿ˜Ž @@ -190,7 +190,7 @@ Normalerweise wird der Exit-Code von Abhรคngigkeiten mit `yield` ausgefรผhrt **n Wenn Sie aber wissen, dass Sie die Abhรคngigkeit nach der Rรผckkehr aus der *Pfadoperation-Funktion* nicht mehr benรถtigen, kรถnnen Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhรคngigkeit nach der Rรผckkehr aus der *Pfadoperation-Funktion* schlieรŸen soll, jedoch **bevor** die **Response gesendet wird**. -{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` erhรคlt einen `scope`-Parameter, der sein kann: @@ -268,7 +268,7 @@ In Python kรถnnen Sie Kontextmanager erstellen, indem Sie Dependency Injection** System. +**FastAPI** hat ein sehr mรคchtiges, aber intuitives **Abhรคngigkeitsinjektion** System. Es ist so konzipiert, sehr einfach zu verwenden zu sein und es jedem Entwickler sehr leicht zu machen, andere Komponenten mit **FastAPI** zu integrieren. diff --git a/docs/de/docs/tutorial/dependencies/sub-dependencies.md b/docs/de/docs/tutorial/dependencies/sub-dependencies.md index d72f820dca..b01cc80a76 100644 --- a/docs/de/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/de/docs/tutorial/dependencies/sub-dependencies.md @@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query Wenn eine Ihrer Abhรคngigkeiten mehrmals fรผr dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhรคngigkeiten eine gemeinsame Unterabhรคngigkeit haben, wird **FastAPI** diese Unterabhรคngigkeit nur einmal pro Request aufrufen. -Und es speichert den zurรผckgegebenen Wert in einem โ€žCacheโ€œ und รผbergibt diesen gecachten Wert an alle โ€žDependantenโ€œ, die ihn in diesem spezifischen Request benรถtigen, anstatt die Abhรคngigkeit mehrmals fรผr denselben Request aufzurufen. +Und es speichert den zurรผckgegebenen Wert in einem โ€žCacheโ€œ und รผbergibt diesen gecachten Wert an alle โ€žDependantenโ€œ, die ihn in diesem spezifischen Request benรถtigen, anstatt die Abhรคngigkeit mehrmals fรผr denselben Request aufzurufen. In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhรคngigkeit bei jedem Schritt (mรถglicherweise mehrmals) in demselben Request aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, kรถnnen Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python hl_lines="1" async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): @@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca //// -//// tab | Python 3.9+ nicht annotiert +//// tab | Python 3.10+ nicht annotiert /// tip | Tipp diff --git a/docs/de/docs/tutorial/extra-models.md b/docs/de/docs/tutorial/extra-models.md index 889fdb9a3b..4f55f2428c 100644 --- a/docs/de/docs/tutorial/extra-models.md +++ b/docs/de/docs/tutorial/extra-models.md @@ -190,9 +190,9 @@ Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, Auf die gleiche Weise kรถnnen Sie Responses von Listen von Objekten deklarieren. -Dafรผr verwenden Sie Pythons Standard-`typing.List` (oder nur `list` in Python 3.9 und hรถher): +Dafรผr verwenden Sie Pythons Standard-`list`: -{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} ## Response mit beliebigem `dict` { #response-with-arbitrary-dict } @@ -200,9 +200,9 @@ Sie kรถnnen auch eine Response deklarieren, die ein beliebiges `dict` zurรผckgib Dies ist nรผtzlich, wenn Sie die gรผltigen Feld-/Attributnamen nicht im Voraus kennen (die fรผr ein Pydantic-Modell benรถtigt werden wรผrden). -In diesem Fall kรถnnen Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und hรถher): +In diesem Fall kรถnnen Sie `dict` verwenden: -{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} ## Zusammenfassung { #recap } diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md index 9505a0bdb7..f02fb3d433 100644 --- a/docs/de/docs/tutorial/first-steps.md +++ b/docs/de/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ Die einfachste FastAPI-Datei kรถnnte wie folgt aussehen: -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Kopieren Sie das in eine Datei `main.py`. @@ -183,7 +183,7 @@ Das war's! Jetzt kรถnnen Sie Ihre App unter dieser URL aufrufen. โœจ ### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` ist eine Python-Klasse, die die gesamte Funktionalitรคt fรผr Ihre API bereitstellt. @@ -197,7 +197,7 @@ Sie kรถnnen alle Requests zustรคndig ist, die an: * den Pfad `/` -* unter der Verwendung der get-Operation gehen +* unter der Verwendung der get-Operation gehen /// info | `@decorator` Info @@ -320,7 +320,7 @@ Das ist unsere โ€ž**Pfadoperation-Funktion**โ€œ: * **Operation**: ist `get`. * **Funktion**: ist die Funktion direkt unter dem โ€žDekoratorโ€œ (unter `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Dies ist eine Python-Funktion. @@ -332,7 +332,7 @@ In diesem Fall handelt es sich um eine `async`-Funktion. Sie kรถnnten sie auch als normale Funktion anstelle von `async def` definieren: -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note | Hinweis @@ -342,7 +342,7 @@ Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *โ€žIn Eile?โ€œ*](../as ### Schritt 5: den Inhalt zurรผckgeben { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Sie kรถnnen ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurรผckgeben. diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md index d890b44629..0cb0de2ca4 100644 --- a/docs/de/docs/tutorial/handling-errors.md +++ b/docs/de/docs/tutorial/handling-errors.md @@ -25,7 +25,7 @@ Um HTTP-Exceptionhandler mit den gleichen Exception-Werkzeugen von Starlette hinzufรผgen. +Sie kรถnnen benutzerdefinierte Exceptionhandler mit den gleichen Exception-Werkzeugen von Starlette hinzufรผgen. Angenommen, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n kรถnnten. @@ -89,7 +89,7 @@ Und Sie mรถchten diese Exception global mit FastAPI handhaben. Sie kรถnnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufรผgen: -{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *} +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n. @@ -127,7 +127,7 @@ Um diesen zu รผberschreiben, importieren Sie den `RequestValidationError` und ve Der Exceptionhandler erhรคlt einen `Request` und die Exception. -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmรครŸigen JSON-Fehlers mit: @@ -159,7 +159,7 @@ Auf die gleiche Weise kรถnnen Sie den `HTTPException`-Handler รผberschreiben. Zum Beispiel kรถnnten Sie eine Klartext-Response statt JSON fรผr diese Fehler zurรผckgeben wollen: -{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *} +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} /// note | Technische Details @@ -183,7 +183,7 @@ Der `RequestValidationError` enthรคlt den empfangenen `body` mit den ungรผltigen Sie kรถnnten diesen wรคhrend der Entwicklung Ihrer Anwendung verwenden, um den Body zu loggen und zu debuggen, ihn an den Benutzer zurรผckzugeben usw. -{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *} +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} Versuchen Sie nun, einen ungรผltigen Artikel zu senden: @@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException Wenn Sie die Exception zusammen mit den gleichen Default-Exceptionhandlern von **FastAPI** verwenden mรถchten, kรถnnen Sie die Default-Exceptionhandler aus `fastapi.exception_handlers` importieren und wiederverwenden: -{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *} +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie kรถnnen die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden. diff --git a/docs/de/docs/tutorial/metadata.md b/docs/de/docs/tutorial/metadata.md index ee88a21d63..f5999a667f 100644 --- a/docs/de/docs/tutorial/metadata.md +++ b/docs/de/docs/tutorial/metadata.md @@ -18,7 +18,7 @@ Sie kรถnnen die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und Sie kรถnnen diese wie folgt setzen: -{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *} +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} /// tip | Tipp @@ -36,7 +36,7 @@ Seit OpenAPI 3.1.0 und FastAPI 0.99.0 kรถnnen Sie die `license_info` auch mit ei Zum Beispiel: -{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *} +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} ## Metadaten fรผr Tags { #metadata-for-tags } @@ -58,7 +58,7 @@ Versuchen wir es mit einem Beispiel mit Tags fรผr `users` und `items`. Erstellen Sie Metadaten fรผr Ihre Tags und รผbergeben Sie diese an den Parameter `openapi_tags`: -{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden kรถnnen. Zum Beispiel wird โ€žloginโ€œ in Fettschrift (**login**) und โ€žfancyโ€œ in Kursivschrift (_fancy_) angezeigt. @@ -72,7 +72,7 @@ Sie mรผssen nicht fรผr alle von Ihnen verwendeten Tags Metadaten hinzufรผgen. Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen: -{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *} +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} /// info | Info @@ -100,7 +100,7 @@ Sie kรถnnen das aber mit dem Parameter `openapi_url` konfigurieren. Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestellt wird: -{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} Wenn Sie das OpenAPI-Schema vollstรคndig deaktivieren mรถchten, kรถnnen Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflรคchen deaktiviert werden, die es verwenden. @@ -117,4 +117,4 @@ Sie kรถnnen die beiden enthaltenen Dokumentationsbenutzeroberflรคchen konfigurie Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren: -{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *} +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/de/docs/tutorial/middleware.md b/docs/de/docs/tutorial/middleware.md index 540a18c4d0..116f87d23c 100644 --- a/docs/de/docs/tutorial/middleware.md +++ b/docs/de/docs/tutorial/middleware.md @@ -31,7 +31,7 @@ Die Middleware-Funktion erhรคlt: * Dann gibt es die von der entsprechenden *Pfadoperation* generierte `response` zurรผck. * Sie kรถnnen die `response` dann weiter modifizieren, bevor Sie sie zurรผckgeben. -{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} /// tip | Tipp @@ -57,7 +57,7 @@ Und auch nachdem die `response` generiert wurde, bevor sie zurรผckgegeben wird. Sie kรถnnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hinzufรผgen, der die Zeit in Sekunden enthรคlt, die benรถtigt wurde, um den Request zu verarbeiten und eine Response zu generieren: -{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *} +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} /// tip | Tipp diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md index a06c85e570..48d6d66035 100644 --- a/docs/de/docs/tutorial/path-operation-configuration.md +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern. **FastAPI** unterstรผtzt das auf die gleiche Weise wie einfache Strings: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## Zusammenfassung und Beschreibung { #summary-and-description } @@ -56,7 +56,7 @@ Sie kรถnnen eine `summary` und eine Docstring der Funktion deklarieren, und **FastAPI** wird sie daraus auslesen. +Da Beschreibungen oft mehrere Zeilen lang sind, kรถnnen Sie die Beschreibung der *Pfadoperation* im Docstring der Funktion deklarieren, und **FastAPI** wird sie daraus auslesen. Sie kรถnnen Markdown im Docstring schreiben, es wird korrekt interpretiert und angezeigt (unter Berรผcksichtigung der Einrรผckung des Docstring). @@ -90,9 +90,9 @@ Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine fรผr โ€žErfolg ## Eine *Pfadoperation* deprecaten { #deprecate-a-path-operation } -Wenn Sie eine *Pfadoperation* als deprecatet kennzeichnen mรถchten, ohne sie zu entfernen, fรผgen Sie den Parameter `deprecated` hinzu: +Wenn Sie eine *Pfadoperation* als deprecatet kennzeichnen mรถchten, ohne sie zu entfernen, fรผgen Sie den Parameter `deprecated` hinzu: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden: diff --git a/docs/de/docs/tutorial/path-params-numeric-validations.md b/docs/de/docs/tutorial/path-params-numeric-validations.md index 8b52e8b42f..5147a7fbc7 100644 --- a/docs/de/docs/tutorial/path-params-numeric-validations.md +++ b/docs/de/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Fรผr **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Na Sie kรถnnen Ihre Funktion also so deklarieren: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte fรผr `Query()` oder `Path()` verwenden. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Die Parameter sortieren, wie Sie mรถchten: Tricks { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ Wenn Sie: Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlรผsselwortargumente (Schlรผssel-Wert-Paare) verwendet werden sollen, auch bekannt als kwargs. Selbst wenn diese keinen Defaultwert haben. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Besser mit `Annotated` { #better-with-annotated } Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, da Sie keine Funktionsparameter-Defaultwerte verwenden, dieses Problem nicht haben werden und wahrscheinlich nicht `*` verwenden mรผssen. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Validierung von Zahlen: GrรถรŸer oder gleich { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Mit `Query` und `Path` (und anderen, die Sie spรคter sehen werden) kรถnnen Sie Z Hier, mit `ge=1`, muss `item_id` eine ganze Zahl sein, die โ€ž`g`reater than or `e`qual toโ€œ (grรถรŸer oder gleich) `1` ist. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Validierung von Zahlen: GrรถรŸer und kleiner oder gleich { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ Das Gleiche gilt fรผr: * `gt`: `g`reater `t`han (grรถรŸer als) * `le`: `l`ess than or `e`qual (kleiner oder gleich) -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Validierung von Zahlen: Floats, grรถรŸer und kleiner { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Also wรคre `0.5` ein gรผltiger Wert. Aber `0.0` oder `0` nicht. Und das Gleiche gilt fรผr lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Zusammenfassung { #recap } diff --git a/docs/de/docs/tutorial/path-params.md b/docs/de/docs/tutorial/path-params.md index 1de4973155..41f6aea55f 100644 --- a/docs/de/docs/tutorial/path-params.md +++ b/docs/de/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Sie kรถnnen Pfad-โ€žParameterโ€œ oder -โ€žVariablenโ€œ mit der gleichen Syntax deklarieren, welche in Python-Formatstrings verwendet wird: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` รผbergeben. @@ -16,7 +16,7 @@ Wenn Sie dieses Beispiel ausfรผhren und auf Konversion { #data-conversion } +## Daten-Konversion { #data-conversion } Wenn Sie dieses Beispiel ausfรผhren und Ihren Browser unter http://127.0.0.1:8000/items/3 รถffnen, sehen Sie als Response: @@ -38,7 +38,7 @@ Wenn Sie dieses Beispiel ausfรผhren und Ihren Browser unter Request automatisch โ€žparsenโ€œ. +Sprich, mit dieser Typdeklaration wird **FastAPI** den โ€žparsenโ€œ. /// @@ -118,13 +118,13 @@ Und Sie haben auch einen Pfad `/users/{user_id}`, um Daten รผber einen spezifisc Weil *Pfadoperationen* in ihrer Reihenfolge ausgewertet werden, mรผssen Sie sicherstellen, dass der Pfad `/users/me` vor `/users/{user_id}` deklariert wurde: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} Ansonsten wรผrde der Pfad fรผr `/users/{user_id}` auch `/users/me` auswerten, und annehmen, dass ein Parameter `user_id` mit dem Wert `"me"` รผbergeben wurde. Sie kรถnnen eine Pfadoperation auch nicht erneut definieren: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst รผbereinstimmt. @@ -140,12 +140,11 @@ Indem Sie von `str` erben, weiรŸ die API-Dokumentation, dass die Werte vom Typ ` Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} - +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | Tipp -Falls Sie sich fragen, was โ€žAlexNetโ€œ, โ€žResNetโ€œ und โ€žLeNetโ€œ ist, das sind Namen von Modellen fรผr maschinelles Lernen. +Falls Sie sich fragen, was โ€žAlexNetโ€œ, โ€žResNetโ€œ und โ€žLeNetโ€œ ist, das sind Namen von Modellen fรผr maschinelles Lernen. /// @@ -153,7 +152,7 @@ Falls Sie sich fragen, was โ€žAlexNetโ€œ, โ€žResNetโ€œ und โ€žLeNetโ€œ ist, das Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`): -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### Die API-Dokumentation testen { #check-the-docs } @@ -169,13 +168,13 @@ Der *Pfad-Parameter* wird ein *parsen" +* Daten โ€žparsenโ€œ * Datenvalidierung * API-Annotationen und automatische Dokumentation diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md index 8977dbcd50..865d10d13c 100644 --- a/docs/de/docs/tutorial/query-params-str-validations.md +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -39,7 +39,7 @@ Stellen Sie sicher, dass Sie [die FastAPI-Version aktualisieren](../deployment/v /// -## Verwenden von `Annotated` im Typ fรผr den `q`-Parameter { #use-annotated-in-the-type-for-the-q-parameter } +## `Annotated` im Typ fรผr den `q`-Parameter verwenden { #use-annotated-in-the-type-for-the-q-parameter } Erinnern Sie sich, dass ich Ihnen zuvor in [Python-Typen-Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} gesagt habe, dass `Annotated` verwendet werden kann, um Metadaten zu Ihren Parametern hinzuzufรผgen? @@ -47,40 +47,16 @@ Jetzt ist es soweit, dies mit FastAPI zu verwenden. ๐Ÿš€ Wir hatten diese Typannotation: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - Was wir tun werden, ist, dies mit `Annotated` zu wrappen, sodass es zu: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Beide dieser Versionen bedeuten dasselbe: `q` ist ein Parameter, der ein `str` oder `None` sein kann, und standardmรครŸig ist er `None`. Jetzt springen wir zu den spannenden Dingen. ๐ŸŽ‰ @@ -109,7 +85,7 @@ FastAPI wird nun: ## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value } -Frรผhere Versionen von FastAPI (vor 0.95.0) erforderten, dass Sie `Query` als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von `Annotated` zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklรคren. +Frรผhere Versionen von FastAPI (vor 0.95.0) erforderten, dass Sie `Query` als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von `Annotated` zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklรคren. /// tip | Tipp @@ -191,7 +167,7 @@ Sie kรถnnen auch einen `min_length`-Parameter hinzufรผgen: ## Regulรคre Ausdrรผcke hinzufรผgen { #add-regular-expressions } -Sie kรถnnen einen regulรคren Ausdruck `pattern` definieren, mit dem der Parameter รผbereinstimmen muss: +Sie kรถnnen einen regulรคren Ausdruck `pattern` definieren, mit dem der Parameter รผbereinstimmen muss: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +187,7 @@ Natรผrlich kรถnnen Sie Defaultwerte verwenden, die nicht `None` sind. Nehmen wir an, Sie mรถchten, dass der `q` Query-Parameter eine `min_length` von `3` hat und einen Defaultwert von `"fixedquery"`: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Hinweis @@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Wenn Sie einen Wert als erforderlich deklarieren mรผssen, wรคhrend Sie `Query` verwenden, deklarieren Sie einfach keinen Defaultwert: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Erforderlich, kann `None` sein { #required-can-be-none } @@ -292,7 +268,7 @@ Die interaktive API-Dokumentation wird entsprechend aktualisiert, um mehrere Wer Sie kรถnnen auch eine Default-`list` von Werten definieren, wenn keine bereitgestellt werden: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Wenn Sie zu: @@ -315,7 +291,7 @@ gehen, wird der Default fรผr `q` sein: `["foo", "bar"]`, und Ihre Response wird Sie kรถnnen auch `list` direkt verwenden, anstelle von `list[str]`: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Hinweis @@ -371,7 +347,7 @@ Dann kรถnnen Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um de Nehmen wir an, Ihnen gefรคllt dieser Parameter nicht mehr. -Sie mรผssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie mรถchten, dass die Dokumentation ihn klar als deprecatet anzeigt. +Sie mรผssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie mรถchten, dass die Dokumentation ihn klar als deprecatet anzeigt. Dann รผbergeben Sie den Parameter `deprecated=True` an `Query`: @@ -393,7 +369,7 @@ Es kann Fรคlle geben, in denen Sie eine **benutzerdefinierte Validierung** durch In diesen Fรคllen kรถnnen Sie eine **benutzerdefinierte Validierungsfunktion** verwenden, die nach der normalen Validierung angewendet wird (z. B. nach der Validierung, dass der Wert ein `str` ist). -Sie kรถnnen dies mit Pydantic's `AfterValidator` innerhalb von `Annotated` erreichen. +Sie kรถnnen dies mit Pydantics `AfterValidator` innerhalb von `Annotated` erreichen. /// tip | Tipp @@ -401,7 +377,7 @@ Pydantic unterstรผtzt auch ISBN-Buchnummer oder mit `imdb-` fรผr eine IMDB-Film-URL-ID beginnt: +Zum Beispiel รผberprรผft dieser benutzerdefinierte Validator, ob die Artikel-ID mit `isbn-` fรผr eine ISBN-Buchnummer oder mit `imdb-` fรผr eine IMDB-Film-URL-ID beginnt: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,7 +411,7 @@ Haben Sie bemerkt? Eine Zeichenkette mit `value.startswith()` kann ein Tuple รผb #### Ein zufรคlliges Item { #a-random-item } -Mit `data.items()` erhalten wir ein iterierbares Objekt mit Tupeln, die Schlรผssel und Wert fรผr jedes Dictionary-Element enthalten. +Mit `data.items()` erhalten wir ein iterierbares Objekt mit Tupeln, die Schlรผssel und Wert fรผr jedes Dictionary-Element enthalten. Wir konvertieren dieses iterierbare Objekt mit `list(data.items())` in eine richtige `list`. diff --git a/docs/de/docs/tutorial/query-params.md b/docs/de/docs/tutorial/query-params.md index 05ed3bc830..5a2a2a012e 100644 --- a/docs/de/docs/tutorial/query-params.md +++ b/docs/de/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Wenn Sie in Ihrer Funktion andere Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als โ€žQueryโ€œ-Parameter interpretiert. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} Die Query ist die Menge von Schlรผssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind. @@ -24,7 +24,7 @@ Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), w Die gleichen Prozesse, die fรผr Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet: * Editor Unterstรผtzung (natรผrlich) -* Daten-โ€žParsenโ€œ +* Daten-โ€žParsenโ€œ * Datenvalidierung * Automatische Dokumentation @@ -127,7 +127,7 @@ Wenn Sie keinen spezifischen Wert haben wollen, sondern der Parameter einfach op Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie einfach keinen Defaultwert: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Hier ist `needy` ein erforderlicher Query-Parameter vom Typ `str`. diff --git a/docs/de/docs/tutorial/request-files.md b/docs/de/docs/tutorial/request-files.md index 0aee898b9c..5b5f72d6db 100644 --- a/docs/de/docs/tutorial/request-files.md +++ b/docs/de/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ Das liegt daran, dass hochgeladene Dateien als โ€žFormulardatenโ€œ gesendet werd Importieren Sie `File` und `UploadFile` von `fastapi`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## `File`-Parameter definieren { #define-file-parameters } Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen wรผrden: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | Info @@ -54,7 +54,7 @@ Aber es gibt viele Fรคlle, in denen Sie davon profitieren, `UploadFile` zu verwe Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} `UploadFile` zu verwenden, hat mehrere Vorzรผge gegenรผber `bytes`: @@ -143,7 +143,7 @@ Sie kรถnnen eine Datei optional machen, indem Sie Standard-Typannotationen verwe Sie kรถnnen auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusรคtzliche Metadaten zu setzen: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## Mehrere Datei-Uploads { #multiple-file-uploads } @@ -153,7 +153,7 @@ Diese werden demselben Formularfeld zugeordnet, welches mit den Formulardaten ge Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} Sie erhalten, wie deklariert, eine `list` von `bytes` oder `UploadFile`s. @@ -169,7 +169,7 @@ Sie kรถnnen auch `from starlette.responses import HTMLResponse` verwenden. Und so wie zuvor kรถnnen Sie `File()` verwenden, um zusรคtzliche Parameter zu setzen, sogar fรผr `UploadFile`: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## Zusammenfassung { #recap } diff --git a/docs/de/docs/tutorial/request-form-models.md b/docs/de/docs/tutorial/request-form-models.md index fbc6c094c7..262a14d6db 100644 --- a/docs/de/docs/tutorial/request-form-models.md +++ b/docs/de/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ Dies wird seit FastAPI Version `0.113.0` unterstรผtzt. ๐Ÿค“ Sie mรผssen nur ein **Pydantic-Modell** mit den Feldern deklarieren, die Sie als **Formularfelder** erhalten mรถchten, und dann den Parameter als `Form` deklarieren: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI** wird die Daten fรผr **jedes Feld** aus den **Formulardaten** im Request **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell รผbergeben. @@ -48,7 +48,7 @@ Dies wird seit FastAPI Version `0.114.0` unterstรผtzt. ๐Ÿค“ Sie kรถnnen die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} Wenn ein Client versucht, einige zusรคtzliche Daten zu senden, erhรคlt er eine **Error-Response**. diff --git a/docs/de/docs/tutorial/request-forms-and-files.md b/docs/de/docs/tutorial/request-forms-and-files.md index cda38bcc2f..f779ff509f 100644 --- a/docs/de/docs/tutorial/request-forms-and-files.md +++ b/docs/de/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## `File` und `Form` importieren { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## `File` und `Form`-Parameter definieren { #define-file-and-form-parameters } Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` oder `Query` machen wรผrden: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} Die Datei- und Formularfelder werden als Formulardaten hochgeladen, und Sie erhalten diese Dateien und Formularfelder. diff --git a/docs/de/docs/tutorial/request-forms.md b/docs/de/docs/tutorial/request-forms.md index 5c2ace67b2..4a36dba725 100644 --- a/docs/de/docs/tutorial/request-forms.md +++ b/docs/de/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart Importieren Sie `Form` von `fastapi`: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## `Form`-Parameter definieren { #define-form-parameters } Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen wรผrden: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} Zum Beispiel stellt eine der Mรถglichkeiten, die OAuth2-Spezifikation zu verwenden (genannt โ€žpassword flowโ€œ), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden. -Die Spec erfordert, dass die Felder exakt `username` und `password` genannt werden und als Formularfelder, nicht JSON, gesendet werden. +Die Spezifikation erfordert, dass die Felder exakt `username` und `password` genannt werden und als Formularfelder, nicht JSON, gesendet werden. Mit `Form` haben Sie die gleichen Konfigurationsmรถglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw. diff --git a/docs/de/docs/tutorial/response-model.md b/docs/de/docs/tutorial/response-model.md index f759bb2571..99d194fe1c 100644 --- a/docs/de/docs/tutorial/response-model.md +++ b/docs/de/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ Es kann Fรคlle geben, bei denen Sie etwas zurรผckgeben, das kein gรผltiges Pydan Der hรคufigste Anwendungsfall ist, wenn Sie [eine Response direkt zurรผckgeben, wie es spรคter im Handbuch fรผr fortgeschrittene Benutzer erlรคutert wird](../advanced/response-directly.md){.internal-link target=_blank}. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die Annotation des Rรผckgabetyps die Klasse (oder eine Unterklasse von) `Response` ist. @@ -193,7 +193,7 @@ Und Tools werden auch glรผcklich sein, weil sowohl `RedirectResponse` als auch ` Sie kรถnnen auch eine Unterklasse von `Response` in der Typannotation verwenden. -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kรผmmert. @@ -201,7 +201,7 @@ Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von ` Aber wenn Sie ein beliebiges anderes Objekt zurรผckgeben, das kein gรผltiger Pydantic-Typ ist (z. B. ein Datenbank-Objekt), und Sie annotieren es so in der Funktion, wird FastAPI versuchen, ein Pydantic-Responsemodell von dieser Typannotation zu erstellen, und scheitern. -Das gleiche wird passieren, wenn Sie eine Union mehrerer Typen haben, und einer oder mehrere sind nicht gรผltige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht ๐Ÿ’ฅ: +Das gleiche wird passieren, wenn Sie eine Union mehrerer Typen haben, und einer oder mehrere sind nicht gรผltige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/de/docs/tutorial/response-status-code.md b/docs/de/docs/tutorial/response-status-code.md index fd17c99336..2ed74f5901 100644 --- a/docs/de/docs/tutorial/response-status-code.md +++ b/docs/de/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ Genauso wie Sie ein Responsemodell angeben kรถnnen, kรถnnen Sie auch den HTTP-St * `@app.delete()` * usw. -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | Hinweis @@ -66,7 +66,7 @@ Kurz gefasst: /// tip | Tipp -Um mehr รผber die einzelnen Statuscodes zu erfahren und welcher wofรผr verwendet wird, sehen Sie sich die MDN Dokumentation รผber HTTP-Statuscodes an. +Um mehr รผber die einzelnen Statuscodes zu erfahren und welcher wofรผr verwendet wird, sehen Sie sich die MDN Dokumentation รผber HTTP-Statuscodes an. /// @@ -74,7 +74,7 @@ Um mehr รผber die einzelnen Statuscodes zu erfahren und welcher wofรผr verwendet Lassen Sie uns das vorherige Beispiel noch einmal anschauen: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` ist der Statuscode fรผr โ€žCreatedโ€œ (โ€žErzeugtโ€œ). @@ -82,7 +82,7 @@ Aber Sie mรผssen sich nicht merken, was jeder dieser Codes bedeutet. Sie kรถnnen die Annehmlichkeit von Variablen aus `fastapi.status` nutzen. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so kรถnnen Sie die Autovervollstรคndigung Ihres Editors verwenden, um sie zu finden: diff --git a/docs/de/docs/tutorial/schema-extra-example.md b/docs/de/docs/tutorial/schema-extra-example.md index 07fe8c5d92..c7b1c2b9ea 100644 --- a/docs/de/docs/tutorial/schema-extra-example.md +++ b/docs/de/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Sie kรถnnen natรผrlich auch mehrere `examples` รผbergeben: Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** fรผr diese Body-Daten. -Wรคhrend dies geschrieben wird, unterstรผtzt Swagger UI, das fรผr die Anzeige der Dokumentations-Benutzeroberflรคche zustรคndige Tool, jedoch nicht die Anzeige mehrerer Beispiele fรผr die Daten in **JSON Schema**. Aber lesen Sie unten fรผr einen Workaround weiter. +Nichtsdestotrotz unterstรผtzt Swagger UI, das fรผr die Anzeige der Dokumentations-Benutzeroberflรคche zustรคndige Tool, zum Zeitpunkt der Erstellung nicht die Anzeige mehrerer Beispiele fรผr die Daten in **JSON Schema**. Aber lesen Sie unten fรผr einen Workaround weiter. ### OpenAPI-spezifische `examples` { #openapi-specific-examples } diff --git a/docs/de/docs/tutorial/security/first-steps.md b/docs/de/docs/tutorial/security/first-steps.md index 20fcd0c007..5806a8ea0f 100644 --- a/docs/de/docs/tutorial/security/first-steps.md +++ b/docs/de/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ Lassen Sie uns zunรคchst einfach den Code verwenden und sehen, wie er funktionie Kopieren Sie das Beispiel in eine Datei `main.py`: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## Ausfรผhren { #run-it } @@ -111,7 +111,7 @@ Betrachten wir es also aus dieser vereinfachten Sicht: * Der Benutzer klickt im Frontend, um zu einem anderen Abschnitt der Frontend-Web-Anwendung zu gelangen. * Das Frontend muss weitere Daten von der API abrufen. * Es benรถtigt jedoch eine Authentifizierung fรผr diesen bestimmten Endpunkt. - * Um sich also bei unserer API zu authentifizieren, sendet es einen Header `Authorization` mit dem Wert `Bearer ` plus dem Token. + * Um sich also bei unserer API zu authentifizieren, sendet es einen `Authorization`-Header mit dem Wert `Bearer ` plus dem Token. * Wenn der Token `foobar` enthielte, wรคre der Inhalt des `Authorization`-Headers: `Bearer foobar`. ## **FastAPI**s `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } @@ -134,7 +134,7 @@ In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen br Wenn wir eine Instanz der Klasse `OAuth2PasswordBearer` erstellen, รผbergeben wir den Parameter `tokenUrl`. Dieser Parameter enthรคlt die URL, die der Client (das Frontend, das im Browser des Benutzers ausgefรผhrt wird) verwendet, wenn er den `username` und das `password` sendet, um einen Token zu erhalten. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | Tipp @@ -172,7 +172,7 @@ Es kann also mit `Depends` verwendet werden. Jetzt kรถnnen Sie dieses `oauth2_scheme` als Abhรคngigkeit `Depends` รผbergeben. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Diese Abhรคngigkeit stellt einen `str` bereit, der dem Parameter `token` der *Pfadoperation-Funktion* zugewiesen wird. diff --git a/docs/de/docs/tutorial/security/get-current-user.md b/docs/de/docs/tutorial/security/get-current-user.md index e32e366698..cfb59ff12f 100644 --- a/docs/de/docs/tutorial/security/get-current-user.md +++ b/docs/de/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` รผberreicht: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} Aber das ist immer noch nicht so nรผtzlich. diff --git a/docs/de/docs/tutorial/security/index.md b/docs/de/docs/tutorial/security/index.md index 39b0b93c98..6330d3d9dc 100644 --- a/docs/de/docs/tutorial/security/index.md +++ b/docs/de/docs/tutorial/security/index.md @@ -20,7 +20,7 @@ OAuth2 ist eine Spezifikation, die verschiedene Mรถglichkeiten zur Handhabung vo Es handelt sich um eine recht umfangreiche Spezifikation, und sie deckt mehrere komplexe Anwendungsfรคlle ab. -Sie umfasst Mรถglichkeiten zur Authentifizierung mithilfe eines โ€žDrittenโ€œ (โ€žthird partyโ€œ). +Sie umfasst Mรถglichkeiten zur Authentifizierung mithilfe eines โ€žDrittenโ€œ. Das ist es, was alle diese โ€žLogin mit Facebook, Google, X (Twitter), GitHubโ€œ-Systeme unter der Haube verwenden. diff --git a/docs/de/docs/tutorial/security/oauth2-jwt.md b/docs/de/docs/tutorial/security/oauth2-jwt.md index 0d5ce587ba..6d35a1436d 100644 --- a/docs/de/docs/tutorial/security/oauth2-jwt.md +++ b/docs/de/docs/tutorial/security/oauth2-jwt.md @@ -116,7 +116,11 @@ Und eine weitere, um zu รผberprรผfen, ob ein empfangenes Passwort mit dem gespei Und noch eine, um einen Benutzer zu authentifizieren und zurรผckzugeben. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Wenn `authenticate_user` mit einem Benutzernamen aufgerufen wird, der in der Datenbank nicht existiert, fรผhren wir dennoch `verify_password` gegen einen Dummy-Hash aus. + +So stellt man sicher, dass der Endpunkt ungefรคhr gleich viel Zeit fรผr die Antwort benรถtigt, unabhรคngig davon, ob der Benutzername gรผltig ist oder nicht. Dadurch werden Timing-Angriffe verhindert, mit denen vorhandene Benutzernamen ermittelt werden kรถnnten. /// note | Hinweis @@ -152,7 +156,7 @@ Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt fรผr die `timedelta` mit der Ablaufz Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurรผck. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### Technische Details zum JWT-โ€žSubjektโ€œ `sub` { #technical-details-about-the-jwt-subject-sub } diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md index 28cb83ba93..ae631f8b72 100644 --- a/docs/de/docs/tutorial/security/simple-oauth2.md +++ b/docs/de/docs/tutorial/security/simple-oauth2.md @@ -18,7 +18,7 @@ Aber fรผr die Login-*Pfadoperation* mรผssen wir diese Namen verwenden, um mit de Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten gesendet werden mรผssen (hier also kein JSON). -### `scope` { #scope } +### `scope` { #scope } Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" (โ€žGeltungsbereichโ€œ) senden kann. diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md index 9ba2501756..26e3853163 100644 --- a/docs/de/docs/tutorial/static-files.md +++ b/docs/de/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ Mit `StaticFiles` kรถnnen Sie statische Dateien aus einem Verzeichnis automatisc * Importieren Sie `StaticFiles`. * โ€žMountenโ€œ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | Technische Details diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md index d889b1e1fb..4fbe37279d 100644 --- a/docs/de/docs/tutorial/testing.md +++ b/docs/de/docs/tutorial/testing.md @@ -30,7 +30,7 @@ Verwenden Sie das `TestClient`-Objekt auf die gleiche Weise wie `httpx`. Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrรผcken, die Sie รผberprรผfen mรผssen (wiederum, Standard-`pytest`). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | Tipp @@ -76,7 +76,7 @@ Nehmen wir an, Sie haben eine Dateistruktur wie in [GrรถรŸere Anwendungen](bigge In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### Testdatei { #testing-file } @@ -93,7 +93,7 @@ Dann kรถnnten Sie eine Datei `test_main.py` mit Ihren Tests haben. Sie kรถnnte s Da sich diese Datei im selben Package befindet, kรถnnen Sie relative Importe verwenden, um das Objekt `app` aus dem `main`-Modul (`main.py`) zu importieren: -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ... und haben den Code fรผr die Tests wie zuvor. diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md index 11da496c54..621b4b1110 100644 --- a/docs/de/docs/virtual-environments.md +++ b/docs/de/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Eine virtuelle Umgebung erstellen { #create-a-virtual-environment } -Wenn Sie zum **ersten Mal** an einem Python-Projekt arbeiten, erstellen Sie eine virtuelle Umgebung **innerhalb Ihres Projekts**. +Wenn Sie zum **ersten Mal** an einem Python-Projekt arbeiten, erstellen Sie eine virtuelle Umgebung **innerhalb Ihres Projekts**. /// tip | Tipp @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate Jedes Mal, wenn Sie ein **neues Paket** in dieser Umgebung installieren, aktivieren Sie die Umgebung erneut. -So stellen Sie sicher, dass, wenn Sie ein **Terminalprogramm (CLI)** verwenden, das durch dieses Paket installiert wurde, Sie das aus Ihrer virtuellen Umgebung verwenden und nicht eines, das global installiert ist, wahrscheinlich mit einer anderen Version als der, die Sie benรถtigen. +So stellen Sie sicher, dass, wenn Sie ein **Terminalprogramm (CLI)** verwenden, das durch dieses Paket installiert wurde, Sie das aus Ihrer virtuellen Umgebung verwenden und nicht eines, das global installiert ist, wahrscheinlich mit einer anderen Version als der, die Sie benรถtigen. /// @@ -639,7 +639,7 @@ $ source .venv/Scripts/activate Dieser Befehl erstellt oder รคndert einige [Umgebungsvariablen](environment-variables.md){.internal-link target=_blank}, die fรผr die nรคchsten Befehle verfรผgbar sein werden. -Eine dieser Variablen ist die `PATH`-Variable. +Eine dieser Variablen ist die `PATH`-Umgebungsvariable. /// tip | Tipp @@ -649,7 +649,7 @@ Sie kรถnnen mehr รผber die `PATH`-Umgebungsvariable im Abschnitt [Umgebungsvaria Das Aktivieren einer virtuellen Umgebung fรผgt deren Pfad `.venv/bin` (auf Linux und macOS) oder `.venv\Scripts` (auf Windows) zur `PATH`-Umgebungsvariable hinzu. -Angenommen, die `PATH`-Variable sah vor dem Aktivieren der Umgebung so aus: +Angenommen, die `PATH`-Umgebungsvariable sah vor dem Aktivieren der Umgebung so aus: //// tab | Linux, macOS @@ -678,7 +678,7 @@ Das bedeutet, dass das System nach Programmen sucht in: //// -Nach dem Aktivieren der virtuellen Umgebung wรผrde die `PATH`-Variable folgendermaรŸen aussehen: +Nach dem Aktivieren der virtuellen Umgebung wรผrde die `PATH`-Umgebungsvariable folgendermaรŸen aussehen: //// tab | Linux, macOS @@ -728,7 +728,7 @@ finden und dieses verwenden. //// -Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Variable platziert. Das System wird es **vor** allen anderen verfรผgbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausfรผhren, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). +Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Umgebungsvariable platziert. Das System wird es **vor** allen anderen verfรผgbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausfรผhren, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). Das Aktivieren einer virtuellen Umgebung รคndert auch ein paar andere Dinge, aber dies ist eines der wichtigsten Dinge, die es tut. From 417990fcb7d933a87117878e131056e76edf969c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Feb 2026 07:57:54 +0000 Subject: [PATCH 236/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2f2d599dc9..631de06115 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for de (update-all) . PR [#14910](https://github.com/fastapi/fastapi/pull/14910) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov). From 7dc1be8b8815c5ea1d09325a973f6af7b531c62b Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:12:41 +0100 Subject: [PATCH 237/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(update-all=20and=20add-missing)=20(#14920)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * Add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/fr/docs/_llm-test.md | 503 ++++++++++ docs/fr/docs/about/index.md | 3 + docs/fr/docs/advanced/additional-responses.md | 6 +- .../docs/advanced/additional-status-codes.md | 2 +- .../fr/docs/advanced/advanced-dependencies.md | 163 ++++ .../fr/docs/advanced/advanced-python-types.md | 61 ++ docs/fr/docs/advanced/async-tests.md | 99 ++ docs/fr/docs/advanced/behind-a-proxy.md | 466 ++++++++++ docs/fr/docs/advanced/custom-response.md | 312 +++++++ docs/fr/docs/advanced/dataclasses.md | 95 ++ docs/fr/docs/advanced/events.md | 165 ++++ docs/fr/docs/advanced/generate-clients.md | 208 +++++ docs/fr/docs/advanced/middleware.md | 97 ++ docs/fr/docs/advanced/openapi-callbacks.md | 186 ++++ docs/fr/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 31 + docs/fr/docs/advanced/response-cookies.md | 51 ++ docs/fr/docs/advanced/response-directly.md | 4 +- docs/fr/docs/advanced/response-headers.md | 41 + .../docs/advanced/security/http-basic-auth.md | 107 +++ docs/fr/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++ docs/fr/docs/advanced/settings.md | 302 ++++++ docs/fr/docs/advanced/sub-applications.md | 67 ++ docs/fr/docs/advanced/templates.md | 126 +++ docs/fr/docs/advanced/testing-dependencies.md | 52 ++ docs/fr/docs/advanced/testing-events.md | 11 + docs/fr/docs/advanced/testing-websockets.md | 13 + .../docs/advanced/using-request-directly.md | 56 ++ docs/fr/docs/advanced/websockets.md | 186 ++++ docs/fr/docs/advanced/wsgi.md | 51 ++ docs/fr/docs/alternatives.md | 152 ++- docs/fr/docs/async.md | 180 ++-- docs/fr/docs/deployment/cloud.md | 24 + docs/fr/docs/deployment/concepts.md | 321 +++++++ docs/fr/docs/deployment/docker.md | 10 +- docs/fr/docs/deployment/fastapicloud.md | 65 ++ docs/fr/docs/deployment/https.md | 2 +- docs/fr/docs/deployment/server-workers.md | 139 +++ docs/fr/docs/environment-variables.md | 298 ++++++ docs/fr/docs/fastapi-cli.md | 75 ++ docs/fr/docs/features.md | 198 ++-- docs/fr/docs/help-fastapi.md | 258 ++++-- docs/fr/docs/history-design-future.md | 22 +- .../authentication-error-status-code.md | 17 + docs/fr/docs/how-to/conditional-openapi.md | 56 ++ docs/fr/docs/how-to/configure-swagger-ui.md | 70 ++ docs/fr/docs/how-to/custom-docs-ui-assets.md | 185 ++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/fr/docs/how-to/extending-openapi.md | 80 ++ docs/fr/docs/how-to/general.md | 39 + docs/fr/docs/how-to/graphql.md | 60 ++ docs/fr/docs/how-to/index.md | 13 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 +++ .../docs/how-to/separate-openapi-schemas.md | 102 +++ docs/fr/docs/how-to/testing-database.md | 7 + docs/fr/docs/index.md | 10 +- docs/fr/docs/learn/index.md | 2 +- docs/fr/docs/python-types.md | 206 +---- docs/fr/docs/resources/index.md | 3 + docs/fr/docs/translation-banner.md | 11 + docs/fr/docs/tutorial/background-tasks.md | 8 +- docs/fr/docs/tutorial/bigger-applications.md | 504 ++++++++++ docs/fr/docs/tutorial/body-fields.md | 61 ++ docs/fr/docs/tutorial/body-multiple-params.md | 6 - docs/fr/docs/tutorial/body-nested-models.md | 220 +++++ docs/fr/docs/tutorial/body-updates.md | 100 ++ docs/fr/docs/tutorial/body.md | 14 +- docs/fr/docs/tutorial/cookie-param-models.md | 76 ++ docs/fr/docs/tutorial/cookie-params.md | 45 + docs/fr/docs/tutorial/cors.md | 88 ++ docs/fr/docs/tutorial/debugging.md | 6 +- .../dependencies/classes-as-dependencies.md | 288 ++++++ ...pendencies-in-path-operation-decorators.md | 69 ++ .../dependencies/dependencies-with-yield.md | 289 ++++++ .../dependencies/global-dependencies.md | 15 + docs/fr/docs/tutorial/dependencies/index.md | 250 +++++ .../tutorial/dependencies/sub-dependencies.md | 105 +++ docs/fr/docs/tutorial/encoder.md | 35 + docs/fr/docs/tutorial/extra-data-types.md | 62 ++ docs/fr/docs/tutorial/extra-models.md | 211 +++++ docs/fr/docs/tutorial/first-steps.md | 24 +- docs/fr/docs/tutorial/handling-errors.md | 244 +++++ docs/fr/docs/tutorial/header-param-models.md | 72 ++ docs/fr/docs/tutorial/header-params.md | 91 ++ docs/fr/docs/tutorial/metadata.md | 120 +++ docs/fr/docs/tutorial/middleware.md | 95 ++ .../tutorial/path-operation-configuration.md | 107 +++ .../path-params-numeric-validations.md | 16 +- docs/fr/docs/tutorial/path-params.md | 30 +- docs/fr/docs/tutorial/query-param-models.md | 68 ++ .../tutorial/query-params-str-validations.md | 42 +- docs/fr/docs/tutorial/query-params.md | 8 +- docs/fr/docs/tutorial/request-files.md | 176 ++++ docs/fr/docs/tutorial/request-form-models.md | 78 ++ .../docs/tutorial/request-forms-and-files.md | 41 + docs/fr/docs/tutorial/request-forms.md | 73 ++ docs/fr/docs/tutorial/response-model.md | 343 +++++++ docs/fr/docs/tutorial/response-status-code.md | 101 ++ docs/fr/docs/tutorial/schema-extra-example.md | 202 ++++ docs/fr/docs/tutorial/security/first-steps.md | 203 ++++ .../tutorial/security/get-current-user.md | 105 +++ docs/fr/docs/tutorial/security/index.md | 106 +++ docs/fr/docs/tutorial/security/oauth2-jwt.md | 277 ++++++ .../docs/tutorial/security/simple-oauth2.md | 289 ++++++ docs/fr/docs/tutorial/sql-databases.md | 357 ++++++++ docs/fr/docs/tutorial/static-files.md | 40 + docs/fr/docs/tutorial/testing.md | 193 ++++ docs/fr/docs/virtual-environments.md | 864 ++++++++++++++++++ 110 files changed, 12889 insertions(+), 605 deletions(-) create mode 100644 docs/fr/docs/_llm-test.md create mode 100644 docs/fr/docs/about/index.md create mode 100644 docs/fr/docs/advanced/advanced-dependencies.md create mode 100644 docs/fr/docs/advanced/advanced-python-types.md create mode 100644 docs/fr/docs/advanced/async-tests.md create mode 100644 docs/fr/docs/advanced/behind-a-proxy.md create mode 100644 docs/fr/docs/advanced/custom-response.md create mode 100644 docs/fr/docs/advanced/dataclasses.md create mode 100644 docs/fr/docs/advanced/events.md create mode 100644 docs/fr/docs/advanced/generate-clients.md create mode 100644 docs/fr/docs/advanced/middleware.md create mode 100644 docs/fr/docs/advanced/openapi-callbacks.md create mode 100644 docs/fr/docs/advanced/openapi-webhooks.md create mode 100644 docs/fr/docs/advanced/response-change-status-code.md create mode 100644 docs/fr/docs/advanced/response-cookies.md create mode 100644 docs/fr/docs/advanced/response-headers.md create mode 100644 docs/fr/docs/advanced/security/http-basic-auth.md create mode 100644 docs/fr/docs/advanced/security/index.md create mode 100644 docs/fr/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/fr/docs/advanced/settings.md create mode 100644 docs/fr/docs/advanced/sub-applications.md create mode 100644 docs/fr/docs/advanced/templates.md create mode 100644 docs/fr/docs/advanced/testing-dependencies.md create mode 100644 docs/fr/docs/advanced/testing-events.md create mode 100644 docs/fr/docs/advanced/testing-websockets.md create mode 100644 docs/fr/docs/advanced/using-request-directly.md create mode 100644 docs/fr/docs/advanced/websockets.md create mode 100644 docs/fr/docs/advanced/wsgi.md create mode 100644 docs/fr/docs/deployment/cloud.md create mode 100644 docs/fr/docs/deployment/concepts.md create mode 100644 docs/fr/docs/deployment/fastapicloud.md create mode 100644 docs/fr/docs/deployment/server-workers.md create mode 100644 docs/fr/docs/environment-variables.md create mode 100644 docs/fr/docs/fastapi-cli.md create mode 100644 docs/fr/docs/how-to/authentication-error-status-code.md create mode 100644 docs/fr/docs/how-to/conditional-openapi.md create mode 100644 docs/fr/docs/how-to/configure-swagger-ui.md create mode 100644 docs/fr/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/fr/docs/how-to/custom-request-and-route.md create mode 100644 docs/fr/docs/how-to/extending-openapi.md create mode 100644 docs/fr/docs/how-to/general.md create mode 100644 docs/fr/docs/how-to/graphql.md create mode 100644 docs/fr/docs/how-to/index.md create mode 100644 docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/fr/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/fr/docs/how-to/testing-database.md create mode 100644 docs/fr/docs/resources/index.md create mode 100644 docs/fr/docs/translation-banner.md create mode 100644 docs/fr/docs/tutorial/bigger-applications.md create mode 100644 docs/fr/docs/tutorial/body-fields.md create mode 100644 docs/fr/docs/tutorial/body-nested-models.md create mode 100644 docs/fr/docs/tutorial/body-updates.md create mode 100644 docs/fr/docs/tutorial/cookie-param-models.md create mode 100644 docs/fr/docs/tutorial/cookie-params.md create mode 100644 docs/fr/docs/tutorial/cors.md create mode 100644 docs/fr/docs/tutorial/dependencies/classes-as-dependencies.md create mode 100644 docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md create mode 100644 docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md create mode 100644 docs/fr/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/fr/docs/tutorial/dependencies/index.md create mode 100644 docs/fr/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/fr/docs/tutorial/encoder.md create mode 100644 docs/fr/docs/tutorial/extra-data-types.md create mode 100644 docs/fr/docs/tutorial/extra-models.md create mode 100644 docs/fr/docs/tutorial/handling-errors.md create mode 100644 docs/fr/docs/tutorial/header-param-models.md create mode 100644 docs/fr/docs/tutorial/header-params.md create mode 100644 docs/fr/docs/tutorial/metadata.md create mode 100644 docs/fr/docs/tutorial/middleware.md create mode 100644 docs/fr/docs/tutorial/path-operation-configuration.md create mode 100644 docs/fr/docs/tutorial/query-param-models.md create mode 100644 docs/fr/docs/tutorial/request-files.md create mode 100644 docs/fr/docs/tutorial/request-form-models.md create mode 100644 docs/fr/docs/tutorial/request-forms-and-files.md create mode 100644 docs/fr/docs/tutorial/request-forms.md create mode 100644 docs/fr/docs/tutorial/response-model.md create mode 100644 docs/fr/docs/tutorial/response-status-code.md create mode 100644 docs/fr/docs/tutorial/schema-extra-example.md create mode 100644 docs/fr/docs/tutorial/security/first-steps.md create mode 100644 docs/fr/docs/tutorial/security/get-current-user.md create mode 100644 docs/fr/docs/tutorial/security/index.md create mode 100644 docs/fr/docs/tutorial/security/oauth2-jwt.md create mode 100644 docs/fr/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/fr/docs/tutorial/sql-databases.md create mode 100644 docs/fr/docs/tutorial/static-files.md create mode 100644 docs/fr/docs/tutorial/testing.md create mode 100644 docs/fr/docs/virtual-environments.md diff --git a/docs/fr/docs/_llm-test.md b/docs/fr/docs/_llm-test.md new file mode 100644 index 0000000000..4fdc677385 --- /dev/null +++ b/docs/fr/docs/_llm-test.md @@ -0,0 +1,503 @@ +# Fichier de test LLM { #llm-test-file } + +Ce document teste si le LLM, qui traduit la documentation, comprend le `general_prompt` dans `scripts/translate.py` et lโ€™invite spรฉcifique ร  la langue dans `docs/{language code}/llm-prompt.md`. Lโ€™invite spรฉcifique ร  la langue est ajoutรฉe ร  la fin de `general_prompt`. + +Les tests ajoutรฉs ici seront visibles par tous les concepteurs dโ€™invites spรฉcifiques ร  chaque langue. + +Utiliser comme suit : + +* Avoir une invite spรฉcifique ร  la langue - `docs/{language code}/llm-prompt.md`. +* Effectuer une nouvelle traduction de ce document dans votre langue cible souhaitรฉe (voir par exemple la commande `translate-page` de `translate.py`). Cela crรฉera la traduction sous `docs/{language code}/docs/_llm-test.md`. +* Vรฉrifier si tout est correct dans la traduction. +* Si nรฉcessaire, amรฉliorer votre invite spรฉcifique ร  la langue, lโ€™invite gรฉnรฉrale, ou le document anglais. +* Corriger ensuite manuellement les problรจmes restants dans la traduction, afin que ce soit une bonne traduction. +* Retraduire, en ayant la bonne traduction en place. Le rรฉsultat idรฉal serait que le LLM ne fasse plus aucun changement ร  la traduction. Cela signifie que lโ€™invite gรฉnรฉrale et votre invite spรฉcifique ร  la langue sont aussi bonnes que possible (il fera parfois quelques changements apparemment alรฉatoires, la raison รฉtant que les LLM ne sont pas des algorithmes dรฉterministes). + +Les tests : + +## Extraits de code { #code-snippets } + +//// tab | Test + +Ceci est un extrait de code : `foo`. Et ceci est un autre extrait de code : `bar`. Et encore un autre : `baz quux`. + +//// + +//// tab | Info + +Le contenu des extraits de code doit รชtre laissรฉ tel quel. + +Voir la section `### Content of code snippets` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +//// + +## Guillemets { #quotes } + +//// tab | Test + +Hier, mon ami a รฉcrit : ยซ Si vous รฉcrivez ยซ incorrectly ยป correctement, vous lโ€™avez รฉcrit de faรงon incorrecte ยป. ร€ quoi jโ€™ai rรฉpondu : ยซ Correct, mais โ€˜incorrectlyโ€™ est incorrectement non pas โ€˜ยซ incorrectly ยปโ€™ ยป. + +/// note | Remarque + +Le LLM traduira probablement ceci de maniรจre erronรฉe. Il est seulement intรฉressant de voir sโ€™il conserve la traduction corrigรฉe lors dโ€™une retraduction. + +/// + +//// + +//// tab | Info + +Le concepteur de lโ€™invite peut choisir sโ€™il souhaite convertir les guillemets neutres en guillemets typographiques. Il est acceptable de les laisser tels quels. + +Voir par exemple la section `### Quotes` dans `docs/de/llm-prompt.md`. + +//// + +## Guillemets dans les extraits de code { #quotes-in-code-snippets } + +//// tab | Test + +`pip install "foo[bar]"` + +Exemples de littรฉraux de chaรฎne dans des extraits de code : `"this"`, `'that'`. + +Un exemple difficile de littรฉraux de chaรฎne dans des extraits de code : `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... Cependant, les guillemets ร  lโ€™intรฉrieur des extraits de code doivent rester tels quels. + +//// + +## Blocs de code { #code-blocks } + +//// tab | Test + +Un exemple de code Bash ... + +```bash +# Afficher un message de bienvenue ร  l'univers +echo "Hello universe" +``` + +... et un exemple de code console ... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +... et un autre exemple de code console ... + +```console +// Crรฉer un rรฉpertoire "Code" +$ mkdir code +// Aller dans ce rรฉpertoire +$ cd code +``` + +... et un exemple de code Python ... + +```Python +wont_work() # Cela ne fonctionnera pas ๐Ÿ˜ฑ +works(foo="bar") # Cela fonctionne ๐ŸŽ‰ +``` + +... et cโ€™est tout. + +//// + +//// tab | Info + +Le code dans les blocs de code ne doit pas รชtre modifiรฉ, ร  lโ€™exception des commentaires. + +Voir la section `### Content of code blocks` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +//// + +## Onglets et encadrรฉs colorรฉs { #tabs-and-colored-boxes } + +//// tab | Test + +/// info | Info +Du texte +/// + +/// note | Remarque +Du texte +/// + +/// note | Dรฉtails techniques +Du texte +/// + +/// check | Vรฉrifications +Du texte +/// + +/// tip | Astuce +Du texte +/// + +/// warning | Alertes +Du texte +/// + +/// danger | Danger +Du texte +/// + +//// + +//// tab | Info + +Les onglets et les blocs ยซ Info ยป/ยซ Note ยป/ยซ Warning ยป/etc. doivent avoir la traduction de leur titre ajoutรฉe aprรจs une barre verticale (ยซ | ยป). + +Voir les sections `### Special blocks` et `### Tab blocks` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +//// + +## Liens Web et internes { #web-and-internal-links } + +//// tab | Test + +Le texte du lien doit รชtre traduit, lโ€™adresse du lien doit rester inchangรฉe : + +* [Lien vers le titre ci-dessus](#code-snippets) +* [Lien interne](index.md#installation){.internal-link target=_blank} +* Lien externe +* Lien vers une feuille de style +* Lien vers un script +* Lien vers une image + +Le texte du lien doit รชtre traduit, lโ€™adresse du lien doit pointer vers la traduction : + +* Lien FastAPI + +//// + +//// tab | Info + +Les liens doivent รชtre traduits, mais leur adresse doit rester inchangรฉe. Exception faite des liens absolus vers des pages de la documentation FastAPI. Dans ce cas, il faut pointer vers la traduction. + +Voir la section `### Links` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +//// + +## ร‰lรฉments HTML ยซ abbr ยป { #html-abbr-elements } + +//// tab | Test + +Voici quelques รฉlรฉments entourรฉs dโ€™un รฉlรฉment HTML ยซ abbr ยป (certains sont inventรฉs) : + +### Lโ€™abbr fournit une expression complรจte { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Lโ€™abbr donne une expression complรจte et une explication { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +Les attributs ยซ title ยป des รฉlรฉments ยซ abbr ยป sont traduits en suivant des consignes spรฉcifiques. + +Les traductions peuvent ajouter leurs propres รฉlรฉments ยซ abbr ยป que le LLM ne doit pas supprimer. Par exemple pour expliquer des mots anglais. + +Voir la section `### HTML abbr elements` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +//// + +## ร‰lรฉments HTML ยซ dfn ยป { #html-dfn-elements } + +* grappe +* Apprentissage profond + +## Titres { #headings } + +//// tab | Test + +### Crรฉer une application Web - un tutoriel { #develop-a-webapp-a-tutorial } + +Bonjour. + +### Annotations de type et indications de type { #type-hints-and-annotations } + +Rebonjour. + +### Superclasses et sous-classes { #super-and-subclasses } + +Rebonjour. + +//// + +//// tab | Info + +La seule rรจgle stricte pour les titres est que le LLM laisse la partie hachage entre accolades inchangรฉe, ce qui garantit que les liens ne se rompent pas. + +Voir la section `### Headings` dans lโ€™invite gรฉnรฉrale dans `scripts/translate.py`. + +Pour certaines consignes spรฉcifiques ร  la langue, voir par exemple la section `### Headings` dans `docs/de/llm-prompt.md`. + +//// + +## Termes utilisรฉs dans les documents { #terms-used-in-the-docs } + +//// tab | Test + +* vous +* votre + +* p. ex. +* etc. + +* `foo` en tant que `int` +* `bar` en tant que `str` +* `baz` en tant que `list` + +* le Tutoriel - Guide utilisateur +* le Guide utilisateur avancรฉ +* la documentation SQLModel +* la documentation de lโ€™API +* la documentation automatique + +* Data Science +* Apprentissage profond +* Apprentissage automatique +* Injection de dรฉpendances +* authentification HTTP Basic +* HTTP Digest +* format ISO +* la norme JSON Schema +* le schรฉma JSON +* la dรฉfinition de schรฉma +* Flux Password +* Mobile + +* dรฉprรฉciรฉ +* conรงu +* invalide +* ร  la volรฉe +* standard +* par dรฉfaut +* sensible ร  la casse +* insensible ร  la casse + +* servir lโ€™application +* servir la page + +* lโ€™app +* lโ€™application + +* la requรชte +* la rรฉponse +* la rรฉponse dโ€™erreur + +* le chemin dโ€™accรจs +* le dรฉcorateur de chemin dโ€™accรจs +* la fonction de chemin dโ€™accรจs + +* le corps +* le corps de la requรชte +* le corps de la rรฉponse +* le corps JSON +* le corps de formulaire +* le corps de fichier +* le corps de la fonction + +* le paramรจtre +* le paramรจtre de corps +* le paramรจtre de chemin +* le paramรจtre de requรชte +* le paramรจtre de cookie +* le paramรจtre dโ€™en-tรชte +* le paramรจtre de formulaire +* le paramรจtre de fonction + +* lโ€™รฉvรฉnement +* lโ€™รฉvรฉnement de dรฉmarrage +* le dรฉmarrage du serveur +* lโ€™รฉvรฉnement dโ€™arrรชt +* lโ€™รฉvรฉnement de cycle de vie + +* le gestionnaire +* le gestionnaire dโ€™รฉvรฉnements +* le gestionnaire dโ€™exceptions +* gรฉrer + +* le modรจle +* le modรจle Pydantic +* le modรจle de donnรฉes +* le modรจle de base de donnรฉes +* le modรจle de formulaire +* lโ€™objet modรจle + +* la classe +* la classe de base +* la classe parente +* la sous-classe +* la classe enfant +* la classe sล“ur +* la mรฉthode de classe + +* lโ€™en-tรชte +* les en-tรชtes +* lโ€™en-tรชte dโ€™autorisation +* lโ€™en-tรชte `Authorization` +* lโ€™en-tรชte transfรฉrรฉ + +* le systรจme dโ€™injection de dรฉpendances +* la dรฉpendance +* lโ€™รฉlรฉment dรฉpendable +* le dรฉpendant + +* liรฉ aux E/S +* liรฉ au processeur +* concurrence +* parallรฉlisme +* multi-traitement + +* la variable dโ€™env +* la variable dโ€™environnement +* le `PATH` +* la variable `PATH` + +* lโ€™authentification +* le fournisseur dโ€™authentification +* lโ€™autorisation +* le formulaire dโ€™autorisation +* le fournisseur dโ€™autorisation +* lโ€™utilisateur sโ€™authentifie +* le systรจme authentifie lโ€™utilisateur + +* la CLI +* lโ€™interface en ligne de commande + +* le serveur +* le client + +* le fournisseur cloud +* le service cloud + +* le dรฉveloppement +* les รฉtapes de dรฉveloppement + +* le dict +* le dictionnaire +* lโ€™รฉnumรฉration +* lโ€™enum +* le membre dโ€™enum + +* lโ€™encodeur +* le dรฉcodeur +* encoder +* dรฉcoder + +* lโ€™exception +* lever + +* lโ€™expression +* lโ€™instruction + +* le frontend +* le backend + +* la discussion GitHub +* le ticket GitHub + +* la performance +* lโ€™optimisation des performances + +* le type de retour +* la valeur de retour + +* la sรฉcuritรฉ +* le schรฉma de sรฉcuritรฉ + +* la tรขche +* la tรขche dโ€™arriรจre-plan +* la fonction de tรขche + +* le template +* le moteur de templates + +* lโ€™annotation de type +* lโ€™annotation de type + +* le worker du serveur +* le worker Uvicorn +* le Worker Gunicorn +* le processus worker +* la classe de worker +* la charge de travail + +* le dรฉploiement +* dรฉployer + +* le SDK +* le kit de dรฉveloppement logiciel + +* le `APIRouter` +* le `requirements.txt` +* le jeton Bearer +* le changement majeur incompatible +* le bogue +* le bouton +* lโ€™appelable +* le code +* le commit +* le gestionnaire de contexte +* la coroutine +* la session de base de donnรฉes +* le disque +* le domaine +* le moteur +* le faux X +* la mรฉthode HTTP GET +* lโ€™รฉlรฉment +* la bibliothรจque +* le cycle de vie +* le verrou +* le middleware +* lโ€™application mobile +* le module +* le montage +* le rรฉseau +* lโ€™origine +* la surcharge +* le payload +* le processeur +* la propriรฉtรฉ +* le proxy +* la pull request +* la requรชte +* la RAM +* la machine distante +* le code dโ€™รฉtat +* la chaรฎne +* lโ€™รฉtiquette +* le framework Web +* le joker +* retourner +* valider + +//// + +//// tab | Info + +Il sโ€™agit dโ€™une liste non exhaustive et non normative de termes (principalement) techniques prรฉsents dans les documents. Elle peut aider le concepteur de lโ€™invite ร  dรฉterminer pour quels termes le LLM a besoin dโ€™un coup de main. Par exemple, lorsquโ€™il continue de remplacer une bonne traduction par une traduction sous-optimale. Ou lorsquโ€™il a des difficultรฉs ร  conjuguer/dรฉcliner un terme dans votre langue. + +Voir par exemple la section `### List of English terms and their preferred German translations` dans `docs/de/llm-prompt.md`. + +//// diff --git a/docs/fr/docs/about/index.md b/docs/fr/docs/about/index.md new file mode 100644 index 0000000000..f6ec12a4f8 --- /dev/null +++ b/docs/fr/docs/about/index.md @@ -0,0 +1,3 @@ +# ร€ propos { #about } + +ร€ propos de FastAPI, de sa conception, de ses sources d'inspiration et plus encore. ๐Ÿค“ diff --git a/docs/fr/docs/advanced/additional-responses.md b/docs/fr/docs/advanced/additional-responses.md index dabcded52e..a073dec692 100644 --- a/docs/fr/docs/advanced/additional-responses.md +++ b/docs/fr/docs/advanced/additional-responses.md @@ -8,7 +8,7 @@ Si vous dรฉbutez avec **FastAPI**, vous n'en aurez peut-รชtre pas besoin. /// -Vous pouvez dรฉclarer des rรฉponses supplรฉmentaires, avec des codes HTTP, des types de mรฉdias, des descriptions, etc. +Vous pouvez dรฉclarer des rรฉponses supplรฉmentaires, avec des codes d'รฉtat supplรฉmentaires, des types de mรฉdias, des descriptions, etc. Ces rรฉponses supplรฉmentaires seront incluses dans le schรฉma OpenAPI, elles apparaรฎtront donc รฉgalement dans la documentation de l'API. @@ -26,7 +26,7 @@ Chacun de ces `dict` de rรฉponse peut avoir une clรฉ `model`, contenant un modรจ Par exemple, pour dรฉclarer une autre rรฉponse avec un code HTTP `404` et un modรจle Pydantic `Message`, vous pouvez รฉcrireย : -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | Remarque @@ -203,7 +203,7 @@ Par exemple, vous pouvez dรฉclarer une rรฉponse avec un code HTTP `404` qui util Et une rรฉponse avec un code HTTP `200` qui utilise votre `response_model`, mais inclut un `example` personnalisรฉย : -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} Tout sera combinรฉ et inclus dans votre OpenAPI, et affichรฉ dans la documentation de l'APIย : diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md index b2befffa8d..b9c8ab1136 100644 --- a/docs/fr/docs/advanced/additional-status-codes.md +++ b/docs/fr/docs/advanced/additional-status-codes.md @@ -36,6 +36,6 @@ Pour plus de commoditรฉs, **FastAPI** fournit les objets `starlette.responses` s ## Documents OpenAPI et API { #openapi-and-api-docs } -Si vous renvoyez directement des codes HTTP et des rรฉponses supplรฉmentaires, ils ne seront pas inclus dans le schรฉma OpenAPI (la documentation de l'API), car FastAPI n'a aucun moyen de savoir ร  l'avance ce que vous allez renvoyer. +Si vous renvoyez directement des codes HTTP et des rรฉponses supplรฉmentaires, ils ne seront pas inclus dans le schรฉma OpenAPI (les documents de l'API), car FastAPI n'a aucun moyen de savoir ร  l'avance ce que vous allez renvoyer. Mais vous pouvez documenter cela dans votre code, en utilisantย : [Rรฉponses supplรฉmentaires](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/advanced/advanced-dependencies.md b/docs/fr/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000..8afd58b48e --- /dev/null +++ b/docs/fr/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# Dรฉpendances avancรฉes { #advanced-dependencies } + +## Dรฉpendances paramรฉtrรฉes { #parameterized-dependencies } + +Toutes les dรฉpendances que nous avons vues รฉtaient des fonctions ou des classes fixes. + +Mais il peut y avoir des cas oรน vous souhaitez pouvoir dรฉfinir des paramรจtres sur la dรฉpendance, sans devoir dรฉclarer de nombreuses fonctions ou classes diffรฉrentes. + +Imaginons que nous voulions avoir une dรฉpendance qui vรฉrifie si le paramรจtre de requรชte `q` contient un contenu fixe. + +Mais nous voulons pouvoir paramรฉtrer ce contenu fixe. + +## Une instance ยซ callable ยป { #a-callable-instance } + +En Python, il existe un moyen de rendre une instance de classe ยซ callable ยป. + +Pas la classe elleโ€‘mรชme (qui est dรฉjร  un callable), mais une instance de cette classe. + +Pour cela, nous dรฉclarons une mรฉthode `__call__` : + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +Dans ce cas, ce `__call__` est ce que **FastAPI** utilisera pour dรฉtecter des paramรจtres supplรฉmentaires et des sousโ€‘dรฉpendances, et cโ€™est ce qui sera appelรฉ pour transmettre ensuite une valeur au paramรจtre dans votre *fonction de chemin d'accรจs*. + +## Paramรฉtrer l'instance { #parameterize-the-instance } + +Et maintenant, nous pouvons utiliser `__init__` pour dรฉclarer les paramรจtres de lโ€™instance, que nous utiliserons pour ยซ paramรฉtrer ยป la dรฉpendance : + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +Dans ce cas, **FastAPI** nโ€™accรจdera pas ร  `__init__` et ne sโ€™en souciera pas ; nous lโ€™utiliserons directement dans notre code. + +## Crรฉer une instance { #create-an-instance } + +Nous pouvons crรฉer une instance de cette classe avec : + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +Et de cette faรงon, nous pouvons ยซ paramรฉtrer ยป notre dรฉpendance, qui contient maintenant ยซ bar ยป, en tant quโ€™attribut `checker.fixed_content`. + +## Utiliser l'instance comme dรฉpendance { #use-the-instance-as-a-dependency } + +Ensuite, nous pourrions utiliser ce `checker` dans un `Depends(checker)`, au lieu de `Depends(FixedContentQueryChecker)`, car la dรฉpendance est lโ€™instance, `checker`, et non la classe elleโ€‘mรชme. + +Et lors de la rรฉsolution de la dรฉpendance, **FastAPI** appellera ce `checker` comme ceci : + +```Python +checker(q="somequery") +``` + +... et passera ce que cela renvoie comme valeur de la dรฉpendance ร  notre *fonction de chemin d'accรจs*, en tant que paramรจtre `fixed_content_included` : + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | Astuce + +Tout cela peut sembler artificiel. Et il nโ€™est peutโ€‘รชtre pas encore trรจs clair en quoi cโ€™est utile. + +Ces exemples sont volontairement simples, mais ils montrent comment tout cela fonctionne. + +Dans les chapitres sur la sรฉcuritรฉ, il existe des fonctions utilitaires implรฉmentรฉes de la mรชme maniรจre. + +Si vous avez compris tout cela, vous savez dรฉjร  comment ces outils utilitaires pour la sรฉcuritรฉ fonctionnent en interne. + +/// + +## Dรฉpendances avec `yield`, `HTTPException`, `except` et tรขches d'arriรจreโ€‘plan { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | Alertes + +Vous nโ€™avez trรจs probablement pas besoin de ces dรฉtails techniques. + +Ces dรฉtails sont utiles principalement si vous aviez une application FastAPI antรฉrieure ร  la version 0.121.0 et que vous rencontrez des problรจmes avec des dรฉpendances utilisant `yield`. + +/// + +Les dรฉpendances avec `yield` ont รฉvoluรฉ au fil du temps pour couvrir diffรฉrents cas dโ€™utilisation et corriger certains problรจmes ; voici un rรฉsumรฉ de ce qui a changรฉ. + +### Dรฉpendances avec `yield` et `scope` { #dependencies-with-yield-and-scope } + +Dans la version 0.121.0, **FastAPI** a ajoutรฉ la prise en charge de `Depends(scope="function")` pour les dรฉpendances avec `yield`. + +Avec `Depends(scope="function")`, le code dโ€™arrรชt aprรจs `yield` sโ€™exรฉcute immรฉdiatement aprรจs la fin de la *fonction de chemin d'accรจs*, avant que la rรฉponse ne soit renvoyรฉe au client. + +Et lorsque vous utilisez `Depends(scope="request")` (valeur par dรฉfaut), le code dโ€™arrรชt aprรจs `yield` sโ€™exรฉcute aprรจs lโ€™envoi de la rรฉponse. + +Vous pouvez en lire davantage dans les documents pour [Dรฉpendances avec `yield` - Sortie anticipรฉe et `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope). + +### Dรฉpendances avec `yield` et `StreamingResponse`, Dรฉtails techniques { #dependencies-with-yield-and-streamingresponse-technical-details } + +Avant FastAPI 0.118.0, si vous utilisiez une dรฉpendance avec `yield`, elle exรฉcutait le code dโ€™arrรชt aprรจs que la *fonction de chemin d'accรจs* a retournรฉ, mais juste avant dโ€™envoyer la rรฉponse. + +Lโ€™objectif รฉtait dโ€™รฉviter de conserver des ressources plus longtemps que nรฉcessaire pendant que la rรฉponse transitait sur le rรฉseau. + +Ce changement impliquait aussi que si vous retourniez une `StreamingResponse`, le code dโ€™arrรชt de la dรฉpendance avec `yield` aurait dรฉjร  รฉtรฉ exรฉcutรฉ. + +Par exemple, si vous aviez une session de base de donnรฉes dans une dรฉpendance avec `yield`, la `StreamingResponse` ne pourrait pas utiliser cette session pendant le streaming des donnรฉes, car la session aurait dรฉjร  รฉtรฉ fermรฉe dans le code dโ€™arrรชt aprรจs `yield`. + +Ce comportement a รฉtรฉ annulรฉ en 0.118.0, afin que le code dโ€™arrรชt aprรจs `yield` sโ€™exรฉcute aprรจs lโ€™envoi de la rรฉponse. + +/// info + +Comme vous le verrez ciโ€‘dessous, cโ€™est trรจs similaire au comportement avant la version 0.106.0, mais avec plusieurs amรฉliorations et corrections de bogues pour des cas limites. + +/// + +#### Cas dโ€™utilisation avec sortie anticipรฉe du code { #use-cases-with-early-exit-code } + +Il existe certains cas dโ€™utilisation avec des conditions spรฉcifiques qui pourraient bรฉnรฉficier de lโ€™ancien comportement, oรน le code dโ€™arrรชt des dรฉpendances avec `yield` sโ€™exรฉcute avant lโ€™envoi de la rรฉponse. + +Par exemple, imaginez que vous ayez du code qui utilise une session de base de donnรฉes dans une dรฉpendance avec `yield` uniquement pour vรฉrifier un utilisateur, mais que la session de base de donnรฉes ne soit plus jamais utilisรฉe dans la *fonction de chemin d'accรจs*, seulement dans la dรฉpendance, et que la rรฉponse mette longtemps ร  รชtre envoyรฉe, comme une `StreamingResponse` qui envoie les donnรฉes lentement mais qui, pour une raison quelconque, nโ€™utilise pas la base de donnรฉes. + +Dans ce cas, la session de base de donnรฉes serait conservรฉe jusquโ€™ร  la fin de lโ€™envoi de la rรฉponse, mais si vous ne lโ€™utilisez pas, il ne serait pas nรฉcessaire de la conserver. + +Voici ร  quoi cela pourrait ressembler : + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +Le code dโ€™arrรชt, la fermeture automatique de la `Session` dans : + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +... serait exรฉcutรฉ aprรจs que la rรฉponse a fini dโ€™envoyer les donnรฉes lentes : + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +Mais comme `generate_stream()` nโ€™utilise pas la session de base de donnรฉes, il nโ€™est pas vraiment nรฉcessaire de garder la session ouverte pendant lโ€™envoi de la rรฉponse. + +Si vous avez ce cas dโ€™utilisation spรฉcifique avec SQLModel (ou SQLAlchemy), vous pouvez fermer explicitement la session dรจs que vous nโ€™en avez plus besoin : + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +De cette maniรจre, la session libรฉrera la connexion ร  la base de donnรฉes, afin que dโ€™autres requรชtes puissent lโ€™utiliser. + +Si vous avez un autre cas dโ€™utilisation qui nรฉcessite une sortie anticipรฉe depuis une dรฉpendance avec `yield`, veuillez crรฉer une Question de discussion GitHub avec votre cas spรฉcifique et pourquoi vous bรฉnรฉficieriez dโ€™une fermeture anticipรฉe pour les dรฉpendances avec `yield`. + +Sโ€™il existe des cas dโ€™utilisation convaincants pour une fermeture anticipรฉe dans les dรฉpendances avec `yield`, jโ€™envisagerai dโ€™ajouter une nouvelle faรงon dโ€™y opter. + +### Dรฉpendances avec `yield` et `except`, Dรฉtails techniques { #dependencies-with-yield-and-except-technical-details } + +Avant FastAPI 0.110.0, si vous utilisiez une dรฉpendance avec `yield`, puis capturiez une exception avec `except` dans cette dรฉpendance, et que vous ne relanciez pas lโ€™exception, lโ€™exception รฉtait automatiquement levรฉe/transmise ร  tout gestionnaire dโ€™exceptions ou au gestionnaire dโ€™erreur interne du serveur. + +Cela a รฉtรฉ modifiรฉ dans la version 0.110.0 pour corriger une consommation de mรฉmoire non gรฉrรฉe due aux exceptions transmises sans gestionnaire (erreurs internes du serveur), et pour rendre le comportement cohรฉrent avec celui du code Python classique. + +### Tรขches d'arriรจreโ€‘plan et dรฉpendances avec `yield`, Dรฉtails techniques { #background-tasks-and-dependencies-with-yield-technical-details } + +Avant FastAPI 0.106.0, lever des exceptions aprรจs `yield` nโ€™รฉtait pas possible, le code dโ€™arrรชt dans les dรฉpendances avec `yield` sโ€™exรฉcutait aprรจs lโ€™envoi de la rรฉponse, donc les [Gestionnaires d'exceptions](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} avaient dรฉjร  รฉtรฉ exรฉcutรฉs. + +Cela avait รฉtรฉ conรงu ainsi principalement pour permettre dโ€™utiliser les mรชmes objets ยซ gรฉnรฉrรฉs par yield ยป par les dรฉpendances ร  lโ€™intรฉrieur de tรขches dโ€™arriรจreโ€‘plan, car le code dโ€™arrรชt sโ€™exรฉcutait aprรจs la fin des tรขches dโ€™arriรจreโ€‘plan. + +Cela a รฉtรฉ modifiรฉ dans FastAPI 0.106.0 afin de ne pas conserver des ressources pendant lโ€™attente de la transmission de la rรฉponse sur le rรฉseau. + +/// tip | Astuce + +De plus, une tรขche dโ€™arriรจreโ€‘plan est normalement un ensemble de logique indรฉpendant qui devrait รชtre gรฉrรฉ sรฉparรฉment, avec ses propres ressources (par ex. sa propre connexion ร  la base de donnรฉes). + +Ainsi, vous aurez probablement un code plus propre. + +/// + +Si vous comptiez sur ce comportement, vous devez dรฉsormais crรฉer les ressources pour les tรขches dโ€™arriรจreโ€‘plan ร  lโ€™intรฉrieur de la tรขche elleโ€‘mรชme, et nโ€™utiliser en interne que des donnรฉes qui ne dรฉpendent pas des ressources des dรฉpendances avec `yield`. + +Par exemple, au lieu dโ€™utiliser la mรชme session de base de donnรฉes, vous crรฉeriez une nouvelle session de base de donnรฉes ร  lโ€™intรฉrieur de la tรขche dโ€™arriรจreโ€‘plan, et vous obtiendriez les objets depuis la base de donnรฉes en utilisant cette nouvelle session. Puis, au lieu de passer lโ€™objet obtenu depuis la base de donnรฉes en paramรจtre ร  la fonction de tรขche dโ€™arriรจreโ€‘plan, vous passeriez lโ€™identifiant (ID) de cet objet et vous obtiendriez ร  nouveau lโ€™objet ร  lโ€™intรฉrieur de la fonction de la tรขche dโ€™arriรจreโ€‘plan. diff --git a/docs/fr/docs/advanced/advanced-python-types.md b/docs/fr/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..3e2d9453b6 --- /dev/null +++ b/docs/fr/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Types Python avancรฉs { #advanced-python-types } + +Voici quelques idรฉes supplรฉmentaires qui peuvent รชtre utiles lorsque vous travaillez avec les types Python. + +## Utiliser `Union` ou `Optional` { #using-union-or-optional } + +Si votre code ne peut pas utiliser `|` pour une raison quelconque, par exemple si ce n'est pas dans une annotation de type mais dans quelque chose comme `response_model=`, au lieu d'utiliser la barre verticale (`|`) vous pouvez utiliser `Union` de `typing`. + +Par exemple, vous pourriez dรฉclarer que quelque chose peut รชtre un `str` ou `None` : + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` propose รฉgalement un raccourci pour dรฉclarer que quelque chose peut รชtre `None`, avec `Optional`. + +Voici un conseil issu de mon point de vue trรจs subjectif : + +- ๐Ÿšจ ร‰vitez d'utiliser `Optional[SomeType]` +- ร€ la place โœจ **utilisez `Union[SomeType, None]`** โœจ. + +Les deux sont รฉquivalents et, en interne, identiques, mais je recommande `Union` plutรดt que `Optional` parce que le mot ยซ optional ยป semble impliquer que la valeur est facultative, alors qu'il signifie en rรฉalitรฉ ยซ elle peut รชtre `None` ยป, mรชme si elle n'est pas facultative et reste requise. + +Je pense que `Union[SomeType, None]` est plus explicite quant ร  sa signification. + +Il ne s'agit que des mots et des noms. Mais ces mots peuvent influencer la maniรจre dont vous et vos coรฉquipiers pensez au code. + +ร€ titre d'exemple, prenons cette fonction : + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +Le paramรจtre `name` est dรฉfini comme `Optional[str]`, mais il n'est pas facultatif, vous ne pouvez pas appeler la fonction sans le paramรจtre : + +```Python +say_hi() # Oh non, cela lรจve une erreur ! ๐Ÿ˜ฑ +``` + +Le paramรจtre `name` est toujours requis (pas facultatif) car il n'a pas de valeur par dรฉfaut. En revanche, `name` accepte `None` comme valeur : + +```Python +say_hi(name=None) # Ceci fonctionne, None est valide ๐ŸŽ‰ +``` + +La bonne nouvelle, c'est que, dans la plupart des cas, vous pourrez simplement utiliser `|` pour dรฉfinir des unions de types : + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Ainsi, normalement, vous n'avez pas ร  vous prรฉoccuper de noms comme `Optional` et `Union`. ๐Ÿ˜Ž diff --git a/docs/fr/docs/advanced/async-tests.md b/docs/fr/docs/advanced/async-tests.md new file mode 100644 index 0000000000..f9cea0ad17 --- /dev/null +++ b/docs/fr/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Tests asynchrones { #async-tests } + +Vous avez dรฉjร  vu comment tester vos applications **FastAPI** en utilisant le `TestClient` fourni. Jusqu'ร  prรฉsent, vous n'avez vu que comment รฉcrire des tests synchrones, sans utiliser de fonctions `async`. + +Pouvoir utiliser des fonctions asynchrones dans vos tests peut รชtre utile, par exemple lorsque vous interrogez votre base de donnรฉes de maniรจre asynchrone. Imaginez que vous vouliez tester l'envoi de requรชtes ร  votre application FastAPI puis vรฉrifier que votre backend a bien รฉcrit les bonnes donnรฉes dans la base, tout en utilisant une bibliothรจque de base de donnรฉes asynchrone. + +Voyons comment procรฉder. + +## pytest.mark.anyio { #pytest-mark-anyio } + +Si nous voulons appeler des fonctions asynchrones dans nos tests, nos fonctions de test doivent รชtre asynchrones. AnyIO fournit un plug-in pratique qui nous permet d'indiquer que certaines fonctions de test doivent รชtre appelรฉes de maniรจre asynchrone. + +## HTTPX { #httpx } + +Mรชme si votre application **FastAPI** utilise des fonctions `def` normales au lieu de `async def`, c'est toujours une application `async` en interne. + +Le `TestClient` fait un peu de magie pour appeler l'application FastAPI asynchrone depuis vos fonctions de test `def` normales, en utilisant pytest standard. Mais cette magie ne fonctionne plus lorsque nous l'utilisons dans des fonctions asynchrones. En exรฉcutant nos tests de maniรจre asynchrone, nous ne pouvons plus utiliser le `TestClient` dans nos fonctions de test. + +Le `TestClient` est basรฉ sur HTTPX et, heureusement, nous pouvons l'utiliser directement pour tester l'API. + +## Exemple { #example } + +Pour un exemple simple, considรฉrons une structure de fichiers similaire ร  celle dรฉcrite dans [Applications plus grandes](../tutorial/bigger-applications.md){.internal-link target=_blank} et [Tests](../tutorial/testing.md){.internal-link target=_blank} : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +Le fichier `main.py` contiendrait : + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +Le fichier `test_main.py` contiendrait les tests pour `main.py`, il pourrait maintenant ressembler ร  ceci : + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## Exรฉcuter { #run-it } + +Vous pouvez lancer vos tests comme d'habitude via : + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## En dรฉtail { #in-detail } + +Le marqueur `@pytest.mark.anyio` indique ร  pytest que cette fonction de test doit รชtre appelรฉe de maniรจre asynchrone : + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | Astuce + +Notez que la fonction de test est maintenant `async def` au lieu de simplement `def` comme auparavant avec le `TestClient`. + +/// + +Nous pouvons ensuite crรฉer un `AsyncClient` avec l'application et lui envoyer des requรชtes asynchrones en utilisant `await`. + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +C'est l'รฉquivalent de : + +```Python +response = client.get('/') +``` + +... que nous utilisions pour faire nos requรชtes avec le `TestClient`. + +/// tip | Astuce + +Notez que nous utilisons async/await avec le nouveau `AsyncClient` โ€” la requรชte est asynchrone. + +/// + +/// warning | Alertes + +Si votre application s'appuie sur des รฉvรฉnements de cycle de vie (lifespan), le `AsyncClient` ne dรฉclenchera pas ces รฉvรฉnements. Pour vous assurer qu'ils sont dรฉclenchรฉs, utilisez `LifespanManager` depuis florimondmanca/asgi-lifespan. + +/// + +## Autres appels de fonctions asynchrones { #other-asynchronous-function-calls } + +Comme la fonction de test est dรฉsormais asynchrone, vous pouvez รฉgalement appeler (et `await`) d'autres fonctions `async` en plus d'envoyer des requรชtes ร  votre application FastAPI dans vos tests, exactement comme vous le feriez ailleurs dans votre code. + +/// tip | Astuce + +Si vous rencontrez une erreur `RuntimeError: Task attached to a different loop` lors de l'intรฉgration d'appels de fonctions asynchrones dans vos tests (par exemple en utilisant MotorClient de MongoDB), n'oubliez pas d'instancier les objets qui ont besoin d'une boucle d'รฉvรฉnements uniquement dans des fonctions async, par exemple dans un callback `@app.on_event("startup")`. + +/// diff --git a/docs/fr/docs/advanced/behind-a-proxy.md b/docs/fr/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..4b540e1a1d --- /dev/null +++ b/docs/fr/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# รŠtre derriรจre un proxy { #behind-a-proxy } + +Dans de nombreuses situations, vous utiliserez un **proxy** comme Traefik ou Nginx devant votre application FastAPI. + +Ces proxies peuvent gรฉrer les certificats HTTPS et d'autres aspects. + +## En-tรชtes transfรฉrรฉs par le proxy { #proxy-forwarded-headers } + +Un **proxy** placรฉ devant votre application dรฉfinit normalement certains en-tรชtes ร  la volรฉe avant d'envoyer les requรชtes ร  votre **serveur**, afin d'indiquer au serveur que la requรชte a รฉtรฉ **transfรฉrรฉe** par le proxy, en lui donnant l'URL d'origine (publique), y compris le domaine, le fait qu'elle utilise HTTPS, etc. + +Le programme **serveur** (par exemple **Uvicorn** via **FastAPI CLI**) est capable d'interprรฉter ces enโ€‘tรชtes, puis de transmettre ces informations ร  votre application. + +Mais, par sรฉcuritรฉ, comme le serveur ne sait pas qu'il se trouve derriรจre un proxy de confiance, il n'interprรฉtera pas ces enโ€‘tรชtes. + +/// note | Dรฉtails techniques + +Les en-tรชtes du proxy sont : + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### Activer les en-tรชtes transfรฉrรฉs par le proxy { #enable-proxy-forwarded-headers } + +Vous pouvez dรฉmarrer FastAPI CLI avec l'option de CLI `--forwarded-allow-ips` et fournir les adresses IP ร  considรฉrer comme fiables pour lire ces enโ€‘tรชtes transfรฉrรฉs. + +Si vous la dรฉfinissez ร  `--forwarded-allow-ips="*"`, elle fera confiance ร  toutes les IP entrantes. + +Si votre **serveur** est derriรจre un **proxy** de confiance et que seul le proxy lui parle, cela fera accepter l'IP de ce **proxy**, quelle qu'elle soit. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Redirections avec HTTPS { #redirects-with-https } + +Par exemple, disons que vous dรฉfinissez un *chemin d'accรจs* `/items/` : + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +Si le client essaie d'aller ร  `/items`, par dรฉfaut, il sera redirigรฉ vers `/items/`. + +Mais avant de dรฉfinir l'option de CLI `--forwarded-allow-ips`, il pourrait rediriger vers `http://localhost:8000/items/`. + +Mais peutโ€‘รชtre que votre application est hรฉbergรฉe ร  `https://mysuperapp.com`, et la redirection devrait รชtre vers `https://mysuperapp.com/items/`. + +En dรฉfinissant `--proxy-headers`, FastAPI pourra dรฉsormais rediriger vers l'emplacement correct. ๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | Astuce + +Si vous voulez en savoir plus sur HTTPS, consultez le guide [ร€ propos de HTTPS](../deployment/https.md){.internal-link target=_blank}. + +/// + +### Comment fonctionnent les enโ€‘tรชtes transfรฉrรฉs par le proxy { #how-proxy-forwarded-headers-work } + +Voici une reprรฉsentation visuelle de la faรงon dont le **proxy** ajoute des enโ€‘tรชtes transfรฉrรฉs entre le client et le **serveur d'application** : + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +Le **proxy** intercepte la requรชte client d'origine et ajoute les en-tรชtes spรฉciaux *forwarded* (`X-Forwarded-*`) avant de transmettre la requรชte au **serveur d'application**. + +Ces enโ€‘tรชtes conservent des informations sur la requรชte d'origine qui seraient autrement perdues : + +* **X-Forwarded-For** : l'adresse IP du client d'origine +* **X-Forwarded-Proto** : le protocole d'origine (`https`) +* **X-Forwarded-Host** : l'hรดte d'origine (`mysuperapp.com`) + +Lorsque **FastAPI CLI** est configurรฉe avec `--forwarded-allow-ips`, elle fait confiance ร  ces enโ€‘tรชtes et les utilise, par exemple pour gรฉnรฉrer les bonnes URL dans les redirections. + +## Proxy avec un prรฉfixe de chemin supprimรฉ { #proxy-with-a-stripped-path-prefix } + +Vous pouvez avoir un proxy qui ajoute un prรฉfixe de chemin ร  votre application. + +Dans ces cas, vous pouvez utiliser `root_path` pour configurer votre application. + +Le `root_path` est un mรฉcanisme fourni par la spรฉcification ASGI (sur laquelle FastAPI est construit, via Starlette). + +Le `root_path` est utilisรฉ pour gรฉrer ces cas spรฉcifiques. + +Et il est รฉgalement utilisรฉ en interne lors du montage de sousโ€‘applications. + +Avoir un proxy avec un prรฉfixe de chemin supprimรฉ, dans ce cas, signifie que vous pourriez dรฉclarer un chemin ร  `/app` dans votre code, mais ensuite, vous ajoutez une couche auโ€‘dessus (le proxy) qui place votre application **FastAPI** sous un chemin comme `/api/v1`. + +Dans ce cas, le chemin original `/app` serait en rรฉalitรฉ servi ร  `/api/v1/app`. + +Mรชme si tout votre code est รฉcrit en supposant qu'il n'y a que `/app`. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +Et le proxy **ยซ stripping ยป** le **prรฉfixe de chemin** ร  la volรฉe avant de transmettre la requรชte au serveur de l'application (probablement Uvicorn via FastAPI CLI), en gardant votre application convaincue qu'elle est servie ร  `/app`, afin que vous n'ayez pas ร  mettre ร  jour tout votre code pour inclure le prรฉfixe `/api/v1`. + +Jusqu'ici, tout fonctionnerait normalement. + +Mais ensuite, lorsque vous ouvrez l'interface de documentation intรฉgrรฉe (le frontend), elle s'attendra ร  obtenir le schรฉma OpenAPI ร  `/openapi.json`, au lieu de `/api/v1/openapi.json`. + +Ainsi, le frontend (qui s'exรฉcute dans le navigateur) essaiera d'atteindre `/openapi.json` et ne pourra pas obtenir le schรฉma OpenAPI. + +Parce que nous avons un proxy avec un prรฉfixe de chemin `/api/v1` pour notre application, le frontend doit rรฉcupรฉrer le schรฉma OpenAPI ร  `/api/v1/openapi.json`. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | Astuce + +L'IP `0.0.0.0` est couramment utilisรฉe pour signifier que le programme รฉcoute sur toutes les IP disponibles de cette machine/serveur. + +/// + +L'interface de documents doit รฉgalement indiquer dans le schรฉma OpenAPI que ce `server` d'API se trouve ร  `/api/v1` (derriรจre le proxy). Par exemple : + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // Plus d'รฉlรฉments ici + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // Plus d'รฉlรฉments ici + } +} +``` + +Dans cet exemple, le ยซ Proxy ยป pourrait รชtre quelque chose comme **Traefik**. Et le serveur serait quelque chose comme FastAPI CLI avec **Uvicorn**, exรฉcutant votre application FastAPI. + +### Fournir le `root_path` { #providing-the-root-path } + +Pour y parvenir, vous pouvez utiliser l'option de ligne de commande `--root-path` comme suit : + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Si vous utilisez Hypercorn, il dispose รฉgalement de l'option `--root-path`. + +/// note | Dรฉtails techniques + +La spรฉcification ASGI dรฉfinit un `root_path` pour ce cas d'usage. + +Et l'option de ligne de commande `--root-path` fournit ce `root_path`. + +/// + +### Vรฉrifier le `root_path` actuel { #checking-the-current-root-path } + +Vous pouvez obtenir le `root_path` actuel utilisรฉ par votre application pour chaque requรชte, il fait partie du dictionnaire `scope` (qui fait partie de la spรฉcification ASGI). + +Ici, nous l'incluons dans le message uniquement ร  des fins de dรฉmonstration. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +Ensuite, si vous dรฉmarrez Uvicorn avec : + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +La rรฉponse sera semblable ร  : + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### Dรฉfinir le `root_path` dans l'application FastAPI { #setting-the-root-path-in-the-fastapi-app } + +Autrement, si vous n'avez pas la possibilitรฉ de fournir une option de ligne de commande comme `--root-path` ou รฉquivalent, vous pouvez dรฉfinir le paramรจtre `root_path` lors de la crรฉation de votre application FastAPI : + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +Passer le `root_path` ร  `FastAPI` รฉquivaut ร  passer l'option de ligne de commande `--root-path` ร  Uvicorn ou Hypercorn. + +### ร€ propos de `root_path` { #about-root-path } + +Gardez ร  l'esprit que le serveur (Uvicorn) n'utilisera ce `root_path` que pour le transmettre ร  l'application. + +Mais si vous allez avec votre navigateur sur http://127.0.0.1:8000/app, vous verrez la rรฉponse normale : + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +Donc, il ne s'attendra pas ร  รชtre accessible ร  `http://127.0.0.1:8000/api/v1/app`. + +Uvicorn s'attendra ร  ce que le proxy accรจde ร  Uvicorn sur `http://127.0.0.1:8000/app`, et ce sera ensuite la responsabilitรฉ du proxy d'ajouter le prรฉfixe supplรฉmentaire `/api/v1` auโ€‘dessus. + +## ร€ propos des proxies avec un prรฉfixe de chemin supprimรฉ { #about-proxies-with-a-stripped-path-prefix } + +Gardez ร  l'esprit qu'un proxy avec prรฉfixe de chemin supprimรฉ n'est qu'une des faรงons de le configurer. + +Dans de nombreux cas, la valeur par dรฉfaut sera probablement que le proxy n'a pas de prรฉfixe de chemin supprimรฉ. + +Dans un cas comme celuiโ€‘ci (sans prรฉfixe de chemin supprimรฉ), le proxy รฉcoutera sur quelque chose comme `https://myawesomeapp.com`, puis si le navigateur va sur `https://myawesomeapp.com/api/v1/app` et que votre serveur (par ex. Uvicorn) รฉcoute sur `http://127.0.0.1:8000`, le proxy (sans prรฉfixe de chemin supprimรฉ) accรฉdera ร  Uvicorn au mรชme chemin : `http://127.0.0.1:8000/api/v1/app`. + +## Tester localement avec Traefik { #testing-locally-with-traefik } + +Vous pouvez facilement faire l'expรฉrience en local avec un prรฉfixe de chemin supprimรฉ en utilisant Traefik. + +Tรฉlรฉchargez Traefik ; c'est un binaire unique, vous pouvez extraire le fichier compressรฉ et l'exรฉcuter directement depuis le terminal. + +Crรฉez ensuite un fichier `traefik.toml` avec : + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +Cela indique ร  Traefik d'รฉcouter sur le port 9999 et d'utiliser un autre fichier `routes.toml`. + +/// tip | Astuce + +Nous utilisons le port 9999 au lieu du port HTTP standard 80 afin que vous n'ayez pas ร  l'exรฉcuter avec des privilรจges administrateur (`sudo`). + +/// + +Crรฉez maintenant cet autre fichier `routes.toml` : + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +Ce fichier configure Traefik pour utiliser le prรฉfixe de chemin `/api/v1`. + +Puis Traefik redirigera ses requรชtes vers votre Uvicorn tournant sur `http://127.0.0.1:8000`. + +Dรฉmarrez maintenant Traefik : + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +Et dรฉmarrez maintenant votre application, en utilisant l'option `--root-path` : + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Vรฉrifier les rรฉponses { #check-the-responses } + +Maintenant, si vous allez ร  l'URL avec le port pour Uvicorn : http://127.0.0.1:8000/app, vous verrez la rรฉponse normale : + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | Astuce + +Remarquez que mรชme si vous y accรฉdez via `http://127.0.0.1:8000/app`, il affiche le `root_path` de `/api/v1`, repris depuis l'option `--root-path`. + +/// + +Et maintenant ouvrez l'URL avec le port pour Traefik, en incluant le prรฉfixe de chemin : http://127.0.0.1:9999/api/v1/app. + +Nous obtenons la mรชme rรฉponse : + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +mais cette fois ร  l'URL avec le prรฉfixe fourni par le proxy : `/api/v1`. + +Bien sรปr, l'idรฉe ici est que tout le monde accรจde ร  l'application via le proxy ; la version avec le prรฉfixe de chemin `/api/v1` est donc la ยซ correcte ยป. + +Et la version sans prรฉfixe de chemin (`http://127.0.0.1:8000/app`), fournie directement par Uvicorn, serait exclusivement destinรฉe au _proxy_ (Traefik) pour y accรฉder. + +Cela montre comment le Proxy (Traefik) utilise le prรฉfixe de chemin et comment le serveur (Uvicorn) utilise le `root_path` fourni par l'option `--root-path`. + +### Vรฉrifier l'interface de documentation { #check-the-docs-ui } + +Mais voici la partie intรฉressante. โœจ + +La maniรจre ยซ officielle ยป d'accรฉder ร  l'application serait via le proxy avec le prรฉfixe de chemin que nous avons dรฉfini. Donc, comme on s'y attend, si vous essayez l'interface de documentation servie directement par Uvicorn, sans le prรฉfixe de chemin dans l'URL, cela ne fonctionne pas, car elle s'attend ร  รชtre accรฉdรฉe via le proxy. + +Vous pouvez le vรฉrifier sur http://127.0.0.1:8000/docs : + + + +Mais si nous accรฉdons ร  l'interface de documents ร  l'URL ยซ officielle ยป en utilisant le proxy avec le port `9999`, ร  `/api/v1/docs`, cela fonctionne correctement ! ๐ŸŽ‰ + +Vous pouvez le vรฉrifier sur http://127.0.0.1:9999/api/v1/docs : + + + +Exactement comme nous le voulions. โœ”๏ธ + +C'est parce que FastAPI utilise ce `root_path` pour crรฉer le `server` par dรฉfaut dans OpenAPI avec l'URL fournie par `root_path`. + +## Serveurs supplรฉmentaires { #additional-servers } + +/// warning | Alertes + +Ceci est un cas d'utilisation plus avancรฉ. N'hรฉsitez pas ร  l'ignorer. + +/// + +Par dรฉfaut, **FastAPI** crรฉera un `server` dans le schรฉma OpenAPI avec l'URL correspondant au `root_path`. + +Mais vous pouvez aussi fournir d'autres `servers` alternatifs, par exemple si vous voulez que la mรชme interface de documents interagisse avec un environnement de staging et un environnement de production. + +Si vous passez une liste personnalisรฉe de `servers` et qu'il y a un `root_path` (parce que votre API vit derriรจre un proxy), **FastAPI** insรฉrera un ยซ server ยป avec ce `root_path` au dรฉbut de la liste. + +Par exemple : + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +Gรฉnรฉrera un schรฉma OpenAPI comme : + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // Plus d'รฉlรฉments ici + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // Plus d'รฉlรฉments ici + } +} +``` + +/// tip | Astuce + +Remarquez le serveur gรฉnรฉrรฉ automatiquement avec une valeur `url` de `/api/v1`, reprise depuis le `root_path`. + +/// + +Dans l'interface de documents sur http://127.0.0.1:9999/api/v1/docs, cela ressemblera ร  ceci : + + + +/// tip | Astuce + +L'interface de documents interagit avec le serveur que vous sรฉlectionnez. + +/// + +/// note | Dรฉtails techniques + +La propriรฉtรฉ `servers` dans la spรฉcification OpenAPI est facultative. + +Si vous ne spรฉcifiez pas le paramรจtre `servers` et que `root_path` est รฉgal ร  `/`, la propriรฉtรฉ `servers` dans le schรฉma OpenAPI gรฉnรฉrรฉ sera entiรจrement omise par dรฉfaut, ce qui รฉquivaut ร  un seul serveur avec une valeur `url` de `/`. + +/// + +### Dรฉsactiver le serveur automatique issu de `root_path` { #disable-automatic-server-from-root-path } + +Si vous ne voulez pas que **FastAPI** inclue un serveur automatique utilisant le `root_path`, vous pouvez utiliser le paramรจtre `root_path_in_servers=False` : + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +et il ne l'inclura alors pas dans le schรฉma OpenAPI. + +## Monter une sous-application { #mounting-a-sub-application } + +Si vous avez besoin de monter une sousโ€‘application (comme dรฉcrit dans [Sousโ€‘applications - montages](sub-applications.md){.internal-link target=_blank}) tout en utilisant un proxy avec `root_path`, vous pouvez le faire normalement, comme vous vous y attendez. + +FastAPI utilisera intelligemment le `root_path` en interne, donc cela fonctionnera simplement. โœจ diff --git a/docs/fr/docs/advanced/custom-response.md b/docs/fr/docs/advanced/custom-response.md new file mode 100644 index 0000000000..7eab5b53fc --- /dev/null +++ b/docs/fr/docs/advanced/custom-response.md @@ -0,0 +1,312 @@ +# Rรฉponse personnalisรฉe - HTML, flux, fichier, autres { #custom-response-html-stream-file-others } + +Par dรฉfaut, **FastAPI** renverra les rรฉponses en utilisant `JSONResponse`. + +Vous pouvez le remplacer en renvoyant directement une `Response` comme expliquรฉ dans [Renvoyer directement une Response](response-directly.md){.internal-link target=_blank}. + +Mais si vous renvoyez directement une `Response` (ou n'importe quelle sous-classe, comme `JSONResponse`), les donnรฉes ne seront pas automatiquement converties (mรชme si vous dรฉclarez un `response_model`), et la documentation ne sera pas gรฉnรฉrรฉe automatiquement (par exemple, l'inclusion du ยซ media type ยป dans l'en-tรชte HTTP `Content-Type` comme partie de l'OpenAPI gรฉnรฉrรฉ). + +Vous pouvez aussi dรฉclarer la `Response` que vous voulez utiliser (par ex. toute sous-classe de `Response`), dans le dรฉcorateur de chemin d'accรจs en utilisant le paramรจtre `response_class`. + +Le contenu que vous renvoyez depuis votre fonction de chemin d'accรจs sera placรฉ ร  l'intรฉrieur de cette `Response`. + +Et si cette `Response` a un ยซ media type ยป JSON (`application/json`), comme c'est le cas avec `JSONResponse` et `UJSONResponse`, les donnรฉes que vous renvoyez seront automatiquement converties (et filtrรฉes) avec tout `response_model` Pydantic que vous avez dรฉclarรฉ dans le dรฉcorateur de chemin d'accรจs. + +/// note | Remarque + +Si vous utilisez une classe de rรฉponse sans ยซ media type ยป, FastAPI s'attendra ร  ce que votre rรฉponse n'ait pas de contenu ; il ne documentera donc pas le format de la rรฉponse dans les documents OpenAPI gรฉnรฉrรฉs. + +/// + +## Utiliser `ORJSONResponse` { #use-orjsonresponse } + +Par exemple, si vous cherchez ร  maximiser la performance, vous pouvez installer et utiliser `orjson` et dรฉfinir la rรฉponse sur `ORJSONResponse`. + +Importez la classe (sous-classe) `Response` que vous voulez utiliser et dรฉclarez-la dans le dรฉcorateur de chemin d'accรจs. + +Pour de grandes rรฉponses, renvoyer directement une `Response` est bien plus rapide que de renvoyer un dictionnaire. + +Cela vient du fait que, par dรฉfaut, FastAPI inspectera chaque รฉlรฉment et s'assurera qu'il est sรฉrialisable en JSON, en utilisant le mรชme [Encodeur compatible JSON](../tutorial/encoder.md){.internal-link target=_blank} expliquรฉ dans le didacticiel. C'est ce qui vous permet de renvoyer des objets arbitraires, par exemple des modรจles de base de donnรฉes. + +Mais si vous รชtes certain que le contenu que vous renvoyez est sรฉrialisable en JSON, vous pouvez le passer directement ร  la classe de rรฉponse et รฉviter le surcoรปt supplรฉmentaire qu'aurait FastAPI en faisant passer votre contenu de retour par le `jsonable_encoder` avant de le transmettre ร  la classe de rรฉponse. + +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} + +/// info + +Le paramรจtre `response_class` sera aussi utilisรฉ pour dรฉfinir le ยซ media type ยป de la rรฉponse. + +Dans ce cas, l'en-tรชte HTTP `Content-Type` sera dรฉfini ร  `application/json`. + +Et il sera documentรฉ comme tel dans OpenAPI. + +/// + +/// tip | Astuce + +`ORJSONResponse` est disponible uniquement dans FastAPI, pas dans Starlette. + +/// + +## Rรฉponse HTML { #html-response } + +Pour renvoyer une rรฉponse avec du HTML directement depuis **FastAPI**, utilisez `HTMLResponse`. + +- Importez `HTMLResponse`. +- Passez `HTMLResponse` comme paramรจtre `response_class` de votre dรฉcorateur de chemin d'accรจs. + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// info + +Le paramรจtre `response_class` sera aussi utilisรฉ pour dรฉfinir le ยซ media type ยป de la rรฉponse. + +Dans ce cas, l'en-tรชte HTTP `Content-Type` sera dรฉfini ร  `text/html`. + +Et il sera documentรฉ comme tel dans OpenAPI. + +/// + +### Renvoyer une `Response` { #return-a-response } + +Comme vu dans [Renvoyer directement une Response](response-directly.md){.internal-link target=_blank}, vous pouvez aussi remplacer la rรฉponse directement dans votre chemin d'accรจs, en la renvoyant. + +Le mรชme exemple ci-dessus, renvoyant une `HTMLResponse`, pourrait ressembler ร  : + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning | Alertes + +Une `Response` renvoyรฉe directement par votre fonction de chemin d'accรจs ne sera pas documentรฉe dans OpenAPI (par exemple, le `Content-Type` ne sera pas documentรฉ) et ne sera pas visible dans les documents interactifs automatiques. + +/// + +/// info + +Bien sรปr, l'en-tรชte `Content-Type` rรฉel, le code d'รฉtat, etc., proviendront de l'objet `Response` que vous avez renvoyรฉ. + +/// + +### Documenter dans OpenAPI et remplacer `Response` { #document-in-openapi-and-override-response } + +Si vous voulez remplacer la rรฉponse depuis l'intรฉrieur de la fonction mais en mรชme temps documenter le ยซ media type ยป dans OpenAPI, vous pouvez utiliser le paramรจtre `response_class` ET renvoyer un objet `Response`. + +`response_class` sera alors utilisรฉ uniquement pour documenter l'opรฉration de chemin d'accรจs OpenAPI, mais votre `Response` sera utilisรฉe telle quelle. + +#### Renvoyer directement une `HTMLResponse` { #return-an-htmlresponse-directly } + +Par exemple, cela pourrait รชtre quelque chose comme : + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +Dans cet exemple, la fonction `generate_html_response()` gรฉnรจre dรฉjร  et renvoie une `Response` au lieu de renvoyer le HTML dans une `str`. + +En renvoyant le rรฉsultat de l'appel ร  `generate_html_response()`, vous renvoyez dรฉjร  une `Response` qui remplacera le comportement par dรฉfaut de **FastAPI**. + +Mais comme vous avez aussi passรฉ `HTMLResponse` dans `response_class`, **FastAPI** saura comment la documenter dans OpenAPI et les documents interactifs comme HTML avec `text/html` : + + + +## Rรฉponses disponibles { #available-responses } + +Voici certaines des rรฉponses disponibles. + +Gardez ร  l'esprit que vous pouvez utiliser `Response` pour renvoyer autre chose, ou mรชme crรฉer une sous-classe personnalisรฉe. + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.responses import HTMLResponse`. + +**FastAPI** fournit les mรชmes `starlette.responses` sous `fastapi.responses` simplement pour votre confort de dรฉveloppement. Mais la plupart des rรฉponses disponibles viennent directement de Starlette. + +/// + +### `Response` { #response } + +La classe principale `Response`, toutes les autres rรฉponses en hรฉritent. + +Vous pouvez la renvoyer directement. + +Elle accepte les paramรจtres suivants : + +- `content` - Une `str` ou des `bytes`. +- `status_code` - Un code d'รฉtat HTTP de type `int`. +- `headers` - Un `dict` de chaรฎnes. +- `media_type` - Une `str` donnant le media type. Par exemple ยซ text/html ยป. + +FastAPI (en fait Starlette) inclura automatiquement un en-tรชte Content-Length. Il inclura aussi un en-tรชte Content-Type, basรฉ sur `media_type` et en ajoutant un charset pour les types textuels. + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +Prend du texte ou des octets et renvoie une rรฉponse HTML, comme vous l'avez lu ci-dessus. + +### `PlainTextResponse` { #plaintextresponse } + +Prend du texte ou des octets et renvoie une rรฉponse en texte brut. + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +Prend des donnรฉes et renvoie une rรฉponse encodรฉe en `application/json`. + +C'est la rรฉponse par dรฉfaut utilisรฉe dans **FastAPI**, comme vous l'avez lu ci-dessus. + +### `ORJSONResponse` { #orjsonresponse } + +Une rรฉponse JSON alternative rapide utilisant `orjson`, comme vous l'avez lu ci-dessus. + +/// info + +Cela nรฉcessite l'installation de `orjson`, par exemple avec `pip install orjson`. + +/// + +### `UJSONResponse` { #ujsonresponse } + +Une rรฉponse JSON alternative utilisant `ujson`. + +/// info + +Cela nรฉcessite l'installation de `ujson`, par exemple avec `pip install ujson`. + +/// + +/// warning | Alertes + +`ujson` est moins rigoureux que l'implรฉmentation intรฉgrรฉe de Python dans sa gestion de certains cas limites. + +/// + +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} + +/// tip | Astuce + +Il est possible que `ORJSONResponse` soit une alternative plus rapide. + +/// + +### `RedirectResponse` { #redirectresponse } + +Renvoie une redirection HTTP. Utilise par dรฉfaut un code d'รฉtat 307 (Temporary Redirect). + +Vous pouvez renvoyer directement une `RedirectResponse` : + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +Ou vous pouvez l'utiliser dans le paramรจtre `response_class` : + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +Si vous faites cela, vous pouvez alors renvoyer directement l'URL depuis votre fonction de chemin d'accรจs. + +Dans ce cas, le `status_code` utilisรฉ sera celui par dรฉfaut pour `RedirectResponse`, c'est-ร -dire `307`. + +--- + +Vous pouvez aussi utiliser le paramรจtre `status_code` combinรฉ avec le paramรจtre `response_class` : + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +Prend un gรฉnรฉrateur async ou un gรฉnรฉrateur/itรฉrateur normal et diffuse le corps de la rรฉponse. + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} + +#### Utiliser `StreamingResponse` avec des objets de type fichier { #using-streamingresponse-with-file-like-objects } + +Si vous avez un objet de type fichier (par ex. l'objet renvoyรฉ par `open()`), vous pouvez crรฉer une fonction gรฉnรฉratrice pour itรฉrer sur cet objet de type fichier. + +De cette faรงon, vous n'avez pas ร  tout lire en mรฉmoire au prรฉalable, et vous pouvez passer cette fonction gรฉnรฉratrice ร  `StreamingResponse`, puis la renvoyer. + +Cela inclut de nombreuses bibliothรจques pour interagir avec du stockage cloud, du traitement vidรฉo, et autres. + +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} + +1. C'est la fonction gรฉnรฉratrice. C'est une ยซ fonction gรฉnรฉratrice ยป parce qu'elle contient des instructions `yield` ร  l'intรฉrieur. +2. En utilisant un bloc `with`, nous nous assurons que l'objet de type fichier est fermรฉ aprรจs l'exรฉcution de la fonction gรฉnรฉratrice. Donc, aprรจs qu'elle a fini d'envoyer la rรฉponse. +3. Ce `yield from` indique ร  la fonction d'itรฉrer sur l'objet nommรฉ `file_like`. Puis, pour chaque partie itรฉrรฉe, de produire cette partie comme provenant de cette fonction gรฉnรฉratrice (`iterfile`). + + Ainsi, c'est une fonction gรฉnรฉratrice qui transfรจre le travail de ยซ gรฉnรฉration ยป ร  autre chose en interne. + + En procรฉdant ainsi, nous pouvons la placer dans un bloc `with` et, de cette faรงon, garantir que l'objet de type fichier est fermรฉ aprรจs la fin. + +/// tip | Astuce + +Remarquez qu'ici, comme nous utilisons le `open()` standard qui ne prend pas en charge `async` et `await`, nous dรฉclarons le chemin d'accรจs avec un `def` normal. + +/// + +### `FileResponse` { #fileresponse } + +Diffuse de faรงon asynchrone un fichier comme rรฉponse. + +Prend un ensemble de paramรจtres diffรฉrent ร  l'instanciation par rapport aux autres types de rรฉponse : + +- `path` - Le chemin du fichier ร  diffuser. +- `headers` - D'รฉventuels en-tรชtes personnalisรฉs ร  inclure, sous forme de dictionnaire. +- `media_type` - Une chaรฎne donnant le media type. Si non dรฉfini, le nom du fichier ou le chemin sera utilisรฉ pour en dรฉduire un media type. +- `filename` - Si dรฉfini, sera inclus dans l'en-tรชte `Content-Disposition` de la rรฉponse. + +Les rรฉponses de type fichier incluront les en-tรชtes appropriรฉs `Content-Length`, `Last-Modified` et `ETag`. + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +Vous pouvez aussi utiliser le paramรจtre `response_class` : + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +Dans ce cas, vous pouvez renvoyer directement le chemin du fichier depuis votre fonction de chemin d'accรจs. + +## Classe de rรฉponse personnalisรฉe { #custom-response-class } + +Vous pouvez crรฉer votre propre classe de rรฉponse personnalisรฉe, hรฉritant de `Response`, et l'utiliser. + +Par exemple, disons que vous voulez utiliser `orjson`, mais avec certains rรฉglages personnalisรฉs non utilisรฉs dans la classe `ORJSONResponse` incluse. + +Disons que vous voulez renvoyer du JSON indentรฉ et formatรฉ, donc vous voulez utiliser l'option orjson `orjson.OPT_INDENT_2`. + +Vous pourriez crรฉer une `CustomORJSONResponse`. L'essentiel est de crรฉer une mรฉthode `Response.render(content)` qui renvoie le contenu en `bytes` : + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +Maintenant, au lieu de renvoyer : + +```json +{"message": "Hello World"} +``` + +... cette rรฉponse renverra : + +```json +{ + "message": "Hello World" +} +``` + +Bien sรปr, vous trouverez probablement des moyens bien meilleurs de tirer parti de cela que de formater du JSON. ๐Ÿ˜‰ + +## Classe de rรฉponse par dรฉfaut { #default-response-class } + +Lors de la crรฉation d'une instance de classe **FastAPI** ou d'un `APIRouter`, vous pouvez spรฉcifier quelle classe de rรฉponse utiliser par dรฉfaut. + +Le paramรจtre qui le dรฉfinit est `default_response_class`. + +Dans l'exemple ci-dessous, **FastAPI** utilisera `ORJSONResponse` par dรฉfaut, dans tous les chemins d'accรจs, au lieu de `JSONResponse`. + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip | Astuce + +Vous pouvez toujours remplacer `response_class` dans les chemins d'accรจs comme auparavant. + +/// + +## Documentation supplรฉmentaire { #additional-documentation } + +Vous pouvez aussi dรฉclarer le media type et de nombreux autres dรฉtails dans OpenAPI en utilisant `responses` : [Rรฉponses supplรฉmentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/advanced/dataclasses.md b/docs/fr/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..2bd77157e8 --- /dev/null +++ b/docs/fr/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Utiliser des dataclasses { #using-dataclasses } + +FastAPI est construit auโ€‘dessus de **Pydantic**, et je vous ai montrรฉ comment utiliser des modรจles Pydantic pour dรฉclarer les requรชtes et les rรฉponses. + +Mais FastAPI prend aussi en charge l'utilisation de `dataclasses` de la mรชme maniรจre : + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +Cela fonctionne grรขce ร  **Pydantic**, qui offre une prise en charge interne des `dataclasses`. + +Ainsi, mรชme avec le code ciโ€‘dessus qui n'emploie pas explicitement Pydantic, FastAPI utilise Pydantic pour convertir ces dataclasses standard en la variante de dataclasses de Pydantic. + +Et bien sรปr, cela prend en charge la mรชme chose : + +* validation des donnรฉes +* sรฉrialisation des donnรฉes +* documentation des donnรฉes, etc. + +Cela fonctionne de la mรชme maniรจre qu'avec les modรจles Pydantic. Et, en rรฉalitรฉ, c'est mis en ล“uvre de la mรชme faรงon en interne, en utilisant Pydantic. + +/// info | Info + +Gardez ร  l'esprit que les dataclasses ne peuvent pas tout ce que peuvent faire les modรจles Pydantic. + +Vous pourriez donc avoir encore besoin d'utiliser des modรจles Pydantic. + +Mais si vous avez dรฉjร  un ensemble de dataclasses sous la main, c'est une astuce pratique pour les utiliser afin d'alimenter une API Web avec FastAPI. ๐Ÿค“ + +/// + +## Utiliser des dataclasses dans `response_model` { #dataclasses-in-response-model } + +Vous pouvez aussi utiliser `dataclasses` dans le paramรจtre `response_model` : + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +La dataclass sera automatiquement convertie en dataclass Pydantic. + +Ainsi, son schรฉma apparaรฎtra dans l'interface utilisateur de la documentation de l'API : + + + +## Utiliser des dataclasses dans des structures de donnรฉes imbriquรฉes { #dataclasses-in-nested-data-structures } + +Vous pouvez aussi combiner `dataclasses` avec d'autres annotations de type pour crรฉer des structures de donnรฉes imbriquรฉes. + +Dans certains cas, vous devrez peutโ€‘รชtre encore utiliser la version `dataclasses` de Pydantic. Par exemple, si vous rencontrez des erreurs avec la documentation d'API gรฉnรฉrรฉe automatiquement. + +Dans ce cas, vous pouvez simplement remplacer les `dataclasses` standard par `pydantic.dataclasses`, qui est un remplacement dropโ€‘in : + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. Nous continuons ร  importer `field` depuis les `dataclasses` standard. + +2. `pydantic.dataclasses` est un remplacement dropโ€‘in pour `dataclasses`. + +3. La dataclass `Author` inclut une liste de dataclasses `Item`. + +4. La dataclass `Author` est utilisรฉe comme paramรจtre `response_model`. + +5. Vous pouvez utiliser d'autres annotations de type standard avec des dataclasses comme corps de la requรชte. + + Dans ce cas, il s'agit d'une liste de dataclasses `Item`. + +6. Ici, nous renvoyons un dictionnaire qui contient `items`, qui est une liste de dataclasses. + + FastAPI est toujours capable de sรฉrialiser les donnรฉes en JSON. + +7. Ici, `response_model` utilise une annotation de type correspondant ร  une liste de dataclasses `Author`. + + Lร  encore, vous pouvez combiner `dataclasses` avec des annotations de type standard. + +8. Notez que cette *fonction de chemin d'accรจs* utilise un `def` classique au lieu de `async def`. + + Comme toujours, avec FastAPI vous pouvez combiner `def` et `async def` selon vos besoins. + + Si vous avez besoin d'un rappel sur quand utiliser l'un ou l'autre, consultez la section _ยซ In a hurry? ยป_ dans la documentation ร  propos de [`async` et `await`](../async.md#in-a-hurry){.internal-link target=_blank}. + +9. Cette *fonction de chemin d'accรจs* ne renvoie pas des dataclasses (mรชme si elle le pourrait), mais une liste de dictionnaires contenant des donnรฉes internes. + + FastAPI utilisera le paramรจtre `response_model` (qui inclut des dataclasses) pour convertir la rรฉponse. + +Vous pouvez combiner `dataclasses` avec d'autres annotations de type, selon de nombreuses combinaisons, pour former des structures de donnรฉes complexes. + +Reportezโ€‘vous aux annotations dans le code ciโ€‘dessus pour voir plus de dรฉtails spรฉcifiques. + +## En savoir plus { #learn-more } + +Vous pouvez aussi combiner `dataclasses` avec d'autres modรจles Pydantic, en hรฉriter, les inclure dans vos propres modรจles, etc. + +Pour en savoir plus, consultez la documentation Pydantic sur les dataclasses. + +## Version { #version } + +C'est disponible depuis FastAPI version `0.67.0`. ๐Ÿ”– diff --git a/docs/fr/docs/advanced/events.md b/docs/fr/docs/advanced/events.md new file mode 100644 index 0000000000..6d0907a8bc --- /dev/null +++ b/docs/fr/docs/advanced/events.md @@ -0,0 +1,165 @@ +# ร‰vรฉnements de cycle de vie { #lifespan-events } + +Vous pouvez dรฉfinir une logique (du code) qui doit รชtre exรฉcutรฉe avant que l'application ne **dรฉmarre**. Cela signifie que ce code sera exรฉcutรฉ **une seule fois**, **avant** que l'application ne **commence ร  recevoir des requรชtes**. + +De la mรชme maniรจre, vous pouvez dรฉfinir une logique (du code) qui doit รชtre exรฉcutรฉe lorsque l'application **s'arrรชte**. Dans ce cas, ce code sera exรฉcutรฉ **une seule fois**, **aprรจs** avoir traitรฉ potentiellement **de nombreuses requรชtes**. + +Comme ce code est exรฉcutรฉ avant que l'application ne **commence** ร  recevoir des requรชtes, et juste aprรจs qu'elle **termine** de les traiter, il couvre tout le **cycle de vie** de l'application (le mot ยซ lifespan ยป va รชtre important dans un instant ๐Ÿ˜‰). + +Cela peut รชtre trรจs utile pour configurer des **ressources** dont vous avez besoin pour l'ensemble de l'application, qui sont **partagรฉes** entre les requรชtes, et/ou que vous devez **nettoyer** ensuite. Par exemple, un pool de connexions ร  une base de donnรฉes, ou le chargement d'un modรจle d'apprentissage automatique partagรฉ. + +## Cas d'utilisation { #use-case } + +Commenรงons par un exemple de **cas d'utilisation**, puis voyons comment le rรฉsoudre avec ceci. + +Imaginons que vous ayez des **modรจles d'apprentissage automatique** que vous souhaitez utiliser pour traiter des requรชtes. ๐Ÿค– + +Les mรชmes modรจles sont partagรฉs entre les requรชtes, ce n'est donc pas un modรจle par requรชte, ni un par utilisateur, ou quelque chose de similaire. + +Imaginons que le chargement du modรจle puisse **prendre pas mal de temps**, car il doit lire beaucoup de **donnรฉes depuis le disque**. Vous ne voulez donc pas le faire pour chaque requรชte. + +Vous pourriez le charger au niveau supรฉrieur du module/fichier, mais cela signifierait aussi qu'il **chargerait le modรจle** mรชme si vous exรฉcutez simplement un test automatisรฉ simple ; ce test serait alors **lent** car il devrait attendre le chargement du modรจle avant de pouvoir exรฉcuter une partie indรฉpendante du code. + +C'est ce que nous allons rรฉsoudre : chargeons le modรจle avant que les requรชtes ne soient traitรฉes, mais seulement juste avant que l'application ne commence ร  recevoir des requรชtes, pas pendant le chargement du code. + +## Cycle de vie { #lifespan } + +Vous pouvez dรฉfinir cette logique de *dรฉmarrage* et d'*arrรชt* en utilisant le paramรจtre `lifespan` de l'application `FastAPI`, et un ยซ gestionnaire de contexte ยป (je vais vous montrer ce que c'est dans un instant). + +Commenรงons par un exemple, puis voyons-le en dรฉtail. + +Nous crรฉons une fonction async `lifespan()` avec `yield` comme ceci : + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +Ici, nous simulons l'opรฉration de *dรฉmarrage* coรปteuse de chargement du modรจle en plaรงant la fonction (factice) du modรจle dans le dictionnaire avec les modรจles d'apprentissage automatique avant le `yield`. Ce code sera exรฉcutรฉ **avant** que l'application ne **commence ร  recevoir des requรชtes**, pendant le *dรฉmarrage*. + +Puis, juste aprรจs le `yield`, nous dรฉchargeons le modรจle. Ce code sera exรฉcutรฉ **aprรจs** que l'application **a fini de traiter les requรชtes**, juste avant l'*arrรชt*. Cela pourrait, par exemple, libรฉrer des ressources comme la mรฉmoire ou un GPU. + +/// tip | Astuce + +Lโ€™ยซ arrรชt ยป se produit lorsque vous **arrรชtez** l'application. + +Peut-รชtre devez-vous dรฉmarrer une nouvelle version, ou vous en avez simplement assez de l'exรฉcuter. ๐Ÿคท + +/// + +### Fonction de cycle de vie { #lifespan-function } + +La premiรจre chose ร  remarquer est que nous dรฉfinissons une fonction async avec `yield`. C'est trรจs similaire aux Dรฉpendances avec `yield`. + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +La premiรจre partie de la fonction, avant le `yield`, sera exรฉcutรฉe **avant** le dรฉmarrage de l'application. + +Et la partie aprรจs le `yield` sera exรฉcutรฉe **aprรจs** que l'application a terminรฉ. + +### Gestionnaire de contexte asynchrone { #async-context-manager } + +Si vous regardez, la fonction est dรฉcorรฉe avec `@asynccontextmanager`. + +Cela convertit la fonction en quelque chose appelรฉ un ยซ **gestionnaire de contexte asynchrone** ยป. + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Un **gestionnaire de contexte** en Python est quelque chose que vous pouvez utiliser dans une instruction `with`. Par exemple, `open()` peut รชtre utilisรฉ comme gestionnaire de contexte : + +```Python +with open("file.txt") as file: + file.read() +``` + +Dans les versions rรฉcentes de Python, il existe aussi un **gestionnaire de contexte asynchrone**. Vous l'utiliseriez avec `async with` : + +```Python +async with lifespan(app): + await do_stuff() +``` + +Quand vous crรฉez un gestionnaire de contexte ou un gestionnaire de contexte asynchrone comme ci-dessus, ce qu'il fait, c'est qu'avant d'entrer dans le bloc `with`, il exรฉcute le code avant le `yield`, et aprรจs รชtre sorti du bloc `with`, il exรฉcute le code aprรจs le `yield`. + +Dans notre exemple de code ci-dessus, nous ne l'utilisons pas directement, mais nous le transmettons ร  FastAPI pour qu'il l'utilise. + +Le paramรจtre `lifespan` de l'application `FastAPI` accepte un **gestionnaire de contexte asynchrone**, nous pouvons donc lui passer notre nouveau gestionnaire de contexte asynchrone `lifespan`. + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## ร‰vรฉnements alternatifs (dรฉprรฉciรฉ) { #alternative-events-deprecated } + +/// warning | Alertes + +La mรฉthode recommandรฉe pour gรฉrer le *dรฉmarrage* et l'*arrรชt* est d'utiliser le paramรจtre `lifespan` de l'application `FastAPI` comme dรฉcrit ci-dessus. Si vous fournissez un paramรจtre `lifespan`, les gestionnaires d'รฉvรฉnements `startup` et `shutdown` ne seront plus appelรฉs. C'est soit tout en `lifespan`, soit tout en รฉvรฉnements, pas les deux. + +Vous pouvez probablement passer cette partie. + +/// + +Il existe une autre maniรจre de dรฉfinir cette logique ร  exรฉcuter au *dรฉmarrage* et ร  l'*arrรชt*. + +Vous pouvez dรฉfinir des gestionnaires d'รฉvรฉnements (fonctions) qui doivent รชtre exรฉcutรฉs avant le dรฉmarrage de l'application, ou lorsque l'application s'arrรชte. + +Ces fonctions peuvent รชtre dรฉclarรฉes avec `async def` ou un `def` normal. + +### ร‰vรฉnement `startup` { #startup-event } + +Pour ajouter une fonction qui doit รชtre exรฉcutรฉe avant le dรฉmarrage de l'application, dรฉclarez-la avec l'รฉvรฉnement ยซ startup ยป : + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +Dans ce cas, la fonction gestionnaire de l'รฉvรฉnement `startup` initialisera la ยซ base de donnรฉes ยป des items (juste un `dict`) avec quelques valeurs. + +Vous pouvez ajouter plusieurs fonctions de gestion d'รฉvรฉnements. + +Et votre application ne commencera pas ร  recevoir des requรชtes avant que tous les gestionnaires de l'รฉvรฉnement `startup` aient terminรฉ. + +### ร‰vรฉnement `shutdown` { #shutdown-event } + +Pour ajouter une fonction qui doit รชtre exรฉcutรฉe lorsque l'application s'arrรชte, dรฉclarez-la avec l'รฉvรฉnement ยซ shutdown ยป : + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +Ici, la fonction gestionnaire de l'รฉvรฉnement `shutdown` รฉcrira une ligne de texte ยซ Application shutdown ยป dans un fichier `log.txt`. + +/// info + +Dans la fonction `open()`, le `mode="a"` signifie ยซ append ยป (ajouter) ; la ligne sera donc ajoutรฉe aprรจs ce qui se trouve dรฉjร  dans ce fichier, sans รฉcraser le contenu prรฉcรฉdent. + +/// + +/// tip | Astuce + +Notez que dans ce cas, nous utilisons une fonction Python standard `open()` qui interagit avec un fichier. + +Cela implique des E/S (input/output), qui nรฉcessitent ยซ d'attendre ยป que des choses soient รฉcrites sur le disque. + +Mais `open()` n'utilise pas `async` et `await`. + +Nous dรฉclarons donc la fonction gestionnaire d'รฉvรฉnement avec un `def` standard plutรดt qu'avec `async def`. + +/// + +### `startup` et `shutdown` ensemble { #startup-and-shutdown-together } + +Il y a de fortes chances que la logique de votre *dรฉmarrage* et de votre *arrรชt* soit liรฉe : vous pourriez vouloir dรฉmarrer quelque chose puis le terminer, acquรฉrir une ressource puis la libรฉrer, etc. + +Faire cela dans des fonctions sรฉparรฉes qui ne partagent pas de logique ni de variables est plus difficile, car vous devriez stocker des valeurs dans des variables globales ou recourir ร  des astuces similaires. + +Pour cette raison, il est dรฉsormais recommandรฉ d'utiliser plutรดt le `lifespan` comme expliquรฉ ci-dessus. + +## Dรฉtails techniques { #technical-details } + +Juste un dรฉtail technique pour les nerds curieux. ๐Ÿค“ + +Sous le capot, dans la spรฉcification technique ASGI, cela fait partie du protocole Lifespan, et il y dรฉfinit des รฉvรฉnements appelรฉs `startup` et `shutdown`. + +/// info + +Vous pouvez en lire plus sur les gestionnaires `lifespan` de Starlette dans la documentation ยซ Lifespan ยป de Starlette. + +Y compris comment gรฉrer l'รฉtat de cycle de vie qui peut รชtre utilisรฉ dans d'autres parties de votre code. + +/// + +## Sous-applications { #sub-applications } + +๐Ÿšจ Gardez ร  l'esprit que ces รฉvรฉnements de cycle de vie (dรฉmarrage et arrรชt) ne seront exรฉcutรฉs que pour l'application principale, pas pour [Sous-applications - Montages](sub-applications.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/advanced/generate-clients.md b/docs/fr/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..6f51ac7be9 --- /dev/null +++ b/docs/fr/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# Gรฉnรฉrer des SDK { #generating-sdks } + +Parce que **FastAPI** est basรฉ sur la spรฉcification **OpenAPI**, ses API peuvent รชtre dรฉcrites dans un format standard compris par de nombreux outils. + +Cela facilite la gรฉnรฉration de **documentation** ร  jour, de bibliothรจques clientes (**SDKs**) dans plusieurs langages, ainsi que de **tests** ou de **workflows dโ€™automatisation** qui restent synchronisรฉs avec votre code. + +Dans ce guide, vous apprendrez ร  gรฉnรฉrer un **SDK TypeScript** pour votre backend FastAPI. + +## Gรฉnรฉrateurs de SDK open source { #open-source-sdk-generators } + +Une option polyvalente est OpenAPI Generator, qui prend en charge **de nombreux langages de programmation** et peut gรฉnรฉrer des SDK ร  partir de votre spรฉcification OpenAPI. + +Pour les **clients TypeScript**, Hey API est une solution dรฉdiรฉe, offrant une expรฉrience optimisรฉe pour lโ€™รฉcosystรจme TypeScript. + +Vous pouvez dรฉcouvrir davantage de gรฉnรฉrateurs de SDK sur OpenAPI.Tools. + +/// tip | Astuce + +FastAPI gรฉnรจre automatiquement des spรฉcifications **OpenAPI 3.1**, donc tout outil que vous utilisez doit prendre en charge cette version. + +/// + +## Gรฉnรฉrateurs de SDK par les sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors } + +Cette section met en avant des solutions **soutenues par des fonds** et **par des entreprises** qui sponsorisent FastAPI. Ces produits offrent **des fonctionnalitรฉs supplรฉmentaires** et **des intรฉgrations** en plus de SDK de haute qualitรฉ gรฉnรฉrรฉs. + +En โœจ [**sponsorisant FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ, ces entreprises contribuent ร  garantir que le framework et son **รฉcosystรจme** restent sains et **durables**. + +Leur sponsoring dรฉmontre รฉgalement un fort engagement envers la **communautรฉ** FastAPI (vous), montrant quโ€™elles se soucient non seulement dโ€™offrir un **excellent service**, mais aussi de soutenir un **framework robuste et florissant**, FastAPI. ๐Ÿ™‡ + +Par exemple, vous pourriez essayer : + +* Speakeasy +* Stainless +* liblab + +Certaines de ces solutions peuvent aussi รชtre open source ou proposer des niveaux gratuits, afin que vous puissiez les essayer sans engagement financier. Dโ€™autres gรฉnรฉrateurs de SDK commerciaux existent et peuvent รชtre trouvรฉs en ligne. ๐Ÿค“ + +## Crรฉer un SDK TypeScript { #create-a-typescript-sdk } + +Commenรงons par une application FastAPI simple : + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +Remarquez que les *chemins d'accรจs* dรฉfinissent les modรจles quโ€™ils utilisent pour le payload de requรชte et le payload de rรฉponse, en utilisant les modรจles `Item` et `ResponseMessage`. + +### Documentation de lโ€™API { #api-docs } + +Si vous allez sur `/docs`, vous verrez quโ€™elle contient les **schรฉmas** pour les donnรฉes ร  envoyer dans les requรชtes et reรงues dans les rรฉponses : + + + +Vous voyez ces schรฉmas parce quโ€™ils ont รฉtรฉ dรฉclarรฉs avec les modรจles dans lโ€™application. + +Ces informations sont disponibles dans le **schรฉma OpenAPI** de lโ€™application, puis affichรฉes dans la documentation de lโ€™API. + +Ces mรชmes informations issues des modรจles, incluses dans OpenAPI, peuvent รชtre utilisรฉes pour **gรฉnรฉrer le code client**. + +### Hey API { #hey-api } + +Une fois que vous avez une application FastAPI avec les modรจles, vous pouvez utiliser Hey API pour gรฉnรฉrer un client TypeScript. Le moyen le plus rapide de le faire est via npx. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +Cela gรฉnรฉrera un SDK TypeScript dans `./src/client`. + +Vous pouvez apprendre ร  installer `@hey-api/openapi-ts` et lire ร  propos du rรฉsultat gรฉnรฉrรฉ sur leur site. + +### Utiliser le SDK { #using-the-sdk } + +Vous pouvez maintenant importer et utiliser le code client. Cela pourrait ressembler ร  ceci, remarquez que vous obtenez lโ€™autocomplรฉtion pour les mรฉthodes : + + + +Vous obtiendrez รฉgalement lโ€™autocomplรฉtion pour le payload ร  envoyer : + + + +/// tip | Astuce + +Remarquez lโ€™autocomplรฉtion pour `name` et `price`, qui a รฉtรฉ dรฉfinie dans lโ€™application FastAPI, dans le modรจle `Item`. + +/// + +Vous aurez des erreurs en ligne pour les donnรฉes que vous envoyez : + + + +Lโ€™objet de rรฉponse aura รฉgalement lโ€™autocomplรฉtion : + + + +## Application FastAPI avec des tags { #fastapi-app-with-tags } + +Dans de nombreux cas, votre application FastAPI sera plus grande, et vous utiliserez probablement des tags pour sรฉparer diffรฉrents groupes de *chemins d'accรจs*. + +Par exemple, vous pourriez avoir une section pour les **items** et une autre section pour les **users**, et elles pourraient รชtre sรฉparรฉes par des tags : + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### Gรฉnรฉrer un client TypeScript avec des tags { #generate-a-typescript-client-with-tags } + +Si vous gรฉnรฉrez un client pour une application FastAPI utilisant des tags, il sรฉparera normalement aussi le code client en fonction des tags. + +De cette faรงon, vous pourrez avoir les รฉlรฉments ordonnรฉs et correctement groupรฉs cรดtรฉ client : + + + +Dans ce cas, vous avez : + +* `ItemsService` +* `UsersService` + +### Noms des mรฉthodes du client { #client-method-names } + +ร€ lโ€™heure actuelle, les noms de mรฉthodes gรฉnรฉrรฉs comme `createItemItemsPost` ne sont pas trรจs propres : + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +... cโ€™est parce que le gรฉnรฉrateur de client utilise lโ€™**operation ID** interne OpenAPI pour chaque *chemin d'accรจs*. + +OpenAPI exige que chaque operation ID soit unique parmi tous les *chemins d'accรจs*, donc FastAPI utilise le **nom de la fonction**, le **chemin**, et la **mรฉthode/opรฉration HTTP** pour gรฉnรฉrer cet operation ID, car de cette faรงon il peut sโ€™assurer que les operation IDs sont uniques. + +Mais je vais vous montrer comment amรฉliorer cela ensuite. ๐Ÿค“ + +## IDs dโ€™opรฉration personnalisรฉs et meilleurs noms de mรฉthodes { #custom-operation-ids-and-better-method-names } + +Vous pouvez **modifier** la faรงon dont ces operation IDs sont **gรฉnรฉrรฉs** pour les simplifier et obtenir des **noms de mรฉthodes plus simples** dans les clients. + +Dans ce cas, vous devez vous assurer que chaque operation ID est **unique** dโ€™une autre maniรจre. + +Par exemple, vous pouvez vous assurer que chaque *chemin d'accรจs* a un tag, puis gรฉnรฉrer lโ€™operation ID ร  partir du **tag** et du **nom** du *chemin d'accรจs* (le nom de la fonction). + +### Fonction personnalisรฉe de gรฉnรฉration dโ€™ID unique { #custom-generate-unique-id-function } + +FastAPI utilise un **ID unique** pour chaque *chemin d'accรจs*, qui est utilisรฉ pour lโ€™**operation ID** et รฉgalement pour les noms des modรจles personnalisรฉs nรฉcessaires, pour les requรชtes ou les rรฉponses. + +Vous pouvez personnaliser cette fonction. Elle prend un `APIRoute` et retourne une chaรฎne. + +Par exemple, ici elle utilise le premier tag (vous nโ€™en aurez probablement quโ€™un) et le nom du *chemin d'accรจs* (le nom de la fonction). + +Vous pouvez ensuite passer cette fonction personnalisรฉe ร  **FastAPI** via le paramรจtre `generate_unique_id_function` : + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### Gรฉnรฉrer un client TypeScript avec des IDs dโ€™opรฉration personnalisรฉs { #generate-a-typescript-client-with-custom-operation-ids } + +Maintenant, si vous rรฉgรฉnรฉrez le client, vous verrez quโ€™il possรจde des noms de mรฉthodes amรฉliorรฉs : + + + +Comme vous le voyez, les noms de mรฉthodes contiennent maintenant le tag puis le nom de la fonction ; ils nโ€™incluent plus dโ€™informations provenant du chemin dโ€™URL et de lโ€™opรฉration HTTP. + +### Prรฉtraiter la spรฉcification OpenAPI pour le gรฉnรฉrateur de client { #preprocess-the-openapi-specification-for-the-client-generator } + +Le code gรฉnรฉrรฉ contient encore des **informations dupliquรฉes**. + +Nous savons dรฉjร  que cette mรฉthode est liรฉe aux **items** parce que ce mot figure dans `ItemsService` (issu du tag), mais nous avons encore le nom du tag prรฉfixรฉ dans le nom de la mรฉthode. ๐Ÿ˜• + +Nous voudrons probablement le conserver pour OpenAPI en gรฉnรฉral, car cela garantira que les operation IDs sont **uniques**. + +Mais pour le client gรฉnรฉrรฉ, nous pourrions **modifier** les operation IDs dโ€™OpenAPI juste avant de gรฉnรฉrer les clients, simplement pour rendre ces noms de mรฉthodes plus agrรฉables et **plus clairs**. + +Nous pourrions tรฉlรฉcharger le JSON OpenAPI dans un fichier `openapi.json` puis **supprimer ce tag prรฉfixรฉ** avec un script comme celui-ci : + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +Avec cela, les operation IDs seraient renommรฉs de `items-get_items` en simplement `get_items`, de sorte que le gรฉnรฉrateur de client puisse produire des noms de mรฉthodes plus simples. + +### Gรฉnรฉrer un client TypeScript avec lโ€™OpenAPI prรฉtraitรฉ { #generate-a-typescript-client-with-the-preprocessed-openapi } + +Puisque le rรฉsultat final se trouve maintenant dans un fichier `openapi.json`, vous devez mettre ร  jour lโ€™emplacement dโ€™entrรฉe : + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +Aprรจs avoir gรฉnรฉrรฉ le nouveau client, vous aurez dรฉsormais des **noms de mรฉthodes propres**, avec toute lโ€™**autocomplรฉtion**, les **erreurs en ligne**, etc. : + + + +## Avantages { #benefits } + +En utilisant les clients gรฉnรฉrรฉs automatiquement, vous obtiendrez de lโ€™**autocomplรฉtion** pour : + +* Mรฉthodes. +* Payloads de requรชte dans le corps, paramรจtres de requรชte, etc. +* Payloads de rรฉponse. + +Vous auriez รฉgalement des **erreurs en ligne** pour tout. + +Et chaque fois que vous mettez ร  jour le code du backend et **rรฉgรฉnรฉrez** le frontend, il inclura les nouveaux *chemins d'accรจs* disponibles en tant que mรฉthodes, supprimera les anciens, et tout autre changement sera reflรฉtรฉ dans le code gรฉnรฉrรฉ. ๐Ÿค“ + +Cela signifie aussi que si quelque chose change, cela sera **reflรฉtรฉ** automatiquement dans le code client. Et si vous **bรขtissez** le client, il รฉchouera en cas de **discordance** dans les donnรฉes utilisรฉes. + +Ainsi, vous **dรฉtecterez de nombreuses erreurs** trรจs tรดt dans le cycle de dรฉveloppement au lieu dโ€™attendre quโ€™elles apparaissent pour vos utilisateurs finaux en production puis de tenter de dรฉboguer lโ€™origine du problรจme. โœจ diff --git a/docs/fr/docs/advanced/middleware.md b/docs/fr/docs/advanced/middleware.md new file mode 100644 index 0000000000..934c910411 --- /dev/null +++ b/docs/fr/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# Utiliser des middlewares avancรฉs { #advanced-middleware } + +Dans le tutoriel principal, vous avez vu comment ajouter des [middlewares personnalisรฉs](../tutorial/middleware.md){.internal-link target=_blank} ร  votre application. + +Vous avez รฉgalement vu comment gรฉrer [CORS avec le `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}. + +Dans cette section, nous allons voir comment utiliser d'autres middlewares. + +## Ajouter des middlewares ASGI { #adding-asgi-middlewares } + +Comme **FastAPI** est basรฉ sur Starlette et implรฉmente la spรฉcification ASGI, vous pouvez utiliser n'importe quel middleware ASGI. + +Un middleware n'a pas besoin d'รชtre conรงu pour FastAPI ou Starlette pour fonctionner, tant qu'il suit la spรฉcification ASGI. + +En gรฉnรฉral, les middlewares ASGI sont des classes qui s'attendent ร  recevoir une application ASGI en premier argument. + +Ainsi, dans la documentation de middlewares ASGI tiers, on vous indiquera probablement de faire quelque chose commeย : + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +Mais FastAPI (en fait Starlette) fournit une maniรจre plus simple de le faire, qui garantit que les middlewares internes gรจrent les erreurs serveur et que les gestionnaires d'exceptions personnalisรฉs fonctionnent correctement. + +Pour cela, vous utilisez `app.add_middleware()` (comme dans l'exemple pour CORS). + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` reรงoit une classe de middleware en premier argument, ainsi que tout argument supplรฉmentaire ร  transmettre au middleware. + +## Utiliser les middlewares intรฉgrรฉs { #integrated-middlewares } + +**FastAPI** inclut plusieurs middlewares pour des cas d'usage courants ; voyons comment les utiliser. + +/// note | Dรฉtails techniques + +Pour les prochains exemples, vous pourriez aussi utiliser `from starlette.middleware.something import SomethingMiddleware`. + +**FastAPI** fournit plusieurs middlewares dans `fastapi.middleware` simplement pour vous faciliter la vie, en tant que dรฉveloppeur. Mais la plupart des middlewares disponibles viennent directement de Starlette. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +Impose que toutes les requรชtes entrantes soient soit `https`, soit `wss`. + +Toute requรชte entrante en `http` ou `ws` sera redirigรฉe vers le schรฉma sรฉcurisรฉ correspondant. + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +Impose que toutes les requรชtes entrantes aient un en-tรชte `Host` correctement dรฉfini, afin de se prรฉmunir contre les attaques de type HTTP Host Header. + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +Les arguments suivants sont pris en chargeย : + +- `allowed_hosts` - Une liste de noms de domaine autorisรฉs comme noms d'hรดte. Les domaines gรฉnรฉriques tels que `*.example.com` sont pris en charge pour faire correspondre les sous-domaines. Pour autoriser n'importe quel nom d'hรดte, utilisez `allowed_hosts=["*"]` ou omettez le middleware. +- `www_redirect` - Si dรฉfini ร  `True`, les requรชtes vers les versions sans www des hรดtes autorisรฉs seront redirigรฉes vers leurs รฉquivalents avec www. Valeur par dรฉfautย : `True`. + +Si une requรชte entrante n'est pas valide, une rรฉponse `400` sera envoyรฉe. + +## `GZipMiddleware` { #gzipmiddleware } + +Gรจre les rรฉponses GZip pour toute requรชte qui inclut ยซ gzip ยป dans l'en-tรชte `Accept-Encoding`. + +Le middleware gรฉrera les rรฉponses standard et en streaming. + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +Les arguments suivants sont pris en chargeย : + +- `minimum_size` - Ne pas compresser en GZip les rรฉponses dont la taille est infรฉrieure ร  ce minimum en octets. Valeur par dรฉfautย : `500`. +- `compresslevel` - Utilisรฉ pendant la compression GZip. Entier compris entre 1 et 9. Valeur par dรฉfautย : `9`. Une valeur plus faible entraรฎne une compression plus rapide mais des fichiers plus volumineux, tandis qu'une valeur plus รฉlevรฉe entraรฎne une compression plus lente mais des fichiers plus petits. + +## Autres middlewares { #other-middlewares } + +Il existe de nombreux autres middlewares ASGI. + +Par exempleย : + +- Le `ProxyHeadersMiddleware` d'Uvicorn +- MessagePack + +Pour voir d'autres middlewares disponibles, consultez la documentation des middlewares de Starlette et la liste ASGI Awesome. diff --git a/docs/fr/docs/advanced/openapi-callbacks.md b/docs/fr/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..669d9447a2 --- /dev/null +++ b/docs/fr/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# Callbacks OpenAPI { #openapi-callbacks } + +Vous pourriez crรฉer une API avec un *chemin d'accรจs* qui dรฉclenche une requรชte vers une *API externe* crรฉรฉe par quelqu'un d'autre (probablement la mรชme personne dรฉveloppeuse qui utiliserait votre API). + +Le processus qui se produit lorsque votre application API appelle lโ€™*API externe* sโ€™appelle un ยซ callback ยป. Parce que le logiciel รฉcrit par la personne dรฉveloppeuse externe envoie une requรชte ร  votre API puis votre API ยซ rappelle ยป, en envoyant une requรชte ร  une *API externe* (probablement crรฉรฉe par la mรชme personne dรฉveloppeuse). + +Dans ce cas, vous pourriez vouloir documenter ร  quoi cette API externe devrait ressembler. Quel *chemin d'accรจs* elle devrait avoir, quel corps elle devrait attendre, quelle rรฉponse elle devrait renvoyer, etc. + +## Une application avec des callbacks { #an-app-with-callbacks } + +Voyons tout cela avec un exemple. + +Imaginez que vous dรฉveloppiez une application qui permet de crรฉer des factures. + +Ces factures auront un `id`, un `title` (facultatif), un `customer` et un `total`. + +Lโ€™utilisateur de votre API (une personne dรฉveloppeuse externe) crรฉera une facture dans votre API avec une requรชte POST. + +Ensuite votre API va (imaginons) : + +* Envoyer la facture ร  un client de la personne dรฉveloppeuse externe. +* Encaisser lโ€™argent. +* Renvoyer une notification ร  lโ€™utilisateur de lโ€™API (la personne dรฉveloppeuse externe). + * Cela sera fait en envoyant une requรชte POST (depuis *votre API*) vers une *API externe* fournie par cette personne dรฉveloppeuse externe (cโ€™est le ยซ callback ยป). + +## Lโ€™application **FastAPI** normale { #the-normal-fastapi-app } + +Voyons dโ€™abord ร  quoi ressemble lโ€™application API normale avant dโ€™ajouter le callback. + +Elle aura un *chemin d'accรจs* qui recevra un corps `Invoice`, et un paramรจtre de requรชte `callback_url` qui contiendra lโ€™URL pour le callback. + +Cette partie est assez normale, la plupart du code vous est probablement dรฉjร  familier : + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | Astuce + +Le paramรจtre de requรชte `callback_url` utilise un type Pydantic Url. + +/// + +La seule nouveautรฉ est `callbacks=invoices_callback_router.routes` comme argument du *dรฉcorateur de chemin d'accรจs*. Nous allons voir ce que cโ€™est ensuite. + +## Documenter le callback { #documenting-the-callback } + +Le code rรฉel du callback dรฉpendra fortement de votre application API. + +Et il variera probablement beaucoup dโ€™une application ร  lโ€™autre. + +Cela pourrait รชtre seulement une ou deux lignes de code, commeย : + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +Mais la partie la plus importante du callback est sans doute de vous assurer que lโ€™utilisateur de votre API (la personne dรฉveloppeuse externe) implรฉmente correctement lโ€™*API externe*, conformรฉment aux donnรฉes que *votre API* va envoyer dans le corps de la requรชte du callback, etc. + +Ainsi, ce que nous allons faire ensuite, cโ€™est ajouter le code pour documenter ร  quoi cette *API externe* devrait ressembler pour recevoir le callback de *votre API*. + +Cette documentation apparaรฎtra dans Swagger UI ร  `/docs` dans votre API, et permettra aux personnes dรฉveloppeuses externes de savoir comment construire lโ€™*API externe*. + +Cet exemple nโ€™implรฉmente pas le callback lui-mรชme (qui pourrait รชtre une simple ligne de code), uniquement la partie documentation. + +/// tip | Astuce + +Le callback rรฉel nโ€™est quโ€™une requรชte HTTP. + +En implรฉmentant vous-mรชme le callback, vous pourriez utiliser quelque chose comme HTTPX ou Requests. + +/// + +## ร‰crire le code de documentation du callback { #write-the-callback-documentation-code } + +Ce code ne sera pas exรฉcutรฉ dans votre application, nous en avons seulement besoin pour *documenter* ร  quoi devrait ressembler cette *API externe*. + +Mais vous savez dรฉjร  comment crรฉer facilement une documentation automatique pour une API avec **FastAPI**. + +Nous allons donc utiliser ce mรชme savoir pour documenter ร  quoi lโ€™*API externe* devrait ressembler ... en crรฉant le(s) *chemin(s) d'accรจs* que lโ€™API externe devrait implรฉmenter (ceux que votre API appellera). + +/// tip | Astuce + +Lorsque vous รฉcrivez le code pour documenter un callback, il peut รชtre utile dโ€™imaginer que vous รชtes cette *personne dรฉveloppeuse externe*. Et que vous implรฉmentez actuellement lโ€™*API externe*, pas *votre API*. + +Adopter temporairement ce point de vue (celui de la *personne dรฉveloppeuse externe*) peut vous aider ร  trouver plus รฉvident oรน placer les paramรจtres, le modรจle Pydantic pour le corps, pour la rรฉponse, etc., pour cette *API externe*. + +/// + +### Crรฉer un `APIRouter` de callback { #create-a-callback-apirouter } + +Commencez par crรฉer un nouveau `APIRouter` qui contiendra un ou plusieurs callbacks. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Crรฉer le *chemin d'accรจs* du callback { #create-the-callback-path-operation } + +Pour crรฉer le *chemin d'accรจs* du callback, utilisez le mรชme `APIRouter` que vous avez crรฉรฉ ci-dessus. + +Il devrait ressembler exactement ร  un *chemin d'accรจs* FastAPI normalย : + +* Il devrait probablement dรฉclarer le corps quโ€™il doit recevoir, par exemple `body: InvoiceEvent`. +* Et il pourrait aussi dรฉclarer la rรฉponse quโ€™il doit renvoyer, par exemple `response_model=InvoiceEventReceived`. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +Il y a 2 principales diffรฉrences par rapport ร  un *chemin d'accรจs* normalย : + +* Il nโ€™a pas besoin dโ€™avoir de code rรฉel, car votre application nโ€™appellera jamais ce code. Il sert uniquement ร  documenter lโ€™*API externe*. La fonction peut donc simplement contenir `pass`. +* Le *chemin* peut contenir une expression OpenAPIย 3 (voir plus bas) oรน il peut utiliser des variables avec des paramรจtres et des parties de la requรชte originale envoyรฉe ร  *votre API*. + +### Lโ€™expression du chemin de callback { #the-callback-path-expression } + +Le *chemin* du callback peut contenir une expression OpenAPIย 3 qui peut inclure des parties de la requรชte originale envoyรฉe ร  *votre API*. + +Dans ce cas, cโ€™est la `str`ย : + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +Ainsi, si lโ€™utilisateur de votre API (la personne dรฉveloppeuse externe) envoie une requรชte ร  *votre API* versย : + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +avec un corps JSONย : + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +alors *votre API* traitera la facture et, ร  un moment ultรฉrieur, enverra une requรชte de callback ร  `callback_url` (lโ€™*API externe*)ย : + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +avec un corps JSON contenant quelque chose commeย : + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +et elle sโ€™attendra ร  une rรฉponse de cette *API externe* avec un corps JSON commeย : + +```JSON +{ + "ok": true +} +``` + +/// tip | Astuce + +Remarquez que lโ€™URL de callback utilisรฉe contient lโ€™URL reรงue en paramรจtre de requรชte dans `callback_url` (`https://www.external.org/events`) et aussi lโ€™`id` de la facture ร  lโ€™intรฉrieur du corps JSON (`2expen51ve`). + +/// + +### Ajouter le routeur de callback { #add-the-callback-router } + +ร€ ce stade, vous avez le(s) *chemin(s) d'accรจs de callback* nรฉcessaire(s) (celui/ceux que la *personne dรฉveloppeuse externe* doit implรฉmenter dans lโ€™*API externe*) dans le routeur de callback que vous avez crรฉรฉ ci-dessus. + +Utilisez maintenant le paramรจtre `callbacks` dans *le dรฉcorateur de chemin d'accรจs de votre API* pour passer lโ€™attribut `.routes` (qui est en fait juste une `list` de routes/*chemins d'accรจs*) depuis ce routeur de callbackย : + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | Astuce + +Remarquez que vous ne passez pas le routeur lui-mรชme (`invoices_callback_router`) ร  `callback=`, mais lโ€™attribut `.routes`, comme dans `invoices_callback_router.routes`. + +/// + +### Vรฉrifier la documentation { #check-the-docs } + +Vous pouvez maintenant dรฉmarrer votre application et aller sur http://127.0.0.1:8000/docs. + +Vous verrez votre documentation incluant une section ยซ Callbacks ยป pour votre *chemin d'accรจs* qui montre ร  quoi lโ€™*API externe* devrait ressemblerย : + + diff --git a/docs/fr/docs/advanced/openapi-webhooks.md b/docs/fr/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..21b6f5f00c --- /dev/null +++ b/docs/fr/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# Webhooks OpenAPI { #openapi-webhooks } + +Il existe des cas oรน vous voulez informer les utilisateurs de votre API que votre application peut appeler leur application (en envoyant une requรชte) avec des donnรฉes, gรฉnรฉralement pour notifier un type d'รฉvรฉnement. + +Cela signifie qu'au lieu du processus habituel oรน vos utilisateurs envoient des requรชtes ร  votre API, c'est votre API (ou votre application) qui peut envoyer des requรชtes vers leur systรจme (vers leur API, leur application). + +On appelle gรฉnรฉralement cela un webhook. + +## ร‰tapes des webhooks { #webhooks-steps } + +Le processus consiste gรฉnรฉralement ร  dรฉfinir dans votre code le message que vous enverrez, c'est-ร -dire le corps de la requรชte. + +Vous dรฉfinissez รฉgalement, d'une maniรจre ou d'une autre, ร  quels moments votre application enverra ces requรชtes ou รฉvรฉnements. + +Et vos utilisateurs dรฉfinissent aussi, d'une maniรจre ou d'une autre (par exemple dans un tableau de bord Web), l'URL ร  laquelle votre application doit envoyer ces requรชtes. + +Toute la logique de gestion des URL des webhooks et le code qui envoie effectivement ces requรชtes vous incombent. Vous l'implรฉmentez comme vous le souhaitez dans votre propre code. + +## Documenter des webhooks avec FastAPI et OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } + +Avec FastAPI, en utilisant OpenAPI, vous pouvez dรฉfinir les noms de ces webhooks, les types d'opรฉrations HTTP que votre application peut envoyer (par exemple `POST`, `PUT`, etc.) et les corps des requรชtes que votre application enverra. + +Cela peut grandement faciliter la tรขche de vos utilisateurs pour implรฉmenter leurs API afin de recevoir vos requรชtes de webhook ; ils pourront mรชme peut-รชtre gรฉnรฉrer automatiquement une partie de leur propre code d'API. + +/// info + +Les webhooks sont disponibles dans OpenAPI 3.1.0 et versions ultรฉrieures, pris en charge par FastAPI `0.99.0` et versions ultรฉrieures. + +/// + +## Crรฉer une application avec des webhooks { #an-app-with-webhooks } + +Lorsque vous crรฉez une application FastAPI, il existe un attribut `webhooks` que vous pouvez utiliser pour dรฉfinir des webhooks, de la mรชme maniรจre que vous dรฉfiniriez des chemins d'accรจs, par exemple avec `@app.webhooks.post()`. + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +Les webhooks que vous dรฉfinissez apparaรฎtront dans le schรฉma **OpenAPI** et dans l'interface de **documentation** automatique. + +/// info + +L'objet `app.webhooks` est en fait simplement un `APIRouter`, le mรชme type que vous utiliseriez pour structurer votre application en plusieurs fichiers. + +/// + +Notez qu'avec les webhooks, vous ne dรฉclarez pas rรฉellement un chemin (comme `/items/`), le texte que vous y passez est simplement un identifiant du webhook (le nom de l'รฉvรฉnement). Par exemple, dans `@app.webhooks.post("new-subscription")`, le nom du webhook est `new-subscription`. + +C'est parce qu'on s'attend ร  ce que vos utilisateurs dรฉfinissent, par un autre moyen (par exemple un tableau de bord Web), le vรฉritable chemin d'URL oรน ils souhaitent recevoir la requรชte de webhook. + +### Consulter la documentation { #check-the-docs } + +Vous pouvez maintenant dรฉmarrer votre application et aller sur http://127.0.0.1:8000/docs. + +Vous verrez que votre documentation contient les chemins d'accรจs habituels et dรฉsormais aussi des webhooks : + + diff --git a/docs/fr/docs/advanced/path-operation-advanced-configuration.md b/docs/fr/docs/advanced/path-operation-advanced-configuration.md index fc88f33633..b482f97ccc 100644 --- a/docs/fr/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/fr/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ Vous pouvez dรฉfinir lโ€™OpenAPI `operationId` ร  utiliser dans votre chemin d Vous devez vous assurer quโ€™il est unique pour chaque opรฉration. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### Utiliser le nom de la fonction de chemin dโ€™accรจs comme operationId { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, Vous devez le faire aprรจs avoir ajoutรฉ tous vos chemins dโ€™accรจs. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | Astuce @@ -40,7 +40,7 @@ Mรชme si elles se trouvent dans des modules diffรฉrents (fichiers Python). Pour exclure un chemin dโ€™accรจs du schรฉma OpenAPI gรฉnรฉrรฉ (et donc des systรจmes de documentation automatiques), utilisez le paramรจtre `include_in_schema` et dรฉfinissez-le ร  `False` : -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## Description avancรฉe depuis la docstring { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ Vous pouvez รฉtendre le schรฉma OpenAPI pour un chemin dโ€™accรจs en utilisant l Cet `openapi_extra` peut รชtre utile, par exemple, pour dรฉclarer des [Extensions OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) : -{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} Si vous ouvrez la documentation automatique de lโ€™API, votre extension apparaรฎtra en bas du chemin dโ€™accรจs spรฉcifique. @@ -139,9 +139,9 @@ Par exemple, vous pourriez dรฉcider de lire et de valider la requรชte avec votre Vous pourriez le faire avec `openapi_extra` : -{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} -Dans cet exemple, nous nโ€™avons dรฉclarรฉ aucun modรจle Pydantic. En fait, le corps de la requรชte nโ€™est mรชme pas parsรฉ en JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargรฉe de lโ€™analyser dโ€™une maniรจre ou dโ€™une autre. +Dans cet exemple, nous nโ€™avons dรฉclarรฉ aucun modรจle Pydantic. En fait, le corps de la requรชte nโ€™est mรชme pas parsรฉ en JSON, il est lu directement en tant que `bytes`, et la fonction `magic_data_reader()` serait chargรฉe de lโ€™analyser dโ€™une maniรจre ou dโ€™une autre. Nรฉanmoins, nous pouvons dรฉclarer le schรฉma attendu pour le corps de la requรชte. @@ -153,7 +153,7 @@ Et vous pourriez le faire mรชme si le type de donnรฉes dans la requรชte nโ€™est Par exemple, dans cette application nous nโ€™utilisons pas la fonctionnalitรฉ intรฉgrรฉe de FastAPI pour extraire le JSON Schema des modรจles Pydantic ni la validation automatique pour le JSON. En fait, nous dรฉclarons le type de contenu de la requรชte comme YAML, pas JSON : -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} Nรฉanmoins, bien que nous nโ€™utilisions pas la fonctionnalitรฉ intรฉgrรฉe par dรฉfaut, nous utilisons toujours un modรจle Pydantic pour gรฉnรฉrer manuellement le JSON Schema pour les donnรฉes que nous souhaitons recevoir en YAML. @@ -161,7 +161,7 @@ Ensuite, nous utilisons directement la requรชte et extrayons le corps en tant qu Ensuite, dans notre code, nous analysons directement ce contenu YAML, puis nous utilisons ร  nouveau le mรชme modรจle Pydantic pour valider le contenu YAML : -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} /// tip | Astuce diff --git a/docs/fr/docs/advanced/response-change-status-code.md b/docs/fr/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000..d08e870995 --- /dev/null +++ b/docs/fr/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Rรฉponse - Modifier le code d'รฉtat { #response-change-status-code } + +Vous avez probablement dรฉjร  lu que vous pouvez dรฉfinir un [Code d'รฉtat de la rรฉponse](../tutorial/response-status-code.md){.internal-link target=_blank} par dรฉfaut. + +Mais dans certains cas, vous devez renvoyer un code d'รฉtat diffรฉrent de celui par dรฉfaut. + +## Cas d'utilisation { #use-case } + +Par exemple, imaginez que vous vouliez renvoyer par dรฉfaut un code d'รฉtat HTTP ยซ OK ยป `200`. + +Mais si les donnรฉes n'existent pas, vous voulez les crรฉer et renvoyer un code d'รฉtat HTTP ยซ CREATED ยป `201`. + +Mais vous souhaitez toujours pouvoir filtrer et convertir les donnรฉes que vous renvoyez avec un `response_model`. + +Pour ces cas, vous pouvez utiliser un paramรจtre `Response`. + +## Utiliser un paramรจtre `Response` { #use-a-response-parameter } + +Vous pouvez dรฉclarer un paramรจtre de type `Response` dans votre fonction de chemin d'accรจs (comme vous pouvez le faire pour les cookies et les en-tรชtes). + +Vous pouvez ensuite dรฉfinir le `status_code` dans cet objet de rรฉponse *temporaire*. + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +Vous pouvez ensuite renvoyer n'importe quel objet nรฉcessaire, comme d'habitude (un `dict`, un modรจle de base de donnรฉes, etc.). + +Et si vous avez dรฉclarรฉ un `response_model`, il sera toujours utilisรฉ pour filtrer et convertir l'objet que vous avez renvoyรฉ. + +**FastAPI** utilisera cette rรฉponse *temporaire* pour extraire le code d'รฉtat (ainsi que les cookies et les en-tรชtes), et les placera dans la rรฉponse finale qui contient la valeur que vous avez renvoyรฉe, filtrรฉe par tout `response_model`. + +Vous pouvez รฉgalement dรฉclarer le paramรจtre `Response` dans des dรฉpendances et y dรฉfinir le code d'รฉtat. Mais gardez ร  l'esprit que la derniรจre valeur dรฉfinie prรฉvaut. diff --git a/docs/fr/docs/advanced/response-cookies.md b/docs/fr/docs/advanced/response-cookies.md new file mode 100644 index 0000000000..d3e51f3317 --- /dev/null +++ b/docs/fr/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# Cookies de rรฉponse { #response-cookies } + +## Utiliser un paramรจtre `Response` { #use-a-response-parameter } + +Vous pouvez dรฉclarer un paramรจtre de type `Response` dans votre fonction de chemin d'accรจs. + +Vous pouvez ensuite dรฉfinir des cookies dans cet objet de rรฉponse *temporaire*. + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +Vous pouvez ensuite renvoyer n'importe quel objet dont vous avez besoin, comme d'habitude (un `dict`, un modรจle de base de donnรฉes, etc.). + +Et si vous avez dรฉclarรฉ un `response_model`, il sera toujours utilisรฉ pour filtrer et convertir l'objet que vous avez renvoyรฉ. + +**FastAPI** utilisera cette rรฉponse *temporaire* pour extraire les cookies (ainsi que les en-tรชtes et le code d'รฉtat), et les placera dans la rรฉponse finale qui contient la valeur que vous avez renvoyรฉe, filtrรฉe par tout `response_model`. + +Vous pouvez รฉgalement dรฉclarer le paramรจtre `Response` dans des dรฉpendances, et y dรฉfinir des cookies (et des en-tรชtes). + +## Renvoyer une `Response` directement { #return-a-response-directly } + +Vous pouvez รฉgalement crรฉer des cookies en renvoyant une `Response` directement dans votre code. + +Pour ce faire, vous pouvez crรฉer une rรฉponse comme dรฉcrit dans [Renvoyer une Response directement](response-directly.md){.internal-link target=_blank}. + +Dรฉfinissez ensuite des cookies dessus, puis renvoyez-la : + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | Astuce + +Gardez ร  l'esprit que si vous renvoyez une rรฉponse directement au lieu d'utiliser le paramรจtre `Response`, FastAPI la renverra telle quelle. + +Vous devez donc vous assurer que vos donnรฉes sont du type correct. Par exemple, qu'elles sont compatibles avec JSON si vous renvoyez une `JSONResponse`. + +Et รฉgalement que vous n'envoyez pas de donnรฉes qui auraient dรป รชtre filtrรฉes par un `response_model`. + +/// + +### En savoir plus { #more-info } + +/// note | Dรฉtails techniques + +Vous pouvez รฉgalement utiliser `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`. + +**FastAPI** fournit les mรชmes `starlette.responses` que `fastapi.responses` simplement pour votre commoditรฉ, en tant que dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. + +Et comme `Response` peut รชtre utilisรฉ frรฉquemment pour dรฉfinir des en-tรชtes et des cookies, **FastAPI** la met รฉgalement ร  disposition via `fastapi.Response`. + +/// + +Pour voir tous les paramรจtres et options disponibles, consultez la documentation de Starlette. diff --git a/docs/fr/docs/advanced/response-directly.md b/docs/fr/docs/advanced/response-directly.md index f35c39c06f..4a49518640 100644 --- a/docs/fr/docs/advanced/response-directly.md +++ b/docs/fr/docs/advanced/response-directly.md @@ -22,7 +22,7 @@ En fait, vous pouvez retourner n'importe quelle `Response` ou n'importe quelle s Et quand vous retournez une `Response`, **FastAPI** la transmet directement. -Elle ne fera aucune conversion de donnรฉes avec les modรจles Pydantic, elle ne convertira pas le contenu en un type quelconque. +Elle ne fera aucune conversion de donnรฉes avec les modรจles Pydantic, elle ne convertira pas le contenu en un type quelconque, etc. Cela vous donne beaucoup de flexibilitรฉ. Vous pouvez retourner n'importe quel type de donnรฉes, surcharger n'importe quelle dรฉclaration ou validation de donnรฉes, etc. @@ -54,7 +54,7 @@ Disons que vous voulez retourner une rรฉponse en utilisant le prรฉfixe `X-`. + +Mais si vous avez des en-tรชtes personnalisรฉs que vous voulez qu'un client dans un navigateur puisse voir, vous devez les ajouter ร  vos configurations CORS (en savoir plus dans [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), en utilisant le paramรจtre `expose_headers` documentรฉ dans la documentation CORS de Starlette. diff --git a/docs/fr/docs/advanced/security/http-basic-auth.md b/docs/fr/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..a8742ce7c2 --- /dev/null +++ b/docs/fr/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# Authentification HTTP Basic { #http-basic-auth } + +Pour les cas les plus simples, vous pouvez utiliser l'authentification HTTP Basic. + +Avec l'authentification HTTP Basic, l'application attend un en-tรชte contenant un nom d'utilisateur et un mot de passe. + +Si elle ne le reรงoit pas, elle renvoie une erreur HTTP 401 ยซ Unauthorized ยป. + +Et elle renvoie un en-tรชte `WWW-Authenticate` avec la valeur `Basic`, et un paramรจtre optionnel `realm`. + +Cela indique au navigateur d'afficher l'invite intรฉgrรฉe pour saisir un nom d'utilisateur et un mot de passe. + +Ensuite, lorsque vous saisissez ce nom d'utilisateur et ce mot de passe, le navigateur les envoie automatiquement dans l'en-tรชte. + +## Authentification HTTP Basic simple { #simple-http-basic-auth } + +- Importer `HTTPBasic` et `HTTPBasicCredentials`. +- Crรฉer un ยซ schรฉma de sรฉcuritรฉ ยป en utilisant `HTTPBasic`. +- Utiliser ce `security` avec une dรฉpendance dans votre chemin d'accรจs. +- Cela renvoie un objet de type `HTTPBasicCredentials` : + - Il contient le `username` et le `password` envoyรฉs. + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +Lorsque vous essayez d'ouvrir l'URL pour la premiรจre fois (ou cliquez sur le bouton ยซ Execute ยป dans les documents) le navigateur vous demandera votre nom d'utilisateur et votre mot de passe : + + + +## Vรฉrifier le nom d'utilisateur { #check-the-username } + +Voici un exemple plus complet. + +Utilisez une dรฉpendance pour vรฉrifier si le nom d'utilisateur et le mot de passe sont corrects. + +Pour cela, utilisez le module standard Python `secrets` pour vรฉrifier le nom d'utilisateur et le mot de passe. + +`secrets.compare_digest()` doit recevoir des `bytes` ou une `str` ne contenant que des caractรจres ASCII (ceux de l'anglais), ce qui signifie qu'elle ne fonctionnerait pas avec des caractรจres comme `รก`, comme dans `Sebastiรกn`. + +Pour gรฉrer cela, nous convertissons d'abord `username` et `password` en `bytes` en les encodant en UTF-8. + +Nous pouvons ensuite utiliser `secrets.compare_digest()` pour vรฉrifier que `credentials.username` est ยซ stanleyjobson ยป et que `credentials.password` est ยซ swordfish ยป. + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +Cela serait รฉquivalent ร  : + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Renvoyer une erreur + ... +``` + +Mais en utilisant `secrets.compare_digest()`, cela sera sรฉcurisรฉ contre un type d'attaques appelรฉ ยซ attaques par chronomรฉtrage ยป. + +### Attaques par chronomรฉtrage { #timing-attacks } + +Mais qu'est-ce qu'une ยซ attaque par chronomรฉtrage ยป ? + +Imaginons que des attaquants essaient de deviner le nom d'utilisateur et le mot de passe. + +Ils envoient alors une requรชte avec un nom d'utilisateur `johndoe` et un mot de passe `love123`. + +Le code Python de votre application serait alors รฉquivalent ร  quelque chose comme : + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Mais au moment oรน Python compare le premier `j` de `johndoe` au premier `s` de `stanleyjobson`, il retournera `False`, car il sait dรฉjร  que ces deux chaรฎnes ne sont pas identiques, en se disant qu'ยซ il n'est pas nรฉcessaire de gaspiller plus de calcul pour comparer le reste des lettres ยป. Et votre application dira ยซ Nom d'utilisateur ou mot de passe incorrect ยป. + +Mais ensuite, les attaquants essaient avec le nom d'utilisateur `stanleyjobsox` et le mot de passe `love123`. + +Et le code de votre application fait quelque chose comme : + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python devra comparer tout `stanleyjobso` dans `stanleyjobsox` et `stanleyjobson` avant de rรฉaliser que les deux chaรฎnes ne sont pas identiques. Cela prendra donc quelques microsecondes supplรฉmentaires pour rรฉpondre ยซ Nom d'utilisateur ou mot de passe incorrect ยป. + +#### Le temps de rรฉponse aide les attaquants { #the-time-to-answer-helps-the-attackers } + +ร€ ce stade, en remarquant que le serveur a mis quelques microsecondes de plus ร  envoyer la rรฉponse ยซ Nom d'utilisateur ou mot de passe incorrect ยป, les attaquants sauront qu'ils ont trouvรฉ quelque chose de juste : certaines des premiรจres lettres รฉtaient correctes. + +Ils peuvent alors rรฉessayer en sachant que c'est probablement quelque chose de plus proche de `stanleyjobsox` que de `johndoe`. + +#### Une attaque ยซ professionnelle ยป { #a-professional-attack } + +Bien sรปr, les attaquants n'essaieraient pas tout cela ร  la main ; ils รฉcriraient un programme pour le faire, avec รฉventuellement des milliers ou des millions de tests par seconde. Ils obtiendraient une lettre correcte supplรฉmentaire ร  la fois. + +Ce faisant, en quelques minutes ou heures, les attaquants devineraient le nom d'utilisateur et le mot de passe corrects, avec ยซ l'aide ยป de notre application, simplement en se basant sur le temps de rรฉponse. + +#### Corrigez-le avec `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } + +Mais dans notre code nous utilisons justement `secrets.compare_digest()`. + +En bref, il faudra le mรชme temps pour comparer `stanleyjobsox` ร  `stanleyjobson` que pour comparer `johndoe` ร  `stanleyjobson`. Il en va de mรชme pour le mot de passe. + +Ainsi, en utilisant `secrets.compare_digest()` dans le code de votre application, votre application sera protรฉgรฉe contre toute cette gamme d'attaques de sรฉcuritรฉ. + +### Renvoyer l'erreur { #return-the-error } + +Aprรจs avoir dรฉtectรฉ que les identifiants sont incorrects, renvoyez une `HTTPException` avec un code d'รฉtat 401 (le mรชme que lorsque aucun identifiant n'est fourni) et ajoutez l'en-tรชte `WWW-Authenticate` pour que le navigateur affiche ร  nouveau l'invite de connexion : + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/fr/docs/advanced/security/index.md b/docs/fr/docs/advanced/security/index.md new file mode 100644 index 0000000000..e84fcef626 --- /dev/null +++ b/docs/fr/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# Sรฉcuritรฉ avancรฉe { #advanced-security } + +## Fonctionnalitรฉs supplรฉmentaires { #additional-features } + +Il existe des fonctionnalitรฉs supplรฉmentaires pour gรฉrer la sรฉcuritรฉ en plus de celles couvertes dans le [Tutoriel - Guide utilisateur : Sรฉcuritรฉ](../../tutorial/security/index.md){.internal-link target=_blank}. + +/// tip | Astuce + +Les sections suivantes ne sont pas nรฉcessairement ยซ advanced ยป. + +Et il est possible que, pour votre cas dโ€™utilisation, la solution se trouve dans lโ€™une dโ€™entre elles. + +/// + +## Lire dโ€™abord le tutoriel { #read-the-tutorial-first } + +Les sections suivantes partent du principe que vous avez dรฉjร  lu le [Tutoriel - Guide utilisateur : Sรฉcuritรฉ](../../tutorial/security/index.md){.internal-link target=_blank} principal. + +Elles sโ€™appuient toutes sur les mรชmes concepts, mais permettent des fonctionnalitรฉs supplรฉmentaires. diff --git a/docs/fr/docs/advanced/security/oauth2-scopes.md b/docs/fr/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..c890a5129d --- /dev/null +++ b/docs/fr/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# Scopes OAuth2 { #oauth2-scopes } + +Vous pouvez utiliser des scopes OAuth2 directement avec **FastAPI**, ils sont intรฉgrรฉs pour fonctionner de maniรจre transparente. + +Cela vous permettrait dโ€™avoir un systรจme dโ€™autorisations plus fin, conforme au standard OAuth2, intรฉgrรฉ ร  votre application OpenAPI (et ร  la documentation de lโ€™API). + +OAuth2 avec scopes est le mรฉcanisme utilisรฉ par de nombreux grands fournisseurs dโ€™authentification, comme Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Ils lโ€™utilisent pour fournir des permissions spรฉcifiques aux utilisateurs et aux applications. + +Chaque fois que vous ยซ log in with ยป Facebook, Google, GitHub, Microsoft, X (Twitter), cette application utilise OAuth2 avec scopes. + +Dans cette section, vous verrez comment gรฉrer lโ€™authentification et lโ€™autorisation avec le mรชme OAuth2 avec scopes dans votre application **FastAPI**. + +/// warning | Alertes + +Cโ€™est une section plus ou moins avancรฉe. Si vous dรฉbutez, vous pouvez la passer. + +Vous nโ€™avez pas nรฉcessairement besoin des scopes OAuth2, et vous pouvez gรฉrer lโ€™authentification et lโ€™autorisation comme vous le souhaitez. + +Mais OAuth2 avec scopes peut sโ€™intรฉgrer รฉlรฉgamment ร  votre API (avec OpenAPI) et ร  votre documentation dโ€™API. + +Nรฉanmoins, cโ€™est toujours ร  vous de faire appliquer ces scopes, ou toute autre exigence de sรฉcuritรฉ/autorisation, selon vos besoins, dans votre code. + +Dans de nombreux cas, OAuth2 avec scopes peut รชtre excessif. + +Mais si vous savez que vous en avez besoin, ou si vous รชtes curieux, continuez ร  lire. + +/// + +## Scopes OAuth2 et OpenAPI { #oauth2-scopes-and-openapi } + +La spรฉcification OAuth2 dรฉfinit des ยซ scopes ยป comme une liste de chaรฎnes sรฉparรฉes par des espaces. + +Le contenu de chacune de ces chaรฎnes peut avoir nโ€™importe quel format, mais ne doit pas contenir dโ€™espaces. + +Ces scopes reprรฉsentent des ยซ permissions ยป. + +Dans OpenAPI (par ex. la documentation de lโ€™API), vous pouvez dรฉfinir des ยซ schรฉmas de sรฉcuritรฉ ยป. + +Lorsquโ€™un de ces schรฉmas de sรฉcuritรฉ utilise OAuth2, vous pouvez aussi dรฉclarer et utiliser des scopes. + +Chaque ยซ scope ยป est juste une chaรฎne (sans espaces). + +Ils sont gรฉnรฉralement utilisรฉs pour dรฉclarer des permissions de sรฉcuritรฉ spรฉcifiques, par exemple : + +* `users:read` ou `users:write` sont des exemples courants. +* `instagram_basic` est utilisรฉ par Facebook / Instagram. +* `https://www.googleapis.com/auth/drive` est utilisรฉ par Google. + +/// info + +Dans OAuth2, un ยซ scope ยป est simplement une chaรฎne qui dรฉclare une permission spรฉcifique requise. + +Peu importe sโ€™il contient dโ€™autres caractรจres comme `:` ou si cโ€™est une URL. + +Ces dรฉtails dรฉpendent de lโ€™implรฉmentation. + +Pour OAuth2, ce ne sont que des chaรฎnes. + +/// + +## Vue dโ€™ensemble { #global-view } + +Voyons dโ€™abord rapidement les parties qui changent par rapport aux exemples du **Tutoriel - Guide utilisateur** pour [OAuth2 avec mot de passe (et hachage), Bearer avec jetons JWT](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Cette fois, en utilisant des scopes OAuth2 : + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +Passons maintenant en revue ces changements รฉtape par รฉtape. + +## Dรฉclarer le schรฉma de sรฉcuritรฉ OAuth2 { #oauth2-security-scheme } + +Le premier changement est que nous dรฉclarons maintenant le schรฉma de sรฉcuritรฉ OAuth2 avec deux scopes disponibles, `me` et `items`. + +Le paramรจtre `scopes` reรงoit un `dict` avec chaque scope en clรฉ et la description en valeur : + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +Comme nous dรฉclarons maintenant ces scopes, ils apparaรฎtront dans la documentation de lโ€™API lorsque vous vous authentifiez/autorisez. + +Et vous pourrez sรฉlectionner ร  quels scopes vous souhaitez accorder lโ€™accรจs : `me` et `items`. + +Cโ€™est le mรชme mรฉcanisme utilisรฉ lorsque vous donnez des permissions en vous connectant avec Facebook, Google, GitHub, etc. : + + + +## Jeton JWT avec scopes { #jwt-token-with-scopes } + +Modifiez maintenant le *chemin dโ€™accรจs* du jeton pour renvoyer les scopes demandรฉs. + +Nous utilisons toujours le mรชme `OAuth2PasswordRequestForm`. Il inclut une propriรฉtรฉ `scopes` avec une `list` de `str`, contenant chaque scope reรงu dans la requรชte. + +Et nous renvoyons les scopes comme partie du jeton JWT. + +/// danger | Danger + +Pour simplifier, ici nous ajoutons directement au jeton les scopes reรงus. + +Mais dans votre application, pour la sรฉcuritรฉ, vous devez vous assurer de nโ€™ajouter que les scopes que lโ€™utilisateur est rรฉellement autorisรฉ ร  avoir, ou ceux que vous avez prรฉdรฉfinis. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## Dรฉclarer des scopes dans les chemins dโ€™accรจs et les dรฉpendances { #declare-scopes-in-path-operations-and-dependencies } + +Nous dรฉclarons maintenant que le *chemin dโ€™accรจs* `/users/me/items/` nรฉcessite le scope `items`. + +Pour cela, nous importons et utilisons `Security` depuis `fastapi`. + +Vous pouvez utiliser `Security` pour dรฉclarer des dรฉpendances (comme `Depends`), mais `Security` reรงoit aussi un paramรจtre `scopes` avec une liste de scopes (chaรฎnes). + +Dans ce cas, nous passons une fonction de dรฉpendance `get_current_active_user` ร  `Security` (de la mรชme maniรจre que nous le ferions avec `Depends`). + +Mais nous passons aussi une `list` de scopes, ici avec un seul scope : `items` (il pourrait y en avoir plus). + +Et la fonction de dรฉpendance `get_current_active_user` peut รฉgalement dรฉclarer des sous-dรฉpendances, non seulement avec `Depends` mais aussi avec `Security`. En dรฉclarant sa propre fonction de sous-dรฉpendance (`get_current_user`), et davantage dโ€™exigences de scopes. + +Dans ce cas, elle nรฉcessite le scope `me` (elle pourrait en exiger plusieurs). + +/// note | Remarque + +Vous nโ€™avez pas nรฉcessairement besoin dโ€™ajouter des scopes diffรฉrents ร  diffรฉrents endroits. + +Nous le faisons ici pour montrer comment **FastAPI** gรจre des scopes dรฉclarรฉs ร  diffรฉrents niveaux. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | Dรฉtails techniques + +`Security` est en rรฉalitรฉ une sous-classe de `Depends`, et elle nโ€™a quโ€™un paramรจtre supplรฉmentaire que nous verrons plus tard. + +Mais en utilisant `Security` au lieu de `Depends`, **FastAPI** saura quโ€™il peut dรฉclarer des scopes de sรฉcuritรฉ, les utiliser en interne et documenter lโ€™API avec OpenAPI. + +Cependant, lorsque vous importez `Query`, `Path`, `Depends`, `Security` et dโ€™autres depuis `fastapi`, ce sont en fait des fonctions qui renvoient des classes spรฉciales. + +/// + +## Utiliser `SecurityScopes` { #use-securityscopes } + +Mettez maintenant ร  jour la dรฉpendance `get_current_user`. + +Cโ€™est celle utilisรฉe par les dรฉpendances ci-dessus. + +Cโ€™est ici que nous utilisons le mรชme schรฉma OAuth2 que nous avons crรฉรฉ auparavant, en le dรฉclarant comme dรฉpendance : `oauth2_scheme`. + +Comme cette fonction de dรฉpendance nโ€™a pas elle-mรชme dโ€™exigences de scope, nous pouvons utiliser `Depends` avec `oauth2_scheme`, nous nโ€™avons pas ร  utiliser `Security` quand nous nโ€™avons pas besoin de spรฉcifier des scopes de sรฉcuritรฉ. + +Nous dรฉclarons รฉgalement un paramรจtre spรฉcial de type `SecurityScopes`, importรฉ de `fastapi.security`. + +Cette classe `SecurityScopes` est similaire ร  `Request` (`Request` servait ร  obtenir directement lโ€™objet requรชte). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## Utiliser les `scopes` { #use-the-scopes } + +Le paramรจtre `security_scopes` sera de type `SecurityScopes`. + +Il aura une propriรฉtรฉ `scopes` avec une liste contenant tous les scopes requis par lui-mรชme et par toutes les dรฉpendances qui lโ€™utilisent comme sous-dรฉpendance. Cela signifie, tous les ยซ dรฉpendants ยป ... cela peut paraรฎtre dรฉroutant, cโ€™est expliquรฉ ร  nouveau plus bas. + +Lโ€™objet `security_scopes` (de classe `SecurityScopes`) fournit aussi un attribut `scope_str` avec une chaรฎne unique, contenant ces scopes sรฉparรฉs par des espaces (nous allons lโ€™utiliser). + +Nous crรฉons une `HTTPException` que nous pouvons rรฉutiliser (`raise`) plus tard ร  plusieurs endroits. + +Dans cette exception, nous incluons les scopes requis (le cas รฉchรฉant) sous forme de chaรฎne sรฉparรฉe par des espaces (en utilisant `scope_str`). Nous plaรงons cette chaรฎne contenant les scopes dans lโ€™en-tรชte `WWW-Authenticate` (cela fait partie de la spรฉcification). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## Vรฉrifier le `username` et la structure des donnรฉes { #verify-the-username-and-data-shape } + +Nous vรฉrifions que nous obtenons un `username`, et extrayons les scopes. + +Nous validons ensuite ces donnรฉes avec le modรจle Pydantic (en capturant lโ€™exception `ValidationError`), et si nous obtenons une erreur lors de la lecture du jeton JWT ou de la validation des donnรฉes avec Pydantic, nous levons la `HTTPException` que nous avons crรฉรฉe auparavant. + +Pour cela, nous mettons ร  jour le modรจle Pydantic `TokenData` avec une nouvelle propriรฉtรฉ `scopes`. + +En validant les donnรฉes avec Pydantic, nous pouvons nous assurer que nous avons, par exemple, exactement une `list` de `str` pour les scopes et un `str` pour le `username`. + +Au lieu, par exemple, dโ€™un `dict`, ou autre chose, ce qui pourrait casser lโ€™application plus tard et constituer un risque de sรฉcuritรฉ. + +Nous vรฉrifions รฉgalement que nous avons un utilisateur avec ce nom dโ€™utilisateur, et sinon, nous levons la mรชme exception que prรฉcรฉdemment. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## Vรฉrifier les `scopes` { #verify-the-scopes } + +Nous vรฉrifions maintenant que tous les scopes requis, par cette dรฉpendance et tous les dรฉpendants (y compris les *chemins dโ€™accรจs*), sont inclus dans les scopes fournis dans le jeton reรงu, sinon nous levons une `HTTPException`. + +Pour cela, nous utilisons `security_scopes.scopes`, qui contient une `list` avec tous ces scopes en `str`. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Arbre de dรฉpendances et scopes { #dependency-tree-and-scopes } + +Revoyons encore cet arbre de dรฉpendances et les scopes. + +Comme la dรฉpendance `get_current_active_user` a une sous-dรฉpendance `get_current_user`, le scope ยซ me ยป dรฉclarรฉ dans `get_current_active_user` sera inclus dans la liste des scopes requis dans `security_scopes.scopes` passรฉ ร  `get_current_user`. + +Le *chemin dโ€™accรจs* lui-mรชme dรฉclare รฉgalement un scope, ยซ items ยป, il sera donc aussi prรฉsent dans la liste `security_scopes.scopes` passรฉe ร  `get_current_user`. + +Voici ร  quoi ressemble la hiรฉrarchie des dรฉpendances et des scopes : + +* Le *chemin dโ€™accรจs* `read_own_items` a : + * Des scopes requis `["items"]` avec la dรฉpendance : + * `get_current_active_user` : + * La fonction de dรฉpendance `get_current_active_user` a : + * Des scopes requis `["me"]` avec la dรฉpendance : + * `get_current_user` : + * La fonction de dรฉpendance `get_current_user` a : + * Aucun scope requis par elle-mรชme. + * Une dรฉpendance utilisant `oauth2_scheme`. + * Un paramรจtre `security_scopes` de type `SecurityScopes` : + * Ce paramรจtre `security_scopes` a une propriรฉtรฉ `scopes` avec une `list` contenant tous les scopes dรฉclarรฉs ci-dessus, donc : + * `security_scopes.scopes` contiendra `["me", "items"]` pour le *chemin dโ€™accรจs* `read_own_items`. + * `security_scopes.scopes` contiendra `["me"]` pour le *chemin dโ€™accรจs* `read_users_me`, car il est dรฉclarรฉ dans la dรฉpendance `get_current_active_user`. + * `security_scopes.scopes` contiendra `[]` (rien) pour le *chemin dโ€™accรจs* `read_system_status`, car il nโ€™a dรฉclarรฉ aucun `Security` avec des `scopes`, et sa dรฉpendance, `get_current_user`, ne dรฉclare pas non plus de `scopes`. + +/// tip | Astuce + +Lโ€™รฉlรฉment important et ยซ magique ยป ici est que `get_current_user` aura une liste diffรฉrente de `scopes` ร  vรฉrifier pour chaque *chemin dโ€™accรจs*. + +Tout dรฉpend des `scopes` dรฉclarรฉs dans chaque *chemin dโ€™accรจs* et chaque dรฉpendance dans lโ€™arbre de dรฉpendances pour ce *chemin dโ€™accรจs* spรฉcifique. + +/// + +## Dรฉtails supplรฉmentaires sur `SecurityScopes` { #more-details-about-securityscopes } + +Vous pouvez utiliser `SecurityScopes` ร  nโ€™importe quel endroit, et ร  de multiples endroits, il nโ€™a pas besoin dโ€™รชtre dans la dรฉpendance ยซ root ยป. + +Il aura toujours les scopes de sรฉcuritรฉ dรฉclarรฉs dans les dรฉpendances `Security` actuelles et tous les dรฉpendants pour **ce** *chemin dโ€™accรจs* spรฉcifique et **cet** arbre de dรฉpendances spรฉcifique. + +Comme `SecurityScopes` contient tous les scopes dรฉclarรฉs par les dรฉpendants, vous pouvez lโ€™utiliser pour vรฉrifier quโ€™un jeton possรจde les scopes requis dans une fonction de dรฉpendance centrale, puis dรฉclarer des exigences de scopes diffรฉrentes dans diffรฉrents *chemins dโ€™accรจs*. + +Elles seront vรฉrifiรฉes indรฉpendamment pour chaque *chemin dโ€™accรจs*. + +## Tester { #check-it } + +Si vous ouvrez la documentation de lโ€™API, vous pouvez vous authentifier et spรฉcifier quels scopes vous voulez autoriser. + + + +Si vous ne sรฉlectionnez aucun scope, vous serez ยซ authenticated ยป, mais lorsque vous essayerez dโ€™accรฉder ร  `/users/me/` ou `/users/me/items/`, vous obtiendrez une erreur indiquant que vous nโ€™avez pas suffisamment de permissions. Vous pourrez toujours accรฉder ร  `/status/`. + +Et si vous sรฉlectionnez le scope `me` mais pas le scope `items`, vous pourrez accรฉder ร  `/users/me/` mais pas ร  `/users/me/items/`. + +Cโ€™est ce qui arriverait ร  une application tierce qui tenterait dโ€™accรฉder ร  lโ€™un de ces *chemins dโ€™accรจs* avec un jeton fourni par un utilisateur, selon le nombre de permissions que lโ€™utilisateur a accordรฉes ร  lโ€™application. + +## ร€ propos des intรฉgrations tierces { #about-third-party-integrations } + +Dans cet exemple, nous utilisons le flux OAuth2 ยซ password ยป. + +Cโ€™est appropriรฉ lorsque nous nous connectons ร  notre propre application, probablement avec notre propre frontend. + +Parce que nous pouvons lui faire confiance pour recevoir le `username` et le `password`, puisque nous le contrรดlons. + +Mais si vous construisez une application OAuth2 ร  laquelle dโ€™autres se connecteraient (c.-ร -d., si vous construisez un fournisseur dโ€™authentification รฉquivalent ร  Facebook, Google, GitHub, etc.), vous devez utiliser lโ€™un des autres flux. + +Le plus courant est le flux implicite. + +Le plus sรปr est le flux ยซ code ยป, mais il est plus complexe ร  implรฉmenter car il nรฉcessite plus dโ€™รฉtapes. Comme il est plus complexe, de nombreux fournisseurs finissent par recommander le flux implicite. + +/// note | Remarque + +Il est courant que chaque fournisseur dโ€™authentification nomme ses flux diffรฉremment, pour en faire une partie de sa marque. + +Mais au final, ils implรฉmentent le mรชme standard OAuth2. + +/// + +**FastAPI** inclut des utilitaires pour tous ces flux dโ€™authentification OAuth2 dans `fastapi.security.oauth2`. + +## `Security` dans les dรฉpendances du dรฉcorateur `dependencies` { #security-in-decorator-dependencies } + +De la mรชme maniรจre que vous pouvez dรฉfinir une `list` de `Depends` dans le paramรจtre `dependencies` du dรฉcorateur (comme expliquรฉ dans [Dรฉpendances dans les dรฉcorateurs de chemins dโ€™accรจs](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), vous pouvez aussi utiliser `Security` avec des `scopes` ร  cet endroit. diff --git a/docs/fr/docs/advanced/settings.md b/docs/fr/docs/advanced/settings.md new file mode 100644 index 0000000000..ed724bf4f6 --- /dev/null +++ b/docs/fr/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Paramรจtres et variables d'environnement { #settings-and-environment-variables } + +Dans de nombreux cas, votre application peut avoir besoin de paramรจtres ou de configurations externes, par exemple des clรฉs secrรจtes, des identifiants de base de donnรฉes, des identifiants pour des services d'e-mail, etc. + +La plupart de ces paramรจtres sont variables (peuvent changer), comme les URL de base de donnรฉes. Et beaucoup peuvent รชtre sensibles, comme les secrets. + +C'est pourquoi il est courant de les fournir via des variables d'environnement lues par l'application. + +/// tip | Astuce + +Pour comprendre les variables d'environnement, vous pouvez lire [Variables d'environnement](../environment-variables.md){.internal-link target=_blank}. + +/// + +## Types et validation { #types-and-validation } + +Ces variables d'environnement ne gรจrent que des chaรฎnes de texte, car elles sont externes ร  Python et doivent รชtre compatibles avec d'autres programmes et le reste du systรจme (et mรชme avec diffรฉrents systรจmes d'exploitation, comme Linux, Windows, macOS). + +Cela signifie que toute valeur lue en Python depuis une variable d'environnement sera une `str`, et toute conversion vers un autre type ou toute validation doit รชtre effectuรฉe dans le code. + +## Pydantic `Settings` { #pydantic-settings } + +Heureusement, Pydantic fournit un excellent utilitaire pour gรฉrer ces paramรจtres provenant des variables d'environnement avec Pydantic : gestion des paramรจtres. + +### Installer `pydantic-settings` { #install-pydantic-settings } + +D'abord, vous devez crรฉer votre [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, puis installer le paquet `pydantic-settings` : + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +Il est รฉgalement inclus lorsque vous installez les extras `all` avec : + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### Crรฉer l'objet `Settings` { #create-the-settings-object } + +Importez `BaseSettings` depuis Pydantic et crรฉez une sous-classe, comme pour un modรจle Pydantic. + +De la mรชme maniรจre qu'avec les modรจles Pydantic, vous dรฉclarez des attributs de classe avec des annotations de type, et รฉventuellement des valeurs par dรฉfaut. + +Vous pouvez utiliser toutes les mรชmes fonctionnalitรฉs et outils de validation que pour les modรจles Pydantic, comme diffรฉrents types de donnรฉes et des validations supplรฉmentaires avec `Field()`. + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | Astuce + +Si vous voulez quelque chose ร  copier-coller rapidement, n'utilisez pas cet exemple, utilisez le dernier ci-dessous. + +/// + +Ensuite, lorsque vous crรฉez une instance de cette classe `Settings` (dans ce cas, l'objet `settings`), Pydantic lira les variables d'environnement de maniรจre insensible ร  la casse, donc une variable en majuscules `APP_NAME` sera tout de mรชme lue pour l'attribut `app_name`. + +Il convertira ensuite et validera les donnรฉes. Ainsi, lorsque vous utilisez cet objet `settings`, vous aurez des donnรฉes des types que vous avez dรฉclarรฉs (par exemple, `items_per_user` sera un `int`). + +### Utiliser `settings` { #use-the-settings } + +Vous pouvez ensuite utiliser le nouvel objet `settings` dans votre application : + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### Exรฉcuter le serveur { #run-the-server } + +Ensuite, vous exรฉcutez le serveur en passant les configurations comme variables d'environnement ; par exemple, vous pouvez dรฉfinir un `ADMIN_EMAIL` et `APP_NAME` avec : + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | Astuce + +Pour dรฉfinir plusieurs variables d'environnement pour une seule commande, sรฉparez-les simplement par un espace et placez-les toutes avant la commande. + +/// + +Ainsi, le paramรจtre `admin_email` sera dรฉfini sur ยซ deadpool@example.com ยป. + +Le `app_name` sera ยซ ChimichangApp ยป. + +Et `items_per_user` conservera sa valeur par dรฉfaut de `50`. + +## Paramรจtres dans un autre module { #settings-in-another-module } + +Vous pouvez placer ces paramรจtres dans un autre module comme vous l'avez vu dans [Applications plus grandes - Plusieurs fichiers](../tutorial/bigger-applications.md){.internal-link target=_blank}. + +Par exemple, vous pourriez avoir un fichier `config.py` avec : + +{* ../../docs_src/settings/app01_py310/config.py *} + +Puis l'utiliser dans un fichier `main.py` : + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | Astuce + +Vous aurez รฉgalement besoin d'un fichier `__init__.py` comme vous l'avez vu dans [Applications plus grandes - Plusieurs fichiers](../tutorial/bigger-applications.md){.internal-link target=_blank}. + +/// + +## Paramรจtres dans une dรฉpendance { #settings-in-a-dependency } + +Dans certains cas, il peut รชtre utile de fournir les paramรจtres via une dรฉpendance, au lieu d'avoir un objet global `settings` utilisรฉ partout. + +Cela peut รชtre particuliรจrement utile pendant les tests, car il est trรจs facile de surcharger une dรฉpendance avec vos propres paramรจtres personnalisรฉs. + +### Le fichier de configuration { #the-config-file } + +En repartant de l'exemple prรฉcรฉdent, votre fichier `config.py` pourrait ressembler ร  : + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +Notez que maintenant, nous ne crรฉons pas d'instance par dรฉfaut `settings = Settings()`. + +### Le fichier principal de l'application { #the-main-app-file } + +Nous crรฉons maintenant une dรฉpendance qui renvoie un nouveau `config.Settings()`. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | Astuce + +Nous parlerons de `@lru_cache` dans un instant. + +Pour l'instant, vous pouvez supposer que `get_settings()` est une fonction normale. + +/// + +Nous pouvons ensuite l'exiger depuis la fonction de chemin d'accรจs comme dรฉpendance et l'utiliser oรน nous en avons besoin. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### Paramรจtres et tests { #settings-and-testing } + +Il devient alors trรจs simple de fournir un autre objet de paramรจtres pendant les tests en crรฉant une surcharge de dรฉpendance pour `get_settings` : + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +Dans la surcharge de dรฉpendance, nous dรฉfinissons une nouvelle valeur pour `admin_email` lors de la crรฉation du nouvel objet `Settings`, puis nous renvoyons ce nouvel objet. + +Nous pouvons ensuite tester qu'il est bien utilisรฉ. + +## Lire un fichier `.env` { #reading-a-env-file } + +Si vous avez de nombreux paramรจtres susceptibles de beaucoup changer, peut-รชtre selon les environnements, il peut รชtre utile de les placer dans un fichier, puis de les lire comme s'il s'agissait de variables d'environnement. + +Cette pratique est suffisamment courante pour avoir un nom ; ces variables d'environnement sont frรฉquemment placรฉes dans un fichier `.env`, et le fichier est appelรฉ un ยซ dotenv ยป. + +/// tip | Astuce + +Un fichier commenรงant par un point (`.`) est un fichier cachรฉ dans les systรจmes de type Unix, comme Linux et macOS. + +Mais un fichier dotenv n'a pas forcรฉment exactement ce nom de fichier. + +/// + +Pydantic prend en charge la lecture depuis ce type de fichiers en utilisant une bibliothรจque externe. Vous pouvez en lire davantage ici : Pydantic Settings : prise en charge de Dotenv (.env). + +/// tip | Astuce + +Pour que cela fonctionne, vous devez exรฉcuter `pip install python-dotenv`. + +/// + +### Le fichier `.env` { #the-env-file } + +Vous pouvez avoir un fichier `.env` avec : + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### Lire les paramรจtres depuis `.env` { #read-settings-from-env } + +Puis mettre ร  jour votre `config.py` avec : + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | Astuce + +L'attribut `model_config` est utilisรฉ uniquement pour la configuration Pydantic. Vous pouvez en lire davantage ici : Pydantic : Concepts : Configuration. + +/// + +Ici, nous dรฉfinissons la configuration `env_file` ร  l'intรฉrieur de votre classe Pydantic `Settings` et lui attribuons le nom du fichier dotenv que nous voulons utiliser. + +### Crรฉer `Settings` une seule fois avec `lru_cache` { #creating-the-settings-only-once-with-lru-cache } + +Lire un fichier depuis le disque est normalement une opรฉration coรปteuse (lente), vous voudrez donc probablement le faire une seule fois puis rรฉutiliser le mรชme objet de paramรจtres, au lieu de le lire ร  chaque requรชte. + +Mais chaque fois que nous faisons : + +```Python +Settings() +``` + +un nouvel objet `Settings` serait crรฉรฉ, et ร  sa crรฉation il lirait ร  nouveau le fichier `.env`. + +Si la fonction de dรฉpendance รฉtait simplement : + +```Python +def get_settings(): + return Settings() +``` + +nous crรฉerions cet objet pour chaque requรชte, et nous lirions le fichier `.env` pour chaque requรชte. โš ๏ธ + +Mais comme nous utilisons le dรฉcorateur `@lru_cache` au-dessus, l'objet `Settings` sera crรฉรฉ une seule fois, la premiรจre fois qu'il est appelรฉ. โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +Ensuite, pour tout appel ultรฉrieur de `get_settings()` dans les dรฉpendances pour les requรชtes suivantes, au lieu d'exรฉcuter le code interne de `get_settings()` et de crรฉer un nouvel objet `Settings`, il renverra le mรชme objet que celui retournรฉ au premier appel, encore et encore. + +#### Dรฉtails techniques de `lru_cache` { #lru-cache-technical-details } + +`@lru_cache` modifie la fonction qu'il dรฉcore pour renvoyer la mรชme valeur que celle qui a รฉtรฉ retournรฉe la premiรจre fois, au lieu de la recalculer en exรฉcutant le code de la fonction ร  chaque fois. + +Ainsi, la fonction situรฉe en dessous sera exรฉcutรฉe une fois pour chaque combinaison d'arguments. Ensuite, les valeurs renvoyรฉes par chacune de ces combinaisons d'arguments seront rรฉutilisรฉes ร  chaque fois que la fonction sera appelรฉe avec exactement la mรชme combinaison d'arguments. + +Par exemple, si vous avez une fonction : + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +votre programme pourrait s'exรฉcuter comme ceci : + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +Dans le cas de notre dรฉpendance `get_settings()`, la fonction ne prend mรชme aucun argument, elle renvoie donc toujours la mรชme valeur. + +De cette faรงon, elle se comporte presque comme s'il s'agissait simplement d'une variable globale. Mais comme elle utilise une fonction de dรฉpendance, nous pouvons alors la surcharger facilement pour les tests. + +`@lru_cache` fait partie de `functools` qui fait partie de la bibliothรจque standard de Python, vous pouvez en lire davantage dans la documentation Python pour `@lru_cache`. + +## Rรฉcapitulatif { #recap } + +Vous pouvez utiliser Pydantic Settings pour gรฉrer les paramรจtres ou configurations de votre application, avec toute la puissance des modรจles Pydantic. + +* En utilisant une dรฉpendance, vous pouvez simplifier les tests. +* Vous pouvez utiliser des fichiers `.env`. +* Utiliser `@lru_cache` vous permet d'รฉviter de relire le fichier dotenv ร  chaque requรชte, tout en vous permettant de le surcharger pendant les tests. diff --git a/docs/fr/docs/advanced/sub-applications.md b/docs/fr/docs/advanced/sub-applications.md new file mode 100644 index 0000000000..777056040e --- /dev/null +++ b/docs/fr/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Sous-applications - Montage { #sub-applications-mounts } + +Si vous avez besoin de deux applications FastAPI indรฉpendantes, avec leur propre OpenAPI et leurs propres interfaces de la documentation, vous pouvez avoir une application principale et ยซ monter ยป une (ou plusieurs) sousโ€‘application(s). + +## Monter une application **FastAPI** { #mounting-a-fastapi-application } + +ยซ Monter ยป signifie ajouter une application entiรจrement ยซ indรฉpendante ยป ร  un chemin spรฉcifique, qui se chargera ensuite de tout gรฉrer sous ce chemin, avec les _chemins d'accรจs_ dรฉclarรฉs dans cette sousโ€‘application. + +### Application de premier niveau { #top-level-application } + +Crรฉez d'abord l'application **FastAPI** principale (de premier niveau) et ses *chemins d'accรจs* : + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### Sous-application { #sub-application } + +Ensuite, crรฉez votre sousโ€‘application et ses *chemins d'accรจs*. + +Cette sousโ€‘application est simplement une autre application FastAPI standard, mais c'est celle qui sera ยซ montรฉe ยป : + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### Monter la sous-application { #mount-the-sub-application } + +Dans votre application de premier niveau, `app`, montez la sousโ€‘application, `subapi`. + +Dans ce cas, elle sera montรฉe au chemin `/subapi` : + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### Vรฉrifier la documentation API automatique { #check-the-automatic-api-docs } + +Exรฉcutez maintenant la commande `fastapi` avec votre fichier : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Puis ouvrez la documentation ร  http://127.0.0.1:8000/docs. + +Vous verrez la documentation API automatique pour l'application principale, n'incluant que ses propres _chemins d'accรจs_ : + + + +Ensuite, ouvrez la documentation de la sousโ€‘application ร  http://127.0.0.1:8000/subapi/docs. + +Vous verrez la documentation API automatique pour la sousโ€‘application, n'incluant que ses propres _chemins d'accรจs_, tous sous le prรฉfixe de sousโ€‘chemin correct `/subapi` : + + + +Si vous essayez d'interagir avec l'une ou l'autre des deux interfaces, elles fonctionneront correctement, car le navigateur pourra communiquer avec chaque application ou sousโ€‘application spรฉcifique. + +### Dรฉtails techniques : `root_path` { #technical-details-root-path } + +Lorsque vous montez une sousโ€‘application comme ciโ€‘dessus, FastAPI se charge de communiquer le chemin de montage ร  la sousโ€‘application au moyen d'un mรฉcanisme de la spรฉcification ASGI appelรฉ `root_path`. + +De cette maniรจre, la sousโ€‘application saura utiliser ce prรฉfixe de chemin pour l'interface de documentation. + +La sousโ€‘application peut รฉgalement avoir ses propres sousโ€‘applications montรฉes et tout fonctionnera correctement, car FastAPI gรจre automatiquement tous ces `root_path`. + +Vous en apprendrez davantage sur `root_path` et sur la faรงon de l'utiliser explicitement dans la section [Derriรจre un proxy](behind-a-proxy.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/advanced/templates.md b/docs/fr/docs/advanced/templates.md new file mode 100644 index 0000000000..7c886ab695 --- /dev/null +++ b/docs/fr/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# Templates { #templates } + +Vous pouvez utiliser n'importe quel moteur de templates avec **FastAPI**. + +Un choix courant est Jinja2, le mรชme que celui utilisรฉ par Flask et d'autres outils. + +Il existe des utilitaires pour le configurer facilement que vous pouvez utiliser directement dans votre application **FastAPI** (fournis par Starlette). + +## Installer les dรฉpendances { #install-dependencies } + +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, puis installer `jinja2` : + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## Utiliser `Jinja2Templates` { #using-jinja2templates } + +- Importez `Jinja2Templates`. +- Crรฉez un objet `templates` que vous pourrez rรฉutiliser par la suite. +- Dรฉclarez un paramรจtre `Request` dans le *chemin d'accรจs* qui renverra un template. +- Utilisez l'objet `templates` que vous avez crรฉรฉ pour rendre et retourner une `TemplateResponse`, en transmettant le nom du template, l'objet de requรชte et un dictionnaire de ยซ context ยป avec des paires clรฉ-valeur ร  utiliser dans le template Jinja2. + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | Remarque + +Avant FastAPI 0.108.0 et Starlette 0.29.0, `name` รฉtait le premier paramรจtre. + +De plus, auparavant, dans les versions prรฉcรฉdentes, l'objet `request` faisait partie des paires clรฉ-valeur du contexte pour Jinja2. + +/// + +/// tip | Astuce + +En dรฉclarant `response_class=HTMLResponse`, l'interface de la documentation saura que la rรฉponse sera en HTML. + +/// + +/// note | Dรฉtails techniques + +Vous pouvez aussi utiliser `from starlette.templating import Jinja2Templates`. + +**FastAPI** expose le mรชme `starlette.templating` sous `fastapi.templating` par simple commoditรฉ pour vous, dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. C'est รฉgalement le cas pour `Request` et `StaticFiles`. + +/// + +## ร‰crire des templates { #writing-templates } + +Vous pouvez ensuite รฉcrire un template dans `templates/item.html`, par exemple : + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Valeurs de contexte du template { #template-context-values } + +Dans le HTML qui contient : + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +... il affichera lโ€™`id` rรฉcupรฉrรฉ ร  partir du `dict` ยซ context ยป que vous avez passรฉ : + +```Python +{"id": id} +``` + +Par exemple, avec un ID de `42`, cela rendrait : + +```html +Item ID: 42 +``` + +### Arguments de `url_for` dans le template { #template-url-for-arguments } + +Vous pouvez aussi utiliser `url_for()` dans le template ; elle prend en paramรจtres les mรชmes arguments que ceux utilisรฉs par votre *fonction de chemin d'accรจs*. + +Ainsi, la section suivante : + +{% raw %} + +```jinja + +``` + +{% endraw %} + +... gรฉnรฉrera un lien vers la mรชme URL que celle gรฉrรฉe par la *fonction de chemin d'accรจs* `read_item(id=id)`. + +Par exemple, avec un ID de `42`, cela rendrait : + +```html + +``` + +## Templates et fichiers statiques { #templates-and-static-files } + +Vous pouvez aussi utiliser `url_for()` dans le template, par exemple avec les `StaticFiles` que vous avez montรฉs avec `name="static"`. + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +Dans cet exemple, cela crรฉera un lien vers un fichier CSS `static/styles.css` avec : + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +Et comme vous utilisez `StaticFiles`, ce fichier CSS est servi automatiquement par votre application **FastAPI** ร  lโ€™URL `/static/styles.css`. + +## En savoir plus { #more-details } + +Pour plus de dรฉtails, y compris sur la faรงon de tester des templates, consultez la documentation de Starlette sur les templates. diff --git a/docs/fr/docs/advanced/testing-dependencies.md b/docs/fr/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000..d6fc576bf6 --- /dev/null +++ b/docs/fr/docs/advanced/testing-dependencies.md @@ -0,0 +1,52 @@ +# Tester des dรฉpendances avec des surcharges { #testing-dependencies-with-overrides } + +## Surcharger des dรฉpendances pendant les tests { #overriding-dependencies-during-testing } + +Il existe des cas oรน vous souhaiterez surcharger une dรฉpendance pendant les tests. + +Vous ne voulez pas exรฉcuter la dรฉpendance originale (ni ses รฉventuelles sousโ€‘dรฉpendances). + +ร€ la place, vous souhaitez fournir une dรฉpendance diffรฉrente, utilisรฉe uniquement pendant les tests (รฉventuellement seulement pour certains tests), et qui fournira une valeur utilisable partout oรน lโ€™on utilisait celle de la dรฉpendance originale. + +### Cas dโ€™usage : service externe { #use-cases-external-service } + +Par exemple, vous avez un fournisseur dโ€™authentification externe ร  appeler. + +Vous lui envoyez un token et il renvoie un utilisateur authentifiรฉ. + +Ce fournisseur peut vous facturer ร  la requรชte, et lโ€™appeler peut prendre plus de temps que si vous aviez un utilisateur factice fixe pour les tests. + +Vous voudrez probablement tester le fournisseur externe une fois, mais pas nรฉcessairement lโ€™appeler pour chaque test exรฉcutรฉ. + +Dans ce cas, vous pouvez surcharger la dรฉpendance qui appelle ce fournisseur et utiliser une dรฉpendance personnalisรฉe qui renvoie un utilisateur factice, uniquement pour vos tests. + +### Utiliser lโ€™attribut `app.dependency_overrides` { #use-the-app-dependency-overrides-attribute } + +Pour ces cas, votre **FastAPI** application possรจde un attribut `app.dependency_overrides` ; cโ€™est un simple `dict`. + +Pour surcharger une dรฉpendance lors des tests, vous mettez comme clรฉ la dรฉpendance originale (une fonction) et comme valeur votre surcharge de dรฉpendance (une autre fonction). + +Ensuite, **FastAPI** appellera cette surcharge au lieu de la dรฉpendance originale. + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | Astuce + +Vous pouvez dรฉfinir une surcharge de dรฉpendance pour une dรฉpendance utilisรฉe nโ€™importe oรน dans votre application **FastAPI**. + +La dรฉpendance originale peut รชtre utilisรฉe dans une fonction de chemin d'accรจs, un dรฉcorateur de chemin d'accรจs (quand vous nโ€™utilisez pas la valeur de retour), un appel ร  `.include_router()`, etc. + +FastAPI pourra toujours la surcharger. + +/// + +Vous pouvez ensuite rรฉinitialiser vos surcharges (les supprimer) en affectant ร  `app.dependency_overrides` un `dict` vide : + +```Python +app.dependency_overrides = {} +``` +/// tip | Astuce + +Si vous souhaitez surcharger une dรฉpendance uniquement pendant certains tests, vous pouvez dรฉfinir la surcharge au dรฉbut du test (dans la fonction de test) et la rรฉinitialiser ร  la fin (ร  la fin de la fonction de test). + +/// diff --git a/docs/fr/docs/advanced/testing-events.md b/docs/fr/docs/advanced/testing-events.md new file mode 100644 index 0000000000..c4f9141b35 --- /dev/null +++ b/docs/fr/docs/advanced/testing-events.md @@ -0,0 +1,11 @@ +# Tester les รฉvรฉnements : lifespan et startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +Lorsque vous avez besoin d'exรฉcuter `lifespan` dans vos tests, vous pouvez utiliser `TestClient` avec une instruction `with` : + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + +Vous pouvez lire plus de dรฉtails dans [ยซ Exรฉcuter lifespan dans les tests sur le site de documentation officiel de Starlette. ยป](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) + +Pour les รฉvรฉnements dรฉprรฉciรฉs `startup` et `shutdown`, vous pouvez utiliser le `TestClient` comme suit : + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/fr/docs/advanced/testing-websockets.md b/docs/fr/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000..e9f97ab5f2 --- /dev/null +++ b/docs/fr/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# Tester les WebSockets { #testing-websockets } + +Vous pouvez utiliser le mรชme `TestClient` pour tester les WebSockets. + +Pour cela, vous utilisez `TestClient` dans une instruction `with`, en vous connectant au WebSocket : + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | Remarque + +Pour plus de dรฉtails, consultez la documentation de Starlette sur le test des WebSockets. + +/// diff --git a/docs/fr/docs/advanced/using-request-directly.md b/docs/fr/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000..4df3f90e8b --- /dev/null +++ b/docs/fr/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Utiliser Request directement { #using-the-request-directly } + +Jusqu'ร  prรฉsent, vous avez dรฉclarรฉ les parties de la requรชte dont vous avez besoin, avec leurs types. + +En rรฉcupรฉrant des donnรฉes depuisย : + +* Le chemin, sous forme de paramรจtres. +* En-tรชtes. +* Cookies. +* etc. + +Et ce faisant, **FastAPI** valide ces donnรฉes, les convertit et gรฉnรจre automatiquement la documentation de votre API. + +Mais il existe des situations oรน vous pouvez avoir besoin d'accรฉder directement ร  l'objet `Request`. + +## Dรฉtails sur l'objet `Request` { #details-about-the-request-object } + +Comme **FastAPI** est en fait **Starlette** en dessous, avec une couche de plusieurs outils au-dessus, vous pouvez utiliser directement l'objet `Request` de Starlette lorsque vous en avez besoin. + +Cela signifie aussi que si vous rรฉcupรฉrez des donnรฉes directement ร  partir de l'objet `Request` (par exemple, lire le corps), elles ne seront pas validรฉes, converties ni documentรฉes (avec OpenAPI, pour l'interface utilisateur automatique de l'API) par FastAPI. + +En revanche, tout autre paramรจtre dรฉclarรฉ normalement (par exemple, le corps avec un modรจle Pydantic) sera toujours validรฉ, converti, annotรฉ, etc. + +Mais il existe des cas spรฉcifiques oรน il est utile d'obtenir l'objet `Request`. + +## Utiliser l'objet `Request` directement { #use-the-request-object-directly } + +Imaginons que vous souhaitiez obtenir l'adresse IP/l'hรดte du client dans votre fonction de chemin d'accรจs. + +Pour cela, vous devez accรฉder directement ร  la requรชte. + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +En dรฉclarant un paramรจtre de fonction de chemin d'accรจs de type `Request`, **FastAPI** saura passer la `Request` dans ce paramรจtre. + +/// tip | Astuce + +Notez que, dans ce cas, nous dรฉclarons un paramรจtre de chemin en plus du paramรจtre de requรชte. + +Ainsi, le paramรจtre de chemin sera extrait, validรฉ, converti vers le type spรฉcifiรฉ et annotรฉ avec OpenAPI. + +De la mรชme faรงon, vous pouvez dรฉclarer tout autre paramรจtre normalement, et en plus, obtenir aussi la `Request`. + +/// + +## Documentation de `Request` { #request-documentation } + +Vous pouvez lire plus de dรฉtails sur l'objet `Request` sur le site de documentation officiel de Starlette. + +/// note | Dรฉtails techniques + +Vous pouvez รฉgalement utiliser `from starlette.requests import Request`. + +**FastAPI** le fournit directement pour votre commoditรฉ, en tant que dรฉveloppeur. Mais il provient directement de Starlette. + +/// diff --git a/docs/fr/docs/advanced/websockets.md b/docs/fr/docs/advanced/websockets.md new file mode 100644 index 0000000000..6f5c3e7033 --- /dev/null +++ b/docs/fr/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +Vous pouvez utiliser API WebSockets avec **FastAPI**. + +## Installer `websockets` { #install-websockets } + +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, et installer `websockets` (une bibliothรจque Python qui facilite l'utilisation du protocole ยซ WebSocket ยป) : + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## Client WebSocket { #websockets-client } + +### En production { #in-production } + +Dans votre systรจme de production, vous avez probablement un frontend crรฉรฉ avec un framework moderne comme React, Vue.js ou Angular. + +Et pour communiquer en utilisant WebSockets avec votre backend, vous utiliseriez probablement les outils fournis par votre frontend. + +Ou vous pouvez avoir une application mobile native qui communique directement avec votre backend WebSocket, en code natif. + +Ou vous pouvez avoir toute autre faรงon de communiquer avec l'endpoint WebSocket. + +--- + +Mais pour cet exemple, nous utiliserons un document HTML trรจs simple avec un peu de JavaScript, le tout dans une longue chaรฎne. + +Cela, bien entendu, n'est pas optimal et vous ne l'utiliseriez pas en production. + +En production, vous auriez l'une des options ci-dessus. + +Mais c'est la faรงon la plus simple de se concentrer sur la partie serveur des WebSockets et d'avoir un exemple fonctionnel : + +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} + +## Crรฉer un `websocket` { #create-a-websocket } + +Dans votre application **FastAPI**, crรฉez un `websocket` : + +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.websockets import WebSocket`. + +**FastAPI** fournit le mรชme `WebSocket` directement, simplement pour vous faciliter la vie en tant que dรฉveloppeur. Mais il provient directement de Starlette. + +/// + +## Attendre des messages et envoyer des messages { #await-for-messages-and-send-messages } + +Dans votre route WebSocket, vous pouvez `await` des messages et envoyer des messages. + +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} + +Vous pouvez recevoir et envoyer des donnรฉes binaires, texte et JSON. + +## Essayer { #try-it } + +Si votre fichier s'appelle `main.py`, exรฉcutez votre application avec : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ouvrez votre navigateur ร  l'adresse http://127.0.0.1:8000. + +Vous verrez une page simple comme : + + + +Vous pouvez saisir des messages dans le champ de saisie et les envoyer : + + + +Et votre application **FastAPI** avec WebSockets vous rรฉpondra : + + + +Vous pouvez envoyer (et recevoir) de nombreux messages : + + + +Et tous utiliseront la mรชme connexion WebSocket. + +## Utiliser `Depends` et autres { #using-depends-and-others } + +Dans les endpoints WebSocket, vous pouvez importer depuis `fastapi` et utiliser : + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +Ils fonctionnent de la mรชme maniรจre que pour les autres endpoints/*chemins d'accรจs* FastAPI : + +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} + +/// info + +Comme il s'agit d'un WebSocket, il n'est pas vraiment logique de lever une `HTTPException`, nous levons plutรดt une `WebSocketException`. + +Vous pouvez utiliser un code de fermeture parmi les codes valides dรฉfinis dans la spรฉcification. + +/// + +### Essayez les WebSockets avec des dรฉpendances { #try-the-websockets-with-dependencies } + +Si votre fichier s'appelle `main.py`, exรฉcutez votre application avec : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ouvrez votre navigateur ร  l'adresse http://127.0.0.1:8000. + +Lร , vous pouvez dรฉfinir : + +* ยซ Item ID ยป, utilisรฉ dans le chemin. +* ยซ Token ยป utilisรฉ comme paramรจtre de requรชte. + +/// tip | Astuce + +Notez que le `token` de requรชte sera gรฉrรฉ par une dรฉpendance. + +/// + +Avec cela, vous pouvez connecter le WebSocket puis envoyer et recevoir des messages : + + + +## Gรฉrer les dรฉconnexions et plusieurs clients { #handling-disconnections-and-multiple-clients } + +Lorsqu'une connexion WebSocket est fermรฉe, l'instruction `await websocket.receive_text()` lรจvera une exception `WebSocketDisconnect`, que vous pouvez ensuite intercepter et gรฉrer comme dans cet exemple. + +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} + +Pour l'essayer : + +* Ouvrez l'application dans plusieurs onglets du navigateur. +* ร‰crivez des messages depuis ceux-ci. +* Puis fermez l'un des onglets. + +Cela lรจvera l'exception `WebSocketDisconnect`, et tous les autres clients recevront un message comme : + +``` +Client #1596980209979 left the chat +``` + +/// tip | Astuce + +L'application ci-dessus est un exemple minimal et simple pour montrer comment gรฉrer et diffuser des messages ร  plusieurs connexions WebSocket. + +Mais gardez ร  l'esprit que, comme tout est gรฉrรฉ en mรฉmoire, dans une seule liste, cela ne fonctionnera que tant que le processus s'exรฉcute et uniquement avec un seul processus. + +Si vous avez besoin de quelque chose de facile ร  intรฉgrer avec FastAPI mais plus robuste, pris en charge par Redis, PostgreSQL ou autres, consultez encode/broadcaster. + +/// + +## Plus d'informations { #more-info } + +Pour en savoir plus sur les options, consultez la documentation de Starlette concernant : + +* La classe `WebSocket`. +* Gestion des WebSocket basรฉe sur des classes. diff --git a/docs/fr/docs/advanced/wsgi.md b/docs/fr/docs/advanced/wsgi.md new file mode 100644 index 0000000000..fc89819d27 --- /dev/null +++ b/docs/fr/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# Inclure WSGI - Flask, Django, autres { #including-wsgi-flask-django-others } + +Vous pouvez monter des applications WSGI comme vous l'avez vu avec [Sous-applications - Montages](sub-applications.md){.internal-link target=_blank}, [Derriรจre un proxy](behind-a-proxy.md){.internal-link target=_blank}. + +Pour cela, vous pouvez utiliser `WSGIMiddleware` et l'utiliser pour envelopper votre application WSGI, par exemple Flask, Django, etc. + +## Utiliser `WSGIMiddleware` { #using-wsgimiddleware } + +/// info + +Cela nรฉcessite l'installation de `a2wsgi`, par exemple avec `pip install a2wsgi`. + +/// + +Vous devez importer `WSGIMiddleware` depuis `a2wsgi`. + +Ensuite, enveloppez l'application WSGI (par ex. Flask) avec le middleware. + +Puis, montez-la sous un chemin. + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | Remarque + +Auparavant, il รฉtait recommandรฉ d'utiliser `WSGIMiddleware` depuis `fastapi.middleware.wsgi`, mais il est dรฉsormais dรฉprรฉciรฉ. + +Il est conseillรฉ d'utiliser le package `a2wsgi` ร  la place. L'utilisation reste la mรชme. + +Assurez-vous simplement que le package `a2wsgi` est installรฉ et importez `WSGIMiddleware` correctement depuis `a2wsgi`. + +/// + +## Vรฉrifiez { #check-it } + +Dรฉsormais, chaque requรชte sous le chemin `/v1/` sera gรฉrรฉe par l'application Flask. + +Et le reste sera gรฉrรฉ par **FastAPI**. + +Si vous l'exรฉcutez et allez ร  http://localhost:8000/v1/, vous verrez la rรฉponse de Flask : + +```txt +Hello, World from Flask! +``` + +Et si vous allez ร  http://localhost:8000/v2, vous verrez la rรฉponse de FastAPI : + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/fr/docs/alternatives.md b/docs/fr/docs/alternatives.md index 9d8d85705c..c344bd1f88 100644 --- a/docs/fr/docs/alternatives.md +++ b/docs/fr/docs/alternatives.md @@ -1,8 +1,8 @@ -# Alternatives, inspiration et comparaisons +# Alternatives, inspiration et comparaisons { #alternatives-inspiration-and-comparisons } Ce qui a inspirรฉ **FastAPI**, comment il se compare ร  d'autres solutions et ce qu'il en a appris. -## Intro +## Intro { #intro } **FastAPI** n'existerait pas sans les prรฉcรฉdentes contributions d'autres projets. @@ -13,11 +13,11 @@ fonctionnalitรฉs couvertes par **FastAPI** en utilisant de nombreux frameworks, Mais ร  un moment donnรฉ il n'y avait pas d'autre option que de crรฉer quelque chose qui offrait toutes ces fonctionnalitรฉs, en reprenant et en combinant de la meilleure faรงon possible les meilleures idรฉes des outils -prรฉcรฉdents, en utilisant des fonctionnalitรฉs du langage qui n'รฉtaient mรชme pas disponibles auparavant (type hints depuis Python 3.6+). +prรฉcรฉdents, en utilisant des fonctionnalitรฉs du langage qui n'รฉtaient mรชme pas disponibles auparavant (annotations de type depuis Python 3.6+). -## Outils prรฉcรฉdents +## Outils prรฉcรฉdents { #previous-tools } -### Django +### Django { #django } C'est le framework Python le plus populaire et il bรฉnรฉficie d'une grande confiance. Il est utilisรฉ pour construire des systรจmes tel qu'Instagram. @@ -26,18 +26,18 @@ Il est relativement fortement couplรฉ aux bases de donnรฉes relationnelles (comm n'est pas trรจs facile d'utiliser une base de donnรฉes NoSQL (comme Couchbase, MongoDB, Cassandra, etc.) comme principal moyen de stockage. -Il a รฉtรฉ crรฉรฉ pour gรฉnรฉrer le HTML en backend, pas pour crรฉer des API consommรฉes par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systรจmes (comme les appareils IoT) communiquant avec lui. +Il a รฉtรฉ crรฉรฉ pour gรฉnรฉrer le HTML en backend, pas pour crรฉer des API consommรฉes par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systรจmes (comme les appareils IoT) communiquant avec lui. -### Django REST Framework +### Django REST Framework { #django-rest-framework } Django REST framework a รฉtรฉ conรงu comme une boรฎte ร  outils flexible permettant de construire des API Web ร  partir de Django, afin d'amรฉliorer ses capacitรฉs en matiรจre d'API. Il est utilisรฉ par de nombreuses entreprises, dont Mozilla, Red Hat et Eventbrite. Il s'agissait de l'un des premiers exemples de **documentation automatique pour API**, et c'est prรฉcisรฉment l'une des -premiรจres idรฉes qui a inspirรฉ "la recherche de" **FastAPI**. +premiรจres idรฉes qui a inspirรฉ ยซ la recherche de ยป **FastAPI**. -/// note +/// note | Remarque Django REST framework a รฉtรฉ crรฉรฉ par Tom Christie. Le crรฉateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basรฉ. @@ -49,9 +49,9 @@ Avoir une interface de documentation automatique de l'API. /// -### Flask +### Flask { #flask } -Flask est un "micro-framework", il ne comprend pas d'intรฉgrations de bases de donnรฉes ni beaucoup de choses qui sont fournies par dรฉfaut dans Django. +Flask est un ยซ microโ€‘framework ยป, il ne comprend pas d'intรฉgrations de bases de donnรฉes ni beaucoup de choses qui sont fournies par dรฉfaut dans Django. Cette simplicitรฉ et cette flexibilitรฉ permettent d'utiliser des bases de donnรฉes NoSQL comme principal systรจme de stockage de donnรฉes. @@ -60,20 +60,20 @@ technique par moments. Il est aussi couramment utilisรฉ pour d'autres applications qui n'ont pas nรฉcessairement besoin d'une base de donnรฉes, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalitรฉs prรฉinstallรฉes dans Django. Bien que beaucoup de ces fonctionnalitรฉs puissent รชtre ajoutรฉes avec des plug-ins. -Ce dรฉcouplage des parties, et le fait d'รชtre un "micro-framework" qui puisse รชtre รฉtendu pour couvrir exactement ce +Ce dรฉcouplage des parties, et le fait d'รชtre un ยซ microโ€‘framework ยป qui puisse รชtre รฉtendu pour couvrir exactement ce qui est nรฉcessaire, รฉtait une caractรฉristique clรฉ que je voulais conserver. -Compte tenu de la simplicitรฉ de Flask, il semblait bien adaptรฉ ร  la crรฉation d'API. La prochaine chose ร  trouver รฉtait un "Django REST Framework" pour Flask. +Compte tenu de la simplicitรฉ de Flask, il semblait bien adaptรฉ ร  la crรฉation d'API. La prochaine chose ร  trouver รฉtait un ยซ Django REST Framework ยป pour Flask. /// check | A inspirรฉ **FastAPI** ร  -รŠtre un micro-framework. Il est donc facile de combiner les outils et les piรจces nรฉcessaires. +รŠtre un microโ€‘framework. Il est donc facile de combiner les outils et les piรจces nรฉcessaires. Proposer un systรจme de routage simple et facile ร  utiliser. /// -### Requests +### Requests { #requests } **FastAPI** n'est pas rรฉellement une alternative ร  **Requests**. Leur cadre est trรจs diffรฉrent. @@ -97,7 +97,7 @@ La faรงon dont vous l'utilisez est trรจs simple. Par exemple, pour faire une req response = requests.get("http://example.com/some/url") ``` -En contrepartie l'API _des opรฉrations de chemin_ de FastAPI pourrait ressembler ร  ceci : +Lโ€™opรฉration de chemin d'accรจs correspondante dans **FastAPI** pourrait ressembler ร  ceci : ```Python hl_lines="1" @app.get("/some/url") @@ -109,13 +109,13 @@ Notez les similitudes entre `requests.get(...)` et `@app.get(...)`. /// check | A inspirรฉ **FastAPI** ร  -Avoir une API simple et intuitive. - -Utiliser les noms de mรฉthodes HTTP (opรฉrations) directement, de maniรจre simple et intuitive. \* Avoir des valeurs par dรฉfaut raisonnables, mais des personnalisations puissantes. +* Avoir une API simple et intuitive. +* Utiliser les noms de mรฉthodes HTTP (opรฉrations) directement, de maniรจre simple et intuitive. +* Avoir des valeurs par dรฉfaut raisonnables, mais des personnalisations puissantes. /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } La principale fonctionnalitรฉ que j'ai empruntรฉ ร  Django REST Framework รฉtait la documentation automatique des API. @@ -126,7 +126,7 @@ Swagger pour une API permettrait d'utiliser cette interface utilisateur web auto ร€ un moment donnรฉ, Swagger a รฉtรฉ cรฉdรฉ ร  la Fondation Linux, puis a รฉtรฉ rebaptisรฉ OpenAPI. -C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire "Swagger", et pour la version 3+ "OpenAPI". +C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire ยซ Swagger ยป, et pour la version 3+ ยซ OpenAPI ยป. /// check | A inspirรฉ **FastAPI** ร  @@ -141,16 +141,15 @@ Ces deux-lร  ont รฉtรฉ choisis parce qu'ils sont populaires et stables, mais en /// -### Frameworks REST pour Flask +### Frameworks REST pour Flask { #flask-rest-frameworks } Il y a plusieurs frameworks REST pour Flask, mais aprรจs avoir investi du temps et du travail pour les รฉtudier, j'ai dรฉcouvert que le dรฉveloppement de beaucoup d'entre eux sont suspendus ou abandonnรฉs, avec plusieurs problรจmes permanents qui les rendent inadaptรฉs. -### Marshmallow +### Marshmallow { #marshmallow } -L'une des principales fonctionnalitรฉs nรฉcessaires aux systรจmes API est la "sรฉrialisation" des donnรฉes, qui consiste ร  prendre les donnรฉes du code (Python) et ร  +L'une des principales fonctionnalitรฉs nรฉcessaires aux systรจmes API est la ยซ sรฉrialisation ยป des donnรฉes, qui consiste ร  prendre les donnรฉes du code (Python) et ร  les convertir en quelque chose qui peut รชtre envoyรฉ sur le rรฉseau. Par exemple, convertir un objet contenant des donnรฉes provenant d'une base de donnรฉes en un objet JSON. Convertir des objets `datetime` en strings, etc. @@ -163,19 +162,17 @@ Sans un systรจme de validation des donnรฉes, vous devriez effectuer toutes les v Ces fonctionnalitรฉs sont ce pourquoi Marshmallow a รฉtรฉ construit. C'est une excellente bibliothรจque, et je l'ai dรฉjร  beaucoup utilisรฉe. -Mais elle a รฉtรฉ crรฉรฉe avant que les type hints n'existent en Python. Ainsi, pour dรฉfinir chaque schรฉma, vous devez utiliser des utilitaires et des classes spรฉcifiques fournies par Marshmallow. +Mais elle a รฉtรฉ crรฉรฉe avant que les annotations de type n'existent en Python. Ainsi, pour dรฉfinir chaque schรฉma, vous devez utiliser des utilitaires et des classes spรฉcifiques fournies par Marshmallow. /// check | A inspirรฉ **FastAPI** ร  -Utilisez du code pour dรฉfinir des "schรฉmas" qui fournissent automatiquement les types de donnรฉes et la validation. +Utilisez du code pour dรฉfinir des ยซ schรฉmas ยป qui fournissent automatiquement les types de donnรฉes et la validation. /// -### Webargs +### Webargs { #webargs } -Une autre grande fonctionnalitรฉ requise par les API est le parsing des donnรฉes provenant des requรชtes entrantes. +Une autre grande fonctionnalitรฉ requise par les API est lโ€™analyse des donnรฉes provenant des requรชtes entrantes. Webargs est un outil qui a รฉtรฉ crรฉรฉ pour fournir cela par-dessus plusieurs frameworks, dont Flask. @@ -195,7 +192,7 @@ Disposer d'une validation automatique des donnรฉes des requรชtes entrantes. /// -### APISpec +### APISpec { #apispec } Marshmallow et Webargs fournissent la validation, l'analyse et la sรฉrialisation en tant que plug-ins. @@ -225,7 +222,7 @@ Supporter la norme ouverte pour les API, OpenAPI. /// -### Flask-apispec +### Flask-apispec { #flask-apispec } C'est un plug-in pour Flask, qui relie Webargs, Marshmallow et APISpec. @@ -240,11 +237,11 @@ Cette combinaison de Flask, Flask-apispec avec Marshmallow et Webargs รฉtait ma Son utilisation a conduit ร  la crรฉation de plusieurs gรฉnรฉrateurs Flask full-stack. Ce sont les principales stacks que j'ai (ainsi que plusieurs รฉquipes externes) utilisรฉes jusqu'ร  prรฉsent : -- https://github.com/tiangolo/full-stack -- https://github.com/tiangolo/full-stack-flask-couchbase -- https://github.com/tiangolo/full-stack-flask-couchdb +* https://github.com/tiangolo/full-stack +* https://github.com/tiangolo/full-stack-flask-couchbase +* https://github.com/tiangolo/full-stack-flask-couchdb -Ces mรชmes gรฉnรฉrateurs full-stack ont servi de base aux [Gรฉnรฉrateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=\_blank}. +Ces mรชmes gรฉnรฉrateurs full-stack ont servi de base aux [Gรฉnรฉrateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=_blank}. /// info @@ -258,15 +255,15 @@ Gรฉnรฉrer le schรฉma OpenAPI automatiquement, ร  partir du mรชme code qui dรฉfin /// -### NestJS (et Angular) +### NestJS (et Angular) { #nestjs-and-angular } Ce n'est mรชme pas du Python, NestJS est un framework JavaScript (TypeScript) NodeJS inspirรฉ d'Angular. Il rรฉalise quelque chose de similaire ร  ce qui peut รชtre fait avec Flask-apispec. -Il possรจde un systรจme d'injection de dรฉpendances intรฉgrรฉ, inspirรฉ d'Angular 2. Il nรฉcessite de prรฉ-enregistrer les "injectables" (comme tous les autres systรจmes d'injection de dรฉpendances que je connais), donc, cela ajoute ร  la verbositรฉ et ร  la rรฉpรฉtition du code. +Il possรจde un systรจme d'injection de dรฉpendances intรฉgrรฉ, inspirรฉ d'Angular 2. Il nรฉcessite de prรฉ-enregistrer les ยซ injectables ยป (comme tous les autres systรจmes d'injection de dรฉpendances que je connais), donc, cela ajoute ร  la verbositรฉ et ร  la rรฉpรฉtition du code. -Comme les paramรจtres sont dรฉcrits avec des types TypeScript (similaires aux type hints de Python), la prise en charge +Comme les paramรจtres sont dรฉcrits avec des types TypeScript (similaires aux annotations de type de Python), la prise en charge par l'รฉditeur est assez bonne. Mais comme les donnรฉes TypeScript ne sont pas prรฉservรฉes aprรจs la compilation en JavaScript, il ne peut pas compter sur les types pour dรฉfinir la validation, la sรฉrialisation et la documentation en mรชme temps. En raison de cela et de certaines dรฉcisions de conception, pour obtenir la validation, la sรฉrialisation et la gรฉnรฉration automatique de schรฉmas, il est nรฉcessaire d'ajouter des dรฉcorateurs ร  de nombreux endroits. Cela devient donc assez verbeux. @@ -281,7 +278,7 @@ Disposer d'un puissant systรจme d'injection de dรฉpendances. Trouver un moyen de /// -### Sanic +### Sanic { #sanic } C'รฉtait l'un des premiers frameworks Python extrรชmement rapides basรฉs sur `asyncio`. Il a รฉtรฉ conรงu pour รชtre trรจs similaire ร  Flask. @@ -301,14 +298,12 @@ C'est pourquoi **FastAPI** est basรฉ sur Starlette, car il s'agit du framework l /// -### Falcon +### Falcon { #falcon } Falcon est un autre framework Python haute performance, il est conรงu pour รชtre minimal, et est utilisรฉ comme fondation pour d'autres frameworks comme Hug. -Il utilise le standard prรฉcรฉdent pour les frameworks web Python (WSGI) qui est synchrone, donc il ne peut pas gรฉrer les WebSockets et d'autres cas d'utilisation. Nรฉanmoins, il offre de trรจs bonnes performances. - -Il est conรงu pour avoir des fonctions qui reรงoivent deux paramรจtres, une "requรชte" et une "rรฉponse". Ensuite, vous -"lisez" des parties de la requรชte et "รฉcrivez" des parties dans la rรฉponse. En raison de cette conception, il n'est +Il est conรงu pour avoir des fonctions qui reรงoivent deux paramรจtres, une ยซ requรชte ยป et une ยซ rรฉponse ยป. Ensuite, vous +ยซ lisez ยป des parties de la requรชte et ยซ รฉcrivez ยป des parties dans la rรฉponse. En raison de cette conception, il n'est pas possible de dรฉclarer des paramรจtres de requรชte et des corps avec des indications de type Python standard comme paramรจtres de fonction. Ainsi, la validation, la sรฉrialisation et la documentation des donnรฉes doivent รชtre effectuรฉes dans le code, et non pas automatiquement. Ou bien elles doivent รชtre implรฉmentรฉes comme un framework au-dessus de Falcon, comme Hug. Cette mรชme distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste ร  avoir un objet de requรชte et un objet de rรฉponse comme paramรจtres. @@ -323,20 +318,20 @@ Bien que dans FastAPI, il est facultatif, et est utilisรฉ principalement pour d /// -### Molten +### Molten { #molten } J'ai dรฉcouvert Molten lors des premiรจres รฉtapes de dรฉveloppement de **FastAPI**. Et il a des idรฉes assez similaires : -- Basรฉ sur les type hints Python. -- Validation et documentation via ces types. -- Systรจme d'injection de dรฉpendances. +* Basรฉ sur les annotations de type Python. +* Validation et documentation via ces types. +* Systรจme d'injection de dรฉpendances. Il n'utilise pas une librairie tiers de validation, sรฉrialisation et de documentation tel que Pydantic, il utilise son propre systรจme. Ainsi, ces dรฉfinitions de types de donnรฉes ne sont pas rรฉutilisables aussi facilement. -Il nรฉcessite une configuration un peu plus verbeuse. Et comme il est basรฉ sur WSGI (au lieu dASGI), il n'est pas +Il nรฉcessite une configuration un peu plus verbeuse. Et comme il est basรฉ sur WSGI (au lieu d'ASGI), il n'est pas conรงu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic. -Le systรจme d'injection de dรฉpendances exige le prรฉ-enregistrement des dรฉpendances et les dรฉpendances sont rรฉsolues sur la base des types dรฉclarรฉs. Ainsi, il n'est pas possible de dรฉclarer plus d'un "composant" qui fournit un certain type. +Le systรจme d'injection de dรฉpendances exige le prรฉ-enregistrement des dรฉpendances et les dรฉpendances sont rรฉsolues sur la base des types dรฉclarรฉs. Ainsi, il n'est pas possible de dรฉclarer plus d'un ยซ composant ยป qui fournit un certain type. Les routes sont dรฉclarรฉes ร  un seul endroit, en utilisant des fonctions dรฉclarรฉes ร  d'autres endroits (au lieu d'utiliser des dรฉcorateurs qui peuvent รชtre placรฉs juste au-dessus de la fonction qui gรจre l'endpoint). Cette @@ -345,15 +340,15 @@ qui sont relativement fortement couplรฉes. /// check | A inspirรฉ **FastAPI** ร  -Dรฉfinir des validations supplรฉmentaires pour les types de donnรฉes utilisant la valeur "par dรฉfaut" des attributs du modรจle. Ceci amรฉliore le support de l'รฉditeur, et n'รฉtait pas disponible dans Pydantic auparavant. +Dรฉfinir des validations supplรฉmentaires pour les types de donnรฉes utilisant la valeur ยซ par dรฉfaut ยป des attributs du modรจle. Ceci amรฉliore le support de l'รฉditeur, et n'รฉtait pas disponible dans Pydantic auparavant. Cela a en fait inspirรฉ la mise ร  jour de certaines parties de Pydantic, afin de supporter le mรชme style de dรฉclaration de validation (toute cette fonctionnalitรฉ est maintenant dรฉjร  disponible dans Pydantic). /// -### Hug +### Hug { #hug } -Hug a รฉtรฉ l'un des premiers frameworks ร  implรฉmenter la dรฉclaration des types de paramรจtres d'API en utilisant les type hints Python. C'รฉtait une excellente idรฉe qui a inspirรฉ d'autres outils ร  faire de mรชme. +Hug a รฉtรฉ l'un des premiers frameworks ร  implรฉmenter la dรฉclaration des types de paramรจtres d'API en utilisant les annotations de type Python. C'รฉtait une excellente idรฉe qui a inspirรฉ d'autres outils ร  faire de mรชme. Il utilisait des types personnalisรฉs dans ses dรฉclarations au lieu des types Python standard, mais c'รฉtait tout de mรชme un รฉnorme pas en avant. @@ -372,28 +367,28 @@ Hug a รฉtรฉ crรฉรฉ par Timothy Crosley, le crรฉateur de APIStar (<= 0.5) +### APIStar (<= 0.5) { #apistar-0-5 } Juste avant de dรฉcider de dรฉvelopper **FastAPI**, j'ai trouvรฉ le serveur **APIStar**. Il contenait presque tout ce que je recherchais et avait un beau design. -C'รฉtait l'une des premiรจres implรฉmentations d'un framework utilisant les type hints Python pour dรฉclarer les paramรจtres +C'รฉtait l'une des premiรจres implรฉmentations d'un framework utilisant les annotations de type Python pour dรฉclarer les paramรจtres et les requรชtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvรฉ plus ou moins en mรชme temps que Hug. Mais APIStar utilisait le standard OpenAPI. -Il disposait de la validation automatique, sรฉrialisation des donnรฉes et d'une gรฉnรฉration de schรฉma OpenAPI basรฉe sur les mรชmes type hints ร  plusieurs endroits. +Il disposait de la validation automatique, sรฉrialisation des donnรฉes et d'une gรฉnรฉration de schรฉma OpenAPI basรฉe sur les mรชmes annotations de type ร  plusieurs endroits. -La dรฉfinition du schรฉma de corps de requรชte n'utilisait pas les mรชmes type hints Python que Pydantic, il รฉtait un peu plus proche de Marshmallow, donc le support de l'รฉditeur n'รฉtait pas aussi bon, mais APIStar รฉtait quand mรชme la meilleure option disponible. +La dรฉfinition du schรฉma de corps de requรชte n'utilisait pas les mรชmes annotations de type Python que Pydantic, il รฉtait un peu plus proche de Marshmallow, donc le support de l'รฉditeur n'รฉtait pas aussi bon, mais APIStar รฉtait quand mรชme la meilleure option disponible. Il avait les meilleures performances d'aprรจs les benchmarks de l'รฉpoque (seulement surpassรฉ par Starlette). @@ -429,20 +424,20 @@ Et aprรจs avoir longtemps cherchรฉ un framework similaire et testรฉ de nombreuse Puis APIStar a cessรฉ d'exister en tant que serveur et Starlette a รฉtรฉ crรฉรฉ, et a constituรฉ une meilleure base pour un tel systรจme. Ce fut l'inspiration finale pour construire **FastAPI**. -Je considรจre **FastAPI** comme un "successeur spirituel" d'APIStar, tout en amรฉliorant et en augmentant les fonctionnalitรฉs, le systรจme de typage et d'autres parties, sur la base des enseignements tirรฉs de tous ces outils prรฉcรฉdents. +Je considรจre **FastAPI** comme un ยซ successeur spirituel ยป d'APIStar, tout en amรฉliorant et en augmentant les fonctionnalitรฉs, le systรจme de typage et d'autres parties, sur la base des enseignements tirรฉs de tous ces outils prรฉcรฉdents. /// -## Utilisรฉs par **FastAPI** +## Utilisรฉs par **FastAPI** { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } -Pydantic est une bibliothรจque permettant de dรฉfinir la validation, la sรฉrialisation et la documentation des donnรฉes (ร  l'aide de JSON Schema) en se basant sur les Python type hints. +Pydantic est une bibliothรจque permettant de dรฉfinir la validation, la sรฉrialisation et la documentation des donnรฉes (ร  l'aide de JSON Schema) en se basant sur les annotations de type Python. Cela le rend extrรชmement intuitif. Il est comparable ร  Marshmallow. Bien qu'il soit plus rapide que Marshmallow dans les benchmarks. Et comme il est -basรฉ sur les mรชmes type hints Python, le support de l'รฉditeur est grand. +basรฉ sur les mรชmes annotations de type Python, le support de l'รฉditeur est grand. /// check | **FastAPI** l'utilise pour @@ -452,9 +447,9 @@ Gรฉrer toute la validation des donnรฉes, leur sรฉrialisation et la documentation /// -### Starlette +### Starlette { #starlette } -Starlette est un framework/toolkit lรฉger ASGI, qui est idรฉal pour construire des services asyncio performants. +Starlette est un framework/toolkit lรฉger ASGI, qui est idรฉal pour construire des services asyncio performants. Il est trรจs simple et intuitif. Il est conรงu pour รชtre facilement extensible et avoir des composants modulaires. @@ -462,29 +457,28 @@ Il offre : - Des performances vraiment impressionnantes. - Le support des WebSockets. -- Le support de GraphQL. - Les tรขches d'arriรจre-plan. - Les รฉvรฉnements de dรฉmarrage et d'arrรชt. -- Un client de test basรฉ sur request. +- Un client de test basรฉ sur HTTPX. - CORS, GZip, fichiers statiques, streaming des rรฉponses. - Le support des sessions et des cookies. - Une couverture de test ร  100 %. - 100 % de la base de code avec des annotations de type. -- Zรฉro forte dรฉpendance ร  d'autres packages. +- Peu de dรฉpendances strictes. Starlette est actuellement le framework Python le plus rapide testรฉ. Seulement dรฉpassรฉ par Uvicorn, qui n'est pas un framework, mais un serveur. -Starlette fournit toutes les fonctionnalitรฉs de base d'un micro-framework web. +Starlette fournit toutes les fonctionnalitรฉs de base d'un microโ€‘framework web. Mais il ne fournit pas de validation automatique des donnรฉes, de sรฉrialisation ou de documentation. -C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basรฉ sur les type hints Python (en utilisant Pydantic). Cela, plus le systรจme d'injection de dรฉpendances, les utilitaires de sรฉcuritรฉ, la gรฉnรฉration de schรฉmas OpenAPI, etc. +C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basรฉ sur les annotations de type Python (en utilisant Pydantic). Cela, plus le systรจme d'injection de dรฉpendances, les utilitaires de sรฉcuritรฉ, la gรฉnรฉration de schรฉmas OpenAPI, etc. /// note | Dรฉtails techniques -ASGI est une nouvelle "norme" dรฉveloppรฉe par les membres de l'รฉquipe principale de Django. Il ne s'agit pas encore d'une "norme Python" (un PEP), bien qu'ils soient en train de le faire. +ASGI est une nouvelle ยซ norme ยป dรฉveloppรฉe par les membres de l'รฉquipe principale de Django. Il ne s'agit pas encore d'une ยซ norme Python ยป (un PEP), bien qu'ils soient en train de le faire. -Nรฉanmoins, il est dรฉjร  utilisรฉ comme "standard" par plusieurs outils. Cela amรฉliore grandement l'interopรฉrabilitรฉ, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`. +Nรฉanmoins, il est dรฉjร  utilisรฉ comme ยซ standard ยป par plusieurs outils. Cela amรฉliore grandement l'interopรฉrabilitรฉ, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`. /// @@ -498,7 +492,7 @@ Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire direct /// -### Uvicorn +### Uvicorn { #uvicorn } Uvicorn est un serveur ASGI rapide comme l'รฉclair, basรฉ sur uvloop et httptools. @@ -511,12 +505,12 @@ C'est le serveur recommandรฉ pour Starlette et **FastAPI**. Le serveur web principal pour exรฉcuter les applications **FastAPI**. -Vous pouvez le combiner avec Gunicorn, pour avoir un serveur multi-processus asynchrone. +Vous pouvez รฉgalement utiliser l'option de ligne de commande `--workers` pour avoir un serveur multiโ€‘processus asynchrone. Pour plus de dรฉtails, consultez la section [Dรฉploiement](deployment/index.md){.internal-link target=_blank}. /// -## Benchmarks et vitesse +## Benchmarks et vitesse { #benchmarks-and-speed } -Pour comprendre, comparer et voir la diffรฉrence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=\_blank}. +Pour comprendre, comparer et voir la diffรฉrence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=_blank}. diff --git a/docs/fr/docs/async.md b/docs/fr/docs/async.md index 1437ae5176..72923e03b0 100644 --- a/docs/fr/docs/async.md +++ b/docs/fr/docs/async.md @@ -1,17 +1,18 @@ -# Concurrence et les mots-clรฉs async et await +# Concurrence et async / await { #concurrency-and-async-await } -Cette page vise ร  fournir des dรฉtails sur la syntaxe `async def` pour les *fonctions de chemins* et quelques rappels sur le code asynchrone, la concurrence et le parallรฉlisme. +Dรฉtails sur la syntaxe `async def` pour les *fonctions de chemin d'accรจs* et quelques rappels sur le code asynchrone, la concurrence et le parallรฉlisme. -## Vous รชtes pressรฉs ? +## Vous รชtes pressรฉs ? { #in-a-hurry } -TL;DR : +TL;DR : Si vous utilisez des bibliothรจques tierces qui nรฉcessitent d'รชtre appelรฉes avec `await`, telles que : ```Python results = await some_library() ``` -Alors, dรฉclarez vos *fonctions de chemins* avec `async def` comme ceci : + +Alors, dรฉclarez vos *fonctions de chemin d'accรจs* avec `async def` comme ceci : ```Python hl_lines="2" @app.get('/') @@ -20,7 +21,7 @@ async def read_results(): return results ``` -/// note +/// note | Remarque Vous pouvez uniquement utiliser `await` dans les fonctions crรฉรฉes avec `async def`. @@ -28,7 +29,7 @@ Vous pouvez uniquement utiliser `await` dans les fonctions crรฉรฉes avec `async --- -Si vous utilisez une bibliothรจque externe qui communique avec quelque chose (une BDD, une API, un systรจme de fichiers, etc.) et qui ne supporte pas l'utilisation d'`await` (ce qui est actuellement le cas pour la majoritรฉ des bibliothรจques de BDD), alors dรฉclarez vos *fonctions de chemin* normalement, avec le classique `def`, comme ceci : +Si vous utilisez une bibliothรจque externe qui communique avec quelque chose (une base de donnรฉes, une API, le systรจme de fichiers, etc.) et qui ne supporte pas l'utilisation d'`await` (ce qui est actuellement le cas pour la majoritรฉ des bibliothรจques de base de donnรฉes), alors dรฉclarez vos *fonctions de chemin d'accรจs* normalement, avec le classique `def`, comme ceci : ```Python hl_lines="2" @app.get('/') @@ -39,7 +40,7 @@ def results(): --- -Si votre application n'a pas ร  communiquer avec une bibliothรจque externe et pas ร  attendre de rรฉponse, utilisez `async def`. +Si votre application n'a pas ร  communiquer avec une autre chose et ร  attendre sa rรฉponse, utilisez `async def`, mรชme si vous n'avez pas besoin d'utiliser `await` ร  l'intรฉrieur. --- @@ -47,15 +48,15 @@ Si vous ne savez pas, utilisez seulement `def` comme vous le feriez habituelleme --- -**Note** : vous pouvez mรฉlanger `def` et `async def` dans vos *fonctions de chemin* autant que nรฉcessaire, **FastAPI** saura faire ce qu'il faut avec. +Note : vous pouvez mรฉlanger `def` et `async def` dans vos *fonctions de chemin d'accรจs* autant que nรฉcessaire, et dรฉfinir chacune avec lโ€™option la plus adaptรฉe pour vous. FastAPI fera ce qu'il faut avec elles. -Au final, peu importe le cas parmi ceux ci-dessus, **FastAPI** fonctionnera de maniรจre asynchrone et sera extrรชmement rapide. +Au final, peu importe le cas parmi ceux ci-dessus, FastAPI fonctionnera de maniรจre asynchrone et sera extrรชmement rapide. -Mais si vous suivez bien les instructions ci-dessus, alors **FastAPI** pourra effectuer quelques optimisations et ainsi amรฉliorer les performances. +Mais si vous suivez bien les instructions ci-dessus, il pourra effectuer quelques optimisations et ainsi amรฉliorer les performances. -## Dรฉtails techniques +## Dรฉtails techniques { #technical-details } -Les versions modernes de Python supportent le **code asynchrone** grรขce aux **"coroutines"** avec les syntaxes **`async` et `await`**. +Les versions modernes de Python supportent le **code asynchrone** grรขce aux **ยซ coroutines ยป** avec les syntaxes **`async` et `await`**. Analysons les diffรฉrentes parties de cette phrase dans les sections suivantes : @@ -63,46 +64,46 @@ Analysons les diffรฉrentes parties de cette phrase dans les sections suivantes : * **`async` et `await`** * **Coroutines** -## Code asynchrone +## Code asynchrone { #asynchronous-code } -Faire du code asynchrone signifie que le langage ๐Ÿ’ฌ est capable de dire ร  l'ordinateur / au programme ๐Ÿค– qu'ร  un moment du code, il ๐Ÿค– devra attendre que *quelque chose d'autre* se termine autre part. Disons que ce *quelque chose d'autre* est appelรฉ "fichier-lent" ๐Ÿ“. +Faire du code asynchrone signifie que le langage ๐Ÿ’ฌ est capable de dire ร  l'ordinateur / au programme ๐Ÿค– qu'ร  un moment du code, il ๐Ÿค– devra attendre que *quelque chose d'autre* se termine autre part. Disons que ce *quelque chose d'autre* est appelรฉ ยซ slow-file ยป ๐Ÿ“. -Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tรขches, pendant que "fichier-lent" ๐Ÿ“ se termine. +Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tรขches, pendant que ยซ slow-file ยป ๐Ÿ“ se termine. Ensuite l'ordinateur / le programme ๐Ÿค– reviendra ร  chaque fois qu'il en a la chance que ce soit parce qu'il attend ร  nouveau, ou car il ๐Ÿค– a fini tout le travail qu'il avait ร  faire. Il ๐Ÿค– regardera donc si les tรขches qu'il attend ont terminรฉ d'รชtre effectuรฉes. -Ensuite, il ๐Ÿค– prendra la premiรจre tรขche ร  finir (disons, notre "fichier-lent" ๐Ÿ“) et continuera ร  faire avec cette derniรจre ce qu'il รฉtait censรฉ. +Ensuite, il ๐Ÿค– prendra la premiรจre tรขche ร  finir (disons, notre ยซ slow-file ยป ๐Ÿ“) et continuera ร  faire avec cette derniรจre ce qu'il รฉtait censรฉ. -Ce "attendre quelque chose d'autre" fait gรฉnรฉralement rรฉfรฉrence ร  des opรฉrations I/O qui sont relativement "lentes" (comparรฉes ร  la vitesse du processeur et de la mรฉmoire RAM) telles qu'attendre que : +Ce ยซ attendre quelque chose d'autre ยป fait gรฉnรฉralement rรฉfรฉrence ร  des opรฉrations I/O qui sont relativement ยซ lentes ยป (comparรฉes ร  la vitesse du processeur et de la mรฉmoire RAM) telles qu'attendre que : * de la donnรฉe soit envoyรฉe par le client ร  travers le rรฉseau * de la donnรฉe envoyรฉe depuis votre programme soit reรงue par le client ร  travers le rรฉseau * le contenu d'un fichier sur le disque soit lu par le systรจme et passรฉ ร  votre programme * le contenu que votre programme a passรฉ au systรจme soit รฉcrit sur le disque * une opรฉration effectuรฉe ร  distance par une API se termine -* une opรฉration en BDD se termine -* une requรชte ร  une BDD renvoie un rรฉsultat +* une opรฉration en base de donnรฉes se termine +* une requรชte ร  une base de donnรฉes renvoie un rรฉsultat * etc. -Le temps d'exรฉcution รฉtant consommรฉ majoritairement par l'attente d'opรฉrations I/O on appelle ceci des opรฉrations "I/O bound". +Le temps d'exรฉcution รฉtant consommรฉ majoritairement par l'attente d'opรฉrations I/O, on appelle ceci des opรฉrations ยซ I/O bound ยป. -Ce concept se nomme l'"asynchronisme" car l'ordinateur / le programme n'a pas besoin d'รชtre "synchronisรฉ" avec la tรขche, attendant le moment exact oรน cette derniรจre se terminera en ne faisant rien, pour รชtre capable de rรฉcupรฉrer le rรฉsultat de la tรขche et l'utiliser dans la suite des opรฉrations. +Ce concept se nomme ยซ asynchrone ยป car l'ordinateur / le programme n'a pas besoin d'รชtre ยซ synchronisรฉ ยป avec la tรขche, attendant le moment exact oรน cette derniรจre se terminera en ne faisant rien, pour รชtre capable de rรฉcupรฉrer le rรฉsultat de la tรขche et l'utiliser dans la suite des opรฉrations. -ร€ la place, en รฉtant "asynchrone", une fois terminรฉe, une tรขche peut lรฉgรจrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il รฉtait en train de faire, et revienne rรฉcupรฉrer le rรฉsultat. +ร€ la place, en รฉtant ยซ asynchrone ยป, une fois terminรฉe, une tรขche peut lรฉgรจrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il รฉtait en train de faire, et revienne rรฉcupรฉrer le rรฉsultat. -Pour parler de tรขches "synchrones" (en opposition ร  "asynchrones"), on utilise souvent le terme "sรฉquentiel", car l'ordinateur / le programme va effectuer toutes les รฉtapes d'une tรขche sรฉquentiellement avant de passer ร  une autre tรขche, mรชme si ces รฉtapes impliquent de l'attente. +Pour parler de tรขches ยซ synchrones ยป (en opposition ร  ยซ asynchrones ยป), on utilise souvent le terme ยซ sรฉquentiel ยป, car l'ordinateur / le programme va effectuer toutes les รฉtapes d'une tรขche sรฉquentiellement avant de passer ร  une autre tรขche, mรชme si ces รฉtapes impliquent de l'attente. -### Concurrence et Burgers +### Concurrence et Burgers { #concurrency-and-burgers } -L'idรฉe de code **asynchrone** dรฉcrite ci-dessus est parfois aussi appelรฉe **"concurrence"**. Ce qui est diffรฉrent du **"parallรฉlisme"**. +L'idรฉe de code **asynchrone** dรฉcrite ci-dessus est parfois aussi appelรฉe **ยซ concurrence ยป**. Ce qui est diffรฉrent du **ยซ parallรฉlisme ยป**. -La **concurrence** et le **parallรฉlisme** sont tous deux liรฉs ร  l'idรฉe de "diffรฉrentes choses arrivant plus ou moins au mรชme moment". +La **concurrence** et le **parallรฉlisme** sont tous deux liรฉs ร  l'idรฉe de ยซ diffรฉrentes choses arrivant plus ou moins au mรชme moment ยป. Mais les dรฉtails entre la **concurrence** et le **parallรฉlisme** diffรจrent sur de nombreux points. Pour expliquer la diffรฉrence, voici une histoire de burgers : -#### Burgers concurrents +### Burgers concurrents { #concurrent-burgers } Vous amenez votre crush ๐Ÿ˜ dans votre fast food ๐Ÿ” favori, et faites la queue pendant que le serveur ๐Ÿ’ prend les commandes des personnes devant vous. @@ -122,13 +123,13 @@ Le serveur ๐Ÿ’ vous donne le numรฉro assignรฉ ร  votre commande. -Pendant que vous attendez, vous allez choisir une table avec votre crush ๐Ÿ˜, vous discutez avec votre crush ๐Ÿ˜ pendant un long moment (les burgers รฉtant "magnifiques" ils sont trรจs longs ร  prรฉparer โœจ๐Ÿ”โœจ). +Pendant que vous attendez, vous allez choisir une table avec votre crush ๐Ÿ˜, vous discutez avec votre crush ๐Ÿ˜ pendant un long moment (les burgers รฉtant ยซ magnifiques ยป ils sont trรจs longs ร  prรฉparer โœจ๐Ÿ”โœจ). Pendant que vous รชtes assis ร  table, en attendant que les burgers ๐Ÿ” soient prรชts, vous pouvez passer ce temps ร  admirer ร  quel point votre crush ๐Ÿ˜ est gรฉniale, mignonne et intelligente โœจ๐Ÿ˜โœจ. -Pendant que vous discutez avec votre crush ๐Ÿ˜, de temps en temps vous jetez un coup d'oeil au nombre affichรฉ au-dessus du comptoir pour savoir si c'est ร  votre tour d'รชtre servis. +Pendant que vous discutez avec votre crush ๐Ÿ˜, de temps en temps vous jetez un coup dโ€™ล“il au nombre affichรฉ au-dessus du comptoir pour savoir si c'est ร  votre tour d'รชtre servis. Jusqu'au moment oรน c'est (enfin) votre tour. Vous allez au comptoir, rรฉcupรฉrez vos burgers ๐Ÿ” et revenez ร  votre table. @@ -148,23 +149,23 @@ Illustrations proposรฉes par @@ -212,7 +213,7 @@ Illustrations proposรฉes par (tout รงa grรขce ร  Starlette). +Et comme on peut avoir du parallรฉlisme et de l'asynchronicitรฉ en mรชme temps, on obtient des performances plus hautes que la plupart des frameworks NodeJS testรฉs et รฉgales ร  celles du Go, qui est un langage compilรฉ plus proche du C (tout รงa grรขce ร  Starlette). -### Est-ce que la concurrence est mieux que le parallรฉlisme ? +### Est-ce que la concurrence est mieux que le parallรฉlisme ? { #is-concurrency-better-than-parallelism } Nope ! C'est รงa la morale de l'histoire. @@ -276,11 +277,11 @@ Mais dans ce cas, si pouviez amener 8 ex-serveurs/cuisiniers/devenus-nettoyeurs Dans ce scรฉnario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail. -Et comme la plupart du temps d'exรฉcution est pris par du "vrai" travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problรจmes dits "CPU bound". +Et comme la plupart du temps d'exรฉcution est pris par du ยซ vrai ยป travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problรจmes dits ยซ CPU bound ยป. --- -Des exemples communs d'opรฉrations "CPU bounds" sont les procรฉdรฉs qui requiรจrent des traitements mathรฉmatiques complexes. +Des exemples communs d'opรฉrations ยซ CPU bound ยป sont les procรฉdรฉs qui requiรจrent des traitements mathรฉmatiques complexes. Par exemple : @@ -289,19 +290,19 @@ Par exemple : * L'apprentissage automatique (ou **Machine Learning**) : cela nรฉcessite de nombreuses multiplications de matrices et vecteurs. Imaginez une รฉnorme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au mรชme moment. * L'apprentissage profond (ou **Deep Learning**) : est un sous-domaine du **Machine Learning**, donc les mรชmes raisons s'appliquent. Avec la diffรฉrence qu'il n'y a pas une unique feuille de calcul de nombres ร  multiplier, mais une รฉnorme quantitรฉ d'entre elles, et dans de nombreux cas, on utilise un processeur spรฉcial pour construire et / ou utiliser ces modรจles. -### Concurrence + Parallรฉlisme : Web + Machine Learning +### Concurrence + Parallรฉlisme : Web + Machine Learning { #concurrency-parallelism-web-machine-learning } Avec **FastAPI** vous pouvez bรฉnรฉficier de la concurrence qui est trรจs courante en dรฉveloppement web (c'est l'attrait principal de NodeJS). -Mais vous pouvez aussi profiter du parallรฉlisme et multiprocessing afin de gรฉrer des charges **CPU bound** qui sont rรฉcurrentes dans les systรจmes de *Machine Learning*. +Mais vous pouvez aussi profiter du parallรฉlisme et du multiprocessing (plusieurs processus s'exรฉcutant en parallรจle) afin de gรฉrer des charges **CPU bound** qui sont rรฉcurrentes dans les systรจmes de *Machine Learning*. ร‡a, ajoutรฉ au fait que Python soit le langage le plus populaire pour la **Data Science**, le **Machine Learning** et surtout le **Deep Learning**, font de **FastAPI** un trรจs bon choix pour les APIs et applications de **Data Science** / **Machine Learning**. Pour comprendre comment mettre en place ce parallรฉlisme en production, allez lire la section [Dรฉploiement](deployment/index.md){.internal-link target=_blank}. -## `async` et `await` +## `async` et `await` { #async-and-await } -Les versions modernes de Python ont une maniรจre trรจs intuitive de dรฉfinir le code asynchrone, tout en gardant une apparence de code "sรฉquentiel" classique en laissant Python faire l'attente pour vous au bon moment. +Les versions modernes de Python ont une maniรจre trรจs intuitive de dรฉfinir le code asynchrone, tout en gardant une apparence de code ยซ sรฉquentiel ยป classique en laissant Python faire l'attente pour vous au bon moment. Pour une opรฉration qui nรฉcessite de l'attente avant de donner un rรฉsultat et qui supporte ces nouvelles fonctionnalitรฉs Python, vous pouvez l'utiliser comme tel : @@ -319,12 +320,12 @@ async def get_burgers(number: int): return burgers ``` -...et non `def` : +... et non `def` : ```Python hl_lines="2" # Ceci n'est pas asynchrone def get_sequential_burgers(number: int): - # Opรฉrations asynchrones pour crรฉer les burgers + # Opรฉrations sรฉquentielles pour crรฉer les burgers return burgers ``` @@ -339,7 +340,7 @@ burgers = get_burgers(2) --- -Donc, si vous utilisez une bibliothรจque qui nรฉcessite que ses fonctions soient appelรฉes avec `await`, vous devez dรฉfinir la *fonction de chemin* en utilisant `async def` comme dans : +Donc, si vous utilisez une bibliothรจque qui nรฉcessite que ses fonctions soient appelรฉes avec `await`, vous devez dรฉfinir la *fonction de chemin d'accรจs* en utilisant `async def` comme dans : ```Python hl_lines="2-3" @app.get('/burgers') @@ -348,52 +349,61 @@ async def read_burgers(): return burgers ``` -### Plus de dรฉtails techniques +### Plus de dรฉtails techniques { #more-technical-details } Vous avez donc compris que `await` peut seulement รชtre utilisรฉ dans des fonctions dรฉfinies avec `async def`. Mais en mรชme temps, les fonctions dรฉfinies avec `async def` doivent รชtre appelรฉes avec `await` et donc dans des fonctions dรฉfinies elles aussi avec `async def`. -Vous avez donc remarquรฉ ce paradoxe d'oeuf et de la poule, comment appelle-t-on la premiรจre fonction `async` ? +Vous avez donc remarquรฉ ce paradoxe d'ล“uf et de la poule, comment appelle-t-on la premiรจre fonction `async` ? + +Si vous utilisez **FastAPI**, pas besoin de vous en inquiรฉter, car cette ยซ premiรจre ยป fonction sera votre *fonction de chemin d'accรจs* ; et **FastAPI** saura comment arriver au rรฉsultat attendu. + +Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez รฉgalement le faire. -Si vous utilisez **FastAPI**, pas besoin de vous en inquiรฉter, car cette "premiรจre" fonction sera votre *fonction de chemin* ; et **FastAPI** saura comment arriver au rรฉsultat attendu. +### ร‰crire votre propre code async { #write-your-own-async-code } -Mais si vous utilisez `async` / `await` sans **FastAPI**, allez jetez un coup d'oeil ร  la documentation officielle de Python. +Starlette (et **FastAPI**) sโ€™appuie sur AnyIO, ce qui le rend compatible ร  la fois avec la bibliothรจque standard asyncio de Python et avec Trio. -### Autres formes de code asynchrone +En particulier, vous pouvez utiliser directement AnyIO pour vos cas dโ€™usage de concurrence avancรฉs qui nรฉcessitent des schรฉmas plus รฉlaborรฉs dans votre propre code. + +Et mรชme si vous nโ€™utilisiez pas FastAPI, vous pourriez aussi รฉcrire vos propres applications async avec AnyIO pour une grande compatibilitรฉ et pour bรฉnรฉficier de ses avantages (par ex. la ยซ structured concurrency ยป). + +Jโ€™ai crรฉรฉ une autre bibliothรจque au-dessus dโ€™AnyIO, comme une fine surcouche, pour amรฉliorer un peu les annotations de type et obtenir une meilleure **autocomplรฉtion**, des **erreurs en ligne**, etc. Elle propose รฉgalement une introduction et un tutoriel accessibles pour vous aider ร  **comprendre** et รฉcrire **votre propre code async** : Asyncer. Elle sera particuliรจrement utile si vous devez **combiner du code async avec du code classique** (bloquant/synchrone). + +### Autres formes de code asynchrone { #other-forms-of-asynchronous-code } L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage. Mais cela rend la programmation asynchrone bien plus simple. -Cette mรชme syntaxe (ou presque) รฉtait aussi incluse dans les versions modernes de Javascript (dans les versions navigateur et NodeJS). +Cette mรชme syntaxe (ou presque) a aussi รฉtรฉ incluse rรฉcemment dans les versions modernes de JavaScript (dans les navigateurs et NodeJS). Mais avant รงa, gรฉrer du code asynchrone รฉtait bien plus complexe et difficile. -Dans les versions prรฉcรฉdentes de Python, vous auriez utilisรฉ des *threads* ou Gevent. Mais le code aurait รฉtรฉ bien plus difficile ร  comprendre, dรฉbugger, et concevoir. - -Dans les versions prรฉcรฉdentes de Javascript NodeJS / Navigateur, vous auriez utilisรฉ des "callbacks". Menant potentiellement ร  ce que l'on appelle le "callback hell". +Dans les versions prรฉcรฉdentes de Python, vous auriez utilisรฉ des threads ou Gevent. Mais le code aurait รฉtรฉ bien plus difficile ร  comprendre, dรฉbugger, et concevoir. +Dans les versions prรฉcรฉdentes de JavaScript cรดtรฉ navigateur / NodeJS, vous auriez utilisรฉ des ยซ callbacks ยป. Menant potentiellement ร  ce que l'on appelle le ยซ callback hell ยป. -## Coroutines +## Coroutines { #coroutines } -**Coroutine** est juste un terme รฉlaborรฉ pour dรฉsigner ce qui est retournรฉ par une fonction dรฉfinie avec `async def`. Python sait que c'est comme une fonction classique qui va dรฉmarrer ร  un moment et terminer ร  un autre, mais qu'elle peut aussi รชtre mise en pause โธ, du moment qu'il y a un `await` dans son contenu. +ยซ Coroutine ยป est juste un terme รฉlaborรฉ pour dรฉsigner ce qui est retournรฉ par une fonction dรฉfinie avec `async def`. Python sait que c'est comme une fonction classique qui va dรฉmarrer ร  un moment et terminer ร  un autre, mais qu'elle peut aussi รชtre mise en pause โธ, du moment qu'il y a un `await` dans son contenu. -Mais toutes ces fonctionnalitรฉs d'utilisation de code asynchrone avec `async` et `await` sont souvent rรฉsumรฉes comme l'utilisation des *coroutines*. On peut comparer cela ร  la principale fonctionnalitรฉ clรฉ de Go, les "Goroutines". +Mais toutes ces fonctionnalitรฉs d'utilisation de code asynchrone avec `async` et `await` sont souvent rรฉsumรฉes comme l'utilisation des ยซ coroutines ยป. On peut comparer cela ร  la principale fonctionnalitรฉ clรฉ de Go, les ยซ Goroutines ยป. -## Conclusion +## Conclusion { #conclusion } Reprenons la phrase du dรฉbut de la page : -> Les versions modernes de Python supportent le **code asynchrone** grรขce aux **"coroutines"** avec les syntaxes **`async` et `await`**. +> Les versions modernes de Python supportent le **code asynchrone** grรขce aux **ยซ coroutines ยป** avec les syntaxes **`async` et `await`**. Ceci devrait รชtre plus comprรฉhensible dรฉsormais. โœจ -Tout ceci est donc ce qui donne sa force ร  **FastAPI** (ร  travers Starlette) et lui permet d'avoir des performances aussi impressionnantes. +Tout ceci est donc ce qui donne sa force ร  FastAPI (ร  travers Starlette) et lui permet d'avoir une performance aussi impressionnante. -## Dรฉtails trรจs techniques +## Dรฉtails trรจs techniques { #very-technical-details } -/// warning | Attention ! +/// warning | Alertes Vous pouvez probablement ignorer cela. @@ -403,32 +413,32 @@ Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloqu /// -### Fonctions de chemin +### Fonctions de chemin d'accรจs { #path-operation-functions } -Quand vous dรฉclarez une *fonction de chemin* avec un `def` normal et non `async def`, elle est exรฉcutรฉe dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutรดt que d'รชtre appelรฉe directement (car cela bloquerait le serveur). +Quand vous dรฉclarez une *fonction de chemin d'accรจs* avec un `def` normal et non `async def`, elle est exรฉcutรฉe dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutรดt que d'รชtre appelรฉe directement (car cela bloquerait le serveur). -Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la faรงon dรฉcrite ci-dessus et que vous รชtes habituรฉs ร  dรฉfinir des *fonctions de chemin* basiques avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutรดt contraire. Dans ces cas-lร , il vaut mieux utiliser `async def` ร  moins que votre *fonction de chemin* utilise du code qui effectue des opรฉrations I/O bloquantes. +Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la faรงon dรฉcrite ci-dessus et que vous รชtes habituรฉ ร  dรฉfinir des *fonctions de chemin d'accรจs* basiques et purement calculatoires avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutรดt contraire. Dans ces cas-lร , il vaut mieux utiliser `async def` ร  moins que votre *fonction de chemin d'accรจs* utilise du code qui effectue des opรฉrations I/O bloquantes. Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de mรชme [plus rapide](index.md#performance){.internal-link target=_blank} que (ou au moins de vitesse รฉgale ร ) votre framework prรฉcรฉdent. -### Dรฉpendances +### Dรฉpendances { #dependencies } -La mรชme chose s'applique aux dรฉpendances. Si une dรฉpendance est dรฉfinie avec `def` plutรดt que `async def`, elle est exรฉcutรฉe dans la threadpool externe. +La mรชme chose s'applique aux [dรฉpendances](tutorial/dependencies/index.md){.internal-link target=_blank}. Si une dรฉpendance est dรฉfinie avec `def` plutรดt que `async def`, elle est exรฉcutรฉe dans la threadpool externe. -### Sous-dรฉpendances +### Sous-dรฉpendances { #sub-dependencies } -Vous pouvez avoir de multiples dรฉpendances et sous-dรฉpendances dรฉpendant les unes des autres (en tant que paramรจtres de la dรฉfinition de la *fonction de chemin*), certaines crรฉรฉes avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles dรฉfinies avec un simple `def` seraient exรฉcutรฉes sur un thread externe (venant de la threadpool) plutรดt que d'รชtre "attendues". +Vous pouvez avoir de multiples dรฉpendances et [sous-dรฉpendances](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} dรฉpendant les unes des autres (en tant que paramรจtres de la dรฉfinition de la *fonction de chemin d'accรจs*), certaines crรฉรฉes avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles dรฉfinies avec un simple `def` seraient exรฉcutรฉes sur un thread externe (venant de la threadpool) plutรดt que d'รชtre ยซ attendues ยป. -### Autres fonctions utilitaires +### Autres fonctions utilitaires { #other-utility-functions } -Toute autre fonction utilitaire que vous appelez directement peut รชtre crรฉรฉe avec un classique `def` ou avec `async def` et **FastAPI** n'aura pas d'impact sur la faรงon dont vous l'appelez. +Toute autre fonction utilitaire que vous appelez directement peut รชtre crรฉรฉe avec un classique `def` ou avec `async def` et FastAPI n'aura pas d'impact sur la faรงon dont vous l'appelez. -Contrairement aux fonctions que **FastAPI** appelle pour vous : les *fonctions de chemin* et dรฉpendances. +Contrairement aux fonctions que FastAPI appelle pour vous : les *fonctions de chemin d'accรจs* et dรฉpendances. -Si votre fonction utilitaire est une fonction classique dรฉfinie avec `def`, elle sera appelรฉe directement (telle qu'รฉcrite dans votre code), pas dans une threadpool, si la fonction est dรฉfinie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer ร  la suite du code. +Si votre fonction utilitaire est une fonction classique dรฉfinie avec `def`, elle sera appelรฉe directement (telle qu'รฉcrite dans votre code), pas dans une threadpool ; si la fonction est dรฉfinie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer ร  la suite du code. --- Encore une fois, ce sont des dรฉtails trรจs techniques qui peuvent รชtre utiles si vous venez ici les chercher. -Sinon, les instructions de la section Vous รชtes pressรฉs ? ci-dessus sont largement suffisantes. +Sinon, les instructions de la section Vous รชtes pressรฉs ? ci-dessus sont largement suffisantes. diff --git a/docs/fr/docs/deployment/cloud.md b/docs/fr/docs/deployment/cloud.md new file mode 100644 index 0000000000..798a72a746 --- /dev/null +++ b/docs/fr/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# Dรฉployer FastAPI sur des fournisseurs cloud { #deploy-fastapi-on-cloud-providers } + +Vous pouvez utiliser pratiquement n'importe quel fournisseur cloud pour dรฉployer votre application FastAPI. + +Dans la plupart des cas, les principaux fournisseurs cloud proposent des guides pour dรฉployer FastAPI avec leurs services. + +## FastAPI Cloud { #fastapi-cloud } + +**FastAPI Cloud** est crรฉรฉe par le mรชme auteur et l'รฉquipe ร  l'origine de **FastAPI**. + +Elle simplifie le processus de **crรฉation**, de **dรฉploiement** et **d'accรจs** ร  une API avec un effort minimal. + +Elle apporte la mรชme **expรฉrience dรฉveloppeur** que celle de la crรฉation d'applications avec FastAPI au **dรฉploiement** de celles-ci dans le cloud. ๐ŸŽ‰ + +FastAPI Cloud est le sponsor principal et le financeur des projets open source *FastAPI and friends*. โœจ + +## Fournisseurs cloud - Sponsors { #cloud-providers-sponsors } + +D'autres fournisseurs cloud โœจ [**parrainent FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ รฉgalement. ๐Ÿ™‡ + +Vous pouvez รฉgalement envisager ces fournisseurs pour suivre leurs guides et essayer leurs services : + +* Render +* Railway diff --git a/docs/fr/docs/deployment/concepts.md b/docs/fr/docs/deployment/concepts.md new file mode 100644 index 0000000000..59b8ddd1b9 --- /dev/null +++ b/docs/fr/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Concepts de dรฉploiement { #deployments-concepts } + +Lorsque vous dรฉployez une application **FastAPI**, ou en fait n'importe quel type de web API, il existe plusieurs concepts qui vous importent probablement, et en les utilisant vous pouvez trouver la maniรจre la **plus appropriรฉe** de **dรฉployer votre application**. + +Parmi les concepts importants, on trouve : + +* Sรฉcuritรฉ - HTTPS +* Exรฉcuter au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables avant de dรฉmarrer + +Nous allons voir comment ils affectent les **dรฉploiements**. + +Au final, l'objectif ultime est de pouvoir **servir vos clients d'API** de maniรจre **sรฉcurisรฉe**, d'**รฉviter les interruptions**, et d'utiliser les **ressources de calcul** (par exemple des serveurs/VM distants) aussi efficacement que possible. ๐Ÿš€ + +Je vais vous en dire un peu plus ici sur ces **concepts**, ce qui devrait vous donner l'**intuition** nรฉcessaire pour dรฉcider comment dรฉployer votre API dans des environnements trรจs diffรฉrents, voire mรชme dans des environnements **futurs** qui n'existent pas encore. + +En tenant compte de ces concepts, vous serez en mesure **d'รฉvaluer et de concevoir** la meilleure faรงon de dรฉployer **vos propres API**. + +Dans les chapitres suivants, je vous donnerai des **recettes concrรจtes** pour dรฉployer des applications FastAPI. + +Mais pour l'instant, voyons ces **idรฉes conceptuelles** importantes. Ces concepts s'appliquent aussi ร  tout autre type de web API. ๐Ÿ’ก + +## Sรฉcuritรฉ - HTTPS { #security-https } + +Dans le [chapitre prรฉcรฉdent ร  propos de HTTPS](https.md){.internal-link target=_blank}, nous avons vu comment HTTPS fournit le chiffrement pour votre API. + +Nous avons รฉgalement vu que HTTPS est normalement fourni par un composant **externe** ร  votre serveur d'application, un **TLS Termination Proxy**. + +Et il doit y avoir quelque chose chargรฉ de **renouveler les certificats HTTPS** ; cela peut รชtre le mรชme composant ou quelque chose de diffรฉrent. + +### Exemples dโ€™outils pour HTTPS { #example-tools-for-https } + +Parmi les outils que vous pourriez utiliser comme TLS Termination Proxy : + +* Traefik + * Gรจre automatiquement le renouvellement des certificats โœจ +* Caddy + * Gรจre automatiquement le renouvellement des certificats โœจ +* Nginx + * Avec un composant externe comme Certbot pour le renouvellement des certificats +* HAProxy + * Avec un composant externe comme Certbot pour le renouvellement des certificats +* Kubernetes avec un Ingress Controller comme Nginx + * Avec un composant externe comme cert-manager pour le renouvellement des certificats +* Pris en charge en interne par un fournisseur cloud dans le cadre de ses services (lisez ci-dessous ๐Ÿ‘‡) + +Une autre option consiste ร  utiliser un **service cloud** qui fait davantage de travail, y compris la mise en place de HTTPS. Il peut avoir certaines restrictions ou vous facturer davantage, etc. Mais dans ce cas, vous n'auriez pas ร  configurer vousโ€‘mรชme un TLS Termination Proxy. + +Je vous montrerai des exemples concrets dans les prochains chapitres. + +--- + +Les concepts suivants ร  considรฉrer concernent tous le programme qui exรฉcute votre API rรฉelle (par ex. Uvicorn). + +## Programme et processus { #program-and-process } + +Nous allons beaucoup parler du ยซ **processus** ยป en cours d'exรฉcution, il est donc utile d'รชtre clair sur ce que cela signifie, et sur la diffรฉrence avec le mot ยซ **programme** ยป. + +### Qu'est-ce qu'un programme { #what-is-a-program } + +Le mot **programme** est couramment utilisรฉ pour dรฉcrire plusieurs choses : + +* Le **code** que vous รฉcrivez, les **fichiers Python**. +* Le **fichier** qui peut รชtre **exรฉcutรฉ** par le systรจme d'exploitation, par exemple : `python`, `python.exe` ou `uvicorn`. +* Un programme particulier lorsqu'il **s'exรฉcute** sur le systรจme d'exploitation, utilisant le CPU et stockant des choses en mรฉmoire. On appelle aussi cela un **processus**. + +### Qu'est-ce qu'un processus { #what-is-a-process } + +Le mot **processus** est normalement utilisรฉ de maniรจre plus spรฉcifique, en ne se rรฉfรฉrant qu'ร  l'รฉlรฉment qui s'exรฉcute dans le systรจme d'exploitation (comme dans le dernier point ciโ€‘dessus) : + +* Un programme particulier lorsqu'il **s'exรฉcute** sur le systรจme d'exploitation. + * Cela ne se rรฉfรจre ni au fichier, ni au code ; cela se rรฉfรจre **spรฉcifiquement** ร  l'รฉlรฉment qui est **exรฉcutรฉ** et gรฉrรฉ par le systรจme d'exploitation. +* N'importe quel programme, n'importe quel code, **ne peut faire des choses** que lorsqu'il est **exรฉcutรฉ**. Donc, lorsqu'il y a un **processus en cours**. +* Le processus peut รชtre **arrรชtรฉ** (ou ยซ tuรฉ ยป) par vous ou par le systรจme d'exploitation. ร€ ce momentโ€‘lร , il cesse de s'exรฉcuter/d'รชtre exรฉcutรฉ, et il **ne peut plus rien faire**. +* Chaque application que vous avez en cours d'exรฉcution sur votre ordinateur a un processus derriรจre elle, chaque programme lancรฉ, chaque fenรชtre, etc. Et il y a normalement de nombreux processus exรฉcutรฉs **en mรชme temps** tant qu'un ordinateur est allumรฉ. +* Il peut y avoir **plusieurs processus** du **mรชme programme** exรฉcutรฉs simultanรฉment. + +Si vous ouvrez le ยซ gestionnaire des tรขches ยป ou le ยซ moniteur systรจme ยป (ou des outils similaires) de votre systรจme d'exploitation, vous verrez nombre de ces processus en cours d'exรฉcution. + +Et, par exemple, vous verrez probablement qu'il y a plusieurs processus exรฉcutant le mรชme navigateur (Firefox, Chrome, Edge, etc.). Ils exรฉcutent normalement un processus par onglet, plus quelques processus supplรฉmentaires. + + + +--- + +Maintenant que nous connaissons la diffรฉrence entre les termes **processus** et **programme**, continuons ร  parler des dรฉploiements. + +## Exรฉcuter au dรฉmarrage { #running-on-startup } + +Dans la plupart des cas, lorsque vous crรฉez une web API, vous voulez qu'elle **tourne en permanence**, sans interruption, afin que vos clients puissent toujours y accรฉder. Bien sรปr, sauf si vous avez une raison spรฉcifique de ne vouloir l'exรฉcuter que dans certaines situations, mais la plupart du temps vous la voulez constamment en cours et **disponible**. + +### Sur un serveur distant { #in-a-remote-server } + +Lorsque vous configurez un serveur distant (un serveur cloud, une machine virtuelle, etc.), la chose la plus simple ร  faire est d'utiliser `fastapi run` (qui utilise Uvicorn) ou quelque chose de similaire, manuellement, de la mรชme maniรจre que lorsque vous dรฉveloppez en local. + +Et cela fonctionnera et sera utile **pendant le dรฉveloppement**. + +Mais si votre connexion au serveur est coupรฉe, le **processus en cours** va probablement s'arrรชter. + +Et si le serveur est redรฉmarrรฉ (par exemple aprรจs des mises ร  jour, ou des migrations chez le fournisseur cloud) vous **ne le remarquerez probablement pas**. Et ร  cause de cela, vous ne saurez mรชme pas que vous devez redรฉmarrer le processus manuellement. Ainsi, votre API restera tout simplement ร  l'arrรชt. ๐Ÿ˜ฑ + +### Lancer automatiquement au dรฉmarrage { #run-automatically-on-startup } + +En gรฉnรฉral, vous voudrez probablement que le programme serveur (par ex. Uvicorn) soit dรฉmarrรฉ automatiquement au dรฉmarrage du serveur, et sans aucune **intervention humaine**, afin d'avoir en permanence un processus exรฉcutant votre API (par ex. Uvicorn exรฉcutant votre app FastAPI). + +### Programme sรฉparรฉ { #separate-program } + +Pour y parvenir, vous aurez normalement un **programme sรฉparรฉ** qui s'assure que votre application est lancรฉe au dรฉmarrage. Et dans de nombreux cas, il s'assurera รฉgalement que d'autres composants ou applications sont รฉgalement lancรฉs, par exemple une base de donnรฉes. + +### Exemples dโ€™outils pour lancer au dรฉmarrage { #example-tools-to-run-at-startup } + +Voici quelques exemples d'outils capables de faire ce travail : + +* Docker +* Kubernetes +* Docker Compose +* Docker en mode Swarm +* Systemd +* Supervisor +* Pris en charge en interne par un fournisseur cloud dans le cadre de ses services +* Autres ... + +Je vous donnerai des exemples plus concrets dans les prochains chapitres. + +## Redรฉmarrages { #restarts } + +De la mรชme maniรจre que vous voulez vous assurer que votre application est lancรฉe au dรฉmarrage, vous voulez probablement aussi vous assurer qu'elle est **redรฉmarrรฉe** aprรจs des รฉchecs. + +### Nous faisons des erreurs { #we-make-mistakes } + +Nous, humains, faisons des **erreurs**, tout le temps. Les logiciels ont presque *toujours* des **bugs** cachรฉs ร  diffรฉrents endroits. ๐Ÿ› + +Et nous, dรฉveloppeurs, continuons ร  amรฉliorer le code au fur et ร  mesure que nous trouvons ces bugs et que nous implรฉmentons de nouvelles fonctionnalitรฉs (en ajoutant รฉventuellement de nouveaux bugs aussi ๐Ÿ˜…). + +### Petites erreurs gรฉrรฉes automatiquement { #small-errors-automatically-handled } + +Lors de la crรฉation de web API avec FastAPI, s'il y a une erreur dans notre code, FastAPI la contiendra normalement ร  la seule requรชte qui a dรฉclenchรฉ l'erreur. ๐Ÿ›ก + +Le client recevra un **500 Internal Server Error** pour cette requรชte, mais l'application continuera de fonctionner pour les requรชtes suivantes au lieu de simplement s'effondrer complรจtement. + +### Erreurs plus importantes - plantages { #bigger-errors-crashes } + +Nรฉanmoins, il peut y avoir des cas oรน nous รฉcrivons du code qui **fait planter l'application entiรจre**, faisant planter Uvicorn et Python. ๐Ÿ’ฅ + +Et malgrรฉ cela, vous ne voudrez probablement pas que l'application reste ร  l'arrรชt parce qu'il y a eu une erreur ร  un endroit ; vous voudrez probablement qu'elle **continue de tourner**, au moins pour les *chemins d'accรจs* qui ne sont pas cassรฉs. + +### Redรฉmarrer aprรจs un plantage { #restart-after-crash } + +Mais dans ces cas avec de trรจs mauvaises erreurs qui font planter le **processus** en cours, vous voudrez un composant externe chargรฉ de **redรฉmarrer** le processus, au moins quelques fois ... + +/// tip | Astuce + +... Bien que si l'application entiรจre **plante immรฉdiatement**, il n'est probablement pas logique de continuer ร  la redรฉmarrer indรฉfiniment. Mais dans ces cas, vous le remarquerez probablement pendant le dรฉveloppement, ou au moins juste aprรจs le dรฉploiement. + +Concentronsโ€‘nous donc sur les cas principaux, oรน elle pourrait planter entiรจrement dans certaines situations particuliรจres **ร  l'avenir**, et oรน il est toujours logique de la redรฉmarrer. + +/// + +Vous voudrez probablement que l'รฉlรฉment chargรฉ de redรฉmarrer votre application soit un **composant externe**, car ร  ce stade, l'application elleโ€‘mรชme avec Uvicorn et Python a dรฉjร  plantรฉ, donc il n'y a rien dans le mรชme code de la mรชme app qui pourrait y faire quoi que ce soit. + +### Exemples dโ€™outils pour redรฉmarrer automatiquement { #example-tools-to-restart-automatically } + +Dans la plupart des cas, le mรชme outil qui est utilisรฉ pour **lancer le programme au dรฉmarrage** est รฉgalement utilisรฉ pour gรฉrer les **redรฉmarrages** automatiques. + +Par exemple, cela peut รชtre gรฉrรฉ par : + +* Docker +* Kubernetes +* Docker Compose +* Docker en mode Swarm +* Systemd +* Supervisor +* Pris en charge en interne par un fournisseur cloud dans le cadre de ses services +* Autres ... + +## Rรฉplication - Processus et mรฉmoire { #replication-processes-and-memory } + +Avec une application FastAPI, en utilisant un programme serveur comme la commande `fastapi` qui exรฉcute Uvicorn, l'exรฉcuter une fois dans **un processus** peut servir plusieurs clients simultanรฉment. + +Mais dans de nombreux cas, vous voudrez exรฉcuter plusieurs processus de travail en mรชme temps. + +### Multiples processus - Workers { #multiple-processes-workers } + +Si vous avez plus de clients que ce qu'un seul processus peut gรฉrer (par exemple si la machine virtuelle n'est pas trรจs grande) et que vous avez **plusieurs cล“urs** dans le CPU du serveur, alors vous pouvez avoir **plusieurs processus** exรฉcutant la mรชme application simultanรฉment, et distribuer toutes les requรชtes entre eux. + +Quand vous exรฉcutez **plusieurs processus** du mรชme programme d'API, on les appelle couramment des **workers**. + +### Processus workers et ports { #worker-processes-and-ports } + +Rappelezโ€‘vous, d'aprรจs les documents [ร€ propos de HTTPS](https.md){.internal-link target=_blank}, qu'un seul processus peut รฉcouter une combinaison de port et d'adresse IP sur un serveur ? + +C'est toujours vrai. + +Donc, pour pouvoir avoir **plusieurs processus** en mรชme temps, il doit y avoir un **seul processus ร  l'รฉcoute sur un port** qui transmet ensuite la communication ร  chaque processus worker d'une maniรจre ou d'une autre. + +### Mรฉmoire par processus { #memory-per-process } + +Maintenant, lorsque le programme charge des choses en mรฉmoire, par exemple, un modรจle de machine learning dans une variable, ou le contenu d'un gros fichier dans une variable, tout cela **consomme une partie de la mรฉmoire (RAM)** du serveur. + +Et plusieurs processus **ne partagent normalement pas de mรฉmoire**. Cela signifie que chaque processus en cours a ses propres รฉlรฉments, variables et mรฉmoire. Et si vous consommez une grande quantitรฉ de mรฉmoire dans votre code, **chaque processus** consommera une quantitรฉ รฉquivalente de mรฉmoire. + +### Mรฉmoire du serveur { #server-memory } + +Par exemple, si votre code charge un modรจle de Machine Learning de **1 Go**, lorsque vous exรฉcutez un processus avec votre API, il consommera au moins 1 Go de RAM. Et si vous dรฉmarrez **4 processus** (4 workers), chacun consommera 1 Go de RAM. Donc au total, votre API consommera **4 Go de RAM**. + +Et si votre serveur distant ou votre machine virtuelle n'a que 3 Go de RAM, essayer de charger plus de 4 Go de RAM posera problรจme. ๐Ÿšจ + +### Multiples processus - Un exemple { #multiple-processes-an-example } + +Dans cet exemple, il y a un **processus gestionnaire** qui dรฉmarre et contrรดle deux **processus workers**. + +Ce processus gestionnaire serait probablement celui qui รฉcoute sur le **port** de l'IP. Et il transmettrait toute la communication aux processus workers. + +Ces processus workers seraient ceux qui exรฉcutent votre application, ils effectueraient les calculs principaux pour recevoir une **requรชte** et renvoyer une **rรฉponse**, et ils chargeraient tout ce que vous mettez dans des variables en RAM. + + + +Et bien sรปr, la mรชme machine aurait probablement **d'autres processus** en cours d'exรฉcution รฉgalement, en plus de votre application. + +Un dรฉtail intรฉressant est que le pourcentage de **CPU utilisรฉ** par chaque processus peut **varier** fortement dans le temps, mais la **mรฉmoire (RAM)** reste normalement plus ou moins **stable**. + +Si vous avez une API qui effectue une quantitรฉ comparable de calculs ร  chaque fois et que vous avez beaucoup de clients, alors l'**utilisation du CPU** sera probablement *รฉgalement stable* (au lieu de monter et descendre rapidement en permanence). + +### Exemples dโ€™outils et de stratรฉgies de rรฉplication { #examples-of-replication-tools-and-strategies } + +Il peut y avoir plusieurs approches pour y parvenir, et je vous en dirai plus sur des stratรฉgies spรฉcifiques dans les prochains chapitres, par exemple en parlant de Docker et des conteneurs. + +La principale contrainte ร  considรฉrer est qu'il doit y avoir un **seul** composant gรฉrant le **port** sur l'**IP publique**. Et il doit ensuite avoir un moyen de **transmettre** la communication aux **processus/workers** rรฉpliquรฉs. + +Voici quelques combinaisons et stratรฉgies possibles : + +* **Uvicorn** avec `--workers` + * Un **gestionnaire de processus** Uvicorn รฉcouterait sur l'**IP** et le **port**, et il dรฉmarrerait **plusieurs processus workers Uvicorn**. +* **Kubernetes** et autres systรจmes **de conteneurs** distribuรฉs + * Quelque chose dans la couche **Kubernetes** รฉcouterait sur l'**IP** et le **port**. La rรฉplication se ferait en ayant **plusieurs conteneurs**, chacun avec **un processus Uvicorn** en cours. +* **Services cloud** qui s'en chargent pour vous + * Le service cloud **gรฉrera probablement la rรฉplication pour vous**. Il vous permettra รฉventuellement de dรฉfinir **un processus ร  exรฉcuter**, ou une **image de conteneur** ร  utiliser ; dans tous les cas, ce sera trรจs probablement **un seul processus Uvicorn**, et le service cloud sera chargรฉ de le rรฉpliquer. + +/// tip | Astuce + +Ne vous inquiรฉtez pas si certains de ces รฉlรฉments concernant les **conteneurs**, Docker ou Kubernetes ne sont pas encore trรจs clairs. + +Je vous en dirai plus sur les images de conteneurs, Docker, Kubernetes, etc. dans un chapitre ร  venir : [FastAPI dans des conteneurs - Docker](docker.md){.internal-link target=_blank}. + +/// + +## ร‰tapes prรฉalables avant de dรฉmarrer { #previous-steps-before-starting } + +Il existe de nombreux cas oรน vous souhaitez effectuer certaines รฉtapes **avant de dรฉmarrer** votre application. + +Par exemple, vous pourriez vouloir exรฉcuter des **migrations de base de donnรฉes**. + +Mais dans la plupart des cas, vous voudrez effectuer ces รฉtapes **une seule fois**. + +Vous voudrez donc avoir un **processus unique** pour effectuer ces **รฉtapes prรฉalables**, avant de dรฉmarrer l'application. + +Et vous devez vous assurer que c'est un processus unique qui exรฉcute ces รฉtapes prรฉalables *mรชme si*, ensuite, vous dรฉmarrez **plusieurs processus** (plusieurs workers) pour l'application elleโ€‘mรชme. Si ces รฉtapes รฉtaient exรฉcutรฉes par **plusieurs processus**, ils **dupliqueraient** le travail en l'exรฉcutant **en parallรจle**, et si les รฉtapes รฉtaient dรฉlicates comme une migration de base de donnรฉes, elles pourraient entrer en conflit les unes avec les autres. + +Bien sรปr, il y a des cas oรน il n'y a aucun problรจme ร  exรฉcuter les รฉtapes prรฉalables plusieurs fois ; dans ce cas, c'est beaucoup plus simple ร  gรฉrer. + +/// tip | Astuce + +Gardez aussi ร  l'esprit que selon votre configuration, dans certains cas vous **n'aurez peutโ€‘รชtre mรชme pas besoin d'รฉtapes prรฉalables** avant de dรฉmarrer votre application. + +Dans ce cas, vous n'auriez pas ร  vous soucier de tout cela. ๐Ÿคท + +/// + +### Exemples de stratรฉgies pour les รฉtapes prรฉalables { #examples-of-previous-steps-strategies } + +Cela **dรฉpendra fortement** de la maniรจre dont vous **dรฉployez votre systรจme**, et sera probablement liรฉ ร  votre maniรจre de dรฉmarrer les programmes, de gรฉrer les redรฉmarrages, etc. + +Voici quelques idรฉes possibles : + +* Un ยซ Init Container ยป dans Kubernetes qui s'exรฉcute avant votre conteneur d'application +* Un script bash qui exรฉcute les รฉtapes prรฉalables puis dรฉmarre votre application + * Vous aurez toujours besoin d'un moyen de dรฉmarrer/redรฉmarrer *ce* script bash, de dรฉtecter les erreurs, etc. + +/// tip | Astuce + +Je vous donnerai des exemples plus concrets pour faire cela avec des conteneurs dans un chapitre ร  venir : [FastAPI dans des conteneurs - Docker](docker.md){.internal-link target=_blank}. + +/// + +## Utilisation des ressources { #resource-utilization } + +Votre ou vos serveurs constituent une **ressource** que vos programmes peuvent consommer ou **utiliser** : le temps de calcul des CPU et la mรฉmoire RAM disponible. + +Quelle quantitรฉ des ressources systรจme voulezโ€‘vous consommer/utiliser ? Il peut รชtre facile de penser ยซ pas beaucoup ยป, mais en rรฉalitรฉ, vous voudrez probablement consommer **le plus possible sans planter**. + +Si vous payez pour 3 serveurs mais que vous n'utilisez qu'un petit peu de leur RAM et CPU, vous **gaspillez probablement de l'argent** ๐Ÿ’ธ, et **gaspillez probablement l'รฉlectricitรฉ des serveurs** ๐ŸŒŽ, etc. + +Dans ce cas, il pourrait รชtre prรฉfรฉrable de n'avoir que 2 serveurs et d'utiliser un pourcentage plus รฉlevรฉ de leurs ressources (CPU, mรฉmoire, disque, bande passante rรฉseau, etc.). + +ร€ l'inverse, si vous avez 2 serveurs et que vous utilisez **100 % de leur CPU et de leur RAM**, ร  un moment donnรฉ un processus demandera plus de mรฉmoire, et le serveur devra utiliser le disque comme ยซ mรฉmoire ยป (ce qui peut รชtre des milliers de fois plus lent), voire **planter**. Ou un processus pourrait avoir besoin de faire un calcul et devrait attendre que le CPU soit ร  nouveau libre. + +Dans ce cas, il serait prรฉfรฉrable d'obtenir **un serveur supplรฉmentaire** et d'y exรฉcuter certains processus afin qu'ils aient tous **suffisamment de RAM et de temps CPU**. + +Il est รฉgalement possible que, pour une raison quelconque, vous ayez un **pic** d'utilisation de votre API. Peutโ€‘รชtre qu'elle devient virale, ou peutโ€‘รชtre que d'autres services ou bots commencent ร  l'utiliser. Et vous voudrez peutโ€‘รชtre disposer de ressources supplรฉmentaires pour รชtre en sรฉcuritรฉ dans ces cas. + +Vous pouvez dรฉfinir un **chiffre arbitraire** comme cible, par exemple **entre 50 % et 90 %** d'utilisation des ressources. L'idรฉe est que ce sont probablement les principaux รฉlรฉments que vous voudrez mesurer et utiliser pour ajuster vos dรฉploiements. + +Vous pouvez utiliser des outils simples comme `htop` pour voir le CPU et la RAM utilisรฉs sur votre serveur ou la quantitรฉ utilisรฉe par chaque processus. Ou vous pouvez utiliser des outils de supervision plus complexes, รฉventuellement distribuรฉs sur plusieurs serveurs, etc. + +## Rรฉcapitulatif { #recap } + +Vous venez de lire ici certains des principaux concepts que vous devrez probablement garder ร  l'esprit lorsque vous dรฉcidez comment dรฉployer votre application : + +* Sรฉcuritรฉ - HTTPS +* Exรฉcuter au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables avant de dรฉmarrer + +Comprendre ces idรฉes et comment les appliquer devrait vous donner l'intuition nรฉcessaire pour prendre toutes les dรฉcisions lors de la configuration et de l'ajustement de vos dรฉploiements. ๐Ÿค“ + +Dans les sections suivantes, je vous donnerai des exemples plus concrets de stratรฉgies possibles ร  suivre. ๐Ÿš€ diff --git a/docs/fr/docs/deployment/docker.md b/docs/fr/docs/deployment/docker.md index ec30f96079..2d86d4a402 100644 --- a/docs/fr/docs/deployment/docker.md +++ b/docs/fr/docs/deployment/docker.md @@ -14,7 +14,7 @@ Vous รชtes pressรฉ et vous connaissez dรฉjร  tout รงa ? Allez directement au [`D Aperรงu du Dockerfile ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ Maintenant, dans le mรชme rรฉpertoire de projet, crรฉez un fichier `Dockerfile` ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ Si votre FastAPI est un seul fichier, par exemple `main.py` sans rรฉpertoire `./ Vous n'auriez alors qu'ร  changer les chemins correspondants pour copier le fichier dans le `Dockerfile` : ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Sans utiliser de conteneurs, faire en sorte que les applications s'exรฉcutent au ## Rรฉplication - Nombre de processus { #replication-number-of-processes } -Si vous avez un cluster de machines avec **Kubernetes**, Docker Swarm Mode, Nomad, ou un autre systรจme complexe similaire pour gรฉrer des conteneurs distribuรฉs sur plusieurs machines, alors vous voudrez probablement **gรฉrer la rรฉplication** au **niveau du cluster** plutรดt que d'utiliser un **gestionnaire de processus** (comme Uvicorn avec workers) dans chaque conteneur. +Si vous avez un cluster de machines avec **Kubernetes**, Docker Swarm Mode, Nomad, ou un autre systรจme complexe similaire pour gรฉrer des conteneurs distribuรฉs sur plusieurs machines, alors vous voudrez probablement **gรฉrer la rรฉplication** au **niveau du cluster** plutรดt que d'utiliser un **gestionnaire de processus** (comme Uvicorn avec workers) dans chaque conteneur. L'un de ces systรจmes de gestion de conteneurs distribuรฉs comme Kubernetes dispose normalement d'une maniรจre intรฉgrรฉe de gรฉrer la **rรฉplication des conteneurs** tout en supportant l'**รฉquilibrage de charge** des requรชtes entrantes. Le tout au **niveau du cluster**. @@ -499,7 +499,7 @@ Bien sรปr, il existe des **cas particuliers** oรน vous pourriez vouloir avoir ** Dans ces cas, vous pouvez utiliser l'option de ligne de commande `--workers` pour dรฉfinir le nombre de workers que vous souhaitez exรฉcuter : ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/fr/docs/deployment/fastapicloud.md b/docs/fr/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..72f275cf6f --- /dev/null +++ b/docs/fr/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +Vous pouvez dรฉployer votre application FastAPI sur FastAPI Cloud avec une **seule commande**, allez vous inscrire sur la liste dโ€™attente si ce nโ€™est pas dรฉjร  fait. ๐Ÿš€ + +## Se connecter { #login } + +Vous devez vous assurer que vous avez dรฉjร  un compte **FastAPI Cloud** (nous vous avons invitรฉ depuis la liste dโ€™attente ๐Ÿ˜‰). + +Connectez-vous ensuite : + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## Dรฉployer { #deploy } + +Dรฉployez maintenant votre application, avec une **seule commande** : + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Cโ€™est tout ! Vous pouvez maintenant accรฉder ร  votre application ร  cette URL. โœจ + +## ร€ propos de FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** est dรฉveloppรฉ par le mรชme auteur et la mรชme รฉquipe ร  lโ€™origine de **FastAPI**. + +Cela simplifie le processus de **crรฉation**, de **dรฉploiement** et **dโ€™accรจs** ร  une API avec un effort minimal. + +Cela apporte la mรชme **expรฉrience dรฉveloppeur** que pour crรฉer des applications avec FastAPI au **dรฉploiement** dans le cloud. ๐ŸŽ‰ + +Cela prend รฉgalement en charge la plupart des รฉlรฉments nรฉcessaires lors du dรฉploiement dโ€™une application, notamment : + +* HTTPS +* Rรฉplication, avec mise ร  lโ€™รฉchelle automatique basรฉe sur les requรชtes +* etc. + +FastAPI Cloud est le sponsor principal et le financeur des projets open source *FastAPI and friends*. โœจ + +## Dรฉployer sur dโ€™autres fournisseurs cloud { #deploy-to-other-cloud-providers } + +FastAPI est open source et basรฉ sur des standards. Vous pouvez dรฉployer des applications FastAPI sur nโ€™importe quel fournisseur cloud de votre choix. + +Suivez les guides de votre fournisseur cloud pour dรฉployer des applications FastAPI avec eux. ๐Ÿค“ + +## Dรฉployer votre propre serveur { #deploy-your-own-server } + +Je vous expliquerai รฉgalement plus loin dans ce guide de **Dรฉploiement** tous les dรฉtails, afin que vous compreniez ce qui se passe, ce qui doit รชtre fait, et comment dรฉployer des applications FastAPI par vous-mรชme, y compris sur vos propres serveurs. ๐Ÿค“ diff --git a/docs/fr/docs/deployment/https.md b/docs/fr/docs/deployment/https.md index 74d38cdb9f..1b3c7be56c 100644 --- a/docs/fr/docs/deployment/https.md +++ b/docs/fr/docs/deployment/https.md @@ -65,7 +65,7 @@ Voici un exemple de ce ร  quoi pourrait ressembler une API HTTPS, รฉtape par รฉt Tout commencerait probablement par le fait que vous **acquรฉriez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le mรชme que votre fournisseur cloud). -Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP **publique** fixe. +Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP publique fixe. Dans le ou les serveurs DNS, vous configureriez un enregistrement (un ยซ `A record` ยป) pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**. diff --git a/docs/fr/docs/deployment/server-workers.md b/docs/fr/docs/deployment/server-workers.md new file mode 100644 index 0000000000..338a5003d5 --- /dev/null +++ b/docs/fr/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Workers du serveur - Uvicorn avec workers { #server-workers-uvicorn-with-workers } + +Reprenons ces concepts de dรฉploiement vus prรฉcรฉdemment : + +* Sรฉcuritรฉ - HTTPS +* Exรฉcution au dรฉmarrage +* Redรฉmarrages +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables avant le dรฉmarrage + +Jusqu'ร  prรฉsent, avec tous les tutoriels dans les documents, vous avez probablement exรฉcutรฉ un programme serveur, par exemple avec la commande `fastapi`, qui lance Uvicorn en exรฉcutant un seul processus. + +Lors du dรฉploiement d'applications, vous voudrez probablement avoir une rรฉplication de processus pour tirer parti de plusieurs cล“urs et pouvoir gรฉrer davantage de requรชtes. + +Comme vous l'avez vu dans le chapitre prรฉcรฉdent sur les [Concepts de dรฉploiement](concepts.md){.internal-link target=_blank}, il existe plusieurs stratรฉgies possibles. + +Ici, je vais vous montrer comment utiliser Uvicorn avec des processus workers en utilisant la commande `fastapi` ou directement la commande `uvicorn`. + +/// info | Info + +Si vous utilisez des conteneurs, par exemple avec Docker ou Kubernetes, je vous en dirai plus ร  ce sujet dans le prochain chapitre : [FastAPI dans des conteneurs - Docker](docker.md){.internal-link target=_blank}. + +En particulier, lorsque vous exรฉcutez sur Kubernetes, vous ne voudrez probablement pas utiliser de workers et plutรดt exรฉcuter un seul processus Uvicorn par conteneur, mais je vous en parlerai plus en dรฉtail dans ce chapitre. + +/// + +## Utiliser plusieurs workers { #multiple-workers } + +Vous pouvez dรฉmarrer plusieurs workers avec l'option de ligne de commande `--workers` : + +//// tab | `fastapi` + +Si vous utilisez la commande `fastapi` : + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +Si vous prรฉfรฉrez utiliser directement la commande `uvicorn` : + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +La seule option nouvelle ici est `--workers` qui indique ร  Uvicorn de dรฉmarrer 4 processus workers. + +Vous pouvez aussi voir qu'il affiche le PID de chaque processus, `27365` pour le processus parent (c'est le gestionnaire de processus) et un pour chaque processus worker : `27368`, `27369`, `27370` et `27367`. + +## Concepts de dรฉploiement { #deployment-concepts } + +Ici, vous avez vu comment utiliser plusieurs workers pour parallรฉliser l'exรฉcution de l'application, tirer parti de plusieurs cล“urs du CPU et รชtre en mesure de servir davantage de requรชtes. + +Dans la liste des concepts de dรฉploiement ci-dessus, l'utilisation de workers aide principalement ร  la partie rรฉplication, et un peu aux redรฉmarrages, mais vous devez toujours vous occuper des autres : + +* Sรฉcuritรฉ - HTTPS +* Exรฉcution au dรฉmarrage +* ***Redรฉmarrages*** +* Rรฉplication (le nombre de processus en cours d'exรฉcution) +* Mรฉmoire +* ร‰tapes prรฉalables avant le dรฉmarrage + +## Conteneurs et Docker { #containers-and-docker } + +Dans le prochain chapitre sur [FastAPI dans des conteneurs - Docker](docker.md){.internal-link target=_blank}, j'expliquerai quelques stratรฉgies que vous pourriez utiliser pour gรฉrer les autres concepts de dรฉploiement. + +Je vous montrerai comment crรฉer votre propre image ร  partir de zรฉro pour exรฉcuter un seul processus Uvicorn. C'est un processus simple et c'est probablement ce que vous voudrez faire lorsque vous utilisez un systรจme distribuรฉ de gestion de conteneurs comme Kubernetes. + +## Rรฉcapitulatif { #recap } + +Vous pouvez utiliser plusieurs processus workers avec l'option CLI `--workers` des commandes `fastapi` ou `uvicorn` pour tirer parti des CPU multicล“urs, et exรฉcuter plusieurs processus en parallรจle. + +Vous pourriez utiliser ces outils et idรฉes si vous mettez en place votre propre systรจme de dรฉploiement tout en prenant vous-mรชme en charge les autres concepts de dรฉploiement. + +Consultez le prochain chapitre pour en savoir plus sur FastAPI avec des conteneurs (par exemple Docker et Kubernetes). Vous verrez que ces outils offrent aussi des moyens simples de rรฉsoudre les autres concepts de dรฉploiement. โœจ diff --git a/docs/fr/docs/environment-variables.md b/docs/fr/docs/environment-variables.md new file mode 100644 index 0000000000..57479852ae --- /dev/null +++ b/docs/fr/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Variables d'environnement { #environment-variables } + +/// tip | Astuce + +Si vous savez dรฉjร  ce que sont les ยซ variables d'environnement ยป et comment les utiliser, vous pouvez passer cette section. + +/// + +Une variable d'environnement (รฉgalement appelรฉe ยซ env var ยป) est une variable qui vit en dehors du code Python, dans le systรจme d'exploitation, et qui peut รชtre lue par votre code Python (ou par d'autres programmes รฉgalement). + +Les variables d'environnement peuvent รชtre utiles pour gรฉrer des **paramรจtres** d'application, dans le cadre de l'**installation** de Python, etc. + +## Crรฉer et utiliser des variables d'environnement { #create-and-use-env-vars } + +Vous pouvez crรฉer et utiliser des variables d'environnement dans le **shell (terminal)**, sans avoir besoin de Python : + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Vous pouvez crรฉer une variable d'environnement MY_NAME avec +$ export MY_NAME="Wade Wilson" + +// Vous pouvez ensuite l'utiliser avec d'autres programmes, par exemple +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Crรฉer une variable d'environnement MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// L'utiliser avec d'autres programmes, par exemple +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Lire des variables d'environnement en Python { #read-env-vars-in-python } + +Vous pouvez รฉgalement crรฉer des variables d'environnement **en dehors** de Python, dans le terminal (ou par tout autre moyen), puis les **lire en Python**. + +Par exemple, vous pouvez avoir un fichier `main.py` contenantย : + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | Astuce + +Le deuxiรจme argument de `os.getenv()` est la valeur par dรฉfaut ร  retourner. + +S'il n'est pas fourni, c'est `None` par dรฉfaut ; ici, nous fournissons `"World"` comme valeur par dรฉfaut ร  utiliser. + +/// + +Vous pouvez ensuite exรฉcuter ce programme Pythonย : + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Ici, nous ne dรฉfinissons pas encore la variable d'environnement +$ python main.py + +// Comme nous ne l'avons pas dรฉfinie, nous obtenons la valeur par dรฉfaut + +Hello World from Python + +// Mais si nous crรฉons d'abord une variable d'environnement +$ export MY_NAME="Wade Wilson" + +// Puis que nous relanรงons le programme +$ python main.py + +// Il peut maintenant lire la variable d'environnement + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Ici, nous ne dรฉfinissons pas encore la variable d'environnement +$ python main.py + +// Comme nous ne l'avons pas dรฉfinie, nous obtenons la valeur par dรฉfaut + +Hello World from Python + +// Mais si nous crรฉons d'abord une variable d'environnement +$ $Env:MY_NAME = "Wade Wilson" + +// Puis que nous relanรงons le programme +$ python main.py + +// Il peut maintenant lire la variable d'environnement + +Hello Wade Wilson from Python +``` + +
+ +//// + +Comme les variables d'environnement peuvent รชtre dรฉfinies en dehors du code, mais lues par le code, et qu'elles n'ont pas besoin d'รชtre stockรฉes (validรฉes dans `git`) avec le reste des fichiers, il est courant de les utiliser pour les configurations ou les **paramรจtres**. + +Vous pouvez รฉgalement crรฉer une variable d'environnement uniquement pour l'**invocation d'un programme spรฉcifique**, qui ne sera disponible que pour ce programme et uniquement pendant sa durรฉe d'exรฉcution. + +Pour cela, crรฉez-la juste avant le programme, sur la mรชme ligneย : + +
+ +```console +// Crรฉer en ligne une variable d'environnement MY_NAME pour cet appel de programme +$ MY_NAME="Wade Wilson" python main.py + +// Il peut maintenant lire la variable d'environnement + +Hello Wade Wilson from Python + +// La variable d'environnement n'existe plus ensuite +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | Astuce + +Vous pouvez en lire davantage sur The Twelve-Factor App : Config. + +/// + +## Gรฉrer les types et la validation { #types-and-validation } + +Ces variables d'environnement ne peuvent gรฉrer que des **chaรฎnes de texte**, car elles sont externes ร  Python et doivent รชtre compatibles avec les autres programmes et le reste du systรจme (et mรชme avec diffรฉrents systรจmes d'exploitation, comme Linux, Windows, macOS). + +Cela signifie que **toute valeur** lue en Python ร  partir d'une variable d'environnement **sera une `str`**, et que toute conversion vers un autre type ou toute validation doit รชtre effectuรฉe dans le code. + +Vous en apprendrez davantage sur l'utilisation des variables d'environnement pour gรฉrer les **paramรจtres d'application** dans le [Guide utilisateur avancรฉ - Paramรจtres et variables d'environnement](./advanced/settings.md){.internal-link target=_blank}. + +## Variable d'environnement `PATH` { #path-environment-variable } + +Il existe une **variable d'environnement spรฉciale** appelรฉe **`PATH`** qui est utilisรฉe par les systรจmes d'exploitation (Linux, macOS, Windows) pour trouver les programmes ร  exรฉcuter. + +La valeur de la variable `PATH` est une longue chaรฎne composรฉe de rรฉpertoires sรฉparรฉs par deux-points `:` sous Linux et macOS, et par point-virgule `;` sous Windows. + +Par exemple, la variable d'environnement `PATH` peut ressembler ร  ceciย : + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Cela signifie que le systรจme doit rechercher les programmes dans les rรฉpertoiresย : + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +Cela signifie que le systรจme doit rechercher les programmes dans les rรฉpertoiresย : + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +Lorsque vous tapez une **commande** dans le terminal, le systรจme d'exploitation **cherche** le programme dans **chacun de ces rรฉpertoires** listรฉs dans la variable d'environnement `PATH`. + +Par exemple, lorsque vous tapez `python` dans le terminal, le systรจme d'exploitation cherche un programme nommรฉ `python` dans le **premier rรฉpertoire** de cette liste. + +S'il le trouve, alors il **l'utilise**. Sinon, il continue ร  chercher dans les **autres rรฉpertoires**. + +### Installer Python et mettre ร  jour `PATH` { #installing-python-and-updating-the-path } + +Lorsque vous installez Python, il est possible que l'on vous demande si vous souhaitez mettre ร  jour la variable d'environnement `PATH`. + +//// tab | Linux, macOS + +Supposons que vous installiez Python et qu'il se retrouve dans un rรฉpertoire `/opt/custompython/bin`. + +Si vous acceptez de mettre ร  jour la variable d'environnement `PATH`, l'installateur ajoutera `/opt/custompython/bin` ร  la variable d'environnement `PATH`. + +Cela pourrait ressembler ร  ceciย : + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +Ainsi, lorsque vous tapez `python` dans le terminal, le systรจme trouvera le programme Python dans `/opt/custompython/bin` (le dernier rรฉpertoire) et utilisera celui-lร . + +//// + +//// tab | Windows + +Supposons que vous installiez Python et qu'il se retrouve dans un rรฉpertoire `C:\opt\custompython\bin`. + +Si vous acceptez de mettre ร  jour la variable d'environnement `PATH`, l'installateur ajoutera `C:\opt\custompython\bin` ร  la variable d'environnement `PATH`. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +Ainsi, lorsque vous tapez `python` dans le terminal, le systรจme trouvera le programme Python dans `C:\opt\custompython\bin` (le dernier rรฉpertoire) et utilisera celui-lร . + +//// + +Ainsi, si vous tapezย : + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +Le systรจme va **trouver** le programme `python` dans `/opt/custompython/bin` et l'exรฉcuter. + +Cela reviendrait ร  peu prรจs ร  taperย : + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +Le systรจme va **trouver** le programme `python` dans `C:\opt\custompython\bin\python` et l'exรฉcuter. + +Cela reviendrait ร  peu prรจs ร  taperย : + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Ces informations vous seront utiles lors de l'apprentissage des [Environnements virtuels](virtual-environments.md){.internal-link target=_blank}. + +## Conclusion { #conclusion } + +Avec cela, vous devriez avoir une comprรฉhension de base de ce que sont les **variables d'environnement** et de la faรงon de les utiliser en Python. + +Vous pouvez รฉgalement en lire davantage sur la page Wikipรฉdia dรฉdiรฉe aux variables d'environnement. + +Dans de nombreux cas, il n'est pas รฉvident de voir immรฉdiatement en quoi les variables d'environnement seraient utiles et applicables. Mais elles rรฉapparaissent dans de nombreux scรฉnarios lorsque vous dรฉveloppez, il est donc bon de les connaรฎtre. + +Par exemple, vous aurez besoin de ces informations dans la section suivante, sur les [Environnements virtuels](virtual-environments.md). diff --git a/docs/fr/docs/fastapi-cli.md b/docs/fr/docs/fastapi-cli.md new file mode 100644 index 0000000000..9f31e8a2f6 --- /dev/null +++ b/docs/fr/docs/fastapi-cli.md @@ -0,0 +1,75 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** est un programme en ligne de commande que vous pouvez utiliser pour servir votre application FastAPI, gรฉrer votre projet FastAPI, et plus encore. + +Lorsque vous installez FastAPI (par exemple avec `pip install "fastapi[standard]"`), cela inclut un package appelรฉ `fastapi-cli` ; ce package fournit la commande `fastapi` dans le terminal. + +Pour exรฉcuter votre application FastAPI en dรฉveloppement, vous pouvez utiliser la commande `fastapi dev` : + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +Le programme en ligne de commande nommรฉ `fastapi` est **FastAPI CLI**. + +FastAPI CLI prend le chemin vers votre programme Python (par exemple `main.py`), dรฉtecte automatiquement lโ€™instance `FastAPI` (gรฉnรฉralement nommรฉe `app`), dรฉtermine la procรฉdure dโ€™importation correcte, puis la sert. + +Pour la production, vous utiliserez plutรดt `fastapi run`. ๐Ÿš€ + +En interne, **FastAPI CLI** utilise Uvicorn, un serveur ASGI haute performance, prรชt pour la production. ๐Ÿ˜Ž + +## `fastapi dev` { #fastapi-dev } + +Lโ€™exรฉcution de `fastapi dev` lance le mode dรฉveloppement. + +Par dรฉfaut, lโ€™**auto-reload** est activรฉ et recharge automatiquement le serveur lorsque vous modifiez votre code. Cela consomme des ressources et peut รชtre moins stable que lorsquโ€™il est dรฉsactivรฉ. Vous devez lโ€™utiliser uniquement pour le dรฉveloppement. Il รฉcoute aussi sur lโ€™adresse IP `127.0.0.1`, qui est lโ€™adresse IP permettant ร  votre machine de communiquer uniquement avec elleโ€‘mรชme (`localhost`). + +## `fastapi run` { #fastapi-run } + +Exรฉcuter `fastapi run` dรฉmarre FastAPI en mode production par dรฉfaut. + +Par dรฉfaut, lโ€™**auto-reload** est dรฉsactivรฉ. Il รฉcoute aussi sur lโ€™adresse IP `0.0.0.0`, ce qui signifie toutes les adresses IP disponibles ; de cette maniรจre, il sera accessible publiquement ร  toute personne pouvant communiquer avec la machine. Cโ€™est ainsi que vous lโ€™exรฉcutez normalement en production, par exemple dans un conteneur. + +Dans la plupart des cas, vous avez (et devez avoir) un ยซ termination proxy ยป auโ€‘dessus qui gรจre le HTTPS pour vous ; cela dรฉpend de la faรงon dont vous dรฉployez votre application : votre fournisseur peut le faire pour vous, ou vous devrez le configurer vousโ€‘mรชme. + +/// tip | Astuce + +Vous pouvez en savoir plus ร  ce sujet dans la [documentation de dรฉploiement](deployment/index.md){.internal-link target=_blank}. + +/// diff --git a/docs/fr/docs/features.md b/docs/fr/docs/features.md index bc63e11b47..e5e809940a 100644 --- a/docs/fr/docs/features.md +++ b/docs/fr/docs/features.md @@ -1,43 +1,43 @@ -# Fonctionnalitรฉs +# Fonctionnalitรฉs { #features } -## Fonctionnalitรฉs de FastAPI +## Fonctionnalitรฉs de FastAPI { #fastapi-features } -**FastAPI** vous offre ceci: +**FastAPI** vous offre les รฉlรฉments suivants : -### Basรฉ sur des standards ouverts +### Basรฉ sur des standards ouverts { #based-on-open-standards } -* OpenAPI pour la crรฉation d'API, incluant la dรฉclaration de path operations, paramรจtres, corps de requรชtes, sรฉcuritรฉ, etc. -* Documentation automatique des modรจles de donnรฉes avec JSON Schema (comme OpenAPI est aussi basรฉe sur JSON Schema). -* Conรงue avec ces standards aprรจs une analyse mรฉticuleuse. Plutรดt qu'en rajoutant des surcouches aprรจs coup. -* Cela permet d'utiliser de la **gรฉnรฉration automatique de code client** dans beaucoup de langages. +* OpenAPI pour la crรฉation d'API, incluant la dรฉclaration de chemin opรฉrations, paramรจtres, corps de requรชtes, sรฉcuritรฉ, etc. +* Documentation automatique des modรจles de donnรฉes avec JSON Schema (puisque OpenAPI est lui-mรชme basรฉ sur JSON Schema). +* Conรงu autour de ces standards, aprรจs une รฉtude mรฉticuleuse. Plutรดt qu'une couche ajoutรฉe aprรจs coup. +* Cela permet รฉgalement d'utiliser la **gรฉnรฉration automatique de code client** dans de nombreux langages. -### Documentation automatique +### Documentation automatique { #automatic-docs } -Documentation d'API interactive et interface web d'exploration. Comme le framework est basรฉ sur OpenAPI, de nombreuses options sont disponibles. Deux d'entre-elles sont incluses par dรฉfaut. +Documentation d'API interactive et interfaces web d'exploration. Comme le framework est basรฉ sur OpenAPI, plusieurs options existent, 2 incluses par dรฉfaut. -* Swagger UI, propose une documentation interactive. Vous permet de directement tester l'API depuis votre navigateur. +* Swagger UI, avec exploration interactive, appelez et testez votre API directement depuis le navigateur. ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* Une autre documentation d'API est fournie par ReDoc. +* Documentation d'API alternative avec ReDoc. ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### Faite en python moderne +### Uniquement du Python moderne { #just-modern-python } -Tout est basรฉ sur la dรฉclaration de type standard de **Python 3.8** (grรขce ร  Pydantic). Pas de nouvelles syntaxes ร  apprendre. Juste du Python standard et moderne. +Tout est basรฉ sur les dรฉclarations de **types Python** standard (grรขce ร  Pydantic). Aucune nouvelle syntaxe ร  apprendre. Juste du Python moderne standard. -Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (mรชme si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}. +Si vous avez besoin d'un rappel de 2 minutes sur l'utilisation des types en Python (mรชme si vous n'utilisez pas FastAPI), consultez le court tutoriel : [Types Python](python-types.md){.internal-link target=_blank}. -Vous รฉcrivez du python standard avec des annotations de types: +Vous รฉcrivez du Python standard avec des types : ```Python from datetime import date from pydantic import BaseModel -# Dรฉclare une variable comme รฉtant une str -# et profitez de l'aide de votre IDE dans cette fonction +# Dรฉclarez une variable comme รฉtant une str +# et profitez de l'aide de l'รฉditeur dans cette fonction def main(user_id: str): return user_id @@ -48,7 +48,8 @@ class User(BaseModel): name: str joined: date ``` -Qui peuvent ensuite รชtre utilisรฉs comme cela: + +Qui peuvent ensuite รชtre utilisรฉs comme ceci : ```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") @@ -64,138 +65,137 @@ my_second_user: User = User(**second_user_data) /// info -`**second_user_data` signifie: +`**second_user_data` signifie : -Utilise les clรฉs et valeurs du dictionnaire `second_user_data` directement comme des arguments clรฉ-valeur. C'est รฉquivalent ร : `User(id=4, name="Mary", joined="2018-11-30")` +Passez les clรฉs et valeurs du dictionnaire `second_user_data` directement comme arguments clรฉ-valeur, รฉquivalent ร  : `User(id=4, name="Mary", joined="2018-11-30")` /// -### Support d'รฉditeurs +### Support des รฉditeurs { #editor-support } -Tout le framework a รฉtรฉ conรงu pour รชtre facile et intuitif d'utilisation, toutes les dรฉcisions de design ont รฉtรฉ testรฉes sur de nombreux รฉditeurs avant mรชme de commencer le dรฉveloppement final afin d'assurer la meilleure expรฉrience de dรฉveloppement possible. +Tout le framework a รฉtรฉ conรงu pour รชtre facile et intuitif ร  utiliser, toutes les dรฉcisions ont รฉtรฉ testรฉes sur plusieurs รฉditeurs avant mรชme de commencer le dรฉveloppement, pour assurer la meilleure expรฉrience de dรฉveloppement. -Dans le dernier sondage effectuรฉ auprรจs de dรฉveloppeurs python il รฉtait clair que la fonctionnalitรฉ la plus utilisรฉe est "lโ€™autocomplรฉtion". +Dans les enquรชtes auprรจs des dรฉveloppeurs Python, il est clair que lโ€™une des fonctionnalitรฉs les plus utilisรฉes est ยซ autocomplรฉtion ยป. -Tout le framework **FastAPI** a รฉtรฉ conรงu avec cela en tรชte. L'autocomplรฉtion fonctionne partout. +L'ensemble du framework **FastAPI** est conรงu pour satisfaire cela. L'autocomplรฉtion fonctionne partout. -Vous devrez rarement revenir ร  la documentation. +Vous aurez rarement besoin de revenir aux documents. -Voici comment votre รฉditeur peut vous aider: +Voici comment votre รฉditeur peut vous aider : -* dans Visual Studio Code: +* dans Visual Studio Code : ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* dans PyCharm: +* dans PyCharm : ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Vous aurez des propositions de complรฉtion que vous n'auriez jamais imaginรฉes. Par exemple la clรฉ `prix` dans le corps d'un document JSON (qui est peut-รชtre imbriquรฉ) venant d'une requรชte. +Vous obtiendrez de l'autocomplรฉtion dans du code que vous auriez pu considรฉrer impossible auparavant. Par exemple, la clรฉ `price` ร  l'intรฉrieur d'un corps JSON (qui aurait pu รชtre imbriquรฉ) provenant d'une requรชte. -Plus jamais vous ne vous tromperez en tapant le nom d'une clรฉ, vous ne ferez des aller-retour entre votre code et la documentation ou vous ne scrollerez de haut en bas afin d'enfin savoir si vous devez taper `username` ou `user_name`. +Fini de taper des noms de clรฉs erronรฉs, de faire des allers-retours entre les documents, ou de faire dรฉfiler vers le haut et vers le bas pour savoir si vous avez finalement utilisรฉ `username` ou `user_name`. -### Court +### Court { #short } -Des **valeurs par dรฉfaut** sont dรฉfinies pour tout, des configurations optionnelles sont prรฉsentent partout. Tous ces paramรจtres peuvent รชtre ajustรฉs afin de faire ce que vous voulez et dรฉfinir l'API dont vous avez besoin. +Des **valeurs par dรฉfaut** sensรฉes pour tout, avec des configurations optionnelles partout. Tous les paramรจtres peuvent รชtre ajustรฉs finement pour faire ce dont vous avez besoin et dรฉfinir l'API dont vous avez besoin. -Mais, **tout fonctionne** par dรฉfaut. +Mais par dรฉfaut, tout **ยซ just works ยป**. -### Validation +### Validation { #validation } -* Validation pour la plupart (ou tous?) les **types de donnรฉes** Python incluant: +* Validation pour la plupart (ou tous ?) des **types de donnรฉes** Python, y compris : * objets JSON (`dict`). - * listes JSON (`list`) dรฉfinissant des types d'รฉlรฉments. - * Champs String (`str`), dรฉfinition de longueur minimum ou maximale. - * Nombres (`int`, `float`) avec valeur minimale and maximale, etc. + * tableaux JSON (`list`) dรฉfinissant les types d'รฉlรฉments. + * champs String (`str`), dรฉfinition des longueurs minimale et maximale. + * nombres (`int`, `float`) avec valeurs minimale et maximale, etc. -* Validation pour des types plus exotiques, tel que: +* Validation pour des types plus exotiques, comme : * URL. * Email. * UUID. - * ...et autres. + * ... et autres. -Toutes les validations sont gรฉrรฉes par le bien รฉtabli et robuste **Pydantic**. +Toutes les validations sont gรฉrรฉes par le **Pydantic** bien รฉtabli et robuste. -### Sรฉcuritรฉ et authentification +### Sรฉcuritรฉ et authentification { #security-and-authentication } -La sรฉcuritรฉ et l'authentification sont intรฉgrรฉes. Sans aucun compromis avec les bases de donnรฉes ou les modรจles de donnรฉes. +Sรฉcuritรฉ et authentification intรฉgrรฉes. Sans aucun compromis avec les bases de donnรฉes ou les modรจles de donnรฉes. -Tous les protocoles de sรฉcuritรฉs sont dรฉfinis dans OpenAPI, incluant: +Tous les schรฉmas de sรฉcuritรฉ dรฉfinis dans OpenAPI, y compris : * HTTP Basic. -* **OAuth2** (aussi avec **JWT tokens**). Jetez un oeil au tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. -* Clรฉs d'API dans: - * Le header. - * Les paramรจtres de requรชtes. - * Les cookies, etc. +* **OAuth2** (รฉgalement avec des **tokens JWT**). Consultez le tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. +* Clรฉs d'API dans : + * les en-tรชtes. + * les paramรจtres de requรชte. + * les cookies, etc. -Plus toutes les fonctionnalitรฉs de sรฉcuritรฉs venant de Starlette (incluant les **cookies de sessions**). +Plus toutes les fonctionnalitรฉs de sรฉcuritรฉ de Starlette (y compris les **cookies de session**). -Le tout conรงu en composant rรฉutilisable facilement intรฉgrable ร  vos systรจmes, data stores, base de donnรฉes relationnelle ou NoSQL, etc. +Le tout construit comme des outils et composants rรฉutilisables, faciles ร  intรฉgrer ร  vos systรจmes, magasins de donnรฉes, bases de donnรฉes relationnelles et NoSQL, etc. -### Injection de dรฉpendances +### Injection de dรฉpendances { #dependency-injection } -FastAPI contient un systรจme simple mais extrรชmement puissant d'Injection de Dรฉpendances. +FastAPI inclut un systรจme dโ€™Injection de dรฉpendances extrรชmement simple ร  utiliser, mais extrรชmement puissant. -* Mรชme les dรฉpendances peuvent avoir des dรฉpendances, crรฉant une hiรฉrarchie ou un **"graph" de dรฉpendances** -* Tout est **automatiquement gรฉrรฉ** par le framework -* Toutes les dรฉpendances peuvent exiger des donnรฉes d'une requรชtes et **Augmenter les contraintes d'un path operation** et de la documentation automatique. -* **Validation automatique** mรชme pour les paramรจtres de *path operation* dรฉfinis dans les dรฉpendances. -* Supporte les systรจmes d'authentification d'utilisateurs complexes, les **connexions de base de donnรฉes**, etc. -* **Aucun compromis** avec les bases de donnรฉes, les frontends, etc. Mais une intรฉgration facile avec n'importe lequel d'entre eux. +* Mรชme les dรฉpendances peuvent avoir des dรฉpendances, crรฉant une hiรฉrarchie ou un **ยซ graphe ยป de dรฉpendances**. +* Le tout **gรฉrรฉ automatiquement** par le framework. +* Toutes les dรฉpendances peuvent exiger des donnรฉes des requรชtes et **augmenter les contraintes du chemin d'accรจs** ainsi que la documentation automatique. +* **Validation automatique** mรชme pour les paramรจtres de *chemin d'accรจs* dรฉfinis dans les dรฉpendances. +* Prise en charge des systรจmes d'authentification d'utilisateurs complexes, des **connexions de base de donnรฉes**, etc. +* **Aucun compromis** avec les bases de donnรฉes, les frontends, etc. Mais une intรฉgration facile avec tous. -### "Plug-ins" illimitรฉs +### ยซ Plug-ins ยป illimitรฉs { #unlimited-plug-ins } -Ou, en d'autres termes, pas besoin d'eux, importez le code que vous voulez et utilisez le. +Ou, autrement dit, pas besoin d'eux, importez et utilisez le code dont vous avez besoin. -Tout intรฉgration est conรงue pour รชtre si simple ร  utiliser (avec des dรฉpendances) que vous pouvez crรฉer un "plug-in" pour votre application en deux lignes de code utilisant la mรชme syntaxe que celle de vos *path operations* +Toute intรฉgration est conรงue pour รชtre si simple ร  utiliser (avec des dรฉpendances) que vous pouvez crรฉer un ยซ plug-in ยป pour votre application en 2 lignes de code en utilisant la mรชme structure et la mรชme syntaxe que pour vos *chemins d'accรจs*. -### Testรฉ +### Testรฉ { #tested } -* 100% de couverture de test. -* 100% d'annotations de type dans le code. -* Utilisรฉ dans des applications mises en production. +* 100 % de couverture de test. +* 100 % de base de code annotรฉe avec des types. +* Utilisรฉ dans des applications en production. -## Fonctionnalitรฉs de Starlette +## Fonctionnalitรฉs de Starlette { #starlette-features } -**FastAPI** est complรจtement compatible (et basรฉ sur) Starlette. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi. +**FastAPI** est entiรจrement compatible avec (et basรฉ sur) Starlette. Donc, tout code Starlette additionnel que vous avez fonctionnera aussi. -En fait, `FastAPI` est un sous composant de `Starlette`. Donc, si vous savez dรฉjร  comment utiliser Starlette, la plupart des fonctionnalitรฉs fonctionneront de la mรชme maniรจre. +`FastAPI` est en fait une sous-classe de `Starlette`. Ainsi, si vous connaissez ou utilisez dรฉjร  Starlette, la plupart des fonctionnalitรฉs fonctionneront de la mรชme maniรจre. -Avec **FastAPI** vous aurez toutes les fonctionnalitรฉs de **Starlette** (FastAPI est juste Starlette sous stรฉroรฏdes): +Avec **FastAPI** vous obtenez toutes les fonctionnalitรฉs de **Starlette** (puisque FastAPI est juste Starlette sous stรฉroรฏdes) : -* Des performances vraiment impressionnantes. C'est l'un des framework Python les plus rapide, ร  รฉgalitรฉ avec **NodeJS** et **GO**. -* Le support des **WebSockets**. -* Le support de **GraphQL**. -* Les tรขches d'arriรจre-plan. -* Des รฉvรจnements de dรฉmarrages et d'arrรชt. -* Un client de test basรฉ sur `request` -* **CORS**, GZip, Static Files, Streaming responses. -* Le support des **Sessions et Cookies**. -* Une couverture de test ร  100 %. -* 100 % de la base de code avec des annotations de type. +* Des performances vraiment impressionnantes. C'est lโ€™un des frameworks Python les plus rapides disponibles, ร  lโ€™รฉgal de **NodeJS** et **Go**. +* Prise en charge des **WebSocket**. +* Tรขches d'arriรจre-plan dans le processus. +* ร‰vรจnements de dรฉmarrage et d'arrรชt. +* Client de test basรฉ sur HTTPX. +* **CORS**, GZip, fichiers statiques, rรฉponses en streaming. +* Prise en charge des **Sessions et Cookies**. +* Couverture de test ร  100 %. +* Base de code annotรฉe ร  100 % avec des types. -## Fonctionnalitรฉs de Pydantic +## Fonctionnalitรฉs de Pydantic { #pydantic-features } -**FastAPI** est totalement compatible avec (et basรฉ sur) Pydantic. Le code utilisant Pydantic que vous ajouterez fonctionnera donc aussi. +**FastAPI** est entiรจrement compatible avec (et basรฉ sur) Pydantic. Donc, tout code Pydantic additionnel que vous avez fonctionnera aussi. -Inclus des librairies externes basรฉes, aussi, sur Pydantic, servent d'ORMs, ODMs pour les bases de donnรฉes. +Y compris des bibliothรจques externes รฉgalement basรฉes sur Pydantic, servant dโ€™ORM, dโ€™ODM pour les bases de donnรฉes. -Cela signifie aussi que, dans la plupart des cas, vous pouvez fournir l'objet reรงu d'une requรชte **directement ร  la base de donnรฉes**, comme tout est validรฉ automatiquement. +Cela signifie รฉgalement que, dans de nombreux cas, vous pouvez passer l'objet que vous recevez d'une requรชte **directement ร  la base de donnรฉes**, puisque tout est validรฉ automatiquement. -Inversement, dans la plupart des cas vous pourrez juste envoyer l'objet rรฉcupรฉrรฉ de la base de donnรฉes **directement au client** +Lโ€™inverse est รฉgalement vrai, dans de nombreux cas, vous pouvez simplement passer l'objet que vous rรฉcupรฉrez de la base de donnรฉes **directement au client**. -Avec **FastAPI** vous aurez toutes les fonctionnalitรฉs de **Pydantic** (comme FastAPI est basรฉ sur Pydantic pour toutes les manipulations de donnรฉes): +Avec **FastAPI** vous obtenez toutes les fonctionnalitรฉs de **Pydantic** (puisque FastAPI est basรฉ sur Pydantic pour toute la gestion des donnรฉes) : -* **Pas de prise de tรชte**: - * Pas de nouveau langage de dรฉfinition de schรฉma ร  apprendre. - * Si vous connaissez le typage en python vous savez comment utiliser Pydantic. -* Aide votre **IDE/linter/cerveau**: - * Parce que les structures de donnรฉes de pydantic consistent seulement en une instance de classe que vous dรฉfinissez; l'auto-complรฉtion, le linting, mypy et votre intuition devrait รชtre largement suffisante pour valider vos donnรฉes. -* Valide les **structures complexes**: - * Utilise les modรจles hiรฉrarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc. - * Et les validateurs permettent aux schรฉmas de donnรฉes complexes d'รชtre clairement et facilement dรฉfinis, validรฉs et documentรฉs sous forme d'un schรฉma JSON. - * Vous pouvez avoir des objets **JSON fortement imbriquรฉs** tout en ayant, pour chacun, de la validation et des annotations. -* **Renouvelable**: - * Pydantic permet de dรฉfinir de nouveaux types de donnรฉes ou vous pouvez รฉtendre la validation avec des mรฉthodes sur un modรจle dรฉcorรฉ avec le dรฉcorateur de validation -* 100% de couverture de test. +* **Pas de prise de tรชte** : + * Pas de micro-langage de dรฉfinition de schรฉma ร  apprendre. + * Si vous connaissez les types Python vous savez utiliser Pydantic. +* Fonctionne bien avec votre **IDE/linter/cerveau** : + * Parce que les structures de donnรฉes de Pydantic sont simplement des instances de classes que vous dรฉfinissez ; l'autocomplรฉtion, le linting, mypy et votre intuition devraient tous bien fonctionner avec vos donnรฉes validรฉes. +* Valider des **structures complexes** : + * Utilisation de modรจles Pydantic hiรฉrarchiques, de `List` et `Dict` du `typing` Python, etc. + * Et les validateurs permettent de dรฉfinir, vรฉrifier et documenter clairement et facilement des schรฉmas de donnรฉes complexes en tant que JSON Schema. + * Vous pouvez avoir des objets **JSON fortement imbriquรฉs** et les faire tous valider et annoter. +* **Extensible** : + * Pydantic permet de dรฉfinir des types de donnรฉes personnalisรฉs ou vous pouvez รฉtendre la validation avec des mรฉthodes sur un modรจle dรฉcorรฉ avec le dรฉcorateur de validation. +* Couverture de test ร  100 %. diff --git a/docs/fr/docs/help-fastapi.md b/docs/fr/docs/help-fastapi.md index 9b75f463b9..08d9a7a723 100644 --- a/docs/fr/docs/help-fastapi.md +++ b/docs/fr/docs/help-fastapi.md @@ -1,103 +1,255 @@ -# Help FastAPI - Obtenir de l'aide +# Aider FastAPI - Obtenir de l'aide { #help-fastapi-get-help } Aimez-vous **FastAPI** ? -Vous souhaitez aider FastAPI, les autres utilisateurs et l'auteur ? +Souhaitez-vous aider FastAPI, les autres utilisateurs et l'auteur ? -Ou souhaitez-vous obtenir de l'aide avec le **FastAPI** ? +Ou souhaitez-vous obtenir de l'aide avec **FastAPI** ? Il existe des moyens trรจs simples d'aider (plusieurs ne nรฉcessitent qu'un ou deux clics). -Il existe รฉgalement plusieurs faรงons d'obtenir de l'aide. +Et il existe aussi plusieurs faรงons d'obtenir de l'aide. -## Star **FastAPI** sur GitHub +## S'abonner ร  la newsletter { #subscribe-to-the-newsletter } -Vous pouvez "star" FastAPI dans GitHub (en cliquant sur le bouton รฉtoile en haut ร  droite) : https://github.com/fastapi/fastapi. โญ๏ธ +Vous pouvez vous abonner ร  la (peu frรฉquente) [newsletter **FastAPI and friends**](newsletter.md){.internal-link target=_blank} pour rester informรฉ ร  proposย : -En ajoutant une รฉtoile, les autres utilisateurs pourront la trouver plus facilement et constater qu'elle a dรฉjร  รฉtรฉ utile ร  d'autres. +* Nouvelles sur FastAPI et ses amis ๐Ÿš€ +* Guides ๐Ÿ“ +* Fonctionnalitรฉs โœจ +* Changements majeurs ๐Ÿšจ +* Astuces et conseils โœ… -## Watch le dรฉpรดt GitHub pour les releases +## Suivre FastAPI sur X (Twitter) { #follow-fastapi-on-x-twitter } -Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut ร  droite) : https://github.com/fastapi/fastapi. ๐Ÿ‘€ +Suivez @fastapi sur **X (Twitter)** pour obtenir les derniรจres nouvelles sur **FastAPI**. ๐Ÿฆ -Vous pouvez y sรฉlectionner "Releases only". +## Mettre une รฉtoile ร  **FastAPI** sur GitHub { #star-fastapi-in-github } -Ainsi, vous recevrez des notifications (dans votre courrier รฉlectronique) chaque fois qu'il y aura une nouvelle version de **FastAPI** avec des corrections de bugs et de nouvelles fonctionnalitรฉs. +Vous pouvez ยซ star ยป FastAPI sur GitHub (en cliquant sur le bouton รฉtoile en haut ร  droite) : https://github.com/fastapi/fastapi. โญ๏ธ -## Se rapprocher de l'auteur +En ajoutant une รฉtoile, les autres utilisateurs pourront le trouver plus facilement et voir qu'il a dรฉjร  รฉtรฉ utile ร  d'autres. -Vous pouvez vous rapprocher de moi (Sebastiรกn Ramรญrez / `tiangolo`), l'auteur. +## Suivre le dรฉpรดt GitHub pour les releases { #watch-the-github-repository-for-releases } -Vous pouvez : +Vous pouvez ยซ watch ยป FastAPI sur GitHub (en cliquant sur le bouton ยซ watch ยป en haut ร  droite) : https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +Vous pouvez y sรฉlectionner ยซ Releases only ยป. + +Ainsi, vous recevrez des notifications (par eโ€‘mail) chaque fois qu'il y aura une nouvelle release (une nouvelle version) de **FastAPI** avec des corrections de bugs et de nouvelles fonctionnalitรฉs. + +## Entrer en contact avec l'auteur { #connect-with-the-author } + +Vous pouvez entrer en contact avec moi (Sebastiรกn Ramรญrez / `tiangolo`), l'auteur. + +Vous pouvezย : * Me suivre sur **GitHub**. * Voir d'autres projets Open Source que j'ai crรฉรฉs et qui pourraient vous aider. - * Suivez-moi pour voir quand je crรฉe un nouveau projet Open Source. -* Me suivre sur **X (Twitter)**. - * Dites-moi comment vous utilisez FastAPI (j'adore entendre รงa). - * Entendre quand je fais des annonces ou que je lance de nouveaux outils. -* Vous connectez ร  moi sur **LinkedIn**. - * Etre notifiรฉ quand je fais des annonces ou que je lance de nouveaux outils (bien que j'utilise plus souvent X (Twitter) ๐Ÿคทโ€โ™‚). -* Lire ce que jโ€™รฉcris (ou me suivre) sur **Dev.to** ou **Medium**. - * Lire d'autres idรฉes, articles, et sur les outils que j'ai crรฉรฉs. - * Suivez-moi pour lire quand je publie quelque chose de nouveau. + * Me suivre pour voir quand je crรฉe un nouveau projet Open Source. +* Me suivre sur **X (Twitter)** ou sur Mastodon. + * Me dire comment vous utilisez FastAPI (j'adore l'entendre). + * รŠtre informรฉ quand je fais des annonces ou publie de nouveaux outils. + * Vous pouvez aussi suivre @fastapi sur X (Twitter) (un compte sรฉparรฉ). +* Me suivre sur **LinkedIn**. + * รŠtre informรฉ quand je fais des annonces ou publie de nouveaux outils (mรชme si j'utilise plus souvent X (Twitter) ๐Ÿคทโ€โ™‚). +* Lire ce que j'รฉcris (ou me suivre) sur **Dev.to** ou **Medium**. + * Lire d'autres idรฉes, des articles, et dรฉcouvrir des outils que j'ai crรฉรฉs. + * Me suivre pour lire quand je publie quelque chose de nouveau. -## Tweeter sur **FastAPI** +## Tweeter ร  propos de **FastAPI** { #tweet-about-fastapi } -Tweetez ร  propos de **FastAPI** et faites-moi savoir, ainsi qu'aux autres, pourquoi vous aimez รงa. ๐ŸŽ‰ +Tweetez ร  propos de **FastAPI** et faites savoir ร  moi et aux autres pourquoi vous l'apprรฉciez. ๐ŸŽ‰ -J'aime entendre parler de l'utilisation du **FastAPI**, de ce que vous avez aimรฉ dedans, dans quel projet/entreprise l'utilisez-vous, etc. +J'adore entendre comment **FastAPI** est utilisรฉ, ce que vous avez aimรฉ, dans quel projet/quelle entreprise vous l'utilisez, etc. -## Voter pour FastAPI +## Voter pour FastAPI { #vote-for-fastapi } * Votez pour **FastAPI** sur Slant. -* Votez pour **FastAPI** sur AlternativeTo. -* Votez pour **FastAPI** sur awesome-rest. +* Votez pour **FastAPI** sur AlternativeTo. +* Indiquez que vous utilisez **FastAPI** sur StackShare. + +## Aider les autres avec des questions sur GitHub { #help-others-with-questions-in-github } + +Vous pouvez essayer d'aider les autres avec leurs questions dansย : + +* GitHub Discussions +* GitHub Issues + +Dans de nombreux cas, vous connaissez peut-รชtre dรฉjร  la rรฉponse ร  ces questions. ๐Ÿค“ + +Si vous aidez beaucoup de personnes avec leurs questions, vous deviendrez un [Expert FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank} officiel. ๐ŸŽ‰ + +N'oubliez pas, le point le plus important est : essayez d'รชtre aimable. Les gens viennent avec leurs frustrations et, dans bien des cas, ne posent pas la question de la meilleure faรงon, mais faites de votre mieux pour rester aimable. ๐Ÿค— + +L'idรฉe est que la communautรฉ **FastAPI** soit bienveillante et accueillante. En mรชme temps, n'acceptez pas l'intimidation ni les comportements irrespectueux envers les autres. Nous devons prendre soin les uns des autres. + +--- + +Voici comment aider les autres avec des questions (dans les discussions ou les issues)ย : + +### Comprendre la question { #understand-the-question } + +* Vรฉrifiez si vous comprenez quel est lโ€™**objectif** et le cas d'utilisation de la personne qui pose la question. + +* Ensuite, vรฉrifiez si la question (la grande majoritรฉ sont des questions) est **claire**. -## Aider les autres ร  rรฉsoudre les problรจmes dans GitHub +* Dans de nombreux cas, la question porte sur une solution imaginaire de l'utilisateur, mais il pourrait y en avoir une **meilleure**. Si vous comprenez mieux le problรจme et le cas d'utilisation, vous pourriez suggรฉrer une **solution alternative** plus adaptรฉe. -Vous pouvez voir les problรจmes existants et essayer d'aider les autres, la plupart du temps il s'agit de questions dont vous connaissez peut-รชtre dรฉjร  la rรฉponse. ๐Ÿค“ +* Si vous ne comprenez pas la question, demandez plus de **dรฉtails**. -## Watch le dรฉpรดt GitHub +### Reproduire le problรจme { #reproduce-the-problem } -Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut ร  droite) : https://github.com/fastapi/fastapi. ๐Ÿ‘€ +Dans la plupart des cas et pour la plupart des questions, il y a quelque chose liรฉ au **code original** de la personne. -Si vous sรฉlectionnez "Watching" au lieu de "Releases only", vous recevrez des notifications lorsque quelqu'un crรฉe une nouvelle Issue. +Dans de nombreux cas, elle ne copiera qu'un fragment de code, mais ce n'est pas suffisant pour **reproduire le problรจme**. -Vous pouvez alors essayer de les aider ร  rรฉsoudre ces problรจmes. +* Vous pouvez leur demander de fournir un exemple minimal, complet et vรฉrifiable, que vous pouvez **copierโ€‘coller** et exรฉcuter localement pour voir la mรชme erreur ou le mรชme comportement qu'ils observent, ou pour mieux comprendre leur cas d'utilisation. -## Crรฉer une Issue +* Si vous vous sentez trรจs gรฉnรฉreux, vous pouvez essayer de **crรฉer un tel exemple** vousโ€‘mรชme, simplement ร  partir de la description du problรจme. Gardez simplement ร  l'esprit que cela peut prendre beaucoup de temps et qu'il peut รชtre prรฉfรฉrable de leur demander d'abord de clarifier le problรจme. -Vous pouvez crรฉer une Issue dans le dรฉpรดt GitHub, par exemple pour : +### Suggรฉrer des solutions { #suggest-solutions } -* Poser une question ou s'informer sur un problรจme. -* Suggรฉrer une nouvelle fonctionnalitรฉ. +* Aprรจs avoir compris la question, vous pouvez leur donner une **rรฉponse** possible. + +* Dans de nombreux cas, il est prรฉfรฉrable de comprendre leur **problรจme sousโ€‘jacent ou cas d'utilisation**, car il pourrait exister une meilleure faรงon de le rรฉsoudre que ce qu'ils essaient de faire. + +### Demander la clรดture { #ask-to-close } + +S'ils rรฉpondent, il y a de fortes chances que vous ayez rรฉsolu leur problรจme, bravo, **vous รชtes un hรฉros** ! ๐Ÿฆธ + +* Maintenant, si cela a rรฉsolu leur problรจme, vous pouvez leur demander deย : + + * Dans GitHub Discussions : marquer le commentaire comme **rรฉponse**. + * Dans GitHub Issues : **fermer** l'issue. + +## Suivre le dรฉpรดt GitHub { #watch-the-github-repository } + +Vous pouvez ยซ watch ยป FastAPI sur GitHub (en cliquant sur le bouton ยซ watch ยป en haut ร  droite) : https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +Si vous sรฉlectionnez ยซ Watching ยป au lieu de ยซ Releases only ยป, vous recevrez des notifications lorsque quelqu'un crรฉe une nouvelle issue ou question. Vous pouvez aussi prรฉciser que vous ne souhaitez รชtre notifiรฉ que pour les nouvelles issues, ou les discussions, ou les PR, etc. + +Vous pouvez alors essayer de les aider ร  rรฉsoudre ces questions. + +## Poser des questions { #ask-questions } + +Vous pouvez crรฉer une nouvelle question dans le dรฉpรดt GitHub, par exemple pourย : + +* Poser une **question** ou demander ร  propos d'un **problรจme**. +* Suggรฉrer une nouvelle **fonctionnalitรฉ**. + +**Remarque** : si vous le faites, je vais vous demander d'aider aussi les autres. ๐Ÿ˜‰ + +## Relire des Pull Requests { #review-pull-requests } + +Vous pouvez m'aider ร  relire les pull requests des autres. + +Encore une fois, essayez autant que possible d'รชtre aimable. ๐Ÿค— + +--- -**Note** : si vous crรฉez un problรจme, alors je vais vous demander d'aider aussi les autres. ๐Ÿ˜‰ +Voici ce ร  garder ร  l'esprit et comment relire une pull requestย : -## Crรฉer une Pull Request +### Comprendre le problรจme { #understand-the-problem } -Vous pouvez crรฉer une Pull Request, par exemple : +* D'abord, assurezโ€‘vous de **comprendre le problรจme** que la pull request essaie de rรฉsoudre. Il peut y avoir une discussion plus longue dans une GitHub Discussion ou une issue. -* Pour corriger une faute de frappe que vous avez trouvรฉe sur la documentation. +* Il y a aussi de bonnes chances que la pull request ne soit pas rรฉellement nรฉcessaire parce que le problรจme peut รชtre rรฉsolu d'une **autre maniรจre**. Vous pouvez alors le suggรฉrer ou poser la question. + +### Ne pas s'inquiรฉter du style { #dont-worry-about-style } + +* Ne vous souciez pas trop des choses comme les styles de messages de commit, je ferai un squash and merge en personnalisant le commit manuellement. + +* Ne vous inquiรฉtez pas non plus des rรจgles de style, il existe dรฉjร  des outils automatisรฉs qui vรฉrifient cela. + +Et s'il y a d'autres besoins de style ou de cohรฉrence, je le demanderai directement, ou j'ajouterai des commits parโ€‘dessus avec les changements nรฉcessaires. + +### Vรฉrifier le code { #check-the-code } + +* Vรฉrifiez et lisez le code, voyez s'il a du sens, **exรฉcutezโ€‘le localement** et voyez s'il rรฉsout effectivement le problรจme. + +* Ensuite, **commentez** en disant que vous l'avez fait, c'est ainsi que je saurai que vous l'avez vraiment vรฉrifiรฉ. + +/// info + +Malheureusement, je ne peux pas simplement faire confiance aux PR qui ont juste plusieurs approbations. + +Plusieurs fois, il est arrivรฉ qu'il y ait des PR avec 3, 5 ou plus approbations, probablement parce que la description est attrayante, mais lorsque je vรฉrifie les PR, elles sont en fait cassรฉes, ont un bug, ou ne rรฉsolvent pas le problรจme qu'elles prรฉtendent rรฉsoudre. ๐Ÿ˜… + +Donc, il est vraiment important que vous lisiez et exรฉcutiez le code, et que vous me le disiez dans les commentaires. ๐Ÿค“ + +/// + +* Si la PR peut รชtre simplifiรฉe d'une certaine maniรจre, vous pouvez le demander, mais il n'est pas nรฉcessaire d'รชtre trop pointilleux, il peut y avoir beaucoup de points de vue subjectifs (et j'aurai les miens aussi ๐Ÿ™ˆ), donc il est prรฉfรฉrable de vous concentrer sur les choses fondamentales. + +### Tests { #tests } + +* Aidezโ€‘moi ร  vรฉrifier que la PR a des **tests**. + +* Vรฉrifiez que les tests **รฉchouent** avant la PR. ๐Ÿšจ + +* Puis vรฉrifiez que les tests **rรฉussissent** aprรจs la PR. โœ… + +* Beaucoup de PR n'ont pas de tests, vous pouvez leur **rappeler** d'ajouter des tests, ou mรชme **suggรฉrer** des tests vousโ€‘mรชme. C'est l'une des choses qui consomment le plus de temps et vous pouvez beaucoup aider. + +* Commentez aussi ce que vous avez essayรฉ, ainsi je saurai que vous l'avez vรฉrifiรฉ. ๐Ÿค“ + +## Crรฉer une Pull Request { #create-a-pull-request } + +Vous pouvez [contribuer](contributing.md){.internal-link target=_blank} au code source avec des Pull Requests, par exempleย : + +* Corriger une coquille que vous avez trouvรฉe dans la documentation. +* Partager un article, une vidรฉo ou un podcast que vous avez crรฉรฉ ou trouvรฉ ร  propos de FastAPI en modifiant ce fichier. + * Vous devez vous assurer d'ajouter votre lien au dรฉbut de la section correspondante. +* Aider ร  [traduire la documentation](contributing.md#translations){.internal-link target=_blank} dans votre langue. + * Vous pouvez aussi aider ร  relire les traductions crรฉรฉes par d'autres. * Proposer de nouvelles sections de documentation. -* Pour corriger une Issue/Bug existant. -* Pour ajouter une nouvelle fonctionnalitรฉ. +* Corriger une issue/un bug existant. + * Vous devez ajouter des tests. +* Ajouter une nouvelle fonctionnalitรฉ. + * Vous devez ajouter des tests. + * Vous devez ajouter de la documentation si c'est pertinent. + +## Aider ร  maintenir FastAPI { #help-maintain-fastapi } + +Aidezโ€‘moi ร  maintenir **FastAPI** ! ๐Ÿค“ + +Il y a beaucoup de travail ร  faire, et pour la plupart, **VOUS** pouvez le faire. + +Les principales tรขches que vous pouvez faire dรจs maintenant sontย : + +* [Aider les autres avec des questions sur GitHub](#help-others-with-questions-in-github){.internal-link target=_blank} (voir la section ciโ€‘dessus). +* [Relire des Pull Requests](#review-pull-requests){.internal-link target=_blank} (voir la section ciโ€‘dessus). + +Ces deux tรขches sont celles qui **consomment le plus de temps**. C'est le travail principal de la maintenance de FastAPI. + +Si vous pouvez m'aider avec cela, **vous m'aidez ร  maintenir FastAPI** et ร  vous assurer qu'il continue **d'avancer plus vite et mieux**. ๐Ÿš€ + +## Rejoindre le chat { #join-the-chat } + +Rejoignez le ๐Ÿ‘ฅ serveur Discord ๐Ÿ‘ฅ et รฉchangez avec d'autres membres de la communautรฉ FastAPI. + +/// tip | Astuce + +Pour les questions, posezโ€‘les dans GitHub Discussions, vous avez bien plus de chances de recevoir de l'aide par les [Experts FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}. + +Utilisez le chat uniquement pour d'autres conversations gรฉnรฉrales. + +/// -## Parrainer l'auteur +### N'utilisez pas le chat pour les questions { #dont-use-the-chat-for-questions } -Vous pouvez รฉgalement soutenir financiรจrement l'auteur (moi) via GitHub sponsors. +Gardez ร  l'esprit que, comme les chats permettent une ยซ conversation libre ยป, il est facile de poser des questions trop gรฉnรฉrales et plus difficiles ร  rรฉpondre ; vous pourriez donc ne pas recevoir de rรฉponses. -Lร , vous pourriez m'offrir un cafรฉ โ˜•๏ธ pour me remercier ๐Ÿ˜„. +Sur GitHub, le modรจle vous guidera pour rรฉdiger la bonne question afin que vous puissiez plus facilement obtenir une bonne rรฉponse, ou mรชme rรฉsoudre le problรจme vousโ€‘mรชme avant de demander. Et sur GitHub, je peux m'assurer de toujours tout rรฉpondre, mรชme si cela prend du temps. Je ne peux pas personnellement faire cela avec les systรจmes de chat. ๐Ÿ˜… -## Sponsoriser les outils qui font fonctionner FastAPI +Les conversations dans les systรจmes de chat ne sont pas non plus aussi facilement recherchables que sur GitHub, donc les questions et rรฉponses peuvent se perdre dans la conversation. Et seules celles sur GitHub comptent pour devenir un [Expert FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, vous aurez donc trรจs probablement plus d'attention sur GitHub. -Comme vous l'avez vu dans la documentation, FastAPI se tient sur les รฉpaules des gรฉants, Starlette et Pydantic. +D'un autre cรดtรฉ, il y a des milliers d'utilisateurs dans les systรจmes de chat, il y a donc de fortes chances que vous trouviez presque toujours quelqu'un avec qui parler. ๐Ÿ˜„ -Vous pouvez รฉgalement parrainer : +## Sponsoriser l'auteur { #sponsor-the-author } -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +Si votre **produit/entreprise** dรฉpend de **FastAPI** ou y est liรฉ et que vous souhaitez atteindre ses utilisateurs, vous pouvez sponsoriser l'auteur (moi) via GitHub sponsors. Selon le niveau, vous pourriez obtenir des avantages supplรฉmentaires, comme un badge dans la documentation. ๐ŸŽ --- diff --git a/docs/fr/docs/history-design-future.md b/docs/fr/docs/history-design-future.md index 15be545ee6..300f2e0f5c 100644 --- a/docs/fr/docs/history-design-future.md +++ b/docs/fr/docs/history-design-future.md @@ -1,4 +1,4 @@ -# Histoire, conception et avenir +# Histoire, conception et avenir { #history-design-and-future } Il y a quelque temps, un utilisateur de **FastAPI** a demandรฉ : @@ -6,7 +6,7 @@ Il y a quelque temps, @@ -28,7 +28,7 @@ Mais ร  un moment donnรฉ, il n'y avait pas d'autre option que de crรฉer quelque -## Recherche +## Recherche { #investigation } En utilisant toutes les alternatives prรฉcรฉdentes, j'ai eu la chance d'apprendre de toutes, de prendre des idรฉes, et de les combiner de la meilleure faรงon que j'ai pu trouver pour moi-mรชme et les รฉquipes de dรฉveloppeurs avec lesquelles j'ai travaillรฉ. @@ -38,9 +38,9 @@ De plus, la meilleure approche รฉtait d'utiliser des normes dรฉjร  existantes. Ainsi, avant mรชme de commencer ร  coder **FastAPI**, j'ai passรฉ plusieurs mois ร  รฉtudier les spรฉcifications d'OpenAPI, JSON Schema, OAuth2, etc. Comprendre leurs relations, leurs similaritรฉs et leurs diffรฉrences. -## Conception +## Conception { #design } -Ensuite, j'ai passรฉ du temps ร  concevoir l'"API" de dรฉveloppeur que je voulais avoir en tant qu'utilisateur (en tant que dรฉveloppeur utilisant FastAPI). +Ensuite, j'ai passรฉ du temps ร  concevoir l'ยซ API ยป de dรฉveloppeur que je voulais avoir en tant qu'utilisateur (en tant que dรฉveloppeur utilisant FastAPI). J'ai testรฉ plusieurs idรฉes dans les รฉditeurs Python les plus populaires : PyCharm, VS Code, les รฉditeurs basรฉs sur Jedi. @@ -48,11 +48,11 @@ D'aprรจs la derniรจre **Pydantic** pour ses avantages. @@ -60,11 +60,11 @@ J'y ai ensuite contribuรฉ, pour le rendre entiรจrement compatible avec JSON Sche Pendant le dรฉveloppement, j'ai รฉgalement contribuรฉ ร  **Starlette**, l'autre exigence clรฉ. -## Dรฉveloppement +## Dรฉveloppement { #development } Au moment oรน j'ai commencรฉ ร  crรฉer **FastAPI** lui-mรชme, la plupart des piรจces รฉtaient dรฉjร  en place, la conception รฉtait dรฉfinie, les exigences et les outils รฉtaient prรชts, et la connaissance des normes et des spรฉcifications รฉtait claire et fraรฎche. -## Futur +## Futur { #future } ร€ ce stade, il est dรฉjร  clair que **FastAPI** et ses idรฉes sont utiles pour de nombreuses personnes. @@ -76,4 +76,4 @@ Mais il y a encore de nombreuses amรฉliorations et fonctionnalitรฉs ร  venir. **FastAPI** a un grand avenir devant lui. -Et [votre aide](help-fastapi.md){.internal-link target=\_blank} est grandement apprรฉciรฉe. +Et [votre aide](help-fastapi.md){.internal-link target=_blank} est grandement apprรฉciรฉe. diff --git a/docs/fr/docs/how-to/authentication-error-status-code.md b/docs/fr/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..b8e87ee71e --- /dev/null +++ b/docs/fr/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# Utiliser les anciens codes d'erreur d'authentification 403 { #use-old-403-authentication-error-status-codes } + +Avant FastAPI version `0.122.0`, lorsque les utilitaires de sรฉcuritรฉ intรฉgrรฉs renvoyaient une erreur au client aprรจs un รฉchec d'authentification, ils utilisaient le code d'รฉtat HTTP `403 Forbidden`. + +ร€ partir de FastAPI version `0.122.0`, ils utilisent le code d'รฉtat HTTP plus appropriรฉ `401 Unauthorized`, et renvoient un en-tรชte `WWW-Authenticate` pertinent dans la rรฉponse, conformรฉment aux spรฉcifications HTTP, RFC 7235, RFC 9110. + +Mais si, pour une raison quelconque, vos clients dรฉpendent de l'ancien comportement, vous pouvez y revenir en surchargeant la mรฉthode `make_not_authenticated_error` dans vos classes de sรฉcuritรฉ. + +Par exemple, vous pouvez crรฉer une sous-classe de `HTTPBearer` qui renvoie une erreur `403 Forbidden` au lieu de l'erreur par dรฉfaut `401 Unauthorized` : + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | Astuce + +Remarquez que la fonction renvoie l'instance de l'exception, elle ne la lรจve pas. La levรฉe est effectuรฉe dans le reste du code interne. + +/// diff --git a/docs/fr/docs/how-to/conditional-openapi.md b/docs/fr/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000..61aa187cc5 --- /dev/null +++ b/docs/fr/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# Configurer OpenAPI de maniรจre conditionnelle { #conditional-openapi } + +Si nรฉcessaire, vous pouvez utiliser des paramรจtres et des variables d'environnement pour configurer OpenAPI de maniรจre conditionnelle selon l'environnement, et mรชme le dรฉsactiver complรจtement. + +## ร€ propos de la sรฉcuritรฉ, des API et de la documentation { #about-security-apis-and-docs } + +Masquer vos interfaces utilisateur de la documentation en production ne devrait pas รชtre la maniรจre de protรฉger votre API. + +Cela n'ajoute aucune sรฉcuritรฉ supplรฉmentaire ร  votre API, les *chemins d'accรจs* resteront disponibles lร  oรน ils se trouvent. + +S'il y a une faille de sรฉcuritรฉ dans votre code, elle existera toujours. + +Masquer la documentation rend simplement plus difficile la comprรฉhension de la maniรจre d'interagir avec votre API et pourrait aussi rendre son dรฉbogage en production plus difficile. Cela pourrait รชtre considรฉrรฉ simplement comme une forme de Sรฉcuritรฉ par l'obscuritรฉ. + +Si vous voulez sรฉcuriser votre API, il y a plusieurs meilleures approches possibles, par exemple : + +* Vous devez vous assurer d'avoir des modรจles Pydantic bien dรฉfinis pour le corps de la requรชte et la rรฉponse. +* Configurez toutes les autorisations et tous les rรดles nรฉcessaires ร  l'aide de dรฉpendances. +* Ne stockez jamais de mots de passe en clair, seulement des hachages de mots de passe. +* Implรฉmentez et utilisez des outils cryptographiques reconnus, comme pwdlib et des jetons JWT, ... etc. +* Ajoutez des contrรดles d'autorisation plus granulaires avec des scopes OAuth2 lorsque nรฉcessaire. +* ... etc. + +Nรฉanmoins, vous pourriez avoir un cas d'utilisation trรจs spรฉcifique oรน vous devez vraiment dรฉsactiver la documentation de l'API pour un certain environnement (par exemple pour la production) ou selon des configurations provenant de variables d'environnement. + +## Configurer OpenAPI de maniรจre conditionnelle avec des paramรจtres et des variables d'environnement { #conditional-openapi-from-settings-and-env-vars } + +Vous pouvez facilement utiliser les mรชmes paramรจtres Pydantic pour configurer votre OpenAPI gรฉnรฉrรฉ et les interfaces utilisateur de la documentation. + +Par exemple : + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +Ici nous dรฉclarons le paramรจtre `openapi_url` avec la mรชme valeur par dรฉfaut `"/openapi.json"`. + +Nous l'utilisons ensuite lors de la crรฉation de l'application `FastAPI`. + +Vous pouvez alors dรฉsactiver OpenAPI (y compris les interfaces utilisateur de la documentation) en dรฉfinissant la variable d'environnement `OPENAPI_URL` sur la chaรฎne vide, comme ceci : + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ensuite, si vous allez aux URL `/openapi.json`, `/docs` ou `/redoc`, vous obtiendrez simplement une erreur `404 Not Found` comme : + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/fr/docs/how-to/configure-swagger-ui.md b/docs/fr/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000..73d0f00e81 --- /dev/null +++ b/docs/fr/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Configurer Swagger UI { #configure-swagger-ui } + +Vous pouvez configurer des paramรจtres supplรฉmentaires de Swagger UI. + +Pour les configurer, passez l'argument `swagger_ui_parameters` lors de la crรฉation de l'objet d'application `FastAPI()` ou ร  la fonction `get_swagger_ui_html()`. + +`swagger_ui_parameters` reรงoit un dictionnaire avec les configurations passรฉes directement ร  Swagger UI. + +FastAPI convertit les configurations en **JSON** pour les rendre compatibles avec JavaScript, car c'est ce dont Swagger UI a besoin. + +## Dรฉsactiver la coloration syntaxique { #disable-syntax-highlighting } + +Par exemple, vous pourriez dรฉsactiver la coloration syntaxique dans Swagger UI. + +Sans modifier les paramรจtres, la coloration syntaxique est activรฉe par dรฉfaut : + + + +Mais vous pouvez la dรฉsactiver en dรฉfinissant `syntaxHighlight` ร  `False` : + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +... et ensuite Swagger UI n'affichera plus la coloration syntaxique : + + + +## Modifier le thรจme { #change-the-theme } + +De la mรชme maniรจre, vous pouvez dรฉfinir le thรจme de la coloration syntaxique avec la clรฉ ยซ syntaxHighlight.theme ยป (remarquez le point au milieu) : + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +Cette configuration modifierait le thรจme de couleurs de la coloration syntaxique : + + + +## Modifier les paramรจtres Swagger UI par dรฉfaut { #change-default-swagger-ui-parameters } + +FastAPI inclut des paramรจtres de configuration par dรฉfaut adaptรฉs ร  la plupart des cas d'utilisation. + +Il inclut ces configurations par dรฉfaut : + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +Vous pouvez remplacer n'importe lequel d'entre eux en dรฉfinissant une valeur diffรฉrente dans l'argument `swagger_ui_parameters`. + +Par exemple, pour dรฉsactiver `deepLinking`, vous pourriez passer ces paramรจtres ร  `swagger_ui_parameters` : + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## Autres paramรจtres de Swagger UI { #other-swagger-ui-parameters } + +Pour voir toutes les autres configurations possibles que vous pouvez utiliser, lisez la documentation officielle des paramรจtres de Swagger UI. + +## Paramรจtres JavaScript uniquement { #javascript-only-settings } + +Swagger UI permet รฉgalement d'autres configurations qui sont des objets rรฉservรฉs ร  JavaScript (par exemple, des fonctions JavaScript). + +FastAPI inclut aussi ces paramรจtres `presets` rรฉservรฉs ร  JavaScript : + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +Ce sont des objets **JavaScript**, pas des chaรฎnes, vous ne pouvez donc pas les passer directement depuis du code Python. + +Si vous devez utiliser des configurations rรฉservรฉes ร  JavaScript comme celles-ci, vous pouvez utiliser l'une des mรฉthodes ci-dessus. Surchargez entiรจrement le *chemin d'accรจs* Swagger UI et รฉcrivez manuellement tout JavaScript nรฉcessaire. diff --git a/docs/fr/docs/how-to/custom-docs-ui-assets.md b/docs/fr/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..d239a9696a --- /dev/null +++ b/docs/fr/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# Hรฉberger en propre les ressources statiques de lโ€™UI des docs personnalisรฉes { #custom-docs-ui-static-assets-self-hosting } + +Les documents de lโ€™API utilisent **Swagger UI** et **ReDoc**, et chacune nรฉcessite des fichiers JavaScript et CSS. + +Par dรฉfaut, ces fichiers sont servis depuis un CDN. + +Mais il est possible de le personnaliser : vous pouvez dรฉfinir un CDN spรฉcifique, ou servir vousโ€‘mรชme les fichiers. + +## Configurer un CDN personnalisรฉ pour JavaScript et CSS { #custom-cdn-for-javascript-and-css } + +Supposons que vous souhaitiez utiliser un autre CDN, par exemple vous voulez utiliser `https://unpkg.com/`. + +Cela peut รชtre utile si, par exemple, vous vivez dans un pays qui restreint certaines URL. + +### Dรฉsactiver les docs automatiques { #disable-the-automatic-docs } + +La premiรจre รฉtape consiste ร  dรฉsactiver les docs automatiques, car par dรฉfaut elles utilisent le CDN par dรฉfaut. + +Pour les dรฉsactiver, dรฉfinissez leurs URL sur `None` lors de la crรฉation de votre application `FastAPI` : + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### Inclure les docs personnalisรฉes { #include-the-custom-docs } + +Vous pouvez maintenant crรฉer les chemins d'accรจs pour les docs personnalisรฉes. + +Vous pouvez rรฉutiliser les fonctions internes de FastAPI pour crรฉer les pages HTML de la documentation et leur passer les arguments nรฉcessaires : + +- `openapi_url` : lโ€™URL oรน la page HTML des docs peut rรฉcupรฉrer le schรฉma OpenAPI de votre API. Vous pouvez utiliser ici lโ€™attribut `app.openapi_url`. +- `title` : le titre de votre API. +- `oauth2_redirect_url` : vous pouvez utiliser `app.swagger_ui_oauth2_redirect_url` ici pour utiliser la valeur par dรฉfaut. +- `swagger_js_url` : lโ€™URL oรน la page HTML de Swagger UI peut rรฉcupรฉrer le fichier **JavaScript**. Cโ€™est lโ€™URL du CDN personnalisรฉ. +- `swagger_css_url` : lโ€™URL oรน la page HTML de Swagger UI peut rรฉcupรฉrer le fichier **CSS**. Cโ€™est lโ€™URL du CDN personnalisรฉ. + +Et de mรชme pour ReDoc ... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | Astuce + +Le chemin d'accรจs pour `swagger_ui_redirect` est un assistant lorsque vous utilisez OAuth2. + +Si vous intรฉgrez votre API ร  un fournisseur OAuth2, vous pourrez vous authentifier et revenir aux docs de lโ€™API avec les identifiants acquis. Et interagir avec elle en utilisant la vรฉritable authentification OAuth2. + +Swagger UI sโ€™en chargera en arriรจreโ€‘plan pour vous, mais il a besoin de cet assistant ยซ redirect ยป. + +/// + +### Crรฉer un chemin d'accรจs pour tester { #create-a-path-operation-to-test-it } + +Maintenant, pour pouvoir vรฉrifier que tout fonctionne, crรฉez un chemin d'accรจs : + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### Tester { #test-it } + +Vous devriez maintenant pouvoir aller ร  vos docs sur http://127.0.0.1:8000/docs, puis recharger la page : elle chargera ces ressources depuis le nouveau CDN. + +## Hรฉberger en propre JavaScript et CSS pour les docs { #self-hosting-javascript-and-css-for-docs } + +Hรฉberger vousโ€‘mรชme le JavaScript et le CSS peut รชtre utile si, par exemple, votre application doit continuer de fonctionner mรชme hors ligne, sans accรจs Internet ouvert, ou sur un rรฉseau local. + +Vous verrez ici comment servir ces fichiers vousโ€‘mรชme, dans la mรชme application FastAPI, et configurer les docs pour les utiliser. + +### Structure des fichiers du projet { #project-file-structure } + +Supposons que la structure de vos fichiers de projet ressemble ร  ceci : + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +Crรฉez maintenant un rรฉpertoire pour stocker ces fichiers statiques. + +Votre nouvelle structure de fichiers pourrait ressembler ร  ceci : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### Tรฉlรฉcharger les fichiers { #download-the-files } + +Tรฉlรฉchargez les fichiers statiques nรฉcessaires aux docs et placezโ€‘les dans ce rรฉpertoire `static/`. + +Vous pouvez probablement cliquer avec le bouton droit sur chaque lien et choisir une option similaire ร  ยซ Enregistrer le lien sous ... ยป. + +**Swagger UI** utilise les fichiers : + +- `swagger-ui-bundle.js` +- `swagger-ui.css` + +Et **ReDoc** utilise le fichier : + +- `redoc.standalone.js` + +Aprรจs cela, votre structure de fichiers pourrait ressembler ร  : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### Servir les fichiers statiques { #serve-the-static-files } + +- Importer `StaticFiles`. +- ยซ Monter ยป une instance `StaticFiles()` sur un chemin spรฉcifique. + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### Tester les fichiers statiques { #test-the-static-files } + +Dรฉmarrez votre application et rendezโ€‘vous sur http://127.0.0.1:8000/static/redoc.standalone.js. + +Vous devriez voir un trรจs long fichier JavaScript pour **ReDoc**. + +Il pourrait commencer par quelque chose comme : + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +Cela confirme que vous parvenez ร  servir des fichiers statiques depuis votre application et que vous avez placรฉ les fichiers statiques des docs au bon endroit. + +Nous pouvons maintenant configurer lโ€™application pour utiliser ces fichiers statiques pour les docs. + +### Dรฉsactiver les docs automatiques pour les fichiers statiques { #disable-the-automatic-docs-for-static-files } + +Comme lors de lโ€™utilisation dโ€™un CDN personnalisรฉ, la premiรจre รฉtape consiste ร  dรฉsactiver les docs automatiques, car elles utilisent un CDN par dรฉfaut. + +Pour les dรฉsactiver, dรฉfinissez leurs URL sur `None` lors de la crรฉation de votre application `FastAPI` : + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### Inclure les docs personnalisรฉes pour les fichiers statiques { #include-the-custom-docs-for-static-files } + +Et comme avec un CDN personnalisรฉ, vous pouvez maintenant crรฉer les chemins d'accรจs pour les docs personnalisรฉes. + +Lร  encore, vous pouvez rรฉutiliser les fonctions internes de FastAPI pour crรฉer les pages HTML de la documentation et leur passer les arguments nรฉcessaires : + +- `openapi_url` : lโ€™URL oรน la page HTML des docs peut rรฉcupรฉrer le schรฉma OpenAPI de votre API. Vous pouvez utiliser ici lโ€™attribut `app.openapi_url`. +- `title` : le titre de votre API. +- `oauth2_redirect_url` : vous pouvez utiliser `app.swagger_ui_oauth2_redirect_url` ici pour utiliser la valeur par dรฉfaut. +- `swagger_js_url` : lโ€™URL oรน la page HTML de Swagger UI peut rรฉcupรฉrer le fichier **JavaScript**. **Cโ€™est celui que votre propre application sert dรฉsormais**. +- `swagger_css_url` : lโ€™URL oรน la page HTML de Swagger UI peut rรฉcupรฉrer le fichier **CSS**. **Cโ€™est celui que votre propre application sert dรฉsormais**. + +Et de mรชme pour ReDoc ... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | Astuce + +Le chemin d'accรจs pour `swagger_ui_redirect` est un assistant lorsque vous utilisez OAuth2. + +Si vous intรฉgrez votre API ร  un fournisseur OAuth2, vous pourrez vous authentifier et revenir aux docs de lโ€™API avec les identifiants acquis. Et interagir avec elle en utilisant la vรฉritable authentification OAuth2. + +Swagger UI sโ€™en chargera en arriรจreโ€‘plan pour vous, mais il a besoin de cet assistant ยซ redirect ยป. + +/// + +### Crรฉer un chemin d'accรจs pour tester les fichiers statiques { #create-a-path-operation-to-test-static-files } + +Maintenant, pour pouvoir vรฉrifier que tout fonctionne, crรฉez un chemin d'accรจs : + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### Tester lโ€™UI avec des fichiers statiques { #test-static-files-ui } + +Vous devriez maintenant pouvoir couper votre Wiโ€‘Fi, aller ร  vos docs sur http://127.0.0.1:8000/docs et recharger la page. + +Et mรชme sans Internet, vous pourrez voir la documentation de votre API et interagir avec elle. diff --git a/docs/fr/docs/how-to/custom-request-and-route.md b/docs/fr/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..506187d9f6 --- /dev/null +++ b/docs/fr/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# Personnaliser les classes Request et APIRoute { #custom-request-and-apiroute-class } + +Dans certains cas, vous pouvez vouloir surcharger la logique utilisรฉe par les classes `Request` et `APIRoute`. + +En particulier, cela peut รชtre une bonne alternative ร  une logique dans un middleware. + +Par exemple, si vous voulez lire ou manipuler le corps de la requรชte avant qu'il ne soit traitรฉ par votre application. + +/// danger | Danger + +Ceci est une fonctionnalitรฉ ยซ avancรฉe ยป. + +Si vous dรฉbutez avec **FastAPI**, vous pouvez ignorer cette section. + +/// + +## Cas d'utilisation { #use-cases } + +Voici quelques cas d'utilisation : + +* Convertir des corps de requรชte non JSON en JSON (par exemple `msgpack`). +* Dรฉcompresser des corps de requรชte compressรฉs en gzip. +* Journaliser automatiquement tous les corps de requรชte. + +## Gรฉrer les encodages personnalisรฉs du corps de la requรชte { #handling-custom-request-body-encodings } + +Voyons comment utiliser une sous-classe personnalisรฉe de `Request` pour dรฉcompresser des requรชtes gzip. + +Et une sous-classe d'`APIRoute` pour utiliser cette classe de requรชte personnalisรฉe. + +### Crรฉer une classe `GzipRequest` personnalisรฉe { #create-a-custom-gziprequest-class } + +/// tip | Astuce + +Il s'agit d'un exemple simplifiรฉ pour montrer le fonctionnement ; si vous avez besoin de la prise en charge de Gzip, vous pouvez utiliser le [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} fourni. + +/// + +Commencez par crรฉer une classe `GzipRequest`, qui va surcharger la mรฉthode `Request.body()` pour dรฉcompresser le corps en prรฉsence d'un en-tรชte appropriรฉ. + +S'il n'y a pas `gzip` dans l'en-tรชte, elle n'essaiera pas de dรฉcompresser le corps. + +De cette maniรจre, la mรชme classe de route peut gรฉrer des requรชtes gzip compressรฉes ou non compressรฉes. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### Crรฉer une classe `GzipRoute` personnalisรฉe { #create-a-custom-gziproute-class } + +Ensuite, nous crรฉons une sous-classe personnalisรฉe de `fastapi.routing.APIRoute` qui utilisera `GzipRequest`. + +Cette fois, elle va surcharger la mรฉthode `APIRoute.get_route_handler()`. + +Cette mรฉthode renvoie une fonction. Et c'est cette fonction qui recevra une requรชte et retournera une rรฉponse. + +Ici, nous l'utilisons pour crรฉer une `GzipRequest` ร  partir de la requรชte originale. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | Dรฉtails techniques + +Un `Request` possรจde un attribut `request.scope`, qui n'est qu'un `dict` Python contenant les mรฉtadonnรฉes liรฉes ร  la requรชte. + +Un `Request` a รฉgalement un `request.receive`, qui est une fonction pour ยซ recevoir ยป le corps de la requรชte. + +Le `dict` `scope` et la fonction `receive` font tous deux partie de la spรฉcification ASGI. + +Et ces deux รฉlรฉments, `scope` et `receive`, sont ce dont on a besoin pour crรฉer une nouvelle instance de `Request`. + +Pour en savoir plus sur `Request`, consultez la documentation de Starlette sur les requรชtes. + +/// + +La seule chose que fait diffรฉremment la fonction renvoyรฉe par `GzipRequest.get_route_handler`, c'est de convertir la `Request` en `GzipRequest`. + +Ce faisant, notre `GzipRequest` se chargera de dรฉcompresser les donnรฉes (si nรฉcessaire) avant de les transmettre ร  nos *chemins d'accรจs*. + +Aprรจs cela, toute la logique de traitement est identique. + +Mais grรขce ร  nos modifications dans `GzipRequest.body`, le corps de la requรชte sera automatiquement dรฉcompressรฉ lorsque **FastAPI** le chargera, si nรฉcessaire. + +## Accรฉder au corps de la requรชte dans un gestionnaire d'exceptions { #accessing-the-request-body-in-an-exception-handler } + +/// tip | Astuce + +Pour rรฉsoudre ce mรชme problรจme, il est probablement beaucoup plus simple d'utiliser `body` dans un gestionnaire personnalisรฉ pour `RequestValidationError` ([Gรฉrer les erreurs](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). + +Mais cet exemple reste valable et montre comment interagir avec les composants internes. + +/// + +Nous pouvons รฉgalement utiliser cette mรชme approche pour accรฉder au corps de la requรชte dans un gestionnaire d'exceptions. + +Il suffit de traiter la requรชte dans un bloc `try`/`except` : + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +Si une exception se produit, l'instance de `Request` sera toujours dans la portรฉe, ce qui nous permet de lire et d'utiliser le corps de la requรชte lors du traitement de l'erreur : + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## Utiliser une classe `APIRoute` personnalisรฉe dans un routeur { #custom-apiroute-class-in-a-router } + +Vous pouvez รฉgalement dรฉfinir le paramรจtre `route_class` d'un `APIRouter` : + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +Dans cet exemple, les *chemins d'accรจs* sous le `router` utiliseront la classe personnalisรฉe `TimedRoute`, et auront un en-tรชte supplรฉmentaire `X-Response-Time` dans la rรฉponse avec le temps nรฉcessaire pour gรฉnรฉrer la rรฉponse : + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/fr/docs/how-to/extending-openapi.md b/docs/fr/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..1c540ea6c7 --- /dev/null +++ b/docs/fr/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# ร‰tendre OpenAPI { #extending-openapi } + +Il existe des cas oรน vous pouvez avoir besoin de modifier le schรฉma OpenAPI gรฉnรฉrรฉ. + +Dans cette section, vous verrez comment faire. + +## Le processus normal { #the-normal-process } + +Le processus normal (par dรฉfaut) est le suivant. + +Une application (instance) `FastAPI` a une mรฉthode `.openapi()` censรฉe retourner le schรฉma OpenAPI. + +Lors de la crรฉation de l'objet application, un *chemin d'accรจs* pour `/openapi.json` (ou pour l'URL que vous avez dรฉfinie dans votre `openapi_url`) est enregistrรฉ. + +Il renvoie simplement une rรฉponse JSON avec le rรฉsultat de la mรฉthode `.openapi()` de l'application. + +Par dรฉfaut, la mรฉthode `.openapi()` vรฉrifie la propriรฉtรฉ `.openapi_schema` pour voir si elle contient des donnรฉes et les renvoie. + +Sinon, elle les gรฉnรจre ร  l'aide de la fonction utilitaire `fastapi.openapi.utils.get_openapi`. + +Et cette fonction `get_openapi()` reรงoit comme paramรจtres : + +* `title` : Le titre OpenAPI, affichรฉ dans les documents. +* `version` : La version de votre API, p. ex. `2.5.0`. +* `openapi_version` : La version de la spรฉcification OpenAPI utilisรฉe. Par dรฉfaut, la plus rรฉcente : `3.1.0`. +* `summary` : Un court rรฉsumรฉ de l'API. +* `description` : La description de votre API ; elle peut inclure du markdown et sera affichรฉe dans la documentation. +* `routes` : Une liste de routes ; chacune correspond ร  un *chemin d'accรจs* enregistrรฉ. Elles sont extraites de `app.routes`. + +/// info + +Le paramรจtre `summary` est disponible ร  partir d'OpenAPI 3.1.0, pris en charge par FastAPI 0.99.0 et versions ultรฉrieures. + +/// + +## Remplacer les valeurs par dรฉfaut { #overriding-the-defaults } + +En vous appuyant sur les informations ci-dessus, vous pouvez utiliser la mรชme fonction utilitaire pour gรฉnรฉrer le schรฉma OpenAPI et remplacer chaque partie dont vous avez besoin. + +Par exemple, ajoutons lโ€™extension OpenAPI de ReDoc pour inclure un logo personnalisรฉ. + +### **FastAPI** normal { #normal-fastapi } + +Tout dโ€™abord, รฉcrivez votre application **FastAPI** comme dโ€™habitude : + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### Gรฉnรฉrer le schรฉma OpenAPI { #generate-the-openapi-schema } + +Ensuite, utilisez la mรชme fonction utilitaire pour gรฉnรฉrer le schรฉma OpenAPI, dans une fonction `custom_openapi()` : + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### Modifier le schรฉma OpenAPI { #modify-the-openapi-schema } + +Vous pouvez maintenant ajouter lโ€™extension ReDoc, en ajoutant un `x-logo` personnalisรฉ ร  lโ€™ยซ objet ยป `info` dans le schรฉma OpenAPI : + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### Mettre en cache le schรฉma OpenAPI { #cache-the-openapi-schema } + +Vous pouvez utiliser la propriรฉtรฉ `.openapi_schema` comme ยซ cache ยป pour stocker votre schรฉma gรฉnรฉrรฉ. + +Ainsi, votre application nโ€™aura pas ร  gรฉnรฉrer le schรฉma ร  chaque fois quโ€™un utilisateur ouvre les documents de votre API. + +Il ne sera gรฉnรฉrรฉ quโ€™une seule fois, puis le mรชme schรฉma en cache sera utilisรฉ pour les requรชtes suivantes. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### Remplacer la mรฉthode { #override-the-method } + +Vous pouvez maintenant remplacer la mรฉthode `.openapi()` par votre nouvelle fonction. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### Vรฉrifier { #check-it } + +Une fois que vous allez sur http://127.0.0.1:8000/redoc, vous verrez que vous utilisez votre logo personnalisรฉ (dans cet exemple, le logo de **FastAPI**) : + + diff --git a/docs/fr/docs/how-to/general.md b/docs/fr/docs/how-to/general.md new file mode 100644 index 0000000000..09d4498aca --- /dev/null +++ b/docs/fr/docs/how-to/general.md @@ -0,0 +1,39 @@ +# Gรฉnรฉral - Guides pratiques - Recettes { #general-how-to-recipes } + +Voici plusieurs renvois vers d'autres endroits de la documentation, pour des questions gรฉnรฉrales ou frรฉquentes. + +## Filtrer des donnรฉes - Sรฉcuritรฉ { #filter-data-security } + +Pour vous assurer que vous ne renvoyez pas plus de donnรฉes que nรฉcessaire, lisez la documentation [Tutoriel - Modรจle de rรฉponse - Type de retour](../tutorial/response-model.md){.internal-link target=_blank}. + +## ร‰tiquettes de documentation - OpenAPI { #documentation-tags-openapi } + +Pour ajouter des รฉtiquettes ร  vos *chemins d'accรจs* et les regrouper dans l'interface utilisateur de la documentation, lisez la documentation [Tutoriel - Configurations de chemin d'accรจs - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. + +## Rรฉsumรฉ et description de la documentation - OpenAPI { #documentation-summary-and-description-openapi } + +Pour ajouter un rรฉsumรฉ et une description ร  vos *chemins d'accรจs* et les afficher dans l'interface utilisateur de la documentation, lisez la documentation [Tutoriel - Configurations de chemin d'accรจs - Rรฉsumรฉ et description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. + +## Description de la rรฉponse dans la documentation - OpenAPI { #documentation-response-description-openapi } + +Pour dรฉfinir la description de la rรฉponse, affichรฉe dans l'interface utilisateur de la documentation, lisez la documentation [Tutoriel - Configurations de chemin d'accรจs - Description de la rรฉponse](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. + +## Dรฉprรฉcier un *chemin d'accรจs* dans la documentation - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +Pour dรฉprรฉcier un *chemin d'accรจs* et l'indiquer dans l'interface utilisateur de la documentation, lisez la documentation [Tutoriel - Configurations de chemin d'accรจs - Dรฉprรฉcier un chemin d'accรจs](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. + +## Convertir n'importe quelles donnรฉes au format compatible JSON { #convert-any-data-to-json-compatible } + +Pour convertir des donnรฉes vers un format compatible JSON, lisez la documentation [Tutoriel - Encodeur compatible JSON](../tutorial/encoder.md){.internal-link target=_blank}. + +## Mรฉtadonnรฉes OpenAPI - Documentation { #openapi-metadata-docs } + +Pour ajouter des mรฉtadonnรฉes ร  votre schรฉma OpenAPI, y compris une licence, une version, un contact, etc., lisez la documentation [Tutoriel - Mรฉtadonnรฉes et URLs de la documentation](../tutorial/metadata.md){.internal-link target=_blank}. + +## URL OpenAPI personnalisรฉe { #openapi-custom-url } + +Pour personnaliser l'URL OpenAPI (ou la supprimer), lisez la documentation [Tutoriel - Mรฉtadonnรฉes et URLs de la documentation](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. + +## URL de la documentation OpenAPI { #openapi-docs-urls } + +Pour mettre ร  jour les URL utilisรฉes pour les interfaces utilisateur de documentation gรฉnรฉrรฉes automatiquement, lisez la documentation [Tutoriel - Mรฉtadonnรฉes et URLs de la documentation](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. diff --git a/docs/fr/docs/how-to/graphql.md b/docs/fr/docs/how-to/graphql.md new file mode 100644 index 0000000000..59cd1590f3 --- /dev/null +++ b/docs/fr/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +Comme **FastAPI** est basรฉ sur la norme **ASGI**, il est trรจs facile d'intรฉgrer toute bibliothรจque **GraphQL** รฉgalement compatible avec ASGI. + +Vous pouvez combiner des *chemins d'accรจs* FastAPI classiques avec GraphQL dans la mรชme application. + +/// tip | Astuce + +**GraphQL** rรฉsout des cas d'utilisation trรจs spรฉcifiques. + +Il prรฉsente des **avantages** et des **inconvรฉnients** par rapport aux **API web** classiques. + +Assurez-vous d'รฉvaluer si les **bรฉnรฉfices** pour votre cas d'utilisation compensent les **inconvรฉnients**. ๐Ÿค“ + +/// + +## Bibliothรจques GraphQL { #graphql-libraries } + +Voici quelques bibliothรจques **GraphQL** qui prennent en charge **ASGI**. Vous pouvez les utiliser avec **FastAPI** : + +* Strawberry ๐Ÿ“ + * Avec la documentation pour FastAPI +* Ariadne + * Avec la documentation pour FastAPI +* Tartiflette + * Avec Tartiflette ASGI pour fournir l'intรฉgration ASGI +* Graphene + * Avec starlette-graphene3 + +## GraphQL avec Strawberry { #graphql-with-strawberry } + +Si vous avez besoin ou souhaitez travailler avec **GraphQL**, **Strawberry** est la bibliothรจque **recommandรฉe** car sa conception est la plus proche de celle de **FastAPI**, tout est basรฉ sur des **annotations de type**. + +Selon votre cas d'utilisation, vous pourriez prรฉfรฉrer une autre bibliothรจque, mais si vous me le demandiez, je vous suggรฉrerais probablement d'essayer **Strawberry**. + +Voici un petit aperรงu de la maniรจre dont vous pouvez intรฉgrer Strawberry avec FastAPI : + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +Vous pouvez en apprendre davantage sur Strawberry dans la documentation de Strawberry. + +Et รฉgalement la documentation sur Strawberry avec FastAPI. + +## Ancien `GraphQLApp` de Starlette { #older-graphqlapp-from-starlette } + +Les versions prรฉcรฉdentes de Starlette incluaient une classe `GraphQLApp` pour s'intรฉgrer ร  Graphene. + +Elle a รฉtรฉ dรฉprรฉciรฉe dans Starlette, mais si vous avez du code qui l'utilisait, vous pouvez facilement **migrer** vers starlette-graphene3, qui couvre le mรชme cas d'utilisation et propose une **interface presque identique**. + +/// tip | Astuce + +Si vous avez besoin de GraphQL, je vous recommande tout de mรชme de regarder Strawberry, car il est basรฉ sur des annotations de type plutรดt que sur des classes et types personnalisรฉs. + +/// + +## En savoir plus { #learn-more } + +Vous pouvez en apprendre davantage sur **GraphQL** dans la documentation officielle de GraphQL. + +Vous pouvez รฉgalement en lire davantage sur chacune des bibliothรจques dรฉcrites ci-dessus via leurs liens. diff --git a/docs/fr/docs/how-to/index.md b/docs/fr/docs/how-to/index.md new file mode 100644 index 0000000000..03736fa43f --- /dev/null +++ b/docs/fr/docs/how-to/index.md @@ -0,0 +1,13 @@ +# Comment faire - Recettes { #how-to-recipes } + +Vous trouverez ici diffรฉrentes recettes ou des guides ยซ comment faire ยป pour **plusieurs sujets**. + +La plupart de ces idรฉes sont plus ou moins **indรฉpendantes**, et dans la plupart des cas vous n'avez besoin de les รฉtudier que si elles s'appliquent directement ร  **votre projet**. + +Si quelque chose vous paraรฎt intรฉressant et utile pour votre projet, allez-y et consultez-le ; sinon, vous pouvez probablement simplement les ignorer. + +/// tip | Astuce + +Si vous voulez **apprendre FastAPI** de faรงon structurรฉe (recommandรฉ), allez lire le [Tutoriel - Guide utilisateur](../tutorial/index.md){.internal-link target=_blank} chapitre par chapitre ร  la place. + +/// diff --git a/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..681cf697bb --- /dev/null +++ b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# Migrer de Pydantic v1 ร  Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } + +Si vous avez une ancienne application FastAPI, vous utilisez peut-รชtre Pydantic version 1. + +FastAPI version 0.100.0 prenait en charge soit Pydantic v1 soit v2. Il utilisait celle que vous aviez installรฉe. + +FastAPI version 0.119.0 a introduit une prise en charge partielle de Pydantic v1 depuis l'intรฉrieur de Pydantic v2 (comme `pydantic.v1`), pour faciliter la migration vers v2. + +FastAPI 0.126.0 a supprimรฉ la prise en charge de Pydantic v1, tout en continuant ร  prendre en charge `pydantic.v1` pendant un certain temps. + +/// warning | Alertes + +L'รฉquipe Pydantic a arrรชtรฉ la prise en charge de Pydantic v1 pour les derniรจres versions de Python, ร  partir de Python 3.14. + +Cela inclut `pydantic.v1`, qui n'est plus pris en charge ร  partir de Python 3.14. + +Si vous souhaitez utiliser les derniรจres fonctionnalitรฉs de Python, vous devez vous assurer que vous utilisez Pydantic v2. + +/// + +Si vous avez une ancienne application FastAPI avec Pydantic v1, je vais vous montrer comment la migrer vers Pydantic v2, et les fonctionnalitรฉs de FastAPI 0.119.0 pour vous aider ร  une migration progressive. + +## Guide officiel { #official-guide } + +Pydantic propose un Guide de migration officiel de la v1 ร  la v2. + +Il inclut aussi ce qui a changรฉ, comment les validations sont dรฉsormais plus correctes et strictes, les piรจges possibles, etc. + +Vous pouvez le lire pour mieux comprendre ce qui a changรฉ. + +## Tests { #tests } + +Vous devez vous assurer d'avoir des [tests](../tutorial/testing.md){.internal-link target=_blank} pour votre application et de les exรฉcuter en intรฉgration continue (CI). + +De cette faรงon, vous pouvez effectuer la mise ร  niveau et vous assurer que tout fonctionne toujours comme prรฉvu. + +## `bump-pydantic` { #bump-pydantic } + +Dans de nombreux cas, lorsque vous utilisez des modรจles Pydantic classiques sans personnalisations, vous pourrez automatiser la majeure partie du processus de migration de Pydantic v1 ร  Pydantic v2. + +Vous pouvez utiliser `bump-pydantic` de la mรชme รฉquipe Pydantic. + +Cet outil vous aidera ร  modifier automatiquement la majeure partie du code ร  adapter. + +Aprรจs cela, vous pouvez exรฉcuter les tests et vรฉrifier que tout fonctionne. Si c'est le cas, vous avez terminรฉ. ๐Ÿ˜Ž + +## Pydantic v1 dans v2 { #pydantic-v1-in-v2 } + +Pydantic v2 inclut tout Pydantic v1 sous la forme du sous-module `pydantic.v1`. Mais cela n'est plus pris en charge dans les versions au-delร  de Python 3.13. + +Cela signifie que vous pouvez installer la derniรจre version de Pydantic v2 et importer/utiliser les anciens composants de Pydantic v1 depuis ce sous-module, comme si vous aviez l'ancien Pydantic v1 installรฉ. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### Prise en charge de FastAPI pour Pydantic v1 dans v2 { #fastapi-support-for-pydantic-v1-in-v2 } + +Depuis FastAPI 0.119.0, il existe รฉgalement une prise en charge partielle de Pydantic v1 depuis l'intรฉrieur de Pydantic v2, pour faciliter la migration vers v2. + +Vous pouvez donc mettre ร  niveau Pydantic vers la derniรจre version 2 et modifier les imports pour utiliser le sous-module `pydantic.v1`, et dans de nombreux cas cela fonctionnera tel quel. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | Alertes + +Gardez ร  l'esprit que, puisque l'รฉquipe Pydantic ne prend plus en charge Pydantic v1 dans les versions rรฉcentes de Python ร  partir de Python 3.14, l'utilisation de `pydantic.v1` n'est pas non plus prise en charge ร  partir de Python 3.14. + +/// + +### Pydantic v1 et v2 dans la mรชme application { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic ne prend pas en charge le fait d'avoir un modรจle Pydantic v2 contenant des champs eux-mรชmes dรฉfinis comme des modรจles Pydantic v1, et inversement. + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +... mais vous pouvez avoir des modรจles sรฉparรฉs utilisant Pydantic v1 et v2 dans la mรชme application. + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +Dans certains cas, il est mรชme possible d'avoir des modรจles Pydantic v1 et v2 dans le mรชme chemin d'accรจs de votre application FastAPI : + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +Dans l'exemple ci-dessus, le modรจle d'entrรฉe est un modรจle Pydantic v1 et le modรจle de sortie (dรฉfini dans `response_model=ItemV2`) est un modรจle Pydantic v2. + +### Paramรจtres Pydantic v1 { #pydantic-v1-parameters } + +Si vous devez utiliser certains des outils spรฉcifiques ร  FastAPI pour les paramรจtres comme `Body`, `Query`, `Form`, etc., avec des modรจles Pydantic v1, vous pouvez les importer depuis `fastapi.temp_pydantic_v1_params` le temps de terminer la migration vers Pydantic v2 : + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### Migrer par รฉtapes { #migrate-in-steps } + +/// tip | Astuce + +Essayez d'abord avec `bump-pydantic` ; si vos tests passent et que cela fonctionne, vous avez tout terminรฉ en une seule commande. โœจ + +/// + +Si `bump-pydantic` ne fonctionne pas pour votre cas d'usage, vous pouvez utiliser la prise en charge des modรจles Pydantic v1 et v2 dans la mรชme application pour effectuer la migration vers Pydantic v2 progressivement. + +Vous pouvez d'abord mettre ร  niveau Pydantic pour utiliser la derniรจre version 2 et modifier les imports pour utiliser `pydantic.v1` pour tous vos modรจles. + +Ensuite, vous pouvez commencer ร  migrer vos modรจles de Pydantic v1 vers v2 par groupes, par รฉtapes progressives. ๐Ÿšถ diff --git a/docs/fr/docs/how-to/separate-openapi-schemas.md b/docs/fr/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..fd767d7388 --- /dev/null +++ b/docs/fr/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# Sรฉparer les schรฉmas OpenAPI pour l'entrรฉe et la sortie ou non { #separate-openapi-schemas-for-input-and-output-or-not } + +Depuis la sortie de **Pydantic v2**, l'OpenAPI gรฉnรฉrรฉ est un peu plus prรฉcis et **correct** qu'avant. ๐Ÿ˜Ž + +En fait, dans certains cas, il y aura mรชme **deux schรฉmas JSON** dans OpenAPI pour le mรชme modรจle Pydantic, pour l'entrรฉe et pour la sortie, selon s'ils ont des **valeurs par dรฉfaut**. + +Voyons comment cela fonctionne et comment le modifier si vous devez le faire. + +## Utiliser des modรจles Pydantic pour l'entrรฉe et la sortie { #pydantic-models-for-input-and-output } + +Supposons que vous ayez un modรจle Pydantic avec des valeurs par dรฉfaut, comme celuiโ€‘ci : + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Modรจle pour l'entrรฉe { #model-for-input } + +Si vous utilisez ce modรจle en entrรฉe comme ici : + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +... alors, le champ `description` ne sera **pas requis**. Parce qu'il a une valeur par dรฉfaut de `None`. + +### Modรจle d'entrรฉe dans les documents { #input-model-in-docs } + +Vous pouvez le confirmer dans les documents, le champ `description` n'a pas d'**astรฉrisque rouge**, il n'est pas indiquรฉ comme requis : + +
+ +
+ +### Modรจle pour la sortie { #model-for-output } + +Mais si vous utilisez le mรชme modรจle en sortie, comme ici : + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +... alors, comme `description` a une valeur par dรฉfaut, si vous ne retournez rien pour ce champ, il aura tout de mรชme cette **valeur par dรฉfaut**. + +### Modรจle pour les donnรฉes de rรฉponse en sortie { #model-for-output-response-data } + +Si vous interagissez avec les documents et vรฉrifiez la rรฉponse, mรชme si le code n'a rien ajoutรฉ dans l'un des champs `description`, la rรฉponse JSON contient la valeur par dรฉfaut (`null`) : + +
+ +
+ +Cela signifie qu'il aura **toujours une valeur**, simplement, parfois la valeur pourra รชtre `None` (ou `null` en JSON). + +Cela signifie que les clients utilisant votre API n'ont pas ร  vรฉrifier si la valeur existe ou non, ils peuvent **supposer que le champ sera toujours prรฉsent**, mais que, dans certains cas, il aura la valeur par dรฉfaut `None`. + +La maniรจre de dรฉcrire cela dans OpenAPI est de marquer ce champ comme **requis**, car il sera toujours prรฉsent. + +Pour cette raison, le schรฉma JSON d'un modรจle peut รชtre diffรฉrent selon qu'il est utilisรฉ pour **l'entrรฉe ou la sortie** : + +- pour **l'entrรฉe**, `description` ne sera **pas requis** +- pour **la sortie**, il sera **requis** (et รฉventuellement `None`, ou en termes JSON, `null`) + +### Modรจle de sortie dans les documents { #model-for-output-in-docs } + +Vous pouvez รฉgalement vรฉrifier le modรจle de sortie dans les documents, **ร  la fois** `name` et `description` sont marquรฉs comme **requis** avec un **astรฉrisque rouge** : + +
+ +
+ +### Modรจle pour l'entrรฉe et la sortie dans les documents { #model-for-input-and-output-in-docs } + +Et si vous consultez tous les schรฉmas disponibles (schรฉmas JSON) dans OpenAPI, vous verrez qu'il y en a deux, un `Item-Input` et un `Item-Output`. + +Pour `Item-Input`, `description` n'est **pas requis**, il n'a pas d'astรฉrisque rouge. + +Mais pour `Item-Output`, `description` est **requis**, il a un astรฉrisque rouge. + +
+ +
+ +Avec cette fonctionnalitรฉ de **Pydantic v2**, la documentation de votre API est plus **prรฉcise**, et si vous avez des clients et SDKs gรฉnรฉrรฉs automatiquement, ils seront eux aussi plus prรฉcis, avec une meilleure **expรฉrience dรฉveloppeur** et davantage de cohรฉrence. ๐ŸŽ‰ + +## Ne pas sรฉparer les schรฉmas { #do-not-separate-schemas } + +Il existe des cas oรน vous pourriez vouloir avoir le **mรชme schรฉma pour l'entrรฉe et la sortie**. + +Le cas d'usage principal est probablement que vous avez dรฉjร  du code client/SDKs gรฉnรฉrรฉs automatiquement et que vous ne souhaitez pas encore mettre ร  jour tout ce code client/ces SDKs gรฉnรฉrรฉs automatiquement ; vous le ferez sans doute ร  un moment donnรฉ, mais peutโ€‘รชtre pas tout de suite. + +Dans ce cas, vous pouvez dรฉsactiver cette fonctionnalitรฉ dans **FastAPI**, avec le paramรจtre `separate_input_output_schemas=False`. + +/// info | info + +La prise en charge de `separate_input_output_schemas` a รฉtรฉ ajoutรฉe dans FastAPI `0.102.0`. ๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Utiliser le mรชme schรฉma pour les modรจles d'entrรฉe et de sortie dans les documents { #same-schema-for-input-and-output-models-in-docs } + +Dรฉsormais, il n'y aura qu'un seul schรฉma pour l'entrรฉe et la sortie du modรจle, uniquement `Item`, et `description` ne sera pas requis : + +
+ +
diff --git a/docs/fr/docs/how-to/testing-database.md b/docs/fr/docs/how-to/testing-database.md new file mode 100644 index 0000000000..3179bc4c6b --- /dev/null +++ b/docs/fr/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Tester une base de donnรฉes { #testing-a-database } + +Vous pouvez รฉtudier les bases de donnรฉes, SQL et SQLModel dans les documents SQLModel. ๐Ÿค“ + +Il existe un mini tutoriel sur l'utilisation de SQLModel avec FastAPI. โœจ + +Ce tutoriel comprend une section sur les tests des bases de donnรฉes SQL. ๐Ÿ˜Ž diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 2aeaa1c692..bf4446b940 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -40,7 +40,7 @@ Les principales fonctionnalitรฉs sont : * **Rapide** : trรจs hautes performances, au niveau de **NodeJS** et **Go** (grรขce ร  Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). * **Rapide ร  coder** : augmente la vitesse de dรฉveloppement des fonctionnalitรฉs d'environ 200 % ร  300 %. * * **Moins de bugs** : rรฉduit d'environ 40 % les erreurs induites par le dรฉveloppeur. * -* **Intuitif** : excellente compatibilitรฉ avec les รฉditeurs. Autocomplรฉtion partout. Moins de temps passรฉ ร  dรฉboguer. +* **Intuitif** : excellente compatibilitรฉ avec les รฉditeurs. Autocomplรฉtion partout. Moins de temps passรฉ ร  dรฉboguer. * **Facile** : conรงu pour รชtre facile ร  utiliser et ร  apprendre. Moins de temps passรฉ ร  lire les documents. * **Concis** : diminue la duplication de code. Plusieurs fonctionnalitรฉs ร  partir de chaque dรฉclaration de paramรจtre. Moins de bugs. * **Robuste** : obtenez un code prรชt pour la production. Avec une documentation interactive automatique. @@ -368,7 +368,7 @@ item: Item * La validation des donnรฉes : * des erreurs automatiques et claires lorsque les donnรฉes ne sont pas valides. * une validation mรชme pour les objets JSON profondรฉment imbriquรฉs. -* Conversion des donnรฉes d'entrรฉe : venant du rรฉseau vers les donnรฉes et types Python. Lecture depuis : +* Conversion des donnรฉes d'entrรฉe : venant du rรฉseau vers les donnรฉes et types Python. Lecture depuis : * JSON. * Paramรจtres de chemin. * Paramรจtres de requรชte. @@ -376,7 +376,7 @@ item: Item * En-tรชtes. * Formulaires. * Fichiers. -* Conversion des donnรฉes de sortie : conversion des donnรฉes et types Python en donnรฉes rรฉseau (au format JSON) : +* Conversion des donnรฉes de sortie : conversion des donnรฉes et types Python en donnรฉes rรฉseau (au format JSON) : * Conversion des types Python (`str`, `int`, `float`, `bool`, `list`, etc). * Objets `datetime`. * Objets `UUID`. @@ -439,7 +439,7 @@ Pour un exemple plus complet comprenant plus de fonctionnalitรฉs, voir le d'injection de dรฉpendances** trรจs puissant et facile ร  utiliser. +* Un systรจme **d'injection de dรฉpendances** trรจs puissant et facile ร  utiliser. * Sรฉcuritรฉ et authentification, y compris la prise en charge de **OAuth2** avec des **JWT tokens** et l'authentification **HTTP Basic**. * Des techniques plus avancรฉes (mais tout aussi faciles) pour dรฉclarer des **modรจles JSON profondรฉment imbriquรฉs** (grรขce ร  Pydantic). * Intรฉgration **GraphQL** avec Strawberry et d'autres bibliothรจques. @@ -524,7 +524,7 @@ Utilisรฉes par Starlette : * httpx - Obligatoire si vous souhaitez utiliser le `TestClient`. * jinja2 - Obligatoire si vous souhaitez utiliser la configuration de template par dรฉfaut. -* python-multipart - Obligatoire si vous souhaitez prendre en charge lโ€™ยซ parsing ยป de formulaires avec `request.form()`. +* python-multipart - Obligatoire si vous souhaitez prendre en charge lโ€™ยซ parsing ยป de formulaires avec `request.form()`. Utilisรฉes par FastAPI : diff --git a/docs/fr/docs/learn/index.md b/docs/fr/docs/learn/index.md index 5526877038..e595ecf789 100644 --- a/docs/fr/docs/learn/index.md +++ b/docs/fr/docs/learn/index.md @@ -2,4 +2,4 @@ Voici les sections introductives et les tutoriels pour apprendre **FastAPI**. -Vous pouvez considรฉrer ceci comme un **livre**, un **cours**, la **mรฉthode officielle** et recommandรฉe pour apprendre FastAPI. ๐Ÿ˜Ž +Vous pouvez considรฉrer ceci comme un **livre**, un **cours**, la mรฉthode **officielle** et recommandรฉe pour apprendre FastAPI. ๐Ÿ˜Ž diff --git a/docs/fr/docs/python-types.md b/docs/fr/docs/python-types.md index f393b0f5c1..770f1514ac 100644 --- a/docs/fr/docs/python-types.md +++ b/docs/fr/docs/python-types.md @@ -1,8 +1,8 @@ # Introduction aux types Python { #python-types-intro } -Python prend en charge des ยซ type hints ยป (aussi appelรฉes ยซ annotations de type ยป) facultatives. +Python prend en charge des ยซ annotations de type ยป (aussi appelรฉes ยซ type hints ยป) facultatives. -Ces ยซ type hints ยป ou annotations sont une syntaxe spรฉciale qui permet de dรฉclarer le type d'une variable. +Ces **ยซ annotations de type ยป** sont une syntaxe spรฉciale qui permet de dรฉclarer le type d'une variable. En dรฉclarant les types de vos variables, les รฉditeurs et outils peuvent vous offrir un meilleur support. @@ -22,7 +22,7 @@ Si vous รชtes un expert Python, et que vous savez dรฉjร  tout sur les annotation Commenรงons par un exemple simple : -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} Exรฉcuter ce programme affiche : @@ -34,9 +34,9 @@ La fonction fait ce qui suit : * Prend un `first_name` et un `last_name`. * Convertit la premiรจre lettre de chacun en majuscule avec `title()`. -* Concatรจne ces deux valeurs avec un espace au milieu. +* Concatรจne ces deux valeurs avec un espace au milieu. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### Modifier le code { #edit-it } @@ -78,7 +78,7 @@ C'est tout. Ce sont les ยซ annotations de type ยป : -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} Ce n'est pas la mรชme chose que de dรฉclarer des valeurs par dรฉfaut, ce qui serait : @@ -106,7 +106,7 @@ Avec cela, vous pouvez faire dรฉfiler en voyant les options, jusqu'ร  trouver ce Regardez cette fonction, elle a dรฉjร  des annotations de type : -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} Comme l'รฉditeur connaรฎt les types des variables, vous n'obtenez pas seulement l'autocomplรฉtion, vous obtenez aussi des vรฉrifications d'erreurs : @@ -114,7 +114,7 @@ Comme l'รฉditeur connaรฎt les types des variables, vous n'obtenez pas seulement Vous savez maintenant qu'il faut corriger, convertir `age` en chaรฎne avec `str(age)` : -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## Dรฉclarer des types { #declaring-types } @@ -133,29 +133,32 @@ Vous pouvez utiliser, par exemple : * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### Types gรฉnรฉriques avec paramรจtres de type { #generic-types-with-type-parameters } +### Module `typing` { #typing-module } -Il existe certaines structures de donnรฉes qui peuvent contenir d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent aussi avoir leur propre type. +Pour certains cas d'utilisation supplรฉmentaires, vous pourriez avoir besoin d'importer certains รฉlรฉments depuis le module standard `typing`, par exemple lorsque vous voulez dรฉclarer que quelque chose a ยซ n'importe quel type ยป, vous pouvez utiliser `Any` depuis `typing` : -Ces types qui ont des types internes sont appelรฉs types ยซ gรฉnรฉriques ยป. Et il est possible de les dรฉclarer, mรชme avec leurs types internes. +```python +from typing import Any -Pour dรฉclarer ces types et les types internes, vous pouvez utiliser le module standard Python `typing`. Il existe spรฉcifiquement pour prendre en charge ces annotations de type. -#### Versions plus rรฉcentes de Python { #newer-versions-of-python } - -La syntaxe utilisant `typing` est compatible avec toutes les versions, de Python 3.6 aux plus rรฉcentes, y compris Python 3.9, Python 3.10, etc. +def some_function(data: Any): + print(data) +``` -Au fur et ร  mesure que Python รฉvolue, les versions plus rรฉcentes apportent un meilleur support pour ces annotations de type et dans de nombreux cas vous n'aurez mรชme pas besoin d'importer et d'utiliser le module `typing` pour les dรฉclarer. +### Types gรฉnรฉriques { #generic-types } -Si vous pouvez choisir une version plus rรฉcente de Python pour votre projet, vous pourrez profiter de cette simplicitรฉ supplรฉmentaire. +Certains types peuvent prendre des ยซ paramรจtres de type ยป entre crochets, pour dรฉfinir leurs types internes, par exemple une ยซ liste de chaรฎnes ยป se dรฉclarerait `list[str]`. -Dans toute la documentation, il y a des exemples compatibles avec chaque version de Python (lorsqu'il y a une diffรฉrence). +Ces types qui peuvent prendre des paramรจtres de type sont appelรฉs des **types gรฉnรฉriques** ou **Generics**. -Par exemple ยซ Python 3.6+ ยป signifie que c'est compatible avec Python 3.6 ou supรฉrieur (y compris 3.7, 3.8, 3.9, 3.10, etc.). Et ยซ Python 3.9+ ยป signifie que c'est compatible avec Python 3.9 ou supรฉrieur (y compris 3.10, etc). +Vous pouvez utiliser les mรชmes types intรฉgrรฉs comme gรฉnรฉriques (avec des crochets et des types ร  l'intรฉrieur) : -Si vous pouvez utiliser les derniรจres versions de Python, utilisez les exemples pour la derniรจre version, ils auront la meilleure et la plus simple syntaxe, par exemple, ยซ Python 3.10+ ยป. +* `list` +* `tuple` +* `set` +* `dict` #### Liste { #list } @@ -167,9 +170,9 @@ Comme type, mettez `list`. Comme la liste est un type qui contient des types internes, mettez-les entre crochets : -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} -/// info +/// info | Info Ces types internes entre crochets sont appelรฉs ยซ paramรจtres de type ยป. @@ -193,7 +196,7 @@ Et pourtant, l'รฉditeur sait que c'est un `str` et fournit le support appropriรฉ Vous feriez la mรชme chose pour dรฉclarer des `tuple` et des `set` : -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} Cela signifie : @@ -208,7 +211,7 @@ Le premier paramรจtre de type est pour les clรฉs du `dict`. Le second paramรจtre de type est pour les valeurs du `dict` : -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} Cela signifie : @@ -218,46 +221,22 @@ Cela signifie : #### Union { #union } -Vous pouvez dรฉclarer qu'une variable peut รชtre de plusieurs types, par exemple, un `int` ou un `str`. - -Dans Python 3.6 et supรฉrieur (y compris Python 3.10), vous pouvez utiliser le type `Union` de `typing` et mettre entre crochets les types possibles ร  accepter. +Vous pouvez dรฉclarer qu'une variable peut รชtre **plusieurs types**, par exemple, un `int` ou un `str`. -Dans Python 3.10, il existe aussi une nouvelle syntaxe oรน vous pouvez mettre les types possibles sรฉparรฉs par une barre verticale (`|`). +Pour le dรฉfinir, vous utilisez la barre verticale (`|`) pour sรฉparer les deux types. -//// tab | Python 3.10+ +C'est ce qu'on appelle une ยซ union ยป, car la variable peut รชtre n'importe quoi dans l'union de ces deux ensembles de types. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -Dans les deux cas, cela signifie que `item` peut รชtre un `int` ou un `str`. +Cela signifie que `item` peut รชtre un `int` ou un `str`. #### Possiblement `None` { #possibly-none } Vous pouvez dรฉclarer qu'une valeur peut avoir un type, comme `str`, mais qu'elle peut aussi รชtre `None`. -Dans Python 3.6 et supรฉrieur (y compris Python 3.10), vous pouvez le dรฉclarer en important et en utilisant `Optional` depuis le module `typing`. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -Utiliser `Optional[str]` au lieu de simplement `str` permettra ร  l'รฉditeur de vous aider ร  dรฉtecter des erreurs oรน vous supposeriez qu'une valeur est toujours un `str`, alors qu'elle pourrait en fait aussi รชtre `None`. - -`Optional[Something]` est en rรฉalitรฉ un raccourci pour `Union[Something, None]`, ils sont รฉquivalents. - -Cela signifie aussi que dans Python 3.10, vous pouvez utiliser `Something | None` : - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -266,96 +245,7 @@ Cela signifie aussi que dans Python 3.10, vous pouvez utiliser `Something | None //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### Utiliser `Union` ou `Optional` { #using-union-or-optional } - -Si vous utilisez une version de Python infรฉrieure ร  3.10, voici un conseil de mon point de vue trรจs **subjectif** : - -* ๐Ÿšจ ร‰vitez d'utiliser `Optional[SomeType]` -* ร€ la place โœจ **utilisez `Union[SomeType, None]`** โœจ. - -Les deux sont รฉquivalents et sous le capot ce sont les mรชmes, mais je recommanderais `Union` plutรดt que `Optional` parce que le mot ยซ facultatif ยป semble impliquer que la valeur est optionnelle, alors que cela signifie en fait ยซ elle peut รชtre `None` ยป, mรชme si elle n'est pas facultative et est toujours requise. - -Je pense que `Union[SomeType, None]` est plus explicite sur ce que cela signifie. - -Il ne s'agit que des mots et des noms. Mais ces mots peuvent influencer la maniรจre dont vous et vos coรฉquipiers pensez au code. - -Par exemple, prenons cette fonction : - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -Le paramรจtre `name` est dรฉfini comme `Optional[str]`, mais il n'est pas facultatif, vous ne pouvez pas appeler la fonction sans le paramรจtre : - -```Python -say_hi() # Oh non, cela lรจve une erreur ! ๐Ÿ˜ฑ -``` - -Le paramรจtre `name` est toujours requis (pas ยซ optionnel ยป) parce qu'il n'a pas de valeur par dรฉfaut. Nรฉanmoins, `name` accepte `None` comme valeur : - -```Python -say_hi(name=None) # Cela fonctionne, None est valide ๐ŸŽ‰ -``` - -La bonne nouvelle est que, dรจs que vous รชtes sur Python 3.10, vous n'avez plus ร  vous en soucier, car vous pourrez simplement utiliser `|` pour dรฉfinir des unions de types : - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -Et alors vous n'aurez plus ร  vous soucier de noms comme `Optional` et `Union`. ๐Ÿ˜Ž - -#### Types gรฉnรฉriques { #generic-types } - -Ces types qui prennent des paramรจtres de type entre crochets sont appelรฉs des **types gรฉnรฉriques** ou **Generics**, par exemple : - -//// tab | Python 3.10+ - -Vous pouvez utiliser les mรชmes types intรฉgrรฉs comme gรฉnรฉriques (avec des crochets et des types ร  l'intรฉrieur) : - -* `list` -* `tuple` -* `set` -* `dict` - -Et, comme avec les versions prรฉcรฉdentes de Python, depuis le module `typing` : - -* `Union` -* `Optional` -* ... et d'autres. - -Dans Python 3.10, comme alternative ร  l'utilisation des gรฉnรฉriques `Union` et `Optional`, vous pouvez utiliser la barre verticale (`|`) pour dรฉclarer des unions de types, c'est bien mieux et plus simple. - -//// - -//// tab | Python 3.9+ - -Vous pouvez utiliser les mรชmes types intรฉgrรฉs comme gรฉnรฉriques (avec des crochets et des types ร  l'intรฉrieur) : - -* `list` -* `tuple` -* `set` -* `dict` - -Et des gรฉnรฉriques depuis le module `typing` : - -* `Union` -* `Optional` -* ... et d'autres. - -//// +Utiliser `str | None` au lieu de simplement `str` permettra ร  l'รฉditeur de vous aider ร  dรฉtecter des erreurs oรน vous supposeriez qu'une valeur est toujours un `str`, alors qu'elle pourrait en fait aussi รชtre `None`. ### Classes en tant que types { #classes-as-types } @@ -363,19 +253,19 @@ Vous pouvez aussi dรฉclarer une classe comme type d'une variable. Disons que vous avez une classe `Person`, avec un nom : -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} Vous pouvez ensuite dรฉclarer une variable de type `Person` : -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} Et lร  encore, vous obtenez tout le support de l'รฉditeur : -Remarquez que cela signifie ยซ `one_person` est une instance de la classe `Person` ยป. +Remarquez que cela signifie ยซ `one_person` est une **instance** de la classe `Person` ยป. -Cela ne signifie pas ยซ `one_person` est la classe appelรฉe `Person` ยป. +Cela ne signifie pas ยซ `one_person` est la **classe** appelรฉe `Person` ยป. ## Modรจles Pydantic { #pydantic-models } @@ -393,7 +283,7 @@ Un exemple tirรฉ de la documentation officielle de Pydantic : {* ../../docs_src/python_types/tutorial011_py310.py *} -/// info +/// info | Info Pour en savoir plus ร  propos de Pydantic, consultez sa documentation. @@ -403,33 +293,27 @@ Pour en savoir plus ร  propos de champs Optionals requis. - -/// - ## Annotations de type avec mรฉtadonnรฉes { #type-hints-with-metadata-annotations } -Python dispose รฉgalement d'une fonctionnalitรฉ qui permet de mettre des **mรฉtadonnรฉes supplรฉmentaires** dans ces annotations de type en utilisant `Annotated`. +Python dispose รฉgalement d'une fonctionnalitรฉ qui permet de mettre des **mรฉtadonnรฉes supplรฉmentaires** dans ces annotations de type en utilisant `Annotated`. -Depuis Python 3.9, `Annotated` fait partie de la bibliothรจque standard, vous pouvez donc l'importer depuis `typing`. +Vous pouvez importer `Annotated` depuis `typing`. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} Python lui-mรชme ne fait rien avec ce `Annotated`. Et pour les รฉditeurs et autres outils, le type est toujours `str`. Mais vous pouvez utiliser cet espace dans `Annotated` pour fournir ร  **FastAPI** des mรฉtadonnรฉes supplรฉmentaires sur la faรงon dont vous voulez que votre application se comporte. -L'important ร  retenir est que le premier paramรจtre de type que vous passez ร  `Annotated` est le type rรฉel. Le reste n'est que des mรฉtadonnรฉes pour d'autres outils. +L'important ร  retenir est que **le premier ยซ paramรจtre de type ยป** que vous passez ร  `Annotated` est le **type rรฉel**. Le reste n'est que des mรฉtadonnรฉes pour d'autres outils. Pour l'instant, vous avez juste besoin de savoir que `Annotated` existe, et que c'est du Python standard. ๐Ÿ˜Ž -Plus tard, vous verrez ร  quel point cela peut รชtre puissant. +Plus tard, vous verrez ร  quel point cela peut รชtre **puissant**. /// tip | Astuce -Le fait que ce soit du Python standard signifie que vous bรฉnรฉficierez toujours de la meilleure expรฉrience dรฉveloppeur possible dans votre รฉditeur, avec les outils que vous utilisez pour analyser et refactoriser votre code, etc. โœจ +Le fait que ce soit du **Python standard** signifie que vous bรฉnรฉficierez toujours de la **meilleure expรฉrience dรฉveloppeur possible** dans votre รฉditeur, avec les outils que vous utilisez pour analyser et refactoriser votre code, etc. โœจ Et aussi que votre code sera trรจs compatible avec de nombreux autres outils et bibliothรจques Python. ๐Ÿš€ @@ -457,7 +341,7 @@ Tout cela peut sembler abstrait. Ne vous inquiรฉtez pas. Vous verrez tout cela e L'important est qu'en utilisant les types standards de Python, en un seul endroit (au lieu d'ajouter plus de classes, de dรฉcorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous. -/// info +/// info | Info Si vous avez dรฉjร  parcouru tout le tutoriel et รชtes revenu pour en voir plus sur les types, une bonne ressource est l'ยซ aide-mรฉmoire ยป de `mypy`. diff --git a/docs/fr/docs/resources/index.md b/docs/fr/docs/resources/index.md new file mode 100644 index 0000000000..e62db346da --- /dev/null +++ b/docs/fr/docs/resources/index.md @@ -0,0 +1,3 @@ +# Ressources { #resources } + +Ressources supplรฉmentaires, liens externes et plus encore. โœˆ๏ธ diff --git a/docs/fr/docs/translation-banner.md b/docs/fr/docs/translation-banner.md new file mode 100644 index 0000000000..9eaedf1b1b --- /dev/null +++ b/docs/fr/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ Traduction par IA et humains + +Cette traduction a รฉtรฉ rรฉalisรฉe par une IA guidรฉe par des humains. ๐Ÿค + +Elle peut contenir des erreurs d'interprรฉtation du sens original, ou paraรฎtre peu naturelle, etc. ๐Ÿค– + +Vous pouvez amรฉliorer cette traduction en [nous aidant ร  mieux guider le LLM d'IA](https://fastapi.tiangolo.com/fr/contributing/#translations). + +[Version anglaise](ENGLISH_VERSION_URL) + +/// diff --git a/docs/fr/docs/tutorial/background-tasks.md b/docs/fr/docs/tutorial/background-tasks.md index ed7494669f..a8444ba27a 100644 --- a/docs/fr/docs/tutorial/background-tasks.md +++ b/docs/fr/docs/tutorial/background-tasks.md @@ -15,12 +15,14 @@ Cela comprend, par exemple : Pour commencer, importez `BackgroundTasks` et dรฉfinissez un paramรจtre dans votre *fonction de chemin d'accรจs* avec `BackgroundTasks` comme type dรฉclarรฉ. -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI** crรฉera l'objet de type `BackgroundTasks` pour vous et le passera comme paramรจtre. ## Crรฉer une fonction de tรขche { #create-a-task-function } +Crรฉez une fonction ร  exรฉcuter comme tรขche d'arriรจre-plan. + Une fonction ร  exรฉcuter comme tรขche d'arriรจre-plan est juste une fonction standard qui peut recevoir des paramรจtres. Elle peut รชtre une fonction asynchrone (`async def`) ou une fonction normale (`def`), **FastAPI** saura la gรฉrer correctement. @@ -29,13 +31,13 @@ Dans cet exemple, la fonction de tรขche รฉcrira dans un fichier (afin de simuler L'opรฉration d'รฉcriture n'utilisant ni `async` ni `await`, on dรฉfinit la fonction avec un `def` normal. -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## Ajouter une tรขche d'arriรจre-plan { #add-the-background-task } Dans votre *fonction de chemin d'accรจs*, passez votre fonction de tรขche ร  l'objet de type `BackgroundTasks` (`background_tasks` ici) grรขce ร  la mรฉthode `.add_task()` : -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()` reรงoit comme arguments : diff --git a/docs/fr/docs/tutorial/bigger-applications.md b/docs/fr/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..0659622366 --- /dev/null +++ b/docs/fr/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# Crรฉer des applications plus grandes - Plusieurs fichiers { #bigger-applications-multiple-files } + +Si vous crรฉez une application ou une API web, il est rare que vous puissiez tout mettre dans un seul fichier. + +**FastAPI** fournit un outil pratique pour structurer votre application tout en conservant toute la flexibilitรฉ. + +/// info + +Si vous venez de Flask, cela รฉquivaut aux Blueprints de Flask. + +/// + +## Exemple de structure de fichiers { #an-example-file-structure } + +Supposons que vous ayez une structure de fichiers comme ceci : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | Astuce + +Il y a plusieurs fichiers `__init__.py` : un dans chaque rรฉpertoire ou sous-rรฉpertoire. + +C'est cela qui permet d'importer du code d'un fichier dans un autre. + +Par exemple, dans `app/main.py` vous pourriez avoir une ligne comme : + +``` +from app.routers import items +``` + +/// + +* Le rรฉpertoire `app` contient tout. Et il a un fichier vide `app/__init__.py`, c'est donc un ยซ package Python ยป (une collection de ยซ modules Python ยป) : `app`. +* Il contient un fichier `app/main.py`. Comme il se trouve dans un package Python (un rรฉpertoire avec un fichier `__init__.py`), c'est un ยซ module ยป de ce package : `app.main`. +* Il y a aussi un fichier `app/dependencies.py`, tout comme `app/main.py`, c'est un ยซ module ยป : `app.dependencies`. +* Il y a un sous-rรฉpertoire `app/routers/` avec un autre fichier `__init__.py`, c'est donc un ยซ sous-package Python ยป : `app.routers`. +* Le fichier `app/routers/items.py` est dans un package, `app/routers/`, c'est donc un sous-module : `app.routers.items`. +* De mรชme pour `app/routers/users.py`, c'est un autre sous-module : `app.routers.users`. +* Il y a aussi un sous-rรฉpertoire `app/internal/` avec un autre fichier `__init__.py`, c'est donc un autre ยซ sous-package Python ยป : `app.internal`. +* Et le fichier `app/internal/admin.py` est un autre sous-module : `app.internal.admin`. + + + +La mรชme structure de fichiers avec des commentaires : + +```bash +. +โ”œโ”€โ”€ app # "app" est un package Python +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ce fichier fait de "app" un "package Python" +โ”‚ย ย  โ”œโ”€โ”€ main.py # module "main", ex. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # module "dependencies", ex. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # "routers" est un "sous-package Python" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # fait de "routers" un "sous-package Python" +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # sous-module "items", ex. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # sous-module "users", ex. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # "internal" est un "sous-package Python" +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # fait de "internal" un "sous-package Python" +โ”‚ย ย  โ””โ”€โ”€ admin.py # sous-module "admin", ex. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +Supposons que le fichier dรฉdiรฉ ร  la gestion des utilisateurs soit le sous-module `/app/routers/users.py`. + +Vous voulez sรฉparer les *chemins d'accรจs* liรฉs ร  vos utilisateurs du reste du code pour le garder organisรฉ. + +Mais cela fait toujours partie de la mรชme application/API web **FastAPI** (cela fait partie du mรชme ยซ package Python ยป). + +Vous pouvez crรฉer les *chemins d'accรจs* pour ce module ร  l'aide de `APIRouter`. + +### Importer `APIRouter` { #import-apirouter } + +Vous l'importez et crรฉez une ยซ instance ยป de la mรชme maniรจre que vous le feriez avec la classe `FastAPI` : + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### Dรฉclarer des *chemins d'accรจs* avec `APIRouter` { #path-operations-with-apirouter } + +Puis vous l'utilisez pour dรฉclarer vos *chemins d'accรจs*. + +Utilisez-le de la mรชme maniรจre que vous utiliseriez la classe `FastAPI` : + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +Vous pouvez considรฉrer `APIRouter` comme une ยซ mini `FastAPI` ยป. + +Toutes les mรชmes options sont prises en charge. + +Tous les mรชmes `parameters`, `responses`, `dependencies`, `tags`, etc. + +/// tip | Astuce + +Dans cet exemple, la variable s'appelle `router`, mais vous pouvez la nommer comme vous le souhaitez. + +/// + +Nous allons inclure ce `APIRouter` dans l'application principale `FastAPI`, mais d'abord, examinons les dรฉpendances et un autre `APIRouter`. + +## Gรฉrer les dรฉpendances { #dependencies } + +Nous voyons que nous allons avoir besoin de certaines dรฉpendances utilisรฉes ร  plusieurs endroits de l'application. + +Nous les mettons donc dans leur propre module `dependencies` (`app/dependencies.py`). + +Nous allons maintenant utiliser une dรฉpendance simple pour lire un en-tรชte personnalisรฉ `X-Token` : + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | Astuce + +Nous utilisons un en-tรชte inventรฉ pour simplifier cet exemple. + +Mais dans les cas rรฉels, vous obtiendrez de meilleurs rรฉsultats en utilisant les [utilitaires de sรฉcuritรฉ](security/index.md){.internal-link target=_blank} intรฉgrรฉs. + +/// + +## Crรฉer un autre module avec `APIRouter` { #another-module-with-apirouter } + +Supposons que vous ayez รฉgalement les endpoints dรฉdiรฉs ร  la gestion des ยซ items ยป de votre application dans le module `app/routers/items.py`. + +Vous avez des *chemins d'accรจs* pour : + +* `/items/` +* `/items/{item_id}` + +C'est exactement la mรชme structure que pour `app/routers/users.py`. + +Mais nous voulons รชtre plus malins et simplifier un peu le code. + +Nous savons que tous les *chemins d'accรจs* de ce module ont les mรชmes รฉlรฉments : + +* Prรฉfixe de chemin `prefix` : `/items`. +* `tags` : (un seul tag : `items`). +* `responses` supplรฉmentaires. +* `dependencies` : ils ont tous besoin de la dรฉpendance `X-Token` que nous avons crรฉรฉe. + +Donc, au lieu d'ajouter tout cela ร  chaque *chemin d'accรจs*, nous pouvons l'ajouter au `APIRouter`. + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +Comme le chemin de chaque *chemin d'accรจs* doit commencer par `/`, comme dans : + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +... le prรฉfixe ne doit pas inclure un `/` final. + +Ainsi, le prรฉfixe dans ce cas est `/items`. + +Nous pouvons รฉgalement ajouter une liste de `tags` et des `responses` supplรฉmentaires qui seront appliquรฉs ร  tous les *chemins d'accรจs* inclus dans ce routeur. + +Et nous pouvons ajouter une liste de `dependencies` qui seront ajoutรฉes ร  tous les *chemins d'accรจs* du routeur et seront exรฉcutรฉes/rรฉsolues pour chaque requรชte qui leur est faite. + +/// tip | Astuce + +Notez que, tout comme pour les [dรฉpendances dans les dรฉcorateurs de *chemin d'accรจs*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, aucune valeur ne sera transmise ร  votre *fonction de chemin d'accรจs*. + +/// + +Le rรฉsultat final est que les chemins d'item sont dรฉsormais : + +* `/items/` +* `/items/{item_id}` + +... comme prรฉvu. + +* Ils seront marquรฉs avec une liste de tags qui contient une seule chaรฎne ยซ items ยป. + * Ces ยซ tags ยป sont particuliรจrement utiles pour les systรจmes de documentation interactive automatique (utilisant OpenAPI). +* Ils incluront tous les `responses` prรฉdรฉfinies. +* Tous ces *chemins d'accรจs* auront la liste des `dependencies` รฉvaluรฉes/exรฉcutรฉes avant eux. + * Si vous dรฉclarez รฉgalement des dรฉpendances dans un *chemin d'accรจs* spรฉcifique, **elles seront aussi exรฉcutรฉes**. + * Les dรฉpendances du routeur sont exรฉcutรฉes en premier, puis les [`dependencies` dans le dรฉcorateur](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, puis les dรฉpendances des paramรจtres normaux. + * Vous pouvez รฉgalement ajouter des [`Security` dependencies avec des `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}. + +/// tip | Astuce + +Avoir des `dependencies` dans le `APIRouter` peut servir, par exemple, ร  exiger une authentification pour tout un groupe de *chemins d'accรจs*. Mรชme si les dรฉpendances ne sont pas ajoutรฉes individuellement ร  chacun d'eux. + +/// + +/// check | Vรฉrifications + +Les paramรจtres `prefix`, `tags`, `responses` et `dependencies` sont (comme dans de nombreux autres cas) simplement une fonctionnalitรฉ de **FastAPI** pour vous aider ร  รฉviter la duplication de code. + +/// + +### Importer les dรฉpendances { #import-the-dependencies } + +Ce code se trouve dans le module `app.routers.items`, le fichier `app/routers/items.py`. + +Et nous devons rรฉcupรฉrer la fonction de dรฉpendance depuis le module `app.dependencies`, le fichier `app/dependencies.py`. + +Nous utilisons donc un import relatif avec `..` pour les dรฉpendances : + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### Comprendre le fonctionnement des imports relatifs { #how-relative-imports-work } + +/// tip | Astuce + +Si vous savez parfaitement comment fonctionnent les imports, passez ร  la section suivante ci-dessous. + +/// + +Un seul point `.`, comme dans : + +```Python +from .dependencies import get_token_header +``` + +signifierait : + +* En partant du mรชme package dans lequel vit ce module (le fichier `app/routers/items.py`) (le rรฉpertoire `app/routers/`)... +* trouver le module `dependencies` (un fichier imaginaire `app/routers/dependencies.py`)... +* et en importer la fonction `get_token_header`. + +Mais ce fichier n'existe pas, nos dรฉpendances sont dans un fichier `app/dependencies.py`. + +Rappelez-vous ร  quoi ressemble la structure de notre app/fichiers : + + + +--- + +Les deux points `..`, comme dans : + +```Python +from ..dependencies import get_token_header +``` + +veulent dire : + +* En partant du mรชme package dans lequel vit ce module (le fichier `app/routers/items.py`) (le rรฉpertoire `app/routers/`)... +* aller au package parent (le rรฉpertoire `app/`)... +* et lร , trouver le module `dependencies` (le fichier `app/dependencies.py`)... +* et en importer la fonction `get_token_header`. + +Cela fonctionne correctement ! ๐ŸŽ‰ + +--- + +De la mรชme maniรจre, si nous avions utilisรฉ trois points `...`, comme dans : + +```Python +from ...dependencies import get_token_header +``` + +cela voudrait dire : + +* En partant du mรชme package dans lequel vit ce module (le fichier `app/routers/items.py`) (le rรฉpertoire `app/routers/`)... +* aller au package parent (le rรฉpertoire `app/`)... +* puis aller au parent de ce package (il n'y a pas de package parent, `app` est le niveau supรฉrieur ๐Ÿ˜ฑ)... +* et lร , trouver le module `dependencies` (le fichier `app/dependencies.py`)... +* et en importer la fonction `get_token_header`. + +Cela ferait rรฉfรฉrence ร  un package au-dessus de `app/`, avec son propre fichier `__init__.py`, etc. Mais nous n'avons pas cela. Donc, cela lรจverait une erreur dans notre exemple. ๐Ÿšจ + +Mais maintenant vous savez comment cela fonctionne, vous pouvez donc utiliser des imports relatifs dans vos propres applications, aussi complexes soient-elles. ๐Ÿค“ + +### Ajouter des `tags`, `responses` et `dependencies` personnalisรฉs { #add-some-custom-tags-responses-and-dependencies } + +Nous n'ajoutons pas le prรฉfixe `/items` ni `tags=["items"]` ร  chaque *chemin d'accรจs* parce que nous les avons ajoutรฉs au `APIRouter`. + +Mais nous pouvons toujours ajouter _davantage_ de `tags` qui seront appliquรฉs ร  un *chemin d'accรจs* spรฉcifique, ainsi que des `responses` supplรฉmentaires propres ร  ce *chemin d'accรจs* : + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | Astuce + +Ce dernier *chemin d'accรจs* aura la combinaison de tags : `["items", "custom"]`. + +Et il aura รฉgalement les deux rรฉponses dans la documentation, une pour `404` et une pour `403`. + +/// + +## Crรฉer l'application `FastAPI` principale { #the-main-fastapi } + +Voyons maintenant le module `app/main.py`. + +C'est ici que vous importez et utilisez la classe `FastAPI`. + +Ce sera le fichier principal de votre application qui reliera tout ensemble. + +Et comme la plupart de votre logique vivra dรฉsormais dans son propre module, le fichier principal sera assez simple. + +### Importer `FastAPI` { #import-fastapi } + +Vous importez et crรฉez une classe `FastAPI` comme d'habitude. + +Et nous pouvons mรชme dรฉclarer des [dรฉpendances globales](dependencies/global-dependencies.md){.internal-link target=_blank} qui seront combinรฉes avec les dรฉpendances de chaque `APIRouter` : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### Importer les `APIRouter` { #import-the-apirouter } + +Nous importons maintenant les autres sous-modules qui ont des `APIRouter` : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +Comme les fichiers `app/routers/users.py` et `app/routers/items.py` sont des sous-modules qui font partie du mรชme package Python `app`, nous pouvons utiliser un seul point `.` pour les importer en utilisant des ยซ imports relatifs ยป. + +### Comprendre le fonctionnement de l'import { #how-the-importing-works } + +La section : + +```Python +from .routers import items, users +``` + +signifie : + +* En partant du mรชme package dans lequel vit ce module (le fichier `app/main.py`) (le rรฉpertoire `app/`)... +* chercher le sous-package `routers` (le rรฉpertoire `app/routers/`)... +* et en importer le sous-module `items` (le fichier `app/routers/items.py`) et `users` (le fichier `app/routers/users.py`)... + +Le module `items` aura une variable `router` (`items.router`). C'est celle que nous avons crรฉรฉe dans le fichier `app/routers/items.py`, c'est un objet `APIRouter`. + +Nous faisons ensuite la mรชme chose pour le module `users`. + +Nous pourrions aussi les importer ainsi : + +```Python +from app.routers import items, users +``` + +/// info + +La premiรจre version est un ยซ import relatif ยป : + +```Python +from .routers import items, users +``` + +La deuxiรจme version est un ยซ import absolu ยป : + +```Python +from app.routers import items, users +``` + +Pour en savoir plus sur les Packages et Modules Python, lisez la documentation officielle de Python sur les modules. + +/// + +### ร‰viter les collisions de noms { #avoid-name-collisions } + +Nous importons le sous-module `items` directement, au lieu d'importer uniquement sa variable `router`. + +C'est parce que nous avons รฉgalement une autre variable nommรฉe `router` dans le sous-module `users`. + +Si nous les avions importรฉes l'une aprรจs l'autre, comme : + +```Python +from .routers.items import router +from .routers.users import router +``` + +le `router` de `users` รฉcraserait celui de `items` et nous ne pourrions pas les utiliser en mรชme temps. + +Donc, pour pouvoir utiliser les deux dans le mรชme fichier, nous importons directement les sous-modules : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### Inclure les `APIRouter` pour `users` et `items` { #include-the-apirouters-for-users-and-items } + +Incluons maintenant les `router` des sous-modules `users` et `items` : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// info + +`users.router` contient le `APIRouter` ร  l'intรฉrieur du fichier `app/routers/users.py`. + +Et `items.router` contient le `APIRouter` ร  l'intรฉrieur du fichier `app/routers/items.py`. + +/// + +Avec `app.include_router()`, nous pouvons ajouter chaque `APIRouter` ร  l'application principale `FastAPI`. + +Cela inclura toutes les routes de ce routeur comme faisant partie de l'application. + +/// note | Dรฉtails techniques + +En interne, cela crรฉera en fait un *chemin d'accรจs* pour chaque *chemin d'accรจs* qui a รฉtรฉ dรฉclarรฉ dans le `APIRouter`. + +Donc, en coulisses, cela fonctionnera comme si tout faisait partie d'une seule et mรชme application. + +/// + +/// check | Vรฉrifications + +Vous n'avez pas ร  vous soucier de la performance lors de l'inclusion de routeurs. + +Cela prendra des microsecondes et ne se produira qu'au dรฉmarrage. + +Donc cela n'affectera pas la performance. โšก + +/// + +### Inclure un `APIRouter` avec un `prefix`, des `tags`, des `responses` et des `dependencies` personnalisรฉs { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +Imaginons maintenant que votre organisation vous ait fourni le fichier `app/internal/admin.py`. + +Il contient un `APIRouter` avec quelques *chemins d'accรจs* d'administration que votre organisation partage entre plusieurs projets. + +Pour cet exemple, il sera trรจs simple. Mais supposons que, parce qu'il est partagรฉ avec d'autres projets de l'organisation, nous ne puissions pas le modifier et ajouter un `prefix`, des `dependencies`, des `tags`, etc. directement au `APIRouter` : + +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +Mais nous voulons quand mรชme dรฉfinir un `prefix` personnalisรฉ lors de l'inclusion du `APIRouter` afin que tous ses *chemins d'accรจs* commencent par `/admin`, nous voulons le sรฉcuriser avec les `dependencies` que nous avons dรฉjร  pour ce projet, et nous voulons inclure des `tags` et des `responses`. + +Nous pouvons dรฉclarer tout cela sans avoir ร  modifier le `APIRouter` d'origine en passant ces paramรจtres ร  `app.include_router()` : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +De cette faรงon, le `APIRouter` original restera inchangรฉ, afin que nous puissions toujours partager ce mรชme fichier `app/internal/admin.py` avec d'autres projets de l'organisation. + +Le rรฉsultat est que, dans notre application, chacun des *chemins d'accรจs* du module `admin` aura : + +* Le prรฉfixe `/admin`. +* Le tag `admin`. +* La dรฉpendance `get_token_header`. +* La rรฉponse `418`. ๐Ÿต + +Mais cela n'affectera que ce `APIRouter` dans notre application, pas dans tout autre code qui l'utilise. + +Ainsi, par exemple, d'autres projets pourraient utiliser le mรชme `APIRouter` avec une mรฉthode d'authentification diffรฉrente. + +### Inclure un *chemin d'accรจs* { #include-a-path-operation } + +Nous pouvons รฉgalement ajouter des *chemins d'accรจs* directement ร  l'application `FastAPI`. + +Ici, nous le faisons... juste pour montrer que nous le pouvons ๐Ÿคท : + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +et cela fonctionnera correctement, avec tous les autres *chemins d'accรจs* ajoutรฉs avec `app.include_router()`. + +/// info | Dรฉtails trรจs techniques + +Note : c'est un dรฉtail trรจs technique que vous pouvez probablement **simplement ignorer**. + +--- + +Les `APIRouter` ne sont pas ยซ montรฉs ยป, ils ne sont pas isolรฉs du reste de l'application. + +C'est parce que nous voulons inclure leurs *chemins d'accรจs* dans le schรฉma OpenAPI et les interfaces utilisateur. + +Comme nous ne pouvons pas simplement les isoler et les ยซ monter ยป indรฉpendamment du reste, les *chemins d'accรจs* sont ยซ clonรฉs ยป (recrรฉรฉs), pas inclus directement. + +/// + +## Consulter la documentation API automatique { #check-the-automatic-api-docs } + +Maintenant, exรฉcutez votre application : + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Et ouvrez les documents ร  http://127.0.0.1:8000/docs. + +Vous verrez la documentation API automatique, incluant les chemins de tous les sous-modules, utilisant les bons chemins (et prรฉfixes) et les bons tags : + + + +## Inclure le mรชme routeur plusieurs fois avec des `prefix` diffรฉrents { #include-the-same-router-multiple-times-with-different-prefix } + +Vous pouvez aussi utiliser `.include_router()` plusieurs fois avec le mรชme routeur en utilisant des prรฉfixes diffรฉrents. + +Cela peut รชtre utile, par exemple, pour exposer la mรชme API sous des prรฉfixes diffรฉrents, p. ex. `/api/v1` et `/api/latest`. + +C'est un usage avancรฉ dont vous n'aurez peut-รชtre pas vraiment besoin, mais il est lร  au cas oรน. + +## Inclure un `APIRouter` dans un autre { #include-an-apirouter-in-another } + +De la mรชme maniรจre que vous pouvez inclure un `APIRouter` dans une application `FastAPI`, vous pouvez inclure un `APIRouter` dans un autre `APIRouter` en utilisant : + +```Python +router.include_router(other_router) +``` + +Vous devez vous assurer de le faire avant d'inclure `router` dans l'application `FastAPI`, afin que les *chemins d'accรจs* de `other_router` soient รฉgalement inclus. diff --git a/docs/fr/docs/tutorial/body-fields.md b/docs/fr/docs/tutorial/body-fields.md new file mode 100644 index 0000000000..9830292c90 --- /dev/null +++ b/docs/fr/docs/tutorial/body-fields.md @@ -0,0 +1,61 @@ +# Corps - Champs { #body-fields } + +De la mรชme maniรจre que vous pouvez dรฉclarer des validations supplรฉmentaires et des mรฉtadonnรฉes dans les paramรจtres d'une fonction de chemin d'accรจs avec `Query`, `Path` et `Body`, vous pouvez dรฉclarer des validations et des mรฉtadonnรฉes ร  l'intรฉrieur des modรจles Pydantic en utilisant `Field` de Pydantic. + +## Importer `Field` { #import-field } + +D'abord, vous devez l'importer : + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + + +/// warning | Alertes + +Notez que `Field` est importรฉ directement depuis `pydantic`, et non depuis `fastapi` comme le sont les autres (`Query`, `Path`, `Body`, etc.). + +/// + +## Dรฉclarer les attributs du modรจle { #declare-model-attributes } + +Vous pouvez ensuite utiliser `Field` avec des attributs de modรจle : + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} + +`Field` fonctionne de la mรชme maniรจre que `Query`, `Path` et `Body`, il dispose des mรชmes paramรจtres, etc. + +/// note | Dรฉtails techniques + +En rรฉalitรฉ, `Query`, `Path` et d'autres que vous verrez ensuite crรฉent des objets de sous-classes d'une classe commune `Param`, qui est elle-mรชme une sous-classe de la classe `FieldInfo` de Pydantic. + +Et `Field` de Pydantic renvoie รฉgalement une instance de `FieldInfo`. + +`Body` renvoie aussi directement des objets d'une sous-classe de `FieldInfo`. Et il y en a d'autres que vous verrez plus tard qui sont des sous-classes de la classe `Body`. + +Rappelez-vous que lorsque vous importez `Query`, `Path` et d'autres depuis `fastapi`, ce sont en rรฉalitรฉ des fonctions qui renvoient des classes spรฉciales. + +/// + +/// tip | Astuce + +Remarquez comment chaque attribut de modรจle avec un type, une valeur par dรฉfaut et `Field` a la mรชme structure qu'un paramรจtre de fonction de chemin d'accรจs, avec `Field` au lieu de `Path`, `Query` et `Body`. + +/// + +## Ajouter des informations supplรฉmentaires { #add-extra-information } + +Vous pouvez dรฉclarer des informations supplรฉmentaires dans `Field`, `Query`, `Body`, etc. Elles seront incluses dans le JSON Schema gรฉnรฉrรฉ. + +Vous en apprendrez davantage sur l'ajout d'informations supplรฉmentaires plus loin dans les documents, lorsque vous apprendrez ร  dรฉclarer des exemples. + +/// warning | Alertes + +Les clรฉs supplรฉmentaires passรฉes ร  `Field` seront รฉgalement prรฉsentes dans le schรฉma OpenAPI rรฉsultant pour votre application. +Comme ces clรฉs ne font pas nรฉcessairement partie de la spรฉcification OpenAPI, certains outils OpenAPI, par exemple [le validateur OpenAPI](https://validator.swagger.io/), peuvent ne pas fonctionner avec votre schรฉma gรฉnรฉrรฉ. + +/// + +## Rรฉcapitulatif { #recap } + +Vous pouvez utiliser `Field` de Pydantic pour dรฉclarer des validations supplรฉmentaires et des mรฉtadonnรฉes pour les attributs de modรจle. + +Vous pouvez รฉgalement utiliser des arguments nommรฉs supplรฉmentaires pour transmettre des mรฉtadonnรฉes JSON Schema additionnelles. diff --git a/docs/fr/docs/tutorial/body-multiple-params.md b/docs/fr/docs/tutorial/body-multiple-params.md index 92ca2afc36..1c1ab0fcac 100644 --- a/docs/fr/docs/tutorial/body-multiple-params.md +++ b/docs/fr/docs/tutorial/body-multiple-params.md @@ -104,12 +104,6 @@ Comme, par dรฉfaut, les valeurs singuliรจres sont interprรฉtรฉes comme des param q: str | None = None ``` -Ou en Python 3.9 : - -```Python -q: Union[str, None] = None -``` - Par exemple : {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/fr/docs/tutorial/body-nested-models.md b/docs/fr/docs/tutorial/body-nested-models.md new file mode 100644 index 0000000000..dccfdb6c5d --- /dev/null +++ b/docs/fr/docs/tutorial/body-nested-models.md @@ -0,0 +1,220 @@ +# Corps - Modรจles imbriquรฉs { #body-nested-models } + +Avec FastAPI, vous pouvez dรฉfinir, valider, documenter et utiliser des modรจles imbriquรฉs ร  n'importe quelle profondeur (grรขce ร  Pydantic). + +## Dรฉclarer des champs de liste { #list-fields } + +Vous pouvez dรฉfinir un attribut comme รฉtant un sous-type. Par exemple, une `list` Python : + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +Cela fera de `tags` une liste, bien que le type des รฉlรฉments de la liste ne soit pas dรฉclarรฉ. + +## Champs de liste avec paramรจtre de type { #list-fields-with-type-parameter } + +Mais Python a une maniรจre spรฉcifique de dรฉclarer des listes avec des types internes, ou ยซ paramรจtres de type ยป : + +### Dรฉclarer une `list` avec un paramรจtre de type { #declare-a-list-with-a-type-parameter } + +Pour dรฉclarer des types qui ont des paramรจtres de type (types internes), comme `list`, `dict`, `tuple`, +passez le(s) type(s) interne(s) comme ยซ paramรจtres de type ยป ร  l'aide de crochets : `[` et `]` + +```Python +my_list: list[str] +``` + +C'est simplement la syntaxe Python standard pour les dรฉclarations de type. + +Utilisez cette mรชme syntaxe standard pour les attributs de modรจles avec des types internes. + +Ainsi, dans notre exemple, nous pouvons faire de `tags` spรฉcifiquement une ยซ liste de chaรฎnes ยป : + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## Types set { #set-types } + +Mais en y rรฉflรฉchissant, nous rรฉalisons que les tags ne devraient pas se rรฉpรฉter, ce seraient probablement des chaรฎnes uniques. + +Et Python dispose d'un type de donnรฉes spรฉcial pour les ensembles d'รฉlรฉments uniques, le `set`. + +Nous pouvons alors dรฉclarer `tags` comme un set de chaรฎnes : + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +Avec cela, mรชme si vous recevez une requรชte contenant des doublons, elle sera convertie en un set d'รฉlรฉments uniques. + +Et chaque fois que vous renverrez ces donnรฉes, mรชme si la source contenait des doublons, elles seront renvoyรฉes sous la forme d'un set d'รฉlรฉments uniques. + +Elles seront รฉgalement annotรฉes / documentรฉes en consรฉquence. + +## Modรจles imbriquรฉs { #nested-models } + +Chaque attribut d'un modรจle Pydantic a un type. + +Mais ce type peut lui-mรชme รชtre un autre modรจle Pydantic. + +Ainsi, vous pouvez dรฉclarer des ยซ objets ยป JSON profondรฉment imbriquรฉs avec des noms d'attributs, des types et des validations spรฉcifiques. + +Tout cela, de maniรจre arbitrairement imbriquรฉe. + +### Dรฉfinir un sous-modรจle { #define-a-submodel } + +Par exemple, nous pouvons dรฉfinir un modรจle `Image` : + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### Utiliser le sous-modรจle comme type { #use-the-submodel-as-a-type } + +Nous pouvons ensuite l'utiliser comme type d'un attribut : + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +Cela signifie que FastAPI attendrait un corps similaire ร  : + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Lร  encore, avec cette simple dรฉclaration, avec FastAPI vous obtenez : + +- Prise en charge par l'รฉditeur (autocomplรฉtion, etc.), mรชme pour les modรจles imbriquรฉs +- Conversion des donnรฉes +- Validation des donnรฉes +- Documentation automatique + +## Types spรฉciaux et validation { #special-types-and-validation } + +Outre les types singuliers normaux comme `str`, `int`, `float`, etc. vous pouvez utiliser des types singuliers plus complexes qui hรฉritent de `str`. + +Pour voir toutes les options dont vous disposez, consultez lโ€™aperรงu des types de Pydantic. Vous verrez quelques exemples au chapitre suivant. + +Par exemple, comme dans le modรจle `Image` nous avons un champ `url`, nous pouvons le dรฉclarer comme instance de `HttpUrl` de Pydantic au lieu de `str` : + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +La chaรฎne sera vรฉrifiรฉe comme URL valide et documentรฉe comme telle dans JSON Schema / OpenAPI. + +## Attributs avec des listes de sous-modรจles { #attributes-with-lists-of-submodels } + +Vous pouvez รฉgalement utiliser des modรจles Pydantic comme sous-types de `list`, `set`, etc. : + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +Cela attendra (convertira, validera, documentera, etc.) un corps JSON comme : + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` +/// info + +Remarquez que la clรฉ `images` contient maintenant une liste d'objets image. + +/// + +## Modรจles profondรฉment imbriquรฉs { #deeply-nested-models } + +Vous pouvez dรฉfinir des modรจles imbriquรฉs ร  une profondeur arbitraire : + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// info + +Remarquez que `Offer` a une liste dโ€™`Item`, qui ร  leur tour ont une liste optionnelle dโ€™`Image`. + +/// + +## Corps de listes pures { #bodies-of-pure-lists } + +Si la valeur de premier niveau du corps JSON attendu est un `array` JSON (une `list` Python), vous pouvez dรฉclarer le type dans le paramรจtre de la fonction, de la mรชme maniรจre que dans les modรจles Pydantic : + +```Python +images: list[Image] +``` + +comme : + +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} + +## Bรฉnรฉficier de la prise en charge de l'รฉditeur partout { #editor-support-everywhere } + +Et vous bรฉnรฉficiez de la prise en charge de l'รฉditeur partout. + +Mรชme pour les รฉlรฉments ร  l'intรฉrieur des listes : + + + +Vous ne pourriez pas obtenir ce type de prise en charge de l'รฉditeur si vous travailliez directement avec des `dict` au lieu de modรจles Pydantic. + +Mais vous n'avez pas ร  vous en soucier non plus, les `dict` entrants sont convertis automatiquement et votre sortie est รฉgalement convertie automatiquement en JSON. + +## Corps de `dict` arbitraires { #bodies-of-arbitrary-dicts } + +Vous pouvez รฉgalement dรฉclarer un corps comme un `dict` avec des clรฉs dโ€™un certain type et des valeurs dโ€™un autre type. + +De cette faรงon, vous n'avez pas besoin de savoir ร  l'avance quels sont les noms de champs/attributs valides (comme ce serait le cas avec des modรจles Pydantic). + +Cela serait utile si vous voulez recevoir des clรฉs que vous ne connaissez pas ร  l'avance. + +--- + +Un autre cas utile est lorsque vous souhaitez avoir des clรฉs d'un autre type (par exemple `int`). + +C'est ce que nous allons voir ici. + +Dans ce cas, vous accepteriez n'importe quel `dict` tant qu'il a des clรฉs `int` avec des valeurs `float` : + +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} + +/// tip | Astuce + +Gardez ร  l'esprit que JSON ne prend en charge que des `str` comme clรฉs. + +Mais Pydantic dispose d'une conversion automatique des donnรฉes. + +Cela signifie que, mรชme si vos clients d'API ne peuvent envoyer que des chaรฎnes comme clรฉs, tant que ces chaรฎnes contiennent des entiers purs, Pydantic les convertira et les validera. + +Et le `dict` que vous recevez dans `weights` aura en rรฉalitรฉ des clรฉs `int` et des valeurs `float`. + +/// + +## Rรฉcapitulatif { #recap } + +Avec FastAPI, vous bรฉnรฉficiez de la flexibilitรฉ maximale fournie par les modรจles Pydantic, tout en gardant votre code simple, concis et รฉlรฉgant. + +Mais avec tous les avantages : + +- Prise en charge par l'รฉditeur (autocomplรฉtion partout !) +- Conversion des donnรฉes (a.k.a. parsing / sรฉrialisation) +- Validation des donnรฉes +- Documentation des schรฉmas +- Documentation automatique diff --git a/docs/fr/docs/tutorial/body-updates.md b/docs/fr/docs/tutorial/body-updates.md new file mode 100644 index 0000000000..36ad12681c --- /dev/null +++ b/docs/fr/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Corps - Mises ร  jour { #body-updates } + +## Mettre ร  jour en remplaรงant avec `PUT` { #update-replacing-with-put } + +Pour mettre ร  jour un รฉlรฉment, vous pouvez utiliser lโ€™opรฉration HTTP `PUT`. + +Vous pouvez utiliser le `jsonable_encoder` pour convertir les donnรฉes dโ€™entrรฉe en donnรฉes pouvant รชtre stockรฉes au format JSON (par exemple, avec une base de donnรฉes NoSQL). Par exemple, convertir `datetime` en `str`. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +On utilise `PUT` pour recevoir des donnรฉes qui doivent remplacer les donnรฉes existantes. + +### Avertissement concernant le remplacement { #warning-about-replacing } + +Cela signifie que si vous souhaitez mettre ร  jour lโ€™รฉlรฉment `bar` avec `PUT` et un corps contenant : + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +comme il nโ€™inclut pas lโ€™attribut dรฉjร  enregistrรฉ ยซ tax ยป: 20.2, le modรจle dโ€™entrรฉe prendrait la valeur par dรฉfaut ยซ tax ยป: 10.5. + +Et les donnรฉes seraient enregistrรฉes avec cette ยซ nouvelle ยป `tax` de `10.5`. + +## Effectuer des mises ร  jour partielles avec `PATCH` { #partial-updates-with-patch } + +Vous pouvez รฉgalement utiliser lโ€™opรฉration HTTP `PATCH` pour mettre ร  jour des donnรฉes de maniรจre partielle. + +Cela signifie que vous pouvez nโ€™envoyer que les donnรฉes que vous souhaitez mettre ร  jour, en laissant le reste intact. + +/// note | Remarque + +`PATCH` est moins utilisรฉ et moins connu que `PUT`. + +Et de nombreuses รฉquipes nโ€™utilisent que `PUT`, mรชme pour les mises ร  jour partielles. + +Vous รชtes libre de les utiliser comme vous le souhaitez, **FastAPI** nโ€™impose aucune restriction. + +Mais ce guide vous montre, plus ou moins, la faรงon dont ils sont censรฉs รชtre utilisรฉs. + +/// + +### Utiliser le paramรจtre `exclude_unset` de Pydantic { #using-pydantics-exclude-unset-parameter } + +Si vous souhaitez recevoir des mises ร  jour partielles, il est trรจs utile dโ€™utiliser le paramรจtre `exclude_unset` dans la mรฉthode `.model_dump()` du modรจle Pydantic. + +Comme `item.model_dump(exclude_unset=True)`. + +Cela gรฉnรจre un `dict` ne contenant que les donnรฉes dรฉfinies lors de la crรฉation du modรจle `item`, en excluant les valeurs par dรฉfaut. + +Vous pouvez ensuite lโ€™utiliser pour produire un `dict` avec uniquement les donnรฉes dรฉfinies (envoyรฉes dans la requรชte), en omettant les valeurs par dรฉfaut : + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Utiliser le paramรจtre `update` de Pydantic { #using-pydantics-update-parameter } + +Vous pouvez maintenant crรฉer une copie du modรจle existant avec `.model_copy()`, et passer le paramรจtre `update` avec un `dict` contenant les donnรฉes ร  mettre ร  jour. + +Comme `stored_item_model.model_copy(update=update_data)` : + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### Rรฉcapitulatif des mises ร  jour partielles { #partial-updates-recap } + +En rรฉsumรฉ, pour appliquer des mises ร  jour partielles, vous procรฉdez ainsi : + +* (Optionnel) utilisez `PATCH` au lieu de `PUT`. +* Rรฉcupรฉrez les donnรฉes stockรฉes. +* Placez ces donnรฉes dans un modรจle Pydantic. +* Gรฉnรฉrez un `dict` sans valeurs par dรฉfaut ร  partir du modรจle dโ€™entrรฉe (en utilisant `exclude_unset`). + * De cette faรงon, vous mettez ร  jour uniquement les valeurs effectivement dรฉfinies par lโ€™utilisateur, au lieu dโ€™รฉcraser des valeurs dรฉjร  stockรฉes par des valeurs par dรฉfaut de votre modรจle. +* Crรฉez une copie du modรจle stockรฉ, en mettant ร  jour ses attributs avec les mises ร  jour partielles reรงues (en utilisant le paramรจtre `update`). +* Convertissez le modรจle copiรฉ en quelque chose qui peut รชtre stockรฉ dans votre base de donnรฉes (par exemple en utilisant le `jsonable_encoder`). + * Cela est comparable ร  lโ€™utilisation ร  nouveau de la mรฉthode `.model_dump()` du modรจle, mais cela vรฉrifie (et convertit) les valeurs vers des types pouvant รชtre convertis en JSON, par exemple `datetime` en `str`. +* Enregistrez les donnรฉes dans votre base de donnรฉes. +* Retournez le modรจle mis ร  jour. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | Astuce + +Vous pouvez en rรฉalitรฉ utiliser cette mรชme technique avec une opรฉration HTTP `PUT`. + +Mais lโ€™exemple ici utilise `PATCH` car il a รฉtรฉ crรฉรฉ pour ces cas dโ€™usage. + +/// + +/// note | Remarque + +Remarquez que le modรจle dโ€™entrรฉe est toujours validรฉ. + +Ainsi, si vous souhaitez recevoir des mises ร  jour partielles pouvant omettre tous les attributs, vous devez disposer dโ€™un modรจle avec tous les attributs marquรฉs comme optionnels (avec des valeurs par dรฉfaut ou `None`). + +Pour distinguer les modรจles avec toutes les valeurs optionnelles pour les mises ร  jour et les modรจles avec des valeurs requises pour la crรฉation, vous pouvez utiliser les idรฉes dรฉcrites dans [Modรจles supplรฉmentaires](extra-models.md){.internal-link target=_blank}. + +/// diff --git a/docs/fr/docs/tutorial/body.md b/docs/fr/docs/tutorial/body.md index ca115fabc7..a8703e030d 100644 --- a/docs/fr/docs/tutorial/body.md +++ b/docs/fr/docs/tutorial/body.md @@ -10,7 +10,7 @@ Pour dรฉclarer un corps de **requรชte**, on utilise les modรจles de -Et seront aussi utilisรฉs dans chaque *opรฉration de chemin* de la documentation utilisant ces modรจles : +Et seront aussi utilisรฉs dans chaque *chemin d'accรจs* de la documentation utilisant ces modรจles : @@ -115,7 +115,7 @@ Ce qui amรฉliore le support pour les modรจles Pydantic avec : * de l'autocomplรฉtion * des vรฉrifications de type -* du ยซย refactoringย ยป (ou remaniement de code) +* du ยซย refactoringย ยป * de la recherche * des inspections @@ -129,7 +129,7 @@ Dans la fonction, vous pouvez accรฉder ร  tous les attributs de l'objet du modรจ ## Corps de la requรชte + paramรจtres de chemin { #request-body-path-parameters } -Vous pouvez dรฉclarer des paramรจtres de chemin et un corps de requรชte pour la mรชme *opรฉration de chemin*. +Vous pouvez dรฉclarer des paramรจtres de chemin et un corps de requรชte pour la mรชme *chemin d'accรจs*. **FastAPI** est capable de reconnaรฎtre que les paramรจtres de la fonction qui correspondent aux paramรจtres de chemin doivent รชtre **rรฉcupรฉrรฉs depuis le chemin**, et que les paramรจtres de fonctions dรฉclarรฉs comme modรจles Pydantic devraient รชtre **rรฉcupรฉrรฉs depuis le corps de la requรชte**. @@ -137,7 +137,7 @@ Vous pouvez dรฉclarer des paramรจtres de chemin et un corps de requรชte pour la ## Corps de la requรชte + paramรจtres de chemin et de requรชte { #request-body-path-query-parameters } -Vous pouvez aussi dรฉclarer un **corps**, et des paramรจtres de **chemin** et de **requรชte** dans la mรชme *opรฉration de chemin*. +Vous pouvez aussi dรฉclarer un **corps**, et des paramรจtres de **chemin** et de **requรชte** dans la mรชme *chemin d'accรจs*. **FastAPI** saura reconnaรฎtre chacun d'entre eux et rรฉcupรฉrer la bonne donnรฉe au bon endroit. @@ -153,7 +153,7 @@ Les paramรจtres de la fonction seront reconnus comme tel : **FastAPI** saura que la valeur de `q` n'est pas requise grรขce ร  la valeur par dรฉfaut `= None`. -L'annotation de type `str | None` (Python 3.10+) ou `Union` dans `Union[str, None]` (Python 3.9+) n'est pas utilisรฉe par **FastAPI** pour dรฉterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par dรฉfaut `= None`. +L'annotation de type `str | None` n'est pas utilisรฉe par **FastAPI** pour dรฉterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par dรฉfaut `= None`. Mais ajouter ces annotations de type permettra ร  votre รฉditeur de vous offrir un meilleur support et de dรฉtecter des erreurs. diff --git a/docs/fr/docs/tutorial/cookie-param-models.md b/docs/fr/docs/tutorial/cookie-param-models.md new file mode 100644 index 0000000000..c6fc2f8262 --- /dev/null +++ b/docs/fr/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Modรจles de paramรจtres de cookies { #cookie-parameter-models } + +Si vous avez un groupe de **cookies** liรฉs, vous pouvez crรฉer un **modรจle Pydantic** pour les dรฉclarer. ๐Ÿช + +Cela vous permet de **rรฉutiliser le modรจle** ร  **plusieurs endroits** et aussi de dรฉclarer des validations et des mรฉtadonnรฉes pour tous les paramรจtres en une seule fois. ๐Ÿ˜Ž + +/// note | Remarque + +Ceci est pris en charge depuis la version `0.115.0` de FastAPI. ๐Ÿค“ + +/// + +/// tip | Astuce + +Cette mรชme technique s'applique ร  `Query`, `Cookie` et `Header`. ๐Ÿ˜Ž + +/// + +## Dรฉclarer des cookies avec un modรจle Pydantic { #cookies-with-a-pydantic-model } + +Dรฉclarez les paramรจtres de **cookie** dont vous avez besoin dans un **modรจle Pydantic**, puis dรฉclarez le paramรจtre comme `Cookie` : + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** va **extraire** les donnรฉes pour **chaque champ** ร  partir des **cookies** reรงus dans la requรชte et vous fournir le modรจle Pydantic que vous avez dรฉfini. + +## Consulter la documentation { #check-the-docs } + +Vous pouvez voir les cookies dรฉfinis dans l'interface de la documentation ร  `/docs` : + +
+ +
+ +/// info + +Gardez ร  l'esprit que, comme les **navigateurs gรจrent les cookies** de maniรจre particuliรจre et en arriรจre-plan, ils **n'autorisent pas** facilement **JavaScript** ร  y accรฉder. + +Si vous allez dans **l'interface de la documentation de l'API** ร  `/docs`, vous pourrez voir la **documentation** des cookies pour vos *chemins d'accรจs*. + +Mais mรชme si vous **remplissez les donnรฉes** et cliquez sur ยซ Execute ยป, comme l'interface de la documentation fonctionne avec **JavaScript**, les cookies ne seront pas envoyรฉs et vous verrez un **message d'erreur** comme si vous n'aviez saisi aucune valeur. + +/// + +## Interdire les cookies supplรฉmentaires { #forbid-extra-cookies } + +Dans certains cas d'utilisation particuliers (probablement peu courants), vous pourriez vouloir **restreindre** les cookies que vous souhaitez recevoir. + +Votre API a dรฉsormais le pouvoir de contrรดler son propre consentement aux cookies. ๐Ÿคช๐Ÿช + +Vous pouvez utiliser la configuration du modรจle de Pydantic pour `forbid` tout champ `extra` : + +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} + +Si un client tente d'envoyer des **cookies supplรฉmentaires**, il recevra une **rรฉponse d'erreur**. + +Pauvres banniรจres de cookies, avec tous leurs efforts pour obtenir votre consentement pour que l'API pour le rejeter. ๐Ÿช + +Par exemple, si le client tente d'envoyer un cookie `santa_tracker` avec la valeur `good-list-please`, il recevra une **rรฉponse d'erreur** lui indiquant que le `santa_tracker` le cookie n'est pas autorisรฉ : + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## Rรฉcapitulatif { #summary } + +Vous pouvez utiliser des **modรจles Pydantic** pour dรฉclarer des **cookies** dans **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/fr/docs/tutorial/cookie-params.md b/docs/fr/docs/tutorial/cookie-params.md new file mode 100644 index 0000000000..8f77d35dca --- /dev/null +++ b/docs/fr/docs/tutorial/cookie-params.md @@ -0,0 +1,45 @@ +# Paramรจtres de cookie { #cookie-parameters } + +Vous pouvez dรฉfinir des paramรจtres de cookie de la mรชme maniรจre que vous dรฉfinissez les paramรจtres `Query` et `Path`. + +## Importer `Cookie` { #import-cookie } + +Commencez par importer `Cookie` : + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} + +## Dรฉclarer des paramรจtres `Cookie` { #declare-cookie-parameters } + +Dรฉclarez ensuite les paramรจtres de cookie en utilisant la mรชme structure qu'avec `Path` et `Query`. + +Vous pouvez dรฉfinir la valeur par dรฉfaut ainsi que tous les paramรจtres supplรฉmentaires de validation ou d'annotation : + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} + +/// note | Dรฉtails techniques + +`Cookie` est une classe ยซ sล“ur ยป de `Path` et `Query`. Elle hรฉrite รฉgalement de la mรชme classe commune `Param`. + +Mais rappelez-vous que lorsque vous importez `Query`, `Path`, `Cookie` et d'autres depuis `fastapi`, il s'agit en rรฉalitรฉ de fonctions qui renvoient des classes spรฉciales. + +/// + +/// info + +Pour dรฉclarer des cookies, vous devez utiliser `Cookie`, sinon les paramรจtres seraient interprรฉtรฉs comme des paramรจtres de requรชte. + +/// + +/// info + +Gardez ร  l'esprit que, comme **les navigateurs gรจrent les cookies** de maniรจre particuliรจre et en coulisses, ils **n'autorisent pas** facilement **JavaScript** ร  y accรฉder. + +Si vous allez dans l'**interface de la documentation de l'API** ร  `/docs`, vous pourrez voir la **documentation** des cookies pour vos *chemins d'accรจs*. + +Mais mรชme si vous **renseignez les donnรฉes** et cliquez sur ยซ Execute ยป, comme l'interface de documentation fonctionne avec **JavaScript**, les cookies ne seront pas envoyรฉs et vous verrez un message **d'erreur** comme si vous n'aviez saisi aucune valeur. + +/// + +## Rรฉcapitulatif { #recap } + +Dรฉclarez les cookies avec `Cookie`, en utilisant le mรชme schรฉma commun que `Query` et `Path`. diff --git a/docs/fr/docs/tutorial/cors.md b/docs/fr/docs/tutorial/cors.md new file mode 100644 index 0000000000..3ae7de07ca --- /dev/null +++ b/docs/fr/docs/tutorial/cors.md @@ -0,0 +1,88 @@ +# CORS (Partage des ressources entre origines) { #cors-cross-origin-resource-sharing } + +
CORS ou ยซ Cross-Origin Resource Sharing ยป fait rรฉfรฉrence aux situations oรน un frontend exรฉcutรฉ dans un navigateur contient du code JavaScript qui communique avec un backend, et oรน le backend se trouve dans une ยซ origine ยป diffรฉrente de celle du frontend. + +## Origine { #origin } + +Une origine est la combinaison du protocole (`http`, `https`), du domaine (`myapp.com`, `localhost`, `localhost.tiangolo.com`) et du port (`80`, `443`, `8080`). + +Ainsi, toutes celles-ci sont des origines diffรฉrentes : + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Mรชme si elles sont toutes sur `localhost`, elles utilisent des protocoles ou des ports diffรฉrents, ce sont donc des ยซ origines ยป diffรฉrentes. + +## ร‰tapes { #steps } + +Disons donc que vous avez un frontend exรฉcutรฉ dans votre navigateur ร  `http://localhost:8080`, et que son JavaScript essaie de communiquer avec un backend exรฉcutรฉ ร  `http://localhost` (comme nous ne spรฉcifions pas de port, le navigateur supposera le port par dรฉfaut `80`). + +Le navigateur enverra alors une requรชte HTTP `OPTIONS` au backend `:80`, et si le backend envoie les en-tรชtes appropriรฉs autorisant la communication depuis cette origine diffรฉrente (`http://localhost:8080`), alors le navigateur `:8080` permettra au JavaScript du frontend dโ€™envoyer sa requรชte au backend `:80`. + +Pour y parvenir, le backend `:80` doit disposer dโ€™une liste ยซ dโ€™origines autorisรฉes ยป. + +Dans ce cas, la liste devrait inclure `http://localhost:8080` pour que le frontend `:8080` fonctionne correctement. + +## Caractรจres gรฉnรฉriques { #wildcards } + +Il est รฉgalement possible de dรฉclarer la liste comme ยซ * ยป (un ยซ wildcard ยป) pour indiquer que toutes sont autorisรฉes. + +Mais cela nโ€™autorisera que certains types de communication, en excluant tout ce qui implique des informations dโ€™identification : cookies, en-tรชtes Authorization comme ceux utilisรฉs avec les Bearer Tokens, etc. + +Ainsi, pour que tout fonctionne correctement, il est prรฉfรฉrable dโ€™indiquer explicitement les origines autorisรฉes. + +## Utiliser `CORSMiddleware` { #use-corsmiddleware } + +Vous pouvez le configurer dans votre application **FastAPI** ร  lโ€™aide de `CORSMiddleware`. + +* Importer `CORSMiddleware`. +* Crรฉer une liste dโ€™origines autorisรฉes (sous forme de chaรฎnes). +* Lโ€™ajouter comme ยซ middleware ยป ร  votre application **FastAPI**. + +Vous pouvez รฉgalement spรฉcifier si votre backend autorise : + +* Les informations dโ€™identification (en-tรชtes Authorization, cookies, etc.). +* Des mรฉthodes HTTP spรฉcifiques (`POST`, `PUT`) ou toutes avec le caractรจre gรฉnรฉrique ยซ * ยป. +* Des en-tรชtes HTTP spรฉcifiques ou tous avec le caractรจre gรฉnรฉrique ยซ * ยป. + +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + +Les paramรจtres utilisรฉs par dรฉfaut par lโ€™implรฉmentation de `CORSMiddleware` sont restrictifs, vous devez donc activer explicitement des origines, mรฉthodes ou en-tรชtes particuliers afin que les navigateurs soient autorisรฉs ร  les utiliser dans un contexte interโ€‘domaine. + +Les arguments suivants sont pris en charge : + +* `allow_origins` - Une liste dโ€™origines autorisรฉes ร  effectuer des requรชtes cross-origin. Par ex. `['https://example.org', 'https://www.example.org']`. Vous pouvez utiliser `['*']` pour autoriser nโ€™importe quelle origine. +* `allow_origin_regex` - Une chaรฎne regex pour faire correspondre les origines autorisรฉes ร  effectuer des requรชtes cross-origin. Par ex. `'https://.*\.example\.org'`. +* `allow_methods` - Une liste de mรฉthodes HTTP qui doivent รชtre autorisรฉes pour les requรชtes cross-origin. Par dรฉfaut `['GET']`. Vous pouvez utiliser `['*']` pour autoriser toutes les mรฉthodes standard. +* `allow_headers` - Une liste dโ€™en-tรชtes HTTP de requรชte qui doivent รชtre pris en charge pour les requรชtes cross-origin. Par dรฉfaut `[]`. Vous pouvez utiliser `['*']` pour autoriser tous les en-tรชtes. Les en-tรชtes `Accept`, `Accept-Language`, `Content-Language` et `Content-Type` sont toujours autorisรฉs pour les requรชtes CORS simples. +* `allow_credentials` - Indique que les cookies doivent รชtre pris en charge pour les requรชtes cross-origin. Par dรฉfaut `False`. + + Aucun de `allow_origins`, `allow_methods` et `allow_headers` ne peut รชtre dรฉfini ร  `['*']` si `allow_credentials` est dรฉfini ร  `True`. Ils doivent tous รชtre spรฉcifiรฉs explicitement. + +* `expose_headers` - Indique les en-tรชtes de rรฉponse qui doivent รชtre accessibles au navigateur. Par dรฉfaut `[]`. +* `max_age` - Dรฉfinit un temps maximum (en secondes) pendant lequel les navigateurs peuvent mettre en cache les rรฉponses CORS. Par dรฉfaut `600`. + +Le middleware rรฉpond ร  deux types particuliers de requรชtes HTTP ... + +### Requรชtes CORS de prรฉโ€‘vรฉrification { #cors-preflight-requests } + +Il sโ€™agit de toute requรชte `OPTIONS` avec les en-tรชtes `Origin` et `Access-Control-Request-Method`. + +Dans ce cas, le middleware interceptera la requรชte entrante et rรฉpondra avec les en-tรชtes CORS appropriรฉs, et soit une rรฉponse `200`, soit `400` ร  titre informatif. + +### Requรชtes simples { #simple-requests } + +Toute requรชte avec un en-tรชte `Origin`. Dans ce cas, le middleware laissera passer la requรชte normalement, mais inclura les en-tรชtes CORS appropriรฉs dans la rรฉponse. + +## En savoir plus { #more-info } + +Pour plus dโ€™informations sur CORS, consultez la documentation CORS de Mozilla. + +/// note | Dรฉtails techniques + +Vous pouvez รฉgalement utiliser `from starlette.middleware.cors import CORSMiddleware`. + +**FastAPI** fournit plusieurs middlewares dans `fastapi.middleware` uniquement pour votre confort, en tant que dรฉveloppeur. Mais la plupart des middlewares disponibles proviennent directement de Starlette. + +/// diff --git a/docs/fr/docs/tutorial/debugging.md b/docs/fr/docs/tutorial/debugging.md index a88fa2b23f..d69e6a3bae 100644 --- a/docs/fr/docs/tutorial/debugging.md +++ b/docs/fr/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ Vous pouvez connecter le dรฉbogueur da Dans votre application FastAPI, importez et exรฉcutez directement `uvicorn` : -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### ร€ propos de `__name__ == "__main__"` { #about-name-main } @@ -87,7 +87,7 @@ Parce que vous exรฉcutez le serveur Uvicorn directement depuis votre code, vous Par exemple, dans Visual Studio Code, vous pouvez : - Allez dans le panneau ยซ Debug ยป. -- ยซ Add configuration... ยป. +- ยซ Add configuration ... ยป. - Sรฉlectionnez ยซ Python ยป. - Lancez le dรฉbogueur avec l'option ยซ Python: Current File (Integrated Terminal) ยป. @@ -102,7 +102,7 @@ Voici ร  quoi cela pourrait ressembler : Si vous utilisez Pycharm, vous pouvez : - Ouvrez le menu ยซ Run ยป. -- Sรฉlectionnez l'option ยซ Debug... ยป. +- Sรฉlectionnez l'option ยซ Debug ... ยป. - Un menu contextuel s'affiche alors. - Sรฉlectionnez le fichier ร  dรฉboguer (dans ce cas, `main.py`). diff --git a/docs/fr/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/fr/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 0000000000..69bc6008ad --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# Utiliser des classes comme dรฉpendances { #classes-as-dependencies } + +Avant d'aller plus loin dans le systรจme d'**Injection de dรฉpendances**, mettons ร  niveau l'exemple prรฉcรฉdent. + +## Un `dict` de l'exemple prรฉcรฉdent { #a-dict-from-the-previous-example } + +Dans l'exemple prรฉcรฉdent, nous renvoyions un `dict` depuis notre dรฉpendance (ยซ dependable ยป)ย : + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +Mais nous recevons alors un `dict` dans le paramรจtre `commons` de la fonction de chemin d'accรจs. + +Et les รฉditeurs ne peuvent pas apporter beaucoup d'assistance (comme l'autocomplรฉtion) pour les `dict`, car ils ne peuvent pas connaรฎtre leurs clรฉs ni les types de valeurs. + +Nous pouvons faire mieux ... + +## Ce qui fait d'un objet une dรฉpendance { #what-makes-a-dependency } + +Jusqu'ร  prรฉsent, vous avez vu des dรฉpendances dรฉclarรฉes sous forme de fonctions. + +Mais ce n'est pas la seule maniรจre de dรฉclarer des dรฉpendances (mรชme si c'est probablement la plus courante). + +L'รฉlรฉment clรฉ est qu'une dรฉpendance doit รชtre un ยซ callable ยป. + +Un ยซ callable ยป en Python est tout ce que Python peut ยซ appeler ยป comme une fonction. + +Ainsi, si vous avez un objet `something` (qui n'est peutโ€‘รชtre pas une fonction) et que vous pouvez ยซ l'appeler ยป (l'exรฉcuter) commeย : + +```Python +something() +``` + +ou + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +alors c'est un ยซ callable ยป. + +## Utiliser des classes comme dรฉpendances { #classes-as-dependencies_1 } + +Vous remarquerez que pour crรฉer une instance d'une classe Python, vous utilisez la mรชme syntaxe. + +Par exempleย : + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +Dans ce cas, `fluffy` est une instance de la classe `Cat`. + +Et pour crรฉer `fluffy`, vous ยซ appelez ยป `Cat`. + +Donc, une classe Python est aussi un ยซ callable ยป. + +Ainsi, avec **FastAPI**, vous pouvez utiliser une classe Python comme dรฉpendance. + +Ce que **FastAPI** vรฉrifie rรฉellement, c'est qu'il s'agit d'un ยซ callable ยป (fonction, classe ou autre) et des paramรจtres qui y sont dรฉfinis. + +Si vous passez un ยซ callable ยป comme dรฉpendance dans **FastAPI**, il en analysera les paramรจtres et les traitera de la mรชme maniรจre que les paramรจtres d'une fonction de chemin d'accรจs. Y compris les sousโ€‘dรฉpendances. + +Cela s'applique รฉgalement aux callables sans aucun paramรจtre. Comme ce serait le cas pour des fonctions de chemin d'accรจs sans paramรจtres. + +Nous pouvons alors remplacer la dรฉpendance ยซ dependable ยป `common_parameters` ciโ€‘dessus par la classe `CommonQueryParams`ย : + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +Faites attention ร  la mรฉthode `__init__` utilisรฉe pour crรฉer l'instance de la classeย : + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +... il a les mรชmes paramรจtres que notre prรฉcรฉdent `common_parameters`ย : + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +Ce sont ces paramรจtres que **FastAPI** utilisera pour ยซ rรฉsoudre ยป la dรฉpendance. + +Dans les deux cas, il y auraย : + +- Un paramรจtre de requรชte optionnel `q` qui est un `str`. +- Un paramรจtre de requรชte `skip` qui est un `int`, avec une valeur par dรฉfaut de `0`. +- Un paramรจtre de requรชte `limit` qui est un `int`, avec une valeur par dรฉfaut de `100`. + +Dans les deux cas, les donnรฉes seront converties, validรฉes, documentรฉes dans le schรฉma OpenAPI, etc. + +## Utiliser { #use-it } + +Vous pouvez maintenant dรฉclarer votre dรฉpendance en utilisant cette classe. + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI** appelle la classe `CommonQueryParams`. Cela crรฉe une ยซ instance ยป de cette classe et l'instance sera passรฉe comme paramรจtre `commons` ร  votre fonction. + +## Annotation de type vs `Depends` { #type-annotation-vs-depends } + +Remarquez que nous รฉcrivons `CommonQueryParams` deux fois dans le code ciโ€‘dessusย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +Le dernier `CommonQueryParams`, dansย : + +```Python +... Depends(CommonQueryParams) +``` + +... est ce que **FastAPI** utilisera rรฉellement pour savoir quelle est la dรฉpendance. + +C'est ร  partir de celuiโ€‘ci que FastAPI extraira les paramรจtres dรฉclarรฉs et c'est ce que FastAPI appellera effectivement. + +--- + +Dans ce cas, le premier `CommonQueryParams`, dansย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +... n'a aucune signification particuliรจre pour **FastAPI**. FastAPI ne l'utilisera pas pour la conversion des donnรฉes, la validation, etc. (car il utilise `Depends(CommonQueryParams)` pour cela). + +Vous pourriez en fait รฉcrire simplementย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +... comme dansย : + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +Mais il est recommandรฉ de dรฉclarer le typeย ; ainsi, votre รฉditeur saura ce qui sera passรฉ comme paramรจtre `commons`, et pourra vous aider avec l'autocomplรฉtion, les vรฉrifications de type, etc.ย : + + + +## Raccourci { #shortcut } + +Mais vous voyez qu'il y a ici de la duplication de codeย : nous รฉcrivons `CommonQueryParams` deux foisย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI** fournit un raccourci pour ces cas, lorsque la dรฉpendance est spรฉcifiquement une classe que **FastAPI** va ยซ appeler ยป pour crรฉer une instance de la classe elleโ€‘mรชme. + +Pour ces cas prรฉcis, vous pouvez faire ce qui suitย : + +Au lieu d'รฉcrireย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +... vous รฉcrivezย : + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.10+ sans Annotated + +/// tip | Astuce + +Privilรฉgiez la version avec `Annotated` si possible. + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +Vous dรฉclarez la dรฉpendance comme type du paramรจtre et vous utilisez `Depends()` sans aucun paramรจtre, au lieu d'avoir ร  rรฉรฉcrire la classe entiรจre ร  l'intรฉrieur de `Depends(CommonQueryParams)`. + +Le mรชme exemple ressemblerait alors ร  ceciย : + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +... et **FastAPI** saura quoi faire. + +/// tip | Astuce + +Si cela vous semble plus dรฉroutant qu'utile, ignorezโ€‘le, vous n'en avez pas besoin. + +Ce n'est qu'un raccourci. Parce que **FastAPI** tient ร  vous aider ร  minimiser la duplication de code. + +/// diff --git a/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 0000000000..bf697fe8de --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# Gรฉrer les dรฉpendances dans les dรฉcorateurs de chemins d'accรจs { #dependencies-in-path-operation-decorators } + +Dans certains cas, vous n'avez pas vraiment besoin de la valeur de retour d'une dรฉpendance dans votre *fonction de chemin d'accรจs*. + +Ou la dรฉpendance ne retourne aucune valeur. + +Mais vous avez quand mรชme besoin qu'elle soit exรฉcutรฉe/rรฉsolue. + +Dans ces cas, au lieu de dรฉclarer un paramรจtre de *fonction de chemin d'accรจs* avec `Depends`, vous pouvez ajouter une `list` de `dependencies` au *dรฉcorateur de chemin d'accรจs*. + +## Ajouter `dependencies` au *dรฉcorateur de chemin d'accรจs* { #add-dependencies-to-the-path-operation-decorator } + +Le *dรฉcorateur de chemin d'accรจs* accepte un argument optionnel `dependencies`. + +Il doit s'agir d'une `list` de `Depends()` : + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} + +Ces dรฉpendances seront exรฉcutรฉes/rรฉsolues de la mรชme maniรจre que des dรฉpendances normales. Mais leur valeur (si elles en retournent une) ne sera pas transmise ร  votre *fonction de chemin d'accรจs*. + +/// tip | Astuce + +Certains รฉditeurs vรฉrifient les paramรจtres de fonction non utilisรฉs et les signalent comme des erreurs. + +En utilisant ces `dependencies` dans le *dรฉcorateur de chemin d'accรจs*, vous pouvez vous assurer qu'elles sont exรฉcutรฉes tout en รฉvitant des erreurs de l'รฉditeur/des outils. + +Cela peut รฉgalement รฉviter toute confusion pour les nouveaux dรฉveloppeurs qui voient un paramรจtre inutilisรฉ dans votre code et pourraient penser qu'il est superflu. + +/// + +/// info | Info + +Dans cet exemple, nous utilisons des en-tรชtes personnalisรฉs fictifs `X-Key` et `X-Token`. + +Mais dans des cas rรฉels, lors de l'implรฉmentation de la sรฉcuritรฉ, vous tirerez davantage d'avantages en utilisant les [utilitaires de sรฉcuritรฉ (chapitre suivant)](../security/index.md){.internal-link target=_blank} intรฉgrรฉs. + +/// + +## Gรฉrer les erreurs et les valeurs de retour des dรฉpendances { #dependencies-errors-and-return-values } + +Vous pouvez utiliser les mรชmes *fonctions* de dรฉpendance que d'habitude. + +### Dรฉfinir les exigences des dรฉpendances { #dependency-requirements } + +Elles peuvent dรฉclarer des exigences pour la requรชte (comme des en-tรชtes) ou d'autres sous-dรฉpendances : + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} + +### Lever des exceptions { #raise-exceptions } + +Ces dรฉpendances peuvent `raise` des exceptions, comme des dรฉpendances normales : + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} + +### Gรฉrer les valeurs de retour { #return-values } + +Elles peuvent retourner des valeurs ou non, ces valeurs ne seront pas utilisรฉes. + +Vous pouvez donc rรฉutiliser une dรฉpendance normale (qui retourne une valeur) que vous utilisez dรฉjร  ailleurs ; mรชme si la valeur n'est pas utilisรฉe, la dรฉpendance sera exรฉcutรฉe : + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} + +## Dรฉfinir des dรฉpendances pour un groupe de chemins d'accรจs { #dependencies-for-a-group-of-path-operations } + +Plus tard, en lisant comment structurer des applications plus grandes ([Applications plus grandes - Plusieurs fichiers](../../tutorial/bigger-applications.md){.internal-link target=_blank}), รฉventuellement avec plusieurs fichiers, vous apprendrez ร  dรฉclarer un unique paramรจtre `dependencies` pour un groupe de *chemins d'accรจs*. + +## Dรฉfinir des dรฉpendances globales { #global-dependencies } + +Ensuite, nous verrons comment ajouter des dรฉpendances ร  l'application `FastAPI` entiรจre, afin qu'elles s'appliquent ร  chaque *chemin d'accรจs*. diff --git a/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 0000000000..3f06df7674 --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,289 @@ +# Utiliser des dรฉpendances avec `yield` { #dependencies-with-yield } + +FastAPI prend en charge des dรฉpendances qui effectuent des รฉtapes supplรฉmentaires aprรจs l'exรฉcution. + +Pour cela, utilisez `yield` au lieu de `return`, et รฉcrivez les รฉtapes supplรฉmentaires (code) aprรจs. + +/// tip | Astuce + +Vous devez vous assurer d'utiliser `yield` une seule fois par dรฉpendance. + +/// + +/// note | Dรฉtails techniques + +Toute fonction valide ร  utiliser avec : + +* `@contextlib.contextmanager` ou +* `@contextlib.asynccontextmanager` + +sera valide comme dรฉpendance **FastAPI**. + +En fait, FastAPI utilise ces deux dรฉcorateurs en interne. + +/// + +## Crรฉer une dรฉpendance de base de donnรฉes avec `yield` { #a-database-dependency-with-yield } + +Par exemple, vous pouvez l'utiliser pour crรฉer une session de base de donnรฉes et la fermer aprรจs la fin. + +Seul le code prรฉcรฉdant et incluant l'instruction `yield` est exรฉcutรฉ avant la crรฉation de la rรฉponse : + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} + +La valeur transmise par `yield` est celle qui est injectรฉe dans les *chemins d'accรจs* et autres dรฉpendances : + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} + +Le code suivant l'instruction `yield` est exรฉcutรฉ aprรจs la rรฉponse : + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} + +/// tip | Astuce + +Vous pouvez utiliser des fonctions `async` ou des fonctions classiques. + +**FastAPI** fera ce qu'il faut dans chaque cas, comme avec des dรฉpendances normales. + +/// + +## Crรฉer une dรฉpendance avec `yield` et `try` { #a-dependency-with-yield-and-try } + +Si vous utilisez un bloc `try` dans une dรฉpendance avec `yield`, vous recevrez toute exception qui a รฉtรฉ levรฉe lors de l'utilisation de la dรฉpendance. + +Par exemple, si ร  un moment donnรฉ, dans une autre dรฉpendance ou dans un *chemin d'accรจs*, un code a effectuรฉ un ยซ rollback ยป de transaction de base de donnรฉes ou a crรฉรฉ une autre exception, vous recevrez l'exception dans votre dรฉpendance. + +Vous pouvez donc rechercher cette exception spรฉcifique dans la dรฉpendance avec `except SomeException`. + +De la mรชme maniรจre, vous pouvez utiliser `finally` pour vous assurer que les รฉtapes de sortie sont exรฉcutรฉes, qu'il y ait eu une exception ou non. + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} + +## Utiliser des sous-dรฉpendances avec `yield` { #sub-dependencies-with-yield } + +Vous pouvez avoir des sous-dรฉpendances et des ยซ arbres ยป de sous-dรฉpendances de toute taille et forme, et certaines ou toutes peuvent utiliser `yield`. + +**FastAPI** s'assurera que le ยซ code de sortie ยป dans chaque dรฉpendance avec `yield` est exรฉcutรฉ dans le bon ordre. + +Par exemple, `dependency_c` peut dรฉpendre de `dependency_b`, et `dependency_b` de `dependency_a` : + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} + +Et elles peuvent toutes utiliser `yield`. + +Dans ce cas, `dependency_c`, pour exรฉcuter son code de sortie, a besoin que la valeur de `dependency_b` (appelรฉe ici `dep_b`) soit toujours disponible. + +Et, ร  son tour, `dependency_b` a besoin que la valeur de `dependency_a` (appelรฉe ici `dep_a`) soit disponible pour son code de sortie. + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} + +De la mรชme maniรจre, vous pouvez avoir certaines dรฉpendances avec `yield` et d'autres avec `return`, et faire en sorte que certaines dรฉpendent des autres. + +Et vous pouvez avoir une seule dรฉpendance qui exige plusieurs autres dรฉpendances avec `yield`, etc. + +Vous pouvez combiner les dรฉpendances comme vous le souhaitez. + +**FastAPI** s'assurera que tout est exรฉcutรฉ dans le bon ordre. + +/// note | Dรฉtails techniques + +Cela fonctionne grรขce aux gestionnaires de contexte de Python. + +**FastAPI** les utilise en interne pour y parvenir. + +/// + +## Utiliser des dรฉpendances avec `yield` et `HTTPException` { #dependencies-with-yield-and-httpexception } + +Vous avez vu que vous pouvez utiliser des dรฉpendances avec `yield` et avoir des blocs `try` qui tentent d'exรฉcuter du code puis exรฉcutent du code de sortie aprรจs `finally`. + +Vous pouvez รฉgalement utiliser `except` pour intercepter l'exception qui a รฉtรฉ levรฉe et faire quelque chose avec. + +Par exemple, vous pouvez lever une autre exception, comme `HTTPException`. + +/// tip | Astuce + +C'est une technique plutรดt avancรฉe, et dans la plupart des cas vous n'en aurez pas vraiment besoin, car vous pouvez lever des exceptions (y compris `HTTPException`) depuis le reste de votre code applicatif, par exemple, dans la *fonction de chemin d'accรจs*. + +Mais elle est ร  votre disposition si vous en avez besoin. ๐Ÿค“ + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} + +Si vous souhaitez intercepter des exceptions et crรฉer une rรฉponse personnalisรฉe en fonction de cela, crรฉez un [Gestionnaire d'exceptions personnalisรฉ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. + +## Utiliser des dรฉpendances avec `yield` et `except` { #dependencies-with-yield-and-except } + +Si vous interceptez une exception avec `except` dans une dรฉpendance avec `yield` et que vous ne la relancez pas (ou que vous ne levez pas une nouvelle exception), FastAPI ne pourra pas remarquer qu'il y a eu une exception, de la mรชme maniรจre que cela se produirait avec Python classique : + +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} + +Dans ce cas, le client verra une rรฉponse *HTTP 500 Internal Server Error* comme il se doit, รฉtant donnรฉ que nous ne levons pas de `HTTPException` ou similaire, mais le serveur **n'aura aucun logs** ni aucune autre indication de l'erreur. ๐Ÿ˜ฑ + +### Toujours `raise` dans les dรฉpendances avec `yield` et `except` { #always-raise-in-dependencies-with-yield-and-except } + +Si vous interceptez une exception dans une dรฉpendance avec `yield`, ร  moins de lever une autre `HTTPException` ou similaire, **vous devez relancer l'exception d'origine**. + +Vous pouvez relancer la mรชme exception avec `raise` : + +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} + +ร€ prรฉsent, le client recevra la mรชme rรฉponse *HTTP 500 Internal Server Error*, mais le serveur aura notre `InternalError` personnalisรฉ dans les logs. ๐Ÿ˜Ž + +## Comprendre l'exรฉcution des dรฉpendances avec `yield` { #execution-of-dependencies-with-yield } + +La sรฉquence d'exรฉcution ressemble plus ou moins ร  ce diagramme. Le temps s'รฉcoule de haut en bas. Et chaque colonne reprรฉsente une des parties qui interagit ou exรฉcute du code. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// info + +Une **seule rรฉponse** sera envoyรฉe au client. Il peut s'agir d'une des rรฉponses d'erreur ou de la rรฉponse provenant du *chemin d'accรจs*. + +Aprรจs l'envoi de l'une de ces rรฉponses, aucune autre rรฉponse ne peut รชtre envoyรฉe. + +/// + +/// tip | Astuce + +Si vous levez une exception dans le code de la *fonction de chemin d'accรจs*, elle sera transmise aux dรฉpendances avec `yield`, y compris `HTTPException`. Dans la plupart des cas, vous voudrez relancer cette mรชme exception ou en lever une nouvelle depuis la dรฉpendance avec `yield` pour vous assurer qu'elle est correctement gรฉrรฉe. + +/// + +## Utiliser la sortie anticipรฉe et `scope` { #early-exit-and-scope } + +Normalement, le code de sortie des dรฉpendances avec `yield` est exรฉcutรฉ **aprรจs la rรฉponse** envoyรฉe au client. + +Mais si vous savez que vous n'aurez pas besoin d'utiliser la dรฉpendance aprรจs รชtre revenu de la *fonction de chemin d'accรจs*, vous pouvez utiliser `Depends(scope="function")` pour indiquer ร  FastAPI qu'il doit fermer la dรฉpendance aprรจs le retour de la *fonction de chemin d'accรจs*, mais **avant** que la **rรฉponse ne soit envoyรฉe**. + +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} + +`Depends()` reรงoit un paramรจtre `scope` qui peut รชtre : + +* ยซ function ยป : dรฉmarrer la dรฉpendance avant la *fonction de chemin d'accรจs* qui gรจre la requรชte, terminer la dรฉpendance aprรจs la fin de la *fonction de chemin d'accรจs*, mais **avant** que la rรฉponse ne soit renvoyรฉe au client. Ainsi, la fonction de dรฉpendance sera exรฉcutรฉe **autour** de la *fonction de chemin d'accรจs*. +* ยซ request ยป : dรฉmarrer la dรฉpendance avant la *fonction de chemin d'accรจs* qui gรจre la requรชte (similaire ร  l'utilisation de ยซ function ยป), mais terminer **aprรจs** que la rรฉponse a รฉtรฉ renvoyรฉe au client. Ainsi, la fonction de dรฉpendance sera exรฉcutรฉe **autour** du cycle **requรชte** et rรฉponse. + +S'il n'est pas spรฉcifiรฉ et que la dรฉpendance utilise `yield`, le `scope` sera par dรฉfaut ยซ request ยป. + +### Dรฉfinir `scope` pour les sous-dรฉpendances { #scope-for-sub-dependencies } + +Lorsque vous dรฉclarez une dรฉpendance avec un `scope="request"` (par dรฉfaut), toute sous-dรฉpendance doit รฉgalement avoir un `scope` de ยซ request ยป. + +Mais une dรฉpendance avec un `scope` de ยซ function ยป peut avoir des dรฉpendances avec un `scope` de ยซ function ยป et un `scope` de ยซ request ยป. + +Cela vient du fait que toute dรฉpendance doit pouvoir exรฉcuter son code de sortie avant ses sous-dรฉpendances, car elle pourrait encore avoir besoin de les utiliser pendant son code de sortie. + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` + +## Utiliser des dรฉpendances avec `yield`, `HTTPException`, `except` et Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } + +Les dรฉpendances avec `yield` ont รฉvoluรฉ au fil du temps pour couvrir diffรฉrents cas d'utilisation et corriger certains problรจmes. + +Si vous souhaitez voir ce qui a changรฉ dans diffรฉrentes versions de FastAPI, vous pouvez en savoir plus dans le guide avancรฉ, dans [Dรฉpendances avancรฉes - Dรฉpendances avec `yield`, `HTTPException`, `except` et Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}. +## Gestionnaires de contexte { #context-managers } + +### Que sont les ยซ Context Managers ยป { #what-are-context-managers } + +Les ยซ Context Managers ยป sont des objets Python que vous pouvez utiliser dans une instruction `with`. + +Par exemple, vous pouvez utiliser `with` pour lire un fichier : + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +En coulisse, `open("./somefile.txt")` crรฉe un objet appelรฉ ยซ Context Manager ยป. + +Lorsque le bloc `with` se termine, il s'assure de fermer le fichier, mรชme s'il y a eu des exceptions. + +Lorsque vous crรฉez une dรฉpendance avec `yield`, **FastAPI** crรฉera en interne un gestionnaire de contexte pour celle-ci et le combinera avec d'autres outils associรฉs. + +### Utiliser des gestionnaires de contexte dans des dรฉpendances avec `yield` { #using-context-managers-in-dependencies-with-yield } + +/// warning | Alertes + +C'est, plus ou moins, une idรฉe ยซ avancรฉe ยป. + +Si vous dรฉbutez avec **FastAPI**, vous voudrez peut-รชtre l'ignorer pour le moment. + +/// + +En Python, vous pouvez crรฉer des gestionnaires de contexte en crรฉant une classe avec deux mรฉthodes : `__enter__()` et `__exit__()`. + +Vous pouvez รฉgalement les utiliser dans des dรฉpendances **FastAPI** avec `yield` en utilisant +des instructions `with` ou `async with` ร  l'intรฉrieur de la fonction de dรฉpendance : + +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} + +/// tip | Astuce + +Une autre faรงon de crรฉer un gestionnaire de contexte consiste ร  utiliser : + +* `@contextlib.contextmanager` ou +* `@contextlib.asynccontextmanager` + +pour dรฉcorer une fonction avec un unique `yield`. + +C'est ce que **FastAPI** utilise en interne pour les dรฉpendances avec `yield`. + +Mais vous n'avez pas ร  utiliser ces dรฉcorateurs pour les dรฉpendances FastAPI (et vous ne devriez pas). + +FastAPI le fera pour vous en interne. + +/// diff --git a/docs/fr/docs/tutorial/dependencies/global-dependencies.md b/docs/fr/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 0000000000..2c418ee4a1 --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,15 @@ +# Dรฉpendances globales { #global-dependencies } + +Pour certains types d'applications, vous pourriez vouloir ajouter des dรฉpendances ร  l'application entiรจre. + +Comme vous pouvez [ajouter des `dependencies` aux *dรฉcorateurs de chemin d'accรจs*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, vous pouvez les ajouter ร  l'application `FastAPI`. + +Dans ce cas, elles seront appliquรฉes ร  tous les *chemins d'accรจs* de l'application : + +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} + +Et toutes les idรฉes de la section sur [l'ajout de `dependencies` aux *dรฉcorateurs de chemin d'accรจs*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} s'appliquent toujours, mais dans ce cas ร  tous les *chemins d'accรจs* de l'application. + +## Dรฉpendances pour des groupes de *chemins d'accรจs* { #dependencies-for-groups-of-path-operations } + +Plus tard, en lisant comment structurer des applications plus grandes ([Applications plus grandes - Plusieurs fichiers](../../tutorial/bigger-applications.md){.internal-link target=_blank}), รฉventuellement avec plusieurs fichiers, vous apprendrez comment dรฉclarer un unique paramรจtre `dependencies` pour un groupe de *chemins d'accรจs*. diff --git a/docs/fr/docs/tutorial/dependencies/index.md b/docs/fr/docs/tutorial/dependencies/index.md new file mode 100644 index 0000000000..8fad77f62a --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/index.md @@ -0,0 +1,250 @@ +# Dรฉpendances { #dependencies } + +**FastAPI** dispose dโ€™un systรจme dโ€™**Injection de dรฉpendances** trรจs puissant mais intuitif. + +Il est conรงu pour รชtre trรจs simple ร  utiliser, et pour faciliter lโ€™intรฉgration dโ€™autres composants ร  **FastAPI** pour nโ€™importe quel dรฉveloppeur. + +## Quโ€™est-ce que ยซ lโ€™injection de dรฉpendances ยป { #what-is-dependency-injection } + +Lโ€™**ยซ injection de dรฉpendances ยป** signifie, en programmation, quโ€™il existe un moyen pour votre code (dans ce cas, vos fonctions de chemins dโ€™accรจs) de dรฉclarer ce dont il a besoin pour fonctionner et utiliser : ยซ dรฉpendances ยป. + +Ensuite, ce systรจme (dans ce cas **FastAPI**) se charge de faire tout le nรฉcessaire pour fournir ร  votre code ces dรฉpendances requises (ยซ injecter ยป les dรฉpendances). + +Cโ€™est trรจs utile lorsque vous avez besoin de : + +* Avoir de la logique partagรฉe (la mรชme logique de code encore et encore). +* Partager des connexions ร  la base de donnรฉes. +* Imposer la sรฉcuritรฉ, lโ€™authentification, des exigences de rรดles, etc. +* Et bien dโ€™autres choses ... + +Tout cela, en minimisant la rรฉpรฉtition de code. + +## Premiers pas { #first-steps } + +Voyons un exemple trรจs simple. Il sera tellement simple quโ€™il nโ€™est pas trรจs utile, pour lโ€™instant. + +Mais de cette faรงon nous pouvons nous concentrer sur le fonctionnement du systรจme dโ€™**injection de dรฉpendances**. + +### Crรฉer une dรฉpendance, ou ยซ dependable ยป { #create-a-dependency-or-dependable } + +Concentrons-nous dโ€™abord sur la dรฉpendance. + +Cโ€™est simplement une fonction qui peut prendre tous les mรชmes paramรจtres quโ€™une fonction de chemin dโ€™accรจs peut prendre : + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +Cโ€™est tout. + +**2 lignes**. + +Et elle a la mรชme forme et structure que toutes vos fonctions de chemins dโ€™accรจs. + +Vous pouvez la considรฉrer comme une fonction de chemin dโ€™accรจs sans le ยซ dรฉcorateur ยป (sans le `@app.get("/some-path")`). + +Et elle peut retourner tout ce que vous voulez. + +Dans ce cas, cette dรฉpendance attend : + +* Un paramรจtre de requรชte optionnel `q` qui est une `str`. +* Un paramรจtre de requรชte optionnel `skip` qui est un `int`, et vaut `0` par dรฉfaut. +* Un paramรจtre de requรชte optionnel `limit` qui est un `int`, et vaut `100` par dรฉfaut. + +Puis elle retourne simplement un `dict` contenant ces valeurs. + +/// info | Info + +FastAPI a ajoutรฉ la prise en charge de `Annotated` (et a commencรฉ ร  le recommander) dans la version 0.95.0. + +Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant dโ€™utiliser `Annotated`. + +Vous devez vous assurer de [mettre ร  niveau la version de FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} vers au moins la 0.95.1 avant dโ€™utiliser `Annotated`. + +/// + +### Importer `Depends` { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### Dรฉclarer la dรฉpendance, dans le ยซ dependant ยป { #declare-the-dependency-in-the-dependant } + +De la mรชme maniรจre que vous utilisez `Body`, `Query`, etc. avec les paramรจtres de votre fonction de chemin dโ€™accรจs, utilisez `Depends` avec un nouveau paramรจtre : + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +Mรชme si vous utilisez `Depends` dans les paramรจtres de votre fonction de la mรชme faรงon que `Body`, `Query`, etc., `Depends` fonctionne un peu diffรฉremment. + +Vous ne donnez ร  `Depends` quโ€™un seul paramรจtre. + +Ce paramรจtre doit รชtre quelque chose comme une fonction. + +Vous ne lโ€™appelez pas directement (nโ€™ajoutez pas de parenthรจses ร  la fin), vous le passez simplement en paramรจtre ร  `Depends()`. + +Et cette fonction prend des paramรจtres de la mรชme maniรจre que les fonctions de chemins dโ€™accรจs. + +/// tip | Astuce + +Vous verrez quelles autres ยซ choses ยป, en plus des fonctions, peuvent รชtre utilisรฉes comme dรฉpendances dans le prochain chapitre. + +/// + +Chaque fois quโ€™une nouvelle requรชte arrive, **FastAPI** se charge de : + +* Appeler votre fonction de dรฉpendance (ยซ dependable ยป) avec les bons paramรจtres. +* Rรฉcupรฉrer le rรฉsultat de votre fonction. +* Affecter ce rรฉsultat au paramรจtre dans votre fonction de chemin dโ€™accรจs. + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +De cette faรงon vous รฉcrivez le code partagรฉ une seule fois et **FastAPI** se charge de lโ€™appeler pour vos chemins dโ€™accรจs. + +/// check | Vรฉrifications + +Notez que vous nโ€™avez pas ร  crรฉer une classe spรฉciale et ร  la passer quelque part ร  **FastAPI** pour lโ€™ยซ enregistrer ยป ou quoi que ce soit de similaire. + +Vous la passez simplement ร  `Depends` et **FastAPI** sait faire le reste. + +/// + +## Partager des dรฉpendances `Annotated` { #share-annotated-dependencies } + +Dans les exemples ci-dessus, vous voyez quโ€™il y a un tout petit peu de **duplication de code**. + +Lorsque vous devez utiliser la dรฉpendance `common_parameters()`, vous devez รฉcrire tout le paramรจtre avec lโ€™annotation de type et `Depends()` : + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +Mais comme nous utilisons `Annotated`, nous pouvons stocker cette valeur `Annotated` dans une variable et lโ€™utiliser ร  plusieurs endroits : + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | Astuce + +Cโ€™est simplement du Python standard, cela sโ€™appelle un ยซ alias de type ยป, ce nโ€™est en fait pas spรฉcifique ร  **FastAPI**. + +Mais comme **FastAPI** est basรฉ sur les standards Python, y compris `Annotated`, vous pouvez utiliser cette astuce dans votre code. ๐Ÿ˜Ž + +/// + +Les dรฉpendances continueront de fonctionner comme prรฉvu, et la **meilleure partie** est que **lโ€™information de type sera conservรฉe**, ce qui signifie que votre รฉditeur pourra continuer ร  vous fournir **lโ€™autocomplรฉtion**, **des erreurs en ligne**, etc. Idem pour dโ€™autres outils comme `mypy`. + +Cela sera particuliรจrement utile lorsque vous lโ€™utiliserez dans une **grande base de code** oรน vous utilisez **les mรชmes dรฉpendances** encore et encore dans **de nombreux chemins dโ€™accรจs**. + +## Utiliser `async` ou non { #to-async-or-not-to-async } + +Comme les dรฉpendances seront aussi appelรฉes par **FastAPI** (tout comme vos fonctions de chemins dโ€™accรจs), les mรชmes rรจgles sโ€™appliquent lors de la dรฉfinition de vos fonctions. + +Vous pouvez utiliser `async def` ou un `def` normal. + +Et vous pouvez dรฉclarer des dรฉpendances avec `async def` ร  lโ€™intรฉrieur de fonctions de chemins dโ€™accรจs `def` normales, ou des dรฉpendances `def` ร  lโ€™intรฉrieur de fonctions de chemins dโ€™accรจs `async def`, etc. + +Peu importe. **FastAPI** saura quoi faire. + +/// note | Remarque + +Si vous ne savez pas, consultez la section [Async : *ยซ Pressรฉ ? ยป*](../../async.md#in-a-hurry){.internal-link target=_blank} ร  propos de `async` et `await` dans la documentation. + +/// + +## Intรฉgrer ร  OpenAPI { #integrated-with-openapi } + +Toutes les dรฉclarations de requรชte, validations et exigences de vos dรฉpendances (et sous-dรฉpendances) seront intรฉgrรฉes dans le mรชme schรฉma OpenAPI. + +Ainsi, la documentation interactive contiendra aussi toutes les informations issues de ces dรฉpendances : + + + +## Utilisation simple { #simple-usage } + +Si vous y regardez de prรจs, les fonctions de chemins dโ€™accรจs sont dรฉclarรฉes pour รชtre utilisรฉes chaque fois quโ€™un ยซ chemin ยป et une ยซ opรฉration ยป correspondent, puis **FastAPI** se charge dโ€™appeler la fonction avec les bons paramรจtres, en extrayant les donnรฉes de la requรชte. + +En rรฉalitรฉ, tous (ou la plupart) des frameworks web fonctionnent de cette maniรจre. + +Vous nโ€™appelez jamais ces fonctions directement. Elles sont appelรฉes par votre framework (dans ce cas, **FastAPI**). + +Avec le systรจme dโ€™injection de dรฉpendances, vous pouvez aussi indiquer ร  **FastAPI** que votre fonction de chemin dโ€™accรจs ยซ dรฉpend ยป รฉgalement dโ€™autre chose qui doit รชtre exรฉcutรฉ avant votre fonction de chemin dโ€™accรจs, et **FastAPI** se chargera de lโ€™exรฉcuter et dโ€™ยซ injecter ยป les rรฉsultats. + +Dโ€™autres termes courants pour cette mรชme idรฉe ยซ dโ€™injection de dรฉpendances ยป sont : + +* ressources +* fournisseurs +* services +* injectables +* composants + +## Plug-ins **FastAPI** { #fastapi-plug-ins } + +Les intรฉgrations et ยซ plug-ins ยป peuvent รชtre construits en utilisant le systรจme dโ€™**injection de dรฉpendances**. Mais en rรฉalitรฉ, il nโ€™y a **pas besoin de crรฉer des ยซ plug-ins ยป**, car en utilisant des dรฉpendances il est possible de dรฉclarer un nombre infini dโ€™intรฉgrations et dโ€™interactions qui deviennent disponibles pour vos fonctions de chemins dโ€™accรจs. + +Et les dรฉpendances peuvent รชtre crรฉรฉes de maniรจre trรจs simple et intuitive, ce qui vous permet dโ€™importer juste les packages Python dont vous avez besoin, et de les intรฉgrer ร  vos fonctions dโ€™API en quelques lignes de code, *littรฉralement*. + +Vous verrez des exemples de cela dans les prochains chapitres, ร  propos des bases de donnรฉes relationnelles et NoSQL, de la sรฉcuritรฉ, etc. + +## Compatibilitรฉ **FastAPI** { #fastapi-compatibility } + +La simplicitรฉ du systรจme dโ€™injection de dรฉpendances rend **FastAPI** compatible avec : + +* toutes les bases de donnรฉes relationnelles +* les bases de donnรฉes NoSQL +* les packages externes +* les API externes +* les systรจmes dโ€™authentification et dโ€™autorisation +* les systรจmes de supervision dโ€™usage dโ€™API +* les systรจmes dโ€™injection de donnรฉes de rรฉponse +* etc. + +## Simple et puissant { #simple-and-powerful } + +Bien que le systรจme hiรฉrarchique dโ€™injection de dรฉpendances soit trรจs simple ร  dรฉfinir et ร  utiliser, il reste trรจs puissant. + +Vous pouvez dรฉfinir des dรฉpendances qui, ร  leur tour, peuvent dรฉfinir leurs propres dรฉpendances. + +Au final, un arbre hiรฉrarchique de dรฉpendances est construit, et le systรจme dโ€™**injection de dรฉpendances** se charge de rรฉsoudre toutes ces dรฉpendances pour vous (et leurs sous-dรฉpendances) et de fournir (injecter) les rรฉsultats ร  chaque รฉtape. + +Par exemple, supposons que vous ayez 4 endpoints dโ€™API (chemins dโ€™accรจs) : + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +alors vous pourriez ajouter diffรฉrentes exigences dโ€™autorisations pour chacun dโ€™eux uniquement avec des dรฉpendances et des sous-dรฉpendances : + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## Intรฉgrer ร  **OpenAPI** { #integrated-with-openapi_1 } + +Toutes ces dรฉpendances, tout en dรฉclarant leurs exigences, ajoutent รฉgalement des paramรจtres, des validations, etc. ร  vos chemins dโ€™accรจs. + +**FastAPI** se chargera dโ€™ajouter le tout au schรฉma OpenAPI, afin que cela apparaisse dans les systรจmes de documentation interactive. diff --git a/docs/fr/docs/tutorial/dependencies/sub-dependencies.md b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000..473ff02ba8 --- /dev/null +++ b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# Sous-dรฉpendances { #sub-dependencies } + +Vous pouvez crรฉer des dรฉpendances qui ont des sous-dรฉpendances. + +Elles peuvent รชtre aussi profondes que nรฉcessaire. + +**FastAPI** se chargera de les rรฉsoudre. + +## Crรฉer une premiรจre dรฉpendance ยซ dependable ยป { #first-dependency-dependable } + +Vous pouvez crรฉer une premiรจre dรฉpendance (ยซ dependable ยป) comme : + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +Elle dรฉclare un paramรจtre de requรชte optionnel `q` de type `str`, puis le retourne simplement. + +C'est assez simple (pas trรจs utile), mais cela nous aidera ร  nous concentrer sur le fonctionnement des sous-dรฉpendances. + +## Crรฉer une seconde dรฉpendance, ยซ dependable ยป et ยซ dependant ยป { #second-dependency-dependable-and-dependant } + +Vous pouvez ensuite crรฉer une autre fonction de dรฉpendance (un ยซ dependable ยป) qui, en mรชme temps, dรฉclare sa propre dรฉpendance (elle est donc aussi un ยซ dependant ยป) : + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +Concentrons-nous sur les paramรจtres dรฉclarรฉs : + +- Mรชme si cette fonction est elleโ€‘mรชme une dรฉpendance (ยซ dependable ยป), elle dรฉclare aussi une autre dรฉpendance (elle ยซ dรฉpend ยป d'autre chose). + - Elle dรฉpend de `query_extractor` et affecte la valeur renvoyรฉe au paramรจtre `q`. +- Elle dรฉclare รฉgalement un cookie `last_query` optionnel, de type `str`. + - Si l'utilisateur n'a fourni aucune requรชte `q`, nous utilisons la derniรจre requรชte utilisรฉe, que nous avons enregistrรฉe auparavant dans un cookie. + +## Utiliser la dรฉpendance { #use-the-dependency } + +Nous pouvons ensuite utiliser la dรฉpendance avec : + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// info + +Notez que nous ne dรฉclarons qu'une seule dรฉpendance dans la *fonction de chemin d'accรจs*, `query_or_cookie_extractor`. + +Mais **FastAPI** saura qu'il doit d'abord rรฉsoudre `query_extractor`, pour passer ses rรฉsultats ร  `query_or_cookie_extractor` lors de son appel. + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## Utiliser la mรชme dรฉpendance plusieurs fois { #using-the-same-dependency-multiple-times } + +Si l'une de vos dรฉpendances est dรฉclarรฉe plusieurs fois pour le mรชme *chemin d'accรจs*, par exemple si plusieurs dรฉpendances ont une sous-dรฉpendance commune, **FastAPI** saura n'appeler cette sous-dรฉpendance qu'une seule fois par requรชte. + +Et il enregistrera la valeur renvoyรฉe dans un ยซ cache ยป et la transmettra ร  tous les ยซ dependants ยป qui en ont besoin dans cette requรชte spรฉcifique, au lieu d'appeler la dรฉpendance plusieurs fois pour la mรชme requรชte. + +Dans un scรฉnario avancรฉ oรน vous savez que vous avez besoin que la dรฉpendance soit appelรฉe ร  chaque รฉtape (รฉventuellement plusieurs fois) dans la mรชme requรชte au lieu d'utiliser la valeur ยซ mise en cache ยป, vous pouvez dรฉfinir le paramรจtre `use_cache=False` lors de l'utilisation de `Depends` : + +//// tab | Python 3.10+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.10+ non annotรฉ + +/// tip | Astuce + +Privilรฉgiez la version `Annotated` si possible. + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## Rรฉcapituler { #recap } + +En dehors de tout le jargon utilisรฉ ici, le systรจme d'**injection de dรฉpendances** est assez simple. + +Ce ne sont que des fonctions qui ressemblent aux *fonctions de chemin d'accรจs*. + +Mais il est trรจs puissant et vous permet de dรฉclarer des ยซ graphes ยป (arbres) de dรฉpendances imbriquรฉes aussi profondรฉment que vous le souhaitez. + +/// tip | Astuce + +Tout cela peut ne pas sembler trรจs utile avec ces exemples simples. + +Mais vous verrez ร  quel point c'est utile dans les chapitres sur la **sรฉcuritรฉ**. + +Et vous verrez aussi la quantitรฉ de code que cela vous fera รฉconomiser. + +/// diff --git a/docs/fr/docs/tutorial/encoder.md b/docs/fr/docs/tutorial/encoder.md new file mode 100644 index 0000000000..f94be429ca --- /dev/null +++ b/docs/fr/docs/tutorial/encoder.md @@ -0,0 +1,35 @@ +# Encodeur compatible JSON { #json-compatible-encoder } + +Il existe des cas oรน vous pourriez avoir besoin de convertir un type de donnรฉes (comme un modรจle Pydantic) en quelque chose de compatible avec JSON (comme un `dict`, `list`, etc.). + +Par exemple, si vous devez le stocker dans une base de donnรฉes. + +Pour cela, **FastAPI** fournit une fonction `jsonable_encoder()`. + +## Utiliser `jsonable_encoder` { #using-the-jsonable-encoder } + +Imaginons que vous ayez une base de donnรฉes `fake_db` qui ne reรงoit que des donnรฉes compatibles JSON. + +Par exemple, elle ne reรงoit pas d'objets `datetime`, car ceux-ci ne sont pas compatibles avec JSON. + +Ainsi, un objet `datetime` doit รชtre converti en une `str` contenant les donnรฉes au format ISO. + +De la mรชme maniรจre, cette base de donnรฉes n'accepterait pas un modรจle Pydantic (un objet avec des attributs), seulement un `dict`. + +Vous pouvez utiliser `jsonable_encoder` pour cela. + +Elle reรงoit un objet, comme un modรจle Pydantic, et renvoie une version compatible JSON : + +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} + +Dans cet exemple, elle convertirait le modรจle Pydantic en `dict`, et le `datetime` en `str`. + +Le rรฉsultat de son appel est quelque chose qui peut รชtre encodรฉ avec la fonction standard de Python `json.dumps()`. + +Elle ne renvoie pas une grande `str` contenant les donnรฉes au format JSON (sous forme de chaรฎne). Elle renvoie une structure de donnรฉes standard de Python (par ex. un `dict`) avec des valeurs et sous-valeurs toutes compatibles avec JSON. + +/// note | Remarque + +`jsonable_encoder` est en fait utilisรฉe par **FastAPI** en interne pour convertir des donnรฉes. Mais elle est utile dans de nombreux autres scรฉnarios. + +/// diff --git a/docs/fr/docs/tutorial/extra-data-types.md b/docs/fr/docs/tutorial/extra-data-types.md new file mode 100644 index 0000000000..edaa7bd4c3 --- /dev/null +++ b/docs/fr/docs/tutorial/extra-data-types.md @@ -0,0 +1,62 @@ +# Types de donnรฉes supplรฉmentaires { #extra-data-types } + +Jusqu'ร  prรฉsent, vous avez utilisรฉ des types de donnรฉes courants, comme : + +* `int` +* `float` +* `str` +* `bool` + +Mais vous pouvez aussi utiliser des types de donnรฉes plus complexes. + +Et vous bรฉnรฉficierez toujours des mรชmes fonctionnalitรฉs que jusqu'ร  prรฉsent : + +* Excellente prise en charge dans l'รฉditeur. +* Conversion des donnรฉes ร  partir des requรชtes entrantes. +* Conversion des donnรฉes pour les donnรฉes de rรฉponse. +* Validation des donnรฉes. +* Annotations et documentation automatiques. + +## Autres types de donnรฉes { #other-data-types } + +Voici quelques types de donnรฉes supplรฉmentaires que vous pouvez utiliser : + +* `UUID` : + * Un ยซ identifiant universel unique ยป standard, couramment utilisรฉ comme ID dans de nombreuses bases de donnรฉes et systรจmes. + * Dans les requรชtes et les rรฉponses, il sera reprรฉsentรฉ sous forme de `str`. +* `datetime.datetime` : + * Un `datetime.datetime` Python. + * Dans les requรชtes et les rรฉponses, il sera reprรฉsentรฉ sous forme de `str` au format ISO 8601, par exemple : `2008-09-15T15:53:00+05:00`. +* `datetime.date` : + * `datetime.date` Python. + * Dans les requรชtes et les rรฉponses, il sera reprรฉsentรฉ sous forme de `str` au format ISO 8601, par exemple : `2008-09-15`. +* `datetime.time` : + * Un `datetime.time` Python. + * Dans les requรชtes et les rรฉponses, il sera reprรฉsentรฉ sous forme de `str` au format ISO 8601, par exemple : `14:23:55.003`. +* `datetime.timedelta` : + * Un `datetime.timedelta` Python. + * Dans les requรชtes et les rรฉponses, il sera reprรฉsentรฉ sous forme de `float` de secondes totales. + * Pydantic permet aussi de le reprรฉsenter sous la forme d'un ยซ encodage de diffรฉrence de temps ISO 8601 ยป, voir la documentation pour plus d'informations. +* `frozenset` : + * Dans les requรชtes et les rรฉponses, traitรฉ de la mรชme maniรจre qu'un `set` : + * Dans les requรชtes, une liste sera lue, les doublons รฉliminรฉs, puis convertie en `set`. + * Dans les rรฉponses, le `set` sera converti en `list`. + * Le schรฉma gรฉnรฉrรฉ indiquera que les valeurs du `set` sont uniques (en utilisant `uniqueItems` de JSON Schema). +* `bytes` : + * `bytes` Python standard. + * Dans les requรชtes et les rรฉponses, traitรฉ comme une `str`. + * Le schรฉma gรฉnรฉrรฉ indiquera qu'il s'agit d'une `str` avec le ยซ format ยป `binary`. +* `Decimal` : + * `Decimal` Python standard. + * Dans les requรชtes et les rรฉponses, gรฉrรฉ de la mรชme maniรจre qu'un `float`. +* Vous pouvez consulter tous les types de donnรฉes Pydantic valides ici : Types de donnรฉes Pydantic. + +## Exemple { #example } + +Voici un exemple de *chemin d'accรจs* avec des paramรจtres utilisant certains des types ci-dessus. + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} + +Notez que les paramรจtres ร  l'intรฉrieur de la fonction ont leur type de donnรฉes naturel et que vous pouvez, par exemple, effectuer des manipulations de dates normales, comme : + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/fr/docs/tutorial/extra-models.md b/docs/fr/docs/tutorial/extra-models.md new file mode 100644 index 0000000000..1f9eb15616 --- /dev/null +++ b/docs/fr/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# Modรจles supplรฉmentaires { #extra-models } + +En poursuivant l'exemple prรฉcรฉdent, il est courant d'avoir plusieurs modรจles liรฉs. + +C'est particuliรจrement vrai pour les modรจles d'utilisateur, car : + +* Le modรจle d'entrรฉe doit pouvoir contenir un mot de passe. +* Le modรจle de sortie ne doit pas avoir de mot de passe. +* Le modรจle de base de donnรฉes devra probablement avoir un mot de passe hachรฉ. + +/// danger | Danger + +Ne stockez jamais les mots de passe des utilisateurs en clair. Stockez toujours un ยซ hachage sรฉcurisรฉ ยป que vous pourrez ensuite vรฉrifier. + +Si vous ne savez pas ce que c'est, vous apprendrez ce qu'est un ยซ hachage de mot de passe ยป dans les [chapitres sur la sรฉcuritรฉ](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}. + +/// + +## Utiliser plusieurs modรจles { #multiple-models } + +Voici une idรฉe gรฉnรฉrale de l'apparence des modรจles avec leurs champs de mot de passe et les endroits oรน ils sont utilisรฉs : + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### ร€ propos de `**user_in.model_dump()` { #about-user-in-model-dump } + +#### La mรฉthode `.model_dump()` de Pydantic { #pydantics-model-dump } + +`user_in` est un modรจle Pydantic de classe `UserIn`. + +Les modรจles Pydantic ont une mรฉthode `.model_dump()` qui renvoie un `dict` avec les donnรฉes du modรจle. + +Ainsi, si nous crรฉons un objet Pydantic `user_in` commeย : + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +et que nous appelons ensuiteย : + +```Python +user_dict = user_in.model_dump() +``` + +nous avons maintenant un `dict` avec les donnรฉes dans la variable `user_dict` (c'est un `dict` au lieu d'un objet modรจle Pydantic). + +Et si nous appelonsย : + +```Python +print(user_dict) +``` + +nous obtiendrions un `dict` Python contenantย : + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### Dรฉballer un `dict` { #unpacking-a-dict } + +Si nous prenons un `dict` comme `user_dict` et que nous le passons ร  une fonction (ou une classe) avec `**user_dict`, Python va ยซ dรฉballer ยป ce `dict`. Il passera les clรฉs et valeurs de `user_dict` directement comme arguments nommรฉs. + +Ainsi, en reprenant `user_dict` ci-dessus, รฉcrireย : + +```Python +UserInDB(**user_dict) +``` + +aurait pour rรฉsultat quelque chose d'รฉquivalent ร ย : + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses contenus futursย : + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### Crรฉer un modรจle Pydantic ร  partir du contenu d'un autre { #a-pydantic-model-from-the-contents-of-another } + +Comme dans l'exemple ci-dessus nous avons obtenu `user_dict` depuis `user_in.model_dump()`, ce codeย : + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +serait รฉquivalent ร ย : + +```Python +UserInDB(**user_in.model_dump()) +``` + +... parce que `user_in.model_dump()` est un `dict`, et nous demandons ensuite ร  Python de ยซ dรฉballer ยป ce `dict` en le passant ร  `UserInDB` prรฉcรฉdรฉ de `**`. + +Ainsi, nous obtenons un modรจle Pydantic ร  partir des donnรฉes d'un autre modรจle Pydantic. + +#### Dรฉballer un `dict` et ajouter des mots-clรฉs supplรฉmentaires { #unpacking-a-dict-and-extra-keywords } + +Et en ajoutant ensuite l'argument nommรฉ supplรฉmentaire `hashed_password=hashed_password`, comme iciย : + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +... revient ร ย : + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | Alertes + +Les fonctions auxiliaires `fake_password_hasher` et `fake_save_user` ne servent qu'ร  dรฉmontrer un flux de donnรฉes possible, mais elles n'offrent รฉvidemment aucune sรฉcuritรฉ rรฉelle. + +/// + +## Rรฉduire la duplication { #reduce-duplication } + +Rรฉduire la duplication de code est l'une des idรฉes centrales de **FastAPI**. + +La duplication de code augmente les risques de bogues, de problรจmes de sรฉcuritรฉ, de dรฉsynchronisation du code (lorsque vous mettez ร  jour un endroit mais pas les autres), etc. + +Et ces modรจles partagent beaucoup de donnรฉes et dupliquent des noms et types d'attributs. + +Nous pouvons faire mieux. + +Nous pouvons dรฉclarer un modรจle `UserBase` qui sert de base ร  nos autres modรจles. Ensuite, nous pouvons crรฉer des sous-classes de ce modรจle qui hรฉritent de ses attributs (dรฉclarations de type, validation, etc.). + +Toutes les conversions de donnรฉes, validations, documentation, etc., fonctionneront comme d'habitude. + +De cette faรงon, nous pouvons ne dรฉclarer que les diffรฉrences entre les modรจles (avec `password` en clair, avec `hashed_password` et sans mot de passe)ย : + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` ou `anyOf` { #union-or-anyof } + +Vous pouvez dรฉclarer qu'une rรฉponse est l'`Union` de deux types ou plus, ce qui signifie que la rรฉponse peut รชtre n'importe lequel d'entre eux. + +Cela sera dรฉfini dans OpenAPI avec `anyOf`. + +Pour ce faire, utilisez l'annotation de type Python standard `typing.Union`ย : + +/// note | Remarque + +Lors de la dรฉfinition d'une `Union`, incluez d'abord le type le plus spรฉcifique, suivi du type le moins spรฉcifique. Dans l'exemple ci-dessous, le type le plus spรฉcifique `PlaneItem` prรฉcรจde `CarItem` dans `Union[PlaneItem, CarItem]`. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### `Union` en Python 3.10 { #union-in-python-3-10 } + +Dans cet exemple, nous passons `Union[PlaneItem, CarItem]` comme valeur de l'argument `response_model`. + +Comme nous le passons comme valeur d'un argument au lieu de l'utiliser dans une annotation de type, nous devons utiliser `Union` mรชme en Python 3.10. + +S'il s'agissait d'une annotation de type, nous pourrions utiliser la barre verticale, commeย : + +```Python +some_variable: PlaneItem | CarItem +``` + +Mais si nous รฉcrivons cela dans l'affectation `response_model=PlaneItem | CarItem`, nous obtiendrons une erreur, car Python essaierait d'effectuer une ยซ opรฉration invalide ยป entre `PlaneItem` et `CarItem` au lieu de l'interprรฉter comme une annotation de type. + +## Liste de modรจles { #list-of-models } + +De la mรชme maniรจre, vous pouvez dรฉclarer des rรฉponses contenant des listes d'objets. + +Pour cela, utilisez le `list` Python standardย : + +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} + +## Rรฉponse avec un `dict` arbitraire { #response-with-arbitrary-dict } + +Vous pouvez รฉgalement dรฉclarer une rรฉponse en utilisant un simple `dict` arbitraire, en dรฉclarant uniquement le type des clรฉs et des valeurs, sans utiliser de modรจle Pydantic. + +C'est utile si vous ne connaissez pas ร  l'avance les noms de champs/attributs valides (qui seraient nรฉcessaires pour un modรจle Pydantic). + +Dans ce cas, vous pouvez utiliser `dict`ย : + +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} + +## Rรฉcapitulatif { #recap } + +Utilisez plusieurs modรจles Pydantic et hรฉritez librement selon chaque cas. + +Vous n'avez pas besoin d'avoir un seul modรจle de donnรฉes par entitรฉ si cette entitรฉ doit pouvoir avoir diffรฉrents ยซ รฉtats ยป. Comme pour l'ยซ entitรฉ ยป utilisateur, avec un รฉtat incluant `password`, `password_hash` et sans mot de passe. diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index b2693b3e5a..ae23584688 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -1,8 +1,8 @@ -# Dรฉmarrage { #first-steps } +# Dรฉmarrer { #first-steps } Le fichier **FastAPI** le plus simple possible pourrait ressembler ร  ceci : -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} Copiez cela dans un fichier `main.py`. @@ -56,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) Cette ligne montre lโ€™URL oรน votre application est servie, sur votre machine locale. -### Vรฉrifiez { #check-it } +### Vรฉrifier { #check-it } Ouvrez votre navigateur ร  lโ€™adresse http://127.0.0.1:8000. @@ -183,7 +183,7 @@ Cโ€™est tout ! Vous pouvez maintenant accรฉder ร  votre application ร  cette URL ### ร‰tape 1 : importer `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` est une classe Python qui fournit toutes les fonctionnalitรฉs nรฉcessaires ร  votre API. @@ -197,7 +197,7 @@ Vous pouvez donc aussi utiliser toutes les fonctionnalitรฉs de get opรฉration +* en utilisant une get opรฉration -/// info | `@dรฉcorateur` Info +/// info | `@decorator` Info Cette syntaxe `@something` en Python est appelรฉe un ยซ dรฉcorateur ยป. @@ -320,7 +320,7 @@ Voici notre ยซ fonction de chemin dโ€™accรจs ยป : * **opรฉration** : `get`. * **fonction** : la fonction sous le ยซ dรฉcorateur ยป (sous `@app.get("/")`). -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} Cโ€™est une fonction Python. @@ -332,9 +332,9 @@ Dans ce cas, cโ€™est une fonction `async`. Vous pouvez aussi la dรฉfinir comme une fonction normale au lieu de `async def` : -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} -/// note +/// note | Remarque Si vous ne connaissez pas la diffรฉrence, consultez [Asynchrone : ยซ Pressรฉ ? ยป](../async.md#in-a-hurry){.internal-link target=_blank}. @@ -342,7 +342,7 @@ Si vous ne connaissez pas la diffรฉrence, consultez [Asynchrone : ยซ Pressรฉ ? ### ร‰tape 5 : retourner le contenu { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} Vous pouvez retourner un `dict`, une `list`, des valeurs uniques comme `str`, `int`, etc. diff --git a/docs/fr/docs/tutorial/handling-errors.md b/docs/fr/docs/tutorial/handling-errors.md new file mode 100644 index 0000000000..38935c21cc --- /dev/null +++ b/docs/fr/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# Gรฉrer les erreurs { #handling-errors } + +Il existe de nombreuses situations oรน vous devez signaler une erreur ร  un client qui utilise votre API. + +Ce client peut รชtre un navigateur avec un frontend, un code d'un tiers, un appareil IoT, etc. + +Vous pourriez avoir besoin d'indiquer au client que : + +* Le client n'a pas les privilรจges suffisants pour cette opรฉration. +* Le client n'a pas accรจs ร  cette ressource. +* L'รฉlรฉment auquel le client tentait d'accรฉder n'existe pas. +* etc. + +Dans ces cas, vous retournez normalement un **code d'รฉtat HTTP** dans la plage de **400** (de 400 ร  499). + +C'est similaire aux codes d'รฉtat HTTP 200 (de 200 ร  299). Ces codes ยซ 200 ยป signifient que, d'une certaine maniรจre, la requรชte a รฉtรฉ un ยซ succรจs ยป. + +Les codes d'รฉtat dans la plage des 400 signifient qu'il y a eu une erreur cรดtรฉ client. + +Vous souvenez-vous de toutes ces erreurs **ยซ 404 Not Found ยป** (et des blagues) ? + +## Utiliser `HTTPException` { #use-httpexception } + +Pour renvoyer au client des rรฉponses HTTP avec des erreurs, vous utilisez `HTTPException`. + +### Importer `HTTPException` { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} + +### Lever une `HTTPException` dans votre code { #raise-an-httpexception-in-your-code } + +`HTTPException` est une exception Python normale avec des donnรฉes supplรฉmentaires pertinentes pour les API. + +Comme il s'agit d'une exception Python, vous ne la `return` pas, vous la `raise`. + +Cela signifie aussi que si vous รชtes dans une fonction utilitaire appelรฉe depuis votre fonction de chemin d'accรจs, et que vous levez la `HTTPException` ร  l'intรฉrieur de cette fonction utilitaire, le reste du code de la fonction de chemin d'accรจs ne s'exรฉcutera pas : la requรชte sera immรฉdiatement interrompue et l'erreur HTTP issue de la `HTTPException` sera envoyรฉe au client. + +L'avantage de lever une exception plutรดt que de retourner une valeur apparaรฎtra plus clairement dans la section sur les Dรฉpendances et la Sรฉcuritรฉ. + +Dans cet exemple, lorsque le client demande un รฉlรฉment par un ID qui n'existe pas, levez une exception avec un code d'รฉtat `404` : + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} + +### Rรฉponse rรฉsultante { #the-resulting-response } + +Si le client demande `http://example.com/items/foo` (un `item_id` ยซ foo ยป), il recevra un code d'รฉtat HTTP 200 et une rรฉponse JSON : + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +Mais si le client demande `http://example.com/items/bar` (un `item_id` inexistant ยซ bar ยป), il recevra un code d'รฉtat HTTP 404 (l'erreur ยซ not found ยป) et une rรฉponse JSON : + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | Astuce + +Lorsque vous levez une `HTTPException`, vous pouvez passer n'importe quelle valeur convertible en JSON comme paramรจtre `detail`, pas uniquement un `str`. + +Vous pouvez passer un `dict`, une `list`, etc. + +Elles sont gรฉrรฉes automatiquement par **FastAPI** et converties en JSON. + +/// + +## Ajouter des en-tรชtes personnalisรฉs { #add-custom-headers } + +Dans certaines situations, il est utile de pouvoir ajouter des en-tรชtes personnalisรฉs ร  l'erreur HTTP. Par exemple, pour certains types de sรฉcuritรฉ. + +Vous n'aurez probablement pas besoin de l'utiliser directement dans votre code. + +Mais si vous en aviez besoin pour un scรฉnario avancรฉ, vous pouvez ajouter des en-tรชtes personnalisรฉs : + +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} + +## Installer des gestionnaires d'exception personnalisรฉs { #install-custom-exception-handlers } + +Vous pouvez ajouter des gestionnaires d'exception personnalisรฉs avec les mรชmes utilitaires d'exception de Starlette. + +Supposons que vous ayez une exception personnalisรฉe `UnicornException` que vous (ou une bibliothรจque que vous utilisez) pourriez `raise`. + +Et vous souhaitez gรฉrer cette exception globalement avec FastAPI. + +Vous pouvez ajouter un gestionnaire d'exception personnalisรฉ avec `@app.exception_handler()` : + +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} + +Ici, si vous appelez `/unicorns/yolo`, le chemin d'accรจs va `raise` une `UnicornException`. + +Mais elle sera gรฉrรฉe par `unicorn_exception_handler`. + +Ainsi, vous recevrez une erreur propre, avec un code d'รฉtat HTTP `418` et un contenu JSON : + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.requests import Request` et `from starlette.responses import JSONResponse`. + +**FastAPI** fournit les mรชmes `starlette.responses` sous `fastapi.responses` par simple commoditรฉ pour vous, dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. Il en va de mรชme pour `Request`. + +/// + +## Remplacer les gestionnaires d'exception par dรฉfaut { #override-the-default-exception-handlers } + +**FastAPI** fournit des gestionnaires d'exception par dรฉfaut. + +Ces gestionnaires se chargent de renvoyer les rรฉponses JSON par dรฉfaut lorsque vous `raise` une `HTTPException` et lorsque la requรชte contient des donnรฉes invalides. + +Vous pouvez remplacer ces gestionnaires d'exception par les vรดtres. + +### Remplacer les exceptions de validation de la requรชte { #override-request-validation-exceptions } + +Lorsqu'une requรชte contient des donnรฉes invalides, **FastAPI** lรจve en interne une `RequestValidationError`. + +Et il inclut รฉgalement un gestionnaire d'exception par dรฉfaut pour cela. + +Pour la remplacer, importez `RequestValidationError` et utilisez-la avec `@app.exception_handler(RequestValidationError)` pour dรฉcorer le gestionnaire d'exception. + +Le gestionnaire d'exception recevra une `Request` et l'exception. + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} + +ร€ prรฉsent, si vous allez sur `/items/foo`, au lieu d'obtenir l'erreur JSON par dรฉfaut suivante : + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +vous obtiendrez une version texte, avec : + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### Remplacer le gestionnaire d'erreurs `HTTPException` { #override-the-httpexception-error-handler } + +De la mรชme maniรจre, vous pouvez remplacer le gestionnaire de `HTTPException`. + +Par exemple, vous pourriez vouloir renvoyer une rรฉponse en texte brut au lieu de JSON pour ces erreurs : + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.responses import PlainTextResponse`. + +**FastAPI** fournit les mรชmes `starlette.responses` sous `fastapi.responses` par simple commoditรฉ pour vous, le dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. + +/// + +/// warning | Alertes + +Gardez ร  l'esprit que la `RequestValidationError` contient l'information du nom de fichier et de la ligne oรน l'erreur de validation se produit, afin que vous puissiez l'afficher dans vos journaux avec les informations pertinentes si vous le souhaitez. + +Mais cela signifie que si vous vous contentez de la convertir en chaรฎne et de renvoyer cette information directement, vous pourriez divulguer un peu d'information sur votre systรจme. C'est pourquoi, ici, le code extrait et affiche chaque erreur indรฉpendamment. + +/// + +### Utiliser le corps de `RequestValidationError` { #use-the-requestvalidationerror-body } + +La `RequestValidationError` contient le `body` qu'elle a reรงu avec des donnรฉes invalides. + +Vous pouvez l'utiliser pendant le dรฉveloppement de votre application pour journaliser le corps et le dรฉboguer, le renvoyer ร  l'utilisateur, etc. + +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} + +Essayez maintenant d'envoyer un รฉlรฉment invalide comme : + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +Vous recevrez une rรฉponse vous indiquant que les donnรฉes sont invalides et contenant le corps reรงu : + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### `HTTPException` de FastAPI vs `HTTPException` de Starlette { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI** a sa propre `HTTPException`. + +Et la classe d'erreur `HTTPException` de **FastAPI** hรฉrite de la classe d'erreur `HTTPException` de Starlette. + +La seule diffรฉrence est que la `HTTPException` de **FastAPI** accepte toute donnรฉe sรฉrialisable en JSON pour le champ `detail`, tandis que la `HTTPException` de Starlette n'accepte que des chaรฎnes. + +Ainsi, vous pouvez continuer ร  lever la `HTTPException` de **FastAPI** normalement dans votre code. + +Mais lorsque vous enregistrez un gestionnaire d'exception, vous devez l'enregistrer pour la `HTTPException` de Starlette. + +De cette faรงon, si une partie du code interne de Starlette, ou une extension ou un plug-in Starlette, lรจve une `HTTPException` de Starlette, votre gestionnaire pourra l'intercepter et la traiter. + +Dans cet exemple, afin de pouvoir avoir les deux `HTTPException` dans le mรชme code, les exceptions de Starlette sont renommรฉes en `StarletteHTTPException` : + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### Rรฉutiliser les gestionnaires d'exception de **FastAPI** { #reuse-fastapis-exception-handlers } + +Si vous souhaitez utiliser l'exception avec les mรชmes gestionnaires d'exception par dรฉfaut de **FastAPI**, vous pouvez importer et rรฉutiliser les gestionnaires d'exception par dรฉfaut depuis `fastapi.exception_handlers` : + +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} + +Dans cet exemple, vous vous contentez d'afficher l'erreur avec un message trรจs expressif, mais vous voyez l'idรฉe. Vous pouvez utiliser l'exception puis simplement rรฉutiliser les gestionnaires d'exception par dรฉfaut. diff --git a/docs/fr/docs/tutorial/header-param-models.md b/docs/fr/docs/tutorial/header-param-models.md new file mode 100644 index 0000000000..8fc1a3d366 --- /dev/null +++ b/docs/fr/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Modรจles de paramรจtres d'en-tรชte { #header-parameter-models } + +Si vous avez un groupe de **paramรจtres d'en-tรชte** liรฉs, vous pouvez crรฉer un **modรจle Pydantic** pour les dรฉclarer. + +Cela vous permet de **rรฉutiliser le modรจle** ร  **plusieurs endroits** et aussi de dรฉclarer des validations et des mรฉtadonnรฉes pour tous les paramรจtres en une seule fois. ๐Ÿ˜Ž + +/// note | Remarque + +Cela est pris en charge depuis la version `0.115.0` de FastAPI. ๐Ÿค“ + +/// + +## Paramรจtres d'en-tรชte avec un modรจle Pydantic { #header-parameters-with-a-pydantic-model } + +Dรฉclarez les **paramรจtres d'en-tรชte** dont vous avez besoin dans un **modรจle Pydantic**, puis dรฉclarez le paramรจtre comme `Header` : + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** extrait les donnรฉes de **chaque champ** depuis les **en-tรชtes** de la requรชte et vous fournit le modรจle Pydantic que vous avez dรฉfini. + +## Consulter la documentation { #check-the-docs } + +Vous pouvez voir les en-tรชtes requis dans l'interface de la documentation ร  `/docs` : + +
+ +
+ +## Interdire les en-tรชtes supplรฉmentaires { #forbid-extra-headers } + +Dans certains cas d'utilisation particuliers (probablement pas trรจs courants), vous pourriez vouloir **restreindre** les en-tรชtes que vous souhaitez recevoir. + +Vous pouvez utiliser la configuration du modรจle de Pydantic pour `forbid` tout champ `extra` : + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Si un client essaie d'envoyer des **en-tรชtes supplรฉmentaires**, il recevra une **rรฉponse d'erreur**. + +Par exemple, si le client essaie d'envoyer un en-tรชte `tool` avec la valeur `plumbus`, il recevra une **rรฉponse d'erreur** lui indiquant que le paramรจtre d'en-tรชte `tool` n'est pas autorisรฉ : + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Dรฉsactiver convert_underscores { #disable-convert-underscores } + +Comme pour les paramรจtres d'en-tรชte classiques, lorsque vous avez des caractรจres de soulignement dans les noms de paramรจtres, ils sont **automatiquement convertis en tirets**. + +Par exemple, si vous avez un paramรจtre d'en-tรชte `save_data` dans le code, l'en-tรชte HTTP attendu sera `save-data`, et il apparaรฎtra ainsi dans la documentation. + +Si, pour une raison quelconque, vous devez dรฉsactiver cette conversion automatique, vous pouvez aussi le faire pour les modรจles Pydantic de paramรจtres d'en-tรชte. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | Alertes + +Avant de dรฉfinir `convert_underscores` ร  `False`, gardez ร  l'esprit que certains proxys et serveurs HTTP interdisent l'utilisation d'en-tรชtes contenant des underscores. + +/// + +## Rรฉsumรฉ { #summary } + +Vous pouvez utiliser des **modรจles Pydantic** pour dรฉclarer des **en-tรชtes** dans **FastAPI**. ๐Ÿ˜Ž diff --git a/docs/fr/docs/tutorial/header-params.md b/docs/fr/docs/tutorial/header-params.md new file mode 100644 index 0000000000..608559c858 --- /dev/null +++ b/docs/fr/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Paramรจtres d'en-tรชte { #header-parameters } + +Vous pouvez dรฉfinir des paramรจtres `Header` de la mรชme maniรจre que vous dรฉfinissez des paramรจtres `Query`, `Path` et `Cookie`. + +## Importer `Header` { #import-header } + +Commencez par importer `Header` : + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## Dรฉclarer des paramรจtres `Header` { #declare-header-parameters } + +Dรฉclarez ensuite les paramรจtres d'en-tรชte en utilisant la mรชme structure qu'avec `Path`, `Query` et `Cookie`. + +Vous pouvez dรฉfinir la valeur par dรฉfaut ainsi que tous les paramรจtres supplรฉmentaires de validation ou d'annotation : + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | Dรฉtails techniques + +`Header` est une classe ยซ sล“ur ยป de `Path`, `Query` et `Cookie`. Elle hรฉrite รฉgalement de la mรชme classe commune `Param`. + +Mais rappelez-vous que lorsque vous importez `Query`, `Path`, `Header` et d'autres depuis `fastapi`, ce sont en rรฉalitรฉ des fonctions qui renvoient des classes spรฉciales. + +/// + +/// info + +Pour dรฉclarer des en-tรชtes, vous devez utiliser `Header`, sinon les paramรจtres seraient interprรฉtรฉs comme des paramรจtres de requรชte. + +/// + +## Conversion automatique { #automatic-conversion } + +`Header` offre un peu de fonctionnalitรฉ supplรฉmentaire par rapport ร  `Path`, `Query` et `Cookie`. + +La plupart des en-tรชtes standards sont sรฉparรฉs par un caractรจre ยซ trait d'union ยป, รฉgalement appelรฉ ยซ signe moins ยป (`-`). + +Mais une variable comme `user-agent` est invalide en Python. + +Ainsi, par dรฉfaut, `Header` convertit les caractรจres des noms de paramรจtres du tiret bas (`_`) en trait d'union (`-`) pour extraire et documenter les en-tรชtes. + +De plus, les en-tรชtes HTTP ne sont pas sensibles ร  la casse, vous pouvez donc les dรฉclarer avec le style Python standard (aussi appelรฉ ยซ snake_case ยป). + +Vous pouvez donc utiliser `user_agent` comme vous le feriez normalement dans du code Python, au lieu d'avoir ร  mettre des majuscules aux premiรจres lettres comme `User_Agent` ou quelque chose de similaire. + +Si, pour une raison quelconque, vous devez dรฉsactiver la conversion automatique des traits bas en traits d'union, dรฉfinissez le paramรจtre `convert_underscores` de `Header` sur `False` : + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | Alertes + +Avant de dรฉfinir `convert_underscores` sur `False`, gardez ร  l'esprit que certains proxies et serveurs HTTP interdisent l'utilisation d'en-tรชtes contenant des traits bas. + +/// + +## Gรฉrer les en-tรชtes dupliquรฉs { #duplicate-headers } + +Il est possible de recevoir des en-tรชtes en double. Autrement dit, le mรชme en-tรชte avec plusieurs valeurs. + +Vous pouvez dรฉfinir ces cas ร  l'aide d'une liste dans la dรฉclaration de type. + +Vous recevrez toutes les valeurs de l'en-tรชte dupliquรฉ sous forme de `list` Python. + +Par exemple, pour dรฉclarer un en-tรชte `X-Token` qui peut apparaรฎtre plusieurs fois, vous pouvez รฉcrire : + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +Si vous communiquez avec ce *chemin d'accรจs* en envoyant deux en-tรชtes HTTP comme : + +``` +X-Token: foo +X-Token: bar +``` + +La rรฉponse ressemblerait ร  ceci : + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## Rรฉcapitulatif { #recap } + +Dรฉclarez les en-tรชtes avec `Header`, en suivant le mรชme modรจle que pour `Query`, `Path` et `Cookie`. + +Et ne vous souciez pas des traits bas dans vos variables, **FastAPI** s'occupe de les convertir. diff --git a/docs/fr/docs/tutorial/metadata.md b/docs/fr/docs/tutorial/metadata.md new file mode 100644 index 0000000000..3ea3865bab --- /dev/null +++ b/docs/fr/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# Mรฉtadonnรฉes et URL des documents { #metadata-and-docs-urls } + +Vous pouvez personnaliser plusieurs configurations de mรฉtadonnรฉes dans votre application **FastAPI**. + +## Mรฉtadonnรฉes pour l'API { #metadata-for-api } + +Vous pouvez dรฉfinir les champs suivants qui sont utilisรฉs dans la spรฉcification OpenAPI et les interfaces utilisateur de documentation automatique de lโ€™APIย : + +| Paramรจtre | Type | Description | +|------------|------|-------------| +| `title` | `str` | Le titre de lโ€™API. | +| `summary` | `str` | Un court rรฉsumรฉ de lโ€™API. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0. | +| `description` | `str` | Une brรจve description de lโ€™API. Elle peut utiliser Markdown. | +| `version` | `string` | La version de lโ€™API. Cโ€™est la version de votre propre application, pas dโ€™OpenAPI. Par exemple `2.5.0`. | +| `terms_of_service` | `str` | Une URL vers les Conditions dโ€™utilisation de lโ€™API. Le cas รฉchรฉant, il doit sโ€™agir dโ€™une URL. | +| `contact` | `dict` | Les informations de contact pour lโ€™API exposรฉe. Cela peut contenir plusieurs champs.
champs de contact
ParamรจtreTypeDescription
namestrLe nom identifiant de la personne/organisation de contact.
urlstrLโ€™URL pointant vers les informations de contact. DOIT รชtre au format dโ€™une URL.
emailstrLโ€™adresse e-mail de la personne/organisation de contact. DOIT รชtre au format dโ€™une adresse e-mail.
| +| `license_info` | `dict` | Les informations de licence pour lโ€™API exposรฉe. Cela peut contenir plusieurs champs.
champs de license_info
ParamรจtreTypeDescription
namestrOBLIGATOIRE (si un license_info est dรฉfini). Le nom de la licence utilisรฉe pour lโ€™API.
identifierstrUne expression de licence SPDX pour lโ€™API. Le champ identifier est mutuellement exclusif du champ url. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUne URL vers la licence utilisรฉe pour lโ€™API. DOIT รชtre au format dโ€™une URL.
| + +Vous pouvez les dรฉfinir comme suitย : + +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} + +/// tip | Astuce + +Vous pouvez รฉcrire du Markdown dans le champ `description` et il sera rendu dans la sortie. + +/// + +Avec cette configuration, les documents API automatiques ressembleraient ร ย : + + + +## Identifiant de licence { #license-identifier } + +Depuis OpenAPI 3.1.0 et FastAPI 0.99.0, vous pouvez รฉgalement dรฉfinir `license_info` avec un `identifier` au lieu dโ€™une `url`. + +Par exempleย : + +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} + +## Mรฉtadonnรฉes pour les tags { #metadata-for-tags } + +Vous pouvez รฉgalement ajouter des mรฉtadonnรฉes supplรฉmentaires pour les diffรฉrents tags utilisรฉs pour regrouper vos chemins d'accรจs avec le paramรจtre `openapi_tags`. + +Il prend une liste contenant un dictionnaire pour chaque tag. + +Chaque dictionnaire peut contenirย : + +* `name` (**requis**)ย : un `str` avec le mรชme nom de tag que vous utilisez dans le paramรจtre `tags` de vos *chemins d'accรจs* et `APIRouter`s. +* `description`ย : un `str` avec une courte description pour le tag. Il peut contenir du Markdown et sera affichรฉ dans lโ€™interface utilisateur de la documentation. +* `externalDocs`ย : un `dict` dรฉcrivant une documentation externe avecย : + * `description`ย : un `str` avec une courte description pour la documentation externe. + * `url` (**requis**)ย : un `str` avec lโ€™URL de la documentation externe. + +### Crรฉer des mรฉtadonnรฉes pour les tags { #create-metadata-for-tags } + +Essayons cela avec un exemple de tags pour `users` et `items`. + +Crรฉez des mรฉtadonnรฉes pour vos tags et transmettez-les au paramรจtre `openapi_tags`ย : + +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} + +Notez que vous pouvez utiliser Markdown ร  lโ€™intรฉrieur des descriptions, par exemple ยซ login ยป sera affichรฉ en gras (**login**) et ยซ fancy ยป sera affichรฉ en italique (_fancy_). + +/// tip | Astuce + +Vous nโ€™avez pas ร  ajouter des mรฉtadonnรฉes pour tous les tags que vous utilisez. + +/// + +### Utiliser vos tags { #use-your-tags } + +Utilisez le paramรจtre `tags` avec vos *chemins d'accรจs* (et `APIRouter`s) pour les affecter ร  diffรฉrents tagsย : + +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} + +/// info + +En savoir plus sur les tags dans [Configuration de chemins d'accรจs](path-operation-configuration.md#tags){.internal-link target=_blank}. + +/// + +### Consultez les documents { #check-the-docs } + +Dรฉsormais, si vous consultez les documents, ils afficheront toutes les mรฉtadonnรฉes supplรฉmentairesย : + + + +### Dรฉfinir lโ€™ordre des tags { #order-of-tags } + +Lโ€™ordre de chaque dictionnaire de mรฉtadonnรฉes de tag dรฉfinit รฉgalement lโ€™ordre affichรฉ dans lโ€™interface utilisateur de la documentation. + +Par exemple, mรชme si `users` viendrait aprรจs `items` par ordre alphabรฉtique, il est affichรฉ avant, car nous avons ajoutรฉ ses mรฉtadonnรฉes comme premier dictionnaire de la liste. + +## URL OpenAPI { #openapi-url } + +Par dรฉfaut, le schรฉma OpenAPI est servi ร  `/openapi.json`. + +Mais vous pouvez le configurer avec le paramรจtre `openapi_url`. + +Par exemple, pour quโ€™il soit servi ร  `/api/v1/openapi.json`ย : + +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} + +Si vous souhaitez dรฉsactiver complรจtement le schรฉma OpenAPI, vous pouvez dรฉfinir `openapi_url=None`, cela dรฉsactivera รฉgalement les interfaces utilisateur de la documentation qui lโ€™utilisent. + +## URL des documents { #docs-urls } + +Vous pouvez configurer les deux interfaces utilisateur de documentation inclusesย : + +* **Swagger UI**ย : servie ร  `/docs`. + * Vous pouvez dรฉfinir son URL avec le paramรจtre `docs_url`. + * Vous pouvez la dรฉsactiver en dรฉfinissant `docs_url=None`. +* **ReDoc**ย : servie ร  `/redoc`. + * Vous pouvez dรฉfinir son URL avec le paramรจtre `redoc_url`. + * Vous pouvez la dรฉsactiver en dรฉfinissant `redoc_url=None`. + +Par exemple, pour que Swagger UI soit servi ร  `/documentation` et dรฉsactiver ReDocย : + +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/fr/docs/tutorial/middleware.md b/docs/fr/docs/tutorial/middleware.md new file mode 100644 index 0000000000..6cbbc3e456 --- /dev/null +++ b/docs/fr/docs/tutorial/middleware.md @@ -0,0 +1,95 @@ +# Middleware { #middleware } + +Vous pouvez ajouter des middlewares aux applications **FastAPI**. + +Un ยซ middleware ยป est une fonction qui agit sur chaque **requรชte** avant quโ€™elle ne soit traitรฉe par un *chemin d'accรจs* spรฉcifique. Et aussi sur chaque **rรฉponse** avant son renvoi. + +* Il intercepte chaque **requรชte** qui parvient ร  votre application. +* Il peut alors faire quelque chose avec cette **requรชte** ou exรฉcuter tout code nรฉcessaire. +* Ensuite, il transmet la **requรชte** pour quโ€™elle soit traitรฉe par le reste de lโ€™application (par un *chemin d'accรจs*). +* Puis il rรฉcupรจre la **rรฉponse** gรฉnรฉrรฉe par lโ€™application (par un *chemin d'accรจs*). +* Il peut faire quelque chose avec cette **rรฉponse** ou exรฉcuter tout code nรฉcessaire. +* Enfin, il renvoie la **rรฉponse**. + +/// note | Dรฉtails techniques + +Si vous avez des dรฉpendances avec `yield`, le code de sortie sโ€™exรฉcutera aprรจs le middleware. + +Sโ€™il y avait des tรขches dโ€™arriรจre-plan (prรฉsentรฉes dans la section [Tรขches dโ€™arriรจre-plan](background-tasks.md){.internal-link target=_blank}, que vous verrez plus tard), elles sโ€™exรฉcuteront aprรจs tous les middlewares. + +/// + +## Crรฉer un middleware { #create-a-middleware } + +Pour crรฉer un middleware, utilisez le dรฉcorateur `@app.middleware("http")` au-dessus dโ€™une fonction. + +La fonction de middleware reรงoitโ€ฏ: + +* La `request`. +* Une fonction `call_next` qui recevra la `request` en paramรจtre. + * Cette fonction transmettra la `request` au *chemin d'accรจs* correspondant. + * Puis elle renverra la `response` gรฉnรฉrรฉe par le *chemin d'accรจs* correspondant. +* Vous pouvez ensuite modifier la `response` avant de la renvoyer. + +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} + +/// tip | Astuce + +Gardez ร  lโ€™esprit que des en-tรชtes propriรฉtaires personnalisรฉs peuvent รชtre ajoutรฉs en utilisant le prรฉfixe `X-`. + +Mais si vous avez des en-tรชtes personnalisรฉs que vous voulez rendre visibles pour un client dans un navigateur, vous devez les ajouter ร  votre configuration CORS ([CORS (Partage des ressources entre origines)](cors.md){.internal-link target=_blank}) en utilisant le paramรจtre `expose_headers` documentรฉ dans la documentation CORS de Starlette. + +/// + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.requests import Request`. + +**FastAPI** le fournit pour votre confort de dรฉveloppeur. Mais cela provient directement de Starlette. + +/// + +### Avant et aprรจs la `response` { #before-and-after-the-response } + +Vous pouvez ajouter du code ร  exรฉcuter avec la `request`, avant que tout *chemin d'accรจs* ne la reรงoive. + +Et aussi aprรจs que la `response` a รฉtรฉ gรฉnรฉrรฉe, avant de la renvoyer. + +Par exemple, vous pourriez ajouter un en-tรชte personnalisรฉ `X-Process-Time` contenant le temps en secondes nรฉcessaire pour traiter la requรชte et gรฉnรฉrer une rรฉponseโ€ฏ: + +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} + +/// tip | Astuce + +Ici, nous utilisons `time.perf_counter()` au lieu de `time.time()` car cela peut รชtre plus prรฉcis pour ces cas dโ€™usage. ๐Ÿค“ + +/// + +## Ordre dโ€™exรฉcution de plusieurs middlewares { #multiple-middleware-execution-order } + +Quand vous ajoutez plusieurs middlewares en utilisant soit le dรฉcorateur `@app.middleware()`, soit la mรฉthode `app.add_middleware()`, chaque nouveau middleware enveloppe lโ€™application, formant une pile. Le dernier middleware ajoutรฉ est le plus externe, et le premier est le plus interne. + +Sur le chemin de la requรชte, le plus externe sโ€™exรฉcute en premier. + +Sur le chemin de la rรฉponse, il sโ€™exรฉcute en dernier. + +Par exempleโ€ฏ: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +Cela aboutit ร  lโ€™ordre dโ€™exรฉcution suivantโ€ฏ: + +* **Requรชte** : MiddlewareB โ†’ MiddlewareA โ†’ route + +* **Rรฉponse** : route โ†’ MiddlewareA โ†’ MiddlewareB + +Ce comportement dโ€™empilement garantit que les middlewares sโ€™exรฉcutent dans un ordre prรฉvisible et contrรดlable. + +## Autres middlewares { #other-middlewares } + +Vous pouvez en lire davantage sur dโ€™autres middlewares dans le [Guide de lโ€™utilisateur avancรฉ : Middleware avancรฉ](../advanced/middleware.md){.internal-link target=_blank}. + +Vous verrez comment gรฉrer CORS avec un middleware dans la section suivante. diff --git a/docs/fr/docs/tutorial/path-operation-configuration.md b/docs/fr/docs/tutorial/path-operation-configuration.md new file mode 100644 index 0000000000..f8041fa691 --- /dev/null +++ b/docs/fr/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# Configurer les chemins d'accรจs { #path-operation-configuration } + +Vous pouvez passer plusieurs paramรจtres ร  votre *dรฉcorateur de chemin d'accรจs* pour le configurer. + +/// warning | Alertes + +Notez que ces paramรจtres sont passรฉs directement au *dรฉcorateur de chemin d'accรจs*, et non ร  votre *fonction de chemin d'accรจs*. + +/// + +## Dรฉfinir le code d'รฉtat de la rรฉponse { #response-status-code } + +Vous pouvez dรฉfinir le `status_code` (HTTP) ร  utiliser dans la rรฉponse de votre *chemin d'accรจs*. + +Vous pouvez passer directement le code `int`, comme `404`. + +Mais si vous ne vous souvenez pas ร  quoi correspond chaque code numรฉrique, vous pouvez utiliser les constantes abrรฉgรฉes dans `status` : + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +Ce code d'รฉtat sera utilisรฉ dans la rรฉponse et ajoutรฉ au schรฉma OpenAPI. + +/// note | Dรฉtails techniques + +Vous pouvez รฉgalement utiliser `from starlette import status`. + +**FastAPI** fournit le mรชme `starlette.status` sous le nom `fastapi.status` pour votre commoditรฉ, en tant que dรฉveloppeur. Mais cela provient directement de Starlette. + +/// + +## Ajouter des tags { #tags } + +Vous pouvez ajouter des tags ร  votre *chemin d'accรจs*, en passant le paramรจtre `tags` avec une `list` de `str` (gรฉnรฉralement un seul `str`) : + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +Ils seront ajoutรฉs au schรฉma OpenAPI et utilisรฉs par les interfaces de documentation automatiques : + + + +### Utiliser des tags avec Enum { #tags-with-enums } + +Si vous avez une grande application, vous pourriez finir par accumuler **plusieurs tags**, et vous voudrez vous assurer d'utiliser toujours le **mรชme tag** pour les *chemins d'accรจs* associรฉs. + +Dans ces cas, il peut รชtre judicieux de stocker les tags dans un `Enum`. + +**FastAPI** le prend en charge de la mรชme maniรจre qu'avec des chaรฎnes simples : + +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} + +## Ajouter un rรฉsumรฉ et une description { #summary-and-description } + +Vous pouvez ajouter un `summary` et une `description` : + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## Utiliser la description depuis la docstring { #description-from-docstring } + +Comme les descriptions ont tendance ร  รชtre longues et ร  couvrir plusieurs lignes, vous pouvez dรฉclarer la description du *chemin d'accรจs* dans la docstring de la fonction et **FastAPI** la lira ร  partir de lร . + +Vous pouvez รฉcrire Markdown dans la docstring, il sera interprรฉtรฉ et affichรฉ correctement (en tenant compte de l'indentation de la docstring). + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +Elle sera utilisรฉe dans les documents interactifs : + + + +## Dรฉfinir la description de la rรฉponse { #response-description } + +Vous pouvez spรฉcifier la description de la rรฉponse avec le paramรจtre `response_description` : + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} + +/// info + +Notez que `response_description` se rรฉfรจre spรฉcifiquement ร  la rรฉponse, tandis que `description` se rรฉfรจre au *chemin d'accรจs* en gรฉnรฉral. + +/// + +/// check | Vรฉrifications + +OpenAPI spรฉcifie que chaque *chemin d'accรจs* requiert une description de rรฉponse. + +Donc, si vous n'en fournissez pas, **FastAPI** en gรฉnรฉrera automatiquement une ยซ Rรฉponse rรฉussie ยป. + +/// + + + +## Dรฉprรฉcier un *chemin d'accรจs* { #deprecate-a-path-operation } + +Si vous devez marquer un *chemin d'accรจs* comme dรฉprรฉciรฉ, sans pour autant le supprimer, passez le paramรจtre `deprecated` : + +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} + +Il sera clairement marquรฉ comme dรฉprรฉciรฉ dans les documents interactifs : + + + +Voyez ร  quoi ressemblent les *chemins d'accรจs* dรฉprรฉciรฉs et non dรฉprรฉciรฉs : + + + +## Rรฉcapitulatif { #recap } + +Vous pouvez facilement configurer et ajouter des mรฉtadonnรฉes ร  vos *chemins d'accรจs* en passant des paramรจtres aux *dรฉcorateurs de chemin d'accรจs*. diff --git a/docs/fr/docs/tutorial/path-params-numeric-validations.md b/docs/fr/docs/tutorial/path-params-numeric-validations.md index c80710777f..2dbaaa8cae 100644 --- a/docs/fr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/fr/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ Cela n'a pas d'importance pour **FastAPI**. Il dรฉtectera les paramรจtres par le Ainsi, vous pouvez dรฉclarer votre fonction comme suit : -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} Mais gardez ร  l'esprit que si vous utilisez `Annotated`, vous n'aurez pas ce problรจme, cela n'aura pas d'importance car vous n'utilisez pas les valeurs par dรฉfaut des paramรจtres de fonction pour `Query()` ou `Path()`. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## Ordonner les paramรจtres comme vous le souhaitez, astuces { #order-the-parameters-as-you-need-tricks } @@ -81,15 +81,15 @@ Si vous voulez : Passez `*`, comme premier paramรจtre de la fonction. -Python ne fera rien avec ce `*`, mais il saura que tous les paramรจtres suivants doivent รชtre appelรฉs comme arguments "mots-clรฉs" (paires clรฉ-valeur), รฉgalement connus sous le nom de kwargs. Mรชme s'ils n'ont pas de valeur par dรฉfaut. +Python ne fera rien avec ce `*`, mais il saura que tous les paramรจtres suivants doivent รชtre appelรฉs comme arguments ยซ mots-clรฉs ยป (paires clรฉ-valeur), รฉgalement connus sous le nom de kwargs. Mรชme s'ils n'ont pas de valeur par dรฉfaut. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### Mieux avec `Annotated` { #better-with-annotated } Gardez ร  l'esprit que si vous utilisez `Annotated`, comme vous n'utilisez pas les valeurs par dรฉfaut des paramรจtres de fonction, vous n'aurez pas ce problรจme, et vous n'aurez probablement pas besoin d'utiliser `*`. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## Validations numรฉriques : supรฉrieur ou รฉgal { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ Avec `Query` et `Path` (et d'autres que vous verrez plus tard) vous pouvez dรฉcl Ici, avec `ge=1`, `item_id` devra รชtre un nombre entier ยซ `g`reater than or `e`qual ยป ร  `1`. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## Validations numรฉriques : supรฉrieur et infรฉrieur ou รฉgal { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ La mรชme chose s'applique pour : * `gt` : `g`reater `t`han * `le` : `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## Validations numรฉriques : flottants, supรฉrieur et infรฉrieur { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ Ainsi, `0.5` serait une valeur valide. Mais `0.0` ou `0` ne le serait pas. Et la mรชme chose pour lt. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## Pour rรฉsumer { #recap } diff --git a/docs/fr/docs/tutorial/path-params.md b/docs/fr/docs/tutorial/path-params.md index 3b2955a95d..985eff6354 100644 --- a/docs/fr/docs/tutorial/path-params.md +++ b/docs/fr/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ Vous pouvez dรฉclarer des ยซ paramรจtres ยป ou ยซ variables ยป de chemin avec la mรชme syntaxe utilisรฉe par les chaรฎnes de format Python : -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} La valeur du paramรจtre de chemin `item_id` sera transmise ร  votre fonction dans l'argument `item_id`. @@ -16,7 +16,7 @@ Donc, si vous exรฉcutez cet exemple et allez sur Conversion de donnรฉes { #data-conversion } +## Conversion de donnรฉes { #data-conversion } Si vous exรฉcutez cet exemple et ouvrez votre navigateur sur http://127.0.0.1:8000/items/3, vous verrez comme rรฉponse : @@ -38,7 +38,7 @@ Si vous exรฉcutez cet exemple et ouvrez votre navigateur sur ยซ parsing ยป de la requรชte. +Ainsi, avec cette dรฉclaration de type, **FastAPI** vous fournit automatiquement le ยซ parsing ยป de la requรชte. /// @@ -118,19 +118,19 @@ Et vous pouvez aussi avoir un chemin `/users/{user_id}` pour rรฉcupรฉrer des don Comme les *chemins d'accรจs* sont รฉvaluรฉs dans l'ordre, vous devez vous assurer que le chemin `/users/me` est dรฉclarรฉ avant celui de `/users/{user_id}` : -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} Sinon, le chemin `/users/{user_id}` correspondrait aussi ร  `/users/me`, ยซ pensant ยป qu'il reรงoit un paramรจtre `user_id` avec la valeur ยซ me ยป. De mรชme, vous ne pouvez pas redรฉfinir un chemin d'accรจs : -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} Le premier sera toujours utilisรฉ puisque le chemin correspond en premier. ## Valeurs prรฉdรฉfinies { #predefined-values } -Si vous avez un *chemin d'accรจs* qui reรงoit un *paramรจtre de chemin*, mais que vous voulez que les valeurs possibles de ce *paramรจtre de chemin* soient prรฉdรฉfinies, vous pouvez utiliser une `Enum` Python standard. +Si vous avez un *chemin d'accรจs* qui reรงoit un *paramรจtre de chemin*, mais que vous voulez que les valeurs possibles de ce *paramรจtre de chemin* soient prรฉdรฉfinies, vous pouvez utiliser une `Enum` Python standard. ### Crรฉer une classe `Enum` { #create-an-enum-class } @@ -140,11 +140,11 @@ En hรฉritant de `str`, la documentation de l'API saura que les valeurs doivent Crรฉez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs valides disponibles : -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | Astuce -Si vous vous demandez, ยซ AlexNet ยป, ยซ ResNet ยป et ยซ LeNet ยป sont juste des noms de modรจles de Machine Learning. +Si vous vous demandez, ยซ AlexNet ยป, ยซ ResNet ยป et ยซ LeNet ยป sont juste des noms de modรจles de Machine Learning. /// @@ -152,7 +152,7 @@ Si vous vous demandez, ยซ AlexNet ยป, ยซ ResNet ยป et ยซ LeNet ยป sont juste des Crรฉez ensuite un *paramรจtre de chemin* avec une annotation de type utilisant la classe d'รฉnumรฉration que vous avez crรฉรฉe (`ModelName`) : -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### Consulter la documentation { #check-the-docs } @@ -168,13 +168,13 @@ La valeur du *paramรจtre de chemin* sera un *membre d'รฉnumรฉration*. Vous pouvez le comparer avec le *membre d'รฉnumรฉration* dans votre enum `ModelName` : -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### Obtenir la *valeur de l'รฉnumรฉration* { #get-the-enumeration-value } Vous pouvez obtenir la valeur rรฉelle (une `str` dans ce cas) avec `model_name.value`, ou en gรฉnรฉral, `votre_membre_d_enum.value` : -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | Astuce @@ -188,7 +188,7 @@ Vous pouvez retourner des *membres d'รฉnumรฉration* depuis votre *chemin d'accรจ Ils seront convertis vers leurs valeurs correspondantes (des chaรฎnes de caractรจres ici) avant d'รชtre renvoyรฉs au client : -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} Dans votre client, vous recevrez une rรฉponse JSON comme : @@ -227,7 +227,7 @@ Dans ce cas, le nom du paramรจtre est `file_path`, et la derniรจre partie, `:pat Vous pouvez donc l'utiliser ainsi : -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | Astuce @@ -242,7 +242,7 @@ Dans ce cas, l'URL serait : `/files//home/johndoe/myfile.txt`, avec un double sl Avec **FastAPI**, en utilisant des dรฉclarations de type Python courtes, intuitives et standard, vous obtenez : * Support de l'รฉditeur : vรฉrifications d'erreurs, autocomplรฉtion, etc. -* Donnรฉes ยซ parsing ยป +* Donnรฉes ยซ parsing ยป * Validation de donnรฉes * Annotations d'API et documentation automatique diff --git a/docs/fr/docs/tutorial/query-param-models.md b/docs/fr/docs/tutorial/query-param-models.md new file mode 100644 index 0000000000..b9bb1d1378 --- /dev/null +++ b/docs/fr/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Modรจles de paramรจtres de requรชte { #query-parameter-models } + +Si vous avez un groupe de paramรจtres de requรชte liรฉs, vous pouvez crรฉer un modรจle Pydantic pour les dรฉclarer. + +Cela vous permet de rรฉutiliser le modรจle ร  plusieurs endroits et aussi de dรฉclarer des validations et des mรฉtadonnรฉes pour tous les paramรจtres en une seule fois. ๐Ÿ˜Ž + +/// note | Remarque + +Pris en charge depuis FastAPI version `0.115.0`. ๐Ÿค“ + +/// + +## Dรฉclarer des paramรจtres de requรชte avec un modรจle Pydantic { #query-parameters-with-a-pydantic-model } + +Dรฉclarez les paramรจtres de requรชte dont vous avez besoin dans un modรจle Pydantic, puis dรฉclarez le paramรจtre en tant que `Query` : + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +FastAPI extrait les donnรฉes pour chaque champ ร  partir des paramรจtres de requรชte de la requรชte et vous fournit le modรจle Pydantic que vous avez dรฉfini. + +## Consulter les documents { #check-the-docs } + +Vous pouvez voir les paramรจtres de requรชte dans l'interface des documents ร  `/docs` : + +
+ +
+ +## Interdire des paramรจtres de requรชte supplรฉmentaires { #forbid-extra-query-parameters } + +Dans certains cas d'utilisation particuliers (probablement peu courants), vous pouvez vouloir restreindre les paramรจtres de requรชte que vous souhaitez recevoir. + +Vous pouvez utiliser la configuration du modรจle Pydantic pour `forbid` tout champ `extra` : + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Si un client tente d'envoyer des donnรฉes supplรฉmentaires dans les paramรจtres de requรชte, il recevra une rรฉponse d'erreur. + +Par exemple, si le client tente d'envoyer un paramรจtre de requรชte `tool` avec la valeur `plumbus`, comme : + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +Il recevra une rรฉponse d'erreur lui indiquant que le paramรจtre de requรชte `tool` n'est pas autorisรฉ : + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## Rรฉsumรฉ { #summary } + +Vous pouvez utiliser des modรจles Pydantic pour dรฉclarer des paramรจtres de requรชte dans FastAPI. ๐Ÿ˜Ž + +/// tip | Astuce + +Alerte spoiler : vous pouvez aussi utiliser des modรจles Pydantic pour dรฉclarer des cookies et des en-tรชtes, mais vous lirez cela plus tard dans le tutoriel. ๐Ÿคซ + +/// diff --git a/docs/fr/docs/tutorial/query-params-str-validations.md b/docs/fr/docs/tutorial/query-params-str-validations.md index 544d10328e..17b751f239 100644 --- a/docs/fr/docs/tutorial/query-params-str-validations.md +++ b/docs/fr/docs/tutorial/query-params-str-validations.md @@ -47,40 +47,16 @@ Cโ€™est le moment de lโ€™utiliser avec FastAPI. ๐Ÿš€ Nous avions cette annotation de type : -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - Ce que nous allons faire, cโ€™est lโ€™englober avec `Annotated`, de sorte que cela devienneย : -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - Les deux versions signifient la mรชme chose, `q` est un paramรจtre qui peut รชtre une `str` ou `None`, et par dรฉfaut, cโ€™est `None`. Passons maintenant aux choses amusantes. ๐ŸŽ‰ @@ -109,7 +85,7 @@ FastAPI va maintenant : ## Alternative (ancienne) : `Query` comme valeur par dรฉfaut { #alternative-old-query-as-the-default-value } -Les versions prรฉcรฉdentes de FastAPI (avant 0.95.0) exigeaient dโ€™utiliser `Query` comme valeur par dรฉfaut de votre paramรจtre, au lieu de le mettre dans `Annotated`. Il y a de fortes chances que vous voyiez du code qui lโ€™utilise encore, je vais donc vous lโ€™expliquer. +Les versions prรฉcรฉdentes de FastAPI (avant 0.95.0) exigeaient dโ€™utiliser `Query` comme valeur par dรฉfaut de votre paramรจtre, au lieu de le mettre dans `Annotated`. Il y a de fortes chances que vous voyiez du code qui lโ€™utilise encore, je vais donc vous lโ€™expliquer. /// tip | Astuce @@ -191,7 +167,7 @@ Vous pouvez รฉgalement ajouter un paramรจtre `min_length` : ## Ajouter des expressions rรฉguliรจres { #add-regular-expressions } -Vous pouvez dรฉfinir un `pattern` dโ€™expression rรฉguliรจre auquel le paramรจtre doit correspondre : +Vous pouvez dรฉfinir un `pattern` dโ€™expression rรฉguliรจre auquel le paramรจtre doit correspondre : {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -211,7 +187,7 @@ Vous pouvez, bien sรปr, utiliser des valeurs par dรฉfaut autres que `None`. Disons que vous voulez dรฉclarer le paramรจtre de requรชte `q` avec un `min_length` de `3`, et avec une valeur par dรฉfaut de ยซ fixedquery ยป : -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Remarque @@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None Donc, lorsque vous avez besoin de dรฉclarer une valeur comme requise tout en utilisant `Query`, vous pouvez simplement ne pas dรฉclarer de valeur par dรฉfaut : -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### Requis, peut valoir `None` { #required-can-be-none } @@ -292,7 +268,7 @@ Lโ€™interface de documentation interactive de lโ€™API sera mise ร  jour en cons Vous pouvez รฉgalement dรฉfinir une `list` de valeurs par dรฉfaut si aucune nโ€™est fournie : -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Si vous allez ร  : @@ -315,7 +291,7 @@ la valeur par dรฉfaut de `q` sera : `["foo", "bar"]` et votre rรฉponse sera : Vous pouvez aussi utiliser `list` directement au lieu de `list[str]` : -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | Remarque @@ -371,7 +347,7 @@ Vous pouvez alors dรฉclarer un `alias`, et cet alias sera utilisรฉ pour trouver Disons que vous nโ€™aimez plus ce paramรจtre. -Vous devez le laisser lร  quelque temps car des clients lโ€™utilisent, mais vous voulez que les documents lโ€™affichent clairement comme dรฉprรฉciรฉ. +Vous devez le laisser lร  quelque temps car des clients lโ€™utilisent, mais vous voulez que les documents lโ€™affichent clairement comme dรฉprรฉciรฉ. Passez alors le paramรจtre `deprecated=True` ร  `Query` : @@ -401,7 +377,7 @@ Pydantic a aussi
ISBN ou par `imdb-` pour un ID dโ€™URL de film IMDB : +Par exemple, ce validateur personnalisรฉ vรฉrifie que lโ€™ID dโ€™item commence par `isbn-` pour un numรฉro de livre ISBN ou par `imdb-` pour un ID dโ€™URL de film IMDB : {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -435,7 +411,7 @@ Avez-vous remarquรฉ ? Une chaรฎne utilisant `value.startswith()` peut prendre un #### Un รฉlรฉment alรฉatoire { #a-random-item } -Avec `data.items()` nous obtenons un objet itรฉrable avec des tuples contenant la clรฉ et la valeur pour chaque รฉlรฉment du dictionnaire. +Avec `data.items()` nous obtenons un objet itรฉrable avec des tuples contenant la clรฉ et la valeur pour chaque รฉlรฉment du dictionnaire. Nous convertissons cet objet itรฉrable en une `list` propre avec `list(data.items())`. diff --git a/docs/fr/docs/tutorial/query-params.md b/docs/fr/docs/tutorial/query-params.md index 1a4880ced3..01540ad17c 100644 --- a/docs/fr/docs/tutorial/query-params.md +++ b/docs/fr/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ Quand vous dรฉclarez d'autres paramรจtres de fonction qui ne font pas partie des paramรจtres de chemin, ils sont automatiquement interprรฉtรฉs comme des paramรจtres de ยซ query ยป. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} La query est l'ensemble des paires clรฉ-valeur placรฉes aprรจs le `?` dans une URL, sรฉparรฉes par des caractรจres `&`. @@ -24,7 +24,7 @@ Mais lorsque vous les dรฉclarez avec des types Python (dans l'exemple ci-dessus, Tous les mรชmes processus qui s'appliquaient aux paramรจtres de chemin s'appliquent aussi aux paramรจtres de requรชte : * Prise en charge de l'รฉditeur (รฉvidemment) -* ยซ parsing ยป des donnรฉes +* ยซ parsing ยป des donnรฉes * Validation des donnรฉes * Documentation automatique @@ -67,7 +67,7 @@ Dans ce cas, le paramรจtre de fonction `q` sera optionnel et vaudra `None` par d /// check | Vรฉrifications -Notez รฉgalement que FastAPI est suffisamment intelligent pour remarquer que le paramรจtre de chemin `item_id` est un paramรจtre de chemin et que `q` ne l'est pas, c'est donc un paramรจtre de requรชte. +Notez รฉgalement que **FastAPI** est suffisamment intelligent pour remarquer que le paramรจtre de chemin `item_id` est un paramรจtre de chemin et que `q` ne l'est pas, c'est donc un paramรจtre de requรชte. /// @@ -127,7 +127,7 @@ Si vous ne voulez pas leur donner de valeur spรฉcifique mais simplement les rend Mais si vous voulez rendre un paramรจtre de requรชte obligatoire, vous pouvez simplement ne dรฉclarer aucune valeur par dรฉfaut : -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} Ici, le paramรจtre de requรชte `needy` est un paramรจtre de requรชte requis de type `str`. diff --git a/docs/fr/docs/tutorial/request-files.md b/docs/fr/docs/tutorial/request-files.md new file mode 100644 index 0000000000..01a0b72eb9 --- /dev/null +++ b/docs/fr/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# Envoyer des fichiers { #request-files } + +Vous pouvez dรฉfinir des fichiers ร  tรฉlรฉverser par le client en utilisant `File`. + +/// info + +Pour recevoir des fichiers tรฉlรฉversรฉs, installez d'abord `python-multipart`. + +Assurez-vous de crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer le paquet, par exempleย : + +```console +$ pip install python-multipart +``` + +C'est parce que les fichiers tรฉlรฉversรฉs sont envoyรฉs en ยซ donnรฉes de formulaire ยป. + +/// + +## Importer `File` { #import-file } + +Importez `File` et `UploadFile` depuis `fastapi`ย : + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} + +## Dรฉfinir des paramรจtres `File` { #define-file-parameters } + +Crรฉez des paramรจtres de fichier de la mรชme maniรจre que pour `Body` ou `Form`ย : + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} + +/// info + +`File` est une classe qui hรฉrite directement de `Form`. + +Mais souvenez-vous que lorsque vous importez `Query`, `Path`, `File` et d'autres depuis `fastapi`, ce sont en rรฉalitรฉ des fonctions qui renvoient des classes spรฉciales. + +/// + +/// tip | Astuce + +Pour dรฉclarer des fichiers dans le corps de la requรชte, vous devez utiliser `File`, sinon les paramรจtres seraient interprรฉtรฉs comme des paramรจtres de requรชte ou des paramรจtres de corps (JSON). + +/// + +Les fichiers seront tรฉlรฉversรฉs en ยซ donnรฉes de formulaire ยป. + +Si vous dรฉclarez le type de votre paramรจtre de *fonction de chemin d'accรจs* comme `bytes`, **FastAPI** lira le fichier pour vous et vous recevrez le contenu sous forme de `bytes`. + +Gardez ร  l'esprit que cela signifie que tout le contenu sera stockรฉ en mรฉmoire. Cela fonctionnera bien pour de petits fichiers. + +Mais dans plusieurs cas, vous pourriez bรฉnรฉficier de l'utilisation d'`UploadFile`. + +## Paramรจtres de fichier avec `UploadFile` { #file-parameters-with-uploadfile } + +Dรฉfinissez un paramรจtre de fichier de type `UploadFile`ย : + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} + +Utiliser `UploadFile` prรฉsente plusieurs avantages par rapport ร  `bytes`ย : + +- Vous n'avez pas besoin d'utiliser `File()` comme valeur par dรฉfaut du paramรจtre. +- Il utilise un fichier ยซ spooled ยปย : + - Un fichier stockรฉ en mรฉmoire jusqu'ร  une taille maximale, puis, au-delร  de cette limite, stockรฉ sur le disque. +- Cela fonctionne donc bien pour des fichiers volumineux comme des images, des vidรฉos, de gros binaires, etc., sans consommer toute la mรฉmoire. +- Vous pouvez obtenir des mรฉtadonnรฉes ร  partir du fichier tรฉlรฉversรฉ. +- Il offre une interface `async` de type file-like. +- Il expose un vรฉritable objet Python `SpooledTemporaryFile` que vous pouvez passer directement ร  d'autres bibliothรจques qui attendent un objet ยซ file-like ยป. + +### `UploadFile` { #uploadfile } + +`UploadFile` a les attributs suivantsย : + +- `filename`ย : une `str` contenant le nom de fichier original tรฉlรฉversรฉ (par ex. `myimage.jpg`). +- `content_type`ย : une `str` avec le type de contenu (type MIME / type mรฉdia) (par ex. `image/jpeg`). +- `file`ย : un `SpooledTemporaryFile` (un objet de type fichier). C'est l'objet fichier Python rรฉel que vous pouvez passer directement ร  d'autres fonctions ou bibliothรจques qui attendent un objet ยซ file-like ยป. + +`UploadFile` a les mรฉthodes `async` suivantes. Elles appellent toutes les mรฉthodes correspondantes du fichier sous-jacent (en utilisant le `SpooledTemporaryFile` interne). + +- `write(data)`ย : รฉcrit `data` (`str` ou `bytes`) dans le fichier. +- `read(size)`ย : lit `size` (`int`) octets/caractรจres du fichier. +- `seek(offset)`ย : se dรฉplace ร  la position d'octet `offset` (`int`) dans le fichier. + - Par ex., `await myfile.seek(0)` irait au dรฉbut du fichier. + - C'est particuliรจrement utile si vous exรฉcutez `await myfile.read()` une fois puis devez relire le contenu. +- `close()`ย : ferme le fichier. + +Comme toutes ces mรฉthodes sont `async`, vous devez les ยซ await ยป. + +Par exemple, ร  l'intรฉrieur d'une *fonction de chemin d'accรจs* `async`, vous pouvez obtenir le contenu avecย : + +```Python +contents = await myfile.read() +``` + +Si vous รชtes dans une *fonction de chemin d'accรจs* `def` normale, vous pouvez accรฉder directement ร  `UploadFile.file`, par exempleย : + +```Python +contents = myfile.file.read() +``` + +/// note | Dรฉtails techniques `async` + +Lorsque vous utilisez les mรฉthodes `async`, **FastAPI** exรฉcute les mรฉthodes de fichier dans un pool de threads et les attend. + +/// + +/// note | Dรฉtails techniques Starlette + +L'`UploadFile` de **FastAPI** hรฉrite directement de l'`UploadFile` de **Starlette**, mais ajoute certaines parties nรฉcessaires pour le rendre compatible avec **Pydantic** et les autres parties de FastAPI. + +/// + +## Qu'est-ce que les ยซ donnรฉes de formulaire ยป { #what-is-form-data } + +La faรงon dont les formulaires HTML (`
`) envoient les donnรฉes au serveur utilise normalement un encodage ยซ spรฉcial ยป pour ces donnรฉes, diffรฉrent de JSON. + +**FastAPI** s'assure de lire ces donnรฉes au bon endroit plutรดt que depuis JSON. + +/// note | Dรฉtails techniques + +Les donnรฉes des formulaires sont normalement encodรฉes avec le ยซ type de mรฉdia ยป `application/x-www-form-urlencoded` lorsqu'elles n'incluent pas de fichiers. + +Mais lorsque le formulaire inclut des fichiers, il est encodรฉ en `multipart/form-data`. Si vous utilisez `File`, **FastAPI** saura qu'il doit rรฉcupรฉrer les fichiers depuis la partie appropriรฉe du corps. + +Si vous souhaitez en savoir plus sur ces encodages et les champs de formulaire, consultez la MDN Web Docs pour POST. + +/// + +/// warning | Alertes + +Vous pouvez dรฉclarer plusieurs paramรจtres `File` et `Form` dans un *chemin d'accรจs*, mais vous ne pouvez pas รฉgalement dรฉclarer des champs `Body` que vous vous attendez ร  recevoir en JSON, car la requรชte aura le corps encodรฉ en `multipart/form-data` au lieu de `application/json`. + +Ce n'est pas une limitation de **FastAPI**, cela fait partie du protocole HTTP. + +/// + +## Tรฉlรฉversement de fichier facultatif { #optional-file-upload } + +Vous pouvez rendre un fichier facultatif en utilisant des annotations de type standard et en dรฉfinissant une valeur par dรฉfaut ร  `None`ย : + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## `UploadFile` avec des mรฉtadonnรฉes supplรฉmentaires { #uploadfile-with-additional-metadata } + +Vous pouvez aussi utiliser `File()` avec `UploadFile`, par exemple pour dรฉfinir des mรฉtadonnรฉes supplรฉmentairesย : + +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} + +## Tรฉlรฉverser plusieurs fichiers { #multiple-file-uploads } + +Il est possible de tรฉlรฉverser plusieurs fichiers en mรชme temps. + +Ils seraient associรฉs au mรชme ยซ champ de formulaire ยป envoyรฉ en ยซ donnรฉes de formulaire ยป. + +Pour cela, dรฉclarez une `list` de `bytes` ou d'`UploadFile`ย : + +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} + +Vous recevrez, comme dรฉclarรฉ, une `list` de `bytes` ou d'`UploadFile`. + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette.responses import HTMLResponse`. + +**FastAPI** fournit les mรชmes `starlette.responses` sous `fastapi.responses` simplement pour votre convenance en tant que dรฉveloppeur. Mais la plupart des rรฉponses disponibles proviennent directement de Starlette. + +/// + +### Tรฉlรฉversements multiples avec mรฉtadonnรฉes supplรฉmentaires { #multiple-file-uploads-with-additional-metadata } + +Et de la mรชme maniรจre que prรฉcรฉdemment, vous pouvez utiliser `File()` pour dรฉfinir des paramรจtres supplรฉmentaires, mรชme pour `UploadFile`ย : + +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} + +## Rรฉcapitulatif { #recap } + +Utilisez `File`, `bytes` et `UploadFile` pour dรฉclarer des fichiers ร  tรฉlรฉverser dans la requรชte, envoyรฉs en ยซ donnรฉes de formulaire ยป. diff --git a/docs/fr/docs/tutorial/request-form-models.md b/docs/fr/docs/tutorial/request-form-models.md new file mode 100644 index 0000000000..3fbac9c74a --- /dev/null +++ b/docs/fr/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Modรจles de formulaire { #form-models } + +Vous pouvez utiliser des **modรจles Pydantic** pour dรฉclarer des **champs de formulaire** dans FastAPI. + +/// info + +Pour utiliser les formulaires, installez d'abord `python-multipart`. + +Assurez-vous de crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer le paquet, par exemple : + +```console +$ pip install python-multipart +``` + +/// + +/// note | Remarque + +Ceci est pris en charge depuis la version `0.113.0` de FastAPI. ๐Ÿค“ + +/// + +## Modรจles Pydantic pour les formulaires { #pydantic-models-for-forms } + +Vous avez simplement besoin de dรฉclarer un **modรจle Pydantic** avec les champs que vous souhaitez recevoir comme **champs de formulaire**, puis de dรฉclarer le paramรจtre comme `Form` : + +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} + +**FastAPI** va **extraire** les donnรฉes pour **chaque champ** ร  partir des **donnรฉes de formulaire** de la requรชte et vous fournir le modรจle Pydantic que vous avez dรฉfini. + +## Consulter les documents { #check-the-docs } + +Vous pouvez le vรฉrifier dans l'interface des documents ร  `/docs` : + +
+ +
+ +## Interdire les champs de formulaire supplรฉmentaires { #forbid-extra-form-fields } + +Dans certains cas d'utilisation particuliers (probablement peu courants), vous pourriez vouloir **restreindre** les champs de formulaire ร  ceux dรฉclarรฉs dans le modรจle Pydantic, et **interdire** tout champ **supplรฉmentaire**. + +/// note | Remarque + +Ceci est pris en charge depuis la version `0.114.0` de FastAPI. ๐Ÿค“ + +/// + +Vous pouvez utiliser la configuration du modรจle Pydantic pour `forbid` tout champ `extra` : + +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} + +Si un client tente d'envoyer des donnรฉes supplรฉmentaires, il recevra une **rรฉponse d'erreur**. + +Par exemple, si le client essaie d'envoyer les champs de formulaire : + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +Il recevra une rรฉponse d'erreur lui indiquant que le champ `extra` n'est pas autorisรฉ : + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## Rรฉsumer { #summary } + +Vous pouvez utiliser des modรจles Pydantic pour dรฉclarer des champs de formulaire dans FastAPI. ๐Ÿ˜Ž diff --git a/docs/fr/docs/tutorial/request-forms-and-files.md b/docs/fr/docs/tutorial/request-forms-and-files.md new file mode 100644 index 0000000000..6774eec8e4 --- /dev/null +++ b/docs/fr/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# Utiliser des formulaires et des fichiers de requรชte { #request-forms-and-files } + +Vous pouvez dรฉfinir des fichiers et des champs de formulaire en mรชme temps ร  l'aide de `File` et `Form`. + +/// info + +Pour recevoir des fichiers tรฉlรฉversรฉs et/ou des donnรฉes de formulaire, installez d'abord `python-multipart`. + +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, l'activer, puis installer ce paquet, par exemple : + +```console +$ pip install python-multipart +``` + +/// + +## Importer `File` et `Form` { #import-file-and-form } + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} + +## Dรฉfinir des paramรจtres `File` et `Form` { #define-file-and-form-parameters } + +Crรฉez des paramรจtres de fichier et de formulaire de la mรชme maniรจre que pour `Body` ou `Query` : + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} + +Les fichiers et les champs de formulaire seront tรฉlรฉversรฉs en tant que donnรฉes de formulaire et vous les recevrez. + +Et vous pouvez dรฉclarer certains fichiers comme `bytes` et d'autres comme `UploadFile`. + +/// warning | Alertes + +Vous pouvez dรฉclarer plusieurs paramรจtres `File` et `Form` dans un *chemin d'accรจs*, mais vous ne pouvez pas aussi dรฉclarer des champs `Body` que vous vous attendez ร  recevoir en JSON, car la requรชte aura le corps encodรฉ en `multipart/form-data` au lieu de `application/json`. + +Ce n'est pas une limitation de **FastAPI**, cela fait partie du protocole HTTP. + +/// + +## Rรฉcapitulatif { #recap } + +Utilisez `File` et `Form` ensemble lorsque vous devez recevoir des donnรฉes et des fichiers dans la mรชme requรชte. diff --git a/docs/fr/docs/tutorial/request-forms.md b/docs/fr/docs/tutorial/request-forms.md new file mode 100644 index 0000000000..cea47c93e6 --- /dev/null +++ b/docs/fr/docs/tutorial/request-forms.md @@ -0,0 +1,73 @@ +# Donnรฉes de formulaire { #form-data } + +Lorsque vous devez recevoir des champs de formulaire au lieu de JSON, vous pouvez utiliser `Form`. + +/// info + +Pour utiliser les formulaires, installez d'abord `python-multipart`. + +Assurez-vous de crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer ce paquet, par exemple : + +```console +$ pip install python-multipart +``` + +/// + +## Importer `Form` { #import-form } + +Importez `Form` depuis `fastapi` : + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} + +## Dรฉfinir les paramรจtres `Form` { #define-form-parameters } + +Crรฉez des paramรจtres de formulaire comme vous le feriez pour `Body` ou `Query` : + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} + +Par exemple, dans l'une des maniรจres dont la spรฉcification OAuth2 peut รชtre utilisรฉe (appelรฉe ยซ password flow ยป), il est requis d'envoyer un `username` et un `password` comme champs de formulaire. + +La spรฉcification exige que les champs soient exactement nommรฉs `username` et `password`, et qu'ils soient envoyรฉs en tant que champs de formulaire, pas en JSON. + +Avec `Form`, vous pouvez dรฉclarer les mรชmes configurations que pour `Body` (ainsi que `Query`, `Path`, `Cookie`), y compris la validation, des exemples, un alias (p. ex. `user-name` au lieu de `username`), etc. + +/// info + +`Form` est une classe qui hรฉrite directement de `Body`. + +/// + +/// tip | Astuce + +Pour dรฉclarer des corps de formulaire, vous devez utiliser `Form` explicitement, car sinon les paramรจtres seraient interprรฉtรฉs comme des paramรจtres de requรชte ou des paramรจtres de corps (JSON). + +/// + +## ร€ propos des ยซ champs de formulaire ยป { #about-form-fields } + +La maniรจre dont les formulaires HTML (`
`) envoient les donnรฉes au serveur utilise normalement un encodage ยซ spรฉcial ยป pour ces donnรฉes, diffรฉrent de JSON. + +**FastAPI** s'assure de lire ces donnรฉes au bon endroit au lieu de JSON. + +/// note | Dรฉtails techniques + +Les donnรฉes issues des formulaires sont normalement encodรฉes avec le ยซ type de mรฉdia ยป `application/x-www-form-urlencoded`. + +Mais lorsque le formulaire inclut des fichiers, il est encodรฉ en `multipart/form-data`. Vous lirez la gestion des fichiers dans le chapitre suivant. + +Si vous voulez en savoir plus sur ces encodages et les champs de formulaire, consultez la MDN web docs pour POST. + +/// + +/// warning | Alertes + +Vous pouvez dรฉclarer plusieurs paramรจtres `Form` dans un chemin d'accรจs, mais vous ne pouvez pas aussi dรฉclarer des champs `Body` que vous vous attendez ร  recevoir en JSON, car la requรชte aura le corps encodรฉ en `application/x-www-form-urlencoded` au lieu de `application/json`. + +Ce n'est pas une limitation de **FastAPI**, cela fait partie du protocole HTTP. + +/// + +## Rรฉcapitulatif { #recap } + +Utilisez `Form` pour dรฉclarer les paramรจtres d'entrรฉe des donnรฉes de formulaire. diff --git a/docs/fr/docs/tutorial/response-model.md b/docs/fr/docs/tutorial/response-model.md new file mode 100644 index 0000000000..337b1aa485 --- /dev/null +++ b/docs/fr/docs/tutorial/response-model.md @@ -0,0 +1,343 @@ +# Modรจle de rรฉponse - Type de retour { #response-model-return-type } + +Vous pouvez dรฉclarer le type utilisรฉ pour la rรฉponse en annotant le **type de retour** de la *fonction de chemin d'accรจs*. + +Vous pouvez utiliser des **annotations de type** de la mรชme maniรจre que pour les donnรฉes d'entrรฉe dans les **paramรจtres** de fonction. Vous pouvez utiliser des modรจles Pydantic, des listes, des dictionnaires, des valeurs scalaires comme des entiers, des boolรฉens, etc. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI utilisera ce type de retour pour : + +* **Valider** les donnรฉes renvoyรฉes. + * Si les donnรฉes sont invalides (par exemple, il manque un champ), cela signifie que le code de *votre* application est dรฉfectueux, qu'il ne renvoie pas ce qu'il devrait, et un erreur serveur sera renvoyรฉe au lieu de renvoyer des donnรฉes incorrectes. De cette faรงon, vous et vos clients pouvez รชtre certains de recevoir les donnรฉes attendues et avec la structure attendue. +* Ajouter un **JSON Schema** pour la rรฉponse, dans lโ€™OpenAPI du *chemin d'accรจs*. + * Ceci sera utilisรฉ par la **documentation automatique**. + * Ceci sera รฉgalement utilisรฉ par les outils de gรฉnรฉration automatique de code client. + +Mais surtout : + +* Il **limitera et filtrera** les donnรฉes de sortie ร  ce qui est dรฉfini dans le type de retour. + * C'est particuliรจrement important pour la **sรฉcuritรฉ**, nous verrons cela plus bas. + +## Paramรจtre `response_model` { #response-model-parameter } + +Il existe des cas oรน vous devez ou souhaitez renvoyer des donnรฉes qui ne correspondent pas exactement ร  ce que dรฉclare le type. + +Par exemple, vous pourriez vouloir **renvoyer un dictionnaire** ou un objet de base de donnรฉes, mais **le dรฉclarer comme un modรจle Pydantic**. Ainsi, le modรจle Pydantic ferait toute la documentation des donnรฉes, la validation, etc. pour l'objet que vous avez renvoyรฉ (par exemple un dictionnaire ou un objet de base de donnรฉes). + +Si vous ajoutez l'annotation du type de retour, les outils et รฉditeurs se plaindront avec une (juste) erreur vous indiquant que votre fonction renvoie un type (par exemple un dict) diffรฉrent de ce que vous avez dรฉclarรฉ (par exemple un modรจle Pydantic). + +Dans ces cas, vous pouvez utiliser le paramรจtre `response_model` du *dรฉcorateur de chemin d'accรจs* au lieu du type de retour. + +Vous pouvez utiliser le paramรจtre `response_model` dans n'importe lequel des *chemins d'accรจs* : + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* etc. + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | Remarque + +Notez que `response_model` est un paramรจtre de la mรฉthode ยซ decorator ยป (`get`, `post`, etc.). Pas de votre *fonction de chemin d'accรจs*, comme tous les paramรจtres et le corps. + +/// + +`response_model` reรงoit le mรชme type que vous dรฉclareriez pour un champ de modรจle Pydantic, il peut donc s'agir d'un modรจle Pydantic, mais il peut aussi รชtre, par exemple, une `list` de modรจles Pydantic, comme `List[Item]`. + +FastAPI utilisera ce `response_model` pour toute la documentation des donnรฉes, la validation, etc. et aussi pour **convertir et filtrer les donnรฉes de sortie** selon sa dรฉclaration de type. + +/// tip | Astuce + +Si vous avez des vรฉrifications de type strictes dans votre รฉditeur, mypy, etc., vous pouvez dรฉclarer le type de retour de la fonction en `Any`. + +Ainsi, vous indiquez ร  l'รฉditeur que vous renvoyez intentionnellement n'importe quoi. Mais FastAPI effectuera quand mรชme la documentation, la validation, le filtrage, etc. des donnรฉes avec `response_model`. + +/// + +### Prioritรฉ de `response_model` { #response-model-priority } + +Si vous dรฉclarez ร  la fois un type de retour et un `response_model`, c'est `response_model` qui aura la prioritรฉ et sera utilisรฉ par FastAPI. + +De cette maniรจre, vous pouvez ajouter des annotations de type correctes ร  vos fonctions mรชme si vous renvoyez un type diffรฉrent du modรจle de rรฉponse, pour qu'il soit utilisรฉ par l'รฉditeur et des outils comme mypy. Et vous pouvez toujours laisser FastAPI faire la validation des donnรฉes, la documentation, etc. avec `response_model`. + +Vous pouvez รฉgalement utiliser `response_model=None` pour dรฉsactiver la crรฉation dโ€™un modรจle de rรฉponse pour ce *chemin d'accรจs* ; vous pourriez en avoir besoin si vous ajoutez des annotations de type pour des choses qui ne sont pas des champs valides Pydantic, vous verrez un exemple de cela dans une des sections ci-dessous. + +## Renvoyer les mรชmes donnรฉes d'entrรฉe { #return-the-same-input-data } + +Ici, nous dรฉclarons un modรจle `UserIn`, il contiendra un mot de passe en clair : + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// info | Info + +Pour utiliser `EmailStr`, installez d'abord `email-validator`. + +Assurez-vous de crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis de l'installer, par exemple : + +```console +$ pip install email-validator +``` + +ou avec : + +```console +$ pip install "pydantic[email]" +``` + +/// + +Et nous utilisons ce modรจle pour dรฉclarer notre entrรฉe et le mรชme modรจle pour dรฉclarer notre sortie : + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +Dรฉsormais, chaque fois qu'un navigateur crรฉe un utilisateur avec un mot de passe, l'API renverra le mรชme mot de passe dans la rรฉponse. + +Dans ce cas, cela peut ne pas poser de problรจme, car c'est le mรชme utilisateur qui envoie le mot de passe. + +Mais si nous utilisons le mรชme modรจle pour un autre *chemin d'accรจs*, nous pourrions envoyer les mots de passe de nos utilisateurs ร  tous les clients. + +/// danger | Danger + +Ne stockez jamais le mot de passe en clair d'un utilisateur et ne l'envoyez pas dans une rรฉponse de cette maniรจre, ร  moins de connaรฎtre tous les รฉcueils et de savoir exactement ce que vous faites. + +/// + +## Ajouter un modรจle de sortie { #add-an-output-model } + +Nous pouvons ร  la place crรฉer un modรจle d'entrรฉe avec le mot de passe en clair et un modรจle de sortie sans celui-ci : + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +Ici, mรชme si notre *fonction de chemin d'accรจs* renvoie le mรชme utilisateur d'entrรฉe qui contient le mot de passe : + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +... nous avons dรฉclarรฉ `response_model` comme รฉtant notre modรจle `UserOut`, qui n'inclut pas le mot de passe : + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +Ainsi, **FastAPI** se chargera de filtrer toutes les donnรฉes qui ne sont pas dรฉclarรฉes dans le modรจle de sortie (en utilisant Pydantic). + +### `response_model` ou type de retour { #response-model-or-return-type } + +Dans ce cas, comme les deux modรจles sont diffรฉrents, si nous annotions le type de retour de la fonction en `UserOut`, lโ€™รฉditeur et les outils se plaindraient que nous renvoyons un type invalide, car ce sont des classes diffรฉrentes. + +C'est pourquoi, dans cet exemple, nous devons le dรฉclarer dans le paramรจtre `response_model`. + +... mais continuez ร  lire ci-dessous pour voir comment contourner cela. + +## Type de retour et filtrage des donnรฉes { #return-type-and-data-filtering } + +Continuons l'exemple prรฉcรฉdent. Nous voulions **annoter la fonction avec un type**, mais nous voulions pouvoir renvoyer depuis la fonction quelque chose qui inclut **plus de donnรฉes**. + +Nous voulons que FastAPI continue de **filtrer** les donnรฉes ร  lโ€™aide du modรจle de rรฉponse. Ainsi, mรชme si la fonction renvoie plus de donnรฉes, la rรฉponse nโ€™inclura que les champs dรฉclarรฉs dans le modรจle de rรฉponse. + +Dans l'exemple prรฉcรฉdent, comme les classes รฉtaient diffรฉrentes, nous avons dรป utiliser le paramรจtre `response_model`. Mais cela signifie aussi que nous ne bรฉnรฉficions pas de la prise en charge de l'รฉditeur et des outils pour la vรฉrification du type de retour de la fonction. + +Mais dans la plupart des cas oรน nous avons besoin de quelque chose comme cela, nous voulons que le modรจle **filtre/supprime** simplement une partie des donnรฉes comme dans cet exemple. + +Et dans ces cas, nous pouvons utiliser des classes et l'hรฉritage pour tirer parti des **annotations de type** de fonction afin d'obtenir une meilleure prise en charge dans l'รฉditeur et les outils, tout en bรฉnรฉficiant du **filtrage de donnรฉes** de FastAPI. + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +Avec cela, nous obtenons la prise en charge des outils, des รฉditeurs et de mypy car ce code est correct en termes de types, et nous bรฉnรฉficions รฉgalement du filtrage des donnรฉes par FastAPI. + +Comment cela fonctionne-t-il ? Voyons cela. ๐Ÿค“ + +### Annotations de type et outils { #type-annotations-and-tooling } + +Voyons d'abord comment les รฉditeurs, mypy et autres outils considรจreraient cela. + +`BaseUser` a les champs de base. Puis `UserIn` hรฉrite de `BaseUser` et ajoute le champ `password`, il inclura donc tous les champs des deux modรจles. + +Nous annotons le type de retour de la fonction en `BaseUser`, mais nous renvoyons en rรฉalitรฉ une instance de `UserIn`. + +Lโ€™รฉditeur, mypy et d'autres outils ne sโ€™en plaindront pas car, en termes de typage, `UserIn` est une sous-classe de `BaseUser`, ce qui signifie que cโ€™est un type *valide* lorsque ce qui est attendu est n'importe quoi de type `BaseUser`. + +### Filtrage des donnรฉes par FastAPI { #fastapi-data-filtering } + +Maintenant, pour FastAPI, il verra le type de retour et s'assurera que ce que vous renvoyez inclut **uniquement** les champs qui sont dรฉclarรฉs dans le type. + +FastAPI fait plusieurs choses en interne avec Pydantic pour s'assurer que ces mรชmes rรจgles d'hรฉritage de classes ne sont pas utilisรฉes pour le filtrage des donnรฉes renvoyรฉes, sinon vous pourriez finir par renvoyer beaucoup plus de donnรฉes que prรฉvu. + +De cette faรงon, vous obtenez le meilleur des deux mondes : annotations de type avec **prise en charge par les outils** et **filtrage des donnรฉes**. + +## Le voir dans la documentation { #see-it-in-the-docs } + +Dans la documentation automatique, vous pouvez vรฉrifier que le modรจle d'entrรฉe et le modรจle de sortie auront chacun leur propre JSON Schema : + + + +Et les deux modรจles seront utilisรฉs pour la documentation API interactive : + + + +## Autres annotations de type de retour { #other-return-type-annotations } + +Il peut y avoir des cas oรน vous renvoyez quelque chose qui n'est pas un champ Pydantic valide et vous l'annotez dans la fonction, uniquement pour obtenir la prise en charge fournie par les outils (lโ€™รฉditeur, mypy, etc.). + +### Renvoyer directement une Response { #return-a-response-directly } + +Le cas le plus courant serait [de renvoyer directement une Response comme expliquรฉ plus loin dans la documentation avancรฉe](../advanced/response-directly.md){.internal-link target=_blank}. + +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} + +Ce cas simple est gรฉrรฉ automatiquement par FastAPI car l'annotation du type de retour est la classe (ou une sous-classe de) `Response`. + +Et les outils seront รฉgalement satisfaits car `RedirectResponse` et `JSONResponse` sont des sous-classes de `Response`, donc l'annotation de type est correcte. + +### Annoter une sous-classe de Response { #annotate-a-response-subclass } + +Vous pouvez aussi utiliser une sous-classe de `Response` dans l'annotation de type : + +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} + +Cela fonctionnera รฉgalement car `RedirectResponse` est une sous-classe de `Response`, et FastAPI gรฉrera automatiquement ce cas simple. + +### Annotations de type de retour invalides { #invalid-return-type-annotations } + +Mais lorsque vous renvoyez un autre objet arbitraire qui n'est pas un type Pydantic valide (par exemple un objet de base de donnรฉes) et que vous l'annotez ainsi dans la fonction, FastAPI essaiera de crรฉer un modรจle de rรฉponse Pydantic ร  partir de cette annotation de type, et รฉchouera. + +Il en serait de mรชme si vous aviez quelque chose comme une union entre diffรฉrents types dont un ou plusieurs ne sont pas des types Pydantic valides, par exemple ceci รฉchouerait ๐Ÿ’ฅ : + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +... cela รฉchoue parce que l'annotation de type n'est pas un type Pydantic et n'est pas juste une unique classe `Response` ou une sous-classe, c'est une union (l'un des deux) entre une `Response` et un `dict`. + +### Dรฉsactiver le modรจle de rรฉponse { #disable-response-model } + +En reprenant l'exemple ci-dessus, vous pourriez ne pas vouloir avoir la validation par dรฉfaut des donnรฉes, la documentation, le filtrage, etc. effectuรฉs par FastAPI. + +Mais vous pourriez vouloir tout de mรชme conserver lโ€™annotation du type de retour dans la fonction pour bรฉnรฉficier de la prise en charge des outils comme les รฉditeurs et les vรฉrificateurs de type (par exemple mypy). + +Dans ce cas, vous pouvez dรฉsactiver la gรฉnรฉration du modรจle de rรฉponse en dรฉfinissant `response_model=None` : + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +Cela fera en sorte que FastAPI ignore la gรฉnรฉration du modรจle de rรฉponse et vous permettra ainsi dโ€™avoir toutes les annotations de type de retour dont vous avez besoin sans que cela nโ€™affecte votre application FastAPI. ๐Ÿค“ + +## Paramรจtres d'encodage du modรจle de rรฉponse { #response-model-encoding-parameters } + +Votre modรจle de rรฉponse peut avoir des valeurs par dรฉfaut, par exemple : + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (ou `str | None = None` en Python 3.10) a une valeur par dรฉfaut `None`. +* `tax: float = 10.5` a une valeur par dรฉfaut `10.5`. +* `tags: List[str] = []` a une valeur par dรฉfaut de liste vide : `[]`. + +mais vous pourriez vouloir les omettre du rรฉsultat si elles n'ont pas รฉtรฉ rรฉellement stockรฉes. + +Par exemple, si vous avez des modรจles avec de nombreux attributs optionnels dans une base NoSQL, mais que vous ne voulez pas envoyer de trรจs longues rรฉponses JSON remplies de valeurs par dรฉfaut. + +### Utiliser le paramรจtre `response_model_exclude_unset` { #use-the-response-model-exclude-unset-parameter } + +Vous pouvez dรฉfinir le paramรจtre du *dรฉcorateur de chemin d'accรจs* `response_model_exclude_unset=True` : + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +et ces valeurs par dรฉfaut ne seront pas incluses dans la rรฉponse, uniquement les valeurs effectivement dรฉfinies. + +Ainsi, si vous envoyez une requรชte ร  ce *chemin d'accรจs* pour l'article avec l'ID `foo`, la rรฉponse (sans les valeurs par dรฉfaut) sera : + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// info | Info + +Vous pouvez รฉgalement utiliser : + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +comme dรฉcrit dans la documentation Pydantic pour `exclude_defaults` et `exclude_none`. + +/// + +#### Donnรฉes avec des valeurs pour des champs avec des valeurs par dรฉfaut { #data-with-values-for-fields-with-defaults } + +Mais si vos donnรฉes ont des valeurs pour les champs du modรจle avec des valeurs par dรฉfaut, comme l'article avec l'ID `bar` : + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` + +elles seront incluses dans la rรฉponse. + +#### Donnรฉes avec les mรชmes valeurs que les valeurs par dรฉfaut { #data-with-the-same-values-as-the-defaults } + +Si les donnรฉes ont les mรชmes valeurs que les valeurs par dรฉfaut, comme l'article avec l'ID `baz` : + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI est suffisamment intelligent (en fait, Pydantic lโ€™est) pour comprendre que, mรชme si `description`, `tax` et `tags` ont les mรชmes valeurs que les valeurs par dรฉfaut, elles ont รฉtรฉ dรฉfinies explicitement (au lieu d'รชtre prises depuis les valeurs par dรฉfaut). + +Elles seront donc incluses dans la rรฉponse JSON. + +/// tip | Astuce + +Notez que les valeurs par dรฉfaut peuvent รชtre n'importe quoi, pas seulement `None`. + +Elles peuvent รชtre une liste (`[]`), un `float` de `10.5`, etc. + +/// + +### `response_model_include` et `response_model_exclude` { #response-model-include-and-response-model-exclude } + +Vous pouvez รฉgalement utiliser les paramรจtres du *dรฉcorateur de chemin d'accรจs* `response_model_include` et `response_model_exclude`. + +Ils prennent un `set` de `str` avec les noms des attributs ร  inclure (en omettant le reste) ou ร  exclure (en incluant le reste). + +Cela peut รชtre utilisรฉ comme un raccourci rapide si vous n'avez qu'un seul modรจle Pydantic et que vous souhaitez supprimer certaines donnรฉes de la sortie. + +/// tip | Astuce + +Mais il est toujours recommandรฉ d'utiliser les idรฉes ci-dessus, en utilisant plusieurs classes, plutรดt que ces paramรจtres. + +En effet, le JSON Schema gรฉnรฉrรฉ dans lโ€™OpenAPI de votre application (et la documentation) restera celui du modรจle complet, mรชme si vous utilisez `response_model_include` ou `response_model_exclude` pour omettre certains attributs. + +Cela s'applique รฉgalement ร  `response_model_by_alias` qui fonctionne de maniรจre similaire. + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | Astuce + +La syntaxe `{"name", "description"}` crรฉe un `set` avec ces deux valeurs. + +Elle est รฉquivalente ร  `set(["name", "description"])`. + +/// + +#### Utiliser des `list` au lieu de `set` { #using-lists-instead-of-sets } + +Si vous oubliez d'utiliser un `set` et utilisez une `list` ou un `tuple` ร  la place, FastAPI le convertira quand mรชme en `set` et cela fonctionnera correctement : + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## Rรฉcapitulatif { #recap } + +Utilisez le paramรจtre du *dรฉcorateur de chemin d'accรจs* `response_model` pour dรฉfinir les modรจles de rรฉponse et surtout pour garantir que les donnรฉes privรฉes sont filtrรฉes. + +Utilisez `response_model_exclude_unset` pour ne renvoyer que les valeurs dรฉfinies explicitement. diff --git a/docs/fr/docs/tutorial/response-status-code.md b/docs/fr/docs/tutorial/response-status-code.md new file mode 100644 index 0000000000..388a53b3df --- /dev/null +++ b/docs/fr/docs/tutorial/response-status-code.md @@ -0,0 +1,101 @@ +# Code d'รฉtat de la rรฉponse { #response-status-code } + +De la mรชme maniรจre que vous pouvez spรฉcifier un modรจle de rรฉponse, vous pouvez รฉgalement dรฉclarer le code d'รฉtat HTTP utilisรฉ pour la rรฉponse avec le paramรจtre `status_code` dans n'importe lequel des chemins d'accรจs : + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* etc. + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +/// note | Remarque + +Remarquez que `status_code` est un paramรจtre de la mรฉthode ยซ decorator ยป (`get`, `post`, etc.). Pas de votre fonction de chemin d'accรจs, comme tous les paramรจtres et le corps. + +/// + +Le paramรจtre `status_code` reรงoit un nombre correspondant au code d'รฉtat HTTP. + +/// info + +`status_code` peut aussi recevoir un `IntEnum`, comme le `http.HTTPStatus` de Python. + +/// + +Il va : + +* Renvoyer ce code d'รฉtat dans la rรฉponse. +* Le documenter comme tel dans le schรฉma OpenAPI (et donc dans les interfaces utilisateur) : + + + +/// note | Remarque + +Certains codes de rรฉponse (voir la section suivante) indiquent que la rรฉponse n'a pas de corps. + +FastAPI le sait et produira une documentation OpenAPI indiquant qu'il n'y a pas de corps de rรฉponse. + +/// + +## ร€ propos des codes d'รฉtat HTTP { #about-http-status-codes } + +/// note | Remarque + +Si vous savez dรฉjร  ce que sont les codes d'รฉtat HTTP, passez ร  la section suivante. + +/// + +En HTTP, vous envoyez un code d'รฉtat numรฉrique de 3 chiffres dans la rรฉponse. + +Ces codes d'รฉtat ont un nom associรฉ pour les reconnaรฎtre, mais la partie importante est le nombre. + +En bref : + +* `100 - 199` sont pour ยซ Information ยป. Vous les utilisez rarement directement. Les rรฉponses avec ces codes d'รฉtat ne peuvent pas avoir de corps. +* **`200 - 299`** sont pour les rรฉponses de ยซ Succรจs ยป. Ce sont celles que vous utiliserez le plus. + * `200` est le code d'รฉtat par dรฉfaut, ce qui signifie que tout รฉtait ยซ OK ยป. + * Un autre exemple est `201`, ยซ Crรฉรฉ ยป. Il est couramment utilisรฉ aprรจs la crรฉation d'un nouvel enregistrement dans la base de donnรฉes. + * Un cas particulier est `204`, ยซ Aucun contenu ยป. Cette rรฉponse est utilisรฉe lorsqu'il n'y a aucun contenu ร  renvoyer au client ; la rรฉponse ne doit donc pas avoir de corps. +* **`300 - 399`** sont pour la ยซ Redirection ยป. Les rรฉponses avec ces codes d'รฉtat peuvent avoir ou non un corps, sauf `304`, ยซ Non modifiรฉ ยป, qui ne doit pas en avoir. +* **`400 - 499`** sont pour les rรฉponses d'ยซ Erreur cรดtรฉ client ยป. C'est probablement le deuxiรจme type que vous utiliserez le plus. + * Un exemple est `404`, pour une rรฉponse ยซ Non trouvรฉ ยป. + * Pour des erreurs gรฉnรฉriques du client, vous pouvez simplement utiliser `400`. +* `500 - 599` sont pour les erreurs cรดtรฉ serveur. Vous ne les utilisez presque jamais directement. Lorsqu'un problรจme survient quelque part dans le code de votre application ou sur le serveur, il renverra automatiquement l'un de ces codes d'รฉtat. + +/// tip | Astuce + +Pour en savoir plus sur chaque code d'รฉtat et ร  quoi il correspond, consultez la MDN documentation about HTTP status codes. + +/// + +## Raccourci pour se souvenir des noms { #shortcut-to-remember-the-names } + +Reprenons l'exemple prรฉcรฉdent : + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +`201` est le code d'รฉtat pour ยซ Crรฉรฉ ยป. + +Mais vous n'avez pas ร  mรฉmoriser la signification de chacun de ces codes. + +Vous pouvez utiliser les variables pratiques de `fastapi.status`. + +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} + +Elles ne sont qu'une commoditรฉ, elles contiennent le mรชme nombre, mais de cette faรงon vous pouvez utiliser l'autocomplรฉtion de l'รฉditeur pour les trouver : + + + +/// note | Dรฉtails techniques + +Vous pourriez aussi utiliser `from starlette import status`. + +FastAPI fournit le mรชme `starlette.status` que `fastapi.status`, uniquement pour votre commoditรฉ de dรฉveloppeur. Mais cela vient directement de Starlette. + +/// + +## Modifier la valeur par dรฉfaut { #changing-the-default } + +Plus tard, dans le [Guide utilisateur avancรฉ](../advanced/response-change-status-code.md){.internal-link target=_blank}, vous verrez comment renvoyer un code d'รฉtat diffรฉrent de celui par dรฉfaut que vous dรฉclarez ici. diff --git a/docs/fr/docs/tutorial/schema-extra-example.md b/docs/fr/docs/tutorial/schema-extra-example.md new file mode 100644 index 0000000000..d4403c779b --- /dev/null +++ b/docs/fr/docs/tutorial/schema-extra-example.md @@ -0,0 +1,202 @@ +# Dรฉclarer des exemples de donnรฉes de requรชte { #declare-request-example-data } + +Vous pouvez dรฉclarer des exemples des donnรฉes que votre application peut recevoir. + +Voici plusieurs faรงons de le faire. + +## Ajouter des donnรฉes JSON Schema supplรฉmentaires dans les modรจles Pydantic { #extra-json-schema-data-in-pydantic-models } + +Vous pouvez dรฉclarer `examples` pour un modรจle Pydantic qui seront ajoutรฉs au JSON Schema gรฉnรฉrรฉ. + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +Ces informations supplรฉmentaires seront ajoutรฉes telles quelles au **JSON Schema** de sortie pour ce modรจle, et elles seront utilisรฉes dans la documentation de l'API. + +Vous pouvez utiliser l'attribut `model_config` qui accepte un `dict` comme dรฉcrit dans Documentation de Pydantic : Configuration. + +Vous pouvez dรฉfinir `"json_schema_extra"` avec un `dict` contenant toutes les donnรฉes supplรฉmentaires que vous souhaitez voir apparaรฎtre dans le JSON Schema gรฉnรฉrรฉ, y compris `examples`. + +/// tip | Astuce + +Vous pouvez utiliser la mรชme technique pour รฉtendre le JSON Schema et ajouter vos propres informations supplรฉmentaires personnalisรฉes. + +Par exemple, vous pourriez l'utiliser pour ajouter des mรฉtadonnรฉes pour une interface utilisateur frontend, etc. + +/// + +/// info + +OpenAPI 3.1.0 (utilisรฉ depuis FastAPI 0.99.0) a ajoutรฉ la prise en charge de `examples`, qui fait partie du standard **JSON Schema**. + +Avant cela, seule la clรฉ `example` avec un exemple unique รฉtait prise en charge. Elle l'est toujours par OpenAPI 3.1.0, mais elle est dรฉprรฉciรฉe et ne fait pas partie du standard JSON Schema. Vous รชtes donc encouragรฉ ร  migrer de `example` vers `examples`. ๐Ÿค“ + +Vous pouvez en lire davantage ร  la fin de cette page. + +/// + +## Arguments supplรฉmentaires de `Field` { #field-additional-arguments } + +Lorsque vous utilisez `Field()` avec des modรจles Pydantic, vous pouvez รฉgalement dรฉclarer des `examples` supplรฉmentaires : + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## `examples` dans JSON Schema - OpenAPI { #examples-in-json-schema-openapi } + +En utilisant l'un des รฉlรฉments suivants : + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +vous pouvez รฉgalement dรฉclarer un groupe de `examples` avec des informations supplรฉmentaires qui seront ajoutรฉes ร  leurs **JSON Schemas** ร  l'intรฉrieur d'**OpenAPI**. + +### `Body` avec `examples` { #body-with-examples } + +Ici, nous passons `examples` contenant un exemple des donnรฉes attendues dans `Body()` : + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### Exemple dans l'interface des documents { #example-in-the-docs-ui } + +Avec l'une des mรฉthodes ci-dessus, cela ressemblerait ร  ceci dans le `/docs` : + + + +### `Body` avec plusieurs `examples` { #body-with-multiple-examples } + +Vous pouvez bien sรปr aussi passer plusieurs `examples` : + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +Lorsque vous faites cela, les exemples feront partie du **JSON Schema** interne pour ces donnรฉes de corps. + +Nรฉanmoins, au moment de la rรฉdaction, Swagger UI, l'outil chargรฉ d'afficher l'interface des documents, ne prend pas en charge l'affichage de plusieurs exemples pour les donnรฉes dans **JSON Schema**. Mais lisez ci-dessous pour un contournement. + +### `examples` spรฉcifiques ร  OpenAPI { #openapi-specific-examples } + +Avant que **JSON Schema** ne prenne en charge `examples`, OpenAPI prenait dรฉjร  en charge un autre champ รฉgalement appelรฉ `examples`. + +Ce `examples` **spรฉcifique ร  OpenAPI** se trouve dans une autre section de la spรฉcification OpenAPI. Il se trouve dans les **dรฉtails de chaque *chemin d'accรจs***, et non ร  l'intรฉrieur de chaque JSON Schema. + +Et Swagger UI prend en charge ce champ particulier `examples` depuis un certain temps. Vous pouvez donc l'utiliser pour **afficher** diffรฉrents **exemples dans l'interface des documents**. + +La forme de ce champ `examples` spรฉcifique ร  OpenAPI est un `dict` avec **plusieurs exemples** (au lieu d'une `list`), chacun avec des informations supplรฉmentaires qui seront รฉgalement ajoutรฉes ร  **OpenAPI**. + +Cela ne va pas ร  l'intรฉrieur de chaque JSON Schema contenu dans OpenAPI, cela se place ร  l'extรฉrieur, directement dans le *chemin d'accรจs*. + +### Utiliser le paramรจtre `openapi_examples` { #using-the-openapi-examples-parameter } + +Vous pouvez dรฉclarer le `examples` spรฉcifique ร  OpenAPI dans FastAPI avec le paramรจtre `openapi_examples` pour : + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +Les clรฉs du `dict` identifient chaque exemple, et chaque valeur est un autre `dict`. + +Chaque `dict` d'exemple spรฉcifique dans `examples` peut contenir : + +* `summary` : une courte description de l'exemple. +* `description` : une description longue qui peut contenir du texte Markdown. +* `value` : c'est l'exemple rรฉel affichรฉ, par ex. un `dict`. +* `externalValue` : alternative ร  `value`, une URL pointant vers l'exemple. Cependant, cela pourrait ne pas รชtre pris en charge par autant d'outils que `value`. + +Vous pouvez l'utiliser ainsi : + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### Exemples OpenAPI dans l'interface des documents { #openapi-examples-in-the-docs-ui } + +Avec `openapi_examples` ajoutรฉ ร  `Body()`, le `/docs` ressemblerait ร  : + + + +## Dรฉtails techniques { #technical-details } + +/// tip | Astuce + +Si vous utilisez dรฉjร  **FastAPI** en version **0.99.0 ou supรฉrieure**, vous pouvez probablement **passer** ces dรฉtails. + +Ils sont plus pertinents pour les versions plus anciennes, avant que OpenAPI 3.1.0 ne soit disponible. + +Vous pouvez considรฉrer ceci comme une courte leรงon d'histoire d'OpenAPI et de JSON Schema. ๐Ÿค“ + +/// + +/// warning | Alertes + +Ce sont des dรฉtails trรจs techniques au sujet des standards **JSON Schema** et **OpenAPI**. + +Si les idรฉes ci-dessus fonctionnent dรฉjร  pour vous, cela pourrait suffire, et vous n'avez probablement pas besoin de ces dรฉtails, n'hรฉsitez pas ร  les ignorer. + +/// + +Avant OpenAPI 3.1.0, OpenAPI utilisait une version plus ancienne et modifiรฉe de **JSON Schema**. + +JSON Schema n'avait pas `examples`, donc OpenAPI a ajoutรฉ son propre champ `example` ร  sa version modifiรฉe. + +OpenAPI a รฉgalement ajoutรฉ les champs `example` et `examples` ร  d'autres parties de la spรฉcification : + +* `Parameter Object` (dans la spรฉcification) qui รฉtait utilisรฉ par les รฉlรฉments FastAPI : + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`, dans le champ `content`, sur le `Media Type Object` (dans la spรฉcification) qui รฉtait utilisรฉ par les รฉlรฉments FastAPI : + * `Body()` + * `File()` + * `Form()` + +/// info + +Ce paramรจtre `examples` ancien et spรฉcifique ร  OpenAPI est dรฉsormais `openapi_examples` depuis FastAPI `0.103.0`. + +/// + +### Le champ `examples` de JSON Schema { #json-schemas-examples-field } + +Ensuite, JSON Schema a ajoutรฉ un champ `examples` dans une nouvelle version de la spรฉcification. + +Puis le nouveau OpenAPI 3.1.0 s'est basรฉ sur la derniรจre version (JSON Schema 2020-12) qui incluait ce nouveau champ `examples`. + +Et dรฉsormais, ce nouveau champ `examples` a prioritรฉ sur l'ancien champ unique (et personnalisรฉ) `example`, qui est maintenant dรฉprรฉciรฉ. + +Ce nouveau champ `examples` dans JSON Schema est **juste une `list`** d'exemples, et non pas un dict avec des mรฉtadonnรฉes supplรฉmentaires comme dans les autres endroits d'OpenAPI (dรฉcrits ci-dessus). + +/// info + +Mรชme aprรจs la sortie d'OpenAPI 3.1.0 avec cette nouvelle intรฉgration plus simple avec JSON Schema, pendant un temps, Swagger UI, l'outil qui fournit la documentation automatique, ne prenait pas en charge OpenAPI 3.1.0 (il le fait depuis la version 5.0.0 ๐ŸŽ‰). + +ร€ cause de cela, les versions de FastAPI antรฉrieures ร  0.99.0 utilisaient encore des versions d'OpenAPI infรฉrieures ร  3.1.0. + +/// + +### `examples` avec Pydantic et FastAPI { #pydantic-and-fastapi-examples } + +Lorsque vous ajoutez `examples` dans un modรจle Pydantic, en utilisant `schema_extra` ou `Field(examples=["something"])`, cet exemple est ajoutรฉ au **JSON Schema** de ce modรจle Pydantic. + +Et ce **JSON Schema** du modรจle Pydantic est inclus dans l'**OpenAPI** de votre API, puis il est utilisรฉ dans l'interface de la documentation. + +Dans les versions de FastAPI antรฉrieures ร  0.99.0 (0.99.0 et supรฉrieures utilisent le nouveau OpenAPI 3.1.0), lorsque vous utilisiez `example` ou `examples` avec l'une des autres utilitaires (`Query()`, `Body()`, etc.), ces exemples n'รฉtaient pas ajoutรฉs au JSON Schema qui dรฉcrit ces donnรฉes (pas mรชme ร  la version de JSON Schema propre ร  OpenAPI), ils รฉtaient ajoutรฉs directement ร  la dรฉclaration du *chemin d'accรจs* dans OpenAPI (en dehors des parties d'OpenAPI qui utilisent JSON Schema). + +Mais maintenant que FastAPI 0.99.0 et supรฉrieures utilisent OpenAPI 3.1.0, qui utilise JSON Schema 2020-12, et Swagger UI 5.0.0 et supรฉrieures, tout est plus cohรฉrent et les exemples sont inclus dans JSON Schema. + +### Swagger UI et `examples` spรฉcifiques ร  OpenAPI { #swagger-ui-and-openapi-specific-examples } + +Comme Swagger UI ne prenait pas en charge plusieurs exemples JSON Schema (au 2023-08-26), les utilisateurs n'avaient pas de moyen d'afficher plusieurs exemples dans les documents. + +Pour rรฉsoudre cela, FastAPI `0.103.0` a **ajoutรฉ la prise en charge** de la dรฉclaration du mรชme ancien champ `examples` **spรฉcifique ร  OpenAPI** avec le nouveau paramรจtre `openapi_examples`. ๐Ÿค“ + +### Rรฉsumรฉ { #summary } + +Je disais que je n'aimais pas trop l'histoire ... et me voilร  maintenant ร  donner des leรงons d'ยซ tech history ยป. ๐Ÿ˜… + +En bref, **mettez ร  niveau vers FastAPI 0.99.0 ou supรฉrieur**, et les choses sont bien plus **simples, cohรฉrentes et intuitives**, et vous n'avez pas besoin de connaรฎtre tous ces dรฉtails historiques. ๐Ÿ˜Ž diff --git a/docs/fr/docs/tutorial/security/first-steps.md b/docs/fr/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000..8c4eb50d76 --- /dev/null +++ b/docs/fr/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# Sรฉcuritรฉ - Premiers pas { #security-first-steps } + +Imaginons que vous ayez votre API de **backend** sur un certain domaine. + +Et vous avez un **frontend** sur un autre domaine ou dans un chemin diffรฉrent du mรชme domaine (ou dans une application mobile). + +Et vous voulez que le **frontend** puisse s'authentifier auprรจs du **backend**, en utilisant un **username** et un **password**. + +Nous pouvons utiliser **OAuth2** pour construire cela avec **FastAPI**. + +Mais รฉpargnons-vous le temps de lire toute la spรฉcification complรจte juste pour trouver les petites informations dont vous avez besoin. + +Utilisons les outils fournis par **FastAPI** pour gรฉrer la sรฉcuritรฉ. + +## Voir ร  quoi cela ressemble { #how-it-looks } + +Commenรงons par utiliser le code et voir comment cela fonctionne, puis nous reviendrons pour comprendre ce qui se passe. + +## Crรฉer `main.py` { #create-main-py } + +Copiez l'exemple dans un fichier `main.py` : + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## Exรฉcuter { #run-it } + +/// info + +Le package `python-multipart` est installรฉ automatiquement avec **FastAPI** lorsque vous exรฉcutez la commande `pip install "fastapi[standard]"`. + +Cependant, si vous utilisez la commande `pip install fastapi`, le package `python-multipart` n'est pas inclus par dรฉfaut. + +Pour l'installer manuellement, vous devez vous assurer de crรฉer un [environnement virtuel](../../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis de l'installer avecย : + +```console +$ pip install python-multipart +``` + +Cela est dรป au fait que **OAuth2** utilise des ยซ form data ยป pour envoyer le `username` et le `password`. + +/// + +Exรฉcutez l'exemple avecย : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## Vรฉrifier { #check-it } + +Allez ร  la documentation interactive ร  l'adresseย : http://127.0.0.1:8000/docs. + +Vous verrez quelque chose comme ceciย : + + + +/// check | Bouton ยซ Authorize ยป ! + +Vous avez dรฉjร  un tout nouveau bouton ยซ Authorize ยป. + +Et votre *chemin d'accรจs* a un petit cadenas dans le coin supรฉrieur droit sur lequel vous pouvez cliquer. + +/// + +Et si vous cliquez dessus, vous obtenez un petit formulaire d'autorisation pour saisir un `username` et un `password` (et d'autres champs optionnels)ย : + + + +/// note | Remarque + +Peu importe ce que vous saisissez dans le formulaire, cela ne fonctionnera pas encore. Mais nous y viendrons. + +/// + +Ce n'est bien sรปr pas le frontend pour les utilisateurs finaux, mais c'est un excellent outil automatique pour documenter de maniรจre interactive toute votre API. + +Il peut รชtre utilisรฉ par l'รฉquipe frontend (qui peut aussi รชtre vous-mรชme). + +Il peut รชtre utilisรฉ par des applications et des systรจmes tiers. + +Et il peut aussi รชtre utilisรฉ par vous-mรชme, pour dรฉboguer, vรฉrifier et tester la mรชme application. + +## Le flux `password` { #the-password-flow } + +Revenons un peu en arriรจre et comprenons de quoi il s'agit. + +Le ยซ flux ยป `password` est l'une des maniรจres (ยซ flows ยป) dรฉfinies dans OAuth2 pour gรฉrer la sรฉcuritรฉ et l'authentification. + +OAuth2 a รฉtรฉ conรงu pour que le backend ou l'API puisse รชtre indรฉpendant du serveur qui authentifie l'utilisateur. + +Mais dans ce cas, la mรชme application **FastAPI** gรฉrera l'API et l'authentification. + +Voyons cela selon ce point de vue simplifiรฉย : + +- L'utilisateur saisit le `username` et le `password` dans le frontend, puis appuie sur Entrรฉe. +- Le frontend (exรฉcutรฉ dans le navigateur de l'utilisateur) envoie ce `username` et ce `password` vers une URL spรฉcifique de notre API (dรฉclarรฉe avec `tokenUrl="token"`). +- L'API vรฉrifie ce `username` et ce `password`, et rรฉpond avec un ยซ token ยป (nous n'avons encore rien implรฉmentรฉ de tout cela). + - Un ยซ token ยป n'est qu'une chaรฎne contenant des informations que nous pouvons utiliser plus tard pour vรฉrifier cet utilisateur. + - Normalement, un token est configurรฉ pour expirer aprรจs un certain temps. + - Ainsi, l'utilisateur devra se reconnecter ร  un moment donnรฉ. + - Et si le token est volรฉ, le risque est moindre. Ce n'est pas une clรฉ permanente qui fonctionnerait indรฉfiniment (dans la plupart des cas). +- Le frontend stocke ce token temporairement quelque part. +- L'utilisateur clique dans le frontend pour aller vers une autre section de l'application web frontend. +- Le frontend doit rรฉcupรฉrer d'autres donnรฉes depuis l'API. + - Mais cela nรฉcessite une authentification pour cet endpoint spรฉcifique. + - Donc, pour s'authentifier auprรจs de notre API, il envoie un en-tรชte `Authorization` avec une valeur `Bearer ` suivie du token. + - Si le token contient `foobar`, le contenu de l'en-tรชte `Authorization` seraitย : `Bearer foobar`. + +## Le `OAuth2PasswordBearer` de **FastAPI** { #fastapis-oauth2passwordbearer } + +**FastAPI** fournit plusieurs outils, ร  diffรฉrents niveaux d'abstraction, pour implรฉmenter ces fonctionnalitรฉs de sรฉcuritรฉ. + +Dans cet exemple, nous allons utiliser **OAuth2**, avec le flux **Password**, en utilisant un token **Bearer**. Nous le faisons avec la classe `OAuth2PasswordBearer`. + +/// info + +Un token ยซ bearer ยป n'est pas la seule option. + +Mais c'est la meilleure pour notre cas d'utilisation. + +Et cela pourrait รชtre la meilleure pour la plupart des cas, sauf si vous รชtes expert en OAuth2 et savez exactement pourquoi une autre option convient mieux ร  vos besoins. + +Dans ce cas, **FastAPI** vous fournit aussi les outils pour la construire. + +/// + +Lorsque nous crรฉons une instance de la classe `OAuth2PasswordBearer`, nous passons le paramรจtre `tokenUrl`. Ce paramรจtre contient l'URL que le client (le frontend s'exรฉcutant dans le navigateur de l'utilisateur) utilisera pour envoyer le `username` et le `password` afin d'obtenir un token. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip | Astuce + +Ici `tokenUrl="token"` fait rรฉfรฉrence ร  une URL relative `token` que nous n'avons pas encore crรฉรฉe. Comme c'est une URL relative, elle est รฉquivalente ร  `./token`. + +Parce que nous utilisons une URL relative, si votre API se trouvait ร  `https://example.com/`, alors elle ferait rรฉfรฉrence ร  `https://example.com/token`. Mais si votre API se trouvait ร  `https://example.com/api/v1/`, alors elle ferait rรฉfรฉrence ร  `https://example.com/api/v1/token`. + +Utiliser une URL relative est important pour vous assurer que votre application continue de fonctionner mรชme dans un cas d'usage avancรฉ comme [Derriรจre un proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}. + +/// + +Ce paramรจtre ne crรฉe pas cet endpoint / *chemin d'accรจs*, mais dรฉclare que l'URL `/token` sera celle que le client doit utiliser pour obtenir le token. Cette information est utilisรฉe dans OpenAPI, puis dans les systรจmes de documentation API interactifs. + +Nous crรฉerons bientรดt aussi le vรฉritable chemin d'accรจs. + +/// info + +Si vous รชtes un ยซ Pythonista ยป trรจs strict, vous pourriez ne pas apprรฉcier le style du nom de paramรจtre `tokenUrl` au lieu de `token_url`. + +C'est parce qu'il utilise le mรชme nom que dans la spรฉcification OpenAPI. Ainsi, si vous devez approfondir l'un de ces schรฉmas de sรฉcuritรฉ, vous pouvez simplement copier-coller pour trouver plus d'informations ร  ce sujet. + +/// + +La variable `oauth2_scheme` est une instance de `OAuth2PasswordBearer`, mais c'est aussi un ยซ callable ยป. + +Elle pourrait รชtre appelรฉe ainsiย : + +```Python +oauth2_scheme(some, parameters) +``` + +Ainsi, elle peut รชtre utilisรฉe avec `Depends`. + +### Utiliser { #use-it } + +Vous pouvez maintenant passer ce `oauth2_scheme` en dรฉpendance avec `Depends`. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +Cette dรฉpendance fournira une `str` qui est affectรฉe au paramรจtre `token` de la fonction de *chemin d'accรจs*. + +**FastAPI** saura qu'il peut utiliser cette dรฉpendance pour dรฉfinir un ยซ schรฉma de sรฉcuritรฉ ยป dans le schรฉma OpenAPI (et la documentation API automatique). + +/// info | Dรฉtails techniques + +**FastAPI** saura qu'il peut utiliser la classe `OAuth2PasswordBearer` (dรฉclarรฉe dans une dรฉpendance) pour dรฉfinir le schรฉma de sรฉcuritรฉ dans OpenAPI parce qu'elle hรฉrite de `fastapi.security.oauth2.OAuth2`, qui hรฉrite ร  son tour de `fastapi.security.base.SecurityBase`. + +Tous les utilitaires de sรฉcuritรฉ qui s'intรจgrent ร  OpenAPI (et ร  la documentation API automatique) hรฉritent de `SecurityBase`, c'est ainsi que **FastAPI** sait comment les intรฉgrer dans OpenAPI. + +/// + +## Ce que cela fait { #what-it-does } + +Il va chercher dans la requรชte cet en-tรชte `Authorization`, vรฉrifier si la valeur est `Bearer ` plus un token, et renverra le token en tant que `str`. + +S'il ne voit pas d'en-tรชte `Authorization`, ou si la valeur n'a pas de token `Bearer `, il rรฉpondra directement avec une erreur de code d'รฉtat 401 (`UNAUTHORIZED`). + +Vous n'avez mรชme pas ร  vรฉrifier si le token existe pour renvoyer une erreur. Vous pouvez รชtre sรปr que si votre fonction est exรฉcutรฉe, elle aura une `str` dans ce token. + +Vous pouvez dรฉjร  l'essayer dans la documentation interactiveย : + + + +Nous ne vรฉrifions pas encore la validitรฉ du token, mais c'est dรฉjร  un dรฉbut. + +## Rรฉcapitulatif { #recap } + +Ainsi, en seulement 3 ou 4 lignes supplรฉmentaires, vous disposez dรฉjร  d'une forme primitive de sรฉcuritรฉ. diff --git a/docs/fr/docs/tutorial/security/get-current-user.md b/docs/fr/docs/tutorial/security/get-current-user.md new file mode 100644 index 0000000000..5f73efea9c --- /dev/null +++ b/docs/fr/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# Obtenir l'utilisateur actuel { #get-current-user } + +Dans le chapitre prรฉcรฉdent, le systรจme de sรฉcuritรฉ (basรฉ sur le systรจme d'injection de dรฉpendances) fournissait ร  la *fonction de chemin d'accรจs* un `token` en tant que `str` : + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +Mais ce n'est pas encore trรจs utile. + +Faisons en sorte qu'il nous fournisse l'utilisateur actuel. + +## Crรฉer un modรจle d'utilisateur { #create-a-user-model } + +Commenรงons par crรฉer un modรจle d'utilisateur Pydantic. + +De la mรชme maniรจre que nous utilisons Pydantic pour dรฉclarer des corps de requรชte, nous pouvons l'utiliser ailleurs : + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} + +## Crรฉer une dรฉpendance `get_current_user` { #create-a-get-current-user-dependency } + +Crรฉons une dรฉpendance `get_current_user`. + +Rappelez-vous que les dรฉpendances peuvent avoir des sous-dรฉpendances ? + +`get_current_user` aura une dรฉpendance avec le mรชme `oauth2_scheme` que nous avons crรฉรฉ prรฉcรฉdemment. + +Comme nous le faisions auparavant directement dans le *chemin d'accรจs*, notre nouvelle dรฉpendance `get_current_user` recevra un `token` en tant que `str` de la sous-dรฉpendance `oauth2_scheme` : + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## Rรฉcupรฉrer l'utilisateur { #get-the-user } + +`get_current_user` utilisera une fonction utilitaire (factice) que nous avons crรฉรฉe, qui prend un token en `str` et retourne notre modรจle Pydantic `User` : + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## Injecter l'utilisateur actuel { #inject-the-current-user } + +Nous pouvons donc utiliser le mรชme `Depends` avec notre `get_current_user` dans le *chemin d'accรจs* : + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +Remarquez que nous dรฉclarons le type de `current_user` comme le modรจle Pydantic `User`. + +Cela nous aidera dans la fonction avec toute l'autocomplรฉtion et les vรฉrifications de type. + +/// tip | Astuce + +Vous vous souvenez peut-รชtre que les corps de requรชte sont รฉgalement dรฉclarรฉs avec des modรจles Pydantic. + +Ici, **FastAPI** ne s'y trompera pas car vous utilisez `Depends`. + +/// + +/// check | Vรฉrifications + +La maniรจre dont ce systรจme de dรฉpendances est conรงu nous permet d'avoir diffรฉrentes dรฉpendances (diffรฉrents ยซ dependables ยป) qui retournent toutes un modรจle `User`. + +Nous ne sommes pas limitรฉs ร  une seule dรฉpendance pouvant retourner ce type de donnรฉes. + +/// + +## Autres modรจles { #other-models } + +Vous pouvez maintenant obtenir l'utilisateur actuel directement dans les *fonctions de chemin d'accรจs* et gรฉrer les mรฉcanismes de sรฉcuritรฉ au niveau de l'**Injection de dรฉpendances**, en utilisant `Depends`. + +Et vous pouvez utiliser n'importe quel modรจle ou donnรฉes pour les exigences de sรฉcuritรฉ (dans ce cas, un modรจle Pydantic `User`). + +Mais vous n'รชtes pas limitรฉ ร  un modรจle, une classe ou un type de donnรฉes spรฉcifique. + +Voulez-vous avoir un `id` et `email` et ne pas avoir de `username` dans votre modรจle ? Bien sรปr. Vous pouvez utiliser ces mรชmes outils. + +Voulez-vous simplement avoir un `str` ? Ou juste un `dict` ? Ou directement une instance d'un modรจle de classe de base de donnรฉes ? Tout fonctionne de la mรชme maniรจre. + +Vous n'avez en fait pas d'utilisateurs qui se connectent ร  votre application, mais des robots, bots ou d'autres systรจmes, qui n'ont qu'un jeton d'accรจs ? Lร  encore, tout fonctionne de la mรชme faรงon. + +Utilisez simplement tout type de modรจle, toute sorte de classe, tout type de base de donnรฉes dont vous avez besoin pour votre application. **FastAPI** vous couvre avec le systรจme d'injection de dรฉpendances. + +## Taille du code { #code-size } + +Cet exemple peut sembler verbeux. Gardez ร  l'esprit que nous mรฉlangeons sรฉcuritรฉ, modรจles de donnรฉes, fonctions utilitaires et *chemins d'accรจs* dans le mรชme fichier. + +Mais voici le point clรฉ. + +La partie sรฉcuritรฉ et injection de dรฉpendances est รฉcrite une seule fois. + +Et vous pouvez la rendre aussi complexe que vous le souhaitez. Et malgrรฉ tout, ne l'รฉcrire qu'une seule fois, en un seul endroit. Avec toute la flexibilitรฉ. + +Mais vous pouvez avoir des milliers d'endpoints (*chemins d'accรจs*) utilisant le mรชme systรจme de sรฉcuritรฉ. + +Et tous (ou seulement une partie d'entre eux, si vous le souhaitez) peuvent profiter de la rรฉutilisation de ces dรฉpendances ou de toute autre dรฉpendance que vous crรฉez. + +Et tous ces milliers de *chemins d'accรจs* peuvent tenir en seulement 3 lignes : + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## Rรฉcapitulatif { #recap } + +Vous pouvez dรฉsormais obtenir l'utilisateur actuel directement dans votre *fonction de chemin d'accรจs*. + +Nous avons dรฉjร  fait la moitiรฉ du chemin. + +Il nous suffit d'ajouter un *chemin d'accรจs* pour que l'utilisateur/client envoie effectivement le `username` et le `password`. + +C'est pour la suite. diff --git a/docs/fr/docs/tutorial/security/index.md b/docs/fr/docs/tutorial/security/index.md new file mode 100644 index 0000000000..6de75aed61 --- /dev/null +++ b/docs/fr/docs/tutorial/security/index.md @@ -0,0 +1,106 @@ +# Sรฉcuritรฉ { #security } + +Il existe de nombreuses faรงons de gรฉrer la sรฉcuritรฉ, l'authentification et l'autorisation. + +Et c'est normalement un sujet complexe et ยซ difficile ยป. + +Dans de nombreux frameworks et systรจmes, le simple fait de gรฉrer la sรฉcuritรฉ et l'authentification demande beaucoup d'efforts et de code (dans de nombreux cas, cela peut reprรฉsenter 50 % ou plus de tout le code รฉcrit). + +**FastAPI** fournit plusieurs outils pour vous aider ร  gรฉrer la **Sรฉcuritรฉ** facilement, rapidement, de maniรจre standard, sans avoir ร  รฉtudier et apprendre toutes les spรฉcifications de sรฉcuritรฉ. + +Mais d'abord, voyons quelques notions. + +## Pressรฉ ? { #in-a-hurry } + +Si ces termes ne vous intรฉressent pas et que vous avez simplement besoin d'ajouter une sรฉcuritรฉ avec une authentification basรฉe sur un nom d'utilisateur et un mot de passe immรฉdiatement, passez aux chapitres suivants. + +## OAuth2 { #oauth2 } + +OAuth2 est une spรฉcification qui dรฉfinit plusieurs faรงons de gรฉrer l'authentification et l'autorisation. + +C'est une spรฉcification assez vaste qui couvre plusieurs cas d'utilisation complexes. + +Elle inclut des moyens de s'authentifier en utilisant un ยซ tiers ยป. + +C'est ce que tous les systรจmes avec ยซ connexion avec Facebook, Google, X (Twitter), GitHub ยป utilisent en arriรจre-plan. + +### OAuth 1 { #oauth-1 } + +Il y a eu un OAuth 1, trรจs diffรฉrent d'OAuth2, et plus complexe, car il incluait des spรฉcifications directes sur la maniรจre de chiffrer la communication. + +Il n'est plus trรจs populaire ni utilisรฉ de nos jours. + +OAuth2 ne spรฉcifie pas comment chiffrer la communication ; il suppose que votre application est servie en HTTPS. + +/// tip | Astuce + +Dans la section sur le dรฉploiement, vous verrez comment configurer HTTPS gratuitement, en utilisant Traefik et Let's Encrypt. + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect est une autre spรฉcification, basรฉe sur **OAuth2**. + +Elle รฉtend simplement OAuth2 en prรฉcisant certains points relativement ambigus dans OAuth2, afin d'essayer de la rendre plus interopรฉrable. + +Par exemple, la connexion Google utilise OpenID Connect (qui, en arriรจre-plan, utilise OAuth2). + +Mais la connexion Facebook ne prend pas en charge OpenID Connect. Elle a sa propre variante d'OAuth2. + +### OpenID (pas ยซ OpenID Connect ยป) { #openid-not-openid-connect } + +Il y avait aussi une spรฉcification ยซ OpenID ยป. Elle essayait de rรฉsoudre la mรชme chose qu'**OpenID Connect**, mais n'รฉtait pas basรฉe sur OAuth2. + +C'รฉtait donc un systรจme totalement distinct. + +Il n'est plus trรจs populaire ni utilisรฉ de nos jours. + +## OpenAPI { #openapi } + +OpenAPI (prรฉcรฉdemment connu sous le nom de Swagger) est la spรฉcification ouverte pour construire des API (dรฉsormais partie de la Linux Foundation). + +**FastAPI** est basรฉ sur **OpenAPI**. + +C'est ce qui rend possibles plusieurs interfaces de documentation interactive automatiques, la gรฉnรฉration de code, etc. + +OpenAPI propose une maniรจre de dรฉfinir plusieurs ยซ schรฉmas ยป de sรฉcuritรฉ. + +En les utilisant, vous pouvez tirer parti de tous ces outils basรฉs sur des standards, y compris ces systรจmes de documentation interactive. + +OpenAPI dรฉfinit les schรฉmas de sรฉcuritรฉ suivants : + +* `apiKey` : une clรฉ spรฉcifique ร  l'application qui peut provenir : + * D'un paramรจtre de requรชte. + * D'un en-tรชte. + * D'un cookie. +* `http` : des systรจmes d'authentification HTTP standards, notamment : + * `bearer` : un en-tรชte `Authorization` avec une valeur `Bearer ` plus un jeton. Hรฉritรฉ d'OAuth2. + * Authentification HTTP Basic. + * HTTP Digest, etc. +* `oauth2` : toutes les mรฉthodes OAuth2 pour gรฉrer la sรฉcuritรฉ (appelรฉes ยซ flows ยป). + * Plusieurs de ces flows conviennent pour construire un fournisseur d'authentification OAuth 2.0 (comme Google, Facebook, X (Twitter), GitHub, etc.) : + * `implicit` + * `clientCredentials` + * `authorizationCode` + * Mais il existe un ยซ flow ยป spรฉcifique qui peut parfaitement รชtre utilisรฉ pour gรฉrer l'authentification directement dans la mรชme application : + * `password` : certains des prochains chapitres couvriront des exemples ร  ce sujet. +* `openIdConnect` : propose un moyen de dรฉfinir comment dรฉcouvrir automatiquement les donnรฉes d'authentification OAuth2. + * Cette dรฉcouverte automatique est ce qui est dรฉfini dans la spรฉcification OpenID Connect. + + +/// tip | Astuce + +Intรฉgrer d'autres fournisseurs d'authentification/autorisation comme Google, Facebook, X (Twitter), GitHub, etc. est รฉgalement possible et relativement facile. + +Le problรจme le plus complexe est de construire un fournisseur d'authentification/autorisation comme ceux-lร , mais **FastAPI** vous donne les outils pour le faire facilement, tout en effectuant le gros du travail pour vous. + +/// + +## Outils **FastAPI** { #fastapi-utilities } + +FastAPI propose plusieurs outils pour chacun de ces schรฉmas de sรฉcuritรฉ dans le module fastapi.security qui simplifient l'utilisation de ces mรฉcanismes de sรฉcuritรฉ. + +Dans les prochains chapitres, vous verrez comment ajouter de la sรฉcuritรฉ ร  votre API en utilisant ces outils fournis par **FastAPI**. + +Et vous verrez aussi comment cela s'intรจgre automatiquement au systรจme de documentation interactive. diff --git a/docs/fr/docs/tutorial/security/oauth2-jwt.md b/docs/fr/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 0000000000..d35530fc9c --- /dev/null +++ b/docs/fr/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# OAuth2 avec mot de passe (et hachage), Bearer avec des jetons JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +Maintenant que nous avons tout le flux de sรฉcuritรฉ, rendons rรฉellement l'application sรฉcurisรฉe, en utilisant des jetons JWT et un hachage de mot de passe sรฉcurisรฉ. + +Ce code est utilisable dans votre application, enregistrez les hachages de mots de passe dans votre base de donnรฉes, etc. + +Nous allons repartir d'oรน nous nous sommes arrรชtรฉs dans le chapitre prรฉcรฉdent et l'enrichir. + +## ร€ propos de JWT { #about-jwt } + +JWT signifie ยซ JSON Web Tokens ยป. + +C'est une norme pour coder un objet JSON dans une longue chaรฎne compacte sans espaces. Cela ressemble ร  ceci : + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +Il n'est pas chiffrรฉ ; ainsi, n'importe qui peut rรฉcupรฉrer les informations ร  partir de son contenu. + +Mais il est signรฉ. Ainsi, quand vous recevez un jeton que vous avez รฉmis, vous pouvez vรฉrifier que vous l'avez bien รฉmis. + +De cette faรงon, vous pouvez crรฉer un jeton avec une expiration d'une semaine, par exemple. Et quand l'utilisateur revient le lendemain avec ce jeton, vous savez qu'il est toujours connectรฉ ร  votre systรจme. + +Aprรจs une semaine, le jeton aura expirรฉ et l'utilisateur ne sera pas autorisรฉ et devra se reconnecter pour obtenir un nouveau jeton. Et si l'utilisateur (ou un tiers) essayait de modifier le jeton pour changer l'expiration, vous pourriez le dรฉtecter, car les signatures ne correspondraient pas. + +Si vous voulez expรฉrimenter avec des jetons JWT et voir comment ils fonctionnent, consultez https://jwt.io. + +## Installer `PyJWT` { #install-pyjwt } + +Nous devons installer `PyJWT` pour gรฉnรฉrer et vรฉrifier les jetons JWT en Python. + +Assurez-vous de crรฉer un [environnement virtuel](../../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer `pyjwt` : + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info + +Si vous prรฉvoyez d'utiliser des algorithmes de signature numรฉrique comme RSA ou ECDSA, vous devez installer la dรฉpendance de bibliothรจque de cryptographie `pyjwt[crypto]`. + +Vous pouvez en lire davantage dans la documentation d'installation de PyJWT. + +/// + +## Hachage de mot de passe { #password-hashing } + +ยซ Hachage ยป signifie convertir un contenu (un mot de passe dans ce cas) en une sรฉquence d'octets (juste une chaรฎne) qui ressemble ร  du charabia. + +Chaque fois que vous fournissez exactement le mรชme contenu (exactement le mรชme mot de passe), vous obtenez exactement le mรชme charabia. + +Mais vous ne pouvez pas convertir le charabia en sens inverse vers le mot de passe. + +### Pourquoi utiliser le hachage de mot de passe { #why-use-password-hashing } + +Si votre base de donnรฉes est volรฉe, le voleur n'aura pas les mots de passe en clair de vos utilisateurs, seulement les hachages. + +Ainsi, le voleur ne pourra pas essayer d'utiliser ce mot de passe dans un autre systรจme (comme beaucoup d'utilisateurs utilisent le mรชme mot de passe partout, ce serait dangereux). + +## Installer `pwdlib` { #install-pwdlib } + +pwdlib est un excellent package Python pour gรฉrer les hachages de mots de passe. + +Il prend en charge de nombreux algorithmes de hachage sรฉcurisรฉs et des utilitaires pour travailler avec eux. + +L'algorithme recommandรฉ est ยซ Argon2 ยป. + +Assurez-vous de crรฉer un [environnement virtuel](../../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer pwdlib avec Argon2 : + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | Astuce + +Avec `pwdlib`, vous pouvez mรชme le configurer pour pouvoir lire des mots de passe crรฉรฉs par **Django**, un plug-in de sรฉcuritรฉ **Flask** ou bien d'autres. + +Ainsi, vous seriez par exemple en mesure de partager les mรชmes donnรฉes d'une application Django dans une base de donnรฉes avec une application FastAPI. Ou de migrer progressivement une application Django en utilisant la mรชme base de donnรฉes. + +Et vos utilisateurs pourraient se connecter depuis votre application Django ou depuis votre application **FastAPI**, en mรชme temps. + +/// + +## Hacher et vรฉrifier les mots de passe { #hash-and-verify-the-passwords } + +Importez les outils nรฉcessaires depuis `pwdlib`. + +Crรฉez une instance PasswordHash avec les rรฉglages recommandรฉs ; elle sera utilisรฉe pour hacher et vรฉrifier les mots de passe. + +/// tip | Astuce + +pwdlib prend รฉgalement en charge l'algorithme de hachage bcrypt, mais n'inclut pas les algorithmes hรฉritรฉs. Pour travailler avec des hachages obsolรจtes, il est recommandรฉ d'utiliser la bibliothรจque passlib. + +Par exemple, vous pourriez l'utiliser pour lire et vรฉrifier des mots de passe gรฉnรฉrรฉs par un autre systรจme (comme Django), mais hacher tous les nouveaux mots de passe avec un autre algorithme comme Argon2 ou Bcrypt. + +Et rester compatible avec tous en mรชme temps. + +/// + +Crรฉez une fonction utilitaire pour hacher un mot de passe fourni par l'utilisateur. + +Et une autre pour vรฉrifier si un mot de passe reรงu correspond au hachage stockรฉ. + +Et une autre pour authentifier et renvoyer un utilisateur. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Lorsque `authenticate_user` est appelรฉe avec un nom d'utilisateur qui n'existe pas dans la base de donnรฉes, nous exรฉcutons tout de mรชme `verify_password` contre un hachage factice. + +Cela garantit que le point de terminaison met approximativement le mรชme temps ร  rรฉpondre que le nom d'utilisateur soit valide ou non, empรชchant des **attaques temporelles** qui pourraient รชtre utilisรฉes pour รฉnumรฉrer les noms d'utilisateur existants. + +/// note | Remarque + +Si vous consultez la nouvelle (fausse) base de donnรฉes `fake_users_db`, vous verrez ร  quoi ressemble maintenant le mot de passe hachรฉ : `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + +/// + +## Gรฉrer les jetons JWT { #handle-jwt-tokens } + +Importez les modules installรฉs. + +Crรฉez une clรฉ secrรจte alรฉatoire qui sera utilisรฉe pour signer les jetons JWT. + +Pour gรฉnรฉrer une clรฉ secrรจte alรฉatoire sรฉcurisรฉe, utilisez la commande : + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +Et copiez la sortie dans la variable `SECRET_KEY` (n'utilisez pas celle de l'exemple). + +Crรฉez une variable `ALGORITHM` avec l'algorithme utilisรฉ pour signer le jeton JWT, et dรฉfinissez-la ร  `"HS256"`. + +Crรฉez une variable pour l'expiration du jeton. + +Dรฉfinissez un modรจle Pydantic qui sera utilisรฉ dans le point de terminaison du jeton pour la rรฉponse. + +Crรฉez une fonction utilitaire pour gรฉnรฉrer un nouveau jeton d'accรจs. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## Mettre ร  jour les dรฉpendances { #update-the-dependencies } + +Mettez ร  jour `get_current_user` pour recevoir le mรชme jeton qu'auparavant, mais cette fois en utilisant des jetons JWT. + +Dรฉcodez le jeton reรงu, vรฉrifiez-le, et renvoyez l'utilisateur courant. + +Si le jeton est invalide, renvoyez immรฉdiatement une erreur HTTP. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## Mettre ร  jour le *chemin d'accรจs* `/token` { #update-the-token-path-operation } + +Crรฉez un `timedelta` avec la durรฉe d'expiration du jeton. + +Crรฉez un vรฉritable jeton d'accรจs JWT et renvoyez-le. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### Dรฉtails techniques au sujet du ยซ subject ยป JWT `sub` { #technical-details-about-the-jwt-subject-sub } + +La spรฉcification JWT indique qu'il existe une clรฉ `sub`, contenant le sujet du jeton. + +Son utilisation est facultative, mais c'est lร  que vous placeriez l'identifiant de l'utilisateur ; nous l'utilisons donc ici. + +Les JWT peuvent รชtre utilisรฉs pour d'autres choses que l'identification d'un utilisateur et l'autorisation d'effectuer des opรฉrations directement sur votre API. + +Par exemple, vous pourriez identifier une ยซ voiture ยป ou un ยซ article de blog ยป. + +Vous pourriez ensuite ajouter des permissions sur cette entitรฉ, comme ยซ conduire ยป (pour la voiture) ou ยซ modifier ยป (pour le blog). + +Vous pourriez alors donner ce jeton JWT ร  un utilisateur (ou un bot), et il pourrait l'utiliser pour effectuer ces actions (conduire la voiture, ou modifier l'article de blog) sans mรชme avoir besoin d'avoir un compte, uniquement avec le jeton JWT que votre API a gรฉnรฉrรฉ pour cela. + +En utilisant ces idรฉes, les JWT peuvent servir ร  des scรฉnarios bien plus sophistiquรฉs. + +Dans ces cas, plusieurs de ces entitรฉs peuvent avoir le mรชme identifiant, disons `foo` (un utilisateur `foo`, une voiture `foo`, et un article de blog `foo`). + +Donc, pour รฉviter les collisions d'identifiants, lors de la crรฉation du jeton JWT pour l'utilisateur, vous pouvez prรฉfixer la valeur de la clรฉ `sub`, par exemple avec `username:`. Ainsi, dans cet exemple, la valeur de `sub` aurait pu รชtre : `username:johndoe`. + +L'important ร  garder ร  l'esprit est que la clรฉ `sub` doit contenir un identifiant unique dans toute l'application, et ce doit รชtre une chaรฎne de caractรจres. + +## Vรฉrifier { #check-it } + +Lancez le serveur et allez ร  la documentation : http://127.0.0.1:8000/docs. + +Vous verrez l'interface utilisateur suivante : + + + +Autorisez l'application de la mรชme maniรจre qu'auparavant. + +En utilisant les identifiants : + +Nom d'utilisateur : `johndoe` +Mot de passe : `secret` + +/// check | Vรฉrifications + +Remarquez qu'ร  aucun endroit du code le mot de passe en clair ยซ secret ยป n'apparaรฎt, nous n'avons que la version hachรฉe. + +/// + + + +Appelez le point de terminaison `/users/me/`, vous obtiendrez la rรฉponse suivante : + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +Si vous ouvrez les outils de dรฉveloppement, vous pouvez voir que les donnรฉes envoyรฉes n'incluent que le jeton ; le mot de passe n'est envoyรฉ que dans la premiรจre requรชte pour authentifier l'utilisateur et obtenir ce jeton d'accรจs, mais plus ensuite : + + + +/// note | Remarque + +Remarquez l'en-tรชte `Authorization`, avec une valeur qui commence par `Bearer `. + +/// + +## Utilisation avancรฉe avec `scopes` { #advanced-usage-with-scopes } + +OAuth2 comporte la notion de ยซ scopes ยป. + +Vous pouvez les utiliser pour ajouter un ensemble spรฉcifique d'autorisations ร  un jeton JWT. + +Vous pouvez ensuite donner ce jeton directement ร  un utilisateur ou ร  un tiers, pour interagir avec votre API avec un ensemble de restrictions. + +Vous pouvez apprendre ร  les utiliser et comment ils sont intรฉgrรฉs ร  **FastAPI** plus tard dans le **Guide de l'utilisateur avancรฉ**. + +## Rรฉcapitulatif { #recap } + +Avec ce que vous avez vu jusqu'ร  prรฉsent, vous pouvez configurer une application **FastAPI** sรฉcurisรฉe en utilisant des standards comme OAuth2 et JWT. + +Dans presque n'importe quel framework, la gestion de la sรฉcuritรฉ devient assez rapidement un sujet plutรดt complexe. + +De nombreux packages qui la simplifient beaucoup doivent faire de nombreux compromis avec le modรจle de donnรฉes, la base de donnรฉes et les fonctionnalitรฉs disponibles. Et certains de ces packages qui simplifient trop les choses comportent en fait des failles de sรฉcuritรฉ sous-jacentes. + +--- + +**FastAPI** ne fait aucun compromis avec une base de donnรฉes, un modรจle de donnรฉes ni un outil. + +Il vous donne toute la flexibilitรฉ pour choisir ceux qui conviennent le mieux ร  votre projet. + +Et vous pouvez utiliser directement de nombreux packages bien maintenus et largement utilisรฉs comme `pwdlib` et `PyJWT`, car **FastAPI** n'exige aucun mรฉcanisme complexe pour intรฉgrer des packages externes. + +Mais il vous fournit les outils pour simplifier le processus autant que possible sans compromettre la flexibilitรฉ, la robustesse ou la sรฉcuritรฉ. + +Et vous pouvez utiliser et implรฉmenter des protocoles sรฉcurisรฉs et standard, comme OAuth2, de maniรจre relativement simple. + +Vous pouvez en apprendre davantage dans le **Guide de l'utilisateur avancรฉ** sur la faรงon d'utiliser les ยซ scopes ยป OAuth2, pour un systรจme d'autorisations plus fin, en suivant ces mรชmes standards. OAuth2 avec scopes est le mรฉcanisme utilisรฉ par de nombreux grands fournisseurs d'authentification, comme Facebook, Google, GitHub, Microsoft, X (Twitter), etc., pour autoriser des applications tierces ร  interagir avec leurs API au nom de leurs utilisateurs. diff --git a/docs/fr/docs/tutorial/security/simple-oauth2.md b/docs/fr/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000..662444753b --- /dev/null +++ b/docs/fr/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# OAuth2 simple avec Password et Bearer { #simple-oauth2-with-password-and-bearer } + +Construisons maintenant ร  partir du chapitre prรฉcรฉdent et ajoutons les รฉlรฉments manquants pour avoir un flux de sรฉcuritรฉ complet. + +## Obtenir `username` et `password` { #get-the-username-and-password } + +Nous allons utiliser les utilitaires de sรฉcuritรฉ de **FastAPI** pour obtenir `username` et `password`. + +OAuth2 spรฉcifie que lorsqu'on utilise le ยซ password flow ยป (ce que nous utilisons), le client/utilisateur doit envoyer des champs `username` et `password` en tant que donnรฉes de formulaire. + +Et la spรฉcification indique que les champs doivent porter exactement ces noms. Ainsi, `user-name` ou `email` ne fonctionneraient pas. + +Mais ne vous inquiรฉtez pas, vous pouvez l'afficher comme vous le souhaitez ร  vos utilisateurs finaux dans le frontend. + +Et vos modรจles de base de donnรฉes peuvent utiliser les noms que vous voulez. + +Mais pour le chemin d'accรจs de connexion, nous devons utiliser ces noms pour รชtre compatibles avec la spรฉcification (et pouvoir, par exemple, utiliser le systรจme de documentation API intรฉgrรฉ). + +La spรฉcification prรฉcise รฉgalement que `username` et `password` doivent รชtre envoyรฉs en donnรฉes de formulaire (donc pas de JSON ici). + +### `scope` { #scope } + +La spรฉcification indique aussi que le client peut envoyer un autre champ de formulaire ยซ scope ยป. + +Le nom du champ de formulaire est `scope` (au singulier), mais il s'agit en fait d'une longue chaรฎne contenant des ยซ scopes ยป sรฉparรฉs par des espaces. + +Chaque ยซ scope ยป n'est qu'une chaรฎne (sans espaces). + +Ils sont normalement utilisรฉs pour dรฉclarer des permissions de sรฉcuritรฉ spรฉcifiques, par exemple : + +* `users:read` ou `users:write` sont des exemples courants. +* `instagram_basic` est utilisรฉ par Facebook / Instagram. +* `https://www.googleapis.com/auth/drive` est utilisรฉ par Google. + +/// info + +En OAuth2, un ยซ scope ยป est simplement une chaรฎne qui dรฉclare une permission spรฉcifique requise. + +Peu importe s'il contient d'autres caractรจres comme `:` ou si c'est une URL. + +Ces dรฉtails dรฉpendent de l'implรฉmentation. + +Pour OAuth2, ce ne sont que des chaรฎnes. + +/// + +## ร‰crire le code pour obtenir `username` et `password` { #code-to-get-the-username-and-password } + +Utilisons maintenant les utilitaires fournis par **FastAPI** pour gรฉrer cela. + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que dรฉpendance avec `Depends` dans le chemin d'accรจs pour `/token` : + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` est une dรฉpendance de classe qui dรฉclare un corps de formulaire avec : + +* Le `username`. +* Le `password`. +* Un champ optionnel `scope` sous forme d'une grande chaรฎne, composรฉe de chaรฎnes sรฉparรฉes par des espaces. +* Un `grant_type` optionnel. + +/// tip | Astuce + +La spรฉcification OAuth2 exige en rรฉalitรฉ un champ `grant_type` avec la valeur fixe `password`, mais `OAuth2PasswordRequestForm` ne l'impose pas. + +Si vous avez besoin de l'imposer, utilisez `OAuth2PasswordRequestFormStrict` au lieu de `OAuth2PasswordRequestForm`. + +/// + +* Un `client_id` optionnel (nous n'en avons pas besoin pour notre exemple). +* Un `client_secret` optionnel (nous n'en avons pas besoin pour notre exemple). + +/// info + +La classe `OAuth2PasswordRequestForm` n'est pas une classe spรฉciale pour **FastAPI** comme l'est `OAuth2PasswordBearer`. + +`OAuth2PasswordBearer` indique ร  **FastAPI** qu'il s'agit d'un schรฉma de sรฉcuritรฉ. Il est donc ajoutรฉ de cette faรงon ร  OpenAPI. + +Mais `OAuth2PasswordRequestForm` est simplement une dรฉpendance de classe que vous auriez pu รฉcrire vousโ€‘mรชme, ou vous auriez pu dรฉclarer des paramรจtres `Form` directement. + +Mais comme c'est un cas d'usage courant, elle est fournie directement par **FastAPI**, simplement pour vous faciliter la vie. + +/// + +### Utiliser les donnรฉes du formulaire { #use-the-form-data } + +/// tip | Astuce + +L'instance de la classe de dรฉpendance `OAuth2PasswordRequestForm` n'aura pas d'attribut `scope` contenant la longue chaรฎne sรฉparรฉe par des espaces ; elle aura plutรดt un attribut `scopes` avec la liste rรฉelle des chaรฎnes pour chaque scope envoyรฉ. + +Nous n'utilisons pas `scopes` dans cet exemple, mais la fonctionnalitรฉ est disponible si vous en avez besoin. + +/// + +Rรฉcupรฉrez maintenant les donnรฉes utilisateur depuis la (fausse) base de donnรฉes, en utilisant le `username` du champ de formulaire. + +S'il n'existe pas d'utilisateur, nous renvoyons une erreur indiquant ยซ Incorrect username or password ยป. + +Pour l'erreur, nous utilisons l'exception `HTTPException` : + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### Vรฉrifier le mot de passe { #check-the-password } + +ร€ ce stade, nous avons les donnรฉes utilisateur depuis notre base, mais nous n'avons pas encore vรฉrifiรฉ le mot de passe. + +Mettons d'abord ces donnรฉes dans le modรจle Pydantic `UserInDB`. + +Vous ne devez jamais enregistrer des mots de passe en clair ; nous allons donc utiliser le systรจme (factice) de hachage de mot de passe. + +Si les mots de passe ne correspondent pas, nous renvoyons la mรชme erreur. + +#### Hachage de mot de passe { #password-hashing } + +Le ยซ hachage ยป signifie : convertir un contenu (un mot de passe, dans ce cas) en une sรฉquence d'octets (juste une chaรฎne) qui ressemble ร  du charabia. + +Chaque fois que vous fournissez exactement le mรชme contenu (exactement le mรชme mot de passe), vous obtenez exactement le mรชme charabia. + +Mais vous ne pouvez pas convertir ce charabia pour retrouver le mot de passe. + +##### Pourquoi utiliser le hachage de mot de passe { #why-use-password-hashing } + +Si votre base de donnรฉes est volรฉe, le voleur n'aura pas les mots de passe en clair de vos utilisateurs, seulement les hachages. + +Ainsi, il ne pourra pas essayer d'utiliser ces mรชmes mots de passe dans un autre systรจme (comme beaucoup d'utilisateurs utilisent le mรชme mot de passe partout, ce serait dangereux). + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### ร€ propos de `**user_dict` { #about-user-dict } + +`UserInDB(**user_dict)` signifie : + +Passez les clรฉs et valeurs de `user_dict` directement comme arguments clรฉโ€‘valeur, รฉquivalent ร  : + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// info + +Pour une explication plus complรจte de `**user_dict`, consultez [la documentation pour **Modรจles supplรฉmentaires**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}. + +/// + +## Renvoyer le jeton { #return-the-token } + +La rรฉponse de l'endpoint `token` doit รชtre un objet JSON. + +Il doit contenir un `token_type`. Dans notre cas, comme nous utilisons des jetons ยซ Bearer ยป, le type de jeton doit รชtre ยซ bearer ยป. + +Et il doit contenir un `access_token`, avec une chaรฎne contenant notre jeton d'accรจs. + +Pour cet exemple simple, nous allons faire quelque chose de complรจtement non sรฉcurisรฉ et renvoyer le mรชme `username` comme jeton. + +/// tip | Astuce + +Dans le prochain chapitre, vous verrez une vรฉritable implรฉmentation sรฉcurisรฉe, avec du hachage de mot de passe et des jetons JWT. + +Mais pour l'instant, concentronsโ€‘nous sur les dรฉtails spรฉcifiques dont nous avons besoin. + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | Astuce + +D'aprรจs la spรฉcification, vous devez renvoyer un JSON avec un `access_token` et un `token_type`, comme dans cet exemple. + +C'est quelque chose que vous devez faire vousโ€‘mรชme dans votre code, et vous devez vous assurer d'utiliser ces clรฉs JSON. + +C'est presque la seule chose que vous devez vous rappeler de faire correctement vousโ€‘mรชme pour รชtre conforme aux spรฉcifications. + +Pour le reste, **FastAPI** s'en charge pour vous. + +/// + +## Mettre ร  jour les dรฉpendances { #update-the-dependencies } + +Nous allons maintenant mettre ร  jour nos dรฉpendances. + +Nous voulons obtenir `current_user` uniquement si cet utilisateur est actif. + +Nous crรฉons donc une dรฉpendance supplรฉmentaire `get_current_active_user` qui utilise ร  son tour `get_current_user` comme dรฉpendance. + +Ces deux dรฉpendances renverront simplement une erreur HTTP si l'utilisateur n'existe pas, ou s'il est inactif. + +Ainsi, dans notre endpoint, nous n'obtiendrons un utilisateur que si l'utilisateur existe, a รฉtรฉ correctement authentifiรฉ et est actif : + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// info + +L'enโ€‘tรชte supplรฉmentaire `WWW-Authenticate` avec la valeur `Bearer` que nous renvoyons ici fait รฉgalement partie de la spรฉcification. + +Il est prรฉvu qu'un code d'รฉtat HTTP (d'erreur) 401 ยซ UNAUTHORIZED ยป renvoie รฉgalement un enโ€‘tรชte `WWW-Authenticate`. + +Dans le cas des jetons bearer (notre cas), la valeur de cet enโ€‘tรชte doit รชtre `Bearer`. + +Vous pouvez en rรฉalitรฉ omettre cet enโ€‘tรชte supplรฉmentaire et cela fonctionnerait quand mรชme. + +Mais il est fourni ici pour รชtre conforme aux spรฉcifications. + +De plus, il peut exister des outils qui l'attendent et l'utilisent (maintenant ou ร  l'avenir) et cela pourrait vous รชtre utile, ร  vous ou ร  vos utilisateurs, maintenant ou ร  l'avenir. + +C'est l'avantage des standards ... + +/// + +## Voir en action { #see-it-in-action } + +Ouvrez la documentation interactive : http://127.0.0.1:8000/docs. + +### S'authentifier { #authenticate } + +Cliquez sur le bouton ยซ Authorize ยป. + +Utilisez les identifiants : + +Utilisateur : `johndoe` + +Mot de passe : `secret` + + + +Aprรจs vous รชtre authentifiรฉ dans le systรจme, vous verrez ceci : + + + +### Obtenir vos propres donnรฉes utilisateur { #get-your-own-user-data } + +Utilisez maintenant l'opรฉration `GET` avec le chemin `/users/me`. + +Vous obtiendrez les donnรฉes de votre utilisateur, par exemple : + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +Si vous cliquez sur l'icรดne de cadenas et vous vous dรฉconnectez, puis rรฉessayez la mรชme opรฉration, vous obtiendrez une erreur HTTP 401 : + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### Utilisateur inactif { #inactive-user } + +Essayez maintenant avec un utilisateur inactif, authentifiezโ€‘vous avec : + +Utilisateur : `alice` + +Mot de passe : `secret2` + +Et essayez d'utiliser l'opรฉration `GET` avec le chemin `/users/me`. + +Vous obtiendrez une erreur ยซ Inactive user ยป, par exemple : + +```JSON +{ + "detail": "Inactive user" +} +``` + +## Rรฉcapitulatif { #recap } + +Vous avez maintenant les outils pour implรฉmenter un systรจme de sรฉcuritรฉ complet basรฉ sur `username` et `password` pour votre API. + +En utilisant ces outils, vous pouvez rendre le systรจme de sรฉcuritรฉ compatible avec n'importe quelle base de donnรฉes et avec n'importe quel modรจle d'utilisateur ou de donnรฉes. + +Le seul dรฉtail manquant est qu'il n'est pas encore rรฉellement ยซ sรฉcurisรฉ ยป. + +Dans le prochain chapitre, vous verrez comment utiliser une bibliothรจque de hachage de mot de passe sรฉcurisรฉe et des jetons JWT. diff --git a/docs/fr/docs/tutorial/sql-databases.md b/docs/fr/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..75f9ae14fc --- /dev/null +++ b/docs/fr/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# Bases de donnรฉes SQL (relationnelles) { #sql-relational-databases } + +**FastAPI** ne vous oblige pas ร  utiliser une base de donnรฉes SQL (relationnelle). Mais vous pouvez utiliser **n'importe quelle base de donnรฉes** que vous voulez. + +Ici, nous allons voir un exemple utilisant SQLModel. + +**SQLModel** est construit au-dessus de SQLAlchemy et de Pydantic. Il a รฉtรฉ crรฉรฉ par le mรชme auteur que **FastAPI** pour รชtre l'accord parfait pour les applications FastAPI qui ont besoin d'utiliser des **bases de donnรฉes SQL**. + +/// tip | Astuce + +Vous pouvez utiliser toute autre bibliothรจque SQL ou NoSQL que vous voulez (dans certains cas appelรฉes ยซ ORMs ยป), FastAPI ne vous impose rien. ๐Ÿ˜Ž + +/// + +Comme SQLModel est basรฉ sur SQLAlchemy, vous pouvez facilement utiliser **toute base prise en charge** par SQLAlchemy (ce qui les rend รฉgalement prises en charge par SQLModel), comme : + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server, etc. + +Dans cet exemple, nous utiliserons **SQLite**, car il utilise un seul fichier et Python a un support intรฉgrรฉ. Ainsi, vous pouvez copier cet exemple et l'exรฉcuter tel quel. + +Plus tard, pour votre application de production, vous voudrez peut-รชtre utiliser un serveur de base de donnรฉes comme **PostgreSQL**. + +/// tip | Astuce + +Il existe un gรฉnรฉrateur de projet officiel avec **FastAPI** et **PostgreSQL**, incluant un frontend et plus d'outils : https://github.com/fastapi/full-stack-fastapi-template + +/// + +Il s'agit d'un tutoriel trรจs simple et court ; si vous souhaitez apprendre sur les bases de donnรฉes en gรฉnรฉral, sur SQL, ou des fonctionnalitรฉs plus avancรฉes, allez voir la documentation SQLModel. + +## Installer `SQLModel` { #install-sqlmodel } + +D'abord, assurez-vous de crรฉer votre [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, de l'activer, puis d'installer `sqlmodel` : + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## Crรฉer l'application avec un modรจle unique { #create-the-app-with-a-single-model } + +Nous allons d'abord crรฉer la premiรจre version la plus simple de l'application avec un seul modรจle **SQLModel**. + +Ensuite, nous l'amรฉliorerons en augmentant la sรฉcuritรฉ et la polyvalence avec **plusieurs modรจles** ci-dessous. ๐Ÿค“ + +### Crรฉer les modรจles { #create-models } + +Importez `SQLModel` et crรฉez un modรจle de base de donnรฉes : + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +La classe `Hero` est trรจs similaire ร  un modรจle Pydantic (en fait, en dessous, c'est rรฉellement un modรจle Pydantic). + +Il y a quelques diffรฉrences : + +* `table=True` indique ร  SQLModel qu'il s'agit d'un *modรจle de table*, il doit reprรฉsenter une **table** dans la base SQL, ce n'est pas seulement un *modรจle de donnรฉes* (comme le serait n'importe quelle autre classe Pydantic classique). + +* `Field(primary_key=True)` indique ร  SQLModel que `id` est la **clรฉ primaire** dans la base SQL (vous pouvez en savoir plus sur les clรฉs primaires SQL dans la documentation SQLModel). + + Remarque : nous utilisons `int | None` pour le champ clรฉ primaire afin qu'en Python nous puissions *crรฉer un objet sans `id`* (`id=None`), en supposant que la base *le gรฉnรจre ร  l'enregistrement*. SQLModel comprend que la base fournira l'`id` et *dรฉfinit la colonne comme un `INTEGER` non nul* dans le schรฉma de base. Voir la documentation SQLModel sur les clรฉs primaires pour plus de dรฉtails. + +* `Field(index=True)` indique ร  SQLModel qu'il doit crรฉer un **index SQL** pour cette colonne, ce qui permettra des recherches plus rapides dans la base lors de la lecture de donnรฉes filtrรฉes par cette colonne. + + SQLModel saura que quelque chose dรฉclarรฉ comme `str` sera une colonne SQL de type `TEXT` (ou `VARCHAR`, selon la base). + +### Crรฉer un engine { #create-an-engine } + +Un `engine` SQLModel (en dessous c'est en fait un `engine` SQLAlchemy) est ce qui **dรฉtient les connexions** ร  la base de donnรฉes. + +Vous devez avoir **un seul objet `engine`** pour tout votre code afin de se connecter ร  la mรชme base. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +L'utilisation de `check_same_thread=False` permet ร  FastAPI d'utiliser la mรชme base SQLite dans diffรฉrents threads. C'est nรฉcessaire car **une seule requรชte** peut utiliser **plus d'un thread** (par exemple dans des dรฉpendances). + +Ne vous inquiรฉtez pas, avec la structure du code, nous nous assurerons d'utiliser **une seule *session* SQLModel par requรชte** plus loin, c'est en fait ce que `check_same_thread` essaie d'assurer. + +### Crรฉer les tables { #create-the-tables } + +Nous ajoutons ensuite une fonction qui utilise `SQLModel.metadata.create_all(engine)` pour **crรฉer les tables** pour tous les *modรจles de table*. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### Crรฉer une dรฉpendance de session { #create-a-session-dependency } + +Une **`Session`** est ce qui stocke les **objets en mรฉmoire** et suit les modifications nรฉcessaires des donnรฉes, puis **utilise l'`engine`** pour communiquer avec la base. + +Nous allons crรฉer une **dรฉpendance** FastAPI avec `yield` qui fournira une nouvelle `Session` pour chaque requรชte. C'est ce qui garantit que nous utilisons une seule session par requรชte. ๐Ÿค“ + +Puis nous crรฉons une dรฉpendance `Annotated` `SessionDep` pour simplifier le reste du code qui utilisera cette dรฉpendance. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### Crรฉer les tables de base au dรฉmarrage { #create-database-tables-on-startup } + +Nous allons crรฉer les tables de base de donnรฉes au dรฉmarrage de l'application. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +Ici, nous crรฉons les tables lors d'un รฉvรฉnement de dรฉmarrage de l'application. + +En production, vous utiliseriez probablement un script de migration qui s'exรฉcute avant de dรฉmarrer votre application. ๐Ÿค“ + +/// tip | Astuce + +SQLModel aura des utilitaires de migration enveloppant Alembic, mais pour l'instant, vous pouvez utiliser Alembic directement. + +/// + +### Crรฉer un hรฉros { #create-a-hero } + +Comme chaque modรจle SQLModel est aussi un modรจle Pydantic, vous pouvez l'utiliser dans les mรชmes **annotations de type** que vous utiliseriez pour des modรจles Pydantic. + +Par exemple, si vous dรฉclarez un paramรจtre de type `Hero`, il sera lu depuis le **corps JSON**. + +De la mรชme maniรจre, vous pouvez le dรฉclarer comme **type de retour** de la fonction, et alors la forme des donnรฉes apparaรฎtra dans l'UI automatique de documentation de l'API. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +Ici, nous utilisons la dรฉpendance `SessionDep` (une `Session`) pour ajouter le nouveau `Hero` ร  l'instance de `Session`, valider les changements dans la base, rafraรฎchir les donnรฉes dans `hero`, puis le retourner. + +### Lire les hรฉros { #read-heroes } + +Nous pouvons **lire** des `Hero` depuis la base en utilisant un `select()`. Nous pouvons inclure une `limit` et un `offset` pour paginer les rรฉsultats. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### Lire un hรฉros { #read-one-hero } + +Nous pouvons **lire** un seul `Hero`. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Supprimer un hรฉros { #delete-a-hero } + +Nous pouvons aussi **supprimer** un `Hero`. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### Exรฉcuter l'application { #run-the-app } + +Vous pouvez exรฉcuter l'application : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Ensuite, allez sur l'UI `/docs`, vous verrez que **FastAPI** utilise ces **modรจles** pour **documenter** l'API, et les utilisera aussi pour **sรฉrialiser** et **valider** les donnรฉes. + +
+ +
+ +## Mettre ร  jour l'application avec plusieurs modรจles { #update-the-app-with-multiple-models } + +Maintenant, **refactorisons** un peu cette application pour augmenter la **sรฉcuritรฉ** et la **polyvalence**. + +Si vous vรฉrifiez l'application prรฉcรฉdente, dans l'UI vous pouvez voir que, jusqu'ร  prรฉsent, elle laisse le client dรฉcider de l'`id` du `Hero` ร  crรฉer. ๐Ÿ˜ฑ + +Nous ne devrions pas laisser cela se produire, ils pourraient รฉcraser un `id` que nous avons dรฉjร  attribuรฉ dans la base. Dรฉcider de l'`id` doit รชtre fait par le **backend** ou la **base**, **pas par le client**. + +De plus, nous crรฉons un `secret_name` pour le hรฉros, mais jusqu'ici, nous le renvoyons partout, ce n'est pas trรจs ยซ secret ยป ... ๐Ÿ˜… + +Nous allons corriger ces choses en ajoutant quelques **modรจles supplรฉmentaires**. C'est lร  que SQLModel brille. โœจ + +### Crรฉer plusieurs modรจles { #create-multiple-models } + +Dans **SQLModel**, toute classe de modรจle qui a `table=True` est un **modรจle de table**. + +Et toute classe de modรจle qui n'a pas `table=True` est un **modรจle de donnรฉes**, ceux-ci sont en rรฉalitรฉ juste des modรจles Pydantic (avec deux petites fonctionnalitรฉs en plus). ๐Ÿค“ + +Avec SQLModel, nous pouvons utiliser **l'hรฉritage** pour **รฉviter de dupliquer** tous les champs dans tous les cas. + +#### `HeroBase` - la classe de base { #herobase-the-base-class } + +Commenรงons avec un modรจle `HeroBase` qui a tous les **champs partagรฉs** par tous les modรจles : + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - le *modรจle de table* { #hero-the-table-model } + +Crรฉons ensuite `Hero`, le *modรจle de table* proprement dit, avec les **champs supplรฉmentaires** qui ne sont pas toujours dans les autres modรจles : + +* `id` +* `secret_name` + +Comme `Hero` hรฉrite de `HeroBase`, il **a aussi** les **champs** dรฉclarรฉs dans `HeroBase`, donc tous les champs de `Hero` sont : + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - le *modรจle de donnรฉes* public { #heropublic-the-public-data-model } + +Ensuite, nous crรฉons un modรจle `HeroPublic`, c'est celui qui sera **retournรฉ** aux clients de l'API. + +Il a les mรชmes champs que `HeroBase`, il n'inclura donc pas `secret_name`. + +Enfin, l'identitรฉ de nos hรฉros est protรฉgรฉe ! ๐Ÿฅท + +Il redรฉclare aussi `id: int`. Ce faisant, nous faisons un **contrat** avec les clients de l'API, afin qu'ils puissent toujours s'attendre ร  ce que `id` soit prรฉsent et soit un `int` (il ne sera jamais `None`). + +/// tip | Astuce + +Avoir le modรจle de retour qui garantit qu'une valeur est toujours disponible et toujours `int` (pas `None`) est trรจs utile pour les clients de l'API, ils peuvent รฉcrire un code beaucoup plus simple avec cette certitude. + +De plus, les **clients gรฉnรฉrรฉs automatiquement** auront des interfaces plus simples, afin que les dรฉveloppeurs qui communiquent avec votre API puissent travailler bien plus facilement avec votre API. ๐Ÿ˜Ž + +/// + +Tous les champs de `HeroPublic` sont les mรชmes que dans `HeroBase`, avec `id` dรฉclarรฉ comme `int` (pas `None`) : + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - le *modรจle de donnรฉes* pour crรฉer un hรฉros { #herocreate-the-data-model-to-create-a-hero } + +Nous crรฉons maintenant un modรจle `HeroCreate`, c'est celui qui **validera** les donnรฉes provenant des clients. + +Il a les mรชmes champs que `HeroBase`, et il a aussi `secret_name`. + +Maintenant, lorsque les clients **crรฉent un nouveau hรฉros**, ils enverront `secret_name`, il sera stockรฉ dans la base, mais ces noms secrets ne seront pas renvoyรฉs dans l'API aux clients. + +/// tip | Astuce + +C'est ainsi que vous gรฉreriez les **mots de passe**. Les recevoir, mais ne pas les renvoyer dans l'API. + +Vous **hacherez** aussi les valeurs des mots de passe avant de les stocker, **ne les stockez jamais en texte en clair**. + +/// + +Les champs de `HeroCreate` sont : + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - le *modรจle de donnรฉes* pour mettre ร  jour un hรฉros { #heroupdate-the-data-model-to-update-a-hero } + +Nous n'avions pas de moyen de **mettre ร  jour un hรฉros** dans la version prรฉcรฉdente de l'application, mais maintenant avec **plusieurs modรจles**, nous pouvons le faire. ๐ŸŽ‰ + +Le *modรจle de donnรฉes* `HeroUpdate` est un peu spรฉcial, il a **tous les mรชmes champs** qui seraient nรฉcessaires pour crรฉer un nouveau hรฉros, mais tous les champs sont **optionnels** (ils ont tous une valeur par dรฉfaut). Ainsi, lorsque vous mettez ร  jour un hรฉros, vous pouvez n'envoyer que les champs que vous souhaitez mettre ร  jour. + +Comme tous les **champs changent rรฉellement** (le type inclut dรฉsormais `None` et ils ont maintenant une valeur par dรฉfaut de `None`), nous devons les **redรฉclarer**. + +Nous n'avons pas vraiment besoin d'hรฉriter de `HeroBase` puisque nous redรฉclarons tous les champs. Je le laisse hรฉriter juste pour la cohรฉrence, mais ce n'est pas nรฉcessaire. C'est plutรดt une question de goรปt personnel. ๐Ÿคท + +Les champs de `HeroUpdate` sont : + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### Crรฉer avec `HeroCreate` et retourner un `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } + +Maintenant que nous avons **plusieurs modรจles**, nous pouvons mettre ร  jour les parties de l'application qui les utilisent. + +Nous recevons dans la requรชte un *modรจle de donnรฉes* `HeroCreate`, et ร  partir de celui-ci, nous crรฉons un *modรจle de table* `Hero`. + +Ce nouveau *modรจle de table* `Hero` aura les champs envoyรฉs par le client, et aura aussi un `id` gรฉnรฉrรฉ par la base. + +Nous retournons ensuite le mรชme *modรจle de table* `Hero` tel quel depuis la fonction. Mais comme nous dรฉclarons le `response_model` avec le *modรจle de donnรฉes* `HeroPublic`, **FastAPI** utilisera `HeroPublic` pour valider et sรฉrialiser les donnรฉes. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | Astuce + +Nous utilisons maintenant `response_model=HeroPublic` au lieu de l'**annotation de type de retour** `-> HeroPublic` car la valeur que nous renvoyons n'est en rรฉalitรฉ *pas* un `HeroPublic`. + +Si nous avions dรฉclarรฉ `-> HeroPublic`, votre รฉditeur et votre linter se plaindraient (ร  juste titre) que vous retournez un `Hero` au lieu d'un `HeroPublic`. + +En le dรฉclarant dans `response_model`, nous disons ร  **FastAPI** de faire son travail, sans interfรฉrer avec les annotations de type et l'aide de votre รฉditeur et d'autres outils. + +/// + +### Lire des hรฉros avec `HeroPublic` { #read-heroes-with-heropublic } + +Nous pouvons faire la mรชme chose qu'avant pour **lire** des `Hero`, ร  nouveau, nous utilisons `response_model=list[HeroPublic]` pour garantir que les donnรฉes sont correctement validรฉes et sรฉrialisรฉes. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### Lire un hรฉros avec `HeroPublic` { #read-one-hero-with-heropublic } + +Nous pouvons **lire** un hรฉros unique : + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### Mettre ร  jour un hรฉros avec `HeroUpdate` { #update-a-hero-with-heroupdate } + +Nous pouvons **mettre ร  jour un hรฉros**. Pour cela, nous utilisons une opรฉration HTTP `PATCH`. + +Et dans le code, nous obtenons un `dict` avec toutes les donnรฉes envoyรฉes par le client, **uniquement les donnรฉes envoyรฉes par le client**, en excluant toute valeur qui serait lร  simplement parce que c'est la valeur par dรฉfaut. Pour ce faire, nous utilisons `exclude_unset=True`. C'est l'astuce principale. ๐Ÿช„ + +Nous utilisons ensuite `hero_db.sqlmodel_update(hero_data)` pour mettre ร  jour `hero_db` avec les donnรฉes de `hero_data`. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### Supprimer un hรฉros (bis) { #delete-a-hero-again } + +**Supprimer** un hรฉros reste pratiquement identique. + +Nous n'allons pas cรฉder ร  l'envie de tout refactoriser pour celui-ci. ๐Ÿ˜… + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### Exรฉcuter l'application ร  nouveau { #run-the-app-again } + +Vous pouvez exรฉcuter l'application ร  nouveau : + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Si vous allez sur l'UI `/docs` de l'API, vous verrez qu'elle est maintenant ร  jour, et qu'elle n'attendra plus de recevoir l'`id` du client lors de la crรฉation d'un hรฉros, etc. + +
+ +
+ +## Rรฉcapitulatif { #recap } + +Vous pouvez utiliser **SQLModel** pour interagir avec une base SQL et simplifier le code avec des *modรจles de donnรฉes* et des *modรจles de table*. + +Vous pouvez en apprendre beaucoup plus dans la documentation **SQLModel**, il y a un mini tutoriel plus long sur l'utilisation de SQLModel avec **FastAPI**. ๐Ÿš€ diff --git a/docs/fr/docs/tutorial/static-files.md b/docs/fr/docs/tutorial/static-files.md new file mode 100644 index 0000000000..3928fed9bc --- /dev/null +++ b/docs/fr/docs/tutorial/static-files.md @@ -0,0 +1,40 @@ +# Fichiers statiques { #static-files } + +Vous pouvez servir des fichiers statiques automatiquement ร  partir d'un rรฉpertoire en utilisant `StaticFiles`. + +## Utiliser `StaticFiles` { #use-staticfiles } + +- Importer `StaticFiles`. +- ยซ Mount ยป une instance `StaticFiles()` sur un chemin spรฉcifique. + +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} + +/// note | Dรฉtails techniques + +Vous pouvez รฉgalement utiliser `from starlette.staticfiles import StaticFiles`. + +**FastAPI** fournit le mรชme `starlette.staticfiles` sous le nom `fastapi.staticfiles` uniquement pour votre commoditรฉ, en tant que dรฉveloppeur. Mais cela provient en rรฉalitรฉ directement de Starlette. + +/// + +### Qu'est-ce que ยซ Mounting ยป { #what-is-mounting } + +ยซ Mounting ยป signifie ajouter une application complรจte ยซ indรฉpendante ยป sur un chemin spรฉcifique, qui se chargera ensuite de gรฉrer tous les sous-chemins. + +Cela diffรจre de l'utilisation d'un `APIRouter`, car une application montรฉe est complรจtement indรฉpendante. L'OpenAPI et les documents de votre application principale n'incluront rien provenant de l'application montรฉe, etc. + +Vous pouvez en lire davantage ร  ce sujet dans le [Guide utilisateur avancรฉ](../advanced/index.md){.internal-link target=_blank}. + +## Dรฉtails { #details } + +Le premier `"/static"` fait rรฉfรฉrence au sous-chemin sur lequel cette ยซ sous-application ยป sera ยซ montรฉe ยป. Ainsi, tout chemin qui commence par `"/static"` sera gรฉrรฉ par elle. + +Le `directory="static"` fait rรฉfรฉrence au nom du rรฉpertoire qui contient vos fichiers statiques. + +Le `name="static"` lui donne un nom utilisable en interne par **FastAPI**. + +Tous ces paramรจtres peuvent รชtre diffรฉrents de ยซ `static` ยป, adaptez-les aux besoins et aux dรฉtails spรฉcifiques de votre propre application. + +## Plus d'informations { #more-info } + +Pour plus de dรฉtails et d'options, consultez la documentation de Starlette sur les fichiers statiques. diff --git a/docs/fr/docs/tutorial/testing.md b/docs/fr/docs/tutorial/testing.md new file mode 100644 index 0000000000..8a609b644d --- /dev/null +++ b/docs/fr/docs/tutorial/testing.md @@ -0,0 +1,193 @@ +# Tester { #testing } + +Grรขce ร  Starlette, tester des applications **FastAPI** est simple et agrรฉable. + +Cโ€™est basรฉ sur HTTPX, dont la conception sโ€™inspire de Requests, ce qui le rend trรจs familier et intuitif. + +Avec cela, vous pouvez utiliser pytest directement avec **FastAPI**. + +## Utiliser `TestClient` { #using-testclient } + +/// info + +Pour utiliser `TestClient`, installez dโ€™abord `httpx`. + +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, lโ€™activer, puis y installer le paquet, par exempleย : + +```console +$ pip install httpx +``` + +/// + +Importez `TestClient`. + +Crรฉez un `TestClient` en lui passant votre application **FastAPI**. + +Crรฉez des fonctions dont le nom commence par `test_` (cโ€™est la convention standard de `pytest`). + +Utilisez lโ€™objet `TestClient` de la mรชme maniรจre que vous utilisez `httpx`. + +ร‰crivez de simples instructions `assert` avec les expressions Python standard que vous devez vรฉrifier (lร  encore, standard `pytest`). + +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} + +/// tip | Astuce + +Remarquez que les fonctions de test sont des `def` normales, pas des `async def`. + +Et les appels au client sont aussi des appels normaux, sans utiliser `await`. + +Cela vous permet dโ€™utiliser `pytest` directement sans complications. + +/// + +/// note | Dรฉtails techniques + +Vous pouvez aussi utiliser `from starlette.testclient import TestClient`. + +**FastAPI** fournit le mรชme `starlette.testclient` sous le nom `fastapi.testclient` uniquement pour votre commoditรฉ, en tant que dรฉveloppeur. Mais cela vient directement de Starlette. + +/// + +/// tip | Astuce + +Si vous souhaitez appeler des fonctions `async` dans vos tests en dehors de lโ€™envoi de requรชtes ร  votre application FastAPI (par exemple des fonctions de base de donnรฉes asynchrones), consultez les [Tests asynchrones](../advanced/async-tests.md){.internal-link target=_blank} dans le tutoriel avancรฉ. + +/// + +## Sรฉparer les tests { #separating-tests } + +Dans une application rรฉelle, vous auriez probablement vos tests dans un fichier diffรฉrent. + +Et votre application **FastAPI** pourrait aussi รชtre composรฉe de plusieurs fichiers/modules, etc. + +### Fichier dโ€™application **FastAPI** { #fastapi-app-file } + +Supposons que vous ayez une structure de fichiers comme dรฉcrit dans [Applications plus grandes](bigger-applications.md){.internal-link target=_blank}ย : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ main.py +``` + +Dans le fichier `main.py`, vous avez votre application **FastAPI**ย : + + +{* ../../docs_src/app_testing/app_a_py310/main.py *} + +### Fichier de test { #testing-file } + +Vous pourriez alors avoir un fichier `test_main.py` avec vos tests. Il pourrait vivre dans le mรชme package Python (le mรชme rรฉpertoire avec un fichier `__init__.py`)ย : + +``` hl_lines="5" +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +Comme ce fichier se trouve dans le mรชme package, vous pouvez utiliser des imports relatifs pour importer lโ€™objet `app` depuis le module `main` (`main.py`)ย : + +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + + +โ€ฆ et avoir le code des tests comme prรฉcรฉdemment. + +## Testerย : exemple รฉtendu { #testing-extended-example } + +ร‰tendons maintenant cet exemple et ajoutons plus de dรฉtails pour voir comment tester diffรฉrentes parties. + +### Fichier dโ€™application **FastAPI** รฉtendu { #extended-fastapi-app-file } + +Continuons avec la mรชme structure de fichiers quโ€™auparavantย : + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +Supposons que dรฉsormais le fichier `main.py` avec votre application **FastAPI** contienne dโ€™autres **chemins dโ€™accรจs**. + +Il a une opรฉration `GET` qui pourrait renvoyer une erreur. + +Il a une opรฉration `POST` qui pourrait renvoyer plusieurs erreurs. + +Les deux chemins dโ€™accรจs requiรจrent un en-tรชte `X-Token`. + +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} + +### Fichier de test รฉtendu { #extended-testing-file } + +Vous pourriez ensuite mettre ร  jour `test_main.py` avec les tests รฉtendusย : + +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + + +Chaque fois que vous avez besoin que le client transmette des informations dans la requรชte et que vous ne savez pas comment faire, vous pouvez chercher (Google) comment le faire avec `httpx`, ou mรชme comment le faire avec `requests`, puisque la conception de HTTPX est basรฉe sur celle de Requests. + +Ensuite, vous faites simplement la mรชme chose dans vos tests. + +Par exempleย : + +* Pour passer un paramรจtre de chemin ou un paramรจtre de requรชte, ajoutez-le directement ร  lโ€™URL. +* Pour passer un corps JSON, passez un objet Python (par exemple un `dict`) au paramรจtre `json`. +* Si vous devez envoyer des *Form Data* au lieu de JSON, utilisez le paramรจtre `data` ร  la place. +* Pour passer des en-tรชtes, utilisez un `dict` dans le paramรจtre `headers`. +* Pour les cookies, un `dict` dans le paramรจtre `cookies`. + +Pour plus dโ€™informations sur la maniรจre de transmettre des donnรฉes au backend (en utilisant `httpx` ou le `TestClient`), consultez la documentation HTTPX. + +/// info + +Notez que le `TestClient` reรงoit des donnรฉes qui peuvent รชtre converties en JSON, pas des modรจles Pydantic. + +Si vous avez un modรจle Pydantic dans votre test et que vous souhaitez envoyer ses donnรฉes ร  lโ€™application pendant les tests, vous pouvez utiliser le `jsonable_encoder` dรฉcrit dans [Encodeur compatible JSON](encoder.md){.internal-link target=_blank}. + +/// + +## Exรฉcuter { #run-it } + +Aprรจs cela, vous avez simplement besoin dโ€™installer `pytest`. + +Vous devez crรฉer un [environnement virtuel](../virtual-environments.md){.internal-link target=_blank}, lโ€™activer, puis y installer le paquet, par exempleย : + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +Il dรฉtectera automatiquement les fichiers et les tests, les exรฉcutera et vous communiquera les rรฉsultats. + +Exรฉcutez les tests avecย : + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/fr/docs/virtual-environments.md b/docs/fr/docs/virtual-environments.md new file mode 100644 index 0000000000..86b5faadce --- /dev/null +++ b/docs/fr/docs/virtual-environments.md @@ -0,0 +1,864 @@ +# Environnements virtuels { #virtual-environments } + +Lorsque vous travaillez sur des projets Python, vous devriez probablement utiliser un environnement virtuel (ou un mรฉcanisme similaire) pour isoler les packages que vous installez pour chaque projet. + +/// info + +Si vous connaissez dรฉjร  les environnements virtuels, comment les crรฉer et les utiliser, vous pouvez passer cette section. ๐Ÿค“ + +/// + +/// tip | Astuce + +Un environnement virtuel est diffรฉrent dโ€™une variable dโ€™environnement. + +Une variable dโ€™environnement est une variable du systรจme qui peut รชtre utilisรฉe par des programmes. + +Un environnement virtuel est un rรฉpertoire contenant certains fichiers. + +/// + +/// info + +Cette page vous apprendra ร  utiliser les environnements virtuels et ร  comprendre leur fonctionnement. + +Si vous รชtes prรชt ร  adopter un outil qui gรจre tout pour vous (y compris lโ€™installation de Python), essayez uv. + +/// + +## Crรฉer un projet { #create-a-project } + +Commencez par crรฉer un rรฉpertoire pour votre projet. + +Ce que je fais gรฉnรฉralement, cโ€™est crรฉer un rรฉpertoire nommรฉ `code` dans mon rรฉpertoire personnel/utilisateur. + +Et ร  lโ€™intรฉrieur, je crรฉe un rรฉpertoire par projet. + +
+ +```console +// Aller au rรฉpertoire personnel +$ cd +// Crรฉer un rรฉpertoire pour tous vos projets de code +$ mkdir code +// Entrer dans ce rรฉpertoire code +$ cd code +// Crรฉer un rรฉpertoire pour ce projet +$ mkdir awesome-project +// Entrer dans ce rรฉpertoire de projet +$ cd awesome-project +``` + +
+ +## Crรฉer un environnement virtuel { #create-a-virtual-environment } + +Lorsque vous commencez ร  travailler sur un projet Python pour la premiรจre fois, crรฉez un environnement virtuel dans votre projet. + +/// tip | Astuce + +Vous nโ€™avez besoin de faire cela quโ€™une seule fois par projet, pas ร  chaque fois que vous travaillez. + +/// + +//// tab | `venv` + +Pour crรฉer un environnement virtuel, vous pouvez utiliser le module `venv` fourni avec Python. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | Que signifie cette commande + +* `python` : utiliser le programme nommรฉ `python` +* `-m` : appeler un module comme un script, nous prรฉciserons ensuite quel module +* `venv` : utiliser le module nommรฉ `venv` qui est normalement installรฉ avec Python +* `.venv` : crรฉer lโ€™environnement virtuel dans le nouveau rรฉpertoire `.venv` + +/// + +//// + +//// tab | `uv` + +Si vous avez installรฉ `uv`, vous pouvez lโ€™utiliser pour crรฉer un environnement virtuel. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | Astuce + +Par dรฉfaut, `uv` crรฉera un environnement virtuel dans un rรฉpertoire appelรฉ `.venv`. + +Mais vous pouvez le personnaliser en passant un argument supplรฉmentaire avec le nom du rรฉpertoire. + +/// + +//// + +Cette commande crรฉe un nouvel environnement virtuel dans un rรฉpertoire appelรฉ `.venv`. + +/// details | `.venv` ou autre nom + +Vous pourriez crรฉer lโ€™environnement virtuel dans un autre rรฉpertoire, mais il est dโ€™usage de lโ€™appeler `.venv`. + +/// + +## Activer lโ€™environnement virtuel { #activate-the-virtual-environment } + +Activez le nouvel environnement virtuel afin que toute commande Python que vous exรฉcutez ou tout package que vous installez lโ€™utilise. + +/// tip | Astuce + +Faites cela ร  chaque fois que vous dรฉmarrez une nouvelle session de terminal pour travailler sur le projet. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Ou si vous utilisez Bash pour Windows (par exemple Git Bash) : + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | Astuce + +Chaque fois que vous installez un nouveau package dans cet environnement, activez de nouveau lโ€™environnement. + +Vous vous assurez ainsi que si vous utilisez un programme de terminal (CLI) installรฉ par ce package, vous utilisez celui de votre environnement virtuel et non un autre qui pourrait รชtre installรฉ globalement, probablement avec une version diffรฉrente de celle dont vous avez besoin. + +/// + +## Vรฉrifier que lโ€™environnement virtuel est actif { #check-the-virtual-environment-is-active } + +Vรฉrifiez que lโ€™environnement virtuel est actif (la commande prรฉcรฉdente a fonctionnรฉ). + +/// tip | Astuce + +Cโ€™est facultatif, mais cโ€™est une bonne maniรจre de vรฉrifier que tout fonctionne comme prรฉvu et que vous utilisez lโ€™environnement virtuel voulu. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +Sโ€™il affiche le binaire `python` ร  `.venv/bin/python`, dans votre projet (dans cet exemple `awesome-project`), alors cela a fonctionnรฉ. ๐ŸŽ‰ + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +Sโ€™il affiche le binaire `python` ร  `.venv\Scripts\python`, dans votre projet (dans cet exemple `awesome-project`), alors cela a fonctionnรฉ. ๐ŸŽ‰ + +//// + +## Mettre ร  niveau `pip` { #upgrade-pip } + +/// tip | Astuce + +Si vous utilisez `uv`, vous lโ€™utiliserez pour installer des รฉlรฉments ร  la place de `pip`, vous nโ€™avez donc pas besoin de mettre `pip` ร  niveau. ๐Ÿ˜Ž + +/// + +Si vous utilisez `pip` pour installer des packages (il est fourni par dรฉfaut avec Python), vous devez le mettre ร  niveau vers la derniรจre version. + +Beaucoup dโ€™erreurs exotiques lors de lโ€™installation dโ€™un package se rรฉsolvent simplement en mettant dโ€™abord `pip` ร  niveau. + +/// tip | Astuce + +Vous feriez normalement cela une seule fois, juste aprรจs avoir crรฉรฉ lโ€™environnement virtuel. + +/// + +Vous devez vous assurer que lโ€™environnement virtuel est actif (avec la commande ci-dessus), puis exรฉcuter : + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +/// tip | Astuce + +Parfois, vous pourriez obtenir une erreur **`No module named pip`** en essayant de mettre ร  niveau pip. + +Si cela arrive, installez et mettez ร  niveau pip avec la commande ci-dessous : + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +Cette commande installera pip sโ€™il nโ€™est pas dรฉjร  installรฉ et garantit aussi que la version de pip installรฉe est au moins aussi rรฉcente que celle disponible dans `ensurepip`. + +/// + +## Ajouter `.gitignore` { #add-gitignore } + +Si vous utilisez Git (vous devriez), ajoutez un fichier `.gitignore` pour exclure tout ce qui se trouve dans votre `.venv` de Git. + +/// tip | Astuce + +Si vous avez utilisรฉ `uv` pour crรฉer lโ€™environnement virtuel, il lโ€™a dรฉjร  fait pour vous, vous pouvez passer cette รฉtape. ๐Ÿ˜Ž + +/// + +/// tip | Astuce + +Faites cela une seule fois, juste aprรจs avoir crรฉรฉ lโ€™environnement virtuel. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | Que signifie cette commande + +* `echo "*"` : va ยซ afficher ยป le texte `*` dans le terminal (la partie suivante change un peu cela) +* `>` : tout ce qui est affichรฉ dans le terminal par la commande ร  gauche de `>` ne doit pas รชtre affichรฉ mais รฉcrit dans le fichier ร  droite de `>` +* `.gitignore` : le nom du fichier dans lequel le texte doit รชtre รฉcrit + +Et `*` signifie pour Git ยซ tout ยป. Ainsi, il ignorera tout dans le rรฉpertoire `.venv`. + +Cette commande crรฉera un fichier `.gitignore` avec le contenu : + +```gitignore +* +``` + +/// + +## Installer des packages { #install-packages } + +Aprรจs avoir activรฉ lโ€™environnement, vous pouvez y installer des packages. + +/// tip | Astuce + +Faites cela une seule fois lorsque vous installez ou mettez ร  niveau les packages nรฉcessaires ร  votre projet. + +Si vous devez mettre ร  niveau une version ou ajouter un nouveau package, vous le referez. + +/// + +### Installer des packages directement { #install-packages-directly } + +Si vous รชtes pressรฉ et ne souhaitez pas utiliser un fichier pour dรฉclarer les dรฉpendances de votre projet, vous pouvez les installer directement. + +/// tip | Astuce + +Cโ€™est une trรจs bonne idรฉe de placer les packages et leurs versions nรฉcessaires ร  votre programme dans un fichier (par exemple `requirements.txt` ou `pyproject.toml`). + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Si vous avez `uv` : + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### Installer depuis `requirements.txt` { #install-from-requirements-txt } + +Si vous avez un `requirements.txt`, vous pouvez maintenant lโ€™utiliser pour installer ses packages. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Si vous avez `uv` : + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +Un `requirements.txt` avec quelques packages pourrait ressembler ร  : + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## Exรฉcuter votre programme { #run-your-program } + +Aprรจs avoir activรฉ lโ€™environnement virtuel, vous pouvez exรฉcuter votre programme, et il utilisera le Python de votre environnement virtuel avec les packages que vous y avez installรฉs. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## Configurer votre รฉditeur { #configure-your-editor } + +Vous utiliserez probablement un รฉditeur, assurez-vous de le configurer pour utiliser le mรชme environnement virtuel que vous avez crรฉรฉ (il le dรฉtectera probablement automatiquement) afin dโ€™avoir lโ€™autocomplรฉtion et les erreurs inline. + +Par exemple : + +* VS Code +* PyCharm + +/// tip | Astuce + +Vous devez normalement faire cela une seule fois, lorsque vous crรฉez lโ€™environnement virtuel. + +/// + +## Dรฉsactiver lโ€™environnement virtuel { #deactivate-the-virtual-environment } + +Une fois que vous avez fini de travailler sur votre projet, vous pouvez dรฉsactiver lโ€™environnement virtuel. + +
+ +```console +$ deactivate +``` + +
+ +Ainsi, lorsque vous exรฉcutez `python`, il nโ€™essaiera pas de lโ€™exรฉcuter depuis cet environnement virtuel avec les packages qui y sont installรฉs. + +## Prรชt ร  travailler { #ready-to-work } + +Vous รชtes maintenant prรชt ร  commencer ร  travailler sur votre projet. + + + +/// tip | Astuce + +Voulez-vous comprendre tout ce qui prรฉcรจde ? + +Continuez la lecture. ๐Ÿ‘‡๐Ÿค“ + +/// + +## Pourquoi des environnements virtuels { #why-virtual-environments } + +Pour travailler avec FastAPI, vous devez installer Python. + +Ensuite, vous devrez installer FastAPI et tout autre package que vous souhaitez utiliser. + +Pour installer des packages, vous utiliseriez normalement la commande `pip` fournie avec Python (ou des alternatives similaires). + +Nรฉanmoins, si vous utilisez simplement `pip` directement, les packages seraient installรฉs dans votre environnement Python global (lโ€™installation globale de Python). + +### Le problรจme { #the-problem } + +Alors, quel est le problรจme dโ€™installer des packages dans lโ€™environnement Python global ? + +ร€ un moment donnรฉ, vous finirez probablement par รฉcrire de nombreux programmes diffรฉrents qui dรฉpendent de packages diffรฉrents. Et certains de ces projets sur lesquels vous travaillez dรฉpendront de versions diffรฉrentes du mรชme package. ๐Ÿ˜ฑ + +Par exemple, vous pourriez crรฉer un projet appelรฉ `philosophers-stone`, ce programme dรฉpend dโ€™un autre package appelรฉ **`harry`, en version `1`**. Vous devez donc installer `harry`. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +Puis, plus tard, vous crรฉez un autre projet appelรฉ `prisoner-of-azkaban`, et ce projet dรฉpend aussi de `harry`, mais il a besoin de **`harry` en version `3`**. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +Mais maintenant, le problรจme est que, si vous installez les packages globalement (dans lโ€™environnement global) au lieu de dans un environnement virtuel local, vous devrez choisir quelle version de `harry` installer. + +Si vous voulez exรฉcuter `philosophers-stone`, vous devrez dโ€™abord installer `harry` en version `1`, par exemple avec : + +
+ +```console +$ pip install "harry==1" +``` + +
+ +Et vous vous retrouverez avec `harry` en version `1` installรฉ dans votre environnement Python global. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +Mais si vous voulez ensuite exรฉcuter `prisoner-of-azkaban`, vous devrez dรฉsinstaller `harry` version `1` et installer `harry` version `3` (ou bien installer la version `3` dรฉsinstallerait automatiquement la version `1`). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +Et vous vous retrouverez alors avec `harry` version `3` installรฉ dans votre environnement Python global. + +Et si vous essayez dโ€™exรฉcuter ร  nouveau `philosophers-stone`, il y a une chance que cela ne fonctionne pas car il a besoin de `harry` version `1`. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|โ›”๏ธ| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | Astuce + +Il est trรจs courant que les packages Python fassent de leur mieux pour รฉviter les changements cassants dans les nouvelles versions, mais il vaut mieux jouer la sรฉcuritรฉ et installer de nouvelles versions intentionnellement et lorsque vous pouvez exรฉcuter les tests pour vรฉrifier que tout fonctionne correctement. + +/// + +Maintenant, imaginez cela avec beaucoup dโ€™autres packages dont tous vos projets dรฉpendent. Cโ€™est trรจs difficile ร  gรฉrer. Et vous finiriez probablement par exรฉcuter certains projets avec des versions incompatibles des packages, sans savoir pourquoi quelque chose ne fonctionne pas. + +De plus, selon votre systรจme dโ€™exploitation (par exemple Linux, Windows, macOS), il se peut quโ€™il soit livrรฉ avec Python dรฉjร  installรฉ. Et dans ce cas, il avait probablement des packages prรฉinstallรฉs avec des versions spรฉcifiques nรฉcessaires ร  votre systรจme. Si vous installez des packages dans lโ€™environnement Python global, vous pourriez finir par casser certains des programmes fournis avec votre systรจme dโ€™exploitation. + +## Oรน les packages sont-ils installรฉs { #where-are-packages-installed } + +Lorsque vous installez Python, il crรฉe des rรฉpertoires avec des fichiers sur votre ordinateur. + +Certains de ces rรฉpertoires sont chargรฉs de contenir tous les packages que vous installez. + +Lorsque vous exรฉcutez : + +
+ +```console +// Ne lโ€™exรฉcutez pas maintenant, cโ€™est juste un exemple ๐Ÿค“ +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +Cela tรฉlรฉchargera un fichier compressรฉ avec le code de FastAPI, normalement depuis PyPI. + +Il tรฉlรฉchargera รฉgalement des fichiers pour dโ€™autres packages dont FastAPI dรฉpend. + +Ensuite, il extraira tous ces fichiers et les placera dans un rรฉpertoire de votre ordinateur. + +Par dรฉfaut, il placera ces fichiers tรฉlรฉchargรฉs et extraits dans le rรฉpertoire fourni avec votre installation de Python, cโ€™est lโ€™environnement global. + +## Quโ€™est-ce quโ€™un environnement virtuel { #what-are-virtual-environments } + +La solution aux problรจmes posรฉs par le fait dโ€™avoir tous les packages dans lโ€™environnement global est dโ€™utiliser un environnement virtuel pour chaque projet sur lequel vous travaillez. + +Un environnement virtuel est un rรฉpertoire, trรจs similaire ร  celui global, oรน vous pouvez installer les packages pour un projet. + +De cette maniรจre, chaque projet aura son propre environnement virtuel (rรฉpertoire `.venv`) avec ses propres packages. + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Que signifie activer un environnement virtuel { #what-does-activating-a-virtual-environment-mean } + +Lorsque vous activez un environnement virtuel, par exemple avec : + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Ou si vous utilisez Bash pour Windows (par exemple Git Bash) : + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +Cette commande crรฉera ou modifiera certaines [variables dโ€™environnement](environment-variables.md){.internal-link target=_blank} qui seront disponibles pour les prochaines commandes. + +Lโ€™une de ces variables est la variable `PATH`. + +/// tip | Astuce + +Vous pouvez en savoir plus sur la variable dโ€™environnement `PATH` dans la section [Variables dโ€™environnement](environment-variables.md#path-environment-variable){.internal-link target=_blank}. + +/// + +Activer un environnement virtuel ajoute son chemin `.venv/bin` (sur Linux et macOS) ou `.venv\Scripts` (sur Windows) ร  la variable dโ€™environnement `PATH`. + +Disons quโ€™avant dโ€™activer lโ€™environnement, la variable `PATH` ressemblait ร  ceci : + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +Cela signifie que le systรจme chercherait des programmes dansโ€ฏ: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +Cela signifie que le systรจme chercherait des programmes dansโ€ฏ: + +* `C:\Windows\System32` + +//// + +Aprรจs avoir activรฉ lโ€™environnement virtuel, la variable `PATH` ressemblerait ร  quelque chose comme ceci : + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Cela signifie que le systรจme commencera maintenant par chercher des programmes dansโ€ฏ: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +avant de chercher dans les autres rรฉpertoires. + +Ainsi, lorsque vous tapez `python` dans le terminal, le systรจme trouvera le programme Python dans + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +et utilisera celui-ci. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +Cela signifie que le systรจme commencera maintenant par chercher des programmes dansโ€ฏ: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +avant de chercher dans les autres rรฉpertoires. + +Ainsi, lorsque vous tapez `python` dans le terminal, le systรจme trouvera le programme Python dans + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +et utilisera celui-ci. + +//// + +Un dรฉtail important est quโ€™il placera le chemin de lโ€™environnement virtuel au dรฉbut de la variable `PATH`. Le systรจme le trouvera avant de trouver tout autre Python disponible. Ainsi, lorsque vous exรฉcutez `python`, il utilisera le Python de lโ€™environnement virtuel au lieu de tout autre `python` (par exemple, un `python` dโ€™un environnement global). + +Activer un environnement virtuel change aussi deux ou trois autres choses, mais cโ€™est lโ€™un des points les plus importants. + +## Vรฉrifier un environnement virtuel { #checking-a-virtual-environment } + +Lorsque vous vรฉrifiez si un environnement virtuel est actif, par exemple avec : + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +Cela signifie que le programme `python` qui sera utilisรฉ est celui dans lโ€™environnement virtuel. + +Vous utilisez `which` sous Linux et macOS et `Get-Command` sous Windows PowerShell. + +La faรงon dont cette commande fonctionne est quโ€™elle va vรฉrifier la variable dโ€™environnement `PATH`, en parcourant chaque chemin dans lโ€™ordre, ร  la recherche du programme nommรฉ `python`. Une fois trouvรฉ, elle vous affichera le chemin vers ce programme. + +La partie la plus importante est que lorsque vous appelez `python`, cโ€™est exactement ยซ `python` ยป qui sera exรฉcutรฉ. + +Ainsi, vous pouvez confirmer si vous รชtes dans le bon environnement virtuel. + +/// tip | Astuce + +Il est facile dโ€™activer un environnement virtuel, dโ€™obtenir un Python, puis dโ€™aller vers un autre projet. + +Et le second projet ne fonctionnerait pas parce que vous utilisez le Python incorrect, provenant dโ€™un environnement virtuel dโ€™un autre projet. + +Il est utile de pouvoir vรฉrifier quel `python` est utilisรฉ. ๐Ÿค“ + +/// + +## Pourquoi dรฉsactiver un environnement virtuel { #why-deactivate-a-virtual-environment } + +Par exemple, vous pourriez travailler sur un projet `philosophers-stone`, activer cet environnement virtuel, installer des packages et travailler avec cet environnement. + +Puis vous souhaitez travailler sur un autre projet `prisoner-of-azkaban`. + +Vous allez vers ce projet : + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +Si vous ne dรฉsactivez pas lโ€™environnement virtuel de `philosophers-stone`, lorsque vous exรฉcutez `python` dans le terminal, il essaiera dโ€™utiliser le Python de `philosophers-stone`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Erreur lors de l'import de sirius, il n'est pas installรฉ ๐Ÿ˜ฑ +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +Mais si vous dรฉsactivez lโ€™environnement virtuel et activez le nouveau pour `prisoner-of-askaban`, alors lorsque vous exรฉcuterez `python`, il utilisera le Python de lโ€™environnement virtuel de `prisoner-of-azkaban`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// Vous nโ€™avez pas besoin dโ€™รชtre dans lโ€™ancien rรฉpertoire pour dรฉsactiver, vous pouvez le faire oรน que vous soyez, mรชme aprรจs รชtre allรฉ dans lโ€™autre projet ๐Ÿ˜Ž +$ deactivate + +// Activer lโ€™environnement virtuel dans prisoner-of-azkaban/.venv ๐Ÿš€ +$ source .venv/bin/activate + +// Maintenant, lorsque vous exรฉcutez python, il trouvera le package sirius installรฉ dans cet environnement virtuel โœจ +$ python main.py + +I solemnly swear ๐Ÿบ +``` + +
+ +## Alternatives { #alternatives } + +Ceci est un guide simple pour vous lancer et vous montrer comment tout fonctionne en dessous. + +Il existe de nombreuses alternatives pour gรฉrer les environnements virtuels, les dรฉpendances de packages (requirements), les projets. + +Lorsque vous รชtes prรชt et souhaitez utiliser un outil pour gรฉrer lโ€™ensemble du projet, les dรฉpendances, les environnements virtuels, etc., je vous suggรจre dโ€™essayer uv. + +`uv` peut faire beaucoup de choses, il peutโ€ฏ: + +* Installer Python pour vous, y compris diffรฉrentes versions +* Gรฉrer lโ€™environnement virtuel pour vos projets +* Installer des packages +* Gรฉrer les dรฉpendances de packages et leurs versions pour votre projet +* Vous assurer dโ€™avoir un ensemble exact de packages et de versions ร  installer, y compris leurs dรฉpendances, afin que vous puissiez รชtre certain dโ€™exรฉcuter votre projet en production exactement comme sur votre ordinateur pendant le dรฉveloppement, cela sโ€™appelle le locking +* Et bien dโ€™autres choses + +## Conclusion { #conclusion } + +Si vous avez lu et compris tout cela, vous en savez maintenant bien plus sur les environnements virtuels que beaucoup de dรฉveloppeurs. ๐Ÿค“ + +Connaรฎtre ces dรฉtails vous sera trรจs probablement utile ร  lโ€™avenir lorsque vous dรฉboguerez quelque chose qui semble complexe, mais vous saurez comment tout fonctionne en dessous. ๐Ÿ˜Ž From dd97806864e5e8d9d9af9b80f7c3177a88735cc8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Feb 2026 08:13:07 +0000 Subject: [PATCH 238/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 631de06115..5ba810aeab 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for fr (update-all and add-missing). PR [#14920](https://github.com/fastapi/fastapi/pull/14920) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-all) . PR [#14910](https://github.com/fastapi/fastapi/pull/14910) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov). From 9a082312f38c7878bc9f5b5dfa6aa0c3ddee88aa Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:15:26 +0100 Subject: [PATCH 239/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(update-all=20and=20add-missing)=20(#14921)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all * Add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/zh-hant/docs/_llm-test.md | 503 ++++++++++++++ .../docs/advanced/additional-responses.md | 247 +++++++ .../docs/advanced/additional-status-codes.md | 41 ++ .../docs/advanced/advanced-dependencies.md | 163 +++++ .../docs/advanced/advanced-python-types.md | 61 ++ docs/zh-hant/docs/advanced/async-tests.md | 99 +++ docs/zh-hant/docs/advanced/behind-a-proxy.md | 466 +++++++++++++ docs/zh-hant/docs/advanced/custom-response.md | 312 +++++++++ docs/zh-hant/docs/advanced/dataclasses.md | 87 +++ docs/zh-hant/docs/advanced/events.md | 165 +++++ .../zh-hant/docs/advanced/generate-clients.md | 208 ++++++ docs/zh-hant/docs/advanced/index.md | 21 + docs/zh-hant/docs/advanced/middleware.md | 97 +++ .../docs/advanced/openapi-callbacks.md | 186 ++++++ .../zh-hant/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 172 +++++ .../advanced/response-change-status-code.md | 31 + .../zh-hant/docs/advanced/response-cookies.md | 51 ++ .../docs/advanced/response-directly.md | 65 ++ .../zh-hant/docs/advanced/response-headers.md | 41 ++ .../docs/advanced/security/http-basic-auth.md | 107 +++ docs/zh-hant/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++++ docs/zh-hant/docs/advanced/settings.md | 302 +++++++++ .../zh-hant/docs/advanced/sub-applications.md | 67 ++ docs/zh-hant/docs/advanced/templates.md | 126 ++++ .../docs/advanced/testing-dependencies.md | 53 ++ docs/zh-hant/docs/advanced/testing-events.md | 11 + .../docs/advanced/testing-websockets.md | 13 + .../docs/advanced/using-request-directly.md | 56 ++ docs/zh-hant/docs/advanced/websockets.md | 186 ++++++ docs/zh-hant/docs/advanced/wsgi.md | 51 ++ docs/zh-hant/docs/alternatives.md | 485 ++++++++++++++ docs/zh-hant/docs/async.md | 80 +-- docs/zh-hant/docs/benchmarks.md | 4 +- docs/zh-hant/docs/deployment/concepts.md | 321 +++++++++ docs/zh-hant/docs/deployment/docker.md | 618 ++++++++++++++++++ docs/zh-hant/docs/deployment/fastapicloud.md | 65 ++ docs/zh-hant/docs/deployment/https.md | 231 +++++++ docs/zh-hant/docs/deployment/index.md | 2 +- docs/zh-hant/docs/deployment/manually.md | 157 +++++ .../zh-hant/docs/deployment/server-workers.md | 139 ++++ docs/zh-hant/docs/deployment/versions.md | 93 +++ docs/zh-hant/docs/fastapi-cli.md | 88 ++- docs/zh-hant/docs/features.md | 70 +- docs/zh-hant/docs/help-fastapi.md | 255 ++++++++ docs/zh-hant/docs/history-design-future.md | 79 +++ .../authentication-error-status-code.md | 15 + .../docs/how-to/conditional-openapi.md | 56 ++ .../docs/how-to/configure-swagger-ui.md | 70 ++ .../docs/how-to/custom-docs-ui-assets.md | 185 ++++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/zh-hant/docs/how-to/extending-openapi.md | 80 +++ docs/zh-hant/docs/how-to/general.md | 39 ++ docs/zh-hant/docs/how-to/graphql.md | 60 ++ ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 ++++ .../docs/how-to/separate-openapi-schemas.md | 102 +++ docs/zh-hant/docs/how-to/testing-database.md | 7 + docs/zh-hant/docs/index.md | 10 +- docs/zh-hant/docs/project-generation.md | 28 + docs/zh-hant/docs/python-types.md | 348 ++++++++++ docs/zh-hant/docs/translation-banner.md | 11 + .../zh-hant/docs/tutorial/background-tasks.md | 84 +++ .../docs/tutorial/bigger-applications.md | 504 ++++++++++++++ docs/zh-hant/docs/tutorial/body-fields.md | 61 ++ .../docs/tutorial/body-multiple-params.md | 165 +++++ .../docs/tutorial/body-nested-models.md | 220 +++++++ docs/zh-hant/docs/tutorial/body-updates.md | 100 +++ docs/zh-hant/docs/tutorial/body.md | 164 +++++ .../docs/tutorial/cookie-param-models.md | 76 +++ docs/zh-hant/docs/tutorial/cookie-params.md | 45 ++ docs/zh-hant/docs/tutorial/cors.md | 88 +++ docs/zh-hant/docs/tutorial/debugging.md | 113 ++++ .../dependencies/classes-as-dependencies.md | 288 ++++++++ ...pendencies-in-path-operation-decorators.md | 69 ++ .../dependencies/dependencies-with-yield.md | 288 ++++++++ .../dependencies/global-dependencies.md | 15 + .../docs/tutorial/dependencies/index.md | 248 +++++++ .../tutorial/dependencies/sub-dependencies.md | 105 +++ docs/zh-hant/docs/tutorial/encoder.md | 35 + .../zh-hant/docs/tutorial/extra-data-types.md | 62 ++ docs/zh-hant/docs/tutorial/extra-models.md | 211 ++++++ docs/zh-hant/docs/tutorial/first-steps.md | 16 +- docs/zh-hant/docs/tutorial/handling-errors.md | 244 +++++++ .../docs/tutorial/header-param-models.md | 72 ++ docs/zh-hant/docs/tutorial/header-params.md | 91 +++ docs/zh-hant/docs/tutorial/metadata.md | 120 ++++ docs/zh-hant/docs/tutorial/middleware.md | 95 +++ .../tutorial/path-operation-configuration.md | 107 +++ .../path-params-numeric-validations.md | 154 +++++ docs/zh-hant/docs/tutorial/path-params.md | 251 +++++++ .../tutorial/query-params-str-validations.md | 449 +++++++++++++ docs/zh-hant/docs/tutorial/query-params.md | 187 ++++++ docs/zh-hant/docs/tutorial/request-files.md | 176 +++++ .../docs/tutorial/request-form-models.md | 78 +++ .../docs/tutorial/request-forms-and-files.md | 41 ++ docs/zh-hant/docs/tutorial/request-forms.md | 73 +++ docs/zh-hant/docs/tutorial/response-model.md | 343 ++++++++++ .../docs/tutorial/response-status-code.md | 101 +++ .../docs/tutorial/schema-extra-example.md | 202 ++++++ .../docs/tutorial/security/first-steps.md | 203 ++++++ .../tutorial/security/get-current-user.md | 105 +++ docs/zh-hant/docs/tutorial/security/index.md | 101 +++ .../docs/tutorial/security/oauth2-jwt.md | 277 ++++++++ .../docs/tutorial/security/simple-oauth2.md | 289 ++++++++ docs/zh-hant/docs/tutorial/sql-databases.md | 357 ++++++++++ docs/zh-hant/docs/tutorial/static-files.md | 40 ++ docs/zh-hant/docs/tutorial/testing.md | 193 ++++++ docs/zh-hant/docs/virtual-environments.md | 6 +- 109 files changed, 15445 insertions(+), 145 deletions(-) create mode 100644 docs/zh-hant/docs/_llm-test.md create mode 100644 docs/zh-hant/docs/advanced/additional-responses.md create mode 100644 docs/zh-hant/docs/advanced/additional-status-codes.md create mode 100644 docs/zh-hant/docs/advanced/advanced-dependencies.md create mode 100644 docs/zh-hant/docs/advanced/advanced-python-types.md create mode 100644 docs/zh-hant/docs/advanced/async-tests.md create mode 100644 docs/zh-hant/docs/advanced/behind-a-proxy.md create mode 100644 docs/zh-hant/docs/advanced/custom-response.md create mode 100644 docs/zh-hant/docs/advanced/dataclasses.md create mode 100644 docs/zh-hant/docs/advanced/events.md create mode 100644 docs/zh-hant/docs/advanced/generate-clients.md create mode 100644 docs/zh-hant/docs/advanced/index.md create mode 100644 docs/zh-hant/docs/advanced/middleware.md create mode 100644 docs/zh-hant/docs/advanced/openapi-callbacks.md create mode 100644 docs/zh-hant/docs/advanced/openapi-webhooks.md create mode 100644 docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md create mode 100644 docs/zh-hant/docs/advanced/response-change-status-code.md create mode 100644 docs/zh-hant/docs/advanced/response-cookies.md create mode 100644 docs/zh-hant/docs/advanced/response-directly.md create mode 100644 docs/zh-hant/docs/advanced/response-headers.md create mode 100644 docs/zh-hant/docs/advanced/security/http-basic-auth.md create mode 100644 docs/zh-hant/docs/advanced/security/index.md create mode 100644 docs/zh-hant/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/zh-hant/docs/advanced/settings.md create mode 100644 docs/zh-hant/docs/advanced/sub-applications.md create mode 100644 docs/zh-hant/docs/advanced/templates.md create mode 100644 docs/zh-hant/docs/advanced/testing-dependencies.md create mode 100644 docs/zh-hant/docs/advanced/testing-events.md create mode 100644 docs/zh-hant/docs/advanced/testing-websockets.md create mode 100644 docs/zh-hant/docs/advanced/using-request-directly.md create mode 100644 docs/zh-hant/docs/advanced/websockets.md create mode 100644 docs/zh-hant/docs/advanced/wsgi.md create mode 100644 docs/zh-hant/docs/alternatives.md create mode 100644 docs/zh-hant/docs/deployment/concepts.md create mode 100644 docs/zh-hant/docs/deployment/docker.md create mode 100644 docs/zh-hant/docs/deployment/fastapicloud.md create mode 100644 docs/zh-hant/docs/deployment/https.md create mode 100644 docs/zh-hant/docs/deployment/manually.md create mode 100644 docs/zh-hant/docs/deployment/server-workers.md create mode 100644 docs/zh-hant/docs/deployment/versions.md create mode 100644 docs/zh-hant/docs/help-fastapi.md create mode 100644 docs/zh-hant/docs/history-design-future.md create mode 100644 docs/zh-hant/docs/how-to/authentication-error-status-code.md create mode 100644 docs/zh-hant/docs/how-to/conditional-openapi.md create mode 100644 docs/zh-hant/docs/how-to/configure-swagger-ui.md create mode 100644 docs/zh-hant/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/zh-hant/docs/how-to/custom-request-and-route.md create mode 100644 docs/zh-hant/docs/how-to/extending-openapi.md create mode 100644 docs/zh-hant/docs/how-to/general.md create mode 100644 docs/zh-hant/docs/how-to/graphql.md create mode 100644 docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/zh-hant/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/zh-hant/docs/how-to/testing-database.md create mode 100644 docs/zh-hant/docs/project-generation.md create mode 100644 docs/zh-hant/docs/python-types.md create mode 100644 docs/zh-hant/docs/translation-banner.md create mode 100644 docs/zh-hant/docs/tutorial/background-tasks.md create mode 100644 docs/zh-hant/docs/tutorial/bigger-applications.md create mode 100644 docs/zh-hant/docs/tutorial/body-fields.md create mode 100644 docs/zh-hant/docs/tutorial/body-multiple-params.md create mode 100644 docs/zh-hant/docs/tutorial/body-nested-models.md create mode 100644 docs/zh-hant/docs/tutorial/body-updates.md create mode 100644 docs/zh-hant/docs/tutorial/body.md create mode 100644 docs/zh-hant/docs/tutorial/cookie-param-models.md create mode 100644 docs/zh-hant/docs/tutorial/cookie-params.md create mode 100644 docs/zh-hant/docs/tutorial/cors.md create mode 100644 docs/zh-hant/docs/tutorial/debugging.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/classes-as-dependencies.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/index.md create mode 100644 docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/zh-hant/docs/tutorial/encoder.md create mode 100644 docs/zh-hant/docs/tutorial/extra-data-types.md create mode 100644 docs/zh-hant/docs/tutorial/extra-models.md create mode 100644 docs/zh-hant/docs/tutorial/handling-errors.md create mode 100644 docs/zh-hant/docs/tutorial/header-param-models.md create mode 100644 docs/zh-hant/docs/tutorial/header-params.md create mode 100644 docs/zh-hant/docs/tutorial/metadata.md create mode 100644 docs/zh-hant/docs/tutorial/middleware.md create mode 100644 docs/zh-hant/docs/tutorial/path-operation-configuration.md create mode 100644 docs/zh-hant/docs/tutorial/path-params-numeric-validations.md create mode 100644 docs/zh-hant/docs/tutorial/path-params.md create mode 100644 docs/zh-hant/docs/tutorial/query-params-str-validations.md create mode 100644 docs/zh-hant/docs/tutorial/query-params.md create mode 100644 docs/zh-hant/docs/tutorial/request-files.md create mode 100644 docs/zh-hant/docs/tutorial/request-form-models.md create mode 100644 docs/zh-hant/docs/tutorial/request-forms-and-files.md create mode 100644 docs/zh-hant/docs/tutorial/request-forms.md create mode 100644 docs/zh-hant/docs/tutorial/response-model.md create mode 100644 docs/zh-hant/docs/tutorial/response-status-code.md create mode 100644 docs/zh-hant/docs/tutorial/schema-extra-example.md create mode 100644 docs/zh-hant/docs/tutorial/security/first-steps.md create mode 100644 docs/zh-hant/docs/tutorial/security/get-current-user.md create mode 100644 docs/zh-hant/docs/tutorial/security/index.md create mode 100644 docs/zh-hant/docs/tutorial/security/oauth2-jwt.md create mode 100644 docs/zh-hant/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/zh-hant/docs/tutorial/sql-databases.md create mode 100644 docs/zh-hant/docs/tutorial/static-files.md create mode 100644 docs/zh-hant/docs/tutorial/testing.md diff --git a/docs/zh-hant/docs/_llm-test.md b/docs/zh-hant/docs/_llm-test.md new file mode 100644 index 0000000000..85cfd22991 --- /dev/null +++ b/docs/zh-hant/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM ๆธฌ่ฉฆๆช”ๆกˆ { #llm-test-file } + +ๆœฌๆ–‡ไปถ็”จไพ†ๆธฌ่ฉฆ็”จๆ–ผ็ฟป่ญฏๆ–‡ไปถ็š„ LLM ๆ˜ฏๅฆ็†่งฃ `scripts/translate.py` ไธญ็š„ `general_prompt`๏ผŒไปฅๅŠ `docs/{language code}/llm-prompt.md` ไธญ็š„่ชž่จ€็‰นๅฎšๆ็คบใ€‚่ชž่จ€็‰นๅฎšๆ็คบๆœƒ้™„ๅŠ ๅœจ `general_prompt` ๅพŒ้ขใ€‚ + +ๆญค่™•ๆ–ฐๅขž็š„ๆธฌ่ฉฆๆœƒๆไพ›็ตฆๆ‰€ๆœ‰่ชž่จ€็‰นๅฎšๆ็คบ็š„่จญ่จˆ่€…ๅƒ่€ƒใ€‚ + +ไฝฟ็”จๆ–นๅผ๏ผš + +* ๆบ–ๅ‚™่ชž่จ€็‰นๅฎšๆ็คบ - `docs/{language code}/llm-prompt.md`ใ€‚ +* ้‡ๅฐๆœฌๆ–‡ไปถๅšไธ€ๆฌกๅ…จๆ–ฐ็š„็ฟป่ญฏ็‚บไฝ ๆƒณ่ฆ็š„็›ฎๆจ™่ชž่จ€๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ `translate.py` ็š„ `translate-page` ๆŒ‡ไปค๏ผ‰ใ€‚้€™ๆœƒๅœจ `docs/{language code}/docs/_llm-test.md` ็”ข็”Ÿ็ฟป่ญฏๆช”ใ€‚ +* ๆชขๆŸฅ็ฟป่ญฏๆ˜ฏๅฆๆญฃ็ขบใ€‚ +* ๅฆ‚ๆœ‰้œ€่ฆ๏ผŒๆ”น้€ฒไฝ ็š„่ชž่จ€็‰นๅฎšๆ็คบใ€้€š็”จๆ็คบ๏ผŒๆˆ–่‹ฑๆ–‡ๅŽŸๆ–‡ใ€‚ +* ็„ถๅพŒๆ‰‹ๅ‹•ไฟฎๆญฃ็ฟป่ญฏไธญๅ‰ฉไธ‹็š„ๅ•้กŒ๏ผŒ่ฎ“ๅฎƒๆˆ็‚บไธ€ๅ€‹ๅฅฝ็š„่ญฏๆ–‡ใ€‚ +* ้‡ๆ–ฐ็ฟป่ญฏ๏ผŒไธฆไฟ็•™้€™ไปฝๅฅฝ็š„่ญฏๆ–‡ใ€‚็†ๆƒณ็ตๆžœๆ˜ฏ LLM ไธๅ†ๅฐ่ฉฒ่ญฏๆ–‡ๅšไปปไฝ•่ฎŠๆ›ดใ€‚้€™ไปฃ่กจ้€š็”จๆ็คบ่ˆ‡ไฝ ็š„่ชž่จ€็‰นๅฎšๆ็คบๅทฒ็ถ“็›กๅฏ่ƒฝๅฎŒๅ–„๏ผˆๆœ‰ๆ™‚ๅฎƒไปๅฏ่ƒฝๅšๅ‡บๅนพๅ€‹็œ‹ไผผ้šจๆฉŸ็š„่ฎŠๆ›ด๏ผŒๅŽŸๅ› ๆ˜ฏLLMs ไธฆ้žๆฑบๅฎšๆ€งๆผ”็ฎ—ๆณ•๏ผ‰ใ€‚ + +ๆธฌ่ฉฆ๏ผš + +## ็จ‹ๅผ็ขผ็‰‡ๆฎต { #code-snippets } + +//// tab | ๆธฌ่ฉฆ + +้€™ๆ˜ฏไธ€ๅ€‹็จ‹ๅผ็ขผ็‰‡ๆฎต๏ผš`foo`ใ€‚้€™ๆ˜ฏๅฆไธ€ๅ€‹็จ‹ๅผ็ขผ็‰‡ๆฎต๏ผš`bar`ใ€‚้‚„ๆœ‰ไธ€ๅ€‹๏ผš`baz quux`ใ€‚ + +//// + +//// tab | ่ณ‡่จŠ + +็จ‹ๅผ็ขผ็‰‡ๆฎตๅ…ง็š„ๅ…งๅฎนๆ‡‰ไฟๆŒๅŽŸๆจฃใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Content of code snippets` ๅฐ็ฏ€ใ€‚ + +//// + +## ๅผ•่™Ÿ { #quotes } + +//// tab | ๆธฌ่ฉฆ + +Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". + +/// note | ๆณจๆ„ + +LLM ๅพˆๅฏ่ƒฝๆœƒๆŠŠ้€™ๆฎต็ฟป่ญฏ้Œฏใ€‚้‡้ปžๅชๅœจๆ–ผ้‡ๆ–ฐ็ฟป่ญฏๆ™‚ๆ˜ฏๅฆ่ƒฝไฟ็•™ๅทฒไฟฎๆญฃ็š„็ฟป่ญฏใ€‚ + +/// + +//// + +//// tab | ่ณ‡่จŠ + +ๆ็คบ่จญ่จˆ่€…ๅฏไปฅ้ธๆ“‡ๆ˜ฏๅฆๅฐ‡ไธญๆ€งๅผ•่™Ÿ่ฝ‰ๆ›็‚บๆŽ’ๅฐๅผ•่™Ÿใ€‚ไฟ็•™ๅŽŸๆจฃไนŸๅฏไปฅใ€‚ + +ไพ‹ๅฆ‚่ซ‹่ฆ‹ `docs/de/llm-prompt.md` ไธญ็š„ `### Quotes` ๅฐ็ฏ€ใ€‚ + +//// + +## ็จ‹ๅผ็ขผ็‰‡ๆฎตไธญ็š„ๅผ•่™Ÿ { #quotes-in-code-snippets } + +//// tab | ๆธฌ่ฉฆ + +`pip install "foo[bar]"` + +็จ‹ๅผ็ขผ็‰‡ๆฎตไธญๅญ—ไธฒๅธธๅ€ผ็š„ไพ‹ๅญ๏ผš"this"ใ€'that'ใ€‚ + +่ผƒ้›ฃ็š„็จ‹ๅผ็ขผ็‰‡ๆฎตไธญๅญ—ไธฒๅธธๅ€ผไพ‹ๅญ๏ผš`f"I like {'oranges' if orange else "apples"}"` + +้€ฒ้šŽ๏ผš`Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | ่ณ‡่จŠ + +... ไธ้Ž๏ผŒ็จ‹ๅผ็ขผ็‰‡ๆฎตไธญ็š„ๅผ•่™Ÿๅฟ…้ ˆไฟๆŒๅŽŸๆจฃใ€‚ + +//// + +## ็จ‹ๅผ็ขผๅ€ๅกŠ { #code-blocks } + +//// tab | ๆธฌ่ฉฆ + +ไธ€ๅ€‹ Bash ็จ‹ๅผ็ขผ็ฏ„ไพ‹... + +```bash +# ๅ‘ๅฎ‡ๅฎ™่ผธๅ‡บๅ•ๅ€™ +echo "Hello universe" +``` + +...ไปฅๅŠไธ€ๅ€‹ไธปๆŽงๅฐ็ฏ„ไพ‹... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...ไปฅๅŠๅฆไธ€ๅ€‹ไธปๆŽงๅฐ็ฏ„ไพ‹... + +```console +// ๅปบ็ซ‹็›ฎ้Œ„ "code" +$ mkdir code +// ๅˆ‡ๆ›ๅˆฐ่ฉฒ็›ฎ้Œ„ +$ cd code +``` + +...ไปฅๅŠไธ€ๅ€‹ Python ็จ‹ๅผ็ขผ็ฏ„ไพ‹... + +```Python +wont_work() # ้€™ไธๆœƒ้‹ไฝœ ๐Ÿ˜ฑ +works(foo="bar") # ้€™ๅฏไปฅ้‹ไฝœ ๐ŸŽ‰ +``` + +...ๅฐฑๆ˜ฏ้€™ๆจฃใ€‚ + +//// + +//// tab | ่ณ‡่จŠ + +็จ‹ๅผ็ขผๅ€ๅกŠไธญ็š„็จ‹ๅผ็ขผไธๆ‡‰ไฟฎๆ”น๏ผŒ่จป่งฃ้™คๅค–ใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Content of code blocks` ๅฐ็ฏ€ใ€‚ + +//// + +## ๅˆ†้ ่ˆ‡่‰ฒๅกŠ { #tabs-and-colored-boxes } + +//// tab | ๆธฌ่ฉฆ + +/// info | ่ณ‡่จŠ +Some text +/// + +/// note | ๆณจๆ„ +Some text +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ +Some text +/// + +/// check | ๆชขๆŸฅ +Some text +/// + +/// tip | ๆ็คบ +Some text +/// + +/// warning | ่ญฆๅ‘Š +Some text +/// + +/// danger | ๅฑ้šช +Some text +/// + +//// + +//// tab | ่ณ‡่จŠ + +ๅˆ†้ ่ˆ‡ `Info`/`Note`/`Warning`/็ญ‰ๅ€ๅกŠ๏ผŒๆ‡‰ๅœจ็›ด็ทš๏ผˆ`|`๏ผ‰ๅพŒๅŠ ๅ…ฅๅ…ถๆจ™้กŒ็š„็ฟป่ญฏใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Special blocks` ่ˆ‡ `### Tab blocks` ๅฐ็ฏ€ใ€‚ + +//// + +## ็ถฒ้ ่ˆ‡ๅ…ง้ƒจ้€ฃ็ต { #web-and-internal-links } + +//// tab | ๆธฌ่ฉฆ + +้€ฃ็ตๆ–‡ๅญ—ๆ‡‰่ขซ็ฟป่ญฏ๏ผŒ้€ฃ็ตไฝๅ€ๆ‡‰ไฟๆŒไธ่ฎŠ๏ผš + +* [้€ฃ็ตๅˆฐไธŠๆ–นๆจ™้กŒ](#code-snippets) +* [ๅ…ง้ƒจ้€ฃ็ต](index.md#installation){.internal-link target=_blank} +* ๅค–้ƒจ้€ฃ็ต +* ้€ฃ็ตๅˆฐๆจฃๅผ +* ้€ฃ็ตๅˆฐ่…ณๆœฌ +* ้€ฃ็ตๅˆฐๅœ–็‰‡ + +้€ฃ็ตๆ–‡ๅญ—ๆ‡‰่ขซ็ฟป่ญฏ๏ผŒ้€ฃ็ตไฝๅ€ๆ‡‰ๆŒ‡ๅ‘ๅฐๆ‡‰็š„็ฟป่ญฏ็‰ˆๆœฌ๏ผš + +* FastAPI ้€ฃ็ต + +//// + +//// tab | ่ณ‡่จŠ + +้€ฃ็ตๆ‡‰็ฟป่ญฏๅ…ถๆ–‡ๅญ—๏ผŒไฝ†ไฝๅ€้œ€ไฟๆŒไธ่ฎŠใ€‚ไพ‹ๅค–ๆ˜ฏๆŒ‡ๅ‘ FastAPI ๆ–‡ไปถ็ถฒ็ซ™็š„็ต•ๅฐ้€ฃ็ต๏ผŒ่ฉฒๆƒ…ๆณไธ‹ไฝๅ€ๆ‡‰ๆŒ‡ๅ‘ๅฐๆ‡‰็š„็ฟป่ญฏ็‰ˆๆœฌใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Links` ๅฐ็ฏ€ใ€‚ + +//// + +## HTMLใ€Œabbrใ€ๅ…ƒ็ด  { #html-abbr-elements } + +//// tab | ๆธฌ่ฉฆ + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅŒ…ๅœจ HTMLใ€Œabbrใ€ๅ…ƒ็ด ไธญ็š„ๅ…งๅฎน๏ผˆ้ƒจๅˆ†็‚บๆœๆ’ฐ๏ผ‰๏ผš + +### abbr ๆไพ›ๅฎŒๆ•ด่ฉž็ต„ { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr ๆไพ›ๅฎŒๆ•ด่ฉž็ต„่ˆ‡่ชชๆ˜Ž { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | ่ณ‡่จŠ + +ใ€Œabbrใ€ๅ…ƒ็ด ็š„ใ€Œtitleใ€ๅฑฌๆ€ง้œ€ไพ็‰นๅฎš่ฆๅ‰‡็ฟป่ญฏใ€‚ + +็ฟป่ญฏๅฏไปฅ่‡ช่กŒๆ–ฐๅขžใ€Œabbrใ€ๅ…ƒ็ด ๏ผˆไพ‹ๅฆ‚็‚บ่งฃ้‡‹่‹ฑๆ–‡ๅ–ฎๅญ—๏ผ‰๏ผŒLLM ไธๆ‡‰็งป้™คๅฎƒๅ€‘ใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### HTML abbr elements` ๅฐ็ฏ€ใ€‚ + +//// + +## HTMLใ€Œdfnใ€ๅ…ƒ็ด  { #html-dfn-elements } + +* ๅข้›† +* ๆทฑๅบฆๅญธ็ฟ’ + +## ๆจ™้กŒ { #headings } + +//// tab | ๆธฌ่ฉฆ + +### ้–‹็™ผ็ถฒ้ ๆ‡‰็”จ็จ‹ๅผ - ๆ•™ๅญธ { #develop-a-webapp-a-tutorial } + +Hello. + +### ๅž‹ๅˆฅๆ็คบ่ˆ‡่จป่งฃ { #type-hints-and-annotations } + +Hello again. + +### ่ถ…้กž่ˆ‡ๅญ้กžๅˆฅ { #super-and-subclasses } + +Hello again. + +//// + +//// tab | ่ณ‡่จŠ + +ๆจ™้กŒๅ”ฏไธ€็š„็กฌๆ€ง่ฆๅ‰‡ๆ˜ฏไฟ็•™่Šฑๆ‹ฌ่™Ÿไธญ็š„้›œๆนŠ็‰‡ๆฎตไธ่ฎŠ๏ผŒไปฅ็ขบไฟ้€ฃ็ตไธๆœƒๅคฑๆ•ˆใ€‚ + +่ซ‹่ฆ‹ `scripts/translate.py` ไธญ้€š็”จๆ็คบ็š„ `### Headings` ๅฐ็ฏ€ใ€‚ + +้—œๆ–ผ่ชž่จ€็‰นๅฎš็š„่ชชๆ˜Ž๏ผŒๅƒ่ฆ‹ไพ‹ๅฆ‚ `docs/de/llm-prompt.md` ไธญ็š„ `### Headings` ๅฐ็ฏ€ใ€‚ + +//// + +## ๆ–‡ไปถไธญไฝฟ็”จ็š„่ก“่ชž { #terms-used-in-the-docs } + +//// tab | ๆธฌ่ฉฆ + +* you +* your + +* e.g. +* etc. + +* `foo` as an `int` +* `bar` as a `str` +* `baz` as a `list` + +* ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ— +* ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— +* SQLModel ๆ–‡ไปถ +* API ๆ–‡ไปถ +* ่‡ชๅ‹•ๆ–‡ไปถ + +* ่ณ‡ๆ–™็ง‘ๅญธ +* ๆทฑๅบฆๅญธ็ฟ’ +* ๆฉŸๅ™จๅญธ็ฟ’ +* ็›ธไพๆ€งๆณจๅ…ฅ +* HTTP ๅŸบๆœฌ้ฉ—่ญ‰ +* HTTP ๆ‘˜่ฆ้ฉ—่ญ‰ +* ISO ๆ ผๅผ +* JSON Schema ๆจ™ๆบ– +* JSON ็ตๆง‹ๆ่ฟฐ +* ็ตๆง‹ๆ่ฟฐๅฎš็พฉ +* ๅฏ†็ขผๆต็จ‹ +* ่กŒๅ‹•่ฃ็ฝฎ + +* ๅทฒๆฃ„็”จ +* ่จญ่จˆ็š„ +* ็„กๆ•ˆ +* ๅณๆ™‚ +* ๆจ™ๆบ– +* ้ ่จญ +* ๅ€ๅˆ†ๅคงๅฐๅฏซ +* ไธๅ€ๅˆ†ๅคงๅฐๅฏซ + +* ๆไพ›ๆ‡‰็”จ็จ‹ๅผๆœๅ‹™ +* ๆไพ›้ ้ขๆœๅ‹™ + +* ๆ‡‰็”จ็จ‹ๅผ +* ๆ‡‰็”จ็จ‹ๅผ + +* ่ซ‹ๆฑ‚ +* ๅ›žๆ‡‰ +* ้Œฏ่ชคๅ›žๆ‡‰ + +* ่ทฏๅพ‘ๆ“ไฝœ +* ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ +* ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ + +* ไธป้ซ” +* ่ซ‹ๆฑ‚ไธป้ซ” +* ๅ›žๆ‡‰ไธป้ซ” +* JSON ไธป้ซ” +* ่กจๅ–ฎไธป้ซ” +* ๆช”ๆกˆไธป้ซ” +* ๅ‡ฝๅผไธป้ซ” + +* ๅƒๆ•ธ +* ไธป้ซ”ๅƒๆ•ธ +* ่ทฏๅพ‘ๅƒๆ•ธ +* ๆŸฅ่ฉขๅƒๆ•ธ +* Cookie ๅƒๆ•ธ +* ๆจ™้ ญๅƒๆ•ธ +* ่กจๅ–ฎๅƒๆ•ธ +* ๅ‡ฝๅผๅƒๆ•ธ + +* ไบ‹ไปถ +* ๅ•Ÿๅ‹•ไบ‹ไปถ +* ไผบๆœๅ™จ็š„ๅ•Ÿๅ‹• +* ้—œ้–‰ไบ‹ไปถ +* ็”Ÿๅ‘ฝ้€ฑๆœŸไบ‹ไปถ + +* ่™•็†ๅ™จ +* ไบ‹ไปถ่™•็†ๅ™จ +* ไพ‹ๅค–่™•็†ๅ™จ +* ่™•็† + +* ๆจกๅž‹ +* Pydantic ๆจกๅž‹ +* ่ณ‡ๆ–™ๆจกๅž‹ +* ่ณ‡ๆ–™ๅบซๆจกๅž‹ +* ่กจๅ–ฎๆจกๅž‹ +* ๆจกๅž‹็‰ฉไปถ + +* ้กžๅˆฅ +* ๅŸบๅบ•้กžๅˆฅ +* ็ˆถ้กžๅˆฅ +* ๅญ้กžๅˆฅ +* ๅญ้กžๅˆฅ +* ๅŒ็ดš้กžๅˆฅ +* ้กžๅˆฅๆ–นๆณ• + +* ๆจ™้ ญ +* ๆจ™้ ญ +* ๆŽˆๆฌŠๆจ™้ ญ +* `Authorization` ๆจ™้ ญ +* ่ฝ‰้€ๆจ™้ ญ + +* ็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑ +* ็›ธไพ้ … +* ๅฏ็›ธไพๅฐ่ฑก +* ็›ธไพ่€… + +* I/O ๅ—้™ +* CPU ๅ—้™ +* ไธฆ็™ผ +* ๅนณ่กŒ่™•็† +* ๅคš่™•็†็จ‹ๅบ + +* ็’ฐๅขƒ่ฎŠๆ•ธ +* ็’ฐๅขƒ่ฎŠๆ•ธ +* `PATH` +* `PATH` ่ฎŠๆ•ธ + +* ้ฉ—่ญ‰ +* ้ฉ—่ญ‰ๆไพ›่€… +* ๆŽˆๆฌŠ +* ๆŽˆๆฌŠ่กจๅ–ฎ +* ๆŽˆๆฌŠๆไพ›่€… +* ไฝฟ็”จ่€…้€ฒ่กŒ้ฉ—่ญ‰ +* ็ณป็ตฑ้ฉ—่ญ‰ไฝฟ็”จ่€… + +* CLI +* ๅ‘ฝไปคๅˆ—ไป‹้ข + +* ไผบๆœๅ™จ +* ็”จๆˆถ็ซฏ + +* ้›ฒ็ซฏๆไพ›่€… +* ้›ฒ็ซฏๆœๅ‹™ + +* ้–‹็™ผ +* ้–‹็™ผ้šŽๆฎต + +* dict +* ๅญ—ๅ…ธ +* ๅˆ—่ˆ‰ +* enum +* ๅˆ—่ˆ‰ๆˆๅ“ก + +* ็ทจ็ขผๅ™จ +* ่งฃ็ขผๅ™จ +* ็ทจ็ขผ +* ่งฃ็ขผ + +* ไพ‹ๅค– +* ๆ‹‹ๅ‡บ + +* ้‹็ฎ—ๅผ +* ้™ณ่ฟฐๅผ + +* ๅ‰็ซฏ +* ๅพŒ็ซฏ + +* GitHub ่จŽ่ซ– +* GitHub ่ญฐ้กŒ + +* ๆ•ˆ่ƒฝ +* ๆ•ˆ่ƒฝๅ„ชๅŒ– + +* ๅ›žๅ‚ณๅž‹ๅˆฅ +* ๅ›žๅ‚ณๅ€ผ + +* ๅฎ‰ๅ…จๆ€ง +* ๅฎ‰ๅ…จๆ€งๆฉŸๅˆถ + +* ไปปๅ‹™ +* ่ƒŒๆ™ฏไปปๅ‹™ +* ไปปๅ‹™ๅ‡ฝๅผ + +* ๆจฃๆฟ +* ๆจฃๆฟๅผ•ๆ“Ž + +* ๅž‹ๅˆฅ่จป่งฃ +* ๅž‹ๅˆฅๆ็คบ + +* ไผบๆœๅ™จๅทฅไฝœ้€ฒ็จ‹ +* Uvicorn ๅทฅไฝœ้€ฒ็จ‹ +* Gunicorn ๅทฅไฝœ้€ฒ็จ‹ +* ๅทฅไฝœ้€ฒ็จ‹ +* worker ้กžๅˆฅ +* ๅทฅไฝœ่ฒ ่ผ‰ + +* ้ƒจ็ฝฒ +* ้ƒจ็ฝฒ + +* SDK +* ่ปŸ้ซ”้–‹็™ผๅทฅๅ…ท็ต„ + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* ็›ธๅฎนๆ€ง็ ดๅฃž่ฎŠๆ›ด +* ้Œฏ่ชค +* ๆŒ‰้ˆ• +* ๅฏๅ‘ผๅซๅฐ่ฑก +* ็จ‹ๅผ็ขผ +* ๆไบค +* ๆƒ…ๅขƒ็ฎก็†ๅ™จ +* ๅ”็จ‹ +* ่ณ‡ๆ–™ๅบซๅทฅไฝœ้šŽๆฎต +* ็ฃ็ขŸ +* ็ถฒๅŸŸ +* ๅผ•ๆ“Ž +* ๅ‡็š„ X +* HTTP GET ๆ–นๆณ• +* ้ …็›ฎ +* ๅ‡ฝๅผๅบซ +* ็”Ÿๅ‘ฝ้€ฑๆœŸ +* ้Ž– +* ไธญไป‹่ปŸ้ซ” +* ่กŒๅ‹•ๆ‡‰็”จ็จ‹ๅผ +* ๆจก็ต„ +* ๆŽ›่ผ‰ +* ็ถฒ่ทฏ +* ไพ†ๆบ +* ่ฆ†ๅฏซ +* ๆœ‰ๆ•ˆ่ฒ ่ผ‰ +* ่™•็†ๅ™จ +* ๅฑฌๆ€ง +* ไปฃ็† +* pull request +* ๆŸฅ่ฉข +* RAM +* ้ ็ซฏๆฉŸๅ™จ +* ็‹€ๆ…‹็ขผ +* ๅญ—ไธฒ +* ๆจ™็ฑค +* Web ๆก†ๆžถ +* ่ฌ็”จๅญ—ๅ…ƒ +* ๅ›žๅ‚ณ +* ้ฉ—่ญ‰ + +//// + +//// tab | ่ณ‡่จŠ + +้€™ๆ˜ฏไธ€ไปฝไธๅฎŒๆ•ดไธ”้ž่ฆ็ฏ„ๆ€ง็š„๏ผˆๅคš็‚บ๏ผ‰ๆŠ€่ก“่ก“่ชžๆธ…ๅ–ฎ๏ผŒไพ†ๆบ็‚บๆ–‡ไปถๅ…งๅฎนใ€‚ๅฎƒๅฏ่ƒฝๆœ‰ๅŠฉๆ–ผๆ็คบ่จญ่จˆ่€…ๅˆคๆ–ทๅ“ชไบ›่ก“่ชž้œ€่ฆ LLM ็š„็‰นๅˆฅๅ”ๅŠฉใ€‚ไพ‹ๅฆ‚็•ถ LLM ๅ่ฆ†ๆŠŠๅฅฝ็š„็ฟป่ญฏๆ”นๅ›žๆˆ่ผƒๅทฎ็š„็‰ˆๆœฌ๏ผŒๆˆ–ๅœจไฝ ็š„่ชž่จ€ไธญๅฐๆŸ่ฉž็š„่ฉžๅฝข่ฎŠๅŒ–่™•็†ๆœ‰ๅ›ฐ้›ฃๆ™‚ใ€‚ + +่ซ‹่ฆ‹ไพ‹ๅฆ‚ `docs/de/llm-prompt.md` ไธญ็š„ `### List of English terms and their preferred German translations` ๅฐ็ฏ€ใ€‚ + +//// diff --git a/docs/zh-hant/docs/advanced/additional-responses.md b/docs/zh-hant/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..bb2bf259bd --- /dev/null +++ b/docs/zh-hant/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI ไธญ็š„้กๅค–ๅ›žๆ‡‰ { #additional-responses-in-openapi } + +/// warning | ่ญฆๅ‘Š + +้€™ๆ˜ฏไธ€ๅ€‹ๅ้€ฒ้šŽ็š„ไธป้กŒใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‰›้–‹ๅง‹ไฝฟ็”จ **FastAPI**๏ผŒๅคงๅคšๆƒ…ๆณไธ‹ไธ้œ€่ฆ็”จๅˆฐๅฎƒใ€‚ + +/// + +ไฝ ๅฏไปฅๅฎฃๅ‘Š้กๅค–็š„ๅ›žๆ‡‰๏ผŒๅŒ…ๅซ้กๅค–็š„็‹€ๆ…‹็ขผใ€ๅช’้ซ”ๅž‹ๅˆฅใ€ๆ่ฟฐ็ญ‰ใ€‚ + +้€™ไบ›้กๅค–ๅ›žๆ‡‰ๆœƒ่ขซๅŒ…ๅซๅœจ OpenAPI ไธญ๏ผŒๅ› ๆญคไนŸๆœƒ้กฏ็คบๅœจ API ๆ–‡ไปถ่ฃกใ€‚ + +ไฝ†ๅฐๆ–ผ้€™ไบ›้กๅค–ๅ›žๆ‡‰๏ผŒไฝ ๅฟ…้ ˆ็›ดๆŽฅๅ›žๅ‚ณๅƒ `JSONResponse` ้€™ๆจฃ็š„ `Response`๏ผŒไธฆๅŒ…ๅซไฝ ็š„็‹€ๆ…‹็ขผ่ˆ‡ๅ…งๅฎนใ€‚ + +## ไฝฟ็”จ `model` ็š„้กๅค–ๅ›žๆ‡‰ { #additional-response-with-model } + +ไฝ ๅฏไปฅๅœจไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญๅ‚ณๅ…ฅๅƒๆ•ธ `responses`ใ€‚ + +ๅฎƒๆŽฅๆ”ถไธ€ๅ€‹ `dict`๏ผš้ตๆ˜ฏๅ„ๅ›žๆ‡‰็š„็‹€ๆ…‹็ขผ๏ผˆไพ‹ๅฆ‚ `200`๏ผ‰๏ผŒๅ€ผๆ˜ฏๅฆไธ€ๅ€‹ `dict`๏ผŒๅ…ถไธญๅŒ…ๅซๆฏๅ€‹ๅ›žๆ‡‰็š„่ณ‡่จŠใ€‚ + +ๆฏๅ€‹ๅ›žๆ‡‰็š„ `dict` ้ƒฝๅฏไปฅๆœ‰ไธ€ๅ€‹้ต `model`๏ผŒๅŒ…ๅซไธ€ๅ€‹ Pydantic ๆจกๅž‹๏ผŒ่ˆ‡ `response_model` ้กžไผผใ€‚ + +**FastAPI** ๆœƒๅ–็”จ่ฉฒๆจกๅž‹ใ€็”ข็”Ÿๅ…ถ JSON Schema๏ผŒไธฆๆŠŠๅฎƒๆ”พๅˆฐ OpenAPI ไธญๆญฃ็ขบ็š„ไฝ็ฝฎใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฆๅฎฃๅ‘Šไธ€ๅ€‹็‹€ๆ…‹็ขผ็‚บ `404` ็š„้กๅค–ๅ›žๆ‡‰๏ผŒไธฆไฝฟ็”จ Pydantic ๆจกๅž‹ `Message`๏ผŒไฝ ๅฏไปฅ้€™ๆจฃๅฏซ๏ผš + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note | ๆณจๆ„ + +่ซ‹่จ˜ไฝไฝ ๅฟ…้ ˆ็›ดๆŽฅๅ›žๅ‚ณ `JSONResponse`ใ€‚ + +/// + +/// info | ่ชชๆ˜Ž + +`model` ้€™ๅ€‹้ตไธๅฑฌๆ–ผ OpenAPIใ€‚ + +**FastAPI** ๆœƒๅพž้€™่ฃกๅ–ๅ‡บ Pydantic ๆจกๅž‹๏ผŒ็”ข็”Ÿ JSON Schema๏ผŒไธฆๆ”พๅˆฐๆญฃ็ขบไฝ็ฝฎใ€‚ + +ๆญฃ็ขบ็š„ไฝ็ฝฎๆ˜ฏ๏ผš + +* ๅœจ `content` ้€™ๅ€‹้ตไธญ๏ผŒๅ…ถๅ€ผๆ˜ฏไธ€ๅ€‹ JSON ็‰ฉไปถ๏ผˆ`dict`๏ผ‰๏ผŒๅŒ…ๅซ๏ผš + * ไธ€ๅ€‹ๅช’้ซ”ๅž‹ๅˆฅไฝœ็‚บ้ต๏ผŒไพ‹ๅฆ‚ `application/json`๏ผŒๅ…ถๅ€ผๆ˜ฏๅฆไธ€ๅ€‹ JSON ็‰ฉไปถ๏ผŒ็•ถไธญๅŒ…ๅซ๏ผš + * ้ต `schema`๏ผŒๅ…ถๅ€ผๆ˜ฏ่ฉฒๆจกๅž‹็š„ JSON Schema๏ผŒ้€™่ฃกๅฐฑๆ˜ฏๆญฃ็ขบ็š„ไฝ็ฝฎใ€‚ + * **FastAPI** ๆœƒๅœจ้€™่ฃกๅŠ ๅ…ฅไธ€ๅ€‹ๆŒ‡ๅ‘ไฝ  OpenAPI ไธญๅ…จๅŸŸ JSON Schemas ็š„ๅƒ็…ง๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๆŠŠๅฎƒๅตŒๅ…ฅใ€‚ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅ…ถไป–ๆ‡‰็”จ่ˆ‡็”จๆˆถ็ซฏๅฏไปฅ็›ดๆŽฅไฝฟ็”จ้‚ฃไบ› JSON Schemas๏ผŒๆไพ›ๆ›ดๅฅฝ็š„็จ‹ๅผ็ขผ็”ข็”Ÿๅทฅๅ…ท็ญ‰ใ€‚ + +/// + +้€™ๅ€‹่ทฏๅพ‘ๆ“ไฝœๅœจ OpenAPI ไธญ็”ข็”Ÿ็š„ๅ›žๆ‡‰ๅฐ‡ๆœƒๆ˜ฏ๏ผš + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +้€™ไบ› Schemas ๆœƒๅœจ OpenAPI ไธญไปฅๅƒ็…ง็š„ๆ–นๅผๆŒ‡ๅ‘ๅ…ถไป–ไฝ็ฝฎ๏ผš + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## ไธปๅ›žๆ‡‰็š„ๅ…ถไป–ๅช’้ซ”ๅž‹ๅˆฅ { #additional-media-types-for-the-main-response } + +ไฝ ๅฏไปฅ็”จๅŒไธ€ๅ€‹ `responses` ๅƒๆ•ธ๏ผŒๆ›ฟ็›ธๅŒ็š„ไธปๅ›žๆ‡‰ๆ–ฐๅขžไธๅŒ็š„ๅช’้ซ”ๅž‹ๅˆฅใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆ–ฐๅขž `image/png` ้€™็จฎๅช’้ซ”ๅž‹ๅˆฅ๏ผŒๅฎฃๅ‘Šไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅฏไปฅๅ›žๅ‚ณ JSON ็‰ฉไปถ๏ผˆๅช’้ซ”ๅž‹ๅˆฅ็‚บ `application/json`๏ผ‰ๆˆ–ไธ€ๅผต PNG ๅœ–็‰‡๏ผš + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | ๆณจๆ„ + +่ซ‹ๆณจๆ„ไฝ ๅฟ…้ ˆ็›ดๆŽฅ็”จ `FileResponse` ๅ›žๅ‚ณๅœ–็‰‡ใ€‚ + +/// + +/// info | ่ชชๆ˜Ž + +้™ค้žไฝ ๅœจ `responses` ๅƒๆ•ธไธญๆ˜Ž็ขบๆŒ‡ๅฎšไธๅŒ็š„ๅช’้ซ”ๅž‹ๅˆฅ๏ผŒๅฆๅ‰‡ FastAPI ๆœƒๅ‡่จญๅ›žๆ‡‰็š„ๅช’้ซ”ๅž‹ๅˆฅ่ˆ‡ไธปๅ›žๆ‡‰้กžๅˆฅ็›ธๅŒ๏ผˆ้ ่จญ็‚บ `application/json`๏ผ‰ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ๆŒ‡ๅฎšไบ†ไธ€ๅ€‹่‡ช่จ‚็š„ๅ›žๆ‡‰้กžๅˆฅ๏ผŒไธ”ๅ…ถๅช’้ซ”ๅž‹ๅˆฅ็‚บ `None`๏ผŒ้‚ฃ้บผๅฐๆ–ผไปปไฝ•ๅ…ท้—œ่ฏๆจกๅž‹็š„้กๅค–ๅ›žๆ‡‰๏ผŒFastAPI ๆœƒไฝฟ็”จ `application/json`ใ€‚ + +/// + +## ็ตๅˆ่ณ‡่จŠ { #combining-information } + +ไฝ ไนŸๅฏไปฅๅพžๅคšๅ€‹ๅœฐๆ–น็ตๅˆๅ›žๆ‡‰่ณ‡่จŠ๏ผŒๅŒ…ๆ‹ฌ `response_model`ใ€`status_code` ่ˆ‡ `responses` ๅƒๆ•ธใ€‚ + +ไฝ ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹ `response_model`๏ผŒไฝฟ็”จ้ ่จญ็‹€ๆ…‹็ขผ `200`๏ผˆๆˆ–ไฝ ้œ€่ฆ็š„่‡ช่จ‚็‹€ๆ…‹็ขผ๏ผ‰๏ผŒ็„ถๅพŒๅœจ `responses` ไธญ็›ดๆŽฅๆ–ผ OpenAPI Schema ็‚บ็›ธๅŒ็š„ๅ›žๆ‡‰ๅฎฃๅ‘Š้กๅค–่ณ‡่จŠใ€‚ + +**FastAPI** ๆœƒไฟ็•™ `responses` ๆไพ›็š„้กๅค–่ณ‡่จŠ๏ผŒไธฆๆŠŠๅฎƒๅ’Œไฝ ๆจกๅž‹็š„ JSON Schema ็ตๅˆใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹็‹€ๆ…‹็ขผ็‚บ `404` ็š„ๅ›žๆ‡‰๏ผŒไฝฟ็”จไธ€ๅ€‹ Pydantic ๆจกๅž‹๏ผŒไธฆๅธถๆœ‰่‡ช่จ‚็š„ `description`ใ€‚ + +ไปฅๅŠไธ€ๅ€‹็‹€ๆ…‹็ขผ็‚บ `200` ็š„ๅ›žๆ‡‰๏ผŒไฝฟ็”จไฝ ็š„ `response_model`๏ผŒไฝ†ๅŒ…ๅซ่‡ช่จ‚็š„ `example`๏ผš + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +ไปฅไธŠ้ƒฝๆœƒ่ขซ็ตๅˆไธฆๅŒ…ๅซๅœจไฝ ็š„ OpenAPI ไธญ๏ผŒไธฆ้กฏ็คบๅœจ API ๆ–‡ไปถ๏ผš + + + +## ็ตๅˆ้ ๅ…ˆๅฎš็พฉ่ˆ‡่‡ช่จ‚็š„ๅ›žๆ‡‰ { #combine-predefined-responses-and-custom-ones } + +ไฝ ๅฏ่ƒฝๆƒณ่ฆๆœ‰ไธ€ไบ›้ฉ็”จๆ–ผๅคšๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„้ ๅ…ˆๅฎš็พฉๅ›žๆ‡‰๏ผŒไฝ†ไนŸๆƒณ่ˆ‡ๆฏๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆ‰€้œ€็š„่‡ช่จ‚ๅ›žๆ‡‰็ตๅˆใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Python ็š„ใ€Œ่งฃๅŒ…ใ€`dict` ๆŠ€ๅทง๏ผŒ้€้Ž `**dict_to_unpack`๏ผš + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +ๆญค่™•๏ผŒ`new_dict` ๆœƒๅŒ…ๅซ `old_dict` ็š„ๆ‰€ๆœ‰้ตๅ€ผ้…ๅฐ๏ผŒๅ†ๅŠ ไธŠๆ–ฐ็š„้ตๅ€ผ้…ๅฐ๏ผš + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +ไฝ ๅฏไปฅ็”จ้€™ๅ€‹ๆŠ€ๅทงๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธญ้‡็”จไธ€ไบ›้ ๅ…ˆๅฎš็พฉ็š„ๅ›žๆ‡‰๏ผŒไธฆ่ˆ‡ๅ…ถไป–่‡ช่จ‚ๅ›žๆ‡‰็ตๅˆใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## ้—œๆ–ผ OpenAPI ๅ›žๆ‡‰็š„ๆ›ดๅคš่ณ‡่จŠ { #more-information-about-openapi-responses } + +่‹ฅ่ฆๆŸฅ็œ‹ๅ›žๆ‡‰ไธญ็ฉถ็ซŸๅฏไปฅๅŒ…ๅซๅ“ชไบ›ๅ…งๅฎน๏ผŒไฝ ๅฏไปฅๅƒ่€ƒ OpenAPI ่ฆ็ฏ„ไธญ็š„้€™ไบ›็ซ ็ฏ€๏ผš + +* OpenAPI Responses ็‰ฉไปถ๏ผŒๅ…ถไธญๅŒ…ๅซ `Response Object`ใ€‚ +* OpenAPI Response ็‰ฉไปถ๏ผŒไฝ ๅฏไปฅๆŠŠ้€™่ฃก็š„ไปปไฝ•ๅ…งๅฎน็›ดๆŽฅๆ”พๅˆฐ `responses` ๅƒๆ•ธๅ…งๅ„ๅ€‹ๅ›žๆ‡‰ไธญใ€‚ๅŒ…ๅซ `description`ใ€`headers`ใ€`content`๏ผˆๅœจๅ…ถไธญๅฎฃๅ‘ŠไธๅŒ็š„ๅช’้ซ”ๅž‹ๅˆฅ่ˆ‡ JSON Schemas๏ผ‰ใ€ไปฅๅŠ `links`ใ€‚ diff --git a/docs/zh-hant/docs/advanced/additional-status-codes.md b/docs/zh-hant/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000..450a4705aa --- /dev/null +++ b/docs/zh-hant/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# ้กๅค–็š„็‹€ๆ…‹็ขผ { #additional-status-codes } + +ๅœจ้ ่จญๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒไฝฟ็”จ `JSONResponse` ๅ‚ณๅ›žๅ›žๆ‡‰๏ผŒไธฆๆŠŠไฝ ๅพžไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€ๅ›žๅ‚ณ็š„ๅ…งๅฎนๆ”พ้€ฒ่ฉฒ `JSONResponse` ไธญใ€‚ + +ๅฎƒๆœƒไฝฟ็”จ้ ่จญ็š„็‹€ๆ…‹็ขผ๏ผŒๆˆ–ไฝ ๅœจ่ทฏๅพ‘ๆ“ไฝœไธญ่จญๅฎš็š„็‹€ๆ…‹็ขผใ€‚ + +## ้กๅค–็š„็‹€ๆ…‹็ขผ { #additional-status-codes_1 } + +ๅฆ‚ๆžœไฝ ๆƒณๅœจไธป่ฆ็‹€ๆ…‹็ขผไน‹ๅค–ๅ†ๅ›žๅ‚ณๅ…ถไป–็‹€ๆ…‹็ขผ๏ผŒๅฏไปฅ็›ดๆŽฅๅ›žๅ‚ณไธ€ๅ€‹ `Response`๏ผˆไพ‹ๅฆ‚ `JSONResponse`๏ผ‰๏ผŒไธฆ็›ดๆŽฅ่จญๅฎšไฝ ๆƒณ่ฆ็š„้กๅค–็‹€ๆ…‹็ขผใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๆƒณ่ฆๆœ‰ไธ€ๅ€‹ๅ…่จฑๆ›ดๆ–ฐ้ …็›ฎ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผŒๆˆๅŠŸๆ™‚ๅ›žๅ‚ณ HTTP ็‹€ๆ…‹็ขผ 200 "OK"ใ€‚ + +ไฝ†ไฝ ไนŸๅธŒๆœ›ๅฎƒ่ƒฝๆŽฅๅ—ๆ–ฐ้ …็›ฎ๏ผ›็•ถ้ …็›ฎๅ…ˆๅ‰ไธๅญ˜ๅœจๆ™‚ๅฐฑๅปบ็ซ‹ๅฎƒๅ€‘๏ผŒไธฆๅ›žๅ‚ณ HTTP ็‹€ๆ…‹็ขผ 201 "Created"ใ€‚ + +่ฆ้”ๆˆ้€™้ปž๏ผŒๅŒฏๅ…ฅ `JSONResponse`๏ผŒ็›ดๆŽฅๅœจ้‚ฃ่ฃกๅ›žๅ‚ณๅ…งๅฎน๏ผŒไธฆ่จญๅฎšไฝ ๆƒณ่ฆ็š„ `status_code`๏ผš + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning + +็•ถไฝ ็›ดๆŽฅๅ›žๅ‚ณไธ€ๅ€‹ `Response`๏ผˆๅฐฑๅƒไธŠ้ข็š„็ฏ„ไพ‹๏ผ‰๏ผŒๅฎƒๆœƒๅŽŸๅฐไธๅ‹•ๅœฐ่ขซ้€ๅ‡บใ€‚ + +ไธๆœƒๅ†็ถ“้Žๆจกๅž‹ๅบๅˆ—ๅŒ–็ญ‰่™•็†ใ€‚ + +่ซ‹็ขบ่ชๅ…ถไธญๅŒ…ๅซไฝ ่ฆ็š„่ณ‡ๆ–™๏ผŒไธ”ๅ„ๅ€ผๆ˜ฏๅˆๆณ•็š„ JSON๏ผˆๅฆ‚ๆžœไฝ ไฝฟ็”จ็š„ๆ˜ฏ `JSONResponse`๏ผ‰ใ€‚ + +/// + +/// note | ๆณจๆ„ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import JSONResponse`ใ€‚ + +**FastAPI** ไนŸๅฐ‡ๅŒๆจฃ็š„ `starlette.responses` ไปฅ `fastapi.responses` ็š„ๅฝขๅผๆไพ›๏ผŒ็ด”็ฒนๆ˜ฏ็‚บไบ†่ฎ“ไฝ ๏ผˆ้–‹็™ผ่€…๏ผ‰ๆ›ดๆ–นไพฟใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅˆฅๅ…ถๅฏฆ้ƒฝ็›ดๆŽฅไพ†่‡ช Starletteใ€‚`status` ไนŸไธ€ๆจฃใ€‚ + +/// + +## OpenAPI ่ˆ‡ API ๆ–‡ไปถ { #openapi-and-api-docs } + +ๅฆ‚ๆžœไฝ ็›ดๆŽฅๅ›žๅ‚ณ้กๅค–็š„็‹€ๆ…‹็ขผ่ˆ‡ๅ›žๆ‡‰๏ผŒๅฎƒๅ€‘ไธๆœƒ่ขซๅŒ…ๅซ้€ฒ OpenAPI ็ถฑ่ฆ๏ผˆAPI ๆ–‡ไปถ๏ผ‰ไธญ๏ผŒๅ› ็‚บ FastAPI ็„กๆณ•ไบ‹ๅ…ˆ็Ÿฅ้“ไฝ ๆœƒๅ›žๅ‚ณไป€้บผใ€‚ + +ไฝ†ไฝ ๅฏไปฅๅœจ็จ‹ๅผ็ขผไธญ่ฃœๅ……ๆ–‡ไปถ๏ผŒไฝฟ็”จ๏ผš[้กๅค–็š„ๅ›žๆ‡‰](additional-responses.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/advanced/advanced-dependencies.md b/docs/zh-hant/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000..472cf470b1 --- /dev/null +++ b/docs/zh-hant/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# ้€ฒ้šŽ็›ธไพ { #advanced-dependencies } + +## ๅƒๆ•ธๅŒ–็š„็›ธไพ { #parameterized-dependencies } + +ๅˆฐ็›ฎๅ‰็‚บๆญข็œ‹ๅˆฐ็š„็›ธไพ้ƒฝๆ˜ฏๅ›บๅฎš็š„ๅ‡ฝๅผๆˆ–้กžๅˆฅใ€‚ + +ไฝ†ๆœ‰ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆ่ƒฝ็‚บ็›ธไพ่จญๅฎšๅƒๆ•ธ๏ผŒ่€Œไธๅฟ…ๅฎฃๅ‘Š่จฑๅคšไธๅŒ็š„ๅ‡ฝๅผๆˆ–้กžๅˆฅใ€‚ + +ๆƒณๅƒๆˆ‘ๅ€‘ๆƒณ่ฆไธ€ๅ€‹็›ธไพ๏ผŒ็”จไพ†ๆชขๆŸฅๆŸฅ่ฉขๅƒๆ•ธ `q` ๆ˜ฏๅฆๅŒ…ๅซๆŸไบ›ๅ›บๅฎšๅ…งๅฎนใ€‚ + +ๅŒๆ™‚ๆˆ‘ๅ€‘ๅธŒๆœ›่ƒฝๅฐ‡้‚ฃๅ€‹ๅ›บๅฎšๅ…งๅฎนๅƒๆ•ธๅŒ–ใ€‚ + +## ใ€Œcallableใ€็š„ๅฏฆไพ‹ { #a-callable-instance } + +ๅœจ Python ไธญๆœ‰ไธ€็จฎๆ–นๅผๅฏไปฅ่ฎ“ไธ€ๅ€‹้กžๅˆฅ็š„ๅฏฆไพ‹่ฎŠๆˆใ€Œcallableใ€ใ€‚ + +ไธๆ˜ฏ้กžๅˆฅๆœฌ่บซ๏ผˆ้กžๅˆฅๆœฌไพ†ๅฐฑๅฏๅ‘ผๅซ๏ผ‰๏ผŒ่€Œๆ˜ฏ่ฉฒ้กžๅˆฅ็š„ๅฏฆไพ‹ใ€‚ + +่ฆๅšๅˆฐ้€™้ปž๏ผŒๆˆ‘ๅ€‘ๅฎฃๅ‘Šไธ€ๅ€‹ `__call__` ๆ–นๆณ•๏ผš + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +ๅœจ้€™ๅ€‹ๆƒ…ๅขƒไธญ๏ผŒ**FastAPI** ๆœƒ็”จ้€™ๅ€‹ `__call__` ไพ†ๆชขๆŸฅ้กๅค–็š„ๅƒๆ•ธ่ˆ‡ๅญ็›ธไพ๏ผŒไธฆๅœจไน‹ๅพŒๅ‘ผๅซๅฎƒ๏ผŒๆŠŠๅ›žๅ‚ณๅ€ผๅ‚ณ้ž็ตฆไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญ็š„ๅƒๆ•ธใ€‚ + +## ่ฎ“ๅฏฆไพ‹ๅฏๅƒๆ•ธๅŒ– { #parameterize-the-instance } + +ๆŽฅ่‘—๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ็”จ `__init__` ไพ†ๅฎฃๅ‘Š้€™ๅ€‹ๅฏฆไพ‹็š„ๅƒๆ•ธ๏ผŒ็”จไปฅใ€Œๅƒๆ•ธๅŒ–ใ€้€™ๅ€‹็›ธไพ๏ผš + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +ๅœจ้€™่ฃก๏ผŒ**FastAPI** ๅฎŒๅ…จไธๆœƒๆŽฅ่งธๆˆ–ๅœจๆ„ `__init__`๏ผŒๆˆ‘ๅ€‘ๆœƒ็›ดๆŽฅๅœจ่‡ชๅทฑ็š„็จ‹ๅผ็ขผไธญไฝฟ็”จๅฎƒใ€‚ + +## ๅปบ็ซ‹ไธ€ๅ€‹ๅฏฆไพ‹ { #create-an-instance } + +ๆˆ‘ๅ€‘ๅฏไปฅ้€™ๆจฃๅปบ็ซ‹่ฉฒ้กžๅˆฅ็š„ๅฏฆไพ‹๏ผš + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +ๅฆ‚ๆญคไธ€ไพ†ๆˆ‘ๅ€‘ๅฐฑ่ƒฝใ€Œๅƒๆ•ธๅŒ–ใ€็›ธไพ๏ผŒ็พๅœจๅฎƒๅ…ง้ƒจๅซๆœ‰ `"bar"`๏ผŒไฝœ็‚บๅฑฌๆ€ง `checker.fixed_content`ใ€‚ + +## ๅฐ‡ๅฏฆไพ‹ไฝœ็‚บ็›ธไพไฝฟ็”จ { #use-the-instance-as-a-dependency } + +็„ถๅพŒ๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅœจ `Depends(checker)` ไธญไฝฟ็”จ้€™ๅ€‹ `checker`๏ผŒ่€Œไธๆ˜ฏ `Depends(FixedContentQueryChecker)`๏ผŒๅ› ็‚บ็›ธไพๆ˜ฏ้‚ฃๅ€‹ๅฏฆไพ‹ `checker`๏ผŒไธๆ˜ฏ้กžๅˆฅๆœฌ่บซใ€‚ + +็•ถ่งฃๆž็›ธไพๆ™‚๏ผŒ**FastAPI** ๆœƒๅƒ้€™ๆจฃๅ‘ผๅซ้€™ๅ€‹ `checker`๏ผš + +```Python +checker(q="somequery") +``` + +...ไธฆๅฐ‡ๅ…ถๅ›žๅ‚ณๅ€ผ๏ผŒไฝœ็‚บ็›ธไพ็š„ๅ€ผ๏ผŒไปฅๅƒๆ•ธ `fixed_content_included` ๅ‚ณ็ตฆๆˆ‘ๅ€‘็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€๏ผš + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | ๆ็คบ + +้€™ไธ€ๅˆ‡็พๅœจ็œ‹่ตทไพ†ไนŸ่จฑๆœ‰้ปž็‰ฝๅผท๏ผŒ่€Œไธ”็›ฎๅ‰ๅฏ่ƒฝ้‚„ไธๅคชๆธ…ๆฅšๆœ‰ไฝ•็”จ้€”ใ€‚ + +้€™ไบ›็ฏ„ไพ‹ๅˆปๆ„ไฟๆŒ็ฐกๅ–ฎ๏ผŒไฝ†ๅฑ•็คบไบ†ๆ•ดๅ€‹ๆฉŸๅˆถๅฆ‚ไฝ•้‹ไฝœใ€‚ + +ๅœจ้—œๆ–ผๅฎ‰ๅ…จๆ€ง็š„็ซ ็ฏ€่ฃก๏ผŒๆœ‰ไธ€ไบ›ๅทฅๅ…ทๅ‡ฝๅผไนŸๆ˜ฏ็”จๅŒๆจฃ็š„ๆ–นๅผๅฏฆไฝœใ€‚ + +ๅฆ‚ๆžœไฝ ็†่งฃไบ†ไปฅไธŠๅ…งๅฎน๏ผŒไฝ ๅ…ถๅฏฆๅทฒ็ถ“็Ÿฅ้“้‚ฃไบ›ๅฎ‰ๅ…จๆ€งๅทฅๅ…ทๅœจๅบ•ๅฑคๆ˜ฏๅฆ‚ไฝ•้‹ไฝœ็š„ใ€‚ + +/// + +## ๅŒๆ™‚ๅซๆœ‰ `yield`ใ€`HTTPException`ใ€`except` ่ˆ‡่ƒŒๆ™ฏไปปๅ‹™็š„็›ธไพ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | ่ญฆๅ‘Š + +ไฝ ๅพˆๅฏ่ƒฝไธ้œ€่ฆ้€™ไบ›ๆŠ€่ก“็ดฐ็ฏ€ใ€‚ + +้€™ไบ›็ดฐ็ฏ€ไธป่ฆๅœจๆ–ผ๏ผšๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹ 0.121.0 ไน‹ๅ‰็š„ FastAPI ๆ‡‰็”จ๏ผŒไธฆไธ”ๅœจไฝฟ็”จๅซๆœ‰ `yield` ็š„็›ธไพๆ™‚้‡ๅˆฐๅ•้กŒ๏ผŒๆœƒๅฐไฝ ๆœ‰ๅนซๅŠฉใ€‚ + +/// + +ๅซๆœ‰ `yield` ็š„็›ธไพ้šจ่‘—ๆ™‚้–“ๆผ”้€ฒ๏ผŒไปฅๆถต่“‹ไธๅŒ็š„ไฝฟ็”จๆƒ…ๅขƒไธฆไฟฎๆญฃไธ€ไบ›ๅ•้กŒใ€‚ไปฅไธ‹ๆ˜ฏ่ฎŠๆ›ดๆ‘˜่ฆใ€‚ + +### ๅซๆœ‰ `yield` ่ˆ‡ `scope` ็š„็›ธไพ { #dependencies-with-yield-and-scope } + +ๅœจ 0.121.0 ็‰ˆไธญ๏ผŒFastAPI ็‚บๅซๆœ‰ `yield` ็š„็›ธไพๅŠ ๅ…ฅไบ† `Depends(scope="function")` ็š„ๆ”ฏๆดใ€‚ + +ไฝฟ็”จ `Depends(scope="function")` ๆ™‚๏ผŒ`yield` ไน‹ๅพŒ็š„็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅŸท่กŒๅฎŒ็•ขๅพŒ็ซ‹ๅˆปๅŸท่กŒ๏ผŒๅœจๅ›žๆ‡‰็™ผ้€ๅ›žๅฎขๆˆถ็ซฏไน‹ๅ‰ใ€‚ + +่€Œ็•ถไฝฟ็”จ `Depends(scope="request")`๏ผˆ้ ่จญๅ€ผ๏ผ‰ๆ™‚๏ผŒ`yield` ไน‹ๅพŒ็š„็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจๅ›žๆ‡‰้€ๅ‡บไน‹ๅพŒๆ‰ๅŸท่กŒใ€‚ + +ไฝ ๅฏไปฅๅœจๆ–‡ไปถไธญ้–ฑ่ฎ€ๆ›ดๅคš๏ผš[ๅซๆœ‰ `yield` ็š„็›ธไพ - ๆๅ‰็ตๆŸ่ˆ‡ `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope)ใ€‚ + +### ๅซๆœ‰ `yield` ่ˆ‡ `StreamingResponse` ็š„็›ธไพ๏ผŒๆŠ€่ก“็ดฐ็ฏ€ { #dependencies-with-yield-and-streamingresponse-technical-details } + +ๅœจ FastAPI 0.118.0 ไน‹ๅ‰๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จๅซๆœ‰ `yield` ็š„็›ธไพ๏ผŒๅฎƒๆœƒๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ›žๅ‚ณไน‹ๅพŒใ€็™ผ้€ๅ›žๆ‡‰ไน‹ๅ‰๏ผŒๅŸท่กŒ็ตๆŸ็จ‹ๅผ็ขผใ€‚ + +้€™ๆจฃๅš็š„็”จๆ„ๆ˜ฏ้ฟๅ…ๅœจ็ญ‰ๅพ…ๅ›žๆ‡‰็ฉฟ่ถŠ็ถฒ่ทฏๆ™‚๏ผŒๆฏ”ๅฟ…่ฆ็š„ๆ™‚้–“ๆ›ดไน…ๅœฐๅ ็”จ่ณ‡ๆบใ€‚ + +ไฝ†้€™ไนŸๆ„ๅ‘ณ่‘—๏ผŒๅฆ‚ๆžœไฝ ๅ›žๅ‚ณ็š„ๆ˜ฏ `StreamingResponse`๏ผŒ่ฉฒๅซๆœ‰ `yield` ็š„็›ธไพ็š„็ตๆŸ็จ‹ๅผ็ขผๆ—ฉๅทฒๅŸท่กŒๅฎŒ็•ขใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅœจๅซๆœ‰ `yield` ็š„็›ธไพไธญไฝฟ็”จไบ†ไธ€ๅ€‹่ณ‡ๆ–™ๅบซ session๏ผŒ`StreamingResponse` ๅœจไธฒๆต่ณ‡ๆ–™ๆ™‚ๅฐ‡็„กๆณ•ไฝฟ็”จ่ฉฒ session๏ผŒๅ› ็‚บๅฎƒๅทฒๅœจ `yield` ไน‹ๅพŒ็š„็ตๆŸ็จ‹ๅผ็ขผไธญ่ขซ้—œ้–‰ไบ†ใ€‚ + +้€™ๅ€‹่กŒ็‚บๅœจ 0.118.0 ่ขซ้‚„ๅŽŸ๏ผŒไฝฟๅพ— `yield` ไน‹ๅพŒ็š„็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจๅ›žๆ‡‰้€ๅ‡บไน‹ๅพŒๆ‰่ขซๅŸท่กŒใ€‚ + +/// info | ่ณ‡่จŠ + +ๅฆ‚ไธ‹ๆ‰€่ฆ‹๏ผŒ้€™่ˆ‡ 0.106.0 ไน‹ๅ‰็š„่กŒ็‚บ้žๅธธ้กžไผผ๏ผŒไฝ†ๅฐไธ€ไบ›้‚Š็•Œๆƒ…ๆณๅšไบ†ๅคš้ …ๆ”น้€ฒ่ˆ‡้Œฏ่ชคไฟฎๆญฃใ€‚ + +/// + +#### ้œ€่ฆๆๆ—ฉๅŸท่กŒ็ตๆŸ็จ‹ๅผ็ขผ็š„ๆƒ…ๅขƒ { #use-cases-with-early-exit-code } + +ๆœ‰ไบ›็‰นๅฎšๆขไปถ็š„ไฝฟ็”จๆƒ…ๅขƒ๏ผŒๅฏ่ƒฝๆœƒๅ—็›Šๆ–ผ่ˆŠ่กŒ็‚บ๏ผˆๅœจ้€ๅ‡บๅ›žๆ‡‰ไน‹ๅ‰ๅŸท่กŒๅซๆœ‰ `yield` ็š„็›ธไพ็š„็ตๆŸ็จ‹ๅผ็ขผ๏ผ‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ๅœจๅซๆœ‰ `yield` ็š„็›ธไพไธญๅช็”จ่ณ‡ๆ–™ๅบซ session ไพ†้ฉ—่ญ‰ไฝฟ็”จ่€…๏ผŒ่€Œ้€™ๅ€‹ session ไน‹ๅพŒไธฆๆœชๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญไฝฟ็”จ๏ผŒๅƒ…ๅœจ็›ธไพไธญไฝฟ็”จ๏ผŒไธ”ๅ›žๆ‡‰้œ€่ฆๅพˆ้•ทๆ™‚้–“ๆ‰ๆœƒ้€ๅ‡บ๏ผŒไพ‹ๅฆ‚ไธ€ๅ€‹ๆ…ข้€Ÿๅ‚ณ้€่ณ‡ๆ–™็š„ `StreamingResponse`๏ผŒไฝ†ๅฎƒไธฆๆฒ’ๆœ‰ไฝฟ็”จ่ณ‡ๆ–™ๅบซใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒ่ณ‡ๆ–™ๅบซ session ๆœƒไธ€็›ด่ขซไฟ็•™ๅˆฐๅ›žๆ‡‰ๅ‚ณ้€ๅฎŒ็•ข็‚บๆญข๏ผŒไฝ†ๅฆ‚ๆžœไฝ ๆ นๆœฌไธๆœƒ็”จๅˆฐๅฎƒ๏ผŒๅฐฑๆฒ’ๆœ‰ๅฟ…่ฆไธ€็›ดๆŒๆœ‰ๅฎƒใ€‚ + +ๅฏ่ƒฝๆœƒๅƒ้€™ๆจฃ๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +็ตๆŸ็จ‹ๅผ็ขผ๏ผˆ่‡ชๅ‹•้—œ้–‰ `Session`๏ผ‰ๅœจ๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...ๆœƒๅœจๅ›žๆ‡‰ๅฎŒๆˆๅ‚ณ้€้€™ไบ›ๆ…ข้€Ÿ่ณ‡ๆ–™ๅพŒๆ‰ๅŸท่กŒ๏ผš + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +ไฝ†ๅ› ็‚บ `generate_stream()` ไธฆๆœชไฝฟ็”จ่ณ‡ๆ–™ๅบซ session๏ผŒๅฏฆ้š›ไธŠไธ้œ€่ฆๅœจๅ‚ณ้€ๅ›žๆ‡‰ๆ™‚ไฟๆŒ session ้–‹ๅ•Ÿใ€‚ + +ๅฆ‚ๆžœไฝ ็”จ็š„ๆ˜ฏ SQLModel๏ผˆๆˆ– SQLAlchemy๏ผ‰ไธ”ๆœ‰้€™็จฎ็‰นๅฎšๆƒ…ๅขƒ๏ผŒไฝ ๅฏไปฅๅœจไธๅ†้œ€่ฆๆ™‚ๆ˜Ž็ขบ้—œ้–‰่ฉฒ session๏ผš + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒ่ฉฒ session ๅฐฑๆœƒ้‡‹ๆ”พ่ณ‡ๆ–™ๅบซ้€ฃ็ทš๏ผŒ่ฎ“ๅ…ถไป–่ซ‹ๆฑ‚ๅฏไปฅไฝฟ็”จใ€‚ + +ๅฆ‚ๆžœไฝ ๆœ‰ไธๅŒ็š„ๆƒ…ๅขƒ๏ผŒ้œ€่ฆๅพžๅซๆœ‰ `yield` ็š„็›ธไพไธญๆๆ—ฉ็ตๆŸ๏ผŒ่ซ‹ๅปบ็ซ‹ไธ€ๅ€‹ GitHub ่จŽ่ซ–ๅ•้กŒ๏ผŒๆ่ฟฐไฝ ็š„ๅ…ท้ซ”ๆƒ…ๅขƒ๏ผŒไปฅๅŠ็‚บไฝ•ๆๆ—ฉ้—œ้–‰ๅซๆœ‰ `yield` ็š„็›ธไพๅฐไฝ ๆœ‰ๅนซๅŠฉใ€‚ + +ๅฆ‚ๆžœๆœ‰ไปคไบบไฟกๆœ็š„ๆกˆไพ‹้œ€่ฆๅœจๅซๆœ‰ `yield` ็š„็›ธไพไธญๆๅ‰้—œ้–‰๏ผŒๆˆ‘ๆœƒ่€ƒๆ…ฎๅŠ ๅ…ฅไธ€็จฎๆ–ฐ็š„้ธ้ …๏ผŒ่ฎ“ไฝ ๅฏไปฅ้ธๆ“‡ๆ€งๅ•Ÿ็”จๆๅ‰้—œ้–‰ใ€‚ + +### ๅซๆœ‰ `yield` ่ˆ‡ `except` ็š„็›ธไพ๏ผŒๆŠ€่ก“็ดฐ็ฏ€ { #dependencies-with-yield-and-except-technical-details } + +ๅœจ FastAPI 0.110.0 ไน‹ๅ‰๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จๅซๆœ‰ `yield` ็š„็›ธไพ๏ผŒไธฆไธ”ๅœจ่ฉฒ็›ธไพไธญ็”จ `except` ๆ•ๆ‰ๅˆฐไพ‹ๅค–๏ผŒไธ”ๆฒ’ๆœ‰ๅ†ๆฌกๆ‹‹ๅ‡บ๏ผŒ้‚ฃๅ€‹ไพ‹ๅค–ๆœƒ่‡ชๅ‹•่ขซๆ‹‹ๅ‡บ๏ผ่ฝ‰ไบค็ตฆไปปไฝ•ไพ‹ๅค–่™•็†ๅ™จๆˆ–ๅ…ง้ƒจไผบๆœๅ™จ้Œฏ่ชค่™•็†ๅ™จใ€‚ + +ๅœจ 0.110.0 ็‰ˆๆœฌไธญ๏ผŒ้€™่ขซไฟฎๆ”นไปฅไฟฎๅพฉๆฒ’ๆœ‰่™•็†ๅ™จ๏ผˆๅ…ง้ƒจไผบๆœๅ™จ้Œฏ่ชค๏ผ‰่€Œ่ขซ่ฝ‰ไบค็š„ไพ‹ๅค–ๆ‰€้€ ๆˆ็š„ๆœช่™•็†่จ˜ๆ†ถ้ซ”ๆถˆ่€—๏ผŒไธฆไฝฟๅ…ถ่กŒ็‚บ่ˆ‡ไธ€่ˆฌ Python ็จ‹ๅผ็ขผไธ€่‡ดใ€‚ + +### ่ƒŒๆ™ฏไปปๅ‹™่ˆ‡ๅซๆœ‰ `yield` ็š„็›ธไพ๏ผŒๆŠ€่ก“็ดฐ็ฏ€ { #background-tasks-and-dependencies-with-yield-technical-details } + +ๅœจ FastAPI 0.106.0 ไน‹ๅ‰๏ผŒไธๅฏ่ƒฝๅœจ `yield` ไน‹ๅพŒๆ‹‹ๅ‡บไพ‹ๅค–๏ผ›ๅซๆœ‰ `yield` ็š„็›ธไพ็š„็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจๅ›žๆ‡‰้€ๅ‡บไน‹ๅพŒๆ‰ๅŸท่กŒ๏ผŒๅ› ๆญค[ไพ‹ๅค–่™•็†ๅ™จ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} ๆ—ฉๅฐฑๅทฒ็ถ“่ท‘ๅฎŒไบ†ใ€‚ + +็•ถๅˆ้€™ๆจฃ่จญ่จˆไธป่ฆๆ˜ฏ็‚บไบ†ๅ…่จฑๅœจ่ƒŒๆ™ฏไปปๅ‹™ไธญไฝฟ็”จ็”ฑ็›ธไพใ€Œyieldใ€ๅ‡บไพ†็š„ๅŒไธ€็ต„็‰ฉไปถ๏ผŒๅ› ็‚บ็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจ่ƒŒๆ™ฏไปปๅ‹™็ตๆŸๅพŒๆ‰ๅŸท่กŒใ€‚ + +ๅœจ FastAPI 0.106.0 ไธญ๏ผŒ้€™ๅ€‹่กŒ็‚บ่ขซไฟฎๆ”น๏ผŒ็›ฎ็š„ๆ˜ฏๅœจ็ญ‰ๅพ…ๅ›žๆ‡‰็ฉฟ่ถŠ็ถฒ่ทฏ็š„ๆœŸ้–“๏ผŒไธ่ฆๆŒๆœ‰่ณ‡ๆบใ€‚ + +/// tip | ๆ็คบ + +ๆญคๅค–๏ผŒ่ƒŒๆ™ฏไปปๅ‹™้€šๅธธๆ˜ฏไธ€็ต„็จ็ซ‹็š„้‚่ผฏ๏ผŒๆ‡‰่ฉฒ็”จ่‡ชๅทฑ็š„่ณ‡ๆบ๏ผˆไพ‹ๅฆ‚่‡ชๅทฑ็š„่ณ‡ๆ–™ๅบซ้€ฃ็ทš๏ผ‰ไพ†่™•็†ใ€‚ + +้€™ๆจฃไฝ ็š„็จ‹ๅผ็ขผ้€šๅธธๆœƒๆ›ดไนพๆทจใ€‚ + +/// + +ๅฆ‚ๆžœไฝ ๅ…ˆๅ‰ไพ่ณด้€™็จฎ่กŒ็‚บ๏ผŒ็พๅœจๆ‡‰่ฉฒๅœจ่ƒŒๆ™ฏไปปๅ‹™ๆœฌ่บซ่ฃกๅปบ็ซ‹ๆ‰€้œ€่ณ‡ๆบ๏ผŒไธฆไธ”ๅชไฝฟ็”จไธไพ่ณดๅซๆœ‰ `yield` ็š„็›ธไพไน‹่ณ‡ๆบ็š„่ณ‡ๆ–™ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไธ่ฆๅ…ฑ็”จๅŒไธ€ๅ€‹่ณ‡ๆ–™ๅบซ session๏ผŒ่€Œๆ˜ฏๅœจ่ƒŒๆ™ฏไปปๅ‹™ไธญๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„่ณ‡ๆ–™ๅบซ session๏ผŒไธฆ็”จ้€™ๅ€‹ๆ–ฐ็š„ session ๅพž่ณ‡ๆ–™ๅบซๅ–ๅพ—็‰ฉไปถใ€‚ๆŽฅ่‘—๏ผŒๅœจๅ‘ผๅซ่ƒŒๆ™ฏไปปๅ‹™ๅ‡ฝๅผๆ™‚๏ผŒไธๆ˜ฏๅ‚ณ้ž่ณ‡ๆ–™ๅบซ็‰ฉไปถๆœฌ่บซ๏ผŒ่€Œๆ˜ฏๅ‚ณ้ž่ฉฒ็‰ฉไปถ็š„ ID๏ผŒ็„ถๅพŒๅœจ่ƒŒๆ™ฏไปปๅ‹™ๅ‡ฝๅผๅ…งๅ†้€้Ž้€™ๅ€‹ ID ๅ–ๅพ—็‰ฉไปถใ€‚ diff --git a/docs/zh-hant/docs/advanced/advanced-python-types.md b/docs/zh-hant/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..ffa139427a --- /dev/null +++ b/docs/zh-hant/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ้€ฒ้šŽ Python ๅž‹ๅˆฅ { #advanced-python-types } + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅœจไฝฟ็”จ Python ๅž‹ๅˆฅๆ™‚ๅฏ่ƒฝๆœ‰็”จ็š„้กๅค–ๆƒณๆณ•ใ€‚ + +## ไฝฟ็”จ `Union` ๆˆ– `Optional` { #using-union-or-optional } + +ๅฆ‚ๆžœไฝ ็š„็จ‹ๅผ็ขผๅ› ๆŸไบ›ๅŽŸๅ› ็„กๆณ•ไฝฟ็”จ `|`๏ผŒไพ‹ๅฆ‚ไธๆ˜ฏๅœจๅž‹ๅˆฅ่จป่จ˜ไธญ๏ผŒ่€Œๆ˜ฏๅœจๅƒ `response_model=` ไน‹้กž็š„ๅƒๆ•ธไฝ็ฝฎ๏ผŒ้‚ฃ้บผไฝ ๅฏไปฅ็”จ `typing` ไธญ็š„ `Union` ไพ†ๅ–ไปฃ่ฑŽ็ทš๏ผˆ`|`๏ผ‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘ŠๆŸๅ€‹ๅ€ผๅฏไปฅๆ˜ฏ `str` ๆˆ– `None`๏ผš + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +ๅœจ `typing` ไธญไนŸๆœ‰็”จ `Optional` ๅฎฃๅ‘ŠๆŸๅ€‹ๅ€ผๅฏไปฅๆ˜ฏ `None` ็š„้€Ÿ่จ˜ๆณ•ใ€‚ + +ไปฅไธ‹ๆ˜ฏๆˆ‘ๅ€‹ไบบ๏ผˆ้žๅธธไธป่ง€๏ผ‰็š„ๅปบ่ญฐ๏ผš + +* ๐Ÿšจ ้ฟๅ…ไฝฟ็”จ `Optional[SomeType]` +* ๆ”น็‚บ โœจ ไฝฟ็”จ `Union[SomeType, None]` โœจใ€‚ + +ๅ…ฉ่€…็ญ‰ๅƒนไธ”ๅบ•ๅฑค็›ธๅŒ๏ผŒไฝ†ๆˆ‘ๆœƒๆŽจ่–ฆ็”จ `Union` ่€Œไธ่ฆ็”จ `Optional`๏ผŒๅ› ็‚บใ€Œoptionalใ€้€™ๅ€‹่ฉž็œ‹่ตทไพ†ๆœƒ่ฎ“ไบบไปฅ็‚บ้€™ๅ€‹ๅ€ผๆ˜ฏๅฏ้ธ็š„๏ผŒไฝ†ๅฏฆ้š›ไธŠๅฎƒ็š„ๆ„ๆ€ๆ˜ฏใ€Œๅฏไปฅๆ˜ฏ `None`ใ€๏ผŒๅณไฝฟๅฎƒไธๆ˜ฏๅฏ้ธ็š„ใ€ไป็„ถๆ˜ฏๅฟ…ๅกซใ€‚ + +ๆˆ‘่ช็‚บ `Union[SomeType, None]` ๆ›ด่ƒฝๆธ…ๆฅš่กจ้”ๅ…ถๅซ็พฉใ€‚ + +้€™ๅชๆ˜ฏๆŽช่พญ่ˆ‡ๅ‘ฝๅๅ•้กŒ๏ผŒไฝ†้€™ไบ›่ฉžๆœƒๅฝฑ้Ÿฟไฝ ่ˆ‡ๅœ˜้šŠๆˆๅ“กๅฐ็จ‹ๅผ็ขผ็š„็†่งฃใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็œ‹็œ‹ไธ‹้ข้€™ๅ€‹ๅ‡ฝๅผ๏ผš + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +ๅƒๆ•ธ `name` ่ขซๆจ™่จป็‚บ `Optional[str]`๏ผŒไฝ†ๅฎƒไธฆไธๆ˜ฏๅฏ้ธ็š„๏ผ›ไฝ ไธ่ƒฝๅœจๆฒ’ๆœ‰่ฉฒๅƒๆ•ธ็š„ๆƒ…ๆณไธ‹ๅ‘ผๅซ้€™ๅ€‹ๅ‡ฝๅผ๏ผš + +```Python +say_hi() # ็ณŸไบ†๏ผŒ้€™ๆœƒๆ‹‹ๅ‡บ้Œฏ่ชค๏ผ๐Ÿ˜ฑ +``` + +ๅƒๆ•ธ `name` ไปๆ˜ฏๅฟ…ๅกซ๏ผˆไธๆ˜ฏๅฏ้ธ๏ผ‰๏ผŒๅ› ็‚บๅฎƒๆฒ’ๆœ‰้ ่จญๅ€ผใ€‚ไธ้Ž๏ผŒ`name` ๅฏไปฅๆŽฅๅ— `None` ไฝœ็‚บๅ€ผ๏ผš + +```Python +say_hi(name=None) # ้€™ๅฏ่กŒ๏ผŒNone ๆ˜ฏๆœ‰ๆ•ˆ็š„ ๐ŸŽ‰ +``` + +ๅฅฝๆถˆๆฏๆ˜ฏ๏ผŒๅคšๆ•ธๆƒ…ๆณไธ‹ไฝ ๅฏไปฅ็›ดๆŽฅ็”จ `|` ไพ†ๅฎš็พฉๅž‹ๅˆฅ่ฏ้›†๏ผš + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +ๅ› ๆญค๏ผŒ้€šๅธธไฝ ไธๅฟ…็‚บ `Optional` ่ˆ‡ `Union` ้€™ไบ›ๅ็จฑๆ“ๅฟƒใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/advanced/async-tests.md b/docs/zh-hant/docs/advanced/async-tests.md new file mode 100644 index 0000000000..cb7430bf6e --- /dev/null +++ b/docs/zh-hant/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# ้žๅŒๆญฅๆธฌ่ฉฆ { #async-tests } + +ไฝ ๅทฒ็ถ“็œ‹้Žๅฆ‚ไฝ•ไฝฟ็”จๆไพ›็š„ `TestClient` ไพ†ๆธฌ่ฉฆไฝ ็š„ FastAPI ๆ‡‰็”จใ€‚ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไฝ ๅช็œ‹ๅˆฐๅฆ‚ไฝ•ๆ’ฐๅฏซๅŒๆญฅๆธฌ่ฉฆ๏ผŒๆฒ’ๆœ‰ไฝฟ็”จ `async` ๅ‡ฝๅผใ€‚ + +ๅœจๆธฌ่ฉฆไธญ่ƒฝไฝฟ็”จ้žๅŒๆญฅๅ‡ฝๅผๆœƒๅพˆๆœ‰็”จ๏ผŒไพ‹ๅฆ‚็•ถไฝ ไปฅ้žๅŒๆญฅๆ–นๅผๆŸฅ่ฉข่ณ‡ๆ–™ๅบซๆ™‚ใ€‚ๆƒณๅƒไฝ ๆƒณๆธฌ่ฉฆ็™ผ้€่ซ‹ๆฑ‚ๅˆฐ FastAPI ๆ‡‰็”จ๏ผŒ็„ถๅพŒๅœจไฝฟ็”จ้žๅŒๆญฅ่ณ‡ๆ–™ๅบซๅ‡ฝๅผๅบซๆ™‚๏ผŒ้ฉ—่ญ‰ๅพŒ็ซฏๆ˜ฏๅฆๆˆๅŠŸๆŠŠๆญฃ็ขบ่ณ‡ๆ–™ๅฏซๅ…ฅ่ณ‡ๆ–™ๅบซใ€‚ + +ไพ†็œ‹็œ‹ๆ€Ž้บผๅšใ€‚ + +## pytest.mark.anyio { #pytest-mark-anyio } + +่‹ฅ่ฆๅœจๆธฌ่ฉฆไธญๅ‘ผๅซ้žๅŒๆญฅๅ‡ฝๅผ๏ผŒๆธฌ่ฉฆๅ‡ฝๅผๆœฌ่บซไนŸๅฟ…้ ˆๆ˜ฏ้žๅŒๆญฅ็š„ใ€‚AnyIO ็‚บๆญคๆไพ›ไบ†ไธ€ๅ€‹ๅฅฝ็”จ็š„ๅค–ๆŽ›๏ผŒ่ฎ“ๆˆ‘ๅ€‘ๅฏไปฅๆจ™็คบๆŸไบ›ๆธฌ่ฉฆๅ‡ฝๅผไปฅ้žๅŒๆญฅๆ–นๅผๅŸท่กŒใ€‚ + +## HTTPX { #httpx } + +ๅณไฝฟไฝ ็š„ FastAPI ๆ‡‰็”จไฝฟ็”จไธ€่ˆฌ็š„ `def` ๅ‡ฝๅผ่€Œ้ž `async def`๏ผŒๅฎƒๅœจๅบ•ๅฑคไป็„ถๆ˜ฏๅ€‹ `async` ๆ‡‰็”จใ€‚ + +`TestClient` ๅœจๅ…ง้ƒจๅšไบ†ไธ€ไบ›้ญ”ๆณ•๏ผŒ่ฎ“ๆˆ‘ๅ€‘่ƒฝๅœจไธ€่ˆฌ็š„ `def` ๆธฌ่ฉฆๅ‡ฝๅผไธญ๏ผŒไฝฟ็”จๆจ™ๆบ– pytest ไพ†ๅ‘ผๅซ้žๅŒๆญฅ็š„ FastAPI ๆ‡‰็”จใ€‚ไฝ†็•ถๆˆ‘ๅ€‘ๅœจ้žๅŒๆญฅๅ‡ฝๅผไธญไฝฟ็”จๅฎƒๆ™‚๏ผŒ้€™ๅ€‹้ญ”ๆณ•ๅฐฑไธๅ†ๅฅๆ•ˆไบ†ใ€‚ไนŸๅฐฑๆ˜ฏ่ชช๏ผŒ็•ถไปฅ้žๅŒๆญฅๆ–นๅผๅŸท่กŒๆธฌ่ฉฆๆ™‚๏ผŒๅฐฑไธ่ƒฝๅœจๆธฌ่ฉฆๅ‡ฝๅผๅ…งไฝฟ็”จ `TestClient`ใ€‚ + +`TestClient` ๆ˜ฏๅปบ็ซ‹ๅœจ HTTPX ไน‹ไธŠ๏ผŒๆ‰€ๅนธๆˆ‘ๅ€‘ๅฏไปฅ็›ดๆŽฅไฝฟ็”จๅฎƒไพ†ๆธฌ่ฉฆ APIใ€‚ + +## ็ฏ„ไพ‹ { #example } + +ไฝœ็‚บ็ฐกๅ–ฎ็ฏ„ไพ‹๏ผŒ่ฎ“ๆˆ‘ๅ€‘่€ƒๆ…ฎ่ˆ‡[ๆ›ดๅคงๅž‹็š„ๆ‡‰็”จ](../tutorial/bigger-applications.md){.internal-link target=_blank}่ˆ‡[ๆธฌ่ฉฆ](../tutorial/testing.md){.internal-link target=_blank}ไธญๆ่ฟฐ็š„้กžไผผๆช”ๆกˆ็ตๆง‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +ๆช”ๆกˆ `main.py` ๆœƒๆ˜ฏ๏ผš + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +ๆช”ๆกˆ `test_main.py` ๆœƒๅŒ…ๅซ้‡ๅฐ `main.py` ็š„ๆธฌ่ฉฆ๏ผŒ็พๅœจๅฏ่ƒฝๅƒ้€™ๆจฃ๏ผš + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## ๅŸท่กŒ { #run-it } + +ๅฆ‚ๅธธๅŸท่กŒๆธฌ่ฉฆ๏ผš + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## ่ฉณ่งฃ { #in-detail } + +ๆจ™่จ˜ `@pytest.mark.anyio` ๅ‘Š่จด pytest ้€™ๅ€‹ๆธฌ่ฉฆๅ‡ฝๅผๆ‡‰ไปฅ้žๅŒๆญฅๆ–นๅผๅŸท่กŒ๏ผš + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip + +ๆณจๆ„๏ผŒๆธฌ่ฉฆๅ‡ฝๅผ็พๅœจๆ˜ฏ `async def`๏ผŒ่€Œไธๆ˜ฏๅƒไฝฟ็”จ `TestClient` ๆ™‚้‚ฃๆจฃๅƒ…็”จ `def`ใ€‚ + +/// + +ๆŽฅ่‘—๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ็”จ่ฉฒๆ‡‰็”จๅปบ็ซ‹ `AsyncClient`๏ผŒไธฆไปฅ `await` ็™ผ้€้žๅŒๆญฅ่ซ‹ๆฑ‚ใ€‚ + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +้€™็ญ‰ๅŒๆ–ผ๏ผš + +```Python +response = client.get('/') +``` + +ไนŸๅฐฑๆ˜ฏๅ…ˆๅ‰็”จ `TestClient` ็™ผ้€่ซ‹ๆฑ‚ๆ™‚ๆ‰€็”จ็š„ๅฏซๆณ•ใ€‚ + +/// tip + +ๆณจๆ„๏ผŒๅฐๆ–ฐ็š„ `AsyncClient` ้œ€ๆญ้… async/await โ€”โ€” ่ซ‹ๆฑ‚ๆ˜ฏ้žๅŒๆญฅ็š„ใ€‚ + +/// + +/// warning + +ๅฆ‚ๆžœไฝ ็š„ๆ‡‰็”จไปฐ่ณด lifespan ไบ‹ไปถ๏ผŒ`AsyncClient` ไธๆœƒ่งธ็™ผ้€™ไบ›ไบ‹ไปถใ€‚่‹ฅ่ฆ็ขบไฟๅฎƒๅ€‘่ขซ่งธ็™ผ๏ผŒ่ซ‹ไฝฟ็”จ florimondmanca/asgi-lifespan ็š„ `LifespanManager`ใ€‚ + +/// + +## ๅ…ถไป–้žๅŒๆญฅๅ‡ฝๅผๅ‘ผๅซ { #other-asynchronous-function-calls } + +็”ฑๆ–ผๆธฌ่ฉฆๅ‡ฝๅผ็พๅœจๆ˜ฏ้žๅŒๆญฅ็š„๏ผŒไฝ ไนŸๅฏไปฅๅœจๆธฌ่ฉฆไธญๅ‘ผๅซ๏ผˆไธฆ `await`๏ผ‰ๅ…ถไป– `async` ๅ‡ฝๅผ๏ผŒๅ’Œๅœจ็จ‹ๅผ็ขผๅ…ถไป–ๅœฐๆ–นไธ€ๆจฃใ€‚ + +/// tip + +ๅฆ‚ๆžœๅœจๅฐ‡้žๅŒๆญฅๅ‘ผๅซๆ•ดๅˆ้€ฒๆธฌ่ฉฆๆ™‚้‡ๅˆฐ `RuntimeError: Task attached to a different loop`๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ MongoDB ็š„ MotorClient ๆ™‚๏ผ‰๏ผŒ่ซ‹่จ˜ๅพ—๏ผš้œ€่ฆไบ‹ไปถ่ฟดๅœˆ็š„็‰ฉไปถๅชๆ‡‰ๅœจ้žๅŒๆญฅๅ‡ฝๅผๅ…งๅฏฆไพ‹ๅŒ–๏ผŒไพ‹ๅฆ‚ๅœจ `@app.on_event("startup")` ๅ›žๅ‘ผไธญใ€‚ + +/// diff --git a/docs/zh-hant/docs/advanced/behind-a-proxy.md b/docs/zh-hant/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..71a0557afd --- /dev/null +++ b/docs/zh-hant/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# ๅœจไปฃ็†ไน‹ๅพŒ { #behind-a-proxy } + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒๅœจ FastAPI ๆ‡‰็”จๅ‰้ขๆ”พไธ€ๅ€‹ใ€Œไปฃ็†ใ€๏ผˆproxy๏ผ‰๏ผŒไพ‹ๅฆ‚ Traefik ๆˆ– Nginxใ€‚ + +้€™ไบ›ไปฃ็†ๅฏไปฅ่™•็† HTTPS ๆ†‘่ญ‰็ญ‰ไบ‹ๅ‹™ใ€‚ + +## ไปฃ็†่ฝ‰็™ผๆจ™้ ญ { #proxy-forwarded-headers } + +ๅœจไฝ ็š„ๆ‡‰็”จๅ‰ๆ–น็š„ใ€Œไปฃ็†ใ€้€šๅธธๆœƒๅœจๅฐ‡่ซ‹ๆฑ‚้€็ตฆไฝ ็š„ใ€Œไผบๆœๅ™จใ€ไน‹ๅ‰๏ผŒ่‡จๆ™‚ๅŠ ๅ…ฅไธ€ไบ›ๆจ™้ ญ๏ผŒ่ฎ“ไผบๆœๅ™จ็Ÿฅ้“้€™ๅ€‹่ซ‹ๆฑ‚ๆ˜ฏ็”ฑไปฃ็†ใ€Œ่ฝ‰็™ผใ€้Žไพ†็š„๏ผŒไธฆๅ‘Š่จดๅฎƒๅŽŸๅง‹๏ผˆๅ…ฌ้–‹๏ผ‰็š„ URL๏ผŒๅŒ…ๆ‹ฌ็ถฒๅŸŸใ€ๆ˜ฏๅฆไฝฟ็”จ HTTPS ็ญ‰ใ€‚ + +ใ€Œไผบๆœๅ™จใ€็จ‹ๅผ๏ผˆไพ‹ๅฆ‚้€้Ž FastAPI CLI ๅ•Ÿๅ‹•็š„ Uvicorn๏ผ‰่ƒฝๅค ่งฃ่ฎ€้€™ไบ›ๆจ™้ ญ๏ผŒ็„ถๅพŒๆŠŠ่ฉฒ่ณ‡่จŠๅ‚ณ้ž็ตฆไฝ ็š„ๆ‡‰็”จใ€‚ + +ไฝ†ๅ‡บๆ–ผๅฎ‰ๅ…จ่€ƒ้‡๏ผŒๅ› ็‚บไผบๆœๅ™จไธฆไธ็Ÿฅ้“่‡ชๅทฑไฝๆ–ผๅ—ไฟกไปป็š„ไปฃ็†ไน‹ๅพŒ๏ผŒๆ‰€ไปฅๅฎƒไธๆœƒ่งฃ่ฎ€้‚ฃไบ›ๆจ™้ ญใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไปฃ็†็›ธ้—œ็š„ๆจ™้ ญๆœ‰๏ผš + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### ๅ•Ÿ็”จไปฃ็†่ฝ‰็™ผๆจ™้ ญ { #enable-proxy-forwarded-headers } + +ไฝ ๅฏไปฅๅœจๅ•Ÿๅ‹• FastAPI CLI ๆ™‚ไฝฟ็”จใ€ŒCLI ้ธ้ …ใ€`--forwarded-allow-ips`๏ผŒไธฆๅ‚ณๅ…ฅๅ…่จฑ่งฃๆž้€™ไบ›่ฝ‰็™ผๆจ™้ ญ็š„ๅ—ไฟกไปป IP ไฝๅ€ใ€‚ + +ๅฆ‚ๆžœๅฐ‡ๅ…ถ่จญ็‚บ `--forwarded-allow-ips="*"`๏ผŒๅฐฑๆœƒไฟกไปปๆ‰€ๆœ‰้€ฒไพ†็š„ IPใ€‚ + +ๅฆ‚ๆžœไฝ ็š„ใ€Œไผบๆœๅ™จใ€ไฝๆ–ผๅ—ไฟกไปป็š„ใ€Œไปฃ็†ใ€ไน‹ๅพŒ๏ผŒไธ”ๅชๆœ‰ไปฃ็†ๆœƒ่ˆ‡ๅฎƒ้€š่จŠ๏ผŒ้€™ๆจฃๆœƒ่ฎ“ๅฎƒๆŽฅๅ—่ฉฒใ€Œไปฃ็†ใ€็š„ไปปไฝ• IPใ€‚ + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ไฝฟ็”จ HTTPS ็š„้‡ๆ–ฐๅฐŽๅ‘ { #redirects-with-https } + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ๅฎš็พฉไบ†ไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€`/items/`๏ผš + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +ๅฆ‚ๆžœ็”จๆˆถ็ซฏๅ˜—่ฉฆๅ‰ๅพ€ `/items`๏ผŒ้ ่จญๆœƒ่ขซ้‡ๆ–ฐๅฐŽๅ‘ๅˆฐ `/items/`ใ€‚ + +ไฝ†ๅœจ่จญๅฎšใ€ŒCLI ้ธ้ …ใ€`--forwarded-allow-ips` ไน‹ๅ‰๏ผŒๅฎƒๅฏ่ƒฝๆœƒ่ขซ้‡ๆ–ฐๅฐŽๅ‘ๅˆฐ `http://localhost:8000/items/`ใ€‚ + +ไธ้Ž๏ผŒไนŸ่จฑไฝ ็š„ๆ‡‰็”จๅฏฆ้š›้ƒจ็ฝฒๅœจ `https://mysuperapp.com`๏ผŒ้‚ฃ้‡ๆ–ฐๅฐŽๅ‘ๅฐฑๆ‡‰่ฉฒๆ˜ฏ `https://mysuperapp.com/items/`ใ€‚ + +่จญๅฎš `--proxy-headers` ไน‹ๅพŒ๏ผŒFastAPI ๅฐฑ่ƒฝ้‡ๆ–ฐๅฐŽๅ‘ๅˆฐๆญฃ็ขบ็š„ไฝ็ฝฎใ€‚๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip + +ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃๆ›ดๅคš HTTPS ็š„ๅ…งๅฎน๏ผŒ่ซ‹ๅƒ่€ƒๆŒ‡ๅ—๏ผป[้—œๆ–ผ HTTPS](../deployment/https.md){.internal-link target=_blank}๏ผฝใ€‚ + +/// + +### ไปฃ็†่ฝ‰็™ผๆจ™้ ญๅฆ‚ไฝ•้‹ไฝœ { #how-proxy-forwarded-headers-work } + +ไปฅไธ‹ๆ˜ฏใ€Œไปฃ็†ใ€ๅœจ็”จๆˆถ็ซฏ่ˆ‡ใ€Œๆ‡‰็”จไผบๆœๅ™จใ€ไน‹้–“ๅŠ ๅ…ฅ่ฝ‰็™ผๆจ™้ ญ็š„่ฆ–่ฆบๅŒ–็คบๆ„๏ผš + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +ใ€Œไปฃ็†ใ€ๆœƒๆ””ๆˆชๅŽŸๅง‹็”จๆˆถ็ซฏ่ซ‹ๆฑ‚๏ผŒไธฆๅœจๅฐ‡ๅ…ถ่ฝ‰ไบค็ตฆใ€Œๆ‡‰็”จไผบๆœๅ™จใ€ไน‹ๅ‰ๅŠ ๅ…ฅ็‰นๆฎŠ็š„ใ€Œ่ฝ‰็™ผใ€ๆจ™้ ญ๏ผˆ`X-Forwarded-*`๏ผ‰ใ€‚ + +้€™ไบ›ๆจ™้ ญๆœƒไฟ็•™ๅŽŸๅง‹่ซ‹ๆฑ‚ไธญๅŽŸๆœฌๆœƒ้บๅคฑ็š„่ณ‡่จŠ๏ผš + +* X-Forwarded-For๏ผšๅŽŸๅง‹็”จๆˆถ็ซฏ็š„ IP ไฝๅ€ +* X-Forwarded-Proto๏ผšๅŽŸๅง‹ๅ”ๅฎš๏ผˆ`https`๏ผ‰ +* X-Forwarded-Host๏ผšๅŽŸๅง‹ไธปๆฉŸ๏ผˆ`mysuperapp.com`๏ผ‰ + +็•ถไปฅ `--forwarded-allow-ips` ่จญๅฎšๅฅฝ FastAPI CLI ๅพŒ๏ผŒๅฎƒๆœƒไฟกไปปไธฆไฝฟ็”จ้€™ไบ›ๆจ™้ ญ๏ผŒไพ‹ๅฆ‚ๅœจ้‡ๆ–ฐๅฐŽๅ‘ๆ™‚็”ข็”Ÿๆญฃ็ขบ็š„ URLใ€‚ + +## ๅ…ทๆœ‰็งป้™ค่ทฏๅพ‘ๅ‰็ถด็š„ไปฃ็† { #proxy-with-a-stripped-path-prefix } + +ไฝ ๅฏ่ƒฝๆœƒๆœ‰ไธ€ๅ€‹ๆœƒ็‚บไฝ ็š„ๆ‡‰็”จๅŠ ๅ…ฅ่ทฏๅพ‘ๅ‰็ถด็š„ไปฃ็†ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `root_path` ไพ†่จญๅฎšไฝ ็š„ๆ‡‰็”จใ€‚ + +`root_path` ๆ˜ฏ ASGI ่ฆๆ ผ๏ผˆFastAPI ้€้Ž Starlette ๆ‰€้ตๅพช็š„่ฆๆ ผ๏ผ‰ๆ‰€ๆไพ›็š„ๆฉŸๅˆถใ€‚ + +`root_path` ็”จไพ†่™•็†้€™ไบ›็‰นๅฎšๆƒ…ๅขƒใ€‚ + +ๅœจๆŽ›่ผ‰ๅญๆ‡‰็”จๆ™‚๏ผŒๅ…ง้ƒจไนŸๆœƒไฝฟ็”จๅฎƒใ€‚ + +้€™็จฎใ€Œๅ…ทๆœ‰็งป้™ค่ทฏๅพ‘ๅ‰็ถด็š„ไปฃ็†ใ€ๆƒ…ๆณ๏ผŒไปฃ่กจไฝ ๅœจ็จ‹ๅผ็ขผไธญๅฎฃๅ‘Šไบ† `/app` ็š„่ทฏๅพ‘๏ผŒไฝ†ไฝ ๅœจไธŠ้ขๅˆๅŠ ไบ†ไธ€ๅฑค๏ผˆไปฃ็†๏ผ‰๏ผŒๆŠŠไฝ ็š„ FastAPI ๆ‡‰็”จๆ”พๅœจๅƒๆ˜ฏ `/api/v1` ้€™ๆจฃ็š„่ทฏๅพ‘ๅบ•ไธ‹ใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅŽŸๆœฌ็š„ `/app` ่ทฏๅพ‘ๅฏฆ้š›ไธŠๆœƒไปฅ `/api/v1/app` ๅฐๅค–ๆไพ›ๆœๅ‹™ใ€‚ + +ๅณไฝฟไฝ ็š„็จ‹ๅผ็ขผ้ƒฝๆ˜ฏไปฅๅชๆœ‰ `/app` ็‚บๅ‰ๆๆ’ฐๅฏซ็š„ใ€‚ + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +่€Œไปฃ็†ๆœƒๅœจๆŠŠ่ซ‹ๆฑ‚่ฝ‰ไบค็ตฆๆ‡‰็”จไผบๆœๅ™จ๏ผˆๅคšๅŠๆ˜ฏ้€้Ž FastAPI CLI ๅ•Ÿๅ‹•็š„ Uvicorn๏ผ‰ไน‹ๅ‰๏ผŒๅ‹•ๆ…‹ๅœฐใ€Œ็งป้™คใ€้€™ๅ€‹ใ€Œ่ทฏๅพ‘ๅ‰็ถดใ€๏ผŒ่ฎ“ไฝ ็š„ๆ‡‰็”จไป็„ถไปฅ็‚บ่‡ชๅทฑๆ˜ฏๅœจ `/app` ๅบ•ไธ‹่ขซๆไพ›๏ผŒ้€™ๆจฃไฝ ๅฐฑไธ้œ€่ฆๆŠŠๆ•ดๅ€‹็จ‹ๅผ็ขผ้ƒฝๆ”นๆˆๅŒ…ๅซ `/api/v1` ้€™ๅ€‹ๅ‰็ถดใ€‚ + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไธ€ๅˆ‡้ƒฝๆœƒๅฆ‚ๅธธ้‹ไฝœใ€‚ + +ไฝ†ๆ˜ฏ๏ผŒ็•ถไฝ ๆ‰“้–‹ๆ•ดๅˆ็š„ๆ–‡ไปถ UI๏ผˆๅ‰็ซฏ๏ผ‰ๆ™‚๏ผŒๅฎƒๆœƒ้ ๆœŸๅœจ `/openapi.json` ๅ–ๅพ— OpenAPI ๆจกๅผ๏ผŒ่€Œไธๆ˜ฏๅœจ `/api/v1/openapi.json`ใ€‚ + +ๅ› ๆญค๏ผŒๅ‰็ซฏ๏ผˆๅœจ็€่ฆฝๅ™จไธญๅŸท่กŒ๏ผ‰ๆœƒๅ˜—่ฉฆๅญ˜ๅ– `/openapi.json`๏ผŒไฝ†็„กๆณ•ๅ–ๅพ— OpenAPI ๆจกๅผใ€‚ + +ๅ› ็‚บๆˆ‘ๅ€‘็š„ๆ‡‰็”จๅ‰้ขๆœ‰ไธ€ๅ€‹ๅฐ‡่ทฏๅพ‘ๅ‰็ถด่จญๅฎš็‚บ `/api/v1` ็š„ไปฃ็†๏ผŒๆ‰€ไปฅๅ‰็ซฏ้œ€่ฆๅพž `/api/v1/openapi.json` ๅ–ๅพ— OpenAPI ๆจกๅผใ€‚ + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip + +IP `0.0.0.0` ้€šๅธธ็”จไพ†่กจ็คบ็จ‹ๅผๅœจ่ฉฒๆฉŸๅ™จ๏ผไผบๆœๅ™จไธŠ็š„ๆ‰€ๆœ‰ๅฏ็”จ IP ไธŠ็›ฃ่ฝใ€‚ + +/// + +ๆ–‡ไปถ UI ไนŸ้œ€่ฆ OpenAPI ๆจกๅผๅฎฃๅ‘Šๆญค API ็š„ `server` ไฝๅœจ `/api/v1`๏ผˆไปฃ็†ไน‹ๅพŒ๏ผ‰ใ€‚ไพ‹ๅฆ‚๏ผš + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // ๅ…ถไป–ๅ…งๅฎน + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // ๅ…ถไป–ๅ…งๅฎน + } +} +``` + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒใ€ŒProxyใ€ๅฏไปฅๆ˜ฏ **Traefik**ใ€‚่€Œไผบๆœๅ™จๅฏไปฅๆ˜ฏไปฅ **Uvicorn** ๅ•Ÿๅ‹•็š„ FastAPI CLI๏ผŒ้‹่กŒไฝ ็š„ FastAPI ๆ‡‰็”จใ€‚ + +### ๆไพ› `root_path` { #providing-the-root-path } + +่ฆ้”ๆˆ้€™ไธ€้ปž๏ผŒไฝ ๅฏไปฅๅƒ้€™ๆจฃไฝฟ็”จๅ‘ฝไปคๅˆ—้ธ้ … `--root-path`๏ผš + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ๅฆ‚ๆžœไฝ ไฝฟ็”จ Hypercorn๏ผŒๅฎƒไนŸๆœ‰ `--root-path` ้€™ๅ€‹้ธ้ …ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ASGI ่ฆๆ ผ้‡ๅฐ้€™็จฎ็”จไพ‹ๅฎš็พฉไบ† `root_path`ใ€‚ + +่€Œๅ‘ฝไปคๅˆ—้ธ้ … `--root-path` ๅฐฑๆ˜ฏๆไพ›่ฉฒ `root_path`ใ€‚ + +/// + +### ๆชข่ฆ–็›ฎๅ‰็š„ `root_path` { #checking-the-current-root-path } + +ไฝ ๅฏไปฅๅœจๆฏๅ€‹่ซ‹ๆฑ‚ไธญๅ–ๅพ—ๆ‡‰็”จไฝฟ็”จ็š„ `root_path`๏ผŒๅฎƒๆ˜ฏ `scope` ๅญ—ๅ…ธ็š„ไธ€้ƒจๅˆ†๏ผˆASGI ่ฆๆ ผ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ + +้€™่ฃกๆˆ‘ๅ€‘ๆŠŠๅฎƒๆ”พๅˆฐๅ›žๅ‚ณ่จŠๆฏไธญๅชๆ˜ฏ็‚บไบ†็คบ็ฏ„ใ€‚ + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +ๆŽฅ่‘—๏ผŒๅฆ‚ๆžœไฝ ็”จไธ‹ๅˆ—ๆ–นๅผๅ•Ÿๅ‹• Uvicorn๏ผš + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ๅ›žๆ‡‰ๆœƒๅƒๆ˜ฏ๏ผš + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### ๅœจ FastAPI ๆ‡‰็”จไธญ่จญๅฎš `root_path` { #setting-the-root-path-in-the-fastapi-app } + +ๆˆ–่€…๏ผŒๅฆ‚ๆžœไฝ ็„กๆณ•ๆไพ›ๅƒ `--root-path` ้€™ๆจฃ็š„ๅ‘ฝไปคๅˆ—้ธ้ …๏ผˆๆˆ–็ญ‰ๆ•ˆๆ–นๅผ๏ผ‰๏ผŒไฝ ๅฏไปฅๅœจๅปบ็ซ‹ FastAPI ๆ‡‰็”จๆ™‚่จญๅฎš `root_path` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +ๆŠŠ `root_path` ๅ‚ณ็ตฆ `FastAPI` ็ญ‰ๅŒๆ–ผๅœจ Uvicorn ๆˆ– Hypercorn ไธŠไฝฟ็”จๅ‘ฝไปคๅˆ—้ธ้ … `--root-path`ใ€‚ + +### ้—œๆ–ผ `root_path` { #about-root-path } + +่ซ‹่จ˜ไฝ๏ผŒไผบๆœๅ™จ๏ผˆUvicorn๏ผ‰้™คไบ†ๆŠŠ `root_path` ๅ‚ณ็ตฆๆ‡‰็”จไน‹ๅค–๏ผŒไธๆœƒๆ‹ฟๅฎƒๅšๅ…ถไป–็”จ้€”ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็”จ็€่ฆฝๅ™จๅ‰ๅพ€ http://127.0.0.1:8000/app๏ผŒไฝ ๆœƒ็œ‹ๅˆฐไธ€่ˆฌ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ๅ› ๆญค๏ผŒๅฎƒไธๆœƒ้ ๆœŸ่ขซไปฅ `http://127.0.0.1:8000/api/v1/app` ็š„ๆ–นๅผๅญ˜ๅ–ใ€‚ + +Uvicorn ๆœƒ้ ๆœŸไปฃ็†ไปฅ `http://127.0.0.1:8000/app` ไพ†ๅญ˜ๅ– Uvicorn๏ผŒ่€Œ็”ฑไปฃ็†่ฒ ่ฒฌๅœจไธŠๅฑคๅŠ ไธŠ้กๅค–็š„ `/api/v1` ๅ‰็ถดใ€‚ + +## ้—œๆ–ผใ€Œ็งป้™ค่ทฏๅพ‘ๅ‰็ถดใ€็š„ไปฃ็† { #about-proxies-with-a-stripped-path-prefix } + +่ซ‹่จ˜ไฝ๏ผŒๅ…ทๆœ‰ใ€Œ็งป้™ค่ทฏๅพ‘ๅ‰็ถดใ€็š„ไปฃ็†ๅชๆ˜ฏๅ…ถไธญไธ€็จฎ่จญๅฎšๆ–นๅผใ€‚ + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒ้ ่จญๅฏ่ƒฝๆ˜ฏไธ็งป้™ค่ทฏๅพ‘ๅ‰็ถดใ€‚ + +ๅœจ้‚ฃ็จฎๆƒ…ๆณ๏ผˆๆฒ’ๆœ‰็งป้™ค่ทฏๅพ‘ๅ‰็ถด๏ผ‰ไธ‹๏ผŒไปฃ็†ๆœƒ็›ฃ่ฝๅƒๆ˜ฏ `https://myawesomeapp.com`๏ผŒ็„ถๅพŒ็•ถ็€่ฆฝๅ™จๅ‰ๅพ€ `https://myawesomeapp.com/api/v1/app`๏ผŒ่€Œไฝ ็š„ไผบๆœๅ™จ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ๅœจ `http://127.0.0.1:8000` ็›ฃ่ฝๆ™‚๏ผŒ่ฉฒไปฃ็†๏ผˆไธ็งป้™ค่ทฏๅพ‘ๅ‰็ถด๏ผ‰ๅฐฑๆœƒไปฅๅŒๆจฃ็š„่ทฏๅพ‘ๅŽปๅญ˜ๅ– Uvicorn๏ผš`http://127.0.0.1:8000/api/v1/app`ใ€‚ + +## ๅœจๆœฌๆฉŸไฝฟ็”จ Traefik ๆธฌ่ฉฆ { #testing-locally-with-traefik } + +ไฝ ๅฏไปฅๅพˆๅฎนๆ˜“ๅœฐ็”จ Traefik ๅœจๆœฌๆฉŸ่ท‘ไธ€ๅ€‹ใ€Œ็งป้™ค่ทฏๅพ‘ๅ‰็ถดใ€็š„ๆธฌ่ฉฆใ€‚ + +ไธ‹่ผ‰ Traefik๏ผŒๅฎƒๆ˜ฏไธ€ๅ€‹ๅ–ฎไธ€็š„ๅŸท่กŒๆช”๏ผŒไฝ ๅฏไปฅ่งฃๅฃ“็ธฎๅพŒ็›ดๆŽฅๅœจ็ต‚็ซฏๆฉŸๅŸท่กŒใ€‚ + +็„ถๅพŒๅปบ็ซ‹ไธ€ๅ€‹ `traefik.toml` ๆช”ๆกˆ๏ผŒๅ…งๅฎนๅฆ‚ไธ‹๏ผš + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +้€™ๅ‘Š่จด Traefik ็›ฃ่ฝ 9999 ๅŸ ๏ผŒไธฆไฝฟ็”จๅฆไธ€ๅ€‹ๆช”ๆกˆ `routes.toml`ใ€‚ + +/// tip + +ๆˆ‘ๅ€‘ไฝฟ็”จ 9999 ๅŸ ่€Œไธๆ˜ฏๆจ™ๆบ–็š„ HTTP 80 ๅŸ ๏ผŒ้€™ๆจฃไฝ ๅฐฑไธ้œ€่ฆไปฅ็ฎก็†ๅ“ก๏ผˆ`sudo`๏ผ‰ๆฌŠ้™ไพ†ๅŸท่กŒใ€‚ + +/// + +ๆŽฅ่‘—ๅปบ็ซ‹ๅฆไธ€ๅ€‹ `routes.toml` ๆช”ๆกˆ๏ผš + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +้€™ๅ€‹ๆช”ๆกˆๆŠŠ Traefik ่จญๅฎš็‚บไฝฟ็”จ `/api/v1` ็š„่ทฏๅพ‘ๅ‰็ถดใ€‚ + +็„ถๅพŒ Traefik ๆœƒๆŠŠๅฎƒ็š„่ซ‹ๆฑ‚่ฝ‰็™ผๅˆฐๅœจ `http://127.0.0.1:8000` ไธŠ้‹่กŒ็š„ Uvicornใ€‚ + +็พๅœจๅ•Ÿๅ‹• Traefik๏ผš + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +็„ถๅพŒๅ•Ÿๅ‹•ไฝ ็š„ๆ‡‰็”จ๏ผŒไฝฟ็”จ `--root-path` ้ธ้ …๏ผš + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ๆชขๆŸฅๅ›žๆ‡‰ { #check-the-responses } + +็พๅœจ๏ผŒๅฆ‚ๆžœไฝ ๅ‰ๅพ€ Uvicorn ็š„ๅŸ ๏ผšhttp://127.0.0.1:8000/app๏ผŒไฝ ๆœƒ็œ‹ๅˆฐไธ€่ˆฌ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip + +ๆณจๆ„๏ผŒๅ„˜็ฎกไฝ ๆ˜ฏ็”จ `http://127.0.0.1:8000/app` ๅญ˜ๅ–๏ผŒๅฎƒไป็„ถ้กฏ็คบๅพž `--root-path` ้ธ้ …ๅ–ๅพ—็š„ `root_path` ็‚บ `/api/v1`ใ€‚ + +/// + +ๆŽฅ่‘—ๆ‰“้–‹ไฝฟ็”จ Traefik ๅŸ ไธ”ๅŒ…ๅซ่ทฏๅพ‘ๅ‰็ถด็š„ URL๏ผšhttp://127.0.0.1:9999/api/v1/appใ€‚ + +ๆˆ‘ๅ€‘ๆœƒๅพ—ๅˆฐ็›ธๅŒ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ไฝ†้€™ๆฌกๆ˜ฏๅœจ็”ฑไปฃ็†ๆไพ›็š„ใ€ๅธถๆœ‰ๅ‰็ถด่ทฏๅพ‘็š„ URL๏ผš`/api/v1`ใ€‚ + +็•ถ็„ถ๏ผŒ้€™่ฃก็š„้‡้ปžๆ˜ฏๅคงๅฎถ้ƒฝๆœƒ้€้Žไปฃ็†ไพ†ๅญ˜ๅ–ๆ‡‰็”จ๏ผŒๆ‰€ไปฅๅธถๆœ‰ `/api/v1` ่ทฏๅพ‘ๅ‰็ถด็š„็‰ˆๆœฌๆ‰ๆ˜ฏใ€Œๆญฃ็ขบใ€็š„ใ€‚ + +่€Œๆฒ’ๆœ‰่ทฏๅพ‘ๅ‰็ถด็š„็‰ˆๆœฌ๏ผˆ`http://127.0.0.1:8000/app`๏ผ‰๏ผŒไนŸๅฐฑๆ˜ฏ็›ดๆŽฅ็”ฑ Uvicorn ๆไพ›็š„๏ผŒๆ‡‰่ฉฒๅช็ตฆใ€Œไปฃ็†ใ€๏ผˆTraefik๏ผ‰ไพ†ๅญ˜ๅ–ใ€‚ + +้€™ๅฑ•็คบไบ†ไปฃ็†๏ผˆTraefik๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ่ทฏๅพ‘ๅ‰็ถด๏ผŒไปฅๅŠไผบๆœๅ™จ๏ผˆUvicorn๏ผ‰ๅฆ‚ไฝ•ไฝฟ็”จ `--root-path` ้ธ้ …ๆไพ›็š„ `root_path`ใ€‚ + +### ๆชขๆŸฅๆ–‡ไปถ UI { #check-the-docs-ui } + +ๆŽฅไธ‹ไพ†ๆ˜ฏๆœ‰่ถฃ็š„้ƒจๅˆ†ใ€‚โœจ + +ใ€Œๆญฃๅผใ€็š„ๅญ˜ๅ–ๆ–นๅผๆ‡‰่ฉฒๆ˜ฏ้€้Žๆˆ‘ๅ€‘ๅฎš็พฉไบ†่ทฏๅพ‘ๅ‰็ถด็š„ไปฃ็†ใ€‚ๅ› ๆญค๏ผŒๅฆ‚ๆˆ‘ๅ€‘้ ๆœŸ๏ผŒๅฆ‚ๆžœไฝ ็›ดๆŽฅ้€้Ž Uvicorn ไพ›ๆ‡‰็š„ๆ–‡ไปถ UIใ€่€Œ URL ไธญๆฒ’ๆœ‰่ฉฒ่ทฏๅพ‘ๅ‰็ถด๏ผŒ้‚ฃๅฎƒไธๆœƒ้‹ไฝœ๏ผŒๅ› ็‚บๅฎƒ้ ๆœŸ่ฆ้€้Žไปฃ็†ไพ†ๅญ˜ๅ–ใ€‚ + +ไฝ ๅฏไปฅๅœจ http://127.0.0.1:8000/docs ๆชขๆŸฅ๏ผš + + + +ไฝ†ๅฆ‚ๆžœๆˆ‘ๅ€‘ๆ”น็”จใ€Œๆญฃๅผใ€็š„ URL๏ผŒไนŸๅฐฑๆ˜ฏไฝฟ็”จๅŸ ่™Ÿ `9999` ็š„ไปฃ็†ใ€ไธฆๅœจ `/api/v1/docs`๏ผŒๅฎƒๅฐฑ่ƒฝๆญฃ็ขบ้‹ไฝœไบ†๏ผ๐ŸŽ‰ + +ไฝ ๅฏไปฅๅœจ http://127.0.0.1:9999/api/v1/docs ๆชขๆŸฅ๏ผš + + + +ๆญฃๅฆ‚ๆˆ‘ๅ€‘ๆ‰€ๅธŒๆœ›็š„้‚ฃๆจฃใ€‚โœ”๏ธ + +้€™ๆ˜ฏๅ› ็‚บ FastAPI ไฝฟ็”จ้€™ๅ€‹ `root_path` ไพ†ๅœจ OpenAPI ไธญๅปบ็ซ‹้ ่จญ็š„ `server`๏ผŒๅ…ถ URL ๅฐฑๆ˜ฏ `root_path` ๆ‰€ๆไพ›็š„ๅ€ผใ€‚ + +## ๅ…ถไป– servers { #additional-servers } + +/// warning + +้€™ๆ˜ฏๆ›ด้€ฒ้šŽ็š„็”จๆณ•ใ€‚ไฝ ๅฏไปฅ้ธๆ“‡็•ฅ้Žใ€‚ + +/// + +้ ่จญๆƒ…ๆณไธ‹๏ผŒFastAPI ๆœƒๅœจ OpenAPI ๆจกๅผไธญๅปบ็ซ‹ไธ€ๅ€‹ `server`๏ผŒๅ…ถ URL ็‚บ `root_path`ใ€‚ + +ไฝ†ไฝ ไนŸๅฏไปฅๅฆๅค–ๆไพ›ๅ…ถไป– `servers`๏ผŒไพ‹ๅฆ‚ไฝ ๆƒณ่ฆ็”จใ€ŒๅŒไธ€ไปฝใ€ๆ–‡ไปถ UI ไพ†่ˆ‡ๆธฌ่ฉฆ๏ผˆstaging๏ผ‰่ˆ‡ๆญฃๅผ๏ผˆproduction๏ผ‰็’ฐๅขƒไบ’ๅ‹•ใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‚ณๅ…ฅ่‡ช่จ‚็š„ `servers` ๆธ…ๅ–ฎ๏ผŒไธ”ๅŒๆ™‚ๅญ˜ๅœจ `root_path`๏ผˆๅ› ็‚บไฝ ็š„ API ไฝๆ–ผไปฃ็†ไน‹ๅพŒ๏ผ‰๏ผŒFastAPI ๆœƒๅœจๆธ…ๅ–ฎ้–‹้ ญๆ’ๅ…ฅไธ€ๅ€‹ `server`๏ผŒๅ…ถ URL ็‚บ่ฉฒ `root_path`ใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +ๅฐ‡ๆœƒ็”ข็”Ÿๅฆ‚ไธ‹็š„ OpenAPI ๆจกๅผ๏ผš + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // ๅ…ถไป–ๅ…งๅฎน + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // ๅ…ถไป–ๅ…งๅฎน + } +} +``` + +/// tip + +ๆณจๆ„่‡ชๅ‹•็”ข็”Ÿ็š„ server๏ผŒๅ…ถ `url` ๅ€ผ็‚บ `/api/v1`๏ผŒๅ–่‡ช `root_path`ใ€‚ + +/// + +ๅœจไฝๆ–ผ http://127.0.0.1:9999/api/v1/docs ็š„ๆ–‡ไปถ UI ไธญ็œ‹่ตทไพ†ๆœƒๅƒ้€™ๆจฃ๏ผš + + + +/// tip + +ๆ–‡ไปถ UI ๆœƒ่ˆ‡ไฝ ๆ‰€้ธๆ“‡็š„ server ไบ’ๅ‹•ใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +OpenAPI ่ฆๆ ผไธญ็š„ `servers` ๅฑฌๆ€งๆ˜ฏๅฏ้ธ็š„ใ€‚ + +ๅฆ‚ๆžœไฝ ๆฒ’ๆœ‰ๆŒ‡ๅฎš `servers` ๅƒๆ•ธ๏ผŒไธ” `root_path` ็ญ‰ๆ–ผ `/`๏ผŒๅ‰‡ๅœจ็”ข็”Ÿ็š„ OpenAPI ๆจกๅผไธญๆœƒๅฎŒๅ…จ็œ็•ฅ `servers` ๅฑฌๆ€ง๏ผˆ้ ่จญ่กŒ็‚บ๏ผ‰๏ผŒ้€™็ญ‰ๅŒๆ–ผๅชๆœ‰ไธ€ๅ€‹ `url` ๅ€ผ็‚บ `/` ็š„ serverใ€‚ + +/// + +### ๅœ็”จๅพž `root_path` ่‡ชๅ‹•ๅŠ ๅ…ฅ็š„ server { #disable-automatic-server-from-root-path } + +ๅฆ‚ๆžœไฝ ไธๅธŒๆœ› FastAPI ไฝฟ็”จ `root_path` ่‡ชๅ‹•ๅŠ ๅ…ฅไธ€ๅ€‹ server๏ผŒไฝ ๅฏไปฅไฝฟ็”จๅƒๆ•ธ `root_path_in_servers=False`๏ผš + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +้€™ๆจฃๅฎƒๅฐฑไธๆœƒ่ขซๅŒ…ๅซๅœจ OpenAPI ๆจกๅผไธญใ€‚ + +## ๆŽ›่ผ‰ๅญๆ‡‰็”จ { #mounting-a-sub-application } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅœจๅŒๆ™‚ไฝฟ็”จๅ…ทๆœ‰ `root_path` ็š„ไปฃ็†ๆ™‚๏ผŒๆŽ›่ผ‰ไธ€ๅ€‹ๅญๆ‡‰็”จ๏ผˆๅฆ‚๏ผป[ๅญๆ‡‰็”จ - ๆŽ›่ผ‰](sub-applications.md){.internal-link target=_blank}๏ผฝไธญๆ‰€่ฟฐ๏ผ‰๏ผŒๅฏไปฅๅƒๅนณๅธธไธ€ๆจฃๆ“ไฝœ๏ผŒๆญฃๅฆ‚ไฝ ๆ‰€้ ๆœŸ็š„้‚ฃๆจฃใ€‚ + +FastAPI ๆœƒๅœจๅ…ง้ƒจๆ™บๆ…งๅœฐไฝฟ็”จ `root_path`๏ผŒๆ‰€ไปฅไธ€ๅˆ‡้ƒฝ่ƒฝ้ †ๅˆฉ้‹ไฝœใ€‚โœจ diff --git a/docs/zh-hant/docs/advanced/custom-response.md b/docs/zh-hant/docs/advanced/custom-response.md new file mode 100644 index 0000000000..b723aa82f6 --- /dev/null +++ b/docs/zh-hant/docs/advanced/custom-response.md @@ -0,0 +1,312 @@ +# ่‡ช่จ‚ๅ›žๆ‡‰โ€”โ€”HTMLใ€ไธฒๆตใ€ๆช”ๆกˆ่ˆ‡ๅ…ถไป– { #custom-response-html-stream-file-others } + +้ ่จญๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒไฝฟ็”จ `JSONResponse` ๅ‚ณๅ›žๅ›žๆ‡‰ใ€‚ + +ไฝ ๅฏไปฅๅƒๅœจ[็›ดๆŽฅๅ›žๅ‚ณ Response](response-directly.md){.internal-link target=_blank} ไธญๆ‰€็คบ๏ผŒ็›ดๆŽฅๅ›žๅ‚ณไธ€ๅ€‹ `Response` ไพ†่ฆ†ๅฏซๅฎƒใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็›ดๆŽฅๅ›žๅ‚ณไธ€ๅ€‹ `Response`๏ผˆๆˆ–ๅ…ถๅญ้กžๅˆฅ๏ผŒๅฆ‚ `JSONResponse`๏ผ‰๏ผŒ่ณ‡ๆ–™ๅฐ‡ไธๆœƒ่ขซ่‡ชๅ‹•่ฝ‰ๆ›๏ผˆๅณไฝฟไฝ ๅฎฃๅ‘Šไบ† `response_model`๏ผ‰๏ผŒ่€Œไธ”ๆ–‡ไปถไนŸไธๆœƒ่‡ชๅ‹•็”ข็”Ÿ๏ผˆไพ‹ๅฆ‚๏ผŒๅœจ็”ข็”Ÿ็š„ OpenAPI ไธญๅŒ…ๅซ HTTP ๆจ™้ ญ `Content-Type` ็š„็‰นๅฎšใ€Œmedia typeใ€๏ผ‰ใ€‚ + +ไฝ ไนŸๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญไฝฟ็”จ `response_class` ๅƒๆ•ธ๏ผŒๅฎฃๅ‘Š่ฆไฝฟ็”จ็š„ `Response`๏ผˆไพ‹ๅฆ‚ไปปๆ„ `Response` ๅญ้กžๅˆฅ๏ผ‰ใ€‚ + +ไฝ ๅพžใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ›žๅ‚ณ็š„ๅ…งๅฎน๏ผŒๆœƒ่ขซๆ”พ้€ฒ่ฉฒ `Response` ไธญใ€‚ + +่‹ฅ่ฉฒ `Response` ็š„ media type ๆ˜ฏ JSON๏ผˆ`application/json`๏ผ‰๏ผŒๅƒ `JSONResponse` ่ˆ‡ `UJSONResponse`๏ผŒๅ‰‡ไฝ ๅ›žๅ‚ณ็š„่ณ‡ๆ–™ๆœƒ่‡ชๅ‹•ไปฅไฝ ๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญๅฎฃๅ‘Š็š„ Pydantic `response_model` ้€ฒ่กŒ่ฝ‰ๆ›๏ผˆ่ˆ‡้Žๆฟพ๏ผ‰ใ€‚ + +/// note + +่‹ฅไฝ ไฝฟ็”จ็š„ๅ›žๆ‡‰้กžๅˆฅๆฒ’ๆœ‰ media type๏ผŒFastAPI ๆœƒๅ‡่จญไฝ ็š„ๅ›žๆ‡‰ๆฒ’ๆœ‰ๅ…งๅฎน๏ผŒๅ› ๆญคไธๆœƒๅœจ็”ข็”Ÿ็š„ OpenAPI ๆ–‡ไปถไธญ่จ˜้Œ„ๅ›žๆ‡‰ๆ ผๅผใ€‚ + +/// + +## ไฝฟ็”จ `ORJSONResponse` { #use-orjsonresponse } + +ไพ‹ๅฆ‚๏ผŒ่‹ฅไฝ ๅœจ่ฟฝๆฑ‚ๆ•ˆ่ƒฝ๏ผŒไฝ ๅฏไปฅๅฎ‰่ฃไธฆไฝฟ็”จ `orjson`๏ผŒไธฆๅฐ‡ๅ›žๆ‡‰่จญ็‚บ `ORJSONResponse`ใ€‚ + +ๅŒฏๅ…ฅไฝ ๆƒณไฝฟ็”จ็š„ `Response` ้กžๅˆฅ๏ผˆๅญ้กž๏ผ‰๏ผŒไธฆๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญๅฎฃๅ‘Šๅฎƒใ€‚ + +ๅฐๆ–ผๅคงๅž‹ๅ›žๆ‡‰๏ผŒ็›ดๆŽฅๅ›žๅ‚ณ `Response` ๆœƒๆฏ”ๅ›žๅ‚ณ `dict` ๅฟซๅพ—ๅคšใ€‚ + +้€™ๆ˜ฏๅ› ็‚บ้ ่จญๆƒ…ๆณไธ‹๏ผŒFastAPI ๆœƒๆชขๆŸฅๆฏๅ€‹้ …็›ฎไธฆ็ขบ่ชๅฎƒ่ƒฝ่ขซๅบๅˆ—ๅŒ–็‚บ JSON๏ผŒไฝฟ็”จ่ˆ‡ๆ•™ๅญธไธญ่ชชๆ˜Ž็š„็›ธๅŒ[JSON ็›ธๅฎน็ทจ็ขผๅ™จ](../tutorial/encoder.md){.internal-link target=_blank}ใ€‚้€™ไฝฟไฝ ๅฏไปฅๅ›žๅ‚ณใ€Œไปปๆ„็‰ฉไปถใ€๏ผŒไพ‹ๅฆ‚่ณ‡ๆ–™ๅบซๆจกๅž‹ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็ขบๅฎšไฝ ๅ›žๅ‚ณ็š„ๅ…งๅฎนใ€Œๅฏไปฅ็”จ JSON ๅบๅˆ—ๅŒ–ใ€๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅฐ‡ๅฎƒๅ‚ณ็ตฆๅ›žๆ‡‰้กžๅˆฅ๏ผŒ้ฟๅ… FastAPI ๅœจๆŠŠไฝ ็š„ๅ›žๅ‚ณๅ…งๅฎนไบค็ตฆๅ›žๆ‡‰้กžๅˆฅไน‹ๅ‰๏ผŒๅ…ˆ็ถ“้Ž `jsonable_encoder` ๆ‰€ๅธถไพ†็š„้กๅค–้–‹้Šทใ€‚ + +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} + +/// info + +ๅƒๆ•ธ `response_class` ไนŸๆœƒ็”จไพ†ๅฎš็พฉๅ›žๆ‡‰็š„ใ€Œmedia typeใ€ใ€‚ + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒHTTP ๆจ™้ ญ `Content-Type` ๆœƒ่ขซ่จญ็‚บ `application/json`ใ€‚ + +่€Œไธ”ๅฎƒๆœƒไปฅๆญคๅฝขๅผ่ขซ่จ˜้Œ„ๅˆฐ OpenAPI ไธญใ€‚ + +/// + +/// tip + +`ORJSONResponse` ๅชๅœจ FastAPI ไธญๅฏ็”จ๏ผŒๅœจ Starlette ไธญไธๅฏ็”จใ€‚ + +/// + +## HTML ๅ›žๆ‡‰ { #html-response } + +่ฆ็›ดๆŽฅๅพž **FastAPI** ๅ›žๅ‚ณ HTML๏ผŒไฝฟ็”จ `HTMLResponse`ใ€‚ + +- ๅŒฏๅ…ฅ `HTMLResponse`ใ€‚ +- ๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญ๏ผŒๅฐ‡ `HTMLResponse` ๅ‚ณ็ตฆ `response_class` ๅƒๆ•ธใ€‚ + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// info + +ๅƒๆ•ธ `response_class` ไนŸๆœƒ็”จไพ†ๅฎš็พฉๅ›žๆ‡‰็š„ใ€Œmedia typeใ€ใ€‚ + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒHTTP ๆจ™้ ญ `Content-Type` ๆœƒ่ขซ่จญ็‚บ `text/html`ใ€‚ + +่€Œไธ”ๅฎƒๆœƒไปฅๆญคๅฝขๅผ่ขซ่จ˜้Œ„ๅˆฐ OpenAPI ไธญใ€‚ + +/// + +### ๅ›žๅ‚ณ `Response` { #return-a-response } + +ๅฆ‚[็›ดๆŽฅๅ›žๅ‚ณ Response](response-directly.md){.internal-link target=_blank} ๆ‰€็คบ๏ผŒไฝ ไนŸๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธญ็›ดๆŽฅๅ›žๅ‚ณไปฅ่ฆ†ๅฏซๅ›žๆ‡‰ใ€‚ + +ไธŠ้ข็š„็›ธๅŒ็ฏ„ไพ‹๏ผŒๅ›žๅ‚ณ `HTMLResponse`๏ผŒๅฏไปฅๅƒ้€™ๆจฃ๏ผš + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning + +็”ฑไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็›ดๆŽฅๅ›žๅ‚ณ็š„ `Response` ไธๆœƒ่ขซ่จ˜้Œ„้€ฒ OpenAPI๏ผˆไพ‹ๅฆ‚ไธๆœƒ่จ˜้Œ„ `Content-Type`๏ผ‰๏ผŒไนŸไธๆœƒๅ‡บ็พๅœจ่‡ชๅ‹•็”ข็”Ÿ็š„ไบ’ๅ‹•ๅผๆ–‡ไปถไธญใ€‚ + +/// + +/// info + +็•ถ็„ถ๏ผŒๅฏฆ้š›็š„ `Content-Type` ๆจ™้ ญใ€็‹€ๆ…‹็ขผ็ญ‰๏ผŒๆœƒไพ†่‡ชไฝ ๅ›žๅ‚ณ็š„ `Response` ็‰ฉไปถใ€‚ + +/// + +### ๅœจ OpenAPI ไธญๆ–‡ไปถๅŒ–ไธฆ่ฆ†ๅฏซ `Response` { #document-in-openapi-and-override-response } + +ๅฆ‚ๆžœไฝ ๆƒณๅœจๅ‡ฝๅผๅ…ง่ฆ†ๅฏซๅ›žๆ‡‰๏ผŒๅŒๆ™‚ๅˆ่ฆๅœจ OpenAPI ไธญ่จ˜้Œ„ใ€Œmedia typeใ€๏ผŒไฝ ๅฏไปฅๅŒๆ™‚ไฝฟ็”จ `response_class` ๅƒๆ•ธไธฆๅ›žๅ‚ณไธ€ๅ€‹ `Response` ็‰ฉไปถใ€‚ + +ๆญคๆ™‚๏ผŒ`response_class` ๅชๆœƒ็”จๆ–ผ่จ˜้Œ„่ฉฒ OpenAPIใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผŒ่€Œไฝ ๅ›žๅ‚ณ็š„ `Response` ๅฐ‡ๆœƒๅฆ‚ๅฏฆไฝฟ็”จใ€‚ + +#### ็›ดๆŽฅๅ›žๅ‚ณ `HTMLResponse` { #return-an-htmlresponse-directly } + +ไพ‹ๅฆ‚๏ผŒๅฏ่ƒฝๆœƒๅƒ้€™ๆจฃ๏ผš + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅ‡ฝๅผ `generate_html_response()` ๅทฒ็ถ“็”ข็”Ÿไธฆๅ›žๅ‚ณไบ†ไธ€ๅ€‹ `Response`๏ผŒ่€Œไธๆ˜ฏๆŠŠ HTML ็•ถไฝœ `str` ๅ›žๅ‚ณใ€‚ + +้€้Žๅ›žๅ‚ณ `generate_html_response()` ็š„็ตๆžœ๏ผŒไฝ ๅ…ถๅฏฆๅทฒ็ถ“ๅ›žๅ‚ณไบ†ไธ€ๅ€‹ `Response`๏ผŒ้€™ๆœƒ่ฆ†ๅฏซ **FastAPI** ็š„้ ่จญ่กŒ็‚บใ€‚ + +ไฝ†ๅ› ็‚บไฝ ๅŒๆ™‚ไนŸๅœจ `response_class` ไธญๅ‚ณๅ…ฅไบ† `HTMLResponse`๏ผŒ**FastAPI** ไพฟ่ƒฝๅœจ OpenAPI ่ˆ‡ไบ’ๅ‹•ๅผๆ–‡ไปถไธญ๏ผŒๅฐ‡ๅ…ถไปฅ `text/html` ็š„ HTML ๅฝขๅผ่จ˜้Œ„๏ผš + + + +## ๅฏ็”จ็š„ๅ›žๆ‡‰ { #available-responses } + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅˆฅใ€‚ + +่จ˜ๅพ—ไฝ ๅฏไปฅ็”จ `Response` ๅ›žๅ‚ณๅ…ถไป–ไปปไฝ•ๆฑ่ฅฟ๏ผŒ็”š่‡ณๅปบ็ซ‹่‡ช่จ‚็š„ๅญ้กžๅˆฅใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import HTMLResponse`ใ€‚ + +**FastAPI** ๅฐ‡ `starlette.responses` ไปฅ `fastapi.responses` ๆไพ›็ตฆไฝ ๏ผˆ้–‹็™ผ่€…๏ผ‰ๅš็‚บๆ–นไพฟไน‹็”จใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +### `Response` { #response } + +ไธป่ฆ็š„ `Response` ้กžๅˆฅ๏ผŒๅ…ถไป–ๅ›žๆ‡‰็š†็นผๆ‰ฟ่‡ชๅฎƒใ€‚ + +ไฝ ไนŸๅฏไปฅ็›ดๆŽฅๅ›žๅ‚ณๅฎƒใ€‚ + +ๅฎƒๆŽฅๅ—ไปฅไธ‹ๅƒๆ•ธ๏ผš + +- `content` - `str` ๆˆ– `bytes`ใ€‚ +- `status_code` - `int` ้กžๅž‹็š„ HTTP ็‹€ๆ…‹็ขผใ€‚ +- `headers` - ็”ฑๅญ—ไธฒ็ต„ๆˆ็š„ `dict`ใ€‚ +- `media_type` - ๆ่ฟฐ media type ็š„ `str`ใ€‚ไพ‹ๅฆ‚ `"text/html"`ใ€‚ + +FastAPI๏ผˆๅฏฆ้š›ไธŠๆ˜ฏ Starlette๏ผ‰ๆœƒ่‡ชๅ‹•ๅŒ…ๅซ Content-Length ๆจ™้ ญใ€‚ไนŸๆœƒๆ นๆ“š `media_type`๏ผˆไธฆ็‚บๆ–‡ๅญ—ๅž‹ๅˆฅ้™„ๅŠ  charset๏ผ‰ๅŒ…ๅซ Content-Type ๆจ™้ ญใ€‚ + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +ๆŽฅๆ”ถๆ–‡ๅญ—ๆˆ–ไฝๅ…ƒ็ต„ไธฆๅ›žๅ‚ณ HTML ๅ›žๆ‡‰๏ผŒๅฆ‚ไธŠๆ‰€่ฟฐใ€‚ + +### `PlainTextResponse` { #plaintextresponse } + +ๆŽฅๆ”ถๆ–‡ๅญ—ๆˆ–ไฝๅ…ƒ็ต„ไธฆๅ›žๅ‚ณ็ด”ๆ–‡ๅญ—ๅ›žๆ‡‰ใ€‚ + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +ๆŽฅๆ”ถ่ณ‡ๆ–™ไธฆๅ›žๅ‚ณ `application/json` ็ทจ็ขผ็š„ๅ›žๆ‡‰ใ€‚ + +้€™ๆ˜ฏ **FastAPI** ็š„้ ่จญๅ›žๆ‡‰๏ผŒๅฆ‚ไธŠๆ‰€่ฟฐใ€‚ + +### `ORJSONResponse` { #orjsonresponse } + +ไฝฟ็”จ `orjson` ็š„ๅฟซ้€Ÿๆ›ฟไปฃ JSON ๅ›žๆ‡‰๏ผŒๅฆ‚ไธŠๆ‰€่ฟฐใ€‚ + +/// info + +้€™้œ€่ฆๅฎ‰่ฃ `orjson`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install orjson`ใ€‚ + +/// + +### `UJSONResponse` { #ujsonresponse } + +ไฝฟ็”จ `ujson` ็š„ๆ›ฟไปฃ JSON ๅ›žๆ‡‰ใ€‚ + +/// info + +้€™้œ€่ฆๅฎ‰่ฃ `ujson`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install ujson`ใ€‚ + +/// + +/// warning + +`ujson` ๅœจ่™•็†ๆŸไบ›้‚Š็•Œๆƒ…ๆณๆ™‚๏ผŒๆฒ’้‚ฃ้บผๅšด่ฌน๏ผŒ่ผƒ Python ๅ…งๅปบๅฏฆไฝœๆ›ดใ€Œ้šจๆ„ใ€ใ€‚ + +/// + +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} + +/// tip + +`ORJSONResponse` ๅฏ่ƒฝๆ˜ฏๆ›ดๅฟซ็š„ๆ›ฟไปฃๆ–นๆกˆใ€‚ + +/// + +### `RedirectResponse` { #redirectresponse } + +ๅ›žๅ‚ณไธ€ๅ€‹ HTTP ้‡ๆ–ฐๅฐŽๅ‘ใ€‚้ ่จญไฝฟ็”จ 307 ็‹€ๆ…‹็ขผ๏ผˆTemporary Redirect๏ผ‰ใ€‚ + +ไฝ ๅฏไปฅ็›ดๆŽฅๅ›žๅ‚ณ `RedirectResponse`๏ผš + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +ๆˆ–่€…ไฝ ๅฏไปฅๅœจ `response_class` ๅƒๆ•ธไธญไฝฟ็”จๅฎƒ๏ผš + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +่‹ฅ้€™้บผๅš๏ผŒไฝ ๅฐฑๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญ็›ดๆŽฅๅ›žๅ‚ณ URLใ€‚ + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒๆ‰€ไฝฟ็”จ็š„ `status_code` ๆœƒๆ˜ฏ `RedirectResponse` ็š„้ ่จญๅ€ผ `307`ใ€‚ + +--- + +ไฝ ไนŸๅฏไปฅๅŒๆ™‚ๆญ้… `status_code` ่ˆ‡ `response_class` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +ๆŽฅๆ”ถไธ€ๅ€‹ async ็”ข็”Ÿๅ™จๆˆ–ไธ€่ˆฌ็š„็”ข็”Ÿๅ™จ๏ผ็–Šไปฃๅ™จ๏ผŒไธฆไปฅไธฒๆตๆ–นๅผๅ‚ณ้€ๅ›žๆ‡‰ๆœฌๆ–‡ใ€‚ + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} + +#### ๅฐใ€Œ้กžๆช”ๆกˆ็‰ฉไปถใ€ไฝฟ็”จ `StreamingResponse` { #using-streamingresponse-with-file-like-objects } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹้กžๆช”ๆกˆ๏ผˆfile-like๏ผ‰็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ `open()` ๅ›žๅ‚ณ็š„็‰ฉไปถ๏ผ‰๏ผŒไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹็”ข็”Ÿๅ™จๅ‡ฝๅผไพ†็–Šไปฃ่ฉฒ้กžๆช”ๆกˆ็‰ฉไปถใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ไธๅฟ…ๅ…ˆๆŠŠๅฎƒๅ…จ้ƒจ่ฎ€้€ฒ่จ˜ๆ†ถ้ซ”๏ผŒๅฐฑ่ƒฝๅฐ‡้‚ฃๅ€‹็”ข็”Ÿๅ™จๅ‡ฝๅผๅ‚ณ็ตฆ `StreamingResponse` ไธฆๅ›žๅ‚ณใ€‚ + +้€™ไนŸๅŒ…ๅซ่จฑๅคš็”จๆ–ผ้›ฒ็ซฏๅ„ฒๅญ˜ใ€ๅฝฑๅƒ๏ผๅฝฑ้Ÿณ่™•็†็ญ‰็š„ๅ‡ฝๅผๅบซใ€‚ + +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} + +1. ้€™ๆ˜ฏ็”ข็”Ÿๅ™จๅ‡ฝๅผใ€‚ๅ› ็‚บๅฎƒๅ…งๅซ `yield` ้™ณ่ฟฐๅผ๏ผŒๆ‰€ไปฅๆ˜ฏใ€Œ็”ข็”Ÿๅ™จๅ‡ฝๅผใ€ใ€‚ +2. ้€้Ž `with` ๅ€ๅกŠ๏ผŒๆˆ‘ๅ€‘็ขบไฟๅœจ็”ข็”Ÿๅ™จๅ‡ฝๅผ็ตๆŸๅพŒ้—œ้–‰้กžๆช”ๆกˆ็‰ฉไปถใ€‚ๅ› ๆญค๏ผŒๅœจๅฎŒๆˆๅ‚ณ้€ๅ›žๆ‡‰ๅพŒๅฐฑๆœƒ้—œ้–‰ใ€‚ +3. ้€™ๅ€‹ `yield from` ๅ‘Š่จดๅ‡ฝๅผๅŽป็–Šไปฃๅ็‚บ `file_like` ็š„ๆฑ่ฅฟใ€‚ๅฐๆ–ผๆฏๅ€‹่ขซ็–Šไปฃๅˆฐ็š„้ƒจๅˆ†๏ผŒๅฐฑๆŠŠ่ฉฒ้ƒจๅˆ†็•ถไฝœๆญค็”ข็”Ÿๅ™จๅ‡ฝๅผ๏ผˆ`iterfile`๏ผ‰็š„่ผธๅ‡บ้€ฒ่กŒ `yield`ใ€‚ + + ๅ› ๆญค๏ผŒ้€™ๆ˜ฏไธ€ๅ€‹ๆŠŠใ€Œ็”Ÿๆˆใ€ๅทฅไฝœๅœจๅ…ง้ƒจ่ฝ‰ไบค็ตฆๅ…ถไป–ๆฑ่ฅฟ็š„็”ข็”Ÿๅ™จๅ‡ฝๅผใ€‚ + + ้€้Ž้€™ๆจฃๅš๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๆŠŠๅฎƒๆ”พ้€ฒ `with` ๅ€ๅกŠ๏ผŒ่—‰ๆญค็ขบไฟๅœจๅฎŒๆˆๅพŒ้—œ้–‰้กžๆช”ๆกˆ็‰ฉไปถใ€‚ + +/// tip + +ๆณจๆ„๏ผŒ้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จ็š„ๆ˜ฏๆจ™ๆบ–็š„ `open()`๏ผŒๅฎƒไธๆ”ฏๆด `async` ่ˆ‡ `await`๏ผŒๅ› ๆญคๆˆ‘ๅ€‘็”จไธ€่ˆฌ็š„ `def` ไพ†ๅฎฃๅ‘Š่ทฏๅพ‘ๆ“ไฝœใ€‚ + +/// + +### `FileResponse` { #fileresponse } + +ไปฅ้žๅŒๆญฅไธฒๆตๆ–นๅผๅฐ‡ๆช”ๆกˆไฝœ็‚บๅ›žๆ‡‰ใ€‚ + +ๅฎƒๅœจๅˆๅง‹ๅŒ–ๆ™‚ๆ‰€้œ€็š„ๅƒๆ•ธ่ˆ‡ๅ…ถไป–ๅ›žๆ‡‰ๅž‹ๅˆฅไธๅŒ๏ผš + +- `path` - ่ฆไธฒๆต็š„ๆช”ๆกˆ่ทฏๅพ‘ใ€‚ +- `headers` - ่ฆๅŒ…ๅซ็š„่‡ช่จ‚ๆจ™้ ญ๏ผŒๅญ—ๅ…ธๅฝขๅผใ€‚ +- `media_type` - ๆ่ฟฐ media type ็š„ๅญ—ไธฒใ€‚่‹ฅๆœช่จญๅฎš๏ผŒๅฐ‡ๆ นๆ“šๆช”ๅๆˆ–่ทฏๅพ‘ๆŽจๆ–ท media typeใ€‚ +- `filename` - ่‹ฅ่จญๅฎš๏ผŒๆœƒๅŒ…ๅซๅœจๅ›žๆ‡‰็š„ `Content-Disposition` ไธญใ€‚ + +ๆช”ๆกˆๅ›žๆ‡‰ๆœƒๅŒ…ๅซ้ฉ็•ถ็š„ `Content-Length`ใ€`Last-Modified` ่ˆ‡ `ETag` ๆจ™้ ญใ€‚ + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `response_class` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญ็›ดๆŽฅๅ›žๅ‚ณๆช”ๆกˆ่ทฏๅพ‘ใ€‚ + +## ่‡ช่จ‚ๅ›žๆ‡‰้กžๅˆฅ { #custom-response-class } + +ไฝ ๅฏไปฅๅปบ็ซ‹่‡ชๅทฑ็š„่‡ช่จ‚ๅ›žๆ‡‰้กžๅˆฅ๏ผŒ็นผๆ‰ฟ่‡ช `Response` ไธฆๅŠ ไปฅไฝฟ็”จใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ่ฆไฝฟ็”จ `orjson`๏ผŒไฝ†ๆƒณๅฅ—็”จไธ€ไบ›ๆœชๅŒ…ๅซๅœจ `ORJSONResponse` ้กžๅˆฅไธญ็š„่‡ช่จ‚่จญๅฎšใ€‚ + +ๅ‡่จญไฝ ๆƒณๅ›žๅ‚ณ็ธฎๆŽ’ไธ”ๆ ผๅผๅŒ–็š„ JSON๏ผŒๅ› ๆญค่ฆไฝฟ็”จ orjson ้ธ้ … `orjson.OPT_INDENT_2`ใ€‚ + +ไฝ ๅฏไปฅๅปบ็ซ‹ `CustomORJSONResponse`ใ€‚ไฝ ไธป่ฆ้œ€่ฆๅš็š„ๆ˜ฏๅปบ็ซ‹ไธ€ๅ€‹ `Response.render(content)` ๆ–นๆณ•๏ผŒๅฐ‡ๅ…งๅฎนไปฅ `bytes` ๅ›žๅ‚ณ๏ผš + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +็พๅœจ๏ผŒไธๅ†ๆ˜ฏๅ›žๅ‚ณ๏ผš + +```json +{"message": "Hello World"} +``` + +โ€ฆโ€ฆ้€™ๅ€‹ๅ›žๆ‡‰ๆœƒๅ›žๅ‚ณ๏ผš + +```json +{ + "message": "Hello World" +} +``` + +็•ถ็„ถ๏ผŒไฝ ๅคงๆฆ‚่ƒฝๆ‰พๅˆฐๆฏ”ๆ ผๅผๅŒ– JSON ๆ›ดๅฅฝ็š„ๆ–นๅผไพ†ๅˆฉ็”จ้€™ๅ€‹่ƒฝๅŠ›ใ€‚๐Ÿ˜‰ + +## ้ ่จญๅ›žๆ‡‰้กžๅˆฅ { #default-response-class } + +ๅœจๅปบ็ซ‹ **FastAPI** ้กžๅˆฅๅฏฆไพ‹ๆˆ– `APIRouter` ๆ™‚๏ผŒไฝ ๅฏไปฅๆŒ‡ๅฎš้ ่จญ่ฆไฝฟ็”จๅ“ชๅ€‹ๅ›žๆ‡‰้กžๅˆฅใ€‚ + +็”จไพ†่จญๅฎš็š„ๆ˜ฏ `default_response_class` ๅƒๆ•ธใ€‚ + +ๅœจไธ‹้ข็š„ไพ‹ๅญไธญ๏ผŒ**FastAPI** ๆœƒๅœจๆ‰€ๆœ‰ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธญ้ ่จญไฝฟ็”จ `ORJSONResponse`๏ผŒ่€Œไธๆ˜ฏ `JSONResponse`ใ€‚ + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip + +ไฝ ไป็„ถๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธญๅƒไปฅๅ‰ไธ€ๆจฃ่ฆ†ๅฏซ `response_class`ใ€‚ + +/// + +## ๅ…ถไป–ๆ–‡ไปถๅŒ–้ธ้ … { #additional-documentation } + +ไฝ ไนŸๅฏไปฅๅœจ OpenAPI ไธญไฝฟ็”จ `responses` ๅฎฃๅ‘Š media type ่ˆ‡ๅ…ถไป–่จฑๅคš็ดฐ็ฏ€๏ผš[ๅœจ OpenAPI ไธญ็š„้กๅค–ๅ›žๆ‡‰](additional-responses.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/advanced/dataclasses.md b/docs/zh-hant/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..d586bd6844 --- /dev/null +++ b/docs/zh-hant/docs/advanced/dataclasses.md @@ -0,0 +1,87 @@ +# ไฝฟ็”จ Dataclasses { #using-dataclasses } + +FastAPI ๅปบ็ซ‹ๅœจ **Pydantic** ไน‹ไธŠ๏ผŒๆˆ‘ไน‹ๅ‰็คบ็ฏ„้Žๅฆ‚ไฝ•ไฝฟ็”จ Pydantic ๆจกๅž‹ไพ†ๅฎฃๅ‘Š่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ใ€‚ + +ไฝ† FastAPI ไนŸๅŒๆจฃๆ”ฏๆดไปฅ็›ธๅŒๆ–นๅผไฝฟ็”จ `dataclasses`๏ผš + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +้€™ไน‹ๆ‰€ไปฅๅฏ่กŒ๏ผŒ่ฆๆ„Ÿ่ฌ **Pydantic**๏ผŒๅ› ็‚บๅฎƒ ๅ…งๅปบๆ”ฏๆด `dataclasses`ใ€‚ + +ๆ‰€ไปฅ๏ผŒๅณไฝฟไธŠ้ข็š„็จ‹ๅผ็ขผๆฒ’ๆœ‰ๆ˜Ž็ขบไฝฟ็”จ Pydantic๏ผŒFastAPI ไปๆœƒไฝฟ็”จ Pydantic ๅฐ‡้‚ฃไบ›ๆจ™ๆบ–็š„ dataclass ่ฝ‰ๆ›็‚บ Pydantic ็‰ˆๆœฌ็š„ dataclassใ€‚ + +่€Œไธ”็•ถ็„ถไธ€ๆจฃๆ”ฏๆด๏ผš + +- ่ณ‡ๆ–™้ฉ—่ญ‰ +- ่ณ‡ๆ–™ๅบๅˆ—ๅŒ– +- ่ณ‡ๆ–™ๆ–‡ไปถๅŒ–็ญ‰ + +ๅฎƒ็š„้‹ไฝœๆ–นๅผ่ˆ‡ Pydantic ๆจกๅž‹็›ธๅŒ๏ผ›ๅฏฆ้š›ไธŠ๏ผŒๅบ•ๅฑคๅฐฑๆ˜ฏ้€้Ž Pydantic ้”ๆˆ็š„ใ€‚ + +/// info + +่ซ‹่จ˜ๅพ—๏ผŒdataclass ็„กๆณ•ๅšๅˆฐ Pydantic ๆจกๅž‹่ƒฝๅš็š„ไธ€ๅˆ‡ใ€‚ + +ๆ‰€ไปฅไฝ ๅฏ่ƒฝไป็„ถ้œ€่ฆไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ๆ‰‹้‚Šๅ‰›ๅฅฝๆœ‰ไธ€ๅ † dataclass๏ผŒ้€™ๆ˜ฏๅ€‹ไธ้Œฏ็š„ๅฐๆŠ€ๅทง๏ผŒๅฏไปฅ็”จไพ†็”จ FastAPI ้ฉ…ๅ‹•ไธ€ๅ€‹ Web APIใ€‚๐Ÿค“ + +/// + +## ๅœจ `response_model` ไธญไฝฟ็”จ Dataclasses { #dataclasses-in-response-model } + +ไฝ ไนŸๅฏไปฅๅœจ `response_model` ๅƒๆ•ธไธญไฝฟ็”จ `dataclasses`๏ผš + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +่ฉฒ dataclass ๆœƒ่‡ชๅ‹•่ฝ‰ๆ›็‚บ Pydantic ็š„ dataclassใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅ…ถ็ตๆง‹ๆ่ฟฐ๏ผˆschema๏ผ‰ๆœƒ้กฏ็คบๅœจ API ๆ–‡ไปถไป‹้ขไธญ๏ผš + + + +## ๅทข็‹€่ณ‡ๆ–™็ตๆง‹ไธญ็š„ Dataclasses { #dataclasses-in-nested-data-structures } + +ไฝ ไนŸๅฏไปฅๅฐ‡ `dataclasses` ่ˆ‡ๅ…ถไป–ๅž‹ๅˆฅ่จป่จ˜็ตๅˆ๏ผŒๅปบ็ซ‹ๅทข็‹€็š„่ณ‡ๆ–™็ตๆง‹ใ€‚ + +ๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝไป้œ€่ฆไฝฟ็”จ Pydantic ็‰ˆๆœฌ็š„ `dataclasses`ใ€‚ไพ‹ๅฆ‚๏ผŒ็•ถ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถๅ‡บ็พ้Œฏ่ชคๆ™‚ใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅๆŠŠๆจ™ๆบ–็š„ `dataclasses` ็›ดๆŽฅๆ›ๆˆ `pydantic.dataclasses`๏ผŒๅฎƒๆ˜ฏๅฏ็›ดๆŽฅๆ›ฟๆ›๏ผˆdrop-in replacement๏ผ‰็š„๏ผš + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. ๆˆ‘ๅ€‘ไป็„ถๅพžๆจ™ๆบ–็š„ `dataclasses` ๅŒฏๅ…ฅ `field`ใ€‚ +2. `pydantic.dataclasses` ๆ˜ฏ `dataclasses` ็š„ๅฏ็›ดๆŽฅๆ›ฟๆ›็‰ˆๆœฌใ€‚ +3. `Author` dataclass ๅ…งๅซไธ€ๅ€‹ `Item` dataclass ็š„ๆธ…ๅ–ฎใ€‚ +4. `Author` dataclass ่ขซ็”จไฝœ `response_model` ๅƒๆ•ธใ€‚ +5. ไฝ ๅฏไปฅๅฐ‡ๅ…ถไป–ๆจ™ๆบ–ๅž‹ๅˆฅ่จป่จ˜่ˆ‡ dataclass ไธ€่ตท็”จไฝœ่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ + + ๅœจๆญคไพ‹ไธญ๏ผŒๅฎƒๆ˜ฏ `Item` dataclass ็š„ๆธ…ๅ–ฎใ€‚ +6. ้€™่ฃกๆˆ‘ๅ€‘ๅ›žๅ‚ณไธ€ๅ€‹ๅญ—ๅ…ธ๏ผŒๅ…ถไธญ็š„ `items` ๆ˜ฏไธ€ๅ€‹ dataclass ๆธ…ๅ–ฎใ€‚ + + FastAPI ไป่ƒฝๅฐ‡่ณ‡ๆ–™ๅบๅˆ—ๅŒ–็‚บ JSONใ€‚ +7. ้€™่ฃก `response_model` ไฝฟ็”จ็š„ๆ˜ฏใ€Œ`Author` dataclass ็š„ๆธ…ๅ–ฎใ€้€™็จฎๅž‹ๅˆฅ่จป่จ˜ใ€‚ + + ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅๆŠŠ `dataclasses` ่ˆ‡ๆจ™ๆบ–ๅž‹ๅˆฅ่จป่จ˜็ต„ๅˆไฝฟ็”จใ€‚ +8. ๆณจๆ„้€™ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไฝฟ็”จ็š„ๆ˜ฏไธ€่ˆฌ็š„ `def` ่€Œ้ž `async def`ใ€‚ + + ไธ€ๅฆ‚ๅพ€ๅธธ๏ผŒๅœจ FastAPI ไธญไฝ ๅฏไปฅ่ฆ–้œ€่ฆๆทท็”จ `def` ่ˆ‡ `async def`ใ€‚ + + ๅฆ‚ๆžœ้œ€่ฆ่ค‡็ฟ’ไฝ•ๆ™‚็”จๅ“ชๅ€‹๏ผŒ่ซ‹ๅƒ่€ƒๆ–‡ไปถไธญ้—œๆ–ผ [`async` ่ˆ‡ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ็š„็ซ ็ฏ€ใ€ŒIn a hurry?ใ€ใ€‚ +9. ้€™ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ›žๅ‚ณ็š„ไธๆ˜ฏ dataclass๏ผˆ้›–็„ถไนŸๅฏไปฅ๏ผ‰๏ผŒ่€Œๆ˜ฏไธ€ๅ€‹ๅŒ…ๅซๅ…ง้ƒจ่ณ‡ๆ–™็š„ๅญ—ๅ…ธๆธ…ๅ–ฎใ€‚ + + FastAPI ๆœƒไฝฟ็”จ `response_model` ๅƒๆ•ธ๏ผˆๅ…ถไธญๅŒ…ๅซ dataclass๏ผ‰ไพ†่ฝ‰ๆ›ๅ›žๆ‡‰ใ€‚ + +ไฝ ๅฏไปฅๆŠŠ `dataclasses` ่ˆ‡ๅ…ถไป–ๅž‹ๅˆฅ่จป่จ˜ไปฅๅคš็จฎๆ–นๅผ็ต„ๅˆ๏ผŒๅฝขๆˆ่ค‡้›œ็š„่ณ‡ๆ–™็ตๆง‹ใ€‚ + +ๆŸฅ็œ‹ไธŠ้ข็จ‹ๅผ็ขผไธญ็š„่จป่งฃๆ็คบไปฅไบ†่งฃๆ›ดๅ…ท้ซ”็š„็ดฐ็ฏ€ใ€‚ + +## ๅปถไผธ้–ฑ่ฎ€ { #learn-more } + +ไฝ ไนŸๅฏไปฅๅฐ‡ `dataclasses` ่ˆ‡ๅ…ถไป– Pydantic ๆจกๅž‹็ตๅˆใ€ๅพžๅฎƒๅ€‘็นผๆ‰ฟใ€ๆŠŠๅฎƒๅ€‘ๅŒ…ๅซ้€ฒไฝ ็š„่‡ช่จ‚ๆจกๅž‹็ญ‰ใ€‚ + +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ซ‹ๅƒ่€ƒ Pydantic ้—œๆ–ผ dataclasses ็š„ๆ–‡ไปถใ€‚ + +## ็‰ˆๆœฌ { #version } + +่‡ช FastAPI ็‰ˆๆœฌ `0.67.0` ่ตทๅฏ็”จใ€‚๐Ÿ”– diff --git a/docs/zh-hant/docs/advanced/events.md b/docs/zh-hant/docs/advanced/events.md new file mode 100644 index 0000000000..e5c0afe48f --- /dev/null +++ b/docs/zh-hant/docs/advanced/events.md @@ -0,0 +1,165 @@ +# ็”Ÿๅ‘ฝ้€ฑๆœŸไบ‹ไปถ { #lifespan-events } + +ไฝ ๅฏไปฅๅฎš็พฉๅœจๆ‡‰็”จ็จ‹ๅผ**ๅ•Ÿๅ‹•**ไน‹ๅ‰่ฆๅŸท่กŒ็š„้‚่ผฏ๏ผˆ็จ‹ๅผ็ขผ๏ผ‰ใ€‚ไนŸๅฐฑๆ˜ฏ่ชช๏ผŒ้€™ๆฎต็จ‹ๅผ็ขผๆœƒๅœจๆ‡‰็”จ้–‹ๅง‹ๆŽฅๆ”ถ่ซ‹ๆฑ‚**ไน‹ๅ‰**ใ€**ๅชๅŸท่กŒไธ€ๆฌก**ใ€‚ + +ๅŒๆจฃๅœฐ๏ผŒไฝ ไนŸๅฏไปฅๅฎš็พฉๅœจๆ‡‰็”จ็จ‹ๅผ**้—œ้–‰**ๆ™‚่ฆๅŸท่กŒ็š„้‚่ผฏ๏ผˆ็จ‹ๅผ็ขผ๏ผ‰ใ€‚ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒ้€™ๆฎต็จ‹ๅผ็ขผๆœƒๅœจ่™•็†ไบ†**่จฑๅคš่ซ‹ๆฑ‚**ไน‹ๅพŒใ€**ๅชๅŸท่กŒไธ€ๆฌก**ใ€‚ + +ๅ› ็‚บ้€™ไบ›็จ‹ๅผ็ขผๅˆ†ๅˆฅๅœจๆ‡‰็”จ้–‹ๅง‹ๆŽฅๆ”ถ่ซ‹ๆฑ‚**ไน‹ๅ‰**่ˆ‡**ๅฎŒๆˆ**่™•็†่ซ‹ๆฑ‚ไน‹ๅพŒๅŸท่กŒ๏ผŒๆ‰€ไปฅๆถต่“‹ไบ†ๆ•ดๅ€‹ๆ‡‰็”จ็š„**็”Ÿๅ‘ฝ้€ฑๆœŸ**๏ผˆใ€Œlifespanใ€้€™ๅ€‹่ฉž็จๅพŒๆœƒๅพˆ้‡่ฆ ๐Ÿ˜‰๏ผ‰ใ€‚ + +้€™ๅฐๆ–ผ็‚บๆ•ดๅ€‹ๆ‡‰็”จ่จญๅฎš้œ€่ฆ**ๅ…ฑ็”จ**ๆ–ผๅคšๅ€‹่ซ‹ๆฑ‚็š„**่ณ‡ๆบ**๏ผŒไปฅๅŠๅœจไน‹ๅพŒ้€ฒ่กŒ**ๆธ…็†**๏ผŒ้žๅธธๆœ‰็”จใ€‚ๆฏ”ๅฆ‚่ณ‡ๆ–™ๅบซ้€ฃ็ทšๆฑ ใ€ๆˆ–่ผ‰ๅ…ฅไธ€ๅ€‹ๅ…ฑ็”จ็š„ๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹ใ€‚ + +## ไฝฟ็”จๆƒ…ๅขƒ { #use-case } + +ๅ…ˆๅพžไธ€ๅ€‹**ไฝฟ็”จๆƒ…ๅขƒ**้–‹ๅง‹๏ผŒ็„ถๅพŒ็œ‹็œ‹ๅฆ‚ไฝ•็”จ้€™ๅ€‹ๆฉŸๅˆถ่งฃๆฑบใ€‚ + +ๆƒณๅƒไฝ ๆœ‰ไธ€ไบ›่ฆ็”จไพ†่™•็†่ซ‹ๆฑ‚็š„**ๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹**ใ€‚๐Ÿค– + +ๅŒไธ€็ต„ๆจกๅž‹ๆœƒๅœจๅคšๅ€‹่ซ‹ๆฑ‚้–“ๅ…ฑ็”จ๏ผŒๆ‰€ไปฅไธๆ˜ฏๆฏๅ€‹่ซ‹ๆฑ‚ๆˆ–ๆฏๅ€‹ไฝฟ็”จ่€…ๅ„ๆœ‰ไธ€ๅ€‹ๆจกๅž‹ใ€‚ + +ๅ†ๆƒณๅƒไธ€ไธ‹๏ผŒ่ผ‰ๅ…ฅๆจกๅž‹**้œ€่ฆไธ€ๆฎตๆ™‚้–“**๏ผŒๅ› ็‚บๅฎƒๅฟ…้ ˆๅพž**็ฃ็ขŸ**่ฎ€ๅ–ๅคง้‡่ณ‡ๆ–™ใ€‚ๆ‰€ไปฅไฝ ไธๆƒณๅœจๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝๅšไธ€ๆฌกใ€‚ + +ไฝ ๅฏไปฅๅœจๆจก็ต„๏ผๆช”ๆกˆ็š„ๆœ€ไธŠๅฑค่ผ‰ๅ…ฅ๏ผŒไฝ†้€™ไนŸ่กจ็คบๅณไฝฟๅชๆ˜ฏ่ฆ่ท‘ไธ€ๅ€‹็ฐกๅ–ฎ็š„่‡ชๅ‹•ๅŒ–ๆธฌ่ฉฆ๏ผŒไนŸๆœƒๅŽป**่ผ‰ๅ…ฅๆจกๅž‹**๏ผŒๅฐŽ่‡ดๆธฌ่ฉฆ**่ฎŠๆ…ข**๏ผŒๅ› ็‚บๅฎƒๅพ—็ญ‰ๆจกๅž‹่ผ‰ๅ…ฅๅฎŒๆ‰่ƒฝๅŸท่กŒ่ˆ‡ๆจกๅž‹็„ก้—œ็š„็จ‹ๅผ็ขผ้ƒจๅˆ†ใ€‚ + +ๆˆ‘ๅ€‘่ฆ่งฃๆฑบ็š„ๆญฃๆ˜ฏ้€™ไปถไบ‹๏ผšๅœจ้–‹ๅง‹่™•็†่ซ‹ๆฑ‚ไน‹ๅ‰ๅ†่ผ‰ๅ…ฅๆจกๅž‹๏ผŒไฝ†ๅชๅœจๆ‡‰็”จ็จ‹ๅผๅณๅฐ‡้–‹ๅง‹ๆŽฅๆ”ถ่ซ‹ๆฑ‚ๆ™‚่ผ‰ๅ…ฅ๏ผŒ่€Œไธๆ˜ฏๅœจๅŒฏๅ…ฅ็จ‹ๅผ็ขผๆ™‚ๅฐฑ่ผ‰ๅ…ฅใ€‚ + +## ็”Ÿๅ‘ฝ้€ฑๆœŸ๏ผˆLifespan๏ผ‰ { #lifespan } + +ไฝ ๅฏไปฅไฝฟ็”จ `FastAPI` ๆ‡‰็”จ็š„ `lifespan` ๅƒๆ•ธ๏ผŒๆญ้…ใ€Œcontext managerใ€๏ผˆ็จๅพŒๆœƒ็คบ็ฏ„๏ผ‰๏ผŒไพ†ๅฎš็พฉ้€™ไบ› *startup* ่ˆ‡ *shutdown* ้‚่ผฏใ€‚ + +ๅ…ˆ็œ‹ไธ€ๅ€‹ไพ‹ๅญ๏ผŒๆŽฅ่‘—ๅ†ๆทฑๅ…ฅ่ชชๆ˜Žใ€‚ + +ๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹ๅธถๆœ‰ `yield` ็š„้žๅŒๆญฅๅ‡ฝๅผ `lifespan()`๏ผŒๅฆ‚ไธ‹๏ผš + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +้€™่ฃกๆˆ‘ๅ€‘้€้Žๅœจ `yield` ไน‹ๅ‰ๆŠŠ๏ผˆๅ‡็š„๏ผ‰ๆจกๅž‹ๅ‡ฝๅผๆ”พ้€ฒๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹็š„ๅญ—ๅ…ธไธญ๏ผŒไพ†ๆจกๆ“ฌๆ˜‚่ฒด็š„ *startup* ่ผ‰ๅ…ฅๆจกๅž‹ๆ“ไฝœใ€‚้€™ๆฎต็จ‹ๅผๆœƒๅœจๆ‡‰็”จ**้–‹ๅง‹ๆŽฅๆ”ถ่ซ‹ๆฑ‚ไน‹ๅ‰**ๅŸท่กŒ๏ผŒไนŸๅฐฑๆ˜ฏ *startup* ้šŽๆฎตใ€‚ + +ๆŽฅ่‘—๏ผŒๅœจ `yield` ไน‹ๅพŒ๏ผŒๆˆ‘ๅ€‘ๅธ่ผ‰ๆจกๅž‹ใ€‚้€™ๆฎต็จ‹ๅผๆœƒๅœจๆ‡‰็”จ**ๅฎŒๆˆ่™•็†่ซ‹ๆฑ‚ไน‹ๅพŒ**ใ€ไนŸๅฐฑๆ˜ฏ *shutdown* ๅ‰ๅŸท่กŒใ€‚้€™ๅฏไปฅ็”จไพ†้‡‹ๆ”พ่ณ‡ๆบ๏ผŒไพ‹ๅฆ‚่จ˜ๆ†ถ้ซ”ๆˆ– GPUใ€‚ + +/// tip + +`shutdown` ๆœƒๅœจไฝ **ๅœๆญข**ๆ‡‰็”จ็จ‹ๅผๆ™‚็™ผ็”Ÿใ€‚ + +ไนŸ่จฑไฝ ่ฆๅ•Ÿๅ‹•ๆ–ฐ็‰ˆๆœฌ๏ผŒๆˆ–ๅชๆ˜ฏไธๆƒณๅ†่ท‘ๅฎƒไบ†ใ€‚๐Ÿคท + +/// + +### Lifespan ๅ‡ฝๅผ { #lifespan-function } + +้ฆ–ๅ…ˆ่ฆๆณจๆ„็š„ๆ˜ฏ๏ผŒๆˆ‘ๅ€‘ๅฎš็พฉไบ†ไธ€ๅ€‹ๅธถๆœ‰ `yield` ็š„ async ๅ‡ฝๅผใ€‚้€™ๅ’Œๅธถๆœ‰ `yield` ็š„ไพ่ณด๏ผˆDependencies๏ผ‰้žๅธธ็›ธไผผใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +ๅ‡ฝๅผๅœจ `yield` ไน‹ๅ‰็š„้ƒจๅˆ†๏ผŒๆœƒๅœจๆ‡‰็”จๅ•Ÿๅ‹•ๅ‰ๅ…ˆๅŸท่กŒใ€‚ + +`yield` ไน‹ๅพŒ็š„้ƒจๅˆ†๏ผŒๆœƒๅœจๆ‡‰็”จ็ตๆŸๅพŒๅ†ๅŸท่กŒใ€‚ + +### ้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จ๏ผˆAsync Context Manager๏ผ‰ { #async-context-manager } + +ไฝ ๆœƒ็œ‹ๅˆฐ้€™ๅ€‹ๅ‡ฝๅผ่ขซ `@asynccontextmanager` ่ฃ้ฃพใ€‚ + +ๅฎƒๆœƒๆŠŠๅ‡ฝๅผ่ฝ‰ๆ›ๆˆๆ‰€่ฌ‚็š„ใ€Œ**้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จ๏ผˆasync context manager๏ผ‰**ใ€ใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Python ไธญ็š„**ๅ…งๅฎน็ฎก็†ๅ™จ๏ผˆcontext manager๏ผ‰**ๅฏไปฅ็”จๅœจ `with` ้™ณ่ฟฐๅผไธญ๏ผŒไพ‹ๅฆ‚ `open()` ๅฏไปฅไฝœ็‚บๅ…งๅฎน็ฎก็†ๅ™จไฝฟ็”จ๏ผš + +```Python +with open("file.txt") as file: + file.read() +``` + +ๅœจ่ผƒๆ–ฐ็š„ Python ็‰ˆๆœฌไธญ๏ผŒไนŸๆœ‰**้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จ**ใ€‚ไฝ ๅฏไปฅ็”จ `async with` ไพ†ไฝฟ็”จๅฎƒ๏ผš + +```Python +async with lifespan(app): + await do_stuff() +``` + +็•ถไฝ ๅƒไธŠ้ข้‚ฃๆจฃๅปบ็ซ‹ไธ€ๅ€‹ๅ…งๅฎน็ฎก็†ๅ™จๆˆ–้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จๆ™‚๏ผŒๅœจ้€ฒๅ…ฅ `with` ๅ€ๅกŠไน‹ๅ‰๏ผŒๆœƒๅ…ˆๅŸท่กŒ `yield` ไน‹ๅ‰็š„็จ‹ๅผ็ขผ๏ผ›้›ข้–‹ `with` ๅ€ๅกŠไน‹ๅพŒ๏ผŒๆœƒๅŸท่กŒ `yield` ไน‹ๅพŒ็š„็จ‹ๅผ็ขผใ€‚ + +ๅœจๆˆ‘ๅ€‘็š„็ฏ„ไพ‹ไธญ๏ผŒไธฆไธๆ˜ฏ็›ดๆŽฅ็”จๅฎƒ๏ผŒ่€Œๆ˜ฏๆŠŠๅฎƒๅ‚ณ็ตฆ FastAPI ไพ†ไฝฟ็”จใ€‚ + +`FastAPI` ๆ‡‰็”จ็š„ `lifespan` ๅƒๆ•ธ้œ€่ฆไธ€ๅ€‹**้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จ**๏ผŒๆ‰€ไปฅๆˆ‘ๅ€‘ๅฏไปฅๆŠŠๅ‰›ๅฏซๅฅฝ็š„ `lifespan` ้žๅŒๆญฅๅ…งๅฎน็ฎก็†ๅ™จๅ‚ณ็ตฆๅฎƒใ€‚ + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## ๆ›ฟไปฃไบ‹ไปถ๏ผˆๅทฒๆฃ„็”จ๏ผ‰ { #alternative-events-deprecated } + +/// warning + +็›ฎๅ‰ๅปบ่ญฐไฝฟ็”จไธŠ้ขๆ‰€่ฟฐ๏ผŒ้€้Ž `FastAPI` ๆ‡‰็”จ็š„ `lifespan` ๅƒๆ•ธไพ†่™•็† *startup* ่ˆ‡ *shutdown*ใ€‚ๅฆ‚ๆžœไฝ ๆไพ›ไบ† `lifespan` ๅƒๆ•ธ๏ผŒ`startup` ่ˆ‡ `shutdown` ไบ‹ไปถ่™•็†ๅ™จๅฐ‡ไธๆœƒ่ขซๅ‘ผๅซใ€‚่ฆๅ˜›ๅ…จ็”จ `lifespan`๏ผŒ่ฆๅ˜›ๅ…จ็”จไบ‹ไปถ๏ผŒไธ่ƒฝๅŒๆ™‚ๆทท็”จใ€‚ + +ไฝ ๅคงๆฆ‚ๅฏไปฅ็›ดๆŽฅ่ทณ้Ž้€™ไธ€็ฏ€ใ€‚ + +/// + +ไนŸๆœ‰ๅฆไธ€็จฎๆ–นๅผๅฏไปฅๅฎš็พฉๅœจ *startup* ่ˆ‡ *shutdown* ๆœŸ้–“่ฆๅŸท่กŒ็š„้‚่ผฏใ€‚ + +ไฝ ๅฏไปฅๅฎš็พฉไบ‹ไปถ่™•็†ๅ™จ๏ผˆๅ‡ฝๅผ๏ผ‰ไพ†ๅœจๆ‡‰็”จๅ•Ÿๅ‹•ๅ‰ๆˆ–้—œ้–‰ๆ™‚ๅŸท่กŒใ€‚ + +้€™ไบ›ๅ‡ฝๅผๅฏไปฅ็”จ `async def` ๆˆ–ไธ€่ˆฌ็š„ `def` ๅฎฃๅ‘Šใ€‚ + +### `startup` ไบ‹ไปถ { #startup-event } + +่ฆๅŠ ๅ…ฅไธ€ๅ€‹ๅœจๆ‡‰็”จๅ•Ÿๅ‹•ๅ‰ๅŸท่กŒ็š„ๅ‡ฝๅผ๏ผŒไฝฟ็”จไบ‹ไปถ `"startup"` ไพ†ๅฎฃๅ‘Š๏ผš + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ`startup` ไบ‹ไปถ่™•็†ๅ™จๅ‡ฝๅผๆœƒ็”จไธ€ไบ›ๅ€ผไพ†ๅˆๅง‹ๅŒ– items ็š„ใ€Œ่ณ‡ๆ–™ๅบซใ€๏ผˆๅ…ถๅฏฆๅฐฑๆ˜ฏๅ€‹ `dict`๏ผ‰ใ€‚ + +ไฝ ๅฏไปฅ่จปๅ†Šๅคšๅ€‹ไบ‹ไปถ่™•็†ๅ‡ฝๅผใ€‚ + +่€Œไธ”ๅœจๆ‰€ๆœ‰ `startup` ไบ‹ไปถ่™•็†ๅ™จ้ƒฝๅฎŒๆˆไน‹ๅ‰๏ผŒไฝ ็š„ๆ‡‰็”จไธๆœƒ้–‹ๅง‹ๆŽฅๆ”ถ่ซ‹ๆฑ‚ใ€‚ + +### `shutdown` ไบ‹ไปถ { #shutdown-event } + +่ฆๅŠ ๅ…ฅไธ€ๅ€‹ๅœจๆ‡‰็”จ้—œ้–‰ๆ™‚ๅŸท่กŒ็š„ๅ‡ฝๅผ๏ผŒไฝฟ็”จไบ‹ไปถ `"shutdown"` ไพ†ๅฎฃๅ‘Š๏ผš + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +ๅœจ้€™่ฃก๏ผŒ`shutdown` ไบ‹ไปถ่™•็†ๅ™จๅ‡ฝๅผๆœƒๆŠŠไธ€่กŒๆ–‡ๅญ— `"Application shutdown"` ๅฏซๅ…ฅๆช”ๆกˆ `log.txt`ใ€‚ + +/// info + +ๅœจ `open()` ๅ‡ฝๅผไธญ๏ผŒ`mode="a"` ่กจ็คบใ€Œappend๏ผˆ้™„ๅŠ ๏ผ‰ใ€๏ผ›ไนŸๅฐฑๆ˜ฏ่ชช๏ผŒ้€™่กŒๆ–‡ๅญ—ๆœƒๅŠ ๅœจๆช”ๆกˆ็พๆœ‰ๅ…งๅฎนไน‹ๅพŒ๏ผŒ่€Œไธๆœƒ่ฆ†ๅฏซๅ…ˆๅ‰็š„ๅ…งๅฎนใ€‚ + +/// + +/// tip + +ๆณจๆ„้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จ็š„ๆ˜ฏๆจ™ๆบ– Python ็š„ `open()` ๅ‡ฝๅผไพ†ๆ“ไฝœๆช”ๆกˆใ€‚ + +้€™ๆถ‰ๅŠ I/O๏ผˆ่ผธๅ…ฅ๏ผ่ผธๅ‡บ๏ผ‰๏ผŒไนŸๅฐฑๆ˜ฏ้œ€่ฆใ€Œ็ญ‰ๅพ…ใ€่ณ‡ๆ–™ๅฏซๅ…ฅ็ฃ็ขŸใ€‚ + +ไฝ† `open()` ไธฆไธไฝฟ็”จ `async` ่ˆ‡ `await`ใ€‚ + +ๆ‰€ไปฅๆˆ‘ๅ€‘็”จไธ€่ˆฌ็š„ `def` ไพ†ๅฎฃๅ‘Šไบ‹ไปถ่™•็†ๅ™จ๏ผŒ่€Œไธๆ˜ฏ `async def`ใ€‚ + +/// + +### ๅŒๆ™‚ไฝฟ็”จ `startup` ่ˆ‡ `shutdown` { #startup-and-shutdown-together } + +ไฝ ็š„ *startup* ่ˆ‡ *shutdown* ้‚่ผฏๅพˆๅฏ่ƒฝๆ˜ฏ็›ธ้—œ่ฏ็š„๏ผšไฝ ๅฏ่ƒฝๆœƒๅ…ˆๅ•Ÿๅ‹•ๆŸๅ€‹ๆฑ่ฅฟๅ†ๆŠŠๅฎƒ็ตๆŸใ€ๅ…ˆๅ–ๅพ—่ณ‡ๆบๅ†้‡‹ๆ”พๅฎƒ๏ผŒ็ญ‰็ญ‰ใ€‚ + +ๅฆ‚ๆžœๆŠŠๅฎƒๅ€‘ๆ‹†ๆˆๅ…ฉๅ€‹ๅฝผๆญคไธๅ…ฑไบซ้‚่ผฏๆˆ–่ฎŠๆ•ธ็š„็จ็ซ‹ๅ‡ฝๅผ๏ผŒๆœƒๆฏ”่ผƒ้บป็…ฉ๏ผŒไฝ ๅพ—ๆŠŠๅ€ผๅญ˜ๅœจๅ…จๅŸŸ่ฎŠๆ•ธๆˆ–็”จๅ…ถไป–ๆŠ€ๅทงใ€‚ + +ๅ› ๆญค๏ผŒ็พๅœจๅปบ่ญฐๆ”น็”จไธŠ้ขไป‹็ดน็š„ `lifespan`ใ€‚ + +## ๆŠ€่ก“็ดฐ็ฏ€ { #technical-details } + +็ตฆๆœ‰่ˆˆ่ถฃ้‘ฝ็ ”็š„ๅŒๅฅฝไธ€้ปžๆŠ€่ก“็ดฐ็ฏ€ใ€‚๐Ÿค“ + +ๅœจๅบ•ๅฑค็š„ ASGI ๆŠ€่ก“่ฆ็ฏ„ไธญ๏ผŒ้€™ๅฑฌๆ–ผ Lifespan Protocol ็š„ไธ€้ƒจๅˆ†๏ผŒไธฆๅฎš็พฉไบ† `startup` ่ˆ‡ `shutdown` ๅ…ฉ็จฎไบ‹ไปถใ€‚ + +/// info + +ไฝ ๅฏไปฅๅœจ Starlette ็š„ Lifespan ๆ–‡ไปถ ่ฎ€ๅˆฐๆ›ดๅคš้—œๆ–ผ Starlette `lifespan` ่™•็†ๅ™จ็š„่ณ‡่จŠใ€‚ + +ไนŸๅŒ…ๅซๅฆ‚ไฝ•่™•็†ๅฏๅœจ็จ‹ๅผๅ…ถไป–ๅ€ๅŸŸไฝฟ็”จ็š„ lifespan ็‹€ๆ…‹ใ€‚ + +/// + +## ๅญๆ‡‰็”จ็จ‹ๅผ { #sub-applications } + +๐Ÿšจ ่ซ‹่จ˜ไฝ๏ผŒ้€™ไบ›็”Ÿๅ‘ฝ้€ฑๆœŸไบ‹ไปถ๏ผˆstartup ่ˆ‡ shutdown๏ผ‰ๅชๆœƒๅœจไธปๆ‡‰็”จ็จ‹ๅผไธŠๅŸท่กŒ๏ผŒไธๆœƒๅœจ[ๅญๆ‡‰็”จ็จ‹ๅผ - ๆŽ›่ผ‰](sub-applications.md){.internal-link target=_blank}ไธŠๅŸท่กŒใ€‚ diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..8d374566cd --- /dev/null +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# ็”ข็”Ÿ SDK { #generating-sdks } + +็”ฑๆ–ผ **FastAPI** ๅปบ็ซ‹ๅœจ **OpenAPI** ่ฆๆ ผไน‹ไธŠ๏ผŒๅ…ถ API ่ƒฝไปฅ่จฑๅคšๅทฅๅ…ท้ƒฝ่ƒฝ็†่งฃ็š„ๆจ™ๆบ–ๆ ผๅผไพ†ๆ่ฟฐใ€‚ + +้€™่ฎ“ไฝ ่ƒฝ่ผ•้ฌ†็”ข็”Ÿๆœ€ๆ–ฐ็š„**ๆ–‡ไปถ**ใ€ๅคš่ชž่จ€็š„็”จๆˆถ็ซฏ็จ‹ๅผๅบซ๏ผˆ**SDKs**๏ผ‰๏ผŒไปฅๅŠ่ˆ‡็จ‹ๅผ็ขผไฟๆŒๅŒๆญฅ็š„**ๆธฌ่ฉฆ**ๆˆ–**่‡ชๅ‹•ๅŒ–ๅทฅไฝœๆต็จ‹**ใ€‚ + +ๅœจๆœฌๆŒ‡ๅ—ไธญ๏ผŒไฝ ๅฐ‡ๅญธๆœƒๅฆ‚ไฝ•็‚บไฝ ็š„ FastAPI ๅพŒ็ซฏ็”ข็”Ÿ **TypeScript SDK**ใ€‚ + +## ้–‹ๆบ SDK ็”ข็”Ÿๅ™จ { #open-source-sdk-generators } + +ๅ…ถไธญไธ€ๅ€‹็›ธ็•ถ่ฌ็”จ็š„้ธๆ“‡ๆ˜ฏ OpenAPI Generator๏ผŒๅฎƒๆ”ฏๆด**ๅคš็จฎ็จ‹ๅผ่ชž่จ€**๏ผŒไธฆ่ƒฝๅพžไฝ ็š„ OpenAPI ่ฆๆ ผ็”ข็”Ÿ SDKใ€‚ + +้‡ๅฐ **TypeScript ็”จๆˆถ็ซฏ**๏ผŒHey API ๆ˜ฏๅฐˆ้–€ๆ‰“้€ ็š„่งฃๆฑบๆ–นๆกˆ๏ผŒ็‚บ TypeScript ็”Ÿๆ…‹็ณปๆไพ›ๆœ€ไฝณๅŒ–็š„้ซ”้ฉ—ใ€‚ + +ไฝ ๅฏไปฅๅœจ OpenAPI.Tools ๆ‰พๅˆฐๆ›ดๅคš SDK ็”ข็”Ÿๅ™จใ€‚ + +/// tip + +FastAPI ๆœƒ่‡ชๅ‹•็”ข็”Ÿ **OpenAPI 3.1** ่ฆๆ ผ๏ผŒๅ› ๆญคไฝ ไฝฟ็”จ็š„ไปปไฝ•ๅทฅๅ…ท้ƒฝๅฟ…้ ˆๆ”ฏๆด้€™ๅ€‹็‰ˆๆœฌใ€‚ + +/// + +## ไพ†่‡ช FastAPI ่ดŠๅŠฉๅ•†็š„ SDK ็”ข็”Ÿๅ™จ { #sdk-generators-from-fastapi-sponsors } + +ๆœฌ็ฏ€้‡้ปžไป‹็ดน็”ฑ่ดŠๅŠฉ FastAPI ็š„ๅ…ฌๅธๆไพ›็š„**ๅ‰ตๆŠ•ๆ”ฏๆŒ**่ˆ‡**ๅ…ฌๅธ็ถญ้‹**็š„่งฃๆฑบๆ–นๆกˆใ€‚้€™ไบ›็”ขๅ“ๅœจ้ซ˜ๅ“่ณช็š„่‡ชๅ‹•็”ข็”Ÿ SDK ไน‹ๅค–๏ผŒ้‚„ๆไพ›**้กๅค–ๅŠŸ่ƒฝ**่ˆ‡**ๆ•ดๅˆ**ใ€‚ + +้€้Ž โœจ [**่ดŠๅŠฉ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๏ผŒ้€™ไบ›ๅ…ฌๅธๅนซๅŠฉ็ขบไฟๆก†ๆžถ่ˆ‡ๅ…ถ**็”Ÿๆ…‹็ณป**็ถญๆŒๅฅๅบทไธ”**ๆฐธ็บŒ**ใ€‚ + +ไป–ๅ€‘็š„่ดŠๅŠฉไนŸๅฑ•็พๅฐ FastAPI **็คพ็พค**๏ผˆไฝ ๏ผ‰็š„้ซ˜ๅบฆๆ‰ฟ่ซพ๏ผŒไธๅƒ…้—œๅฟƒๆไพ›**ๅ„ช่‰ฏๆœๅ‹™**๏ผŒไนŸๆ”ฏๆŒ **FastAPI** ไฝœ็‚บไธ€ๅ€‹**็ฉฉๅฅไธ”่“ฌๅ‹ƒ็š„ๆก†ๆžถ**ใ€‚๐Ÿ™‡ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅ˜—่ฉฆ๏ผš + +* Speakeasy +* Stainless +* liblab + +ๅ…ถไธญๆœ‰ไบ›ๆ–นๆกˆไนŸๅฏ่ƒฝๆ˜ฏ้–‹ๆบๆˆ–ๆไพ›ๅ…่ฒปๆ–นๆกˆ๏ผŒ่ฎ“ไฝ ไธ้œ€่ฒกๅ‹™ๆ‰ฟ่ซพๅฐฑ่ƒฝ่ฉฆ็”จใ€‚ๅ…ถไป–ๅ•†ๆฅญ็š„ SDK ็”ข็”Ÿๅ™จไนŸไธๅฐ‘๏ผŒไฝ ๅฏไปฅๅœจ็ถฒ่ทฏไธŠๆ‰พๅˆฐใ€‚๐Ÿค“ + +## ๅปบ็ซ‹ TypeScript SDK { #create-a-typescript-sdk } + +ๅ…ˆๅพžไธ€ๅ€‹็ฐกๅ–ฎ็š„ FastAPI ๆ‡‰็”จ้–‹ๅง‹๏ผš + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +ๆณจๆ„้€™ไบ› *่ทฏๅพ‘ๆ“ไฝœ* ็‚บ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰็š„ๆœ‰ๆ•ˆ่ผ‰่ทๅฎš็พฉไบ†ๆ‰€็”จ็š„ๆจกๅž‹๏ผŒไฝฟ็”จไบ† `Item` ่ˆ‡ `ResponseMessage` ้€™ๅ…ฉๅ€‹ๆจกๅž‹ใ€‚ + +### API ๆ–‡ไปถ { #api-docs } + +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€ `/docs`๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅ…ถไธญๅŒ…ๅซไบ†่ซ‹ๆฑ‚่ฆ้€ๅ‡บ็š„่ณ‡ๆ–™่ˆ‡ๅ›žๆ‡‰ๆŽฅๆ”ถ็š„่ณ‡ๆ–™ไน‹**็ตๆง‹๏ผˆschemas๏ผ‰**๏ผš + + + +ไฝ ไน‹ๆ‰€ไปฅ่ƒฝ็œ‹ๅˆฐ้€™ไบ›็ตๆง‹๏ผŒๆ˜ฏๅ› ็‚บๅฎƒๅ€‘ๅœจๆ‡‰็”จๅ…งไปฅๆจกๅž‹ๅฎฃๅ‘Šไบ†ใ€‚ + +้€™ไบ›่ณ‡่จŠ้ƒฝๅœจๆ‡‰็”จ็š„ **OpenAPI ็ตๆง‹**ไธญ๏ผŒไธฆ้กฏ็คบๅœจ API ๆ–‡ไปถ่ฃกใ€‚ + +ๅŒๆจฃๅŒ…ๅซๅœจ OpenAPI ไธญ็š„ๆจกๅž‹่ณ‡่จŠ๏ผŒไนŸๅฏไปฅ็”จไพ†**็”ข็”Ÿ็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ**ใ€‚ + +### Hey API { #hey-api } + +็•ถๆˆ‘ๅ€‘ๆœ‰ๅซๆจกๅž‹็š„ FastAPI ๆ‡‰็”จๅพŒ๏ผŒๅฐฑ่ƒฝ็”จ Hey API ไพ†็”ข็”Ÿ TypeScript ็”จๆˆถ็ซฏใ€‚ๆœ€ๅฟซ็š„ๆ–นๆณ•ๆ˜ฏ้€้Ž npx๏ผš + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +้€™ๆœƒๅœจ `./src/client` ็”ข็”Ÿไธ€ๅ€‹ TypeScript SDKใ€‚ + +ไฝ ๅฏไปฅๅœจไป–ๅ€‘็š„็ถฒ็ซ™ไบ†่งฃๅฆ‚ไฝ•ๅฎ‰่ฃ `@hey-api/openapi-ts`๏ผŒไปฅๅŠ้–ฑ่ฎ€็”ข็”Ÿ็š„่ผธๅ‡บๅ…งๅฎนใ€‚ + +### ไฝฟ็”จ SDK { #using-the-sdk } + +็พๅœจไฝ ๅฏไปฅๅŒฏๅ…ฅไธฆไฝฟ็”จ็”จๆˆถ็ซฏ็จ‹ๅผ็ขผใ€‚ๅคง่‡ด็œ‹่ตทไพ†ๆœƒๅƒ้€™ๆจฃ๏ผŒไฝ ๆœƒ็™ผ็พๆ–นๆณ•ๆœ‰่‡ชๅ‹•ๅฎŒๆˆ๏ผš + + + +ไฝ ไนŸๆœƒๅฐ่ฆ้€ๅ‡บ็š„ๆœ‰ๆ•ˆ่ผ‰่ท็ฒๅพ—่‡ชๅ‹•ๅฎŒๆˆ๏ผš + + + +/// tip + +ๆณจๆ„ `name` ่ˆ‡ `price` ็š„่‡ชๅ‹•ๅฎŒๆˆ๏ผŒ้€™ๆ˜ฏ็”ฑ FastAPI ๆ‡‰็”จไธญ็š„ `Item` ๆจกๅž‹ๆ‰€ๅฎš็พฉใ€‚ + +/// + +ไฝ ๅœจ้€ๅ‡บ็š„่ณ‡ๆ–™ไธŠไนŸๆœƒ็œ‹ๅˆฐ่กŒๅ…ง้Œฏ่ชค๏ผš + + + +ๅ›žๆ‡‰็‰ฉไปถๅŒๆจฃๆœ‰่‡ชๅ‹•ๅฎŒๆˆ๏ผš + + + +## ๅซๆจ™็ฑค็š„ FastAPI ๆ‡‰็”จ { #fastapi-app-with-tags } + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ็š„ FastAPI ๆ‡‰็”จๆœƒๆ›ดๅคง๏ผŒไฝ ๅฏ่ƒฝๆœƒ็”จๆจ™็ฑคๅฐ‡ไธๅŒ็พค็ต„็š„ *่ทฏๅพ‘ๆ“ไฝœ* ๅˆ†้–‹ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆœ‰ไธ€ๅ€‹ **items** ๅ€ๅกŠ่ˆ‡ๅฆไธ€ๅ€‹ **users** ๅ€ๅกŠ๏ผŒไธฆ้€้Žๆจ™็ฑคๅ€ๅˆ†๏ผš + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### ไฝฟ็”จๆจ™็ฑค็”ข็”Ÿ TypeScript ็”จๆˆถ็ซฏ { #generate-a-typescript-client-with-tags } + +่‹ฅไฝ ็‚บไฝฟ็”จๆจ™็ฑค็š„ FastAPI ๆ‡‰็”จ็”ข็”Ÿ็”จๆˆถ็ซฏ๏ผŒ็”ข็”Ÿๅ™จ้€šๅธธไนŸๆœƒไพๆจ™็ฑคๅฐ‡็”จๆˆถ็ซฏ็จ‹ๅผ็ขผๅˆ†้–‹ใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒ็”จๆˆถ็ซฏ็จ‹ๅผ็ขผๅฐฑ่ƒฝๆœ‰ๆข็†ๅœฐๆญฃ็ขบๅˆ†็ต„่ˆ‡ๆŽ’ๅˆ—๏ผš + + + +ๅœจๆญคไพ‹ไธญ๏ผŒไฝ ๆœƒๆœ‰๏ผš + +* `ItemsService` +* `UsersService` + +### ็”จๆˆถ็ซฏๆ–นๆณ•ๅ็จฑ { #client-method-names } + +็›ฎๅ‰ๅƒ `createItemItemsPost` ้€™ๆจฃ็š„็”ข็”Ÿๆ–นๆณ•ๅ็จฑ็œ‹่ตทไพ†ไธๅคชไฟ่ฝ๏ผš + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +โ€ฆโ€ฆ้‚ฃๆ˜ฏๅ› ็‚บ็”จๆˆถ็ซฏ็”ข็”Ÿๅ™จๅฐๆฏๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ* ้ƒฝไฝฟ็”จ OpenAPI ๅ…ง้ƒจ็š„**ๆ“ไฝœ ID๏ผˆoperation ID๏ผ‰**ใ€‚ + +OpenAPI ่ฆๆฑ‚ๆฏๅ€‹ๆ“ไฝœ ID ๅœจๆ‰€ๆœ‰ *่ทฏๅพ‘ๆ“ไฝœ* ไน‹้–“ๅฟ…้ ˆๅ”ฏไธ€๏ผŒๅ› ๆญค FastAPI ๆœƒ็”จ**ๅ‡ฝๅผๅ็จฑ**ใ€**่ทฏๅพ‘**่ˆ‡ **HTTP ๆ–นๆณ•/ๆ“ไฝœ**ไพ†็”ข็”Ÿ่ฉฒๆ“ไฝœ ID๏ผŒๅฆ‚ๆญคไพฟ่ƒฝ็ขบไฟๆ“ไฝœ ID ็š„ๅ”ฏไธ€ๆ€งใ€‚ + +ๆŽฅไธ‹ไพ†ๆˆ‘ๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•ๆŠŠๅฎƒ่ฎŠๅพ—ๆ›ดๅฅฝ็œ‹ใ€‚๐Ÿค“ + +## ่‡ช่จ‚ Operation ID ่ˆ‡ๆ›ดๅฅฝ็š„ๆ–นๆณ•ๅ็จฑ { #custom-operation-ids-and-better-method-names } + +ไฝ ๅฏไปฅ**ไฟฎๆ”น**้€™ไบ›ๆ“ไฝœ ID ็š„**็”ข็”Ÿๆ–นๅผ**๏ผŒ่ฎ“ๅฎƒๅ€‘ๆ›ด็ฐกๆฝ”๏ผŒไธฆๅœจ็”จๆˆถ็ซฏไธญๅพ—ๅˆฐ**ๆ›ด็ฐกๆฝ”็š„ๆ–นๆณ•ๅ็จฑ**ใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ้œ€่ฆ็”จๅ…ถไป–ๆ–นๅผ็ขบไฟๆฏๅ€‹ๆ“ไฝœ ID ้ƒฝๆ˜ฏ**ๅ”ฏไธ€**็š„ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็ขบไฟๆฏๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ* ้ƒฝๆœ‰ๆจ™็ฑค๏ผŒๆŽฅ่‘—ๆ นๆ“š**ๆจ™็ฑค**่ˆ‡ *่ทฏๅพ‘ๆ“ไฝœ* ็š„**ๅ็จฑ**๏ผˆๅ‡ฝๅผๅ็จฑ๏ผ‰ไพ†็”ข็”Ÿๆ“ไฝœ IDใ€‚ + +### ่‡ช่จ‚ๅ”ฏไธ€ ID ็”ข็”Ÿๅ‡ฝๅผ { #custom-generate-unique-id-function } + +FastAPI ๆœƒ็‚บๆฏๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ* ไฝฟ็”จไธ€ๅ€‹**ๅ”ฏไธ€ ID**๏ผŒๅฎƒๆœƒ่ขซ็”จๆ–ผ**ๆ“ไฝœ ID**๏ผŒไปฅๅŠไปปไฝ•่ซ‹ๆฑ‚ๆˆ–ๅ›žๆ‡‰ๆ‰€้œ€็š„่‡ช่จ‚ๆจกๅž‹ๅ็จฑใ€‚ + +ไฝ ๅฏไปฅ่‡ช่จ‚่ฉฒๅ‡ฝๅผใ€‚ๅฎƒๆŽฅๆ”ถไธ€ๅ€‹ APIRoute ไธฆๅ›žๅ‚ณๅญ—ไธฒใ€‚ + +ไพ‹ๅฆ‚๏ผŒไธ‹้ขไฝฟ็”จ็ฌฌไธ€ๅ€‹ๆจ™็ฑค๏ผˆไฝ ้€šๅธธๅชๆœƒๆœ‰ไธ€ๅ€‹ๆจ™็ฑค๏ผ‰ไปฅๅŠ *่ทฏๅพ‘ๆ“ไฝœ* ็š„ๅ็จฑ๏ผˆๅ‡ฝๅผๅ็จฑ๏ผ‰ใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅฐ‡้€™ๅ€‹่‡ช่จ‚ๅ‡ฝๅผไปฅ `generate_unique_id_function` ๅƒๆ•ธๅ‚ณ็ตฆ **FastAPI**๏ผš + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### ไฝฟ็”จ่‡ช่จ‚ Operation ID ็”ข็”Ÿ TypeScript ็”จๆˆถ็ซฏ { #generate-a-typescript-client-with-custom-operation-ids } + +็พๅœจ๏ผŒๅฆ‚ๆžœไฝ ๅ†ๆฌก็”ข็”Ÿ็”จๆˆถ็ซฏ๏ผŒๆœƒ็œ‹ๅˆฐๆ–นๆณ•ๅ็จฑๅทฒๆ”นๅ–„๏ผš + + + +ๅฆ‚ไฝ ๆ‰€่ฆ‹๏ผŒๆ–นๆณ•ๅ็จฑ็พๅœจๅŒ…ๅซๆจ™็ฑค่ˆ‡ๅ‡ฝๅผๅ็จฑ๏ผŒไธๅ†ๅŒ…ๅซ URL ่ทฏๅพ‘่ˆ‡ HTTP ๆ“ไฝœ็š„่ณ‡่จŠใ€‚ + +### ็‚บ็”จๆˆถ็ซฏ็”ข็”Ÿๅ™จ้ ่™•็† OpenAPI ่ฆๆ ผ { #preprocess-the-openapi-specification-for-the-client-generator } + +็”ข็”Ÿ็š„็จ‹ๅผ็ขผไปๆœ‰ไธ€ไบ›**้‡่ค‡่ณ‡่จŠ**ใ€‚ + +ๆˆ‘ๅ€‘ๅทฒ็ถ“็Ÿฅ้“้€™ๅ€‹ๆ–นๆณ•่ˆ‡ **items** ็›ธ้—œ๏ผŒๅ› ็‚บ่ฉฒๅญ—ๅทฒๅ‡บ็พๅœจ `ItemsService`๏ผˆๅ–่‡ชๆจ™็ฑค๏ผ‰ไธญ๏ผŒไฝ†ๆ–นๆณ•ๅ็จฑไป็„ถๅŠ ไธŠไบ†ๆจ™็ฑคๅ็จฑๅšๅ‰็ถดใ€‚๐Ÿ˜• + +ๅฐๆ–ผ OpenAPI ๆœฌ่บซ๏ผŒๆˆ‘ๅ€‘ๅฏ่ƒฝไปๆƒณไฟ็•™๏ผŒๅ› ็‚บ้‚ฃ่ƒฝ็ขบไฟๆ“ไฝœ ID ๆ˜ฏ**ๅ”ฏไธ€**็š„ใ€‚ + +ไฝ†ๅฐฑ็”ข็”Ÿ็”จๆˆถ็ซฏ่€Œ่จ€๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅœจ็”ข็”Ÿๅ‰**ไฟฎๆ”น** OpenAPI ็š„ๆ“ไฝœ ID๏ผŒไพ†่ฎ“ๆ–นๆณ•ๅ็จฑๆ›ด**็ฐกๆฝ”**ใ€ๆ›ด**ไนพๆทจ**ใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅๆŠŠ OpenAPI JSON ไธ‹่ผ‰ๅˆฐ `openapi.json` ๆช”ๆกˆ๏ผŒ็„ถๅพŒ็”จๅƒ้€™ๆจฃ็š„่…ณๆœฌ**็งป้™ค่ฉฒๆจ™็ฑคๅ‰็ถด**๏ผš + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๆ“ไฝœ ID ๆœƒๅพž `items-get_items` ไน‹้กž็š„ๅญ—ไธฒ๏ผŒ่ฎŠๆˆๅ–ฎ็ด”็š„ `get_items`๏ผŒ่ฎ“็”จๆˆถ็ซฏ็”ข็”Ÿๅ™จ่ƒฝ็”ข็”Ÿๆ›ด็ฐกๆฝ”็š„ๆ–นๆณ•ๅ็จฑใ€‚ + +### ไฝฟ็”จ้ ่™•็†ๅพŒ็š„ OpenAPI ็”ข็”Ÿ TypeScript ็”จๆˆถ็ซฏ { #generate-a-typescript-client-with-the-preprocessed-openapi } + +็”ฑๆ–ผๆœ€็ต‚็ตๆžœ็พๅœจๆ˜ฏๅœจ `openapi.json` ๆช”ๆกˆไธญ๏ผŒไฝ ้œ€่ฆๆ›ดๆ–ฐ่ผธๅ…ฅไฝ็ฝฎ๏ผš + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +็”ข็”Ÿๆ–ฐ็š„็”จๆˆถ็ซฏๅพŒ๏ผŒไฝ ็พๅœจๆœƒๅพ—ๅˆฐ**ไนพๆทจ็š„ๆ–นๆณ•ๅ็จฑ**๏ผŒๅŒๆ™‚ไฟๆœ‰ๆ‰€ๆœ‰็š„**่‡ชๅ‹•ๅฎŒๆˆ**ใ€**่กŒๅ…ง้Œฏ่ชค**็ญ‰ๅŠŸ่ƒฝ๏ผš + + + +## ๅฅฝ่™• { #benefits } + +ไฝฟ็”จ่‡ชๅ‹•็”ข็”Ÿ็š„็”จๆˆถ็ซฏๆ™‚๏ผŒไฝ ๆœƒๅพ—ๅˆฐไปฅไธ‹้ …็›ฎ็š„**่‡ชๅ‹•ๅฎŒๆˆ**๏ผš + +* ๆ–นๆณ• +* ๆœฌๆ–‡ไธญ็š„่ซ‹ๆฑ‚ๆœ‰ๆ•ˆ่ผ‰่ทใ€ๆŸฅ่ฉขๅƒๆ•ธ็ญ‰ +* ๅ›žๆ‡‰็š„ๆœ‰ๆ•ˆ่ผ‰่ท + +ไฝ ไนŸๆœƒๅฐๆ‰€ๆœ‰ๅ…งๅฎน็ฒๅพ—**่กŒๅ…ง้Œฏ่ชค**ๆ็คบใ€‚ + +่€Œไธ”ๆฏ็•ถไฝ ๆ›ดๆ–ฐๅพŒ็ซฏ็จ‹ๅผ็ขผไธฆ**้‡ๆ–ฐ็”ข็”Ÿ**ๅ‰็ซฏ๏ผˆ็”จๆˆถ็ซฏ๏ผ‰๏ผŒๆ–ฐ็š„ *่ทฏๅพ‘ๆ“ไฝœ* ๆœƒไปฅๆ–นๆณ•ๅฝขๅผๅฏ็”จใ€่ˆŠ็š„ๆœƒ่ขซ็งป้™ค๏ผŒๅ…ถไป–ไปปไฝ•่ฎŠๆ›ดไนŸ้ƒฝๆœƒๅๆ˜ ๅˆฐ็”ข็”Ÿ็š„็จ‹ๅผ็ขผไธญใ€‚๐Ÿค“ + +้€™ไนŸไปฃ่กจๅช่ฆๆœ‰ไปปไฝ•่ฎŠๆ›ด๏ผŒไพฟๆœƒ่‡ชๅ‹•**ๅๆ˜ **ๅˆฐ็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ๏ผ›่€Œ็•ถไฝ **ๅปบ็ฝฎ**็”จๆˆถ็ซฏๆ™‚๏ผŒๅฆ‚ๆžœไฝฟ็”จ็š„่ณ‡ๆ–™ๆœ‰ไปปไฝ•**ไธๅŒน้…**๏ผŒๅฐฑๆœƒ็›ดๆŽฅๅ ฑ้Œฏใ€‚ + +ๅ› ๆญค๏ผŒไฝ ่ƒฝๅœจ้–‹็™ผ้€ฑๆœŸ็š„ๅพˆๆ—ฉๆœŸๅฐฑ**ๅตๆธฌๅˆฐ่จฑๅคš้Œฏ่ชค**๏ผŒ่€Œไธๅฟ…็ญ‰ๅˆฐ้Œฏ่ชคๅœจๆญฃๅผ็’ฐๅขƒ็š„ๆœ€็ต‚ไฝฟ็”จ่€…้‚ฃ่ฃกๆ‰ๅ‡บ็พ๏ผŒ็„ถๅพŒๆ‰้–‹ๅง‹่ฟฝๆŸฅๅ•้กŒๆ‰€ๅœจใ€‚โœจ diff --git a/docs/zh-hant/docs/advanced/index.md b/docs/zh-hant/docs/advanced/index.md new file mode 100644 index 0000000000..cfbc17afec --- /dev/null +++ b/docs/zh-hant/docs/advanced/index.md @@ -0,0 +1,21 @@ +# ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ— { #advanced-user-guide } + +## ๆ›ดๅคšๅŠŸ่ƒฝ { #additional-features } + +ไธป่ฆ็š„[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank} ๆ‡‰่ถณไปฅๅธถไฝ ๅฟซ้€Ÿ็€่ฆฝ **FastAPI** ็š„ๆ‰€ๆœ‰ๆ ธๅฟƒๅŠŸ่ƒฝใ€‚ + +ๅœจๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ไธญ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅ…ถไป–้ธ้ …ใ€่จญๅฎš๏ผŒไปฅๅŠๆ›ดๅคšๅŠŸ่ƒฝใ€‚ + +/// tip + +ๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ไธไธ€ๅฎšใ€Œ้€ฒ้šŽใ€ใ€‚ + +่€Œไธ”ๅฐๆ–ผไฝ ็š„ไฝฟ็”จๆƒ…ๅขƒ๏ผŒ่งฃๆณ•ๅพˆๅฏ่ƒฝๅฐฑๅœจๅ…ถไธญๆŸไธ€็ฏ€ใ€‚ + +/// + +## ๅ…ˆ้–ฑ่ฎ€ๆ•™ๅญธ { #read-the-tutorial-first } + +ๅช่ฆๆŽŒๆกไธป่ฆ[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—](../tutorial/index.md){.internal-link target=_blank} ็š„ๅ…งๅฎน๏ผŒไฝ ๅฐฑ่ƒฝไฝฟ็”จ **FastAPI** ็š„ๅคงๅคšๆ•ธๅŠŸ่ƒฝใ€‚ + +ๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ไนŸๅ‡่จญไฝ ๅทฒ็ถ“่ฎ€้Ž๏ผŒไธฆๅทฒไบ†่งฃ้‚ฃไบ›ไธป่ฆ่ง€ๅฟตใ€‚ diff --git a/docs/zh-hant/docs/advanced/middleware.md b/docs/zh-hant/docs/advanced/middleware.md new file mode 100644 index 0000000000..80cda345c3 --- /dev/null +++ b/docs/zh-hant/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# ้€ฒ้šŽไธญไป‹่ปŸ้ซ” { #advanced-middleware } + +ๅœจไธป่ฆๆ•™ๅญธไธญไฝ ๅทฒๅญธ้Žๅฆ‚ไฝ•ๅฐ‡[่‡ช่จ‚ไธญไป‹่ปŸ้ซ”](../tutorial/middleware.md){.internal-link target=_blank}ๅŠ ๅ…ฅๅˆฐไฝ ็š„ๆ‡‰็”จ็จ‹ๅผใ€‚ + +ไฝ ไนŸ่ฎ€้Žๅฆ‚ไฝ•ไฝฟ็”จ `CORSMiddleware` ่™•็† [CORS](../tutorial/cors.md){.internal-link target=_blank}ใ€‚ + +ๆœฌ็ฏ€ๅฐ‡็คบ็ฏ„ๅฆ‚ไฝ•ไฝฟ็”จๅ…ถไป–ไธญไป‹่ปŸ้ซ”ใ€‚ + +## ๆ–ฐๅขž ASGI ไธญไป‹่ปŸ้ซ” { #adding-asgi-middlewares } + +็”ฑๆ–ผ **FastAPI** ๅปบ็ซ‹ๅœจ Starlette ไธŠไธฆๅฏฆไฝœไบ† ASGI ่ฆ็ฏ„๏ผŒไฝ ๅฏไปฅไฝฟ็”จไปปไฝ• ASGI ไธญไป‹่ปŸ้ซ”ใ€‚ + +ไธญไป‹่ปŸ้ซ”ไธไธ€ๅฎš่ฆ็‚บ FastAPI ๆˆ– Starlette ๅฐˆ้–€ๆ’ฐๅฏซ๏ผŒๅช่ฆ้ตๅพช ASGI ่ฆ็ฏ„ๅณๅฏ้‹ไฝœใ€‚ + +ไธ€่ˆฌไพ†่ชช๏ผŒASGI ไธญไป‹่ปŸ้ซ”ๆ˜ฏ้กžๅˆฅ๏ผŒ้ ๆœŸ็ฌฌไธ€ๅ€‹ๅƒๆ•ธๆŽฅๆ”ถไธ€ๅ€‹ ASGI ๆ‡‰็”จ็จ‹ๅผใ€‚ + +ๅ› ๆญค๏ผŒๅœจ็ฌฌไธ‰ๆ–น ASGI ไธญไป‹่ปŸ้ซ”็š„ๆ–‡ไปถไธญ๏ผŒ้€šๅธธๆœƒๆŒ‡็คบไฝ ้€™ๆจฃๅš๏ผš + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +ไฝ† FastAPI๏ผˆๅฏฆ้š›ไธŠๆ˜ฏ Starlette๏ผ‰ๆไพ›ไบ†ไธ€็จฎๆ›ด็ฐกๅ–ฎ็š„ๆ–นๅผ๏ผŒ็ขบไฟๅ…ง้ƒจไธญไป‹่ปŸ้ซ”่ƒฝ่™•็†ไผบๆœๅ™จ้Œฏ่ชค๏ผŒไธ”่‡ช่จ‚ไพ‹ๅค–่™•็†ๅ™จๅฏๆญฃๅธธ้‹ไฝœใ€‚ + +็‚บๆญค๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `app.add_middleware()`๏ผˆๅฆ‚ๅŒ CORS ็ฏ„ไพ‹๏ผ‰ใ€‚ + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` ๅฐ‡ไธญไป‹่ปŸ้ซ”้กžๅˆฅไฝœ็‚บ็ฌฌไธ€ๅ€‹ๅผ•ๆ•ธ๏ผŒไธฆๆŽฅๆ”ถ่ฆๅ‚ณ้ž็ตฆ่ฉฒไธญไป‹่ปŸ้ซ”็š„ๅ…ถไป–ๅผ•ๆ•ธใ€‚ + +## ๅ…งๅปบไธญไป‹่ปŸ้ซ” { #integrated-middlewares } + +**FastAPI** ๅ…งๅปบๆ•ธๅ€‹ๅธธ่ฆ‹็”จ้€”็š„ไธญไป‹่ปŸ้ซ”๏ผŒไปฅไธ‹ๅฐ‡็คบ็ฏ„ๅฆ‚ไฝ•ไฝฟ็”จใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅœจๆŽฅไธ‹ไพ†็š„็ฏ„ไพ‹ไธญ๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.middleware.something import SomethingMiddleware`ใ€‚ + +**FastAPI** ๅœจ `fastapi.middleware` ไธญๆไพ›ไบ†ไธ€ไบ›ไธญไป‹่ปŸ้ซ”๏ผŒ็ด”็ฒนๆ˜ฏ็‚บไบ†ๆ–นไพฟไฝ ้€™ไฝ้–‹็™ผ่€…ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ไธญไป‹่ปŸ้ซ”็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +ๅผทๅˆถๆ‰€ๆœ‰ๅ‚ณๅ…ฅ่ซ‹ๆฑ‚ๅฟ…้ ˆไฝฟ็”จ `https` ๆˆ– `wss`ใ€‚ + +ไปปไฝ•ๆŒ‡ๅ‘ `http` ๆˆ– `ws` ็š„่ซ‹ๆฑ‚้ƒฝๆœƒ่ขซ้‡ๆ–ฐๅฐŽๅ‘่‡ณๅฐๆ‡‰็š„ๅฎ‰ๅ…จๅ”ๅฎšใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +ๅผทๅˆถๆ‰€ๆœ‰ๅ‚ณๅ…ฅ่ซ‹ๆฑ‚ๆญฃ็ขบ่จญๅฎš `Host` ๆจ™้ ญ๏ผŒไปฅ้˜ฒ็ฏ„ HTTP Host Header ๆ”ปๆ“Šใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +ๆ”ฏๆดไปฅไธ‹ๅƒๆ•ธ๏ผš + +- `allowed_hosts` - ๅ…่จฑไฝœ็‚บไธปๆฉŸๅ็จฑ็š„็ถฒๅŸŸๅ็จฑๆธ…ๅ–ฎใ€‚ๆ”ฏๆด่ฌ็”จๅญ—ๅ…ƒ็ถฒๅŸŸ๏ผˆไพ‹ๅฆ‚ `*.example.com`๏ผ‰ไปฅๆฏ”ๅฐๅญ็ถฒๅŸŸใ€‚่‹ฅ่ฆๅ…่จฑไปปๆ„ไธปๆฉŸๅ็จฑ๏ผŒๅฏไฝฟ็”จ `allowed_hosts=["*"]`๏ผŒๆˆ–ไนพ่„†ไธ่ฆๅŠ ไธŠๆญคไธญไป‹่ปŸ้ซ”ใ€‚ +- `www_redirect` - ่‹ฅ่จญ็‚บ True๏ผŒๅฐๅ…่จฑไธปๆฉŸ็š„ไธๅซ www ็‰ˆๆœฌ็š„่ซ‹ๆฑ‚ๆœƒ่ขซ้‡ๆ–ฐๅฐŽๅ‘่‡ณๅ…ถ www ๅฐๆ‡‰็‰ˆๆœฌใ€‚้ ่จญ็‚บ `True`ใ€‚ + +่‹ฅๅ‚ณๅ…ฅ่ซ‹ๆฑ‚้ฉ—่ญ‰ๅคฑๆ•—๏ผŒๅฐ‡ๅ›žๅ‚ณ `400` ๅ›žๆ‡‰ใ€‚ + +## `GZipMiddleware` { #gzipmiddleware } + +่™•็†ๅœจ `Accept-Encoding` ๆจ™้ ญไธญๅŒ…ๅซ `"gzip"` ็š„่ซ‹ๆฑ‚ไน‹ GZip ๅฃ“็ธฎๅ›žๆ‡‰ใ€‚ + +ๆญคไธญไป‹่ปŸ้ซ”ๆœƒ่™•็†ไธ€่ˆฌ่ˆ‡ไธฒๆตๅ›žๆ‡‰ใ€‚ + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +ๆ”ฏๆดไปฅไธ‹ๅƒๆ•ธ๏ผš + +- `minimum_size` - ๅฐๆ–ผๆญคไฝๅ…ƒ็ต„ๅคงๅฐ็š„ๅ›žๆ‡‰ไธๆœƒ้€ฒ่กŒ GZipใ€‚้ ่จญ็‚บ `500`ใ€‚ +- `compresslevel` - GZip ๅฃ“็ธฎๆ™‚ไฝฟ็”จ็š„็ญ‰็ดšใ€‚็‚บ 1 ๅˆฐ 9 ็š„ๆ•ดๆ•ธใ€‚้ ่จญ็‚บ `9`ใ€‚ๅ€ผ่ถŠๅฐๅฃ“็ธฎ่ถŠๅฟซไฝ†ๆช”ๆกˆ่ผƒๅคง๏ผŒๅ€ผ่ถŠๅคงๅฃ“็ธฎ่ผƒๆ…ขไฝ†ๆช”ๆกˆ่ผƒๅฐใ€‚ + +## ๅ…ถไป–ไธญไป‹่ปŸ้ซ” { #other-middlewares } + +้‚„ๆœ‰่จฑๅคšๅ…ถไป– ASGI ไธญไป‹่ปŸ้ซ”ใ€‚ + +ไพ‹ๅฆ‚๏ผš + +- Uvicorn ็š„ `ProxyHeadersMiddleware` +- MessagePack + +ๆƒณ็žญ่งฃๆ›ดๅคšๅฏ็”จ็š„ไธญไป‹่ปŸ้ซ”๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ็š„ไธญไป‹่ปŸ้ซ”ๆ–‡ไปถ ่ˆ‡ ASGI ็ฒพ้ธๆธ…ๅ–ฎใ€‚ diff --git a/docs/zh-hant/docs/advanced/openapi-callbacks.md b/docs/zh-hant/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..b1a16be249 --- /dev/null +++ b/docs/zh-hant/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI ๅ›žๅ‘ผ { #openapi-callbacks } + +ไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹ๅซๆœ‰ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€็š„ API๏ผŒ่ฉฒๆ“ไฝœๆœƒ่งธ็™ผๅฐๆŸๅ€‹ใ€Œๅค–้ƒจ API๏ผˆexternal API๏ผ‰ใ€็š„่ซ‹ๆฑ‚๏ผˆ้€šๅธธ็”ฑไฝฟ็”จไฝ  API ็š„ๅŒไธ€ไฝ้–‹็™ผ่€…ๆไพ›๏ผ‰ใ€‚ + +็•ถไฝ ็š„ API ๆ‡‰็”จๅ‘ผๅซใ€Œๅค–้ƒจ APIใ€ๆ™‚็™ผ็”Ÿ็š„้Ž็จ‹็จฑ็‚บใ€Œๅ›žๅ‘ผ๏ผˆcallback๏ผ‰ใ€ใ€‚ๅ› ็‚บๅค–้ƒจ้–‹็™ผ่€…ๆ’ฐๅฏซ็š„่ปŸ้ซ”ๆœƒๅ…ˆๅ‘ไฝ ็š„ API ็™ผๅ‡บ่ซ‹ๆฑ‚๏ผŒๆŽฅ่‘—ไฝ ็š„ API ๅ†ใ€Œๅ›žๅ‘ผใ€๏ผŒไนŸๅฐฑๆ˜ฏๅ‘๏ผˆๅฏ่ƒฝๅŒไธ€ไฝ้–‹็™ผ่€…ๅปบ็ซ‹็š„๏ผ‰ๅค–้ƒจ API ็™ผ้€่ซ‹ๆฑ‚ใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆๆ–‡ไปถๅŒ–่ชชๆ˜Ž่ฉฒๅค–้ƒจ API ๆ‡‰่ฉฒ้•ทไป€้บผๆจฃๅญใ€‚ๅฎƒๆ‡‰่ฉฒๆœ‰ๅ“ชไบ›ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ใ€ๆ‡‰่ฉฒๆŽฅๅ—ไป€้บผ bodyใ€ๆ‡‰่ฉฒๅ›žๅ‚ณไป€้บผ response๏ผŒ็ญ‰็ญ‰ใ€‚ + +## ๅธถๆœ‰ๅ›žๅ‘ผ็š„ๆ‡‰็”จ { #an-app-with-callbacks } + +ๆˆ‘ๅ€‘็”จไธ€ๅ€‹ไพ‹ๅญไพ†็œ‹ใ€‚ + +ๆƒณๅƒไฝ ้–‹็™ผไบ†ไธ€ๅ€‹ๅ…่จฑๅปบ็ซ‹็™ผ็ฅจ็š„ๆ‡‰็”จใ€‚ + +้€™ไบ›็™ผ็ฅจๆœƒๆœ‰ `id`ใ€`title`๏ผˆๅฏ้ธ๏ผ‰ใ€`customer` ๅ’Œ `total`ใ€‚ + +ไฝ ็š„ API ็š„ไฝฟ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™ผ่€…๏ผ‰ๆœƒ้€้Žไธ€ๅ€‹ POST ่ซ‹ๆฑ‚ๅœจไฝ ็š„ API ไธญๅปบ็ซ‹ไธ€ๅผต็™ผ็ฅจใ€‚ + +็„ถๅพŒไฝ ็š„ API ๆœƒ๏ผˆ่ฎ“ๆˆ‘ๅ€‘ๆƒณๅƒ๏ผ‰๏ผš + +* ๅฐ‡็™ผ็ฅจๅฏ„็ตฆ่ฉฒๅค–้ƒจ้–‹็™ผ่€…็š„ๆŸไฝๅฎขๆˆถใ€‚ +* ไปฃๆ”ถๆฌพ้ …ใ€‚ +* ๅ†ๆŠŠ้€š็Ÿฅๅ›žๅ‚ณ็ตฆ API ไฝฟ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™ผ่€…๏ผ‰ใ€‚ + * ้€™ๆœƒ้€้Žๅพžใ€Œไฝ ็š„ APIใ€ๅ‘่ฉฒๅค–้ƒจ้–‹็™ผ่€…ๆไพ›็š„ใ€Œๅค–้ƒจ APIใ€้€ๅ‡บ POST ่ซ‹ๆฑ‚ๅฎŒๆˆ๏ผˆ้€™ๅฐฑๆ˜ฏใ€Œๅ›žๅ‘ผใ€๏ผ‰ใ€‚ + +## ไธ€่ˆฌ็š„ **FastAPI** ๆ‡‰็”จ { #the-normal-fastapi-app } + +ๅ…ˆ็œ‹็œ‹ๅœจๅŠ ๅ…ฅๅ›žๅ‘ผไน‹ๅ‰๏ผŒไธ€ๅ€‹ไธ€่ˆฌ็š„ API ๆ‡‰็”จๆœƒ้•ทไป€้บผๆจฃๅญใ€‚ + +ๅฎƒๆœƒๆœ‰ไธ€ๅ€‹ๆŽฅๆ”ถ `Invoice` body ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผŒไปฅๅŠไธ€ๅ€‹ๆŸฅ่ฉขๅƒๆ•ธ `callback_url`๏ผŒๅ…ถไธญๅŒ…ๅซ็”จๆ–ผๅ›žๅ‘ผ็š„ URLใ€‚ + +้€™้ƒจๅˆ†ๅพˆๆญฃๅธธ๏ผŒๅคšๆ•ธ็จ‹ๅผ็ขผไฝ ๆ‡‰่ฉฒๅทฒ็ถ“ๅพˆ็†Ÿๆ‚‰ไบ†๏ผš + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip + +`callback_url` ๆŸฅ่ฉขๅƒๆ•ธไฝฟ็”จ็š„ๆ˜ฏ Pydantic ็š„ Url ๅž‹ๅˆฅใ€‚ + +/// + +ๅ”ฏไธ€ๆ–ฐ็š„ๅœฐๆ–นๆ˜ฏๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญๅŠ ๅ…ฅๅƒๆ•ธ `callbacks=invoices_callback_router.routes`ใ€‚ๆˆ‘ๅ€‘ๆŽฅไธ‹ไพ†ๆœƒ็œ‹ๅˆฐ้‚ฃๆ˜ฏไป€้บผใ€‚ + +## ๆ–‡ไปถๅŒ–ๅ›žๅ‘ผ { #documenting-the-callback } + +ๅฏฆ้š›็š„ๅ›žๅ‘ผ็จ‹ๅผ็ขผๆœƒ้ซ˜ๅบฆไพ่ณดไฝ ็š„ API ๆ‡‰็”จๆœฌ่บซใ€‚ + +่€Œไธ”ๅพˆๅฏ่ƒฝๆฏๅ€‹ๆ‡‰็”จ้ƒฝๅทฎๅพˆๅคšใ€‚ + +ๅฎƒๅฏ่ƒฝๅฐฑๅชๆœ‰ไธ€ๅ…ฉ่กŒ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +ไฝ†ๅ›žๅ‘ผไธญๆœ€้‡่ฆ็š„้ƒจๅˆ†๏ผŒๅฏ่ƒฝๆ˜ฏๅœจ็ขบไฟไฝ ็š„ API ไฝฟ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™ผ่€…๏ผ‰่ƒฝๆญฃ็ขบๅฏฆไฝœใ€Œๅค–้ƒจ APIใ€๏ผŒ็ฌฆๅˆใ€Œไฝ ็š„ APIใ€ๅœจๅ›žๅ‘ผ่ซ‹ๆฑ‚ body ไธญ่ฆ้€ๅ‡บ็š„่ณ‡ๆ–™ๆ ผๅผ๏ผŒ็ญ‰็ญ‰ใ€‚ + +ๅ› ๆญค๏ผŒๆŽฅไธ‹ไพ†ๆˆ‘ๅ€‘่ฆๅŠ ไธŠ็”จไพ†ใ€Œๆ–‡ไปถๅŒ–ใ€่ชชๆ˜Ž๏ผŒ่ฉฒใ€Œๅค–้ƒจ APIใ€ๆ‡‰่ฉฒ้•ทไป€้บผๆจฃๅญ๏ผŒๆ‰่ƒฝๆŽฅๆ”ถไพ†่‡ชใ€Œไฝ ็š„ APIใ€็š„ๅ›žๅ‘ผใ€‚ + +้€™ไปฝๆ–‡ไปถๆœƒๅ‡บ็พๅœจไฝ ็š„ API ็š„ Swagger UI `/docs`๏ผŒ่ฎ“ๅค–้ƒจ้–‹็™ผ่€…็Ÿฅ้“่ฉฒๅฆ‚ไฝ•ๅปบ็ฝฎใ€Œๅค–้ƒจ APIใ€ใ€‚ + +้€™ๅ€‹็ฏ„ไพ‹ไธๆœƒๅฏฆไฝœๅ›žๅ‘ผๆœฌ่บซ๏ผˆ้‚ฃๅฏ่ƒฝๅฐฑๅชๆ˜ฏไธ€่กŒ็จ‹ๅผ็ขผ๏ผ‰๏ผŒๅชๆœƒๅฏฆไฝœๆ–‡ไปถ็š„้ƒจๅˆ†ใ€‚ + +/// tip + +ๅฏฆ้š›็š„ๅ›žๅ‘ผๅฐฑๆ˜ฏไธ€ๅ€‹ HTTP ่ซ‹ๆฑ‚ใ€‚ + +็•ถไฝ ่‡ชๅทฑๅฏฆไฝœๅ›žๅ‘ผๆ™‚๏ผŒๅฏไปฅไฝฟ็”จๅƒๆ˜ฏ HTTPX ๆˆ– Requestsใ€‚ + +/// + +## ๆ’ฐๅฏซๅ›žๅ‘ผ็š„ๆ–‡ไปถๅŒ–็จ‹ๅผ็ขผ { #write-the-callback-documentation-code } + +้€™ๆฎต็จ‹ๅผ็ขผๅœจไฝ ็š„ๆ‡‰็”จไธญไธๆœƒ่ขซๅŸท่กŒ๏ผŒๆˆ‘ๅ€‘ๅช้œ€่ฆๅฎƒไพ†ใ€Œๆ–‡ไปถๅŒ–ใ€่ชชๆ˜Ž้‚ฃๅ€‹ใ€Œๅค–้ƒจ APIใ€ๆ‡‰่ฉฒ้•ทไป€้บผๆจฃๅญใ€‚ + +ไธ้Ž๏ผŒไฝ ๅทฒ็ถ“็Ÿฅ้“ๅฆ‚ไฝ•็”จ **FastAPI** ่ผ•้ฌ†็‚บ API ๅปบ็ซ‹่‡ชๅ‹•ๆ–‡ไปถใ€‚ + +ๆ‰€ไปฅๆˆ‘ๅ€‘ๆœƒ็”จๅŒๆจฃ็š„ๆ–นๅผ๏ผŒไพ†ๆ–‡ไปถๅŒ–ใ€Œๅค–้ƒจ APIใ€ๆ‡‰่ฉฒ้•ทไป€้บผๆจฃๅญ... ไนŸๅฐฑๆ˜ฏๅปบ็ซ‹ๅค–้ƒจ API ๆ‡‰่ฉฒๅฏฆไฝœ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆๅ€‘๏ผ‰ใ€๏ผˆ้‚ฃไบ›ใ€Œไฝ ็š„ APIใ€ๆœƒๅŽปๅ‘ผๅซ็š„ๆ“ไฝœ๏ผ‰ใ€‚ + +/// tip + +ๅœจๆ’ฐๅฏซๅ›žๅ‘ผ็š„ๆ–‡ไปถๅŒ–็จ‹ๅผ็ขผๆ™‚๏ผŒๆŠŠ่‡ชๅทฑๆƒณๅƒๆˆ้‚ฃไฝใ€Œๅค–้ƒจ้–‹็™ผ่€…ใ€ๆœƒๅพˆๆœ‰ๅนซๅŠฉใ€‚่€Œไธ”ไฝ ็พๅœจๆ˜ฏๅœจๅฏฆไฝœใ€Œๅค–้ƒจ APIใ€๏ผŒไธๆ˜ฏใ€Œไฝ ็š„ APIใ€ใ€‚ + +ๆšซๆ™‚ๆŽก็”จ้€™ๅ€‹๏ผˆๅค–้ƒจ้–‹็™ผ่€…๏ผ‰็š„่ฆ–่ง’๏ผŒๆœ‰ๅŠฉๆ–ผ่ฎ“ไฝ ๆ›ด็›ด่ฆบๅœฐๆฑบๅฎš่ฉฒๆŠŠๅƒๆ•ธใ€body ็š„ Pydantic ๆจกๅž‹ใ€response ็š„ๆจกๅž‹็ญ‰ๆ”พๅœจๅ“ช่ฃก๏ผŒๅฐๆ–ผ้‚ฃๅ€‹ใ€Œๅค–้ƒจ APIใ€ๆœƒๆ›ดๆธ…ๆฅšใ€‚ + +/// + +### ๅปบ็ซ‹ไธ€ๅ€‹ๅ›žๅ‘ผ็”จ็š„ `APIRouter` { #create-a-callback-apirouter } + +ๅ…ˆๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„ `APIRouter`๏ผŒ็”จไพ†ๆ”พไธ€ๅ€‹ๆˆ–ๅคšๅ€‹ๅ›žๅ‘ผใ€‚ + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### ๅปบ็ซ‹ๅ›žๅ‘ผ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ { #create-the-callback-path-operation } + +่ฆๅปบ็ซ‹ๅ›žๅ‘ผ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผŒๅฐฑไฝฟ็”จไฝ ไธŠ้ขๅปบ็ซ‹็š„ๅŒไธ€ๅ€‹ `APIRouter`ใ€‚ + +ๅฎƒ็œ‹่ตทไพ†ๅฐฑๅƒไธ€่ˆฌ็š„ FastAPIใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผš + +* ๅฏ่ƒฝ้œ€่ฆๅฎฃๅ‘Šๅฎƒๆ‡‰่ฉฒๆŽฅๆ”ถ็š„ body๏ผŒไพ‹ๅฆ‚ `body: InvoiceEvent`ใ€‚ +* ไนŸๅฏไปฅๅฎฃๅ‘Šๅฎƒๆ‡‰่ฉฒๅ›žๅ‚ณ็š„ response๏ผŒไพ‹ๅฆ‚ `response_model=InvoiceEventReceived`ใ€‚ + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +ๅ’Œไธ€่ˆฌใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็›ธๆฏ”ๆœ‰ๅ…ฉๅ€‹ไธป่ฆๅทฎ็•ฐ๏ผš + +* ไธ้œ€่ฆไปปไฝ•ๅฏฆ้š›็จ‹ๅผ็ขผ๏ผŒๅ› ็‚บไฝ ็š„ๆ‡‰็”จๆฐธ้ ไธๆœƒๅ‘ผๅซ้€™ๆฎต็จ‹ๅผใ€‚ๅฎƒๅช็”จไพ†ๆ–‡ไปถๅŒ–ใ€Œๅค–้ƒจ APIใ€ใ€‚ๅ› ๆญคๅ‡ฝๅผๅฏไปฅๅชๆœ‰ `pass`ใ€‚ +* ใ€Œ่ทฏๅพ‘ใ€ๅฏไปฅๅŒ…ๅซไธ€ๅ€‹ OpenAPI 3 ่กจ้”ๅผ๏ผˆ่ฆ‹ไธ‹ๆ–‡๏ผ‰๏ผŒๅฏไฝฟ็”จๅƒๆ•ธ่ˆ‡ๅŽŸๅง‹้€ๅˆฐใ€Œไฝ ็š„ APIใ€็š„่ซ‹ๆฑ‚ไธญ็š„้ƒจๅˆ†ๆฌ„ไฝใ€‚ + +### ๅ›žๅ‘ผ่ทฏๅพ‘่กจ้”ๅผ { #the-callback-path-expression } + +ๅ›žๅ‘ผ็š„ใ€Œ่ทฏๅพ‘ใ€ๅฏไปฅๅŒ…ๅซไธ€ๅ€‹ OpenAPI 3 ่กจ้”ๅผ๏ผŒ่ƒฝๅผ•็”จๅŽŸๆœฌ้€ๅˆฐใ€Œไฝ ็š„ APIใ€็š„่ซ‹ๆฑ‚ไธญ็š„้ƒจๅˆ†ๅ…งๅฎนใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅฎƒๆ˜ฏไธ€ๅ€‹ `str`๏ผš + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +ๆ‰€ไปฅ๏ผŒๅฆ‚ๆžœไฝ ็š„ API ไฝฟ็”จ่€…๏ผˆๅค–้ƒจ้–‹็™ผ่€…๏ผ‰ๅ‘ใ€Œไฝ ็š„ APIใ€้€ๅ‡บ้€™ๆจฃ็š„่ซ‹ๆฑ‚๏ผš + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +ไธฆ้™„ไธŠ้€™ๅ€‹ JSON body๏ผš + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +้‚ฃ้บผใ€Œไฝ ็š„ APIใ€ๆœƒ่™•็†้€™ๅผต็™ผ็ฅจ๏ผŒไธฆๅœจ็จๅพŒๆŸๅ€‹ๆ™‚้ปž๏ผŒๅ‘ `callback_url`๏ผˆไนŸๅฐฑๆ˜ฏใ€Œๅค–้ƒจ APIใ€๏ผ‰้€ๅ‡บๅ›žๅ‘ผ่ซ‹ๆฑ‚๏ผš + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +ๅ…ถ JSON body ๅคง่‡ดๅŒ…ๅซ๏ผš + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +่€Œๅฎƒๆœƒ้ ๆœŸ่ฉฒใ€Œๅค–้ƒจ APIใ€ๅ›žๅ‚ณ็š„ JSON body ไพ‹ๅฆ‚๏ผš + +```JSON +{ + "ok": true +} +``` + +/// tip + +ๆณจๆ„ๅ›žๅ‘ผๆ‰€็”จ็š„ URL๏ผŒๅŒ…ๅซไบ†ๅœจๆŸฅ่ฉขๅƒๆ•ธ `callback_url` ไธญๆ”ถๅˆฐ็š„ URL๏ผˆ`https://www.external.org/events`๏ผ‰๏ผŒไปฅๅŠไพ†่‡ช JSON body ๅ…ง็š„็™ผ็ฅจ `id`๏ผˆ`2expen51ve`๏ผ‰ใ€‚ + +/// + +### ๅŠ ๅ…ฅๅ›žๅ‘ผ router { #add-the-callback-router } + +ๆญคๆ™‚ไฝ ๅทฒ็ถ“ๅœจๅ…ˆๅ‰ๅปบ็ซ‹็š„ๅ›žๅ‘ผ router ไธญ๏ผŒๆ“ๆœ‰ๆ‰€้œ€็š„ๅ›žๅ‘ผใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆๅ€‘๏ผ‰ใ€๏ผˆไนŸๅฐฑๆ˜ฏใ€Œๅค–้ƒจ้–‹็™ผ่€…ใ€ๆ‡‰่ฉฒๅœจใ€Œๅค–้ƒจ APIใ€ไธญๅฏฆไฝœ็š„้‚ฃไบ›๏ผ‰ใ€‚ + +็พๅœจๅœจใ€Œไฝ ็š„ API ็š„่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญไฝฟ็”จๅƒๆ•ธ `callbacks`๏ผŒๅฐ‡่ฉฒๅ›žๅ‘ผ router ็š„ๅฑฌๆ€ง `.routes`๏ผˆๅฏฆ้š›ไธŠๅฐฑๆ˜ฏไธ€ๅ€‹็”ฑ่ทฏ็”ฑ๏ผใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆ‰€็ต„ๆˆ็š„ `list`๏ผ‰ๅ‚ณๅ…ฅ๏ผš + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip + +ๆณจๆ„ไฝ ๅ‚ณ็ตฆ `callback=` ็š„ไธๆ˜ฏๆ•ดๅ€‹ router ๆœฌ่บซ๏ผˆ`invoices_callback_router`๏ผ‰๏ผŒ่€Œๆ˜ฏๅฎƒ็š„ๅฑฌๆ€ง `.routes`๏ผŒไนŸๅฐฑๆ˜ฏ `invoices_callback_router.routes`ใ€‚ + +/// + +### ๆชขๆŸฅๆ–‡ไปถ { #check-the-docs } + +็พๅœจไฝ ๅฏไปฅๅ•Ÿๅ‹•ๆ‡‰็”จ๏ผŒไธฆๅ‰ๅพ€ http://127.0.0.1:8000/docsใ€‚ + +ไฝ ๆœƒๅœจๆ–‡ไปถไธญ็œ‹ๅˆฐไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅŒ…ๅซไธ€ๅ€‹ใ€ŒCallbacksใ€ๅ€ๅกŠ๏ผŒ้กฏ็คบใ€Œๅค–้ƒจ APIใ€ๆ‡‰่ฉฒ้•ทไป€้บผๆจฃๅญ๏ผš + + diff --git a/docs/zh-hant/docs/advanced/openapi-webhooks.md b/docs/zh-hant/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..ef52c3884f --- /dev/null +++ b/docs/zh-hant/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhook { #openapi-webhooks } + +ๆœ‰ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒๆƒณๅ‘Š่จดไฝ ็š„ API ไฝฟ็”จ่€…๏ผŒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๅฏ่ƒฝๆœƒๆ”œๅธถไธ€ไบ›่ณ‡ๆ–™ๅŽปๅ‘ผๅซไป–ๅ€‘็š„ๆ‡‰็”จ็จ‹ๅผ๏ผˆ็™ผ้€่ซ‹ๆฑ‚๏ผ‰๏ผŒ้€šๅธธๆ˜ฏ็‚บไบ†้€š็ŸฅๆŸ็จฎ้กžๅž‹็š„ไบ‹ไปถใ€‚ + +้€™่กจ็คบ๏ผŒ่ˆ‡ๅ…ถ็”ฑไฝฟ็”จ่€…ๅ‘ไฝ ็š„ API ็™ผ้€่ซ‹ๆฑ‚๏ผŒๆ”น็‚บไฝ ็š„ API๏ผˆๆˆ–ไฝ ็š„ๆ‡‰็”จ๏ผ‰ๅฏ่ƒฝๆœƒๅ‘ไป–ๅ€‘็š„็ณป็ตฑ๏ผˆไป–ๅ€‘็š„ APIใ€ไป–ๅ€‘็š„ๆ‡‰็”จ๏ผ‰็™ผ้€่ซ‹ๆฑ‚ใ€‚ + +้€™้€šๅธธ็จฑ็‚บ webhookใ€‚ + +## Webhook ๆญฅ้ฉŸ { #webhooks-steps } + +ๆต็จ‹้€šๅธธๆ˜ฏ๏ผšไฝ ๅœจ็จ‹ๅผ็ขผไธญๅฎš็พฉ่ฆ็™ผ้€็š„่จŠๆฏ๏ผŒไนŸๅฐฑๆ˜ฏ่ซ‹ๆฑ‚็š„ไธป้ซ”๏ผˆrequest body๏ผ‰ใ€‚ + +ไฝ ไนŸๆœƒไปฅๆŸ็จฎๆ–นๅผๅฎš็พฉๆ‡‰็”จๅœจๅ“ชไบ›ๆ™‚ๅˆปๆœƒ็™ผ้€้‚ฃไบ›่ซ‹ๆฑ‚ๆˆ–ไบ‹ไปถใ€‚ + +่€Œไฝ ็š„ไฝฟ็”จ่€…ๅ‰‡ๆœƒไปฅๆŸ็จฎๆ–นๅผ๏ผˆไพ‹ๅฆ‚ๅœจๆŸๅ€‹ Web ๆŽงๅˆถๅฐ๏ผ‰่จญๅฎšไฝ ็š„ๆ‡‰็”จๆ‡‰่ฉฒๅฐ‡้€™ไบ›่ซ‹ๆฑ‚้€ๅพ€็š„ URLใ€‚ + +้—œๆ–ผๅฆ‚ไฝ•่จปๅ†Š webhook ็š„ URL๏ผŒไปฅๅŠๅฏฆ้š›็™ผ้€้‚ฃไบ›่ซ‹ๆฑ‚็š„็จ‹ๅผ็ขผ็ญ‰ๆ‰€ๆœ‰้‚่ผฏ๏ผŒ้ƒฝ็”ฑไฝ ๆฑบๅฎšใ€‚ไฝ ๅฏไปฅๅœจ่‡ชๅทฑ็š„็จ‹ๅผ็ขผไธญ็”จไฝ ๆƒณ่ฆ็š„ๆ–นๅผๆ’ฐๅฏซใ€‚ + +## ไฝฟ็”จ FastAPI ่ˆ‡ OpenAPI ่จ˜้Œ„ webhook { #documenting-webhooks-with-fastapi-and-openapi } + +ๅœจ FastAPI ไธญ๏ผŒ้€้Ž OpenAPI๏ผŒไฝ ๅฏไปฅๅฎš็พฉ้€™ไบ› webhook ็š„ๅ็จฑใ€ไฝ ็š„ๆ‡‰็”จๅฐ‡็™ผ้€็š„ HTTP ๆ“ไฝœ้กžๅž‹๏ผˆไพ‹ๅฆ‚ `POST`ใ€`PUT` ็ญ‰๏ผ‰๏ผŒไปฅๅŠไฝ ็š„ๆ‡‰็”จ่ฆ็™ผ้€็š„่ซ‹ๆฑ‚ไธป้ซ”ใ€‚ + +้€™่ƒฝ่ฎ“ไฝ ็š„ไฝฟ็”จ่€…ๆ›ดๅฎนๆ˜“ๅฏฆไฝœไป–ๅ€‘็š„ API ไปฅๆŽฅๆ”ถไฝ ็š„ webhook ่ซ‹ๆฑ‚๏ผŒ็”š่‡ณๅฏ่ƒฝ่‡ชๅ‹•็”ข็”Ÿ้ƒจๅˆ†ไป–ๅ€‘่‡ชๅทฑ็š„ API ็จ‹ๅผ็ขผใ€‚ + +/// info + +Webhook ๅŠŸ่ƒฝ่‡ช OpenAPI 3.1.0 ่ตทๆไพ›๏ผŒFastAPI `0.99.0` ไปฅไธŠ็‰ˆๆœฌๆ”ฏๆดใ€‚ + +/// + +## ๅซๆœ‰ webhook ็š„ๆ‡‰็”จ { #an-app-with-webhooks } + +ๅปบ็ซ‹ FastAPI ๆ‡‰็”จๆ™‚๏ผŒๆœƒๆœ‰ไธ€ๅ€‹ `webhooks` ๅฑฌๆ€งๅฏ็”จไพ†ๅฎš็พฉ webhook๏ผŒๆ–นๅผ่ˆ‡ๅฎš็พฉ่ทฏๅพ‘ๆ“ไฝœ็›ธๅŒ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `@app.webhooks.post()`ใ€‚ + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +ไฝ ๅฎš็พฉ็š„ webhook ๆœƒๅ‡บ็พๅœจ OpenAPI ็ตๆง‹ๆ่ฟฐ่ˆ‡่‡ชๅ‹•็”ข็”Ÿ็š„ๆ–‡ไปถ UI ไธญใ€‚ + +/// info + +`app.webhooks` ๅ…ถๅฏฆๅฐฑๆ˜ฏไธ€ๅ€‹ `APIRouter`๏ผŒ่ˆ‡ไฝ ๅœจๅฐ‡ๆ‡‰็”จๆ‹†ๅˆ†็‚บๅคšๅ€‹ๆช”ๆกˆๆ™‚ๆ‰€ไฝฟ็”จ็š„ๅž‹ๅˆฅ็›ธๅŒใ€‚ + +/// + +ๆณจๆ„๏ผŒไฝฟ็”จ webhook ๆ™‚ไฝ ๅ…ถๅฏฆไธๆ˜ฏๅœจๅฎฃๅ‘Š่ทฏๅพ‘๏ผˆไพ‹ๅฆ‚ `/items/`๏ผ‰๏ผŒไฝ ๅ‚ณๅ…ฅ็š„ๆ–‡ๅญ—ๅชๆ˜ฏ่ฉฒ webhook ็š„่ญ˜ๅˆฅๅ็จฑ๏ผˆไบ‹ไปถๅ็จฑ๏ผ‰ใ€‚ไพ‹ๅฆ‚ๅœจ `@app.webhooks.post("new-subscription")` ไธญ๏ผŒwebhook ๅ็จฑๆ˜ฏ `new-subscription`ใ€‚ + +้€™ๆ˜ฏๅ› ็‚บ้ ๆœŸ็”ฑไฝ ็š„ไฝฟ็”จ่€…ไปฅๅ…ถไป–ๆ–นๅผ๏ผˆไพ‹ๅฆ‚ Web ๆŽงๅˆถๅฐ๏ผ‰ไพ†่จญๅฎšๅฏฆ้š›่ฆๆŽฅๆ”ถ webhook ่ซ‹ๆฑ‚็š„ URL ่ทฏๅพ‘ใ€‚ + +### ๆŸฅ็œ‹ๆ–‡ไปถ { #check-the-docs } + +็พๅœจไฝ ๅฏไปฅๅ•Ÿๅ‹•ๆ‡‰็”จ๏ผŒ็„ถๅพŒๅ‰ๅพ€ http://127.0.0.1:8000/docsใ€‚ + +ไฝ ๆœƒๅœจๆ–‡ไปถไธญ็œ‹ๅˆฐไธ€่ˆฌ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผŒๅฆๅค–้‚„ๆœ‰ไธ€ไบ› webhook๏ผš + + diff --git a/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000..4f25eb9878 --- /dev/null +++ b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,172 @@ +# ่ทฏๅพ‘ๆ“ไฝœ้€ฒ้šŽ่จญๅฎš { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning + +ๅฆ‚ๆžœไฝ ไธๆ˜ฏ OpenAPI ็š„ใ€Œๅฐˆๅฎถใ€๏ผŒๅคงๆฆ‚ไธ้œ€่ฆ้€™ๅ€‹ใ€‚ + +/// + +ไฝ ๅฏไปฅ็”จๅƒๆ•ธ `operation_id` ็‚บไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰*่จญๅฎš่ฆไฝฟ็”จ็š„ OpenAPI `operationId`ใ€‚ + +ไฝ ๅฟ…้ ˆ็ขบไฟๆฏๅ€‹ๆ“ไฝœ็š„ `operationId` ้ƒฝๆ˜ฏๅ”ฏไธ€็š„ใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### ไฝฟ็”จ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰็š„ๅ็จฑไฝœ็‚บ operationId { #using-the-path-operation-function-name-as-the-operationid } + +ๅฆ‚ๆžœไฝ ๆƒณ็”จ API ็š„ๅ‡ฝๅผๅ็จฑไฝœ็‚บ `operationId`๏ผŒไฝ ๅฏไปฅ้ๆญทๆ‰€ๆœ‰่ทฏๅพ‘๏ผŒไธฆไฝฟ็”จๅ„่‡ช็š„ `APIRoute.name` ่ฆ†ๅฏซๆฏๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*็š„ `operation_id`ใ€‚ + +ๆ‡‰ๅœจๅŠ ๅ…ฅๆ‰€ๆœ‰*่ทฏๅพ‘ๆ“ไฝœ*ไน‹ๅพŒๅ†้€™้บผๅšใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} + +/// tip + +ๅฆ‚ๆžœไฝ ๆœƒๆ‰‹ๅ‹•ๅ‘ผๅซ `app.openapi()`๏ผŒ่ซ‹ๅ‹™ๅฟ…ๅ…ˆๆ›ดๆ–ฐๆ‰€ๆœ‰ `operationId` ๅ†ๅ‘ผๅซใ€‚ + +/// + +/// warning + +ๅฆ‚ๆžœไฝ ้€™ๆจฃๅš๏ผŒๅฟ…้ ˆ็ขบไฟๆฏๅ€‹*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*้ƒฝๆœ‰ๅ”ฏไธ€็š„ๅ็จฑ๏ผŒ + +ๅณไฝฟๅฎƒๅ€‘ไฝๆ–ผไธๅŒ็š„ๆจก็ต„๏ผˆPython ๆช”ๆกˆ๏ผ‰ไธญใ€‚ + +/// + +## ๅพž OpenAPI ๆŽ’้™ค { #exclude-from-openapi } + +่‹ฅ่ฆๅพž็”ข็”Ÿ็š„ OpenAPI ็ตๆง‹๏ผˆไนŸๅฐฑๆ˜ฏ่‡ชๅ‹•ๆ–‡ไปถ็ณป็ตฑ๏ผ‰ไธญๆŽ’้™คๆŸๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*๏ผŒไฝฟ็”จๅƒๆ•ธ `include_in_schema` ไธฆๅฐ‡ๅ…ถ่จญ็‚บ `False`๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} + +## ๅพž docstring ๆไพ›้€ฒ้šŽๆ่ฟฐ { #advanced-description-from-docstring } + +ไฝ ๅฏไปฅ้™ๅˆถ OpenAPI ๅพž*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*็š„ docstring ไธญไฝฟ็”จ็š„ๅ…งๅฎน่กŒๆ•ธใ€‚ + +ๅŠ ไธŠไธ€ๅ€‹ `\f`๏ผˆ่ทณ้ ๅญ—ๅ…ƒ๏ผŒform feed๏ผ‰ๆœƒ่ฎ“ FastAPI ๅœจๆญค่™•ๆˆชๆ–ท็”จๆ–ผ OpenAPI ็š„่ผธๅ‡บใ€‚ + +้€™ๅ€‹ๅญ—ๅ…ƒไธๆœƒๅ‡บ็พๅœจๆ–‡ไปถไธญ๏ผŒไฝ†ๅ…ถไป–ๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ Sphinx๏ผ‰ไปๅฏไฝฟ็”จๅ…ถๅพŒ็š„ๅ…งๅฎนใ€‚ + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## ้กๅค–ๅ›žๆ‡‰ { #additional-responses } + +ไฝ ๅคงๆฆ‚ๅทฒ็œ‹้Žๅฆ‚ไฝ•็‚บ*่ทฏๅพ‘ๆ“ไฝœ*ๅฎฃๅ‘Š `response_model` ่ˆ‡ `status_code`ใ€‚ + +้€™ๆœƒๅฎš็พฉ่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ*ไธป่ฆๅ›žๆ‡‰็š„ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +ไฝ ไนŸๅฏไปฅๅฎฃๅ‘Š้กๅค–็š„ๅ›žๆ‡‰ๅŠๅ…ถๆจกๅž‹ใ€็‹€ๆ…‹็ขผ็ญ‰ใ€‚ + +ๆ–‡ไปถไธญๆœ‰ๅฎŒๆ•ด็ซ ็ฏ€่ชชๆ˜Ž๏ผŒ่ซ‹่ฆ‹ [OpenAPI ไธญ็š„้กๅค–ๅ›žๆ‡‰](additional-responses.md){.internal-link target=_blank}ใ€‚ + +## OpenAPI ้กๅค–่ณ‡่จŠ { #openapi-extra } + +็•ถไฝ ๅœจๆ‡‰็”จ็จ‹ๅผไธญๅฎฃๅ‘Šไธ€ๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*ๆ™‚๏ผŒFastAPI ๆœƒ่‡ชๅ‹•็”ข็”Ÿ่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ*็š„็›ธ้—œไธญ็นผ่ณ‡ๆ–™๏ผŒไธฆ็ดๅ…ฅ OpenAPI ็ตๆง‹ไธญใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅœจ OpenAPI ่ฆๆ ผไธญ๏ผŒ้€™็จฑ็‚บ Operation ็‰ฉไปถใ€‚ + +/// + +ๅฎƒๅŒ…ๅซ้—œๆ–ผ*่ทฏๅพ‘ๆ“ไฝœ*็š„ๆ‰€ๆœ‰่ณ‡่จŠ๏ผŒไธฆ็”จๆ–ผ็”ข็”Ÿ่‡ชๅ‹•ๆ–‡ไปถใ€‚ + +ๅ…ถไธญๅŒ…ๅซ `tags`ใ€`parameters`ใ€`requestBody`ใ€`responses` ็ญ‰ใ€‚ + +้€™ๅ€‹้‡ๅฐๅ–ฎไธ€่ทฏๅพ‘ๆ“ไฝœ็š„ OpenAPI ็ตๆง‹้€šๅธธ็”ฑ FastAPI ่‡ชๅ‹•็”ข็”Ÿ๏ผŒไฝ†ไฝ ไนŸๅฏไปฅๆ“ดๅ……ๅฎƒใ€‚ + +/// tip + +้€™ๆ˜ฏไธ€ๅ€‹่ผƒไฝŽ้šŽ็š„ๆ“ดๅ……ไป‹้ขใ€‚ + +ๅฆ‚ๆžœไฝ ๅช้œ€่ฆๅฎฃๅ‘Š้กๅค–ๅ›žๆ‡‰๏ผŒๆ›ดๆ–นไพฟ็š„ๆ–นๅผๆ˜ฏไฝฟ็”จ [OpenAPI ไธญ็š„้กๅค–ๅ›žๆ‡‰](additional-responses.md){.internal-link target=_blank}ใ€‚ + +/// + +ไฝ ๅฏไปฅไฝฟ็”จๅƒๆ•ธ `openapi_extra` ไพ†ๆ“ดๅ……ๆŸๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*็š„ OpenAPI ็ตๆง‹ใ€‚ + +### OpenAPI ๆ“ดๅ…… { #openapi-extensions } + +`openapi_extra` ๅฏ็”จไพ†ๅฎฃๅ‘Šไพ‹ๅฆ‚ [OpenAPI ๆ“ดๅ……](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) ็š„่ณ‡ๆ–™๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} + +ๆ‰“้–‹่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถๆ™‚๏ผŒไฝ ็š„ๆ“ดๅ……ๆœƒ้กฏ็คบๅœจ่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ*้ ้ข็š„ๅบ•้ƒจใ€‚ + + + +่€Œๅœจๆชข่ฆ–็”ข็”Ÿๅ‡บ็š„ OpenAPI๏ผˆไฝๆ–ผไฝ ็š„ API ็š„ `/openapi.json`๏ผ‰ๆ™‚๏ผŒไนŸๅฏไปฅๅœจ็›ธๆ‡‰*่ทฏๅพ‘ๆ“ไฝœ*ไธญ็œ‹ๅˆฐไฝ ็š„ๆ“ดๅ……๏ผš + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ่‡ช่จ‚ OpenAPI ่ทฏๅพ‘ๆ“ไฝœ็ตๆง‹ { #custom-openapi-path-operation-schema } + +`openapi_extra` ไธญ็š„ๅญ—ๅ…ธๆœƒ่ˆ‡่‡ชๅ‹•็”ข็”Ÿ็š„่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ*ไน‹ OpenAPI ็ตๆง‹้€ฒ่กŒๆทฑๅบฆๅˆไฝตใ€‚ + +ๅ› ๆญคไฝ ๅฏไปฅๅœจ่‡ชๅ‹•็”ข็”Ÿ็š„็ตๆง‹ไธŠๅŠ ๅ…ฅ้กๅค–่ณ‡ๆ–™ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ้ธๆ“‡็”จ่‡ชๅทฑ็š„็จ‹ๅผ็ขผ่ฎ€ๅ–ไธฆ้ฉ—่ญ‰่ซ‹ๆฑ‚๏ผŒ่€Œไธไฝฟ็”จ FastAPI ่ˆ‡ Pydantic ็š„่‡ชๅ‹•ๅŠŸ่ƒฝ๏ผŒไฝ†ไป็„ถๅธŒๆœ›ๅœจ OpenAPI ็ตๆง‹ไธญๅฎš็พฉ่ฉฒ่ซ‹ๆฑ‚ใ€‚ + +ไฝ ๅฏไปฅ้€้Ž `openapi_extra` ่พฆๅˆฐ๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๆฒ’ๆœ‰ๅฎฃๅ‘Šไปปไฝ• Pydantic ๆจกๅž‹ใ€‚ไบ‹ๅฏฆไธŠ๏ผŒ่ซ‹ๆฑ‚ๆœฌๆ–‡็”š่‡ณไธๆœƒ่ขซ ่งฃๆž ็‚บ JSON๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅไปฅ `bytes` ่ฎ€ๅ–๏ผŒไธฆ็”ฑๅ‡ฝๅผ `magic_data_reader()` ไปฅๆŸ็จฎๆ–นๅผ่ฒ ่ฒฌ่งฃๆžใ€‚ + +ๅ„˜็ฎกๅฆ‚ๆญค๏ผŒๆˆ‘ๅ€‘ไปๅฏๅฎฃๅ‘Š่ซ‹ๆฑ‚ๆœฌๆ–‡็š„้ ๆœŸ็ตๆง‹ใ€‚ + +### ่‡ช่จ‚ OpenAPI Content-Type { #custom-openapi-content-type } + +็”จๅŒๆจฃ็š„ๆ–นๆณ•๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ไพ†ๅฎš็พฉ JSON Schema๏ผŒไธฆๆŠŠๅฎƒๅŒ…ๅซๅˆฐ่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ*็š„่‡ช่จ‚ OpenAPI ๅ€ๆฎตไธญใ€‚ + +ๅณไฝฟ่ซ‹ๆฑ‚ไธญ็š„่ณ‡ๆ–™ๅž‹ๅˆฅไธๆ˜ฏ JSON ไนŸๅฏไปฅ้€™้บผๅšใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅœจ้€™ๅ€‹ๆ‡‰็”จไธญ๏ผŒๆˆ‘ๅ€‘ไธไฝฟ็”จ FastAPI ๅ…งๅปบ็š„ๅพž Pydantic ๆจกๅž‹ๆ“ทๅ– JSON Schema ็š„ๅŠŸ่ƒฝ๏ผŒไนŸไธไฝฟ็”จ JSON ็š„่‡ชๅ‹•้ฉ—่ญ‰ใ€‚ๅฏฆ้š›ไธŠ๏ผŒๆˆ‘ๅ€‘ๅฐ‡่ซ‹ๆฑ‚็š„ content type ๅฎฃๅ‘Š็‚บ YAML๏ผŒ่€Œ้ž JSON๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +ๅ„˜็ฎกๆฒ’ๆœ‰ไฝฟ็”จ้ ่จญ็š„ๅ…งๅปบๅŠŸ่ƒฝ๏ผŒๆˆ‘ๅ€‘ไป้€้Ž Pydantic ๆจกๅž‹ๆ‰‹ๅ‹•็”ข็”Ÿๆƒณไปฅ YAML ๆŽฅๆ”ถไน‹่ณ‡ๆ–™็š„ JSON Schemaใ€‚ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘็›ดๆŽฅไฝฟ็”จ่ซ‹ๆฑ‚๏ผŒไธฆๅฐ‡ๆœฌๆ–‡ๆ“ทๅ–็‚บ `bytes`ใ€‚้€™่กจ็คบ FastAPI ็”š่‡ณไธๆœƒๅ˜—่ฉฆๆŠŠ่ซ‹ๆฑ‚่ฒ ่ผ‰่งฃๆž็‚บ JSONใ€‚ + +็„ถๅพŒๅœจ็จ‹ๅผไธญ็›ดๆŽฅ่งฃๆž่ฉฒ YAML ๅ…งๅฎน๏ผŒไธฆๅ†ๆฌกไฝฟ็”จ็›ธๅŒ็š„ Pydantic ๆจกๅž‹ไพ†้ฉ—่ญ‰่ฉฒ YAML ๅ…งๅฎน๏ผš + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip + +้€™่ฃกๆˆ‘ๅ€‘้‡่ค‡ไฝฟ็”จๅŒไธ€ๅ€‹ Pydantic ๆจกๅž‹ใ€‚ + +ไธ้ŽไนŸๅฏไปฅ็”จๅ…ถไป–ๆ–นๅผ้€ฒ่กŒ้ฉ—่ญ‰ใ€‚ + +/// diff --git a/docs/zh-hant/docs/advanced/response-change-status-code.md b/docs/zh-hant/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000..4b8d459ca2 --- /dev/null +++ b/docs/zh-hant/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# ๅ›žๆ‡‰ - ่ฎŠๆ›ด็‹€ๆ…‹็ขผ { #response-change-status-code } + +ไฝ ๅฏ่ƒฝๅทฒ็ถ“่ฎ€้Ž๏ผŒๅฏไปฅ่จญๅฎš้ ่จญ็š„[ๅ›žๆ‡‰็‹€ๆ…‹็ขผ](../tutorial/response-status-code.md){.internal-link target=_blank}ใ€‚ + +ไฝ†ๆœ‰ไบ›ๆƒ…ๆณไฝ ้œ€่ฆๅ›žๅ‚ณ่ˆ‡้ ่จญไธๅŒ็š„็‹€ๆ…‹็ขผใ€‚ + +## ไฝฟ็”จๆƒ…ๅขƒ { #use-case } + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ้ ่จญๆƒณๅ›žๅ‚ณ HTTP ็‹€ๆ…‹็ขผ "OK" `200`ใ€‚ + +ไฝ†ๅฆ‚ๆžœ่ณ‡ๆ–™ไธๅญ˜ๅœจ๏ผŒไฝ ๆƒณ่ฆๅปบ็ซ‹ๅฎƒ๏ผŒไธฆๅ›žๅ‚ณ HTTP ็‹€ๆ…‹็ขผ "CREATED" `201`ใ€‚ + +ๅŒๆ™‚ไฝ ไปๅธŒๆœ›่ƒฝ็”จ `response_model` ้Žๆฟพไธฆ่ฝ‰ๆ›ๆ‰€ๅ›žๅ‚ณ็š„่ณ‡ๆ–™ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Response` ๅƒๆ•ธใ€‚ + +## ไฝฟ็”จ `Response` ๅƒๆ•ธ { #use-a-response-parameter } + +ไฝ ๅฏไปฅๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰ไธญๅฎฃๅ‘Šไธ€ๅ€‹ `Response` ๅž‹ๅˆฅ็š„ๅƒๆ•ธ๏ผˆๅฐฑๅƒไฝ ๅฏไปฅๅฐ Cookies ๅ’Œๆจ™้ ญ้‚ฃๆจฃ๏ผ‰ใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจ้‚ฃๅ€‹ใ€Œ*ๆšซๆ™‚็š„*ใ€ๅ›žๆ‡‰็‰ฉไปถไธŠ่จญๅฎš `status_code`ใ€‚ + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +็„ถๅพŒไฝ ๅฏไปฅ็…งๅธธๅ›žๅ‚ณไปปไฝ•้œ€่ฆ็š„็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ `dict`ใ€่ณ‡ๆ–™ๅบซๆจกๅž‹็ญ‰๏ผ‰ใ€‚ + +่‹ฅไฝ ๅฎฃๅ‘Šไบ† `response_model`๏ผŒๅฎƒไปๆœƒ่ขซ็”จไพ†้Žๆฟพไธฆ่ฝ‰ๆ›ไฝ ๅ›žๅ‚ณ็š„็‰ฉไปถใ€‚ + +FastAPI ๆœƒไฝฟ็”จ้‚ฃๅ€‹ใ€Œ*ๆšซๆ™‚็š„*ใ€ๅ›žๆ‡‰ไพ†ๅ–ๅพ—็‹€ๆ…‹็ขผ๏ผˆไปฅๅŠ Cookies ๅ’Œๆจ™้ ญ๏ผ‰๏ผŒไธฆๅฐ‡ๅฎƒๅ€‘ๆ”พๅ…ฅๆœ€็ต‚ๅ›žๆ‡‰ไธญ๏ผ›ๆœ€็ต‚ๅ›žๆ‡‰ๅŒ…ๅซไฝ ๅ›žๅ‚ณ็š„ๅ€ผ๏ผŒไธ”ๆœƒ่ขซไปปไฝ• `response_model` ้Žๆฟพใ€‚ + +ไฝ ไนŸๅฏไปฅๅœจ็›ธไพๆ€ง๏ผˆdependencies๏ผ‰ไธญๅฎฃๅ‘Š `Response` ๅƒๆ•ธ๏ผŒไธฆๅœจๅ…ถไธญ่จญๅฎš็‹€ๆ…‹็ขผใ€‚ไฝ†่ซ‹ๆณจๆ„๏ผŒๆœ€ๅพŒ่ขซ่จญๅฎš็š„ๅ€ผๆœƒ็”Ÿๆ•ˆใ€‚ diff --git a/docs/zh-hant/docs/advanced/response-cookies.md b/docs/zh-hant/docs/advanced/response-cookies.md new file mode 100644 index 0000000000..b7225d571c --- /dev/null +++ b/docs/zh-hant/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# ๅ›žๆ‡‰ Cookie { #response-cookies } + +## ไฝฟ็”จ `Response` ๅƒๆ•ธ { #use-a-response-parameter } + +ไฝ ๅฏไปฅๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰ไธญๅฎฃๅ‘Šไธ€ๅ€‹ๅž‹ๅˆฅ็‚บ `Response` ็š„ๅƒๆ•ธใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจ้‚ฃๅ€‹ใ€Œๆšซๆ™‚ใ€็š„ `Response` ็‰ฉไปถไธŠ่จญๅฎš Cookieใ€‚ + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +ไน‹ๅพŒๅฆ‚ๅธธๅ›žๅ‚ณไฝ ้œ€่ฆ็š„ไปปไฝ•็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ `dict`ใ€่ณ‡ๆ–™ๅบซๆจกๅž‹็ญ‰๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ๅฎฃๅ‘Šไบ† `response_model`๏ผŒๅฎƒไปๆœƒ็”จไพ†้Žๆฟพไธฆ่ฝ‰ๆ›ไฝ ๅ›žๅ‚ณ็š„็‰ฉไปถใ€‚ + +FastAPI ๆœƒไฝฟ็”จ้‚ฃๅ€‹ๆšซๆ™‚็š„ `Response` ๅ–ๅ‡บ Cookie๏ผˆไปฅๅŠๆจ™้ ญ่ˆ‡็‹€ๆ…‹็ขผ๏ผ‰๏ผŒไธฆๅฐ‡ๅฎƒๅ€‘ๆ”พๅ…ฅๆœ€็ต‚ๅ›žๆ‡‰๏ผ›ๆœ€็ต‚ๅ›žๆ‡‰ๅŒ…ๅซไฝ ๅ›žๅ‚ณ็š„ๅ€ผ๏ผŒไธ”ๆœƒๅฅ—็”จไปปไฝ• `response_model` ็š„้Žๆฟพใ€‚ + +ไฝ ไนŸๅฏไปฅๅœจ็›ธไพ้ …๏ผˆdependencies๏ผ‰ไธญๅฎฃๅ‘Š `Response` ๅƒๆ•ธ๏ผŒไธฆๅœจๅ…ถไธญ่จญๅฎš Cookie๏ผˆ่ˆ‡ๆจ™้ ญ๏ผ‰ใ€‚ + +## ็›ดๆŽฅๅ›žๅ‚ณ `Response` { #return-a-response-directly } + +็•ถไฝ ๅœจ็จ‹ๅผ็ขผไธญ็›ดๆŽฅๅ›žๅ‚ณ `Response` ๆ™‚๏ผŒไนŸๅฏไปฅๅปบ็ซ‹ Cookieใ€‚ + +่ฆ้€™้บผๅš๏ผŒไฝ ๅฏไปฅไพ็…ง [็›ดๆŽฅๅ›žๅ‚ณ Response](response-directly.md){.internal-link target=_blank} ไธญ็š„่ชชๆ˜Žๅปบ็ซ‹ไธ€ๅ€‹ๅ›žๆ‡‰ใ€‚ + +ๆŽฅ่‘—ๅœจๅ…ถไธญ่จญๅฎš Cookie๏ผŒ็„ถๅพŒๅ›žๅ‚ณๅฎƒ๏ผš + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | ๆ็คบ + +่ซ‹ๆณจๆ„๏ผŒๅฆ‚ๆžœไฝ ไธๆ˜ฏไฝฟ็”จ `Response` ๅƒๆ•ธ๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅๅ›žๅ‚ณไธ€ๅ€‹ `Response`๏ผŒFastAPI ๆœƒๅŽŸๆจฃๅ›žๅ‚ณๅฎƒใ€‚ + +ๅ› ๆญคไฝ ๅฟ…้ ˆ็ขบไฟ่ณ‡ๆ–™ๅž‹ๅˆฅๆญฃ็ขบ๏ผ›ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅ›žๅ‚ณ็š„ๆ˜ฏ `JSONResponse`๏ผŒๅฐฑ่ฆ็ขบไฟ่ณ‡ๆ–™ๅฏ่ˆ‡ JSON ็›ธๅฎนใ€‚ + +ๅŒๆ™‚ไนŸ่ฆ็ขบ่ชๆฒ’ๆœ‰้€ๅ‡บๅŽŸๆœฌๆ‡‰่ฉฒ็”ฑ `response_model` ้Žๆฟพ็š„่ณ‡ๆ–™ใ€‚ + +/// + +### ๆ›ดๅคš่ณ‡่จŠ { #more-info } + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import Response` ๆˆ– `from starlette.responses import JSONResponse`ใ€‚ + +็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…๏ผŒFastAPI ไนŸๅฐ‡็›ธๅŒ็š„ `starlette.responses` ้€้Ž `fastapi.responses` ๆไพ›ใ€‚ไธ้Ž๏ผŒๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅˆฅ้ƒฝ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +ๅฆๅค–็”ฑๆ–ผ `Response` ๅธธ็”จๆ–ผ่จญๅฎšๆจ™้ ญ่ˆ‡ Cookie๏ผŒFastAPI ไนŸๅœจ `fastapi.Response` ๆไพ›ไบ†ๅฎƒใ€‚ + +/// + +ๆƒณๆŸฅ็œ‹ๆ‰€ๆœ‰ๅฏ็”จ็š„ๅƒๆ•ธ่ˆ‡้ธ้ …๏ผŒ่ซ‹ๅƒ้–ฑ Starlette ๆ–‡ไปถใ€‚ diff --git a/docs/zh-hant/docs/advanced/response-directly.md b/docs/zh-hant/docs/advanced/response-directly.md new file mode 100644 index 0000000000..5603548934 --- /dev/null +++ b/docs/zh-hant/docs/advanced/response-directly.md @@ -0,0 +1,65 @@ +# ็›ดๆŽฅๅ›žๅ‚ณ Response { #return-a-response-directly } + +็•ถไฝ ๅปบ็ซ‹ไธ€ๅ€‹ **FastAPI** ็š„่ทฏๅพ‘ๆ“ไฝœ (path operation) ๆ™‚๏ผŒ้€šๅธธๅฏไปฅๅพžไธญๅ›žๅ‚ณไปปไฝ•่ณ‡ๆ–™๏ผš`dict`ใ€`list`ใ€Pydantic ๆจกๅž‹ใ€่ณ‡ๆ–™ๅบซๆจกๅž‹็ญ‰ใ€‚ + +้ ่จญๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒไฝฟ็”จๅœจ[JSON ็›ธๅฎน็ทจ็ขผๅ™จ](../tutorial/encoder.md){.internal-link target=_blank}ไธญ่ชชๆ˜Ž็š„ `jsonable_encoder`๏ผŒ่‡ชๅ‹•ๅฐ‡ๅ›žๅ‚ณๅ€ผ่ฝ‰็‚บ JSONใ€‚ + +็„ถๅพŒๅœจๅน•ๅพŒ๏ผŒๅฎƒๆœƒๆŠŠ้€™ไบ›่ˆ‡ JSON ็›ธๅฎน็š„่ณ‡ๆ–™๏ผˆไพ‹ๅฆ‚ `dict`๏ผ‰ๆ”พ้€ฒ `JSONResponse`๏ผŒ็”จไพ†ๆŠŠๅ›žๆ‡‰ๅ‚ณๅ›ž็ตฆ็”จๆˆถ็ซฏใ€‚ + +ไฝ†ไฝ ไนŸๅฏไปฅ็›ดๆŽฅๅพž่ทฏๅพ‘ๆ“ไฝœๅ›žๅ‚ณ `JSONResponse`ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็•ถไฝ ้œ€่ฆๅ›žๅ‚ณ่‡ช่จ‚็š„ headers ๆˆ– cookies ๆ™‚ๅฐฑๅพˆๆœ‰็”จใ€‚ + +## ๅ›žๅ‚ณ `Response` { #return-a-response } + +ๅ…ถๅฏฆ๏ผŒไฝ ๅฏไปฅๅ›žๅ‚ณไปปไฝ• `Response`๏ผŒๆˆ–ๅ…ถไปปไฝ•ๅญ้กžๅˆฅใ€‚ + +/// tip + +`JSONResponse` ๆœฌ่บซๅฐฑๆ˜ฏ `Response` ็š„ๅญ้กžๅˆฅใ€‚ + +/// + +็•ถไฝ ๅ›žๅ‚ณไธ€ๅ€‹ `Response` ๆ™‚๏ผŒ**FastAPI** ๆœƒ็›ดๆŽฅๅ‚ณ้žๅฎƒใ€‚ + +ๅฎƒไธๆœƒๅฐ Pydantic ๆจกๅž‹ๅšไปปไฝ•่ณ‡ๆ–™่ฝ‰ๆ›๏ผŒไนŸไธๆœƒๆŠŠๅ…งๅฎน่ฝ‰ๆˆๅ…ถไป–ๅž‹ๅˆฅ็ญ‰ใ€‚ + +้€™็ตฆไบ†ไฝ ๅพˆๅคง็š„ๅฝˆๆ€งใ€‚ไฝ ๅฏไปฅๅ›žๅ‚ณไปปไฝ•่ณ‡ๆ–™ๅž‹ๅˆฅใ€่ฆ†ๅฏซไปปไฝ•่ณ‡ๆ–™ๅฎฃๅ‘Šๆˆ–้ฉ—่ญ‰็ญ‰ใ€‚ + +## ๅœจ `Response` ไธญไฝฟ็”จ `jsonable_encoder` { #using-the-jsonable-encoder-in-a-response } + +ๅ› ็‚บ **FastAPI** ไธๆœƒๅฐไฝ ๅ›žๅ‚ณ็š„ `Response` ๅšไปปไฝ•ๆ›ดๅ‹•๏ผŒไฝ ้œ€่ฆ่‡ช่กŒ็ขบไฟๅฎƒ็š„ๅ…งๅฎนๅทฒ็ถ“ๆบ–ๅ‚™ๅฅฝใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ไธ่ƒฝ็›ดๆŽฅๆŠŠไธ€ๅ€‹ Pydantic ๆจกๅž‹ๆ”พ้€ฒ `JSONResponse`๏ผŒ้œ€่ฆๅ…ˆๆŠŠๅฎƒ่ฝ‰ๆˆ `dict`๏ผŒไธฆๅฐ‡ๆ‰€ๆœ‰่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผˆๅƒๆ˜ฏ `datetime`ใ€`UUID` ็ญ‰๏ผ‰่ฝ‰ๆˆ่ˆ‡ JSON ็›ธๅฎน็š„ๅž‹ๅˆฅใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅๅ…ˆ็”จ `jsonable_encoder` ๆŠŠ่ณ‡ๆ–™่ฝ‰ๅฅฝ๏ผŒๅ†ๅ‚ณ็ตฆๅ›žๆ‡‰็‰ฉไปถ๏ผš + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import JSONResponse`ใ€‚ + +**FastAPI** ็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…๏ผŒๅฐ‡ `starlette.responses` ไนŸๆไพ›็‚บ `fastapi.responses`ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅž‹ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +## ๅ›žๅ‚ณ่‡ช่จ‚ `Response` { #returning-a-custom-response } + +ไธŠ้ข็š„็ฏ„ไพ‹ๅฑ•็คบไบ†ๆ‰€้œ€็š„ๅ„ๅ€‹้ƒจๅˆ†๏ผŒไฝ†็›ฎๅ‰้‚„ไธๅคชๅฏฆ็”จ๏ผŒๅ› ็‚บไฝ ๅ…ถๅฏฆๅฏไปฅ็›ดๆŽฅๅ›žๅ‚ณ `item`๏ผŒ**FastAPI** ๅฐฑๆœƒๅนซไฝ ๆŠŠๅฎƒๆ”พ้€ฒ `JSONResponse`๏ผŒ่ฝ‰ๆˆ `dict` ็ญ‰๏ผŒ้€™ไบ›้ƒฝๆ˜ฏ้ ่จญ่กŒ็‚บใ€‚ + +็พๅœจไพ†็œ‹็œ‹ๅฆ‚ไฝ•็”จๅฎƒไพ†ๅ›žๅ‚ณ่‡ช่จ‚ๅ›žๆ‡‰ใ€‚ + +ๅ‡่จญไฝ ๆƒณ่ฆๅ›žๅ‚ณไธ€ๅ€‹ XML ๅ›žๆ‡‰ใ€‚ + +ไฝ ๅฏไปฅๆŠŠ XML ๅ…งๅฎนๆ”พ้€ฒไธ€ๅ€‹ๅญ—ไธฒ๏ผŒๆŠŠๅฎƒๆ”พ้€ฒ `Response`๏ผŒ็„ถๅพŒๅ›žๅ‚ณๅฎƒ๏ผš + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## ๆณจๆ„ไบ‹้ … { #notes } + +็•ถไฝ ็›ดๆŽฅๅ›žๅ‚ณ `Response` ๆ™‚๏ผŒๅ…ถ่ณ‡ๆ–™ไธๆœƒ่‡ชๅ‹•่ขซ้ฉ—่ญ‰ใ€่ฝ‰ๆ›๏ผˆๅบๅˆ—ๅŒ–๏ผ‰ๆˆ–ๆ–‡ไปถๅŒ–ใ€‚ + +ไฝ†ไฝ ไป็„ถๅฏไปฅไพ็…ง[ๅœจ OpenAPI ไธญ็š„้กๅค–ๅ›žๆ‡‰](additional-responses.md){.internal-link target=_blank}ไธญ็š„่ชชๆ˜Ž้€ฒ่กŒๆ–‡ไปถๅŒ–ใ€‚ + +ๅœจๅพŒ็บŒ็ซ ็ฏ€ไธญ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฆ‚ไฝ•ๅœจไปไฟๆœ‰่‡ชๅ‹•่ณ‡ๆ–™่ฝ‰ๆ›ใ€ๆ–‡ไปถๅŒ–็ญ‰็š„ๅŒๆ™‚๏ผŒไฝฟ็”จ๏ผๅฎฃๅ‘Š้€™ไบ›่‡ช่จ‚็š„ `Response`ใ€‚ diff --git a/docs/zh-hant/docs/advanced/response-headers.md b/docs/zh-hant/docs/advanced/response-headers.md new file mode 100644 index 0000000000..6e32ca1b39 --- /dev/null +++ b/docs/zh-hant/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# ๅ›žๆ‡‰ๆจ™้ ญ { #response-headers } + +## ไฝฟ็”จ `Response` ๅƒๆ•ธ { #use-a-response-parameter } + +ไฝ ๅฏไปฅๅœจไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰*ไธญๅฎฃๅ‘Šไธ€ๅ€‹ `Response` ๅž‹ๅˆฅ็š„ๅƒๆ•ธ๏ผˆๅฐฑๅƒ่™•็† Cookie ไธ€ๆจฃ๏ผ‰ใ€‚ + +็„ถๅพŒไฝ ๅฏไปฅๅœจ้‚ฃๅ€‹*ๆšซๆ™‚ๆ€ง็š„* `Response` ็‰ฉไปถไธŠ่จญๅฎšๆจ™้ ญใ€‚ + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅƒๅนณๅธธไธ€ๆจฃๅ›žๅ‚ณไปปไฝ•ไฝ ้œ€่ฆ็š„็‰ฉไปถ๏ผˆ`dict`ใ€่ณ‡ๆ–™ๅบซๆจกๅž‹็ญ‰๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ๅฎฃๅ‘Šไบ† `response_model`๏ผŒๅฎƒไปๆœƒ็”จไพ†้Žๆฟพไธฆ่ฝ‰ๆ›ไฝ ๅ›žๅ‚ณ็š„็‰ฉไปถใ€‚ + +FastAPI ๆœƒไฝฟ็”จ้‚ฃๅ€‹ๆšซๆ™‚ๆ€ง็š„ๅ›žๆ‡‰ไพ†ๆ“ทๅ–ๆจ™้ ญ๏ผˆ้‚„ๆœ‰ Cookie ่ˆ‡็‹€ๆ…‹็ขผ๏ผ‰๏ผŒไธฆๆŠŠๅฎƒๅ€‘ๆ”พๅˆฐๆœ€็ต‚ๅ›žๆ‡‰ไธญ๏ผ›ๆœ€็ต‚ๅ›žๆ‡‰ๅŒ…ๅซไฝ ๅ›žๅ‚ณ็š„ๅ€ผ๏ผŒไธ”ๆœƒไพไปปไฝ• `response_model` ้€ฒ่กŒ้Žๆฟพใ€‚ + +ไฝ ไนŸๅฏไปฅๅœจไพ่ณดไธญๅฎฃๅ‘Š `Response` ๅƒๆ•ธ๏ผŒไธฆๅœจๅ…ถไธญ่จญๅฎšๆจ™้ ญ๏ผˆ่ˆ‡ Cookie๏ผ‰ใ€‚ + +## ็›ดๆŽฅๅ›žๅ‚ณ `Response` { #return-a-response-directly } + +็•ถไฝ ็›ดๆŽฅๅ›žๅ‚ณ `Response` ๆ™‚๏ผŒไนŸ่ƒฝๅŠ ๅ…ฅๆจ™้ ญใ€‚ + +ไพ็…ง[็›ดๆŽฅๅ›žๅ‚ณ Response](response-directly.md){.internal-link target=_blank}ไธญ็š„่ชชๆ˜Žๅปบ็ซ‹ๅ›žๆ‡‰๏ผŒไธฆๆŠŠๆจ™้ ญไฝœ็‚บ้กๅค–ๅƒๆ•ธๅ‚ณๅ…ฅ๏ผš + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import Response` ๆˆ– `from starlette.responses import JSONResponse`ใ€‚ + +็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…๏ผŒFastAPI ๆไพ›่ˆ‡ `starlette.responses` ็›ธๅŒ็š„ๅ…งๅฎนๆ–ผ `fastapi.responses`ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅž‹ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +็”ฑๆ–ผ `Response` ๅธธ็”จไพ†่จญๅฎšๆจ™้ ญ่ˆ‡ Cookie๏ผŒFastAPI ไนŸๅœจ `fastapi.Response` ๆไพ›ไบ†ๅฎƒใ€‚ + +/// + +## ่‡ช่จ‚ๆจ™้ ญ { #custom-headers } + +่ซ‹่จ˜ไฝ๏ผŒๅฐˆๆœ‰็š„่‡ช่จ‚ๆจ™้ ญๅฏไปฅไฝฟ็”จ `X-` ๅ‰็ถดไพ†ๆ–ฐๅขžใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ๆœ‰่‡ช่จ‚ๆจ™้ ญไธฆๅธŒๆœ›็€่ฆฝๅ™จ็ซฏ็š„ๅฎขๆˆถ็ซฏ่ƒฝ็œ‹่ฆ‹ๅฎƒๅ€‘๏ผŒไฝ ้œ€่ฆๆŠŠ้€™ไบ›ๆจ™้ ญๅŠ ๅ…ฅๅˆฐ CORS ่จญๅฎšไธญ๏ผˆ่ฉณ่ฆ‹ [CORS๏ผˆ่ทจไพ†ๆบ่ณ‡ๆบๅ…ฑ็”จ๏ผ‰](../tutorial/cors.md){.internal-link target=_blank}๏ผ‰๏ผŒไฝฟ็”จๅœจStarlette ็š„ CORS ๆ–‡ไปถไธญ่จ˜่ผ‰็š„ `expose_headers` ๅƒๆ•ธใ€‚ diff --git a/docs/zh-hant/docs/advanced/security/http-basic-auth.md b/docs/zh-hant/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..ea3d528292 --- /dev/null +++ b/docs/zh-hant/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP ๅŸบๆœฌ่ช่ญ‰ { #http-basic-auth } + +ๅœจๆœ€็ฐกๅ–ฎ็š„ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จ HTTP Basic ่ช่ญ‰ใ€‚ + +ๅœจ HTTP Basic ่ช่ญ‰ไธญ๏ผŒๆ‡‰็”จ็จ‹ๅผๆœƒๆœŸๅพ…ไธ€ๅ€‹ๅŒ…ๅซไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผ็š„ๆจ™้ ญใ€‚ + +ๅฆ‚ๆžœๆฒ’ๆœ‰ๆŽฅๆ”ถๅˆฐ๏ผŒๆœƒๅ›žๅ‚ณ HTTP 401ใ€ŒUnauthorizedใ€้Œฏ่ชคใ€‚ + +ไธฆๅ›žๅ‚ณไธ€ๅ€‹ `WWW-Authenticate` ๆจ™้ ญ๏ผŒๅ…ถๅ€ผ็‚บ `Basic`๏ผŒไปฅๅŠๅฏ้ธ็š„ `realm` ๅƒๆ•ธใ€‚ + +้€™ๆœƒๅ‘Š่จด็€่ฆฝๅ™จ้กฏ็คบๅ…งๅปบ็š„ไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผๆ็คบ่ฆ–็ช—ใ€‚ + +ๆŽฅ่‘—๏ผŒ็•ถไฝ ่ผธๅ…ฅ่ฉฒไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผๆ™‚๏ผŒ็€่ฆฝๅ™จๆœƒ่‡ชๅ‹•ๅœจๆจ™้ ญไธญ้€ๅ‡บๅฎƒๅ€‘ใ€‚ + +## ็ฐกๅ–ฎ็š„ HTTP ๅŸบๆœฌ่ช่ญ‰ { #simple-http-basic-auth } + +- ๅŒฏๅ…ฅ `HTTPBasic` ่ˆ‡ `HTTPBasicCredentials`ใ€‚ +- ไฝฟ็”จ `HTTPBasic` ๅปบ็ซ‹ไธ€ๅ€‹ใ€Œ`security` schemeใ€ใ€‚ +- ๅœจไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœ*ไธญไปฅไพ่ณด็š„ๆ–นๅผไฝฟ็”จ่ฉฒ `security`ใ€‚ +- ๅฎƒๆœƒๅ›žๅ‚ณไธ€ๅ€‹ `HTTPBasicCredentials` ๅž‹ๅˆฅ็š„็‰ฉไปถ๏ผš + - ๅ…ถไธญๅŒ…ๅซๅ‚ณไพ†็š„ `username` ่ˆ‡ `password`ใ€‚ + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +็•ถไฝ ็ฌฌไธ€ๆฌกๅ˜—่ฉฆ้–‹ๅ•Ÿ่ฉฒ URL๏ผˆๆˆ–ๅœจๆ–‡ไปถไธญ้ปžๆ“Š "Execute" ๆŒ‰้ˆ•๏ผ‰ๆ™‚๏ผŒ็€่ฆฝๅ™จๆœƒ่ฆๆฑ‚่ผธๅ…ฅไฝ ็š„ไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผ๏ผš + + + +## ๆชขๆŸฅไฝฟ็”จ่€…ๅ็จฑ { #check-the-username } + +ไปฅไธ‹ๆ˜ฏไธ€ๅ€‹ๆ›ดๅฎŒๆ•ด็š„็ฏ„ไพ‹ใ€‚ + +ไฝฟ็”จไธ€ๅ€‹ไพ่ณดไพ†ๆชขๆŸฅไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผๆ˜ฏๅฆๆญฃ็ขบใ€‚ + +็‚บๆญค๏ผŒไฝฟ็”จ Python ๆจ™ๆบ–ๆจก็ต„ `secrets` ไพ†ๆฏ”ๅฐไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผใ€‚ + +`secrets.compare_digest()` ้œ€่ฆๆŽฅๆ”ถ `bytes`๏ผŒๆˆ–ๆ˜ฏๅชๅŒ…ๅซ ASCII ๅญ—ๅ…ƒ๏ผˆ่‹ฑๆ–‡ๅญ—็ฌฆ๏ผ‰็š„ `str`ใ€‚้€™่กจ็คบๅฎƒ็„กๆณ•่™•็†ๅƒ `รก` ้€™ๆจฃ็š„ๅญ—ๅ…ƒ๏ผŒไพ‹ๅฆ‚ `Sebastiรกn`ใ€‚ + +็‚บไบ†่™•็†้€™้ปž๏ผŒๆˆ‘ๅ€‘ๆœƒๅ…ˆๅฐ‡ `username` ่ˆ‡ `password` ไปฅ UTF-8 ็ทจ็ขผๆˆ `bytes`ใ€‚ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅฏไปฅไฝฟ็”จ `secrets.compare_digest()` ไพ†็ขบ่ช `credentials.username` ็ญ‰ๆ–ผ `"stanleyjobson"`๏ผŒ่€Œ `credentials.password` ็ญ‰ๆ–ผ `"swordfish"`ใ€‚ + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +้€™ๅคง่‡ด็ญ‰ๅŒๆ–ผ๏ผš + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # ๅ›žๅ‚ณ้Œฏ่ชค + ... +``` + +ไฝ†่—‰็”ฑไฝฟ็”จ `secrets.compare_digest()`๏ผŒๅฏไปฅ้˜ฒ็ฆฆไธ€็จฎ็จฑ็‚บใ€Œ่จˆๆ™‚ๆ”ปๆ“Šใ€็š„ๆ”ปๆ“Šใ€‚ + +### ่จˆๆ™‚ๆ”ปๆ“Š { #timing-attacks } + +ไป€้บผๆ˜ฏใ€Œ่จˆๆ™‚ๆ”ปๆ“Šใ€ๅ‘ข๏ผŸ + +ๆƒณๅƒๆœ‰ๆ”ปๆ“Š่€…ๅœจๅ˜—่ฉฆ็Œœๆธฌไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผใ€‚ + +ไป–ๅ€‘้€ๅ‡บไธ€ๅ€‹ๅธถๆœ‰ไฝฟ็”จ่€…ๅ็จฑ `johndoe` ่ˆ‡ๅฏ†็ขผ `love123` ็š„่ซ‹ๆฑ‚ใ€‚ + +ๆŽฅ่‘—๏ผŒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไธญ็š„ Python ็จ‹ๅผ็ขผ็ญ‰ๅŒๆ–ผ๏ผš + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +็•ถ Python ๆฏ”่ผƒ `johndoe` ็š„็ฌฌไธ€ๅ€‹ `j` ่ˆ‡ `stanleyjobson` ็š„็ฌฌไธ€ๅ€‹ `s` ๆ™‚๏ผŒๆœƒ็ซ‹ๅˆปๅ›žๅ‚ณ `False`๏ผŒๅ› ็‚บๅทฒ็ถ“็Ÿฅ้“ๅ…ฉๅ€‹ๅญ—ไธฒไธๅŒ๏ผŒ่ฆบๅพ—ใ€Œๆฒ’ๅฟ…่ฆๆตช่ฒป่จˆ็ฎ—่ณ‡ๆบ็นผ็บŒๆฏ”่ผƒๅ‰ฉไธ‹็š„ๅญ—ๅ…ƒใ€ใ€‚ไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไพฟๆœƒๅ›žๆ‡‰ใ€ŒIncorrect username or passwordใ€ใ€‚ + +ไฝ†ๆŽฅ่‘—ๆ”ปๆ“Š่€…ๆ”น็”จไฝฟ็”จ่€…ๅ็จฑ `stanleyjobsox` ่ˆ‡ๅฏ†็ขผ `love123` ๅ˜—่ฉฆใ€‚ + +ไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ็จ‹ๅผ็ขผๆœƒๅš้กžไผผ๏ผš + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python ๆœƒๅฟ…้ ˆๅ…ˆๆฏ”่ผƒๅฎŒๆ•ด็š„ `stanleyjobso`๏ผˆๅœจ `stanleyjobsox` ่ˆ‡ `stanleyjobson` ไน‹ไธญ้ƒฝไธ€ๆจฃ๏ผ‰๏ผŒๆ‰ๆœƒ็™ผ็พๅ…ฉๅ€‹ๅญ—ไธฒไธๅŒใ€‚ๅ› ๆญคๅ›ž่ฆ†ใ€ŒIncorrect username or passwordใ€ๆœƒๅคš่Šฑไธ€ไบ›ๅพฎ็ง’ใ€‚ + +#### ๅ›žๆ‡‰ๆ™‚้–“ๅนซไบ†ๆ”ปๆ“Š่€… { #the-time-to-answer-helps-the-attackers } + +ๆญคๆ™‚๏ผŒ้€้Ž่ง€ๅฏŸไผบๆœๅ™จๅ›ž่ฆ†ใ€ŒIncorrect username or passwordใ€ๅคš่Šฑไบ†ๅนพๅ€‹ๅพฎ็ง’๏ผŒๆ”ปๆ“Š่€…ๅฐฑ็Ÿฅ้“ไป–ๅ€‘ๆœ‰ๆŸไบ›ๅœฐๆ–น็Œœๅฐไบ†๏ผŒๅ‰ๅนพๅ€‹ๅญ—ๆฏๆ˜ฏๆญฃ็ขบ็š„ใ€‚ + +ๆŽฅ่‘—ไป–ๅ€‘ๆœƒๅ†ๅ˜—่ฉฆ๏ผŒ็Ÿฅ้“ๅฎƒๆ›ดๅฏ่ƒฝๆŽฅ่ฟ‘ `stanleyjobsox` ่€Œไธๆ˜ฏ `johndoe`ใ€‚ + +#### ใ€Œๅฐˆๆฅญใ€็š„ๆ”ปๆ“Š { #a-professional-attack } + +็•ถ็„ถ๏ผŒๆ”ปๆ“Š่€…ไธๆœƒๆ‰‹ๅ‹•ๅ˜—่ฉฆ้€™ไธ€ๅˆ‡๏ผŒไป–ๅ€‘ๆœƒๅฏซ็จ‹ๅผไพ†ๅš๏ผŒๅฏ่ƒฝๆฏ็ง’้€ฒ่กŒไธŠๅƒๆˆ–ไธŠ็™พ่ฌๆฌกๆธฌ่ฉฆ๏ผŒไธ€ๆฌกๅชๅคš็Œœไธญไธ€ๅ€‹ๆญฃ็ขบๅญ—ๆฏใ€‚ + +ไฝ†้€™ๆจฃๅš๏ผŒๅนพๅˆ†้˜ๆˆ–ๅนพๅฐๆ™‚ๅ…ง๏ผŒไป–ๅ€‘ๅฐฑ่ƒฝๅœจๆˆ‘ๅ€‘ๆ‡‰็”จ็จ‹ๅผใ€Œๅ”ๅŠฉใ€ไธ‹๏ผŒๅƒ…้ ๅ›žๆ‡‰ๆ™‚้–“ๅฐฑ็Œœๅ‡บๆญฃ็ขบ็š„ไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผใ€‚ + +#### ็”จ `secrets.compare_digest()` ไฟฎๆญฃ { #fix-it-with-secrets-compare-digest } + +ไฝ†ๅœจๆˆ‘ๅ€‘็š„็จ‹ๅผ็ขผไธญๅฏฆ้š›ไฝฟ็”จ็š„ๆ˜ฏ `secrets.compare_digest()`ใ€‚ + +็ฐก่€Œ่จ€ไน‹๏ผŒๅฐ‡ `stanleyjobsox` ่ˆ‡ `stanleyjobson` ๆฏ”่ผƒๆ‰€่Šฑ็š„ๆ™‚้–“๏ผŒๆœƒ่ˆ‡ๅฐ‡ `johndoe` ่ˆ‡ `stanleyjobson` ๆฏ”่ผƒๆ‰€่Šฑ็š„ๆ™‚้–“็›ธๅŒ๏ผ›ๅฏ†็ขผไนŸไธ€ๆจฃใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅœจๆ‡‰็”จ็จ‹ๅผ็จ‹ๅผ็ขผไธญไฝฟ็”จ `secrets.compare_digest()`๏ผŒๅฐฑ่ƒฝๅฎ‰ๅ…จๅœฐ้˜ฒ็ฆฆ้€™ๆ•ด้กž็š„ๅฎ‰ๅ…จๆ”ปๆ“Šใ€‚ + +### ๅ›žๅ‚ณ้Œฏ่ชค { #return-the-error } + +ๅœจๅตๆธฌๅˆฐๆ†‘่ญ‰ไธๆญฃ็ขบไน‹ๅพŒ๏ผŒๅ›žๅ‚ณไธ€ๅ€‹็‹€ๆ…‹็ขผ็‚บ 401 ็š„ `HTTPException`๏ผˆ่ˆ‡ๆœชๆไพ›ๆ†‘่ญ‰ๆ™‚็›ธๅŒ๏ผ‰๏ผŒไธฆๅŠ ไธŠ `WWW-Authenticate` ๆจ™้ ญ๏ผŒ่ฎ“็€่ฆฝๅ™จๅ†ๆฌก้กฏ็คบ็™ปๅ…ฅๆ็คบ๏ผš + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/zh-hant/docs/advanced/security/index.md b/docs/zh-hant/docs/advanced/security/index.md new file mode 100644 index 0000000000..9a4cfbbfd6 --- /dev/null +++ b/docs/zh-hant/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# ้€ฒ้šŽๅฎ‰ๅ…จๆ€ง { #advanced-security } + +## ้กๅค–ๅŠŸ่ƒฝ { #additional-features } + +้™คไบ†[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—๏ผšๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank}ไธญๆถต่“‹็š„ๅ…งๅฎนๅค–๏ผŒ้‚„ๆœ‰ไธ€ไบ›็”จไพ†่™•็†ๅฎ‰ๅ…จๆ€ง็š„้กๅค–ๅŠŸ่ƒฝใ€‚ + +/// tip + +ไปฅไธ‹ๅ„็ฏ€ไธไธ€ๅฎšๆ˜ฏใ€Œ้€ฒ้šŽใ€ๅ…งๅฎนใ€‚ + +่€Œไธ”ไฝ ็š„ๆƒ…ๅขƒๅพˆๅฏ่ƒฝๅฏไปฅๅœจๅ…ถไธญๆ‰พๅˆฐ่งฃๆฑบๆ–นๆกˆใ€‚ + +/// + +## ่ซ‹ๅ…ˆ้–ฑ่ฎ€ๆ•™ๅญธ { #read-the-tutorial-first } + +ไปฅไธ‹ๅ„็ฏ€ๅ‡่จญไฝ ๅทฒ้–ฑ่ฎ€ไธป่ฆ็š„[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—๏ผšๅฎ‰ๅ…จๆ€ง](../../tutorial/security/index.md){.internal-link target=_blank}ใ€‚ + +ๅฎƒๅ€‘้ƒฝๅปบ็ซ‹ๅœจ็›ธๅŒ็š„ๆฆ‚ๅฟตไน‹ไธŠ๏ผŒไฝ†ๆไพ›ไธ€ไบ›้กๅค–็š„ๅŠŸ่ƒฝใ€‚ diff --git a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..029572d433 --- /dev/null +++ b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 ็ฏ„ๅœ๏ผˆscopes๏ผ‰ { #oauth2-scopes } + +ไฝ ๅฏไปฅ็›ดๆŽฅๅœจ FastAPI ไธญไฝฟ็”จ OAuth2 ็š„ scopes๏ผŒๅทฒๆ•ดๅˆๅฏ็„ก็ธซ้‹ไฝœใ€‚ + +้€™่ƒฝ่ฎ“ไฝ ๅœจ OpenAPI ๆ‡‰็”จ๏ผˆไปฅๅŠ API ๆ–‡ไปถ๏ผ‰ไธญ๏ผŒไพ็…ง OAuth2 ๆจ™ๆบ–๏ผŒๅฏฆไฝœๆ›ด็ดฐ็ฒ’ๅบฆ็š„ๆฌŠ้™็ณป็ตฑใ€‚ + +ๅธถๆœ‰ scopes ็š„ OAuth2 ๆ˜ฏ่จฑๅคšๅคงๅž‹่บซๅˆ†้ฉ—่ญ‰ๆไพ›่€…๏ผˆๅฆ‚ Facebookใ€Googleใ€GitHubใ€Microsoftใ€X๏ผˆTwitter๏ผ‰็ญ‰๏ผ‰ๆ‰€ไฝฟ็”จ็š„ๆฉŸๅˆถใ€‚ไป–ๅ€‘็”จๅฎƒไพ†็‚บไฝฟ็”จ่€…่ˆ‡ๆ‡‰็”จ็จ‹ๅผๆไพ›็‰นๅฎšๆฌŠ้™ใ€‚ + +ๆฏๆฌกไฝ ใ€Œไฝฟ็”จใ€Facebookใ€Googleใ€GitHubใ€Microsoftใ€X๏ผˆTwitter๏ผ‰ใ€Œ็™ปๅ…ฅใ€ๆ™‚๏ผŒ้‚ฃๅ€‹ๆ‡‰็”จๅฐฑๆ˜ฏๅœจไฝฟ็”จๅธถๆœ‰ scopes ็š„ OAuth2ใ€‚ + +ๅœจๆœฌ็ฏ€ไธญ๏ผŒไฝ ๅฐ‡็œ‹ๅˆฐๅฆ‚ไฝ•ๅœจไฝ ็š„ FastAPI ๆ‡‰็”จไธญ๏ผŒ็”จๅŒๆจฃ็š„ๅธถๆœ‰ scopes ็š„ OAuth2 ็ฎก็†้ฉ—่ญ‰่ˆ‡ๆŽˆๆฌŠใ€‚ + +/// warning + +้€™ไธ€็ฏ€็ฎ—ๆ˜ฏ้€ฒ้šŽๅ…งๅฎนใ€‚ๅฆ‚ๆžœไฝ ๅ‰›้–‹ๅง‹๏ผŒๅฏไปฅๅ…ˆ่ทณ้Žใ€‚ + +ไฝ ไธไธ€ๅฎš้œ€่ฆ OAuth2 scopes๏ผŒไฝ ๅฏไปฅ็”จไปปไฝ•ไฝ ๆƒณ่ฆ็š„ๆ–นๅผ่™•็†้ฉ—่ญ‰่ˆ‡ๆŽˆๆฌŠใ€‚ + +ไฝ†ๅธถๆœ‰ scopes ็š„ OAuth2 ๅฏไปฅๅพˆๆผ‚ไบฎๅœฐๆ•ดๅˆ้€ฒไฝ ็š„ API๏ผˆ้€้Ž OpenAPI๏ผ‰่ˆ‡ API ๆ–‡ไปถใ€‚ + +็„ก่ซ–ๅฆ‚ไฝ•๏ผŒไฝ ไป็„ถๆœƒๅœจ็จ‹ๅผ็ขผไธญ๏ผŒไพไฝ ็š„้œ€ๆฑ‚๏ผŒๅผทๅˆถๆชขๆŸฅ้‚ฃไบ› scopes๏ผŒๆˆ–ๅ…ถไป–ไปปไฝ•ๅฎ‰ๅ…จๆ€ง๏ผๆŽˆๆฌŠ้œ€ๆฑ‚ใ€‚ + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒๅธถๆœ‰ scopes ็š„ OAuth2 ๅฏ่ƒฝๆœ‰้ปžๅคงๆๅฐ็”จใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็ขบๅฎš้œ€่ฆ๏ผŒๆˆ–ๆ˜ฏๅฅฝๅฅ‡๏ผŒ่ซ‹็นผ็บŒ้–ฑ่ฎ€ใ€‚ + +/// + +## OAuth2 scopes ่ˆ‡ OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 ่ฆๆ ผๅฐ‡ใ€Œscopesใ€ๅฎš็พฉ็‚บไปฅ็ฉบ็™ฝๅˆ†้š”็š„ไธ€ไธฒๅญ—ไธฒๅˆ—่กจใ€‚ + +ๆฏๅ€‹ๅญ—ไธฒ็š„ๅ…งๅฎนๅฏไปฅๆœ‰ไปปๆ„ๆ ผๅผ๏ผŒไฝ†ไธๆ‡‰ๅŒ…ๅซ็ฉบ็™ฝใ€‚ + +้€™ไบ› scopes ไปฃ่กจใ€ŒๆฌŠ้™ใ€ใ€‚ + +ๅœจ OpenAPI๏ผˆไพ‹ๅฆ‚ API ๆ–‡ไปถ๏ผ‰ไธญ๏ผŒไฝ ๅฏไปฅๅฎš็พฉใ€Œsecurity schemesใ€ใ€‚ + +็•ถๆŸๅ€‹ security scheme ไฝฟ็”จ OAuth2 ๆ™‚๏ผŒไฝ ไนŸๅฏไปฅๅฎฃๅ‘Šไธฆไฝฟ็”จ scopesใ€‚ + +ๆฏๅ€‹ใ€Œscopeใ€ๅฐฑๆ˜ฏไธ€ๅ€‹๏ผˆไธๅซ็ฉบ็™ฝ็š„๏ผ‰ๅญ—ไธฒใ€‚ + +ๅฎƒๅ€‘้€šๅธธ็”จไพ†ๅฎฃๅ‘Š็‰นๅฎš็š„ๅฎ‰ๅ…จๆ€งๆฌŠ้™๏ผŒไพ‹ๅฆ‚๏ผš + +- `users:read` ๆˆ– `users:write` ๆ˜ฏๅธธ่ฆ‹็š„ไพ‹ๅญใ€‚ +- `instagram_basic` ๆ˜ฏ Facebook / Instagram ไฝฟ็”จ็š„ใ€‚ +- `https://www.googleapis.com/auth/drive` ๆ˜ฏ Google ไฝฟ็”จ็š„ใ€‚ + +/// info + +ๅœจ OAuth2 ไธญ๏ผŒใ€Œscopeใ€ๅชๆ˜ฏๅฎฃๅ‘Šๆ‰€้œ€็‰นๅฎšๆฌŠ้™็š„ไธ€ๅ€‹ๅญ—ไธฒใ€‚ + +ๆ˜ฏๅฆๅŒ…ๅซๅƒ `:` ้€™ๆจฃ็š„ๅญ—ๅ…ƒ๏ผŒๆˆ–ๆ˜ฏๅฆๆ˜ฏไธ€ๅ€‹ URL๏ผŒ้ƒฝๆฒ’ๅทฎใ€‚ + +้‚ฃไบ›็ดฐ็ฏ€ๅ–ๆฑบๆ–ผๅฏฆไฝœใ€‚ + +ๅฐ OAuth2 ่€Œ่จ€๏ผŒๅฎƒๅ€‘ๅฐฑๆ˜ฏๅญ—ไธฒใ€‚ + +/// + +## ๅ…จๅฑ€ๆฆ‚่ง€ { #global-view } + +ๅ…ˆๅฟซ้€Ÿ็œ‹็œ‹็›ธๅฐๆ–ผไธปๆ•™ๅญธใ€Œไฝฟ็”จๅฏ†็ขผ๏ผˆ่ˆ‡้›œๆนŠ๏ผ‰ใ€Bearer ่ˆ‡ JWT token ็š„ OAuth2ใ€็š„ๅทฎ็•ฐ๏ผˆ[OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}๏ผ‰ใ€‚็พๅœจๅŠ ๅ…ฅไบ† OAuth2 scopes๏ผš + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ไธ€ๆญฅไธ€ๆญฅๆชข่ฆ–้€™ไบ›่ฎŠๆ›ดใ€‚ + +## OAuth2 ๅฎ‰ๅ…จๆ€งๆ–นๆกˆ { #oauth2-security-scheme } + +็ฌฌไธ€ๅ€‹่ฎŠๆ›ดๆ˜ฏ๏ผšๆˆ‘ๅ€‘็พๅœจๅฎฃๅ‘Šไบ†ๅธถๆœ‰ๅ…ฉๅ€‹ๅฏ็”จ scope ็š„ OAuth2 ๅฎ‰ๅ…จๆ€งๆ–นๆกˆ๏ผŒ`me` ่ˆ‡ `items`ใ€‚ + +ๅƒๆ•ธ `scopes` ๆŽฅๆ”ถไธ€ๅ€‹ `dict`๏ผŒไปฅๅ„ scope ็‚บ้ตใ€ๅ…ถๆ่ฟฐ็‚บๅ€ผ๏ผš + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +็”ฑๆ–ผ็พๅœจๅฎฃๅ‘Šไบ†้€™ไบ› scopes๏ผŒ็•ถไฝ ็™ปๅ…ฅ๏ผๆŽˆๆฌŠๆ™‚๏ผŒๅฎƒๅ€‘ๆœƒๅ‡บ็พๅœจ API ๆ–‡ไปถไธญใ€‚ + +ไฝ ๅฏไปฅ้ธๆ“‡่ฆๆŽˆไบˆๅ“ชไบ› scopes ๅญ˜ๅ–ๆฌŠ๏ผš`me` ่ˆ‡ `items`ใ€‚ + +้€™่ˆ‡ไฝ ไฝฟ็”จ Facebookใ€Googleใ€GitHub ็ญ‰็™ปๅ…ฅๆ™‚ๆ‰€ๆŽˆ่ˆ‡ๆฌŠ้™็š„ๆฉŸๅˆถ็›ธๅŒ๏ผš + + + +## ๅ…งๅซ scopes ็š„ JWT token { #jwt-token-with-scopes } + +็พๅœจ๏ผŒไฟฎๆ”น token ็š„่ทฏๅพ‘ๆ“ไฝœไปฅๅ›žๅ‚ณๆ‰€่ซ‹ๆฑ‚็š„ scopesใ€‚ + +ๆˆ‘ๅ€‘ไป็„ถไฝฟ็”จ็›ธๅŒ็š„ `OAuth2PasswordRequestForm`ใ€‚ๅฎƒๅŒ…ๅซๅฑฌๆ€ง `scopes`๏ผŒๅ…ถ็‚บ `list` ็š„ `str`๏ผŒๅˆ—ๅ‡บ่ซ‹ๆฑ‚ไธญๆ”ถๅˆฐ็š„ๆฏๅ€‹ scopeใ€‚ + +ไธฆไธ”ๆˆ‘ๅ€‘ๅฐ‡้€™ไบ› scopes ไฝœ็‚บ JWT token ็š„ไธ€้ƒจๅˆ†ๅ›žๅ‚ณใ€‚ + +/// danger + +็‚บไบ†็ฐกๅŒ–๏ผŒ้€™่ฃกๆˆ‘ๅ€‘ๅชๆ˜ฏ็›ดๆŽฅๆŠŠๆŽฅๆ”ถๅˆฐ็š„ scopes ๅŠ ้€ฒ tokenใ€‚ + +ไฝ†ๅœจไฝ ็š„ๆ‡‰็”จไธญ๏ผŒ็‚บไบ†ๅฎ‰ๅ…จๆ€ง๏ผŒไฝ ๆ‡‰็ขบไฟๅชๅŠ ๅ…ฅ่ฉฒไฝฟ็”จ่€…ๅฏฆ้š›ๅฏๆ“ๆœ‰ๆˆ–ไฝ ้ ๅ…ˆๅฎš็พฉ็š„ scopesใ€‚ + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## ๅœจ่ทฏๅพ‘ๆ“ไฝœ่ˆ‡็›ธไพๆ€งไธญๅฎฃๅ‘Š scopes { #declare-scopes-in-path-operations-and-dependencies } + +็พๅœจๆˆ‘ๅ€‘ๅฎฃๅ‘Š `/users/me/items/` ้€™ๅ€‹่ทฏๅพ‘ๆ“ไฝœ้œ€่ฆ `items` ้€™ๅ€‹ scopeใ€‚ + +็‚บๆญค๏ผŒๆˆ‘ๅ€‘ๅพž `fastapi` ๅŒฏๅ…ฅไธฆไฝฟ็”จ `Security`ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `Security` ไพ†ๅฎฃๅ‘Š็›ธไพๆ€ง๏ผˆๅฐฑๅƒ `Depends`๏ผ‰๏ผŒไฝ† `Security` ไนŸ่ƒฝๆŽฅๆ”ถๅƒๆ•ธ `scopes`๏ผŒๅ…ถ็‚บ scopes๏ผˆๅญ—ไธฒ๏ผ‰็š„ๅˆ—่กจใ€‚ + +ๅœจ้€™่ฃก๏ผŒๆˆ‘ๅ€‘ๅฐ‡็›ธไพๅ‡ฝๅผ `get_current_active_user` ๅ‚ณ็ตฆ `Security`๏ผˆๅฐฑๅƒไฝฟ็”จ `Depends` ไธ€ๆจฃ๏ผ‰ใ€‚ + +ไฝ†ๅŒๆ™‚ไนŸๅ‚ณๅ…ฅไธ€ๅ€‹ `list` ็š„ scopes๏ผŒ้€™่ฃกๅชๆœ‰ไธ€ๅ€‹ scope๏ผš`items`๏ผˆ็•ถ็„ถไนŸๅฏไปฅๆœ‰ๆ›ดๅคš๏ผ‰ใ€‚ + +่€Œ็›ธไพๅ‡ฝๅผ `get_current_active_user` ไนŸ่ƒฝๅฎฃๅ‘Šๅญ็›ธไพๆ€ง๏ผŒไธๅช็”จ `Depends`๏ผŒไนŸ่ƒฝ็”จ `Security`ใ€‚ๅฎƒๅฎฃๅ‘Šไบ†่‡ชๅทฑ็š„ๅญ็›ธไพๅ‡ฝๅผ๏ผˆ`get_current_user`๏ผ‰๏ผŒไธฆๅŠ ๅ…ฅๆ›ดๅคš scope ่ฆๆฑ‚ใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅฎƒ่ฆๆฑ‚ `me` ้€™ๅ€‹ scope๏ผˆไนŸๅฏไปฅ่ฆๆฑ‚ๅคšๅ€‹๏ผ‰ใ€‚ + +/// note + +ไฝ ไธไธ€ๅฎš้œ€่ฆๅœจไธๅŒๅœฐๆ–นๅŠ ไธŠไธๅŒ็š„ scopesใ€‚ + +ๆˆ‘ๅ€‘ๅœจ้€™่ฃก้€™ๆจฃๅš๏ผŒๆ˜ฏ็‚บไบ†็คบ็ฏ„ FastAPI ๅฆ‚ไฝ•่™•็†ๅœจไธๅŒๅฑค็ดšๅฎฃๅ‘Š็š„ scopesใ€‚ + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | ๆŠ€่ก“็ดฐ็ฏ€ + +`Security` ๅ…ถๅฏฆๆ˜ฏ `Depends` ็š„ๅญ้กžๅˆฅ๏ผŒๅƒ…ๅคšไบ†ไธ€ๅ€‹ๆˆ‘ๅ€‘็จๅพŒๆœƒ็œ‹ๅˆฐ็š„ๅƒๆ•ธใ€‚ + +ๆ”น็”จ `Security` ่€Œไธๆ˜ฏ `Depends`๏ผŒ่ƒฝ่ฎ“ FastAPI ็Ÿฅ้“ๅฏไปฅๅฎฃๅ‘Šๅฎ‰ๅ…จๆ€ง scopesใ€ๅœจๅ…ง้ƒจไฝฟ็”จๅฎƒๅ€‘๏ผŒไธฆ็”จ OpenAPI ๆ–‡ไปถๅŒ– APIใ€‚ + +ๅฆๅค–๏ผŒ็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path`ใ€`Depends`ใ€`Security` ็ญ‰ๆ™‚๏ผŒๅฏฆ้š›ไธŠๅฎƒๅ€‘ๆ˜ฏๅ›žๅ‚ณ็‰นๆฎŠ้กžๅˆฅ็š„ๅ‡ฝๅผใ€‚ + +/// + +## ไฝฟ็”จ `SecurityScopes` { #use-securityscopes } + +็พๅœจๆ›ดๆ–ฐ็›ธไพๆ€ง `get_current_user`ใ€‚ + +ไธŠ้ข็š„็›ธไพๆ€งๅฐฑๆ˜ฏไฝฟ็”จๅฎƒใ€‚ + +้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จๅ…ˆๅ‰ๅปบ็ซ‹็š„็›ธๅŒ OAuth2 scheme๏ผŒไธฆๅฐ‡ๅ…ถๅฎฃๅ‘Š็‚บ็›ธไพๆ€ง๏ผš`oauth2_scheme`ใ€‚ + +ๅ› ็‚บๆญค็›ธไพๅ‡ฝๅผๆœฌ่บซๆฒ’ๆœ‰ไปปไฝ• scope ่ฆๆฑ‚๏ผŒๆ‰€ไปฅๆˆ‘ๅ€‘ๅฏไปฅ็”จ `Depends` ๆญ้… `oauth2_scheme`๏ผŒ็•ถไธ้œ€่ฆๆŒ‡ๅฎšๅฎ‰ๅ…จๆ€ง scopes ๆ™‚ๅฐฑไธๅฟ…็”จ `Security`ใ€‚ + +ๆˆ‘ๅ€‘ไนŸๅฎฃๅ‘Šไบ†ไธ€ๅ€‹ๅž‹ๅˆฅ็‚บ `SecurityScopes` ็š„็‰นๆฎŠๅƒๆ•ธ๏ผŒๅพž `fastapi.security` ๅŒฏๅ…ฅใ€‚ + +้€™ๅ€‹ `SecurityScopes` ้กžไผผๆ–ผ `Request`๏ผˆ`Request` ็”จไพ†็›ดๆŽฅๅ–ๅพ—่ซ‹ๆฑ‚็‰ฉไปถ๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## ไฝฟ็”จ้€™ไบ› `scopes` { #use-the-scopes } + +ๅƒๆ•ธ `security_scopes` ็š„ๅž‹ๅˆฅๆ˜ฏ `SecurityScopes`ใ€‚ + +ๅฎƒๆœƒๆœ‰ๅฑฌๆ€ง `scopes`๏ผŒๅŒ…ๅซไธ€ๅ€‹ๅˆ—่กจ๏ผŒๅ…งๅซๆญคๅ‡ฝๅผๆœฌ่บซ่ˆ‡ๆ‰€ๆœ‰ไฝฟ็”จๅฎƒ็‚บๅญ็›ธไพๆ€ง็š„็›ธไพๆ€งๆ‰€่ฆๆฑ‚็š„ๆ‰€ๆœ‰ scopesใ€‚ไนŸๅฐฑๆ˜ฏๆ‰€ๆœ‰ใ€Œ็›ธไพ่€…๏ผˆdependants๏ผ‰ใ€... ้€™่ฝ่ตทไพ†ๅฏ่ƒฝๆœ‰้ปžๆททไบ‚๏ผŒไธ‹้ขๆœƒๅ†่งฃ้‡‹ใ€‚ + +`security_scopes` ็‰ฉไปถ๏ผˆ้กžๅˆฅ `SecurityScopes`๏ผ‰ไนŸๆไพ› `scope_str` ๅฑฌๆ€ง๏ผŒ็‚บไธ€ๅ€‹ๅญ—ไธฒ๏ผŒๅŒ…ๅซ้‚ฃไบ›ไปฅ็ฉบ็™ฝๅˆ†้š”็š„ scopes๏ผˆๆˆ‘ๅ€‘ๆœƒ็”จๅˆฐ๏ผ‰ใ€‚ + +ๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹ๅฏๅœจๅคš่™•้‡่ค‡ไธŸๅ‡บ๏ผˆ`raise`๏ผ‰็š„ `HTTPException`ใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅค–ไธญ๏ผŒๆˆ‘ๅ€‘ๆŠŠๆ‰€้œ€็š„ scopes๏ผˆ่‹ฅๆœ‰๏ผ‰ไปฅ็ฉบ็™ฝๅˆ†้š”็š„ๅญ—ไธฒๅฝขๅผ๏ผˆ้€้Ž `scope_str`๏ผ‰ๅŠ ๅ…ฅ๏ผŒไธฆๅฐ‡่ฉฒๅŒ…ๅซ scopes ็š„ๅญ—ไธฒๆ”พๅœจ `WWW-Authenticate` ๆจ™้ ญไธญ๏ผˆ้€™ๆ˜ฏ่ฆๆ ผ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## ้ฉ—่ญ‰ `username` ่ˆ‡่ณ‡ๆ–™็ตๆง‹ { #verify-the-username-and-data-shape } + +ๆˆ‘ๅ€‘ๅ…ˆ็ขบ่ชๅ–ๅพ—ไบ† `username`๏ผŒไธฆๅ–ๅ‡บ scopesใ€‚ + +ๆŽฅ่‘—็”จ Pydantic ๆจกๅž‹้ฉ—่ญ‰้€™ไบ›่ณ‡ๆ–™๏ผˆๆ•ๆ‰ `ValidationError` ไพ‹ๅค–๏ผ‰๏ผŒ่‹ฅๅœจ่ฎ€ๅ– JWT token ๆˆ–็”จ Pydantic ้ฉ—่ญ‰่ณ‡ๆ–™ๆ™‚ๅ‡บ้Œฏ๏ผŒๅฐฑไธŸๅ‡บๅ…ˆๅ‰ๅปบ็ซ‹็š„ `HTTPException`ใ€‚ + +็‚บๆญค๏ผŒๆˆ‘ๅ€‘ๆ›ดๆ–ฐไบ† Pydantic ๆจกๅž‹ `TokenData`๏ผŒๅŠ ๅ…ฅๆ–ฐๅฑฌๆ€ง `scopes`ใ€‚ + +้€้Ž Pydantic ้ฉ—่ญ‰่ณ‡ๆ–™๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ็ขบไฟ๏ผŒไพ‹ๅฆ‚๏ผŒscopes ๆญฃๅฅฝๆ˜ฏ `list` ็š„ `str`๏ผŒ่€Œ `username` ๆ˜ฏ `str`ใ€‚ + +ๅฆๅ‰‡่‹ฅๆ˜ฏ `dict` ๆˆ–ๅ…ถไป–ๅž‹ๅˆฅ๏ผŒๅฏ่ƒฝๅœจๅพŒ็บŒๆŸ่™•ไฝฟๆ‡‰็”จๅฃžๆމ๏ผŒ้€ ๆˆๅฎ‰ๅ…จ้ขจ้šชใ€‚ + +ๆˆ‘ๅ€‘ไนŸๆœƒ็ขบ่ช่ฉฒ `username` ๅฐๆ‡‰็š„ไฝฟ็”จ่€…ๆ˜ฏๅฆๅญ˜ๅœจ๏ผŒๅฆๅ‰‡ๅŒๆจฃไธŸๅ‡บไน‹ๅ‰ๅปบ็ซ‹็š„ไพ‹ๅค–ใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## ้ฉ—่ญ‰ `scopes` { #verify-the-scopes } + +ๆˆ‘ๅ€‘็พๅœจ่ฆ้ฉ—่ญ‰๏ผŒๆญค็›ธไพๆ€ง่ˆ‡ๆ‰€ๆœ‰็›ธไพ่€…๏ผˆๅŒ…ๅซ่ทฏๅพ‘ๆ“ไฝœ๏ผ‰ๆ‰€่ฆๆฑ‚็š„ๆ‰€ๆœ‰ scopes๏ผŒๆ˜ฏๅฆ้ƒฝๅŒ…ๅซๅœจๆ”ถๅˆฐ็š„ token ๅ…งๆ‰€ๆไพ›็š„ scopes ไธญ๏ผ›ๅฆๅ‰‡ๅฐฑไธŸๅ‡บ `HTTPException`ใ€‚ + +็‚บๆญค๏ผŒๆˆ‘ๅ€‘ไฝฟ็”จ `security_scopes.scopes`๏ผŒๅ…ถไธญๅŒ…ๅซไธ€ๅ€‹ `list`๏ผŒๅˆ—ๅ‡บๆ‰€ๆœ‰้€™ไบ› `str` ๅฝขๅผ็š„ scopesใ€‚ + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## ็›ธไพๆ€งๆจน่ˆ‡ scopes { #dependency-tree-and-scopes } + +ๆˆ‘ๅ€‘ๅ†ๅ›ž้กงไธ€ๆฌก้€™ๅ€‹็›ธไพๆ€งๆจน่ˆ‡ 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` ไธญใ€‚ + +ไปฅไธ‹ๆ˜ฏ็›ธไพๆ€ง่ˆ‡ 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` ๆธ…ๅ–ฎ้œ€่ฆๆชขๆŸฅใ€‚ + +้€™ๅฎŒๅ…จๅ–ๆฑบๆ–ผ่ฉฒ่ทฏๅพ‘ๆ“ไฝœ่ˆ‡ๅ…ถ็›ธไพๆ€งๆจนไธญๆฏๅ€‹็›ธไพๆ€งๆ‰€ๅฎฃๅ‘Š็š„ `scopes`ใ€‚ + +/// + +## ๆ›ดๅคš้—œๆ–ผ `SecurityScopes` ็š„็ดฐ็ฏ€ { #more-details-about-securityscopes } + +ไฝ ๅฏไปฅๅœจไปปๆ„ไฝ็ฝฎใ€ๅคšๅ€‹ๅœฐๆ–นไฝฟ็”จ `SecurityScopes`๏ผŒๅฎƒไธ้œ€่ฆไฝๆ–ผใ€Œๆ นใ€็›ธไพๆ€งใ€‚ + +ๅฎƒๆœƒๆฐธ้ ๅธถๆœ‰ๅฐๆ–ผใ€Œ่ฉฒ็‰นๅฎšใ€่ทฏๅพ‘ๆ“ไฝœ่ˆ‡ใ€Œ่ฉฒ็‰นๅฎšใ€็›ธไพๆ€งๆจนไธญ๏ผŒ็›ฎๅ‰ `Security` ็›ธไพๆ€งๆ‰€ๅฎฃๅ‘Š็š„ๅฎ‰ๅ…จๆ€ง scopes๏ผˆไปฅๅŠๆ‰€ๆœ‰็›ธไพ่€…๏ผ‰๏ผš + +ๅ› ็‚บ `SecurityScopes` ๆœƒๆ“ๆœ‰็”ฑ็›ธไพ่€…ๅฎฃๅ‘Š็š„ๆ‰€ๆœ‰ scopes๏ผŒไฝ ๅฏไปฅๅœจไธ€ๅ€‹้›†ไธญๅผ็›ธไพๅ‡ฝๅผไธญ็”จๅฎƒไพ†้ฉ—่ญ‰ token ๆ˜ฏๅฆๅ…ทๆœ‰ๆ‰€้œ€ scopes๏ผŒ็„ถๅพŒๅœจไธๅŒ่ทฏๅพ‘ๆ“ไฝœไธญๅฎฃๅ‘ŠไธๅŒ็š„ scope ่ฆๆฑ‚ใ€‚ + +ๅฎƒๅ€‘ๆœƒๅœจๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœ่ขซๅ„่‡ช็จ็ซ‹ๆชขๆŸฅใ€‚ + +## ่ฉฆ็”จ็œ‹็œ‹ { #check-it } + +ๅฆ‚ๆžœไฝ ๆ‰“้–‹ API ๆ–‡ไปถ๏ผŒไฝ ๅฏไปฅๅ…ˆ้ฉ—่ญ‰ไธฆๆŒ‡ๅฎšไฝ ่ฆๆŽˆๆฌŠ็š„ scopesใ€‚ + + + +ๅฆ‚ๆžœไฝ ๆฒ’ๆœ‰้ธไปปไฝ• scope๏ผŒไฝ ไปๆœƒใ€Œ้€š้Ž้ฉ—่ญ‰ใ€๏ผŒไฝ†็•ถไฝ ๅ˜—่ฉฆๅญ˜ๅ– `/users/me/` ๆˆ– `/users/me/items/` ๆ™‚๏ผŒๆœƒๆ”ถๅˆฐๆฒ’ๆœ‰่ถณๅค ๆฌŠ้™็š„้Œฏ่ชคใ€‚ไฝ ไป่ƒฝๅญ˜ๅ– `/status/`ใ€‚ + +่‹ฅไฝ ๅช้ธไบ† `me` ่€Œๆœช้ธ `items`๏ผŒไฝ ่ƒฝๅญ˜ๅ– `/users/me/`๏ผŒไฝ†็„กๆณ•ๅญ˜ๅ– `/users/me/items/`ใ€‚ + +้€™ๅฐฑๆ˜ฏ็ฌฌไธ‰ๆ–นๆ‡‰็”จๅœจๅ–ๅพ—ไฝฟ็”จ่€…ๆไพ›็š„ token ๅพŒ๏ผŒๅ˜—่ฉฆๅญ˜ๅ–ไธŠ่ฟฐ่ทฏๅพ‘ๆ“ไฝœๆ™‚๏ผŒๆœƒไพไฝฟ็”จ่€…ๆŽˆ่ˆ‡่ฉฒๆ‡‰็”จ็š„ๆฌŠ้™ๅคšๅฏก่€Œๆœ‰ไธๅŒ็ตๆžœใ€‚ + +## ้—œๆ–ผ็ฌฌไธ‰ๆ–นๆ•ดๅˆ { #about-third-party-integrations } + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ไฝฟ็”จ OAuth2 ็š„ใ€Œpasswordใ€ๆต็จ‹ใ€‚ + +็•ถๆˆ‘ๅ€‘็™ปๅ…ฅ่‡ชๅทฑ็š„ๆ‡‰็”จ๏ผˆๅฏ่ƒฝไนŸๆœ‰่‡ชๅทฑ็š„ๅ‰็ซฏ๏ผ‰ๆ™‚๏ผŒ้€™ๆ˜ฏๅˆ้ฉ็š„ใ€‚ + +ๅ› ็‚บๆˆ‘ๅ€‘ๅฏไปฅไฟกไปปๅฎƒๆŽฅๆ”ถ `username` ่ˆ‡ `password`๏ผŒๅ› ็‚บๆˆ‘ๅ€‘ๆŽŒๆŽงๅฎƒใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ่ฆๆ‰“้€ ไธ€ๅ€‹่ฎ“ไป–ไบบ้€ฃๆŽฅ็š„ OAuth2 ๆ‡‰็”จ๏ผˆไนŸๅฐฑๆ˜ฏไฝ ่ฆๅปบ็ซ‹ไธ€ๅ€‹็›ธ็•ถๆ–ผ Facebookใ€Googleใ€GitHub ็ญ‰็š„่บซๅˆ†้ฉ—่ญ‰ๆไพ›่€…๏ผ‰๏ผŒไฝ ๆ‡‰่ฉฒไฝฟ็”จๅ…ถไป–ๆต็จ‹ไน‹ไธ€ใ€‚ + +ๆœ€ๅธธ่ฆ‹็š„ๆ˜ฏ Implicit Flow๏ผˆ้šฑๅผๆต็จ‹๏ผ‰ใ€‚ + +ๆœ€ๅฎ‰ๅ…จ็š„ๆ˜ฏ Authorization Code Flow๏ผˆๆŽˆๆฌŠ็ขผๆต็จ‹๏ผ‰๏ผŒไฝ†ๅฎƒ้œ€่ฆๆ›ดๅคšๆญฅ้ฉŸใ€ๅฏฆไฝœไนŸๆ›ด่ค‡้›œใ€‚ๅ› ็‚บ่ผƒ่ค‡้›œ๏ผŒ่จฑๅคšๆไพ›่€…ๆœ€ๅพŒๆœƒๅปบ่ญฐไฝฟ็”จ้šฑๅผๆต็จ‹ใ€‚ + +/// note + +ๅพˆๅธธ่ฆ‹็š„ๆ˜ฏ๏ผŒๆฏๅ€‹่บซๅˆ†้ฉ—่ญ‰ๆไพ›่€…ๆœƒ็”จไธๅŒ็š„ๆ–นๅผๅ‘ฝๅไป–ๅ€‘็š„ๆต็จ‹๏ผŒ่ฎ“ๅฎƒๆˆ็‚บๅ“็‰Œ็š„ไธ€้ƒจๅˆ†ใ€‚ + +ไฝ†ๆœ€็ต‚๏ผŒไป–ๅ€‘ๅฏฆไฝœ็š„้ƒฝๆ˜ฏ็›ธๅŒ็š„ OAuth2 ๆจ™ๆบ–ใ€‚ + +/// + +FastAPI ๅœจ `fastapi.security.oauth2` ไธญๆไพ›ไบ†ๆ‰€ๆœ‰้€™ไบ› OAuth2 ้ฉ—่ญ‰ๆต็จ‹็š„ๅทฅๅ…ทใ€‚ + +## ๅœจ่ฃ้ฃพๅ™จ `dependencies` ไธญไฝฟ็”จ `Security` { #security-in-decorator-dependencies } + +ๅฐฑๅƒไฝ ๅฏไปฅๅœจ่ฃ้ฃพๅ™จ็š„ `dependencies` ๅƒๆ•ธไธญๅฎš็พฉไธ€ๅ€‹ `Depends` ็š„ `list` ไธ€ๆจฃ๏ผˆ่ฉณ่ฆ‹[่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จไธญ็š„็›ธไพๆ€ง](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}๏ผ‰๏ผŒไฝ ไนŸๅฏไปฅๅœจ้‚ฃ่ฃกไฝฟ็”จๅธถๆœ‰ `scopes` ็š„ `Security`ใ€‚ diff --git a/docs/zh-hant/docs/advanced/settings.md b/docs/zh-hant/docs/advanced/settings.md new file mode 100644 index 0000000000..1ee5ad7cc2 --- /dev/null +++ b/docs/zh-hant/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# ่จญๅฎš่ˆ‡็’ฐๅขƒ่ฎŠๆ•ธ { #settings-and-environment-variables } + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๅฏ่ƒฝ้œ€่ฆไธ€ไบ›ๅค–้ƒจ่จญๅฎšๆˆ–็ต„ๆ…‹๏ผŒไพ‹ๅฆ‚ๅฏ†้‘ฐใ€่ณ‡ๆ–™ๅบซๆ†‘่ญ‰ใ€้›ปๅญ้ƒตไปถๆœๅ‹™็š„ๆ†‘่ญ‰็ญ‰ใ€‚ + +้€™ไบ›่จญๅฎšๅคงๅคšๆ˜ฏๅฏ่ฎŠ็š„๏ผˆๅฏ่ƒฝๆœƒๆ”น่ฎŠ๏ผ‰๏ผŒๅƒๆ˜ฏ่ณ‡ๆ–™ๅบซ URLใ€‚ไนŸๆœ‰่จฑๅคšๅฏ่ƒฝๆ˜ฏๆ•ๆ„Ÿ่ณ‡่จŠ๏ผŒไพ‹ๅฆ‚ๅฏ†้‘ฐใ€‚ + +ๅ› ๆญค๏ผŒ้€šๅธธๆœƒ้€้Ž็’ฐๅขƒ่ฎŠๆ•ธๆไพ›้€™ไบ›่จญๅฎš๏ผŒ่ฎ“ๆ‡‰็”จ็จ‹ๅผๅŽป่ฎ€ๅ–ใ€‚ + +/// tip + +่‹ฅๆƒณไบ†่งฃ็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒไฝ ๅฏไปฅ้–ฑ่ฎ€[็’ฐๅขƒ่ฎŠๆ•ธ](../environment-variables.md){.internal-link target=_blank}ใ€‚ + +/// + +## ๅž‹ๅˆฅ่ˆ‡้ฉ—่ญ‰ { #types-and-validation } + +้€™ไบ›็’ฐๅขƒ่ฎŠๆ•ธๅช่ƒฝ่™•็†ๆ–‡ๅญ—ๅญ—ไธฒ๏ผŒๅ› ็‚บๅฎƒๅ€‘ๅœจ Python ไน‹ๅค–๏ผŒๅฟ…้ ˆ่ˆ‡ๅ…ถไป–็จ‹ๅผ่ˆ‡็ณป็ตฑ็š„ๅ…ถ้ค˜้ƒจๅˆ†็›ธๅฎน๏ผˆ็”š่‡ณ่ทจไฝœๆฅญ็ณป็ตฑ๏ผŒๅฆ‚ Linuxใ€Windowsใ€macOS๏ผ‰ใ€‚ + +้€™่กจ็คบๅœจ Python ไธญ่‡ช็’ฐๅขƒ่ฎŠๆ•ธ่ฎ€ๅ–ๅˆฐ็š„ไปปไฝ•ๅ€ผ้ƒฝๆœƒๆ˜ฏ `str`๏ผŒ่€Œไปปไฝ•่ฝ‰ๅž‹ๆˆๅ…ถไป–ๅž‹ๅˆฅๆˆ–้ฉ—่ญ‰้ƒฝๅฟ…้ ˆๅœจ็จ‹ๅผ็ขผไธญๅฎŒๆˆใ€‚ + +## Pydantic `Settings` { #pydantic-settings } + +ๅนธๅฅฝ๏ผŒPydantic ๆไพ›ไบ†ๅพˆๅฅฝ็š„ๅทฅๅ…ท๏ผŒๅฏ็”จไพ†่™•็†็”ฑ็’ฐๅขƒ่ฎŠๆ•ธ่€Œไพ†็š„่จญๅฎš๏ผšPydantic๏ผš่จญๅฎš็ฎก็†ใ€‚ + +### ๅฎ‰่ฃ `pydantic-settings` { #install-pydantic-settings } + +้ฆ–ๅ…ˆ๏ผŒ่ซ‹ๅ…ˆๅปบ็ซ‹ไฝ ็š„[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒๅ•Ÿ็”จๅฎƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ `pydantic-settings` ๅฅ—ไปถ๏ผš + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +็•ถไฝ ็”จ `all` extras ๅฎ‰่ฃๆ™‚๏ผŒๅฎƒไนŸๆœƒไธ€ไฝตๅŒ…ๅซๅœจๅ…ง๏ผš + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### ๅปบ็ซ‹ `Settings` ็‰ฉไปถ { #create-the-settings-object } + +ๅพž Pydantic ๅŒฏๅ…ฅ `BaseSettings` ไธฆๅปบ็ซ‹ๅญ้กžๅˆฅ๏ผŒ่ˆ‡ๅปบ็ซ‹ Pydantic model ็š„ๆ–นๅผ้žๅธธ้กžไผผใ€‚ + +ๅฐฑๅƒไฝฟ็”จ Pydantic model ไธ€ๆจฃ๏ผŒไฝ ็”จๅž‹ๅˆฅ่จป่งฃๅฎฃๅ‘Š้กžๅˆฅๅฑฌๆ€ง๏ผŒไธฆๅฏ้ธๆ“‡ๆ€งๅœฐๆไพ›้ ่จญๅ€ผใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ่ˆ‡ Pydantic model ็›ธๅŒ็š„ๆ‰€ๆœ‰้ฉ—่ญ‰ๅŠŸ่ƒฝ่ˆ‡ๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ไธๅŒ็š„่ณ‡ๆ–™ๅž‹ๅˆฅ่ˆ‡้€้Ž `Field()` ้€ฒ่กŒ้กๅค–้ฉ—่ญ‰ใ€‚ + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip + +ๅฆ‚ๆžœไฝ ๆƒณ่ฆๅฏไปฅ็›ดๆŽฅ่ค‡่ฃฝ่ฒผไธŠ็š„็ฏ„ไพ‹๏ผŒๅ…ˆๅˆฅ็”จ้€™ๅ€‹๏ผŒ่ซ‹ๆ”น็”จๆœฌๆ–‡ๆœ€ๅพŒไธ€ๅ€‹็ฏ„ไพ‹ใ€‚ + +/// + +ๆŽฅ่‘—๏ผŒ็•ถไฝ ๅปบ็ซ‹่ฉฒ `Settings` ้กžๅˆฅ็š„ๅฏฆไพ‹๏ผˆๆญค่™•็‚บ `settings` ็‰ฉไปถ๏ผ‰ๆ™‚๏ผŒPydantic ๆœƒไปฅไธๅ€ๅˆ†ๅคงๅฐๅฏซ็š„ๆ–นๅผ่ฎ€ๅ–็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒๅ› ๆญค๏ผŒๅณไฝฟ็’ฐๅขƒ่ฎŠๆ•ธๆ˜ฏๅคงๅฏซ็š„ `APP_NAME`๏ผŒไนŸๆœƒ่ขซ่ฎ€ๅ…ฅๅฑฌๆ€ง `app_name`ใ€‚ + +็„ถๅพŒๅฎƒๆœƒ่ฝ‰ๆ›ไธฆ้ฉ—่ญ‰่ณ‡ๆ–™ใ€‚ๅ› ๆญค๏ผŒ็•ถไฝ ไฝฟ็”จ่ฉฒ `settings` ็‰ฉไปถๆ™‚๏ผŒไฝ ๆœƒๅพ—ๅˆฐไฝ ๅฎฃๅ‘Š็š„ๅž‹ๅˆฅ็š„่ณ‡ๆ–™๏ผˆไพ‹ๅฆ‚ `items_per_user` ๆœƒๆ˜ฏ `int`๏ผ‰ใ€‚ + +### ไฝฟ็”จ `settings` { #use-the-settings } + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจๆ‡‰็”จ็จ‹ๅผไธญไฝฟ็”จๆ–ฐ็š„ `settings` ็‰ฉไปถ๏ผš + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### ๅŸท่กŒไผบๆœๅ™จ { #run-the-server } + +ๆŽฅไธ‹ไพ†๏ผŒไฝ ๅฏไปฅๅœจๅ•Ÿๅ‹•ไผบๆœๅ™จๆ™‚๏ผŒๅฐ‡่จญๅฎšไปฅ็’ฐๅขƒ่ฎŠๆ•ธๅ‚ณๅ…ฅใ€‚่ˆ‰ไพ‹ไพ†่ชช๏ผŒไฝ ๅฏไปฅ่จญๅฎš `ADMIN_EMAIL` ่ˆ‡ `APP_NAME`๏ผš + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip + +่ฆ็‚บๅ–ฎไธ€ๆŒ‡ไปค่จญๅฎšๅคšๅ€‹็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒๅช่ฆ็”จ็ฉบ็™ฝๅˆ†้š”ๅฎƒๅ€‘๏ผŒไธฆๅ…จ้ƒจๆ”พๅœจๆŒ‡ไปคๅ‰้ขๅณๅฏใ€‚ + +/// + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒ`admin_email` ่จญๅฎšๆœƒ่ขซ่จญ็‚บ `"deadpool@example.com"`ใ€‚ + +`app_name` ๆœƒๆ˜ฏ `"ChimichangApp"`ใ€‚ + +่€Œ `items_per_user` ๅ‰‡ๆœƒไฟ็•™ๅ…ถ้ ่จญๅ€ผ `50`ใ€‚ + +## ๅœจๅฆไธ€ๅ€‹ๆจก็ต„ไธญ็š„่จญๅฎš { #settings-in-another-module } + +ไฝ ไนŸๅฏไปฅๆŠŠ้€™ไบ›่จญๅฎšๆ”พๅœจๅฆไธ€ๅ€‹ๆจก็ต„ๆช”ๆกˆไธญ๏ผŒๅฐฑๅƒๅœจ[ๆ›ดๅคง็š„ๆ‡‰็”จ็จ‹ๅผ - ๅคšๅ€‹ๆช”ๆกˆ](../tutorial/bigger-applications.md){.internal-link target=_blank}ๆ‰€็คบใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆœ‰ไธ€ๅ€‹ `config.py` ๆช”ๆกˆๅฆ‚ไธ‹๏ผš + +{* ../../docs_src/settings/app01_py310/config.py *} + +็„ถๅพŒๅœจ `main.py` ๆช”ๆกˆไธญไฝฟ็”จๅฎƒ๏ผš + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip + +ไฝ ไนŸ้œ€่ฆไธ€ๅ€‹ `__init__.py` ๆช”ๆกˆ๏ผŒ่ฉณ่ฆ‹[ๆ›ดๅคง็š„ๆ‡‰็”จ็จ‹ๅผ - ๅคšๅ€‹ๆช”ๆกˆ](../tutorial/bigger-applications.md){.internal-link target=_blank}ใ€‚ + +/// + +## ๅœจ็›ธไพไธญ็š„่จญๅฎš { #settings-in-a-dependency } + +ๅœจๆŸไบ›ๆƒ…ๅขƒไธญ๏ผŒๅพž็›ธไพ๏ผˆdependency๏ผ‰ๆไพ›่จญๅฎš๏ผŒๆœƒๆฏ”ๅœจๅ„่™•ไฝฟ็”จไธ€ๅ€‹ๅ…จๅŸŸ็š„ `settings` ็‰ฉไปถๆ›ดๆœ‰็”จใ€‚ + +้€™ๅœจๆธฌ่ฉฆๆ™‚็‰นๅˆฅๅฏฆ็”จ๏ผŒๅ› ็‚บไฝ ๅฏไปฅๅพˆๅฎนๆ˜“็”จ่‡ช่จ‚็š„่จญๅฎšไพ†่ฆ†ๅฏซไธ€ๅ€‹็›ธไพใ€‚ + +### ่จญๅฎšๆช” { #the-config-file } + +ๅปถ็บŒๅ‰ไธ€ๅ€‹็ฏ„ไพ‹๏ผŒไฝ ็š„ `config.py` ๅฏไปฅๅƒ้€™ๆจฃ๏ผš + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +ๆณจๆ„็พๅœจๆˆ‘ๅ€‘ไธๅ†ๅปบ็ซ‹้ ่จญๅฏฆไพ‹ `settings = Settings()`ใ€‚ + +### ไธปๆ‡‰็”จ็จ‹ๅผๆช”ๆกˆ { #the-main-app-file } + +็พๅœจๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹็›ธไพ๏ผŒๅ›žๅ‚ณๆ–ฐ็š„ `config.Settings()`ใ€‚ + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip + +ๆˆ‘ๅ€‘็จๅพŒๆœƒ่จŽ่ซ– `@lru_cache`ใ€‚ + +็พๅœจไฝ ๅฏไปฅๅ…ˆๆŠŠ `get_settings()` ่ฆ–็‚บไธ€่ˆฌๅ‡ฝๅผใ€‚ + +/// + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅฏไปฅๅœจ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ (path operation function)* ไธญๅฐ‡ๅฎƒๅฎฃๅ‘Š็‚บ็›ธไพ๏ผŒไธฆๅœจ้œ€่ฆ็š„ๅœฐๆ–นไฝฟ็”จๅฎƒใ€‚ + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### ่จญๅฎš่ˆ‡ๆธฌ่ฉฆ { #settings-and-testing } + +ๆŽฅ่‘—๏ผŒๅœจๆธฌ่ฉฆๆ™‚่ฆๆไพ›ไธๅŒ็š„่จญๅฎš็‰ฉไปถๆœƒ้žๅธธๅฎนๆ˜“๏ผŒๅช่ฆ็‚บ `get_settings` ๅปบ็ซ‹็›ธไพ่ฆ†ๅฏซ๏ผˆdependency override๏ผ‰ๅณๅฏ๏ผš + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +ๅœจ็›ธไพ่ฆ†ๅฏซไธญ๏ผŒๆˆ‘ๅ€‘ๅœจๅปบ็ซ‹ๆ–ฐ็š„ `Settings` ็‰ฉไปถๆ™‚่จญๅฎš `admin_email` ็š„ๆ–ฐๅ€ผ๏ผŒ็„ถๅพŒๅ›žๅ‚ณ่ฉฒๆ–ฐ็‰ฉไปถใ€‚ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅฐฑๅฏไปฅๆธฌ่ฉฆๅฎƒๆ˜ฏๅฆ่ขซไฝฟ็”จใ€‚ + +## ่ฎ€ๅ– `.env` ๆช” { #reading-a-env-file } + +ๅฆ‚ๆžœไฝ ๆœ‰่จฑๅคš่จญๅฎš๏ผŒ่€Œไธ”ๅœจไธๅŒ็’ฐๅขƒไธญๅฏ่ƒฝๅธธๅธธ่ฎŠๅ‹•๏ผŒๅฐ‡ๅฎƒๅ€‘ๆ”พๅœจไธ€ๅ€‹ๆช”ๆกˆไธญ๏ผŒ็„ถๅพŒๅƒ่ฎ€ๅ–็’ฐๅขƒ่ฎŠๆ•ธไธ€ๆจฃ่‡ช่ฉฒๆช”ๆกˆ่ฎ€ๅ–๏ผŒๅฏ่ƒฝๆœƒๅพˆๅฏฆ็”จใ€‚ + +้€™็จฎไฝœๆณ•ๅพˆๅธธ่ฆ‹๏ผŒ้€™ไบ›็’ฐๅขƒ่ฎŠๆ•ธ้€šๅธธๆ”พๅœจ `.env` ๆช”ไธญ๏ผŒ่€Œ่ฉฒๆช”ๆกˆ่ขซ็จฑ็‚บใ€Œdotenvใ€ใ€‚ + +/// tip + +ๅœจ้กž Unix ็ณป็ตฑ๏ผˆๅฆ‚ Linux ่ˆ‡ macOS๏ผ‰ไธญ๏ผŒไปฅ้ปž๏ผˆ`.`๏ผ‰้–‹้ ญ็š„ๆช”ๆกˆๆ˜ฏ้šฑ่—ๆช”ใ€‚ + +ไฝ† dotenv ๆช”ไธฆไธไธ€ๅฎšๅฟ…้ ˆไฝฟ็”จ้€™ๅ€‹็ขบๅˆ‡็š„ๆช”ๅใ€‚ + +/// + +Pydantic ้€้Žๅค–้ƒจๅ‡ฝๅผๅบซๆ”ฏๆด่ฎ€ๅ–้€™้กžๅž‹็š„ๆช”ๆกˆใ€‚ไฝ ๅฏไปฅ้–ฑ่ฎ€ๆ›ดๅคš๏ผšPydantic Settings๏ผšDotenv (.env) ๆ”ฏๆดใ€‚ + +/// tip + +่ฆ่ฎ“้€™ๅ€‹ๅŠŸ่ƒฝ้‹ไฝœ๏ผŒไฝ ้œ€่ฆ `pip install python-dotenv`ใ€‚ + +/// + +### `.env` ๆช” { #the-env-file } + +ไฝ ๅฏไปฅๆœ‰ไธ€ๅ€‹ `.env` ๆช”ๅฆ‚ไธ‹๏ผš + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### ๅพž `.env` ่ฎ€ๅ–่จญๅฎš { #read-settings-from-env } + +็„ถๅพŒๆ›ดๆ–ฐไฝ ็š„ `config.py`๏ผš + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip + +`model_config` ๅฑฌๆ€งๅƒ…็”จๆ–ผ Pydantic ็š„่จญๅฎšใ€‚ไฝ ๅฏไปฅ้–ฑ่ฎ€ๆ›ดๅคš๏ผšPydantic๏ผšๆฆ‚ๅฟต๏ผš่จญๅฎšใ€‚ + +/// + +ๅœจ้€™่ฃกๆˆ‘ๅ€‘ๅœจ Pydantic ็š„ `Settings` ้กžๅˆฅไธญๅฎš็พฉ่จญๅฎš `env_file`๏ผŒไธฆๅฐ‡ๅ…ถๅ€ผ่จญ็‚บ่ฆไฝฟ็”จ็š„ dotenv ๆช”ๅใ€‚ + +### ไฝฟ็”จ `lru_cache` ๅชๅปบ็ซ‹ไธ€ๆฌก `Settings` { #creating-the-settings-only-once-with-lru-cache } + +ๅพž็ฃ็ขŸ่ฎ€ๅ–ๆช”ๆกˆ้€šๅธธๆ˜ฏๆ˜‚่ฒด๏ผˆๆ…ข๏ผ‰็š„ๆ“ไฝœ๏ผŒๆ‰€ไปฅไฝ ๅฏ่ƒฝๅธŒๆœ›ๅชๅšไธ€ๆฌก๏ผŒ็„ถๅพŒ้‡่ค‡ไฝฟ็”จๅŒไธ€ๅ€‹่จญๅฎš็‰ฉไปถ๏ผŒ่€Œไธๆ˜ฏๅœจๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝ่ฎ€ๅ–ใ€‚ + +ไฝ†ๆฏๆฌกๆˆ‘ๅ€‘้€™ๆจฃๅš๏ผš + +```Python +Settings() +``` + +้ƒฝๆœƒๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„ `Settings` ็‰ฉไปถ๏ผŒ่€Œไธ”ๅœจๅปบ็ซ‹ๆ™‚ๆœƒๅ†ๆฌก่ฎ€ๅ– `.env` ๆช”ใ€‚ + +ๅฆ‚ๆžœ็›ธไพๅ‡ฝๅผๅชๆ˜ฏๅƒ้€™ๆจฃ๏ผš + +```Python +def get_settings(): + return Settings() +``` + +ๆˆ‘ๅ€‘ๅฐฑๆœƒ็‚บๆฏๅ€‹่ซ‹ๆฑ‚ๅปบ็ซ‹่ฉฒ็‰ฉไปถ๏ผŒไธฆๅœจๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝ่ฎ€ๅ– `.env` ๆช”ใ€‚โš ๏ธ + +ไฝ†็”ฑๆ–ผๆˆ‘ๅ€‘ๅœจไธŠๆ–นไฝฟ็”จไบ† `@lru_cache` ่ฃ้ฃพๅ™จ๏ผŒ`Settings` ็‰ฉไปถๅชๆœƒๅœจ็ฌฌไธ€ๆฌกๅ‘ผๅซๆ™‚ๅปบ็ซ‹ไธ€ๆฌกใ€‚โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +ไน‹ๅพŒๅœจไธ‹ไธ€ๆ‰น่ซ‹ๆฑ‚็š„็›ธไพไธญไปปไฝ•ๅฐ `get_settings()` ็š„ๅ‘ผๅซ๏ผŒ้ƒฝไธๆœƒๅ†ๅŸท่กŒ `get_settings()` ็š„ๅ…ง้ƒจ็จ‹ๅผ็ขผ่ˆ‡ๅปบ็ซ‹ๆ–ฐ็š„ `Settings` ็‰ฉไปถ๏ผŒ่€Œๆ˜ฏๆœƒไธ€ๅ†ๅ›žๅ‚ณ็ฌฌไธ€ๆฌกๅ‘ผๅซๆ™‚ๅ›žๅ‚ณ็š„ๅŒไธ€ๅ€‹็‰ฉไปถใ€‚ + +#### `lru_cache` ๆŠ€่ก“็ดฐ็ฏ€ { #lru-cache-technical-details } + +`@lru_cache` ๆœƒไฟฎๆ”นๅฎƒๆ‰€่ฃ้ฃพ็š„ๅ‡ฝๅผ๏ผŒไฝฟๅ…ถๅ›žๅ‚ณ็ฌฌไธ€ๆฌกๅ›žๅ‚ณ็š„็›ธๅŒๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆฏๆฌก้ƒฝ้‡ๆ–ฐ่จˆ็ฎ—ใ€ๅŸท่กŒๅ‡ฝๅผ็ขผใ€‚ + +ๅ› ๆญค๏ผŒ่ขซ่ฃ้ฃพ็š„ๅ‡ฝๅผๅฐๆ–ผๆฏ็ต„ๅƒๆ•ธ็ต„ๅˆๅชๆœƒๅŸท่กŒไธ€ๆฌกใ€‚ไน‹ๅพŒ๏ผŒๅ‡กๆ˜ฏไปฅๅฎŒๅ…จ็›ธๅŒๅƒๆ•ธ็ต„ๅˆๅ‘ผๅซๆ™‚๏ผŒ้ƒฝๆœƒ้‡่ค‡ไฝฟ็”จๅ…ˆๅ‰ๅฐๆ‡‰็š„ๅ›žๅ‚ณๅ€ผใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹ๅ‡ฝๅผ๏ผš + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +ไฝ ็š„็จ‹ๅผๅฏ่ƒฝๆœƒ้€™ๆจฃๅŸท่กŒ๏ผš + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +ๅœจๆˆ‘ๅ€‘็š„็›ธไพ `get_settings()` ้€™ๅ€‹ๆกˆไพ‹ไธญ๏ผŒ่ฉฒๅ‡ฝๅผ็”š่‡ณไธๅธถไปปไฝ•ๅƒๆ•ธ๏ผŒๅ› ๆญคๅฎƒ็ธฝๆ˜ฏๅ›žๅ‚ณ็›ธๅŒ็š„ๅ€ผใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅฎƒ็š„่กŒ็‚บๅนพไนŽๅฐฑๅƒๅ…จๅŸŸ่ฎŠๆ•ธใ€‚ไฝ†ๅ› ็‚บๅฎƒไฝฟ็”จ็›ธไพๅ‡ฝๅผ๏ผŒๅ› ๆญคๆˆ‘ๅ€‘ๅฏไปฅๅœจๆธฌ่ฉฆๆ™‚่ผ•้ฌ†ๅฐ‡ๅ…ถ่ฆ†ๅฏซใ€‚ + +`@lru_cache` ๆ˜ฏ `functools` ็š„ไธ€้ƒจๅˆ†๏ผŒ่€Œ `functools` ๆ˜ฏ Python ๆจ™ๆบ–็จ‹ๅผๅบซ็š„ไธ€้ƒจๅˆ†ใ€‚ไฝ ๅฏไปฅๅœจPython ๆ–‡ไปถไธญ้–ฑ่ฎ€ `@lru_cache` ไปฅไบ†่งฃๆ›ดๅคšใ€‚ + +## ๅ›ž้กง { #recap } + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic Settings ไพ†่™•็†ๆ‡‰็”จ็จ‹ๅผ็š„่จญๅฎšๆˆ–็ต„ๆ…‹๏ผŒไธฆไบซๆœ‰ Pydantic model ็š„ๅ…จ้ƒจ่ƒฝๅŠ›ใ€‚ + +- ้€้Ž็›ธไพๅฏไปฅ่ฎ“ๆธฌ่ฉฆๆ›ดๅฎนๆ˜“ใ€‚ +- ไฝ ๅฏไปฅๆญ้… `.env` ๆช”ไฝฟ็”จใ€‚ +- ไฝฟ็”จ `@lru_cache` ๅฏไปฅ้ฟๅ…ๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝ้‡่ค‡่ฎ€ๅ– dotenv ๆช”๏ผŒๅŒๆ™‚ไปๅฏๅœจๆธฌ่ฉฆๆ™‚่ฆ†ๅฏซ่จญๅฎšใ€‚ diff --git a/docs/zh-hant/docs/advanced/sub-applications.md b/docs/zh-hant/docs/advanced/sub-applications.md new file mode 100644 index 0000000000..773bc4b886 --- /dev/null +++ b/docs/zh-hant/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# ๅญๆ‡‰็”จ็จ‹ๅผ - ๆŽ›่ผ‰ { #sub-applications-mounts } + +่‹ฅไฝ ้œ€่ฆๅ…ฉๅ€‹ๅฝผๆญค็จ็ซ‹็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผ๏ผŒๅ„่‡ชๆ“ๆœ‰็จ็ซ‹็š„ OpenAPI ่ˆ‡ๆ–‡ไปถ UI๏ผŒไฝ ๅฏไปฅๆœ‰ไธ€ๅ€‹ไธปๆ‡‰็”จ๏ผŒไธฆใ€ŒๆŽ›่ผ‰ใ€ไธ€ๅ€‹๏ผˆๆˆ–ๅคšๅ€‹๏ผ‰ๅญๆ‡‰็”จ็จ‹ๅผใ€‚ + +## ๆŽ›่ผ‰ไธ€ๅ€‹ **FastAPI** ๆ‡‰็”จ็จ‹ๅผ { #mounting-a-fastapi-application } + +ใ€ŒๆŽ›่ผ‰ใ€ๆ˜ฏๆŒ‡ๅœจๆŸๅ€‹็‰นๅฎš่ทฏๅพ‘ไธ‹ๅŠ ๅ…ฅไธ€ๅ€‹ๅฎŒๅ…จใ€Œ็จ็ซ‹ใ€็š„ๆ‡‰็”จ็จ‹ๅผ๏ผŒไน‹ๅพŒ่ฉฒๆ‡‰็”จ็จ‹ๅผๆœƒ่ฒ ่ฒฌ่™•็†่ฉฒ่ทฏๅพ‘ๅบ•ไธ‹็š„ไธ€ๅˆ‡๏ผŒไฝฟ็”จ่ฉฒๅญๆ‡‰็”จ็จ‹ๅผไธญๅฎฃๅ‘Š็š„*่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰*ใ€‚ + +### ้ ‚ๅฑคๆ‡‰็”จ็จ‹ๅผ { #top-level-application } + +ๅ…ˆๅปบ็ซ‹ไธป๏ผˆ้ ‚ๅฑค๏ผ‰**FastAPI** ๆ‡‰็”จ็จ‹ๅผไปฅๅŠๅฎƒ็š„*่ทฏๅพ‘ๆ“ไฝœ*๏ผš + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### ๅญๆ‡‰็”จ็จ‹ๅผ { #sub-application } + +ๆŽฅ่‘—๏ผŒๅปบ็ซ‹ไฝ ็š„ๅญๆ‡‰็”จ็จ‹ๅผๅŠๅ…ถ*่ทฏๅพ‘ๆ“ไฝœ*ใ€‚ + +้€™ๅ€‹ๅญๆ‡‰็”จ็จ‹ๅผๅฐฑๆ˜ฏๅฆไธ€ๅ€‹ๆจ™ๆบ–็š„ FastAPI ๆ‡‰็”จ๏ผŒไฝ†้€™ๅ€‹ๆœƒ่ขซใ€ŒๆŽ›่ผ‰ใ€๏ผš + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### ๆŽ›่ผ‰ๅญๆ‡‰็”จ็จ‹ๅผ { #mount-the-sub-application } + +ๅœจไฝ ็š„้ ‚ๅฑคๆ‡‰็”จ็จ‹ๅผ `app` ไธญ๏ผŒๆŽ›่ผ‰ๅญๆ‡‰็”จ็จ‹ๅผ `subapi`ใ€‚ + +ๅœจๆญค็ฏ„ไพ‹ไธญ๏ผŒๅฎƒๆœƒ่ขซๆŽ›่ผ‰ๅœจ่ทฏๅพ‘ `/subapi`๏ผš + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### ๆชขๆŸฅ่‡ชๅ‹• API ๆ–‡ไปถ { #check-the-automatic-api-docs } + +็พๅœจ๏ผŒ็”จไฝ ็š„ๆช”ๆกˆๅŸท่กŒ `fastapi` ๆŒ‡ไปค๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +็„ถๅพŒ้–‹ๅ•Ÿไฝๆ–ผ http://127.0.0.1:8000/docs ็š„ๆ–‡ไปถใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐไธปๆ‡‰็”จ็š„่‡ชๅ‹• API ๆ–‡ไปถ๏ผŒๅชๅŒ…ๅซๅฎƒ่‡ชๅทฑ็š„*่ทฏๅพ‘ๆ“ไฝœ*๏ผš + + + +ๆŽฅ่‘—๏ผŒ้–‹ๅ•Ÿๅญๆ‡‰็”จ็จ‹ๅผ็š„ๆ–‡ไปถ๏ผšhttp://127.0.0.1:8000/subapi/docsใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐๅญๆ‡‰็”จ็จ‹ๅผ็š„่‡ชๅ‹• API ๆ–‡ไปถ๏ผŒๅชๅŒ…ๅซๅฎƒ่‡ชๅทฑ็š„*่ทฏๅพ‘ๆ“ไฝœ*๏ผŒ่€Œไธ”้ƒฝๅœจๆญฃ็ขบ็š„ๅญ่ทฏๅพ‘ๅ‰็ถด `/subapi` ไน‹ไธ‹๏ผš + + + +ๅฆ‚ๆžœไฝ ๅ˜—่ฉฆๅœจไปปไธ€ไป‹้ขไธญไบ’ๅ‹•๏ผŒๅฎƒๅ€‘้ƒฝๆœƒๆญฃๅธธ้‹ไฝœ๏ผŒๅ› ็‚บ็€่ฆฝๅ™จ่ƒฝ่ˆ‡ๅ„่‡ช็š„ๆ‡‰็”จ็จ‹ๅผๆˆ–ๅญๆ‡‰็”จ็จ‹ๅผ้€š่จŠใ€‚ + +### ๆŠ€่ก“็ดฐ็ฏ€๏ผš`root_path` { #technical-details-root-path } + +็•ถไฝ ๅƒไธŠ้ข้‚ฃๆจฃๆŽ›่ผ‰ๅญๆ‡‰็”จ็จ‹ๅผๆ™‚๏ผŒFastAPI ๆœƒไฝฟ็”จ ASGI ่ฆ็ฏ„ไธญ็š„ไธ€ๅ€‹ๆฉŸๅˆถ `root_path`๏ผŒๅฐ‡ๅญๆ‡‰็”จ็จ‹ๅผ็š„ๆŽ›่ผ‰่ทฏๅพ‘ๅ‘Š็Ÿฅๅฎƒใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅญๆ‡‰็”จ็จ‹ๅผๅฐฑๆœƒ็Ÿฅ้“ๅœจๆ–‡ไปถ UI ไฝฟ็”จ่ฉฒ่ทฏๅพ‘ๅ‰็ถดใ€‚ + +่€Œไธ”ๅญๆ‡‰็”จ็จ‹ๅผไนŸ่ƒฝๅ†ๆŽ›่ผ‰่‡ชๅทฑ็š„ๅญๆ‡‰็”จ็จ‹ๅผ๏ผŒไธ€ๅˆ‡้ƒฝ่ƒฝๆญฃ็ขบ้‹ไฝœ๏ผŒๅ› ็‚บ FastAPI ๆœƒ่‡ชๅ‹•่™•็†ๆ‰€ๆœ‰้€™ไบ› `root_path`ใ€‚ + +ไฝ ๅฏไปฅๅœจ[ๅœจไปฃ็†ไผบๆœๅ™จไน‹ๅพŒ](behind-a-proxy.md){.internal-link target=_blank}ไธ€็ฏ€ไธญ้€ฒไธ€ๆญฅไบ†่งฃ `root_path` ่ˆ‡ๅฆ‚ไฝ•้กฏๅผไฝฟ็”จๅฎƒใ€‚ diff --git a/docs/zh-hant/docs/advanced/templates.md b/docs/zh-hant/docs/advanced/templates.md new file mode 100644 index 0000000000..ffc7599ae2 --- /dev/null +++ b/docs/zh-hant/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# ๆจกๆฟ { #templates } + +ไฝ ๅฏไปฅๅœจ **FastAPI** ไธญไฝฟ็”จไปปๆ„ไฝ ๆƒณ่ฆ็š„ๆจกๆฟๅผ•ๆ“Žใ€‚ + +ๅธธ่ฆ‹็š„้ธๆ“‡ๆ˜ฏ Jinja2๏ผŒ่ˆ‡ Flask ่ˆ‡ๅ…ถไป–ๅทฅๅ…ทๆ‰€ไฝฟ็”จ็š„ไธ€ๆจฃใ€‚ + +ๆœ‰ไธ€ไบ›ๅทฅๅ…ทๅฏ่ฎ“ไฝ ่ผ•้ฌ†่จญๅฎš๏ผŒไธฆๅฏ็›ดๆŽฅๅœจไฝ ็š„ **FastAPI** ๆ‡‰็”จ็จ‹ๅผไธญไฝฟ็”จ๏ผˆ็”ฑ Starlette ๆไพ›๏ผ‰ใ€‚ + +## ๅฎ‰่ฃ็›ธไพๅฅ—ไปถ { #install-dependencies } + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๅ•Ÿ็”จๅฎƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ `jinja2`๏ผš + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## ไฝฟ็”จ `Jinja2Templates` { #using-jinja2templates } + +- ๅŒฏๅ…ฅ `Jinja2Templates`ใ€‚ +- ๅปบ็ซ‹ไธ€ๅ€‹ๅฏ้‡่ค‡ไฝฟ็”จ็š„ `templates` ็‰ฉไปถใ€‚ +- ๅœจๆœƒๅ›žๅ‚ณๆจกๆฟ็š„ใ€Œ*่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰*ใ€ไธญๅฎฃๅ‘Šไธ€ๅ€‹ `Request` ๅƒๆ•ธใ€‚ +- ไฝฟ็”จไฝ ๅปบ็ซ‹็š„ `templates` ไพ†ๆธฒๆŸ“ไธฆๅ›žๅ‚ณ `TemplateResponse`๏ผŒๅ‚ณๅ…ฅๆจกๆฟๅ็จฑใ€`request` ็‰ฉไปถ๏ผŒไปฅๅŠๅœจ Jinja2 ๆจกๆฟไธญไฝฟ็”จ็š„ใ€Œcontextใ€้ตๅ€ผๅฐๅญ—ๅ…ธใ€‚ + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note + +ๅœจ FastAPI 0.108.0ใ€Starlette 0.29.0 ไน‹ๅ‰๏ผŒ`name` ๆ˜ฏ็ฌฌไธ€ๅ€‹ๅƒๆ•ธใ€‚ + +ๆญคๅค–๏ผŒๅœจๆ›ดๆ—ฉ็š„็‰ˆๆœฌไธญ๏ผŒ`request` ็‰ฉไปถๆ˜ฏไฝœ็‚บ context ็š„้ตๅ€ผๅฐไน‹ไธ€ๅ‚ณ็ตฆ Jinja2 ็š„ใ€‚ + +/// + +/// tip + +้€้Žๅฎฃๅ‘Š `response_class=HTMLResponse`๏ผŒๆ–‡ไปถ UI ่ƒฝๅค ็Ÿฅ้“ๅ›žๆ‡‰ๅฐ‡ๆœƒๆ˜ฏ HTMLใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.templating import Jinja2Templates`ใ€‚ + +**FastAPI** ไปฅ `fastapi.templating` ็š„ๅฝขๅผๆไพ›่ˆ‡ `starlette.templating` ็›ธๅŒ็š„ๅ…งๅฎน๏ผŒๅƒ…็‚บไบ†ๆ–นไพฟไฝ ๏ผˆ้–‹็™ผ่€…๏ผ‰ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅˆฅ้ƒฝ็›ดๆŽฅไพ†่‡ช Starlette๏ผŒ`Request` ่ˆ‡ `StaticFiles` ไนŸๆ˜ฏๅฆ‚ๆญคใ€‚ + +/// + +## ๆ’ฐๅฏซๆจกๆฟ { #writing-templates } + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจ `templates/item.html` ็ทจๅฏซๆจกๆฟ๏ผŒไพ‹ๅฆ‚๏ผš + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### ๆจกๆฟ context ๅ€ผ { #template-context-values } + +ๅœจๅŒ…ๅซไปฅไธ‹ๅ…งๅฎน็š„ HTML ไธญ๏ผš + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...ๅฎƒๆœƒ้กฏ็คบไฝ ๅœจๅ‚ณๅ…ฅ็š„ context `dict` ไธญๆไพ›็š„ `id`๏ผš + +```Python +{"id": id} +``` + +ไพ‹ๅฆ‚๏ผŒ่‹ฅ ID ็‚บ `42`๏ผŒๆœƒๆธฒๆŸ“็‚บ๏ผš + +```html +Item ID: 42 +``` + +### ๆจกๆฟ `url_for` ๅƒๆ•ธ { #template-url-for-arguments } + +ไฝ ไนŸๅฏไปฅๅœจๆจกๆฟไธญไฝฟ็”จ `url_for()`๏ผŒๅฎƒๆ‰€ๆŽฅๅ—็š„ๅƒๆ•ธ่ˆ‡ไฝ ็š„ใ€Œ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰*ใ€ๆ‰€ไฝฟ็”จ็š„ๅƒๆ•ธ็›ธๅŒใ€‚ + +ๅ› ๆญค๏ผŒๅŒ…ๅซไปฅไธ‹ๅ…งๅฎน็š„ๅ€ๅกŠ๏ผš + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...ๆœƒ็”ข็”ŸๆŒ‡ๅ‘่ˆ‡ใ€Œ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*ใ€`read_item(id=id)` ็›ธๅŒ URL ็š„้€ฃ็ตใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่‹ฅ ID ็‚บ `42`๏ผŒๆœƒๆธฒๆŸ“็‚บ๏ผš + +```html + +``` + +## ๆจกๆฟ่ˆ‡้œๆ…‹ๆช”ๆกˆ { #templates-and-static-files } + +ไฝ ไนŸๅฏไปฅๅœจๆจกๆฟไธญไฝฟ็”จ `url_for()`๏ผŒไพ‹ๅฆ‚ๆญ้…ไฝ ไปฅ `name="static"` ๆŽ›่ผ‰็š„ `StaticFiles` ไฝฟ็”จใ€‚ + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅฎƒๆœƒ้€ฃ็ตๅˆฐ `static/styles.css` ็š„ CSS ๆช”ๆกˆ๏ผŒๅ…งๅฎน็‚บ๏ผš + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +่€Œไธ”ๅ› ็‚บไฝ ไฝฟ็”จไบ† `StaticFiles`๏ผŒ่ฉฒ CSS ๆช”ๆกˆๆœƒ็”ฑไฝ ็š„ **FastAPI** ๆ‡‰็”จ็จ‹ๅผๅœจ URL `/static/styles.css` ่‡ชๅ‹•ๆไพ›ใ€‚ + +## ๆ›ดๅคš็ดฐ็ฏ€ { #more-details } + +ๆƒณไบ†่งฃๆ›ดๅคš็ดฐ็ฏ€๏ผˆๅŒ…ๅซๅฆ‚ไฝ•ๆธฌ่ฉฆๆจกๆฟ๏ผ‰๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ็š„ๆจกๆฟ่ชชๆ˜Žๆ–‡ไปถใ€‚ diff --git a/docs/zh-hant/docs/advanced/testing-dependencies.md b/docs/zh-hant/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000..3ce72ccab8 --- /dev/null +++ b/docs/zh-hant/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# ็”จ่ฆ†ๅฏซๆธฌ่ฉฆ็›ธไพ { #testing-dependencies-with-overrides } + +## ๅœจๆธฌ่ฉฆๆœŸ้–“่ฆ†ๅฏซ็›ธไพ { #overriding-dependencies-during-testing } + +ๆœ‰ไบ›ๆƒ…ๅขƒไฝ ๅฏ่ƒฝๆƒณๅœจๆธฌ่ฉฆๆ™‚่ฆ†ๅฏซ๏ผˆoverride๏ผ‰ๆŸๅ€‹็›ธไพ๏ผˆdependency๏ผ‰ใ€‚ + +ไฝ ไธๅธŒๆœ›ๅŸท่กŒๅŽŸๆœฌ็š„็›ธไพ๏ผˆไปฅๅŠๅฎƒๅฏ่ƒฝๅ…ทๆœ‰็š„ไปปไฝ•ๅญ็›ธไพ๏ผ‰ใ€‚ + +็›ธๅๅœฐ๏ผŒไฝ ๆƒณๆไพ›ไธ€ๅ€‹ๅชๅœจๆธฌ่ฉฆๆœŸ้–“ไฝฟ็”จ็š„ไธๅŒ็›ธไพ๏ผˆๅฏ่ƒฝๅชๅœจ็‰นๅฎšๆธฌ่ฉฆไธญ๏ผ‰๏ผŒไธฆๅ›žๅ‚ณไธ€ๅ€‹ๅฏไปฅๅœจๅŽŸๆœฌ็›ธไพๅ€ผ่ขซไฝฟ็”จไน‹่™•ไฝฟ็”จ็š„ๅ€ผใ€‚ + +### ไฝฟ็”จๆƒ…ๅขƒ๏ผšๅค–้ƒจๆœๅ‹™ { #use-cases-external-service } + +ไพ‹ๅฆ‚ไฝ ๆœ‰ไธ€ๅ€‹้œ€่ฆๅ‘ผๅซ็š„ๅค–้ƒจ้ฉ—่ญ‰ๆไพ›่€…ใ€‚ + +ไฝ ๅ‚ณ้€ไธ€ๅ€‹ token๏ผŒๅฎƒๆœƒๅ›žๅ‚ณไธ€ๅ€‹ๅทฒ้ฉ—่ญ‰็š„ไฝฟ็”จ่€…ใ€‚ + +้€™ๅ€‹ๆไพ›่€…ๅฏ่ƒฝๆŒ‰ๆฏๅ€‹่ซ‹ๆฑ‚ๆ”ถ่ฒป๏ผŒ่€Œไธ”ๅ‘ผๅซๅฎƒๅฏ่ƒฝๆฏ”ๅœจๆธฌ่ฉฆไธญไฝฟ็”จๅ›บๅฎš็š„ๆจกๆ“ฌไฝฟ็”จ่€…ๅคš่Šฑไธ€ไบ›ๆ™‚้–“ใ€‚ + +ไฝ ๅคงๆฆ‚ๅชๆƒณๅฐๅค–้ƒจๆไพ›่€…ๆธฌ่ฉฆไธ€ๆฌก๏ผŒ่€Œไธ้œ€่ฆๅœจๆฏๅ€‹ๆธฌ่ฉฆ้ƒฝๅ‘ผๅซๅฎƒใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅ่ฆ†ๅฏซ็”จไพ†ๅ‘ผๅซ่ฉฒๆไพ›่€…็š„็›ธไพ๏ผŒไธฆๅœจๆธฌ่ฉฆไธญไฝฟ็”จ่‡ช่จ‚็š„็›ธไพไพ†ๅ›žๅ‚ณไธ€ๅ€‹ๆจกๆ“ฌไฝฟ็”จ่€…ใ€‚ + +### ไฝฟ็”จ `app.dependency_overrides` ๅฑฌๆ€ง { #use-the-app-dependency-overrides-attribute } + +ๅฐ้€™ไบ›ๆƒ…ๆณ๏ผŒไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผๆœ‰ไธ€ๅ€‹ๅฑฌๆ€ง `app.dependency_overrides`๏ผŒๅฎƒๆ˜ฏไธ€ๅ€‹็ฐกๅ–ฎ็š„ `dict`ใ€‚ + +่ฆๅœจๆธฌ่ฉฆๆ™‚่ฆ†ๅฏซๆŸๅ€‹็›ธไพ๏ผŒๆŠŠๅŽŸๅง‹็›ธไพ๏ผˆๅ‡ฝๅผ๏ผ‰ไฝœ็‚บ้ต๏ผŒไธฆๆŠŠไฝ ็š„่ฆ†ๅฏซ็›ธไพ๏ผˆๅฆไธ€ๅ€‹ๅ‡ฝๅผ๏ผ‰ไฝœ็‚บๅ€ผใ€‚ + +ๆŽฅ่‘— FastAPI ๆœƒๅ‘ผๅซ้€™ๅ€‹่ฆ†ๅฏซ๏ผŒ่€Œไธๆ˜ฏๅŽŸๆœฌ็š„็›ธไพใ€‚ + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip + +ไฝ ๅฏไปฅ็‚บๆ‡‰็”จ็จ‹ๅผไธญไปปไฝ•ๅœฐๆ–นไฝฟ็”จๅˆฐ็š„็›ธไพ่จญๅฎš่ฆ†ๅฏซใ€‚ + +ๅŽŸๅง‹็›ธไพๅฏไปฅ็”จๅœจ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*ใ€*่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ*๏ผˆ็•ถไฝ ไธไฝฟ็”จๅ…ถๅ›žๅ‚ณๅ€ผๆ™‚๏ผ‰ใ€`.include_router()` ๅ‘ผๅซ็ญ‰ใ€‚ + +FastAPI ไป็„ถ่ƒฝๅค ๅฐ‡ๅ…ถ่ฆ†ๅฏซใ€‚ + +/// + +็„ถๅพŒไฝ ๅฏไปฅๅฐ‡ `app.dependency_overrides` ่จญ็‚บ็ฉบ็š„ `dict` ไปฅ้‡่จญ๏ผˆ็งป้™ค๏ผ‰ๆ‰€ๆœ‰่ฆ†ๅฏซ๏ผš + +```Python +app.dependency_overrides = {} +``` + +/// tip + +ๅฆ‚ๆžœๅชๆƒณๅœจๆŸไบ›ๆธฌ่ฉฆไธญ่ฆ†ๅฏซ็›ธไพ๏ผŒไฝ ๅฏไปฅๅœจๆธฌ่ฉฆ้–‹ๅง‹ๆ™‚๏ผˆๆธฌ่ฉฆๅ‡ฝๅผๅ…ง๏ผ‰่จญๅฎš่ฆ†ๅฏซ๏ผŒไธฆๅœจ็ตๆŸๆ™‚๏ผˆๆธฌ่ฉฆๅ‡ฝๅผ็ตๅฐพ๏ผ‰้‡่จญใ€‚ + +/// diff --git a/docs/zh-hant/docs/advanced/testing-events.md b/docs/zh-hant/docs/advanced/testing-events.md new file mode 100644 index 0000000000..db678977a3 --- /dev/null +++ b/docs/zh-hant/docs/advanced/testing-events.md @@ -0,0 +1,11 @@ +# ๆธฌ่ฉฆไบ‹ไปถ๏ผšlifespan ่ˆ‡ startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +็•ถไฝ ้œ€่ฆๅœจๆธฌ่ฉฆไธญๅŸท่กŒ lifespan๏ผˆ็”Ÿๅ‘ฝ้€ฑๆœŸ๏ผ‰ๆ™‚๏ผŒไฝ ๅฏไปฅไฝฟ็”จ TestClient ไธฆๆญ้… with ้™ณ่ฟฐๅผ๏ผš + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + +ไฝ ๅฏไปฅ้–ฑ่ฎ€ๆ›ดๅคš็ดฐ็ฏ€๏ผš[ๅœจๆธฌ่ฉฆไธญๅŸท่กŒ lifespan](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)๏ผˆStarlette ๅฎ˜ๆ–นๆ–‡ไปถ๏ผ‰ใ€‚ + +ๅฐๆ–ผๅทฒๆฃ„็”จ็š„ `startup` ๅ’Œ `shutdown` ไบ‹ไปถ๏ผŒไฝ ๅฏไปฅ้€™ๆจฃไฝฟ็”จ TestClient๏ผš + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/zh-hant/docs/advanced/testing-websockets.md b/docs/zh-hant/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000..7348e60fdf --- /dev/null +++ b/docs/zh-hant/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# ๆธฌ่ฉฆ WebSocket { #testing-websockets } + +ไฝ ๅฏไปฅไฝฟ็”จ็›ธๅŒ็š„ `TestClient` ไพ†ๆธฌ่ฉฆ WebSocketใ€‚ + +็‚บๆญค๏ผŒไฝ ๅฏไปฅๅœจ `with` ้™ณ่ฟฐๅผไธญไฝฟ็”จ `TestClient`๏ผŒ้€ฃ็ทšๅˆฐ่ฉฒ WebSocket๏ผš + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | ๆณจๆ„ + +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ็š„ ๆธฌ่ฉฆ WebSocket ๆ–‡ไปถใ€‚ + +/// diff --git a/docs/zh-hant/docs/advanced/using-request-directly.md b/docs/zh-hant/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000..f1dae9bf29 --- /dev/null +++ b/docs/zh-hant/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# ็›ดๆŽฅไฝฟ็”จ Request { #using-the-request-directly } + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไฝ ้ƒฝๆ˜ฏ็”จๅฐๆ‡‰็š„ๅž‹ๅˆฅไพ†ๅฎฃๅ‘Šไฝ ้œ€่ฆ็š„่ซ‹ๆฑ‚ๅ„้ƒจๅˆ†ใ€‚ + +ไพ‹ๅฆ‚ๅพžไปฅไธ‹ไพ†ๆบๅ–ๅพ—่ณ‡ๆ–™๏ผš + +- ่ทฏๅพ‘ไธญ็š„ๅƒๆ•ธใ€‚ +- ๆจ™้ ญใ€‚ +- Cookiesใ€‚ +- ็ญ‰็ญ‰ใ€‚ + +้€™้บผๅšๆ™‚๏ผŒFastAPI ๆœƒ่‡ชๅ‹•้ฉ—่ญ‰ไธฆ่ฝ‰ๆ›้€™ไบ›่ณ‡ๆ–™๏ผŒ้‚„ๆœƒ็‚บไฝ ็š„ API ็”ข็”Ÿๆ–‡ไปถใ€‚ + +ไฝ†ๆœ‰ไบ›ๆƒ…ๆณไฝ ๅฏ่ƒฝ้œ€่ฆ็›ดๆŽฅๅญ˜ๅ– `Request` ็‰ฉไปถใ€‚ + +## ้—œๆ–ผ `Request` ็‰ฉไปถ็š„็ดฐ็ฏ€ { #details-about-the-request-object } + +็”ฑๆ–ผ FastAPI ๅบ•ๅฑคๅ…ถๅฏฆๆ˜ฏ Starlette๏ผŒๅ†ๅŠ ไธŠไธ€ๅฑคๅทฅๅ…ท๏ผŒๅ› ๆญคๅœจ้œ€่ฆๆ™‚ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ Starlette ็š„ `Request` ็‰ฉไปถใ€‚ + +ๅŒๆ™‚ไนŸไปฃ่กจ๏ผŒๅฆ‚ๆžœไฝ ็›ดๆŽฅๅพž `Request` ็‰ฉไปถๅ–ๅพ—่ณ‡ๆ–™๏ผˆไพ‹ๅฆ‚่ฎ€ๅ– body๏ผ‰๏ผŒFastAPI ไธๆœƒๆ›ฟๅฎƒๅš้ฉ—่ญ‰ใ€่ฝ‰ๆ›ๆˆ–ๆ–‡ไปถๅŒ–๏ผˆ้€้Ž OpenAPI ็‚บ่‡ชๅ‹•ๅŒ–็š„ API ไป‹้ข็”ข็”Ÿๆ–‡ไปถ๏ผ‰ใ€‚ + +ไธ้Ž๏ผŒๅ…ถไป–ไปฅไธ€่ˆฌๆ–นๅผๅฎฃๅ‘Š็š„ๅƒๆ•ธ๏ผˆไพ‹ๅฆ‚ไปฅ Pydantic ๆจกๅž‹ๅฎฃๅ‘Š็š„ body๏ผ‰ไป็„ถๆœƒ่ขซ้ฉ—่ญ‰ใ€่ฝ‰ๆ›ใ€ๅŠ ไธŠๆจ™่จป็ญ‰ใ€‚ + +ไฝ†ๅœจๆŸไบ›็‰นๅฎšๆƒ…ๅขƒไธ‹๏ผŒ็›ดๆŽฅๅ–ๅพ— `Request` ็‰ฉไปถๆœƒๅพˆๅฏฆ็”จใ€‚ + +## ็›ดๆŽฅไฝฟ็”จ `Request` ็‰ฉไปถ { #use-the-request-object-directly } + +ๅ‡่จญไฝ ๆƒณๅœจไฝ ็š„ ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰ ไธญๅ–ๅพ—็”จๆˆถ็ซฏ็š„ IP ไฝๅ€๏ผไธปๆฉŸใ€‚ + +็‚บๆญค๏ผŒไฝ ้œ€่ฆ็›ดๆŽฅๅญ˜ๅ–่ซ‹ๆฑ‚ใ€‚ + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +ๅช่ฆๅœจ ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ ไธญๅฎฃๅ‘Šไธ€ๅ€‹ๅž‹ๅˆฅ็‚บ `Request` ็š„ๅƒๆ•ธ๏ผŒFastAPI ๅฐฑๆœƒๅฐ‡็•ถๅ‰็š„ `Request` ๅ‚ณๅ…ฅ่ฉฒๅƒๆ•ธใ€‚ + +/// tip + +ๆณจๆ„ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ้™คไบ† request ๅƒๆ•ธไน‹ๅค–๏ผŒๆˆ‘ๅ€‘ไนŸๅฎฃๅ‘Šไบ†ไธ€ๅ€‹่ทฏๅพ‘ๅƒๆ•ธใ€‚ + +ๅ› ๆญค๏ผŒ่ทฏๅพ‘ๅƒๆ•ธๆœƒ่ขซๆ“ทๅ–ใ€้ฉ—่ญ‰ใ€่ฝ‰ๆ›็‚บๆŒ‡ๅฎšๅž‹ๅˆฅ๏ผŒไธฆๅœจ OpenAPI ไธญๅŠ ๅ…ฅๆจ™่จปใ€‚ + +ๅŒ็†๏ผŒไฝ ๅฏไปฅ็…งๅธธๅฎฃๅ‘Šๅ…ถไป–ๅƒๆ•ธ๏ผŒไธฆๅฆๅค–ๅŒๆ™‚ๅ–ๅพ— `Request`ใ€‚ + +/// + +## `Request` ๆ–‡ไปถ { #request-documentation } + +ไฝ ๅฏไปฅๅœจ Starlette ๅฎ˜ๆ–นๆ–‡ไปถ็ซ™้ปžไธญ็š„ `Request` ็‰ฉไปถ ไบ†่งฃๆ›ดๅคš็ดฐ็ฏ€ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request`ใ€‚ + +FastAPI ไน‹ๆ‰€ไปฅ็›ดๆŽฅๆไพ›ๅฎƒ๏ผŒๆ˜ฏ็‚บไบ†่ฎ“้–‹็™ผ่€…ๆ›ดๆ–นไพฟ๏ผ›ไฝ†ๅฎƒๆœฌ่บซๆ˜ฏไพ†่‡ช Starletteใ€‚ + +/// diff --git a/docs/zh-hant/docs/advanced/websockets.md b/docs/zh-hant/docs/advanced/websockets.md new file mode 100644 index 0000000000..c4e904f6f6 --- /dev/null +++ b/docs/zh-hant/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +ไฝ ๅฏไปฅๅœจ **FastAPI** ไธญไฝฟ็”จ WebSocketsใ€‚ + +## ๅฎ‰่ฃ `websockets` { #install-websockets } + +่ซ‹ๅ…ˆๅปบ็ซ‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๅ•Ÿ็”จๅฎƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ `websockets`๏ผˆไธ€ๅ€‹่ฎ“ไฝ ๆ›ดๅฎนๆ˜“ไฝฟ็”จใ€ŒWebSocketใ€้€š่จŠๅ”ๅฎš็š„ Python ๅฅ—ไปถ๏ผ‰๏ผš + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets ็”จๆˆถ็ซฏ { #websockets-client } + +### ๅœจ็”Ÿ็”ข็’ฐๅขƒ { #in-production } + +ๅœจไฝ ็š„็”Ÿ็”ข็ณป็ตฑไธญ๏ผŒไฝ ๅพˆๅฏ่ƒฝๆœ‰ไธ€ๅ€‹ไฝฟ็”จ็พไปฃๆก†ๆžถ๏ผˆๅฆ‚ Reactใ€Vue.js ๆˆ– Angular๏ผ‰ๅปบ็ซ‹็š„ๅ‰็ซฏใ€‚ + +่€Œ็‚บไบ†้€้Ž WebSockets ่ˆ‡ๅพŒ็ซฏ้€š่จŠ๏ผŒไฝ ้€šๅธธๆœƒไฝฟ็”จๅ‰็ซฏ็š„ๅทฅๅ…ทใ€‚ + +ๆˆ–่€…ไฝ ๅฏ่ƒฝๆœ‰ไธ€ๅ€‹ๅŽŸ็”Ÿ่กŒๅ‹•ๆ‡‰็”จ๏ผŒไฝฟ็”จๅŽŸ็”Ÿ็จ‹ๅผ็ขผ็›ดๆŽฅ่ˆ‡ WebSocket ๅพŒ็ซฏ้€š่จŠใ€‚ + +ๅˆๆˆ–่€…ไฝ ๆœ‰ๅ…ถไป–ไปปไฝ•ๆ–นๅผ่ˆ‡ WebSocket ็ซฏ้ปž้€š่จŠใ€‚ + +--- + +ไฝ†ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๆœƒ็”จไธ€ๅ€‹้žๅธธ็ฐกๅ–ฎ็š„ HTML ๆ–‡ไปถ่ˆ‡ไธ€ไบ› JavaScript๏ผŒๅ…จ้ƒฝๅฏซๅœจไธ€ๅ€‹้•ทๅญ—ไธฒ่ฃกใ€‚ + +็•ถ็„ถ๏ผŒ้€™ไธฆไธ็†ๆƒณ๏ผŒไฝ ไธๆœƒๅœจ็”Ÿ็”ข็’ฐๅขƒ้€™ๆจฃๅšใ€‚ + +ๅœจ็”Ÿ็”ข็’ฐๅขƒไฝ ้€šๅธธๆœƒ็”จไธŠ่ฟฐๅ…ถไธญไธ€็จฎๆ–นๅผใ€‚ + +ไฝ†้€™ๆ˜ฏ่ƒฝ่ฎ“ๆˆ‘ๅ€‘ๅฐˆๆณจๆ–ผ WebSocket ไผบๆœ็ซฏไธฆ่ท‘่ตทไธ€ๅ€‹ๅฏ้‹ไฝœ็ฏ„ไพ‹็š„ๆœ€็ฐกๅ–ฎๆ–นๅผ๏ผš + +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} + +## ๅปบ็ซ‹ไธ€ๅ€‹ `websocket` { #create-a-websocket } + +ๅœจไฝ ็š„ **FastAPI** ๆ‡‰็”จไธญ๏ผŒๅปบ็ซ‹ไธ€ๅ€‹ `websocket`๏ผš + +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.websockets import WebSocket`ใ€‚ + +**FastAPI** ็›ดๆŽฅๆไพ›็›ธๅŒ็š„ `WebSocket` ๅชๆ˜ฏ็‚บไบ†ๆ–นไพฟไฝ ้€™ไฝ้–‹็™ผ่€…๏ผŒไฝ†ๅฎƒๅ…ถๅฏฆๆ˜ฏ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +## ็ญ‰ๅพ…่ˆ‡ๅ‚ณ้€่จŠๆฏ { #await-for-messages-and-send-messages } + +ๅœจไฝ ็š„ WebSocket ่ทฏ็”ฑไธญ๏ผŒไฝ ๅฏไปฅ `await` ๆŽฅๆ”ถ่จŠๆฏไธฆๅ‚ณ้€่จŠๆฏใ€‚ + +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} + +ไฝ ๅฏไปฅๆŽฅๆ”ถ่ˆ‡ๅ‚ณ้€ไบŒ้€ฒไฝใ€ๆ–‡ๅญ—่ˆ‡ JSON ่ณ‡ๆ–™ใ€‚ + +## ่ฉฆ่ฉฆ็œ‹ { #try-it } + +ๅฆ‚ๆžœไฝ ็š„ๆช”ๆกˆๅ็‚บ `main.py`๏ผŒ็”จไปฅไธ‹ๆŒ‡ไปคๅŸท่กŒๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ๅœจ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000ใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐไธ€ๅ€‹ๅƒ้€™ๆจฃ็š„็ฐกๅ–ฎ้ ้ข๏ผš + + + +ไฝ ๅฏไปฅๅœจ่ผธๅ…ฅๆก†่ผธๅ…ฅ่จŠๆฏไธฆ้€ๅ‡บ๏ผš + + + +ไฝ ็š„ **FastAPI** ๆ‡‰็”จๆœƒ้€้Ž WebSockets ๅ›žๆ‡‰๏ผš + + + +ไฝ ๅฏไปฅๅ‚ณ้€๏ผˆ่ˆ‡ๆŽฅๆ”ถ๏ผ‰ๅคšๅ‰‡่จŠๆฏ๏ผš + + + +่€Œไธ”ๅฎƒๅ€‘้ƒฝๆœƒไฝฟ็”จๅŒไธ€ๅ€‹ WebSocket ้€ฃ็ทšใ€‚ + +## ไฝฟ็”จ `Depends` ่ˆ‡ๅ…ถไป–ๅŠŸ่ƒฝ { #using-depends-and-others } + +ๅœจ WebSocket ็ซฏ้ปžไธญ๏ผŒไฝ ๅฏไปฅๅพž `fastapi` ๅŒฏๅ…ฅไธฆไฝฟ็”จ๏ผš + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +ๅฎƒๅ€‘็š„้‹ไฝœๆ–นๅผ่ˆ‡ๅ…ถไป– FastAPI ็ซฏ้ปž/*่ทฏๅพ‘ๆ“ไฝœ* ็›ธๅŒ๏ผš + +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} + +/// info + +ๅ› ็‚บ้€™ๆ˜ฏ WebSocket๏ผŒๆ‹‹ๅ‡บ `HTTPException` ไธฆๆฒ’ๆœ‰ๆ„็พฉ๏ผŒๅ› ๆญคๆˆ‘ๅ€‘ๆ”น็‚บๆ‹‹ๅ‡บ `WebSocketException`ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ่ฆ็ฏ„ไธญๅฎš็พฉ็š„ๆœ‰ๆ•ˆ้—œ้–‰ไปฃ็ขผไน‹ไธ€ใ€‚ + +/// + +### ็”จไพ่ณด่ฉฆ็”จ WebSocket { #try-the-websockets-with-dependencies } + +ๅฆ‚ๆžœไฝ ็š„ๆช”ๆกˆๅ็‚บ `main.py`๏ผŒ็”จไปฅไธ‹ๆŒ‡ไปคๅŸท่กŒๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ๅœจ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000ใ€‚ + +ๅœจ้‚ฃ่ฃกไฝ ๅฏไปฅ่จญๅฎš๏ผš + +* "Item ID"๏ผŒ็”จๆ–ผ่ทฏๅพ‘ใ€‚ +* "Token"๏ผŒไฝœ็‚บๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +/// tip + +ๆณจๆ„ๆŸฅ่ฉขๅƒๆ•ธ `token` ๆœƒ็”ฑไธ€ๅ€‹ไพ่ณด่™•็†ใ€‚ + +/// + +ไน‹ๅพŒไฝ ๅฐฑ่ƒฝ้€ฃ็ทšๅˆฐ WebSocket๏ผŒไธฆ้–‹ๅง‹ๆ”ถ็™ผ่จŠๆฏ๏ผš + + + +## ่™•็†ๆ–ท็ทš่ˆ‡ๅคšๅ€‹็”จๆˆถ็ซฏ { #handling-disconnections-and-multiple-clients } + +็•ถ WebSocket ้€ฃ็ทš้—œ้–‰ๆ™‚๏ผŒ`await websocket.receive_text()` ๆœƒๆ‹‹ๅ‡บ `WebSocketDisconnect` ไพ‹ๅค–๏ผŒไฝ ๅฏไปฅๅƒ็ฏ„ไพ‹ไธญ้‚ฃๆจฃๆ•ๆ‰ไธฆ่™•็†ใ€‚ + +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} + +่ฉฆ็”จๆ–นๅผ๏ผš + +* ็”จๅคšๅ€‹็€่ฆฝๅ™จๅˆ†้ ้–‹ๅ•Ÿ่ฉฒๆ‡‰็”จใ€‚ +* ๅพžๆฏๅ€‹ๅˆ†้ ๅ‚ณ้€่จŠๆฏใ€‚ +* ็„ถๅพŒ้—œ้–‰ๅ…ถไธญไธ€ๅ€‹ๅˆ†้ ใ€‚ + +้€™ๆœƒๅผ•็™ผ `WebSocketDisconnect` ไพ‹ๅค–๏ผŒๅ…ถไป–ๆ‰€ๆœ‰็”จๆˆถ็ซฏ้ƒฝๆœƒๆ”ถๅˆฐ้กžไผผไปฅไธ‹็š„่จŠๆฏ๏ผš + +``` +Client #1596980209979 left the chat +``` + +/// tip + +ไธŠ้ข็š„ๆ‡‰็”จๆ˜ฏไธ€ๅ€‹ๆฅต็ฐก็ฏ„ไพ‹๏ผŒ็”จไพ†็คบ็ฏ„ๅฆ‚ไฝ•่™•็†ไธฆๅ‘ๅคšๅ€‹ WebSocket ้€ฃ็ทšๅปฃๆ’ญ่จŠๆฏใ€‚ + +ไฝ†่ซ‹ๆณจๆ„๏ผŒๅ› ็‚บๆ‰€ๆœ‰็‹€ๆ…‹้ƒฝๅœจ่จ˜ๆ†ถ้ซ”ไธญ็š„ๅ–ฎไธ€ list ่ฃก็ฎก็†๏ผŒๅฎƒๅชๆœƒๅœจ่ฉฒ็จ‹ๅบๅŸท่กŒๆœŸ้–“็”Ÿๆ•ˆ๏ผŒไธ”ๅƒ…้ฉ็”จๆ–ผๅ–ฎไธ€็จ‹ๅบใ€‚ + +ๅฆ‚ๆžœไฝ ้œ€่ฆไธ€ๅ€‹ๅฎนๆ˜“่ˆ‡ FastAPI ๆ•ดๅˆใ€ไฝ†ๆ›ดๅฅๅฃฏ๏ผŒไธ”ๅฏ็”ฑ Redisใ€PostgreSQL ็ญ‰ๅพŒ็ซฏๆ”ฏๆด็š„ๆ–นๆกˆ๏ผŒ่ซ‹ๅƒ่€ƒ encode/broadcasterใ€‚ + +/// + +## ๆ›ดๅคš่ณ‡่จŠ { #more-info } + +ๆƒณไบ†่งฃๆ›ดๅคš้ธ้ …๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ็š„ๆ–‡ไปถ๏ผš + +* `WebSocket` ้กžๅˆฅใ€‚ +* ไปฅ้กžๅˆฅ็‚บๅŸบ็คŽ็š„ WebSocket ่™•็†ใ€‚ diff --git a/docs/zh-hant/docs/advanced/wsgi.md b/docs/zh-hant/docs/advanced/wsgi.md new file mode 100644 index 0000000000..9d03b56924 --- /dev/null +++ b/docs/zh-hant/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# ๅŒ…ๅซ WSGI๏ผšFlaskใ€Django ็ญ‰ { #including-wsgi-flask-django-others } + +ไฝ ๅฏไปฅๅƒๅœจ [ๅญๆ‡‰็”จ็จ‹ๅผ - ๆŽ›่ผ‰](sub-applications.md){.internal-link target=_blank}ใ€[ๅœจ Proxy ๅพŒๆ–น](behind-a-proxy.md){.internal-link target=_blank} ไธญๆ‰€่ฆ‹้‚ฃๆจฃๆŽ›่ผ‰ WSGI ๆ‡‰็”จใ€‚ + +็‚บๆญค๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `WSGIMiddleware` ไพ†ๅŒ…ไฝไฝ ็š„ WSGI ๆ‡‰็”จ๏ผŒไพ‹ๅฆ‚ Flaskใ€Django ็ญ‰ใ€‚ + +## ไฝฟ็”จ `WSGIMiddleware` { #using-wsgimiddleware } + +/// info + +้€™้œ€่ฆๅ…ˆๅฎ‰่ฃ `a2wsgi`๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `pip install a2wsgi`ใ€‚ + +/// + +ไฝ ้œ€่ฆๅพž `a2wsgi` ๅŒฏๅ…ฅ `WSGIMiddleware`ใ€‚ + +็„ถๅพŒ็”จ่ฉฒ middleware ๅŒ…ไฝ WSGI๏ผˆไพ‹ๅฆ‚ Flask๏ผ‰ๆ‡‰็”จใ€‚ + +ๆŽฅ่‘—ๆŠŠๅฎƒๆŽ›่ผ‰ๅˆฐๆŸๅ€‹่ทฏๅพ‘ไธ‹ใ€‚ + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note + +ๅ…ˆๅ‰ๅปบ่ญฐไฝฟ็”จไพ†่‡ช `fastapi.middleware.wsgi` ็š„ `WSGIMiddleware`๏ผŒไฝ†็พๅœจๅทฒๆฃ„็”จใ€‚ + +ๅปบ่ญฐๆ”น็”จ `a2wsgi` ๅฅ—ไปถใ€‚็”จๆณ•ไฟๆŒ็›ธๅŒใ€‚ + +ๅช่ฆ็ขบไฟๅทฒๅฎ‰่ฃ `a2wsgi`๏ผŒไธฆๅพž `a2wsgi` ๆญฃ็ขบๅŒฏๅ…ฅ `WSGIMiddleware` ๅณๅฏใ€‚ + +/// + +## ่ฉฆ่ฉฆ็œ‹ { #check-it } + +็พๅœจ๏ผŒไฝๆ–ผ่ทฏๅพ‘ `/v1/` ๅบ•ไธ‹็š„ๆ‰€ๆœ‰่ซ‹ๆฑ‚้ƒฝๆœƒ็”ฑ Flask ๆ‡‰็”จ่™•็†ใ€‚ + +ๅ…ถ้ค˜ๅ‰‡็”ฑ **FastAPI** ่™•็†ใ€‚ + +ๅฆ‚ๆžœไฝ ๅ•Ÿๅ‹•ๅฎƒไธฆๅ‰ๅพ€ http://localhost:8000/v1/๏ผŒไฝ ๆœƒ็œ‹ๅˆฐไพ†่‡ช Flask ็š„ๅ›žๆ‡‰๏ผš + +```txt +Hello, World from Flask! +``` + +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€ http://localhost:8000/v2๏ผŒไฝ ๆœƒ็œ‹ๅˆฐไพ†่‡ช FastAPI ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/zh-hant/docs/alternatives.md b/docs/zh-hant/docs/alternatives.md new file mode 100644 index 0000000000..340c47d8ba --- /dev/null +++ b/docs/zh-hant/docs/alternatives.md @@ -0,0 +1,485 @@ +# ๆ›ฟไปฃๆ–นๆกˆใ€้ˆๆ„Ÿ่ˆ‡ๆฏ”่ผƒ { #alternatives-inspiration-and-comparisons } + +ๅ•Ÿ็™ผ FastAPI ็š„ไพ†ๆบใ€่ˆ‡ๅ…ถไป–ๆ–นๆกˆ็š„ๆฏ”่ผƒ๏ผŒไปฅๅŠๅพžไธญๅญธๅˆฐ็š„ๅ…งๅฎนใ€‚ + +## ไป‹็ดน { #intro } + +ๆฒ’ๆœ‰ๅ‰ไบบ็š„ๅทฅไฝœ๏ผŒๅฐฑไธๆœƒๆœ‰ **FastAPI**ใ€‚ + +ๅœจๅฎƒ่ช•็”Ÿไน‹ๅ‰๏ผŒๅทฒ็ถ“ๆœ‰่จฑๅคšๅทฅๅ…ทๅ•Ÿ็™ผไบ†ๅฎƒ็š„่จญ่จˆใ€‚ + +ๆˆ‘ๅคšๅนดไพ†ไธ€็›ด้ฟๅ…ๆ‰“้€ ๆ–ฐๆก†ๆžถใ€‚่ตทๅˆๆˆ‘ๅ˜—่ฉฆ็”จ่จฑๅคšไธๅŒ็š„ๆก†ๆžถใ€ๅค–ๆŽ›่ˆ‡ๅทฅๅ…ท๏ผŒไพ†ๅฏฆไฝœ **FastAPI** ๆถต่“‹็š„ๆ‰€ๆœ‰ๅŠŸ่ƒฝใ€‚ + +ไฝ†ๅœจๆŸๅ€‹ๆ™‚้–“้ปž๏ผŒ้™คไบ†ๅ‰ตๅปบไธ€ๅ€‹่ƒฝๆไพ›ๆ‰€ๆœ‰้€™ไบ›ๅŠŸ่ƒฝใ€ๆฑฒๅ–ๅ‰ไบบๅทฅๅ…ท็š„ๅ„ช้ปž๏ผŒไธฆไปฅๆœ€ไฝณๆ–นๅผ็ต„ๅˆ่ตทไพ†ใ€ๅŒๆ™‚้‹็”จ้ŽๅŽป็”š่‡ณไธๅญ˜ๅœจ็š„่ชž่จ€็‰นๆ€ง๏ผˆPython 3.6+ ็š„ๅž‹ๅˆฅๆ็คบ๏ผ‰ไน‹ๅค–๏ผŒๅทฒๅˆฅ็„กไป–ๆณ•ใ€‚ + +## ๅ…ˆๅ‰็š„ๅทฅๅ…ท { #previous-tools } + +### Django { #django } + +ๅฎƒๆ˜ฏๆœ€ๅ—ๆญก่ฟŽไธ”ๅปฃๅ—ไฟกไปป็š„ Python ๆก†ๆžถใ€‚ๅƒ Instagram ็ญ‰็ณป็ตฑๅฐฑๆ˜ฏ็”จๅฎƒๆ‰“้€ ็š„ใ€‚ + +ๅฎƒ่ˆ‡้—œ่ฏๅผ่ณ‡ๆ–™ๅบซ๏ผˆๅฆ‚ MySQL ๆˆ– PostgreSQL๏ผ‰็›ธๅฐ็ทŠๅฏ†่€ฆๅˆ๏ผŒๅ› ๆญค่ฆไปฅ NoSQL ่ณ‡ๆ–™ๅบซ๏ผˆๅฆ‚ Couchbaseใ€MongoDBใ€Cassandra ็ญ‰๏ผ‰ไฝœ็‚บไธป่ฆๅ„ฒๅญ˜ๅผ•ๆ“Žไธฆไธๅฎนๆ˜“ใ€‚ + +ๅฎƒไธ€้–‹ๅง‹ๆ˜ฏ็‚บๅœจๅพŒ็ซฏ็”ข็”Ÿ HTML ่€Œ่จญ่จˆ๏ผŒ่€Œ้ž็‚บไบ†ๅปบ็ซ‹ๆไพ›็พไปฃๅ‰็ซฏ๏ผˆๅฆ‚ Reactใ€Vue.jsใ€Angular๏ผ‰ๆˆ–ๅ…ถไป–็ณป็ตฑ๏ผˆๅฆ‚ IoT ่ฃ็ฝฎ๏ผ‰ไฝฟ็”จ็š„ APIใ€‚ + +### Django REST Framework { #django-rest-framework } + +Django REST framework ็š„็›ฎๆจ™ๆ˜ฏๆˆ็‚บไธ€ๅฅ—ๅœจ Django ไน‹ไธŠๆง‹ๅปบ Web API ็š„ๅฝˆๆ€งๅทฅๅ…ท็ต„๏ผŒไปฅๅผทๅŒ–ๅ…ถ API ่ƒฝๅŠ›ใ€‚ + +ๅฎƒ่ขซ Mozillaใ€Red Hatใ€Eventbrite ็ญ‰็œพๅคšๅ…ฌๅธไฝฟ็”จใ€‚ + +ๅฎƒๆ˜ฏใ€Œ่‡ชๅ‹• API ๆ–‡ไปถใ€็š„ๆ—ฉๆœŸๅ…ธ็ฏ„ไน‹ไธ€๏ผŒ่€Œ้€™ๆญฃๆ˜ฏๅ•Ÿ็™ผๆˆ‘ใ€Œๅฐ‹ๆ‰พใ€**FastAPI** ็š„็ฌฌไธ€ๅ€‹ๆƒณๆณ•ใ€‚ + +/// note | ๆณจๆ„ + +Django REST Framework ็”ฑ Tom Christie ๅ‰ตๅปบใ€‚ไป–ๅŒๆ™‚ไนŸๆ˜ฏ Starlette ่ˆ‡ Uvicorn ็š„ไฝœ่€…๏ผŒ่€Œ **FastAPI** ๅฐฑๆ˜ฏๅปบ็ซ‹ๅœจๅฎƒๅ€‘ไน‹ไธŠใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๆไพ›่‡ชๅ‹•ๅŒ–็š„ API ๆ–‡ไปถ็ถฒ้ ไฝฟ็”จ่€…ไป‹้ขใ€‚ + +/// + +### Flask { #flask } + +Flask ๆ˜ฏไธ€ๅ€‹ใ€Œๅพฎๆก†ๆžถใ€๏ผŒๅฎƒไธๅŒ…ๅซ่ณ‡ๆ–™ๅบซๆ•ดๅˆ๏ผŒไนŸๆฒ’ๆœ‰ๅƒ Django ้‚ฃๆจฃๅ…งๅปบ่จฑๅคšๅŠŸ่ƒฝใ€‚ + +้€™็จฎ็ฐกๅ–ฎ่ˆ‡ๅฝˆๆ€ง๏ผŒ่ฎ“ไฝ ๅฏไปฅๆŠŠ NoSQL ่ณ‡ๆ–™ๅบซไฝœ็‚บไธป่ฆ็š„่ณ‡ๆ–™ๅ„ฒๅญ˜็ณป็ตฑใ€‚ + +็”ฑๆ–ผๅฎƒ้žๅธธ็ฐกๅ–ฎ๏ผŒๅญธ่ตทไพ†็›ธๅฐ็›ด่ง€๏ผŒๅ„˜็ฎกๆ–‡ไปถๅœจๆŸไบ›ๅœฐๆ–นๆœƒ่ฎŠๅพ—่ผƒๆŠ€่ก“ๆ€งใ€‚ + +ๅฎƒไนŸๅธธ็”จๆ–ผๅ…ถไป–ไธไธ€ๅฎš้œ€่ฆ่ณ‡ๆ–™ๅบซใ€ไฝฟ็”จ่€…็ฎก็†ๆˆ– Django ๅ…งๅปบ็œพๅคšๅŠŸ่ƒฝ็š„ๆ‡‰็”จ็จ‹ๅผใ€‚้›–็„ถ้€™ไบ›ๅŠŸ่ƒฝไธญ็š„่จฑๅคš้ƒฝๅฏไปฅ็”จๅค–ๆŽ›ๆ–ฐๅขžใ€‚ + +้€™็จฎๅ…ƒไปถ็š„่งฃ่€ฆ๏ผŒไปฅๅŠไฝœ็‚บๅฏๆ“ดๅ……ไปฅ็ฒพๆบ–ๆปฟ่ถณ้œ€ๆฑ‚็š„ใ€Œๅพฎๆก†ๆžถใ€๏ผŒๆ˜ฏๆˆ‘ๆƒณ่ฆไฟ็•™็š„้—œ้ต็‰นๆ€งใ€‚ + +ๅŸบๆ–ผ Flask ็š„็ฐกๆฝ”๏ผŒๅฎƒ็œ‹่ตทไพ†ๅพˆ้ฉๅˆ็”จไพ†ๆง‹ๅปบ APIใ€‚ๆŽฅไธ‹ไพ†่ฆๆ‰พ็š„๏ผŒๅฐฑๆ˜ฏ Flask ไธ–็•Œ่ฃก็š„ใ€ŒDjango REST Frameworkใ€ใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๆˆ็‚บไธ€ๅ€‹ๅพฎๆก†ๆžถ๏ผŒ่ฎ“ๆ‰€้œ€็š„ๅทฅๅ…ท่ˆ‡ๅ…ƒไปถ่ƒฝ่ผ•้ฌ†ๆญ้…็ต„ๅˆใ€‚ + +ๅ…ทๅ‚™็ฐกๅ–ฎใ€ๆ˜“็”จ็š„่ทฏ็”ฑ็ณป็ตฑใ€‚ + +/// + +### Requests { #requests } + +**FastAPI** ๅ…ถๅฏฆไธๆ˜ฏ **Requests** ็š„ๆ›ฟไปฃๅ“ใ€‚ๅ…ฉ่€…็š„็ฏ„็–‡ๆˆช็„ถไธๅŒใ€‚ + +ๅœจ FastAPI ๆ‡‰็”จ็จ‹ๅผใ€Œๅ…ง้ƒจใ€ไฝฟ็”จ Requests ๅ…ถๅฏฆๅพˆๅธธ่ฆ‹ใ€‚ + +ๅ„˜็ฎกๅฆ‚ๆญค๏ผŒFastAPI ไปๅพž Requests ๅพ—ๅˆฐไบ†ไธๅฐ‘ๅ•Ÿ็™ผใ€‚ + +**Requests** ๆ˜ฏไธ€ๅ€‹ใ€Œ่ˆ‡ API ไบ’ๅ‹•ใ€๏ผˆไฝœ็‚บ็”จๆˆถ็ซฏ๏ผ‰็š„็จ‹ๅผๅบซ๏ผŒ่€Œ **FastAPI** ๆ˜ฏไธ€ๅ€‹ใ€Œๅปบ็ซ‹ APIใ€๏ผˆไฝœ็‚บไผบๆœ็ซฏ๏ผ‰็š„็จ‹ๅผๅบซใ€‚ + +ๅฎƒๅ€‘ๅคง่‡ดไฝๆ–ผ็›ธๅๅ…ฉ็ซฏ๏ผŒๅฝผๆญคไบ’่ฃœใ€‚ + +Requests ่จญ่จˆ้žๅธธ็ฐกๅ–ฎ็›ด่ง€ใ€ๅฎนๆ˜“ไฝฟ็”จ๏ผŒไธ”ๆœ‰ๅˆ็†็š„้ ่จญๅ€ผใ€‚ๅŒๆ™‚ๅฎƒไนŸ้žๅธธๅผทๅคงไธ”ๅฏ่‡ช่จ‚ใ€‚ + +ๅ› ๆญค๏ผŒๅฆ‚ๅ…ถๅฎ˜็ถฒๆ‰€่จ€๏ผš + +> Requests is one of the most downloaded Python packages of all time + +็”จๆณ•้žๅธธ็ฐกๅ–ฎใ€‚ไพ‹ๅฆ‚๏ผŒ็™ผๅ‡บไธ€ๅ€‹ `GET` ่ซ‹ๆฑ‚๏ผŒไฝ ๆœƒๅฏซ๏ผš + +```Python +response = requests.get("http://example.com/some/url") +``` + +็›ธๅฐๅœฐ๏ผŒFastAPI ็š„ API ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ๅฏ่ƒฝๅƒ้€™ๆจฃ๏ผš + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +็œ‹็œ‹ `requests.get(...)` ่ˆ‡ `@app.get(...)` ็š„็›ธไผผไน‹่™•ใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +* ๆ“ๆœ‰็ฐกๅ–ฎ็›ด่ง€็š„ APIใ€‚ +* ็›ดๆŽฅไฝฟ็”จ HTTP ๆ–นๆณ•ๅ็จฑ๏ผˆๆ“ไฝœ๏ผ‰๏ผŒไปฅ็›ดๆŽฅใ€็›ด่ง€็š„ๆ–นๅผ่กจ้”ใ€‚ +* ๅ…ทๅ‚™ๅˆ็†็š„้ ่จญๅ€ผ๏ผŒๅŒๆ™‚ๆไพ›ๅผทๅคง็š„่‡ช่จ‚่ƒฝๅŠ›ใ€‚ + +/// + +### Swagger / OpenAPI { #swagger-openapi } + +ๆˆ‘ๆƒณๅพž Django REST Framework ๅพ—ๅˆฐ็š„ไธป่ฆๅŠŸ่ƒฝๆ˜ฏ่‡ชๅ‹• API ๆ–‡ไปถใ€‚ + +ๅพŒไพ†ๆˆ‘็™ผ็พๆœ‰ไธ€ๅ€‹ไฝฟ็”จ JSON๏ผˆๆˆ– YAML๏ผŒJSON ็š„ๅปถไผธ๏ผ‰ไพ†ๆ่ฟฐ API ็š„ๆจ™ๆบ–๏ผŒๅซๅš Swaggerใ€‚ + +่€Œไธ”ๅทฒๆœ‰ๅฐ Swagger API ็š„็ถฒ้ ไฝฟ็”จ่€…ไป‹้ขใ€‚ๅ› ๆญค๏ผŒๅช่ฆ่ƒฝ็‚บ API ็”ข็”Ÿ Swagger ๆ–‡ไปถ๏ผŒๅฐฑๅฏไปฅ่‡ชๅ‹•ไฝฟ็”จ้€™ๅ€‹็ถฒ้ ไป‹้ขใ€‚ + +ไน‹ๅพŒ Swagger ไบค็”ฑ Linux ๅŸบ้‡‘ๆœƒ็ฎก็†๏ผŒไธฆๆ›ดๅ็‚บ OpenAPIใ€‚ + +ๅ› ๆญค๏ผŒ่ซ‡ๅˆฐ 2.0 ็‰ˆๆ™‚ๅธธ่ชชใ€ŒSwaggerใ€๏ผŒ่€Œ 3+ ็‰ˆๅ‰‡ๆ˜ฏใ€ŒOpenAPIใ€ใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๆŽก็”จไธฆไฝฟ็”จ้–‹ๆ”พ็š„ API ่ฆๆ ผๆจ™ๆบ–๏ผŒ่€Œ้ž่‡ช่จ‚ๆ ผๅผใ€‚ + +ไธฆๆ•ดๅˆๅŸบๆ–ผๆจ™ๆบ–็š„ไฝฟ็”จ่€…ไป‹้ขๅทฅๅ…ท๏ผš + +* Swagger UI +* ReDoc + +้ธๆ“‡้€™ๅ…ฉๅ€‹ๆ˜ฏๅ› ็‚บๅฎƒๅ€‘็›ธ็•ถๅ—ๆญก่ฟŽไธ”็ฉฉๅฎš๏ผŒไฝ†็จๅŠ ๆœๅฐ‹๏ผŒไฝ ๆœƒ็™ผ็พๆœ‰ๆ•ธๅ็จฎ OpenAPI ็š„ๆ›ฟไปฃไฝฟ็”จ่€…ไป‹้ข๏ผˆ้ƒฝ่ƒฝ่ˆ‡ **FastAPI** ไธ€่ตทไฝฟ็”จ๏ผ‰ใ€‚ + +/// + +### Flask ็š„ REST ๆก†ๆžถ { #flask-rest-frameworks } + +ๆœ‰ๅนพๅ€‹ Flask ็š„ REST ๆก†ๆžถ๏ผŒไฝ†ๅœจๆŠ•ๅ…ฅๆ™‚้–“่ชฟๆŸฅๅพŒ๏ผŒๆˆ‘็™ผ็พ่จฑๅคšๅทฒๅœๆญข็ถญ่ญทๆˆ–่ขซๆฃ„็ฝฎ๏ผŒไธ”ๅญ˜ๅœจไธ€ไบ›้—œ้ตๅ•้กŒไฝฟไน‹ไธ้ฉ็”จใ€‚ + +### Marshmallow { #marshmallow } + +API ็ณป็ตฑ้œ€่ฆ็š„ไธป่ฆๅŠŸ่ƒฝไน‹ไธ€ๆ˜ฏ่ณ‡ๆ–™ใ€Œๅบๅˆ—ๅŒ–ใ€๏ผŒไนŸๅฐฑๆ˜ฏๆŠŠ็จ‹ๅผไธญ็š„่ณ‡ๆ–™๏ผˆPython๏ผ‰่ฝ‰ๆˆ่ƒฝ้€้Ž็ถฒ่ทฏๅ‚ณ่ผธ็š„ๅฝขๅผใ€‚ไพ‹ๅฆ‚๏ผŒๅฐ‡ๅซๆœ‰่ณ‡ๆ–™ๅบซ่ณ‡ๆ–™็š„็‰ฉไปถ่ฝ‰ๆˆ JSON ็‰ฉไปถใ€ๆŠŠ `datetime` ็‰ฉไปถ่ฝ‰ๆˆๅญ—ไธฒ็ญ‰็ญ‰ใ€‚ + +API ้œ€่ฆ็š„ๅฆไธ€ๅ€‹้‡่ฆๅŠŸ่ƒฝๆ˜ฏ่ณ‡ๆ–™้ฉ—่ญ‰๏ผŒ็ขบไฟ่ณ‡ๆ–™ๅœจ็‰นๅฎšๆขไปถไธ‹ๆœ‰ๆ•ˆใ€‚ไพ‹ๅฆ‚๏ผŒๆŸๅ€‹ๆฌ„ไฝๅฟ…้ ˆๆ˜ฏ `int`๏ผŒ่€Œไธๆ˜ฏ้šจไพฟ็š„ๅญ—ไธฒใ€‚้€™ๅฐๆ–ผ่ผธๅ…ฅ่ณ‡ๆ–™็‰นๅˆฅๆœ‰็”จใ€‚ + +ๆฒ’ๆœ‰่ณ‡ๆ–™้ฉ—่ญ‰็ณป็ตฑ็š„่ฉฑ๏ผŒไฝ ๅฐฑๅพ—ๅœจ็จ‹ๅผ็ขผไธญๆ‰‹ๅ‹•้€ไธ€ๆชขๆŸฅใ€‚ + +้€™ไบ›ๅŠŸ่ƒฝๆญฃๆ˜ฏ Marshmallow ๆ‰€่ฆๆไพ›็š„ใ€‚ๅฎƒๆ˜ฏๅพˆๆฃ’็š„ๅ‡ฝๅผๅบซ๏ผŒๆˆ‘ไน‹ๅ‰ไนŸๅคง้‡ไฝฟ็”จใ€‚ + +ไฝ†ๅฎƒ่ช•็”Ÿๆ–ผ Python ๅž‹ๅˆฅๆ็คบๅ‡บ็พไน‹ๅ‰ใ€‚ๅ› ๆญค๏ผŒ็‚บไบ†ๅฎš็พฉๆฏๅ€‹ ็ตๆง‹๏ผˆschema๏ผ‰๏ผŒไฝ ้œ€่ฆไฝฟ็”จ Marshmallow ๆไพ›็š„็‰นๅฎšๅทฅๅ…ท่ˆ‡้กžๅˆฅใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +็”จ็จ‹ๅผ็ขผๅฎš็พฉ่ƒฝ่‡ชๅ‹•ๆไพ›่ณ‡ๆ–™ๅž‹ๅˆฅ่ˆ‡้ฉ—่ญ‰็š„ใ€Œschemasใ€ใ€‚ + +/// + +### Webargs { #webargs } + +API ๆ‰€้œ€็š„ๅฆไธ€้ …ๅคงๅŠŸ่ƒฝ๏ผŒๆ˜ฏๅพžๅ‚ณๅ…ฅ่ซ‹ๆฑ‚ไธญ่งฃๆž่ณ‡ๆ–™ใ€‚ + +Webargs ๆ˜ฏๅœจๅคšๅ€‹ๆก†ๆžถ๏ผˆๅŒ…ๅซ Flask๏ผ‰ไน‹ไธŠๆไพ›่ฉฒๅŠŸ่ƒฝ็š„ๅทฅๅ…ทใ€‚ + +ๅฎƒๅบ•ๅฑคไฝฟ็”จ Marshmallow ไพ†ๅš่ณ‡ๆ–™้ฉ—่ญ‰๏ผŒไธ”็”ฑๅŒไธ€็พค้–‹็™ผ่€…ๅปบ็ซ‹ใ€‚ + +ๅฎƒๆ˜ฏไธ€ๅ€‹ๅพˆๆฃ’็š„ๅทฅๅ…ท๏ผŒๅœจๆœ‰ **FastAPI** ไน‹ๅ‰ๆˆ‘ไนŸ็ถ“ๅธธไฝฟ็”จใ€‚ + +/// info + +Webargs ็”ฑ่ˆ‡ Marshmallow ็›ธๅŒ็š„้–‹็™ผ่€…ๅ‰ตๅปบใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +่‡ชๅ‹•้ฉ—่ญ‰ๅ‚ณๅ…ฅ่ซ‹ๆฑ‚่ณ‡ๆ–™ใ€‚ + +/// + +### APISpec { #apispec } + +Marshmallow ่ˆ‡ Webargs ไปฅๅค–ๆŽ›ๆไพ›้ฉ—่ญ‰ใ€่งฃๆž่ˆ‡ๅบๅˆ—ๅŒ–ใ€‚ + +ไฝ†ๆ–‡ไปถไป็„ถ็ผบๅคฑ๏ผŒๆ–ผๆ˜ฏ APISpec ๅ‡บ็พไบ†ใ€‚ + +ๅฎƒๆ˜ฏๅคšๅ€‹ๆก†ๆžถ็š„ๅค–ๆŽ›๏ผˆStarlette ไนŸๆœ‰ๅฐๆ‡‰ๅค–ๆŽ›๏ผ‰ใ€‚ + +ๅฎƒ็š„ไฝœๆณ•ๆ˜ฏ๏ผšไฝ ๅœจ่™•็†่ทฏ็”ฑ็š„ๆฏๅ€‹ๅ‡ฝๅผ็š„ docstring ไธญ๏ผŒ็”จ YAML ๆ ผๅผๆ’ฐๅฏซ็ตๆง‹ๅฎš็พฉใ€‚ + +็„ถๅพŒๅฎƒๆœƒ็”ข็”Ÿ OpenAPI schemasใ€‚ + +ๅœจ Flaskใ€Starletteใ€Responder ็ญ‰ๆก†ๆžถไธญ้ƒฝๆ˜ฏ้€™ๆจฃ้‹ไฝœใ€‚ + +ไฝ†้€™ๅˆๅธถไพ†ไธ€ๅ€‹ๅ•้กŒ๏ผšๅœจ Python ๅญ—ไธฒไธญ๏ผˆๅคงๅž‹ YAML๏ผ‰ๅŠ ๅ…ฅไธ€ๆฎตๅพฎ่ชžๆณ•ใ€‚ + +็ทจ่ผฏๅ™จๅนซไธไธŠๅคชๅคšๅฟ™ใ€‚่€Œไธ”ๅฆ‚ๆžœๆˆ‘ๅ€‘ไฟฎๆ”นไบ†ๅƒๆ•ธๆˆ– Marshmallow ็š„ schemas ๅปๅฟ˜ไบ†ๅŒๆญฅไฟฎๆ”น YAML docstring๏ผŒ็”ข็”Ÿ็š„็ตๆง‹ๅฐฑๆœƒ้Žๆ™‚ใ€‚ + +/// info + +APISpec ็”ฑ่ˆ‡ Marshmallow ็›ธๅŒ็š„้–‹็™ผ่€…ๅ‰ตๅปบใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๆ”ฏๆด API ็š„้–‹ๆ”พๆจ™ๆบ– OpenAPIใ€‚ + +/// + +### Flask-apispec { #flask-apispec } + +้€™ๆ˜ฏไธ€ๅ€‹ Flask ๅค–ๆŽ›๏ผŒๆŠŠ Webargsใ€Marshmallow ่ˆ‡ APISpec ไธฒๅœจไธ€่ตทใ€‚ + +ๅฎƒไฝฟ็”จ Webargs ่ˆ‡ Marshmallow ็š„่ณ‡่จŠ๏ผŒ้€้Ž APISpec ่‡ชๅ‹•็”ข็”Ÿ OpenAPI ็ตๆง‹ใ€‚ + +ๅฎƒๆ˜ฏๅ€‹ๅพˆๆฃ’ไฝ†่ขซไฝŽไผฐ็š„ๅทฅๅ…ทใ€‚ๅฎƒ็†ๆ‡‰ๆฏ”่จฑๅคš Flask ๅค–ๆŽ›ๆ›ดๅ—ๆญก่ฟŽ๏ผŒๅฏ่ƒฝๅ› ็‚บๅฎƒ็š„ๆ–‡ไปถ้Žๆ–ผ็ฐกๆฝ”่ˆ‡ๆŠฝ่ฑกใ€‚ + +้€™่งฃๆฑบไบ†ๅœจ Python ๆ–‡ไปถๅญ—ไธฒไธญๆ’ฐๅฏซ YAML๏ผˆๅฆไธ€็จฎ่ชžๆณ•๏ผ‰็š„้—ฎ้ข˜ใ€‚ + +ๅœจๆ‰“้€  **FastAPI** ๅ‰๏ผŒๆˆ‘ๆœ€ๅ–œๆญก็š„ๅพŒ็ซฏๆŠ€่ก“็ต„ๅˆๅฐฑๆ˜ฏ Flaskใ€Flask-apispecใ€Marshmallow ่ˆ‡ Webargsใ€‚ + +ไฝฟ็”จๅฎƒไฟƒๆˆไบ†ๆ•ธๅ€‹ Flask ๅ…จ็ซฏ๏ผˆfull-stack๏ผ‰็”ข็”Ÿๅ™จใ€‚้€™ไบ›ๆ˜ฏๆˆ‘๏ผˆไปฅๅŠ่‹ฅๅนฒๅค–้ƒจๅœ˜้šŠ๏ผ‰่‡ณไปŠไธป่ฆไฝฟ็”จ็š„ๆŠ€่ก“็ต„ๅˆ๏ผš + +* https://github.com/tiangolo/full-stack +* https://github.com/tiangolo/full-stack-flask-couchbase +* https://github.com/tiangolo/full-stack-flask-couchdb + +่€Œ้€™ไบ›ๅ…จ็ซฏ็”ข็”Ÿๅ™จ๏ผŒไนŸๆˆ็‚บไบ† [**FastAPI** ๅฐˆๆกˆ็”ข็”Ÿๅ™จ](project-generation.md){.internal-link target=_blank} ็š„ๅŸบ็คŽใ€‚ + +/// info + +Flask-apispec ็”ฑ่ˆ‡ Marshmallow ็›ธๅŒ็š„้–‹็™ผ่€…ๅ‰ตๅปบใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๅพžๅฎš็พฉๅบๅˆ—ๅŒ–่ˆ‡้ฉ—่ญ‰็š„็›ธๅŒ็จ‹ๅผ็ขผ๏ผŒ่‡ชๅ‹•็”ข็”Ÿ OpenAPI ็ตๆง‹๏ผˆschema๏ผ‰ใ€‚ + +/// + +### NestJS๏ผˆ่ˆ‡ Angular๏ผ‰ { #nestjs-and-angular } + +้€™็”š่‡ณไธๆ˜ฏ Pythonใ€‚NestJS ๆ˜ฏๅ— Angular ๅ•Ÿ็™ผ็š„ JavaScript๏ผˆTypeScript๏ผ‰NodeJS ๆก†ๆžถใ€‚ + +ๅฎƒ้”ๆˆ็š„ๆ•ˆๆžœ่ˆ‡ Flask-apispec ่ƒฝๅš็š„ๆœ‰้ปž็›ธไผผใ€‚ + +ๅฎƒๆœ‰ไธ€ๅฅ—ๅ— Angular 2 ๅ•Ÿ็™ผ็š„ๆ•ดๅˆๅผ็›ธไพๆ€งๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰็ณป็ตฑใ€‚้œ€่ฆ้ ๅ…ˆ่จปๅ†Šใ€Œๅฏๆณจๅ…ฅใ€ๅ…ƒไปถ๏ผˆๅฐฑๅƒๆˆ‘ๆ‰€็Ÿฅ็š„ๅ…ถไป–็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑไธ€ๆจฃ๏ผ‰๏ผŒๅ› ๆญคๆœƒๅขžๅŠ ๅ†—้•ท่ˆ‡้‡่ค‡็จ‹ๅผ็ขผใ€‚ + +็”ฑๆ–ผๅƒๆ•ธไปฅ TypeScript ๅž‹ๅˆฅๆ่ฟฐ๏ผˆ่ˆ‡ Python ๅž‹ๅˆฅๆ็คบ็›ธไผผ๏ผ‰๏ผŒ็ทจ่ผฏๅ™จๆ”ฏๆด็›ธ็•ถไธ้Œฏใ€‚ + +ไฝ†ๅ› ็‚บ TypeScript ็š„ๅž‹ๅˆฅๅœจ็ทจ่ญฏๆˆ JavaScript ๅพŒไธๆœƒ่ขซไฟ็•™๏ผŒๅฎƒ็„กๆณ•ๅƒ…้ ๅž‹ๅˆฅๅŒๆ™‚ๅฎš็พฉ้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถใ€‚็”ฑๆ–ผ้€™้ปžไปฅๅŠ้ƒจๅˆ†่จญ่จˆๆฑบๅฎš๏ผŒ่‹ฅ่ฆๅ–ๅพ—้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡่‡ชๅ‹•็ตๆง‹็”ข็”Ÿ๏ผŒๅฐฑ้œ€่ฆๅœจ่จฑๅคšๅœฐๆ–นๅŠ ไธŠ่ฃ้ฃพๅ™จ๏ผŒๅ› ๆญคๆœƒ็›ธ็•ถๅ†—้•ทใ€‚ + +ๅฎƒ็„กๆณ•ๅพˆๅฅฝๅœฐ่™•็†ๅทข็‹€ๆจกๅž‹ใ€‚่‹ฅ่ซ‹ๆฑ‚็š„ JSON ไธป้ซ”ไธญๆœ‰ๅ…งๅฑคๆฌ„ไฝ๏ผŒไธ”้€™ไบ›ๅ…งๅฑคๆฌ„ไฝๅˆๆ˜ฏๅทข็‹€ JSON ็‰ฉไปถ๏ผŒๅฐฑ็„กๆณ•่ขซๅฆฅๅ–„ๅœฐๆ–‡ไปถๅŒ–่ˆ‡้ฉ—่ญ‰ใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ไฝฟ็”จ Python ๅž‹ๅˆฅไปฅ็ฒๅพ—ๅ„ช็ง€็š„็ทจ่ผฏๅ™จๆ”ฏๆดใ€‚ + +ๆไพ›ๅผทๅคง็š„็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑ๏ผŒไธฆๆƒณ่พฆๆณ•ๅฐ‡้‡่ค‡็จ‹ๅผ็ขผ้™ๅˆฐๆœ€ไฝŽใ€‚ + +/// + +### Sanic { #sanic } + +ๅฎƒๆ˜ฏๆœ€ๆ—ฉๅŸบๆ–ผ `asyncio` ็š„ๆฅต้ซ˜้€Ÿ Python ๆก†ๆžถไน‹ไธ€๏ผŒไธฆๅšๅพ—ๅพˆๅƒ Flaskใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅฎƒไฝฟ็”จ `uvloop` ๅ–ไปฃ้ ่จญ็š„ Python `asyncio` ไบ‹ไปถๅœˆใ€‚้€™ไนŸๆ˜ฏๅฎƒๅฆ‚ๆญคไน‹ๅฟซ็š„ๅŽŸๅ› ใ€‚ + +ๅฎƒๆ˜Ž้กฏๅ•Ÿ็™ผไบ† Uvicorn ่ˆ‡ Starlette๏ผŒ่€Œๅœจๅ…ฌ้–‹็š„ๅŸบๆบ–ๆธฌ่ฉฆไธญ๏ผŒๅฎƒๅ€‘็›ฎๅ‰ๆฏ” Sanic ๆ›ดๅฟซใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๆƒณ่พฆๆณ•้”ๅˆฐ็˜‹็‹‚็š„ๆ•ˆ่ƒฝใ€‚ + +้€™ๅฐฑๆ˜ฏ็‚บไป€้บผ **FastAPI** ๅปบ็ซ‹ๆ–ผ Starlette ไน‹ไธŠ๏ผŒๅ› ็‚บๅฎƒๆ˜ฏๅฏ็”จ็š„ๆœ€ๅฟซๆก†ๆžถ๏ผˆ็”ฑ็ฌฌไธ‰ๆ–น่ฉ•ๆธฌ๏ผ‰ใ€‚ + +/// + +### Falcon { #falcon } + +Falcon ๆ˜ฏๅฆไธ€ๅ€‹้ซ˜ๆ•ˆ่ƒฝ Python ๆก†ๆžถ๏ผŒ่จญ่จˆไธŠๆฅต็ฐก๏ผŒไธฆไฝœ็‚บๅ…ถไป–ๆก†ๆžถ๏ผˆๅฆ‚ Hug๏ผ‰็š„ๅŸบ็คŽใ€‚ + +ๅฎƒ่จญ่จˆ็‚บๅ‡ฝๅผๆŽฅๆ”ถๅ…ฉๅ€‹ๅƒๆ•ธ๏ผŒไธ€ๅ€‹ๆ˜ฏใ€Œrequestใ€๏ผŒไธ€ๅ€‹ๆ˜ฏใ€Œresponseใ€ใ€‚็„ถๅพŒไฝ ๅพž requestใ€Œ่ฎ€ๅ–ใ€่ณ‡ๆ–™ใ€ๅพ€ responseใ€Œๅฏซๅ…ฅใ€่ณ‡ๆ–™ใ€‚็”ฑๆ–ผ้€™็จฎ่จญ่จˆ๏ผŒ็„กๆณ•ไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๆ็คบ๏ผŒ็›ดๆŽฅไปฅๅ‡ฝๅผๅƒๆ•ธๅฎฃๅ‘Š่ซ‹ๆฑ‚ๅƒๆ•ธ่ˆ‡ไธป้ซ”ใ€‚ + +ๅ› ๆญค๏ผŒ่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถๅฟ…้ ˆไปฅ็จ‹ๅผ็ขผๆ‰‹ๅ‹•ๅฎŒๆˆ๏ผŒ็„กๆณ•่‡ชๅ‹•ๅŒ–ใ€‚ๆˆ–่€…้œ€ๅœจ Falcon ไน‹ไธŠๅฏฆไฝœๅฆไธ€ๅฑคๆก†ๆžถ๏ผˆๅฆ‚ Hug๏ผ‰ใ€‚ๅ…ถไป–ๅ— Falcon ่จญ่จˆๅ•Ÿ็™ผ็š„ๆก†ๆžถไนŸๆœ‰ๅŒๆจฃ็š„ๅ€ๅˆฅ๏ผšๅฐ‡ request ่ˆ‡ response ็‰ฉไปถไฝœ็‚บๅƒๆ•ธใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +่จญๆณ•ๅ–ๅพ—ๅ„ช็ง€็š„ๆ•ˆ่ƒฝใ€‚ + +้€ฃๅŒ Hug๏ผˆHug ๅปบ็ซ‹ๆ–ผ Falcon ไน‹ไธŠ๏ผ‰ไธ€่ตท๏ผŒไนŸๅ•Ÿ็™ผ **FastAPI** ๅœจๅ‡ฝๅผไธญๅฎฃๅ‘Šไธ€ๅ€‹ `response` ๅƒๆ•ธใ€‚ + +ไธ้Žๅœจ FastAPI ไธญๅฎƒๆ˜ฏๅฏ้ธ็š„๏ผŒไธป่ฆ็”จไพ†่จญๅฎšๆจ™้ ญใ€Cookie ่ˆ‡ๆ›ฟไปฃ็‹€ๆ…‹็ขผใ€‚ + +/// + +### Molten { #molten } + +ๆˆ‘ๅœจ **FastAPI** ๆ‰“้€ ็š„ๆ—ฉๆœŸ็™ผ็พไบ† Moltenใ€‚ๅฎƒๆœ‰ไธ€ไบ›็›ธ็•ถ้กžไผผ็š„ๆƒณๆณ•๏ผš + +* ๅŸบๆ–ผ Python ๅž‹ๅˆฅๆ็คบใ€‚ +* ๅพž้€™ไบ›ๅž‹ๅˆฅๅ–ๅพ—้ฉ—่ญ‰่ˆ‡ๆ–‡ไปถใ€‚ +* ็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑใ€‚ + +ๅฎƒๆฒ’ๆœ‰ไฝฟ็”จๅƒ Pydantic ้€™ๆจฃ็š„็ฌฌไธ‰ๆ–น่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถๅบซ๏ผŒ่€Œๆ˜ฏๆœ‰่‡ชๅทฑ็š„ใ€‚ๅ› ๆญค๏ผŒ้€™ไบ›่ณ‡ๆ–™ๅž‹ๅˆฅๅฎš็พฉ่ผƒไธๅฎนๆ˜“้‡่ค‡ไฝฟ็”จใ€‚ + +ๅฎƒ้œ€่ฆๆ›ด็‚บๅ†—้•ท็š„่จญๅฎšใ€‚่€Œไธ”ๅ› ็‚บๅฎƒๅŸบๆ–ผ WSGI๏ผˆ่€Œ้ž ASGI๏ผ‰๏ผŒไธฆๆœช่จญ่จˆไพ†ไบซๅ—ๅฆ‚ Uvicornใ€Starletteใ€Sanic ็ญ‰ๅทฅๅ…ทๆ‰€ๆไพ›็š„้ซ˜ๆ•ˆ่ƒฝใ€‚ + +ๅ…ถ็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑ้œ€่ฆ้ ๅ…ˆ่จปๅ†Šไพ่ณด๏ผŒไธฆไธ”ไพๆ“šๅฎฃๅ‘Š็š„ๅž‹ๅˆฅไพ†่งฃๆžไพ่ณดใ€‚ๅ› ๆญค๏ผŒ็„กๆณ•ๅฎฃๅ‘Šๅคšๅ€‹่ƒฝๆไพ›็›ธๅŒๅž‹ๅˆฅ็š„ใ€Œๅ…ƒไปถใ€ใ€‚ + +่ทฏ็”ฑ้œ€่ฆๅœจๅ–ฎไธ€ๅœฐๆ–นๅฎฃๅ‘Š๏ผŒไฝฟ็”จๅœจๅ…ถไป–ๅœฐๆ–นๅฎฃๅ‘Š็š„ๅ‡ฝๅผ๏ผˆ่€Œไธๆ˜ฏ็”จๅฏไปฅ็›ดๆŽฅๆ”พๅœจ็ซฏ้ปž่™•็†ๅ‡ฝๅผไธŠๆ–น็š„่ฃ้ฃพๅ™จ๏ผ‰ใ€‚้€™ๆ›ดๆŽฅ่ฟ‘ Django ็š„ไฝœๆณ•๏ผŒ่€Œไธๆ˜ฏ Flask๏ผˆ่ˆ‡ Starlette๏ผ‰็š„ไฝœๆณ•ใ€‚ๅฎƒๅœจ็จ‹ๅผ็ขผไธญๅˆ†้›ขไบ†ๅ…ถๅฏฆ็›ธ็•ถ็ทŠๅฏ†่€ฆๅˆ็š„ไบ‹็‰ฉใ€‚ + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +็”จๆจกๅž‹ๅฑฌๆ€ง็š„ใ€Œ้ ่จญๅ€ผใ€ไพ†ๅฎš็พฉ่ณ‡ๆ–™ๅž‹ๅˆฅ็š„้กๅค–้ฉ—่ญ‰ใ€‚้€™ๆๅ‡ไบ†็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ่€Œ้€™ๅœจ็•ถๆ™‚็š„ Pydantic ้‚„ไธๆ”ฏๆดใ€‚ + +้€™ๅฏฆ้š›ไธŠไนŸๅ•Ÿ็™ผไบ† Pydantic ็š„้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒไปฅๆ”ฏๆด็›ธๅŒ็š„้ฉ—่ญ‰ๅฎฃๅ‘Š้ขจๆ ผ๏ผˆ้€™ไบ›ๅŠŸ่ƒฝ็พๅœจๅทฒๅœจ Pydantic ไธญๅฏ็”จ๏ผ‰ใ€‚ + +/// + +### Hug { #hug } + +Hug ๆ˜ฏๆœ€ๆ—ฉไฝฟ็”จ Python ๅž‹ๅˆฅๆ็คบไพ†ๅฎฃๅ‘Š API ๅƒๆ•ธๅž‹ๅˆฅ็š„ๆก†ๆžถไน‹ไธ€ใ€‚้€™ๆ˜ฏๅ€‹ๅพˆๆฃ’็š„้ปžๅญ๏ผŒไนŸๅ•Ÿ็™ผไบ†ๅ…ถไป–ๅทฅๅ…ทใ€‚ + +ๅฎƒๅœจๅฎฃๅ‘Šไธญไฝฟ็”จ่‡ช่จ‚ๅž‹ๅˆฅ่€Œ้žๆจ™ๆบ– Python ๅž‹ๅˆฅ๏ผŒไฝ†ไป็„ถๆ˜ฏๅทจๅคง็š„ไธ€ๆญฅใ€‚ + +ๅฎƒไนŸๆ˜ฏๆœ€ๆ—ฉ่ƒฝไปฅ JSON ็”ขๅ‡บ่‡ช่จ‚็ตๆง‹ใ€ๆ่ฟฐๆ•ดๅ€‹ API ็š„ๆก†ๆžถไน‹ไธ€ใ€‚ + +ๅฎƒไธๆ˜ฏๅŸบๆ–ผ OpenAPI ่ˆ‡ JSON Schema ็ญ‰ๆจ™ๆบ–ใ€‚ๅ› ๆญค๏ผŒ่ˆ‡ๅ…ถไป–ๅทฅๅ…ท๏ผˆๅฆ‚ Swagger UI๏ผ‰็š„ๆ•ดๅˆไธฆไธ็›ด่ฆบใ€‚ไฝ†ๅฎƒไปๆ˜ฏไธ€ๅ€‹้žๅธธๅ‰ตๆ–ฐ็š„ๆƒณๆณ•ใ€‚ + +ๅฎƒๆœ‰ๅ€‹ๆœ‰่ถฃใ€ๅฐ‘่ฆ‹็š„ๅŠŸ่ƒฝ๏ผšๅŒไธ€ๅ€‹ๆก†ๆžถๅฏๅŒๆ™‚ๅปบ็ซ‹ API ่ˆ‡ CLIใ€‚ + +็”ฑๆ–ผๅฎƒๅŸบๆ–ผๅŒๆญฅ Python ็ถฒ้ ๆก†ๆžถ็š„่ˆŠๆจ™ๆบ–๏ผˆWSGI๏ผ‰๏ผŒ็„กๆณ•่™•็† WebSocket ่ˆ‡ๅ…ถไป–ๅŠŸ่ƒฝ๏ผŒๅ„˜็ฎกๆ•ˆ่ƒฝไป็„ถๅพˆ้ซ˜ใ€‚ + +/// info + +Hug ็”ฑ Timothy Crosley ๅ‰ตๅปบ๏ผŒไป–ๅŒๆ™‚ไนŸๆ˜ฏ `isort` ็š„ไฝœ่€…๏ผŒไธ€ๅ€‹่‡ชๅ‹•ๆŽ’ๅบ Python ๅŒฏๅ…ฅ็š„ๅฅฝๅทฅๅ…ทใ€‚ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** ็š„ๆƒณๆณ• + +Hug ๅ•Ÿ็™ผไบ† APIStar ็š„้ƒจๅˆ†่จญ่จˆ๏ผŒไนŸๆ˜ฏๆˆ‘่ฆบๅพ—ๆœ€ๆœ‰ๅ‰ๆ™ฏ็š„ๅทฅๅ…ทไน‹ไธ€๏ผŒ่ˆ‡ APIStar ไธฆๅˆ—ใ€‚ + +Hug ๅ•Ÿ็™ผ **FastAPI** ไฝฟ็”จ Python ๅž‹ๅˆฅๆ็คบๅฎฃๅ‘Šๅƒๆ•ธ๏ผŒไธฆ่‡ชๅ‹•็”ข็”Ÿๅฎš็พฉ API ็š„็ตๆง‹ใ€‚ + +Hug ๅ•Ÿ็™ผ **FastAPI** ๅœจๅ‡ฝๅผไธญๅฎฃๅ‘Š `response` ๅƒๆ•ธไปฅ่จญๅฎšๆจ™้ ญ่ˆ‡ Cookieใ€‚ + +/// + +### APIStar (<= 0.5) { #apistar-0-5 } + +ๅœจๆฑบๅฎšๆ‰“้€  **FastAPI** ไน‹ๅ‰๏ผŒๆˆ‘ๆ‰พๅˆฐไบ† **APIStar** ไผบๆœๅ™จใ€‚ๅฎƒๅนพไนŽๅ…ทๅ‚™ๆˆ‘ๆ‰€ๅฐ‹ๆ‰พ็š„ไธ€ๅˆ‡๏ผŒ่€Œไธ”่จญ่จˆๅพˆๅ‡บ่‰ฒใ€‚ + +ๅฎƒๆ˜ฏๆˆ‘่ฆ‹้Žๆœ€ๆ—ฉไฝฟ็”จ Python ๅž‹ๅˆฅๆ็คบไพ†ๅฎฃๅ‘Šๅƒๆ•ธ่ˆ‡่ซ‹ๆฑ‚็š„ๆก†ๆžถๅฏฆไฝœไน‹ไธ€๏ผˆๆ—ฉๆ–ผ NestJS ่ˆ‡ Molten๏ผ‰ใ€‚ๆˆ‘่ˆ‡ Hug ๅนพไนŽๅœจๅŒๆ™‚้–“็™ผ็พๅฎƒใ€‚ไธ้Ž APIStar ไฝฟ็”จ็š„ๆ˜ฏ OpenAPI ๆจ™ๆบ–ใ€‚ + +ๅฎƒๅŸบๆ–ผ็›ธๅŒ็š„ๅž‹ๅˆฅๆ็คบ๏ผŒๅœจๅคš่™•่‡ชๅ‹•้€ฒ่กŒ่ณ‡ๆ–™้ฉ—่ญ‰ใ€่ณ‡ๆ–™ๅบๅˆ—ๅŒ–่ˆ‡ OpenAPI ็ตๆง‹็”ข็”Ÿใ€‚ + +ไธป้ซ”็ตๆง‹๏ผˆbody schema๏ผ‰็š„ๅฎš็พฉไธฆๆœชไฝฟ็”จๅƒ Pydantic ้‚ฃๆจฃ็š„ Python ๅž‹ๅˆฅๆ็คบ๏ผŒๆ›ดๅƒ Marshmallow๏ผŒๅ› ๆญค็ทจ่ผฏๅ™จๆ”ฏๆดๆฒ’ๆœ‰้‚ฃ้บผๅฅฝ๏ผŒไฝ†ๆ•ด้ซ”่€Œ่จ€๏ผŒAPIStar ๆ˜ฏ็•ถๆ™‚ๆœ€ๅฅฝ็š„้ธๆ“‡ใ€‚ + +ๅฎƒๅœจ็•ถๆ™‚็š„ๆ•ˆ่ƒฝ่ฉ•ๆธฌไธญๅๅˆ—ๅ‰่Œ…๏ผˆๅƒ…่ขซ Starlette ่ถ…่ถŠ๏ผ‰ใ€‚ + +ไธ€้–‹ๅง‹ๅฎƒๆฒ’ๆœ‰่‡ชๅ‹• API ๆ–‡ไปถ็š„็ถฒ้  UI๏ผŒไฝ†ๆˆ‘็Ÿฅ้“ๆˆ‘ๅฏไปฅๆ›ฟๅฎƒๅŠ ไธŠ Swagger UIใ€‚ + +ๅฎƒๆœ‰็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑใ€‚้œ€่ฆ้ ๅ…ˆ่จปๅ†Šๅ…ƒไปถ๏ผŒ่ˆ‡ไธŠ้ขๆๅˆฐ็š„ๅ…ถไป–ๅทฅๅ…ท็›ธๅŒใ€‚ไธ้Ž้€™ไปๆ˜ฏๅพˆๆฃ’็š„ๅŠŸ่ƒฝใ€‚ + +ๆˆ‘ๅพžๆœช่ƒฝๅœจๅฎŒๆ•ดๅฐˆๆกˆไธญไฝฟ็”จๅฎƒ๏ผŒๅ› ็‚บๅฎƒๆฒ’ๆœ‰ๅฎ‰ๅ…จๆ€งๆ•ดๅˆ๏ผŒๆ‰€ไปฅ็„กๆณ•ๅ–ไปฃๆˆ‘็”จ Flask-apispec ๅ…จ็ซฏ็”ข็”Ÿๅ™จๆ‰€ๆ“ๆœ‰็š„ๅ…จ้ƒจๅŠŸ่ƒฝใ€‚ๆˆ‘ๆ›พๆŠŠๆ–ฐๅขž่ฉฒๅŠŸ่ƒฝ็š„ pull request ๆ”พๅœจๅพ…่พฆๆธ…ๅ–ฎไธญใ€‚ + +ไฝ†ไน‹ๅพŒ๏ผŒๅฐˆๆกˆ็š„้‡ๅฟƒๆ”น่ฎŠไบ†ใ€‚ + +ๅฎƒไธๅ†ๆ˜ฏ API ็ถฒ้ ๆก†ๆžถ๏ผŒๅ› ็‚บไฝœ่€…้œ€่ฆๅฐˆๆณจๆ–ผ Starletteใ€‚ + +็พๅœจ็š„ APIStar ๆ˜ฏไธ€ๅฅ—็”จๆ–ผ้ฉ—่ญ‰ OpenAPI ่ฆๆ ผ็š„ๅทฅๅ…ท๏ผŒไธๆ˜ฏ็ถฒ้ ๆก†ๆžถใ€‚ + +/// info + +APIStar ็”ฑ Tom Christie ๅ‰ตๅปบใ€‚ไป–ไนŸๅ‰ตๅปบไบ†๏ผš + +* Django REST Framework +* Starlette๏ผˆ**FastAPI** ๅปบ็ซ‹ๆ–ผๅ…ถไธŠ๏ผ‰ +* Uvicorn๏ผˆStarlette ่ˆ‡ **FastAPI** ไฝฟ็”จ๏ผ‰ + +/// + +/// check | ๅ•Ÿ็™ผ **FastAPI** + +ๅญ˜ๅœจใ€‚ + +็”จ็›ธๅŒ็š„ Python ๅž‹ๅˆฅๅŒๆ™‚ๅฎฃๅ‘Šๅคšไปถไบ‹๏ผˆ่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถ๏ผ‰๏ผŒไธฆๅŒๆ™‚ๆไพ›ๅ‡บ่‰ฒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ้€™ๆ˜ฏไธ€ๅ€‹ๆฅตๅฅฝ็š„้ปžๅญใ€‚ + +ๅœจ้•ทๆ™‚้–“ๅฐ‹ๆ‰พไธฆๆธฌ่ฉฆๅคš็จฎไธๅŒๆ›ฟไปฃๆ–นๆกˆๅพŒ๏ผŒAPIStar ๆ˜ฏๆœ€ๅฅฝ็š„ๅฏ็”จ้ธๆ“‡ใ€‚ + +็•ถ APIStar ไธๅ†ไฝœ็‚บไผบๆœๅ™จๅญ˜ๅœจ๏ผŒ่€Œ Starlette ่ช•็”Ÿไธฆๆˆ็‚บๆ›ดๅฅฝ็š„ๅŸบ็คŽๆ™‚๏ผŒ้€™ๆˆ็‚บๆ‰“้€  **FastAPI** ็š„ๆœ€ๅพŒไธ€ๅ€‹้ˆๆ„Ÿใ€‚ + +ๆˆ‘ๅฐ‡ **FastAPI** ่ฆ–็‚บ APIStar ็š„ใ€Œ็ฒพ็ฅž็นผๆ‰ฟ่€…ใ€๏ผŒๅŒๆ™‚ๅŸบๆ–ผๆ‰€ๆœ‰้€™ไบ›ๅ…ˆๅ‰ๅทฅๅ…ท็š„็ถ“้ฉ—๏ผŒๆ”น้€ฒไธฆๆ“ดๅขžไบ†ๅŠŸ่ƒฝใ€ๅž‹ๅˆฅ็ณป็ตฑ่ˆ‡ๅ…ถไป–้ƒจๅˆ†ใ€‚ + +/// + +## **FastAPI** ๆ‰€ๆŽก็”จ็š„ๅทฅๅ…ท { #used-by-fastapi } + +### Pydantic { #pydantic } + +Pydantic ๆ˜ฏๅŸบๆ–ผ Python ๅž‹ๅˆฅๆ็คบ๏ผŒๅฎš็พฉ่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–่ˆ‡ๆ–‡ไปถ๏ผˆไฝฟ็”จ JSON Schema๏ผ‰็š„ๅ‡ฝๅผๅบซใ€‚ + +้€™่ฎ“ๅฎƒ้žๅธธ็›ด่ฆบใ€‚ + +ๅฎƒๅฏ่ˆ‡ Marshmallow ็›ธๆไธฆ่ซ–ใ€‚ๅ„˜็ฎกๅœจๆ•ˆ่ƒฝๆธฌ่ฉฆไธญๅฎƒๆฏ” Marshmallow ๆ›ดๅฟซใ€‚่€Œไธ”ๅ› ็‚บๅฎƒๅŸบๆ–ผ็›ธๅŒ็š„ Python ๅž‹ๅˆฅๆ็คบ๏ผŒ็ทจ่ผฏๅ™จๆ”ฏๆดไนŸๅพˆๅ‡บ่‰ฒใ€‚ + +/// check | **FastAPI** ็”จๆ–ผ + +่™•็†ๆ‰€ๆœ‰่ณ‡ๆ–™้ฉ—่ญ‰ใ€่ณ‡ๆ–™ๅบๅˆ—ๅŒ–่ˆ‡่‡ชๅ‹•ๆจกๅž‹ๆ–‡ไปถ๏ผˆๅŸบๆ–ผ JSON Schema๏ผ‰ใ€‚ + +**FastAPI** ๆŽฅ่‘—ๆœƒๆŠŠ้€™ไบ› JSON Schema ่ณ‡ๆ–™ๆ”พๅ…ฅ OpenAPI ไธญ๏ผŒๆญคๅค–้‚„ๆœ‰ๅ…ถไป–่จฑๅคšๅŠŸ่ƒฝใ€‚ + +/// + +### Starlette { #starlette } + +Starlette ๆ˜ฏไธ€ๅ€‹่ผ•้‡็š„ ASGI ๆก†ๆžถ๏ผๅทฅๅ…ท้›†๏ผŒ้žๅธธ้ฉๅˆ็”จไพ†ๅปบๆง‹้ซ˜ๆ•ˆ่ƒฝ็š„ asyncio ๆœๅ‹™ใ€‚ + +ๅฎƒ้žๅธธ็ฐกๅ–ฎ็›ด่ง€ใ€‚่จญ่จˆไธŠๆ˜“ๆ–ผๆ“ดๅ……๏ผŒไธ”ๅ…ƒไปถๅŒ–ใ€‚ + +ๅฎƒๅ…ทๅ‚™๏ผš + +* ไปคไบบๅฐ่ฑกๆทฑๅˆป็š„ๆ•ˆ่ƒฝใ€‚ +* WebSocket ๆ”ฏๆดใ€‚ +* ่กŒ็จ‹ๅ…ง๏ผˆin-process๏ผ‰่ƒŒๆ™ฏไปปๅ‹™ใ€‚ +* ๅ•Ÿๅ‹•่ˆ‡้—œ้–‰ไบ‹ไปถใ€‚ +* ๅปบ็ซ‹ๅœจ HTTPX ไธŠ็š„ๆธฌ่ฉฆ็”จๆˆถ็ซฏใ€‚ +* CORSใ€GZipใ€้œๆ…‹ๆช”ๆกˆใ€ไธฒๆตๅ›žๆ‡‰ใ€‚ +* Session ่ˆ‡ Cookie ๆ”ฏๆดใ€‚ +* 100% ๆธฌ่ฉฆๆถต่“‹็އใ€‚ +* 100% ๅž‹ๅˆฅ่จป่งฃ็š„็จ‹ๅผ็ขผๅบซใ€‚ +* ๅนพไนŽๆฒ’ๆœ‰็กฌๆ€ง็›ธไพใ€‚ + +Starlette ็›ฎๅ‰ๆ˜ฏๆธฌ่ฉฆไธญๆœ€ๅฟซ็š„ Python ๆก†ๆžถใ€‚ๅƒ…ๆฌกๆ–ผ Uvicorn๏ผˆๅฎƒไธๆ˜ฏๆก†ๆžถ๏ผŒ่€Œๆ˜ฏไผบๆœๅ™จ๏ผ‰ใ€‚ + +Starlette ๆไพ›ๆ‰€ๆœ‰็ถฒ้ ๅพฎๆก†ๆžถ็š„ๅŸบ็คŽๅŠŸ่ƒฝใ€‚ + +ไฝ†ๅฎƒไธๆไพ›่‡ชๅ‹•็š„่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๅบๅˆ—ๅŒ–ๆˆ–ๆ–‡ไปถใ€‚ + +้€™ๆญฃๆ˜ฏ **FastAPI** ๅœจๅ…ถไธŠๆ–นๅŠ ๅ…ฅ็š„ไธป่ฆๅŠŸ่ƒฝไน‹ไธ€๏ผŒไธ”ๅ…จ้ƒจๅŸบๆ–ผ Python ๅž‹ๅˆฅๆ็คบ๏ผˆไฝฟ็”จ Pydantic๏ผ‰ใ€‚ๆญคๅค–้‚„ๆœ‰็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑใ€ๅฎ‰ๅ…จๆ€งๅทฅๅ…ทใ€OpenAPI ็ตๆง‹็”ข็”Ÿ็ญ‰ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ASGI ๆ˜ฏ็”ฑ Django ๆ ธๅฟƒๅœ˜้šŠๆˆๅ“กๆญฃๅœจ้–‹็™ผ็š„ๆ–ฐใ€Œๆจ™ๆบ–ใ€ใ€‚ๅฎƒๅฐšๆœชๆˆ็‚บใ€ŒPython ๆจ™ๆบ–ใ€๏ผˆPEP๏ผ‰๏ผŒไฝ†ไป–ๅ€‘ๆญฃ่‘—ๆ‰‹้€ฒ่กŒไธญใ€‚ + +ๅ„˜็ฎกๅฆ‚ๆญค๏ผŒๅฎƒๅทฒ่ขซๅคšๅ€‹ๅทฅๅ…ทไฝœ็‚บใ€Œๆจ™ๆบ–ใ€ๆŽก็”จใ€‚้€™ๅคงๅน…ๆๅ‡ไบ†ไบ’้€šๆ€ง๏ผŒไพ‹ๅฆ‚ไฝ ๅฏไปฅๆŠŠ Uvicorn ๆ›ๆˆๅ…ถไป– ASGI ไผบๆœๅ™จ๏ผˆๅฆ‚ Daphne ๆˆ– Hypercorn๏ผ‰๏ผŒๆˆ–ๅŠ ๅ…ฅ็›ธๅฎน ASGI ็š„ๅทฅๅ…ท๏ผŒๅฆ‚ `python-socketio`ใ€‚ + +/// + +/// check | **FastAPI** ็”จๆ–ผ + +่™•็†ๆ‰€ๆœ‰ๆ ธๅฟƒ็ถฒ้ ้ƒจๅˆ†๏ผŒไธฆๅœจๅ…ถไธŠๅŠ ไธŠๅŠŸ่ƒฝใ€‚ + +`FastAPI` ้€™ๅ€‹้กžๅˆฅๆœฌ่บซ็›ดๆŽฅ็นผๆ‰ฟ่‡ช `Starlette` ้กžๅˆฅใ€‚ + +ๅ› ๆญค๏ผŒๅ‡กๆ˜ฏไฝ ่ƒฝ็”จ Starlette ๅš็š„ไบ‹๏ผŒไฝ ๅนพไนŽ้ƒฝ่ƒฝ็›ดๆŽฅ็”จ **FastAPI** ๅฎŒๆˆ๏ผŒๅ› ็‚บๅฎƒๅŸบๆœฌไธŠๅฐฑๆ˜ฏๅŠ ๅผท็‰ˆ็š„ Starletteใ€‚ + +/// + +### Uvicorn { #uvicorn } + +Uvicorn ๆ˜ฏๅŸบๆ–ผ uvloop ่ˆ‡ httptools ็š„ๆฅต้€Ÿ ASGI ไผบๆœๅ™จใ€‚ + +ๅฎƒไธๆ˜ฏ็ถฒ้ ๆก†ๆžถ๏ผŒ่€Œๆ˜ฏไผบๆœๅ™จใ€‚ไพ‹ๅฆ‚๏ผŒๅฎƒไธๆไพ›ไพๆ“š่ทฏๅพ‘่ทฏ็”ฑ็š„ๅทฅๅ…ทใ€‚้€™ๆ˜ฏๅƒ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰้€™ๆจฃ็š„ๆก†ๆžถๅœจๅ…ถไธŠๆ–นๆไพ›็š„ๅŠŸ่ƒฝใ€‚ + +ๅฎƒๆ˜ฏ Starlette ่ˆ‡ **FastAPI** ๆŽจ่–ฆไฝฟ็”จ็š„ไผบๆœๅ™จใ€‚ + +/// check | **FastAPI** ๅปบ่ญฐ็”จไฝœ + +ๅŸท่กŒ **FastAPI** ๆ‡‰็”จ็š„ไธป่ฆ็ถฒ้ ไผบๆœๅ™จใ€‚ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `--workers` ๅ‘ฝไปคๅˆ—้ธ้ …๏ผŒๅ–ๅพ—้žๅŒๆญฅ็š„ๅคš่ฃฝ็จ‹ไผบๆœๅ™จใ€‚ + +ๆ›ดๅคš็ดฐ็ฏ€่ซ‹่ฆ‹[้ƒจ็ฝฒ](deployment/index.md){.internal-link target=_blank}็ซ ็ฏ€ใ€‚ + +/// + +## ๆ•ˆ่ƒฝ่ˆ‡้€Ÿๅบฆ { #benchmarks-and-speed } + +ๆƒณไบ†่งฃใ€ๆฏ”่ผƒไธฆ็œ‹ๅ‡บ Uvicornใ€Starlette ่ˆ‡ FastAPI ไน‹้–“็š„ๅทฎ็•ฐ๏ผŒ่ซ‹ๅƒ่€ƒ[ๆ•ˆ่ƒฝ่ฉ•ๆธฌ](benchmarks.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/async.md b/docs/zh-hant/docs/async.md index 09e2bf9949..a03d71815f 100644 --- a/docs/zh-hant/docs/async.md +++ b/docs/zh-hant/docs/async.md @@ -1,10 +1,10 @@ -# ไธฆ่กŒ่ˆ‡ async / await +# ไธฆ่กŒ่ˆ‡ async / await { #concurrency-and-async-await } ๆœ‰้—œ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*็š„ `async def` ่ชžๆณ•็š„็ดฐ็ฏ€่ˆ‡้žๅŒๆญฅ (asynchronous) ็จ‹ๅผ็ขผใ€ไธฆ่กŒ (concurrency) ่ˆ‡ๅนณ่กŒ (parallelism) ็š„ไธ€ไบ›่ƒŒๆ™ฏ็Ÿฅ่ญ˜ใ€‚ -## ่ถ•ๆ™‚้–“ๅ—Ž? +## ่ถ•ๆ™‚้–“ๅ—Ž? { #in-a-hurry } -TL;DR: +TL;DR: ๅฆ‚ๆžœไฝ ๆญฃๅœจไฝฟ็”จ่ฆๆฑ‚ไฝ ไปฅ `await` ่ชžๆณ•ๅ‘ผๅซ็š„็ฌฌไธ‰ๆ–นๅ‡ฝๅผๅบซ๏ผŒไพ‹ๅฆ‚๏ผš @@ -41,7 +41,7 @@ def results(): --- -ๅฆ‚ๆžœไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไธ้œ€่ฆ่ˆ‡ๅค–้ƒจ่ณ‡ๆบ้€ฒ่กŒไปปไฝ•้€š่จŠไธฆ็ญ‰ๅพ…ๅ…ถๅ›žๆ‡‰๏ผŒ่ซ‹ไฝฟ็”จ `async def`ใ€‚ +ๅฆ‚ๆžœไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไธ้œ€่ฆ่ˆ‡ๅค–้ƒจ่ณ‡ๆบ้€ฒ่กŒไปปไฝ•้€š่จŠไธฆ็ญ‰ๅพ…ๅ…ถๅ›žๆ‡‰๏ผŒ่ซ‹ไฝฟ็”จ `async def`๏ผŒๅณไฝฟๅ…ง้ƒจไธ้œ€่ฆไฝฟ็”จ `await` ไนŸๅฏไปฅใ€‚ --- @@ -55,7 +55,7 @@ def results(): ไฝ†้€้Ž้ตๅพชไธŠ่ฟฐๆญฅ้ฉŸ๏ผŒๅฎƒๅฐ‡่ƒฝ้€ฒ่กŒไธ€ไบ›ๆ•ˆ่ƒฝๆœ€ไฝณๅŒ–ใ€‚ -## ๆŠ€่ก“็ดฐ็ฏ€ +## ๆŠ€่ก“็ดฐ็ฏ€ { #technical-details } ็พไปฃ็‰ˆๆœฌ็š„ Python ๆ”ฏๆดไฝฟ็”จ **ใ€Œๅ”็จ‹ใ€** ็š„ **`async` ๅ’Œ `await`** ่ชžๆณ•ไพ†ๅฏซ **ใ€Œ้žๅŒๆญฅ็จ‹ๅผ็ขผใ€**ใ€‚ @@ -65,7 +65,7 @@ def results(): * **`async` ๅ’Œ `await`** * **ๅ”็จ‹** -## ้žๅŒๆญฅ็จ‹ๅผ็ขผ +## ้žๅŒๆญฅ็จ‹ๅผ็ขผ { #asynchronous-code } ้žๅŒๆญฅ็จ‹ๅผ็ขผๅƒ…ๆ„ๅ‘ณ่‘—็จ‹ๅผ่ชž่จ€ ๐Ÿ’ฌ ๆœ‰่พฆๆณ•ๅ‘Š่จด้›ป่…ฆ/็จ‹ๅผ ๐Ÿค– ๅœจ็จ‹ๅผ็ขผไธญ็š„ๆŸๅ€‹้ปž๏ผŒๅฎƒ ๐Ÿค– ้œ€่ฆ็ญ‰ๅพ…ๆŸไบ›ไบ‹ๆƒ…ๅฎŒๆˆใ€‚่ฎ“ๆˆ‘ๅ€‘ๅ‡่จญ้€™ไบ›ไบ‹ๆƒ…่ขซ็จฑ็‚บใ€Œๆ…ข้€Ÿๆช”ๆกˆใ€๐Ÿ“ใ€‚ @@ -74,7 +74,7 @@ def results(): ๆŽฅ่‘—็จ‹ๅผ ๐Ÿค– ๆœƒๅœจๆœ‰็ฉบๆช”ๆ™‚ๅ›žไพ†ๆŸฅ็œ‹ๆ˜ฏๅฆๆœ‰็ญ‰ๅพ…็š„ๅทฅไฝœๅทฒ็ถ“ๅฎŒๆˆ๏ผŒไธฆๅŸท่กŒๅฟ…่ฆ็š„ๅพŒ็บŒๆ“ไฝœใ€‚ ๆŽฅไธ‹ไพ†๏ผŒๅฎƒ ๐Ÿค– ๅฎŒๆˆ็ฌฌไธ€ๅ€‹ๅทฅไฝœ๏ผˆไพ‹ๅฆ‚ๆˆ‘ๅ€‘็š„ใ€Œๆ…ข้€Ÿๆช”ๆกˆใ€๐Ÿ“๏ผ‰ไธฆ็นผ็บŒๅŸท่กŒ็›ธ้—œ็š„ๆ‰€ๆœ‰ๆ“ไฝœใ€‚ -้€™ๅ€‹ใ€Œ็ญ‰ๅพ…ๅ…ถไป–ไบ‹ๆƒ…ใ€้€šๅธธๆŒ‡็š„ๆ˜ฏไธ€ไบ›็›ธๅฐ่ผƒๆ…ข็š„๏ผˆ่ˆ‡่™•็†ๅ™จๅ’Œ RAM ่จ˜ๆ†ถ้ซ”็š„้€Ÿๅบฆ็›ธๆฏ”๏ผ‰็š„ I/O ๆ“ไฝœ๏ผŒๆฏ”ๅฆ‚่ชช๏ผš +้€™ๅ€‹ใ€Œ็ญ‰ๅพ…ๅ…ถไป–ไบ‹ๆƒ…ใ€้€šๅธธๆŒ‡็š„ๆ˜ฏไธ€ไบ›็›ธๅฐ่ผƒๆ…ข็š„๏ผˆ่ˆ‡่™•็†ๅ™จๅ’Œ RAM ่จ˜ๆ†ถ้ซ”็š„้€Ÿๅบฆ็›ธๆฏ”๏ผ‰็š„ I/O ๆ“ไฝœ๏ผŒๆฏ”ๅฆ‚่ชช๏ผš * ้€้Ž็ถฒ่ทฏๅ‚ณ้€ไพ†่‡ช็”จๆˆถ็ซฏ็š„่ณ‡ๆ–™ * ๅพž็ถฒ่ทฏๆŽฅๆ”ถไพ†่‡ช็”จๆˆถ็ซฏ็š„่ณ‡ๆ–™ @@ -85,7 +85,7 @@ def results(): * ่ณ‡ๆ–™ๅบซๆŸฅ่ฉข * ็ญ‰็ญ‰ -็”ฑๆ–ผๅคง้ƒจๅˆ†็š„ๅŸท่กŒๆ™‚้–“้ƒฝๆถˆ่€—ๅœจ็ญ‰ๅพ… I/O ๆ“ไฝœไธŠ๏ผŒๅ› ๆญค้€™ไบ›ๆ“ไฝœ่ขซ็จฑ็‚บ "I/O ๅฏ†้›†ๅž‹" ๆ“ไฝœใ€‚ +็”ฑๆ–ผๅคง้ƒจๅˆ†็š„ๅŸท่กŒๆ™‚้–“้ƒฝๆถˆ่€—ๅœจ็ญ‰ๅพ… I/O ๆ“ไฝœไธŠ๏ผŒๅ› ๆญค้€™ไบ›ๆ“ไฝœ่ขซ็จฑ็‚บ "I/O ๅฏ†้›†ๅž‹" ๆ“ไฝœใ€‚ ไน‹ๆ‰€ไปฅ็จฑ็‚บใ€Œ้žๅŒๆญฅใ€๏ผŒๆ˜ฏๅ› ็‚บ้›ป่…ฆ/็จ‹ๅผไธ้œ€่ฆ่ˆ‡้‚ฃไบ›่€—ๆ™‚็š„ไปปๅ‹™ใ€ŒๅŒๆญฅใ€๏ผŒ็ญ‰ๅพ…ไปปๅ‹™ๅฎŒๆˆ็š„็ฒพ็ขบๆ™‚้–“๏ผŒ็„ถๅพŒๆ‰่ƒฝๅ–ๅพ—็ตๆžœไธฆ็นผ็บŒๅทฅไฝœใ€‚ @@ -93,7 +93,7 @@ def results(): ็›ธๅฐๆ–ผใ€Œ้žๅŒๆญฅใ€๏ผˆasynchronous๏ผ‰๏ผŒใ€ŒๅŒๆญฅใ€๏ผˆsynchronous๏ผ‰ไนŸๅธธ่ขซ็จฑไฝœใ€Œ้ †ๅบๆ€งใ€๏ผˆsequential๏ผ‰๏ผŒๅ› ็‚บ้›ป่…ฆ/็จ‹ๅผๆœƒไพๅบๅŸท่กŒๆ‰€ๆœ‰ๆญฅ้ฉŸ๏ผŒๅณไพฟ้€™ไบ›ๆญฅ้ฉŸๆถ‰ๅŠ็ญ‰ๅพ…๏ผŒๆ‰ๆœƒๅˆ‡ๆ›ๅˆฐๅ…ถไป–ไปปๅ‹™ใ€‚ -### ไธฆ่กŒ่ˆ‡ๆผขๅ ก +### ไธฆ่กŒ่ˆ‡ๆผขๅ ก { #concurrency-and-burgers } ไธŠ่ฟฐ้žๅŒๆญฅ็จ‹ๅผ็ขผ็š„ๆฆ‚ๅฟตๆœ‰ๆ™‚ไนŸ่ขซ็จฑ็‚บใ€Œไธฆ่กŒใ€๏ผŒๅฎƒไธๅŒๆ–ผใ€Œๅนณ่กŒใ€ใ€‚ @@ -103,7 +103,7 @@ def results(): ็‚บไบ†็†่งฃๅทฎ็•ฐ๏ผŒ่ซ‹ๆƒณๅƒไปฅไธ‹ๆœ‰้—œๆผขๅ ก็š„ๆ•…ไบ‹๏ผš -### ไธฆ่กŒๆผขๅ ก +### ไธฆ่กŒๆผขๅ ก { #concurrent-burgers } ไฝ ๅ’Œไฝ ็š„ๆˆ€ไบบๅŽป้€Ÿ้ฃŸๅบ—๏ผŒๆŽ’้šŠ็ญ‰ๅ€™ๆ™‚๏ผŒๆ”ถ้Š€ๅ“กๆญฃๅœจๅนซๆŽ’ๅœจไฝ ๅ‰้ข็š„ไบบ้ปž้คใ€‚๐Ÿ˜ @@ -163,7 +163,7 @@ def results(): ็„ถๅพŒไฝ ่ตฐๅ‘ๆซƒๆชฏ ๐Ÿ”€๏ผŒๅ›žๅˆฐๅทฒ็ถ“ๅฎŒๆˆ็š„ๆœ€ๅˆไปปๅ‹™ โฏ๏ผŒๆ‹ฟ่ตทๆผขๅ ก๏ผŒ่ชช่ฒ่ฌ่ฌ๏ผŒไธฆๅธถๅ›žๆกŒไธŠใ€‚้€™ๅฐฑ็ตๆŸไบ†่ˆ‡ๆซƒๆชฏ็š„ไบ’ๅ‹•ๆญฅ้ฉŸ/ไปปๅ‹™ โน๏ผŒๆŽฅไธ‹ไพ†ๆœƒ็”ข็”Ÿไธ€ๅ€‹ๆ–ฐ็š„ไปปๅ‹™๏ผŒใ€Œๅƒๆผขๅ กใ€ ๐Ÿ”€ โฏ๏ผŒ่€Œๅ…ˆๅ‰็š„ใ€Œๆ‹ฟๆผขๅ กใ€ไปปๅ‹™ๅทฒ็ถ“ๅฎŒๆˆไบ† โนใ€‚ -### ๅนณ่กŒๆผขๅ ก +### ๅนณ่กŒๆผขๅ ก { #parallel-burgers } ็พๅœจ๏ผŒ่ฎ“ๆˆ‘ๅ€‘ไพ†ๆƒณๅƒ้€™่ฃกไธๆ˜ฏใ€Œไธฆ่กŒๆผขๅ กใ€๏ผŒ่€Œๆ˜ฏใ€Œๅนณ่กŒๆผขๅ กใ€ใ€‚ @@ -233,7 +233,7 @@ def results(): ๆ‰€ไปฅ๏ผŒไฝ ไธๆœƒๆƒณๅธถไฝ ็š„ๆˆ€ไบบ ๐Ÿ˜ ไธ€่ตทๅŽป้Š€่กŒ่พฆไบ‹ ๐Ÿฆใ€‚ -### ๆผขๅ ก็ต่ซ– +### ๆผขๅ ก็ต่ซ– { #burger-conclusion } ๅœจใ€Œๅ’Œๆˆ€ไบบไธ€่ตทๅƒ้€Ÿ้ฃŸๆผขๅ กใ€็š„้€™ๅ€‹ๅ ดๆ™ฏไธญ๏ผŒ็”ฑๆ–ผๆœ‰ๅคง้‡็š„็ญ‰ๅพ… ๐Ÿ•™๏ผŒไฝฟ็”จไธฆ่กŒ็ณป็ตฑ โธ๐Ÿ”€โฏ ๆ›ดๆœ‰ๆ„็พฉใ€‚ @@ -253,7 +253,7 @@ def results(): ไฝ ๅฏไปฅๅŒๆ™‚ๅˆฉ็”จไธฆ่กŒๆ€งๅ’Œๅนณ่กŒๆ€ง๏ผŒ้€ฒไธ€ๆญฅๆๅ‡ๆ•ˆ่ƒฝ๏ผŒ้€™ๆฏ”ๅคงๅคšๆ•ธๅทฒๆธฌ่ฉฆ็š„ NodeJS ๆก†ๆžถ้ƒฝๆ›ดๅฟซ๏ผŒไธฆไธ”่ˆ‡ Go ่ชž่จ€็›ธ็•ถ๏ผŒ่€Œ Go ๆ˜ฏไธ€็จฎๆ›ดๆŽฅ่ฟ‘ C ็š„็ทจ่ญฏ่ชž่จ€๏ผˆๆ„Ÿ่ฌ Starlette๏ผ‰ใ€‚ -### ไธฆ่กŒๆฏ”ๅนณ่กŒๆ›ดๅฅฝๅ—Ž๏ผŸ +### ไธฆ่กŒๆฏ”ๅนณ่กŒๆ›ดๅฅฝๅ—Ž๏ผŸ { #is-concurrency-better-than-parallelism } ไธๆ˜ฏ็š„๏ผ้€™ไธๆ˜ฏๆ•…ไบ‹็š„ๆœฌๆ„ใ€‚ @@ -277,7 +277,7 @@ def results(): ๅœจ้€™ๅ€‹ๅ ดๆ™ฏไธญ๏ผŒๆฏๅ€‹ๆธ…ๆฝ”ๅทฅ๏ผˆๅŒ…ๆ‹ฌไฝ ๏ผ‰้ƒฝๆ˜ฏไธ€ๅ€‹่™•็†ๅ™จ๏ผŒๅฎŒๆˆๅทฅไฝœ็š„ไธ€้ƒจๅˆ†ใ€‚ -็”ฑๆ–ผๅคงๅคšๆ•ธ็š„ๅŸท่กŒๆ™‚้–“้ƒฝ่Šฑๅœจๅฏฆ้š›็š„ๅทฅไฝœไธŠ๏ผˆ่€Œไธๆ˜ฏ็ญ‰ๅพ…๏ผ‰๏ผŒ่€Œ้›ป่…ฆไธญ็š„ๅทฅไฝœ็”ฑ CPU ๅฎŒๆˆ๏ผŒๅ› ๆญค้€™ไบ›ๅ•้กŒ่ขซ็จฑ็‚บใ€ŒCPU ๅฏ†้›†ๅž‹ใ€ใ€‚ +็”ฑๆ–ผๅคงๅคšๆ•ธ็š„ๅŸท่กŒๆ™‚้–“้ƒฝ่Šฑๅœจๅฏฆ้š›็š„ๅทฅไฝœไธŠ๏ผˆ่€Œไธๆ˜ฏ็ญ‰ๅพ…๏ผ‰๏ผŒ่€Œ้›ป่…ฆไธญ็š„ๅทฅไฝœ็”ฑ CPU ๅฎŒๆˆ๏ผŒๅ› ๆญค้€™ไบ›ๅ•้กŒ่ขซ็จฑ็‚บใ€ŒCPU ๅฏ†้›†ๅž‹ใ€ใ€‚ --- @@ -290,7 +290,7 @@ def results(): * **ๆฉŸๅ™จๅญธ็ฟ’**: ้€šๅธธ้œ€่ฆๅคง้‡็š„ใ€Œ็Ÿฉ้™ฃใ€ๅ’Œใ€Œๅ‘้‡ใ€้‹็ฎ—ใ€‚ๆƒณๅƒไธ€ๅ€‹ๅŒ…ๅซๆ•ธๅญ—็š„ๅทจๅคง้›ปๅญ่กจๆ ผ๏ผŒไธฆๆ‰€ๆœ‰็š„ๆ•ธๅญ—ๅŒๆ™‚็›ธไน˜; * **ๆทฑๅบฆๅญธ็ฟ’**: ้€™ๆ˜ฏๆฉŸๅ™จๅญธ็ฟ’็š„ๅญ้ ˜ๅŸŸ๏ผŒๅŒๆจฃ้ฉ็”จใ€‚ๅชไธ้Ž้€™ไธๅƒ…ๅƒ…ๆ˜ฏไธ€ๅผตๆ•ธๅญ—่กจๆ ผ๏ผŒ่€Œๆ˜ฏๅคง้‡็š„ๆ•ธๆ“š้›†ๅˆ๏ผŒไธฆไธ”ๅœจๅพˆๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒไฝฟ็”จ็‰นๆฎŠ็š„่™•็†ๅ™จไพ†ๆง‹ๅปบๆˆ–ไฝฟ็”จ้€™ไบ›ๆจกๅž‹ใ€‚ -### ไธฆ่กŒ + ๅนณ่กŒ: Web + ๆฉŸๅ™จๅญธ็ฟ’ +### ไธฆ่กŒ + ๅนณ่กŒ: Web + ๆฉŸๅ™จๅญธ็ฟ’ { #concurrency-parallelism-web-machine-learning } ไฝฟ็”จ **FastAPI**๏ผŒไฝ ๅฏไปฅๅˆฉ็”จไธฆ่กŒ็š„ๅ„ชๅ‹ข๏ผŒ้€™ๅœจ Web ้–‹็™ผไธญ้žๅธธๅธธ่ฆ‹๏ผˆ้€™ไนŸๆ˜ฏ NodeJS ็š„ๆœ€ๅคงๅธๅผ•ๅŠ›๏ผ‰ใ€‚ @@ -300,9 +300,9 @@ def results(): ๆƒณไบ†่งฃๅฆ‚ไฝ•ๅœจ็”Ÿ็”ข็’ฐๅขƒไธญๅฏฆ็พ้€™็จฎๅนณ่กŒๆ€ง๏ผŒ่ซ‹ๅƒ่ฆ‹ [้ƒจๅฑฌ](deployment/index.md){.internal-link target=_blank}ใ€‚ -## `async` ๅ’Œ `await` +## `async` ๅ’Œ `await` { #async-and-await } -็พไปฃ Python ็‰ˆๆœฌๆไพ›ไธ€็จฎ้žๅธธ็›ด่ง€็š„ๆ–นๅผๅฎš็พฉ้žๅŒๆญฅ็จ‹ๅผ็ขผใ€‚้€™ไฝฟๅพ—ๅฎƒ็œ‹่ตทไพ†ๅฐฑๅƒๆญฃๅธธ็š„ใ€Œ้ †ๅบใ€็จ‹ๅผ็ขผ๏ผŒไธฆๅœจ้ฉ็•ถ็š„ๆ™‚ๆฉŸใ€Œ็ญ‰ๅพ…ใ€ใ€‚ +็พไปฃ Python ็‰ˆๆœฌๆไพ›ไธ€็จฎ้žๅธธ็›ด่ง€็š„ๆ–นๅผๅฎš็พฉ้žๅŒๆญฅ็จ‹ๅผ็ขผใ€‚้€™ไฝฟๅพ—ๅฎƒ็œ‹่ตทไพ†ๅฐฑๅƒๆญฃๅธธ็š„ใ€Œ้ †ๅบใ€็จ‹ๅผ็ขผ๏ผŒไธฆๅœจ้ฉ็•ถ็š„ๆ™‚ๆฉŸๆ›ฟไฝ ใ€Œ็ญ‰ๅพ…ใ€ใ€‚ ็•ถๆŸๅ€‹ๆ“ไฝœ้œ€่ฆ็ญ‰ๅพ…ๆ‰่ƒฝๅ›žๅ‚ณ็ตๆžœ๏ผŒไธฆไธ”ๆ”ฏๆด้€™ไบ›ๆ–ฐ็š„ Python ็‰นๆ€งๆ™‚๏ผŒไฝ ๅฏไปฅๅƒ้€™ๆจฃ็ทจๅฏซ็จ‹ๅผ็ขผ๏ผš @@ -329,7 +329,7 @@ def get_sequential_burgers(number: int): return burgers ``` -ไฝฟ็”จ `async def`๏ผŒPython Python ็Ÿฅ้“ๅœจ่ฉฒๅ‡ฝๅผๅ…ง้œ€่ฆๆณจๆ„ `await`๏ผŒไธฆไธ”ๅฎƒๅฏไปฅใ€Œๆšซๅœใ€ โธ ๅŸท่กŒ่ฉฒๅ‡ฝๅผ๏ผŒ็„ถๅพŒๅŸท่กŒๅ…ถไป–ไปปๅ‹™ ๐Ÿ”€ ๅพŒๅ›žไพ†ใ€‚ +ไฝฟ็”จ `async def`๏ผŒPython ็Ÿฅ้“ๅœจ่ฉฒๅ‡ฝๅผๅ…ง้œ€่ฆๆณจๆ„ `await`๏ผŒไธฆไธ”ๅฎƒๅฏไปฅใ€Œๆšซๅœใ€ โธ ๅŸท่กŒ่ฉฒๅ‡ฝๅผ๏ผŒ็„ถๅพŒๅŸท่กŒๅ…ถไป–ไปปๅ‹™ ๐Ÿ”€ ๅพŒๅ›žไพ†ใ€‚ ็•ถไฝ ๆƒณ่ฆๅ‘ผๅซ `async def` ๅ‡ฝๅผๆ™‚๏ผŒๅฟ…้ ˆไฝฟ็”จใ€Œawaitใ€ใ€‚ๅ› ๆญค๏ผŒ้€™ๆจฃๅฏซๅฐ‡็„กๆณ•้‹่กŒ๏ผš @@ -349,11 +349,11 @@ async def read_burgers(): return burgers ``` -### ๆ›ดๅคšๆŠ€่ก“็ดฐ็ฏ€ +### ๆ›ดๅคšๆŠ€่ก“็ดฐ็ฏ€ { #more-technical-details } ไฝ ๅฏ่ƒฝๅทฒ็ถ“ๆณจๆ„ๅˆฐ๏ผŒ`await` ๅช่ƒฝๅœจ `async def` ๅฎš็พฉ็š„ๅ‡ฝๅผๅ…งไฝฟ็”จใ€‚ -ไฝ†ๅŒๆ™‚๏ผŒไฝฟ็”จ `async def` ๅฎš็พฉ็š„ๅ‡ฝๅผๆœฌ่บซไนŸๅฟ…้ ˆ่ขซใ€Œ็ญ‰ๅพ…ใ€ใ€‚ๆ‰€ไปฅ๏ผŒๅธถๆœ‰ `async def` ๅ‡ฝๅผๅช่ƒฝๅœจๅ…ถไป–ไฝฟ็”จ `async def` ๅฎš็พฉ็š„ๅ‡ฝๅผๅ…งๅ‘ผๅซใ€‚ +ไฝ†ๅŒๆ™‚๏ผŒไฝฟ็”จ `async def` ๅฎš็พฉ็š„ๅ‡ฝๅผๆœฌ่บซไนŸๅฟ…้ ˆ่ขซใ€Œ็ญ‰ๅพ…ใ€ใ€‚ๆ‰€ไปฅ๏ผŒๅธถๆœ‰ `async def` ็š„ๅ‡ฝๅผๅช่ƒฝๅœจๅ…ถไป–ไฝฟ็”จ `async def` ๅฎš็พฉ็š„ๅ‡ฝๅผๅ…งๅ‘ผๅซใ€‚ ้‚ฃ้บผ๏ผŒ้€™ๅฐฑๅƒใ€Œๅ…ˆๆœ‰้›ž้‚„ๆ˜ฏๅ…ˆๆœ‰่›‹ใ€็š„ๅ•้กŒ๏ผŒ่ฆๅฆ‚ไฝ•ๅ‘ผๅซ็ฌฌไธ€ๅ€‹ `async` ๅ‡ฝๅผๅ‘ข๏ผŸ @@ -361,35 +361,37 @@ async def read_burgers(): ไฝ†ๅฆ‚ๆžœไฝ ๆƒณๅœจๆฒ’ๆœ‰ FastAPI ็š„ๆƒ…ๆณไธ‹ไฝฟ็”จ `async` / `await`๏ผŒไฝ ไนŸๅฏไปฅ้€™ๆจฃๅšใ€‚ -### ็ทจๅฏซ่‡ชๅทฑ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผ +### ็ทจๅฏซ่‡ชๅทฑ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผ { #write-your-own-async-code } -Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบๆ–ผ AnyIO ๅฏฆไฝœ็š„๏ผŒ้€™ไฝฟๅพ—ๅฎƒๅ€‘่ˆ‡ Python ๆจ™ๆบ–ๅ‡ฝๅผๅบซ็›ธๅฎน asyncio ๅ’Œ Trioใ€‚ +Starlette๏ผˆๅ’Œ **FastAPI**๏ผ‰ๆ˜ฏๅŸบๆ–ผ AnyIO ๅฏฆไฝœ็š„๏ผŒ้€™ไฝฟๅพ—ๅฎƒๅ€‘่ˆ‡ Python ๆจ™ๆบ–ๅ‡ฝๅผๅบซ asyncio ๅ’Œ Trio ็›ธๅฎนใ€‚ ็‰นๅˆฅๆ˜ฏ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ AnyIO ไพ†่™•็†ๆ›ด่ค‡้›œ็š„ไธฆ่กŒไฝฟ็”จๆกˆไพ‹๏ผŒ้€™ไบ›ๆกˆไพ‹้œ€่ฆไฝ ๅœจ่‡ชๅทฑ็š„็จ‹ๅผ็ขผไธญไฝฟ็”จๆ›ด้ซ˜้šŽ็š„ๆจกๅผใ€‚ -ๅณไฝฟไฝ ไธไฝฟ็”จ **FastAPI**๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ AnyIO ไพ†ๆ’ฐๅฏซ่‡ชๅทฑ็š„้žๅŒๆญฅๆ‡‰็”จ็จ‹ๅผ๏ผŒไธฆ็ฒๅพ—้ซ˜็›ธๅฎนๆ€งๅŠไธ€ไบ›ๅฅฝ่™•๏ผˆไพ‹ๅฆ‚็ตๆง‹ๅŒ–ไธฆ่กŒ๏ผ‰ใ€‚ +ๅณไฝฟไฝ ไธไฝฟ็”จ **FastAPI**๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ AnyIO ไพ†ๆ’ฐๅฏซ่‡ชๅทฑ็š„้žๅŒๆญฅๆ‡‰็”จ็จ‹ๅผ๏ผŒไธฆ็ฒๅพ—้ซ˜็›ธๅฎนๆ€งๅŠไธ€ไบ›ๅฅฝ่™•๏ผˆไพ‹ๅฆ‚ใ€Œ็ตๆง‹ๅŒ–ไธฆ่กŒใ€๏ผ‰ใ€‚ -### ๅ…ถไป–ๅฝขๅผ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผ +ๆˆ‘ๅฆๅค–ๅœจ AnyIO ไน‹ไธŠๅšไบ†ไธ€ๅ€‹่–„ๅฐ่ฃ็š„ๅ‡ฝๅผๅบซ๏ผŒ็จๅพฎๆ”น้€ฒๅž‹ๅˆฅ่จป่งฃไปฅ็ฒๅพ—ๆ›ดๅฅฝ็š„**่‡ชๅ‹•่ฃœๅ…จ**ใ€**ๅณๆ™‚้Œฏ่ชค**็ญ‰ใ€‚ๅŒๆ™‚ๅฎƒไนŸๆไพ›ๅ‹ๅ–„็š„ไป‹็ดน่ˆ‡ๆ•™ๅญธ๏ผŒๅนซๅŠฉไฝ **็†่งฃ**ไธฆๆ’ฐๅฏซ**่‡ชๅทฑ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผ**๏ผšAsyncerใ€‚็•ถไฝ ้œ€่ฆ**ๅฐ‡้žๅŒๆญฅ็จ‹ๅผ็ขผ่ˆ‡ไธ€่ˆฌ**๏ผˆ้˜ปๅกž/ๅŒๆญฅ๏ผ‰**็จ‹ๅผ็ขผๆ•ดๅˆ**ๆ™‚๏ผŒๅฎƒ็‰นๅˆฅๅฏฆ็”จใ€‚ + +### ๅ…ถไป–ๅฝขๅผ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผ { #other-forms-of-asynchronous-code } ไฝฟ็”จ `async` ๅ’Œ `await` ็š„้ขจๆ ผๅœจ่ชž่จ€ไธญ็›ธๅฐ่ผƒๆ–ฐใ€‚ -ไฝ†ๅฎƒไฝฟ่™•็†็•ฐๆญฅ็จ‹ๅผ็ขผ่ฎŠๅพ—ๆ›ดๅŠ ๅฎนๆ˜“ใ€‚ +ไฝ†ๅฎƒไฝฟ่™•็†้žๅŒๆญฅ็จ‹ๅผ็ขผ่ฎŠๅพ—ๆ›ดๅŠ ๅฎนๆ˜“ใ€‚ ็›ธๅŒ็š„่ชžๆณ•๏ผˆๆˆ–ๅนพไนŽ็›ธๅŒ็š„่ชžๆณ•๏ผ‰ๆœ€่ฟ‘ไนŸ่ขซๅŒ…ๅซๅœจ็พไปฃ JavaScript๏ผˆ็„ก่ซ–ๆ˜ฏ็€่ฆฝๅ™จ้‚„ๆ˜ฏ NodeJS๏ผ‰ไธญใ€‚ -ไฝ†ๅœจๆญคไน‹ๅ‰๏ผŒ่™•็†็•ฐๆญฅ็จ‹ๅผ็ขผ่ฆๆ›ดๅŠ ่ค‡้›œๅ’Œๅ›ฐ้›ฃใ€‚ +ไฝ†ๅœจๆญคไน‹ๅ‰๏ผŒ่™•็†้žๅŒๆญฅ็จ‹ๅผ็ขผ่ฆๆ›ดๅŠ ่ค‡้›œๅ’Œๅ›ฐ้›ฃใ€‚ ๅœจ่ผƒ่ˆŠ็š„ Python ็‰ˆๆœฌไธญ๏ผŒไฝ ๅฏ่ƒฝๆœƒไฝฟ็”จๅคšๅŸท่กŒ็ท’ๆˆ– Geventใ€‚ไฝ†้€™ไบ›็จ‹ๅผ็ขผ่ฆๆ›ด้›ฃไปฅ็†่งฃใ€่ชฟ่ฉฆๅ’Œๆ€่€ƒใ€‚ ๅœจ่ผƒ่ˆŠ็š„ NodeJS / ็€่ฆฝๅ™จ JavaScript ไธญ๏ผŒไฝ ๆœƒไฝฟ็”จใ€Œๅ›žๅ‘ผใ€๏ผŒ้€™ๅฏ่ƒฝๆœƒๅฐŽ่‡ดโ€œๅ›žๅ‘ผๅœฐ็„โ€ใ€‚ -## ๅ”็จ‹ +## ๅ”็จ‹ { #coroutines } -**ๅ”็จ‹** ๅชๆ˜ฏ `async def` ๅ‡ฝๅผๆ‰€ๅ›žๅ‚ณ็š„้žๅธธ็‰นๆฎŠ็š„ไบ‹็‰ฉๅ็จฑใ€‚Python ็Ÿฅ้“ๅฎƒๆ˜ฏไธ€ๅ€‹้กžไผผๅ‡ฝๅผ็š„ๆฑ่ฅฟ๏ผŒๅฏไปฅๅ•Ÿๅ‹•ๅฎƒ๏ผŒไธฆไธ”ๅœจๆŸๅ€‹ๆ™‚ๅˆปๅฎƒๆœƒ็ตๆŸ๏ผŒไฝ†ๅฎƒไนŸๅฏ่ƒฝๅœจๅ…ง้ƒจๆšซๅœ โธ๏ผŒๅช่ฆ้‡ๅˆฐ `await`ใ€‚ +ใ€Œๅ”็จ‹ใ€ๅชๆ˜ฏ `async def` ๅ‡ฝๅผๆ‰€ๅ›žๅ‚ณ็š„้žๅธธ็‰นๆฎŠ็š„ไบ‹็‰ฉๅ็จฑใ€‚Python ็Ÿฅ้“ๅฎƒๆ˜ฏไธ€ๅ€‹้กžไผผๅ‡ฝๅผ็š„ๆฑ่ฅฟ๏ผŒๅฏไปฅๅ•Ÿๅ‹•ๅฎƒ๏ผŒไธฆไธ”ๅœจๆŸๅ€‹ๆ™‚ๅˆปๅฎƒๆœƒ็ตๆŸ๏ผŒไฝ†ๅฎƒไนŸๅฏ่ƒฝๅœจๅ…ง้ƒจๆšซๅœ โธ๏ผŒๅช่ฆ้‡ๅˆฐ `await`ใ€‚ ้€™็จฎไฝฟ็”จ `async` ๅ’Œ `await` ็š„้žๅŒๆญฅ็จ‹ๅผ็ขผๅŠŸ่ƒฝ้€šๅธธ่ขซๆฆ‚ๆ‹ฌ็‚บใ€Œๅ”็จ‹ใ€ใ€‚้€™่ˆ‡ Go ่ชž่จ€็š„ไธป่ฆ็‰นๆ€งใ€ŒGoroutinesใ€็›ธไผผใ€‚ -## ็ต่ซ– +## ็ต่ซ– { #conclusion } ่ฎ“ๆˆ‘ๅ€‘ๅ†ๆฌกๅ›ž้กงไน‹ๅ‰็š„ๅฅๅญ๏ผš @@ -397,9 +399,9 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบๆ–ผ I/O ็š„็จ‹ๅผ็ขผใ€‚ +ๅฆ‚ๆžœไฝ ไพ†่‡ชๆ–ผๅ…ถไป–ไธไปฅ้€™็จฎๆ–นๅผ้‹ไฝœ็š„้žๅŒๆญฅๆก†ๆžถ๏ผŒ่€Œไธ”ไฝ ็ฟ’ๆ…ฃๆ–ผไฝฟ็”จๆ™ฎ้€š็š„ `def` ๅฎš็พฉๅƒ…้€ฒ่กŒ็ฐกๅ–ฎ่จˆ็ฎ—็š„*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*๏ผŒ็›ฎ็š„ๆ˜ฏ็ฒๅพ—ๅพฎๅฐ็š„ๆ€ง่ƒฝๅขž็›Š๏ผˆๅคง็ด„ 100 ๅฅˆ็ง’๏ผ‰๏ผŒ่ซ‹ๆณจๆ„๏ผŒๅœจ FastAPI ไธญ๏ผŒๆ•ˆๆžœๆœƒๅฎŒๅ…จ็›ธๅใ€‚ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒๆœ€ๅฅฝไฝฟ็”จ `async def`๏ผŒ้™ค้žไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*ๅŸท่กŒ้˜ปๅกž็š„ I/O ็š„็จ‹ๅผ็ขผใ€‚ -ไธ้Ž๏ผŒๅœจ้€™ๅ…ฉ็จฎๆƒ…ๆณไธ‹๏ผŒ**FastAPI** [ไป็„ถๅพˆๅฟซ](index.md#_11){.internal-link target=_blank}่‡ณๅฐ‘่ˆ‡ไฝ ไน‹ๅ‰็š„ๆก†ๆžถ็›ธ็•ถ๏ผˆๆˆ–่€…ๆ›ดๅฟซ๏ผ‰ใ€‚ +ไธ้Ž๏ผŒๅœจ้€™ๅ…ฉ็จฎๆƒ…ๆณไธ‹๏ผŒ**FastAPI** [ไป็„ถๅพˆๅฟซ](index.md#performance){.internal-link target=_blank}๏ผŒ่‡ณๅฐ‘่ˆ‡ไฝ ไน‹ๅ‰็š„ๆก†ๆžถ็›ธ็•ถ๏ผˆๆˆ–่€…ๆ›ดๅฟซ๏ผ‰ใ€‚ -### ไพ่ณด้ …(Dependencies) +### ไพ่ณด้ …(Dependencies) { #dependencies } ๅŒๆจฃ้ฉ็”จๆ–ผ[ไพ่ณด้ …](tutorial/dependencies/index.md){.internal-link target=_blank}ใ€‚ๅฆ‚ๆžœไพ่ณด้ …ๆ˜ฏไธ€ๅ€‹ๆจ™ๆบ–็š„ `def` ๅ‡ฝๅผ๏ผŒ่€Œไธๆ˜ฏ `async def`๏ผŒ้‚ฃ้บผๅฎƒๅœจๅค–้ƒจ็š„ๅŸท่กŒ็ท’ๆฑ ่ขซ้‹่กŒใ€‚ -### ๅญไพ่ณด้ … +### ๅญไพ่ณด้ … { #sub-dependencies } -ไฝ ๅฏไปฅๆ“ๆœ‰ๅคšๅ€‹็›ธไบ’ไพ่ณด็š„ไพ่ณด้ …ๅ’Œ[ๅญไพ่ณด้ …](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} ๏ผˆไฝœ็‚บๅ‡ฝๅผๅฎš็พฉ็š„ๅƒๆ•ธ๏ผ‰๏ผŒๅ…ถไธญไธ€ไบ›ๅฏ่ƒฝๆ˜ฏ็”จ `async def` ๅฎฃๅ‘Š๏ผŒไนŸๅฏ่ƒฝๆ˜ฏ็”จ `def` ๅฎฃๅ‘Šใ€‚ๅฎƒๅ€‘ไป็„ถๅฏไปฅๆญฃๅธธ้‹ไฝœ๏ผŒ็”จ `def` ๅฎš็พฉ็š„้‚ฃไบ›ๅฐ‡ๆœƒๅœจๅค–้ƒจ็š„ๅŸท่กŒ็ท’ไธญๅ‘ผๅซ๏ผˆไพ†่‡ชๅŸท่กŒ็ท’ๆฑ ๏ผ‰๏ผŒ่€Œไธๆ˜ฏ่ขซใ€Œ็ญ‰ๅพ…ใ€ใ€‚ +ไฝ ๅฏไปฅๆ“ๆœ‰ๅคšๅ€‹็›ธไบ’ไพ่ณด็š„ไพ่ณด้ …ๅ’Œ[ๅญไพ่ณด้ …](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}๏ผˆไฝœ็‚บๅ‡ฝๅผๅฎš็พฉ็š„ๅƒๆ•ธ๏ผ‰๏ผŒๅ…ถไธญไธ€ไบ›ๅฏ่ƒฝๆ˜ฏ็”จ `async def` ๅฎฃๅ‘Š๏ผŒไนŸๅฏ่ƒฝๆ˜ฏ็”จ `def` ๅฎฃๅ‘Šใ€‚ๅฎƒๅ€‘ไป็„ถๅฏไปฅๆญฃๅธธ้‹ไฝœ๏ผŒ็”จ `def` ๅฎš็พฉ็š„้‚ฃไบ›ๅฐ‡ๆœƒๅœจๅค–้ƒจ็š„ๅŸท่กŒ็ท’ไธญๅ‘ผๅซ๏ผˆไพ†่‡ชๅŸท่กŒ็ท’ๆฑ ๏ผ‰๏ผŒ่€Œไธๆ˜ฏ่ขซใ€Œ็ญ‰ๅพ…ใ€ใ€‚ -### ๅ…ถไป–่ผ”ๅŠฉๅ‡ฝๅผ +### ๅ…ถไป–่ผ”ๅŠฉๅ‡ฝๅผ { #other-utility-functions } ไฝ ๅฏไปฅ็›ดๆŽฅๅ‘ผๅซไปปไฝ•ไฝฟ็”จ `def` ๆˆ– `async def` ๅปบ็ซ‹็š„ๅ…ถไป–่ผ”ๅŠฉๅ‡ฝๅผ๏ผŒFastAPI ไธๆœƒๅฝฑ้Ÿฟไฝ ๅ‘ผๅซๅฎƒๅ€‘็š„ๆ–นๅผใ€‚ @@ -439,4 +441,4 @@ Starlette ๏ผˆๅ’Œ **FastAPI**๏ผ‰ ๆ˜ฏๅŸบๆ–ผ ่ถ•ๆ™‚้–“ๅ—Ž?. +ๅฆๅ‰‡๏ผŒๅช้œ€้ตๅพชไธŠ้ขๆๅˆฐ็š„ๆŒ‡ๅผ•ๅณๅฏ๏ผš่ถ•ๆ™‚้–“ๅ—Ž?ใ€‚ diff --git a/docs/zh-hant/docs/benchmarks.md b/docs/zh-hant/docs/benchmarks.md index df49621c53..c5b76700b3 100644 --- a/docs/zh-hant/docs/benchmarks.md +++ b/docs/zh-hant/docs/benchmarks.md @@ -6,7 +6,7 @@ ## ๅŸบๆบ–ๆธฌ่ฉฆๅ’Œ้€Ÿๅบฆ { #benchmarks-and-speed } -็•ถไฝ ๆŸฅ็œ‹ๅŸบๆบ–ๆธฌ่ฉฆๆ™‚๏ผŒๆ™‚ๅธธๆœƒ่ฆ‹ๅˆฐๅนพๅ€‹ไธๅŒ้กžๅž‹็š„ๅทฅๅ…ท่ขซๅŒๆ™‚้€ฒ่กŒๆธฌ่ฉฆใ€‚ +็•ถไฝ ๆŸฅ็œ‹ๅŸบๆบ–ๆธฌ่ฉฆๆ™‚๏ผŒๅธธ่ฆ‹ๅˆฐไธๅŒ้กžๅž‹็š„ๅคšๅ€‹ๅทฅๅ…ท่ขซ่ฆ–็‚บ็ญ‰ๅŒไพ†ๆฏ”่ผƒใ€‚ ๅ…ท้ซ”ไพ†่ชช๏ผŒๆ˜ฏๅฐ‡ Uvicornใ€Starlette ๅ’Œ FastAPI ๅŒๆ™‚้€ฒ่กŒๆฏ”่ผƒ๏ผˆไปฅๅŠ่จฑๅคšๅ…ถไป–ๅทฅๅ…ท๏ผ‰ใ€‚ @@ -20,7 +20,7 @@ * **Uvicorn**๏ผš * ๅ…ทๆœ‰ๆœ€ไฝณๆ•ˆ่ƒฝ๏ผŒๅ› ็‚บ้™คไบ†ไผบๆœๅ™จๆœฌ่บซไน‹ๅค–๏ผŒๅฎƒๆฒ’ๆœ‰ๅคชๅคš้กๅค–็š„็จ‹ๅผ็ขผใ€‚ - * ไฝ ไธๆœƒ็›ดๆŽฅๅœจ Uvicorn ไธญ็ทจๅฏซๆ‡‰็”จ็จ‹ๅผใ€‚้€™ๆ„ๅ‘ณ่‘—ไฝ ็š„็จ‹ๅผ็ขผๅฟ…้ ˆๆˆ–ๅคšๆˆ–ๅฐ‘ๅœฐๅŒ…ๅซ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰ๆไพ›็š„ๆ‰€ๆœ‰็จ‹ๅผ็ขผใ€‚ๅฆ‚ๆžœไฝ ้€™ๆจฃๅš๏ผŒไฝ ็š„ๆœ€็ต‚ๆ‡‰็”จ็จ‹ๅผๅฐ‡ๅ…ทๆœ‰่ˆ‡ไฝฟ็”จๆก†ๆžถ็›ธๅŒ็š„้–‹้Šทไธฆๆœ€ๅคง้™ๅบฆๅœฐๆธ›ๅฐ‘ๆ‡‰็”จ็จ‹ๅผ็จ‹ๅผ็ขผๅ’Œ้Œฏ่ชคใ€‚ + * ไฝ ไธๆœƒ็›ดๆŽฅๅœจ Uvicorn ไธญ็ทจๅฏซๆ‡‰็”จ็จ‹ๅผใ€‚้€™ๆ„ๅ‘ณ่‘—ไฝ ็š„็จ‹ๅผ็ขผๅฟ…้ ˆๆˆ–ๅคšๆˆ–ๅฐ‘ๅœฐๅŒ…ๅซ Starlette๏ผˆๆˆ– **FastAPI**๏ผ‰ๆไพ›็š„ๆ‰€ๆœ‰็จ‹ๅผ็ขผใ€‚ๅฆ‚ๆžœไฝ ้€™ๆจฃๅš๏ผŒไฝ ็š„ๆœ€็ต‚ๆ‡‰็”จ็จ‹ๅผๅฐ‡ๅ…ทๆœ‰่ˆ‡ไฝฟ็”จๆก†ๆžถ็›ธๅŒ็š„้–‹้Šท๏ผŒไธ”็„กๆณ•ๅƒไฝฟ็”จๆก†ๆžถ้‚ฃๆจฃๆธ›ๅฐ‘ๆ‡‰็”จ็จ‹ๅผ็จ‹ๅผ็ขผ่ˆ‡้Œฏ่ชคใ€‚ * ๅฆ‚ๆžœไฝ ่ฆๆฏ”่ผƒ Uvicorn๏ผŒ่ซ‹ๅฐ‡ๅ…ถ่ˆ‡ Daphneใ€Hypercornใ€uWSGI ็ญ‰ๆ‡‰็”จ็จ‹ๅผไผบๆœๅ™จ้€ฒ่กŒๆฏ”่ผƒใ€‚ * **Starlette**๏ผš * ็นผ Uvicorn ไน‹ๅพŒ็š„ๆฌกไฝณ่กจ็พใ€‚ไบ‹ๅฏฆไธŠ๏ผŒStarlette ไฝฟ็”จ Uvicorn ไพ†้‹่กŒใ€‚ๅ› ๆญคๅฎƒๅฐ‡ๅฏ่ƒฝๅช้€้ŽๅŸท่กŒๆ›ดๅคš็จ‹ๅผ็ขผ่€Œ่ฎŠๅพ—ๆฏ” Uvicornใ€Œๆ…ขใ€ใ€‚ diff --git a/docs/zh-hant/docs/deployment/concepts.md b/docs/zh-hant/docs/deployment/concepts.md new file mode 100644 index 0000000000..0cca31d260 --- /dev/null +++ b/docs/zh-hant/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployments-concepts } + +็•ถไฝ ่ฆ้ƒจ็ฝฒไธ€ๅ€‹ FastAPI ๆ‡‰็”จ๏ผŒๆˆ–ๅ…ถๅฏฆไปปไฝ•้กžๅž‹็š„ Web API ๆ™‚๏ผŒๆœ‰ๅนพๅ€‹ไฝ ๅฏ่ƒฝๅœจๆ„็š„ๆฆ‚ๅฟตใ€‚ๆŽŒๆก้€™ไบ›ๆฆ‚ๅฟตๅพŒ๏ผŒไฝ ๅฐฑ่ƒฝๆ‰พๅ‡บๆœ€้ฉๅˆ้ƒจ็ฝฒไฝ ๆ‡‰็”จ็š„ๆ–นๅผใ€‚ + +ไธ€ไบ›้‡่ฆ็š„ๆฆ‚ๅฟตๅŒ…ๆ‹ฌ๏ผš + +- ๅฎ‰ๅ…จๆ€ง - HTTPS +- ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ +- ้‡ๆ–ฐๅ•Ÿๅ‹• +- ่ค‡ๆœฌ๏ผˆๅŸท่กŒไธญ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +- ่จ˜ๆ†ถ้ซ” +- ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +ๆˆ‘ๅ€‘ๅฐ‡็œ‹็œ‹ๅฎƒๅ€‘ๅฆ‚ไฝ•ๅฝฑ้Ÿฟ้ƒจ็ฝฒใ€‚ + +ๆœ€็ต‚็›ฎๆจ™ๆ˜ฏ่ƒฝๅค ไปฅๅฎ‰ๅ…จใ€้ฟๅ…ไธญๆ–ท๏ผŒไธฆ็›กๅฏ่ƒฝ้ซ˜ๆ•ˆไฝฟ็”จ้‹็ฎ—่ณ‡ๆบ๏ผˆไพ‹ๅฆ‚้ ็ซฏไผบๆœๅ™จ๏ผ่™›ๆ“ฌๆฉŸ๏ผ‰็š„ๆ–นๅผไพ†ๆœๅ‹™ไฝ ็š„ API ็”จๆˆถ็ซฏใ€‚๐Ÿš€ + +ๆˆ‘ๆœƒๅœจ้€™่ฃกๅคšไป‹็ดนไธ€ไบ›้€™ไบ›่ง€ๅฟต๏ผŒๅธŒๆœ›่ƒฝๅนซไฝ ๅปบ็ซ‹ๅฟ…่ฆ็š„็›ด่ฆบ๏ผŒ่ฎ“ไฝ ่ƒฝๅœจ้žๅธธไธๅŒใ€็”š่‡ณๅฐšๆœชๅ‡บ็พ็š„ๆœชไพ†็’ฐๅขƒไธญๆฑบๅฎš่ฆๅฆ‚ไฝ•้ƒจ็ฝฒไฝ ็š„ APIใ€‚ + +ๅœจๆ€่€ƒ้€™ไบ›ๆฆ‚ๅฟตไน‹ๅพŒ๏ผŒไฝ ๅฐ‡่ƒฝๅค ่ฉ•ไผฐ่ˆ‡่จญ่จˆๆœ€้ฉๅˆ้ƒจ็ฝฒไฝ ่‡ชๅทฑ API ็š„ๆ–นๅผใ€‚ + +ๅœจๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€๏ผŒๆˆ‘ๆœƒๆไพ›ๆ›ดๅ…ท้ซ”็š„้ƒจ็ฝฒ FastAPI ๆ‡‰็”จ็š„้ฃŸ่ญœใ€‚ + +ไฝ†็พๅœจ๏ผŒๅ…ˆไพ†็œ‹็œ‹้€™ไบ›้‡่ฆ็š„ๆฆ‚ๅฟตๆƒณๆณ•ใ€‚้€™ไบ›ๆฆ‚ๅฟตๅŒๆจฃ้ฉ็”จๆ–ผไปปไฝ•ๅ…ถไป–้กžๅž‹็š„ Web APIใ€‚๐Ÿ’ก + +## ๅฎ‰ๅ…จๆ€ง - HTTPS { #security-https } + +ๅœจ[ๅ‰ไธ€็ซ ้—œๆ–ผ HTTPS](https.md){.internal-link target=_blank} ไธญ๏ผŒๆˆ‘ๅ€‘ๅญธๅˆฐ HTTPS ๅฆ‚ไฝ•็‚บไฝ ็š„ API ๆไพ›ๅŠ ๅฏ†ใ€‚ + +ๆˆ‘ๅ€‘ไนŸ็œ‹ๅˆฐ๏ผŒHTTPS ้€šๅธธ็”ฑๆ‡‰็”จไผบๆœๅ™จๅค–้ƒจ็š„ๅ…ƒไปถๆไพ›๏ผŒๅณ TLS Termination Proxyใ€‚ + +่€Œไธ”ๅฟ…้ ˆๆœ‰ๆŸๅ€‹ๆฑ่ฅฟ่ฒ ่ฒฌ็บŒๆœŸ HTTPS ๆ†‘่ญ‰๏ผŒๅฏ่ƒฝๆ˜ฏๅŒไธ€ๅ€‹ๅ…ƒไปถ๏ผŒไนŸๅฏ่ƒฝๆ˜ฏไธๅŒ็š„ๆฑ่ฅฟใ€‚ + +### HTTPS ๅทฅๅ…ท็ฏ„ไพ‹ { #example-tools-for-https } + +ไฝ ๅฏไปฅ็”จไพ†ไฝœ็‚บ TLS Termination Proxy ็š„ๅทฅๅ…ทๅŒ…ๆ‹ฌ๏ผš + +- Traefik + - ่‡ชๅ‹•่™•็†ๆ†‘่ญ‰็บŒๆœŸ โœจ +- Caddy + - ่‡ชๅ‹•่™•็†ๆ†‘่ญ‰็บŒๆœŸ โœจ +- Nginx + - ๆญ้…ๅƒ Certbot ้€™้กžๅค–้ƒจๅ…ƒไปถ้€ฒ่กŒๆ†‘่ญ‰็บŒๆœŸ +- HAProxy + - ๆญ้…ๅƒ Certbot ้€™้กžๅค–้ƒจๅ…ƒไปถ้€ฒ่กŒๆ†‘่ญ‰็บŒๆœŸ +- Kubernetes๏ผŒไฝฟ็”จๅฆ‚ Nginx ็š„ Ingress Controller + - ๆญ้…ๅƒ cert-manager ้€™้กžๅค–้ƒจๅ…ƒไปถ้€ฒ่กŒๆ†‘่ญ‰็บŒๆœŸ +- ็”ฑ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ๅœจๅ…ถๆœๅ‹™ๅ…ง้ƒจ่™•็†๏ผˆ่ฆ‹ไธ‹ๆ–‡ ๐Ÿ‘‡๏ผ‰ + +ๅฆไธ€ๅ€‹้ธ้ …ๆ˜ฏไฝฟ็”จ่ƒฝๅนซไฝ ๅšๆ›ดๅคšไบ‹ๆƒ…็š„้›ฒ็ซฏๆœๅ‹™๏ผˆๅŒ…ๅซ่จญๅฎš HTTPS๏ผ‰ใ€‚ๅฎƒๅฏ่ƒฝๆœ‰ไธ€ไบ›้™ๅˆถๆˆ–่ฆ้กๅค–ไป˜่ฒป็ญ‰ใ€‚ไฝ†ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฐฑไธๅฟ…่‡ชๅทฑ่จญๅฎš TLS Termination Proxyใ€‚ + +ๆˆ‘ๆœƒๅœจๅพŒ็บŒ็ซ ็ฏ€ๅฑ•็คบไธ€ไบ›ๅ…ท้ซ”ไพ‹ๅญใ€‚ + +--- + +ๆŽฅไธ‹ไพ†่ฆ่€ƒๆ…ฎ็š„ๆฆ‚ๅฟต้ƒฝ่ˆ‡ๅฏฆ้š›ๅŸท่กŒไฝ ็š„ API ็š„็จ‹ๅผ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ๆœ‰้—œใ€‚ + +## ็จ‹ๅผ่ˆ‡่กŒ็จ‹ { #program-and-process } + +ๆˆ‘ๅ€‘ๆœƒๅธธๆๅˆฐๅŸท่กŒไธญ็š„ใ€Œ่กŒ็จ‹๏ผˆprocess๏ผ‰ใ€๏ผŒๅ› ๆญคๅ…ˆ้‡ๆธ…ๅฎƒ็š„ๆ„ๆ€๏ผŒไปฅๅŠ่ˆ‡ใ€Œ็จ‹ๅผ๏ผˆprogram๏ผ‰ใ€็š„ๅทฎ็•ฐๅพˆๆœ‰ๅนซๅŠฉใ€‚ + +### ไป€้บผๆ˜ฏ็จ‹ๅผ { #what-is-a-program } + +ใ€Œ็จ‹ๅผ๏ผˆprogram๏ผ‰ใ€ไธ€่ฉžๅธธ็”จไพ†ๆ่ฟฐ่จฑๅคšๆฑ่ฅฟ๏ผš + +- ไฝ ๅฏซ็š„ๅŽŸๅง‹็ขผ๏ผŒไนŸๅฐฑๆ˜ฏ Python ๆช”ๆกˆใ€‚ +- ๅฏ็”ฑไฝœๆฅญ็ณป็ตฑๅŸท่กŒ็š„ๆช”ๆกˆ๏ผŒไพ‹ๅฆ‚๏ผš`python`ใ€`python.exe` ๆˆ– `uvicorn`ใ€‚ +- ๅœจไฝœๆฅญ็ณป็ตฑไธŠๅŸท่กŒไธญ็š„็‰นๅฎš็จ‹ๅผ๏ผŒไฝฟ็”จ CPU ไธฆๅฐ‡่ณ‡ๆ–™ๅญ˜ๆ–ผ่จ˜ๆ†ถ้ซ”ใ€‚้€™ไนŸ็จฑ็‚บใ€Œ่กŒ็จ‹ใ€ใ€‚ + +### ไป€้บผๆ˜ฏ่กŒ็จ‹ { #what-is-a-process } + +ใ€Œ่กŒ็จ‹๏ผˆprocess๏ผ‰ใ€้€šๅธธไปฅๆ›ด็‰นๅฎš็š„ๆ–นๅผไฝฟ็”จ๏ผŒๅชๆŒ‡ไฝœๆฅญ็ณป็ตฑไธญๆญฃๅœจๅŸท่กŒ็š„ๆฑ่ฅฟ๏ผˆๅฆ‚ไธŠ้ขๆœ€ๅพŒไธ€้ปž๏ผ‰๏ผš + +- ๅœจไฝœๆฅญ็ณป็ตฑไธŠใ€ŒๅŸท่กŒไธญใ€็š„็‰นๅฎš็จ‹ๅผใ€‚ + - ้€™ไธๆ˜ฏๆŒ‡ๆช”ๆกˆๆˆ–ๅŽŸๅง‹็ขผ๏ผŒ่€Œๆ˜ฏ็‰นๆŒ‡ๆญฃๅœจ่ขซไฝœๆฅญ็ณป็ตฑๅŸท่กŒไธฆ็ฎก็†็š„้‚ฃๅ€‹ๆฑ่ฅฟใ€‚ +- ไปปไฝ•็จ‹ๅผใ€ไปปไฝ•็จ‹ๅผ็ขผ๏ผŒๅชๆœ‰ๅœจใ€Œ่ขซๅŸท่กŒใ€ๆ™‚ๆ‰่ƒฝๅšไบ‹ใ€‚ๆ‰€ไปฅ๏ผŒ็•ถๆœ‰ใ€Œ่กŒ็จ‹ๅœจๅŸท่กŒใ€ๆ™‚ๆ‰่ƒฝ้‹ไฝœใ€‚ +- ่กŒ็จ‹ๅฏไปฅ่ขซไฝ ๆˆ–ไฝœๆฅญ็ณป็ตฑ็ต‚ๆญข๏ผˆkill๏ผ‰ใ€‚ๆญคๆ™‚ๅฎƒๅฐฑๅœๆญขๅŸท่กŒ๏ผŒ็„กๆณ•ๅ†ๅšไปปไฝ•ไบ‹ใ€‚ +- ไฝ ้›ป่…ฆไธŠๅŸท่กŒ็š„ๆฏๅ€‹ๆ‡‰็”จ็จ‹ๅผใ€ๆฏๅ€‹่ฆ–็ช—็ญ‰๏ผŒ่ƒŒๅพŒ้ƒฝๆœ‰ไธ€ไบ›่กŒ็จ‹ใ€‚่€Œไธ”ๅœจ้›ป่…ฆ้–‹ๆฉŸๆ™‚๏ผŒ้€šๅธธๆœƒๅŒๆ™‚ๆœ‰่จฑๅคš่กŒ็จ‹ๅœจ่ท‘ใ€‚ +- ๅŒไธ€ๅ€‹็จ‹ๅผๅฏไปฅๅŒๆ™‚ๆœ‰ๅคšๅ€‹่กŒ็จ‹ๅœจๅŸท่กŒใ€‚ + +ๅฆ‚ๆžœไฝ ๆ‰“้–‹ไฝœๆฅญ็ณป็ตฑ็š„ใ€Œๅทฅไฝœ็ฎก็†ๅ“กใ€ๆˆ–ใ€Œ็ณป็ตฑ็›ฃๆŽงๅ™จใ€๏ผˆๆˆ–้กžไผผๅทฅๅ…ท๏ผ‰๏ผŒๅฐฑ่ƒฝ็œ‹ๅˆฐ่จฑๅคšๆญฃๅœจๅŸท่กŒ็š„่กŒ็จ‹ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅคงๆฆ‚ๆœƒ็œ‹ๅˆฐๅŒไธ€ๅ€‹็€่ฆฝๅ™จ๏ผˆFirefoxใ€Chromeใ€Edge ็ญ‰๏ผ‰ๆœƒๆœ‰ๅคšๅ€‹่กŒ็จ‹ๅœจๅŸท่กŒใ€‚ๅฎƒๅ€‘้€šๅธธๆฏๅ€‹ๅˆ†้ ไธ€ๅ€‹่กŒ็จ‹๏ผŒๅค–ๅŠ ๅ…ถไป–ไธ€ไบ›้กๅค–่กŒ็จ‹ใ€‚ + + + +--- + +็พๅœจๆˆ‘ๅ€‘็Ÿฅ้“ใ€Œ่กŒ็จ‹ใ€่ˆ‡ใ€Œ็จ‹ๅผใ€็š„ๅทฎ็•ฐไบ†๏ผŒ็นผ็บŒ่ซ‡้ƒจ็ฝฒใ€‚ + +## ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ { #running-on-startup } + +ๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒ็•ถไฝ ๅปบ็ซ‹ไธ€ๅ€‹ Web API๏ผŒไฝ ๆœƒๅธŒๆœ›ๅฎƒใ€Œไธ€็›ดๅœจๅŸท่กŒใ€๏ผŒไธไธญๆ–ท๏ผŒ่ฎ“ๅฎขๆˆถ็ซฏ้šจๆ™‚ๅฏ็”จใ€‚้™ค้žไฝ ๆœ‰็‰นๅฎš็†็”ฑๅชๅœจๆŸไบ›ๆƒ…ๆณไธ‹ๆ‰ๅŸท่กŒ๏ผŒไฝ†ๅคง้ƒจๅˆ†ๆ™‚ๅ€™ไฝ ๆœƒๅธŒๆœ›ๅฎƒๆŒ็บŒ้‹ไฝœไธฆไธ”ๅฏ็”จใ€‚ + +### ๅœจ้ ็ซฏไผบๆœๅ™จไธŠ { #in-a-remote-server } + +็•ถไฝ ่จญๅฎšไธ€ๅฐ้ ็ซฏไผบๆœๅ™จ๏ผˆ้›ฒ็ซฏไผบๆœๅ™จใ€่™›ๆ“ฌๆฉŸ็ญ‰๏ผ‰๏ผŒๆœ€็ฐกๅ–ฎ็š„ไฝœๆณ•ๅฐฑๆ˜ฏๅƒๆœฌๆฉŸ้–‹็™ผๆ™‚ไธ€ๆจฃ๏ผŒๆ‰‹ๅ‹•ไฝฟ็”จ `fastapi run`๏ผˆๅฎƒไฝฟ็”จ Uvicorn๏ผ‰ๆˆ–้กžไผผ็š„ๆ–นๅผใ€‚ + +้€™ๅœจใ€Œ้–‹็™ผๆœŸ้–“ใ€ๆœƒ้‹ไฝœ่‰ฏๅฅฝ่€Œไธ”ๆœ‰็”จใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ่ˆ‡ไผบๆœๅ™จ็š„้€ฃ็ทšไธญๆ–ท๏ผŒๆญฃๅœจๅŸท่กŒ็š„่กŒ็จ‹ๅพˆๅฏ่ƒฝๆœƒๆญปๆމใ€‚ + +่€Œๅฆ‚ๆžœไผบๆœๅ™จ่ขซ้‡ๆ–ฐๅ•Ÿๅ‹•๏ผˆไพ‹ๅฆ‚ๆ›ดๆ–ฐๅพŒใ€ๆˆ–้›ฒ็ซฏไพ›ๆ‡‰ๅ•†้€ฒ่กŒ้ท็งป๏ผ‰๏ผŒไฝ ๅคงๆฆ‚ใ€Œไธๆœƒๆณจๆ„ๅˆฐใ€ใ€‚ๅ› ๆญคไฝ ็”š่‡ณไธ็Ÿฅ้“่ฆๆ‰‹ๅ‹•้‡ๅ•Ÿ่กŒ็จ‹ใ€‚ไฝ ็š„ API ๅฐฑๆœƒไธ€็›ดๆŽ›่‘—ใ€‚๐Ÿ˜ฑ + +### ้–‹ๆฉŸ่‡ชๅ‹•ๅ•Ÿๅ‹• { #run-automatically-on-startup } + +้€šๅธธไฝ ๆœƒๅธŒๆœ›ไผบๆœๅ™จ็จ‹ๅผ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ๅœจไผบๆœๅ™จ้–‹ๆฉŸๆ™‚่‡ชๅ‹•ๅ•Ÿๅ‹•๏ผŒไธ”ไธ้œ€ไปปไฝ•ใ€Œไบบๅทฅไป‹ๅ…ฅใ€๏ผŒ่ฎ“ไฝ ็š„ API๏ผˆไพ‹ๅฆ‚ Uvicorn ๅŸท่กŒไฝ ็š„ FastAPI ๆ‡‰็”จ๏ผ‰็ธฝๆ˜ฏๆœ‰่กŒ็จ‹ๅœจ่ท‘ใ€‚ + +### ็จ็ซ‹็จ‹ๅผ { #separate-program } + +็‚บไบ†้”ๆˆ้€™้ปž๏ผŒไฝ ้€šๅธธๆœƒๆœ‰ไธ€ๅ€‹ใ€Œ็จ็ซ‹็š„็จ‹ๅผใ€ไพ†็ขบไฟไฝ ็š„ๆ‡‰็”จๅœจ้–‹ๆฉŸๆ™‚ๆœƒ่ขซๅ•Ÿๅ‹•ใ€‚ๅพˆๅคšๆƒ…ๆณไธ‹๏ผŒๅฎƒไนŸๆœƒ็ขบไฟๅ…ถไป–ๅ…ƒไปถๆˆ–ๆ‡‰็”จไธ€ไฝตๅ•Ÿๅ‹•๏ผŒไพ‹ๅฆ‚่ณ‡ๆ–™ๅบซใ€‚ + +### ้–‹ๆฉŸ่‡ชๅ‹•ๅ•Ÿๅ‹•็š„ๅทฅๅ…ท็ฏ„ไพ‹ { #example-tools-to-run-at-startup } + +่ƒฝๅšๅˆฐ้€™ไปถไบ‹็š„ๅทฅๅ…ทๅŒ…ๆ‹ฌ๏ผš + +- Docker +- Kubernetes +- Docker Compose +- Docker ็š„ Swarm ๆจกๅผ +- Systemd +- Supervisor +- ็”ฑ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ๅœจๅ…ถๆœๅ‹™ๅ…ง้ƒจ่™•็† +- ๅ…ถไป–... + +ๆˆ‘ๆœƒๅœจๅพŒ็บŒ็ซ ็ฏ€็ตฆๅ‡บๆ›ดๅ…ท้ซ”็š„ไพ‹ๅญใ€‚ + +## ้‡ๆ–ฐๅ•Ÿๅ‹• { #restarts } + +ๅ’Œ็ขบไฟไฝ ็š„ๆ‡‰็”จๅœจ้–‹ๆฉŸๆ™‚ๆœƒๅŸท่กŒไธ€ๆจฃ๏ผŒไฝ ๅคงๆฆ‚ไนŸๆœƒๅธŒๆœ›ๅœจ็™ผ็”Ÿๅคฑๆ•—ไน‹ๅพŒ๏ผŒๅฎƒ่ƒฝใ€Œ่‡ชๅ‹•้‡ๆ–ฐๅ•Ÿๅ‹•ใ€ใ€‚ + +### ไบบ้ƒฝๆœƒ็Šฏ้Œฏ { #we-make-mistakes } + +ๆˆ‘ๅ€‘่บซ็‚บไบบ๏ผŒๅธธๅธธๆœƒ็Šฏ้Œฏใ€‚่ปŸ้ซ”ๅนพไนŽ็ธฝๆ˜ฏๆœ‰่—ๅœจๅ„่™•็š„ใ€Œ่‡ญ่Ÿฒ๏ผˆbugs๏ผ‰ใ€๐Ÿ› + +่€Œๆˆ‘ๅ€‘้–‹็™ผ่€…ๆœƒๅœจ็™ผ็พ้€™ไบ› bug ๅพŒๆŒ็บŒๆ”น้€ฒ็จ‹ๅผ็ขผใ€ๅฏฆไฝœๆ–ฐๅŠŸ่ƒฝ๏ผˆไนŸๅฏ่ƒฝ้ †ไพฟๅŠ ้€ฒๆ–ฐ็š„ bug ๐Ÿ˜…๏ผ‰ใ€‚ + +### ๅฐ้Œฏ่ชค่‡ชๅ‹•่™•็† { #small-errors-automatically-handled } + +ไฝฟ็”จ FastAPI ๅปบๆง‹ Web API ๆ™‚๏ผŒๅฆ‚ๆžœๆˆ‘ๅ€‘็š„็จ‹ๅผ็ขผๅ‡บ้Œฏ๏ผŒFastAPI ้€šๅธธๆœƒๆŠŠๅฎƒ้™ๅˆถๅœจ่งธ็™ผ่ฉฒ้Œฏ่ชค็š„ๅ–ฎๆฌก่ซ‹ๆฑ‚ไน‹ไธญใ€‚๐Ÿ›ก + +็”จๆˆถ็ซฏๆœƒๆ”ถๅˆฐใ€Œ500 Internal Server Errorใ€๏ผŒไฝ†ๆ‡‰็”จๆœƒ็นผ็บŒ่™•็†ไน‹ๅพŒ็š„่ซ‹ๆฑ‚๏ผŒ่€Œไธๆ˜ฏๆ•ดๅ€‹ๅดฉๆฝฐใ€‚ + +### ๆ›ดๅšด้‡็š„้Œฏ่ชค - ็•ถๆฉŸ { #bigger-errors-crashes } + +็„ถ่€Œ๏ผŒไปๅฏ่ƒฝๆœ‰ไธ€ไบ›ๆƒ…ๆณ๏ผŒๆˆ‘ๅ€‘ๅฏซ็š„็จ‹ๅผ็ขผใ€Œ่ฎ“ๆ•ดๅ€‹ๆ‡‰็”จ็•ถๆฉŸใ€๏ผŒไฝฟ Uvicorn ่ˆ‡ Python ้ƒฝๅดฉๆฝฐใ€‚๐Ÿ’ฅ + +ๅณไพฟๅฆ‚ๆญค๏ผŒไฝ ๅคงๆฆ‚ไนŸไธๆœƒๅธŒๆœ›ๆ‡‰็”จๅ› ็‚บๆŸ่™•้Œฏ่ชคๅฐฑไธ€็›ด่™•ๆ–ผๆญปไบก็‹€ๆ…‹๏ผŒไฝ ๅฏ่ƒฝๆœƒๅธŒๆœ›ๅฎƒใ€Œ็นผ็บŒ้‹ไฝœใ€๏ผŒ่‡ณๅฐ‘่ฎ“ๆฒ’ๆœ‰ๅฃžๆމ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operations๏ผ‰ใ€่ƒฝๆŒ็บŒๆœๅ‹™ใ€‚ + +### ็•ถๆฉŸๅพŒ้‡ๆ–ฐๅ•Ÿๅ‹• { #restart-after-crash } + +ๅœจ้€™ไบ›ๆœƒ่ฎ“ใ€ŒๅŸท่กŒไธญ่กŒ็จ‹ใ€ๆ•ดๅ€‹ๅดฉๆฝฐ็š„ๅšด้‡้Œฏ่ชคๆกˆไพ‹่ฃก๏ผŒไฝ ๆœƒๅธŒๆœ›ๆœ‰ๅ€‹ๅค–้ƒจๅ…ƒไปถ่ฒ ่ฒฌใ€Œ้‡ๆ–ฐๅ•Ÿๅ‹•ใ€่ฉฒ่กŒ็จ‹๏ผŒ่‡ณๅฐ‘ๅ˜—่ฉฆๅนพๆฌก... + +/// tip + +...ไธ้Ž๏ผŒๅฆ‚ๆžœๆ•ดๅ€‹ๆ‡‰็”จใ€Œไธ€ๅ•Ÿๅ‹•ๅฐฑ็ซ‹ๅˆปใ€ๅดฉๆฝฐ๏ผŒ้‚ฃๆŒ็บŒ็„กๆญขๅขƒๅœฐ้‡ๅ•Ÿๅคงๆฆ‚ๆฒ’ๆœ‰ๆ„็พฉใ€‚ไฝ†ๅœจ้€™้กžๆƒ…ๆณไธ‹๏ผŒไฝ ๅพˆๅฏ่ƒฝๆœƒๅœจ้–‹็™ผ้Ž็จ‹ไธญๅฐฑ็™ผ็พ๏ผŒๆˆ–่‡ณๅฐ‘ๅœจ้ƒจ็ฝฒๅพŒ้ฆฌไธŠๆณจๆ„ๅˆฐใ€‚ + +ๆ‰€ไปฅ่ฎ“ๆˆ‘ๅ€‘ๅฐˆๆณจๅœจไธป่ฆๆƒ…ๅขƒ๏ผšๆ‡‰็”จๅœจๆœชไพ†ๆŸไบ›็‰นๅฎšๆกˆไพ‹ไธญๅฏ่ƒฝๆœƒๆ•ด้ซ”ๅดฉๆฝฐ๏ผŒไฝ†ๆญคๆ™‚้‡ๆ–ฐๅ•Ÿๅ‹•ไป็„ถๆ˜ฏๆœ‰ๆ„็พฉ็š„ใ€‚ + +/// + +ไฝ ๅคงๆฆ‚ๆœƒๅธŒๆœ›ๆŠŠ่ฒ ่ฒฌ้‡ๆ–ฐๅ•Ÿๅ‹•ๆ‡‰็”จ็š„ๆฑ่ฅฟๆ”พๅœจใ€Œๅค–้ƒจๅ…ƒไปถใ€๏ผŒๅ› ็‚บ้‚ฃๅ€‹ๆ™‚ๅ€™๏ผŒๆ‡‰็”จๆœฌ่บซ้€ฃๅŒ Uvicorn ่ˆ‡ Python ้ƒฝๅทฒ็ถ“ๆŽ›ไบ†๏ผŒๅœจๅŒไธ€ๅ€‹ๆ‡‰็”จ็š„็จ‹ๅผ็ขผ่ฃกไนŸ็„กๆณ•ๅšไป€้บผใ€‚ + +### ่‡ชๅ‹•้‡ๆ–ฐๅ•Ÿๅ‹•็š„ๅทฅๅ…ท็ฏ„ไพ‹ { #example-tools-to-restart-automatically } + +ๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒ็”จไพ†ใ€Œๅœจ้–‹ๆฉŸๆ™‚ๅ•Ÿๅ‹•็จ‹ๅผใ€็š„ๅŒไธ€ๅฅ—ๅทฅๅ…ท๏ผŒไนŸๆœƒ่ฒ ่ฒฌ่™•็†่‡ชๅ‹•ใ€Œ้‡ๆ–ฐๅ•Ÿๅ‹•ใ€ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฏไปฅ็”ฑไธ‹ๅˆ—ๅทฅๅ…ท่™•็†๏ผš + +- Docker +- Kubernetes +- Docker Compose +- Docker ็š„ Swarm ๆจกๅผ +- Systemd +- Supervisor +- ็”ฑ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ๅœจๅ…ถๆœๅ‹™ๅ…ง้ƒจ่™•็† +- ๅ…ถไป–... + +## ่ค‡ๆœฌ๏ผš่กŒ็จ‹่ˆ‡่จ˜ๆ†ถ้ซ” { #replication-processes-and-memory } + +ๅœจ FastAPI ๆ‡‰็”จไธญ๏ผŒไฝฟ็”จๅƒ `fastapi` ๆŒ‡ไปค๏ผˆๅŸท่กŒ Uvicorn๏ผ‰็š„ไผบๆœๅ™จ็จ‹ๅผ๏ผŒๅณไฝฟๅชๅœจใ€Œไธ€ๅ€‹่กŒ็จ‹ใ€ไธญๅŸท่กŒ๏ผŒไนŸ่ƒฝๅŒๆ™‚ๆœๅ‹™ๅคšๅ€‹ๅฎขๆˆถ็ซฏใ€‚ + +ไฝ†ๅพˆๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒๆƒณๅŒๆ™‚ๅŸท่กŒๅคšๅ€‹ๅทฅไฝœ่กŒ็จ‹๏ผˆworkers๏ผ‰ใ€‚ + +### ๅคšๅ€‹่กŒ็จ‹ - Workers { #multiple-processes-workers } + +ๅฆ‚ๆžœไฝ ็š„ๅฎขๆˆถ็ซฏๆฏ”ๅ–ฎไธ€่กŒ็จ‹ๆ‰€่ƒฝ่™•็†็š„ๆ›ดๅคš๏ผˆไพ‹ๅฆ‚่™›ๆ“ฌๆฉŸ่ฆๆ ผไธๅคง๏ผ‰๏ผŒ่€Œไผบๆœๅ™จ CPU ๆœ‰ใ€Œๅคšๆ ธๅฟƒใ€๏ผŒ้‚ฃไฝ ๅฏไปฅๅŒๆ™‚ๅŸท่กŒใ€Œๅคšๅ€‹่กŒ็จ‹ใ€่ผ‰ๅ…ฅ็›ธๅŒ็š„ๆ‡‰็”จ๏ผŒไธฆๆŠŠๆ‰€ๆœ‰่ซ‹ๆฑ‚ๅˆ†ๆ•ฃ็ตฆๅฎƒๅ€‘ใ€‚ + +็•ถไฝ ๅŸท่กŒๅŒไธ€ๅ€‹ API ็จ‹ๅผ็š„ใ€Œๅคšๅ€‹่กŒ็จ‹ใ€ๆ™‚๏ผŒ้€šๅธธ็จฑ็‚บใ€Œworkers๏ผˆๅทฅไฝœ่กŒ็จ‹๏ผ‰ใ€ใ€‚ + +### ๅทฅไฝœ่กŒ็จ‹่ˆ‡้€ฃๆŽฅๅŸ  { #worker-processes-and-ports } + +้‚„่จ˜ๅพ—ๆ–‡ไปถไธญ[้—œๆ–ผ HTTPS](https.md){.internal-link target=_blank} ็š„่ชชๆ˜Žๅ—Ž๏ผšๅœจไธ€ๅฐไผบๆœๅ™จไธŠ๏ผŒไธ€็ต„ IP ่ˆ‡้€ฃๆŽฅๅŸ ็š„็ต„ๅˆๅช่ƒฝ็”ฑใ€Œไธ€ๅ€‹่กŒ็จ‹ใ€็›ฃ่ฝ๏ผŸ + +้€™่ฃกๅŒๆจฃ้ฉ็”จใ€‚ + +ๅ› ๆญค๏ผŒ่‹ฅ่ฆๅŒๆ™‚ๆ“ๆœ‰ใ€Œๅคšๅ€‹่กŒ็จ‹ใ€๏ผŒๅฐฑๅฟ…้ ˆๆœ‰ใ€Œๅ–ฎไธ€่กŒ็จ‹ใ€ๅœจ่ฉฒ้€ฃๆŽฅๅŸ ไธŠ็›ฃ่ฝ๏ผŒ็„ถๅพŒไปฅๆŸ็จฎๆ–นๅผๆŠŠ้€šไฟกๅ‚ณ้ž็ตฆๅ„ๅ€‹ๅทฅไฝœ่กŒ็จ‹ใ€‚ + +### ๆฏๅ€‹่กŒ็จ‹็š„่จ˜ๆ†ถ้ซ” { #memory-per-process } + +็•ถ็จ‹ๅผๆŠŠๆฑ่ฅฟ่ผ‰ๅ…ฅ่จ˜ๆ†ถ้ซ”ๆ™‚๏ผŒไพ‹ๅฆ‚ๆŠŠๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹ๅญ˜ๅˆฐ่ฎŠๆ•ธไธญ๏ผŒๆˆ–ๆŠŠๅคงๅž‹ๆช”ๆกˆๅ…งๅฎน่ฎ€ๅˆฐ่ฎŠๆ•ธไธญ๏ผŒ้€™ไบ›้ƒฝๆœƒใ€Œๆถˆ่€—ไธ€ไบ›ไผบๆœๅ™จ็š„่จ˜ๆ†ถ้ซ”๏ผˆRAM๏ผ‰ใ€ใ€‚ + +่€Œๅคšๅ€‹่กŒ็จ‹้€šๅธธใ€Œไธๅ…ฑไบซ่จ˜ๆ†ถ้ซ”ใ€ใ€‚้€™่กจ็คบๆฏๅ€‹ๅŸท่กŒไธญ็š„่กŒ็จ‹้ƒฝๆœ‰่‡ชๅทฑ็š„ๆฑ่ฅฟใ€่ฎŠๆ•ธ่ˆ‡่จ˜ๆ†ถ้ซ”ใ€‚ๅฆ‚ๆžœไฝ ็š„็จ‹ๅผ็ขผๆœƒ็”จๆމๅคง้‡่จ˜ๆ†ถ้ซ”๏ผŒใ€Œๆฏๅ€‹่กŒ็จ‹ใ€้ƒฝๆœƒๆถˆ่€—็ญ‰้‡็š„่จ˜ๆ†ถ้ซ”ใ€‚ + +### ไผบๆœๅ™จ่จ˜ๆ†ถ้ซ” { #server-memory } + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ็š„็จ‹ๅผ็ขผ่ผ‰ๅ…ฅไธ€ๅ€‹ใ€Œ1 GB ๅคงๅฐใ€็š„ๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹๏ผŒ็•ถไฝ ็”จไธ€ๅ€‹่กŒ็จ‹ๅŸท่กŒไฝ ็š„ API๏ผŒๅฎƒๅฐฑๆœƒ่‡ณๅฐ‘ๅƒๆމ 1 GB ็š„ RAMใ€‚่‹ฅไฝ ๅ•Ÿๅ‹•ใ€Œ4 ๅ€‹่กŒ็จ‹ใ€๏ผˆ4 ๅ€‹ workers๏ผ‰๏ผŒๆฏๅ€‹ๆœƒๅƒ 1 GB RAMใ€‚็ธฝ่จˆไฝ ็š„ API ๆœƒๅƒๆމใ€Œ4 GB RAMใ€ใ€‚ + +ๅฆ‚ๆžœไฝ ็š„้ ็ซฏไผบๆœๅ™จๆˆ–่™›ๆ“ฌๆฉŸๅชๆœ‰ 3 GB RAM๏ผŒๅ˜—่ฉฆ่ผ‰ๅ…ฅ่ถ…้Ž 4 GB ็š„ RAM ๅฐฑๆœƒๅ‡บๅ•้กŒใ€‚๐Ÿšจ + +### ๅคšๅ€‹่กŒ็จ‹ - ็ฏ„ไพ‹ { #multiple-processes-an-example } + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๆœ‰ไธ€ๅ€‹ใ€Œ็ฎก็†่กŒ็จ‹๏ผˆManager Process๏ผ‰ใ€ๆœƒๅ•Ÿๅ‹•ไธฆๆŽงๅˆถๅ…ฉๅ€‹ใ€Œๅทฅไฝœ่กŒ็จ‹๏ผˆWorker Processes๏ผ‰ใ€ใ€‚ + +้€™ๅ€‹็ฎก็†่กŒ็จ‹ๅคงๆฆ‚ๅฐฑๆ˜ฏๅœจ IP ็š„ใ€Œ้€ฃๆŽฅๅŸ ใ€ไธŠ็›ฃ่ฝ็š„้‚ฃๅ€‹ใ€‚ๅฎƒๆœƒๆŠŠๆ‰€ๆœ‰้€šไฟก่ฝ‰็™ผๅˆฐๅ„ๅ€‹ๅทฅไฝœ่กŒ็จ‹ใ€‚ + +้‚ฃไบ›ๅทฅไฝœ่กŒ็จ‹ๆ‰ๆ˜ฏๅฏฆ้š›ๅŸท่กŒไฝ ็š„ๆ‡‰็”จ็š„๏ผŒๅฎƒๅ€‘ๆœƒๅฎŒๆˆไธป่ฆ็š„่จˆ็ฎ—๏ผŒๆŽฅๆ”ถใ€Œ่ซ‹ๆฑ‚ใ€ไธฆๅ›žๅ‚ณใ€Œๅ›žๆ‡‰ใ€๏ผŒไนŸๆœƒๆŠŠไฝ ๆ”พๅœจ่ฎŠๆ•ธไธญ็š„ๆฑ่ฅฟ่ผ‰ๅ…ฅ RAMใ€‚ + + + +็•ถ็„ถ๏ผŒๅŒไธ€ๅฐๆฉŸๅ™จไธŠ้™คไบ†ไฝ ็š„ๆ‡‰็”จไน‹ๅค–๏ผŒ้€šๅธธไนŸๆœƒๆœ‰ใ€Œๅ…ถไป–่กŒ็จ‹ใ€ๅœจๅŸท่กŒใ€‚ + +ๆœ‰ๅ€‹ๆœ‰่ถฃ็š„็ดฐ็ฏ€ๆ˜ฏ๏ผŒๆฏๅ€‹่กŒ็จ‹็š„ใ€ŒCPU ไฝฟ็”จ็އใ€็™พๅˆ†ๆฏ”ๆœƒ้šจๆ™‚้–“ๅคงๅน…ใ€Œ่ฎŠๅ‹•ใ€๏ผŒไฝ†ใ€Œ่จ˜ๆ†ถ้ซ”๏ผˆRAM๏ผ‰ใ€้€šๅธธ็ถญๆŒ็›ธๅฐใ€Œ็ฉฉๅฎšใ€ใ€‚ + +ๅฆ‚ๆžœไฝ ็š„ API ๆฏๆฌกๅš็š„่จˆ็ฎ—้‡็›ธ่ฟ‘๏ผŒไธ”ๅฎขๆˆถๅพˆๅคš๏ผŒ้‚ฃใ€ŒCPU ไฝฟ็”จ็އใ€ไนŸๅฏ่ƒฝใ€Œ็›ธๅฐ็ฉฉๅฎšใ€๏ผˆ่€Œไธๆ˜ฏๅฟซ้€ŸไธŠไธ‹่ตทไผ๏ผ‰ใ€‚ + +### ่ค‡ๆœฌ่ˆ‡ๆ“ดๅฑ•็š„ๅทฅๅ…ท่ˆ‡็ญ–็•ฅ็ฏ„ไพ‹ { #examples-of-replication-tools-and-strategies } + +่ฆ้”ๆˆ้€™ไบ›ๆœ‰ๅพˆๅคš็จฎไฝœๆณ•ใ€‚ๆˆ‘ๆœƒๅœจๅพŒ็บŒ็ซ ็ฏ€๏ผˆไพ‹ๅฆ‚่ซ‡ๅˆฐ Docker ่ˆ‡ๅฎนๅ™จๆ™‚๏ผ‰ไป‹็ดนๆ›ดๅ…ท้ซ”็š„็ญ–็•ฅใ€‚ + +ไธป่ฆ็š„้™ๅˆถๆ˜ฏ๏ผšๅฟ…้ ˆๆœ‰ใ€Œๅ–ฎไธ€ใ€ๅ…ƒไปถ่ฒ ่ฒฌ่™•็†ใ€Œๅ…ฌ้–‹ IPใ€ไธŠ็š„ใ€Œ้€ฃๆŽฅๅŸ ใ€ใ€‚ๆŽฅ่‘—ๅฎƒๅฟ…้ ˆ่ƒฝๆŠŠ้€šไฟกใ€Œ่ฝ‰็™ผใ€ๅˆฐ่ขซ่ค‡่ฃฝ็š„ใ€Œ่กŒ็จ‹๏ผworkersใ€ใ€‚ + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅฏ่ƒฝ็š„็ต„ๅˆ่ˆ‡็ญ–็•ฅ๏ผš + +- Uvicorn ๆญ้… `--workers` + - ไธ€ๅ€‹ Uvicornใ€Œ็ฎก็†่กŒ็จ‹ใ€ๆœƒๅœจใ€ŒIPใ€่ˆ‡ใ€Œ้€ฃๆŽฅๅŸ ใ€ไธŠ็›ฃ่ฝ๏ผŒไธฆๅ•Ÿๅ‹•ใ€Œๅคšๅ€‹ Uvicorn ๅทฅไฝœ่กŒ็จ‹ใ€ใ€‚ +- Kubernetes ่ˆ‡ๅ…ถไป–ๅˆ†ๆ•ฃๅผใ€Œๅฎนๅ™จ็ณป็ตฑใ€ + - ็”ฑใ€ŒKubernetesใ€ๅฑคๅœจใ€ŒIPใ€่ˆ‡ใ€Œ้€ฃๆŽฅๅŸ ใ€ไธŠ็›ฃ่ฝใ€‚่ค‡ๆœฌ็š„ๆ–นๅผๆ˜ฏๆœ‰ใ€Œๅคšๅ€‹ๅฎนๅ™จใ€๏ผŒๆฏๅ€‹ๅฎนๅ™จๅ…งๅŸท่กŒใ€Œไธ€ๅ€‹ Uvicorn ่กŒ็จ‹ใ€ใ€‚ +- ็”ฑใ€Œ้›ฒ็ซฏๆœๅ‹™ใ€ๆ›ฟไฝ ่™•็† + - ้›ฒ็ซฏๆœๅ‹™ๅพˆๅฏ่ƒฝใ€Œๆ›ฟไฝ ่™•็†่ค‡ๆœฌใ€ใ€‚ๅฎƒๅฏ่ƒฝ่ฎ“ไฝ ๅฎš็พฉใ€Œ่ฆๅŸท่กŒ็š„่กŒ็จ‹ใ€ๆˆ–ใ€Œๅฎนๅ™จๆ˜ ๅƒใ€๏ผŒ็„ก่ซ–ๅฆ‚ไฝ•๏ผŒๅคšๅŠๆœƒๆ˜ฏใ€Œๅ–ฎไธ€ Uvicorn ่กŒ็จ‹ใ€๏ผŒ่€Œ็”ฑ้›ฒ็ซฏๆœๅ‹™่ฒ ่ฒฌ้€ฒ่กŒ่ค‡่ฃฝใ€‚ + +/// tip + +ๅ…ˆๅˆฅๆ“”ๅฟƒ้€™่ฃกๆๅˆฐ็š„ใ€Œๅฎนๅ™จใ€ใ€Docker ๆˆ– Kubernetes ๅฆ‚ๆžœ็พๅœจ้‚„ไธๅคชๆ‡‚ใ€‚ + +ๆˆ‘ๆœƒๅœจๆœชไพ†็š„็ซ ็ฏ€้€ฒไธ€ๆญฅ่ชชๆ˜Žๅฎนๅ™จๆ˜ ๅƒใ€Dockerใ€Kubernetes ็ญ‰็ญ‰๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ + +/// + +## ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ { #previous-steps-before-starting } + +ๅพˆๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒๅธŒๆœ›ๅœจๆ‡‰็”จใ€Œๅ•Ÿๅ‹•ไน‹ๅ‰ใ€ๅ…ˆๅŸท่กŒไธ€ไบ›ๆญฅ้ฉŸใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๆƒณๅ…ˆๅŸท่กŒใ€Œ่ณ‡ๆ–™ๅบซ้ท็งปใ€ใ€‚ + +ไฝ†ๅœจๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒๅธŒๆœ›้€™ไบ›ๆญฅ้ฉŸๅชๅŸท่กŒใ€Œไธ€ๆฌกใ€ใ€‚ + +ๆ‰€ไปฅ๏ผŒไฝ ๆœƒๅธŒๆœ›็”จใ€Œๅ–ฎไธ€่กŒ็จ‹ใ€ไพ†ๅŸท่กŒ้‚ฃไบ›ใ€Œๅ‰็ฝฎๆญฅ้ฉŸใ€๏ผŒๅœจๅ•Ÿๅ‹•ๆ‡‰็”จไน‹ๅ‰ๅฎŒๆˆใ€‚ + +่€Œไธ”ๅณไฝฟไน‹ๅพŒไฝ ่ฆ็‚บๆ‡‰็”จๆœฌ่บซๅ•Ÿๅ‹•ใ€Œๅคšๅ€‹่กŒ็จ‹ใ€๏ผˆๅคšๅ€‹ workers๏ผ‰๏ผŒไฝ ไนŸๅฟ…้ ˆ็ขบไฟๅชๆœ‰ไธ€ๅ€‹่กŒ็จ‹ๅœจ่ท‘้‚ฃไบ›ๅ‰็ฝฎๆญฅ้ฉŸใ€‚่‹ฅ็”ฑใ€Œๅคšๅ€‹่กŒ็จ‹ใ€ๅŽป่ท‘๏ผŒๆœƒๅœจใ€Œๅนณ่กŒใ€ไธญ้‡่ค‡ๅŒๆจฃ็š„ๅทฅไฝœ๏ผ›่€Œๅฆ‚ๆžœ้‚ฃไบ›ๆญฅ้ฉŸๅƒๆ˜ฏ่ณ‡ๆ–™ๅบซ้ท็งป้€™้กžๆ•ๆ„Ÿๆ“ไฝœ๏ผŒๅฎƒๅ€‘ไน‹้–“ๅฏ่ƒฝๆœƒไบ’็›ธ่ก็ชใ€‚ + +็•ถ็„ถ๏ผŒไนŸๆœ‰ไธ€ไบ›ๆƒ…ๆณ๏ผŒ้‡่ค‡ๅŸท่กŒๅ‰็ฝฎๆญฅ้ฉŸไธๆœƒๆœ‰ๅ•้กŒ๏ผ›ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹ๅฐฑๅฎนๆ˜“่™•็†ๅพ—ๅคšใ€‚ + +/// tip + +ๅฆๅค–่ซ‹่จ˜ไฝ๏ผŒไพ็…งไฝ ็š„่จญๅฎš๏ผŒๅœจๆŸไบ›ๆƒ…ๆณไธ‹ไฝ ใ€Œ็”š่‡ณๅฏ่ƒฝไธ้œ€่ฆไปปไฝ•ๅ‰็ฝฎๆญฅ้ฉŸใ€ๆ‰่ƒฝๅ•Ÿๅ‹•ๆ‡‰็”จใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฐฑไธ็”จ็‚บๆญค่ฒปๅฟƒไบ†ใ€‚๐Ÿคท + +/// + +### ๅ‰็ฝฎๆญฅ้ฉŸ็ญ–็•ฅ็ฏ„ไพ‹ { #examples-of-previous-steps-strategies } + +้€™ๆœƒใ€Œ้ซ˜ๅบฆๅ–ๆฑบๆ–ผใ€ไฝ ใ€Œ้ƒจ็ฝฒ็ณป็ตฑใ€็š„ๆ–นๅผ๏ผŒ่€Œไธ”ๅพˆๅฏ่ƒฝ่ˆ‡ไฝ ๅฆ‚ไฝ•ๅ•Ÿๅ‹•็จ‹ๅผใ€่™•็†้‡ๆ–ฐๅ•Ÿๅ‹•็ญ‰ๆœ‰้—œใ€‚ + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅฏ่ƒฝ็š„ๅšๆณ•๏ผš + +- ๅœจ Kubernetes ไธญไฝฟ็”จไธ€ๅ€‹ใ€ŒInit Containerใ€๏ผŒๅฎƒๆœƒๅœจไฝ ็š„ๆ‡‰็”จๅฎนๅ™จไน‹ๅ‰ๅ…ˆๅŸท่กŒ +- ไธ€ๅ€‹ bash ่…ณๆœฌๅ…ˆ่ท‘ๅ‰็ฝฎๆญฅ้ฉŸ๏ผŒ็„ถๅพŒๅ†ๅ•Ÿๅ‹•ไฝ ็š„ๆ‡‰็”จ + - ไฝ ไป็„ถ้œ€่ฆๆœ‰ๆฉŸๅˆถไพ†ๅ•Ÿๅ‹•๏ผ้‡ๆ–ฐๅ•Ÿๅ‹•ใ€Œ้‚ฃๅ€‹ใ€bash ่…ณๆœฌใ€ๅตๆธฌ้Œฏ่ชค็ญ‰ + +/// tip + +ๆˆ‘ๆœƒๅœจๆœชไพ†้—œๆ–ผๅฎนๅ™จ็š„็ซ ็ฏ€ๆไพ›ๆ›ดๅ…ท้ซ”็š„็ฏ„ไพ‹๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ + +/// + +## ่ณ‡ๆบไฝฟ็”จ็އ { #resource-utilization } + +ไฝ ็š„ไผบๆœๅ™จ๏ผˆ็พค๏ผ‰ๆ˜ฏๅฏไปฅ่ขซใ€Œๆถˆ่€—๏ผๅˆฉ็”จใ€็š„ใ€Œ่ณ‡ๆบใ€๏ผŒไฝ ็š„็จ‹ๅผๆœƒไฝฟ็”จ CPU ็š„่จˆ็ฎ—ๆ™‚้–“๏ผŒไปฅๅŠๅฏ็”จ็š„ RAM ่จ˜ๆ†ถ้ซ”ใ€‚ + +ไฝ ๆƒณ่ฆๆถˆ่€—๏ผๅˆฉ็”จๅคšๅฐ‘็ณป็ตฑ่ณ‡ๆบ๏ผŸ็›ด่ฆบไธŠๅฏ่ƒฝๆœƒๆƒณใ€Œไธ่ฆๅคชๅคšใ€๏ผŒไฝ†ๅฏฆ้š›ไธŠ๏ผŒไฝ ๅคงๆฆ‚ๆœƒๅธŒๆœ›ๅœจใ€Œไธ็•ถๆฉŸใ€็š„ๅ‰ๆไธ‹ใ€Œ็›กๅฏ่ƒฝ็”จๅคšไธ€้ปžใ€ใ€‚ + +ๅฆ‚ๆžœไฝ ่Šฑ้Œข็งŸไบ† 3 ๅฐไผบๆœๅ™จ๏ผŒๅปๅช็”จไบ†ๅฎƒๅ€‘ๅฐ‘้‡็š„ RAM ่ˆ‡ CPU๏ผŒ้‚ฃไฝ ๅฏ่ƒฝๆ˜ฏๅœจใ€Œๆตช่ฒป้‡‘้Œขใ€๐Ÿ’ธใ€ไนŸใ€Œๆตช่ฒปไผบๆœๅ™จ้›ปๅŠ›ใ€๐ŸŒŽ ็ญ‰ใ€‚ + +ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹๏ผŒๅฏ่ƒฝๆ›ดๅฅฝ็š„ๆ˜ฏๅช็”จ 2 ๅฐไผบๆœๅ™จ๏ผŒไธฆไปฅๆ›ด้ซ˜็š„ๆฏ”ไพ‹ไฝฟ็”จๅฎƒๅ€‘็š„่ณ‡ๆบ๏ผˆCPUใ€่จ˜ๆ†ถ้ซ”ใ€็ฃ็ขŸใ€็ถฒ่ทฏ้ ปๅฏฌ็ญ‰๏ผ‰ใ€‚ + +ๅฆไธ€ๆ–น้ข๏ผŒๅฆ‚ๆžœไฝ ๆœ‰ 2 ๅฐไผบๆœๅ™จ๏ผŒไธ”ไฝ ไฝฟ็”จไบ†ๅฎƒๅ€‘ใ€Œ100% ็š„ CPU ่ˆ‡ RAMใ€๏ผŒๆŸๅ€‹ๆ™‚ๅˆปไธ€ๅ€‹่กŒ็จ‹ๆœƒ่ฆๆฑ‚ๆ›ดๅคš่จ˜ๆ†ถ้ซ”๏ผŒไผบๆœๅ™จๅฐฑๅพ—็”จ็ฃ็ขŸ็•ถไฝœใ€Œ่จ˜ๆ†ถ้ซ”ใ€๏ผˆ้€™ๅฏ่ƒฝๆ…ขไธŠๆ•ธๅƒๅ€๏ผ‰๏ผŒ็”š่‡ณใ€Œ็•ถๆฉŸใ€ใ€‚ๆˆ–ๆ˜ฏๆŸๅ€‹่กŒ็จ‹้œ€่ฆๅš่จˆ็ฎ—ๆ™‚๏ผŒๅฟ…้ ˆ็ญ‰ๅˆฐ CPU ๅ†ๅบฆ็ฉบ้–’ใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒๆœ€ๅฅฝๆ˜ฏๅ†ๅŠ ไธ€ๅฐไผบๆœๅ™จ๏ผŒไธฆๅœจไธŠ้ข่ท‘้ƒจๅˆ†่กŒ็จ‹๏ผŒ่ฎ“ๆ‰€ๆœ‰่กŒ็จ‹้ƒฝๆœ‰ใ€Œ่ถณๅค ็š„ RAM ่ˆ‡ CPU ๆ™‚้–“ใ€ใ€‚ + +ไนŸๆœ‰ๆฉŸๆœƒๅ› ็‚บๆŸไบ›ๅŽŸๅ› ๏ผŒไฝ ็š„ API ไฝฟ็”จ้‡ๅ‡บ็พใ€Œๅฐ–ๅณฐใ€ใ€‚ไนŸ่จฑๅฎƒ็ˆ†็ด…ไบ†๏ผŒๆˆ–ๆ˜ฏๅ…ถไป–ๆœๅ‹™ๆˆ–ๆฉŸๅ™จไบบ้–‹ๅง‹ไฝฟ็”จๅฎƒใ€‚ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝๆœƒๅธŒๆœ›็•™ๆœ‰ไธ€ไบ›้กๅค–่ณ‡ๆบไปฅ็ญ–ๅฎ‰ๅ…จใ€‚ + +ไฝ ๅฏไปฅ่จญๅฎšไธ€ๅ€‹ใ€Œ็›ฎๆจ™ๆ•ธๅญ—ใ€๏ผŒไพ‹ๅฆ‚่ณ‡ๆบไฝฟ็”จ็އ่ฝๅœจใ€Œ50% ๅˆฐ 90%ใ€ไน‹้–“ใ€‚้‡้ปžๆ˜ฏ๏ผŒ้€™ไบ›ๅคงๆฆ‚ๅฐฑๆ˜ฏไฝ ๆœƒๆƒณๆธฌ้‡ไธฆ็”จไพ†่ชฟๆ ก้ƒจ็ฝฒ็š„ไธป่ฆๆŒ‡ๆจ™ใ€‚ + +ไฝ ๅฏไปฅ็”จๅƒ `htop` ้€™ๆจฃ็š„็ฐกๅ–ฎๅทฅๅ…ท๏ผŒๆŸฅ็œ‹ไผบๆœๅ™จ็š„ CPU ่ˆ‡ RAM ไฝฟ็”จ้‡๏ผŒๆˆ–ๅ„่กŒ็จ‹็š„ไฝฟ็”จ้‡ใ€‚ไนŸๅฏไปฅ็”จๆ›ด่ค‡้›œ็š„็›ฃๆŽงๅทฅๅ…ท๏ผŒๅˆ†ๆ•ฃๅผๅœฐ็›ฃ็œ‹ๅคšๅฐไผบๆœๅ™จ๏ผŒ็ญ‰็ญ‰ใ€‚ + +## ้‡้ปžๅ›ž้กง { #recap } + +้€™่ฃกไป‹็ดนไบ†ไธ€ไบ›ไฝ ๅœจๆฑบๅฎšๅฆ‚ไฝ•้ƒจ็ฝฒๆ‡‰็”จๆ™‚ๆ‡‰่ฉฒ่จ˜ไฝ็š„ไธป่ฆๆฆ‚ๅฟต๏ผš + +- ๅฎ‰ๅ…จๆ€ง - HTTPS +- ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ +- ้‡ๆ–ฐๅ•Ÿๅ‹• +- ่ค‡ๆœฌ๏ผˆๅŸท่กŒไธญ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +- ่จ˜ๆ†ถ้ซ” +- ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +็†่งฃ้€™ไบ›ๆƒณๆณ•่ˆ‡ๅฆ‚ไฝ•ๅฅ—็”จๅฎƒๅ€‘๏ผŒๆ‡‰่ƒฝ็ตฆไฝ ่ถณๅค ็š„็›ด่ฆบ๏ผŒๅœจ่จญๅฎš่ˆ‡่ชฟๆ•ด้ƒจ็ฝฒๆ™‚ๅšๅ‡บๅ„็จฎๆฑบ็ญ–ใ€‚๐Ÿค“ + +ๅœจๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€๏ผŒๆˆ‘ๆœƒๆไพ›ๆ›ดๅคšๅฏ่กŒ็ญ–็•ฅ็š„ๅ…ท้ซ”็ฏ„ไพ‹ใ€‚๐Ÿš€ diff --git a/docs/zh-hant/docs/deployment/docker.md b/docs/zh-hant/docs/deployment/docker.md new file mode 100644 index 0000000000..87f4e6f9f0 --- /dev/null +++ b/docs/zh-hant/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# ๅœจๅฎนๅ™จไธญไฝฟ็”จ FastAPI - Docker { #fastapi-in-containers-docker } + +้ƒจ็ฝฒ FastAPI ๆ‡‰็”จๆ™‚๏ผŒไธ€ๅ€‹ๅธธ่ฆ‹ๅšๆณ•ๆ˜ฏๅปบ็ฝฎไธ€ๅ€‹ใ€ŒLinux ๅฎนๅ™จๆ˜ ๅƒ๏ผˆcontainer image๏ผ‰ใ€ใ€‚้€šๅธธไฝฟ็”จ Docker ไพ†ๅฎŒๆˆใ€‚ไน‹ๅพŒไฝ ๅฏไปฅ็”จๅคš็จฎๆ–นๅผ้ƒจ็ฝฒ่ฉฒๅฎนๅ™จๆ˜ ๅƒใ€‚ + +ไฝฟ็”จ Linux ๅฎนๅ™จๆœ‰ๅคš็จฎๅ„ช้ปž๏ผŒๅŒ…ๆ‹ฌๅฎ‰ๅ…จๆ€งใ€ๅฏ้‡็พๆ€งใ€็ฐกๅ–ฎๆ€ง็ญ‰ใ€‚ + +/// tip | ๆ็คบ + +่ถ•ๆ™‚้–“่€Œไธ”ๅทฒ็ถ“ๆ‡‚้€™ไบ›๏ผŸ็›ดๆŽฅ่ทณๅˆฐไธ‹้ข็š„ [`Dockerfile` ๐Ÿ‘‡](#build-a-docker-image-for-fastapi)ใ€‚ + +/// + +
+Dockerfile ้ ่ฆฝ ๐Ÿ‘€ + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# ่‹ฅๅœจ Nginx ๆˆ– Traefik ็ญ‰ไปฃ็†ไผบๆœๅ™จๅพŒๆ–นๅŸท่กŒ๏ผŒ่ซ‹ๅŠ ๅ…ฅ --proxy-headers +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## ไป€้บผๆ˜ฏๅฎนๅ™จ { #what-is-a-container } + +ๅฎนๅ™จ๏ผˆไธป่ฆๆ˜ฏ Linux ๅฎนๅ™จ๏ผ‰ๆ˜ฏไธ€็จฎ้žๅธธ่ผ•้‡็š„ๆ–นๅผ๏ผŒ็”จไพ†ๅฐ่ฃๆ‡‰็”จๅŠๅ…ถๆ‰€ๆœ‰็›ธไพ่ˆ‡ๅฟ…่ฆๆช”ๆกˆ๏ผŒไธฆ่ฎ“ๅ…ถ่ˆ‡ๅŒไธ€็ณป็ตฑไธญ็š„ๅ…ถไป–ๅฎนๅ™จ๏ผˆๅ…ถไป–ๆ‡‰็”จๆˆ–ๅ…ƒไปถ๏ผ‰้š”้›ขใ€‚ + +Linux ๅฎนๅ™จไฝฟ็”จ่ˆ‡ไธปๆฉŸ๏ผˆๆฉŸๅ™จใ€่™›ๆ“ฌๆฉŸใ€้›ฒ็ซฏไผบๆœๅ™จ็ญ‰๏ผ‰็›ธๅŒ็š„ Linux kernelใ€‚้€™ๆ„ๅ‘ณ่‘—ๅฎƒๅ€‘้žๅธธ่ผ•้‡๏ผˆ็›ธ่ผƒๆ–ผๅฎŒๆ•ดๆจกๆ“ฌๆ•ดๅ€‹ไฝœๆฅญ็ณป็ตฑ็š„่™›ๆ“ฌๆฉŸ๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒๅฎนๅ™จๅชๆถˆ่€—ๅพˆๅฐ‘็š„่ณ‡ๆบ๏ผŒ่ˆ‡็›ดๆŽฅๅŸท่กŒ่กŒ็จ‹็›ธ็•ถ๏ผˆ่€Œ่™›ๆ“ฌๆฉŸๆœƒๆถˆ่€—ๆ›ดๅคš๏ผ‰ใ€‚ + +ๅฎนๅ™จไนŸๆœ‰ๅ…ถๅ„่‡ช้š”้›ข็š„ๅŸท่กŒ่กŒ็จ‹๏ผˆ้€šๅธธๅชๆœ‰ไธ€ๅ€‹่กŒ็จ‹๏ผ‰ใ€ๆช”ๆกˆ็ณป็ตฑ่ˆ‡็ถฒ่ทฏ๏ผŒ็ฐกๅŒ–้ƒจ็ฝฒใ€ๅฎ‰ๅ…จๆ€ง่ˆ‡้–‹็™ผ็ญ‰ใ€‚ + +## ไป€้บผๆ˜ฏๅฎนๅ™จๆ˜ ๅƒ { #what-is-a-container-image } + +ๅฎนๅ™จๆ˜ฏ็”ฑๅฎนๅ™จๆ˜ ๅƒๅ•Ÿๅ‹•ๅŸท่กŒ็š„ใ€‚ + +ๅฎนๅ™จๆ˜ ๅƒๆ˜ฏๆ‰€ๆœ‰ๆช”ๆกˆใ€็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒไปฅๅŠๅœจๅฎนๅ™จไธญๆ‡‰่ฉฒๅŸท่กŒ็š„้ ่จญๆŒ‡ไปค/็จ‹ๅผ็š„้œๆ…‹็‰ˆๆœฌใ€‚้€™่ฃก็š„ใ€Œ้œๆ…‹ใ€ๆ„ๆŒ‡ๅฎนๅ™จๆ˜ ๅƒไธๅœจๅŸท่กŒ๏ผŒๅฎƒๅชๆ˜ฏ่ขซๅฐ่ฃ็š„ๆช”ๆกˆ่ˆ‡ metadataใ€‚ + +็›ธๅฐๆ–ผๅ„ฒๅญ˜็š„้œๆ…‹ๅ…งๅฎนใ€Œๅฎนๅ™จๆ˜ ๅƒใ€๏ผŒใ€Œๅฎนๅ™จใ€้€šๅธธๆŒ‡ๅŸท่กŒไธญ็š„ๅฏฆไพ‹๏ผŒไนŸๅฐฑๆ˜ฏๆญฃๅœจ่ขซๅŸท่กŒ็š„ๆฑ่ฅฟใ€‚ + +็•ถๅฎนๅ™จๅ•Ÿๅ‹•ไธฆๅŸท่กŒๆ™‚๏ผˆ่‡ชๅฎนๅ™จๆ˜ ๅƒๅ•Ÿๅ‹•๏ผ‰๏ผŒๅฎƒๅฏไปฅๅปบ็ซ‹ๆˆ–่ฎŠๆ›ดๆช”ๆกˆใ€็’ฐๅขƒ่ฎŠๆ•ธ็ญ‰ใ€‚้€™ไบ›่ฎŠๆ›ดๅชๆœƒๅญ˜ๅœจๆ–ผ่ฉฒๅฎนๅ™จไธญ๏ผŒไธๆœƒๆŒไน…ๅŒ–ๅ›žๅบ•ๅฑค็š„ๅฎนๅ™จๆ˜ ๅƒ๏ผˆไธๆœƒๅฏซๅ›ž็ฃ็ขŸ๏ผ‰ใ€‚ + +ๅฎนๅ™จๆ˜ ๅƒๅฏ้กžๆฏ”็‚บ็จ‹ๅผๆช”่ˆ‡ๅ…ถๅ…งๅฎน๏ผŒไพ‹ๅฆ‚ `python` ่ˆ‡ๆŸๅ€‹ `main.py` ๆช”ๆกˆใ€‚ + +่€Œๅฎนๅ™จๆœฌ่บซ๏ผˆ็›ธๅฐๆ–ผๅฎนๅ™จๆ˜ ๅƒ๏ผ‰ๆ˜ฏๆ˜ ๅƒ็š„ๅฏฆ้š›ๅŸท่กŒๅฏฆไพ‹๏ผŒ้กžๆฏ”็‚บใ€Œ่กŒ็จ‹ใ€ใ€‚ไบ‹ๅฏฆไธŠ๏ผŒๅฎนๅ™จๅชๆœ‰ๅœจๆœ‰่กŒ็จ‹ๅŸท่กŒๆ™‚ๆ‰ๅœจ้‹ไฝœ๏ผˆ้€šๅธธๅชๆœ‰ๅ–ฎไธ€่กŒ็จ‹๏ผ‰ใ€‚็•ถๅ…ถไธญๆฒ’ๆœ‰่กŒ็จ‹ๅœจๅŸท่กŒๆ™‚๏ผŒๅฎนๅ™จๅฐฑๆœƒๅœๆญขใ€‚ + +## ๅฎนๅ™จๆ˜ ๅƒ { #container-images } + +Docker ๆ˜ฏ็”จไพ†ๅปบ็ซ‹่ˆ‡็ฎก็†ๅฎนๅ™จๆ˜ ๅƒ่ˆ‡ๅฎนๅ™จ็š„ไธป่ฆๅทฅๅ…ทไน‹ไธ€ใ€‚ + +ไนŸๆœ‰ไธ€ๅ€‹ๅ…ฌ้–‹็š„ Docker Hub๏ผŒๅ…งๅซ่จฑๅคšๅทฅๅ…ทใ€็’ฐๅขƒใ€่ณ‡ๆ–™ๅบซ่ˆ‡ๆ‡‰็”จ็š„้ ๅ…ˆ่ฃฝไฝœใ€Œๅฎ˜ๆ–นๆ˜ ๅƒใ€ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๆœ‰ๅฎ˜ๆ–น็š„ Python ๆ˜ ๅƒใ€‚ + +ไนŸๆœ‰่จฑๅคšๅ…ถไป–้‡ๅฐไธๅŒ็”จ้€”็š„ๆ˜ ๅƒ๏ผŒไพ‹ๅฆ‚่ณ‡ๆ–™ๅบซ๏ผš + +* PostgreSQL +* MySQL +* MongoDB +* Redis ็ญ‰ใ€‚ + +ไฝฟ็”จ้ ่ฃฝ็š„ๅฎนๅ™จๆ˜ ๅƒๅพˆๅฎนๆ˜“ใ€Œ็ต„ๅˆใ€ไธฆไฝฟ็”จไธๅŒๅทฅๅ…ทใ€‚ไพ‹ๅฆ‚๏ผŒๅ˜—่ฉฆไธ€ๅ€‹ๆ–ฐ่ณ‡ๆ–™ๅบซใ€‚ๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จๅฎ˜ๆ–นๆ˜ ๅƒ๏ผŒไธฆๅƒ…็”จ็’ฐๅขƒ่ฎŠๆ•ธๅŠ ไปฅ่จญๅฎšใ€‚ + +ๅฆ‚ๆญค๏ผŒไฝ ๅฏไปฅๅญธๆœƒ้—œๆ–ผๅฎนๅ™จ่ˆ‡ Docker ็š„็Ÿฅ่ญ˜๏ผŒไธฆๅฐ‡้€™ไบ›็Ÿฅ่ญ˜้‡่ค‡้‹็”จๅˆฐ่จฑๅคšไธๅŒๅทฅๅ…ท่ˆ‡ๅ…ƒไปถไธŠใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๆœƒๅŸท่กŒๅคšๅ€‹ๅฎนๅ™จ๏ผŒๅ…งๅฎนๅ„ไธ็›ธๅŒ๏ผŒไพ‹ๅฆ‚ไธ€ๅ€‹่ณ‡ๆ–™ๅบซใ€ไธ€ๅ€‹ Python ๆ‡‰็”จใ€ไธ€ๅ€‹ๅธถๆœ‰ React ๅ‰็ซฏๆ‡‰็”จ็š„็ถฒ้ ไผบๆœๅ™จ๏ผŒไธฆ้€้Žๅฎƒๅ€‘็š„ๅ…ง้ƒจ็ถฒ่ทฏๆŠŠๅฎƒๅ€‘้€ฃๆŽฅๅœจไธ€่ตทใ€‚ + +ๆ‰€ๆœ‰ๅฎนๅ™จ็ฎก็†็ณป็ตฑ๏ผˆไพ‹ๅฆ‚ Docker ๆˆ– Kubernetes๏ผ‰้ƒฝๅ…งๅปบไบ†้€™ไบ›็ถฒ่ทฏๅŠŸ่ƒฝใ€‚ + +## ๅฎนๅ™จ่ˆ‡่กŒ็จ‹ { #containers-and-processes } + +ๅฎนๅ™จๆ˜ ๅƒ้€šๅธธๅœจๅ…ถ metadata ไธญๅŒ…ๅซ็•ถๅฎนๅ™จๅ•Ÿๅ‹•ๆ™‚ๆ‡‰ๅŸท่กŒ็š„้ ่จญ็จ‹ๅผๆˆ–ๆŒ‡ไปค๏ผŒไปฅๅŠ่ฆๅ‚ณ็ตฆ่ฉฒ็จ‹ๅผ็š„ๅƒๆ•ธใ€‚้€™่ˆ‡ๅœจๅ‘ฝไปคๅˆ—่ฆๅŸท่กŒ็š„ๅ…งๅฎน้žๅธธ้กžไผผใ€‚ + +็•ถๅฎนๅ™จๅ•Ÿๅ‹•ๆ™‚๏ผŒๅฎƒๆœƒๅŸท่กŒ่ฉฒๆŒ‡ไปค/็จ‹ๅผ๏ผˆ้›–็„ถไฝ ๅฏไปฅ่ฆ†ๅฏซๅฎƒ๏ผŒ่ฎ“ๅฎƒๅŸท่กŒไธๅŒ็š„ๆŒ‡ไปค/็จ‹ๅผ๏ผ‰ใ€‚ + +ๅช่ฆไธป่ฆ่กŒ็จ‹๏ผˆๆŒ‡ไปคๆˆ–็จ‹ๅผ๏ผ‰ๅœจๅŸท่กŒ๏ผŒๅฎนๅ™จๅฐฑๆœƒ้‹ไฝœใ€‚ + +ๅฎนๅ™จ้€šๅธธๅชๆœ‰ๅ–ฎไธ€่กŒ็จ‹๏ผŒไฝ†ไนŸๅฏไปฅ็”ฑไธป่ฆ่กŒ็จ‹ๅ•Ÿๅ‹•ๅญ่กŒ็จ‹๏ผŒๅฆ‚ๆญคไฝ ๆœƒๅœจๅŒไธ€ๅ€‹ๅฎนๅ™จๅ…งๆœ‰ๅคšๅ€‹่กŒ็จ‹ใ€‚ + +ไฝ†ไธๅฏ่ƒฝๅœจๆฒ’ๆœ‰่‡ณๅฐ‘ไธ€ๅ€‹ๅŸท่กŒไธญ่กŒ็จ‹็š„ๆƒ…ๆณไธ‹่ฎ“ๅฎนๅ™จ้‹ไฝœใ€‚่‹ฅไธป่ฆ่กŒ็จ‹ๅœๆญข๏ผŒๅฎนๅ™จไนŸๆœƒๅœๆญขใ€‚ + +## ๅปบ็ฝฎ FastAPI ็š„ Docker ๆ˜ ๅƒ { #build-a-docker-image-for-fastapi } + +ๅฅฝไบ†๏ผŒ็พๅœจไพ†ๅ‹•ๆ‰‹ๅš้ปžๆฑ่ฅฟๅง๏ผ๐Ÿš€ + +ๆˆ‘ๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•ๅพž้›ถ้–‹ๅง‹๏ผŒๅŸบๆ–ผๅฎ˜ๆ–น็š„ Python ๆ˜ ๅƒ๏ผŒ็‚บ FastAPI ๅปบ็ฝฎไธ€ๅ€‹ Docker ๆ˜ ๅƒใ€‚ + +้€™ๆ˜ฏไฝ ๅœจๅคšๆ•ธๆƒ…ๆณไธ‹ๆœƒๆƒณๅš็š„ไบ‹๏ผŒไพ‹ๅฆ‚๏ผš + +* ไฝฟ็”จ Kubernetes ๆˆ–้กžไผผๅทฅๅ…ท +* ๅœจ Raspberry Pi ไธŠๅŸท่กŒ +* ไฝฟ็”จๆœƒๆ›ฟไฝ ๅŸท่กŒๅฎนๅ™จๆ˜ ๅƒ็š„้›ฒ็ซฏๆœๅ‹™็ญ‰ + +### ๅฅ—ไปถ้œ€ๆฑ‚ { #package-requirements } + +ไฝ ็š„ๆ‡‰็”จ้€šๅธธๆœƒๆŠŠใ€Œๅฅ—ไปถ้œ€ๆฑ‚ใ€ๆ”พๅœจๆŸๅ€‹ๆช”ๆกˆไธญใ€‚ + +้€™ไธป่ฆๅ–ๆฑบๆ–ผไฝ ็”จไป€้บผๅทฅๅ…ทไพ†ๅฎ‰่ฃ้‚ฃไบ›้œ€ๆฑ‚ใ€‚ + +ๆœ€ๅธธ่ฆ‹็š„ๆ–นๅผๆ˜ฏๆบ–ๅ‚™ไธ€ๅ€‹ `requirements.txt` ๆช”ๆกˆ๏ผŒ้€่กŒๅˆ—ๅ‡บๅฅ—ไปถๅ็จฑ่ˆ‡็‰ˆๆœฌใ€‚ + +็•ถ็„ถ๏ผŒไฝ ๆœƒ็”จ่ˆ‡ๅœจ [้—œๆ–ผ FastAPI ็‰ˆๆœฌ](versions.md){.internal-link target=_blank} ไธญ่ฎ€ๅˆฐ็š„็›ธๅŒๆฆ‚ๅฟต๏ผŒไพ†่จญๅฎš็‰ˆๆœฌ็ฏ„ๅœใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ็š„ `requirements.txt` ๅฏ่ƒฝๅƒ้€™ๆจฃ๏ผš + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +ๆŽฅ่‘—ไฝ ้€šๅธธๆœƒ็”จ `pip` ไพ†ๅฎ‰่ฃ้€™ไบ›ๅฅ—ไปถ็›ธไพ๏ผŒไพ‹ๅฆ‚๏ผš + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// info | ่ณ‡่จŠ + +้‚„ๆœ‰ๅ…ถไป–ๆ ผๅผ่ˆ‡ๅทฅๅ…ทๅฏไปฅ็”จไพ†ๅฎš็พฉ่ˆ‡ๅฎ‰่ฃๅฅ—ไปถ็›ธไพใ€‚ + +/// + +### ๅปบ็ซ‹ FastAPI ็จ‹ๅผ็ขผ { #create-the-fastapi-code } + +* ๅปบ็ซ‹ไธ€ๅ€‹ `app` ็›ฎ้Œ„ไธฆ้€ฒๅ…ฅใ€‚ +* ๅปบ็ซ‹ไธ€ๅ€‹็ฉบ็š„ `__init__.py` ๆช”ๆกˆใ€‚ +* ๅปบ็ซ‹ไธ€ๅ€‹ `main.py` ๆช”ๆกˆ๏ผŒๅ…งๅฎนๅฆ‚ไธ‹๏ผš + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +็พๅœจๅœจๅŒไธ€ๅ€‹ๅฐˆๆกˆ็›ฎ้Œ„ๅปบ็ซ‹ไธ€ๅ€‹ `Dockerfile` ๆช”ๆกˆ๏ผŒๅ…งๅฎนๅฆ‚ไธ‹๏ผš + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. ๅพžๅฎ˜ๆ–น็š„ Python ๅŸบๅบ•ๆ˜ ๅƒ้–‹ๅง‹ใ€‚ + +2. ๅฐ‡็›ฎๅ‰ๅทฅไฝœ็›ฎ้Œ„่จญ็‚บ `/code`ใ€‚ + + ๆˆ‘ๅ€‘ๆœƒๆŠŠ `requirements.txt` ๆช”ๆกˆ่ˆ‡ `app` ็›ฎ้Œ„ๆ”พๅœจ้€™่ฃกใ€‚ + +3. ๅฐ‡้œ€ๆฑ‚ๆช”ๆกˆ่ค‡่ฃฝๅˆฐ `/code` ็›ฎ้Œ„ใ€‚ + + ๅ…ˆๅช่ค‡่ฃฝ้œ€ๆฑ‚ๆช”ๆกˆ๏ผŒไธ่ฆ่ค‡่ฃฝๅ…ถไป–็จ‹ๅผ็ขผใ€‚ + + ๅ› ็‚บ้€™ๅ€‹ๆช”ๆกˆไธๅธธ่ฎŠๅ‹•๏ผŒDocker ่ƒฝๅตๆธฌไธฆๅœจๆญคๆญฅ้ฉŸไฝฟ็”จๅฟซๅ–๏ผŒไนŸ่ƒฝๅ•Ÿ็”จไธ‹ไธ€ๆญฅ็š„ๅฟซๅ–ใ€‚ + +4. ๅฎ‰่ฃ้œ€ๆฑ‚ๆช”ๆกˆไธญ็š„ๅฅ—ไปถ็›ธไพใ€‚ + + `--no-cache-dir` ้ธ้ …ๅ‘Š่จด `pip` ไธ่ฆๆŠŠไธ‹่ผ‰็š„ๅฅ—ไปถไฟๅญ˜ๅœจๆœฌๆฉŸ๏ผŒๅ› ็‚บ้‚ฃๅชๅœจ `pip` ไน‹ๅพŒ้‚„ๆœƒๅ†ๆฌกๅฎ‰่ฃ็›ธๅŒๅฅ—ไปถๆ™‚ๆ‰ๆœ‰็”จ๏ผŒ่€Œๅœจไฝฟ็”จๅฎนๅ™จๆ™‚ไธฆ้žๅฆ‚ๆญคใ€‚ + + /// note | ๆณจๆ„ + + `--no-cache-dir` ๅช่ทŸ `pip` ๆœ‰้—œ๏ผŒ่ˆ‡ Docker ๆˆ–ๅฎนๅ™จ็„ก้—œใ€‚ + + /// + + `--upgrade` ้ธ้ …ๅ‘Š่จด `pip` ่‹ฅๅฅ—ไปถๅทฒๅฎ‰่ฃๅ‰‡ๅ‡็ดšๅฎƒๅ€‘ใ€‚ + + ๅ› ็‚บๅ‰ไธ€ๆญฅ่ค‡่ฃฝๆช”ๆกˆๅฏ่ƒฝ่ขซ Docker ๅฟซๅ–ๅตๆธฌๅˆฐ๏ผŒ้€™ไธ€ๆญฅไนŸๆœƒๅœจๅฏ็”จๆ™‚ไฝฟ็”จ Docker ๅฟซๅ–ใ€‚ + + ๅœจๆญคๆญฅ้ฉŸไฝฟ็”จๅฟซๅ–ๅฏไปฅๅœจ้–‹็™ผๆœŸ้–“ๅ่ฆ†ๅปบ็ฝฎๆ˜ ๅƒๆ™‚๏ผŒ็‚บไฝ ็œไธ‹ๅคง้‡ๆ™‚้–“๏ผŒ่€Œไธๅฟ…ๆฏๆฌก้ƒฝ้‡ๆ–ฐไธ‹่ผ‰ไธฆๅฎ‰่ฃๆ‰€ๆœ‰็›ธไพใ€‚ + +5. ๅฐ‡ `./app` ็›ฎ้Œ„่ค‡่ฃฝๅˆฐ `/code` ็›ฎ้Œ„ไธญใ€‚ + + ็”ฑๆ–ผ้€™ๅŒ…ๅซไบ†ๆ‰€ๆœ‰็จ‹ๅผ็ขผ๏ผŒไนŸๆ˜ฏๆœ€ๅธธ่ฎŠๅ‹•็š„้ƒจๅˆ†๏ผŒDocker ็š„ๅฟซๅ–ๅœจ้€™ไธ€ๆญฅๆˆ–ไน‹ๅพŒ็š„ๆญฅ้ฉŸๅฐ‡ไธๅฎนๆ˜“่ขซไฝฟ็”จใ€‚ + + ๅ› ๆญค๏ผŒ้‡่ฆ็š„ๆ˜ฏๆŠŠ้€™ไธ€ๆญฅๆ”พๅœจ `Dockerfile` ็š„ๆŽฅ่ฟ‘็ตๅฐพ่™•๏ผŒไปฅๆœ€ไฝณๅŒ–ๅฎนๅ™จๆ˜ ๅƒ็š„ๅปบ็ฝฎๆ™‚้–“ใ€‚ + +6. ่จญๅฎšๆŒ‡ไปคไฝฟ็”จ `fastapi run`๏ผŒๅ…ถๅบ•ๅฑคไฝฟ็”จ Uvicornใ€‚ + + `CMD` ๆŽฅๅ—ๅญ—ไธฒๆธ…ๅ–ฎ๏ผŒๆฏๅ€‹ๅญ—ไธฒๅฐๆ‡‰ไฝ ๅœจๅ‘ฝไปคๅˆ—ไธญ็”จ็ฉบ็™ฝๅˆ†้š”ๆ‰€่ผธๅ…ฅ็š„ๅ…งๅฎนใ€‚ + + ้€™ๅ€‹ๆŒ‡ไปคๆœƒๅพž็›ฎๅ‰็š„ๅทฅไฝœ็›ฎ้Œ„ๅŸท่กŒ๏ผŒไนŸๅฐฑๆ˜ฏไฝ ๅ…ˆๅ‰็”จ `WORKDIR /code` ่จญๅฎš็š„ `/code` ็›ฎ้Œ„ใ€‚ + +/// tip | ๆ็คบ + +้ปžๆ“Š็จ‹ๅผ็ขผไธญ็š„ๆฏๅ€‹ๆ•ธๅญ—ๆณกๆณกไพ†ๆŸฅ็œ‹ๆฏไธ€่กŒๅœจๅšไป€้บผใ€‚๐Ÿ‘† + +/// + +/// warning | ่ญฆๅ‘Š + +ๅ‹™ๅฟ…ใ€Œ็ธฝๆ˜ฏใ€ไฝฟ็”จ `CMD` ๆŒ‡ไปค็š„ใ€Œexec ๅฝขๅผใ€๏ผŒๅฆ‚ไธ‹ๆ‰€่ฟฐใ€‚ + +/// + +#### ไฝฟ็”จ `CMD` ็š„ Exec ๅฝขๅผ { #use-cmd-exec-form } + +Docker ็š„ `CMD` ๆŒ‡ไปคๅฏไปฅๆœ‰ๅ…ฉ็จฎๅฏซๆณ•๏ผš + +โœ… Exec ๅฝขๅผ๏ผš + +```Dockerfile +# โœ… ่ซ‹้€™ๆจฃๅš +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ Shell ๅฝขๅผ๏ผš + +```Dockerfile +# โ›”๏ธ ่ซ‹ไธ่ฆ้€™ๆจฃๅš +CMD fastapi run app/main.py --port 80 +``` + +ๅ‹™ๅฟ…็ธฝๆ˜ฏไฝฟ็”จ exec ๅฝขๅผ๏ผŒไปฅ็ขบไฟ FastAPI ่ƒฝๅค ๅ„ช้›…ๅœฐ้—œ้–‰๏ผŒไธฆ่งธ็™ผ [lifespan events](../advanced/events.md){.internal-link target=_blank}ใ€‚ + +ไฝ ๅฏไปฅๅœจ Docker ้—œๆ–ผ shell ่ˆ‡ exec ๅฝขๅผ็š„ๆ–‡ไปถ้–ฑ่ฎ€ๆ›ดๅคšใ€‚ + +ไฝฟ็”จ `docker compose` ๆ™‚้€™ๆœƒ็‰นๅˆฅๆ˜Ž้กฏใ€‚ๆŠ€่ก“็ดฐ็ฏ€่ซ‹่ฆ‹้€™ๆฎต Docker Compose ๅธธ่ฆ‹ๅ•้กŒ๏ผš็‚บไป€้บผๆˆ‘็š„ๆœๅ‹™่ฆ่Šฑ 10 ็ง’ๆ‰้‡ๆ–ฐๅปบ็ซ‹ๆˆ–ๅœๆญข๏ผŸ + +#### ็›ฎ้Œ„็ตๆง‹ { #directory-structure } + +ไฝ ็พๅœจๆ‡‰่ฉฒๆœƒๆœ‰ๅฆ‚ไธ‹็š„็›ฎ้Œ„็ตๆง‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ โ””โ”€โ”€ main.py +โ”œโ”€โ”€ Dockerfile +โ””โ”€โ”€ requirements.txt +``` + +#### ไฝๆ–ผ TLS ็ต‚ๆญขไปฃ็†ไน‹ๅพŒ { #behind-a-tls-termination-proxy } + +ๅฆ‚ๆžœไฝ ๅœจ TLS ็ต‚ๆญขไปฃ็†๏ผˆ่ฒ ่ผ‰ๅนณ่กกๅ™จ๏ผ‰ๅฆ‚ Nginx ๆˆ– Traefik ไน‹ๅพŒๅŸท่กŒๅฎนๅ™จ๏ผŒ่ซ‹ๅŠ ไธŠ `--proxy-headers` ้ธ้ …๏ผŒ้€™ๆœƒๅ‘Š่จด Uvicorn๏ผˆ้€้Ž FastAPI CLI๏ผ‰ไฟกไปป่ฉฒไปฃ็†ๆ‰€้€ไพ†็š„ๆจ™้ ญ๏ผŒ่กจ็คบๆ‡‰็”จๅœจ HTTPS ๅพŒๆ–นๅŸท่กŒ็ญ‰ใ€‚ + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker ๅฟซๅ– { #docker-cache } + +้€™ๅ€‹ `Dockerfile` ไธญๆœ‰ๅ€‹้‡่ฆๆŠ€ๅทง๏ผšๆˆ‘ๅ€‘ๅ…ˆๅช่ค‡่ฃฝใ€Œ็›ธไพๆช”ๆกˆใ€๏ผŒ่€Œไธๆ˜ฏๅ…ถไป–็จ‹ๅผ็ขผใ€‚ๅŽŸๅ› ๅฆ‚ไธ‹ใ€‚ + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker ่ˆ‡ๅ…ถไป–ๅทฅๅ…ทๆœƒใ€Œๅขž้‡ๅผใ€ๅปบ็ฝฎๅฎนๅ™จๆ˜ ๅƒ๏ผŒๅพž `Dockerfile` ้ ‚็ซฏ้–‹ๅง‹๏ผŒ้€ๅฑคๅŠ ๅ…ฅ๏ผŒๆฏๅ€‹ๆŒ‡ไปคๆ‰€ๅปบ็ซ‹็š„ๆช”ๆกˆ้ƒฝๆœƒๅฝขๆˆไธ€ๅฑคใ€‚ + +Docker ่ˆ‡้กžไผผๅทฅๅ…ทๅœจๅปบ็ฝฎๆ˜ ๅƒๆ™‚ไนŸๆœƒไฝฟ็”จๅ…ง้ƒจๅฟซๅ–๏ผ›ๅฆ‚ๆžœๆŸๆช”ๆกˆ่‡ชไธŠๆฌกๅปบ็ฝฎไปฅไพ†ๆœช่ฎŠๆ›ด๏ผŒๅ‰‡ๆœƒ้‡็”จไธŠๆฌกๅปบ็ซ‹็š„ๅŒไธ€ๅฑค๏ผŒ่€Œไธๆ˜ฏๅ†ๆฌก่ค‡่ฃฝไธฆๅพž้›ถๅปบ็ซ‹ๆ–ฐๅฑคใ€‚ + +ๅƒ…ๅƒ…้ฟๅ…่ค‡่ฃฝๆช”ๆกˆๆœฌ่บซๆˆ–่จฑๅนซๅŠฉไธๅคง๏ผŒไฝ†ๅ› ็‚บ่ฉฒๆญฅ้ฉŸไฝฟ็”จไบ†ๅฟซๅ–๏ผŒๆŽฅไธ‹ไพ†็š„ๆญฅ้ฉŸไนŸๅฐฑ่ƒฝใ€Œไฝฟ็”จๅฟซๅ–ใ€ใ€‚ไพ‹ๅฆ‚๏ผŒๅฎ‰่ฃ็›ธไพ็š„้€™ๅ€‹ๆŒ‡ไปคๅฐฑ่ƒฝไฝฟ็”จๅฟซๅ–๏ผš + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +ๅฅ—ไปถ็›ธไพ็š„ๆช”ๆกˆใ€Œไธๆœƒ็ถ“ๅธธ่ฎŠๅ‹•ใ€ใ€‚ๅ› ๆญค๏ผŒๅช่ค‡่ฃฝ่ฉฒๆช”ๆกˆ๏ผŒDocker ๅฐฑ่ƒฝๅœจๆญคๆญฅ้ฉŸใ€Œไฝฟ็”จๅฟซๅ–ใ€ใ€‚ + +ๆŽฅ่‘—๏ผŒDocker ไนŸๅฐฑ่ƒฝๅฐไธ‹ไธ€ๆญฅใ€Œไธ‹่ผ‰ไธฆๅฎ‰่ฃ้€™ไบ›็›ธไพใ€ไฝฟ็”จๅฟซๅ–ใ€‚้€™ๆญฃๆ˜ฏๆˆ‘ๅ€‘่ƒฝใ€Œ็œไธ‹ๅคง้‡ๆ™‚้–“ใ€็š„ๅœฐๆ–นใ€‚โœจ ไนŸ่ƒฝ้ฟๅ…็„ก่Š็š„็ญ‰ๅพ…ใ€‚๐Ÿ˜ช๐Ÿ˜† + +ไธ‹่ผ‰่ˆ‡ๅฎ‰่ฃๅฅ—ไปถ็›ธไพใ€Œๅฏ่ƒฝ่ฆ่Šฑๅฅฝๅนพๅˆ†้˜ใ€๏ผŒไฝ†ไฝฟ็”จใ€Œๅฟซๅ–ใ€ๆœ€ๅคšๅช้œ€ๅนพ็ง’ใ€‚ + +ๅœจ้–‹็™ผๆœŸ้–“๏ผŒไฝ ๆœƒไธ€ๅ†ๅปบ็ฝฎๅฎนๅ™จๆ˜ ๅƒไปฅๆธฌ่ฉฆ็จ‹ๅผ็ขผ่ฎŠๆ›ดๆ˜ฏๅฆ็”Ÿๆ•ˆ๏ผŒ็ดฏ็ฉไธ‹ไพ†้€™่ƒฝ็œไธ‹่จฑๅคšๆ™‚้–“ใ€‚ + +ไน‹ๅพŒ๏ผŒๅœจ `Dockerfile` ็š„ๆŽฅ่ฟ‘็ตๅฐพ่™•๏ผŒๆˆ‘ๅ€‘ๆ‰่ค‡่ฃฝๆ‰€ๆœ‰็จ‹ๅผ็ขผใ€‚็”ฑๆ–ผ้€™ๆ˜ฏใ€Œๆœ€ๅธธ่ฎŠๅ‹•ใ€็š„้ƒจๅˆ†๏ผŒๆˆ‘ๅ€‘ๆŠŠๅฎƒๆ”พๅœจๆŽฅ่ฟ‘็ตๅฐพ๏ผŒๅ› ็‚บๅนพไนŽ็ธฝๆ˜ฏๆญคๆญฅ้ฉŸไน‹ๅพŒ็š„ไปปไฝ•ๆญฅ้ฉŸ้ƒฝ็„กๆณ•ไฝฟ็”จๅฟซๅ–ใ€‚ + +```Dockerfile +COPY ./app /code/app +``` + +### ๅปบ็ฝฎ Docker ๆ˜ ๅƒ { #build-the-docker-image } + +็พๅœจๆ‰€ๆœ‰ๆช”ๆกˆๅฐฑ็ท’๏ผŒไพ†ๅปบ็ฝฎๅฎนๅ™จๆ˜ ๅƒใ€‚ + +* ้€ฒๅˆฐๅฐˆๆกˆ็›ฎ้Œ„๏ผˆไฝ ็š„ `Dockerfile` ๆ‰€ๅœจ๏ผŒไธ”ๅŒ…ๅซ `app` ็›ฎ้Œ„๏ผ‰ใ€‚ +* ๅปบ็ฝฎไฝ ็š„ FastAPI ๆ˜ ๅƒ๏ผš + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | ๆ็คบ + +ๆณจๆ„ๆœ€ๅพŒ็š„ `.`๏ผŒ็ญ‰ๅŒๆ–ผ `./`๏ผŒๅฎƒๅ‘Š่จด Docker ่ฆ็”จๅ“ชๅ€‹็›ฎ้Œ„ไพ†ๅปบ็ฝฎๅฎนๅ™จๆ˜ ๅƒใ€‚ + +้€™่ฃกๆ˜ฏ็›ฎๅ‰็š„็›ฎ้Œ„๏ผˆ`.`๏ผ‰ใ€‚ + +/// + +### ๅ•Ÿๅ‹• Docker ๅฎนๅ™จ { #start-the-docker-container } + +* ไปฅไฝ ็š„ๆ˜ ๅƒ็‚บๅŸบ็คŽๅŸท่กŒไธ€ๅ€‹ๅฎนๅ™จ๏ผš + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## ๆชขๆŸฅ { #check-it } + +ไฝ ๆ‡‰่ฉฒๅฏไปฅ้€้Ž Docker ๅฎนๅ™จ็š„็ถฒๅ€ๆชขๆŸฅ๏ผŒไพ‹ๅฆ‚๏ผšhttp://192.168.99.100/items/5?q=somequery ๆˆ– http://127.0.0.1/items/5?q=somequery๏ผˆๆˆ–็ญ‰ๆ•ˆ็š„ใ€ไฝฟ็”จไฝ ็š„ Docker ไธปๆฉŸ๏ผ‰ใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐ้กžไผผ้€™ๆจฃ๏ผš + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ { #interactive-api-docs } + +็พๅœจไฝ ๅฏไปฅๅ‰ๅพ€ http://192.168.99.100/docs ๆˆ– http://127.0.0.1/docs๏ผˆๆˆ–็ญ‰ๆ•ˆ็š„ใ€ไฝฟ็”จไฝ ็š„ Docker ไธปๆฉŸ๏ผ‰ใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐ่‡ชๅ‹•็”ข็”Ÿ็š„ไบ’ๅ‹•ๅผ API ๆ–‡ไปถ๏ผˆ็”ฑ Swagger UI ๆไพ›๏ผ‰๏ผš + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## ๆ›ฟไปฃ็š„ API ๆ–‡ไปถ { #alternative-api-docs } + +ไฝ ไนŸๅฏไปฅๅ‰ๅพ€ http://192.168.99.100/redoc ๆˆ– http://127.0.0.1/redoc๏ผˆๆˆ–็ญ‰ๆ•ˆ็š„ใ€ไฝฟ็”จไฝ ็š„ Docker ไธปๆฉŸ๏ผ‰ใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐๅฆไธ€็จฎ่‡ชๅ‹•็”ข็”Ÿ็š„ๆ–‡ไปถ๏ผˆ็”ฑ ReDoc ๆไพ›๏ผ‰๏ผš + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## ็‚บๅ–ฎๆช” FastAPI ๅปบ็ฝฎ Docker ๆ˜ ๅƒ { #build-a-docker-image-with-a-single-file-fastapi } + +ๅฆ‚ๆžœไฝ ็š„ FastAPI ๆ˜ฏๅ–ฎไธ€ๆช”ๆกˆ๏ผŒไพ‹ๅฆ‚ๆฒ’ๆœ‰ `./app` ็›ฎ้Œ„็š„ `main.py`๏ผŒไฝ ็š„ๆช”ๆกˆ็ตๆง‹ๅฏ่ƒฝๅƒ้€™ๆจฃ๏ผš + +``` +. +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ main.py +โ””โ”€โ”€ requirements.txt +``` + +ๆŽฅ่‘—ไฝ ๅช้œ€่ฆๅœจ `Dockerfile` ไธญ่ชฟๆ•ดๅฐๆ‡‰็š„่ทฏๅพ‘ไปฅ่ค‡่ฃฝ่ฉฒๆช”ๆกˆ๏ผš + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. ๅฐ‡ `main.py` ็›ดๆŽฅ่ค‡่ฃฝๅˆฐ `/code` ็›ฎ้Œ„๏ผˆไธ้œ€่ฆ `./app` ็›ฎ้Œ„๏ผ‰ใ€‚ + +2. ไฝฟ็”จ `fastapi run` ไพ†ๆœๅ‹™ๅ–ฎๆช”็š„ `main.py` ๆ‡‰็”จใ€‚ + +็•ถไฝ ๆŠŠๆช”ๆกˆๅ‚ณ็ตฆ `fastapi run`๏ผŒๅฎƒๆœƒ่‡ชๅ‹•ๅตๆธฌ้€™ๆ˜ฏไธ€ๅ€‹ๅ–ฎไธ€ๆช”ๆกˆ่€Œ้žๅฅ—ไปถ็š„ไธ€้ƒจๅˆ†๏ผŒไธฆ็Ÿฅ้“ๅฆ‚ไฝ•ๅŒฏๅ…ฅไธฆๆœๅ‹™ไฝ ็š„ FastAPI ๆ‡‰็”จใ€‚๐Ÿ˜Ž + +## ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployment-concepts } + +ๆˆ‘ๅ€‘็”จๅฎนๅ™จ็š„่ง’ๅบฆๅ†่ซ‡ไธ€ๆฌก้ƒจๅˆ†็›ธๅŒ็š„[้ƒจ็ฝฒๆฆ‚ๅฟต](concepts.md){.internal-link target=_blank}ใ€‚ + +ๅฎนๅ™จไธป่ฆๆ˜ฏ็ฐกๅŒ–ๆ‡‰็”จใ€Œๅปบ็ฝฎ่ˆ‡้ƒจ็ฝฒใ€ๆต็จ‹็š„ๅทฅๅ…ท๏ผŒไฝ†ๅฎƒๅ€‘ไธๅผทๅˆถ็‰นๅฎš็š„ๆ–นๅผไพ†่™•็†้€™ไบ›ใ€Œ้ƒจ็ฝฒๆฆ‚ๅฟตใ€๏ผŒ่€Œๆ˜ฏๆœ‰ๅคš็จฎ็ญ–็•ฅๅฏ้ธใ€‚ + +ๅฅฝๆถˆๆฏๆ˜ฏ๏ผŒๆฏ็จฎไธๅŒ็š„็ญ–็•ฅ้ƒฝ่ƒฝๆถต่“‹ๆ‰€ๆœ‰้ƒจ็ฝฒๆฆ‚ๅฟตใ€‚๐ŸŽ‰ + +่ฎ“ๆˆ‘ๅ€‘็”จๅฎนๅ™จ็š„่ง’ๅบฆๅ›ž้กง้€™ไบ›้ƒจ็ฝฒๆฆ‚ๅฟต๏ผš + +* HTTPS +* ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ +* ๅคฑๆ•—้‡ๅ•Ÿ +* ่ค‡ๆœฌ๏ผˆๅŸท่กŒ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +* ่จ˜ๆ†ถ้ซ” +* ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +## HTTPS { #https } + +่‹ฅๅƒ…่š็„ฆๆ–ผ FastAPI ๆ‡‰็”จ็š„ใ€Œๅฎนๅ™จๆ˜ ๅƒใ€๏ผˆไปฅๅŠ็จๅพŒ็š„ๅŸท่กŒไธญใ€Œๅฎนๅ™จใ€๏ผ‰๏ผŒHTTPS ้€šๅธธๆœƒ็”ฑๅฆไธ€ๅ€‹ๅทฅๅ…ทๅœจใ€Œๅค–้ƒจใ€่™•็†ใ€‚ + +ๅฎƒๅฏไปฅๆ˜ฏๅฆไธ€ๅ€‹ๅฎนๅ™จ๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ Traefik๏ผŒไพ†่™•็†ใ€ŒHTTPSใ€ไปฅๅŠใ€Œ่‡ชๅ‹•ใ€ๅ–ๅพ—ใ€Œๆ†‘่ญ‰ใ€ใ€‚ + +/// tip | ๆ็คบ + +Traefik ่ˆ‡ Dockerใ€Kubernetes ็ญ‰ๆ•ดๅˆ่‰ฏๅฅฝ๏ผŒๅ› ๆญค็‚บไฝ ็š„ๅฎนๅ™จ่จญๅฎš่ˆ‡้…็ฝฎ HTTPS ้žๅธธๅฎนๆ˜“ใ€‚ + +/// + +ๆˆ–่€…๏ผŒHTTPS ไนŸๅฏ่ƒฝ็”ฑ้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ไปฅๅ…ถๆœๅ‹™ไพ†่™•็†๏ผˆๅŒๆ™‚ๆ‡‰็”จไปไปฅๅฎนๅ™จๅŸท่กŒ๏ผ‰ใ€‚ + +## ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ่ˆ‡้‡ๅ•Ÿ { #running-on-startup-and-restarts } + +้€šๅธธๆœƒๆœ‰ๅฆไธ€ๅ€‹ๅทฅๅ…ท่ฒ ่ฒฌใ€Œๅ•Ÿๅ‹•ไธฆๅŸท่กŒใ€ไฝ ็š„ๅฎนๅ™จใ€‚ + +ๅฏ่ƒฝๆ˜ฏ็›ดๆŽฅ็”จ Dockerใ€Docker Composeใ€Kubernetesใ€ๆŸๅ€‹้›ฒ็ซฏๆœๅ‹™็ญ‰ใ€‚ + +ๅœจๅคงๅคšๆ•ธ๏ผˆๆˆ–ๅ…จ้ƒจ๏ผ‰ๆƒ…ๆณไธ‹๏ผŒ้ƒฝๆœ‰็ฐกๅ–ฎ็š„้ธ้ …ๅฏไปฅๅœจ้–‹ๆฉŸๆ™‚่‡ชๅ‹•ๅŸท่กŒๅฎนๅ™จ๏ผŒไธฆๅœจๅคฑๆ•—ๆ™‚้‡ๅ•Ÿใ€‚ไพ‹ๅฆ‚๏ผŒๅœจ Docker ไธญ๏ผŒๅฏ็”จๅ‘ฝไปคๅˆ—้ธ้ … `--restart`ใ€‚ + +ๅฆ‚ๆžœไธไฝฟ็”จๅฎนๅ™จ๏ผŒ่ฎ“ๆ‡‰็”จๅœจ้–‹ๆฉŸๆ™‚่‡ชๅ‹•ๅŸท่กŒไธฆๆ”ฏๆด้‡ๅ•Ÿๅฏ่ƒฝๆ—ข็น็‘ฃๅˆๅ›ฐ้›ฃใ€‚ไฝ†ๅœจใ€Œไฝฟ็”จๅฎนๅ™จใ€ๆ™‚๏ผŒ้€™้กžๅŠŸ่ƒฝๅœจๅคšๆ•ธๆƒ…ๆณไธ‹้ƒฝๆ˜ฏ้ ่จญๅŒ…ๅซ็š„ใ€‚โœจ + +## ่ค‡ๆœฌ - ่กŒ็จ‹ๆ•ธ้‡ { #replication-number-of-processes } + +ๅฆ‚ๆžœไฝ ๅœจๆœ‰ Kubernetesใ€Docker Swarm Modeใ€Nomad๏ผŒๆˆ–ๅ…ถไป–้กžไผผ็š„ๅˆ†ๆ•ฃๅผๅฎนๅ™จ็ฎก็†็ณป็ตฑ็š„ใ€Œๅข้›†ใ€ไธŠ้‹ไฝœ๏ผŒ้‚ฃไฝ ๅคงๆฆ‚ๆœƒๅธŒๆœ›ๅœจใ€Œๅข้›†ๅฑค็ดšใ€่™•็†ใ€Œ่ค‡ๆœฌใ€๏ผŒ่€Œไธๆ˜ฏๅœจๆฏๅ€‹ๅฎนๅ™จๅ…งไฝฟ็”จใ€Œ่กŒ็จ‹็ฎก็†ๅ™จใ€๏ผˆไพ‹ๅฆ‚ๅธถๆœ‰ workers ็š„ Uvicorn๏ผ‰ใ€‚ + +ๅƒ Kubernetes ้€™้กž็š„ๅˆ†ๆ•ฃๅผๅฎนๅ™จ็ฎก็†็ณป็ตฑ๏ผŒ้€šๅธธๅ…งๅปบ่™•็†ใ€Œๅฎนๅ™จ่ค‡ๆœฌใ€ไปฅๅŠๆ”ฏๆด้€ฒๅ…ฅ่ซ‹ๆฑ‚็š„ใ€Œ่ฒ ่ผ‰ๅนณ่กกใ€็š„่ƒฝๅŠ›โ€”โ€”ๅ…จ้ƒจ้ƒฝๅœจใ€Œๅข้›†ๅฑค็ดšใ€ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅคงๆฆ‚ๆœƒๆƒณ่ฆๅฆ‚[ไธŠ้ขๆ‰€่ฟฐ](#dockerfile)ๅพž้›ถ้–‹ๅง‹ๅปบ็ฝฎไธ€ๅ€‹ Docker ๆ˜ ๅƒ๏ผŒๅฎ‰่ฃไฝ ็š„็›ธไพ๏ผŒไธฆไธ”ๅชๅŸท่กŒใ€Œๅ–ฎไธ€ Uvicorn ่กŒ็จ‹ใ€๏ผŒ่€Œไธๆ˜ฏไฝฟ็”จๅคšๅ€‹ Uvicorn workersใ€‚ + +### ่ฒ ่ผ‰ๅนณ่กกๅ™จ { #load-balancer } + +ไฝฟ็”จๅฎนๅ™จๆ™‚๏ผŒ้€šๅธธๆœƒๆœ‰ๆŸๅ€‹ๅ…ƒไปถๅœจใ€ŒไธปๅŸ ๅฃใ€ไธŠ็›ฃ่ฝใ€‚ๅฎƒไนŸๅฏ่ƒฝๆ˜ฏๅฆไธ€ๅ€‹ๅŒๆ™‚ๅš็‚บใ€ŒTLS ็ต‚ๆญขไปฃ็†ใ€็š„ๅฎนๅ™จไพ†่™•็†ใ€ŒHTTPSใ€๏ผŒๆˆ–้กžไผผ็š„ๅทฅๅ…ทใ€‚ + +็”ฑๆ–ผ้€™ๅ€‹ๅ…ƒไปถๆœƒๆ‰ฟๆŽฅ่ซ‹ๆฑ‚็š„ใ€Œ่ฒ ่ผ‰ใ€๏ผŒไธฆๅฐ‡ๅ…ถๅˆ†้…็ตฆ workers๏ผŒไฝฟๅ…ถ๏ผˆๅธŒๆœ›๏ผ‰ใ€Œๅนณ่กกใ€๏ผŒๅ› ๆญคไนŸๅธธ่ขซ็จฑ็‚บใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จ๏ผˆLoad Balancer๏ผ‰ใ€ใ€‚ + +/// tip | ๆ็คบ + +็”จๆ–ผ HTTPS ็š„ๅŒไธ€ๅ€‹ใ€ŒTLS ็ต‚ๆญขไปฃ็†ใ€ๅ…ƒไปถ้€šๅธธไนŸๆœƒๆ˜ฏใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€ใ€‚ + +/// + +่€Œๅœจไฝฟ็”จๅฎนๅ™จๆ™‚๏ผŒไฝ ็”จไพ†ๅ•“ๅ‹•่ˆ‡็ฎก็†ๅฎƒๅ€‘็š„็ณป็ตฑ๏ผŒๅทฒๅ…งๅปบๆŠŠใ€Œ็ถฒ่ทฏ้€š่จŠใ€๏ผˆไพ‹ๅฆ‚ HTTP ่ซ‹ๆฑ‚๏ผ‰ๅพž่ฉฒใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€๏ผˆไนŸๅฏ่ƒฝๆ˜ฏใ€ŒTLS ็ต‚ๆญขไปฃ็†ใ€๏ผ‰ๅ‚ณ้žๅˆฐไฝ ็š„ๆ‡‰็”จๅฎนๅ™จ็š„ๅทฅๅ…ทใ€‚ + +### ไธ€ๅ€‹่ฒ ่ผ‰ๅนณ่กกๅ™จ - ๅคšๅ€‹ๅทฅไฝœๅฎนๅ™จ { #one-load-balancer-multiple-worker-containers } + +ไฝฟ็”จ Kubernetes ๆˆ–้กžไผผ็š„ๅˆ†ๆ•ฃๅผๅฎนๅ™จ็ฎก็†็ณป็ตฑๆ™‚๏ผŒไฝฟ็”จๅ…ถๅ…ง้ƒจ็ถฒ่ทฏๆฉŸๅˆถๅฏไปฅ่ฎ“ๅœจไธปใ€ŒๅŸ ๅฃใ€ไธŠ็›ฃ่ฝ็š„ๅ–ฎไธ€ใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€๏ผŒๆŠŠ้€š่จŠ๏ผˆ่ซ‹ๆฑ‚๏ผ‰ๅ‚ณ้ž็ตฆๅฏ่ƒฝ็š„ใ€Œๅคšๅ€‹ๅŸท่กŒไฝ ๆ‡‰็”จ็š„ๅฎนๅ™จใ€ใ€‚ + +ๆฏๅ€‹ๅŸท่กŒไฝ ๆ‡‰็”จ็š„ๅฎนๅ™จ้€šๅธธๅชๆœ‰ใ€Œๅ–ฎไธ€่กŒ็จ‹ใ€๏ผˆไพ‹ๅฆ‚ๅŸท่กŒไฝ ็š„ FastAPI ๆ‡‰็”จ็š„ Uvicorn ่กŒ็จ‹๏ผ‰ใ€‚ๅฎƒๅ€‘้ƒฝๆ˜ฏใ€Œ็›ธๅŒ็š„ๅฎนๅ™จใ€๏ผŒๅŸท่กŒ็›ธๅŒ็š„ๆฑ่ฅฟ๏ผŒไฝ†ๅ„่‡ชๆ“ๆœ‰่‡ชๅทฑ็š„่กŒ็จ‹ใ€่จ˜ๆ†ถ้ซ”็ญ‰ใ€‚ๅฆ‚ๆญคๅณๅฏๅœจ CPU ็š„ใ€ŒไธๅŒๆ ธๅฟƒใ€ใ€็”š่‡ณๆ˜ฏใ€ŒไธๅŒๆฉŸๅ™จใ€ไธŠ็™ผๆฎใ€Œๅนณ่กŒๅŒ–ใ€็š„ๆ•ˆ็›Šใ€‚ + +่€Œๅˆ†ๆ•ฃๅผๅฎนๅ™จ็ณป็ตฑไธญ็š„ใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€ๆœƒใ€Œ่ผชๆตใ€ๆŠŠ่ซ‹ๆฑ‚ๅˆ†้…็ตฆๅ„ๅ€‹ๅŸท่กŒไฝ ๆ‡‰็”จ็š„ๅฎนๅ™จใ€‚ๅ› ๆญค๏ผŒๆฏๅ€‹่ซ‹ๆฑ‚้ƒฝๅฏ่ƒฝ็”ฑๅคšๅ€‹ใ€Œ่ค‡่ฃฝ็š„ๅฎนๅ™จใ€ไธญ็š„ๅ…ถไธญไธ€ๅ€‹ไพ†่™•็†ใ€‚ + +้€šๅธธ้€™ๅ€‹ใ€Œ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€ไนŸ่ƒฝ่™•็†้€ๅพ€ๅข้›†ไธญใ€Œๅ…ถไป–ใ€ๆ‡‰็”จ็š„่ซ‹ๆฑ‚๏ผˆไพ‹ๅฆ‚ไธๅŒ็ถฒๅŸŸ๏ผŒๆˆ–ไธๅŒ URL ่ทฏๅพ‘ๅ‰็ถด๏ผ‰๏ผŒไธฆๆŠŠ้€š่จŠ่ฝ‰้€ๅˆฐ่ฉฒใ€Œๅ…ถไป–ใ€ๆ‡‰็”จๅฐๆ‡‰็š„ๅฎนๅ™จใ€‚ + +### ๆฏๅ€‹ๅฎนๅ™จไธ€ๅ€‹่กŒ็จ‹ { #one-process-per-container } + +ๅœจ้€™็จฎๆƒ…ๅขƒไธญ๏ผŒไฝ ๅคงๆฆ‚ๆœƒๅธŒๆœ›ใ€Œๆฏๅ€‹ๅฎนๅ™จๅชๆœ‰ไธ€ๅ€‹๏ผˆUvicorn๏ผ‰่กŒ็จ‹ใ€๏ผŒๅ› ็‚บไฝ ๅทฒๅœจๅข้›†ๅฑค็ดš่™•็†ไบ†่ค‡ๆœฌใ€‚ + +ๆ‰€ไปฅ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ใ€Œไธๆœƒใ€ๆƒณๅœจๅฎนๅ™จไธญไฝฟ็”จๅคšๅ€‹ workers๏ผˆไพ‹ๅฆ‚็”จ `--workers` ๅ‘ฝไปคๅˆ—้ธ้ …๏ผ‰ใ€‚ไฝ ๆœƒๆƒณๆฏๅ€‹ๅฎนๅ™จๅชๅŸท่กŒใ€Œไธ€ๅ€‹ Uvicorn ่กŒ็จ‹ใ€๏ผˆไฝ†ๅฏ่ƒฝๆœ‰ๅคšๅ€‹ๅฎนๅ™จ๏ผ‰ใ€‚ + +ๅœจๅฎนๅ™จๅ…งๅ†ๆ”พไธ€ๅ€‹่กŒ็จ‹็ฎก็†ๅ™จ๏ผˆๅฆ‚ๅŒๅคš workers ็š„ๆƒ…ๆณ๏ผ‰ๅชๆœƒๅขžๅŠ ใ€Œไธๅฟ…่ฆ็š„่ค‡้›œๅบฆใ€๏ผŒ่€Œไฝ ๅพˆๅฏ่ƒฝๅทฒ็”จๅข้›†็ณป็ตฑ่™•็†ๅฅฝไบ†ใ€‚ + +### ๅคš่กŒ็จ‹ๅฎนๅ™จ่ˆ‡็‰นๆฎŠๆƒ…ๅขƒ { #containers-with-multiple-processes-and-special-cases } + +็•ถ็„ถ๏ผŒๆœ‰ไบ›ใ€Œ็‰นๆฎŠๆƒ…ๆณใ€ไฝ ๅฏ่ƒฝๆœƒๆƒณๅœจใ€Œไธ€ๅ€‹ๅฎนๅ™จๅ…งใ€ๅŸท่กŒๆ•ธๅ€‹ใ€ŒUvicorn worker ่กŒ็จ‹ใ€ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธญ๏ผŒไฝ ๅฏไปฅ็”จ `--workers` ๅ‘ฝไปคๅˆ—้ธ้ …ไพ†่จญๅฎš่ฆๅ•Ÿๅ‹•็š„ workers ๆ•ธ้‡๏ผš + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. ้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จ `--workers` ๅ‘ฝไปคๅˆ—้ธ้ …ๆŠŠ worker ๆ•ธ้‡่จญๅฎš็‚บ 4ใ€‚ + +ไปฅไธ‹ๆ˜ฏไธ€ไบ›ๅˆ็†็š„ไพ‹ๅญ๏ผš + +#### ็ฐกๅ–ฎๆ‡‰็”จ { #a-simple-app } + +ๅฆ‚ๆžœไฝ ็š„ๆ‡‰็”จใ€Œ่ถณๅค ็ฐกๅ–ฎใ€๏ผŒๅฏไปฅๅœจใ€Œๅ–ฎไธ€ไผบๆœๅ™จใ€่€Œ้žๅข้›†ไธŠๅŸท่กŒ๏ผŒไฝ ๅฏ่ƒฝๆœƒๅธŒๆœ›ๅœจๅฎนๅ™จๅ…งไฝฟ็”จ่กŒ็จ‹็ฎก็†ๅ™จใ€‚ + +#### Docker Compose { #docker-compose } + +ๅฆ‚ๆžœไฝ ้ƒจ็ฝฒๅˆฐใ€Œๅ–ฎไธ€ไผบๆœๅ™จใ€๏ผˆ้žๅข้›†๏ผ‰๏ผŒไธ”ไฝฟ็”จใ€ŒDocker Composeใ€๏ผŒ้‚ฃ้บผไฝ ็„กๆณ•่ผ•ๆ˜“๏ผˆ็”จ Docker Compose๏ผ‰ๅœจไฟๆœ‰ๅ…ฑ็”จ็ถฒ่ทฏ่ˆ‡ใ€Œ่ฒ ่ผ‰ๅนณ่กกใ€็š„ๅŒๆ™‚็ฎก็†ๅฎนๅ™จ่ค‡ๆœฌใ€‚ + +้‚ฃไฝ ๅฏ่ƒฝๆœƒๆƒณ่ฆใ€Œๅ–ฎไธ€ๅฎนๅ™จใ€ๆญ้…ใ€Œ่กŒ็จ‹็ฎก็†ๅ™จใ€๏ผŒๅœจๅ…ถไธญๅ•Ÿๅ‹•ใ€Œๅคšๅ€‹ worker ่กŒ็จ‹ใ€ใ€‚ + +--- + +้‡้ปžๆ˜ฏ๏ผŒ้€™ไบ›ใ€Œ้ƒฝไธๆ˜ฏใ€ๅฟ…้ ˆ็›ฒ็›ฎ้ตๅฎˆ็š„ใ€Œ้ตๅพ‹ใ€ใ€‚ไฝ ๅฏไปฅ็”จ้€™ไบ›ๆƒณๆณ•ไพ†ใ€Œ่ฉ•ไผฐไฝ ็š„ไฝฟ็”จๆƒ…ๅขƒใ€๏ผŒไธฆๆฑบๅฎšๅฐไฝ ็š„็ณป็ตฑๆœ€ๅฅฝ็š„ๅšๆณ•๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•็ฎก็†ไปฅไธ‹ๆฆ‚ๅฟต๏ผš + +* ๅฎ‰ๅ…จๆ€ง - HTTPS +* ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ +* ๅคฑๆ•—้‡ๅ•Ÿ +* ่ค‡ๆœฌ๏ผˆๅŸท่กŒ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +* ่จ˜ๆ†ถ้ซ” +* ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +## ่จ˜ๆ†ถ้ซ” { #memory } + +ๅฆ‚ๆžœไฝ ๆŽก็”จใ€Œๆฏๅ€‹ๅฎนๅ™จไธ€ๅ€‹่กŒ็จ‹ใ€๏ผŒ้‚ฃๆฏๅ€‹ๅฎนๅ™จ๏ผˆ่‹ฅๆœ‰่ค‡ๆœฌๅ‰‡ๅคšๅ€‹ๅฎนๅ™จ๏ผ‰ๆ‰€ๆถˆ่€—็š„่จ˜ๆ†ถ้ซ”ๆœƒๆ˜ฏ็›ธๅฐๆ˜Ž็ขบใ€็ฉฉๅฎšไธ”ๆœ‰้™็š„ใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจๅฎนๅ™จ็ฎก็†็ณป็ตฑ๏ผˆไพ‹ๅฆ‚ Kubernetes๏ผ‰็š„่จญๅฎšไธญ็‚บๅฎนๅ™จ่จญๅฎš็›ธๅŒ็š„่จ˜ๆ†ถ้ซ”้™ๅˆถ่ˆ‡้œ€ๆฑ‚ใ€‚ๅฆ‚ๆญค๏ผŒๅฎƒๅฐฑ่ƒฝๅœจใ€Œๅฏ็”จ็š„ๆฉŸๅ™จใ€ไธŠใ€Œ่ค‡่ฃฝๅฎนๅ™จใ€๏ผŒไธฆ่€ƒ้‡ๅฎนๅ™จๆ‰€้œ€็š„่จ˜ๆ†ถ้ซ”้‡่ˆ‡ๅข้›†ไธญๆฉŸๅ™จ็š„ๅฏ็”จ่จ˜ๆ†ถ้ซ”ใ€‚ + +่‹ฅไฝ ็š„ๆ‡‰็”จใ€Œๅพˆ็ฐกๅ–ฎใ€๏ผŒ้€™ๅฏ่ƒฝใ€Œไธๆ˜ฏๅ•้กŒใ€๏ผŒไฝ ๅฏ่ƒฝไธ้œ€่ฆๆŒ‡ๅฎšๅšดๆ ผ็š„่จ˜ๆ†ถ้ซ”้™ๅˆถใ€‚ไฝ†ๅฆ‚ๆžœไฝ ใ€Œไฝฟ็”จๅคง้‡่จ˜ๆ†ถ้ซ”ใ€๏ผˆไพ‹ๅฆ‚ไฝฟ็”จๆฉŸๅ™จๅญธ็ฟ’ๆจกๅž‹๏ผ‰๏ผŒไฝ ๆ‡‰่ฉฒๆชขๆŸฅๅฏฆ้š›ๆถˆ่€—็š„่จ˜ๆ†ถ้ซ”๏ผŒไธฆ่ชฟๆ•ดใ€ŒๆฏๅฐๆฉŸๅ™จไธŠๅŸท่กŒ็š„ๅฎนๅ™จๆ•ธ้‡ใ€๏ผˆไนŸ่จฑ้‚„่ฆ็‚บๅข้›†ๅŠ ๆฉŸๅ™จ๏ผ‰ใ€‚ + +่‹ฅไฝ ๆŽก็”จใ€Œๆฏๅ€‹ๅฎนๅ™จๅคšๅ€‹่กŒ็จ‹ใ€๏ผŒไฝ ๅฐฑๅพ—็ขบไฟๅ•Ÿๅ‹•็š„่กŒ็จ‹ๆ•ธ้‡ไธๆœƒใ€Œ่ถ…้Žๅฏ็”จ่จ˜ๆ†ถ้ซ”ใ€ใ€‚ + +## ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ่ˆ‡ๅฎนๅ™จ { #previous-steps-before-starting-and-containers } + +ๅฆ‚ๆžœไฝ ไฝฟ็”จๅฎนๅ™จ๏ผˆไพ‹ๅฆ‚ Dockerใ€Kubernetes๏ผ‰๏ผŒ้‚ฃๆœ‰ๅ…ฉ็จฎไธป่ฆๅšๆณ•ๅฏ็”จใ€‚ + +### ๅคšๅ€‹ๅฎนๅ™จ { #multiple-containers } + +ๅฆ‚ๆžœไฝ ๆœ‰ใ€Œๅคšๅ€‹ๅฎนๅ™จใ€๏ผŒไธ”ๆฏๅ€‹ๅฎนๅ™จๅคงๆฆ‚้ƒฝๅชๅŸท่กŒใ€Œๅ–ฎไธ€่กŒ็จ‹ใ€๏ผˆไพ‹ๅฆ‚ๅœจไธ€ๅ€‹ Kubernetes ๅข้›†ไธญ๏ผ‰๏ผŒ้‚ฃไฝ ๅฏ่ƒฝๆœƒๆƒณ่ฆไธ€ๅ€‹ใ€Œ็จ็ซ‹็š„ๅฎนๅ™จใ€ไพ†ๅฎŒๆˆใ€Œๅ‰็ฝฎๆญฅ้ฉŸใ€็š„ๅทฅไฝœ๏ผŒไธฆๅชๅœจๅ–ฎไธ€ๅฎนๅ™จใ€ๅ–ฎไธ€่กŒ็จ‹ไธญๅŸท่กŒ๏ผŒๆŽฅ่‘—ๆ‰ๅ•Ÿๅ‹•ๅคšๅ€‹่ค‡ๆœฌ็š„ๅทฅไฝœๅฎนๅ™จใ€‚ + +/// info | ่ณ‡่จŠ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ Kubernetes๏ผŒ้€™ๅคงๆฆ‚ๆœƒๆ˜ฏไธ€ๅ€‹ Init Containerใ€‚ + +/// + +ๅฆ‚ๆžœไฝ ็š„ๆƒ…ๅขƒไธญ๏ผŒ่ฎ“้‚ฃไบ›ๅ‰็ฝฎๆญฅ้ฉŸใ€Œๅนณ่กŒ้‡่ค‡ๅŸท่กŒๅคšๆฌกใ€ๆฒ’ๆœ‰ๅ•้กŒ๏ผˆไพ‹ๅฆ‚ไธๆ˜ฏๅœจ่ท‘่ณ‡ๆ–™ๅบซ้ท็งป๏ผŒ่€Œๅชๆ˜ฏๆชขๆŸฅ่ณ‡ๆ–™ๅบซๆ˜ฏๅฆๅฐฑ็ท’๏ผ‰๏ผŒ้‚ฃไนŸๅฏไปฅๆŠŠ้€™ไบ›ๆญฅ้ฉŸๆ”พๅœจๆฏๅ€‹ๅฎนๅ™จไธญใ€ๅœจๅ•Ÿๅ‹•ไธป่ฆ่กŒ็จ‹ๅ‰ๅŸท่กŒใ€‚ + +### ๅ–ฎไธ€ๅฎนๅ™จ { #single-container } + +ๅฆ‚ๆžœไฝ ็š„ๆžถๆง‹ๅพˆ็ฐกๅ–ฎ๏ผŒๅชๆœ‰ใ€Œๅ–ฎไธ€ๅฎนๅ™จใ€๏ผŒๆŽฅ่‘—ๅœจๅ…ถไธญๅ•Ÿๅ‹•ๅคšๅ€‹ใ€Œworker ่กŒ็จ‹ใ€๏ผˆๆˆ–ไนŸๅฏ่ƒฝๅฐฑไธ€ๅ€‹่กŒ็จ‹๏ผ‰๏ผŒ้‚ฃไฝ ๅฏไปฅๅœจ็›ธๅŒ็š„ๅฎนๅ™จไธญใ€ๆ–ผๅ•Ÿๅ‹•ๆ‡‰็”จ่กŒ็จ‹ๅ‰ๅ…ˆๅŸท่กŒ้€™ไบ›ๅ‰็ฝฎๆญฅ้ฉŸใ€‚ + +### ๅŸบๅบ• Docker ๆ˜ ๅƒ { #base-docker-image } + +ๆ›พ็ถ“ๆœ‰ไธ€ๅ€‹ๅฎ˜ๆ–น็š„ FastAPI Docker ๆ˜ ๅƒ๏ผštiangolo/uvicorn-gunicorn-fastapiใ€‚ไฝ†็พๅœจๅทฒ่ขซๆฃ„็”จใ€‚โ›”๏ธ + +ไฝ ๅคงๆฆ‚ใ€Œไธๆ‡‰่ฉฒใ€ไฝฟ็”จ้€™ๅ€‹ๅŸบๅบ• Docker ๆ˜ ๅƒ๏ผˆๆˆ–ๅ…ถไป–้กžไผผ็š„๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ Kubernetes๏ผˆๆˆ–ๅ…ถไป–๏ผ‰ไธฆๅทฒๅœจๅข้›†ๅฑค็ดš่จญๅฎšใ€Œ่ค‡ๆœฌใ€ใ€ไฝฟ็”จๅคšๅ€‹ใ€Œๅฎนๅ™จใ€ใ€‚ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒๆ›ดๅฅฝ็š„ๅšๆณ•ๆ˜ฏๅฆ‚ไธŠๆ‰€่ฟฐ[ๅพž้›ถๅปบ็ฝฎๆ˜ ๅƒ](#build-a-docker-image-for-fastapi)ใ€‚ + +่‹ฅไฝ ้œ€่ฆๅคšๅ€‹ workers๏ผŒๅช่ฆไฝฟ็”จ `--workers` ๅ‘ฝไปคๅˆ—้ธ้ …ๅณๅฏใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +้€™ๅ€‹ Docker ๆ˜ ๅƒๆ˜ฏๅœจ Uvicorn ๅฐšๆœชๆ”ฏๆด็ฎก็†่ˆ‡้‡ๅ•Ÿๆญปไบก workers ็š„ๅนดไปฃๆ‰€ๅปบ็ซ‹๏ผŒๅ› ๆญค้œ€่ฆ็”จ Gunicorn ๆญ้… Uvicorn๏ผŒ็‚บไบ†่ฎ“ Gunicorn ็ฎก็†ไธฆ้‡ๅ•Ÿ Uvicorn workers๏ผŒ่€Œๅผ•ๅ…ฅไบ†็›ธ็•ถๅคš็š„่ค‡้›œๅบฆใ€‚ + +ไฝ†็พๅœจ Uvicorn๏ผˆไปฅๅŠ `fastapi` ๆŒ‡ไปค๏ผ‰ๅทฒๆ”ฏๆดไฝฟ็”จ `--workers`๏ผŒๅ› ๆญคๆฒ’ๆœ‰็†็”ฑไฝฟ็”จไธ€ๅ€‹ๅŸบๅบ• Docker ๆ˜ ๅƒ๏ผŒ่€Œไธๆ˜ฏๅปบ็ฝฎไฝ ่‡ชๅทฑ็š„๏ผˆ่€Œไธ”ๅฏฆ้š›ไธŠ็จ‹ๅผ็ขผ้‡ไนŸๅทฎไธๅคš ๐Ÿ˜…๏ผ‰ใ€‚ + +/// + +## ้ƒจ็ฝฒๅฎนๅ™จๆ˜ ๅƒ { #deploy-the-container-image } + +ๆ“ๆœ‰ๅฎนๅ™จ๏ผˆDocker๏ผ‰ๆ˜ ๅƒๅพŒ๏ผŒๆœ‰ๅคš็จฎ้ƒจ็ฝฒๆ–นๅผใ€‚ + +ไพ‹ๅฆ‚๏ผš + +* ๅœจๅ–ฎไธ€ไผบๆœๅ™จไธŠไฝฟ็”จ Docker Compose +* ไฝฟ็”จ Kubernetes ๅข้›† +* ไฝฟ็”จ Docker Swarm Mode ๅข้›† +* ไฝฟ็”จๅƒ Nomad ไน‹้กž็š„ๅ…ถไป–ๅทฅๅ…ท +* ไฝฟ็”จๆœƒๆŽฅๆ”ถไฝ ็š„ๅฎนๅ™จๆ˜ ๅƒไธฆไปฃ็‚บ้ƒจ็ฝฒ็š„้›ฒ็ซฏๆœๅ‹™ + +## ไฝฟ็”จ `uv` ็š„ Docker ๆ˜ ๅƒ { #docker-image-with-uv } + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ uv ไพ†ๅฎ‰่ฃ่ˆ‡็ฎก็†ๅฐˆๆกˆ๏ผŒไฝ ๅฏไปฅๅƒ่€ƒไป–ๅ€‘็š„ uv Docker ๆŒ‡ๅ—ใ€‚ + +## ็ธฝ็ต { #recap } + +ไฝฟ็”จๅฎนๅ™จ็ณป็ตฑ๏ผˆไพ‹ๅฆ‚ Docker ่ˆ‡ Kubernetes๏ผ‰ๅฏไปฅ็›ธๅฐ็›ดๆŽฅๅœฐ่™•็†ๆ‰€ๆœ‰ใ€Œ้ƒจ็ฝฒๆฆ‚ๅฟตใ€๏ผš + +* HTTPS +* ้–‹ๆฉŸ่‡ชๅ‹•ๅŸท่กŒ +* ๅคฑๆ•—้‡ๅ•Ÿ +* ่ค‡ๆœฌ๏ผˆๅŸท่กŒ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +* ่จ˜ๆ†ถ้ซ” +* ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +ๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๅคงๆฆ‚ไธๆœƒๆƒณ็”จไปปไฝ•ๅŸบๅบ•ๆ˜ ๅƒ๏ผŒ่€Œๆ˜ฏใ€Œๅพž้›ถๅปบ็ฝฎๅฎนๅ™จๆ˜ ๅƒใ€๏ผŒไปฅๅฎ˜ๆ–น็š„ Python Docker ๆ˜ ๅƒ็‚บๅŸบ็คŽใ€‚ + +ๅ–„็”จ `Dockerfile` ไธญๆŒ‡ไปค็š„ใ€Œ้ †ๅบใ€่ˆ‡ใ€ŒDocker ๅฟซๅ–ใ€๏ผŒไฝ ๅฏไปฅใ€Œๆœ€ๅฐๅŒ–ๅปบ็ฝฎๆ™‚้–“ใ€๏ผŒๆๅ‡็”Ÿ็”ขๅŠ›๏ผˆไธฆ้ฟๅ…็„ก่Š๏ผ‰ใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/deployment/fastapicloud.md b/docs/zh-hant/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..5663590d14 --- /dev/null +++ b/docs/zh-hant/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +ไฝ ๅฏไปฅ็”จใ€Œไธ€่กŒๆŒ‡ไปคใ€ๆŠŠไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผ้ƒจ็ฝฒๅˆฐ FastAPI Cloudใ€‚ๅฆ‚ๆžœไฝ ้‚„ๆฒ’ๅŠ ๅ…ฅ๏ผŒๅฟซๅŽป็™ป่จ˜็ญ‰ๅ€™ๅๅ–ฎๅง๏ผ๐Ÿš€ + +## ็™ปๅ…ฅ { #login } + +่ซ‹ๅ…ˆ็ขบ่ชไฝ ๅทฒ็ถ“ๆœ‰ **FastAPI Cloud** ๅธณ่™Ÿ๏ผˆๆˆ‘ๅ€‘ๅทฒๅพž็ญ‰ๅ€™ๅๅ–ฎ้‚€่ซ‹ไฝ  ๐Ÿ˜‰๏ผ‰ใ€‚ + +็„ถๅพŒ็™ปๅ…ฅ๏ผš + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## ้ƒจ็ฝฒ { #deploy } + +็พๅœจ็”จใ€Œไธ€่กŒๆŒ‡ไปคใ€้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ๅฐฑ้€™ๆจฃ๏ผ็พๅœจไฝ ๅฏไปฅ้€้Ž่ฉฒ URL ้€ ่จชไฝ ็š„ๆ‡‰็”จใ€‚โœจ + +## ้—œๆ–ผ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ็”ฑ **FastAPI** ็š„ไฝœ่€…่ˆ‡ๅœ˜้šŠๆ‰“้€ ใ€‚ + +ๅฎƒไปฅๆœ€ๅฐ‘็š„ๅฟƒๅŠ›๏ผŒ็ฒพ็ฐกๅŒ–ๅปบ็ซ‹ใ€้ƒจ็ฝฒ่ˆ‡ๅญ˜ๅ– API ็š„ๆต็จ‹ใ€‚ + +ๅฎƒๆŠŠไฝฟ็”จ FastAPI ้–‹็™ผๆ‡‰็”จ็š„ๅ„ช็•ฐ้–‹็™ผ้ซ”้ฉ—๏ผŒๅปถไผธๅˆฐๅฐ‡ๅฎƒๅ€‘้ƒจ็ฝฒๅˆฐ้›ฒ็ซฏใ€‚๐ŸŽ‰ + +ๅฎƒไนŸๆœƒ็‚บไฝ ่™•็†้ƒจ็ฝฒๆ‡‰็”จๆ™‚ๅคšๆ•ธ้œ€่ฆ้ขๅฐ็š„ไบ‹้ …๏ผŒไพ‹ๅฆ‚๏ผš + +* HTTPS +* ๅคšๅ‰ฏๆœฌ๏ผŒไธฆๅฏไพๆ“š่ซ‹ๆฑ‚่‡ชๅ‹•ๆ“ด็ธฎ +* ็ญ‰็ญ‰ใ€‚ + +FastAPI Cloud ๆ˜ฏ *FastAPI and friends* ้–‹ๆบๅฐˆๆกˆ็š„ไธป่ฆ่ดŠๅŠฉ่€…่ˆ‡่ณ‡้‡‘ๆไพ›่€…ใ€‚โœจ + +## ้ƒจ็ฝฒๅˆฐๅ…ถไป–้›ฒ็ซฏไพ›ๆ‡‰ๅ•† { #deploy-to-other-cloud-providers } + +FastAPI ๆ˜ฏๅŸบๆ–ผๆจ™ๆบ–็š„้–‹ๆบๅฐˆๆกˆใ€‚ไฝ ๅฏไปฅๆŠŠ FastAPI ๆ‡‰็”จ้ƒจ็ฝฒๅˆฐไฝ ้ธๆ“‡็š„ไปปไฝ•้›ฒ็ซฏไพ›ๆ‡‰ๅ•†ใ€‚ + +่ซ‹ไพ็…งไฝ ็š„้›ฒ็ซฏไพ›ๆ‡‰ๅ•†็š„ๆŒ‡ๅ—๏ผŒไฝฟ็”จไป–ๅ€‘็š„ๆ–นๅผ้ƒจ็ฝฒ FastAPI ๆ‡‰็”จใ€‚๐Ÿค“ + +## ้ƒจ็ฝฒๅˆฐไฝ ่‡ชๅทฑ็š„ไผบๆœๅ™จ { #deploy-your-own-server } + +ๅœจ้€™ไปฝใ€Œ้ƒจ็ฝฒใ€ๆŒ‡ๅ—็š„ๅพŒ็บŒๅ…งๅฎนไธญ๏ผŒๆˆ‘ไนŸๆœƒๆ•™ไฝ ๆ‰€ๆœ‰็ดฐ็ฏ€๏ผŒ่ฎ“ไฝ ไบ†่งฃ่ƒŒๅพŒ็™ผ็”Ÿไบ†ไป€้บผใ€้œ€่ฆๅšๅ“ชไบ›ไบ‹๏ผŒไปฅๅŠๅฆ‚ไฝ•่‡ช่กŒ้ƒจ็ฝฒ FastAPI ๆ‡‰็”จ๏ผŒๅŒ…ๆ‹ฌๅœจไฝ ่‡ชๅทฑ็š„ไผบๆœๅ™จไธŠใ€‚๐Ÿค“ diff --git a/docs/zh-hant/docs/deployment/https.md b/docs/zh-hant/docs/deployment/https.md new file mode 100644 index 0000000000..0934b02831 --- /dev/null +++ b/docs/zh-hant/docs/deployment/https.md @@ -0,0 +1,231 @@ +# ้—œๆ–ผ HTTPS { #about-https } + +ไบบๅ€‘ๅพˆๅฎนๆ˜“ไปฅ็‚บ HTTPS ๅชๆ˜ฏใ€Œๅ•Ÿ็”จๆˆ–ๆœชๅ•Ÿ็”จใ€็š„ๅŠŸ่ƒฝใ€‚ + +ไฝ†ๅฏฆ้š›ไธŠ่ค‡้›œๅพ—ๅคšใ€‚ + +/// tip + +ๅฆ‚ๆžœไฝ ่ถ•ๆ™‚้–“ๆˆ–ไธๅœจๆ„็ดฐ็ฏ€๏ผŒๅฏไปฅ็›ดๆŽฅ็œ‹ๅพŒ็บŒ็ซ ็ฏ€๏ผŒไพ็…ง้€ๆญฅๆŒ‡ๅผ•็”จไธๅŒๆ–นๅผๅฎŒๆˆ่จญๅฎšใ€‚ + +/// + +ๆƒณๅพžไฝฟ็”จ่€…่ง’ๅบฆๅญธ็ฟ’ HTTPS ๅŸบ็คŽ๏ผŒ่ซ‹ๅƒ่€ƒ https://howhttps.works/ใ€‚ + +ๆŽฅ่‘—ไปฅ้–‹็™ผ่€…่ง’ๅบฆ๏ผŒ่ซ‡ๅนพๅ€‹้—œๆ–ผ HTTPS ้œ€่ฆๆณจๆ„็š„้‡้ปž๏ผš + +* ๅฐๆ–ผ HTTPS๏ผŒไผบๆœๅ™จ้œ€่ฆๆ“ๆœ‰็”ฑ**็ฌฌไธ‰ๆ–น**็ฐฝ็™ผ็š„**ใ€Œๆ†‘่ญ‰ใ€**ใ€‚ + * ้€™ไบ›ๆ†‘่ญ‰ๅฏฆ้š›ไธŠๆ˜ฏๅ‘็ฌฌไธ‰ๆ–น**ๅ–ๅพ—**๏ผŒไธๆ˜ฏใ€Œ่‡ชๅทฑ็”ข็”Ÿใ€ใ€‚ +* ๆ†‘่ญ‰ๆœ‰**ๆœ‰ๆ•ˆๆœŸ**ใ€‚ + * ๆœƒ**้ŽๆœŸ**ใ€‚ + * ้ŽๆœŸๅพŒ้œ€่ฆ**็บŒๆœŸ**๏ผŒไนŸๅฐฑๆ˜ฏๅ†ๅ‘็ฌฌไธ‰ๆ–น**้‡ๆ–ฐๅ–ๅพ—**ใ€‚ +* ้€ฃ็ทšๅŠ ๅฏ†็™ผ็”Ÿๅœจ **TCP ๅฑค**ใ€‚ + * ้‚ฃๆ˜ฏๅœจ **HTTP ็š„ไธ‹ไธ€ๅฑค**ใ€‚ + * ๅ› ๆญค๏ผŒ**ๆ†‘่ญ‰่ˆ‡ๅŠ ๅฏ†**็š„่™•็†ๆœƒๅœจ **้€ฒๅ…ฅ HTTP ไน‹ๅ‰**ๅฎŒๆˆใ€‚ +* **TCP ไธ็Ÿฅ้“ใ€Œ็ถฒๅŸŸใ€**๏ผŒๅช็Ÿฅ้“ IP ไฝๅ€ใ€‚ + * ้—œๆ–ผ**็‰นๅฎš็ถฒๅŸŸ**็š„่ณ‡่จŠๆœƒๆ”พๅœจ **HTTP ่ณ‡ๆ–™**ไธญใ€‚ +* **HTTPS ๆ†‘่ญ‰**ๆ˜ฏ็‚บๆŸๅ€‹**็‰นๅฎš็ถฒๅŸŸ**่ƒŒๆ›ธ๏ผŒไฝ†้€š่จŠๅ”ๅฎš่ˆ‡ๅŠ ๅฏ†ๅœจ TCP ๅฑค้€ฒ่กŒ๏ผŒ็™ผ็”Ÿๅœจ**ๅฐšๆœช็Ÿฅ้“**่ฆ่™•็†ๅ“ชๅ€‹็ถฒๅŸŸไน‹ๅ‰ใ€‚ +* **้ ่จญ**ๆƒ…ๆณไธ‹๏ผŒ้€™่กจ็คบไฝ ๆฏๅ€‹ IP ไฝๅ€**ๅช่ƒฝ**ไฝฟ็”จ**ไธ€ๅผต HTTPS ๆ†‘่ญ‰**ใ€‚ + * ไธ่ซ–ไฝ ็š„ไผบๆœๅ™จๅคšๅผทๆˆ–ไฝ ๅœจไธŠ้ข่ท‘็š„ๆ‡‰็”จๅคšๅฐใ€‚ + * ไธ้Ž๏ผŒ้€™ๆ˜ฏๆœ‰**่งฃๆณ•**็š„ใ€‚ +* ๅœจ **TLS** ๅ”ๅฎš๏ผˆๅœจ HTTP ไน‹ๅ‰ๆ–ผ TCP ๅฑค่™•็†ๅŠ ๅฏ†็š„ๅ”ๅฎš๏ผ‰ไธŠๆœ‰ๅ€‹**ๆ“ดๅ……**็จฑ็‚บ **SNI**ใ€‚ + * ้€™ๅ€‹ SNI ๆ“ดๅ……่ฎ“ๅ–ฎไธ€ไผบๆœๅ™จ๏ผˆๅ–ฎไธ€ IP ไฝๅ€๏ผ‰ๅฏไปฅๆ“ๆœ‰**ๅคšๅผต HTTPS ๆ†‘่ญ‰**๏ผŒไธฆๆœๅ‹™**ๅคšๅ€‹ HTTPS ็ถฒๅŸŸ๏ผๆ‡‰็”จ**ใ€‚ + * ่ฆ่ฎ“ๅฎƒ้‹ไฝœ๏ผŒไผบๆœๅ™จไธŠๅฟ…้ ˆๆœ‰ไธ€ๅ€‹**ๅ–ฎไธ€**็š„ๅ…ƒไปถ๏ผˆ็จ‹ๅผ๏ผ‰ๅœจ**ๅ…ฌ็”จ IP**ไธŠ็›ฃ่ฝ๏ผŒไธ”ๆŒๆœ‰ไผบๆœๅ™จไธŠ็š„**ๆ‰€ๆœ‰ HTTPS ๆ†‘่ญ‰**ใ€‚ +* ๅœจๅ–ๅพ—ๅฎ‰ๅ…จ้€ฃ็ทš**ไน‹ๅพŒ**๏ผŒ้€š่จŠๅ”ๅฎš**ไป็„ถๆ˜ฏ HTTP**ใ€‚ + * ้›–็„ถ้€้Ž **HTTP ๅ”ๅฎš**ๅ‚ณ้€๏ผŒไฝ†ๅ…งๅฎนๆ˜ฏ**ๅŠ ๅฏ†**็š„ใ€‚ + +ๅธธ่ฆ‹ๅšๆณ•ๆ˜ฏ่ฎ“ไผบๆœๅ™จ๏ผˆๆฉŸๅ™จใ€ไธปๆฉŸ็ญ‰๏ผ‰ไธŠ่ท‘**ไธ€ๅ€‹็จ‹ๅผ๏ผHTTP ไผบๆœๅ™จ**ไพ†**็ฎก็†ๆ‰€ๆœ‰ HTTPS ็›ธ้—œๅทฅไฝœ**๏ผšๆŽฅๆ”ถ**ๅŠ ๅฏ†็š„ HTTPS ่ซ‹ๆฑ‚**ใ€ๅฐ‡ๅ…ถ**่งฃๅฏ†**ๆˆ**็ด” HTTP ่ซ‹ๆฑ‚**่ฝ‰ไบค็ตฆๅŒๅฐไผบๆœๅ™จไธŠๅฏฆ้š›้‹่กŒ็š„ HTTP ๆ‡‰็”จ๏ผˆๆœฌไพ‹็‚บ **FastAPI** ๆ‡‰็”จ๏ผ‰ใ€ๅพžๆ‡‰็”จๅ–ๅพ— **HTTP ๅ›žๆ‡‰**ใ€ๅ†็”จๅˆ้ฉ็š„ **HTTPS ๆ†‘่ญ‰**ๅฐ‡ๅ…ถ**ๅŠ ๅฏ†**ไธฆไปฅ **HTTPS** ๅ‚ณๅ›ž็ตฆ็”จๆˆถ็ซฏใ€‚้€™้กžไผบๆœๅ™จๅธธ่ขซ็จฑ็‚บ **TLS ็ต‚ๆญขไปฃ็† (TLS Termination Proxy)**ใ€‚ + +ๅฏไฝœ็‚บ TLS ็ต‚ๆญขไปฃ็†็š„้ธ้ …ๅŒ…ๆ‹ฌ๏ผš + +* Traefik๏ผˆไนŸๅฏ่™•็†ๆ†‘่ญ‰็บŒๆœŸ๏ผ‰ +* Caddy๏ผˆไนŸๅฏ่™•็†ๆ†‘่ญ‰็บŒๆœŸ๏ผ‰ +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +ๅœจ Let's Encrypt ไน‹ๅ‰๏ผŒ้€™ไบ› **HTTPS ๆ†‘่ญ‰**ๆ˜ฏ็”ฑๅ—ไฟกไปป็š„็ฌฌไธ‰ๆ–น่ฒฉๅ”ฎใ€‚ + +ๅ–ๅพ—้€™ไบ›ๆ†‘่ญ‰็š„ๆต็จ‹้ŽๅŽป็›ธ็•ถ็น็‘ฃ๏ผŒ้œ€่ฆ่จฑๅคšๆ‰‹็บŒ๏ผŒไธ”ๆ†‘่ญ‰็›ธ็•ถๆ˜‚่ฒดใ€‚ + +ไน‹ๅพŒๅ‡บ็พไบ† **Let's Encrypt**ใ€‚ + +ๅฎƒๆ˜ฏ Linux Foundation ็š„ๅฐˆๆกˆ๏ผŒ่ƒฝ**ๅ…่ฒป**ไธ”่‡ชๅ‹•ๅŒ–ๅœฐๆไพ› **HTTPS ๆ†‘่ญ‰**ใ€‚้€™ไบ›ๆ†‘่ญ‰ๆŽก็”จๆจ™ๆบ–็š„ๅฏ†็ขผๅญธๅฎ‰ๅ…จๆฉŸๅˆถ๏ผŒไธ”ๆœ‰ๆ•ˆๆœŸ่ผƒ็Ÿญ๏ผˆ็ด„ 3 ๅ€‹ๆœˆ๏ผ‰๏ผŒๅ› ๆญคๅ› ็‚บๅฃฝๅ‘ฝ็Ÿญ๏ผŒ**ๅฎ‰ๅ…จๆ€งๅ…ถๅฏฆๆ›ดๅฅฝ**ใ€‚ + +็ถฒๅŸŸๆœƒ่ขซๅฎ‰ๅ…จ้ฉ—่ญ‰๏ผŒๆ†‘่ญ‰ๆœƒ่‡ชๅ‹•็”ข็”Ÿใ€‚้€™ไนŸ่ฎ“ๆ†‘่ญ‰็บŒๆœŸๅพ—ไปฅ่‡ชๅ‹•ๅŒ–ใ€‚ + +็›ฎๆจ™ๆ˜ฏ่ฎ“ๆ†‘่ญ‰็š„็”ณ่ซ‹่ˆ‡็บŒๆœŸ่‡ชๅ‹•ๅŒ–๏ผŒ่ฎ“ไฝ **ๆฐธ้ ๅ…่ฒปไฝฟ็”จๅฎ‰ๅ…จ็š„ HTTPS**ใ€‚ + +## ็ตฆ้–‹็™ผ่€…็š„ HTTPS { #https-for-developers } + +ไปฅไธ‹ไปฅ้€ๆญฅ็ฏ„ไพ‹่ชชๆ˜Žไธ€ๅ€‹ HTTPS API ๅฏ่ƒฝ้•ทไป€้บผๆจฃๅญ๏ผŒ่‘—้‡ๆ–ผๅฐ้–‹็™ผ่€…้‡่ฆ็š„ๆฆ‚ๅฟตใ€‚ + +### ็ถฒๅŸŸๅ็จฑ { #domain-name } + +้€šๅธธๆœƒๅ…ˆ**ๅ–ๅพ—**ไธ€ๅ€‹**็ถฒๅŸŸๅ็จฑ**๏ผŒๆŽฅ่‘—ๅœจ DNS ไผบๆœๅ™จ๏ผˆๅฏ่ƒฝๆ˜ฏๅŒไธ€ๅ€‹้›ฒ็ซฏไพ›ๆ‡‰ๅ•†๏ผ‰ไธญ่จญๅฎšๅฎƒใ€‚ + +ไฝ ๅฏ่ƒฝๆœƒ็งŸไธ€ๅฐ้›ฒ็ซฏไผบๆœๅ™จ๏ผˆ่™›ๆ“ฌๆฉŸ๏ผ‰ๆˆ–้กžไผผ็š„ๆœๅ‹™๏ผŒไธฆๆ“ๆœ‰ไธ€ๅ€‹ๅ›บๅฎš็š„**ๅ…ฌ็”จ IP ไฝๅ€**ใ€‚ + +ๅœจ DNS ไผบๆœๅ™จไธญ๏ผŒไฝ ๆœƒ่จญๅฎšไธ€ๅ€‹็ด€้Œ„๏ผˆใ€Œ`A record`ใ€๏ผ‰ๆŒ‡ๅ‘**ไฝ ็š„็ถฒๅŸŸ**ๆ‰€ๅฐๆ‡‰็š„**ไผบๆœๅ™จๅ…ฌ็”จ IP ไฝๅ€**ใ€‚ + +้€™้€šๅธธๅœจๅˆๆฌกๅปบ็ฝฎๆ™‚่จญๅฎšไธ€ๆฌกๅณๅฏใ€‚ + +/// tip + +ใ€Œ็ถฒๅŸŸๅ็จฑใ€ๆ˜ฏ็™ผ็”Ÿๅœจ HTTPS ไน‹ๅ‰็š„ไบ‹ๆƒ…๏ผŒไฝ†ไธ€ๅˆ‡้ƒฝไพ่ณด็ถฒๅŸŸ่ˆ‡ IP ไฝๅ€๏ผŒๅ› ๆญคๅœจๆญคไธ€ไฝต่ชชๆ˜Žใ€‚ + +/// + +### DNS { #dns } + +็พๅœจ่š็„ฆๅœจๅฏฆ้š›็š„ HTTPS ้ƒจๅˆ†ใ€‚ + +้ฆ–ๅ…ˆ๏ผŒ็€่ฆฝๅ™จๆœƒๅ‘ **DNS ไผบๆœๅ™จ**ๆŸฅ่ฉข่ฉฒ**็ถฒๅŸŸ็š„ IP**๏ผŒไพ‹ๅฆ‚ `someapp.example.com`ใ€‚ + +DNS ไผบๆœๅ™จๆœƒๅ›ž่ฆ†่ฆไฝฟ็”จ็š„**IP ไฝๅ€**๏ผŒ้‚ฃๅฐฑๆ˜ฏไฝ ๅœจ DNS ไผบๆœๅ™จไธญ่จญๅฎš็š„ใ€ไผบๆœๅ™จๅฐๅค–็š„ๅ…ฌ็”จ IP ไฝๅ€ใ€‚ + + + +### TLS ๆกๆ‰‹้–‹ๅง‹ { #tls-handshake-start } + +ๆŽฅ่‘—็€่ฆฝๅ™จๆœƒ้€ฃ็ทšๅˆฐ่ฉฒ IP ็š„ **443 ๅŸ **๏ผˆHTTPS ้ ่จญๅŸ ๏ผ‰ใ€‚ + +้€š่จŠ็š„็ฌฌไธ€้ƒจๅˆ†ๆ˜ฏๅปบ็ซ‹็”จๆˆถ็ซฏ่ˆ‡ไผบๆœๅ™จไน‹้–“็š„้€ฃ็ทš๏ผŒไธฆๅ”ๅ•†่ฆไฝฟ็”จๅ“ชไบ›้‡‘้‘ฐ็ญ‰ๅฏ†็ขผๅƒๆ•ธใ€‚ + + + +็”จๆˆถ็ซฏ่ˆ‡ไผบๆœๅ™จ็‚บๅปบ็ซ‹ TLS ้€ฃ็ทš่€Œ้€ฒ่กŒ็š„้€™ๆฎตไบ’ๅ‹•็จฑ็‚บ **TLS ๆกๆ‰‹**ใ€‚ + +### ๅธถ SNI ๆ“ดๅ……็š„ TLS { #tls-with-sni-extension } + +ๅœจ็‰นๅฎš็š„**IP ไฝๅ€**่ˆ‡็‰นๅฎš**ๅŸ **ไธŠ๏ผŒๅŒไธ€ๆ™‚้–“**ๅช่ƒฝๆœ‰ไธ€ๅ€‹่กŒ็จ‹**ๅœจ็›ฃ่ฝใ€‚ๅฏไปฅๅœจๅŒไธ€ๅ€‹ IP ไธŠ็›ฃ่ฝไธๅŒๅŸ ๏ผŒไฝ†ๆฏๅ€‹ IP ่ˆ‡ๅŸ ็š„็ต„ๅˆๅช่ƒฝๆœ‰ไธ€ๅ€‹่กŒ็จ‹ใ€‚ + +TLS๏ผˆHTTPS๏ผ‰้ ่จญไฝฟ็”จ `443` ๅŸ ๏ผŒๅ› ๆญคๆˆ‘ๅ€‘้œ€่ฆ็”จๅˆฐ้€™ๅ€‹ๅŸ ใ€‚ + +็”ฑๆ–ผๅช่ƒฝๆœ‰ไธ€ๅ€‹่กŒ็จ‹็›ฃ่ฝ่ฉฒๅŸ ๏ผŒ่ฒ ่ฒฌ็›ฃ่ฝ็š„ๆœƒๆ˜ฏ **TLS ็ต‚ๆญขไปฃ็†**ใ€‚ + +TLS ็ต‚ๆญขไปฃ็†ๆœƒๅญ˜ๅ–ไธ€ๅผตๆˆ–ๅคšๅผต **TLS ๆ†‘่ญ‰**๏ผˆHTTPS ๆ†‘่ญ‰๏ผ‰ใ€‚ + +้€้ŽไธŠ้ขๆๅˆฐ็š„ **SNI ๆ“ดๅ……**๏ผŒTLS ็ต‚ๆญขไปฃ็†ๆœƒๆ นๆ“š็”จๆˆถ็ซฏ้ ๆœŸ็š„็ถฒๅŸŸ๏ผŒๅพžๅฏ็”จ็š„ TLS๏ผˆHTTPS๏ผ‰ๆ†‘่ญ‰ไธญๆŒ‘้ธๆœฌๆฌก้€ฃ็ทš่ฆ็”จ็š„ๆ†‘่ญ‰ใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๆœƒไฝฟ็”จ `someapp.example.com` ็š„ๆ†‘่ญ‰ใ€‚ + + + +็”จๆˆถ็ซฏ**ไฟกไปป**็ฐฝ็™ผ่ฉฒ TLS ๆ†‘่ญ‰็š„ๅ–ฎไฝ๏ผˆๆœฌไพ‹็‚บ Let's Encrypt๏ผŒ็จๅพŒๆœƒๅ†่ซ‡๏ผ‰๏ผŒๅ› ๆญคๅฏไปฅ**้ฉ—่ญ‰**ๆ†‘่ญ‰ๆœ‰ๆ•ˆใ€‚ + +ๆŽฅ่‘—๏ผŒ็”จๆˆถ็ซฏ่ˆ‡ TLS ็ต‚ๆญขไปฃ็†ๆœƒไปฅ่ฉฒๆ†‘่ญ‰็‚บๅŸบ็คŽ๏ผŒ**ๅ”ๅ•†ๅพŒ็บŒๅฆ‚ไฝ•ๅŠ ๅฏ†**ๆ•ดๆฎต **TCP ้€š่จŠ**ใ€‚่‡ณๆญคๅฎŒๆˆ **TLS ๆกๆ‰‹**ใ€‚ + +ไน‹ๅพŒ๏ผŒ็”จๆˆถ็ซฏ่ˆ‡ไผบๆœๅ™จไน‹้–“ๅฐฑๆœ‰ไธ€ๆข**ๅทฒๅŠ ๅฏ†็š„ TCP ้€ฃ็ทš**๏ผŒ้€™ๅฐฑๆ˜ฏ TLS ๆ‰€ๆไพ›็š„่ƒฝๅŠ›ใ€‚ๆŽฅ่‘—ไป–ๅ€‘ๅฏไปฅๅœจ้€™ๆข้€ฃ็ทšไธŠ้–‹ๅง‹ๅฏฆ้š›็š„ **HTTP** ้€š่จŠใ€‚ + +้€™ไนŸๅฐฑๆ˜ฏ **HTTPS** ็š„ๆœฌ่ณช๏ผšๅœจ**ๅฎ‰ๅ…จ็š„ TLS ้€ฃ็ทš**ๅ…งๅ‚ณ้€ไธ€่ˆฌ็š„ **HTTP**๏ผŒ่€Œ้žๅœจ็ด”๏ผˆๆœชๅŠ ๅฏ†๏ผ‰็š„ TCP ้€ฃ็ทšไธŠใ€‚ + +/// tip + +่ซ‹ๆณจๆ„๏ผŒๅŠ ๅฏ†็™ผ็”Ÿๅœจ **TCP ๅฑค**๏ผŒไธๆ˜ฏๅœจ HTTP ๅฑคใ€‚ + +/// + +### HTTPS ่ซ‹ๆฑ‚ { #https-request } + +็พๅœจ็”จๆˆถ็ซฏ่ˆ‡ไผบๆœๅ™จ๏ผˆๆ›ด็ฒพ็ขบๅœฐ่ชช๏ผŒๆ˜ฏ็€่ฆฝๅ™จ่ˆ‡ TLS ็ต‚ๆญขไปฃ็†๏ผ‰ไน‹้–“ๅทฒๆœ‰**ๅŠ ๅฏ†็š„ TCP ้€ฃ็ทš**๏ผŒไป–ๅ€‘ๅฏไปฅ้–‹ๅง‹้€ฒ่กŒ **HTTP** ้€š่จŠใ€‚ + +ๅ› ๆญค๏ผŒ็”จๆˆถ็ซฏ้€ๅ‡บไธ€ๅ€‹ **HTTPS ่ซ‹ๆฑ‚**ใ€‚ๅฎƒๅ…ถๅฏฆๅฐฑๆ˜ฏ้€้ŽๅŠ ๅฏ†็š„ TLS ้€ฃ็ทš็™ผ้€็š„ไธ€ๅ€‹ HTTP ่ซ‹ๆฑ‚ใ€‚ + + + +### ่งฃๅฏ†่ซ‹ๆฑ‚ { #decrypt-the-request } + +TLS ็ต‚ๆญขไปฃ็†ๆœƒไพ็…งๅ…ˆๅ‰ๅ”ๅ•†็š„ๆ–นๅผ**่งฃๅฏ†่ซ‹ๆฑ‚**๏ผŒไธฆๅฐ‡**็ด”๏ผˆๅทฒ่งฃๅฏ†๏ผ‰็š„ HTTP ่ซ‹ๆฑ‚**่ฝ‰ไบค็ตฆ้‹่กŒๆ‡‰็”จ็š„่กŒ็จ‹๏ผˆไพ‹ๅฆ‚ไปฅ Uvicorn ๅŸท่กŒ็š„ FastAPI ๆ‡‰็”จ่กŒ็จ‹๏ผ‰ใ€‚ + + + +### HTTP ๅ›žๆ‡‰ { #http-response } + +ๆ‡‰็”จๆœƒ่™•็†่ฉฒ่ซ‹ๆฑ‚๏ผŒไธฆๅฐ‡**็ด”๏ผˆๆœชๅŠ ๅฏ†๏ผ‰็š„ HTTP ๅ›žๆ‡‰**้€ๅ›ž TLS ็ต‚ๆญขไปฃ็†ใ€‚ + + + +### HTTPS ๅ›žๆ‡‰ { #https-response } + +TLS ็ต‚ๆญขไปฃ็†ๆŽฅ่‘—ๆœƒไพ็…งๅ…ˆๅ‰ๅ”ๅ•†๏ผˆ่ตท้ปžๆ˜ฏ `someapp.example.com` ็š„ๆ†‘่ญ‰๏ผ‰็š„ๆ–นๅผ**ๅŠ ๅฏ†ๅ›žๆ‡‰**๏ผŒไธฆๅ‚ณๅ›ž็ตฆ็€่ฆฝๅ™จใ€‚ + +ๆŽฅ่‘—๏ผŒ็€่ฆฝๅ™จๆœƒ้ฉ—่ญ‰ๅ›žๆ‡‰ๆ˜ฏๅฆๅˆๆณ•ใ€ๆ˜ฏๅฆไฝฟ็”จๆญฃ็ขบ็š„้‡‘้‘ฐๅŠ ๅฏ†็ญ‰ใ€‚็„ถๅพŒ**่งฃๅฏ†ๅ›žๆ‡‰**ไธฆ่™•็†ใ€‚ + + + +็”จๆˆถ็ซฏ๏ผˆ็€่ฆฝๅ™จ๏ผ‰ๆœƒ็Ÿฅ้“ๅ›žๆ‡‰ไพ†่‡ชๆญฃ็ขบ็š„ไผบๆœๅ™จ๏ผŒๅ› ็‚บๅฎƒไฝฟ็”จไบ†ๅ…ˆๅ‰ไพๆ“š **HTTPS ๆ†‘่ญ‰**ๆ‰€ๅ”ๅ•†็š„ๅฏ†็ขผๆฉŸๅˆถใ€‚ + +### ๅคšๅ€‹ๆ‡‰็”จ { #multiple-applications } + +ๅŒไธ€ๅฐ๏ผˆๆˆ–ๅคšๅฐ๏ผ‰ไผบๆœๅ™จไธŠๅฏไปฅๆœ‰**ๅคšๅ€‹ๆ‡‰็”จ**๏ผŒไพ‹ๅฆ‚ๅ…ถไป– API ็จ‹ๅผๆˆ–่ณ‡ๆ–™ๅบซใ€‚ + +้›–็„ถๅชๆœ‰ไธ€ๅ€‹่กŒ็จ‹ๅฏไปฅ่™•็†็‰นๅฎš IP ่ˆ‡ๅŸ ็š„็ต„ๅˆ๏ผˆๆœฌไพ‹ไธญ็š„ TLS ็ต‚ๆญขไปฃ็†๏ผ‰๏ผŒไฝ†ๅ…ถไป–ๆ‡‰็”จ๏ผ่กŒ็จ‹ไนŸ้ƒฝ่ƒฝๅœจไผบๆœๅ™จไธŠ้‹่กŒ๏ผŒๅช่ฆๅฎƒๅ€‘ไธไฝฟ็”จ็›ธๅŒ็š„**ๅ…ฌ็”จ IP ่ˆ‡ๅŸ **็ต„ๅˆๅณๅฏใ€‚ + + + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒTLS ็ต‚ๆญขไปฃ็†ๅฐฑ่ƒฝ็‚บ**ๅคšๅ€‹็ถฒๅŸŸ**ใ€ๅคšๅ€‹ๆ‡‰็”จ่™•็† HTTPS ่ˆ‡ๆ†‘่ญ‰๏ผŒไธฆๆŠŠ่ซ‹ๆฑ‚่ฝ‰็™ผๅˆฐๅฐๆ‡‰็š„ๆ‡‰็”จใ€‚ + +### ๆ†‘่ญ‰็บŒๆœŸ { #certificate-renewal } + +ๅœจๆœชไพ†ๆŸๅ€‹ๆ™‚้–“้ปž๏ผŒๆฏๅผตๆ†‘่ญ‰้ƒฝๆœƒ**้ŽๆœŸ**๏ผˆ่‡ชๅ–ๅพ—่ตท็ด„ 3 ๅ€‹ๆœˆ๏ผ‰ใ€‚ + +ไน‹ๅพŒ๏ผŒๆœƒๆœ‰ๅฆไธ€ๅ€‹็จ‹ๅผ๏ผˆๆœ‰ๆ™‚ๆ˜ฏๅฆไธ€ๅ€‹็จ‹ๅผ๏ผŒๆœ‰ๆ™‚ไนŸๅฏ่ƒฝๅฐฑๆ˜ฏๅŒไธ€ๅ€‹ TLS ็ต‚ๆญขไปฃ็†๏ผ‰่ˆ‡ Let's Encrypt ๆบ้€šไธฆ็บŒๆœŸๆ†‘่ญ‰ใ€‚ + + + +**TLS ๆ†‘่ญ‰**ๆ˜ฏ**็ถๅฎš็ถฒๅŸŸๅ็จฑ**๏ผŒไธๆ˜ฏ็ถๅฎš IP ไฝๅ€ใ€‚ + +ๅ› ๆญค๏ผŒ่ฆ็บŒๆœŸๆ†‘่ญ‰ๆ™‚๏ผŒ็บŒๆœŸ็จ‹ๅผ้œ€่ฆๅ‘ๆ†‘่ญ‰ๆฉŸๆง‹๏ผˆLet's Encrypt๏ผ‰**่ญ‰ๆ˜Ž**ๅฎƒ็š„็ขบ**ๆ“ๆœ‰ไธฆๆŽงๅˆถ่ฉฒ็ถฒๅŸŸ**ใ€‚ + +็‚บไบ†้”ๆˆ้€™้ปžใ€ไธฆๅ…ผ้กงไธๅŒๆ‡‰็”จๆƒ…ๅขƒ๏ผŒๆœ‰ๅนพ็จฎๅธธ่ฆ‹ๆ–นๅผ๏ผš + +* **ไฟฎๆ”น้ƒจๅˆ† DNS ็ด€้Œ„**ใ€‚ + * ็‚บๆญค๏ผŒ็บŒๆœŸ็จ‹ๅผ้œ€่ฆๆ”ฏๆด่ฉฒ DNS ไพ›ๆ‡‰ๅ•†็š„ API๏ผŒๅ› ๆญคไพไฝ ไฝฟ็”จ็š„ DNS ไพ›ๆ‡‰ๅ•†ไธๅŒ๏ผŒ้€™ๆ–นๅผๅฏ่ƒฝๅฏ่กŒๆˆ–ไธๅฏ่กŒใ€‚ +* **ไฝœ็‚บไผบๆœๅ™จ้‹่กŒ**๏ผˆ่‡ณๅฐ‘ๅœจๆ†‘่ญ‰็”ณ่ซ‹้Ž็จ‹ไธญ๏ผ‰ๆ–ผ่ฉฒ็ถฒๅŸŸๅฐๆ‡‰็š„ๅ…ฌ็”จ IP ไธŠใ€‚ + * ๅฆ‚ๅ‰ๆ‰€่ฟฐ๏ผŒๅŒไธ€ๆ™‚้–“ๅชๆœ‰ไธ€ๅ€‹่กŒ็จ‹่ƒฝๅœจ็‰นๅฎš IP ่ˆ‡ๅŸ ไธŠ็›ฃ่ฝใ€‚ + * ้€™ไนŸๆ˜ฏ็‚บไป€้บผ่ฎ“ๅŒไธ€ๅ€‹ TLS ็ต‚ๆญขไปฃ็†ไธ€ไฝต่™•็†ๆ†‘่ญ‰็บŒๆœŸ้žๅธธๅฏฆ็”จ็š„ๅŽŸๅ› ไน‹ไธ€ใ€‚ + * ๅฆๅ‰‡ไฝ ๅฏ่ƒฝๅพ—ๆšซๅœ TLS ็ต‚ๆญขไปฃ็†ใ€ๅ•Ÿๅ‹•็บŒๆœŸ็จ‹ๅผ็”ณ่ซ‹ๆ†‘่ญ‰ใ€ๅฐ‡ๆ†‘่ญ‰้…็ฝฎๅˆฐ TLS ็ต‚ๆญขไปฃ็†๏ผŒ็„ถๅพŒๅ†้‡ๅ•Ÿ TLS ็ต‚ๆญขไปฃ็†ใ€‚้€™ไธฆไธ็†ๆƒณ๏ผŒๅ› ็‚บๅœจ TLS ็ต‚ๆญขไปฃ็†ๅœๆฉŸๆœŸ้–“๏ผŒไฝ ็š„ๆ‡‰็”จๅฐ‡ไธๅฏ็”จใ€‚ + +ๅœจไธไธญๆ–ทๆœๅ‹™็š„ๅŒๆ™‚ๅฎŒๆˆๆ•ดๅ€‹็บŒๆœŸๆต็จ‹๏ผŒๆ˜ฏไฝ ๆœƒๆƒณ็”จ**็จ็ซ‹็ณป็ตฑ๏ผˆTLS ็ต‚ๆญขไปฃ็†๏ผ‰ไพ†่™•็† HTTPS**ใ€่€Œไธๆ˜ฏ็›ดๆŽฅๆŠŠ TLS ๆ†‘่ญ‰ๆŽ›ๅœจๆ‡‰็”จไผบๆœๅ™จ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ไธŠ็š„ไธป่ฆๅŽŸๅ› ไน‹ไธ€ใ€‚ + +## ไปฃ็†่ฝ‰็™ผๆจ™้ ญ { #proxy-forwarded-headers } + +็•ถไฝ ไฝฟ็”จไปฃ็†่™•็† HTTPS ๆ™‚๏ผŒไฝ ็š„**ๆ‡‰็”จไผบๆœๅ™จ**๏ผˆไพ‹ๅฆ‚้€้Ž FastAPI CLI ๅ•Ÿๅ‹•็š„ Uvicorn๏ผ‰ๅ…ถๅฏฆไธ็Ÿฅ้“ไปปไฝ• HTTPS ็š„่™•็†ๆต็จ‹๏ผŒๅฎƒๆ˜ฏ็”จ็ด” HTTP ่ˆ‡ **TLS ็ต‚ๆญขไปฃ็†**้€š่จŠใ€‚ + +้€™ๅ€‹**ไปฃ็†**้€šๅธธๆœƒๅœจๆŠŠ่ซ‹ๆฑ‚่ฝ‰็™ผ็ตฆ**ๆ‡‰็”จไผบๆœๅ™จ**ไน‹ๅ‰๏ผŒ่‡จๆ™‚ๅŠ ๅ…ฅไธ€ไบ› HTTP ๆจ™้ ญ๏ผŒ่ฎ“ๆ‡‰็”จไผบๆœๅ™จ็Ÿฅ้“่ฉฒ่ซ‹ๆฑ‚ๆ˜ฏ็”ฑไปฃ็†**่ฝ‰็™ผ**้Žไพ†็š„ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +้€™ไบ›ไปฃ็†ๆจ™้ ญๅŒ…ๆ‹ฌ๏ผš + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +็„ถ่€Œ๏ผŒๅ› ็‚บ**ๆ‡‰็”จไผบๆœๅ™จ**ไธฆไธ็Ÿฅ้“่‡ชๅทฑๅœจๅ—ไฟกไปป็š„**ไปฃ็†**ไน‹ๅพŒ๏ผŒ้ ่จญๆƒ…ๆณไธ‹ๅฎƒไธๆœƒไฟกไปป้€™ไบ›ๆจ™้ ญใ€‚ + +ไฝ†ไฝ ๅฏไปฅ่จญๅฎš**ๆ‡‰็”จไผบๆœๅ™จ**ๅŽปไฟกไปป็”ฑ**ไปฃ็†**้€ไพ†็š„ใ€Œ่ฝ‰็™ผใ€ๆจ™้ ญใ€‚่‹ฅไฝ ไฝฟ็”จ FastAPI CLI๏ผŒๅฏไปฅ็”จ *CLI ๅƒๆ•ธ* `--forwarded-allow-ips` ๆŒ‡ๅฎšๆ‡‰ไฟกไปปๅ“ชไบ› IP ไพ†็š„ใ€Œ่ฝ‰็™ผใ€ๆจ™้ ญใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœ**ๆ‡‰็”จไผบๆœๅ™จ**ๅชๆœƒๆŽฅๆ”ถไพ†่‡ชๅ—ไฟกไปป**ไปฃ็†**็š„้€ฃ็ทš๏ผŒไฝ ๅฏไปฅ่จญๅฎš `--forwarded-allow-ips="*"`๏ผŒไนŸๅฐฑๆ˜ฏไฟกไปปๆ‰€ๆœ‰ไพ†ๆบ IP๏ผŒๅ› ็‚บๅฏฆ้š›ไธŠๅฎƒๅชๆœƒๆ”ถๅˆฐ**ไปฃ็†**้‚ฃๅ€‹ IP ้€ไพ†็š„่ซ‹ๆฑ‚ใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๆ‡‰็”จๅฐฑ่ƒฝ็Ÿฅ้“่‡ชๅทฑ็š„ๅฐๅค– URLใ€ๆ˜ฏๅฆไฝฟ็”จ HTTPSใ€็ถฒๅŸŸ็‚บไฝ•็ญ‰่ณ‡่จŠใ€‚ + +้€™ๅœจๆญฃ็ขบ่™•็†้‡ๆ–ฐๅฐŽๅ‘็ญ‰ๆƒ…ๅขƒๆ™‚ๅพˆๆœ‰็”จใ€‚ + +/// tip + +ไฝ ๅฏไปฅๅœจๆ–‡ไปถ [ๅœจไปฃ็†ๅพŒๆ–น - ๅ•Ÿ็”จไปฃ็†่ฝ‰็™ผๆจ™้ ญ](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} ไธญไบ†่งฃๆ›ดๅคšใ€‚ + +/// + +## ้‡้ปžๅ›ž้กง { #recap } + +ๆ“ๆœ‰ **HTTPS** ้žๅธธ้‡่ฆ๏ผŒ่€Œไธ”ๅœจๅคšๆ•ธๆƒ…ๆณ้ƒฝ็›ธ็•ถ**้—œ้ต**ใ€‚ไฝœ็‚บ้–‹็™ผ่€…๏ผŒไฝ ๅœจ HTTPS ไธŠ็š„ๅคง้ƒจๅˆ†ๆŠ•ๅ…ฅๅ…ถๅฏฆๆ˜ฏ**็†่งฃ้€™ไบ›ๆฆ‚ๅฟต**ๅŠๅ…ถ้‹ไฝœๆ–นๅผใ€‚ + +ไธ€ๆ—ฆๆŽŒๆกไบ†**็ตฆ้–‹็™ผ่€…็š„ HTTPS ๅŸบ็คŽ**๏ผŒไฝ ๅฐฑ่ƒฝ่ผ•้ฌ†็ต„ๅˆไธฆ่จญๅฎšไธๅŒๅทฅๅ…ท๏ผŒ่ฎ“ไธ€ๅˆ‡็ฎก็†่ฎŠๅพ—็ฐกๅ–ฎใ€‚ + +ๅœจๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ไธญ๏ผŒๆˆ‘ๆœƒ็คบ็ฏ„ๅนพๅ€‹็‚บ **FastAPI** ๆ‡‰็”จ่จญๅฎš **HTTPS** ็š„ๅ…ท้ซ”ไพ‹ๅญใ€‚๐Ÿ”’ diff --git a/docs/zh-hant/docs/deployment/index.md b/docs/zh-hant/docs/deployment/index.md index 9edd3368b2..ddf533efc9 100644 --- a/docs/zh-hant/docs/deployment/index.md +++ b/docs/zh-hant/docs/deployment/index.md @@ -8,7 +8,7 @@ ๅฐๆ–ผไธ€ๅ€‹ **Web API**๏ผŒ้ƒจ็ฝฒ้€šๅธธๆถ‰ๅŠๅฐ‡ๅ…ถๆ”พ็ฝฎๅœจ**้ ็ซฏไผบๆœๅ™จ**ไธŠ๏ผŒไธฆไฝฟ็”จๆ€ง่ƒฝๅ„ช่‰ฏไธ”็ฉฉๅฎš็š„**ไผบๆœๅ™จ็จ‹ๅผ**๏ผŒ็ขบไฟไฝฟ็”จ่€…่ƒฝๅค ้ซ˜ๆ•ˆใ€็„กไธญๆ–ทๅœฐๅญ˜ๅ–ๆ‡‰็”จ็จ‹ๅผ๏ผŒไธ”ไธๆœƒ้‡ๅˆฐๅ•้กŒใ€‚ -้€™่ˆ‡**้–‹็™ผ**้šŽๆฎตๅฝขๆˆ้ฎฎๆ˜Žๅฐๆฏ”๏ผŒๅœจ**้–‹็™ผ**้šŽๆฎต๏ผŒไฝ ๆœƒไธๆ–ทๆ›ดๆ”น็จ‹ๅผ็ขผใ€็ ดๅฃž็จ‹ๅผ็ขผใ€ไฟฎๅพฉ็จ‹ๅผ็ขผ๏ผŒ็„ถๅพŒๅœๆญขๅ’Œ้‡ๆ–ฐๅ•Ÿๅ‹•ไผบๆœๅ™จ็ญ‰ใ€‚ +้€™่ˆ‡**้–‹็™ผ**้šŽๆฎตๅฝขๆˆ้ฎฎๆ˜Žๅฐๆฏ”๏ผŒๅœจ**้–‹็™ผ**้šŽๆฎต๏ผŒไฝ ๆœƒไธๆ–ทๆ›ดๆ”น็จ‹ๅผ็ขผใ€็ ดๅฃž็จ‹ๅผ็ขผใ€ไฟฎๅพฉ็จ‹ๅผ็ขผ๏ผŒ็„ถๅพŒๅœๆญขๅ’Œ้‡ๆ–ฐๅ•Ÿๅ‹•้–‹็™ผไผบๆœๅ™จ็ญ‰ใ€‚ ## ้ƒจ็ฝฒ็ญ–็•ฅ { #deployment-strategies } diff --git a/docs/zh-hant/docs/deployment/manually.md b/docs/zh-hant/docs/deployment/manually.md new file mode 100644 index 0000000000..bf9f6a93f4 --- /dev/null +++ b/docs/zh-hant/docs/deployment/manually.md @@ -0,0 +1,157 @@ +# ๆ‰‹ๅ‹•ๅŸท่กŒไผบๆœๅ™จ { #run-a-server-manually } + +## ไฝฟ็”จ `fastapi run` ๆŒ‡ไปค { #use-the-fastapi-run-command } + +็ฐก่€Œ่จ€ไน‹๏ผŒไฝฟ็”จ `fastapi run` ไพ†ๅ•Ÿๅ‹•ไฝ ็š„ FastAPI ๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +้€™ๅœจๅคšๆ•ธๆƒ…ๆณไธ‹้ƒฝ้ฉ็”จใ€‚๐Ÿ˜Ž + +ไฝ ๅฏไปฅ็”จ้€™ๅ€‹ๆŒ‡ไปคๅœจๅฎนๅ™จใ€ไผบๆœๅ™จ็ญ‰็’ฐๅขƒไธญๅ•Ÿๅ‹•ไฝ ็š„ FastAPI ๆ‡‰็”จใ€‚ + +## ASGI ไผบๆœๅ™จ { #asgi-servers } + +ๆˆ‘ๅ€‘ๅ†ๆทฑๅ…ฅไธ€ไบ›็ดฐ็ฏ€ใ€‚ + +FastAPI ๆŽก็”จๅปบ็ซ‹ Python ็ถฒ้ ๆก†ๆžถ่ˆ‡ไผบๆœๅ™จ็š„ๆจ™ๆบ– ASGIใ€‚FastAPI ๆ˜ฏไธ€ๅ€‹ ASGI ็ถฒ้ ๆก†ๆžถใ€‚ + +ๅœจ้ ็ซฏไผบๆœๅ™จๆฉŸๅ™จไธŠๅŸท่กŒ FastAPI ๆ‡‰็”จ๏ผˆๆˆ–ไปปไฝ• ASGI ๆ‡‰็”จ๏ผ‰ๆ‰€้œ€็š„้—œ้ตๆ˜ฏ ASGI ไผบๆœๅ™จ็จ‹ๅผ๏ผŒไพ‹ๅฆ‚ Uvicorn๏ผ›`fastapi` ๆŒ‡ไปค้ ่จญๅฐฑๆ˜ฏไฝฟ็”จๅฎƒใ€‚ + +ๆœ‰ๆ•ธๅ€‹ๆ›ฟไปฃๆ–นๆกˆ๏ผŒๅŒ…ๆ‹ฌ๏ผš + +* Uvicorn๏ผš้ซ˜ๆ•ˆ่ƒฝ ASGI ไผบๆœๅ™จใ€‚ +* Hypercorn๏ผšๆ”ฏๆด HTTP/2 ่ˆ‡ Trio ็ญ‰ๅŠŸ่ƒฝ็š„ ASGI ไผบๆœๅ™จใ€‚ +* Daphne๏ผš็‚บ Django Channels ๆ‰“้€ ็š„ ASGI ไผบๆœๅ™จใ€‚ +* Granian๏ผš้‡ๅฐ Python ๆ‡‰็”จ็š„ Rust HTTP ไผบๆœๅ™จใ€‚ +* NGINX Unit๏ผšNGINX Unit ๆ˜ฏ่ผ•้‡ไธ”ๅคšๅŠŸ่ƒฝ็š„็ถฒ้ ๆ‡‰็”จๅŸท่กŒ็’ฐๅขƒใ€‚ + +## ไผบๆœๅ™จๆฉŸๅ™จ่ˆ‡ไผบๆœๅ™จ็จ‹ๅผ { #server-machine-and-server-program } + +ๆœ‰ๅ€‹ๅ‘ฝๅไธŠ็š„ๅฐ็ดฐ็ฏ€่ซ‹็•™ๆ„ใ€‚๐Ÿ’ก + +ใ€Œserver๏ผˆไผบๆœๅ™จ๏ผ‰ใ€ไธ€่ฉžๅธธๅŒๆ™‚็”จไพ†ๆŒ‡้ ็ซฏ๏ผ้›ฒ็ซฏ้›ป่…ฆ๏ผˆๅฏฆ้ซ”ๆˆ–่™›ๆ“ฌๆฉŸๅ™จ๏ผ‰๏ผŒไนŸ็”จไพ†ๆŒ‡ๅœจ่ฉฒๆฉŸๅ™จไธŠๅŸท่กŒ็š„็จ‹ๅผ๏ผˆไพ‹ๅฆ‚ Uvicorn๏ผ‰ใ€‚ + +ๅ› ๆญค็œ‹ๅˆฐใ€Œserverใ€ๆ™‚๏ผŒๆ–‡ๆ„ๅฏ่ƒฝๆŒ‡้€™ๅ…ฉ่€…ไน‹ไธ€ใ€‚ + +ๆŒ‡ๆถ‰้ ็ซฏๆฉŸๅ™จๆ™‚๏ผŒๅธธ็จฑ็‚บ serverใ€machineใ€VM๏ผˆ่™›ๆ“ฌๆฉŸๅ™จ๏ผ‰ใ€node ็ญ‰๏ผŒ้€™ไบ›้ƒฝๆŒ‡ๆŸ็จฎ้ ็ซฏๆฉŸๅ™จ๏ผˆ้€šๅธธๅŸท่กŒ Linux๏ผ‰๏ผŒไฝ ๆœƒๅœจๅ…ถไธŠๅŸท่กŒ็จ‹ๅผใ€‚ + +## ๅฎ‰่ฃไผบๆœๅ™จ็จ‹ๅผ { #install-the-server-program } + +ๅฎ‰่ฃ FastAPI ๆ™‚ๆœƒ้™„ๅธถไธ€ๅ€‹ๅฏ็”จๆ–ผ็”Ÿ็”ข็’ฐๅขƒ็š„ไผบๆœๅ™จ Uvicorn๏ผŒไฝ ๅฏไปฅ็”จ `fastapi run` ไพ†ๅ•Ÿๅ‹•ๅฎƒใ€‚ + +ไฝ†ไฝ ไนŸๅฏไปฅๆ‰‹ๅ‹•ๅฎ‰่ฃ ASGI ไผบๆœๅ™จใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹ [่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒๆŽฅ่‘—ๅ†ๅฎ‰่ฃไผบๆœๅ™จ็จ‹ๅผใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฎ‰่ฃ Uvicorn๏ผš + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +ๅ…ถไป– ASGI ไผบๆœๅ™จ็š„ๅฎ‰่ฃๆต็จ‹ไนŸๅคง่‡ด็›ธๅŒใ€‚ + +/// tip + +ๅŠ ๅ…ฅ `standard` ๆœƒ่ฎ“ Uvicorn ๅฎ‰่ฃไธฆไฝฟ็”จไธ€ไบ›ๅปบ่ญฐ็š„้กๅค–็›ธไพๅฅ—ไปถใ€‚ + +ๅ…ถไธญๅŒ…ๅซ `uvloop`๏ผŒๅฎƒๆ˜ฏ `asyncio` ็š„้ซ˜ๆ•ˆ่ƒฝๆ›ฟไปฃๅฏฆไฝœ๏ผŒๅฏๅคงๅน…ๆๅ‡ไธฆ่กŒๆ•ˆ่ƒฝใ€‚ + +็•ถไฝ ็”จ `pip install "fastapi[standard]"` ๅฎ‰่ฃ FastAPI ๆ™‚๏ผŒไนŸๆœƒไธ€ไฝตๅ–ๅพ— `uvicorn[standard]`ใ€‚ + +/// + +## ๅŸท่กŒไผบๆœๅ™จ็จ‹ๅผ { #run-the-server-program } + +ๅฆ‚ๆžœไฝ ๆ˜ฏๆ‰‹ๅ‹•ๅฎ‰่ฃ ASGI ไผบๆœๅ™จ๏ผŒ้€šๅธธ้œ€่ฆๆไพ›็‰นๅฎšๆ ผๅผ็š„ import ๅญ—ไธฒ๏ผŒ่ฎ“ๅฎƒ่ƒฝๅŒฏๅ…ฅไฝ ็š„ FastAPI ๆ‡‰็”จ๏ผš + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note + +ๆŒ‡ไปค `uvicorn main:app` ๆŒ‡็š„ๆ˜ฏ๏ผš + +* `main`๏ผšๆช”ๆกˆ `main.py`๏ผˆPythonใ€Œๆจก็ต„ใ€๏ผ‰ใ€‚ +* `app`๏ผšๅœจ `main.py` ไธญไปฅ `app = FastAPI()` ๅปบ็ซ‹็š„็‰ฉไปถใ€‚ + +็ญ‰ๅŒๆ–ผ๏ผš + +```Python +from main import app +``` + +/// + +ๅ…ถไป– ASGI ไผบๆœๅ™จไนŸๆœ‰้กžไผผ็š„ๆŒ‡ไปค๏ผŒ่ฉณ่ฆ‹ๅ„่‡ช็š„ๆ–‡ไปถใ€‚ + +/// warning + +Uvicorn ่ˆ‡ๅ…ถไป–ไผบๆœๅ™จๆ”ฏๆด `--reload` ้ธ้ …๏ผŒๅฐ้–‹็™ผๆœŸ้–“ๅพˆๆœ‰ๅนซๅŠฉใ€‚ + +`--reload` ๆœƒๆถˆ่€—ๆ›ดๅคš่ณ‡ๆบ๏ผŒไนŸ่ผƒไธ็ฉฉๅฎš็ญ‰ใ€‚ + +ๅฎƒๅœจ้–‹็™ผ้šŽๆฎตๅพˆๅฏฆ็”จ๏ผŒไฝ†ๅœจ็”Ÿ็”ข็’ฐๅขƒไธญไธๆ‡‰ไฝฟ็”จใ€‚ + +/// + +## ้ƒจ็ฝฒ่ง€ๅฟต { #deployment-concepts } + +ไธŠ่ฟฐ็ฏ„ไพ‹ๆœƒๅ•Ÿๅ‹•ไผบๆœๅ™จ็จ‹ๅผ๏ผˆๅฆ‚ Uvicorn๏ผ‰๏ผŒไปฅๅ–ฎไธ€่กŒ็จ‹ๅœจๆŒ‡ๅฎš้€ฃๆŽฅๅŸ ๏ผˆๅฆ‚ `80`๏ผ‰ไธŠ็›ฃ่ฝๆ‰€ๆœ‰ IP๏ผˆ`0.0.0.0`๏ผ‰ใ€‚ + +้€™ๆ˜ฏๅŸบๆœฌๆฆ‚ๅฟตใ€‚ไฝ†ไฝ ๅพˆๅฏ่ƒฝ้‚„้œ€่ฆ่™•็†ไธ€ไบ›้กๅค–ไบ‹้ …๏ผŒไพ‹ๅฆ‚๏ผš + +* ๅฎ‰ๅ…จๆ€ง - HTTPS +* ้–‹ๆฉŸ่‡ชๅ‹•ๅ•Ÿๅ‹• +* ่‡ชๅ‹•้‡ๅ•Ÿ +* ๅคšๅ‰ฏๆœฌ๏ผˆๅŸท่กŒ็š„่กŒ็จ‹ๆ•ธ้‡๏ผ‰ +* ่จ˜ๆ†ถ้ซ” +* ๅ•Ÿๅ‹•ๅ‰้œ€่ฆๅŸท่กŒ็š„ๅ‰็ฝฎๆญฅ้ฉŸ + +ๅœจไธ‹ไธ€็ซ ็ฏ€ๆˆ‘ๆœƒ้€ฒไธ€ๆญฅ่ชชๆ˜Ž้€™ไบ›่ง€ๅฟตใ€ๆ€่€ƒๆ–นๅผ๏ผŒไปฅๅŠๅฐๆ‡‰็š„่™•็†็ญ–็•ฅ่ˆ‡ๅฏฆไฝœ็ฏ„ไพ‹ใ€‚๐Ÿš€ diff --git a/docs/zh-hant/docs/deployment/server-workers.md b/docs/zh-hant/docs/deployment/server-workers.md new file mode 100644 index 0000000000..56569e49ad --- /dev/null +++ b/docs/zh-hant/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# ไผบๆœๅ™จๅทฅไฝœ่™•็†ๅบ - ไฝฟ็”จ Uvicorn Workers { #server-workers-uvicorn-with-workers } + +ๆˆ‘ๅ€‘ๅ›ž้กงไธ€ไธ‹ๅ…ˆๅ‰ๆๅˆฐ็š„้ƒจ็ฝฒๆฆ‚ๅฟต๏ผš + +* ๅฎ‰ๅ…จ - HTTPS +* ็ณป็ตฑๅ•Ÿๅ‹•ๆ™‚ๅŸท่กŒ +* ้‡ๅ•Ÿ +* **ๅ‰ฏๆœฌ๏ผˆๆญฃๅœจๅŸท่กŒ็š„่™•็†ๅบๆ•ธ้‡๏ผ‰** +* ่จ˜ๆ†ถ้ซ” +* ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎไฝœๆฅญ + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไพ็…งๆ–‡ไปถไธญ็š„ๆ•™ๅญธ๏ผŒไฝ ๅคงๅคšๆ˜ฏ้€้Ž `fastapi` ๆŒ‡ไปคๅ•Ÿๅ‹•ไธ€ๅ€‹ๅŸท่กŒ Uvicorn ็š„ไผบๆœๅ™จ็จ‹ๅผ๏ผŒไธ”ๅช่ท‘ๅ–ฎไธ€่™•็†ๅบใ€‚ + +ๅœจ้ƒจ็ฝฒๆ‡‰็”จๆ™‚๏ผŒไฝ ้€šๅธธๆœƒๅธŒๆœ›ๆœ‰ไธ€ไบ›่™•็†ๅบ็š„่ค‡่ฃฝไพ†ๅ–„็”จๅคšๆ ธๅฟƒ๏ผŒไธฆ่ƒฝ่™•็†ๆ›ดๅคš่ซ‹ๆฑ‚ใ€‚ + +ๅฆ‚ๅŒๅ‰ไธ€็ซ ้—œๆ–ผ [้ƒจ็ฝฒๆฆ‚ๅฟต](concepts.md){.internal-link target=_blank} ๆ‰€็คบ๏ผŒไฝ ๅฏไปฅๆŽก็”จๅคš็จฎ็ญ–็•ฅใ€‚ + +้€™่ฃกๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•ไฝฟ็”จ `fastapi` ๆŒ‡ไปคๆˆ–็›ดๆŽฅไฝฟ็”จ `uvicorn` ๆŒ‡ไปค๏ผŒๆญ้… Uvicorn ็š„ๅทฅไฝœ่™•็†ๅบ๏ผˆworker processes๏ผ‰ใ€‚ + +/// info + +ๅฆ‚ๆžœไฝ ไฝฟ็”จๅฎนๅ™จ๏ผˆไพ‹ๅฆ‚ Docker ๆˆ– Kubernetes๏ผ‰๏ผŒๆˆ‘ๆœƒๅœจไธ‹ไธ€็ซ ่ชชๆ˜Žๆ›ดๅคš๏ผš[ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank}ใ€‚ + +็‰นๅˆฅๆ˜ฏ๏ผŒๅœจ **Kubernetes** ไธŠๅŸท่กŒๆ™‚๏ผŒไฝ ๅคšๅŠๆœƒ้ธๆ“‡ไธ่ฆไฝฟ็”จ workers๏ผŒ่€Œๆ˜ฏๆฏๅ€‹ๅฎนๅ™จๅช่ท‘ไธ€ๅ€‹ **Uvicorn ๅ–ฎไธ€่™•็†ๅบ**ใ€‚ๆˆ‘ๆœƒๅœจ่ฉฒ็ซ ็ฏ€ไธญ้€ฒไธ€ๆญฅ่ชชๆ˜Žใ€‚ + +/// + +## ๅคšๅ€‹ๅทฅไฝœ่™•็†ๅบ { #multiple-workers } + +ไฝ ๅฏไปฅ็”จๅ‘ฝไปคๅˆ—้ธ้ … `--workers` ไพ†ๅ•Ÿๅ‹•ๅคšๅ€‹ workers๏ผš + +//// tab | `fastapi` + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `fastapi` ๆŒ‡ไปค๏ผš + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +ๅฆ‚ๆžœไฝ ๅๅฅฝ็›ดๆŽฅไฝฟ็”จ `uvicorn` ๆŒ‡ไปค๏ผš + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +้€™่ฃกๅ”ฏไธ€ๆ–ฐๅขž็š„้ธ้ …ๆ˜ฏ `--workers`๏ผŒๅ‘Š่จด Uvicorn ่ฆๅ•Ÿๅ‹• 4 ๅ€‹ๅทฅไฝœ่™•็†ๅบใ€‚ + +ไฝ ไนŸๆœƒ็œ‹ๅˆฐๅฎƒ้กฏ็คบๆฏๅ€‹่™•็†ๅบ็š„ **PID**๏ผŒ`27365` ๆ˜ฏ็ˆถ่™•็†ๅบ๏ผˆ้€™ๆ˜ฏ**่™•็†ๅบ็ฎก็†ๅ™จ**๏ผ‰๏ผŒๅฆๅค–ๆฏๅ€‹ๅทฅไฝœ่™•็†ๅบๅ„ๆœ‰ไธ€ๅ€‹๏ผš`27368`ใ€`27369`ใ€`27370`ใ€`27367`ใ€‚ + +## ้ƒจ็ฝฒๆฆ‚ๅฟต { #deployment-concepts } + +ไฝ ๅทฒ็ถ“็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จๅคšๅ€‹ **workers** ไพ†ๅฐ‡ๆ‡‰็”จ็š„ๅŸท่กŒ้€ฒ่กŒ**ๅนณ่กŒๅŒ–**๏ผŒๅ–„็”จ CPU ็š„**ๅคšๆ ธๅฟƒ**๏ผŒไธฆ่ƒฝๆœๅ‹™**ๆ›ดๅคš่ซ‹ๆฑ‚**ใ€‚ + +ๅœจไธŠ้ข็š„้ƒจ็ฝฒๆฆ‚ๅฟตๆธ…ๅ–ฎไธญ๏ผŒไฝฟ็”จ workers ไธป่ฆ่ƒฝๅนซๅŠฉๅˆฐ**ๅ‰ฏๆœฌ**้€™ไธ€ๅกŠ๏ผŒไธฆๅฐ**้‡ๅ•Ÿ**ไนŸๆœ‰ไธ€้ปžๅนซๅŠฉ๏ผŒไฝ†ไฝ ไป้œ€่ฆ่™•็†ๅ…ถไป–้ƒจๅˆ†๏ผš + +* **ๅฎ‰ๅ…จ - HTTPS** +* **็ณป็ตฑๅ•Ÿๅ‹•ๆ™‚ๅŸท่กŒ** +* ***้‡ๅ•Ÿ*** +* ๅ‰ฏๆœฌ๏ผˆๆญฃๅœจๅŸท่กŒ็š„่™•็†ๅบๆ•ธ้‡๏ผ‰ +* **่จ˜ๆ†ถ้ซ”** +* **ๅ•Ÿๅ‹•ๅ‰็š„ๅ‰็ฝฎไฝœๆฅญ** + +## ๅฎนๅ™จ่ˆ‡ Docker { #containers-and-docker } + +ๅœจไธ‹ไธ€็ซ  [ๅฎนๅ™จไธญ็š„ FastAPI - Docker](docker.md){.internal-link target=_blank} ๆˆ‘ๆœƒ่ชชๆ˜Žไธ€ไบ›็ญ–็•ฅ๏ผŒๅนซไฝ ่™•็†ๅ…ถไป–็š„**้ƒจ็ฝฒๆฆ‚ๅฟต**ใ€‚ + +ๆˆ‘ๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•**ๅพž้›ถๅปบ็ซ‹ไฝ ็š„ๆ˜ ๅƒๆช”**ไพ†ๅŸท่กŒๅ–ฎไธ€ Uvicorn ่™•็†ๅบใ€‚้€™ๅ€‹ๆต็จ‹็›ธ็•ถ็ฐกๅ–ฎ๏ผŒ่€Œไธ”ๅœจไฝฟ็”จๅƒ **Kubernetes** ้€™้กžๅˆ†ๆ•ฃๅผๅฎนๅ™จ็ฎก็†็ณป็ตฑๆ™‚๏ผŒๅคงๅคšๆƒ…ๆณไนŸๆœƒ้€™้บผๅšใ€‚ + +## ้‡้ปžๅ›ž้กง { #recap } + +ไฝ ๅฏไปฅๅœจ `fastapi` ๆˆ– `uvicorn` ๆŒ‡ไปคไธญไฝฟ็”จ `--workers` ้€™ๅ€‹ CLI ้ธ้ …ไพ†ๅ•Ÿๅ‹•ๅคšๅ€‹ๅทฅไฝœ่™•็†ๅบ๏ผŒไปฅๅ–„็”จ**ๅคšๆ ธๅฟƒ CPU**๏ผŒ**ๅนณ่กŒ**ๅŸท่กŒๅคšๅ€‹่™•็†ๅบใ€‚ + +ๅฆ‚ๆžœไฝ ่ฆ่‡ช่กŒๅปบ็ฝฎ**่‡ชๅทฑ็š„้ƒจ็ฝฒ็ณป็ตฑ**๏ผŒไฝ ๅฏไปฅ้‹็”จ้€™ไบ›ๅทฅๅ…ท่ˆ‡ๆƒณๆณ•๏ผŒๅŒๆ™‚่‡ช่กŒ่™•็†ๅ…ถไป–้ƒจ็ฝฒๆฆ‚ๅฟตใ€‚ + +ๆŽฅ่‘—็œ‹็œ‹ไธ‹ไธ€็ซ ้—œๆ–ผๅœจๅฎนๅ™จ๏ผˆไพ‹ๅฆ‚ Docker ่ˆ‡ Kubernetes๏ผ‰ไธญไฝฟ็”จ **FastAPI**ใ€‚ไฝ ๆœƒ็œ‹ๅˆฐ้‚ฃไบ›ๅทฅๅ…ทไนŸๆœ‰็ฐกๅ–ฎ็š„ๆ–นๆณ•ไพ†่งฃๆฑบๅ…ถไป–**้ƒจ็ฝฒๆฆ‚ๅฟต**ใ€‚โœจ diff --git a/docs/zh-hant/docs/deployment/versions.md b/docs/zh-hant/docs/deployment/versions.md new file mode 100644 index 0000000000..c4f9c52624 --- /dev/null +++ b/docs/zh-hant/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# ้—œๆ–ผ FastAPI ็‰ˆๆœฌ { #about-fastapi-versions } + +**FastAPI** ๅทฒ็ถ“ๅœจ่จฑๅคšๆ‡‰็”จ่ˆ‡็ณป็ตฑ็š„็”Ÿ็”ข็’ฐๅขƒไธญไฝฟ็”จ๏ผŒไธ”ๆธฌ่ฉฆๆถต่“‹็އ็ถญๆŒๅœจ 100%ใ€‚ๅŒๆ™‚้–‹็™ผไปๅœจๅฟซ้€ŸๆŽจ้€ฒใ€‚ + +็ถ“ๅธธๅŠ ๅ…ฅๆ–ฐๅŠŸ่ƒฝใ€ๅฎšๆœŸไฟฎๅพฉ้Œฏ่ชค๏ผŒ็จ‹ๅผ็ขผไนŸๅœจๆŒ็บŒๆ”น้€ฒใ€‚ + +้€™ๅฐฑๆ˜ฏ็‚บไป€้บผ็›ฎๅ‰็‰ˆๆœฌไป็‚บ `0.x.x`๏ผŒ้€™่กจ็คบๆฏๅ€‹็‰ˆๆœฌ้ƒฝๅฏ่ƒฝๅŒ…ๅซ็ ดๅฃžๆ€ง่ฎŠๆ›ดใ€‚้€™้ตๅพช ่ชžๆ„ๅŒ–็‰ˆๆœฌ๏ผˆSemantic Versioning๏ผ‰ ็š„ๆ…ฃไพ‹ใ€‚ + +ไฝ ็พๅœจๅฐฑๅฏไปฅ็”จ **FastAPI** ๅปบ็ฝฎ็”Ÿ็”ข็’ฐๅขƒ็š„ๆ‡‰็”จ๏ผˆ่€Œไธ”ไฝ ๅฏ่ƒฝๅทฒ็ถ“้€™้บผๅšไธ€ๆฎตๆ™‚้–“ไบ†๏ผ‰๏ผŒๅช่ฆ็ขบไฟไฝ ไฝฟ็”จ็š„็‰ˆๆœฌ่ƒฝ่ˆ‡ๅ…ถ้ค˜็จ‹ๅผ็ขผๆญฃ็ขบ็›ธๅฎนใ€‚ + +## ้Ž–ๅฎšไฝ ็š„ `fastapi` ็‰ˆๆœฌ { #pin-your-fastapi-version } + +้ฆ–ๅ…ˆ๏ผŒไฝ ๆ‡‰่ฉฒๅฐ‡ไฝ ไฝฟ็”จ็š„ **FastAPI** ็‰ˆๆœฌใ€Œ้Ž–ๅฎš๏ผˆpin๏ผ‰ใ€ๅˆฐไฝ ็Ÿฅ้“ๅฐไฝ ็š„ๆ‡‰็”จๅฏๆญฃๅธธ้‹ไฝœ็š„ๆœ€ๆ–ฐ็‰นๅฎš็‰ˆๆœฌใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ็š„ๆ‡‰็”จไฝฟ็”จ `0.112.0` ็‰ˆๆœฌใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `requirements.txt` ๆช”ๆกˆ๏ผŒๅฏไปฅ้€™ๆจฃๆŒ‡ๅฎš็‰ˆๆœฌ๏ผš + +```txt +fastapi[standard]==0.112.0 +``` + +้€™่กจ็คบไฝ ๆœƒไฝฟ็”จๅฎŒๅ…จ็›ธๅŒ็š„ `0.112.0` ็‰ˆๆœฌใ€‚ + +ๆˆ–ไฝ ไนŸๅฏไปฅ้€™ๆจฃ้Ž–ๅฎš๏ผš + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +้€™่กจ็คบๆœƒไฝฟ็”จ `0.112.0`๏ผˆๅซ๏ผ‰ไปฅไธŠไฝ†ๅฐๆ–ผ `0.113.0` ็š„็‰ˆๆœฌ๏ผŒไพ‹ๅฆ‚ `0.112.2` ไนŸๆœƒ่ขซๆŽฅๅ—ใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จๅ…ถไป–ๅฎ‰่ฃ็ฎก็†ๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ `uv`ใ€Poetryใ€Pipenv ็ญ‰๏ผŒๅฎƒๅ€‘ไนŸ้ƒฝๆœ‰ๅฏ็”จไพ†ๆŒ‡ๅฎšๅฅ—ไปถ็‰นๅฎš็‰ˆๆœฌ็š„ๆ–นๆณ•ใ€‚ + +## ๅฏ็”จ็‰ˆๆœฌ { #available-versions } + +ไฝ ๅฏไปฅๅœจ [็™ผ่กŒ่ชชๆ˜Ž](../release-notes.md){.internal-link target=_blank} ๆŸฅ็œ‹ๅฏ็”จ็‰ˆๆœฌ๏ผˆไพ‹ๅฆ‚็”จไพ†็ขบ่ช็›ฎๅ‰ๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผ‰ใ€‚ + +## ้—œๆ–ผ็‰ˆๆœฌ { #about-versions } + +ไพ็…ง่ชžๆ„ๅŒ–็‰ˆๆœฌ็š„ๆ…ฃไพ‹๏ผŒไปปไฝ•ไฝŽๆ–ผ `1.0.0` ็š„็‰ˆๆœฌ้ƒฝๅฏ่ƒฝๅŠ ๅ…ฅ็ ดๅฃžๆ€ง่ฎŠๆ›ดใ€‚ + +FastAPI ไนŸ้ตๅพชๆ…ฃไพ‹๏ผšไปปไฝ•ใ€ŒPATCHใ€็‰ˆๆœฌ่ฎŠๆ›ดๅƒ…็”จๆ–ผไฟฎๆญฃ้Œฏ่ชค่ˆ‡้ž็ ดๅฃžๆ€ง่ฎŠๆ›ดใ€‚ + +/// tip + +ใ€ŒPATCHใ€ๆ˜ฏๆœ€ๅพŒไธ€ๅ€‹ๆ•ธๅญ—๏ผŒไพ‹ๅฆ‚ๅœจ `0.2.3` ไธญ๏ผŒPATCH ็‰ˆๆœฌๆ˜ฏ `3`ใ€‚ + +/// + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅฐ‡็‰ˆๆœฌ้Ž–ๅฎš็‚บๅฆ‚ไธ‹ๅฝขๅผ๏ผš + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +็ ดๅฃžๆ€ง่ฎŠๆ›ด่ˆ‡ๆ–ฐๅŠŸ่ƒฝๆœƒๅœจใ€ŒMINORใ€็‰ˆๆœฌๅŠ ๅ…ฅใ€‚ + +/// tip + +ใ€ŒMINORใ€ๆ˜ฏไธญ้–“็š„ๆ•ธๅญ—๏ผŒไพ‹ๅฆ‚ๅœจ `0.2.3` ไธญ๏ผŒMINOR ็‰ˆๆœฌๆ˜ฏ `2`ใ€‚ + +/// + +## ๅ‡็ดš FastAPI ็‰ˆๆœฌ { #upgrading-the-fastapi-versions } + +ไฝ ๆ‡‰่ฉฒ็‚บไฝ ็š„ๆ‡‰็”จๆ’ฐๅฏซๆธฌ่ฉฆใ€‚ + +ๅœจ **FastAPI** ไธญ้€™ๅพˆๅฎนๆ˜“๏ผˆๆ„Ÿ่ฌ Starlette๏ผ‰๏ผŒ่ซ‹ๅƒ่€ƒๆ–‡ไปถ๏ผš[ๆธฌ่ฉฆ](../tutorial/testing.md){.internal-link target=_blank} + +ๆœ‰ไบ†ๆธฌ่ฉฆไน‹ๅพŒ๏ผŒไฝ ๅฐฑๅฏไปฅๅฐ‡ **FastAPI** ๅ‡็ดšๅˆฐ่ผƒๆ–ฐ็š„็‰ˆๆœฌ๏ผŒไธฆ้€้ŽๅŸท่กŒๆธฌ่ฉฆไพ†็ขบไฟๆ‰€ๆœ‰็จ‹ๅผ็ขผ้ƒฝ่ƒฝๆญฃ็ขบ้‹ไฝœใ€‚ + +ๅฆ‚ๆžœไธ€ๅˆ‡ๆญฃๅธธ๏ผŒๆˆ–ๅœจๅฎŒๆˆๅฟ…่ฆ่ชฟๆ•ดไธ”ๆ‰€ๆœ‰ๆธฌ่ฉฆ้€š้Žไน‹ๅพŒ๏ผŒๅฐฑๅฏไปฅๆŠŠไฝ ็š„ `fastapi` ้Ž–ๅฎšๅˆฐ่ฉฒๆ–ฐ็š„็‰ˆๆœฌใ€‚ + +## ้—œๆ–ผ Starlette { #about-starlette } + +ไฝ ไธๆ‡‰้Ž–ๅฎš `starlette` ็š„็‰ˆๆœฌใ€‚ + +ไธๅŒ็š„ **FastAPI** ็‰ˆๆœฌๆœƒไฝฟ็”จ็‰นๅฎš่ผƒๆ–ฐ็š„ Starlette ็‰ˆๆœฌใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅ่ฎ“ **FastAPI** ไฝฟ็”จๆญฃ็ขบ็š„ Starlette ็‰ˆๆœฌใ€‚ + +## ้—œๆ–ผ Pydantic { #about-pydantic } + +Pydantic ๅœจๅ…ถๆธฌ่ฉฆไธญๆถต่“‹ไบ† **FastAPI** ็š„ๆธฌ่ฉฆ๏ผŒๅ› ๆญค Pydantic ็š„ๆ–ฐ็‰ˆๆœฌ๏ผˆ้ซ˜ๆ–ผ `1.0.0`๏ผ‰ไธ€ๅพ‹่ˆ‡ FastAPI ็›ธๅฎนใ€‚ + +ไฝ ๅฏไปฅๅฐ‡ Pydantic ้Ž–ๅฎšๅˆฐไปปไฝ•้ซ˜ๆ–ผ `1.0.0`ใ€้ฉๅˆไฝ ็š„็‰ˆๆœฌใ€‚ + +ไพ‹ๅฆ‚๏ผš + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/zh-hant/docs/fastapi-cli.md b/docs/zh-hant/docs/fastapi-cli.md index b107e7e73f..57b5ec98f2 100644 --- a/docs/zh-hant/docs/fastapi-cli.md +++ b/docs/zh-hant/docs/fastapi-cli.md @@ -1,4 +1,4 @@ -# FastAPI CLI +# FastAPI CLI { #fastapi-cli } **FastAPI CLI** ๆ˜ฏไธ€ๅ€‹ๅ‘ฝไปคๅˆ—็จ‹ๅผ๏ผŒ่ƒฝ็”จไพ†้‹่กŒไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผใ€็ฎก็†ไฝ ็š„ FastAPI ๅฐˆๆกˆ็ญ‰ใ€‚ @@ -9,72 +9,64 @@
```console -$ fastapi dev main.py -INFO Using path main.py -INFO Resolved absolute path /home/user/code/awesomeapp/main.py -INFO Searching for package file structure from directories with __init__.py files -INFO Importing from /home/user/code/awesomeapp - - โ•ญโ”€ Python module file โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ ๐Ÿ main.py โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Importing module main -INFO Found importable FastAPI app - - โ•ญโ”€ Importable FastAPI app โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ from main import app โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO Using import string main:app - - โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ FastAPI CLI - Development mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ - โ”‚ โ”‚ - โ”‚ Serving at: http://127.0.0.1:8000 โ”‚ - โ”‚ โ”‚ - โ”‚ API docs: http://127.0.0.1:8000/docs โ”‚ - โ”‚ โ”‚ - โ”‚ Running in development mode, for production use: โ”‚ - โ”‚ โ”‚ - โ”‚ fastapi run โ”‚ - โ”‚ โ”‚ - โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2265862] using WatchFiles -INFO: Started server process [2265873] -INFO: Waiting for application startup. -INFO: Application startup complete. +$ fastapi dev main.py + + FastAPI Starting development server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-`fastapi` ๅ‘ฝไปคๅˆ—็จ‹ๅผๅฐฑๆ˜ฏ **FastAPI CLI**ใ€‚ +ๅ็‚บ `fastapi` ็š„ๅ‘ฝไปคๅˆ—็จ‹ๅผๅฐฑๆ˜ฏ **FastAPI CLI**ใ€‚ -FastAPI CLI ๆŽฅๆ”ถไฝ ็š„ Python ็จ‹ๅผ่ทฏๅพ‘๏ผˆไพ‹ๅฆ‚ `main.py`๏ผ‰๏ผŒไธฆ่‡ชๅ‹•ๆชขๆธฌ FastAPI ๅฏฆไพ‹๏ผˆ้€šๅธธๅ‘ฝๅ็‚บ `app`๏ผ‰๏ผŒ็ขบๅฎšๆญฃ็ขบ็š„ๅผ•ๅ…ฅๆจก็ต„ๆต็จ‹๏ผŒ็„ถๅพŒ้‹่กŒ่ฉฒๆ‡‰็”จ็จ‹ๅผใ€‚ +FastAPI CLI ๆŽฅๆ”ถไฝ ็š„ Python ็จ‹ๅผ่ทฏๅพ‘๏ผˆไพ‹ๅฆ‚ `main.py`๏ผ‰๏ผŒไธฆ่‡ชๅ‹•ๆชขๆธฌ `FastAPI` ๅฏฆไพ‹๏ผˆ้€šๅธธๅ‘ฝๅ็‚บ `app`๏ผ‰๏ผŒ็ขบๅฎšๆญฃ็ขบ็š„ๅผ•ๅ…ฅๆจก็ต„ๆต็จ‹๏ผŒ็„ถๅพŒ้‹่กŒ่ฉฒๆ‡‰็”จ็จ‹ๅผใ€‚ ๅœจ็”Ÿ็”ข็’ฐๅขƒ๏ผŒไฝ ๆ‡‰่ฉฒไฝฟ็”จ `fastapi run` ๅ‘ฝไปคใ€‚ ๐Ÿš€ **FastAPI CLI** ๅ…ง้ƒจไฝฟ็”จไบ† Uvicorn๏ผŒ้€™ๆ˜ฏไธ€ๅ€‹้ซ˜ๆ•ˆ่ƒฝใ€้ฉๅˆ็”Ÿ็”ข็’ฐๅขƒ็š„ ASGI ไผบๆœๅ™จใ€‚ ๐Ÿ˜Ž -## `fastapi dev` +## `fastapi dev` { #fastapi-dev } ๅŸท่กŒ `fastapi dev` ๆœƒๅ•Ÿๅ‹•้–‹็™ผๆจกๅผใ€‚ ้ ่จญๆƒ…ๆณไธ‹๏ผŒ**auto-reload** ๅŠŸ่ƒฝๆ˜ฏๅ•Ÿ็”จ็š„๏ผŒ็•ถไฝ ๅฐ็จ‹ๅผ็ขผ้€ฒ่กŒไฟฎๆ”นๆ™‚๏ผŒไผบๆœๅ™จๆœƒ่‡ชๅ‹•้‡ๆ–ฐ่ผ‰ๅ…ฅใ€‚้€™ๆœƒๆถˆ่€—่ผƒๅคš่ณ‡ๆบ๏ผŒไธฆไธ”ๅฏ่ƒฝๆฏ”็ฆ็”จๆ™‚ๆ›ดไธ็ฉฉๅฎšใ€‚ๅ› ๆญค๏ผŒไฝ ๆ‡‰่ฉฒๅชๅœจ้–‹็™ผ็’ฐๅขƒไธญไฝฟ็”จๆญคๅŠŸ่ƒฝใ€‚ๅฎƒไนŸๆœƒๅœจ IP ไฝๅ€ `127.0.0.1` ไธŠ็›ฃ่ฝ๏ผŒ้€™ๆ˜ฏ็”จๆ–ผไฝ ็š„ๆฉŸๅ™จ่ˆ‡่‡ช่บซ้€š่จŠ็š„ IP ไฝๅ€๏ผˆ`localhost`๏ผ‰ใ€‚ -## `fastapi run` +## `fastapi run` { #fastapi-run } ๅŸท่กŒ `fastapi run` ๆœƒไปฅ็”Ÿ็”ขๆจกๅผๅ•Ÿๅ‹• FastAPIใ€‚ -้ ่จญๆƒ…ๆณไธ‹๏ผŒ**auto-reload** ๅŠŸ่ƒฝๆ˜ฏ็ฆ็”จ็š„ใ€‚ๅฎƒไนŸๆœƒๅœจ IP ไฝๅ€ `0.0.0.0` ไธŠ็›ฃ่ฝ๏ผŒ่กจ็คบๆœƒ็›ฃ่ฝๆ‰€ๆœ‰ๅฏ็”จ็š„ IP ๅœฐๅ€๏ผŒ้€™ๆจฃไปปไฝ•่ƒฝ่ˆ‡่ฉฒๆฉŸๅ™จ้€š่จŠ็š„ไบบ้ƒฝๅฏไปฅๅ…ฌ้–‹ๅญ˜ๅ–ๅฎƒใ€‚้€™้€šๅธธๆ˜ฏไฝ ๅœจ็”Ÿ็”ข็’ฐๅขƒไธญ้‹่กŒๆ‡‰็”จ็จ‹ๅผ็š„ๆ–นๅผ๏ผŒไพ‹ๅฆ‚ๅœจๅฎนๅ™จไธญ้‹่กŒๆ™‚ใ€‚ +้ ่จญๆƒ…ๆณไธ‹๏ผŒ**auto-reload** ๅŠŸ่ƒฝๆ˜ฏ็ฆ็”จ็š„ใ€‚ๅฎƒไนŸๆœƒๅœจ IP ไฝๅ€ `0.0.0.0` ไธŠ็›ฃ่ฝ๏ผŒ่กจ็คบๆœƒ็›ฃ่ฝๆ‰€ๆœ‰ๅฏ็”จ็š„ IP ไฝๅ€๏ผŒ้€™ๆจฃไปปไฝ•่ƒฝ่ˆ‡่ฉฒๆฉŸๅ™จ้€š่จŠ็š„ไบบ้ƒฝๅฏไปฅๅ…ฌ้–‹ๅญ˜ๅ–ๅฎƒใ€‚้€™้€šๅธธๆ˜ฏไฝ ๅœจ็”Ÿ็”ข็’ฐๅขƒไธญ้‹่กŒๆ‡‰็”จ็จ‹ๅผ็š„ๆ–นๅผ๏ผŒไพ‹ๅฆ‚ๅœจๅฎนๅ™จไธญ้‹่กŒๆ™‚ใ€‚ -ๅœจๅคงๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒ๏ผˆไนŸๆ‡‰่ฉฒ๏ผ‰ๆœ‰ไธ€ๅ€‹ใ€Œ็ต‚ๆญขไปฃ็†ใ€ไพ†่™•็† HTTPS๏ผŒ้€™ๅ–ๆฑบๆ–ผไฝ ๅฆ‚ไฝ•้ƒจ็ฝฒไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ๏ผŒไฝ ็š„ๆœๅ‹™ไพ›ๆ‡‰ๅ•†ๅฏ่ƒฝๆœƒ็‚บไฝ ๅš้€™ไปถไบ‹๏ผŒๆˆ–่€…ไฝ ้œ€่ฆ่‡ชๅทฑ่จญ็ฝฎๅฎƒใ€‚ +ๅœจๅคงๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๆœƒ๏ผˆไนŸๆ‡‰่ฉฒ๏ผ‰ๆœ‰ไธ€ๅ€‹ใ€Œ็ต‚ๆญขไปฃ็†ใ€ๅœจๅค–ๅฑคๅนซไฝ ่™•็† HTTPS๏ผ›้€™ๅ–ๆฑบๆ–ผไฝ ๅฆ‚ไฝ•้ƒจ็ฝฒๆ‡‰็”จ็จ‹ๅผ๏ผŒไฝ ็š„ๆœๅ‹™ไพ›ๆ‡‰ๅ•†ๅฏ่ƒฝๆœƒๅนซไฝ ่™•็†๏ผŒๆˆ–่€…ไฝ ้œ€่ฆ่‡ชๅทฑ่จญ็ฝฎใ€‚ /// tip diff --git a/docs/zh-hant/docs/features.md b/docs/zh-hant/docs/features.md index f44d28a7f8..77c0203073 100644 --- a/docs/zh-hant/docs/features.md +++ b/docs/zh-hant/docs/features.md @@ -1,17 +1,17 @@ -# ็‰นๆ€ง +# ็‰นๆ€ง { #features } -## FastAPI ็‰นๆ€ง +## FastAPI ็‰นๆ€ง { #fastapi-features } -**FastAPI** ๆไพ›ไบ†ไปฅไธ‹ๅ†…ๅฎน๏ผš +**FastAPI** ๆไพ›ไบ†ไปฅไธ‹ๅ…งๅฎน๏ผš -### ๅปบ็ซ‹ๅœจ้–‹ๆ”พๆจ™ๆบ–็š„ๅŸบ็คŽไธŠ +### ๅปบ็ซ‹ๅœจ้–‹ๆ”พๆจ™ๆบ–็š„ๅŸบ็คŽไธŠ { #based-on-open-standards } -* ไฝฟ็”จ OpenAPI ไพ†ๅปบ็ซ‹ API๏ผŒๅŒ…ๅซ่ทฏๅพ‘ๆ“ไฝœใ€ๅƒๆ•ธใ€่ซ‹ๆฑ‚ๅ…งๆ–‡ใ€ๅฎ‰ๅ…จๆ€ง็ญ‰่ฒๆ˜Žใ€‚ +* ไฝฟ็”จ OpenAPI ไพ†ๅปบ็ซ‹ API๏ผŒๅŒ…ๅซ ่ทฏๅพ‘ใ€ๆ“ไฝœใ€ๅƒๆ•ธใ€่ซ‹ๆฑ‚ๅ…งๆ–‡ใ€ๅฎ‰ๅ…จๆ€ง็ญ‰ๅฎฃๅ‘Šใ€‚ * ไฝฟ็”จ JSON Schema๏ผˆๅ› ็‚บ OpenAPI ๆœฌ่บซๅฐฑๆ˜ฏๅŸบๆ–ผ JSON Schema๏ผ‰่‡ชๅ‹•็”Ÿๆˆ่ณ‡ๆ–™ๆจกๅž‹ๆ–‡ไปถใ€‚ * ็ถ“้Ž็ธๅฏ†็š„็ ”็ฉถๅพŒๅœ็นž้€™ไบ›ๆจ™ๆบ–้€ฒ่กŒ่จญ่จˆ๏ผŒ่€Œไธๆ˜ฏไบ‹ๅพŒๅœจๅทฒๆœ‰็ณป็ตฑไธŠ้™„ๅŠ ็š„ไธ€ๅฑคๅŠŸ่ƒฝใ€‚ * ้€™ไนŸ่ฎ“ๆˆ‘ๅ€‘ๅœจๅคš็จฎ่ชž่จ€ไธญๅฏไปฅไฝฟ็”จ่‡ชๅ‹•**็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ็”Ÿๆˆ**ใ€‚ -### ่ƒฝๅค ่‡ชๅ‹•็”Ÿๆˆๆ–‡ไปถ +### ่ƒฝๅค ่‡ชๅ‹•็”Ÿๆˆๆ–‡ไปถ { #automatic-docs } FastAPI ่ƒฝ็”Ÿๆˆไบ’ๅ‹•ๅผ API ๆ–‡ไปถๅ’ŒๆŽข็ดขๆ€ง็š„ Web ไฝฟ็”จ่€…ไป‹้ขใ€‚็”ฑๆ–ผ่ฉฒๆก†ๆžถๅŸบๆ–ผ OpenAPI๏ผŒๅ› ๆญคๆœ‰ๅคš็จฎ้ธๆ“‡๏ผŒ้ ่จญๆไพ›ไบ†ๅ…ฉ็จฎใ€‚ @@ -19,12 +19,11 @@ FastAPI ่ƒฝ็”Ÿๆˆไบ’ๅ‹•ๅผ API ๆ–‡ไปถๅ’ŒๆŽข็ดขๆ€ง็š„ Web ไฝฟ็”จ่€…ไป‹้ขใ€‚็”ฑ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDoc ๆไพ›็ตๆง‹ๆ€ง็š„ๆ–‡ไปถ๏ผŒ่ฎ“ไฝ ๅฏไปฅๅœจ็€่ฆฝๅ™จไธญๆŸฅ็œ‹ใ€‚ +* ไฝฟ็”จ ReDoc ็š„ๆ›ฟไปฃ API ๆ–‡ไปถใ€‚ ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) - -### ็พไปฃ Python +### ็พไปฃ Python { #just-modern-python } ้€™ไธ€ๅˆ‡้ƒฝๅŸบๆ–ผๆจ™ๆบ–็š„ **Python ๅž‹ๅˆฅ**ๅฎฃๅ‘Š๏ผˆๆ„Ÿ่ฌ Pydantic๏ผ‰ใ€‚็„ก้œ€ๅญธ็ฟ’ๆ–ฐ็š„่ชžๆณ•๏ผŒๅช้œ€ไฝฟ็”จๆจ™ๆบ–็š„็พไปฃ Pythonใ€‚ @@ -32,7 +31,7 @@ FastAPI ่ƒฝ็”Ÿๆˆไบ’ๅ‹•ๅผ API ๆ–‡ไปถๅ’ŒๆŽข็ดขๆ€ง็š„ Web ไฝฟ็”จ่€…ไป‹้ขใ€‚็”ฑ ๅฆ‚ๆžœไฝ ๅฏซๅธถๆœ‰ Python ๅž‹ๅˆฅ็š„็จ‹ๅผ็ขผ๏ผš -```python +```Python from datetime import date from pydantic import BaseModel @@ -50,10 +49,9 @@ class User(BaseModel): joined: date ``` - ๅฏไปฅๅƒ้€™ๆจฃไพ†ไฝฟ็”จ๏ผš -```python +```Python my_user: User = User(id=3, name="John Doe", joined="2018-07-19") second_user_data = { @@ -65,7 +63,6 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` - /// info `**second_user_data` ๆ„ๆ€ๆ˜ฏ: @@ -74,11 +71,11 @@ my_second_user: User = User(**second_user_data) /// -### ๅคš็จฎ็ทจ่ผฏๅ™จๆ”ฏๆด +### ๅคš็จฎ็ทจ่ผฏๅ™จๆ”ฏๆด { #editor-support } ๆ•ดๅ€‹ๆก†ๆžถ็š„่จญ่จˆๆ˜ฏ็‚บไบ†่ฎ“ไฝฟ็”จ่ฎŠๅพ—็ฐกๅ–ฎไธ”็›ด่ง€๏ผŒๅœจ้–‹ๅง‹้–‹็™ผไน‹ๅ‰๏ผŒๆ‰€ๆœ‰ๆฑบ็ญ–้ƒฝๅœจๅคšๅ€‹็ทจ่ผฏๅ™จไธŠ้€ฒ่กŒไบ†ๆธฌ่ฉฆ๏ผŒไปฅ็ขบไฟๆไพ›ๆœ€ไฝณ็š„้–‹็™ผ้ซ”้ฉ—ใ€‚ -ๅœจๆœ€่ฟ‘็š„ Python ้–‹็™ผ่€…่ชฟๆŸฅไธญ๏ผŒๆˆ‘ๅ€‘่ƒฝ็œ‹ๅˆฐ ่ขซไฝฟ็”จๆœ€ๅคš็š„ๅŠŸ่ƒฝๆ˜ฏ autocompletion๏ผŒๆญคๅŠŸ่ƒฝๅฏไปฅ้ ๆธฌๅฐ‡่ฆ่ผธๅ…ฅๆ–‡ๅญ—๏ผŒไธฆ่‡ชๅ‹•่ฃœ้ฝŠใ€‚ +ๅœจๆœ€่ฟ‘็š„ Python ้–‹็™ผ่€…่ชฟๆŸฅไธญ๏ผŒๆˆ‘ๅ€‘่ƒฝ็œ‹ๅˆฐ ่ขซไฝฟ็”จๆœ€ๅคš็š„ๅŠŸ่ƒฝๆ˜ฏ autocompletionใ€‚ ๆ•ดๅ€‹ **FastAPI** ๆก†ๆžถๅฐฑๆ˜ฏๅŸบๆ–ผ้€™ไธ€้ปž๏ผŒไปปไฝ•ๅœฐๆ–น้ƒฝๅฏไปฅ้€ฒ่กŒ่‡ชๅ‹•่ฃœ้ฝŠใ€‚ @@ -86,11 +83,11 @@ my_second_user: User = User(**second_user_data) ๅœจ้€™่ฃก๏ผŒไฝ ็š„็ทจ่ผฏๅ™จๅฏ่ƒฝๆœƒ้€™ๆจฃๅนซๅŠฉไฝ ๏ผš -* Visual Studio Code ไธญ: +* ๅœจ Visual Studio Code ไธญ: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* PyCharm ไธญ: +* ๅœจ PyCharm ไธญ: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) @@ -98,17 +95,13 @@ my_second_user: User = User(**second_user_data) ้€™ๆจฃๆฏ”่ผƒไธๆœƒ่ผธ้Œฏ้ตๅ๏ผŒไธ็”จไพ†ๅ›ž็ฟป็œ‹ๆ–‡ไปถ๏ผŒไนŸไธ็”จไพ†ๅ›žๆปพๅ‹•ๅฐ‹ๆ‰พไฝ ๆœ€ๅพŒไฝฟ็”จ็š„ `username` ๆˆ–่€… `user_name`ใ€‚ - - -### ็ฐกๆฝ” +### ็ฐกๆฝ” { #short } FastAPI ็‚บไฝ ๆไพ›ไบ†**้ ่จญๅ€ผ**๏ผŒ่ฎ“ไฝ ไธๅฟ…ๅœจๅˆๆœŸ้€ฒ่กŒ็น็‘ฃ็š„้…็ฝฎ๏ผŒไธ€ๅˆ‡้ƒฝๅฏไปฅ่‡ชๅ‹•้‹ไฝœใ€‚ๅฆ‚ๆžœไฝ ๆœ‰ๆ›ดๅ…ท้ซ”็š„้œ€ๆฑ‚๏ผŒๅ‰‡ๅฏไปฅ้€ฒ่กŒ่ชฟๆ•ดๅ’Œ่‡ชๅฎš็พฉ๏ผŒ -ไฝ†ๅœจๅคงๅคšๆ•ธๆƒ…ๆณไธ‹๏ผŒไฝ ๅช้œ€่ฆ็›ดๆŽฅไฝฟ็”จ้ ่จญๅ€ผ๏ผŒๅฐฑ่ƒฝ้ †ๅˆฉๅฎŒๆˆ API ้–‹็™ผใ€‚ +ไฝ†้ ่จญๆƒ…ๆณไธ‹๏ผŒไธ€ๅˆ‡้ƒฝใ€Œ็›ดๆŽฅๅฏ็”จใ€ใ€‚ -### ้ฉ—่ญ‰ - -ๆ‰€ๆœ‰็š„้ฉ—่ญ‰้ƒฝ็”ฑๅฎŒๅ–„ไธ”ๅผทๅคง็š„ **Pydantic** ่™•็†ใ€‚ +### ้ฉ—่ญ‰ { #validation } * ้ฉ—่ญ‰ๅคง้ƒจๅˆ†๏ผˆ็”š่‡ณๆ‰€ๆœ‰๏ผŸ๏ผ‰็š„ Python **่ณ‡ๆ–™ๅž‹ๅˆฅ**๏ผŒๅŒ…ๆ‹ฌ๏ผš * JSON ็‰ฉไปถ (`dict`)ใ€‚ @@ -120,9 +113,11 @@ FastAPI ็‚บไฝ ๆไพ›ไบ†**้ ่จญๅ€ผ**๏ผŒ่ฎ“ไฝ ไธๅฟ…ๅœจๅˆๆœŸ้€ฒ่กŒ็น็‘ฃ็š„้… * URL * Email * UUID + * ...็ญ‰็ญ‰ใ€‚ +ๆ‰€ๆœ‰็š„้ฉ—่ญ‰้ƒฝ็”ฑๅฎŒๅ–„ไธ”ๅผทๅคง็š„ **Pydantic** ่™•็†ใ€‚ -### ๅฎ‰ๅ…จๆ€งๅŠ่บซไปฝ้ฉ—่ญ‰ +### ๅฎ‰ๅ…จๆ€งๅŠ่บซไปฝ้ฉ—่ญ‰ { #security-and-authentication } FastAPI ๅทฒ็ถ“ๆ•ดๅˆไบ†ๅฎ‰ๅ…จๆ€งๅ’Œ่บซไปฝ้ฉ—่ญ‰็š„ๅŠŸ่ƒฝ๏ผŒไฝ†ไธๆœƒๅผทๅˆถ่ˆ‡็‰นๅฎš็š„่ณ‡ๆ–™ๅบซๆˆ–่ณ‡ๆ–™ๆจกๅž‹้€ฒ่กŒ็ถๅฎšใ€‚ @@ -139,10 +134,9 @@ OpenAPI ไธญๅฎš็พฉ็š„ๅฎ‰ๅ…จๆจกๅผ๏ผŒๅŒ…ๆ‹ฌ๏ผš ๆ‰€ๆœ‰็š„้€™ไบ›้ƒฝๆ˜ฏๅฏ้‡่ค‡ไฝฟ็”จ็š„ๅทฅๅ…ทๅ’Œๅฅ—ไปถ๏ผŒๅฏไปฅ่ผ•้ฌ†่ˆ‡ไฝ ็š„็ณป็ตฑใ€่ณ‡ๆ–™ๅ„ฒๅญ˜๏ผˆData Stores๏ผ‰ใ€้—œ่ฏๅผ่ณ‡ๆ–™ๅบซ๏ผˆRDBMS๏ผ‰ไปฅๅŠ้ž้—œ่ฏๅผ่ณ‡ๆ–™ๅบซ๏ผˆNoSQL๏ผ‰็ญ‰็ญ‰ๆ•ดๅˆใ€‚ +### ไพ่ณดๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰ { #dependency-injection } -### ไพ่ณดๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰ - -FastAPI ๆœ‰ไธ€ๅ€‹ไฝฟ็”จ็ฐกๅ–ฎ๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผทๅคง็š„ไพ่ณดๆณจๅ…ฅ็ณป็ตฑใ€‚ +FastAPI ๆœ‰ไธ€ๅ€‹ไฝฟ็”จ็ฐกๅ–ฎ๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผทๅคง็š„ ไพ่ณดๆณจๅ…ฅ ็ณป็ตฑใ€‚ * ไพ่ณด้ …็”š่‡ณๅฏไปฅๆœ‰่‡ชๅทฑ็š„ไพ่ณด๏ผŒๅพž่€Œๅฝขๆˆไธ€ๅ€‹ๅฑค็ดšๆˆ–**ไพ่ณดๅœ–**็š„็ตๆง‹ใ€‚ * ๆ‰€ๆœ‰**่‡ชๅ‹•ๅŒ–่™•็†**้ƒฝ็”ฑๆก†ๆžถๅฎŒๆˆใ€‚ @@ -151,23 +145,21 @@ FastAPI ๆœ‰ไธ€ๅ€‹ไฝฟ็”จ็ฐกๅ–ฎ๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผทๅคง็š„Pydanticใ€‚ๆ‰€ไปฅ๏ผŒไฝ ๆœ‰ๅ…ถไป– Pydantic ็จ‹ๅผ็ขผไนŸ่ƒฝๆญฃๅธธๅทฅไฝœใ€‚ -็›ธๅฎนๅŒ…ๆ‹ฌๅŸบๆ–ผ Pydantic ็š„ๅค–้ƒจๅ‡ฝๅผๅบซ๏ผŒ ไพ‹ๅฆ‚็”จๆ–ผ่ณ‡ๆ–™ๅบซ็š„ ORMs, ODMsใ€‚ +็›ธๅฎนๅŒ…ๆ‹ฌๅŸบๆ–ผ Pydantic ็š„ๅค–้ƒจๅ‡ฝๅผๅบซ๏ผŒไพ‹ๅฆ‚็”จๆ–ผ่ณ‡ๆ–™ๅบซ็š„ ORMsใ€ODMsใ€‚ ้€™ไนŸๆ„ๅ‘ณ่‘—ๅœจๅพˆๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅๆŠŠๅพž่ซ‹ๆฑ‚ไธญ็ฒๅพ—็š„็‰ฉไปถ**็›ดๆŽฅๅ‚ณๅˆฐ่ณ‡ๆ–™ๅบซ**๏ผŒๅ› ็‚บๆ‰€ๆœ‰่ณ‡ๆ–™้ƒฝๆœƒ่‡ชๅ‹•้€ฒ่กŒ้ฉ—่ญ‰ใ€‚ @@ -196,7 +188,7 @@ FastAPI ๆœ‰ไธ€ๅ€‹ไฝฟ็”จ็ฐกๅ–ฎ๏ผŒไฝ†ๆ˜ฏ้žๅธธๅผทๅคง็š„็™ผไธ€ๅ‰‡้—œๆ–ผ **FastAPI** ็š„ๆŽจๆ–‡๏ผŒ่ฎ“ๆˆ‘่ˆ‡ๅ…ถไป–ไบบ็Ÿฅ้“ไฝ ็‚บไป€้บผๅ–œๆญกๅฎƒใ€‚๐ŸŽ‰ + +ๆˆ‘ๅพˆๆจ‚ๆ–ผ่ฝๅˆฐ **FastAPI** ๆ˜ฏๅฆ‚ไฝ•่ขซไฝฟ็”จใ€ไฝ ๅ–œๆญกๅฎƒ็š„ๅ“ชไบ›ๅœฐๆ–นใ€ๅœจๅ“ชๅ€‹ๅฐˆๆกˆ๏ผๅ…ฌๅธไฝฟ็”จๅฎƒ็ญ‰็ญ‰ใ€‚ + +## ็‚บ FastAPI ๆŠ•็ฅจ { #vote-for-fastapi } + +* ๅœจ Slant ็‚บ **FastAPI** ๆŠ•็ฅจใ€‚ +* ๅœจ AlternativeTo ็‚บ **FastAPI** ๆŠ•็ฅจใ€‚ +* ๅœจ StackShare ่กจ็คบไฝ ไฝฟ็”จ **FastAPI**ใ€‚ + +## ๅœจ GitHub ๅนซๅŠฉไป–ไบบ่งฃ็ญ”ๅ•้กŒ { #help-others-with-questions-in-github } + +ไฝ ๅฏไปฅๅ˜—่ฉฆๅนซๅŠฉไป–ไบบๅ›ž็ญ”ไปฅไธ‹ๅœฐๆ–น็š„ๅ•้กŒ๏ผš + +* GitHub Discussions +* GitHub Issues + +ๅพˆๅคšๆ™‚ๅ€™ไฝ ๅฏ่ƒฝๅทฒ็ถ“็Ÿฅ้“้€™ไบ›ๅ•้กŒ็š„่งฃ็ญ”ใ€‚๐Ÿค“ + +ๅฆ‚ๆžœไฝ ็ถ“ๅธธๅนซๅคงๅฎถ่งฃๆฑบๅ•้กŒ๏ผŒไฝ ๆœƒๆˆ็‚บๅฎ˜ๆ–น็š„ [FastAPI ๅฐˆๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank}ใ€‚๐ŸŽ‰ + +่ซ‹่จ˜ๅพ—๏ผŒๆœ€้‡่ฆ็š„ๆ˜ฏ๏ผš็›ก้‡ๅ‹ๅ–„ใ€‚ๅคงๅฎถๅฏ่ƒฝๅธถ่‘—ๆŒซๆŠ˜่€Œไพ†๏ผŒๅพˆๅคšๆ™‚ๅ€™ๆๅ•ๆ–นๅผไธๅค ็†ๆƒณ๏ผŒไฝ†่ซ‹็›กไฝ ๆ‰€่ƒฝไฟๆŒๅ‹ๅ–„ใ€‚๐Ÿค— + +**FastAPI** ็คพ็พค็š„็†ๅฟตๆ˜ฏๅ‹ๅ–„ไธ”ๆญก่ฟŽๅคงๅฎถใ€‚ๅŒๆ™‚๏ผŒไนŸไธ่ฆๆŽฅๅ—้œธๅ‡Œๆˆ–ๅฐไป–ไบบไธๅฐŠ้‡็š„่กŒ็‚บใ€‚ๆˆ‘ๅ€‘่ฆๅฝผๆญค็…ง้กงใ€‚ + +--- + +ไปฅไธ‹ๆ˜ฏๅœจ๏ผˆDiscussions ๆˆ– Issues๏ผ‰ไธญๅนซๅŠฉไป–ไบบ่งฃๆฑบๅ•้กŒ็š„ๆ–นๅผ๏ผš + +### ๅ…ˆ็†่งฃๅ•้กŒ { #understand-the-question } + +* ๅ…ˆ็ขบ่ชไฝ ๆ˜ฏๅฆ่ƒฝ็†่งฃๆๅ•่€…็š„**็›ฎ็š„**่ˆ‡ไฝฟ็”จๆƒ…ๅขƒใ€‚ + +* ๆŽฅ่‘—็œ‹็œ‹ๅ•้กŒ๏ผˆ็ต•ๅคงๅคšๆ•ธๆ˜ฏๆๅ•๏ผ‰ๆ˜ฏๅฆ**ๆธ…ๆฅš**ใ€‚ + +* ๅพˆๅคšๆ™‚ๅ€™๏ผŒๆๅ•ๆ˜ฏๅŸบๆ–ผไฝฟ็”จ่€…่‡ชๅทฑๆƒณๅƒไธญ็š„่งฃๆณ•๏ผŒไฝ†ๅฏ่ƒฝๆœ‰**ๆ›ดๅฅฝ**็š„ๆ–นๆณ•ใ€‚ๅฆ‚ๆžœไฝ ่ƒฝๆ›ด็†่งฃไป–ๅ€‘็š„ๅ•้กŒ่ˆ‡ไฝฟ็”จๆƒ…ๅขƒ๏ผŒไฝ ไนŸ่จฑ่ƒฝๆๅ‡บๆ›ดๅฅฝ็š„**ๆ›ฟไปฃ่งฃๆณ•**ใ€‚ + +* ๅฆ‚ๆžœไฝ ็„กๆณ•็†่งฃๅ•้กŒ๏ผŒ่ซ‹่ฆๆฑ‚ๆไพ›ๆ›ดๅคš**็ดฐ็ฏ€**ใ€‚ + +### ้‡็พๅ•้กŒ { #reproduce-the-problem } + +ๅœจๅคงๅคšๆ•ธๆƒ…ๆณ่ˆ‡ๅ•้กŒไธญ๏ผŒ้ƒฝๆœƒ่ˆ‡ๅฐๆ–น็š„**ๅŽŸๅง‹็จ‹ๅผ็ขผ**ๆœ‰้—œใ€‚ + +ๅพˆๅคšๆ™‚ๅ€™ไป–ๅ€‘ๅชๆœƒ่ฒผๅ‡บไธ€ๅฐๆฎต็จ‹ๅผ็ขผ๏ผŒไฝ†้‚ฃไธ่ถณไปฅ**้‡็พๅ•้กŒ**ใ€‚ + +* ไฝ ๅฏไปฅ่ซ‹ไป–ๅ€‘ๆไพ›ไธ€ๅ€‹ๆœ€ๅฐๅฏ้‡็พ็ฏ„ไพ‹๏ผŒ่ฎ“ไฝ ๅฏไปฅ**่ค‡่ฃฝ่ฒผไธŠ**ไธฆๅœจๆœฌๆฉŸๅŸท่กŒ๏ผŒ็œ‹ๅˆฐ่ˆ‡ไป–ๅ€‘็›ธๅŒ็š„้Œฏ่ชคๆˆ–่กŒ็‚บ๏ผŒๆˆ–ๆ›ดๅฅฝๅœฐ็†่งฃไป–ๅ€‘็š„ไฝฟ็”จๆƒ…ๅขƒใ€‚ + +* ๅฆ‚ๆžœไฝ ๆœ‰ๅฟƒๅŠ›๏ผŒไฝ ไนŸๅฏไปฅๅ˜—่ฉฆ่‡ชๅทฑ**ๅปบ็ซ‹ไธ€ๅ€‹็ฏ„ไพ‹**๏ผŒๅƒ…ไพๆ“šๅ•้กŒๆ่ฟฐไพ†้‚„ๅŽŸใ€‚ไธ้Ž่ซ‹่จ˜ๅพ—้€™ๅฏ่ƒฝๅพˆ่€—ๆ™‚๏ผŒๆˆ–่จฑๆ›ดๅฅฝ็š„ๆ˜ฏๅ…ˆ่ซ‹ไป–ๅ€‘ๆŠŠๅ•้กŒ่ชชๆธ…ๆฅšใ€‚ + +### ๆๅ‡บ่งฃๆณ•ๅปบ่ญฐ { #suggest-solutions } + +* ๅœจ่ƒฝๅค ็†่งฃๅ•้กŒๅพŒ๏ผŒไฝ ๅฏไปฅ็ตฆๅ‡บๅฏ่ƒฝ็š„**็ญ”ๆกˆ**ใ€‚ + +* ๅพˆๅคšๆ™‚ๅ€™๏ผŒๆœ€ๅฅฝ่ƒฝ็†่งฃไป–ๅ€‘็š„**ๅบ•ๅฑคๅ•้กŒๆˆ–ไฝฟ็”จๆƒ…ๅขƒ**๏ผŒๅ› ็‚บๅฏ่ƒฝๆœ‰ๆฏ”ไป–ๅ€‘ๅ˜—่ฉฆ็š„ๆ–นๆณ•ๆ›ดๅฅฝ็š„่งฃๆฑบไน‹้“ใ€‚ + +### ่ซ‹ๆฑ‚้—œ้–‰่ญฐ้กŒ { #ask-to-close } + +ๅฆ‚ๆžœไป–ๅ€‘ๅ›ž่ฆ†ไบ†๏ผŒไฝ ๅพˆๅฏ่ƒฝๅทฒ็ถ“่งฃๆฑบไบ†ไป–ๅ€‘็š„ๅ•้กŒ๏ผŒๆญๅ–œ๏ผŒ**ไฝ ๆ˜ฏ่‹ฑ้›„**๏ผ๐Ÿฆธ + +* ็พๅœจ๏ผŒๅฆ‚ๆžœๅ•้กŒๅทฒ่งฃๆฑบ๏ผŒไฝ ๅฏไปฅ่ซ‹ไป–ๅ€‘๏ผš + * ๅœจ GitHub Discussions๏ผšๆŠŠๆŸๅ‰‡็•™่จ€ๆจ™่จ˜็‚บ**็ญ”ๆกˆ**ใ€‚ + * ๅœจ GitHub Issues๏ผš**้—œ้–‰**่ฉฒ issueใ€‚ + +## ่ฟฝ่นค GitHub ๅ„ฒๅญ˜ๅบซ { #watch-the-github-repository } + +ไฝ ๅฏไปฅๅœจ GitHubใ€Œwatchใ€FastAPI๏ผˆ้ปžๆ“ŠๅณไธŠ่ง’็š„ใ€Œwatchใ€ๆŒ‰้ˆ•๏ผ‰๏ผšhttps://github.com/fastapi/fastapiใ€‚๐Ÿ‘€ + +ๅฆ‚ๆžœไฝ ้ธๆ“‡ใ€ŒWatchingใ€่€Œไธๆ˜ฏใ€ŒReleases onlyใ€๏ผŒ็•ถๆœ‰ไบบๅปบ็ซ‹ๆ–ฐ็š„ issue ๆˆ–ๅ•้กŒๆ™‚ไฝ ๆœƒๆ”ถๅˆฐ้€š็Ÿฅใ€‚ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšๅชๆƒณ่ขซ้€š็Ÿฅๆ–ฐ็š„ issuesใ€discussionsใ€PR ็ญ‰็ญ‰ใ€‚ + +ๆŽฅ่‘—ไฝ ๅฐฑๅฏไปฅๅ˜—่ฉฆๅนซๅฟ™่งฃๆฑบ้‚ฃไบ›ๅ•้กŒใ€‚ + +## ๆๅ• { #ask-questions } + +ไฝ ๅฏไปฅๅœจ GitHub ๅ„ฒๅญ˜ๅบซๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„ๅ•้กŒ๏ผˆQuestion๏ผ‰๏ผŒไพ‹ๅฆ‚็”จไพ†๏ผš + +* ๆๅ‡บ**ๅ•้กŒ**ๆˆ–่ฉขๅ•ๆŸๅ€‹**็–‘้›ฃ**ใ€‚ +* ๅปบ่ญฐไธ€ๅ€‹ๆ–ฐ็š„**ๅŠŸ่ƒฝ**ใ€‚ + +**ๆณจๆ„**๏ผšๅฆ‚ๆžœไฝ ้€™้บผๅš๏ผŒ้‚ฃๆˆ‘ไนŸๆœƒ่ซ‹ไฝ ๅŽปๅนซๅŠฉๅ…ถไป–ไบบใ€‚๐Ÿ˜‰ + +## ๅฏฉๆ ธ Pull Request { #review-pull-requests } + +ไฝ ๅฏไปฅๅนซๆˆ‘ๅฏฉๆŸฅไป–ไบบ็š„ Pull Requestใ€‚ + +ๅ†ๅผท่ชฟไธ€ๆฌก๏ผŒ่ซ‹็›ก้‡ไฟๆŒๅ‹ๅ–„ใ€‚๐Ÿค— + +--- + +ไปฅไธ‹ๆ˜ฏๅฏฉๆŸฅ Pull Request ๆ™‚้œ€่ฆๆณจๆ„่ˆ‡ๅฆ‚ไฝ•้€ฒ่กŒ๏ผš + +### ๅ…ˆ็†่งฃ่ฆ่งฃ็š„ๅ•้กŒ { #understand-the-problem } + +* ้ฆ–ๅ…ˆ๏ผŒ็ขบ่ชไฝ **็†่งฃไบ†่ฉฒ Pull Request ๆƒณ่งฃๆฑบ็š„ๅ•้กŒ**ใ€‚ๅฏ่ƒฝๅœจ GitHub Discussion ๆˆ– issue ไธญๆœ‰ๆ›ด้•ท็š„่จŽ่ซ–ใ€‚ + +* ไนŸๅพˆๆœ‰ๅฏ่ƒฝ้€™ๅ€‹ Pull Request ๅ…ถๅฏฆไธ้œ€่ฆ๏ผŒๅ› ็‚บๅ•้กŒๅฏไปฅ็”จ**ไธๅŒ็š„ๆ–นๆณ•**่งฃๆฑบใ€‚้‚ฃไฝ ๅฐฑๅฏไปฅๆๅ‡บๆˆ–่ฉขๅ•้‚ฃๅ€‹ๆ–นๅ‘ใ€‚ + +### ไธ็”จๅคชๅœจๆ„้ขจๆ ผ { #dont-worry-about-style } + +* ไธ่ฆๅคชๆ“”ๅฟƒๅƒๆ˜ฏๆไบค่จŠๆฏ๏ผˆcommit message๏ผ‰็š„้ขจๆ ผ๏ผŒๆˆ‘ๆœƒ็”จ squash and merge ไธฆๆ‰‹ๅ‹•่ชฟๆ•ดๆไบคๅ…งๅฎนใ€‚ + +* ไนŸไธ็”จๅคชๅœจๆ„็จ‹ๅผ็ขผ้ขจๆ ผ่ฆ็ฏ„๏ผŒๅทฒ็ถ“ๆœ‰่‡ชๅ‹•ๅŒ–ๅทฅๅ…ทๅœจๆชขๆŸฅใ€‚ + +ๅฆ‚ๆžœ้‚„ๆœ‰ๅ…ถไป–้ขจๆ ผๆˆ–ไธ€่‡ดๆ€ง็š„้œ€ๆฑ‚๏ผŒๆˆ‘ๆœƒ็›ดๆŽฅๆๅ‡บ่ซ‹ๆฑ‚๏ผŒๆˆ–ๆ˜ฏๅœจไธŠ้ขๅ†่ฃœไธŠ้œ€่ฆ็š„ไฟฎๆ”นๆไบคใ€‚ + +### ๆชขๆŸฅ็จ‹ๅผ็ขผ { #check-the-code } + +* ๆชขๆŸฅไธฆ้–ฑ่ฎ€็จ‹ๅผ็ขผ๏ผŒ็œ‹็œ‹ๆ˜ฏๅฆๅˆ็†๏ผŒ**ๅœจๆœฌๆฉŸๅŸท่กŒ**ไธฆ็ขบ่ชๅฎƒๆ˜ฏๅฆ็œŸ็š„่งฃๆฑบไบ†ๅ•้กŒใ€‚ + +* ็„ถๅพŒ**็•™่จ€**่ชชไฝ ๅšไบ†้€™ไบ›๏ผŒ้€™ๆจฃๆˆ‘ๆ‰็Ÿฅ้“ไฝ ็œŸ็š„ๆชขๆŸฅ้Žไบ†ใ€‚ + +/// info + +ๅพˆ้บๆ†พ๏ผŒๆˆ‘ไธ่ƒฝๅƒ…ๅ› ็‚บไธ€ๅ€‹ PR ๆœ‰ๅฅฝๅนพๅ€‹ๆ ธๅฏๅฐฑ็›ดๆŽฅไฟกไปปๅฎƒใ€‚ + +็™ผ็”Ÿ้Žๅฅฝๅนพๆฌก๏ผŒPR ๆœ‰ 3ใ€5 ๅ€‹็”š่‡ณๆ›ดๅคšๆ ธๅฏ๏ผŒๅฏ่ƒฝๆ˜ฏๅ› ็‚บๆ่ฟฐๅพˆๅธๅผ•ไบบ๏ผŒไฝ†็•ถๆˆ‘ๅฏฆ้š›ๆชขๆŸฅๆ™‚๏ผŒๅฎƒๅ…ถๅฏฆๆ˜ฏๅฃž็š„ใ€ๆœ‰ bug๏ผŒๆˆ–ๆ˜ฏๆ นๆœฌๆฒ’ๆœ‰่งฃๆฑบๅฎƒๅฎฃ็จฑ่ฆ่งฃๆฑบ็š„ๅ•้กŒใ€‚๐Ÿ˜… + +ๆ‰€ไปฅ๏ผŒ็œŸ็š„ๅพˆ้‡่ฆ็š„ๆ˜ฏไฝ ่ฆๅฏฆ้š›้–ฑ่ฎ€ไธฆๅŸท่กŒ็จ‹ๅผ็ขผ๏ผŒไธฆๅœจ็•™่จ€ไธญ่ฎ“ๆˆ‘็Ÿฅ้“ไฝ ๅš้Žไบ†ใ€‚๐Ÿค“ + +/// + +* ๅฆ‚ๆžœ PR ๆœ‰ๆฉŸๆœƒๅ†่ขซ็ฐกๅŒ–๏ผŒไฝ ๅฏไปฅๆๅ‡บ่ฆๆฑ‚๏ผŒไฝ†ๆฒ’ๅฟ…่ฆๅคช้ŽๆŒ‘ๅ‰”๏ผŒๅพˆๅคšไบ‹ๆƒ…ๆ˜ฏไธป่ง€็š„๏ผˆๆˆ‘่‡ชๅทฑไนŸๆœƒๆœ‰ไธป่ง€็œ‹ๆณ• ๐Ÿ™ˆ๏ผ‰๏ผŒๆ‰€ไปฅๆœ€ๅฅฝ่š็„ฆๅœจ้—œ้ต็š„ไบ‹ๆƒ…ไธŠใ€‚ + +### ๆธฌ่ฉฆ { #tests } + +* ๅนซๆˆ‘็ขบ่ช PR ๆœ‰**ๆธฌ่ฉฆ**ใ€‚ + +* ๆชขๆŸฅๅœจ PR ไน‹ๅ‰๏ผŒๆธฌ่ฉฆๆœƒ**ๅคฑๆ•—**ใ€‚๐Ÿšจ + +* ็„ถๅพŒๆชขๆŸฅๅœจ PR ไน‹ๅพŒ๏ผŒๆธฌ่ฉฆๆœƒ**้€š้Ž**ใ€‚โœ… + +* ๅพˆๅคš PR ไธฆๆฒ’ๆœ‰ๆธฌ่ฉฆ๏ผŒไฝ ๅฏไปฅ**ๆ้†’**ไป–ๅ€‘ๅŠ ไธŠๆธฌ่ฉฆ๏ผŒๆˆ–็”š่‡ณ**ๅปบ่ญฐ**ไธ€ไบ›ๆธฌ่ฉฆใ€‚้€™ๆ˜ฏๆœ€่Šฑๆ™‚้–“็š„ไบ‹ไน‹ไธ€๏ผŒ่€Œไฝ ๅฏไปฅๅœจ้€™ๆ–น้ขๅนซไธŠๅพˆๅคง็š„ๅฟ™ใ€‚ + +* ๆŽฅ่‘—ไนŸ่ซ‹็•™่จ€ไฝ ๅ˜—่ฉฆไบ†ไป€้บผ๏ผŒ้€™ๆจฃๆˆ‘ๅฐฑ็Ÿฅ้“ไฝ ๆœ‰ๆชขๆŸฅ้Žใ€‚๐Ÿค“ + +## ๅปบ็ซ‹ Pull Request { #create-a-pull-request } + +ไฝ ๅฏไปฅ้€้Ž Pull Request ไพ†[่ฒข็ป](contributing.md){.internal-link target=_blank}ๅŽŸๅง‹็ขผ๏ผŒไพ‹ๅฆ‚๏ผš + +* ไฟฎๆญฃๆ–‡ๆช”ไธญไฝ ็™ผ็พ็š„้Œฏๅญ—ใ€‚ +* ๅˆ†ไบซไฝ ๅปบ็ซ‹ๆˆ–็™ผ็พ็š„ FastAPI ็›ธ้—œๆ–‡็ซ ใ€ๅฝฑ็‰‡ๆˆ– podcast๏ผŒๆ–นๆณ•ๆ˜ฏ็ทจ่ผฏ้€™ๅ€‹ๆช”ๆกˆใ€‚ + * ่ซ‹็ขบไฟๆŠŠไฝ ็š„้€ฃ็ตๅŠ ๅˆฐๅฐๆ‡‰็ซ ็ฏ€็š„้–‹้ ญใ€‚ +* ๅ”ๅŠฉๆŠŠ[ๆ–‡ไปถ็ฟป่ญฏ](contributing.md#translations){.internal-link target=_blank}ๆˆไฝ ็š„่ชž่จ€ใ€‚ + * ไฝ ไนŸๅฏไปฅๅนซๅฟ™ๅฏฉๆŸฅไป–ไบบๆไบค็š„็ฟป่ญฏใ€‚ +* ๆ่ญฐๆ–ฐ็š„ๆ–‡ไปถ็ซ ็ฏ€ใ€‚ +* ไฟฎๅพฉๆ—ขๆœ‰็š„ issue๏ผbugใ€‚ + * ่จ˜ๅพ—่ฆๅŠ ไธŠๆธฌ่ฉฆใ€‚ +* ๆ–ฐๅขžไธ€ๅ€‹ๅŠŸ่ƒฝใ€‚ + * ่จ˜ๅพ—่ฆๅŠ ไธŠๆธฌ่ฉฆใ€‚ + * ่‹ฅ็›ธ้—œ๏ผŒ่ซ‹่จ˜ๅพ—่ฃœไธŠๆ–‡ไปถใ€‚ + +## ๅ”ๅŠฉ็ถญ่ญท FastAPI { #help-maintain-fastapi } + +ๅนซๆˆ‘ไธ€่ตท็ถญ่ญท **FastAPI**๏ผ๐Ÿค“ + +ๆœ‰ๅพˆๅคšไบ‹ๆƒ…่ฆๅš๏ผŒ่€Œๅ…ถไธญๅคงๅคšๆ•ธๅ…ถๅฏฆ**ไฝ **ๅฐฑ่ƒฝๅฎŒๆˆใ€‚ + +ไฝ ็พๅœจๅฐฑ่ƒฝๅš็š„ไธป่ฆไปปๅ‹™ๆœ‰๏ผš + +* [ๅœจ GitHub ๅนซๅŠฉไป–ไบบ่งฃ็ญ”ๅ•้กŒ](#help-others-with-questions-in-github){.internal-link target=_blank}๏ผˆ่ฆ‹ไธŠๆ–น็ซ ็ฏ€๏ผ‰ใ€‚ +* [ๅฏฉๆ ธ Pull Request](#review-pull-requests){.internal-link target=_blank}๏ผˆ่ฆ‹ไธŠๆ–น็ซ ็ฏ€๏ผ‰ใ€‚ + +้€™ๅ…ฉไปถไบ‹ๆ˜ฏ**ๆœ€่€—ๆ™‚**็š„ใ€‚้€™ไนŸๆ˜ฏ็ถญ่ญท FastAPI ็š„ไธป่ฆๅทฅไฝœใ€‚ + +ๅฆ‚ๆžœไฝ ่ƒฝๅœจ้€™ๆ–น้ขๅนซๆˆ‘๏ผŒ**ไฝ ๅฐฑๆ˜ฏๅœจๅนซๆˆ‘็ถญ่ญท FastAPI**๏ผŒไธฆ็ขบไฟๅฎƒ่ƒฝ**ๆ›ดๅฟซๆ›ดๅฅฝๅœฐๅ‰้€ฒ**ใ€‚๐Ÿš€ + +## ๅŠ ๅ…ฅ่Šๅคฉๅฎค { #join-the-chat } + +ๅŠ ๅ…ฅ ๐Ÿ‘ฅ Discord ่Šๅคฉไผบๆœๅ™จ ๐Ÿ‘ฅ๏ผŒ่ˆ‡ FastAPI ็คพ็พค็š„ๅ…ถไป–ไบบไธ€่ตทไบคๆตใ€‚ + +/// tip + +่‹ฅ่ฆๆๅ•๏ผŒ่ซ‹ๅˆฐ GitHub Discussions๏ผŒๅœจ้‚ฃ่ฃกๆ›ดๆœ‰ๆฉŸๆœƒ็ฒๅพ—[FastAPI ๅฐˆๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank}็š„ๅ”ๅŠฉใ€‚ + +่Šๅคฉๅฎค่ซ‹ๅƒ…็”จๆ–ผๅ…ถไป–ไธ€่ˆฌๆ€ง็š„ไบคๆตใ€‚ + +/// + +### ไธ่ฆๅœจ่Šๅคฉๅฎคๆๅ• { #dont-use-the-chat-for-questions } + +่ซ‹่จ˜ๅพ—๏ผŒ็”ฑๆ–ผ่Šๅคฉๅฎคๅ…่จฑ่ผƒใ€Œ่‡ช็”ฑ็š„ๅฐ่ฉฑใ€๏ผŒๅพˆๅฎนๆ˜“ๆๅ‡บ้Žๆ–ผ็ฑ ็ตฑใ€่ผƒ้›ฃๅ›ž็ญ”็š„ๅ•้กŒ๏ผŒๅ› ๆญคไฝ ๅฏ่ƒฝไธๆœƒๅพ—ๅˆฐ็ญ”ๆกˆใ€‚ + +ๅœจ GitHub ไธŠ๏ผŒๆจกๆฟๆœƒๅผ•ๅฐŽไฝ ๅฏซๅ‡บๅˆ้ฉ็š„ๆๅ•๏ผŒ่ฎ“ไฝ ๆ›ดๅฎนๆ˜“ๅพ—ๅˆฐๅฅฝ็š„่งฃ็ญ”๏ผŒ็”š่‡ณๅœจๆๅ•ๅ‰ๅฐฑ่‡ชๅทฑ่งฃๆฑบๅ•้กŒใ€‚่€Œไธ”ๅœจ GitHub ไธŠ๏ผŒๆˆ‘่ƒฝ็ขบไฟๆœ€็ต‚้ƒฝๆœƒๅ›ž่ฆ†๏ผˆๅณไฝฟ้œ€่ฆไธ€ไบ›ๆ™‚้–“๏ผ‰ใ€‚ๆˆ‘ๅ€‹ไบบ็„กๆณ•ๅœจ่Šๅคฉ็ณป็ตฑๅšๅˆฐ้€™ไธ€้ปžใ€‚๐Ÿ˜… + +่Šๅคฉ็ณป็ตฑไธญ็š„ๅฐ่ฉฑไนŸไธๅƒ GitHub ้‚ฃๆจฃๅฎนๆ˜“่ขซๆœๅฐ‹๏ผŒๅ› ๆญคๅ•้กŒ่ˆ‡็ญ”ๆกˆๅฏ่ƒฝๅœจๅฐ่ฉฑไธญๆทนๆฒ’ใ€‚่€Œไธ”ๅชๆœ‰ GitHub ไธŠ็š„ๅ•้กŒ่ˆ‡ๅ›ž็ญ”ๆ‰ๆœƒ่ขซ่จˆๅ…ฅๆˆ็‚บ[FastAPI ๅฐˆๅฎถ](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๏ผŒๅ› ๆญคไฝ ๅœจ GitHub ไธŠๆ›ดๆœ‰ๆฉŸๆœƒ็ฒๅพ—้—œๆณจใ€‚ + +ๅฆไธ€ๆ–น้ข๏ผŒ่Šๅคฉๅฎค่ฃกๆœ‰ๆˆๅƒไธŠ่ฌ็š„ไฝฟ็”จ่€…๏ผŒๆ‰€ไปฅๅนพไนŽ้šจๆ™‚้ƒฝๆœ‰ๅพˆๅคง็š„ๆฉŸๆœƒ่ƒฝๆ‰พๅˆฐไบบ่Šๅคฉใ€‚๐Ÿ˜„ + +## ่ดŠๅŠฉไฝœ่€… { #sponsor-the-author } + +ๅฆ‚ๆžœไฝ ็š„**็”ขๅ“๏ผๅ…ฌๅธ**ไพ่ณดๆˆ–่ˆ‡ **FastAPI** ็›ธ้—œ๏ผŒไธ”ไฝ ๆƒณ่งธๅŠๅฎƒ็š„ไฝฟ็”จ่€…๏ผŒไฝ ๅฏไปฅ้€้Ž GitHub sponsors ่ดŠๅŠฉไฝœ่€…๏ผˆๆˆ‘๏ผ‰ใ€‚ไพๆ“šไธๅŒ็ดšๅˆฅ๏ผŒไฝ ๅฏ่ƒฝๆœƒๅพ—ๅˆฐไธ€ไบ›้กๅค–็ฆๅˆฉ๏ผŒไพ‹ๅฆ‚ๅœจๆ–‡ไปถไธญ้กฏ็คบๅพฝ็ซ ใ€‚๐ŸŽ + +--- + +ๆ„Ÿ่ฌ๏ผ๐Ÿš€ diff --git a/docs/zh-hant/docs/history-design-future.md b/docs/zh-hant/docs/history-design-future.md new file mode 100644 index 0000000000..b7f57a3636 --- /dev/null +++ b/docs/zh-hant/docs/history-design-future.md @@ -0,0 +1,79 @@ +# ๆญทๅฒใ€่จญ่จˆ่ˆ‡ๆœชไพ† { #history-design-and-future } + +ไธไน…ไน‹ๅ‰๏ผŒไธ€ไฝ **FastAPI** ไฝฟ็”จ่€…ๆๅ•๏ผš + +> ้€™ๅ€‹ๅฐˆๆกˆ็š„ๆญทๅฒๆ˜ฏไป€้บผ๏ผŸ็œ‹่ตทไพ†ๅฎƒๅœจ็Ÿญ็Ÿญๅนพ้€ฑๅ…งๅพž้ป˜้ป˜็„กๅ่ฎŠๅพ—้žๅธธๅŽฒๅฎณ [...] + +ไปฅไธ‹ๆ˜ฏๅ…ถไธญไธ€ๅฐๆฎตๆญทๅฒใ€‚ + +## ๆ›ฟไปฃๆ–นๆกˆ { #alternatives } + +ๅคšๅนดไพ†ๆˆ‘ไธ€็›ดๅœจๆ‰“้€ ๅ…ทๆœ‰่ค‡้›œ้œ€ๆฑ‚็š„ API๏ผˆๆฉŸๅ™จๅญธ็ฟ’ใ€ๅˆ†ๆ•ฃๅผ็ณป็ตฑใ€้žๅŒๆญฅๅทฅไฝœใ€NoSQL ่ณ‡ๆ–™ๅบซ็ญ‰๏ผ‰๏ผŒไธฆๅธถ้ ˜ๅคšๅ€‹้–‹็™ผๅœ˜้šŠใ€‚ + +ๅœจๆญค้Ž็จ‹ไธญ๏ผŒๆˆ‘้œ€่ฆ่ชฟๆŸฅใ€ๆธฌ่ฉฆไธฆไฝฟ็”จ่จฑๅคšๆ›ฟไปฃๆ–นๆกˆใ€‚ + +**FastAPI** ็š„ๆญทๅฒ๏ผŒๅœจๅพˆๅคง็จ‹ๅบฆไธŠไนŸๆ˜ฏๅ…ถๅ‰่บซๅทฅๅ…ท็š„ๆญทๅฒใ€‚ + +ๅฆ‚ๅœจ[ๆ›ฟไปฃๆ–นๆกˆ](alternatives.md){.internal-link target=_blank}็ซ ็ฏ€ๆ‰€่ฟฐ๏ผš + +
+ +่‹ฅๆฒ’ๆœ‰ไป–ไบบ็š„ๅ‰ๆœŸๆˆๆžœ๏ผŒๅฐฑไธๆœƒๆœ‰ **FastAPI**ใ€‚ + +ๅ…ˆๅ‰ๅทฒๆœ‰่จฑๅคšๅทฅๅ…ทๅ•Ÿ็™ผไบ†ๅฎƒ็š„่ช•็”Ÿใ€‚ + +ๆˆ‘ๆ›พ็ถ“ๅคšๅนด้ฟๅ…ๅ†ๅŽปๆ‰“้€ ไธ€ๅ€‹ๆ–ฐๆก†ๆžถใ€‚่ตทๅˆๆˆ‘ๅ˜—่ฉฆ็”จๅ„็จฎไธๅŒ็š„ๆก†ๆžถใ€ๅค–ๆŽ›่ˆ‡ๅทฅๅ…ท๏ผŒไพ†ๆปฟ่ถณ **FastAPI** ๆถต่“‹็š„ๆ‰€ๆœ‰ๅŠŸ่ƒฝใ€‚ + +ไฝ†ๅœจๆŸๅ€‹ๆ™‚ๅˆป๏ผŒๅˆฅ็„ก้ธๆ“‡๏ผŒๅช่ƒฝๆ‰“้€ ไธ€ๅ€‹ๅŒๆ™‚ๆไพ›ๆ‰€ๆœ‰้€™ไบ›ๅŠŸ่ƒฝ็š„ๆฑ่ฅฟ๏ผŒๅ–้ŽๅŽปๅทฅๅ…ทไน‹้•ท๏ผŒไธฆไปฅๅฏ่ƒฝ็š„ๆœ€ไฝณๆ–นๅผๅŠ ไปฅ็ตๅˆ๏ผŒ้‚„้‹็”จไบ†ไปฅๅพ€็”š่‡ณไธๅญ˜ๅœจ็š„่ชž่จ€ๅŠŸ่ƒฝ๏ผˆPython 3.6+ ็š„ๅž‹ๅˆฅๆ็คบ๏ผ‰ใ€‚ + +
+ +## ่ชฟ็ ” { #investigation } + +้€้Žๅฏฆ้š›ไฝฟ็”จ้€™ไบ›ๆ›ฟไปฃๆ–นๆกˆ๏ผŒๆˆ‘ๅพ—ไปฅๅ‘ๅฎƒๅ€‘ๅญธ็ฟ’ใ€ๆฑฒๅ–ๆƒณๆณ•๏ผŒไธฆไปฅๆˆ‘่ƒฝ็‚บ่‡ชๅทฑ่ˆ‡ๅˆไฝœ้–‹็™ผๅœ˜้šŠๆ‰พๅˆฐ็š„ๆœ€ไฝณๆ–นๅผๅŠ ไปฅๆ•ดๅˆใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅพˆๆธ…ๆฅš็†ๆƒณไธŠๆ‡‰ไปฅๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๆ็คบ็‚บๅŸบ็คŽใ€‚ + +ๅŒๆ™‚๏ผŒๆœ€ไฝณๅšๆณ•ๅฐฑๆ˜ฏๆŽก็”จ็พๆœ‰ๆจ™ๆบ–ใ€‚ + +ๅ› ๆญค๏ผŒๅœจ้–‹ๅง‹ๆ’ฐๅฏซ **FastAPI** ไน‹ๅ‰๏ผŒๆˆ‘่Šฑไบ†ๅฅฝๅนพๅ€‹ๆœˆ็ ”็ฉถ OpenAPIใ€JSON Schemaใ€OAuth2 ็ญ‰่ฆ็ฏ„๏ผŒไบ†่งฃๅฎƒๅ€‘ไน‹้–“็š„้—œไฟ‚ใ€้‡็–Š่ˆ‡ๅทฎ็•ฐใ€‚ + +## ่จญ่จˆ { #design } + +ๆŽฅ่‘—๏ผŒๆˆ‘่Šฑๆ™‚้–“่จญ่จˆไฝœ็‚บไฝฟ็”จ่€…๏ผˆไฝœ็‚บไฝฟ็”จ FastAPI ็š„้–‹็™ผ่€…๏ผ‰ๆ™‚ๅธŒๆœ›ๆ“ๆœ‰็š„้–‹็™ผ่€…ใ€ŒAPIใ€ใ€‚ + +ๆˆ‘ๅœจๆœ€ๅ—ๆญก่ฟŽ็š„ Python ็ทจ่ผฏๅ™จไธญๆธฌ่ฉฆไบ†ๅคšๅ€‹ๆƒณๆณ•๏ผšPyCharmใ€VS Codeใ€ๅŸบๆ–ผ Jedi ็š„็ทจ่ผฏๅ™จใ€‚ + +ๆ นๆ“šๆœ€ๆ–ฐ็š„ Python ้–‹็™ผ่€…่ชฟๆŸฅ๏ผŒ้€™ไบ›ๅทฅๅ…ทๆถต่“‹็ด„ 80% ็š„ไฝฟ็”จ่€…ใ€‚ + +้€™่กจ็คบ **FastAPI** ๅทฒ้‡ๅฐ 80% ็š„ Python ้–‹็™ผ่€…ๆ‰€ไฝฟ็”จ็š„็ทจ่ผฏๅ™จ้€ฒ่กŒ้Žๅฐˆ้–€ๆธฌ่ฉฆใ€‚่€Œ็”ฑๆ–ผๅ…ถไป–ๅคšๆ•ธ็ทจ่ผฏๅ™จ็š„่กŒ็‚บไนŸ้กžไผผ๏ผŒ้€™ไบ›ๅ„ช้ปžๅนพไนŽๅœจๆ‰€ๆœ‰็ทจ่ผฏๅ™จไธŠ้ƒฝ่ƒฝ็”Ÿๆ•ˆใ€‚ + +่—‰ๆญคๆˆ‘ๆ‰พๅˆฐไบ†็›กๅฏ่ƒฝๆธ›ๅฐ‘็จ‹ๅผ็ขผ้‡่ค‡ใ€ๅœจๅ„่™•ๆไพ›่‡ชๅ‹•่ฃœๅ…จใ€ๅž‹ๅˆฅ่ˆ‡้Œฏ่ชคๆชขๆŸฅ็ญ‰็š„ๆœ€ไฝณๆ–นๅผใ€‚ + +ไธ€ๅˆ‡้ƒฝๆ˜ฏ็‚บไบ†่ฎ“ๆ‰€ๆœ‰้–‹็™ผ่€…้ƒฝ่ƒฝๆ“ๆœ‰ๆœ€ไฝณ็š„้–‹็™ผ้ซ”้ฉ—ใ€‚ + +## ้œ€ๆฑ‚ { #requirements } + +ๅœจๆธฌ่ฉฆๅคš็จฎๆ›ฟไปฃๆ–นๆกˆๅพŒ๏ผŒๆˆ‘ๆฑบๅฎšๆŽก็”จ **Pydantic**๏ผŒๅ› ็‚บๅฎƒ็š„ๅ„ชๅ‹ขใ€‚ + +้šจๅพŒๆˆ‘ไนŸๅฐๅฎƒๅšๅ‡บ่ฒข็ป๏ผŒไฝฟๅ…ถๅฎŒๅ…จ็ฌฆๅˆ JSON Schemaใ€ๆ”ฏๆดไปฅไธๅŒๆ–นๅผๅฎš็พฉ็ด„ๆŸ๏ผŒไธฆไพๆ“šๅœจๅคšๆฌพ็ทจ่ผฏๅ™จไธญ็š„ๆธฌ่ฉฆ็ตๆžœๆ”น้€ฒ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผˆๅž‹ๅˆฅๆชขๆŸฅใ€่‡ชๅ‹•่ฃœๅ…จ๏ผ‰ใ€‚ + +ๅœจ้–‹็™ผ้Ž็จ‹ไธญ๏ผŒๆˆ‘ไนŸๅฐ **Starlette**๏ผˆๅฆไธ€ๅ€‹้—œ้ตไพ่ณด๏ผ‰ๅšๅ‡บ่ฒข็ปใ€‚ + +## ้–‹็™ผ { #development } + +็•ถๆˆ‘้–‹ๅง‹่‘—ๆ‰‹ๅฏฆไฝœ **FastAPI** ๆœฌ่บซๆ™‚๏ผŒๅคšๆ•ธๆ‹ผๅœ–ๅทฒ็ถ“ๅฐฑ็ท’๏ผŒ่จญ่จˆๅทฒๅฎš๏ผŒ้œ€ๆฑ‚่ˆ‡ๅทฅๅ…ทๅทฒๅ‚™้ฝŠ๏ผŒๅฐๅ„้ …ๆจ™ๆบ–่ˆ‡่ฆ็ฏ„็š„็†่งฃไนŸๆธ…ๆ™ฐไธ”ๆ–ฐ้ฎฎใ€‚ + +## ๆœชไพ† { #future } + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒ**FastAPI** ๅŠๅ…ถ็†ๅฟตๅทฒ็ถ“ๅฐ่จฑๅคšไบบๆœ‰ๅนซๅŠฉใ€‚ + +็›ธ่ผƒๅ…ˆๅ‰็š„ๆ›ฟไปฃๆ–นๆกˆ๏ผŒๅฎƒๆ›ด้ฉๅˆ่จฑๅคšไฝฟ็”จๆƒ…ๅขƒ๏ผŒๅ› ่€Œ่ขซ้ธ็”จใ€‚ + +่จฑๅคš้–‹็™ผ่€…่ˆ‡ๅœ˜้šŠ๏ผˆๅŒ…ๆ‹ฌๆˆ‘ๅ’Œๆˆ‘็š„ๅœ˜้šŠ๏ผ‰ๅทฒ็ถ“ๅœจไป–ๅ€‘็š„ๅฐˆๆกˆไธญไพ่ณด **FastAPI**ใ€‚ + +ไฝ†ไปๆœ‰่จฑๅคšๆ”น้€ฒ่ˆ‡ๅŠŸ่ƒฝๅณๅฐ‡ๅˆฐไพ†ใ€‚ + +**FastAPI** ็š„ๅ‰ๆ™ฏ้žๅธธๅ…‰ๆ˜Žใ€‚ + +ไนŸ้žๅธธๆ„Ÿ่ฌ[ไฝ ็š„ๅนซๅŠฉ](help-fastapi.md){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/how-to/authentication-error-status-code.md b/docs/zh-hant/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..9a8de4c910 --- /dev/null +++ b/docs/zh-hant/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,15 @@ +# ไฝฟ็”จ่ˆŠ็š„ 403 ่บซๅˆ†้ฉ—่ญ‰้Œฏ่ชค็‹€ๆ…‹็ขผ { #use-old-403-authentication-error-status-codes } + +ๅœจ FastAPI ็‰ˆๆœฌ `0.122.0` ไน‹ๅ‰๏ผŒ็•ถๅ…งๅปบ็š„ๅฎ‰ๅ…จๅทฅๅ…ทๅœจ่บซๅˆ†้ฉ—่ญ‰ๅคฑๆ•—ๅพŒๅ›žๅ‚ณ้Œฏ่ชค็ตฆ็”จๆˆถ็ซฏๆ™‚๏ผŒๆœƒไฝฟ็”จ HTTP ็‹€ๆ…‹็ขผ `403 Forbidden`ใ€‚ + +ๅพž FastAPI ็‰ˆๆœฌ `0.122.0` ่ตท๏ผŒๆ”น็‚บไฝฟ็”จๆ›ดๅˆ้ฉ็š„ HTTP ็‹€ๆ…‹็ขผ `401 Unauthorized`๏ผŒไธฆๅœจๅ›žๆ‡‰ไธญไพๆ“š HTTP ่ฆ็ฏ„ๅŠ ไธŠๅˆ็†็š„ `WWW-Authenticate` ๆจ™้ ญ๏ผŒๅƒ่€ƒ RFC 7235ใ€RFC 9110ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็š„็”จๆˆถ็ซฏๅ› ๆŸไบ›ๅŽŸๅ› ไพ่ณดๆ–ผ่ˆŠ่กŒ็‚บ๏ผŒไฝ ๅฏไปฅๅœจไฝ ็š„ security ้กžๅˆฅไธญ่ฆ†ๅฏซ `make_not_authenticated_error` ๆ–นๆณ•ไปฅๆขๅพฉ่ˆŠ็š„่กŒ็‚บใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅปบ็ซ‹ `HTTPBearer` ็š„ๅญ้กžๅˆฅ๏ผŒ่ฎ“ๅฎƒๅ›žๅ‚ณ `403 Forbidden` ้Œฏ่ชค๏ผŒ่€Œไธๆ˜ฏ้ ่จญ็š„ `401 Unauthorized` ้Œฏ่ชค๏ผš + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip +ๆณจๆ„้€™ๅ€‹ๅ‡ฝๅผๅ›žๅ‚ณ็š„ๆ˜ฏไพ‹ๅค–็‰ฉไปถๆœฌ่บซ๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๆ‹‹ๅ‡บๅฎƒใ€‚ๆ‹‹ๅ‡บ็š„ๅ‹•ไฝœๆœƒๅœจๅ…ถ้ค˜็š„ๅ…ง้ƒจ็จ‹ๅผ็ขผไธญ่™•็†ใ€‚ +/// diff --git a/docs/zh-hant/docs/how-to/conditional-openapi.md b/docs/zh-hant/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000..5c091e5b7b --- /dev/null +++ b/docs/zh-hant/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# ๆขไปถๅผ OpenAPI { #conditional-openapi } + +ๅฆ‚ๆžœ้œ€่ฆ๏ผŒไฝ ๅฏไปฅ็”จ่จญๅฎš่ˆ‡็’ฐๅขƒ่ฎŠๆ•ธ๏ผŒไพๆ“šๅŸท่กŒ็’ฐๅขƒๆœ‰ๆขไปถๅœฐ่ชฟๆ•ด OpenAPI๏ผŒ็”š่‡ณๅฎŒๅ…จๅœ็”จๅฎƒใ€‚ + +## ้—œๆ–ผๅฎ‰ๅ…จๆ€งใ€API ่ˆ‡ๆ–‡ไปถ { #about-security-apis-and-docs } + +ๅœจๆญฃๅผ็’ฐๅขƒไธญ้šฑ่—ๆ–‡ไปถ UI *ไธๆ‡‰่ฉฒ* ๆ˜ฏ็”จไพ†ไฟ่ญท API ็š„ๆ–นๅผใ€‚ + +้€™ไธฆไธๆœƒ็‚บไฝ ็š„ API ๅขžๆทปไปปไฝ•้กๅค–็š„ๅฎ‰ๅ…จๆ€ง๏ผŒ*่ทฏๅพ‘ๆ“ไฝœ* ไป่ˆŠ็…งๅธธๅฏ็”จใ€‚ + +่‹ฅไฝ ็š„็จ‹ๅผ็ขผๆœ‰ๅฎ‰ๅ…จๆ€ง็ผบ้™ท๏ผŒๅฎƒไพ็„ถๆœƒๅญ˜ๅœจใ€‚ + +้šฑ่—ๆ–‡ไปถๅชๆœƒ่ฎ“ไป–ไบบๆ›ด้›ฃ็†่งฃๅฆ‚ไฝ•่ˆ‡ไฝ ็š„ API ไบ’ๅ‹•๏ผŒไนŸๅฏ่ƒฝ่ฎ“ไฝ ๅœจๆญฃๅผ็’ฐๅขƒ้™ค้Œฏๆ›ดๅ›ฐ้›ฃใ€‚้€™้€šๅธธๅƒ…่ขซ่ฆ–็‚บไธ€็จฎ ไปฅ้šฑๅŒฟๆฑ‚ๅฎ‰ๅ…จใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณไฟ่ญท API๏ผŒๆœ‰่จฑๅคšๆ›ดๅฅฝ็š„ไฝœๆณ•๏ผŒไพ‹ๅฆ‚๏ผš + +- ็ขบไฟ้‡ๅฐ่ซ‹ๆฑ‚ๆœฌๆ–‡่ˆ‡ๅ›žๆ‡‰๏ผŒๅ…ทๅ‚™ๅฎš็พฉ่‰ฏๅฅฝ็š„ Pydantic ๆจกๅž‹ใ€‚ +- ้€้Žไพ่ณด่จญๅฎšๆ‰€้œ€็š„ๆฌŠ้™่ˆ‡่ง’่‰ฒใ€‚ +- ๅˆ‡ๅ‹ฟๅ„ฒๅญ˜ๆ˜Žๆ–‡ๅฏ†็ขผ๏ผŒๅชๅ„ฒๅญ˜ๅฏ†็ขผ้›œๆนŠใ€‚ +- ๅฏฆไฝœไธฆไฝฟ็”จๆˆ็†Ÿไธ”ๅปฃ็‚บไบบ็Ÿฅ็š„ๅฏ†็ขผๅญธๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ pwdlib ่ˆ‡ JWT ๆฌŠๆ–็ญ‰ใ€‚ +- ่ฆ–้œ€่ฆไปฅ OAuth2 scopes ๆ–ฐๅขžๆ›ด็ดฐ็ทป็š„ๆฌŠ้™ๆŽง็ฎกใ€‚ +- ...็ญ‰ใ€‚ + +ๅ„˜็ฎกๅฆ‚ๆญค๏ผŒๅœจๆŸไบ›็‰นๅฎšๆƒ…ๅขƒไธ‹๏ผŒไฝ ๅฏ่ƒฝ็ขบๅฏฆ้œ€่ฆๅœจๆŸไบ›็’ฐๅขƒ๏ผˆไพ‹ๅฆ‚ๆญฃๅผ็’ฐๅขƒ๏ผ‰ๅœ็”จ API ๆ–‡ไปถ๏ผŒๆˆ–ไพๆ“š็’ฐๅขƒ่ฎŠๆ•ธ็š„่จญๅฎšไพ†ๆฑบๅฎšๆ˜ฏๅฆๅ•Ÿ็”จใ€‚ + +## ้€้Ž่จญๅฎš่ˆ‡็’ฐๅขƒ่ฎŠๆ•ธ็š„ๆขไปถๅผ OpenAPI { #conditional-openapi-from-settings-and-env-vars } + +ไฝ ๅฏไปฅ็”จ็›ธๅŒ็š„ Pydantic ่จญๅฎš๏ผŒไพ†้…็ฝฎ็”ข็”Ÿ็š„ OpenAPI ่ˆ‡ๆ–‡ไปถ UIใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +้€™่ฃกๆˆ‘ๅ€‘ๅฎฃๅ‘Š `openapi_url` ่จญๅฎš๏ผŒ้ ่จญๅ€ผๅŒๆจฃๆ˜ฏ `"/openapi.json"`ใ€‚ + +ๆŽฅ่‘—ๅœจๅปบ็ซ‹ `FastAPI` ๆ‡‰็”จๆ™‚ไฝฟ็”จๅฎƒใ€‚ + +็„ถๅพŒไฝ ๅฏไปฅๅฐ‡็’ฐๅขƒ่ฎŠๆ•ธ `OPENAPI_URL` ่จญ็‚บ็ฉบๅญ—ไธฒ๏ผŒไปฅๅœ็”จ OpenAPI๏ผˆๅŒ…ๅซๆ–‡ไปถ UI๏ผ‰๏ผŒๅฆ‚ไธ‹๏ผš + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ไน‹ๅพŒ่‹ฅไฝ ้€ ่จช `/openapi.json`ใ€`/docs` ๆˆ– `/redoc`๏ผŒๆœƒ็œ‹ๅˆฐๅฆ‚ไธ‹็š„ `404 Not Found` ้Œฏ่ชค๏ผš + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/zh-hant/docs/how-to/configure-swagger-ui.md b/docs/zh-hant/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000..e5b6d7d1e3 --- /dev/null +++ b/docs/zh-hant/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# ่จญๅฎš Swagger UI { #configure-swagger-ui } + +ไฝ ๅฏไปฅ่จญๅฎšไธ€ไบ›้กๅค–็š„ Swagger UI ๅƒๆ•ธใ€‚ + +่ฆ่จญๅฎšๅฎƒๅ€‘๏ผŒๅปบ็ซ‹ `FastAPI()` ๆ‡‰็”จ็‰ฉไปถๆ™‚๏ผŒๆˆ–ๅ‘ผๅซ `get_swagger_ui_html()` ๅ‡ฝๅผๆ™‚๏ผŒๅ‚ณๅ…ฅๅƒๆ•ธ `swagger_ui_parameters`ใ€‚ + +`swagger_ui_parameters` ๆŽฅๅ—ไธ€ๅ€‹ dict๏ผŒๅ…งๅฎนๆœƒ็›ดๆŽฅๅ‚ณ็ตฆ Swagger UI ไฝœ็‚บ่จญๅฎšใ€‚ + +FastAPI ๆœƒๆŠŠ้€™ไบ›่จญๅฎš่ฝ‰ๆ›ๆˆ JSON๏ผŒไปฅไพฟ่ˆ‡ JavaScript ็›ธๅฎน๏ผŒๅ› ็‚บ Swagger UI ้œ€่ฆ็š„ๆ˜ฏ้€™็จฎๆ ผๅผใ€‚ + +## ๅœ็”จ่ชžๆณ•้†’็›ฎๆ็คบ { #disable-syntax-highlighting } + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๅœจ Swagger UI ไธญๅœ็”จ่ชžๆณ•้†’็›ฎๆ็คบ๏ผˆsyntax highlighting๏ผ‰ใ€‚ + +ไธๆ›ดๅ‹•่จญๅฎšๆ™‚๏ผŒ่ชžๆณ•้†’็›ฎๆ็คบ้ ่จญ็‚บๅ•Ÿ็”จ๏ผš + + + +ไฝ†ไฝ ๅฏไปฅๅฐ‡ `syntaxHighlight` ่จญ็‚บ `False` ไพ†ๅœ็”จๅฎƒ๏ผš + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...็„ถๅพŒ Swagger UI ๅฐฑไธๆœƒๅ†้กฏ็คบ่ชžๆณ•้†’็›ฎๆ็คบ๏ผš + + + +## ๆ›ดๆ›ไธป้กŒ { #change-the-theme } + +ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅ็”จ้ต `"syntaxHighlight.theme"` ่จญๅฎš่ชžๆณ•้†’็›ฎๆ็คบไธป้กŒ๏ผˆๆณจๆ„ไธญ้–“ๆœ‰ไธ€ๅ€‹้ปž๏ผ‰๏ผš + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +้€™ๅ€‹่จญๅฎšๆœƒ่ฎŠๆ›ด่ชžๆณ•้†’็›ฎๆ็คบ็š„้…่‰ฒไธป้กŒ๏ผš + + + +## ๆ›ดๆ”น้ ่จญ็š„ Swagger UI ๅƒๆ•ธ { #change-default-swagger-ui-parameters } + +FastAPI ๅ…งๅปบไธ€ไบ›้ ่จญๅƒๆ•ธ๏ผŒ้ฉ็”จๆ–ผๅคงๅคšๆ•ธๆƒ…ๅขƒใ€‚ + +ๅŒ…ๅซไปฅไธ‹้ ่จญ่จญๅฎš๏ผš + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +ไฝ ๅฏไปฅๅœจ `swagger_ui_parameters` ๅƒๆ•ธไธญๆไพ›ไธๅŒ็š„ๅ€ผไพ†่ฆ†่“‹ๅ…ถไธญไปปไธ€้ …ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฆๅœ็”จ `deepLinking`๏ผŒๅฏไปฅๅœจ `swagger_ui_parameters` ๅ‚ณๅ…ฅไปฅไธ‹่จญๅฎš๏ผš + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## ๅ…ถไป– Swagger UI ๅƒๆ•ธ { #other-swagger-ui-parameters } + +่‹ฅ่ฆๆŸฅ็œ‹ๆ‰€ๆœ‰ๅฏ็”จ็š„่จญๅฎš๏ผŒ่ซ‹ๅƒ่€ƒๅฎ˜ๆ–น็š„ Swagger UI ๅƒๆ•ธๆ–‡ไปถใ€‚ + +## ๅƒ…้™ JavaScript ็š„่จญๅฎš { #javascript-only-settings } + +Swagger UI ไนŸๅ…่จฑๆŸไบ›่จญๅฎšๆ˜ฏๅƒ…้™ JavaScript ็š„็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ JavaScript ๅ‡ฝๅผ๏ผ‰ใ€‚ + +FastAPI ไนŸๅŒ…ๅซไปฅไธ‹ๅƒ…้™ JavaScript ็š„ `presets` ่จญๅฎš๏ผš + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +้€™ไบ›ๆ˜ฏ JavaScript ็‰ฉไปถ๏ผŒ่€Œไธๆ˜ฏๅญ—ไธฒ๏ผŒๅ› ๆญค็„กๆณ•็›ดๆŽฅๅพž Python ็จ‹ๅผ็ขผๅ‚ณ้žใ€‚ + +่‹ฅ้œ€่ฆไฝฟ็”จ้€™้กžๅƒ…้™ JavaScript ็š„่จญๅฎš๏ผŒไฝ ๅฏไปฅไฝฟ็”จไธŠ้ขไป‹็ดน็š„ๆ–นๆณ•๏ผš่ฆ†ๅฏซๆ‰€ๆœ‰ Swagger UI ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰๏ผŒไธฆๆ‰‹ๅ‹•ๆ’ฐๅฏซๆ‰€้œ€็š„ JavaScriptใ€‚ diff --git a/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md b/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..4b53945891 --- /dev/null +++ b/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ่‡ช่จ‚ๆ–‡ไปถ UI ้œๆ…‹่ณ‡ๆบ๏ผˆ่‡ชๆˆ‘่จ—็ฎก๏ผ‰ { #custom-docs-ui-static-assets-self-hosting } + +API ๆ–‡ไปถไฝฟ็”จ Swagger UI ่ˆ‡ ReDoc๏ผŒๅฎƒๅ€‘ๅ„่‡ช้œ€่ฆไธ€ไบ› JavaScript ่ˆ‡ CSS ๆช”ๆกˆใ€‚ + +้ ่จญๆƒ…ๆณไธ‹๏ผŒ้€™ไบ›ๆช”ๆกˆๆœƒๅพž CDN ๆไพ›ใ€‚ + +ไฝ†ไฝ ๅฏไปฅ่‡ช่จ‚๏ผšไฝ ๅฏไปฅๆŒ‡ๅฎš็‰นๅฎš็š„ CDN๏ผŒๆˆ–่‡ช่กŒๆไพ›้€™ไบ›ๆช”ๆกˆใ€‚ + +## ็‚บ JavaScript ๅ’Œ CSS ไฝฟ็”จ่‡ช่จ‚ CDN { #custom-cdn-for-javascript-and-css } + +ๅ‡่จญไฝ ๆƒณไฝฟ็”จไธๅŒ็š„ CDN๏ผŒไพ‹ๅฆ‚ไฝฟ็”จ `https://unpkg.com/`ใ€‚ + +่‹ฅไฝ ๆ‰€ๅœจ็š„ๅœ‹ๅฎถ้™ๅˆถ้ƒจๅˆ†็ถฒๅ€๏ผŒ้€™ๆœƒๅพˆๆœ‰็”จใ€‚ + +### ๅœ็”จ่‡ชๅ‹•็”ข็”Ÿ็š„ๆ–‡ไปถ { #disable-the-automatic-docs } + +็ฌฌไธ€ๆญฅๆ˜ฏๅœ็”จ่‡ชๅ‹•ๆ–‡ไปถ๏ผŒๅ› ็‚บ้ ่จญๆœƒไฝฟ็”จ้ ่จญ็š„ CDNใ€‚ + +่ฆๅœ็”จๅฎƒๅ€‘๏ผŒๅปบ็ซ‹ `FastAPI` ๆ‡‰็”จๆ™‚ๆŠŠ็›ธ้—œ URL ่จญ็‚บ `None`๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### ๅŠ ๅ…ฅ่‡ช่จ‚ๆ–‡ไปถ { #include-the-custom-docs } + +็พๅœจไฝ ๅฏไปฅ็‚บ่‡ช่จ‚ๆ–‡ไปถๅปบ็ซ‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€ใ€‚ + +ไฝ ๅฏไปฅ้‡็”จ FastAPI ็š„ๅ…ง้ƒจๅ‡ฝๅผไพ†ๅปบ็ซ‹ๆ–‡ไปถ็š„ HTML ้ ้ข๏ผŒไธฆๅ‚ณๅ…ฅๆ‰€้œ€ๅƒๆ•ธ๏ผš + +* `openapi_url`๏ผšๆ–‡ไปถ HTML ้ ้ข็”จไพ†ๅ–ๅพ—ไฝ  API ็š„ OpenAPI schema ็š„ URLใ€‚ๅฏไฝฟ็”จๅฑฌๆ€ง `app.openapi_url`ใ€‚ +* `title`๏ผšไฝ ็š„ API ๆจ™้กŒใ€‚ +* `oauth2_redirect_url`๏ผšๅฏไฝฟ็”จ `app.swagger_ui_oauth2_redirect_url` ไปฅๆฒฟ็”จ้ ่จญๅ€ผใ€‚ +* `swagger_js_url`๏ผšSwagger UI ๆ–‡ไปถ HTML ็”จไพ†ๅ–ๅพ—ใ€ŒJavaScriptใ€ๆช”ๆกˆ็š„ URLใ€‚้€™ๆ˜ฏไฝ ็š„่‡ช่จ‚ CDN ไฝๅ€ใ€‚ +* `swagger_css_url`๏ผšSwagger UI ๆ–‡ไปถ HTML ็”จไพ†ๅ–ๅพ—ใ€ŒCSSใ€ๆช”ๆกˆ็š„ URLใ€‚้€™ๆ˜ฏไฝ ็š„่‡ช่จ‚ CDN ไฝๅ€ใ€‚ + +ReDoc ไนŸ้กžไผผ... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip + +็•ถไฝ ไฝฟ็”จ OAuth2 ๆ™‚๏ผŒ`swagger_ui_redirect` ็š„่ทฏๅพ‘ๆ“ไฝœๆ˜ฏๅ€‹่ผ”ๅŠฉ็ซฏ้ปžใ€‚ + +ๅฆ‚ๆžœไฝ ๆŠŠ API ่ˆ‡ OAuth2 ๆไพ›่€…ๆ•ดๅˆ๏ผŒไพฟ่ƒฝๅฎŒๆˆ่ช่ญ‰ไธฆๅธถ่‘—ๅ–ๅพ—็š„ๆ†‘่ญ‰ๅ›žๅˆฐ API ๆ–‡ไปถ๏ผŒๆŽฅ่‘—ไปฅ็œŸๆญฃ็š„ OAuth2 ้ฉ—่ญ‰่ˆ‡ไน‹ไบ’ๅ‹•ใ€‚ + +Swagger UI ๆœƒๅœจ่ƒŒๅพŒๅนซไฝ ่™•็†๏ผŒไธ้Žๅฎƒ้œ€่ฆ้€™ๅ€‹ใ€Œredirectใ€่ผ”ๅŠฉ็ซฏ้ปžใ€‚ + +/// + +### ๅปบ็ซ‹่ทฏๅพ‘ๆ“ไฝœไปฅ้€ฒ่กŒๆธฌ่ฉฆ { #create-a-path-operation-to-test-it } + +็พๅœจ๏ผŒ็‚บไบ†ๆธฌ่ฉฆไธ€ๅˆ‡ๆ˜ฏๅฆๆญฃๅธธ๏ผŒๅปบ็ซ‹ไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœ๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### ๆธฌ่ฉฆ { #test-it } + +็พๅœจไฝ ๆ‡‰่ฉฒ่ƒฝ้€ ่จช http://127.0.0.1:8000/docs๏ผŒ้‡ๆ–ฐ่ผ‰ๅ…ฅ้ ้ขๅพŒ๏ผŒ่ณ‡ๆบๆœƒๅพžๆ–ฐ็š„ CDN ่ผ‰ๅ…ฅใ€‚ + +## ่‡ช่กŒ่จ—็ฎกๆ–‡ไปถๆ‰€้œ€็š„ JavaScript ่ˆ‡ CSS { #self-hosting-javascript-and-css-for-docs } + +่‹ฅไฝ ้œ€่ฆๆ‡‰็”จๅœจ้›ข็ทšใ€็„กๅ…ฌๅ…ฑ็ถฒ่ทฏๆˆ–ๅƒ…ๅœจๅ€ๅŸŸ็ถฒ่ทฏไธญไนŸ่ƒฝ้‹ไฝœ๏ผŒ่‡ช่กŒ่จ—็ฎก JavaScript ่ˆ‡ CSS ๆœƒๅพˆๅฏฆ็”จใ€‚ + +ไปฅไธ‹็คบ็ฏ„ๅฆ‚ไฝ•ๅœจๅŒไธ€ๅ€‹ FastAPI ๆ‡‰็”จไธญ่‡ช่กŒๆไพ›้€™ไบ›ๆช”ๆกˆ๏ผŒไธฆ่จญๅฎšๆ–‡ไปถไฝฟ็”จๅฎƒๅ€‘ใ€‚ + +### ๅฐˆๆกˆๆช”ๆกˆ็ตๆง‹ { #project-file-structure } + +ๅ‡่จญไฝ ็š„ๅฐˆๆกˆๆช”ๆกˆ็ตๆง‹ๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +็พๅœจๅปบ็ซ‹ไธ€ๅ€‹็›ฎ้Œ„ไพ†ๅญ˜ๆ”พ้€™ไบ›้œๆ…‹ๆช”ๆกˆใ€‚ + +ๆ–ฐ็š„ๆช”ๆกˆ็ตๆง‹ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### ไธ‹่ผ‰ๆช”ๆกˆ { #download-the-files } + +ไธ‹่ผ‰ๆ–‡ไปถๆ‰€้œ€็š„้œๆ…‹ๆช”ๆกˆไธฆๆ”พๅˆฐ `static/` ็›ฎ้Œ„ไธญใ€‚ + +ไฝ ๅฏไปฅๅœจๅ„้€ฃ็ตไธŠๆŒ‰ๅณ้ต๏ผŒ้ธๆ“‡้กžไผผใ€Œๅฆๅญ˜้€ฃ็ต็‚บ...ใ€็š„้ธ้ …ใ€‚ + +Swagger UI ้œ€่ฆไปฅไธ‹ๆช”ๆกˆ๏ผš + +* `swagger-ui-bundle.js` +* `swagger-ui.css` + +่€Œ ReDoc ้œ€่ฆไปฅไธ‹ๆช”ๆกˆ๏ผš + +* `redoc.standalone.js` + +ไน‹ๅพŒ๏ผŒไฝ ็š„ๆช”ๆกˆ็ตๆง‹ๅฏ่ƒฝๅฆ‚ไธ‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### ๆไพ›้œๆ…‹ๆช”ๆกˆ { #serve-the-static-files } + +* ๅŒฏๅ…ฅ `StaticFiles`ใ€‚ +* ๅœจ็‰นๅฎš่ทฏๅพ‘ใ€ŒๆŽ›่ผ‰ใ€ไธ€ๅ€‹ `StaticFiles()` ๅฏฆไพ‹ใ€‚ + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### ๆธฌ่ฉฆ้œๆ…‹ๆช”ๆกˆ { #test-the-static-files } + +ๅ•Ÿๅ‹•ไฝ ็š„ๆ‡‰็”จไธฆๅ‰ๅพ€ http://127.0.0.1:8000/static/redoc.standalone.jsใ€‚ + +ไฝ ๆ‡‰่ฉฒๆœƒ็œ‹ๅˆฐไธ€ๅ€‹ๅพˆ้•ท็š„ **ReDoc** JavaScript ๆช”ๆกˆใ€‚ + +ๅฎƒๅฏ่ƒฝๆœƒไปฅๅฆ‚ไธ‹ๅ…งๅฎน้–‹้ ญ๏ผš + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +้€™่กจ็คบไฝ ็š„ๆ‡‰็”จๅทฒ่ƒฝๆไพ›้œๆ…‹ๆช”ๆกˆ๏ผŒไธ”ๆ–‡ไปถ็”จ็š„้œๆ…‹ๆช”ๅทฒๆ”พๅœจๆญฃ็ขบไฝ็ฝฎใ€‚ + +ๆŽฅ่‘—ๆŠŠๆ‡‰็”จ่จญๅฎš็‚บ่ฎ“ๆ–‡ไปถไฝฟ็”จ้€™ไบ›้œๆ…‹ๆช”ใ€‚ + +### ็‚บ้œๆ…‹ๆช”ๆกˆๅœ็”จ่‡ชๅ‹•ๆ–‡ไปถ { #disable-the-automatic-docs-for-static-files } + +ๅ’Œไฝฟ็”จ่‡ช่จ‚ CDN ไธ€ๆจฃ๏ผŒ็ฌฌไธ€ๆญฅๆ˜ฏๅœ็”จ่‡ชๅ‹•ๆ–‡ไปถ๏ผŒๅ› ็‚บ้ ่จญๆœƒไฝฟ็”จ CDNใ€‚ + +่ฆๅœ็”จๅฎƒๅ€‘๏ผŒๅปบ็ซ‹ `FastAPI` ๆ‡‰็”จๆ™‚ๆŠŠ็›ธ้—œ URL ่จญ็‚บ `None`๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### ๅŠ ๅ…ฅไฝฟ็”จ้œๆ…‹ๆช”ๆกˆ็š„่‡ช่จ‚ๆ–‡ไปถ { #include-the-custom-docs-for-static-files } + +ๅŒๆจฃๅœฐ๏ผŒ็พๅœจไฝ ๅฏไปฅ็‚บ่‡ช่จ‚ๆ–‡ไปถๅปบ็ซ‹่ทฏๅพ‘ๆ“ไฝœใ€‚ + +ๅ†ๆฌก้‡็”จ FastAPI ็š„ๅ…ง้ƒจๅ‡ฝๅผไพ†ๅปบ็ซ‹ๆ–‡ไปถ็š„ HTML ้ ้ข๏ผŒไธฆๅ‚ณๅ…ฅๆ‰€้œ€ๅƒๆ•ธ๏ผš + +* `openapi_url`๏ผšๆ–‡ไปถ HTML ้ ้ข็”จไพ†ๅ–ๅพ—ไฝ  API ็š„ OpenAPI schema ็š„ URLใ€‚ๅฏไฝฟ็”จๅฑฌๆ€ง `app.openapi_url`ใ€‚ +* `title`๏ผšไฝ ็š„ API ๆจ™้กŒใ€‚ +* `oauth2_redirect_url`๏ผšๅฏไฝฟ็”จ `app.swagger_ui_oauth2_redirect_url` ไปฅๆฒฟ็”จ้ ่จญๅ€ผใ€‚ +* `swagger_js_url`๏ผšSwagger UI ๆ–‡ไปถ HTML ็”จไพ†ๅ–ๅพ—ใ€ŒJavaScriptใ€ๆช”ๆกˆ็š„ URLใ€‚้€™ๅฐฑๆ˜ฏไฝ ็š„ๆ‡‰็”จ็พๅœจๆไพ›็š„ๆช”ๆกˆใ€‚ +* `swagger_css_url`๏ผšSwagger UI ๆ–‡ไปถ HTML ็”จไพ†ๅ–ๅพ—ใ€ŒCSSใ€ๆช”ๆกˆ็š„ URLใ€‚้€™ๅฐฑๆ˜ฏไฝ ็š„ๆ‡‰็”จ็พๅœจๆไพ›็š„ๆช”ๆกˆใ€‚ + +ReDoc ไนŸ้กžไผผ... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip + +็•ถไฝ ไฝฟ็”จ OAuth2 ๆ™‚๏ผŒ`swagger_ui_redirect` ็š„่ทฏๅพ‘ๆ“ไฝœๆ˜ฏๅ€‹่ผ”ๅŠฉ็ซฏ้ปžใ€‚ + +ๅฆ‚ๆžœไฝ ๆŠŠ API ่ˆ‡ OAuth2 ๆไพ›่€…ๆ•ดๅˆ๏ผŒไพฟ่ƒฝๅฎŒๆˆ่ช่ญ‰ไธฆๅธถ่‘—ๅ–ๅพ—็š„ๆ†‘่ญ‰ๅ›žๅˆฐ API ๆ–‡ไปถ๏ผŒๆŽฅ่‘—ไปฅ็œŸๆญฃ็š„ OAuth2 ้ฉ—่ญ‰่ˆ‡ไน‹ไบ’ๅ‹•ใ€‚ + +Swagger UI ๆœƒๅœจ่ƒŒๅพŒๅนซไฝ ่™•็†๏ผŒไธ้Žๅฎƒ้œ€่ฆ้€™ๅ€‹ใ€Œredirectใ€่ผ”ๅŠฉ็ซฏ้ปžใ€‚ + +/// + +### ๅปบ็ซ‹่ทฏๅพ‘ๆ“ไฝœไปฅๆธฌ่ฉฆ้œๆ…‹ๆช”ๆกˆ { #create-a-path-operation-to-test-static-files } + +็พๅœจ๏ผŒ็‚บไบ†ๆธฌ่ฉฆไธ€ๅˆ‡ๆ˜ฏๅฆๆญฃๅธธ๏ผŒๅปบ็ซ‹ไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœ๏ผš + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### ๆธฌ่ฉฆไฝฟ็”จ้œๆ…‹ๆช”ๆกˆ็š„ UI { #test-static-files-ui } + +็พๅœจ๏ผŒไฝ ๆ‡‰่ฉฒๅฏไปฅ้—œ้–‰ WiFi๏ผŒ้€ ่จชไฝ ็š„ๆ–‡ไปถ http://127.0.0.1:8000/docs๏ผŒไธฆ้‡ๆ–ฐ่ผ‰ๅ…ฅ้ ้ขใ€‚ + +ๅณไฝฟๆฒ’ๆœ‰็ถฒ้š›็ถฒ่ทฏ๏ผŒไนŸ่ƒฝ็œ‹ๅˆฐไฝ ็š„ API ๆ–‡ไปถไธฆ่ˆ‡ไน‹ไบ’ๅ‹•ใ€‚ diff --git a/docs/zh-hant/docs/how-to/custom-request-and-route.md b/docs/zh-hant/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..99c3410e47 --- /dev/null +++ b/docs/zh-hant/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ่‡ช่จ‚ Request ่ˆ‡ APIRoute ้กžๅˆฅ { #custom-request-and-apiroute-class } + +ๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆ่ฆ†ๅฏซ `Request` ่ˆ‡ `APIRoute` ้กžๅˆฅๆ‰€ไฝฟ็”จ็š„้‚่ผฏใ€‚ + +็‰นๅˆฅๆ˜ฏ๏ผŒ้€™ๅฏ่ƒฝๆ˜ฏๆ›ฟไปฃไธญไป‹่ปŸ้ซ”๏ผˆmiddleware๏ผ‰ไธญๅฏฆไฝœ้‚่ผฏ็š„ไธ€ๅ€‹ๅฅฝๆ–นๆณ•ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๆƒณๅœจๆ‡‰็”จ็จ‹ๅผ่™•็†ไน‹ๅ‰่ฎ€ๅ–ๆˆ–ๆ“ไฝœ่ซ‹ๆฑ‚ๆœฌๆ–‡๏ผˆrequest body๏ผ‰ใ€‚ + +/// danger + +้€™ๆ˜ฏ้€ฒ้šŽๅŠŸ่ƒฝใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‰›้–‹ๅง‹ไฝฟ็”จ **FastAPI**๏ผŒๅฏไปฅๅ…ˆ่ทณ้Žๆœฌ็ฏ€ใ€‚ + +/// + +## ไฝฟ็”จๆƒ…ๅขƒ { #use-cases } + +ๅฏ่ƒฝ็š„ไฝฟ็”จๆƒ…ๅขƒๅŒ…ๆ‹ฌ๏ผš + +* ๅฐ‡้ž JSON ็š„่ซ‹ๆฑ‚ๆœฌๆ–‡่ฝ‰ๆ›็‚บ JSON๏ผˆไพ‹ๅฆ‚ `msgpack`๏ผ‰ใ€‚ +* ่งฃๅฃ“็ธฎไปฅ gzip ๅฃ“็ธฎ็š„่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ +* ่‡ชๅ‹•่จ˜้Œ„ๆ‰€ๆœ‰่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ + +## ่™•็†่‡ช่จ‚่ซ‹ๆฑ‚ๆœฌๆ–‡็ทจ็ขผ { #handling-custom-request-body-encodings } + +่ฎ“ๆˆ‘ๅ€‘็œ‹็œ‹ๅฆ‚ไฝ•ไฝฟ็”จ่‡ช่จ‚็š„ `Request` ๅญ้กžๅˆฅไพ†่งฃๅฃ“็ธฎ gzip ่ซ‹ๆฑ‚ใ€‚ + +ไธฆ้€้Ž `APIRoute` ๅญ้กžๅˆฅไพ†ไฝฟ็”จ่ฉฒ่‡ช่จ‚็š„่ซ‹ๆฑ‚้กžๅˆฅใ€‚ + +### ๅปบ็ซ‹่‡ช่จ‚็š„ `GzipRequest` ้กžๅˆฅ { #create-a-custom-gziprequest-class } + +/// tip + +้€™ๆ˜ฏไธ€ๅ€‹็คบ็ฏ„็”จ็š„็ฐกๅŒ–็ฏ„ไพ‹๏ผ›ๅฆ‚ๆžœไฝ ้œ€่ฆ Gzip ๆ”ฏๆด๏ผŒๅฏไปฅ็›ดๆŽฅไฝฟ็”จๆไพ›็š„ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}ใ€‚ + +/// + +้ฆ–ๅ…ˆ๏ผŒๆˆ‘ๅ€‘ๅปบ็ซ‹ `GzipRequest` ้กžๅˆฅ๏ผŒๅฎƒๆœƒ่ฆ†ๅฏซ `Request.body()` ๆ–นๆณ•๏ผŒ็•ถๅญ˜ๅœจๅฐๆ‡‰็š„ๆจ™้ ญๆ™‚่งฃๅฃ“็ธฎๆœฌๆ–‡ใ€‚ + +ๅฆ‚ๆžœๆจ™้ ญไธญๆฒ’ๆœ‰ `gzip`๏ผŒๅฎƒๅฐฑไธๆœƒๅ˜—่ฉฆ่งฃๅฃ“็ธฎๆœฌๆ–‡ใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒ็›ธๅŒ็š„่ทฏ็”ฑ้กžๅˆฅๅณๅฏๅŒๆ™‚่™•็†็ถ“ gzip ๅฃ“็ธฎ่ˆ‡ๆœชๅฃ“็ธฎ็š„่ซ‹ๆฑ‚. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ๅปบ็ซ‹่‡ช่จ‚็š„ `GzipRoute` ้กžๅˆฅ { #create-a-custom-gziproute-class } + +ๆŽฅ่‘—๏ผŒๆˆ‘ๅ€‘ๅปบ็ซ‹ `fastapi.routing.APIRoute` ็š„่‡ช่จ‚ๅญ้กžๅˆฅ๏ผŒ่ฎ“ๅฎƒไฝฟ็”จ `GzipRequest`ใ€‚ + +้€™ๆฌก๏ผŒๅฎƒๆœƒ่ฆ†ๅฏซ `APIRoute.get_route_handler()` ๆ–นๆณ•ใ€‚ + +้€™ๅ€‹ๆ–นๆณ•ๆœƒๅ›žๅ‚ณไธ€ๅ€‹ๅ‡ฝๅผ๏ผŒ่€Œ่ฉฒๅ‡ฝๅผๆœƒๆŽฅๆ”ถ่ซ‹ๆฑ‚ไธฆๅ›žๅ‚ณๅ›žๆ‡‰ใ€‚ + +ๅœจ้€™่ฃก๏ผŒๆˆ‘ๅ€‘็”จๅฎƒๅฐ‡ๅŽŸๅง‹็š„่ซ‹ๆฑ‚ๅŒ…่ฃๆˆ `GzipRequest`ใ€‚ + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +`Request` ๅ…ทๆœ‰ `request.scope` ๅฑฌๆ€ง๏ผŒๅฎƒๅ…ถๅฏฆๅฐฑๆ˜ฏไธ€ๅ€‹ Python ็š„ `dict`๏ผŒๅŒ…ๅซ่ˆ‡่ฉฒ่ซ‹ๆฑ‚็›ธ้—œ็š„ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +`Request` ไนŸๆœ‰ `request.receive`๏ผŒ้‚ฃๆ˜ฏไธ€ๅ€‹็”จไพ†ใ€ŒๆŽฅๆ”ถใ€่ซ‹ๆฑ‚ๆœฌๆ–‡็š„ๅ‡ฝๅผใ€‚ + +`scope` ้€™ๅ€‹ `dict` ่ˆ‡ `receive` ๅ‡ฝๅผ้ƒฝๆ˜ฏ ASGI ่ฆๆ ผ็š„ไธ€้ƒจๅˆ†ใ€‚ + +่€Œ `scope` ่ˆ‡ `receive` ้€™ๅ…ฉ่€…๏ผŒๅฐฑๆ˜ฏๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„ `Request` ๅฏฆไพ‹ๆ‰€้œ€็š„่ณ‡ๆ–™ใ€‚ + +ๆƒณไบ†่งฃๆ›ดๅคš `Request`๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ็š„ Request ๆ–‡ไปถใ€‚ + +/// + +็”ฑ `GzipRequest.get_route_handler` ๅ›žๅ‚ณ็š„ๅ‡ฝๅผ๏ผŒๅ”ฏไธ€ไธๅŒไน‹่™•ๅœจๆ–ผๅฎƒๆœƒๆŠŠ `Request` ่ฝ‰ๆ›ๆˆ `GzipRequest`ใ€‚ + +้€™้บผๅšไน‹ๅพŒ๏ผŒ`GzipRequest` ๆœƒๅœจๆŠŠ่ณ‡ๆ–™ไบค็ตฆ *่ทฏๅพ‘ๆ“ไฝœ* ไน‹ๅ‰๏ผˆ่‹ฅๆœ‰้œ€่ฆ๏ผ‰ๅ…ˆ่ฒ ่ฒฌ่งฃๅฃ“็ธฎใ€‚ + +ไน‹ๅพŒ็š„่™•็†้‚่ผฏๅฎŒๅ…จ็›ธๅŒใ€‚ + +ไฝ†็”ฑๆ–ผๆˆ‘ๅ€‘ไฟฎๆ”นไบ† `GzipRequest.body`๏ผŒๅœจ **FastAPI** ้œ€่ฆ่ฎ€ๅ–ๆœฌๆ–‡ๆ™‚๏ผŒ่ซ‹ๆฑ‚ๆœฌๆ–‡ๆœƒ่‡ชๅ‹•่งฃๅฃ“็ธฎใ€‚ + +## ๅœจไพ‹ๅค–่™•็†ๅ™จไธญๅญ˜ๅ–่ซ‹ๆฑ‚ๆœฌๆ–‡ { #accessing-the-request-body-in-an-exception-handler } + +/// tip + +่ฆ่งฃๆฑบ็›ธๅŒๅ•้กŒ๏ผŒไฝฟ็”จ้‡ๅฐ `RequestValidationError` ็š„่‡ช่จ‚่™•็†ๅ™จไพ†่ฎ€ๅ– `body` ้€šๅธธๆ›ด็ฐกๅ–ฎ๏ผˆ[่™•็†้Œฏ่ชค](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}๏ผ‰ใ€‚ + +ไฝ†ๆœฌ็ฏ„ไพ‹ไป็„ถๆœ‰ๆ•ˆ๏ผŒไธฆ็คบ็ฏ„ไบ†ๅฆ‚ไฝ•่ˆ‡ๅ…ง้ƒจๅ…ƒไปถไบ’ๅ‹•ใ€‚ + +/// + +ๆˆ‘ๅ€‘ไนŸๅฏไปฅ็”จๅŒๆจฃ็š„ๆ–นๆณ•๏ผŒๅœจไพ‹ๅค–่™•็†ๅ™จไธญๅญ˜ๅ–่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ + +ๆˆ‘ๅ€‘ๅช้œ€่ฆๅœจ `try`/`except` ๅ€ๅกŠไธญ่™•็†่ซ‹ๆฑ‚ๅณๅฏ๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +่‹ฅ็™ผ็”Ÿไพ‹ๅค–๏ผŒ`Request` ๅฏฆไพ‹ไพ็„ถๅœจไฝœ็”จๅŸŸๅ…ง๏ผŒๅ› ๆญคๅœจ่™•็†้Œฏ่ชคๆ™‚ๆˆ‘ๅ€‘ไปๅฏ่ฎ€ๅ–ไธฆไฝฟ็”จ่ซ‹ๆฑ‚ๆœฌๆ–‡๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## ๅœจ่ทฏ็”ฑๅ™จไธญ่‡ช่จ‚ `APIRoute` ้กžๅˆฅ { #custom-apiroute-class-in-a-router } + +ไฝ ไนŸๅฏไปฅๅœจ `APIRouter` ไธŠ่จญๅฎš `route_class` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +ๅœจๆญค็ฏ„ไพ‹ไธญ๏ผŒ`router` ๅบ•ไธ‹็š„่ทฏๅพ‘ๆ“ไฝœๆœƒไฝฟ็”จ่‡ช่จ‚็š„ `TimedRoute` ้กžๅˆฅ๏ผŒไธฆๅœจๅ›žๆ‡‰ไธญๅคšๅŠ ไธŠไธ€ๅ€‹ `X-Response-Time` ๆจ™้ ญ๏ผŒๆจ™็คบ็”ข็”Ÿ่ฉฒๅ›žๆ‡‰ๆ‰€่Šฑ่ฒป็š„ๆ™‚้–“๏ผš + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh-hant/docs/how-to/extending-openapi.md b/docs/zh-hant/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..c51e896f32 --- /dev/null +++ b/docs/zh-hant/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# ๆ“ดๅ…… OpenAPI { #extending-openapi } + +ๆœ‰ไบ›ๆƒ…ๆณไฝ ๅฏ่ƒฝ้œ€่ฆไฟฎๆ”น่‡ชๅ‹•็”ข็”Ÿ็š„ OpenAPI ็ตๆง‹๏ผˆschema๏ผ‰ใ€‚ + +ๆœฌ็ซ ๅฐ‡็คบ็ฏ„ๅฆ‚ไฝ•ๅšใ€‚ + +## ไธ€่ˆฌๆต็จ‹ { #the-normal-process } + +ไธ€่ˆฌ๏ผˆ้ ่จญ๏ผ‰็š„ๆต็จ‹ๅฆ‚ไธ‹ใ€‚ + +`FastAPI` ๆ‡‰็”จ็จ‹ๅผ๏ผˆๅฏฆไพ‹๏ผ‰ๆœ‰ไธ€ๅ€‹ `.openapi()` ๆ–นๆณ•๏ผŒๆœƒๅ›žๅ‚ณ OpenAPI ็ตๆง‹ใ€‚ + +ๅœจๅปบ็ซ‹ๆ‡‰็”จ็‰ฉไปถๆ™‚๏ผŒๆœƒๅŒๆ™‚่จปๅ†Šไธ€ๅ€‹ `/openapi.json`๏ผˆๆˆ–ไฝ ๅœจ `openapi_url` ่จญๅฎš็š„่ทฏๅพ‘๏ผ‰็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€‚ + +้€™ๅ€‹่ทฏๅพ‘ๅชๆœƒๅ›žๅ‚ณไธ€ๅ€‹ JSON ๅ›žๆ‡‰๏ผŒๅ…งๅฎนๅฐฑๆ˜ฏๆ‡‰็”จ็š„ `.openapi()` ๆ–นๆณ•็ตๆžœใ€‚ + +้ ่จญๆƒ…ๆณไธ‹๏ผŒ`.openapi()` ๆœƒๅ…ˆๆชขๆŸฅ `.openapi_schema` ๅฑฌๆ€งๆ˜ฏๅฆๅทฒๆœ‰ๅ…งๅฎน๏ผŒๆœ‰็š„่ฉฑๅฐฑ็›ดๆŽฅๅ›žๅ‚ณใ€‚ + +่‹ฅๆฒ’ๆœ‰๏ผŒๅ‰‡ๆœƒๅ‘ผๅซ `fastapi.openapi.utils.get_openapi` ้€™ๅ€‹ๅทฅๅ…ทๅ‡ฝๅผไพ†็”ข็”Ÿใ€‚ + +`get_openapi()` ๅ‡ฝๅผๆœƒๆŽฅๆ”ถไปฅไธ‹ๅƒๆ•ธ๏ผš + +* `title`๏ผšOpenAPI ็š„ๆจ™้กŒ๏ผŒๆœƒ้กฏ็คบๅœจๆ–‡ไปถไธญใ€‚ +* `version`๏ผšไฝ ็š„ API ็‰ˆๆœฌ๏ผŒไพ‹ๅฆ‚ `2.5.0`ใ€‚ +* `openapi_version`๏ผšๆ‰€ไฝฟ็”จ็š„ OpenAPI ่ฆๆ ผ็‰ˆๆœฌใ€‚้ ่จญ็‚บๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผš`3.1.0`ใ€‚ +* `summary`๏ผšAPI ็š„็ฐก็Ÿญๆ‘˜่ฆใ€‚ +* `description`๏ผšAPI ็š„ๆ่ฟฐ๏ผŒๅฏๅŒ…ๅซ Markdown๏ผŒๆœƒ้กฏ็คบๅœจๆ–‡ไปถไธญใ€‚ +* `routes`๏ผš่ทฏ็”ฑๅˆ—่กจ๏ผŒไนŸๅฐฑๆ˜ฏๆ‰€ๆœ‰ๅทฒ่จปๅ†Š็š„่ทฏๅพ‘ๆ“ไฝœใ€‚ไพ†ๆบ็‚บ `app.routes`ใ€‚ + +/// info + +`summary` ๅƒๆ•ธๅœจ OpenAPI 3.1.0 ไปฅไธŠๅฏ็”จ๏ผŒไธ”้œ€ FastAPI 0.99.0 ไปฅไธŠ็‰ˆๆœฌๆ”ฏๆดใ€‚ + +/// + +## ่ฆ†ๅฏซ้ ่จญ่กŒ็‚บ { #overriding-the-defaults } + +ๅŸบๆ–ผไธŠ่ฟฐ่ณ‡่จŠ๏ผŒไฝ ๅฏไปฅ็”จ็›ธๅŒ็š„ๅทฅๅ…ทๅ‡ฝๅผไพ†็”ข็”Ÿ OpenAPI ็ตๆง‹๏ผŒไธฆ่ฆ†ๅฏซไฝ ้œ€่ฆๅฎข่ฃฝ็š„้ƒจๅˆ†ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๆˆ‘ๅ€‘่ฆๅŠ ๅ…ฅ ReDoc ็š„ OpenAPI ๆ“ดๅ……๏ผŒๆ’ๅ…ฅ่‡ช่จ‚ logoใ€‚ + +### ไธ€่ˆฌ็š„ **FastAPI** { #normal-fastapi } + +ๅ…ˆ็…งๅธธๆ’ฐๅฏซไฝ ็š„ **FastAPI** ๆ‡‰็”จ๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### ็”ข็”Ÿ OpenAPI ็ตๆง‹ { #generate-the-openapi-schema } + +ๆŽฅ่‘—๏ผŒๅœจ `custom_openapi()` ๅ‡ฝๅผๅ…ง๏ผŒไฝฟ็”จ็›ธๅŒ็š„ๅทฅๅ…ทๅ‡ฝๅผไพ†็”ข็”Ÿ OpenAPI ็ตๆง‹๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### ไฟฎๆ”น OpenAPI ็ตๆง‹ { #modify-the-openapi-schema } + +็พๅœจๅฏไปฅๅŠ ๅ…ฅ ReDoc ๆ“ดๅ……๏ผŒๅœจ OpenAPI ็ตๆง‹็š„ `info`ใ€Œ็‰ฉไปถใ€ไธญๆ–ฐๅขž่‡ช่จ‚็š„ `x-logo`๏ผš + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### ๅฟซๅ– OpenAPI ็ตๆง‹ { #cache-the-openapi-schema } + +ไฝ ๅฏไปฅๆŠŠ `.openapi_schema` ๅฑฌๆ€ง็•ถไฝœใ€Œๅฟซๅ–ใ€ไพ†ๅ„ฒๅญ˜ๅทฒ็”ข็”Ÿ็š„็ตๆง‹ใ€‚ + +้€™ๆจฃไฝฟ็”จ่€…ๆฏๆฌก้–‹ๅ•Ÿ API ๆ–‡ไปถๆ™‚๏ผŒๆ‡‰็”จๅฐฑไธๅฟ…้‡่ค‡็”ข็”Ÿ็ตๆง‹ใ€‚ + +็ตๆง‹ๅชๆœƒ็”ข็”Ÿไธ€ๆฌก๏ผŒไน‹ๅพŒ็š„่ซ‹ๆฑ‚้ƒฝๆœƒไฝฟ็”จ็›ธๅŒ็š„ๅฟซๅ–็ตๆžœใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### ่ฆ†ๅฏซๆ–นๆณ• { #override-the-method } + +็พๅœจไฝ ๅฏไปฅ็”จๆ–ฐ็š„ๅ‡ฝๅผๅ–ไปฃ `.openapi()` ๆ–นๆณ•ใ€‚ + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### ๆชขๆŸฅ็œ‹็œ‹ { #check-it } + +้€ ่จช http://127.0.0.1:8000/redoc ๅพŒ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ่‡ช่จ‚็š„ logo๏ผˆๆญคไพ‹็‚บ **FastAPI** ็š„ logo๏ผ‰๏ผš + + diff --git a/docs/zh-hant/docs/how-to/general.md b/docs/zh-hant/docs/how-to/general.md new file mode 100644 index 0000000000..96a71d62dd --- /dev/null +++ b/docs/zh-hant/docs/how-to/general.md @@ -0,0 +1,39 @@ +# ้€š็”จ - ๆ“ไฝœๆŒ‡ๅ— - ๅฏฆ็”จ็ฏ„ไพ‹ { #general-how-to-recipes } + +ไปฅไธ‹ๆ˜ฏๆ–‡ไปถไธญๅ…ถไป–ไฝ็ฝฎ็š„ๆŒ‡ๅผ•้€ฃ็ต๏ผŒ้ฉ็”จๆ–ผไธ€่ˆฌๆˆ–ๅธธ่ฆ‹ๅ•้กŒใ€‚ + +## ็ฏฉ้ธ่ณ‡ๆ–™ - ๅฎ‰ๅ…จๆ€ง { #filter-data-security } + +็‚บ็ขบไฟไฝ ไธๆœƒๅ›žๅ‚ณ่ถ…ๅ‡บๆ‡‰ๆœ‰็š„่ณ‡ๆ–™๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ๅ›žๆ‡‰ๆจกๅž‹ - ๅ›žๅ‚ณๅž‹ๅˆฅ](../tutorial/response-model.md){.internal-link target=_blank}ใ€‚ + +## ๆ–‡ไปถๆจ™็ฑค - OpenAPI { #documentation-tags-openapi } + +่ฆๅœจไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰*ๅŠ ๅ…ฅๆจ™็ฑค๏ผŒไธฆๅœจๆ–‡ไปถ UI ไธญๅˆ†็ต„๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš - ๆจ™็ฑค](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}ใ€‚ + +## ๆ–‡ไปถๆ‘˜่ฆ่ˆ‡ๆ่ฟฐ - OpenAPI { #documentation-summary-and-description-openapi } + +่ฆ็‚บไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœ*ๅŠ ๅ…ฅๆ‘˜่ฆ่ˆ‡ๆ่ฟฐ๏ผŒไธฆๅœจๆ–‡ไปถ UI ไธญ้กฏ็คบ๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš - ๆ‘˜่ฆ่ˆ‡ๆ่ฟฐ](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}ใ€‚ + +## ๆ–‡ไปถๅ›žๆ‡‰ๆ่ฟฐ - OpenAPI { #documentation-response-description-openapi } + +่ฆๅฎš็พฉๅœจๆ–‡ไปถ UI ไธญ้กฏ็คบ็š„ๅ›žๆ‡‰ๆ่ฟฐ๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš - ๅ›žๆ‡‰ๆ่ฟฐ](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}ใ€‚ + +## ๆ–‡ไปถๅฐ‡*่ทฏๅพ‘ๆ“ไฝœ*ๆจ™่จ˜็‚บๅทฒๆฃ„็”จ - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +่ฆๅฐ‡*่ทฏๅพ‘ๆ“ไฝœ*ๆจ™่จ˜็‚บๅทฒๆฃ„็”จ๏ผŒไธฆๅœจๆ–‡ไปถ UI ไธญ้กฏ็คบ๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš - ๆฃ„็”จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}ใ€‚ + +## ๅฐ‡ไปปๆ„่ณ‡ๆ–™่ฝ‰ๆ›็‚บ JSON ็›ธๅฎนๆ ผๅผ { #convert-any-data-to-json-compatible } + +่ฆๅฐ‡ไปปๆ„่ณ‡ๆ–™่ฝ‰ๆ›็‚บ JSON ็›ธๅฎนๆ ผๅผ๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - JSON ็›ธๅฎน็ทจ็ขผๅ™จ](../tutorial/encoder.md){.internal-link target=_blank}ใ€‚ + +## OpenAPI ไธญ็นผ่ณ‡ๆ–™ - ๆ–‡ไปถ { #openapi-metadata-docs } + +่ฆๅœจไฝ ็š„ OpenAPI ็ถฑ่ฆไธญๅŠ ๅ…ฅไธญ็นผ่ณ‡ๆ–™๏ผˆๅŒ…ๅซๆŽˆๆฌŠใ€็‰ˆๆœฌใ€่ฏ็ตกๆ–นๅผ็ญ‰๏ผ‰๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ไธญ็นผ่ณ‡ๆ–™่ˆ‡ๆ–‡ไปถ URL](../tutorial/metadata.md){.internal-link target=_blank}ใ€‚ + +## ่‡ช่จ‚ OpenAPI URL { #openapi-custom-url } + +่ฆ่‡ช่จ‚๏ผˆๆˆ–็งป้™ค๏ผ‰OpenAPI ็š„ URL๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ไธญ็นผ่ณ‡ๆ–™่ˆ‡ๆ–‡ไปถ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}ใ€‚ + +## OpenAPI ๆ–‡ไปถ URL { #openapi-docs-urls } + +่ฆๆ›ดๆ–ฐ่‡ชๅ‹•็”ข็”Ÿ็š„ๆ–‡ไปถไฝฟ็”จ่€…ไป‹้ขๆ‰€ไฝฟ็”จ็š„ URL๏ผŒ่ซ‹ๅƒ้–ฑ[ๆ•™ๅญธ - ไธญ็นผ่ณ‡ๆ–™่ˆ‡ๆ–‡ไปถ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/how-to/graphql.md b/docs/zh-hant/docs/how-to/graphql.md new file mode 100644 index 0000000000..51933210c5 --- /dev/null +++ b/docs/zh-hant/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +็”ฑๆ–ผ FastAPI ๅŸบๆ–ผ ASGI ๆจ™ๆบ–๏ผŒๆ•ดๅˆไปปไฝ•่ˆ‡ ASGI ็›ธๅฎน็š„ GraphQL ๅ‡ฝๅผๅบซ้ƒฝๅพˆๅฎนๆ˜“ใ€‚ + +ไฝ ๅฏไปฅๅœจๅŒไธ€ๅ€‹ๆ‡‰็”จ็จ‹ๅผไธญๅŒๆ™‚ไฝฟ็”จไธ€่ˆฌ็š„ FastAPI ่ทฏๅพ‘ๆ“ไฝœ (path operation) ่ˆ‡ GraphQLใ€‚ + +/// tip + +GraphQL ่งฃๆฑบๆŸไบ›้žๅธธ็‰นๅฎš็š„ไฝฟ็”จๆƒ…ๅขƒใ€‚ + +่ˆ‡ไธ€่ˆฌ็š„ Web API ็›ธๆฏ”๏ผŒๅฎƒๆœ‰ๅ„ช้ปžไนŸๆœ‰็ผบ้ปžใ€‚ + +่ซ‹็ขบ่ชๅœจไฝ ็š„ไฝฟ็”จๆƒ…ๅขƒไธญ๏ผŒ้€™ไบ›ๆ•ˆ็›Šๆ˜ฏๅฆ่ถณไปฅๅฝŒ่ฃœๅ…ถ้™ๅˆถใ€‚ ๐Ÿค“ + +/// + +## GraphQL ๅ‡ฝๅผๅบซ { #graphql-libraries } + +ไธ‹้ขๆ˜ฏๆ”ฏๆด ASGI ็š„้ƒจๅˆ† GraphQL ๅ‡ฝๅผๅบซ๏ผŒไฝ ๅฏไปฅ่ˆ‡ FastAPI ไธ€่ตทไฝฟ็”จ๏ผš + +* Strawberry ๐Ÿ“ + * ๆไพ› FastAPI ๆ–‡ไปถ +* Ariadne + * ๆไพ› FastAPI ๆ–‡ไปถ +* Tartiflette + * ไฝฟ็”จ Tartiflette ASGI ๆไพ› ASGI ๆ•ดๅˆ +* Graphene + * ๆญ้… starlette-graphene3 + +## ไฝฟ็”จ Strawberry ็š„ GraphQL { #graphql-with-strawberry } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๆˆ–ๆƒณไฝฟ็”จ GraphQL๏ผŒStrawberry ๆ˜ฏๆŽจ่–ฆ็š„ๅ‡ฝๅผๅบซ๏ผŒๅ› ็‚บๅฎƒ็š„่จญ่จˆ่ˆ‡ FastAPI ๆœ€ๆŽฅ่ฟ‘๏ผŒๅ…จ้ƒจ้ƒฝๅŸบๆ–ผๅž‹ๅˆฅ่จป่งฃ (type annotations)ใ€‚ + +่ฆ–ไฝ ็š„ไฝฟ็”จๆƒ…ๅขƒ่€Œๅฎš๏ผŒไฝ ๅฏ่ƒฝๆœƒๅๅฅฝๅ…ถไป–ๅ‡ฝๅผๅบซ๏ผŒไฝ†ๅฆ‚ๆžœไฝ ๅ•ๆˆ‘๏ผŒๆˆ‘ๅคงๆฆ‚ๆœƒๅปบ่ญฐไฝ ๅ…ˆ่ฉฆ่ฉฆ Strawberryใ€‚ + +ไปฅไธ‹ๆ˜ฏๅฆ‚ไฝ•ๅฐ‡ Strawberry ่ˆ‡ FastAPI ๆ•ดๅˆ็š„ไธ€ๅ€‹ๅฐไพ‹ๅญ๏ผš + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +ไฝ ๅฏไปฅๅœจ Strawberry ๆ–‡ไปถ ไธญ้€ฒไธ€ๆญฅไบ†่งฃ Strawberryใ€‚ + +ไนŸๅฏไปฅๅƒ่€ƒ้—œๆ–ผ Strawberry ่ˆ‡ FastAPI ็š„ๆ–‡ไปถใ€‚ + +## ไพ†่‡ช Starlette ็š„่ผƒ่ˆŠ `GraphQLApp` { #older-graphqlapp-from-starlette } + +ๆ—ฉๆœŸ็‰ˆๆœฌ็š„ Starlette ๆไพ› `GraphQLApp` ้กžๅˆฅไปฅๆ•ดๅˆ Grapheneใ€‚ + +ๅฎƒๅทฒๅœจ Starlette ไธญ่ขซๆฃ„็”จ๏ผŒไฝ†ๅฆ‚ๆžœไฝ ็š„็จ‹ๅผ็ขผไฝฟ็”จไบ†ๅฎƒ๏ผŒๅฏไปฅ่ผ•้ฌ†้ท็งปๅˆฐ starlette-graphene3๏ผŒๆถต่“‹็›ธๅŒ็š„ไฝฟ็”จๆƒ…ๅขƒ๏ผŒไธ”ไป‹้ขๅนพไนŽ็›ธๅŒใ€‚ + +/// tip + +ๅฆ‚ๆžœไฝ ้œ€่ฆ GraphQL๏ผŒๆˆ‘ไปๅปบ่ญฐไฝ ็œ‹็œ‹ Strawberry๏ผŒๅ› ็‚บๅฎƒๅŸบๆ–ผๅž‹ๅˆฅ่จป่งฃ๏ผŒ่€Œไธๆ˜ฏ่‡ช่จ‚็š„้กžๅˆฅ่ˆ‡ๅž‹ๅˆฅใ€‚ + +/// + +## ้€ฒไธ€ๆญฅไบ†่งฃ { #learn-more } + +ไฝ ๅฏไปฅๅœจ ๅฎ˜ๆ–น GraphQL ๆ–‡ไปถ ไธญ้€ฒไธ€ๆญฅไบ†่งฃ GraphQLใ€‚ + +ไฝ ไนŸๅฏไปฅ้€้ŽไธŠ่ฟฐ้€ฃ็ต้–ฑ่ฎ€ๅ„ๅ€‹ๅ‡ฝๅผๅบซ็š„ๆ›ดๅคšๅ…งๅฎนใ€‚ diff --git a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..109e57bc81 --- /dev/null +++ b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# ๅพž Pydantic v1 ้ท็งปๅˆฐ Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹่ˆŠ็š„ FastAPI ๆ‡‰็”จ๏ผŒๅฏ่ƒฝๆญฃๅœจไฝฟ็”จ Pydantic 1 ็‰ˆใ€‚ + +FastAPI 0.100.0 ๅŒๆ™‚ๆ”ฏๆด Pydantic v1 ๆˆ– v2๏ผŒๆœƒไฝฟ็”จไฝ ๅทฒๅฎ‰่ฃ็š„้‚ฃๅ€‹็‰ˆๆœฌใ€‚ + +FastAPI 0.119.0 ้€้Ž Pydantic v2 ๅ…ง็š„ `pydantic.v1` ๆไพ›ๅฐ Pydantic v1 ็š„้ƒจๅˆ†ๆ”ฏๆด๏ผŒไปฅไพฟ้ท็งปๅˆฐ v2ใ€‚ + +FastAPI 0.126.0 ็งป้™คไบ†ๅฐ Pydantic v1 ็š„ๆ”ฏๆด๏ผŒไฝ†ๅœจไธ€ๆฎตๆ™‚้–“ๅ…งไปๆ”ฏๆด `pydantic.v1`ใ€‚ + +/// warning + +Pydantic ๅœ˜้šŠ่‡ช **Python 3.14** ่ตท๏ผŒๅทฒๅœๆญขๅœจๆœ€ๆ–ฐ็š„ Python ็‰ˆๆœฌไธญๆ”ฏๆด Pydantic v1ใ€‚ + +้€™ไนŸๅŒ…ๅซ `pydantic.v1`๏ผŒๅœจ Python 3.14 ๅŠไปฅไธŠ็‰ˆๆœฌไธๅ†ๆ”ฏๆดใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณไฝฟ็”จๆœ€ๆ–ฐ็š„ Python ๅŠŸ่ƒฝ๏ผŒๅฐฑ้œ€่ฆ็ขบไฟไฝฟ็”จ Pydantic v2ใ€‚ + +/// + +ๅฆ‚ๆžœไฝ ็š„่ˆŠ FastAPI ๆ‡‰็”จไปไฝฟ็”จ Pydantic v1๏ผŒ้€™่ฃกๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•้ท็งปๅˆฐ Pydantic v2๏ผŒไธฆไป‹็ดน **FastAPI 0.119.0** ไธญๅฏๅ”ๅŠฉไฝ ้€ๆญฅ้ท็งป็š„ๅŠŸ่ƒฝใ€‚ + +## ๅฎ˜ๆ–นๆŒ‡ๅ— { #official-guide } + +Pydantic ๆไพ›ๅพž v1 ้ท็งปๅˆฐ v2 ็š„ๅฎ˜ๆ–น้ท็งปๆŒ‡ๅ—ใ€‚ + +ๅ…ถไธญๅŒ…ๅซ่ฎŠๆ›ดๅ…งๅฎนใ€้ฉ—่ญ‰ๅฆ‚ไฝ•ๆ›ดๆญฃ็ขบไธ”ๆ›ดๅšดๆ ผใ€ๅฏ่ƒฝ็š„ๆณจๆ„ไบ‹้ …็ญ‰ใ€‚ + +ไฝ ๅฏไปฅๅ…ˆ้–ฑ่ฎ€ไปฅๆ›ดๅฅฝ็†่งฃๅ…ท้ซ”่ฎŠๆ›ดใ€‚ + +## ๆธฌ่ฉฆ { #tests } + +็ขบไฟไฝ ็š„ๆ‡‰็”จๆœ‰[ๆธฌ่ฉฆ](../tutorial/testing.md){.internal-link target=_blank}๏ผŒไธฆๅœจ CI๏ผˆๆŒ็บŒๆ•ดๅˆ๏ผ‰ไธŠๅŸท่กŒใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ๅฏไปฅๅ‡็ดšๅพŒ็ขบ่ชไธ€ๅˆ‡ไปๅฆ‚้ ๆœŸ้‹ไฝœใ€‚ + +## `bump-pydantic` { #bump-pydantic } + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒ่‹ฅไฝ ไฝฟ็”จ็š„ๆ˜ฏๆœช่‡ช่จ‚็š„ๆจ™ๆบ– Pydantic ๆจกๅž‹๏ผŒๅคšๆ•ธ้ท็งปๆญฅ้ฉŸ้ƒฝ่ƒฝ่‡ชๅ‹•ๅŒ–ๅฎŒๆˆใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๅœ˜้šŠๆไพ›็š„ `bump-pydantic`ใ€‚ + +้€™ๅ€‹ๅทฅๅ…ทๆœƒ่‡ชๅ‹•ไฟฎๆ”นๅคง้ƒจๅˆ†้œ€่ฆ่ฎŠๆ›ด็š„็จ‹ๅผ็ขผใ€‚ + +ไน‹ๅพŒๅŸท่กŒๆธฌ่ฉฆ็ขบ่ชไธ€ๅˆ‡ๆญฃๅธธๅณๅฏๅฎŒๆˆใ€‚๐Ÿ˜Ž + +## v2 ไธญ็š„ Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2 ๅ…งๅซๅญๆจก็ต„ `pydantic.v1`๏ผŒๆไพ› Pydantic v1 ็š„ๆ‰€ๆœ‰ๅ…งๅฎนใ€‚ไฝ†ๅœจ Python 3.13 ไปฅไธŠ็‰ˆๆœฌไธๅ†ๆ”ฏๆดใ€‚ + +้€™่กจ็คบไฝ ๅฏไปฅๅฎ‰่ฃๆœ€ๆ–ฐ็š„ Pydantic v2๏ผŒไธฆๅพž่ฉฒๅญๆจก็ต„ๅŒฏๅ…ฅไธฆไฝฟ็”จ่ˆŠ็š„ Pydantic v1 ๅ…ƒไปถ๏ผŒๅฐฑๅƒๅฎ‰่ฃไบ†่ˆŠ็‰ˆ Pydantic v1 ไธ€ๆจฃใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### FastAPI ๅฐ v2 ไธญ Pydantic v1 ็š„ๆ”ฏๆด { #fastapi-support-for-pydantic-v1-in-v2 } + +่‡ช FastAPI 0.119.0 ่ตท๏ผŒไนŸๆ”ฏๆด้€้Ž Pydantic v2 ๅ…ง็š„ Pydantic v1๏ผˆ้ƒจๅˆ†๏ผ‰ไปฅๅ”ๅŠฉ้ท็งป่‡ณ v2ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅ…ˆๅ‡็ดšๅˆฐๆœ€ๆ–ฐ็š„ Pydantic v2๏ผŒไธฆๅฐ‡ๅŒฏๅ…ฅๆ”น็‚บไฝฟ็”จ `pydantic.v1` ๅญๆจก็ต„๏ผŒๅœจๅคšๆ•ธๆƒ…ๆณไธ‹ๅณๅฏๆญฃๅธธ้‹ไฝœใ€‚ + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning + +่ซ‹ๆณจๆ„๏ผŒ็”ฑๆ–ผ Pydantic ๅœ˜้šŠ่‡ช Python 3.14 ่ตทไธๅ†ๆ”ฏๆด Pydantic v1๏ผŒๅ› ๆญคๅœจ Python 3.14 ๅŠไปฅไธŠ็‰ˆๆœฌไธญไนŸไธๆ”ฏๆดไฝฟ็”จ `pydantic.v1`ใ€‚ + +/// + +### ๅŒไธ€ๆ‡‰็”จๅŒๆ™‚ไฝฟ็”จ Pydantic v1 ่ˆ‡ v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic ไธๆ”ฏๆดๅœจ Pydantic v2 ๆจกๅž‹็š„ๆฌ„ไฝไธญไฝฟ็”จ Pydantic v1 ๆจกๅž‹๏ผŒๅไน‹ไบฆ็„ถใ€‚ + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...ไฝ†ไฝ ๅฏไปฅๅœจๅŒไธ€ๆ‡‰็”จไธญๅŒๆ™‚ๅญ˜ๅœจๅˆ†้–‹็š„ Pydantic v1 ่ˆ‡ v2 ๆจกๅž‹ใ€‚ + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +ๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ็”š่‡ณๅฏไปฅๅœจๅŒไธ€ๅ€‹ FastAPI ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ไธญๅŒๆ™‚ไฝฟ็”จ Pydantic v1 ่ˆ‡ v2 ๆจกๅž‹๏ผš + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ๅœจไธŠ้ข็š„็ฏ„ไพ‹ไธญ๏ผŒ่ผธๅ…ฅๆจกๅž‹ๆ˜ฏ Pydantic v1๏ผŒ่ผธๅ‡บๆจกๅž‹๏ผˆๆ–ผ `response_model=ItemV2` ๅฎš็พฉ๏ผ‰ๆ˜ฏ Pydantic v2ใ€‚ + +### Pydantic v1 ๅƒๆ•ธ { #pydantic-v1-parameters } + +่‹ฅไฝ ้œ€่ฆๅœจ Pydantic v1 ๆจกๅž‹ไธŠไฝฟ็”จ FastAPI ็š„ๅƒๆ•ธๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ `Body`ใ€`Query`ใ€`Form` ็ญ‰๏ผ‰๏ผŒๅœจๅฎŒๆˆ้ท็งปๅˆฐ Pydantic v2 ไน‹ๅ‰๏ผŒๅฏไปฅๅพž `fastapi.temp_pydantic_v1_params` ๅŒฏๅ…ฅ๏ผš + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### ๅˆ†ๆญฅ้ท็งป { #migrate-in-steps } + +/// tip + +ๅ…ˆๅ˜—่ฉฆไฝฟ็”จ `bump-pydantic`๏ผŒๅฆ‚ๆžœๆธฌ่ฉฆ้€š้Žไธ”ไธ€ๅˆ‡ๆญฃๅธธ๏ผŒไฝ ๅฐฑ่ƒฝ็”จไธ€ๆขๆŒ‡ไปคๅฎŒๆˆ้ท็งปใ€‚โœจ + +/// + +่‹ฅ `bump-pydantic` ไธ้ฉ็”จๆ–ผไฝ ็š„ๆƒ…ๅขƒ๏ผŒๅฏไปฅๅˆฉ็”จๅœจๅŒไธ€ๆ‡‰็”จๅŒๆ™‚ๆ”ฏๆด Pydantic v1 ่ˆ‡ v2 ็š„่ƒฝๅŠ›๏ผŒ้€ๆญฅๅฎŒๆˆ้ท็งปใ€‚ + +ไฝ ๅฏไปฅๅ…ˆๅ‡็ดš Pydantic ๅˆฐๆœ€ๆ–ฐ v2๏ผŒไธฆๅฐ‡ๆ‰€ๆœ‰ๆจกๅž‹็š„ๅŒฏๅ…ฅๆ”น็‚บไฝฟ็”จ `pydantic.v1`ใ€‚ + +ๆŽฅ่‘—ๆŒ‰็พค็ต„้€ๆญฅๆŠŠๆจกๅž‹ๅพž Pydantic v1 ้ท็งปๅˆฐ v2ใ€‚๐Ÿšถ diff --git a/docs/zh-hant/docs/how-to/separate-openapi-schemas.md b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..2ecb6afbc1 --- /dev/null +++ b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# ๆ˜ฏๅฆๅฐ‡่ผธๅ…ฅ่ˆ‡่ผธๅ‡บไฝฟ็”จไธๅŒ็š„ OpenAPI ็ตๆง‹ๆ่ฟฐ { #separate-openapi-schemas-for-input-and-output-or-not } + +่‡ชๅพž Pydantic v2 ็™ผไฝˆๅพŒ๏ผŒ็”Ÿๆˆ็š„ OpenAPI ๆฏ”ไปฅๅพ€ๆ›ด็ฒพ็ขบไนŸๆ›ดๆญฃ็ขบใ€‚๐Ÿ˜Ž + +ๅฏฆ้š›ไธŠ๏ผŒๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒๅŒไธ€ๅ€‹ Pydantic ๆจกๅž‹ๅœจ OpenAPI ไธญๆœƒๅŒๆ™‚ๆœ‰ๅ…ฉๅ€‹ JSON Schema๏ผšๅˆ†ๅˆฅ็”จๆ–ผ่ผธๅ…ฅ่ˆ‡่ผธๅ‡บ๏ผŒ้€™ๅ–ๆฑบๆ–ผๅฎƒๆ˜ฏๅฆๆœ‰้ ่จญๅ€ผใ€‚ + +ไพ†็œ‹็œ‹ๅฎƒๅฆ‚ไฝ•้‹ไฝœ๏ผŒไปฅๅŠ่‹ฅ้œ€่ฆๆ™‚่ฉฒๅฆ‚ไฝ•่ชฟๆ•ดใ€‚ + +## ไฝœ็‚บ่ผธๅ…ฅ่ˆ‡่ผธๅ‡บ็š„ Pydantic ๆจกๅž‹ { #pydantic-models-for-input-and-output } + +ๅ‡่จญไฝ ๆœ‰ไธ€ๅ€‹ๅธถๆœ‰้ ่จญๅ€ผ็š„ Pydantic ๆจกๅž‹๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### ่ผธๅ…ฅ็”จๆจกๅž‹ { #model-for-input } + +ๅฆ‚ๆžœไฝ ๆŠŠ้€™ๅ€‹ๆจกๅž‹็”จไฝœ่ผธๅ…ฅ๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...ๅ‰‡ `description` ๆฌ„ไฝๅฐ‡ไธๆ˜ฏๅฟ…ๅกซใ€‚ๅ› ็‚บๅฎƒ็š„้ ่จญๅ€ผๆ˜ฏ `None`ใ€‚ + +### ๆ–‡ไปถไธญ็š„่ผธๅ…ฅๆจกๅž‹ { #input-model-in-docs } + +ไฝ ๅฏไปฅๅœจๆ–‡ไปถไธญ็ขบ่ช๏ผŒ`description` ๆฌ„ไฝๆฒ’ๆœ‰็ด…่‰ฒๆ˜Ÿ่™Ÿ๏ผŒ่กจ็คบไธๆ˜ฏๅฟ…ๅกซ๏ผš + +
+ +
+ +### ่ผธๅ‡บ็”จๆจกๅž‹ { #model-for-output } + +ไฝ†ๅฆ‚ๆžœไฝ ๆŠŠๅŒไธ€ๅ€‹ๆจกๅž‹็”จไฝœ่ผธๅ‡บ๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...็”ฑๆ–ผ `description` ๆœ‰้ ่จญๅ€ผ๏ผŒๅฐฑ็ฎ—ไฝ ๆฒ’ๆœ‰็‚บ่ฉฒๆฌ„ไฝๅ›žๅ‚ณไปปไฝ•ๅ…งๅฎน๏ผŒๅฎƒไปๆœƒๆœ‰้‚ฃๅ€‹้ ่จญๅ€ผใ€‚ + +### ่ผธๅ‡บๅ›žๆ‡‰่ณ‡ๆ–™็š„ๆจกๅž‹ { #model-for-output-response-data } + +ๅœจไบ’ๅ‹•ๅผๆ–‡ไปถไธญ่ฉฆ็”จไธฆๆชข่ฆ–ๅ›žๆ‡‰ๆ™‚๏ผŒๅ„˜็ฎก็จ‹ๅผ็ขผๆฒ’ๆœ‰็‚บๅ…ถไธญไธ€ๅ€‹ `description` ๆฌ„ไฝๅŠ ๅ…ฅไปปไฝ•ๅ…งๅฎน๏ผŒJSON ๅ›žๆ‡‰ไปๅŒ…ๅซ้ ่จญๅ€ผ๏ผˆ`null`๏ผ‰๏ผš + +
+ +
+ +้€™ไปฃ่กจ่ฉฒๆฌ„ไฝไธ€ๅฎšๆœƒๆœ‰ๅ€ผ๏ผŒๅชๆ˜ฏๆœ‰ๆ™‚ๅ€™ๅ€ผๅฏ่ƒฝๆ˜ฏ `None`๏ผˆๅœจ JSON ไธญ็‚บ `null`๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒไฝฟ็”จไฝ  API ็š„็”จๆˆถ็ซฏไธๅฟ…ๆชขๆŸฅๅ€ผๆ˜ฏๅฆๅญ˜ๅœจ๏ผŒๅฏไปฅๅ‡่จญ่ฉฒๆฌ„ไฝไธ€ๅฎšๅญ˜ๅœจ๏ผ›ๅชๆ˜ฏๆœ‰ไบ›ๆƒ…ๆณไธ‹ๅฎƒ็š„ๅ€ผๆœƒๆ˜ฏ้ ่จญ็š„ `None`ใ€‚ + +ๅœจ OpenAPI ไธญ๏ผŒๆ่ฟฐ้€™็จฎๆƒ…ๆณ็š„ๆ–นๅผๆ˜ฏๅฐ‡่ฉฒๆฌ„ไฝๆจ™่จ˜็‚บๅฟ…ๅกซ๏ผŒๅ› ็‚บๅฎƒไธ€ๅฎšๅญ˜ๅœจใ€‚ + +ๅ› ๆญค๏ผŒๅŒไธ€ๅ€‹ๆจกๅž‹็š„ JSON Schema ๆœƒไพ็”จๆ–ผ่ผธๅ…ฅๆˆ–่ผธๅ‡บ่€ŒไธๅŒ๏ผš + +- ็”จๆ–ผ่ผธๅ…ฅๆ™‚๏ผŒ`description` ไธๆ˜ฏๅฟ…ๅกซ +- ็”จๆ–ผ่ผธๅ‡บๆ™‚๏ผŒ`description` ๆ˜ฏๅฟ…ๅกซ๏ผˆไธ”ๅฏ่ƒฝ็‚บ `None`๏ผŒๅœจ JSON ไธญ็‚บ `null`๏ผ‰ + +### ๆ–‡ไปถไธญ็š„่ผธๅ‡บๆจกๅž‹ { #model-for-output-in-docs } + +ไฝ ไนŸๅฏไปฅๅœจๆ–‡ไปถไธญๆชข่ฆ–่ผธๅ‡บๆจกๅž‹๏ผŒ`name` ่ˆ‡ `description` ้ƒฝไปฅ็ด…่‰ฒๆ˜Ÿ่™Ÿๆจ™็คบ็‚บๅฟ…ๅกซ๏ผš + +
+ +
+ +### ๆ–‡ไปถไธญ็š„่ผธๅ…ฅ่ˆ‡่ผธๅ‡บๆจกๅž‹ { #model-for-input-and-output-in-docs } + +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ OpenAPI ไธญๆ‰€ๆœ‰ๅฏ็”จ็š„็ตๆง‹ๆ่ฟฐ๏ผˆJSON Schema๏ผ‰๏ผŒๆœƒ็œ‹ๅˆฐๆœ‰ๅ…ฉๅ€‹๏ผš`Item-Input` ่ˆ‡ `Item-Output`ใ€‚ + +ๅฐๆ–ผ `Item-Input`๏ผŒ`description` ไธๆ˜ฏๅฟ…ๅกซ๏ผŒๆฒ’ๆœ‰็ด…่‰ฒๆ˜Ÿ่™Ÿใ€‚ + +ไฝ†ๅฐๆ–ผ `Item-Output`๏ผŒ`description` ๆ˜ฏๅฟ…ๅกซ๏ผŒๆœ‰็ด…่‰ฒๆ˜Ÿ่™Ÿใ€‚ + +
+ +
+ +ๆœ‰ไบ† Pydantic v2 ็š„้€™ๅ€‹็‰นๆ€ง๏ผŒไฝ ็š„ API ๆ–‡ไปถๆœƒๆ›ด็ฒพ็ขบ๏ผ›่‹ฅไฝ ๆœ‰่‡ชๅ‹•็”ข็”Ÿ็š„็”จๆˆถ็ซฏ่ˆ‡ SDK๏ผŒๅฎƒๅ€‘ไนŸๆœƒๆ›ด็ฒพ็ขบ๏ผŒๆไพ›ๆ›ดๅฅฝ็š„้–‹็™ผ่€…้ซ”้ฉ—่ˆ‡ไธ€่‡ดๆ€งใ€‚๐ŸŽ‰ + +## ไธ่ฆๅˆ†้–‹็ตๆง‹ๆ่ฟฐ { #do-not-separate-schemas } + +ไธ้Ž๏ผŒๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝๆœƒๅธŒๆœ›่ผธๅ…ฅ่ˆ‡่ผธๅ‡บไฝฟ็”จ็›ธๅŒ็š„็ตๆง‹ๆ่ฟฐใ€‚ + +ๆœ€ๅธธ่ฆ‹็š„ๆƒ…ๅขƒๆ˜ฏ๏ผšไฝ ๅทฒ็ถ“ๆœ‰ไธ€ไบ›่‡ชๅ‹•็”ข็”Ÿ็š„็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ๏ผSDK๏ผŒ็›ฎๅ‰้‚„ไธๆƒณๅ…จ้ƒจๆ›ดๆ–ฐ๏ผ›ไนŸ่จฑไน‹ๅพŒๆœƒๅš๏ผŒไฝ†ไธๆ˜ฏ็พๅœจใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅๅœจ FastAPI ไธญ้€้Žๅƒๆ•ธ `separate_input_output_schemas=False` ๅœ็”จ้€™ๅ€‹ๅŠŸ่ƒฝใ€‚ + +/// info + +่‡ช FastAPI `0.102.0` ่ตทๆ–ฐๅขž `separate_input_output_schemas` ็š„ๆ”ฏๆดใ€‚๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### ๆ–‡ไปถไธญ่ผธๅ…ฅ่ˆ‡่ผธๅ‡บไฝฟ็”จ็›ธๅŒ็ตๆง‹ๆ่ฟฐ็š„ๆจกๅž‹ { #same-schema-for-input-and-output-models-in-docs } + +ๆญคๆ™‚่ผธๅ…ฅ่ˆ‡่ผธๅ‡บๅฐ‡ๅ…ฑ็”จๅŒไธ€ๅ€‹ๆจกๅž‹็ตๆง‹ๆ่ฟฐ๏ผŒๅชๆœ‰ `Item`๏ผŒๅ…ถไธญ `description` ไธๆ˜ฏๅฟ…ๅกซ๏ผš + +
+ +
diff --git a/docs/zh-hant/docs/how-to/testing-database.md b/docs/zh-hant/docs/how-to/testing-database.md new file mode 100644 index 0000000000..cbaecc2389 --- /dev/null +++ b/docs/zh-hant/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# ๆธฌ่ฉฆ่ณ‡ๆ–™ๅบซ { #testing-a-database } + +ไฝ ๅฏไปฅๅœจ SQLModel ๆ–‡ไปถ ไธญๅญธ็ฟ’้—œๆ–ผ่ณ‡ๆ–™ๅบซใ€SQL ่ˆ‡ SQLModelใ€‚ ๐Ÿค“ + +ๆœ‰ไธ€ๅ€‹่ฟทไฝ  ๅฐ‡ SQLModel ่ˆ‡ FastAPI ๆญ้…ไฝฟ็”จ็š„ๆ•™ๅญธใ€‚ โœจ + +่ฉฒๆ•™ๅญธๅŒ…ๅซไธ€็ฏ€ไป‹็ดน ๆธฌ่ฉฆ SQL ่ณ‡ๆ–™ๅบซใ€‚ ๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index a31647f3cd..77eba9b149 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -40,7 +40,7 @@ FastAPI ๆ˜ฏไธ€ๅ€‹็พไปฃใ€ๅฟซ้€Ÿ๏ผˆ้ซ˜ๆ•ˆ่ƒฝ๏ผ‰็š„ Web ๆก†ๆžถ๏ผŒ็”จๆ–ผไปฅ Python * **ๅฟซ้€Ÿ**๏ผš้žๅธธ้ซ˜็š„ๆ•ˆ่ƒฝ๏ผŒๅฏ่ˆ‡ **NodeJS** ๅ’Œ **Go** ็›ธ็•ถ๏ผˆๆญธๅŠŸๆ–ผ Starlette ๅ’Œ Pydantic๏ผ‰ใ€‚[ๆœ€ๅฟซ็š„ Python ๆก†ๆžถไน‹ไธ€](#performance)ใ€‚ * **ๆฅต้€Ÿ้–‹็™ผ**๏ผš้–‹็™ผๅŠŸ่ƒฝ็š„้€Ÿๅบฆๅฏๆๅ‡็ด„ 200% ่‡ณ 300%ใ€‚* * **ๆ›ดๅฐ‘็š„ Bug**๏ผšๆธ›ๅฐ‘็ด„ 40% ็š„ไบบ็‚บ๏ผˆ้–‹็™ผ่€…๏ผ‰้Œฏ่ชคใ€‚* -* **็›ด่ฆบ**๏ผšๅ…ทๆœ‰ๅ‡บ่‰ฒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ่™•่™•้ƒฝๆœ‰ ่‡ชๅ‹•่ฃœๅ…จใ€‚ๆ›ดๅฐ‘็š„ๅต้Œฏๆ™‚้–“ใ€‚ +* **็›ด่ฆบ**๏ผšๅ…ทๆœ‰ๅ‡บ่‰ฒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒ่™•่™•้ƒฝๆœ‰ ่‡ชๅ‹•่ฃœๅ…จใ€‚ๆ›ดๅฐ‘็š„ๅต้Œฏๆ™‚้–“ใ€‚ * **็ฐกๅ–ฎ**๏ผš่จญ่จˆไธŠๆ˜“ๆ–ผไฝฟ็”จ่ˆ‡ๅญธ็ฟ’ใ€‚ๆ›ดๅฐ‘็š„่ฎ€ๆ–‡ไปถๆ™‚้–“ใ€‚ * **็ฐกๆฝ”**๏ผšๆœ€ๅฐๅŒ–็จ‹ๅผ็ขผ้‡่ค‡ๆ€งใ€‚ๆฏๅ€‹ๅƒๆ•ธๅฎฃๅ‘Šๅฏๅธถไพ†ๅคšๅ€‹ๅŠŸ่ƒฝใ€‚ๆ›ดๅฐ‘็š„้Œฏ่ชคใ€‚ * **็ฉฉๅฅ**๏ผš็ซ‹ๅณ็ฒๅพ—ๅฏๆŠ•ๅ…ฅ็”Ÿ็”ข็š„็จ‹ๅผ็ขผ๏ผŒไธฆ่‡ชๅ‹•็”Ÿๆˆไบ’ๅ‹•ๅผๆ–‡ไปถใ€‚ @@ -368,7 +368,7 @@ item: Item * ่ณ‡ๆ–™้ฉ—่ญ‰๏ผš * ็•ถ่ณ‡ๆ–™็„กๆ•ˆๆ™‚๏ผŒ่‡ชๅ‹•ไธ”ๆธ…ๆฅš็š„้Œฏ่ชคใ€‚ * ๅณไฝฟๆ˜ฏๆทฑๅบฆๅทข็‹€็š„ JSON ็‰ฉไปถไนŸ่ƒฝ้ฉ—่ญ‰ใ€‚ -* ่ผธๅ…ฅ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž็ถฒ่ทฏ่ฎ€ๅ…ฅๅˆฐ Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅใ€‚ๅŒ…ๅซ๏ผš +* ่ผธๅ…ฅ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž็ถฒ่ทฏ่ฎ€ๅ…ฅๅˆฐ Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅใ€‚ๅŒ…ๅซ๏ผš * JSONใ€‚ * ่ทฏๅพ‘ๅƒๆ•ธใ€‚ * ๆŸฅ่ฉขๅƒๆ•ธใ€‚ @@ -376,7 +376,7 @@ item: Item * ๆจ™้ ญใ€‚ * ่กจๅ–ฎใ€‚ * ๆช”ๆกˆใ€‚ -* ่ผธๅ‡บ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅ่ฝ‰ๆ›็‚บ็ถฒ่ทฏ่ณ‡ๆ–™๏ผˆJSON๏ผ‰๏ผš +* ่ผธๅ‡บ่ณ‡ๆ–™็š„ ่ฝ‰ๆ›๏ผšๅพž Python ่ณ‡ๆ–™่ˆ‡ๅž‹ๅˆฅ่ฝ‰ๆ›็‚บ็ถฒ่ทฏ่ณ‡ๆ–™๏ผˆJSON๏ผ‰๏ผš * ่ฝ‰ๆ› Python ๅž‹ๅˆฅ๏ผˆ`str`ใ€`int`ใ€`float`ใ€`bool`ใ€`list` ็ญ‰๏ผ‰ใ€‚ * `datetime` ็‰ฉไปถใ€‚ * `UUID` ็‰ฉไปถใ€‚ @@ -439,7 +439,7 @@ item: Item * ไพ†่‡ชไธๅŒไพ†ๆบ็š„**ๅƒๆ•ธ**ๅฎฃๅ‘Š๏ผšไพ‹ๅฆ‚ **headers**ใ€**cookies**ใ€**form fields** ๅ’Œ **files**ใ€‚ * ๅฆ‚ไฝ•่จญๅฎš**้ฉ—่ญ‰้™ๅˆถ**๏ผŒๅฆ‚ `maximum_length` ๆˆ– `regex`ใ€‚ -* ไธ€ๅ€‹้žๅธธๅผทๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑใ€‚ +* ไธ€ๅ€‹้žๅธธๅผทๅคงไธ”ๆ˜“็”จ็š„ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑใ€‚ * ๅฎ‰ๅ…จ่ˆ‡้ฉ—่ญ‰๏ผŒๅŒ…ๅซๆ”ฏๆด **OAuth2** ๆญ้… **JWT tokens** ่ˆ‡ **HTTP Basic** ้ฉ—่ญ‰ใ€‚ * ๅฎฃๅ‘Š**ๆทฑๅบฆๅทข็‹€ JSON ๆจกๅž‹**็š„้€ฒ้šŽ๏ผˆไฝ†ๅŒๆจฃ็ฐกๅ–ฎ๏ผ‰ๆŠ€ๅทง๏ผˆๆ„Ÿ่ฌ Pydantic๏ผ‰ใ€‚ * ่ˆ‡ Strawberry ๅŠๅ…ถไป–ๅ‡ฝๅผๅบซ็š„ **GraphQL** ๆ•ดๅˆใ€‚ @@ -524,7 +524,7 @@ Starlette ๆœƒไฝฟ็”จ๏ผš * httpx - ่‹ฅ่ฆไฝฟ็”จ `TestClient` ๅฟ…้ ˆๅฎ‰่ฃใ€‚ * jinja2 - ่‹ฅ่ฆไฝฟ็”จ้ ่จญ็š„ๆจกๆฟ่จญๅฎšๅฟ…้ ˆๅฎ‰่ฃใ€‚ -* python-multipart - ่‹ฅ่ฆๆ”ฏๆด่กจๅ–ฎ "่งฃๆž"๏ผŒๆญ้… `request.form()`ใ€‚ +* python-multipart - ่‹ฅ่ฆๆ”ฏๆด่กจๅ–ฎ "่งฃๆž"๏ผŒๆญ้… `request.form()`ใ€‚ FastAPI ๆœƒไฝฟ็”จ๏ผš diff --git a/docs/zh-hant/docs/project-generation.md b/docs/zh-hant/docs/project-generation.md new file mode 100644 index 0000000000..7fa92ce558 --- /dev/null +++ b/docs/zh-hant/docs/project-generation.md @@ -0,0 +1,28 @@ +# ๅ…จ็ซฏ FastAPI ็ฏ„ๆœฌ { #full-stack-fastapi-template } + +็ฏ„ๆœฌ้€šๅธธ้™„ๅธถ็‰นๅฎš็š„่จญๅฎš๏ผŒไฝ†่จญ่จˆไธŠๅ…ทๆœ‰ๅฝˆๆ€งไธ”ๅฏ่‡ช่จ‚ใ€‚้€™่ฎ“ไฝ ๅฏไปฅไพๅฐˆๆกˆ้œ€ๆฑ‚่ชฟๆ•ด่ˆ‡ๆ“ดๅ……๏ผŒๅ› ๆญค้žๅธธ้ฉๅˆไฝœ็‚บ่ตท้ปžใ€‚๐Ÿ + +ไฝ ๅฏไปฅไฝฟ็”จๆญค็ฏ„ๆœฌๅฟซ้€Ÿ่ตทๆญฅ๏ผŒ่ฃก้ขๅทฒๆ›ฟไฝ ๅฎŒๆˆๅคง้‡ๅˆๅง‹่จญๅฎšใ€ๅฎ‰ๅ…จๆ€งใ€่ณ‡ๆ–™ๅบซ๏ผŒไปฅๅŠ้ƒจๅˆ† API ็ซฏ้ปžใ€‚ + +GitHub ๅ„ฒๅญ˜ๅบซ๏ผšๅ…จ็ซฏ FastAPI ็ฏ„ๆœฌ + +## ๅ…จ็ซฏ FastAPI ็ฏ„ๆœฌ - ๆŠ€่ก“ๅ †็–Š่ˆ‡ๅŠŸ่ƒฝ { #full-stack-fastapi-template-technology-stack-and-features } + +- โšก [**FastAPI**](https://fastapi.tiangolo.com/zh-hant) ไฝœ็‚บ Python ๅพŒ็ซฏ APIใ€‚ + - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) ไฝœ็‚บ Python ่ˆ‡ SQL ่ณ‡ๆ–™ๅบซไบ’ๅ‹•๏ผˆORM๏ผ‰ใ€‚ + - ๐Ÿ” [Pydantic](https://docs.pydantic.dev)๏ผˆ็”ฑ FastAPI ไฝฟ็”จ๏ผ‰็”จๆ–ผ่ณ‡ๆ–™้ฉ—่ญ‰่ˆ‡่จญๅฎš็ฎก็†ใ€‚ + - ๐Ÿ’พ [PostgreSQL](https://www.postgresql.org) ไฝœ็‚บ SQL ่ณ‡ๆ–™ๅบซใ€‚ +- ๐Ÿš€ [React](https://react.dev) ไฝœ็‚บๅ‰็ซฏใ€‚ + - ๐Ÿ’ƒ ไฝฟ็”จ TypeScriptใ€hooksใ€Vite๏ผŒไปฅๅŠ็พไปฃๅ‰็ซฏๆŠ€่ก“ๅ †็–Š็š„ๅ…ถไป–็ต„ไปถใ€‚ + - ๐ŸŽจ [Tailwind CSS](https://tailwindcss.com) ่ˆ‡ [shadcn/ui](https://ui.shadcn.com) ไฝœ็‚บๅ‰็ซฏๅ…ƒไปถใ€‚ + - ๐Ÿค– ่‡ชๅ‹•็”ข็”Ÿ็š„ๅ‰็ซฏ็”จๆˆถ็ซฏใ€‚ + - ๐Ÿงช [Playwright](https://playwright.dev) ็”จๆ–ผ็ซฏๅˆฐ็ซฏๆธฌ่ฉฆใ€‚ + - ๐Ÿฆ‡ ๆ”ฏๆดๆทฑ่‰ฒๆจกๅผใ€‚ +- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ็”จๆ–ผ้–‹็™ผ่ˆ‡ๆญฃๅผ็’ฐๅขƒใ€‚ +- ๐Ÿ”’ ้ ่จญๅณๆŽก็”จๅฎ‰ๅ…จ็š„ๅฏ†็ขผ้›œๆนŠใ€‚ +- ๐Ÿ”‘ JWT๏ผˆJSON Web Token๏ผ‰้ฉ—่ญ‰ใ€‚ +- ๐Ÿ“ซ ไปฅ Email ็‚บๅŸบ็คŽ็š„ๅฏ†็ขผ้‡่จญใ€‚ +- โœ… ไฝฟ็”จ [Pytest](https://pytest.org) ็š„ๆธฌ่ฉฆใ€‚ +- ๐Ÿ“ž [Traefik](https://traefik.io) ไฝœ็‚บๅๅ‘ไปฃ็†๏ผ่ฒ ่ผ‰ๅนณ่กกๅ™จใ€‚ +- ๐Ÿšข ไฝฟ็”จ Docker Compose ็š„้ƒจ็ฝฒๆŒ‡ๅผ•๏ผŒๅŒ…ๅซๅฆ‚ไฝ•่จญๅฎšๅ‰็ซฏ Traefik ไปฃ็†ไปฅ่‡ชๅ‹•่™•็† HTTPS ๆ†‘่ญ‰ใ€‚ +- ๐Ÿญ ๅŸบๆ–ผ GitHub Actions ็š„ CI๏ผˆๆŒ็บŒๆ•ดๅˆ๏ผ‰่ˆ‡ CD๏ผˆๆŒ็บŒ้ƒจ็ฝฒ๏ผ‰ใ€‚ diff --git a/docs/zh-hant/docs/python-types.md b/docs/zh-hant/docs/python-types.md new file mode 100644 index 0000000000..4f498ab734 --- /dev/null +++ b/docs/zh-hant/docs/python-types.md @@ -0,0 +1,348 @@ +# Python ๅž‹ๅˆฅๅ…ฅ้–€ { #python-types-intro } + +Python ๆ”ฏๆดๅฏ้ธ็”จ็š„ใ€Œๅž‹ๅˆฅๆ็คบใ€๏ผˆไนŸ็จฑ็‚บใ€Œๅž‹ๅˆฅ่จป่จ˜ใ€๏ผ‰ใ€‚ + +้€™ไบ›ใ€Œๅž‹ๅˆฅๆ็คบใ€ๆˆ–่จป่จ˜ๆ˜ฏไธ€็จฎ็‰นๆฎŠ่ชžๆณ•๏ผŒ็”จไพ†ๅฎฃๅ‘Š่ฎŠๆ•ธ็š„ๅž‹ๅˆฅใ€‚ + +็‚บไฝ ็š„่ฎŠๆ•ธๅฎฃๅ‘Šๅž‹ๅˆฅๅพŒ๏ผŒ็ทจ่ผฏๅ™จ่ˆ‡ๅทฅๅ…ทๅฐฑ่ƒฝๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆดใ€‚ + +้€™่ฃกๅชๆ˜ฏ้—œๆ–ผ Python ๅž‹ๅˆฅๆ็คบ็š„ๅฟซ้€Ÿๆ•™ๅญธ๏ผ่ค‡็ฟ’ใ€‚ๅฎƒๅชๆถต่“‹ไฝฟ็”จๅœจ **FastAPI** ๆ™‚ๆ‰€้œ€็š„ๆœ€ไฝŽ้™ๅบฆ...ๅ…ถๅฏฆ้žๅธธๅฐ‘ใ€‚ + +**FastAPI** ๅฎŒๅ…จๆ˜ฏไปฅ้€™ไบ›ๅž‹ๅˆฅๆ็คบ็‚บๅŸบ็คŽ๏ผŒไธฆๅ› ๆญคๅธถไพ†่จฑๅคšๅ„ชๅ‹ข่ˆ‡ๅฅฝ่™•ใ€‚ + +ไฝ†ๅฐฑ็ฎ—ไฝ ๅพžไธไฝฟ็”จ **FastAPI**๏ผŒๅญธไธ€้ปžๅž‹ๅˆฅๆ็คบไนŸๆœƒๆœ‰ๅนซๅŠฉใ€‚ + +/// note | ๆณจๆ„ + +ๅฆ‚ๆžœไฝ ๆ˜ฏ Python ๅฐˆๅฎถ๏ผŒ่€Œไธ”ๅทฒ็ถ“ๅฎŒๅ…จไบ†่งฃๅž‹ๅˆฅๆ็คบ๏ผŒๅฏไปฅ็›ดๆŽฅ่ทณๅˆฐไธ‹ไธ€็ซ ใ€‚ + +/// + +## ๅ‹•ๆฉŸ { #motivation } + +ๅ…ˆๅพžไธ€ๅ€‹็ฐกๅ–ฎ็š„ไพ‹ๅญ้–‹ๅง‹๏ผš + +{* ../../docs_src/python_types/tutorial001_py310.py *} + +ๅŸท่กŒ้€™ๅ€‹็จ‹ๅผๆœƒ่ผธๅ‡บ๏ผš + +``` +John Doe +``` + +้€™ๅ€‹ๅ‡ฝๅผๆœƒๅšไปฅไธ‹ไบ‹ๆƒ…๏ผš + +* ๆŽฅๆ”ถ `first_name` ่ˆ‡ `last_name`ใ€‚ +* ็”จ `title()` ๆŠŠๆฏๅ€‹ๅญ—็š„็ฌฌไธ€ๅ€‹ๅญ—ๆฏ่ฝ‰ๆˆๅคงๅฏซใ€‚ +* ็”จไธ€ๅ€‹็ฉบ็™ฝๆŠŠๅฎƒๅ€‘ไธฒๆŽฅ่ตทไพ†ใ€‚ + +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} + +### ็ทจ่ผฏๅฎƒ { #edit-it } + +้€™ๆ˜ฏไธ€ๅ€‹้žๅธธ็ฐกๅ–ฎ็š„็จ‹ๅผใ€‚ + +ไฝ†็พๅœจๆƒณๅƒไฝ ๆญฃๅพž้›ถ้–‹ๅง‹ๅฏซๅฎƒใ€‚ + +ๅœจๆŸๅ€‹ๆ™‚้–“้ปžไฝ ๆœƒ้–‹ๅง‹ๅฎš็พฉๅ‡ฝๅผ๏ผŒๅƒๆ•ธ้ƒฝๆบ–ๅ‚™ๅฅฝไบ†... + +ๆŽฅ่‘—ไฝ ้œ€่ฆๅ‘ผๅซใ€Œ้‚ฃๅ€‹ๆŠŠ็ฌฌไธ€ๅ€‹ๅญ—ๆฏ่ฝ‰ๅคงๅฏซ็š„ๆ–นๆณ•ใ€ใ€‚ + +ๆ˜ฏ `upper`๏ผŸ้‚„ๆ˜ฏ `uppercase`๏ผŸ`first_uppercase`๏ผŸ`capitalize`๏ผŸ + +็„ถๅพŒไฝ ่ฉฆ่‘—็”จ่€็‰Œ็จ‹ๅผ่จญ่จˆๅธซ็š„ๅฅฝๆœ‹ๅ‹โ€”โ€”็ทจ่ผฏๅ™จ่‡ชๅ‹•ๅฎŒๆˆใ€‚ + +ไฝ ่ผธๅ…ฅๅ‡ฝๅผ็š„็ฌฌไธ€ๅ€‹ๅƒๆ•ธ `first_name`๏ผŒๆŽฅ่‘—ๆ‰“ไธ€ๅ€‹้ปž๏ผˆ`.`๏ผ‰๏ผŒ็„ถๅพŒๆŒ‰ไธ‹ `Ctrl+Space` ่งธ็™ผ่‡ชๅ‹•ๅฎŒๆˆใ€‚ + +ไฝ†ๅพˆ้บๆ†พ๏ผŒไฝ ไป€้บผๆœ‰็”จ็š„ไนŸๆฒ’ๅพ—ๅˆฐ๏ผš + + + +### ๅŠ ไธŠๅž‹ๅˆฅ { #add-types } + +ๆˆ‘ๅ€‘ไพ†ไฟฎๆ”นๅ‰ไธ€็‰ˆไธญ็š„ไธ€่กŒใ€‚ + +ๆˆ‘ๅ€‘ๅช่ฆๆŠŠๅ‡ฝๅผๅƒๆ•ธ้€™ไธ€ๆฎต๏ผŒๅพž๏ผš + +```Python + first_name, last_name +``` + +ๆ”นๆˆ๏ผš + +```Python + first_name: str, last_name: str +``` + +ๅฐฑ้€™ๆจฃใ€‚ + +้‚ฃไบ›ๅฐฑๆ˜ฏใ€Œๅž‹ๅˆฅๆ็คบใ€๏ผš + +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} + +้€™ๅ’Œๅฎฃๅ‘Š้ ่จญๅ€ผไธๅŒ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python + first_name="john", last_name="doe" +``` + +้€™ๆ˜ฏไธๅŒ็š„ๆฑ่ฅฟใ€‚ + +ๆˆ‘ๅ€‘ไฝฟ็”จ็š„ๆ˜ฏๅ†’่™Ÿ๏ผˆ`:`๏ผ‰๏ผŒไธๆ˜ฏ็ญ‰่™Ÿ๏ผˆ`=`๏ผ‰ใ€‚ + +่€Œไธ”ๅŠ ไธŠๅž‹ๅˆฅๆ็คบ้€šๅธธไธๆœƒๆ”น่ฎŠๅŸท่กŒ็ตๆžœ๏ผŒๅ’ŒไธๅŠ ๆ™‚ๆ˜ฏไธ€ๆจฃ็š„ใ€‚ + +ไธ้Ž็พๅœจ๏ผŒๆƒณๅƒไฝ ๅˆๅœจๆ’ฐๅฏซ้‚ฃๅ€‹ๅ‡ฝๅผ๏ผŒไฝ†้€™ๆฌกๆœ‰ๅž‹ๅˆฅๆ็คบใ€‚ + +ๅœจๅŒๆจฃ็š„ๅœฐๆ–น๏ผŒไฝ ๆŒ‰ `Ctrl+Space` ๅ˜—่ฉฆ่‡ชๅ‹•ๅฎŒๆˆ๏ผŒ็„ถๅพŒไฝ ๆœƒ็œ‹ๅˆฐ๏ผš + + + +ๆœ‰ไบ†้€™ไบ›๏ผŒไฝ ๅฏไปฅๅพ€ไธ‹ๆฒๅ‹•ๆŸฅ็œ‹้ธ้ …๏ผŒ็›ดๅˆฐๆ‰พๅˆฐไธ€ๅ€‹ใ€Œ็œ‹่ตทไพ†็œผ็†Ÿใ€็š„๏ผš + + + +## ๆ›ดๅคšๅ‹•ๆฉŸ { #more-motivation } + +็œ‹้€™ๅ€‹ๅ‡ฝๅผ๏ผŒๅฎƒๅทฒ็ถ“ๆœ‰ๅž‹ๅˆฅๆ็คบไบ†๏ผš + +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} + +ๅ› ็‚บ็ทจ่ผฏๅ™จ็Ÿฅ้“่ฎŠๆ•ธ็š„ๅž‹ๅˆฅ๏ผŒไฝ ไธๅชๆœƒๅพ—ๅˆฐ่‡ชๅ‹•ๅฎŒๆˆ๏ผŒ้‚„ๆœƒๅพ—ๅˆฐ้Œฏ่ชคๆชขๆŸฅ๏ผš + + + +็พๅœจไฝ ็Ÿฅ้“่ฆไฟฎๆญฃๅฎƒ๏ผŒๆŠŠ `age` ็”จ `str(age)` ่ฝ‰ๆˆๅญ—ไธฒ๏ผš + +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} + +## ๅฎฃๅ‘Šๅž‹ๅˆฅ { #declaring-types } + +ไฝ ๅ‰›ๅ‰›็œ‹ๅˆฐๅฎฃๅ‘Šๅž‹ๅˆฅๆ็คบ็š„ไธป่ฆไฝ็ฝฎ๏ผšๅ‡ฝๅผๅƒๆ•ธใ€‚ + +้€™ไนŸๆ˜ฏไฝ ๅœจ **FastAPI** ไธญๆœ€ๅธธไฝฟ็”จๅฎƒๅ€‘็š„ๅœฐๆ–นใ€‚ + +### ็ฐกๅ–ฎๅž‹ๅˆฅ { #simple-types } + +ไฝ ๅฏไปฅๅฎฃๅ‘Šๆ‰€ๆœ‰ๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅ๏ผŒไธๅช `str`ใ€‚ + +ไพ‹ๅฆ‚ไฝ ๅฏไปฅ็”จ๏ผš + +* `int` +* `float` +* `bool` +* `bytes` + +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} + +### `typing` ๆจก็ต„ { #typing-module } + +ๅœจไธ€ไบ›ๅ…ถไป–ๆƒ…ๅขƒไธญ๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆๅพžๆจ™ๆบ–็จ‹ๅผๅบซ็š„ `typing` ๆจก็ต„ๅŒฏๅ…ฅไธ€ไบ›ๆฑ่ฅฟ๏ผŒๆฏ”ๅฆ‚็•ถไฝ ๆƒณๅฎฃๅ‘ŠๆŸๅ€‹ๆฑ่ฅฟๅฏไปฅๆ˜ฏใ€Œไปปไฝ•ๅž‹ๅˆฅใ€ๆ™‚๏ผŒๅฏไปฅ็”จ `typing` ่ฃก็š„ `Any`๏ผš + +```python +from typing import Any + + +def some_function(data: Any): + print(data) +``` + +### ๆณ›ๅž‹๏ผˆGeneric types๏ผ‰ { #generic-types } + +ๆœ‰ไบ›ๅž‹ๅˆฅๅฏไปฅๅœจๆ–นๆ‹ฌ่™ŸไธญๆŽฅๆ”ถใ€Œๅž‹ๅˆฅๅƒๆ•ธใ€๏ผŒไปฅๅฎš็พฉๅ…ถๅ…ง้ƒจๅ…ƒ็ด ็š„ๅž‹ๅˆฅ๏ผŒไพ‹ๅฆ‚ใ€Œๅญ—ไธฒ็š„ listใ€ๅฏไปฅๅฎฃๅ‘Š็‚บ `list[str]`ใ€‚ + +้€™ไบ›่ƒฝๆŽฅๆ”ถๅž‹ๅˆฅๅƒๆ•ธ็š„ๅž‹ๅˆฅ็จฑ็‚บใ€Œๆณ›ๅž‹๏ผˆGeneric types๏ผ‰ใ€ๆˆ–ใ€ŒGenericsใ€ใ€‚ + +ไฝ ๅฏไปฅๅฐ‡็›ธๅŒ็š„ๅ…งๅปบๅž‹ๅˆฅ็”จไฝœๆณ›ๅž‹๏ผˆไฝฟ็”จๆ–นๆ‹ฌ่™Ÿไธฆๅœจ่ฃก้ขๆ”พๅž‹ๅˆฅ๏ผ‰๏ผš + +* `list` +* `tuple` +* `set` +* `dict` + +#### List { #list } + +ไพ‹ๅฆ‚๏ผŒ่ฎ“ๆˆ‘ๅ€‘ๅฎš็พฉไธ€ๅ€‹่ฎŠๆ•ธๆ˜ฏ `str` ็š„ `list`ใ€‚ + +ๅฎฃๅ‘Š่ฎŠๆ•ธ๏ผŒไฝฟ็”จ็›ธๅŒ็š„ๅ†’่™Ÿ๏ผˆ`:`๏ผ‰่ชžๆณ•ใ€‚ + +ๅž‹ๅˆฅๅกซ `list`ใ€‚ + +็”ฑๆ–ผ list ๆ˜ฏไธ€็จฎๅŒ…ๅซๅ…ง้ƒจๅž‹ๅˆฅ็š„ๅž‹ๅˆฅ๏ผŒไฝ ่ฆๆŠŠๅ…ง้ƒจๅž‹ๅˆฅๆ”พๅœจๆ–นๆ‹ฌ่™Ÿไธญ๏ผš + +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} + +/// info | ่ณ‡่จŠ + +ๆ–นๆ‹ฌ่™Ÿ่ฃก็š„้‚ฃไบ›ๅ…ง้ƒจๅž‹ๅˆฅ็จฑ็‚บใ€Œๅž‹ๅˆฅๅƒๆ•ธใ€ใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ`str` ๆ˜ฏๅ‚ณ็ตฆ `list` ็š„ๅž‹ๅˆฅๅƒๆ•ธใ€‚ + +/// + +้€™่กจ็คบ๏ผšใ€Œ่ฎŠๆ•ธ `items` ๆ˜ฏไธ€ๅ€‹ `list`๏ผŒ่€Œ้€™ๅ€‹ๆธ…ๅ–ฎไธญ็š„ๆฏๅ€‹ๅ…ƒ็ด ้ƒฝๆ˜ฏ `str`ใ€ใ€‚ + +้€™้บผๅšไน‹ๅพŒ๏ผŒไฝ ็š„็ทจ่ผฏๅ™จ็”š่‡ณๅœจ่™•็†ๆธ…ๅ–ฎ่ฃก็š„้ …็›ฎๆ™‚ไนŸ่ƒฝๆไพ›ๆ”ฏๆด๏ผš + + + +ๆฒ’ๆœ‰ๅž‹ๅˆฅๆ™‚๏ผŒๅนพไนŽไธๅฏ่ƒฝๅšๅˆฐ้€™้ปžใ€‚ + +่ซ‹ๆณจๆ„๏ผŒ่ฎŠๆ•ธ `item` ๆ˜ฏๆธ…ๅ–ฎ `items` ไธญ็š„ไธ€ๅ€‹ๅ…ƒ็ด ใ€‚ + +ๅณไพฟๅฆ‚ๆญค๏ผŒ็ทจ่ผฏๅ™จไป็„ถ็Ÿฅ้“ๅฎƒๆ˜ฏ `str`๏ผŒไธฆๆไพ›็›ธๆ‡‰็š„ๆ”ฏๆดใ€‚ + +#### Tuple ่ˆ‡ Set { #tuple-and-set } + +ไฝ ไนŸๅฏไปฅ็”จ็›ธๅŒๆ–นๅผไพ†ๅฎฃๅ‘Š `tuple` ่ˆ‡ `set`๏ผš + +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} + +้€™ไปฃ่กจ๏ผš + +* ่ฎŠๆ•ธ `items_t` ๆ˜ฏไธ€ๅ€‹ๆœ‰ 3 ๅ€‹้ …็›ฎ็š„ `tuple`๏ผŒๅˆ†ๅˆฅๆ˜ฏ `int`ใ€`int` ๅ’Œ `str`ใ€‚ +* ่ฎŠๆ•ธ `items_s` ๆ˜ฏไธ€ๅ€‹ `set`๏ผŒ่€Œๅ…ถไธญๆฏๅ€‹้ …็›ฎ้ƒฝๆ˜ฏ `bytes` ๅž‹ๅˆฅใ€‚ + +#### Dict { #dict } + +ๅฎš็พฉ `dict` ๆ™‚๏ผŒไฝ ้œ€่ฆๅ‚ณๅ…ฅ 2 ๅ€‹ไปฅ้€—่™Ÿๅˆ†้š”็š„ๅž‹ๅˆฅๅƒๆ•ธใ€‚ + +็ฌฌไธ€ๅ€‹ๅž‹ๅˆฅๅƒๆ•ธๆ˜ฏ `dict` ็š„้ต๏ผˆkey๏ผ‰ใ€‚ + +็ฌฌไบŒๅ€‹ๅž‹ๅˆฅๅƒๆ•ธๆ˜ฏ `dict` ็š„ๅ€ผ๏ผˆvalue๏ผ‰๏ผš + +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} + +้€™ไปฃ่กจ๏ผš + +* ่ฎŠๆ•ธ `prices` ๆ˜ฏๅ€‹ `dict`๏ผš + * ้€™ๅ€‹ `dict` ็š„้ตๆ˜ฏ `str`๏ผˆไพ‹ๅฆ‚ๆฏๅ€‹้ …็›ฎ็š„ๅ็จฑ๏ผ‰ใ€‚ + * ้€™ๅ€‹ `dict` ็š„ๅ€ผๆ˜ฏ `float`๏ผˆไพ‹ๅฆ‚ๆฏๅ€‹้ …็›ฎ็š„ๅƒนๆ ผ๏ผ‰ใ€‚ + +#### Union { #union } + +ไฝ ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹่ฎŠๆ•ธๅฏไปฅๆ˜ฏใ€Œๅคš็จฎๅž‹ๅˆฅใ€ไธญ็š„ไปปไธ€็จฎ๏ผŒไพ‹ๅฆ‚ `int` ๆˆ– `str`ใ€‚ + +่ฆ้€™้บผๅฎš็พฉ๏ผŒไฝ ไฝฟ็”จ่ฑŽ็ทš๏ผˆ`|`๏ผ‰ไพ†ๅˆ†้š”ๅ…ฉ็จฎๅž‹ๅˆฅใ€‚ + +้€™็จฑ็‚บใ€Œunionใ€๏ผŒๅ› ็‚บ่ฎŠๆ•ธๅฏไปฅๆ˜ฏ้€™ๅ…ฉ็จฎๅž‹ๅˆฅ้›†ๅˆ็š„่ฏ้›†ไธญ็š„ไปปไธ€็จฎใ€‚ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +้€™่กจ็คบ `item` ๅฏไปฅๆ˜ฏ `int` ๆˆ– `str`ใ€‚ + +#### ๅฏ่ƒฝ็‚บ `None` { #possibly-none } + +ไฝ ๅฏไปฅๅฎฃๅ‘ŠๆŸๅ€‹ๅ€ผๅฏไปฅๆ˜ฏๆŸๅ€‹ๅž‹ๅˆฅ๏ผˆไพ‹ๅฆ‚ `str`๏ผ‰๏ผŒไฝ†ๅฎƒไนŸๅฏ่ƒฝๆ˜ฏ `None`ใ€‚ + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +ไฝฟ็”จ `str | None` ่€Œไธๆ˜ฏๅ–ฎ็ด”็š„ `str`๏ผŒๅฏไปฅ่ฎ“็ทจ่ผฏๅ™จๅนซไฝ ๅตๆธฌ้Œฏ่ชค๏ผŒไพ‹ๅฆ‚ไฝ ไปฅ็‚บๆŸๅ€‹ๅ€ผไธ€ๅฎšๆ˜ฏ `str`๏ผŒไฝ†ๅฎƒๅ…ถๅฏฆไนŸๅฏ่ƒฝๆ˜ฏ `None`ใ€‚ + +### ้กžๅˆฅไฝœ็‚บๅž‹ๅˆฅ { #classes-as-types } + +ไฝ ไนŸๅฏไปฅ็”จ้กžๅˆฅไพ†ๅฎฃๅ‘Š่ฎŠๆ•ธ็š„ๅž‹ๅˆฅใ€‚ + +ๅ‡่จญไฝ ๆœ‰ไธ€ๅ€‹ `Person` ้กžๅˆฅ๏ผŒๅธถๆœ‰ๅ็จฑ๏ผš + +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹่ฎŠๆ•ธ็‚บ `Person` ๅž‹ๅˆฅ๏ผš + +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} + +็„ถๅพŒ๏ผŒไฝ ไธ€ๆจฃๆœƒๅพ—ๅˆฐๅฎŒๆ•ด็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผš + + + +่ซ‹ๆณจๆ„๏ผŒ้€™่กจ็คบใ€Œ`one_person` ๆ˜ฏ้กžๅˆฅ `Person` ็š„ใ€Žๅฏฆไพ‹๏ผˆinstance๏ผ‰ใ€ใ€ใ€‚ + +ไธฆไธๆ˜ฏใ€Œ`one_person` ๅฐฑๆ˜ฏๅ็‚บ `Person` ็š„ใ€Ž้กžๅˆฅ๏ผˆclass๏ผ‰ใ€ใ€ใ€‚ + +## Pydantic ๆจกๅž‹ { #pydantic-models } + +Pydantic ๆ˜ฏไธ€ๅ€‹็”จไพ†ๅš่ณ‡ๆ–™้ฉ—่ญ‰็š„ Python ็จ‹ๅผๅบซใ€‚ + +ไฝ ไปฅๅธถๆœ‰ๅฑฌๆ€ง็š„้กžๅˆฅไพ†ๅฎฃๅ‘Š่ณ‡ๆ–™็š„ใ€Œๅฝข็‹€ใ€ใ€‚ + +่€Œๆฏๅ€‹ๅฑฌๆ€ง้ƒฝๆœ‰ๅ…ถๅž‹ๅˆฅใ€‚ + +ๆŽฅ่‘—ไฝ ็”จไธ€ไบ›ๅ€ผๅปบ็ซ‹้€™ๅ€‹้กžๅˆฅ็š„ๅฏฆไพ‹๏ผŒๅฎƒๆœƒ้ฉ—่ญ‰้€™ไบ›ๅ€ผใ€ๅœจ้œ€่ฆๆ™‚ๆŠŠๅฎƒๅ€‘่ฝ‰ๆ›ๆˆ้ฉ็•ถ็š„ๅž‹ๅˆฅ๏ผŒ็„ถๅพŒๅ›ž็ตฆไฝ ไธ€ๅ€‹ๅŒ…ๅซๆ‰€ๆœ‰่ณ‡ๆ–™็š„็‰ฉไปถใ€‚ + +ไฝ ไนŸๆœƒๅฐ้€™ๅ€‹็”ข็”Ÿ็š„็‰ฉไปถๅพ—ๅˆฐๅฎŒๆ•ด็š„็ทจ่ผฏๅ™จๆ”ฏๆดใ€‚ + +ไปฅไธ‹ๆ˜ฏไพ†่‡ช Pydantic ๅฎ˜ๆ–นๆ–‡ไปถ็š„ไพ‹ๅญ๏ผš + +{* ../../docs_src/python_types/tutorial011_py310.py *} + +/// info | ่ณ‡่จŠ + +ๆƒณไบ†่งฃๆ›ดๅคš Pydantic๏ผŒ่ซ‹ๆŸฅ็œ‹ๅฎƒ็š„ๆ–‡ไปถใ€‚ + +/// + +**FastAPI** ๅฎŒๅ…จๆ˜ฏไปฅ Pydantic ็‚บๅŸบ็คŽใ€‚ + +ไฝ ๆœƒๅœจ[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐๆ›ดๅคšๅฏฆ้š›็ฏ„ไพ‹ใ€‚ + +## ๅซไธญ็นผ่ณ‡ๆ–™็š„ๅž‹ๅˆฅๆ็คบ { #type-hints-with-metadata-annotations } + +Python ไนŸๆœ‰ไธ€ๅ€‹ๅŠŸ่ƒฝ๏ผŒๅ…่จฑไฝฟ็”จ `Annotated` ๅœจ้€™ไบ›ๅž‹ๅˆฅๆ็คบไธญๆ”พๅ…ฅ้กๅค–็š„ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +ไฝ ๅฏไปฅๅพž `typing` ๅŒฏๅ…ฅ `Annotated`ใ€‚ + +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} + +Python ๆœฌ่บซไธๆœƒๅฐ้€™ๅ€‹ `Annotated` ๅšไปปไฝ•ไบ‹ใ€‚ๅฐ็ทจ่ผฏๅ™จ่ˆ‡ๅ…ถไป–ๅทฅๅ…ท่€Œ่จ€๏ผŒ่ฉฒๅž‹ๅˆฅไป็„ถๆ˜ฏ `str`ใ€‚ + +ไฝ†ไฝ ๅฏไปฅๅˆฉ็”จ `Annotated` ้€™ๅ€‹็ฉบ้–“๏ผŒไพ†ๆไพ› **FastAPI** ้กๅค–็š„ไธญ็นผ่ณ‡ๆ–™๏ผŒๅ‘Š่จดๅฎƒไฝ ๅธŒๆœ›ๆ‡‰็”จ็จ‹ๅผๅฆ‚ไฝ•้‹ไฝœใ€‚ + +้‡่ฆ็š„ๆ˜ฏ่ฆ่จ˜ไฝ๏ผŒๅ‚ณ็ตฆ `Annotated` ็š„ใ€Œ็ฌฌไธ€ๅ€‹ๅž‹ๅˆฅๅƒๆ•ธใ€ๆ‰ๆ˜ฏใ€Œ็œŸๆญฃ็š„ๅž‹ๅˆฅใ€ใ€‚ๅ…ถ้ค˜็š„๏ผŒ้ƒฝๆ˜ฏ็ตฆๅ…ถไป–ๅทฅๅ…ท็”จ็š„ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +็›ฎๅ‰ไฝ ๅช้œ€่ฆ็Ÿฅ้“ `Annotated` ็š„ๅญ˜ๅœจ๏ผŒ่€Œไธ”ๅฎƒๆ˜ฏๆจ™ๆบ–็š„ Pythonใ€‚๐Ÿ˜Ž + +ไน‹ๅพŒไฝ ๆœƒ็œ‹ๅˆฐๅฎƒๆœ‰ๅคšใ€Œๅผทๅคงใ€ใ€‚ + +/// tip | ๆ็คบ + +ๅ› ็‚บ้€™ๆ˜ฏใ€Œๆจ™ๆบ– Pythonใ€๏ผŒๆ‰€ไปฅไฝ ๅœจ็ทจ่ผฏๅ™จใ€ๅˆ†ๆž่ˆ‡้‡ๆง‹็จ‹ๅผ็ขผ็š„ๅทฅๅ…ท็ญ‰ๆ–น้ข๏ผŒไป็„ถ่ƒฝ็ฒๅพ—ใ€Œๆœ€ไฝณ็š„้–‹็™ผ้ซ”้ฉ—ใ€ใ€‚โœจ + +่€Œไธ”ไฝ ็š„็จ‹ๅผ็ขผไนŸๆœƒ่ˆ‡่จฑๅคšๅ…ถไป– Python ๅทฅๅ…ท่ˆ‡็จ‹ๅผๅบซ้žๅธธ็›ธๅฎนใ€‚๐Ÿš€ + +/// + +## ๅœจ **FastAPI** ไธญ็š„ๅž‹ๅˆฅๆ็คบ { #type-hints-in-fastapi } + +**FastAPI** ๅ–„็”จ้€™ไบ›ๅž‹ๅˆฅๆ็คบไพ†ๅฎŒๆˆๅคš้ …ๅทฅไฝœใ€‚ + +ๅœจ **FastAPI** ไธญ๏ผŒไฝ ็”จๅž‹ๅˆฅๆ็คบไพ†ๅฎฃๅ‘Šๅƒๆ•ธ๏ผŒ็„ถๅพŒไฝ ๆœƒๅพ—ๅˆฐ๏ผš + +* ็ทจ่ผฏๅ™จๆ”ฏๆด +* ๅž‹ๅˆฅๆชขๆŸฅ + +...่€Œ **FastAPI** ไนŸๆœƒ็”จๅŒๆจฃ็š„ๅฎฃๅ‘Šไพ†๏ผš + +* ๅฎš็พฉ้œ€ๆฑ‚๏ผšไพ†่‡ช่ซ‹ๆฑ‚็š„่ทฏๅพ‘ๅƒๆ•ธใ€ๆŸฅ่ฉขๅƒๆ•ธใ€ๆจ™้ ญใ€ไธป้ซ”๏ผˆbody๏ผ‰ใ€็›ธไพๆ€ง็ญ‰ +* ่ฝ‰ๆ›่ณ‡ๆ–™๏ผšๆŠŠ่ซ‹ๆฑ‚ไธญ็š„่ณ‡ๆ–™่ฝ‰ๆˆๆ‰€้œ€ๅž‹ๅˆฅ +* ้ฉ—่ญ‰่ณ‡ๆ–™๏ผšไพ†่‡ชๆฏๅ€‹่ซ‹ๆฑ‚็š„่ณ‡ๆ–™๏ผš + * ็•ถ่ณ‡ๆ–™็„กๆ•ˆๆ™‚๏ผŒ่‡ชๅ‹•็”ข็”Ÿ้Œฏ่ชคไธฆๅ›žๅ‚ณ็ตฆ็”จๆˆถ็ซฏ +* ไฝฟ็”จ OpenAPI ๆ›ธๅฏซ API ๆ–‡ไปถ๏ผš + * ไน‹ๅพŒๆœƒ็”ฑ่‡ชๅ‹•็š„ไบ’ๅ‹•ๅผๆ–‡ไปถไป‹้ขๆ‰€ไฝฟ็”จ + +้€™ไบ›็พๅœจ่ฝ่ตทไพ†ๅฏ่ƒฝๆœ‰้ปžๆŠฝ่ฑกใ€‚ๅˆฅๆ“”ๅฟƒใ€‚ไฝ ๆœƒๅœจ[ๆ•™ๅญธ - ไฝฟ็”จ่€…ๆŒ‡ๅ—](tutorial/index.md){.internal-link target=_blank}ไธญ็œ‹ๅˆฐๅฎƒๅ€‘็š„ๅฏฆ้š›้‹ไฝœใ€‚ + +้‡้ปžๆ˜ฏ๏ผŒ้€้Žๅœจๅ–ฎไธ€ไฝ็ฝฎไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅ๏ผˆ่€Œไธๆ˜ฏๆ–ฐๅขžๆ›ดๅคš้กžๅˆฅใ€่ฃ้ฃพๅ™จ็ญ‰๏ผ‰๏ผŒ**FastAPI** ๆœƒๅนซไฝ ๅฎŒๆˆๅพˆๅคšๅทฅไฝœใ€‚ + +/// info | ่ณ‡่จŠ + +ๅฆ‚ๆžœไฝ ๅทฒ็ถ“ๅฎŒๆ•ด่ฎ€ๅฎŒๆ•ดๅ€‹ๆ•™ๅญธ๏ผŒไธฆๅ›žไพ†ๆƒณๅคš็œ‹ไธ€ไบ›้—œๆ–ผๅž‹ๅˆฅ็š„ๅ…งๅฎน๏ผŒไธ€ๅ€‹ไธ้Œฏ็š„่ณ‡ๆบๆ˜ฏ `mypy` ็š„ใ€ŒๅฐๆŠ„ใ€ใ€‚ + +/// diff --git a/docs/zh-hant/docs/translation-banner.md b/docs/zh-hant/docs/translation-banner.md new file mode 100644 index 0000000000..58b49965a9 --- /dev/null +++ b/docs/zh-hant/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ AI ่ˆ‡ไบบ้กžๅ…ฑๅŒๅฎŒๆˆ็š„็ฟป่ญฏ + +ๆญค็ฟป่ญฏ็”ฑไบบ้กžๆŒ‡ๅฐŽ็š„ AI ๅฎŒๆˆใ€‚๐Ÿค + +ๅฏ่ƒฝๆœƒๆœ‰ๅฐๅŽŸๆ„็š„่ชค่งฃ๏ผŒๆˆ–่ฎ€่ตทไพ†ไธ่‡ช็„ถ็ญ‰ๅ•้กŒใ€‚๐Ÿค– + +ไฝ ๅฏไปฅ้€้Ž[ๅ”ๅŠฉๆˆ‘ๅ€‘ๆ›ดๅฅฝๅœฐๅผ•ๅฐŽ AI LLM](https://fastapi.tiangolo.com/zh-hant/contributing/#translations)ไพ†ๆ”น้€ฒๆญค็ฟป่ญฏใ€‚ + +[่‹ฑๆ–‡็‰ˆ](ENGLISH_VERSION_URL) + +/// diff --git a/docs/zh-hant/docs/tutorial/background-tasks.md b/docs/zh-hant/docs/tutorial/background-tasks.md new file mode 100644 index 0000000000..63e4e5a160 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/background-tasks.md @@ -0,0 +1,84 @@ +# ่ƒŒๆ™ฏไปปๅ‹™ { #background-tasks } + +ไฝ ๅฏไปฅๅฎš็พฉ่ƒŒๆ™ฏไปปๅ‹™๏ผŒ่ฎ“ๅฎƒๅ€‘ๅœจๅ‚ณๅ›žๅ›žๆ‡‰ไน‹ๅพŒๅŸท่กŒใ€‚ + +้€™ๅฐๆ–ผ้‚ฃไบ›้œ€่ฆๅœจ่ซ‹ๆฑ‚ไน‹ๅพŒ็™ผ็”Ÿใ€ไฝ†็”จๆˆถ็ซฏๅ…ถๅฏฆไธๅฟ…ๅœจๆ”ถๅˆฐๅ›žๆ‡‰ๅ‰็ญ‰ๅฎƒๅฎŒๆˆ็š„ๆ“ไฝœๅพˆๆœ‰็”จใ€‚ + +ไพ‹ๅฆ‚๏ผš + +* ๅœจๅŸท่กŒๆŸๅ€‹ๅ‹•ไฝœๅพŒ็™ผ้€้›ปๅญ้ƒตไปถ้€š็Ÿฅ๏ผš + * ็”ฑๆ–ผ้€ฃ็ทšๅˆฐ้ƒตไปถไผบๆœๅ™จไธฆๅฏ„้€้ƒตไปถ้€šๅธธ่ผƒใ€Œๆ…ขใ€๏ผˆๆ•ธ็ง’๏ผ‰๏ผŒไฝ ๅฏไปฅๅ…ˆ็ซ‹ๅณๅ›žๆ‡‰๏ผŒไธฆๅœจ่ƒŒๆ™ฏไธญ็™ผ้€้ƒตไปถ้€š็Ÿฅใ€‚ +* ่™•็†่ณ‡ๆ–™๏ผš + * ไพ‹ๅฆ‚๏ผŒๆ”ถๅˆฐไธ€ๅ€‹้œ€่ฆ็ถ“้Ž่ผƒๆ…ข่™•็†ๆต็จ‹็š„ๆช”ๆกˆๆ™‚๏ผŒไฝ ๅฏไปฅๅ…ˆๅ›žๆ‡‰ใ€ŒAcceptedใ€๏ผˆHTTP 202๏ผ‰๏ผŒๅ†ๅœจ่ƒŒๆ™ฏ่™•็†่ฉฒๆช”ๆกˆใ€‚ + +## ไฝฟ็”จ `BackgroundTasks` { #using-backgroundtasks } + +้ฆ–ๅ…ˆ๏ผŒๅŒฏๅ…ฅ `BackgroundTasks`๏ผŒไธฆๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญๅฎš็พฉไธ€ๅ€‹ๅž‹ๅˆฅ็‚บ `BackgroundTasks` ็š„ๅƒๆ•ธ๏ผš + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} + +**FastAPI** ๆœƒ็‚บไฝ ๅปบ็ซ‹ `BackgroundTasks` ็‰ฉไปถ๏ผŒไธฆไปฅ่ฉฒๅƒๆ•ธๅ‚ณๅ…ฅใ€‚ + +## ๅปบ็ซ‹ไปปๅ‹™ๅ‡ฝๅผ { #create-a-task-function } + +ๅปบ็ซ‹ไธ€ๅ€‹ไฝœ็‚บ่ƒŒๆ™ฏไปปๅ‹™ๅŸท่กŒ็š„ๅ‡ฝๅผใ€‚ + +ๅฎƒๅชๆ˜ฏๅ€‹ๅฏๆŽฅๆ”ถๅƒๆ•ธ็š„ไธ€่ˆฌๅ‡ฝๅผใ€‚ + +ๅฎƒๅฏไปฅๆ˜ฏ `async def`๏ผŒไนŸๅฏไปฅๆ˜ฏไธ€่ˆฌ็š„ `def`๏ผŒ**FastAPI** ้ƒฝ่ƒฝๆญฃ็ขบ่™•็†ใ€‚ + +ๅœจๆญคไพ‹ไธญ๏ผŒไปปๅ‹™ๅ‡ฝๅผๆœƒๅฏซๅ…ฅๆช”ๆกˆ๏ผˆๆจกๆ“ฌๅฏ„้€้›ปๅญ้ƒตไปถ๏ผ‰ใ€‚ + +็”ฑๆ–ผๅฏซๅ…ฅๆ“ไฝœๆœชไฝฟ็”จ `async` ่ˆ‡ `await`๏ผŒๅ› ๆญคไปฅไธ€่ˆฌ็š„ `def` ๅฎš็พฉ่ฉฒๅ‡ฝๅผ๏ผš + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} + +## ๆ–ฐๅขž่ƒŒๆ™ฏไปปๅ‹™ { #add-the-background-task } + +ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผๅ…ง๏ผŒไฝฟ็”จ `.add_task()` ๅฐ‡ไปปๅ‹™ๅ‡ฝๅผๅŠ ๅ…ฅ่ƒŒๆ™ฏไปปๅ‹™็‰ฉไปถ๏ผš + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} + +`.add_task()` ็š„ๅผ•ๆ•ธๅŒ…ๆ‹ฌ๏ผš + +* ่ฆๅœจ่ƒŒๆ™ฏๅŸท่กŒ็š„ไปปๅ‹™ๅ‡ฝๅผ๏ผˆ`write_notification`๏ผ‰ใ€‚ +* ไพๅบๅ‚ณ็ตฆไปปๅ‹™ๅ‡ฝๅผ็š„ไฝ็ฝฎๅผ•ๆ•ธ๏ผˆ`email`๏ผ‰ใ€‚ +* ่ฆๅ‚ณ็ตฆไปปๅ‹™ๅ‡ฝๅผ็š„้—œ้ตๅญ—ๅผ•ๆ•ธ๏ผˆ`message="some notification"`๏ผ‰ใ€‚ + +## ็›ธไพๆ€งๆณจๅ…ฅ { #dependency-injection } + +ๅœจ็›ธไพๆ€งๆณจๅ…ฅ็ณป็ตฑไธญไนŸๅฏไฝฟ็”จ `BackgroundTasks`ใ€‚ไฝ ๅฏไปฅๅœจๅคšๅ€‹ๅฑค็ดšๅฎฃๅ‘Š `BackgroundTasks` ๅž‹ๅˆฅ็š„ๅƒๆ•ธ๏ผš่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็›ธไพ้ …๏ผˆdependable๏ผ‰ใ€ๆฌก็ดš็›ธไพ้ …็ญ‰ใ€‚ + +**FastAPI** ๆœƒๅœจๅ„็จฎๆƒ…ๆณไธ‹ๆญฃ็ขบ่™•็†ไธฆ้‡็”จๅŒไธ€ๅ€‹็‰ฉไปถ๏ผŒๅฐ‡ๆ‰€ๆœ‰่ƒŒๆ™ฏไปปๅ‹™ๅˆไฝต๏ผŒไธฆๅœจไน‹ๅพŒๆ–ผ่ƒŒๆ™ฏๅŸท่กŒ๏ผš + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + +ๅœจๆญค็ฏ„ไพ‹ไธญ๏ผŒ่จŠๆฏๆœƒๅœจๅ›žๆ‡‰้€ๅ‡บไน‹ๅพŒๅฏซๅ…ฅ `log.txt` ๆช”ๆกˆใ€‚ + +ๅฆ‚ๆžœ่ซ‹ๆฑ‚ไธญๆœ‰ๆŸฅ่ฉขๅƒๆ•ธ๏ผŒๆœƒไปฅ่ƒŒๆ™ฏไปปๅ‹™ๅฏซๅ…ฅๆ—ฅ่ชŒใ€‚ + +ๆŽฅ่‘—๏ผŒๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญๅปบ็ซ‹็š„ๅฆไธ€ๅ€‹่ƒŒๆ™ฏไปปๅ‹™ๆœƒไฝฟ็”จ `email` ่ทฏๅพ‘ๅƒๆ•ธๅฏซๅ…ฅ่จŠๆฏใ€‚ + +## ๆŠ€่ก“็ดฐ็ฏ€ { #technical-details } + +้กžๅˆฅ `BackgroundTasks` ็›ดๆŽฅไพ†่‡ช `starlette.background`ใ€‚ + +ๅฎƒ่ขซ็›ดๆŽฅๅŒฏๅ…ฅ/ๅŒ…ๅซๅˆฐ FastAPI ไธญ๏ผŒๅ› ๆญคไฝ ๅฏไปฅๅพž `fastapi` ๅŒฏๅ…ฅๅฎƒ๏ผŒไธฆ้ฟๅ…ไธๅฐๅฟƒๅพž `starlette.background` ๅŒฏๅ…ฅๅฆไธ€ๅ€‹ๅŒๅ็š„ `BackgroundTask`๏ผˆ็ตๅฐพๆฒ’ๆœ‰ s๏ผ‰ใ€‚ + +ๅชไฝฟ็”จ `BackgroundTasks`๏ผˆ่€Œ้ž `BackgroundTask`๏ผ‰ๆ™‚๏ผŒไฝ ๅฐฑ่ƒฝๆŠŠๅฎƒ็•ถไฝœ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ็š„ๅƒๆ•ธ๏ผŒไธฆ่ฎ“ **FastAPI** ๅนซไฝ ่™•็†ๅ…ถ้ค˜้ƒจๅˆ†๏ผŒๅฐฑๅƒ็›ดๆŽฅไฝฟ็”จ `Request` ็‰ฉไปถไธ€ๆจฃใ€‚ + +ๅœจ FastAPI ไธญไปๅฏๅ–ฎ็จไฝฟ็”จ `BackgroundTask`๏ผŒไฝ†ไฝ ้œ€่ฆๅœจ็จ‹ๅผ็ขผไธญ่‡ช่กŒๅปบ็ซ‹่ฉฒ็‰ฉไปถ๏ผŒไธฆๅ›žๅ‚ณๅŒ…ๅซๅฎƒ็š„ Starlette `Response`ใ€‚ + +ๆ›ดๅคš็ดฐ็ฏ€่ซ‹ๅƒ้–ฑ Starlette ๅฎ˜ๆ–น็š„ Background Tasks ๆ–‡ไปถใ€‚ + +## ๆณจๆ„ไบ‹้ … { #caveat } + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅŸท่กŒ็น้‡็š„่ƒŒๆ™ฏ่จˆ็ฎ—๏ผŒไธ”ไธไธ€ๅฎš่ฆ็”ฑๅŒไธ€ๅ€‹่กŒ็จ‹ๅŸท่กŒ๏ผˆไพ‹ๅฆ‚ไธ้œ€่ฆๅ…ฑ็”จ่จ˜ๆ†ถ้ซ”ใ€่ฎŠๆ•ธ็ญ‰๏ผ‰๏ผŒๅฏไปฅ่€ƒๆ…ฎไฝฟ็”จๆ›ดๅคงๅž‹็š„ๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ Celeryใ€‚ + +้€™้กžๅทฅๅ…ท้€šๅธธ้œ€่ฆ่ผƒ่ค‡้›œ็š„่จญๅฎš๏ผŒไปฅๅŠ่จŠๆฏ/ๅทฅไฝœไฝ‡ๅˆ—็ฎก็†ๅ™จ๏ผˆๅฆ‚ RabbitMQ ๆˆ– Redis๏ผ‰๏ผŒไฝ†ๅฎƒๅ€‘ๅ…่จฑไฝ ๅœจๅคšๅ€‹่กŒ็จ‹๏ผŒ็”š่‡ณๅคšๅฐไผบๆœๅ™จไธŠๅŸท่กŒ่ƒŒๆ™ฏไปปๅ‹™ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ้œ€่ฆๅญ˜ๅ–ๅŒไธ€ๅ€‹ **FastAPI** ๆ‡‰็”จไธญ็š„่ฎŠๆ•ธ่ˆ‡็‰ฉไปถ๏ผŒๆˆ–ๅช้œ€ๅŸท่กŒๅฐๅž‹็š„่ƒŒๆ™ฏไปปๅ‹™๏ผˆไพ‹ๅฆ‚ๅฏ„้€้ƒตไปถ้€š็Ÿฅ๏ผ‰๏ผŒๅƒ…ไฝฟ็”จ `BackgroundTasks` ๅณๅฏใ€‚ + +## ้‡้ปžๅ›ž้กง { #recap } + +ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ่ˆ‡็›ธไพ้ …ไธญๅŒฏๅ…ฅไธฆไฝฟ็”จ `BackgroundTasks` ๅƒๆ•ธ๏ผŒไปฅๆ–ฐๅขž่ƒŒๆ™ฏไปปๅ‹™ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/bigger-applications.md b/docs/zh-hant/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..d8b8c9bff8 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# ๆ›ดๅคงๅž‹็š„ๆ‡‰็”จ็จ‹ๅผ - ๅคšๅ€‹ๆช”ๆกˆ { #bigger-applications-multiple-files } + +ๅฆ‚ๆžœไฝ ๆญฃๅœจๅปบ็ฝฎไธ€ๅ€‹ๆ‡‰็”จ็จ‹ๅผๆˆ– Web API๏ผŒๅพˆๅฐ‘ๆœƒๆŠŠๆ‰€ๆœ‰ๆฑ่ฅฟ้ƒฝๆ”พๅœจๅ–ฎไธ€ๆช”ๆกˆ่ฃกใ€‚ + +FastAPI ๆไพ›ไบ†ไธ€ๅ€‹ๆ–นไพฟ็š„ๅทฅๅ…ท๏ผŒ่ฎ“ไฝ ๅœจ็ถญๆŒๅฝˆๆ€ง็š„ๅŒๆ™‚๏ผŒๅนซไฝ ็ต„็น”ๆ‡‰็”จ็จ‹ๅผ็š„็ตๆง‹ใ€‚ + +/// info | ่ณ‡่จŠ + +ๅฆ‚ๆžœไฝ ไพ†่‡ช Flask๏ผŒ้€™็›ธ็•ถๆ–ผ Flask ็š„ Blueprintsใ€‚ + +/// + +## ็ฏ„ไพ‹ๆช”ๆกˆ็ตๆง‹ { #an-example-file-structure } + +ๅ‡่จญไฝ ๆœ‰ๅฆ‚ไธ‹็š„ๆช”ๆกˆ็ตๆง‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | ๆ็คบ + +ๆœ‰ๅฅฝๅนพๅ€‹ `__init__.py` ๆช”ๆกˆ๏ผšๆฏๅ€‹็›ฎ้Œ„ๆˆ–ๅญ็›ฎ้Œ„ๅ„ไธ€ๅ€‹ใ€‚ + +้€™่ฎ“ๆˆ‘ๅ€‘ๅฏไปฅๆŠŠไธ€ๅ€‹ๆช”ๆกˆไธญ็š„็จ‹ๅผ็ขผๅŒฏๅ…ฅๅˆฐๅฆไธ€ๅ€‹ๆช”ๆกˆใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅœจ `app/main.py` ไฝ ๅฏไปฅๆœ‰ไธ€่กŒ๏ผš + +``` +from app.routers import items +``` + +/// + +* `app` ็›ฎ้Œ„ๅŒ…ๅซๆ‰€ๆœ‰ๅ…งๅฎนใ€‚ๅฎƒๆœ‰ไธ€ๅ€‹็ฉบ็š„ `app/__init__.py` ๆช”ๆกˆ๏ผŒๆ‰€ไปฅๅฎƒๆ˜ฏไธ€ๅ€‹ใ€ŒPython ๅฅ—ไปถใ€๏ผˆใ€ŒPython ๆจก็ต„ใ€็š„้›†ๅˆ๏ผ‰๏ผš`app`ใ€‚ +* ๅฎƒๅŒ…ๅซไธ€ๅ€‹ `app/main.py` ๆช”ๆกˆใ€‚ๅ› ็‚บๅฎƒๅœจไธ€ๅ€‹ Python ๅฅ—ไปถไธญ๏ผˆๆœ‰ `__init__.py` ๆช”ๆกˆ็š„็›ฎ้Œ„๏ผ‰๏ผŒๅฎƒๆ˜ฏ่ฉฒๅฅ—ไปถ็š„ไธ€ๅ€‹ใ€Œๆจก็ต„ใ€๏ผš`app.main`ใ€‚ +* ้‚„ๆœ‰ไธ€ๅ€‹ `app/dependencies.py` ๆช”ๆกˆ๏ผŒๅฐฑๅƒ `app/main.py` ไธ€ๆจฃ๏ผŒๅฎƒๆ˜ฏไธ€ๅ€‹ใ€Œๆจก็ต„ใ€๏ผš`app.dependencies`ใ€‚ +* ๆœ‰ไธ€ๅ€‹ๅญ็›ฎ้Œ„ `app/routers/`๏ผŒ่ฃก้ขๆœ‰ๅฆไธ€ๅ€‹ `__init__.py` ๆช”ๆกˆ๏ผŒๆ‰€ไปฅๅฎƒๆ˜ฏไธ€ๅ€‹ใ€ŒPython ๅญๅฅ—ไปถใ€๏ผš`app.routers`ใ€‚ +* ๆช”ๆกˆ `app/routers/items.py` ๅœจไธ€ๅ€‹ๅฅ—ไปถ `app/routers/` ๅ…ง๏ผŒๅ› ๆญคๅฎƒๆ˜ฏไธ€ๅ€‹ๅญๆจก็ต„๏ผš`app.routers.items`ใ€‚ +* ๅŒๆจฃๅœฐ๏ผŒ`app/routers/users.py` ๆ˜ฏๅฆไธ€ๅ€‹ๅญๆจก็ต„๏ผš`app.routers.users`ใ€‚ +* ้‚„ๆœ‰ไธ€ๅ€‹ๅญ็›ฎ้Œ„ `app/internal/`๏ผŒ่ฃก้ขๆœ‰ๅฆไธ€ๅ€‹ `__init__.py` ๆช”ๆกˆ๏ผŒๆ‰€ไปฅๅฎƒๅˆๆ˜ฏไธ€ๅ€‹ใ€ŒPython ๅญๅฅ—ไปถใ€๏ผš`app.internal`ใ€‚ +* ๆช”ๆกˆ `app/internal/admin.py` ๆ˜ฏๅฆไธ€ๅ€‹ๅญๆจก็ต„๏ผš`app.internal.admin`ใ€‚ + + + +ๅŒๆจฃ็š„ๆช”ๆกˆ็ตๆง‹๏ผŒ้™„ไธŠ่จป่งฃ๏ผš + +```bash +. +โ”œโ”€โ”€ app # ใ€Œappใ€ๆ˜ฏไธ€ๅ€‹ Python ๅฅ—ไปถ +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ้€™ๅ€‹ๆช”ๆกˆ่ฎ“ใ€Œappใ€ๆˆ็‚บใ€ŒPython ๅฅ—ไปถใ€ +โ”‚ย ย  โ”œโ”€โ”€ main.py # ใ€Œmainใ€ๆจก็ต„๏ผŒไพ‹ๅฆ‚ import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # ใ€Œdependenciesใ€ๆจก็ต„๏ผŒไพ‹ๅฆ‚ import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # ใ€Œroutersใ€ๆ˜ฏไธ€ๅ€‹ใ€ŒPython ๅญๅฅ—ไปถใ€ +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # ่ฎ“ใ€Œroutersใ€ๆˆ็‚บใ€ŒPython ๅญๅฅ—ไปถใ€ +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # ใ€Œitemsใ€ๅญๆจก็ต„๏ผŒไพ‹ๅฆ‚ import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # ใ€Œusersใ€ๅญๆจก็ต„๏ผŒไพ‹ๅฆ‚ import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # ใ€Œinternalใ€ๆ˜ฏไธ€ๅ€‹ใ€ŒPython ๅญๅฅ—ไปถใ€ +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ่ฎ“ใ€Œinternalใ€ๆˆ็‚บใ€ŒPython ๅญๅฅ—ไปถใ€ +โ”‚ย ย  โ””โ”€โ”€ admin.py # ใ€Œadminใ€ๅญๆจก็ต„๏ผŒไพ‹ๅฆ‚ import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +ๅ‡่จญๅฐˆ้–€่™•็†ไฝฟ็”จ่€…็š„ๆช”ๆกˆๆ˜ฏไฝๆ–ผ `/app/routers/users.py` ็š„ๅญๆจก็ต„ใ€‚ + +ไฝ ๅธŒๆœ›ๆŠŠ่ˆ‡ไฝฟ็”จ่€…็›ธ้—œ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ (path operation)ใ€ๅพžๅ…ถไป–็จ‹ๅผ็ขผๅˆ†้›ข๏ผŒ่ฎ“็ตๆง‹ๆ›ดๆœ‰ๆข็†ใ€‚ + +ไฝ†ๅฎƒไป็„ถๆ˜ฏๅŒไธ€ๅ€‹ FastAPI ๆ‡‰็”จ็จ‹ๅผ / Web API ็š„ไธ€้ƒจๅˆ†๏ผˆๅฑฌๆ–ผๅŒไธ€ๅ€‹ใ€ŒPython ๅฅ—ไปถใ€๏ผ‰ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `APIRouter` ็‚บ่ฉฒๆจก็ต„ๅปบ็ซ‹่ทฏๅพ‘ๆ“ไฝœใ€‚ + +### ๅŒฏๅ…ฅ `APIRouter` { #import-apirouter } + +ไฝ ๅฏไปฅๅƒๅฐ `FastAPI` ้กžๅˆฅ้‚ฃๆจฃๅŒฏๅ…ฅไธฆๅปบ็ซ‹ไธ€ๅ€‹ใ€Œๅฏฆไพ‹ใ€๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### ไฝฟ็”จ `APIRouter` ๅฎฃๅ‘Š่ทฏๅพ‘ๆ“ไฝœ { #path-operations-with-apirouter } + +็„ถๅพŒ็”จๅฎƒไพ†ๅฎฃๅ‘Šไฝ ็š„่ทฏๅพ‘ๆ“ไฝœใ€‚ + +็”จๆณ•ๅฐฑๅ’Œ `FastAPI` ้กžๅˆฅไธ€ๆจฃ๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +ไฝ ๅฏไปฅๆŠŠ `APIRouter` ๆƒณๆˆๆ˜ฏใ€Œ่ฟทไฝ ็‰ˆ็š„ `FastAPI`ใ€้กžๅˆฅใ€‚ + +ๆ‰€ๆœ‰็›ธๅŒ็š„้ธ้ …้ƒฝๆ”ฏๆดใ€‚ + +ๅŒๆจฃ็š„ `parameters`ใ€`responses`ใ€`dependencies`ใ€`tags` ็ญ‰ๅ…จ้ƒฝๅฏ็”จใ€‚ + +/// tip | ๆ็คบ + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒ่ฎŠๆ•ธๅๅซ `router`๏ผŒไฝ†ไฝ ๅฏไปฅ็”จไปปไฝ•ไฝ ๆƒณ็”จ็š„ๅ็จฑใ€‚ + +/// + +ๆˆ‘ๅ€‘็จๅพŒๆœƒๆŠŠ้€™ๅ€‹ `APIRouter` ๅŠ ้€ฒไธป่ฆ็š„ `FastAPI` ๆ‡‰็”จ็จ‹ๅผไธญ๏ผŒไฝ†ๅ…ˆไพ†็œ‹็œ‹็›ธไพๆ€ง่ˆ‡ๅฆไธ€ๅ€‹ `APIRouter`ใ€‚ + +## ็›ธไพๆ€ง { #dependencies } + +ๆˆ‘ๅ€‘็™ผ็พๆ‡‰็”จ็จ‹ๅผ็š„ๅคšๅ€‹ๅœฐๆ–นๆœƒ็”จๅˆฐไธ€ไบ›็›ธไพๆ€งใ€‚ + +ๆ‰€ไปฅๆŠŠๅฎƒๅ€‘ๆ”พ้€ฒ็จ็ซ‹็š„ `dependencies` ๆจก็ต„๏ผˆ`app/dependencies.py`๏ผ‰ใ€‚ + +ๆŽฅไธ‹ไพ†ๆˆ‘ๅ€‘ๆœƒ็”จไธ€ๅ€‹็ฐกๅ–ฎ็š„็›ธไพๆ€งไพ†่ฎ€ๅ–่‡ช่จ‚็š„ `X-Token` ๆจ™้ ญ๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | ๆ็คบ + +็‚บไบ†็ฐกๅŒ–็ฏ„ไพ‹๏ผŒๆˆ‘ๅ€‘ไฝฟ็”จไบ†ไธ€ๅ€‹่™›ๆง‹็š„ๆจ™้ ญใ€‚ + +ไฝ†ๅœจ็œŸๅฏฆๆƒ…ๆณไธ‹๏ผŒไฝฟ็”จๅ…งๅปบ็š„[ๅฎ‰ๅ…จๅทฅๅ…ท](security/index.md){.internal-link target=_blank}ๆœƒๆœ‰ๆ›ดๅฅฝ็š„ๆ•ˆๆžœใ€‚ + +/// + +## ๅฆไธ€ๅ€‹ๅธถๆœ‰ `APIRouter` ็š„ๆจก็ต„ { #another-module-with-apirouter } + +ๅ‡่จญไฝ ้‚„ๆœ‰ไธ€ๅ€‹ๆจก็ต„ `app/routers/items.py`๏ผŒๅฐˆ้–€่™•็†ๆ‡‰็”จ็จ‹ๅผไธญ็š„ใ€Œitemsใ€ใ€‚ + +ไฝ ๆœ‰ไปฅไธ‹่ทฏๅพ‘ๆ“ไฝœ๏ผš + +* `/items/` +* `/items/{item_id}` + +ๅ…ถ็ตๆง‹่ˆ‡ `app/routers/users.py` ็›ธๅŒใ€‚ + +ไฝ†ๆˆ‘ๅ€‘ๆƒณ่ฆๆ›ด่ฐๆ˜Žๅœฐ็ฐกๅŒ–ไธ€ไบ›็จ‹ๅผ็ขผใ€‚ + +ๆˆ‘ๅ€‘็Ÿฅ้“้€™ๅ€‹ๆจก็ต„ไธญ็š„ๆ‰€ๆœ‰่ทฏๅพ‘ๆ“ไฝœ้ƒฝๆœ‰็›ธๅŒ็š„๏ผš + +* ่ทฏๅพ‘ `prefix`๏ผš`/items` +* `tags`๏ผš๏ผˆๅชๆœ‰ไธ€ๅ€‹ๆจ™็ฑค๏ผš`items`๏ผ‰ +* ้กๅค–็š„ `responses` +* `dependencies`๏ผšๅฎƒๅ€‘้ƒฝ้œ€่ฆๆˆ‘ๅ€‘ๅ…ˆๅ‰ๅปบ็ซ‹็š„ `X-Token` ็›ธไพๆ€ง + +ๅ› ๆญค๏ผŒๆˆ‘ๅ€‘ๅฏไปฅไธๅฟ…ๆŠŠ้€™ไบ›้ƒฝๅŠ ๅœจๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœไธŠ๏ผŒ่€Œๆ˜ฏๆŠŠๅฎƒๅ€‘ๅŠ ๅœจ `APIRouter` ไธŠใ€‚ + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +็”ฑๆ–ผๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœ็š„่ทฏๅพ‘้ƒฝๅฟ…้ ˆไปฅ `/` ้–‹้ ญ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...ๆ‰€ไปฅ prefix ๆœซๅฐพไธ่ƒฝๅธถๆœ‰ `/`ใ€‚ + +ๅ› ๆญค๏ผŒๆญค่™•็š„ prefix ๆ˜ฏ `/items`ใ€‚ + +ๆˆ‘ๅ€‘ไนŸๅฏไปฅๅŠ ไธŠไธ€ๅ€‹ `tags` ๆธ…ๅ–ฎ๏ผŒไปฅๅŠๆœƒๅฅ—็”จๅœจๆญค router ๅ…งๆ‰€ๆœ‰่ทฏๅพ‘ๆ“ไฝœไธŠ็š„้กๅค– `responses`ใ€‚ + +ๆˆ‘ๅ€‘้‚„ๅฏไปฅๅŠ ไธŠไธ€ๅ€‹ `dependencies` ๆธ…ๅ–ฎ๏ผŒ้€™ไบ›็›ธไพๆ€งๆœƒๅŠ ๅ…ฅๆญค router ๅ…งๆ‰€ๆœ‰็š„่ทฏๅพ‘ๆ“ไฝœ๏ผŒไธฆๅœจๅฐๅฎƒๅ€‘็š„ๆฏๅ€‹่ซ‹ๆฑ‚ไธŠๅŸท่กŒ / ่งฃๆฑบใ€‚ + +/// tip | ๆ็คบ + +่ซ‹ๆณจๆ„๏ผŒๅฐฑๅƒๅœจ[่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จไธญ็š„็›ธไพๆ€ง](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}ไธ€ๆจฃ๏ผŒไธๆœƒๆŠŠไปปไฝ•ๅ€ผๅ‚ณ้ž็ตฆไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰ใ€‚ + +/// + +ๆœ€ๅพŒ็š„็ตๆžœๆ˜ฏ้€™ไบ› item ็š„่ทฏๅพ‘ๅฆ‚ไธ‹๏ผš + +* `/items/` +* `/items/{item_id}` + +...ๆญฃๅฆ‚ๆˆ‘ๅ€‘้ ๆœŸ็š„ใ€‚ + +* ๅฎƒๅ€‘ๆœƒ่ขซๆจ™่จ˜็‚บๅชๆœ‰ไธ€ๅ€‹ๅญ—ไธฒ `"items"` ็š„ๆจ™็ฑคๆธ…ๅ–ฎใ€‚ + * ้€™ไบ›ใ€Œๆจ™็ฑคใ€ๅฐ่‡ชๅ‹•ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑ๏ผˆไฝฟ็”จ OpenAPI๏ผ‰็‰นๅˆฅๆœ‰็”จใ€‚ +* ๅฎƒๅ€‘้ƒฝๆœƒๅŒ…ๅซ้ ๅ…ˆๅฎš็พฉ็š„ `responses`ใ€‚ +* ้€™ไบ›่ทฏๅพ‘ๆ“ไฝœ้ƒฝๆœƒๅœจๅŸท่กŒๅ‰่ฉ•ไผฐ / ๅŸท่กŒๅ…ถ `dependencies` ๆธ…ๅ–ฎใ€‚ + * ๅฆ‚ๆžœไฝ ไนŸๅœจ็‰นๅฎš็š„่ทฏๅพ‘ๆ“ไฝœไธญๅฎฃๅ‘Šไบ†็›ธไพๆ€ง๏ผŒ้€™ไบ›็›ธไพๆ€งไนŸๆœƒ่ขซๅŸท่กŒใ€‚ + * Router ็š„็›ธไพๆ€งๆœƒๅ…ˆๅŸท่กŒ๏ผŒ็„ถๅพŒๆ˜ฏ[่ฃ้ฃพๅ™จไธญ็š„ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}๏ผŒๆœ€ๅพŒๆ˜ฏไธ€่ˆฌๅƒๆ•ธ็›ธไพๆ€งใ€‚ + * ไฝ ไนŸๅฏไปฅๅŠ ๅ…ฅๅธถๆœ‰ `scopes` ็š„ [`Security` ็›ธไพๆ€ง](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}ใ€‚ + +/// tip | ๆ็คบ + +ๅœจ `APIRouter` ไธญ่จญๅฎš `dependencies`๏ผŒไพ‹ๅฆ‚ๅฏไปฅ็”จไพ†ๅฐไธ€ๆ•ด็ต„่ทฏๅพ‘ๆ“ไฝœ่ฆๆฑ‚้ฉ—่ญ‰ใ€‚ๅณไฝฟๆฒ’ๆœ‰ๅœจๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœๅ€‹ๅˆฅๅŠ ๅ…ฅ็›ธไพๆ€งไนŸๆฒ’้—œไฟ‚ใ€‚ + +/// + +/// check | ๆชขๆŸฅ + +`prefix`ใ€`tags`ใ€`responses` ่ˆ‡ `dependencies` ๅƒๆ•ธ๏ผˆๅฐฑๅƒ่จฑๅคšๅ…ถไป–ๆƒ…ๆณไธ€ๆจฃ๏ผ‰ๅชๆ˜ฏ FastAPI ๆไพ›็š„ๅŠŸ่ƒฝ๏ผŒๅนซๅŠฉไฝ ้ฟๅ…้‡่ค‡็จ‹ๅผ็ขผใ€‚ + +/// + +### ๅŒฏๅ…ฅ็›ธไพๆ€ง { #import-the-dependencies } + +้€™ๆฎต็จ‹ๅผ็ขผๅœจๆจก็ต„ `app.routers.items`๏ผˆๆช”ๆกˆ `app/routers/items.py`๏ผ‰ไธญใ€‚ + +ๆˆ‘ๅ€‘้œ€่ฆๅพžๆจก็ต„ `app.dependencies`๏ผˆๆช”ๆกˆ `app/dependencies.py`๏ผ‰ๅ–ๅพ—็›ธไพๆ€งๅ‡ฝๅผใ€‚ + +ๅ› ๆญคๆˆ‘ๅ€‘็”จ `..` ๅš็›ธๅฐๅŒฏๅ…ฅ็›ธไพๆ€ง๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### ็›ธๅฐๅŒฏๅ…ฅๅฆ‚ไฝ•้‹ไฝœ { #how-relative-imports-work } + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ๅฐๅŒฏๅ…ฅ็š„้‹ไฝœๆ–นๅผๅๅˆ†ไบ†่งฃ๏ผŒๅฏไปฅ็›ดๆŽฅ่ทณๅˆฐไธ‹ไธ€็ฏ€ใ€‚ + +/// + +ๅ–ฎไธ€็š„้ปž่™Ÿ `.`๏ผŒๅฆ‚ไธ‹๏ผš + +```Python +from .dependencies import get_token_header +``` + +ไปฃ่กจ๏ผš + +* ๅพžๆญคๆจก็ต„๏ผˆๆช”ๆกˆ `app/routers/items.py`๏ผ‰ๆ‰€ๅœจ็š„็›ธๅŒๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/routers/`๏ผ‰้–‹ๅง‹... +* ๆ‰พๅˆฐๆจก็ต„ `dependencies`๏ผˆๆƒณๅƒ็š„ๆช”ๆกˆ `app/routers/dependencies.py`๏ผ‰... +* ไธฆๅพžไธญๅŒฏๅ…ฅๅ‡ฝๅผ `get_token_header`ใ€‚ + +ไฝ†้‚ฃๅ€‹ๆช”ๆกˆไธๅญ˜ๅœจ๏ผŒๆˆ‘ๅ€‘็š„็›ธไพๆ€งๅœจ `app/dependencies.py`ใ€‚ + +ๅ›žๆƒณไธ€ไธ‹ๆˆ‘ๅ€‘็š„ๆ‡‰็”จ / ๆช”ๆกˆ็ตๆง‹้•ท้€™ๆจฃ๏ผš + + + +--- + +ๅ…ฉๅ€‹้ปž่™Ÿ `..`๏ผŒๅฆ‚ไธ‹๏ผš + +```Python +from ..dependencies import get_token_header +``` + +ไปฃ่กจ๏ผš + +* ๅพžๆญคๆจก็ต„๏ผˆๆช”ๆกˆ `app/routers/items.py`๏ผ‰ๆ‰€ๅœจ็š„็›ธๅŒๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/routers/`๏ผ‰้–‹ๅง‹... +* ๅ‰ๅพ€ๅ…ถ็ˆถๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/`๏ผ‰... +* ็„ถๅพŒๅœจ้‚ฃ่ฃกๆ‰พๅˆฐๆจก็ต„ `dependencies`๏ผˆๆช”ๆกˆ `app/dependencies.py`๏ผ‰... +* ไธฆๅพžไธญๅŒฏๅ…ฅๅ‡ฝๅผ `get_token_header`ใ€‚ + +้€™ๅฐฑๆญฃ็ขบไบ†๏ผ๐ŸŽ‰ + +--- + +ๅŒๆจฃๅœฐ๏ผŒๅฆ‚ๆžœๆˆ‘ๅ€‘็”จไธ‰ๅ€‹้ปž่™Ÿ `...`๏ผŒๅฆ‚ไธ‹๏ผš + +```Python +from ...dependencies import get_token_header +``` + +ๅฐฑไปฃ่กจ๏ผš + +* ๅพžๆญคๆจก็ต„๏ผˆๆช”ๆกˆ `app/routers/items.py`๏ผ‰ๆ‰€ๅœจ็š„็›ธๅŒๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/routers/`๏ผ‰้–‹ๅง‹... +* ๅ‰ๅพ€ๅ…ถ็ˆถๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/`๏ผ‰... +* ๅ†ๅ‰ๅพ€้‚ฃๅ€‹ๅฅ—ไปถ็š„็ˆถๅฑค๏ผˆๆฒ’ๆœ‰ๆ›ดไธŠๅฑค็š„ๅฅ—ไปถไบ†๏ผŒ`app` ๅทฒๆ˜ฏๆœ€ไธŠๅฑค ๐Ÿ˜ฑ๏ผ‰... +* ็„ถๅพŒๅœจ้‚ฃ่ฃกๆ‰พๅˆฐๆจก็ต„ `dependencies`๏ผˆๆช”ๆกˆ `app/dependencies.py`๏ผ‰... +* ไธฆๅพžไธญๅŒฏๅ…ฅๅ‡ฝๅผ `get_token_header`ใ€‚ + +้‚ฃๆœƒๆŒ‡ๅ‘ `app/` ไน‹ไธŠ็š„ๆŸๅ€‹ๅฅ—ไปถ๏ผŒ่ฉฒๅฅ—ไปถ้œ€ๆœ‰่‡ชๅทฑ็š„ `__init__.py` ็ญ‰็ญ‰ใ€‚ไฝ†ๆˆ‘ๅ€‘ๆฒ’ๆœ‰ใ€‚ๆ‰€ไปฅๅœจ้€™ๅ€‹ไพ‹ๅญไธญๆœƒไธŸๅ‡บ้Œฏ่ชคใ€‚๐Ÿšจ + +ไธ้Ž็พๅœจไฝ ็Ÿฅ้“ๅฎƒ็š„้‹ไฝœๆ–นๅผไบ†๏ผŒๅ› ๆญค็„ก่ซ–ไฝ ็š„ๆ‡‰็”จๆœ‰ๅคš่ค‡้›œ๏ผŒไฝ ้ƒฝๅฏไปฅไฝฟ็”จ็›ธๅฐๅŒฏๅ…ฅใ€‚๐Ÿค“ + +### ๅŠ ไธŠไธ€ไบ›่‡ช่จ‚็š„ `tags`ใ€`responses` ่ˆ‡ `dependencies` { #add-some-custom-tags-responses-and-dependencies } + +ๆˆ‘ๅ€‘ๆฒ’ๆœ‰ๆŠŠ `/items` ็š„ prefix ไปฅๅŠ `tags=["items"]` ๅŠ ๅœจๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœไธŠ๏ผŒๅ› ็‚บๆˆ‘ๅ€‘ๅทฒ็ถ“ๆŠŠๅฎƒๅ€‘ๅŠ ๅœจ `APIRouter` ไธŠไบ†ใ€‚ + +ไฝ†ๆˆ‘ๅ€‘ไปๅฏไปฅๅœจ็‰นๅฎš็š„่ทฏๅพ‘ๆ“ไฝœไธŠๅ†ๅŠ ไธŠๆ›ดๅคš็š„ `tags`๏ผŒไปฅๅŠไธ€ไบ›ๅชๅฑฌๆ–ผ่ฉฒ่ทฏๅพ‘ๆ“ไฝœ็š„้กๅค– `responses`๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | ๆ็คบ + +้€™ๆœ€ๅพŒไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœๆœƒๆœ‰็ต„ๅˆๅพŒ็š„ๆจ™็ฑค๏ผš`["items", "custom"]`ใ€‚ + +่€Œไธ”ๅœจๆ–‡ไปถไธญๅŒๆ™‚ๆœƒๆœ‰ `404` ่ˆ‡ `403` ๅ…ฉ็จฎๅ›žๆ‡‰ใ€‚ + +/// + +## ไธป็จ‹ๅผ `FastAPI` { #the-main-fastapi } + +็พๅœจ๏ผŒไพ†็œ‹็œ‹ `app/main.py` ้€™ๅ€‹ๆจก็ต„ใ€‚ + +ไฝ ๆœƒๅœจ้€™่ฃกๅŒฏๅ…ฅไธฆไฝฟ็”จ `FastAPI` ้กžๅˆฅใ€‚ + +้€™ๆœƒๆ˜ฏไฝ ็š„ๆ‡‰็”จ็จ‹ๅผไธญๆŠŠไธ€ๅˆ‡ไธฒ่ตทไพ†็š„ไธปๆช”ๆกˆใ€‚ + +่€Œ้šจ่‘—ๅคงๅคšๆ•ธ็š„้‚่ผฏ้ƒฝๆ”พๅœจๅ„่‡ช็š„ๆจก็ต„ไธญ๏ผŒไธปๆช”ๆกˆๆœƒ็›ธ็•ถ็ฐกๆฝ”ใ€‚ + +### ๅŒฏๅ…ฅ `FastAPI` { #import-fastapi } + +็…งๅธธๅŒฏๅ…ฅไธฆๅปบ็ซ‹ `FastAPI` ้กžๅˆฅใ€‚ + +ๆˆ‘ๅ€‘็”š่‡ณๅฏไปฅๅฎฃๅ‘Š[ๅ…จๅŸŸ็›ธไพๆ€ง](dependencies/global-dependencies.md){.internal-link target=_blank}๏ผŒๅฎƒๅ€‘ๆœƒ่ˆ‡ๅ„ `APIRouter` ็š„็›ธไพๆ€งๅˆไฝต๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### ๅŒฏๅ…ฅ `APIRouter` { #import-the-apirouter } + +็พๅœจๆˆ‘ๅ€‘ๅŒฏๅ…ฅๅŒ…ๅซ `APIRouter` ็š„ๅ…ถไป–ๅญๆจก็ต„๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +็”ฑๆ–ผ `app/routers/users.py` ่ˆ‡ `app/routers/items.py` ๆ˜ฏๅŒไธ€ๅ€‹ Python ๅฅ—ไปถ `app` ็š„ๅญๆจก็ต„๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ็”จๅ–ฎไธ€็š„้ปž่™Ÿ `.` ไพ†้€ฒ่กŒใ€Œ็›ธๅฐๅŒฏๅ…ฅใ€ใ€‚ + +### ๅŒฏๅ…ฅๅฆ‚ไฝ•้‹ไฝœ { #how-the-importing-works } + +้€™ๆฎต๏ผš + +```Python +from .routers import items, users +``` + +ไปฃ่กจ๏ผš + +* ๅพžๆญคๆจก็ต„๏ผˆๆช”ๆกˆ `app/main.py`๏ผ‰ๆ‰€ๅœจ็š„็›ธๅŒๅฅ—ไปถ๏ผˆ็›ฎ้Œ„ `app/`๏ผ‰้–‹ๅง‹... +* ๅฐ‹ๆ‰พๅญๅฅ—ไปถ `routers`๏ผˆ็›ฎ้Œ„ `app/routers/`๏ผ‰... +* ไธฆๅพžไธญๅŒฏๅ…ฅๅญๆจก็ต„ `items`๏ผˆๆช”ๆกˆ `app/routers/items.py`๏ผ‰่ˆ‡ `users`๏ผˆๆช”ๆกˆ `app/routers/users.py`๏ผ‰... + +ๆจก็ต„ `items` ๆœƒๆœ‰ไธ€ๅ€‹่ฎŠๆ•ธ `router`๏ผˆ`items.router`๏ผ‰ใ€‚้€™ๅฐฑๆ˜ฏๆˆ‘ๅ€‘ๅœจ `app/routers/items.py` ๅปบ็ซ‹็š„้‚ฃๅ€‹ `APIRouter` ็‰ฉไปถใ€‚ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅฐ `users` ๆจก็ต„ๅšไธ€ๆจฃ็š„ไบ‹ใ€‚ + +ๆˆ‘ๅ€‘ไนŸๅฏไปฅ้€™ๆจฃๅŒฏๅ…ฅ๏ผš + +```Python +from app.routers import items, users +``` + +/// info | ่ณ‡่จŠ + +็ฌฌไธ€็จฎๆ˜ฏใ€Œ็›ธๅฐๅŒฏๅ…ฅใ€๏ผš + +```Python +from .routers import items, users +``` + +็ฌฌไบŒ็จฎๆ˜ฏใ€Œ็ต•ๅฐๅŒฏๅ…ฅใ€๏ผš + +```Python +from app.routers import items, users +``` + +ๆƒณไบ†่งฃๆ›ดๅคš้—œๆ–ผ Python ๅฅ—ไปถ่ˆ‡ๆจก็ต„๏ผŒ่ซ‹้–ฑ่ฎ€ๅฎ˜ๆ–น็š„ๆจก็ต„่ชชๆ˜Žๆ–‡ไปถใ€‚ + +/// + +### ้ฟๅ…ๅ็จฑ่ก็ช { #avoid-name-collisions } + +ๆˆ‘ๅ€‘็›ดๆŽฅๅŒฏๅ…ฅๅญๆจก็ต„ `items`๏ผŒ่€Œไธๆ˜ฏๅชๅŒฏๅ…ฅๅฎƒ็š„่ฎŠๆ•ธ `router`ใ€‚ + +้€™ๆ˜ฏๅ› ็‚บๅœจๅญๆจก็ต„ `users` ไธญไนŸๆœ‰ๅฆไธ€ๅ€‹ๅ็‚บ `router` ็š„่ฎŠๆ•ธใ€‚ + +ๅฆ‚ๆžœๆˆ‘ๅ€‘ๅƒไธ‹้ข้€™ๆจฃไธ€ๅ€‹ๆŽฅไธ€ๅ€‹ๅŒฏๅ…ฅ๏ผš + +```Python +from .routers.items import router +from .routers.users import router +``` + +ไพ†่‡ช `users` ็š„ `router` ๆœƒ่ฆ†่“‹ๆމ `items` ็š„ `router`๏ผŒๆˆ‘ๅ€‘ๅฐฑ็„กๆณ•ๅŒๆ™‚ไฝฟ็”จๅ…ฉ่€…ใ€‚ + +ๅ› ๆญค๏ผŒ็‚บไบ†่ƒฝๅœจๅŒไธ€ๅ€‹ๆช”ๆกˆไธญๅŒๆ™‚ไฝฟ็”จๅฎƒๅ€‘๏ผŒๆˆ‘ๅ€‘็›ดๆŽฅๅŒฏๅ…ฅๅญๆจก็ต„๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### ๅฐ‡ `users` ่ˆ‡ `items` ็š„ `APIRouter` ็ดๅ…ฅ { #include-the-apirouters-for-users-and-items } + +็พๅœจ๏ผŒๆŠŠๅญๆจก็ต„ `users` ่ˆ‡ `items` ็š„ `router` ็ดๅ…ฅ๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// info | ่ณ‡่จŠ + +`users.router` ๆ˜ฏไฝๆ–ผ `app/routers/users.py` ๆช”ๆกˆๅ…ง็š„ `APIRouter`ใ€‚ + +่€Œ `items.router` ๆ˜ฏไฝๆ–ผ `app/routers/items.py` ๆช”ๆกˆๅ…ง็š„ `APIRouter`ใ€‚ + +/// + +้€้Ž `app.include_router()`๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๆŠŠๆฏๅ€‹ `APIRouter` ๅŠ ๅˆฐไธป่ฆ็š„ `FastAPI` ๆ‡‰็”จ็จ‹ๅผใ€‚ + +ๅฎƒๆœƒๆŠŠ่ฉฒ router ็š„ๆ‰€ๆœ‰่ทฏ็”ฑ้ƒฝ็ดๅ…ฅๆˆ็‚บๆ‡‰็”จ็š„ไธ€้ƒจๅˆ†ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅฏฆ้š›ไธŠ๏ผŒๅฎƒๆœƒๅœจๅ…ง้ƒจ็‚บ `APIRouter` ไธญๅฎฃๅ‘Š็š„ๆฏไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅปบ็ซ‹ไธ€ๅ€‹ๅฐๆ‡‰็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ใ€‚ + +ๆ‰€ไปฅๅœจๅน•ๅพŒ๏ผŒๅฎƒๅฏฆ้š›้‹ไฝœ่ตทไพ†ๅฐฑๅƒๆ˜ฏไธ€ๅ€‹ๅ–ฎไธ€็š„ๆ‡‰็”จใ€‚ + +/// + +/// check | ๆชขๆŸฅ + +ๆŠŠ router ็ดๅ…ฅๆ™‚ไธ้œ€่ฆๆ“”ๅฟƒๆ•ˆ่ƒฝใ€‚ + +้€™ๅชๆœƒๅœจๅ•Ÿๅ‹•ๆ™‚่Šฑ่ฒปๅพฎ็ง’็ญ‰็ดš๏ผŒไธ”ๅช็™ผ็”Ÿไธ€ๆฌกใ€‚ + +ๅ› ๆญคไธๆœƒๅฝฑ้Ÿฟๆ•ˆ่ƒฝใ€‚โšก + +/// + +### ไปฅ่‡ช่จ‚็š„ `prefix`ใ€`tags`ใ€`responses` ่ˆ‡ `dependencies` ็ดๅ…ฅไธ€ๅ€‹ `APIRouter` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +็พๅœจ๏ผŒๅ‡่จญไฝ ็š„็ต„็น”ๆไพ›ไบ†ไธ€ๅ€‹ `app/internal/admin.py` ๆช”ๆกˆ็ตฆไฝ ใ€‚ + +ๅฎƒๅŒ…ๅซไธ€ๅ€‹ๅธถๆœ‰ไธ€ไบ›็ฎก็†ๅ“ก่ทฏๅพ‘ๆ“ไฝœ็š„ `APIRouter`๏ผŒไธฆๅœจ็ต„็น”ๅ…งๅคšๅ€‹ๅฐˆๆกˆไน‹้–“ๅ…ฑ็”จใ€‚ + +็‚บไบ†้€™ๅ€‹็ฏ„ไพ‹ๅฎƒๆœƒ้žๅธธ็ฐกๅ–ฎใ€‚ไฝ†ๅ‡่จญๅ› ็‚บๅฎƒๆœƒ่ˆ‡็ต„็น”ๅ…ง็š„ๅ…ถไป–ๅฐˆๆกˆๅ…ฑ็”จ๏ผŒๆˆ‘ๅ€‘ไธ่ƒฝ็›ดๆŽฅไฟฎๆ”นๅฎƒไธฆๆŠŠ `prefix`ใ€`dependencies`ใ€`tags` ็ญ‰ๅŠ ๅœจ `APIRouter` ไธŠ๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +ไฝ†็•ถๆˆ‘ๅ€‘ๆŠŠ้€™ๅ€‹ `APIRouter` ็ดๅ…ฅๆ™‚๏ผŒไป็„ถๅธŒๆœ›่จญๅฎš่‡ช่จ‚็š„ `prefix`๏ผŒ่ฎ“ๅฎƒๆ‰€ๆœ‰็š„่ทฏๅพ‘ๆ“ไฝœ้ƒฝไปฅ `/admin` ้–‹้ ญ๏ผ›ๆˆ‘ๅ€‘ๆƒณ็”จ้€™ๅ€‹ๅฐˆๆกˆๅทฒ็ถ“ๆœ‰็š„ `dependencies` ไพ†ไฟ่ญทๅฎƒ๏ผŒไธฆไธ”่ฆๅŠ ๅ…ฅ `tags` ่ˆ‡ `responses`ใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅๅœจไธไฟฎๆ”นๅŽŸๅง‹ `APIRouter` ็š„ๆƒ…ๆณไธ‹๏ผŒๅฐ‡้€™ไบ›ๅƒๆ•ธๅ‚ณ็ตฆ `app.include_router()` ไพ†้”ๆˆ๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅŽŸๅง‹็š„ `APIRouter` ๅฐ‡ไฟๆŒไธ่ฎŠ๏ผŒๅ› ๆญคๆˆ‘ๅ€‘ไป็„ถๅฏไปฅๆŠŠๅŒไธ€ๅ€‹ `app/internal/admin.py` ๆช”ๆกˆ่ˆ‡็ต„็น”ไธญ็š„ๅ…ถไป–ๅฐˆๆกˆๅ…ฑ็”จใ€‚ + +็ตๆžœๆ˜ฏๅœจๆˆ‘ๅ€‘็š„ๆ‡‰็”จไธญ๏ผŒไพ†่‡ช `admin` ๆจก็ต„็š„ๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœ้ƒฝๆœƒๆœ‰๏ผš + +* ๅ‰็ถด `/admin` +* ๆจ™็ฑค `admin` +* ็›ธไพๆ€ง `get_token_header` +* ๅ›žๆ‡‰ `418` ๐Ÿต + +ไฝ†้€™ๅชๆœƒๅฝฑ้Ÿฟๆˆ‘ๅ€‘ๆ‡‰็”จไธญ็š„้‚ฃๅ€‹ `APIRouter`๏ผŒไธๆœƒๅฝฑ้Ÿฟไปปไฝ•ๅ…ถไป–ไฝฟ็”จๅฎƒ็š„็จ‹ๅผ็ขผใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ…ถไป–ๅฐˆๆกˆๅฏไปฅ็”จไธๅŒ็š„้ฉ—่ญ‰ๆ–นๅผๆญ้…็›ธๅŒ็š„ `APIRouter`ใ€‚ + +### ๅŠ ไธŠไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœ { #include-a-path-operation } + +ๆˆ‘ๅ€‘ไนŸๅฏไปฅ็›ดๆŽฅๆŠŠ่ทฏๅพ‘ๆ“ไฝœๅŠ ๅˆฐ `FastAPI` ๆ‡‰็”จไธญใ€‚ + +้€™่ฃกๆˆ‘ๅ€‘ๅฐฑๅŠ ไธ€ไธ‹... ๅชๆ˜ฏ็‚บไบ†็คบ็ฏ„ๅฏไปฅ้€™้บผๅš ๐Ÿคท๏ผš + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +่€Œไธ”ๅฎƒๆœƒๅ’Œ้€้Ž `app.include_router()` ๅŠ ๅ…ฅ็š„ๅ…ถไป–่ทฏๅพ‘ๆ“ไฝœๆญฃ็ขบๅœฐไธ€่ตท้‹ไฝœใ€‚ + +/// info | ้žๅธธๆŠ€่ก“็ดฐ็ฏ€ + +ๆณจๆ„๏ผš้€™ๆ˜ฏๅ€‹้žๅธธๆŠ€่ก“ๆ€ง็š„็ดฐ็ฏ€๏ผŒไฝ ๅคงๆฆ‚ๅฏไปฅ็›ดๆŽฅ็•ฅ้Žใ€‚ + +--- + +`APIRouter` ไธๆ˜ฏ่ขซใ€ŒๆŽ›่ผ‰ (mount)ใ€็š„๏ผŒๅฎƒๅ€‘ไธๆœƒ่ˆ‡ๆ‡‰็”จ็š„ๅ…ถไป–้ƒจๅˆ†้š”้›ข้–‹ไพ†ใ€‚ + +้€™ๆ˜ฏๅ› ็‚บๆˆ‘ๅ€‘่ฆๆŠŠๅฎƒๅ€‘็š„่ทฏๅพ‘ๆ“ไฝœๅŒ…ๅซ้€ฒ OpenAPI ็ตๆง‹่ˆ‡ไฝฟ็”จ่€…ไป‹้ขไธญใ€‚ + +็”ฑๆ–ผ็„กๆณ•ๅฐ‡ๅฎƒๅ€‘้š”้›ขไธฆ็จ็ซ‹ใ€ŒๆŽ›่ผ‰ใ€๏ผŒๆ‰€ไปฅ้€™ไบ›่ทฏๅพ‘ๆ“ไฝœๆœƒ่ขซใ€Œ่ค‡่ฃฝใ€๏ผˆ้‡ๆ–ฐๅปบ็ซ‹๏ผ‰๏ผŒ่€Œไธๆ˜ฏ็›ดๆŽฅๅŒ…ๅซ้€ฒไพ†ใ€‚ + +/// + +## ๆชขๆŸฅ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถ { #check-the-automatic-api-docs } + +็พๅœจ๏ผŒๅŸท่กŒไฝ ็š„ๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +็„ถๅพŒ้–‹ๅ•Ÿไฝๆ–ผ http://127.0.0.1:8000/docs ็š„ๆ–‡ไปถใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถ๏ผŒๅŒ…ๅซไพ†่‡ชๆ‰€ๆœ‰ๅญๆจก็ต„็š„่ทฏๅพ‘๏ผŒไฝฟ็”จๆญฃ็ขบ็š„่ทฏๅพ‘๏ผˆ่ˆ‡ๅ‰็ถด๏ผ‰่ˆ‡ๆญฃ็ขบ็š„ๆจ™็ฑค๏ผš + + + +## ไปฅไธๅŒ็š„ `prefix` ๅคšๆฌก็ดๅ…ฅๅŒไธ€ๅ€‹ router { #include-the-same-router-multiple-times-with-different-prefix } + +ไฝ ไนŸๅฏไปฅ็”จไธๅŒ็š„ๅ‰็ถด๏ผŒๅฐๅŒไธ€ๅ€‹ router ๅคšๆฌกๅ‘ผๅซ `.include_router()`ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ้€™ๅฐๆ–ผๅœจไธๅŒๅ‰็ถดไธ‹ๆไพ›็›ธๅŒ็š„ API ๅพˆๆœ‰็”จ๏ผŒๅฆ‚ `/api/v1` ่ˆ‡ `/api/latest`ใ€‚ + +้€™ๆ˜ฏ้€ฒ้šŽ็”จๆณ•๏ผŒไฝ ๅฏ่ƒฝไธๆœƒ้œ€่ฆ๏ผŒไฝ†่‹ฅๆœ‰้œ€่ฆๅฎƒๅฐฑๅœจ้‚ฃ่ฃกใ€‚ + +## ๅœจๅฆไธ€ๅ€‹ `APIRouter` ไธญ็ดๅ…ฅไธ€ๅ€‹ `APIRouter` { #include-an-apirouter-in-another } + +ๅฐฑๅƒไฝ ๅฏไปฅๅœจ `FastAPI` ๆ‡‰็”จไธญ็ดๅ…ฅไธ€ๅ€‹ `APIRouter` ไธ€ๆจฃ๏ผŒไฝ ไนŸๅฏไปฅๅœจๅฆไธ€ๅ€‹ `APIRouter` ไธญ็ดๅ…ฅไธ€ๅ€‹ `APIRouter`๏ผŒ็”จๆณ•ๅฆ‚ไธ‹๏ผš + +```Python +router.include_router(other_router) +``` + +่ซ‹็ขบไฟๅœจๆŠŠ `router` ็ดๅ…ฅ `FastAPI` ๆ‡‰็”จไน‹ๅ‰ๅ…ˆ้€™้บผๅš๏ผŒ้€™ๆจฃ `other_router` ็š„่ทฏๅพ‘ๆ“ไฝœไนŸๆœƒ่ขซๅŒ…ๅซ้€ฒๅŽปใ€‚ diff --git a/docs/zh-hant/docs/tutorial/body-fields.md b/docs/zh-hant/docs/tutorial/body-fields.md new file mode 100644 index 0000000000..a16e756b7c --- /dev/null +++ b/docs/zh-hant/docs/tutorial/body-fields.md @@ -0,0 +1,61 @@ +# Body - ๆฌ„ไฝ { #body-fields } + +ๅฐฑๅƒไฝ ๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ (path operation function)ใ€็š„ๅƒๆ•ธไธญ็”จ `Query`ใ€`Path` ๅ’Œ `Body` ๅฎฃๅ‘Š้กๅค–็š„้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ไธ€ๆจฃ๏ผŒไฝ ไนŸๅฏไปฅๅœจ Pydantic ๆจกๅž‹ไธญไฝฟ็”จ Pydantic ็š„ `Field` ไพ†ๅฎฃๅ‘Š้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +## ๅŒฏๅ…ฅ `Field` { #import-field } + +้ฆ–ๅ…ˆ๏ผŒไฝ ้œ€่ฆๅŒฏๅ…ฅๅฎƒ๏ผš + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + + +/// warning + +่ซ‹ๆณจๆ„๏ผŒ`Field` ๆ˜ฏ็›ดๆŽฅๅพž `pydantic` ๅŒฏๅ…ฅ็š„๏ผŒไธๅƒๅ…ถไป–๏ผˆๅฆ‚ `Query`ใ€`Path`ใ€`Body` ็ญ‰๏ผ‰ๆ˜ฏๅพž `fastapi` ๅŒฏๅ…ฅใ€‚ + +/// + +## ๅฎฃๅ‘Šๆจกๅž‹ๅฑฌๆ€ง { #declare-model-attributes } + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅœจๆจกๅž‹ๅฑฌๆ€งไธŠไฝฟ็”จ `Field`๏ผš + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} + +`Field` ็š„็”จๆณ•่ˆ‡ `Query`ใ€`Path`ใ€`Body` ็›ธๅŒ๏ผŒๆ“ๆœ‰็›ธๅŒ็š„ๅƒๆ•ธ็ญ‰ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅฏฆ้š›ไธŠ๏ผŒไฝ ๆŽฅไธ‹ไพ†ๆœƒ็œ‹ๅˆฐ็š„ `Query`ใ€`Path` ็ญ‰๏ผŒๆœƒๅปบ็ซ‹ๅ…ฑๅŒ็ˆถ้กžๅˆฅ `Param` ็š„ๅญ้กžๅˆฅ็‰ฉไปถ๏ผŒ่€Œ `Param` ๆœฌ่บซๆ˜ฏ Pydantic ็š„ `FieldInfo` ้กžๅˆฅ็š„ๅญ้กžๅˆฅใ€‚ + +่€Œ Pydantic ็š„ `Field` ไนŸๆœƒๅ›žๅ‚ณไธ€ๅ€‹ `FieldInfo` ็š„ๅฏฆไพ‹ใ€‚ + +`Body` ไนŸๆœƒ็›ดๆŽฅๅ›žๅ‚ณ `FieldInfo` ๅญ้กžๅˆฅ็š„็‰ฉไปถใ€‚็จๅพŒไฝ ๆœƒ็œ‹ๅˆฐ้‚„ๆœ‰ๅ…ถไป–้กžๅˆฅๆ˜ฏ `Body` ้กžๅˆฅ็š„ๅญ้กžๅˆฅใ€‚ + +่จ˜ๅพ—๏ผŒ็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path` ็ญ‰ๆ™‚๏ผŒๅฎƒๅ€‘ๅ…ถๅฏฆๆ˜ฏๅ›žๅ‚ณ็‰นๆฎŠ้กžๅˆฅ็š„ๅ‡ฝๅผใ€‚ + +/// + +/// tip + +ๆณจๆ„๏ผŒๆฏๅ€‹ๅธถๆœ‰ๅž‹ๅˆฅใ€้ ่จญๅ€ผ่ˆ‡ `Field` ็š„ๆจกๅž‹ๅฑฌๆ€ง๏ผŒๅ…ถ็ตๆง‹ๅ’Œใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็š„ๅƒๆ•ธ็›ธๅŒ๏ผŒๅชๆ˜ฏๆŠŠ `Path`ใ€`Query`ใ€`Body` ๆ›ๆˆไบ† `Field`ใ€‚ + +/// + +## ๅŠ ๅ…ฅ้กๅค–่ณ‡่จŠ { #add-extra-information } + +ไฝ ๅฏไปฅๅœจ `Field`ใ€`Query`ใ€`Body` ็ญ‰ไธญๅฎฃๅ‘Š้กๅค–่ณ‡่จŠใ€‚้€™ไบ›่ณ‡่จŠๆœƒ่ขซๅŒ…ๅซๅœจ็”ข็”Ÿ็š„ JSON Schema ไธญใ€‚ + +ไฝ ๆœƒๅœจๅพŒ็บŒๆ–‡ไปถไธญๅญธๅˆฐๆ›ดๅคš้—œๆ–ผๅŠ ๅ…ฅ้กๅค–่ณ‡่จŠ็š„ๅ…งๅฎน๏ผŒ็‰นๅˆฅๆ˜ฏๅœจๅฎฃๅ‘Š็ฏ„ไพ‹ๆ™‚ใ€‚ + +/// warning + +ๅ‚ณๅ…ฅ `Field` ็š„้กๅค–้ตไนŸๆœƒๅ‡บ็พๅœจไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๆ‰€็”ข็”Ÿ็š„ OpenAPI schema ไธญใ€‚ +็”ฑๆ–ผ้€™ไบ›้ตไธไธ€ๅฎšๅฑฌๆ–ผ OpenAPI ่ฆๆ ผ็š„ไธ€้ƒจๅˆ†๏ผŒไธ€ไบ› OpenAPI ๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ [OpenAPI ้ฉ—่ญ‰ๅ™จ](https://validator.swagger.io/)๏ผ‰ๅฏ่ƒฝ็„กๆณ•่™•็†ไฝ ็”ข็”Ÿ็š„ schemaใ€‚ + +/// + +## ๅ›ž้กง { #recap } + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ `Field` ็‚บๆจกๅž‹ๅฑฌๆ€งๅฎฃๅ‘Š้กๅค–็š„้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ้กๅค–็š„้—œ้ตๅญ—ๅผ•ๆ•ธไพ†ๅ‚ณ้ž้กๅค–็š„ JSON Schema ไธญ็นผ่ณ‡ๆ–™ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/body-multiple-params.md b/docs/zh-hant/docs/tutorial/body-multiple-params.md new file mode 100644 index 0000000000..1c334f51f5 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/body-multiple-params.md @@ -0,0 +1,165 @@ +# Body - ๅคšๅ€‹ๅƒๆ•ธ { #body-multiple-parameters } + +็พๅœจๆˆ‘ๅ€‘ๅทฒ็ถ“็Ÿฅ้“ๅฆ‚ไฝ•ไฝฟ็”จ `Path` ่ˆ‡ `Query`๏ผŒๆŽฅไธ‹ไพ†็œ‹็œ‹ๆ›ด้€ฒ้šŽ็š„่ซ‹ๆฑ‚ไธป้ซ”๏ผˆrequest body๏ผ‰ๅฎฃๅ‘Š็”จๆณ•ใ€‚ + +## ๆทท็”จ `Path`ใ€`Query` ่ˆ‡ Body ๅƒๆ•ธ { #mix-path-query-and-body-parameters } + +้ฆ–ๅ…ˆ๏ผŒ็•ถ็„ถไฝ ๅฏไปฅ่‡ช็”ฑๆทท็”จ `Path`ใ€`Query` ่ˆ‡่ซ‹ๆฑ‚ Body ๅƒๆ•ธ็š„ๅฎฃๅ‘Š๏ผŒ**FastAPI** ๆœƒ็Ÿฅ้“่ฉฒๆ€Ž้บผๅšใ€‚ + +ไฝ ไนŸๅฏไปฅๅฐ‡ Body ๅƒๆ•ธๅฎฃๅ‘Š็‚บๅฏ้ธ๏ผŒๆ–นๆณ•ๆ˜ฏๅฐ‡้ ่จญๅ€ผ่จญ็‚บ `None`๏ผš + +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} + +/// note | ๆณจๆ„ + +่ซ‹ๆณจๆ„๏ผŒๅœจๆญคๆƒ…ๆณไธ‹๏ผŒๅพž body ๅ–ๅพ—็š„ `item` ๆ˜ฏๅฏ้ธ็š„๏ผŒๅ› ็‚บๅฎƒ็š„้ ่จญๅ€ผๆ˜ฏ `None`ใ€‚ + +/// + +## ๅคšๅ€‹ Body ๅƒๆ•ธ { #multiple-body-parameters } + +ๅœจๅ‰ไธ€ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ๆœƒๆœŸๆœ›ไธ€ๅ€‹ๅŒ…ๅซ `Item` ๅฑฌๆ€ง็š„ JSON ไธป้ซ”๏ผŒไพ‹ๅฆ‚๏ผš + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +ไฝ†ไฝ ไนŸๅฏไปฅๅฎฃๅ‘Šๅคšๅ€‹ Body ๅƒๆ•ธ๏ผŒไพ‹ๅฆ‚ `item` ่ˆ‡ `user`๏ผš + +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒๆณจๆ„ๅˆฐๅ‡ฝๅผไธญๆœ‰ๅคšๅ€‹ Body ๅƒๆ•ธ๏ผˆๆœ‰ๅ…ฉๅ€‹ๅƒๆ•ธๆ˜ฏ Pydantic ๆจกๅž‹๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒๅฎƒๆœƒไฝฟ็”จๅƒๆ•ธๅ็จฑไฝœ็‚บ body ไธญ็š„้ต๏ผˆๆฌ„ไฝๅ็จฑ๏ผ‰๏ผŒไธฆๆœŸๆœ›ๅฆ‚ไธ‹็š„ไธป้ซ”๏ผš + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +/// note | ๆณจๆ„ + +ๅ„˜็ฎก `item` ็š„ๅฎฃๅ‘Šๆ–นๅผ่ˆ‡ๅ…ˆๅ‰็›ธๅŒ๏ผŒ็พๅœจ้ ๆœŸๅฎƒๆœƒไฝๆ–ผ body ๅ…ง๏ผŒไธ”้ต็‚บ `item`ใ€‚ + +/// + +**FastAPI** ๆœƒ่‡ชๅ‹•ๅพž่ซ‹ๆฑ‚ไธญ้€ฒ่กŒ่ฝ‰ๆ›๏ผŒ่ฎ“ๅƒๆ•ธ `item` ๆ”ถๅˆฐๅฐๆ‡‰ๅ…งๅฎน๏ผŒ`user` ไบฆๅŒใ€‚ + +ๅฎƒๆœƒๅฐ่ค‡ๅˆ่ณ‡ๆ–™้€ฒ่กŒ้ฉ—่ญ‰๏ผŒไธฆๅœจ OpenAPI ็ตๆง‹่ˆ‡่‡ชๅ‹•ๆ–‡ไปถไธญๅฆ‚ๆญคๆ่ฟฐใ€‚ + +## Body ไธญ็š„ๅ–ฎไธ€ๅ€ผ { #singular-values-in-body } + +ๅฐฑๅƒไฝ ๅฏไปฅ็”จ `Query` ่ˆ‡ `Path` ็‚บๆŸฅ่ฉข่ˆ‡่ทฏๅพ‘ๅƒๆ•ธๅฎš็พฉ้กๅค–่ณ‡่จŠไธ€ๆจฃ๏ผŒ**FastAPI** ไนŸๆไพ›ๅฐๆ‡‰็š„ `Body`ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅปถไผธๅ‰่ฟฐๆจกๅž‹๏ผŒไฝ ๅฏไปฅๆฑบๅฎšๅœจ็›ธๅŒ็š„ Body ไธญ๏ผŒ้™คไบ† `item` ่ˆ‡ `user` ๅค–๏ผŒ้‚„่ฆๆœ‰ๅฆไธ€ๅ€‹้ต `importance`ใ€‚ + +ๅฆ‚ๆžœ็›ดๆŽฅ้€™ๆจฃๅฎฃๅ‘Š๏ผŒๅ› ็‚บๅฎƒๆ˜ฏๅ–ฎไธ€ๅ€ผ๏ผŒ**FastAPI** ๆœƒๅฐ‡ๅ…ถ่ฆ–็‚บๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +ไฝ†ไฝ ๅฏไปฅไฝฟ็”จ `Body` ๆŒ‡็คบ **FastAPI** ๅฐ‡ๅ…ถ่ฆ–็‚บๅฆไธ€ๅ€‹ Body ้ต๏ผš + +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒๆœŸๆœ›ๅฆ‚ไธ‹็š„ไธป้ซ”๏ผš + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` + +ๅŒๆจฃๅœฐ๏ผŒๅฎƒๆœƒ้€ฒ่กŒๅž‹ๅˆฅ่ฝ‰ๆ›ใ€้ฉ—่ญ‰ใ€ๆ–‡ไปถๅŒ–็ญ‰ใ€‚ + +## ๅคšๅ€‹ Body ๅƒๆ•ธ่ˆ‡ Query { #multiple-body-params-and-query } + +็•ถ็„ถ๏ผŒไฝ ไนŸๅฏไปฅๅœจไปปไฝ• Body ๅƒๆ•ธไน‹ๅค–๏ผŒ่ฆ–้œ€่ฆๅฎฃๅ‘Š้กๅค–็š„ๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +็”ฑๆ–ผ้ ่จญๆƒ…ๆณไธ‹๏ผŒๅ–ฎไธ€ๅ€ผๆœƒ่ขซ่งฃ่ฎ€็‚บๆŸฅ่ฉขๅƒๆ•ธ๏ผŒไฝ ไธๅฟ…ๆ˜Ž็ขบไฝฟ็”จ `Query`๏ผŒ็›ดๆŽฅ้€™ๆจฃๅฏซๅณๅฏ๏ผš + +```Python +q: str | None = None +``` + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} + +/// info | ๆณจๆ„ + +`Body` ไนŸๅ…ทๆœ‰่ˆ‡ `Query`ใ€`Path` ไปฅๅŠไน‹ๅพŒไฝ ๆœƒ็œ‹ๅˆฐ็š„ๅ…ถไป–ๅทฅๅ…ท็›ธๅŒ็š„้กๅค–้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ๅƒๆ•ธใ€‚ + +/// + +## ๅตŒๅ…ฅๅ–ฎไธ€ Body ๅƒๆ•ธ { #embed-a-single-body-parameter } + +ๅ‡่จญไฝ ๅชๆœ‰ไธ€ๅ€‹ไพ†่‡ช Pydantic ๆจกๅž‹ `Item` ็š„ๅ–ฎไธ€ `item` Body ๅƒๆ•ธใ€‚ + +้ ่จญๆƒ…ๆณไธ‹๏ผŒ**FastAPI** ๆœƒ็›ดๆŽฅๆœŸๆœ›่ฉฒๆจกๅž‹็š„ๅ…งๅฎนไฝœ็‚บ่ซ‹ๆฑ‚ไธป้ซ”ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ๆƒณ่ฎ“ๅฎƒๅƒๅฎฃๅ‘Šๅคšๅ€‹ Body ๅƒๆ•ธๆ™‚้‚ฃๆจฃ๏ผŒๆœŸๆœ›ไธ€ๅ€‹ๅธถๆœ‰ `item` ้ตใ€ๅ…ถๅ…งๅซๆจกๅž‹ๅ…งๅฎน็š„ JSON๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Body` ็š„็‰นๆฎŠๅƒๆ•ธ `embed`๏ผš + +```Python +item: Item = Body(embed=True) +``` + +ๅฆ‚ไธ‹๏ผš + +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + +ๅœจๆญคๆƒ…ๆณไธ‹ **FastAPI** ๆœƒๆœŸๆœ›ๅฆ‚ไธ‹็š„ไธป้ซ”๏ผš + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +่€Œไธๆ˜ฏ๏ผš + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## ๅฐ็ต { #recap } + +ๅณไพฟไธ€ๅ€‹่ซ‹ๆฑ‚ๅช่ƒฝๆœ‰ๅ–ฎไธ€ไธป้ซ”๏ผŒไฝ ไปๅฏๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญๅฎฃๅ‘Šๅคšๅ€‹ Body ๅƒๆ•ธใ€‚ + +ไฝ† **FastAPI** ๆœƒ่™•็†ๅฅฝ้€™ไธ€ๅˆ‡๏ผŒๅœจไฝ ็š„ๅ‡ฝๅผไธญๆไพ›ๆญฃ็ขบ็š„่ณ‡ๆ–™๏ผŒไธฆๅœจ่ทฏๅพ‘ๆ“ไฝœไธญ้ฉ—่ญ‰่ˆ‡ๆ–‡ไปถๅŒ–ๆญฃ็ขบ็š„็ตๆง‹ใ€‚ + +ไฝ ไนŸๅฏไปฅๅฐ‡ๅ–ฎไธ€ๅ€ผๅฎฃๅ‘Š็‚บ Body ็š„ไธ€้ƒจๅˆ†ไพ†ๆŽฅๆ”ถใ€‚ + +ๅณไฝฟๅชๅฎฃๅ‘Šไบ†ไธ€ๅ€‹ๅƒๆ•ธ๏ผŒไนŸๅฏไปฅๆŒ‡็คบ **FastAPI** ๅฐ‡ Body ไปฅๆŸๅ€‹้ต้€ฒ่กŒๅตŒๅ…ฅใ€‚ diff --git a/docs/zh-hant/docs/tutorial/body-nested-models.md b/docs/zh-hant/docs/tutorial/body-nested-models.md new file mode 100644 index 0000000000..df4aff6972 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/body-nested-models.md @@ -0,0 +1,220 @@ +# Body - ๅทข็‹€ๆจกๅž‹ { #body-nested-models } + +ไฝฟ็”จ **FastAPI**๏ผŒไฝ ๅฏไปฅๅฎš็พฉใ€้ฉ—่ญ‰ใ€ๆ–‡ไปถๅŒ–๏ผŒไธฆไฝฟ็”จไปปๆ„ๆทฑๅบฆ็š„ๅทข็‹€ๆจกๅž‹๏ผˆๆ„Ÿ่ฌ Pydantic๏ผ‰ใ€‚ + +## ๅˆ—่กจๆฌ„ไฝ { #list-fields } + +ไฝ ๅฏไปฅๅฐ‡ๅฑฌๆ€งๅฎš็พฉ็‚บๆŸๅ€‹ๅญๅž‹ๅˆฅใ€‚ไพ‹ๅฆ‚๏ผŒPython ็š„ `list`๏ผš + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +้€™ๆœƒ่ฎ“ `tags` ๆˆ็‚บไธ€ๅ€‹ๅˆ—่กจ๏ผŒๅ„˜็ฎกๅฐšๆœชๅฎฃๅ‘Šๅˆ—่กจๅ…ƒ็ด ็š„ๅž‹ๅˆฅใ€‚ + +## ๅ…ทๆœ‰ๅž‹ๅˆฅๅƒๆ•ธ็š„ๅˆ—่กจๆฌ„ไฝ { #list-fields-with-type-parameter } + +ไธ้Ž๏ผŒPython ๆœ‰ไธ€็จฎๅฐˆ้–€็š„ๆ–นๅผไพ†ๅฎฃๅ‘Šๅ…ทๆœ‰ๅ…ง้ƒจๅž‹ๅˆฅ๏ผˆใ€Œๅž‹ๅˆฅๅƒๆ•ธใ€๏ผ‰็š„ๅˆ—่กจ๏ผš + +### ๅฎฃๅ‘Šๅธถๆœ‰ๅž‹ๅˆฅๅƒๆ•ธ็š„ `list` { #declare-a-list-with-a-type-parameter } + +่ฆๅฎฃๅ‘Šๅ…ทๆœ‰ๅž‹ๅˆฅๅƒๆ•ธ๏ผˆๅ…ง้ƒจๅž‹ๅˆฅ๏ผ‰็š„ๅž‹ๅˆฅ๏ผŒไพ‹ๅฆ‚ `list`ใ€`dict`ใ€`tuple`๏ผŒไฝฟ็”จๆ–นๆ‹ฌ่™Ÿ `[` ่ˆ‡ `]` ๅ‚ณๅ…ฅๅ…ง้ƒจๅž‹ๅˆฅไฝœ็‚บใ€Œๅž‹ๅˆฅๅƒๆ•ธใ€๏ผš + +```Python +my_list: list[str] +``` + +ไปฅไธŠ้ƒฝๆ˜ฏๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๅฎฃๅ‘Š่ชžๆณ•ใ€‚ + +ๅฐๆ–ผๅ…ทๆœ‰ๅ…ง้ƒจๅž‹ๅˆฅ็š„ๆจกๅž‹ๅฑฌๆ€ง๏ผŒไนŸไฝฟ็”จ็›ธๅŒ็š„ๆจ™ๆบ–่ชžๆณ•ใ€‚ + +ๅ› ๆญค๏ผŒๅœจๆˆ‘ๅ€‘็š„็ฏ„ไพ‹ไธญ๏ผŒๅฏไปฅ่ฎ“ `tags` ๆ˜Ž็ขบๆˆ็‚บใ€Œๅญ—ไธฒ็š„ๅˆ—่กจใ€๏ผš + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## ้›†ๅˆๅž‹ๅˆฅ { #set-types } + +ไฝ†้€ฒไธ€ๆญฅๆ€่€ƒๅพŒ๏ผŒๆˆ‘ๅ€‘ๆœƒๆ„่ญ˜ๅˆฐ `tags` ไธๆ‡‰่ฉฒ้‡่ฆ†๏ผŒๆ‡‰่ฉฒๆ˜ฏๅ”ฏไธ€็š„ๅญ—ไธฒใ€‚ + +่€Œ Python ๆœ‰ไธ€็จฎ็”จๆ–ผๅ”ฏไธ€ๅ…ƒ็ด ้›†ๅˆ็š„็‰นๆฎŠ่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผš`set`ใ€‚ + +ๅ› ๆญคๆˆ‘ๅ€‘ๅฏไปฅๅฐ‡ `tags` ๅฎฃๅ‘Š็‚บๅญ—ไธฒ็š„ `set`๏ผš + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +้€™ๆจฃไธ€ไพ†๏ผŒๅณไฝฟๆ”ถๅˆฐๅŒ…ๅซ้‡่ฆ†่ณ‡ๆ–™็š„่ซ‹ๆฑ‚๏ผŒไนŸๆœƒ่ขซ่ฝ‰ๆ›็‚บ็”ฑๅ”ฏไธ€ๅ…ƒ็ด ็ต„ๆˆ็š„ `set`ใ€‚ + +ไน‹ๅพŒๅช่ฆ่ผธๅ‡บ่ฉฒ่ณ‡ๆ–™๏ผŒๅณไฝฟไพ†ๆบๆœ‰้‡่ฆ†๏ผŒไนŸๆœƒไปฅๅ”ฏไธ€ๅ…ƒ็ด ็š„ `set` ่ผธๅ‡บใ€‚ + +ไธฆไธ”ไนŸๆœƒๅœจ่จป่งฃ๏ผๆ–‡ไปถไธญ็›ธๆ‡‰ๆจ™็คบใ€‚ + +## ๅทข็‹€ๆจกๅž‹ { #nested-models } + +ๆฏๅ€‹ Pydantic ๆจกๅž‹็š„ๅฑฌๆ€ง้ƒฝๆœ‰ๅž‹ๅˆฅใ€‚ + +่€Œ่ฉฒๅž‹ๅˆฅๆœฌ่บซไนŸๅฏไปฅๆ˜ฏๅฆไธ€ๅ€‹ Pydantic ๆจกๅž‹ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘Šๅ…ทๆœ‰็‰นๅฎšๅฑฌๆ€งๅ็จฑใ€ๅž‹ๅˆฅ่ˆ‡้ฉ—่ญ‰็š„ๆทฑๅบฆๅทข็‹€ JSONใ€Œ็‰ฉไปถใ€ใ€‚ + +่€Œไธ”ๅฏไปฅไปปๆ„ๆทฑๅบฆๅทข็‹€ใ€‚ + +### ๅฎš็พฉๅญๆจกๅž‹ { #define-a-submodel } + +ไพ‹ๅฆ‚๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅฎš็พฉไธ€ๅ€‹ `Image` ๆจกๅž‹๏ผš + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### ๅฐ‡ๅญๆจกๅž‹ไฝœ็‚บๅž‹ๅˆฅไฝฟ็”จ { #use-the-submodel-as-a-type } + +็„ถๅพŒๆŠŠๅฎƒไฝœ็‚บๆŸๅ€‹ๅฑฌๆ€ง็š„ๅž‹ๅˆฅไฝฟ็”จ๏ผš + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +้€™่กจ็คบ **FastAPI** ๆœƒๆœŸๆœ›ไธ€ๅ€‹้กžไผผๅฆ‚ไธ‹็š„ๆœฌๆ–‡๏ผš + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +ๅช้œ€้€ฒ่กŒไธŠ่ฟฐๅฎฃๅ‘Š๏ผŒไฝฟ็”จ **FastAPI** ไฝ ๅฐฑ่ƒฝ็ฒๅพ—๏ผš + +- ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผˆ่‡ชๅ‹•ๅฎŒๆˆ็ญ‰๏ผ‰๏ผŒๅณไฝฟๆ˜ฏๅทข็‹€ๆจกๅž‹ +- ่ณ‡ๆ–™่ฝ‰ๆ› +- ่ณ‡ๆ–™้ฉ—่ญ‰ +- ่‡ชๅ‹•็”ข็”Ÿๆ–‡ไปถ + +## ็‰นๆฎŠๅž‹ๅˆฅ่ˆ‡้ฉ—่ญ‰ { #special-types-and-validation } + +้™คไบ† `str`ใ€`int`ใ€`float` ็ญ‰ไธ€่ˆฌ็š„ๅ–ฎไธ€ๅž‹ๅˆฅๅค–๏ผŒไฝ ไนŸๅฏไปฅไฝฟ็”จ็นผๆ‰ฟ่‡ช `str` ็š„ๆ›ด่ค‡้›œๅ–ฎไธ€ๅž‹ๅˆฅใ€‚ + +่‹ฅ่ฆๆŸฅ็œ‹ๆ‰€ๆœ‰ๅฏ็”จ้ธ้ …๏ผŒ่ซ‹ๅƒ้–ฑ Pydantic ็š„ๅž‹ๅˆฅ็ธฝ่ฆฝใ€‚ไฝ ๆœƒๅœจไธ‹ไธ€็ซ ็œ‹ๅˆฐไธ€ไบ›็ฏ„ไพ‹ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅœจ `Image` ๆจกๅž‹ไธญๆœ‰ไธ€ๅ€‹ `url` ๆฌ„ไฝ๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅฐ‡ๅ…ถๅฎฃๅ‘Š็‚บ Pydantic ็š„ `HttpUrl`๏ผŒ่€Œไธๆ˜ฏ `str`๏ผš + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +่ฉฒๅญ—ไธฒๆœƒ่ขซๆชขๆŸฅๆ˜ฏๅฆ็‚บๆœ‰ๆ•ˆ็š„ URL๏ผŒไธฆๅœจ JSON Schema / OpenAPI ไธญ็›ธๆ‡‰่จป่จ˜ใ€‚ + +## ๅ…ทๆœ‰ๅญๆจกๅž‹ๅˆ—่กจ็š„ๅฑฌๆ€ง { #attributes-with-lists-of-submodels } + +ไฝ ไนŸๅฏไปฅๅฐ‡ Pydantic ๆจกๅž‹ไฝœ็‚บ `list`ใ€`set` ็ญ‰็š„ๅญๅž‹ๅˆฅไฝฟ็”จ๏ผš + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +้€™ๆœƒๆœŸๆœ›๏ผˆไธฆ้€ฒ่กŒ่ฝ‰ๆ›ใ€้ฉ—่ญ‰ใ€ๆ–‡ไปถๅŒ–็ญ‰๏ผ‰ๅฆ‚ไธ‹็š„ JSON ๆœฌๆ–‡๏ผš + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// info + +ๆณจๆ„ `images` ้ต็พๅœจๆ˜ฏไธ€ๅ€‹็”ฑ image ็‰ฉไปถ็ต„ๆˆ็š„ๅˆ—่กจใ€‚ + +/// + +## ๆทฑๅบฆๅทข็‹€ๆจกๅž‹ { #deeply-nested-models } + +ไฝ ๅฏไปฅๅฎš็พฉไปปๆ„ๆทฑๅบฆ็š„ๅทข็‹€ๆจกๅž‹๏ผš + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// info + +่ซ‹ๆณจๆ„๏ผŒ`Offer` ๅ…ทๆœ‰ไธ€ๅ€‹ `Item` ็š„ๅˆ—่กจ๏ผŒ่€Œๆฏๅ€‹ `Item` ๅˆๆœ‰ไธ€ๅ€‹ๅฏ้ธ็š„ `Image` ๅˆ—่กจใ€‚ + +/// + +## ็ด”ๅˆ—่กจ็š„ๆœฌๆ–‡ { #bodies-of-pure-lists } + +ๅฆ‚ๆžœไฝ ๆœŸๆœ›็š„ JSON ๆœฌๆ–‡้ ‚ๅฑคๅ€ผๆ˜ฏไธ€ๅ€‹ JSON `array`๏ผˆPython ็š„ `list`๏ผ‰๏ผŒๅฏไปฅๅƒๅœจ Pydantic ๆจกๅž‹ไธญ้‚ฃๆจฃ๏ผŒ็›ดๆŽฅๅœจๅ‡ฝๅผๅƒๆ•ธไธŠๅฎฃๅ‘Šๅ…ถๅž‹ๅˆฅ๏ผš + +```Python +images: list[Image] +``` + +ๅฆ‚ไธ‹ๆ‰€็คบ๏ผš + +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} + +## ้šจ่™•ๅฏๅพ—็š„็ทจ่ผฏๅ™จๆ”ฏๆด { #editor-support-everywhere } + +ไฝ ๅฐ‡ๅœจๅ„่™•็ฒๅพ—็ทจ่ผฏๅ™จๆ”ฏๆดใ€‚ + +ๅณไฝฟๆ˜ฏๅˆ—่กจไธญ็š„้ …็›ฎไนŸไธ€ๆจฃ๏ผš + + + +่‹ฅ็›ดๆŽฅๆ“ไฝœ `dict` ่€Œไธๆ˜ฏไฝฟ็”จ Pydantic ๆจกๅž‹๏ผŒๅฐฑ็„กๆณ•็ฒๅพ—้€™็จฎ็ญ‰็ดš็š„็ทจ่ผฏๅ™จๆ”ฏๆดใ€‚ + +ไฝ†ไฝ ไนŸไธๅฟ…ๆ“”ๅฟƒ๏ผŒๅ‚ณๅ…ฅ็š„ dict ๆœƒ่‡ชๅ‹•่ขซ่ฝ‰ๆ›๏ผŒ่€Œไฝ ็š„่ผธๅ‡บไนŸๆœƒ่‡ชๅ‹•่ฝ‰ๆ›็‚บ JSONใ€‚ + +## ไปปๆ„ `dict` ็š„ๆœฌๆ–‡ { #bodies-of-arbitrary-dicts } + +ไฝ ไนŸๅฏไปฅๅฐ‡ๆœฌๆ–‡ๅฎฃๅ‘Š็‚บไธ€ๅ€‹ `dict`๏ผŒๅ…ถ้ต็‚บๆŸ็จฎๅž‹ๅˆฅใ€ๅ€ผ็‚บๅฆไธ€็จฎๅž‹ๅˆฅใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ็„ก้œ€ไบ‹ๅ…ˆ็Ÿฅ้“ๆœ‰ๆ•ˆ็š„ๆฌ„ไฝ๏ผๅฑฌๆ€งๅ็จฑ็‚บไฝ•๏ผˆไธๅƒไฝฟ็”จ Pydantic ๆจกๅž‹ๆ™‚้œ€่ฆ๏ผ‰ใ€‚ + +้€™ๅœจไฝ ๆƒณๆŽฅๆ”ถๅฐšๆœช้ ็Ÿฅ็š„้ตๆ™‚ๅพˆๆœ‰็”จใ€‚ + +--- + +ๅฆไธ€ๅ€‹ๅฏฆ็”จๆƒ…ๅขƒๆ˜ฏ็•ถไฝ ๅธŒๆœ›้ตๆ˜ฏๅ…ถไป–ๅž‹ๅˆฅ๏ผˆไพ‹ๅฆ‚๏ผŒ`int`๏ผ‰ๆ™‚ใ€‚ + +้€™ๆญฃๆ˜ฏๆˆ‘ๅ€‘ๅœจๆญค่ฆ็คบ็ฏ„็š„ใ€‚ + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒๅช่ฆๆ˜ฏๆ“ๆœ‰ `int` ้ตไธ”ๅฐๆ‡‰ `float` ๅ€ผ็š„ `dict` ้ƒฝๆœƒ่ขซๆŽฅๅ—๏ผš + +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} + +/// tip + +่ซ‹่จ˜ไฝ๏ผŒJSON ๅชๆ”ฏๆด `str` ไฝœ็‚บ้ตใ€‚ + +ไฝ† Pydantic ๅ…ทๆœ‰่‡ชๅ‹•่ณ‡ๆ–™่ฝ‰ๆ›ใ€‚ + +้€™่กจ็คบๅณไฝฟไฝ ็š„ API ็”จๆˆถ็ซฏๅช่ƒฝไปฅๅญ—ไธฒไฝœ็‚บ้ต๏ผŒๅช่ฆ้€™ไบ›ๅญ—ไธฒๆ˜ฏ็ด”ๆ•ดๆ•ธ๏ผŒPydantic ๆœƒ่‡ชๅ‹•่ฝ‰ๆ›ไธฆ้ฉ—่ญ‰ๅฎƒๅ€‘ใ€‚ + +่€Œไฝ ไฝœ็‚บ `weights` ๆ‰€ๆŽฅๆ”ถ็š„ `dict`๏ผŒๅฏฆ้š›ไธŠๆœƒๆ“ๆœ‰ `int` ้ต่ˆ‡ `float` ๅ€ผใ€‚ + +/// + +## ็ธฝ็ต { #recap } + +ไฝฟ็”จ **FastAPI**๏ผŒไฝ ๅœจไฟๆŒ็จ‹ๅผ็ขผ็ฐกๆฝ”ๅ„ช้›…็š„ๅŒๆ™‚๏ผŒไบฆๅฏๆ“ๆœ‰ Pydantic ๆจกๅž‹ๆ‰€ๆไพ›็š„้ซ˜ๅบฆๅฝˆๆ€งใ€‚ + +ๅŒๆ™‚้‚„ๅ…ทๅ‚™ไปฅไธ‹ๅ„ช้ปž๏ผš + +- ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผˆๅˆฐ่™•้ƒฝๆœ‰่‡ชๅ‹•ๅฎŒๆˆ๏ผ๏ผ‰ +- ่ณ‡ๆ–™่ฝ‰ๆ›๏ผˆไบฆๅณ parsing๏ผserialization๏ผ‰ +- ่ณ‡ๆ–™้ฉ—่ญ‰ +- ็ตๆง‹ๆ่ฟฐ๏ผˆSchema๏ผ‰ๆ–‡ไปถ +- ่‡ชๅ‹•็”ข็”Ÿๆ–‡ไปถ diff --git a/docs/zh-hant/docs/tutorial/body-updates.md b/docs/zh-hant/docs/tutorial/body-updates.md new file mode 100644 index 0000000000..a309e3522c --- /dev/null +++ b/docs/zh-hant/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Body - ๆ›ดๆ–ฐ { #body-updates } + +## ไฝฟ็”จ `PUT` ๅ–ไปฃๅผๆ›ดๆ–ฐ { #update-replacing-with-put } + +่ฆๆ›ดๆ–ฐไธ€ๅ€‹้ …็›ฎ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ HTTP `PUT` ๆ“ไฝœใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `jsonable_encoder` ๅฐ‡่ผธๅ…ฅ่ณ‡ๆ–™่ฝ‰ๆ›็‚บๅฏๅ„ฒๅญ˜็‚บ JSON ็š„่ณ‡ๆ–™๏ผˆไพ‹ๅฆ‚็”จๆ–ผ NoSQL ่ณ‡ๆ–™ๅบซ๏ผ‰ใ€‚ไพ‹ๅฆ‚ๆŠŠ `datetime` ่ฝ‰ๆˆ `str`ใ€‚ + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT` ็”จๆ–ผๆŽฅๆ”ถๆ‡‰่ฉฒๅ–ไปฃ็พๆœ‰่ณ‡ๆ–™็š„่ณ‡ๆ–™ใ€‚ + +### ้—œๆ–ผๅ–ไปฃ็š„่ญฆๅ‘Š { #warning-about-replacing } + +้€™่กจ็คบ๏ผŒๅฆ‚ๆžœไฝ ๆƒณ็”จ `PUT` ไธฆๅœจ body ไธญๅŒ…ๅซไปฅไธ‹ๅ…งๅฎนไพ†ๆ›ดๆ–ฐ้ …็›ฎ `bar`๏ผš + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +็”ฑๆ–ผ้€™่ฃกๆฒ’ๆœ‰ๅŒ…ๅซๅทฒๅ„ฒๅญ˜็š„ๅฑฌๆ€ง `"tax": 20.2`๏ผŒ่ผธๅ…ฅ็š„ๆจกๅž‹ๆœƒๆŽก็”จ้ ่จญๅ€ผ `"tax": 10.5`ใ€‚ + +ๆœ€็ต‚่ณ‡ๆ–™ๆœƒไปฅ้€™ๅ€‹ใ€Œๆ–ฐ็š„ใ€ `tax` ๅ€ผ `10.5` ่ขซๅ„ฒๅญ˜ใ€‚ + +## ไฝฟ็”จ `PATCH` ้€ฒ่กŒ้ƒจๅˆ†ๆ›ดๆ–ฐ { #partial-updates-with-patch } + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ HTTP `PATCH` ๆ“ไฝœไพ†้€ฒ่กŒ*้ƒจๅˆ†*ๆ›ดๆ–ฐใ€‚ + +้€™่กจ็คบไฝ ๅช้œ€ๅ‚ณ้€ๆƒณ่ฆๆ›ดๆ–ฐ็š„่ณ‡ๆ–™๏ผŒๅ…ถ้ค˜ไฟๆŒไธ่ฎŠใ€‚ + +/// note | ๆณจๆ„ + +`PATCH` ็›ธ่ผƒๆ–ผ `PUT` ่ผƒๅฐ‘่ขซไฝฟ็”จใ€ไนŸ่ผƒไธ็‚บไบบ็Ÿฅใ€‚ + +่จฑๅคšๅœ˜้šŠ็”š่‡ณๅœจ้ƒจๅˆ†ๆ›ดๆ–ฐๆ™‚ไนŸๅช็”จ `PUT`ใ€‚ + +ไฝ ๅฏไปฅไพ้œ€ๆฑ‚่‡ช็”ฑ้ธ็”จ๏ผŒ**FastAPI** ไธๆœƒๅผทๅˆถ่ฆ็ฏ„ใ€‚ + +ไฝ†ๆœฌๆŒ‡ๅ—ๆœƒๅคง่‡ด็คบ็ฏ„ๅฎƒๅ€‘ๅ„่‡ช็š„่จญ่จˆ็”จๆณ•ใ€‚ + +/// + +### ไฝฟ็”จ Pydantic ็š„ `exclude_unset` ๅƒๆ•ธ { #using-pydantics-exclude-unset-parameter } + +ๅฆ‚ๆžœ่ฆๆŽฅๆ”ถ้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒๅœจ Pydantic ๆจกๅž‹็š„ `.model_dump()` ไธญไฝฟ็”จ `exclude_unset` ๅƒๆ•ธ้žๅธธๅฏฆ็”จใ€‚ + +ไพ‹ๅฆ‚ `item.model_dump(exclude_unset=True)`ใ€‚ + +้€™ๆœƒ็”ข็”Ÿไธ€ๅ€‹ๅชๅŒ…ๅซๅปบ็ซ‹ `item` ๆจกๅž‹ๆ™‚ๅฏฆ้š›่จญๅฎš้Žไน‹ๆฌ„ไฝ็š„ `dict`๏ผŒไธๅซ้ ่จญๅ€ผใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅ็”จๅฎƒไพ†็”ŸๆˆๅชๅŒ…ๅซๅฏฆ้š›่จญๅฎš๏ผˆ่ซ‹ๆฑ‚ไธญๅ‚ณไพ†๏ผ‰็š„่ณ‡ๆ–™ไน‹ `dict`๏ผŒ็œ็•ฅ้ ่จญๅ€ผ๏ผš + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### ไฝฟ็”จ Pydantic ็š„ `update` ๅƒๆ•ธ { #using-pydantics-update-parameter } + +ๆŽฅ่‘—๏ผŒไฝ ๅฏไปฅ็”จ `.model_copy()` ๅปบ็ซ‹็พๆœ‰ๆจกๅž‹็š„ๅ‰ฏๆœฌ๏ผŒไธฆๅ‚ณๅ…ฅๅซๆœ‰่ฆๆ›ดๆ–ฐ่ณ‡ๆ–™ไน‹ `dict` ๅˆฐ `update` ๅƒๆ•ธใ€‚ + +ไพ‹ๅฆ‚ `stored_item_model.model_copy(update=update_data)`๏ผš + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### ้ƒจๅˆ†ๆ›ดๆ–ฐๆ‘˜่ฆ { #partial-updates-recap } + +็ธฝ็ตไธ€ไธ‹๏ผŒ่‹ฅ่ฆๅฅ—็”จ้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒไฝ ๅฏไปฅ๏ผš + +*๏ผˆๅฏ้ธ๏ผ‰ไฝฟ็”จ `PATCH` ๅ–ไปฃ `PUT`ใ€‚ +* ๅ–ๅ›žๅทฒๅ„ฒๅญ˜็š„่ณ‡ๆ–™ใ€‚ +* ๅฐ‡่ฉฒ่ณ‡ๆ–™ๆ”พๅ…ฅไธ€ๅ€‹ Pydantic ๆจกๅž‹ใ€‚ +* ๅพž่ผธๅ…ฅๆจกๅž‹็”ข็”Ÿไธ€ๅ€‹ไธๅซ้ ่จญๅ€ผ็š„ `dict`๏ผˆไฝฟ็”จ `exclude_unset`๏ผ‰ใ€‚ + * ๅฆ‚ๆญคๅณๅฏๅชๆ›ดๆ–ฐไฝฟ็”จ่€…ๅฏฆ้š›่จญๅฎš็š„ๅ€ผ๏ผŒ่€Œไธๆœƒไปฅๆจกๅž‹็š„้ ่จญๅ€ผ่ฆ†ๅฏซๅทฒๅ„ฒๅญ˜็š„ๅ€ผใ€‚ +* ๅปบ็ซ‹ๅทฒๅ„ฒๅญ˜ๆจกๅž‹็š„ๅ‰ฏๆœฌ๏ผŒไธฆไปฅๆ”ถๅˆฐ็š„้ƒจๅˆ†ๆ›ดๆ–ฐๅ€ผๆ›ดๆ–ฐๅ…ถๅฑฌๆ€ง๏ผˆไฝฟ็”จ `update` ๅƒๆ•ธ๏ผ‰ใ€‚ +* ๅฐ‡่ฉฒๅ‰ฏๆœฌๆจกๅž‹่ฝ‰ๆˆๅฏๅ„ฒๅญ˜ๅˆฐ่ณ‡ๆ–™ๅบซ็š„ๅž‹ๅˆฅ๏ผˆไพ‹ๅฆ‚ไฝฟ็”จ `jsonable_encoder`๏ผ‰ใ€‚ + * ้€™่ˆ‡ๅ†ๆฌกไฝฟ็”จๆจกๅž‹็š„ `.model_dump()` ้กžไผผ๏ผŒไฝ†ๅฎƒๆœƒ็ขบไฟ๏ผˆไธฆ่ฝ‰ๆ›๏ผ‰ๆ‰€ๆœ‰ๅ€ผ็‚บๅฏ่ฝ‰็‚บ JSON ็š„่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผŒไพ‹ๅฆ‚ๆŠŠ `datetime` ่ฝ‰็‚บ `str`ใ€‚ +* ๅฐ‡่ณ‡ๆ–™ๅ„ฒๅญ˜ๅˆฐ่ณ‡ๆ–™ๅบซใ€‚ +* ๅ›žๅ‚ณๆ›ดๆ–ฐๅพŒ็š„ๆจกๅž‹ใ€‚ + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | ๆ็คบ + +ๅ…ถๅฏฆไฝ ไนŸๅฏไปฅๅœจ HTTP `PUT` ๆ“ไฝœไธญไฝฟ็”จๅŒไธ€ๅฅ—ๆŠ€ๅทงใ€‚ + +ไฝ†ๆญค่™•็คบไพ‹ไฝฟ็”จ `PATCH`๏ผŒๅ› ็‚บๅฎƒๆญฃๆ˜ฏ็‚บ้€™้กžๆƒ…ๅขƒ่จญ่จˆ็š„ใ€‚ + +/// + +/// note | ๆณจๆ„ + +่ซ‹ๆณจๆ„๏ผŒ่ผธๅ…ฅ็š„ๆจกๅž‹ไพ็„ถๆœƒ่ขซ้ฉ—่ญ‰ใ€‚ + +ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๅธŒๆœ›ๆŽฅๆ”ถๅฏไปฅ็œ็•ฅๆ‰€ๆœ‰ๅฑฌๆ€ง็š„้ƒจๅˆ†ๆ›ดๆ–ฐ๏ผŒไฝ ้œ€่ฆไธ€ๅ€‹ๆ‰€ๆœ‰ๅฑฌๆ€ง็š†็‚บๅฏ้ธ๏ผˆๅ…ท้ ่จญๅ€ผๆˆ–็‚บ `None`๏ผ‰็š„ๆจกๅž‹ใ€‚ + +็‚บไบ†ๅ€ๅˆ†็”จๆ–ผๆ›ดๆ–ฐ๏ผˆๅ…จ้ƒจๅฏ้ธ๏ผ‰่ˆ‡็”จๆ–ผๅปบ็ซ‹๏ผˆๆฌ„ไฝ็‚บๅฟ…ๅกซ๏ผ‰็š„ๆจกๅž‹๏ผŒไฝ ๅฏไปฅๅƒ่€ƒ [้กๅค–ๆจกๅž‹](extra-models.md){.internal-link target=_blank} ไธญ็š„ๅšๆณ•ใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/body.md b/docs/zh-hant/docs/tutorial/body.md new file mode 100644 index 0000000000..bddcbbf434 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/body.md @@ -0,0 +1,164 @@ +# ่ซ‹ๆฑ‚ๆœฌๆ–‡ { #request-body } + +็•ถไฝ ้œ€่ฆๅพž็”จๆˆถ็ซฏ๏ผˆไพ‹ๅฆ‚็€่ฆฝๅ™จ๏ผ‰ๅฐ‡่ณ‡ๆ–™ๅ‚ณ้€ๅˆฐไฝ ็š„ API ๆ™‚๏ผŒๆœƒๆŠŠๅฎƒไฝœ็‚บ**่ซ‹ๆฑ‚ๆœฌๆ–‡**้€ๅ‡บใ€‚ + +**่ซ‹ๆฑ‚**ๆœฌๆ–‡ๆ˜ฏ็”จๆˆถ็ซฏๅ‚ณ็ตฆไฝ ็š„ API ็š„่ณ‡ๆ–™ใ€‚**ๅ›žๆ‡‰**ๆœฌๆ–‡ๆ˜ฏไฝ ็š„ API ๅ‚ณๅ›ž็ตฆ็”จๆˆถ็ซฏ็š„่ณ‡ๆ–™ใ€‚ + +ไฝ ็š„ API ๅนพไนŽ็ธฝๆ˜ฏ้œ€่ฆๅ‚ณๅ›ž**ๅ›žๆ‡‰**ๆœฌๆ–‡ใ€‚ไฝ†็”จๆˆถ็ซฏไธไธ€ๅฎšๆฏๆฌก้ƒฝ่ฆ้€ๅ‡บ**่ซ‹ๆฑ‚ๆœฌๆ–‡**๏ผŒๆœ‰ๆ™‚ๅชๆœƒ่ซ‹ๆฑ‚ๆŸๅ€‹่ทฏๅพ‘๏ผŒๅฏ่ƒฝๅธถไธ€ไบ›ๆŸฅ่ฉขๅƒๆ•ธ๏ผŒไฝ†ไธๆœƒๅ‚ณ้€ๆœฌๆ–‡ใ€‚ + +่ฆๅฎฃๅ‘Š**่ซ‹ๆฑ‚**ๆœฌๆ–‡๏ผŒไฝ ๆœƒไฝฟ็”จ Pydantic ๆจกๅž‹๏ผŒไบซๅ—ๅ…ถๅฎŒๆ•ด็š„ๅŠŸ่ƒฝ่ˆ‡ๅ„ช้ปžใ€‚ + +/// info + +่ฆๅ‚ณ้€่ณ‡ๆ–™๏ผŒๆ‡‰ไฝฟ็”จไธ‹ๅˆ—ๅ…ถไธญไธ€็จฎๆ–นๆณ•๏ผš`POST`๏ผˆๆœ€ๅธธ่ฆ‹๏ผ‰ใ€`PUT`ใ€`DELETE` ๆˆ– `PATCH`ใ€‚ + +ๅœจ่ฆ็ฏ„ไธญ๏ผŒๆ–ผ `GET` ่ซ‹ๆฑ‚ไธญๆ”œๅธถๆœฌๆ–‡็š„่กŒ็‚บๆ˜ฏๆœชๅฎš็พฉ็š„ใ€‚ไธ้Ž๏ผŒFastAPI ไปๆ”ฏๆดๅฎƒ๏ผŒไฝ†ๅƒ…้ฉ็”จๆ–ผ้žๅธธ่ค‡้›œ๏ผๆฅต็ซฏ็š„ๆƒ…ๅขƒใ€‚ + +็”ฑๆ–ผไธๅปบ่ญฐ้€™้บผๅš๏ผŒไฝฟ็”จ Swagger UI ็š„ไบ’ๅ‹•ๅผๆ–‡ไปถๅœจไฝฟ็”จ `GET` ๆ™‚ไธๆœƒ้กฏ็คบๆœฌๆ–‡็š„ๆ–‡ไปถ๏ผŒ่€Œไธ”ไธญ้–“็š„ไปฃ็†ไผบๆœๅ™จไนŸๅฏ่ƒฝไธๆ”ฏๆดใ€‚ + +/// + +## ๅŒฏๅ…ฅ Pydantic ็š„ `BaseModel` { #import-pydantics-basemodel } + +้ฆ–ๅ…ˆ๏ผŒๅพž `pydantic` ๅŒฏๅ…ฅ `BaseModel`๏ผš + +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} + +## ๅปบ็ซ‹ไฝ ็š„่ณ‡ๆ–™ๆจกๅž‹ { #create-your-data-model } + +ๆŽฅ่‘—๏ผŒไฝ ๅฐ‡่ณ‡ๆ–™ๆจกๅž‹ๅฎฃๅ‘Š็‚บ็นผๆ‰ฟ่‡ช `BaseModel` ็š„้กžๅˆฅใ€‚ + +ๅฐๆ‰€ๆœ‰ๅฑฌๆ€งไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅ๏ผš + +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + +ๅฐฑๅ’Œๅฎฃๅ‘ŠๆŸฅ่ฉขๅƒๆ•ธๆ™‚ไธ€ๆจฃ๏ผŒ็•ถๆจกๅž‹ๅฑฌๆ€งๆœ‰้ ่จญๅ€ผๆ™‚๏ผŒๅฎƒๅฐฑไธๆ˜ฏๅฟ…ๅกซ๏ผ›ๅฆๅ‰‡ๅฐฑๆ˜ฏๅฟ…ๅกซใ€‚ไฝฟ็”จ `None` ๅฏไฝฟๅ…ถๆˆ็‚บ้ธๅกซใ€‚ + +ไพ‹ๅฆ‚๏ผŒไธŠ่ฟฐๆจกๅž‹ๅฐๆ‡‰็š„ JSONใ€Œ`object`ใ€๏ผˆๆˆ– Python `dict`๏ผ‰ๅฆ‚ไธ‹๏ผš + +```JSON +{ + "name": "Foo", + "description": "An optional description", + "price": 45.2, + "tax": 3.5 +} +``` + +...็”ฑๆ–ผ `description` ่ˆ‡ `tax` ๆ˜ฏ้ธๅกซ๏ผˆ้ ่จญ็‚บ `None`๏ผ‰๏ผŒไปฅไธ‹้€™ๅ€‹ JSONใ€Œ`object`ใ€ไนŸๆœ‰ๆ•ˆ๏ผš + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## ๅฐ‡ๅฎƒๅฎฃๅ‘Š็‚บๅƒๆ•ธ { #declare-it-as-a-parameter } + +่ฆๆŠŠๅฎƒๅŠ ๅˆฐไฝ ็š„*่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰*ไธญ๏ผŒๅฎฃๅ‘Šๆ–นๅผ่ˆ‡่ทฏๅพ‘่ˆ‡ๆŸฅ่ฉขๅƒๆ•ธ็›ธๅŒ๏ผš + +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} + +...ไธฆๅฐ‡ๅ…ถๅž‹ๅˆฅๅฎฃๅ‘Š็‚บไฝ ๅปบ็ซ‹็š„ๆจกๅž‹ `Item`ใ€‚ + +## ๆ•ˆๆžœ { #results } + +ๅช้ ้€™ๆจฃ็š„ Python ๅž‹ๅˆฅๅฎฃๅ‘Š๏ผŒ**FastAPI** ๆœƒ๏ผš + +- ๅฐ‡่ซ‹ๆฑ‚ๆœฌๆ–‡่ฎ€ๅ–็‚บ JSONใ€‚ +- ๏ผˆๅฟ…่ฆๆ™‚๏ผ‰่ฝ‰ๆ›็‚บๅฐๆ‡‰็š„ๅž‹ๅˆฅใ€‚ +- ้ฉ—่ญ‰่ณ‡ๆ–™ใ€‚ + - ่‹ฅ่ณ‡ๆ–™็„กๆ•ˆ๏ผŒๆœƒๅ›žๅ‚ณๆธ…ๆฅšๆ˜“ๆ‡‚็š„้Œฏ่ชค๏ผŒๆŒ‡ๅ‡บๅ“ช่ฃกใ€ๅ“ช็ญ†่ณ‡ๆ–™ไธๆญฃ็ขบใ€‚ +- ๆŠŠๆŽฅๆ”ถๅˆฐ็š„่ณ‡ๆ–™ๆ”พๅœจๅƒๆ•ธ `item` ไธญๆไพ›็ตฆไฝ ใ€‚ + - ็”ฑๆ–ผไฝ ๅœจๅ‡ฝๅผไธญๅฐ‡ๅ…ถๅฎฃๅ‘Š็‚บ `Item` ๅž‹ๅˆฅ๏ผŒไฝ ไนŸๆœƒ็ฒๅพ—ๅฎŒๆ•ด็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผˆ่‡ชๅ‹•ๅฎŒๆˆ็ญ‰๏ผ‰ไปฅๅŠๆ‰€ๆœ‰ๅฑฌๆ€ง่ˆ‡ๅ…ถๅž‹ๅˆฅใ€‚ +- ็‚บไฝ ็š„ๆจกๅž‹็”ข็”Ÿ JSON Schema ๅฎš็พฉ๏ผŒๅฆ‚ๆœ‰้œ€่ฆ๏ผŒไฝ ไนŸๅฏไปฅๅœจๅฐˆๆกˆไธญ็š„ๅ…ถไป–ๅœฐๆ–นไฝฟ็”จใ€‚ +- ้€™ไบ› schema ๆœƒๆˆ็‚บ็”ข็”Ÿ็š„ OpenAPI schema ็š„ไธ€้ƒจๅˆ†๏ผŒไธฆ็”ฑ่‡ชๅ‹•ๆ–‡ไปถ UIs ไฝฟ็”จใ€‚ + +## ่‡ชๅ‹•ๆ–‡ไปถ { #automatic-docs } + +ไฝ ็š„ๆจกๅž‹็š„ JSON Schema ๆœƒ็ดๅ…ฅ็”ข็”Ÿ็š„ OpenAPI schema๏ผŒไธฆ้กฏ็คบๅœจไบ’ๅ‹•ๅผ API ๆ–‡ไปถไธญ๏ผš + + + +ไนŸๆœƒ็”จๆ–ผๆฏๅ€‹้œ€่ฆๅฎƒๅ€‘็š„*่ทฏๅพ‘ๆ“ไฝœ*ๅ…ง็š„ API ๆ–‡ไปถ๏ผš + + + +## ็ทจ่ผฏๅ™จๆ”ฏๆด { #editor-support } + +ๅœจ็ทจ่ผฏๅ™จ่ฃกใ€ๆ–ผไฝ ็š„ๅ‡ฝๅผไธญ๏ผŒไฝ ๆœƒๅœจๅ„่™•็ฒๅพ—ๅž‹ๅˆฅๆ็คบ่ˆ‡่‡ชๅ‹•ๅฎŒๆˆ๏ผˆๅฆ‚ๆžœไฝ ๆŽฅๆ”ถ็š„ๆ˜ฏ `dict` ่€Œไธๆ˜ฏ Pydantic ๆจกๅž‹๏ผŒๅฐฑไธๆœƒๆœ‰้€™ไบ›๏ผ‰๏ผš + + + +ไฝ ไนŸๆœƒ็ฒๅพ—ๅฐไธๆญฃ็ขบๅž‹ๅˆฅๆ“ไฝœ็š„้Œฏ่ชคๆชขๆŸฅ๏ผš + + + +้€™ไธๆ˜ฏๅถ็„ถ๏ผŒๆ•ดๅ€‹ๆก†ๆžถๅฐฑๆ˜ฏๅœ็นž้€™ๅ€‹่จญ่จˆ่€Œๅปบใ€‚ + +่€Œไธ”ๅœจๅฏฆไฝœไน‹ๅ‰็š„่จญ่จˆ้šŽๆฎตๅฐฑๅทฒๅพนๅบ•ๆธฌ่ฉฆ๏ผŒ็ขบไฟ่ƒฝๅœจๅ„็จฎ็ทจ่ผฏๅ™จไธญ้‹ไฝœ่‰ฏๅฅฝใ€‚ + +็”š่‡ณ็‚บไบ†ๆ”ฏๆด้€™้ปž๏ผŒPydantic ๆœฌ่บซไนŸๅšไบ†ไบ›ไฟฎๆ”นใ€‚ + +ๅ‰้ข็š„่žขๅน•ๆˆชๅœ–ๆ˜ฏไฝฟ็”จ Visual Studio Code ๆ‹็š„ใ€‚ + +ไฝ†ไฝ ๅœจ PyCharm ่ˆ‡ๅคงๅคšๆ•ธๅ…ถๅฎƒ Python ็ทจ่ผฏๅ™จไธญไนŸๆœƒๅพ—ๅˆฐ็›ธๅŒ็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผš + + + +/// tip + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ PyCharm ไฝœ็‚บ็ทจ่ผฏๅ™จ๏ผŒๅฏไปฅๅฎ‰่ฃ Pydantic PyCharm Pluginใ€‚ + +ๅฎƒ่ƒฝๅขžๅผท Pydantic ๆจกๅž‹็š„็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒๅŒ…ๅซ๏ผš + +- ่‡ชๅ‹•ๅฎŒๆˆ +- ๅž‹ๅˆฅๆชขๆŸฅ +- ้‡ๆง‹ +- ๆœๅฐ‹ +- ็จ‹ๅผ็ขผๆชขๆŸฅ + +/// + +## ไฝฟ็”จ่ฉฒๆจกๅž‹ { #use-the-model } + +ๅœจๅ‡ฝๅผๅ…ง๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅญ˜ๅ–ๆจกๅž‹็‰ฉไปถ็š„ๆ‰€ๆœ‰ๅฑฌๆ€ง๏ผš + +{* ../../docs_src/body/tutorial002_py310.py *} + +## ่ซ‹ๆฑ‚ๆœฌๆ–‡ + ่ทฏๅพ‘ๅƒๆ•ธ { #request-body-path-parameters } + +ไฝ ๅฏไปฅๅŒๆ™‚ๅฎฃๅ‘Š่ทฏๅพ‘ๅƒๆ•ธ่ˆ‡่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ + +**FastAPI** ๆœƒ่พจ่ญ˜ๅ‡บ่ˆ‡่ทฏๅพ‘ๅƒๆ•ธ็›ธ็ฌฆ็š„ๅ‡ฝๅผๅƒๆ•ธๆ‡‰่ฉฒๅพž**่ทฏๅพ‘**ๅ–ๅพ—๏ผŒ่€Œๅฎฃๅ‘Š็‚บ Pydantic ๆจกๅž‹็š„ๅ‡ฝๅผๅƒๆ•ธๆ‡‰่ฉฒๅพž**่ซ‹ๆฑ‚ๆœฌๆ–‡**ๅ–ๅพ—ใ€‚ + +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + +## ่ซ‹ๆฑ‚ๆœฌๆ–‡ + ่ทฏๅพ‘ + ๆŸฅ่ฉขๅƒๆ•ธ { #request-body-path-query-parameters } + +ไฝ ไนŸๅฏไปฅๅŒๆ™‚ๅฎฃๅ‘Š**ๆœฌๆ–‡**ใ€**่ทฏๅพ‘**่ˆ‡**ๆŸฅ่ฉข**ๅƒๆ•ธใ€‚ + +**FastAPI** ๆœƒๅˆ†ๅˆฅ่พจ่ญ˜ไธฆๅพžๆญฃ็ขบ็š„ไฝ็ฝฎๅ–ๅพ—่ณ‡ๆ–™ใ€‚ + +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} + +ๅ‡ฝๅผๅƒๆ•ธ็š„่พจ่ญ˜ๆ–นๅผๅฆ‚ไธ‹๏ผš + +- ๅฆ‚ๆžœๅƒๆ•ธๅŒๆ™‚ๅœจ**่ทฏๅพ‘**ไธญๅฎฃๅ‘Š๏ผŒๅ‰‡ไฝœ็‚บ่ทฏๅพ‘ๅƒๆ•ธใ€‚ +- ๅฆ‚ๆžœๅƒๆ•ธๆ˜ฏ**ๅ–ฎไธ€ๅž‹ๅˆฅ**๏ผˆๅƒๆ˜ฏ `int`ใ€`float`ใ€`str`ใ€`bool` ็ญ‰๏ผ‰๏ผŒๆœƒ่ขซ่ฆ–็‚บ**ๆŸฅ่ฉข**ๅƒๆ•ธใ€‚ +- ๅฆ‚ๆžœๅƒๆ•ธๅฎฃๅ‘Š็‚บ **Pydantic ๆจกๅž‹** ๅž‹ๅˆฅ๏ผŒๆœƒ่ขซ่ฆ–็‚บ่ซ‹ๆฑ‚**ๆœฌๆ–‡**ใ€‚ + +/// note + +FastAPI ๆœƒๅ› ็‚บ้ ่จญๅ€ผ `= None` ่€Œ็Ÿฅ้“ `q` ็š„ๅ€ผไธๆ˜ฏๅฟ…ๅกซใ€‚ + +`str | None` ไธฆ้ž FastAPI ็”จไพ†ๅˆคๆ–ทๆ˜ฏๅฆๅฟ…ๅกซ็š„ไพๆ“š๏ผ›ๅฎƒๆœƒๅ› ็‚บๆœ‰้ ่จญๅ€ผ `= None` ่€Œ็Ÿฅ้“ไธๆ˜ฏๅฟ…ๅกซใ€‚ + +ไฝ†ๅŠ ๅ…ฅ้€™ไบ›ๅž‹ๅˆฅ่จป่งฃ่ƒฝ่ฎ“ไฝ ็š„็ทจ่ผฏๅ™จๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆด่ˆ‡้Œฏ่ชคๅตๆธฌใ€‚ + +/// + +## ไธไฝฟ็”จ Pydantic { #without-pydantic } + +่‹ฅไฝ ไธๆƒณไฝฟ็”จ Pydantic ๆจกๅž‹๏ผŒไนŸๅฏไปฅไฝฟ็”จ **Body** ๅƒๆ•ธใ€‚่ซ‹ๅƒ่€ƒ[Body - ๅคšๅ€‹ๅƒๆ•ธ๏ผšๆœฌๆ–‡ไธญ็š„ๅ–ฎไธ€ๅ€ผ](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/cookie-param-models.md b/docs/zh-hant/docs/tutorial/cookie-param-models.md new file mode 100644 index 0000000000..8997903e38 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Cookie ๅƒๆ•ธๆจกๅž‹ { #cookie-parameter-models } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€็ต„ๅฝผๆญค็›ธ้—œ็š„ใ€Œ**Cookie**ใ€๏ผŒไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹ใ€Œ**Pydantic ๆจกๅž‹**ใ€ไพ†ๅฎฃๅ‘Šๅฎƒๅ€‘ใ€‚๐Ÿช + +้€™ๆจฃไฝ ๅฐฑ่ƒฝๅœจ**ๅคš่™•**้‡่ค‡ไฝฟ็”จ่ฉฒๆจกๅž‹๏ผŒไธฆไธ”่ƒฝไธ€ๆฌกๆ€ง็‚บๆ‰€ๆœ‰ๅƒๆ•ธๅฎฃๅ‘Š**้ฉ—่ญ‰**่ˆ‡**ไธญ็นผ่ณ‡ๆ–™**ใ€‚๐Ÿ˜Ž + +/// note | ๆณจๆ„ + +่‡ช FastAPI ็‰ˆๆœฌ `0.115.0` ่ตทๆ”ฏๆดใ€‚๐Ÿค“ + +/// + +/// tip + +ๅŒๆจฃ็š„ๆŠ€ๅทงไนŸ้ฉ็”จๆ–ผ `Query`ใ€`Cookie` ่ˆ‡ `Header`ใ€‚๐Ÿ˜Ž + +/// + +## ไปฅ Pydantic ๆจกๅž‹ๅฎฃๅ‘Š Cookie { #cookies-with-a-pydantic-model } + +ๅœจ **Pydantic ๆจกๅž‹**ไธญๅฎฃๅ‘Šๆ‰€้œ€็š„ **Cookie** ๅƒๆ•ธ๏ผŒๆŽฅ่‘—ๅฐ‡ๅƒๆ•ธๅฎฃๅ‘Š็‚บ `Cookie`๏ผš + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** ๆœƒๅพž่ซ‹ๆฑ‚ๆ”ถๅˆฐ็š„ **Cookie** ไธญๆ“ทๅ– **ๆฏๅ€‹ๆฌ„ไฝ** ็š„่ณ‡ๆ–™๏ผŒไธฆไบค็ตฆไฝ ๅฎš็พฉ็š„ Pydantic ๆจกๅž‹ใ€‚ + +## ๆŸฅ็œ‹ๆ–‡ไปถ { #check-the-docs } + +ไฝ ๅฏไปฅๅœจ `/docs` ็š„ๆ–‡ไปถไป‹้ขไธญ็œ‹ๅˆฐๅทฒๅฎš็พฉ็š„ Cookie๏ผš + +
+ +
+ +/// info + +่ซ‹ๆณจๆ„๏ผŒ็”ฑๆ–ผ**็€่ฆฝๅ™จๆœƒไปฅ็‰นๆฎŠไธ”ๅœจ่ƒŒๆ™ฏ้€ฒ่กŒ็š„ๆ–นๅผ่™•็† Cookie**๏ผŒๅ› ๆญค**ไธๆœƒ**่ผ•ๆ˜“ๅ…่จฑ **JavaScript** ๅญ˜ๅ–ๅฎƒๅ€‘ใ€‚ + +็•ถไฝ ๅ‰ๅพ€ไฝๆ–ผ `/docs` ็š„ **API ๆ–‡ไปถไป‹้ข**ๆ™‚๏ผŒๅฏไปฅ็œ‹ๅˆฐ่ทฏๅพ‘ๆ“ไฝœ็š„ Cookie ่ชชๆ˜Žใ€‚ + +ไฝ†ๅณไฝฟไฝ **ๅกซๅ…ฅ่ณ‡ๆ–™**ไธฆ้ปžๆ“Šใ€ŒExecuteใ€๏ผŒๅ› ็‚บ่ฉฒๆ–‡ไปถไป‹้ขๆ˜ฏไปฅ **JavaScript** ้‹ไฝœ๏ผŒCookie ไธๆœƒ่ขซ้€ๅ‡บ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ**้Œฏ่ชค**่จŠๆฏ๏ผŒๅฐฑๅƒๅฎŒๅ…จๆฒ’ๆœ‰ๅกซไปปไฝ•ๅ€ผไธ€ๆจฃใ€‚ + +/// + +## ็ฆๆญข้กๅค–็š„ Cookie { #forbid-extra-cookies } + +ๅœจๆŸไบ›็‰นๆฎŠๆƒ…ๅขƒ๏ผˆๅฏ่ƒฝไธๅคชๅธธ่ฆ‹๏ผ‰ไธ‹๏ผŒไฝ ๅฏ่ƒฝๆœƒๆƒณ**้™ๅˆถ**ๅ…่จฑๆŽฅๆ”ถ็š„ Cookieใ€‚ + +ไฝ ็š„ API ็พๅœจไนŸ่ƒฝๆŽŒๆŽง่‡ชๅทฑ็š„ Cookie ๅŒๆ„ใ€‚๐Ÿคช๐Ÿช + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹่จญๅฎšไพ† `forbid` ไปปไฝ• `extra` ๆฌ„ไฝ๏ผš + +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} + +ๅฆ‚ๆžœๅฎขๆˆถ็ซฏๅ˜—่ฉฆ้€ๅ‡บ**้กๅค–็š„ Cookie**๏ผŒๆœƒๆ”ถๅˆฐ**้Œฏ่ชค**ๅ›žๆ‡‰ใ€‚ + +ๅฏๆ†็š„ Cookie ๆฉซๅน…่พ›่‹ฆๆ”ถ้›†ไฝ ็š„ๅŒๆ„๏ผŒๆœ€ๅพŒๅปๆ˜ฏ็‚บไบ†่ฎ“ API ๆ‹’็ต•ๅฎƒใ€‚๐Ÿช + +ไพ‹ๅฆ‚๏ผŒ่‹ฅๅฎขๆˆถ็ซฏๅ˜—่ฉฆ้€ๅ‡บๅ็‚บ `santa_tracker`ใ€ๅ€ผ็‚บ `good-list-please` ็š„ Cookie๏ผŒๅฎขๆˆถ็ซฏๆœƒๆ”ถๅˆฐ**้Œฏ่ชค**ๅ›žๆ‡‰๏ผŒๅ‘Š็Ÿฅ `santa_tracker` ้€™ๅ€‹ Cookie ไธ่ขซๅ…่จฑ๏ผš + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## ๆ‘˜่ฆ { #summary } + +ไฝ ๅฏไปฅๅœจ **FastAPI** ไธญไฝฟ็”จ **Pydantic ๆจกๅž‹**ไพ†ๅฎฃๅ‘Š **Cookie**ใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/tutorial/cookie-params.md b/docs/zh-hant/docs/tutorial/cookie-params.md new file mode 100644 index 0000000000..cc9d4b6828 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/cookie-params.md @@ -0,0 +1,45 @@ +# Cookie ๅƒๆ•ธ { #cookie-parameters } + +ไฝ ๅฏไปฅ็”จ่ˆ‡ๅฎš็พฉ `Query` ่ˆ‡ `Path` ๅƒๆ•ธ็›ธๅŒ็š„ๆ–นๅผๅฎš็พฉ Cookie ๅƒๆ•ธใ€‚ + +## ๅŒฏๅ…ฅ `Cookie` { #import-cookie } + +ๅ…ˆๅŒฏๅ…ฅ `Cookie`๏ผš + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} + +## ๅฎฃๅ‘Š `Cookie` ๅƒๆ•ธ { #declare-cookie-parameters } + +็„ถๅพŒ็”จ่ˆ‡ `Path`ใ€`Query` ็›ธๅŒ็š„็ตๆง‹ๅฎฃๅ‘Š `Cookie` ๅƒๆ•ธใ€‚ + +ไฝ ๅฏไปฅ่จญๅฎš้ ่จญๅ€ผ๏ผŒไปฅๅŠๆ‰€ๆœ‰้กๅค–็š„้ฉ—่ญ‰ๆˆ–่จป่งฃๅƒๆ•ธ๏ผš + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +`Cookie` ๆ˜ฏ `Path` ่ˆ‡ `Query` ็š„ใ€ŒๅงŠๅฆนใ€้กžๅˆฅใ€‚ๅฎƒๅŒๆจฃ็นผๆ‰ฟ่‡ชๅ…ฑๅŒ็š„ `Param` ้กžๅˆฅใ€‚ + +ไฝ†่ซ‹่จ˜ไฝ๏ผŒ็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path`ใ€`Cookie` ็ญ‰ๆ™‚๏ผŒๅฎƒๅ€‘ๅฏฆ้š›ไธŠๆ˜ฏๅ›žๅ‚ณ็‰นๆฎŠ้กžๅˆฅ็š„ๅ‡ฝๅผใ€‚ + +/// + +/// info + +่ฆๅฎฃๅ‘Š cookies๏ผŒไฝ ้œ€่ฆไฝฟ็”จ `Cookie`๏ผŒๅฆๅ‰‡ๅƒๆ•ธๆœƒ่ขซ็•ถไฝœๆŸฅ่ฉขๅƒๆ•ธ๏ผˆquery parameters๏ผ‰ไพ†่งฃๆžใ€‚ + +/// + +/// info + +่ซ‹ๆณจๆ„๏ผŒ็”ฑๆ–ผ็€่ฆฝๅ™จไปฅ็‰นๆฎŠไธ”ๅœจ่ƒŒๅพŒ่™•็†็š„ๆ–นๅผ็ฎก็† cookies๏ผŒๅฎƒๅ€‘้€šๅธธไธๅ…่จฑ JavaScript ่ผ•ๆ˜“ๅญ˜ๅ–ๅฎƒๅ€‘ใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€ไฝๆ–ผ `/docs` ็š„ API ๆ–‡ไปถไป‹้ข๏ผŒไฝ ๅฏไปฅๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operations๏ผ‰็š„ๆ–‡ไปถไธญ็œ‹ๅˆฐ cookies ็š„่ชชๆ˜Žใ€‚ + +ไฝ†ๅณไฝฟไฝ ๅกซๅ…ฅ่ณ‡ๆ–™ไธฆ้ปžๆ“Šใ€ŒExecuteใ€๏ผŒ็”ฑๆ–ผ่ฉฒๆ–‡ไปถไป‹้ขๆ˜ฏไปฅ JavaScript ้‹ไฝœ๏ผŒcookies ไธๆœƒ่ขซ้€ๅ‡บ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐไธ€ๅ‰‡้Œฏ่ชค่จŠๆฏ๏ผŒๅฐฑๅฅฝๅƒไฝ ๆฒ’ๆœ‰ๅกซไปปไฝ•ๅ€ผไธ€ๆจฃใ€‚ + +/// + +## ็ธฝ็ต { #recap } + +ไฝฟ็”จ `Cookie` ไพ†ๅฎฃๅ‘Š cookies๏ผŒ้ตๅพช่ˆ‡ `Query`ใ€`Path` ็›ธๅŒ็š„้€š็”จๅฏซๆณ•ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/cors.md b/docs/zh-hant/docs/tutorial/cors.md new file mode 100644 index 0000000000..5fa497c081 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/cors.md @@ -0,0 +1,88 @@ +# CORS๏ผˆ่ทจไพ†ๆบ่ณ‡ๆบๅ…ฑ็”จ๏ผ‰ { #cors-cross-origin-resource-sharing } + +CORS ๆˆ–ใ€ŒCross-Origin Resource Sharingใ€ๆŒ‡็š„ๆ˜ฏ๏ผš็•ถๅœจ็€่ฆฝๅ™จไธญๅŸท่กŒ็š„ๅ‰็ซฏไปฅ JavaScript ่ˆ‡ๅพŒ็ซฏ้€š่จŠ๏ผŒ่€ŒๅพŒ็ซฏ่ˆ‡ๅ‰็ซฏไฝๆ–ผไธๅŒใ€Œไพ†ๆบ๏ผˆorigin๏ผ‰ใ€ๆ™‚็š„ๆƒ…ๅขƒใ€‚ + +## ไพ†ๆบ๏ผˆOrigin๏ผ‰ { #origin } + +ไธ€ๅ€‹ไพ†ๆบๆ˜ฏ็”ฑ้€š่จŠๅ”ๅฎš๏ผˆ`http`ใ€`https`๏ผ‰ใ€็ถฒๅŸŸ๏ผˆ`myapp.com`ใ€`localhost`ใ€`localhost.tiangolo.com`๏ผ‰่ˆ‡้€ฃๆŽฅๅŸ ๏ผˆ`80`ใ€`443`ใ€`8080`๏ผ‰ไธ‰่€…็ต„ๅˆ่€Œๆˆใ€‚ + +ๅ› ๆญค๏ผŒไปฅไธ‹็š†ๆ˜ฏไธๅŒ็š„ไพ†ๆบ๏ผš + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +ๅณไฝฟๅฎƒๅ€‘้ƒฝๅœจ `localhost`๏ผŒไฝ†ไฝฟ็”จไบ†ไธๅŒ็š„้€š่จŠๅ”ๅฎšๆˆ–้€ฃๆŽฅๅŸ ๏ผŒๆ‰€ไปฅๅฎƒๅ€‘ๆ˜ฏไธๅŒ็š„ใ€Œไพ†ๆบใ€ใ€‚ + +## ๆญฅ้ฉŸ { #steps } + +ๅ‡่จญไฝ ็š„ๅ‰็ซฏๅœจ็€่ฆฝๅ™จไธญๅŸท่กŒๆ–ผ `http://localhost:8080`๏ผŒๅ…ถ JavaScript ๅ˜—่ฉฆ่ˆ‡ๅŸท่กŒๅœจ `http://localhost` ็š„ๅพŒ็ซฏ้€š่จŠ๏ผˆๅ› ็‚บๆœชๆŒ‡ๅฎš้€ฃๆŽฅๅŸ ๏ผŒ็€่ฆฝๅ™จๆœƒๅ‡่จญ้ ่จญ้€ฃๆŽฅๅŸ ็‚บ `80`๏ผ‰ใ€‚ + +ๆŽฅ่‘—๏ผŒ็€่ฆฝๅ™จๆœƒๅ‘ `:80` ็š„ๅพŒ็ซฏ้€ๅ‡บไธ€ๅ€‹ HTTP `OPTIONS` ่ซ‹ๆฑ‚๏ผ›่‹ฅๅพŒ็ซฏๅ›žๅ‚ณ้ฉ็•ถ็š„ๆจ™้ ญ๏ผŒๆŽˆๆฌŠๆญคไธๅŒไพ†ๆบ๏ผˆ`http://localhost:8080`๏ผ‰็š„้€š่จŠ๏ผŒๅ‰‡ๅœจ `:8080` ็š„็€่ฆฝๅ™จๅฐฑๆœƒๅ…่จฑๅ‰็ซฏ็š„ JavaScript ๅ‘ `:80` ็š„ๅพŒ็ซฏ้€ๅ‡บๅฎƒ็š„่ซ‹ๆฑ‚ใ€‚ + +็‚บไบ†้”ๆˆ้€™้ปž๏ผŒ`:80` ็š„ๅพŒ็ซฏๅฟ…้ ˆๆœ‰ไธ€ไปฝใ€Œๅ…่จฑ็š„ไพ†ๆบใ€ๆธ…ๅ–ฎใ€‚ + +ๅœจๆญคๆƒ…ๆณไธ‹๏ผŒ่ฉฒๆธ…ๅ–ฎๅฟ…้ ˆๅŒ…ๅซ `http://localhost:8080`๏ผŒ` :8080` ็š„ๅ‰็ซฏๆ‰่ƒฝๆญฃ็ขบ้‹ไฝœใ€‚ + +## ่ฌ็”จๅญ—ๅ…ƒ { #wildcards } + +ไนŸๅฏไปฅๅฐ‡ๆธ…ๅ–ฎๅฎฃๅ‘Š็‚บ `"*"`๏ผˆใ€Œwildcardใ€่ฌ็”จๅญ—ๅ…ƒ๏ผ‰๏ผŒ่กจ็คบๅ…จ้ƒจ้ƒฝๅ…่จฑใ€‚ + +ไฝ†้‚ฃๅชๆœƒๅ…่จฑๆŸไบ›้กžๅž‹็š„้€š่จŠ๏ผŒๅ‡กๆ˜ฏๆถ‰ๅŠๆ†‘่ญ‰๏ผˆcredentials๏ผ‰็š„้ƒฝๆœƒ่ขซๆŽ’้™ค๏ผšไพ‹ๅฆ‚ Cookieใ€Authorization ๆจ™้ ญ๏ผˆๅƒ Bearer Token ๆœƒ็”จๅˆฐ็š„๏ผ‰็ญ‰ใ€‚ + +ๅ› ๆญค๏ผŒ็‚บไบ†่ฎ“ไธ€ๅˆ‡ๆญฃๅธธ้‹ไฝœ๏ผŒๆœ€ๅฅฝๆ˜Ž็ขบๆŒ‡ๅฎš่ขซๅ…่จฑ็š„ไพ†ๆบใ€‚ + +## ไฝฟ็”จ `CORSMiddleware` { #use-corsmiddleware } + +ไฝ ๅฏไปฅๅœจ **FastAPI** ๆ‡‰็”จ็จ‹ๅผไธญไฝฟ็”จ `CORSMiddleware` ไพ†่จญๅฎš๏ผš + +* ๅŒฏๅ…ฅ `CORSMiddleware`ใ€‚ +* ๅปบ็ซ‹ๅ…่จฑ็š„ไพ†ๆบๆธ…ๅ–ฎ๏ผˆๅญ—ไธฒ๏ผ‰ใ€‚ +* ๅฐ‡ๅฎƒๅŠ ๅ…ฅๅˆฐไฝ ็š„ **FastAPI** ๆ‡‰็”จ็จ‹ๅผๅš็‚บใ€Œไธญไป‹่ปŸ้ซ”๏ผˆmiddleware๏ผ‰ใ€ใ€‚ + +ไฝ ไนŸๅฏไปฅๆŒ‡ๅฎšไฝ ็š„ๅพŒ็ซฏๆ˜ฏๅฆๅ…่จฑ๏ผš + +* ๆ†‘่ญ‰๏ผˆcredentials๏ผŒไพ‹ๅฆ‚ Authorization ๆจ™้ ญใ€Cookie ็ญ‰๏ผ‰ใ€‚ +* ็‰นๅฎš็š„ HTTP ๆ–นๆณ•๏ผˆๅฆ‚ `POST`ใ€`PUT`๏ผ‰๏ผŒๆˆ–ไฝฟ็”จ่ฌ็”จๅญ—ๅ…ƒ `"*"` ่กจ็คบๅ…จ้ƒจใ€‚ +* ็‰นๅฎš็š„ HTTP ๆจ™้ ญ๏ผŒๆˆ–ไฝฟ็”จ่ฌ็”จๅญ—ๅ…ƒ `"*"` ่กจ็คบๅ…จ้ƒจใ€‚ + +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + +`CORSMiddleware` ็š„ๅฏฆไฝœๅœจ้ ่จญๅƒๆ•ธไธŠ็›ธ็•ถๅšดๆ ผ๏ผŒๅ› ๆญคไฝ ้œ€่ฆๆ˜Ž็ขบๅ•Ÿ็”จ็‰นๅฎš็š„ไพ†ๆบใ€ๆ–นๆณ•ๆˆ–ๆจ™้ ญ๏ผŒ็€่ฆฝๅ™จๆ‰ๆœƒๅ…่จฑๅœจ่ทจ็ถฒๅŸŸๆƒ…ๅขƒไธญไฝฟ็”จๅฎƒๅ€‘ใ€‚ + +ๆ”ฏๆดไปฅไธ‹ๅƒๆ•ธ๏ผš + +* `allow_origins` - ๅ…่จฑ้€ฒ่กŒ่ทจไพ†ๆบ่ซ‹ๆฑ‚็š„ไพ†ๆบๆธ…ๅ–ฎใ€‚ไพ‹ๅฆ‚ `['https://example.org', 'https://www.example.org']`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ไพ†ๅ…่จฑไปปไฝ•ไพ†ๆบใ€‚ +* `allow_origin_regex` - ๅ…่จฑ้€ฒ่กŒ่ทจไพ†ๆบ่ซ‹ๆฑ‚็š„ไพ†ๆบ๏ผŒไฝฟ็”จๆญฃ่ฆ่กจ็คบๅผๅญ—ไธฒๆฏ”ๅฐใ€‚ไพ‹ๅฆ‚ `'https://.*\.example\.org'`ใ€‚ +* `allow_methods` - ๅ…่จฑ่ทจไพ†ๆบ่ซ‹ๆฑ‚็š„ HTTP ๆ–นๆณ•ๆธ…ๅ–ฎใ€‚้ ่จญ็‚บ `['GET']`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ไพ†ๅ…่จฑๆ‰€ๆœ‰ๆจ™ๆบ–ๆ–นๆณ•ใ€‚ +* `allow_headers` - ๅ…่จฑ่ทจไพ†ๆบ่ซ‹ๆฑ‚ๆ‰€ๆ”ฏๆด็š„ HTTP ่ซ‹ๆฑ‚ๆจ™้ ญๆธ…ๅ–ฎใ€‚้ ่จญ็‚บ `[]`ใ€‚ไฝ ๅฏไปฅไฝฟ็”จ `['*']` ไพ†ๅ…่จฑๆ‰€ๆœ‰ๆจ™้ ญใ€‚ๅฐๆ–ผ็ฐกๅ–ฎ CORS ่ซ‹ๆฑ‚๏ผŒ`Accept`ใ€`Accept-Language`ใ€`Content-Language` ่ˆ‡ `Content-Type` ๆจ™้ ญไธ€ๅพ‹่ขซๅ…่จฑใ€‚ +* `allow_credentials` - ๆŒ‡็คบๆ˜ฏๅฆๆ”ฏๆด่ทจไพ†ๆบ่ซ‹ๆฑ‚็š„ Cookieใ€‚้ ่จญ็‚บ `False`ใ€‚ + + ็•ถ `allow_credentials` ่จญ็‚บ `True` ๆ™‚๏ผŒ`allow_origins`ใ€`allow_methods` ่ˆ‡ `allow_headers` ้ƒฝไธ่ƒฝ่จญ็‚บ `['*']`ใ€‚ไธŠ่ฟฐๅ„้ …ๅฟ…้ ˆๆ˜Ž็ขบๆŒ‡ๅฎšใ€‚ + +* `expose_headers` - ๆŒ‡็คบๅ“ชไบ›ๅ›žๆ‡‰ๆจ™้ ญๆ‡‰่ฉฒ่ฎ“็€่ฆฝๅ™จๅฏๅญ˜ๅ–ใ€‚้ ่จญ็‚บ `[]`ใ€‚ +* `max_age` - ่จญๅฎš็€่ฆฝๅ™จๅฟซๅ– CORS ๅ›žๆ‡‰็š„ๆœ€้•ท็ง’ๆ•ธใ€‚้ ่จญ็‚บ `600`ใ€‚ + +ๆญคไธญไป‹่ปŸ้ซ”ๆœƒๅ›žๆ‡‰ๅ…ฉ็จฎ็‰นๅฎš็š„ HTTP ่ซ‹ๆฑ‚้กžๅž‹... + +### CORS ้ ๆชข่ซ‹ๆฑ‚ { #cors-preflight-requests } + +ไปปไฝ•ๅธถๆœ‰ `Origin` ่ˆ‡ `Access-Control-Request-Method` ๆจ™้ ญ็š„ `OPTIONS` ่ซ‹ๆฑ‚ใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไธญไป‹่ปŸ้ซ”ๆœƒๆ””ๆˆชๅ‚ณๅ…ฅ็š„่ซ‹ๆฑ‚ไธฆๅ›žๆ‡‰้ฉ็•ถ็š„ CORS ๆจ™้ ญ๏ผŒไธฆๅ›žๅ‚ณ `200` ๆˆ– `400`๏ผˆๅƒ…ไพ›่ณ‡่จŠๅƒ่€ƒ๏ผ‰ใ€‚ + +### ็ฐกๅ–ฎ่ซ‹ๆฑ‚ { #simple-requests } + +ไปปไฝ•ๅธถๆœ‰ `Origin` ๆจ™้ ญ็š„่ซ‹ๆฑ‚ใ€‚ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒไธญไป‹่ปŸ้ซ”ๆœƒๅฆ‚ๅธธๅฐ‡่ซ‹ๆฑ‚ๅพ€ไธ‹ๅ‚ณ้ž๏ผŒไฝ†ๆœƒๅœจๅ›žๆ‡‰ไธŠๅŠ ๅ…ฅ้ฉ็•ถ็š„ CORS ๆจ™้ ญใ€‚ + +## ๆ›ดๅคš่ณ‡่จŠ { #more-info } + +ๆƒณ้€ฒไธ€ๆญฅไบ†่งฃ CORS๏ผŒ่ซ‹ๅƒ่€ƒ Mozilla ็š„ CORS ๆ–‡ไปถใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.middleware.cors import CORSMiddleware`ใ€‚ + +**FastAPI** ๅœจ `fastapi.middleware` ไธญๆไพ›ไบ†ๅนพๅ€‹ไธญไป‹่ปŸ้ซ”๏ผŒๅš็‚บ้–‹็™ผ่€…็š„ไพฟๅˆฉๆ€งใ€‚ไฝ†ๅคšๆ•ธๅฏ็”จ็š„ไธญไป‹่ปŸ้ซ”ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/debugging.md b/docs/zh-hant/docs/tutorial/debugging.md new file mode 100644 index 0000000000..cb82ee417b --- /dev/null +++ b/docs/zh-hant/docs/tutorial/debugging.md @@ -0,0 +1,113 @@ +# ๅต้Œฏ { #debugging } + +ไฝ ๅฏไปฅๅœจ็ทจ่ผฏๅ™จไธญ้€ฃๆŽฅๅต้Œฏๅ™จ๏ผŒไพ‹ๅฆ‚ Visual Studio Code ๆˆ– PyCharmใ€‚ + +## ๅ‘ผๅซ `uvicorn` { #call-uvicorn } + +ๅœจไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผไธญ๏ผŒ็›ดๆŽฅๅŒฏๅ…ฅไธฆๅŸท่กŒ `uvicorn`๏ผš + +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} + +### ้—œๆ–ผ `__name__ == "__main__"` { #about-name-main } + +`__name__ == "__main__"` ็š„ไธป่ฆ็›ฎ็š„ๆ˜ฏ๏ผŒ็•ถไฝ ็š„ๆช”ๆกˆไปฅไปฅไธ‹ๆ–นๅผๅ‘ผๅซๆ™‚๏ผŒๅŸท่กŒๆŸไบ›็จ‹ๅผ็ขผ๏ผš + +
+ +```console +$ python myapp.py +``` + +
+ +ไฝ†็•ถๅ…ถไป–ๆช”ๆกˆๅŒฏๅ…ฅๅฎƒๆ™‚ไธๆœƒๅŸท่กŒ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +from myapp import app +``` + +#### ๆ›ดๅคš็ดฐ็ฏ€ { #more-details } + +ๅ‡่จญไฝ ็š„ๆช”ๅๆ˜ฏ `myapp.py`ใ€‚ + +ๅฆ‚ๆžœไฝ ็”จไปฅไธ‹ๆ–นๅผๅŸท่กŒๅฎƒ๏ผš + +
+ +```console +$ python myapp.py +``` + +
+ +้‚ฃ้บผๅœจไฝ ็š„ๆช”ๆกˆไธญ๏ผŒ็”ฑ Python ่‡ชๅ‹•ๅปบ็ซ‹็š„ๅ…ง้ƒจ่ฎŠๆ•ธ `__name__`๏ผŒๅ…ถๅ€ผๆœƒๆ˜ฏๅญ—ไธฒ `"__main__"`ใ€‚ + +ๅ› ๆญค๏ผŒ้€™ๆฎต๏ผš + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ๆœƒ่ขซๅŸท่กŒใ€‚ + +--- + +ๅฆ‚ๆžœไฝ ๆ˜ฏๅŒฏๅ…ฅ่ฉฒๆจก็ต„๏ผˆๆช”ๆกˆ๏ผ‰๏ผŒๅฐฑไธๆœƒ็™ผ็”Ÿ้€™ไปถไบ‹ใ€‚ + +ๆ‰€ไปฅ๏ผŒๅฆ‚ๆžœไฝ ๆœ‰ๅฆไธ€ๅ€‹ๆช”ๆกˆ `importer.py`๏ผŒๅ…งๅฎนๅฆ‚ไธ‹๏ผš + +```Python +from myapp import app + +# Some more code +``` + +ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹๏ผŒ`myapp.py` ไธญ่‡ชๅ‹•ๅปบ็ซ‹็š„่ฎŠๆ•ธ `__name__` ๅฐฑไธๆœƒๆ˜ฏ `"__main__"`ใ€‚ + +ๅ› ๆญค๏ผŒ้€™ไธ€่กŒ๏ผš + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ๅฐฑไธๆœƒ่ขซๅŸท่กŒใ€‚ + +/// info | ่ชชๆ˜Ž + +ๆƒณไบ†่งฃๆ›ดๅคš๏ผŒๅƒ่€ƒ Python ๅฎ˜ๆ–นๆ–‡ไปถใ€‚ + +/// + +## ็”จๅต้Œฏๅ™จๅŸท่กŒไฝ ็š„็จ‹ๅผ็ขผ { #run-your-code-with-your-debugger } + +ๅ› ็‚บไฝ ๆ˜ฏ็›ดๆŽฅๅพž็จ‹ๅผ็ขผไธญๅŸท่กŒ Uvicorn ไผบๆœๅ™จ๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅ็›ดๆŽฅๅพžๅต้Œฏๅ™จๅ‘ผๅซไฝ ็š„ Python ็จ‹ๅผ๏ผˆไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผ๏ผ‰ใ€‚ + +--- + +ไพ‹ๅฆ‚๏ผŒๅœจ Visual Studio Code ไธญ๏ผŒไฝ ๅฏไปฅ๏ผš + +* ๅ‰ๅพ€ "Debug" ้ขๆฟ +* ้ปž้ธ "Add configuration..." +* ้ธๆ“‡ "Python" +* ไฝฟ็”จ้ธ้ … "`Python: Current File (Integrated Terminal)`" ๅ•Ÿๅ‹•ๅต้Œฏๅ™จ + +ๆŽฅ่‘—ๅฎƒๆœƒ็”จไฝ ็š„ **FastAPI** ็จ‹ๅผ็ขผๅ•Ÿๅ‹•ไผบๆœๅ™จใ€ๅœจไฝ ็š„ไธญๆ–ท้ปžๅœไธ‹็ญ‰ใ€‚ + +ๅฏ่ƒฝๆœƒ้•ท้€™ๆจฃ๏ผš + + + +--- + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ PyCharm๏ผŒไฝ ๅฏไปฅ๏ผš + +* ้–‹ๅ•Ÿ "Run" ้ธๅ–ฎ +* ้ธๆ“‡ "Debug..." +* ๆœƒๅ‡บ็พไธ€ๅ€‹ๆƒ…ๅขƒ้ธๅ–ฎ +* ้ธๆ“‡่ฆๅต้Œฏ็š„ๆช”ๆกˆ๏ผˆๆญคไพ‹็‚บ `main.py`๏ผ‰ + +ๆŽฅ่‘—ๅฎƒๆœƒ็”จไฝ ็š„ **FastAPI** ็จ‹ๅผ็ขผๅ•Ÿๅ‹•ไผบๆœๅ™จใ€ๅœจไฝ ็š„ไธญๆ–ท้ปžๅœไธ‹็ญ‰ใ€‚ + +ๅฏ่ƒฝๆœƒ้•ท้€™ๆจฃ๏ผš + + diff --git a/docs/zh-hant/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh-hant/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 0000000000..34b8732109 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# ไปฅ้กžๅˆฅไฝœ็‚บ็›ธไพๆ€ง { #classes-as-dependencies } + +ๅœจๆ›ดๆทฑๅ…ฅไบ†่งฃ **็›ธไพๆ€งๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰** ็ณป็ตฑไน‹ๅ‰๏ผŒๆˆ‘ๅ€‘ๅ…ˆๆŠŠๅ‰ไธ€ๅ€‹็ฏ„ไพ‹ๅ‡็ดšไธ€ไธ‹ใ€‚ + +## ๅ‰ไธ€ๅ€‹็ฏ„ไพ‹ไธญ็š„ `dict` { #a-dict-from-the-previous-example } + +ๅœจๅ‰ไธ€ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๅพž็›ธไพ้ …๏ผˆ"dependable"๏ผ‰ๅ›žๅ‚ณไบ†ไธ€ๅ€‹ `dict`๏ผš + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +ไฝ†ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆ*path operation function*๏ผ‰็š„ๅƒๆ•ธ `commons` ไธญๅ–ๅพ—็š„ๆ˜ฏไธ€ๅ€‹ `dict`ใ€‚ + +่€Œๆˆ‘ๅ€‘็Ÿฅ้“๏ผŒ็ทจ่ผฏๅ™จๅฐ `dict` ็„กๆณ•ๆไพ›ๅคชๅคš่ผ”ๅŠฉ๏ผˆไพ‹ๅฆ‚่‡ชๅ‹•ๅฎŒๆˆ๏ผ‰๏ผŒๅ› ็‚บๅฎƒ็„กๆณ•้ ๅ…ˆ็Ÿฅ้“ๅ…ถไธญ็š„้ต่ˆ‡ๅ€ผ็š„ๅž‹ๅˆฅใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅๅšๅพ—ๆ›ดๅฅฝ... + +## ไป€้บผ็ฎ—ๆ˜ฏ็›ธไพๆ€ง { #what-makes-a-dependency } + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไฝ ็œ‹ๅˆฐ็š„็›ธไพๆ€ง้ƒฝๆ˜ฏๅฎฃๅ‘Šๆˆๅ‡ฝๅผใ€‚ + +ไฝ†้‚ฃไธๆ˜ฏๅฎฃๅ‘Š็›ธไพๆ€ง็š„ๅ”ฏไธ€ๆ–นๅผ๏ผˆ้›–็„ถ้‚ฃๅคงๆฆ‚ๆ˜ฏๆœ€ๅธธ่ฆ‹็š„๏ผ‰ใ€‚ + +้—œ้ตๅœจๆ–ผ๏ผŒ็›ธไพๆ€งๆ‡‰่ฉฒ่ฆๆ˜ฏใ€Œcallableใ€ใ€‚ + +ๅœจ Python ไธญ๏ผŒใ€Œ**callable**ใ€ๆŒ‡็š„ๆ˜ฏไปปไฝ•ๅฏไปฅๅƒๅ‡ฝๅผไธ€ๆจฃ่ขซ Pythonใ€Œๅ‘ผๅซใ€็š„ๆฑ่ฅฟใ€‚ + +ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹็‰ฉไปถ `something`๏ผˆๅฎƒๅฏ่ƒฝไธๆ˜ฏๅ‡ฝๅผ๏ผ‰๏ผŒ่€Œไฝ ๅฏไปฅๅƒ้€™ๆจฃใ€Œๅ‘ผๅซใ€๏ผˆๅŸท่กŒ๏ผ‰ๅฎƒ๏ผš + +```Python +something() +``` + +ๆˆ–ๆ˜ฏ + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +้‚ฃๅฎƒๅฐฑๆ˜ฏไธ€ๅ€‹ใ€Œcallableใ€ใ€‚ + +## ไปฅ้กžๅˆฅไฝœ็‚บ็›ธไพๆ€ง { #classes-as-dependencies_1 } + +ไฝ ๅฏ่ƒฝๅทฒ็ถ“ๆณจๆ„ๅˆฐ๏ผŒๅปบ็ซ‹ไธ€ๅ€‹ Python ้กžๅˆฅ็š„ๅฏฆไพ‹ๆ™‚๏ผŒไฝ ็”จ็š„่ชžๆณ•ไนŸๆ˜ฏไธ€ๆจฃ็š„ใ€‚ + +ไพ‹ๅฆ‚๏ผš + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ`fluffy` ๆ˜ฏ `Cat` ้กžๅˆฅ็š„ไธ€ๅ€‹ๅฏฆไพ‹ใ€‚ + +่€Œ่ฆๅปบ็ซ‹ `fluffy`๏ผŒไฝ ๅ…ถๅฏฆๆ˜ฏๅœจใ€Œๅ‘ผๅซใ€`Cat`ใ€‚ + +ๆ‰€ไปฅ๏ผŒPython ้กžๅˆฅๆœฌ่บซไนŸๆ˜ฏไธ€็จฎ **callable**ใ€‚ + +ๅ› ๆญค๏ผŒๅœจ **FastAPI** ไธญ๏ผŒไฝ ๅฏไปฅๅฐ‡ Python ้กžๅˆฅไฝœ็‚บ็›ธไพๆ€งใ€‚ + +FastAPI ๅ…ถๅฏฆๆชขๆŸฅ็š„ๆ˜ฏๅฎƒๆ˜ฏๅฆ็‚บใ€Œcallableใ€๏ผˆๅ‡ฝๅผใ€้กžๅˆฅๆˆ–ๅ…ถไป–๏ผ‰๏ผŒไปฅๅŠๅฎƒๆ‰€ๅฎš็พฉ็š„ๅƒๆ•ธใ€‚ + +ๅฆ‚ๆžœไฝ ๅœจ **FastAPI** ไธญๅ‚ณๅ…ฅไธ€ๅ€‹ใ€Œcallableใ€ไฝœ็‚บ็›ธไพๆ€ง๏ผŒFastAPI ๆœƒๅˆ†ๆž่ฉฒใ€Œcallableใ€็š„ๅƒๆ•ธ๏ผŒไธฆไปฅ่ˆ‡่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผๅƒๆ•ธ็›ธๅŒ็š„ๆ–นๅผไพ†่™•็†ๅฎƒๅ€‘๏ผŒๅŒ…ๆ‹ฌๅญ็›ธไพๆ€งใ€‚ + +้€™ไนŸ้ฉ็”จๆ–ผๅฎŒๅ…จๆฒ’ๆœ‰ๅƒๆ•ธ็š„ callable๏ผŒๅฐฑๅ’Œๆฒ’ๆœ‰ๅƒๆ•ธ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธ€ๆจฃใ€‚ + +ๆŽฅ่‘—๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๆŠŠไธŠ้ข็š„็›ธไพ้ …๏ผˆdependable๏ผ‰`common_parameters` ๆ”นๆˆ้กžๅˆฅ `CommonQueryParams`๏ผš + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +ๆณจๆ„็”จไพ†ๅปบ็ซ‹่ฉฒ้กžๅˆฅๅฏฆไพ‹็š„ `__init__` ๆ–นๆณ•๏ผš + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +...ๅฎƒ็š„ๅƒๆ•ธ่ˆ‡ๆˆ‘ๅ€‘ไน‹ๅ‰็š„ `common_parameters` ็›ธๅŒ๏ผš + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +**FastAPI** ๆœƒ็”จ้€™ไบ›ๅƒๆ•ธไพ†ใ€Œ่งฃๆžใ€่ฉฒ็›ธไพๆ€งใ€‚ + +ๅ…ฉ็จฎๆƒ…ๆณไธ‹้ƒฝๆœƒๆœ‰๏ผš + +- ไธ€ๅ€‹ๅฏ้ธ็š„ๆŸฅ่ฉขๅƒๆ•ธ `q`๏ผŒๅž‹ๅˆฅ็‚บ `str`ใ€‚ +- ไธ€ๅ€‹ๆŸฅ่ฉขๅƒๆ•ธ `skip`๏ผŒๅž‹ๅˆฅ็‚บ `int`๏ผŒ้ ่จญ็‚บ `0`ใ€‚ +- ไธ€ๅ€‹ๆŸฅ่ฉขๅƒๆ•ธ `limit`๏ผŒๅž‹ๅˆฅ็‚บ `int`๏ผŒ้ ่จญ็‚บ `100`ใ€‚ + +ๅ…ฉ็จฎๆƒ…ๆณไธ‹๏ผŒ่ณ‡ๆ–™้ƒฝๆœƒ่ขซ่ฝ‰ๆ›ใ€้ฉ—่ญ‰๏ผŒไธฆ่จ˜้Œ„ๅˆฐ OpenAPI schema ไธญ็ญ‰ใ€‚ + +## ๅฆ‚ไฝ•ไฝฟ็”จ { #use-it } + +็พๅœจไฝ ๅฏไปฅ็”จ้€™ๅ€‹้กžๅˆฅไพ†ๅฎฃๅ‘Šไฝ ็š„็›ธไพๆ€งใ€‚ + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI** ๆœƒๅ‘ผๅซ `CommonQueryParams` ้กžๅˆฅใ€‚้€™ๆœƒๅปบ็ซ‹่ฉฒ้กžๅˆฅ็š„ไธ€ๅ€‹ใ€Œๅฏฆไพ‹ใ€๏ผŒ่€Œ่ฉฒๅฏฆไพ‹ๆœƒไปฅๅƒๆ•ธ `commons` ็š„ๅฝขๅผๅ‚ณ็ตฆไฝ ็š„ๅ‡ฝๅผใ€‚ + +## ๅž‹ๅˆฅ่จป่งฃ่ˆ‡ `Depends` { #type-annotation-vs-depends } + +ๆณจๆ„ไธŠ้ข็จ‹ๅผ็ขผ่ฃกๆˆ‘ๅ€‘ๅฏซไบ†ๅ…ฉๆฌก `CommonQueryParams`๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +ๆœ€ๅพŒ้ข็š„ `CommonQueryParams`๏ผŒๅœจ๏ผš + +```Python +... Depends(CommonQueryParams) +``` + +...ๆ‰ๆ˜ฏ **FastAPI** ๅฏฆ้š›็”จไพ†็Ÿฅ้“็›ธไพๆ€งๆ˜ฏไป€้บผ็š„ไพๆ“šใ€‚ + +FastAPI ๆœƒๅพž้€™ๅ€‹็‰ฉไปถไธญๆๅ–ๅฎฃๅ‘Š็š„ๅƒๆ•ธ๏ผŒไธฆไธ”ๅฏฆ้š›ๅ‘ผๅซๅฎƒใ€‚ + +--- + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅ‰้ข็š„ `CommonQueryParams`๏ผŒๆ–ผ๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +...ๅฐ **FastAPI** ไพ†่ชชๆฒ’ๆœ‰ไปปไฝ•็‰นๆฎŠๆ„็พฉใ€‚FastAPI ไธๆœƒ็”จๅฎƒไพ†ๅš่ณ‡ๆ–™่ฝ‰ๆ›ใ€้ฉ—่ญ‰็ญ‰๏ผˆๅ› ็‚บ้€™้ƒจๅˆ†็”ฑ `Depends(CommonQueryParams)` ่™•็†๏ผ‰ใ€‚ + +ๅ…ถๅฏฆไฝ ๅฏไปฅๅชๅฏซ๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +...ๅƒๆ˜ฏ๏ผš + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +ไฝ†ไปๅปบ่ญฐๅฎฃๅ‘Šๅž‹ๅˆฅ๏ผŒ้€™ๆจฃไฝ ็š„็ทจ่ผฏๅ™จๅฐฑ็Ÿฅ้“ๆœƒไปฅไฝ•็จฎๅž‹ๅˆฅไฝœ็‚บๅƒๆ•ธ `commons` ๅ‚ณๅ…ฅ๏ผŒ้€ฒ่€ŒๅนซๅŠฉไฝ ๅš่‡ชๅ‹•ๅฎŒๆˆใ€ๅž‹ๅˆฅๆชขๆŸฅ็ญ‰๏ผš + + + +## ๆทๅพ‘ { #shortcut } + +ไธ้Žไฝ ๆœƒ็™ผ็พ้€™่ฃกๆœ‰ไบ›้‡่ค‡็จ‹ๅผ็ขผ๏ผŒๆˆ‘ๅ€‘ๅฏซไบ†ๅ…ฉๆฌก `CommonQueryParams`๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI** ็‚บ้€™้กžๆƒ…ๆณๆไพ›ไบ†ไธ€ๅ€‹ๆทๅพ‘๏ผš็•ถ็›ธไพๆ€งใ€Œๆ˜Ž็ขบใ€ๆ˜ฏไธ€ๅ€‹้กžๅˆฅ๏ผŒไธ” **FastAPI** ๆœƒใ€Œๅ‘ผๅซใ€ๅฎƒไพ†ๅปบ็ซ‹่ฉฒ้กžๅˆฅ็š„ๅฏฆไพ‹ๆ™‚ใ€‚ + +ๅฐ้€™ไบ›็‰นๅฎšๆƒ…ๆณ๏ผŒไฝ ๅฏไปฅ้€™ๆจฃๅš๏ผš + +ไธ่ฆๅฏซ๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +...่€Œๆ˜ฏๆ”น็‚บ๏ผš + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.10+ ้ž Annotated + +/// tip + +ๅฆ‚ๆœ‰ๅฏ่ƒฝ๏ผŒๅ„ชๅ…ˆไฝฟ็”จ `Annotated` ็‰ˆๆœฌใ€‚ + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +ไฝ ๆŠŠ็›ธไพๆ€งๅฎฃๅ‘Š็‚บๅƒๆ•ธ็š„ๅž‹ๅˆฅ๏ผŒไธฆไฝฟ็”จไธๅธถไปปไฝ•ๅƒๆ•ธ็š„ `Depends()`๏ผŒ่€Œไธ็”จๅœจ `Depends(CommonQueryParams)` ่ฃกใ€Œๅ†ใ€ๅฏซไธ€ๆฌกๆ•ดๅ€‹้กžๅˆฅใ€‚ + +ๆ•ดๅ€‹็ฏ„ไพ‹ๅฐฑๆœƒ่ฎŠๆˆ๏ผš + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +...่€Œ **FastAPI** ๆœƒ็Ÿฅ้“่ฉฒๆ€Ž้บผๅšใ€‚ + +/// tip + +ๅฆ‚ๆžœไฝ ่ฆบๅพ—้€™ๆจฃๆฏ”ๅนซๅŠฉๆ›ดไปคไบบๅ›ฐๆƒ‘๏ผŒ้‚ฃๅฐฑๅฟฝ็•ฅๅฎƒๅง๏ผŒไฝ ไธฆไธใ€Œ้œ€่ฆใ€้€™ๅ€‹ๆŠ€ๅทงใ€‚ + +้€™ๅชๆ˜ฏๅ€‹ๆทๅพ‘ใ€‚ๅ› ็‚บ **FastAPI** ๅœจๆ„ๅนซไฝ ๆธ›ๅฐ‘้‡่ค‡็š„็จ‹ๅผ็ขผใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 0000000000..e30c385375 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จไธญ็š„ไพ่ณด { #dependencies-in-path-operation-decorators } + +ๆœ‰ๆ™‚ๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญ๏ผŒๅ…ถๅฏฆไธ้œ€่ฆๆŸๅ€‹ไพ่ณด็š„ๅ›žๅ‚ณๅ€ผใ€‚ + +ๆˆ–ๆ˜ฏ่ฉฒไพ่ณดๆ นๆœฌๆฒ’ๆœ‰ๅ›žๅ‚ณๅ€ผใ€‚ + +ไฝ†ไฝ ไป้œ€่ฆๅฎƒ่ขซๅŸท่กŒ๏ผ่งฃๆžใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไธๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ็š„ๅƒๆ•ธไธŠไฝฟ็”จ `Depends`๏ผŒ่€Œๆ˜ฏๅœจ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จๅŠ ๅ…ฅไธ€ๅ€‹ `dependencies` ็š„ `list`ใ€‚ + +## ๅœจ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จๅŠ ๅ…ฅ `dependencies` { #add-dependencies-to-the-path-operation-decorator } + +่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จๅฏๆŽฅๅ—ไธ€ๅ€‹ๅฏ้ธๅƒๆ•ธ `dependencies`ใ€‚ + +ๅฎƒๆ‡‰่ฉฒๆ˜ฏ็”ฑ `Depends()` ็ต„ๆˆ็š„ `list`๏ผš + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} + +้€™ไบ›ไพ่ณดๆœƒไปฅ่ˆ‡ไธ€่ˆฌไพ่ณด็›ธๅŒ็š„ๆ–นๅผ่ขซๅŸท่กŒ๏ผ่งฃๆžใ€‚ไฝ†ๅฎƒๅ€‘็š„ๅ€ผ๏ผˆๅฆ‚ๆžœๆœ‰ๅ›žๅ‚ณ๏ผ‰ไธๆœƒๅ‚ณ้ž็ตฆไฝ ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€‚ + +/// tip + +ๆœ‰ไบ›็ทจ่ผฏๅ™จๆœƒๆชขๆŸฅๆœชไฝฟ็”จ็š„ๅ‡ฝๅผๅƒๆ•ธ๏ผŒไธฆๅฐ‡ๅ…ถๆจ™็คบ็‚บ้Œฏ่ชคใ€‚ + +ๆŠŠ้€™ไบ›ไพ่ณดๆ”พๅœจ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จไธญ๏ผŒๅฏไปฅ็ขบไฟๅฎƒๅ€‘่ขซๅŸท่กŒ๏ผŒๅŒๆ™‚้ฟๅ…็ทจ่ผฏๅ™จ๏ผๅทฅๅ…ทๅ ฑ้Œฏใ€‚ + +้€™ไนŸๆœ‰ๅŠฉๆ–ผ้ฟๅ…่ฎ“ๆ–ฐๅŠ ๅ…ฅ็š„้–‹็™ผ่€…็œ‹ๅˆฐๆœชไฝฟ็”จ็š„ๅƒๆ•ธๆ™‚๏ผŒไปฅ็‚บๅฎƒๆ˜ฏไธๅฟ…่ฆ็š„่€Œๆ„Ÿๅˆฐๅ›ฐๆƒ‘ใ€‚ + +/// + +/// info + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญๆˆ‘ๅ€‘ไฝฟ็”จไบ†่‡ช่จ‚็š„๏ผˆ่™›ๆง‹็š„๏ผ‰ๆจ™้ ญ `X-Key` ่ˆ‡ `X-Token`ใ€‚ + +ไฝ†ๅœจๅฏฆ้š›ๆƒ…ๆณไธ‹๏ผŒ็•ถไฝ ๅฏฆไฝœๅฎ‰ๅ…จๆฉŸๅˆถๆ™‚๏ผŒไฝฟ็”จๆ•ดๅˆ็š„ [Security utilities๏ผˆไธ‹ไธ€็ซ ๏ผ‰](../security/index.md){.internal-link target=_blank} ๆœƒ็ฒๅพ—ๆ›ดๅคšๅฅฝ่™•ใ€‚ + +/// + +## ไพ่ณด็š„้Œฏ่ชค่ˆ‡ๅ›žๅ‚ณๅ€ผ { #dependencies-errors-and-return-values } + +ไฝ ๅฏไปฅไฝฟ็”จ่ˆ‡ๅนณๅธธ็›ธๅŒ็š„ไพ่ณดๅ‡ฝๅผใ€‚ + +### ไพ่ณด็š„้œ€ๆฑ‚ { #dependency-requirements } + +ๅฎƒๅ€‘ๅฏไปฅๅฎฃๅ‘Š่ซ‹ๆฑ‚้œ€ๆฑ‚๏ผˆไพ‹ๅฆ‚ๆจ™้ ญ๏ผˆheaders๏ผ‰๏ผ‰ๆˆ–ๅ…ถไป–ๅญไพ่ณด๏ผš + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} + +### ๆ‹‹ๅ‡บไพ‹ๅค– { #raise-exceptions } + +้€™ไบ›ไพ่ณดๅฏไปฅ `raise` ไพ‹ๅค–๏ผŒ่ˆ‡ไธ€่ˆฌไพ่ณด็›ธๅŒ๏ผš + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} + +### ๅ›žๅ‚ณๅ€ผ { #return-values } + +ๅฎƒๅ€‘ๅฏไปฅๅ›žๅ‚ณๅ€ผ๏ผŒไนŸๅฏไปฅไธๅ›žๅ‚ณ๏ผ›็„ก่ซ–ๅฆ‚ไฝ•๏ผŒๅ›žๅ‚ณๅ€ผ้ƒฝไธๆœƒ่ขซไฝฟ็”จใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ้‡่ค‡ไฝฟ็”จๅœจๅ…ถไป–ๅœฐๆ–นๅทฒไฝฟ็”จ้Ž็š„ไธ€่ˆฌไพ่ณด๏ผˆๆœƒๅ›žๅ‚ณๅ€ผ๏ผ‰๏ผŒๅณไฝฟๅ›žๅ‚ณๅ€ผไธๆœƒ่ขซไฝฟ็”จ๏ผŒ่ฉฒไพ่ณดไปๆœƒ่ขซๅŸท่กŒ๏ผš + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} + +## ไธ€็ต„่ทฏๅพ‘ๆ“ไฝœ็š„ไพ่ณด { #dependencies-for-a-group-of-path-operations } + +ไน‹ๅพŒๅœจ้–ฑ่ฎ€ๅฆ‚ไฝ•็ต„็น”่ผƒๅคง็š„ๆ‡‰็”จ็จ‹ๅผ๏ผˆ[่ผƒๅคงๅž‹ๆ‡‰็”จ็จ‹ๅผโ€”โ€”ๅคšๅ€‹ๆช”ๆกˆ](../../tutorial/bigger-applications.md){.internal-link target=_blank}๏ผ‰ๆ™‚๏ผŒไฝ ๆœƒๅญธๅˆฐๅฆ‚ไฝ•็‚บไธ€็ต„่ทฏๅพ‘ๆ“ไฝœๅฎฃๅ‘Šไธ€ๅ€‹ๅ…ฑๅŒ็š„ `dependencies` ๅƒๆ•ธใ€‚ + +## ๅ…จๅŸŸไพ่ณด { #global-dependencies } + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๆœƒ็œ‹็œ‹ๅฆ‚ไฝ•ๆŠŠไพ่ณดๅŠ ๅˆฐๆ•ดๅ€‹ `FastAPI` ๆ‡‰็”จ็จ‹ๅผ๏ผŒไฝฟๅ…ถๅฅ—็”จๅˆฐๆฏๅ€‹่ทฏๅพ‘ๆ“ไฝœใ€‚ diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 0000000000..2339c6ef30 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,288 @@ +# ไฝฟ็”จ yield ็š„็›ธไพ { #dependencies-with-yield } + +FastAPI ๆ”ฏๆดๅœจๅฎŒๆˆๅพŒๅŸท่กŒไธ€ไบ›้กๅค–ๆญฅ้ฉŸ็š„็›ธไพใ€‚ + +่ฆๅšๅˆฐ้€™้ปž๏ผŒไฝฟ็”จ `yield` ๅ–ไปฃ `return`๏ผŒไธฆๆŠŠ้กๅค–ๆญฅ้ฉŸ๏ผˆ็จ‹ๅผ็ขผ๏ผ‰ๅฏซๅœจๅ…ถๅพŒใ€‚ + +/// tip + +่ซ‹็ขบไฟๆฏๅ€‹็›ธไพๅ…งๅชไฝฟ็”จไธ€ๆฌก `yield`ใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไปปไฝ•ๅฏ็”จๆ–ผไธ‹ๅˆ—่ฃ้ฃพๅ™จ็š„ๅ‡ฝๅผ๏ผš + +* `@contextlib.contextmanager` ๆˆ– +* `@contextlib.asynccontextmanager` + +้ƒฝๅฏไปฅไฝœ็‚บ **FastAPI** ็š„็›ธไพใ€‚ + +ไบ‹ๅฏฆไธŠ๏ผŒFastAPI ๅ…ง้ƒจๅฐฑๆ˜ฏไฝฟ็”จ้€™ๅ…ฉๅ€‹่ฃ้ฃพๅ™จใ€‚ + +/// + +## ไฝฟ็”จ `yield` ็š„่ณ‡ๆ–™ๅบซ็›ธไพ { #a-database-dependency-with-yield } + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒๅปบ็ซ‹ไธ€ๅ€‹่ณ‡ๆ–™ๅบซ session๏ผŒไธฆๅœจๅฎŒๆˆๅพŒ้—œ้–‰ใ€‚ + +ๅชๆœ‰ `yield` ไน‹ๅ‰๏ผˆๅซ `yield` ๆœฌ่บซ๏ผ‰็š„็จ‹ๅผ็ขผๆœƒๅœจ็”ข็”Ÿๅ›žๆ‡‰ไน‹ๅ‰ๅŸท่กŒ๏ผš + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} + +็”ฑ `yield` ็”ข็”Ÿ็š„ๅ€ผๆœƒ่ขซๆณจๅ…ฅๅˆฐ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰่ˆ‡ๅ…ถไป–็›ธไพไธญ๏ผš + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} + +ไฝๆ–ผ `yield` ไน‹ๅพŒ็š„็จ‹ๅผ็ขผๆœƒๅœจๅ›žๆ‡‰ไน‹ๅพŒๅŸท่กŒ๏ผš + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} + +/// tip + +ไฝ ๅฏไปฅไฝฟ็”จ `async` ๆˆ–ไธ€่ˆฌๅ‡ฝๅผใ€‚ + +**FastAPI** ้ƒฝๆœƒๆญฃ็ขบ่™•็†๏ผŒๅ’Œไธ€่ˆฌ็›ธไพ็›ธๅŒใ€‚ + +/// + +## ๅŒๆ™‚ไฝฟ็”จ `yield` ่ˆ‡ `try` ็š„็›ธไพ { #a-dependency-with-yield-and-try } + +ๅฆ‚ๆžœๅœจๅซ `yield` ็š„็›ธไพไธญไฝฟ็”จ `try` ๅ€ๅกŠ๏ผŒไฝ ๆœƒๆŽฅๆ”ถๅˆฐไฝฟ็”จ่ฉฒ็›ธไพๆ™‚ๆ‹‹ๅ‡บ็š„ไปปไฝ•ไพ‹ๅค–ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœๅœจไธญ้€”็š„ๆŸๆฎต็จ‹ๅผ็ขผใ€ๅ…ถไป–็›ธไพ๏ผŒๆˆ–ๆŸๅ€‹่ทฏๅพ‘ๆ“ไฝœไธญ๏ผŒ่ฎ“่ณ‡ๆ–™ๅบซไบคๆ˜“ใ€Œrollbackใ€ๆˆ–็”ข็”Ÿไบ†ไปปไฝ•ไพ‹ๅค–๏ผŒไฝ ้ƒฝๆœƒๅœจไฝ ็š„็›ธไพไธญๆŽฅๆ”ถๅˆฐ่ฉฒไพ‹ๅค–ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅœจ็›ธไพๅ…ง็”จ `except SomeException` ไพ†ๆ””ๆˆช็‰นๅฎšไพ‹ๅค–ใ€‚ + +ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `finally` ไพ†็ขบไฟ็„ก่ซ–ๆ˜ฏๅฆๆœ‰ไพ‹ๅค–้ƒฝๆœƒๅŸท่กŒ็ตๆŸๆญฅ้ฉŸใ€‚ + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} + +## ๅซ `yield` ็š„ๅญ็›ธไพ { #sub-dependencies-with-yield } + +ไฝ ๅฏไปฅๆ“ๆœ‰ไปปไฝ•ๅคงๅฐ่ˆ‡ๅฝข็‹€็š„ๅญ็›ธไพ่ˆ‡็›ธไพๆจน๏ผŒ่€Œๅฎƒๅ€‘้ƒฝๅฏไปฅ๏ผˆๆˆ–ไธ๏ผ‰ไฝฟ็”จ `yield`ใ€‚ + +**FastAPI** ๆœƒ็ขบไฟๆฏๅ€‹ไฝฟ็”จ `yield` ็š„็›ธไพ๏ผŒๅ…ถใ€Œ็ตๆŸ็จ‹ๅผ็ขผใ€ๆœƒไปฅๆญฃ็ขบ็š„้ †ๅบๅŸท่กŒใ€‚ + +ไพ‹ๅฆ‚๏ผŒ`dependency_c` ๅฏไปฅ็›ธไพๆ–ผ `dependency_b`๏ผŒ่€Œ `dependency_b` ็›ธไพๆ–ผ `dependency_a`๏ผš + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} + +่€Œไธ”ๅฎƒๅ€‘้ƒฝๅฏไปฅไฝฟ็”จ `yield`ใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ`dependency_c` ็‚บไบ†ๅŸท่กŒๅฎƒ็š„็ตๆŸ็จ‹ๅผ็ขผ๏ผŒ้œ€่ฆไพ†่‡ช `dependency_b`๏ผˆๆญค่™•ๅ‘ฝๅ็‚บ `dep_b`๏ผ‰็š„ๅ€ผไป็„ถๅฏ็”จใ€‚ + +ๅŒ็†๏ผŒ`dependency_b` ็‚บไบ†ๅŸท่กŒๅฎƒ็š„็ตๆŸ็จ‹ๅผ็ขผ๏ผŒ้œ€่ฆไพ†่‡ช `dependency_a`๏ผˆๆญค่™•ๅ‘ฝๅ็‚บ `dep_a`๏ผ‰็š„ๅ€ผๅฏ็”จใ€‚ + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} + +ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅๅŒๆ™‚ๆ“ๆœ‰ไฝฟ็”จ `yield` ็š„็›ธไพ่ˆ‡ไฝฟ็”จ `return` ็š„็›ธไพ๏ผŒไธฆ่ฎ“ๅ…ถไธญไธ€ไบ›็›ธไพๅฝผๆญค็›ธไพใ€‚ + +ไฝ ไนŸๅฏไปฅๆœ‰ไธ€ๅ€‹็›ธไพๅŒๆ™‚้œ€่ฆๅคšๅ€‹ไฝฟ็”จ `yield` ็š„ๅ…ถไป–็›ธไพ๏ผŒ็ญ‰็ญ‰ใ€‚ + +ไฝ ๅฏไปฅๆ“ๆœ‰ไปปไฝ•ไฝ ้œ€่ฆ็š„็›ธไพ็ต„ๅˆใ€‚ + +**FastAPI** ๆœƒ็ขบไฟไธ€ๅˆ‡้ƒฝไปฅๆญฃ็ขบ็š„้ †ๅบๅŸท่กŒใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +้€™่ƒฝ้‹ไฝœ๏ผŒๅคš่™งไบ† Python ็š„ Context Managersใ€‚ + +**FastAPI** ๅœจๅ…ง้ƒจไฝฟ็”จๅฎƒๅ€‘ไพ†้”ๆˆ้€™้ปžใ€‚ + +/// + +## ๅซ `yield` ่ˆ‡ `HTTPException` ็š„็›ธไพ { #dependencies-with-yield-and-httpexception } + +ไฝ ๅทฒ็œ‹ๅˆฐๅฏไปฅๅœจๅซ `yield` ็š„็›ธไพไธญไฝฟ็”จ `try` ๅ€ๅกŠ๏ผŒๅ˜—่ฉฆๅŸท่กŒไธ€ไบ›็จ‹ๅผ็ขผ๏ผŒ็„ถๅพŒๅœจ `finally` ๅพŒๅŸท่กŒ็ตๆŸ็จ‹ๅผ็ขผใ€‚ + +ไฝ ไนŸๅฏไปฅ็”จ `except` ไพ†ๆ””ๆˆช่ขซๆ‹‹ๅ‡บ็š„ไพ‹ๅค–ไธฆๅŠ ไปฅ่™•็†ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆ‹‹ๅ‡บไธๅŒ็š„ไพ‹ๅค–๏ผŒๅฆ‚ `HTTPException`ใ€‚ + +/// tip + +้€™็ฎ—ๆ˜ฏ้€ฒ้šŽๆŠ€ๅทง๏ผ›ๅคšๆ•ธๆƒ…ๆณไฝ ไธฆไธ้œ€่ฆ๏ผŒๅ› ็‚บไฝ ๅฏไปฅๅœจๆ‡‰็”จ็จ‹ๅผๅ…ถไป–็จ‹ๅผ็ขผไธญ๏ผˆไพ‹ๅฆ‚ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰ไธญ๏ผ‰็›ดๆŽฅๆ‹‹ๅ‡บไพ‹ๅค–๏ผˆๅŒ…ๅซ `HTTPException`๏ผ‰ใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ้œ€่ฆ๏ผŒๅฎƒๅฐฑๅœจ้€™่ฃกใ€‚๐Ÿค“ + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} + +ๅฆ‚ๆžœไฝ ๆƒณๆ””ๆˆชไพ‹ๅค–ไธฆๆ“šๆญคๅ›žๅ‚ณ่‡ช่จ‚ๅ›žๆ‡‰๏ผŒ่ซ‹ๅปบ็ซ‹ไธ€ๅ€‹[่‡ช่จ‚ไพ‹ๅค–่™•็†ๅ™จ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ใ€‚ + +## ๅซ `yield` ่ˆ‡ `except` ็š„็›ธไพ { #dependencies-with-yield-and-except } + +ๅฆ‚ๆžœไฝ ๅœจๅซ `yield` ็š„็›ธไพไธญ็”จ `except` ๆ””ๆˆชไบ†ไพ‹ๅค–๏ผŒไธ”ๆฒ’ๆœ‰ๅ†ๆฌกๆ‹‹ๅ‡บๅฎƒ๏ผˆๆˆ–ๆ‹‹ๅ‡บๆ–ฐ็š„ไพ‹ๅค–๏ผ‰๏ผŒFastAPI ๅฐ‡็„กๆณ•ๅฏŸ่ฆบๆœ‰ไพ‹ๅค–็™ผ็”Ÿ๏ผŒๅฐฑๅƒๅœจไธ€่ˆฌ็š„ Python ไธญไธ€ๆจฃ๏ผš + +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฎขๆˆถ็ซฏๆœƒๅฆ‚้ ๆœŸๅœฐ็œ‹ๅˆฐไธ€ๅ€‹ *HTTP 500 Internal Server Error* ๅ›žๆ‡‰๏ผˆๅ› ็‚บๆˆ‘ๅ€‘ๆฒ’ๆœ‰ๆ‹‹ๅ‡บ `HTTPException` ๆˆ–้กžไผผ็š„ๆฑ่ฅฟ๏ผ‰๏ผŒไฝ†ไผบๆœๅ™จๅฐ‡ไธๆœƒๆœ‰ไปปไฝ•ๆ—ฅ่ชŒๆˆ–ๅ…ถไป–้Œฏ่ชค็ทš็ดขใ€‚๐Ÿ˜ฑ + +### ๅœจๅซ `yield` ่ˆ‡ `except` ็š„็›ธไพไธญๅ‹™ๅฟ… `raise` { #always-raise-in-dependencies-with-yield-and-except } + +ๅฆ‚ๆžœไฝ ๅœจๅซ `yield` ็š„็›ธไพไธญๆ””ๆˆชๅˆฐไบ†ไพ‹ๅค–๏ผŒ้™ค้žไฝ ่ฆๆ‹‹ๅ‡บๅฆไธ€ๅ€‹ `HTTPException` ๆˆ–้กžไผผ็š„ไพ‹ๅค–๏ผŒๅฆๅ‰‡**ไฝ ๆ‡‰่ฉฒ้‡ๆ–ฐๆ‹‹ๅ‡บๅŽŸๆœฌ็š„ไพ‹ๅค–**ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `raise` ้‡ๆ–ฐๆ‹‹ๅ‡บๅŒไธ€ๅ€‹ไพ‹ๅค–๏ผš + +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} + +็พๅœจๅฎขๆˆถ็ซฏไปๆœƒ็ฒๅพ—ๅŒๆจฃ็š„ *HTTP 500 Internal Server Error* ๅ›žๆ‡‰๏ผŒไฝ†ไผบๆœๅ™จ็š„ๆ—ฅ่ชŒไธญๆœƒๆœ‰ๆˆ‘ๅ€‘่‡ช่จ‚็š„ `InternalError`ใ€‚๐Ÿ˜Ž + +## ๅซ `yield` ็š„็›ธไพๅŸท่กŒ้ †ๅบ { #execution-of-dependencies-with-yield } + +ๅŸท่กŒ้ †ๅบๅคง่‡ดๅฆ‚ไธ‹ๅœ–ใ€‚ๆ™‚้–“ๅพžไธŠๅพ€ไธ‹ๆตๅ‹•๏ผŒๆฏไธ€ๆฌ„ไปฃ่กจไธ€ๅ€‹ไบ’ๅ‹•ๆˆ–ๅŸท่กŒ็จ‹ๅผ็ขผ็š„้ƒจๅˆ†ใ€‚ + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// info + +ๅชๆœƒๅ‘็”จๆˆถ็ซฏ้€ๅ‡บใ€Œไธ€ๅ€‹ๅ›žๆ‡‰ใ€ใ€‚ๅฏ่ƒฝๆ˜ฏๅ…ถไธญไธ€ๅ€‹้Œฏ่ชคๅ›žๆ‡‰๏ผŒๆˆ–ๆ˜ฏไพ†่‡ช่ฉฒ่ทฏๅพ‘ๆ“ไฝœ็š„ๅ›žๆ‡‰ใ€‚ + +ไธ€ๆ—ฆ้€ๅ‡บไบ†ๅ…ถไธญไธ€ๅ€‹ๅ›žๆ‡‰๏ผŒๅฐฑไธ่ƒฝๅ†้€ๅ‡บๅ…ถไป–ๅ›žๆ‡‰ใ€‚ + +/// + +/// tip + +ๅฆ‚ๆžœไฝ ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ็š„็จ‹ๅผ็ขผไธญๆ‹‹ๅ‡บไปปไฝ•ไพ‹ๅค–๏ผŒๅฎƒๆœƒ่ขซๅ‚ณ้žๅˆฐไฝฟ็”จ `yield` ็š„็›ธไพไธญ๏ผˆๅŒ…ๅซ `HTTPException`๏ผ‰ใ€‚ๅคงๅคšๆ•ธๆƒ…ๆณไฝ ๆœƒๆƒณๅœจ่ฉฒไฝฟ็”จ `yield` ็š„็›ธไพไธญ้‡ๆ–ฐๆ‹‹ๅ‡บ็›ธๅŒ็š„ไพ‹ๅค–ๆˆ–ไธ€ๅ€‹ๆ–ฐ็š„ไพ‹ๅค–๏ผŒไปฅ็ขบไฟๅฎƒ่ขซๆญฃ็ขบ่™•็†ใ€‚ + +/// + +## ๆๆ—ฉ้—œ้–‰่ˆ‡ `scope` { #early-exit-and-scope } + +้€šๅธธ๏ผŒๅซ `yield` ็š„็›ธไพไน‹็ตๆŸ็จ‹ๅผ็ขผๆœƒๅœจๅ›žๆ‡‰้€ๅ‡บ็ตฆ็”จๆˆถ็ซฏไน‹ๅพŒๆ‰ๅŸท่กŒใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ็ขบๅฎšๅœจๅพž่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ่ฟ”ๅ›žๅพŒๅฐฑไธๆœƒๅ†ไฝฟ็”จ่ฉฒ็›ธไพ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `Depends(scope="function")`๏ผŒๅ‘Š่จด FastAPI ๆ‡‰ๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ่ฟ”ๅ›žไน‹ๅพŒใ€ไฝ†ๅœจๅ›žๆ‡‰้€ๅ‡บไน‹ๅ‰้—œ้–‰่ฉฒ็›ธไพใ€‚ + +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} + +`Depends()` ๆŽฅๅ—ไธ€ๅ€‹ `scope` ๅƒๆ•ธ๏ผŒๅฏไปฅๆ˜ฏ๏ผš + +* `"function"`๏ผšๅœจ่™•็†่ซ‹ๆฑ‚็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไน‹ๅ‰ๅ•Ÿๅ‹•็›ธไพ๏ผŒๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ็ตๆŸไน‹ๅพŒ็ตๆŸ็›ธไพ๏ผŒไฝ†ๅœจๅ›žๆ‡‰้€ๅ›ž็”จๆˆถ็ซฏไน‹ๅ‰ใ€‚ๆ‰€ไปฅ๏ผŒ็›ธไพๅ‡ฝๅผๆœƒๅœจ่ทฏๅพ‘ๆ“ไฝœ**ๅ‡ฝๅผ**็š„ใ€Œๅ‘จๅœใ€ๅŸท่กŒใ€‚ +* `"request"`๏ผšๅœจ่™•็†่ซ‹ๆฑ‚็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไน‹ๅ‰ๅ•Ÿๅ‹•็›ธไพ๏ผˆ่ˆ‡ไฝฟ็”จ `"function"` ้กžไผผ๏ผ‰๏ผŒไฝ†ๅœจๅ›žๆ‡‰้€ๅ›ž็”จๆˆถ็ซฏไน‹ๅพŒๆ‰็ตๆŸ็›ธไพใ€‚ๆ‰€ไปฅ๏ผŒ็›ธไพๅ‡ฝๅผๆœƒๅœจๆ•ดๅ€‹**่ซ‹ๆฑ‚**่ˆ‡ๅ›žๆ‡‰ๅพช็’ฐ็š„ใ€Œๅ‘จๅœใ€ๅŸท่กŒใ€‚ + +ๅฆ‚ๆžœๆœชๆŒ‡ๅฎšไธ”็›ธไพไฝฟ็”จไบ† `yield`๏ผŒๅ‰‡้ ่จญ `scope` ็‚บ `"request"`ใ€‚ + +### ๅญ็›ธไพ็š„ `scope` { #scope-for-sub-dependencies } + +็•ถไฝ ๅฎฃๅ‘Šไธ€ๅ€‹ `scope="request"`๏ผˆ้ ่จญๅ€ผ๏ผ‰็š„็›ธไพๆ™‚๏ผŒไปปไฝ•ๅญ็›ธไพไนŸ้œ€่ฆๆœ‰ `"request"` ็š„ `scope`ใ€‚ + +ไฝ†ไธ€ๅ€‹ `scope` ็‚บ `"function"` ็š„็›ธไพ๏ผŒๅฏไปฅๆ“ๆœ‰ `scope` ็‚บ `"function"` ๆˆ– `"request"` ็š„ๅญ็›ธไพใ€‚ + +้€™ๆ˜ฏๅ› ็‚บไปปไฝ•็›ธไพ้ƒฝ้œ€่ฆ่ƒฝๅœจๅญ็›ธไพไน‹ๅ‰ๅŸท่กŒๅ…ถ็ตๆŸ็จ‹ๅผ็ขผ๏ผŒๅ› ็‚บๅฎƒๅฏ่ƒฝๅœจ็ตๆŸ็จ‹ๅผ็ขผไธญไป้œ€่ฆไฝฟ็”จ้‚ฃไบ›ๅญ็›ธไพใ€‚ + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` + +## ๅซ `yield`ใ€`HTTPException`ใ€`except` ่ˆ‡่ƒŒๆ™ฏไปปๅ‹™็š„็›ธไพ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +ๅซ `yield` ็š„็›ธไพ้šจๆ™‚้–“ๆผ”้€ฒ๏ผŒไปฅๆถต่“‹ไธๅŒ็š„ไฝฟ็”จๆƒ…ๅขƒไธฆไฟฎๆญฃไธ€ไบ›ๅ•้กŒใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณไบ†่งฃๅœจไธๅŒ FastAPI ็‰ˆๆœฌไธญๆ”นไบ†ๅ“ชไบ›ๅ…งๅฎน๏ผŒๅฏไปฅๅœจ้€ฒ้šŽๆŒ‡ๅ—ไธญ้–ฑ่ฎ€๏ผš[้€ฒ้šŽ็›ธไพ โ€” ๅซ `yield`ใ€`HTTPException`ใ€`except` ่ˆ‡่ƒŒๆ™ฏไปปๅ‹™็š„็›ธไพ](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}ใ€‚ +## ๆƒ…ๅขƒ็ฎก็†ๅ™จ { #context-managers } + +### ไป€้บผๆ˜ฏใ€Œๆƒ…ๅขƒ็ฎก็†ๅ™จใ€ { #what-are-context-managers } + +ใ€Œๆƒ…ๅขƒ็ฎก็†ๅ™จใ€ๆ˜ฏ้‚ฃไบ›ไฝ ๅฏไปฅๅœจ `with` ้™ณ่ฟฐๅผไธญไฝฟ็”จ็š„ Python ็‰ฉไปถใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จ `with` ไพ†่ฎ€ๅ–ๆช”ๆกˆ๏ผš + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +ๅœจๅบ•ๅฑค๏ผŒ`open("./somefile.txt")` ๆœƒๅปบ็ซ‹ไธ€ๅ€‹็จฑ็‚บใ€Œๆƒ…ๅขƒ็ฎก็†ๅ™จใ€็š„็‰ฉไปถใ€‚ + +็•ถ `with` ๅ€ๅกŠ็ตๆŸๆ™‚๏ผŒๅฎƒๆœƒ็ขบไฟ้—œ้–‰ๆช”ๆกˆ๏ผŒๅณไฝฟ็™ผ็”Ÿไบ†ไพ‹ๅค–ไนŸไธ€ๆจฃใ€‚ + +็•ถไฝ ๅปบ็ซ‹ไธ€ๅ€‹ๅซ `yield` ็š„็›ธไพๆ™‚๏ผŒ**FastAPI** ๆœƒๅœจๅ…ง้ƒจ็‚บๅฎƒๅปบ็ซ‹ไธ€ๅ€‹ๆƒ…ๅขƒ็ฎก็†ๅ™จ๏ผŒไธฆ่ˆ‡ๅ…ถไป–็›ธ้—œๅทฅๅ…ท็ตๅˆใ€‚ + +### ๅœจๅซ `yield` ็š„็›ธไพไธญไฝฟ็”จๆƒ…ๅขƒ็ฎก็†ๅ™จ { #using-context-managers-in-dependencies-with-yield } + +/// warning + +้€™ๅคง่‡ด็ฎ—ๆ˜ฏไธ€ๅ€‹ใ€Œ้€ฒ้šŽใ€ๆฆ‚ๅฟตใ€‚ + +ๅฆ‚ๆžœไฝ ๅ‰›้–‹ๅง‹ๅญธ็ฟ’ **FastAPI**๏ผŒๆญค่™•ๅฏไปฅๅ…ˆ่ทณ้Žใ€‚ + +/// + +ๅœจ Python ไธญ๏ผŒไฝ ๅฏไปฅ้€้Žๅปบ็ซ‹ไธ€ๅ€‹ๆ“ๆœ‰ `__enter__()` ่ˆ‡ `__exit__()` ๅ…ฉๅ€‹ๆ–นๆณ•็š„้กžๅˆฅไพ†ๅปบ็ซ‹ๆƒ…ๅขƒ็ฎก็†ๅ™จใ€‚ + +ไฝ ไนŸๅฏไปฅๅœจ **FastAPI** ็š„ๅซ `yield` ็›ธไพไธญ๏ผŒๆ–ผ็›ธไพๅ‡ฝๅผๅ…งไฝฟ็”จ `with` ๆˆ– `async with` ้™ณ่ฟฐๅผไพ†ไฝฟ็”จๅฎƒๅ€‘๏ผš + +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} + +/// tip + +ๅปบ็ซ‹ๆƒ…ๅขƒ็ฎก็†ๅ™จ็š„ๅฆไธ€็จฎๆ–นๅผๆ˜ฏ๏ผš + +* `@contextlib.contextmanager` ๆˆ– +* `@contextlib.asynccontextmanager` + +็”จๅฎƒๅ€‘่ฃ้ฃพไธ€ๅ€‹ๅชๅŒ…ๅซๅ–ฎไธ€ `yield` ็š„ๅ‡ฝๅผใ€‚ + +้€™ๆญฃๆ˜ฏ **FastAPI** ๅœจๅ…ง้ƒจ็‚บๅซ `yield` ็š„็›ธไพๆ‰€ไฝฟ็”จ็š„ๆ–นๆณ•ใ€‚ + +ไฝ†ไฝ ไธ้œ€่ฆ๏ผˆ่€Œไธ”ไนŸไธ่ฉฒ๏ผ‰ๅœจ FastAPI ็š„็›ธไพไธŠไฝฟ็”จ้€™ไบ›่ฃ้ฃพๅ™จใ€‚ + +FastAPI ๆœƒๅœจๅ…ง้ƒจๆ›ฟไฝ ่™•็†ๅฅฝใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md b/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 0000000000..3aac1a228b --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,15 @@ +# ๅ…จๅŸŸไพ่ณด { #global-dependencies } + +ๅœจๆŸไบ›้กžๅž‹็š„ๆ‡‰็”จ็จ‹ๅผไธญ๏ผŒไฝ ๅฏ่ƒฝๆƒณ็‚บๆ•ดๅ€‹ๆ‡‰็”จ็จ‹ๅผๆ–ฐๅขžไพ่ณดใ€‚ + +้กžไผผๆ–ผไฝ ๅฏไปฅๅœจ[่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰็š„่ฃ้ฃพๅ™จไธญๆ–ฐๅขž `dependencies`](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ็š„ๆ–นๅผ๏ผŒไฝ ไนŸๅฏไปฅๆŠŠๅฎƒๅ€‘ๅŠ ๅˆฐ `FastAPI` ๆ‡‰็”จ็จ‹ๅผไธŠใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฎƒๅ€‘ๆœƒๅฅ—็”จๅˆฐๆ‡‰็”จ็จ‹ๅผไธญ็š„ๆ‰€ๆœ‰่ทฏๅพ‘ๆ“ไฝœ๏ผš + +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} + +่€Œไธ”๏ผŒๅœจ[ๅฐ‡ `dependencies` ๆ–ฐๅขžๅˆฐ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จ](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ้‚ฃไธ€็ฏ€ไธญ็š„ๆ‰€ๆœ‰ๆฆ‚ๅฟตไพ็„ถ้ฉ็”จ๏ผŒๅชๆ˜ฏ้€™่ฃกๆ˜ฏๅฅ—็”จๅˆฐๆ•ดๅ€‹ๆ‡‰็”จไธญ็š„ๆ‰€ๆœ‰่ทฏๅพ‘ๆ“ไฝœใ€‚ + +## ่ทฏๅพ‘ๆ“ไฝœ็พค็ต„็š„ไพ่ณด { #dependencies-for-groups-of-path-operations } + +ไน‹ๅพŒ๏ผŒๅœจ้–ฑ่ฎ€ๅฆ‚ไฝ•็ต„็น”ๆ›ดๅคง็š„ๆ‡‰็”จ็จ‹ๅผ๏ผˆ[ๆ›ดๅคง็š„ๆ‡‰็”จ็จ‹ๅผ - ๅคšๅ€‹ๆช”ๆกˆ](../../tutorial/bigger-applications.md){.internal-link target=_blank}๏ผ‰ๆ™‚๏ผŒๅฏ่ƒฝๆœƒๆœ‰ๅคšๅ€‹ๆช”ๆกˆ๏ผŒไฝ ๅฐ‡ๆœƒๅญธๅˆฐๅฆ‚ไฝ•็‚บไธ€็ต„่ทฏๅพ‘ๆ“ไฝœๅฎฃๅ‘Šๅ–ฎไธ€็š„ `dependencies` ๅƒๆ•ธใ€‚ diff --git a/docs/zh-hant/docs/tutorial/dependencies/index.md b/docs/zh-hant/docs/tutorial/dependencies/index.md new file mode 100644 index 0000000000..39c05ab056 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/index.md @@ -0,0 +1,248 @@ +# ไพ่ณด { #dependencies } + +**FastAPI** ๅ…งๅปบไธ€ๅฅ—ๅผทๅคงไธ”็›ด่ฆบ็š„ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑใ€‚ + +ๅฎƒ่ขซ่จญ่จˆ็‚บๆ˜“ๆ–ผไฝฟ็”จ๏ผŒไฝฟไปปไฝ•้–‹็™ผ่€…้ƒฝ่ƒฝ่ผ•้ฌ†ๅฐ‡ๅ…ถไป–ๅ…ƒไปถ่ˆ‡ **FastAPI** ๆ•ดๅˆใ€‚ + +## ไป€้บผๆ˜ฏใ€Œไพ่ณดๆณจๅ…ฅใ€ { #what-is-dependency-injection } + +ๅœจ็จ‹ๅผ่จญ่จˆไธญ๏ผŒใ€Œไพ่ณดๆณจๅ…ฅใ€็š„ๆ„ๆ€ๆ˜ฏ๏ผšไฝ ็š„็จ‹ๅผ็ขผ๏ผˆๆญค่™•ๆŒ‡ไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ (path operation functions)ใ€๏ผ‰ๅฏไปฅๅฎฃๅ‘Šๅฎƒ็‚บไบ†ๆญฃๅธธ้‹ไฝœๆ‰€้œ€่ฆ็š„ๅ„็จฎๆฑ่ฅฟ๏ผšไนŸๅฐฑๆ˜ฏใ€Œไพ่ณดใ€ใ€‚ + +ๆŽฅ่‘—๏ผŒ้€™ๅ€‹็ณป็ตฑ๏ผˆๆญค่™•ๆ˜ฏ **FastAPI**๏ผ‰ๆœƒ่ฒ ่ฒฌๅšไปปไฝ•ๅฟ…่ฆ็š„ไบ‹๏ผŒๅฐ‡้€™ไบ›ๆ‰€้œ€็š„ไพ่ณดๆไพ›็ตฆไฝ ็š„็จ‹ๅผ็ขผ๏ผˆใ€Œๆณจๅ…ฅใ€ไพ่ณด๏ผ‰ใ€‚ + +็•ถไฝ ้œ€่ฆไปฅไธ‹ๆƒ…ๅขƒๆ™‚๏ผŒ้€™็‰นๅˆฅๆœ‰็”จ๏ผš + +* ๅ…ฑไบซ้‚่ผฏ๏ผˆ็›ธๅŒ็š„้‚่ผฏไธ€ๆฌกๅˆไธ€ๆฌกๅœฐไฝฟ็”จ๏ผ‰ใ€‚ +* ๅ…ฑ็”จ่ณ‡ๆ–™ๅบซ้€ฃ็ทšใ€‚ +* ๅผทๅˆถๅฅ—็”จๅฎ‰ๅ…จๆ€งใ€้ฉ—่ญ‰ใ€่ง’่‰ฒ่ฆๆฑ‚็ญ‰ใ€‚ +* ไปฅๅŠ่จฑๅคšๅ…ถไป–ไบ‹ๆƒ…... + +ๅŒๆ™‚ๆŠŠ้‡่ค‡็š„็จ‹ๅผ็ขผ้™ๅˆฐๆœ€ไฝŽใ€‚ + +## ๅ…ฅ้–€ { #first-steps } + +ๅ…ˆ็œ‹ไธ€ๅ€‹้žๅธธ็ฐกๅ–ฎ็š„็ฏ„ไพ‹ใ€‚ๅฎƒ็พๅœจ้‚„ไธๅคชๅฏฆ็”จ๏ผŒไฝ†ๅค ็ฐกๅ–ฎ๏ผŒ่ฎ“ๆˆ‘ๅ€‘่ƒฝๅฐˆๆณจๅœจ **ไพ่ณดๆณจๅ…ฅ** ็š„้‹ไฝœๆ–นๅผใ€‚ + +### ๅปบ็ซ‹ไธ€ๅ€‹ไพ่ณด๏ผŒๆˆ–็จฑใ€Œdependableใ€ { #create-a-dependency-or-dependable } + +ๅ…ˆๅฐˆๆณจๅœจไพ่ณดๆœฌ่บซใ€‚ + +ๅฎƒๅฐฑๆ˜ฏไธ€ๅ€‹ๅ‡ฝๅผ๏ผŒๅฏไปฅๆŽฅๅ—่ˆ‡ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็›ธๅŒ็š„ๅ„็จฎๅƒๆ•ธ๏ผš + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +ๅฐฑ้€™ๆจฃใ€‚ + +ๅƒ…ๅƒ…ๅ…ฉ่กŒใ€‚ + +่€Œไธ”ๅฎƒ็š„ๅค–่ง€่ˆ‡็ตๆง‹ๅ’Œไฝ ็š„ๆ‰€ๆœ‰ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธ€ๆจฃใ€‚ + +ไฝ ๅฏไปฅๆŠŠๅฎƒๆƒณๆˆไธ€ๅ€‹ๆฒ’ๆœ‰ใ€Œ่ฃ้ฃพๅ™จใ€๏ผˆๆฒ’ๆœ‰ `@app.get("/some-path")`๏ผ‰็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ใ€‚ + +ๅฎƒๅฏไปฅๅ›žๅ‚ณไฝ ๆƒณ่ฆ็š„ไปปไฝ•ๆฑ่ฅฟใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ้€™ๅ€‹ไพ่ณดๆœƒๆœŸๆœ›๏ผš + +* ไธ€ๅ€‹้ธ็”จ็š„ๆŸฅ่ฉขๅƒๆ•ธ `q`๏ผŒๅž‹ๅˆฅ็‚บ `str`ใ€‚ +* ไธ€ๅ€‹้ธ็”จ็š„ๆŸฅ่ฉขๅƒๆ•ธ `skip`๏ผŒๅž‹ๅˆฅ็‚บ `int`๏ผŒ้ ่จญ็‚บ `0`ใ€‚ +* ไธ€ๅ€‹้ธ็”จ็š„ๆŸฅ่ฉขๅƒๆ•ธ `limit`๏ผŒๅž‹ๅˆฅ็‚บ `int`๏ผŒ้ ่จญ็‚บ `100`ใ€‚ + +็„ถๅพŒๅฎƒๅชๆœƒๅ›žๅ‚ณไธ€ๅ€‹ๅŒ…ๅซ้€™ไบ›ๅ€ผ็š„ `dict`ใ€‚ + +/// info | ่ชชๆ˜Ž + +FastAPI ๅœจ 0.95.0 ็‰ˆๆ–ฐๅขžไบ†ๅฐ `Annotated` ็š„ๆ”ฏๆด๏ผˆไธฆ้–‹ๅง‹ๅปบ่ญฐไฝฟ็”จ๏ผ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ่ผƒ่ˆŠ็š„็‰ˆๆœฌ๏ผŒๅ˜—่ฉฆไฝฟ็”จ `Annotated` ๆ™‚ๆœƒๅ‡บ็พ้Œฏ่ชคใ€‚ + +ๅœจไฝฟ็”จ `Annotated` ไน‹ๅ‰๏ผŒ่ซ‹ๅ…ˆ[ๅ‡็ดš FastAPI ็‰ˆๆœฌ](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ๅˆฐ่‡ณๅฐ‘ 0.95.1ใ€‚ + +/// + +### ๅŒฏๅ…ฅ `Depends` { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### ๅœจใ€Œ่ขซไพ่ณด่€…ใ€๏ผˆdependant๏ผ‰ไธญๅฎฃๅ‘Šไพ่ณด { #declare-the-dependency-in-the-dependant } + +ๅ’Œไฝ ๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅƒๆ•ธไธŠไฝฟ็”จ `Body`ใ€`Query` ็ญ‰ๆ–นๅผไธ€ๆจฃ๏ผŒ้‡ๅฐๆ–ฐๅƒๆ•ธไฝฟ็”จ `Depends`๏ผš + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +้›–็„ถไฝ ๅœจๅ‡ฝๅผๅƒๆ•ธไธŠไฝฟ็”จ `Depends` ็š„ๆ–นๅผๅ’Œ `Body`ใ€`Query` ็ญ‰็›ธๅŒ๏ผŒไฝ† `Depends` ็š„้‹ไฝœๆ–นๅผๆœ‰้ปžไธๅŒใ€‚ + +ไฝ ๅช้œ€่ฆๅ‚ณ็ตฆ `Depends` ไธ€ๅ€‹ๅƒๆ•ธใ€‚ + +้€™ๅ€‹ๅƒๆ•ธๅฟ…้ ˆๆ˜ฏ้กžไผผๅ‡ฝๅผ็š„ๆฑ่ฅฟใ€‚ + +ไฝ ไธ้œ€่ฆ็›ดๆŽฅๅ‘ผๅซๅฎƒ๏ผˆไธ่ฆๅœจๅพŒ้ขๅŠ ไธŠๆ‹ฌ่™Ÿ๏ผ‰๏ผŒๅช่ฆๆŠŠๅฎƒไฝœ็‚บๅƒๆ•ธๅ‚ณ็ตฆ `Depends()` ๅณๅฏใ€‚ + +่€Œ่ฉฒๅ‡ฝๅผ็š„ๅƒๆ•ธๅฎฃๅ‘Šๆ–นๅผ่ˆ‡ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็›ธๅŒใ€‚ + +/// tip | ๆ็คบ + +้™คไบ†ๅ‡ฝๅผไน‹ๅค–๏ผŒ้‚„ๆœ‰ๅ…ถไป–ใ€Œๆฑ่ฅฟใ€ไนŸ่ƒฝ็•ถไฝœไพ่ณด๏ผŒๆœƒๅœจไธ‹ไธ€็ซ ไป‹็ดนใ€‚ + +/// + +็•ถๆœ‰ๆ–ฐ็š„่ซ‹ๆฑ‚ๅˆฐ้”ๆ™‚๏ผŒ**FastAPI** ๆœƒ่ฒ ่ฒฌ๏ผš + +* ไปฅๆญฃ็ขบ็š„ๅƒๆ•ธๅ‘ผๅซไฝ ็š„ไพ่ณด๏ผˆdependable๏ผ‰ๅ‡ฝๅผใ€‚ +* ๅ–ๅพ—่ฉฒๅ‡ฝๅผ็š„ๅ›žๅ‚ณ็ตๆžœใ€‚ +* ๅฐ‡็ตๆžœๆŒ‡ๅฎš็ตฆไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญ็š„ๅฐๆ‡‰ๅƒๆ•ธใ€‚ + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ๅช้œ€ๆ’ฐๅฏซไธ€ๆฌกๅ…ฑ็”จ็จ‹ๅผ็ขผ๏ผŒ**FastAPI** ๆœƒๆ›ฟไฝ ็š„ๅ„ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅ‘ผๅซๅฎƒใ€‚ + +/// check | ๆชขๆŸฅ + +ๆณจๆ„๏ผŒไฝ ไธๅฟ…ๅปบ็ซ‹็‰นๆฎŠ็š„้กžๅˆฅไธฆๆŠŠๅฎƒๅ‚ณๅˆฐ **FastAPI** ๅŽปใ€Œ่จปๅ†Šใ€ๆˆ–ๅš้กžไผผ็š„ไบ‹ใ€‚ + +ๅช่ฆๆŠŠๅฎƒๅ‚ณ็ตฆ `Depends`๏ผŒ**FastAPI** ๅฐฑ็Ÿฅ้“่ฉฒๆ€Ž้บผ่™•็†ๅ…ถ้ค˜็š„้ƒจๅˆ†ใ€‚ + +/// + +## ๅ…ฑ็”จ `Annotated` ไพ่ณด { #share-annotated-dependencies } + +ๅœจไธŠ้ข็š„็ฏ„ไพ‹ไธญ๏ผŒๅฏไปฅ็œ‹ๅˆฐๆœ‰ไธ€้ปž้ปž็š„ใ€Œ้‡่ค‡็จ‹ๅผ็ขผใ€ใ€‚ + +็•ถไฝ ่ฆไฝฟ็”จ `common_parameters()` ้€™ๅ€‹ไพ่ณดๆ™‚๏ผŒไฝ ๅพ—ๅฏซๅ‡บๅฎŒๆ•ด็š„ๅž‹ๅˆฅ่จป่งฃๆญ้… `Depends()`๏ผš + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +ไฝ†ๅ› ็‚บๆˆ‘ๅ€‘ๅœจไฝฟ็”จ `Annotated`๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๆŠŠ้€™ๅ€‹ `Annotated` ็š„ๅ€ผๅญ˜ๅˆฐไธ€ๅ€‹่ฎŠๆ•ธไธญ๏ผŒไธฆๅœจๅคšๅ€‹ๅœฐๆ–น้‡่ค‡ไฝฟ็”จ๏ผš + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | ๆ็คบ + +้€™ๅชๆ˜ฏๆจ™ๆบ–็š„ Python๏ผŒ็”จ็š„ๆ˜ฏๆ‰€่ฌ‚็š„ใ€Œๅž‹ๅˆฅๅˆฅๅ (type alias)ใ€๏ผŒๅ…ถๅฏฆๅ’Œ **FastAPI** ๆœฌ่บซ็„ก้—œใ€‚ + +ไฝ†ๅ› ็‚บ **FastAPI** ๆ˜ฏๅปบ็ซ‹ๅœจ Python ๆจ™ๆบ–ไน‹ไธŠ๏ผˆๅŒ…ๅซ `Annotated`๏ผ‰๏ผŒไฝ ๅฐฑๅฏไปฅๅœจ็จ‹ๅผ็ขผไธญไฝฟ็”จ้€™ๅ€‹ๆŠ€ๅทงใ€‚๐Ÿ˜Ž + +/// + +้€™ไบ›ไพ่ณดไพ็„ถๆœƒๅฆ‚้ ๆœŸ้‹ไฝœ๏ผŒ่€Œๆœ€ๆฃ’็š„ๆ˜ฏใ€Œๅž‹ๅˆฅ่ณ‡่จŠๆœƒ่ขซไฟ็•™ใ€๏ผŒไปฃ่กจไฝ ็š„็ทจ่ผฏๅ™จไป่ƒฝๆไพ›ใ€Œ่‡ชๅ‹•ๅฎŒๆˆใ€ใ€ใ€Œๅณๆ™‚้Œฏ่ชคใ€็ญ‰ๅŠŸ่ƒฝ๏ผŒๅƒ `mypy` ็ญ‰ๅ…ถไป–ๅทฅๅ…ทไนŸไธ€ๆจฃๅ—็›Šใ€‚ + +็•ถไฝ ๅœจใ€Œๅคงๅž‹็จ‹ๅผ็ขผๅบซใ€ไธญ๏ผŒๆ–ผ่จฑๅคšใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅ่ฆ†ไฝฟ็”จใ€Œ็›ธๅŒ็š„ไพ่ณดใ€ๆ™‚๏ผŒ้€™ๆœƒ็‰นๅˆฅๆœ‰็”จใ€‚ + +## ่ฆไธ่ฆไฝฟ็”จ `async` { #to-async-or-not-to-async } + +ๅ› ็‚บไพ่ณดไนŸๆœƒ็”ฑ **FastAPI** ๅ‘ผๅซ๏ผˆๅฐฑๅƒไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€๏ผ‰๏ผŒๆ‰€ไปฅๅœจๅฎš็พฉๅ‡ฝๅผๆ™‚ๅฅ—็”จ็›ธๅŒ็š„่ฆๅ‰‡ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `async def` ๆˆ–ไธ€่ˆฌ็š„ `def`ใ€‚ + +่€Œไธ”ไฝ ๅฏไปฅๅœจไธ€่ˆฌ `def` ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญๅฎฃๅ‘Š `async def` ็š„ไพ่ณด๏ผŒๆˆ–ๅœจ `async def` ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไธญๅฎฃๅ‘Š `def` ็š„ไพ่ณด๏ผŒ็ญ‰็ญ‰ใ€‚ + +้ƒฝๆฒ’้—œไฟ‚ใ€‚**FastAPI** ๆœƒ็Ÿฅ้“่ฉฒๆ€Ž้บผๅšใ€‚ + +/// note | ๆณจๆ„ + +ๅฆ‚ๆžœไฝ ไธ็†Ÿๆ‚‰๏ผŒ่ซ‹ๅƒ่€ƒๆ–‡ไปถไธญ็š„ [Async: "In a hurry?"](../../async.md#in-a-hurry){.internal-link target=_blank} ไธ€็ฏ€๏ผŒ็žญ่งฃ `async` ่ˆ‡ `await`ใ€‚ + +/// + +## ่ˆ‡ OpenAPI ๆ•ดๅˆ { #integrated-with-openapi } + +ไฝ ็š„ไพ่ณด๏ผˆไปฅๅŠๅ…ถๅญไพ่ณด๏ผ‰ๆ‰€ๅฎฃๅ‘Š็š„ๆ‰€ๆœ‰่ซ‹ๆฑ‚ๅƒๆ•ธใ€้ฉ—่ญ‰่ˆ‡้œ€ๆฑ‚๏ผŒ้ƒฝๆœƒๆ•ดๅˆ้€ฒๅŒไธ€ไปฝ OpenAPI ็ตๆง‹ไธญใ€‚ + +ๅ› ๆญค๏ผŒไบ’ๅ‹•ๅผๆ–‡ไปถไนŸๆœƒๅŒ…ๅซไพ†่‡ช้€™ไบ›ไพ่ณด็š„ๆ‰€ๆœ‰่ณ‡่จŠ๏ผš + + + +## ็ฐกๅ–ฎ็”จๆณ• { #simple-usage } + +ๆƒณไธ€ๆƒณ๏ผŒใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๆ˜ฏๅฎฃๅ‘Šๅฅฝ่ฎ“ๆก†ๆžถๅœจใ€Œ่ทฏๅพ‘ใ€่ˆ‡ใ€Œๆ“ไฝœใ€็ฌฆๅˆๆ™‚ไฝฟ็”จ็š„๏ผŒ็„ถๅพŒ **FastAPI** ๆœƒ่ฒ ่ฒฌๅธถๅ…ฅๆญฃ็ขบ็š„ๅƒๆ•ธใ€ๅพž่ซ‹ๆฑ‚ไธญๆ“ทๅ–่ณ‡ๆ–™๏ผŒไธฆๅ‘ผๅซ่ฉฒๅ‡ฝๅผใ€‚ + +ๅ…ถๅฏฆ๏ผŒๆ‰€ๆœ‰๏ผˆๆˆ–ๅคงๅคšๆ•ธ๏ผ‰Web ๆก†ๆžถ้ƒฝๆ˜ฏ้€™ๆจฃ้‹ไฝœใ€‚ + +ไฝ ๅพžไธๆœƒ็›ดๆŽฅๅ‘ผๅซ้€™ไบ›ๅ‡ฝๅผใ€‚ๅฎƒๅ€‘ๆ˜ฏ็”ฑๆก†ๆžถ๏ผˆๆญค่™•ๆ˜ฏ **FastAPI**๏ผ‰ๅ‘ผๅซ็š„ใ€‚ + +้€้Žไพ่ณดๆณจๅ…ฅ็ณป็ตฑ๏ผŒไฝ ไนŸๅฏไปฅๅ‘Š่จด **FastAPI**๏ผšไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€้‚„ใ€Œไพ่ณดใ€ๅ…ถไป–ๆฑ่ฅฟ๏ผŒๆ‡‰ๅœจไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไน‹ๅ‰ๅŸท่กŒ๏ผŒ**FastAPI** ๆœƒ่ฒ ่ฒฌๅŸท่กŒๅฎƒไธฆใ€Œๆณจๅ…ฅใ€ๅ…ถ็ตๆžœใ€‚ + +้€™ๅ€‹ใ€Œไพ่ณดๆณจๅ…ฅใ€ๆฆ‚ๅฟต็š„ๅ…ถไป–ๅธธ่ฆ‹็จฑๅ‘ผๅŒ…ๆ‹ฌ๏ผš + +* ่ณ‡ๆบ +* ๆไพ›่€… +* ๆœๅ‹™ +* ๅฏๆณจๅ…ฅ้ … +* ๅ…ƒไปถ + +## **FastAPI** ๅค–ๆŽ› { #fastapi-plug-ins } + +ๅ„็จฎๆ•ดๅˆ่ˆ‡ใ€Œๅค–ๆŽ›ใ€้ƒฝ่ƒฝไปฅ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑไพ†ๆง‹ๅปบใ€‚ไฝ†ไบ‹ๅฏฆไธŠ๏ผŒไธฆไธ้œ€่ฆ็œŸ็š„ๅŽปๆ‰“้€ ใ€Œๅค–ๆŽ›ใ€๏ผŒๅ› ็‚บ้€้Žไพ่ณด๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘Š็„กๆ•ธ็š„ๆ•ดๅˆ่ˆ‡ไบ’ๅ‹•๏ผŒไธฆ่ฎ“ๅฎƒๅ€‘ไพ›ไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ไฝฟ็”จใ€‚ + +่€Œไธ”ไพ่ณดๅฏไปฅ็”จ้žๅธธ็ฐกๅ–ฎ็›ด่ฆบ็š„ๆ–นๅผๅปบ็ซ‹๏ผŒไฝ ๅช้œ€่ฆๅŒฏๅ…ฅๆ‰€้œ€็š„ Python ๅฅ—ไปถ๏ผŒ็„ถๅพŒ็”จๅนพ่กŒ็จ‹ๅผ็ขผๅฐฑ่ƒฝๆŠŠๅฎƒๅ€‘่ˆ‡ไฝ ็š„ API ๅ‡ฝๅผๆ•ดๅˆ๏ผŒ็œŸ็š„ๆ˜ฏใ€Œๅช่ฆๅนพ่กŒใ€ใ€‚ + +ๅœจๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ไธญไฝ ๆœƒ็œ‹ๅˆฐ้€™ๆ–น้ข็š„ไพ‹ๅญ๏ผŒไพ‹ๅฆ‚้—œ่ฏๅผ่ˆ‡ NoSQL ่ณ‡ๆ–™ๅบซใ€ๅฎ‰ๅ…จๆ€ง็ญ‰ใ€‚ + +## **FastAPI** ็›ธๅฎนๆ€ง { #fastapi-compatibility } + +ไพ่ณดๆณจๅ…ฅ็ณป็ตฑ็š„็ฐกๆฝ”๏ผŒไฝฟ **FastAPI** ่ƒฝ่ˆ‡ไปฅไธ‹ไบ‹็‰ฉ็›ธๅฎน๏ผš + +* ๆ‰€ๆœ‰้—œ่ฏๅผ่ณ‡ๆ–™ๅบซ +* NoSQL ่ณ‡ๆ–™ๅบซ +* ๅค–้ƒจๅฅ—ไปถ +* ๅค–้ƒจ API +* ้ฉ—่ญ‰่ˆ‡ๆŽˆๆฌŠ็ณป็ตฑ +* API ไฝฟ็”จ็›ฃๆŽง็ณป็ตฑ +* ๅ›žๆ‡‰่ณ‡ๆ–™ๆณจๅ…ฅ็ณป็ตฑ +* ็ญ‰็ญ‰ + +## ็ฐกๅ–ฎ่€Œๅผทๅคง { #simple-and-powerful } + +้›–็„ถ้šŽๅฑคๅผ็š„ไพ่ณดๆณจๅ…ฅ็ณป็ตฑ็›ธ็•ถๅฎนๆ˜“ๅฎš็พฉ่ˆ‡ไฝฟ็”จ๏ผŒไฝ†ๅฎƒไพ็„ถ้žๅธธๅผทๅคงใ€‚ + +ไฝ ๅฏไปฅๅฎš็พฉๆœƒ้€ฒไธ€ๆญฅไพ่ณดๅ…ถไป–ไพ่ณด็š„ไพ่ณดใ€‚ + +ๆœ€็ต‚ๆœƒๅฝขๆˆไธ€ๆฃต้šŽๅฑคๅผ็š„ไพ่ณดๆจน๏ผŒ่€Œ **ไพ่ณดๆณจๅ…ฅ** ็ณป็ตฑๆœƒ่ฒ ่ฒฌ็‚บไฝ ่งฃๆฑบๆ‰€ๆœ‰้€™ไบ›ไพ่ณด๏ผˆไปฅๅŠๅฎƒๅ€‘็š„ๅญไพ่ณด๏ผ‰๏ผŒไธฆๅœจๆฏไธ€ๆญฅๆไพ›๏ผˆๆณจๅ…ฅ๏ผ‰ๅฐๆ‡‰็š„็ตๆžœใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅ‡่จญไฝ ๆœ‰ 4 ๅ€‹ API ็ซฏ้ปž๏ผˆใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผ‰๏ผš + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +้‚ฃ้บผไฝ ๅฐฑ่ƒฝๅช้€้Žไพ่ณด่ˆ‡ๅญไพ่ณด๏ผŒ็‚บๆฏๅ€‹็ซฏ้ปžๅŠ ๅ…ฅไธๅŒ็š„ๆฌŠ้™้œ€ๆฑ‚๏ผš + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## ่ˆ‡ **OpenAPI** ๆ•ดๅˆ { #integrated-with-openapi_1 } + +ๆ‰€ๆœ‰้€™ไบ›ไพ่ณดๅœจๅฎฃๅ‘Šๅ…ถ้œ€ๆฑ‚็š„ๅŒๆ™‚๏ผŒไนŸๆœƒ็‚บไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆ–ฐๅขžๅƒๆ•ธใ€้ฉ—่ญ‰็ญ‰ใ€‚ + +**FastAPI** ๆœƒ่ฒ ่ฒฌๆŠŠ้€™ไธ€ๅˆ‡ๅŠ ๅ…ฅ OpenAPI ็ตๆง‹ไธญ๏ผŒ่ฎ“ๅฎƒๅ€‘้กฏ็คบๅœจไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑ่ฃกใ€‚ diff --git a/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000..50c4e17908 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# ๅญ็›ธไพ { #sub-dependencies } + +ไฝ ๅฏไปฅๅปบ็ซ‹ๅ…ทๆœ‰ใ€Œๅญ็›ธไพใ€็š„็›ธไพ้ …ใ€‚ + +ๅฎƒๅ€‘ๅฏไปฅๆŒ‰ไฝ ็š„้œ€่ฆ๏ผŒๅฑค็ดšไปปๆ„ๅŠ ๆทฑใ€‚ + +**FastAPI** ๆœƒ่ฒ ่ฒฌ่งฃๆžๅฎƒๅ€‘ใ€‚ + +## ็ฌฌไธ€ๅ€‹็›ธไพ้ … "dependable" { #first-dependency-dependable } + +ไฝ ๅฏไปฅๅปบ็ซ‹็ฌฌไธ€ๅ€‹็›ธไพ้ …๏ผˆ"dependable"๏ผ‰ๅฆ‚ไธ‹๏ผš + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +ๅฎƒๅฎฃๅ‘Šไบ†ไธ€ๅ€‹ๅฏ้ธ็š„ๆŸฅ่ฉขๅƒๆ•ธ `q`๏ผˆๅž‹ๅˆฅ็‚บ `str`๏ผ‰๏ผŒ็„ถๅพŒ็›ดๆŽฅๅ›žๅ‚ณๅฎƒใ€‚ + +้€™ๅพˆ็ฐกๅ–ฎ๏ผˆไธๅคชๅฏฆ็”จ๏ผ‰๏ผŒไฝ†ๆœ‰ๅŠฉๆ–ผๆˆ‘ๅ€‘ๅฐˆๆณจๆ–ผๅญ็›ธไพๅฆ‚ไฝ•้‹ไฝœใ€‚ + +## ็ฌฌไบŒๅ€‹็›ธไพ๏ผŒๅŒๆ™‚ๆ˜ฏ "dependable" ไนŸๆ˜ฏ "dependant" { #second-dependency-dependable-and-dependant } + +ๆŽฅ่‘—ไฝ ๅฏไปฅๅปบ็ซ‹ๅฆไธ€ๅ€‹็›ธไพๅ‡ฝๅผ๏ผˆ"dependable"๏ผ‰๏ผŒๅŒๆ™‚ๅฎƒไนŸๅฎฃๅ‘Šไบ†่‡ชๅทฑ็š„็›ธไพ๏ผˆๅ› ๆญคๅฎƒๅŒๆ™‚ไนŸๆ˜ฏ "dependant"๏ผ‰๏ผš + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +ไพ†็œ‹ๅฎƒๆ‰€ๅฎฃๅ‘Š็š„ๅƒๆ•ธ๏ผš + +- ๅณไฝฟ้€™ๅ€‹ๅ‡ฝๅผๆœฌ่บซๆ˜ฏๅ€‹็›ธไพ้ …๏ผˆ"dependable"๏ผ‰๏ผŒๅฎƒไนŸๅฎฃๅ‘Šไบ†ๅฆไธ€ๅ€‹็›ธไพ๏ผˆๅฎƒใ€Œ็›ธไพๆ–ผใ€ๅ…ถไป–ๆฑ่ฅฟ๏ผ‰ใ€‚ + - ๅฎƒ็›ธไพ `query_extractor`๏ผŒไธฆๆŠŠๅ…ถๅ›žๅ‚ณๅ€ผๆŒ‡ๅฎš็ตฆๅƒๆ•ธ `q`ใ€‚ +- ๅฎƒ้‚„ๅฎฃๅ‘Šไบ†ไธ€ๅ€‹ๅฏ้ธ็š„ `last_query` cookie๏ผŒๅž‹ๅˆฅ็‚บ `str`ใ€‚ + - ๅฆ‚ๆžœไฝฟ็”จ่€…ๆฒ’ๆœ‰ๆไพ›ๆŸฅ่ฉข `q`๏ผŒๆˆ‘ๅ€‘ๅฐฑไฝฟ็”จๅ…ˆๅ‰ๅ„ฒๅญ˜ๅœจ cookie ไธญ็š„ๆœ€ๅพŒไธ€ๆฌกๆŸฅ่ฉขๅ€ผใ€‚ + +## ไฝฟ็”จ็›ธไพ้ … { #use-the-dependency } + +็„ถๅพŒๆˆ‘ๅ€‘ๅฏไปฅ้€™ๆจฃไฝฟ็”จ้€™ๅ€‹็›ธไพ้ …๏ผš + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// info + +ๆณจๆ„๏ผŒๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญๆˆ‘ๅ€‘ๅชๅฎฃๅ‘Šไบ†ไธ€ๅ€‹็›ธไพ้ … `query_or_cookie_extractor`ใ€‚ + +ไฝ† **FastAPI** ๆœƒ็Ÿฅ้“ๅฎƒๅฟ…้ ˆๅ…ˆ่งฃๆž `query_extractor`๏ผŒๅœจๅ‘ผๅซ `query_or_cookie_extractor` ๆ™‚ๆŠŠๅ…ถ็ตๆžœๅ‚ณๅ…ฅใ€‚ + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## ๅคšๆฌกไฝฟ็”จๅŒไธ€ๅ€‹็›ธไพ้ … { #using-the-same-dependency-multiple-times } + +ๅฆ‚ๆžœไฝ ็š„ๆŸๅ€‹็›ธไพ้ …ๅœจๅŒไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœไธญ่ขซๅฎฃๅ‘Šไบ†ๅคšๆฌก๏ผŒไพ‹ๅฆ‚ๅคšๅ€‹็›ธไพๅ…ฑ็”จๅŒไธ€ๅ€‹ๅญ็›ธไพ๏ผŒ**FastAPI** ๆœƒ็Ÿฅ้“ๅช้œ€ๅœจๆฏๆฌก่ซ‹ๆฑ‚ไธญๅ‘ผๅซ่ฉฒๅญ็›ธไพไธ€ๆฌกใ€‚ + +ๅฎƒๆœƒๆŠŠๅ›žๅ‚ณๅ€ผๅ„ฒๅญ˜ๅœจไธ€ๅ€‹ ใ€Œๅฟซๅ–ใ€ ไธญ๏ผŒไธฆๅœจ่ฉฒๆฌก่ซ‹ๆฑ‚ไธญๅ‚ณ้ž็ตฆๆ‰€ๆœ‰้œ€่ฆๅฎƒ็š„ใ€Œ็›ธไพ่€…ใ€๏ผŒ่€Œไธๆ˜ฏ็‚บๅŒไธ€ๅ€‹่ซ‹ๆฑ‚ๅคšๆฌกๅ‘ผๅซ็›ธๅŒ็š„็›ธไพ้ …ใ€‚ + +ๅœจ้€ฒ้šŽๆƒ…ๅขƒไธ‹๏ผŒๅฆ‚ๆžœไฝ ็ขบๅฎš้œ€่ฆๅœจๅŒไธ€ๆฌก่ซ‹ๆฑ‚็š„ๆฏๅ€‹ๆญฅ้ฉŸ้ƒฝๅ‘ผๅซ่ฉฒ็›ธไพ๏ผˆๅฏ่ƒฝๅ‘ผๅซๅคšๆฌก๏ผ‰๏ผŒ่€Œไธๆ˜ฏไฝฟ็”จใ€Œๅฟซๅ–ใ€็š„ๅ€ผ๏ผŒไฝ ๅฏไปฅๅœจไฝฟ็”จ `Depends` ๆ™‚่จญๅฎšๅƒๆ•ธ `use_cache=False`๏ผš + +//// tab | Python 3.10+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.10+ ๆœชไฝฟ็”จ Annotated + +/// tip + +่‹ฅๅฏ่กŒ๏ผŒๅปบ่ญฐไฝฟ็”จ `Annotated` ็š„็‰ˆๆœฌใ€‚ + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## ๅ›ž้กง { #recap } + +ๆ’‡้–‹้€™่ฃก็”จๅˆฐ็š„่ก“่ชžไธ่ซ‡๏ผŒ**็›ธไพๆ€งๆณจๅ…ฅ๏ผˆDependency Injection๏ผ‰** ็ณป็ตฑๅ…ถๅฏฆๅพˆ็ฐกๅ–ฎใ€‚ + +ๅฎƒๅชๆ˜ฏไธ€ไบ›่ˆ‡่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผๅค–่ง€็›ธๅŒ็š„ๅ‡ฝๅผใ€‚ + +ไฝ†ๅฎƒ้žๅธธๅผทๅคง๏ผŒๅ…่จฑไฝ ๅฎฃๅ‘Šไปปๆ„ๆทฑๅบฆๅทข็‹€็š„็›ธไพใ€Œๅœ–ใ€๏ผˆๆจน๏ผ‰ใ€‚ + +/// tip + +็”จ้€™ไบ›็ฐกๅ–ฎ็š„ไพ‹ๅญ็œ‹่ตทไพ†ๅฏ่ƒฝไธ้‚ฃ้บผๆœ‰็”จใ€‚ + +ไฝ†ๅœจ้—œๆ–ผๅฎ‰ๅ…จๆ€ง็š„็ซ ็ฏ€ไธญ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฎƒๆœ‰ๅคšๅฏฆ็”จใ€‚ + +ไฝ ไนŸๆœƒ็œ‹ๅˆฐๅฎƒ่ƒฝ็‚บไฝ ็œไธ‹ๅคšๅฐ‘็จ‹ๅผ็ขผใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/encoder.md b/docs/zh-hant/docs/tutorial/encoder.md new file mode 100644 index 0000000000..03b7db6394 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/encoder.md @@ -0,0 +1,35 @@ +# JSON ็›ธๅฎน็ทจ็ขผๅ™จ { #json-compatible-encoder } + +ๅœจๆŸไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏ่ƒฝ้œ€่ฆๅฐ‡ๆŸ็จฎ่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผˆไพ‹ๅฆ‚ Pydantic ๆจกๅž‹๏ผ‰่ฝ‰ๆ›็‚บ่ˆ‡ JSON ็›ธๅฎน็š„้กžๅž‹๏ผˆไพ‹ๅฆ‚ `dict`ใ€`list` ็ญ‰๏ผ‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็•ถไฝ ้œ€่ฆๆŠŠๅฎƒๅ„ฒๅญ˜ๅœจ่ณ‡ๆ–™ๅบซไธญใ€‚ + +็‚บๆญค๏ผŒ**FastAPI** ๆไพ›ไบ† `jsonable_encoder()` ๅ‡ฝๅผใ€‚ + +## ไฝฟ็”จ `jsonable_encoder` { #using-the-jsonable-encoder } + +ๆƒณๅƒไฝ ๆœ‰ไธ€ๅ€‹ๅชๆŽฅๅ—่ˆ‡ JSON ็›ธๅฎน่ณ‡ๆ–™็š„่ณ‡ๆ–™ๅบซ `fake_db`ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฎƒไธๆŽฅๅ— `datetime` ็‰ฉไปถ๏ผŒๅ› ็‚บ้‚ฃ่ˆ‡ JSON ไธ็›ธๅฎนใ€‚ + +ๅ› ๆญค๏ผŒๅฟ…้ ˆๅฐ‡ `datetime` ็‰ฉไปถ่ฝ‰็‚บไธ€ๅ€‹ไปฅ ISO ๆ ผๅผ ่กจ็คบ่ณ‡ๆ–™็š„ `str`ใ€‚ + +ๅŒๆจฃๅœฐ๏ผŒ้€™ๅ€‹่ณ‡ๆ–™ๅบซไธๆœƒๆŽฅๅ— Pydantic ๆจกๅž‹๏ผˆๅธถๆœ‰ๅฑฌๆ€ง็š„็‰ฉไปถ๏ผ‰๏ผŒๅชๆŽฅๅ— `dict`ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `jsonable_encoder` ไพ†่™•็†ใ€‚ + +ๅฎƒๆŽฅๆ”ถไธ€ๅ€‹็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ Pydantic ๆจกๅž‹๏ผ‰๏ผŒไธฆๅ›žๅ‚ณไธ€ๅ€‹่ˆ‡ JSON ็›ธๅฎน็š„็‰ˆๆœฌ๏ผš + +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} + +ๅœจๆญค็ฏ„ไพ‹ไธญ๏ผŒๅฎƒๆœƒๆŠŠ Pydantic ๆจกๅž‹่ฝ‰ๆˆ `dict`๏ผŒไธฆๅฐ‡ `datetime` ่ฝ‰ๆˆ `str`ใ€‚ + +ๅ‘ผๅซๅพŒ็š„็ตๆžœๅฏไปฅ็”จ Python ๆจ™ๆบ–็š„ `json.dumps()` ้€ฒ่กŒ็ทจ็ขผใ€‚ + +ๅฎƒไธๆœƒๅ›žๅ‚ณไธ€ๅ€‹ๅŒ…ๅซ JSON ๅ…งๅฎน็š„ๅคงๅž‹ `str`๏ผˆๅญ—ไธฒ๏ผ‰ใ€‚ๅฎƒๆœƒๅ›žๅ‚ณ Python ๆจ™ๆบ–็š„่ณ‡ๆ–™็ตๆง‹๏ผˆไพ‹ๅฆ‚ `dict`๏ผ‰๏ผŒๅ…ถไธญ็š„ๅ€ผ่ˆ‡ๅญๅ€ผ้ƒฝ่ˆ‡ JSON ็›ธๅฎนใ€‚ + +/// note + +ไบ‹ๅฏฆไธŠ๏ผŒ`jsonable_encoder` ๅœจ **FastAPI** ๅ…ง้ƒจไนŸ่ขซ็”จไพ†่ฝ‰ๆ›่ณ‡ๆ–™ใ€‚ไธ้Žๅœจ่จฑๅคšๅ…ถไป–ๆƒ…ๅขƒไธญๅฎƒๅŒๆจฃๅฏฆ็”จใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/extra-data-types.md b/docs/zh-hant/docs/tutorial/extra-data-types.md new file mode 100644 index 0000000000..f516d965a4 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/extra-data-types.md @@ -0,0 +1,62 @@ +# ้กๅค–็š„่ณ‡ๆ–™ๅž‹ๅˆฅ { #extra-data-types } + +ๅˆฐ็›ฎๅ‰็‚บๆญข๏ผŒไฝ ไธ€็›ดๅœจไฝฟ็”จๅธธ่ฆ‹็š„่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผŒไพ‹ๅฆ‚๏ผš + +* `int` +* `float` +* `str` +* `bool` + +ไฝ†ไฝ ไนŸๅฏไปฅไฝฟ็”จๆ›ด่ค‡้›œ็š„่ณ‡ๆ–™ๅž‹ๅˆฅใ€‚ + +่€Œไธ”ไฝ ไป็„ถๆœƒๆ“ๆœ‰็›ฎๅ‰็‚บๆญขๆ‰€่ฆ‹็š„ๅŒๆจฃๅŠŸ่ƒฝ๏ผš + +* ๆฅตไฝณ็š„็ทจ่ผฏๅ™จๆ”ฏๆดใ€‚ +* ๅฐ‡ๅ‚ณๅ…ฅ่ซ‹ๆฑ‚็š„่ณ‡ๆ–™่ฝ‰ๆ›ใ€‚ +* ๅ›žๆ‡‰่ณ‡ๆ–™็š„่ฝ‰ๆ›ใ€‚ +* ่ณ‡ๆ–™้ฉ—่ญ‰ใ€‚ +* ่‡ชๅ‹•็”ข็”Ÿ่จป่งฃ่ˆ‡ๆ–‡ไปถใ€‚ + +## ๅ…ถไป–่ณ‡ๆ–™ๅž‹ๅˆฅ { #other-data-types } + +ไปฅไธ‹ๆ˜ฏไฝ ๅฏไปฅไฝฟ็”จ็š„ไธ€ไบ›ๅ…ถไป–่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผš + +* `UUID`๏ผš + * ไธ€็จฎๆจ™ๆบ–็š„ใ€Œ้€š็”จๅ”ฏไธ€่ญ˜ๅˆฅ็ขผ (Universally Unique Identifier)ใ€๏ผŒๅธธ่ฆ‹ๆ–ผ่จฑๅคš่ณ‡ๆ–™ๅบซ่ˆ‡็ณป็ตฑ็š„ IDใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒไปฅ `str` ่กจ็คบใ€‚ +* `datetime.datetime`๏ผš + * Python ็š„ `datetime.datetime`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒไปฅ ISO 8601 ๆ ผๅผ็š„ `str` ่กจ็คบ๏ผŒไพ‹ๅฆ‚๏ผš`2008-09-15T15:53:00+05:00`ใ€‚ +* `datetime.date`๏ผš + * Python ็š„ `datetime.date`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒไปฅ ISO 8601 ๆ ผๅผ็š„ `str` ่กจ็คบ๏ผŒไพ‹ๅฆ‚๏ผš`2008-09-15`ใ€‚ +* `datetime.time`๏ผš + * Python ็š„ `datetime.time`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒไปฅ ISO 8601 ๆ ผๅผ็š„ `str` ่กจ็คบ๏ผŒไพ‹ๅฆ‚๏ผš`14:23:55.003`ใ€‚ +* `datetime.timedelta`๏ผš + * Python ็š„ `datetime.timedelta`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒไปฅ็ธฝ็ง’ๆ•ธ็š„ `float` ่กจ็คบใ€‚ + * Pydantic ไนŸๅ…่จฑ็”จใ€ŒISO 8601 time diff encodingใ€ไพ†่กจ็คบ๏ผŒ่ฉณๆƒ…่ฆ‹ๆ–‡ไปถใ€‚ +* `frozenset`๏ผš + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญ่ˆ‡ `set` ็›ธๅŒ่™•็†๏ผš + * ๅœจ่ซ‹ๆฑ‚ไธญ๏ผŒๆœƒ่ฎ€ๅ–ไธ€ๅ€‹ list๏ผŒๅŽป้™ค้‡่ค‡ไธฆ่ฝ‰็‚บ `set`ใ€‚ + * ๅœจๅ›žๆ‡‰ไธญ๏ผŒ`set` ๆœƒ่ขซ่ฝ‰็‚บ `list`ใ€‚ + * ็”Ÿๆˆ็š„ schema ๆœƒๆŒ‡ๅฎš `set` ็š„ๅ€ผ็‚บๅ”ฏไธ€๏ผˆไฝฟ็”จ JSON Schema ็š„ `uniqueItems`๏ผ‰ใ€‚ +* `bytes`๏ผš + * ๆจ™ๆบ–็š„ Python `bytes`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญๆœƒ่ขซ็•ถไฝœ `str` ่™•็†ใ€‚ + * ็”Ÿๆˆ็š„ schema ๆœƒๆŒ‡ๅฎšๅ…ถ็‚บ `str`๏ผŒไธ” "format" ็‚บ `binary`ใ€‚ +* `Decimal`๏ผš + * ๆจ™ๆบ–็š„ Python `Decimal`ใ€‚ + * ๅœจ่ซ‹ๆฑ‚่ˆ‡ๅ›žๆ‡‰ไธญ๏ผŒ่ˆ‡ `float` ็š„่™•็†ๆ–นๅผ็›ธๅŒใ€‚ +* ไฝ ๅฏไปฅๅœจๆญคๆŸฅ้–ฑๆ‰€ๆœ‰ๅฏ็”จ็š„ Pydantic ่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผšPydantic ่ณ‡ๆ–™ๅž‹ๅˆฅใ€‚ + +## ็ฏ„ไพ‹ { #example } + +ไปฅไธ‹ๆ˜ฏไธ€ๅ€‹ๅธถๆœ‰ๅƒๆ•ธใ€ไฝฟ็”จไธŠ่ฟฐ้ƒจๅˆ†ๅž‹ๅˆฅ็š„ *่ทฏๅพ‘ๆ“ไฝœ (path operation)* ็ฏ„ไพ‹ใ€‚ + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} + +่ซ‹ๆณจๆ„๏ผŒๅ‡ฝๅผๅ…ง็š„ๅƒๆ•ธๆœƒๆ˜ฏๅฎƒๅ€‘็š„่‡ช็„ถ่ณ‡ๆ–™ๅž‹ๅˆฅ๏ผŒๅ› ๆญคไฝ ๅฏไปฅ้€ฒ่กŒไธ€่ˆฌ็š„ๆ—ฅๆœŸ้‹็ฎ—๏ผŒไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/zh-hant/docs/tutorial/extra-models.md b/docs/zh-hant/docs/tutorial/extra-models.md new file mode 100644 index 0000000000..8aae62f8e1 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# ้กๅค–็š„ๆจกๅž‹ { #extra-models } + +ๅปถ็บŒๅ‰ไธ€ๅ€‹็ฏ„ไพ‹๏ผŒ้€šๅธธๆœƒๆœ‰ไธๅชไธ€ๅ€‹ๅฝผๆญค็›ธ้—œ็š„ๆจกๅž‹ใ€‚ + +ๅฐไฝฟ็”จ่€…ๆจกๅž‹ๅฐคๅ…ถๅฆ‚ๆญค๏ผŒๅ› ็‚บ๏ผš + +* ใ€Œ่ผธๅ…ฅๆจกๅž‹ใ€้œ€่ฆ่ƒฝๅŒ…ๅซๅฏ†็ขผใ€‚ +* ใ€Œ่ผธๅ‡บๆจกๅž‹ใ€ไธๆ‡‰ๅŒ…ๅซๅฏ†็ขผใ€‚ +* ใ€Œ่ณ‡ๆ–™ๅบซๆจกๅž‹ใ€้€šๅธธ้œ€่ฆๅ„ฒๅญ˜้›œๆนŠๅพŒ็š„ๅฏ†็ขผใ€‚ + +/// danger + +ๅˆ‡ๅ‹ฟๅ„ฒๅญ˜ไฝฟ็”จ่€…็š„ๆ˜Žๆ–‡ๅฏ†็ขผใ€‚ๅ‹™ๅฟ…ๅชๅ„ฒๅญ˜ๅฏไพ›้ฉ—่ญ‰็š„ใ€Œๅฎ‰ๅ…จ้›œๆนŠใ€ใ€‚ + +่‹ฅไฝ ้‚„ไธๆธ…ๆฅš๏ผŒ็จๅพŒๆœƒๅœจ[ๅฎ‰ๅ…จๆ€ง็ซ ็ฏ€](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}ๅญธๅˆฐไป€้บผๆ˜ฏใ€Œๅฏ†็ขผ้›œๆนŠใ€ใ€‚ + +/// + +## ๅคšๅ€‹ๆจกๅž‹ { #multiple-models } + +ไปฅไธ‹ๆ˜ฏๆจกๅž‹ๅคง่‡ด้•ท็›ธใ€่ˆ‡ๅ…ถๅฏ†็ขผๆฌ„ไฝไปฅๅŠๅฎƒๅ€‘่ขซไฝฟ็”จ็š„ไฝ็ฝฎ๏ผš + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### ้—œๆ–ผ `**user_in.model_dump()` { #about-user-in-model-dump } + +#### Pydantic ็š„ `.model_dump()` { #pydantics-model-dump } + +`user_in` ๆ˜ฏไธ€ๅ€‹ `UserIn` ้กžๅˆฅ็š„ Pydantic ๆจกๅž‹ใ€‚ + +Pydantic ๆจกๅž‹ๆœ‰ `.model_dump()` ๆ–นๆณ•๏ผŒๆœƒๅ›žๅ‚ณๅŒ…ๅซ่ฉฒๆจกๅž‹่ณ‡ๆ–™็š„ `dict`ใ€‚ + +ๅ› ๆญค๏ผŒ่‹ฅๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹ Pydantic ็‰ฉไปถ `user_in` ๅฆ‚๏ผš + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +ๆŽฅ่‘—ๅ‘ผๅซ๏ผš + +```Python +user_dict = user_in.model_dump() +``` + +ๆญคๆ™‚่ฎŠๆ•ธ `user_dict` ๆœƒๆ˜ฏไธ€ๅ€‹ๆ‰ฟ่ผ‰่ณ‡ๆ–™็š„ `dict`๏ผˆไนŸๅฐฑๆ˜ฏ `dict`๏ผŒ่€Œ้ž Pydantic ๆจกๅž‹็‰ฉไปถ๏ผ‰ใ€‚ + +่‹ฅๅ†ๅ‘ผๅซ๏ผš + +```Python +print(user_dict) +``` + +ๆˆ‘ๅ€‘ๆœƒๅพ—ๅˆฐไธ€ๅ€‹ Python `dict`๏ผš + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### ่งฃๅŒ… `dict` { #unpacking-a-dict } + +่‹ฅๅฐ‡ๅƒ `user_dict` ้€™ๆจฃ็š„ `dict` ไปฅ `**user_dict` ๅ‚ณ็ตฆๅ‡ฝๅผ๏ผˆๆˆ–้กžๅˆฅ๏ผ‰๏ผŒPython ๆœƒๅฐ‡ๅ…ถใ€Œ่งฃๅŒ…ใ€๏ผŒๆŠŠ `user_dict` ็š„้ตๅ’Œๅ€ผ็›ดๆŽฅ็•ถไฝœๅ…ทๅๅผ•ๆ•ธๅ‚ณๅ…ฅใ€‚ + +ๅ› ๆญค๏ผŒๅปถ็บŒไธŠ้ข็š„ `user_dict`๏ผŒๅฏซๆˆ๏ผš + +```Python +UserInDB(**user_dict) +``` + +ๆ•ˆๆžœ็ญ‰ๅŒๆ–ผ๏ผš + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +ๆ›ด็ฒพ็ขบๅœฐ่ชช๏ผŒ็›ดๆŽฅไฝฟ็”จ `user_dict`๏ผˆๆœชไพ†ๅ…งๅฎนๅฏ่ƒฝๆœ‰ๆ‰€ไธๅŒ๏ผ‰ๅ‰‡็ญ‰ๅŒๆ–ผ๏ผš + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### ็”ฑๅฆไธ€ๅ€‹ๆจกๅž‹ๅ…งๅฎนๅปบ็ซ‹ Pydantic ๆจกๅž‹ { #a-pydantic-model-from-the-contents-of-another } + +ๅฆ‚ไธŠไพ‹ๆˆ‘ๅ€‘ๅพž `user_in.model_dump()` ๅพ—ๅˆฐ `user_dict`๏ผŒไปฅไธ‹็จ‹ๅผ็ขผ๏ผš + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +็ญ‰ๅŒๆ–ผ๏ผš + +```Python +UserInDB(**user_in.model_dump()) +``` + +...ๅ› ็‚บ `user_in.model_dump()` ๅ›žๅ‚ณ็š„ๆ˜ฏ `dict`๏ผŒๆŽฅ่‘—ๅœจๅ‚ณ็ตฆ `UserInDB` ๆ™‚ไปฅ `**` ๅ‰็ถด่ฎ“ Python ้€ฒ่กŒ่งฃๅŒ…ใ€‚ + +ๅ› ๆญค๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ็”จไธ€ๅ€‹ Pydantic ๆจกๅž‹็š„่ณ‡ๆ–™ๅปบ็ซ‹ๅฆไธ€ๅ€‹ Pydantic ๆจกๅž‹ใ€‚ + +#### ่งฃๅŒ… `dict` ไธฆๅŠ ๅ…ฅ้กๅค–ๅƒๆ•ธ { #unpacking-a-dict-and-extra-keywords } + +ๆŽฅ่‘—ๅŠ ๅ…ฅ้กๅค–็š„ๅ…ทๅๅผ•ๆ•ธ `hashed_password=hashed_password`๏ผŒๅฆ‚ไธ‹๏ผš + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +...็ตๆžœ็ญ‰ๅŒๆ–ผ๏ผš + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning + +่ผ”ๅŠฉๅ‡ฝๅผ `fake_password_hasher` ่ˆ‡ `fake_save_user` ๅชๆ˜ฏ็”จไพ†็คบ็ฏ„่ณ‡ๆ–™ๆต็จ‹๏ผŒไธฆไธๆไพ›ไปปไฝ•ๅฏฆ้š›็š„ๅฎ‰ๅ…จๆ€งใ€‚ + +/// + +## ๆธ›ๅฐ‘้‡่ค‡ { #reduce-duplication } + +ๆธ›ๅฐ‘็จ‹ๅผ็ขผ้‡่ค‡ๆ˜ฏ FastAPI ็š„ๆ ธๅฟƒ็†ๅฟตไน‹ไธ€ใ€‚ + +ๅ› ็‚บ้‡่ค‡็š„็จ‹ๅผ็ขผๆœƒๆ้ซ˜็™ผ็”Ÿ้Œฏ่ชคใ€ๅฎ‰ๅ…จๆ€งๅ•้กŒใ€็จ‹ๅผไธๅŒๆญฅ๏ผˆๆŸ่™•ๆ›ดๆ–ฐไฝ†ๅ…ถไป–่™•ๆœชๆ›ดๆ–ฐ๏ผ‰็ญ‰้ขจ้šชใ€‚ + +่€Œ้€™ไบ›ๆจกๅž‹ๅ…ฑไบซๅคง้‡่ณ‡ๆ–™๏ผŒ้‡่ค‡ไบ†ๅฑฌๆ€งๅ็จฑ่ˆ‡ๅž‹ๅˆฅใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅๅšๅพ—ๆ›ดๅฅฝใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹ไฝœ็‚บๅŸบๅบ•็š„ `UserBase` ๆจกๅž‹๏ผŒๅ…ถไป–ๆจกๅž‹็นผๆ‰ฟๅฎƒๆˆ็‚บๅญ้กžๅˆฅ๏ผŒๆฒฟ็”จๅ…ถๅฑฌๆ€ง๏ผˆๅž‹ๅˆฅๅฎฃๅ‘Šใ€้ฉ—่ญ‰็ญ‰๏ผ‰ใ€‚ + +ๆ‰€ๆœ‰่ณ‡ๆ–™่ฝ‰ๆ›ใ€้ฉ—่ญ‰ใ€ๆ–‡ไปถ็”ข็”Ÿ็ญ‰ไปๅฏๆญฃๅธธ้‹ไฝœใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๆˆ‘ๅ€‘ๅช้œ€่ฆๅฎฃๅ‘Šๆจกๅž‹ไน‹้–“็š„ๅทฎ็•ฐ๏ผˆๅซๆ˜Žๆ–‡ `password`ใ€ๅซ `hashed_password`ใ€ๆˆ–ไธๅซๅฏ†็ขผ๏ผ‰๏ผš + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` ๆˆ– `anyOf` { #union-or-anyof } + +ไฝ ๅฏไปฅๅฐ‡ๅ›žๆ‡‰ๅฎฃๅ‘Š็‚บๅคšๅ€‹ๅž‹ๅˆฅ็š„ `Union`๏ผŒ่กจ็คบๅ›žๆ‡‰ๅฏ่ƒฝๆ˜ฏๅ…ถไธญไปปไธ€ๅž‹ๅˆฅใ€‚ + +ๅœจ OpenAPI ไธญๆœƒไปฅ `anyOf` ๅฎš็พฉใ€‚ + +่ฆ้”ๆˆ้€™้ปž๏ผŒไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๆ็คบ `typing.Union`๏ผš + +/// note + +ๅœจๅฎš็พฉ `Union` ๆ™‚๏ผŒ่ซ‹ๅ…ˆๆ”พ็ฝฎใ€Œๆ›ดๅ…ท้ซ”ใ€็š„ๅž‹ๅˆฅ๏ผŒๅ†ๆ”พใ€Œ่ผƒไธๅ…ท้ซ”ใ€็š„ๅž‹ๅˆฅใ€‚ไปฅไธ‹็ฏ„ไพ‹ไธญ๏ผŒ่ผƒๅ…ท้ซ”็š„ `PlaneItem` ็ฝฎๆ–ผ `CarItem` ไน‹ๅ‰๏ผš`Union[PlaneItem, CarItem]`ใ€‚ + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### Python 3.10 ไธญ็š„ `Union` { #union-in-python-3-10 } + +ๆญค็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๅฐ‡ `Union[PlaneItem, CarItem]` ไฝœ็‚บๅผ•ๆ•ธ `response_model` ็š„ๅ€ผใ€‚ + +็”ฑๆ–ผ้€™่ฃกๆ˜ฏๆŠŠๅฎƒ็•ถไฝœๅผ•ๆ•ธ็š„ใ€Œๅ€ผใ€ๅ‚ณๅ…ฅ๏ผŒ่€Œ้ž็”จๆ–ผๅž‹ๅˆฅ่จป่จ˜๏ผŒๅ› ๆญคๅณไฝฟๅœจ Python 3.10 ไนŸๅฟ…้ ˆไฝฟ็”จ `Union`ใ€‚ + +่‹ฅ็”จๆ–ผๅž‹ๅˆฅ่จป่จ˜๏ผŒๅ‰‡ๅฏไปฅไฝฟ็”จ็›ด็ทš๏ผˆ|๏ผ‰๏ผŒๅฆ‚ไธ‹๏ผš + +```Python +some_variable: PlaneItem | CarItem +``` + +ไฝ†่‹ฅๅฏซๆˆๆŒ‡ๅฎšๅ€ผ `response_model=PlaneItem | CarItem` ๆœƒ็™ผ็”Ÿ้Œฏ่ชค๏ผŒๅ› ็‚บ Python ๆœƒๅ˜—่ฉฆๅœจ `PlaneItem` ่ˆ‡ `CarItem` ไน‹้–“ๅŸท่กŒใ€Œ็„กๆ•ˆ้‹็ฎ—ใ€๏ผŒ่€Œ้žๅฐ‡ๅ…ถ่ฆ–็‚บๅž‹ๅˆฅ่จป่จ˜ใ€‚ + +## ๆจกๅž‹็š„ๆธ…ๅ–ฎ { #list-of-models } + +ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅๅฐ‡ๅ›žๆ‡‰ๅฎฃๅ‘Š็‚บ็‰ฉไปถ็š„ `list`ใ€‚ + +็‚บๆญค๏ผŒไฝฟ็”จๆจ™ๆบ–็š„ Python `list`๏ผš + +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} + +## ไปฅไปปๆ„ `dict` ไฝœ็‚บๅ›žๆ‡‰ { #response-with-arbitrary-dict } + +ไฝ ไนŸๅฏไปฅ็”จไธ€่ˆฌ็š„ไปปๆ„ `dict` ๅฎฃๅ‘Šๅ›žๆ‡‰๏ผŒๅช้œ€ๆŒ‡ๅฎš้ตๅ’Œๅ€ผ็š„ๅž‹ๅˆฅ๏ผŒ่€Œไธๅฟ…ไฝฟ็”จ Pydantic ๆจกๅž‹ใ€‚ + +็•ถไฝ ไบ‹ๅ…ˆไธ็Ÿฅ้“ๅฏ็”จ็š„ๆฌ„ไฝ๏ผๅฑฌๆ€งๅ็จฑ๏ผˆๅฎš็พฉ Pydantic ๆจกๅž‹ๆ‰€้œ€๏ผ‰ๆ™‚๏ผŒ้€™ๅพˆๅฏฆ็”จใ€‚ + +ๆญคๆ™‚ๅฏไฝฟ็”จ `dict`๏ผš + +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} + +## ้‡้ปžๅ›ž้กง { #recap } + +ไพๆƒ…ๅขƒไฝฟ็”จๅคšๅ€‹ Pydantic ๆจกๅž‹ไธฆ้ˆๆดป็นผๆ‰ฟใ€‚ + +็•ถไธ€ๅ€‹ๅฏฆ้ซ”้œ€่ฆๅ‘ˆ็พไธๅŒใ€Œ็‹€ๆ…‹ใ€ๆ™‚๏ผŒไธๅฟ…ไพท้™ๆ–ผไธ€ๅ€‹่ณ‡ๆ–™ๆจกๅž‹ใ€‚ไพ‹ๅฆ‚ไฝฟ็”จ่€…้€™ๅ€‹ๅฏฆ้ซ”๏ผŒๅฏ่ƒฝๆœ‰ๅŒ…ๅซ `password`ใ€ๅŒ…ๅซ `password_hash`๏ผŒๆˆ–ไธๅซๅฏ†็ขผ็ญ‰ไธๅŒ็‹€ๆ…‹ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index 6bcb453bff..3aa2d39ae1 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -2,7 +2,7 @@ ๆœ€็ฐกๅ–ฎ็š„ FastAPI ๆช”ๆกˆๅฏ่ƒฝ็œ‹่ตทไพ†ๅƒ้€™ๆจฃ๏ผš -{* ../../docs_src/first_steps/tutorial001_py39.py *} +{* ../../docs_src/first_steps/tutorial001_py310.py *} ๅฐ‡ๅ…ถ่ค‡่ฃฝๅˆฐไธ€ๅ€‹ๅ็‚บ `main.py` ็š„ๆ–‡ไปถไธญใ€‚ @@ -183,7 +183,7 @@ Deploying to FastAPI Cloud... ### ็ฌฌไธ€ๆญฅ๏ผšๅผ•ๅ…ฅ `FastAPI` { #step-1-import-fastapi } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} `FastAPI` ๆ˜ฏไธ€ๅ€‹ Python ้กžๅˆฅ๏ผŒๆไพ›ๆ‰€ๆœ‰ API ็š„ๅ…จ้ƒจๅŠŸ่ƒฝใ€‚ @@ -197,7 +197,7 @@ Deploying to FastAPI Cloud... ### ็ฌฌไบŒๆญฅ๏ผšๅปบ็ซ‹ไธ€ๅ€‹ `FastAPI`ใ€Œๅฏฆไพ‹ใ€ { #step-2-create-a-fastapi-instance } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} ้€™่ฃก็š„ `app` ่ฎŠๆ•ธๅฐ‡ๆœƒๆ˜ฏ `FastAPI` ้กžๅˆฅ็š„ใ€Œๅฏฆไพ‹ใ€ใ€‚ @@ -266,12 +266,12 @@ https://example.com/items/foo #### ๅฎš็พฉไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ { #define-a-path-operation-decorator } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} `@app.get("/")` ๅ‘Š่จด **FastAPI** ้‚ฃๅ€‹ๅ‡ฝๅผ่ฒ ่ฒฌ่™•็†่ซ‹ๆฑ‚๏ผš * ่ทฏๅพ‘ `/` -* ไฝฟ็”จ getๆ“ไฝœ +* ไฝฟ็”จ get ๆ“ไฝœ /// info | `@decorator` ่ชชๆ˜Ž @@ -320,7 +320,7 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ * **operation**๏ผšๆ˜ฏ `get`ใ€‚ * **function**๏ผšๆ˜ฏ่ฃ้ฃพๅ™จไธ‹้ข็š„ๅ‡ฝๅผ๏ผˆๅœจ `@app.get("/")` ไธ‹้ข๏ผ‰ใ€‚ -{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} ้€™ๅฐฑๆ˜ฏไธ€ๅ€‹ Python ๅ‡ฝๅผใ€‚ @@ -332,7 +332,7 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ ไฝ ไนŸๅฏไปฅๅฐ‡ๅฎƒๅฎš็พฉ็‚บไธ€่ˆฌๅ‡ฝๅผ๏ผŒ่€Œไธๆ˜ฏ `async def`๏ผš -{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *} +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} /// note @@ -342,7 +342,7 @@ Python ไธญ็š„ `@something` ่ชžๆณ•่ขซ็จฑ็‚บใ€Œ่ฃ้ฃพๅ™จใ€ใ€‚ ### ็ฌฌไบ”ๆญฅ๏ผšๅ›žๅ‚ณๅ…งๅฎน { #step-5-return-the-content } -{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *} +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} ไฝ ๅฏไปฅ่ฟ”ๅ›žไธ€ๅ€‹ `dict`ใ€`list`ใ€ๅ–ฎๅ€‹ๅ€ผไฝœ็‚บ `str`ใ€`int` ็ญ‰ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/handling-errors.md b/docs/zh-hant/docs/tutorial/handling-errors.md new file mode 100644 index 0000000000..f3a7573cd5 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# ้Œฏ่ชค่™•็† { #handling-errors } + +ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒไฝ ้œ€่ฆ้€š็Ÿฅไฝฟ็”จไฝ  API ็š„็”จๆˆถ็ซฏ็™ผ็”Ÿ้Œฏ่ชคใ€‚ + +้€™ๅ€‹็”จๆˆถ็ซฏๅฏ่ƒฝๆ˜ฏๅธถๆœ‰ๅ‰็ซฏ็š„็€่ฆฝๅ™จใ€ไป–ไบบ็š„็จ‹ๅผ็ขผใ€IoT ่ฃ็ฝฎ็ญ‰ใ€‚ + +ไฝ ๅฏ่ƒฝ้œ€่ฆๅ‘Š่จด็”จๆˆถ็ซฏ๏ผš + +* ็”จๆˆถ็ซฏๆฒ’ๆœ‰่ถณๅค ๆฌŠ้™ๅŸท่กŒ่ฉฒๆ“ไฝœใ€‚ +* ็”จๆˆถ็ซฏๆฒ’ๆœ‰ๆฌŠ้™ๅญ˜ๅ–่ฉฒ่ณ‡ๆบใ€‚ +* ็”จๆˆถ็ซฏๅ˜—่ฉฆๅญ˜ๅ–็š„้ …็›ฎไธๅญ˜ๅœจใ€‚ +* ็ญ‰็ญ‰ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒ้€šๅธธๆœƒๅ›žๅ‚ณ็ฏ„ๅœ็‚บ 400๏ผˆ400 ๅˆฐ 499๏ผ‰็š„ HTTP ็‹€ๆ…‹็ขผใ€‚ + +้€™้กžไผผๆ–ผ 200 ็ฏ„ๅœ็š„ HTTP ็‹€ๆ…‹็ขผ๏ผˆ200 ๅˆฐ 299๏ผ‰ใ€‚้‚ฃไบ›ใ€Œ200ใ€็‹€ๆ…‹็ขผ่กจ็คบ่ซ‹ๆฑ‚ๅœจๆŸ็จฎ็จ‹ๅบฆไธŠๆ˜ฏใ€ŒๆˆๅŠŸใ€็š„ใ€‚ + +400 ็ฏ„ๅœ็š„็‹€ๆ…‹็ขผ่กจ็คบ็”จๆˆถ็ซฏ้Œฏ่ชคใ€‚ + +้‚„่จ˜ๅพ—้‚ฃไบ›ใ€Œ404 Not Foundใ€้Œฏ่ชค๏ผˆๅ’Œๆข—๏ผ‰ๅ—Ž๏ผŸ + +## ไฝฟ็”จ `HTTPException` { #use-httpexception } + +่ฆๅ‘็”จๆˆถ็ซฏๅ›žๅ‚ณๅธถๆœ‰้Œฏ่ชค็š„ HTTP ๅ›žๆ‡‰๏ผŒไฝฟ็”จ `HTTPException`ใ€‚ + +### ๅŒฏๅ…ฅ `HTTPException` { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} + +### ๅœจ็จ‹ๅผไธญ raise ไธ€ๅ€‹ `HTTPException` { #raise-an-httpexception-in-your-code } + +`HTTPException` ๆ˜ฏไธ€่ˆฌ็š„ Python ไพ‹ๅค–๏ผŒไฝ†ๅŒ…ๅซ่ˆ‡ API ็›ธ้—œ็š„้™„ๅŠ ่ณ‡ๆ–™ใ€‚ + +ๅ› ็‚บๅฎƒๆ˜ฏ Python ็š„ไพ‹ๅค–๏ผŒไฝ ไธๆ˜ฏ `return`๏ผŒ่€Œๆ˜ฏ `raise`ใ€‚ + +้€™ไนŸ่กจ็คบ๏ผŒๅฆ‚ๆžœไฝ ๅœจๆŸๅ€‹ๅทฅๅ…ทๅ‡ฝๅผไธญ๏ผˆ่ฉฒๅ‡ฝๅผ่ขซไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ‘ผๅซ๏ผ‰๏ผŒไธฆๅœจ่ฉฒๅทฅๅ…ทๅ‡ฝๅผ่ฃก raise `HTTPException`๏ผŒ้‚ฃ้บผใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ‰ฉไธ‹็š„็จ‹ๅผ็ขผๅฐ‡ไธๆœƒๅŸท่กŒ๏ผ›่ฉฒ่ซ‹ๆฑ‚ๆœƒ็ซ‹ๅˆป่ขซ็ต‚ๆญข๏ผŒไธฆๅฐ‡ `HTTPException` ็š„ HTTP ้Œฏ่ชคๅ‚ณๅ›ž็ตฆ็”จๆˆถ็ซฏใ€‚ + +็‚บไฝ•้ธๆ“‡ raise ไพ‹ๅค–่€Œ้žๅ›žๅ‚ณๅ€ผ็š„ๅฅฝ่™•๏ผŒๆœƒๅœจ็›ธไพๆ€ง่ˆ‡ๅฎ‰ๅ…จๆ€ง็ซ ็ฏ€ๆ›ด็‚บๆ˜Ž้กฏใ€‚ + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒ็•ถ็”จๆˆถ็ซฏไปฅไธๅญ˜ๅœจ็š„ ID ่ซ‹ๆฑ‚้ …็›ฎๆ™‚๏ผŒraise ไธ€ๅ€‹็‹€ๆ…‹็ขผ็‚บ `404` ็š„ไพ‹ๅค–๏ผš + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} + +### ๅ›žๆ‡‰็ตๆžœ { #the-resulting-response } + +ๅฆ‚ๆžœ็”จๆˆถ็ซฏ่ซ‹ๆฑ‚ `http://example.com/items/foo`๏ผˆ`item_id` ็‚บ `"foo"`๏ผ‰๏ผŒๆœƒๆ”ถๅˆฐ 200 ็š„ HTTP ็‹€ๆ…‹็ขผ๏ผŒไปฅๅŠไปฅไธ‹ JSON ๅ›žๆ‡‰๏ผš + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +ไฝ†ๅฆ‚ๆžœ็”จๆˆถ็ซฏ่ซ‹ๆฑ‚ `http://example.com/items/bar`๏ผˆไธๅญ˜ๅœจ็š„ `item_id` `"bar"`๏ผ‰๏ผŒๆœƒๆ”ถๅˆฐ 404๏ผˆ"not found"๏ผ‰็š„ HTTP ็‹€ๆ…‹็ขผ๏ผŒไปฅๅŠไปฅไธ‹ JSON ๅ›žๆ‡‰๏ผš + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip + +ๅœจ raise ไธ€ๅ€‹ `HTTPException` ๆ™‚๏ผŒไฝ ๅฏไปฅๅฐ‡ไปปไฝ•ๅฏ่ฝ‰็‚บ JSON ็š„ๅ€ผไฝœ็‚บ `detail` ๅƒๆ•ธ๏ผŒไธๅช้™ๆ–ผ `str`ใ€‚ + +ไฝ ๅฏไปฅๅ‚ณๅ…ฅ `dict`ใ€`list` ็ญ‰ใ€‚ + +**FastAPI** ๆœƒ่‡ชๅ‹•่™•็†ไธฆ่ฝ‰็‚บ JSONใ€‚ + +/// + +## ๆ–ฐๅขž่‡ช่จ‚ๆจ™้ ญ { #add-custom-headers } + +ๆœ‰ไบ›ๆƒ…ๆณ้œ€่ฆๅœจ HTTP ้Œฏ่ชคๅ›žๆ‡‰ไธญๅŠ ๅ…ฅ่‡ช่จ‚ๆจ™้ ญ๏ผŒไพ‹ๅฆ‚ๆŸไบ›ๅฎ‰ๅ…จๆ€งๆƒ…ๅขƒใ€‚ + +ไฝ ๅคงๆฆ‚ไธ้œ€่ฆๅœจ็จ‹ๅผ็ขผไธญ็›ดๆŽฅไฝฟ็”จใ€‚ + +ไฝ†่‹ฅไฝ ๅœจ้€ฒ้šŽๆƒ…ๅขƒไธญ้œ€่ฆ๏ผŒๅฏไปฅ้€™ๆจฃๅŠ ๅ…ฅ่‡ช่จ‚ๆจ™้ ญ๏ผš + +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} + +## ๅฎ‰่ฃ่‡ช่จ‚ไพ‹ๅค–่™•็†ๅ™จ { #install-custom-exception-handlers } + +ไฝ ๅฏไปฅไฝฟ็”จ Starlette ็š„็›ธๅŒไพ‹ๅค–ๅทฅๅ…ท ไพ†ๅŠ ๅ…ฅ่‡ช่จ‚ไพ‹ๅค–่™•็†ๅ™จใ€‚ + +ๅ‡่จญไฝ ๆœ‰ไธ€ๅ€‹่‡ช่จ‚ไพ‹ๅค– `UnicornException`๏ผŒไฝ ๏ผˆๆˆ–ไฝ ไฝฟ็”จ็š„ๅ‡ฝๅผๅบซ๏ผ‰ๅฏ่ƒฝๆœƒ `raise` ๅฎƒใ€‚ + +่€Œไฝ ๆƒณ็”จ FastAPI ๅ…จๅŸŸ่™•็†้€™ๅ€‹ไพ‹ๅค–ใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `@app.exception_handler()` ๅŠ ๅ…ฅ่‡ช่จ‚ไพ‹ๅค–่™•็†ๅ™จ๏ผš + +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} + +ๅœจ้€™่ฃก๏ผŒๅฆ‚ๆžœไฝ ่ซ‹ๆฑ‚ `/unicorns/yolo`๏ผŒ่ฉฒใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆœƒ `raise` ไธ€ๅ€‹ `UnicornException`ใ€‚ + +ไฝ†ๅฎƒๆœƒ่ขซ `unicorn_exception_handler` ๆ‰€่™•็†ใ€‚ + +ๅ› ๆญคไฝ ๆœƒๅพ—ๅˆฐไธ€ๅ€‹ไนพๆทจ็š„้Œฏ่ชคๅ›žๆ‡‰๏ผŒHTTP ็‹€ๆ…‹็ขผ็‚บ `418`๏ผŒJSON ๅ…งๅฎนๅฆ‚ไธ‹๏ผš + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request` ่ˆ‡ `from starlette.responses import JSONResponse`ใ€‚ + +**FastAPI** ไปฅไพฟๅˆฉๆ€ง็‚บ็”ฑ๏ผŒๆไพ›ๅ’Œ `starlette.responses` ็›ธๅŒ็š„ไป‹้ขๆ–ผ `fastapi.responses`ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅž‹ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚`Request` ไนŸไธ€ๆจฃใ€‚ + +/// + +## ่ฆ†ๅฏซ้ ่จญไพ‹ๅค–่™•็†ๅ™จ { #override-the-default-exception-handlers } + +**FastAPI** ๅ…งๅปบไบ†ไธ€ไบ›้ ่จญไพ‹ๅค–่™•็†ๅ™จใ€‚ + +้€™ไบ›่™•็†ๅ™จ่ฒ ่ฒฌๅœจไฝ  `raise` ไธ€ๅ€‹ `HTTPException` ๆˆ–่ซ‹ๆฑ‚ๅธถๆœ‰็„กๆ•ˆ่ณ‡ๆ–™ๆ™‚๏ผŒๅ›žๅ‚ณ้ ่จญ็š„ JSON ๅ›žๆ‡‰ใ€‚ + +ไฝ ๅฏไปฅ็”จ่‡ชๅทฑ็š„่™•็†ๅ™จไพ†่ฆ†ๅฏซๅฎƒๅ€‘ใ€‚ + +### ่ฆ†ๅฏซ่ซ‹ๆฑ‚้ฉ—่ญ‰ไพ‹ๅค– { #override-request-validation-exceptions } + +็•ถ่ซ‹ๆฑ‚ๅŒ…ๅซ็„กๆ•ˆ่ณ‡ๆ–™ๆ™‚๏ผŒ**FastAPI** ๆœƒๅœจๅ…ง้ƒจ raise ไธ€ๅ€‹ `RequestValidationError`ใ€‚ + +ๅฎƒๅŒๆ™‚ไนŸๅŒ…ๅซไบ†ๅฐๆ‡‰็š„้ ่จญไพ‹ๅค–่™•็†ๅ™จใ€‚ + +่ฆ่ฆ†ๅฏซๅฎƒ๏ผŒๅŒฏๅ…ฅ `RequestValidationError`๏ผŒไธฆ็”จ `@app.exception_handler(RequestValidationError)` ไพ†่ฃ้ฃพไฝ ็š„ไพ‹ๅค–่™•็†ๅ™จใ€‚ + +ไพ‹ๅค–่™•็†ๅ™จๆœƒๆŽฅๆ”ถไธ€ๅ€‹ `Request` ๅ’Œ่ฉฒไพ‹ๅค–ใ€‚ + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} + +็พๅœจ๏ผŒๅฆ‚ๆžœไฝ ๅ‰ๅพ€ `/items/foo`๏ผŒ้ ่จญ็š„ JSON ้Œฏ่ชคๆœฌๆ‡‰็‚บ๏ผš + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +ไฝ ๅฐ‡ๆœƒๆ”น่€Œๅพ—ๅˆฐๆ–‡ๅญ—็‰ˆ๏ผš + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### ่ฆ†ๅฏซ `HTTPException` ็š„้Œฏ่ชค่™•็†ๅ™จ { #override-the-httpexception-error-handler } + +ๅŒๆจฃๅœฐ๏ผŒไฝ ไนŸๅฏไปฅ่ฆ†ๅฏซ `HTTPException` ็š„่™•็†ๅ™จใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๆƒณๅœจ้€™ไบ›้Œฏ่ชคๆ™‚ๅ›žๅ‚ณ็ด”ๆ–‡ๅญ—่€Œ้ž JSON๏ผš + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import PlainTextResponse`ใ€‚ + +**FastAPI** ไปฅไพฟๅˆฉๆ€ง็‚บ็”ฑ๏ผŒๆไพ›ๅ’Œ `starlette.responses` ็›ธๅŒ็š„ไป‹้ขๆ–ผ `fastapi.responses`ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅž‹ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +/// warning + +่ซ‹ๆณจๆ„๏ผŒ`RequestValidationError` ๅ…งๅซ้ฉ—่ญ‰้Œฏ่ชค็™ผ็”Ÿ็š„ๆช”ๅ่ˆ‡่กŒ่™Ÿ๏ผŒๅฆ‚ๆžœไฝ ้ก˜ๆ„๏ผŒๅฏไปฅๅœจๆ—ฅ่ชŒไธญ้กฏ็คบ้€™ไบ›็›ธ้—œ่ณ‡่จŠใ€‚ + +ไฝ†้€™ไนŸไปฃ่กจๅฆ‚ๆžœไฝ ๅชๆ˜ฏๆŠŠๅฎƒ่ฝ‰ๆˆๅญ—ไธฒไธฆ็›ดๆŽฅๅ›žๅ‚ณ๏ผŒๅฏ่ƒฝๆœƒๆดฉๆผไธ€ไบ›้—œๆ–ผไฝ ็ณป็ตฑ็š„่ณ‡่จŠใ€‚ๅ› ๆญค้€™่ฃก็š„็จ‹ๅผ็ขผๆœƒๅˆ†ๅˆฅๆ“ทๅ–ไธฆ้กฏ็คบๆฏๅ€‹้Œฏ่ชคใ€‚ + +/// + +### ไฝฟ็”จ `RequestValidationError` ็š„ body { #use-the-requestvalidationerror-body } + +`RequestValidationError` ๅŒ…ๅซๅฎƒๆ”ถๅˆฐ็š„๏ผˆไฝ†็„กๆ•ˆ็š„๏ผ‰`body`ใ€‚ + +ๅœจ้–‹็™ผๆ‡‰็”จๆ™‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒไพ†่จ˜้Œ„ body ไธฆ้™ค้Œฏใ€ๅ›žๅ‚ณ็ตฆไฝฟ็”จ่€…็ญ‰ใ€‚ + +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} + +็พๅœจๅ˜—่ฉฆ้€ๅ‡บไธ€ๅ€‹็„กๆ•ˆ็š„้ …็›ฎ๏ผŒไพ‹ๅฆ‚๏ผš + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +ไฝ ๆœƒๆ”ถๅˆฐไธ€ๅ€‹ๅ‘Š็Ÿฅ่ณ‡ๆ–™็„กๆ•ˆใ€ไธ”ๅŒ…ๅซๆ‰€ๆ”ถๅˆฐ body ็š„ๅ›žๆ‡‰๏ผš + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### FastAPI ็š„ `HTTPException` ่ˆ‡ Starlette ็š„ `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI** ๆœ‰่‡ชๅทฑๅฎš็พฉ็š„ `HTTPException`ใ€‚ + +่€Œ **FastAPI** ็š„ `HTTPException` ้Œฏ่ชค้กžๅˆฅๆ˜ฏ็นผๆ‰ฟ่‡ช Starlette ็š„ `HTTPException` ้Œฏ่ชค้กžๅˆฅใ€‚ + +ๅ”ฏไธ€็š„ๅทฎ็•ฐๆ˜ฏ๏ผŒ**FastAPI** ็š„ `HTTPException` ๅœจ `detail` ๆฌ„ไฝๆŽฅๅ—ไปปไฝ•ๅฏ่ฝ‰็‚บ JSON ็š„่ณ‡ๆ–™๏ผŒ่€Œ Starlette ็š„ `HTTPException` ๅชๆŽฅๅ—ๅญ—ไธฒใ€‚ + +ๅ› ๆญค๏ผŒๅœจไฝ ็š„็จ‹ๅผ็ขผไธญ๏ผŒไฝ ๅฏไปฅไธ€ๅฆ‚ๅพ€ๅธธๅœฐ raise **FastAPI** ็š„ `HTTPException`ใ€‚ + +ไฝ†็•ถไฝ ่จปๅ†Šไพ‹ๅค–่™•็†ๅ™จๆ™‚๏ผŒๆ‡‰่ฉฒ้‡ๅฐ Starlette ็š„ `HTTPException` ไพ†่จปๅ†Šใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅฆ‚ๆžœ Starlette ็š„ๅ…ง้ƒจ็จ‹ๅผ็ขผ๏ผŒๆˆ–ไปปไฝ• Starlette ๆ“ดๅ……/ๅค–ๆŽ› raise ไบ† Starlette ็š„ `HTTPException`๏ผŒไฝ ็š„่™•็†ๅ™จๅฐฑ่ƒฝๆ””ๆˆชไธฆ่™•็†ๅฎƒใ€‚ + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒ็‚บไบ†่ƒฝๅœจๅŒไธ€ไปฝ็จ‹ๅผ็ขผไธญๅŒๆ™‚ไฝฟ็”จๅ…ฉ็จฎ `HTTPException`๏ผŒๆˆ‘ๅ€‘ๆŠŠ Starlette ็š„ไพ‹ๅค–้‡ๆ–ฐๅ‘ฝๅ็‚บ `StarletteHTTPException`๏ผš + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### ้‡็”จ **FastAPI** ็š„ไพ‹ๅค–่™•็†ๅ™จ { #reuse-fastapis-exception-handlers } + +ๅฆ‚ๆžœไฝ ๆƒณๅœจไฝฟ็”จไพ‹ๅค–็š„ๅŒๆ™‚๏ผŒๆฒฟ็”จ **FastAPI** ็š„้ ่จญไพ‹ๅค–่™•็†ๅ™จ๏ผŒไฝ ๅฏไปฅๅพž `fastapi.exception_handlers` ๅŒฏๅ…ฅไธฆ้‡็”จ้ ่จญ็š„่™•็†ๅ™จ๏ผš + +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒไฝ ๅชๆ˜ฏ็”จไธ€ๆฎตๅพˆ็”Ÿๅ‹•็š„่จŠๆฏๆŠŠ้Œฏ่ชคๅฐๅ‡บไพ†๏ผŒไธ้Ž้‡้ปžๆ˜ฏ๏ผšไฝ ๅฏไปฅไฝฟ็”จ่ฉฒไพ‹ๅค–๏ผŒ็„ถๅพŒ็›ดๆŽฅ้‡็”จ้ ่จญ็š„ไพ‹ๅค–่™•็†ๅ™จใ€‚ diff --git a/docs/zh-hant/docs/tutorial/header-param-models.md b/docs/zh-hant/docs/tutorial/header-param-models.md new file mode 100644 index 0000000000..ca2b1f8dee --- /dev/null +++ b/docs/zh-hant/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# ๆจ™้ ญๅƒๆ•ธๆจกๅž‹ { #header-parameter-models } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€็ต„็›ธ้—œ็š„ๆจ™้ ญๅƒๆ•ธ๏ผŒๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹ Pydantic ๆจกๅž‹ไพ†ๅฎฃๅ‘Šๅฎƒๅ€‘ใ€‚ + +้€™่ƒฝ่ฎ“ไฝ ๅœจๅคš่™•้‡่ค‡ไฝฟ็”จ่ฉฒๆจกๅž‹๏ผŒไธฆไธ€ๆฌกๆ€ง็‚บๆ‰€ๆœ‰ๅƒๆ•ธๅฎฃๅ‘Š้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ใ€‚๐Ÿ˜Ž + +/// note | ๆณจๆ„ + +่‡ช FastAPI ็‰ˆๆœฌ `0.115.0` ่ตทๆ”ฏๆดใ€‚๐Ÿค“ + +/// + +## ไปฅ Pydantic ๆจกๅž‹ๅฎฃๅ‘Šๆจ™้ ญๅƒๆ•ธ { #header-parameters-with-a-pydantic-model } + +ๅœจ Pydantic ๆจกๅž‹ไธญๅฎฃๅ‘Šไฝ ้œ€่ฆ็š„ๆจ™้ ญๅƒๆ•ธ๏ผŒ็„ถๅพŒๅฐ‡ๅƒๆ•ธๅฎฃๅ‘Š็‚บ `Header`๏ผš + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +FastAPI ๆœƒๅพž่ซ‹ๆฑ‚็š„ๆจ™้ ญ็‚บๆฏๅ€‹ๆฌ„ไฝๆ“ทๅ–่ณ‡ๆ–™๏ผŒไธฆไบค็ตฆไฝ ๅทฒๅฎš็พฉ็š„ Pydantic ๆจกๅž‹ๅฏฆไพ‹ใ€‚ + +## ๆชข่ฆ–ๆ–‡ไปถ { #check-the-docs } + +ไฝ ๅฏไปฅๅœจ `/docs` ็š„ๆ–‡ไปถไป‹้ข็œ‹ๅˆฐๆ‰€้œ€็š„ๆจ™้ ญ๏ผš + +
+ +
+ +## ็ฆๆญข้กๅค–ๆจ™้ ญ { #forbid-extra-headers } + +ๅœจๆŸไบ›็‰นๆฎŠๆƒ…ๅขƒ๏ผˆๅฏ่ƒฝไธๅธธ่ฆ‹๏ผ‰ไธ‹๏ผŒไฝ ๅฏ่ƒฝๆƒณ้™ๅˆถๅ…่จฑๆŽฅๆ”ถ็š„ๆจ™้ ญใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹่จญๅฎšไพ† `forbid` ไปปไฝ• `extra` ๆฌ„ไฝ๏ผš + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +ๅฆ‚ๆžœ็”จๆˆถ็ซฏๅ˜—่ฉฆๅ‚ณ้€้กๅค–็š„ๆจ™้ ญ๏ผŒๆœƒๆ”ถๅˆฐ้Œฏ่ชคๅ›žๆ‡‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็”จๆˆถ็ซฏ่‹ฅๅ‚ณ้€ๅ็‚บ `tool`ใ€ๅ€ผ็‚บ `plumbus` ็š„ๆจ™้ ญ๏ผŒๆœƒๆ”ถๅˆฐ้Œฏ่ชคๅ›žๆ‡‰๏ผŒๆŒ‡ๅ‡บไธๅ…่จฑๆจ™้ ญๅƒๆ•ธ `tool`๏ผš + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## ๅœ็”จๅบ•็ทš่ฝ‰ๆ› { #disable-convert-underscores } + +่ˆ‡ไธ€่ˆฌๆจ™้ ญๅƒๆ•ธ็›ธๅŒ๏ผŒ็•ถๅƒๆ•ธๅ็จฑๅŒ…ๅซๅบ•็ทšๅญ—ๅ…ƒๆ™‚๏ผŒๆœƒ่‡ชๅ‹•่ฝ‰ๆ›็‚บ้€ฃๅญ—่™Ÿใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่‹ฅๅœจ็จ‹ๅผ็ขผไธญๆœ‰ๆจ™้ ญๅƒๆ•ธ `save_data`๏ผŒๅฏฆ้š›ๆœŸๆœ›็š„ HTTP ๆจ™้ ญ็‚บ `save-data`๏ผŒๅœจๆ–‡ไปถไธญไนŸๆœƒๅฆ‚ๆญค้กฏ็คบใ€‚ + +ๅฆ‚ๆžœๅ› ๆŸไบ›ๅŽŸๅ› ้œ€่ฆๅœ็”จ้€™ๅ€‹่‡ชๅ‹•่ฝ‰ๆ›๏ผŒไฝ ไนŸๅฏไปฅๅœจๆจ™้ ญๅƒๆ•ธ็š„ Pydantic ๆจกๅž‹ไธŠ่จญๅฎšใ€‚ + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | ่ญฆๅ‘Š + +ๅœจๅฐ‡ `convert_underscores` ่จญ็‚บ `False` ไน‹ๅ‰๏ผŒ่ซ‹ๆณจๆ„ๆœ‰ไบ› HTTP ไปฃ็†่ˆ‡ไผบๆœๅ™จไธๅ…่จฑๅซๆœ‰ๅบ•็ทš็š„ๆจ™้ ญใ€‚ + +/// + +## ๆ‘˜่ฆ { #summary } + +ไฝ ๅฏไปฅๅœจ FastAPI ไธญไฝฟ็”จ Pydantic ๆจกๅž‹ๅฎฃๅ‘Šๆจ™้ ญใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/tutorial/header-params.md b/docs/zh-hant/docs/tutorial/header-params.md new file mode 100644 index 0000000000..2d6aade4bb --- /dev/null +++ b/docs/zh-hant/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Header ๅƒๆ•ธ { #header-parameters } + +ไฝ ๅฏไปฅ็”จ่ˆ‡ๅฎš็พฉ `Query`ใ€`Path`ใ€`Cookie` ๅƒๆ•ธ็›ธๅŒ็š„ๆ–นๅผไพ†ๅฎš็พฉ Header ๅƒๆ•ธใ€‚ + +## ๅŒฏๅ…ฅ `Header` { #import-header } + +ๅ…ˆๅŒฏๅ…ฅ `Header`๏ผš + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## ๅฎฃๅ‘Š `Header` ๅƒๆ•ธ { #declare-header-parameters } + +ๆŽฅ่‘—ไฝฟ็”จ่ˆ‡ `Path`ใ€`Query`ใ€`Cookie` ็›ธๅŒ็š„็ตๆง‹ไพ†ๅฎฃๅ‘Šๆจ™้ ญๅƒๆ•ธใ€‚ + +ไฝ ๅฏไปฅ่จญๅฎš้ ่จญๅ€ผ๏ผŒไปฅๅŠๆ‰€ๆœ‰้กๅค–็š„้ฉ—่ญ‰ๆˆ–่จป่งฃๅƒๆ•ธ๏ผš + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | ๆณจๆ„ + +`Header` ่ˆ‡ `Path`ใ€`Query`ใ€`Cookie` ๆ˜ฏใ€ŒๅงŠๅฆนใ€้กžๅˆฅ๏ผŒๅŒๆจฃ็นผๆ‰ฟ่‡ชๅ…ฑๅŒ็š„ `Param` ้กžๅˆฅใ€‚ + +ไฝ†่ซ‹่จ˜ๅพ—๏ผŒ็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path`ใ€`Header` ็ญ‰ๆ™‚๏ผŒๅฎƒๅ€‘ๅ…ถๅฏฆๆ˜ฏๆœƒๅ›žๅ‚ณ็‰นๆฎŠ้กžๅˆฅ็š„ๅ‡ฝๅผใ€‚ + +/// + +/// info | ่ชชๆ˜Ž + +่ฆๅฎฃๅ‘Šๆจ™้ ญ๏ผŒๅฟ…้ ˆไฝฟ็”จ `Header`๏ผŒๅฆๅ‰‡ๅƒๆ•ธๆœƒ่ขซ่งฃ่ฎ€็‚บๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +/// + +## ่‡ชๅ‹•่ฝ‰ๆ› { #automatic-conversion } + +ๅœจ `Path`ใ€`Query`ใ€`Cookie` ๆไพ›็š„ๅŠŸ่ƒฝไน‹ไธŠ๏ผŒ`Header` ้‚„ๆœ‰ไธ€ไบ›้กๅค–็š„ๅฐๅŠŸ่ƒฝใ€‚ + +ๅคงๅคšๆ•ธๆจ™ๆบ–ๆจ™้ ญ็š„ๅ–ฎๅญ—ไปฅ้€ฃๅญ—่™Ÿ๏ผˆๆธ›่™Ÿ๏ผŒ`-`๏ผ‰ๅˆ†้š”ใ€‚ + +ไฝ†ๅƒ `user-agent` ้€™ๆจฃ็š„่ฎŠๆ•ธๅ็จฑๅœจ Python ไธญๆ˜ฏ็„กๆ•ˆ็š„ใ€‚ + +ๅ› ๆญค๏ผŒ`Header` ๆœƒๅœจ้ ่จญๆƒ…ๆณไธ‹ๆŠŠๅƒๆ•ธๅ็จฑไธญ็š„ๅบ•็ทš๏ผˆ`_`๏ผ‰่ฝ‰ๆ›็‚บ้€ฃๅญ—่™Ÿ๏ผˆ`-`๏ผ‰๏ผŒไปฅไพฟ่ฎ€ๅ–ไธฆๅœจๆ–‡ไปถไธญ้กฏ็คบ่ฉฒๆจ™้ ญใ€‚ + +ๆญคๅค–๏ผŒHTTP ๆจ™้ ญไธๅ€ๅˆ†ๅคงๅฐๅฏซ๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅไฝฟ็”จๆจ™ๆบ–็š„ Python ๅ‘ฝๅ้ขจๆ ผ๏ผˆsnake_case๏ผ‰ไพ†ๅฎฃๅ‘Šใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅๅƒๅœจ Python ็จ‹ๅผไธญไธ€ๆจฃไฝฟ็”จ `user_agent`๏ผŒไธ้œ€่ฆๆŠŠ้ฆ–ๅญ—ๆฏๅคงๅฏซๆˆ `User_Agent` ๆˆ–้กžไผผๅฏซๆณ•ใ€‚ + +่‹ฅๅ› ๆŸไบ›ๅŽŸๅ› ้œ€่ฆๅœ็”จๅบ•็ทš่‡ชๅ‹•่ฝ‰้€ฃๅญ—่™Ÿ็š„่กŒ็‚บ๏ผŒๅฐ‡ `Header` ็š„ `convert_underscores` ๅƒๆ•ธ่จญ็‚บ `False`๏ผš + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | ่ญฆๅ‘Š + +ๅœจๅฐ‡ `convert_underscores` ่จญ็‚บ `False` ไน‹ๅ‰๏ผŒ่ซ‹ๆณจๆ„ๆœ‰ไบ› HTTP ไปฃ็†่ˆ‡ไผบๆœๅ™จไธๅ…่จฑไฝฟ็”จๅธถๆœ‰ๅบ•็ทš็š„ๆจ™้ ญใ€‚ + +/// + +## ้‡่ค‡็š„ๆจ™้ ญ { #duplicate-headers } + +ๆœ‰ๆ™‚ๅฏ่ƒฝๆœƒๆ”ถๅˆฐ้‡่ค‡็š„ๆจ™้ ญ๏ผŒไนŸๅฐฑๆ˜ฏๅŒไธ€ๅ€‹ๆจ™้ ญๆœƒๆœ‰ๅคšๅ€‹ๅ€ผใ€‚ + +ๅฏไปฅๅœจๅž‹ๅˆฅๅฎฃๅ‘Šไธญไฝฟ็”จ list ไพ†ๅฎš็พฉ้€™็จฎๆƒ…ๆณใ€‚ + +ไฝ ๆœƒไปฅ Python ็š„ `list` ๅฝขๅผๆ”ถๅˆฐ่ฉฒ้‡่ค‡ๆจ™้ ญ็š„ๆ‰€ๆœ‰ๅ€ผใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฆๅฎฃๅ‘Šๅฏไปฅๅ‡บ็พๅคšๆฌก็š„ `X-Token` ๆจ™้ ญ๏ผŒๅฏไปฅ้€™ๆจฃๅฏซ๏ผš + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +ๅฆ‚ๆžœไฝ ๅœจ่ˆ‡่ฉฒ*่ทฏๅพ‘ๆ“ไฝœ (path operation)* ๆบ้€šๆ™‚้€ๅ‡บๅ…ฉๅ€‹ HTTP ๆจ™้ ญๅฆ‚ไธ‹๏ผš + +``` +X-Token: foo +X-Token: bar +``` + +ๅ›žๆ‡‰ๆœƒๅƒ้€™ๆจฃ๏ผš + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## ๅฐ็ต { #recap } + +ไฝฟ็”จ `Header` ๅฎฃๅ‘Šๆจ™้ ญ๏ผŒๅฅ—็”จ่ˆ‡ `Query`ใ€`Path`ใ€`Cookie` ็›ธๅŒ็š„้€š็”จๆจกๅผใ€‚ + +่€Œไธ”ๅˆฅๆ“”ๅฟƒ่ฎŠๆ•ธๅ็จฑไธญ็š„ๅบ•็ทš๏ผŒ**FastAPI** ๆœƒ่‡ชๅ‹•ๅนซไฝ ่ฝ‰ๆ›ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/metadata.md b/docs/zh-hant/docs/tutorial/metadata.md new file mode 100644 index 0000000000..3243efa89c --- /dev/null +++ b/docs/zh-hant/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# ไธญ็นผ่ณ‡ๆ–™่ˆ‡ๆ–‡ไปถ URL { #metadata-and-docs-urls } + +ไฝ ๅฏไปฅๅœจไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผไธญ่‡ช่จ‚ๅคš้ …ไธญ็นผ่ณ‡ๆ–™่จญๅฎšใ€‚ + +## API ็š„ไธญ็นผ่ณ‡ๆ–™ { #metadata-for-api } + +ไฝ ๅฏไปฅ่จญๅฎšไธ‹ๅˆ—ๆฌ„ไฝ๏ผŒ้€™ไบ›ๆฌ„ไฝๆœƒ็”จๅœจ OpenAPI ่ฆๆ ผ่ˆ‡่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถไป‹้ขไธญ๏ผš + +| ๅƒๆ•ธ | ๅž‹ๅˆฅ | ่ชชๆ˜Ž | +|------------|------|-------------| +| `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`ใ€‚ | +| `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 ๆŽˆๆฌŠ่กจ็คบๅผใ€‚identifier ๆฌ„ไฝ่ˆ‡ url ๆฌ„ไฝไบ’ๆ–ฅใ€‚่‡ช OpenAPI 3.1.0ใ€FastAPI 0.99.0 ่ตทๅฏ็”จใ€‚
urlstrAPI ๆ‰€ๆŽก็”จๆŽˆๆฌŠ็š„ URLใ€‚ๅฟ…้ ˆๆ˜ฏ URL ๆ ผๅผใ€‚
| + +ไฝ ๅฏไปฅ้€™ๆจฃ่จญๅฎšๅฎƒๅ€‘๏ผš + +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} + +/// tip | ๆ็คบ + +ไฝ ๅฏไปฅๅœจ `description` ๆฌ„ไฝไธญๆ’ฐๅฏซ Markdown๏ผŒ่ผธๅ‡บๆ™‚ๆœƒ่ขซๆญฃ็ขบๆธฒๆŸ“ใ€‚ + +/// + +ไฝฟ็”จ้€™ไบ›่จญๅฎšๅพŒ๏ผŒ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถๆœƒๅƒ้€™ๆจฃ๏ผš + + + +## ๆŽˆๆฌŠ่ญ˜ๅˆฅ็ขผ { #license-identifier } + +่‡ช OpenAPI 3.1.0 ่ˆ‡ FastAPI 0.99.0 ่ตท๏ผŒไฝ ไนŸๅฏไปฅๅœจ `license_info` ไธญไฝฟ็”จ `identifier` ไพ†ๅ–ไปฃ `url`ใ€‚ + +ไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} + +## ๆจ™็ฑค็š„ไธญ็นผ่ณ‡ๆ–™ { #metadata-for-tags } + +ไฝ ไนŸๅฏไปฅ้€้Ž `openapi_tags` ๅƒๆ•ธ๏ผŒ็‚บ็”จไพ†ๅˆ†็ต„ไฝ ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰็š„ๅ„ๅ€‹ๆจ™็ฑคๅŠ ๅ…ฅ้กๅค–ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +ๅฎƒๆŽฅๆ”ถไธ€ๅ€‹ list๏ผŒๅ…ถไธญๆฏๅ€‹ๆจ™็ฑคๅฐๆ‡‰ไธ€ๅ€‹ dictionaryใ€‚ + +ๆฏๅ€‹ dictionary ๅฏๅŒ…ๅซ๏ผš + +* `name`๏ผˆ**ๅฟ…ๅกซ**๏ผ‰๏ผšไธ€ๅ€‹ `str`๏ผŒๅ…ถๅ€ผ้œ€่ˆ‡ไฝ ๅœจ่ทฏๅพ‘ๆ“ไฝœ่ˆ‡ `APIRouter`s ็š„ `tags` ๅƒๆ•ธไธญไฝฟ็”จ็š„ๆจ™็ฑคๅ็จฑ็›ธๅŒใ€‚ +* `description`๏ผšไธ€ๅ€‹ `str`๏ผŒ็‚บ่ฉฒๆจ™็ฑค็š„็ฐก็Ÿญๆ่ฟฐใ€‚ๅฏไฝฟ็”จ Markdown๏ผŒไธฆๆœƒ้กฏ็คบๅœจๆ–‡ไปถไป‹้ขไธญใ€‚ +* `externalDocs`๏ผšไธ€ๅ€‹ `dict`๏ผŒๆ่ฟฐๅค–้ƒจๆ–‡ไปถ๏ผŒๅŒ…ๅซ๏ผš + * `description`๏ผšไธ€ๅ€‹ `str`๏ผŒๅค–้ƒจๆ–‡ไปถ็š„็ฐก็Ÿญๆ่ฟฐใ€‚ + * `url`๏ผˆ**ๅฟ…ๅกซ**๏ผ‰๏ผšไธ€ๅ€‹ `str`๏ผŒๅค–้ƒจๆ–‡ไปถ็š„ URLใ€‚ + +### ๅปบ็ซ‹ๆจ™็ฑค็š„ไธญ็นผ่ณ‡ๆ–™ { #create-metadata-for-tags } + +ๆˆ‘ๅ€‘็”จ `users` ่ˆ‡ `items` ๅ…ฉๅ€‹ๆจ™็ฑคไพ†็คบ็ฏ„ใ€‚ + +ๅ…ˆ็‚บไฝ ็š„ๆจ™็ฑคๅปบ็ซ‹ไธญ็นผ่ณ‡ๆ–™๏ผŒ็„ถๅพŒๅฐ‡ๅฎƒๅ‚ณ็ตฆ `openapi_tags` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} + +ๆณจๆ„ไฝ ๅฏไปฅๅœจๆ่ฟฐไธญไฝฟ็”จ Markdown๏ผŒไพ‹ๅฆ‚ใ€Œloginใ€ๆœƒไปฅ็ฒ—้ซ”๏ผˆ**login**๏ผ‰้กฏ็คบ๏ผŒ่€Œใ€Œfancyใ€ๆœƒไปฅๆ–œ้ซ”๏ผˆ_fancy_๏ผ‰้กฏ็คบใ€‚ + +/// tip | ๆ็คบ + +ไฝ ไธๅฟ…็‚บไฝ ไฝฟ็”จๅˆฐ็š„ๆฏๅ€‹ๆจ™็ฑค้ƒฝๅŠ ๅ…ฅไธญ็นผ่ณ‡ๆ–™ใ€‚ + +/// + +### ไฝฟ็”จไฝ ็š„ๆจ™็ฑค { #use-your-tags } + +ๅœจไฝ ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆไปฅๅŠ `APIRouter`s๏ผ‰ไธŠไฝฟ็”จ `tags` ๅƒๆ•ธ๏ผŒๅฐ‡ๅฎƒๅ€‘ๆญธ้กžๅˆฐไธๅŒๆจ™็ฑคไธ‹๏ผš + +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} + +/// info | ่ณ‡่จŠ + +ๅœจ๏ผป่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš๏ผฝไธญ้–ฑ่ฎ€ๆ›ดๅคš้—œๆ–ผๆจ™็ฑค็š„ๅ…งๅฎน๏ผš[Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank}ใ€‚ + +/// + +### ๆชข่ฆ–ๆ–‡ไปถ { #check-the-docs } + +็พๅœจๆชข่ฆ–ๆ–‡ไปถๆ™‚๏ผŒๆœƒ็œ‹ๅˆฐๆ‰€ๆœ‰้กๅค–็š„ไธญ็นผ่ณ‡ๆ–™๏ผš + + + +### ๆจ™็ฑค้ †ๅบ { #order-of-tags } + +ๆฏๅ€‹ๆจ™็ฑคไธญ็นผ่ณ‡ๆ–™ dictionary ๅœจๆธ…ๅ–ฎไธญ็š„้ †ๅบ๏ผŒไนŸๆœƒๆฑบๅฎšๅฎƒๅ€‘ๅœจๆ–‡ไปถไป‹้ขไธญ็š„้กฏ็คบ้ †ๅบใ€‚ + +ไพ‹ๅฆ‚๏ผŒ้›–็„ถๆŒ‰ๅญ—ๆฏๆŽ’ๅบๆ™‚ `users` ๆœƒๆŽ’ๅœจ `items` ไน‹ๅพŒ๏ผŒไฝ†ๅ› ็‚บๆˆ‘ๅ€‘ๅœจๆธ…ๅ–ฎไธญๅฐ‡ๅฎƒ็š„ไธญ็นผ่ณ‡ๆ–™ๆ”พๅœจ็ฌฌไธ€ๅ€‹๏ผŒๆ‰€ไปฅๅฎƒๆœƒๅ…ˆ้กฏ็คบใ€‚ + +## OpenAPI URL { #openapi-url } + +้ ่จญๆƒ…ๆณไธ‹๏ผŒOpenAPI ็ถฑ่ฆ๏ผˆschema๏ผ‰ๆœƒๆไพ›ๅœจ `/openapi.json`ใ€‚ + +ไฝ†ไฝ ๅฏไปฅ็”จ `openapi_url` ๅƒๆ•ธไพ†่ชฟๆ•ดใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฐ‡ๅฎƒ่จญๅฎš็‚บๆไพ›ๅœจ `/api/v1/openapi.json`๏ผš + +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} + +ๅฆ‚ๆžœไฝ ๆƒณๅฎŒๅ…จๅœ็”จ OpenAPI ็ถฑ่ฆ๏ผŒๅฏไปฅ่จญๅฎš `openapi_url=None`๏ผŒๅŒๆ™‚ไนŸๆœƒๅœ็”จไพ่ณดๅฎƒ็š„ๆ–‡ไปถไฝฟ็”จ่€…ไป‹้ขใ€‚ + +## ๆ–‡ไปถ URL { #docs-urls } + +ไฝ ๅฏไปฅ่จญๅฎšๅ…งๅปบ็š„ๅ…ฉๅ€‹ๆ–‡ไปถไฝฟ็”จ่€…ไป‹้ข๏ผš + +* Swagger UI๏ผšๆไพ›ๆ–ผ `/docs`ใ€‚ + * ๅฏ็”จ `docs_url` ๅƒๆ•ธ่จญๅฎšๅ…ถ URLใ€‚ + * ่จญๅฎš `docs_url=None` ๅฏๅœ็”จใ€‚ +* ReDoc๏ผšๆไพ›ๆ–ผ `/redoc`ใ€‚ + * ๅฏ็”จ `redoc_url` ๅƒๆ•ธ่จญๅฎšๅ…ถ URLใ€‚ + * ่จญๅฎš `redoc_url=None` ๅฏๅœ็”จใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฐ‡ Swagger UI ๆไพ›ๆ–ผ `/documentation`๏ผŒไธฆๅœ็”จ ReDoc๏ผš + +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/zh-hant/docs/tutorial/middleware.md b/docs/zh-hant/docs/tutorial/middleware.md new file mode 100644 index 0000000000..ac6f5367d0 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/middleware.md @@ -0,0 +1,95 @@ +# ไธญไป‹่ปŸ้ซ” { #middleware } + +ไฝ ๅฏไปฅๅœจ **FastAPI** ๆ‡‰็”จ็จ‹ๅผไธญๅŠ ๅ…ฅไธญไป‹่ปŸ้ซ”ใ€‚ + +ใ€Œไธญไป‹่ปŸ้ซ”ใ€ๆ˜ฏไธ€ๅ€‹ๅ‡ฝๅผ๏ผŒๅœจไปปไฝ•็‰นๅฎš็š„*่ทฏๅพ‘ๆ“ไฝœ*่™•็†ไน‹ๅ‰ๅ…ˆ่™•็†ๆฏๅ€‹**่ซ‹ๆฑ‚**๏ผ›ๅœจๅ›žๅ‚ณไน‹ๅ‰๏ผŒไนŸๆœƒ่™•็†ๆฏๅ€‹**ๅ›žๆ‡‰**ใ€‚ + +- ๅฎƒๆœƒๆ””ๆˆช้€ฒๅˆฐๆ‡‰็”จ็จ‹ๅผ็š„ๆฏๅ€‹**่ซ‹ๆฑ‚**ใ€‚ +- ็„ถๅพŒๅฏไปฅๅฐ่ฉฒ**่ซ‹ๆฑ‚**ๅšไธ€ไบ›่™•็†ๆˆ–ๅŸท่กŒๆ‰€้œ€็š„็จ‹ๅผ็ขผใ€‚ +- ๆŽฅ่‘—ๆŠŠ**่ซ‹ๆฑ‚**ๅ‚ณ้ž็ตฆๆ‡‰็”จ็จ‹ๅผ็š„ๅ…ถ้ค˜้ƒจๅˆ†๏ผˆๆŸๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*๏ผ‰่™•็†ใ€‚ +- ไน‹ๅพŒๅ†ๆŽฅๆ”ถๆ‡‰็”จ็จ‹ๅผ๏ผˆๆŸๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*๏ผ‰ๆ‰€็”ข็”Ÿ็š„**ๅ›žๆ‡‰**ใ€‚ +- ๅฏไปฅๅฐ่ฉฒ**ๅ›žๆ‡‰**ๅšไธ€ไบ›่™•็†ๆˆ–ๅŸท่กŒๆ‰€้œ€็š„็จ‹ๅผ็ขผใ€‚ +- ็„ถๅพŒๅ›žๅ‚ณ**ๅ›žๆ‡‰**ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ๅฆ‚ๆžœไฝ ๆœ‰ไฝฟ็”จๅธถๆœ‰ `yield` ็š„็›ธไพๆ€ง๏ผŒๅ…ถ้‡‹ๆ”พ้šŽๆฎต็š„็จ‹ๅผ็ขผๆœƒๅœจไธญไป‹่ปŸ้ซ”ไน‹ๅพŒๅŸท่กŒใ€‚ + +่‹ฅๆœ‰่ƒŒๆ™ฏๅทฅไฝœ๏ผˆๅœจ[่ƒŒๆ™ฏๅทฅไฝœ](background-tasks.md){.internal-link target=_blank}ไธ€็ฏ€ๆœƒไป‹็ดน๏ผŒไฝ ็จๅพŒๆœƒ็œ‹ๅˆฐ๏ผ‰๏ผŒๅฎƒๅ€‘ๆœƒๅœจๆ‰€ๆœ‰ไธญไป‹่ปŸ้ซ”ไน‹ๅพŒๅŸท่กŒใ€‚ + +/// + +## ๅปบ็ซ‹ไธญไป‹่ปŸ้ซ” { #create-a-middleware } + +่ฆๅปบ็ซ‹ไธญไป‹่ปŸ้ซ”๏ผŒๅฐ‡่ฃ้ฃพๅ™จ `@app.middleware("http")` ๅŠ ๅœจๅ‡ฝๅผไธŠๆ–นใ€‚ + +ไธญไป‹่ปŸ้ซ”ๅ‡ฝๅผๆœƒๆŽฅๆ”ถ๏ผš + +- `request`ใ€‚ +- ไธ€ๅ€‹ๅ‡ฝๅผ `call_next`๏ผŒๆœƒไปฅ `request` ไฝœ็‚บๅƒๆ•ธใ€‚ + - ้€™ๅ€‹ๅ‡ฝๅผๆœƒๆŠŠ `request` ๅ‚ณ็ตฆๅฐๆ‡‰็š„*่ทฏๅพ‘ๆ“ไฝœ*ใ€‚ + - ็„ถๅพŒๅ›žๅ‚ณๅฐๆ‡‰*่ทฏๅพ‘ๆ“ไฝœ*ๆ‰€็”ข็”Ÿ็š„ `response`ใ€‚ +- ็„ถๅพŒไฝ ๅฏไปฅๅœจๅ›žๅ‚ณไน‹ๅ‰้€ฒไธ€ๆญฅไฟฎๆ”น `response`ใ€‚ + +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} + +/// tip + +่ซ‹่จ˜ๅพ—๏ผŒ่‡ช่จ‚็š„้žๆจ™ๆบ–ๆจ™้ ญๅฏไปฅไฝฟ็”จ `X-` ๅ‰็ถดใ€‚ + +ไฝ†ๅฆ‚ๆžœไฝ ๆœ‰่‡ช่จ‚ๆจ™้ ญไธฆๅธŒๆœ›็€่ฆฝๅ™จ็ซฏ็š„็”จๆˆถ็ซฏ่ƒฝ็œ‹ๅˆฐๅฎƒๅ€‘๏ผŒไฝ ้œ€่ฆๅœจ CORS ่จญๅฎš๏ผˆ[CORS๏ผˆCross-Origin Resource Sharing๏ผ‰](cors.md){.internal-link target=_blank}๏ผ‰ไธญไฝฟ็”จ Starlette ็š„ CORS ๆ–‡ไปถๆ‰€่จ˜่ผ‰็š„ๅƒๆ•ธ `expose_headers` ๅฐ‡ๅฎƒๅ€‘ๅŠ ๅ…ฅใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.requests import Request`ใ€‚ + +**FastAPI** ็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…่€Œๆไพ›ไบ†ๅฎƒ๏ผŒไฝ†ๅฏฆ้š›ไธŠๅฎƒ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +### ๅœจ `response` ไน‹ๅ‰่ˆ‡ไน‹ๅพŒ { #before-and-after-the-response } + +ไฝ ๅฏไปฅๅœจไปปไฝ•*่ทฏๅพ‘ๆ“ไฝœ*ๆŽฅๆ”ถ `request` ไน‹ๅ‰๏ผŒๅŠ ๅ…ฅ่ฆๅŸท่กŒ็š„็จ‹ๅผ็ขผใ€‚ + +ไนŸๅฏไปฅๅœจ็”ข็”Ÿๅ‡บ `response` ไน‹ๅพŒใ€ๅ›žๅ‚ณไน‹ๅ‰ๅŸท่กŒ็จ‹ๅผ็ขผใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅๆ–ฐๅขžไธ€ๅ€‹่‡ช่จ‚ๆจ™้ ญ `X-Process-Time`๏ผŒๅ…ถๅ…งๅฎน็‚บ่™•็†่ซ‹ๆฑ‚ไธฆ็”ข็”Ÿๅ›žๆ‡‰ๆ‰€่Šฑ่ฒป็š„็ง’ๆ•ธ๏ผš + +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} + +/// tip + +้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จ `time.perf_counter()` ่€Œไธๆ˜ฏ `time.time()`๏ผŒๅ› ็‚บๅœจ้€™ไบ›็”จไพ‹ไธญๅฎƒๅฏ่ƒฝๆ›ด็ฒพ็ขบใ€‚๐Ÿค“ + +/// + +## ๅคšๅ€‹ไธญไป‹่ปŸ้ซ”็š„ๅŸท่กŒ้ †ๅบ { #multiple-middleware-execution-order } + +็•ถไฝ ไฝฟ็”จ `@app.middleware()` ่ฃ้ฃพๅ™จๆˆ– `app.add_middleware()` ๆ–นๆณ•ๅŠ ๅ…ฅๅคšๅ€‹ไธญไป‹่ปŸ้ซ”ๆ™‚๏ผŒๆฏๅ€‹ๆ–ฐ็š„ไธญไป‹่ปŸ้ซ”้ƒฝๆœƒๅŒ…่ฃนๆ‡‰็”จ็จ‹ๅผ๏ผŒๅฝขๆˆไธ€ๅ€‹ๅ †็–Šใ€‚ๆœ€ๅพŒๅŠ ๅ…ฅ็š„ไธญไป‹่ปŸ้ซ”ไฝๆ–ผๆœ€ๅค–ๅฑค๏ผŒๆœ€ๅ…ˆๅŠ ๅ…ฅ็š„ไฝๆ–ผๆœ€ๅ…งๅฑคใ€‚ + +ๅœจ่ซ‹ๆฑ‚่ทฏๅพ‘ไธŠ๏ผŒๆœ€ๅค–ๅฑค็š„ไธญไป‹่ปŸ้ซ”ๆœ€ๅ…ˆๅŸท่กŒใ€‚ + +ๅœจๅ›žๆ‡‰่ทฏๅพ‘ไธŠ๏ผŒๅฎƒๆœ€ๅพŒๅŸท่กŒใ€‚ + +ไพ‹ๅฆ‚๏ผš + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +ๅŸท่กŒ้ †ๅบๅฆ‚ไธ‹๏ผš + +- **่ซ‹ๆฑ‚**๏ผšMiddlewareB โ†’ MiddlewareA โ†’ ่ทฏ็”ฑ + +- **ๅ›žๆ‡‰**๏ผš่ทฏ็”ฑ โ†’ MiddlewareA โ†’ MiddlewareB + +้€™็จฎๅ †็–Š่กŒ็‚บๅฏ็ขบไฟไธญไป‹่ปŸ้ซ”ไปฅๅฏ้ ๆœŸไธ”ๅฏๆŽงๅˆถ็š„้ †ๅบๅŸท่กŒใ€‚ + +## ๅ…ถไป–ไธญไป‹่ปŸ้ซ” { #other-middlewares } + +ไฝ ไน‹ๅพŒๅฏไปฅๅœจ[้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—๏ผš้€ฒ้šŽไธญไป‹่ปŸ้ซ”](../advanced/middleware.md){.internal-link target=_blank}้–ฑ่ฎ€ๆ›ดๅคš้—œๆ–ผๅ…ถไป–ไธญไป‹่ปŸ้ซ”็š„ๅ…งๅฎนใ€‚ + +ไธ‹ไธ€็ฏ€ไฝ ๅฐ‡ๆœƒ่ฎ€ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จไธญไป‹่ปŸ้ซ”่™•็† CORSใ€‚ diff --git a/docs/zh-hant/docs/tutorial/path-operation-configuration.md b/docs/zh-hant/docs/tutorial/path-operation-configuration.md new file mode 100644 index 0000000000..45c101434d --- /dev/null +++ b/docs/zh-hant/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# ่ทฏๅพ‘ๆ“ไฝœ่จญๅฎš { #path-operation-configuration } + +ไฝ ๅฏไปฅๅœจไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธญๅ‚ณๅ…ฅๅคšๅ€‹ๅƒๆ•ธไพ†้€ฒ่กŒ่จญๅฎšใ€‚ + +/// warning | ่ญฆๅ‘Š + +่ซ‹ๆณจๆ„๏ผŒ้€™ไบ›ๅƒๆ•ธๆ˜ฏ็›ดๆŽฅๅ‚ณ็ตฆใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€๏ผŒ่€Œไธๆ˜ฏๅ‚ณ็ตฆไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ใ€‚ + +/// + +## ๅ›žๆ‡‰็‹€ๆ…‹็ขผ { #response-status-code } + +ไฝ ๅฏไปฅ็‚บใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„ๅ›žๆ‡‰่จญๅฎš (HTTP) `status_code`ใ€‚ + +ไฝ ๅฏไปฅ็›ดๆŽฅๅ‚ณๅ…ฅๆ•ดๆ•ธไปฃ็ขผ๏ผŒไพ‹ๅฆ‚ `404`ใ€‚ + +ๅฆ‚ๆžœไธ่จ˜ๅพ—ๆฏๅ€‹ๆ•ธๅญ—ไปฃ็ขผไปฃ่กจไป€้บผ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `status` ไธญ็š„้€Ÿ่จ˜ๅธธๆ•ธ๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +่ฉฒ็‹€ๆ…‹็ขผๆœƒ็”จๆ–ผๅ›žๆ‡‰๏ผŒไธฆ่ขซๅŠ ๅ…ฅ่‡ณ OpenAPI ็ตๆง‹ๆ่ฟฐไธญใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette import status`ใ€‚ + +**FastAPI** ๆไพ›่ˆ‡ `starlette.status` ็›ธๅŒ็š„ `fastapi.status`๏ผŒๅƒ…็‚บไบ†ๆ–นไพฟไฝ ้€™ไฝ้–‹็™ผ่€…๏ผŒไฝ†ๅฎƒๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +## ๆจ™็ฑค { #tags } + +ไฝ ๅฏไปฅ็‚บใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅŠ ๅ…ฅๆจ™็ฑค๏ผŒๅ‚ณๅ…ฅๅƒๆ•ธ `tags`๏ผŒๅ…ถๅ€ผ็‚บ็”ฑ `str` ็ต„ๆˆ็š„ `list`๏ผˆ้€šๅธธๅชๆ˜ฏไธ€ๅ€‹ `str`๏ผ‰๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +้€™ไบ›ๆจ™็ฑคๆœƒ่ขซๅŠ ๅ…ฅๅˆฐ OpenAPI ็ตๆง‹ๆ่ฟฐ๏ผŒไธฆ็”ฑ่‡ชๅ‹•ๅŒ–ๆ–‡ไปถไป‹้ขไฝฟ็”จ๏ผš + + + +### ๅซ Enum ็š„ๆจ™็ฑค { #tags-with-enums } + +ๅฆ‚ๆžœไฝ ็š„ๆ‡‰็”จๅพˆๅคง๏ผŒๅฏ่ƒฝๆœƒ็ดฏ็ฉๆ•ธๅ€‹ๆจ™็ฑค๏ผŒไฝ ๆœƒๅธŒๆœ›ๅฐ็›ธ้—œ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅง‹็ต‚ไฝฟ็”จ็›ธๅŒ็š„ๆจ™็ฑคใ€‚ + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฏไปฅ่€ƒๆ…ฎๆŠŠๆจ™็ฑคๅญ˜ๆ”พๅœจ `Enum` ไธญใ€‚ + +**FastAPI** ๅฐๆญค็š„ๆ”ฏๆดๆ–นๅผ่ˆ‡ไฝฟ็”จๆ™ฎ้€šๅญ—ไธฒ็›ธๅŒ๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} + +## ๆ‘˜่ฆ่ˆ‡ๆ่ฟฐ { #summary-and-description } + +ไฝ ๅฏไปฅๅŠ ๅ…ฅ `summary` ่ˆ‡ `description`๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## ๅพž docstring ๅ–ๅพ—ๆ่ฟฐ { #description-from-docstring } + +็”ฑๆ–ผๆ่ฟฐๅธธๅธธ่ผƒ้•ทใ€่ทจ่ถŠๅคš่กŒ๏ผŒไฝ ๅฏไปฅๅœจๅ‡ฝๅผ็š„ ๆ–‡ไปถๅญ—ไธฒ๏ผˆdocstring๏ผ‰ ไธญๅฎฃๅ‘Šใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„ๆ่ฟฐ๏ผŒ**FastAPI** ๆœƒๅพž้‚ฃ่ฃก่ฎ€ๅ–ใ€‚ + +ไฝ ๅฏไปฅๅœจ docstring ไธญๆ›ธๅฏซ Markdown๏ผŒๅฎƒๆœƒ่ขซๆญฃ็ขบ่งฃๆžไธฆ้กฏ็คบ๏ผˆๆœƒ่€ƒๆ…ฎ docstring ็š„็ธฎๆŽ’๏ผ‰ใ€‚ + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +้€™ๆœƒ็”จๆ–ผไบ’ๅ‹•ๅผๆ–‡ไปถ๏ผš + + + +## ๅ›žๆ‡‰ๆ่ฟฐ { #response-description } + +ไฝ ๅฏไปฅ็”จๅƒๆ•ธ `response_description` ๆŒ‡ๅฎšๅ›žๆ‡‰็š„ๆ่ฟฐ๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} + +/// info | ่ณ‡่จŠ + +่ซ‹ๆณจๆ„๏ผŒ`response_description` ๅฐˆๆŒ‡ๅ›žๆ‡‰๏ผŒ่€Œ `description` ๅ‰‡ๆ˜ฏ้‡ๅฐๆ•ดๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„ไธ€่ˆฌๆ่ฟฐใ€‚ + +/// + +/// check | ๆชขๆŸฅ + +OpenAPI ่ฆ็ฏ„่ฆๆฑ‚ๆฏๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€้ƒฝๅฟ…้ ˆๆœ‰ไธ€ๅ€‹ๅ›žๆ‡‰ๆ่ฟฐใ€‚ + +ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๆœชๆไพ›๏ผŒ**FastAPI** ๆœƒ่‡ชๅ‹•็”ข็”Ÿ "Successful response"ใ€‚ + +/// + + + +## ๅฐ‡ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆจ™่จ˜็‚บๅทฒๆฃ„็”จ { #deprecate-a-path-operation } + +่‹ฅ้œ€่ฆๅฐ‡ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆจ™่จ˜็‚บ ๅทฒๆฃ„็”จ๏ผŒไฝ†ไธ็งป้™คๅฎƒ๏ผŒ่ซ‹ๅ‚ณๅ…ฅๅƒๆ•ธ `deprecated`๏ผš + +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} + +ๅœจไบ’ๅ‹•ๅผๆ–‡ไปถไธญ๏ผŒๅฎƒๆœƒ่ขซๆธ…ๆฅšๆจ™็คบ็‚บๅทฒๆฃ„็”จ๏ผš + + + +ๆฏ”่ผƒๅทฒๆฃ„็”จ่ˆ‡ๆœชๆฃ„็”จ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅœจๆ–‡ไปถไธญ็š„ๅ‘ˆ็พ๏ผš + + + +## ็ธฝ็ต { #recap } + +ไฝ ๅฏไปฅ้€้Žๅฐ‡ๅƒๆ•ธๅ‚ณ็ตฆใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€๏ผŒ่ผ•้ฌ†ๅœฐ่จญๅฎšไธฆ็‚บไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅŠ ๅ…ฅไธญ็นผ่ณ‡ๆ–™ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 0000000000..a07f825b05 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,154 @@ +# ่ทฏๅพ‘ๅƒๆ•ธ่ˆ‡ๆ•ธๅ€ผ้ฉ—่ญ‰ { #path-parameters-and-numeric-validations } + +ๅฐฑๅƒไฝฟ็”จ `Query` ็‚บๆŸฅ่ฉขๅƒๆ•ธๅฎฃๅ‘Šๆ›ดๅคš้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ไธ€ๆจฃ๏ผŒไฝ ไนŸๅฏไปฅ็”จ `Path` ็‚บ่ทฏๅพ‘ๅƒๆ•ธๅฎฃๅ‘Š็›ธๅŒ้กžๅž‹็š„้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +## ๅŒฏๅ…ฅ `Path` { #import-path } + +้ฆ–ๅ…ˆ๏ผŒๅพž `fastapi` ๅŒฏๅ…ฅ `Path`๏ผŒไธฆๅŒฏๅ…ฅ `Annotated`๏ผš + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// info + +FastAPI ๅœจ 0.95.0 ็‰ˆๅŠ ๅ…ฅไธฆ้–‹ๅง‹ๆŽจ่–ฆไฝฟ็”จ `Annotated`ใ€‚ + +ๅฆ‚ๆžœไฝ ไฝฟ็”จๆ›ด่ˆŠ็š„็‰ˆๆœฌ๏ผŒๅ˜—่ฉฆไฝฟ็”จ `Annotated` ๆœƒๅ‡บ้Œฏใ€‚ + +่ซ‹็ขบไฟๅœจไฝฟ็”จ `Annotated` ๅ‰๏ผŒๅ…ˆ[ๅ‡็ดš FastAPI ็‰ˆๆœฌ](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}ๅˆฐ่‡ณๅฐ‘ 0.95.1ใ€‚ + +/// + +## ๅฎฃๅ‘Šไธญ็นผ่ณ‡ๆ–™ { #declare-metadata } + +ไฝ ๅฏไปฅๅฎฃๅ‘Š่ˆ‡ `Query` ็›ธๅŒ็š„ๆ‰€ๆœ‰ๅƒๆ•ธใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่‹ฅ่ฆ็‚บ่ทฏๅพ‘ๅƒๆ•ธ `item_id` ๅฎฃๅ‘Š `title` ไธญ็นผ่ณ‡ๆ–™๏ผŒๅฏไปฅ้€™ๆจฃๅฏซ๏ผš + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note + +่ทฏๅพ‘ๅƒๆ•ธไธ€ๅฎšๆ˜ฏๅฟ…ๅกซ๏ผŒๅ› ็‚บๅฎƒๅฟ…้ ˆๆ˜ฏ่ทฏๅพ‘็š„ไธ€้ƒจๅˆ†ใ€‚ๅณไฝฟไฝ ๅฐ‡ๅ…ถๅฎฃๅ‘Š็‚บ `None` ๆˆ–่จญๅฎš้ ่จญๅ€ผ๏ผŒไนŸไธๆœƒๆœ‰ไปปไฝ•ๅฝฑ้Ÿฟ๏ผŒๅฎƒไป็„ถๆ˜ฏๅฟ…ๅกซใ€‚ + +/// + +## ไพ้œ€ๆฑ‚่ชฟๆ•ดๅƒๆ•ธ้ †ๅบ { #order-the-parameters-as-you-need } + +/// tip + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒ้€™้ปžๅคงๆฆ‚ๆฒ’้‚ฃ้บผ้‡่ฆๆˆ–ๅฟ…่ฆใ€‚ + +/// + +ๅ‡่จญไฝ ๆƒณๆŠŠๆŸฅ่ฉขๅƒๆ•ธ `q` ๅฎฃๅ‘Š็‚บๅฟ…่ฆ็š„ `str`ใ€‚ + +่€Œไฝ ไธ้œ€่ฆ็‚บ่ฉฒๅƒๆ•ธๅฎฃๅ‘Šๅ…ถไป–ๅ…งๅฎน๏ผŒๆ‰€ไปฅๅ…ถๅฏฆไธ้œ€่ฆ็”จ `Query`ใ€‚ + +ไฝ†ไฝ ไป้œ€่ฆ็‚บ่ทฏๅพ‘ๅƒๆ•ธ `item_id` ไฝฟ็”จ `Path`๏ผŒ่€Œไธ”ๅŸบๆ–ผๆŸไบ›็†็”ฑไฝ ไธๆƒณ็”จ `Annotated`ใ€‚ + +ๅฆ‚ๆžœไฝ ๆŠŠๆœ‰ใ€Œ้ ่จญๅ€ผใ€็š„ๅƒๆ•ธๆ”พๅœจๆฒ’ๆœ‰ใ€Œ้ ่จญๅ€ผใ€็š„ๅƒๆ•ธไน‹ๅ‰๏ผŒPython ๆœƒๆŠฑๆ€จใ€‚ + +ไฝ†ไฝ ๅฏไปฅ่ชฟๆ•ดๅฎƒๅ€‘็š„้ †ๅบ๏ผŒๅ…ˆๆ”พๆฒ’ๆœ‰้ ่จญๅ€ผ๏ผˆๆŸฅ่ฉขๅƒๆ•ธ `q`๏ผ‰็š„ๅƒๆ•ธใ€‚ + +ๅฐ **FastAPI** ไพ†่ชชๆฒ’ๅทฎใ€‚ๅฎƒๆœƒไพๅƒๆ•ธๅ็จฑใ€ๅž‹ๅˆฅ่ˆ‡้ ่จญๅฎฃๅ‘Š๏ผˆ`Query`ใ€`Path` ็ญ‰๏ผ‰ไพ†่พจ่ญ˜ๅƒๆ•ธ๏ผŒไธฆไธๅœจๆ„้ †ๅบใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ้€™ๆจฃๅฎฃๅ‘Šไฝ ็š„ๅ‡ฝๅผ๏ผš + +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} + +ไฝ†่ซ‹่จ˜ไฝ๏ผŒ่‹ฅไฝฟ็”จ `Annotated`๏ผŒไฝ ๅฐฑไธๆœƒๆœ‰้€™ๅ€‹ๅ•้กŒ๏ผŒๅ› ็‚บไฝ ไธๆ˜ฏ็”จๅ‡ฝๅผๅƒๆ•ธ้ ่จญๅ€ผไพ†ๆ”พ `Query()` ๆˆ– `Path()`ใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} + +## ไพ้œ€ๆฑ‚่ชฟๆ•ดๅƒๆ•ธ้ †ๅบ็š„ๆŠ€ๅทง { #order-the-parameters-as-you-need-tricks } + +/// tip + +ๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒ้€™้ปžๅคงๆฆ‚ๆฒ’้‚ฃ้บผ้‡่ฆๆˆ–ๅฟ…่ฆใ€‚ + +/// + +้€™่ฃกๆœ‰ๅ€‹ๅฐๆŠ€ๅทงๅถ็ˆพๅพˆๅฅฝ็”จ๏ผŒไธ้Žไฝ ๅคงๆฆ‚ไธๅธธ้œ€่ฆใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณ่ฆ๏ผš + +* ไธ็”จ `Query`ใ€ไนŸไธ็ตฆ้ ่จญๅ€ผๅฐฑๅฎฃๅ‘ŠๆŸฅ่ฉขๅƒๆ•ธ `q` +* ไฝฟ็”จ `Path` ๅฎฃๅ‘Š่ทฏๅพ‘ๅƒๆ•ธ `item_id` +* ่ฎ“ๅฎƒๅ€‘็š„้ †ๅบไธๅŒ +* ไธไฝฟ็”จ `Annotated` + +โ€ฆPython ๆœ‰ๅ€‹ๅฐ่ชžๆณ•ๅฏไปฅๅšๅˆฐใ€‚ + +ๅœจๅ‡ฝๅผ็š„ๅƒๆ•ธๅˆ—่กจๆœ€ๅ‰้ขๆ”พไธ€ๅ€‹ `*`ใ€‚ + +Python ไธๆœƒๅฐ้€™ๅ€‹ `*` ๅšไปปไฝ•ไบ‹๏ผŒไฝ†ๅฎƒๆœƒ็Ÿฅ้“ๅพŒ็บŒ็š„ๆ‰€ๆœ‰ๅƒๆ•ธ้ƒฝๅฟ…้ ˆไปฅ้—œ้ตๅญ—ๅผ•ๆ•ธ๏ผˆkey-value pairs๏ผ‰ๆ–นๅผๅ‘ผๅซ๏ผŒไนŸๅฐฑๆ˜ฏๆ‰€่ฌ‚็š„ kwargsใ€‚ๅณไพฟๅฎƒๅ€‘ๆฒ’ๆœ‰้ ่จญๅ€ผไนŸไธ€ๆจฃใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} + +### ไฝฟ็”จ `Annotated` ๆ›ดๅฅฝ { #better-with-annotated } + +่จ˜ไฝ๏ผŒๅฆ‚ๆžœไฝ ไฝฟ็”จ `Annotated`๏ผŒๅ› ็‚บไธๆ˜ฏ็”จๅ‡ฝๅผๅƒๆ•ธ้ ่จญๅ€ผ๏ผŒๆ‰€ไปฅไฝ ไธๆœƒ้‡ๅˆฐ้€™ๅ€‹ๅ•้กŒ๏ผŒไนŸๅฏ่ƒฝไธ้œ€่ฆไฝฟ็”จ `*`ใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} + +## ๆ•ธๅ€ผ้ฉ—่ญ‰๏ผšๅคงๆ–ผๆˆ–็ญ‰ๆ–ผ { #number-validations-greater-than-or-equal } + +ไฝฟ็”จ `Query` ๅ’Œ `Path`๏ผˆไปฅๅŠไฝ ไน‹ๅพŒๆœƒ็œ‹ๅˆฐ็š„ๅ…ถไป–้กžๅˆฅ๏ผ‰ๅฏไปฅๅฎฃๅ‘Šๆ•ธๅ€ผ้™ๅˆถใ€‚ + +้€™่ฃก็”จ `ge=1`๏ผŒไปฃ่กจ `item_id` ๅฟ…้ ˆๆ˜ฏใ€Œๅคงๆ–ผ๏ผˆ`g`reater๏ผ‰ๆˆ–็ญ‰ๆ–ผ๏ผˆ`e`qual๏ผ‰ใ€`1` ็š„ๆ•ดๆ•ธใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} + +## ๆ•ธๅ€ผ้ฉ—่ญ‰๏ผšๅคงๆ–ผ่ˆ‡ๅฐๆ–ผๆˆ–็ญ‰ๆ–ผ { #number-validations-greater-than-and-less-than-or-equal } + +ๅŒๆจฃไนŸ้ฉ็”จๆ–ผ๏ผš + +* `gt`๏ผšๅคงๆ–ผ๏ผˆ`g`reater `t`han๏ผ‰ +* `le`๏ผšๅฐๆ–ผๆˆ–็ญ‰ๆ–ผ๏ผˆ`l`ess than or `e`qual๏ผ‰ + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} + +## ๆ•ธๅ€ผ้ฉ—่ญ‰๏ผšๆตฎ้ปžๆ•ธใ€ๅคงๆ–ผ่ˆ‡ๅฐๆ–ผ { #number-validations-floats-greater-than-and-less-than } + +ๆ•ธๅ€ผ้ฉ—่ญ‰ไนŸ้ฉ็”จๆ–ผ `float`ใ€‚ + +้€™ๆ™‚ๅฐฑ่ƒฝ็œ‹ๅ‡บ่ƒฝๅฎฃๅ‘Š gt๏ผˆไธๅชๆ˜ฏ ge๏ผ‰็š„้‡่ฆๆ€งใ€‚ๅ› ็‚บไฝ ๅฏไปฅ่ฆๆฑ‚ๆ•ธๅ€ผๅฟ…้ ˆๅคงๆ–ผ `0`๏ผŒๅณไพฟๅฎƒๅฐๆ–ผ `1`ใ€‚ + +ๆ‰€ไปฅ๏ผŒ`0.5` ๆ˜ฏๆœ‰ๆ•ˆ็š„ๅ€ผ๏ผŒไฝ† `0.0` ๆˆ– `0` ๅ‰‡็„กๆ•ˆใ€‚ + +lt ไนŸๆ˜ฏๅŒๆจฃ็š„้“็†ใ€‚ + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} + +## ๅฐ็ต { #recap } + +ไฝฟ็”จ `Query`ใ€`Path`๏ผˆไปฅๅŠไฝ ๅฐšๆœช็œ‹ๅˆฐ็š„ๅ…ถไป–้กžๅˆฅ๏ผ‰ๆ™‚๏ผŒไฝ ๅฏไปฅๅƒๅœจ[ๆŸฅ่ฉขๅƒๆ•ธ่ˆ‡ๅญ—ไธฒ้ฉ—่ญ‰](query-params-str-validations.md){.internal-link target=_blank}ไธญไธ€ๆจฃ๏ผŒๅฎฃๅ‘Šไธญ็นผ่ณ‡ๆ–™่ˆ‡ๅญ—ไธฒ้ฉ—่ญ‰ใ€‚ + +ไฝ ไนŸๅฏไปฅๅฎฃๅ‘Šๆ•ธๅ€ผ้ฉ—่ญ‰๏ผš + +* `gt`๏ผšๅคงๆ–ผ๏ผˆ`g`reater `t`han๏ผ‰ +* `ge`๏ผšๅคงๆ–ผๆˆ–็ญ‰ๆ–ผ๏ผˆ`g`reater than or `e`qual๏ผ‰ +* `lt`๏ผšๅฐๆ–ผ๏ผˆ`l`ess `t`han๏ผ‰ +* `le`๏ผšๅฐๆ–ผๆˆ–็ญ‰ๆ–ผ๏ผˆ`l`ess than or `e`qual๏ผ‰ + +/// info + +ไฝ ไน‹ๅพŒๆœƒ็œ‹ๅˆฐ็š„ `Query`ใ€`Path` ่ˆ‡ๅ…ถไป–้กžๅˆฅ๏ผŒ้ƒฝๆ˜ฏๅ…ฑๅŒ็ˆถ้กžๅˆฅ `Param` ็š„ๅญ้กžๅˆฅใ€‚ + +ๅฎƒๅ€‘ๅ…ฑไบซไฝ ๅทฒ็ถ“็œ‹ๅˆฐ็š„้‚ฃไบ›็”จๆ–ผ้กๅค–้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™็š„ๅƒๆ•ธใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path` ็ญ‰ๆ™‚๏ผŒๅฎƒๅ€‘ๅ…ถๅฏฆๆ˜ฏๅ‡ฝๅผใ€‚ + +ๅ‘ผๅซๅฎƒๅ€‘ๆ™‚๏ผŒๆœƒๅ›žๅ‚ณๅŒๅ้กžๅˆฅ็š„ๅฏฆไพ‹ใ€‚ + +ไนŸๅฐฑๆ˜ฏ่ชช๏ผŒไฝ ๅŒฏๅ…ฅ็š„ๆ˜ฏๅ็‚บ `Query` ็š„ๅ‡ฝๅผ๏ผŒ่€Œ็•ถไฝ ๅ‘ผๅซๅฎƒๆ™‚๏ผŒๅฎƒๆœƒๅ›žๅ‚ณๅŒๅ็š„ `Query` ้กžๅˆฅๅฏฆไพ‹ใ€‚ + +้€™ไบ›ๅ‡ฝๅผไน‹ๆ‰€ไปฅๅญ˜ๅœจ๏ผˆ่€Œไธๆ˜ฏ็›ดๆŽฅไฝฟ็”จ้กžๅˆฅ๏ผ‰๏ผŒๆ˜ฏ็‚บไบ†้ฟๅ…็ทจ่ผฏๅ™จๆจ™่จ˜ๅฎƒๅ€‘็š„ๅž‹ๅˆฅ้Œฏ่ชคใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ๅฐฑ่ƒฝไฝฟ็”จไธ€่ˆฌ็š„็ทจ่ผฏๅ™จ่ˆ‡้–‹็™ผๅทฅๅ…ท๏ผŒ่€Œไธ้œ€่ฆ้กๅค–่จญๅฎšไพ†ๅฟฝ็•ฅ้‚ฃไบ›้Œฏ่ชคใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/path-params.md b/docs/zh-hant/docs/tutorial/path-params.md new file mode 100644 index 0000000000..373f430cde --- /dev/null +++ b/docs/zh-hant/docs/tutorial/path-params.md @@ -0,0 +1,251 @@ +# ่ทฏๅพ‘ๅƒๆ•ธ { #path-parameters } + +ไฝ ๅฏไปฅ็”จ่ˆ‡ Python ๆ ผๅผๅŒ–ๅญ—ไธฒ็›ธๅŒ็š„่ชžๆณ•ไพ†ๅฎฃๅ‘Š่ทฏๅพ‘ใ€Œๅƒๆ•ธใ€ๆˆ–ใ€Œ่ฎŠๆ•ธใ€๏ผš + +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} + +่ทฏๅพ‘ๅƒๆ•ธ `item_id` ็š„ๅ€ผๆœƒไฝœ็‚บๅผ•ๆ•ธ `item_id` ๅ‚ณๅ…ฅไฝ ็š„ๅ‡ฝๅผใ€‚ + +ๆ‰€ไปฅ๏ผŒๅฆ‚ๆžœไฝ ๅŸท่กŒ้€™ๅ€‹็ฏ„ไพ‹ไธฆๅ‰ๅพ€ http://127.0.0.1:8000/items/foo๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ้€™ๆจฃ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{"item_id":"foo"} +``` + +## ๅ…ทๅž‹ๅˆฅ็š„่ทฏๅพ‘ๅƒๆ•ธ { #path-parameters-with-types } + +ไฝ ๅฏไปฅๅœจๅ‡ฝๅผไธญไฝฟ็”จๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅ่จป่จ˜็‚บ่ทฏๅพ‘ๅƒๆ•ธๅฎฃๅ‘Šๅž‹ๅˆฅ๏ผš + +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} + +ๅœจ้€™ๅ€‹ไพ‹ๅญ่ฃก๏ผŒ`item_id` ่ขซๅฎฃๅ‘Š็‚บ `int`ใ€‚ + +/// check + +้€™ๆœƒๅœจไฝ ็š„ๅ‡ฝๅผไธญๆไพ›็ทจ่ผฏๅ™จๆ”ฏๆด๏ผŒๅŒ…ๆ‹ฌ้Œฏ่ชคๆชขๆŸฅใ€่‡ชๅ‹•ๅฎŒๆˆ็ญ‰ใ€‚ + +/// + +## ่ณ‡ๆ–™ ่ฝ‰ๆ› { #data-conversion } + +ๅฆ‚ๆžœไฝ ๅŸท่กŒ้€™ๅ€‹็ฏ„ไพ‹ไธฆๅœจ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/items/3๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ้€™ๆจฃ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{"item_id":3} +``` + +/// check + +ๆณจๆ„ไฝ ็š„ๅ‡ฝๅผๆŽฅๆ”ถ๏ผˆไธฆๅ›žๅ‚ณ๏ผ‰็š„ๅ€ผๆ˜ฏ `3`๏ผŒไนŸๅฐฑๆ˜ฏ Python ็š„ `int`๏ผŒ่€Œไธๆ˜ฏๅญ—ไธฒ `"3"`ใ€‚ + +ๅ› ๆญค๏ผŒๆœ‰ไบ†้€™ๅ€‹ๅž‹ๅˆฅๅฎฃๅ‘Š๏ผŒ**FastAPI** ๆœƒ่‡ชๅ‹•็‚บไฝ ่™•็†่ซ‹ๆฑ‚็š„ ใ€Œ่งฃๆžใ€ใ€‚ + +/// + +## ่ณ‡ๆ–™้ฉ—่ญ‰ { #data-validation } + +ไฝ†ๅฆ‚ๆžœไฝ ๅœจ็€่ฆฝๅ™จๅ‰ๅพ€ http://127.0.0.1:8000/items/foo๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๆผ‚ไบฎ็š„ HTTP ้Œฏ่ชค๏ผš + +```JSON +{ + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] +} +``` + +ๅ› ็‚บ่ทฏๅพ‘ๅƒๆ•ธ `item_id` ็š„ๅ€ผๆ˜ฏ `"foo"`๏ผŒๅฎƒไธๆ˜ฏ `int`ใ€‚ + +ๅŒๆจฃ็š„้Œฏ่ชคไนŸๆœƒๅœจไฝ ๆไพ› `float` ่€Œไธๆ˜ฏ `int` ๆ™‚ๅ‡บ็พ๏ผŒไพ‹ๅฆ‚๏ผšhttp://127.0.0.1:8000/items/4.2 + +/// check + +ๅ› ๆญค๏ผŒๆญ้…็›ธๅŒ็š„ Python ๅž‹ๅˆฅๅฎฃๅ‘Š๏ผŒ**FastAPI** ๆœƒ็‚บไฝ ้€ฒ่กŒ่ณ‡ๆ–™้ฉ—่ญ‰ใ€‚ + +ๆณจๆ„้Œฏ่ชคไนŸๆธ…ๆฅšๆŒ‡ๅ‡บ้ฉ—่ญ‰ๆœช้€š้Ž็š„็ขบๅˆ‡ไฝ็ฝฎใ€‚ + +้€™ๅœจ้–‹็™ผ่ˆ‡้™ค้Œฏ่ˆ‡ไฝ ็š„ API ไบ’ๅ‹•็š„็จ‹ๅผ็ขผๆ™‚้žๅธธๆœ‰ๅนซๅŠฉใ€‚ + +/// + +## ๆ–‡ไปถ { #documentation } + +็•ถไฝ ๅœจ็€่ฆฝๅ™จ้–‹ๅ•Ÿ http://127.0.0.1:8000/docs๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ่‡ชๅ‹•็”ข็”Ÿใ€ๅฏไบ’ๅ‹•็š„ API ๆ–‡ไปถ๏ผŒไพ‹ๅฆ‚๏ผš + + + +/// check + +ๅŒๆจฃๅœฐ๏ผŒๅช่ฆไฝฟ็”จ้‚ฃๅ€‹ Python ๅž‹ๅˆฅๅฎฃๅ‘Š๏ผŒ**FastAPI** ๅฐฑๆœƒๆไพ›่‡ชๅ‹•ใ€ไบ’ๅ‹•ๅผ็š„ๆ–‡ไปถ๏ผˆๆ•ดๅˆ Swagger UI๏ผ‰ใ€‚ + +ๆณจๆ„่ทฏๅพ‘ๅƒๆ•ธ่ขซๅฎฃๅ‘Š็‚บๆ•ดๆ•ธใ€‚ + +/// + +## ๅŸบๆ–ผๆจ™ๆบ–็š„ๅ„ชๅ‹ข่ˆ‡ๆ›ฟไปฃๆ–‡ไปถ { #standards-based-benefits-alternative-documentation } + +่€Œไธ”ๅ› ็‚บ็”ข็”Ÿ็š„ schema ไพ†่‡ช OpenAPI ๆจ™ๆบ–๏ผŒๆœ‰ๅพˆๅคš็›ธๅฎน็š„ๅทฅๅ…ทๅฏ็”จใ€‚ + +ๅ› ๆญค๏ผŒ**FastAPI** ๆœฌ่บซไนŸๆไพ›ๅฆไธ€็จฎ API ๆ–‡ไปถ๏ผˆไฝฟ็”จ ReDoc๏ผ‰๏ผŒไฝ ๅฏไปฅๅœจ http://127.0.0.1:8000/redoc ๅญ˜ๅ–๏ผš + + + +ๅŒๆจฃๅœฐ๏ผŒไนŸๆœ‰่จฑๅคš็›ธๅฎนๅทฅๅ…ทๅฏ็”จ๏ผŒๅŒ…ๆ‹ฌๆ”ฏๆดๅคš็จฎ่ชž่จ€็š„็จ‹ๅผ็ขผ็”ข็”Ÿๅทฅๅ…ทใ€‚ + +## Pydantic { #pydantic } + +ๆ‰€ๆœ‰่ณ‡ๆ–™้ฉ—่ญ‰้ƒฝ็”ฑ Pydantic ๅœจๅบ•ๅฑค่™•็†๏ผŒๅ› ๆญคไฝ ่ƒฝ็›ดๆŽฅๅ—ๆƒ ใ€‚่€Œไธ”ไฝ ๅฏไปฅๆ”พๅฟƒไฝฟ็”จใ€‚ + +ไฝ ๅฏไปฅ็”จ็›ธๅŒ็š„ๅž‹ๅˆฅๅฎฃๅ‘Šๆญ้… `str`ใ€`float`ใ€`bool` ่ˆ‡่จฑๅคšๆ›ด่ค‡้›œ็š„่ณ‡ๆ–™ๅž‹ๅˆฅใ€‚ + +้€™ไบ›ไน‹ไธญ็š„ๅฅฝๅนพๅ€‹ๆœƒๅœจๆŽฅไธ‹ไพ†็š„ๆ•™ๅญธ็ซ ็ฏ€ไธญไป‹็ดนใ€‚ + +## ้ †ๅบๅพˆ้‡่ฆ { #order-matters } + +ๅœจๅปบ็ซ‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆ™‚๏ผŒไฝ ๅฏ่ƒฝๆœƒ้‡ๅˆฐๆœ‰ๅ›บๅฎš่ทฏๅพ‘็š„ๆƒ…ๆณใ€‚ + +ๅƒๆ˜ฏ `/users/me`๏ผŒๅ‡่จญๅฎƒ็”จไพ†ๅ–ๅพ—็›ฎๅ‰ไฝฟ็”จ่€…็š„่ณ‡ๆ–™ใ€‚ + +็„ถๅพŒไฝ ไนŸๅฏ่ƒฝๆœ‰ไธ€ๅ€‹่ทฏๅพ‘ `/users/{user_id}` ็”จไพ†ไพไฝฟ็”จ่€… ID ๅ–ๅพ—็‰นๅฎšไฝฟ็”จ่€…็š„่ณ‡ๆ–™ใ€‚ + +ๅ› ็‚บใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๆœƒไพๅฎฃๅ‘Š้ †ๅบไพ†ๆฏ”ๅฐ๏ผŒไฝ ๅฟ…้ ˆ็ขบไฟ `/users/me` ็š„่ทฏๅพ‘ๅœจ `/users/{user_id}` ไน‹ๅ‰ๅฎฃๅ‘Š๏ผš + +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} + +ๅฆๅ‰‡๏ผŒ`/users/{user_id}` ็š„่ทฏๅพ‘ไนŸๆœƒๅŒน้… `/users/me`๏ผŒไธฆใ€Œ่ช็‚บใ€ๅฎƒๆ”ถๅˆฐไธ€ๅ€‹ๅ€ผ็‚บ `"me"` ็š„ `user_id` ๅƒๆ•ธใ€‚ + +ๅŒๆจฃๅœฐ๏ผŒไฝ ไธ่ƒฝ้‡ๆ–ฐๅฎš็พฉๅŒไธ€่ทฏๅพ‘ๆ“ไฝœ๏ผš + +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} + +ๅ› ็‚บ็ฌฌไธ€ๅ€‹ๆœƒ่ขซๅ„ชๅ…ˆไฝฟ็”จ๏ผˆ่ทฏๅพ‘ๅ…ˆๅŒน้…ๅˆฐ๏ผ‰ใ€‚ + +## ้ ๅ…ˆๅฎš็พฉ็š„ๅ€ผ { #predefined-values } + +ๅฆ‚ๆžœไฝ ๆœ‰ไธ€ๅ€‹ๆŽฅๆ”ถใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผŒไฝ†ไฝ ๅธŒๆœ›ๅฏ็”จ็š„ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€ๅ€ผๆ˜ฏ้ ๅ…ˆๅฎš็พฉๅฅฝ็š„๏ผŒไฝ ๅฏไปฅไฝฟ็”จๆจ™ๆบ–็š„ Python `Enum`ใ€‚ + +### ๅปบ็ซ‹ `Enum` ้กžๅˆฅ { #create-an-enum-class } + +ๅŒฏๅ…ฅ `Enum` ไธฆๅปบ็ซ‹ไธ€ๅ€‹ๅŒๆ™‚็นผๆ‰ฟ่‡ช `str` ่ˆ‡ `Enum` ็š„ๅญ้กžๅˆฅใ€‚ + +็นผๆ‰ฟ่‡ช `str` ไน‹ๅพŒ๏ผŒAPI ๆ–‡ไปถๅฐฑ่ƒฝ็Ÿฅ้“้€™ไบ›ๅ€ผ็š„ๅž‹ๅˆฅๅฟ…้ ˆๆ˜ฏ `string`๏ผŒไธฆ่ƒฝๆญฃ็ขบๅœฐๅ‘ˆ็พใ€‚ + +็„ถๅพŒๅปบ็ซ‹ๅ…ทๆœ‰ๅ›บๅฎšๅ€ผ็š„้กžๅˆฅๅฑฌๆ€ง๏ผŒ้€™ไบ›ๅฐฑๆ˜ฏๅฏ็”จ็š„ๆœ‰ๆ•ˆๅ€ผ๏ผš + +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} + +/// tip + +ๅฆ‚ๆžœไฝ ๅœจๆƒณ๏ผŒใ€ŒAlexNetใ€ใ€ใ€ŒResNetใ€ๅ’Œใ€ŒLeNetใ€ๅชๆ˜ฏไธ€ไบ›ๆฉŸๅ™จๅญธ็ฟ’ ๆจกๅž‹ ็š„ๅๅญ—ใ€‚ + +/// + +### ๅฎฃๅ‘Šไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€ { #declare-a-path-parameter } + +ๆŽฅ่‘—ไฝฟ็”จไฝ ๅปบ็ซ‹็š„ๅˆ—่ˆ‰้กžๅˆฅ๏ผˆ`ModelName`๏ผ‰ไฝœ็‚บๅž‹ๅˆฅ่จป่จ˜๏ผŒๅปบ็ซ‹ไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€๏ผš + +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} + +### ๆŸฅ็œ‹ๆ–‡ไปถ { #check-the-docs } + +ๅ› ็‚บใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€็š„ๅฏ็”จๅ€ผๆ˜ฏ้ ๅ…ˆๅฎš็พฉ็š„๏ผŒไบ’ๅ‹•ๅผๆ–‡ไปถๅฏไปฅๅพˆๆผ‚ไบฎๅœฐ้กฏ็คบๅฎƒๅ€‘๏ผš + + + +### ไฝฟ็”จ Pythonใ€Œๅˆ—่ˆ‰ใ€ { #working-with-python-enumerations } + +ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€็š„ๅ€ผๆœƒๆ˜ฏไธ€ๅ€‹ใ€Œๅˆ—่ˆ‰ๆˆๅ“กใ€ใ€‚ + +#### ๆฏ”่ผƒใ€Œๅˆ—่ˆ‰ๆˆๅ“กใ€ { #compare-enumeration-members } + +ไฝ ๅฏไปฅๆŠŠๅฎƒ่ˆ‡ไฝ ๅปบ็ซ‹็š„ๅˆ—่ˆ‰ `ModelName` ไธญ็š„ใ€Œๅˆ—่ˆ‰ๆˆๅ“กใ€ๆฏ”่ผƒ๏ผš + +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} + +#### ๅ–ๅพ—ใ€Œๅˆ—่ˆ‰ๅ€ผใ€ { #get-the-enumeration-value } + +ไฝ ๅฏไปฅ็”จ `model_name.value` ๅ–ๅพ—ๅฏฆ้š›็š„ๅ€ผ๏ผˆๅœจ้€™ๅ€‹ไพ‹ๅญไธญๆ˜ฏ `str`๏ผ‰๏ผŒไธ€่ˆฌ่€Œ่จ€ๅฐฑๆ˜ฏ `your_enum_member.value`๏ผš + +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} + +/// tip + +ไฝ ไนŸๅฏไปฅ็”จ `ModelName.lenet.value` ๅ–ๅพ—ๅ€ผ `"lenet"`ใ€‚ + +/// + +#### ๅ›žๅ‚ณใ€Œๅˆ—่ˆ‰ๆˆๅ“กใ€ { #return-enumeration-members } + +ไฝ ๅฏไปฅๅพžใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅ›žๅ‚ณใ€Œๅˆ—่ˆ‰ๆˆๅ“กใ€๏ผŒๅณไฝฟๆ˜ฏๅทข็‹€ๅœจ JSON ไธป้ซ”๏ผˆไพ‹ๅฆ‚ `dict`๏ผ‰่ฃกใ€‚ + +ๅœจๅ›žๅ‚ณ็ตฆ็”จๆˆถ็ซฏไน‹ๅ‰๏ผŒๅฎƒๅ€‘ๆœƒ่ขซ่ฝ‰ๆˆๅฐๆ‡‰็š„ๅ€ผ๏ผˆๆญคไพ‹็‚บๅญ—ไธฒ๏ผ‰๏ผš + +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} + +ไฝ ็š„็”จๆˆถ็ซฏๆœƒๆ”ถๅˆฐๅƒ้€™ๆจฃ็š„ JSON ๅ›žๆ‡‰๏ผš + +```JSON +{ + "model_name": "alexnet", + "message": "Deep Learning FTW!" +} +``` + +## ๅŒ…ๅซ่ทฏๅพ‘็š„่ทฏๅพ‘ๅƒๆ•ธ { #path-parameters-containing-paths } + +ๅ‡่จญไฝ ๆœ‰ไธ€ๅ€‹่ทฏๅพ‘็‚บ `/files/{file_path}` ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ใ€‚ + +ไฝ†ไฝ ้œ€่ฆ `file_path` ๆœฌ่บซๅฐฑๅŒ…ๅซไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ใ€๏ผŒๅƒๆ˜ฏ `home/johndoe/myfile.txt`ใ€‚ + +ๆ‰€ไปฅ๏ผŒ่ฉฒๆช”ๆกˆ็š„ URL ๆœƒๆ˜ฏ๏ผš`/files/home/johndoe/myfile.txt`ใ€‚ + +### OpenAPI ๆ”ฏๆด { #openapi-support } + +OpenAPI ไธฆไธๆ”ฏๆด็›ดๆŽฅๅฎฃๅ‘Šไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€ๅ…งๅ†ๅŒ…ๅซไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ใ€๏ผŒๅ› ็‚บ้‚ฃๆœƒๅฐŽ่‡ด้›ฃไปฅๆธฌ่ฉฆ่ˆ‡ๅฎš็พฉ็š„ๆƒ…ๆณใ€‚ + +็„ถ่€Œ๏ผŒไฝ ไปๅฏๅœจ **FastAPI** ไธญ้€™ๆจฃๅš๏ผŒๆ–นๆณ•ๆ˜ฏไฝฟ็”จ Starlette ็š„ๅ…ถไธญไธ€ๅ€‹ๅ…ง้ƒจๅทฅๅ…ทใ€‚ + +่€Œๆ–‡ไปถไพ็„ถ่ƒฝ้‹ไฝœ๏ผŒๅชๆ˜ฏๅฎƒไธๆœƒ้กๅค–่ชชๆ˜Ž่ฉฒๅƒๆ•ธๆ‡‰่ฉฒๅŒ…ๅซไธ€ๅ€‹่ทฏๅพ‘ใ€‚ + +### ่ทฏๅพ‘่ฝ‰ๆ›ๅ™จ { #path-convertor } + +ไฝฟ็”จ Starlette ๆไพ›็š„้ธ้ …๏ผŒไฝ ๅฏไปฅ็”จๅƒ้€™ๆจฃ็š„ URL ไพ†ๅฎฃๅ‘Šไธ€ๅ€‹ๅŒ…ๅซใ€Œ่ทฏๅพ‘ใ€็š„ใ€Œ่ทฏๅพ‘ๅƒๆ•ธใ€๏ผš + +``` +/files/{file_path:path} +``` + +ๅœจ้€™ๅ€‹ไพ‹ๅญ่ฃก๏ผŒๅƒๆ•ธๅ็จฑๆ˜ฏ `file_path`๏ผŒ่€Œๆœ€ๅพŒ้ข็š„ `:path` ่กจ็คบ่ฉฒๅƒๆ•ธๆ‡‰่ฉฒๅŒน้…ไปปๆ„ใ€Œ่ทฏๅพ‘ใ€ใ€‚ + +ๆ‰€ไปฅไฝ ๅฏไปฅ้€™ๆจฃไฝฟ็”จๅฎƒ๏ผš + +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} + +/// tip + +ไฝ ๅฏ่ƒฝ้œ€่ฆ้€™ๅ€‹ๅƒๆ•ธๅŒ…ๅซ `/home/johndoe/myfile.txt`๏ผŒไนŸๅฐฑๆ˜ฏๅ‰้ขๅธถๆœ‰ๆ–œ็ทš๏ผˆ`/`๏ผ‰ใ€‚ + +ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹๏ผŒURL ๆœƒๆ˜ฏ๏ผš`/files//home/johndoe/myfile.txt`๏ผŒๅœจ `files` ่ˆ‡ `home` ไน‹้–“ๆœ‰ๅ…ฉๅ€‹ๆ–œ็ทš๏ผˆ`//`๏ผ‰ใ€‚ + +/// + +## ๅ›ž้กง { #recap } + +ไฝฟ็”จ **FastAPI**๏ผŒๅช่ฆๆ’ฐๅฏซ็ฐก็Ÿญใ€็›ด่ฆบไธ”ๆจ™ๆบ–็š„ Python ๅž‹ๅˆฅๅฎฃๅ‘Š๏ผŒไฝ ๅฐฑ่ƒฝ็ฒๅพ—๏ผš + +* ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผš้Œฏ่ชคๆชขๆŸฅใ€่‡ชๅ‹•ๅฎŒๆˆ็ญ‰ +* ่ณ‡ๆ–™ "่งฃๆž" +* ่ณ‡ๆ–™้ฉ—่ญ‰ +* API ่จป่งฃ่ˆ‡่‡ชๅ‹•็”ข็”Ÿๆ–‡ไปถ + +่€Œไธ”ไฝ ๅช่ฆๅฎฃๅ‘Šไธ€ๆฌกๅฐฑๅฅฝใ€‚ + +้€™ๅคงๆฆ‚ๆ˜ฏ **FastAPI** ็›ธ่ผƒๆ–ผๅ…ถไป–ๆก†ๆžถๆœ€ๆ˜Ž้กฏ็š„ๅ„ชๅ‹ขไน‹ไธ€๏ผˆ้™คไบ†ๅŽŸๅง‹ๆ•ˆ่ƒฝไน‹ๅค–๏ผ‰ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/query-params-str-validations.md b/docs/zh-hant/docs/tutorial/query-params-str-validations.md new file mode 100644 index 0000000000..ea84234c0e --- /dev/null +++ b/docs/zh-hant/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,449 @@ +# ๆŸฅ่ฉขๅƒๆ•ธ่ˆ‡ๅญ—ไธฒ้ฉ—่ญ‰ { #query-parameters-and-string-validations } + +FastAPI ๅ…่จฑไฝ ็‚บๅƒๆ•ธๅฎฃๅ‘Š้กๅค–็š„่ณ‡่จŠ่ˆ‡้ฉ—่ญ‰ใ€‚ + +ไปฅไธ‹้ข้€™ๅ€‹ๆ‡‰็”จ็‚บไพ‹๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +ๆŸฅ่ฉขๅƒๆ•ธ `q` ็š„ๅž‹ๅˆฅๆ˜ฏ `str | None`๏ผŒ่กจ็คบๅฎƒๆ˜ฏ `str` ไฝ†ไนŸๅฏไปฅๆ˜ฏ `None`๏ผŒ่€Œไธ”้ ่จญๅ€ผๅฐฑๆ˜ฏ `None`๏ผŒๅ› ๆญค FastAPI ๆœƒ็Ÿฅ้“ๅฎƒไธๆ˜ฏๅฟ…ๅกซใ€‚ + +/// note | ๆณจๆ„ + +FastAPI ๆœƒๅ› ็‚บ้ ่จญๅ€ผๆ˜ฏ `= None` ่€Œ็Ÿฅ้“ `q` ไธๆ˜ฏๅฟ…ๅกซใ€‚ + +ไฝฟ็”จ `str | None` ไนŸ่ƒฝ่ฎ“ไฝ ็š„็ทจ่ผฏๅ™จๆไพ›ๆ›ดๅฅฝ็š„ๆ”ฏๆดไธฆๅตๆธฌ้Œฏ่ชคใ€‚ + +/// + +## ้กๅค–้ฉ—่ญ‰ { #additional-validation } + +ๆˆ‘ๅ€‘่ฆๅผทๅˆถ๏ผšๅณไฝฟ `q` ๆ˜ฏๅฏ้ธ๏ผŒๅช่ฆๆไพ›ไบ†๏ผŒ้•ทๅบฆๅฐฑไธ่ƒฝ่ถ…้Ž 50 ๅ€‹ๅญ—ๅ…ƒใ€‚ + +### ๅŒฏๅ…ฅ `Query` ่ˆ‡ `Annotated` { #import-query-and-annotated } + +่ฆ้”ๆˆ้€™้ปž๏ผŒๅ…ˆๅŒฏๅ…ฅ๏ผš + +- ๅพž `fastapi` ๅŒฏๅ…ฅ `Query` +- ๅพž `typing` ๅŒฏๅ…ฅ `Annotated` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | ่ชชๆ˜Ž + +FastAPI ่‡ช 0.95.0 ็‰ˆ่ตทๅŠ ๅ…ฅไธฆ้–‹ๅง‹ๆŽจ่–ฆไฝฟ็”จ `Annotated`ใ€‚ + +ๅฆ‚ๆžœไฝ ็š„็‰ˆๆœฌ่ผƒ่ˆŠ๏ผŒๅ˜—่ฉฆไฝฟ็”จ `Annotated` ๆœƒๅ‡บ้Œฏใ€‚ + +่ซ‹ๅ…ˆ่‡ณๅฐ‘ [ๅ‡็ดš FastAPI ็‰ˆๆœฌ](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ๅˆฐ 0.95.1 ๅ†ไฝฟ็”จ `Annotated`ใ€‚ + +/// + +## ๅœจ `q` ๅƒๆ•ธ็š„ๅž‹ๅˆฅไธญไฝฟ็”จ `Annotated` { #use-annotated-in-the-type-for-the-q-parameter } + +้‚„่จ˜ๅพ—ๅ…ˆๅ‰ๅœจ [Python ๅž‹ๅˆฅไป‹็ดน](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} ๆๅˆฐๅฏไปฅ็”จ `Annotated` ็‚บๅƒๆ•ธๅŠ ๅ…ฅไธญ็นผ่ณ‡ๆ–™ๅ—Ž๏ผŸ + +็พๅœจๅฐฑ็”จๅœจ FastAPI ไธŠๅงใ€‚๐Ÿš€ + +ๆˆ‘ๅ€‘ๅŽŸๆœฌ็š„ๅž‹ๅˆฅ่จป่จ˜ๆ˜ฏ๏ผš + +```Python +q: str | None = None +``` + +ๆŽฅ่‘—ๆŠŠๅฎƒ็”จ `Annotated` ๅŒ…่ตทไพ†๏ผŒ่ฎŠๆˆ๏ผš + +```Python +q: Annotated[str | None] = None +``` + +้€™ๅ…ฉ็จฎๅฏซๆณ•ไปฃ่กจ็š„ๆ„ๆ€็›ธๅŒ๏ผš`q` ๅฏไปฅๆ˜ฏ `str` ๆˆ– `None`๏ผŒไธ”้ ่จญๆ˜ฏ `None`ใ€‚ + +็พๅœจไพ†ๅšๆœ‰่ถฃ็š„้ƒจๅˆ†ใ€‚๐ŸŽ‰ + +## ๅœจ `q` ๅƒๆ•ธ็š„ `Annotated` ไธญๅŠ ๅ…ฅ `Query` { #add-query-to-annotated-in-the-q-parameter } + +ๆ—ข็„ถๆˆ‘ๅ€‘ๆœ‰ๅฏไปฅๆ”พๆ›ดๅคš่ณ‡่จŠ็š„ `Annotated`๏ผˆๅœจๆญคๆ˜ฏ้กๅค–้ฉ—่ญ‰๏ผ‰๏ผŒๅฐฑๆŠŠ `Query` ๆ”พ้€ฒ `Annotated`๏ผŒไธฆๆŠŠๅƒๆ•ธ `max_length` ่จญ็‚บ `50`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +ๆณจๆ„้ ่จญๅ€ผไป็„ถๆ˜ฏ `None`๏ผŒๆ‰€ไปฅ้€™ๅ€‹ๅƒๆ•ธไปๆ˜ฏๅฏ้ธใ€‚ + +ไธ้Ž๏ผŒ็พๅœจๅœจ `Annotated` ่ฃกๆœ‰ `Query(max_length=50)`๏ผŒๆˆ‘ๅ€‘ๅฐฑๅ‘Š่จด FastAPI ่ฆๅฐ้€™ๅ€‹ๅ€ผๅšใ€Œ้กๅค–้ฉ—่ญ‰ใ€๏ผŒๆœ€ๅคš 50 ๅ€‹ๅญ—ๅ…ƒๅณๅฏใ€‚๐Ÿ˜Ž + +/// tip | ๆ็คบ + +้€™่ฃก็”จ็š„ๆ˜ฏ `Query()`๏ผŒๅ› ็‚บ้€™ๆ˜ฏใ€ŒๆŸฅ่ฉขๅƒๆ•ธใ€ใ€‚็จๅพŒไฝ ๆœƒ็œ‹ๅˆฐ `Path()`ใ€`Body()`ใ€`Header()`ใ€`Cookie()` ็ญ‰๏ผŒๅฎƒๅ€‘ไนŸๆŽฅๅ—่ˆ‡ `Query()` ็›ธๅŒ็š„ๅƒๆ•ธใ€‚ + +/// + +FastAPI ็พๅœจๆœƒ๏ผš + +- ้ฉ—่ญ‰่ณ‡ๆ–™๏ผŒ็ขบไฟ้•ทๅบฆๆœ€ๅคš 50 ๅ€‹ๅญ—ๅ…ƒ +- ็•ถ่ณ‡ๆ–™ไธๅˆๆณ•ๆ™‚๏ผŒๅ›ž็ตฆ็”จๆˆถ็ซฏๆธ…ๆฅš็š„้Œฏ่ชค +- ๅœจ OpenAPI ็š„่ทฏๅพ‘ๆ“ไฝœไธญๆ–‡ไปถๅŒ–่ฉฒๅƒๆ•ธ๏ผˆๅ› ๆญคๆœƒๅ‡บ็พๅœจ่‡ชๅ‹•ๆ–‡ไปถ UI๏ผ‰ + +## ๆ›ฟไปฃๆ–นๅผ๏ผˆ่ˆŠ๏ผ‰๏ผšๅฐ‡ `Query` ไฝœ็‚บ้ ่จญๅ€ผ { #alternative-old-query-as-the-default-value } + +่ˆŠ็‰ˆ FastAPI๏ผˆ0.95.0 ไปฅๅ‰๏ผ‰้œ€่ฆๆŠŠ `Query` ็•ถๆˆๅƒๆ•ธ็š„้ ่จญๅ€ผ๏ผŒ่€Œไธๆ˜ฏๆ”พๅœจ `Annotated` ่ฃกใ€‚ไฝ ๅพˆๅฏ่ƒฝๆœƒๅœจๅ„่™•็œ‹ๅˆฐ้€™็จฎๅฏซๆณ•๏ผŒๆ‰€ไปฅๆˆ‘ไนŸๆœƒ่ชชๆ˜Žไธ€ไธ‹ใ€‚ + +/// tip | ๆ็คบ + +ๆ–ฐ็จ‹ๅผ็ขผไธ”ๅœจๅฏ่ƒฝ็š„ๆƒ…ๆณไธ‹๏ผŒ่ซ‹ไพไธŠ้ข่ชชๆ˜Žไฝฟ็”จ `Annotated`ใ€‚ๅฎƒๆœ‰ๅคš้ …ๅ„ช้ปž๏ผˆๅฆ‚ไธ‹ๆ‰€่ฟฐ๏ผ‰๏ผŒ่€Œๆฒ’ๆœ‰็ผบ้ปžใ€‚๐Ÿฐ + +/// + +้€™ๆ˜ฏๆŠŠ `Query()` ไฝœ็‚บๅ‡ฝๅผๅƒๆ•ธ้ ่จญๅ€ผ็š„ๅฏซๆณ•๏ผŒไธฆๆŠŠๅƒๆ•ธ `max_length` ่จญ็‚บ 50๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผˆๆœชไฝฟ็”จ `Annotated`๏ผ‰๏ผŒๆˆ‘ๅ€‘ๅฟ…้ ˆ็”จ `Query()` ๅ–ไปฃๅ‡ฝๅผไธญ็š„้ ่จญๅ€ผ `None`๏ผŒๅ› ๆญค้œ€่ฆ็”จ `Query(default=None)` ไพ†่จญๅฎš้ ่จญๅ€ผ๏ผ›ๅฐ FastAPI ่€Œ่จ€๏ผŒ้€™้”ๅˆฐ็›ธๅŒ็›ฎ็š„ใ€‚ + +ๆ‰€ไปฅ๏ผš + +```Python +q: str | None = Query(default=None) +``` + +โ€ฆๆœƒ่ฎ“ๅƒๆ•ธ่ฎŠ็‚บๅฏ้ธใ€้ ่จญๅ€ผๆ˜ฏ `None`๏ผŒ็ญ‰ๅŒๆ–ผ๏ผš + +```Python +q: str | None = None +``` + +ไฝ†็”จ `Query` ็š„็‰ˆๆœฌๆœƒๆ˜Ž็ขบๅฎฃๅ‘Šๅฎƒๆ˜ฏๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +ๆŽฅ่‘—๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅ‚ณๆ›ดๅคšๅƒๆ•ธ็ตฆ `Query`ใ€‚ๆญคไพ‹ไธญๆ˜ฏ็”จๆ–ผๅญ—ไธฒ็š„ `max_length` ๅƒๆ•ธ๏ผš + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +้€™ไธ€ๆจฃๆœƒ้ฉ—่ญ‰่ณ‡ๆ–™ใ€ๅœจ่ณ‡ๆ–™ไธๅˆๆณ•ๆ™‚้กฏ็คบๆธ…ๆฅš้Œฏ่ชค๏ผŒไธฆๅœจ OpenAPI ็š„่ทฏๅพ‘ๆ“ไฝœไธญๆ–‡ไปถๅŒ–่ฉฒๅƒๆ•ธใ€‚ + +### ๅฐ‡ `Query` ไฝœ็‚บ้ ่จญๅ€ผๆˆ–ๆ”พๅœจ `Annotated` ไธญ { #query-as-the-default-value-or-in-annotated } + +ๆณจๆ„๏ผŒๆŠŠ `Query` ๆ”พๅœจ `Annotated` ๅ…งๆ™‚๏ผŒไธ่ƒฝไฝฟ็”จ `Query` ็š„ `default` ๅƒๆ•ธใ€‚ + +่ซ‹ๆ”น็”จๅ‡ฝๅผๅƒๆ•ธ็š„ๅฏฆ้š›้ ่จญๅ€ผใ€‚ๅฆๅ‰‡ๆœƒไธไธ€่‡ดใ€‚ + +ไพ‹ๅฆ‚๏ผŒ้€™ๆ˜ฏไธๅ…่จฑ็š„๏ผš + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +โ€ฆๅ› ็‚บไธๆธ…ๆฅš้ ่จญๅ€ผๅˆฐๅบ•่ฉฒๆ˜ฏ `"rick"` ้‚„ๆ˜ฏ `"morty"`ใ€‚ + +ๅ› ๆญค๏ผŒไฝ ๅฏไปฅ๏ผˆไธ”ๆ›ดๆŽจ่–ฆ๏ผ‰้€™ๆจฃๅฏซ๏ผš + +```Python +q: Annotated[str, Query()] = "rick" +``` + +โ€ฆๆˆ–ๅœจ่ผƒ่ˆŠ็š„็จ‹ๅผ็ขผไธญไฝ ๆœƒ็œ‹ๅˆฐ๏ผš + +```Python +q: str = Query(default="rick") +``` + +### `Annotated` ็š„ๅ„ช้ปž { #advantages-of-annotated } + +ๅปบ่ญฐไฝฟ็”จ `Annotated`๏ผŒ่€Œไธๆ˜ฏๅœจๅ‡ฝๅผๅƒๆ•ธไธŠไฝฟ็”จ๏ผˆ่ˆŠๅผ็š„๏ผ‰้ ่จญๅ€ผๅฏซๆณ•๏ผŒ็†็”ฑๅพˆๅคš๏ผŒไธ”ๆ›ดๅฅฝใ€‚๐Ÿค“ + +ๅ‡ฝๅผๅƒๆ•ธ็š„ใ€Œ้ ่จญๅ€ผใ€ๅฐฑๆ˜ฏใ€Œๅฏฆ้š›็š„้ ่จญๅ€ผใ€๏ผŒ้€™ๅœจ Python ็š„็›ด่ฆบไธŠๆ›ดไธ€่‡ดใ€‚๐Ÿ˜Œ + +ไฝ ไนŸๅฏไปฅๅœจๆฒ’ๆœ‰ FastAPI ็š„ๅ…ถไป–ๅœฐๆ–นใ€Œ็›ดๆŽฅๅ‘ผๅซใ€ๅŒไธ€ๅ€‹ๅ‡ฝๅผ๏ผŒ่€Œไธ”่ƒฝใ€Œๅฆ‚้ ๆœŸใ€้‹ไฝœใ€‚่‹ฅๆœ‰ใ€Œๅฟ…ๅกซใ€ๅƒๆ•ธ๏ผˆๆฒ’ๆœ‰้ ่จญๅ€ผ๏ผ‰๏ผŒไฝ ็š„ใ€Œ็ทจ่ผฏๅ™จใ€ๆœƒๆ็คบ้Œฏ่ชค๏ผŒใ€ŒPythonใ€ๅœจๅŸท่กŒๆ™‚ไนŸๆœƒๆŠฑๆ€จไฝ ๆœชๅ‚ณ้žๅฟ…ๅกซๅƒๆ•ธใ€‚ + +่‹ฅไธไฝฟ็”จ `Annotated`ใ€ๆ”น็”จใ€Œ๏ผˆ่ˆŠๅผ๏ผ‰้ ่จญๅ€ผใ€ๅฏซๆณ•๏ผŒไฝ ๅœจๆฒ’ๆœ‰ FastAPI ็š„ใ€Œๅ…ถไป–ๅœฐๆ–นใ€ๅ‘ผๅซ่ฉฒๅ‡ฝๅผๆ™‚๏ผŒๅฐฑๅพ—ใ€Œ่จ˜ๅพ—ใ€ๅ‚ณๅ…ฅๆญฃ็ขบๅƒๆ•ธ๏ผŒๅฆๅ‰‡ๅ€ผๆœƒๅ’Œ้ ๆœŸไธๅŒ๏ผˆไพ‹ๅฆ‚ๆœƒๅพ—ๅˆฐ `QueryInfo` ๆˆ–้กžไผผ็š„ๆฑ่ฅฟ๏ผŒ่€Œไธๆ˜ฏ `str`๏ผ‰ใ€‚ไฝ ็š„็ทจ่ผฏๅ™จไธๆœƒๆ็คบ๏ผŒPython ๅŸท่กŒ่ฉฒๅ‡ฝๅผๆ™‚ไนŸไธๆœƒๆŠฑๆ€จ๏ผŒๅชๆœ‰ๅœจๅ…ง้ƒจๆ“ไฝœๅคฑๆ•—ๆ™‚ๆ‰ๆœƒๅ‡บ้Œฏใ€‚ + +ๅ› ็‚บ `Annotated` ๅฏไปฅๆœ‰ๅคšๅ€‹ไธญ็นผ่ณ‡ๆ–™่จป่งฃ๏ผŒไฝ ็”š่‡ณๅฏไปฅ็”จๅŒไธ€ๅ€‹ๅ‡ฝๅผ้…ๅˆๅ…ถไป–ๅทฅๅ…ท๏ผŒไพ‹ๅฆ‚ Typerใ€‚๐Ÿš€ + +## ๅŠ ๅ…ฅๆ›ดๅคš้ฉ—่ญ‰ { #add-more-validations } + +ไฝ ไนŸๅฏไปฅๅŠ ๅ…ฅ `min_length` ๅƒๆ•ธ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## ๅŠ ๅ…ฅๆญฃ่ฆ่กจ็คบๅผ { #add-regular-expressions } + +ไฝ ๅฏไปฅๅฎš็พฉๅƒๆ•ธๅฟ…้ ˆ็ฌฆๅˆ็š„ regular expression `pattern`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +้€™ๅ€‹็‰นๅฎš็š„ๆญฃ่ฆ่กจ็คบๅผๆจฃๅผๆœƒๆชขๆŸฅๆ”ถๅˆฐ็š„ๅƒๆ•ธๅ€ผๆ˜ฏๅฆ๏ผš + +- `^`๏ผšไปฅๅพŒ็บŒ็š„ๅญ—ๅ…ƒ้–‹้ ญ๏ผŒๅ‰้ขไธ่ƒฝๆœ‰ๅ…ถไป–ๅญ—ๅ…ƒใ€‚ +- `fixedquery`๏ผšๅฟ…้ ˆๆญฃๅฅฝ็ญ‰ๆ–ผ `fixedquery`ใ€‚ +- `$`๏ผšๅœจๆญค็ตๆŸ๏ผŒ`fixedquery` ๅพŒ้ขไธ่ƒฝๅ†ๆœ‰ๅ…ถไป–ๅญ—ๅ…ƒใ€‚ + +ๅฆ‚ๆžœไฝ ๅฐใ€Œๆญฃ่ฆ่กจ็คบๅผใ€ๆ„Ÿๅˆฐๅ›ฐๆƒ‘๏ผŒๅˆฅๆ“”ๅฟƒใ€‚้€™ๅฐๅพˆๅคšไบบไพ†่ชช้ƒฝไธๅฎนๆ˜“ใ€‚ไฝ ไป็„ถๅฏไปฅๅ…ˆไธไฝฟ็”จๆญฃ่ฆ่กจ็คบๅผๅฐฑๅฎŒๆˆๅพˆๅคšไบ‹ๆƒ…ใ€‚ + +็พๅœจไฝ ็Ÿฅ้“๏ผŒ็•ถไฝ ้œ€่ฆๅฎƒๅ€‘ๆ™‚๏ผŒๅฏไปฅๅœจ FastAPI ไธญไฝฟ็”จๅฎƒๅ€‘ใ€‚ + +## ้ ่จญๅ€ผ { #default-values } + +็•ถ็„ถ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `None` ไปฅๅค–็š„้ ่จญๅ€ผใ€‚ + +ๅ‡่จญไฝ ๆƒณๅฎฃๅ‘ŠๆŸฅ่ฉขๅƒๆ•ธ `q` ็š„ `min_length` ๆ˜ฏ `3`๏ผŒไธ”้ ่จญๅ€ผๆ˜ฏ `"fixedquery"`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} + +/// note | ๆณจๆ„ + +ๅช่ฆๆœ‰ไปปไฝ•ๅž‹ๅˆฅ็š„้ ่จญๅ€ผ๏ผˆๅŒ…ๅซ `None`๏ผ‰๏ผŒๅƒๆ•ธๅฐฑๆ˜ฏๅฏ้ธ๏ผˆ้žๅฟ…ๅกซ๏ผ‰ใ€‚ + +/// + +## ๅฟ…ๅกซๅƒๆ•ธ { #required-parameters } + +็•ถๆˆ‘ๅ€‘ไธ้œ€่ฆๅฎฃๅ‘Šๆ›ดๅคš็š„้ฉ—่ญ‰ๆˆ–ไธญ็นผ่ณ‡ๆ–™ๆ™‚๏ผŒๅช่ฆไธๆไพ›้ ่จญๅ€ผ๏ผŒๅฐฑ่ƒฝ่ฎ“ๆŸฅ่ฉขๅƒๆ•ธ `q` ๆˆ็‚บๅฟ…ๅกซ๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +q: str +``` + +่€Œไธๆ˜ฏ๏ผš + +```Python +q: str | None = None +``` + +ไฝ†็พๅœจๆˆ‘ๅ€‘่ฆๆญ้… `Query` ไพ†ๅฎฃๅ‘Š๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +ๅ› ๆญค๏ผŒๅœจไฝฟ็”จ `Query` ๆ™‚่‹ฅ่ฆๅฎฃๅ‘Šๅ€ผ็‚บๅฟ…ๅกซ๏ผŒๅช่ฆไธ่ฆๅฎฃๅ‘Š้ ่จญๅ€ผๅณๅฏ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} + +### ๅฟ…ๅกซ๏ผŒไฝ†ๅฏ็‚บ `None` { #required-can-be-none } + +ไฝ ๅฏไปฅๅฎฃๅ‘Šๅƒๆ•ธๅฏไปฅๆŽฅๅ— `None`๏ผŒไฝ†ไป็„ถๆ˜ฏๅฟ…ๅกซใ€‚้€™ๆœƒๅผทๅˆถ็”จๆˆถ็ซฏไธ€ๅฎš่ฆ้€ๅ‡บไธ€ๅ€‹ๅ€ผ๏ผŒๅณไฝฟ่ฉฒๅ€ผๆ˜ฏ `None`ใ€‚ + +่ฆๅšๅˆฐ้€™้ปž๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘Š `None` ๆ˜ฏๅˆๆณ•ๅž‹ๅˆฅ๏ผŒไฝ†ไธ่ฆๅฎฃๅ‘Š้ ่จญๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## ๆŸฅ่ฉขๅƒๆ•ธๆธ…ๅ–ฎ๏ผๅคšๅ€‹ๅ€ผ { #query-parameter-list-multiple-values } + +็•ถไฝ ็”จ `Query` ๆ˜Ž็ขบๅฎš็พฉๆŸฅ่ฉขๅƒๆ•ธๆ™‚๏ผŒไนŸๅฏไปฅ่ฎ“ๅฎƒๆŽฅๆ”ถไธ€ๅ€‹ๅ€ผ็š„ๆธ…ๅ–ฎ๏ผ›ๆ›ๅฅ่ฉฑ่ชช๏ผŒๅฐฑๆ˜ฏใ€Œๅคšๅ€‹ๅ€ผใ€ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ่ฆๅฎฃๅ‘ŠๆŸฅ่ฉขๅƒๆ•ธ `q` ๅฏไปฅๅœจ URL ไธญๅ‡บ็พๅคšๆฌก๏ผŒไฝ ๅฏไปฅ้€™ๆจฃๅฏซ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +่‹ฅไฝฟ็”จ้€™ๆจฃ็š„ URL๏ผš + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +ไฝ ๆœƒๅœจ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ็š„ๅƒๆ•ธ `q` ไธญ๏ผŒๆ”ถๅˆฐๅคšๅ€‹ `q` ๆŸฅ่ฉขๅƒๆ•ธ็š„ๅ€ผ๏ผˆ`foo` ่ˆ‡ `bar`๏ผ‰๏ผŒไปฅ Python ็š„ `list` ๅฝขๅผใ€‚ + +ๅ› ๆญค๏ผŒๅฐ่ฉฒ URL ็š„ๅ›žๆ‡‰ๆœƒๆ˜ฏ๏ผš + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | ๆ็คบ + +่ฆๅฎฃๅ‘Šๅž‹ๅˆฅ็‚บ `list` ็š„ๆŸฅ่ฉขๅƒๆ•ธ๏ผˆๅฆ‚ไธŠไพ‹๏ผ‰๏ผŒ้œ€่ฆๆ˜Ž็ขบไฝฟ็”จ `Query`๏ผŒๅฆๅ‰‡ๅฎƒๆœƒ่ขซ่งฃ่ฎ€็‚บ่ซ‹ๆฑ‚ๆœฌๆ–‡ใ€‚ + +/// + +ไบ’ๅ‹•ๅผ API ๆ–‡ไปถไนŸๆœƒ็›ธๆ‡‰ๆ›ดๆ–ฐ๏ผŒไปฅไพฟๆ”ฏๆดๅคšๅ€‹ๅ€ผ๏ผš + + + +### ๆŸฅ่ฉขๅƒๆ•ธๆธ…ๅ–ฎ๏ผๅคšๅ€‹ๅ€ผ็š„้ ่จญๅ€ผ { #query-parameter-list-multiple-values-with-defaults } + +ไนŸๅฏไปฅๅœจๆœชๆไพ›ไปปไฝ•ๅ€ผๆ™‚๏ผŒๅฎš็พฉ `list` ๅž‹ๅˆฅ็š„้ ่จญๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} + +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€๏ผš + +``` +http://localhost:8000/items/ +``` + +`q` ็š„้ ่จญๅ€ผๆœƒๆ˜ฏ๏ผš`["foo", "bar"]`๏ผŒ่€Œๅ›žๆ‡‰ๆœƒๆ˜ฏ๏ผš + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### ๅชไฝฟ็”จ `list` { #using-just-list } + +ไฝ ไนŸๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `list`๏ผŒ่€Œไธๆ˜ฏ `list[str]`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} + +/// note | ๆณจๆ„ + +ๆณจๆ„๏ผŒๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒFastAPI ไธๆœƒๆชขๆŸฅๆธ…ๅ–ฎ็š„ๅ…งๅฎนใ€‚ + +ไพ‹ๅฆ‚๏ผŒ`list[int]` ๆœƒๆชขๆŸฅ๏ผˆไธฆๆ–‡ไปถๅŒ–๏ผ‰ๆธ…ๅ–ฎๅ…งๅฎน็‚บๆ•ดๆ•ธ๏ผ›ไฝ†ๅ–ฎ็จไฝฟ็”จ `list` ๅ‰‡ไธๆœƒใ€‚ + +/// + +## ๅฎฃๅ‘Šๆ›ดๅคšไธญ็นผ่ณ‡ๆ–™ { #declare-more-metadata } + +ไฝ ๅฏไปฅ็‚บๅƒๆ•ธๅŠ ๅ…ฅๆ›ดๅคš่ณ‡่จŠใ€‚ + +้€™ไบ›่ณ‡่จŠๆœƒ่ขซๅŒ…ๅซๅœจ็”ข็”Ÿ็š„ OpenAPI ไธญ๏ผŒไพ›ๆ–‡ไปถ UI ่ˆ‡ๅค–้ƒจๅทฅๅ…ทไฝฟ็”จใ€‚ + +/// note | ๆณจๆ„ + +่ซ‹็•™ๆ„๏ผŒไธๅŒๅทฅๅ…ทๅฐ OpenAPI ็š„ๆ”ฏๆด็จ‹ๅบฆๅฏ่ƒฝไธๅŒใ€‚ + +ๆœ‰ไบ›ๅทฅๅ…ทๅฏ่ƒฝๆšซๆ™‚้‚„ไธๆœƒ้กฏ็คบๆ‰€ๆœ‰้กๅค–่ณ‡่จŠ๏ผ›ไธ้ŽๅคšๅŠ้€™ไบ›็ผบๆผๅŠŸ่ƒฝๅทฒๅœจ้–‹็™ผ่ฆๅŠƒไธญใ€‚ + +/// + +ไฝ ๅฏไปฅๅŠ ๅ…ฅ `title`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +ไปฅๅŠ `description`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## ๅˆฅๅๅƒๆ•ธ { #alias-parameters } + +ๆƒณๅƒไฝ ๅธŒๆœ›ๅƒๆ•ธๅ็จฑๆ˜ฏ `item-query`ใ€‚ + +ๅƒ้€™ๆจฃ๏ผš + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +ไฝ† `item-query` ไธๆ˜ฏๅˆๆณ•็š„ Python ่ฎŠๆ•ธๅ็จฑใ€‚ + +ๆœ€ๆŽฅ่ฟ‘็š„ๅคงๆฆ‚ๆ˜ฏ `item_query`ใ€‚ + +ไฝ†ไฝ ไป็„ถ้œ€่ฆๅฎƒๅฐฑๆ˜ฏ `item-query`... + +้‚ฃไฝ ๅฏไปฅๅฎฃๅ‘Šไธ€ๅ€‹ `alias`๏ผŒๅฏฆ้š›ไธŠๅฐฑๆœƒ็”จ้€™ๅ€‹ๅˆฅๅไพ†่ฎ€ๅ–ๅƒๆ•ธๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## ๆฃ„็”จๅƒๆ•ธ { #deprecating-parameters } + +็พๅœจๅ‡่จญไฝ ไธๅ†ๅ–œๆญก้€™ๅ€‹ๅƒๆ•ธไบ†ใ€‚ + +ไฝ ๅฟ…้ ˆๆšซๆ™‚ไฟ็•™ๅฎƒ๏ผŒๅ› ็‚บ้‚„ๆœ‰็”จๆˆถ็ซฏๅœจ็”จ๏ผŒไฝ†ไฝ ๅธŒๆœ›ๆ–‡ไปถ่ƒฝๆธ…ๆฅšๆจ™็คบๅฎƒๆ˜ฏๅทฒๆฃ„็”จใ€‚ + +ๆŽฅ่‘—ๆŠŠๅƒๆ•ธ `deprecated=True` ๅ‚ณ็ตฆ `Query`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +ๆ–‡ไปถๆœƒ้€™ๆจฃ้กฏ็คบ๏ผš + + + +## ๅพž OpenAPI ๆŽ’้™คๅƒๆ•ธ { #exclude-parameters-from-openapi } + +่‹ฅ่ฆๆŠŠๆŸๅ€‹ๆŸฅ่ฉขๅƒๆ•ธๅพž็”ข็”Ÿ็š„ OpenAPI๏ผˆไปฅๅŠ่‡ชๅ‹•ๆ–‡ไปถ็ณป็ตฑ๏ผ‰ไธญๆŽ’้™ค๏ผŒๅฐ‡ `Query` ็š„ `include_in_schema` ่จญ็‚บ `False`๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## ่‡ช่จ‚้ฉ—่ญ‰ { #custom-validation } + +ๆœ‰ๆ™‚ไฝ ้œ€่ฆๅšไธ€ไบ›ไธŠ่ฟฐๅƒๆ•ธ็„กๆณ•่™•็†็š„ใ€Œ่‡ช่จ‚้ฉ—่ญ‰ใ€ใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จใ€Œ่‡ช่จ‚้ฉ—่ญ‰ๅ‡ฝๅผใ€๏ผŒๅฎƒๆœƒๅœจไธ€่ˆฌ้ฉ—่ญ‰ไน‹ๅพŒๅฅ—็”จ๏ผˆไพ‹ๅฆ‚ๅ…ˆ็ขบ่ชๅ€ผๆ˜ฏ `str` ไน‹ๅพŒ๏ผ‰ใ€‚ + +ไฝ ๅฏไปฅๅœจ `Annotated` ไธญไฝฟ็”จ Pydantic ็š„ `AfterValidator` ไพ†้”ๆˆใ€‚ + +/// tip | ๆ็คบ + +Pydantic ไนŸๆœ‰ `BeforeValidator` ็ญ‰็ญ‰ใ€‚๐Ÿค“ + +/// + +ไพ‹ๅฆ‚๏ผŒไปฅไธ‹่‡ช่จ‚้ฉ—่ญ‰ๅ™จๆœƒๆชขๆŸฅ้ …็›ฎ ID ๆ˜ฏๅฆไปฅ `isbn-` ้–‹้ ญ๏ผˆISBN ๆ›ธ็ฑ็ทจ่™Ÿ๏ผ‰๏ผŒๆˆ–ไปฅ `imdb-` ้–‹้ ญ๏ผˆIMDB ้›ปๅฝฑ URL ็š„ ID๏ผ‰๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | ่ชชๆ˜Ž + +้€™้œ€ๆญ้… Pydantic 2 ๆˆ–ไปฅไธŠ็‰ˆๆœฌใ€‚๐Ÿ˜Ž + +/// + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅšไปปไฝ•้œ€่ฆ่ˆ‡ใ€Œๅค–้ƒจๅ…ƒไปถใ€ๆบ้€š็š„้ฉ—่ญ‰๏ผˆไพ‹ๅฆ‚่ณ‡ๆ–™ๅบซๆˆ–ๅ…ถไป– API๏ผ‰๏ผŒๆ‡‰่ฉฒๆ”น็”จใ€ŒFastAPI ไพ่ณดใ€๏ผˆFastAPI Dependencies๏ผ‰๏ผŒไฝ ็จๅพŒๆœƒๅญธๅˆฐใ€‚ + +้€™ไบ›่‡ช่จ‚้ฉ—่ญ‰ๅ™จ้ฉ็”จๆ–ผๅช้œ€ไฝฟ็”จ่ซ‹ๆฑ‚ไธญใ€ŒๅŒไธ€ไปฝ่ณ‡ๆ–™ใ€ๅณๅฏๅฎŒๆˆ็š„ๆชขๆŸฅใ€‚ + +/// + +### ็†่งฃ้€™ๆฎต็จ‹ๅผ็ขผ { #understand-that-code } + +้‡้ปžๅฐฑๆ˜ฏๅœจ `Annotated` ไธญไฝฟ็”จใ€Œ`AfterValidator` ๆญ้…ๅ‡ฝๅผใ€ใ€‚ๅฆ‚ๆžœไฝ ้ก˜ๆ„๏ผŒๅฏไปฅ็•ฅ้Ž้€™ไธ€็ฏ€ใ€‚๐Ÿคธ + +--- + +ไฝ†ๅฆ‚ๆžœไฝ ๅฐ้€™ๅ€‹็ฏ„ไพ‹ๆ„Ÿๅˆฐๅฅฝๅฅ‡ไธ”ไปๆœ‰่ˆˆ่‡ด๏ผŒไปฅไธ‹ๆ˜ฏไธ€ไบ›้กๅค–็ดฐ็ฏ€ใ€‚ + +#### ไฝฟ็”จ `value.startswith()` ็š„ๅญ—ไธฒ { #string-with-value-startswith } + +ไฝ ๆณจๆ„ๅˆฐไบ†ๅ—Ž๏ผŸๅญ—ไธฒ็š„ `value.startswith()` ๅฏไปฅๆŽฅๆ”ถไธ€ๅ€‹ tuple๏ผŒไธฆ้€ไธ€ๆชขๆŸฅ tuple ไธญ็š„ๆฏๅ€‹ๅ€ผ๏ผš + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### ้šจๆฉŸ้ …็›ฎ { #a-random-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 ็š„ๅ…ฉๅ€‹ๅ€ผๅˆ†ๅˆฅๆŒ‡ๅฎš็ตฆ่ฎŠๆ•ธ `id` ๅ’Œ `name`ใ€‚ + +ๅ› ๆญค๏ผŒๅณไฝฟไฝฟ็”จ่€…ๆฒ’ๆœ‰ๆไพ› item ID๏ผŒไป็„ถๆœƒๆ”ถๅˆฐไธ€ๅ€‹้šจๆฉŸๅปบ่ญฐใ€‚ + +โ€ฆโ€ฆ่€Œ้€™ๅ…จ้ƒจๅช็”จไธ€่กŒ็ฐกๅ–ฎ็š„็จ‹ๅผ็ขผๅฎŒๆˆใ€‚๐Ÿคฏ ไฝ ไธๆ„› Python ๅ—Ž๏ผŸ๐Ÿ + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## ้‡้ปžๅ›ž้กง { #recap } + +ไฝ ๅฏไปฅ็‚บๅƒๆ•ธๅฎฃๅ‘Š้กๅค–็š„้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™ใ€‚ + +้€š็”จ็š„้ฉ—่ญ‰่ˆ‡ไธญ็นผ่ณ‡ๆ–™๏ผš + +- `alias` +- `title` +- `description` +- `deprecated` + +ๅญ—ไธฒๅฐˆ็”จ็š„้ฉ—่ญ‰๏ผš + +- `min_length` +- `max_length` +- `pattern` + +ไฝฟ็”จ `AfterValidator` ็š„่‡ช่จ‚้ฉ—่ญ‰ใ€‚ + +ๅœจ้€™ไบ›็ฏ„ไพ‹ไธญ๏ผŒไฝ ็œ‹ๅˆฐไบ†ๅฆ‚ไฝ•็‚บ `str` ๅ€ผๅฎฃๅ‘Š้ฉ—่ญ‰ใ€‚ + +ๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•็‚บๅ…ถไป–ๅž‹ๅˆฅ๏ผˆๅƒๆ˜ฏๆ•ธๅญ—๏ผ‰ๅฎฃๅ‘Š้ฉ—่ญ‰ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/query-params.md b/docs/zh-hant/docs/tutorial/query-params.md new file mode 100644 index 0000000000..f21bf40506 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/query-params.md @@ -0,0 +1,187 @@ +# ๆŸฅ่ฉขๅƒๆ•ธ { #query-parameters } + +็•ถไฝ ๅฎฃๅ‘Šไธๆ˜ฏ่ทฏๅพ‘ๅƒๆ•ธ็š„ๅ…ถไป–ๅ‡ฝๅผๅƒๆ•ธๆ™‚๏ผŒๆœƒ่‡ชๅ‹•่ขซ่ฆ–็‚บใ€ŒๆŸฅ่ฉข๏ผˆquery๏ผ‰ใ€ๅƒๆ•ธใ€‚ + +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} + +ๆŸฅ่ฉขๆ˜ฏๅ‡บ็พๅœจ URL ไธญ `?` ไน‹ๅพŒ็š„ไธ€็ต„้ตๅ€ผๅฐ๏ผŒไปฅ `&` ๅญ—ๅ…ƒๅˆ†้š”ใ€‚ + +ไพ‹ๅฆ‚๏ผŒURL๏ผš + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +...ๆŸฅ่ฉขๅƒๆ•ธ็‚บ๏ผš + +* `skip`๏ผšๅ€ผ็‚บ `0` +* `limit`๏ผšๅ€ผ็‚บ `10` + +ๅ› ็‚บๅฎƒๅ€‘ๆ˜ฏ URL ็š„ไธ€้ƒจๅˆ†๏ผŒๅคฉ็”Ÿๆ˜ฏๅญ—ไธฒใ€‚ + +ไฝ†็•ถไฝ ไปฅ Python ๅž‹ๅˆฅๅฎฃๅ‘Šๅฎƒๅ€‘๏ผˆๅฆ‚ไธŠไพ‹ไธญ็š„ `int`๏ผ‰๏ผŒๅฎƒๅ€‘ๆœƒ่ขซ่ฝ‰ๆ›ๆˆ่ฉฒๅž‹ๅˆฅไธฆๆ“šๆญค้ฉ—่ญ‰ใ€‚ + +ๅฐๆ–ผๆŸฅ่ฉขๅƒๆ•ธ๏ผŒๆœƒๅฅ—็”จ่ˆ‡่ทฏๅพ‘ๅƒๆ•ธ็›ธๅŒ็š„่™•็†ๆต็จ‹๏ผš + +* ็ทจ่ผฏๅ™จๆ”ฏๆด๏ผˆ็•ถ็„ถ๏ผ‰ +* ่ณ‡ๆ–™ ใ€Œ่งฃๆžใ€ +* ่ณ‡ๆ–™้ฉ—่ญ‰ +* ่‡ชๅ‹•ๆ–‡ไปถ + +## ้ ่จญๅ€ผ { #defaults } + +็”ฑๆ–ผๆŸฅ่ฉขๅƒๆ•ธไธๆ˜ฏ่ทฏๅพ‘็š„ๅ›บๅฎš้ƒจๅˆ†๏ผŒๅ› ๆญคๅฏไปฅๆ˜ฏ้ธๅกซไธฆๅ…ทๆœ‰้ ่จญๅ€ผใ€‚ + +ๅœจไธŠ้ข็š„ไพ‹ๅญไธญ๏ผŒ้ ่จญๅ€ผ็‚บ `skip=0` ่ˆ‡ `limit=10`ใ€‚ + +ๅ› ๆญค๏ผŒ้€ ่จชไธ‹ๅˆ— URL๏ผš + +``` +http://127.0.0.1:8000/items/ +``` + +็ญ‰ๅŒๆ–ผ้€ ่จช๏ผš + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +ไฝ†ๅฆ‚ๆžœไฝ ๆ”น็‚บ้€ ่จช๏ผš + +``` +http://127.0.0.1:8000/items/?skip=20 +``` + +ๅ‡ฝๅผไธญ็š„ๅƒๆ•ธๅ€ผๆœƒๆ˜ฏ๏ผš + +* `skip=20`๏ผšๅ› ็‚บไฝ ๅœจ URL ไธญ่จญๅฎšไบ†ๅฎƒ +* `limit=10`๏ผšๅ› ็‚บ้‚ฃๆ˜ฏ้ ่จญๅ€ผ + +## ้ธ็”จๅƒๆ•ธ { #optional-parameters } + +ๅŒๆจฃๅœฐ๏ผŒไฝ ๅฏไปฅๅฐ‡้ ่จญๅ€ผ่จญ็‚บ `None` ไพ†ๅฎฃๅ‘Š้ธ็”จ็š„ๆŸฅ่ฉขๅƒๆ•ธ๏ผš + +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅ‡ฝๅผๅƒๆ•ธ `q` ็‚บ้ธ็”จ๏ผŒไธ”้ ่จญ็‚บ `None`ใ€‚ + +/// check | ๆณจๆ„ + +ๅฆๅค–่ซ‹ๆณจๆ„๏ผŒFastAPI ่ƒฝ่พจ่ญ˜ๅ‡บ่ทฏๅพ‘ๅƒๆ•ธ `item_id` ๆ˜ฏ่ทฏๅพ‘ๅƒๆ•ธ๏ผŒ่€Œ `q` ไธๆ˜ฏ๏ผŒๅ› ๆญค `q` ๆœƒ่ขซ็•ถไฝœๆŸฅ่ฉขๅƒๆ•ธใ€‚ + +/// + +## ๆŸฅ่ฉขๅƒๆ•ธๅž‹ๅˆฅ่ฝ‰ๆ› { #query-parameter-type-conversion } + +ไฝ ไนŸๅฏไปฅๅฎฃๅ‘Š `bool` ๅž‹ๅˆฅ๏ผŒๅ€ผๆœƒ่ขซ่‡ชๅ‹•่ฝ‰ๆ›๏ผš + +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅฆ‚ๆžœไฝ ้€ ่จช๏ผš + +``` +http://127.0.0.1:8000/items/foo?short=1 +``` + +ๆˆ– + +``` +http://127.0.0.1:8000/items/foo?short=True +``` + +ๆˆ– + +``` +http://127.0.0.1:8000/items/foo?short=true +``` + +ๆˆ– + +``` +http://127.0.0.1:8000/items/foo?short=on +``` + +ๆˆ– + +``` +http://127.0.0.1:8000/items/foo?short=yes +``` + +ๆˆ–ไปปไฝ•ๅ…ถไป–ๅคงๅฐๅฏซ่ฎŠๅŒ–๏ผˆๅ…จๅคงๅฏซใ€้ฆ–ๅญ—ๆฏๅคงๅฏซ็ญ‰๏ผ‰๏ผŒไฝ ็š„ๅ‡ฝๅผๆœƒๅฐ‡ๅƒๆ•ธ `short` ่ฆ–็‚บ `bool` ๅ€ผ `True`ใ€‚ๅฆๅ‰‡็‚บ `False`ใ€‚ + +## ๅคšๅ€‹่ทฏๅพ‘่ˆ‡ๆŸฅ่ฉขๅƒๆ•ธ { #multiple-path-and-query-parameters } + +ไฝ ๅฏไปฅๅŒๆ™‚ๅฎฃๅ‘Šๅคšๅ€‹่ทฏๅพ‘ๅƒๆ•ธ่ˆ‡ๆŸฅ่ฉขๅƒๆ•ธ๏ผŒFastAPI ๆœƒ่‡ชๅ‹•ๅˆ†่พจใ€‚ + +่€Œไธ”ไธๅฟ…ๆŒ‰็‰นๅฎš้ †ๅบๅฎฃๅ‘Šใ€‚ + +ๆœƒไพๅ็จฑ่พจ่ญ˜๏ผš + +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} + +## ๅฟ…ๅกซๆŸฅ่ฉขๅƒๆ•ธ { #required-query-parameters } + +็•ถไฝ ็‚บ้ž่ทฏๅพ‘ๅƒๆ•ธ๏ผˆ็›ฎๅ‰ๆˆ‘ๅ€‘ๅช็œ‹ๅˆฐๆŸฅ่ฉขๅƒๆ•ธ๏ผ‰ๅฎฃๅ‘Šไบ†้ ่จญๅ€ผๆ™‚๏ผŒๅฎƒๅฐฑไธๆ˜ฏๅฟ…ๅกซใ€‚ + +่‹ฅไฝ ไธๆƒณๆไพ›็‰นๅฎš้ ่จญๅ€ผใ€ๅชๆƒณ่ฎ“ๅฎƒ็‚บ้ธๅกซ๏ผŒๅฐ‡้ ่จญๅ€ผ่จญ็‚บ `None`ใ€‚ + +ไฝ†่‹ฅไฝ ่ฆ่ฎ“ๆŸฅ่ฉขๅƒๆ•ธๆˆ็‚บๅฟ…ๅกซ๏ผŒๅช่ฆไธ่ฆๅฎฃๅ‘Šไปปไฝ•้ ่จญๅ€ผ๏ผš + +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} + +ๆญค่™•ๆŸฅ่ฉขๅƒๆ•ธ `needy` ๆ˜ฏๅฟ…ๅกซ็š„ `str`ใ€‚ + +ๅฆ‚ๆžœไฝ ๅœจ็€่ฆฝๅ™จไธญ้–‹ๅ•Ÿๅฆ‚ไธ‹็š„ URL๏ผš + +``` +http://127.0.0.1:8000/items/foo-item +``` + +...ๆฒ’ๆœ‰ๅŠ ไธŠๅฟ…ๅกซ็š„ `needy` ๅƒๆ•ธ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ้กžไผผ้€™ๆจฃ็š„้Œฏ่ชค๏ผš + +```JSON +{ + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] +} +``` + +็”ฑๆ–ผ `needy` ๆ˜ฏๅฟ…ๅกซๅƒๆ•ธ๏ผŒไฝ ้œ€่ฆๅœจ URL ไธญ่จญๅฎšๅฎƒ๏ผš + +``` +http://127.0.0.1:8000/items/foo-item?needy=sooooneedy +``` + +...้€™ๆจฃๅฐฑๆœƒๆˆๅŠŸ๏ผš + +```JSON +{ + "item_id": "foo-item", + "needy": "sooooneedy" +} +``` + +็•ถ็„ถ๏ผŒไฝ ๅฏไปฅๅŒๆ™‚ๅฎš็พฉ้ƒจๅˆ†ๅƒๆ•ธ็‚บๅฟ…ๅกซใ€้ƒจๅˆ†ๆœ‰้ ่จญๅ€ผใ€้ƒจๅˆ†็‚บ้ธๅกซ๏ผš + +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} + +ๅœจๆญคไพ‹ไธญ๏ผŒๆœ‰ 3 ๅ€‹ๆŸฅ่ฉขๅƒๆ•ธ๏ผš + +* `needy`๏ผŒๅฟ…ๅกซ็š„ `str`ใ€‚ +* `skip`๏ผŒๅ…ทๆœ‰้ ่จญๅ€ผ `0` ็š„ `int`ใ€‚ +* `limit`๏ผŒ้ธๅกซ็š„ `int`ใ€‚ + +/// tip | ๆ็คบ + +ไฝ ไนŸๅฏไปฅๅƒๅœจ[่ทฏๅพ‘ๅƒๆ•ธ](path-params.md#predefined-values){.internal-link target=_blank}ไธญไธ€ๆจฃไฝฟ็”จ `Enum`ใ€‚ + +/// diff --git a/docs/zh-hant/docs/tutorial/request-files.md b/docs/zh-hant/docs/tutorial/request-files.md new file mode 100644 index 0000000000..c8606a3f23 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# ่ซ‹ๆฑ‚ไธญ็š„ๆช”ๆกˆ { #request-files } + +ไฝ ๅฏไปฅไฝฟ็”จ `File` ๅฎš็พฉ็”ฑ็”จๆˆถ็ซฏไธŠๅ‚ณ็š„ๆช”ๆกˆใ€‚ + +/// info + +่‹ฅ่ฆๆŽฅๆ”ถไธŠๅ‚ณ็š„ๆช”ๆกˆ๏ผŒ่ซ‹ๅ…ˆๅฎ‰่ฃ `python-multipart`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` + +ๅ› ็‚บไธŠๅ‚ณ็š„ๆช”ๆกˆๆ˜ฏไปฅใ€Œ่กจๅ–ฎ่ณ‡ๆ–™ใ€้€ๅ‡บ็š„ใ€‚ + +/// + +## ๅŒฏๅ…ฅ `File` { #import-file } + +ๅพž `fastapi` ๅŒฏๅ…ฅ `File` ่ˆ‡ `UploadFile`๏ผš + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} + +## ๅฎš็พฉ `File` ๅƒๆ•ธ { #define-file-parameters } + +ๅ’Œ `Body` ๆˆ– `Form` ไธ€ๆจฃ็š„ๆ–นๅผๅปบ็ซ‹ๆช”ๆกˆๅƒๆ•ธ๏ผš + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} + +/// info + +`File` ๆ˜ฏ็›ดๆŽฅ็นผๆ‰ฟ่‡ช `Form` ็š„้กžๅˆฅใ€‚ + +ไฝ†่ซ‹่จ˜ไฝ๏ผŒ็•ถไฝ ๅพž `fastapi` ๅŒฏๅ…ฅ `Query`ใ€`Path`ใ€`File` ็ญ‰ๆ™‚๏ผŒๅฎƒๅ€‘ๅ…ถๅฏฆๆ˜ฏๅ›žๅ‚ณ็‰นๆฎŠ้กžๅˆฅ็š„ๅ‡ฝๅผใ€‚ + +/// + +/// tip + +่ฆๅฎฃๅ‘Šๆช”ๆกˆๆœฌๆ–‡๏ผŒๅฟ…้ ˆไฝฟ็”จ `File`๏ผŒๅฆๅ‰‡ๅƒๆ•ธๆœƒ่ขซ่งฃ่ฎ€็‚บๆŸฅ่ฉขๅƒๆ•ธๆˆ–ๆœฌๆ–‡๏ผˆJSON๏ผ‰ๅƒๆ•ธใ€‚ + +/// + +ๆช”ๆกˆๆœƒไปฅใ€Œ่กจๅ–ฎ่ณ‡ๆ–™ใ€ไธŠๅ‚ณใ€‚ + +ๅฆ‚ๆžœไฝ ๅฐ‡่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ๏ผˆpath operation function๏ผ‰็š„ๅƒๆ•ธๅž‹ๅˆฅๅฎฃๅ‘Š็‚บ `bytes`๏ผŒ**FastAPI** ๆœƒๆ›ฟไฝ ่ฎ€ๅ–ๆช”ๆกˆ๏ผŒไฝ ๆœƒไปฅ `bytes` ๅ–ๅพ—ๅ…งๅฎนใ€‚ + +่ซ‹ๆณจๆ„๏ผŒ้€™่กจ็คบๆ•ดๅ€‹ๅ…งๅฎนๆœƒๅญ˜ๆ”พๅœจ่จ˜ๆ†ถ้ซ”ไธญ๏ผŒ้ฉๅˆๅฐๆช”ๆกˆใ€‚ + +ไฝ†ๅœจ่จฑๅคšๆƒ…ๆณไธ‹๏ผŒไฝฟ็”จ `UploadFile` ๆœƒๆ›ดๅฅฝใ€‚ + +## ไฝฟ็”จ `UploadFile` ็š„ๆช”ๆกˆๅƒๆ•ธ { #file-parameters-with-uploadfile } + +ๅฐ‡ๆช”ๆกˆๅƒๆ•ธๅž‹ๅˆฅ่จญ็‚บ `UploadFile`๏ผš + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} + +ไฝฟ็”จ `UploadFile` ็›ธ่ผƒๆ–ผ `bytes` ๆœ‰ๆ•ธๅ€‹ๅ„ช้ปž๏ผš + +* ไฝ ไธๅฟ…ๅœจๅƒๆ•ธ็š„้ ่จญๅ€ผไฝฟ็”จ `File()`ใ€‚ +* ๅฎƒไฝฟ็”จใ€Œspooledใ€ๆช”ๆกˆ๏ผš + * ๆช”ๆกˆๅœจ่จ˜ๆ†ถ้ซ”ไธญไฟๅญ˜ๅˆฐๆŸๅ€‹ๅคงๅฐไธŠ้™๏ผŒ่ถ…้ŽไธŠ้™ๅพŒๆœƒๅญ˜ๅˆฐ็ฃ็ขŸใ€‚ +* ๅ› ๆญค้ฉๅˆ่™•็†ๅคงๅž‹ๆช”ๆกˆ๏ผˆไพ‹ๅฆ‚ๅœ–็‰‡ใ€ๅฝฑ็‰‡ใ€ๅคงๅž‹ไบŒ้€ฒไฝๆช”็ญ‰๏ผ‰๏ผŒ่€Œไธๆœƒ่€—็›ก่จ˜ๆ†ถ้ซ”ใ€‚ +* ไฝ ๅฏไปฅๅ–ๅพ—ไธŠๅ‚ณๆช”ๆกˆ็š„ไธญ็นผ่ณ‡ๆ–™ใ€‚ +* ๅฎƒๆไพ›ไธ€ๅ€‹้กžๆช”ๆกˆ็š„ `async` ไป‹้ขใ€‚ +* ๅฎƒๆœƒๆไพ›ๅฏฆ้š›็š„ Python `SpooledTemporaryFile` ็‰ฉไปถ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅ‚ณ็ตฆ้œ€่ฆ้กžๆช”ๆกˆ็‰ฉไปถ็š„ๅ…ถไป–ๅ‡ฝๅผๆˆ–ๅ‡ฝๅผๅบซใ€‚ + +### `UploadFile` { #uploadfile } + +`UploadFile` ๅ…ทๆœ‰ไปฅไธ‹ๅฑฌๆ€ง๏ผš + +* `filename`๏ผšไธ€ๅ€‹ `str`๏ผŒ็‚บไธŠๅ‚ณ็š„ๅŽŸๅง‹ๆช”ๅ๏ผˆไพ‹ๅฆ‚ `myimage.jpg`๏ผ‰ใ€‚ +* `content_type`๏ผšไธ€ๅ€‹ `str`๏ผŒ็‚บๅ…งๅฎน้กžๅž‹๏ผˆMIME type / media type๏ผ‰๏ผˆไพ‹ๅฆ‚ `image/jpeg`๏ผ‰ใ€‚ +* `file`๏ผšไธ€ๅ€‹ `SpooledTemporaryFile`๏ผˆ้กžๆช”ๆกˆ็‰ฉไปถ๏ผ‰ใ€‚้€™ๆ˜ฏ็œŸๆญฃ็š„ Python ๆช”ๆกˆ็‰ฉไปถ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅ‚ณ็ตฆๆœŸๅพ…ใ€Œ้กžๆช”ๆกˆใ€็‰ฉไปถ็š„ๅ…ถไป–ๅ‡ฝๅผๆˆ–ๅ‡ฝๅผๅบซใ€‚ + +`UploadFile` ๆœ‰ไปฅไธ‹ `async` ๆ–นๆณ•ใ€‚ๅฎƒๅ€‘ๅบ•ๅฑคๆœƒๅ‘ผๅซๅฐๆ‡‰็š„ๆช”ๆกˆๆ–นๆณ•๏ผˆไฝฟ็”จๅ…ง้ƒจ็š„ `SpooledTemporaryFile`๏ผ‰ใ€‚ + +* `write(data)`๏ผšๅฐ‡ `data`๏ผˆ`str` ๆˆ– `bytes`๏ผ‰ๅฏซๅ…ฅๆช”ๆกˆใ€‚ +* `read(size)`๏ผš่ฎ€ๅ–ๆช”ๆกˆ็š„ `size`๏ผˆ`int`๏ผ‰ๅ€‹ไฝๅ…ƒ็ต„/ๅญ—ๅ…ƒใ€‚ +* `seek(offset)`๏ผš็งปๅ‹•ๅˆฐๆช”ๆกˆไธญ็š„ไฝๅ…ƒ็ต„ไฝ็ฝฎ `offset`๏ผˆ`int`๏ผ‰ใ€‚ + * ไพ‹ๅฆ‚๏ผŒ`await myfile.seek(0)` ๆœƒ็งปๅˆฐๆช”ๆกˆ้–‹้ ญใ€‚ + * ็•ถไฝ ๅทฒ็ถ“ๅŸท่กŒ้Ž `await myfile.read()`๏ผŒไน‹ๅพŒ้œ€่ฆๅ†ๆฌก่ฎ€ๅ–ๅ…งๅฎนๆ™‚็‰นๅˆฅๆœ‰็”จใ€‚ +* `close()`๏ผš้—œ้–‰ๆช”ๆกˆใ€‚ + +็”ฑๆ–ผ้€™ไบ›้ƒฝๆ˜ฏ `async` ๆ–นๆณ•๏ผŒไฝ ้œ€่ฆไปฅ await ๅ‘ผๅซๅฎƒๅ€‘ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅœจ `async` ็š„่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญๅฏ้€™ๆจฃ่ฎ€ๅ–ๅ…งๅฎน๏ผš + +```Python +contents = await myfile.read() +``` + +่‹ฅๆ˜ฏๅœจไธ€่ˆฌ็š„ `def` ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผไธญ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅๅญ˜ๅ– `UploadFile.file`๏ผŒไพ‹ๅฆ‚๏ผš + +```Python +contents = myfile.file.read() +``` + +/// note | `async` ๆŠ€่ก“็ดฐ็ฏ€ + +็•ถไฝ ไฝฟ็”จ้€™ไบ› `async` ๆ–นๆณ•ๆ™‚๏ผŒ**FastAPI** ๆœƒๅœจๅŸท่กŒ็ท’ๆฑ ไธญๅŸท่กŒๅฐๆ‡‰็š„ๆช”ๆกˆๆ–นๆณ•ไธฆ็ญ‰ๅพ…็ตๆžœใ€‚ + +/// + +/// note | Starlette ๆŠ€่ก“็ดฐ็ฏ€ + +**FastAPI** ็š„ `UploadFile` ็›ดๆŽฅ็นผๆ‰ฟ่‡ช **Starlette** ็š„ `UploadFile`๏ผŒไฝ†ๆ–ฐๅขžไบ†ไธ€ไบ›ๅฟ…่ฆ้ƒจๅˆ†๏ผŒไฝฟๅ…ถ่ˆ‡ **Pydantic** ๅŠ FastAPI ๅ…ถไป–้ƒจๅˆ†็›ธๅฎนใ€‚ + +/// + +## ไป€้บผๆ˜ฏใ€Œ่กจๅ–ฎ่ณ‡ๆ–™ใ€ { #what-is-form-data } + +HTML ่กจๅ–ฎ๏ผˆ`
`๏ผ‰้€ๅˆฐไผบๆœๅ™จ็š„่ณ‡ๆ–™้€šๅธธไฝฟ็”จไธ€็จฎใ€Œ็‰นๆฎŠใ€็ทจ็ขผ๏ผŒ่ˆ‡ JSON ไธๅŒใ€‚ + +**FastAPI** ๆœƒๅพžๆญฃ็ขบ็š„ไฝ็ฝฎ่ฎ€ๅ–่ฉฒ่ณ‡ๆ–™๏ผŒ่€Œไธๆ˜ฏ็•ถไฝœ JSONใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +่กจๅ–ฎ่ณ‡ๆ–™ๅœจไธๅŒ…ๅซๆช”ๆกˆๆ™‚๏ผŒ้€šๅธธไฝฟ็”จๅช’้ซ”ๅž‹ๅˆฅ `application/x-www-form-urlencoded` ็ทจ็ขผใ€‚ + +ไฝ†็•ถ่กจๅ–ฎๅŒ…ๅซๆช”ๆกˆๆ™‚๏ผŒๆœƒไฝฟ็”จ `multipart/form-data` ็ทจ็ขผใ€‚่‹ฅไฝ ไฝฟ็”จ `File`๏ผŒ**FastAPI** ๆœƒ็Ÿฅ้“่ฆๅพž่ซ‹ๆฑ‚ๆœฌๆ–‡็š„ๆญฃ็ขบ้ƒจๅˆ†ๅ–ๅพ—ๆช”ๆกˆใ€‚ + +่‹ฅๆƒณ้€ฒไธ€ๆญฅไบ†่งฃ้€™ไบ›็ทจ็ขผ่ˆ‡่กจๅ–ฎๆฌ„ไฝ๏ผŒ่ซ‹ๅƒ่€ƒ MDN Web Docs ็š„ POSTใ€‚ + +/// + +/// warning + +ไฝ ๅฏไปฅๅœจไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœไธญๅฎฃๅ‘Šๅคšๅ€‹ `File` ่ˆ‡ `Form` ๅƒๆ•ธ๏ผŒไฝ†ไธ่ƒฝๅŒๆ™‚ๅฎฃๅ‘Š้ ๆœŸไปฅ JSON ๆŽฅๆ”ถ็š„ `Body` ๆฌ„ไฝ๏ผŒๅ› ็‚บๆญค่ซ‹ๆฑ‚็š„ๆœฌๆ–‡ๆœƒไฝฟ็”จ `multipart/form-data` ่€Œไธๆ˜ฏ `application/json`ใ€‚ + +้€™ไธๆ˜ฏ **FastAPI** ็š„้™ๅˆถ๏ผŒ่€Œๆ˜ฏ HTTP ๅ”ๅฎšๆœฌ่บซ็š„่ฆ็ฏ„ใ€‚ + +/// + +## ๅฏ้ธ็š„ๆช”ๆกˆไธŠๅ‚ณ { #optional-file-upload } + +ๅฏ้€้Žไธ€่ˆฌๅž‹ๅˆฅ่จป่งฃไธฆๅฐ‡้ ่จญๅ€ผ่จญ็‚บ `None` ไฝฟๆช”ๆกˆๆˆ็‚บๅฏ้ธ๏ผš + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## `UploadFile` ๆญ้…้กๅค–ไธญ็นผ่ณ‡ๆ–™ { #uploadfile-with-additional-metadata } + +ไฝ ไนŸๅฏไปฅๅœจ `UploadFile` ไธŠๆญ้… `File()`๏ผŒไพ‹ๅฆ‚็”จไพ†่จญๅฎš้กๅค–็š„ไธญ็นผ่ณ‡ๆ–™๏ผš + +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} + +## ๅคšๆช”ๆกˆไธŠๅ‚ณ { #multiple-file-uploads } + +ๅฏไปฅๅŒๆ™‚ไธŠๅ‚ณๅคšๅ€‹ๆช”ๆกˆใ€‚ + +ๅฎƒๅ€‘ๆœƒๅŒๅฑฌๆ–ผไปฅใ€Œ่กจๅ–ฎ่ณ‡ๆ–™ใ€้€ๅ‡บ็š„ๅŒไธ€ๅ€‹่กจๅ–ฎๆฌ„ไฝใ€‚ + +่ฆ้€™้บผๅš๏ผŒๅฐ‡ๅž‹ๅˆฅๅฎฃๅ‘Š็‚บ `bytes` ๆˆ– `UploadFile` ็š„ `list`๏ผš + +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} + +ไฝ ๆœƒๅฆ‚ๅฎฃๅ‘Šๆ‰€็คบ๏ผŒๆ”ถๅˆฐ็”ฑ `bytes` ๆˆ– `UploadFile` ็ต„ๆˆ็š„ `list`ใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.responses import HTMLResponse`ใ€‚ + +**FastAPI** ็‚บไบ†่ฎ“ไฝ ๏ผˆ้–‹็™ผ่€…๏ผ‰ๆ›ดๆ–นไพฟ๏ผŒๆไพ›่ˆ‡ `starlette.responses` ็›ธๅŒ็š„ๅ…งๅฎนไฝœ็‚บ `fastapi.responses`ใ€‚ไฝ†ๅคงๅคšๆ•ธๅฏ็”จ็š„ๅ›žๆ‡‰้กžๅž‹ๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +### ๅคšๆช”ๆกˆไธŠๅ‚ณไธ”ๅŒ…ๅซ้กๅค–ไธญ็นผ่ณ‡ๆ–™ { #multiple-file-uploads-with-additional-metadata } + +ๅŒๆจฃๅœฐ๏ผŒๅณไฝฟๅฐ `UploadFile`๏ผŒไฝ ไนŸๅฏไปฅ็”จ `File()` ่จญๅฎš้กๅค–ๅƒๆ•ธ๏ผš + +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} + +## ๅฐ็ต { #recap } + +ไฝฟ็”จ `File`ใ€`bytes` ่ˆ‡ `UploadFile` ไพ†ๅฎฃๅ‘Š่ซ‹ๆฑ‚ไธญ่ฆไธŠๅ‚ณ็š„ๆช”ๆกˆ๏ผŒ้€™ไบ›ๆช”ๆกˆๆœƒไปฅ่กจๅ–ฎ่ณ‡ๆ–™้€ๅ‡บใ€‚ diff --git a/docs/zh-hant/docs/tutorial/request-form-models.md b/docs/zh-hant/docs/tutorial/request-form-models.md new file mode 100644 index 0000000000..8cf4a7c5e8 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# ่กจๅ–ฎๆจกๅž‹ { #form-models } + +ไฝ ๅฏไปฅไฝฟ็”จ **Pydantic ๆจกๅž‹** ๅœจ FastAPI ไธญๅฎฃๅ‘Š **่กจๅ–ฎๆฌ„ไฝ**ใ€‚ + +/// info | ่ชชๆ˜Ž + +่ฆไฝฟ็”จ่กจๅ–ฎ๏ผŒ้ฆ–ๅ…ˆๅฎ‰่ฃ `python-multipart`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๅ•Ÿ็”จๅพŒๅ†ๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` + +/// + +/// note | ๆณจๆ„ + +ๆญคๅŠŸ่ƒฝ่‡ช FastAPI ็‰ˆๆœฌ `0.113.0` ่ตทๆ”ฏๆดใ€‚๐Ÿค“ + +/// + +## ้‡ๅฐ่กจๅ–ฎ็š„ Pydantic ๆจกๅž‹ { #pydantic-models-for-forms } + +ไฝ ๅช้œ€่ฆๅฎฃๅ‘Šไธ€ๅ€‹ **Pydantic ๆจกๅž‹**๏ผŒๅŒ…ๅซไฝ ่ฆๆŽฅๆ”ถ็‚บ **่กจๅ–ฎๆฌ„ไฝ** ็š„ๆฌ„ไฝ๏ผŒ็„ถๅพŒๅฐ‡ๅƒๆ•ธๅฎฃๅ‘Š็‚บ `Form`๏ผš + +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} + +**FastAPI** ๆœƒๅพž่ซ‹ๆฑ‚ไธญ็š„ **่กจๅ–ฎ่ณ‡ๆ–™** ๆ“ทๅ– **ๅ„ๆฌ„ไฝ** ็š„่ณ‡ๆ–™๏ผŒไธฆๅฐ‡้€™ไบ›่ณ‡ๆ–™็ต„ๆˆไฝ ๅฎš็พฉ็š„ Pydantic ๆจกๅž‹ๅฏฆไพ‹ใ€‚ + +## ๆชข่ฆ–ๆ–‡ไปถ { #check-the-docs } + +ไฝ ๅฏไปฅๅœจ `/docs` ็š„ๆ–‡ไปถ UI ไธญ้ฉ—่ญ‰๏ผš + +
+ +
+ +## ็ฆๆญข้กๅค–็š„่กจๅ–ฎๆฌ„ไฝ { #forbid-extra-form-fields } + +ๅœจๆŸไบ›็‰นๆฎŠๆƒ…ๆณ๏ผˆๅฏ่ƒฝไธๅธธ่ฆ‹๏ผ‰ไธ‹๏ผŒไฝ ๅฏ่ƒฝๅธŒๆœ›ๅƒ…ๅ…่จฑ Pydantic ๆจกๅž‹ไธญๅฎฃๅ‘Š็š„่กจๅ–ฎๆฌ„ไฝ๏ผŒไธฆ็ฆๆญขไปปไฝ•้กๅค–ๆฌ„ไฝใ€‚ + +/// note | ๆณจๆ„ + +ๆญคๅŠŸ่ƒฝ่‡ช FastAPI ็‰ˆๆœฌ `0.114.0` ่ตทๆ”ฏๆดใ€‚๐Ÿค“ + +/// + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ็š„ๆจกๅž‹่จญๅฎšไพ† `forbid` ไปปไฝ• `extra` ๆฌ„ไฝ๏ผš + +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} + +ๅฆ‚ๆžœ็”จๆˆถ็ซฏๅ˜—่ฉฆๅ‚ณ้€้กๅค–่ณ‡ๆ–™๏ผŒๅฐ‡ๆœƒๆ”ถๅˆฐ้Œฏ่ชคๅ›žๆ‡‰ใ€‚ + +ไพ‹ๅฆ‚๏ผŒ็”จๆˆถ็ซฏ่‹ฅ้€ๅ‡บไปฅไธ‹่กจๅ–ฎๆฌ„ไฝ๏ผš + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +ไป–ๅ€‘ๆœƒๆ”ถๅˆฐไธ€ๅ€‹้Œฏ่ชคๅ›žๆ‡‰๏ผŒๅ‘Š็Ÿฅๆฌ„ไฝ `extra` ไธ่ขซๅ…่จฑ๏ผš + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## ๆ‘˜่ฆ { #summary } + +ไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ๅœจ FastAPI ไธญๅฎฃๅ‘Š่กจๅ–ฎๆฌ„ไฝใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/tutorial/request-forms-and-files.md b/docs/zh-hant/docs/tutorial/request-forms-and-files.md new file mode 100644 index 0000000000..6dcc1c260f --- /dev/null +++ b/docs/zh-hant/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# ่ซ‹ๆฑ‚ไธญ็š„่กจๅ–ฎ่ˆ‡ๆช”ๆกˆ { #request-forms-and-files } + +ไฝ ๅฏไปฅไฝฟ็”จ `File` ่ˆ‡ `Form` ๅŒๆ™‚ๅฎš็พฉๆช”ๆกˆ่ˆ‡่กจๅ–ฎๆฌ„ไฝใ€‚ + +/// info + +่ฆๆŽฅๆ”ถไธŠๅ‚ณ็š„ๆช”ๆกˆ่ˆ‡/ๆˆ–่กจๅ–ฎ่ณ‡ๆ–™๏ผŒ่ซ‹ๅ…ˆๅฎ‰่ฃ `python-multipart`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹ [่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅ†ๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` + +/// + +## ๅŒฏๅ…ฅ `File` ่ˆ‡ `Form` { #import-file-and-form } + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} + +## ๅฎš็พฉ `File` ่ˆ‡ `Form` ๅƒๆ•ธ { #define-file-and-form-parameters } + +ไปฅ่ˆ‡ `Body` ๆˆ– `Query` ็›ธๅŒ็š„ๆ–นๅผๅปบ็ซ‹ๆช”ๆกˆ่ˆ‡่กจๅ–ฎๅƒๆ•ธ๏ผš + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} + +ๆช”ๆกˆ่ˆ‡่กจๅ–ฎๆฌ„ไฝๆœƒไฝœ็‚บ่กจๅ–ฎ่ณ‡ๆ–™ไธŠๅ‚ณ๏ผŒ่€Œไฝ ๅฐ‡่ƒฝๆŽฅๆ”ถๅˆฐ้€™ไบ›ๆช”ๆกˆ่ˆ‡ๆฌ„ไฝใ€‚ + +ไฝ ไนŸๅฏไปฅๅฐ‡้ƒจๅˆ†ๆช”ๆกˆๅฎฃๅ‘Š็‚บ `bytes`๏ผŒๅฆไธ€ไบ›ๅฎฃๅ‘Š็‚บ `UploadFile`ใ€‚ + +/// warning + +ไฝ ๅฏไปฅๅœจไธ€ๅ€‹่ทฏๅพ‘ๆ“ไฝœ (path operation) ไธญๅฎฃๅ‘Šๅคšๅ€‹ `File` ่ˆ‡ `Form` ๅƒๆ•ธ๏ผŒไฝ†ไธ่ƒฝๅŒๆ™‚ๅ†ๅฎฃๅ‘Š้ ๆœŸไปฅ JSON ๆŽฅๆ”ถ็š„ `Body` ๆฌ„ไฝ๏ผŒๅ› ็‚บ่ฉฒ่ซ‹ๆฑ‚็š„ๆœฌๆ–‡ๆœƒไฝฟ็”จ `multipart/form-data` ่€Œ้ž `application/json` ้€ฒ่กŒ็ทจ็ขผใ€‚ + +้€™ไธๆ˜ฏ **FastAPI** ็š„้™ๅˆถ๏ผŒ้€™ๆ˜ฏ HTTP ้€š่จŠๅ”ๅฎšๆœฌ่บซ็š„่ฆ็ฏ„ใ€‚ + +/// + +## ๅฐ็ต { #recap } + +็•ถไฝ ้œ€่ฆๅœจๅŒไธ€ๅ€‹่ซ‹ๆฑ‚ไธญๅŒๆ™‚ๆŽฅๆ”ถ่ณ‡ๆ–™่ˆ‡ๆช”ๆกˆๆ™‚๏ผŒ่ซ‹ๆญ้…ไฝฟ็”จ `File` ่ˆ‡ `Form`ใ€‚ diff --git a/docs/zh-hant/docs/tutorial/request-forms.md b/docs/zh-hant/docs/tutorial/request-forms.md new file mode 100644 index 0000000000..733a3e2869 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/request-forms.md @@ -0,0 +1,73 @@ +# ่กจๅ–ฎ่ณ‡ๆ–™ { #form-data } + +็•ถไฝ ้œ€่ฆๆŽฅๆ”ถ่กจๅ–ฎๆฌ„ไฝ่€Œไธๆ˜ฏ JSON ๆ™‚๏ผŒๅฏไปฅไฝฟ็”จ `Form`ใ€‚ + +/// info + +่ฆไฝฟ็”จ่กจๅ–ฎ๏ผŒ่ซ‹ๅ…ˆๅฎ‰่ฃ `python-multipart`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅ†ๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install python-multipart +``` + +/// + +## ๅŒฏๅ…ฅ `Form` { #import-form } + +ๅพž `fastapi` ๅŒฏๅ…ฅ `Form`๏ผš + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} + +## ๅฎš็พฉ `Form` ๅƒๆ•ธ { #define-form-parameters } + +ไปฅ่ˆ‡ `Body` ๆˆ– `Query` ็›ธๅŒ็š„ๆ–นๅผๅปบ็ซ‹่กจๅ–ฎๅƒๆ•ธ๏ผš + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} + +ไพ‹ๅฆ‚๏ผŒๅœจ OAuth2 ่ฆ็ฏ„็š„ไธ€็จฎ็”จๆณ•๏ผˆ็จฑ็‚บใ€Œpassword flowใ€๏ผ‰ไธญ๏ผŒๅฟ…้ ˆไปฅ่กจๅ–ฎๆฌ„ไฝๅ‚ณ้€ `username` ่ˆ‡ `password`ใ€‚ + +่ฉฒ ่ฆ็ฏ„ ่ฆๆฑ‚ๆฌ„ไฝๅ็จฑๅฟ…้ ˆๆญฃๅฅฝๆ˜ฏ `username` ๅ’Œ `password`๏ผŒ่€Œไธ”ๅฟ…้ ˆไปฅ่กจๅ–ฎๆฌ„ไฝๅ‚ณ้€๏ผŒ่€Œไธๆ˜ฏ JSONใ€‚ + +ไฝฟ็”จ `Form` ๆ™‚๏ผŒไฝ ๅฏไปฅๅฎฃๅ‘Š่ˆ‡ `Body`๏ผˆไปฅๅŠ `Query`ใ€`Path`ใ€`Cookie`๏ผ‰็›ธๅŒ็š„่จญๅฎš๏ผŒๅŒ…ๆ‹ฌ้ฉ—่ญ‰ใ€็ฏ„ไพ‹ใ€ๅˆฅๅ๏ผˆไพ‹ๅฆ‚็”จ `user-name` ๅ–ไปฃ `username`๏ผ‰็ญ‰ใ€‚ + +/// info + +`Form` ๆ˜ฏไธ€ๅ€‹็›ดๆŽฅ็นผๆ‰ฟ่‡ช `Body` ็š„้กžๅˆฅใ€‚ + +/// + +/// tip + +่ฆๅฎฃๅ‘Š่กจๅ–ฎ็š„่ซ‹ๆฑ‚ๆœฌๆ–‡๏ผŒไฝ ้œ€่ฆๆ˜Ž็ขบไฝฟ็”จ `Form`๏ผŒๅฆๅ‰‡้€™ไบ›ๅƒๆ•ธๆœƒ่ขซ่งฃ่ฎ€็‚บๆŸฅ่ฉขๅƒๆ•ธๆˆ–่ซ‹ๆฑ‚ๆœฌๆ–‡๏ผˆJSON๏ผ‰ๅƒๆ•ธใ€‚ + +/// + +## ้—œๆ–ผใ€Œ่กจๅ–ฎๆฌ„ไฝใ€ { #about-form-fields } + +HTML ่กจๅ–ฎ๏ผˆ`
`๏ผ‰ๅ‘ไผบๆœๅ™จๅ‚ณ้€่ณ‡ๆ–™ๆ™‚๏ผŒ้€šๅธธๆœƒไฝฟ็”จไธ€็จฎใ€Œ็‰นๆฎŠใ€็š„็ทจ็ขผๆ–นๅผ๏ผŒ่ˆ‡ JSON ไธๅŒใ€‚ + +**FastAPI** ๆœƒๅพžๆญฃ็ขบ็š„ไฝ็ฝฎ่ฎ€ๅ–้‚ฃไบ›่ณ‡ๆ–™๏ผŒ่€Œไธๆ˜ฏๅพž JSONใ€‚ + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +่กจๅ–ฎ่ณ‡ๆ–™้€šๅธธๆœƒไฝฟ็”จใ€Œๅช’้ซ”้กžๅž‹ใ€`application/x-www-form-urlencoded` ้€ฒ่กŒ็ทจ็ขผใ€‚ + +ไฝ†็•ถ่กจๅ–ฎๅŒ…ๅซๆช”ๆกˆๆ™‚๏ผŒๆœƒไฝฟ็”จ `multipart/form-data`ใ€‚ไฝ ๆœƒๅœจไธ‹ไธ€็ซ ้–ฑ่ฎ€ๅฆ‚ไฝ•่™•็†ๆช”ๆกˆใ€‚ + +่‹ฅๆƒณ้€ฒไธ€ๆญฅไบ†่งฃ้€™ไบ›็ทจ็ขผ่ˆ‡่กจๅ–ฎๆฌ„ไฝ๏ผŒ่ซ‹ๅƒ่€ƒ MDN ็š„ POST ็ถฒ้ ๆ–‡ไปถใ€‚ + +/// + +/// warning + +ไฝ ๅฏไปฅๅœจไธ€ๅ€‹ *่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰* ไธญๅฎฃๅ‘Šๅคšๅ€‹ `Form` ๅƒๆ•ธ๏ผŒไฝ†ไธ่ƒฝๅŒๆ™‚ๅ†ๅฎฃๅ‘ŠๆœŸๆœ›ไปฅ JSON ๆŽฅๆ”ถ็š„ `Body` ๆฌ„ไฝ๏ผŒๅ› ็‚บ่ฉฒ่ซ‹ๆฑ‚็š„ๆœฌๆ–‡ๆœƒไฝฟ็”จ `application/x-www-form-urlencoded` ็ทจ็ขผ๏ผŒ่€Œไธๆ˜ฏ `application/json`ใ€‚ + +้€™ไธๆ˜ฏ **FastAPI** ็š„้™ๅˆถ๏ผŒ่€Œๆ˜ฏ HTTP ๅ”ๅฎšๆœฌ่บซ็š„่ฆๅฎšใ€‚ + +/// + +## ๅ›ž้กง { #recap } + +ไฝฟ็”จ `Form` ไพ†ๅฎฃๅ‘Š่กจๅ–ฎ่ณ‡ๆ–™็š„่ผธๅ…ฅๅƒๆ•ธใ€‚ diff --git a/docs/zh-hant/docs/tutorial/response-model.md b/docs/zh-hant/docs/tutorial/response-model.md new file mode 100644 index 0000000000..d22402e180 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/response-model.md @@ -0,0 +1,343 @@ +# ๅ›žๆ‡‰ๆจกๅž‹ - ๅ›žๅ‚ณๅž‹ๅˆฅ { #response-model-return-type } + +ไฝ ๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็š„ๅ›žๅ‚ณๅž‹ๅˆฅไธŠๅŠ ไธŠ่จป่งฃ๏ผŒๅฎฃๅ‘Š็”จๆ–ผๅ›žๆ‡‰็š„ๅž‹ๅˆฅใ€‚ + +ไฝ ๅฏไปฅๅƒๅœจๅ‡ฝๅผใ€Œๅƒๆ•ธใ€็š„่ผธๅ…ฅ่ณ‡ๆ–™้‚ฃๆจฃไฝฟ็”จๅž‹ๅˆฅ่จป่งฃ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ Pydantic ๆจกๅž‹ใ€listใ€dictionaryใ€ๆ•ดๆ•ธใ€ๅธƒๆž—็ญ‰็ด”้‡ๅ€ผใ€‚ + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI ๆœƒไฝฟ็”จ้€™ๅ€‹ๅ›žๅ‚ณๅž‹ๅˆฅไพ†๏ผš + +* ้ฉ—่ญ‰ๅ›žๅ‚ณ็š„่ณ‡ๆ–™ใ€‚ + * ๅฆ‚ๆžœ่ณ‡ๆ–™็„กๆ•ˆ๏ผˆไพ‹ๅฆ‚็ผบๅฐ‘ๆฌ„ไฝ๏ผ‰๏ผŒไปฃ่กจไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ็จ‹ๅผ็ขผๆœ‰ๅ•้กŒ๏ผŒๆฒ’ๆœ‰ๅ›žๅ‚ณๆ‡‰่ฉฒๅ›žๅ‚ณ็š„ๅ…งๅฎน๏ผŒFastAPI ๆœƒๅ›žๅ‚ณไผบๆœๅ™จ้Œฏ่ชค๏ผŒ่€Œไธๆ˜ฏๅ›žๅ‚ณไธๆญฃ็ขบ็š„่ณ‡ๆ–™ใ€‚ๅฆ‚ๆญคไฝ ๅ’Œไฝ ็š„็”จๆˆถ็ซฏ้ƒฝ่ƒฝ็ขบๅฎšๆœƒๆ”ถๅˆฐ้ ๆœŸ็š„่ณ‡ๆ–™่ˆ‡่ณ‡ๆ–™็ตๆง‹ใ€‚ +* ๅœจ OpenAPI ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธญ็‚บๅ›žๆ‡‰ๆ–ฐๅขž JSON Schemaใ€‚ + * ้€™ๆœƒ่ขซ่‡ชๅ‹•ๆ–‡ไปถไฝฟ็”จใ€‚ + * ไนŸๆœƒ่ขซ่‡ชๅ‹•็”จๆˆถ็ซฏ็จ‹ๅผ็ขผ็”ข็”Ÿๅทฅๅ…ทไฝฟ็”จใ€‚ + +ไฝ†ๆ›ด้‡่ฆ็š„ๆ˜ฏ๏ผš + +* ๅฎƒๆœƒๅฐ‡่ผธๅ‡บ่ณ‡ๆ–™้™ๅˆถไธฆ้Žๆฟพ็‚บๅ›žๅ‚ณๅž‹ๅˆฅไธญๅฎš็พฉ็š„ๅ…งๅฎนใ€‚ + * ้€™ๅฐๅฎ‰ๅ…จๆ€ง็‰นๅˆฅ้‡่ฆ๏ผŒไธ‹้ขๆœƒๅ†็œ‹ๅˆฐๆ›ดๅคš็ดฐ็ฏ€ใ€‚ + +## `response_model` ๅƒๆ•ธ { #response-model-parameter } + +ๆœ‰ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ้œ€่ฆๆˆ–ๆƒณ่ฆๅ›žๅ‚ณ็š„่ณ‡ๆ–™่ˆ‡ไฝ ๅฎฃๅ‘Š็š„ๅž‹ๅˆฅไธๅฎŒๅ…จ็›ธๅŒใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆๅ›žๅ‚ณไธ€ๅ€‹ dictionary ๆˆ–่ณ‡ๆ–™ๅบซ็‰ฉไปถ๏ผŒไฝ†ๆŠŠๅ›žๆ‡‰ๅฎฃๅ‘Š็‚บไธ€ๅ€‹ Pydantic ๆจกๅž‹ใ€‚้€™ๆจฃ Pydantic ๆจกๅž‹ๅฐฑๆœƒๆ›ฟไฝ ๅ›žๅ‚ณ็š„็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ dictionary ๆˆ–่ณ‡ๆ–™ๅบซ็‰ฉไปถ๏ผ‰่™•็†ๆ‰€ๆœ‰็š„่ณ‡ๆ–™ๆ–‡ไปถใ€้ฉ—่ญ‰็ญ‰ใ€‚ + +ๅฆ‚ๆžœไฝ ๅŠ ไบ†ๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ๏ผŒๅทฅๅ…ท่ˆ‡็ทจ่ผฏๅ™จๆœƒ๏ผˆๆญฃ็ขบๅœฐ๏ผ‰ๆŠฑๆ€จไฝ ็š„ๅ‡ฝๅผๅ›žๅ‚ณ็š„ๅž‹ๅˆฅ๏ผˆไพ‹ๅฆ‚ dict๏ผ‰่ˆ‡ไฝ ๅฎฃๅ‘Š็š„๏ผˆไพ‹ๅฆ‚ Pydantic ๆจกๅž‹๏ผ‰ไธๅŒใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅไฝฟ็”จใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ๅƒๆ•ธ `response_model`๏ผŒ่€Œไธๆ˜ฏๅ‡ฝๅผ็š„ๅ›žๅ‚ณๅž‹ๅˆฅใ€‚ + +ไฝ ๅฏไปฅๅœจไปปไฝ•ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธŠไฝฟ็”จ `response_model` ๅƒๆ•ธ๏ผš + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* ็ญ‰็ญ‰ใ€‚ + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | ๆณจๆ„ + +ๆณจๆ„ `response_model` ๆ˜ฏใ€Œ่ฃ้ฃพๅ™จใ€ๆ–นๆณ•๏ผˆ`get`ใ€`post` ็ญ‰๏ผ‰็š„ๅƒๆ•ธใ€‚ไธๆ˜ฏไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็š„ๅƒๆ•ธ๏ผˆๅƒๅ…ถไป–ๅƒๆ•ธ่ˆ‡่ซ‹ๆฑ‚ไธป้ซ”้‚ฃๆจฃ๏ผ‰ใ€‚ + +/// + +`response_model` ๆŽฅๅ—็š„ๅž‹ๅˆฅ่ˆ‡ไฝ ๅœจ Pydantic ๆจกๅž‹ๆฌ„ไฝไธญๅฎฃๅ‘Š็š„็›ธๅŒ๏ผŒๆ‰€ไปฅๅฎƒๅฏไปฅๆ˜ฏไธ€ๅ€‹ Pydantic ๆจกๅž‹๏ผŒไนŸๅฏไปฅๆ˜ฏไพ‹ๅฆ‚็”ฑ Pydantic ๆจกๅž‹็ต„ๆˆ็š„ `list`๏ผŒๅƒๆ˜ฏ `List[Item]`ใ€‚ + +FastAPI ๆœƒไฝฟ็”จ้€™ๅ€‹ `response_model` ไพ†ๅšๆ‰€ๆœ‰็š„่ณ‡ๆ–™ๆ–‡ไปถใ€้ฉ—่ญ‰็ญ‰๏ผŒไธฆไธ”ไนŸๆœƒๅฐ‡่ผธๅ‡บ่ณ‡ๆ–™่ฝ‰ๆ›่ˆ‡้Žๆฟพ็‚บๅ…ถๅž‹ๅˆฅๅฎฃๅ‘Šใ€‚ + +/// tip | ๆ็คบ + +ๅฆ‚ๆžœไฝ ๅœจ็ทจ่ผฏๅ™จใ€mypy ็ญ‰ไธญๆœ‰ๅšดๆ ผๅž‹ๅˆฅๆชขๆŸฅ๏ผŒไฝ ๅฏไปฅๆŠŠๅ‡ฝๅผๅ›žๅ‚ณๅž‹ๅˆฅๅฎฃๅ‘Š็‚บ `Any`ใ€‚ + +้€™ๆจฃไฝ ๆ˜ฏๅœจๅ‘Š่จด็ทจ่ผฏๅ™จไฝ ๆ˜ฏๅˆปๆ„ๅ›žๅ‚ณไปปๆ„ๅž‹ๅˆฅใ€‚ไฝ† FastAPI ไปๆœƒ็”จ `response_model` ๅš่ณ‡ๆ–™ๆ–‡ไปถใ€้ฉ—่ญ‰ใ€้Žๆฟพ็ญ‰ใ€‚ + +/// + +### `response_model` ๅ„ชๅ…ˆๆฌŠ { #response-model-priority } + +ๅฆ‚ๆžœๅŒๆ™‚ๅฎฃๅ‘Šไบ†ๅ›žๅ‚ณๅž‹ๅˆฅ่ˆ‡ `response_model`๏ผŒ`response_model` ๆœƒๆœ‰ๅ„ชๅ…ˆๆฌŠไธฆ็”ฑ FastAPI ไฝฟ็”จใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒๅณไพฟไฝ ๅ›žๅ‚ณ็š„ๅฏฆ้š›ๅž‹ๅˆฅ่ˆ‡ๅ›žๆ‡‰ๆจกๅž‹ไธๅŒ๏ผŒไฝ ไปๅฏๅœจๅ‡ฝๅผไธŠๅŠ ไธŠๆญฃ็ขบ็š„ๅž‹ๅˆฅ่จป่งฃ๏ผŒไพ›็ทจ่ผฏๅ™จ่ˆ‡ๅฆ‚ mypy ็š„ๅทฅๅ…ทไฝฟ็”จใ€‚ๅŒๆ™‚ไป็”ฑ FastAPI ไฝฟ็”จ `response_model` ๅš่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๆ–‡ไปถๅŒ–็ญ‰ใ€‚ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `response_model=None` ไพ†ๅœ็”จ่ฉฒใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„ๅ›žๆ‡‰ๆจกๅž‹็”ข็”Ÿ๏ผ›็•ถไฝ ็‚บไธๆ˜ฏๆœ‰ๆ•ˆ Pydantic ๆฌ„ไฝ็š„ๆฑ่ฅฟๅŠ ไธŠๅž‹ๅˆฅ่จป่งฃๆ™‚๏ผŒๅฏ่ƒฝ้œ€่ฆ้€™้บผๅš๏ผŒไฝ ๆœƒๅœจไธ‹ๆ–นๆŸ็ฏ€็œ‹ๅˆฐ็ฏ„ไพ‹ใ€‚ + +## ๅ›žๅ‚ณ่ˆ‡่ผธๅ…ฅ็›ธๅŒ็š„่ณ‡ๆ–™ { #return-the-same-input-data } + +้€™่ฃกๆˆ‘ๅ€‘ๅฎฃๅ‘Šไธ€ๅ€‹ `UserIn` ๆจกๅž‹๏ผŒๅ…ถไธญๆœƒๅŒ…ๅซๆ˜Žๆ–‡ๅฏ†็ขผ๏ผš + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// info | ่ชชๆ˜Ž + +่ฆไฝฟ็”จ `EmailStr`๏ผŒ่ซ‹ๅ…ˆๅฎ‰่ฃ `email-validator`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๅ•Ÿ็”จๅฎƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install email-validator +``` + +ๆˆ–๏ผš + +```console +$ pip install "pydantic[email]" +``` + +/// + +่€Œๆˆ‘ๅ€‘ไฝฟ็”จ้€™ๅ€‹ๆจกๅž‹ๅŒๆ™‚ๅฎฃๅ‘Š่ผธๅ…ฅ่ˆ‡่ผธๅ‡บ๏ผš + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +็พๅœจ๏ผŒ็•ถ็€่ฆฝๅ™จๅปบ็ซ‹ไธ€ๅ€‹ๅธถๆœ‰ๅฏ†็ขผ็š„ไฝฟ็”จ่€…ๆ™‚๏ผŒAPI ๆœƒๅœจๅ›žๆ‡‰ไธญๅ›žๅ‚ณ็›ธๅŒ็š„ๅฏ†็ขผใ€‚ + +ๅœจ้€™ๅ€‹ไพ‹ๅญไธญๅฏ่ƒฝไธๆ˜ฏๅ•้กŒ๏ผŒๅ› ็‚บๆ˜ฏๅŒไธ€ๅ€‹ไฝฟ็”จ่€…้€ๅ‡บ่ฉฒๅฏ†็ขผใ€‚ + +ไฝ†ๅฆ‚ๆžœๆˆ‘ๅ€‘ๅฐๅ…ถไป–ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไฝฟ็”จ็›ธๅŒ็š„ๆจกๅž‹๏ผŒๆˆ‘ๅ€‘ๅฏ่ƒฝๆœƒๆŠŠไฝฟ็”จ่€…ๅฏ†็ขผ้€็ตฆๆ‰€ๆœ‰็”จๆˆถ็ซฏใ€‚ + +/// danger | ่ญฆๅ‘Š + +้™ค้žไฝ ้žๅธธๆธ…ๆฅšๆ‰€ๆœ‰ๅฝฑ้Ÿฟไธฆ็ขบๅฎš่‡ชๅทฑๅœจๅšไป€้บผ๏ผŒๅฆๅ‰‡ๆฐธ้ ไธ่ฆๅ„ฒๅญ˜ไฝฟ็”จ่€…็š„ๆ˜Žๆ–‡ๅฏ†็ขผ๏ผŒไนŸไธ่ฆๅƒ้€™ๆจฃๅœจๅ›žๆ‡‰ไธญๅ‚ณ้€ใ€‚ + +/// + +## ๆ–ฐๅขžไธ€ๅ€‹่ผธๅ‡บๆจกๅž‹ { #add-an-output-model } + +ๆˆ‘ๅ€‘ๅฏไปฅๆ”น็‚บๅปบ็ซ‹ไธ€ๅ€‹ๅŒ…ๅซๆ˜Žๆ–‡ๅฏ†็ขผ็š„่ผธๅ…ฅๆจกๅž‹๏ผŒไปฅๅŠไธ€ๅ€‹ไธๅซๅฏ†็ขผ็š„่ผธๅ‡บๆจกๅž‹๏ผš + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +ๅœจ้€™่ฃก๏ผŒ้›–็„ถใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€ๅ›žๅ‚ณ็š„ๆ˜ฏๅŒไธ€ๅ€‹ๅŒ…ๅซๅฏ†็ขผ็š„่ผธๅ…ฅไฝฟ็”จ่€…๏ผš + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...ๆˆ‘ๅ€‘ๆŠŠ `response_model` ๅฎฃๅ‘Š็‚บไธๅŒ…ๅซๅฏ†็ขผ็š„ `UserOut` ๆจกๅž‹๏ผš + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +ๅ› ๆญค๏ผŒFastAPI ๆœƒ่ฒ ่ฒฌ๏ผˆ้€้Ž Pydantic๏ผ‰้Žๆฟพๆމ่ผธๅ‡บๆจกๅž‹ไธญๆœชๅฎฃๅ‘Š็š„ๆ‰€ๆœ‰่ณ‡ๆ–™ใ€‚ + +### `response_model` ๆˆ–ๅ›žๅ‚ณๅž‹ๅˆฅ { #response-model-or-return-type } + +ๅœจ้€™็จฎๆƒ…ๆณไธ‹๏ผŒๅ› ็‚บๅ…ฉๅ€‹ๆจกๅž‹ไธๅŒ๏ผŒๅฆ‚ๆžœๆˆ‘ๅ€‘ๆŠŠๅ‡ฝๅผๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ็‚บ `UserOut`๏ผŒ็ทจ่ผฏๅ™จๅ’Œๅทฅๅ…ทๆœƒๆŠฑๆ€จๆˆ‘ๅ€‘ๅ›žๅ‚ณไบ†็„กๆ•ˆ็š„ๅž‹ๅˆฅ๏ผŒๅ› ็‚บๅฎƒๅ€‘ๆ˜ฏไธๅŒ็š„้กžๅˆฅใ€‚ + +้€™ๅฐฑๆ˜ฏ็‚บไป€้บผๅœจ้€™ๅ€‹ไพ‹ๅญไธญๆˆ‘ๅ€‘ๅฟ…้ ˆๅœจ `response_model` ๅƒๆ•ธไธญๅฎฃๅ‘Šๅฎƒใ€‚ + +...ไฝ†็นผ็บŒๅพ€ไธ‹่ฎ€็œ‹็œ‹ๅฆ‚ไฝ•ๅ…‹ๆœ้€™ๅ€‹ๅ•้กŒใ€‚ + +## ๅ›žๅ‚ณๅž‹ๅˆฅ่ˆ‡่ณ‡ๆ–™้Žๆฟพ { #return-type-and-data-filtering } + +่ฎ“ๆˆ‘ๅ€‘ๅปถ็บŒๅ‰ไธ€ๅ€‹็ฏ„ไพ‹ใ€‚ๆˆ‘ๅ€‘ๆƒณ่ฆ็”จไธ€็จฎๅž‹ๅˆฅไพ†่จป่งฃๅ‡ฝๅผ๏ผŒไฝ†ๅฏฆ้š›ไธŠๅธŒๆœ›่ƒฝๅค ๅพžๅ‡ฝๅผๅ›žๅ‚ณๅŒ…ๅซๆ›ดๅคš่ณ‡ๆ–™็š„ๅ…งๅฎนใ€‚ + +ๆˆ‘ๅ€‘ๅธŒๆœ› FastAPI ไป็„ถ็”จๅ›žๆ‡‰ๆจกๅž‹ไพ†้Žๆฟพ่ณ‡ๆ–™ใ€‚้€™ๆจฃๅณไฝฟๅ‡ฝๅผๅ›žๅ‚ณๆ›ดๅคš่ณ‡ๆ–™๏ผŒๅ›žๆ‡‰ไธญไนŸๅชๆœƒๅŒ…ๅซๅ›žๆ‡‰ๆจกๅž‹ไธญๅฎฃๅ‘Š็š„ๆฌ„ไฝใ€‚ + +ๅœจๅ‰ไธ€ๅ€‹ไพ‹ๅญไธญ๏ผŒๅ› ็‚บ้กžๅˆฅไธๅŒ๏ผŒๆˆ‘ๅ€‘ๅฟ…้ ˆไฝฟ็”จ `response_model` ๅƒๆ•ธใ€‚ไฝ†้€™ไนŸไปฃ่กจๆˆ‘ๅ€‘ๅคฑๅŽปไบ†็ทจ่ผฏๅ™จ่ˆ‡ๅทฅๅ…ทๅฐๅ‡ฝๅผๅ›žๅ‚ณๅž‹ๅˆฅ็š„ๆชขๆŸฅๆ”ฏๆดใ€‚ + +ไธ้Žๅœจๅคงๅคšๆ•ธ้œ€่ฆ้€™ๆจฃๅš็š„ๆƒ…ๆณไธ‹๏ผŒๆˆ‘ๅ€‘ๅชๆ˜ฏๆƒณ่ฆๅƒ้€™ๅ€‹ไพ‹ๅญไธ€ๆจฃ๏ผŒ่ฎ“ๆจกๅž‹้Žๆฟพ/็งป้™ค้ƒจๅˆ†่ณ‡ๆ–™ใ€‚ + +ๅœจ้€™ไบ›ๆƒ…ๆณไธ‹๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅˆฉ็”จ้กžๅˆฅ่ˆ‡็นผๆ‰ฟ๏ผŒๆญ้…ๅ‡ฝๅผ็š„ๅž‹ๅˆฅ่จป่งฃ๏ผŒๅ–ๅพ—ๆ›ดๅฅฝ็š„็ทจ่ผฏๅ™จ่ˆ‡ๅทฅๅ…ทๆ”ฏๆด๏ผŒๅŒๆ™‚ไป่ƒฝ่ฎ“ FastAPI ๅš่ณ‡ๆ–™้Žๆฟพใ€‚ + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +้€™ๆจฃๆˆ‘ๅ€‘่ƒฝๅพ—ๅˆฐๅทฅๅ…ทๆ”ฏๆด๏ผŒๅฐๆ–ผ็ทจ่ผฏๅ™จ่ˆ‡ mypy ไพ†่ชช๏ผŒ้€™ๆฎต็จ‹ๅผ็ขผๅœจๅž‹ๅˆฅไธŠๆ˜ฏๆญฃ็ขบ็š„๏ผŒๅŒๆ™‚ๆˆ‘ๅ€‘ไนŸ่ƒฝๅพ—ๅˆฐ FastAPI ็š„่ณ‡ๆ–™้Žๆฟพใ€‚ + +้€™ๆ˜ฏๆ€Ž้บผ้‹ไฝœ็š„๏ผŸไพ†็œ‹ไธ€ไธ‹ใ€‚๐Ÿค“ + +### ๅž‹ๅˆฅ่จป่งฃ่ˆ‡ๅทฅๅ…ทๆ”ฏๆด { #type-annotations-and-tooling } + +ๅ…ˆ็œ‹็œ‹็ทจ่ผฏๅ™จใ€mypy ่ˆ‡ๅ…ถไป–ๅทฅๅ…ทๆœƒๆ€Ž้บผ็œ‹้€™ไปถไบ‹ใ€‚ + +`BaseUser` ๆœ‰ๅŸบ็คŽๆฌ„ไฝใ€‚็„ถๅพŒ `UserIn` ็นผๆ‰ฟ่‡ช `BaseUser` ไธฆๆ–ฐๅขž `password` ๆฌ„ไฝ๏ผŒๅ› ๆญคๅฎƒๆœƒๅŒ…ๅซๅ…ฉๅ€‹ๆจกๅž‹็š„ๆ‰€ๆœ‰ๆฌ„ไฝใ€‚ + +ๆˆ‘ๅ€‘ๆŠŠๅ‡ฝๅผๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ็‚บ `BaseUser`๏ผŒไฝ†ๅฏฆ้š›ไธŠๅ›žๅ‚ณ็š„ๆ˜ฏ `UserIn` ๅฏฆไพ‹ใ€‚ + +็ทจ่ผฏๅ™จใ€mypy ่ˆ‡ๅ…ถไป–ๅทฅๅ…ทไธๆœƒๆŠฑๆ€จ๏ผŒๅ› ็‚บๅฐฑๅž‹ๅˆฅๅญธ่€Œ่จ€๏ผŒ`UserIn` ๆ˜ฏ `BaseUser` ็š„ๅญ้กžๅˆฅ๏ผŒ้€™ไปฃ่กจ็•ถ้ ๆœŸไปปไฝ• `BaseUser` ๆ™‚๏ผŒ`UserIn` ๆ˜ฏไธ€ๅ€‹ๆœ‰ๆ•ˆ็š„ๅž‹ๅˆฅใ€‚ + +### FastAPI ็š„่ณ‡ๆ–™้Žๆฟพ { #fastapi-data-filtering } + +ๅฐ FastAPI ่€Œ่จ€๏ผŒๅฎƒๆœƒๆŸฅ็œ‹ๅ›žๅ‚ณๅž‹ๅˆฅ๏ผŒไธฆ็ขบไฟไฝ ๅ›žๅ‚ณ็š„ๅ…งๅฎนๅชๅŒ…ๅซ่ฉฒๅž‹ๅˆฅไธญๅฎฃๅ‘Š็š„ๆฌ„ไฝใ€‚ + +FastAPI ๅœจๅ…ง้ƒจๆœƒๆญ้… Pydantic ๅšไธ€ไบ›ไบ‹ๆƒ…๏ผŒไพ†็ขบไฟไธๆœƒๆŠŠ้กžๅˆฅ็นผๆ‰ฟ็š„้‚ฃไบ›่ฆๅ‰‡็›ดๆŽฅ็”จๅœจๅ›žๅ‚ณ่ณ‡ๆ–™็š„้ŽๆฟพไธŠ๏ผŒๅฆๅ‰‡ไฝ ๅฏ่ƒฝๆœƒๅ›žๅ‚ณๆฏ”้ ๆœŸๆ›ดๅคš็š„่ณ‡ๆ–™ใ€‚ + +ๅฆ‚ๆญค๏ผŒไฝ ๅฐฑ่ƒฝๅŒๆ™‚ๆ“ๆœ‰ๅ…ฉ็จฎๅฅฝ่™•๏ผšๅ…ทๅ‚™ๅทฅๅ…ทๆ”ฏๆด็š„ๅž‹ๅˆฅ่จป่งฃ๏ผŒไปฅๅŠ่ณ‡ๆ–™้Žๆฟพใ€‚ + +## ๅœจๆ–‡ไปถไธญๆŸฅ็œ‹ { #see-it-in-the-docs } + +ๅœจ่‡ชๅ‹•ๆ–‡ไปถไธญ๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐ่ผธๅ…ฅๆจกๅž‹่ˆ‡่ผธๅ‡บๆจกๅž‹ๅ„่‡ช้ƒฝๆœ‰่‡ชๅทฑ็š„ JSON Schema๏ผš + + + +่€Œไธ”ๅ…ฉๅ€‹ๆจกๅž‹้ƒฝๆœƒ็”จๅœจไบ’ๅ‹•ๅผ API ๆ–‡ไปถไธญ๏ผš + + + +## ๅ…ถไป–ๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ { #other-return-type-annotations } + +ๆœ‰ๆ™‚ไฝ ๅ›žๅ‚ณ็š„ๆฑ่ฅฟไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ๆฌ„ไฝ๏ผŒไฝ ไปๆœƒๅœจๅ‡ฝๅผไธŠๅŠ ไธŠ่จป่งฃ๏ผŒๅช็‚บไบ†็ฒๅพ—ๅทฅๅ…ท๏ผˆ็ทจ่ผฏๅ™จใ€mypy ็ญ‰๏ผ‰ๆไพ›็š„ๆ”ฏๆดใ€‚ + +### ็›ดๆŽฅๅ›žๅ‚ณ Response { #return-a-response-directly } + +ๆœ€ๅธธ่ฆ‹็š„ๆƒ…ๆณๆ˜ฏ[็›ดๆŽฅๅ›žๅ‚ณ Response๏ผˆๅœจ้€ฒ้šŽๆ–‡ไปถไธญ็จๅพŒๆœƒ่งฃ้‡‹๏ผ‰](../advanced/response-directly.md){.internal-link target=_blank}ใ€‚ + +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} + +้€™ๅ€‹็ฐกๅ–ฎๆƒ…ๅขƒๆœƒ็”ฑ FastAPI ่‡ชๅ‹•่™•็†๏ผŒๅ› ็‚บๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃๆ˜ฏ `Response` ้กžๅˆฅ๏ผˆๆˆ–ๅ…ถๅญ้กžๅˆฅ๏ผ‰ใ€‚ + +่€Œๅทฅๅ…ทไนŸๆœƒๆปฟๆ„๏ผŒๅ› ็‚บ `RedirectResponse` ่ˆ‡ `JSONResponse` ้ƒฝๆ˜ฏ `Response` ็š„ๅญ้กžๅˆฅ๏ผŒๆ‰€ไปฅๅž‹ๅˆฅ่จป่งฃๆ˜ฏๆญฃ็ขบ็š„ใ€‚ + +### ่จป่งฃ็‚บๆŸๅ€‹ Response ็š„ๅญ้กžๅˆฅ { #annotate-a-response-subclass } + +ไฝ ไนŸๅฏไปฅๅœจๅž‹ๅˆฅ่จป่งฃไธญไฝฟ็”จ `Response` ็š„ๅญ้กžๅˆฅ๏ผš + +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} + +้€™ๅŒๆจฃๅฏ่กŒ๏ผŒๅ› ็‚บ `RedirectResponse` ๆ˜ฏ `Response` ็š„ๅญ้กžๅˆฅ๏ผŒ่€Œ FastAPI ๆœƒ่‡ชๅ‹•่™•็†้€™็จฎ็ฐกๅ–ฎๆƒ…ๆณใ€‚ + +### ็„กๆ•ˆ็š„ๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ { #invalid-return-type-annotations } + +ไฝ†็•ถไฝ ๅ›žๅ‚ณๅ…ถไป–ไปปๆ„็‰ฉไปถ๏ผˆไพ‹ๅฆ‚่ณ‡ๆ–™ๅบซ็‰ฉไปถ๏ผ‰๏ผŒๅฎƒไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ๅž‹ๅˆฅ๏ผŒไธฆไธ”ไฝ ๅœจๅ‡ฝๅผไธŠไนŸ้€™ๆจฃ่จป่งฃๆ™‚๏ผŒFastAPI ๆœƒๅ˜—่ฉฆๅพž่ฉฒๅž‹ๅˆฅ่จป่งฃๅปบ็ซ‹ไธ€ๅ€‹ Pydantic ๅ›žๆ‡‰ๆจกๅž‹๏ผŒๅ› ่€Œๅคฑๆ•—ใ€‚ + +ๅฆ‚ๆžœไฝ ๆœ‰ๅƒๆ˜ฏๅคš็จฎๅž‹ๅˆฅ็š„่ฏ้›†๏ผŒๅ…ถไธญไธ€ๅ€‹ๆˆ–ๅคšๅ€‹ไธๆ˜ฏๆœ‰ๆ•ˆ็š„ Pydantic ๅž‹ๅˆฅ๏ผŒไนŸๆœƒ็™ผ็”Ÿ็›ธๅŒ็š„ไบ‹ๆƒ…๏ผŒไพ‹ๅฆ‚้€™ๅ€‹ๅฐฑๆœƒๅคฑๆ•— ๐Ÿ’ฅ๏ผš + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...้€™ๆœƒๅคฑๆ•—๏ผŒๅ› ็‚บ่ฉฒๅž‹ๅˆฅ่จป่งฃไธๆ˜ฏ Pydantic ๅž‹ๅˆฅ๏ผŒไธ”ๅฎƒไนŸไธๅชๆ˜ฏไธ€ๅ€‹ๅ–ฎไธ€็š„ `Response` ้กžๅˆฅๆˆ–ๅ…ถๅญ้กžๅˆฅ๏ผŒ่€Œๆ˜ฏ `Response` ่ˆ‡ `dict` ็š„่ฏ้›†๏ผˆๅ…ฉ่€…ไปปไธ€๏ผ‰ใ€‚ + +### ๅœ็”จๅ›žๆ‡‰ๆจกๅž‹ { #disable-response-model } + +ๅปถ็บŒไธŠ้ข็š„ไพ‹ๅญ๏ผŒไฝ ๅฏ่ƒฝไธๆƒณ่ฆ FastAPI ๅŸท่กŒ้ ่จญ็š„่ณ‡ๆ–™้ฉ—่ญ‰ใ€ๆ–‡ไปถๅŒ–ใ€้Žๆฟพ็ญ‰ๅ‹•ไฝœใ€‚ + +ไฝ†ไฝ ๅฏ่ƒฝไปๆƒณๅœจๅ‡ฝๅผไธŠไฟ็•™ๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ๏ผŒไปฅ็ฒๅพ—็ทจ่ผฏๅ™จ่ˆ‡ๅž‹ๅˆฅๆชขๆŸฅๅทฅๅ…ท๏ผˆไพ‹ๅฆ‚ mypy๏ผ‰็š„ๆ”ฏๆดใ€‚ + +้€™็จฎๆƒ…ๆณไธ‹๏ผŒไฝ ๅฏไปฅ่จญๅฎš `response_model=None` ไพ†ๅœ็”จๅ›žๆ‡‰ๆจกๅž‹็š„็”ข็”Ÿ๏ผš + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +้€™ๆœƒ่ฎ“ FastAPI ็•ฅ้Žๅ›žๆ‡‰ๆจกๅž‹็š„็”ข็”Ÿ๏ผŒๅฆ‚ๆญคไฝ ๅฐฑ่ƒฝไฝฟ็”จไปปไฝ•ไฝ ้œ€่ฆ็š„ๅ›žๅ‚ณๅž‹ๅˆฅ่จป่งฃ๏ผŒ่€Œไธๆœƒๅฝฑ้Ÿฟไฝ ็š„ FastAPI ๆ‡‰็”จ็จ‹ๅผใ€‚๐Ÿค“ + +## ๅ›žๆ‡‰ๆจกๅž‹็ทจ็ขผๅƒๆ•ธ { #response-model-encoding-parameters } + +ไฝ ็š„ๅ›žๆ‡‰ๆจกๅž‹ๅฏ่ƒฝๆœ‰้ ่จญๅ€ผ๏ผŒไพ‹ๅฆ‚๏ผš + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None`๏ผˆๆˆ–ๅœจ Python 3.10 ไธญ็š„ `str | None = None`๏ผ‰้ ่จญ็‚บ `None`ใ€‚ +* `tax: float = 10.5` ้ ่จญ็‚บ `10.5`ใ€‚ +* `tags: List[str] = []` ้ ่จญ็‚บ็ฉบ็š„ list๏ผš`[]`ใ€‚ + +ไฝ†ๅฆ‚ๆžœ้€™ไบ›ๅ€ผๅ…ถๅฏฆๆฒ’ๆœ‰่ขซๅ„ฒๅญ˜๏ผŒไฝ ๅฏ่ƒฝๆƒณ่ฆๅœจ็ตๆžœไธญ็œ็•ฅๅฎƒๅ€‘ใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅœจ NoSQL ่ณ‡ๆ–™ๅบซไธญๆœ‰ๅŒ…ๅซ่จฑๅคš้ธๆ“‡ๆ€งๅฑฌๆ€ง็š„ๆจกๅž‹๏ผŒไฝ†ไฝ ไธๆƒณๅ‚ณ้€ๅ……ๆปฟ้ ่จญๅ€ผ็š„ๅ†—้•ท JSON ๅ›žๆ‡‰ใ€‚ + +### ไฝฟ็”จ `response_model_exclude_unset` ๅƒๆ•ธ { #use-the-response-model-exclude-unset-parameter } + +ไฝ ๅฏไปฅๅœจใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ไธŠ่จญๅฎš `response_model_exclude_unset=True`๏ผš + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +ๅฆ‚ๆญค้€™ไบ›้ ่จญๅ€ผๅฐฑไธๆœƒ่ขซๅŒ…ๅซๅœจๅ›žๆ‡‰ไธญ๏ผŒๅชๆœ‰ๅฏฆ้š›่ขซ่จญๅฎš็š„ๅ€ผๆ‰ๆœƒๅŒ…ๅซใ€‚ + +ๅ› ๆญค๏ผŒๅฆ‚ๆžœไฝ ๅฐ่ฉฒใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็™ผ้€้‡ๅฐ ID ็‚บ `foo` ็š„้ …็›ฎ็š„่ซ‹ๆฑ‚๏ผŒๅ›žๆ‡‰๏ผˆไธๅŒ…ๅซ้ ่จญๅ€ผ๏ผ‰ๆœƒๆ˜ฏ๏ผš + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// info | ่ชชๆ˜Ž + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ๏ผš + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +ๅฆ‚ Pydantic ๆ–‡ไปถไธญๅฐ `exclude_defaults` ่ˆ‡ `exclude_none` ็š„่ชชๆ˜Žใ€‚ + +/// + +#### ๅฐๆ–ผๆœ‰้ ่จญๅ€ผๆฌ„ไฝไนŸๆœ‰ๅฏฆ้š›ๅ€ผ็š„่ณ‡ๆ–™ { #data-with-values-for-fields-with-defaults } + +ไฝ†ๅฆ‚ๆžœไฝ ็š„่ณ‡ๆ–™ๅœจๆจกๅž‹ไธญๅฐๆ–ผๆœ‰้ ่จญๅ€ผ็š„ๆฌ„ไฝไนŸๆœ‰ๅฏฆ้š›ๅ€ผ๏ผŒไพ‹ๅฆ‚ ID ็‚บ `bar` ็š„้ …็›ฎ๏ผš + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` + +ๅฎƒๅ€‘ๆœƒ่ขซๅŒ…ๅซๅœจๅ›žๆ‡‰ไธญใ€‚ + +#### ่ˆ‡้ ่จญๅ€ผ็›ธๅŒ็š„่ณ‡ๆ–™ { #data-with-the-same-values-as-the-defaults } + +ๅฆ‚ๆžœ่ณ‡ๆ–™็š„ๅ€ผ่ˆ‡้ ่จญๅ€ผ็›ธๅŒ๏ผŒไพ‹ๅฆ‚ ID ็‚บ `baz` ็š„้ …็›ฎ๏ผš + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI ่ถณๅค ่ฐๆ˜Ž๏ผˆๅ…ถๅฏฆๆ˜ฏ Pydantic ่ถณๅค ่ฐๆ˜Ž๏ผ‰ๅŽปๅˆคๆ–ท๏ผŒๅ„˜็ฎก `description`ใ€`tax` ่ˆ‡ `tags` ็š„ๅ€ผ่ˆ‡้ ่จญๅ€ผ็›ธๅŒ๏ผŒไฝ†ๅฎƒๅ€‘ๆ˜ฏ่ขซๆ˜Ž็ขบ่จญๅฎš็š„๏ผˆ่€Œไธๆ˜ฏๅ–่‡ช้ ่จญๅ€ผ๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒๅฎƒๅ€‘ๆœƒ่ขซๅŒ…ๅซๅœจ JSON ๅ›žๆ‡‰ไธญใ€‚ + +/// tip | ๆ็คบ + +ๆณจๆ„้ ่จญๅ€ผๅฏไปฅๆ˜ฏไปปไฝ•ๆฑ่ฅฟ๏ผŒไธๅชๆœ‰ `None`ใ€‚ + +ๅฎƒๅ€‘ๅฏไปฅๆ˜ฏไธ€ๅ€‹ list๏ผˆ`[]`๏ผ‰ใ€ไธ€ๅ€‹ `float` ็š„ `10.5`๏ผŒ็ญ‰็ญ‰ใ€‚ + +/// + +### `response_model_include` ่ˆ‡ `response_model_exclude` { #response-model-include-and-response-model-exclude } + +ไฝ ไนŸๅฏไปฅไฝฟ็”จใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€ๅƒๆ•ธ `response_model_include` ่ˆ‡ `response_model_exclude`ใ€‚ + +ๅฎƒๅ€‘ๆŽฅๅ—ไธ€ๅ€‹็”ฑๅฑฌๆ€งๅ็จฑๅญ—ไธฒๆ‰€็ต„ๆˆ็š„ `set`๏ผŒๅˆ†ๅˆฅ็”จไพ†ๅŒ…ๅซ๏ผˆ็œ็•ฅๅ…ถไป–๏ผ‰ๆˆ–ๆŽ’้™ค๏ผˆๅŒ…ๅซๅ…ถไป–๏ผ‰ๅฑฌๆ€งใ€‚ + +ๅฆ‚ๆžœไฝ ๅชๆœ‰ไธ€ๅ€‹ Pydantic ๆจกๅž‹ไธฆไธ”ๆƒณๅพž่ผธๅ‡บ็งป้™ค้ƒจๅˆ†่ณ‡ๆ–™๏ผŒ้€™ๅฏไปฅไฝœ็‚บไธ€ๅ€‹ๅฟซ้€Ÿๆทๅพ‘ใ€‚ + +/// tip | ๆ็คบ + +ไฝ†ไปๅปบ่ญฐไฝฟ็”จไธŠ้ขๆๅˆฐ็š„ไฝœๆณ•๏ผŒไฝฟ็”จๅคšๅ€‹้กžๅˆฅ๏ผŒ่€Œไธๆ˜ฏ้€™ไบ›ๅƒๆ•ธใ€‚ + +ๅ› ็‚บๅœจไฝ ็š„ๆ‡‰็”จ็จ‹ๅผ OpenAPI๏ผˆ่ˆ‡ๆ–‡ไปถ๏ผ‰ไธญๆ‰€็”ข็”Ÿ็š„ JSON Schema ไปๆœƒๆ˜ฏๅฎŒๆ•ดๆจกๅž‹็š„๏ผŒๅณไพฟไฝ ไฝฟ็”จ `response_model_include` ๆˆ– `response_model_exclude` ็œ็•ฅไบ†ไธ€ไบ›ๅฑฌๆ€งใ€‚ + +`response_model_by_alias` ไนŸๆœ‰้กžไผผ็š„ๆƒ…ๆณใ€‚ + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | ๆ็คบ + +่ชžๆณ• `{"name", "description"}` ๆœƒๅปบ็ซ‹ไธ€ๅ€‹ๅŒ…ๅซ้€™ๅ…ฉๅ€‹ๅ€ผ็š„ `set`ใ€‚ + +ๅฎƒ็ญ‰ๅŒๆ–ผ `set(["name", "description"])`ใ€‚ + +/// + +#### ไฝฟ็”จ `list` ไพ†ไปฃๆ›ฟ `set` { #using-lists-instead-of-sets } + +ๅฆ‚ๆžœไฝ ๅฟ˜ไบ†ไฝฟ็”จ `set` ่€Œ็”จไบ† `list` ๆˆ– `tuple`๏ผŒFastAPI ไปๆœƒๆŠŠๅฎƒ่ฝ‰ๆ›ๆˆ `set`๏ผŒไธฆ่ƒฝๆญฃ็ขบ้‹ไฝœ๏ผš + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## ้‡้ปžๅ›ž้กง { #recap } + +ไฝฟ็”จใ€Œ่ทฏๅพ‘ๆ“ไฝœ่ฃ้ฃพๅ™จใ€็š„ `response_model` ๅƒๆ•ธไพ†ๅฎš็พฉๅ›žๆ‡‰ๆจกๅž‹๏ผŒ็‰นๅˆฅๆ˜ฏ็‚บไบ†็ขบไฟ็งๆœ‰่ณ‡ๆ–™่ขซ้Žๆฟพๆމใ€‚ + +ไฝฟ็”จ `response_model_exclude_unset` ๅƒ…ๅ›žๅ‚ณ่ขซๆ˜Ž็ขบ่จญๅฎš็š„ๅ€ผใ€‚ diff --git a/docs/zh-hant/docs/tutorial/response-status-code.md b/docs/zh-hant/docs/tutorial/response-status-code.md new file mode 100644 index 0000000000..cbcc67ca55 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/response-status-code.md @@ -0,0 +1,101 @@ +# ๅ›žๆ‡‰็‹€ๆ…‹็ขผ { #response-status-code } + +ๅฐฑๅƒไฝ ๅฏไปฅๆŒ‡ๅฎšๅ›žๆ‡‰ๆจกๅž‹ไธ€ๆจฃ๏ผŒไฝ ไนŸๅฏไปฅๅœจไปปไธ€ๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰ใ€็š„ๅƒๆ•ธ `status_code` ไธญๅฎฃๅ‘Šๅ›žๆ‡‰ๆ‰€ไฝฟ็”จ็š„ HTTP ็‹€ๆ…‹็ขผ๏ผš + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* ็ญ‰็ญ‰ + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +/// note | ๆณจๆ„ + +่ซ‹ๆณจๆ„๏ผŒ`status_code` ๆ˜ฏใ€Œ่ฃ้ฃพๅ™จ๏ผˆdecorator๏ผ‰ใ€ๆ–นๆณ•๏ผˆ`get`ใ€`post` ็ญ‰็ญ‰๏ผ‰็š„ๅƒๆ•ธ๏ผŒ่€Œไธๆ˜ฏไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็š„ๅƒๆ•ธ๏ผŒๅฐฑๅƒๆ‰€ๆœ‰็š„ๅƒๆ•ธ่ˆ‡ body ไธ€ๆจฃใ€‚ + +/// + +ๅƒๆ•ธ `status_code` ๆŽฅๅ—ไธ€ๅ€‹ๆ•ธๅญ—ไฝœ็‚บ HTTP ็‹€ๆ…‹็ขผใ€‚ + +/// info | ่ณ‡่จŠ + +`status_code` ไนŸๅฏไปฅๆŽฅๆ”ถไธ€ๅ€‹ `IntEnum`๏ผŒไพ‹ๅฆ‚ Python ็š„ `http.HTTPStatus`ใ€‚ + +/// + +ๅฎƒๆœƒ๏ผš + +* ๅœจๅ›žๆ‡‰ไธญๅ‚ณๅ›ž่ฉฒ็‹€ๆ…‹็ขผใ€‚ +* ๅœจ OpenAPI ็ตๆง‹ไธญๅฆ‚ๆญค่จ˜้Œ„๏ผˆๅ› ๆญคไนŸๆœƒๅๆ˜ ๅœจไฝฟ็”จ่€…ไป‹้ขไธญ๏ผ‰๏ผš + + + +/// note | ๆณจๆ„ + +ๆœ‰ไบ›ๅ›žๆ‡‰็ขผ๏ผˆ่ฆ‹ไธ‹ไธ€็ฏ€๏ผ‰่กจ็คบๅ›žๆ‡‰ไธๅŒ…ๅซๆœฌๆ–‡๏ผˆbody๏ผ‰ใ€‚ + +FastAPI ็Ÿฅ้“้€™้ปž๏ผŒไธฆๆœƒ็”ข็”Ÿ่ฒๆ˜Žใ€Œ็„กๅ›žๆ‡‰ๆœฌๆ–‡ใ€็š„ OpenAPI ๆ–‡ไปถใ€‚ + +/// + +## ้—œๆ–ผ HTTP ็‹€ๆ…‹็ขผ { #about-http-status-codes } + +/// note | ๆณจๆ„ + +ๅฆ‚ๆžœไฝ ๅทฒ็ถ“็Ÿฅ้“ไป€้บผๆ˜ฏ HTTP ็‹€ๆ…‹็ขผ๏ผŒๅฏไปฅ็›ดๆŽฅ่ทณๅˆฐไธ‹ไธ€็ฏ€ใ€‚ + +/// + +ๅœจ HTTP ไธญ๏ผŒไฝ ๆœƒๅœจๅ›žๆ‡‰็š„ไธ€้ƒจๅˆ†ๅ‚ณๅ›ž 3 ไฝๆ•ธ็š„็‹€ๆ…‹็ขผใ€‚ + +้€™ไบ›็‹€ๆ…‹็ขผๆœ‰ๅฐๆ‡‰็š„ๅ็จฑไปฅไพฟ่พจ่ญ˜๏ผŒไฝ†้‡้ปžๆ˜ฏๆ•ธๅญ—ๆœฌ่บซใ€‚ + +็ฐก่€Œ่จ€ไน‹๏ผš + +* `100 - 199` ่กจ็คบใ€Œ่ณ‡่จŠใ€ใ€‚ไฝ ๅพˆๅฐ‘ๆœƒ็›ดๆŽฅไฝฟ็”จๅฎƒๅ€‘ใ€‚้€™ไบ›็‹€ๆ…‹็ขผ็š„ๅ›žๆ‡‰ไธๅฏๅŒ…ๅซๆœฌๆ–‡ใ€‚ +* **`200 - 299`** ่กจ็คบใ€ŒๆˆๅŠŸใ€ใ€‚้€™ๆ˜ฏไฝ ๆœ€ๅธธไฝฟ็”จ็š„ไธ€็ต„ใ€‚ + * `200` ๆ˜ฏ้ ่จญ็‹€ๆ…‹็ขผ๏ผŒ่กจ็คบไธ€ๅˆ‡ใ€ŒOKใ€ใ€‚ + * ๅฆไธ€ๅ€‹ไพ‹ๅญๆ˜ฏ `201`๏ผŒไปฃ่กจใ€Œๅทฒๅปบ็ซ‹ใ€ใ€‚ๅธธ็”จๆ–ผๅœจ่ณ‡ๆ–™ๅบซไธญๅปบ็ซ‹ๆ–ฐ็ด€้Œ„ไน‹ๅพŒใ€‚ + * ไธ€ๅ€‹็‰นๆฎŠๆƒ…ๆณๆ˜ฏ `204`๏ผŒไปฃ่กจใ€Œ็„กๅ…งๅฎนใ€ใ€‚็•ถๆฒ’ๆœ‰ๅ…งๅฎน่ฆๅ›žๅ‚ณ็ตฆ็”จๆˆถ็ซฏๆ™‚ไฝฟ็”จ๏ผŒๅ› ๆญคๅ›žๆ‡‰ไธๅพ—ๆœ‰ๆœฌๆ–‡ใ€‚ +* **`300 - 399`** ่กจ็คบใ€Œ้‡ๆ–ฐๅฐŽๅ‘ใ€ใ€‚้€™ไบ›็‹€ๆ…‹็ขผ็š„ๅ›žๆ‡‰ๅฏ่ƒฝๆœ‰ๆˆ–ๆฒ’ๆœ‰ๆœฌๆ–‡๏ผŒๅ”ฏ็จ `304`๏ผˆใ€Œๆœชไฟฎๆ”นใ€๏ผ‰ๅฟ…้ ˆๆฒ’ๆœ‰ๆœฌๆ–‡ใ€‚ +* **`400 - 499`** ่กจ็คบใ€Œ็”จๆˆถ็ซฏ้Œฏ่ชคใ€ใ€‚้€™ๅคงๆฆ‚ๆ˜ฏไฝ ็ฌฌไบŒๅธธ็”จ็š„ไธ€็ต„ใ€‚ + * ไพ‹ๅฆ‚ `404`๏ผŒไปฃ่กจใ€Œๆ‰พไธๅˆฐใ€ใ€‚ + * ๅฐๆ–ผไธ€่ˆฌๆ€ง็š„็”จๆˆถ็ซฏ้Œฏ่ชค๏ผŒไฝ ๅฏไปฅไฝฟ็”จ `400`ใ€‚ +* `500 - 599` ่กจ็คบไผบๆœๅ™จ้Œฏ่ชคใ€‚ไฝ ๅนพไนŽไธๆœƒ็›ดๆŽฅไฝฟ็”จๅฎƒๅ€‘ใ€‚็•ถไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๆˆ–ไผบๆœๅ™จๆŸ่™•ๅ‡บ้Œฏๆ™‚๏ผŒๆœƒ่‡ชๅ‹•ๅ›žๅ‚ณๅ…ถไธญไธ€ๅ€‹็‹€ๆ…‹็ขผใ€‚ + +/// tip | ๆ็คบ + +ๆƒณๆทฑๅ…ฅ็žญ่งฃๅ„็‹€ๆ…‹็ขผ่ˆ‡ๅ…ถ็”จ้€”๏ผŒ่ซ‹ๅƒ่€ƒ MDN ้—œๆ–ผ HTTP ็‹€ๆ…‹็ขผ็š„ๆ–‡ไปถใ€‚ + +/// + +## ๅฟซ้€Ÿ่จ˜ไฝๅ็จฑ { #shortcut-to-remember-the-names } + +ๅ†็œ‹ไธ€ๆฌกๅ‰้ข็š„็ฏ„ไพ‹๏ผš + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +`201` ๆ˜ฏใ€Œๅทฒๅปบ็ซ‹๏ผˆCreated๏ผ‰ใ€็š„็‹€ๆ…‹็ขผใ€‚ + +ไฝ†ไฝ ไธ้œ€่ฆ่ƒŒไธ‹ๆฏๅ€‹ไปฃ็ขผไปฃ่กจไป€้บผใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จ `fastapi.status` ๆไพ›็š„ไพฟๅˆฉ่ฎŠๆ•ธใ€‚ + +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} + +ๅฎƒๅ€‘ๅชๆ˜ฏๆ–นไพฟ็”จ็š„ๅธธๆ•ธ๏ผŒๅ€ผ่ˆ‡ๆ•ธๅญ—็›ธๅŒ๏ผŒไฝ†้€™ๆจฃไฝ ๅฏไปฅ็”จ็ทจ่ผฏๅ™จ็š„่‡ชๅ‹•ๅฎŒๆˆไพ†ๆ‰พๅˆฐๅฎƒๅ€‘๏ผš + + + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette import status`ใ€‚ + +**FastAPI** ๅฐ‡ๅŒไธ€ๅ€‹ `starlette.status` ไปฅ `fastapi.status` ๅฝขๅผๆไพ›๏ผŒ็ด”็ฒนๆ˜ฏ็‚บไบ†่ฎ“ไฝ ๏ผˆ้–‹็™ผ่€…๏ผ‰ๆ–นไพฟใ€‚ไฝ†ๅฎƒ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +## ่ฎŠๆ›ด้ ่จญๅ€ผ { #changing-the-default } + +็จๅพŒๅœจ [้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—](../advanced/response-change-status-code.md){.internal-link target=_blank} ไธญ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฆ‚ไฝ•ๅ›žๅ‚ณไธ€ๅ€‹ไธๅŒๆ–ผๆญค่™•ๆ‰€ๅฎฃๅ‘Š้ ่จญๅ€ผ็š„็‹€ๆ…‹็ขผใ€‚ diff --git a/docs/zh-hant/docs/tutorial/schema-extra-example.md b/docs/zh-hant/docs/tutorial/schema-extra-example.md new file mode 100644 index 0000000000..661938ac26 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/schema-extra-example.md @@ -0,0 +1,202 @@ +# ๅฎฃๅ‘Š่ซ‹ๆฑ‚็ฏ„ไพ‹่ณ‡ๆ–™ { #declare-request-example-data } + +ไฝ ๅฏไปฅๅฎฃๅ‘Šไฝ ็š„ๆ‡‰็”จ็จ‹ๅผๅฏๆŽฅๆ”ถ่ณ‡ๆ–™็š„ examplesใ€‚ + +ไปฅไธ‹ๆœ‰ๆ•ธ็จฎๆ–นๅผๅฏ้”ๆˆใ€‚ + +## Pydantic ๆจกๅž‹ไธญ็š„้กๅค– JSON Schema ่ณ‡ๆ–™ { #extra-json-schema-data-in-pydantic-models } + +ไฝ ๅฏไปฅ็‚บ Pydantic ๆจกๅž‹ๅฎฃๅ‘Š `examples`๏ผŒๅฎƒๅ€‘ๆœƒๅŠ ๅ…ฅๅˆฐ็”ข็”Ÿๅ‡บ็š„ JSON Schema ไธญใ€‚ + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +้€™ไบ›้กๅค–่ณ‡่จŠๆœƒๅŽŸๅฐไธๅ‹•ๅŠ ๅ…ฅ่ฉฒๆจกๅž‹่ผธๅ‡บ็š„ JSON Schema๏ผŒไธฆไธ”ๆœƒ็”จๅœจ API ๆ–‡ไปถ่ฃกใ€‚ + +ไฝ ๅฏไปฅไฝฟ็”จๅฑฌๆ€ง `model_config`๏ผˆๆŽฅๆ”ถไธ€ๅ€‹ `dict`๏ผ‰๏ผŒ่ฉณ่ฆ‹ Pydantic ๆ–‡ไปถ๏ผšConfigurationใ€‚ + +ไฝ ๅฏไปฅๅฐ‡ `"json_schema_extra"` ่จญ็‚บไธ€ๅ€‹ `dict`๏ผŒๅ…ถไธญๅŒ…ๅซไฝ ๆƒณๅœจ็”ข็”Ÿ็š„ JSON Schema ไธญๅ‡บ็พ็š„ไปปไฝ•้กๅค–่ณ‡ๆ–™๏ผŒๅŒ…ๆ‹ฌ `examples`ใ€‚ + +/// tip + +ไฝ ๅฏไปฅ็”จ็›ธๅŒๆŠ€ๅทงๆ“ดๅ…… JSON Schema๏ผŒๅŠ ๅ…ฅไฝ ่‡ชๅทฑ็š„่‡ช่จ‚้กๅค–่ณ‡่จŠใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒ็‚บๅ‰็ซฏไฝฟ็”จ่€…ไป‹้ขๆ–ฐๅขžไธญ็นผ่ณ‡ๆ–™็ญ‰ใ€‚ + +/// + +/// info + +OpenAPI 3.1.0๏ผˆ่‡ช FastAPI 0.99.0 ่ตทไฝฟ็”จ๏ผ‰ๆ–ฐๅขžไบ†ๅฐ `examples` ็š„ๆ”ฏๆด๏ผŒ้€™ๆ˜ฏ **JSON Schema** ๆจ™ๆบ–็š„ไธ€้ƒจๅˆ†ใ€‚ + +ๅœจ้‚ฃไน‹ๅ‰๏ผŒๅชๆ”ฏๆดไฝฟ็”จๅ–ฎไธ€็ฏ„ไพ‹็š„้—œ้ตๅญ— `example`ใ€‚OpenAPI 3.1.0 ไป็„ถๆ”ฏๆด `example`๏ผŒไฝ†ๅฎƒๅทฒ่ขซๆฃ„็”จ๏ผŒไธ”ไธๆ˜ฏ JSON Schema ๆจ™ๆบ–็š„ไธ€้ƒจๅˆ†ใ€‚ๅ› ๆญคๅปบ่ญฐไฝ ๅฐ‡ `example` ้ท็งป็‚บ `examples`ใ€‚๐Ÿค“ + +ไฝ ๅฏไปฅๅœจๆœฌ้ ็ตๅฐพ้–ฑ่ฎ€ๆ›ดๅคšใ€‚ + +/// + +## `Field` ๅ…ถไป–ๅƒๆ•ธ { #field-additional-arguments } + +ๅœจ Pydantic ๆจกๅž‹ไธญไฝฟ็”จ `Field()` ๆ™‚๏ผŒไฝ ไนŸๅฏไปฅๅฎฃๅ‘Š้กๅค–็š„ `examples`๏ผš + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## JSON Schema ็š„ `examples` - OpenAPI { #examples-in-json-schema-openapi } + +็•ถไฝฟ็”จไธ‹ๅˆ—ไปปไธ€้ …๏ผš + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +ไฝ ไนŸๅฏไปฅๅฎฃๅ‘Šไธ€็ต„ `examples`๏ผŒๅŒ…ๅซๆœƒๅŠ ๅ…ฅๅˆฐ **OpenAPI** ไธญๅฎƒๅ€‘ๅ„่‡ช **JSON Schemas** ็š„้กๅค–่ณ‡่จŠใ€‚ + +### `Body` ๆญ้… `examples` { #body-with-examples } + +้€™่ฃกๆˆ‘ๅ€‘ๅ‚ณๅ…ฅ `examples`๏ผŒๅ…ถไธญๅŒ…ๅซ `Body()` ้ ๆœŸ่ณ‡ๆ–™็š„ไธ€ๅ€‹็ฏ„ไพ‹๏ผš + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### ๆ–‡ไปถ UI ไธญ็š„็ฏ„ไพ‹ { #example-in-the-docs-ui } + +ไฝฟ็”จไปฅไธŠไปปไธ€ๆ–นๆณ•๏ผŒๅœจ `/docs` ไธญ็œ‹่ตทไพ†ๆœƒๅƒ้€™ๆจฃ๏ผš + + + +### `Body` ๆญ้…ๅคšๅ€‹ `examples` { #body-with-multiple-examples } + +็•ถ็„ถ๏ผŒไฝ ไนŸๅฏไปฅๅ‚ณๅ…ฅๅคšๅ€‹ `examples`๏ผš + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +้€™้บผๅšๆ™‚๏ผŒ้€™ไบ›็ฏ„ไพ‹ๆœƒๆˆ็‚บ่ฉฒ body ่ณ‡ๆ–™ๅ…ง้ƒจ **JSON Schema** ็š„ไธ€้ƒจๅˆ†ใ€‚ + +็„ถ่€Œ๏ผŒๆ’ฐๅฏซๆœฌๆ–‡ๆ™‚๏ผŒ่ฒ ่ฒฌๅ‘ˆ็พๆ–‡ไปถ UI ็š„ๅทฅๅ…ท Swagger UI ไธฆไธๆ”ฏๆดๅœจ **JSON Schema** ไธญ้กฏ็คบๅคšๅ€‹็ฏ„ไพ‹ใ€‚ไธ้Ž่ซ‹็นผ็บŒๅพ€ไธ‹้–ฑ่ฎ€ไปฅๅ–ๅพ—่ฎŠ้€šๆ–นๅผใ€‚ + +### OpenAPI ็‰นๅฎš็š„ `examples` { #openapi-specific-examples } + +ๅœจ **JSON Schema** ๆ”ฏๆด `examples` ไน‹ๅ‰๏ผŒOpenAPI ๅฐฑๅทฒๆ”ฏๆดๅฆไธ€ๅ€‹ๅŒๅ็š„ๆฌ„ไฝ `examples`ใ€‚ + +้€™ๅ€‹ใ€ŒOpenAPI ็‰นๅฎšใ€็š„ `examples` ไฝๆ–ผ OpenAPI ่ฆ็ฏ„็š„ๅฆไธ€ๅ€‹ๅ€ๅกŠ๏ผšๅœจๆฏๅ€‹ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€็š„่ฉณ็ดฐ่ณ‡่จŠไธญ๏ผŒ่€Œไธๆ˜ฏๅœจๅ„ๅ€‹ JSON Schema ๅ…งใ€‚ + +่€Œ Swagger UI ๆ—ฉๅทฒๆ”ฏๆด้€™ๅ€‹ๆฌ„ไฝ๏ผŒๅ› ๆญคไฝ ๅฏไปฅ็”จๅฎƒๅœจๆ–‡ไปถ UI ไธญ้กฏ็คบไธๅŒ็š„็ฏ„ไพ‹ใ€‚ + +้€™ๅ€‹ OpenAPI ็‰นๅฎšๆฌ„ไฝ `examples` ็š„็ตๆง‹ๆ˜ฏไธ€ๅ€‹ๅŒ…ๅซใ€Œๅคšๅ€‹็ฏ„ไพ‹ใ€็š„ `dict`๏ผˆ่€Œ้ž `list`๏ผ‰๏ผŒๆฏๅ€‹็ฏ„ไพ‹้ƒฝๅฏๅŒ…ๅซๆœƒไธ€ไฝตๅŠ ๅ…ฅๅˆฐ **OpenAPI** ็š„้กๅค–่ณ‡่จŠใ€‚ + +ๅฎƒไธๆœƒๅ‡บ็พๅœจ OpenAPI ๆ‰€ๅซ็š„ๅ„ๅ€‹ JSON Schema ๅ…ง๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅๆ”พๅœจๅฐๆ‡‰็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ไธŠใ€‚ + +### ไฝฟ็”จ `openapi_examples` ๅƒๆ•ธ { #using-the-openapi-examples-parameter } + +ไฝ ๅฏไปฅๅœจ FastAPI ไธญ้€้Žๅƒๆ•ธ `openapi_examples` ็‚บไธ‹ๅˆ—้ …็›ฎๅฎฃๅ‘Š OpenAPI ็‰นๅฎš็š„ `examples`๏ผš + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +่ฉฒ `dict` ็š„้ต็”จไพ†่ญ˜ๅˆฅๅ„ๅ€‹็ฏ„ไพ‹๏ผŒ่€Œๆฏๅ€‹ๅ€ผๅ‰‡ๆ˜ฏๅฆไธ€ๅ€‹ `dict`ใ€‚ + +ๅœจ `examples` ไธญ๏ผŒๆฏๅ€‹็ฏ„ไพ‹็š„ `dict` ๅฏไปฅๅŒ…ๅซ๏ผš + +* `summary`๏ผš็ฏ„ไพ‹็š„็ฐก็Ÿญๆ่ฟฐใ€‚ +* `description`๏ผš่ผƒ้•ท็š„ๆ่ฟฐ๏ผŒๅฏๅŒ…ๅซ Markdown ๆ–‡ๅญ—ใ€‚ +* `value`๏ผšๅฏฆ้š›้กฏ็คบ็š„็ฏ„ไพ‹๏ผŒไพ‹ๅฆ‚ไธ€ๅ€‹ `dict`ใ€‚ +* `externalValue`๏ผš`value` ็š„ๆ›ฟไปฃๆ–นๆกˆ๏ผŒ็‚บๆŒ‡ๅ‘็ฏ„ไพ‹็š„ URLใ€‚ๅ„˜็ฎก้€™ๅฏ่ƒฝไธๅฆ‚ `value` ่ขซๅทฅๅ…ทๅปฃๆณ›ๆ”ฏๆดใ€‚ + +ไฝ ๅฏไปฅ้€™ๆจฃไฝฟ็”จ๏ผš + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### ๆ–‡ไปถ UI ไธญ็š„ OpenAPI ็ฏ„ไพ‹ { #openapi-examples-in-the-docs-ui } + +็•ถๅœจ `Body()` ๅŠ ไธŠ `openapi_examples`๏ผŒ`/docs` ๆœƒ้กฏ็คบ็‚บ๏ผš + + + +## ๆŠ€่ก“็ดฐ็ฏ€ { #technical-details } + +/// tip + +ๅฆ‚ๆžœไฝ ๅทฒ็ถ“ๅœจไฝฟ็”จ **FastAPI** **0.99.0 ๆˆ–ไปฅไธŠ**็š„็‰ˆๆœฌ๏ผŒๅคงๆฆ‚ๅฏไปฅ็•ฅ้Ž้€™ไบ›็ดฐ็ฏ€ใ€‚ + +้€™ไบ›ๅ…งๅฎนๆฏ”่ผƒ่ˆ‡่ˆŠ็‰ˆ๏ผˆๅœจ OpenAPI 3.1.0 ๅฏ็”จไน‹ๅ‰๏ผ‰็›ธ้—œใ€‚ + +ไฝ ๅฏไปฅๆŠŠ้€™ๆฎต็•ถไฝœไธ€ๅฐๅ ‚ OpenAPI ่ˆ‡ JSON Schema ็š„ๆญทๅฒ่ชฒใ€‚๐Ÿค“ + +/// + +/// warning + +ไปฅไธ‹ๆ˜ฏ้—œๆ–ผ **JSON Schema** ่ˆ‡ **OpenAPI** ๆจ™ๆบ–็š„ๆŠ€่ก“็ดฐ็ฏ€ใ€‚ + +ๅฆ‚ๆžœไธŠ้ข็š„ๅšๆณ•ๅฐไฝ ๅทฒ็ถ“่ถณๅค ๅฏ็”จ๏ผŒๅฐฑไธ้œ€่ฆ้€™ไบ›็ดฐ็ฏ€๏ผŒๅ„˜็ฎก็›ดๆŽฅ่ทณ้Žใ€‚ + +/// + +ๅœจ OpenAPI 3.1.0 ไน‹ๅ‰๏ผŒOpenAPI ไฝฟ็”จ็š„ๆ˜ฏ่ผƒ่ˆŠไธ”็ถ“้Žไฟฎๆ”น็š„ **JSON Schema** ็‰ˆๆœฌใ€‚ + +็•ถๆ™‚ JSON Schema ๆฒ’ๆœ‰ `examples`๏ผŒๅ› ๆญค OpenAPI ๅœจๅฎƒ่‡ช่จ‚ไฟฎๆ”น็š„็‰ˆๆœฌไธญๆ–ฐๅขžไบ†่‡ชๅทฑ็š„ `example` ๆฌ„ไฝใ€‚ + +OpenAPI ไนŸๅœจ่ฆ็ฏ„็š„ๅ…ถไป–้ƒจๅˆ†ๆ–ฐๅขžไบ† `example` ่ˆ‡ `examples` ๆฌ„ไฝ๏ผš + +* `Parameter Object`๏ผˆ่ฆ็ฏ„๏ผ‰๏ผŒๅฐๆ‡‰ๅˆฐ FastAPI ็š„๏ผš + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object` ไธญ็š„ `content` ๆฌ„ไฝ่ฃก็š„ `Media Type Object`๏ผˆ่ฆ็ฏ„๏ผ‰๏ผŒๅฐๆ‡‰ๅˆฐ FastAPI ็š„๏ผš + * `Body()` + * `File()` + * `Form()` + +/// info + +้€™ๅ€‹่ˆŠ็š„ใ€OpenAPI ็‰นๅฎš็š„ `examples` ๅƒๆ•ธ๏ผŒๅพž FastAPI `0.103.0` ่ตทๆ”นๅ็‚บ `openapi_examples`ใ€‚ + +/// + +### JSON Schema ็š„ `examples` ๆฌ„ไฝ { #json-schemas-examples-field } + +ๅพŒไพ† JSON Schema ๅœจๆ–ฐ็‰ˆๆœฌ่ฆ็ฏ„ไธญๆ–ฐๅขžไบ† `examples` ๆฌ„ไฝใ€‚ + +ๆŽฅ่‘—ๆ–ฐ็š„ OpenAPI 3.1.0 ไปฅๆœ€ๆ–ฐ็‰ˆๆœฌ๏ผˆJSON Schema 2020-12๏ผ‰็‚บๅŸบ็คŽ๏ผŒ่ฉฒ็‰ˆๆœฌๅฐฑๅŒ…ๅซ้€™ๅ€‹ๆ–ฐ็š„ `examples` ๆฌ„ไฝใ€‚ + +็พๅœจ้€™ๅ€‹ๆ–ฐ็š„ `examples` ๆฌ„ไฝๅ„ชๅ…ˆๆ–ผ่ˆŠ็š„ๅ–ฎไธ€๏ผˆไธ”ๅฎข่ฃฝ๏ผ‰`example` ๆฌ„ไฝ๏ผŒๅพŒ่€…ๅทฒ่ขซๆฃ„็”จใ€‚ + +JSON Schema ไธญๆ–ฐ็š„ `examples` ๆฌ„ไฝใ€Œๅฐฑๆ˜ฏไธ€ๅ€‹ `list`ใ€็š„็ฏ„ไพ‹้›†ๅˆ๏ผŒ่€Œไธๆ˜ฏๅƒ OpenAPI ๅ…ถไป–ๅœฐๆ–น๏ผˆๅฆ‚ไธŠๆ‰€่ฟฐ๏ผ‰้‚ฃๆจฃ้™„ๅธถ้กๅค–ไธญ็นผ่ณ‡ๆ–™็š„ `dict`ใ€‚ + +/// info + +ๅณไฝฟ OpenAPI 3.1.0 ๅทฒ็™ผไฝˆไธฆ่ˆ‡ JSON Schema ๆœ‰ๆ›ด็ฐกๆฝ”็š„ๆ•ดๅˆ๏ผŒไธ€ๆฎตๆ™‚้–“ๅ…งๆไพ›่‡ชๅ‹•ๆ–‡ไปถ็š„ Swagger UI ไธฆไธๆ”ฏๆด OpenAPI 3.1.0๏ผˆ่‡ช 5.0.0 ็‰ˆ่ตทๆ”ฏๆด ๐ŸŽ‰๏ผ‰ใ€‚ + +ๅ› ๆญค๏ผŒFastAPI 0.99.0 ไน‹ๅ‰็š„็‰ˆๆœฌไปไฝฟ็”จ 3.1.0 ไปฅไธ‹็š„ OpenAPI ็‰ˆๆœฌใ€‚ + +/// + +### Pydantic ่ˆ‡ FastAPI ็š„ `examples` { #pydantic-and-fastapi-examples } + +็•ถไฝ ๅœจ Pydantic ๆจกๅž‹ไธญๅŠ ๅ…ฅ `examples`๏ผŒไธ่ซ–ๆ˜ฏ็”จ `schema_extra` ๆˆ– `Field(examples=["something"])`๏ผŒ่ฉฒ็ฏ„ไพ‹้ƒฝๆœƒ่ขซๅŠ ๅ…ฅ่ฉฒ Pydantic ๆจกๅž‹็š„ **JSON Schema**ใ€‚ + +่€Œ่ฉฒ Pydantic ๆจกๅž‹็š„ **JSON Schema** ๆœƒ่ขซๅŒ…ๅซๅˆฐไฝ ็š„ API ็š„ **OpenAPI** ไธญ๏ผŒๆŽฅ่‘—็”จๆ–ผๆ–‡ไปถ UIใ€‚ + +ๅœจ FastAPI 0.99.0 ไน‹ๅ‰็š„็‰ˆๆœฌ๏ผˆ0.99.0 ่ตทไฝฟ็”จ่ผƒๆ–ฐ็š„ OpenAPI 3.1.0๏ผ‰ไธญ๏ผŒ็•ถไฝ ๅฐๅ…ถไป–ๅทฅๅ…ท๏ผˆ`Query()`ใ€`Body()` ็ญ‰๏ผ‰ไฝฟ็”จ `example` ๆˆ– `examples` ๆ™‚๏ผŒ้€™ไบ›็ฏ„ไพ‹ไธๆœƒ่ขซๅŠ ๅ…ฅๆ่ฟฐ่ฉฒ่ณ‡ๆ–™็š„ JSON Schema๏ผˆ็”š่‡ณไธๆœƒๅŠ ๅ…ฅๅˆฐ OpenAPI ่‡ชๅทฑ็‰ˆๆœฌ็š„ JSON Schema ไธญ๏ผ‰๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅๅŠ ๅ…ฅๅˆฐ OpenAPI ไธญ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅฎฃๅ‘Š๏ผˆๅœจ OpenAPI ไฝฟ็”จ JSON Schema ็š„้‚ฃไบ›้ƒจๅˆ†ไน‹ๅค–๏ผ‰ใ€‚ + +ไฝ†็พๅœจ FastAPI 0.99.0 ไปฅไธŠไฝฟ็”จ็š„ OpenAPI 3.1.0 ๆญ้… JSON Schema 2020-12๏ผŒไปฅๅŠ Swagger UI 5.0.0 ไปฅไธŠ็‰ˆๆœฌ๏ผŒๆ•ด้ซ”ๆ›ดๅŠ ไธ€่‡ด๏ผŒ็ฏ„ไพ‹ๆœƒๅŒ…ๅซๅœจ JSON Schema ไธญใ€‚ + +### Swagger UI ่ˆ‡ OpenAPI ็‰นๅฎš็š„ `examples` { #swagger-ui-and-openapi-specific-examples } + +็”ฑๆ–ผๅœจ๏ผˆ2023-08-26 ๆ™‚๏ผ‰Swagger UI ไธๆ”ฏๆดๅคšๅ€‹ JSON Schema ็ฏ„ไพ‹๏ผŒไฝฟ็”จ่€…็„กๆณ•ๅœจๆ–‡ไปถไธญ้กฏ็คบๅคšๅ€‹็ฏ„ไพ‹ใ€‚ + +็‚บไบ†่งฃๆฑบๆญคๅ•้กŒ๏ผŒFastAPI `0.103.0` ้€้Žๆ–ฐๅƒๆ•ธ `openapi_examples` **ๆ–ฐๅขžๆ”ฏๆด** ๅฎฃๅ‘Š่ˆŠ็š„ใ€ŒOpenAPI ็‰นๅฎšใ€`examples` ๆฌ„ไฝใ€‚๐Ÿค“ + +### ็ธฝ็ต { #summary } + +ๆˆ‘ไปฅๅ‰ๅธธ่ชชๆˆ‘ไธๅคชๅ–œๆญกๆญทๅฒโ€ฆโ€ฆ็ตๆžœ็พๅœจๅœจ้€™่ฃก่ฌ›ใ€Œ็ง‘ๆŠ€ๅฒใ€ใ€‚๐Ÿ˜… + +็ฐก่€Œ่จ€ไน‹๏ผŒ**ๅ‡็ดšๅˆฐ FastAPI 0.99.0 ๆˆ–ไปฅไธŠ**๏ผŒไบ‹ๆƒ…ๆœƒๆ›ด**็ฐกๅ–ฎใ€ไธ€่‡ดๅˆ็›ด่ฆบ**๏ผŒ่€Œไธ”ไฝ ไธ้œ€่ฆไบ†่งฃ้€™ไบ›ๆญทๅฒ็ดฐ็ฏ€ใ€‚๐Ÿ˜Ž diff --git a/docs/zh-hant/docs/tutorial/security/first-steps.md b/docs/zh-hant/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000..109f59a37a --- /dev/null +++ b/docs/zh-hant/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# ๅฎ‰ๅ…จๆ€ง - ๅ…ฅ้–€ { #security-first-steps } + +ๆƒณๅƒไฝ ๆœ‰ไธ€ๅ€‹้ƒจ็ฝฒๅœจๆŸๅ€‹็ถฒๅŸŸ็š„ๅพŒ็ซฏ APIใ€‚ + +้‚„ๆœ‰ไธ€ๅ€‹ๅ‰็ซฏๅœจๅฆไธ€ๅ€‹็ถฒๅŸŸ๏ผŒๆˆ–ๅŒไธ€็ถฒๅŸŸ็š„ไธๅŒ่ทฏๅพ‘๏ผˆๆˆ–ๆ˜ฏ่กŒๅ‹•ๆ‡‰็”จ็จ‹ๅผ๏ผ‰ใ€‚ + +ไฝ ๅธŒๆœ›ๅ‰็ซฏ่ƒฝ็”จไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผๅ‘ๅพŒ็ซฏ้€ฒ่กŒ่บซๅˆ†้ฉ—่ญ‰ใ€‚ + +ๆˆ‘ๅ€‘ๅฏไปฅ็”จ OAuth2 ๆญ้… FastAPI ไพ†ๅฏฆไฝœใ€‚ + +ไฝ†ไธๅฟ…้€š่ฎ€ๆ•ดไปฝๅ†—้•ท่ฆๆ ผๅช็‚บไบ†ๆ‰พๅ‡บไฝ ้œ€่ฆ็š„ๅนพๅ€‹้‡้ปžใ€‚ + +ๅฐฑ็”จ FastAPI ๆไพ›็š„ๅทฅๅ…ท่™•็†ๅฎ‰ๅ…จๆ€งใ€‚ + +## ็œ‹่ตทไพ†ๅฆ‚ไฝ• { #how-it-looks } + +ๅ…ˆ็›ดๆŽฅ่ท‘็ฏ„ไพ‹็œ‹ๆ•ˆๆžœ๏ผŒๅ†ๅ›ž้ ญ็†่งฃๅ…ถๅŽŸ็†ใ€‚ + +## ๅปบ็ซ‹ `main.py` { #create-main-py } + +ๅฐ‡็ฏ„ไพ‹่ค‡่ฃฝๅˆฐๆช”ๆกˆ `main.py`๏ผš + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## ๅŸท่กŒ { #run-it } + +/// info + +็•ถไฝ ไฝฟ็”จ `pip install "fastapi[standard]"` ๆŒ‡ไปคๅฎ‰่ฃๆ™‚๏ผŒ`python-multipart` ๅฅ—ไปถๆœƒ้šจ FastAPI ่‡ชๅ‹•ๅฎ‰่ฃใ€‚ + +ไธ้Ž่‹ฅๅชๅŸท่กŒ `pip install fastapi`๏ผŒ้ ่จญไธๆœƒๅŒ…ๅซ `python-multipart`ใ€‚ + +่‹ฅ่ฆๆ‰‹ๅ‹•ๅฎ‰่ฃ๏ผŒ่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒๆŽฅ่‘—ๅŸท่กŒ๏ผš + +```console +$ pip install python-multipart +``` + +ๅ› ็‚บ OAuth2 ๆœƒไปฅใ€Œform dataใ€ๅ‚ณ้€ `username` ่ˆ‡ `password`ใ€‚ + +/// + +็”จไปฅไธ‹ๆŒ‡ไปคๅŸท่กŒ็ฏ„ไพ‹๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## ๆชขๆŸฅ { #check-it } + +้–‹ๅ•Ÿไบ’ๅ‹•ๅผๆ–‡ไปถ๏ผšhttp://127.0.0.1:8000/docsใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐ้กžไผผ้€™ๆจฃ๏ผš + + + +/// check | Authorize ๆŒ‰้ˆ•๏ผ + +ไฝ ๆœƒ็œ‹ๅˆฐไธ€ๅ€‹ๆ–ฐ็š„ใ€ŒAuthorizeใ€ๆŒ‰้ˆ•ใ€‚ + +่€Œไฝ ็š„ใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€ๅณไธŠ่ง’ไนŸๆœƒๅ‡บ็พไธ€ๅ€‹ๅฐ้Ž–้ ญๅฏไปฅ้ปžๆ“Šใ€‚ + +/// + +้ปžๆ“ŠๅพŒๆœƒ่ทณๅ‡บไธ€ๅ€‹ๅฐ่ฆ–็ช—๏ผŒ่ฎ“ไฝ ่ผธๅ…ฅ `username` ่ˆ‡ `password`๏ผˆไปฅๅŠๅ…ถไป–ๅฏ้ธๆฌ„ไฝ๏ผ‰๏ผš + + + +/// note | ๆณจๆ„ + +ไธ็ฎกไฝ ๅœจ่กจๅ–ฎ่ผธๅ…ฅไป€้บผ๏ผŒ็พๅœจ้ƒฝ้‚„ไธๆœƒๆˆๅŠŸ๏ผ›็ญ‰็ญ‰ๆˆ‘ๅ€‘ๆœƒๆŠŠๅฎƒๅฎŒๆˆใ€‚ + +/// + +้€™็•ถ็„ถไธๆ˜ฏ็ตฆๆœ€็ต‚ไฝฟ็”จ่€…็”จ็š„ๅ‰็ซฏ๏ผŒไฝ†ๅฎƒๆ˜ฏ็”จไพ†ไบ’ๅ‹•ๅผๆ–‡ไปถๅŒ–ๆ•ดๅ€‹ API ็š„ๆฅตไฝณ่‡ชๅ‹•ๅŒ–ๅทฅๅ…ทใ€‚ + +ๅ‰็ซฏๅœ˜้šŠ๏ผˆไนŸๅฏ่ƒฝๅฐฑๆ˜ฏไฝ ๏ผ‰ๅฏไปฅไฝฟ็”จๅฎƒใ€‚ + +็ฌฌไธ‰ๆ–นๆ‡‰็”จๆˆ–็ณป็ตฑไนŸ่ƒฝไฝฟ็”จๅฎƒใ€‚ + +ไฝ ไนŸ่ƒฝ็”จๅฎƒไพ†้™ค้Œฏใ€ๆชขๆŸฅ่ˆ‡ๆธฌ่ฉฆๅŒไธ€ๅ€‹ๆ‡‰็”จใ€‚ + +## `password` ๆต็จ‹ { #the-password-flow } + +็พๅœจๅ›ž้ ญ็†่งฃๅ‰›ๅ‰›้‚ฃไบ›ๆ˜ฏไป€้บผใ€‚ + +ๅœจ OAuth2 ไธญ๏ผŒ`password` ๆ˜ฏ่™•็†ๅฎ‰ๅ…จ่ˆ‡่บซๅˆ†้ฉ—่ญ‰็š„ๅ…ถไธญไธ€็จฎใ€Œๆต็จ‹ใ€๏ผˆflow๏ผ‰ใ€‚ + +OAuth2 ็š„่จญ่จˆ่ฎ“ๅพŒ็ซฏๆˆ– API ๅฏไปฅ็จ็ซ‹ๆ–ผๅŸท่กŒไฝฟ็”จ่€…้ฉ—่ญ‰็š„ไผบๆœๅ™จใ€‚ + +ไฝ†ๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒๅŒไธ€ๅ€‹ FastAPI ๆ‡‰็”จๆœƒๅŒๆ™‚่™•็† API ่ˆ‡้ฉ—่ญ‰ใ€‚ + +็ฐกๅŒ–ไพ†็œ‹ๆต็จ‹ๅฆ‚ไธ‹๏ผš + +- ไฝฟ็”จ่€…ๅœจๅ‰็ซฏ่ผธๅ…ฅ `username` ่ˆ‡ `password`๏ผŒๆŒ‰ไธ‹ `Enter`ใ€‚ +- ๅ‰็ซฏ๏ผˆๅœจไฝฟ็”จ่€…็š„็€่ฆฝๅ™จไธญๅŸท่กŒ๏ผ‰ๆŠŠ `username` ่ˆ‡ `password` ๅ‚ณๅˆฐๆˆ‘ๅ€‘ API ็š„็‰นๅฎš URL๏ผˆๅœจ็จ‹ๅผไธญๅฎฃๅ‘Š็‚บ `tokenUrl="token"`๏ผ‰ใ€‚ +- API ๆชขๆŸฅ `username` ่ˆ‡ `password`๏ผŒไธฆๅ›žๅ‚ณไธ€ๅ€‹ใ€Œtoken๏ผˆๆฌŠๆ–๏ผ‰ใ€๏ผˆๆˆ‘ๅ€‘้‚„ๆฒ’ๅฏฆไฝœ้€™้ƒจๅˆ†๏ผ‰ใ€‚ + - ใ€Œtoken๏ผˆๆฌŠๆ–๏ผ‰ใ€ๅฐฑๆ˜ฏไธ€ๆฎตๅญ—ไธฒ๏ผŒไน‹ๅพŒๅฏ็”จไพ†่ญ˜ๅˆฅไธฆ้ฉ—่ญ‰ๆญคไฝฟ็”จ่€…ใ€‚ + - ้€šๅธธ token ๆœƒ่จญๅฎšไธ€ๆฎตๆ™‚้–“ๅพŒๅคฑๆ•ˆใ€‚ + - ๅ› ๆญคไฝฟ็”จ่€…ไน‹ๅพŒ้œ€่ฆ้‡ๆ–ฐ็™ปๅ…ฅใ€‚ + - ่‹ฅ token ่ขซ็ซŠๅ–๏ผŒ้ขจ้šชไนŸ่ผƒไฝŽ๏ผ›ๅฎƒไธๅƒๆฐธ้ ๆœ‰ๆ•ˆ็š„่ฌ็”จ้‘ฐๅŒ™๏ผˆๅคšๆ•ธๆƒ…ๆณไธ‹๏ผ‰ใ€‚ +- ๅ‰็ซฏๆœƒๆšซๅญ˜้€™ๅ€‹ tokenใ€‚ +- ไฝฟ็”จ่€…ๅœจๅ‰็ซฏ้ปžๆ“Šๅ‰ๅพ€ๅ…ถไป–้ ้ข/ๅ€ๆฎตใ€‚ +- ๅ‰็ซฏ้œ€่ฆๅ†ๅ‘ API ๅ–ๅพ—่ณ‡ๆ–™ใ€‚ + - ไฝ†่ฉฒ็ซฏ้ปž้œ€่ฆ้ฉ—่ญ‰ใ€‚ + - ๅ› ๆญค็‚บไบ†ๅ‘ API ้ฉ—่ญ‰๏ผŒ่ซ‹ๆฑ‚ๆœƒๅธถไธŠไธ€ๅ€‹ `Authorization` ๆจ™้ ญ๏ผŒๅ€ผ็‚บ `Bearer ` ๅŠ ไธŠ tokenใ€‚ + - ไพ‹ๅฆ‚ token ๆ˜ฏ `foobar`๏ผŒๅ‰‡ `Authorization` ๆจ™้ ญๅ…งๅฎน็‚บ๏ผš`Bearer foobar`ใ€‚ + +## FastAPI ็š„ `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } + +FastAPI ๆไพ›ๅคšๅฑคๆŠฝ่ฑก็š„ๅทฅๅ…ทไพ†ๅฏฆไฝœ้€™ไบ›ๅฎ‰ๅ…จๆฉŸๅˆถใ€‚ + +ๆœฌไพ‹ๅฐ‡ไฝฟ็”จ OAuth2 ็š„ Password ๆต็จ‹๏ผŒไธฆไปฅ Bearer token ้€ฒ่กŒ้ฉ—่ญ‰๏ผ›ๆˆ‘ๅ€‘ๆœƒ็”จ `OAuth2PasswordBearer` ้กžๅˆฅไพ†ๅฎŒๆˆใ€‚ + +/// info + +ใ€ŒBearerใ€token ไธๆ˜ฏๅ”ฏไธ€้ธ้ …ใ€‚ + +ไฝ†ๅฐๆœฌไพ‹ๆœ€ๅˆ้ฉใ€‚ + +้€šๅธธๅฐๅคšๆ•ธๆƒ…ๅขƒไนŸ่ถณๅค ๏ผŒ้™ค้žไฝ ๆ˜ฏ OAuth2 ๅฐˆๅฎถไธฆ็ขบไฟกๆœ‰ๆ›ด้ฉๅˆไฝ ็š„้ธ้ …ใ€‚ + +ๅœจ้‚ฃ็จฎๆƒ…ๆณไธ‹๏ผŒFastAPI ไนŸๆไพ›็›ธๆ‡‰ๅทฅๅ…ท่ฎ“ไฝ ่‡ช่กŒ็ต„ๅˆใ€‚ + +/// + +็•ถๆˆ‘ๅ€‘ๅปบ็ซ‹ `OAuth2PasswordBearer` ้กžๅˆฅ็š„ๅฏฆไพ‹ๆ™‚๏ผŒๆœƒๅ‚ณๅ…ฅ `tokenUrl` ๅƒๆ•ธใ€‚้€™ๅ€‹ๅƒๆ•ธๅŒ…ๅซไบ†ๅฎขๆˆถ็ซฏ๏ผˆๅœจไฝฟ็”จ่€…็€่ฆฝๅ™จไธญๅŸท่กŒ็š„ๅ‰็ซฏ๏ผ‰็”จไพ†้€ๅ‡บ `username` ่ˆ‡ `password` ไปฅๅ–ๅพ— token ็š„ URLใ€‚ + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip + +้€™่ฃก็š„ `tokenUrl="token"` ๆŒ‡็š„ๆ˜ฏๅฐšๆœชๅปบ็ซ‹็š„็›ธๅฐ URL `token`ใ€‚ๅ› ็‚บๆ˜ฏ็›ธๅฐ URL๏ผŒๆ‰€ไปฅ็ญ‰ๅŒๆ–ผ `./token`ใ€‚ + +็”ฑๆ–ผไฝฟ็”จไบ†็›ธๅฐ URL๏ผŒ่‹ฅไฝ ็š„ API ไฝๆ–ผ `https://example.com/`๏ผŒ้‚ฃๅฎƒๆœƒๆŒ‡ๅ‘ `https://example.com/token`๏ผ›ไฝ†่‹ฅไฝ ็š„ API ไฝๆ–ผ `https://example.com/api/v1/`๏ผŒ้‚ฃๅฎƒๆœƒๆŒ‡ๅ‘ `https://example.com/api/v1/token`ใ€‚ + +ไฝฟ็”จ็›ธๅฐ URL ๅพˆ้‡่ฆ๏ผŒ่ƒฝ็ขบไฟไฝ ็š„ๆ‡‰็”จๅœจๅƒๆ˜ฏ[ๅœจ Proxy ๅพŒๆ–น](../../advanced/behind-a-proxy.md){.internal-link target=_blank}้€™้กž้€ฒ้šŽๆƒ…ๅขƒไธญไป่ƒฝๆญฃๅธธ้‹ไฝœใ€‚ + +/// + +้€™ๅ€‹ๅƒๆ•ธไธๆœƒๅปบ็ซ‹่ฉฒ็ซฏ้ปž๏ผใ€Œ่ทฏๅพ‘ๆ“ไฝœใ€๏ผŒ่€Œๆ˜ฏๅฎฃๅ‘Š `/token` ๅฐ‡ๆ˜ฏๅฎขๆˆถ็ซฏ็”จไพ†ๅ–ๅพ— token ็š„ URLใ€‚้€™ไบ›่ณ‡่จŠๆœƒๅ‡บ็พๅœจ OpenAPI๏ผŒไธฆ่ขซไบ’ๅ‹•ๅผ API ๆ–‡ไปถ็ณป็ตฑไฝฟ็”จใ€‚ + +ๆˆ‘ๅ€‘ๅพˆๅฟซไนŸๆœƒๅปบ็ซ‹ๅฏฆ้š›็š„่ทฏๅพ‘ๆ“ไฝœใ€‚ + +/// info + +ๅฆ‚ๆžœไฝ ๆ˜ฏ้žๅธธๅšดๆ ผ็š„ใ€ŒPythonistaใ€๏ผŒๅฏ่ƒฝไธๅ–œๆญกๅƒๆ•ธๅ็จฑ็”จ `tokenUrl` ่€Œไธๆ˜ฏ `token_url`ใ€‚ + +้‚ฃๆ˜ฏๅ› ็‚บๅฎƒๆฒฟ็”จไบ† OpenAPI ่ฆๆ ผไธญ็š„ๅ็จฑใ€‚ๅฆ‚ๆญคไธ€ไพ†๏ผŒ่‹ฅไฝ ่ฆๆทฑๅ…ฅๆŸฅ้–ฑ้€™ไบ›ๅฎ‰ๅ…จๆ–นๆกˆ๏ผŒไพฟ่ƒฝ็›ดๆŽฅ่ค‡่ฃฝ่ฒผไธŠๅŽปๆœๅฐ‹ๆ›ดๅคš่ณ‡่จŠใ€‚ + +/// + +่ฎŠๆ•ธ `oauth2_scheme` ๆ˜ฏ `OAuth2PasswordBearer` ็š„ๅฏฆไพ‹๏ผŒไฝ†ๅŒๆ™‚ๅฎƒไนŸๆ˜ฏใ€Œๅฏๅ‘ผๅซ็š„ใ€๏ผˆcallable๏ผ‰ใ€‚ + +ๅฎƒๅฏไปฅ้€™ๆจฃ่ขซๅ‘ผๅซ๏ผš + +```Python +oauth2_scheme(some, parameters) +``` + +ๅ› ๆญคๅฎƒๅฏไปฅ้…ๅˆ `Depends` ไฝฟ็”จใ€‚ + +### ๅฆ‚ไฝ•ไฝฟ็”จ { #use-it } + +็พๅœจไฝ ๅฏไปฅๅœจ็›ธไพๆ€งไธญๅ‚ณๅ…ฅ `oauth2_scheme` ่ˆ‡ `Depends` ๆญ้…ใ€‚ + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +ๆญค็›ธไพๆ€งๆœƒๆไพ›ไธ€ๅ€‹ `str`๏ผŒๆŒ‡ๆดพ็ตฆใ€Œ่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผใ€็š„ๅƒๆ•ธ `token`ใ€‚ + +FastAPI ๆœƒ็Ÿฅ้“ๅฏไปฅไฝฟ็”จ้€™ๅ€‹็›ธไพๆ€ง๏ผŒๅœจ OpenAPI๏ผˆไปฅๅŠ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถ๏ผ‰ไธญๅฎš็พฉไธ€ๅ€‹ใ€Œๅฎ‰ๅ…จๆ€งๆ–นๆกˆใ€ใ€‚ + +/// info | ๆŠ€่ก“็ดฐ็ฏ€ + +FastAPI ไน‹ๆ‰€ไปฅ็Ÿฅ้“ๅฏไปฅ็”จ๏ผˆ็›ธไพๆ€งไธญๅฎฃๅ‘Š็š„๏ผ‰`OAuth2PasswordBearer` ้กžๅˆฅ๏ผŒๅœจ OpenAPI ไธญๅฎš็พฉๅฎ‰ๅ…จๆ€งๆ–นๆกˆ๏ผŒๆ˜ฏๅ› ็‚บๅฎƒ็นผๆ‰ฟ่‡ช `fastapi.security.oauth2.OAuth2`๏ผŒ่€ŒๅพŒ่€…ๅˆ็นผๆ‰ฟ่‡ช `fastapi.security.base.SecurityBase`ใ€‚ + +ๆ‰€ๆœ‰่ƒฝ่ˆ‡ OpenAPI๏ผˆไปฅๅŠ่‡ชๅ‹• API ๆ–‡ไปถ๏ผ‰ๆ•ดๅˆ็š„ๅฎ‰ๅ…จๅทฅๅ…ท้ƒฝ็นผๆ‰ฟ่‡ช `SecurityBase`๏ผŒFastAPI ๆ‰่ƒฝ็Ÿฅ้“ๅฆ‚ไฝ•ๆŠŠๅฎƒๅ€‘ๆ•ดๅˆ้€ฒ OpenAPIใ€‚ + +/// + +## ๅฎƒๅšไบ†ไป€้บผ { #what-it-does } + +ๅฎƒๆœƒๅพž่ซ‹ๆฑ‚ไธญๅฐ‹ๆ‰พ `Authorization` ๆจ™้ ญ๏ผŒๆชขๆŸฅๅ…ถๅ€ผๆ˜ฏๅฆ็‚บ `Bearer ` ๅŠ ไธŠไธ€ๆฎต token๏ผŒไธฆๅฐ‡่ฉฒ token ไปฅ `str` ๅ›žๅ‚ณใ€‚ + +่‹ฅๆœชๆ‰พๅˆฐ `Authorization` ๆจ™้ ญ๏ผŒๆˆ–ๅ…ถๅ€ผไธๆ˜ฏ `Bearer ` token๏ผŒๅ‰‡ๆœƒ็›ดๆŽฅๅ›žๅ‚ณ 401๏ผˆ`UNAUTHORIZED`๏ผ‰้Œฏ่ชคใ€‚ + +ไฝ ไธๅฟ…ๅ†่‡ช่กŒๆชขๆŸฅ token ๆ˜ฏๅฆๅญ˜ๅœจ๏ผ›ไฝ ๅฏไปฅ็ขบไฟกๅช่ฆไฝ ็š„ๅ‡ฝๅผ่ขซๅŸท่กŒ๏ผŒ่ฉฒ token ๅƒๆ•ธๅฐฑไธ€ๅฎšๆœƒๆ˜ฏ `str`ใ€‚ + +ไฝ ๅฏไปฅๅœจไบ’ๅ‹•ๅผๆ–‡ไปถไธญ่ฉฆ่ฉฆ็œ‹๏ผš + + + +ๆˆ‘ๅ€‘้‚„ๆฒ’้ฉ—่ญ‰ token ๆ˜ฏๅฆๆœ‰ๆ•ˆ๏ผŒไฝ†้€™ๅทฒๆ˜ฏๅ€‹้–‹ๅง‹ใ€‚ + +## ๅฐ็ต { #recap } + +ๅช้œ€ๅคšๅฏซ 3ใ€4 ่กŒ๏ผŒๅฐฑ่ƒฝๆœ‰ไธ€ๅ€‹ๅŸบๆœฌ็š„ๅฎ‰ๅ…จๆฉŸๅˆถใ€‚ diff --git a/docs/zh-hant/docs/tutorial/security/get-current-user.md b/docs/zh-hant/docs/tutorial/security/get-current-user.md new file mode 100644 index 0000000000..b223d4823b --- /dev/null +++ b/docs/zh-hant/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# ๅ–ๅพ—็›ฎๅ‰ไฝฟ็”จ่€… { #get-current-user } + +ๅœจๅ‰ไธ€็ซ ๏ผŒๅŸบๆ–ผไพ่ณดๆณจๅ…ฅ็ณป็ตฑ็š„ๅฎ‰ๅ…จๆฉŸๅˆถๆœƒๆŠŠไธ€ๅ€‹ `token`๏ผˆไฝœ็‚บ `str`๏ผ‰ๆไพ›็ตฆ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*๏ผš + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +ไฝ†้€™้‚„ไธๅคชๆœ‰็”จใ€‚ + +่ฎ“ๅฎƒๆ”น็‚บๅ›žๅ‚ณ็›ฎๅ‰ไฝฟ็”จ่€…ๅงใ€‚ + +## ๅปบ็ซ‹ไฝฟ็”จ่€…ๆจกๅž‹ { #create-a-user-model } + +ๅ…ˆๅปบ็ซ‹ไธ€ๅ€‹ Pydantic ็š„ไฝฟ็”จ่€…ๆจกๅž‹ใ€‚ + +ๅฐฑๅƒ็”จ Pydantic ๅฎฃๅ‘Š่ซ‹ๆฑ‚้ซ”ไธ€ๆจฃ๏ผŒๆˆ‘ๅ€‘ไนŸๅฏไปฅๅœจๅ…ถไป–ๅœฐๆ–นไฝฟ็”จๅฎƒ๏ผš + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} + +## ๅปบ็ซ‹ `get_current_user` ไพ่ณด { #create-a-get-current-user-dependency } + +่ฎ“ๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹ไพ่ณด `get_current_user`ใ€‚ + +่จ˜ๅพ—ไพ่ณดๅฏไปฅๆœ‰ๅญไพ่ณดๅ—Ž๏ผŸ + +`get_current_user` ๆœƒไพ่ณดๆˆ‘ๅ€‘ๅ…ˆๅ‰ๅปบ็ซ‹็š„็›ธๅŒ `oauth2_scheme`ใ€‚ + +ๅฆ‚ๅŒๅ…ˆๅ‰ๅœจ*่ทฏๅพ‘ๆ“ไฝœ*ไธญ็›ดๆŽฅๅš็š„ไธ€ๆจฃ๏ผŒๆ–ฐ็š„ไพ่ณด `get_current_user` ๆœƒๅพžๅญไพ่ณด `oauth2_scheme` ๆŽฅๆ”ถไธ€ๅ€‹ไฝœ็‚บ `str` ็š„ `token`๏ผš + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## ๅ–ๅพ—ไฝฟ็”จ่€… { #get-the-user } + +`get_current_user` ๆœƒไฝฟ็”จๆˆ‘ๅ€‘ๅปบ็ซ‹็š„๏ผˆๅ‡็š„๏ผ‰ๅทฅๅ…ทๅ‡ฝๅผ๏ผŒๅฎƒๆŽฅๆ”ถไธ€ๅ€‹ไฝœ็‚บ `str` ็š„ token๏ผŒไธฆๅ›žๅ‚ณๆˆ‘ๅ€‘็š„ Pydantic `User` ๆจกๅž‹๏ผš + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## ๆณจๅ…ฅ็›ฎๅ‰ไฝฟ็”จ่€… { #inject-the-current-user } + +็พๅœจๆˆ‘ๅ€‘ๅฏไปฅๅœจ*่ทฏๅพ‘ๆ“ไฝœ*ไธญ็”จ็›ธๅŒ็š„ `Depends` ไพ†ไฝฟ็”จ `get_current_user`๏ผš + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +ๆณจๆ„ๆˆ‘ๅ€‘ๆŠŠ `current_user` ็š„ๅž‹ๅˆฅๅฎฃๅ‘Š็‚บ Pydantic ็š„ `User` ๆจกๅž‹ใ€‚ + +้€™่ƒฝๅœจๅ‡ฝๅผๅ…งๆไพ›่‡ชๅ‹•่ฃœๅ…จ่ˆ‡ๅž‹ๅˆฅๆชขๆŸฅ็š„ๅ”ๅŠฉใ€‚ + +/// tip | ๆ็คบ + +ไฝ ๅฏ่ƒฝ่จ˜ๅพ—๏ผŒ่ซ‹ๆฑ‚้ซ”ไนŸๆœƒ็”จ Pydantic ๆจกๅž‹ๅฎฃๅ‘Šใ€‚ + +้€™่ฃกๅ› ็‚บไฝ ไฝฟ็”จไบ† `Depends`๏ผŒ**FastAPI** ไธๆœƒๆททๆท†ใ€‚ + +/// + +/// check | ๆชขๆŸฅ + +้€™ๅ€‹ไพ่ณด็ณป็ตฑ็š„่จญ่จˆ่ฎ“ๆˆ‘ๅ€‘ๅฏไปฅๆœ‰ไธๅŒ็š„ไพ่ณด๏ผˆไธๅŒ็š„ "dependables"๏ผ‰๏ผŒ้ƒฝๅ›žๅ‚ณ `User` ๆจกๅž‹ใ€‚ + +ๆˆ‘ๅ€‘ไธๅ—้™ๆ–ผๅช่ƒฝๆœ‰ไธ€ๅ€‹่ƒฝๅ›žๅ‚ณ่ฉฒ้กžๅž‹่ณ‡ๆ–™็š„ไพ่ณดใ€‚ + +/// + +## ๅ…ถไป–ๆจกๅž‹ { #other-models } + +็พๅœจไฝ ๅฏไปฅๅœจ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*ไธญ็›ดๆŽฅๅ–ๅพ—็›ฎๅ‰ไฝฟ็”จ่€…๏ผŒไธฆๅœจ**ไพ่ณดๆณจๅ…ฅ**ๅฑค่™•็†ๅฎ‰ๅ…จๆฉŸๅˆถ๏ผŒไฝฟ็”จ `Depends`ใ€‚ + +่€Œไธ”ไฝ ๅฏไปฅ็‚บๅฎ‰ๅ…จ้œ€ๆฑ‚ไฝฟ็”จไปปๆ„ๆจกๅž‹ๆˆ–่ณ‡ๆ–™๏ผˆๆœฌไพ‹ไธญๆ˜ฏ Pydantic ๆจกๅž‹ `User`๏ผ‰ใ€‚ + +ไฝ†ไฝ ไธๅ—้™ๆ–ผๆŸๅ€‹็‰นๅฎš็š„่ณ‡ๆ–™ๆจกๅž‹ใ€้กžๅˆฅๆˆ–ๅž‹ๅˆฅใ€‚ + +ๆƒณๅœจๆจกๅž‹ไธญๅชๆœ‰ `id` ่ˆ‡ `email` ่€Œๆฒ’ๆœ‰ไปปไฝ• `username`๏ผŸ็•ถ็„ถๅฏไปฅใ€‚ไฝ ๅฏไปฅ็”จๅŒๆจฃ็š„ๅทฅๅ…ท้”ๆˆใ€‚ + +ๆƒณๅช็”จไธ€ๅ€‹ `str`๏ผŸๆˆ–ๅช็”จไธ€ๅ€‹ `dict`๏ผŸๆˆ–็›ดๆŽฅไฝฟ็”จ่ณ‡ๆ–™ๅบซ้กžๅˆฅ็š„ๆจกๅž‹ๅฏฆไพ‹๏ผŸ้ƒฝๅฏไปฅ๏ผŒไธ€ๆจฃ้‹ไฝœใ€‚ + +ไฝ ็š„ๆ‡‰็”จๅ…ถๅฏฆๆฒ’ๆœ‰็œŸไบบไฝฟ็”จ่€…็™ปๅ…ฅ๏ผŒ่€Œๆ˜ฏๆฉŸๅ™จไบบใ€bot๏ผŒๆˆ–ๅ…ถไป–็ณป็ตฑ๏ผŒๅชๆŒๆœ‰ access token๏ผŸๅŒๆจฃๆฒ’ๆœ‰ๅ•้กŒใ€‚ + +ๅช่ฆ็”จไปปไฝ•ไฝ ็š„ๆ‡‰็”จ้œ€่ฆ็š„ๆจกๅž‹ใ€้กžๅˆฅๆˆ–่ณ‡ๆ–™ๅบซๅณๅฏใ€‚**FastAPI** ็š„ไพ่ณดๆณจๅ…ฅ็ณป็ตฑ้ƒฝๆ”ฏๆดใ€‚ + +## ็จ‹ๅผ็ขผๅคงๅฐ { #code-size } + +้€™ๅ€‹็ฏ„ไพ‹็œ‹่ตทไพ†ๅฏ่ƒฝๆœ‰้ปžๅ†—้•ทใ€‚่จ˜ไฝๆˆ‘ๅ€‘ๆŠŠๅฎ‰ๅ…จใ€่ณ‡ๆ–™ๆจกๅž‹ใ€ๅทฅๅ…ทๅ‡ฝๅผ่ˆ‡*่ทฏๅพ‘ๆ“ไฝœ*ๆททๅœจๅŒไธ€ๅ€‹ๆช”ๆกˆไธญใ€‚ + +ไฝ†้‡้ปžๅœจ้€™่ฃกใ€‚ + +ๅฎ‰ๅ…จ่ˆ‡ไพ่ณดๆณจๅ…ฅ็›ธ้—œ็š„ๅ…งๅฎนๅช้œ€่ฆๅฏซไธ€ๆฌกใ€‚ + +ไฝ ๅฏไปฅๆŠŠๅฎƒ่จญ่จˆๅพ—ๅ†่ค‡้›œ้ƒฝๆฒ’ๅ•้กŒ๏ผŒไป็„ถๅช้œ€ๅœจๅ–ฎไธ€ไฝ็ฝฎๅฏซไธ€ๆฌก๏ผŒไพ็„ถๅ…ทๅ‚™ๅฎŒๆ•ด็š„ๅฝˆๆ€งใ€‚ + +ไฝ†ไฝ ๅฏไปฅๆœ‰ๆˆๅƒไธŠ่ฌๅ€‹็ซฏ้ปž๏ผˆ*่ทฏๅพ‘ๆ“ไฝœ*๏ผ‰ๅ…ฑ็”จๅŒไธ€ๅฅ—ๅฎ‰ๅ…จ็ณป็ตฑใ€‚ + +่€Œไธ”ๅฎƒๅ€‘ๅ…จ้ƒจ๏ผˆๆˆ–ไฝ ๆƒณ่ฆ็š„ไธ€้ƒจๅˆ†๏ผ‰้ƒฝๅฏไปฅ้‡็”จ้€™ไบ›ไพ่ณด๏ผŒๆˆ–ไฝ ๅปบ็ซ‹็š„ๅ…ถไป–ไพ่ณดใ€‚ + +่€Œๆ‰€ๆœ‰้€™ไบ›ไธŠๅƒๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*้ƒฝๅฏไปฅๅฐๅˆฐๅช่ฆ 3 ่กŒ๏ผš + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## ๅ›ž้กง { #recap } + +็พๅœจไฝ ๅฏไปฅๅœจ*่ทฏๅพ‘ๆ“ไฝœๅ‡ฝๅผ*ไธญ็›ดๆŽฅๅ–ๅพ—็›ฎๅ‰ไฝฟ็”จ่€…ใ€‚ + +ๆˆ‘ๅ€‘ๅทฒ็ถ“ๅฎŒๆˆไธ€ๅŠไบ†ใ€‚ + +ๆˆ‘ๅ€‘ๅช้œ€่ฆๅ†ๆ–ฐๅขžไธ€ๅ€‹*่ทฏๅพ‘ๆ“ไฝœ*๏ผŒ่ฎ“ไฝฟ็”จ่€…/็”จๆˆถ็ซฏๅฏฆ้š›้€ๅ‡บ `username` ่ˆ‡ `password`ใ€‚ + +ไธ‹ไธ€ๆญฅๅฐฑๆœƒๅšใ€‚ diff --git a/docs/zh-hant/docs/tutorial/security/index.md b/docs/zh-hant/docs/tutorial/security/index.md new file mode 100644 index 0000000000..b5e3738bcd --- /dev/null +++ b/docs/zh-hant/docs/tutorial/security/index.md @@ -0,0 +1,101 @@ +# ๅฎ‰ๅ…จๆ€ง { #security } + +ๆœ‰่จฑๅคšๆ–นๅผๅฏไปฅ่™•็†ๅฎ‰ๅ…จๆ€งใ€่บซๅˆ†้ฉ—่ญ‰่ˆ‡ๆŽˆๆฌŠใ€‚ + +่€Œไธ”้€™้€šๅธธๆ˜ฏไธ€ๅ€‹่ค‡้›œไธ”ใ€Œๅ›ฐ้›ฃใ€็š„ไธป้กŒใ€‚ + +ๅœจ่จฑๅคšๆก†ๆžถ่ˆ‡็ณป็ตฑไธญ๏ผŒๅ…‰ๆ˜ฏ่™•็†ๅฎ‰ๅ…จๆ€ง่ˆ‡่บซๅˆ†้ฉ—่ญ‰ๅฐฑ่ฆ่Šฑ่ฒปๅคง้‡ๅฟƒๅŠ›่ˆ‡็จ‹ๅผ็ขผ๏ผˆๅพˆๅคšๆƒ…ๆณไธ‹ๅฏ่ƒฝไฝ”ไบ†ๅ…จ้ƒจ็จ‹ๅผ็ขผ็š„ 50% ไปฅไธŠ๏ผ‰ใ€‚ + +**FastAPI** ๆไพ›ๅคš็จฎๅทฅๅ…ท๏ผŒ่ฎ“ไฝ ่ƒฝไปฅๆจ™ๆบ–ๆ–นๅผ่ผ•้ฌ†ใ€ๅฟซ้€Ÿๅœฐ่™•็†ใ€Œๅฎ‰ๅ…จๆ€งใ€๏ผŒ่€Œไธๅฟ…ๅ…ˆ็ ”็ฉถไธฆๅญธๆœƒๆ‰€ๆœ‰ๅฎ‰ๅ…จๆ€ง่ฆ็ฏ„ใ€‚ + +ไฝ†ๅœจๆญคไน‹ๅ‰๏ผŒๅ…ˆ้‡ๆธ…ๅนพๅ€‹ๅฐๆฆ‚ๅฟตใ€‚ + +## ๆ€ฅ่‘—ไธŠๆ‰‹๏ผŸ { #in-a-hurry } + +ๅฆ‚ๆžœไฝ ไธๅœจๆ„้€™ไบ›่ก“่ชž๏ผŒๅช้œ€่ฆ็ซ‹ๅˆปๅŠ ๅ…ฅไปฅไฝฟ็”จ่€…ๅ็จฑ่ˆ‡ๅฏ†็ขผ็‚บๅŸบ็คŽ็š„่บซๅˆ†้ฉ—่ญ‰่ˆ‡ๅฎ‰ๅ…จๆ€ง๏ผŒๅฐฑ็›ดๆŽฅ่ทณๅˆฐๅพŒ็บŒ็ซ ็ฏ€ใ€‚ + +## OAuth2 { #oauth2 } + +OAuth2 ๆ˜ฏไธ€ๅฅ—่ฆ็ฏ„๏ผŒๅฎš็พฉไบ†ๅคš็จฎ่™•็†่บซๅˆ†้ฉ—่ญ‰่ˆ‡ๆŽˆๆฌŠ็š„ๆ–นๆณ•ใ€‚ + +ๅฎƒ็›ธ็•ถ้พๅคง๏ผŒๆถต่“‹่จฑๅคš่ค‡้›œ็š„ไฝฟ็”จๆƒ…ๅขƒใ€‚ + +ๅฎƒไนŸๅŒ…ๅซไฝฟ็”จใ€Œ็ฌฌไธ‰ๆ–นใ€้€ฒ่กŒ่บซๅˆ†้ฉ—่ญ‰็š„ๆ–นๅผใ€‚ + +้€™ๆญฃๆ˜ฏๅ„็จฎใ€Œไฝฟ็”จ Facebookใ€Googleใ€X๏ผˆTwitter๏ผ‰ใ€GitHub ็™ปๅ…ฅใ€็ณป็ตฑๅœจๅบ•ๅฑคๆŽก็”จ็š„ๆฉŸๅˆถใ€‚ + +### OAuth 1 { #oauth-1 } + +้ŽๅŽปๆœ‰ OAuth 1๏ผŒๅ’Œ OAuth2 ้žๅธธไธๅŒ๏ผŒไนŸๆ›ด่ค‡้›œ๏ผŒๅ› ็‚บๅฎƒ็›ดๆŽฅ่ฆ็ฏ„ไบ†ๅฆ‚ไฝ•ๅŠ ๅฏ†้€š่จŠใ€‚ + +ๅฎƒ็พๅœจไธฆไธๆต่กŒ๏ผŒไนŸๅพˆๅฐ‘่ขซไฝฟ็”จใ€‚ + +OAuth2 ไธ่ฆ็ฏ„้€š่จŠๅฆ‚ไฝ•ๅŠ ๅฏ†๏ผŒ่€Œๆ˜ฏๅ‡่จญไฝ ็š„ๆ‡‰็”จๆœƒ้€้Ž HTTPS ๆไพ›ๆœๅ‹™ใ€‚ + +/// tip | ๆ็คบ +ๅœจ้ƒจ็ฝฒ็›ธ้—œ็ซ ็ฏ€ไธญ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จ Traefik ่ˆ‡ Let's Encrypt ๅ…่ฒป่จญๅฎš HTTPSใ€‚ +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect ๆ˜ฏๅŸบๆ–ผ **OAuth2** ็š„ๅฆไธ€ๅฅ—่ฆ็ฏ„ใ€‚ + +ๅฎƒๅชๆ˜ฏๆ“ดๅ……ไบ† OAuth2๏ผŒ้‡ๆธ…ไบ† OAuth2 ไธญ็›ธๅฐๆจก็ณŠ็š„้ƒจไปฝ๏ผŒไปฅๆๅ‡ไบ’้€šๆ€งใ€‚ + +ไพ‹ๅฆ‚๏ผŒGoogle ็™ปๅ…ฅไฝฟ็”จ็š„ๆ˜ฏ OpenID Connect๏ผˆๅ…ถๅบ•ๅฑคไฝฟ็”จ OAuth2๏ผ‰ใ€‚ + +ไฝ† Facebook ็™ปๅ…ฅไธๆ”ฏๆด OpenID Connect๏ผŒๅฎƒๆœ‰่‡ชๅทฑ้ขจๆ ผ็š„ OAuth2ใ€‚ + +### OpenID๏ผˆไธๆ˜ฏใ€ŒOpenID Connectใ€๏ผ‰ { #openid-not-openid-connect } + +้ŽๅŽปไนŸๆœ‰ไธ€ๅ€‹ใ€ŒOpenIDใ€่ฆ็ฏ„ใ€‚ๅฎƒ่ฉฆๅœ–่งฃๆฑบ่ˆ‡ **OpenID Connect** ็›ธๅŒ็š„ๅ•้กŒ๏ผŒไฝ†ไธๆ˜ฏๅปบ็ซ‹ๅœจ OAuth2 ไน‹ไธŠใ€‚ + +ๅ› ๆญค๏ผŒๅฎƒๆ˜ฏไธ€ๅฅ—ๅฎŒๅ…จ้กๅค–ใ€็จ็ซ‹็š„็ณป็ตฑใ€‚ + +ๅฎƒ็พๅœจไธฆไธๆต่กŒ๏ผŒไนŸๅพˆๅฐ‘่ขซไฝฟ็”จใ€‚ + +## OpenAPI { #openapi } + +OpenAPI๏ผˆๅ…ˆๅ‰็จฑ็‚บ Swagger๏ผ‰ๆ˜ฏไธ€ๅฅ—็”จๆ–ผๆง‹ๅปบ API ็š„้–‹ๆ”พ่ฆ็ฏ„๏ผˆ็พ็‚บ Linux ๅŸบ้‡‘ๆœƒ็š„ไธ€้ƒจๅˆ†๏ผ‰ใ€‚ + +**FastAPI** ๅปบ็ซ‹ๅœจ **OpenAPI** ไน‹ไธŠใ€‚ + +้€™ไฝฟๅพ—ๅฎƒ่ƒฝๆไพ›ๅคš็จฎ่‡ชๅ‹•ๅŒ–็š„ไบ’ๅ‹•ๅผๆ–‡ไปถไป‹้ขใ€็จ‹ๅผ็ขผ็”ข็”Ÿ็ญ‰ๅŠŸ่ƒฝใ€‚ + +OpenAPI ๆไพ›ๅฎš็พฉๅคš็จฎๅฎ‰ๅ…จๆ€งใ€Œๆ–นๆกˆใ€ใ€‚ + +้€้Žไฝฟ็”จๅฎƒๅ€‘๏ผŒไฝ ๅฏไปฅๅ–„็”จ้€™ไบ›ๅŸบๆ–ผๆจ™ๆบ–็š„ๅทฅๅ…ท๏ผŒๅŒ…ๆ‹ฌ้€™ไบ›ไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑใ€‚ + +OpenAPI ๅฎš็พฉไบ†ไธ‹ๅˆ—ๅฎ‰ๅ…จๆ€งๆ–นๆกˆ๏ผš + +* `apiKey`๏ผšๆ‡‰็”จ็จ‹ๅผ็‰นๅฎš็š„้‡‘้‘ฐ๏ผŒไพ†ๆบๅฏไปฅๆ˜ฏ๏ผš + * ๆŸฅ่ฉขๅƒๆ•ธใ€‚ + * ๆจ™้ ญ๏ผˆheader๏ผ‰ใ€‚ + * Cookieใ€‚ +* `http`๏ผšๆจ™ๆบ–็š„ HTTP ้ฉ—่ญ‰็ณป็ตฑ๏ผŒๅŒ…ๆ‹ฌ๏ผš + * `bearer`๏ผšไฝฟ็”จ `Authorization` ๆจ™้ ญ๏ผŒๅ€ผ็‚บ `Bearer ` ๅŠ ไธŠไธ€ๅ€‹ tokenใ€‚้€™ๆ˜ฏๅพž OAuth2 ๅปถไผธ่€Œไพ†ใ€‚ + * HTTP Basic ้ฉ—่ญ‰ใ€‚ + * HTTP Digest ็ญ‰ใ€‚ +* `oauth2`๏ผšๆ‰€ๆœ‰ OAuth2 ็š„ๅฎ‰ๅ…จๆ€ง่™•็†ๆ–นๅผ๏ผˆ็จฑ็‚บใ€Œflowsใ€๏ผ‰ใ€‚ + * ๅ…ถไธญๆ•ธๅ€‹ flow ้ฉๅˆ็”จไพ†ๅปบ็ซ‹ OAuth 2.0 ่บซๅˆ†้ฉ—่ญ‰ๆไพ›่€…๏ผˆๅฆ‚ Googleใ€Facebookใ€X๏ผˆTwitter๏ผ‰ใ€GitHub ็ญ‰๏ผ‰๏ผš + * `implicit` + * `clientCredentials` + * `authorizationCode` + * ไฝ†ๆœ‰ไธ€ๅ€‹็‰นๅฎš็š„ flow ๅฏ็›ดๆŽฅๅœจๅŒไธ€ๅ€‹ๆ‡‰็”จไธญ่™•็†่บซๅˆ†้ฉ—่ญ‰๏ผš + * `password`๏ผšๅพŒ็บŒๅนพๅ€‹็ซ ็ฏ€ๆœƒ็คบ็ฏ„้€™ๅ€‹ใ€‚ +* `openIdConnect`๏ผšๆไพ›ไธ€็จฎๆ–นๅผไพ†ๅฎš็พฉๅฆ‚ไฝ•่‡ชๅ‹•็™ผ็พ OAuth2 ็š„่บซๅˆ†้ฉ—่ญ‰่ณ‡่จŠใ€‚ + * ้€™็จฎ่‡ชๅ‹•ๆŽข็ดขๆฉŸๅˆถๅณ็”ฑ OpenID Connect ่ฆ็ฏ„ๅฎš็พฉใ€‚ + +/// tip | ๆ็คบ +ๆ•ดๅˆๅƒ Googleใ€Facebookใ€X๏ผˆTwitter๏ผ‰ใ€GitHub ็ญ‰ๅ…ถไป–่บซๅˆ†้ฉ—่ญ‰/ๆŽˆๆฌŠๆไพ›่€…ไนŸๆ˜ฏๅฏ่กŒ่€Œไธ”็›ธๅฐๅฎนๆ˜“ใ€‚ + +ๆœ€่ค‡้›œ็š„้ƒจๅˆ†ๅ…ถๅฏฆๆ˜ฏๆ‰“้€ ไธ€ๅ€‹้กžไผผ้‚ฃๆจฃ็š„่บซๅˆ†้ฉ—่ญ‰/ๆŽˆๆฌŠๆไพ›่€…๏ผŒไฝ† **FastAPI** ๆไพ›ไบ†ๅทฅๅ…ท๏ผŒ่ƒฝๆ›ฟไฝ ่™•็†็น้‡ๅทฅไฝœ๏ผŒ่ฎ“ไฝ ๆ›ด่ผ•้ฌ†ๅฎŒๆˆใ€‚ +/// + +## **FastAPI** ๅทฅๅ…ท { #fastapi-utilities } + +FastAPI ๅœจ `fastapi.security` ๆจก็ต„ไธญ็‚บไธŠ่ฟฐๅ„็จฎๅฎ‰ๅ…จๆ€งๆ–นๆกˆๆไพ›ไบ†ๅคš็จฎๅทฅๅ…ท๏ผŒ่ฎ“้€™ไบ›ๆฉŸๅˆถๆ›ดๅฎนๆ˜“ไฝฟ็”จใ€‚ + +ๆŽฅไธ‹ไพ†็š„็ซ ็ฏ€ๆœƒ็คบ็ฏ„ๅฆ‚ไฝ•ไฝฟ็”จ้€™ไบ› **FastAPI** ๆไพ›็š„ๅทฅๅ…ท๏ผŒ็‚บไฝ ็š„ API ๅŠ ๅ…ฅๅฎ‰ๅ…จๆ€งใ€‚ + +ไฝ ไนŸๆœƒ็œ‹ๅˆฐๅฎƒๅฆ‚ไฝ•่‡ชๅ‹•ๆ•ดๅˆๅˆฐไบ’ๅ‹•ๅผๆ–‡ไปถ็ณป็ตฑไธญใ€‚ diff --git a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 0000000000..d6761a0051 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# ไฝฟ็”จๅฏ†็ขผ๏ผˆ่ˆ‡้›œๆนŠ๏ผ‰็š„ OAuth2ใ€ไปฅ Bearer ๆญ้… JWT ๆฌŠๆ– { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +็พๅœจๆˆ‘ๅ€‘ๅทฒ็ถ“ๆœ‰ๅฎŒๆ•ด็š„ๅฎ‰ๅ…จๆต็จ‹ไบ†๏ผŒๆŽฅไธ‹ไพ†็”จ JWT ๆฌŠๆ–่ˆ‡ๅฎ‰ๅ…จ็š„ๅฏ†็ขผ้›œๆนŠ๏ผŒ่ฎ“ๆ‡‰็”จ็œŸๆญฃๅฎ‰ๅ…จใ€‚ + +้€™ไปฝ็จ‹ๅผ็ขผๅฏไปฅ็›ดๆŽฅ็”จๅœจไฝ ็š„ๆ‡‰็”จไธญ๏ผŒๆŠŠๅฏ†็ขผ้›œๆนŠๅญ˜้€ฒ่ณ‡ๆ–™ๅบซ็ญ‰็ญ‰ใ€‚ + +ๆˆ‘ๅ€‘ๆœƒๅพžไธŠไธ€็ซ ็š„ๅ…งๅฎน็นผ็บŒๅพ€ไธ‹ๆ“ดๅ……ใ€‚ + +## ้—œๆ–ผ JWT { #about-jwt } + +JWT ็š„ๆ„ๆ€ๆ˜ฏใ€ŒJSON Web Tokensใ€ใ€‚ + +ๅฎƒๆ˜ฏไธ€็จฎๆŠŠ JSON ็‰ฉไปถ็ทจ็ขผๆˆไธ€ๆฎต้•ทไธ”็ทŠๅฏ†๏ผˆๆฒ’ๆœ‰็ฉบ็™ฝ๏ผ‰็š„ๅญ—ไธฒ็š„ๆจ™ๆบ–ใ€‚็œ‹่ตทไพ†ๅƒ้€™ๆจฃ๏ผš + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +ๅฎƒไธๆ˜ฏๅŠ ๅฏ†็š„๏ผŒๆ‰€ไปฅไปปไฝ•ไบบ้ƒฝๅฏไปฅๅพžๅ…งๅฎน้‚„ๅŽŸๅ‡บ่ณ‡่จŠใ€‚ + +ไฝ†ๅฎƒๆ˜ฏ็ฐฝๅ้Ž็š„ใ€‚ๅ› ๆญค็•ถไฝ ๆ”ถๅˆฐไธ€ๅ€‹ไฝ ๆ‰€็ฐฝ็™ผ็š„ๆฌŠๆ–ๆ™‚๏ผŒไฝ ๅฏไปฅ้ฉ—่ญ‰็ขบๅฏฆๆ˜ฏไฝ ็ฐฝ็™ผ็š„ใ€‚ + +ๅฆ‚ๆญคไธ€ไพ†๏ผŒไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹๏ผˆไพ‹ๅฆ‚๏ผ‰ๆœ‰ๆ•ˆๆœŸ็‚บ 1 ้€ฑ็š„ๆฌŠๆ–ใ€‚็•ถไฝฟ็”จ่€…้š”ๅคฉๅธถ่‘—้€™ๅ€‹ๆฌŠๆ–ๅ›žไพ†ๆ™‚๏ผŒไฝ ๅฐฑ็Ÿฅ้“่ฉฒไฝฟ็”จ่€…ไป็„ถ็™ปๅ…ฅๅœจไฝ ็š„็ณป็ตฑไธญใ€‚ + +ไธ€้€ฑๅพŒ๏ผŒๆฌŠๆ–ๆœƒ้ŽๆœŸ๏ผŒไฝฟ็”จ่€…ๅฐฑไธๅ†่ขซๆŽˆๆฌŠ๏ผŒ้œ€่ฆๅ†ๆฌก็™ปๅ…ฅไปฅๅ–ๅพ—ๆ–ฐ็š„ๆฌŠๆ–ใ€‚่€Œๅฆ‚ๆžœไฝฟ็”จ่€…๏ผˆๆˆ–็ฌฌไธ‰ๆ–น๏ผ‰่ฉฆๅœ–ไฟฎๆ”นๆฌŠๆ–ไพ†ๆ”น่ฎŠๆœ‰ๆ•ˆๆœŸ๏ผŒไฝ ไนŸ่ƒฝ็™ผ็พ๏ผŒๅ› ็‚บ็ฐฝๅไธๆœƒ็›ธ็ฌฆใ€‚ + +ๅฆ‚ๆžœไฝ ๆƒณ็Žฉ็Žฉ็œ‹ JWT ๆฌŠๆ–ไธฆไบ†่งฃๅ…ถ้‹ไฝœ๏ผŒ่ซ‹ๅƒ่€ƒ https://jwt.ioใ€‚ + +## ๅฎ‰่ฃ `PyJWT` { #install-pyjwt } + +ๆˆ‘ๅ€‘้œ€่ฆๅฎ‰่ฃ `PyJWT` ๆ‰่ƒฝๅœจ Python ไธญ็”ข็”Ÿ่ˆ‡้ฉ—่ญ‰ JWT ๆฌŠๆ–ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅฎ‰่ฃ `pyjwt`๏ผš + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info | ่ชชๆ˜Ž + +ๅฆ‚ๆžœไฝ ๆ‰“็ฎ—ไฝฟ็”จๅƒ RSA ๆˆ– ECDSA ้€™้กž็š„ๆ•ธไฝ็ฐฝ็ซ ๆผ”็ฎ—ๆณ•๏ผŒๆ‡‰่ฉฒๅฎ‰่ฃๅธถๆœ‰ๅŠ ๅฏ†ๅ‡ฝๅผๅบซ็›ธไพ็š„ `pyjwt[crypto]`ใ€‚ + +ๆ›ดๅคšๅ…งๅฎนๅฏๅƒ่€ƒ PyJWT ๅฎ‰่ฃๆ–‡ไปถใ€‚ + +/// + +## ๅฏ†็ขผ้›œๆนŠ { #password-hashing } + +ใ€Œ้›œๆนŠใ€ๆ˜ฏๆŒ‡ๆŠŠๆŸไบ›ๅ…งๅฎน๏ผˆๆญค่™•็‚บๅฏ†็ขผ๏ผ‰่ฝ‰ๆ›ๆˆไธ€ไธฒ็œ‹่ตทไพ†ๅƒไบ‚็ขผ็š„ไฝๅ…ƒ็ต„ๅบๅˆ—๏ผˆๅ…ถๅฏฆๅฐฑๆ˜ฏๅญ—ไธฒ๏ผ‰ใ€‚ + +ๆฏ็•ถไฝ ่ผธๅ…ฅๅฎŒๅ…จ็›ธๅŒ็š„ๅ…งๅฎน๏ผˆๅฎŒๅ…จ็›ธๅŒ็š„ๅฏ†็ขผ๏ผ‰๏ผŒๅฐฑๆœƒๅพ—ๅˆฐๅฎŒๅ…จ็›ธๅŒ็š„ไบ‚็ขผใ€‚ + +ไฝ†ไฝ ็„กๆณ•ๅพž้€™ไธฒไบ‚็ขผๅ†ๅๆŽจๅ›žๅŽŸๆœฌ็š„ๅฏ†็ขผใ€‚ + +### ็‚บไป€้บผ่ฆ็”จๅฏ†็ขผ้›œๆนŠ { #why-use-password-hashing } + +ๅฆ‚ๆžœไฝ ็š„่ณ‡ๆ–™ๅบซ่ขซๅทไบ†๏ผŒ็ซŠ่ณŠๆ‹ฟๅˆฐ็š„ไธๆ˜ฏไฝฟ็”จ่€…็š„ๆ˜Žๆ–‡ๅฏ†็ขผ๏ผŒ่€Œๅชๆ˜ฏ้›œๆนŠๅ€ผใ€‚ + +ๅ› ๆญค๏ผŒ็ซŠ่ณŠ็„กๆณ•็›ดๆŽฅๆ‹ฟ่ฉฒๅฏ†็ขผๅŽปๅ˜—่ฉฆ็™ปๅ…ฅๅ…ถไป–็ณป็ตฑ๏ผˆ็”ฑๆ–ผ่จฑๅคšไฝฟ็”จ่€…ๅœจๅ„่™•้ƒฝ็”จๅŒไธ€็ต„ๅฏ†็ขผ๏ผŒ้€™ๆœƒๅพˆๅฑ้šช๏ผ‰ใ€‚ + +## ๅฎ‰่ฃ `pwdlib` { #install-pwdlib } + +pwdlib ๆ˜ฏไธ€ๅ€‹ๅพˆๆฃ’็š„ Python ๅฅ—ไปถ๏ผŒ็”จไพ†่™•็†ๅฏ†็ขผ้›œๆนŠใ€‚ + +ๅฎƒๆ”ฏๆดๅคš็จฎๅฎ‰ๅ…จ็š„้›œๆนŠๆผ”็ฎ—ๆณ•่ˆ‡็›ธ้—œๅทฅๅ…ทใ€‚ + +ๅปบ่ญฐไฝฟ็”จ็š„ๆผ”็ฎ—ๆณ•ๆ˜ฏใ€ŒArgon2ใ€ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒไปฅ Argon2 ๆ”ฏๆดๅฎ‰่ฃ pwdlib๏ผš + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | ๆ็คบ + +ไฝฟ็”จ `pwdlib`๏ผŒไฝ ็”š่‡ณๅฏไปฅๆŠŠๅฎƒ่จญๅฎš็‚บ่ƒฝ่ฎ€ๅ–็”ฑ **Django**ใ€**Flask** ็š„ๅฎ‰ๅ…จๅค–ๆŽ›ๆˆ–ๅ…ถไป–่จฑๅคš็ณป็ตฑๆ‰€ๅปบ็ซ‹็š„ๅฏ†็ขผใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ่ฎ“ Django ๆ‡‰็”จ่ˆ‡ FastAPI ๆ‡‰็”จๅ…ฑ็”จๅŒไธ€ๅ€‹่ณ‡ๆ–™ๅบซไธญ็š„่ณ‡ๆ–™ใ€‚ๆˆ–่€…้€ๆญฅ้ท็งปไธ€ๅ€‹ Django ๆ‡‰็”จ๏ผŒๅŒๆจฃไฝฟ็”จ่ฉฒ่ณ‡ๆ–™ๅบซใ€‚ + +่€Œไฝ ็š„ไฝฟ็”จ่€…ๅฏไปฅๅŒๆ™‚ๅพž Django ๆ‡‰็”จๆˆ– **FastAPI** ๆ‡‰็”จ็™ปๅ…ฅใ€‚ + +/// + +## ้›œๆนŠ่ˆ‡้ฉ—่ญ‰ๅฏ†็ขผ { #hash-and-verify-the-passwords } + +ๅพž `pwdlib` ๅŒฏๅ…ฅๆˆ‘ๅ€‘้œ€่ฆ็š„ๅทฅๅ…ทใ€‚ + +็”จๅปบ่ญฐ่จญๅฎšๅปบ็ซ‹ไธ€ๅ€‹ PasswordHash ๅŸท่กŒๅ€‹้ซ”โ€”โ€”ๅฎƒๆœƒ็”จๆ–ผ้›œๆนŠ่ˆ‡้ฉ—่ญ‰ๅฏ†็ขผใ€‚ + +/// tip | ๆ็คบ + +pwdlib ไนŸๆ”ฏๆด bcrypt ้›œๆนŠๆผ”็ฎ—ๆณ•๏ผŒไฝ†ไธๅŒ…ๅซๅ‚ณ็ตฑ๏ผˆlegacy๏ผ‰ๆผ”็ฎ—ๆณ•โ€”โ€”่‹ฅ้œ€่ฆ่™•็†้Žๆ™‚็š„้›œๆนŠ๏ผŒๅปบ่ญฐไฝฟ็”จ passlib ๅ‡ฝๅผๅบซใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ็”จๅฎƒ่ฎ€ๅ–ไธฆ้ฉ—่ญ‰็”ฑๅ…ถไป–็ณป็ตฑ๏ผˆๅฆ‚ Django๏ผ‰็”ข็”Ÿ็š„ๅฏ†็ขผ๏ผŒไฝ†้‡ๅฐไปปไฝ•ๆ–ฐๅฏ†็ขผๅ‰‡ๆ”น็”จๅƒ Argon2 ๆˆ– Bcrypt ้€™้กž็š„ไธๅŒๆผ”็ฎ—ๆณ•ไพ†้›œๆนŠใ€‚ + +ไธฆๅŒๆ™‚่ˆ‡ๆ‰€ๆœ‰้€™ไบ›ๆ ผๅผ็›ธๅฎนใ€‚ + +/// + +ๅปบ็ซ‹ไธ€ๅ€‹ๅทฅๅ…ทๅ‡ฝๅผไพ†้›œๆนŠไฝฟ็”จ่€…้€ไพ†็š„ๅฏ†็ขผใ€‚ + +ๅ†ๅปบ็ซ‹ๅฆไธ€ๅ€‹ๅทฅๅ…ทไพ†้ฉ—่ญ‰ๆ”ถๅˆฐ็š„ๅฏ†็ขผๆ˜ฏๅฆ็ฌฆๅˆๅทฒๅ„ฒๅญ˜็š„้›œๆนŠใ€‚ + +ไปฅๅŠๅฆไธ€ๅ€‹็”จๆ–ผ้ฉ—่ญ‰ไธฆๅ›žๅ‚ณไฝฟ็”จ่€…็š„ๅทฅๅ…ทใ€‚ + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +็•ถไปฅไธๅญ˜ๅœจๆ–ผ่ณ‡ๆ–™ๅบซ็š„ไฝฟ็”จ่€…ๅ็จฑๅ‘ผๅซ `authenticate_user` ๆ™‚๏ผŒๆˆ‘ๅ€‘ไป็„ถๆœƒๆ‹ฟไธ€ๅ€‹ๅ‡็š„้›œๆนŠๅŽป่ท‘ไธ€ๆฌก `verify_password`ใ€‚ + +้€™ๅฏ็ขบไฟ็„ก่ซ–ไฝฟ็”จ่€…ๅ็จฑๆ˜ฏๅฆๆœ‰ๆ•ˆ๏ผŒ็ซฏ้ปž็š„ๅ›žๆ‡‰ๆ™‚้–“้ƒฝๅคง่‡ด็›ธๅŒ๏ผŒ้ฟๅ…ๅฏ็”จไพ†ๆžš่ˆ‰ๆ—ขๆœ‰ไฝฟ็”จ่€…ๅ็จฑ็š„ใ€Œ่จˆๆ™‚ๆ”ปๆ“Šใ€๏ผˆtiming attacks๏ผ‰ใ€‚ + +/// note | ๆณจๆ„ + +ๅฆ‚ๆžœไฝ ๆŸฅ็œ‹ๆ–ฐ็š„๏ผˆๅ‡๏ผ‰่ณ‡ๆ–™ๅบซ `fake_users_db`๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ้›œๆนŠๅพŒ็š„ๅฏ†็ขผ็พๅœจ้•ท้€™ๆจฃ๏ผš`"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`ใ€‚ + +/// + +## ่™•็† JWT ๆฌŠๆ– { #handle-jwt-tokens } + +ๅŒฏๅ…ฅๅ‰›ๅฎ‰่ฃ็š„ๆจก็ต„ใ€‚ + +ๅปบ็ซ‹ไธ€ๆŠŠ้šจๆฉŸ็š„ๅฏ†้‘ฐ๏ผˆsecret key๏ผ‰็”จๆ–ผ็ฐฝ็ฝฒ JWT ๆฌŠๆ–ใ€‚ + +่ฆ็”ข็”Ÿๅฎ‰ๅ…จ็š„้šจๆฉŸๅฏ†้‘ฐๅฏไฝฟ็”จไปฅไธ‹ๆŒ‡ไปค๏ผš + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +ๅฐ‡่ผธๅ‡บ็š„ๅ€ผ่ค‡่ฃฝๅˆฐ่ฎŠๆ•ธ `SECRET_KEY`๏ผˆไธ่ฆไฝฟ็”จ็ฏ„ไพ‹ไธญ็š„้‚ฃไธ€็ต„๏ผ‰ใ€‚ + +ๅปบ็ซ‹่ฎŠๆ•ธ `ALGORITHM` ๆŒ‡ๅฎš็”จไพ†็ฐฝ็ฝฒ JWT ๆฌŠๆ–็š„ๆผ”็ฎ—ๆณ•๏ผŒ่จญ็‚บ `"HS256"`ใ€‚ + +ๅปบ็ซ‹ไธ€ๅ€‹ๆฌŠๆ–ๆœ‰ๆ•ˆๆœŸ็š„่ฎŠๆ•ธใ€‚ + +ๅฎš็พฉไธ€ๅ€‹็”จๆ–ผๆฌŠๆ–็ซฏ้ปžๅ›žๆ‡‰็š„ Pydantic Modelใ€‚ + +ๅปบ็ซ‹ไธ€ๅ€‹ๅทฅๅ…ทๅ‡ฝๅผไพ†็”ข็”Ÿๆ–ฐ็š„ access tokenใ€‚ + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## ๆ›ดๆ–ฐ็›ธไพ้ …็›ฎ { #update-the-dependencies } + +ๆ›ดๆ–ฐ `get_current_user`๏ผŒ่ฎ“ๅฎƒไปๆŽฅๆ”ถ็›ธๅŒ็š„ๆฌŠๆ–๏ผŒไฝ†้€™ๆฌกๆ”น็”จ JWT ๆฌŠๆ–ใ€‚ + +่งฃ็ขผๆ”ถๅˆฐ็š„ๆฌŠๆ–ใ€้ฉ—่ญ‰ๅฎƒ๏ผŒไธฆๅ›žๅ‚ณ็›ฎๅ‰็š„ไฝฟ็”จ่€…ใ€‚ + +ๅฆ‚ๆžœๆฌŠๆ–็„กๆ•ˆ๏ผŒ็ซ‹ๅณๅ›žๅ‚ณไธ€ๅ€‹ HTTP ้Œฏ่ชคใ€‚ + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## ๆ›ดๆ–ฐ `/token` ่ทฏๅพ‘ๆ“ไฝœ { #update-the-token-path-operation } + +็”จๆฌŠๆ–ๆœ‰ๆ•ˆๆœŸๅปบ็ซ‹ไธ€ๅ€‹ `timedelta`ใ€‚ + +ๅปบ็ซ‹็œŸๆญฃ็š„ JWT access token ไธฆๅ›žๅ‚ณๅฎƒใ€‚ + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### ้—œๆ–ผ JWTใ€Œไธป้ซ”ใ€`sub` ็š„ๆŠ€่ก“็ดฐ็ฏ€ { #technical-details-about-the-jwt-subject-sub } + +JWT ่ฆ็ฏ„่ชชๆœ‰ๅ€‹้ต `sub`๏ผŒไปฃ่กจๆฌŠๆ–็š„ไธป้ซ”๏ผˆsubject๏ผ‰ใ€‚ + +ไฝฟ็”จๅฎƒๆ˜ฏๅฏ้ธ็š„๏ผŒไฝ†้€šๅธธๆœƒๆŠŠไฝฟ็”จ่€…็š„่ญ˜ๅˆฅ่ณ‡่จŠๆ”พๅœจ้€™่ฃก๏ผŒๆ‰€ไปฅๆˆ‘ๅ€‘ๅœจๆญคๆŽก็”จใ€‚ + +JWT ้™คไบ†็”จไพ†่ญ˜ๅˆฅไฝฟ็”จ่€…ไธฆๅ…่จฑไป–็›ดๆŽฅๅฐไฝ ็š„ API ๅŸท่กŒๆ“ไฝœๅค–๏ผŒไนŸๅฏ็”จๆ–ผๅ…ถไป–็”จ้€”ใ€‚ + +ไพ‹ๅฆ‚๏ผŒไฝ ๅฏไปฅ่ญ˜ๅˆฅไธ€ๅฐใ€Œ่ปŠใ€ๆˆ–ไธ€็ฏ‡ใ€Œ้ƒจ่ฝๆ ผๆ–‡็ซ ใ€ใ€‚ + +ๆŽฅ่‘—ๅฏไปฅๆ›ฟ่ฉฒๅฏฆ้ซ”ๅŠ ไธŠๆฌŠ้™๏ผŒๅฆ‚ใ€Œdriveใ€๏ผˆๅฐ่ปŠ่€Œ่จ€๏ผ‰ๆˆ–ใ€Œeditใ€๏ผˆๅฐๆ–‡็ซ ่€Œ่จ€๏ผ‰ใ€‚ + +็„ถๅพŒไฝ ๅฏไปฅๆŠŠ่ฉฒ JWT ๆฌŠๆ–ไบค็ตฆๆŸๅ€‹ไฝฟ็”จ่€…๏ผˆๆˆ–ๆฉŸๅ™จไบบ๏ผ‰๏ผŒไป–ๅ€‘ๅฐฑ่ƒฝ็”จๅฎƒไพ†ๅŸท่กŒ้‚ฃไบ›ๅ‹•ไฝœ๏ผˆ้–‹่ปŠใ€ๆˆ–็ทจ่ผฏๆ–‡็ซ ๏ผ‰๏ผŒ็”š่‡ณไธ้œ€่ฆๆœ‰ๅธณ่™Ÿ๏ผŒๅช่ฆไฝฟ็”จไฝ ็š„ API ๆ‰€็”ข็”Ÿ็š„ JWT ๆฌŠๆ–ๅณๅฏใ€‚ + +ๅŸบๆ–ผ้€™ไบ›ๆฆ‚ๅฟต๏ผŒJWT ่ƒฝ็”จๅœจๆ›ด่ค‡้›œ็š„ๆƒ…ๅขƒไธญใ€‚ + +ๅœจ้‚ฃไบ›ๆƒ…ๅขƒ่ฃก๏ผŒๆ•ธๅ€‹ๅฏฆ้ซ”ๅฏ่ƒฝๆ“ๆœ‰็›ธๅŒ็š„ ID๏ผŒไพ‹ๅฆ‚ `foo`๏ผˆไฝฟ็”จ่€… `foo`ใ€่ปŠ `foo`ใ€ไปฅๅŠๆ–‡็ซ  `foo`๏ผ‰ใ€‚ + +็‚บไบ†้ฟๅ… ID ่ก็ช๏ผŒๅœจ็‚บไฝฟ็”จ่€…ๅปบ็ซ‹ JWT ๆฌŠๆ–ๆ™‚๏ผŒไฝ ๅฏไปฅๆ›ฟ `sub` ็š„ๅ€ผๅŠ ไธŠๅ‰็ถด๏ผŒไพ‹ๅฆ‚ `username:`ใ€‚ๅ› ๆญคๅœจ้€™ๅ€‹ไพ‹ๅญไธญ๏ผŒ`sub` ็š„ๅ€ผๅฏไปฅๆ˜ฏ๏ผš`username:johndoe`ใ€‚ + +่ฆ่จ˜ไฝ็š„้‡่ฆ้ปžๆ˜ฏ๏ผš`sub` ๅฟ…้ ˆๆ˜ฏๅœจๆ•ดๅ€‹ๆ‡‰็”จไธญๅ”ฏไธ€็š„่ญ˜ๅˆฅๅญ๏ผŒไธฆไธ”ๅฟ…้ ˆๆ˜ฏๅญ—ไธฒใ€‚ + +## ่ฉฆ่ฉฆ็œ‹ { #check-it } + +ๅ•Ÿๅ‹•ไผบๆœๅ™จไธฆๅ‰ๅพ€ๆ–‡ไปถ้ ๏ผšhttp://127.0.0.1:8000/docsใ€‚ + +ไฝ ๆœƒ็œ‹ๅˆฐ้€™ๆจฃ็š„ไป‹้ข๏ผš + + + +็”จๅ’Œๅ…ˆๅ‰็›ธๅŒ็š„ๆ–นๅผๆŽˆๆฌŠๆ‡‰็”จใ€‚ + +ไฝฟ็”จไธ‹ๅˆ—่ช่ญ‰่ณ‡่จŠ๏ผš + +Username: `johndoe` +Password: `secret` + +/// check | ๆชขๆŸฅ + +ๆณจๆ„ๅœจ็จ‹ๅผ็ขผไธญๅฎŒๅ…จๆฒ’ๆœ‰ๆ˜Žๆ–‡ๅฏ†็ขผใ€Œ`secret`ใ€๏ผŒๆˆ‘ๅ€‘ๅชๆœ‰้›œๆนŠๅพŒ็š„็‰ˆๆœฌใ€‚ + +/// + + + +ๅ‘ผๅซ็ซฏ้ปž `/users/me/`๏ผŒไฝ ๆœƒๅพ—ๅˆฐ้กžไผผ้€™ๆจฃ็š„ๅ›žๆ‡‰๏ผš + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +ๅฆ‚ๆžœไฝ ๆ‰“้–‹้–‹็™ผ่€…ๅทฅๅ…ท๏ผŒๅฏไปฅ็œ‹ๅˆฐ้€ๅ‡บ็š„่ณ‡ๆ–™ๅชๅŒ…ๅซๆฌŠๆ–๏ผ›ๅฏ†็ขผๅชๆœƒๅœจ็ฌฌไธ€ๆฌก่ซ‹ๆฑ‚๏ผˆ็”จไพ†้ฉ—่ญ‰ไฝฟ็”จ่€…ไธฆๅ–ๅพ— access token๏ผ‰ๆ™‚้€ๅ‡บ๏ผŒไน‹ๅพŒๅฐฑไธๆœƒๅ†้€๏ผš + + + +/// note | ๆณจๆ„ + +็•™ๆ„ๆจ™้ ญ `Authorization`๏ผŒๅ…ถๅ€ผๆ˜ฏไปฅ `Bearer ` ้–‹้ ญใ€‚ + +/// + +## ้€ฒ้šŽ็”จๆณ•๏ผš`scopes` { #advanced-usage-with-scopes } + +OAuth2 ๆœ‰ใ€Œscopesใ€็š„ๆฆ‚ๅฟตใ€‚ + +ไฝ ๅฏไปฅ็”จๅฎƒๅ€‘ๆ›ฟ JWT ๆฌŠๆ–ๅŠ ไธŠไธ€็ต„็‰นๅฎš็š„ๆฌŠ้™ใ€‚ + +ๆŽฅ่‘—ไฝ ๅฏไปฅๆŠŠ้€™ๅ€‹ๆฌŠๆ–็›ดๆŽฅไบค็ตฆๆŸๅ€‹ไฝฟ็”จ่€…ๆˆ–็ฌฌไธ‰ๆ–น๏ผŒ่ฎ“ไป–ๅ€‘ๅœจไธ€็ต„ๅ—้™ๆขไปถไธ‹่ˆ‡ไฝ ็š„ API ไบ’ๅ‹•ใ€‚ + +ไฝ ๅฏไปฅๅœจไน‹ๅพŒ็š„ใ€Œ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—ใ€ๅญธๅˆฐๅฆ‚ไฝ•ไฝฟ็”จๅฎƒๅ€‘๏ผŒไปฅๅŠๅฎƒๅ€‘ๅฆ‚ไฝ•ๆ•ดๅˆ้€ฒ **FastAPI**ใ€‚ + +## ๅฐ็ต { #recap } + +ไพ็…งไฝ ็›ฎๅ‰ๅญธๅˆฐ็š„ๅ…งๅฎน๏ผŒไฝ ๅฏไปฅ็”จ OAuth2 ่ˆ‡ JWT ็ญ‰ๆจ™ๆบ–๏ผŒ่จญๅฎšไธ€ๅ€‹ๅฎ‰ๅ…จ็š„ **FastAPI** ๆ‡‰็”จใ€‚ + +ๅœจๅนพไนŽไปปไฝ•ๆก†ๆžถไธญ๏ผŒๅฎ‰ๅ…จๆ€ง่™•็†้ƒฝๆœƒๅพˆๅฟซ่ฎŠๅพ—็›ธ็•ถ่ค‡้›œใ€‚ + +่จฑๅคš่ƒฝๅคงๅน…็ฐกๅŒ–ๅทฅไฝœ็š„ๅฅ—ไปถ๏ผŒๅพ€ๅพ€ๅฟ…้ ˆๅœจ่ณ‡ๆ–™ๆจกๅž‹ใ€่ณ‡ๆ–™ๅบซ่ˆ‡ๅฏ็”จๅŠŸ่ƒฝไธŠๅšๅ‡บๅพˆๅคšๅ–ๆจใ€‚่€Œๆœ‰ไบ›้Žๅบฆ็ฐกๅŒ–็š„ๅฅ—ไปถๅบ•ๅฑคๅ…ถๅฏฆๅญ˜ๅœจๅฎ‰ๅ…จๅผฑ้ปžใ€‚ + +--- + +**FastAPI** ไธๆœƒๅœจไปปไฝ•่ณ‡ๆ–™ๅบซใ€่ณ‡ๆ–™ๆจกๅž‹ๆˆ–ๅทฅๅ…ทไธŠๅšๅฆฅๅ”ใ€‚ + +ๅฎƒ็ตฆไฝ ๅฎŒๅ…จ็š„ๅฝˆๆ€ง๏ผŒ่ฎ“ไฝ ๆŒ‘้ธๆœ€้ฉๅˆไฝ ๅฐˆๆกˆ็š„็ต„ๅˆใ€‚ + +่€Œไธ”ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ่จฑๅคš็ถญ่ญท่‰ฏๅฅฝไธ”่ขซๅปฃๆณ›ๆŽก็”จ็š„ๅฅ—ไปถ๏ผŒไพ‹ๅฆ‚ `pwdlib` ่ˆ‡ `PyJWT`๏ผŒๅ› ็‚บ **FastAPI** ไธ้œ€่ฆไปปไฝ•่ค‡้›œๆฉŸๅˆถๅฐฑ่ƒฝๆ•ดๅˆๅค–้ƒจๅฅ—ไปถใ€‚ + +ๅŒๆ™‚ๅฎƒไนŸๆไพ›ๅทฅๅ…ทไพ†ๅœจไธ็Šง็‰ฒๅฝˆๆ€งใ€็ฉฉๅฅๆˆ–ๅฎ‰ๅ…จ็š„ๅ‰ๆไธ‹๏ผŒ็›กๅฏ่ƒฝๅœฐ็ฐกๅŒ–ๆต็จ‹ใ€‚ + +ไฝ ๅฏไปฅ็”จ็›ธๅฐ็ฐกๅ–ฎ็š„ๆ–นๅผไฝฟ็”จไธฆๅฏฆไฝœๅƒ OAuth2 ้€™ๆจฃ็š„ๅฎ‰ๅ…จๆจ™ๆบ–ๅ”ๅฎšใ€‚ + +ไฝ ๅฏไปฅๅœจใ€Œ้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—ใ€้€ฒไธ€ๆญฅไบ†่งฃๅฆ‚ไฝ•ไฝฟ็”จ OAuth2 ็š„ใ€Œscopesใ€๏ผŒไปฅๅฏฆไฝœๆ›ด็ดฐ็ทป็š„ๆฌŠ้™็ณป็ตฑ๏ผŒไธฆ้ตๅพช็›ธๅŒ็š„ๆจ™ๆบ–ใ€‚ๅธถๆœ‰ scopes ็š„ OAuth2 ๆ˜ฏ่จฑๅคšๅคงๅž‹่บซไปฝ้ฉ—่ญ‰ไพ›ๆ‡‰ๅ•†๏ผˆๅฆ‚ Facebookใ€Googleใ€GitHubใ€Microsoftใ€X๏ผˆTwitter๏ผ‰็ญ‰๏ผ‰็”จไพ†ๆŽˆๆฌŠ็ฌฌไธ‰ๆ–นๆ‡‰็”จไปฃ่กจๅ…ถไฝฟ็”จ่€…่ˆ‡ๅ…ถ API ไบ’ๅ‹•็š„ๆฉŸๅˆถใ€‚ diff --git a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000..3b9aae3416 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# ็ฐกๆ˜“ OAuth2๏ผšPassword ่ˆ‡ Bearer { #simple-oauth2-with-password-and-bearer } + +็พๅœจๅพžไธŠไธ€็ซ ๅปถไผธ๏ผŒ่ฃœไธŠ็ผบๅฐ‘็š„้ƒจๅˆ†๏ผŒๅฎŒๆˆๆ•ดๅ€‹ๅฎ‰ๅ…จๆต็จ‹ใ€‚ + +## ๅ–ๅพ— `username` ่ˆ‡ `password` { #get-the-username-and-password } + +ๆˆ‘ๅ€‘่ฆไฝฟ็”จ **FastAPI** ๆไพ›็š„ๅฎ‰ๅ…จๆ€งๅทฅๅ…ทไพ†ๅ–ๅพ— `username` ่ˆ‡ `password`ใ€‚ + +OAuth2 ่ฆ็ฏ„ไธญ๏ผŒ็•ถไฝฟ็”จใ€Œpassword flowใ€๏ผˆๆˆ‘ๅ€‘็พๅœจไฝฟ็”จ็š„๏ผ‰ๆ™‚๏ผŒ็”จๆˆถ็ซฏ๏ผไฝฟ็”จ่€…ๅฟ…้ ˆไปฅ่กจๅ–ฎ่ณ‡ๆ–™้€ๅ‡บ `username` ่ˆ‡ `password` ๆฌ„ไฝใ€‚ + +่€Œไธ”่ฆ็ฏ„่ฆๆฑ‚ๆฌ„ไฝๅ็จฑๅฟ…้ ˆๅฐฑๆ˜ฏ้€™ๅ…ฉๅ€‹๏ผŒๆ‰€ไปฅๅƒๆ˜ฏ `user-name` ๆˆ– `email` ้ƒฝไธ่กŒใ€‚ + +ไฝ†ๅˆฅๆ“”ๅฟƒ๏ผŒไฝ ๅœจๅ‰็ซฏ่ฆๆ€Ž้บผๅ‘ˆ็พ็ตฆๆœ€็ต‚ไฝฟ็”จ่€…้ƒฝๅฏไปฅใ€‚ + +่€Œไฝ ็š„่ณ‡ๆ–™ๅบซๆจกๅž‹ไนŸๅฏไปฅไฝฟ็”จไปปไฝ•ไฝ ๆƒณ่ฆ็š„ๆฌ„ไฝๅ็จฑใ€‚ + +ไธ้Žๅœจ็™ปๅ…ฅ็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operation๏ผ‰่ฃก๏ผŒๆˆ‘ๅ€‘้œ€่ฆไฝฟ็”จ้€™ไบ›ๅ็จฑ๏ผŒๆ‰่ƒฝ็ฌฆๅˆ่ฆ็ฏ„๏ผˆไพ‹ๅฆ‚ๆ‰่ƒฝไฝฟ็”จๆ•ดๅˆ็š„ API ๆ–‡ไปถ็ณป็ตฑ๏ผ‰ใ€‚ + +่ฆ็ฏ„ไนŸ่ชชๆ˜Ž `username` ่ˆ‡ `password` ๅฟ…้ ˆไปฅ่กจๅ–ฎ่ณ‡ๆ–™ๅ‚ณ้€๏ผˆไนŸๅฐฑๆ˜ฏ้€™่ฃกไธ่ƒฝ็”จ JSON๏ผ‰ใ€‚ + +### `scope` { #scope } + +่ฆ็ฏ„ไนŸ่ชช็”จๆˆถ็ซฏๅฏไปฅๅ†้€ไธ€ๅ€‹่กจๅ–ฎๆฌ„ไฝใ€Œ`scope`ใ€ใ€‚ + +ๆฌ„ไฝๅ็จฑๆ˜ฏๅ–ฎๆ•ธ็š„ `scope`๏ผŒไฝ†ๅฏฆ้š›ไธŠๆ˜ฏ็”ฑๅคšๅ€‹ไปฅ็ฉบ็™ฝๅˆ†้š”็š„ใ€Œscopesใ€็ต„ๆˆ็š„ไธ€้•ทไธฒๅญ—ไธฒใ€‚ + +ๆฏๅ€‹ใ€Œscopeใ€ๅฐฑๆ˜ฏไธ€ๅ€‹๏ผˆไธๅซ็ฉบ็™ฝ็š„๏ผ‰ๅญ—ไธฒใ€‚ + +ๅฎƒๅ€‘้€šๅธธ็”จไพ†ๅฎฃๅ‘Š็‰นๅฎš็š„ๆฌŠ้™๏ผŒไพ‹ๅฆ‚๏ผš + +- `users:read` ๆˆ– `users:write` ๆ˜ฏๅธธ่ฆ‹็š„ไพ‹ๅญ +- `instagram_basic` ็”จๅœจ Facebook / Instagram +- `https://www.googleapis.com/auth/drive` ็”จๅœจ Google + +/// info + +ๅœจ OAuth2 ่ฃก๏ผŒใ€Œscopeใ€ๅชๆ˜ฏ็”จไพ†ๅฎฃๅ‘Š็‰นๅฎšๆ‰€้œ€ๆฌŠ้™็š„ไธ€ๅ€‹ๅญ—ไธฒใ€‚ + +ไธ่ซ–่ฃก้ขๆ˜ฏๅฆๅŒ…ๅซๅƒ `:` ไน‹้กž็š„ๅญ—ๅ…ƒ๏ผŒๆˆ–ๆ˜ฏๅฆๆ˜ฏไธ€ๅ€‹ URL๏ผŒ้ƒฝๆฒ’ๅทฎใ€‚ + +้‚ฃไบ›้ƒฝๆ˜ฏๅฏฆไฝœ็ดฐ็ฏ€ใ€‚ + +ๅฐ OAuth2 ่€Œ่จ€๏ผŒๅฎƒๅ€‘ๅฐฑๆ˜ฏๅญ—ไธฒ่€Œๅทฒใ€‚ + +/// + +## ๅ–ๅพ— `username` ่ˆ‡ `password` ็š„็จ‹ๅผ็ขผ { #code-to-get-the-username-and-password } + +็พๅœจ็”จ **FastAPI** ๆไพ›็š„ๅทฅๅ…ทไพ†่™•็†ใ€‚ + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +ๅ…ˆๅŒฏๅ…ฅ `OAuth2PasswordRequestForm`๏ผŒไธฆๅœจ `/token` ็š„่ทฏๅพ‘ๆ“ไฝœไธญ๏ผŒๆญ้… `Depends` ็•ถไฝœไพ่ณดไฝฟ็”จ๏ผš + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` ๆ˜ฏไธ€ๅ€‹้กžๅˆฅๅž‹ไพ่ณด๏ผŒๅฎƒๅฎฃๅ‘Šไบ†ไธ€ๅ€‹่กจๅ–ฎๆœฌๆ–‡๏ผŒๅŒ…ๅซ๏ผš + +- `username` +- `password` +- ๅฏ้ธ็š„ `scope` ๆฌ„ไฝ๏ผŒๅ…งๅฎนๆ˜ฏไธ€ๅ€‹็”ฑ็ฉบ็™ฝๅˆ†้š”็š„้•ทๅญ—ไธฒ +- ๅฏ้ธ็š„ `grant_type` + +/// tip + +ไพ่ฆ็ฏ„๏ผŒๅฏฆ้š›ไธŠ้œ€่ฆไธ€ๅ€‹ `grant_type` ๆฌ„ไฝไธ”ๅ›บๅฎšๅ€ผ็‚บ `password`๏ผŒไฝ† `OAuth2PasswordRequestForm` ไธฆไธๆœƒๅผทๅˆถๆชขๆŸฅใ€‚ + +ๅฆ‚ๆžœไฝ ้œ€่ฆๅผทๅˆถๆชขๆŸฅ๏ผŒ่ซ‹ๆ”น็”จ `OAuth2PasswordRequestFormStrict` ๅ–ไปฃ `OAuth2PasswordRequestForm`ใ€‚ + +/// + +- ๅฏ้ธ็š„ `client_id`๏ผˆๆœฌไพ‹ไธ้œ€่ฆ๏ผ‰ +- ๅฏ้ธ็š„ `client_secret`๏ผˆๆœฌไพ‹ไธ้œ€่ฆ๏ผ‰ + +/// info + +`OAuth2PasswordRequestForm` ไธฆไธๆ˜ฏๅƒ `OAuth2PasswordBearer` ้‚ฃๆจฃๅฐ **FastAPI** ไพ†่ชช็š„็‰นๆฎŠ้กžๅˆฅใ€‚ + +`OAuth2PasswordBearer` ๆœƒ่ฎ“ **FastAPI** ็Ÿฅ้“ๅฎƒๆ˜ฏไธ€ๅ€‹ security scheme๏ผŒๅ› ๆญคๆœƒไปฅ้‚ฃ็จฎๆ–นๅผๅŠ ๅ…ฅ OpenAPIใ€‚ + +ไฝ† `OAuth2PasswordRequestForm` ๅชๆ˜ฏไฝ ไนŸๅฏไปฅ่‡ชๅทฑๆ’ฐๅฏซ็š„ไธ€ๅ€‹้กžๅˆฅๅž‹ไพ่ณด๏ผŒๆˆ–ๆ˜ฏไฝ ไนŸๅฏไปฅ็›ดๆŽฅๅฎฃๅ‘Š `Form` ๅƒๆ•ธใ€‚ + +ๅชๆ˜ฏๅ› ็‚บ้€™ๆ˜ฏๅพˆๅธธ่ฆ‹็š„็”จไพ‹๏ผŒๆ‰€ไปฅ **FastAPI** ็›ดๆŽฅๅ…งๅปบๆไพ›๏ผŒ่ฎ“ไบ‹ๆƒ…ๆ›ด็ฐกๅ–ฎใ€‚ + +/// + +### ไฝฟ็”จ่กจๅ–ฎ่ณ‡ๆ–™ { #use-the-form-data } + +/// tip + +`OAuth2PasswordRequestForm` ้€™ๅ€‹ไพ่ณด้กžๅˆฅ็š„ๅฏฆไพ‹ไธๆœƒๆœ‰ไปฅ็ฉบ็™ฝๅˆ†้š”้•ทๅญ—ไธฒ็š„ `scope` ๅฑฌๆ€ง๏ผŒ่€Œๆ˜ฏๆœƒๆœ‰ไธ€ๅ€‹ `scopes` ๅฑฌๆ€ง๏ผŒ่ฃก้ขๆ˜ฏๅ„ๅ€‹ scope ็š„ๅฏฆ้š›ๅญ—ไธฒๆธ…ๅ–ฎใ€‚ + +ๆœฌ็คบไพ‹ๆฒ’ๆœ‰ไฝฟ็”จ `scopes`๏ผŒไฝ†ๅฆ‚ๆžœไฝ ้œ€่ฆ๏ผŒๅŠŸ่ƒฝๅทฒ็ถ“ๅœจ้‚ฃ่ฃกไบ†ใ€‚ + +/// + +็พๅœจ๏ผŒๅพž๏ผˆๅ‡็š„๏ผ‰่ณ‡ๆ–™ๅบซ่ฃก็”จ่กจๅ–ฎๆฌ„ไฝ็š„ `username` ๅ–ๅพ—ไฝฟ็”จ่€…่ณ‡ๆ–™ใ€‚ + +ๅฆ‚ๆžœๆฒ’ๆœ‰่ฉฒไฝฟ็”จ่€…๏ผŒๅฐฑๅ›žๅ‚ณใ€ŒIncorrect username or passwordใ€็š„้Œฏ่ชคใ€‚ + +ๆˆ‘ๅ€‘็”จ `HTTPException` ้€™ๅ€‹ไพ‹ๅค–ไพ†ๅ›žๅ‚ณ้Œฏ่ชค๏ผš + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### ๆชขๆŸฅๅฏ†็ขผ { #check-the-password } + +้€™ๆ™‚ๆˆ‘ๅ€‘ๅทฒ็ถ“ๆœ‰ไพ†่‡ช่ณ‡ๆ–™ๅบซ็š„ไฝฟ็”จ่€…่ณ‡ๆ–™๏ผŒไฝ†้‚„ๆฒ’ๆชขๆŸฅๅฏ†็ขผใ€‚ + +ๅ…ˆๆŠŠ้‚ฃไบ›่ณ‡ๆ–™ๆ”พ้€ฒ Pydantic ็š„ `UserInDB` ๆจกๅž‹ใ€‚ + +ไฝ ็ต•ๅฐไธ่ฆไปฅ็ด”ๆ–‡ๅญ—ๅ„ฒๅญ˜ๅฏ†็ขผ๏ผŒๆ‰€ไปฅๆˆ‘ๅ€‘ๆœƒไฝฟ็”จ๏ผˆๅ‡็š„๏ผ‰ๅฏ†็ขผ้›œๆนŠ็ณป็ตฑใ€‚ + +ๅฆ‚ๆžœๅฏ†็ขผไธๅŒน้…๏ผŒๆˆ‘ๅ€‘ๅ›žๅ‚ณๅŒๆจฃ็š„้Œฏ่ชคใ€‚ + +#### ๅฏ†็ขผ้›œๆนŠ๏ผˆhashing๏ผ‰ { #password-hashing } + +ใ€Œ้›œๆนŠใ€็š„ๆ„ๆ€ๆ˜ฏ๏ผšๆŠŠไธ€ไบ›ๅ…งๅฎน๏ผˆ้€™่ฃกๆ˜ฏๅฏ†็ขผ๏ผ‰่ฝ‰ๆ›ๆˆไธ€ไธฒ็œ‹่ตทไพ†ๅƒไบ‚็ขผ็š„ไฝๅ…ƒ็ต„ๅบๅˆ—๏ผˆๅฐฑๆ˜ฏๅญ—ไธฒ๏ผ‰ใ€‚ + +ๅช่ฆไฝ ่ผธๅ…ฅๅฎŒๅ…จ็›ธๅŒ็š„ๅ…งๅฎน๏ผˆๅฎŒๅ…จ็›ธๅŒ็š„ๅฏ†็ขผ๏ผ‰๏ผŒๅฐฑๆœƒๅพ—ๅˆฐๅฎŒๅ…จ็›ธๅŒ็š„ไบ‚็ขผใ€‚ + +ไฝ†ไฝ ็„กๆณ•ๅพž้€™ไธฒไบ‚็ขผ้‚„ๅŽŸๅ›žๅŽŸๆœฌ็š„ๅฏ†็ขผใ€‚ + +##### ็‚บไฝ•่ฆๅšๅฏ†็ขผ้›œๆนŠ { #why-use-password-hashing } + +ๅฆ‚ๆžœไฝ ็š„่ณ‡ๆ–™ๅบซ่ขซ็ซŠๅ–๏ผŒๆ”ปๆ“Š่€…ๆ‹ฟๅˆฐ็š„ไธๆ˜ฏไฝฟ็”จ่€…็š„็ด”ๆ–‡ๅญ—ๅฏ†็ขผ๏ผŒ่€Œๅชๆ˜ฏ้›œๆนŠๅ€ผใ€‚ + +ๅ› ๆญคๆ”ปๆ“Š่€…็„กๆณ•ๅ˜—่ฉฆๆŠŠ้‚ฃไบ›ๅฏ†็ขผ็”จๅœจๅ…ถไป–็ณป็ตฑไธŠ๏ผˆๅ› ็‚บๅพˆๅคšไฝฟ็”จ่€…ๅœจๅ„่™•้ƒฝ็”จๅŒไธ€็ต„ๅฏ†็ขผ๏ผŒ้€™ๆœƒๅพˆๅฑ้šช๏ผ‰ใ€‚ + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### ้—œๆ–ผ `**user_dict**` { #about-user-dict } + +`UserInDB(**user_dict)` ็š„ๆ„ๆ€ๆ˜ฏ๏ผš + +ๆŠŠ `user_dict` ็š„้ตๅ’Œๅ€ผ็›ดๆŽฅ็•ถไฝœๅ…ทๅๅƒๆ•ธๅ‚ณๅ…ฅ๏ผŒ็ญ‰ๅŒๆ–ผ๏ผš + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// info + +ๆƒณๆ›ดๅฎŒๆ•ดๅœฐไบ†่งฃ `**user_dict`๏ผŒ่ซ‹ๅ›žๅˆฐ[**้กๅค–ๆจกๅž‹** ็š„ๆ–‡ไปถ](../extra-models.md#about-user-in-dict){.internal-link target=_blank}ใ€‚ + +/// + +## ๅ›žๅ‚ณ token { #return-the-token } + +`token` ็ซฏ้ปž็š„ๅ›žๆ‡‰ๅฟ…้ ˆๆ˜ฏ JSON ็‰ฉไปถใ€‚ + +ๅฎƒๆ‡‰่ฉฒๆœ‰ไธ€ๅ€‹ `token_type`ใ€‚ๅœจๆœฌไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ไฝฟ็”จใ€ŒBearerใ€tokens๏ผŒtoken ้กžๅž‹ๆ‡‰่ฉฒๆ˜ฏใ€Œ`bearer`ใ€ใ€‚ + +่€Œไธ”ๅฎƒ้‚„ๆ‡‰่ฉฒๆœ‰ไธ€ๅ€‹ `access_token`๏ผŒๅ…ถๅ€ผ็‚บๅŒ…ๅซๆˆ‘ๅ€‘ๅญ˜ๅ–ๆฌŠๆ–็š„ๅญ—ไธฒใ€‚ + +ๅœจ้€™ๅ€‹็ฐกๅ–ฎ็คบไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๆœƒไธๅฎ‰ๅ…จๅœฐ็›ดๆŽฅๅ›žๅ‚ณ็›ธๅŒ็š„ `username` ็•ถไฝœ tokenใ€‚ + +/// tip + +ไธ‹ไธ€็ซ ไฝ ๆœƒ็œ‹ๅˆฐ็œŸๆญฃๅฎ‰ๅ…จ็š„ๅฏฆไฝœ๏ผŒๅŒ…ๅซๅฏ†็ขผ้›œๆนŠ่ˆ‡ JWT tokensใ€‚ + +ไฝ†็พๅœจๅ…ˆๆŠŠๆณจๆ„ๅŠ›ๆ”พๅœจๆˆ‘ๅ€‘้œ€่ฆ็š„้€™ไบ›็ดฐ็ฏ€ไธŠใ€‚ + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip + +ไพ็…ง่ฆ็ฏ„๏ผŒไฝ ๆ‡‰่ฉฒๅ›žๅ‚ณไธ€ๅ€‹ๅŒ…ๅซ `access_token` ่ˆ‡ `token_type` ็š„ JSON๏ผŒๅฐฑๅƒ้€™ๅ€‹็ฏ„ไพ‹ใ€‚ + +้€™้ƒจๅˆ†้œ€่ฆไฝ ่‡ชๅทฑๅœจ็จ‹ๅผไธญๅฎŒๆˆ๏ผŒไธฆ็ขบไฟไฝฟ็”จ้€™ไบ› JSON keyใ€‚ + +้€™ๅนพไนŽๆ˜ฏไฝ ็‚บไบ†็ฌฆๅˆ่ฆ็ฏ„่€Œๅฟ…้ ˆ่‡ช่กŒ่จ˜ๅพ—ๆญฃ็ขบ่™•็†็š„ๅ”ฏไธ€ไบ‹ๆƒ…ใ€‚ + +ๅ…ถ้ค˜็š„ **FastAPI** ้ƒฝๆœƒๅนซไฝ ่™•็†ใ€‚ + +/// + +## ๆ›ดๆ–ฐไพ่ณด้ … { #update-the-dependencies } + +ๆŽฅ่‘—ๆˆ‘ๅ€‘่ฆๆ›ดๆ–ฐไพ่ณด้ …ใ€‚ + +ๆˆ‘ๅ€‘ๅชๆƒณๅœจไฝฟ็”จ่€…็‚บๅ•Ÿ็”จ็‹€ๆ…‹ๆ™‚ๅ–ๅพ— `current_user`ใ€‚ + +ๆ‰€ไปฅ๏ผŒๆˆ‘ๅ€‘ๆ–ฐๅขžไธ€ๅ€‹ไพ่ณด `get_current_active_user`๏ผŒ่€Œๅฎƒๆœฌ่บซๅˆไพ่ณด `get_current_user`ใ€‚ + +้€™ๅ…ฉๅ€‹ไพ่ณดๆœƒๅœจไฝฟ็”จ่€…ไธๅญ˜ๅœจๆˆ–ๆœชๅ•Ÿ็”จๆ™‚ๅ›žๅ‚ณ HTTP ้Œฏ่ชคใ€‚ + +ๅ› ๆญค๏ผŒๅœจ็ซฏ้ปžไธญ๏ผŒๅชๆœ‰ๅœจไฝฟ็”จ่€…ๅญ˜ๅœจใ€ๅทฒๆญฃ็ขบ้ฉ—่ญ‰ไธ”็‚บๅ•Ÿ็”จ็‹€ๆ…‹ๆ™‚๏ผŒๆˆ‘ๅ€‘ๆ‰ๆœƒๅ–ๅพ—ไฝฟ็”จ่€…๏ผš + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// info + +้€™่ฃกๆˆ‘ๅ€‘ไธ€ไฝตๅ›žๅ‚ณๅ€ผ็‚บ `Bearer` ็š„้กๅค–ๆจ™้ ญ `WWW-Authenticate`๏ผŒ้€™ไนŸๆ˜ฏ่ฆ็ฏ„็š„ไธ€้ƒจๅˆ†ใ€‚ + +ไปปไฝ• HTTP๏ผˆ้Œฏ่ชค๏ผ‰็‹€ๆ…‹็ขผ 401ใ€ŒUNAUTHORIZEDใ€้ƒฝๆ‡‰่ฉฒๅŒๆ™‚ๅ›žๅ‚ณ `WWW-Authenticate` ๆจ™้ ญใ€‚ + +ๅœจ bearer tokens๏ผˆๆˆ‘ๅ€‘็š„ๆƒ…ๆณ๏ผ‰ไธ‹๏ผŒ่ฉฒๆจ™้ ญ็š„ๅ€ผๆ‡‰่ฉฒๆ˜ฏ `Bearer`ใ€‚ + +ๅ…ถๅฏฆไฝ ๅฏไปฅ็œ็•ฅ้€™ๅ€‹้กๅค–ๆจ™้ ญ๏ผŒๅŠŸ่ƒฝไปๆœƒๆญฃๅธธใ€‚ + +ไฝ†ๆญค่™•ๅŠ ไธŠๅฎƒๆ˜ฏ็‚บไบ†้ตๅพช่ฆ็ฏ„ใ€‚ + +ๅŒๆ™‚ไนŸๅฏ่ƒฝๆœ‰ๅทฅๅ…ทๆœƒๆœŸๅพ…ไธฆไฝฟ็”จๅฎƒ๏ผˆ็พๅœจๆˆ–ๆœชไพ†๏ผ‰๏ผŒ่€Œ้€™ๅฏ่ƒฝๅฐไฝ ๆˆ–ไฝ ็š„ไฝฟ็”จ่€…ๆœ‰ๅนซๅŠฉ๏ผŒ็พๅœจๆˆ–ๆœชไพ†็š†็„ถใ€‚ + +้€™ๅฐฑๆ˜ฏๆจ™ๆบ–็š„ๅฅฝ่™•... + +/// + +## ๅฏฆ้š›ๆ“ไฝœ็œ‹็œ‹ { #see-it-in-action } + +้–‹ๅ•Ÿไบ’ๅ‹•ๅผๆ–‡ไปถ๏ผšhttp://127.0.0.1:8000/docsใ€‚ + +### ้ฉ—่ญ‰่บซๅˆ† { #authenticate } + +้ปž้ธใ€ŒAuthorizeใ€ๆŒ‰้ˆ•ใ€‚ + +ไฝฟ็”จไธ‹ๅˆ—ๅธณๅฏ†๏ผš + +User: `johndoe` + +Password: `secret` + + + +ๅœจ็ณป็ตฑไธญๅฎŒๆˆ้ฉ—่ญ‰ๅพŒ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฆ‚ไธ‹็•ซ้ข๏ผš + + + +### ๅ–ๅพ—่‡ชๅทฑ็š„ไฝฟ็”จ่€…่ณ‡ๆ–™ { #get-your-own-user-data } + +็พๅœจไฝฟ็”จ `GET` ๆ–นๆณ•ๅ‘ผๅซ่ทฏๅพ‘ `/users/me`ใ€‚ + +ไฝ ๆœƒๅ–ๅพ—่‡ชๅทฑ็š„ไฝฟ็”จ่€…่ณ‡ๆ–™๏ผŒๅฆ‚๏ผš + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +ๅฆ‚ๆžœไฝ ้ปžๆ“Š้Ž–้ ญๅœ–็คบ็™ปๅ‡บ๏ผŒ็„ถๅพŒๅ†ๆฌกๅ˜—่ฉฆ็›ธๅŒๆ“ไฝœ๏ผŒไฝ ๆœƒๅพ—ๅˆฐ HTTP 401 ้Œฏ่ชค๏ผš + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### ๆœชๅ•Ÿ็”จ็š„ไฝฟ็”จ่€… { #inactive-user } + +็พๅœจๆ”น็”จไธ€ๅ€‹ๆœชๅ•Ÿ็”จ็š„ไฝฟ็”จ่€…๏ผŒไฝฟ็”จไปฅไธ‹ๅธณๅฏ†้ฉ—่ญ‰๏ผš + +User: `alice` + +Password: `secret2` + +็„ถๅพŒๅ†ๅ‘ผๅซ `GET` ๆ–นๆณ•็š„ `/users/me`ใ€‚ + +ไฝ ๆœƒๅพ—ๅˆฐใ€ŒInactive userใ€็š„้Œฏ่ชค๏ผŒไพ‹ๅฆ‚๏ผš + +```JSON +{ + "detail": "Inactive user" +} +``` + +## ๅฐ็ต { #recap } + +ไฝ ็พๅœจๅทฒ็ถ“ๆœ‰่ถณๅค ็š„ๅทฅๅ…ท๏ผŒ่ƒฝ็‚บไฝ ็š„ API ไปฅ `username` ่ˆ‡ `password` ๅฏฆไฝœไธ€ๅ€‹ๅฎŒๆ•ด็š„ๅฎ‰ๅ…จๆ€ง็ณป็ตฑใ€‚ + +ไฝฟ็”จ้€™ไบ›ๅทฅๅ…ท๏ผŒไฝ ๅฏไปฅ่ฎ“ๅฎ‰ๅ…จๆ€ง็ณป็ตฑ็›ธๅฎนๆ–ผไปปไฝ•่ณ‡ๆ–™ๅบซ๏ผŒไปฅๅŠไปปไฝ•ไฝฟ็”จ่€…ๆˆ–่ณ‡ๆ–™ๆจกๅž‹ใ€‚ + +ๅ”ฏไธ€ๅฐšๆœช่ฃœไธŠ็š„็ดฐ็ฏ€ๆ˜ฏ๏ผšๅฎƒ็พๅœจๅ…ถๅฏฆ้‚„ไธใ€Œๅฎ‰ๅ…จใ€ใ€‚ + +ๅœจไธ‹ไธ€็ซ ๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฆ‚ไฝ•ไฝฟ็”จๅฎ‰ๅ…จ็š„ๅฏ†็ขผ้›œๆนŠๅ‡ฝๅผๅบซ่ˆ‡ JWT tokensใ€‚ diff --git a/docs/zh-hant/docs/tutorial/sql-databases.md b/docs/zh-hant/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..930dc4e8a5 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL๏ผˆ้—œ่ฏๅผ๏ผ‰่ณ‡ๆ–™ๅบซ { #sql-relational-databases } + +FastAPI ไธๅผทๅˆถไฝ ไฝฟ็”จ SQL๏ผˆ้—œ่ฏๅผ๏ผ‰่ณ‡ๆ–™ๅบซใ€‚ไฝ ๅฏไปฅไฝฟ็”จไปปไฝ•ไฝ ๆƒณ่ฆ็š„่ณ‡ๆ–™ๅบซใ€‚ + +้€™่ฃกๆˆ‘ๅ€‘ๆœƒ็”จ SQLModel ไฝœ็‚บ็ฏ„ไพ‹ใ€‚ + +SQLModel ๅปบ็ซ‹ๅœจ SQLAlchemy ่ˆ‡ Pydantic ไน‹ไธŠใ€‚ๅฎƒ็”ฑ FastAPI ็š„ไฝœ่€…้–‹็™ผ๏ผŒ้žๅธธ้ฉๅˆ้œ€่ฆไฝฟ็”จ SQL ่ณ‡ๆ–™ๅบซ็š„ FastAPI ๆ‡‰็”จใ€‚ + +/// tip | ๆ็คบ + +ไฝ ๅฏไปฅไฝฟ็”จไปปไฝ•ไฝ ๆƒณ็”จ็š„ SQL ๆˆ– NoSQL ่ณ‡ๆ–™ๅบซๅ‡ฝๅผๅบซ๏ผˆๆœ‰ๆ™‚็จฑ็‚บ "ORMs"๏ผ‰๏ผŒFastAPI ไธๆœƒๅผท่ฟซไฝ ไฝฟ็”จ็‰นๅฎšๅทฅๅ…ทใ€‚๐Ÿ˜Ž + +/// + +ๅ› ็‚บ SQLModel ๅปบ็ซ‹ๅœจ SQLAlchemy ไน‹ไธŠ๏ผŒไฝ ๅฏไปฅ่ผ•้ฌ†ไฝฟ็”จ SQLAlchemy ๆ‰€ๆ”ฏๆด็š„ไปปไฝ•่ณ‡ๆ–™ๅบซ๏ผˆๅ› ๆญค SQLModel ไนŸๆ”ฏๆด๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server๏ผŒ็ญ‰็ญ‰ใ€‚ + +ๅœจ้€™ๅ€‹็ฏ„ไพ‹ไธญ๏ผŒๆˆ‘ๅ€‘ๆœƒไฝฟ็”จ SQLite๏ผŒๅ› ็‚บๅฎƒๅช็”จๅˆฐๅ–ฎไธ€ๆช”ๆกˆ๏ผŒ่€Œไธ” Python ๅ…งๅปบๆ”ฏๆดใ€‚ไฝ ๅฏไปฅ็›ดๆŽฅ่ค‡่ฃฝ้€™ๅ€‹็ฏ„ไพ‹ไธฆๅŽŸๆจฃๅŸท่กŒใ€‚ + +ไน‹ๅพŒ๏ผŒๅœจไฝ ็š„ๆญฃๅผ็’ฐๅขƒๆ‡‰็”จไธญ๏ผŒไฝ ๅฏ่ƒฝๆœƒๆƒณไฝฟ็”จๅƒ PostgreSQL ้€™้กž็š„่ณ‡ๆ–™ๅบซไผบๆœๅ™จใ€‚ + +/// tip | ๆ็คบ + +ๆœ‰ไธ€ๅ€‹ๅŒ…ๅซ FastAPI ่ˆ‡ PostgreSQL ็š„ๅฎ˜ๆ–นๅฐˆๆกˆ่…ณๆ‰‹ๆžถ๏ผŒ้‚„ๆœ‰ๅ‰็ซฏ่ˆ‡ๆ›ดๅคšๅทฅๅ…ท๏ผšhttps://github.com/fastapi/full-stack-fastapi-template + +/// + +้€™ๆ˜ฏไธ€ไปฝ้žๅธธ็ฐก็Ÿญ็š„ๆ•™ๅญธ๏ผŒๅฆ‚ๆžœไฝ ๆƒณๆ›ดๅ…จ้ขๅญธ็ฟ’่ณ‡ๆ–™ๅบซใ€SQL๏ผŒๆˆ–ๆ›ด้€ฒ้šŽ็š„ๅŠŸ่ƒฝ๏ผŒ่ซ‹ๅƒ่€ƒ SQLModel ๆ–‡ไปถใ€‚ + +## ๅฎ‰่ฃ `SQLModel` { #install-sqlmodel } + +้ฆ–ๅ…ˆ๏ผŒ่ซ‹ๅ…ˆๅปบ็ซ‹ไฝ ็š„[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}ใ€ๅ•Ÿ็”จๅฎƒ๏ผŒ็„ถๅพŒๅฎ‰่ฃ `sqlmodel`๏ผš + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## ๅปบ็ซ‹ๅชๆœ‰ๅ–ฎไธ€ๆจกๅž‹็š„ๆ‡‰็”จ { #create-the-app-with-a-single-model } + +ๆˆ‘ๅ€‘ๅ…ˆ็”จๅ–ฎไธ€ SQLModel ๆจกๅž‹ๅปบ็ซ‹้€™ๅ€‹ๆ‡‰็”จ็š„ๆœ€็ฐก็‰ˆใ€‚ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๆœƒๅœจไธ‹ๆ–น็”จๅคšๅ€‹ๆจกๅž‹ไพ†ๆๅ‡ๅฎ‰ๅ…จๆ€ง่ˆ‡ๅฝˆๆ€งใ€‚๐Ÿค“ + +### ๅปบ็ซ‹ๆจกๅž‹ { #create-models } + +ๅŒฏๅ…ฅ `SQLModel` ไธฆๅปบ็ซ‹ไธ€ๅ€‹่ณ‡ๆ–™ๅบซๆจกๅž‹๏ผš + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +`Hero` ้กžๅˆฅ่ˆ‡ Pydantic ๆจกๅž‹้žๅธธ็›ธไผผ๏ผˆไบ‹ๅฏฆไธŠ๏ผŒๅœจๅบ•ๅฑคๅฎƒๅฐฑๆ˜ฏไธ€ๅ€‹ Pydantic ๆจกๅž‹๏ผ‰ใ€‚ + +ๆœ‰ๅนพ้ปžๅทฎ็•ฐ๏ผš + +* `table=True` ๅ‘Š่จด SQLModel ้€™ๆ˜ฏไธ€ๅ€‹ใ€Œ่ณ‡ๆ–™่กจๆจกๅž‹ใ€๏ผˆtable model๏ผ‰๏ผŒๅฎƒๆ‡‰่ฉฒไปฃ่กจ SQL ่ณ‡ๆ–™ๅบซไธญ็š„ไธ€ๅ€‹่ณ‡ๆ–™่กจ๏ผŒ่€Œไธๅƒ…ๅƒ…ๆ˜ฏใ€Œ่ณ‡ๆ–™ๆจกๅž‹ใ€๏ผˆๅฐฑๅƒไธ€่ˆฌ็š„ Pydantic ้กžๅˆฅ๏ผ‰ใ€‚ + +* `Field(primary_key=True)` ๅ‘Š่จด SQLModel๏ผŒ`id` ๆ˜ฏ SQL ่ณ‡ๆ–™ๅบซไธญ็š„ใ€Œไธป้ตใ€ใ€‚ ๏ผˆไฝ ๅฏไปฅๅœจ SQLModel ๆ–‡ไปถไธญ้€ฒไธ€ๆญฅไบ†่งฃ SQL ไธป้ต๏ผ‰ + + ๆณจๆ„๏ผšๆˆ‘ๅ€‘ๅœจไธป้ตๆฌ„ไฝไฝฟ็”จ `int | None`๏ผŒ้€™ๆจฃๅœจ Python ็จ‹ๅผ็ขผไธญๆˆ‘ๅ€‘ๅฏไปฅใ€Œๅœจๆฒ’ๆœ‰ `id` ็š„ๆƒ…ๆณไธ‹ๅปบ็ซ‹็‰ฉไปถใ€๏ผˆ`id=None`๏ผ‰๏ผŒๅ‡่จญ่ณ‡ๆ–™ๅบซๅœจๅ„ฒๅญ˜ๆ™‚ๆœƒใ€Œ่‡ชๅ‹•็”ข็”Ÿใ€ใ€‚SQLModel ็žญ่งฃ่ณ‡ๆ–™ๅบซๆœƒๆไพ› `id`๏ผŒไธฆไธ”ๅœจ่ณ‡ๆ–™ๅบซ็ถฑ่ฆไธญใ€Œๅฐ‡่ฉฒๆฌ„ไฝๅฎš็พฉ็‚บ้ž็ฉบ็š„ `INTEGER`ใ€ใ€‚่ฉณๆƒ…่ซ‹่ฆ‹ SQLModel ๆ–‡ไปถ๏ผšไธป้ตใ€‚ + +* `Field(index=True)` ๅ‘Š่จด SQLModel ๆ‡‰็‚บๆญคๆฌ„ไฝๅปบ็ซ‹ใ€ŒSQL ็ดขๅผ•ใ€๏ผŒไปฅไพฟๅœจ็”จๆญคๆฌ„ไฝ้Žๆฟพ่ฎ€ๅ–่ณ‡ๆ–™ๆ™‚ๆ›ดๅฟซๆŸฅ่ฉขใ€‚ + + SQLModel ๆœƒ็Ÿฅ้“ๅฎฃๅ‘Š็‚บ `str` ็š„ๆฌ„ไฝๅœจ SQL ไธญๆœƒๆ˜ฏ `TEXT`๏ผˆๆˆ– `VARCHAR`๏ผŒไพ่ณ‡ๆ–™ๅบซ่€Œๅฎš๏ผ‰ใ€‚ + +### ๅปบ็ซ‹ๅผ•ๆ“Ž { #create-an-engine } + +SQLModel ็š„ `engine`๏ผˆๅบ•ๅฑคๅฏฆ้š›ไธŠๆ˜ฏ SQLAlchemy ็š„ `engine`๏ผ‰ๆ˜ฏ็”จไพ†ใ€Œ็ถญ่ญท่ˆ‡่ณ‡ๆ–™ๅบซ้€ฃ็ทšใ€็š„ๆฑ่ฅฟใ€‚ + +ไฝ ็š„็จ‹ๅผไธญๆ‡‰่ฉฒๅชๆœ‰ใ€Œๅ–ฎไธ€ `engine` ็‰ฉไปถใ€ไพ†้€ฃๅˆฐๅŒไธ€ๅ€‹่ณ‡ๆ–™ๅบซใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +ไฝฟ็”จ `check_same_thread=False` ๅ…่จฑ FastAPI ๅœจไธๅŒๅŸท่กŒ็ท’ไธญไฝฟ็”จๅŒไธ€ๅ€‹ SQLite ่ณ‡ๆ–™ๅบซใ€‚้€™ๆ˜ฏๅฟ…่ฆ็š„๏ผŒๅ› ็‚บใ€Œๅ–ฎไธ€่ซ‹ๆฑ‚ใ€ๅฏ่ƒฝๆœƒไฝฟ็”จใ€Œๅคšๅ€‹ๅŸท่กŒ็ท’ใ€๏ผˆไพ‹ๅฆ‚ๅœจไพ่ณด้ …ไธญ๏ผ‰ใ€‚ + +ๅˆฅๆ“”ๅฟƒ๏ผŒไพ็…งๆˆ‘ๅ€‘็š„็จ‹ๅผ็ตๆง‹๏ผŒ็จๅพŒๆˆ‘ๅ€‘ๆœƒ็ขบไฟใ€Œๆฏๅ€‹่ซ‹ๆฑ‚ๅชไฝฟ็”จๅ–ฎไธ€ SQLModel ็š„ sessionใ€๏ผŒ้€™ๅ…ถๅฏฆๅฐฑๆ˜ฏ `check_same_thread` ๆƒณ่ฆ้”ๆˆ็š„ไบ‹ใ€‚ + +### ๅปบ็ซ‹่ณ‡ๆ–™่กจ { #create-the-tables } + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๆ–ฐๅขžไธ€ๅ€‹ๅ‡ฝๅผ๏ผŒไฝฟ็”จ `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`ใ€่ˆ‡่ณ‡ๆ–™ๅบซๆบ้€šใ€‚ + +ๆˆ‘ๅ€‘ๆœƒ็”จ `yield` ๅปบ็ซ‹ไธ€ๅ€‹ FastAPI ็š„ใ€Œไพ่ณดใ€๏ผŒ็‚บๆฏๅ€‹่ซ‹ๆฑ‚ๆไพ›ไธ€ๅ€‹ๆ–ฐ็š„ `Session`ใ€‚้€™ๅฏ็ขบไฟๆฏๅ€‹่ซ‹ๆฑ‚ๅชไฝฟ็”จๅ–ฎไธ€็š„ sessionใ€‚๐Ÿค“ + +ๆŽฅ่‘—ๆˆ‘ๅ€‘ๅปบ็ซ‹ไธ€ๅ€‹ `Annotated` ็š„ไพ่ณด `SessionDep`๏ผŒ่ฎ“ๅพŒ็บŒไฝฟ็”จ้€™ๅ€‹ไพ่ณด็š„็จ‹ๅผ็ขผๆ›ด็ฐกๆฝ”ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### ๅœจๅ•Ÿๅ‹•ๆ™‚ๅปบ็ซ‹่ณ‡ๆ–™่กจ { #create-database-tables-on-startup } + +ๆˆ‘ๅ€‘ๆœƒๅœจๆ‡‰็”จๅ•Ÿๅ‹•ๆ™‚ๅปบ็ซ‹่ณ‡ๆ–™ๅบซ็š„่ณ‡ๆ–™่กจใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +้€™่ฃกๆˆ‘ๅ€‘ๅœจๆ‡‰็”จ็š„ๅ•Ÿๅ‹•ไบ‹ไปถไธญๅปบ็ซ‹่ณ‡ๆ–™่กจใ€‚ + +ๅœจๆญฃๅผ็’ฐๅขƒไธญ๏ผŒไฝ ๅคงๆฆ‚ๆœƒๅœจๅ•Ÿๅ‹•ๆ‡‰็”จๅ‰ไฝฟ็”จ้ท็งป่…ณๆœฌไพ†่™•็†ใ€‚๐Ÿค“ + +/// tip | ๆ็คบ + +SQLModel ไน‹ๅพŒๆœƒๆไพ›ๅŒ…่ฃ Alembic ็š„้ท็งปๅทฅๅ…ท๏ผŒไฝ†็›ฎๅ‰ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ Alembicใ€‚ + +/// + +### ๅปบ็ซ‹ Hero { #create-a-hero } + +ๅ› ็‚บๆฏๅ€‹ SQLModel ๆจกๅž‹ๅŒๆ™‚ไนŸๆ˜ฏไธ€ๅ€‹ Pydantic ๆจกๅž‹๏ผŒไฝ ๅฏไปฅๅœจใ€Œๅž‹ๅˆฅๆจ™่จปใ€ไธญๅƒไฝฟ็”จ Pydantic ๆจกๅž‹ไธ€ๆจฃไฝฟ็”จๅฎƒใ€‚ + +ไพ‹ๅฆ‚๏ผŒๅฆ‚ๆžœไฝ ๅฎฃๅ‘Šไธ€ๅ€‹ๅƒๆ•ธๅž‹ๅˆฅ็‚บ `Hero`๏ผŒๅฎƒๆœƒๅพžใ€ŒJSON bodyใ€ไธญ่ฎ€ๅ–ใ€‚ + +ๅŒๆจฃๅœฐ๏ผŒไฝ ไนŸๅฏไปฅๅฐ‡ๅฎƒๅฎฃๅ‘Š็‚บๅ‡ฝๅผ็š„ใ€Œๅ›žๅ‚ณๅž‹ๅˆฅใ€๏ผŒ็„ถๅพŒๅœจ่‡ชๅ‹•็”ข็”Ÿ็š„ API ๆ–‡ไปถ UI ไธญๅฐฑๆœƒ้กฏ็คบๅ…ถ่ณ‡ๆ–™็ตๆง‹ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +้€™่ฃกๆˆ‘ๅ€‘ไฝฟ็”จ `SessionDep` ไพ่ณด๏ผˆๅณไธ€ๅ€‹ `Session`๏ผ‰๏ผŒๆŠŠๆ–ฐ็š„ `Hero` ๅŠ ๅ…ฅ `Session` ๅฏฆไพ‹๏ผŒๆไบค่ฎŠๆ›ดๅˆฐ่ณ‡ๆ–™ๅบซ๏ผŒๅˆทๆ–ฐ `hero` ็š„่ณ‡ๆ–™๏ผŒ็„ถๅพŒๅ›žๅ‚ณๅฎƒใ€‚ + +### ่ฎ€ๅ–ๅคšๅ€‹ Hero { #read-heroes } + +ๆˆ‘ๅ€‘ๅฏไปฅ็”จ `select()` ๅพž่ณ‡ๆ–™ๅบซใ€Œ่ฎ€ๅ–ใ€ๅคšๅ€‹ `Hero`ใ€‚ๅฏไปฅๅŠ ๅ…ฅ `limit` ่ˆ‡ `offset` ไพ†ๅˆ†้ ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### ่ฎ€ๅ–ๅ–ฎไธ€ Hero { #read-one-hero } + +ๆˆ‘ๅ€‘ๅฏไปฅใ€Œ่ฎ€ๅ–ใ€ๅ–ฎไธ€็š„ `Hero`ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### ๅˆช้™ค Hero { #delete-a-hero } + +ๆˆ‘ๅ€‘ไนŸๅฏไปฅใ€Œๅˆช้™คใ€ไธ€ๅ€‹ `Hero`ใ€‚ + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### ๅŸท่กŒๆ‡‰็”จ { #run-the-app } + +ไฝ ๅฏไปฅๅŸท่กŒๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +็„ถๅพŒๅ‰ๅพ€ `/docs` ็š„ UI๏ผŒไฝ ๆœƒ็œ‹ๅˆฐ FastAPI ไฝฟ็”จ้€™ไบ›ๆจกๅž‹ไพ†ใ€Œๆ–‡ไปถๅŒ–ใ€API๏ผŒไนŸๆœƒ็”จๅฎƒๅ€‘ไพ†ใ€Œๅบๅˆ—ๅŒ–ใ€่ˆ‡ใ€Œ้ฉ—่ญ‰ใ€่ณ‡ๆ–™ใ€‚ + +
+ +
+ +## ็”จๅคšๅ€‹ๆจกๅž‹ๆ›ดๆ–ฐๆ‡‰็”จ { #update-the-app-with-multiple-models } + +็พๅœจๆˆ‘ๅ€‘็จๅพฎใ€Œ้‡ๆง‹ใ€ไธ€ไธ‹้€™ๅ€‹ๆ‡‰็”จ๏ผŒไปฅๆๅ‡ใ€Œๅฎ‰ๅ…จๆ€งใ€่ˆ‡ใ€Œๅฝˆๆ€งใ€ใ€‚ + +ๅฆ‚ๆžœไฝ ๆชขๆŸฅๅ‰ไธ€็‰ˆ็š„ๆ‡‰็”จ๏ผŒๅœจ UI ไธญไฝ ๆœƒ็œ‹ๅˆฐ๏ผŒๅˆฐ็›ฎๅ‰็‚บๆญขๅฎƒ่ฎ“็”จๆˆถ็ซฏ่‡ชๅทฑๆฑบๅฎš่ฆๅปบ็ซ‹็š„ `Hero` ็š„ `id`ใ€‚๐Ÿ˜ฑ + +ๆˆ‘ๅ€‘ไธ่ฉฒๅ…่จฑ้€™ๆจฃ๏ผŒๅ› ็‚บไป–ๅ€‘ๅฏ่ƒฝๆœƒ่ฆ†่“‹่ณ‡ๆ–™ๅบซไธญๆˆ‘ๅ€‘ๅทฒๅˆ†้…็š„ `id`ใ€‚ๆฑบๅฎš `id` ๆ‡‰่ฉฒ็”ฑใ€ŒๅพŒ็ซฏใ€ๆˆ–ใ€Œ่ณ‡ๆ–™ๅบซใ€ไพ†ๅš๏ผŒใ€Œไธๆ˜ฏ็”จๆˆถ็ซฏใ€ใ€‚ + +ๅฆๅค–๏ผŒๆˆ‘ๅ€‘็‚บ hero ๅปบ็ซ‹ไบ† `secret_name`๏ผŒไฝ†็›ฎๅ‰ๆˆ‘ๅ€‘ๅœจๅ„่™•้ƒฝๆŠŠๅฎƒๅ›žๅ‚ณๅ‡บๅŽป๏ผŒ้€™ไธ€้ปž้ƒฝไธใ€Œไฟๅฏ†ใ€... ๐Ÿ˜… + +ๆˆ‘ๅ€‘ๆœƒ้€้ŽๅŠ ๅ…ฅไธ€ไบ›ใ€Œ้กๅค–ๆจกๅž‹ใ€ไพ†ไฟฎๆญฃ้€™ไบ›ๅ•้กŒใ€‚้€™ๆญฃๆ˜ฏ SQLModel ๅคงๆ”พ็•ฐๅฝฉ็š„ๅœฐๆ–นใ€‚โœจ + +### ๅปบ็ซ‹ๅคšๅ€‹ๆจกๅž‹ { #create-multiple-models } + +ๅœจ SQLModel ไธญ๏ผŒไปปไฝ•่จญไบ† `table=True` ็š„ๆจกๅž‹้กžๅˆฅ้ƒฝๆ˜ฏใ€Œ่ณ‡ๆ–™่กจๆจกๅž‹ใ€ใ€‚ + +่€Œๆฒ’ๆœ‰่จญ `table=True` ็š„ๆจกๅž‹้กžๅˆฅๅฐฑๆ˜ฏใ€Œ่ณ‡ๆ–™ๆจกๅž‹ใ€๏ผŒ้€™ไบ›ๅ…ถๅฏฆๅฐฑๆ˜ฏ Pydantic ๆจกๅž‹๏ผˆๅชๆœ‰ไธ€้ปžๅฐๅขžๅผท๏ผ‰ใ€‚๐Ÿค“ + +ไฝฟ็”จ SQLModel๏ผŒๆˆ‘ๅ€‘ๅฏไปฅๅˆฉ็”จใ€Œ็นผๆ‰ฟใ€ไพ†ใ€Œ้ฟๅ…้‡่ค‡ใ€ๅœจๅ„็จฎๆƒ…ๆณไธ‹ไธ€ๅ†ๅฎฃๅ‘Šๆ‰€ๆœ‰ๆฌ„ไฝใ€‚ + +#### `HeroBase` - ๅŸบๅบ•้กžๅˆฅ { #herobase-the-base-class } + +ๅ…ˆๅพž `HeroBase` ๆจกๅž‹้–‹ๅง‹๏ผŒๅฎƒๅŒ…ๅซๆ‰€ๆœ‰ๆจกๅž‹ใ€Œๅ…ฑไบซใ€็š„ๆฌ„ไฝ๏ผš + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - ่ณ‡ๆ–™่กจๆจกๅž‹ { #hero-the-table-model } + +ๆŽฅ่‘—ๅปบ็ซ‹ `Hero`๏ผŒไนŸๅฐฑๆ˜ฏๅฏฆ้š›็š„ใ€Œ่ณ‡ๆ–™่กจๆจกๅž‹ใ€๏ผŒๅฎƒๅŒ…ๅซไธไธ€ๅฎšๆœƒๅ‡บ็พๅœจๅ…ถไป–ๆจกๅž‹ไธญ็š„ใ€Œ้กๅค–ๆฌ„ไฝใ€๏ผš + +* `id` +* `secret_name` + +ๅ› ็‚บ `Hero` ็นผๆ‰ฟ่‡ช `HeroBase`๏ผŒๅฎƒใ€ŒไนŸใ€ๆ“ๆœ‰ `HeroBase` ไธญๅฎฃๅ‘Š็š„ใ€Œๆฌ„ไฝใ€๏ผŒๅ› ๆญค `Hero` ็š„ๅฎŒๆ•ดๆฌ„ไฝ็‚บ๏ผš + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - ๅ…ฌ้–‹็š„่ณ‡ๆ–™ๆจกๅž‹ { #heropublic-the-public-data-model } + +ๆŽฅไธ‹ไพ†ๅปบ็ซ‹ `HeroPublic` ๆจกๅž‹๏ผŒๅฎƒๆ˜ฏ่ฆใ€Œๅ›žๅ‚ณใ€็ตฆ API ็”จๆˆถ็ซฏ็š„ๆจกๅž‹ใ€‚ + +ๅฎƒๆ“ๆœ‰่ˆ‡ `HeroBase` ็›ธๅŒ็š„ๆฌ„ไฝ๏ผŒๅ› ๆญคไธๆœƒๅŒ…ๅซ `secret_name`ใ€‚ + +็ต‚ๆ–ผ๏ผŒๆˆ‘ๅ€‘่‹ฑ้›„็š„็œŸๅฏฆ่บซๅˆ†ๅ—ไฟ่ญทไบ†๏ผ๐Ÿฅท + +ๅฎƒไนŸ้‡ๆ–ฐๅฎฃๅ‘Šไบ† `id: int`ใ€‚้€™้บผๅšๆ˜ฏ่ˆ‡ API ็”จๆˆถ็ซฏ่จ‚็ซ‹ไธ€ๅ€‹ใ€Œๅฅ‘็ด„ใ€๏ผŒ่ฎ“ไป–ๅ€‘ๅฏไปฅ็ขบๅฎš `id` ไธ€ๅฎšๅญ˜ๅœจ่€Œไธ”ๆ˜ฏ `int`๏ผˆไธๆœƒๆ˜ฏ `None`๏ผ‰ใ€‚ + +/// tip | ๆ็คบ + +่ฎ“ๅ›žๅ‚ณๆจกๅž‹ไฟ่ญ‰ๆŸๅ€‹ๅ€ผไธ€ๅฎšๅญ˜ๅœจใ€่€Œไธ”ไธ€ๅฎšๆ˜ฏ `int`๏ผˆไธๆ˜ฏ `None`๏ผ‰๏ผŒๅฐ API ็”จๆˆถ็ซฏ้žๅธธๆœ‰ๅนซๅŠฉใ€‚ไป–ๅ€‘ๅœจๆœ‰้€™ๅ€‹็ขบไฟกไธ‹ๅฏไปฅๅฏซๅ‡บๆ›ด็ฐกๅ–ฎ็š„็จ‹ๅผ็ขผใ€‚ + +ๆญคๅค–๏ผŒ้€้Žใ€Œ่‡ชๅ‹•็”ข็”Ÿ็š„ๅฎขๆˆถ็ซฏใ€ไนŸๆœƒๆœ‰ๆ›ด็ฐกๆฝ”็š„ไป‹้ข๏ผŒ่ฎ“่ฆไฝฟ็”จไฝ  API ็š„้–‹็™ผ่€…่ƒฝๆœ‰ๆ›ดๅฅฝ็š„้–‹็™ผ้ซ”้ฉ—ใ€‚๐Ÿ˜Ž + +/// + +`HeroPublic` ไธญ็š„ๆฌ„ไฝ่ˆ‡ `HeroBase` ็›ธๅŒ๏ผŒๅƒ… `id` ๅฎฃๅ‘Š็‚บ `int`๏ผˆ้ž `None`๏ผ‰๏ผš + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - ็”จๆ–ผๅปบ็ซ‹ Hero ็š„่ณ‡ๆ–™ๆจกๅž‹ { #herocreate-the-data-model-to-create-a-hero } + +็พๅœจๆˆ‘ๅ€‘ๅปบ็ซ‹ `HeroCreate` ๆจกๅž‹๏ผŒ้€™ๆ˜ฏ็”จไพ†ใ€Œ้ฉ—่ญ‰ใ€็”จๆˆถ็ซฏ้€ไพ†่ณ‡ๆ–™็š„ๆจกๅž‹ใ€‚ + +ๅฎƒๅ…ทๆœ‰่ˆ‡ `HeroBase` ็›ธๅŒ็š„ๆฌ„ไฝ๏ผŒไธฆไธ”้‚„ๆœ‰ `secret_name`ใ€‚ + +ๆŽฅไธ‹ไพ†๏ผŒ็•ถ็”จๆˆถ็ซฏใ€Œๅปบ็ซ‹ๆ–ฐ heroใ€ๆ™‚๏ผŒไป–ๅ€‘ๆœƒ้€ไธŠ `secret_name`๏ผŒๅฎƒๆœƒ่ขซๅ„ฒๅญ˜ๅœจ่ณ‡ๆ–™ๅบซไธญ๏ผŒไฝ†้€™ไบ›็ฅ•ๅฏ†ๅ็จฑไธๆœƒๅœจ API ไธญๅ›žๅ‚ณ็ตฆ็”จๆˆถ็ซฏใ€‚ + +/// tip | ๆ็คบ + +้€™ไนŸๅฐฑๆ˜ฏไฝ ่™•็†ใ€Œๅฏ†็ขผใ€็š„ๆ–นๅผใ€‚ๆŽฅๆ”ถๅฎƒๅ€‘๏ผŒไฝ†ไธ่ฆๅœจ API ไธญๅ›žๅ‚ณใ€‚ + +ไฝ ไนŸๆ‡‰่ฉฒๅœจๅ„ฒๅญ˜ๅ‰ๅ…ˆๅฐๅฏ†็ขผๅšใ€Œ้›œๆนŠใ€๏ผŒใ€Œๆฐธ้ ไธ่ฆไปฅๆ˜Žๆ–‡ๅ„ฒๅญ˜ใ€ใ€‚ + +/// + +`HeroCreate` ็š„ๆฌ„ไฝๆœ‰๏ผš + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - ็”จๆ–ผๆ›ดๆ–ฐ Hero ็š„่ณ‡ๆ–™ๆจกๅž‹ { #heroupdate-the-data-model-to-update-a-hero } + +ๅœจๅ‰ไธ€็‰ˆ็š„ๆ‡‰็”จไธญ๏ผŒๆˆ‘ๅ€‘ๆฒ’ๆœ‰ใ€Œๆ›ดๆ–ฐ heroใ€็š„ๆ–นๅผ๏ผŒไฝ†็พๅœจๆœ‰ไบ†ใ€Œๅคšๅ€‹ๆจกๅž‹ใ€๏ผŒๆˆ‘ๅ€‘ๅฐฑ่ƒฝๅšๅˆฐใ€‚๐ŸŽ‰ + +`HeroUpdate` ้€™ๅ€‹่ณ‡ๆ–™ๆจกๅž‹ๆœ‰้ปž็‰นๅˆฅ๏ผŒๅฎƒๅŒ…ๅซใ€Œๅปบ็ซ‹ๆ–ฐ hero ๆ‰€้œ€็š„ๆ‰€ๆœ‰ๆฌ„ไฝใ€๏ผŒไฝ†ๆ‰€ๆœ‰ๆฌ„ไฝ้ƒฝๆ˜ฏใ€Œๅฏ้ธ็š„ใ€๏ผˆ้ƒฝๆœ‰้ ่จญๅ€ผ๏ผ‰ใ€‚้€™ๆจฃๅœจๆ›ดๆ–ฐๆ™‚๏ผŒไฝ ๅช้œ€่ฆ้€ๅ‡บๆƒณ่ฆๆ›ดๆ–ฐ็š„ๆฌ„ไฝๅณๅฏใ€‚ + +ๅ› ็‚บๆ‰€ๆœ‰ๆฌ„ไฝ็š„ใ€Œๅž‹ๅˆฅๅ…ถๅฏฆ้ƒฝๆ”น่ฎŠไบ†ใ€๏ผˆๅž‹ๅˆฅ็พๅœจๅŒ…ๅซ `None`๏ผŒ่€Œไธ”้ ่จญๅ€ผ็‚บ `None`๏ผ‰๏ผŒๆˆ‘ๅ€‘้œ€่ฆใ€Œ้‡ๆ–ฐๅฎฃๅ‘Šใ€ๅฎƒๅ€‘ใ€‚ + +ๅ…ถๅฏฆไธไธ€ๅฎš่ฆ็นผๆ‰ฟ `HeroBase`๏ผŒๅ› ็‚บๆˆ‘ๅ€‘ๆœƒ้‡ๆ–ฐๅฎฃๅ‘Šๆ‰€ๆœ‰ๆฌ„ไฝใ€‚ๆˆ‘้€™่ฃกไฟ็•™็นผๆ‰ฟๅชๆ˜ฏ็‚บไบ†ไธ€่‡ดๆ€ง๏ผŒไธฆ้žๅฟ…่ฆใ€‚้€™ไธป่ฆๆ˜ฏๅ€‹ไบบๅๅฅฝ็š„ๅ•้กŒใ€‚๐Ÿคท + +`HeroUpdate` ็š„ๆฌ„ไฝๆœ‰๏ผš + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### ็”จ `HeroCreate` ๅปบ็ซ‹ไธฆๅ›žๅ‚ณ `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } + +็พๅœจๆˆ‘ๅ€‘ๆœ‰ไบ†ใ€Œๅคšๅ€‹ๆจกๅž‹ใ€๏ผŒๅฏไปฅๆ›ดๆ–ฐๆ‡‰็”จไธญไฝฟ็”จๅฎƒๅ€‘็š„้ƒจๅˆ†ใ€‚ + +ๆˆ‘ๅ€‘ๅœจ่ซ‹ๆฑ‚ไธญๆŽฅๆ”ถ `HeroCreate`๏ผˆ่ณ‡ๆ–™ๆจกๅž‹๏ผ‰๏ผŒไธฆ็”ฑๅฎƒๅปบ็ซ‹ไธ€ๅ€‹ `Hero`๏ผˆ่ณ‡ๆ–™่กจๆจกๅž‹๏ผ‰ใ€‚ + +้€™ๅ€‹ๆ–ฐ็š„่ณ‡ๆ–™่กจๆจกๅž‹ `Hero` ๆœƒๆœ‰็”จๆˆถ็ซฏๅ‚ณไพ†็š„ๆฌ„ไฝ๏ผŒไธฆไธ”ๆœƒ็”ฑ่ณ‡ๆ–™ๅบซ็”ข็”Ÿไธ€ๅ€‹ `id`ใ€‚ + +็„ถๅพŒๆˆ‘ๅ€‘็›ดๆŽฅๅพžๅ‡ฝๅผๅ›žๅ‚ณ้€™ๅ€‹่ณ‡ๆ–™่กจๆจกๅž‹ `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`ใ€‚ + +ๅฆ‚ๆžœๆˆ‘ๅ€‘ๅฎฃๅ‘Š `-> HeroPublic`๏ผŒไฝ ็š„็ทจ่ผฏๅ™จ่ˆ‡ linter ๆœƒ๏ผˆ็†ๆ‰€็•ถ็„ถๅœฐ๏ผ‰ๆŠฑๆ€จไฝ ๅ›žๅ‚ณ็š„ๆ˜ฏ `Hero` ่€Œไธๆ˜ฏ `HeroPublic`ใ€‚ + +ๅœจ `response_model` ไธญๅฎฃๅ‘Š๏ผŒๅฐฑๆ˜ฏ่ฆ่ฎ“ FastAPI ๅŽปๅšๅฎƒ่ฉฒๅš็š„ไบ‹๏ผŒ่€Œไธๅฝฑ้Ÿฟๅž‹ๅˆฅๆจ™่จป๏ผŒไปฅๅŠไฝ ็š„็ทจ่ผฏๅ™จ่ˆ‡ๅ…ถไป–ๅทฅๅ…ทๆไพ›็š„ๅ”ๅŠฉใ€‚ + +/// + +### ไฝฟ็”จ `HeroPublic` ่ฎ€ๅ–ๅคšๅ€‹ Hero { #read-heroes-with-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๏ผš + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### ไฝฟ็”จ `HeroUpdate` ๆ›ดๆ–ฐ Hero { #update-a-hero-with-heroupdate } + +ๆˆ‘ๅ€‘ๅฏไปฅใ€Œๆ›ดๆ–ฐ heroใ€ใ€‚็‚บๆญคๆˆ‘ๅ€‘ไฝฟ็”จ HTTP ็š„ `PATCH` ๆ“ไฝœใ€‚ + +ๅœจ็จ‹ๅผ็ขผไธญ๏ผŒๆˆ‘ๅ€‘ๆœƒๅ–ๅพ—ไธ€ๅ€‹ๅชๅŒ…ๅซ็”จๆˆถ็ซฏๆœ‰ๅ‚ณ้€็š„่ณ‡ๆ–™็š„ `dict`๏ผŒไธๅŒ…ๅซๅชๆ˜ฏๅ› ็‚บๆœ‰้ ่จญๅ€ผ่€Œๅญ˜ๅœจ็š„ๆฌ„ไฝใ€‚็‚บไบ†้”ๆˆ้€™้ปž๏ผŒๆˆ‘ๅ€‘ไฝฟ็”จ `exclude_unset=True`ใ€‚้€™ๆ˜ฏ้—œ้ตใ€‚๐Ÿช„ + +็„ถๅพŒๆˆ‘ๅ€‘ไฝฟ็”จ `hero_db.sqlmodel_update(hero_data)` ไปฅ `hero_data` ็š„่ณ‡ๆ–™ๆ›ดๆ–ฐ `hero_db`ใ€‚ + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### ๅ†ๆฌกๅˆช้™ค Hero { #delete-a-hero-again } + +ใ€Œๅˆช้™คใ€ hero ๅŸบๆœฌไธŠ็ถญๆŒไธ่ฎŠใ€‚ + +ๆˆ‘ๅ€‘ไธๆœƒ็‚บไบ†้‡ๆง‹่€Œ้‡ๆง‹ไธ€ๅˆ‡ใ€‚๐Ÿ˜… + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### ๅ†ๆฌกๅŸท่กŒๆ‡‰็”จ { #run-the-app-again } + +ไฝ ๅฏไปฅๅ†ๆฌกๅŸท่กŒๆ‡‰็”จ๏ผš + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ๅฆ‚ๆžœไฝ ๅ‰ๅพ€ `/docs` ็š„ API UI๏ผŒไฝ ๆœƒ็œ‹ๅˆฐๅฎƒๅทฒๆ›ดๆ–ฐ๏ผŒๅปบ็ซ‹ hero ๆ™‚ไธๅ†ๆœŸๅพ…ๅพž็”จๆˆถ็ซฏๆŽฅๆ”ถ `id`๏ผŒ็ญ‰็ญ‰ใ€‚ + +
+ +
+ +## ็ธฝ็ต { #recap } + +ไฝ ๅฏไปฅไฝฟ็”จ SQLModel ่ˆ‡ SQL ่ณ‡ๆ–™ๅบซไบ’ๅ‹•๏ผŒไธฆ็”จใ€Œ่ณ‡ๆ–™ๆจกๅž‹ใ€่ˆ‡ใ€Œ่ณ‡ๆ–™่กจๆจกๅž‹ใ€่ฎ“็จ‹ๅผ็ขผๆ›ด็ฐกๆฝ”ใ€‚ + +ไฝ ๅฏไปฅๅœจ SQLModel ๆ–‡ไปถๅญธๅˆฐๆ›ดๅคšๅ…งๅฎน๏ผŒ้€™่ฃก้‚„ๆœ‰ไธ€ไปฝๆ›ด้•ท็š„ ไฝฟ็”จ SQLModel ่ˆ‡ FastAPI ็š„ๆ•™ๅญธใ€‚๐Ÿš€ diff --git a/docs/zh-hant/docs/tutorial/static-files.md b/docs/zh-hant/docs/tutorial/static-files.md new file mode 100644 index 0000000000..06b6176760 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/static-files.md @@ -0,0 +1,40 @@ +# ้œๆ…‹ๆช”ๆกˆ { #static-files } + +ไฝ ๅฏไปฅไฝฟ็”จ `StaticFiles` ๅพžๆŸๅ€‹็›ฎ้Œ„่‡ชๅ‹•ๆไพ›้œๆ…‹ๆช”ๆกˆใ€‚ + +## ไฝฟ็”จ `StaticFiles` { #use-staticfiles } + +- ๅŒฏๅ…ฅ `StaticFiles`ใ€‚ +- ๅœจ็‰นๅฎš่ทฏๅพ‘ไธŠใ€ŒๆŽ›่ผ‰ใ€ไธ€ๅ€‹ `StaticFiles()` ๅฏฆไพ‹ใ€‚ + +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.staticfiles import StaticFiles`ใ€‚ + +**FastAPI** ็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…๏ผŒๆไพ›่ˆ‡ `starlette.staticfiles` ็›ธๅŒ็š„ไป‹้ขไฝœ็‚บ `fastapi.staticfiles`ใ€‚ไฝ†ๅฎƒๅ…ถๅฏฆๆ˜ฏ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +### ไป€้บผๆ˜ฏใ€ŒๆŽ›่ผ‰ใ€ { #what-is-mounting } + +ใ€ŒๆŽ›่ผ‰๏ผˆmounting๏ผ‰ใ€ๆ˜ฏๆŒ‡ๅœจ็‰นๅฎš่ทฏๅพ‘ไธ‹ๅŠ ๅ…ฅไธ€ๅ€‹ๅฎŒๆ•ดไธ”ใ€Œ็จ็ซ‹ใ€็š„ๆ‡‰็”จ๏ผŒไน‹ๅพŒๆ‰€ๆœ‰่ฉฒ่ทฏๅพ‘ไธ‹็š„ๅญ่ทฏๅพ‘้ƒฝ็”ฑๅฎƒ่™•็†ใ€‚ + +้€™่ˆ‡ไฝฟ็”จ `APIRouter` ไธๅŒ๏ผŒๅ› ็‚บ่ขซๆŽ›่ผ‰็š„ๆ‡‰็”จๆ˜ฏๅฎŒๅ…จ็จ็ซ‹็š„ใ€‚ไธปๆ‡‰็”จ็š„ OpenAPI ่ˆ‡ๆ–‡ไปถไธๆœƒๅŒ…ๅซๆŽ›่ผ‰ๆ‡‰็”จ็š„ไปปไฝ•ๅ…งๅฎน๏ผŒ็ญ‰็ญ‰ใ€‚ + +ไฝ ๅฏไปฅๅœจ[้€ฒ้šŽไฝฟ็”จ่€…ๆŒ‡ๅ—](../advanced/index.md){.internal-link target=_blank}ไธญ้–ฑ่ฎ€ๆ›ดๅคš็›ธ้—œๅ…งๅฎนใ€‚ + +## ็ดฐ็ฏ€ { #details } + +็ฌฌไธ€ๅ€‹ `"/static"` ๆŒ‡็š„ๆ˜ฏ้€™ๅ€‹ใ€Œๅญๆ‡‰็”จใ€่ฆ่ขซใ€ŒๆŽ›่ผ‰ใ€็š„ๅญ่ทฏๅพ‘ใ€‚ๅ› ๆญค๏ผŒไปปไฝ•ไปฅ `"/static"` ้–‹้ ญ็š„่ทฏๅพ‘้ƒฝๆœƒ็”ฑๅฎƒ่™•็†ใ€‚ + +`directory="static"` ๆŒ‡ๅ‘ๅŒ…ๅซไฝ ้œๆ…‹ๆช”ๆกˆ็š„็›ฎ้Œ„ๅ็จฑใ€‚ + +`name="static"` ็‚บๅฎƒๆŒ‡ๅฎšไธ€ๅ€‹ๅฏไพ› **FastAPI** ๅ…ง้ƒจไฝฟ็”จ็š„ๅ็จฑใ€‚ + +ไปฅไธŠๅƒๆ•ธ้ƒฝไธไธ€ๅฎš่ฆๆ˜ฏ "`static`"๏ผŒ่ซ‹ไพไฝ ็š„ๆ‡‰็”จ้œ€ๆฑ‚่ˆ‡็ดฐ็ฏ€่ชฟๆ•ดใ€‚ + +## ๆ›ดๅคš่ณ‡่จŠ { #more-info } + +ๅฆ‚้œ€ๆ›ดๅคš็ดฐ็ฏ€่ˆ‡้ธ้ …๏ผŒ่ซ‹ๅƒ่€ƒ Starlette ้—œๆ–ผ้œๆ…‹ๆช”ๆกˆ็š„ๆ–‡ไปถใ€‚ diff --git a/docs/zh-hant/docs/tutorial/testing.md b/docs/zh-hant/docs/tutorial/testing.md new file mode 100644 index 0000000000..0d49fd5d7b --- /dev/null +++ b/docs/zh-hant/docs/tutorial/testing.md @@ -0,0 +1,193 @@ +# ๆธฌ่ฉฆ { #testing } + +ๅคš่™งไบ† Starlette๏ผŒๆธฌ่ฉฆ **FastAPI** ๆ‡‰็”จๆ—ข็ฐกๅ–ฎๅˆๅฅฝ็”จใ€‚ + +ๅฎƒๆ˜ฏๅŸบๆ–ผ HTTPX ๆ‰“้€ ๏ผŒ่€Œ HTTPX ็š„่จญ่จˆๅˆๅƒ่€ƒไบ† Requests๏ผŒๆ‰€ไปฅ็”จ่ตทไพ†้žๅธธ็†Ÿๆ‚‰ใ€็›ด่ฆบใ€‚ + +ๅ€ŸๅŠฉๅฎƒ๏ผŒไฝ ๅฏไปฅ็›ดๆŽฅ็”จ pytest ไพ†ๆธฌ่ฉฆ **FastAPI**ใ€‚ + +## ไฝฟ็”จ `TestClient` { #using-testclient } + +/// info + +่ฆไฝฟ็”จ `TestClient`๏ผŒ่ซ‹ๅ…ˆๅฎ‰่ฃ `httpx`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +```console +$ pip install httpx +``` + +/// + +ๅŒฏๅ…ฅ `TestClient`ใ€‚ + +ๅปบ็ซ‹ไธ€ๅ€‹ `TestClient`๏ผŒๆŠŠไฝ ็š„ **FastAPI** ๆ‡‰็”จๅ‚ณๅ…ฅๅ…ถไธญใ€‚ + +ๅปบ็ซ‹ๅ็จฑไปฅ `test_` ้–‹้ ญ็š„ๅ‡ฝๅผ๏ผˆ้€™ๆ˜ฏ `pytest` ็š„ๆ…ฃไพ‹๏ผ‰ใ€‚ + +ๅƒไฝฟ็”จ `httpx` ไธ€ๆจฃไฝฟ็”จ `TestClient` ็‰ฉไปถใ€‚ + +็”จ็ฐกๅ–ฎ็š„ `assert` ๆ•˜่ฟฐๆญ้…ๆจ™ๆบ–็š„ Python ้‹็ฎ—ๅผไพ†ๆชขๆŸฅ๏ผˆๅŒๆจฃๆ˜ฏ `pytest` ็š„ๆจ™ๆบ–็”จๆณ•๏ผ‰ใ€‚ + +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} + +/// tip + +ๆณจๆ„ๆธฌ่ฉฆๅ‡ฝๅผๆ˜ฏไธ€่ˆฌ็š„ `def`๏ผŒไธๆ˜ฏ `async def`ใ€‚ + +่€Œไธ”ๅฐ client ็š„ๅ‘ผๅซไนŸ้ƒฝๆ˜ฏไธ€่ˆฌๅ‘ผๅซ๏ผŒไธ้œ€่ฆไฝฟ็”จ `await`ใ€‚ + +้€™่ฎ“ไฝ ๅฏไปฅ็›ดๆŽฅไฝฟ็”จ `pytest`๏ผŒไธๅฟ…่ฒปๅฟƒ่™•็†้žๅŒๆญฅใ€‚ + +/// + +/// note | ๆŠ€่ก“็ดฐ็ฏ€ + +ไฝ ไนŸๅฏไปฅไฝฟ็”จ `from starlette.testclient import TestClient`ใ€‚ + +**FastAPI** ็‚บไบ†ๆ–นไพฟ้–‹็™ผ่€…๏ผŒไนŸๆไพ›่ˆ‡ `starlette.testclient` ็›ธๅŒ็š„ `fastapi.testclient`ใ€‚ไฝ†ๅฎƒๅ…ถๅฏฆ็›ดๆŽฅไพ†่‡ช Starletteใ€‚ + +/// + +/// tip + +ๅฆ‚ๆžœไฝ ๆƒณๅœจๆธฌ่ฉฆไธญๅ‘ผๅซๅ…ถไป– `async` ๅ‡ฝๅผ๏ผŒ่€Œไธๅชๆ˜ฏๅฐ FastAPI ๆ‡‰็”จ็™ผ้€่ซ‹ๆฑ‚๏ผˆไพ‹ๅฆ‚้žๅŒๆญฅ็š„่ณ‡ๆ–™ๅบซๅ‡ฝๅผ๏ผ‰๏ผŒ่ซ‹ๅƒ่€ƒ้€ฒ้šŽๆ•™ๅญธไธญ็š„[้žๅŒๆญฅๆธฌ่ฉฆ](../advanced/async-tests.md){.internal-link target=_blank}ใ€‚ + +/// + +## ๅˆ†้›ขๆธฌ่ฉฆ { #separating-tests } + +ๅœจ็œŸๅฏฆๅฐˆๆกˆไธญ๏ผŒไฝ ๅคงๆฆ‚ๆœƒๆŠŠๆธฌ่ฉฆๆ”พๅœจไธๅŒ็š„ๆช”ๆกˆไธญใ€‚ + +ไฝ ็š„ **FastAPI** ๆ‡‰็”จไนŸๅฏ่ƒฝ็”ฑๅคšๅ€‹ๆช”ๆกˆ/ๆจก็ต„็ต„ๆˆ๏ผŒ็ญ‰็ญ‰ใ€‚ + +### **FastAPI** ๆ‡‰็”จๆช”ๆกˆ { #fastapi-app-file } + +ๅ‡่จญไฝ ็š„ๆช”ๆกˆ็ตๆง‹ๅฆ‚[ๆ›ดๅคงๅž‹็š„ๆ‡‰็”จ](bigger-applications.md){.internal-link target=_blank}ๆ‰€่ฟฐ๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ main.py +``` + +ๅœจ `main.py` ๆช”ๆกˆไธญๆœ‰ไฝ ็š„ **FastAPI** ๆ‡‰็”จ๏ผš + + +{* ../../docs_src/app_testing/app_a_py310/main.py *} + +### ๆธฌ่ฉฆๆช”ๆกˆ { #testing-file } + +็„ถๅพŒไฝ ๅฏไปฅๅปบ็ซ‹ไธ€ๅ€‹ `test_main.py` ๆ”พไฝ ็š„ๆธฌ่ฉฆใ€‚ๅฎƒๅฏไปฅ่ˆ‡ๆ‡‰็”จไฝๆ–ผๅŒไธ€ๅ€‹ Python ๅฅ—ไปถ๏ผˆๅŒไธ€ๅ€‹ๅŒ…ๅซ `__init__.py` ็š„็›ฎ้Œ„๏ผ‰๏ผš + +``` hl_lines="5" +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +ๅ› ็‚บ้€™ๅ€‹ๆช”ๆกˆๅœจๅŒไธ€ๅ€‹ๅฅ—ไปถไธญ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ็›ธๅฐๅŒฏๅ…ฅ๏ผŒๅพž `main` ๆจก็ต„๏ผˆ`main.py`๏ผ‰ๅŒฏๅ…ฅ `app` ้€™ๅ€‹็‰ฉไปถ๏ผš + +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + + +...็„ถๅพŒๆธฌ่ฉฆ็š„็จ‹ๅผ็ขผๅฐฑๅ’Œๅ…ˆๅ‰ไธ€ๆจฃใ€‚ + +## ๆธฌ่ฉฆ๏ผš้€ฒ้šŽ็ฏ„ไพ‹ { #testing-extended-example } + +็พๅœจๆˆ‘ๅ€‘ๅปถไผธ้€™ๅ€‹็ฏ„ไพ‹ไธฆๅŠ ๅ…ฅๆ›ดๅคš็ดฐ็ฏ€๏ผŒ็œ‹็œ‹ๅฆ‚ไฝ•ๆธฌ่ฉฆไธๅŒ้ƒจๅˆ†ใ€‚ + +### ๆ“ดๅ……็š„ **FastAPI** ๆ‡‰็”จๆช”ๆกˆ { #extended-fastapi-app-file } + +ๆฒฟ็”จๅ…ˆๅ‰็›ธๅŒ็š„ๆช”ๆกˆ็ตๆง‹๏ผš + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +ๅ‡่จญ็พๅœจไฝ ็š„ **FastAPI** ๆ‡‰็”จๆ‰€ๅœจ็š„ `main.py` ๆœ‰ไธ€ไบ›ๅ…ถไป–็š„่ทฏๅพ‘ๆ“ไฝœ๏ผˆpath operations๏ผ‰ใ€‚ + +ๅฎƒๆœ‰ไธ€ๅ€‹ๅฏ่ƒฝๅ›žๅ‚ณ้Œฏ่ชค็š„ `GET` ๆ“ไฝœใ€‚ + +ๅฎƒๆœ‰ไธ€ๅ€‹ๅฏ่ƒฝๅ›žๅ‚ณๅคš็จฎ้Œฏ่ชค็š„ `POST` ๆ“ไฝœใ€‚ + +ๅ…ฉๅ€‹่ทฏๅพ‘ๆ“ไฝœ้ƒฝ้œ€่ฆไธ€ๅ€‹ `X-Token` ๆจ™้ ญ๏ผˆheader๏ผ‰ใ€‚ + +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} + +### ๆ“ดๅ……็š„ๆธฌ่ฉฆๆช”ๆกˆ { #extended-testing-file } + +ๆŽฅ่‘—ไฝ ๅฏไปฅๆŠŠ `test_main.py` ๆ›ดๆ–ฐ็‚บๆ“ดๅ……ๅพŒ็š„ๆธฌ่ฉฆ๏ผš + +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + + +ๆฏ็•ถไฝ ้œ€่ฆๅœจ่ซ‹ๆฑ‚ไธญ่ฎ“ client ๅธถไธ€ไบ›่ณ‡ๆ–™๏ผŒไฝ†ไธ็ขบๅฎš่ฉฒๆ€Ž้บผๅšๆ™‚๏ผŒไฝ ๅฏไปฅๆœๅฐ‹๏ผˆGoogle๏ผ‰ๅœจ `httpx` ่ฆๅฆ‚ไฝ•ๅ‚ณ้ž๏ผŒ็”š่‡ณ็”จ Requests ๆ€Ž้บผๅš๏ผŒๅ› ็‚บ HTTPX ็š„่จญ่จˆๆ˜ฏๅŸบๆ–ผ Requestsใ€‚ + +็„ถๅพŒๅœจไฝ ็š„ๆธฌ่ฉฆไธญๅšไธ€ๆจฃ็š„ไบ‹ๅณๅฏใ€‚ + +ไพ‹ๅฆ‚๏ผš + +* ่ฆๅ‚ณ้ž่ทฏๅพ‘ๆˆ–ๆŸฅ่ฉขๅƒๆ•ธ๏ผŒ็›ดๆŽฅๆŠŠๅฎƒๅŠ ๅœจ URL ไธŠใ€‚ +* ่ฆๅ‚ณ้ž JSON ๆœฌๆ–‡๏ผŒๅฐ‡ Python ็‰ฉไปถ๏ผˆไพ‹ๅฆ‚ `dict`๏ผ‰ๅ‚ณ็ตฆ `json` ๅƒๆ•ธใ€‚ +* ๅฆ‚ๆžœ้œ€่ฆ้€ๅ‡บ่กจๅ–ฎ่ณ‡ๆ–™๏ผˆForm Data๏ผ‰่€Œไธๆ˜ฏ JSON๏ผŒๆ”น็”จ `data` ๅƒๆ•ธใ€‚ +* ่ฆๅ‚ณ้žๆจ™้ ญ๏ผˆheaders๏ผ‰๏ผŒๅœจ `headers` ๅƒๆ•ธไธญๆ”พไธ€ๅ€‹ `dict`ใ€‚ +* ๅฐๆ–ผ Cookie๏ผˆcookies๏ผ‰๏ผŒๅœจ `cookies` ๅƒๆ•ธไธญๆ”พไธ€ๅ€‹ `dict`ใ€‚ + +้—œๆ–ผๅฆ‚ไฝ•ๆŠŠ่ณ‡ๆ–™ๅ‚ณ็ตฆๅพŒ็ซฏ๏ผˆไฝฟ็”จ `httpx` ๆˆ– `TestClient`๏ผ‰๏ผŒๆ›ดๅคš่ณ‡่จŠ่ซ‹ๅƒ่€ƒ HTTPX ๆ–‡ไปถใ€‚ + +/// info + +่ซ‹ๆณจๆ„๏ผŒ`TestClient` ๆŽฅๆ”ถ็š„ๆ˜ฏๅฏ่ฝ‰็‚บ JSON ็š„่ณ‡ๆ–™๏ผŒ่€Œไธๆ˜ฏ Pydantic modelsใ€‚ + +ๅฆ‚ๆžœไฝ ็š„ๆธฌ่ฉฆ่ฃกๆœ‰ไธ€ๅ€‹ Pydantic model๏ผŒไธฆๆƒณๅœจๆธฌ่ฉฆๆ™‚ๆŠŠๅฎƒ็š„่ณ‡ๆ–™้€็ตฆๆ‡‰็”จ๏ผŒไฝ ๅฏไปฅไฝฟ็”จ[JSON ็›ธๅฎน็ทจ็ขผๅ™จ](encoder.md){.internal-link target=_blank}ไธญไป‹็ดน็š„ `jsonable_encoder`ใ€‚ + +/// + +## ๅŸท่กŒ { #run-it } + +ๆŽฅไธ‹ไพ†๏ผŒไฝ ๅช้œ€่ฆๅฎ‰่ฃ `pytest`ใ€‚ + +่ซ‹ๅ…ˆๅปบ็ซ‹ไธฆๅ•Ÿ็”จไธ€ๅ€‹[่™›ๆ“ฌ็’ฐๅขƒ](../virtual-environments.md){.internal-link target=_blank}๏ผŒ็„ถๅพŒๅฎ‰่ฃ๏ผŒไพ‹ๅฆ‚๏ผš + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +ๅฎƒๆœƒ่‡ชๅ‹•ๅตๆธฌๆช”ๆกˆ่ˆ‡ๆธฌ่ฉฆใ€ๅŸท่กŒๅฎƒๅ€‘๏ผŒไธฆๆŠŠ็ตๆžœๅ›žๅ ฑ็ตฆไฝ ใ€‚ + +็”จไปฅไธ‹ๆŒ‡ไปคๅŸท่กŒๆธฌ่ฉฆ๏ผš + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index acd1d914ea..74b8b9f8c8 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -30,7 +30,7 @@ ้ฆ–ๅ…ˆ๏ผŒ็‚บไฝ ็š„ๅฐˆๆกˆๅปบ็ซ‹ไธ€ๅ€‹็›ฎ้Œ„ใ€‚ -ๆˆ‘๏ผˆๆŒ‡ๅŽŸไฝœ่€… โ€”โ€” ่ญฏ่€…ๆณจ๏ผ‰้€šๅธธๆœƒๅœจๆˆ‘็š„ไธป็›ฎ้Œ„ไธ‹ๅปบ็ซ‹ไธ€ๅ€‹ๅ็‚บ `code` ็š„็›ฎ้Œ„ใ€‚ +ๆˆ‘้€šๅธธๆœƒๅœจๆˆ‘็š„ไธป็›ฎ้Œ„ไธ‹ๅปบ็ซ‹ไธ€ๅ€‹ๅ็‚บ `code` ็š„็›ฎ้Œ„ใ€‚ ๅœจ้€™ๅ€‹็›ฎ้Œ„ไธ‹๏ผŒๆˆ‘ๅ†็‚บๆฏๅ€‹ๅฐˆๆกˆๅปบ็ซ‹ไธ€ๅ€‹็›ฎ้Œ„ใ€‚ @@ -53,7 +53,7 @@ $ cd awesome-project ## ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒ { #create-a-virtual-environment } -ๅœจ้–‹ๅง‹ไธ€ๅ€‹ Python ๅฐˆๆกˆ็š„**็ฌฌไธ€ๆ™‚้–“**๏ผŒ**ๅœจไฝ ็š„ๅฐˆๆกˆๅ…ง้ƒจ**ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒใ€‚ +ๅœจ้–‹ๅง‹ไธ€ๅ€‹ Python ๅฐˆๆกˆ็š„**็ฌฌไธ€ๆ™‚้–“**๏ผŒ**ๅœจไฝ ็š„ๅฐˆๆกˆๅ…ง้ƒจ**ๅปบ็ซ‹ไธ€ๅ€‹่™›ๆ“ฌ็’ฐๅขƒใ€‚ /// tip @@ -412,7 +412,7 @@ Hello World ## ่จญๅฎš็ทจ่ผฏๅ™จ { #configure-your-editor } -ไฝ ๅฏ่ƒฝๆœƒ็”จๅˆฐ็ทจ่ผฏๅ™จ๏ผŒ่ซ‹็ขบไฟ่จญๅฎšๅฎƒไฝฟ็”จไฝ ๅปบ็ซ‹็š„็›ธๅŒ่™›ๆ“ฌ็’ฐๅขƒ๏ผˆๅฎƒๅฏ่ƒฝๆœƒ่‡ชๅ‹•ๅตๆธฌๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ็ฒๅพ—่‡ชๅ‹•ๅฎŒๆˆๅ’Œๅ†…ๅตŒ้Œฏ่ชคๆ็คบใ€‚ +ไฝ ๅฏ่ƒฝๆœƒ็”จๅˆฐ็ทจ่ผฏๅ™จ๏ผŒ่ซ‹็ขบไฟ่จญๅฎšๅฎƒไฝฟ็”จไฝ ๅปบ็ซ‹็š„็›ธๅŒ่™›ๆ“ฌ็’ฐๅขƒ๏ผˆๅฎƒๅฏ่ƒฝๆœƒ่‡ชๅ‹•ๅตๆธฌๅˆฐ๏ผ‰๏ผŒไปฅไพฟไฝ ๅฏไปฅ็ฒๅพ—่‡ชๅ‹•ๅฎŒๆˆๅ’Œๅ…งๅตŒ้Œฏ่ชคๆ็คบใ€‚ ไพ‹ๅฆ‚๏ผš From 12f7e656709d570110dd26e6187b27e40442b8a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Feb 2026 08:15:47 +0000 Subject: [PATCH 240/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5ba810aeab..5e1eaf9372 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for zh-hant (update-all and add-missing). PR [#14921](https://github.com/fastapi/fastapi/pull/14921) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for fr (update-all and add-missing). PR [#14920](https://github.com/fastapi/fastapi/pull/14920) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-all) . PR [#14910](https://github.com/fastapi/fastapi/pull/14910) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov). From ec35d6d380a243fa693633fd40d60a465c47f7c9 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:43:14 +0100 Subject: [PATCH 241/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(add-missing)=20(#14922)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/uk/docs/_llm-test.md | 502 ++++++++++ docs/uk/docs/about/index.md | 3 + docs/uk/docs/advanced/additional-responses.md | 247 +++++ .../docs/advanced/additional-status-codes.md | 41 + .../uk/docs/advanced/advanced-dependencies.md | 163 ++++ .../uk/docs/advanced/advanced-python-types.md | 61 ++ docs/uk/docs/advanced/async-tests.md | 99 ++ docs/uk/docs/advanced/behind-a-proxy.md | 466 ++++++++++ docs/uk/docs/advanced/custom-response.md | 312 +++++++ docs/uk/docs/advanced/dataclasses.md | 95 ++ docs/uk/docs/advanced/events.md | 165 ++++ docs/uk/docs/advanced/generate-clients.md | 208 +++++ docs/uk/docs/advanced/index.md | 21 + docs/uk/docs/advanced/middleware.md | 97 ++ docs/uk/docs/advanced/openapi-callbacks.md | 186 ++++ docs/uk/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 172 ++++ .../advanced/response-change-status-code.md | 31 + docs/uk/docs/advanced/response-cookies.md | 51 ++ docs/uk/docs/advanced/response-directly.md | 65 ++ docs/uk/docs/advanced/response-headers.md | 41 + .../docs/advanced/security/http-basic-auth.md | 107 +++ docs/uk/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++ docs/uk/docs/advanced/settings.md | 302 ++++++ docs/uk/docs/advanced/sub-applications.md | 67 ++ docs/uk/docs/advanced/templates.md | 126 +++ docs/uk/docs/advanced/testing-dependencies.md | 53 ++ docs/uk/docs/advanced/testing-events.md | 11 + docs/uk/docs/advanced/testing-websockets.md | 13 + .../docs/advanced/using-request-directly.md | 55 ++ docs/uk/docs/advanced/websockets.md | 186 ++++ docs/uk/docs/advanced/wsgi.md | 51 ++ docs/uk/docs/async.md | 444 +++++++++ docs/uk/docs/benchmarks.md | 34 + docs/uk/docs/deployment/cloud.md | 24 + docs/uk/docs/deployment/concepts.md | 321 +++++++ docs/uk/docs/deployment/docker.md | 618 +++++++++++++ docs/uk/docs/deployment/fastapicloud.md | 65 ++ docs/uk/docs/deployment/https.md | 231 +++++ docs/uk/docs/deployment/index.md | 23 + docs/uk/docs/deployment/manually.md | 157 ++++ docs/uk/docs/deployment/server-workers.md | 139 +++ docs/uk/docs/deployment/versions.md | 93 ++ docs/uk/docs/environment-variables.md | 298 ++++++ docs/uk/docs/help-fastapi.md | 256 ++++++ docs/uk/docs/history-design-future.md | 79 ++ .../authentication-error-status-code.md | 17 + docs/uk/docs/how-to/conditional-openapi.md | 56 ++ docs/uk/docs/how-to/configure-swagger-ui.md | 70 ++ docs/uk/docs/how-to/custom-docs-ui-assets.md | 185 ++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/uk/docs/how-to/extending-openapi.md | 80 ++ docs/uk/docs/how-to/general.md | 39 + docs/uk/docs/how-to/graphql.md | 60 ++ docs/uk/docs/how-to/index.md | 13 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 135 +++ .../docs/how-to/separate-openapi-schemas.md | 101 ++ docs/uk/docs/how-to/testing-database.md | 7 + docs/uk/docs/project-generation.md | 28 + docs/uk/docs/resources/index.md | 3 + docs/uk/docs/translation-banner.md | 11 + docs/uk/docs/tutorial/bigger-applications.md | 504 ++++++++++ .../dependencies/classes-as-dependencies.md | 288 ++++++ ...pendencies-in-path-operation-decorators.md | 69 ++ .../dependencies/dependencies-with-yield.md | 289 ++++++ .../dependencies/global-dependencies.md | 15 + docs/uk/docs/tutorial/dependencies/index.md | 250 +++++ .../tutorial/dependencies/sub-dependencies.md | 105 +++ docs/uk/docs/tutorial/extra-models.md | 211 +++++ .../tutorial/path-operation-configuration.md | 107 +++ docs/uk/docs/tutorial/security/first-steps.md | 203 +++++ .../tutorial/security/get-current-user.md | 105 +++ docs/uk/docs/tutorial/security/oauth2-jwt.md | 277 ++++++ .../docs/tutorial/security/simple-oauth2.md | 289 ++++++ docs/uk/docs/tutorial/sql-databases.md | 357 ++++++++ docs/uk/docs/virtual-environments.md | 862 ++++++++++++++++++ 77 files changed, 11972 insertions(+) create mode 100644 docs/uk/docs/_llm-test.md create mode 100644 docs/uk/docs/about/index.md create mode 100644 docs/uk/docs/advanced/additional-responses.md create mode 100644 docs/uk/docs/advanced/additional-status-codes.md create mode 100644 docs/uk/docs/advanced/advanced-dependencies.md create mode 100644 docs/uk/docs/advanced/advanced-python-types.md create mode 100644 docs/uk/docs/advanced/async-tests.md create mode 100644 docs/uk/docs/advanced/behind-a-proxy.md create mode 100644 docs/uk/docs/advanced/custom-response.md create mode 100644 docs/uk/docs/advanced/dataclasses.md create mode 100644 docs/uk/docs/advanced/events.md create mode 100644 docs/uk/docs/advanced/generate-clients.md create mode 100644 docs/uk/docs/advanced/index.md create mode 100644 docs/uk/docs/advanced/middleware.md create mode 100644 docs/uk/docs/advanced/openapi-callbacks.md create mode 100644 docs/uk/docs/advanced/openapi-webhooks.md create mode 100644 docs/uk/docs/advanced/path-operation-advanced-configuration.md create mode 100644 docs/uk/docs/advanced/response-change-status-code.md create mode 100644 docs/uk/docs/advanced/response-cookies.md create mode 100644 docs/uk/docs/advanced/response-directly.md create mode 100644 docs/uk/docs/advanced/response-headers.md create mode 100644 docs/uk/docs/advanced/security/http-basic-auth.md create mode 100644 docs/uk/docs/advanced/security/index.md create mode 100644 docs/uk/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/uk/docs/advanced/settings.md create mode 100644 docs/uk/docs/advanced/sub-applications.md create mode 100644 docs/uk/docs/advanced/templates.md create mode 100644 docs/uk/docs/advanced/testing-dependencies.md create mode 100644 docs/uk/docs/advanced/testing-events.md create mode 100644 docs/uk/docs/advanced/testing-websockets.md create mode 100644 docs/uk/docs/advanced/using-request-directly.md create mode 100644 docs/uk/docs/advanced/websockets.md create mode 100644 docs/uk/docs/advanced/wsgi.md create mode 100644 docs/uk/docs/async.md create mode 100644 docs/uk/docs/benchmarks.md create mode 100644 docs/uk/docs/deployment/cloud.md create mode 100644 docs/uk/docs/deployment/concepts.md create mode 100644 docs/uk/docs/deployment/docker.md create mode 100644 docs/uk/docs/deployment/fastapicloud.md create mode 100644 docs/uk/docs/deployment/https.md create mode 100644 docs/uk/docs/deployment/index.md create mode 100644 docs/uk/docs/deployment/manually.md create mode 100644 docs/uk/docs/deployment/server-workers.md create mode 100644 docs/uk/docs/deployment/versions.md create mode 100644 docs/uk/docs/environment-variables.md create mode 100644 docs/uk/docs/help-fastapi.md create mode 100644 docs/uk/docs/history-design-future.md create mode 100644 docs/uk/docs/how-to/authentication-error-status-code.md create mode 100644 docs/uk/docs/how-to/conditional-openapi.md create mode 100644 docs/uk/docs/how-to/configure-swagger-ui.md create mode 100644 docs/uk/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/uk/docs/how-to/custom-request-and-route.md create mode 100644 docs/uk/docs/how-to/extending-openapi.md create mode 100644 docs/uk/docs/how-to/general.md create mode 100644 docs/uk/docs/how-to/graphql.md create mode 100644 docs/uk/docs/how-to/index.md create mode 100644 docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/uk/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/uk/docs/how-to/testing-database.md create mode 100644 docs/uk/docs/project-generation.md create mode 100644 docs/uk/docs/resources/index.md create mode 100644 docs/uk/docs/translation-banner.md create mode 100644 docs/uk/docs/tutorial/bigger-applications.md create mode 100644 docs/uk/docs/tutorial/dependencies/classes-as-dependencies.md create mode 100644 docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md create mode 100644 docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md create mode 100644 docs/uk/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/uk/docs/tutorial/dependencies/index.md create mode 100644 docs/uk/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/uk/docs/tutorial/extra-models.md create mode 100644 docs/uk/docs/tutorial/path-operation-configuration.md create mode 100644 docs/uk/docs/tutorial/security/first-steps.md create mode 100644 docs/uk/docs/tutorial/security/get-current-user.md create mode 100644 docs/uk/docs/tutorial/security/oauth2-jwt.md create mode 100644 docs/uk/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/uk/docs/tutorial/sql-databases.md create mode 100644 docs/uk/docs/virtual-environments.md diff --git a/docs/uk/docs/_llm-test.md b/docs/uk/docs/_llm-test.md new file mode 100644 index 0000000000..0dbfaa3db4 --- /dev/null +++ b/docs/uk/docs/_llm-test.md @@ -0,0 +1,502 @@ +# ะขะตัั‚ะพะฒะธะน ั„ะฐะนะป LLM { #llm-test-file } + +ะฆะตะน ะดะพะบัƒะผะตะฝั‚ ะฟะตั€ะตะฒั–ั€ัั”, ั‡ะธ ั€ะพะทัƒะผั–ั” LLM, ัะบะธะน ะฟะตั€ะตะบะปะฐะดะฐั” ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ, `general_prompt` ัƒ `scripts/translate.py` ั‚ะฐ ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝัƒ ะฟั–ะดัะบะฐะทะบัƒ ะฒ `docs/{language code}/llm-prompt.md`. ะœะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝะฐ ะฟั–ะดัะบะฐะทะบะฐ ะดะพะดะฐั”ั‚ัŒัั ะดะพ `general_prompt`. + +ะขะตัั‚ะธ, ะดะพะดะฐะฝั– ั‚ัƒั‚, ะฟะพะฑะฐั‡ะฐั‚ัŒ ัƒัั– ะฐะฒั‚ะพั€ะธ ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝะธั… ะฟั–ะดัะบะฐะทะพะบ. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั‚ะฐะบ: + +* ะœะฐะนั‚ะต ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝัƒ ะฟั–ะดัะบะฐะทะบัƒ - `docs/{language code}/llm-prompt.md`. +* ะ—ั€ะพะฑั–ั‚ัŒ ัะฒั–ะถะธะน ะฟะตั€ะตะบะปะฐะด ั†ัŒะพะณะพ ะดะพะบัƒะผะตะฝั‚ะฐ ะฝะฐ ะฑะฐะถะฐะฝัƒ ั†ั–ะปัŒะพะฒัƒ ะผะพะฒัƒ (ะดะธะฒ., ะฝะฐะฟั€ะธะบะปะฐะด, ะบะพะผะฐะฝะดัƒ `translate-page` ัƒ `translate.py`). ะฆะต ัั‚ะฒะพั€ะธั‚ัŒ ะฟะตั€ะตะบะปะฐะด ัƒ `docs/{language code}/docs/_llm-test.md`. +* ะŸะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ ะฒัะต ะณะฐั€ะฐะทะด ัƒ ะฟะตั€ะตะบะปะฐะดั–. +* ะ—ะฐ ะฟะพั‚ั€ะตะฑะธ ะฟะพะบั€ะฐั‰ั–ั‚ัŒ ะฒะฐัˆัƒ ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝัƒ ะฟั–ะดัะบะฐะทะบัƒ, ะทะฐะณะฐะปัŒะฝัƒ ะฟั–ะดัะบะฐะทะบัƒ ะฐะฑะพ ะฐะฝะณะปั–ะนััŒะบะธะน ะดะพะบัƒะผะตะฝั‚. +* ะŸะพั‚ั–ะผ ะฒั€ัƒั‡ะฝัƒ ะฒะธะฟั€ะฐะฒั‚ะต ั€ะตัˆั‚ัƒ ะฟั€ะพะฑะปะตะผ ัƒ ะฟะตั€ะตะบะปะฐะดั–, ั‰ะพะฑ ะฒั–ะฝ ะฑัƒะฒ ัะบั–ัะฝะธะผ. +* ะŸะตั€ะตะบะปะฐะดั–ั‚ัŒ ะฟะพะฒั‚ะพั€ะฝะพ, ะผะฐัŽั‡ะธ ัะบั–ัะฝะธะน ะฟะตั€ะตะบะปะฐะด ะฝะฐ ะผั–ัั†ั–. ะ†ะดะตะฐะปัŒะฝะธะน ั€ะตะทัƒะปัŒั‚ะฐั‚ - ะบะพะปะธ LLM ะฑั–ะปัŒัˆะต ะฝะต ะฒะฝะพัะธั‚ัŒ ะทะผั–ะฝ ะดะพ ะฟะตั€ะตะบะปะฐะดัƒ. ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะทะฐะณะฐะปัŒะฝะฐ ะฟั–ะดัะบะฐะทะบะฐ ั‚ะฐ ะฒะฐัˆะฐ ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝะฐ ะฟั–ะดัะบะฐะทะบะฐ ะฝะฐัั‚ั–ะปัŒะบะธ ะดะพะฑั€ั–, ะฝะฐัะบั–ะปัŒะบะธ ั†ะต ะผะพะถะปะธะฒะพ (ั–ะฝะบะพะปะธ ะฒั–ะฝ ั€ะพะฑะธั‚ะธะผะต ะบั–ะปัŒะบะฐ, ะทะดะฐะฒะฐะปะพัั ะฑ, ะฒะธะฟะฐะดะบะพะฒะธั… ะทะผั–ะฝ, ะฟั€ะธั‡ะธะฝะฐ ะฒ ั‚ะพะผัƒ, ั‰ะพ LLM-ะธ ะฝะต ั” ะดะตั‚ะตั€ะผั–ะฝั–ัั‚ะธั‡ะฝะธะผะธ ะฐะปะณะพั€ะธั‚ะผะฐะผะธ). + +ะขะตัั‚ะธ: + +## ะคั€ะฐะณะผะตะฝั‚ะธ ะบะพะดัƒ { #code-snippets } + +//// tab | ะขะตัั‚ + +ะฆะต ั„ั€ะฐะณะผะตะฝั‚ ะบะพะดัƒ: `foo`. ะ ั†ะต ั‰ะต ะพะดะธะฝ ั„ั€ะฐะณะผะตะฝั‚ ะบะพะดัƒ: `bar`. ะ† ั‰ะต ะพะดะธะฝ: `baz quux`. + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ’ะผั–ัั‚ ั„ั€ะฐะณะผะตะฝั‚ั–ะฒ ะบะพะดัƒ ัะปั–ะด ะทะฐะปะธัˆะฐั‚ะธ ะฑะตะท ะทะผั–ะฝ. + +ะ”ะธะฒ. ั€ะพะทะดั–ะป `### Content of code snippets` ะฒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +//// + +## ะฆะธั‚ะฐั‚ะธ { #quotes } + +//// tab | ะขะตัั‚ + +ะ’ั‡ะพั€ะฐ ะผั–ะน ะดั€ัƒะณ ะฝะฐะฟะธัะฐะฒ: ยซะฏะบั‰ะพ ะฒะธ ะฟั€ะฐะฒะธะปัŒะฝะพ ะฝะฐะฟะธัˆะตั‚ะต "incorrectly", ะฒะธ ะฝะฐะฟะธัะฐะปะธ ั†ะต ะฝะตะฟั€ะฐะฒะธะปัŒะฝะพยป. ะะฐ ั‰ะพ ั ะฒั–ะดะฟะพะฒั–ะฒ: ยซะŸั€ะฐะฒะธะปัŒะฝะพ, ะฐะปะต 'incorrectly' - ั†ะต ะฝะตะฟั€ะฐะฒะธะปัŒะฝะพ, ะฐ ะฝะต '"incorrectly"'ยป. + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +LLM, ะนะผะพะฒั–ั€ะฝะพ, ะฟะตั€ะตะบะปะฐะดะต ั†ะต ะฝะตะฟั€ะฐะฒะธะปัŒะฝะพ. ะฆั–ะบะฐะฒะพ ะปะธัˆะต ั‚ะต, ั‡ะธ ะทะฑะตั€ะตะถะต ะฒั–ะฝ ะฒะธะฟั€ะฐะฒะปะตะฝะธะน ะฟะตั€ะตะบะปะฐะด ะฟั–ะด ั‡ะฐั ะฟะพะฒั‚ะพั€ะฝะพะณะพ ะฟะตั€ะตะบะปะฐะดัƒ. + +/// + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะะฒั‚ะพั€ ะฟั–ะดัะบะฐะทะบะธ ะผะพะถะต ะพะฑั€ะฐั‚ะธ, ั‡ะธ ะบะพะฝะฒะตั€ั‚ัƒะฒะฐั‚ะธ ะฝะตะนั‚ั€ะฐะปัŒะฝั– ะปะฐะฟะบะธ ะฒ ั‚ะธะฟะพะณั€ะฐั„ััŒะบั–. ะœะพะถะฝะฐ ะทะฐะปะธัˆะธั‚ะธ ัะบ ั”. + +ะ”ะธะฒ., ะฝะฐะฟั€ะธะบะปะฐะด, ั€ะพะทะดั–ะป `### Quotes` ัƒ `docs/de/llm-prompt.md`. + +//// + +## ะ›ะฐะฟะบะธ ัƒ ั„ั€ะฐะณะผะตะฝั‚ะฐั… ะบะพะดัƒ { #quotes-in-code-snippets } + +//// tab | ะขะตัั‚ + +`pip install "foo[bar]"` + +ะŸั€ะธะบะปะฐะดะธ ัั‚ั€ะพะบะพะฒะธั… ะปั–ั‚ะตั€ะฐะปั–ะฒ ัƒ ั„ั€ะฐะณะผะตะฝั‚ะฐั… ะบะพะดัƒ: `"this"`, `'that'`. + +ะกะบะปะฐะดะฝะธะน ะฟั€ะธะบะปะฐะด ัั‚ั€ะพะบะพะฒะธั… ะปั–ั‚ะตั€ะฐะปั–ะฒ ัƒ ั„ั€ะฐะณะผะตะฝั‚ะฐั… ะบะพะดัƒ: `f"I like {'oranges' if orange else "apples"}"` + +ะฅะฐั€ะดะบะพั€: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +... ะžะดะฝะฐะบ ะปะฐะฟะบะธ ะฒัะตั€ะตะดะธะฝั– ั„ั€ะฐะณะผะตะฝั‚ั–ะฒ ะบะพะดัƒ ะผะฐัŽั‚ัŒ ะทะฐะปะธัˆะฐั‚ะธัั ัะบ ั”. + +//// + +## ะ‘ะปะพะบะธ ะบะพะดัƒ { #code-blocks } + +//// tab | ะขะตัั‚ + +ะŸั€ะธะบะปะฐะด ะบะพะดัƒ Bash... + +```bash +# ะ’ะธะฒะตัั‚ะธ ะฟั€ะธะฒั–ั‚ะฐะฝะฝั ะฒัะตัะฒั–ั‚ัƒ +echo "Hello universe" +``` + +...ั– ะฟั€ะธะบะปะฐะด ะบะพะดัƒ ะบะพะฝัะพะปั–... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...ั– ั‰ะต ะพะดะธะฝ ะฟั€ะธะบะปะฐะด ะบะพะดัƒ ะบะพะฝัะพะปั–... + +```console +// ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะฐั‚ะฐะปะพะณ "code" +$ mkdir code +// ะŸะตั€ะตะนะดั–ั‚ัŒ ะดะพ ั†ัŒะพะณะพ ะบะฐั‚ะฐะปะพะณัƒ +$ cd code +``` + +...ั– ะฟั€ะธะบะปะฐะด ะบะพะดัƒ Python... + +```Python +wont_work() # ะฆะต ะฝะต ัะฟั€ะฐั†ัŽั” ๐Ÿ˜ฑ +works(foo="bar") # ะฆะต ะฟั€ะฐั†ัŽั” ๐ŸŽ‰ +``` + +...ั– ั†ะต ะฒัะต. + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะšะพะด ัƒ ะฑะปะพะบะฐั… ะบะพะดัƒ ะฝะต ัะปั–ะด ะทะผั–ะฝัŽะฒะฐั‚ะธ, ะทะฐ ะฒะธะฝัั‚ะบะพะผ ะบะพะผะตะฝั‚ะฐั€ั–ะฒ. + +ะ”ะธะฒ. ั€ะพะทะดั–ะป `### Content of code blocks` ะฒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +//// + +## ะ’ะบะปะฐะดะบะธ ั‚ะฐ ะบะพะปัŒะพั€ะพะฒั– ะฑะปะพะบะธ { #tabs-and-colored-boxes } + +//// tab | ะขะตัั‚ + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั +Some text +/// + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ +Some text +/// + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– +Some text +/// + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต +Some text +/// + +/// tip | ะŸะพั€ะฐะดะฐ +Some text +/// + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั +Some text +/// + +/// danger | ะžะฑะตั€ะตะถะฝะพ +Some text +/// + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฃ ะฒะบะปะฐะดะบะฐั… ั– ะฑะปะพะบะฐั… `Info`/`Note`/`Warning`/ั‚ะพั‰ะพ ะฝะตะพะฑั…ั–ะดะฝะพ ะดะพะดะฐั‚ะธ ะฟะตั€ะตะบะปะฐะด ั—ั…ะฝัŒะพะณะพ ะทะฐะณะพะปะพะฒะบะฐ ะฟั–ัะปั ะฒะตั€ั‚ะธะบะฐะปัŒะฝะพั— ั€ะธัะบะธ (`|`). + +ะ”ะธะฒ. ั€ะพะทะดั–ะปะธ `### Special blocks` ั– `### Tab blocks` ะฒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +//// + +## ะ’ะตะฑ- ั– ะฒะฝัƒั‚ั€ั–ัˆะฝั– ะฟะพัะธะปะฐะฝะฝั { #web-and-internal-links } + +//// tab | ะขะตัั‚ + +ะขะตะบัั‚ ะฟะพัะธะปะฐะฝะฝั ะผะฐั” ะฑัƒั‚ะธ ะฟะตั€ะตะบะปะฐะดะตะฝะธะน, ะฐะดั€ะตัะฐ ะฟะพัะธะปะฐะฝะฝั ะผะฐั” ะทะฐะปะธัˆะธั‚ะธัั ะฝะตะทะผั–ะฝะฝะพัŽ: + +* [ะŸะพัะธะปะฐะฝะฝั ะฝะฐ ะทะฐะณะพะปะพะฒะพะบ ะฒะธั‰ะต](#code-snippets) +* [ะ’ะฝัƒั‚ั€ั–ัˆะฝั” ะฟะพัะธะปะฐะฝะฝั](index.md#installation){.internal-link target=_blank} +* ะ—ะพะฒะฝั–ัˆะฝั” ะฟะพัะธะปะฐะฝะฝั +* ะŸะพัะธะปะฐะฝะฝั ะฝะฐ ัั‚ะธะปัŒ +* ะŸะพัะธะปะฐะฝะฝั ะฝะฐ ัะบั€ะธะฟั‚ +* ะŸะพัะธะปะฐะฝะฝั ะฝะฐ ะทะพะฑั€ะฐะถะตะฝะฝั + +ะขะตะบัั‚ ะฟะพัะธะปะฐะฝะฝั ะผะฐั” ะฑัƒั‚ะธ ะฟะตั€ะตะบะปะฐะดะตะฝะธะน, ะฐะดั€ะตัะฐ ะฟะพัะธะปะฐะฝะฝั ะผะฐั” ะฒะบะฐะทัƒะฒะฐั‚ะธ ะฝะฐ ะฟะตั€ะตะบะปะฐะด: + +* ะŸะพัะธะปะฐะฝะฝั ะฝะฐ FastAPI + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะพัะธะปะฐะฝะฝั ัะปั–ะด ะฟะตั€ะตะบะปะฐะดะฐั‚ะธ, ะฐะปะต ั—ั…ะฝั– ะฐะดั€ะตัะธ ะผะฐัŽั‚ัŒ ะปะธัˆะฐั‚ะธัั ะฝะตะทะผั–ะฝะฝะธะผะธ. ะ’ะธะฝัั‚ะพะบ - ะฐะฑัะพะปัŽั‚ะฝั– ะฟะพัะธะปะฐะฝะฝั ะฝะฐ ัั‚ะพั€ั–ะฝะบะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— FastAPI. ะฃ ั‚ะฐะบะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะพะฝะธ ะผะฐัŽั‚ัŒ ะฒะบะฐะทัƒะฒะฐั‚ะธ ะฝะฐ ะฟะตั€ะตะบะปะฐะด. + +ะ”ะธะฒ. ั€ะพะทะดั–ะป `### Links` ะฒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +//// + +## ะ•ะปะตะผะตะฝั‚ะธ HTML ยซabbrยป { #html-abbr-elements } + +//// tab | ะขะตัั‚ + +ะžััŒ ะดะตัะบั– ั€ะตั‡ั–, ะพะฑะณะพั€ะฝัƒั‚ั– ะฒ ะตะปะตะผะตะฝั‚ะธ HTML ยซabbrยป (ะดะตัะบั– ะฒะธะณะฐะดะฐะฝั–): + +### ะกะบะพั€ะพั‡ะตะฝะฝั ะผั–ัั‚ะธั‚ัŒ ะฟะพะฒะฝัƒ ั„ั€ะฐะทัƒ { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### ะกะบะพั€ะพั‡ะตะฝะฝั ะผั–ัั‚ะธั‚ัŒ ะฟะพะฒะฝัƒ ั„ั€ะฐะทัƒ ั‚ะฐ ะฟะพััะฝะตะฝะฝั { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะั‚ั€ะธะฑัƒั‚ะธ "title" ะตะปะตะผะตะฝั‚ั–ะฒ "abbr" ะฟะตั€ะตะบะปะฐะดะฐัŽั‚ัŒัั ะทะฐ ะฟะตะฒะฝะธะผะธ ั–ะฝัั‚ั€ัƒะบั†ั–ัะผะธ. + +ะŸะตั€ะตะบะปะฐะดะธ ะผะพะถัƒั‚ัŒ ะดะพะดะฐะฒะฐั‚ะธ ะฒะปะฐัะฝั– ะตะปะตะผะตะฝั‚ะธ "abbr", ัะบั– LLM ะฝะต ะฟะพะฒะธะฝะตะฝ ะฟั€ะธะฑะธั€ะฐั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฟะพััะฝะธั‚ะธ ะฐะฝะณะปั–ะนััŒะบั– ัะปะพะฒะฐ. + +ะ”ะธะฒ. ั€ะพะทะดั–ะป `### HTML abbr elements` ะฒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +//// + +## ะ•ะปะตะผะตะฝั‚ะธ HTML ยซdfnยป { #html-dfn-elements } + +* ะบะปะฐัั‚ะตั€ +* ะ“ะปะธะฑะพะบะต ะฝะฐะฒั‡ะฐะฝะฝั + +## ะ—ะฐะณะพะปะพะฒะบะธ { #headings } + +//// tab | ะขะตัั‚ + +### ะ ะพะทั€ะพะฑะบะฐ ะฒะตะฑะทะฐัั‚ะพััƒะฝะบัƒ - ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ { #develop-a-webapp-a-tutorial } + +ะŸั€ะธะฒั–ั‚. + +### ะŸั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ ั‚ะฐ - ะฐะฝะพั‚ะฐั†ั–ั— { #type-hints-and-annotations } + +ะฉะต ั€ะฐะท ะฟั€ะธะฒั–ั‚. + +### ะกัƒะฟะตั€- ั‚ะฐ ะฟั–ะดะบะปะฐัะธ { #super-and-subclasses } + +ะฉะต ั€ะฐะท ะฟั€ะธะฒั–ั‚. + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ„ะดะธะฝะต ะถะพั€ัั‚ะบะต ะฟั€ะฐะฒะธะปะพ ะดะปั ะทะฐะณะพะปะพะฒะบั–ะฒ - LLM ะผะฐั” ะทะฐะปะธัˆะฐั‚ะธ ั…ะตัˆ-ั‡ะฐัั‚ะธะฝัƒ ะฒ ั„ั–ะณัƒั€ะฝะธั… ะดัƒะถะบะฐั… ะฝะตะทะผั–ะฝะฝะพัŽ, ั‰ะพะฑ ะฟะพัะธะปะฐะฝะฝั ะฝะต ะปะฐะผะฐะปะธัั. + +ะ”ะธะฒ. ั€ะพะทะดั–ะป `### Headings` ัƒ ะทะฐะณะฐะปัŒะฝั–ะน ะฟั–ะดัะบะฐะทั†ั– ะฒ `scripts/translate.py`. + +ะ”ะปั ะดะตัะบะธั… ะผะพะฒะฝะพ-ัะฟะตั†ะธั„ั–ั‡ะฝะธั… ั–ะฝัั‚ั€ัƒะบั†ั–ะน ะดะธะฒ., ะฝะฐะฟั€ะธะบะปะฐะด, ั€ะพะทะดั–ะป `### Headings` ัƒ `docs/de/llm-prompt.md`. + +//// + +## ะขะตั€ะผั–ะฝะธ, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #terms-used-in-the-docs } + +//// tab | ะขะตัั‚ + +* ะฒะธ +* ะฒะฐัˆ + +* ะฝะฐะฟั€. +* ั‚ะพั‰ะพ + +* `foo` ัะบ `int` +* `bar` ัะบ `str` +* `baz` ัะบ `list` + +* ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะšะตั€ั–ะฒะฝะธั†ั‚ะฒะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ +* ะฟั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ +* ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั SQLModel +* ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API +* ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั + +* ะะฐัƒะบะฐ ะฟั€ะพ ะดะฐะฝั– +* ะณะปะธะฑะพะบะต ะฝะฐะฒั‡ะฐะฝะฝั +* ะผะฐัˆะธะฝะฝะต ะฝะฐะฒั‡ะฐะฝะฝั +* ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน +* HTTP ะฑะฐะทะพะฒะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั +* HTTP ะดะฐะนะดะถะตัั‚ +* ั„ะพั€ะผะฐั‚ ISO +* ัั‚ะฐะฝะดะฐั€ั‚ ะกั…ะตะผะธ JSON +* ะกั…ะตะผะฐ JSON +* ะฒะธะทะฝะฐั‡ะตะฝะฝั ัั…ะตะผะธ +* ะฟะพั‚ั–ะบ ะฟะฐั€ะพะปัŽ +* ะผะพะฑั–ะปัŒะฝะธะน + +* ะทะฐัั‚ะฐั€ั–ะปะต +* ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะพ +* ะฝะตะดั–ะนัะฝะธะน +* ะฝะฐ ะปัŒะพั‚ัƒ +* ัั‚ะฐะฝะดะฐั€ั‚ +* ั‚ะธะฟะพะฒะต +* ั‡ัƒั‚ะปะธะฒะธะน ะดะพ ั€ะตะณั–ัั‚ั€ัƒ +* ะฝะตั‡ัƒั‚ะปะธะฒะธะน ะดะพ ั€ะตะณั–ัั‚ั€ัƒ + +* ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ +* ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ัั‚ะพั€ั–ะฝะบัƒ + +* ะทะฐัั‚ะพััƒะฝะพะบ +* ะทะฐัั‚ะพััƒะฝะพะบ + +* ะทะฐะฟะธั‚ +* ะฒั–ะดะฟะพะฒั–ะดัŒ +* ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฟะพะผะธะปะบะพัŽ + +* ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ +* ะดะตะบะพั€ะฐั‚ะพั€ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ +* ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ + +* ั‚ั–ะปะพ +* ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ +* ั‚ั–ะปะพ ะฒั–ะดะฟะพะฒั–ะดั– +* ั‚ั–ะปะพ JSON +* ั‚ั–ะปะพ ั„ะพั€ะผะธ +* ั‚ั–ะปะพ ั„ัƒะฝะบั†ั–ั— + +* ะฟะฐั€ะฐะผะตั‚ั€ +* ะฟะฐั€ะฐะผะตั‚ั€ ั‚ั–ะปะฐ +* ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ +* ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ +* ะฟะฐั€ะฐะผะตั‚ั€ ะบัƒะบั– +* ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะณะพะปะพะฒะบะฐ +* ะฟะฐั€ะฐะผะตั‚ั€ ั„ะพั€ะผะธ +* ะฟะฐั€ะฐะผะตั‚ั€ ั„ัƒะฝะบั†ั–ั— + +* ะฟะพะดั–ั +* ะฟะพะดั–ั ะทะฐะฟัƒัะบัƒ +* ะทะฐะฟัƒัะบ ัะตั€ะฒะตั€ะฐ +* ะฟะพะดั–ั ะฒะธะผะบะฝะตะฝะฝั +* ะฟะพะดั–ั ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั + +* ะพะฑั€ะพะฑะฝะธะบ +* ะพะฑั€ะพะฑะฝะธะบ ะฟะพะดั–ั— +* ะพะฑั€ะพะฑะฝะธะบ ะฒะธะฝัั‚ะบั–ะฒ +* ะพะฑั€ะพะฑะปัั‚ะธ + +* ะผะพะดะตะปัŒ +* ะผะพะดะตะปัŒ Pydantic +* ะผะพะดะตะปัŒ ะดะฐะฝะธั… +* ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั… +* ะผะพะดะตะปัŒ ั„ะพั€ะผะธ +* ะพะฑ'ั”ะบั‚ ะผะพะดะตะปั– + +* ะบะปะฐั +* ะฑะฐะทะพะฒะธะน ะบะปะฐั +* ะฑะฐั‚ัŒะบั–ะฒััŒะบะธะน ะบะปะฐั +* ะฟั–ะดะบะปะฐั +* ะดะพั‡ั–ั€ะฝั–ะน ะบะปะฐั +* ัะฟะพั€ั–ะดะฝะตะฝะธะน ะบะปะฐั +* ะผะตั‚ะพะด ะบะปะฐััƒ + +* ะทะฐะณะพะปะพะฒะพะบ +* ะทะฐะณะพะปะพะฒะบะธ +* ะทะฐะณะพะปะพะฒะพะบ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั— +* ะทะฐะณะพะปะพะฒะพะบ `Authorization` +* ะฝะฐะฟั€ะฐะฒะปะตะฝะธะน ะทะฐะณะพะปะพะฒะพะบ + +* ัะธัั‚ะตะผะฐ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน +* ะทะฐะปะตะถะฝั–ัั‚ัŒ +* ะทะฐะปะตะถะฝะธะน +* ะทะฐะปะตะถะฝะธะน + +* I/O-ะพะฑะผะตะถะตะฝะธะน +* CPU-ะพะฑะผะตะถะตะฝะธะน +* ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ +* ะฟะฐั€ะฐะปะตะปั–ะทะผ +* ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะพั€ะฝั–ัั‚ัŒ + +* ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั +* ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั +* `PATH` +* ะทะผั–ะฝะฝะฐ `PATH` + +* ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั +* ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— +* ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั +* ั„ะพั€ะผะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั— +* ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั— +* ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒั”ั‚ัŒัั +* ัะธัั‚ะตะผะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒั” ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ + +* CLI +* ั–ะฝั‚ะตั€ั„ะตะนั ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ + +* ัะตั€ะฒะตั€ +* ะบะปั–ั”ะฝั‚ + +* ั…ะผะฐั€ะฝะธะน ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบ +* ั…ะผะฐั€ะฝะธะน ัะตั€ะฒั–ั + +* ั€ะพะทั€ะพะฑะบะฐ +* ะตั‚ะฐะฟะธ ั€ะพะทั€ะพะฑะบะธ + +* ัะปะพะฒะฝะธะบ +* ัะปะพะฒะฝะธะบ +* ะฟะตั€ะตะปั–ะบ +* ะฟะตั€ะตะปั–ะบ +* ะตะปะตะผะตะฝั‚ ะฟะตั€ะตะปั–ะบัƒ + +* ะบะพะดัƒะฒะฐะปัŒะฝะธะบ +* ะดะตะบะพะดัƒะฒะฐะปัŒะฝะธะบ +* ะบะพะดัƒะฒะฐั‚ะธ +* ะดะตะบะพะดัƒะฒะฐั‚ะธ + +* ะฒะธะฝัั‚ะพะบ +* ะฟะพั€ะพะดะถัƒะฒะฐั‚ะธ + +* ะฒะธั€ะฐะท +* ะพะฟะตั€ะฐั‚ะพั€ + +* ั„ั€ะพะฝั‚ะตะฝะด +* ะฑะตะบะตะฝะด + +* ะพะฑะณะพะฒะพั€ะตะฝะฝั GitHub +* ะฟั€ะพะฑะปะตะผะฐ GitHub + +* ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ +* ะพะฟั‚ะธะผั–ะทะฐั†ั–ั ะฟั€ะพะดัƒะบั‚ะธะฒะฝะพัั‚ั– + +* ั‚ะธะฟ, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั +* ะฟะพะฒะตั€ะฝะตะฝะต ะทะฝะฐั‡ะตะฝะฝั + +* ะฑะตะทะฟะตะบะฐ +* ัั…ะตะผะฐ ะฑะตะทะฟะตะบะธ + +* ะทะฐะฒะดะฐะฝะฝั +* ั„ะพะฝะพะฒะต ะทะฐะฒะดะฐะฝะฝั +* ั„ัƒะฝะบั†ั–ั ะทะฐะฒะดะฐะฝะฝั + +* ัˆะฐะฑะปะพะฝ +* ั€ัƒัˆั–ะน ัˆะฐะฑะปะพะฝั–ะฒ + +* ะฐะฝะพั‚ะฐั†ั–ั ั‚ะธะฟัƒ +* ะฟั–ะดะบะฐะทะบะฐ ั‚ะธะฟัƒ + +* ัะตั€ะฒะตั€ะฝะธะน ะฟั€ะฐั†ั–ะฒะฝะธะบ +* ะฟั€ะฐั†ั–ะฒะฝะธะบ Uvicorn +* ะฟั€ะฐั†ั–ะฒะฝะธะบ Gunicorn +* ะฟั€ะพั†ะตั ะฟั€ะฐั†ั–ะฒะฝะธะบะฐ +* ะบะปะฐั ะฟั€ะฐั†ั–ะฒะฝะธะบะฐ +* ั€ะพะฑะพั‡ะต ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั + +* ั€ะพะทะณะพั€ั‚ะฐะฝะฝั +* ั€ะพะทะณะพั€ั‚ะฐั‚ะธ + +* SDK +* ะฝะฐะฑั–ั€ ะดะปั ั€ะพะทั€ะพะฑะบะธ ะฟั€ะพะณั€ะฐะผะฝะพะณะพ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั + +* `APIRouter` +* `requirements.txt` +* ั‚ะพะบะตะฝ ะฝะพัั–ั +* ะฝะตััƒะผั–ัะฝะฐ ะทะผั–ะฝะฐ +* ะฟะพะผะธะปะบะฐ +* ะบะฝะพะฟะบะฐ +* ะฒะธะบะปะธะบะฐั”ะผะธะน +* ะบะพะด +* ั„ั–ะบัะฐั†ั–ั +* ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ +* ัะฟั–ะฒะฟั€ะพะณั€ะฐะผะฐ +* ัะตะฐะฝั ะฑะฐะทะธ ะดะฐะฝะธั… +* ะดะธัะบ +* ะดะพะผะตะฝ +* ั€ัƒัˆั–ะน +* ั„ะฐะปัŒัˆะธะฒะธะน X +* ะผะตั‚ะพะด HTTP GET +* ะฟั€ะตะดะผะตั‚ +* ะฑั–ะฑะปั–ะพั‚ะตะบะฐ +* ั‚ั€ะธะฒะฐะปั–ัั‚ัŒ ะถะธั‚ั‚ั +* ะฑะปะพะบัƒะฒะฐะฝะฝั +* ะฟั€ะพะผั–ะถะฝะต ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั +* ะผะพะฑั–ะปัŒะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ +* ะผะพะดัƒะปัŒ +* ะผะพะฝั‚ัƒะฒะฐะฝะฝั +* ะผะตั€ะตะถะฐ +* ะดะถะตั€ะตะปะพ +* ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั +* ะบะพั€ะธัะฝะต ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั +* ะฟั€ะพั†ะตัะพั€ +* ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ +* ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ +* ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ +* ะทะฐะฟะธั‚ +* ะฟะฐะผ'ัั‚ัŒ ะท ะดะพะฒั–ะปัŒะฝะธะผ ะดะพัั‚ัƒะฟะพะผ +* ะฒั–ะดะดะฐะปะตะฝะฐ ะผะฐัˆะธะฝะฐ +* ะบะพะด ัั‚ะฐั‚ัƒััƒ +* ัั‚ั€ะพะบะฐ +* ะผั–ั‚ะบะฐ +* ะฒะตะฑ-ั„ั€ะตะนะผะฒะพั€ะบ +* ะดะธะบะฐ ะบะฐั€ั‚ะฐ +* ะฟะพะฒะตั€ั‚ะฐั‚ะธ +* ะฟะตั€ะตะฒั–ั€ัั‚ะธ + +//// + +//// tab | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฆะต ะฝะตะฟะพะฒะฝะธะน ั– ะฝะต ะฝะพั€ะผะฐั‚ะธะฒะฝะธะน ัะฟะธัะพะบ (ะฟะตั€ะตะฒะฐะถะฝะพ) ั‚ะตั…ะฝั–ั‡ะฝะธั… ั‚ะตั€ะผั–ะฝั–ะฒ, ั‰ะพ ะทัƒัั‚ั€ั–ั‡ะฐัŽั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. ะ’ั–ะฝ ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะธะผ ะฐะฒั‚ะพั€ัƒ ะฟั–ะดัะบะฐะทะบะธ, ั‰ะพะฑ ะทั€ะพะทัƒะผั–ั‚ะธ, ะดะปั ัะบะธั… ั‚ะตั€ะผั–ะฝั–ะฒ LLM ะฟะพั‚ั€ั–ะฑะฝะฐ ะดะพะฟะพะผะพะณะฐ. ะะฐะฟั€ะธะบะปะฐะด, ะบะพะปะธ ะฒั–ะฝ ะฟะพัั‚ั–ะนะฝะพ ะฟะพะฒะตั€ั‚ะฐั” ั…ะพั€ะพัˆะธะน ะฟะตั€ะตะบะปะฐะด ะดะพ ะผะตะฝัˆ ะฒะดะฐะปะพะณะพ. ะะฑะพ ะบะพะปะธ ะนะพะผัƒ ัะบะปะฐะดะฝะพ ะฒั–ะดะผั–ะฝัŽะฒะฐั‚ะธ ั‚ะตั€ะผั–ะฝ ะฒะฐัˆะพัŽ ะผะพะฒะพัŽ. + +ะ”ะธะฒ., ะฝะฐะฟั€ะธะบะปะฐะด, ั€ะพะทะดั–ะป `### List of English terms and their preferred German translations` ัƒ `docs/de/llm-prompt.md`. + +//// diff --git a/docs/uk/docs/about/index.md b/docs/uk/docs/about/index.md new file mode 100644 index 0000000000..198fd828e5 --- /dev/null +++ b/docs/uk/docs/about/index.md @@ -0,0 +1,3 @@ +# ะŸั€ะพ { #about } + +ะŸั€ะพ FastAPI, ะนะพะณะพ ะฟั€ะพั”ะบั‚ัƒะฒะฐะฝะฝั, ะฝะฐั‚ั…ะฝะตะฝะฝั ั‚ะฐ ั–ะฝัˆะต. ๐Ÿค“ diff --git a/docs/uk/docs/advanced/additional-responses.md b/docs/uk/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..089967a51a --- /dev/null +++ b/docs/uk/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะฒ OpenAPI { #additional-responses-in-openapi } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฆะต ะดะพะฒะพะปั– ะฟั€ะพััƒะฝัƒั‚ะฐ ั‚ะตะผะฐ. + +ะฏะบั‰ะพ ะฒะธ ะปะธัˆะต ะฟะพั‡ะธะฝะฐั”ั‚ะต ะท **FastAPI**, ะนะผะพะฒั–ั€ะฝะพ, ะฒะฐะผ ั†ะต ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ. + +/// + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะท ะดะพะดะฐั‚ะบะพะฒะธะผะธ ะบะพะดะฐะผะธ ัั‚ะฐั‚ัƒััƒ, ั‚ะธะฟะฐะผะธ ะผะตะดั–ะฐ, ะพะฟะธัะฐะผะธ ั‚ะพั‰ะพ. + +ะฆั– ะดะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะฑัƒะดะต ะฒะบะปัŽั‡ะตะฝะพ ะดะพ ัั…ะตะผะธ OpenAPI, ั‚ะพะถ ะฒะพะฝะธ ะท'ัะฒะปัั‚ัŒัั ั– ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API. + +ะะปะต ะดะปั ั‚ะฐะบะธั… ะดะพะดะฐั‚ะบะพะฒะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะฒะตั€ั‚ะฐั‚ะธ `Response` ะฝะฐ ะบัˆั‚ะฐะปั‚ `JSONResponse` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ั–ะท ะฟะพั‚ั€ั–ะฑะฝะธะผ ะบะพะดะพะผ ัั‚ะฐั‚ัƒััƒ ั‚ะฐ ะฒะผั–ัั‚ะพะผ. + +## ะ”ะพะดะฐั‚ะบะพะฒะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ ะท `model` { #additional-response-with-model } + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ะฒะฐัˆะธะผ ะดะตะบะพั€ะฐั‚ะพั€ะฐะผ ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ ะฟะฐั€ะฐะผะตั‚ั€ `responses`. + +ะ’ั–ะฝ ะฟั€ะธะนะผะฐั” `dict`: ะบะปัŽั‡ั– - ั†ะต ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ ะดะปั ะบะพะถะฝะพั— ะฒั–ะดะฟะพะฒั–ะดั– (ะฝะฐะฟั€ะธะบะปะฐะด, `200`), ะฐ ะทะฝะฐั‡ะตะฝะฝั - ั–ะฝัˆั– `dict` ะท ั–ะฝั„ะพั€ะผะฐั†ั–ั”ัŽ ะดะปั ะบะพะถะฝะพั— ะท ะฝะธั…. + +ะšะพะถะตะฝ ั–ะท ั†ะธั… ัะปะพะฒะฝะธะบั–ะฒ ะฒั–ะดะฟะพะฒั–ะดั– ะผะพะถะต ะผะฐั‚ะธ ะบะปัŽั‡ `model`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ Pydantic-ะผะพะดะตะปัŒ, ะฟะพะดั–ะฑะฝะพ ะดะพ `response_model`. + +**FastAPI** ะฒั–ะทัŒะผะต ั†ัŽ ะผะพะดะตะปัŒ, ะทะณะตะฝะตั€ัƒั” ั—ั— ะกั…ะตะผัƒ JSON ั– ะดะพะดะฐัั‚ัŒ ัƒ ะฒั–ะดะฟะพะฒั–ะดะฝะต ะผั–ัั†ะต ะฒ OpenAPI. + +ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ ั–ะฝัˆัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะบะพะดะพะผ ัั‚ะฐั‚ัƒััƒ `404` ั– Pydantic-ะผะพะดะตะปะปัŽ `Message`, ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะฟะธัะฐั‚ะธ: + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะฒะตั€ั‚ะฐั‚ะธ `JSONResponse` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +/// + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะšะปัŽั‡ `model` ะฝะต ั” ั‡ะฐัั‚ะธะฝะพัŽ OpenAPI. + +**FastAPI** ะฒั–ะทัŒะผะต ะทะฒั–ะดั‚ะธ Pydantic-ะผะพะดะตะปัŒ, ะทะณะตะฝะตั€ัƒั” ะกั…ะตะผัƒ JSON ั– ะฟะพะผั–ัั‚ะธั‚ัŒ ัƒ ะฒั–ะดะฟะพะฒั–ะดะฝะต ะผั–ัั†ะต. + +ะ’ั–ะดะฟะพะฒั–ะดะฝะต ะผั–ัั†ะต ั†ะต: + +- ะฃ ะบะปัŽั‡ั– `content`, ะทะฝะฐั‡ะตะฝะฝัะผ ัะบะพะณะพ ั” ั–ะฝัˆะธะน JSON-ะพะฑ'ั”ะบั‚ (`dict`), ั‰ะพ ะผั–ัั‚ะธั‚ัŒ: + - ะšะปัŽั‡ ั–ะท ั‚ะธะฟะพะผ ะผะตะดั–ะฐ, ะฝะฐะฟั€. `application/json`, ะทะฝะฐั‡ะตะฝะฝัะผ ัะบะพะณะพ ั” ั–ะฝัˆะธะน JSON-ะพะฑ'ั”ะบั‚, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ: + - ะšะปัŽั‡ `schema`, ะทะฝะฐั‡ะตะฝะฝัะผ ัะบะพะณะพ ั” ะกั…ะตะผะฐ JSON ะท ะผะพะดะตะปั– - ะพััŒ ั†ะต ั– ั” ะฟั€ะฐะฒะธะปัŒะฝะต ะผั–ัั†ะต. + - **FastAPI** ะดะพะดะฐั” ั‚ัƒั‚ ะฟะพัะธะปะฐะฝะฝั ะฝะฐ ะณะปะพะฑะฐะปัŒะฝั– ะกั…ะตะผะธ JSON ะฒ ั–ะฝัˆะพะผัƒ ะผั–ัั†ั– ะฒะฐัˆะพะณะพ OpenAPI ะทะฐะผั–ัั‚ัŒ ะฟั€ัะผะพะณะพ ะฒะบะปัŽั‡ะตะฝะฝั. ะขะฐะบ ั–ะฝัˆั– ะทะฐัั‚ะพััƒะฝะบะธ ั‚ะฐ ะบะปั–ั”ะฝั‚ะธ ะผะพะถัƒั‚ัŒ ะฝะฐะฟั€ัะผัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ั– ะกั…ะตะผะธ JSON, ะฝะฐะดะฐะฒะฐั‚ะธ ะบั€ะฐั‰ั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะณะตะฝะตั€ะฐั†ั–ั— ะบะพะดัƒ ั‚ะพั‰ะพ. + +/// + +ะ—ะณะตะฝะตั€ะพะฒะฐะฝั– ะฒั–ะดะฟะพะฒั–ะดั– ะฒ OpenAPI ะดะปั ั†ั–ั”ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฑัƒะดัƒั‚ัŒ ั‚ะฐะบะธะผะธ: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +ะกั…ะตะผะธ ะฟะพัะธะปะฐัŽั‚ัŒัั ะฝะฐ ั–ะฝัˆะต ะผั–ัั†ะต ะฒัะตั€ะตะดะธะฝั– ัั…ะตะผะธ OpenAPI: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## ะ”ะพะดะฐั‚ะบะพะฒั– ั‚ะธะฟะธ ะผะตะดั–ะฐ ะดะปั ะพัะฝะพะฒะฝะพั— ะฒั–ะดะฟะพะฒั–ะดั– { #additional-media-types-for-the-main-response } + +ะœะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะตะน ัะฐะผะธะน ะฟะฐั€ะฐะผะตั‚ั€ `responses`, ั‰ะพะฑ ะดะพะดะฐั‚ะธ ั€ั–ะทะฝั– ั‚ะธะฟะธ ะผะตะดั–ะฐ ะดะปั ั‚ั–ั”ั— ะถ ะพัะฝะพะฒะฝะพั— ะฒั–ะดะฟะพะฒั–ะดั–. + +ะะฐะฟั€ะธะบะปะฐะด, ะผะพะถะฝะฐ ะดะพะดะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒะธะน ั‚ะธะฟ ะผะตะดั–ะฐ `image/png`, ะพะณะพะปะพัะธะฒัˆะธ, ั‰ะพ ะฒะฐัˆะฐ ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ ะผะพะถะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ JSON-ะพะฑ'ั”ะบั‚ (ะท ั‚ะธะฟะพะผ ะผะตะดั–ะฐ `application/json`) ะฐะฑะพ PNG-ะทะพะฑั€ะฐะถะตะฝะฝั: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะทะพะฑั€ะฐะถะตะฝะฝั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `FileResponse`. + +/// + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะพะบะธ ะฒะธ ัะฒะฝะพ ะฝะต ะฒะบะฐะถะตั‚ะต ั–ะฝัˆะธะน ั‚ะธะฟ ะผะตะดั–ะฐ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ั– `responses`, FastAPI ะฒะฒะฐะถะฐั‚ะธะผะต, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะผะฐั” ั‚ะพะน ัะฐะผะธะน ั‚ะธะฟ ะผะตะดั–ะฐ, ั‰ะพ ะน ะพัะฝะพะฒะฝะธะน ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั– (ั‚ะธะฟะพะฒะพ `application/json`). + +ะะปะต ัะบั‰ะพ ะฒะธ ะฒะบะฐะทะฐะปะธ ะฒะปะฐัะฝะธะน ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั– ะท `None` ัะบ ั‚ะธะฟะพะผ ะผะตะดั–ะฐ, FastAPI ะฒะธะบะพั€ะธัั‚ะฐั” `application/json` ะดะปั ะฑัƒะดัŒ-ัะบะพั— ะดะพะดะฐั‚ะบะพะฒะพั— ะฒั–ะดะฟะพะฒั–ะดั–, ั‰ะพ ะผะฐั” ะฟะพะฒ'ัะทะฐะฝัƒ ะผะพะดะตะปัŒ. + +/// + +## ะšะพะผะฑั–ะฝัƒะฒะฐะฝะฝั ั–ะฝั„ะพั€ะผะฐั†ั–ั— { #combining-information } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฟั€ะพ ะฒั–ะดะฟะพะฒั–ะดั– ะท ะบั–ะปัŒะบะพั… ะผั–ัั†ัŒ, ะทะพะบั€ะตะผะฐ ะท ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ `response_model`, `status_code` ั– `responses`. + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ `response_model`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะธะฟะพะฒะธะน ะบะพะด ัั‚ะฐั‚ัƒััƒ `200` (ะฐะฑะพ ะฒะปะฐัะฝะธะน ะทะฐ ะฟะพั‚ั€ะตะฑะธ), ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะดะปั ั†ั–ั”ั— ะถ ะฒั–ะดะฟะพะฒั–ะดั– ะฒ `responses`, ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ัั…ะตะผั– OpenAPI. + +**FastAPI** ะทะฑะตั€ะตะถะต ะดะพะดะฐั‚ะบะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะท `responses` ั– ะฟะพั”ะดะฝะฐั” ั—ั— ะทั– ะกั…ะตะผะพัŽ JSON ะท ะฒะฐัˆะพั— ะผะพะดะตะปั–. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะบะพะดะพะผ ัั‚ะฐั‚ัƒััƒ `404`, ัะบะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Pydantic-ะผะพะดะตะปัŒ ั– ะผะฐั” ะฒะปะฐัะฝะธะน `description`. + +ะ† ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะบะพะดะพะผ ัั‚ะฐั‚ัƒััƒ `200`, ัะบะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒะฐัˆ `response_model`, ะฐะปะต ะผั–ัั‚ะธั‚ัŒ ะฒะปะฐัะฝะธะน `example`: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +ะฃัะต ั†ะต ะฑัƒะดะต ะฟะพั”ะดะฝะฐะฝะพ ั‚ะฐ ะฒะบะปัŽั‡ะตะฝะพ ะดะพ ะฒะฐัˆะพะณะพ OpenAPI ั– ะฟะพะบะฐะทะฐะฝะพ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API: + + + +## ะšะพะผะฑั–ะฝัƒะนั‚ะต ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝั– ั‚ะฐ ะฒะปะฐัะฝั– ะฒั–ะดะฟะพะฒั–ะดั– { #combine-predefined-responses-and-custom-ones } + +ะœะพะถะปะธะฒะพ, ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน, ั‰ะพ ะทะฐัั‚ะพัะพะฒัƒัŽั‚ัŒัั ะดะพ ะฑะฐะณะฐั‚ัŒะพั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ, ะฐะปะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ ั—ั… ั–ะท ะฒะปะฐัะฝะธะผะธ ะฒั–ะดะฟะพะฒั–ะดัะผะธ, ะฟะพั‚ั€ั–ะฑะฝะธะผะธ ะดะปั ะบะพะถะฝะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ ะผะพะถะฝะฐ ัะบะพั€ะธัั‚ะฐั‚ะธัั ะฟั€ะธะนะพะผะพะผ Python ยซั€ะพะทะฟะฐะบัƒะฒะฐะฝะฝัยป `dict` ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `**dict_to_unpack`: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +ะขัƒั‚ `new_dict` ะผั–ัั‚ะธั‚ะธะผะต ะฒัั– ะฟะฐั€ะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั ะท `old_dict` ะฟะปัŽั ะฝะพะฒัƒ ะฟะฐั€ัƒ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +ะฆะตะน ะฟั€ะธะนะพะผ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ, ั‰ะพะฑ ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะดะตัะบั– ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะตะฝั– ะฒั–ะดะฟะพะฒั–ะดั– ัƒ ะฒะฐัˆะธั… ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ ั‚ะฐ ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ ั—ั… ั–ะท ะดะพะดะฐั‚ะบะพะฒะธะผะธ ะฒะปะฐัะฝะธะผะธ. + +ะะฐะฟั€ะธะบะปะฐะด: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## ะ”ะพะบะปะฐะดะฝั–ัˆะต ะฟั€ะพ ะฒั–ะดะฟะพะฒั–ะดั– OpenAPI { #more-information-about-openapi-responses } + +ะฉะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ, ั‰ะพ ัะฐะผะต ะผะพะถะฝะฐ ะฒะบะปัŽั‡ะฐั‚ะธ ัƒ ะฒั–ะดะฟะพะฒั–ะดั–, ะพะทะฝะฐะนะพะผั‚ะตัั ะท ั†ะธะผะธ ั€ะพะทะดั–ะปะฐะผะธ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI: + +- ะžะฑ'ั”ะบั‚ ะฒั–ะดะฟะพะฒั–ะดะตะน OpenAPI, ะฒั–ะฝ ะฒะบะปัŽั‡ะฐั” `Response Object`. +- ะžะฑ'ั”ะบั‚ ะฒั–ะดะฟะพะฒั–ะดั– OpenAPI, ะฒะธ ะผะพะถะตั‚ะต ะฒะบะปัŽั‡ะธั‚ะธ ะฑัƒะดัŒ-ั‰ะพ ะท ั†ัŒะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ะบะพะถะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– `responses`. ะ—ะพะบั€ะตะผะฐ `description`, `headers`, `content` (ัƒัะตั€ะตะดะธะฝั– ะฝัŒะพะณะพ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ั€ั–ะทะฝั– ั‚ะธะฟะธ ะผะตะดั–ะฐ ั‚ะฐ ะกั…ะตะผะธ JSON) ั– `links`. diff --git a/docs/uk/docs/advanced/additional-status-codes.md b/docs/uk/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000..afba933e20 --- /dev/null +++ b/docs/uk/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# ะ”ะพะดะฐั‚ะบะพะฒั– ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ { #additional-status-codes } + +ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ **FastAPI** ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ะฒั–ะดะฟะพะฒั–ะดั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `JSONResponse`, ะฟะพะผั–ั‰ะฐัŽั‡ะธ ะฒะผั–ัั‚, ัะบะธะน ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ะท ะฒะฐัˆะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ัƒ ั†ะตะน `JSONResponse`. + +ะ’ั–ะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต ะบะพะด ัั‚ะฐั‚ัƒััƒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฐะฑะพ ั‚ะพะน, ัะบะธะน ะฒะธ ะฒัั‚ะฐะฝะพะฒะธั‚ะต ัƒ ัะฒะพั—ะน *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +## ะ”ะพะดะฐั‚ะบะพะฒั– ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ { #additional-status-codes_1 } + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ, ะพะบั€ั–ะผ ะพัะฝะพะฒะฝะพะณะพ, ะทั€ะพะฑั–ั‚ัŒ ั†ะต, ะฟะพะฒะตั€ั‚ะฐัŽั‡ะธ `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฝะฐะฟั€ะธะบะปะฐะด `JSONResponse`, ั– ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ะดะพะดะฐั‚ะบะพะฒะธะน ะบะพะด ัั‚ะฐั‚ัƒััƒ ะฝะฐะฟั€ัะผัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ*, ัะบะฐ ะดะพะทะฒะพะปัั” ะพะฝะพะฒะปัŽะฒะฐั‚ะธ ะฟั€ะตะดะผะตั‚ะธ ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” ะบะพะด ัั‚ะฐั‚ัƒััƒ HTTP 200 ยซOKยป ัƒ ั€ะฐะทั– ัƒัะฟั–ั…ัƒ. + +ะะปะต ะฒะธ ั‚ะฐะบะพะถ ั…ะพั‡ะตั‚ะต ะฟั€ะธะนะผะฐั‚ะธ ะฝะพะฒั– ะฟั€ะตะดะผะตั‚ะธ. ะ† ะบะพะปะธ ั‚ะฐะบะธั… ะฟั€ะตะดะผะตั‚ั–ะฒ ั€ะฐะฝั–ัˆะต ะฝะต ั–ัะฝัƒะฒะฐะปะพ, ะพะฟะตั€ะฐั†ั–ั ัั‚ะฒะพั€ัŽั” ั—ั… ั– ะฟะพะฒะตั€ั‚ะฐั” ะบะพะด ัั‚ะฐั‚ัƒััƒ HTTP 201 ยซCreatedยป. + +ะฉะพะฑ ั†ะต ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ, ั–ะผะฟะพั€ั‚ัƒะนั‚ะต `JSONResponse` ั– ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะฒะฐัˆ ะฒะผั–ัั‚ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ั‚ะฐะผ, ะฒัั‚ะฐะฝะพะฒะธะฒัˆะธ ะฟะพั‚ั€ั–ะฑะฝะธะน `status_code`: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะšะพะปะธ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ัะบ ัƒ ะฟั€ะธะบะปะฐะดั– ะฒะธั‰ะต, ะฒั–ะฝ ั– ะฑัƒะดะต ะฟะพะฒะตั€ะฝะตะฝะธะน ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +ะ’ั–ะฝ ะฝะต ะฑัƒะดะต ัะตั€ั–ะฐะปั–ะทะพะฒะฐะฝะธะน ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะผะพะดะตะปั– ั‚ะพั‰ะพ. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒั–ะฝ ะผั–ัั‚ะธั‚ัŒ ัะฐะผะต ั‚ั– ะดะฐะฝั–, ัะบั– ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–, ั– ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ั” ะบะพั€ะตะบั‚ะฝะธะผ JSON (ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `JSONResponse`). + +/// + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.responses import JSONResponse`. + +**FastAPI** ะฝะฐะดะฐั” ั‚ั– ัะฐะผั– `starlette.responses` ัะบ `fastapi.responses` ะฟั€ะพัั‚ะพ ะดะปั ะฒะฐัˆะพั— ะทั€ัƒั‡ะฝะพัั‚ั– ัะบ ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฝะฐะดั…ะพะดะธั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. ะขะต ัะฐะผะต ั– ะทั– `status`. + +/// + +## OpenAPI ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API { #openapi-and-api-docs } + +ะฏะบั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ะดะพะดะฐั‚ะบะพะฒั– ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ ั‚ะฐ ะฒั–ะดะฟะพะฒั–ะดั– ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะฒะพะฝะธ ะฝะต ะฑัƒะดัƒั‚ัŒ ะฒะบะปัŽั‡ะตะฝั– ะดะพ ัั…ะตะผะธ OpenAPI (ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API), ะฐะดะถะต FastAPI ะฝะต ะผะฐั” ัะฟะพัะพะฑัƒ ะทะฐะทะดะฐะปะตะณั–ะดัŒ ะทะฝะฐั‚ะธ, ั‰ะพ ัะฐะผะต ะฒะธ ะฟะพะฒะตั€ะฝะตั‚ะต. + +ะะปะต ะฒะธ ะผะพะถะตั‚ะต ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ั†ะต ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ: [ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั–](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/uk/docs/advanced/advanced-dependencies.md b/docs/uk/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000..0c6f8cbb34 --- /dev/null +++ b/docs/uk/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# ะŸั€ะพััƒะฝัƒั‚ั– ะทะฐะปะตะถะฝะพัั‚ั– { #advanced-dependencies } + +## ะŸะฐั€ะฐะผะตั‚ั€ะธะทะพะฒะฐะฝั– ะทะฐะปะตะถะฝะพัั‚ั– { #parameterized-dependencies } + +ะฃัั– ะทะฐะปะตะถะฝะพัั‚ั–, ัะบั– ะผะธ ะฑะฐั‡ะธะปะธ, - ั†ะต ั„ั–ะบัะพะฒะฐะฝะฐ ั„ัƒะฝะบั†ั–ั ะฐะฑะพ ะบะปะฐั. + +ะะปะต ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฒะธ ั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะทะผะพะณัƒ ะทะฐะดะฐะฒะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฐะปะตะถะฝะพัั‚ั–, ะฝะต ะพะณะพะปะพัˆัƒัŽั‡ะธ ะฑะฐะณะฐั‚ะพ ั€ั–ะทะฝะธั… ั„ัƒะฝะบั†ั–ะน ะฐะฑะพ ะบะปะฐัั–ะฒ. + +ะฃัะฒั–ะผะพ, ั‰ะพ ะผะธ ั…ะพั‡ะตะผะพ ะผะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบะฐ ะฟะตั€ะตะฒั–ั€ัั”, ั‡ะธ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `q` ะผั–ัั‚ะธั‚ัŒ ะฟะตะฒะฝะธะน ั„ั–ะบัะพะฒะฐะฝะธะน ะฒะผั–ัั‚. + +ะะปะต ะผะธ ั…ะพั‡ะตะผะพ ะผะฐั‚ะธ ะทะผะพะณัƒ ะฟะฐั€ะฐะผะตั‚ั€ะธะทัƒะฒะฐั‚ะธ ั†ะตะน ั„ั–ะบัะพะฒะฐะฝะธะน ะฒะผั–ัั‚. + +## ะ•ะบะทะตะผะฟะปัั€ ยซcallableยป { #a-callable-instance } + +ะฃ Python ั” ัะฟะพัั–ะฑ ะทั€ะพะฑะธั‚ะธ ะตะบะทะตะผะฟะปัั€ ะบะปะฐััƒ ยซcallableยป. + +ะะต ัะฐะผ ะบะปะฐั (ัะบะธะน ัƒะถะต ั” ยซcallableยป), ะฐ ะตะบะทะตะผะฟะปัั€ ั†ัŒะพะณะพ ะบะปะฐััƒ. + +ะฉะพะฑ ั†ะต ะทั€ะพะฑะธั‚ะธ, ะพะณะพะปะพัˆัƒั”ะผะพ ะผะตั‚ะพะด `__call__`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ัะฐะผะต `__call__` **FastAPI** ะฒะธะบะพั€ะธัั‚ะฐั” ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะพะดะฐั‚ะบะพะฒะธั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ ั– ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ะตะน, ั– ัะฐะผะต ะนะพะณะพ ะฑัƒะดะต ะฒะธะบะปะธะบะฐะฝะพ, ั‰ะพะฑ ะฟะตั€ะตะดะฐั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ัƒ ัƒ ะฒะฐัˆัƒ *ั„ัƒะฝะบั†ั–ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฟั–ะทะฝั–ัˆะต. + +## ะŸะฐั€ะฐะผะตั‚ั€ะธะทัƒะฒะฐั‚ะธ ะตะบะทะตะผะฟะปัั€ { #parameterize-the-instance } + +ะขะตะฟะตั€ ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `__init__`, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะตะบะทะตะผะฟะปัั€ะฐ, ัะบั– ะผะพะถะฝะฐ ะทะฐัั‚ะพััƒะฒะฐั‚ะธ ะดะปั ยซะฟะฐั€ะฐะผะตั‚ั€ะธะทะฐั†ั–ั—ยป ะทะฐะปะตะถะฝะพัั‚ั–: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ **FastAPI** ะฝั–ะบะพะปะธ ะฝะต ั‚ะพั€ะบะฐั”ั‚ัŒัั `__init__` ั– ะฝะต ะฟะพะบะปะฐะดะฐั”ั‚ัŒัั ะฝะฐ ะฝัŒะพะณะพ - ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตะผะพ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–. + +## ะกั‚ะฒะพั€ะธั‚ะธ ะตะบะทะตะผะฟะปัั€ { #create-an-instance } + +ะœะธ ะผะพะถะตะผะพ ัั‚ะฒะพั€ะธั‚ะธ ะตะบะทะตะผะฟะปัั€ ั†ัŒะพะณะพ ะบะปะฐััƒ ั‚ะฐะบ: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะผะธ ยซะฟะฐั€ะฐะผะตั‚ั€ะธะทัƒั”ะผะพยป ะฝะฐัˆัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบะฐ ั‚ะตะฟะตั€ ะผั–ัั‚ะธั‚ัŒ ยซbarยป ัะบ ะฐั‚ั€ะธะฑัƒั‚ `checker.fixed_content`. + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะตะบะทะตะผะฟะปัั€ ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ { #use-the-instance-as-a-dependency } + +ะ”ะฐะปั– ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะตะน `checker` ัƒ `Depends(checker)` ะทะฐะผั–ัั‚ัŒ `Depends(FixedContentQueryChecker)`, ะฐะดะถะต ะทะฐะปะตะถะฝั–ัั‚ัŽ ั” ะตะบะทะตะผะฟะปัั€ `checker`, ะฐ ะฝะต ัะฐะผ ะบะปะฐั. + +ะšะพะปะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั€ะพะทะฒ'ัะทัƒั”ั‚ัŒัั, **FastAPI** ะฒะธะบะปะธั‡ะต ั†ะตะน `checker` ั‚ะฐะบ: + +```Python +checker(q="somequery") +``` + +...ั– ะฟะตั€ะตะดะฐัั‚ัŒ ัƒัะต, ั‰ะพ ะฒั–ะฝ ะฟะพะฒะตั€ะฝะต, ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั– ัƒ ะฝะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ัะบ ะฟะฐั€ะฐะผะตั‚ั€ `fixed_content_included`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃัะต ั†ะต ะผะพะถะต ะทะดะฐะฒะฐั‚ะธัั ะฝะฐะดัƒะผะฐะฝะธะผ. ะ† ะฟะพะบะธ ั‰ะพ ะผะพะถะต ะฑัƒั‚ะธ ะฝะต ะดัƒะถะต ะทั€ะพะทัƒะผั–ะปะพ, ะฝะฐะฒั–ั‰ะพ ั†ะต ะบะพั€ะธัะฝะพ. + +ะฆั– ะฟั€ะธะบะปะฐะดะธ ะฝะฐะฒะผะธัะฝะพ ะฟั€ะพัั‚ั–, ะฐะปะต ะฟะพะบะฐะทัƒัŽั‚ัŒ, ัะบ ัƒัะต ะฟั€ะฐั†ัŽั”. + +ะฃ ั€ะพะทะดั–ะปะฐั… ะฟั€ะพ ะฑะตะทะฟะตะบัƒ ั” ัƒั‚ะธะปั–ั‚ะฐั€ะฝั– ั„ัƒะฝะบั†ั–ั—, ั€ะตะฐะปั–ะทะพะฒะฐะฝั– ั‚ะฐะบะธะผ ัะฐะผะธะผ ัะฟะพัะพะฑะพะผ. + +ะฏะบั‰ะพ ะฒะธ ะฒัะต ั†ะต ะทั€ะพะทัƒะผั–ะปะธ, ะฒะธ ะฒะถะต ะทะฝะฐั”ั‚ะต, ัะบ ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ะฟั€ะฐั†ัŽัŽั‚ัŒ ั‚ั– ัƒั‚ะธะปั–ั‚ะธ ะดะปั ะฑะตะทะฟะตะบะธ. + +/// + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield`, `HTTPException`, `except` ั‚ะฐ ั„ะพะฝะพะฒะธะผะธ ะทะฐะดะฐั‡ะฐะผะธ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะฒะฐะผ ะฝะต ะทะฝะฐะดะพะฑะปัั‚ัŒัั ั†ั– ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั–. + +ะ’ะพะฝะธ ะบะพั€ะธัะฝั– ะณะพะปะพะฒะฝะพ, ัะบั‰ะพ ัƒ ะฒะฐั ะฑัƒะฒ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ัั‚ะฐั€ั–ัˆะธะน ะทะฐ 0.121.0 ั– ะฒะธ ัั‚ะธะบะฐั”ั‚ะตัั ะท ะฟั€ะพะฑะปะตะผะฐะผะธ ะทะฐะปะตะถะฝะพัั‚ะตะน ั–ะท `yield`. + +/// + +ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ะตะฒะพะปัŽั†ั–ะพะฝัƒะฒะฐะปะธ ะท ั‡ะฐัะพะผ, ั‰ะพะฑ ะพั…ะพะฟะธั‚ะธ ั€ั–ะทะฝั– ัั†ะตะฝะฐั€ั–ั— ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ะฐ ะฒะธะฟั€ะฐะฒะธั‚ะธ ะดะตัะบั– ะฟั€ะพะฑะปะตะผะธ, ะพััŒ ะฟั–ะดััƒะผะพะบ ะทะผั–ะฝ. + +### ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั– `scope` { #dependencies-with-yield-and-scope } + +ะฃ ะฒะตั€ัั–ั— 0.121.0 **FastAPI** ะดะพะดะฐะฝะพ ะฟั–ะดั‚ั€ะธะผะบัƒ `Depends(scope="function")` ะดะปั ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield`. + +ะ— `Depends(scope="function")` ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฟั–ัะปั `yield` ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะพะดั€ะฐะทัƒ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะดะพ ั‚ะพะณะพ ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะฐ ะบะปั–ั”ะฝั‚ัƒ. + +ะ ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– `Depends(scope="request")` (ั‚ะธะฟะพะฒะต ะทะฝะฐั‡ะตะฝะฝั) ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฟั–ัะปั `yield` ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟั–ัะปั ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ั‡ะธั‚ะฐะนั‚ะต ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: [ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` - ะ ะฐะฝะฝั–ะน ะฒะธั…ั–ะด ั– `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope). + +### ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั– `StreamingResponse`, ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #dependencies-with-yield-and-streamingresponse-technical-details } + +ะ”ะพ **FastAPI** 0.118.0, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั–ะท `yield`, ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฒะธะบะพะฝัƒะฒะฐะฒัั ะฟั–ัะปั ะฟะพะฒะตั€ะฝะตะฝะฝั ะท *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฐะปะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝัะผ ะฒั–ะดะฟะพะฒั–ะดั–. + +ะœะตั‚ะพัŽ ะฑัƒะปะพ ัƒะฝะธะบะฝัƒั‚ะธ ัƒั‚ั€ะธะผะฐะฝะฝั ั€ะตััƒั€ัั–ะฒ ะดะพะฒัˆะต, ะฝั–ะถ ะฟะพั‚ั€ั–ะฑะฝะพ, ะพั‡ั–ะบัƒัŽั‡ะธ, ะฟะพะบะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฟั€ะพะนะดะต ะผะตั€ะตะถะตัŽ. + +ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐะปะพ, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐะปะธ `StreamingResponse`, ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ัƒะถะต ะฑัƒะปะพ ะฑ ะฒะธะบะพะฝะฐะฝะพ. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัƒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ะฑัƒะปะฐ ัะตัั–ั ะฑะฐะทะธ ะดะฐะฝะธั…, `StreamingResponse` ะฝะต ะทะผั–ะณ ะฑะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ัŽ ัะตัั–ัŽ ะฟั–ะด ั‡ะฐั ะฟะพั‚ะพะบะพะฒะพั— ะฟะตั€ะตะดะฐั‡ั– ะดะฐะฝะธั…, ั‚ะพะผัƒ ั‰ะพ ัะตัั–ัŽ ะฒะถะต ะทะฐะบั€ะธั‚ะพ ะฒ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะพะผัƒ ะบะพะดั– ะฟั–ัะปั `yield`. + +ะฆัŽ ะฟะพะฒะตะดั–ะฝะบัƒ ะทะผั–ะฝะตะฝะพ ัƒ 0.118.0: ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฟั–ัะปั `yield` ะทะฝะพะฒัƒ ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟั–ัะปั ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบ ะฟะพะฑะฐั‡ะธั‚ะต ะฝะธะถั‡ะต, ั†ะต ะดัƒะถะต ัั…ะพะถะต ะฝะฐ ะฟะพะฒะตะดั–ะฝะบัƒ ะดะพ ะฒะตั€ัั–ั— 0.106.0, ะฐะปะต ะท ะบั–ะปัŒะบะพะผะฐ ะฟะพะบั€ะฐั‰ะตะฝะฝัะผะธ ั‚ะฐ ะฒะธะฟั€ะฐะฒะปะตะฝะฝัะผะธ ะฟะพะผะธะปะพะบ ัƒ ะบั€ะฐะนะพะฒะธั… ะฒะธะฟะฐะดะบะฐั…. + +/// + +#### ะ’ะธะฟะฐะดะบะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะท ั€ะฐะฝะฝั–ะผ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะผ ะบะพะดะพะผ { #use-cases-with-early-exit-code } + +ะ„ ะบั–ะปัŒะบะฐ ัั†ะตะฝะฐั€ั–ั—ะฒ ั–ะท ะฟะตะฒะฝะธะผะธ ัƒะผะพะฒะฐะผะธ, ัะบั– ะผะพะถัƒั‚ัŒ ะฒะธะณั€ะฐั‚ะธ ะฒั–ะด ัั‚ะฐั€ะพั— ะฟะพะฒะตะดั–ะฝะบะธ - ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield` ะดะพ ะฝะฐะดัะธะปะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒัะฒั–ั‚ัŒ, ั‰ะพ ัƒ ะฒะฐั ั” ะบะพะด, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัะตัั–ัŽ ะฑะฐะทะธ ะดะฐะฝะธั… ัƒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ะปะธัˆะต ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ะฐะปะต ัะตัั–ั ะฑั–ะปัŒัˆะต ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั‚ั–ะปัŒะบะธ ะฒ ะทะฐะปะตะถะฝะพัั‚ั–, ั– ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั– ั‚ั€ะธะฒะฐั” ะดะพะฒะณะพ - ัะบ ัƒ `StreamingResponse`, ั‰ะพ ะฟะพะฒั–ะปัŒะฝะพ ะฝะฐะดัะธะปะฐั” ะดะฐะฝั–, ะฐะปะต ะท ัะบะพั—ััŒ ะฟั€ะธั‡ะธะฝะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฑะฐะทัƒ ะดะฐะฝะธั…. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ัะตัั–ั ะ‘ะ” ัƒั‚ั€ะธะผัƒะฒะฐะปะฐัั ะฑ ะดะพ ะทะฐะฒะตั€ัˆะตะฝะฝั ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–, ะฐะปะต ัะบั‰ะพ ะฒะธ ั—ั— ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต, ัƒั‚ั€ะธะผัƒะฒะฐั‚ะธ ั—ั— ะฝะตะผะฐั” ะฟะพั‚ั€ะตะฑะธ. + +ะžััŒ ัะบ ั†ะต ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +ะ—ะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด - ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะทะฐะบั€ะธั‚ั‚ั `Session` ัƒ: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...ะฒะธะบะพะฝะฐั”ั‚ัŒัั ะฟั–ัะปั ั‚ะพะณะพ, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะทะฐะฒะตั€ัˆะธั‚ัŒ ะฝะฐะดัะธะปะฐั‚ะธ ะฟะพะฒั–ะปัŒะฝั– ะดะฐะฝั–: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +ะะปะต ะพัะบั–ะปัŒะบะธ `generate_stream()` ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัะตัั–ัŽ ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะตะผะฐั” ั€ะตะฐะปัŒะฝะพั— ะฟะพั‚ั€ะตะฑะธ ั‚ั€ะธะผะฐั‚ะธ ัะตัั–ัŽ ะฒั–ะดะบั€ะธั‚ะพัŽ ะฟั–ะด ั‡ะฐั ะฝะฐะดัะธะปะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. + +ะฏะบั‰ะพ ัƒ ะฒะฐั ัะฐะผะต ั‚ะฐะบะธะน ะฒะธะฟะฐะดะพะบ ั–ะท SQLModel (ะฐะฑะพ SQLAlchemy), ะฒะธ ะผะพะถะตั‚ะต ัะฒะฝะพ ะทะฐะบั€ะธั‚ะธ ัะตัั–ัŽ, ะบะพะปะธ ะฒะพะฝะฐ ะฑั–ะปัŒัˆะต ะฝะต ะฟะพั‚ั€ั–ะฑะฝะฐ: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +ะขะฐะบ ัะตัั–ั ะทะฒั–ะปัŒะฝะธั‚ัŒ ะท'ั”ะดะฝะฐะฝะฝั ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั…, ั– ะนะพะณะพ ะทะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆั– ะทะฐะฟะธั‚ะธ. + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั–ะฝัˆะธะน ัั†ะตะฝะฐั€ั–ะน, ะดะต ะฟะพั‚ั€ั–ะฑะฝะพ ั€ะฐะฝะฝั” ะทะฐะฒะตั€ัˆะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ัั‚ะฒะพั€ั–ั‚ัŒ, ะฑัƒะดัŒ ะปะฐัะบะฐ, ะฟะธั‚ะฐะฝะฝั ะฒ ะพะฑะณะพะฒะพั€ะตะฝะฝัั… GitHub ั–ะท ะฒะฐัˆะธะผ ะบะพะฝะบั€ะตั‚ะฝะธะผ ะฒะธะฟะฐะดะบะพะผ ั– ะฟะพััะฝะตะฝะฝัะผ, ั‡ะพะผัƒ ะฒะฐะผ ะบะพั€ะธัะฝะต ั€ะฐะฝะฝั” ะทะฐะบั€ะธั‚ั‚ั ะดะปั ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield`. + +ะฏะบั‰ะพ ะฑัƒะดัƒั‚ัŒ ะฟะตั€ะตะบะพะฝะปะธะฒั– ะฟั€ะธะบะปะฐะดะธ ะดะปั ั€ะฐะฝะฝัŒะพะณะพ ะทะฐะบั€ะธั‚ั‚ั ะฒ ะทะฐะปะตะถะฝะพัั‚ัั… ะท `yield`, ั ั€ะพะทะณะปัะฝัƒ ะดะพะดะฐะฒะฐะฝะฝั ะฝะพะฒะพะณะพ ัะฟะพัะพะฑัƒ ัƒะฒั–ะผะบะฝัƒั‚ะธ ั€ะฐะฝะฝั” ะทะฐะบั€ะธั‚ั‚ั. + +### ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั– `except`, ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #dependencies-with-yield-and-except-technical-details } + +ะ”ะพ **FastAPI** 0.110.0, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั–ะท `yield`, ะฟะตั€ะตั…ะพะฟะปัŽะฒะฐะปะธ ะฒะธะฝัั‚ะพะบ ั‡ะตั€ะตะท `except` ัƒ ั†ั–ะน ะทะฐะปะตะถะฝะพัั‚ั– ั– ะฝะต ะฟั–ะดะฝั–ะผะฐะปะธ ะนะพะณะพ ะทะฝะพะฒัƒ, ะฒะธะฝัั‚ะพะบ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟั–ะดะฝั–ะผะฐะฒัั/ะฟะตั€ะตัะธะปะฐะฒัั ะดะพ ะฑัƒะดัŒ-ัะบะธั… ะพะฑั€ะพะฑะฝะธะบั–ะฒ ะฒะธะฝัั‚ะบั–ะฒ ะฐะฑะพ ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพะณะพ ะพะฑั€ะพะฑะฝะธะบะฐ ะฟะพะผะธะปะพะบ ัะตั€ะฒะตั€ะฐ. + +ะฆะต ะทะผั–ะฝะตะฝะพ ัƒ ะฒะตั€ัั–ั— 0.110.0, ั‰ะพะฑ ัƒััƒะฝัƒั‚ะธ ะฝะตะบะพะฝั‚ั€ะพะปัŒะพะฒะฐะฝะต ัะฟะพะถะธะฒะฐะฝะฝั ะฟะฐะผ'ัั‚ั– ะฒั–ะด ะฟะตั€ะตัะปะฐะฝะธั… ะฒะธะฝัั‚ะบั–ะฒ ะฑะตะท ะพะฑั€ะพะฑะฝะธะบะฐ (ะฒะฝัƒั‚ั€ั–ัˆะฝั– ะฟะพะผะธะปะบะธ ัะตั€ะฒะตั€ะฐ) ั‚ะฐ ะทั€ะพะฑะธั‚ะธ ะฟะพะฒะตะดั–ะฝะบัƒ ัƒะทะณะพะดะถะตะฝะพัŽ ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ Python-ะบะพะดะพะผ. + +### ะคะพะฝะพะฒั– ะทะฐะดะฐั‡ั– ั‚ะฐ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #background-tasks-and-dependencies-with-yield-technical-details } + +ะ”ะพ **FastAPI** 0.106.0 ะฟั–ะดะฝั–ะผะฐั‚ะธ ะฒะธะฝัั‚ะบะธ ะฟั–ัะปั `yield` ะฑัƒะปะพ ะฝะตะผะพะถะปะธะฒะพ: ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ะท `yield` ะฒะธะบะพะฝัƒะฒะฐะฒัั ะฟั–ัะปั ะฝะฐะดัะธะปะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–, ั‚ะพะถ [ะพะฑั€ะพะฑะฝะธะบะธ ะฒะธะฝัั‚ะบั–ะฒ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} ัƒะถะต ะฒั–ะดะฟั€ะฐั†ัŽะฒะฐะปะธ ะฑ. + +ะขะฐะบ ะฑัƒะปะพ ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะพ ะณะพะปะพะฒะฝะพ ะดะปั ั‚ะพะณะพ, ั‰ะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ะพะฑ'ั”ะบั‚ะธ, ยซะฒั–ะดะดะฐะฝั–ยป ะทะฐะปะตะถะฝะพัั‚ัะผะธ ั‡ะตั€ะตะท `yield`, ัƒัะตั€ะตะดะธะฝั– ั„ะพะฝะพะฒะธั… ะทะฐะดะฐั‡, ะพัะบั–ะปัŒะบะธ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฒะธะบะพะฝัƒะฒะฐะฒัั ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ั„ะพะฝะพะฒะธั… ะทะฐะดะฐั‡. + +ะฃ **FastAPI** 0.106.0 ั†ะต ะทะผั–ะฝะตะฝะพ, ั‰ะพะฑ ะฝะต ัƒั‚ั€ะธะผัƒะฒะฐั‚ะธ ั€ะตััƒั€ัะธ ะฟั–ะด ั‡ะฐั ะพั‡ั–ะบัƒะฒะฐะฝะฝั, ะฟะพะบะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฟั–ะดะต ะผะตั€ะตะถะตัŽ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะšั€ั–ะผ ั‚ะพะณะพ, ั„ะพะฝะพะฒะฐ ะทะฐะดะฐั‡ะฐ ะทะฐะทะฒะธั‡ะฐะน ั” ะฝะตะทะฐะปะตะถะฝะธะผ ะฝะฐะฑะพั€ะพะผ ะปะพะณั–ะบะธ, ัะบะธะน ัะปั–ะด ะพะฑั€ะพะฑะปัั‚ะธ ะพะบั€ะตะผะพ, ะท ะฒะปะฐัะฝะธะผะธ ั€ะตััƒั€ัะฐะผะธ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะปะฐัะฝะธะผ ะท'ั”ะดะฝะฐะฝะฝัะผ ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั…). + +ะขะพะถ ั‚ะฐะบ ัƒ ะฒะฐั, ะนะผะพะฒั–ั€ะฝะพ, ะฑัƒะดะต ั‡ะธัั‚ั–ัˆะธะน ะบะพะด. + +/// + +ะฏะบั‰ะพ ะฒะธ ั€ะฐะฝั–ัˆะต ะฟะพะบะปะฐะดะฐะปะธัั ะฝะฐ ั†ัŽ ะฟะพะฒะตะดั–ะฝะบัƒ, ั‚ะตะฟะตั€ ัะปั–ะด ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั€ะตััƒั€ัะธ ะดะปั ั„ะพะฝะพะฒะธั… ะทะฐะดะฐั‡ ัƒัะตั€ะตะดะธะฝั– ัะฐะผะพั— ั„ะพะฝะพะฒะพั— ะทะฐะดะฐั‡ั– ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒัะตั€ะตะดะธะฝั– ะปะธัˆะต ะดะฐะฝั–, ั‰ะพ ะฝะต ะทะฐะปะตะถะฐั‚ัŒ ะฒั–ะด ั€ะตััƒั€ัั–ะฒ ะทะฐะปะตะถะฝะพัั‚ะตะน ั–ะท `yield`. + +ะะฐะฟั€ะธะบะปะฐะด, ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ั–ั”ั— ัะฐะผะพั— ัะตัั–ั— ะฑะฐะทะธ ะดะฐะฝะธั… ะฒะธ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธะผะตั‚ะต ะฝะพะฒัƒ ัะตัั–ัŽ ะฒ ัะฐะผั–ะน ั„ะพะฝะพะฒั–ะน ะทะฐะดะฐั‡ั– ั‚ะฐ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผะตั‚ะต ะพะฑ'ั”ะบั‚ะธ ะท ะฑะฐะทะธ ะดะฐะฝะธั…, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั†ัŽ ะฝะพะฒัƒ ัะตัั–ัŽ. ะ† ะดะฐะปั–, ะทะฐะผั–ัั‚ัŒ ะฟะตั€ะตะดะฐะฒะฐะฝะฝั ะพะฑ'ั”ะบั‚ะฐ ะท ะฑะฐะทะธ ะดะฐะฝะธั… ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ัƒ ั„ัƒะฝะบั†ั–ัŽ ั„ะพะฝะพะฒะพั— ะทะฐะดะฐั‡ั–, ะฒะธ ะฟะตั€ะตะดะฐัั‚ะต ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€ ั†ัŒะพะณะพ ะพะฑ'ั”ะบั‚ะฐ, ะฐ ะฟะพั‚ั–ะผ ะพั‚ั€ะธะผะฐั”ั‚ะต ะพะฑ'ั”ะบั‚ ะทะฝะพะฒัƒ ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— ั„ะพะฝะพะฒะพั— ะทะฐะดะฐั‡ั–. diff --git a/docs/uk/docs/advanced/advanced-python-types.md b/docs/uk/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..9eedc48568 --- /dev/null +++ b/docs/uk/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ะŸั€ะพััƒะฝัƒั‚ั– ั‚ะธะฟะธ Python { #advanced-python-types } + +ะžััŒ ะบั–ะปัŒะบะฐ ะดะพะดะฐั‚ะบะพะฒะธั… ั–ะดะตะน, ัะบั– ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะบะพั€ะธัะฝั– ะฟั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะท ั‚ะธะฟะฐะผะธ ะฒ Python. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `Union` ะฐะฑะพ `Optional` { #using-union-or-optional } + +ะฏะบั‰ะพ ะฒะฐัˆ ะบะพะด ะท ัะบะพั—ััŒ ะฟั€ะธั‡ะธะฝะธ ะฝะต ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `|`, ะฝะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ั†ะต ะฝะต ะฐะฝะพั‚ะฐั†ั–ั ั‚ะธะฟั–ะฒ, ะฐ ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ `response_model=`, ะทะฐะผั–ัั‚ัŒ ะฒะตั€ั‚ะธะบะฐะปัŒะฝะพั— ั€ะธัะบะธ (`|`) ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `Union` ะท `typing`. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ, ั‰ะพ ั‰ะพััŒ ะผะพะถะต ะฑัƒั‚ะธ `str` ะฐะฑะพ `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +ะฃ `typing` ั‚ะฐะบะพะถ ั” ัะบะพั€ะพั‡ะตะฝะฝั, ั‰ะพะฑ ะพะณะพะปะพัะธั‚ะธ, ั‰ะพ ั‰ะพััŒ ะผะพะถะต ะฑัƒั‚ะธ `None`, - `Optional`. + +ะžััŒ ะฟะพั€ะฐะดะฐ ะท ะผะพั”ั— ะดัƒะถะต ยซััƒะฑ'ั”ะบั‚ะธะฒะฝะพั—ยป ั‚ะพั‡ะบะธ ะทะพั€ัƒ: + +- ๐Ÿšจ ะฃะฝะธะบะฐะนั‚ะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `Optional[SomeType]` +- ะะฐั‚ะพะผั–ัั‚ัŒ โœจ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `Union[SomeType, None]`** โœจ. + +ะžะฑะธะดะฒะฐ ะฒะฐั€ั–ะฐะฝั‚ะธ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝั– ั– ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ะพะดะฝะฐะบะพะฒั–, ะฐะปะต ั ั€ะตะบะพะผะตะฝะดัƒัŽ `Union` ะทะฐะผั–ัั‚ัŒ `Optional`, ั‚ะพะผัƒ ั‰ะพ ัะปะพะฒะพ ยซ**optional**ยป ะฝั–ะฑะธ ะฝะฐั‚ัะบะฐั”, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ, ะฐ ะฝะฐัะฟั€ะฐะฒะดั– ะพะทะฝะฐั‡ะฐั” ยซะผะพะถะต ะฑัƒั‚ะธ `None`ยป, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะพ ะฝะต ั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ ั– ะฒัะต ั‰ะต ะพะฑะพะฒ'ัะทะบะพะฒะต. + +ะ’ะฒะฐะถะฐัŽ, `Union[SomeType, None]` ะฑั–ะปัŒัˆ ัะฒะฝะพ ั†ะต ะฟะตั€ะตะดะฐั”. + +ะ™ะดะตั‚ัŒัั ะปะธัˆะต ะฟั€ะพ ัะปะพะฒะฐ ั‚ะฐ ะฝะฐะทะฒะธ. ะะปะต ั†ั– ัะปะพะฒะฐ ะผะพะถัƒั‚ัŒ ะฒะฟะปะธะฒะฐั‚ะธ ะฝะฐ ั‚ะต, ัะบ ะฒะธ ั‚ะฐ ะฒะฐัˆะฐ ะบะพะผะฐะฝะดะฐ ะดัƒะผะฐั”ั‚ะต ะฟั€ะพ ะบะพะด. + +ะฏะบ ะฟั€ะธะบะปะฐะด, ั€ะพะทะณะปัะฝัŒะผะพ ั†ัŽ ั„ัƒะฝะบั†ั–ัŽ: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +ะŸะฐั€ะฐะผะตั‚ั€ `name` ะฒะธะทะฝะฐั‡ะตะฝะพ ัะบ `Optional[str]`, ะฐะปะต ะฒั–ะฝ ะฝะต ั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ, ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฒะธะบะปะธะบะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ ะฑะตะท ั†ัŒะพะณะพ ะฟะฐั€ะฐะผะตั‚ั€ะฐ: + +```Python +say_hi() # ะž ะฝั–, ั†ะต ะฒะธะบะปะธะบะฐั” ะฟะพะผะธะปะบัƒ! ๐Ÿ˜ฑ +``` + +ะŸะฐั€ะฐะผะตั‚ั€ `name` ะฒัะต ั‰ะต ะพะฑะพะฒ'ัะทะบะพะฒะธะน (ะฝะต ยซะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะนยป), ั‚ะพะผัƒ ั‰ะพ ะฝะต ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. ะ’ะพะดะฝะพั‡ะฐั `name` ะฟั€ะธะนะผะฐั” `None` ัะบ ะทะฝะฐั‡ะตะฝะฝั: + +```Python +say_hi(name=None) # ะฆะต ะฟั€ะฐั†ัŽั”, None ะฟั€ะธะฟัƒัั‚ะธะผะธะน ๐ŸŽ‰ +``` + +ะ“ะฐั€ะฝะฐ ะฝะพะฒะธะฝะฐ: ัƒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะทะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `|`, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะพะฑ'ั”ะดะฝะฐะฝะฝั ั‚ะธะฟั–ะฒ: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +ะขะพะถ ะทะฐะทะฒะธั‡ะฐะน ะฒะฐะผ ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ะฟะตั€ะตะนะผะฐั‚ะธัั ั‚ะฐะบะธะผะธ ะฝะฐะทะฒะฐะผะธ, ัะบ `Optional` ั– `Union`. ๐Ÿ˜Ž diff --git a/docs/uk/docs/advanced/async-tests.md b/docs/uk/docs/advanced/async-tests.md new file mode 100644 index 0000000000..51d0d57610 --- /dev/null +++ b/docs/uk/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# ะัะธะฝั…ั€ะพะฝะฝั– ั‚ะตัั‚ะธ { #async-tests } + +ะ’ะธ ะฒะถะต ะฑะฐั‡ะธะปะธ, ัะบ ั‚ะตัั‚ัƒะฒะฐั‚ะธ ะฒะฐัˆั– ะทะฐัั‚ะพััƒะฝะบะธ **FastAPI** ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฝะฐะดะฐะฝะพะณะพ `TestClient`. ะ”ะพ ั†ัŒะพะณะพ ั‡ะฐััƒ ะฒะธ ะฑะฐั‡ะธะปะธ ะปะธัˆะต, ัะบ ะฟะธัะฐั‚ะธ ัะธะฝั…ั€ะพะฝะฝั– ั‚ะตัั‚ะธ, ะฑะตะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั„ัƒะฝะบั†ั–ะน `async`. + +ะœะพะถะปะธะฒั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝั– ั„ัƒะฝะบั†ั–ั— ัƒ ั‚ะตัั‚ะฐั… ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพัŽ, ะฝะฐะฟั€ะธะบะปะฐะด, ะบะพะปะธ ะฒะธ ะฐัะธะฝั…ั€ะพะฝะฝะพ ะทะฒะตั€ั‚ะฐั”ั‚ะตัั ะดะพ ะฑะฐะทะธ ะดะฐะฝะธั…. ะฃัะฒั–ั‚ัŒ, ั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั€ะพั‚ะตัั‚ัƒะฒะฐั‚ะธ ะฝะฐะดัะธะปะฐะฝะฝั ะทะฐะฟะธั‚ั–ะฒ ะดะพ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI, ะฐ ะฟะพั‚ั–ะผ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ะฒะฐัˆ ะฑะตะบะตะฝะด ัƒัะฟั–ัˆะฝะพ ะทะฐะฟะธัะฐะฒ ะบะพั€ะตะบั‚ะฝั– ะดะฐะฝั– ะฒ ะฑะฐะทัƒ ะดะฐะฝะธั…, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฐัะธะฝั…ั€ะพะฝะฝัƒ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ ะดะปั ะฑะฐะทะธ ะดะฐะฝะธั…. + +ะ ะพะทะณะปัะฝัŒะผะพ, ัะบ ั†ะต ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ. + +## pytest.mark.anyio { #pytest-mark-anyio } + +ะฏะบั‰ะพ ะผะธ ั…ะพั‡ะตะผะพ ะฒะธะบะปะธะบะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝั– ั„ัƒะฝะบั†ั–ั— ัƒ ั‚ะตัั‚ะฐั…, ัะฐะผั– ั‚ะตัั‚ะพะฒั– ั„ัƒะฝะบั†ั–ั— ะผะฐัŽั‚ัŒ ะฑัƒั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะผะธ. AnyIO ะฝะฐะดะฐั” ะทั€ัƒั‡ะฝะธะน ะฟะปะฐะณั–ะฝ, ัะบะธะน ะดะพะทะฒะพะปัั” ะฒะบะฐะทะฐั‚ะธ, ั‰ะพ ะดะตัะบั– ั‚ะตัั‚ะพะฒั– ั„ัƒะฝะบั†ั–ั— ัะปั–ะด ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะพ. + +## HTTPX { #httpx } + +ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะทะฒะธั‡ะฐะนะฝั– ั„ัƒะฝะบั†ั–ั— `def` ะทะฐะผั–ัั‚ัŒ `async def`, ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ั†ะต ะฒัะต ะพะดะฝะพ `async`-ะทะฐัั‚ะพััƒะฝะพะบ. + +`TestClient` ั€ะพะฑะธั‚ัŒ ะฟะตะฒะฝัƒ ยซะผะฐะณั–ัŽยป ะฒัะตั€ะตะดะธะฝั–, ั‰ะพะฑ ะฒะธะบะปะธะบะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ัƒ ะฒะฐัˆะธั… ะทะฒะธั‡ะฐะนะฝะธั… ั‚ะตัั‚ะพะฒะธั… ั„ัƒะฝะบั†ั–ัั… `def`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน pytest. ะะปะต ั†ั ยซะผะฐะณั–ัยป ะฑั–ะปัŒัˆะต ะฝะต ะฟั€ะฐั†ัŽั”, ะบะพะปะธ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะนะพะณะพ ะฒัะตั€ะตะดะธะฝั– ะฐัะธะฝั…ั€ะพะฝะฝะธั… ั„ัƒะฝะบั†ั–ะน. ะ—ะฐะฟัƒัะบะฐัŽั‡ะธ ั‚ะตัั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะพ, ะผะธ ะฑั–ะปัŒัˆะต ะฝะต ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `TestClient` ัƒ ะฝะฐัˆะธั… ั‚ะตัั‚ะพะฒะธั… ั„ัƒะฝะบั†ั–ัั…. + +`TestClient` ะฟะพะฑัƒะดะพะฒะฐะฝะธะน ะฝะฐ ะพัะฝะพะฒั– HTTPX, ั– ะฝะฐ ั‰ะฐัั‚ั, ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะดะปั ั‚ะตัั‚ัƒะฒะฐะฝะฝั API. + +## ะŸั€ะธะบะปะฐะด { #example } + +ะ”ะปั ะฟั€ะพัั‚ะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ั€ะพะทะณะปัะฝัŒะผะพ ัั‚ั€ัƒะบั‚ัƒั€ัƒ ั„ะฐะนะปั–ะฒ, ะฟะพะดั–ะฑะฝัƒ ะดะพ ะพะฟะธัะฐะฝะพั— ะฒ [ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ](../tutorial/bigger-applications.md){.internal-link target=_blank} ั‚ะฐ [ะขะตัั‚ัƒะฒะฐะฝะฝั](../tutorial/testing.md){.internal-link target=_blank}: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ””โ”€โ”€ test_main.py +``` + +ะคะฐะนะป `main.py` ะผั–ัั‚ะธั‚ะธะผะต: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +ะคะฐะนะป `test_main.py` ะผั–ัั‚ะธั‚ะธะผะต ั‚ะตัั‚ะธ ะดะปั `main.py`, ั‚ะตะฟะตั€ ั†ะต ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## ะ—ะฐะฟัƒัะบ { #run-it } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ั‚ะตัั‚ะธ ัะบ ะทะฐะทะฒะธั‡ะฐะน: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## ะ”ะพะบะปะฐะดะฝะพ { #in-detail } + +ะœะฐั€ะบะตั€ `@pytest.mark.anyio` ะฟะพะฒั–ะดะพะผะปัั” pytest, ั‰ะพ ั†ัŽ ั‚ะตัั‚ะพะฒัƒ ั„ัƒะฝะบั†ั–ัŽ ัะปั–ะด ะฒะธะบะปะธะบะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะพ: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐัƒะฒะฐะถั‚ะต, ั‰ะพ ั‚ะตัั‚ะพะฒะฐ ั„ัƒะฝะบั†ั–ั ั‚ะตะฟะตั€ `async def` ะทะฐะผั–ัั‚ัŒ ะฟั€ะพัั‚ะพ `def`, ัะบ ั†ะต ะฑัƒะปะพ ั€ะฐะฝั–ัˆะต ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– `TestClient`. + +/// + +ะ”ะฐะปั– ะผะธ ะผะพะถะตะผะพ ัั‚ะฒะพั€ะธั‚ะธ `AsyncClient` ั–ะท ะทะฐัั‚ะพััƒะฝะบะพะผ ั– ะฝะฐะดัะธะปะฐั‚ะธ ะดะพ ะฝัŒะพะณะพ ะฐัะธะฝั…ั€ะพะฝะฝั– ะทะฐะฟะธั‚ะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `await`. + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +ะฆะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ: + +```Python +response = client.get('/') +``` + +...ั‰ะพ ะผะธ ั€ะฐะฝั–ัˆะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ะดะปั ะฝะฐะดัะธะปะฐะฝะฝั ะทะฐะฟะธั‚ั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `TestClient`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐัƒะฒะฐะถั‚ะต, ั‰ะพ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ async/await ั–ะท ะฝะพะฒะธะผ `AsyncClient` - ะทะฐะฟะธั‚ ั” ะฐัะธะฝั…ั€ะพะฝะฝะธะผ. + +/// + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฏะบั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด ะฟะพะดั–ะน ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั, `AsyncClient` ะฝะต ั–ะฝั–ั†ั–ัŽะฒะฐั‚ะธะผะต ั†ั– ะฟะพะดั–ั—. ะฉะพะฑ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ั—ั… ั–ะฝั–ั†ั–ะฐะปั–ะทะฐั†ั–ัŽ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `LifespanManager` ะท florimondmanca/asgi-lifespan. + +/// + +## ะ†ะฝัˆั– ะฐัะธะฝั…ั€ะพะฝะฝั– ะฒะธะบะปะธะบะธ ั„ัƒะฝะบั†ั–ะน { #other-asynchronous-function-calls } + +ะžัะบั–ะปัŒะบะธ ั‚ะตัั‚ะพะฒะฐ ั„ัƒะฝะบั†ั–ั ั‚ะตะฟะตั€ ะฐัะธะฝั…ั€ะพะฝะฝะฐ, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะปะธะบะฐั‚ะธ (ั– `await`) ั–ะฝัˆั– `async`-ั„ัƒะฝะบั†ั–ั— ะพะบั€ั–ะผ ะฝะฐะดัะธะปะฐะฝะฝั ะทะฐะฟะธั‚ั–ะฒ ะดะพ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI ัƒ ั‚ะตัั‚ะฐั… - ั‚ะฐะบ ัะฐะผะพ, ัะบ ะฒะธ ั€ะพะฑะธะปะธ ะฑ ั†ะต ะฑัƒะดัŒ-ะดะต ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั–. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฝะฐั‚ั€ะฐะฟะธะปะธ ะฝะฐ `RuntimeError: Task attached to a different loop` ะฟั–ะด ั‡ะฐั ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะฐัะธะฝั…ั€ะพะฝะฝะธั… ะฒะธะบะปะธะบั–ะฒ ัƒ ะฒะฐัˆั– ั‚ะตัั‚ะธ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– MongoDB's MotorClient), ะฟะฐะผ'ัั‚ะฐะนั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะพะฑ'ั”ะบั‚ะธ, ัะบะธะผ ะฟะพั‚ั€ั–ะฑะตะฝ ั†ะธะบะป ะฟะพะดั–ะน, ะปะธัˆะต ะฒัะตั€ะตะดะธะฝั– ะฐัะธะฝั…ั€ะพะฝะฝะธั… ั„ัƒะฝะบั†ั–ะน, ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะทะฒะพั€ะพั‚ะฝะพะผัƒ ะฒะธะบะปะธะบัƒ `@app.on_event("startup")`. + +/// diff --git a/docs/uk/docs/advanced/behind-a-proxy.md b/docs/uk/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000..66bb4c0827 --- /dev/null +++ b/docs/uk/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# ะ—ะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ { #behind-a-proxy } + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะฑัƒะดะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ** ะฝะฐ ะบัˆั‚ะฐะปั‚ Traefik ะฐะฑะพ Nginx ะฟะตั€ะตะด ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ FastAPI. + +ะขะฐะบั– ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะธ ะผะพะถัƒั‚ัŒ ะพะฑั€ะพะฑะปัั‚ะธ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ HTTPS ั‚ะฐ ั–ะฝัˆั– ั€ะตั‡ั–. + +## ะะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ { #proxy-forwarded-headers } + +**ะŸั€ะตะดัั‚ะฐะฒะฝะธะบ** ะฟะตั€ะตะด ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ ะทะฐะทะฒะธั‡ะฐะน ะฒัั‚ะฐะฝะพะฒะปัŽั” ะดะตัะบั– ะทะฐะณะพะปะพะฒะบะธ ะฝะฐ ะปัŒะพั‚ัƒ ะฟะตั€ะตะด ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝัะผ ะทะฐะฟะธั‚ั–ะฒ ะดะพ ะฒะฐัˆะพะณะพ **ัะตั€ะฒะตั€ะฐ**, ั‰ะพะฑ ะฟะพะฒั–ะดะพะผะธั‚ะธ ัะตั€ะฒะตั€ัƒ, ั‰ะพ ะทะฐะฟะธั‚ ะฑัƒะปะพ **ะฝะฐะฟั€ะฐะฒะปะตะฝะพ** ั‡ะตั€ะตะท ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ, ะฒะบะฐะทะฐั‚ะธ ะพั€ะธะณั–ะฝะฐะปัŒะฝัƒ (ะฟัƒะฑะปั–ั‡ะฝัƒ) URL-ะฐะดั€ะตััƒ, ะฒะบะปัŽั‡ะฝะพ ะท ะดะพะผะตะฝะพะผ, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั HTTPS ั‚ะพั‰ะพ. + +ะŸั€ะพะณั€ะฐะผะฝะธะน **ัะตั€ะฒะตั€** (ะฝะฐะฟั€ะธะบะปะฐะด, **Uvicorn** ั‡ะตั€ะตะท **FastAPI CLI**) ะทะดะฐั‚ะฝะธะน ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒะฒะฐั‚ะธ ั†ั– ะทะฐะณะพะปะพะฒะบะธ ั– ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ั†ัŽ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะะปะต ะท ะผั–ั€ะบัƒะฒะฐะฝัŒ ะฑะตะทะฟะตะบะธ, ะพัะบั–ะปัŒะบะธ ัะตั€ะฒะตั€ ะฝะต ะทะฝะฐั”, ั‰ะพ ะฒั–ะฝ ะฟั€ะฐั†ัŽั” ะทะฐ ะดะพะฒั–ั€ะตะฝะธะผ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ, ะฒั–ะฝ ะฝะต ั–ะฝั‚ะตั€ะฟั€ะตั‚ัƒะฒะฐั‚ะธะผะต ั†ั– ะทะฐะณะพะปะพะฒะบะธ. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ—ะฐะณะพะปะพะฒะบะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### ะฃะฒั–ะผะบะฝัƒั‚ะธ ะฝะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ { #enable-proxy-forwarded-headers } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ FastAPI CLI ะท *ะพะฟั†ั–ั”ัŽ CLI* `--forwarded-allow-ips` ั– ะฟะตั€ะตะดะฐั‚ะธ IP-ะฐะดั€ะตัะธ, ัะบะธะผ ัะปั–ะด ะดะพะฒั–ั€ัั‚ะธ ะดะปั ั‡ะธั‚ะฐะฝะฝั ั†ะธั… ะฝะฐะฟั€ะฐะฒะปะตะฝะธั… ะทะฐะณะพะปะพะฒะบั–ะฒ. + +ะฏะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะธั‚ะต `--forwarded-allow-ips="*"`, ั†ะต ะพะทะฝะฐั‡ะฐั‚ะธะผะต ะดะพะฒั–ั€ัƒ ะดะพ ะฒัั–ั… ะฒั…ั–ะดะฝะธั… IP. + +ะฏะบั‰ะพ ะฒะฐัˆ **ัะตั€ะฒะตั€** ะทะฝะฐั…ะพะดะธั‚ัŒัั ะทะฐ ะดะพะฒั–ั€ะตะฝะธะผ **ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ** ั– ั‚ั–ะปัŒะบะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ัะฟั–ะปะบัƒั”ั‚ัŒัั ะท ะฝะธะผ, ั†ะต ะทะผัƒัะธั‚ัŒ ัะตั€ะฒะตั€ ะฟั€ะธะนะผะฐั‚ะธ ะฑัƒะดัŒ-ัะบัƒ IP-ะฐะดั€ะตััƒ ั†ัŒะพะณะพ **ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ**. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ะŸะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะฝั ะท HTTPS { #redirects-with-https } + +ะะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธะฟัƒัั‚ะธะผะพ, ะฒะธ ะฒะธะทะฝะฐั‡ะธะปะธ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* `/items/`: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +ะฏะบั‰ะพ ะบะปั–ั”ะฝั‚ ัะฟั€ะพะฑัƒั” ะฟะตั€ะตะนั‚ะธ ะดะพ `/items`, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะฝั ะฝะฐ `/items/`. + +ะะปะต ะดะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั *ะพะฟั†ั–ั— CLI* `--forwarded-allow-ips` ั†ะต ะผะพะณะปะพ ะฑ ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะธั‚ะธ ะฝะฐ `http://localhost:8000/items/`. + +ะ’ั‚ั–ะผ, ะผะพะถะปะธะฒะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ั€ะพะทะผั–ั‰ะตะฝะพ ะฝะฐ `https://mysuperapp.com`, ั– ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะฝั ะผะฐั” ะฑัƒั‚ะธ ะฝะฐ `https://mysuperapp.com/items/`. + +ะะฐะปะฐัˆั‚ัƒะฒะฐะฒัˆะธ `--proxy-headers`, FastAPI ะทะผะพะถะต ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปัั‚ะธ ะฝะฐ ะฟั€ะฐะฒะธะปัŒะฝัƒ ะฐะดั€ะตััƒ. ๐Ÿ˜Ž + +``` +https://mysuperapp.com/items/ +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ HTTPS, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะฟะพัั–ะฑะฝะธะบ [ะŸั€ะพ HTTPS](../deployment/https.md){.internal-link target=_blank}. + +/// + +### ะฏะบ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฝะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ { #how-proxy-forwarded-headers-work } + +ะžััŒ ะฒั–ะทัƒะฐะปัŒะฝะต ะฟะพะดะฐะฝะฝั ั‚ะพะณะพ, ัะบ **ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ** ะดะพะดะฐั” ะฝะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะผั–ะถ ะบะปั–ั”ะฝั‚ะพะผ ั– **ัะตั€ะฒะตั€ะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ**: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**ะŸั€ะตะดัั‚ะฐะฒะฝะธะบ** ะฟะตั€ะตั…ะพะฟะปัŽั” ะฟะพั‡ะฐั‚ะบะพะฒะธะน ะทะฐะฟะธั‚ ะบะปั–ั”ะฝั‚ะฐ ั– ะดะพะดะฐั” ัะฟะตั†ั–ะฐะปัŒะฝั– *ะฝะฐะฟั€ะฐะฒะปะตะฝั–* ะทะฐะณะพะปะพะฒะบะธ (`X-Forwarded-*`) ะฟะตั€ะตะด ะฟะตั€ะตะดะฐั‡ะตัŽ ะทะฐะฟะธั‚ัƒ ะฝะฐ **ัะตั€ะฒะตั€ ะทะฐัั‚ะพััƒะฝะบัƒ**. + +ะฆั– ะทะฐะณะพะปะพะฒะบะธ ะทะฑะตั€ั–ะณะฐัŽั‚ัŒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฟั€ะพ ะพั€ะธะณั–ะฝะฐะปัŒะฝะธะน ะทะฐะฟะธั‚, ัะบะฐ ั–ะฝะฐะบัˆะต ะฑัƒะปะฐ ะฑ ะฒั‚ั€ะฐั‡ะตะฝะฐ: + +- X-Forwarded-For: ะพั€ะธะณั–ะฝะฐะปัŒะฝะฐ IP-ะฐะดั€ะตัะฐ ะบะปั–ั”ะฝั‚ะฐ +- X-Forwarded-Proto: ะพั€ะธะณั–ะฝะฐะปัŒะฝะธะน ะฟั€ะพั‚ะพะบะพะป (`https`) +- X-Forwarded-Host: ะพั€ะธะณั–ะฝะฐะปัŒะฝะธะน ั…ะพัั‚ (`mysuperapp.com`) + +ะšะพะปะธ **FastAPI CLI** ะฝะฐะปะฐัˆั‚ะพะฒะฐะฝะพ ะท `--forwarded-allow-ips`, ะฒั–ะฝ ะดะพะฒั–ั€ัั” ั†ะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั—ั…, ะฝะฐะฟั€ะธะบะปะฐะด, ะดะปั ะฟะพะฑัƒะดะพะฒะธ ะบะพั€ะตะบั‚ะฝะธั… URL-ะฐะดั€ะตั ัƒ ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะฝัั…. + +## ะŸั€ะตะดัั‚ะฐะฒะฝะธะบ ั–ะท ะฒะธะปัƒั‡ะตะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ { #proxy-with-a-stripped-path-prefix } + +ะฃ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ, ั‰ะพ ะดะพะดะฐั” ะฟั€ะตั„ั–ะบั ัˆะปัั…ัƒ ะดะพ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `root_path` ะดะปั ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— ะทะฐัั‚ะพััƒะฝะบัƒ. + +`root_path` - ั†ะต ะผะตั…ะฐะฝั–ะทะผ, ะฝะฐะดะฐะฝะธะน ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั”ัŽ ASGI (ะฝะฐ ัะบั–ะน ะฟะพะฑัƒะดะพะฒะฐะฝะพ FastAPI ั‡ะตั€ะตะท Starlette). + +`root_path` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ะพะฑั€ะพะฑะบะธ ัะฐะผะต ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ. + +ะ™ะพะณะพ ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ะฟั–ะด ั‡ะฐั ะผะพะฝั‚ัƒะฒะฐะฝะฝั ะฟั–ะดะทะฐัั‚ะพััƒะฝะบั–ะฒ. + +ะะฐัะฒะฝั–ัั‚ัŒ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ ะท ะฒะธะปัƒั‡ะตะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒะธ ะผะพะณะปะธ ะฑ ะพะณะพะปะพัะธั‚ะธ ัˆะปัั… `/app` ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั–, ะฐะปะต ะฟะพั‚ั–ะผ ะดะพะดะฐั‚ะธ ัˆะฐั€ ะทะฒะตั€ั…ัƒ (ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ), ัะบะธะน ั€ะพะทะผั–ัั‚ะธั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ะฟั–ะด ัˆะปัั…ะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚ `/api/v1`. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฟะพั‡ะฐั‚ะบะพะฒะธะน ัˆะปัั… `/app` ั„ะฐะบั‚ะธั‡ะฝะพ ะฑัƒะดะต ะดะพัั‚ัƒะฟะฝะธะน ะทะฐ `/api/v1/app`. + +ะฅะพั‡ะฐ ะฒะตััŒ ะฒะฐัˆ ะบะพะด ะฝะฐะฟะธัะฐะฝะพ ะท ะฟั€ะธะฟัƒั‰ะตะฝะฝัะผ, ั‰ะพ ั” ะปะธัˆะต `/app`. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +ะ† ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ะฑัƒะดะต **ยซะทั€ั–ะทะฐั‚ะธยป** **ะฟั€ะตั„ั–ะบั ัˆะปัั…ัƒ** ะฝะฐ ะปัŒะพั‚ัƒ ะฟะตั€ะตะด ะฟะตั€ะตะดะฐั‡ะตัŽ ะทะฐะฟะธั‚ัƒ ัะตั€ะฒะตั€ัƒ ะทะฐัั‚ะพััƒะฝะบัƒ (ะนะผะพะฒั–ั€ะฝะพ, Uvicorn ั‡ะตั€ะตะท FastAPI CLI), ะทะฑะตั€ั–ะณะฐัŽั‡ะธ ะฟะตั€ะตะบะพะฝะฐะฝะฝั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ะนะพะณะพ ะพะฑัะปัƒะณะพะฒัƒัŽั‚ัŒ ะทะฐ `/app`, ั‚ะพะถ ะฒะฐะผ ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ะพะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒะตััŒ ะบะพะด, ั‰ะพะฑ ะดะพะดะฐั‚ะธ ะฟั€ะตั„ั–ะบั `/api/v1`. + +ะ”ะพั‚ะตะฟะตั€ ัƒัะต ะฟั€ะฐั†ัŽะฒะฐะปะพ ะฑ ัะบ ะทะฐะทะฒะธั‡ะฐะน. + +ะะปะต ะบะพะปะธ ะฒะธ ะฒั–ะดะบั€ะธั”ั‚ะต ะฒะฑัƒะดะพะฒะฐะฝะธะน ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ั„ั€ะพะฝั‚ะตะฝะด), ะฒั–ะฝ ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต ะพั‚ั€ะธะผะฐั‚ะธ ัั…ะตะผัƒ OpenAPI ะทะฐ `/openapi.json`, ะทะฐะผั–ัั‚ัŒ `/api/v1/openapi.json`. + +ะžั‚ะถะต, ั„ั€ะพะฝั‚ะตะฝะด (ั‰ะพ ะฟั€ะฐั†ัŽั” ัƒ ะฑั€ะฐัƒะทะตั€ั–) ัะฟั€ะพะฑัƒั” ะทะฒะตั€ะฝัƒั‚ะธัั ะดะพ `/openapi.json` ั– ะฝะต ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ัั…ะตะผัƒ OpenAPI. + +ะžัะบั–ะปัŒะบะธ ัƒ ะฝะฐั ั” ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ะท ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ `/api/v1` ะดะปั ะฝะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ั„ั€ะพะฝั‚ะตะฝะดัƒ ะฟะพั‚ั€ั–ะฑะฝะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ัั…ะตะผัƒ OpenAPI ะทะฐ `/api/v1/openapi.json`. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +IP `0.0.0.0` ะทะฐะทะฒะธั‡ะฐะน ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฟั€ะพะณั€ะฐะผะฐ ัะปัƒั…ะฐั” ะฝะฐ ะฒัั–ั… IP-ะฐะดั€ะตัะฐั…, ะดะพัั‚ัƒะฟะฝะธั… ะฝะฐ ั†ั–ะน ะผะฐัˆะธะฝั–/ัะตั€ะฒะตั€ั–. + +/// + +ะ†ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั‚ะฐะบะพะถ ะฟะพั‚ั€ั–ะฑะฝะพ, ั‰ะพะฑ ัั…ะตะผะฐ OpenAPI ะพะณะพะปะพัˆัƒะฒะฐะปะฐ, ั‰ะพ ั†ะตะน `server` API ั€ะพะทั‚ะฐัˆะพะฒะฐะฝะธะน ะทะฐ `/api/v1` (ะทะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ). ะะฐะฟั€ะธะบะปะฐะด: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // ะฉะต ะดะตั‰ะพ ั‚ัƒั‚ + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // ะฉะต ะดะตั‰ะพ ั‚ัƒั‚ + } +} +``` + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ยซProxyยป ะผะพะถะต ะฑัƒั‚ะธ ั‡ะธะผะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ **Traefik**. ะ ัะตั€ะฒะตั€ะพะผ ะฑัƒะดะต ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ FastAPI CLI ะท **Uvicorn**, ัะบะธะน ะทะฐะฟัƒัะบะฐั” ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI. + +### ะ—ะฐะดะฐะฝะฝั `root_path` { #providing-the-root-path } + +ะฉะพะฑ ั†ัŒะพะณะพ ะดะพััะณั‚ะธ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--root-path`, ะฝะฐะฟั€ะธะบะปะฐะด: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Hypercorn, ัƒ ะฝัŒะพะณะพ ั‚ะฐะบะพะถ ั” ะพะฟั†ั–ั `--root-path`. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั ASGI ะฒะธะทะฝะฐั‡ะฐั” `root_path` ะดะปั ั‚ะฐะบะพะณะพ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. + +ะ ะพะฟั†ั–ั ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--root-path` ะฝะฐะดะฐั” ั†ะตะน `root_path`. + +/// + +### ะŸะตั€ะตะฒั–ั€ะบะฐ ะฟะพั‚ะพั‡ะฝะพะณะพ `root_path` { #checking-the-current-root-path } + +ะ’ะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะฟะพั‚ะพั‡ะฝะธะน `root_path`, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ, ะฒั–ะฝ ั” ั‡ะฐัั‚ะธะฝะพัŽ ัะปะพะฒะฝะธะบะฐ `scope` (ั†ะต ั‡ะฐัั‚ะธะฝะฐ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— ASGI). + +ะขัƒั‚ ะผะธ ะดะพะดะฐั”ะผะพ ะนะพะณะพ ัƒ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะปะธัˆะต ะดะปั ะดะตะผะพะฝัั‚ั€ะฐั†ั–ั—. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +ะŸะพั‚ั–ะผ, ัะบั‰ะพ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต Uvicorn ั‚ะฐะบ: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะ’ั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบะพัŽ: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### ะ’ัั‚ะฐะฝะพะฒะปะตะฝะฝั `root_path` ัƒ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI { #setting-the-root-path-in-the-fastapi-app } + +ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะพ, ัะบั‰ะพ ัƒ ะฒะฐั ะฝะตะผะฐั” ัะฟะพัะพะฑัƒ ะฟะตั€ะตะดะฐั‚ะธ ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ ะฝะฐ ะบัˆั‚ะฐะปั‚ `--root-path` ั‡ะธ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝัƒ, ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `root_path` ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI: + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +ะŸะตั€ะตะดะฐั‡ะฐ `root_path` ะดะพ `FastAPI` ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะฐ ะฟะตั€ะตะดะฐั‡ั– ะพะฟั†ั–ั— ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--root-path` ะดะพ Uvicorn ะฐะฑะพ Hypercorn. + +### ะŸั€ะพ `root_path` { #about-root-path } + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ัะตั€ะฒะตั€ (Uvicorn) ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต `root_path` ะฝั– ะดะปั ั‡ะพะณะพ, ะพะบั€ั–ะผ ะฟะตั€ะตะดะฐั‡ั– ะนะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะะปะต ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ัƒ ะฒะฐัˆะพะผัƒ ะฑั€ะฐัƒะทะตั€ั– ะฝะฐ http://127.0.0.1:8000/app, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะทะฒะธั‡ะฐะนะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ะขะพะฑั‚ะพ ะฒั–ะฝ ะฝะต ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต ะดะพัั‚ัƒะฟัƒ ะทะฐ ะฐะดั€ะตัะพัŽ `http://127.0.0.1:8000/api/v1/app`. + +Uvicorn ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต, ั‰ะพ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ะฑัƒะดะต ะทะฒะตั€ั‚ะฐั‚ะธัั ะดะพ Uvicorn ะฝะฐ `http://127.0.0.1:8000/app`, ั– ั‚ะพะดั– ัะฐะผะต ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธะผะต ะทะฐ ะดะพะดะฐะฒะฐะฝะฝั ะดะพะดะฐั‚ะบะพะฒะพะณะพ ะฟั€ะตั„ั–ะบัะฐ `/api/v1` ะทะฒะตั€ั…ัƒ. + +## ะŸั€ะพ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบั–ะฒ ั–ะท ะฒะธะปัƒั‡ะตะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ { #about-proxies-with-a-stripped-path-prefix } + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ั–ะท ะฒะธะปัƒั‡ะตะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ - ั†ะต ะปะธัˆะต ะพะดะธะฝ ะทั– ัะฟะพัะพะฑั–ะฒ ะนะพะณะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ะฝะต ะผะฐั‚ะธะผะต ะฒะธะปัƒั‡ะตะฝะพะณะพ ะฟั€ะตั„ั–ะบัะฐ ัˆะปัั…ัƒ. + +ะฃ ั‚ะฐะบะพะผัƒ ะฒะธะฟะฐะดะบัƒ (ะฑะตะท ะฒะธะปัƒั‡ะตะฝะพะณะพ ะฟั€ะตั„ั–ะบัะฐ ัˆะปัั…ัƒ) ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ ัะปัƒั…ะฐั‚ะธะผะต ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ `https://myawesomeapp.com`, ั– ะบะพะปะธ ะฑั€ะฐัƒะทะตั€ ะฟะตั€ะตะนะดะต ะฝะฐ `https://myawesomeapp.com/api/v1/app`, ะฐ ะฒะฐัˆ ัะตั€ะฒะตั€ (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn) ัะปัƒั…ะฐั” ะฝะฐ `http://127.0.0.1:8000`, ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ (ะฑะตะท ะฒะธะปัƒั‡ะตะฝะพะณะพ ะฟั€ะตั„ั–ะบัะฐ) ะทะฒะตั€ะฝะตั‚ัŒัั ะดะพ Uvicorn ะทะฐ ั‚ะธะผ ัะฐะผะธะผ ัˆะปัั…ะพะผ: `http://127.0.0.1:8000/api/v1/app`. + +## ะ›ะพะบะฐะปัŒะฝะต ั‚ะตัั‚ัƒะฒะฐะฝะฝั ะท Traefik { #testing-locally-with-traefik } + +ะ’ะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฟั€ะพะฒะตัั‚ะธ ะตะบัะฟะตั€ะธะผะตะฝั‚ ะปะพะบะฐะปัŒะฝะพ ะท ะฒะธะปัƒั‡ะตะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ Traefik. + +ะ—ะฐะฒะฐะฝั‚ะฐะถั‚ะต Traefik, ั†ะต ะพะดะธะฝ ะฑั–ะฝะฐั€ะฝะธะน ั„ะฐะนะป, ะฒะธ ะผะพะถะตั‚ะต ั€ะพะทะฟะฐะบัƒะฒะฐั‚ะธ ะฐั€ั…ั–ะฒ ั– ะทะฐะฟัƒัั‚ะธั‚ะธ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ั‚ะตั€ะผั–ะฝะฐะปะฐ. + +ะŸะพั‚ั–ะผ ัั‚ะฒะพั€ั–ั‚ัŒ ั„ะฐะนะป `traefik.toml` ะท ั‚ะฐะบะธะผ ะฒะผั–ัั‚ะพะผ: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +ะฆะต ะฒะบะฐะทัƒั” Traefik ัะปัƒั…ะฐั‚ะธ ะฟะพั€ั‚ 9999 ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆะธะน ั„ะฐะนะป `routes.toml`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฟะพั€ั‚ 9999 ะทะฐะผั–ัั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะณะพ HTTP-ะฟะพั€ั‚ัƒ 80, ั‰ะพะฑ ะฒะฐะผ ะฝะต ะดะพะฒะตะปะพัั ะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ะท ะฐะดะผั–ะฝ-ะฟะพะฒะฝะพะฒะฐะถะตะฝะฝัะผะธ (`sudo`). + +/// + +ะขะตะฟะตั€ ัั‚ะฒะพั€ั–ั‚ัŒ ั–ะฝัˆะธะน ั„ะฐะนะป `routes.toml`: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +ะฆะตะน ั„ะฐะนะป ะฝะฐะปะฐัˆั‚ะพะฒัƒั” Traefik ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั€ะตั„ั–ะบัะฐ ัˆะปัั…ัƒ `/api/v1`. + +ะŸะพั‚ั–ะผ Traefik ะฟะตั€ะตัะฟั€ัะผะพะฒัƒะฒะฐั‚ะธะผะต ัะฒะพั— ะทะฐะฟะธั‚ะธ ะดะพ ะฒะฐัˆะพะณะพ Uvicorn, ัะบะธะน ะฟั€ะฐั†ัŽั” ะฝะฐ `http://127.0.0.1:8000`. + +ะขะตะฟะตั€ ะทะฐะฟัƒัั‚ั–ั‚ัŒ Traefik: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +ะ ั‚ะตะฟะตั€ ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะพะฟั†ั–ัŽ `--root-path`: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะฒั–ะดะฟะพะฒั–ะดั– { #check-the-responses } + +ะขะตะฟะตั€, ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะทะฐ URL ั–ะท ะฟะพั€ั‚ะพะผ Uvicorn: http://127.0.0.1:8000/app, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะทะฒะธั‡ะฐะนะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั…ะพั‡ะฐ ะฒะธ ะทะฒะตั€ั‚ะฐั”ั‚ะตัั ะทะฐ ะฐะดั€ะตัะพัŽ `http://127.0.0.1:8000/app`, ะฒั–ะดะพะฑั€ะฐะถะฐั”ั‚ัŒัั `root_path` `/api/v1`, ะฒะทัั‚ะธะน ั–ะท ะพะฟั†ั–ั— `--root-path`. + +/// + +ะ ั‚ะตะฟะตั€ ะฒั–ะดะบั€ะธะนั‚ะต URL ั–ะท ะฟะพั€ั‚ะพะผ Traefik, ะฒะบะปัŽั‡ะฝะพ ะท ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ: http://127.0.0.1:9999/api/v1/app. + +ะœะธ ะพั‚ั€ะธะผัƒั”ะผะพ ั‚ัƒ ัะฐะผัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +ะฐะปะต ั†ัŒะพะณะพ ั€ะฐะทัƒ ะทะฐ URL ั–ะท ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ, ัะบะธะน ะฝะฐะดะฐั” ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ: `/api/v1`. + +ะ—ะฒั–ัะฝะพ, ั–ะดะตั ะฟะพะปัะณะฐั” ะฒ ั‚ะพะผัƒ, ั‰ะพ ะฒัั– ะผะฐัŽั‚ัŒ ะดะพัั‚ัƒะฟะฐั‚ะธัั ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ ั‡ะตั€ะตะท ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ, ั‚ะพะถ ะฒะฐั€ั–ะฐะฝั‚ ั–ะท ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ `/api/v1` ั” ยซะฟั€ะฐะฒะธะปัŒะฝะธะผยป. + +ะ ะฒะฐั€ั–ะฐะฝั‚ ะฑะตะท ะฟั€ะตั„ั–ะบัะฐ ัˆะปัั…ัƒ (`http://127.0.0.1:8000/app`), ัะบะธะน ะฝะฐะดะฐั” ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ Uvicorn, ะผะฐั” ะฑัƒั‚ะธ ะฒะธะบะปัŽั‡ะฝะพ ะดะปั ั‚ะพะณะพ, ั‰ะพะฑ _ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ_ (Traefik) ะทะฒะตั€ั‚ะฐะฒัั ะดะพ ะฝัŒะพะณะพ. + +ะฆะต ะดะตะผะพะฝัั‚ั€ัƒั”, ัะบ ะŸั€ะตะดัั‚ะฐะฒะฝะธะบ (Traefik) ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฟั€ะตั„ั–ะบั ัˆะปัั…ัƒ ั– ัะบ ัะตั€ะฒะตั€ (Uvicorn) ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `root_path` ะท ะพะฟั†ั–ั— `--root-path`. + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #check-the-docs-ui } + +ะ ั‚ะตะฟะตั€ ะดะพ ั†ั–ะบะฐะฒะพั— ั‡ะฐัั‚ะธะฝะธ. โœจ + +ยซะžั„ั–ั†ั–ะนะฝะธะนยป ัะฟะพัั–ะฑ ะดะพัั‚ัƒะฟัƒ ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ - ั‡ะตั€ะตะท ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ ะท ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ, ัะบะธะน ะผะธ ะฒะธะทะฝะฐั‡ะธะปะธ. ะขะพะถ, ัะบ ั– ะพั‡ั–ะบัƒั”ั‚ัŒัั, ัะบั‰ะพ ะฒะธ ัะฟั€ะพะฑัƒั”ั‚ะต ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ัะบะธะน ะพะฑัะปัƒะณะพะฒัƒั” ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ Uvicorn ะฑะตะท ะฟั€ะตั„ั–ะบัะฐ ัˆะปัั…ัƒ ะฒ URL, ั†ะต ะฝะต ะทะฐะฟั€ะฐั†ัŽั”, ะพัะบั–ะปัŒะบะธ ะฒั–ะฝ ะพั‡ั–ะบัƒั” ะดะพัั‚ัƒะฟัƒ ั‡ะตั€ะตะท ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั†ะต ะฝะฐ http://127.0.0.1:8000/docs: + + + +ะะปะต ัะบั‰ะพ ะผะธ ะทะฒะตั€ะฝะตะผะพัั ะดะพ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะฐ ยซะพั„ั–ั†ั–ะนะฝะธะผยป URL, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ ะท ะฟะพั€ั‚ะพะผ `9999`, ะทะฐ ะฐะดั€ะตัะพัŽ `/api/v1/docs`, ัƒัะต ะฟั€ะฐั†ัŽั” ะบะพั€ะตะบั‚ะฝะพ! ๐ŸŽ‰ + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั†ะต ะฝะฐ http://127.0.0.1:9999/api/v1/docs: + + + +ะกะฐะผะต ั‚ะฐะบ, ัะบ ะผะธ ั…ะพั‚ั–ะปะธ. โœ”๏ธ + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `root_path`, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ั‚ะธะฟะพะฒะธะน `server` ะฒ OpenAPI ะท URL, ะฝะฐะดะฐะฝะพัŽ `root_path`. + +## ะ”ะพะดะฐั‚ะบะพะฒั– ัะตั€ะฒะตั€ะธ { #additional-servers } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฆะต ะฑั–ะปัŒัˆ ะฟั€ะพััƒะฝัƒั‚ะธะน ะฒะธะฟะฐะดะพะบ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. ะœะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ะนะพะณะพ. + +/// + +ะ—ะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ **FastAPI** ัั‚ะฒะพั€ะธั‚ัŒ `server` ัƒ ัั…ะตะผั– OpenAPI ะท URL ะดะปั `root_path`. + +ะะปะต ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฝะฐะดะฐั‚ะธ ั–ะฝัˆั– ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝั– `servers`, ะฝะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ั‚ะพะน ัะฐะผะธะน ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒะทะฐั”ะผะพะดั–ัะฒ ั– ะทั– ัั‚ะตะนะดะถะธะฝะณะพะผ, ั– ะท ะฟั€ะพะดะฐะบัˆะฝะพะผ. + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะดะฐัั‚ะต ะฒะปะฐัะฝะธะน ัะฟะธัะพะบ `servers`, ั– ั” `root_path` (ั‚ะพะผัƒ ั‰ะพ ะฒะฐัˆ API ะทะฝะฐั…ะพะดะธั‚ัŒัั ะทะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ), **FastAPI** ะฒัั‚ะฐะฒะธั‚ัŒ ยซserverยป ะท ั†ะธะผ `root_path` ะฝะฐ ะฟะพั‡ะฐั‚ะพะบ ัะฟะธัะบัƒ. + +ะะฐะฟั€ะธะบะปะฐะด: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +ะ‘ัƒะดะต ะทะณะตะฝะตั€ะพะฒะฐะฝะฐ ัั…ะตะผะฐ OpenAPI ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // ะฉะต ะดะตั‰ะพ ั‚ัƒั‚ + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // ะฉะต ะดะตั‰ะพ ั‚ัƒั‚ + } +} +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ัะตั€ะฒะตั€ ั–ะท ะทะฝะฐั‡ะตะฝะฝัะผ `url` `/api/v1`, ะฒะทัั‚ะธะผ ั–ะท `root_path`. + +/// + +ะ’ ั–ะฝั‚ะตั€ั„ะตะนัั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:9999/api/v1/docs ั†ะต ะฒะธะณะปัะดะฐั‚ะธะผะต ั‚ะฐะบ: + + + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ†ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒะทะฐั”ะผะพะดั–ัั‚ะธะผะต ะท ัะตั€ะฒะตั€ะพะผ, ัะบะธะน ะฒะธ ะพะฑะตั€ะตั‚ะต. + +/// + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะปะฐัั‚ะธะฒั–ัั‚ัŒ `servers` ัƒ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI ั” ะฝะตะพะฑะพะฒสผัะทะบะพะฒะพัŽ. + +ะฏะบั‰ะพ ะฒะธ ะฝะต ะฒะบะฐะถะตั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `servers`, ั– `root_path` ะดะพั€ั–ะฒะฝัŽั” `/`, ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `servers` ัƒ ะทะณะตะฝะตั€ะพะฒะฐะฝั–ะน ัั…ะตะผั– OpenAPI ะฑัƒะดะต ะฟะพะฒะฝั–ัั‚ัŽ ะฟั€ะพะฟัƒั‰ะตะฝะพ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ั‰ะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ ะพะดะฝะพะผัƒ ัะตั€ะฒะตั€ัƒ ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `url` ั€ั–ะฒะฝะธะผ `/`. + +/// + +### ะ’ะธะผะบะฝัƒั‚ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธะน ัะตั€ะฒะตั€ ั–ะท `root_path` { #disable-automatic-server-from-root-path } + +ะฏะบั‰ะพ ะฒะธ ะฝะต ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ **FastAPI** ะดะพะดะฐะฒะฐะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธะน ัะตั€ะฒะตั€, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `root_path`, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `root_path_in_servers=False`: + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +ั– ั‚ะพะดั– ะฒั–ะฝ ะฝะต ะฑัƒะดะต ะฒะบะปัŽั‡ะตะฝะธะน ัƒ ัั…ะตะผัƒ OpenAPI. + +## ะœะพะฝั‚ัƒะฒะฐะฝะฝั ะฟั–ะดะทะฐัั‚ะพััƒะฝะบัƒ { #mounting-a-sub-application } + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะทะผะพะฝั‚ัƒะฒะฐั‚ะธ ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ (ัะบ ะพะฟะธัะฐะฝะพ ะฒ [ะŸั–ะดะทะฐัั‚ะพััƒะฝะบะธ - ะผะพะฝั‚ัƒะฒะฐะฝะฝั](sub-applications.md){.internal-link target=_blank}), ะพะดะฝะพั‡ะฐัะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ ะท `root_path`, ะฒะธ ะผะพะถะตั‚ะต ั€ะพะฑะธั‚ะธ ั†ะต ะทะฒะธั‡ะฐะนะฝะธะผ ั‡ะธะฝะพะผ, ัะบ ั– ะพั‡ั–ะบัƒั”ั‚ะต. + +FastAPI ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ั€ะพะทัƒะผะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต `root_path`, ั‚ะพะถ ัƒัะต ะฟั€ะพัั‚ะพ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต. โœจ diff --git a/docs/uk/docs/advanced/custom-response.md b/docs/uk/docs/advanced/custom-response.md new file mode 100644 index 0000000000..ebd0ec24a1 --- /dev/null +++ b/docs/uk/docs/advanced/custom-response.md @@ -0,0 +1,312 @@ +# ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ - HTML, ัั‚ั€ั–ะผ, ั„ะฐะนะป, ั–ะฝัˆะต { #custom-response-html-stream-file-others } + +ะขะธะฟะพะฒะพ **FastAPI** ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ะฒั–ะดะฟะพะฒั–ะดั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `JSONResponse`. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ ั†ะต, ะฟะพะฒะตั€ะฝัƒะฒัˆะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ `Response`, ัะบ ะฟะพะบะฐะทะฐะฝะพ ะฒ [ะŸะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ](response-directly.md){.internal-link target=_blank}. + +ะะปะต ัะบั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธะน ะนะพะณะพ ะฟั–ะดะบะปะฐั, ัะบ-ะพั‚ `JSONResponse`), ะดะฐะฝั– ะฝะต ะฑัƒะดัƒั‚ัŒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะบะพะฝะฒะตั€ั‚ะพะฒะฐะฝั– (ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะพะณะพะปะพัะธั‚ะต `response_model`), ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะฝะต ะฑัƒะดะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะฐ (ะฝะฐะฟั€ะธะบะปะฐะด, ั–ะท ะฒะบะปัŽั‡ะตะฝะฝัะผ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ยซะผะตะดั–ะฐ-ั‚ะธะฟัƒยป ะฒ HTTP-ะทะฐะณะพะปะพะฒะบัƒ `Content-Type` ัะบ ั‡ะฐัั‚ะธะฝะธ ะทะณะตะฝะตั€ะพะฒะฐะฝะพะณะพ OpenAPI). + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ `Response`, ัะบะธะน ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฑัƒะดัŒ-ัะบะธะน ะฟั–ะดะบะปะฐั `Response`), ัƒ ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั‡ะตั€ะตะท ะฟะฐั€ะฐะผะตั‚ั€ `response_class`. + +ะ’ะผั–ัั‚, ัะบะธะน ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ะท ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฑัƒะดะต ะฟะพะผั–ั‰ะตะฝะธะน ัƒัะตั€ะตะดะธะฝัƒ ั†ัŒะพะณะพ `Response`. + +ะ† ัะบั‰ะพ ั†ะตะน `Response` ะผะฐั” JSON ะผะตะดั–ะฐ-ั‚ะธะฟ (`application/json`), ัะบ ัƒ ะฒะธะฟะฐะดะบัƒ ะท `JSONResponse` ั‚ะฐ `UJSONResponse`, ะดะฐะฝั–, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒัั, ะฑัƒะดัƒั‚ัŒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตั‚ะฒะพั€ะตะฝั– (ั– ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝั–) ะท ัƒั€ะฐั…ัƒะฒะฐะฝะฝัะผ ะฑัƒะดัŒ-ัะบะพะณะพ Pydantic `response_model`, ัะบะธะน ะฒะธ ะพะณะพะปะพัะธะปะธ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั– ะฑะตะท ะผะตะดั–ะฐ-ั‚ะธะฟัƒ, FastAPI ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต, ั‰ะพ ัƒ ะฒะฐัˆะพั— ะฒั–ะดะฟะพะฒั–ะดั– ะฝะต ะฑัƒะดะต ะฒะผั–ัั‚ัƒ, ั‚ะพะถ ั„ะพั€ะผะฐั‚ ะฒั–ะดะฟะพะฒั–ะดั– ะฝะต ะฑัƒะดะต ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะพ ะฒ ะทะณะตะฝะตั€ะพะฒะฐะฝะธั… OpenAPI-ะดะพะบัƒะผะตะฝั‚ะฐั…. + +/// + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `ORJSONResponse` { #use-orjsonresponse } + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒะธ ะผะฐะบัะธะผะฐะปัŒะฝะพ ะพะฟั‚ะธะผั–ะทัƒั”ั‚ะต ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `orjson` ั– ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ัะบ `ORJSONResponse`. + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ะฟะพั‚ั€ั–ะฑะฝะธะน ะบะปะฐั `Response` (ะฟั–ะดะบะปะฐั) ั– ะพะณะพะปะพัั–ั‚ัŒ ะนะพะณะพ ะฒ ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะ”ะปั ะฒะตะปะธะบะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฟะพะฒะตั€ะฝะตะฝะฝั `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฝะฐั‡ะฝะพ ัˆะฒะธะดัˆะต, ะฝั–ะถ ะฟะพะฒะตั€ะฝะตะฝะฝั ัะปะพะฒะฝะธะบะฐ. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ FastAPI ะฟะตั€ะตะฒั–ั€ัั‚ะธะผะต ะบะพะถะตะฝ ะตะปะตะผะตะฝั‚ ัƒัะตั€ะตะดะธะฝั– ั‚ะฐ ะฟะตั€ะตะบะพะฝัƒะฒะฐั‚ะธะผะตั‚ัŒัั, ั‰ะพ ะนะพะณะพ ะผะพะถะฝะฐ ัะตั€ั–ะฐะปั–ะทัƒะฒะฐั‚ะธ ัะบ JSON, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ัะฐะผะธะน [ะกัƒะผั–ัะฝะธะน ะบะพะดัƒะฒะฐะปัŒะฝะธะบ JSON](../tutorial/encoder.md){.internal-link target=_blank}, ะพะฟะธัะฐะฝะธะน ัƒ ะฝะฐะฒั‡ะฐะปัŒะฝะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ. ะกะฐะผะต ั†ะต ะดะพะทะฒะพะปัั” ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะดะพะฒั–ะปัŒะฝั– ะพะฑ'ั”ะบั‚ะธ, ะฝะฐะฟั€ะธะบะปะฐะด ะผะพะดะตะปั– ะฑะฐะทะธ ะดะฐะฝะธั…. + +ะะปะต ัะบั‰ะพ ะฒะธ ะฒะฟะตะฒะฝะตะฝั–, ั‰ะพ ะฒะผั–ัั‚, ัะบะธะน ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั, ัะตั€ั–ะฐะปั–ะทัƒั”ั‚ัŒัั ะฒ JSON, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะบะปะฐััƒ ะฒั–ะดะฟะพะฒั–ะดั– ั‚ะฐ ัƒะฝะธะบะฝัƒั‚ะธ ะดะพะดะฐั‚ะบะพะฒะธั… ะฒะธั‚ั€ะฐั‚ FastAPI ะฝะฐ ะฟั€ะพะฟัƒัะบะฐะฝะฝั ะฒะฐัˆะพะณะพ ะฒะผั–ัั‚ัƒ ั‡ะตั€ะตะท `jsonable_encoder` ะฟะตั€ะตะด ะฟะตั€ะตะดะฐะฒะฐะฝะฝัะผ ะนะพะณะพ ะบะปะฐััƒ ะฒั–ะดะฟะพะฒั–ะดั–. + +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะฐั€ะฐะผะตั‚ั€ `response_class` ั‚ะฐะบะพะถ ะฒะธะทะฝะฐั‡ะฐั‚ะธะผะต ยซะผะตะดั–ะฐ-ั‚ะธะฟยป ะฒั–ะดะฟะพะฒั–ะดั–. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ HTTP-ะทะฐะณะพะปะพะฒะพะบ `Content-Type` ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ะฒ `application/json`. + +ะ† ั†ะต ะฑัƒะดะต ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะพ ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะฒ OpenAPI. + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +`ORJSONResponse` ะดะพัั‚ัƒะฟะฝะธะน ะปะธัˆะต ัƒ FastAPI, ะฝะต ะฒ Starlette. + +/// + +## HTML-ะฒั–ะดะฟะพะฒั–ะดัŒ { #html-response } + +ะฉะพะฑ ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ั–ะท HTML ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท **FastAPI**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `HTMLResponse`. + +- ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `HTMLResponse`. +- ะŸะตั€ะตะดะฐะนั‚ะต `HTMLResponse` ัะบ ะฟะฐั€ะฐะผะตั‚ั€ `response_class` ะฒะฐัˆะพะณะพ ะดะตะบะพั€ะฐั‚ะพั€ะฐ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะฐั€ะฐะผะตั‚ั€ `response_class` ั‚ะฐะบะพะถ ะฒะธะทะฝะฐั‡ะฐั‚ะธะผะต ยซะผะตะดั–ะฐ-ั‚ะธะฟยป ะฒั–ะดะฟะพะฒั–ะดั–. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ HTTP-ะทะฐะณะพะปะพะฒะพะบ `Content-Type` ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ะฒ `text/html`. + +ะ† ั†ะต ะฑัƒะดะต ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะพ ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะฒ OpenAPI. + +/// + +### ะŸะพะฒะตั€ะฝัƒั‚ะธ `Response` { #return-a-response } + +ะฏะบ ะฟะพะบะฐะทะฐะฝะพ ะฒ [ะŸะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ](response-directly.md){.internal-link target=_blank}, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ะฒะฐัˆั–ะน ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ะฝัƒะฒัˆะธ ั—ั—. + +ะขะพะน ัะฐะผะธะน ะฟั€ะธะบะปะฐะด ะฒะธั‰ะต, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐั” `HTMLResponse`, ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +`Response`, ะฟะพะฒะตั€ะฝะตะฝะธะน ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒะฐัˆะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฝะต ะฑัƒะดะต ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะพ ะฒ OpenAPI (ะฝะฐะฟั€ะธะบะปะฐะด, `Content-Type` ะฝะต ะฑัƒะดะต ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะพ) ั– ะฝะต ะฑัƒะดะต ะฒะธะดะฝะพ ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝั–ะน ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +/// + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ—ะฒั–ัะฝะพ, ั„ะฐะบั‚ะธั‡ะฝั– ะทะฐะณะพะปะพะฒะพะบ `Content-Type`, ะบะพะด ัั‚ะฐั‚ัƒััƒ ั‚ะพั‰ะพ ะฟั€ะธะนะดัƒั‚ัŒ ะท ะพะฑ'ั”ะบั‚ะฐ `Response`, ัะบะธะน ะฒะธ ะฟะพะฒะตั€ะฝัƒะปะธ. + +/// + +### ะ—ะฐะดะพะบัƒะผะตะฝั‚ัƒะนั‚ะต ะฒ OpenAPI ั– ะฟะตั€ะตะฟะธัˆั–ั‚ัŒ `Response` { #document-in-openapi-and-override-response } + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ัƒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั—, ะฐะปะต ะฒะพะดะฝะพั‡ะฐั ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ยซะผะตะดั–ะฐ-ั‚ะธะฟยป ะฒ OpenAPI, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response_class` ะ† ะฟะพะฒะตั€ะฝัƒั‚ะธ ะพะฑ'ั”ะบั‚ `Response`. + +ะขะพะดั– `response_class` ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะปะธัˆะต ะดะปั ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฒ OpenAPI, ะฐ ะฒะฐัˆะฐ `Response` ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฐ ัะบ ั”. + +#### ะŸะพะฒะตั€ะฝัƒั‚ะธ `HTMLResponse` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #return-an-htmlresponse-directly } + +ะะฐะฟั€ะธะบะปะฐะด, ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚: + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ั„ัƒะฝะบั†ั–ั `generate_html_response()` ัƒะถะต ะณะตะฝะตั€ัƒั” ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” `Response` ะทะฐะผั–ัั‚ัŒ ะฟะพะฒะตั€ะฝะตะฝะฝั HTML ัะบ `str`. + +ะŸะพะฒะตั€ั‚ะฐัŽั‡ะธ ั€ะตะทัƒะปัŒั‚ะฐั‚ ะฒะธะบะปะธะบัƒ `generate_html_response()`, ะฒะธ ะฒะถะต ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response`, ัะบะฐ ะฟะตั€ะตะฟะธัˆะต ั‚ะธะฟะพะฒัƒ ะฟะพะฒะตะดั–ะฝะบัƒ **FastAPI**. + +ะะปะต ะพัะบั–ะปัŒะบะธ ะฒะธ ั‚ะฐะบะพะถ ะฟะตั€ะตะดะฐะปะธ `HTMLResponse` ัƒ `response_class`, **FastAPI** ะทะฝะฐั‚ะธะผะต, ัะบ ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ั†ะต ะฒ OpenAPI ั‚ะฐ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ัะบ HTML ะท `text/html`: + + + +## ะ”ะพัั‚ัƒะฟะฝั– ะฒั–ะดะฟะพะฒั–ะดั– { #available-responses } + +ะžััŒ ะดะตัะบั– ะท ะดะพัั‚ัƒะฟะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน. + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Response`, ั‰ะพะฑ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ั‰ะพ ะทะฐะฒะณะพะดะฝะพ ั–ะฝัˆะต, ะฐะฑะพ ะฝะฐะฒั–ั‚ัŒ ัั‚ะฒะพั€ะธั‚ะธ ะฒะปะฐัะฝะธะน ะฟั–ะดะบะปะฐั. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.responses import HTMLResponse`. + +**FastAPI** ะฝะฐะดะฐั” ั‚ั– ะถ `starlette.responses` ัะบ `fastapi.responses` ะปะธัˆะต ะดะปั ะฒะฐัˆะพั— ะทั€ัƒั‡ะฝะพัั‚ั– ัะบ ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฝะฐะดั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +/// + +### `Response` { #response } + +ะ“ะพะปะพะฒะฝะธะน ะบะปะฐั `Response`, ะฒั–ะด ัะบะพะณะพ ัƒัะฟะฐะดะบะพะฒัƒัŽั‚ัŒัั ะฒัั– ั–ะฝัˆั– ะฒั–ะดะฟะพะฒั–ะดั–. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +ะ’ั–ะฝ ะฟั€ะธะนะผะฐั” ั‚ะฐะบั– ะฟะฐั€ะฐะผะตั‚ั€ะธ: + +- `content` - `str` ะฐะฑะพ `bytes`. +- `status_code` - `int` - ะบะพะด ัั‚ะฐั‚ัƒััƒ HTTP. +- `headers` - `dict` ัั‚ั€ะพะบ. +- `media_type` - `str`, ั‰ะพ ะทะฐะดะฐั” ะผะตะดั–ะฐ-ั‚ะธะฟ, ะฝะฐะฟั€. `"text/html"`. + +FastAPI (ะฝะฐัะฟั€ะฐะฒะดั– Starlette) ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะดะพะดะฐัั‚ัŒ ะทะฐะณะพะปะพะฒะพะบ Content-Length. ะขะฐะบะพะถ ะฑัƒะดะต ะดะพะดะฐะฝะพ ะทะฐะณะพะปะพะฒะพะบ Content-Type, ะฝะฐ ะพัะฝะพะฒั– `media_type` ะท ะดะพะดะฐะฒะฐะฝะฝัะผ ะฝะฐะฑะพั€ัƒ ัะธะผะฒะพะปั–ะฒ ะดะปั ั‚ะตะบัั‚ะพะฒะธั… ั‚ะธะฟั–ะฒ. + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +ะŸั€ะธะนะผะฐั” ั‚ะตะบัั‚ ะฐะฑะพ ะฑะฐะนั‚ะธ ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” HTML-ะฒั–ะดะฟะพะฒั–ะดัŒ, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต. + +### `PlainTextResponse` { #plaintextresponse } + +ะŸั€ะธะนะผะฐั” ั‚ะตะบัั‚ ะฐะฑะพ ะฑะฐะนั‚ะธ ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ ะทะฒะธั‡ะฐะนะฝะธะผ ั‚ะตะบัั‚ะพะผ. + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +ะŸั€ะธะนะผะฐั” ะดะฐะฝั– ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ, ะทะฐะบะพะดะพะฒะฐะฝัƒ ัะบ `application/json`. + +ะฆะต ั‚ะธะฟะพะฒะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ, ัะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” **FastAPI**, ัะบ ะทะฐะทะฝะฐั‡ะตะฝะพ ะฒะธั‰ะต. + +### `ORJSONResponse` { #orjsonresponse } + +ะจะฒะธะดะบะฐ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐ JSON-ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ `orjson`, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `orjson`, ะฝะฐะฟั€ะธะบะปะฐะด `pip install orjson`. + +/// + +### `UJSONResponse` { #ujsonresponse } + +ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐ JSON-ะฒั–ะดะฟะพะฒั–ะดัŒ ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ `ujson`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `ujson`, ะฝะฐะฟั€ะธะบะปะฐะด `pip install ujson`. + +/// + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +`ujson` ะผะตะฝัˆ ะพะฑะตั€ะตะถะฝะธะน, ะฝั–ะถ ะฒะฑัƒะดะพะฒะฐะฝะฐ ั€ะตะฐะปั–ะทะฐั†ั–ั Python, ัƒ ะฟะพะฒะพะดะถะตะฝะฝั– ะท ะดะตัะบะธะผะธ ะบั€ะฐะนะฝั–ะผะธ ะฒะธะฟะฐะดะบะฐะผะธ. + +/// + +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ™ะผะพะฒั–ั€ะฝะพ, `ORJSONResponse` ะผะพะถะต ะฑัƒั‚ะธ ัˆะฒะธะดัˆะพัŽ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะพัŽ. + +/// + +### `RedirectResponse` { #redirectresponse } + +ะŸะพะฒะตั€ั‚ะฐั” HTTP-ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะฝั. ะขะธะฟะพะฒะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะบะพะด ัั‚ะฐั‚ัƒััƒ 307 (Temporary Redirect). + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ `RedirectResponse` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ: + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +ะะฑะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะนะพะณะพ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ั– `response_class`: + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ URL ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `status_code` ะฑัƒะดะต ั‚ะธะฟะพะฒะธะผ ะดะปั `RedirectResponse`, ั‚ะพะฑั‚ะพ `307`. + +--- + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `status_code` ั€ะฐะทะพะผ ั–ะท ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `response_class`: + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +ะŸั€ะธะนะผะฐั” async-ะณะตะฝะตั€ะฐั‚ะพั€ ะฐะฑะพ ะทะฒะธั‡ะฐะนะฝะธะน ะณะตะฝะตั€ะฐั‚ะพั€/ั–ั‚ะตั€ะฐั‚ะพั€ ั– ั‚ั€ะฐะฝัะปัŽั” ั‚ั–ะปะพ ะฒั–ะดะฟะพะฒั–ะดั– ะฟะพั‚ะพะบะพะฒะพ. + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} + +#### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `StreamingResponse` ะท ะพะฑ'ั”ะบั‚ะฐะผะธ ั‚ะธะฟัƒ file-like { #using-streamingresponse-with-file-like-objects } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” file-like ะพะฑ'ั”ะบั‚ (ะฝะฐะฟั€ะธะบะปะฐะด, ะพะฑ'ั”ะบั‚, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั `open()`), ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะณะตะฝะตั€ะฐั‚ะพั€ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะดะปั ั–ั‚ะตั€ะฐั†ั–ั— ะฟะพ ั†ัŒะพะผัƒ file-like ะพะฑ'ั”ะบั‚ัƒ. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ัะฟะพั‡ะฐั‚ะบัƒ ั‡ะธั‚ะฐั‚ะธ ะฒัะต ะฒ ะฟะฐะผ'ัั‚ัŒ, ั– ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั†ัŽ ะณะตะฝะตั€ะฐั‚ะพั€ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะฒ `StreamingResponse` ั– ะฟะพะฒะตั€ะฝัƒั‚ะธ ั—ั—. + +ะกัŽะดะธ ะฒั…ะพะดะธั‚ัŒ ะฑะฐะณะฐั‚ะพ ะฑั–ะฑะปั–ะพั‚ะตะบ ะดะปั ะฒะทะฐั”ะผะพะดั–ั— ะท ั…ะผะฐั€ะฝะธะผะธ ัั…ะพะฒะธั‰ะฐะผะธ, ะพะฑั€ะพะฑะบะธ ะฒั–ะดะตะพ ั‚ะฐ ั–ะฝัˆั–. + +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} + +1. ะฆะต ะณะตะฝะตั€ะฐั‚ะพั€ะฝะฐ ั„ัƒะฝะบั†ั–ั. ะ’ะพะฝะฐ ั” ยซะณะตะฝะตั€ะฐั‚ะพั€ะฝะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽยป, ะฑะพ ะผั–ัั‚ะธั‚ัŒ ะพะฟะตั€ะฐั‚ะพั€ะธ `yield` ัƒัะตั€ะตะดะธะฝั–. +2. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฑะปะพะบ `with`, ะผะธ ะณะฐั€ะฐะฝั‚ัƒั”ะผะพ, ั‰ะพ file-like ะพะฑ'ั”ะบั‚ ะฑัƒะดะต ะทะฐะบั€ะธั‚ะพ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ั€ะพะฑะพั‚ะธ ะณะตะฝะตั€ะฐั‚ะพั€ะฝะพั— ั„ัƒะฝะบั†ั–ั—. ะขะพะฑั‚ะพ ะฟั–ัะปั ั‚ะพะณะพ, ัะบ ะฒะพะฝะฐ ะทะฐะฒะตั€ัˆะธั‚ัŒ ะฝะฐะดัะธะปะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. +3. ะฆะตะน `yield from` ะฒะบะฐะทัƒั” ั„ัƒะฝะบั†ั–ั— ั–ั‚ะตั€ัƒะฒะฐั‚ะธัั ะฟะพ ะพะฑ'ั”ะบั‚ัƒ ะท ะฝะฐะทะฒะพัŽ `file_like`. ะ ะฟะพั‚ั–ะผ, ะดะปั ะบะพะถะฝะพั— ั–ั‚ะตั€ะพะฒะฐะฝะพั— ั‡ะฐัั‚ะธะฝะธ, ะฟะพะฒะตั€ั‚ะฐั‚ะธ ั†ัŽ ั‡ะฐัั‚ะธะฝัƒ, ะฝั–ะฑะธ ะฒะพะฝะฐ ะฝะฐะดั…ะพะดะธั‚ัŒ ะท ั†ั–ั”ั— ะณะตะฝะตั€ะฐั‚ะพั€ะฝะพั— ั„ัƒะฝะบั†ั–ั— (`iterfile`). + + ะขะพะถ ั†ะต ะณะตะฝะตั€ะฐั‚ะพั€ะฝะฐ ั„ัƒะฝะบั†ั–ั, ัะบะฐ ะฒัะตั€ะตะดะธะฝั– ะฟะตั€ะตะดะฐั” ั€ะพะฑะพั‚ัƒ ยซะณะตะฝะตั€ะฐั†ั–ั—ยป ั‡ะพะผัƒััŒ ั–ะฝัˆะพะผัƒ. + + ะ ะพะฑะปัั‡ะธ ั†ะต ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ, ะผะธ ะผะพะถะตะผะพ ะฟะพะผั–ัั‚ะธั‚ะธ ั—ั— ะฒ ะฑะปะพะบ `with` ั– ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ, ั‰ะพ file-like ะพะฑ'ั”ะบั‚ ะฑัƒะดะต ะทะฐะบั€ะธั‚ะพ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั‚ัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน `open()`, ัะบะธะน ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” `async` ั‚ะฐ `await`, ั‚ะพะผัƒ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ะทะฒะธั‡ะฐะนะฝะพัŽ `def`. + +/// + +### `FileResponse` { #fileresponse } + +ะัะธะฝั…ั€ะพะฝะฝะพ ั‚ั€ะฐะฝัะปัŽั” ั„ะฐะนะป ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ. + +ะŸั€ะธะนะผะฐั” ั–ะฝัˆะธะน ะฝะฐะฑั–ั€ ะฐั€ะณัƒะผะตะฝั‚ั–ะฒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะตะบะทะตะผะฟะปัั€ะฐ, ะฝั–ะถ ั–ะฝัˆั– ั‚ะธะฟะธ ะฒั–ะดะฟะพะฒั–ะดะตะน: + +- `path` - ัˆะปัั… ะดะพ ั„ะฐะนะปัƒ ะดะปั ั‚ั€ะฐะฝัะปัั†ั–ั—. +- `headers` - ะฑัƒะดัŒ-ัะบั– ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ะทะฐะณะพะปะพะฒะบะธ ัะบ ัะปะพะฒะฝะธะบ. +- `media_type` - ัั‚ั€ะพะบะฐ, ั‰ะพ ะทะฐะดะฐั” ะผะตะดั–ะฐ-ั‚ะธะฟ. ะฏะบั‰ะพ ะฝะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ, ะผะตะดั–ะฐ-ั‚ะธะฟ ะฑัƒะดะต ะฒะธะฒะตะดะตะฝะพ ะท ั–ะผะตะฝั– ั„ะฐะนะปัƒ ะฐะฑะพ ัˆะปัั…ัƒ. +- `filename` - ัะบั‰ะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ, ะฑัƒะดะต ะฒะบะปัŽั‡ะตะฝะพ ะดะพ `Content-Disposition` ะฒั–ะดะฟะพะฒั–ะดั–. + +ะ’ั–ะดะฟะพะฒั–ะดั– ะท ั„ะฐะนะปะฐะผะธ ะฒะบะปัŽั‡ะฐั‚ะธะผัƒั‚ัŒ ะฒั–ะดะฟะพะฒั–ะดะฝั– ะทะฐะณะพะปะพะฒะบะธ `Content-Length`, `Last-Modified` ั– `ETag`. + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `response_class`: + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ัˆะปัั… ะดะพ ั„ะฐะนะปัƒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +## ะ’ะปะฐัะฝะธะน ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั– { #custom-response-class } + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฒะปะฐัะฝะธะน ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั–, ัƒัะฟะฐะดะบัƒะฒะฐะฒัˆะธ ะนะพะณะพ ะฒั–ะด `Response`, ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบะฐะถั–ะผะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `orjson`, ะฐะปะต ะท ะดะตัะบะธะผะธ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะผะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ, ัะบั– ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ัƒ ะฒะฑัƒะดะพะฒะฐะฝะพะผัƒ ะบะปะฐัั– `ORJSONResponse`. + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฟะพะฒะตั€ั‚ะฐะฒัั ะฒั–ะดั„ะพั€ะผะฐั‚ะพะฒะฐะฝะธะน ั–ะท ะฒั–ะดัั‚ัƒะฟะฐะผะธ JSON, ั‚ะพะถ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฟั†ั–ัŽ orjson `orjson.OPT_INDENT_2`. + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ `CustomORJSONResponse`. ะ“ะพะปะพะฒะฝะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะทั€ะพะฑะธั‚ะธ, ั†ะต ัั‚ะฒะพั€ะธั‚ะธ ะผะตั‚ะพะด `Response.render(content)`, ัะบะธะน ะฟะพะฒะตั€ั‚ะฐั” ะฒะผั–ัั‚ ัะบ `bytes`: + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +ะขะตะฟะตั€ ะทะฐะผั–ัั‚ัŒ ะฟะพะฒะตั€ะฝะตะฝะฝั: + +```json +{"message": "Hello World"} +``` + +...ั†ั ะฒั–ะดะฟะพะฒั–ะดัŒ ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต: + +```json +{ + "message": "Hello World" +} +``` + +ะ—ะฒั–ัะฝะพ, ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฝะฐะนะดะตั‚ะต ะทะฝะฐั‡ะฝะพ ะบั€ะฐั‰ั– ัะฟะพัะพะฑะธ ัะบะพั€ะธัั‚ะฐั‚ะธัั ั†ะธะผ, ะฝั–ะถ ะฟั€ะพัั‚ะพ ั„ะพั€ะผะฐั‚ัƒะฒะฐะฝะฝั JSON. ๐Ÿ˜‰ + +## ะขะธะฟะพะฒะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ { #default-response-class } + +ะกั‚ะฒะพั€ัŽัŽั‡ะธ ะตะบะทะตะผะฟะปัั€ ะบะปะฐััƒ **FastAPI** ะฐะฑะพ `APIRouter`, ะฒะธ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ, ัะบะธะน ะบะปะฐั ะฒั–ะดะฟะพะฒั–ะดั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. + +ะŸะฐั€ะฐะผะตั‚ั€, ั‰ะพ ั†ะต ะฒะธะทะฝะฐั‡ะฐั”, - `default_response_class`. + +ะฃ ะฟั€ะธะบะปะฐะดั– ะฝะธะถั‡ะต **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต `ORJSONResponse` ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฒ ัƒัั–ั… ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ ะทะฐะผั–ัั‚ัŒ `JSONResponse`. + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะธ ะฒัะต ะพะดะฝะพ ะผะพะถะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ `response_class` ะฒ ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ, ัะบ ั– ั€ะฐะฝั–ัˆะต. + +/// + +## ะ”ะพะดะฐั‚ะบะพะฒะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั { #additional-documentation } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะผะตะดั–ะฐ-ั‚ะธะฟ ั– ะฑะฐะณะฐั‚ะพ ั–ะฝัˆะธั… ะดะตั‚ะฐะปะตะน ะฒ OpenAPI, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `responses`: [ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะฒ OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/uk/docs/advanced/dataclasses.md b/docs/uk/docs/advanced/dataclasses.md new file mode 100644 index 0000000000..a41e6e5890 --- /dev/null +++ b/docs/uk/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั dataclasses { #using-dataclasses } + +FastAPI ะฟะพะฑัƒะดะพะฒะฐะฝะพ ะฟะพะฒะตั€ั… **Pydantic**, ั– ั ะฟะพะบะฐะทัƒะฒะฐะฒ ะฒะฐะผ, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปั– Pydantic ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะทะฐะฟะธั‚ั–ะฒ ั– ะฒั–ะดะฟะพะฒั–ะดะตะน. + +ะะปะต FastAPI ั‚ะฐะบะพะถ ะฟั–ะดั‚ั€ะธะผัƒั” ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `dataclasses` ั‚ะฐะบะธะผ ัะฐะผะธะผ ั‡ะธะฝะพะผ: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +ะฆะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ะทะฐะฒะดัะบะธ **Pydantic**, ะฐะดะถะต ะฒั–ะฝ ะผะฐั” ะฒะฝัƒั‚ั€ั–ัˆะฝัŽ ะฟั–ะดั‚ั€ะธะผะบัƒ `dataclasses`. + +ะขะพะถ ะฝะฐะฒั–ั‚ัŒ ั–ะท ะฝะฐะฒะตะดะตะฝะธะผ ะฒะธั‰ะต ะบะพะดะพะผ, ัะบะธะน ัะฒะฝะพ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Pydantic, FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Pydantic, ั‰ะพะฑ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝั– dataclasses ัƒ ะฒะปะฐัะฝะธะน ะฒะฐั€ั–ะฐะฝั‚ dataclasses Pydantic. + +ะ†, ะทะฒั–ัะฝะพ, ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ั‚ะต ัะฐะผะต: + +* ะฒะฐะปั–ะดะฐั†ั–ั ะดะฐะฝะธั… +* ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั ะดะฐะฝะธั… +* ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะดะฐะฝะธั… ั‚ะพั‰ะพ + +ะฆะต ะฟั€ะฐั†ัŽั” ั‚ะฐะบ ัะฐะผะพ, ัะบ ั–ะท ะผะพะดะตะปัะผะธ Pydantic. ะะฐัะฟั€ะฐะฒะดั– ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ั†ะต ั‚ะฐะบะพะถ ะดะพััะณะฐั”ั‚ัŒัั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Pydantic. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ dataclasses ะฝะต ะผะพะถัƒั‚ัŒ ั€ะพะฑะธั‚ะธ ะฒัะต ั‚ะต, ั‰ะพ ะผะพะถัƒั‚ัŒ ะผะพะดะตะปั– Pydantic. + +ะขะพะถ ะฒะฐะผ ัƒัะต ั‰ะต ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปั– Pydantic. + +ะะปะต ัะบั‰ะพ ัƒ ะฒะฐั ะฒะถะต ั” ั‡ะธะผะฐะปะพ dataclasses, ั†ะต ะทั€ัƒั‡ะฝะธะน ั‚ั€ัŽะบ, ั‰ะพะฑ ะทะฐะดั–ัั‚ะธ ั—ั… ะดะปั ะฒะตะฑ-API ะฝะฐ FastAPI. ๐Ÿค“ + +/// + +## Dataclasses ัƒ `response_model` { #dataclasses-in-response-model } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `dataclasses` ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– `response_model`: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +Dataclass ะฑัƒะดะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตั‚ะฒะพั€ะตะฝะพ ะฝะฐ dataclass Pydantic. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะนะพะณะพ ัั…ะตะผะฐ ะท'ัะฒะธั‚ัŒัั ะฒ ั–ะฝั‚ะตั€ั„ะตะนัั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API: + + + +## Dataclasses ัƒ ะฒะบะปะฐะดะตะฝะธั… ัั‚ั€ัƒะบั‚ัƒั€ะฐั… ะดะฐะฝะธั… { #dataclasses-in-nested-data-structures } + +ะœะพะถะฝะฐ ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ `dataclasses` ะท ั–ะฝัˆะธะผะธ ะฐะฝะพั‚ะฐั†ั–ัะผะธ ั‚ะธะฟั–ะฒ, ั‰ะพะฑ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฒะบะปะฐะดะตะฝั– ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั…. + +ะฃ ะดะตัะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะฐะผ ัƒัะต ะถ ะดะพะฒะตะดะตั‚ัŒัั ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะฐั€ั–ะฐะฝั‚ `dataclasses` ะฒั–ะด Pydantic. ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒะธะฝะธะบะฐัŽั‚ัŒ ะฟะพะผะธะปะบะธ ะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ API. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะทะฐะผั–ะฝะธั‚ะธ ัั‚ะฐะฝะดะฐั€ั‚ะฝั– `dataclasses` ะฝะฐ `pydantic.dataclasses`, ั‰ะพ ั” ะฒะทะฐั”ะผะพะทะฐะผั–ะฝะฝะธะบะพะผ: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. ะœะธ ะฒัะต ั‰ะต ั–ะผะฟะพั€ั‚ัƒั”ะผะพ `field` ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… `dataclasses`. + +2. `pydantic.dataclasses` - ั†ะต ะฒะทะฐั”ะผะพะทะฐะผั–ะฝะฝะธะบ ะดะปั `dataclasses`. + +3. Dataclass `Author` ะผั–ัั‚ะธั‚ัŒ ัะฟะธัะพะบ dataclass `Item`. + +4. Dataclass `Author` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัะบ ะฟะฐั€ะฐะผะตั‚ั€ `response_model`. + +5. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆั– ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟั–ะฒ ั–ะท dataclasses ัะบ ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ. + + ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั†ะต ัะฟะธัะพะบ dataclass `Item`. + +6. ะขัƒั‚ ะผะธ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ัะปะพะฒะฝะธะบ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ `items`, ัะบะธะน ั” ัะฟะธัะบะพะผ dataclass. + + FastAPI ัƒัะต ั‰ะต ะทะดะฐั‚ะฝะธะน ัะตั€ั–ะฐะปั–ะทัƒะฒะฐั‚ะธ ะดะฐะฝั– ะดะพ JSON. + +7. ะขัƒั‚ ัƒ `response_model` ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะฐะฝะพั‚ะฐั†ั–ัŽ ั‚ะธะฟัƒ ัะฟะธัะพะบ dataclass `Author`. + + ะ—ะฝะพะฒัƒ ะถ, ะฒะธ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ `dataclasses` ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะผะธ ะฐะฝะพั‚ะฐั†ั–ัะผะธ ั‚ะธะฟั–ะฒ. + +8. ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั†ั *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะทะฒะธั‡ะฐะนะฝะธะน `def` ะทะฐะผั–ัั‚ัŒ `async def`. + + ะฏะบ ะทะฐะฒะถะดะธ, ัƒ FastAPI ะฒะธ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ `def` ั– `async def` ะทะฐ ะฟะพั‚ั€ะตะฑะธ. + + ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะต ะบะพั€ะพั‚ะบะต ะฝะฐะณะฐะดัƒะฒะฐะฝะฝั, ะบะพะปะธ ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ั€ะพะทะดั–ะป _ยซะŸะพัะฟั–ัˆะฐั”ั‚ะต?ยป_ ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฟั€ะพ [`async` ั‚ะฐ `await`](../async.md#in-a-hurry){.internal-link target=_blank}. + +9. ะฆั *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฝะต ะฟะพะฒะตั€ั‚ะฐั” dataclasses (ั…ะพั‡ะฐ ะผะพะณะปะฐ ะฑ), ะฐ ัะฟะธัะพะบ ัะปะพะฒะฝะธะบั–ะฒ ั–ะท ะฒะฝัƒั‚ั€ั–ัˆะฝั–ะผะธ ะดะฐะฝะธะผะธ. + + FastAPI ะฒะธะบะพั€ะธัั‚ะฐั” ะฟะฐั€ะฐะผะตั‚ั€ `response_model` (ั‰ะพ ะฒะบะปัŽั‡ะฐั” dataclasses), ั‰ะพะฑ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ `dataclasses` ะท ั–ะฝัˆะธะผะธ ะฐะฝะพั‚ะฐั†ั–ัะผะธ ั‚ะธะฟั–ะฒ ัƒ ะฑะฐะณะฐั‚ัŒะพั… ะฟะพั”ะดะฝะฐะฝะฝัั…, ั‰ะพะฑ ั„ะพั€ะผัƒะฒะฐั‚ะธ ัะบะปะฐะดะฝั– ัั‚ั€ัƒะบั‚ัƒั€ะธ ะดะฐะฝะธั…. + +ะŸะตั€ะตะณะปัะฝัŒั‚ะต ะฟั–ะดะบะฐะทะบะธ ั‰ะพะดะพ ะฐะฝะพั‚ะฐั†ั–ะน ัƒ ะบะพะดั– ะฒะธั‰ะต, ั‰ะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ะฑั–ะปัŒัˆะต ะดะตั‚ะฐะปะตะน. + +## ะ”ั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต { #learn-more } + +ะœะพะถะฝะฐ ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ `dataclasses` ะท ั–ะฝัˆะธะผะธ ะผะพะดะตะปัะผะธ Pydantic, ะฝะฐัะปั–ะดัƒะฒะฐั‚ะธ ั—ั…, ะฒะบะปัŽั‡ะฐั‚ะธ ัƒ ะฒะปะฐัะฝั– ะผะพะดะตะปั– ั‚ะพั‰ะพ. + +ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Pydantic ะฟั€ะพ dataclasses. + +## ะ’ะตั€ัั–ั { #version } + +ะ”ะพัั‚ัƒะฟะฝะพ ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท ะฒะตั€ัั–ั— FastAPI `0.67.0`. ๐Ÿ”– diff --git a/docs/uk/docs/advanced/events.md b/docs/uk/docs/advanced/events.md new file mode 100644 index 0000000000..7c05ee4a4e --- /dev/null +++ b/docs/uk/docs/advanced/events.md @@ -0,0 +1,165 @@ +# ะŸะพะดั–ั— ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั { #lifespan-events } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะปะพะณั–ะบัƒ (ะบะพะด), ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะทะฐะฟัƒัั‚ะธั‚ัŒัั. ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ั†ะตะน ะบะพะด ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะพะดะธะฝ ั€ะฐะท, ะฟะตั€ะตะด ั‚ะธะผ ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะฟะพั‡ะฝะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะทะฐะฟะธั‚ะธ. + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะปะพะณั–ะบัƒ (ะบะพะด), ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ ะฟั–ะด ั‡ะฐั ะฒะธะผะบะฝะตะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ. ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะบะพะด ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะพะดะธะฝ ั€ะฐะท, ะฟั–ัะปั ะพะฑั€ะพะฑะบะธ ะผะพะถะปะธะฒะพ ะฑะฐะณะฐั‚ัŒะพั… ะทะฐะฟะธั‚ั–ะฒ. + +ะžัะบั–ะปัŒะบะธ ั†ะตะน ะบะพะด ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะฟะพั‡ะฝะต ะฟั€ะธะนะผะฐั‚ะธ ะทะฐะฟะธั‚ะธ, ั– ะพะดั€ะฐะทัƒ ะฟั–ัะปั ั‚ะพะณะพ, ัะบ ะฒั–ะฝ ะทะฐะฒะตั€ัˆะธั‚ัŒ ั—ั… ะพะฑั€ะพะฑะบัƒ, ะฒั–ะฝ ะพั…ะพะฟะปัŽั” ะฒััŽ ั‚ั€ะธะฒะฐะปั–ัั‚ัŒ ะถะธั‚ั‚ั ะทะฐัั‚ะพััƒะฝะบัƒ (ัะปะพะฒะพ ยซlifespanยป ะฑัƒะดะต ะฒะฐะถะปะธะฒะธะผ ะทะฐ ะผะธั‚ัŒ ๐Ÿ˜‰). + +ะฆะต ะดัƒะถะต ะบะพั€ะธัะฝะพ ะดะปั ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั€ะตััƒั€ัั–ะฒ, ัะบั– ะฟะพั‚ั€ั–ะฑะฝั– ะดะปั ะฒััŒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ัะบั– ัะฟั–ะปัŒะฝั– ะผั–ะถ ะทะฐะฟะธั‚ะฐะผะธ, ั‚ะฐ/ะฐะฑะพ ัะบั– ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพั‚ั–ะผ ะฟั€ะธะฑั€ะฐั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด, ะฟัƒะป ะทโ€™ั”ะดะฝะฐะฝัŒ ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั… ะฐะฑะพ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ัะฟั–ะปัŒะฝะพั— ะผะพะดะตะปั– ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั. + +## ะ’ะธะฟะฐะดะพะบ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั { #use-case } + +ะŸะพั‡ะฝะตะผะพ ะท ะฟั€ะธะบะปะฐะดัƒ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั, ะฐ ะฟะพั‚ั–ะผ ะฟะพะดะธะฒะธะผะพััŒ, ัะบ ั†ะต ะฒะธั€ั–ัˆะธั‚ะธ. + +ะฃัะฒั–ะผะพ, ั‰ะพ ัƒ ะฒะฐั ั” ะผะพะดะตะปั– ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั, ัะบะธะผะธ ะฒะธ ั…ะพั‡ะตั‚ะต ะพะฑั€ะพะฑะปัั‚ะธ ะทะฐะฟะธั‚ะธ. ๐Ÿค– + +ะขั– ัะฐะผั– ะผะพะดะตะปั– ัะฟั–ะปัŒะฝั– ะผั–ะถ ะทะฐะฟะธั‚ะฐะผะธ, ั‚ะพะฑั‚ะพ ั†ะต ะฝะต ะพะบั€ะตะผะฐ ะผะพะดะตะปัŒ ะฝะฐ ะทะฐะฟะธั‚ ั‡ะธ ะฝะฐ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะฃัะฒั–ะผะพ, ั‰ะพ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะผะพะดะตะปั– ะผะพะถะต ะทะฐะนะผะฐั‚ะธ ั‡ะธะผะฐะปะพ ั‡ะฐััƒ, ะฑะพ ั‚ั€ะตะฑะฐ ั‡ะธั‚ะฐั‚ะธ ะฑะฐะณะฐั‚ะพ ะดะฐะฝะธั… ะท ะดะธัะบะฐ. ะขะพะถ ะฒะธ ะฝะต ั…ะพั‡ะตั‚ะต ั€ะพะฑะธั‚ะธ ั†ะต ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ. + +ะ’ะธ ะผะพะณะปะธ ะฑ ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ั—ั— ะฝะฐ ะฒะตั€ั…ะฝัŒะพะผัƒ ั€ั–ะฒะฝั– ะผะพะดัƒะปั/ั„ะฐะนะปัƒ, ะฐะปะต ั†ะต ะพะทะฝะฐั‡ะฐะปะพ ะฑ, ั‰ะพ ะผะพะดะตะปัŒ ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ัŒัั ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะฟั€ะพัั‚ะพ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะฟั€ะพัั‚ะธะน ะฐะฒั‚ะพะผะฐั‚ะธะทะพะฒะฐะฝะธะน ั‚ะตัั‚ - ั‚ะพะดั– ั‚ะตัั‚ ะฑัƒะดะต ะฟะพะฒั–ะปัŒะฝะธะผ, ะฑะพ ะนะพะผัƒ ะดะพะฒะตะดะตั‚ัŒัั ั‡ะตะบะฐั‚ะธ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะผะพะดะตะปั– ะฟะตั€ะตะด ะฒะธะบะพะฝะฐะฝะฝัะผ ะฝะตะทะฐะปะตะถะฝะพั— ั‡ะฐัั‚ะธะฝะธ ะบะพะดัƒ. + +ะžััŒ ั†ะต ะผะธ ะน ะฒะธั€ั–ัˆะธะผะพ: ะทะฐะฒะฐะฝั‚ะฐะถะธะผะพ ะผะพะดะตะปัŒ ะฟะตั€ะตะด ะพะฑั€ะพะฑะบะพัŽ ะทะฐะฟะธั‚ั–ะฒ, ะฐะปะต ะปะธัˆะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะฟะพั‡ะฝะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะทะฐะฟะธั‚ะธ, ะฐ ะฝะต ะฟั–ะด ั‡ะฐั ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะบะพะดัƒ. + +## ะขั€ะธะฒะฐะปั–ัั‚ัŒ ะถะธั‚ั‚ั { #lifespan } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ั†ัŽ ะปะพะณั–ะบัƒ ะทะฐะฟัƒัะบัƒ ั– ะฒะธะผะบะฝะตะฝะฝั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `lifespan` ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI` ั‚ะฐ ยซะผะตะฝะตะดะถะตั€ะฐ ะบะพะฝั‚ะตะบัั‚ัƒยป (ะทะฐั€ะฐะท ะฟะพะบะฐะถัƒ, ั‰ะพ ั†ะต). + +ะŸะพั‡ะฝะตะผะพ ะท ะฟั€ะธะบะปะฐะดัƒ, ะฐ ะฟะพั‚ั–ะผ ั€ะพะทะฑะตั€ะตะผะพ ะดะตั‚ะฐะปัŒะฝะพ. + +ะœะธ ัั‚ะฒะพั€ัŽั”ะผะพ ะฐัะธะฝั…ั€ะพะฝะฝัƒ ั„ัƒะฝะบั†ั–ัŽ `lifespan()` ะท `yield` ั‚ะฐะบ: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +ะขัƒั‚ ะผะธ ั–ะผั–ั‚ัƒั”ะผะพ ะดะพั€ะพะณัƒ ะพะฟะตั€ะฐั†ั–ัŽ ะทะฐะฟัƒัะบัƒ ั–ะท ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝัะผ ะผะพะดะตะปั–, ะฟะพะผั–ั‰ะฐัŽั‡ะธ (ั„ะฐะปัŒัˆะธะฒัƒ) ั„ัƒะฝะบั†ั–ัŽ ะผะพะดะตะปั– ัƒ ัะปะพะฒะฝะธะบ ะท ะผะพะดะตะปัะผะธ ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั ะฟะตั€ะตะด `yield`. ะฆะตะน ะบะพะด ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะฟะพั‡ะฝะต ะฟั€ะธะนะผะฐั‚ะธ ะทะฐะฟะธั‚ะธ, ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ. + +ะ ะพะดั€ะฐะทัƒ ะฟั–ัะปั `yield` ะผะธ ั€ะพะทะฒะฐะฝั‚ะฐะถัƒั”ะผะพ ะผะพะดะตะปัŒ. ะฆะตะน ะบะพะด ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะฟั–ัะปั ั‚ะพะณะพ, ัะบ ะทะฐัั‚ะพััƒะฝะพะบ ะทะฐะฒะตั€ัˆะธั‚ัŒ ะพะฑั€ะพะฑะบัƒ ะทะฐะฟะธั‚ั–ะฒ, ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะฒะธะผะบะฝะตะฝะฝัะผ. ะฆะต, ะฝะฐะฟั€ะธะบะปะฐะด, ะผะพะถะต ะทะฒั–ะปัŒะฝะธั‚ะธ ั€ะตััƒั€ัะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ ะฟะฐะผโ€™ัั‚ั– ะฐะฑะพ GPU. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะพะดั–ั `shutdown` ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั, ะบะพะปะธ ะฒะธ ะทัƒะฟะธะฝัั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ. + +ะœะพะถะปะธะฒะพ, ะฒะฐะผ ั‚ั€ะตะฑะฐ ะทะฐะฟัƒัั‚ะธั‚ะธ ะฝะพะฒัƒ ะฒะตั€ัั–ัŽ, ะฐะฑะพ ะฒะธ ะฟั€ะพัั‚ะพ ะฒั‚ะพะผะธะปะธัั ั—ั— ะทะฐะฟัƒัะบะฐั‚ะธ. ๐Ÿคท + +/// + +### ะคัƒะฝะบั†ั–ั ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั { #lifespan-function } + +ะŸะตั€ัˆะต, ะฝะฐ ั‰ะพ ัะปั–ะด ะทะฒะตั€ะฝัƒั‚ะธ ัƒะฒะฐะณัƒ: ะผะธ ะฒะธะทะฝะฐั‡ะฐั”ะผะพ ะฐัะธะฝั…ั€ะพะฝะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะท `yield`. ะฆะต ะดัƒะถะต ัั…ะพะถะต ะฝะฐ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`. + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +ะŸะตั€ัˆะฐ ั‡ะฐัั‚ะธะฝะฐ ั„ัƒะฝะบั†ั–ั— ะดะพ `yield` ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะฐ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะ ั‡ะฐัั‚ะธะฝะฐ ะฟั–ัะปั `yield` ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะฐ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั ั€ะพะฑะพั‚ะธ ะทะฐัั‚ะพััƒะฝะบัƒ. + +### ะัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ { #async-context-manager } + +ะฏะบั‰ะพ ะฟั€ะธะดะธะฒะธั‚ะธัั, ั„ัƒะฝะบั†ั–ั ะทะฐะดะตะบะพั€ะพะฒะฐะฝะฐ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `@asynccontextmanager`. + +ะฆะต ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั„ัƒะฝะบั†ั–ัŽ ะฝะฐ ั‚ะฐะบ ะทะฒะฐะฝะธะน ยซะฐัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒยป. + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +ะœะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ ะฒ Python - ั†ะต ั‚ะต, ั‰ะพ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒ ะพะฟะตั€ะฐั‚ะพั€ั– `with`, ะฝะฐะฟั€ะธะบะปะฐะด, `open()` ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะบ ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ: + +```Python +with open("file.txt") as file: + file.read() +``` + +ะฃ ะฝะพะฒั–ัˆะธั… ะฒะตั€ัั–ัั… Python ั‚ะฐะบะพะถ ั” ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ. ะ™ะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะท `async with`: + +```Python +async with lifespan(app): + await do_stuff() +``` + +ะšะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ ะฐะฑะพ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ, ัะบ ะฒะธั‰ะต, ะฟะตั€ะตะด ะฒั…ะพะดะพะผ ัƒ ะฑะปะพะบ `with` ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะบะพะด ะฟะตั€ะตะด `yield`, ะฐ ะฟั–ัะปั ะฒะธั…ะพะดัƒ ะท ะฑะปะพะบัƒ `with` ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะบะพะด ะฟั–ัะปั `yield`. + +ะฃ ะฝะฐัˆะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะบะพะดัƒ ะฒะธั‰ะต ะผะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะนะพะณะพ ะฝะฐะฟั€ัะผัƒ, ะฐ ะฟะตั€ะตะดะฐั”ะผะพ ะนะพะณะพ ะดะพ FastAPI, ั‰ะพะฑ ะฒั–ะฝ ะนะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะฒ. + +ะŸะฐั€ะฐะผะตั‚ั€ `lifespan` ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI` ะฟั€ะธะนะผะฐั” ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ, ั‚ะพะถ ะผะธ ะผะพะถะตะผะพ ะฟะตั€ะตะดะฐั‚ะธ ะนะพะผัƒ ะฝะฐัˆ ะฝะพะฒะธะน ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ `lifespan`. + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝั– ะฟะพะดั–ั— (ะทะฐัั‚ะฐั€ั–ะปะพ) { #alternative-events-deprecated } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะ ะตะบะพะผะตะฝะดะพะฒะฐะฝะธะน ัะฟะพัั–ะฑ ะพะฑั€ะพะฑะปัั‚ะธ ะทะฐะฟัƒัะบ ั– ะฒะธะผะบะฝะตะฝะฝั - ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `lifespan` ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต. ะฏะบั‰ะพ ะฒะธ ะฝะฐะดะฐั”ั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `lifespan`, ะพะฑั€ะพะฑะฝะธะบะธ ะฟะพะดั–ะน `startup` ั– `shutdown` ะฑั–ะปัŒัˆะต ะฝะต ะฑัƒะดัƒั‚ัŒ ะฒะธะบะปะธะบะฐะฝั–. ะะฑะพ ะฒัะต ั‡ะตั€ะตะท `lifespan`, ะฐะฑะพ ะฒัะต ั‡ะตั€ะตะท ะฟะพะดั–ั— - ะฝะต ะพะฑะธะดะฒะฐ ะพะดะฝะพั‡ะฐัะฝะพ. + +ะœะพะถะตั‚ะต, ะนะผะพะฒั–ั€ะฝะพ, ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ัŽ ั‡ะฐัั‚ะธะฝัƒ. + +/// + +ะ„ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะธะน ัะฟะพัั–ะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะปะพะณั–ะบัƒ, ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ ั– ะฟั–ะด ั‡ะฐั ะฒะธะผะบะฝะตะฝะฝั. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะพะฑั€ะพะฑะฝะธะบะธ ะฟะพะดั–ะน (ั„ัƒะฝะบั†ั–ั—), ัะบั– ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝะฐั‚ะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ ะฐะฑะพ ะบะพะปะธ ะทะฐัั‚ะพััƒะฝะพะบ ะฒะธะผะธะบะฐั”ั‚ัŒัั. + +ะฆั– ั„ัƒะฝะบั†ั–ั— ะผะพะถะฝะฐ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ัะบ ะท `async def`, ั‚ะฐะบ ั– ะทะฒะธั‡ะฐะนะฝะธะผ `def`. + +### ะŸะพะดั–ั `startup` { #startup-event } + +ะฉะพะฑ ะดะพะดะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ, ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ, ะพะณะพะปะพัั–ั‚ัŒ ั—ั— ะท ะฟะพะดั–ั”ัŽ `"startup"`: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั„ัƒะฝะบั†ั–ั-ะพะฑั€ะพะฑะฝะธะบ ะฟะพะดั–ั— `startup` ั–ะฝั–ั†ั–ะฐะปั–ะทัƒั” ยซะฑะฐะทัƒ ะดะฐะฝะธั…ยป ะฟั€ะตะดะผะตั‚ั–ะฒ (ั†ะต ะปะธัˆะต `dict`) ะดะตัะบะธะผะธ ะทะฝะฐั‡ะตะฝะฝัะผะธ. + +ะ’ะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะฑั–ะปัŒัˆะต ะฝั–ะถ ะพะดะธะฝ ะพะฑั€ะพะฑะฝะธะบ ะฟะพะดั–ั—. + +ะ† ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฝะต ะฟะพั‡ะฝะต ะฟั€ะธะนะผะฐั‚ะธ ะทะฐะฟะธั‚ะธ, ะดะพะบะธ ะฒัั– ะพะฑั€ะพะฑะฝะธะบะธ ะฟะพะดั–ั— `startup` ะฝะต ะทะฐะฒะตั€ัˆะฐั‚ัŒัั. + +### ะŸะพะดั–ั `shutdown` { #shutdown-event } + +ะฉะพะฑ ะดะพะดะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ, ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ, ะบะพะปะธ ะทะฐัั‚ะพััƒะฝะพะบ ะฒะธะผะธะบะฐั”ั‚ัŒัั, ะพะณะพะปะพัั–ั‚ัŒ ั—ั— ะท ะฟะพะดั–ั”ัŽ `"shutdown"`: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +ะขัƒั‚ ั„ัƒะฝะบั†ั–ั-ะพะฑั€ะพะฑะฝะธะบ ะฟะพะดั–ั— `shutdown` ะทะฐะฟะธัˆะต ั‚ะตะบัั‚ะพะฒะธะน ั€ัะดะพะบ `"Application shutdown"` ัƒ ั„ะฐะนะป `log.txt`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฃ ั„ัƒะฝะบั†ั–ั— `open()` ะฟะฐั€ะฐะผะตั‚ั€ `mode="a"` ะพะทะฝะฐั‡ะฐั” ยซappendยป, ั‚ะพะถ ั€ัะดะพะบ ะฑัƒะดะต ะดะพะดะฐะฝะพ ะฟั–ัะปั ะฒััŒะพะณะพ, ั‰ะพ ั” ัƒ ั„ะฐะนะปั–, ะฑะตะท ะฟะตั€ะตะทะฐะฟะธััƒ ะฟะพะฟะตั€ะตะดะฝัŒะพะณะพ ะฒะผั–ัั‚ัƒ. + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐัƒะฒะฐะถั‚ะต, ั‰ะพ ะฒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒ Python-ั„ัƒะฝะบั†ั–ัŽ `open()`, ัะบะฐ ะฟั€ะฐั†ัŽั” ะท ั„ะฐะนะปะพะผ. + +ะขะพะฑั‚ะพ ะฒะพะฝะฐ ะฒะบะปัŽั‡ะฐั” I/O (input/output), ะดะต ะฟะพั‚ั€ั–ะฑะฝะพ ยซั‡ะตะบะฐั‚ะธยป, ะฟะพะบะธ ะดะฐะฝั– ะฑัƒะดะต ะทะฐะฟะธัะฐะฝะพ ะฝะฐ ะดะธัะบ. + +ะะปะต `open()` ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `async` ั– `await`. + +ะขะพะผัƒ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ั„ัƒะฝะบั†ั–ัŽ-ะพะฑั€ะพะฑะฝะธะบ ะฟะพะดั–ั— ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะผ `def`, ะฐ ะฝะต `async def`. + +/// + +### ะ ะฐะทะพะผ `startup` ั– `shutdown` { #startup-and-shutdown-together } + +ะ’ะตะปะธะบะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ ะปะพะณั–ะบะฐ ะดะปั ะฒะฐัˆะพะณะพ ะทะฐะฟัƒัะบัƒ ั– ะฒะธะผะบะฝะตะฝะฝั ะฟะพะฒโ€™ัะทะฐะฝะฐ: ะฒะธ ะผะพะถะตั‚ะต ั…ะพั‚ั–ั‚ะธ ั‰ะพััŒ ะทะฐะฟัƒัั‚ะธั‚ะธ, ะฐ ะฟะพั‚ั–ะผ ะทะฐะฒะตั€ัˆะธั‚ะธ, ะพั‚ั€ะธะผะฐั‚ะธ ั€ะตััƒั€ั, ะฐ ะฟะพั‚ั–ะผ ะทะฒั–ะปัŒะฝะธั‚ะธ ะนะพะณะพ ั‚ะพั‰ะพ. + +ะ ะพะฑะธั‚ะธ ั†ะต ะฒ ะพะบั€ะตะผะธั… ั„ัƒะฝะบั†ั–ัั…, ัะบั– ะฝะต ะดั–ะปัั‚ัŒัั ะปะพะณั–ะบะพัŽ ั‡ะธ ะทะผั–ะฝะฝะธะผะธ, ัะบะปะฐะดะฝั–ัˆะต - ะดะพะฒะตะดะตั‚ัŒัั ะทะฑะตั€ั–ะณะฐั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ัƒ ะณะปะพะฑะฐะปัŒะฝะธั… ะทะผั–ะฝะฝะธั… ะฐะฑะพ ะฒะดะฐะฒะฐั‚ะธัั ะดะพ ะฟะพะดั–ะฑะฝะธั… ั‚ั€ัŽะบั–ะฒ. + +ะขะพะผัƒ ะทะฐั€ะฐะท ั€ะตะบะพะผะตะฝะดัƒั”ั‚ัŒัั ะฝะฐั‚ะพะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `lifespan`, ัะบ ะฟะพััะฝะตะฝะพ ะฒะธั‰ะต. + +## ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #technical-details } + +ะะตะฒะตะปะธะบะฐ ั‚ะตั…ะฝั–ั‡ะฝะฐ ะดะตั‚ะฐะปัŒ ะดะปั ะดะพะฟะธั‚ะปะธะฒะธั… ะฝะตั€ะดั–ะฒ. ๐Ÿค“ + +ะŸั–ะด ะบะฐะฟะพั‚ะพะผ, ัƒ ั‚ะตั…ะฝั–ั‡ะฝั–ะน ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— ASGI, ั†ะต ั‡ะฐัั‚ะธะฝะฐ ะŸั€ะพั‚ะพะบะพะปัƒ ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั, ั– ั‚ะฐะผ ะฒะธะทะฝะฐั‡ะตะฝั– ะฟะพะดั–ั— `startup` ั– `shutdown`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ’ะธ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฑั–ะปัŒัˆะต ะฟั€ะพ ะพะฑั€ะพะฑะฝะธะบะธ `lifespan` ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Starlette ะฟั€ะพ Lifespan. + +ะ—ะพะบั€ะตะผะฐ, ัะบ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะทั– ัั‚ะฐะฝะพะผ ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั, ัะบะธะน ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒ ั–ะฝัˆะธั… ะดั–ะปัะฝะบะฐั… ะฒะฐัˆะพะณะพ ะบะพะดัƒ. + +/// + +## ะŸั–ะดะทะฐัั‚ะพััƒะฝะบะธ { #sub-applications } + +๐Ÿšจ ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ั†ั– ะฟะพะดั–ั— ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั (startup ั– shutdown) ะฒะธะบะพะฝัƒัŽั‚ัŒัั ะปะธัˆะต ะดะปั ะณะพะปะพะฒะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฐ ะฝะต ะดะปั [ะŸั–ะดะทะฐัั‚ะพััƒะฝะบะธ - ะผะพะฝั‚ัƒะฒะฐะฝะฝั](sub-applications.md){.internal-link target=_blank}. diff --git a/docs/uk/docs/advanced/generate-clients.md b/docs/uk/docs/advanced/generate-clients.md new file mode 100644 index 0000000000..66e9193ac3 --- /dev/null +++ b/docs/uk/docs/advanced/generate-clients.md @@ -0,0 +1,208 @@ +# ะ“ะตะฝะตั€ะฐั†ั–ั SDK { #generating-sdks } + +ะžัะบั–ะปัŒะบะธ **FastAPI** ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— **OpenAPI**, ะนะพะณะพ API ะผะพะถะฝะฐ ะพะฟะธัะฐั‚ะธ ัƒ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพะผัƒ ั„ะพั€ะผะฐั‚ั–, ัะบะธะน ั€ะพะทัƒะผั–ัŽั‚ัŒ ะฑะฐะณะฐั‚ะพ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. + +ะฆะต ัะฟั€ะพั‰ัƒั” ัั‚ะฒะพั€ะตะฝะฝั ะฐะบั‚ัƒะฐะปัŒะฝะพั— **ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—**, ะบะปั–ั”ะฝั‚ััŒะบะธั… ะฑั–ะฑะปั–ะพั‚ะตะบ (**SDKs**) ะฑะฐะณะฐั‚ัŒะผะฐ ะผะพะฒะฐะผะธ, ะฐ ั‚ะฐะบะพะถ **ั‚ะตัั‚ัƒะฒะฐะฝะฝั** ั‡ะธ **ะฐะฒั‚ะพะผะฐั‚ะธะทะพะฒะฐะฝะธั… ั€ะพะฑะพั‡ะธั… ะฟั€ะพั†ะตัั–ะฒ**, ั‰ะพ ะทะฐะปะธัˆะฐัŽั‚ัŒัั ัะธะฝั…ั€ะพะฝั–ะทะพะฒะฐะฝะธะผะธ ะท ะฒะฐัˆะธะผ ะบะพะดะพะผ. + +ะฃ ั†ัŒะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ ะฒะธ ะดั–ะทะฝะฐั”ั‚ะตัั, ัะบ ะทะณะตะฝะตั€ัƒะฒะฐั‚ะธ **TypeScript SDK** ะดะปั ะฒะฐัˆะพะณะพ ะฑะตะบะตะฝะดะฐ ะฝะฐ FastAPI. + +## ะ“ะตะฝะตั€ะฐั‚ะพั€ะธ SDK ะท ะฒั–ะดะบั€ะธั‚ะธะผ ะบะพะดะพะผ { #open-source-sdk-generators } + +ะฃะฝั–ะฒะตั€ัะฐะปัŒะฝะธะผ ะฒะฐั€ั–ะฐะฝั‚ะพะผ ั” OpenAPI Generator, ัะบะธะน ะฟั–ะดั‚ั€ะธะผัƒั” **ะฑะฐะณะฐั‚ะพ ะผะพะฒ ะฟั€ะพะณั€ะฐะผัƒะฒะฐะฝะฝั** ั‚ะฐ ะผะพะถะต ะณะตะฝะตั€ัƒะฒะฐั‚ะธ SDK ะท ะฒะฐัˆะพั— ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI. + +ะ”ะปั **ะบะปั–ั”ะฝั‚ั–ะฒ TypeScript** Hey API โ€” ัะฟะตั†ั–ะฐะปั–ะทะพะฒะฐะฝะต ั€ั–ัˆะตะฝะฝั, ั‰ะพ ะฝะฐะดะฐั” ะพะฟั‚ะธะผั–ะทะพะฒะฐะฝะธะน ะดะพัะฒั–ะด ะดะปั ะตะบะพัะธัั‚ะตะผะธ TypeScript. + +ะ‘ั–ะปัŒัˆะต ะณะตะฝะตั€ะฐั‚ะพั€ั–ะฒ SDK ะฒะธ ะผะพะถะตั‚ะต ะทะฝะฐะนั‚ะธ ะฝะฐ OpenAPI.Tools. + +/// tip | ะŸะพั€ะฐะดะฐ + +FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะณะตะฝะตั€ัƒั” ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— **OpenAPI 3.1**, ั‚ะพะถ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ัะบะธะน ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต, ะผะฐั” ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ั†ัŽ ะฒะตั€ัั–ัŽ. + +/// + +## ะ“ะตะฝะตั€ะฐั‚ะพั€ะธ SDK ะฒั–ะด ัะฟะพะฝัะพั€ั–ะฒ FastAPI { #sdk-generators-from-fastapi-sponsors } + +ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฟั€ะตะดัั‚ะฐะฒะปะตะฝะพ ั€ั–ัˆะตะฝะฝั ะฒั–ะด ะบะพะผะฟะฐะฝั–ะน, ั‰ะพ ัะฟะพะฝัะพั€ัƒัŽั‚ัŒ FastAPI: ะฒะพะฝะธ ะผะฐัŽั‚ัŒ **ะฒะตะฝั‡ัƒั€ะฝัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ** ั‚ะฐ **ะบะพั€ะฟะพั€ะฐั‚ะธะฒะฝัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ**. ะฆั– ะฟั€ะพะดัƒะบั‚ะธ ะฝะฐะดะฐัŽั‚ัŒ **ะดะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั–** ั‚ะฐ **ั–ะฝั‚ะตะณั€ะฐั†ั–ั—** ะฟะพะฒะตั€ั… ะฒะธัะพะบะพัะบั–ัะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะธั… SDK. + +ะ—ะฐะฒะดัะบะธ โœจ [**ัะฟะพะฝัะพั€ัั‚ะฒัƒ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ ั†ั– ะบะพะผะฟะฐะฝั–ั— ะดะพะฟะพะผะฐะณะฐัŽั‚ัŒ ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ ั„ั€ะตะนะผะฒะพั€ะบ ั‚ะฐ ะนะพะณะพ **ะตะบะพัะธัั‚ะตะผัƒ** ะทะดะพั€ะพะฒะธะผะธ ั‚ะฐ **ัั‚ะฐะปะธะผะธ**. + +ะ‡ั…ะฝั ะฟั–ะดั‚ั€ะธะผะบะฐ ั‚ะฐะบะพะถ ะดะตะผะพะฝัั‚ั€ัƒั” ัะธะปัŒะฝัƒ ะฒั–ะดะดะฐะฝั–ัั‚ัŒ **ัะฟั–ะปัŒะฝะพั‚ั–** FastAPI (ะฒะฐะผ), ะฟะพะบะฐะทัƒัŽั‡ะธ, ั‰ะพ ั—ะผ ะฒะฐะถะปะธะฒะพ ะฝะต ะปะธัˆะต ะฝะฐะดะฐะฒะฐั‚ะธ **ะฒั–ะดะผั–ะฝะฝะธะน ัะตั€ะฒั–ั**, ะฐ ะน ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ **ะผั–ั†ะฝะธะน ั– ะฟั€ะพั†ะฒั–ั‚ะฐัŽั‡ะธะน ั„ั€ะตะนะผะฒะพั€ะบ**, FastAPI. ๐Ÿ™‡ + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ: + +* Speakeasy +* Stainless +* liblab + +ะ”ะตัะบั– ะท ั†ะธั… ั€ั–ัˆะตะฝัŒ ั‚ะฐะบะพะถ ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะท ะฒั–ะดะบั€ะธั‚ะธะผ ะบะพะดะพะผ ะฐะฑะพ ะผะฐั‚ะธ ะฑะตะทะบะพัˆั‚ะพะฒะฝั– ั‚ะฐั€ะธั„ะธ, ั‚ะพะถ ะฒะธ ะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ั—ั… ะฑะตะท ั„ั–ะฝะฐะฝัะพะฒะธั… ะทะพะฑะพะฒ'ัะทะฐะฝัŒ. ะ†ะฝัˆั– ะบะพะผะตั€ั†ั–ะนะฝั– ะณะตะฝะตั€ะฐั‚ะพั€ะธ SDK ั‚ะฐะบะพะถ ะดะพัั‚ัƒะฟะฝั– ะน ั—ั… ะผะพะถะฝะฐ ะทะฝะฐะนั‚ะธ ะพะฝะปะฐะนะฝ. ๐Ÿค“ + +## ะกั‚ะฒะพั€ะธั‚ะธ TypeScript SDK { #create-a-typescript-sdk } + +ะŸะพั‡ะฝั–ะผะพ ะท ะฟั€ะพัั‚ะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒะธะทะฝะฐั‡ะฐัŽั‚ัŒ ะผะพะดะตะปั–, ัะบั– ะฒะพะฝะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ะบะพั€ะธัะฝะพะณะพ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะทะฐะฟะธั‚ัƒ ั‚ะฐ ะบะพั€ะธัะฝะพะณะพ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะพะดะตะปั– `Item` ั– `ResponseMessage`. + +### ะ”ะพะบัƒะผะตะฝั‚ะฐั†ั–ั API { #api-docs } + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะดะพ `/docs`, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต **ัั…ะตะผะธ** ะดะฐะฝะธั…, ัะบั– ะฝะฐะดัะธะปะฐัŽั‚ัŒัั ะฒ ะทะฐะฟะธั‚ะฐั… ั– ะฟั€ะธะนะผะฐัŽั‚ัŒัั ัƒ ะฒั–ะดะฟะพะฒั–ะดัั…: + + + +ะ’ะธ ะฑะฐั‡ะธั‚ะต ั†ั– ัั…ะตะผะธ, ะพัะบั–ะปัŒะบะธ ั—ั… ะฑัƒะปะพ ะพะณะพะปะพัˆะตะฝะพ ัะบ ะผะพะดะตะปั– ะฒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฆั ั–ะฝั„ะพั€ะผะฐั†ั–ั ะดะพัั‚ัƒะฟะฝะฐ ัƒ **ัั…ะตะผั– OpenAPI** ะทะฐัั‚ะพััƒะฝะบัƒ, ะฐ ะฟะพั‚ั–ะผ ะฟะพะบะฐะทัƒั”ั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API. + +ะขะฐ ัะฐะผะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั ะท ะผะพะดะตะปะตะน, ัะบัƒ ะฒะบะปัŽั‡ะตะฝะพ ะดะพ OpenAPI, ะผะพะถะต ะฑัƒั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฐ ะดะปั **ะณะตะฝะตั€ะฐั†ั–ั— ะบะปั–ั”ะฝั‚ััŒะบะพะณะพ ะบะพะดัƒ**. + +### Hey API { #hey-api } + +ะšะพะปะธ ัƒ ะฝะฐั ั” ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ะท ะผะพะดะตะปัะผะธ, ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ Hey API ะดะปั ะณะตะฝะตั€ะฐั†ั–ั— ะบะปั–ั”ะฝั‚ะฐ TypeScript. ะะฐะนัˆะฒะธะดัˆะธะน ัะฟะพัั–ะฑ ะทั€ะพะฑะธั‚ะธ ั†ะต โ€” ั‡ะตั€ะตะท npx. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +ะฆะต ะทะณะตะฝะตั€ัƒั” TypeScript SDK ัƒ `./src/client`. + +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั, ัะบ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `@hey-api/openapi-ts`, ั– ะฟะพั‡ะธั‚ะฐั‚ะธ ะฟั€ะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ั€ะตะทัƒะปัŒั‚ะฐั‚ ะฝะฐ ั—ั…ะฝัŒะพะผัƒ ัะฐะนั‚ั–. + +### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั SDK { #using-the-sdk } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะปั–ั”ะฝั‚ััŒะบะธะน ะบะพะด. ะฆะต ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ; ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ยซะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัยป ะดะปั ะผะตั‚ะพะดั–ะฒ: + + + +ะ’ะธ ั‚ะฐะบะพะถ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะดะปั ะบะพั€ะธัะฝะพะณะพ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั, ัะบะต ะฝะฐะดัะธะปะฐั”ั‚ะต: + + + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะดะปั `name` ั– `price`, ัะบั– ะฑัƒะปะธ ะฒะธะทะฝะฐั‡ะตะฝั– ะฒ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI, ัƒ ะผะพะดะตะปั– `Item`. + +/// + +ะ’ะธ ะฑะฐั‡ะธั‚ะธะผะตั‚ะต ะฒะฑัƒะดะพะฒะฐะฝั– ะฟะพะผะธะปะบะธ ะดะปั ะดะฐะฝะธั…, ัะบั– ะฝะฐะดัะธะปะฐั”ั‚ะต: + + + +ะžะฑ'ั”ะบั‚ ะฒั–ะดะฟะพะฒั–ะดั– ั‚ะฐะบะพะถ ะผะฐั‚ะธะผะต ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั: + + + +## ะ—ะฐัั‚ะพััƒะฝะพะบ FastAPI ะท ะผั–ั‚ะบะฐะผะธ { #fastapi-app-with-tags } + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ะฑัƒะดะต ะฑั–ะปัŒัˆะธะผ, ั– ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ะผั–ั‚ะบะธ, ั‰ะพะฑ ั€ะพะทะดั–ะปัั‚ะธ ั€ั–ะทะฝั– ะณั€ัƒะฟะธ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ัะตะบั†ั–ั ะดะปั **items** ั– ะพะบั€ะตะผะฐ ัะตะบั†ั–ั ะดะปั **users**, ั– ั—ั… ะผะพะถะฝะฐ ั€ะพะทะดั–ะปะธั‚ะธ ะผั–ั‚ะบะฐะผะธ: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### ะ—ะณะตะฝะตั€ัƒะฒะฐั‚ะธ TypeScript-ะบะปั–ั”ะฝั‚ ั–ะท ะผั–ั‚ะบะฐะผะธ { #generate-a-typescript-client-with-tags } + +ะฏะบั‰ะพ ะฒะธ ะทะณะตะฝะตั€ัƒั”ั‚ะต ะบะปั–ั”ะฝั‚ ะดะปั ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะผั–ั‚ะบะธ, ะทะฐะทะฒะธั‡ะฐะน ะบะปั–ั”ะฝั‚ััŒะบะธะน ะบะพะด ั‚ะฐะบะพะถ ะฑัƒะดะต ั€ะพะทะดั–ะปะตะฝะพ ะทะฐ ั†ะธะผะธ ะผั–ั‚ะบะฐะผะธ. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะธ ะผะฐั‚ะธะผะตั‚ะต ะฟั€ะฐะฒะธะปัŒะฝะพ ะฒะฟะพั€ัะดะบะพะฒะฐะฝั– ั‚ะฐ ะทะณั€ัƒะฟะพะฒะฐะฝั– ั‡ะฐัั‚ะธะฝะธ ะบะปั–ั”ะฝั‚ััŒะบะพะณะพ ะบะพะดัƒ: + + + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ัƒ ะฒะฐั ั”: + +* `ItemsService` +* `UsersService` + +### ะะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ ะบะปั–ั”ะฝั‚ะฐ { #client-method-names } + +ะ—ะฐั€ะฐะท ะทะณะตะฝะตั€ะพะฒะฐะฝั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ ะฝะฐ ะบัˆั‚ะฐะปั‚ `createItemItemsPost` ะฒะธะณะปัะดะฐัŽั‚ัŒ ะฝะต ะดัƒะถะต ะพั…ะฐะนะฝะพ: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...ั†ะต ั‚ะพะผัƒ, ั‰ะพ ะณะตะฝะตั€ะฐั‚ะพั€ ะบะปั–ั”ะฝั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒะฝัƒั‚ั€ั–ัˆะฝั–ะน OpenAPI **operation ID** ะดะปั ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +OpenAPI ะฒะธะผะฐะณะฐั”, ั‰ะพะฑ ะบะพะถะตะฝ operation ID ะฑัƒะฒ ัƒะฝั–ะบะฐะปัŒะฝะธะผ ะดะปั ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*, ั‚ะพะผัƒ FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” **ะฝะฐะทะฒัƒ ั„ัƒะฝะบั†ั–ั—**, **ัˆะปัั…** ั– **HTTP-ะผะตั‚ะพะด/ะพะฟะตั€ะฐั†ั–ัŽ** ะดะปั ะณะตะฝะตั€ะฐั†ั–ั— ั†ัŒะพะณะพ operation ID, ะฐะดะถะต ั‚ะฐะบ ะฒะพะฝะพ ะผะพะถะต ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ัƒะฝั–ะบะฐะปัŒะฝั–ัั‚ัŒ operation ID. + +ะะปะต ะดะฐะปั– ั ะฟะพะบะฐะถัƒ, ัะบ ั†ะต ะฟะพะบั€ะฐั‰ะธั‚ะธ. ๐Ÿค“ + +## ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– operation ID ั‚ะฐ ะบั€ะฐั‰ั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ { #custom-operation-ids-and-better-method-names } + +ะ’ะธ ะผะพะถะตั‚ะต **ะทะผั–ะฝะธั‚ะธ** ัะฟะพัั–ะฑ **ะณะตะฝะตั€ะฐั†ั–ั—** ั†ะธั… operation ID, ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ั—ั… ะฟั€ะพัั‚ั–ัˆะธะผะธ ั‚ะฐ ะผะฐั‚ะธ **ะฟั€ะพัั‚ั–ัˆั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ** ัƒ ะบะปั–ั”ะฝั‚ะฐั…. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะดะต ั–ะฝัˆะธะผ ัะฟะพัะพะฑะพะผ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ, ั‰ะพ ะบะพะถะตะฝ operation ID ั” **ัƒะฝั–ะบะฐะปัŒะฝะธะผ**. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะบะพะถะฝะฐ *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะผะฐั” ะผั–ั‚ะบัƒ, ะฐ ะฟะพั‚ั–ะผ ะณะตะฝะตั€ัƒะฒะฐั‚ะธ operation ID ะฝะฐ ะพัะฝะพะฒั– **ะผั–ั‚ะบะธ** ั‚ะฐ **ะฝะฐะทะฒะธ** *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* (ะฝะฐะทะฒะธ ั„ัƒะฝะบั†ั–ั—). + +### ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะฐ ั„ัƒะฝะบั†ั–ั ะณะตะฝะตั€ัƒะฒะฐะฝะฝั ัƒะฝั–ะบะฐะปัŒะฝะพะณะพ ID { #custom-generate-unique-id-function } + +FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” **ัƒะฝั–ะบะฐะปัŒะฝะธะน ID** ะดะปั ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ัะบะธะน ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั ะดะปั **operation ID**, ะฐ ั‚ะฐะบะพะถ ะดะปั ะฝะฐะทะฒ ะฑัƒะดัŒ-ัะบะธั… ะฟะพั‚ั€ั–ะฑะฝะธั… ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธั… ะผะพะดะตะปะตะน ะดะปั ะทะฐะฟะธั‚ั–ะฒ ั‡ะธ ะฒั–ะดะฟะพะฒั–ะดะตะน. + +ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั†ัŽ ั„ัƒะฝะบั†ั–ัŽ. ะ’ะพะฝะฐ ะฟั€ะธะนะผะฐั” `APIRoute` ั– ะฟะพะฒะตั€ั‚ะฐั” ัั‚ั€ะพะบัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, ั‚ัƒั‚ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฟะตั€ัˆะฐ ะผั–ั‚ะบะฐ (ัƒ ะฒะฐั, ะนะผะพะฒั–ั€ะฝะพ, ะฑัƒะดะต ะปะธัˆะต ะพะดะฝะฐ ะผั–ั‚ะบะฐ) ั– ะฝะฐะทะฒะฐ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* (ะฝะฐะทะฒะฐ ั„ัƒะฝะบั†ั–ั—). + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั†ัŽ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบัƒ ั„ัƒะฝะบั†ั–ัŽ ะดะพ **FastAPI** ัะบ ะฟะฐั€ะฐะผะตั‚ั€ `generate_unique_id_function`: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### ะ—ะณะตะฝะตั€ัƒะฒะฐั‚ะธ TypeScript-ะบะปั–ั”ะฝั‚ ะท ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะผะธ operation ID { #generate-a-typescript-client-with-custom-operation-ids } + +ะขะตะฟะตั€, ัะบั‰ะพ ะฒะธ ะทะณะตะฝะตั€ัƒั”ั‚ะต ะบะปั–ั”ะฝั‚ ะทะฝะพะฒัƒ, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฟะพะบั€ะฐั‰ะตะฝั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ: + + + +ะฏะบ ะฑะฐั‡ะธั‚ะต, ั‚ะตะฟะตั€ ัƒ ะฝะฐะทะฒะฐั… ะผะตั‚ะพะดั–ะฒ ั” ะผั–ั‚ะบะฐ, ะฐ ะฟะพั‚ั–ะผ ะฝะฐะทะฒะฐ ั„ัƒะฝะบั†ั–ั—; ะฒะพะฝะธ ะฑั–ะปัŒัˆะต ะฝะต ะผั–ัั‚ัั‚ัŒ ั–ะฝั„ะพั€ะผะฐั†ั–ั— ะท URL-ัˆะปัั…ัƒ ั‚ะฐ HTTP-ะพะฟะตั€ะฐั†ั–ั—. + +### ะŸะพะฟะตั€ะตะดะฝั ะพะฑั€ะพะฑะบะฐ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI ะดะปั ะณะตะฝะตั€ะฐั‚ะพั€ะฐ ะบะปั–ั”ะฝั‚ะฐ { #preprocess-the-openapi-specification-for-the-client-generator } + +ะฃ ะทะณะตะฝะตั€ะพะฒะฐะฝะพะผัƒ ะบะพะดั– ะฒัะต ั‰ะต ั” ะฟะตะฒะฝะฐ **ะดัƒะฑะปัŒะพะฒะฐะฝะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั**. + +ะœะธ ะฒะถะต ะทะฝะฐั”ะผะพ, ั‰ะพ ั†ะตะน ะผะตั‚ะพะด ัั‚ะพััƒั”ั‚ัŒัั **items**, ะฐะดะถะต ั†ะต ัะปะพะฒะพ ั” ะฒ `ItemsService` (ะฒะทัั‚ะพ ะท ะผั–ั‚ะบะธ), ะฐะปะต ะฒัะต ั‰ะต ะผะฐั”ะผะพ ะฝะฐะทะฒัƒ ะผั–ั‚ะบะธ ัะบ ะฟั€ะตั„ั–ะบั ัƒ ะฝะฐะทะฒั– ะผะตั‚ะพะดัƒ. ๐Ÿ˜• + +ะœะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฒัะต ะพะดะฝะพ ะทะฐั…ะพั‡ะตะผะพ ะทะฑะตั€ะตะณั‚ะธ ั†ะต ะทะฐะณะฐะปะพะผ ะดะปั OpenAPI, ะฐะดะถะต ั‚ะฐะบ ะณะฐั€ะฐะฝั‚ัƒั”ั‚ัŒัั ัƒะฝั–ะบะฐะปัŒะฝั–ัั‚ัŒ operation ID. + +ะะปะต ะดะปั ะทะณะตะฝะตั€ะพะฒะฐะฝะพะณะพ ะบะปั–ั”ะฝั‚ะฐ ะผะธ ะผะพะถะตะผะพ **ะทะผั–ะฝะธั‚ะธ** operation ID ะฒ OpenAPI ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะณะตะฝะตั€ะฐั†ั–ั”ัŽ ะบะปั–ั”ะฝั‚ั–ะฒ, ะฟั€ะพัั‚ะพ ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ ะฟั€ะธั”ะผะฝั–ัˆะธะผะธ ั‚ะฐ **ั‡ะธัั‚ั–ัˆะธะผะธ**. + +ะœะธ ะผะพะถะตะผะพ ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ JSON OpenAPI ัƒ ั„ะฐะนะป `openapi.json`, ะฐ ะฟะพั‚ั–ะผ **ะฟั€ะธะฑั€ะฐั‚ะธ ั†ะตะน ะฟั€ะตั„ั–ะบั ั–ะท ะผั–ั‚ะบะพัŽ** ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะฐะบะพะณะพ ัะบั€ะธะฟั‚ัƒ: + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +ะŸั–ัะปั ั†ัŒะพะณะพ operation ID ะฑัƒะดะต ะฟะตั€ะตะนะผะตะฝะพะฒะฐะฝะพ ะท ั‡ะพะณะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ `items-get_items` ะฟั€ะพัั‚ะพ ะฝะฐ `get_items`, ั‚ะพะถ ะณะตะฝะตั€ะฐั‚ะพั€ ะบะปั–ั”ะฝั‚ะฐ ะทะผะพะถะต ัั‚ะฒะพั€ะธั‚ะธ ะฟั€ะพัั‚ั–ัˆั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ. + +### ะ—ะณะตะฝะตั€ัƒะฒะฐั‚ะธ TypeScript-ะบะปั–ั”ะฝั‚ ั–ะท ะฟะพะฟะตั€ะตะดะฝัŒะพ ะพะฑั€ะพะฑะปะตะฝะธะผ OpenAPI { #generate-a-typescript-client-with-the-preprocessed-openapi } + +ะžัะบั–ะปัŒะบะธ ะบั–ะฝั†ะตะฒะธะน ั€ะตะทัƒะปัŒั‚ะฐั‚ ั‚ะตะฟะตั€ ัƒ ั„ะฐะนะปั– `openapi.json`, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพะฝะพะฒะธั‚ะธ ัˆะปัั… ะดะพ ะฒั…ั–ะดะฝะธั… ะดะฐะฝะธั…: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +ะŸั–ัะปั ะณะตะฝะตั€ะฐั†ั–ั— ะฝะพะฒะพะณะพ ะบะปั–ั”ะฝั‚ะฐ ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต **ั‡ะธัั‚ั– ะฝะฐะทะฒะธ ะผะตั‚ะพะดั–ะฒ**, ั–ะท ัƒัั–ะผ **ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัะผ**, **ะฒะฑัƒะดะพะฒะฐะฝะธะผะธ ะฟะพะผะธะปะบะฐะผะธ** ั‚ะพั‰ะพ: + + + +## ะŸะตั€ะตะฒะฐะณะธ { #benefits } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝั– ะบะปั–ั”ะฝั‚ะธ, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต **ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั** ะดะปั: + +* ะœะตั‚ะพะดั–ะฒ. +* ะšะพั€ะธัะฝะพะณะพ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะทะฐะฟะธั‚ัƒ ะฒ ั‚ั–ะปั–, ะฟะฐั€ะฐะผะตั‚ั€ะฐั… ะทะฐะฟะธั‚ัƒ ั‚ะพั‰ะพ. +* ะšะพั€ะธัะฝะพะณะพ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–. + +ะขะฐะบะพะถ ะฒะธ ะผะฐั‚ะธะผะตั‚ะต **ะฒะฑัƒะดะพะฒะฐะฝั– ะฟะพะผะธะปะบะธ** ะดะปั ะฒััŒะพะณะพ. + +ะ† ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะพะฝะพะฒะปัŽั”ั‚ะต ะบะพะด ะฑะตะบะตะฝะดะฐ ั‚ะฐ **ะฟะตั€ะตะณะตะฝะตั€ะพะฒัƒั”ั‚ะต** ั„ั€ะพะฝั‚ะตะฝะด, ัƒ ะฝัŒะพะผัƒ ะท'ัะฒะปัั‚ะธะผัƒั‚ัŒัั ะฝะพะฒั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ัะบ ะผะตั‚ะพะดะธ, ัั‚ะฐั€ั– ะฑัƒะดะต ะฒะธะดะฐะปะตะฝะพ, ะฐ ะฑัƒะดัŒ-ัะบั– ั–ะฝัˆั– ะทะผั–ะฝะธ ะฒั–ะดะพะฑั€ะฐะทัั‚ัŒัั ัƒ ะทะณะตะฝะตั€ะพะฒะฐะฝะพะผัƒ ะบะพะดั–. ๐Ÿค“ + +ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะบั‰ะพ ั‰ะพััŒ ะทะผั–ะฝะธะปะพัั, ั†ะต ะฑัƒะดะต **ะฒั–ะดะพะฑั€ะฐะถะตะฝะพ** ะฒ ะบะปั–ั”ะฝั‚ััŒะบะพะผัƒ ะบะพะดั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ. ะ ัะบั‰ะพ ะฒะธ **ะทั–ะฑะตั€ะตั‚ะต** ะบะปั–ั”ะฝั‚, ะฑัƒะดะต ะฟะพะฒั–ะดะพะผะปะตะฝะพ ะฟั€ะพ ะฟะพะผะธะปะบัƒ, ัะบั‰ะพ ั” ะฑัƒะดัŒ-ัะบะฐ **ะฝะตะฒั–ะดะฟะพะฒั–ะดะฝั–ัั‚ัŒ** ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะธั… ะดะฐะฝะธั…. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะธ **ะฒะธัะฒะปัั‚ะธะผะตั‚ะต ะฑะฐะณะฐั‚ะพ ะฟะพะผะธะปะพะบ** ะดัƒะถะต ั€ะฐะฝะพ ะฒ ั†ะธะบะปั– ั€ะพะทั€ะพะฑะบะธ, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ั‡ะตะบะฐั‚ะธ, ะฟะพะบะธ ะฟะพะผะธะปะบะธ ะฟั€ะพัะฒะปัั‚ัŒัั ัƒ ะฒะฐัˆะธั… ะบั–ะฝั†ะตะฒะธั… ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ ัƒ ะฟั€ะพะดะฐะบัˆะตะฝั–, ั– ะปะธัˆะต ะฟะพั‚ั–ะผ ะฝะฐะผะฐะณะฐั‚ะธัั ะท'ัััƒะฒะฐั‚ะธ, ัƒ ั‡ะพะผัƒ ะฟั€ะพะฑะปะตะผะฐ. โœจ diff --git a/docs/uk/docs/advanced/index.md b/docs/uk/docs/advanced/index.md new file mode 100644 index 0000000000..1cffe0cecd --- /dev/null +++ b/docs/uk/docs/advanced/index.md @@ -0,0 +1,21 @@ +# ะŸั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #advanced-user-guide } + +## ะ”ะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– { #additional-features } + +ะžัะฝะพะฒะฝะธะน [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ](../tutorial/index.md){.internal-link target=_blank} ะผะฐั” ะฑัƒั‚ะธ ะดะพัั‚ะฐั‚ะฝั–ะผ, ั‰ะพะฑ ะฟั€ะพะฒะตัั‚ะธ ะฒะฐั ั‡ะตั€ะตะท ัƒัั– ะพัะฝะพะฒะฝั– ะผะพะถะปะธะฒะพัั‚ั– **FastAPI**. + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ั–ะฝัˆั– ะพะฟั†ั–ั—, ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— ั‚ะฐ ะดะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั–. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐัั‚ัƒะฟะฝั– ั€ะพะทะดั–ะปะธ ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ ยซะฟั€ะพััƒะฝัƒั‚ั–ยป. + +ะ† ะผะพะถะปะธะฒะพ, ั‰ะพ ั€ั–ัˆะตะฝะฝั ะดะปั ะฒะฐัˆะพะณะพ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะผะพะถะต ะฑัƒั‚ะธ ะฒ ะพะดะฝะพะผัƒ ะท ะฝะธั…. + +/// + +## ะกะฟะตั€ัˆัƒ ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ { #read-the-tutorial-first } + +ะ’ะธ ะฒัะต ั‰ะต ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑั–ะปัŒัˆั–ัั‚ัŒ ะผะพะถะปะธะฒะพัั‚ะตะน **FastAPI**, ะผะฐัŽั‡ะธ ะทะฝะฐะฝะฝั ะท ะพัะฝะพะฒะฝะพะณะพ [ะะฐะฒั‡ะฐะปัŒะฝะพะณะพ ะฟะพัั–ะฑะฝะธะบะฐ - ะŸะพัั–ะฑะฝะธะบะฐ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ](../tutorial/index.md){.internal-link target=_blank}. + +ะ ะฒ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ะฟะตั€ะตะดะฑะฐั‡ะฐั”ั‚ัŒัั, ั‰ะพ ะฒะธ ะฒะถะต ะนะพะณะพ ะฟั€ะพั‡ะธั‚ะฐะปะธ ั– ะทะฝะฐะนะพะผั– ะท ะพัะฝะพะฒะฝะธะผะธ ั–ะดะตัะผะธ. diff --git a/docs/uk/docs/advanced/middleware.md b/docs/uk/docs/advanced/middleware.md new file mode 100644 index 0000000000..207ca96e0a --- /dev/null +++ b/docs/uk/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# ะŸั€ะพััƒะฝัƒั‚ะต ะฟั€ะพะผั–ะถะฝะต ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั { #advanced-middleware } + +ะฃ ะณะพะปะพะฒะฝะพะผัƒ ะฝะฐะฒั‡ะฐะปัŒะฝะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ ะฒะธ ั‡ะธั‚ะฐะปะธ, ัะบ ะดะพะดะฐั‚ะธ [ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะต ะฟั€ะพะผั–ะถะฝะต ะŸะ—](../tutorial/middleware.md){.internal-link target=_blank} ะดะพ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะขะฐะบะพะถ ะฒะธ ั‡ะธั‚ะฐะปะธ, ัะบ ะพะฑั€ะพะฑะปัั‚ะธ [CORS ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}. + +ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ั€ะพะทะณะปัะฝะตะผะพ, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆะต ะฟั€ะพะผั–ะถะฝะต ะŸะ—. + +## ะ”ะพะดะฐะฒะฐะฝะฝั middleware ASGI { #adding-asgi-middlewares } + +ะžัะบั–ะปัŒะบะธ **FastAPI** ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ Starlette ั– ั€ะตะฐะปั–ะทัƒั” ัะฟะตั†ะธั„ั–ะบะฐั†ั–ัŽ ASGI, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบะต ะฟั€ะพะผั–ะถะฝะต ะŸะ— ASGI. + +Middleware ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ ะผะฐั” ะฑัƒั‚ะธ ัั‚ะฒะพั€ะตะฝะต ัะฐะผะต ะดะปั FastAPI ะฐะฑะพ Starlette, ะณะพะปะพะฒะฝะต - ั‰ะพะฑ ะฒะพะฝะพ ะฒั–ะดะฟะพะฒั–ะดะฐะปะพ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— ASGI. + +ะ—ะฐะณะฐะปะพะผ, middleware ASGI โ€” ั†ะต ะบะปะฐัะธ, ัะบั– ะพั‡ั–ะบัƒัŽั‚ัŒ ะพั‚ั€ะธะผะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ ASGI ัะบ ะฟะตั€ัˆะธะน ะฐั€ะณัƒะผะตะฝั‚. + +ะขะพะถ ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะดะพ ัั‚ะพั€ะพะฝะฝั–ั… middleware ASGI ะฒะฐะผ, ั–ะผะพะฒั–ั€ะฝะพ, ะฟะพั€ะฐะดัั‚ัŒ ะทั€ะพะฑะธั‚ะธ ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบ: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +ะะปะต FastAPI (ั‚ะพั‡ะฝั–ัˆะต Starlette) ะฝะฐะดะฐั” ะฟั€ะพัั‚ั–ัˆะธะน ัะฟะพัั–ะฑ, ัะบะธะน ะณะฐั€ะฐะฝั‚ัƒั”, ั‰ะพ ะฒะฝัƒั‚ั€ั–ัˆะฝั” middleware ะพะฑั€ะพะฑะปัั” ะฟะพะผะธะปะบะธ ัะตั€ะฒะตั€ะฐ, ะฐ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ะพะฑั€ะพะฑะฝะธะบะธ ะฒะธะฝัั‚ะบั–ะฒ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะบะพั€ะตะบั‚ะฝะพ. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `app.add_middleware()` (ัะบ ัƒ ะฟั€ะธะบะปะฐะดั– ะดะปั CORS). + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` ะฟั€ะธะนะผะฐั” ะบะปะฐั middleware ัะบ ะฟะตั€ัˆะธะน ะฐั€ะณัƒะผะตะฝั‚ ั– ะฑัƒะดัŒ-ัะบั– ะดะพะดะฐั‚ะบะพะฒั– ะฐั€ะณัƒะผะตะฝั‚ะธ, ั‰ะพ ะฑัƒะดัƒั‚ัŒ ะฟะตั€ะตะดะฐะฝั– ั†ัŒะพะผัƒ middleware. + +## ะ’ะฑัƒะดะพะฒะฐะฝะต middleware { #integrated-middlewares } + +**FastAPI** ะผั–ัั‚ะธั‚ัŒ ะบั–ะปัŒะบะฐ middleware ะดะปั ะฟะพัˆะธั€ะตะฝะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั, ะดะฐะปั– ั€ะพะทะณะปัะฝะตะผะพ, ัะบ ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ะฟั€ะธะบะปะฐะดะฐั… ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `from starlette.middleware.something import SomethingMiddleware`. + +**FastAPI** ะฝะฐะดะฐั” ะบั–ะปัŒะบะฐ middleware ัƒ `fastapi.middleware` ะฒะธะบะปัŽั‡ะฝะพ ะดะปั ะทั€ัƒั‡ะฝะพัั‚ั– ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… middleware ะฟะพั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +ะŸั€ะธะผัƒัˆัƒั”, ั‰ะพะฑ ัƒัั– ะฒั…ั–ะดะฝั– ะทะฐะฟะธั‚ะธ ะฑัƒะปะธ ะฐะฑะพ `https`, ะฐะฑะพ `wss`. + +ะ‘ัƒะดัŒ-ัะบะธะน ะฒั…ั–ะดะฝะธะน ะทะฐะฟะธั‚ ะดะพ `http` ะฐะฑะพ `ws` ะฑัƒะดะต ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะพ ะฝะฐ ะทะฐั…ะธั‰ะตะฝัƒ ัั…ะตะผัƒ. + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +ะŸั€ะธะผัƒัˆัƒั”, ั‰ะพะฑ ัƒัั– ะฒั…ั–ะดะฝั– ะทะฐะฟะธั‚ะธ ะผะฐะปะธ ะบะพั€ะตะบั‚ะฝะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะธะน ะทะฐะณะพะปะพะฒะพะบ `Host`, ั‰ะพะฑ ะทะฐั…ะธัั‚ะธั‚ะธัั ะฒั–ะด ะฐั‚ะฐะบ HTTP Host Header. + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ั‚ะฐะบั– ะฐั€ะณัƒะผะตะฝั‚ะธ: + +- `allowed_hosts` - ะกะฟะธัะพะบ ะดะพะผะตะฝะฝะธั… ั–ะผะตะฝ, ัะบั– ัะปั–ะด ะดะพะทะฒะพะปะธั‚ะธ ัะบ ั–ะผะตะฝะฐ ั…ะพัั‚ั–ะฒ. ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ะดะพะผะตะฝะธ ะท ยซะดะธะบะพัŽ ะบะฐั€ั‚ะพัŽยป, ั‚ะฐะบั– ัะบ `*.example.com`, ะดะปั ะทั–ัั‚ะฐะฒะปะตะฝะฝั ะฟั–ะดะดะพะผะตะฝั–ะฒ. ะฉะพะฑ ะดะพะทะฒะพะปะธั‚ะธ ะฑัƒะดัŒ-ัะบะต ั–ะผ'ั ั…ะพัั‚ะฐ, ะฐะฑะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `allowed_hosts=["*"]`, ะฐะฑะพ ะฝะต ะดะพะดะฐะฒะฐะนั‚ะต ั†ะต middleware. +- `www_redirect` - ะฏะบั‰ะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ True, ะทะฐะฟะธั‚ะธ ะดะพ ะฝะต-www ะฒะตั€ัั–ะน ะดะพะทะฒะพะปะตะฝะธั… ั…ะพัั‚ั–ะฒ ะฑัƒะดะต ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝะพ ะดะพ ั—ั…ะฝั–ั… www-ะฒะฐั€ั–ะฐะฝั‚ั–ะฒ. ะขะธะฟะพะฒะพ `True`. + +ะฏะบั‰ะพ ะฒั…ั–ะดะฝะธะน ะทะฐะฟะธั‚ ะฝะต ะฟั€ะพั…ะพะดะธั‚ัŒ ะฟะตั€ะตะฒั–ั€ะบัƒ, ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะพ ะฒั–ะดะฟะพะฒั–ะดัŒ `400`. + +## `GZipMiddleware` { #gzipmiddleware } + +ะžะฑั€ะพะฑะปัั” ะฒั–ะดะฟะพะฒั–ะดั– GZip ะดะปั ะฑัƒะดัŒ-ัะบะพะณะพ ะทะฐะฟะธั‚ัƒ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ `"gzip"` ัƒ ะทะฐะณะพะปะพะฒะบัƒ `Accept-Encoding`. + +Middleware ะพะฑั€ะพะฑะปัั” ัะบ ัั‚ะฐะฝะดะฐั€ั‚ะฝั–, ั‚ะฐะบ ั– ะฟะพั‚ะพะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั–. + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ั‚ะฐะบั– ะฐั€ะณัƒะผะตะฝั‚ะธ: + +- `minimum_size` - ะะต GZip-ัƒะฒะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดั–, ะผะตะฝัˆั– ะทะฐ ั†ะตะน ะผั–ะฝั–ะผะฐะปัŒะฝะธะน ั€ะพะทะผั–ั€ ัƒ ะฑะฐะนั‚ะฐั…. ะขะธะฟะพะฒะพ `500`. +- `compresslevel` - ะ’ะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฟั–ะด ั‡ะฐั ัั‚ะธัะฝะตะฝะฝั GZip. ะฆะต ั†ั–ะปะต ั‡ะธัะปะพ ะฒ ะดั–ะฐะฟะฐะทะพะฝั– ะฒั–ะด 1 ะดะพ 9. ะขะธะฟะพะฒะพ `9`. ะœะตะฝัˆะต ะทะฝะฐั‡ะตะฝะฝั ะดะฐั” ัˆะฒะธะดัˆะต ัั‚ะธัะฝะตะฝะฝั, ะฐะปะต ะฑั–ะปัŒัˆะธะน ั€ะพะทะผั–ั€ ั„ะฐะนะปั–ะฒ; ะฑั–ะปัŒัˆะต ะทะฝะฐั‡ะตะฝะฝั ะดะฐั” ะฟะพะฒั–ะปัŒะฝั–ัˆะต ัั‚ะธัะฝะตะฝะฝั, ะฐะปะต ะผะตะฝัˆะธะน ั€ะพะทะผั–ั€ ั„ะฐะนะปั–ะฒ. + +## ะ†ะฝัˆะต middleware { #other-middlewares } + +ะ„ ะฑะฐะณะฐั‚ะพ ั–ะฝัˆะพะณะพ ะฟั€ะพะผั–ะถะฝะพะณะพ ะŸะ— ASGI. + +ะะฐะฟั€ะธะบะปะฐะด: + +- `ProxyHeadersMiddleware` ะท Uvicorn +- MessagePack + +ะฉะพะฑ ะฟะตั€ะตะณะปัะฝัƒั‚ะธ ั–ะฝัˆั– ะดะพัั‚ัƒะฟะฝั– middleware, ะพะทะฝะฐะนะพะผั‚ะตัั ะท ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ Starlette ั‰ะพะดะพ middleware ั‚ะฐ ัะฟะธัะบะพะผ ASGI Awesome. diff --git a/docs/uk/docs/advanced/openapi-callbacks.md b/docs/uk/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000..1f2adb1fc0 --- /dev/null +++ b/docs/uk/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# ะ—ะฒะพั€ะพั‚ะฝั– ะฒะธะบะปะธะบะธ OpenAPI { #openapi-callbacks } + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ API ะท ะพะฟะตั€ะฐั†ั–ั”ัŽ ัˆะปัั…ัƒ, ัะบะฐ ั–ะฝั–ั†ั–ัŽะฒะฐั‚ะธะผะต ะทะฐะฟะธั‚ ะดะพ ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API, ัั‚ะฒะพั€ะตะฝะพะณะพ ะบะธะผะพััŒ ั–ะฝัˆะธะผ (ะนะผะพะฒั–ั€ะฝะพ ั‚ะธะผ ัะฐะผะธะผ ั€ะพะทั€ะพะฑะฝะธะบะพะผ, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะฐัˆ API). + +ะŸั€ะพั†ะตั, ั‰ะพ ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั, ะบะพะปะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ API ะฒะธะบะปะธะบะฐั” ะทะพะฒะฝั–ัˆะฝั–ะน API, ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบยป. ะขะพะผัƒ ั‰ะพ ะฟั€ะพะณั€ะฐะผะฝะต ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั, ะฝะฐะฟะธัะฐะฝะต ะทะพะฒะฝั–ัˆะฝั–ะผ ั€ะพะทั€ะพะฑะฝะธะบะพะผ, ะฝะฐะดัะธะปะฐั” ะทะฐะฟะธั‚ ะดะพ ะฒะฐัˆะพะณะพ API, ะฐ ะฟะพั‚ั–ะผ ะฒะฐัˆ API ะฒะธะบะพะฝัƒั” ะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบ, ะฝะฐะดัะธะปะฐัŽั‡ะธ ะทะฐะฟะธั‚ ะดะพ ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API (ะนะพะณะพ, ะนะผะพะฒั–ั€ะฝะพ, ั‚ะฐะบะพะถ ัั‚ะฒะพั€ะธะฒ ั‚ะพะน ัะฐะผะธะน ั€ะพะทั€ะพะฑะฝะธะบ). + +ะฃ ั‚ะฐะบะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะฐะผ ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ, ัะบะธะผ ะผะฐั” ะฑัƒั‚ะธ ั‚ะพะน ะทะพะฒะฝั–ัˆะฝั–ะน API: ัะบั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฒั–ะฝ ะผะฐั” ะผะฐั‚ะธ, ัะบะต ั‚ั–ะปะพ ะพั‡ั–ะบัƒะฒะฐั‚ะธ, ัะบัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ั‚ะพั‰ะพ. + +## ะ—ะฐัั‚ะพััƒะฝะพะบ ะทั– ะทะฒะพั€ะพั‚ะฝะธะผะธ ะฒะธะบะปะธะบะฐะผะธ { #an-app-with-callbacks } + +ะ ะพะทะณะปัะฝัŒะผะพ ั†ะต ะฝะฐ ะฟั€ะธะบะปะฐะดั–. + +ะฃัะฒั–ะผะพ, ั‰ะพ ะฒะธ ั€ะพะทั€ะพะฑะปัั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ั€ะฐั…ัƒะฝะบั–ะฒ. + +ะฆั– ั€ะฐั…ัƒะฝะบะธ ะผะฐั‚ะธะผัƒั‚ัŒ `id`, `title` (ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะพ), `customer` ั– `total`. + +ะšะพั€ะธัั‚ัƒะฒะฐั‡ ะฒะฐัˆะพะณะพ API (ะทะพะฒะฝั–ัˆะฝั–ะน ั€ะพะทั€ะพะฑะฝะธะบ) ัั‚ะฒะพั€ะธั‚ัŒ ั€ะฐั…ัƒะฝะพะบ ัƒ ะฒะฐัˆะพะผัƒ API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ POST-ะทะฐะฟะธั‚ัƒ. + +ะŸะพั‚ั–ะผ ะฒะฐัˆ API ะฑัƒะดะต (ัƒัะฒั–ะผะพ): + +- ะะฐะดัะธะปะฐั‚ะธ ั€ะฐั…ัƒะฝะพะบ ะดะตัะบะพะผัƒ ะบะปั–ั”ะฝั‚ัƒ ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ ั€ะพะทั€ะพะฑะฝะธะบะฐ. +- ะžั‚ั€ะธะผัƒะฒะฐั‚ะธ ะพะฟะปะฐั‚ัƒ. +- ะะฐะดัะธะปะฐั‚ะธ ัะฟะพะฒั–ั‰ะตะฝะฝั ะฝะฐะทะฐะด ะบะพั€ะธัั‚ัƒะฒะฐั‡ัƒ API (ะทะพะฒะฝั–ัˆะฝัŒะพะผัƒ ั€ะพะทั€ะพะฑะฝะธะบัƒ). + - ะฆะต ะฑัƒะดะต ะทั€ะพะฑะปะตะฝะพ ัˆะปัั…ะพะผ ะฝะฐะดัะธะปะฐะฝะฝั POST-ะทะฐะฟะธั‚ัƒ (ะท ะฒะฐัˆะพะณะพ API) ะดะพ ะดะตัะบะพะณะพ ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API, ะฝะฐะดะฐะฝะพะณะพ ั‚ะธะผ ะทะพะฒะฝั–ัˆะฝั–ะผ ั€ะพะทั€ะพะฑะฝะธะบะพะผ (ั†ะต ั– ั” ยซะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบยป). + +## ะ—ะฒะธั‡ะฐะนะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ FastAPI { #the-normal-fastapi-app } + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฟะพะดะธะฒั–ะผะพัั, ัะบ ะฒะธะณะปัะดะฐะฒ ะฑะธ ะทะฒะธั‡ะฐะนะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ API ะดะพ ะดะพะดะฐะฒะฐะฝะฝั ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ. + +ะ’ั–ะฝ ะผะฐั‚ะธะผะต ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ, ัะบะฐ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผะต ั‚ั–ะปะพ `Invoice`, ั– ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `callback_url`, ั‰ะพ ะผั–ัั‚ะธั‚ะธะผะต URL ะดะปั ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ. + +ะฆั ั‡ะฐัั‚ะธะฝะฐ ั†ั–ะปะบะพะผ ะทะฒะธั‡ะฝะฐ, ะฑั–ะปัŒัˆั–ัั‚ัŒ ะบะพะดัƒ ะฒะฐะผ, ะนะผะพะฒั–ั€ะฝะพ, ัƒะถะต ะทะฝะฐะนะพะผะฐ: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `callback_url` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั‚ะธะฟ Pydantic Url. + +/// + +ะ„ะดะธะฝะฐ ะฝะพะฒะฐ ั€ั–ั‡ - ั†ะต `callbacks=invoices_callback_router.routes` ัะบ ะฐั€ะณัƒะผะตะฝั‚ ะดะตะบะพั€ะฐั‚ะพั€ะฐ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. ะ”ะฐะปั– ั€ะพะทะณะปัะฝะตะผะพ, ั‰ะพ ั†ะต ั‚ะฐะบะต. + +## ะ”ะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ { #documenting-the-callback } + +ะคะฐะบั‚ะธั‡ะฝะธะน ะบะพะด ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ ัะธะปัŒะฝะพ ะทะฐะปะตะถะฐั‚ะธะผะต ะฒั–ะด ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ API. + +ะ†, ะนะผะพะฒั–ั€ะฝะพ, ัะธะปัŒะฝะพ ะฒั–ะดั€ั–ะทะฝัั‚ะธะผะตั‚ัŒัั ะฒั–ะด ะทะฐัั‚ะพััƒะฝะบัƒ ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฆะต ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะปะธัˆะต ะพะดะธะฝ-ะดะฒะฐ ั€ัะดะบะธ ะบะพะดัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +ะะปะต, ะผะพะถะปะธะฒะพ, ะฝะฐะนะฒะฐะถะปะธะฒั–ัˆะฐ ั‡ะฐัั‚ะธะฝะฐ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ - ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฒะฐัˆะพะณะพ API (ะทะพะฒะฝั–ัˆะฝั–ะน ั€ะพะทั€ะพะฑะฝะธะบ) ะฟั€ะฐะฒะธะปัŒะฝะพ ั€ะตะฐะปั–ะทัƒั” ะทะพะฒะฝั–ัˆะฝั–ะน API ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะดะพ ะดะฐะฝะธั…, ัะบั– ะฒะฐัˆ API ะฝะฐะดัะธะปะฐั‚ะธะผะต ะฒ ั‚ั–ะปั– ะทะฐะฟะธั‚ัƒ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ ั‚ะพั‰ะพ. + +ะขะพะผัƒ ะดะฐะปั– ะผะธ ะดะพะดะฐะผะพ ะบะพะด, ั‰ะพะฑ ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ, ัะบะธะผ ะผะฐั” ะฑัƒั‚ะธ ั†ะตะน ะทะพะฒะฝั–ัˆะฝั–ะน API, ั‰ะพะฑ ะฟั€ะธะนะผะฐั‚ะธ ะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบ ะฒั–ะด ะฒะฐัˆะพะณะพ API. + +ะฆั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะท'ัะฒะธั‚ัŒัั ะฒ Swagger UI ะทะฐ ะฐะดั€ะตัะพัŽ `/docs` ัƒ ะฒะฐัˆะพะผัƒ API ั– ะดะฐัั‚ัŒ ะทะผะพะณัƒ ะทะพะฒะฝั–ัˆะฝั–ะผ ั€ะพะทั€ะพะฑะฝะธะบะฐะผ ะทั€ะพะทัƒะผั–ั‚ะธ, ัะบ ัั‚ะฒะพั€ะธั‚ะธ ะทะพะฒะฝั–ัˆะฝั–ะน API. + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ัะฐะผ ะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบ ะฝะต ั€ะตะฐะปั–ะทะพะฒะฐะฝะพ (ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ะปะธัˆะต ะพะดะธะฝ ั€ัะดะพะบ ะบะพะดัƒ), ะปะธัˆะต ั‡ะฐัั‚ะธะฝัƒ ะท ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะคะฐะบั‚ะธั‡ะฝะธะน ะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบ - ั†ะต ะฟั€ะพัั‚ะพ HTTP-ะทะฐะฟะธั‚. + +ะ ะตะฐะปั–ะทัƒัŽั‡ะธ ะทะฒะพั€ะพั‚ะฝะธะน ะฒะธะบะปะธะบ ัะฐะผะพัั‚ั–ะนะฝะพ, ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั, ะฝะฐะฟั€ะธะบะปะฐะด, HTTPX ะฐะฑะพ Requests. + +/// + +## ะะฐะฟะธัˆั–ั‚ัŒ ะบะพะด ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะดะปั ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ { #write-the-callback-documentation-code } + +ะฆะตะน ะบะพะด ะฝะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธะผะตั‚ัŒัั ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฒั–ะฝ ะฟะพั‚ั€ั–ะฑะตะฝ ะปะธัˆะต, ั‰ะพะฑ ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ, ัะบะธะผ ะผะฐั” ะฑัƒั‚ะธ ะทะพะฒะฝั–ัˆะฝั–ะน API. + +ะะปะต ะฒะธ ะฒะถะต ะทะฝะฐั”ั‚ะต, ัะบ ะปะตะณะบะพ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั API ะทะฐ ะดะพะฟะพะผะพะณะพัŽ FastAPI. + +ะขะพะถ ะผะธ ัะบะพั€ะธัั‚ะฐั”ะผะพัั ั†ะธะผะธ ะทะฝะฐะฝะฝัะผะธ, ั‰ะพะฑ ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ, ัะบะธะผ ะผะฐั” ะฑัƒั‚ะธ ะทะพะฒะฝั–ัˆะฝั–ะน API... ัั‚ะฒะพั€ะธะฒัˆะธ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ัะบั– ะผะฐั” ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ะทะพะฒะฝั–ัˆะฝั–ะน API (ั‚ั–, ัะบั– ะฒะธะบะปะธะบะฐั‚ะธะผะต ะฒะฐัˆ API). + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะธัˆัƒั‡ะธ ะบะพะด ะดะปั ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ, ะบะพั€ะธัะฝะพ ัƒัะฒะธั‚ะธ, ั‰ะพ ะฒะธ - ั‚ะพะน *ะทะพะฒะฝั–ัˆะฝั–ะน ั€ะพะทั€ะพะฑะฝะธะบ*. ะ† ั‰ะพ ะฒะธ ะทะฐั€ะฐะท ั€ะตะฐะปั–ะทัƒั”ั‚ะต *ะทะพะฒะฝั–ัˆะฝั–ะน API*, ะฐ ะฝะต *ะฒะฐัˆ API*. + +ะขะธะผั‡ะฐัะพะฒะพ ะฟั€ะธะนะฝัะฒัˆะธ ั†ัŽ ั‚ะพั‡ะบัƒ ะทะพั€ัƒ ( *ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ ั€ะพะทั€ะพะฑะฝะธะบะฐ* ), ะฒะฐะผ ะฑัƒะดะต ะพั‡ะตะฒะธะดะฝั–ัˆะต, ะบัƒะดะธ ะฟะพะผั–ัั‚ะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ, ัะบัƒ Pydantic-ะผะพะดะตะปัŒ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะดะปั ั‚ั–ะปะฐ, ะดะปั ะฒั–ะดะฟะพะฒั–ะดั– ั‚ะพั‰ะพ ะดะปั ั‚ะพะณะพ *ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API*. + +/// + +### ะกั‚ะฒะพั€ั–ั‚ัŒ callback `APIRouter` { #create-a-callback-apirouter } + +ะกะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ั–ั‚ัŒ ะฝะพะฒะธะน `APIRouter`, ัะบะธะน ะผั–ัั‚ะธั‚ะธะผะต ะพะดะธะฝ ะฐะฑะพ ะบั–ะปัŒะบะฐ ะทะฒะพั€ะพั‚ะฝะธั… ะฒะธะบะปะธะบั–ะฒ. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ { #create-the-callback-path-operation } + +ะฉะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ, ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ั‚ะพะน ัะฐะผะธะน `APIRouter`, ัะบะธะน ะฒะธ ัั‚ะฒะพั€ะธะปะธ ะฒะธั‰ะต. + +ะ’ะพะฝะฐ ะผะฐั” ะฒะธะณะปัะดะฐั‚ะธ ัะบ ะทะฒะธั‡ะฐะนะฝะฐ ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ FastAPI: + +- ะ™ะผะพะฒั–ั€ะฝะพ ะผะฐั” ะผั–ัั‚ะธั‚ะธ ะพะณะพะปะพัˆะตะฝะฝั ั‚ั–ะปะฐ, ัะบะต ะฒะพะฝะฐ ะฟั€ะธะนะผะฐั”, ะฝะฐะฟั€. `body: InvoiceEvent`. +- ะ† ั‚ะฐะบะพะถ ะผะพะถะต ะผั–ัั‚ะธั‚ะธ ะพะณะพะปะพัˆะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–, ัะบัƒ ะฒะพะฝะฐ ะฟะพะฒะตั€ั‚ะฐั”, ะฝะฐะฟั€. `response_model=InvoiceEventReceived`. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +ะ„ 2 ะพัะฝะพะฒะฝั– ะฒั–ะดะผั–ะฝะฝะพัั‚ั– ะฒั–ะด ะทะฒะธั‡ะฐะนะฝะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ: + +- ะ‡ะน ะฝะต ะฟะพั‚ั€ั–ะฑะตะฝ ั€ะตะฐะปัŒะฝะธะน ะบะพะด, ะฐะดะถะต ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฝั–ะบะพะปะธ ะฝะต ะฒะธะบะปะธะบะฐั‚ะธะผะต ั†ะตะน ะบะพะด. ะ’ะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะปะธัˆะต ะดะปั ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API. ะขะพะผัƒ ั„ัƒะฝะบั†ั–ั ะผะพะถะต ะฟั€ะพัั‚ะพ ะผั–ัั‚ะธั‚ะธ `pass`. +- ะจะปัั… ะผะพะถะต ะผั–ัั‚ะธั‚ะธ ะฒะธั€ะฐะท OpenAPI 3 (ะดะธะฒ. ะฝะธะถั‡ะต), ะดะต ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทะผั–ะฝะฝั– ะท ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ั‚ะฐ ั‡ะฐัั‚ะธะฝะธ ะพั€ะธะณั–ะฝะฐะปัŒะฝะพะณะพ ะทะฐะฟะธั‚ัƒ, ะฝะฐะดั–ัะปะฐะฝะพะณะพ ะดะพ ะฒะฐัˆะพะณะพ API. + +### ะ’ะธั€ะฐะท ัˆะปัั…ัƒ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ { #the-callback-path-expression } + +ะจะปัั… ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ ะผะพะถะต ะผั–ัั‚ะธั‚ะธ ะฒะธั€ะฐะท OpenAPI 3, ัะบะธะน ะฒะบะปัŽั‡ะฐั” ั‡ะฐัั‚ะธะฝะธ ะพั€ะธะณั–ะฝะฐะปัŒะฝะพะณะพ ะทะฐะฟะธั‚ัƒ, ะฝะฐะดั–ัะปะฐะฝะพะณะพ ะดะพ ะฒะฐัˆะพะณะพ API. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั†ะต ัั‚ั€ะพะบะฐ: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +ะžั‚ะถะต, ัะบั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฒะฐัˆะพะณะพ API (ะทะพะฒะฝั–ัˆะฝั–ะน ั€ะพะทั€ะพะฑะฝะธะบ) ะฝะฐะดั–ัˆะปะต ะทะฐะฟะธั‚ ะดะพ *ะฒะฐัˆะพะณะพ API* ะฝะฐ: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +ะท JSON-ั‚ั–ะปะพะผ: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +ั‚ะพะดั– *ะฒะฐัˆ API* ะพะฟั€ะฐั†ัŽั” ั€ะฐั…ัƒะฝะพะบ ั– ะทะณะพะดะพะผ ะฝะฐะดั–ัˆะปะต ะทะฐะฟะธั‚ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ ะฝะฐ `callback_url` ( *ะทะพะฒะฝั–ัˆะฝั–ะน API* ): + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +ะท JSON-ั‚ั–ะปะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +ั– ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต ะฒั–ะดะฟะพะฒั–ะดัŒ ะฒั–ะด ั‚ะพะณะพ *ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ API* ะท JSON-ั‚ั–ะปะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```JSON +{ + "ok": true +} +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะธะน URL ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ ะผั–ัั‚ะธั‚ัŒ URL, ะพั‚ั€ะธะผะฐะฝะธะน ัะบ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ ะฒ `callback_url` (`https://www.external.org/events`), ะฐ ั‚ะฐะบะพะถ `id` ั€ะฐั…ัƒะฝะบัƒ ะทัะตั€ะตะดะธะฝะธ JSON-ั‚ั–ะปะฐ (`2expen51ve`). + +/// + +### ะ”ะพะดะฐะนั‚ะต ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ { #add-the-callback-router } + +ะะฐ ั†ัŒะพะผัƒ ะตั‚ะฐะฟั– ะฒะธ ะผะฐั”ั‚ะต ะฟะพั‚ั€ั–ะฑะฝั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ (ั‚ั–, ัะบั– ะผะฐั” ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ *ะทะพะฒะฝั–ัˆะฝั–ะน ั€ะพะทั€ะพะฑะฝะธะบ* ัƒ *ะทะพะฒะฝั–ัˆะฝัŒะพะผัƒ API*) ัƒ ัั‚ะฒะพั€ะตะฝะพะผัƒ ะฒะธั‰ะต ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ั– ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ. + +ะขะตะฟะตั€ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `callbacks` ัƒ ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฒะฐัˆะพะณะพ API, ั‰ะพะฑ ะฟะตั€ะตะดะฐั‚ะธ ะฐั‚ั€ะธะฑัƒั‚ `.routes` (ั†ะต ะฝะฐัะฟั€ะฐะฒะดั– ะฟั€ะพัั‚ะพ `list` ะผะฐั€ัˆั€ัƒั‚ั–ะฒ/ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ) ะท ั†ัŒะพะณะพ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ะฐ ะทะฒะพั€ะพั‚ะฝะพะณะพ ะฒะธะบะปะธะบัƒ: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ะฝะต ัะฐะผ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ (`invoices_callback_router`) ัƒ `callback=`, ะฐ ะฐั‚ั€ะธะฑัƒั‚ `.routes`, ั‚ะพะฑั‚ะพ `invoices_callback_router.routes`. + +/// + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #check-the-docs } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ ั– ะฟะตั€ะตะนั‚ะธ ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฒะฐัˆัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะท ั€ะพะทะดั–ะปะพะผ ยซCallbacksยป ะดะปั ะฒะฐัˆะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ัะบะธะน ะฟะพะบะฐะทัƒั”, ัะบ ะผะฐั” ะฒะธะณะปัะดะฐั‚ะธ ะทะพะฒะฝั–ัˆะฝั–ะน API: + + diff --git a/docs/uk/docs/advanced/openapi-webhooks.md b/docs/uk/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000..0d8a7f4c5f --- /dev/null +++ b/docs/uk/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# ะ’ะตะฑั…ัƒะบะธ OpenAPI { #openapi-webhooks } + +ะ‘ัƒะฒะฐัŽั‚ัŒ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะพะฒั–ะดะพะผะธั‚ะธ **ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ** ะฒะฐัˆะพะณะพ API, ั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะผะพะถะต ะฒะธะบะปะธะบะฐั‚ะธ *ั—ั…ะฝั–ะน* ะทะฐัั‚ะพััƒะฝะพะบ (ะฝะฐะดัะธะปะฐัŽั‡ะธ ะทะฐะฟะธั‚) ั–ะท ะดะตัะบะธะผะธ ะดะฐะฝะธะผะธ, ะทะฐะทะฒะธั‡ะฐะน ั‰ะพะฑ **ัะฟะพะฒั–ัั‚ะธั‚ะธ** ะฟั€ะพ ะฟะตะฒะฝะธะน ั‚ะธะฟ **ะฟะพะดั–ั—**. + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะทะฐะผั–ัั‚ัŒ ะทะฒะธั‡ะฝะพะณะพ ะฟั€ะพั†ะตััƒ, ะบะพะปะธ ะฒะฐัˆั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั– ะฝะฐะดัะธะปะฐัŽั‚ัŒ ะทะฐะฟะธั‚ะธ ะดะพ ะฒะฐัˆะพะณะพ API, ัะฐะผะต **ะฒะฐัˆ API** (ะฐะฑะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ) ะผะพะถะต **ะฝะฐะดัะธะปะฐั‚ะธ ะทะฐะฟะธั‚ะธ ะดะพ ั—ั…ะฝัŒะพั— ัะธัั‚ะตะผะธ** (ะดะพ ั—ั… API, ั—ั… ะทะฐัั‚ะพััƒะฝะบัƒ). + +ะ—ะฐะทะฒะธั‡ะฐะน ั†ะต ะฝะฐะทะธะฒะฐัŽั‚ัŒ **ะฒะตะฑั…ัƒะบะพะผ**. + +## ะšั€ะพะบะธ ะฒะตะฑั…ัƒะบั–ะฒ { #webhooks-steps } + +ะ—ะฐะทะฒะธั‡ะฐะน ะฟั€ะพั†ะตั ั‚ะฐะบะธะน: ะฒะธ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–, ัะบะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฝะฐะดัะธะปะฐั‚ะธะผะตั‚ะต, ั‚ะพะฑั‚ะพ **ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ**. + +ะ’ะธ ั‚ะฐะบะพะถ ัะบะธะผะพััŒ ั‡ะธะฝะพะผ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต ะผะพะผะตะฝั‚ะธ, ะบะพะปะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฝะฐะดัะธะปะฐั‚ะธะผะต ั†ั– ะทะฐะฟะธั‚ะธ ะฐะฑะพ ะฟะพะดั–ั—. + +ะ **ะฒะฐัˆั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–** ัะบะธะผะพััŒ ั‡ะธะฝะพะผ (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะตะฑ-ะดะฐัˆะฑะพั€ะดั–) ะฒะธะทะฝะฐั‡ะฐัŽั‚ัŒ **URL**, ะบัƒะดะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะผะฐั” ะฝะฐะดัะธะปะฐั‚ะธ ั†ั– ะทะฐะฟะธั‚ะธ. + +ะฃัั **ะปะพะณั–ะบะฐ** ั‰ะพะดะพ ั€ะตั”ัั‚ั€ะฐั†ั–ั— URL ะดะปั ะฒะตะฑั…ัƒะบั–ะฒ ั– ะบะพะด ะดะปั ั„ะฐะบั‚ะธั‡ะฝะพะณะพ ะฝะฐะดัะธะปะฐะฝะฝั ั†ะธั… ะทะฐะฟะธั‚ั–ะฒ - ะฝะฐ ะฒะฐัˆ ั€ะพะทััƒะด. ะ’ะธ ะฟะธัˆะตั‚ะต ั†ะต ัƒ **ะฒะปะฐัะฝะพะผัƒ ะบะพะดั–** ั‚ะฐะบ, ัะบ ะฒะฒะฐะถะฐั”ั‚ะต ะทะฐ ะฟะพั‚ั€ั–ะฑะฝะต. + +## ะ”ะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั ะฒะตะฑั…ัƒะบั–ะฒ ัƒ **FastAPI** ั‚ะฐ OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } + +ะฃ **FastAPI**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ OpenAPI, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ ะฝะฐะทะฒะธ ั†ะธั… ะฒะตะฑั…ัƒะบั–ะฒ, ั‚ะธะฟะธ HTTP-ะพะฟะตั€ะฐั†ั–ะน, ัะบั– ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะผะพะถะต ะฝะฐะดัะธะปะฐั‚ะธ (ะฝะฐะฟั€ะธะบะปะฐะด, `POST`, `PUT` ั‚ะพั‰ะพ), ั– **ั‚ั–ะปะฐ** ะทะฐะฟะธั‚ั–ะฒ, ัะบั– ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฝะฐะดัะธะปะฐั‚ะธะผะต. + +ะฆะต ะทะฝะฐั‡ะฝะพ ัะฟั€ะพัั‚ะธั‚ัŒ ะดะปั ะฒะฐัˆะธั… ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ **ั€ะตะฐะปั–ะทะฐั†ั–ัŽ ั—ั…ะฝั–ั… API** ะดะปั ะพั‚ั€ะธะผะฐะฝะฝั ะฒะฐัˆะธั… ะทะฐะฟะธั‚ั–ะฒ **ะฒะตะฑั…ัƒะบั–ะฒ**; ะฒะพะฝะธ ะฝะฐะฒั–ั‚ัŒ ะทะผะพะถัƒั‚ัŒ ะทะณะตะฝะตั€ัƒะฒะฐั‚ะธ ั‡ะฐัั‚ะธะฝัƒ ะฒะปะฐัะฝะพะณะพ ะบะพะดัƒ API ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ’ะตะฑั…ัƒะบะธ ะดะพัั‚ัƒะฟะฝั– ะฒ OpenAPI 3.1.0 ั– ะฒะธั‰ะต, ะฟั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั FastAPI `0.99.0` ั– ะฒะธั‰ะต. + +/// + +## ะ—ะฐัั‚ะพััƒะฝะพะบ ั–ะท ะฒะตะฑั…ัƒะบะฐะผะธ { #an-app-with-webhooks } + +ะšะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI**, ั” ะฐั‚ั€ะธะฑัƒั‚ `webhooks`, ัะบะธะน ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั *ะฒะตะฑั…ัƒะบั–ะฒ* ั‚ะฐะบ ัะฐะผะพ, ัะบ ะฒะธ ะฒะธะทะฝะฐั‡ะฐั”ั‚ะต *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฝะฐะฟั€ะธะบะปะฐะด ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `@app.webhooks.post()`. + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +ะ’ะธะทะฝะฐั‡ะตะฝั– ะฒะฐะผะธ ะฒะตะฑั…ัƒะบะธ ะฟะพั‚ั€ะฐะฟะปัั‚ัŒ ะดะพ **ัั…ะตะผะธ OpenAPI** ั‚ะฐ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะณะพ **ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—**. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะžะฑ'ั”ะบั‚ `app.webhooks` ะฝะฐัะฟั€ะฐะฒะดั– ั” ะฟั€ะพัั‚ะพ `APIRouter` - ั‚ะธะผ ัะฐะผะธะผ ั‚ะธะฟะพะผ, ัะบะธะน ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต, ัั‚ั€ัƒะบั‚ัƒั€ะธะทัƒัŽั‡ะธ ะทะฐัั‚ะพััƒะฝะพะบ ัƒ ะบั–ะปัŒะบะพั… ั„ะฐะนะปะฐั…. + +/// + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะท ะฒะตะฑั…ัƒะบะฐะผะธ ะฒะธ ั„ะฐะบั‚ะธั‡ะฝะพ ะฝะต ะพะณะพะปะพัˆัƒั”ั‚ะต *ัˆะปัั…* (ะฝะฐ ะบัˆั‚ะฐะปั‚ `/items/`), ั‚ะตะบัั‚, ัะบะธะน ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ั‚ะฐะผ, - ั†ะต ะปะธัˆะต **ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€** ะฒะตะฑั…ัƒะบะฐ (ะฝะฐะทะฒะฐ ะฟะพะดั–ั—). ะะฐะฟั€ะธะบะปะฐะด, ัƒ `@app.webhooks.post("new-subscription")` ะฝะฐะทะฒะฐ ะฒะตะฑั…ัƒะบะฐ - `new-subscription`. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะพั‡ั–ะบัƒั”ั‚ัŒัั, ั‰ะพ **ะฒะฐัˆั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–** ั–ะฝัˆะธะผ ัะฟะพัะพะฑะพะผ (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะตะฑ-ะดะฐัˆะฑะพั€ะดั–) ะฒะธะทะฝะฐั‡ะฐั‚ัŒ ั„ะฐะบั‚ะธั‡ะฝะธะน **URL-ัˆะปัั…**, ะดะต ะฒะพะฝะธ ั…ะพั‡ัƒั‚ัŒ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะทะฐะฟะธั‚ ะฒะตะฑั…ัƒะบะฐ. + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #check-the-docs } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ัะฒั–ะน ะทะฐัั‚ะพััƒะฝะพะบ ั– ะฟะตั€ะตะนั‚ะธ ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ัƒ ัะฒะพั—ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะฒะธั‡ะฐะนะฝั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฐ ั‚ะฐะบะพะถ ะดะตัะบั– **ะฒะตะฑั…ัƒะบะธ**: + + diff --git a/docs/uk/docs/advanced/path-operation-advanced-configuration.md b/docs/uk/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000..202f9317ed --- /dev/null +++ b/docs/uk/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,172 @@ +# ะ”ะพะดะฐั‚ะบะพะฒะฐ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฏะบั‰ะพ ะฒะธ ะฝะต ยซะตะบัะฟะตั€ั‚ยป ะท OpenAPI, ั–ะผะพะฒั–ั€ะฝะพ, ะฒะฐะผ ั†ะต ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ. + +/// + +ะ’ะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ OpenAPI `operationId`, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ัƒ ะฒะฐัˆั–ะน *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ `operation_id`. + +ะŸะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะฒั–ะฝ ัƒะฝั–ะบะฐะปัŒะฝะธะน ะดะปั ะบะพะถะฝะพั— ะพะฟะตั€ะฐั†ั–ั—. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะฝะฐะทะฒะธ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ัะบ operationId { #using-the-path-operation-function-name-as-the-operationid } + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฝะฐะทะฒะธ ั„ัƒะฝะบั†ั–ะน ะฒะฐัˆะธั… API ัะบ `operationId`, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพะนั‚ะธัั ะฟะพ ะฒัั–ั… ะฝะธั… ั– ะฟะตั€ะตะฟะธัะฐั‚ะธ `operation_id` ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั—ั…ะฝั–ะน `APIRoute.name`. + +ะ—ั€ะพะฑั–ั‚ัŒ ั†ะต ะฟั–ัะปั ะดะพะดะฐะฒะฐะฝะฝั ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฒั€ัƒั‡ะฝัƒ ะฒะธะบะปะธะบะฐั”ั‚ะต `app.openapi()`, ะพะฝะพะฒั–ั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั `operationId` ะดะพ ั†ัŒะพะณะพ. + +/// + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฏะบั‰ะพ ะฒะธ ั€ะพะฑะธั‚ะต ั†ะต, ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะบะพะถะฝะฐ ะท ะฒะฐัˆะธั… *ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะผะฐั” ัƒะฝั–ะบะฐะปัŒะฝัƒ ะฝะฐะทะฒัƒ. + +ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะพะฝะธ ะฒ ั€ั–ะทะฝะธั… ะผะพะดัƒะปัั… (ั„ะฐะนะปะฐั… Python). + +/// + +## ะ’ะธะบะปัŽั‡ะตะฝะฝั ะท OpenAPI { #exclude-from-openapi } + +ะฉะพะฑ ะฒะธะบะปัŽั‡ะธั‚ะธ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* ะทั– ะทะณะตะฝะตั€ะพะฒะฐะฝะพั— ะกั…ะตะผะธ OpenAPI (ะฐ ะพั‚ะถะต, ั– ะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธั… ัะธัั‚ะตะผ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—), ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `include_in_schema` ั– ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ะนะพะณะพ ะฒ `False`: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} + +## ะ ะพะทัˆะธั€ะตะฝะธะน ะพะฟะธั ั–ะท docstring { #advanced-description-from-docstring } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะฑะผะตะถะธั‚ะธ ะบั–ะปัŒะบั–ัั‚ัŒ ั€ัะดะบั–ะฒ ั–ะท docstring *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะดะปั OpenAPI. + +ะ”ะพะดะฐะฒะฐะฝะฝั `\f` (ะตะบั€ะฐะฝะพะฒะฐะฝะพะณะพ ัะธะผะฒะพะปัƒ ยซform feedยป) ะทะผัƒัะธั‚ัŒ **FastAPI** ะพะฑั€ั–ะทะฐั‚ะธ ะฒะธะฒั–ะด ะดะปั OpenAPI ะฒ ั†ั–ะน ั‚ะพั‡ั†ั–. + +ะฆะต ะฝะต ะทโ€™ัะฒะธั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฐะปะต ั–ะฝัˆั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ (ั‚ะฐะบั– ัะบ Sphinx) ะทะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั€ะตัˆั‚ัƒ. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– { #additional-responses } + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะฒะถะต ะฑะฐั‡ะธะปะธ, ัะบ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ `response_model` ั– `status_code` ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะฆะต ะฒะธะทะฝะฐั‡ะฐั” ะผะตั‚ะฐะดะฐะฝั– ะฟั€ะพ ะพัะฝะพะฒะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะขะฐะบะพะถ ะผะพะถะฝะฐ ะพะณะพะปะพัะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะท ั—ั…ะฝั–ะผะธ ะผะพะดะตะปัะผะธ, ะบะพะดะฐะผะธ ัั‚ะฐั‚ัƒััƒ ั‚ะพั‰ะพ. + +ะฃ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั” ั†ั–ะปะธะน ั€ะพะทะดั–ะป ะฟั€ะพ ั†ะต, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะนะพะณะพ ั‚ัƒั‚: [ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะฒ OpenAPI](additional-responses.md){.internal-link target=_blank}. + +## ะ”ะพะดะฐั‚ะบะพะฒะพ ะฒ OpenAPI { #openapi-extra } + +ะšะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* ัƒ ัะฒะพั”ะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, **FastAPI** ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะณะตะฝะตั€ัƒั” ะฒั–ะดะฟะพะฒั–ะดะฝั– ะผะตั‚ะฐะดะฐะฝั– ะฟั€ะพ ั†ัŽ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* ะดะปั ะฒะบะปัŽั‡ะตะฝะฝั ะฒ ะกั…ะตะผัƒ OpenAPI. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะฃ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI ั†ะต ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ะžะฑ'ั”ะบั‚ Operation. + +/// + +ะ’ั–ะฝ ะผั–ัั‚ะธั‚ัŒ ัƒััŽ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฟั€ะพ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ะฟะพะฑัƒะดะพะฒะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะ’ั–ะฝ ะฒะบะปัŽั‡ะฐั” `tags`, `parameters`, `requestBody`, `responses` ั‚ะพั‰ะพ. + +ะฆัŽ OpenAPI-ัั…ะตะผัƒ, ัะฟะตั†ะธั„ั–ั‡ะฝัƒ ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะทะฐะทะฒะธั‡ะฐะน ะณะตะฝะตั€ัƒั” **FastAPI** ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ, ะฐะปะต ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ั—ั— ั€ะพะทัˆะธั€ะธั‚ะธ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะฝะธะทัŒะบะพั€ั–ะฒะฝะตะฒะฐ ั‚ะพั‡ะบะฐ ั€ะพะทัˆะธั€ะตะฝะฝั. + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะปะธัˆะต ะพะณะพะปะพัะธั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั–, ะทั€ัƒั‡ะฝั–ัˆะต ะทั€ะพะฑะธั‚ะธ ั†ะต ั‡ะตั€ะตะท [ะ”ะพะดะฐั‚ะบะพะฒั– ะฒั–ะดะฟะพะฒั–ะดั– ะฒ OpenAPI](additional-responses.md){.internal-link target=_blank}. + +/// + +ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทัˆะธั€ะธั‚ะธ OpenAPI-ัั…ะตะผัƒ ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟะฐั€ะฐะผะตั‚ั€ `openapi_extra`. + +### ะ ะพะทัˆะธั€ะตะฝะฝั OpenAPI { #openapi-extensions } + +`openapi_extra` ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะธะผ, ะฝะฐะฟั€ะธะบะปะฐะด, ะดะปั ะพะณะพะปะพัˆะตะฝะฝั [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} + +ะฏะบั‰ะพ ะฒะธ ะฒั–ะดะบั€ะธั”ั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API, ะฒะฐัˆะต ั€ะพะทัˆะธั€ะตะฝะฝั ะทโ€™ัะฒะธั‚ัŒัั ะฒะฝะธะทัƒ ะบะพะฝะบั€ะตั‚ะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + + + +ะ† ัะบั‰ะพ ะฒะธ ะฒั–ะดะบั€ะธั”ั‚ะต ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน OpenAPI (ะทะฐ ะฐะดั€ะตัะพัŽ `/openapi.json` ัƒ ะฒะฐัˆะพะผัƒ API), ะฒะธ ั‚ะฐะบะพะถ ะฟะพะฑะฐั‡ะธั‚ะต ัะฒะพั” ั€ะพะทัˆะธั€ะตะฝะฝั ัะบ ั‡ะฐัั‚ะธะฝัƒ ะบะพะฝะบั€ะตั‚ะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### ะ’ะปะฐัะฝะฐ ัั…ะตะผะฐ OpenAPI ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* { #custom-openapi-path-operation-schema } + +ะกะปะพะฒะฝะธะบ ัƒ `openapi_extra` ะฑัƒะดะต ะณะปะธะฑะพะบะพ ะพะฑโ€™ั”ะดะฝะฐะฝะพ ะท ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะพัŽ OpenAPI-ัั…ะตะผะพัŽ ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะขะพะถ ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะดะฐะฝั– ะดะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะพั— ัั…ะตะผะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฒะธั€ั–ัˆะธั‚ะธ ั‡ะธั‚ะฐั‚ะธ ั‚ะฐ ะฟะตั€ะตะฒั–ั€ัั‚ะธ ะทะฐะฟะธั‚ ะฒะปะฐัะฝะธะผ ะบะพะดะพะผ, ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝั– ะผะพะถะปะธะฒะพัั‚ั– FastAPI ะท Pydantic, ะฐะปะต ะฒัะต ะถ ะทะฐั…ะพั‚ั–ั‚ะธ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะทะฐะฟะธั‚ ัƒ ะกั…ะตะผั– OpenAPI. + +ะ’ะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `openapi_extra`: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฝะต ะพะณะพะปะพัˆัƒะฒะฐะปะธ ะถะพะดะฝะพั— ะผะพะดะตะปั– Pydantic. ะะฐัะฟั€ะฐะฒะดั– ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ ะฝะฐะฒั–ั‚ัŒ ะฝะต ั€ะพะทั–ะฑั€ะฐะฝะพ ัะบ JSON, ะฒะพะฝะพ ั‡ะธั‚ะฐั”ั‚ัŒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัะบ `bytes`, ะฐ ั„ัƒะฝะบั†ั–ั `magic_data_reader()` ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธะผะต ะทะฐ ะนะพะณะพ ั€ะพะทะฑั–ั€ ะฟะตะฒะฝะธะผ ั‡ะธะฝะพะผ. + +ะ’ะพะดะฝะพั‡ะฐั ะผะธ ะผะพะถะตะผะพ ะพะณะพะปะพัะธั‚ะธ ะพั‡ั–ะบัƒะฒะฐะฝัƒ ัั…ะตะผัƒ ะดะปั ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ. + +### ะ’ะปะฐัะฝะธะน ั‚ะธะฟ ะฒะผั–ัั‚ัƒ OpenAPI { #custom-openapi-content-type } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ัะฐะผะธะน ะฟั€ะธะนะพะผ, ะฒะธ ะผะพะถะตั‚ะต ะทะฐัั‚ะพััƒะฒะฐั‚ะธ ะผะพะดะตะปัŒ Pydantic, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะกั…ะตะผัƒ JSON, ัะบะฐ ะฟะพั‚ั–ะผ ะฒะบะปัŽั‡ะฐั”ั‚ัŒัั ะฒ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ั€ะพะทะดั–ะป OpenAPI-ัั…ะตะผะธ ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั†ะต, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ั‚ะธะฟ ะดะฐะฝะธั… ัƒ ะทะฐะฟะธั‚ั– - ะฝะต JSON. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ ั†ัŒะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะผะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฒะฑัƒะดะพะฒะฐะฝัƒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ FastAPI ะดะปั ะพั‚ั€ะธะผะฐะฝะฝั ะกั…ะตะผะธ JSON ะท ะผะพะดะตะปะตะน Pydantic ั– ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะปั JSON. ะะฐัะฟั€ะฐะฒะดั– ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ั‚ะธะฟ ะฒะผั–ัั‚ัƒ ะทะฐะฟะธั‚ัƒ ัะบ YAML, ะฐ ะฝะต JSON: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +ะŸะพะฟั€ะธ ั‚ะต, ั‰ะพ ะผะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ะธะฟะพะฒัƒ ะฒะฑัƒะดะพะฒะฐะฝัƒ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ, ะผะธ ะฒัะต ะพะดะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะผะพะดะตะปัŒ Pydantic, ั‰ะพะฑ ะฒั€ัƒั‡ะฝัƒ ะทะณะตะฝะตั€ัƒะฒะฐั‚ะธ ะกั…ะตะผัƒ JSON ะดะปั ะดะฐะฝะธั…, ัะบั– ั…ะพั‡ะตะผะพ ะพั‚ั€ะธะผะฐั‚ะธ ัƒ ั„ะพั€ะผะฐั‚ั– YAML. + +ะŸะพั‚ั–ะผ ะผะธ ะฟั€ะฐั†ัŽั”ะผะพ ั–ะท ะทะฐะฟะธั‚ะพะผ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ั– ะพั‚ั€ะธะผัƒั”ะผะพ ั‚ั–ะปะพ ัะบ `bytes`. ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ FastAPI ะฝะฐะฒั–ั‚ัŒ ะฝะต ะฝะฐะผะฐะณะฐั‚ะธะผะตั‚ัŒัั ั€ะพะทั–ะฑั€ะฐั‚ะธ ะบะพั€ะธัะฝะต ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะทะฐะฟะธั‚ัƒ ัะบ JSON. + +ะ”ะฐะปั– ัƒ ะฝะฐัˆะพะผัƒ ะบะพะดั– ะผะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ั€ะพะทะฑะธั€ะฐั”ะผะพ ั†ะตะน YAML-ะฒะผั–ัั‚ ั– ะทะฝะพะฒัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ัƒ ัะฐะผัƒ ะผะพะดะตะปัŒ Pydantic, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ YAML-ะฒะผั–ัั‚: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขัƒั‚ ะผะธ ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ัƒ ัะฐะผัƒ ะผะพะดะตะปัŒ Pydantic. + +ะะปะต ั‚ะฐะบ ัะฐะผะพ ะผะธ ะผะพะณะปะธ ะฑ ะฟะตั€ะตะฒั–ั€ัั‚ะธ ะดะฐะฝั– ั–ะฝัˆะธะผ ัะฟะพัะพะฑะพะผ. + +/// diff --git a/docs/uk/docs/advanced/response-change-status-code.md b/docs/uk/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000..fdf9f81c56 --- /dev/null +++ b/docs/uk/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# ะ’ั–ะดะฟะพะฒั–ะดัŒ - ะทะผั–ะฝะฐ ะบะพะดัƒ ัั‚ะฐั‚ัƒััƒ { #response-change-status-code } + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะฒะถะต ั‡ะธั‚ะฐะปะธ, ั‰ะพ ะผะพะถะฝะฐ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ั‚ะธะฟะพะฒะธะน [ะบะพะด ัั‚ะฐั‚ัƒััƒ ะฒั–ะดะฟะพะฒั–ะดั–](../tutorial/response-status-code.md){.internal-link target=_blank}. + +ะะปะต ั–ะฝะบะพะปะธ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะฒะตั€ะฝัƒั‚ะธ ั–ะฝัˆะธะน ะบะพะด ัั‚ะฐั‚ัƒััƒ, ะฝั–ะถ ั‚ะธะฟะพะฒะธะน. + +## ะ’ะธะฟะฐะดะพะบ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั { #use-case } + +ะะฐะฟั€ะธะบะปะฐะด, ัƒัะฒั–ะผะพ, ั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะบะพะด ัั‚ะฐั‚ัƒััƒ HTTP ยซOKยป `200`. + +ะะปะต ัะบั‰ะพ ะดะฐะฝะธั… ะฝะต ั–ัะฝัƒะฒะฐะปะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ั—ั… ั– ะฟะพะฒะตั€ะฝัƒั‚ะธ ะบะพะด ัั‚ะฐั‚ัƒััƒ HTTP ยซCREATEDยป `201`. + +ะ’ะพะดะฝะพั‡ะฐั ะฒะธ ะฒัะต ะพะดะฝะพ ั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะทะผะพะณัƒ ั„ั–ะปัŒั‚ั€ัƒะฒะฐั‚ะธ ั‚ะฐ ะฟะตั€ะตั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฟะพะฒะตั€ะฝะตะฝั– ะดะฐะฝั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `response_model`. + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `Response`. + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `Response` { #use-a-response-parameter } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `Response` ัƒ ัะฒะพั—ะน ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ (ั‚ะฐะบ ัะฐะผะพ, ัะบ ะดะปั ะบัƒะบั– ั‚ะฐ ะทะฐะณะพะปะพะฒะบั–ะฒ). + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `status_code` ัƒ ั†ัŒะพะผัƒ *ั‚ะธะผั‡ะฐัะพะฒะพะผัƒ* ะพะฑ'ั”ะบั‚ั– ะฒั–ะดะฟะพะฒั–ะดั–. + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ะฟะพั‚ั€ั–ะฑะฝะธะน ะพะฑ'ั”ะบั‚, ัะบ ะทะฐะทะฒะธั‡ะฐะน (`dict`, ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ). + +ะ† ัะบั‰ะพ ะฒะธ ะพะณะพะปะพัะธะปะธ `response_model`, ะฒั–ะฝ ัƒัะต ะพะดะฝะพ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะธะน ะดะปั ั„ั–ะปัŒั‚ั€ะฐั†ั–ั— ั‚ะฐ ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฟะพะฒะตั€ะฝะตะฝะพะณะพ ะพะฑ'ั”ะบั‚ะฐ. + +**FastAPI** ะฒะธะบะพั€ะธัั‚ะฐั” ั†ะตะน *ั‚ะธะผั‡ะฐัะพะฒะธะน* ะพะฑ'ั”ะบั‚ ะฒั–ะดะฟะพะฒั–ะดั–, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ะบะพะด ัั‚ะฐั‚ัƒััƒ (ะฐ ั‚ะฐะบะพะถ ะบัƒะบั– ั‚ะฐ ะทะฐะณะพะปะพะฒะบะธ), ั– ะฟะพะผั–ัั‚ะธั‚ัŒ ั—ั… ัƒ ั„ั–ะฝะฐะปัŒะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะฟะพะฒะตั€ะฝัƒั‚ะต ะฒะฐะผะธ ะทะฝะฐั‡ะตะฝะฝั, ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `response_model`. + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `Response` ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ั– ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ั‚ะฐะผ ะบะพะด ัั‚ะฐั‚ัƒััƒ. ะะปะต ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–: ะพัั‚ะฐะฝะฝั” ะฒัั‚ะฐะฝะพะฒะปะตะฝะต ะทะฝะฐั‡ะตะฝะฝั ะผะฐั‚ะธะผะต ะฟั€ั–ะพั€ะธั‚ะตั‚. diff --git a/docs/uk/docs/advanced/response-cookies.md b/docs/uk/docs/advanced/response-cookies.md new file mode 100644 index 0000000000..826602e708 --- /dev/null +++ b/docs/uk/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# ะšัƒะบั– ัƒ ะฒั–ะดะฟะพะฒั–ะดั– { #response-cookies } + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `Response` { #use-a-response-parameter } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `Response` ัƒ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะบัƒะบั– ะฒ ั†ัŒะพะผัƒ *ั‚ะธะผั‡ะฐัะพะฒะพะผัƒ* ะพะฑ'ั”ะบั‚ั– ะฒั–ะดะฟะพะฒั–ะดั–. + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ะฟะพั‚ั€ั–ะฑะฝะธะน ะพะฑ'ั”ะบั‚, ัะบ ะทะฐะทะฒะธั‡ะฐะน (ะฝะฐะฟั€ะธะบะปะฐะด, `dict`, ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ). + +ะ† ัะบั‰ะพ ะฒะธ ะพะณะพะปะพัะธะปะธ `response_model`, ะฒั–ะฝ ัƒัะต ะพะดะฝะพ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะธะน ะดะปั ั„ั–ะปัŒั‚ั€ะฐั†ั–ั— ั‚ะฐ ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะพะฑ'ั”ะบั‚ะฐ, ัะบะธะน ะฒะธ ะฟะพะฒะตั€ะฝัƒะปะธ. + +**FastAPI** ะฒะธะบะพั€ะธัั‚ะฐั” ั†ัŽ *ั‚ะธะผั‡ะฐัะพะฒัƒ* ะฒั–ะดะฟะพะฒั–ะดัŒ, ั‰ะพะฑ ะฒะธั‚ัะณะฝัƒั‚ะธ ะบัƒะบั– (ะฐ ั‚ะฐะบะพะถ ะทะฐะณะพะปะพะฒะบะธ ั‚ะฐ ะบะพะด ัั‚ะฐั‚ัƒััƒ) ั– ะฟะพะผั–ัั‚ะธั‚ัŒ ั—ั… ัƒ ั„ั–ะฝะฐะปัŒะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะฒะธ ะฟะพะฒะตั€ะฝัƒะปะธ, ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝะต ะฑัƒะดัŒ-ัะบะพัŽ `response_model`. + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `Response` ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ั– ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒ ะฝะธั… ะบัƒะบั– (ั– ะทะฐะณะพะปะพะฒะบะธ). + +## ะŸะพะฒะตั€ั‚ะฐะนั‚ะต `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #return-a-response-directly } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะบัƒะบั–, ะฟะพะฒะตั€ั‚ะฐัŽั‡ะธ `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั–. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ, ัะบ ะพะฟะธัะฐะฝะพ ะฒ [ะŸะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ](response-directly.md){.internal-link target=_blank}. + +ะŸะพั‚ั–ะผ ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ัƒ ะฝัŒะพะผัƒ ะบัƒะบั– ั– ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะนะพะณะพ: + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ะฐ `Response`, FastAPI ะฟะพะฒะตั€ะฝะต ั—ั— ะฝะฐะฟั€ัะผัƒ. + +ะขะพะผัƒ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะฒะฐัˆั– ะดะฐะฝั– ะผะฐัŽั‚ัŒ ะบะพั€ะตะบั‚ะฝะธะน ั‚ะธะฟ. ะะฐะฟั€ะธะบะปะฐะด, ััƒะผั–ัะฝั– ะท JSON, ัะบั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `JSONResponse`. + +ะ ั‚ะฐะบะพะถ ั‰ะพ ะฒะธ ะฝะต ะฝะฐะดัะธะปะฐั”ั‚ะต ะดะฐะฝั–, ัะบั– ะผะฐะปะธ ะฑ ะฑัƒั‚ะธ ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `response_model`. + +/// + +### ะ‘ั–ะปัŒัˆะต ั–ะฝั„ะพั€ะผะฐั†ั–ั— { #more-info } + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.responses import Response` ะฐะฑะพ `from starlette.responses import JSONResponse`. + +**FastAPI** ะฝะฐะดะฐั” ั‚ั– ัะฐะผั– `starlette.responses` ัะบ `fastapi.responses` ะปะธัˆะต ะดะปั ะทั€ัƒั‡ะฝะพัั‚ั– ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฝะฐะดั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +ะ† ะพัะบั–ะปัŒะบะธ `Response` ั‡ะฐัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั– ะบัƒะบั–, **FastAPI** ั‚ะฐะบะพะถ ะฝะฐะดะฐั” ะนะพะณะพ ัะบ `fastapi.Response`. + +/// + +ะฉะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ะฒัั– ะดะพัั‚ัƒะฟะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ะฐ ะพะฟั†ั–ั—, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะฒ Starlette. diff --git a/docs/uk/docs/advanced/response-directly.md b/docs/uk/docs/advanced/response-directly.md new file mode 100644 index 0000000000..7396ab7565 --- /dev/null +++ b/docs/uk/docs/advanced/response-directly.md @@ -0,0 +1,65 @@ +# ะŸะพะฒะตั€ะฝะตะฝะฝั Response ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #return-a-response-directly } + +ะšะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ FastAPI, ะทะฐะทะฒะธั‡ะฐะน ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะท ะฝะตั— ะฑัƒะดัŒ-ัะบั– ะดะฐะฝั–: `dict`, `list`, ะผะพะดะตะปัŒ Pydantic, ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ. + +ะขะธะฟะพะฒะพ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ัŒ ั†ะต ะทะฝะฐั‡ะตะฝะฝั ะฟะพะฒะตั€ะฝะตะฝะฝั ะฝะฐ JSON, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `jsonable_encoder`, ะพะฟะธัะฐะฝะธะน ัƒ [ะกัƒะผั–ัะฝะพะผัƒ ะท JSON ะบะพะดะตั€ั–](../tutorial/encoder.md){.internal-link target=_blank}. + +ะŸะพั‚ั–ะผ, ะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธ, ะฒั–ะฝ ะฟะพะผั–ัั‚ะธั‚ัŒ ั†ั– ะดะฐะฝั–, ััƒะผั–ัะฝั– ะท JSON (ะฝะฐะฟั€ะธะบะปะฐะด, `dict`), ัƒ `JSONResponse`, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะดะปั ะฝะฐะดัะธะปะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั– ะบะปั–ั”ะฝั‚ัƒ. + +ะะปะต ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ `JSONResponse` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ะฒะฐัˆะธั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะธะผ, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฐะฑะพ ะบัƒะบั–. + +## ะŸะพะฒะตั€ะฝะตะฝะฝั `Response` { #return-a-response } + +ะะฐัะฟั€ะฐะฒะดั– ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะฑัƒะดัŒ-ัะบะธะน `Response` ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธะน ะนะพะณะพ ะฟั–ะดะบะปะฐั. + +/// tip | ะŸะพั€ะฐะดะฐ + +`JSONResponse` ัะฐะผ ั” ะฟั–ะดะบะปะฐัะพะผ `Response`. + +/// + +ะ† ะบะพะปะธ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response`, FastAPI ะฟะตั€ะตะดะฐัั‚ัŒ ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +ะ’ั–ะฝ ะฝะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธะผะต ะถะพะดะฝะธั… ะฟะตั€ะตั‚ะฒะพั€ะตะฝัŒ ะดะฐะฝะธั… ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะผะพะดะตะปะตะน Pydantic, ะฝะต ะฟะตั€ะตั‚ะฒะพั€ัŽะฒะฐั‚ะธะผะต ะฒะผั–ัั‚ ะฝะฐ ะฑัƒะดัŒ-ัะบะธะน ั‚ะธะฟ ั‚ะพั‰ะพ. + +ะฆะต ะดะฐั” ะฒะฐะผ ะฑะฐะณะฐั‚ะพ ะณะฝัƒั‡ะบะพัั‚ั–. ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ั‚ะธะฟะธ ะดะฐะฝะธั…, ะฟะตั€ะตะฟะธััƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ะพะณะพะปะพัˆะตะฝะฝั ะฐะฑะพ ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `jsonable_encoder` ัƒ `Response` { #using-the-jsonable-encoder-in-a-response } + +ะžัะบั–ะปัŒะบะธ FastAPI ะฝะต ะฒะฝะพัะธั‚ัŒ ะทะผั–ะฝ ัƒ `Response`, ัะบะธะน ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะฟะตะฒะฝะธั‚ะธัั, ั‰ะพ ะนะพะณะพ ะฒะผั–ัั‚ ะณะพั‚ะพะฒะธะน. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฟะพะบะปะฐัั‚ะธ ะผะพะดะตะปัŒ Pydantic ัƒ `JSONResponse`, ะฝะต ะฟะตั€ะตั‚ะฒะพั€ะธะฒัˆะธ ั—ั— ัะฟะพั‡ะฐั‚ะบัƒ ะฝะฐ `dict` ะท ัƒัั–ะผะฐ ั‚ะธะฟะฐะผะธ ะดะฐะฝะธั… (ัะบ-ะพั‚ `datetime`, `UUID` ั‚ะพั‰ะพ), ะฟะตั€ะตั‚ะฒะพั€ะตะฝะธะผะธ ะฝะฐ ั‚ะธะฟะธ, ััƒะผั–ัะฝั– ะท JSON. + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `jsonable_encoder`, ั‰ะพะฑ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ะฒะฐัˆั– ะดะฐะฝั– ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ะฟะตั€ะตะดะฐั‚ะธ ั—ั… ัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ: + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.responses import JSONResponse`. + +FastAPI ะฝะฐะดะฐั” ั‚ั– ัะฐะผั– `starlette.responses` ัะบ `fastapi.responses` ะฟั€ะพัั‚ะพ ัะบ ะทั€ัƒั‡ะฝั–ัั‚ัŒ ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… `Response` ะฟะพั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +/// + +## ะŸะพะฒะตั€ะฝะตะฝะฝั ะฒะปะฐัะฝะพะณะพ `Response` { #returning-a-custom-response } + +ะะฐะฒะตะดะตะฝะธะน ะฒะธั‰ะต ะฟั€ะธะบะปะฐะด ะฟะพะบะฐะทัƒั” ะฒัั– ะฝะตะพะฑั…ั–ะดะฝั– ั‡ะฐัั‚ะธะฝะธ, ะฐะปะต ะฒั–ะฝ ั‰ะต ะฝะต ะดัƒะถะต ะบะพั€ะธัะฝะธะน, ะฐะดะถะต ะฒะธ ะผะพะณะปะธ ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ะฝัƒั‚ะธ `item` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ั– FastAPI ะฟะพะผั–ัั‚ะธะฒ ะฑะธ ะนะพะณะพ ัƒ `JSONResponse`, ะฟะตั€ะตั‚ะฒะพั€ะธะฒัˆะธ ะฝะฐ `dict` ั‚ะพั‰ะพ. ะฃัะต ั†ะต ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. + +ะขะตะฟะตั€ ะฟะพะดะธะฒั–ะผะพัั, ัะบ ั†ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ, ั‰ะพะฑ ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฒะปะฐัะฝัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ. + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ XML. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะผั–ัั‚ะธั‚ะธ ัะฒั–ะน ะฒะผั–ัั‚ XML ัƒ ัั‚ั€ะพะบัƒ, ะฟะพะผั–ัั‚ะธั‚ะธ ั†ะต ะฒ `Response` ั– ะฟะพะฒะตั€ะฝัƒั‚ะธ: + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## ะŸั€ะธะผั–ั‚ะบะธ { #notes } + +ะšะพะปะธ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะนะพะณะพ ะดะฐะฝั– ะฝะต ะฟะตั€ะตะฒั–ั€ััŽั‚ัŒัั, ะฝะต ะฟะตั€ะตั‚ะฒะพั€ัŽัŽั‚ัŒัั (ัะตั€ั–ะฐะปั–ะทัƒัŽั‚ัŒัั) ั– ะฝะต ะดะพะบัƒะผะตะฝั‚ัƒัŽั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ. + +ะะปะต ะฒะธ ะฒัะต ั‰ะต ะผะพะถะตั‚ะต ะทะฐะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ ั†ะต, ัะบ ะพะฟะธัะฐะฝะพ ะฒ [ะ”ะพะดะฐั‚ะบะพะฒะธั… ะฒั–ะดะฟะพะฒั–ะดัั… ะฒ OpenAPI](additional-responses.md){.internal-link target=_blank}. + +ะฃ ะฟะพะดะฐะปัŒัˆะธั… ั€ะพะทะดั–ะปะฐั… ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ/ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั†ั– ะฒะปะฐัะฝั– `Response`, ะฒะพะดะฝะพั‡ะฐั ะทะฑะตั€ั–ะณะฐัŽั‡ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั…, ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ั‚ะพั‰ะพ. diff --git a/docs/uk/docs/advanced/response-headers.md b/docs/uk/docs/advanced/response-headers.md new file mode 100644 index 0000000000..1c9d4e6773 --- /dev/null +++ b/docs/uk/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# ะ—ะฐะณะพะปะพะฒะบะธ ะฒั–ะดะฟะพะฒั–ะดั– { #response-headers } + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `Response` { #use-a-response-parameter } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `Response` ัƒ ะฒะฐัˆั–ะน ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ (ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะดะปั ะบัƒะบั–). + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะทะฐะณะพะปะพะฒะบะธ ะฒ ั†ัŒะพะผัƒ *ั‚ะธะผั‡ะฐัะพะฒะพะผัƒ* ะพะฑสผั”ะบั‚ั– ะฒั–ะดะฟะพะฒั–ะดั–. + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +ะ”ะฐะปั– ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ะฟะพั‚ั€ั–ะฑะฝะธะน ะพะฑสผั”ะบั‚, ัะบ ะทะฐะทะฒะธั‡ะฐะน (ะฝะฐะฟั€ะธะบะปะฐะด, `dict`, ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั… ั‚ะพั‰ะพ). + +ะฏะบั‰ะพ ะฒะธ ะพะณะพะปะพัะธะปะธ `response_model`, ะนะพะณะพ ะฒัะต ะพะดะฝะพ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะดะปั ั„ั–ะปัŒั‚ั€ะฐั†ั–ั— ั‚ะฐ ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฟะพะฒะตั€ะฝะตะฝะพะณะพ ะพะฑสผั”ะบั‚ะฐ. + +FastAPI ะฒะธะบะพั€ะธัั‚ะฐั” ั†ะตะน *ั‚ะธะผั‡ะฐัะพะฒะธะน* ะพะฑสผั”ะบั‚ ะฒั–ะดะฟะพะฒั–ะดั–, ั‰ะพะฑ ะฒะธั‚ัะณั‚ะธ ะทะฐะณะพะปะพะฒะบะธ (ะฐ ั‚ะฐะบะพะถ ะบัƒะบั– ั‚ะฐ ะบะพะด ัั‚ะฐั‚ัƒััƒ) ั– ะฟะพะผั–ัั‚ะธั‚ัŒ ั—ั… ัƒ ะบั–ะฝั†ะตะฒัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ัะบะฐ ะผั–ัั‚ะธั‚ะธะผะต ะฟะพะฒะตั€ะฝัƒั‚ะต ะฒะฐะผะธ ะทะฝะฐั‡ะตะฝะฝั, ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝะต ะฑัƒะดัŒ-ัะบะธะผ `response_model`. + +ะขะฐะบะพะถ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `Response` ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ั– ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒ ะฝะธั… ะทะฐะณะพะปะพะฒะบะธ (ั‚ะฐ ะบัƒะบั–). + +## ะŸะพะฒะตั€ะฝั–ั‚ัŒ `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #return-a-response-directly } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะดะพะดะฐะฒะฐั‚ะธ ะทะฐะณะพะปะพะฒะบะธ, ะบะพะปะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Response` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ัะบ ะพะฟะธัะฐะฝะพ ะฒ [ะŸะพะฒะตั€ะฝะตะฝะฝั Response ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ](response-directly.md){.internal-link target=_blank}, ั– ะฟะตั€ะตะดะฐะนั‚ะต ะทะฐะณะพะปะพะฒะบะธ ัะบ ะดะพะดะฐั‚ะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.responses import Response` ะฐะฑะพ `from starlette.responses import JSONResponse`. + +FastAPI ะฝะฐะดะฐั” ั‚ั– ัะฐะผั– `starlette.responses` ัะบ `fastapi.responses` ะฟั€ะพัั‚ะพ ะดะปั ะทั€ัƒั‡ะฝะพัั‚ั– ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… ั‚ะธะฟั–ะฒ ะฒั–ะดะฟะพะฒั–ะดะตะน ะฟะพั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +ะžัะบั–ะปัŒะบะธ `Response` ั‡ะฐัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะณะพะปะพะฒะบั–ะฒ ั– ะบัƒะบั–, FastAPI ั‚ะฐะบะพะถ ะฝะฐะดะฐั” ะนะพะณะพ ัะบ `fastapi.Response`. + +/// + +## ะ’ะปะฐัะฝั– ะทะฐะณะพะปะพะฒะบะธ { #custom-headers } + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะฒะปะฐัะฝั– ะทะฐะบั€ะธั‚ั– ะทะฐะณะพะปะพะฒะบะธ ะผะพะถะฝะฐ ะดะพะดะฐะฒะฐั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟั€ะตั„ั–ะบัะฐ `X-`. + +ะะปะต ัะบั‰ะพ ัƒ ะฒะฐั ั” ะฒะปะฐัะฝั– ะทะฐะณะพะปะพะฒะบะธ, ัะบั– ะบะปั–ั”ะฝั‚ ัƒ ะฑั€ะฐัƒะทะตั€ั– ะผะฐั” ะฑะฐั‡ะธั‚ะธ, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะดะพะดะฐั‚ะธ ั—ั… ัƒ ะฒะฐัˆัƒ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัŽ CORS (ะดะพะบะปะฐะดะฝั–ัˆะต ะฒ [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟะฐั€ะฐะผะตั‚ั€ `expose_headers`, ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝะธะน ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Starlette ั‰ะพะดะพ CORS. diff --git a/docs/uk/docs/advanced/security/http-basic-auth.md b/docs/uk/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000..e0578772d3 --- /dev/null +++ b/docs/uk/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +ะ”ะปั ะฝะฐะนะฟั€ะพัั‚ั–ัˆะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ HTTP Basic Auth. + +ะฃ HTTP Basic Auth ะทะฐัั‚ะพััƒะฝะพะบ ะพั‡ั–ะบัƒั” ะทะฐะณะพะปะพะฒะพะบ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ. + +ะฏะบั‰ะพ ะฒั–ะฝ ะนะพะณะพ ะฝะต ะพั‚ั€ะธะผัƒั”, ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั ะฟะพะผะธะปะบะฐ HTTP 401 ยซUnauthorizedยป. + +ะ† ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `Basic` ั‚ะฐ ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `realm`. + +ะฆะต ะบะฐะถะต ะฑั€ะฐัƒะทะตั€ัƒ ะฟะพะบะฐะทะฐั‚ะธ ะฒะฑัƒะดะพะฒะฐะฝัƒ ะฟั–ะดัะบะฐะทะบัƒ ะดะปั ะฒะฒะตะดะตะฝะฝั ั–ะผะตะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปั. + +ะŸะพั‚ั–ะผ, ะบะพะปะธ ะฒะธ ะฒะฒะตะดะตั‚ะต ั†ะต ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ, ะฑั€ะฐัƒะทะตั€ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฝะฐะดั–ัˆะปะต ั—ั… ัƒ ะทะฐะณะพะปะพะฒะบัƒ. + +## ะŸั€ะพัั‚ะธะน HTTP Basic Auth { #simple-http-basic-auth } + +- ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `HTTPBasic` ั– `HTTPBasicCredentials`. +- ะกั‚ะฒะพั€ั–ั‚ัŒ ยซ`security` schemeยป ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `HTTPBasic`. +- ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ั†ะตะน `security` ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒ ะฒะฐัˆั–ะน ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. +- ะ’ั–ะฝ ะฟะพะฒะตั€ั‚ะฐั” ะพะฑ'ั”ะบั‚ ั‚ะธะฟัƒ `HTTPBasicCredentials`: + - ะ’ั–ะฝ ะผั–ัั‚ะธั‚ัŒ ะฝะฐะดั–ัะปะฐะฝั– `username` ั– `password`. + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +ะšะพะปะธ ะฒะธ ัะฟั€ะพะฑัƒั”ั‚ะต ะฒั–ะดะบั€ะธั‚ะธ URL ะฒะฟะตั€ัˆะต (ะฐะฑะพ ะฝะฐั‚ะธัะฝะตั‚ะต ะบะฝะพะฟะบัƒ ยซExecuteยป ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—), ะฑั€ะฐัƒะทะตั€ ะฟะพะฟั€ะพัะธั‚ัŒ ะฒะฐั ะฒะฒะตัั‚ะธ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ: + + + +## ะŸะตั€ะตะฒั–ั€ั‚ะต ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #check-the-username } + +ะžััŒ ะฑั–ะปัŒัˆ ะฟะพะฒะฝะธะน ะฟั€ะธะบะปะฐะด. + +ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ะทะฐะปะตะถะฝั–ัั‚ัŒ, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‡ะธ ะฟั€ะฐะฒะธะปัŒะฝั– ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน ะผะพะดัƒะปัŒ Python `secrets`, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ. + +`secrets.compare_digest()` ะฟะพะฒะธะฝะตะฝ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ `bytes` ะฐะฑะพ `str`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะปะธัˆะต ASCII-ัะธะผะฒะพะปะธ (ะฐะฝะณะปั–ะนััŒะบั–), ั†ะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒั–ะฝ ะฝะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะท ัะธะผะฒะพะปะฐะผะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ `รก`, ัะบ ัƒ `Sebastiรกn`. + +ะฉะพะฑ ั†ะต ะพะฑั–ะนั‚ะธ, ะผะธ ัะฟะพั‡ะฐั‚ะบัƒ ะฟะตั€ะตั‚ะฒะพั€ัŽั”ะผะพ `username` ั– `password` ัƒ `bytes`, ะบะพะดัƒะฒะฐะฒัˆะธ ั—ั… ัƒ UTF-8. + +ะŸะพั‚ั–ะผ ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `secrets.compare_digest()`, ั‰ะพะฑ ัƒะฟะตะฒะฝะธั‚ะธัั, ั‰ะพ `credentials.username` ะดะพั€ั–ะฒะฝัŽั” `"stanleyjobson"`, ะฐ `credentials.password` ะดะพั€ั–ะฒะฝัŽั” `"swordfish"`. + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +ะฆะต ะฑัƒะปะพ ะฑ ะฟะพะดั–ะฑะฝะพ ะดะพ: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Return some error + ... +``` + +ะะปะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `secrets.compare_digest()`, ั†ะต ะฑัƒะดะต ะทะฐั…ะธั‰ะตะฝะพ ะฒั–ะด ั‚ะธะฟัƒ ะฐั‚ะฐะบ, ั‰ะพ ะฝะฐะทะธะฒะฐัŽั‚ัŒัั ยซะฐั‚ะฐะบะธ ะทะฐ ั‡ะฐัะพะผยป (timing attacks). + +### ะั‚ะฐะบะธ ะทะฐ ั‡ะฐัะพะผ { #timing-attacks } + +ะฉะพ ั‚ะฐะบะต ยซะฐั‚ะฐะบะฐ ะทะฐ ั‡ะฐัะพะผยป? + +ะฃัะฒั–ะผะพ, ั‰ะพ ะทะปะพะฒะผะธัะฝะธะบะธ ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะฒะณะฐะดะฐั‚ะธ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ. + +ะ’ะพะฝะธ ะฝะฐะดัะธะปะฐัŽั‚ัŒ ะทะฐะฟะธั‚ ะท ั–ะผ'ัะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ `johndoe` ั‚ะฐ ะฟะฐั€ะพะปะตะผ `love123`. + +ะขะพะดั– Python-ะบะพะด ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฑัƒะดะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะธะน ั‡ะพะผัƒััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +ะะปะต ะฒ ั‚ะพะน ะผะพะผะตะฝั‚, ะบะพะปะธ Python ะฟะพั€ั–ะฒะฝัŽั” ะฟะตั€ัˆัƒ `j` ัƒ `johndoe` ะท ะฟะตั€ัˆะพัŽ `s` ัƒ `stanleyjobson`, ะฒั–ะฝ ะฟะพะฒะตั€ะฝะต `False`, ั‚ะพะผัƒ ั‰ะพ ะฒะถะต ะทะฝะฐั”, ั‰ะพ ั†ั– ะดะฒั– ัั‚ั€ะพะบะธ ะฝะต ะพะดะฝะฐะบะพะฒั–, ยซะฝะตะผะฐั” ัะตะฝััƒ ะฒะธั‚ั€ะฐั‡ะฐั‚ะธ ะพะฑั‡ะธัะปะตะฝะฝั ะฝะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั ั€ะตัˆั‚ะธ ะปั–ั‚ะตั€ยป. ะ† ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ัะบะฐะถะต ยซะะตะฒั–ั€ะฝั– ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฐะฑะพ ะฟะฐั€ะพะปัŒยป. + +ะ ะฟะพั‚ั–ะผ ะทะปะพะฒะผะธัะฝะธะบะธ ัะฟั€ะพะฑัƒัŽั‚ัŒ ะท ั–ะผ'ัะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ `stanleyjobsox` ั– ะฟะฐั€ะพะปะตะผ `love123`. + +ะ† ะฒะฐัˆ ะบะพะด ะทะฐัั‚ะพััƒะฝะบัƒ ะทั€ะพะฑะธั‚ัŒ ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python ะดะพะฒะตะดะตั‚ัŒัั ะฟะพั€ั–ะฒะฝัั‚ะธ ะฒะตััŒ `stanleyjobso` ัƒ ะพะฑะพั… `stanleyjobsox` ั– `stanleyjobson`, ะฟะตั€ัˆ ะฝั–ะถ ะทั€ะพะทัƒะผั–ั‚ะธ, ั‰ะพ ัั‚ั€ะพะบะธ ั€ั–ะทะฝั–. ะขะพะผัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ ยซะะตะฒั–ั€ะฝั– ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฐะฑะพ ะฟะฐั€ะพะปัŒยป ะทะฐะนะผะต ะฝะฐ ะบั–ะปัŒะบะฐ ะผั–ะบั€ะพัะตะบัƒะฝะด ะดะพะฒัˆะต. + +#### ะงะฐั ะฒั–ะดะฟะพะฒั–ะดั– ะดะพะฟะพะผะฐะณะฐั” ะทะปะพะฒะผะธัะฝะธะบะฐะผ { #the-time-to-answer-helps-the-attackers } + +ะฃ ั†ะตะน ะผะพะผะตะฝั‚, ะฟะพะผั–ั‚ะธะฒัˆะธ, ั‰ะพ ัะตั€ะฒะตั€ ะฒะธั‚ั€ะฐั‚ะธะฒ ะฝะฐ ะบั–ะปัŒะบะฐ ะผั–ะบั€ะพัะตะบัƒะฝะด ะฑั–ะปัŒัˆะต, ั‰ะพะฑ ะฝะฐะดั–ัะปะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ยซะะตะฒั–ั€ะฝั– ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฐะฑะพ ะฟะฐั€ะพะปัŒยป, ะทะปะพะฒะผะธัะฝะธะบะธ ะทะฝะฐั‚ะธะผัƒั‚ัŒ, ั‰ะพ ะฒะพะฝะธ ั‰ะพััŒ ะฒะณะฐะดะฐะปะธ, ะดะตัะบั– ะฟะพั‡ะฐั‚ะบะพะฒั– ะปั–ั‚ะตั€ะธ ะฟั€ะฐะฒะธะปัŒะฝั–. + +ะ† ั‚ะพะดั– ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ะทะฝะพะฒัƒ, ะทะฝะฐัŽั‡ะธ, ั‰ะพ ั†ะต, ะนะผะพะฒั–ั€ะฝะพ, ั‰ะพััŒ ะฑั–ะปัŒัˆ ัั…ะพะถะต ะฝะฐ `stanleyjobsox`, ะฝั–ะถ ะฝะฐ `johndoe`. + +#### ยซะŸั€ะพั„ะตัั–ะนะฝะฐยป ะฐั‚ะฐะบะฐ { #a-professional-attack } + +ะ—ะฒั–ัะฝะพ, ะทะปะพะฒะผะธัะฝะธะบะธ ะฝะต ั€ะพะฑะธั‚ะธะผัƒั‚ัŒ ัƒัะต ั†ะต ะฒั€ัƒั‡ะฝัƒ, ะฒะพะฝะธ ะฝะฐะฟะธัˆัƒั‚ัŒ ะฟั€ะพะณั€ะฐะผัƒ, ะผะพะถะปะธะฒะพ ะท ั‚ะธััั‡ะฐะผะธ ะฐะฑะพ ะผั–ะปัŒะนะพะฝะฐะผะธ ะฟะตั€ะตะฒั–ั€ะพะบ ะทะฐ ัะตะบัƒะฝะดัƒ. ะ† ะฒะพะฝะธ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผัƒั‚ัŒ ะปะธัˆะต ะฟะพ ะพะดะฝั–ะน ะฟั€ะฐะฒะธะปัŒะฝั–ะน ะปั–ั‚ะตั€ั– ะทะฐ ั€ะฐะท. + +ะะปะต ั‚ะฐะบ ะทะฐ ะบั–ะปัŒะบะฐ ั…ะฒะธะปะธะฝ ะฐะฑะพ ะณะพะดะธะฝ ะทะปะพะฒะผะธัะฝะธะบะธ ะฒะณะฐะดะฐัŽั‚ัŒ ะฟั€ะฐะฒะธะปัŒะฝั– ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ, ยซะทะฐ ะดะพะฟะพะผะพะณะพัŽยป ะฝะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‡ะฐั, ะฟะพั‚ั€ั–ะฑะฝะธะน ะดะปั ะฒั–ะดะฟะพะฒั–ะดั–. + +#### ะ’ะธะฟั€ะฐะฒั‚ะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } + +ะะปะต ะฒ ะฝะฐัˆะพะผัƒ ะบะพะดั– ะผะธ ะฝะฐัะฟั€ะฐะฒะดั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `secrets.compare_digest()`. + +ะšะพั€ะพั‚ะบะพ, ะฒั–ะฝ ะฒะธั‚ั€ะฐั‡ะฐั” ะพะดะฝะฐะบะพะฒะธะน ั‡ะฐั ะฝะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั `stanleyjobsox` ะทั– `stanleyjobson`, ัะบ ั– ะฝะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั `johndoe` ะทั– `stanleyjobson`. ะ† ั‚ะฐะบ ัะฐะผะพ ะดะปั ะฟะฐั€ะพะปั. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `secrets.compare_digest()` ัƒ ะบะพะดั– ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฒั–ะฝ ะฑัƒะดะต ะทะฐั…ะธั‰ะตะฝะธะน ะฒั–ะด ัƒััŒะพะณะพ ั†ัŒะพะณะพ ะบะปะฐััƒ ะฐั‚ะฐะบ ะฑะตะทะฟะตะบะธ. + +### ะŸะพะฒะตั€ะฝั–ั‚ัŒ ะฟะพะผะธะปะบัƒ { #return-the-error } + +ะŸั–ัะปั ะฒะธัะฒะปะตะฝะฝั, ั‰ะพ ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั– ะฝะตะฟั€ะฐะฒะธะปัŒะฝั–, ะฟะพะฒะตั€ะฝั–ั‚ัŒ `HTTPException` ะท ะบะพะดะพะผ ัั‚ะฐั‚ัƒััƒ 401 (ั‚ะฐะบะธะน ัะฐะผะธะน ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั, ะบะพะปะธ ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั– ะฝะต ะฝะฐะดะฐะฝั–) ั– ะดะพะดะฐะนั‚ะต ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate`, ั‰ะพะฑ ะฑั€ะฐัƒะทะตั€ ะทะฝะพะฒัƒ ะฟะพะบะฐะทะฐะฒ ะฟั–ะดัะบะฐะทะบัƒ ะฒั…ะพะดัƒ: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/uk/docs/advanced/security/index.md b/docs/uk/docs/advanced/security/index.md new file mode 100644 index 0000000000..a3479794f8 --- /dev/null +++ b/docs/uk/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# ะŸั€ะพััƒะฝัƒั‚ะฐ ะฑะตะทะฟะตะบะฐ { #advanced-security } + +## ะ”ะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– { #additional-features } + +ะ„ ะบั–ะปัŒะบะฐ ะดะพะดะฐั‚ะบะพะฒะธั… ะผะพะถะปะธะฒะพัั‚ะตะน ะดะปั ั€ะพะฑะพั‚ะธ ะท ะฑะตะทะฟะตะบะพัŽ, ะพะบั€ั–ะผ ั‚ะธั…, ั‰ะพ ั€ะพะทะณะปัะฝัƒั‚ั– ะฒ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ: ะ‘ะตะทะฟะตะบะฐ](../../tutorial/security/index.md){.internal-link target=_blank}. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐัั‚ัƒะฟะฝั– ั€ะพะทะดั–ะปะธ ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ ยซะฟั€ะพััƒะฝัƒั‚ั–ยป. + +ะ† ะผะพะถะปะธะฒะพ, ั‰ะพ ะดะปั ะฒะฐัˆะพะณะพ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั€ั–ัˆะตะฝะฝั ั” ะฒ ะพะดะฝะพะผัƒ ะท ะฝะธั…. + +/// + +## ะกะฟะตั€ัˆัƒ ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ { #read-the-tutorial-first } + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ะฟะตั€ะตะดะฑะฐั‡ะฐั”ั‚ัŒัั, ั‰ะพ ะฒะธ ะฒะถะต ะฟั€ะพั‡ะธั‚ะฐะปะธ ะพัะฝะพะฒะฝะธะน [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ: ะ‘ะตะทะฟะตะบะฐ](../../tutorial/security/index.md){.internal-link target=_blank}. + +ะฃัั– ะฒะพะฝะธ ะฑะฐะทัƒัŽั‚ัŒัั ะฝะฐ ั‚ะธั… ัะฐะผะธั… ะบะพะฝั†ะตะฟั†ั–ัั…, ะฐะปะต ะฝะฐะดะฐัŽั‚ัŒ ะดะตัะบั– ะดะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั–. diff --git a/docs/uk/docs/advanced/security/oauth2-scopes.md b/docs/uk/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000..34ef04a288 --- /dev/null +++ b/docs/uk/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 scopes { #oauth2-scopes } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ OAuth2 scopes ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท **FastAPI**, ะฒะพะฝะธ ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– ะดะปั ะฑะตะทัˆะพะฒะฝะพั— ั€ะพะฑะพั‚ะธ. + +ะฆะต ะดะพะทะฒะพะปะธั‚ัŒ ะผะฐั‚ะธ ะฑั–ะปัŒัˆ ะดะตั‚ะฐะปัŒะฝัƒ ัะธัั‚ะตะผัƒ ะดะพะทะฒะพะปั–ะฒ, ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะดะพ ัั‚ะฐะฝะดะฐั€ั‚ัƒ OAuth2, ั–ะฝั‚ะตะณั€ะพะฒะฐะฝัƒ ัƒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ OpenAPI (ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API). + +OAuth2 ะทั– scopes - ั†ะต ะผะตั…ะฐะฝั–ะทะผ, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฑะฐะณะฐั‚ะพ ะฒะตะปะธะบะธั… ะฟั€ะพะฒะฐะนะดะตั€ั–ะฒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—, ัะบ-ะพั‚ Facebook, Google, GitHub, Microsoft, X (Twitter) ั‚ะพั‰ะพ. ะ’ะพะฝะธ ะทะฐัั‚ะพัะพะฒัƒัŽั‚ัŒ ะนะพะณะพ, ั‰ะพะฑ ะฝะฐะดะฐะฒะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝั– ะดะพะทะฒะพะปะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐะผ ั– ะทะฐัั‚ะพััƒะฝะบะฐะผ. + +ะšะพะถะฝะพะณะพ ั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ยซlog in withยป Facebook, Google, GitHub, Microsoft, X (Twitter), ั†ะตะน ะทะฐัั‚ะพััƒะฝะพะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” OAuth2 ะทั– scopes. + +ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบ ะบะตั€ัƒะฒะฐั‚ะธ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั”ัŽ ั‚ะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั”ัŽ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะพะณะพ ะถ OAuth2 ะทั– scopes ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI**. + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฆะต ะฑั–ะปัŒัˆ-ะผะตะฝัˆ ะฟั€ะพััƒะฝัƒั‚ะธะน ั€ะพะทะดั–ะป. ะฏะบั‰ะพ ะฒะธ ั‚ั–ะปัŒะบะธ ะฟะพั‡ะธะฝะฐั”ั‚ะต, ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ะนะพะณะพ. + +ะ’ะฐะผ ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ะฟะพั‚ั€ั–ะฑะฝั– OAuth2 scopes, ะฒะธ ะผะพะถะตั‚ะต ะบะตั€ัƒะฒะฐั‚ะธ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั”ัŽ ั‚ะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั”ัŽ ะฑัƒะดัŒ-ัะบะธะผ ะทั€ัƒั‡ะฝะธะผ ัะฟะพัะพะฑะพะผ. + +ะะปะต OAuth2 ะทั– scopes ะผะพะถะฝะฐ ะณะฐั€ะฝะพ ั–ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ัƒ ะฒะฐัˆ API (ะท OpenAPI) ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API. + +ะ’ะพะดะฝะพั‡ะฐั ะฒะธ ะฒัะต ะพะดะฝะพ ะฟั€ะธะผัƒัˆัƒั”ั‚ะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ั†ั– scopes ะฐะฑะพ ะฑัƒะดัŒ-ัะบั– ั–ะฝัˆั– ะฒะธะผะพะณะธ ะฑะตะทะฟะตะบะธ/ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั— ั‚ะฐะบ, ัะบ ะฟะพั‚ั€ั–ะฑะฝะพ, ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–. + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… OAuth2 ะทั– scopes - ั†ะต ะฝะฐะดะผั–ั€ะฝั–ัั‚ัŒ. + +ะะปะต ัะบั‰ะพ ะฒะธ ะทะฝะฐั”ั‚ะต, ั‰ะพ ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ, ะฐะฑะพ ะฟั€ะพัั‚ะพ ั†ั–ะบะฐะฒะพ, ั‡ะธั‚ะฐะนั‚ะต ะดะฐะปั–. + +/// + +## OAuth2 scopes ั‚ะฐ OpenAPI { #oauth2-scopes-and-openapi } + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั OAuth2 ะฒะธะทะฝะฐั‡ะฐั” ยซscopesยป ัะบ ัะฟะธัะพะบ ัั‚ั€ะพะบ, ั€ะพะทะดั–ะปะตะฝะธั… ะฟั€ะพะฑั–ะปะฐะผะธ. + +ะ’ะผั–ัั‚ ะบะพะถะฝะพั— ะท ั†ะธั… ัั‚ั€ะพะบ ะผะพะถะต ะผะฐั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ั„ะพั€ะผะฐั‚, ะฐะปะต ะฝะต ะฟะพะฒะธะฝะตะฝ ะผั–ัั‚ะธั‚ะธ ะฟั€ะพะฑั–ะปั–ะฒ. + +ะฆั– scopes ะฟั€ะตะดัั‚ะฐะฒะปััŽั‚ัŒ ยซะดะพะทะฒะพะปะธยป. + +ะ’ OpenAPI (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API) ะฒะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะฐั‚ะธ ยซัั…ะตะผะธ ะฑะตะทะฟะตะบะธยป. + +ะšะพะปะธ ะพะดะฝะฐ ะท ั†ะธั… ัั…ะตะผ ะฑะตะทะฟะตะบะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” OAuth2, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ scopes. + +ะšะพะถะตะฝ ยซscopeยป - ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะฐ (ะฑะตะท ะฟั€ะพะฑั–ะปั–ะฒ). + +ะ—ะฐะทะฒะธั‡ะฐะน ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะบะพะฝะบั€ะตั‚ะฝะธั… ะดะพะทะฒะพะปั–ะฒ ะฑะตะทะฟะตะบะธ, ะฝะฐะฟั€ะธะบะปะฐะด: + +- `users:read` ะฐะฑะพ `users:write` - ะฟะพัˆะธั€ะตะฝั– ะฟั€ะธะบะปะฐะดะธ. +- `instagram_basic` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Facebook / Instagram. +- `https://www.googleapis.com/auth/drive` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Google. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ’ OAuth2 ยซscopeยป - ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะฐ, ั‰ะพ ะดะตะบะปะฐั€ัƒั” ะบะพะฝะบั€ะตั‚ะฝะธะน ะฟะพั‚ั€ั–ะฑะฝะธะน ะดะพะทะฒั–ะป. + +ะะต ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั, ั‡ะธ ะผั–ัั‚ะธั‚ัŒ ะฒะพะฝะฐ ั–ะฝัˆั– ัะธะผะฒะพะปะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ `:` ะฐะฑะพ ั‡ะธ ั†ะต URL. + +ะฆั– ะดะตั‚ะฐะปั– ัะฟะตั†ะธั„ั–ั‡ะฝั– ะดะปั ั€ะตะฐะปั–ะทะฐั†ั–ั—. + +ะ”ะปั OAuth2 ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะธ. + +/// + +## ะ—ะฐะณะฐะปัŒะฝะธะน ะพะณะปัะด { #global-view } + +ะกะฟะพั‡ะฐั‚ะบัƒ ัˆะฒะธะดะบะพ ะฟะพะดะธะฒั–ะผะพัั ะฝะฐ ั‡ะฐัั‚ะธะฝะธ, ั‰ะพ ะฒั–ะดั€ั–ะทะฝััŽั‚ัŒัั ะฒั–ะด ะฟั€ะธะบะปะฐะดั–ะฒ ัƒ ะณะพะปะพะฒะฝะพะผัƒ **ะะฐะฒั‡ะฐะปัŒะฝะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ - ะšะตั€ั–ะฒะฝะธั†ั‚ะฒั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ** ะดะปั [OAuth2 ะท ะฟะฐั€ะพะปะตะผ (ั– ั…ะตัˆัƒะฒะฐะฝะฝัะผ), Bearer ะท JWT-ั‚ะพะบะตะฝะฐะผะธ](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. ะขะตะฟะตั€ ั–ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ OAuth2 scopes: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +ะขะตะฟะตั€ ั€ะพะทะณะปัะฝัŒะผะพ ั†ั– ะทะผั–ะฝะธ ะบั€ะพะบ ะทะฐ ะบั€ะพะบะพะผ. + +## ะกั…ะตะผะฐ ะฑะตะทะฟะตะบะธ OAuth2 { #oauth2-security-scheme } + +ะŸะตั€ัˆะฐ ะทะผั–ะฝะฐ - ั‚ะตะฟะตั€ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ัั…ะตะผัƒ ะฑะตะทะฟะตะบะธ OAuth2 ะท ะดะฒะพะผะฐ ะดะพัั‚ัƒะฟะฝะธะผะธ scopes: `me` ั– `items`. + +ะŸะฐั€ะฐะผะตั‚ั€ `scopes` ะฟั€ะธะนะผะฐั” `dict`, ะดะต ะบะพะถะตะฝ scope - ั†ะต ะบะปัŽั‡, ะฐ ะพะฟะธั - ะทะฝะฐั‡ะตะฝะฝั: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +ะžัะบั–ะปัŒะบะธ ั‚ะตะฟะตั€ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ั†ั– scopes, ะฒะพะฝะธ ะทโ€™ัะฒะปัั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API, ะบะพะปะธ ะฒะธ ัƒะฒั–ะนะดะตั‚ะต/ะฐะฒั‚ะพั€ะธะทัƒั”ั‚ะตัั. + +ะ† ะฒะธ ะทะผะพะถะตั‚ะต ะพะฑั€ะฐั‚ะธ, ัะบั– scopes ะฝะฐะดะฐั‚ะธ ะดะพัั‚ัƒะฟ: `me` ั– `items`. + +ะฆะต ั‚ะพะน ัะฐะผะธะน ะผะตั…ะฐะฝั–ะทะผ, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั, ะบะพะปะธ ะฒะธ ะฝะฐะดะฐั”ั‚ะต ะดะพะทะฒะพะปะธ ะฟั–ะด ั‡ะฐั ะฒั…ะพะดัƒ ั‡ะตั€ะตะท Facebook, Google, GitHub ั‚ะพั‰ะพ: + + + +## JWT ั‚ะพะบะตะฝ ะทั– scopes { #jwt-token-with-scopes } + +ะขะตะฟะตั€ ะทะผั–ะฝั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ั‚ะพะบะตะฝะฐ, ั‰ะพะฑ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะทะฐะฟะธั‚ะฐะฝั– scopes. + +ะœะธ ะฒัะต ั‰ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ะพะน ัะฐะผะธะน `OAuth2PasswordRequestForm`. ะ’ั–ะฝ ะผั–ัั‚ะธั‚ัŒ ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `scopes` ะทั– `list` ะท `str`, ะฟะพ ะพะดะฝะพะผัƒ scope, ะพั‚ั€ะธะผะฐะฝะพะผัƒ ะฒ ะทะฐะฟะธั‚ั–. + +ะ† ะผะธ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ scopes ัะบ ั‡ะฐัั‚ะธะฝัƒ JWT ั‚ะพะบะตะฝะฐ. + +/// danger | ะžะฑะตั€ะตะถะฝะพ + +ะ”ะปั ะฟั€ะพัั‚ะพั‚ะธ ั‚ัƒั‚ ะผะธ ะฟั€ะพัั‚ะพ ะดะพะดะฐั”ะผะพ ะพั‚ั€ะธะผะฐะฝั– scopes ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะดะพ ั‚ะพะบะตะฝะฐ. + +ะะปะต ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, ะท ะผั–ั€ะบัƒะฒะฐะฝัŒ ะฑะตะทะฟะตะบะธ, ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ะดะพะดะฐั”ั‚ะต ะปะธัˆะต ั‚ั– scopes, ัะบั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะดั–ะนัะฝะพ ะผะพะถะต ะผะฐั‚ะธ, ะฐะฑะพ ั‚ั–, ั‰ะพ ะฒะธ ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒะธะทะฝะฐั‡ะธะปะธ. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## ะžะณะพะปะพัั–ั‚ัŒ scopes ะฒ ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ ั‚ะฐ ะทะฐะปะตะถะฝะพัั‚ัั… { #declare-scopes-in-path-operations-and-dependencies } + +ะขะตะฟะตั€ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ, ั‰ะพ ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ ะดะปั `/users/me/items/` ะฒะธะผะฐะณะฐั” scope `items`. + +ะ”ะปั ั†ัŒะพะณะพ ั–ะผะฟะพั€ั‚ัƒั”ะผะพ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `Security` ะท `fastapi`. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Security` ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน (ั‚ะฐะบ ัะฐะผะพ ัะบ `Depends`), ะฐะปะต `Security` ั‚ะฐะบะพะถ ะฟั€ะธะนะผะฐั” ะฟะฐั€ะฐะผะตั‚ั€ `scopes` ะทั– ัะฟะธัะบะพะผ scopes (ัั‚ั€ะพะบ). + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะผะธ ะฟะตั€ะตะดะฐั”ะผะพ ั„ัƒะฝะบั†ั–ัŽ-ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_active_user` ะดะพ `Security` (ั‚ะฐะบ ัะฐะผะพ, ัะบ ะทั€ะพะฑะธะปะธ ะฑ ั–ะท `Depends`). + +ะ ั‚ะฐะบะพะถ ะฟะตั€ะตะดะฐั”ะผะพ `list` scopes, ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะปะธัˆะต ะพะดะธะฝ scope: `items` (ั—ั… ะผะพะณะปะพ ะฑ ะฑัƒั‚ะธ ะฑั–ะปัŒัˆะต). + +ะ† ั„ัƒะฝะบั†ั–ั-ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_active_user` ั‚ะฐะบะพะถ ะผะพะถะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั– ะฝะต ะปะธัˆะต ะท `Depends`, ะฐ ะน ะท `Security`. ะžะณะพะปะพัˆัƒัŽั‡ะธ ัะฒะพัŽ ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ (`get_current_user`) ั– ะดะพะดะฐั‚ะบะพะฒั– ะฒะธะผะพะณะธ ะดะพ scopes. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะพะฝะฐ ะฒะธะผะฐะณะฐั” scope `me` (ะฒะพะฝะฐ ะผะพะณะปะฐ ะฑ ะฒะธะผะฐะณะฐั‚ะธ ะฑั–ะปัŒัˆ ะฝั–ะถ ะพะดะธะฝ scope). + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ’ะฐะผ ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ะดะพะดะฐะฒะฐั‚ะธ ั€ั–ะทะฝั– scopes ัƒ ั€ั–ะทะฝะธั… ะผั–ัั†ัั…. + +ะœะธ ั€ะพะฑะธะผะพ ั†ะต ั‚ัƒั‚, ั‰ะพะฑ ะฟะพะบะฐะทะฐั‚ะธ, ัะบ **FastAPI** ะพะฑั€ะพะฑะปัั” scopes, ะพะณะพะปะพัˆะตะฝั– ะฝะฐ ั€ั–ะทะฝะธั… ั€ั–ะฒะฝัั…. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// info | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +`Security` ะฝะฐัะฟั€ะฐะฒะดั– ั” ะฟั–ะดะบะปะฐัะพะผ `Depends`, ั– ะผะฐั” ะปะธัˆะต ะพะดะธะฝ ะดะพะดะฐั‚ะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€, ัะบะธะน ะผะธ ะฟะพะฑะฐั‡ะธะผะพ ะฟั–ะทะฝั–ัˆะต. + +ะะปะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `Security` ะทะฐะผั–ัั‚ัŒ `Depends`, **FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะผะพะถะฝะฐ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ scopes ะฑะตะทะฟะตะบะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ API ั‡ะตั€ะตะท OpenAPI. + +ะšะพะปะธ ะฒะธ ั–ะผะฟะพั€ั‚ัƒั”ั‚ะต `Query`, `Path`, `Depends`, `Security` ั‚ะฐ ั–ะฝัˆั– ะท `fastapi`, ั†ะต ะฝะฐัะฟั€ะฐะฒะดั– ั„ัƒะฝะบั†ั–ั—, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒ ัะฟะตั†ั–ะฐะปัŒะฝั– ะบะปะฐัะธ. + +/// + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `SecurityScopes` { #use-securityscopes } + +ะขะตะฟะตั€ ะพะฝะพะฒั–ั‚ัŒ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user`. + +ะ’ะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฝะฐะฒะตะดะตะฝะธะผะธ ะฒะธั‰ะต ะทะฐะปะตะถะฝะพัั‚ัะผะธ. + +ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ัƒ ัะฐะผัƒ ัั…ะตะผัƒ OAuth2, ัั‚ะฒะพั€ะตะฝัƒ ั€ะฐะฝั–ัˆะต, ะพะณะพะปะพัˆัƒัŽั‡ะธ ั—ั— ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ: `oauth2_scheme`. + +ะžัะบั–ะปัŒะบะธ ั†ั ั„ัƒะฝะบั†ั–ั-ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฝะต ะผะฐั” ะฒะปะฐัะฝะธั… ะฒะธะผะพะณ ะดะพ scopes, ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Depends` ะท `oauth2_scheme`, ะฝะตะผะฐั” ะฟะพั‚ั€ะตะฑะธ ะทะฐัั‚ะพัะพะฒัƒะฒะฐั‚ะธ `Security`, ะบะพะปะธ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะบะฐะทัƒะฒะฐั‚ะธ scopes ะฑะตะทะฟะตะบะธ. + +ะœะธ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒั”ะผะพ ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `SecurityScopes`, ั–ะผะฟะพั€ั‚ะพะฒะฐะฝะธะน ะท `fastapi.security`. + +ะšะปะฐั `SecurityScopes` ะฟะพะดั–ะฑะฝะธะน ะดะพ `Request` (ัƒ `Request` ะผะธ ะฝะฐะฟั€ัะผัƒ ะพั‚ั€ะธะผัƒะฒะฐะปะธ ะพะฑโ€™ั”ะบั‚ ะทะฐะฟะธั‚ัƒ). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต scopes { #use-the-scopes } + +ะŸะฐั€ะฐะผะตั‚ั€ `security_scopes` ะผะฐั‚ะธะผะต ั‚ะธะฟ `SecurityScopes`. + +ะ’ั–ะฝ ะผะฐั‚ะธะผะต ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `scopes` ะทั– ัะฟะธัะบะพะผ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ัƒัั– scopes, ะฟะพั‚ั€ั–ะฑะฝั– ัะฐะผั–ะน ั„ัƒะฝะบั†ั–ั— ั‚ะฐ ะฒัั–ะผ ะทะฐะปะตะถะฝะธะผ, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ั—ั— ัะบ ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ. ะขะพะฑั‚ะพ ะฒัั–ะผ ยซะทะฐะปะตะถะฝะธะผยป... ั†ะต ะผะพะถะต ะทะฒัƒั‡ะฐั‚ะธ ะทะฐะฟะปัƒั‚ะฐะฝะพ, ะฝะธะถั‡ะต ะฟะพััะฝะตะฝะพ ั‰ะต ั€ะฐะท. + +ะžะฑโ€™ั”ะบั‚ `security_scopes` (ะบะปะฐััƒ `SecurityScopes`) ั‚ะฐะบะพะถ ะฝะฐะดะฐั” ะฐั‚ั€ะธะฑัƒั‚ `scope_str` ะท ะพะดะฝะธะผ ั€ัะดะบะพะผ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ั†ั– scopes, ั€ะพะทะดั–ะปะตะฝั– ะฟั€ะพะฑั–ะปะฐะผะธ (ะผะธ ะนะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ). + +ะœะธ ัั‚ะฒะพั€ัŽั”ะผะพ `HTTPException`, ัะบะธะน ะทะผะพะถะตะผะพ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ (`raise`) ัƒ ะบั–ะปัŒะบะพั… ะผั–ัั†ัั…. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฝัั‚ะบัƒ ะผะธ ะฒะบะปัŽั‡ะฐั”ะผะพ ะฟะพั‚ั€ั–ะฑะฝั– scopes (ัะบั‰ะพ ั”) ัะบ ัั‚ั€ะพะบัƒ, ั€ะพะทะดั–ะปะตะฝัƒ ะฟั€ะพะฑั–ะปะฐะผะธ (ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `scope_str`). ะœะธ ะฟะพะผั–ั‰ะฐั”ะผะพ ั†ัŽ ัั‚ั€ะพะบัƒ ะทั– scopes ะฒ ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate` (ั†ะต ั‡ะฐัั‚ะธะฝะฐ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั—). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## ะŸะตั€ะตะฒั–ั€ั‚ะต `username` ั– ัั‚ั€ัƒะบั‚ัƒั€ัƒ ะดะฐะฝะธั… { #verify-the-username-and-data-shape } + +ะœะธ ะฟะตั€ะตะฒั–ั€ัั”ะผะพ, ั‰ะพ ะพั‚ั€ะธะผะฐะปะธ `username`, ั– ะฒะธะดะพะฑัƒะฒะฐั”ะผะพ scopes. + +ะŸะพั‚ั–ะผ ะฒะฐะปั–ะดะพะฒัƒั”ะผะพ ั†ั– ะดะฐะฝั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Pydantic-ะผะพะดะตะปั– (ะฟะตั€ะตั…ะพะฟะปัŽัŽั‡ะธ ะฒะธะฝัั‚ะพะบ `ValidationError`), ั– ัะบั‰ะพ ะฒะธะฝะธะบะฐั” ะฟะพะผะธะปะบะฐ ั‡ะธั‚ะฐะฝะฝั JWT ั‚ะพะบะตะฝะฐ ะฐะฑะพ ะฒะฐะปั–ะดะฐั†ั–ั— ะดะฐะฝะธั… Pydantic, ะฟั–ะดั–ะนะผะฐั”ะผะพ ั€ะฐะฝั–ัˆะต ัั‚ะฒะพั€ะตะฝะธะน `HTTPException`. + +ะ”ะปั ั†ัŒะพะณะพ ะผะธ ะพะฝะพะฒะปัŽั”ะผะพ Pydantic-ะผะพะดะตะปัŒ `TokenData` ะฝะพะฒะพัŽ ะฒะปะฐัั‚ะธะฒั–ัั‚ัŽ `scopes`. + +ะ’ะฐะปั–ะดัƒะฒะฐะฒัˆะธ ะดะฐะฝั– ั‡ะตั€ะตะท Pydantic, ะผะธ ะณะฐั€ะฐะฝั‚ัƒั”ะผะพ, ั‰ะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ะผะฐั”ะผะพ ัะฐะผะต `list` ั–ะท `str` ะดะปั scopes ั– `str` ะดะปั `username`. + +ะ—ะฐะผั–ัั‚ัŒ, ะฝะฐะฟั€ะธะบะปะฐะด, `dict` ะฐะฑะพ ั‡ะพะณะพััŒ ั–ะฝัˆะพะณะพ, ั‰ะพ ะผะพะถะต ะทะปะฐะผะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ ะดะฐะปั–, ัั‚ะฒะพั€ะธะฒัˆะธ ั€ะธะทะธะบ ะฑะตะทะฟะตะบะธ. + +ะœะธ ั‚ะฐะบะพะถ ะฟะตั€ะตะฒั–ั€ัั”ะผะพ, ั‰ะพ ั–ัะฝัƒั” ะบะพั€ะธัั‚ัƒะฒะฐั‡ ั–ะท ั†ะธะผ username, ั–ะฝะฐะบัˆะต ะฟั–ะดั–ะนะผะฐั”ะผะพ ั‚ะพะน ัะฐะผะธะน ะฒะธะฝัั‚ะพะบ. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## ะŸะตั€ะตะฒั–ั€ั‚ะต `scopes` { #verify-the-scopes } + +ะขะตะฟะตั€ ะฟะตั€ะตะฒั–ั€ัั”ะผะพ, ั‰ะพ ะฒัั– ะฟะพั‚ั€ั–ะฑะฝั– scopes - ะดะปั ั†ั–ั”ั— ะทะฐะปะตะถะฝะพัั‚ั– ั‚ะฐ ะฒัั–ั… ะทะฐะปะตะถะฝะธั… (ะฒะบะปัŽั‡ะฝะพ ะท ะพะฟะตั€ะฐั†ั–ัะผะธ ัˆะปัั…ัƒ) - ะผั–ัั‚ัั‚ัŒัั ะฒ scopes, ะฝะฐะดะฐะฝะธั… ัƒ ะพั‚ั€ะธะผะฐะฝะพะผัƒ ั‚ะพะบะตะฝั–, ั–ะฝะฐะบัˆะต ะฟั–ะดั–ะนะผะฐั”ะผะพ `HTTPException`. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `security_scopes.scopes`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ `list` ั–ะท ัƒัั–ะผะฐ ั†ะธะผะธ scopes ัะบ `str`. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## ะ”ะตั€ะตะฒะพ ะทะฐะปะตะถะฝะพัั‚ะตะน ั– scopes { #dependency-tree-and-scopes } + +ะฉะต ั€ะฐะท ั€ะพะทะณะปัะฝัŒะผะพ ะดะตั€ะตะฒะพ ะทะฐะปะตะถะฝะพัั‚ะตะน ั– scopes. + +ะžัะบั–ะปัŒะบะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_active_user` ะผะฐั” ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user`, scope ยซmeยป, ะพะณะพะปะพัˆะตะฝะธะน ัƒ `get_current_active_user`, ะฑัƒะดะต ะฒะบะปัŽั‡ะตะฝะธะน ะดะพ ัะฟะธัะบัƒ ะฟะพั‚ั€ั–ะฑะฝะธั… scopes ัƒ `security_scopes.scopes`, ะฟะตั€ะตะดะฐะฝะพะณะพ ะดะพ `get_current_user`. + +ะกะฐะผะฐ ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒั” scope ยซitemsยป, ะพั‚ะถะต ะฒั–ะฝ ั‚ะฐะบะพะถ ะฑัƒะดะต ัƒ ัะฟะธัะบัƒ `security_scopes.scopes`, ะฟะตั€ะตะดะฐะฝะพะผัƒ ะดะพ `get_current_user`. + +ะžััŒ ัะบ ะฒะธะณะปัะดะฐั” ั–ั”ั€ะฐั€ั…ั–ั ะทะฐะปะตะถะฝะพัั‚ะตะน ั– 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`. + - ะŸะฐั€ะฐะผะตั‚ั€ `security_scopes` ั‚ะธะฟัƒ `SecurityScopes`: + - ะฆะตะน ะฟะฐั€ะฐะผะตั‚ั€ `security_scopes` ะผะฐั” ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `scopes` ั–ะท `list`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ัƒัั– ะฝะฐะฒะตะดะตะฝั– ะฒะธั‰ะต scopes, ะพั‚ะถะต: + - `security_scopes.scopes` ะผั–ัั‚ะธั‚ะธะผะต `["me", "items"]` ะดะปั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ `read_own_items`. + - `security_scopes.scopes` ะผั–ัั‚ะธั‚ะธะผะต `["me"]` ะดะปั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ `read_users_me`, ะฐะดะถะต ะฒั–ะฝ ะพะณะพะปะพัˆะตะฝะธะน ัƒ ะทะฐะปะตะถะฝะพัั‚ั– `get_current_active_user`. + - `security_scopes.scopes` ะผั–ัั‚ะธั‚ะธะผะต `[]` (ะฝั–ั‡ะพะณะพ) ะดะปั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ `read_system_status`, ะฑะพ ะฒะพะฝะฐ ะฝะต ะพะณะพะปะพัˆัƒั” ะถะพะดะฝะพะณะพ `Security` ะทั– `scopes`, ั– ั—ั— ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user` ั‚ะฐะบะพะถ ะฝะต ะพะณะพะปะพัˆัƒั” ะถะพะดะฝะธั… `scopes`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะฐะถะปะธะฒะต ั– ยซะผะฐะณั–ั‡ะฝะตยป ั‚ัƒั‚ ัƒ ั‚ะพะผัƒ, ั‰ะพ `get_current_user` ะผะฐั‚ะธะผะต ั€ั–ะทะฝั– ัะฟะธัะบะธ `scopes` ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะปั ะบะพะถะฝะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะฃัะต ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด `scopes`, ะพะณะพะปะพัˆะตะฝะธั… ัƒ ะบะพะถะฝั–ะน ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั‚ะฐ ะบะพะถะฝั–ะน ะทะฐะปะตะถะฝะพัั‚ั– ะฒ ะดะตั€ะตะฒั– ะทะฐะปะตะถะฝะพัั‚ะตะน ะดะปั ะบะพะฝะบั€ะตั‚ะฝะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +/// + +## ะ‘ั–ะปัŒัˆะต ะดะตั‚ะฐะปะตะน ะฟั€ะพ `SecurityScopes` { #more-details-about-securityscopes } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `SecurityScopes` ัƒ ะฑัƒะดัŒ-ัะบะพะผัƒ ะผั–ัั†ั– ะน ัƒ ะบั–ะปัŒะบะพั… ะผั–ัั†ัั…, ะฒั–ะฝ ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ะผะฐั” ะฑัƒั‚ะธ ะฒ ยซะบะพั€ะตะฝะตะฒั–ะนยป ะทะฐะปะตะถะฝะพัั‚ั–. + +ะ’ั–ะฝ ะทะฐะฒะถะดะธ ะผั–ัั‚ะธั‚ะธะผะต scopes ะฑะตะทะฟะตะบะธ, ะพะณะพะปะพัˆะตะฝั– ะฒ ะฟะพั‚ะพั‡ะฝะธั… ะทะฐะปะตะถะฝะพัั‚ัั… `Security` ั– ะฒัั–ั… ะทะฐะปะตะถะฝะธั… ะดะปั **ั†ั–ั”ั— ะบะพะฝะบั€ะตั‚ะฝะพั—** ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั– **ั†ัŒะพะณะพ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ** ะดะตั€ะตะฒะฐ ะทะฐะปะตะถะฝะพัั‚ะตะน. + +ะžัะบั–ะปัŒะบะธ `SecurityScopes` ะผั–ัั‚ะธั‚ะธะผะต ะฒัั– scopes, ะพะณะพะปะพัˆะตะฝั– ะทะฐะปะตะถะฝะธะผะธ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ั‚ะพะบะตะฝ ะผะฐั” ะฟะพั‚ั€ั–ะฑะฝั– scopes, ัƒ ั†ะตะฝั‚ั€ะฐะปัŒะฝั–ะน ั„ัƒะฝะบั†ั–ั—-ะทะฐะปะตะถะฝะพัั‚ั–, ะฐ ะฟะพั‚ั–ะผ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั€ั–ะทะฝั– ะฒะธะผะพะณะธ ะดะพ scopes ัƒ ั€ั–ะทะฝะธั… ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ. + +ะ’ะพะฝะธ ะฟะตั€ะตะฒั–ั€ัั‚ะธะผัƒั‚ัŒัั ะฝะตะทะฐะปะตะถะฝะพ ะดะปั ะบะพะถะฝะพั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +## ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะฏะบั‰ะพ ะฒะธ ะฒั–ะดะบั€ะธั”ั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API, ะฒะธ ะทะผะพะถะตั‚ะต ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธัั ั– ะฒะบะฐะทะฐั‚ะธ, ัะบั– scopes ั…ะพั‡ะตั‚ะต ะฐะฒั‚ะพั€ะธะทัƒะฒะฐั‚ะธ. + + + +ะฏะบั‰ะพ ะฒะธ ะฝะต ะพะฑะตั€ะตั‚ะต ะถะพะดะฝะพะณะพ scope, ะฒะธ ะฑัƒะดะตั‚ะต ยซะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะพะฒะฐะฝั–ยป, ะฐะปะต ะฟั€ะธ ัะฟั€ะพะฑั– ะดะพัั‚ัƒะฟัƒ ะดะพ `/users/me/` ะฐะฑะพ `/users/me/items/` ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะพะผะธะปะบัƒ ะฟั€ะพ ะฝะตะดะพัั‚ะฐั‚ะฝั– ะดะพะทะฒะพะปะธ. ะ’ะธ ะฒัะต ั‰ะต ะผะฐั‚ะธะผะตั‚ะต ะดะพัั‚ัƒะฟ ะดะพ `/status/`. + +ะฏะบั‰ะพ ะพะฑะตั€ะตั‚ะต scope `me`, ะฐะปะต ะฝะต scope `items`, ะฒะธ ะทะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ `/users/me/`, ะฐะปะต ะฝะต ะดะพ `/users/me/items/`. + +ะขะฐะบ ัั‚ะฐะฝะตั‚ัŒัั ะทั– ัั‚ะพั€ะพะฝะฝั–ะผ ะทะฐัั‚ะพััƒะฝะบะพะผ, ัะบะธะน ัะฟั€ะพะฑัƒั” ะทะฒะตั€ะฝัƒั‚ะธัั ะดะพ ะพะดะฝั–ั”ั— ะท ั†ะธั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ ะท ั‚ะพะบะตะฝะพะผ, ะฝะฐะดะฐะฝะธะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะตะผ, ะทะฐะปะตะถะฝะพ ะฒั–ะด ั‚ะพะณะพ, ัะบั–ะปัŒะบะธ ะดะพะทะฒะพะปั–ะฒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฝะฐะดะฐะฒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +## ะŸั€ะพ ัั‚ะพั€ะพะฝะฝั– ั–ะฝั‚ะตะณั€ะฐั†ั–ั— { #about-third-party-integrations } + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ยซะฟะพั‚ั–ะบ ะฟะฐั€ะพะปัŽยป OAuth2. + +ะฆะต ะดะพั€ะตั‡ะฝะพ, ะบะพะปะธ ะผะธ ะฒั…ะพะดะธะผะพ ัƒ ะฒะปะฐัะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ, ะนะผะพะฒั–ั€ะฝะพ, ะท ะฒะปะฐัะฝะธะผ ั„ั€ะพะฝั‚ะตะฝะดะพะผ. + +ะะดะถะต ะผะธ ะผะพะถะตะผะพ ะดะพะฒั–ั€ัั‚ะธ ะนะพะผัƒ ะพั‚ั€ะธะผะฐะฝะฝั `username` ั– `password`, ะฑะพ ะผะธ ะนะพะณะพ ะบะพะฝั‚ั€ะพะปัŽั”ะผะพ. + +ะะปะต ัะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต OAuth2-ะทะฐัั‚ะพััƒะฝะพะบ, ะดะพ ัะบะพะณะพ ะฟั–ะดะบะปัŽั‡ะฐั‚ะธะผัƒั‚ัŒัั ั–ะฝัˆั– (ั‚ะพะฑั‚ะพ ัะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะฝะฐ ะบัˆั‚ะฐะปั‚ Facebook, Google, GitHub ั‚ะพั‰ะพ), ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะดะธะฝ ะท ั–ะฝัˆะธั… ะฟะพั‚ะพะบั–ะฒ. + +ะะฐะนะฟะพัˆะธั€ะตะฝั–ัˆะธะน - ะฝะตัะฒะฝะธะน ะฟะพั‚ั–ะบ (implicit flow). + +ะะฐะนะฑะตะทะฟะตั‡ะฝั–ัˆะธะน - ะฟะพั‚ั–ะบ ะบะพะดัƒ (code flow), ะฐะปะต ะนะพะณะพ ัะบะปะฐะดะฝั–ัˆะต ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ, ะพัะบั–ะปัŒะบะธ ะฒั–ะฝ ะฟะพั‚ั€ะตะฑัƒั” ะฑั–ะปัŒัˆะต ะบั€ะพะบั–ะฒ. ะงะตั€ะตะท ัะบะปะฐะดะฝั–ัั‚ัŒ ะฑะฐะณะฐั‚ะพ ะฟั€ะพะฒะฐะนะดะตั€ั–ะฒ ัƒ ะฟั–ะดััƒะผะบัƒ ั€ะฐะดัั‚ัŒ ะฝะตัะฒะฝะธะน ะฟะพั‚ั–ะบ. + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะงะฐัั‚ะพ ะบะพะถะตะฝ ะฟั€ะพะฒะฐะนะดะตั€ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะฝะฐะทะธะฒะฐั” ัะฒะพั— ะฟะพั‚ะพะบะธ ะฟะพ-ั€ั–ะทะฝะพะผัƒ, ั€ะพะฑะปัั‡ะธ ั†ะต ั‡ะฐัั‚ะธะฝะพัŽ ัะฒะพะณะพ ะฑั€ะตะฝะดัƒ. + +ะะปะต ะทั€ะตัˆั‚ะพัŽ ะฒะพะฝะธ ั€ะตะฐะปั–ะทัƒัŽั‚ัŒ ั‚ะพะน ัะฐะผะธะน ัั‚ะฐะฝะดะฐั€ั‚ OAuth2. + +/// + +**FastAPI** ะผั–ัั‚ะธั‚ัŒ ัƒั‚ะธะปั–ั‚ะธ ะดะปั ะฒัั–ั… ั†ะธั… ะฟะพั‚ะพะบั–ะฒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— OAuth2 ัƒ `fastapi.security.oauth2`. + +## `Security` ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– ะดะตะบะพั€ะฐั‚ะพั€ะฐ `dependencies` { #security-in-decorator-dependencies } + +ะขะฐะบ ัะฐะผะพ ัะบ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ `list` ั–ะท `Depends` ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– `dependencies` ะดะตะบะพั€ะฐั‚ะพั€ะฐ (ัะบ ะฟะพััะฝะตะฝะพ ะฒ [ะ—ะฐะปะตะถะฝะพัั‚ั– ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะฐะผ `Security` ะทั– `scopes`. diff --git a/docs/uk/docs/advanced/settings.md b/docs/uk/docs/advanced/settings.md new file mode 100644 index 0000000000..dccb4b0911 --- /dev/null +++ b/docs/uk/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั‚ะฐ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั { #settings-and-environment-variables } + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะผะพะถัƒั‚ัŒ ะทะฝะฐะดะพะฑะธั‚ะธัั ะทะพะฒะฝั–ัˆะฝั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฐะฑะพ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั—, ะฝะฐะฟั€ะธะบะปะฐะด ัะตะบั€ะตั‚ะฝั– ะบะปัŽั‡ั–, ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั– ะฑะฐะทะธ ะดะฐะฝะธั…, ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั– ะดะปั email-ัะตั€ะฒั–ัั–ะฒ ั‚ะพั‰ะพ. + +ะ‘ั–ะปัŒัˆั–ัั‚ัŒ ั–ะท ั†ะธั… ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ะทะผั–ะฝะฝั– (ะผะพะถัƒั‚ัŒ ะทะผั–ะฝัŽะฒะฐั‚ะธัั), ัะบ-ะพั‚ URL-ะฐะดั€ะตัะธ ะฑะฐะท ะดะฐะฝะธั…. ะ† ะฑะฐะณะฐั‚ะพ ะท ะฝะธั… ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ั‡ัƒั‚ะปะธะฒะธะผะธ, ัะบ-ะพั‚ ัะตะบั€ะตั‚ะธ. + +ะ— ั†ั–ั”ั— ะฟั€ะธั‡ะธะฝะธ ะฟะพัˆะธั€ะตะฝะพ ะฝะฐะดะฐะฒะฐั‚ะธ ั—ั… ัƒ ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั, ัะบั– ะทั‡ะธั‚ัƒัŽั‚ัŒัั ะทะฐัั‚ะพััƒะฝะบะพะผ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฉะพะฑ ะทั€ะพะทัƒะผั–ั‚ะธ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ [ะ—ะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั](../environment-variables.md){.internal-link target=_blank}. + +/// + +## ะขะธะฟะธ ั‚ะฐ ะฟะตั€ะตะฒั–ั€ะบะฐ { #types-and-validation } + +ะฆั– ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะผะพะถัƒั‚ัŒ ะผั–ัั‚ะธั‚ะธ ะปะธัˆะต ั‚ะตะบัั‚ะพะฒั– ัั‚ั€ะพะบะธ, ะพัะบั–ะปัŒะบะธ ะฒะพะฝะธ ะทะพะฒะฝั–ัˆะฝั– ะดะพ Python ั– ะผะฐัŽั‚ัŒ ะฑัƒั‚ะธ ััƒะผั–ัะฝั– ะท ั–ะฝัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ ั‚ะฐ ั€ะตัˆั‚ะพัŽ ัะธัั‚ะตะผะธ (ั– ะฝะฐะฒั–ั‚ัŒ ะท ั€ั–ะทะฝะธะผะธ ะพะฟะตั€ะฐั†ั–ะนะฝะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ัะบ-ะพั‚ Linux, Windows, macOS). + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฑัƒะดัŒ-ัะบะต ะทะฝะฐั‡ะตะฝะฝั, ะฟั€ะพั‡ะธั‚ะฐะฝะต ะฒ Python ะทั– ะทะผั–ะฝะฝะพั— ะพั‚ะพั‡ะตะฝะฝั, ะฑัƒะดะต `str`, ั– ะฑัƒะดัŒ-ัะบะต ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฒ ั–ะฝัˆะธะน ั‚ะธะฟ ะฐะฑะพ ะฑัƒะดัŒ-ัะบะฐ ะฟะตั€ะตะฒั–ั€ะบะฐ ะผะฐัŽั‚ัŒ ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั ะฒ ะบะพะดั–. + +## Pydantic `Settings` { #pydantic-settings } + +ะะฐ ั‰ะฐัั‚ั, Pydantic ะฝะฐะดะฐั” ั‡ัƒะดะพะฒะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ะพะฑั€ะพะฑะบะธ ั†ะธั… ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ั–ะท ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั - Pydantic: Settings management. + +### ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ `pydantic-settings` { #install-pydantic-settings } + +ะกะฟะตั€ัˆัƒ ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ, ะฐ ะฟะพั‚ั–ะผ ะฒัั‚ะฐะฝะพะฒะธะปะธ ะฟะฐะบะตั‚ `pydantic-settings`: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +ะ’ั–ะฝ ั‚ะฐะบะพะถ ะฒั…ะพะดะธั‚ัŒ ัƒ ัะบะปะฐะด, ัะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะดะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– ยซallยป ะทะฐ ะดะพะฟะพะผะพะณะพัŽ: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะพะฑ'ั”ะบั‚ `Settings` { #create-the-settings-object } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `BaseSettings` ั–ะท Pydantic ั– ัั‚ะฒะพั€ั–ั‚ัŒ ะฟั–ะดะบะปะฐั, ะดัƒะถะต ะฟะพะดั–ะฑะฝะพ ะดะพ ะผะพะดะตะปั– Pydantic. + +ะขะฐะบ ัะฐะผะพ, ัะบ ั– ะท ะผะพะดะตะปัะผะธ Pydantic, ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ะฐั‚ั€ะธะฑัƒั‚ะธ ะบะปะฐััƒ ะท ะฐะฝะพั‚ะฐั†ั–ัะผะธ ั‚ะธะฟั–ะฒ ั–, ะทะฐ ะฟะพั‚ั€ะตะฑะธ, ะทะฝะฐั‡ะตะฝะฝัะผะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒัั– ั‚ั– ัะฐะผั– ะผะพะถะปะธะฒะพัั‚ั– ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ั‰ะพ ะน ะดะปั ะผะพะดะตะปะตะน Pydantic, ัะบ-ะพั‚ ั€ั–ะทะฝั– ั‚ะธะฟะธ ะดะฐะฝะธั… ั– ะดะพะดะฐั‚ะบะพะฒั– ะฟะตั€ะตะฒั–ั€ะบะธ ะท `Field()`. + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ั‰ะพััŒ ัˆะฒะธะดะบะพ ัะบะพะฟั–ัŽะฒะฐั‚ะธ ะน ะฒัั‚ะฐะฒะธั‚ะธ, ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั†ะตะน ะฟั€ะธะบะปะฐะด, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ะพัั‚ะฐะฝะฝั–ะผ ะฝะธะถั‡ะต. + +/// + +ะŸะพั‚ั–ะผ, ะบะพะปะธ ะฒะธ ัั‚ะฒะพั€ะธั‚ะต ะตะบะทะตะผะฟะปัั€ ั†ัŒะพะณะพ ะบะปะฐััƒ `Settings` (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒ ะพะฑ'ั”ะบั‚ั– `settings`), Pydantic ะทั‡ะธั‚ัƒะฒะฐั‚ะธะผะต ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะฑะตะท ัƒั€ะฐั…ัƒะฒะฐะฝะฝั ั€ะตะณั–ัั‚ั€ัƒ, ั‚ะพะถ ะฒะตั€ั…ะฝัŒะพั€ะตะณั–ัั‚ั€ะพะฒะฐ ะทะผั–ะฝะฝะฐ `APP_NAME` ะฒัะต ะพะดะฝะพ ะฑัƒะดะต ะฟั€ะพั‡ะธั‚ะฐะฝะฐ ะดะปั ะฐั‚ั€ะธะฑัƒั‚ะฐ `app_name`. + +ะ”ะฐะปั– ะฒั–ะฝ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ัŒ ั– ะฟะตั€ะตะฒั–ั€ะธั‚ัŒ ะดะฐะฝั–. ะขะพะถ ะบะพะปะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ะพะฑ'ั”ะบั‚ `settings`, ัƒ ะฒะฐั ะฑัƒะดัƒั‚ัŒ ะดะฐะฝั– ั‚ะธั… ั‚ะธะฟั–ะฒ, ัะบั– ะฒะธ ะพะณะพะปะพัะธะปะธ (ะฝะฐะฟั€ะธะบะปะฐะด, `items_per_user` ะฑัƒะดะต `int`). + +### ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `settings` { #use-the-settings } + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฝะพะฒะธะน ะพะฑ'ั”ะบั‚ `settings` ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ัะตั€ะฒะตั€ { #run-the-server } + +ะ”ะฐะปั– ะฒะธ ะฑ ะทะฐะฟัƒัั‚ะธะปะธ ัะตั€ะฒะตั€, ะฟะตั€ะตะดะฐัŽั‡ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— ัะบ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `ADMIN_EMAIL` ั– `APP_NAME` ั‚ะฐะบ: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะฉะพะฑ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะบั–ะปัŒะบะฐ ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั ะดะปั ะพะดะฝั–ั”ั— ะบะพะผะฐะฝะดะธ, ะฟั€ะพัั‚ะพ ั€ะพะทะดั–ะปั–ั‚ัŒ ั—ั… ะฟั€ะพะฑั–ะปะฐะผะธ ั– ั€ะพะทะผั–ัั‚ั–ั‚ัŒ ัƒัั– ะฟะตั€ะตะด ะบะพะผะฐะฝะดะพัŽ. + +/// + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั `admin_email` ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ะฒ `"deadpool@example.com"`. + +`app_name` ะฑัƒะดะต `"ChimichangApp"`. + +ะ `items_per_user` ะทะฑะตั€ะตะถะต ัะฒะพั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `50`. + +## ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฒ ั–ะฝัˆะพะผัƒ ะผะพะดัƒะปั– { #settings-in-another-module } + +ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะผั–ัั‚ะธั‚ะธ ั†ั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฒ ั–ะฝัˆะพะผัƒ ะผะพะดัƒะปั–, ัะบ ะฒะธ ะฑะฐั‡ะธะปะธ ะฒ [ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ - ะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ](../tutorial/bigger-applications.md){.internal-link target=_blank}. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ั„ะฐะนะป `config.py` ะท: + +{* ../../docs_src/settings/app01_py310/config.py *} + +ะ ะฟะพั‚ั–ะผ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะนะพะณะพ ัƒ ั„ะฐะนะปั– `main.py`: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะฐะผ ั‚ะฐะบะพะถ ะทะฝะฐะดะพะฑะธั‚ัŒัั ั„ะฐะนะป `__init__.py`, ัะบ ะฒะธ ะฑะฐั‡ะธะปะธ ะฒ [ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ - ะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ](../tutorial/bigger-applications.md){.internal-link target=_blank}. + +/// + +## ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ { #settings-in-a-dependency } + +ะ†ะฝะพะดั– ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพ ะฝะฐะดะฐะฒะฐั‚ะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั‡ะตั€ะตะท ะทะฐะปะตะถะฝั–ัั‚ัŒ, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะผะฐั‚ะธ ะณะปะพะฑะฐะปัŒะฝะธะน ะพะฑ'ั”ะบั‚ `settings`, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒััŽะดะธ. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะพัะพะฑะปะธะฒะพ ะบะพั€ะธัะฝะพ ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ัƒะฒะฐะฝะฝั, ะพัะบั–ะปัŒะบะธ ะดัƒะถะต ะปะตะณะบะพ ะฟะตั€ะตะฟะธัะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฒะปะฐัะฝะธะผะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ. + +### ะคะฐะนะป ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— { #the-config-file } + +ะŸั€ะพะดะพะฒะถัƒัŽั‡ะธ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฟั€ะธะบะปะฐะด, ะฒะฐัˆ ั„ะฐะนะป `config.py` ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั‚ะตะฟะตั€ ะผะธ ะฝะต ัั‚ะฒะพั€ัŽั”ะผะพ ะตะบะทะตะผะฟะปัั€ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `settings = Settings()`. + +### ะžัะฝะพะฒะฝะธะน ั„ะฐะนะป ะทะฐัั‚ะพััƒะฝะบัƒ { #the-main-app-file } + +ะขะตะฟะตั€ ะผะธ ัั‚ะฒะพั€ัŽั”ะผะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบะฐ ะฟะพะฒะตั€ั‚ะฐั” ะฝะพะฒะธะน `config.Settings()`. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะธ ะพะฑะณะพะฒะพั€ะธะผะพ `@lru_cache` ั‚ั€ะพั…ะธ ะทะณะพะดะพะผ. + +ะŸะพะบะธ ั‰ะพ ะผะพะถะตั‚ะต ะฒะฒะฐะถะฐั‚ะธ, ั‰ะพ `get_settings()` - ั†ะต ะทะฒะธั‡ะฐะนะฝะฐ ั„ัƒะฝะบั†ั–ั. + +/// + +ะ ะดะฐะปั– ะผะธ ะผะพะถะตะผะพ ะฒะธะผะฐะณะฐั‚ะธ ั—ั— ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ะดะต, ะดะต ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั– ั‚ะตัั‚ัƒะฒะฐะฝะฝั { #settings-and-testing } + +ะŸะพั‚ั–ะผ ะฑัƒะดะต ะดัƒะถะต ะฟั€ะพัั‚ะพ ะฝะฐะดะฐั‚ะธ ั–ะฝัˆะธะน ะพะฑ'ั”ะบั‚ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ัƒะฒะฐะฝะฝั, ัั‚ะฒะพั€ะธะฒัˆะธ ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั– ะดะปั `get_settings`: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +ะฃ ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั– ะทะฐะปะตะถะฝะพัั‚ั– ะผะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ะผะพ ะฝะพะฒะต ะทะฝะฐั‡ะตะฝะฝั `admin_email` ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ะพะฑ'ั”ะบั‚ะฐ `Settings`, ะฐ ะฟะพั‚ั–ะผ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ั†ะตะน ะฝะพะฒะธะน ะพะฑ'ั”ะบั‚. + +ะŸั–ัะปั ั†ัŒะพะณะพ ะผะธ ะผะพะถะตะผะพ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ัะฐะผะต ะฒั–ะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั. + +## ะงะธั‚ะฐะฝะฝั ั„ะฐะนะปัƒ `.env` { #reading-a-env-file } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ะฑะฐะณะฐั‚ะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ, ัะบั– ะผะพะถัƒั‚ัŒ ั‡ะฐัั‚ะพ ะทะผั–ะฝัŽะฒะฐั‚ะธัั, ะผะพะถะปะธะฒะพ ะฒ ั€ั–ะทะฝะธั… ะพั‚ะพั‡ะตะฝะฝัั…, ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพ ั€ะพะทะผั–ัั‚ะธั‚ะธ ั—ั… ัƒ ั„ะฐะนะปั–, ะฐ ะฟะพั‚ั–ะผ ะทั‡ะธั‚ัƒะฒะฐั‚ะธ ั—ั… ั–ะท ะฝัŒะพะณะพ ั‚ะฐะบ, ะฝั–ะฑะธ ั†ะต ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั. + +ะฆั ะฟั€ะฐะบั‚ะธะบะฐ ะดะพัั‚ะฐั‚ะฝัŒะพ ะฟะพัˆะธั€ะตะฝะฐ, ั‚ะพะถ ะผะฐั” ะฝะฐะทะฒัƒ - ั†ั– ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะทะฐะทะฒะธั‡ะฐะน ั€ะพะทะผั–ั‰ัƒัŽั‚ัŒัั ัƒ ั„ะฐะนะปั– `.env`, ะฐ ัะฐะผ ั„ะฐะนะป ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซdotenvยป. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะคะฐะนะป, ั‰ะพ ะฟะพั‡ะธะฝะฐั”ั‚ัŒัั ะท ะบั€ะฐะฟะบะธ (`.`), ั” ะฟั€ะธั…ะพะฒะฐะฝะธะผ ัƒ ัะธัั‚ะตะผะฐั…, ะฟะพะดั–ะฑะฝะธั… ะดะพ Unix, ัะบ-ะพั‚ Linux ั– macOS. + +ะะปะต ั„ะฐะนะป dotenv ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ ะผะฐั” ะผะฐั‚ะธ ัะฐะผะต ั‚ะฐะบัƒ ะฝะฐะทะฒัƒ. + +/// + +Pydantic ะผะฐั” ะฟั–ะดั‚ั€ะธะผะบัƒ ั‡ะธั‚ะฐะฝะฝั ะท ั‚ะฐะบะธั… ั‚ะธะฟั–ะฒ ั„ะฐะนะปั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะทะพะฒะฝั–ัˆะฝัŒะพั— ะฑั–ะฑะปั–ะพั‚ะตะบะธ. ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ั‚ัƒั‚: Pydantic Settings: Dotenv (.env) support. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฉะพะฑ ั†ะต ะฟั€ะฐั†ัŽะฒะฐะปะพ, ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝะฐั‚ะธ `pip install python-dotenv`. + +/// + +### ะคะฐะนะป `.env` { #the-env-file } + +ะฃ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ั„ะฐะนะป `.env` ั–ะท ะฒะผั–ัั‚ะพะผ: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### ะ—ั‡ะธั‚ัƒะฒะฐะฝะฝั ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ั–ะท `.env` { #read-settings-from-env } + +ะŸะพั‚ั–ะผ ะพะฝะพะฒั–ั‚ัŒ ะฒะฐัˆ `config.py` ั‚ะฐะบ: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะั‚ั€ะธะฑัƒั‚ `model_config` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะปะธัˆะต ะดะปั ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— Pydantic. ะ”ะพะบะปะฐะดะฝั–ัˆะต: Pydantic: Concepts: Configuration. + +/// + +ะขัƒั‚ ะผะธ ะฒะธะทะฝะฐั‡ะฐั”ะผะพ ะบะพะฝั„ั–ะณ `env_file` ัƒัะตั€ะตะดะธะฝั– ะฒะฐัˆะพะณะพ ะบะปะฐััƒ Pydantic `Settings` ั– ะทะฐะดะฐั”ะผะพ ะทะฝะฐั‡ะตะฝะฝั - ั–ะผ'ั ั„ะฐะนะปะฐ ะท dotenv, ัะบะธะน ะผะธ ั…ะพั‡ะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ. + +### ะกั‚ะฒะพั€ะตะฝะฝั `Settings` ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `lru_cache` { #creating-the-settings-only-once-with-lru-cache } + +ะงะธั‚ะฐะฝะฝั ั„ะฐะนะปะฐ ะท ะดะธัะบะฐ ะทะฐะทะฒะธั‡ะฐะน ั” ะดะพั€ะพะณะพัŽ (ะฟะพะฒั–ะปัŒะฝะพัŽ) ะพะฟะตั€ะฐั†ั–ั”ัŽ, ั‚ะพะถ, ั–ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ั€ะพะฑะธั‚ะธ ั†ะต ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท ั– ะฟะพั‚ั–ะผ ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ะทะฐะผั–ัั‚ัŒ ะทั‡ะธั‚ัƒะฒะฐะฝะฝั ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ. + +ะะปะต ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะผะธ ั€ะพะฑะธะผะพ: + +```Python +Settings() +``` + +ะฑัƒะดะต ัั‚ะฒะพั€ะตะฝะพ ะฝะพะฒะธะน ะพะฑ'ั”ะบั‚ `Settings`, ั– ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะฒั–ะฝ ะทะฝะพะฒัƒ ะทั‡ะธั‚ัƒะฒะฐั‚ะธะผะต ั„ะฐะนะป `.env`. + +ะฏะบะฑะธ ั„ัƒะฝะบั†ั–ั ะทะฐะปะตะถะฝะพัั‚ั– ะฒะธะณะปัะดะฐะปะฐ ั‚ะฐะบ: + +```Python +def get_settings(): + return Settings() +``` + +ะผะธ ัั‚ะฒะพั€ัŽะฒะฐะปะธ ะฑ ั†ะตะน ะพะฑ'ั”ะบั‚ ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ ั– ั‡ะธั‚ะฐะปะธ ะฑ ั„ะฐะนะป `.env` ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ. โš ๏ธ + +ะะปะต ะพัะบั–ะปัŒะบะธ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะดะตะบะพั€ะฐั‚ะพั€ `@lru_cache` ะทะฒะตั€ั…ัƒ, ะพะฑ'ั”ะบั‚ `Settings` ะฑัƒะดะต ัั‚ะฒะพั€ะตะฝะพ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท, ะฟั–ะด ั‡ะฐั ะฟะตั€ัˆะพะณะพ ะฒะธะบะปะธะบัƒ. โœ”๏ธ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +ะŸะพั‚ั–ะผ ะดะปั ะฑัƒะดัŒ-ัะบะพะณะพ ะฟะพะดะฐะปัŒัˆะพะณะพ ะฒะธะบะปะธะบัƒ `get_settings()` ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ะดะปั ะฝะฐัั‚ัƒะฟะฝะธั… ะทะฐะฟะธั‚ั–ะฒ, ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพะฝะฐะฝะฝั ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพะณะพ ะบะพะดัƒ `get_settings()` ั– ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ะพะฑ'ั”ะบั‚ะฐ `Settings`, ะฒั–ะฝ ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ั‚ะพะน ัะฐะผะธะน ะพะฑ'ั”ะบั‚, ั‰ะพ ะฑัƒะฒ ะฟะพะฒะตั€ะฝัƒั‚ะธะน ะฟั–ะด ั‡ะฐั ะฟะตั€ัˆะพะณะพ ะฒะธะบะปะธะบัƒ, ะทะฝะพะฒัƒ ั– ะทะฝะพะฒัƒ. + +#### ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– `lru_cache` { #lru-cache-technical-details } + +`@lru_cache` ะผะพะดะธั„ั–ะบัƒั” ั„ัƒะฝะบั†ั–ัŽ, ัะบัƒ ะฒั–ะฝ ะดะตะบะพั€ัƒั”, ั‚ะฐะบ, ั‰ะพะฑ ะฒะพะฝะฐ ะฟะพะฒะตั€ั‚ะฐะปะฐ ั‚ะต ัะฐะผะต ะทะฝะฐั‡ะตะฝะฝั, ั‰ะพ ะน ัƒะฟะตั€ัˆะต, ะทะฐะผั–ัั‚ัŒ ะฟะพะฒั‚ะพั€ะฝะพะณะพ ะพะฑั‡ะธัะปะตะฝะฝั, ะฒะธะบะพะฝัƒัŽั‡ะธ ะบะพะด ั„ัƒะฝะบั†ั–ั— ั‰ะพั€ะฐะทัƒ. + +ะขะพะฑั‚ะพ ั„ัƒะฝะบั†ั–ั ะฟั–ะด ะฝะธะผ ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะฐ ะพะดะธะฝ ั€ะฐะท ะดะปั ะบะพะถะฝะพั— ะบะพะผะฑั–ะฝะฐั†ั–ั— ะฐั€ะณัƒะผะตะฝั‚ั–ะฒ. ะ ะฟะพั‚ั–ะผ ะทะฝะฐั‡ะตะฝะฝั, ะฟะพะฒะตั€ะฝะตะฝั– ะบะพะถะฝะพัŽ ะท ั†ะธั… ะบะพะผะฑั–ะฝะฐั†ั–ะน ะฐั€ะณัƒะผะตะฝั‚ั–ะฒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒัั ะทะฝะพะฒัƒ ั– ะทะฝะพะฒัƒ ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ั„ัƒะฝะบั†ั–ัŽ ะฒะธะบะปะธะบะฐัŽั‚ัŒ ั–ะท ั‚ะพั‡ะฝะพ ั‚ะฐะบะพัŽ ะถ ะบะพะผะฑั–ะฝะฐั†ั–ั”ัŽ ะฐั€ะณัƒะผะตะฝั‚ั–ะฒ. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัƒ ะฒะฐั ั” ั„ัƒะฝะบั†ั–ั: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +ะฒะฐัˆะฐ ะฟั€ะพะณั€ะฐะผะฐ ะผะพะถะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธััŒ ั‚ะฐะบ: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +ะฃ ะฒะธะฟะฐะดะบัƒ ะท ะฝะฐัˆะพัŽ ะทะฐะปะตะถะฝั–ัั‚ัŽ `get_settings()` ั„ัƒะฝะบั†ั–ั ะฒะทะฐะณะฐะปั– ะฝะต ะฟั€ะธะนะผะฐั” ะถะพะดะฝะธั… ะฐั€ะณัƒะผะตะฝั‚ั–ะฒ, ั‚ะพะถ ะฒะพะฝะฐ ะทะฐะฒะถะดะธ ะฟะพะฒะตั€ั‚ะฐั” ั‚ะต ัะฐะผะต ะทะฝะฐั‡ะตะฝะฝั. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะพะฝะฐ ะฟะพะฒะพะดะธั‚ัŒัั ะผะฐะนะถะต ั‚ะฐะบ ัะฐะผะพ, ัะบะฑะธ ั†ะต ะฑัƒะปะฐ ะฟั€ะพัั‚ะพ ะณะปะพะฑะฐะปัŒะฝะฐ ะทะผั–ะฝะฝะฐ. ะะปะต ะพัะบั–ะปัŒะบะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ั„ัƒะฝะบั†ั–ั ะทะฐะปะตะถะฝะพัั‚ั–, ะผะธ ะผะพะถะตะผะพ ะปะตะณะบะพ ะฟะตั€ะตะฟะธัะฐั‚ะธ ั—ั— ะดะปั ั‚ะตัั‚ัƒะฒะฐะฝะฝั. + +`@lru_cache` ั” ั‡ะฐัั‚ะธะฝะพัŽ `functools`, ั‰ะพ ะฒั…ะพะดะธั‚ัŒ ะดะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝะพั— ะฑั–ะฑะปั–ะพั‚ะตะบะธ Python, ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Python ะดะปั `@lru_cache`. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Pydantic Settings ะดะปั ะพะฑั€ะพะฑะบะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ะฐะฑะพ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ะน ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะท ัƒัั–ั”ัŽ ะฟะพั‚ัƒะถะฝั–ัั‚ัŽ ะผะพะดะตะปะตะน Pydantic. + +- ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ะฒะธ ะผะพะถะตั‚ะต ัะฟั€ะพัั‚ะธั‚ะธ ั‚ะตัั‚ัƒะฒะฐะฝะฝั. +- ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท ะฝะธะผ ั„ะฐะนะปะธ `.env`. +- ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `@lru_cache` ะดะฐั” ะทะผะพะณัƒ ัƒะฝะธะบะฝัƒั‚ะธ ะฟะพะฒั‚ะพั€ะฝะพะณะพ ั‡ะธั‚ะฐะฝะฝั ั„ะฐะนะปะฐ dotenv ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ, ะฒะพะดะฝะพั‡ะฐั ะดะพะทะฒะพะปััŽั‡ะธ ะฟะตั€ะตะฟะธััƒะฒะฐั‚ะธ ะนะพะณะพ ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ัƒะฒะฐะฝะฝั. diff --git a/docs/uk/docs/advanced/sub-applications.md b/docs/uk/docs/advanced/sub-applications.md new file mode 100644 index 0000000000..5e611c6ff2 --- /dev/null +++ b/docs/uk/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# ะŸั–ะดะทะฐัั‚ะพััƒะฝะบะธ - ะผะพะฝั‚ัƒะฒะฐะฝะฝั { #sub-applications-mounts } + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะผะฐั‚ะธ ะดะฒะฐ ะฝะตะทะฐะปะตะถะฝั– ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ะท ะฒะปะฐัะฝะธะผะธ ะฝะตะทะฐะปะตะถะฝะธะผะธ OpenAPI ั‚ะฐ ะฒะปะฐัะฝะธะผะธ ั–ะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะณะพะปะพะฒะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ ั– ยซะทะผะพะฝั‚ัƒะฒะฐั‚ะธยป ะพะดะธะฝ ะฐะฑะพ ะบั–ะปัŒะบะฐ ะฟั–ะดะทะฐัั‚ะพััƒะฝะบั–ะฒ. + +## ะœะพะฝั‚ัƒะฒะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** { #mounting-a-fastapi-application } + +ยซะœะพะฝั‚ัƒะฒะฐะฝะฝัยป ะพะทะฝะฐั‡ะฐั” ะดะพะดะฐะฒะฐะฝะฝั ะฟะพะฒะฝั–ัั‚ัŽ ยซะฝะตะทะฐะปะตะถะฝะพะณะพยป ะทะฐัั‚ะพััƒะฝะบัƒ ะฝะฐ ะบะพะฝะบั€ะตั‚ะฝะธะน ัˆะปัั…, ัะบะธะน ะดะฐะปั– ะพะฑั€ะพะฑะปัั” ะฒัะต ะฟั–ะด ั†ะธะผ ัˆะปัั…ะพะผ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ _ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ_, ะพะณะพะปะพัˆะตะฝะธั… ัƒ ั†ัŒะพะผัƒ ะฟั–ะดะทะฐัั‚ะพััƒะฝะบัƒ. + +### ะ—ะฐัั‚ะพััƒะฝะพะบ ะฒะตั€ั…ะฝัŒะพะณะพ ั€ั–ะฒะฝั { #top-level-application } + +ะกะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ั–ั‚ัŒ ะณะพะปะพะฒะฝะธะน, ะฒะตั€ั…ะฝัŒะพั€ั–ะฒะฝะตะฒะธะน ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ั‚ะฐ ะนะพะณะพ _ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ_: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### ะŸั–ะดะทะฐัั‚ะพััƒะฝะพะบ { #sub-application } + +ะŸะพั‚ั–ะผ ัั‚ะฒะพั€ั–ั‚ัŒ ัะฒั–ะน ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ ั‚ะฐ ะนะพะณะพ _ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ_. + +ะฆะตะน ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ - ะฟั€ะพัั‚ะพ ั‰ะต ะพะดะธะฝ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ FastAPI, ะฐะปะต ัะฐะผะต ะนะพะณะพ ะฑัƒะดะต ยซะทะผะพะฝั‚ะพะฒะฐะฝะพยป: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### ะ—ะผะพะฝั‚ัƒะนั‚ะต ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ { #mount-the-sub-application } + +ะฃ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒะตั€ั…ะฝัŒะพะณะพ ั€ั–ะฒะฝั, `app`, ะทะผะพะฝั‚ัƒะนั‚ะต ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ `subapi`. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะนะพะณะพ ะฑัƒะดะต ะทะผะพะฝั‚ะพะฒะฐะฝะพ ะทะฐ ัˆะปัั…ะพะผ `/subapi`: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API { #check-the-automatic-api-docs } + +ะขะตะฟะตั€ ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะบะพะผะฐะฝะดัƒ `fastapi` ะท ะฒะฐัˆะธะผ ั„ะฐะนะปะพะผ: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะ† ะฒั–ะดะบั€ะธะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API ะดะปั ะณะพะปะพะฒะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะปะธัˆะต ะนะพะณะพ ะฒะปะฐัะฝั– _ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ_: + + + +ะ ะฟะพั‚ั–ะผ ะฒั–ะดะบั€ะธะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั ะฟั–ะดะทะฐัั‚ะพััƒะฝะบัƒ ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/subapi/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API ะดะปั ะฟั–ะดะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะปะธัˆะต ะนะพะณะพ ะฒะปะฐัะฝั– _ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ_, ัƒัั– ะท ะฟั€ะฐะฒะธะปัŒะฝะธะผ ะฟั€ะตั„ั–ะบัะพะผ ะฟั–ะดัˆะปัั…ัƒ `/subapi`: + + + +ะฏะบั‰ะพ ะฒะธ ัะฟั€ะพะฑัƒั”ั‚ะต ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฑัƒะดัŒ-ัะบะธะผ ั–ะท ะดะฒะพั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ะฒะพะฝะธ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผัƒั‚ัŒ ะบะพั€ะตะบั‚ะฝะพ, ะฐะดะถะต ะฑั€ะฐัƒะทะตั€ ะทะผะพะถะต ัะฟั–ะปะบัƒะฒะฐั‚ะธัั ะท ะบะพะถะฝะธะผ ะบะพะฝะบั€ะตั‚ะฝะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ ะฐะฑะพ ะฟั–ะดะทะฐัั‚ะพััƒะฝะบะพะผ. + +### ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั–: `root_path` { #technical-details-root-path } + +ะšะพะปะธ ะฒะธ ะผะพะฝั‚ัƒั”ั‚ะต ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต, FastAPI ะฟะพะดะฑะฐั” ะฟั€ะพ ะฟะตั€ะตะดะฐั‡ัƒ ัˆะปัั…ัƒ ะผะพะฝั‚ัƒะฒะฐะฝะฝั ะดะปั ะฟั–ะดะทะฐัั‚ะพััƒะฝะบัƒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะตั…ะฐะฝั–ะทะผ ะทั– ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— ASGI ะฟั–ะด ะฝะฐะทะฒะพัŽ `root_path`. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะฟั–ะดะทะฐัั‚ะพััƒะฝะพะบ ะทะฝะฐั‚ะธะผะต, ั‰ะพ ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ะตะน ะฟั€ะตั„ั–ะบั ัˆะปัั…ัƒ ะดะปั ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะŸั–ะดะทะฐัั‚ะพััƒะฝะพะบ ั‚ะฐะบะพะถ ะผะพะถะต ะผะฐั‚ะธ ะฒะปะฐัะฝั– ะทะผะพะฝั‚ะพะฒะฐะฝั– ะฟั–ะดะทะฐัั‚ะพััƒะฝะบะธ, ั– ะฒัะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะบะพั€ะตะบั‚ะฝะพ, ะพัะบั–ะปัŒะบะธ FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั” ะฒัั– ั†ั– `root_path`. + +ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตัั ะฑั–ะปัŒัˆะต ะฟั€ะพ `root_path` ั– ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ัะฒะฝะพ ะฒ ั€ะพะทะดั–ะปั– [ะ—ะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ](behind-a-proxy.md){.internal-link target=_blank}. diff --git a/docs/uk/docs/advanced/templates.md b/docs/uk/docs/advanced/templates.md new file mode 100644 index 0000000000..9e1ce3709b --- /dev/null +++ b/docs/uk/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# ะจะฐะฑะปะพะฝะธ { #templates } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ั€ัƒัˆั–ะน ัˆะฐะฑะปะพะฝั–ะฒ ะท **FastAPI**. + +ะŸะพัˆะธั€ะตะฝะธะน ะฒะธะฑั–ั€ - Jinja2, ั‚ะพะน ัะฐะผะธะน, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒ Flask ั‚ะฐ ั–ะฝัˆะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐั…. + +ะ„ ัƒั‚ะธะปั–ั‚ะธ ะดะปั ะฟั€ะพัั‚ะพั— ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั—, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** (ะฝะฐะดะฐั” Starlette). + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– { #install-dependencies } + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ั‚ะฐ ะฒัั‚ะฐะฝะพะฒะธะปะธ `jinja2`: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `Jinja2Templates` { #using-jinja2templates } + +- ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `Jinja2Templates`. +- ะกั‚ะฒะพั€ั–ั‚ัŒ ะพะฑ'ั”ะบั‚ `templates`, ัะบะธะน ะฒะธ ะทะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ. +- ะžะณะพะปะพัั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ `Request` ะฒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ัะบะฐ ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ัˆะฐะฑะปะพะฝ. +- ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ัั‚ะฒะพั€ะตะฝั– `templates`, ั‰ะพะฑ ะทั€ะตะฝะดะตั€ะธั‚ะธ ั‚ะฐ ะฟะพะฒะตั€ะฝัƒั‚ะธ `TemplateResponse`; ะฟะตั€ะตะดะฐะนั‚ะต ะฝะฐะทะฒัƒ ัˆะฐะฑะปะพะฝัƒ, ะพะฑ'ั”ะบั‚ `request` ั– ัะปะพะฒะฝะธะบ ยซะบะพะฝั‚ะตะบัั‚ยป ะท ะฟะฐั€ะฐะผะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั, ัะบั– ะฑัƒะดัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝั– ะฒัะตั€ะตะดะธะฝั– ัˆะฐะฑะปะพะฝัƒ Jinja2. + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ”ะพ FastAPI 0.108.0, Starlette 0.29.0, ะฟะฐั€ะฐะผะตั‚ั€ `name` ะฑัƒะฒ ะฟะตั€ัˆะธะผ. + +ะขะฐะบะพะถ ั€ะฐะฝั–ัˆะต, ัƒ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั…, ะพะฑ'ั”ะบั‚ `request` ะฟะตั€ะตะดะฐะฒะฐะฒัั ัะบ ั‡ะฐัั‚ะธะฝะฐ ะฟะฐั€ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั ะฒ ะบะพะฝั‚ะตะบัั‚ั– ะดะปั Jinja2. + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะบะฐะทะฐั‚ะธ `response_class=HTMLResponse`, ั–ะฝั‚ะตั€ั„ะตะนั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต HTML. + +/// + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะœะพะถะฝะฐ ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.templating import Jinja2Templates`. + +**FastAPI** ะฝะฐะดะฐั” ั‚ะพะน ัะฐะผะธะน `starlette.templating` ัะบ `fastapi.templating` ะฟั€ะพัั‚ะพ ะดะปั ะทั€ัƒั‡ะฝะพัั‚ั– ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฑั–ะปัŒัˆั–ัั‚ัŒ ะดะพัั‚ัƒะฟะฝะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฝะฐะดั…ะพะดัั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. ะขะฐะบ ัะฐะผะพ ะท `Request` ั– `StaticFiles`. + +/// + +## ะกั‚ะฒะพั€ะตะฝะฝั ัˆะฐะฑะปะพะฝั–ะฒ { #writing-templates } + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะฟะธัะฐั‚ะธ ัˆะฐะฑะปะพะฝ ัƒ `templates/item.html`, ะฝะฐะฟั€ะธะบะปะฐะด: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### ะ—ะฝะฐั‡ะตะฝะฝั ะบะพะฝั‚ะตะบัั‚ัƒ ัˆะฐะฑะปะพะฝัƒ { #template-context-values } + +ะฃ HTML, ัะบะธะน ะผั–ัั‚ะธั‚ัŒ: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...ะฑัƒะดะต ะฟะพะบะฐะทะฐะฝะพ `id`, ะฒะทัั‚ะธะน ั–ะท ยซะบะพะฝั‚ะตะบัั‚ัƒยป `dict`, ัะบะธะน ะฒะธ ะฟะตั€ะตะดะฐะปะธ: + +```Python +{"id": id} +``` + +ะะฐะฟั€ะธะบะปะฐะด, ะท ID `42` ั†ะต ะฑัƒะดะต ะฒั–ะดะพะฑั€ะฐะถะตะฝะพ ัะบ: + +```html +Item ID: 42 +``` + +### ะั€ะณัƒะผะตะฝั‚ะธ `url_for` ัƒ ัˆะฐะฑะปะพะฝั– { #template-url-for-arguments } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `url_for()` ัƒ ัˆะฐะฑะปะพะฝั– - ะฒะพะฝะฐ ะฟั€ะธะนะผะฐั” ั‚ั– ัะฐะผั– ะฐั€ะณัƒะผะตะฝั‚ะธ, ั‰ะพ ะน ะฒะฐัˆะฐ *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะขะพะถ ั„ั€ะฐะณะผะตะฝั‚: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...ะทะณะตะฝะตั€ัƒั” ะฟะพัะธะปะฐะฝะฝั ะฝะฐ ั‚ะพะน ัะฐะผะธะน URL, ัะบะธะน ะพะฑั€ะพะฑะปัั‚ะธะผะต *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* `read_item(id=id)`. + +ะะฐะฟั€ะธะบะปะฐะด, ะท ID `42` ั†ะต ะฑัƒะดะต ะฒั–ะดะพะฑั€ะฐะถะตะฝะพ ัะบ: + +```html + +``` + +## ะจะฐะฑะปะพะฝะธ ั– ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ { #templates-and-static-files } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `url_for()` ัƒ ัˆะฐะฑะปะพะฝั–, ะฝะฐะฟั€ะธะบะปะฐะด ะท `StaticFiles`, ัะบั– ะฒะธ ะทะผะพะฝั‚ัƒะฒะฐะปะธ ะท `name="static"`. + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ั†ะต ะฟะพัะธะปะฐั‚ะธะผะตั‚ัŒัั ะฝะฐ ั„ะฐะนะป CSS ัƒ `static/styles.css` ะทะฐ ะดะพะฟะพะผะพะณะพัŽ: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +ะ† ะพัะบั–ะปัŒะบะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `StaticFiles`, ั†ะตะน ั„ะฐะนะป CSS ะฑัƒะดะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธััŒ ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ **FastAPI** ะทะฐ URL `/static/styles.css`. + +## ะ”ะตั‚ะฐะปัŒะฝั–ัˆะต { #more-details } + +ะ”ะพะบะปะฐะดะฝั–ัˆะต, ะทะพะบั€ะตะผะฐ ัะบ ั‚ะตัั‚ัƒะฒะฐั‚ะธ ัˆะฐะฑะปะพะฝะธ, ะดะธะฒั–ั‚ัŒัั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Starlette ั‰ะพะดะพ ัˆะฐะฑะปะพะฝั–ะฒ. diff --git a/docs/uk/docs/advanced/testing-dependencies.md b/docs/uk/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000..3061e745d3 --- /dev/null +++ b/docs/uk/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# ะขะตัั‚ัƒะฒะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะท ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝัะผะธ { #testing-dependencies-with-overrides } + +## ะŸะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ัƒะฒะฐะฝะฝั { #overriding-dependencies-during-testing } + +ะ„ ัั†ะตะฝะฐั€ั–ั—, ะบะพะปะธ ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะฟะตั€ะตะฟะธัะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ัƒะฒะฐะฝะฝั. + +ะ’ะธ ะฝะต ั…ะพั‡ะตั‚ะต ะทะฐะฟัƒัะบะฐั‚ะธ ะพั€ะธะณั–ะฝะฐะปัŒะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ะฐะฝั– ะฑัƒะดัŒ-ัะบั– ั—ั— ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–). + +ะะฐั‚ะพะผั–ัั‚ัŒ ะฒะธ ั…ะพั‡ะตั‚ะต ะฝะฐะดะฐั‚ะธ ั–ะฝัˆัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบัƒ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะปะธัˆะต ะฟั–ะด ั‡ะฐั ั‚ะตัั‚ั–ะฒ (ะผะพะถะปะธะฒะพ, ั‚ั–ะปัŒะบะธ ะฒ ะพะบั€ะตะผะธั… ั‚ะตัั‚ะฐั…), ั– ัะบะฐ ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ะทะฝะฐั‡ะตะฝะฝั, ั‰ะพ ะฟั–ะดัั‚ะฐะฒะปัั”ั‚ัŒัั ะฒััŽะดะธ, ะดะต ั€ะฐะฝั–ัˆะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะพัั ะทะฝะฐั‡ะตะฝะฝั ะพั€ะธะณั–ะฝะฐะปัŒะฝะพั— ะทะฐะปะตะถะฝะพัั‚ั–. + +### ะ’ะธะฟะฐะดะบะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั: ะทะพะฒะฝั–ัˆะฝั–ะน ัะตั€ะฒั–ั { #use-cases-external-service } + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะฐั ั” ะทะพะฒะฝั–ัˆะฝั–ะน ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—, ัะบะธะน ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะปะธะบะฐั‚ะธ. + +ะ’ะธ ะฝะฐะดัะธะปะฐั”ั‚ะต ะนะพะผัƒ ั‚ะพะบะตะฝ, ั– ะฒั–ะฝ ะฟะพะฒะตั€ั‚ะฐั” ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะพะฒะฐะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะขะฐะบะธะน ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบ ะผะพะถะต ัั‚ัะณัƒะฒะฐั‚ะธ ะฟะปะฐั‚ัƒ ะทะฐ ะบะพะถะฝะธะน ะทะฐะฟะธั‚, ะฐ ะฒะธะบะปะธะบ ะผะพะถะต ะทะฐะนะผะฐั‚ะธ ะฑั–ะปัŒัˆะต ั‡ะฐััƒ, ะฝั–ะถ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั„ั–ะบัะพะฒะฐะฝะพะณะพ ั„ะฐะปัŒัˆะธะฒะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะดะปั ั‚ะตัั‚ั–ะฒ. + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั€ะพั‚ะตัั‚ัƒะฒะฐั‚ะธ ะทะพะฒะฝั–ัˆะฝัŒะพะณะพ ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะฐ ะพะดะธะฝ ั€ะฐะท, ะฐะปะต ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ ะฒะธะบะปะธะบะฐั‚ะธ ะนะพะณะพ ะดะปั ะบะพะถะฝะพะณะพ ั‚ะตัั‚ัƒ. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ั‰ะพ ะฒะธะบะปะธะบะฐั” ั†ัŒะพะณะพ ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะฐ, ั– ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฒะปะฐัะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบะฐ ะฟะพะฒะตั€ั‚ะฐั” ั„ะฐะปัŒัˆะธะฒะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ะปะธัˆะต ะดะปั ะฒะฐัˆะธั… ั‚ะตัั‚ั–ะฒ. + +### ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฐั‚ั€ะธะฑัƒั‚ `app.dependency_overrides` { #use-the-app-dependency-overrides-attribute } + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ะผะฐั” ะฐั‚ั€ะธะฑัƒั‚ `app.dependency_overrides`, ั†ะต ะฟั€ะพัั‚ะธะน `dict`. + +ะฉะพะฑ ะฟะตั€ะตะฟะธัะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะดะปั ั‚ะตัั‚ัƒะฒะฐะฝะฝั, ะฒะบะฐะถั–ั‚ัŒ ัƒ ะบะปัŽั‡ั– ะพั€ะธะณั–ะฝะฐะปัŒะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ั„ัƒะฝะบั†ั–ัŽ), ะฐ ะทะฝะฐั‡ะตะฝะฝัะผ - ะฒะฐัˆะต ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั– (ั–ะฝัˆัƒ ั„ัƒะฝะบั†ั–ัŽ). + +ะŸั–ัะปั ั†ัŒะพะณะพ FastAPI ะฒะธะบะปะธะบะฐั‚ะธะผะต ั†ะต ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะทะฐะผั–ัั‚ัŒ ะพั€ะธะณั–ะฝะฐะปัŒะฝะพั— ะทะฐะปะตะถะฝะพัั‚ั–. + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะดะปั ะทะฐะปะตะถะฝะพัั‚ั–, ัะบะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะต ะทะฐะฒะณะพะดะฝะพ ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI. + +ะžั€ะธะณั–ะฝะฐะปัŒะฝะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธัั ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ัƒ ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ (ะบะพะปะธ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะต ะทะฝะฐั‡ะตะฝะฝั), ัƒ ะฒะธะบะปะธะบัƒ `.include_router()` ั‚ะพั‰ะพ. + +FastAPI ัƒัะต ะพะดะฝะพ ะทะผะพะถะต ั—ั— ะฟะตั€ะตะฟะธัะฐั‚ะธ. + +/// + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ัะบะธะฝัƒั‚ะธ ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั (ะฒะธะดะฐะปะธั‚ะธ ั—ั…), ะฒัั‚ะฐะฝะพะฒะธะฒัˆะธ ะดะปั `app.dependency_overrides` ะฟะพั€ะพะถะฝั–ะน `dict`: + +```Python +app.dependency_overrides = {} +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะตั€ะตะฟะธััƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะปะธัˆะต ะฟั–ะด ั‡ะฐั ะพะบั€ะตะผะธั… ั‚ะตัั‚ั–ะฒ, ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ะฟะตั€ะตะฟะธััƒะฒะฐะฝะฝั ะฝะฐ ะฟะพั‡ะฐั‚ะบัƒ ั‚ะตัั‚ัƒ (ะฒัะตั€ะตะดะธะฝั– ั‚ะตัั‚ะพะฒะพั— ั„ัƒะฝะบั†ั–ั—) ั– ัะบะธะฝัŒั‚ะต ะนะพะณะพ ะฝะฐะฟั€ะธะบั–ะฝั†ั– (ะฒ ะบั–ะฝั†ั– ั‚ะตัั‚ะพะฒะพั— ั„ัƒะฝะบั†ั–ั—). + +/// diff --git a/docs/uk/docs/advanced/testing-events.md b/docs/uk/docs/advanced/testing-events.md new file mode 100644 index 0000000000..040b4f756f --- /dev/null +++ b/docs/uk/docs/advanced/testing-events.md @@ -0,0 +1,11 @@ +# ะขะตัั‚ัƒะฒะฐะฝะฝั ะฟะพะดั–ะน: ั‚ั€ะธะฒะฐะปั–ัั‚ัŒ ะถะธั‚ั‚ั ั‚ะฐ ะทะฐะฟัƒัะบ - ะฒะธะผะบะฝะตะฝะฝั { #testing-events-lifespan-and-startup-shutdown } + +ะšะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ, ั‰ะพะฑ `lifespan` ะฒะธะบะพะฝัƒะฒะฐะฒัั ัƒ ะฒะฐัˆะธั… ั‚ะตัั‚ะฐั…, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `TestClient` ะท ะพะฟะตั€ะฐั‚ะพั€ะพะผ `with`: + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + +ะ’ะธ ะผะพะถะตั‚ะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฑั–ะปัŒัˆะต ัƒ [ยซะ—ะฐะฟัƒัะบ ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั ัƒ ั‚ะตัั‚ะฐั… ะฝะฐ ะพั„ั–ั†ั–ะนะฝะพะผัƒ ัะฐะนั‚ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Starlette.ยป](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) + +ะ”ะปั ะทะฐัั‚ะฐั€ั–ะปะธั… ะฟะพะดั–ะน `startup` ั– `shutdown` ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `TestClient` ั‚ะฐะบ: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/uk/docs/advanced/testing-websockets.md b/docs/uk/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000..cec576fddf --- /dev/null +++ b/docs/uk/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# ะขะตัั‚ัƒะฒะฐะฝะฝั WebSocket { #testing-websockets } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน `TestClient` ะดะปั ั‚ะตัั‚ัƒะฒะฐะฝะฝั WebSocket. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต `TestClient` ะฒ ั–ะฝัั‚ั€ัƒะบั†ั–ั— `with`, ะฟั–ะดะบะปัŽั‡ะฐัŽั‡ะธััŒ ะดะพ WebSocket: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ะดะธะฒั–ั‚ัŒัั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Starlette ะท ั‚ะตัั‚ัƒะฒะฐะฝะฝั WebSocket. + +/// diff --git a/docs/uk/docs/advanced/using-request-directly.md b/docs/uk/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000..81b90f19b9 --- /dev/null +++ b/docs/uk/docs/advanced/using-request-directly.md @@ -0,0 +1,55 @@ +# ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั Request ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #using-the-request-directly } + +ะ”ะพั‚ะตะฟะตั€ ะฒะธ ะพะณะพะปะพัˆัƒะฒะฐะปะธ ะฟะพั‚ั€ั–ะฑะฝั– ะฒะฐะผ ั‡ะฐัั‚ะธะฝะธ ะทะฐะฟะธั‚ัƒ ั€ะฐะทะพะผ ะท ั—ั… ั‚ะธะฟะฐะผะธ. + +ะžั‚ั€ะธะผัƒัŽั‡ะธ ะดะฐะฝั– ะท: +- ัˆะปัั…ัƒ ัะบ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ; +- ะทะฐะณะพะปะพะฒะบั–ะฒ; +- ะบัƒะบั–; +- ั‚ะพั‰ะพ. + +ะ† ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ **FastAPI** ะฟะตั€ะตะฒั–ั€ัั” ั†ั– ะดะฐะฝั–, ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั—ั… ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะณะตะฝะตั€ัƒั” ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั ะฒะฐัˆะพะณะพ API. + +ะะปะต ะฑัƒะฒะฐัŽั‚ัŒ ัะธั‚ัƒะฐั†ั–ั—, ะบะพะปะธ ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะดะพัั‚ัƒะฟ ะดะพ ะพะฑ'ั”ะบั‚ะฐ `Request` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +## ะ”ะตั‚ะฐะปั– ะฟั€ะพ ะพะฑ'ั”ะบั‚ `Request` { #details-about-the-request-object } + +ะžัะบั–ะปัŒะบะธ ะฟั–ะด ะบะฐะฟะพั‚ะพะผ **FastAPI** - ั†ะต **Starlette** ะท ัˆะฐั€ะพะผ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะทะฒะตั€ั…ัƒ, ะฒะธ ะผะพะถะตั‚ะต ะทะฐ ะฟะพั‚ั€ะตะฑะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะฑ'ั”ะบั‚ `Request` Starlette ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +ะฆะต ั‚ะฐะบะพะถ ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะบั‰ะพ ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะดะฐะฝั– ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ะพะฑ'ั”ะบั‚ะฐ `Request` (ะฝะฐะฟั€ะธะบะปะฐะด, ั‡ะธั‚ะฐั”ั‚ะต ั‚ั–ะปะพ), FastAPI ะฝะต ะฑัƒะดะต ั—ั… ะฟะตั€ะตะฒั–ั€ัั‚ะธ, ะฟะตั€ะตั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฐะฑะพ ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐั‚ะธ (ั‡ะตั€ะตะท OpenAPI ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะณะพ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ API). + +ะ’ะพะดะฝะพั‡ะฐั ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะฟะฐั€ะฐะผะตั‚ั€, ะพะณะพะปะพัˆะตะฝะธะน ะทะฒะธั‡ะฐะนะฝะธะผ ัะฟะพัะพะฑะพะผ (ะฝะฐะฟั€ะธะบะปะฐะด, ั‚ั–ะปะพ ะท ะผะพะดะตะปะปัŽ Pydantic), ั– ะฝะฐะดะฐะปั– ะฑัƒะดะต ะฟะตั€ะตะฒั–ั€ะตะฝะธะน, ะฟะตั€ะตั‚ะฒะพั€ะตะฝะธะน, ะฐะฝะพั‚ะพะฒะฐะฝะธะน ั‚ะพั‰ะพ. + +ะะปะต ั” ะพะบั€ะตะผั– ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะบะพั€ะธัะฝะพ ะพั‚ั€ะธะผะฐั‚ะธ ะพะฑ'ั”ะบั‚ `Request`. + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะพะฑ'ั”ะบั‚ `Request` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #use-the-request-object-directly } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ IP-ะฐะดั€ะตััƒ/ั…ะพัั‚ ะบะปั–ั”ะฝั‚ะฐ ะฒัะตั€ะตะดะธะฝั– ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะ”ะปั ั†ัŒะพะณะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะทะฒะตั€ะฝัƒั‚ะธัั ะดะพ ะทะฐะฟะธั‚ัƒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +ะฏะบั‰ะพ ะฒะบะฐะทะฐั‚ะธ ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `Request`, **FastAPI** ะฟะตั€ะตะดะฐัั‚ัŒ ัƒ ะฝัŒะพะณะพ ะพะฑ'ั”ะบั‚ `Request`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐัƒะฒะฐะถั‚ะต, ั‰ะพ ะฒ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ ะฟะพั€ัะด ั–ะท ะฟะฐั€ะฐะผะตั‚ั€ะพะผ ะทะฐะฟะธั‚ัƒ. + +ะขะพะผัƒ ะฟะฐั€ะฐะผะตั‚ั€ ัˆะปัั…ัƒ ะฑัƒะดะต ะฒะธั‚ัะณะฝัƒั‚ะพ, ะฟะตั€ะตะฒั–ั€ะตะฝะพ, ะฟะตั€ะตั‚ะฒะพั€ะตะฝะพ ะดะพ ะฒะบะฐะทะฐะฝะพะณะพ ั‚ะธะฟัƒ ั‚ะฐ ะฐะฝะพั‚ะพะฒะฐะฝะพ ะฒ OpenAPI. + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ั–ะฝัˆั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะทะฒะธั‡ะฐะนะฝะธะผ ั‡ะธะฝะพะผ ั– ะดะพะดะฐั‚ะบะพะฒะพ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ `Request`. + +/// + +## ะ”ะพะบัƒะผะตะฝั‚ะฐั†ั–ั `Request` { #request-documentation } + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ะฟั€ะพ ะพะฑ'ั”ะบั‚ `Request` ะฝะฐ ะพั„ั–ั†ั–ะนะฝะพะผัƒ ัะฐะนั‚ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Starlette. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.requests import Request`. + +**FastAPI** ะฝะฐะดะฐั” ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัะบ ะทั€ัƒั‡ะฝั–ัั‚ัŒ ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฒั–ะฝ ะฟะพั…ะพะดะธั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ั–ะท Starlette. + +/// diff --git a/docs/uk/docs/advanced/websockets.md b/docs/uk/docs/advanced/websockets.md new file mode 100644 index 0000000000..21bb61d7e9 --- /dev/null +++ b/docs/uk/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ WebSockets ะท **FastAPI**. + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ `websockets` { #install-websockets } + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ั‚ะฐ ะฒัั‚ะฐะฝะพะฒะธะปะธ `websockets` (ะฑั–ะฑะปั–ะพั‚ะตะบัƒ Python, ั‰ะพ ะฟะพะปะตะณัˆัƒั” ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั€ะพั‚ะพะบะพะปัƒ ยซWebSocketยป): + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## ะšะปั–ั”ะฝั‚ WebSockets { #websockets-client } + +### ะฃ ะฟั€ะพะดะฐะบัˆะตะฝั– { #in-production } + +ะฃ ะฒะฐัˆั–ะน ะฟั€ะพะดะฐะบัˆะตะฝ-ัะธัั‚ะตะผั– ัƒ ะฒะฐั, ะฝะฐะฟะตะฒะฝะพ, ั” ั„ั€ะพะฝั‚ะตะฝะด, ัั‚ะฒะพั€ะตะฝะธะน ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ััƒั‡ะฐัะฝะพะณะพ ั„ั€ะตะนะผะฒะพั€ะบัƒ ะฝะฐ ะบัˆั‚ะฐะปั‚ React, Vue.js ะฐะฑะพ Angular. + +ะ”ะปั ัะฟั–ะปะบัƒะฒะฐะฝะฝั ั‡ะตั€ะตะท WebSockets ะท ะฑะตะบะตะฝะดะพะผ ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ัƒั‚ะธะปั–ั‚ะธ ะฒะฐัˆะพะณะพ ั„ั€ะพะฝั‚ะตะฝะดัƒ. + +ะะฑะพ ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ะฝะฐั‚ะธะฒะฝะธะน ะผะพะฑั–ะปัŒะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ, ั‰ะพ ะฝะฐะฟั€ัะผัƒ ัะฟั–ะปะบัƒั”ั‚ัŒัั ะท ะฒะฐัˆะธะผ WebSocket-ะฑะตะบะตะฝะดะพะผ ะฝะฐั‚ะธะฒะฝะธะผ ะบะพะดะพะผ. + +ะะฑะพ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ัะฟะพัั–ะฑ ัะฟั–ะปะบัƒะฒะฐะฝะฝั ะท ะบั–ะฝั†ะตะฒะพัŽ ั‚ะพั‡ะบะพัŽ WebSocket. + +--- + +ะะปะต ะดะปั ั†ัŒะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ะผะธ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ ะดัƒะถะต ะฟั€ะพัั‚ะธะน HTML-ะดะพะบัƒะผะตะฝั‚ ะท ะฝะตะฒะตะปะธะบะธะผ JavaScript, ัƒัะต ะฒัะตั€ะตะดะธะฝั– ะดะพะฒะณะพะณะพ ั€ัะดะบะฐ. + +ะ—ะฒั–ัะฝะพ, ั†ะต ะฝะต ะพะฟั‚ะธะผะฐะปัŒะฝะพ ั– ะฒะธ ะฑ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ั†ะต ัƒ ะฟั€ะพะดะฐะบัˆะตะฝั–. + +ะฃ ะฟั€ะพะดะฐะบัˆะตะฝั– ะฒะธ ะฑ ะฒะธะบะพั€ะธัั‚ะฐะปะธ ะพะดะธะฝ ะท ะฒะฐั€ั–ะฐะฝั‚ั–ะฒ ะฒะธั‰ะต. + +ะะปะต ั†ะต ะฝะฐะนะฟั€ะพัั‚ั–ัˆะธะน ัะฟะพัั–ะฑ ะทะพัะตั€ะตะดะธั‚ะธัั ะฝะฐ ัะตั€ะฒะตั€ะฝั–ะน ั‡ะฐัั‚ะธะฝั– WebSockets ั– ะผะฐั‚ะธ ั€ะพะฑะพั‡ะธะน ะฟั€ะธะบะปะฐะด: + +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} + +## ะกั‚ะฒะพั€ั–ั‚ัŒ `websocket` { #create-a-websocket } + +ะฃ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** ัั‚ะฒะพั€ั–ั‚ัŒ `websocket`: + +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette.websockets import WebSocket`. + +**FastAPI** ะฝะฐะดะฐั” ั‚ะพะน ัะฐะผะธะน `WebSocket` ะฝะฐะฟั€ัะผัƒ ัะบ ะทั€ัƒั‡ะฝั–ัั‚ัŒ ะดะปั ะฒะฐั, ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฒั–ะฝ ะฟะพั…ะพะดะธั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +/// + +## ะžั‡ั–ะบัƒะนั‚ะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ั‚ะฐ ะฝะฐะดัะธะปะฐะนั‚ะต ะฟะพะฒั–ะดะพะผะปะตะฝะฝั { #await-for-messages-and-send-messages } + +ะฃ ะฒะฐัˆะพะผัƒ ะผะฐั€ัˆั€ัƒั‚ั– WebSocket ะฒะธ ะผะพะถะตั‚ะต `await` ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ั– ะฝะฐะดัะธะปะฐั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั. + +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} + +ะ’ะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ั‚ะฐ ะฝะฐะดัะธะปะฐั‚ะธ ะฑั–ะฝะฐั€ะฝั–, ั‚ะตะบัั‚ะพะฒั– ั‚ะฐ JSON-ะดะฐะฝั–. + +## ะกะฟั€ะพะฑัƒะนั‚ะต { #try-it } + +ะฏะบั‰ะพ ะฒะฐัˆ ั„ะฐะนะป ะฝะฐะทะธะฒะฐั”ั‚ัŒัั `main.py`, ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะบะพะผะฐะฝะดะพัŽ: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะ’ั–ะดะบั€ะธะนั‚ะต ัƒ ะฑั€ะฐัƒะทะตั€ั– http://127.0.0.1:8000. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฟั€ะพัั‚ัƒ ัั‚ะพั€ั–ะฝะบัƒ ะฝะฐ ะบัˆั‚ะฐะปั‚: + + + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะฒะพะดะธั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ัƒ ะฟะพะปะต ะฒะฒะพะดัƒ ั‚ะฐ ะฝะฐะดัะธะปะฐั‚ะธ ั—ั…: + + + +ะ† ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ะท WebSockets ะฒั–ะดะฟะพะฒั–ัั‚ัŒ: + + + +ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะดัะธะปะฐั‚ะธ (ั– ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ) ะฑะฐะณะฐั‚ะพ ะฟะพะฒั–ะดะพะผะปะตะฝัŒ: + + + +ะ† ะฒัั– ะฒะพะฝะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒ ั‚ะต ัะฐะผะต ะท'ั”ะดะฝะฐะฝะฝั WebSocket. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `Depends` ั‚ะฐ ั–ะฝัˆะพะณะพ { #using-depends-and-others } + +ะฃ ะบั–ะฝั†ะตะฒะธั… ั‚ะพั‡ะบะฐั… WebSocket ะฒะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะท `fastapi` ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +ะ’ะพะฝะธ ะฟั€ะฐั†ัŽัŽั‚ัŒ ั‚ะฐะบ ัะฐะผะพ, ัะบ ะดะปั ั–ะฝัˆะธั… ะตะฝะดะฟะพะนะฝั‚ั–ะฒ FastAPI/*ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*: + +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} + +/// info + +ะžัะบั–ะปัŒะบะธ ั†ะต WebSocket, ะฝะต ะผะฐั” ัะตะฝััƒ ะฟั–ะดะฝั–ะผะฐั‚ะธ `HTTPException`, ะฝะฐั‚ะพะผั–ัั‚ัŒ ะผะธ ะฟั–ะดะฝั–ะผะฐั”ะผะพ `WebSocketException`. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะด ะทะฐะบั€ะธั‚ั‚ั ะท ั‡ะธะฝะฝะธั… ะบะพะดั–ะฒ, ะฒะธะทะฝะฐั‡ะตะฝะธั… ัƒ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั—. + +/// + +### ะกะฟั€ะพะฑัƒะนั‚ะต WebSockets ั–ะท ะทะฐะปะตะถะฝะพัั‚ัะผะธ { #try-the-websockets-with-dependencies } + +ะฏะบั‰ะพ ะฒะฐัˆ ั„ะฐะนะป ะฝะฐะทะธะฒะฐั”ั‚ัŒัั `main.py`, ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะบะพะผะฐะฝะดะพัŽ: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะ’ั–ะดะบั€ะธะนั‚ะต ัƒ ะฑั€ะฐัƒะทะตั€ั– http://127.0.0.1:8000. + +ะขะฐะผ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ: + +* ยซItem IDยป, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒ ัˆะปัั…ัƒ. +* ยซTokenยป, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัะบ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ. + +/// tip + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `token` ะฑัƒะดะต ะพะฑั€ะพะฑะปะตะฝะพ ะทะฐะปะตะถะฝั–ัั‚ัŽ. + +/// + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒะธ ะทะผะพะถะตั‚ะต ะฟั–ะด'ั”ะดะฝะฐั‚ะธ WebSocket, ะฐ ะดะฐะปั– ะฝะฐะดัะธะปะฐั‚ะธ ะน ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั: + + + +## ะžะฑั€ะพะฑะบะฐ ะฒั–ะดะบะปัŽั‡ะตะฝัŒ ั– ะบั–ะปัŒะบะพั… ะบะปั–ั”ะฝั‚ั–ะฒ { #handling-disconnections-and-multiple-clients } + +ะšะพะปะธ ะท'ั”ะดะฝะฐะฝะฝั WebSocket ะทะฐะบั€ะธะฒะฐั”ั‚ัŒัั, `await websocket.receive_text()` ะฟั–ะดะฝั–ะผะต ะฒะธะฝัั‚ะพะบ `WebSocketDisconnect`, ัะบะธะน ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตั…ะพะฟะธั‚ะธ ะน ะพะฑั€ะพะฑะธั‚ะธ, ัะบ ัƒ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั–. + +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} + +ะฉะพะฑ ัะฟั€ะพะฑัƒะฒะฐั‚ะธ: + +* ะ’ั–ะดะบั€ะธะนั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ ัƒ ะบั–ะปัŒะบะพั… ะฒะบะปะฐะดะบะฐั… ะฑั€ะฐัƒะทะตั€ะฐ. +* ะะฐะดัะธะปะฐะนั‚ะต ะท ะฝะธั… ะฟะพะฒั–ะดะพะผะปะตะฝะฝั. +* ะŸะพั‚ั–ะผ ะทะฐะบั€ะธะนั‚ะต ะพะดะฝัƒ ะท ะฒะบะปะฐะดะพะบ. + +ะฆะต ะฟั–ะดะฝั–ะผะต ะฒะธะฝัั‚ะพะบ `WebSocketDisconnect`, ั– ะฒัั– ั–ะฝัˆั– ะบะปั–ั”ะฝั‚ะธ ะพั‚ั€ะธะผะฐัŽั‚ัŒ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะฝะฐ ะบัˆั‚ะฐะปั‚: + +``` +Client #1596980209979 left the chat +``` + +/// tip + +ะ—ะฐัั‚ะพััƒะฝะพะบ ะฒะธั‰ะต - ั†ะต ะผั–ะฝั–ะผะฐะปัŒะฝะธะน ั– ะฟั€ะพัั‚ะธะน ะฟั€ะธะบะปะฐะด, ั‰ะพ ะดะตะผะพะฝัั‚ั€ัƒั”, ัะบ ะพะฑั€ะพะฑะปัั‚ะธ ั‚ะฐ ั€ะพะทัะธะปะฐั‚ะธ ะฟะพะฒั–ะดะพะผะปะตะฝะฝั ะบั–ะปัŒะบะพะผ ะท'ั”ะดะฝะฐะฝะฝัะผ WebSocket. + +ะะปะต ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ ะฒัะต ะพะฑั€ะพะฑะปัั”ั‚ัŒัั ะฒ ะฟะฐะผ'ัั‚ั–, ะฒ ะพะดะฝะพะผัƒ ัะฟะธัะบัƒ, ั†ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะปะธัˆะต ะฟะพะบะธ ะฟั€ะพั†ะตั ะทะฐะฟัƒั‰ะตะฝะธะน, ั– ะปะธัˆะต ะท ะพะดะฝะธะผ ะฟั€ะพั†ะตัะพะผ. + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะต ั‰ะพััŒ ะฟั€ะพัั‚ะต ะดะปั ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะท FastAPI, ะฐะปะต ะฑั–ะปัŒัˆ ะฝะฐะดั–ะนะฝะต, ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ Redis, PostgreSQL ั‡ะธ ั–ะฝัˆะธั…, ะฟะตั€ะตะณะปัะฝัŒั‚ะต encode/broadcaster. + +/// + +## ะ”ะตั‚ะฐะปัŒะฝั–ัˆะต { #more-info } + +ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะผะพะถะปะธะฒะพัั‚ั–, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Starlette: + +* ะšะปะฐั `WebSocket`. +* ะžะฑั€ะพะฑะบะฐ WebSocket ะฝะฐ ะพัะฝะพะฒั– ะบะปะฐัั–ะฒ. diff --git a/docs/uk/docs/advanced/wsgi.md b/docs/uk/docs/advanced/wsgi.md new file mode 100644 index 0000000000..8969241350 --- /dev/null +++ b/docs/uk/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# ะŸั–ะดะบะปัŽั‡ะตะฝะฝั WSGI - Flask, Django ั‚ะฐ ั–ะฝัˆั– { #including-wsgi-flask-django-others } + +ะ’ะธ ะผะพะถะตั‚ะต ะผะพะฝั‚ัƒะฒะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ WSGI, ัะบ ะฒะธ ะฑะฐั‡ะธะปะธ ะฒ [ะŸั–ะดะทะฐัั‚ะพััƒะฝะบะธ - ะผะพะฝั‚ัƒะฒะฐะฝะฝั](sub-applications.md){.internal-link target=_blank}, [ะ—ะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ](behind-a-proxy.md){.internal-link target=_blank}. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `WSGIMiddleware` ั– ะพะฑะณะพั€ะฝัƒั‚ะธ ะฝะธะผ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ WSGI, ะฝะฐะฟั€ะธะบะปะฐะด Flask, Django ั‚ะพั‰ะพ. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `WSGIMiddleware` { #using-wsgimiddleware } + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ”ะปั ั†ัŒะพะณะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `a2wsgi`, ะฝะฐะฟั€ะธะบะปะฐะด ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `pip install a2wsgi`. + +/// + +ะŸะพั‚ั€ั–ะฑะฝะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ `WSGIMiddleware` ะท `a2wsgi`. + +ะŸะพั‚ั–ะผ ะพะฑะณะพั€ะฝั–ั‚ัŒ ะทะฐัั‚ะพััƒะฝะพะบ WSGI (ะฝะฐะฟั€., Flask) ั†ะธะผ ะฟั€ะพะผั–ะถะฝะธะผ ะฟั€ะพะณั€ะฐะผะฝะธะผ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝัะผ. + +ะ† ะทะผะพะฝั‚ัƒะนั‚ะต ะนะพะณะพ ะฟั–ะด ะฟะตะฒะฝะธะผ ัˆะปัั…ะพะผ. + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ ะฐะฝั–ัˆะต ั€ะตะบะพะผะตะฝะดัƒะฒะฐะปะพัั ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `WSGIMiddleware` ะท `fastapi.middleware.wsgi`, ะฐะปะต ั‚ะตะฟะตั€ ะนะพะณะพ ะฒะธะทะฝะฐะฝะพ ะทะฐัั‚ะฐั€ั–ะปะธะผ. + +ะ—ะฐะผั–ัั‚ัŒ ั†ัŒะพะณะพ ั€ะฐะดะธะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟะฐะบะตั‚ `a2wsgi`. ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะปะธัˆะฐั”ั‚ัŒัั ั‚ะฐะบะธะผ ัะฐะผะธะผ. + +ะŸั€ะพัั‚ะพ ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ัƒ ะฒะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ะฟะฐะบะตั‚ `a2wsgi`, ั– ั–ะผะฟะพั€ั‚ัƒะนั‚ะต `WSGIMiddleware` ะบะพั€ะตะบั‚ะฝะพ ะท `a2wsgi`. + +/// + +## ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะขะตะฟะตั€ ะบะพะถะตะฝ ะทะฐะฟะธั‚ ะทะฐ ัˆะปัั…ะพะผ `/v1/` ะพะฑั€ะพะฑะปัั‚ะธะผะตั‚ัŒัั ะทะฐัั‚ะพััƒะฝะบะพะผ Flask. + +ะ ั€ะตัˆั‚ะฐ - **FastAPI**. + +ะฏะบั‰ะพ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต ั†ะต ะน ะฟะตั€ะตะนะดะตั‚ะต ะฝะฐ http://localhost:8000/v1/, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ ะฒั–ะด Flask: + +```txt +Hello, World from Flask! +``` + +ะ ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะฝะฐ http://localhost:8000/v2, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ ะฒั–ะด FastAPI: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/uk/docs/async.md b/docs/uk/docs/async.md new file mode 100644 index 0000000000..baf4720542 --- /dev/null +++ b/docs/uk/docs/async.md @@ -0,0 +1,444 @@ +# ะ ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ั– async / await { #concurrency-and-async-await } + +ะ”ะตั‚ะฐะปั– ั‰ะพะดะพ ัะธะฝั‚ะฐะบัะธััƒ `async def` ะดะปั ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั– ะดะตัะบั– ะฒั–ะดะพะผะพัั‚ั– ะฟั€ะพ ะฐัะธะฝั…ั€ะพะฝะฝะธะน ะบะพะด, ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ั– ะฟะฐั€ะฐะปะตะปั–ะทะผ. + +## ะŸะพัะฟั–ัˆะฐั”ั‚ะต? { #in-a-hurry } + +TL;DR: + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัั‚ะพั€ะพะฝะฝั– ะฑั–ะฑะปั–ะพั‚ะตะบะธ, ัะบั– ะฒะธะผะฐะณะฐัŽั‚ัŒ ะฒะธะบะปะธะบัƒ ะท `await`, ะฝะฐะฟั€ะธะบะปะฐะด: + +```Python +results = await some_library() +``` + +ะขะพะดั– ะพะณะพะปะพัˆัƒะนั‚ะต ะฒะฐัˆั– ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะท `async def`, ะฝะฐะฟั€ะธะบะปะฐะด: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `await` ะปะธัˆะต ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ะน, ัั‚ะฒะพั€ะตะฝะธั… ะท `async def`. + +/// + +--- + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัั‚ะพั€ะพะฝะฝัŽ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ, ัะบะฐ ะฒะทะฐั”ะผะพะดั–ั” ะท ั‡ะธะผะพััŒ (ะฑะฐะทะฐ ะดะฐะฝะธั…, API, ั„ะฐะนะปะพะฒะฐ ัะธัั‚ะตะผะฐ ั‚ะพั‰ะพ) ั– ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `await` (ะฝะฐั€ะฐะทั– ั†ะต ัั‚ะพััƒั”ั‚ัŒัั ะฑั–ะปัŒัˆะพัั‚ั– ะฑั–ะฑะปั–ะพั‚ะตะบ ะฑะฐะท ะดะฐะฝะธั…), ั‚ะพะดั– ะพะณะพะปะพัˆัƒะนั‚ะต ะฒะฐัˆั– ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ัะบ ะทะฐะทะฒะธั‡ะฐะน, ะฟั€ะพัั‚ะพ ะท `def`, ะฝะฐะฟั€ะธะบะปะฐะด: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +ะฏะบั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ (ัะบะธะผะพััŒ ั‡ะธะฝะพะผ) ะฝะต ะผะฐั” ะบะพะผัƒะฝั–ะบัƒะฒะฐั‚ะธ ะท ั‡ะธะผะพััŒ ั–ะฝัˆะธะผ ั– ั‡ะตะบะฐั‚ะธ ะฝะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `async def`, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `await` ะฒัะตั€ะตะดะธะฝั–. + +--- + +ะฏะบั‰ะพ ะฒะธ ะฝะต ะฟะตะฒะฝั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะทะฒะธั‡ะฐะนะฝะธะน `def`. + +--- + +ะŸั€ะธะผั–ั‚ะบะฐ: ะฒะธ ะผะพะถะตั‚ะต ะทะผั–ัˆัƒะฒะฐั‚ะธ `def` ั– `async def` ัƒ ะฒะฐัˆะธั… ั„ัƒะฝะบั†ั–ัั… ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ัะบั–ะปัŒะบะธ ะทะฐะฒะณะพะดะฝะพ ั– ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะบะพะถะฝัƒ ะท ะฝะธั… ะฝะฐะนะบั€ะฐั‰ะธะผ ะดะปั ะฒะฐั ัะฟะพัะพะฑะพะผ. FastAPI ะทั€ะพะฑะธั‚ัŒ ะท ะฝะธะผะธ ะฒัะต ะฟั€ะฐะฒะธะปัŒะฝะพ. + +ะฃ ะฑัƒะดัŒ-ัะบะพะผัƒ ะท ะฝะฐะฒะตะดะตะฝะธั… ะฒะธะฟะฐะดะบั–ะฒ FastAPI ะฒัะต ะพะดะฝะพ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะฐัะธะฝั…ั€ะพะฝะฝะพ ั– ะฑัƒะดะต ะฝะฐะดะทะฒะธั‡ะฐะนะฝะพ ัˆะฒะธะดะบะธะผ. + +ะะปะต ัะปั–ะดัƒัŽั‡ะธ ะบั€ะพะบะฐะผ ะฒะธั‰ะต, ะฒั–ะฝ ะทะผะพะถะต ะทั€ะพะฑะธั‚ะธ ะดะตัะบั– ะพะฟั‚ะธะผั–ะทะฐั†ั–ั— ะฟั€ะพะดัƒะบั‚ะธะฒะฝะพัั‚ั–. + +## ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #technical-details } + +ะกัƒั‡ะฐัะฝั– ะฒะตั€ัั–ั— Python ะผะฐัŽั‚ัŒ ะฟั–ะดั‚ั€ะธะผะบัƒ ยซะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ ะบะพะดัƒยป ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะฐะบ ะทะฒะฐะฝะธั… ยซัะฟั–ะฒะฟั€ะพะณั€ะฐะผยป ะท ัะธะฝั‚ะฐะบัะธัะพะผ **`async` ั– `await`**. + +ะ ะพะทะณะปัะฝัŒะผะพ ั†ัŽ ั„ั€ะฐะทัƒ ะฟะพ ั‡ะฐัั‚ะธะฝะฐั… ัƒ ัะตะบั†ั–ัั… ะฝะธะถั‡ะต: + +- ะัะธะฝั…ั€ะพะฝะฝะธะน ะบะพะด +- `async` ั– `await` +- ะกะฟั–ะฒะฟั€ะพะณั€ะฐะผะธ + +## ะัะธะฝั…ั€ะพะฝะฝะธะน ะบะพะด { #asynchronous-code } + +ะัะธะฝั…ั€ะพะฝะฝะธะน ะบะพะด ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะผะพะฒะฐ ๐Ÿ’ฌ ะผะฐั” ัะฟะพัั–ะฑ ัะบะฐะทะฐั‚ะธ ะบะพะผะฟโ€™ัŽั‚ะตั€ัƒ/ะฟั€ะพะณั€ะฐะผั– ๐Ÿค–, ั‰ะพ ะฒ ะฟะตะฒะฝะธะน ะผะพะผะตะฝั‚ ัƒ ะบะพะดั– ะฒั–ะฝ ๐Ÿค– ะผะฐั” ะฟะพั‡ะตะบะฐั‚ะธ, ะฟะพะบะธ ยซั‰ะพััŒ ั–ะฝัˆะตยป ะทะฐะฒะตั€ัˆะธั‚ัŒัั ะดะตััŒ ั‰ะต. ะกะบะฐะถั–ะผะพ, ั†ะต ยซั‰ะพััŒ ั–ะฝัˆะตยป ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซslow-fileยป ๐Ÿ“. + +ะžั‚ะถะต, ะฒ ั†ะตะน ั‡ะฐั ะบะพะผะฟโ€™ัŽั‚ะตั€ ะผะพะถะต ะฟั–ั‚ะธ ั– ะทั€ะพะฑะธั‚ะธ ั–ะฝัˆัƒ ั€ะพะฑะพั‚ัƒ, ะดะพะบะธ ยซslow-fileยป ๐Ÿ“ ะทะฐะฒะตั€ัˆัƒั”ั‚ัŒัั. + +ะ”ะฐะปั– ะบะพะผะฟโ€™ัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะฐ ๐Ÿค– ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะตั‚ัŒัั ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะผะฐั‚ะธะผะต ะผะพะถะปะธะฒั–ัั‚ัŒ, ะฑะพ ะทะฝะพะฒัƒ ั‡ะตะบะฐั”, ะฐะฑะพ ะบะพะปะธ ะฒั–ะฝ ๐Ÿค– ะทะฐะฒะตั€ัˆะธะฒ ัƒััŽ ั€ะพะฑะพั‚ัƒ, ัะบะฐ ะฑัƒะปะฐ ะฒ ะฝัŒะพะณะพ ะฝะฐ ั‚ะพะน ะผะพะผะตะฝั‚. ะ† ะฒั–ะฝ ๐Ÿค– ะฟะตั€ะตะฒั–ั€ะธั‚ัŒ, ั‡ะธ ัะบะฐััŒ ั–ะท ะทะฐะดะฐั‡, ะฝะฐ ัะบั– ะฒั–ะฝ ั‡ะตะบะฐะฒ, ัƒะถะต ะทะฐะฒะตั€ัˆะธะปะฐัั, ะฒะธะบะพะฝะฐะฒัˆะธ ะฒัะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ. + +ะŸะพั‚ั–ะผ ะฒั–ะฝ ๐Ÿค– ะฑะตั€ะต ะฟะตั€ัˆัƒ ะทะฐะฒะตั€ัˆะตะฝัƒ ะทะฐะดะฐั‡ัƒ (ัะบะฐะถั–ะผะพ, ะฝะฐัˆ ยซslow-fileยป ๐Ÿ“) ั– ะฟั€ะพะดะพะฒะถัƒั” ั€ะพะฑะธั‚ะธ ั‚ะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะปะพ ะทั€ะพะฑะธั‚ะธ ะท ะฝะตัŽ. + +ะฆะต ยซั‡ะตะบะฐั‚ะธ ะฝะฐ ั‰ะพััŒ ั–ะฝัˆะตยป ะทะฐะทะฒะธั‡ะฐะน ัั‚ะพััƒั”ั‚ัŒัั ะพะฟะตั€ะฐั†ั–ะน I/O, ัะบั– ะฒั–ะดะฝะพัะฝะพ ยซะฟะพะฒั–ะปัŒะฝั–ยป (ะฟะพั€ั–ะฒะฝัะฝะพ ะทั– ัˆะฒะธะดะบั–ัั‚ัŽ ะฟั€ะพั†ะตัะพั€ะฐ ั‚ะฐ ะฟะฐะผโ€™ัั‚ั– ะท ะดะพะฒั–ะปัŒะฝะธะผ ะดะพัั‚ัƒะฟะพะผ), ะฝะฐะฟั€ะธะบะปะฐะด, ะพั‡ั–ะบัƒะฒะฐะฝะฝั: + +- ะดะฐะฝะธั… ะฒั–ะด ะบะปั–ั”ะฝั‚ะฐ, ั‰ะพ ะฝะฐะดัะธะปะฐัŽั‚ัŒัั ะผะตั€ะตะถะตัŽ +- ะดะฐะฝะธั…, ะฝะฐะดั–ัะปะฐะฝะธั… ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ, ัะบั– ะบะปั–ั”ะฝั‚ ะผะฐั” ะพั‚ั€ะธะผะฐั‚ะธ ะผะตั€ะตะถะตัŽ +- ะฒะผั–ัั‚ัƒ ั„ะฐะนะปะฐ ะฝะฐ ะดะธัะบัƒ, ัะบะธะน ัะธัั‚ะตะผะฐ ะผะฐั” ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ั– ะฟะตั€ะตะดะฐั‚ะธ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ +- ะฒะผั–ัั‚ัƒ, ัะบะธะน ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฟะตั€ะตะดะฐะฒ ัะธัั‚ะตะผั–, ั‰ะพะฑ ะฒั–ะฝ ะฑัƒะฒ ะทะฐะฟะธัะฐะฝะธะน ะฝะฐ ะดะธัะบ +- ะฒั–ะดะดะฐะปะตะฝะพั— ะพะฟะตั€ะฐั†ั–ั— API +- ะทะฐะฒะตั€ัˆะตะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ะฑะฐะทะธ ะดะฐะฝะธั… +- ะฟะพะฒะตั€ะฝะตะฝะฝั ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ ะทะฐะฟะธั‚ัƒ ะดะพ ะฑะฐะทะธ ะดะฐะฝะธั… +- ั‚ะพั‰ะพ + +ะžัะบั–ะปัŒะบะธ ั‡ะฐั ะฒะธะบะพะฝะฐะฝะฝั ะฟะตั€ะตะฒะฐะถะฝะพ ะฒะธั‚ั€ะฐั‡ะฐั”ั‚ัŒัั ะฝะฐ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ะน I/O, ั—ั… ะฝะฐะทะธะฒะฐัŽั‚ัŒ ะพะฟะตั€ะฐั†ั–ัะผะธ ยซI/O boundยป. + +ะฆะต ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซะฐัะธะฝั…ั€ะพะฝะฝะธะผยป, ั‚ะพะผัƒ ั‰ะพ ะบะพะผะฟโ€™ัŽั‚ะตั€ัƒ/ะฟั€ะพะณั€ะฐะผั– ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒั‚ะธ ยซัะธะฝั…ั€ะพะฝั–ะทะพะฒะฐะฝะธะผะธยป ะท ะฟะพะฒั–ะปัŒะฝะพัŽ ะทะฐะดะฐั‡ะตัŽ, ะพั‡ั–ะบัƒัŽั‡ะธ ั‚ะพั‡ะฝะพะณะพ ะผะพะผะตะฝั‚ัƒ ั—ั— ะทะฐะฒะตั€ัˆะตะฝะฝั, ะฝั–ั‡ะพะณะพ ะฝะต ั€ะพะฑะปัั‡ะธ, ะปะธัˆะต ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ั€ะตะทัƒะปัŒั‚ะฐั‚ ะทะฐะดะฐั‡ั– ั‚ะฐ ะฟั€ะพะดะพะฒะถะธั‚ะธ ั€ะพะฑะพั‚ัƒ. + +ะะฐั‚ะพะผั–ัั‚ัŒ, ัƒ ยซะฐัะธะฝั…ั€ะพะฝะฝั–ะนยป ัะธัั‚ะตะผั– ั‰ะพะนะฝะพ ะทะฐะฒะตั€ัˆะตะฝะฐ ะทะฐะดะฐั‡ะฐ ะผะพะถะต ั‚ั€ะพั…ะธ ะทะฐั‡ะตะบะฐั‚ะธ ะฒ ั‡ะตั€ะทั– (ะบั–ะปัŒะบะฐ ะผั–ะบั€ะพัะตะบัƒะฝะด), ะดะพะบะธ ะบะพะผะฟโ€™ัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะฐ ะทะฐะฒะตั€ัˆะธั‚ัŒ ั‚ะต, ั‰ะพ ะฟั–ัˆะพะฒ ั€ะพะฑะธั‚ะธ, ะฐ ะฟะพั‚ั–ะผ ะฟะพะฒะตั€ะฝะตั‚ัŒัั, ั‰ะพะฑ ะทะฐะฑั€ะฐั‚ะธ ั€ะตะทัƒะปัŒั‚ะฐั‚ะธ ั– ะฟั€ะพะดะพะฒะถะธั‚ะธ ั€ะพะฑะพั‚ัƒ ะท ะฝะธะผะธ. + +ะ”ะปั ยซัะธะฝั…ั€ะพะฝะฝะพะณะพยป (ะฝะฐ ะฟั€ะพั‚ะธะฒะฐะณัƒ ยซะฐัะธะฝั…ั€ะพะฝะฝะพะผัƒยป) ั‡ะฐัั‚ะพ ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ั‚ะตั€ะผั–ะฝ ยซะฟะพัะปั–ะดะพะฒะฝะธะนยป, ะฑะพ ะบะพะผะฟโ€™ัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะฐ ัะปั–ะดัƒั” ะฒัั–ะผ ะบั€ะพะบะฐะผ ะฟะพัะปั–ะดะพะฒะฝะพ, ะฟะตั€ัˆ ะฝั–ะถ ะฟะตั€ะตะผะบะฝัƒั‚ะธัั ะฝะฐ ั–ะฝัˆัƒ ะทะฐะดะฐั‡ัƒ, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ั†ั– ะบั€ะพะบะธ ะฒะบะปัŽั‡ะฐัŽั‚ัŒ ะพั‡ั–ะบัƒะฒะฐะฝะฝั. + +### ะ ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ั– ะฑัƒั€ะณะตั€ะธ { #concurrency-and-burgers } + +ะ†ะดะตัŽ **ะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ** ะบะพะดัƒ, ะพะฟะธัะฐะฝัƒ ะฒะธั‰ะต, ั–ะฝะบะพะปะธ ั‚ะฐะบะพะถ ะฝะฐะทะธะฒะฐัŽั‚ัŒ **ยซั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŽยป**. ะ’ะพะฝะฐ ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด **ยซะฟะฐั€ะฐะปะตะปั–ะทะผัƒยป**. + +ะ† ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ, ั– ะฟะฐั€ะฐะปะตะปั–ะทะผ ัั‚ะพััƒัŽั‚ัŒัั ยซั€ั–ะทะฝะธั… ั€ะตั‡ะตะน, ั‰ะพ ะฒั–ะดะฑัƒะฒะฐัŽั‚ัŒัั ะฑั–ะปัŒัˆ-ะผะตะฝัˆ ะพะดะฝะพั‡ะฐัะฝะพยป. + +ะะปะต ะดะตั‚ะฐะปั– ะผั–ะถ ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŽ ั– ะฟะฐั€ะฐะปะตะปั–ะทะผะพะผ ะดะพัะธั‚ัŒ ั€ั–ะทะฝั–. + +ะฉะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ั€ั–ะทะฝะธั†ัŽ, ัƒัะฒั–ะผะพ ั‚ะฐะบัƒ ั–ัั‚ะพั€ั–ัŽ ะฟั€ะพ ะฑัƒั€ะณะตั€ะธ: + +### ะ ั–ะฒะฝะพั‡ะฐัะฝั– ะฑัƒั€ะณะตั€ะธ { #concurrent-burgers } + +ะ’ะธ ะนะดะตั‚ะต ะทั– ัะฒะพั”ัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ะฟะพ ั„ะฐัั‚ั„ัƒะด, ัั‚ะฐั”ั‚ะต ะฒ ั‡ะตั€ะณัƒ, ะดะพะบะธ ะบะฐัะธั€ ะฟั€ะธะนะผะฐั” ะทะฐะผะพะฒะปะตะฝะฝั ัƒ ะปัŽะดะตะน ะฟะตั€ะตะด ะฒะฐะผะธ. ๐Ÿ˜ + + + +ะŸะพั‚ั–ะผ ะฒะฐัˆะฐ ั‡ะตั€ะณะฐ, ะฒะธ ะทะฐะผะพะฒะปัั”ั‚ะต 2 ะดัƒะถะต ะฒะธัˆัƒะบะฐะฝั– ะฑัƒั€ะณะตั€ะธ ะดะปั ะฒะฐัˆะพั— ัะธะผะฟะฐั‚ั–ั— ั– ะดะปั ัะตะฑะต. ๐Ÿ”๐Ÿ” + + + +ะšะฐัะธั€ ะบะฐะถะต ั‰ะพััŒ ะบัƒั…ะฐั€ัŽ ะฝะฐ ะบัƒั…ะฝั–, ั‰ะพะฑ ั‚ะพะน ะทะฝะฐะฒ, ั‰ะพ ั‚ั€ะตะฑะฐ ะฟั€ะธะณะพั‚ัƒะฒะฐั‚ะธ ะฒะฐัˆั– ะฑัƒั€ะณะตั€ะธ (ั…ะพั‡ะฐ ะทะฐั€ะฐะท ะฒั–ะฝ ะณะพั‚ัƒั” ะฑัƒั€ะณะตั€ะธ ะดะปั ะฟะพะฟะตั€ะตะดะฝั–ั… ะบะปั–ั”ะฝั‚ั–ะฒ). + + + +ะ’ะธ ะฟะปะฐั‚ะธั‚ะต. ๐Ÿ’ธ + +ะšะฐัะธั€ ะดะฐั” ะฒะฐะผ ะฝะพะผะตั€ ะฒะฐัˆะพั— ั‡ะตั€ะณะธ. + + + +ะŸะพะบะธ ะฒะธ ั‡ะตะบะฐั”ั‚ะต, ะฒะธ ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ะพะฑะธั€ะฐั”ั‚ะต ัั‚ะพะปะธะบ, ัั–ะดะฐั”ั‚ะต ั– ะดะพะฒะณะพ ั€ะพะทะผะพะฒะปัั”ั‚ะต (ะฐะดะถะต ะฒะฐัˆั– ะฑัƒั€ะณะตั€ะธ ะดัƒะถะต ะฒะธัˆัƒะบะฐะฝั– ั– ะฟะพั‚ั€ะตะฑัƒัŽั‚ัŒ ั‡ะฐััƒ ะฝะฐ ะฟั€ะธะณะพั‚ัƒะฒะฐะฝะฝั). + +ะกะธะดัั‡ะธ ะทะฐ ัั‚ะพะปะธะบะพะผ ั–ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ, ะดะพะบะธ ั‡ะตะบะฐั”ั‚ะต ะฑัƒั€ะณะตั€ะธ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธั‚ั€ะฐั‚ะธั‚ะธ ั†ะตะน ั‡ะฐั, ะผะธะปัƒัŽั‡ะธััŒ ั‚ะธะผ, ัะบะฐ ะฒะฐัˆะฐ ัะธะผะฟะฐั‚ั–ั ะบะปะฐัะฝะฐ, ะผะธะปะฐ ั– ั€ะพะทัƒะผะฝะฐ โœจ๐Ÿ˜โœจ. + + + +ะงะตะบะฐัŽั‡ะธ ั– ัะฟั–ะปะบัƒัŽั‡ะธััŒ ั–ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ, ั‡ะฐั ะฒั–ะด ั‡ะฐััƒ ะฒะธ ะฟะตั€ะตะฒั–ั€ัั”ั‚ะต ะฝะพะผะตั€ ะฝะฐ ั‚ะฐะฑะปะพ ะฑั–ะปั ะฟั€ะธะปะฐะฒะบะฐ, ั‰ะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ, ั‡ะธ ะฒะถะต ะฒะฐัˆะฐ ั‡ะตั€ะณะฐ. + +ะ† ะพั‚ ะฝะฐั€ะตัˆั‚ั– ะฒะฐัˆะฐ ั‡ะตั€ะณะฐ. ะ’ะธ ะฟั–ะดั…ะพะดะธั‚ะต ะดะพ ะฟั€ะธะปะฐะฒะบะฐ, ะทะฐะฑะธั€ะฐั”ั‚ะต ะฑัƒั€ะณะตั€ะธ ั– ะฟะพะฒะตั€ั‚ะฐั”ั‚ะตัั ะดะพ ัั‚ะพะปะธะบะฐ. + + + +ะ’ะธ ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ั—ัั‚ะต ะฑัƒั€ะณะตั€ะธ ั– ะณะฐั€ะฝะพ ะฟั€ะพะฒะพะดะธั‚ะต ั‡ะฐั. โœจ + + + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸั€ะตะบั€ะฐัะฝั– ั–ะปัŽัั‚ั€ะฐั†ั–ั— ะฒั–ะด Ketrina Thompson. ๐ŸŽจ + +/// + +--- + +ะฃัะฒั–ั‚ัŒ, ั‰ะพ ะฒ ั†ั–ะน ั–ัั‚ะพั€ั–ั— ะฒะธ - ะบะพะผะฟโ€™ัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะฐ ๐Ÿค–. + +ะŸะพะบะธ ะฒะธ ะฒ ั‡ะตั€ะทั–, ะฒะธ ะฟั€ะพัั‚ะพ ะฑะตะทะดั–ัะปัŒะฝั– ๐Ÿ˜ด, ั‡ะตะบะฐั”ั‚ะต ัะฒะพั”ั— ั‡ะตั€ะณะธ, ะฝั–ั‡ะพะณะพ ยซะฟั€ะพะดัƒะบั‚ะธะฒะฝะพะณะพยป ะฝะต ั€ะพะฑะปัั‡ะธ. ะะปะต ั‡ะตั€ะณะฐ ั€ัƒั…ะฐั”ั‚ัŒัั ัˆะฒะธะดะบะพ, ะฑะพ ะบะฐัะธั€ ะปะธัˆะต ะฟั€ะธะนะผะฐั” ะทะฐะผะพะฒะปะตะฝะฝั (ะฐ ะฝะต ะณะพั‚ัƒั” ั—ั…), ั‚ะพะถ ั†ะต ะฝะพั€ะผะฐะปัŒะฝะพ. + +ะšะพะปะธ ะถ ะฒะฐัˆะฐ ั‡ะตั€ะณะฐ, ะฒะธ ะฒะธะบะพะฝัƒั”ั‚ะต ัะฟั€ะฐะฒะดั– ยซะฟั€ะพะดัƒะบั‚ะธะฒะฝัƒยป ั€ะพะฑะพั‚ัƒ: ะฟะตั€ะตะณะปัะดะฐั”ั‚ะต ะผะตะฝัŽ, ะฒะธั€ั–ัˆัƒั”ั‚ะต, ั‰ะพ ะฑะฐะถะฐั”ั‚ะต, ะดั–ะทะฝะฐั”ั‚ะตัั ะฒะธะฑั–ั€ ะฒะฐัˆะพั— ัะธะผะฟะฐั‚ั–ั—, ะฟะปะฐั‚ะธั‚ะต, ะฟะตั€ะตะฒั–ั€ัั”ั‚ะต, ั‰ะพ ะฒั–ะดะดะฐั”ั‚ะต ะฟั€ะฐะฒะธะปัŒะฝัƒ ะบัƒะฟัŽั€ัƒ ั‡ะธ ะบะฐั€ั‚ะบัƒ, ั‰ะพ ะท ะฒะฐั ะฟั€ะฐะฒะธะปัŒะฝะพ ัะฟะธัะฐะปะธ ะบะพัˆั‚ะธ, ั‰ะพ ะทะฐะผะพะฒะปะตะฝะฝั ะผั–ัั‚ะธั‚ัŒ ะฟั€ะฐะฒะธะปัŒะฝั– ะฟะพะทะธั†ั–ั— ั‚ะพั‰ะพ. + +ะะปะต ะฟะพั‚ั–ะผ, ั…ะพั‡ะฐ ัƒ ะฒะฐั ั‰ะต ะฝะตะผะฐั” ะฑัƒั€ะณะตั€ั–ะฒ, ะฒะฐัˆะฐ ะฒะทะฐั”ะผะพะดั–ั ะท ะบะฐัะธั€ะพะผ ยซะฝะฐ ะฟะฐัƒะทั–ยป โธ, ะฑะพ ะฒะฐะผ ะดะพะฒะพะดะธั‚ัŒัั ั‡ะตะบะฐั‚ะธ ๐Ÿ•™, ะฟะพะบะธ ะฑัƒั€ะณะตั€ะธ ะฑัƒะดัƒั‚ัŒ ะณะพั‚ะพะฒั–. + +ะ’ั‚ั–ะผ, ะฒั–ะดั–ะนัˆะพะฒัˆะธ ะฒั–ะด ะฟั€ะธะปะฐะฒะบะฐ ั– ัั–ะฒัˆะธ ะทะฐ ัั‚ะพะปะธะบ ั–ะท ะฝะพะผะตั€ะบะพะผ, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะผะบะฝัƒั‚ะธ ๐Ÿ”€ ัƒะฒะฐะณัƒ ะฝะฐ ัะฒะพัŽ ัะธะผะฟะฐั‚ั–ัŽ ั– ยซะฟะพะฟั€ะฐั†ัŽะฒะฐั‚ะธยป โฏ ๐Ÿค“ ะฝะฐะด ั†ะธะผ. ะขะพะดั– ะฒะธ ะทะฝะพะฒัƒ ั€ะพะฑะธั‚ะต ั‰ะพััŒ ะดัƒะถะต ยซะฟั€ะพะดัƒะบั‚ะธะฒะฝะตยป - ั„ะปั–ั€ั‚ัƒั”ั‚ะต ะทั– ัะฒะพั”ัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ๐Ÿ˜. + +ะŸะพั‚ั–ะผ ะบะฐัะธั€ ๐Ÿ’ ะบะฐะถะต ยซะฏ ะทะฐะบั–ะฝั‡ะธะฒ ั€ะพะฑะธั‚ะธ ะฑัƒั€ะณะตั€ะธยป, ะฒะธะฒะพะดัั‡ะธ ะฒะฐัˆ ะฝะพะผะตั€ ะฝะฐ ั‚ะฐะฑะปะพ ะฟั€ะธะปะฐะฒะบะฐ, ะฐะปะต ะฒะธ ะฝะต ะฟั–ะดัั‚ั€ะธะฑัƒั”ั‚ะต ะผะธั‚ั‚ั”ะฒะพ, ั‰ะพะนะฝะพ ะฝะพะผะตั€ ะทะผั–ะฝัŽั”ั‚ัŒัั ะฝะฐ ะฒะฐัˆ. ะ’ะธ ะทะฝะฐั”ั‚ะต, ั‰ะพ ะฝั–ั…ั‚ะพ ะฝะต ะฒะบั€ะฐะดะต ะฒะฐัˆั– ะฑัƒั€ะณะตั€ะธ, ะฐะดะถะต ัƒ ะฒะฐั ั” ะฝะพะผะตั€ ะฒะฐัˆะพั— ั‡ะตั€ะณะธ, ะฐ ะฒ ั–ะฝัˆะธั… - ัะฒั–ะน. + +ะขะพะถ ะฒะธ ั‡ะตะบะฐั”ั‚ะต, ะฟะพะบะธ ะฒะฐัˆะฐ ัะธะผะฟะฐั‚ั–ั ะทะฐะฒะตั€ัˆะธั‚ัŒ ั–ัั‚ะพั€ั–ัŽ (ะทะฐะฒะตั€ัˆะธั‚ัŒ ะฟะพั‚ะพั‡ะฝัƒ ั€ะพะฑะพั‚ัƒ โฏ/ะทะฐะดะฐั‡ัƒ ๐Ÿค“), ะปะฐะณั–ะดะฝะพ ัƒัะผั–ั…ะฐั”ั‚ะตัั ั– ะบะฐะถะตั‚ะต, ั‰ะพ ะฟั–ะดะตั‚ะต ะทะฐ ะฑัƒั€ะณะตั€ะฐะผะธ โธ. + +ะŸะพั‚ั–ะผ ะฒะธ ะนะดะตั‚ะต ะดะพ ะฟั€ะธะปะฐะฒะบะฐ ๐Ÿ”€, ะดะพ ะฟะพั‡ะฐั‚ะบะพะฒะพั— ะทะฐะดะฐั‡ั–, ัะบัƒ ั‚ะตะฟะตั€ ะทะฐะฒะตั€ัˆะตะฝะพ โฏ, ะทะฐะฑะธั€ะฐั”ั‚ะต ะฑัƒั€ะณะตั€ะธ, ะดัะบัƒั”ั‚ะต ั– ะฝะตัะตั‚ะต ั—ั… ะดะพ ัั‚ะพะปัƒ. ะฆะต ะทะฐะฒะตั€ัˆัƒั” ั‚ะพะน ะบั€ะพะบ/ะทะฐะดะฐั‡ัƒ ะฒะทะฐั”ะผะพะดั–ั— ะท ะฟั€ะธะปะฐะฒะบะพะผ โน. ะะฐั‚ะพะผั–ัั‚ัŒ ะทโ€™ัะฒะปัั”ั‚ัŒัั ะฝะพะฒะฐ ะทะฐะดะฐั‡ะฐ ยซั—ัั‚ะธ ะฑัƒั€ะณะตั€ะธยป ๐Ÿ”€ โฏ, ะฐะปะต ะฟะพะฟะตั€ะตะดะฝั ยซะพั‚ั€ะธะผะฐั‚ะธ ะฑัƒั€ะณะตั€ะธยป ะทะฐะฒะตั€ัˆะตะฝะฐ โน. + +### ะŸะฐั€ะฐะปะตะปัŒะฝั– ะฑัƒั€ะณะตั€ะธ { #parallel-burgers } + +ะ ั‚ะตะฟะตั€ ัƒัะฒั–ะผะพ, ั‰ะพ ั†ะต ะฝะต ยซั€ั–ะฒะฝะพั‡ะฐัะฝั– ะฑัƒั€ะณะตั€ะธยป, ะฐ ยซะฟะฐั€ะฐะปะตะปัŒะฝั– ะฑัƒั€ะณะตั€ะธยป. + +ะ’ะธ ะนะดะตั‚ะต ะทั– ัะฒะพั”ัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ะฟะพ ะฟะฐั€ะฐะปะตะปัŒะฝะธะน ั„ะฐัั‚ั„ัƒะด. + +ะ’ะธ ัั‚ะฐั”ั‚ะต ะฒ ั‡ะตั€ะณัƒ, ะฟะพะบะธ ะบั–ะปัŒะบะฐ (ัะบะฐะถั–ะผะพ, 8) ะบะฐัะธั€ั–ะฒ, ัะบั– ะฒะพะดะฝะพั‡ะฐั ั” ะบัƒั…ะฐั€ัะผะธ, ะฟั€ะธะนะผะฐัŽั‚ัŒ ะทะฐะผะพะฒะปะตะฝะฝั ัƒ ะปัŽะดะตะน ะฟะตั€ะตะด ะฒะฐะผะธ. + +ะšะพะถะตะฝ ะฟะตั€ะตะด ะฒะฐะผะธ ั‡ะตะบะฐั”, ะฟะพะบะธ ะนะพะณะพ ะฑัƒั€ะณะตั€ะธ ะฑัƒะดัƒั‚ัŒ ะณะพั‚ะพะฒั–, ะฟะตั€ัˆ ะฝั–ะถ ะฒั–ะดั–ะนั‚ะธ ะฒั–ะด ะฟั€ะธะปะฐะฒะบะฐ, ั‚ะพะผัƒ ั‰ะพ ะบะพะถะตะฝ ะท 8 ะบะฐัะธั€ั–ะฒ ะพะดั€ะฐะทัƒ ะนะดะต ั– ะณะพั‚ัƒั” ะฑัƒั€ะณะตั€, ะฟะตั€ัˆ ะฝั–ะถ ะฟั€ะธะนะผะฐั‚ะธ ะฝะฐัั‚ัƒะฟะฝะต ะทะฐะผะพะฒะปะตะฝะฝั. + + + +ะะฐั€ะตัˆั‚ั– ะฒะฐัˆะฐ ั‡ะตั€ะณะฐ, ะฒะธ ะทะฐะผะพะฒะปัั”ั‚ะต 2 ะดัƒะถะต ะฒะธัˆัƒะบะฐะฝั– ะฑัƒั€ะณะตั€ะธ ะดะปั ะฒะฐัˆะพั— ัะธะผะฟะฐั‚ั–ั— ั– ะดะปั ัะตะฑะต. + +ะ’ะธ ะฟะปะฐั‚ะธั‚ะต ๐Ÿ’ธ. + + + +ะšะฐัะธั€ ั–ะดะต ะฝะฐ ะบัƒั…ะฝัŽ. + +ะ’ะธ ั‡ะตะบะฐั”ั‚ะต, ัั‚ะพัั‡ะธ ะฟะตั€ะตะด ะฟั€ะธะปะฐะฒะบะพะผ ๐Ÿ•™, ั‰ะพะฑ ะฝั–ั…ั‚ะพ ั–ะฝัˆะธะน ะฝะต ะทะฐะฑั€ะฐะฒ ะฒะฐัˆั– ะฑัƒั€ะณะตั€ะธ ั€ะฐะฝั–ัˆะต, ะฝั–ะถ ะฒะธ, ะฐะดะถะต ะฝะพะผะตั€ะบั–ะฒ ั‡ะตั€ะณะธ ะฝะตะผะฐั”. + + + +ะžัะบั–ะปัŒะบะธ ะฒะธ ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ ะทะฐะนะฝัั‚ั– ั‚ะธะผ, ั‰ะพะฑ ะฝั–ั…ั‚ะพ ะฝะต ัั‚ะฐะฒ ะฟะตั€ะตะด ะฒะฐะผะธ ั– ะฝะต ะทะฐะฑั€ะฐะฒ ะฒะฐัˆั– ะฑัƒั€ะณะตั€ะธ, ั‰ะพะนะฝะพ ะฒะพะฝะธ ะทโ€™ัะฒะปัั‚ัŒัั, ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฟั€ะธะดั–ะปัั‚ะธ ัƒะฒะฐะณัƒ ัะฒะพั—ะน ัะธะผะฟะฐั‚ั–ั—. ๐Ÿ˜ž + +ะฆะต ยซัะธะฝั…ั€ะพะฝะฝะฐยป ั€ะพะฑะพั‚ะฐ, ะฒะธ ยซัะธะฝั…ั€ะพะฝั–ะทะพะฒะฐะฝั–ยป ะท ะบะฐัะธั€ะพะผ/ะบัƒั…ะฐั€ะตะผ ๐Ÿ‘จโ€๐Ÿณ. ะ’ะฐะผ ะดะพะฒะพะดะธั‚ัŒัั ั‡ะตะบะฐั‚ะธ ๐Ÿ•™ ั– ะฑัƒั‚ะธ ั‚ัƒั‚ ัƒ ั‚ะพั‡ะฝะธะน ะผะพะผะตะฝั‚, ะบะพะปะธ ะบะฐัะธั€/ะบัƒั…ะฐั€ ๐Ÿ‘จโ€๐Ÿณ ะทะฐะฒะตั€ัˆะธั‚ัŒ ะฑัƒั€ะณะตั€ะธ ั– ะฒั–ะดะดะฐัั‚ัŒ ั—ั… ะฒะฐะผ, ั–ะฝะฐะบัˆะต ั…ั‚ะพััŒ ั–ะฝัˆะธะน ะผะพะถะต ั—ั… ะทะฐะฑั€ะฐั‚ะธ. + + + +ะŸะพั‚ั–ะผ ะฒะฐัˆ ะบะฐัะธั€/ะบัƒั…ะฐั€ ๐Ÿ‘จโ€๐Ÿณ ะฝะฐั€ะตัˆั‚ั– ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั ะท ะฒะฐัˆะธะผะธ ะฑัƒั€ะณะตั€ะฐะผะธ ะฟั–ัะปั ะดะพะฒะณะพะณะพ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ๐Ÿ•™ ะฟะตั€ะตะด ะฟั€ะธะปะฐะฒะบะพะผ. + + + +ะ’ะธ ะฑะตั€ะตั‚ะต ะฑัƒั€ะณะตั€ะธ ั– ะนะดะตั‚ะต ะดะพ ัั‚ะพะปะธะบะฐ ะทั– ัะฒะพั”ัŽ ัะธะผะฟะฐั‚ั–ั”ัŽ. + +ะ’ะธ ะฟั€ะพัั‚ะพ ั—ั… ั—ัั‚ะต - ั– ะฒัะต. โน + + + +ะ‘ะฐะณะฐั‚ะพ ั€ะพะทะผะพะฒ ั‡ะธ ั„ะปั–ั€ั‚ัƒ ะฝะต ะฑัƒะปะพ, ะฑะพ ะฑั–ะปัŒัˆั–ัั‚ัŒ ั‡ะฐััƒ ะฟั–ัˆะปะฐ ะฝะฐ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ๐Ÿ•™ ะฟะตั€ะตะด ะฟั€ะธะปะฐะฒะบะพะผ. ๐Ÿ˜ž + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸั€ะตะบั€ะฐัะฝั– ั–ะปัŽัั‚ั€ะฐั†ั–ั— ะฒั–ะด Ketrina Thompson. ๐ŸŽจ + +/// + +--- + +ะฃ ั†ัŒะพะผัƒ ัั†ะตะฝะฐั€ั–ั— ะฟะฐั€ะฐะปะตะปัŒะฝะธั… ะฑัƒั€ะณะตั€ั–ะฒ ะฒะธ - ะบะพะผะฟโ€™ัŽั‚ะตั€/ะฟั€ะพะณั€ะฐะผะฐ ๐Ÿค– ะท ะดะฒะพะผะฐ ะฟั€ะพั†ะตัะพั€ะฐะผะธ (ะฒะธ ั– ะฒะฐัˆะฐ ัะธะผะฟะฐั‚ั–ั), ัะบั– ะพะฑะธะดะฒะฐ ั‡ะตะบะฐัŽั‚ัŒ ๐Ÿ•™ ั– ะฟั€ะธะดั–ะปััŽั‚ัŒ ัƒะฒะฐะณัƒ โฏ ยซะพั‡ั–ะบัƒะฒะฐะฝะฝัŽ ะฑั–ะปั ะฟั€ะธะปะฐะฒะบะฐยป ๐Ÿ•™ ั‚ั€ะธะฒะฐะปะธะน ั‡ะฐั. + +ะฃ ะทะฐะบะปะฐะดัƒ ั„ะฐัั‚ั„ัƒะดัƒ 8 ะฟั€ะพั†ะตัะพั€ั–ะฒ (ะบะฐัะธั€ะฐ/ะบัƒั…ะฐั€ั). ะฃ ั‚ะพะน ั‡ะฐั ัะบ ัƒ ะทะฐะบะปะฐะดั– ะท ั€ั–ะฒะฝะพั‡ะฐัะฝะธะผะธ ะฑัƒั€ะณะตั€ะฐะผะธ ะผะพะณะปะพ ะฑัƒั‚ะธ ะปะธัˆะต 2 (ะพะดะธะฝ ะบะฐัะธั€ ั– ะพะดะธะฝ ะบัƒั…ะฐั€). + +ะขะฐ ะฒัะต ะพะดะฝะพ ั„ั–ะฝะฐะปัŒะฝะธะน ะดะพัะฒั–ะด ะฝะต ะฝะฐะนะบั€ะฐั‰ะธะน. ๐Ÿ˜ž + +--- + +ะฆะต ะฑัƒะปะฐ ะฑ ะฟะฐั€ะฐะปะตะปัŒะฝะฐ ั–ัั‚ะพั€ั–ั ะฟั€ะพ ะฑัƒั€ะณะตั€ะธ. ๐Ÿ” + +ะ”ะปั ะฑั–ะปัŒัˆ ยซั€ะตะฐะปัŒะฝะพะณะพยป ะฟั€ะธะบะปะฐะดัƒ ัƒัะฒั–ั‚ัŒ ะฑะฐะฝะบ. + +ะ”ะพ ะฝะตะดะฐะฒะฝัŒะพะณะพ ั‡ะฐััƒ ะฑั–ะปัŒัˆั–ัั‚ัŒ ะฑะฐะฝะบั–ะฒ ะผะฐะปะธ ะบั–ะปัŒะบะฐ ะบะฐัะธั€ั–ะฒ ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ ั– ะฒะตะปะธะบัƒ ั‡ะตั€ะณัƒ ๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™๐Ÿ•™. + +ะฃัั– ะบะฐัะธั€ะธ ั€ะพะฑะธะปะธ ะฒััŽ ั€ะพะฑะพั‚ัƒ ะท ะพะดะฝะธะผ ะบะปั–ั”ะฝั‚ะพะผ ะทะฐ ั–ะฝัˆะธะผ ๐Ÿ‘จโ€๐Ÿ’ผโฏ. + +ะ† ะฒะฐะผ ะดะพะฒะพะดะธะปะพัั ๐Ÿ•™ ะดะพะฒะณะพ ัั‚ะพัั‚ะธ ะฒ ั‡ะตั€ะทั–, ั–ะฝะฐะบัˆะต ะฒะธ ะฒั‚ั€ะฐั‚ะธั‚ะต ัะฒะพัŽ ั‡ะตั€ะณัƒ. + +ะ’ะธ, ะฝะฐะฟะตะฒะฝะพ, ะฝะต ั…ะพั‚ั–ะปะธ ะฑ ะฑั€ะฐั‚ะธ ัะฒะพัŽ ัะธะผะฟะฐั‚ั–ัŽ ๐Ÿ˜ ั–ะท ัะพะฑะพัŽ ัƒ ัะฟั€ะฐะฒะธ ะดะพ ะฑะฐะฝะบัƒ ๐Ÿฆ. + +### ะ’ะธัะฝะพะฒะพะบ ะฟั€ะพ ะฑัƒั€ะณะตั€ะธ { #burger-conclusion } + +ะฃ ั†ัŒะพะผัƒ ัั†ะตะฝะฐั€ั–ั— ยซั„ะฐัั‚ั„ัƒะด ั–ะท ะฒะฐัˆะพัŽ ัะธะผะฟะฐั‚ั–ั”ัŽยป, ะพัะบั–ะปัŒะบะธ ั” ะฑะฐะณะฐั‚ะพ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ๐Ÿ•™, ะทะฝะฐั‡ะฝะพ ะดะพั†ั–ะปัŒะฝั–ัˆะต ะผะฐั‚ะธ ั€ั–ะฒะฝะพั‡ะฐัะฝัƒ ัะธัั‚ะตะผัƒ โธ๐Ÿ”€โฏ. + +ะขะฐะบ ั” ัƒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะตะฑะทะฐัั‚ะพััƒะฝะบั–ะฒ. + +ะ‘ะฐะณะฐั‚ะพ-ะฑะฐะณะฐั‚ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, ะฐะปะต ะฒะฐัˆ ัะตั€ะฒะตั€ ั‡ะตะบะฐั” ๐Ÿ•™ ะฝะฐ ั—ั…ะฝั” ะฝะต ะฝะฐะดั‚ะพ ะณะฐั€ะฝะต ะทโ€™ั”ะดะฝะฐะฝะฝั, ั‰ะพะฑ ะฒะพะฝะธ ะฝะฐะดั–ัะปะฐะปะธ ัะฒะพั— ะทะฐะฟะธั‚ะธ. + +ะ ะฟะพั‚ั–ะผ ะทะฝะพะฒัƒ ั‡ะตะบะฐั” ๐Ÿ•™ ะฝะฐ ะฟะพะฒะตั€ะฝะตะฝะฝั ะฒั–ะดะฟะพะฒั–ะดะตะน. + +ะฆะต ยซะพั‡ั–ะบัƒะฒะฐะฝะฝัยป ๐Ÿ•™ ะฒะธะผั–ั€ัŽั”ั‚ัŒัั ัƒ ะผั–ะบั€ะพัะตะบัƒะฝะดะฐั…, ะฐะปะต ะฒัะต ะถ, ัƒ ััƒะผั– - ั†ะต ะฑะฐะณะฐั‚ะพ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ะฒ ะฟั–ะดััƒะผะบัƒ. + +ะžััŒ ั‡ะพะผัƒ ะดัƒะถะต ะปะพะณั–ั‡ะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฐัะธะฝั…ั€ะพะฝะฝะธะน โธ๐Ÿ”€โฏ ะบะพะด ะดะปั ะฒะตะฑ API. + +ะขะฐะบะธะน ั‚ะธะฟ ะฐัะธะฝั…ั€ะพะฝะฝะพัั‚ั– ะทั€ะพะฑะธะฒ NodeJS ะฟะพะฟัƒะปัั€ะฝะธะผ (ั…ะพั‡ะฐ NodeJS ะฝะต ั” ะฟะฐั€ะฐะปะตะปัŒะฝะธะผ), ั– ั†ะต ัะธะปะฐ Go ัะบ ะผะพะฒะธ ะฟั€ะพะณั€ะฐะผัƒะฒะฐะฝะฝั. + +ะ† ั‚ะฐะบะธะน ัะฐะผะธะน ั€ั–ะฒะตะฝัŒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝะพัั‚ั– ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะท **FastAPI**. + +ะ ะพัะบั–ะปัŒะบะธ ะผะพะถะฝะฐ ะผะฐั‚ะธ ะฟะฐั€ะฐะปะตะปั–ะทะผ ั– ะฐัะธะฝั…ั€ะพะฝะฝั–ัั‚ัŒ ะพะดะฝะพั‡ะฐัะฝะพ, ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฒะธั‰ัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะฝั–ะถ ะฑั–ะปัŒัˆั–ัั‚ัŒ ะฟั€ะพั‚ะตัั‚ะพะฒะฐะฝะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ NodeJS, ั– ะฝะฐ ั€ั–ะฒะฝั– ะท Go, ัะบะธะน ั” ะบะพะผะฟั–ะปัŒะพะฒะฐะฝะพัŽ ะผะพะฒะพัŽ, ะฑะปะธะถั‡ะพัŽ ะดะพ C (ัƒัะต ะทะฐะฒะดัะบะธ Starlette). + +### ะงะธ ะบั€ะฐั‰ะฐ ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ะทะฐ ะฟะฐั€ะฐะปะตะปั–ะทะผ? { #is-concurrency-better-than-parallelism } + +ะั–! ะฆะต ะฝะต ะผะพั€ะฐะปัŒ ั–ัั‚ะพั€ั–ั—. + +ะ ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด ะฟะฐั€ะฐะปะตะปั–ะทะผัƒ. ะ† ะฒะพะฝะฐ ะบั€ะฐั‰ะฐ ัƒ ะบะพะฝะบั€ะตั‚ะฝะธั… ัั†ะตะฝะฐั€ั–ัั…, ั‰ะพ ะผั–ัั‚ัั‚ัŒ ะฑะฐะณะฐั‚ะพ ะพั‡ั–ะบัƒะฒะฐะฝะฝั. ะงะตั€ะตะท ั†ะต ะทะฐะทะฒะธั‡ะฐะน ะฒะพะฝะฐ ะทะฝะฐั‡ะฝะพ ะบั€ะฐั‰ะฐ ะทะฐ ะฟะฐั€ะฐะปะตะปั–ะทะผ ะดะปั ั€ะพะทั€ะพะฑะบะธ ะฒะตะฑะทะฐัั‚ะพััƒะฝะบั–ะฒ. ะะปะต ะฝะต ะดะปั ะฒััŒะพะณะพ. + +ะฉะพะฑ ัƒั€ั–ะฒะฝะพะฒะฐะถะธั‚ะธ ั†ะต, ัƒัะฒั–ะผะพ ะบะพั€ะพั‚ะบัƒ ั–ัั‚ะพั€ั–ัŽ: + +> ะ’ะธ ะผะฐั”ั‚ะต ะฟั€ะธะฑั€ะฐั‚ะธ ะฒะตะปะธะบะธะน ะฑั€ัƒะดะฝะธะน ะฑัƒะดะธะฝะพะบ. + +*ะขะฐะบ, ั†ะต ะฒัั ั–ัั‚ะพั€ั–ั*. + +--- + +ะขัƒั‚ ะฝะตะผะฐั” ะพั‡ั–ะบัƒะฒะฐะฝะฝั ๐Ÿ•™ - ะฟั€ะพัั‚ะพ ะฑะฐะณะฐั‚ะพ ั€ะพะฑะพั‚ะธ, ัะบัƒ ั‚ั€ะตะฑะฐ ะทั€ะพะฑะธั‚ะธ, ัƒ ะฑะฐะณะฐั‚ัŒะพั… ะผั–ัั†ัั… ะฑัƒะดะธะฝะบัƒ. + +ะฃ ะฒะฐั ะผะพะณะปะธ ะฑ ะฑัƒั‚ะธ ยซั‡ะตั€ะณะธยป ัะบ ัƒ ะฟั€ะธะบะปะฐะดั– ะท ะฑัƒั€ะณะตั€ะฐะผะธ: ัะฟะพั‡ะฐั‚ะบัƒ ะฒั–ั‚ะฐะปัŒะฝั, ะฟะพั‚ั–ะผ ะบัƒั…ะฝั. ะะปะต ะพัะบั–ะปัŒะบะธ ะฒะธ ะฝั– ะฝะฐ ั‰ะพ ะฝะต ั‡ะตะบะฐั”ั‚ะต ๐Ÿ•™, ะฐ ะฟั€ะพัั‚ะพ ะฟั€ะธะฑะธั€ะฐั”ั‚ะต, ยซั‡ะตั€ะณะธยป ะฝั–ั‡ะพะณะพ ะฝะต ะทะผั–ะฝัั‚ัŒ. + +ะ—ะฐะฒะตั€ัˆะตะฝะฝั ะทะฐะนะผะต ั‚ะพะน ัะฐะผะธะน ั‡ะฐั ั–ะท ยซั‡ะตั€ะณะฐะผะธยป ั‡ะธ ะฑะตะท (ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ), ั– ะฒะธ ะฒะธะบะพะฝะฐั”ั‚ะต ั‚ะพะน ัะฐะผะธะน ะพะฑััะณ ั€ะพะฑะพั‚ะธ. + +ะะปะต ะฒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ, ัะบะฑะธ ะฒะธ ะผะพะณะปะธ ะฟั€ะธะฒะตัั‚ะธ 8 ะบะพะปะธัˆะฝั–ั… ะบะฐัะธั€ั–ะฒ/ะบัƒั…ะฐั€ั–ะฒ/ั‚ะตะฟะตั€ ะฟั€ะธะฑะธั€ะฐะปัŒะฝะธะบั–ะฒ, ั– ะบะพะถะตะฝ ะท ะฝะธั… (ั€ะฐะทะพะผ ั–ะท ะฒะฐะผะธ) ะฒะทัะฒ ะฑะธ ัะฒะพัŽ ะทะพะฝัƒ ะฑัƒะดะธะฝะบัƒ ะดะปั ะฟั€ะธะฑะธั€ะฐะฝะฝั, ะฒะธ ะผะพะณะปะธ ะฑ ะฒะธะบะพะฝะฐั‚ะธ ะฒััŽ ั€ะพะฑะพั‚ัƒ ะฟะฐั€ะฐะปะตะปัŒะฝะพ โ€” ะท ะดะพะดะฐั‚ะบะพะฒะพัŽ ะดะพะฟะพะผะพะณะพัŽ โ€” ั– ะทะฐะฒะตั€ัˆะธั‚ะธ ะทะฝะฐั‡ะฝะพ ัˆะฒะธะดัˆะต. + +ะฃ ั†ัŒะพะผัƒ ัั†ะตะฝะฐั€ั–ั— ะบะพะถะตะฝ ะท ะฟั€ะธะฑะธั€ะฐะปัŒะฝะธะบั–ะฒ (ะฒะบะปัŽั‡ะฝะพ ะท ะฒะฐะผะธ) ะฑัƒะฒ ะฑะธ ะฟั€ะพั†ะตัะพั€ะพะผ, ั‰ะพ ะฒะธะบะพะฝัƒั” ัะฒะพัŽ ั‡ะฐัั‚ะธะฝัƒ ั€ะพะฑะพั‚ะธ. + +ะ† ะพัะบั–ะปัŒะบะธ ะฑั–ะปัŒัˆั–ัั‚ัŒ ั‡ะฐััƒ ะฒะธะบะพะฝะฐะฝะฝั ะทะฐะนะผะฐั” ั€ะตะฐะปัŒะฝะฐ ั€ะพะฑะพั‚ะฐ (ะฐ ะฝะต ะพั‡ั–ะบัƒะฒะฐะฝะฝั), ะฐ ั€ะพะฑะพั‚ัƒ ะฝะฐ ะบะพะผะฟโ€™ัŽั‚ะตั€ั– ะฒะธะบะพะฝัƒั” CPU, ั†ั– ะฟั€ะพะฑะปะตะผะธ ะฝะฐะทะธะฒะฐัŽั‚ัŒ ยซCPU boundยป. + +--- + +ะŸะพัˆะธั€ะตะฝั– ะฟั€ะธะบะปะฐะดะธ ยซCPU boundยป ะพะฟะตั€ะฐั†ั–ะน - ั†ะต ั€ะตั‡ั–, ั‰ะพ ะฟะพั‚ั€ะตะฑัƒัŽั‚ัŒ ัะบะปะฐะดะฝะพั— ะผะฐั‚ะตะผะฐั‚ะธั‡ะฝะพั— ะพะฑั€ะพะฑะบะธ. + +ะะฐะฟั€ะธะบะปะฐะด: + +- **ะžะฑั€ะพะฑะบะฐ ะฐัƒะดั–ะพ** ะฐะฑะพ **ะทะพะฑั€ะฐะถะตะฝัŒ**. +- **ะšะพะผะฟโ€™ัŽั‚ะตั€ะฝะธะน ะทั–ั€**: ะทะพะฑั€ะฐะถะตะฝะฝั ัะบะปะฐะดะฐั”ั‚ัŒัั ะท ะผั–ะปัŒะนะพะฝั–ะฒ ะฟั–ะบัะตะปั–ะฒ, ะบะพะถะตะฝ ะฟั–ะบัะตะปัŒ ะผะฐั” 3 ะทะฝะฐั‡ะตะฝะฝั/ะบะพะปัŒะพั€ะธ, ะพะฑั€ะพะฑะบะฐ ะทะฐะทะฒะธั‡ะฐะน ะฟะพั‚ั€ะตะฑัƒั” ะพะฑั‡ะธัะปะตะฝะฝั ั‡ะพะณะพััŒ ะฝะฐะด ั†ะธะผะธ ะฟั–ะบัะตะปัะผะธ, ัƒัั–ะผะฐ ะพะดะฝะพั‡ะฐัะฝะพ. +- **ะœะฐัˆะธะฝะฝะต ะฝะฐะฒั‡ะฐะฝะฝั**: ะทะฐะทะฒะธั‡ะฐะน ะฟะพั‚ั€ะตะฑัƒั” ะฒะตะปะธะบะพั— ะบั–ะปัŒะบะพัั‚ั– ะผะฝะพะถะตะฝัŒ ยซะผะฐั‚ั€ะธั†ัŒยป ั– ยซะฒะตะบั‚ะพั€ั–ะฒยป. ะฃัะฒั–ั‚ัŒ ะฒะตะปะธั‡ะตะทะฝัƒ ั‚ะฐะฑะปะธั†ัŽ ะท ั‡ะธัะปะฐะผะธ ั– ะผะฝะพะถะตะฝะฝั ะฒัั–ั… ั—ั… ั€ะฐะทะพะผ ะพะดะฝะพั‡ะฐัะฝะพ. +- **ะ“ะปะธะฑะพะบะต ะฝะฐะฒั‡ะฐะฝะฝั**: ั†ะต ะฟั–ะดะณะฐะปัƒะทัŒ ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั, ั‚ะพะถ ั‚ะต ัะฐะผะต ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั. ะŸั€ะพัั‚ะพ ั‚ัƒั‚ ะฝะต ะพะดะฝะฐ ั‚ะฐะฑะปะธั†ั ั‡ะธัะตะป ะดะปั ะผะฝะพะถะตะฝะฝั, ะฐ ะฒะตะปะธั‡ะตะทะฝะธะน ั—ั… ะฝะฐะฑั–ั€, ั– ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะฟั€ะพั†ะตัะพั€ ะดะปั ะฟะพะฑัƒะดะพะฒะธ ั‚ะฐ/ะฐะฑะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั†ะธั… ะผะพะดะตะปะตะน. + +### ะ ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ + ะฟะฐั€ะฐะปะตะปั–ะทะผ: ะฒะตะฑ + ะผะฐัˆะธะฝะฝะต ะฝะฐะฒั‡ะฐะฝะฝั { #concurrency-parallelism-web-machine-learning } + +ะ— **FastAPI** ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŽ, ั‰ะพ ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะฐ ัƒ ะฒะตะฑั€ะพะทั€ะพะฑั†ั– (ั‚ะฐ ะถ ะณะพะปะพะฒะฝะฐ ะฟั€ะธะฝะฐะดะฐ NodeJS). + +ะะปะต ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะตั€ะตะฒะฐะณะธ ะฟะฐั€ะฐะปะตะปั–ะทะผัƒ ั– ะฑะฐะณะฐั‚ะพะฟั€ะพั†ะตัะพั€ะฝะพัั‚ั– (ะฝะฐัะฒะฝั–ัั‚ัŒ ะบั–ะปัŒะบะพั… ะฟั€ะพั†ะตัั–ะฒ, ั‰ะพ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฟะฐั€ะฐะปะตะปัŒะฝะพ) ะดะปั ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝัŒ ยซCPU boundยป, ัะบ ัƒ ัะธัั‚ะตะผะฐั… ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั. + +ะฆะต, ะฟะปัŽั ะฟั€ะพัั‚ะธะน ั„ะฐะบั‚, ั‰ะพ Python ั” ะพัะฝะพะฒะฝะพัŽ ะผะพะฒะพัŽ ะดะปั **Data Science**, ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั ั– ะพัะพะฑะปะธะฒะพ ะณะปะธะฑะพะบะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั, ั€ะพะฑะธั‚ัŒ FastAPI ะดัƒะถะต ะฒะดะฐะปะธะผ ะฒะธะฑะพั€ะพะผ ะดะปั ะฒะตะฑ API ั‚ะฐ ะทะฐัั‚ะพััƒะฝะบั–ะฒ Data Science / ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั (ัะตั€ะตะด ะฑะฐะณะฐั‚ัŒะพั… ั–ะฝัˆะธั…). + +ะฉะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ, ัะบ ะดะพััะณั‚ะธ ั†ัŒะพะณะพ ะฟะฐั€ะฐะปะตะปั–ะทะผัƒ ัƒ ะฟั€ะพะดะฐะบัˆะฝั–, ะดะธะฒ. ั€ะพะทะดั–ะป ะฟั€ะพ [ะ ะพะทะณะพั€ั‚ะฐะฝะฝั](deployment/index.md){.internal-link target=_blank}. + +## `async` ั– `await` { #async-and-await } + +ะกัƒั‡ะฐัะฝั– ะฒะตั€ัั–ั— Python ะผะฐัŽั‚ัŒ ะดัƒะถะต ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะธะน ัะฟะพัั–ะฑ ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ ะบะพะดัƒ. ะฆะต ั€ะพะฑะธั‚ัŒ ะนะพะณะพ ัั…ะพะถะธะผ ะฝะฐ ะทะฒะธั‡ะฐะนะฝะธะน ยซะฟะพัะปั–ะดะพะฒะฝะธะนยป ะบะพะด ั– ะฒะธะบะพะฝัƒั” ยซะพั‡ั–ะบัƒะฒะฐะฝะฝัยป ะทะฐ ะฒะฐั ัƒ ะฒั–ะดะฟะพะฒั–ะดะฝั– ะผะพะผะตะฝั‚ะธ. + +ะšะพะปะธ ั” ะพะฟะตั€ะฐั†ั–ั, ัะบะฐ ะฒะธะผะฐะณะฐั‚ะธะผะต ะพั‡ั–ะบัƒะฒะฐะฝะฝั ะฟะตั€ะตะด ะฟะพะฒะตั€ะฝะตะฝะฝัะผ ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ ั– ะผะฐั” ะฟั–ะดั‚ั€ะธะผะบัƒ ั†ะธั… ะฝะพะฒะธั… ะผะพะถะปะธะฒะพัั‚ะตะน Python, ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะฟะธัะฐั‚ะธ ั—ั— ั‚ะฐะบ: + +```Python +burgers = await get_burgers(2) +``` + +ะšะปัŽั‡ ั‚ัƒั‚ - `await`. ะ’ั–ะฝ ะบะฐะถะต Python, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพั‡ะตะบะฐั‚ะธ โธ, ะฟะพะบะธ `get_burgers(2)` ะทะฐะฒะตั€ัˆะธั‚ัŒ ัะฒะพัŽ ั€ะพะฑะพั‚ัƒ ๐Ÿ•™, ะฟะตั€ัˆ ะฝั–ะถ ะทะฑะตั€ะตะณั‚ะธ ั€ะตะทัƒะปัŒั‚ะฐั‚ะธ ะฒ `burgers`. ะ—ะฐะฒะดัะบะธ ั†ัŒะพะผัƒ Python ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะผะพะถะต ะฟั–ั‚ะธ ั– ะทั€ะพะฑะธั‚ะธ ั‰ะพััŒ ั–ะฝัˆะต ๐Ÿ”€ โฏ ั‚ะธะผ ั‡ะฐัะพะผ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธะนะฝัั‚ะธ ั–ะฝัˆะธะน ะทะฐะฟะธั‚). + +ะฉะพะฑ `await` ะฟั€ะฐั†ัŽะฒะฐะฒ, ะฒั–ะฝ ะผะฐั” ะฑัƒั‚ะธ ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั—, ั‰ะพ ะฟั–ะดั‚ั€ะธะผัƒั” ั†ัŽ ะฐัะธะฝั…ั€ะพะฝะฝั–ัั‚ัŒ. ะ”ะปั ั†ัŒะพะณะพ ะฟั€ะพัั‚ะพ ะพะณะพะปะพัั–ั‚ัŒ ั—ั— ัะบ `async def`: + +```Python hl_lines="1" +async def get_burgers(number: int): + # ะ’ะธะบะพะฝะฐะนั‚ะต ะดะตัะบั– ะฐัะธะฝั…ั€ะพะฝะฝั– ะดั–ั—, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะฑัƒั€ะณะตั€ะธ + return burgers +``` + +...ะทะฐะผั–ัั‚ัŒ `def`: + +```Python hl_lines="2" +# ะฆะต ะฝะต ะฐัะธะฝั…ั€ะพะฝะฝะพ +def get_sequential_burgers(number: int): + # ะ’ะธะบะพะฝะฐะนั‚ะต ะดะตัะบั– ะฟะพัะปั–ะดะพะฒะฝั– ะดั–ั—, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะฑัƒั€ะณะตั€ะธ + return burgers +``` + +ะ— `async def` Python ะทะฝะฐั”, ั‰ะพ ะฒัะตั€ะตะดะธะฝั– ั†ั–ั”ั— ั„ัƒะฝะบั†ั–ั— ะฒั–ะฝ ะผะฐั” ะฒั–ะดัะปั–ะดะบะพะฒัƒะฒะฐั‚ะธ ะฒะธั€ะฐะทะธ `await`, ั– ั‰ะพ ะฒั–ะฝ ะผะพะถะต ยซัั‚ะฐะฒะธั‚ะธ ะฝะฐ ะฟะฐัƒะทัƒยป โธ ะฒะธะบะพะฝะฐะฝะฝั ั†ั–ั”ั— ั„ัƒะฝะบั†ั–ั— ั– ะนั‚ะธ ั€ะพะฑะธั‚ะธ ั‰ะพััŒ ั–ะฝัˆะต ๐Ÿ”€, ะฟะตั€ัˆ ะฝั–ะถ ะฟะพะฒะตั€ะฝัƒั‚ะธัั. + +ะšะพะปะธ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะปะธะบะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ, ะฒะธะทะฝะฐั‡ะตะฝัƒ ะท `async def`, ะฒะธ ะผะฐั”ั‚ะต ยซะพั‡ั–ะบัƒะฒะฐั‚ะธยป ั—ั—. ะขะพะถ ั†ะต ะฝะต ัะฟั€ะฐั†ัŽั”: + +```Python +# ะฆะต ะฝะต ัะฟั€ะฐั†ัŽั”, ั‚ะพะผัƒ ั‰ะพ get_burgers ะฒะธะทะฝะฐั‡ะตะฝะพ ัะบ: async def +burgers = get_burgers(2) +``` + +--- + +ะžั‚ะถะต, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฑั–ะฑะปั–ะพั‚ะตะบัƒ, ัะบัƒ ะผะพะถะฝะฐ ะฒะธะบะปะธะบะฐั‚ะธ ะท `await`, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ัั‚ะฒะพั€ะธั‚ะธ ั„ัƒะฝะบั†ั–ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ั‰ะพ ั—ั— ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”, ะท `async def`, ัะบ ั‚ัƒั‚: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### ะ‘ั–ะปัŒัˆะต ั‚ะตั…ะฝั–ั‡ะฝะธั… ะดะตั‚ะฐะปะตะน { #more-technical-details } + +ะ’ะธ ะผะพะณะปะธ ะฟะพะผั–ั‚ะธั‚ะธ, ั‰ะพ `await` ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะปะธัˆะต ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ะน, ะฒะธะทะฝะฐั‡ะตะฝะธั… ะท `async def`. + +ะ ะฒะพะดะฝะพั‡ะฐั ั„ัƒะฝะบั†ั–ั—, ะฒะธะทะฝะฐั‡ะตะฝั– ะท `async def`, ะฟะพั‚ั€ั–ะฑะฝะพ ยซะพั‡ั–ะบัƒะฒะฐั‚ะธยป. ะขะพะถ ั„ัƒะฝะบั†ั–ั— ะท `async def` ั‚ะฐะบะพะถ ะผะพะถะฝะฐ ะฒะธะบะปะธะบะฐั‚ะธ ะปะธัˆะต ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ะน, ะฒะธะทะฝะฐั‡ะตะฝะธั… ะท `async def`. + +ะขะพะถ ัะบ ะถะต ะฒะธะบะปะธะบะฐั‚ะธ ะฟะตั€ัˆัƒ `async`-ั„ัƒะฝะบั†ั–ัŽ - ะบัƒั€ะบะฐ ั‡ะธ ัะนั†ะต? + +ะฏะบั‰ะพ ะฒะธ ะฟั€ะฐั†ัŽั”ั‚ะต ะท **FastAPI**, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั€ะพ ั†ะต ั‚ัƒั€ะฑัƒะฒะฐั‚ะธัั, ะฐะดะถะต ั†ั–ั”ัŽ ยซะฟะตั€ัˆะพัŽยป ั„ัƒะฝะบั†ั–ั”ัŽ ะฑัƒะดะต ะฒะฐัˆะฐ ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ั– FastAPI ะทะฝะฐั‚ะธะผะต, ัะบ ัƒั‡ะธะฝะธั‚ะธ ะฟั€ะฐะฒะธะปัŒะฝะพ. + +ะะปะต ัะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `async` / `await` ะฑะตะท FastAPI, ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ั†ะต ะทั€ะพะฑะธั‚ะธ. + +### ะŸะธัˆะตะผะพ ัะฒั–ะน ะฒะปะฐัะฝะธะน async-ะบะพะด { #write-your-own-async-code } + +Starlette (ั– **FastAPI**) ะฑะฐะทัƒัŽั‚ัŒัั ะฝะฐ AnyIO, ั‰ะพ ั€ะพะฑะธั‚ัŒ ั—ั… ััƒะผั–ัะฝะธะผะธ ัะบ ะทั– ัั‚ะฐะฝะดะฐั€ั‚ะฝะพัŽ ะฑั–ะฑะปั–ะพั‚ะตะบะพัŽ Python asyncio, ั‚ะฐะบ ั– ะท Trio. + +ะ—ะพะบั€ะตะผะฐ, ะฒะธ ะผะพะถะตั‚ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ AnyIO ะดะปั ะฒะฐัˆะธั… ะฟั€ะพััƒะฝัƒั‚ะธั… ัั†ะตะฝะฐั€ั–ั—ะฒ ั€ั–ะฒะฝะพั‡ะฐัะฝะพัั‚ั–, ั‰ะพ ะฟะพั‚ั€ะตะฑัƒัŽั‚ัŒ ัะบะปะฐะดะฝั–ัˆะธั… ะฟะฐั‚ะตั€ะฝั–ะฒ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั–. + +ะ† ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ FastAPI, ะฒะธ ะผะพะณะปะธ ะฑ ะฟะธัะฐั‚ะธ ัะฒะพั— ะฒะปะฐัะฝั– async-ะทะฐัั‚ะพััƒะฝะบะธ ะท AnyIO, ั‰ะพะฑ ะผะฐั‚ะธ ะฒะธัะพะบัƒ ััƒะผั–ัะฝั–ัั‚ัŒ ั– ะพั‚ั€ะธะผะฐั‚ะธ ะนะพะณะพ ะฟะตั€ะตะฒะฐะณะธ (ะฝะฐะฟั€ะธะบะปะฐะด, *ัั‚ั€ัƒะบั‚ัƒั€ะพะฒะฐะฝะฐ ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ*). + +ะฏ ัั‚ะฒะพั€ะธะฒ ั–ะฝัˆัƒ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ ะฟะพะฒะตั€ั… AnyIO, ัะบ ั‚ะพะฝะบะธะน ัˆะฐั€, ั‰ะพะฑ ะดะตั‰ะพ ะฟะพะบั€ะฐั‰ะธั‚ะธ ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟั–ะฒ ั– ะพั‚ั€ะธะผะฐั‚ะธ ะบั€ะฐั‰ัƒ **ะฐะฒั‚ะพะดะพะฟะพะผะพะณัƒ** (autocompletion), **ะฒะฑัƒะดะพะฒะฐะฝั– ะฟะพะผะธะปะบะธ** (inline errors) ั‚ะพั‰ะพ. ะ’ะพะฝะฐ ั‚ะฐะบะพะถ ะผะฐั” ะดั€ัƒะถะฝั–ะน ะฒัั‚ัƒะฟ ั– ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ, ั‰ะพะฑ ะดะพะฟะพะผะพะณั‚ะธ ะฒะฐะผ **ะทั€ะพะทัƒะผั–ั‚ะธ** ั– ะฝะฐะฟะธัะฐั‚ะธ **ะฒะปะฐัะฝะธะน async-ะบะพะด**: Asyncer. ะ’ะพะฝะฐ ะฑัƒะดะต ะพัะพะฑะปะธะฒะพ ะบะพั€ะธัะฝะพัŽ, ัะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ **ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ async-ะบะพะด ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ** (ะฑะปะพะบัƒัŽั‡ะธะผ/ัะธะฝั…ั€ะพะฝะฝะธะผ) ะบะพะดะพะผ. + +### ะ†ะฝัˆั– ั„ะพั€ะผะธ ะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ ะบะพะดัƒ { #other-forms-of-asynchronous-code } + +ะขะฐะบะธะน ัั‚ะธะปัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `async` ั– `await` ะฒั–ะดะฝะพัะฝะพ ะฝะพะฒะธะน ัƒ ะผะพะฒั–. + +ะะปะต ะฒั–ะฝ ะทะฝะฐั‡ะฝะพ ะฟะพะปะตะณัˆัƒั” ั€ะพะฑะพั‚ัƒ ะท ะฐัะธะฝั…ั€ะพะฝะฝะธะผ ะบะพะดะพะผ. + +ะขะฐะบะธะน ัะฐะผะธะน (ะฐะฑะพ ะผะฐะนะถะต ั–ะดะตะฝั‚ะธั‡ะฝะธะน) ัะธะฝั‚ะฐะบัะธั ะฝะตั‰ะพะดะฐะฒะฝะพ ะทโ€™ัะฒะธะฒัั ะฒ ััƒั‡ะฐัะฝะธั… ะฒะตั€ัั–ัั… JavaScript (ัƒ Browser ั– NodeJS). + +ะ”ะพ ั†ัŒะพะณะพ ั€ะพะฑะพั‚ะฐ ะท ะฐัะธะฝั…ั€ะพะฝะฝะธะผ ะบะพะดะพะผ ะฑัƒะปะฐ ะทะฝะฐั‡ะฝะพ ัะบะปะฐะดะฝั–ัˆะพัŽ. + +ะฃ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั… Python ะฒะธ ะผะพะณะปะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟะพั‚ะพะบะธ (threads) ะฐะฑะพ Gevent. ะะปะต ะบะพะด ะฝะฐะฑะฐะณะฐั‚ะพ ัะบะปะฐะดะฝั–ัˆะธะน ะดะปั ั€ะพะทัƒะผั–ะฝะฝั, ะฝะฐะปะฐะณะพะดะถะตะฝะฝั ั– ะผะธัะปะตะฝะฝั ะฟั€ะพ ะฝัŒะพะณะพ. + +ะฃ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฒะตั€ัั–ัั… NodeJS/Browser JavaScript ะฒะธ ะฑ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ยซcallbacksยป, ั‰ะพ ะฟั€ะธะทะฒะพะดะธั‚ัŒ ะดะพ ยซcallback hellยป. + +## ะกะฟั–ะฒะฟั€ะพะณั€ะฐะผะธ { #coroutines } + +**ะกะฟั–ะฒะฟั€ะพะณั€ะฐะผะฐ** - ั†ะต ะฟั€ะพัั‚ะพ ะดัƒะถะต ะฒะธัˆัƒะบะฐะฝะฐ ะฝะฐะทะฒะฐ ะดะปั ะพะฑโ€™ั”ะบั‚ะฐ, ัะบะธะน ะฟะพะฒะตั€ั‚ะฐั” ั„ัƒะฝะบั†ั–ั `async def`. Python ะทะฝะฐั”, ั‰ะพ ั†ะต ั‰ะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ ั„ัƒะฝะบั†ั–ั—, ัะบัƒ ะผะพะถะฝะฐ ะทะฐะฟัƒัั‚ะธั‚ะธ ั– ัะบะฐ ะทะฐะฒะตั€ัˆะธั‚ัŒัั ะฒ ะฟะตะฒะฝะธะน ะผะพะผะตะฝั‚, ะฐะปะต ัะบัƒ ั‚ะฐะบะพะถ ะผะพะถะฝะฐ ะฟะพัั‚ะฐะฒะธั‚ะธ ะฝะฐ ะฟะฐัƒะทัƒ โธ ะฒัะตั€ะตะดะธะฝั–, ะบะพะปะธ ั” `await`. + +ะะปะต ะฒััŽ ั†ัŽ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ ะบะพะดัƒ ะท `async` ั– `await` ั‡ะฐัั‚ะพ ะฟั–ะดััƒะผะพะฒัƒัŽั‚ัŒ ัะบ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ยซัะฟั–ะฒะฟั€ะพะณั€ะฐะผยป. ะฆะต ะฟะพั€ั–ะฒะฝัะฝะพ ะท ะณะพะปะพะฒะฝะพัŽ ะบะปัŽั‡ะพะฒะพัŽ ะพัะพะฑะปะธะฒั–ัั‚ัŽ Go - ยซGoroutinesยป. + +## ะ’ะธัะฝะพะฒะพะบ { #conclusion } + +ะŸะพะณะปัะฝัŒะผะพ ะฝะฐ ั‚ัƒ ัะฐะผัƒ ั„ั€ะฐะทัƒ ั‰ะต ั€ะฐะท: + +> ะกัƒั‡ะฐัะฝั– ะฒะตั€ัั–ั— Python ะผะฐัŽั‚ัŒ ะฟั–ะดั‚ั€ะธะผะบัƒ ยซะฐัะธะฝั…ั€ะพะฝะฝะพะณะพ ะบะพะดัƒยป ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ั‚ะฐะบ ะทะฒะฐะฝะธั… ยซัะฟั–ะฒะฟั€ะพะณั€ะฐะผยป, ะท ัะธะฝั‚ะฐะบัะธัะพะผ **`async` ั– `await`**. + +ะขะตะฟะตั€ ั†ะต ะผะฐั” ะฑั–ะปัŒัˆะต ัะตะฝััƒ. โœจ + +ะฃัะต ั†ะต ะฟั€ะธะฒะพะดะธั‚ัŒ ัƒ ะดั–ัŽ FastAPI (ั‡ะตั€ะตะท Starlette) ั– ะดะฐั” ะนะพะผัƒ ั‚ะฐะบัƒ ะฒั€ะฐะถะฐัŽั‡ัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. + +## ะ”ัƒะถะต ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– { #very-technical-details } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะต. + +ะฆะต ะดัƒะถะต ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– ะฟั€ะพ ั‚ะต, ัะบ **FastAPI** ะฟั€ะฐั†ัŽั” ยซะฟั–ะด ะบะฐะฟะพั‚ะพะผยป. + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” ั‡ะธะผะฐะปะพ ั‚ะตั…ะฝั–ั‡ะฝะธั… ะทะฝะฐะฝัŒ (ัะฟั–ะฒะฟั€ะพะณั€ะฐะผะธ, ะฟะพั‚ะพะบะธ, ะฑะปะพะบัƒะฒะฐะฝะฝั ั‚ะพั‰ะพ) ั– ะฒะฐะผ ั†ั–ะบะฐะฒะพ, ัะบ FastAPI ะพะฑั€ะพะฑะปัั” `async def` ะฟั€ะพั‚ะธ ะทะฒะธั‡ะฐะนะฝะพะณะพ `def`, - ะฒะฟะตั€ะตะด. + +/// + +### ะคัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ { #path-operation-functions } + +ะšะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ั„ัƒะฝะบั†ั–ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ `def` ะทะฐะผั–ัั‚ัŒ `async def`, ะฒะพะฝะฐ ะฒะธะบะพะฝัƒั”ั‚ัŒัั ัƒ ะทะพะฒะฝั–ัˆะฝัŒะพะผัƒ ะฟัƒะปั– ะฟะพั‚ะพะบั–ะฒ (threadpool), ัะบะธะน ะฟะพั‚ั–ะผ ยซะพั‡ั–ะบัƒั”ั‚ัŒััยป, ะทะฐะผั–ัั‚ัŒ ะฟั€ัะผะพะณะพ ะฒะธะบะปะธะบัƒ (ะพัะบั–ะปัŒะบะธ ะฟั€ัะผะธะน ะฒะธะบะปะธะบ ะฑะปะพะบัƒะฒะฐะฒ ะฑะธ ัะตั€ะฒะตั€). + +ะฏะบั‰ะพ ะฒะธ ะฟั€ะธะนัˆะปะธ ะท ั–ะฝัˆะพะณะพ async-ั„ั€ะตะนะผะฒะพั€ะบัƒ, ัะบะธะน ะฝะต ะฟั€ะฐั†ัŽั” ั‚ะฐะบ, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต, ั– ะทะฒะธะบะปะธ ะฒะธะทะฝะฐั‡ะฐั‚ะธ ั‚ั€ะธะฒั–ะฐะปัŒะฝั–, ะปะธัˆะต ะพะฑั‡ะธัะปัŽะฒะฐะปัŒะฝั– ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ `def` ะทะฐั€ะฐะดะธ ะบั€ะธั…ั–ั‚ะฝะพะณะพ ะฒะธะณั€ะฐัˆัƒ ัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝะพัั‚ั– (ะฑะปะธะทัŒะบะพ 100 ะฝะฐะฝะพัะตะบัƒะฝะด), ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ัƒ **FastAPI** ะตั„ะตะบั‚ ะฑัƒะดะต ะฟั€ะพั‚ะธะปะตะถะฝะธะผ. ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะบั€ะฐั‰ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `async def`, ัะบั‰ะพ ั‚ั–ะปัŒะบะธ ะฒะฐัˆั– ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะบะพะด, ั‰ะพ ะฒะธะบะพะฝัƒั” ะฑะปะพะบัƒัŽั‡ะต I/O. + +ะ’ั‚ั–ะผ, ัƒ ะฑัƒะดัŒ-ัะบั–ะน ัะธั‚ัƒะฐั†ั–ั— ั” ะฒะตะปะธะบะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ **FastAPI** [ะฒัะต ะพะดะฝะพ ะฑัƒะดะต ัˆะฒะธะดัˆะธะผ](index.md#performance){.internal-link target=_blank} (ะฐะฑะพ ะฟั€ะธะฝะฐะนะผะฝั– ะฟะพั€ั–ะฒะฝัะฝะฝะธะผ) ะทะฐ ะฒะฐัˆ ะฟะพะฟะตั€ะตะดะฝั–ะน ั„ั€ะตะนะผะฒะพั€ะบ. + +### ะ—ะฐะปะตะถะฝะพัั‚ั– { #dependencies } + +ะขะต ัะฐะผะต ัั‚ะพััƒั”ั‚ัŒัั ั– [ะทะฐะปะตะถะฝะพัั‚ะตะน](tutorial/dependencies/index.md){.internal-link target=_blank}. ะฏะบั‰ะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั” ัั‚ะฐะฝะดะฐั€ั‚ะฝะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ `def` ะทะฐะผั–ัั‚ัŒ `async def`, ะฒะพะฝะฐ ะฒะธะบะพะฝัƒั”ั‚ัŒัั ัƒ ะทะพะฒะฝั–ัˆะฝัŒะพะผัƒ ะฟัƒะปั– ะฟะพั‚ะพะบั–ะฒ. + +### ะŸั–ะดะทะฐะปะตะถะฝะพัั‚ั– { #sub-dependencies } + +ะ’ะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะบั–ะปัŒะบะฐ ะทะฐะปะตะถะฝะพัั‚ะตะน ั– [ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ะตะน](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}, ัะบั– ะฒะธะผะฐะณะฐัŽั‚ัŒ ะพะดะฝะฐ ะพะดะฝัƒ (ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฒะธะทะฝะฐั‡ะตะฝัŒ ั„ัƒะฝะบั†ั–ะน). ะ”ะตัะบั– ะท ะฝะธั… ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ัั‚ะฒะพั€ะตะฝั– ะท `async def`, ะฐ ะดะตัะบั– - ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ `def`. ะ’ัะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต, ั– ั‚ั–, ั‰ะพ ัั‚ะฒะพั€ะตะฝั– ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ `def`, ะฑัƒะดัƒั‚ัŒ ะฒะธะบะปะธะบะฐะฝั– ัƒ ะทะพะฒะฝั–ัˆะฝัŒะพะผัƒ ะฟะพั‚ะพั†ั– (ะท ะฟัƒะปัƒ ะฟะพั‚ะพะบั–ะฒ), ะฐ ะฝะต ยซะพั‡ั–ะบัƒะฒะฐะฝั–ยป. + +### ะ†ะฝัˆั– ะดะพะฟะพะผั–ะถะฝั– ั„ัƒะฝะบั†ั–ั— { #other-utility-functions } + +ะ‘ัƒะดัŒ-ัะบะฐ ั–ะฝัˆะฐ ะดะพะฟะพะผั–ะถะฝะฐ ั„ัƒะฝะบั†ั–ั, ัะบัƒ ะฒะธ ะฒะธะบะปะธะบะฐั”ั‚ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ะผะพะถะต ะฑัƒั‚ะธ ัั‚ะฒะพั€ะตะฝะฐ ะทั– ะทะฒะธั‡ะฐะนะฝะธะผ `def` ะฐะฑะพ `async def`, ั– FastAPI ะฝะต ะฒะฟะปะธะฒะฐั‚ะธะผะต ะฝะฐ ัะฟะพัั–ะฑ ั—ั— ะฒะธะบะปะธะบัƒ. + +ะฆะต ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด ั„ัƒะฝะบั†ั–ะน, ัะบั– FastAPI ะฒะธะบะปะธะบะฐั” ะทะฐ ะฒะฐั: ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ั– ะทะฐะปะตะถะฝะพัั‚ั–. + +ะฏะบั‰ะพ ะฒะฐัˆะฐ ะดะพะฟะพะผั–ะถะฝะฐ ั„ัƒะฝะบั†ั–ั ั” ะทะฒะธั‡ะฐะนะฝะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ ะท `def`, ั—ั— ะฑัƒะดะต ะฒะธะบะปะธะบะฐะฝะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ (ัะบ ะฒะธ ะฝะฐะฟะธัะฐะปะธ ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–), ะฝะต ะฒ ะฟัƒะปั– ะฟะพั‚ะพะบั–ะฒ; ัะบั‰ะพ ั„ัƒะฝะบั†ั–ั ัั‚ะฒะพั€ะตะฝะฐ ะท `async def`, ั‚ะพะดั– ะฒะฐะผ ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `await` ะฟั€ะธ ั—ั— ะฒะธะบะปะธะบัƒ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั–. + +--- + +ะ—ะฝะพะฒัƒ ะถ ั‚ะฐะบะธ, ั†ะต ะดัƒะถะต ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั–, ัะบั–, ะนะผะพะฒั–ั€ะฝะพ, ัั‚ะฐะฝัƒั‚ัŒ ัƒ ะฟั€ะธะณะพะดั–, ัะบั‰ะพ ะฒะธ ัะฟะตั†ั–ะฐะปัŒะฝะพ ั—ั… ัˆัƒะบะฐะปะธ. + +ะ†ะฝะฐะบัˆะต ะฒะฐะผ ะฒะธัั‚ะฐั‡ะธั‚ัŒ ะฝะฐัั‚ะฐะฝะพะฒ ั–ะท ั€ะพะทะดั–ะปัƒ ะฒะธั‰ะต: ะŸะพัะฟั–ัˆะฐั”ั‚ะต?. diff --git a/docs/uk/docs/benchmarks.md b/docs/uk/docs/benchmarks.md new file mode 100644 index 0000000000..d53b7ee989 --- /dev/null +++ b/docs/uk/docs/benchmarks.md @@ -0,0 +1,34 @@ +# ะ‘ะตะฝั‡ะผะฐั€ะบะธ { #benchmarks } + +ะะตะทะฐะปะตะถะฝั– ะฑะตะฝั‡ะผะฐั€ะบะธ TechEmpower ะฟะพะบะฐะทัƒัŽั‚ัŒ, ั‰ะพ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI, ะทะฐะฟัƒั‰ะตะฝั– ะฟั–ะด ะบะตั€ัƒะฒะฐะฝะฝัะผ Uvicorn, ั” ะพะดะฝะธะผ ั–ะท ะฝะฐะนัˆะฒะธะดัˆะธั… ะดะพัั‚ัƒะฟะฝะธั… ั„ั€ะตะนะผะฒะพั€ะบั–ะฒ Python, ะฟะพัั‚ัƒะฟะฐัŽั‡ะธััŒ ะปะธัˆะต ัะฐะผะธะผ Starlette ั– Uvicorn (ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั FastAPI ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ). + +ะะปะต ะฟะตั€ะตะณะปัะดะฐัŽั‡ะธ ะฑะตะฝั‡ะผะฐั€ะบะธ ั‚ะฐ ะฟะพั€ั–ะฒะฝัะฝะฝั, ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั– ั‚ะฐะบะต. + +## ะ‘ะตะฝั‡ะผะฐั€ะบะธ ั‚ะฐ ัˆะฒะธะดะบั–ัั‚ัŒ { #benchmarks-and-speed } + +ะŸั–ะด ั‡ะฐั ะฟะตั€ะตะณะปัะดัƒ ะฑะตะฝั‡ะผะฐั€ะบั–ะฒ ั‡ะฐัั‚ะพ ะฟะพั€ั–ะฒะฝัŽัŽั‚ัŒ ะบั–ะปัŒะบะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั€ั–ะทะฝะธั… ั‚ะธะฟั–ะฒ ัะบ ั€ั–ะฒะฝะพั†ั–ะฝะฝั–. + +ะ—ะพะบั€ะตะผะฐ, ั€ะฐะทะพะผ ะฟะพั€ั–ะฒะฝัŽัŽั‚ัŒ Uvicorn, Starlette ั– FastAPI (ัะตั€ะตะด ะฑะฐะณะฐั‚ัŒะพั… ั–ะฝัˆะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ). + +ะงะธะผ ะฟั€ะพัั‚ั–ัˆะต ะทะฐะฒะดะฐะฝะฝั, ัะบะต ั€ะพะทะฒ'ัะทัƒั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ั‚ะธะผ ะบั€ะฐั‰ะพัŽ ะฑัƒะดะต ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. ะ† ะฑั–ะปัŒัˆั–ัั‚ัŒ ะฑะตะฝั‡ะผะฐั€ะบั–ะฒ ะฝะต ะฟะตั€ะตะฒั–ั€ััŽั‚ัŒ ะดะพะดะฐั‚ะบะพะฒั– ะผะพะถะปะธะฒะพัั‚ั–, ั‰ะพ ะฝะฐะดะฐั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚. + +ะ†ั”ั€ะฐั€ั…ั–ั ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบะฐ: + +* Uvicorn: ัะตั€ะฒะตั€ ASGI + * Starlette: (ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn) ะฒะตะฑ-ะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบ + * FastAPI: (ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Starlette) ะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบ ะดะปั API ะท ะฝะธะทะบะพัŽ ะดะพะดะฐั‚ะบะพะฒะธั… ะผะพะถะปะธะฒะพัั‚ะตะน ะดะปั ัั‚ะฒะพั€ะตะฝะฝั API, ะท ะฒะฐะปั–ะดะฐั†ั–ั”ัŽ ะดะฐะฝะธั… ั‚ะพั‰ะพ. + +* Uvicorn: + * ะœะฐั‚ะธะผะต ะฝะฐะนะฒะธั‰ัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ะฐะดะถะต ะผะฐะนะถะต ะฝะต ะผั–ัั‚ะธั‚ัŒ ะดะพะดะฐั‚ะบะพะฒะพะณะพ ะบะพะดัƒ ะพะบั€ั–ะผ ะฒะปะฐัะฝะต ัะตั€ะฒะตั€ะฐ. + * ะ’ะธ ะฝะต ะฟะธัะฐั‚ะธะผะตั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฝะฐ Uvicorn. ะฆะต ะพะทะฝะฐั‡ะฐะปะพ ะฑ, ั‰ะพ ะฒะฐัˆ ะบะพะด ะผะฐะฒ ะฑะธ ะฒะบะปัŽั‡ะฐั‚ะธ ะฟั€ะธะฝะฐะนะผะฝั– ะฟั€ะธะฑะปะธะทะฝะพ ะฒะตััŒ ะบะพะด, ัะบะธะน ะฝะฐะดะฐั” Starlette (ะฐะฑะพ FastAPI). ะ† ัะบั‰ะพ ะทั€ะพะฑะธั‚ะธ ั‚ะฐะบ, ะฒะฐัˆ ะบั–ะฝั†ะตะฒะธะน ะทะฐัั‚ะพััƒะฝะพะบ ะผะฐั‚ะธะผะต ั‚ั– ัะฐะผั– ะฝะฐะบะปะฐะดะฝั– ะฒะธั‚ั€ะฐั‚ะธ, ั‰ะพ ะน ะฟั–ะด ั‡ะฐั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั„ั€ะตะนะผะฒะพั€ะบัƒ, ัะบะธะน ะผั–ะฝั–ะผั–ะทัƒั” ะบะพะด ะทะฐัั‚ะพััƒะฝะบัƒ ั‚ะฐ ะฟะพะผะธะปะบะธ. + * ะฏะบั‰ะพ ะฒะธ ะฟะพั€ั–ะฒะฝัŽั”ั‚ะต Uvicorn, ะฟะพั€ั–ะฒะฝัŽะนั‚ะต ะนะพะณะพ ะท Daphne, Hypercorn, uWSGI ั‚ะพั‰ะพ. ะกะตั€ะฒะตั€ะธ ะทะฐัั‚ะพััƒะฝะบั–ะฒ. +* Starlette: + * ะœะฐั‚ะธะผะต ะฝะฐัั‚ัƒะฟะฝัƒ ะทะฐ ัˆะฒะธะดะบั–ัั‚ัŽ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ ะฟั–ัะปั Uvicorn. ะะฐัะฟั€ะฐะฒะดั– Starlette ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn ะดะปั ะทะฐะฟัƒัะบัƒ. ะขะพะถ ะฒะพะฝะฐ ะผะพะถะต ะฑัƒั‚ะธ ยซะฟะพะฒั–ะปัŒะฝั–ัˆะพัŽยป ะทะฐ Uvicorn ะปะธัˆะต ั‡ะตั€ะตะท ะฝะตะพะฑั…ั–ะดะฝั–ัั‚ัŒ ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฑั–ะปัŒัˆะต ะบะพะดัƒ. + * ะะปะต ะฝะฐะดะฐั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฟั€ะพัั‚ะธั… ะฒะตะฑ-ะทะฐัั‚ะพััƒะฝะบั–ะฒ ั–ะท ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั†ั–ั”ัŽ ะฝะฐ ะพัะฝะพะฒั– ัˆะปัั…ั–ะฒ ั‚ะพั‰ะพ. + * ะฏะบั‰ะพ ะฒะธ ะฟะพั€ั–ะฒะฝัŽั”ั‚ะต Starlette, ะฟะพั€ั–ะฒะฝัŽะนั‚ะต ั—ั— ะท Sanic, Flask, Django ั‚ะพั‰ะพ. ะ’ะตะฑ-ั„ั€ะตะนะผะฒะพั€ะบะธ (ะฐะฑะพ ะผั–ะบั€ะพั„ั€ะตะนะผะฒะพั€ะบะธ). +* FastAPI: + * ะะฝะฐะปะพะณั–ั‡ะฝะพ ะดะพ ั‚ะพะณะพ, ัะบ Starlette ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn ั– ะฝะต ะผะพะถะต ะฑัƒั‚ะธ ัˆะฒะธะดัˆะพัŽ ะทะฐ ะฝัŒะพะณะพ, FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Starlette, ั‚ะพะถ ะฝะต ะผะพะถะต ะฑัƒั‚ะธ ัˆะฒะธะดัˆะพัŽ ะทะฐ ะฝะตั—. + * FastAPI ะฝะฐะดะฐั” ะฑั–ะปัŒัˆะต ะผะพะถะปะธะฒะพัั‚ะตะน ะฟะพะฒะตั€ั… Starlette. ะœะพะถะปะธะฒะพัั‚ั–, ัะบั– ะผะฐะนะถะต ะทะฐะฒะถะดะธ ะฟะพั‚ั€ั–ะฑะฝั– ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั API, ัะบ-ะพั‚ ะฒะฐะปั–ะดะฐั†ั–ั ั‚ะฐ ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั ะดะฐะฝะธั…. ะ†, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะนะพะณะพ, ะฒะธ ะฑะตะทะบะพัˆั‚ะพะฒะฝะพ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ (ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ะฝะฐะฒั–ั‚ัŒ ะฝะต ะดะพะดะฐั” ะฝะฐะบะปะฐะดะฝะธั… ะฒะธั‚ั€ะฐั‚ ะฟั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะทะฐัั‚ะพััƒะฝะบัƒ - ะฒะพะฝะฐ ะณะตะฝะตั€ัƒั”ั‚ัŒัั ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ). + * ะฏะบะฑะธ ะฒะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ FastAPI ั– ะทะฐัั‚ะพััƒะฒะฐะปะธ Starlette ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ (ะฐะฑะพ ั–ะฝัˆะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ะฝะฐะฟั€ะธะบะปะฐะด Sanic, Flask, Responder ั‚ะพั‰ะพ), ะฒะฐะผ ะดะพะฒะตะปะพัั ะฑ ัะฐะผะพัั‚ั–ะนะฝะพ ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ะฒััŽ ะฒะฐะปั–ะดะฐั†ั–ัŽ ั‚ะฐ ัะตั€ั–ะฐะปั–ะทะฐั†ั–ัŽ ะดะฐะฝะธั…. ะขะพะถ ะฒะฐัˆ ะบั–ะฝั†ะตะฒะธะน ะทะฐัั‚ะพััƒะฝะพะบ ัƒัะต ะพะดะฝะพ ะผะฐะฒ ะฑะธ ั‚ั– ัะฐะผั– ะฝะฐะบะปะฐะดะฝั– ะฒะธั‚ั€ะฐั‚ะธ, ะฝั–ะฑะธ ะฒั–ะฝ ะฑัƒะฒ ัั‚ะฒะพั€ะตะฝะธะน ั–ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ FastAPI. ะ† ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ัะฐะผะต ั†ั ะฒะฐะปั–ะดะฐั†ั–ั ั‚ะฐ ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั ะดะฐะฝะธั… ัั‚ะฐะฝะพะฒะธั‚ัŒ ะฝะฐะนะฑั–ะปัŒัˆะธะน ะพะฑััะณ ะบะพะดัƒ ะฒ ะทะฐัั‚ะพััƒะฝะบะฐั…. + * ะžั‚ะถะต, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ FastAPI, ะฒะธ ะทะฐะพั‰ะฐะดะถัƒั”ั‚ะต ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ, ะทะผะตะฝัˆัƒั”ั‚ะต ะบั–ะปัŒะบั–ัั‚ัŒ ะฟะพะผะธะปะพะบ ั– ั€ัะดะบั–ะฒ ะบะพะดัƒ ั‚ะฐ, ะนะผะพะฒั–ั€ะฝะพ, ะพั‚ั€ะธะผัƒั”ั‚ะต ั‚ะฐะบัƒ ัะฐะผัƒ (ะฐะฑะพ ะบั€ะฐั‰ัƒ) ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ัะบ ั– ะฑะตะท ะฝัŒะพะณะพ (ะฐะดะถะต ั–ะฝะฐะบัˆะต ะฒะฐะผ ะดะพะฒะตะปะพัั ะฑ ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ะฒัะต ั†ะต ัƒ ะฒะปะฐัะฝะพะผัƒ ะบะพะดั–). + * ะฏะบั‰ะพ ะฒะธ ะฟะพั€ั–ะฒะฝัŽั”ั‚ะต FastAPI, ะฟะพั€ั–ะฒะฝัŽะนั‚ะต ะนะพะณะพ ะท ะฒะตะฑ-ั„ั€ะตะนะผะฒะพั€ะบะพะผ (ะฐะฑะพ ะฝะฐะฑะพั€ะพะผ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ), ัะบะธะน ะฝะฐะดะฐั” ะฒะฐะปั–ะดะฐั†ั–ัŽ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ัŽ ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ, ะฝะฐะฟั€ะธะบะปะฐะด Flask-apispec, NestJS, Molten ั‚ะพั‰ะพ. ะคั€ะตะนะผะฒะพั€ะบะธ ะท ะฒะฑัƒะดะพะฒะฐะฝะพัŽ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ะฒะฐะปั–ะดะฐั†ั–ั”ัŽ ะดะฐะฝะธั…, ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั”ัŽ ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ. diff --git a/docs/uk/docs/deployment/cloud.md b/docs/uk/docs/deployment/cloud.md new file mode 100644 index 0000000000..a17aaf2591 --- /dev/null +++ b/docs/uk/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# ะ ะพะทะณะพั€ั‚ะฐะฝะฝั FastAPI ัƒ ั…ะผะฐั€ะฝะธั… ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบั–ะฒ { #deploy-fastapi-on-cloud-providers } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟั€ะฐะบั‚ะธั‡ะฝะพ **ะฑัƒะดัŒ-ัะบะพะณะพ ั…ะผะฐั€ะฝะพะณะพ ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะฐ**, ั‰ะพะฑ ั€ะพะทะณะพั€ะฝัƒั‚ะธ ัะฒั–ะน ะทะฐัั‚ะพััƒะฝะพะบ FastAPI. + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะพัะฝะพะฒะฝั– ั…ะผะฐั€ะฝั– ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะธ ะผะฐัŽั‚ัŒ ั–ะฝัั‚ั€ัƒะบั†ั–ั— ะท ั€ะพะทะณะพั€ั‚ะฐะฝะฝั FastAPI ัƒ ะฝะธั…. + +## FastAPI Cloud { #fastapi-cloud } + +**FastAPI Cloud** ัั‚ะฒะพั€ะตะฝะพ ั‚ะธะผ ัะฐะผะธะผ ะฐะฒั‚ะพั€ะพะผ ั– ะบะพะผะฐะฝะดะพัŽ, ั‰ะพ ัั‚ะพัั‚ัŒ ะทะฐ **FastAPI**. + +ะ’ะพะฝะพ ัะฟั€ะพั‰ัƒั” ะฟั€ะพั†ะตั **ัั‚ะฒะพั€ะตะฝะฝั**, **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั** ั‚ะฐ **ะดะพัั‚ัƒะฟัƒ** ะดะพ API ะท ะผั–ะฝั–ะผะฐะปัŒะฝะธะผะธ ะทัƒัะธะปะปัะผะธ. + +ะ’ะพะฝะพ ะฟะตั€ะตะฝะพัะธั‚ัŒ ั‚ะพะน ัะฐะผะธะน **ะดะพัะฒั–ะด ั€ะพะทั€ะพะฑะฝะธะบะฐ** ะทั– ัั‚ะฒะพั€ะตะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ ั–ะท FastAPI ะฝะฐ ั—ั… **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั** ัƒ ั…ะผะฐั€ั–. ๐ŸŽ‰ + +FastAPI Cloud ั” ะพัะฝะพะฒะฝะธะผ ัะฟะพะฝัะพั€ะพะผ ั– ะดะถะตั€ะตะปะพะผ ั„ั–ะฝะฐะฝััƒะฒะฐะฝะฝั ะฟั€ะพั”ะบั‚ั–ะฒ ะท ะฒั–ะดะบั€ะธั‚ะธะผ ะบะพะดะพะผ *FastAPI and friends*. โœจ + +## ะฅะผะฐั€ะฝั– ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะธ - ัะฟะพะฝัะพั€ะธ { #cloud-providers-sponsors } + +ะ”ะตัะบั– ั–ะฝัˆั– ั…ะผะฐั€ะฝั– ะฟะพัั‚ะฐั‡ะฐะปัŒะฝะธะบะธ โœจ [**ัะฟะพะฝัะพั€ัƒัŽั‚ัŒ FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ ั‚ะฐะบะพะถ. ๐Ÿ™‡ + +ะœะพะถะปะธะฒะพ, ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ั€ะพะทะณะปัะฝัƒั‚ะธ ั—ั…, ั‰ะพะฑ ะดะพั‚ั€ะธะผัƒะฒะฐั‚ะธัั ั—ั…ะฝั–ั… ั–ะฝัั‚ั€ัƒะบั†ั–ะน ั– ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ั—ั…ะฝั– ัะตั€ะฒั–ัะธ: + +* Render +* Railway diff --git a/docs/uk/docs/deployment/concepts.md b/docs/uk/docs/deployment/concepts.md new file mode 100644 index 0000000000..07ad314405 --- /dev/null +++ b/docs/uk/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# ะšะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployments-concepts } + +ะŸั–ะด ั‡ะฐั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะพะณะพ ะฒะตะฑ-API) ั” ะบั–ะปัŒะบะฐ ะบะพะฝั†ะตะฟั†ั–ะน, ัะบั–, ะนะผะพะฒั–ั€ะฝะพ, ะฒะฐั ั†ั–ะบะฐะฒะปัั‚ัŒ, ั–, ัะฟะธั€ะฐัŽั‡ะธััŒ ะฝะฐ ะฝะธั…, ะฒะธ ะทะผะพะถะตั‚ะต ะทะฝะฐะนั‚ะธ **ะฝะฐะนะฒั–ะดะฟะพะฒั–ะดะฝั–ัˆะธะน** ัะฟะพัั–ะฑ **ั€ะพะทะณะพั€ะฝัƒั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ**. + +ะ”ะตัะบั– ะฒะฐะถะปะธะฒั– ะบะพะฝั†ะตะฟั†ั–ั—: + +- ะ‘ะตะทะฟะตะบะฐ - HTTPS +- ะ—ะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ +- ะŸะตั€ะตะทะฐะฟัƒัะบะธ +- ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +- ะŸะฐะผ'ัั‚ัŒ +- ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ + +ะŸะพะดะธะฒะธะผะพััŒ, ัะบ ะฒะพะฝะธ ะฒะฟะปะธะฒะฐัŽั‚ัŒ ะฝะฐ **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั**. + +ะ—ั€ะตัˆั‚ะพัŽ ะณะพะปะพะฒะฝะฐ ะผะตั‚ะฐ - **ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะบะปั–ั”ะฝั‚ั–ะฒ ะฒะฐัˆะพะณะพ API** ั‚ะฐะบ, ั‰ะพะฑ ั†ะต ะฑัƒะปะพ **ะฑะตะทะฟะตั‡ะฝะธะผ**, ะท **ะผั–ะฝั–ะผัƒะผะพะผ ะฟะตั€ะตั€ะฒ ัƒ ั€ะพะฑะพั‚ั–**, ั– ั‰ะพะฑ **ะพะฑั‡ะธัะปัŽะฒะฐะปัŒะฝั– ั€ะตััƒั€ัะธ** (ะฝะฐะฟั€ะธะบะปะฐะด, ะฒั–ะดะดะฐะปะตะฝั– ัะตั€ะฒะตั€ะธ/ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ะผะฐัˆะธะฝะธ) ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธัั ัะบะพะผะพะณะฐ ะตั„ะตะบั‚ะธะฒะฝั–ัˆะต. ๐Ÿš€ + +ะะธะถั‡ะต ั ั‚ั€ะพั…ะธ ะฑั–ะปัŒัˆะต ั€ะพะทะฟะพะฒั–ะผ ะฟั€ะพ ั†ั– **ะบะพะฝั†ะตะฟั†ั–ั—**, ั–, ัะฟะพะดั–ะฒะฐัŽัั, ั†ะต ะดะฐัั‚ัŒ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝัƒ **ั–ะฝั‚ัƒั—ั†ั–ัŽ**, ั‰ะพะฑ ะฒะธั€ั–ัˆัƒะฒะฐั‚ะธ, ัะบ ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะฒะฐัˆ API ะฒ ะดัƒะถะต ั€ั–ะทะฝะธั… ัะตั€ะตะดะพะฒะธั‰ะฐั…, ะผะพะถะปะธะฒะพ, ะฝะฐะฒั–ั‚ัŒ ัƒ **ะผะฐะนะฑัƒั‚ะฝั–ั…**, ัะบะธั… ั‰ะต ะฝะต ั–ัะฝัƒั”. + +ะ’ั€ะฐั…ะพะฒัƒัŽั‡ะธ ั†ั– ะบะพะฝั†ะตะฟั†ั–ั—, ะฒะธ ะทะผะพะถะตั‚ะต **ะพั†ั–ะฝัŽะฒะฐั‚ะธ ั‚ะฐ ะฟั€ะพั”ะบั‚ัƒะฒะฐั‚ะธ** ะฝะฐะนะบั€ะฐั‰ะธะน ัะฟะพัั–ะฑ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั **ะฒะฐัˆะธั… ะฒะปะฐัะฝะธั… API**. + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ะฝะฐะฒะตะดัƒ ะฑั–ะปัŒัˆ **ะบะพะฝะบั€ะตั‚ะฝั– ั€ะตั†ะตะฟั‚ะธ** ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ FastAPI. + +ะ ะฟะพะบะธ ะฟะตั€ะตะณะปัะฝัŒะผะพ ั†ั– ะฒะฐะถะปะธะฒั– **ะบะพะฝั†ะตะฟั‚ัƒะฐะปัŒะฝั– ั–ะดะตั—**. ะ’ะพะฝะธ ั‚ะฐะบะพะถ ะทะฐัั‚ะพัะพะฒะฝั– ะดะพ ะฑัƒะดัŒ-ัะบะพะณะพ ั–ะฝัˆะพะณะพ ั‚ะธะฟัƒ ะฒะตะฑ-API. ๐Ÿ’ก + +## ะ‘ะตะทะฟะตะบะฐ - HTTPS { #security-https } + +ะฃ [ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฟั€ะพ HTTPS](https.md){.internal-link target=_blank} ะผะธ ะดั–ะทะฝะฐะปะธัั, ัะบ HTTPS ะทะฐะฑะตะทะฟะตั‡ัƒั” ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะดะปั ะฒะฐัˆะพะณะพ API. + +ะœะธ ั‚ะฐะบะพะถ ะฑะฐั‡ะธะปะธ, ั‰ะพ HTTPS ะทะฐะทะฒะธั‡ะฐะน ะฝะฐะดะฐั”ั‚ัŒัั ะบะพะผะฟะพะฝะตะฝั‚ะพะผ, **ะทะพะฒะฝั–ัˆะฝั–ะผ** ั‰ะพะดะพ ะฒะฐัˆะพะณะพ ัะตั€ะฒะตั€ะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, - **TLS Termination Proxy**. + +ะ† ะผะฐั” ะฑัƒั‚ะธ ั‰ะพััŒ, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ **ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ HTTPS** - ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ั‚ะพะน ัะฐะผะธะน ะบะพะผะฟะพะฝะตะฝั‚ ะฐะฑะพ ั–ะฝัˆะธะน. + +### ะŸั€ะธะบะปะฐะดะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะดะปั HTTPS { #example-tools-for-https } + +ะ”ะตัะบั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะบ TLS Termination Proxy: + +- Traefik + - ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั” ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ โœจ +- Caddy + - ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะพะฑั€ะพะฑะปัั” ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ โœจ +- Nginx + - ะ— ะทะพะฒะฝั–ัˆะฝั–ะผ ะบะพะผะฟะพะฝะตะฝั‚ะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚ Certbot ะดะปั ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ +- HAProxy + - ะ— ะทะพะฒะฝั–ัˆะฝั–ะผ ะบะพะผะฟะพะฝะตะฝั‚ะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚ Certbot ะดะปั ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ +- Kubernetes ะท Ingress Controller, ะฝะฐะฟั€ะธะบะปะฐะด Nginx + - ะ— ะทะพะฒะฝั–ัˆะฝั–ะผ ะบะพะผะฟะพะฝะตะฝั‚ะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚ cert-manager ะดะปั ะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ +- ะžะฑั€ะพะฑะปัั”ั‚ัŒัั ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ั…ะผะฐั€ะฝะธะผ ะฟั€ะพะฒะฐะนะดะตั€ะพะผ ัะบ ั‡ะฐัั‚ะธะฝะฐ ั—ั…ะฝั–ั… ัะตั€ะฒั–ัั–ะฒ (ะดะธะฒ. ะฝะธะถั‡ะต ๐Ÿ‘‡) + +ะฉะต ะพะดะธะฝ ะฒะฐั€ั–ะฐะฝั‚ - ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ **ั…ะผะฐั€ะฝะธะน ัะตั€ะฒั–ั**, ัะบะธะน ะทั€ะพะฑะธั‚ัŒ ะฑั–ะปัŒัˆะต ั€ะพะฑะพั‚ะธ, ะทะพะบั€ะตะผะฐ ะฝะฐะปะฐัˆั‚ัƒั” HTTPS. ะœะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะพะฑะผะตะถะตะฝะฝั ะฐะฑะพ ะดะพะดะฐั‚ะบะพะฒะฐ ะฒะฐั€ั‚ั–ัั‚ัŒ ั‚ะพั‰ะพ. ะะปะต ัƒ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ัะฐะผะพัั‚ั–ะนะฝะพ ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธ TLS Termination Proxy. + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ะฟะพะบะฐะถัƒ ะบั–ะปัŒะบะฐ ะบะพะฝะบั€ะตั‚ะฝะธั… ะฟั€ะธะบะปะฐะดั–ะฒ. + +--- + +ะ”ะฐะปั– ะฒัั– ะฝะฐัั‚ัƒะฟะฝั– ะบะพะฝั†ะตะฟั†ั–ั— ัั‚ะพััƒัŽั‚ัŒัั ะฟั€ะพะณั€ะฐะผะธ, ัะบะฐ ะทะฐะฟัƒัะบะฐั” ะฒะฐัˆ ั„ะฐะบั‚ะธั‡ะฝะธะน API (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn). + +## ะŸั€ะพะณั€ะฐะผะฐ ั– ะฟั€ะพั†ะตั { #program-and-process } + +ะœะธ ะฑะฐะณะฐั‚ะพ ะณะพะฒะพั€ะธั‚ะธะผะตะผะพ ะฟั€ะพ ะทะฐะฟัƒั‰ะตะฝะธะน ยซะฟั€ะพั†ะตัยป, ั‚ะพะถ ะบะพั€ะธัะฝะพ ั‡ั–ั‚ะบะพ ั€ะพะทัƒะผั–ั‚ะธ, ั‰ะพ ั†ะต ะพะทะฝะฐั‡ะฐั”, ั– ั‡ะธะผ ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด ัะปะพะฒะฐ ยซะฟั€ะพะณั€ะฐะผะฐยป. + +### ะฉะพ ั‚ะฐะบะต ะฟั€ะพะณั€ะฐะผะฐ { #what-is-a-program } + +ะกะปะพะฒะพ **ะฟั€ะพะณั€ะฐะผะฐ** ะทะฐะทะฒะธั‡ะฐะน ะฒะถะธะฒะฐัŽั‚ัŒ ะดะปั ะพะฟะธััƒ ะฑะฐะณะฐั‚ัŒะพั… ั€ะตั‡ะตะน: + +- **ะšะพะด**, ัะบะธะน ะฒะธ ะฟะธัˆะตั‚ะต, **ั„ะฐะนะปะธ Python**. +- **ะคะฐะนะป**, ัะบะธะน ะผะพะถะต ะฑัƒั‚ะธ **ะฒะธะบะพะฝะฐะฝะธะน** ะพะฟะตั€ะฐั†ั–ะนะฝะพัŽ ัะธัั‚ะตะผะพัŽ, ะฝะฐะฟั€ะธะบะปะฐะด: `python`, `python.exe` ะฐะฑะพ `uvicorn`. +- ะšะพะฝะบั€ะตั‚ะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ ะฟั–ะด ั‡ะฐั **ะฒะธะบะพะฝะฐะฝะฝั** ะฒ ะพะฟะตั€ะฐั†ั–ะนะฝั–ะน ัะธัั‚ะตะผั–, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” CPU ั‚ะฐ ะทะฑะตั€ั–ะณะฐั” ะดะฐะฝั– ะฒ ะฟะฐะผ'ัั‚ั–. ะฆะต ั‚ะฐะบะพะถ ะฝะฐะทะธะฒะฐัŽั‚ัŒ **ะฟั€ะพั†ะตัะพะผ**. + +### ะฉะพ ั‚ะฐะบะต ะฟั€ะพั†ะตั { #what-is-a-process } + +ะกะปะพะฒะพ **ะฟั€ะพั†ะตั** ะทะฐะทะฒะธั‡ะฐะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ัƒ ะฑั–ะปัŒัˆ ัะฟะตั†ะธั„ั–ั‡ะฝะพะผัƒ ะทะฝะฐั‡ะตะฝะฝั–, ะผะฐัŽั‡ะธ ะฝะฐ ัƒะฒะฐะทั– ัะฐะผะต ั‚ะต, ั‰ะพ ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฒ ะพะฟะตั€ะฐั†ั–ะนะฝั–ะน ัะธัั‚ะตะผั– (ัะบ ัƒ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ะฟัƒะฝะบั‚ั–): + +- ะšะพะฝะบั€ะตั‚ะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ ะฟั–ะด ั‡ะฐั **ะฒะธะบะพะฝะฐะฝะฝั** ะฒ ะพะฟะตั€ะฐั†ั–ะนะฝั–ะน ัะธัั‚ะตะผั–. + - ะฆะต ะฝะต ะฟั€ะพ ั„ะฐะนะป ั– ะฝะต ะฟั€ะพ ะบะพะด, ั†ะต **ะบะพะฝะบั€ะตั‚ะฝะพ** ะฟั€ะพ ั‚ะต, ั‰ะพ **ะฒะธะบะพะฝัƒั”ั‚ัŒัั** ั‚ะฐ ะบะตั€ัƒั”ั‚ัŒัั ะพะฟะตั€ะฐั†ั–ะนะฝะพัŽ ัะธัั‚ะตะผะพัŽ. +- ะ‘ัƒะดัŒ-ัะบะฐ ะฟั€ะพะณั€ะฐะผะฐ, ะฑัƒะดัŒ-ัะบะธะน ะบะพะด **ะผะพะถะต ั‰ะพััŒ ั€ะพะฑะธั‚ะธ** ะปะธัˆะต ะฟั–ะด ั‡ะฐั **ะฒะธะบะพะฝะฐะฝะฝั**. ะขะพะฑั‚ะพ ะบะพะปะธ **ะฟั€ะพั†ะตั ะทะฐะฟัƒั‰ะตะฝะธะน**. +- ะŸั€ะพั†ะตั ะผะพะถะต ะฑัƒั‚ะธ **ะทะฐะฒะตั€ัˆะตะฝะธะน** (ะฐะฑะพ ยซkillยป) ะฒะฐะผะธ ั‡ะธ ะพะฟะตั€ะฐั†ั–ะนะฝะพัŽ ัะธัั‚ะตะผะพัŽ. ะฃ ั†ะตะน ะผะพะผะตะฝั‚ ะฒั–ะฝ ะฟั€ะธะฟะธะฝัั” ะฒะธะบะพะฝะฐะฝะฝั ั– **ะฑั–ะปัŒัˆะต ะฝั–ั‡ะพะณะพ ะฝะต ะผะพะถะต ั€ะพะฑะธั‚ะธ**. +- ะšะพะถะตะฝ ะทะฐัั‚ะพััƒะฝะพะบ, ัะบะธะน ะฟั€ะฐั†ัŽั” ะฝะฐ ะฒะฐัˆะพะผัƒ ะบะพะผะฟ'ัŽั‚ะตั€ั–, ะผะฐั” ะฟะตะฒะฝะธะน ะฟั€ะพั†ะตั ะทะฐ ัะพะฑะพัŽ: ะบะพะถะฝะฐ ะทะฐะฟัƒั‰ะตะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ, ะบะพะถะฝะต ะฒั–ะบะฝะพ ั‚ะพั‰ะพ. ะ—ะฐะทะฒะธั‡ะฐะน ะฝะฐ ะบะพะผะฟ'ัŽั‚ะตั€ั– ะพะดะฝะพั‡ะฐัะฝะพ ะฟั€ะฐั†ัŽั” **ะฑะฐะณะฐั‚ะพ ะฟั€ะพั†ะตัั–ะฒ**. +- **ะšั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ** **ะพะดะฝั–ั”ั— ะน ั‚ั–ั”ั— ัะฐะผะพั— ะฟั€ะพะณั€ะฐะผะธ** ะผะพะถัƒั‚ัŒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะพะดะฝะพั‡ะฐัะฝะพ. + +ะฏะบั‰ะพ ะฒะธ ะฒั–ะดะบั€ะธั”ั‚ะต ยซะดะธัะฟะตั‚ั‡ะตั€ ะทะฐะฒะดะฐะฝัŒยป ะฐะฑะพ ยซัะธัั‚ะตะผะฝะธะน ะผะพะฝั–ั‚ะพั€ยป (ั‡ะธ ะฟะพะดั–ะฑะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ) ะฒ ะพะฟะตั€ะฐั†ั–ะนะฝั–ะน ัะธัั‚ะตะผั–, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฑะฐะณะฐั‚ะพ ั‚ะฐะบะธั… ะฟั€ะพั†ะตัั–ะฒ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฟะพะฑะฐั‡ะธั‚ะต ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ ั‚ะพะณะพ ัะฐะผะพะณะพ ะฑั€ะฐัƒะทะตั€ะฐ (Firefox, Chrome, Edge ั‚ะพั‰ะพ). ะ—ะฐะทะฒะธั‡ะฐะน ะฒั–ะฝ ะทะฐะฟัƒัะบะฐั” ะพะดะธะฝ ะฟั€ะพั†ะตั ะฝะฐ ะฒะบะปะฐะดะบัƒ ะฟะปัŽั ะดะตัะบั– ะดะพะดะฐั‚ะบะพะฒั– ะฟั€ะพั†ะตัะธ. + + + +--- + +ะขะตะฟะตั€, ะบะพะปะธ ะผะธ ะทะฝะฐั”ะผะพ ั€ั–ะทะฝะธั†ัŽ ะผั–ะถ ั‚ะตั€ะผั–ะฝะฐะผะธ **ะฟั€ะพั†ะตั** ั– **ะฟั€ะพะณั€ะฐะผะฐ**, ะฟั€ะพะดะพะฒะถะธะผะพ ะณะพะฒะพั€ะธั‚ะธ ะฟั€ะพ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. + +## ะ—ะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ { #running-on-startup } + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ, ะบะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะฒะตะฑ-API, ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฒั–ะฝ **ะฟั€ะฐั†ัŽะฒะฐะฒ ะฟะพัั‚ั–ะนะฝะพ**, ะฑะตะท ะฟะตั€ะตั€ะฒ, ั‰ะพะฑ ะบะปั–ั”ะฝั‚ะธ ะทะฐะฒะถะดะธ ะผะฐะปะธ ะดะพ ะฝัŒะพะณะพ ะดะพัั‚ัƒะฟ. ะ—ะฒั–ัะฝะพ, ัะบั‰ะพ ะฝะตะผะฐั” ะพัะพะฑะปะธะฒะธั… ะฟั€ะธั‡ะธะฝ ะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ะปะธัˆะต ะฒ ะฟะตะฒะฝะธั… ัะธั‚ัƒะฐั†ั–ัั…. ะะปะต ะทะฐะทะฒะธั‡ะฐะน ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฒั–ะฝ ะฟะพัั‚ั–ะนะฝะพ ะฟั€ะฐั†ัŽะฒะฐะฒ ั– ะฑัƒะฒ **ะดะพัั‚ัƒะฟะฝะธะน**. + +### ะะฐ ะฒั–ะดะดะฐะปะตะฝะพะผัƒ ัะตั€ะฒะตั€ั– { #in-a-remote-server } + +ะšะพะปะธ ะฒะธ ะฝะฐะปะฐัˆั‚ะพะฒัƒั”ั‚ะต ะฒั–ะดะดะฐะปะตะฝะธะน ัะตั€ะฒะตั€ (ั…ะผะฐั€ะฝะธะน ัะตั€ะฒะตั€, ะฒั–ั€ั‚ัƒะฐะปัŒะฝัƒ ะผะฐัˆะธะฝัƒ ั‚ะพั‰ะพ), ะฝะฐะนะฟั€ะพัั‚ั–ัˆะต - ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `fastapi run` (ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn) ะฐะฑะพ ั‰ะพััŒ ัั…ะพะถะต, ะฒั€ัƒั‡ะฝัƒ, ั‚ะฐะบ ัะฐะผะพ, ัะบ ะฟั–ะด ั‡ะฐั ะปะพะบะฐะปัŒะฝะพั— ั€ะพะทั€ะพะฑะบะธ. + +ะ† ั†ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ั‚ะฐ ะฑัƒะดะต ะบะพั€ะธัะฝะธะผ **ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ**. + +ะะปะต ัะบั‰ะพ ะฒะธ ะฒั‚ั€ะฐั‚ะธั‚ะต ะท'ั”ะดะฝะฐะฝะฝั ะท ัะตั€ะฒะตั€ะพะผ, **ะทะฐะฟัƒั‰ะตะฝะธะน ะฟั€ะพั†ะตั**, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะทะฐะฒะตั€ัˆะธั‚ัŒัั. + +ะ† ัะบั‰ะพ ัะตั€ะฒะตั€ ะฑัƒะดะต ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถะตะฝะพ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั–ัะปั ะพะฝะพะฒะปะตะฝัŒ ะฐะฑะพ ะผั–ะณั€ะฐั†ั–ะน ัƒ ั…ะผะฐั€ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ), ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, **ะฝะต ะฟะพะผั–ั‚ะธั‚ะต ั†ัŒะพะณะพ**. ะ† ั‡ะตั€ะตะท ั†ะต ะฒะธ ะฝะฐะฒั–ั‚ัŒ ะฝะต ะทะฝะฐั‚ะธะผะตั‚ะต, ั‰ะพ ั‚ั€ะตะฑะฐ ะฒั€ัƒั‡ะฝัƒ ะฟะตั€ะตะทะฐะฟัƒัั‚ะธั‚ะธ ะฟั€ะพั†ะตั. ะฃ ั€ะตะทัƒะปัŒั‚ะฐั‚ั– ะฒะฐัˆ API ะฟั€ะพัั‚ะพ ะทะฐะปะธัˆะธั‚ัŒัั ยซะผะตั€ั‚ะฒะธะผยป. ๐Ÿ˜ฑ + +### ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะธะน ะทะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ { #run-automatically-on-startup } + +ะ—ะฐะณะฐะปะพะผ ะฒะธ, ะฝะฐะฟะตะฒะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ัะตั€ะฒะตั€ะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn) ะทะฐะฟัƒัะบะฐะปะฐัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ ัะตั€ะฒะตั€ะฐ ั– ะฑะตะท ะฑัƒะดัŒ-ัะบะพะณะพ **ะปัŽะดััŒะบะพะณะพ ะฒั‚ั€ัƒั‡ะฐะฝะฝั**, ั‰ะพะฑ ะทะฐะฒะถะดะธ ะฑัƒะฒ ะทะฐะฟัƒั‰ะตะฝะธะน ะฟั€ะพั†ะตั ั–ะท ะฒะฐัˆะธะผ API (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn ั–ะท ะฒะฐัˆะธะผ FastAPI-ะทะฐัั‚ะพััƒะฝะบะพะผ). + +### ะžะบั€ะตะผะฐ ะฟั€ะพะณั€ะฐะผะฐ { #separate-program } + +ะฉะพะฑ ั†ัŒะพะณะพ ะดะพััะณั‚ะธ, ะทะฐะทะฒะธั‡ะฐะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ **ะพะบั€ะตะผัƒ ะฟั€ะพะณั€ะฐะผัƒ**, ัะบะฐ ะณะฐั€ะฐะฝั‚ัƒั” ะทะฐะฟัƒัะบ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ. ะ† ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะพะฝะฐ ั‚ะฐะบะพะถ ะทะฐะฑะตะทะฟะตั‡ัƒั” ะทะฐะฟัƒัะบ ั–ะฝัˆะธั… ะบะพะผะฟะพะฝะตะฝั‚ั–ะฒ ะฐะฑะพ ะทะฐัั‚ะพััƒะฝะบั–ะฒ, ะฝะฐะฟั€ะธะบะปะฐะด ะฑะฐะทะธ ะดะฐะฝะธั…. + +### ะŸั€ะธะบะปะฐะดะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะดะปั ะทะฐะฟัƒัะบัƒ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ { #example-tools-to-run-at-startup } + +ะŸั€ะธะบะปะฐะดะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ัะบั– ะผะพะถัƒั‚ัŒ ั†ะต ั€ะพะฑะธั‚ะธ: + +- Docker +- Kubernetes +- Docker Compose +- Docker ัƒ ั€ะตะถะธะผั– Swarm +- Systemd +- Supervisor +- ะžะฑั€ะพะฑะปัั”ั‚ัŒัั ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ั…ะผะฐั€ะฝะธะผ ะฟั€ะพะฒะฐะนะดะตั€ะพะผ ัะบ ั‡ะฐัั‚ะธะฝะฐ ั—ั…ะฝั–ั… ัะตั€ะฒั–ัั–ะฒ +- ะ†ะฝัˆั–... + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ะฝะฐะฒะตะดัƒ ะฑั–ะปัŒัˆ ะบะพะฝะบั€ะตั‚ะฝั– ะฟั€ะธะบะปะฐะดะธ. + +## ะŸะตั€ะตะทะฐะฟัƒัะบะธ { #restarts } + +ะŸะพะดั–ะฑะฝะพ ะดะพ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั ะทะฐะฟัƒัะบัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ ัะธัั‚ะตะผะธ, ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ั‚ะฐะบะพะถ ะทะฐั…ะพั‡ะตั‚ะต ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ **ะฟะตั€ะตะทะฐะฟัƒัะบ** ะฟั–ัะปั ะทะฑะพั—ะฒ. + +### ะœะธ ะฟะพะผะธะปัั”ะผะพัั { #we-make-mistakes } + +ะœะธ, ะปัŽะดะธ, ะฟะพัั‚ั–ะนะฝะพ ั€ะพะฑะธะผะพ **ะฟะพะผะธะปะบะธ**. ะœะฐะนะถะต ะทะฐะฒะถะดะธ ัƒ ะฟั€ะพะณั€ะฐะผะฝะพะผัƒ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั– ั” ะฟั€ะธั…ะพะฒะฐะฝั– **ะฟะพะผะธะปะบะธ**. ๐Ÿ› + +ะ† ะผะธ ัะบ ั€ะพะทั€ะพะฑะฝะธะบะธ ะฟะพัั‚ั–ะนะฝะพ ะฟะพะบั€ะฐั‰ัƒั”ะผะพ ะบะพะด, ะทะฝะฐั…ะพะดัั‡ะธ ั†ั– ะฟะพะผะธะปะบะธ ั‚ะฐ ะดะพะดะฐัŽั‡ะธ ะฝะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– (ะผะพะถะปะธะฒะพ, ั‚ะตะถ ะดะพะดะฐัŽั‡ะธ ะฝะพะฒั– ะฟะพะผะธะปะบะธ ๐Ÿ˜…). + +### ะะตะฒะตะปะธะบั– ะฟะพะผะธะปะบะธ ะพะฑั€ะพะฑะปััŽั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ { #small-errors-automatically-handled } + +ะกั‚ะฒะพั€ัŽัŽั‡ะธ ะฒะตะฑ-API ะท FastAPI, ัะบั‰ะพ ะฒ ะฝะฐัˆะพะผัƒ ะบะพะดั– ั” ะฟะพะผะธะปะบะฐ, FastAPI ะทะฐะทะฒะธั‡ะฐะน ะพะฑะผะตะถัƒั” ั—ั— ะพะดะฝะธะผ ะทะฐะฟะธั‚ะพะผ, ัะบะธะน ั†ัŽ ะฟะพะผะธะปะบัƒ ัะฟั€ะพะฒะพะบัƒะฒะฐะฒ. ๐Ÿ›ก + +ะšะปั–ั”ะฝั‚ ะพั‚ั€ะธะผะฐั” **500 Internal Server Error** ะดะปั ั†ัŒะพะณะพ ะทะฐะฟะธั‚ัƒ, ะฐะปะต ะทะฐัั‚ะพััƒะฝะพะบ ะฟั€ะพะดะพะฒะถะธั‚ัŒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะดะปั ะฝะฐัั‚ัƒะฟะฝะธั… ะทะฐะฟะธั‚ั–ะฒ ะทะฐะผั–ัั‚ัŒ ะฟะพะฒะฝะพะณะพ ะบั€ะฐั…ัƒ. + +### ะ’ะตะปะธะบั– ะฟะพะผะธะปะบะธ - ะบั€ะฐั…ะธ { #bigger-errors-crashes } + +ะ’ั‚ั–ะผ, ะฑัƒะฒะฐัŽั‚ัŒ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะผะธ ะฟะธัˆะตะผะพ ะบะพะด, ัะบะธะน **ะฟะฐะดะฐั” ะฒะตััŒ ะทะฐัั‚ะพััƒะฝะพะบ**, ัะฟั€ะธั‡ะธะฝััŽั‡ะธ ะบั€ะฐั… Uvicorn ั– Python. ๐Ÿ’ฅ + +ะ† ะฒัะต ะถ ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะทะฐั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะทะฐัั‚ะพััƒะฝะพะบ ะทะฐะปะธัˆะฐะฒัั ยซะผะตั€ั‚ะฒะธะผยป ั‡ะตั€ะตะท ะฟะพะผะธะปะบัƒ ะฒ ะพะดะฝะพะผัƒ ะผั–ัั†ั– - ะฒะธ, ะฝะฐะฟะตะฒะฝะพ, ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ ะฒั–ะฝ **ะฟั€ะพะดะพะฒะถัƒะฒะฐะฒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ** ะฟั€ะธะฝะฐะนะผะฝั– ะดะปั ั‚ะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*, ั‰ะพ ะฝะต ะทะปะฐะผะฐะฝั–. + +### ะŸะตั€ะตะทะฐะฟัƒัะบ ะฟั–ัะปั ะบั€ะฐั…ัƒ { #restart-after-crash } + +ะะปะต ะฒ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ั–ะท ัะตั€ะนะพะทะฝะธะผะธ ะฟะพะผะธะปะบะฐะผะธ, ั‰ะพ ะฟั€ะธะทะฒะพะดัั‚ัŒ ะดะพ ะบั€ะฐั…ัƒ ะทะฐะฟัƒั‰ะตะฝะพะณะพ **ะฟั€ะพั†ะตััƒ**, ะฟะพั‚ั€ั–ะฑะตะฝ ะทะพะฒะฝั–ัˆะฝั–ะน ะบะพะผะฟะพะฝะตะฝั‚, ะฒั–ะดะฟะพะฒั–ะดะฐะปัŒะฝะธะน ะทะฐ **ะฟะตั€ะตะทะฐะฟัƒัะบ** ะฟั€ะพั†ะตััƒ, ะฟั€ะธะฝะฐะนะผะฝั– ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ... + +/// tip | ะŸะพั€ะฐะดะฐ + +...ะฅะพั‡ะฐ ัะบั‰ะพ ะฒะตััŒ ะทะฐัั‚ะพััƒะฝะพะบ ะฟั€ะพัั‚ะพ **ะผะธั‚ั‚ั”ะฒะพ ะฟะฐะดะฐั”**, ะฑะตะทะณะปัƒะทะดะพ ะฟะตั€ะตะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ะฑะตะทะบั–ะฝะตั‡ะฝะพ. ะะปะต ะฒ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฟะพะผั–ั‚ะธั‚ะต ั†ะต ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ ะฐะฑะพ ะฟั€ะธะฝะฐะนะผะฝั– ะฒั–ะดั€ะฐะทัƒ ะฟั–ัะปั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. + +ะขะพะถ ะทะพัะตั€ะตะดัŒะผะพัั ะฝะฐ ะพัะฝะพะฒะฝะธั… ะฒะธะฟะฐะดะบะฐั…, ะบะพะปะธ ัƒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ ะฒั–ะฝ ะผะพะถะต ะฟะพะฒะฝั–ัั‚ัŽ ะฟะฐะดะฐั‚ะธ ะทะฐ ะฟะตะฒะฝะธั… ะพะฑัั‚ะฐะฒะธะฝ, ั– ั‚ะพะดั– ะฒัะต ั‰ะต ะผะฐั” ัะตะฝั ะนะพะณะพ ะฟะตั€ะตะทะฐะฟัƒัะบะฐั‚ะธ. + +/// + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะฒั–ะดะพะบั€ะตะผะปะตะฝะธะน **ะทะพะฒะฝั–ัˆะฝั–ะน ะบะพะผะฟะพะฝะตะฝั‚**, ัะบะธะน ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ ะฟะตั€ะตะทะฐะฟัƒัะบ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฐะดะถะต ะดะพ ั‚ะพะณะพ ะผะพะผะตะฝั‚ัƒ ัะฐะผ ะทะฐัั‚ะพััƒะฝะพะบ ะท Uvicorn ั– Python ัƒะถะต ะฒะฟะฐะฒ, ั– ะฝั–ั‡ะพะณะพ ะฒ ั‚ะพะผัƒ ะถ ะบะพะดั– ั†ั–ั”ั— ะถ ะฟั€ะพะณั€ะฐะผะธ ะทั€ะพะฑะธั‚ะธ ะฝะต ะทะผะพะถะต. + +### ะŸั€ะธะบะปะฐะดะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะณะพ ะฟะตั€ะตะทะฐะฟัƒัะบัƒ { #example-tools-to-restart-automatically } + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ั‚ะพะน ัะฐะผะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั **ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผะธ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ**, ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธั… **ะฟะตั€ะตะทะฐะฟัƒัะบั–ะฒ**. + +ะะฐะฟั€ะธะบะปะฐะด, ั†ะต ะผะพะถัƒั‚ัŒ ะทะฐะฑะตะทะฟะตั‡ัƒะฒะฐั‚ะธ: + +- Docker +- Kubernetes +- Docker Compose +- Docker ัƒ ั€ะตะถะธะผั– Swarm +- Systemd +- Supervisor +- ะžะฑั€ะพะฑะปัั”ั‚ัŒัั ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ั…ะผะฐั€ะฝะธะผ ะฟั€ะพะฒะฐะนะดะตั€ะพะผ ัะบ ั‡ะฐัั‚ะธะฝะฐ ั—ั…ะฝั–ั… ัะตั€ะฒั–ัั–ะฒ +- ะ†ะฝัˆั–... + +## ะ ะตะฟะปั–ะบะฐั†ั–ั - ะฟั€ะพั†ะตัะธ ั‚ะฐ ะฟะฐะผ'ัั‚ัŒ { #replication-processes-and-memory } + +ะฃ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ, ัะบ-ะพั‚ ะบะพะผะฐะฝะดัƒ `fastapi`, ั‰ะพ ะทะฐะฟัƒัะบะฐั” Uvicorn, ะพะดะธะฝ ะทะฐะฟัƒัะบ ะฒ **ะพะดะฝะพะผัƒ ะฟั€ะพั†ะตัั–** ะผะพะถะต ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะบั–ะปัŒะบะพั… ะบะปั–ั”ะฝั‚ั–ะฒ ั€ั–ะฒะฝะพั‡ะฐัะฝะพ. + +ะะปะต ั‡ะฐัั‚ะพ ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะทะฐะฟัƒัะบะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ะพะดะฝะพั‡ะฐัะฝะพ. + +### ะšั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ - ะฟั€ะฐั†ั–ะฒะฝะธะบะธ { #multiple-processes-workers } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ะฑั–ะปัŒัˆะต ะบะปั–ั”ะฝั‚ั–ะฒ, ะฝั–ะถ ะผะพะถะต ะพะฑั€ะพะฑะธั‚ะธ ะพะดะธะฝ ะฟั€ะพั†ะตั (ะฝะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ ะฝะต ะฝะฐะดั‚ะพ ะฟะพั‚ัƒะถะฝะฐ) ั– ะฝะฐ ัะตั€ะฒะตั€ั– ั” **ะบั–ะปัŒะบะฐ ัะดะตั€** CPU, ั‚ะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ **ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ** ั–ะท ั‚ะธะผ ัะฐะผะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ ะฟะฐั€ะฐะปะตะปัŒะฝะพ ั– ั€ะพะทะฟะพะดั–ะปัั‚ะธ ะทะฐะฟะธั‚ะธ ะผั–ะถ ะฝะธะผะธ. + +ะšะพะปะธ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต **ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ** ั‚ะพะณะพ ัะฐะผะพะณะพ ะฟั€ะพะณั€ะฐะผะฝะพะณะพ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั API, ั—ั… ะทะฐะทะฒะธั‡ะฐะน ะฝะฐะทะธะฒะฐัŽั‚ัŒ **ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ** (workers). + +### ะŸั€ะพั†ะตัะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะธ ั– ะฟะพั€ั‚ะธ { #worker-processes-and-ports } + +ะŸะฐะผ'ัั‚ะฐั”ั‚ะต ะท ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— [ะŸั€ะพ HTTPS](https.md){.internal-link target=_blank}, ั‰ะพ ะฝะฐ ัะตั€ะฒะตั€ั– ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะผะพะถะต ัะปัƒั…ะฐั‚ะธ ะฟะตะฒะฝัƒ ะบะพะผะฑั–ะฝะฐั†ั–ัŽ ะฟะพั€ั‚ัƒ ั‚ะฐ IP-ะฐะดั€ะตัะธ? + +ะฆะต ะดะพัั– ั‚ะฐะบ. + +ะžั‚ะถะต, ั‰ะพะฑ ะผะฐั‚ะธ **ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ** ะพะดะฝะพั‡ะฐัะฝะพ, ะผะฐั” ะฑัƒั‚ะธ **ั”ะดะธะฝะธะน ะฟั€ะพั†ะตั, ัะบะธะน ัะปัƒั…ะฐั” ะฟะพั€ั‚**, ั– ัะบะธะน ะดะฐะปั– ัะบะธะผะพััŒ ั‡ะธะฝะพะผ ะฟะตั€ะตะดะฐั” ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ะบะพะถะฝะพะผัƒ ะฟั€ะพั†ะตััƒ-ะฟั€ะฐั†ั–ะฒะฝะธะบัƒ. + +### ะŸะฐะผ'ัั‚ัŒ ะฝะฐ ะฟั€ะพั†ะตั { #memory-per-process } + +ะšะพะปะธ ะฟั€ะพะณั€ะฐะผะฐ ะทะฐะฒะฐะฝั‚ะฐะถัƒั” ั‰ะพััŒ ัƒ ะฟะฐะผ'ัั‚ัŒ, ะฝะฐะฟั€ะธะบะปะฐะด ะผะพะดะตะปัŒ ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั ะฒ ะทะผั–ะฝะฝัƒ ะฐะฑะพ ะฒะผั–ัั‚ ะฒะตะปะธะบะพะณะพ ั„ะฐะนะปัƒ ะฒ ะทะผั–ะฝะฝัƒ, ะฒัะต ั†ะต **ัะฟะพะถะธะฒะฐั” ั‡ะฐัั‚ะธะฝัƒ ะฟะฐะผ'ัั‚ั– (RAM)** ัะตั€ะฒะตั€ะฐ. + +ะ† ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ ะทะฐะทะฒะธั‡ะฐะน **ะฝะต ะดั–ะปัั‚ัŒัั ะฟะฐะผ'ัั‚ั‚ัŽ**. ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะบะพะถะตะฝ ะทะฐะฟัƒั‰ะตะฝะธะน ะฟั€ะพั†ะตั ะผะฐั” ะฒะปะฐัะฝั– ั€ะตั‡ั–, ะทะผั–ะฝะฝั– ั‚ะฐ ะฟะฐะผ'ัั‚ัŒ. ะ† ัะบั‰ะพ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั– ัะฟะพะถะธะฒะฐั”ั‚ัŒัั ะฑะฐะณะฐั‚ะพ ะฟะฐะผ'ัั‚ั–, **ะบะพะถะตะฝ ะฟั€ะพั†ะตั** ัะฟะพะถะธะฒะฐั‚ะธะผะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะธะน ะพะฑััะณ ะฟะฐะผ'ัั‚ั–. + +### ะŸะฐะผ'ัั‚ัŒ ัะตั€ะฒะตั€ะฐ { #server-memory } + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒะฐัˆ ะบะพะด ะทะฐะฒะฐะฝั‚ะฐะถัƒั” ะผะพะดะตะปัŒ ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั ั€ะพะทะผั–ั€ะพะผ **1 GB**, ั‚ะพ ะฟั€ะธ ะทะฐะฟัƒัะบัƒ ะพะดะฝะพะณะพ ะฟั€ะพั†ะตััƒ ะท ะฒะฐัˆะธะผ API ะฒั–ะฝ ัะฟะพะถะธะฒะฐั‚ะธะผะต ั‰ะพะฝะฐะนะผะตะฝัˆะต 1 GB RAM. ะ ัะบั‰ะพ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต **4 ะฟั€ะพั†ะตัะธ** (4 ะฟั€ะฐั†ั–ะฒะฝะธะบะธ) - ะบะพะถะตะฝ ัะฟะพะถะธะฒะฐั‚ะธะผะต 1 GB RAM. ะžั‚ะถะต, ะทะฐะณะฐะปะพะผ ะฒะฐัˆ API ัะฟะพะถะธะฒะฐั‚ะธะผะต **4 GB RAM**. + +ะ† ัะบั‰ะพ ะฒะฐัˆ ะฒั–ะดะดะฐะปะตะฝะธะน ัะตั€ะฒะตั€ ะฐะฑะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ ะผะฐั” ะปะธัˆะต 3 GB RAM, ัะฟั€ะพะฑะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟะพะฝะฐะด 4 GB ะฟั€ะธะทะฒะตะดะต ะดะพ ะฟั€ะพะฑะปะตะผ. ๐Ÿšจ + +### ะšั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ - ะฟั€ะธะบะปะฐะด { #multiple-processes-an-example } + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ั” **ะบะตั€ั–ะฒะฝะธะน ะฟั€ะพั†ะตั** (Manager Process), ัะบะธะน ะทะฐะฟัƒัะบะฐั” ั– ะบะพะฝั‚ั€ะพะปัŽั” ะดะฒะฐ **ะฟั€ะพั†ะตัะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะธ**. + +ะฆะตะน ะบะตั€ั–ะฒะฝะธะน ะฟั€ะพั†ะตั, ั–ะผะพะฒั–ั€ะฝะพ, ัะฐะผะต ั– ัะปัƒั…ะฐั‚ะธะผะต **ะฟะพั€ั‚** ะฝะฐ IP. ะ† ะฒั–ะฝ ะฟะตั€ะตะดะฐะฒะฐั‚ะธะผะต ะฒััŽ ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ะฟั€ะพั†ะตัะฐะผ-ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผ. + +ะฆั– ะฟั€ะพั†ะตัะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะธ ะฒะธะบะพะฝัƒะฒะฐั‚ะธะผัƒั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ, ะทะดั–ะนัะฝัŽะฒะฐั‚ะธะผัƒั‚ัŒ ะพัะฝะพะฒะฝั– ะพะฑั‡ะธัะปะตะฝะฝั, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ **ะทะฐะฟะธั‚** ั– ะฟะพะฒะตั€ะฝัƒั‚ะธ **ะฒั–ะดะฟะพะฒั–ะดัŒ**, ั– ะทะฐะฒะฐะฝั‚ะฐะถัƒะฒะฐั‚ะธะผัƒั‚ัŒ ัƒัะต, ั‰ะพ ะฒะธ ะทะฑะตั€ั–ะณะฐั”ั‚ะต ะฒ ะทะผั–ะฝะฝะธั… ัƒ RAM. + + + +ะ—ะฒั–ัะฝะพ, ะฝะฐ ั‚ั–ะน ัะฐะผั–ะน ะผะฐัˆะธะฝั–, ะพะบั€ั–ะผ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะทะฐะทะฒะธั‡ะฐะน ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผัƒั‚ัŒ **ั–ะฝัˆั– ะฟั€ะพั†ะตัะธ**. + +ะฆั–ะบะฐะฒะธะน ะผะพะผะตะฝั‚: ะฒั–ะดัะพั‚ะพะบ **ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั CPU** ะบะพะถะฝะธะผ ะฟั€ะพั†ะตัะพะผ ะผะพะถะต ัะธะปัŒะฝะพ **ะฒะฐั€ั–ัŽะฒะฐั‚ะธัั** ะท ั‡ะฐัะพะผ, ั‚ะพะดั– ัะบ **ะฟะฐะผ'ัั‚ัŒ (RAM)** ะทะฐะทะฒะธั‡ะฐะน ะทะฐะปะธัˆะฐั”ั‚ัŒัั ะฑั–ะปัŒัˆ-ะผะตะฝัˆ **ัั‚ะฐะฑั–ะปัŒะฝะพัŽ**. + +ะฏะบั‰ะพ ัƒ ะฒะฐั API, ั‰ะพ ะฒะธะบะพะฝัƒั” ะฟะพั€ั–ะฒะฝัะฝะธะน ะพะฑััะณ ะพะฑั‡ะธัะปะตะฝัŒ ั‰ะพั€ะฐะทัƒ ั– ัƒ ะฒะฐั ะฑะฐะณะฐั‚ะพ ะบะปั–ั”ะฝั‚ั–ะฒ, ั‚ะพะดั– **ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั CPU** ั‚ะฐะบะพะถ, ะนะผะพะฒั–ั€ะฝะพ, ะฑัƒะดะต *ัั‚ะฐะฑั–ะปัŒะฝะธะผ* (ะทะฐะผั–ัั‚ัŒ ะฟะพัั‚ั–ะนะฝะธั… ัˆะฒะธะดะบะธั… ะบะพะปะธะฒะฐะฝัŒ). + +### ะŸั€ะธะบะปะฐะดะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั– ัั‚ั€ะฐั‚ะตะณั–ะน ั€ะตะฟะปั–ะบะฐั†ั–ั— { #examples-of-replication-tools-and-strategies } + +ะ„ ะบั–ะปัŒะบะฐ ะฟั–ะดั…ะพะดั–ะฒ ะดะปั ั†ัŒะพะณะพ, ั– ะฟั€ะพ ะบะพะฝะบั€ะตั‚ะฝั– ัั‚ั€ะฐั‚ะตะณั–ั— ั ั€ะพะทะฟะพะฒั–ะผ ัƒ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั…, ะฝะฐะฟั€ะธะบะปะฐะด, ะบะพะปะธ ะณะพะฒะพั€ะธั‚ะธะผะตะผะพ ะฟั€ะพ Docker ั– ะบะพะฝั‚ะตะนะฝะตั€ะธ. + +ะ“ะพะปะพะฒะฝะต ะพะฑะผะตะถะตะฝะฝั: ะผะฐั” ะฑัƒั‚ะธ **ั”ะดะธะฝะธะน** ะบะพะผะฟะพะฝะตะฝั‚, ั‰ะพ ะพะฑั€ะพะฑะปัั” **ะฟะพั€ั‚** ะฝะฐ **ะฟัƒะฑะปั–ั‡ะฝั–ะน IP-ะฐะดั€ะตัั–**. ะ ั‚ะพะดั– ะฒั–ะฝ ะผะฐั” ะผะฐั‚ะธ ัะฟะพัั–ะฑ **ะฟะตั€ะตะดะฐะฒะฐั‚ะธ** ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ั€ะตะฟะปั–ะบะพะฒะฐะฝะธะผ **ะฟั€ะพั†ะตัะฐะผ/ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผ**. + +ะžััŒ ะบั–ะปัŒะบะฐ ะผะพะถะปะธะฒะธั… ะบะพะผะฑั–ะฝะฐั†ั–ะน ั– ัั‚ั€ะฐั‚ะตะณั–ะน: + +- **Uvicorn** ะท `--workers` + - ะžะดะธะฝ **ะผะตะฝะตะดะถะตั€ ะฟั€ะพั†ะตัั–ะฒ** Uvicorn ัะปัƒั…ะฐั‚ะธะผะต **IP** ั– **ะฟะพั€ั‚** ั‚ะฐ ะทะฐะฟัƒัะบะฐั‚ะธะผะต **ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ Uvicorn**. +- **Kubernetes** ั‚ะฐ ั–ะฝัˆั– ั€ะพะทะฟะพะดั–ะปะตะฝั– **ัะธัั‚ะตะผะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ** + - ะฉะพััŒ ะฝะฐ ั€ั–ะฒะฝั– **Kubernetes** ัะปัƒั…ะฐั‚ะธะผะต **IP** ั– **ะฟะพั€ั‚**. ะ ะตะฟะปั–ะบะฐั†ั–ั ะฒั–ะดะฑัƒะฒะฐั‚ะธะผะตั‚ัŒัั ั‡ะตั€ะตะท **ะบั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ**, ัƒ ะบะพะถะฝะพะผัƒ ะท ัะบะธั… ะทะฐะฟัƒั‰ะตะฝะพ **ะพะดะธะฝ ะฟั€ะพั†ะตั Uvicorn**. +- **ะฅะผะฐั€ะฝั– ัะตั€ะฒั–ัะธ**, ั‰ะพ ั€ะพะฑะปัั‚ัŒ ั†ะต ะทะฐ ะฒะฐั + - ะฅะผะฐั€ะฝะธะน ัะตั€ะฒั–ั, ะนะผะพะฒั–ั€ะฝะพ, **ะทะฐะฑะตะทะฟะตั‡ะธั‚ัŒ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะทะฐ ะฒะฐั**. ะ’ั–ะฝ ะผะพะถะต ะดะพะทะฒะพะปัั‚ะธ ะฒะธะทะฝะฐั‡ะธั‚ะธ **ะฟั€ะพั†ะตั ะดะปั ะทะฐะฟัƒัะบัƒ** ะฐะฑะพ **ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ** ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั; ัƒ ะฑัƒะดัŒ-ัะบะพะผัƒ ั€ะฐะทั– ั†ะต, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะฑัƒะดะต **ะพะดะธะฝ ะฟั€ะพั†ะตั Uvicorn**, ะฐ ัะตั€ะฒั–ั ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธะผะต ะทะฐ ะนะพะณะพ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะต ั…ะฒะธะปัŽะนั‚ะตัั, ัะบั‰ะพ ะดะตัะบั– ะฟัƒะฝะบั‚ะธ ะฟั€ะพ **ะบะพะฝั‚ะตะนะฝะตั€ะธ**, Docker ั‡ะธ Kubernetes ะฟะพะบะธ ั‰ะพ ะฝะต ะดัƒะถะต ะทั€ะพะทัƒะผั–ะปั–. + +ะฏ ั€ะพะทะฟะพะฒั–ะผ ะฑั–ะปัŒัˆะต ะฟั€ะพ ะพะฑั€ะฐะทะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, Docker, Kubernetes ั‚ะพั‰ะพ ะฒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั–: [FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐั… - Docker](docker.md){.internal-link target=_blank}. + +/// + +## ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ { #previous-steps-before-starting } + +ะ„ ะฑะฐะณะฐั‚ะพ ะฒะธะฟะฐะดะบั–ะฒ, ะบะพะปะธ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝะฐั‚ะธ ะดะตัะบั– ะบั€ะพะบะธ **ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ** ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะทะฐะฟัƒัั‚ะธั‚ะธ **ะผั–ะณั€ะฐั†ั–ั— ะฑะฐะทะธ ะดะฐะฝะธั…**. + +ะะปะต ะฝะฐะนั‡ะฐัั‚ั–ัˆะต ั†ั– ะบั€ะพะบะธ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะปะธัˆะต **ะพะดะธะฝ ั€ะฐะท**. + +ะžั‚ะถะต, ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ **ั”ะดะธะฝะธะน ะฟั€ะพั†ะตั**, ัะบะธะน ะฒะธะบะพะฝะฐั” ั†ั– **ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ** ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะ† ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ั—ั… ะฒะธะบะพะฝัƒั” ัะฐะผะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฟะพั‚ั–ะผ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต **ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ** (ะบั–ะปัŒะบะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ) ะดะปั ัะฐะผะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. ะฏะบั‰ะพ ั†ั– ะบั€ะพะบะธ ะฒะธะบะพะฝัƒะฒะฐั‚ะธะผัƒั‚ัŒัั **ะบั–ะปัŒะบะพะผะฐ ะฟั€ะพั†ะตัะฐะผะธ**, ะฒะพะฝะธ **ะฟะพะดะฒะพัŽะฒะฐั‚ะธะผัƒั‚ัŒ** ั€ะพะฑะพั‚ัƒ, ะฒะธะบะพะฝัƒัŽั‡ะธ ั—ั— **ะฟะฐั€ะฐะปะตะปัŒะฝะพ**, ั– ัะบั‰ะพ ะบั€ะพะบะธ ะดะตะปั–ะบะฐั‚ะฝั–, ัะบ-ะพั‚ ะผั–ะณั€ะฐั†ั–ั— ะฑะฐะทะธ ะดะฐะฝะธั…, ั†ะต ะผะพะถะต ะฟั€ะธะทะฒะตัั‚ะธ ะดะพ ะบะพะฝั„ะปั–ะบั‚ั–ะฒ. + +ะ—ะฒั–ัะฝะพ, ะฑัƒะฒะฐัŽั‚ัŒ ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฝะตะผะฐั” ะฟั€ะพะฑะปะตะผะธ ะทะฐะฟัƒัะบะฐั‚ะธ ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ - ั‚ะพะดั– ะฒัะต ะฝะฐะฑะฐะณะฐั‚ะพ ะฟั€ะพัั‚ั–ัˆะต. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขะฐะบะพะถ ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะพะณะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั–ะฝะบะพะปะธ **ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฒะทะฐะณะฐะปั– ะฝะต ะฟะพั‚ั€ั–ะฑะฝั–** ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฝะต ั‚ัƒั€ะฑัƒะฒะฐั‚ะธัั. ๐Ÿคท + +/// + +### ะŸั€ะธะบะปะฐะดะธ ัั‚ั€ะฐั‚ะตะณั–ะน ะฟะพะฟะตั€ะตะดะฝั–ั… ะบั€ะพะบั–ะฒ { #examples-of-previous-steps-strategies } + +ะฆะต **ะทะฝะฐั‡ะฝะพัŽ ะผั–ั€ะพัŽ ะทะฐะปะตะถะธั‚ัŒ** ะฒั–ะด ัะฟะพัะพะฑัƒ **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะฒะฐัˆะพั— ัะธัั‚ะตะผะธ** ั–, ะนะผะพะฒั–ั€ะฝะพ, ะฑัƒะดะต ะฟะพะฒ'ัะทะฐะฝะพ ะทั– ัะฟะพัะพะฑะพะผ ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผ, ะพะฑั€ะพะฑะบะธ ะฟะตั€ะตะทะฐะฟัƒัะบั–ะฒ ั‚ะพั‰ะพ. + +ะžััŒ ะบั–ะปัŒะบะฐ ะผะพะถะปะธะฒะธั… ั–ะดะตะน: + +- ยซInit Containerยป ัƒ Kubernetes, ัะบะธะน ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟะตั€ะตะด ะฒะฐัˆะธะผ ะบะพะฝั‚ะตะนะฝะตั€ะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ +- bash-ัะบั€ะธะฟั‚, ัะบะธะน ะฒะธะบะพะฝัƒั” ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ, ะฐ ะฟะพั‚ั–ะผ ะทะฐะฟัƒัะบะฐั” ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ + - ะ’ะฐะผ ัƒัะต ะพะดะฝะพ ะฟะพั‚ั€ั–ะฑะตะฝ ัะฟะพัั–ะฑ ะทะฐะฟัƒัะบะฐั‚ะธ/ะฟะตั€ะตะทะฐะฟัƒัะบะฐั‚ะธ ั†ะตะน bash-ัะบั€ะธะฟั‚, ะฒะธัะฒะปัั‚ะธ ะฟะพะผะธะปะบะธ ั‚ะพั‰ะพ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏ ะฝะฐะฒะตะดัƒ ะฑั–ะปัŒัˆ ะบะพะฝะบั€ะตั‚ะฝั– ะฟั€ะธะบะปะฐะดะธ ะดะปั ั†ัŒะพะณะพ ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ัƒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั–: [FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐั… - Docker](docker.md){.internal-link target=_blank}. + +/// + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั€ะตััƒั€ัั–ะฒ { #resource-utilization } + +ะ’ะฐัˆ ัะตั€ะฒะตั€(ะธ) - ั†ะต **ั€ะตััƒั€ั**, ัะบะธะน ะฒะธ ะผะพะถะตั‚ะต ัะฟะพะถะธะฒะฐั‚ะธ/**ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ** ะฒะฐัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ: ั‡ะฐั ะพะฑั‡ะธัะปะตะฝัŒ ะฝะฐ CPU ั‚ะฐ ะดะพัั‚ัƒะฟะฝัƒ RAM. + +ะกะบั–ะปัŒะบะธ ัะธัั‚ะตะผะฝะธั… ั€ะตััƒั€ัั–ะฒ ะฒะธ ั…ะพั‡ะตั‚ะต ัะฟะพะถะธะฒะฐั‚ะธ/ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ? ะ›ะตะณะบะพ ะฟะพะดัƒะผะฐั‚ะธ ยซะฝะตะฑะฐะณะฐั‚ะพยป, ะฐะปะต ะฝะฐัะฟั€ะฐะฒะดั– ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต ัะฟะพะถะธะฒะฐั‚ะธ **ะฝะฐัั‚ั–ะปัŒะบะธ ะฑะฐะณะฐั‚ะพ, ะฝะฐัะบั–ะปัŒะบะธ ะผะพะถะปะธะฒะพ ะฑะตะท ะบั€ะฐั…ัƒ**. + +ะฏะบั‰ะพ ะฒะธ ะฟะปะฐั‚ะธั‚ะต ะทะฐ 3 ัะตั€ะฒะตั€ะธ, ะฐะปะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะปะธัˆะต ั‚ั€ะพั…ะธ ั—ั… RAM ั– CPU, ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, **ะผะฐั€ะฝัƒั”ั‚ะต ะณั€ะพัˆั–** ๐Ÿ’ธ ั–, ะผะพะถะปะธะฒะพ, **ะตะปะตะบั‚ั€ะพะตะฝะตั€ะณั–ัŽ ัะตั€ะฒะตั€ั–ะฒ** ๐ŸŒŽ ั‚ะพั‰ะพ. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะผะพะถะต ะฑัƒั‚ะธ ะบั€ะฐั‰ะต ะผะฐั‚ะธ ะปะธัˆะต 2 ัะตั€ะฒะตั€ะธ ะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑั–ะปัŒัˆะธะน ะฒั–ะดัะพั‚ะพะบ ั—ั…ะฝั–ั… ั€ะตััƒั€ัั–ะฒ (CPU, ะฟะฐะผ'ัั‚ัŒ, ะดะธัะบ, ะฟั€ะพะฟัƒัะบะฝัƒ ะทะดะฐั‚ะฝั–ัั‚ัŒ ะผะตั€ะตะถั– ั‚ะพั‰ะพ). + +ะ— ั–ะฝัˆะพะณะพ ะฑะพะบัƒ, ัะบั‰ะพ ัƒ ะฒะฐั 2 ัะตั€ะฒะตั€ะธ ั– ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต **100% ั—ั…ะฝัŒะพะณะพ CPU ั‚ะฐ RAM**, ัƒ ะฟะตะฒะฝะธะน ะผะพะผะตะฝั‚ ัะบะธะนััŒ ะฟั€ะพั†ะตั ะฟะพะฟั€ะพัะธั‚ัŒ ะฑั–ะปัŒัˆะต ะฟะฐะผ'ัั‚ั–, ั– ัะตั€ะฒะตั€ ะผัƒัะธั‚ะธะผะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะดะธัะบ ัะบ ยซะฟะฐะผ'ัั‚ัŒยป (ั‰ะพ ะผะพะถะต ะฑัƒั‚ะธ ัƒ ั‚ะธััั‡ั– ั€ะฐะทั–ะฒ ะฟะพะฒั–ะปัŒะฝั–ัˆะธะผ) ะฐะฑะพ ะฝะฐะฒั–ั‚ัŒ **ะฒะฟะฐัั‚ะธ**. ะะฑะพ ะฟั€ะพั†ะตััƒ ะทะฝะฐะดะพะฑะปัั‚ัŒัั ะพะฑั‡ะธัะปะตะฝะฝั, ั– ะฒั–ะฝ ั‡ะตะบะฐั‚ะธะผะต, ะดะพะบะธ CPU ะทะฝะพะฒัƒ ะทะฒั–ะปัŒะฝะธั‚ัŒัั. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะบั€ะฐั‰ะต ะดะพะดะฐั‚ะธ **ั‰ะต ะพะดะธะฝ ัะตั€ะฒะตั€** ั– ะทะฐะฟัƒัั‚ะธั‚ะธ ั‡ะฐัั‚ะธะฝัƒ ะฟั€ะพั†ะตัั–ะฒ ะฝะฐ ะฝัŒะพะผัƒ, ั‰ะพะฑ ัƒ ะฒัั–ั… ะฑัƒะปะพ **ะดะพัั‚ะฐั‚ะฝัŒะพ RAM ั‚ะฐ ั‡ะฐััƒ CPU**. + +ะขะฐะบะพะถ ะผะพะถะปะธะฒะฐ ัะธั‚ัƒะฐั†ั–ั, ะบะพะปะธ ะท ะฟะตะฒะฝะพั— ะฟั€ะธั‡ะธะฝะธ ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต **ัั‚ั€ะธะฑะพะบ** ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒะฐัˆะพะณะพ API. ะœะพะถะปะธะฒะพ, ะฒั–ะฝ ัั‚ะฐะฒ ะฒั–ั€ัƒัะฝะธะผ ะฐะฑะพ ะนะพะณะพ ะฟะพั‡ะฐะปะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆั– ัะตั€ะฒั–ัะธ ั‡ะธ ะฑะพั‚ะธ. ะ† ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะผะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ั€ะตััƒั€ัะธ ะฝะฐ ะฒะธะฟะฐะดะพะบ ั‚ะฐะบะธั… ัะธั‚ัƒะฐั†ั–ะน. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ **ะดะพะฒั–ะปัŒะฝะธะน ั†ั–ะปัŒะพะฒะธะน** ั€ั–ะฒะตะฝัŒ, ะฝะฐะฟั€ะธะบะปะฐะด, **ะผั–ะถ 50% ั– 90%** ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั€ะตััƒั€ัั–ะฒ. ะกัƒั‚ัŒ ัƒ ั‚ะพะผัƒ, ั‰ะพ ั†ะต, ะนะผะพะฒั–ั€ะฝะพ, ะณะพะปะพะฒะฝั– ั€ะตั‡ั–, ัะบั– ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะฒะธะผั–ั€ัŽะฒะฐั‚ะธ ะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะดะปั ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั€ะพะทะณะพั€ั‚ะฐะฝัŒ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟั€ะพัั‚ั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ัะบ-ะพั‚ `htop`, ั‰ะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั CPU ั– RAM ะฝะฐ ัะตั€ะฒะตั€ั– ะฐะฑะพ ะบั–ะปัŒะบั–ัั‚ัŒ, ัะฟะพะถะธั‚ัƒ ะบะพะถะฝะธะผ ะฟั€ะพั†ะตัะพะผ. ะะฑะพ ัะบะปะฐะดะฝั–ัˆั– ะทะฐัะพะฑะธ ะผะพะฝั–ั‚ะพั€ะธะฝะณัƒ, ั€ะพะทะฟะพะดั–ะปะตะฝั– ะผั–ะถ ัะตั€ะฒะตั€ะฐะผะธ ั‚ะพั‰ะพ. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะขัƒั‚ ะฒะธ ะฟั€ะพั‡ะธั‚ะฐะปะธ ะฟั€ะพ ะพัะฝะพะฒะฝั– ะบะพะฝั†ะตะฟั†ั–ั—, ัะบั–, ะนะผะพะฒั–ั€ะฝะพ, ะฟะพั‚ั€ั–ะฑะฝะพ ั‚ั€ะธะผะฐั‚ะธ ะฒ ะณะพะปะพะฒั–, ะฒะธั€ั–ัˆัƒัŽั‡ะธ, ัะบ ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ: + +- ะ‘ะตะทะฟะตะบะฐ - HTTPS +- ะ—ะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ +- ะŸะตั€ะตะทะฐะฟัƒัะบะธ +- ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +- ะŸะฐะผ'ัั‚ัŒ +- ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ + +ะ ะพะทัƒะผั–ะฝะฝั ั†ะธั… ั–ะดะตะน ั– ั‚ะพะณะพ, ัะบ ั—ั… ะทะฐัั‚ะพัะพะฒัƒะฒะฐั‚ะธ, ะผะฐั” ะดะฐั‚ะธ ะฒะฐะผ ั–ะฝั‚ัƒั—ั†ั–ัŽ, ะฝะตะพะฑั…ั–ะดะฝัƒ ะดะปั ะฟั€ะธะนะฝัั‚ั‚ั ั€ั–ัˆะตะฝัŒ ะฟั–ะด ั‡ะฐั ะบะพะฝั„ั–ะณัƒั€ัƒะฒะฐะฝะฝั ั– ั‚ะพะฝะบะพะณะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฒะฐัˆะธั… ั€ะพะทะณะพั€ั‚ะฐะฝัŒ. ๐Ÿค“ + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ะฝะฐะฒะตะดัƒ ะฑั–ะปัŒัˆะต ะบะพะฝะบั€ะตั‚ะฝะธั… ะฟั€ะธะบะปะฐะดั–ะฒ ะผะพะถะปะธะฒะธั… ัั‚ั€ะฐั‚ะตะณั–ะน, ัะบะธะผะธ ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั. ๐Ÿš€ diff --git a/docs/uk/docs/deployment/docker.md b/docs/uk/docs/deployment/docker.md new file mode 100644 index 0000000000..d6faacfe5e --- /dev/null +++ b/docs/uk/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐั… - Docker { #fastapi-in-containers-docker } + +ะŸั–ะด ั‡ะฐั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ FastAPI ะฟะพัˆะธั€ะตะฝะธะน ะฟั–ะดั…ั–ะด - ะทะฑะธั€ะฐั‚ะธ ะพะฑั€ะฐะทะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ Linux. ะ—ะฐะทะฒะธั‡ะฐะน ั†ะต ั€ะพะฑะธั‚ัŒัั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Docker. ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ะฝัƒั‚ะธ ั†ะตะน ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะบั–ะปัŒะบะพะผะฐ ั€ั–ะทะฝะธะผะธ ัะฟะพัะพะฑะฐะผะธ. + +ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ Linux ะผะฐั” ะบั–ะปัŒะบะฐ ะฟะตั€ะตะฒะฐะณ, ะทะพะบั€ะตะผะฐ ะฑะตะทะฟะตะบะฐ, ะฒั–ะดั‚ะฒะพั€ัŽะฒะฐะฝั–ัั‚ัŒ, ะฟั€ะพัั‚ะพั‚ะฐ ั‚ะฐ ั–ะฝัˆั–. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะพัะฟั–ัˆะฐั”ั‚ะต ั– ะฒะถะต ะฒัะต ั†ะต ะทะฝะฐั”ั‚ะต? ะŸะตั€ะตะนะดั–ั‚ัŒ ะดะพ [`Dockerfile` ะฝะธะถั‡ะต ๐Ÿ‘‡](#build-a-docker-image-for-fastapi). + +/// + +
+ะŸะพะฟะตั€ะตะดะฝั–ะน ะฟะตั€ะตะณะปัะด Dockerfile ๐Ÿ‘€ + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# ะฏะบั‰ะพ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะทะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ ะฝะฐ ะบัˆั‚ะฐะปั‚ Nginx ะฐะฑะพ Traefik, ะดะพะดะฐะนั‚ะต --proxy-headers +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## ะฉะพ ั‚ะฐะบะต ะบะพะฝั‚ะตะนะฝะตั€ { #what-is-a-container } + +ะšะพะฝั‚ะตะนะฝะตั€ะธ (ะฟะตั€ะตะฒะฐะถะฝะพ ะบะพะฝั‚ะตะนะฝะตั€ะธ Linux) - ั†ะต ะดัƒะถะต ะปะตะณะบะธะน ัะฟะพัั–ะฑ ัƒะฟะฐะบัƒะฒะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ ะท ัƒัั–ะผะฐ ั—ั…ะฝั–ะผะธ ะทะฐะปะตะถะฝะพัั‚ัะผะธ ั‚ะฐ ะฟะพั‚ั€ั–ะฑะฝะธะผะธ ั„ะฐะนะปะฐะผะธ, ั–ะทะพะปัŽะฒะฐะฒัˆะธ ั—ั… ะฒั–ะด ั–ะฝัˆะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ (ั–ะฝัˆะธั… ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะฐะฑะพ ะบะพะผะฟะพะฝะตะฝั‚ั–ะฒ) ัƒ ั‚ั–ะน ัะฐะผั–ะน ัะธัั‚ะตะผั–. + +ะšะพะฝั‚ะตะนะฝะตั€ะธ Linux ะฟั€ะฐั†ัŽัŽั‚ัŒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะน ัะฐะผะธะน ัะดั€ะพ Linux, ั‰ะพ ะน ั…ะพัั‚ (ะผะฐัˆะธะฝะฐ, ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ, ั…ะผะฐั€ะฝะธะน ัะตั€ะฒะตั€ ั‚ะพั‰ะพ). ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒะพะฝะธ ะดัƒะถะต ะปะตะณะบั– (ัƒ ะฟะพั€ั–ะฒะฝัะฝะฝั– ะท ะฟะพะฒะฝะธะผะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะธะผะธ ะผะฐัˆะธะฝะฐะผะธ, ัะบั– ะตะผัƒะปัŽัŽั‚ัŒ ั†ั–ะปัƒ ะพะฟะตั€ะฐั†ั–ะนะฝัƒ ัะธัั‚ะตะผัƒ). + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะบะพะฝั‚ะตะนะฝะตั€ะธ ัะฟะพะถะธะฒะฐัŽั‚ัŒ ะผะฐะปะพ ั€ะตััƒั€ัั–ะฒ, ะฟั€ะธะฑะปะธะทะฝะพ ัะบ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐะฟัƒั‰ะตะฝั– ะฟั€ะพั†ะตัะธ (ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ ัะฟะพะถะธะฒะฐะปะฐ ะฑ ะทะฝะฐั‡ะฝะพ ะฑั–ะปัŒัˆะต). + +ะฃ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั‚ะฐะบะพะถ ั” ะฒะปะฐัะฝั– ั–ะทะพะปัŒะพะฒะฐะฝั– ะฟั€ะพั†ะตัะธ ะฒะธะบะพะฝะฐะฝะฝั (ะทะฐะทะฒะธั‡ะฐะน ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั), ั„ะฐะนะปะพะฒั– ัะธัั‚ะตะผะธ ั‚ะฐ ะผะตั€ะตะถั–, ั‰ะพ ัะฟั€ะพั‰ัƒั” ั€ะพะทะณะพั€ั‚ะฐะฝะฝั, ะฑะตะทะฟะตะบัƒ, ั€ะพะทั€ะพะฑะบัƒ ั‚ะพั‰ะพ. + +## ะฉะพ ั‚ะฐะบะต ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ { #what-is-a-container-image } + +ะšะพะฝั‚ะตะนะฝะตั€ ะทะฐะฟัƒัะบะฐั”ั‚ัŒัั ะท ะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ. + +ะžะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ - ั†ะต ัั‚ะฐั‚ะธั‡ะฝะฐ ะฒะตั€ัั–ั ะฒัั–ั… ั„ะฐะนะปั–ะฒ, ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั ั‚ะฐ ั‚ะธะฟะพะฒะฐ ะบะพะผะฐะฝะดะฐ/ะฟั€ะพะณั€ะฐะผะฐ, ัะบะฐ ะผะฐั” ะฑัƒั‚ะธ ะฟั€ะธััƒั‚ะฝั ะฒ ะบะพะฝั‚ะตะนะฝะตั€ั–. ะขัƒั‚ ยซัั‚ะฐั‚ะธั‡ะฝะฐยป ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะฝะต ะทะฐะฟัƒั‰ะตะฝะธะน, ะฒั–ะฝ ะฝะต ะฒะธะบะพะฝัƒั”ั‚ัŒัั, ั†ะต ะปะธัˆะต ัƒะฟะฐะบะพะฒะฐะฝั– ั„ะฐะนะปะธ ั‚ะฐ ะผะตั‚ะฐะดะฐะฝั–. + +ะะฐ ะฟั€ะพั‚ะธะฒะฐะณัƒ ยซะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐยป, ั‰ะพ ั” ะทะฑะตั€ะตะถะตะฝะธะผ ัั‚ะฐั‚ะธั‡ะฝะธะผ ะฒะผั–ัั‚ะพะผ, ยซะบะพะฝั‚ะตะนะฝะตั€ยป ะทะฐะทะฒะธั‡ะฐะน ะพะทะฝะฐั‡ะฐั” ะทะฐะฟัƒั‰ะตะฝะธะน ะตะบะทะตะผะฟะปัั€, ั‚ะต, ั‰ะพ ะฒะธะบะพะฝัƒั”ั‚ัŒัั. + +ะšะพะปะธ ะบะพะฝั‚ะตะนะฝะตั€ ะทะฐะฟัƒั‰ะตะฝะพ (ะทะฐะฟัƒั‰ะตะฝะธะน ะท ะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ), ะฒั–ะฝ ะผะพะถะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฐะฑะพ ะทะผั–ะฝัŽะฒะฐั‚ะธ ั„ะฐะนะปะธ, ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ั‚ะพั‰ะพ. ะฆั– ะทะผั–ะฝะธ ั–ัะฝัƒะฒะฐั‚ะธะผัƒั‚ัŒ ะปะธัˆะต ะฒ ั†ัŒะพะผัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–, ะฐะปะต ะฝะต ะทะฑะตั€ะตะถัƒั‚ัŒัั ะฒ ะฑะฐะทะพะฒะพะผัƒ ะพะฑั€ะฐะทั– ะบะพะฝั‚ะตะนะฝะตั€ะฐ (ะฝะต ะฑัƒะดัƒั‚ัŒ ะทะฐะฟะธัะฐะฝั– ะฝะฐ ะดะธัะบ). + +ะžะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะผะพะถะฝะฐ ะฟะพั€ั–ะฒะฝัั‚ะธ ะท ั„ะฐะนะปะพะผ ั– ะฒะผั–ัั‚ะพะผ ะฟั€ะพะณั€ะฐะผะธ, ะฝะฐะฟั€ะธะบะปะฐะด `python` ั– ั„ะฐะนะปะพะผ `main.py`. + +ะ ัะฐะผ ะบะพะฝั‚ะตะนะฝะตั€ (ะฝะฐ ะฒั–ะดะผั–ะฝัƒ ะฒั–ะด ะพะฑั€ะฐะทัƒ) - ั†ะต ั„ะฐะบั‚ะธั‡ะฝะพ ะทะฐะฟัƒั‰ะตะฝะธะน ะตะบะทะตะผะฟะปัั€ ะพะฑั€ะฐะทัƒ, ะฟะพั€ั–ะฒะฝัะฝะฝะธะน ั–ะท ะฟั€ะพั†ะตัะพะผ. ะะฐัะฟั€ะฐะฒะดั– ะบะพะฝั‚ะตะนะฝะตั€ ะฟั€ะฐั†ัŽั” ะปะธัˆะต ั‚ะพะดั–, ะบะพะปะธ ะฒ ะฝัŒะพะผัƒ ะฟั€ะฐั†ัŽั” ะฟั€ะพั†ะตั (ั– ะทะฐะทะฒะธั‡ะฐะน ั†ะต ะพะดะธะฝ ะฟั€ะพั†ะตั). ะšะพะฝั‚ะตะนะฝะตั€ ะทัƒะฟะธะฝัั”ั‚ัŒัั, ะบะพะปะธ ะฒ ะฝัŒะพะผัƒ ะฝะต ะฟั€ะฐั†ัŽั” ะถะพะดะตะฝ ะฟั€ะพั†ะตั. + +## ะžะฑั€ะฐะทะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ { #container-images } + +Docker ะฑัƒะฒ ะพะดะฝะธะผ ะท ะพัะฝะพะฒะฝะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ั‚ะฐ ะบะตั€ัƒะฒะฐะฝะฝั ะพะฑั€ะฐะทะฐะผะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั– ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ. + +ะ†ัะฝัƒั” ะฟัƒะฑะปั–ั‡ะฝะธะน Docker Hub ะท ะณะพั‚ะพะฒะธะผะธ ะพั„ั–ั†ั–ะนะฝะธะผะธ ะพะฑั€ะฐะทะฐะผะธ ะดะปั ะฑะฐะณะฐั‚ัŒะพั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ัะตั€ะตะดะพะฒะธั‰, ะฑะฐะท ะดะฐะฝะธั… ั– ะทะฐัั‚ะพััƒะฝะบั–ะฒ. + +ะะฐะฟั€ะธะบะปะฐะด, ั” ะพั„ั–ั†ั–ะนะฝะธะน ะพะฑั€ะฐะท Python. + +ะ† ั” ะฑะฐะณะฐั‚ะพ ั–ะฝัˆะธั… ะพะฑั€ะฐะทั–ะฒ ะดะปั ั€ั–ะทะฝะธั… ั€ะตั‡ะตะน, ัะบ-ะพั‚ ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะฐะฟั€ะธะบะปะฐะด ะดะปั: + +* PostgreSQL +* MySQL +* MongoDB +* Redis ั‚ะพั‰ะพ. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะณะพั‚ะพะฒะธะน ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ, ะดัƒะถะต ะปะตะณะบะพ ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั€ั–ะทะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ. ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฒะธะฟั€ะพะฑัƒะฒะฐั‚ะธ ะฝะพะฒัƒ ะฑะฐะทัƒ ะดะฐะฝะธั…. ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพั„ั–ั†ั–ะนะฝั– ะพะฑั€ะฐะทะธ ั‚ะฐ ะฟั€ะพัั‚ะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั—ั… ะทะผั–ะฝะฝะธะผะธ ะพั‚ะพั‡ะตะฝะฝั. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ัƒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะทะผะพะถะตั‚ะต ะฝะฐะฒั‡ะธั‚ะธัั ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ั– Docker ั‚ะฐ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ั– ะทะฝะฐะฝะฝั ะท ะฑะฐะณะฐั‚ัŒะผะฐ ั€ั–ะทะฝะธะผะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ ั– ะบะพะผะฟะพะฝะตะฝั‚ะฐะผะธ. + +ะขะพะฑั‚ะพ ะฒะธ ะทะฐะฟัƒัะบะฐั‚ะธะผะตั‚ะต ะบั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ะท ั€ั–ะทะฝะธะผะธ ั€ะตั‡ะฐะผะธ, ัะบ-ะพั‚ ะฑะฐะทัƒ ะดะฐะฝะธั…, ะทะฐัั‚ะพััƒะฝะพะบ ะฝะฐ Python, ะฒะตะฑัะตั€ะฒะตั€ ั–ะท ั„ั€ะพะฝั‚ะตะฝะดะพะผ ะฝะฐ React, ั– ะทโ€™ั”ะดะฝะฐั”ั‚ะต ั—ั… ั‡ะตั€ะตะท ะฒะฝัƒั‚ั€ั–ัˆะฝัŽ ะผะตั€ะตะถัƒ. + +ะฃัั– ัะธัั‚ะตะผะธ ะบะตั€ัƒะฒะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ (ัะบ Docker ั‡ะธ Kubernetes) ะผะฐัŽั‚ัŒ ั†ั– ะผะตั€ะตะถะตะฒั– ะผะพะถะปะธะฒะพัั‚ั– ะฒะฑัƒะดะพะฒะฐะฝะพ. + +## ะšะพะฝั‚ะตะนะฝะตั€ะธ ั– ะฟั€ะพั†ะตัะธ { #containers-and-processes } + +ะžะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะทะฐะทะฒะธั‡ะฐะน ะผั–ัั‚ะธั‚ัŒ ัƒ ัะฒะพั—ั… ะผะตั‚ะฐะดะฐะฝะธั… ั‚ะธะฟะพะฒัƒ ะฟั€ะพะณั€ะฐะผัƒ ะฐะฑะพ ะบะพะผะฐะฝะดัƒ, ัะบัƒ ัะปั–ะด ะฒะธะบะพะฝะฐั‚ะธ ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ, ั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะดะปั ั†ั–ั”ั— ะฟั€ะพะณั€ะฐะผะธ. ะ”ัƒะถะต ัั…ะพะถะต ะฝะฐ ั‚ะต, ั‰ะพ ะฒะธ ะฑ ะฒะธะบะพะฝะฐะปะธ ะฒ ะบะพะผะฐะฝะดะฝะพะผัƒ ั€ัะดะบัƒ. + +ะšะพะปะธ ะบะพะฝั‚ะตะนะฝะตั€ ะทะฐะฟัƒัะบะฐั”ั‚ัŒัั, ะฒั–ะฝ ะฒะธะบะพะฝะฐั” ั†ัŽ ะบะพะผะฐะฝะดัƒ/ะฟั€ะพะณั€ะฐะผัƒ (ั…ะพั‡ะฐ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะทะฝะฐั‡ะธั‚ะธ ั—ั— ั– ะทะฐะฟัƒัั‚ะธั‚ะธ ั–ะฝัˆัƒ ะบะพะผะฐะฝะดัƒ/ะฟั€ะพะณั€ะฐะผัƒ). + +ะšะพะฝั‚ะตะนะฝะตั€ ะฟั€ะฐั†ัŽั” ะดะพั‚ะธ, ะดะพะบะธ ะฟั€ะฐั†ัŽั” ะณะพะปะพะฒะฝะธะน ะฟั€ะพั†ะตั (ะบะพะผะฐะฝะดะฐ ะฐะฑะพ ะฟั€ะพะณั€ะฐะผะฐ). + +ะ—ะฐะทะฒะธั‡ะฐะน ะบะพะฝั‚ะตะนะฝะตั€ ะผะฐั” ะพะดะธะฝ ะฟั€ะพั†ะตั, ะฐะปะต ั‚ะฐะบะพะถ ะผะพะถะปะธะฒะพ ะทะฐะฟัƒัะบะฐั‚ะธ ะฟั–ะดะฟั€ะพั†ะตัะธ ะท ะณะพะปะพะฒะฝะพะณะพ ะฟั€ะพั†ะตััƒ, ั– ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ ัƒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–. + +ะะปะต ะฝะตะผะพะถะปะธะฒะพ ะผะฐั‚ะธ ะทะฐะฟัƒั‰ะตะฝะธะน ะบะพะฝั‚ะตะนะฝะตั€ ะฑะตะท ะฟั€ะธะฝะฐะนะผะฝั– ะพะดะฝะพะณะพ ะทะฐะฟัƒั‰ะตะฝะพะณะพ ะฟั€ะพั†ะตััƒ. ะฏะบั‰ะพ ะณะพะปะพะฒะฝะธะน ะฟั€ะพั†ะตั ะทัƒะฟะธะฝัั”ั‚ัŒัั, ะบะพะฝั‚ะตะนะฝะตั€ ะทัƒะฟะธะฝัั”ั‚ัŒัั. + +## ะ—ั–ะฑั€ะฐั‚ะธ Docker-ะพะฑั€ะฐะท ะดะปั FastAPI { #build-a-docker-image-for-fastapi } + +ะ“ะฐั€ะฐะทะด, ะทะฑะตั€ั–ะผะพ ั‰ะพััŒ ะทะฐั€ะฐะท! ๐Ÿš€ + +ะฏ ะฟะพะบะฐะถัƒ ะฒะฐะผ, ัะบ ะทั–ะฑั€ะฐั‚ะธ ะพะฑั€ะฐะท Docker ะดะปั FastAPI ะท ะฝัƒะปั ะฝะฐ ะพัะฝะพะฒั– ะพั„ั–ั†ั–ะนะฝะพะณะพ ะพะฑั€ะฐะทัƒ Python. + +ะฆะต ั‚ะต, ั‰ะพ ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ั€ะพะฑะธั‚ะธ ัƒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ, ะฝะฐะฟั€ะธะบะปะฐะด: + +* ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั Kubernetes ะฐะฑะพ ะฟะพะดั–ะฑะฝะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ +* ะŸั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ ะฝะฐ Raspberry Pi +* ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั…ะผะฐั€ะฝะพะณะพ ัะตั€ะฒั–ััƒ, ัะบะธะน ะทะฐะฟัƒัั‚ะธั‚ัŒ ะดะปั ะฒะฐั ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ั‚ะพั‰ะพ + +### ะ’ะธะผะพะณะธ ะดะพ ะฟะฐะบะตั‚ั–ะฒ { #package-requirements } + +ะ—ะฐะทะฒะธั‡ะฐะน ะฒะธ ะผะฐั”ั‚ะต ะฒะธะผะพะณะธ ะดะพ ะฟะฐะบะตั‚ั–ะฒ ะดะปั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒ ะพะบั€ะตะผะพะผัƒ ั„ะฐะนะปั–. + +ะฆะต ะทะฐะปะตะถะธั‚ัŒ ะฟะตั€ะตะฒะฐะถะฝะพ ะฒั–ะด ั–ะฝัั‚ั€ัƒะผะตะฝั‚ัƒ, ัะบะธะน ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ั†ะธั… ะฒะธะผะพะณ. + +ะะฐะนะฟะพัˆะธั€ะตะฝั–ัˆะธะน ัะฟะพัั–ะฑ - ะผะฐั‚ะธ ั„ะฐะนะป `requirements.txt` ะท ะฝะฐะทะฒะฐะผะธ ะฟะฐะบะตั‚ั–ะฒ ั– ั—ั…ะฝั–ะผะธ ะฒะตั€ัั–ัะผะธ, ะฟะพ ะพะดะฝะพะผัƒ ะฝะฐ ั€ัะดะพะบ. + +ะ—ะฒั–ัะฝะพ, ะฒะธ ะทะฐัั‚ะพััƒั”ั‚ะต ั‚ั– ัะฐะผั– ั–ะดะตั— ะท [ะŸั€ะพ ะฒะตั€ัั–ั— FastAPI](versions.md){.internal-link target=_blank}, ั‰ะพะฑ ะทะฐะดะฐั‚ะธ ะดั–ะฐะฟะฐะทะพะฝะธ ะฒะตั€ัั–ะน. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะฐัˆ `requirements.txt` ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +ะ† ะทะฐะทะฒะธั‡ะฐะน ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธะผะตั‚ะต ั†ั– ะทะฐะปะตะถะฝะพัั‚ั– ะฟะฐะบะตั‚ั–ะฒ ั‡ะตั€ะตะท `pip`, ะฝะฐะฟั€ะธะบะปะฐะด: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ†ัะฝัƒัŽั‚ัŒ ั–ะฝัˆั– ั„ะพั€ะผะฐั‚ะธ ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะดะปั ะฒะธะทะฝะฐั‡ะตะฝะฝั ั– ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะฟะฐะบะตั‚ั–ะฒ. + +/// + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะพะด **FastAPI** { #create-the-fastapi-code } + +* ะกั‚ะฒะพั€ั–ั‚ัŒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ `app` ั– ะฟะตั€ะตะนะดั–ั‚ัŒ ัƒ ะฝะตั—. +* ะกั‚ะฒะพั€ั–ั‚ัŒ ะฟะพั€ะพะถะฝั–ะน ั„ะฐะนะป `__init__.py`. +* ะกั‚ะฒะพั€ั–ั‚ัŒ ั„ะฐะนะป `main.py` ะท ะฒะผั–ัั‚ะพะผ: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +ะขะตะฟะตั€ ัƒ ั‚ั–ะน ัะฐะผั–ะน ะดะธั€ะตะบั‚ะพั€ั–ั— ะฟั€ะพั”ะบั‚ัƒ ัั‚ะฒะพั€ั–ั‚ัŒ ั„ะฐะนะป `Dockerfile` ะท ะฒะผั–ัั‚ะพะผ: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. ะŸะพั‡ะฝั–ั‚ัŒ ะท ะพั„ั–ั†ั–ะนะฝะพะณะพ ะฑะฐะทะพะฒะพะณะพ ะพะฑั€ะฐะทัƒ Python. + +2. ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะฟะพั‚ะพั‡ะฝัƒ ั€ะพะฑะพั‡ัƒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ ะฒ `/code`. + + ะกะฐะผะต ััŽะดะธ ะผะธ ะฟะพะผั–ัั‚ะธะผะพ ั„ะฐะนะป `requirements.txt` ั– ะดะธั€ะตะบั‚ะพั€ั–ัŽ `app`. + +3. ะกะบะพะฟั–ัŽะนั‚ะต ั„ะฐะนะป ะท ะฒะธะผะพะณะฐะผะธ ะฒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ `/code`. + + ะกะฟะพั‡ะฐั‚ะบัƒ ัะบะพะฟั–ัŽะนั‚ะต ะปะธัˆะต ั„ะฐะนะป ะท ะฒะธะผะพะณะฐะผะธ, ะฐ ะฝะต ั€ะตัˆั‚ัƒ ะบะพะดัƒ. + + ะžัะบั–ะปัŒะบะธ ั†ะตะน ั„ะฐะนะป ะทะผั–ะฝัŽั”ั‚ัŒัั ะฝะตั‡ะฐัั‚ะพ, Docker ะฒะธัะฒะธั‚ัŒ ั†ะต ั– ะฒะธะบะพั€ะธัั‚ะฐั” ะบะตัˆ ะดะปั ั†ัŒะพะณะพ ะบั€ะพะบัƒ, ั‰ะพ ั‚ะฐะบะพะถ ัƒะฒั–ะผะบะฝะต ะบะตัˆ ั– ะดะปั ะฝะฐัั‚ัƒะฟะฝะพะณะพ ะบั€ะพะบัƒ. + +4. ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– ะฟะฐะบะตั‚ั–ะฒ ั–ะท ั„ะฐะนะปัƒ ะฒะธะผะพะณ. + + ะžะฟั†ั–ั `--no-cache-dir` ะบะฐะถะต `pip` ะฝะต ะทะฑะตั€ั–ะณะฐั‚ะธ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ะฟะฐะบะตั‚ะธ ะปะพะบะฐะปัŒะฝะพ, ะฐะดะถะต ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ ะปะธัˆะต ั‚ะพะดั–, ัะบั‰ะพ `pip` ะฑัƒะดะต ะทะฐะฟัƒั‰ะตะฝะพ ะทะฝะพะฒัƒ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ั‚ะธั… ัะฐะผะธั… ะฟะฐะบะตั‚ั–ะฒ, ะฐะปะต ะฒ ั€ะพะฑะพั‚ั– ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ั†ะต ะฝะต ั‚ะฐะบ. + + /// note | ะŸั€ะธะผั–ั‚ะบะฐ + + `--no-cache-dir` ัั‚ะพััƒั”ั‚ัŒัั ะปะธัˆะต `pip`, ั†ะต ะฝะต ะผะฐั” ะฒั–ะดะฝะพัˆะตะฝะฝั ะดะพ Docker ั‡ะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ. + + /// + + ะžะฟั†ั–ั `--upgrade` ะบะฐะถะต `pip` ะพะฝะพะฒะธั‚ะธ ะฟะฐะบะตั‚ะธ, ัะบั‰ะพ ะฒะพะฝะธ ะฒะถะต ะฒัั‚ะฐะฝะพะฒะปะตะฝั–. + + ะžัะบั–ะปัŒะบะธ ะฟะพะฟะตั€ะตะดะฝั–ะน ะบั€ะพะบ ะบะพะฟั–ัŽะฒะฐะฝะฝั ั„ะฐะนะปัƒ ะผะพะถะต ะฑัƒั‚ะธ ะฒะธัะฒะปะตะฝะธะน ะบะตัˆะตะผ Docker, ั†ะตะน ะบั€ะพะบ ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต ะบะตัˆ Docker, ะบะพะปะธ ั†ะต ะผะพะถะปะธะฒะพ. + + ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะบะตัˆัƒ ะฝะฐ ั†ัŒะพะผัƒ ะบั€ะพั†ั– ะทะฑะตั€ะตะถะต ะฒะฐะผ ะฑะฐะณะฐั‚ะพ ั‡ะฐััƒ ะฟั–ะด ั‡ะฐั ะฟะพะฒั‚ะพั€ะฝะธั… ะทะฑั–ั€ะพะบ ะพะฑั€ะฐะทัƒ ะฒ ั€ะพะทั€ะพะฑั†ั–, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ ั‰ะพะฑ ะทะฐะฒะถะดะธ ะทะฐะฒะฐะฝั‚ะฐะถัƒะฒะฐั‚ะธ ั– ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒัั– ะทะฐะปะตะถะฝะพัั‚ั–. + +5. ะกะบะพะฟั–ัŽะนั‚ะต ะดะธั€ะตะบั‚ะพั€ั–ัŽ `./app` ัƒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ `/code`. + + ะžัะบั–ะปัŒะบะธ ั‚ัƒั‚ ัƒะฒะตััŒ ะบะพะด, ัะบะธะน ะทะผั–ะฝัŽั”ั‚ัŒัั ะฝะฐะนั‡ะฐัั‚ั–ัˆะต, ะบะตัˆ Docker ะฝะต ะฑัƒะดะต ะปะตะณะบะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะธะน ะดะปั ั†ัŒะพะณะพ ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธั… ะฝะฐัั‚ัƒะฟะฝะธั… ะบั€ะพะบั–ะฒ. + + ะขะพะผัƒ ะฒะฐะถะปะธะฒะพ ั€ะพะทะผั–ัั‚ะธั‚ะธ ั†ะต ะฑะปะธะถั‡ะต ะดะพ ะบั–ะฝั†ั `Dockerfile`, ั‰ะพะฑ ะพะฟั‚ะธะผั–ะทัƒะฒะฐั‚ะธ ั‡ะฐั ะทะฑั–ั€ะบะธ ะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ. + +6. ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะบะพะผะฐะฝะดัƒ ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `fastapi run`, ัะบะฐ ะฒัะตั€ะตะดะธะฝั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” Uvicorn. + + `CMD` ะฟั€ะธะนะผะฐั” ัะฟะธัะพะบ ัั‚ั€ะพะบ, ะบะพะถะฝะฐ ะท ัะบะธั… - ั†ะต ั‚ะต, ั‰ะพ ะฒะธ ะฑ ะฝะฐะฑะธั€ะฐะปะธ ะฒ ะบะพะผะฐะฝะดะฝะพะผัƒ ั€ัะดะบัƒ, ั€ะพะทะดั–ะปะตะฝะต ะฟั€ะพะฑั–ะปะฐะผะธ. + + ะฆั ะบะพะผะฐะฝะดะฐ ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะฐ ะท ะฟะพั‚ะพั‡ะฝะพั— ั€ะพะฑะพั‡ะพั— ะดะธั€ะตะบั‚ะพั€ั–ั—, ั‚ั–ั”ั— ัะฐะผะพั— `/code`, ัะบัƒ ะฒะธ ะฒะบะฐะทะฐะปะธ ะฒะธั‰ะต ั‡ะตั€ะตะท `WORKDIR /code`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะตั€ะตะณะปัะฝัŒั‚ะต, ั‰ะพ ั€ะพะฑะธั‚ัŒ ะบะพะถะตะฝ ั€ัะดะพะบ, ะบะปะฐั†ะฝัƒะฒัˆะธ ะฝะฐ ะบะพะถะฝัƒ ะฝะพะผะตั€ะฝัƒ ะฟะพะทะฝะฐั‡ะบัƒ ะฒ ะบะพะดั–. ๐Ÿ‘† + +/// + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะžะฑะพะฒโ€™ัะทะบะพะฒะพ ะทะฐะฒะถะดะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต exec form ั–ะฝัั‚ั€ัƒะบั†ั–ั— `CMD`, ัะบ ะฟะพััะฝะตะฝะพ ะฝะธะถั‡ะต. + +/// + +#### ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `CMD` - exec form { #use-cmd-exec-form } + +ะ†ะฝัั‚ั€ัƒะบั†ั–ัŽ Docker `CMD` ะผะพะถะฝะฐ ะทะฐะฟะธัะฐั‚ะธ ัƒ ะดะฒะพั… ั„ะพั€ะผะฐั…: + +โœ… Exec form: + +```Dockerfile +# โœ… ะ ะพะฑั–ั‚ัŒ ั‚ะฐะบ +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +โ›”๏ธ Shell form: + +```Dockerfile +# โ›”๏ธ ะะต ั€ะพะฑั–ั‚ัŒ ั‚ะฐะบ +CMD fastapi run app/main.py --port 80 +``` + +ะžะฑะพะฒโ€™ัะทะบะพะฒะพ ะทะฐะฒะถะดะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต exec form, ั‰ะพะฑ FastAPI ะผั–ะณ ะบะพั€ะตะบั‚ะฝะพ ะทะฐะฒะตั€ัˆัƒะฒะฐั‚ะธ ั€ะพะฑะพั‚ัƒ ั‚ะฐ ั‰ะพะฑ ะฑัƒะปะธ ะฒะธะบะปะธะบะฐะฝั– [ะฟะพะดั–ั— ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั](../advanced/events.md){.internal-link target=_blank}. + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Docker ะฟั€ะพ shell ั‚ะฐ exec form. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะพัะพะฑะปะธะฒะพ ะฟะพะผั–ั‚ะฝะพ ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– `docker compose`. ะ”ะธะฒ. ั€ะพะทะดั–ะป FAQ Docker Compose ะดะปั ั‚ะตั…ะฝั–ั‡ะฝะธั… ะดะตั‚ะฐะปะตะน: ะงะพะผัƒ ะผะพั— ัะตั€ะฒั–ัะธ ะฟะพั‚ั€ะตะฑัƒัŽั‚ัŒ 10 ัะตะบัƒะฝะด, ั‰ะพะฑ ะฟะตั€ะตัะพั‚ะฒะพั€ะธั‚ะธัั ะฐะฑะพ ะทัƒะฟะธะฝะธั‚ะธัั?. + +#### ะกั‚ั€ัƒะบั‚ัƒั€ะฐ ะดะธั€ะตะบั‚ะพั€ั–ะน { #directory-structure } + +ะ—ะฐั€ะฐะท ัƒ ะฒะฐั ะผะฐั” ะฑัƒั‚ะธ ั‚ะฐะบะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ะดะธั€ะตะบั‚ะพั€ั–ะน: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ โ””โ”€โ”€ main.py +โ”œโ”€โ”€ Dockerfile +โ””โ”€โ”€ requirements.txt +``` + +#### ะ—ะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ ะท ั‚ะตั€ะผั–ะฝะฐั†ั–ั”ัŽ TLS { #behind-a-tls-termination-proxy } + +ะฏะบั‰ะพ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะบะพะฝั‚ะตะนะฝะตั€ ะทะฐ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ ะท ั‚ะตั€ะผั–ะฝะฐั†ั–ั”ัŽ TLS (ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบะพะผ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั), ะฝะฐะฟั€ะธะบะปะฐะด Nginx ะฐะฑะพ Traefik, ะดะพะดะฐะนั‚ะต ะพะฟั†ั–ัŽ `--proxy-headers`. ะฆะต ัะบะฐะถะต Uvicorn (ั‡ะตั€ะตะท CLI FastAPI) ะดะพะฒั–ั€ัั‚ะธ ะทะฐะณะพะปะพะฒะบะฐะผ, ั‰ะพ ะฝะฐะดัะธะปะฐัŽั‚ัŒัั ั†ะธะผ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ, ัะบั– ะฒะบะฐะทัƒัŽั‚ัŒ, ั‰ะพ ะทะฐัั‚ะพััƒะฝะพะบ ะฟั€ะฐั†ัŽั” ะทะฐ HTTPS ั‚ะพั‰ะพ. + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### ะšะตัˆ Docker { #docker-cache } + +ะฃ ั†ัŒะพะผัƒ `Dockerfile` ั” ะฒะฐะถะปะธะฒะธะน ั‚ั€ัŽะบ: ัะฟะพั‡ะฐั‚ะบัƒ ะผะธ ะบะพะฟั–ัŽั”ะผะพ ะปะธัˆะต ั„ะฐะนะป ั–ะท ะทะฐะปะตะถะฝะพัั‚ัะผะธ, ะฐ ะฝะต ั€ะตัˆั‚ัƒ ะบะพะดัƒ. ะžััŒ ั‡ะพะผัƒ. + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker ั‚ะฐ ั–ะฝัˆั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะทะฑะธั€ะฐัŽั‚ัŒ ั†ั– ะพะฑั€ะฐะทะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั–ะฝะบั€ะตะผะตะฝั‚ะฐะปัŒะฝะพ, ะดะพะดะฐัŽั‡ะธ ะพะดะธะฝ ัˆะฐั€ ะฟะพะฒะตั€ั… ั–ะฝัˆะพะณะพ, ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท ะฒะตั€ั…ะฝัŒะพั— ั‡ะฐัั‚ะธะฝะธ `Dockerfile` ั– ะดะพะดะฐัŽั‡ะธ ะฑัƒะดัŒ-ัะบั– ั„ะฐะนะปะธ, ัั‚ะฒะพั€ะตะฝั– ะบะพะถะฝะพัŽ ั–ะฝัั‚ั€ัƒะบั†ั–ั”ัŽ ะฒ `Dockerfile`. + +Docker ั‚ะฐ ะฟะพะดั–ะฑะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั‚ะฐะบะพะถ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฒะฝัƒั‚ั€ั–ัˆะฝั–ะน ะบะตัˆ ะฟั–ะด ั‡ะฐั ะทะฑั–ั€ะบะธ ะพะฑั€ะฐะทัƒ. ะฏะบั‰ะพ ั„ะฐะนะป ะฝะต ะทะผั–ะฝัŽะฒะฐะฒัั ะท ะผะพะผะตะฝั‚ัƒ ะพัั‚ะฐะฝะฝัŒะพั— ะทะฑั–ั€ะบะธ, ั‚ะพะดั– ะฒั–ะฝ ะฟะพะฒั‚ะพั€ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั” ั‚ะพะน ัะฐะผะธะน ัˆะฐั€, ัั‚ะฒะพั€ะตะฝะธะน ะฒะพัั‚ะฐะฝะฝั”, ะทะฐะผั–ัั‚ัŒ ะบะพะฟั–ัŽะฒะฐะฝะฝั ั„ะฐะนะปัƒ ะทะฝะพะฒัƒ ั‚ะฐ ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ัˆะฐั€ัƒ ะท ะฝัƒะปั. + +ะŸั€ะพัั‚ะต ัƒะฝะธะบะฝะตะฝะฝั ะบะพะฟั–ัŽะฒะฐะฝะฝั ั„ะฐะนะปั–ะฒ ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ััƒั‚ั‚ั”ะฒะพ ะฟะพะบั€ะฐั‰ัƒั” ัะธั‚ัƒะฐั†ั–ัŽ, ะฐะปะต ะพัะบั–ะปัŒะบะธ ะดะปั ั†ัŒะพะณะพ ะบั€ะพะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะบะตัˆ, ะฒั–ะฝ ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะตัˆ ั– ะดะปั ะฝะฐัั‚ัƒะฟะฝะพะณะพ ะบั€ะพะบัƒ. ะะฐะฟั€ะธะบะปะฐะด, ะฒั–ะฝ ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะตัˆ ะดะปั ั–ะฝัั‚ั€ัƒะบั†ั–ั—, ัะบะฐ ะฒัั‚ะฐะฝะพะฒะปัŽั” ะทะฐะปะตะถะฝะพัั‚ั–: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +ะคะฐะนะป ั–ะท ะฒะธะผะพะณะฐะผะธ ะดะพ ะฟะฐะบะตั‚ั–ะฒ ะทะผั–ะฝัŽะฒะฐั‚ะธะผะตั‚ัŒัั ะฝะตั‡ะฐัั‚ะพ. ะžั‚ะถะต, ะบะพะฟั–ัŽัŽั‡ะธ ะปะธัˆะต ั†ะตะน ั„ะฐะนะป, Docker ะทะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะตัˆ ะดะปั ั†ัŒะพะณะพ ะบั€ะพะบัƒ. + +ะ ะฟะพั‚ั–ะผ Docker ะทะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะตัˆ ั– ะดะปั ะฝะฐัั‚ัƒะฟะฝะพะณะพ ะบั€ะพะบัƒ, ัะบะธะน ะทะฐะฒะฐะฝั‚ะฐะถัƒั” ั‚ะฐ ะฒัั‚ะฐะฝะพะฒะปัŽั” ั†ั– ะทะฐะปะตะถะฝะพัั‚ั–. ะ† ัะฐะผะต ั‚ัƒั‚ ะผะธ ะทะฐะพั‰ะฐะดะถัƒั”ะผะพ ะฑะฐะณะฐั‚ะพ ั‡ะฐััƒ. โœจ ...ั– ัƒะฝะธะบะฐั”ะผะพ ะฝัƒะดะฝะพะณะพ ะพั‡ั–ะบัƒะฒะฐะฝะฝั. ๐Ÿ˜ช๐Ÿ˜† + +ะ—ะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ั– ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะฟะฐะบะตั‚ั–ะฒ ะผะพะถะต ะทะฐะนะผะฐั‚ะธ ั…ะฒะธะปะธะฝะธ, ะฐะปะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะบะตัˆัƒ ะทะฐะนะผะต ะผะฐะบัะธะผัƒะผ ัะตะบัƒะฝะดะธ. + +ะ† ะพัะบั–ะปัŒะบะธ ะฒะธ ะทะฑะธั€ะฐั‚ะธะผะตั‚ะต ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะทะฝะพะฒัƒ ั– ะทะฝะพะฒัƒ ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ัั‚ะธ, ั‰ะพ ะทะผั–ะฝะธ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั– ะฟั€ะฐั†ัŽัŽั‚ัŒ, ั†ะต ะทะฐะพั‰ะฐะดะธั‚ัŒ ะฑะฐะณะฐั‚ะพ ะฝะฐะบะพะฟะธั‡ะตะฝะพะณะพ ั‡ะฐััƒ. + +ะŸะพั‚ั–ะผ, ะฑะปะธะถั‡ะต ะดะพ ะบั–ะฝั†ั `Dockerfile`, ะผะธ ะบะพะฟั–ัŽั”ะผะพ ะฒะตััŒ ะบะพะด. ะžัะบั–ะปัŒะบะธ ั†ะต ั‚ะต, ั‰ะพ ะทะผั–ะฝัŽั”ั‚ัŒัั ะฝะฐะนั‡ะฐัั‚ั–ัˆะต, ะผะธ ั€ะพะทะผั–ั‰ัƒั”ะผะพ ั†ะต ะฑะปะธะถั‡ะต ะดะพ ะบั–ะฝั†ั, ะฐะดะถะต ะผะฐะนะถะต ะทะฐะฒะถะดะธ ะฒัะต ะฟั–ัะปั ั†ัŒะพะณะพ ะบั€ะพะบัƒ ะฝะต ะทะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะตัˆ. + +```Dockerfile +COPY ./app /code/app +``` + +### ะ—ะฑะตั€ั–ั‚ัŒ Docker-ะพะฑั€ะฐะท { #build-the-docker-image } + +ะขะตะฟะตั€, ะบะพะปะธ ะฒัั– ั„ะฐะนะปะธ ะฝะฐ ะผั–ัั†ั–, ะทะฑะตั€ั–ะผะพ ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ. + +* ะŸะตั€ะตะนะดั–ั‚ัŒ ัƒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ ะฟั€ะพั”ะบั‚ัƒ (ะดะต ะฒะฐัˆ `Dockerfile`, ัะบะธะน ะผั–ัั‚ะธั‚ัŒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ `app`). +* ะ—ะฑะตั€ั–ั‚ัŒ ะฒะฐัˆ ะพะฑั€ะฐะท FastAPI: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ `.` ะฒ ะบั–ะฝั†ั–. ะฆะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ `./`. ะ’ะพะฝะพ ะบะฐะถะต Docker, ัะบัƒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะดะปั ะทะฑั–ั€ะบะธ ะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ - ั†ะต ะฟะพั‚ะพั‡ะฝะฐ ะดะธั€ะตะบั‚ะพั€ั–ั (`.`). + +/// + +### ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ Docker-ะบะพะฝั‚ะตะนะฝะตั€ { #start-the-docker-container } + +* ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ะบะพะฝั‚ะตะนะฝะตั€ ะฝะฐ ะพัะฝะพะฒั– ะฒะฐัˆะพะณะพ ะพะฑั€ะฐะทัƒ: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะ’ะธ ะผะฐั”ั‚ะต ะทะผะพะณัƒ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั†ะต ะทะฐ URL ะฒะฐัˆะพะณะพ Docker-ะบะพะฝั‚ะตะนะฝะตั€ะฐ, ะฝะฐะฟั€ะธะบะปะฐะด: http://192.168.99.100/items/5?q=somequery ะฐะฑะพ http://127.0.0.1/items/5?q=somequery (ะฐะฑะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒะฐัˆ Docker-ั…ะพัั‚). + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ั‰ะพััŒ ั‚ะฐะบะต: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## ะ†ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API { #interactive-api-docs } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะนั‚ะธ ะฝะฐ http://192.168.99.100/docs ะฐะฑะพ http://127.0.0.1/docs (ะฐะฑะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒะฐัˆ Docker-ั…ะพัั‚). + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API (ะฝะฐะดะฐั”ั‚ัŒัั Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API { #alternative-api-docs } + +ะขะฐะบะพะถ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะนั‚ะธ ะฝะฐ http://192.168.99.100/redoc ะฐะฑะพ http://127.0.0.1/redoc (ะฐะฑะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒะฐัˆ Docker-ั…ะพัั‚). + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝัƒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ (ะฝะฐะดะฐั”ั‚ัŒัั ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## ะ—ะฑั–ั€ะบะฐ Docker-ะพะฑั€ะฐะทัƒ ะท FastAPI ะฒ ะพะดะฝะพะผัƒ ั„ะฐะนะปั– { #build-a-docker-image-with-a-single-file-fastapi } + +ะฏะบั‰ะพ ะฒะฐัˆ FastAPI - ั†ะต ะพะดะธะฝ ั„ะฐะนะป, ะฝะฐะฟั€ะธะบะปะฐะด `main.py` ะฑะตะท ะดะธั€ะตะบั‚ะพั€ั–ั— `./app`, ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +``` +. +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ main.py +โ””โ”€โ”€ requirements.txt +``` + +ะขะพะดั– ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะปะธัˆะต ะทะผั–ะฝะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดะฝั– ัˆะปัั…ะธ ะดะปั ะบะพะฟั–ัŽะฒะฐะฝะฝั ั„ะฐะนะปัƒ ะฒัะตั€ะตะดะธะฝั– `Dockerfile`: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. ะกะบะพะฟั–ัŽะนั‚ะต ั„ะฐะนะป `main.py` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ะดะธั€ะตะบั‚ะพั€ั–ัŽ `/code` (ะฑะตะท ะฑัƒะดัŒ-ัะบะพั— ะดะธั€ะตะบั‚ะพั€ั–ั— `./app`). + +2. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `fastapi run`, ั‰ะพะฑ ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะท ะพะดะฝะพะณะพ ั„ะฐะนะปัƒ `main.py`. + +ะšะพะปะธ ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ั„ะฐะนะป ัƒ `fastapi run`, ะฒะพะฝะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฒะธะทะฝะฐั‡ะธั‚ัŒ, ั‰ะพ ั†ะต ะพะดะธะฝ ั„ะฐะนะป, ะฐ ะฝะต ั‡ะฐัั‚ะธะฝะฐ ะฟะฐะบะตั‚ะฐ, ั– ะทะฝะฐั‚ะธะผะต, ัะบ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ั‚ะฐ ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI. ๐Ÿ˜Ž + +## ะšะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployment-concepts } + +ะŸะพะณะพะฒะพั€ั–ะผะพ ะทะฝะพะฒัƒ ะฟั€ะพ ะดะตัะบั– ะท ั‚ะธั… ัะฐะผะธั… [ะšะพะฝั†ะตะฟั†ั–ะน ั€ะพะทะณะพั€ั‚ะฐะฝะฝั](concepts.md){.internal-link target=_blank} ัƒ ั‚ะตั€ะผั–ะฝะฐั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ. + +ะšะพะฝั‚ะตะนะฝะตั€ะธ - ั†ะต ะฟะตั€ะตะฒะฐะถะฝะพ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ัะฟั€ะพั‰ะตะฝะฝั ะฟั€ะพั†ะตััƒ ะทะฑะธั€ะฐะฝะฝั ั‚ะฐ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ, ะฐะปะต ะฒะพะฝะธ ะฝะต ะฝะฐะฒโ€™ัะทัƒัŽั‚ัŒ ะบะพะฝะบั€ะตั‚ะฝะธะน ะฟั–ะดั…ั–ะด ะดะพ ะพะฑั€ะพะฑะบะธ ั†ะธั… ะบะพะฝั†ะตะฟั†ั–ะน ั€ะพะทะณะพั€ั‚ะฐะฝะฝั, ั– ั–ัะฝัƒั” ะบั–ะปัŒะบะฐ ะผะพะถะปะธะฒะธั… ัั‚ั€ะฐั‚ะตะณั–ะน. + +ะ“ะฐั€ะฝะฐ ะฝะพะฒะธะฝะฐ ะฟะพะปัะณะฐั” ะฒ ั‚ะพะผัƒ, ั‰ะพ ะดะปั ะบะพะถะฝะพั— ัั‚ั€ะฐั‚ะตะณั–ั— ั” ัะฟะพัั–ะฑ ะฟะพะบั€ะธั‚ะธ ะฒัั– ะบะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. ๐ŸŽ‰ + +ะ ะพะทะณะปัะฝัŒะผะพ ั†ั– ะบะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะฒ ะบะพะฝั‚ะตะบัั‚ั– ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ: + +* HTTPS +* ะะฒั‚ะพะทะฐะฟัƒัะบ +* ะŸะตั€ะตะทะฐะฟัƒัะบะธ +* ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +* ะŸะฐะผโ€™ัั‚ัŒ +* ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ + +## HTTPS { #https } + +ะฏะบั‰ะพ ะทะพัะตั€ะตะดะธั‚ะธััŒ ะปะธัˆะต ะฝะฐ ะพะฑั€ะฐะทั– ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะดะปั ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI (ะฐ ะทะณะพะดะพะผ ะฝะฐ ะทะฐะฟัƒั‰ะตะฝะพะผัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–), HTTPS ะทะฐะทะฒะธั‡ะฐะน ะพะฑั€ะพะฑะปัั”ั‚ัŒัั ะทะพะฒะฝั–ัˆะฝั–ะผ ั–ะฝัˆะธะผ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะพะผ. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ั–ะฝัˆะธะน ะบะพะฝั‚ะตะนะฝะตั€, ะฝะฐะฟั€ะธะบะปะฐะด ะท Traefik, ั‰ะพ ะพะฑั€ะพะฑะปัั” HTTPS ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะพั‚ั€ะธะผะฐะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +Traefik ะผะฐั” ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะท Docker, Kubernetes ั‚ะฐ ั–ะฝัˆะธะผะธ, ั‚ะพะถ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั– ัะบะพะฝั„ั–ะณัƒั€ัƒะฒะฐั‚ะธ HTTPS ะดะปั ะฒะฐัˆะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ะท ะฝะธะผ ะดัƒะถะต ะฟั€ะพัั‚ะพ. + +/// + +ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะพ, HTTPS ะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธััŒ ั…ะผะฐั€ะฝะธะผ ะฟั€ะพะฒะฐะนะดะตั€ะพะผ ัะบ ะพะดะธะฝ ะท ั—ั…ะฝั–ั… ัะตั€ะฒั–ัั–ะฒ (ะฟั€ะธ ั†ัŒะพะผัƒ ะทะฐัั‚ะพััƒะฝะพะบ ัƒัะต ั‰ะต ะฟั€ะฐั†ัŽั” ะฒ ะบะพะฝั‚ะตะนะฝะตั€ั–). + +## ะะฒั‚ะพะทะฐะฟัƒัะบ ั– ะฟะตั€ะตะทะฐะฟัƒัะบะธ { #running-on-startup-and-restarts } + +ะ—ะฐะทะฒะธั‡ะฐะน ั–ะฝัˆะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฐ ะทะฐะฟัƒัะบ ั– ะฒะธะบะพะฝะฐะฝะฝั ะฒะฐัˆะพะณะพ ะบะพะฝั‚ะตะนะฝะตั€ะฐ. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ Docker, Docker Compose, Kubernetes, ั…ะผะฐั€ะฝะธะน ัะตั€ะฒั–ั ั‚ะพั‰ะพ. + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– (ะฐะฑะพ ะฒัั–ั…) ะฒะธะฟะฐะดะบั–ะฒ ั” ะฟั€ะพัั‚ะฐ ะพะฟั†ั–ั, ั‰ะพะฑ ัƒะฒั–ะผะบะฝัƒั‚ะธ ะทะฐะฟัƒัะบ ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะฟั€ะธ ัั‚ะฐั€ั‚ั– ัะธัั‚ะตะผะธ ั‚ะฐ ะฟะตั€ะตะทะฐะฟัƒัะบะธ ัƒ ั€ะฐะทั– ะทะฑะพั—ะฒ. ะะฐะฟั€ะธะบะปะฐะด, ัƒ Docker ั†ะต ะพะฟั†ั–ั ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--restart`. + +ะ‘ะตะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ะทะผัƒัะธั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ ะทะฐะฟัƒัะบะฐั‚ะธัั ะฟั€ะธ ัั‚ะฐั€ั‚ั– ัะธัั‚ะตะผะธ ั‚ะฐ ะท ะฟะตั€ะตะทะฐะฟัƒัะบะฐะผะธ ะผะพะถะต ะฑัƒั‚ะธ ะบะปะพะฟั–ั‚ะฝะพ ั– ัะบะปะฐะดะฝะพ. ะะปะต ะฟั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ัƒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ั†ั ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ ะฒะฑัƒะดะพะฒะฐะฝะฐ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. โœจ + +## ะ ะตะฟะปั–ะบะฐั†ั–ั - ะบั–ะปัŒะบั–ัั‚ัŒ ะฟั€ะพั†ะตัั–ะฒ { #replication-number-of-processes } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” ะบะปะฐัั‚ะตั€ ะผะฐัˆะธะฝ ั–ะท Kubernetes, Docker Swarm Mode, Nomad ะฐะฑะพ ั–ะฝัˆะพัŽ ะฟะพะดั–ะฑะฝะพัŽ ัะบะปะฐะดะฝะพัŽ ัะธัั‚ะตะผะพัŽ ะดะปั ะบะตั€ัƒะฒะฐะฝะฝั ั€ะพะทะฟะพะดั–ะปะตะฝะธะผะธ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ะฝะฐ ะบั–ะปัŒะบะพั… ะผะฐัˆะธะฝะฐั…, ั‚ะพะดั– ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต ะพะฑั€ะพะฑะปัั‚ะธ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะฝะฐ ั€ั–ะฒะฝั– ะบะปะฐัั‚ะตั€ะฐ ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะผะตะฝะตะดะถะตั€ะฐ ะฟั€ะพั†ะตัั–ะฒ (ัะบ-ะพั‚ Uvicorn ะท ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ) ัƒ ะบะพะถะฝะพะผัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–. + +ะžะดะฝะฐ ะท ั‚ะฐะบะธั… ั€ะพะทะฟะพะดั–ะปะตะฝะธั… ัะธัั‚ะตะผ ะบะตั€ัƒะฒะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ, ัะบ-ะพั‚ Kubernetes, ะทะฐะทะฒะธั‡ะฐะน ะผะฐั” ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– ัะฟะพัะพะฑะธ ะพะฑั€ะพะฑะปัั‚ะธ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, ะฟั–ะดั‚ั€ะธะผัƒัŽั‡ะธ ะฒะพะดะฝะพั‡ะฐั ะฑะฐะปะฐะฝััƒะฒะฐะฝะฝั ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะดะปั ะฒั…ั–ะดะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. ะฃัะต ั†ะต - ะฝะฐ ั€ั–ะฒะฝั– ะบะปะฐัั‚ะตั€ะฐ. + +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต ะทั–ะฑั€ะฐั‚ะธ Docker-ะพะฑั€ะฐะท ะท ะฝัƒะปั, ัะบ [ะฟะพััะฝะตะฝะพ ะฒะธั‰ะต](#dockerfile), ะฒัั‚ะฐะฝะพะฒะธะฒัˆะธ ะฒะฐัˆั– ะทะฐะปะตะถะฝะพัั‚ั– ั– ะทะฐะฟัƒัั‚ะธะฒัˆะธ ะพะดะธะฝ ะฟั€ะพั†ะตั Uvicorn ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะบั–ะปัŒะบะพั… ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ Uvicorn. + +### ะ‘ะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั { #load-balancer } + +ะŸั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ะทะฐะทะฒะธั‡ะฐะน ั” ัะบะธะนััŒ ะบะพะผะฟะพะฝะตะฝั‚, ั‰ะพ ัะปัƒั…ะฐั” ะฝะฐ ะณะพะปะพะฒะฝะพะผัƒ ะฟะพั€ั‚ัƒ. ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ั–ะฝัˆะธะน ะบะพะฝั‚ะตะนะฝะตั€, ัะบะธะน ั‚ะฐะบะพะถ ั” ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ ะท ั‚ะตั€ะผั–ะฝะฐั†ั–ั”ัŽ TLS ะดะปั ะพะฑั€ะพะฑะบะธ HTTPS, ะฐะฑะพ ะฟะพะดั–ะฑะฝะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚. + +ะžัะบั–ะปัŒะบะธ ั†ะตะน ะบะพะผะฟะพะฝะตะฝั‚ ะฟั€ะธะนะผะฐั” ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะทะฐะฟะธั‚ั–ะฒ ั– ั€ะพะทะฟะพะดั–ะปัั” ะนะพะณะพ ะผั–ะถ ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ (ัะฟะพะดั–ะฒะฐั”ะผะพััŒ) ะทะฑะฐะปะฐะฝัะพะฒะฐะฝะพ, ะนะพะณะพ ั‚ะฐะบะพะถ ั‡ะฐัั‚ะพ ะฝะฐะทะธะฒะฐัŽั‚ัŒ ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบะพะผ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขะพะน ัะฐะผะธะน ะบะพะผะฟะพะฝะตะฝั‚ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ ะท ั‚ะตั€ะผั–ะฝะฐั†ั–ั”ัŽ TLS, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะดะปั HTTPS, ัˆะฒะธะดัˆะต ะทะฐ ะฒัะต, ั‚ะฐะบะพะถ ะฑัƒะดะต ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบะพะผ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั. + +/// + +ะ† ะฟั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ั‚ะฐ ัะฐะผะฐ ัะธัั‚ะตะผะฐ, ัะบัƒ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะดะปั ั—ั… ะทะฐะฟัƒัะบัƒ ั– ะบะตั€ัƒะฒะฐะฝะฝั ะฝะธะผะธ, ะฒะถะต ะผะฐั‚ะธะผะต ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะดะปั ะฟะตั€ะตะดะฐะฒะฐะฝะฝั ะผะตั€ะตะถะตะฒะพั— ะบะพะผัƒะฝั–ะบะฐั†ั–ั— (ะฝะฐะฟั€ะธะบะปะฐะด, HTTP-ะทะฐะฟะธั‚ั–ะฒ) ะฒั–ะด ั†ัŒะพะณะพ ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบะฐ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั (ัะบะธะน ั‚ะฐะบะพะถ ะผะพะถะต ะฑัƒั‚ะธ ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะพะผ ะท ั‚ะตั€ะผั–ะฝะฐั†ั–ั”ัŽ TLS) ะดะพ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั–ะท ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ. + +### ะžะดะธะฝ ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั - ะบั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ { #one-load-balancer-multiple-worker-containers } + +ะŸั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะท Kubernetes ะฐะฑะพ ะฟะพะดั–ะฑะฝะธะผะธ ั€ะพะทะฟะพะดั–ะปะตะฝะธะผะธ ัะธัั‚ะตะผะฐะผะธ ะบะตั€ัƒะฒะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั—ั…ะฝั–ั… ะฒะฝัƒั‚ั€ั–ัˆะฝั–ั… ะผะตั€ะตะถะตะฒะธั… ะผะตั…ะฐะฝั–ะทะผั–ะฒ ะดะพะทะฒะพะปัั” ั”ะดะธะฝะพะผัƒ ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบัƒ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั, ั‰ะพ ัะปัƒั…ะฐั” ะฝะฐ ะณะพะปะพะฒะฝะพะผัƒ ะฟะพั€ั‚ัƒ, ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ (ะทะฐะฟะธั‚ะธ) ะดะพ ะบั–ะปัŒะบะพั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, ัƒ ัะบะธั… ะทะฐะฟัƒั‰ะตะฝะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ. + +ะšะพะถะตะฝ ะท ั†ะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั–ะท ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ ะทะฐะทะฒะธั‡ะฐะน ะผะฐั” ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั€ะพั†ะตั Uvicorn, ั‰ะพ ะทะฐะฟัƒัะบะฐั” ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI). ะฃัั– ะฒะพะฝะธ ะฑัƒะดัƒั‚ัŒ ั–ะดะตะฝั‚ะธั‡ะฝะธะผะธ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ, ัะบั– ะทะฐะฟัƒัะบะฐัŽั‚ัŒ ั‚ะต ัะฐะผะต, ะฐะปะต ะบะพะถะตะฝ ะทั– ัะฒะพั—ะผ ะฟั€ะพั†ะตัะพะผ, ะฟะฐะผโ€™ัั‚ั‚ัŽ ั‚ะพั‰ะพ. ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะฒะธ ะฒะธะบะพั€ะธัั‚ะฐั”ั‚ะต ะฟะตั€ะตะฒะฐะณะธ ะฟะฐั€ะฐะปะตะปั–ะทะผัƒ ะฝะฐ ั€ั–ะทะฝะธั… ัะดั€ะฐั… ะฟั€ะพั†ะตัะพั€ะฐ ะฐะฑะพ ะฝะฐะฒั–ั‚ัŒ ะฝะฐ ั€ั–ะทะฝะธั… ะผะฐัˆะธะฝะฐั…. + +ะ ั€ะพะทะฟะพะดั–ะปะตะฝะฐ ัะธัั‚ะตะผะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั–ะท ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบะพะผ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ั€ะพะทะฟะพะดั–ะปัั‚ะธะผะต ะทะฐะฟะธั‚ะธ ะผั–ะถ ะบะพะถะฝะธะผ ั–ะท ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ั–ะท ะฒะฐัˆะธะผ ะทะฐัั‚ะพััƒะฝะบะพะผ ะฟะพ ั‡ะตั€ะทั–. ะขะพะถ ะบะพะถะตะฝ ะทะฐะฟะธั‚ ะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธัั ะพะดะฝะธะผ ั–ะท ะบั–ะปัŒะบะพั… ั€ะตะฟะปั–ะบะพะฒะฐะฝะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, ั‰ะพ ะทะฐะฟัƒัะบะฐัŽั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ. + +ะ† ะทะฐะทะฒะธั‡ะฐะน ั†ะตะน ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั ะทะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธ ะทะฐะฟะธั‚ะธ, ัะบั– ะนะดัƒั‚ัŒ ะดะพ ั–ะฝัˆะธั… ะทะฐัั‚ะพััƒะฝะบั–ะฒ ัƒ ะฒะฐัˆะพะผัƒ ะบะปะฐัั‚ะตั€ั– (ะฝะฐะฟั€ะธะบะปะฐะด, ะดะพ ั–ะฝัˆะพะณะพ ะดะพะผะตะฝัƒ ะฐะฑะพ ะฟั–ะด ั–ะฝัˆะธะผ ะฟั€ะตั„ั–ะบัะพะผ ัˆะปัั…ัƒ URL), ั– ะฟะตั€ะตะดะฐะฒะฐั‚ะธะผะต ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ะดะพ ะฒั–ะดะฟะพะฒั–ะดะฝะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ ะดะปั ั‚ะพะณะพ ั–ะฝัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ะฟั€ะฐั†ัŽั” ัƒ ะฒะฐัˆะพะผัƒ ะบะปะฐัั‚ะตั€ั–. + +### ะžะดะธะฝ ะฟั€ะพั†ะตั ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€ { #one-process-per-container } + +ะฃ ั‚ะฐะบะพะผัƒ ัั†ะตะฝะฐั€ั–ั— ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะพะดะธะฝ (Uvicorn) ะฟั€ะพั†ะตั ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€, ะฐะดะถะต ะฒะธ ะฒะถะต ะพะฑั€ะพะฑะปัั”ั‚ะต ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะฝะฐ ั€ั–ะฒะฝั– ะบะปะฐัั‚ะตั€ะฐ. + +ะขะพะฑั‚ะพ ะฒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะธ ะฝะต ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะบั–ะปัŒะบะพั… ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–, ะฝะฐะฟั€ะธะบะปะฐะด ั‡ะตั€ะตะท ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`. ะ’ะธ ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั Uvicorn ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€ (ะฐะปะต, ะนะผะพะฒั–ั€ะฝะพ, ะบั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ). + +ะะฐัะฒะฝั–ัั‚ัŒ ั–ะฝัˆะพะณะพ ะผะตะฝะตะดะถะตั€ะฐ ะฟั€ะพั†ะตัั–ะฒ ะฒัะตั€ะตะดะธะฝั– ะบะพะฝั‚ะตะนะฝะตั€ะฐ (ัะบ ั†ะต ะฑัƒะปะพ ะฑ ั–ะท ะบั–ะปัŒะบะพะผะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ) ะปะธัˆะต ะดะพะดะฐัั‚ัŒ ะทะฐะนะฒะพั— ัะบะปะฐะดะฝะพัั‚ั–, ัะบัƒ, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะฒะธ ะฒะถะต ะฒะธั€ั–ัˆัƒั”ั‚ะต ะฝะฐ ั€ั–ะฒะฝั– ะบะปะฐัั‚ะตั€ะฐ. + +### ะšะพะฝั‚ะตะนะฝะตั€ะธ ะท ะบั–ะปัŒะบะพะผะฐ ะฟั€ะพั†ะตัะฐะผะธ ั‚ะฐ ะพัะพะฑะปะธะฒั– ะฒะธะฟะฐะดะบะธ { #containers-with-multiple-processes-and-special-cases } + +ะ—ะฒั–ัะฝะพ, ั” ะพัะพะฑะปะธะฒั– ะฒะธะฟะฐะดะบะธ, ะบะพะปะธ ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะผะฐั‚ะธ ะบะพะฝั‚ะตะนะฝะตั€ ั–ะท ะบั–ะปัŒะบะพะผะฐ ะฟั€ะพั†ะตัะฐะผะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ Uvicorn ะฒัะตั€ะตะดะธะฝั–. + +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`, ั‰ะพะฑ ะทะฐะดะฐั‚ะธ ะบั–ะปัŒะบั–ัั‚ัŒ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ, ัะบะธั… ะฟะพั‚ั€ั–ะฑะฝะพ ะทะฐะฟัƒัั‚ะธั‚ะธ: + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`, ั‰ะพะฑ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะบั–ะปัŒะบั–ัั‚ัŒ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ 4. + +ะžััŒ ะบั–ะปัŒะบะฐ ะฟั€ะธะบะปะฐะดั–ะฒ, ะบะพะปะธ ั†ะต ะผะพะถะต ะผะฐั‚ะธ ัะตะฝั: + +#### ะŸั€ะพัั‚ะธะน ะทะฐัั‚ะพััƒะฝะพะบ { #a-simple-app } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะผะตะฝะตะดะถะตั€ ะฟั€ะพั†ะตัั–ะฒ ัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–, ัะบั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะดะพัั‚ะฐั‚ะฝัŒะพ ะฟั€ะพัั‚ะธะน, ั‰ะพะฑ ะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ะฝะฐ ะพะดะฝะพะผัƒ ัะตั€ะฒะตั€ั–, ะฐ ะฝะต ะฝะฐ ะบะปะฐัั‚ะตั€ั–. + +#### Docker Compose { #docker-compose } + +ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะฝะฐ ะพะดะฝะพะผัƒ ัะตั€ะฒะตั€ั– (ะฝะต ะฒ ะบะปะฐัั‚ะตั€ั–) ะทะฐ ะดะพะฟะพะผะพะณะพัŽ Docker Compose, ั‚ะพะถ ัƒ ะฒะฐั ะฝะต ะฑัƒะดะต ะฟั€ะพัั‚ะพะณะพ ัะฟะพัะพะฑัƒ ะบะตั€ัƒะฒะฐั‚ะธ ั€ะตะฟะปั–ะบะฐั†ั–ั”ัŽ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ (ัƒ Docker Compose), ะทะฑะตั€ั–ะณะฐัŽั‡ะธ ัะฟั–ะปัŒะฝัƒ ะผะตั€ะตะถัƒ ั‚ะฐ ะฑะฐะปะฐะฝััƒะฒะฐะฝะฝั ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั. + +ะขะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะผะฐั‚ะธ ะพะดะธะฝ ะบะพะฝั‚ะตะนะฝะตั€ ั–ะท ะผะตะฝะตะดะถะตั€ะพะผ ะฟั€ะพั†ะตัั–ะฒ, ั‰ะพ ะทะฐะฟัƒัะบะฐั” ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ะฒัะตั€ะตะดะธะฝั–. + +--- + +ะ“ะพะปะพะฒะฝะฐ ะดัƒะผะบะฐ: ั†ะต ะฝะต ะฟั€ะฐะฒะธะปะฐ, ะฒะธะบะฐั€ะฑัƒะฒะฐะฝั– ะฒ ะบะฐะผะตะฝั–, ัะบะธั… ะฟะพั‚ั€ั–ะฑะฝะพ ัะปั–ะฟะพ ะดะพั‚ั€ะธะผัƒะฒะฐั‚ะธัั. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ั– ั–ะดะตั—, ั‰ะพะฑ ะพั†ั–ะฝะธั‚ะธ ะฒะปะฐัะฝะธะน ะบะตะนั ั– ะฒะธั€ั–ัˆะธั‚ะธ, ัะบะธะน ะฟั–ะดั…ั–ะด ะฝะฐะนะบั€ะฐั‰ะธะน ะดะปั ะฒะฐัˆะพั— ัะธัั‚ะตะผะธ, ั€ะพะทะณะปัะดะฐัŽั‡ะธ, ัะบ ะบะตั€ัƒะฒะฐั‚ะธ ั‚ะฐะบะธะผะธ ะบะพะฝั†ะตะฟั†ั–ัะผะธ: + +* ะ‘ะตะทะฟะตะบะฐ - HTTPS +* ะะฒั‚ะพะทะฐะฟัƒัะบ +* ะŸะตั€ะตะทะฐะฟัƒัะบะธ +* ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +* ะŸะฐะผโ€™ัั‚ัŒ +* ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ + +## ะŸะฐะผโ€™ัั‚ัŒ { #memory } + +ะฏะบั‰ะพ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€, ะฒะธ ะผะฐั‚ะธะผะตั‚ะต ะฑั–ะปัŒัˆ-ะผะตะฝัˆ ั‡ั–ั‚ะบะพ ะฒะธะทะฝะฐั‡ะตะฝะธะน, ัั‚ะฐะฑั–ะปัŒะฝะธะน ั– ะพะฑะผะตะถะตะฝะธะน ะพะฑััะณ ะฟะฐะผโ€™ัั‚ั–, ั‰ะพ ัะฟะพะถะธะฒะฐั”ั‚ัŒัั ะบะพะถะฝะธะผ ั–ะท ั†ะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ (ั—ั… ะผะพะถะต ะฑัƒั‚ะธ ะฑั–ะปัŒัˆะต ะพะดะฝะพะณะพ, ัะบั‰ะพ ะฒะพะฝะธ ั€ะตะฟะปั–ะบะพะฒะฐะฝั–). + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ั‚ั– ัะฐะผั– ะปั–ะผั–ั‚ะธ ั‚ะฐ ะฒะธะผะพะณะธ ะดะพ ะฟะฐะผโ€™ัั‚ั– ัƒ ะฒะฐัˆะธั… ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ัั… ะดะปั ัะธัั‚ะตะผะธ ะบะตั€ัƒะฒะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ Kubernetes). ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะฒะพะฝะฐ ะทะผะพะถะต ั€ะตะฟะปั–ะบัƒะฒะฐั‚ะธ ะบะพะฝั‚ะตะนะฝะตั€ะธ ะฝะฐ ะดะพัั‚ัƒะฟะฝะธั… ะผะฐัˆะธะฝะฐั…, ะฒั€ะฐั…ะพะฒัƒัŽั‡ะธ ะพะฑััะณ ะฟะฐะผโ€™ัั‚ั–, ะฟะพั‚ั€ั–ะฑะฝะธะน ั—ะผ, ั– ะพะฑััะณ ะดะพัั‚ัƒะฟะฝะพั— ะฟะฐะผโ€™ัั‚ั– ะฝะฐ ะผะฐัˆะธะฝะฐั… ัƒ ะบะปะฐัั‚ะตั€ั–. + +ะฏะบั‰ะพ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะฟั€ะพัั‚ะธะน, ั–ะผะพะฒั–ั€ะฝะพ, ั†ะต ะฝะต ะฑัƒะดะต ะฟั€ะพะฑะปะตะผะพัŽ, ั– ะฒะฐะผ ะผะพะถะต ะฝะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะทะฐะดะฐะฒะฐั‚ะธ ะถะพั€ัั‚ะบั– ะปั–ะผั–ั‚ะธ ะฟะฐะผโ€™ัั‚ั–. ะะปะต ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฑะฐะณะฐั‚ะพ ะฟะฐะผโ€™ัั‚ั– (ะฝะฐะฟั€ะธะบะปะฐะด, ั–ะท ะผะพะดะตะปัะผะธ ะผะฐัˆะธะฝะฝะพะณะพ ะฝะฐะฒั‡ะฐะฝะฝั), ะฒะฐะผ ัะปั–ะด ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ัะบั–ะปัŒะบะธ ะฟะฐะผโ€™ัั‚ั– ะฒะธ ัะฟะพะถะธะฒะฐั”ั‚ะต, ั– ะฒั–ะดะบะพั€ะธะณัƒะฒะฐั‚ะธ ะบั–ะปัŒะบั–ัั‚ัŒ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, ั‰ะพ ะทะฐะฟัƒัะบะฐัŽั‚ัŒัั ะฝะฐ ะบะพะถะฝั–ะน ะผะฐัˆะธะฝั– (ั–, ะผะพะถะปะธะฒะพ, ะดะพะดะฐั‚ะธ ะฑั–ะปัŒัˆะต ะผะฐัˆะธะฝ ัƒ ะฒะฐัˆ ะบะปะฐัั‚ะตั€). + +ะฏะบั‰ะพ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ ะฝะต ัะฟะพะถะธะฒะฐั” ะฑั–ะปัŒัˆะต ะฟะฐะผโ€™ัั‚ั–, ะฝั–ะถ ะดะพัั‚ัƒะฟะฝะพ. + +## ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ั– ะบะพะฝั‚ะตะนะฝะตั€ะธ { #previous-steps-before-starting-and-containers } + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะพะฝั‚ะตะนะฝะตั€ะธ (ะฝะฐะฟั€ะธะบะปะฐะด, Docker, Kubernetes), ั‚ะพ ั” ะดะฒะฐ ะพัะฝะพะฒะฝั– ะฟั–ะดั…ะพะดะธ. + +### ะšั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ { #multiple-containers } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ะบั–ะปัŒะบะฐ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ, ั–ะผะพะฒั–ั€ะฝะพ ะบะพะถะตะฝ ะทะฐะฟัƒัะบะฐั” ะพะดะธะฝ ะฟั€ะพั†ะตั (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะบะปะฐัั‚ะตั€ั– Kubernetes), ั‚ะพะดั– ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ะพะบั€ะตะผะธะน ะบะพะฝั‚ะตะนะฝะตั€, ัะบะธะน ะฒะธะบะพะฝะฐั” ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฒ ะพะดะฝะพะผัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–, ะทะฐะฟัƒัั‚ะธะฒัˆะธ ะพะดะธะฝ ะฟั€ะพั†ะตั, ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ั€ะตะฟะปั–ะบะพะฒะฐะฝะธั… ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Kubernetes, ั†ะต, ะนะผะพะฒั–ั€ะฝะพ, ะฑัƒะดะต Init Container. + +/// + +ะฏะบั‰ะพ ัƒ ะฒะฐัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฝะตะผะฐั” ะฟั€ะพะฑะปะตะผะธ ะทะฐะฟัƒัะบะฐั‚ะธ ั†ั– ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ ะฟะฐั€ะฐะปะตะปัŒะฝะพ (ะฝะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒะธ ะฝะต ะฒะธะบะพะฝัƒั”ั‚ะต ะผั–ะณั€ะฐั†ั–ั— ะฑะฐะทะธ ะดะฐะฝะธั…, ะฐ ะปะธัˆะต ะฟะตั€ะตะฒั–ั€ัั”ั‚ะต, ั‡ะธ ะฑะฐะทะฐ ะฒะถะต ะณะพั‚ะพะฒะฐ), ั‚ะพะดั– ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฟะพะผั–ัั‚ะธั‚ะธ ั—ั… ัƒ ะบะพะถะตะฝ ะบะพะฝั‚ะตะนะฝะตั€ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะณะพะปะพะฒะฝะพะณะพ ะฟั€ะพั†ะตััƒ. + +### ะžะดะธะฝ ะบะพะฝั‚ะตะนะฝะตั€ { #single-container } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ะฟั€ะพัั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะท ะพะดะฝะธะผ ะบะพะฝั‚ะตะนะฝะตั€ะพะผ, ัะบะธะน ะฟะพั‚ั–ะผ ะทะฐะฟัƒัะบะฐั” ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ (ะฐะฑะพ ั‚ะตะถ ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั), ั‚ะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพะฝะฐั‚ะธ ั†ั– ะฟะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฒ ั‚ะพะผัƒ ะถ ะบะพะฝั‚ะตะนะฝะตั€ั– ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ ะฟั€ะพั†ะตััƒ ั–ะท ะทะฐัั‚ะพััƒะฝะบะพะผ. + +### ะ‘ะฐะทะพะฒะธะน ะพะฑั€ะฐะท Docker { #base-docker-image } + +ะšะพะปะธััŒ ั–ัะฝัƒะฒะฐะฒ ะพั„ั–ั†ั–ะนะฝะธะน ะพะฑั€ะฐะท Docker ะดะปั FastAPI: tiangolo/uvicorn-gunicorn-fastapi. ะะปะต ะทะฐั€ะฐะท ะฒั–ะฝ ะทะฐัั‚ะฐั€ั–ะปะธะน. โ›”๏ธ + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะฐะผ ะฝะต ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ะตะน ะฑะฐะทะพะฒะธะน ะพะฑั€ะฐะท Docker (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะฟะพะดั–ะฑะฝะธะน). + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Kubernetes (ะฐะฑะพ ั–ะฝัˆั–) ั– ะฒะถะต ะฝะฐะปะฐัˆั‚ะพะฒัƒั”ั‚ะต ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะฝะฐ ั€ั–ะฒะฝั– ะบะปะฐัั‚ะตั€ะฐ ะท ะบั–ะปัŒะบะพะผะฐ ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ. ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะบั€ะฐั‰ะต ะทั–ะฑั€ะฐั‚ะธ ะพะฑั€ะฐะท ะท ะฝัƒะปั, ัะบ ะพะฟะธัะฐะฝะพ ะฒะธั‰ะต: [ะ—ั–ะฑั€ะฐั‚ะธ Docker-ะพะฑั€ะฐะท ะดะปั FastAPI](#build-a-docker-image-for-fastapi). + +ะ ัะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะผะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฟั†ั–ัŽ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะฆะตะน ะพะฑั€ะฐะท Docker ะฑัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ ั‚ะพะดั–, ะบะพะปะธ Uvicorn ะฝะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐะฒ ะบะตั€ัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะตั€ะตะทะฐะฟัƒัะบ ยซะผะตั€ั‚ะฒะธั…ยป ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ, ั‚ะพะผัƒ ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะปะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Gunicorn ะท Uvicorn, ั‰ะพ ะดะพะดะฐะฒะฐะปะพ ั‡ะธะผะฐะปะพ ัะบะปะฐะดะฝะพัั‚ั– ะปะธัˆะต ะดะปั ั‚ะพะณะพ, ั‰ะพะฑ Gunicorn ะบะตั€ัƒะฒะฐะฒ ั‚ะฐ ะฟะตั€ะตะทะฐะฟัƒัะบะฐะฒ ะฟั€ะพั†ะตัะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะธ Uvicorn. + +ะะปะต ั‚ะตะฟะตั€, ะบะพะปะธ Uvicorn (ั– ะบะพะผะฐะฝะดะฐ `fastapi`) ะฟั–ะดั‚ั€ะธะผัƒัŽั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `--workers`, ะฝะตะผะฐั” ะฟั€ะธั‡ะธะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑะฐะทะพะฒะธะน ะพะฑั€ะฐะท Docker ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะทั–ะฑั€ะฐั‚ะธ ะฒะปะฐัะฝะธะน (ั†ะต ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐ ัะฐะผะฐ ะบั–ะปัŒะบั–ัั‚ัŒ ะบะพะดัƒ ๐Ÿ˜…). + +/// + +## ะ ะพะทะณะพั€ะฝัƒั‚ะธ ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ { #deploy-the-container-image } + +ะŸั–ัะปั ะพั‚ั€ะธะผะฐะฝะฝั ะพะฑั€ะฐะทัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ (Docker) ั” ะบั–ะปัŒะบะฐ ัะฟะพัะพะฑั–ะฒ ะนะพะณะพ ั€ะพะทะณะพั€ะฝัƒั‚ะธ. + +ะะฐะฟั€ะธะบะปะฐะด: + +* ะ— Docker Compose ะฝะฐ ะพะดะฝะพะผัƒ ัะตั€ะฒะตั€ั– +* ะ— ะบะปะฐัั‚ะตั€ะพะผ Kubernetes +* ะ— ะบะปะฐัั‚ะตั€ะพะผ Docker Swarm Mode +* ะ— ั–ะฝัˆะธะผ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะพะผ, ัะบ-ะพั‚ Nomad +* ะ— ั…ะผะฐั€ะฝะธะผ ัะตั€ะฒั–ัะพะผ, ัะบะธะน ะฑะตั€ะต ะฒะฐัˆ ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ั– ั€ะพะทะณะพั€ั‚ะฐั” ะนะพะณะพ + +## ะžะฑั€ะฐะท Docker ะท `uv` { #docker-image-with-uv } + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต uv ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ั‚ะฐ ะบะตั€ัƒะฒะฐะฝะฝั ะฒะฐัˆะธะผ ะฟั€ะพั”ะบั‚ะพะผ, ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ั—ั…ะฝั–ะผ ะฟะพัั–ะฑะฝะธะบะพะผ Docker ะดะปั uv. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัะธัั‚ะตะผะธ ะบะพะฝั‚ะตะนะฝะตั€ั–ะฒ (ะฝะฐะฟั€ะธะบะปะฐะด, ะท Docker ั– Kubernetes), ะดะพัะธั‚ัŒ ะฟั€ะพัั‚ะพ ะพะฑั€ะพะฑะปัั‚ะธ ะฒัั– ะบะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั: + +* HTTPS +* ะะฒั‚ะพะทะฐะฟัƒัะบ +* ะŸะตั€ะตะทะฐะฟัƒัะบะธ +* ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +* ะŸะฐะผโ€™ัั‚ัŒ +* ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฝะต ะทะฐั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบะธะน ะฑะฐะทะพะฒะธะน ะพะฑั€ะฐะท, ะฐ ะฝะฐั‚ะพะผั–ัั‚ัŒ ะทั–ะฑั€ะฐั‚ะธ ะพะฑั€ะฐะท ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะท ะฝัƒะปั ะฝะฐ ะพัะฝะพะฒั– ะพั„ั–ั†ั–ะนะฝะพะณะพ ะพะฑั€ะฐะทัƒ Python ะดะปั Docker. + +ะ”ะพั‚ั€ะธะผัƒัŽั‡ะธััŒ ะฟะพั€ัะดะบัƒ ั–ะฝัั‚ั€ัƒะบั†ั–ะน ัƒ `Dockerfile` ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะบะตัˆ Docker, ะฒะธ ะผะพะถะตั‚ะต ะผั–ะฝั–ะผั–ะทัƒะฒะฐั‚ะธ ั‡ะฐั ะทะฑั–ั€ะบะธ, ั‰ะพะฑ ะผะฐะบัะธะผั–ะทัƒะฒะฐั‚ะธ ัะฒะพัŽ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ (ั– ัƒะฝะธะบะฝัƒั‚ะธ ะฝัƒะดัŒะณะธ). ๐Ÿ˜Ž diff --git a/docs/uk/docs/deployment/fastapicloud.md b/docs/uk/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000..4b4f3e59be --- /dev/null +++ b/docs/uk/docs/deployment/fastapicloud.md @@ -0,0 +1,65 @@ +# FastAPI Cloud { #fastapi-cloud } + +ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ะฝัƒั‚ะธ ัะฒั–ะน ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ะฝะฐ FastAPI Cloud ะพะดะฝั–ั”ัŽ ะบะพะผะฐะฝะดะพัŽ, ะฟั€ะธั”ะดะฝัƒะนั‚ะตััŒ ะดะพ ัะฟะธัะบัƒ ะพั‡ั–ะบัƒะฒะฐะฝะฝั, ัะบั‰ะพ ั‰ะต ะฝั–. ๐Ÿš€ + +## ะ’ั…ั–ะด { #login } + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ัƒ ะฒะฐั ะฒะถะต ั” ะพะฑะปั–ะบะพะฒะธะน ะทะฐะฟะธั **FastAPI Cloud** (ะผะธ ะทะฐะฟั€ะพัะธะปะธ ะฒะฐั ะทั– ัะฟะธัะบัƒ ะพั‡ั–ะบัƒะฒะฐะฝะฝั ๐Ÿ˜‰). + +ะŸะพั‚ั–ะผ ัƒะฒั–ะนะดั–ั‚ัŒ: + +
+ +```console +$ fastapi login + +You are logged in to FastAPI Cloud ๐Ÿš€ +``` + +
+ +## ะ ะพะทะณะพั€ั‚ะฐะฝะฝั { #deploy } + +ะขะตะฟะตั€ ั€ะพะทะณะพั€ะฝั–ั‚ัŒ ัะฒั–ะน ะทะฐัั‚ะพััƒะฝะพะบ ะพะดะฝั–ั”ัŽ ะบะพะผะฐะฝะดะพัŽ: + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +โœ… Deployment successful! + +๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +ะžััŒ ั– ะฒัะต! ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ัะฒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะทะฐ ั†ะธะผ URL. โœจ + +## ะŸั€ะพ FastAPI Cloud { #about-fastapi-cloud } + +**FastAPI Cloud** ัั‚ะฒะพั€ะตะฝะพ ั‚ะธะผ ัะฐะผะธะผ ะฐะฒั‚ะพั€ะพะผ ั– ะบะพะผะฐะฝะดะพัŽ, ั‰ะพ ัั‚ะพั—ั‚ัŒ ะทะฐ **FastAPI**. + +ะ’ั–ะฝ ัะฟั€ะพั‰ัƒั” ะฟั€ะพั†ะตั **ัั‚ะฒะพั€ะตะฝะฝั**, **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั** ั‚ะฐ **ะดะพัั‚ัƒะฟัƒ** ะดะพ API ะท ะผั–ะฝั–ะผะฐะปัŒะฝะธะผะธ ะทัƒัะธะปะปัะผะธ. + +ะ’ั–ะฝ ะฟะตั€ะตะฝะพัะธั‚ัŒ ั‚ะพะน ัะฐะผะธะน **ะดะพัะฒั–ะด ั€ะพะทั€ะพะฑะฝะธะบะฐ**, ั‰ะพ ั– ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะท FastAPI, ะฝะฐ ั—ั… **ั€ะพะทะณะพั€ั‚ะฐะฝะฝั** ัƒ ั…ะผะฐั€ั–. ๐ŸŽ‰ + +ะ’ั–ะฝ ั‚ะฐะบะพะถ ะฟะพะดะฑะฐั” ะฟั€ะพ ะฑั–ะปัŒัˆั–ัั‚ัŒ ั€ะตั‡ะตะน, ัะบั– ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝั– ะฟั–ะด ั‡ะฐั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ, ัะบ-ะพั‚: + +- HTTPS +- ั€ะตะฟะปั–ะบะฐั†ั–ั ะท ะฐะฒั‚ะพะผะฐััˆั‚ะฐะฑัƒะฒะฐะฝะฝัะผ ะฝะฐ ะพัะฝะพะฒั– ะทะฐะฟะธั‚ั–ะฒ +- ั‚ะพั‰ะพ + +FastAPI Cloud - ะพัะฝะพะฒะฝะธะน ัะฟะพะฝัะพั€ ั– ะดะถะตั€ะตะปะพ ั„ั–ะฝะฐะฝััƒะฒะฐะฝะฝั ะดะปั ะฒั–ะดะบั€ะธั‚ะธั… ะฟั€ะพั”ะบั‚ั–ะฒ *ยซFastAPI ั‚ะฐ ะดั€ัƒะทั–ยป*. โœจ + +## ะ ะพะทะณะพั€ั‚ะฐะฝะฝั ะฒ ั–ะฝัˆะธั… ั…ะผะฐั€ะฝะธั… ะฟั€ะพะฒะฐะนะดะตั€ั–ะฒ { #deploy-to-other-cloud-providers } + +FastAPI ั” ะฒั–ะดะบั€ะธั‚ะธะผ ะบะพะดะพะผ ั– ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฐั…. ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ะฒ ะฑัƒะดัŒ-ัะบะพะณะพ ั…ะผะฐั€ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ ะทะฐ ะฒะฐัˆะธะผ ะฒะธะฑะพั€ะพะผ. + +ะ”ะพั‚ั€ะธะผัƒะนั‚ะตััŒ ั–ะฝัั‚ั€ัƒะบั†ั–ะน ะฒะฐัˆะพะณะพ ั…ะผะฐั€ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ, ั‰ะพะฑ ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ัƒ ะฝะธั…. ๐Ÿค“ + +## ะ ะพะทะณะพั€ั‚ะฐะฝะฝั ะฝะฐ ะฒะฐัˆะพะผัƒ ัะตั€ะฒะตั€ั– { #deploy-your-own-server } + +ะŸั–ะทะฝั–ัˆะต ะฒ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– **ะ ะพะทะณะพั€ั‚ะฐะฝะฝั** ั ั‚ะฐะบะพะถ ะฝะฐะฒั‡ัƒ ะฒะฐั ัƒัั–ะผ ะดะตั‚ะฐะปัะผ, ั‰ะพะฑ ะฒะธ ั€ะพะทัƒะผั–ะปะธ, ั‰ะพ ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะทั€ะพะฑะธั‚ะธ ั– ัะบ ั€ะพะทะณะพั€ั‚ะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะบะธ FastAPI ัะฐะผะพัั‚ั–ะนะฝะพ, ะทะพะบั€ะตะผะฐ ะฝะฐ ะฒะปะฐัะฝะธั… ัะตั€ะฒะตั€ะฐั…. ๐Ÿค“ diff --git a/docs/uk/docs/deployment/https.md b/docs/uk/docs/deployment/https.md new file mode 100644 index 0000000000..29329c88f0 --- /dev/null +++ b/docs/uk/docs/deployment/https.md @@ -0,0 +1,231 @@ +# ะŸั€ะพ HTTPS { #about-https } + +ะ›ะตะณะบะพ ะฟั€ะธะฟัƒัั‚ะธั‚ะธ, ั‰ะพ HTTPS - ั†ะต ั‰ะพััŒ, ั‰ะพ ะฟั€ะพัั‚ะพ ยซัƒะฒั–ะผะบะฝะตะฝะพยป ะฐะฑะพ ะฝั–. + +ะะปะต ะฒัะต ะทะฝะฐั‡ะฝะพ ัะบะปะฐะดะฝั–ัˆะต. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฟะพัะฟั–ัˆะฐั”ั‚ะต ะฐะฑะพ ั†ะต ะฝะตะฒะฐะถะปะธะฒะพ ะดะปั ะฒะฐั, ะฟะตั€ะตั…ะพะดัŒั‚ะต ะดะพ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปั–ะฒ ะดะปั ะฟะพะบั€ะพะบะพะฒะธั… ั–ะฝัั‚ั€ัƒะบั†ั–ะน ั–ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฒััŒะพะณะพ ั€ั–ะทะฝะธะผะธ ั‚ะตั…ะฝั–ะบะฐะผะธ. + +/// + +ะฉะพะฑ ะฒะธะฒั‡ะธั‚ะธ ะพัะฝะพะฒะธ HTTPS ะท ั‚ะพั‡ะบะธ ะทะพั€ัƒ ัะฟะพะถะธะฒะฐั‡ะฐ, ะฟะตั€ะตะณะปัะฝัŒั‚ะต https://howhttps.works/. + +ะขะตะฟะตั€, ะท ั‚ะพั‡ะบะธ ะทะพั€ัƒ ั€ะพะทั€ะพะฑะฝะธะบะฐ, ะพััŒ ะบั–ะปัŒะบะฐ ั€ะตั‡ะตะน, ัะบั– ะฒะฐั€ั‚ะพ ะฟะฐะผ'ัั‚ะฐั‚ะธ, ั€ะพะทะผั–ั€ะบะพะฒัƒัŽั‡ะธ ะฟั€ะพ HTTPS: + +* ะ”ะปั HTTPS ัะตั€ะฒะตั€ ะผะฐั” ะผะฐั‚ะธ ยซัะตั€ั‚ะธั„ั–ะบะฐั‚ะธยป, ะฒะธะดะฐะฝั– ั‚ั€ะตั‚ัŒะพัŽ ัั‚ะพั€ะพะฝะพัŽ. + * ะะฐัะฟั€ะฐะฒะดั– ั†ั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ยซะพั‚ั€ะธะผัƒัŽั‚ัŒััยป ัƒ ั‚ั€ะตั‚ัŒะพั— ัั‚ะพั€ะพะฝะธ, ะฐ ะฝะต ยซะณะตะฝะตั€ัƒัŽั‚ัŒััยป. +* ะกะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ะผะฐัŽั‚ัŒ ัั‚ั€ะพะบ ะดั–ั—. + * ะ‡ั…ะฝั–ะน ัั‚ั€ะพะบ ะดั–ั— ัะฟะปะธะฒะฐั”. + * ะ† ั‚ะพะดั– ั—ั… ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะฝะพะฒะธั‚ะธ, ะทะฝะพะฒัƒ ะพั‚ั€ะธะผะฐะฒัˆะธ ัƒ ั‚ั€ะตั‚ัŒะพั— ัั‚ะพั€ะพะฝะธ. +* ะจะธั„ั€ัƒะฒะฐะฝะฝั ะท'ั”ะดะฝะฐะฝะฝั ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั ะฝะฐ ั€ั–ะฒะฝั– TCP. + * ะฆะต ะพะดะธะฝ ัˆะฐั€ ะฝะธะถั‡ะต ะฒั–ะด HTTP. + * ะขะพะถ ะพะฑั€ะพะฑะบะฐ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ ั‚ะฐ ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะดะพ HTTP. +* TCP ะฝะต ะทะฝะฐั” ะฟั€ะพ ยซะดะพะผะตะฝะธยป. ะ›ะธัˆะต ะฟั€ะพ IP-ะฐะดั€ะตัะธ. + * ะ†ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะบะพะฝะบั€ะตั‚ะฝะธะน ะดะพะผะตะฝ, ัะบะธะน ะทะฐะฟะธั‚ัƒั”ั‚ัŒัั, ะผั–ัั‚ะธั‚ัŒัั ะฒ ะดะฐะฝะธั… HTTP. +* ะกะตั€ั‚ะธั„ั–ะบะฐั‚ะธ HTTPS ยซะทะฐัะฒั–ะดั‡ัƒัŽั‚ัŒยป ะฟะตะฒะฝะธะน ะดะพะผะตะฝ, ะฐะปะต ะฟั€ะพั‚ะพะบะพะป ั– ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฝะฐ ั€ั–ะฒะฝั– TCP, ะดะพ ั‚ะพะณะพ ัะบ ะฒั–ะดะพะผะพ, ะท ัะบะธะผ ะดะพะผะตะฝะพะผ ะผะฐั”ะผะพ ัะฟั€ะฐะฒัƒ. +* ะขะธะฟะพะฒะพ ั†ะต ะพะทะฝะฐั‡ะฐะปะพ ะฑ, ั‰ะพ ะฝะฐ ะพะดะฝัƒ IP-ะฐะดั€ะตััƒ ะผะพะถะฝะฐ ะผะฐั‚ะธ ะปะธัˆะต ะพะดะธะฝ ัะตั€ั‚ะธั„ั–ะบะฐั‚ HTTPS. + * ะะตะฒะฐะถะปะธะฒะพ, ะฝะฐัะบั–ะปัŒะบะธ ะฒะตะปะธะบะธะน ะฒะฐัˆ ัะตั€ะฒะตั€ ะฐะฑะพ ะฝะฐัะบั–ะปัŒะบะธ ะผะฐะปะธะน ะบะพะถะตะฝ ะทะฐัั‚ะพััƒะฝะพะบ ะฝะฐ ะฝัŒะพะผัƒ. + * ะžะดะฝะฐะบ ะดะปั ั†ัŒะพะณะพ ั” ั€ั–ัˆะตะฝะฝั. +* ะ„ ั€ะพะทัˆะธั€ะตะฝะฝั ะฟั€ะพั‚ะพะบะพะปัƒ TLS (ัะบะธะน ะพะฑั€ะพะฑะปัั” ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะฝะฐ ั€ั–ะฒะฝั– TCP, ะดะพ HTTP), ั‰ะพ ะฝะฐะทะธะฒะฐั”ั‚ัŒัั SNI. + * ะฆะต ั€ะพะทัˆะธั€ะตะฝะฝั SNI ะดะพะทะฒะพะปัั” ะพะดะฝะพะผัƒ ัะตั€ะฒะตั€ัƒ (ะท ะพะดะฝั–ั”ัŽ IP-ะฐะดั€ะตัะพัŽ) ะผะฐั‚ะธ ะบั–ะปัŒะบะฐ ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ HTTPS ั– ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะบั–ะปัŒะบะฐ ะดะพะผะตะฝั–ะฒ/ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะฟะพ HTTPS. + * ะฉะพะฑ ั†ะต ะฟั€ะฐั†ัŽะฒะฐะปะพ, ะพะดะธะฝ-ั”ะดะธะฝะธะน ะบะพะผะฟะพะฝะตะฝั‚ (ะฟั€ะพะณั€ะฐะผะฐ), ั‰ะพ ะฟั€ะฐั†ัŽั” ะฝะฐ ัะตั€ะฒะตั€ั– ั‚ะฐ ัะปัƒั…ะฐั” ะฟัƒะฑะปั–ั‡ะฝัƒ IP-ะฐะดั€ะตััƒ, ะผะฐั” ะผะฐั‚ะธ ะฒัั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ HTTPS ะฝะฐ ัะตั€ะฒะตั€ั–. +* ะŸั–ัะปั ะพั‚ั€ะธะผะฐะฝะฝั ะทะฐั…ะธั‰ะตะฝะพะณะพ ะท'ั”ะดะฝะฐะฝะฝั ะฟั€ะพั‚ะพะบะพะป ะพะฑะผั–ะฝัƒ ะฒัะต ั‰ะต HTTP. + * ะ’ะผั–ัั‚ ะทะฐัˆะธั„ั€ะพะฒะฐะฝะพ, ั…ะพั‡ะฐ ะฒั–ะฝ ะฝะฐะดัะธะปะฐั”ั‚ัŒัั ะฟั€ะพั‚ะพะบะพะปะพะผ HTTP. + +ะŸะพัˆะธั€ะตะฝะฐ ะฟั€ะฐะบั‚ะธะบะฐ ะผะฐั‚ะธ ะพะดะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ/HTTP-ัะตั€ะฒะตั€, ั‰ะพ ะฟั€ะฐั†ัŽั” ะฝะฐ ัะตั€ะฒะตั€ั– (ะผะฐัˆะธะฝั–, ั…ะพัั‚ั– ั‚ะพั‰ะพ) ั– ะบะตั€ัƒั” ะฒัั–ะผะฐ ั‡ะฐัั‚ะธะฝะฐะผะธ HTTPS: ะฟั€ะธะนะผะฐั” ะทะฐัˆะธั„ั€ะพะฒะฐะฝั– HTTPS-ะทะฐะฟะธั‚ะธ, ะฝะฐะดัะธะปะฐั” ั€ะพะทัˆะธั„ั€ะพะฒะฐะฝั– HTTP-ะทะฐะฟะธั‚ะธ ะดะพ ั„ะฐะบั‚ะธั‡ะฝะพะณะพ HTTP-ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ะฟั€ะฐั†ัŽั” ะฝะฐ ั‚ะพะผัƒ ะถ ัะตั€ะฒะตั€ั– (ัƒ ะฝะฐัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI), ะพั‚ั€ะธะผัƒั” HTTP-ะฒั–ะดะฟะพะฒั–ะดัŒ ะฒั–ะด ะทะฐัั‚ะพััƒะฝะบัƒ, ัˆะธั„ั€ัƒั” ั—ั— ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฒั–ะดะฟะพะฒั–ะดะฝะพะณะพ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ HTTPS ั– ะฝะฐะดัะธะปะฐั” ั—ั— ะฝะฐะทะฐะด ะบะปั–ั”ะฝั‚ัƒ ั‡ะตั€ะตะท HTTPS. ะขะฐะบะธะน ัะตั€ะฒะตั€ ั‡ะฐัั‚ะพ ะฝะฐะทะธะฒะฐัŽั‚ัŒ TLS Termination Proxy. + +ะ”ะตัะบั– ะฒะฐั€ั–ะฐะฝั‚ะธ, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ัะบ TLS Termination Proxy: + +* Traefik (ั‚ะฐะบะพะถ ะผะพะถะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฟะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ) +* Caddy (ั‚ะฐะบะพะถ ะผะพะถะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฟะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +ะ”ะพ Let's Encrypt ั†ั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ HTTPS ะฟั€ะพะดะฐะฒะฐะปะธัั ะดะพะฒั–ั€ะตะฝะธะผะธ ั‚ั€ะตั‚ั–ะผะธ ัั‚ะพั€ะพะฝะฐะผะธ. + +ะŸั€ะพั†ะตั ะพั‚ั€ะธะผะฐะฝะฝั ะพะดะฝะพะณะพ ะท ั‚ะฐะบะธั… ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ ะฑัƒะฒ ะณั€ะพะผั–ะทะดะบะธะผ, ะฒะธะผะฐะณะฐะฒ ั‡ะธะผะฐะปะพ ะฟะฐะฟะตั€ะพะฒะพั— ั€ะพะฑะพั‚ะธ, ะฐ ัะฐะผั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ะฑัƒะปะธ ะดะพะฒะพะปั– ะดะพั€ะพะณะธะผะธ. + +ะะปะต ะฟะพั‚ั–ะผ ะท'ัะฒะธะฒัั ะฟั€ะพั”ะบั‚ Let's Encrypt. + +ะฆะต ะฟั€ะพั”ะบั‚ Linux Foundation. ะ’ั–ะฝ ะฝะฐะดะฐั” ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ HTTPS ะฑะตะทะบะพัˆั‚ะพะฒะฝะพ, ะฒ ะฐะฒั‚ะพะผะฐั‚ะธะทะพะฒะฐะฝะธะน ัะฟะพัั–ะฑ. ะฆั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ัƒัั– ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ั‡ะฝั– ะผะตั…ะฐะฝั–ะทะผะธ ะฑะตะทะฟะตะบะธ ั– ั” ะบะพั€ะพั‚ะบะพัั‚ั€ะพะบะพะฒะธะผะธ (ะฑะปะธะทัŒะบะพ 3 ะผั–ััั†ั–ะฒ), ั‚ะพะถ ะฑะตะทะฟะตะบะฐ ะฝะฐัะฟั€ะฐะฒะดั– ะบั€ะฐั‰ะฐ ะทะฐะฒะดัะบะธ ะทะผะตะฝัˆะตะฝั–ะน ั‚ั€ะธะฒะฐะปะพัั‚ั– ะถะธั‚ั‚ั. + +ะ”ะพะผะตะฝะธ ะฑะตะทะฟะตั‡ะฝะพ ะฟะตั€ะตะฒั–ั€ััŽั‚ัŒัั, ะฐ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ะณะตะฝะตั€ัƒัŽั‚ัŒัั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ. ะฆะต ั‚ะฐะบะพะถ ะดะพะทะฒะพะปัั” ะฐะฒั‚ะพะผะฐั‚ะธะทัƒะฒะฐั‚ะธ ะฟะพะฝะพะฒะปะตะฝะฝั ั†ะธั… ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ. + +ะ†ะดะตั ะฟะพะปัะณะฐั” ะฒ ะฐะฒั‚ะพะผะฐั‚ะธะทะฐั†ั–ั— ะพั‚ั€ะธะผะฐะฝะฝั ั‚ะฐ ะฟะพะฝะพะฒะปะตะฝะฝั ั†ะธั… ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ, ั‰ะพะฑ ะฒะธ ะผะพะณะปะธ ะผะฐั‚ะธ ะฑะตะทะฟะตั‡ะฝะธะน HTTPS ะฑะตะทะบะพัˆั‚ะพะฒะฝะพ ั‚ะฐ ะฝะฐะทะฐะฒะถะดะธ. + +## HTTPS ะดะปั ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ { #https-for-developers } + +ะžััŒ ะฟั€ะธะบะปะฐะด ั‚ะพะณะพ, ัะบ ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ HTTPS API, ะบั€ะพะบ ะทะฐ ะบั€ะพะบะพะผ, ะทะพัะตั€ะตะดะถัƒัŽั‡ะธััŒ ะฟะตั€ะตะฒะฐะถะฝะพ ะฝะฐ ั–ะดะตัั…, ะฒะฐะถะปะธะฒะธั… ะดะปั ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ. + +### ะ”ะพะผะตะฝะฝะต ั–ะผ'ั { #domain-name } + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒัะต ะฟะพั‡ะฝะตั‚ัŒัั ะท ั‚ะพะณะพ, ั‰ะพ ะฒะธ ะฟั€ะธะดะฑะฐั”ั‚ะต ัะบะตััŒ ะดะพะผะตะฝะฝะต ั–ะผ'ั. ะŸะพั‚ั–ะผ ะฒะธ ะฝะฐะปะฐัˆั‚ัƒั”ั‚ะต ะนะพะณะพ ะฝะฐ ัะตั€ะฒะตั€ั– DNS (ะผะพะถะปะธะฒะพ, ัƒ ะฒะฐัˆะพะณะพ ะถ ั…ะผะฐั€ะฝะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ). + +ะ’ะธ, ัะบะพั€ั–ัˆ ะทะฐ ะฒัะต, ะพั‚ั€ะธะผะฐั”ั‚ะต ั…ะผะฐั€ะฝะธะน ัะตั€ะฒะตั€ (ะฒั–ั€ั‚ัƒะฐะปัŒะฝัƒ ะผะฐัˆะธะฝัƒ) ะฐะฑะพ ั‰ะพััŒ ะฟะพะดั–ะฑะฝะต, ั– ะฒั–ะฝ ะผะฐั‚ะธะผะต ั„ั–ะบัะพะฒะฐะฝัƒ ะฟัƒะฑะปั–ั‡ะฝัƒ IP-ะฐะดั€ะตััƒ. + +ะะฐ ัะตั€ะฒะตั€ั–(ะฐั…) DNS ะฒะธ ะฝะฐะปะฐัˆั‚ัƒั”ั‚ะต ะทะฐะฟะธั (ยซ`A record`ยป), ั‰ะพะฑ ัะฟั€ัะผัƒะฒะฐั‚ะธ ะฒะฐัˆ ะดะพะผะตะฝ ะฝะฐ ะฟัƒะฑะปั–ั‡ะฝัƒ IP-ะฐะดั€ะตััƒ ะฒะฐัˆะพะณะพ ัะตั€ะฒะตั€ะฐ. + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะทั€ะพะฑะธั‚ะต ั†ะต ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท, ัƒะฟะตั€ัˆะต, ะบะพะปะธ ะฒัะต ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะงะฐัั‚ะธะฝะฐ ะฟั€ะพ ะดะพะผะตะฝะฝะต ั–ะผ'ั ะทะฝะฐั‡ะฝะพ ั€ะฐะฝั–ัˆะต ะทะฐ HTTPS, ะฐะปะต ะพัะบั–ะปัŒะบะธ ะฒัะต ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด ะดะพะผะตะฝัƒ ั‚ะฐ IP-ะฐะดั€ะตัะธ, ะฒะฐั€ั‚ะพ ะทะณะฐะดะฐั‚ะธ ั†ะต ั‚ัƒั‚. + +/// + +### DNS { #dns } + +ะขะตะฟะตั€ ะทะพัะตั€ะตะดัŒะผะพัั ะฝะฐ ะฒัั–ั… ะฒะปะฐัะฝะต ั‡ะฐัั‚ะธะฝะฐั… HTTPS. + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฑั€ะฐัƒะทะตั€ ะทะฒะตั€ะฝะตั‚ัŒัั ะดะพ ัะตั€ะฒะตั€ั–ะฒ DNS, ั‰ะพะฑ ะดั–ะทะฝะฐั‚ะธัั, ัะบะฐ IP-ะฐะดั€ะตัะฐ ะดะปั ะดะพะผะตะฝัƒ, ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `someapp.example.com`. + +ะกะตั€ะฒะตั€ะธ DNS ะฟะพะฒั–ะดะพะผะปัั‚ัŒ ะฑั€ะฐัƒะทะตั€ัƒ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝัƒ IP-ะฐะดั€ะตััƒ. ะฆะต ะฑัƒะดะต ะฟัƒะฑะปั–ั‡ะฝะฐ IP-ะฐะดั€ะตัะฐ, ัะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒะฐัˆ ัะตั€ะฒะตั€ ั– ัะบัƒ ะฒะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะปะธ ะฝะฐ ัะตั€ะฒะตั€ะฐั… DNS. + + + +### ะŸะพั‡ะฐั‚ะพะบ TLS ั€ัƒะบะพัั‚ะธัะบะฐะฝะฝั { #tls-handshake-start } + +ะŸะพั‚ั–ะผ ะฑั€ะฐัƒะทะตั€ ะทะฒ'ัะถะตั‚ัŒัั ะท ั†ั–ั”ัŽ IP-ะฐะดั€ะตัะพัŽ ะฝะฐ ะฟะพั€ั‚ัƒ 443 (ะฟะพั€ั‚ HTTPS). + +ะŸะตั€ัˆะฐ ั‡ะฐัั‚ะธะฝะฐ ะบะพะผัƒะฝั–ะบะฐั†ั–ั— - ั†ะต ะฟั€ะพัั‚ะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะท'ั”ะดะฝะฐะฝะฝั ะผั–ะถ ะบะปั–ั”ะฝั‚ะพะผ ั– ัะตั€ะฒะตั€ะพะผ ั‚ะฐ ัƒะทะณะพะดะถะตะฝะฝั ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ั‡ะฝะธั… ะบะปัŽั‡ั–ะฒ ั‚ะพั‰ะพ. + + + +ะฆั ะฒะทะฐั”ะผะพะดั–ั ะผั–ะถ ะบะปั–ั”ะฝั‚ะพะผ ั– ัะตั€ะฒะตั€ะพะผ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะท'ั”ะดะฝะฐะฝะฝั TLS ะฝะฐะทะธะฒะฐั”ั‚ัŒัั TLS ั€ัƒะบะพัั‚ะธัะบะฐะฝะฝัะผ. + +### TLS ั–ะท ั€ะพะทัˆะธั€ะตะฝะฝัะผ SNI { #tls-with-sni-extension } + +ะ›ะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะฝะฐ ัะตั€ะฒะตั€ั– ะผะพะถะต ัะปัƒั…ะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝะธะน ะฟะพั€ั‚ ะฝะฐ ะบะพะฝะบั€ะตั‚ะฝั–ะน IP-ะฐะดั€ะตัั–. ะ†ะฝัˆั– ะฟั€ะพั†ะตัะธ ะผะพะถัƒั‚ัŒ ัะปัƒั…ะฐั‚ะธ ั–ะฝัˆั– ะฟะพั€ั‚ะธ ะฝะฐ ั‚ั–ะน ัะฐะผั–ะน IP-ะฐะดั€ะตัั–, ะฐะปะต ะปะธัˆะต ะพะดะธะฝ ะดะปั ะบะพะถะฝะพั— ะบะพะผะฑั–ะฝะฐั†ั–ั— IP-ะฐะดั€ะตัะธ ั‚ะฐ ะฟะพั€ั‚ัƒ. + +TLS (HTTPS) ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะบะพะฝะบั€ะตั‚ะฝะธะน ะฟะพั€ั‚ `443`. ะžั‚ะถะต, ั†ะต ะฟะพั€ั‚, ัะบะธะน ะฝะฐะผ ะฟะพั‚ั€ั–ะฑะตะฝ. + +ะžัะบั–ะปัŒะบะธ ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะผะพะถะต ัะปัƒั…ะฐั‚ะธ ั†ะตะน ะฟะพั€ั‚, ะฟั€ะพั†ะตัะพะผ, ั‰ะพ ั€ะพะฑะธั‚ะธะผะต ั†ะต, ะฑัƒะดะต TLS Termination Proxy. + +TLS Termination Proxy ะผะฐั‚ะธะผะต ะดะพัั‚ัƒะฟ ะดะพ ะพะดะฝะพะณะพ ะฐะฑะพ ะบั–ะปัŒะบะพั… ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ TLS (ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ HTTPS). + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะพะฑะณะพะฒะพั€ะตะฝะต ะฒะธั‰ะต ั€ะพะทัˆะธั€ะตะฝะฝั SNI, TLS Termination Proxy ะฟะตั€ะตะฒั–ั€ะธั‚ัŒ, ัะบะธะน ั–ะท ะฝะฐัะฒะฝะธั… ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ TLS (HTTPS) ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะดะปั ั†ัŒะพะณะพ ะท'ั”ะดะฝะฐะฝะฝั, ะพะฑั€ะฐะฒัˆะธ ั‚ะพะน, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดะฐั” ะดะพะผะตะฝัƒ, ะพั‡ั–ะบัƒะฒะฐะฝะพะผัƒ ะบะปั–ั”ะฝั‚ะพะผ. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒั–ะฝ ะฒะธะบะพั€ะธัั‚ะฐั” ัะตั€ั‚ะธั„ั–ะบะฐั‚ ะดะปั `someapp.example.com`. + + + +ะšะปั–ั”ะฝั‚ ัƒะถะต ะดะพะฒั–ั€ัั” ััƒั‚ะฝะพัั‚ั–, ัะบะฐ ะฒะธะดะฐะปะฐ ั†ะตะน ัะตั€ั‚ะธั„ั–ะบะฐั‚ TLS (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ Let's Encrypt, ะฐะปะต ะฟั€ะพ ั†ะต ะทะณะพะดะพะผ), ั‚ะพะถ ะฒั–ะฝ ะผะพะถะต ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ัะตั€ั‚ะธั„ั–ะบะฐั‚ ะดั–ะนัะฝะธะน. + +ะŸะพั‚ั–ะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัะตั€ั‚ะธั„ั–ะบะฐั‚, ะบะปั–ั”ะฝั‚ ั– TLS Termination Proxy ัƒะทะณะพะดะถัƒัŽั‚ัŒ, ัะบ ัˆะธั„ั€ัƒะฒะฐั‚ะธ ั€ะตัˆั‚ัƒ TCP-ะบะพะผัƒะฝั–ะบะฐั†ั–ั—. ะะฐ ั†ัŒะพะผัƒ ั‡ะฐัั‚ะธะฝะฐ TLS ั€ัƒะบะพัั‚ะธัะบะฐะฝะฝั ะทะฐะฒะตั€ัˆัƒั”ั‚ัŒัั. + +ะŸั–ัะปั ั†ัŒะพะณะพ ะบะปั–ั”ะฝั‚ ั– ัะตั€ะฒะตั€ ะผะฐัŽั‚ัŒ ะทะฐัˆะธั„ั€ะพะฒะฐะฝะต TCP-ะท'ั”ะดะฝะฐะฝะฝั - ัะฐะผะต ั†ะต ะฝะฐะดะฐั” TLS. ะ† ั‚ะพะดั– ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะต ะท'ั”ะดะฝะฐะฝะฝั, ั‰ะพะฑ ะฟะพั‡ะฐั‚ะธ ะฒะปะฐัะฝะต HTTP-ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ. + +ะ† ั†ะต ั– ั” HTTPS: ั†ะต ะทะฒะธั‡ะฐะนะฝะธะน HTTP ัƒัะตั€ะตะดะธะฝั– ะทะฐั…ะธั‰ะตะฝะพะณะพ TLS-ะท'ั”ะดะฝะฐะฝะฝั ะทะฐะผั–ัั‚ัŒ ั‡ะธัั‚ะพะณะพ (ะฝะตะทะฐัˆะธั„ั€ะพะฒะฐะฝะพะณะพ) TCP-ะท'ั”ะดะฝะฐะฝะฝั. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ัˆะธั„ั€ัƒะฒะฐะฝะฝั ะบะพะผัƒะฝั–ะบะฐั†ั–ั— ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั ะฝะฐ ั€ั–ะฒะฝั– TCP, ะฐ ะฝะต ะฝะฐ ั€ั–ะฒะฝั– HTTP. + +/// + +### HTTPS-ะทะฐะฟะธั‚ { #https-request } + +ะขะตะฟะตั€, ะบะพะปะธ ะบะปั–ั”ะฝั‚ ั– ัะตั€ะฒะตั€ (ะบะพะฝะบั€ะตั‚ะฝะพ ะฑั€ะฐัƒะทะตั€ ั– TLS Termination Proxy) ะผะฐัŽั‚ัŒ ะทะฐัˆะธั„ั€ะพะฒะฐะฝะต TCP-ะท'ั”ะดะฝะฐะฝะฝั, ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ะฟะพั‡ะฐั‚ะธ HTTP-ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ. + +ะžั‚ะถะต, ะบะปั–ั”ะฝั‚ ะฝะฐะดัะธะปะฐั” HTTPS-ะทะฐะฟะธั‚. ะฆะต ะฟั€ะพัั‚ะพ HTTP-ะทะฐะฟะธั‚ ั‡ะตั€ะตะท ะทะฐัˆะธั„ั€ะพะฒะฐะฝะต TLS-ะท'ั”ะดะฝะฐะฝะฝั. + + + +### ะ ะพะทัˆะธั„ั€ัƒะฒะฐะฝะฝั ะทะฐะฟะธั‚ัƒ { #decrypt-the-request } + +TLS Termination Proxy ะฒะธะบะพั€ะธัั‚ะฐั” ัƒะทะณะพะดะถะตะฝะต ัˆะธั„ั€ัƒะฒะฐะฝะฝั, ั‰ะพะฑ ั€ะพะทัˆะธั„ั€ัƒะฒะฐั‚ะธ ะทะฐะฟะธั‚, ั– ะฟะตั€ะตะดะฐัั‚ัŒ ะทะฒะธั‡ะฐะนะฝะธะน (ั€ะพะทัˆะธั„ั€ะพะฒะฐะฝะธะน) HTTP-ะทะฐะฟะธั‚ ะฟั€ะพั†ะตััƒ, ั‰ะพ ะทะฐะฟัƒัะบะฐั” ะทะฐัั‚ะพััƒะฝะพะบ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฟั€ะพั†ะตััƒ ะท Uvicorn, ัะบะธะน ะทะฐะฟัƒัะบะฐั” ะทะฐัั‚ะพััƒะฝะพะบ FastAPI). + + + +### HTTP-ะฒั–ะดะฟะพะฒั–ะดัŒ { #http-response } + +ะ—ะฐัั‚ะพััƒะฝะพะบ ะพะฑั€ะพะฑะธั‚ัŒ ะทะฐะฟะธั‚ ั– ะฝะฐะดั–ัˆะปะต ะทะฒะธั‡ะฐะนะฝัƒ (ะฝะตะทะฐัˆะธั„ั€ะพะฒะฐะฝัƒ) HTTP-ะฒั–ะดะฟะพะฒั–ะดัŒ TLS Termination Proxy. + + + +### HTTPS-ะฒั–ะดะฟะพะฒั–ะดัŒ { #https-response } + +ะŸะพั‚ั–ะผ TLS Termination Proxy ะทะฐัˆะธั„ั€ัƒั” ะฒั–ะดะฟะพะฒั–ะดัŒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฟะพะฟะตั€ะตะดะฝัŒะพ ัƒะทะณะพะดะถะตะฝัƒ ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ัŽ (ั‰ะพ ะฟะพั‡ะฐะปะฐัั ั–ะท ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ ะดะปั `someapp.example.com`), ั– ะฝะฐะดั–ัˆะปะต ั—ั— ะฝะฐะทะฐะด ัƒ ะฑั€ะฐัƒะทะตั€. + +ะ”ะฐะปั– ะฑั€ะฐัƒะทะตั€ ะฟะตั€ะตะฒั–ั€ะธั‚ัŒ, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะดั–ะนัะฝะฐ ะน ะทะฐัˆะธั„ั€ะพะฒะฐะฝะฐ ะฟั€ะฐะฒะธะปัŒะฝะธะผ ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ั‡ะฝะธะผ ะบะปัŽั‡ะตะผ ั‚ะพั‰ะพ. ะŸะพั‚ั–ะผ ะฒั–ะฝ ั€ะพะทัˆะธั„ั€ัƒั” ะฒั–ะดะฟะพะฒั–ะดัŒ ั– ะพะฑั€ะพะฑะธั‚ัŒ ั—ั—. + + + +ะšะปั–ั”ะฝั‚ (ะฑั€ะฐัƒะทะตั€) ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฝะฐะดั…ะพะดะธั‚ัŒ ะฒั–ะด ะฟั€ะฐะฒะธะปัŒะฝะพะณะพ ัะตั€ะฒะตั€ะฐ, ั‚ะพะผัƒ ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒะทะณะพะดะถะตะฝะฐ ั€ะฐะฝั–ัˆะต ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ั ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ HTTPS. + +### ะšั–ะปัŒะบะฐ ะทะฐัั‚ะพััƒะฝะบั–ะฒ { #multiple-applications } + +ะะฐ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ัะตั€ะฒะตั€ั– (ะฐะฑะพ ัะตั€ะฒะตั€ะฐั…) ะผะพะถะต ะฑัƒั‚ะธ ะบั–ะปัŒะบะฐ ะทะฐัั‚ะพััƒะฝะบั–ะฒ, ะฝะฐะฟั€ะธะบะปะฐะด ั–ะฝัˆั– ะฟั€ะพะณั€ะฐะผะธ API ะฐะฑะพ ะฑะฐะทะฐ ะดะฐะฝะธั…. + +ะ›ะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธ ะบะพะฝะบั€ะตั‚ะฝัƒ IP-ะฐะดั€ะตััƒ ั– ะฟะพั€ั‚ (TLS Termination Proxy ัƒ ะฝะฐัˆะพะผัƒ ะฟั€ะธะบะปะฐะดั–), ะฐะปะต ั–ะฝัˆั– ะทะฐัั‚ะพััƒะฝะบะธ/ะฟั€ะพั†ะตัะธ ั‚ะฐะบะพะถ ะผะพะถัƒั‚ัŒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐ ัะตั€ะฒะตั€ั–(ะฐั…), ะดะพะบะธ ะฒะพะฝะธ ะฝะต ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ัƒ ัะฐะผัƒ ะบะพะผะฑั–ะฝะฐั†ั–ัŽ ะฟัƒะฑะปั–ั‡ะฝะพั— IP-ะฐะดั€ะตัะธ ะน ะฟะพั€ั‚ัƒ. + + + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, TLS Termination Proxy ะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธ HTTPS ั– ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ ะดะปั ะบั–ะปัŒะบะพั… ะดะพะผะตะฝั–ะฒ, ะดะปั ะบั–ะปัŒะบะพั… ะทะฐัั‚ะพััƒะฝะบั–ะฒ, ะฐ ะฟะพั‚ั–ะผ ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ะทะฐะฟะธั‚ะธ ะดะพ ะฒั–ะดะฟะพะฒั–ะดะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒ ะบะพะถะฝะพะผัƒ ะฒะธะฟะฐะดะบัƒ. + +### ะŸะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ { #certificate-renewal } + +ะฃ ะฟะตะฒะฝะธะน ะผะพะผะตะฝั‚ ัƒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ ัั‚ั€ะพะบ ะดั–ั— ะบะพะถะฝะพะณะพ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ ัะฟะปะธะฒะต (ะฟั€ะธะฑะปะธะทะฝะพ ั‡ะตั€ะตะท 3 ะผั–ััั†ั– ะฟั–ัะปั ะนะพะณะพ ะพั‚ั€ะธะผะฐะฝะฝั). + +ะŸะพั‚ั–ะผ ั–ะฝัˆะฐ ะฟั€ะพะณั€ะฐะผะฐ (ะฒ ะดะตัะบะธั… ะฒะธะฟะฐะดะบะฐั… ั†ะต ั–ะฝัˆะฐ ะฟั€ะพะณั€ะฐะผะฐ, ะฐ ะฒ ะดะตัะบะธั… - ั‚ะพะน ัะฐะผะธะน TLS Termination Proxy) ะทะฒ'ัะถะตั‚ัŒัั ะท Let's Encrypt ั– ะฟะพะฝะพะฒะธั‚ัŒ ัะตั€ั‚ะธั„ั–ะบะฐั‚(ะธ). + + + +ะกะตั€ั‚ะธั„ั–ะบะฐั‚ะธ TLS ะฟะพะฒ'ัะทะฐะฝั– ะท ะดะพะผะตะฝะฝะธะผ ั–ะผะตะฝะตะผ, ะฐ ะฝะต ะท IP-ะฐะดั€ะตัะพัŽ. + +ะขะพะผัƒ, ั‰ะพะฑ ะฟะพะฝะพะฒะธั‚ะธ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ, ะฟั€ะพะณั€ะฐะผะฐ ะฟะพะฝะพะฒะปะตะฝะฝั ะผะฐั” ะดะพะฒะตัั‚ะธ ะฐะฒั‚ะพั€ะธั‚ะตั‚ัƒ (Let's Encrypt), ั‰ะพ ะฒะพะฝะฐ ัะฟั€ะฐะฒะดั– ยซะฒะพะปะพะดั–ั”ยป ั– ะบะพะฝั‚ั€ะพะปัŽั” ั†ะตะน ะดะพะผะตะฝ. + +ะฉะพะฑ ะทั€ะพะฑะธั‚ะธ ั†ะต ะน ะทะฐะดะพะฒะพะปัŒะฝะธั‚ะธ ั€ั–ะทะฝั– ะฟะพั‚ั€ะตะฑะธ ะทะฐัั‚ะพััƒะฝะบั–ะฒ, ั” ะบั–ะปัŒะบะฐ ัะฟะพัะพะฑั–ะฒ. ะ”ะตัะบั– ะฟะพะฟัƒะปัั€ะฝั–: + +* ะ—ะผั–ะฝะธั‚ะธ ะดะตัะบั– ะทะฐะฟะธัะธ DNS. + * ะ”ะปั ั†ัŒะพะณะพ ะฟั€ะพะณั€ะฐะผะฐ ะฟะพะฝะพะฒะปะตะฝะฝั ะผะฐั” ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ API ะฟั€ะพะฒะฐะนะดะตั€ะฐ DNS, ั‚ะพะถ ะทะฐะปะตะถะฝะพ ะฒั–ะด ั‚ะพะณะพ, ัะบะพะณะพ ะฟั€ะพะฒะฐะนะดะตั€ะฐ DNS ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต, ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ะฐะฑะพ ะฝะต ะฑัƒั‚ะธ ะฒะฐั€ั–ะฐะฝั‚ะพะผ. +* ะ—ะฐะฟัƒัั‚ะธั‚ะธัั ัะบ ัะตั€ะฒะตั€ (ะฟั€ะธะฝะฐะนะผะฝั– ะฟั–ะด ั‡ะฐั ะฟั€ะพั†ะตััƒ ะพั‚ั€ะธะผะฐะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ะฐ) ะฝะฐ ะฟัƒะฑะปั–ั‡ะฝั–ะน IP-ะฐะดั€ะตัั–, ะฟะพะฒ'ัะทะฐะฝั–ะน ั–ะท ะดะพะผะตะฝะพะผ. + * ะฏะบ ะผะธ ะบะฐะทะฐะปะธ ะฒะธั‰ะต, ะปะธัˆะต ะพะดะธะฝ ะฟั€ะพั†ะตั ะผะพะถะต ัะปัƒั…ะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝัƒ IP-ะฐะดั€ะตััƒ ั‚ะฐ ะฟะพั€ั‚. + * ะฆะต ะพะดะฝะฐ ะท ะฟั€ะธั‡ะธะฝ, ั‡ะพะผัƒ ะดัƒะถะต ะทั€ัƒั‡ะฝะพ, ะบะพะปะธ ั‚ะพะน ัะฐะผะธะน TLS Termination Proxy ั‚ะฐะบะพะถ ะทะฐะนะผะฐั”ั‚ัŒัั ะฟั€ะพั†ะตัะพะผ ะฟะพะฝะพะฒะปะตะฝะฝั ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ. + * ะ†ะฝะฐะบัˆะต ะฒะฐะผ, ะผะพะถะปะธะฒะพ, ะดะพะฒะตะดะตั‚ัŒัั ะฝะฐ ะผะธั‚ัŒ ะทัƒะฟะธะฝะธั‚ะธ TLS Termination Proxy, ะทะฐะฟัƒัั‚ะธั‚ะธ ะฟั€ะพะณั€ะฐะผัƒ ะฟะพะฝะพะฒะปะตะฝะฝั, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ, ะฟะพั‚ั–ะผ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั—ั… ัƒ TLS Termination Proxy ั– ะฟะตั€ะตะทะฐะฟัƒัั‚ะธั‚ะธ TLS Termination Proxy. ะฆะต ะฝะตั–ะดะตะฐะปัŒะฝะพ, ะพัะบั–ะปัŒะบะธ ะฒะฐัˆั– ะทะฐัั‚ะพััƒะฝะบะธ ะฑัƒะดัƒั‚ัŒ ะฝะตะดะพัั‚ัƒะฟะฝั– ะฟั–ะด ั‡ะฐั ะฒะธะผะบะฝะตะฝะฝั TLS Termination Proxy. + +ะฃะฒะตััŒ ั†ะตะน ะฟั€ะพั†ะตั ะฟะพะฝะพะฒะปะตะฝะฝั, ะฟะฐั€ะฐะปะตะปัŒะฝะพ ะท ะพะฑัะปัƒะณะพะฒัƒะฒะฐะฝะฝัะผ ะทะฐัั‚ะพััƒะฝะบัƒ, - ะพะดะฝะฐ ะท ะณะพะปะพะฒะฝะธั… ะฟั€ะธั‡ะธะฝ, ั‡ะพะผัƒ ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะผะฐั‚ะธ ะพะบั€ะตะผัƒ ัะธัั‚ะตะผัƒ ะดะปั ะพะฑั€ะพะฑะบะธ HTTPS ะทะฐ ะดะพะฟะพะผะพะณะพัŽ TLS Termination Proxy ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ, ั‰ะพะฑ ะฟั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะตั€ั‚ะธั„ั–ะบะฐั‚ะธ TLS ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ัะตั€ะฒะตั€ะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn). + +## ะะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะพะบัั– { #proxy-forwarded-headers } + +ะšะพะปะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฟั€ะพะบัั– ะดะปั ะพะฑั€ะพะฑะบะธ HTTPS, ะฒะฐัˆ ัะตั€ะฒะตั€ ะทะฐัั‚ะพััƒะฝะบัƒ (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn ั‡ะตั€ะตะท FastAPI CLI) ะฝั–ั‡ะพะณะพ ะฝะต ะทะฝะฐั” ะฟั€ะพ ะฟั€ะพั†ะตั HTTPS, ะฒั–ะฝ ัะฟั–ะปะบัƒั”ั‚ัŒัั ะทะฒะธั‡ะฐะนะฝะธะผ HTTP ั–ะท TLS Termination Proxy. + +ะฆะตะน ะฟั€ะพะบัั– ะทะฐะทะฒะธั‡ะฐะน ะดะธะฝะฐะผั–ั‡ะฝะพ ะฒัั‚ะฐะฝะพะฒะปัŽั” ะดะตัะบั– HTTP-ะทะฐะณะพะปะพะฒะบะธ ะฟะตั€ะตะด ะฟะตั€ะตะดะฐั‡ะตัŽ ะทะฐะฟะธั‚ัƒ ัะตั€ะฒะตั€ัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพะฑ ะดะฐั‚ะธ ะนะพะผัƒ ะทะฝะฐั‚ะธ, ั‰ะพ ะทะฐะฟะธั‚ ะฝะฐะฟั€ะฐะฒะปัั”ั‚ัŒัั ะฟั€ะพะบัั–. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ—ะฐะณะพะปะพะฒะบะธ ะฟั€ะพะบัั–: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +ะ’ั‚ั–ะผ, ะพัะบั–ะปัŒะบะธ ัะตั€ะฒะตั€ ะทะฐัั‚ะพััƒะฝะบัƒ ะฝะต ะทะฝะฐั”, ั‰ะพ ะฒั–ะฝ ัั‚ะพั—ั‚ัŒ ะทะฐ ะดะพะฒั–ั€ะตะฝะธะผ ะฟั€ะพะบัั–, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฒั–ะฝ ะฝะต ะดะพะฒั–ั€ัั‚ะธะผะต ั†ะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ. + +ะะปะต ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ัะตั€ะฒะตั€ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพะฑ ะดะพะฒั–ั€ัั‚ะธ ะฝะฐะฟั€ะฐะฒะปะตะฝะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ, ะฝะฐะดั–ัะปะฐะฝะธะผ ะฟั€ะพะบัั–. ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต FastAPI CLI, ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ะบัƒั€ัะธะฒะฝะพัŽ *ะพะฟั†ั–ั”ัŽ CLI* `--forwarded-allow-ips`, ั‰ะพะฑ ะฟะพะฒั–ะดะพะผะธั‚ะธ, ะท ัะบะธั… IP-ะฐะดั€ะตั ัะปั–ะด ะดะพะฒั–ั€ัั‚ะธ ั†ะธะผ ะฝะฐะฟั€ะฐะฒะปะตะฝะธะผ ะทะฐะณะพะปะพะฒะบะฐะผ. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัะตั€ะฒะตั€ ะทะฐัั‚ะพััƒะฝะบัƒ ะพั‚ั€ะธะผัƒั” ะบะพะผัƒะฝั–ะบะฐั†ั–ัŽ ะปะธัˆะต ะฒั–ะด ะดะพะฒั–ั€ะตะฝะพะณะพ ะฟั€ะพะบัั–, ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `--forwarded-allow-ips="*"`, ั‰ะพะฑ ะดะพะฒั–ั€ัั‚ะธ ะฒัั–ะผ ะฒั…ั–ะดะฝะธะผ IP-ะฐะดั€ะตัะฐะผ, ะพัะบั–ะปัŒะบะธ ะฒั–ะฝ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผะต ะทะฐะฟะธั‚ะธ ะปะธัˆะต ะท ั‚ั–ั”ั— IP-ะฐะดั€ะตัะธ, ัะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฟั€ะพะบัั–. + +ะขะฐะบ ะทะฐัั‚ะพััƒะฝะพะบ ะทะผะพะถะต ะทะฝะฐั‚ะธ ัะฒะพัŽ ะฟัƒะฑะปั–ั‡ะฝัƒ URL-ะฐะดั€ะตััƒ, ั‡ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒั–ะฝ HTTPS, ะดะพะผะตะฝ ั‚ะพั‰ะพ. + +ะฆะต ะฑัƒะดะต ะบะพั€ะธัะฝะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ะดะปั ะบะพั€ะตะบั‚ะฝะพั— ะพะฑั€ะพะฑะบะธ ะฟะตั€ะตะฝะฐะฟั€ะฐะฒะปะตะฝัŒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั†ะต ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— [ะ—ะฐ ะฟั€ะพะบัั– - ะฃะฒั–ะผะบะฝัƒั‚ะธ ะฝะฐะฟั€ะฐะฒะปะตะฝั– ะทะฐะณะพะปะพะฒะบะธ ะฟั€ะพะบัั–](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} + +/// + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะะฐัะฒะฝั–ัั‚ัŒ HTTPS ะดัƒะถะต ะฒะฐะถะปะธะฒะฐ ั– ะฒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะบั€ะธั‚ะธั‡ะฝะฐ. ะ‘ั–ะปัŒัˆั–ัั‚ัŒ ะทัƒัะธะปัŒ, ัะบั– ะฒะฐะผ ัะบ ั€ะพะทั€ะพะฑะฝะธะบัƒ ะดะพะฒะตะดะตั‚ัŒัั ะดะพะบะปะฐัั‚ะธ ะฝะฐะฒะบะพะปะพ HTTPS, ะฟะพะปัะณะฐัŽั‚ัŒ ะปะธัˆะต ะฒ ั€ะพะทัƒะผั–ะฝะฝั– ั†ะธั… ะบะพะฝั†ะตะฟั†ั–ะน ั– ั‚ะพะณะพ, ัะบ ะฒะพะฝะธ ะฟั€ะฐั†ัŽัŽั‚ัŒ. + +ะะปะต ัะบ ั‚ั–ะปัŒะบะธ ะฒะธ ะทะฝะฐั”ั‚ะต ะฑะฐะทะพะฒัƒ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะฟั€ะพ HTTPS ะดะปั ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะบะพะผะฑั–ะฝัƒะฒะฐั‚ะธ ะน ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธ ั€ั–ะทะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ั‰ะพะฑ ะบะตั€ัƒะฒะฐั‚ะธ ะฒัั–ะผ ะฟั€ะพัั‚ะพ. + +ะฃ ะดะตัะบะธั… ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ะฟะพะบะฐะถัƒ ะบั–ะปัŒะบะฐ ะบะพะฝะบั€ะตั‚ะฝะธั… ะฟั€ะธะบะปะฐะดั–ะฒ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั HTTPS ะดะปั ะทะฐัั‚ะพััƒะฝะบั–ะฒ FastAPI. ๐Ÿ”’ diff --git a/docs/uk/docs/deployment/index.md b/docs/uk/docs/deployment/index.md new file mode 100644 index 0000000000..7386681397 --- /dev/null +++ b/docs/uk/docs/deployment/index.md @@ -0,0 +1,23 @@ +# ะ ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployment } + +ะ ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** ะฒั–ะดะฝะพัะฝะพ ะฟั€ะพัั‚ะต. + +## ะฉะพ ะพะทะฝะฐั‡ะฐั” ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #what-does-deployment-mean } + +ะ ะพะทะณะพั€ะฝัƒั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ - ั†ะต ะฒะธะบะพะฝะฐั‚ะธ ะฝะตะพะฑั…ั–ะดะฝั– ะบั€ะพะบะธ, ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ะนะพะณะพ ะดะพัั‚ัƒะฟะฝะธะผ ะดะปั ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ. + +ะ”ะปั **ะฒะตะฑ API** ั†ะต ะทะฐะทะฒะธั‡ะฐะน ะพะทะฝะฐั‡ะฐั” ั€ะพะทะผั–ั‰ะตะฝะฝั ะนะพะณะพ ะฝะฐ **ะฒั–ะดะดะฐะปะตะฝั–ะน ะผะฐัˆะธะฝั–** ะท **ัะตั€ะฒะตั€ะฝะพัŽ ะฟั€ะพะณั€ะฐะผะพัŽ**, ั‰ะพ ะทะฐะฑะตะทะฟะตั‡ัƒั” ั…ะพั€ะพัˆัƒ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ, ัั‚ะฐะฑั–ะปัŒะฝั–ัั‚ัŒ ั‚ะพั‰ะพ, ั‰ะพะฑ ะฒะฐัˆั– **ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–** ะผะพะณะปะธ **ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะดะพัั‚ัƒะฟ** ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ ะตั„ะตะบั‚ะธะฒะฝะพ ั‚ะฐ ะฑะตะท ะฟะตั€ะตั€ะฒ ั‡ะธ ะฟั€ะพะฑะปะตะผ. + +ะฆะต ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด ะตั‚ะฐะฟั–ะฒ **ั€ะพะทั€ะพะฑะบะธ**, ะบะพะปะธ ะฒะธ ะฟะพัั‚ั–ะนะฝะพ ะทะผั–ะฝัŽั”ั‚ะต ะบะพะด, ะปะฐะผะฐั”ั‚ะต ะน ะฒะธะฟั€ะฐะฒะปัั”ั‚ะต ะนะพะณะพ, ะทัƒะฟะธะฝัั”ั‚ะต ั‚ะฐ ะฟะตั€ะตะทะฐะฟัƒัะบะฐั”ั‚ะต ัะตั€ะฒะตั€ ั€ะพะทั€ะพะฑะบะธ ั‚ะพั‰ะพ. + +## ะกั‚ั€ะฐั‚ะตะณั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployment-strategies } + +ะ†ัะฝัƒั” ะบั–ะปัŒะบะฐ ัะฟะพัะพะฑั–ะฒ ะทั€ะพะฑะธั‚ะธ ั†ะต ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะพะณะพ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ัะบั– ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต. + +ะ’ะธ ะผะพะถะตั‚ะต ั€ะพะทะณะพั€ะฝัƒั‚ะธ ัะตั€ะฒะตั€ ัะฐะผะพัั‚ั–ะนะฝะพ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะบะพะผะฑั–ะฝะฐั†ั–ัŽ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั **ั…ะผะฐั€ะฝะธะผ ัะตั€ะฒั–ัะพะผ**, ัะบะธะน ะฒะธะบะพะฝัƒั” ั‡ะฐัั‚ะธะฝัƒ ั€ะพะฑะพั‚ะธ ะทะฐ ะฒะฐั, ะฐะฑะพ ะพะฑั€ะฐั‚ะธ ั–ะฝัˆั– ะฒะฐั€ั–ะฐะฝั‚ะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะผะธ, ะบะพะผะฐะฝะดะฐ, ั‰ะพ ัั‚ะพั—ั‚ัŒ ะทะฐ FastAPI, ัั‚ะฒะพั€ะธะปะธ **FastAPI Cloud**, ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ FastAPI ัƒ ั…ะผะฐั€ั– ัะบะพะผะพะณะฐ ะฟั€ะพัั‚ั–ัˆะธะผ ั– ะท ั‚ะธะผ ัะฐะผะธะผ ะดะพัะฒั–ะดะพะผ ั€ะพะทั€ะพะฑะบะธ, ั‰ะพ ะน ะฟั–ะด ั‡ะฐั ั€ะพะฑะพั‚ะธ ะท FastAPI. + +ะฏ ะฟะพะบะฐะถัƒ ะฒะฐะผ ะบั–ะปัŒะบะฐ ะพัะฝะพะฒะฝะธั… ะบะพะฝั†ะตะฟั†ั–ะน, ะฟั€ะพ ัะบั–, ะนะผะพะฒั–ั€ะฝะพ, ะฒะฐั€ั‚ะพ ะฟะฐะผ'ัั‚ะฐั‚ะธ ะฟั–ะด ั‡ะฐั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั **FastAPI**-ะทะฐัั‚ะพััƒะฝะบัƒ (ั…ะพั‡ะฐ ะฑั–ะปัŒัˆั–ัั‚ัŒ ั–ะท ะฝะธั… ัั‚ะพััƒั”ั‚ัŒัั ะฑัƒะดัŒ-ัะบะธั… ั–ะฝัˆะธั… ั‚ะธะฟั–ะฒ ะฒะตะฑ-ะทะฐัั‚ะพััƒะฝะบั–ะฒ). + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฑั–ะปัŒัˆะต ะดะตั‚ะฐะปะตะน, ะฝะฐ ัะบั– ะฒะฐั€ั‚ะพ ะทะฒะฐะถะฐั‚ะธ, ั‚ะฐ ะดะตัะบั– ั‚ะตั…ะฝั–ะบะธ, ัะบ ั†ะต ะทั€ะพะฑะธั‚ะธ. โœจ diff --git a/docs/uk/docs/deployment/manually.md b/docs/uk/docs/deployment/manually.md new file mode 100644 index 0000000000..d70ec5d5d0 --- /dev/null +++ b/docs/uk/docs/deployment/manually.md @@ -0,0 +1,157 @@ +# ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ัะตั€ะฒะตั€ ะฒั€ัƒั‡ะฝัƒ { #run-a-server-manually } + +## ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะบะพะผะฐะฝะดัƒ `fastapi run` { #use-the-fastapi-run-command } + +ะšะพั€ะพั‚ะบะพ: ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `fastapi run`, ั‰ะพะฑ ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +ะฆะต ัะฟั€ะฐั†ัŽั” ะฒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ. ๐Ÿ˜Ž + +ะฆัŽ ะบะพะผะฐะฝะดัƒ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ั–, ะฝะฐ ัะตั€ะฒะตั€ั– ั‚ะพั‰ะพ. + +## ะกะตั€ะฒะตั€ะธ ASGI { #asgi-servers } + +ะ ะพะทะณะปัะฝัŒะผะพ ะดะตั‚ะฐะปั–. + +FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัั‚ะฐะฝะดะฐั€ั‚ ะดะปั ะฟะพะฑัƒะดะพะฒะธ Python ะฒะตะฑั„ั€ะตะนะผะฒะพั€ะบั–ะฒ ั– ัะตั€ะฒะตั€ั–ะฒ ะฟั–ะด ะฝะฐะทะฒะพัŽ ASGI. FastAPI - ั†ะต ASGI ะฒะตะฑั„ั€ะตะนะผะฒะพั€ะบ. + +ะ“ะพะปะพะฒะฝะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ, ั‰ะพะฑ ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ASGI-ะทะฐัั‚ะพััƒะฝะพะบ) ะฝะฐ ะฒั–ะดะดะฐะปะตะฝั–ะน ัะตั€ะฒะตั€ะฝั–ะน ะผะฐัˆะธะฝั–, - ั†ะต ะฟั€ะพะณั€ะฐะผะฐ ASGI-ัะตั€ะฒะตั€ะฐ ะฝะฐ ะบัˆั‚ะฐะปั‚ **Uvicorn**; ัะฐะผะต ะฒะพะฝะฐ ะฟะพัั‚ะฐั‡ะฐั”ั‚ัŒัั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ัƒ ะบะพะผะฐะฝะดั– `fastapi`. + +ะ„ ะบั–ะปัŒะบะฐ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, ะทะพะบั€ะตะผะฐ: + +* Uvicorn: ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝะธะน ASGI-ัะตั€ะฒะตั€. +* Hypercorn: ASGI-ัะตั€ะฒะตั€, ััƒะผั–ัะฝะธะน ะท HTTP/2 ั– Trio, ัะตั€ะตะด ั–ะฝัˆะธั… ะผะพะถะปะธะฒะพัั‚ะตะน. +* Daphne: ASGI-ัะตั€ะฒะตั€, ัั‚ะฒะพั€ะตะฝะธะน ะดะปั Django Channels. +* Granian: Rust HTTP-ัะตั€ะฒะตั€ ะดะปั Python-ะทะฐัั‚ะพััƒะฝะบั–ะฒ. +* NGINX Unit: NGINX Unit - ะปะตะณะบะต ะน ัƒะฝั–ะฒะตั€ัะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒะธะบะพะฝะฐะฝะฝั ะฒะตะฑะทะฐัั‚ะพััƒะฝะบั–ะฒ. + +## ะกะตั€ะฒะตั€ะฝะฐ ะผะฐัˆะธะฝะฐ ั– ัะตั€ะฒะตั€ะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ { #server-machine-and-server-program } + +ะ„ ะฝะตะฒะตะปะธะบะฐ ะดะตั‚ะฐะปัŒ ั‰ะพะดะพ ะฝะฐะทะฒ, ัะบัƒ ะฒะฐั€ั‚ะพ ะฟะฐะผ'ัั‚ะฐั‚ะธ. ๐Ÿ’ก + +ะกะปะพะฒะพ ยซ**ัะตั€ะฒะตั€**ยป ะทะฐะทะฒะธั‡ะฐะน ะพะทะฝะฐั‡ะฐั” ั– ะฒั–ะดะดะฐะปะตะฝะธะน/ั…ะผะฐั€ะฝะธะน ะบะพะผะฟ'ัŽั‚ะตั€ (ั„ั–ะทะธั‡ะฝะฐ ะฐะฑะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ), ั– ะฟั€ะพะณั€ะฐะผัƒ, ั‰ะพ ะฟั€ะฐั†ัŽั” ะฝะฐ ั†ั–ะน ะผะฐัˆะธะฝั– (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn). + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะบะพะปะธ ะฒะธ ะฑะฐั‡ะธั‚ะต ัะปะพะฒะพ ยซัะตั€ะฒะตั€ยป ะทะฐะณะฐะปะพะผ, ะฒะพะฝะพ ะผะพะถะต ัั‚ะพััƒะฒะฐั‚ะธัั ะฑัƒะดัŒ-ัะบะพะณะพ ะท ั†ะธั… ะดะฒะพั… ะทะฝะฐั‡ะตะฝัŒ. + +ะšะพะปะธ ะนะดะตั‚ัŒัั ะฟั€ะพ ะฒั–ะดะดะฐะปะตะฝัƒ ะผะฐัˆะธะฝัƒ, ั—ั— ั‡ะฐัั‚ะพ ะฝะฐะทะธะฒะฐัŽั‚ัŒ ยซัะตั€ะฒะตั€ยป, ะฐ ั‚ะฐะบะพะถ ยซะผะฐัˆะธะฝะฐยป, ยซVMยป (ะฒั–ั€ั‚ัƒะฐะปัŒะฝะฐ ะผะฐัˆะธะฝะฐ), ยซะฒัƒะทะพะปยป. ะฃัะต ั†ะต ะพะทะฝะฐั‡ะฐั” ั€ั–ะทะฝะพะฒะธะดะธ ะฒั–ะดะดะฐะปะตะฝะพั— ะผะฐัˆะธะฝะธ, ะทะฐะทะฒะธั‡ะฐะน ะท Linux, ะฝะฐ ัะบั–ะน ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต ะฟั€ะพะณั€ะฐะผะธ. + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ { #install-the-server-program } + +ะŸั–ัะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั FastAPI ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ะฟั€ะพะดะฐะบัˆะฝ-ัะตั€ะฒะตั€ Uvicorn ั– ะผะพะถะตั‚ะต ะทะฐะฟัƒัะบะฐั‚ะธ ะนะพะณะพ ะบะพะผะฐะฝะดะพัŽ `fastapi run`. + +ะะปะต ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ASGI-ัะตั€ะฒะตั€ ะฒั€ัƒั‡ะฝัƒ. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ, ะฟั–ัะปั ั‡ะพะณะพ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ัƒัั‚ะฐะฝะพะฒะธั‚ะธ Uvicorn: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +ะŸะพะดั–ะฑะฝะธะน ะฟั€ะพั†ะตั ะทะฐัั‚ะพัะพะฒัƒั”ั‚ัŒัั ะดะพ ะฑัƒะดัŒ-ัะบะพั— ั–ะฝัˆะพั— ASGI-ัะตั€ะฒะตั€ะฝะพั— ะฟั€ะพะณั€ะฐะผะธ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ะพะดะฐะฒัˆะธ `standard`, Uvicorn ะฒัั‚ะฐะฝะพะฒะธั‚ัŒ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต ะดะตัะบั– ั€ะตะบะพะผะตะฝะดะพะฒะฐะฝั– ะดะพะดะฐั‚ะบะพะฒั– ะทะฐะปะตะถะฝะพัั‚ั–. + +ะ—ะพะบั€ะตะผะฐ `uvloop` - ะฒะธัะพะบะพะฟั€ะพะดัƒะบั‚ะธะฒะฝัƒ ะทะฐะผั–ะฝัƒ ยซะฑะตะท ะทะผั–ะฝ ัƒ ะบะพะดั–ยป ะดะปั `asyncio`, ั‰ะพ ััƒั‚ั‚ั”ะฒะพ ะฟั–ะดะฒะธั‰ัƒั” ั€ั–ะฒะฝะพั‡ะฐัะฝั–ัั‚ัŒ ั– ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. + +ะฏะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต FastAPI ั‡ะตั€ะตะท `pip install "fastapi[standard]"`, ะฒะธ ะฒะถะต ะพั‚ั€ะธะผะฐั”ั‚ะต ั– `uvicorn[standard]`. + +/// + +## ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ { #run-the-server-program } + +ะฏะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะธะปะธ ASGI-ัะตั€ะฒะตั€ ะฒั€ัƒั‡ะฝัƒ, ะทะฐะทะฒะธั‡ะฐะน ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะดะฐั‚ะธ ั€ัะดะพะบ ั–ะผะฟะพั€ั‚ัƒ ะฒ ัะฟะตั†ั–ะฐะปัŒะฝะพะผัƒ ั„ะพั€ะผะฐั‚ั–, ั‰ะพะฑ ะฒั–ะฝ ั–ะผะฟะพั€ั‚ัƒะฒะฐะฒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ FastAPI: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะšะพะผะฐะฝะดะฐ `uvicorn main:app` ะพะทะฝะฐั‡ะฐั”: + +* `main`: ั„ะฐะนะป `main.py` (Python ยซะผะพะดัƒะปัŒยป). +* `app`: ะพะฑ'ั”ะบั‚, ัั‚ะฒะพั€ะตะฝะธะน ัƒ `main.py` ั€ัะดะบะพะผ `app = FastAPI()`. + +ะฆะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ: + +```Python +from main import app +``` + +/// + +ะšะพะถะฝะฐ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฝะฐ ASGI-ัะตั€ะฒะตั€ะฝะฐ ะฟั€ะพะณั€ะฐะผะฐ ะผะฐั‚ะธะผะต ะฟะพะดั–ะฑะฝัƒ ะบะพะผะฐะฝะดัƒ; ั‡ะธั‚ะฐะนั‚ะต ะฑั–ะปัŒัˆะต ะฒ ั—ั…ะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +Uvicorn ั‚ะฐ ั–ะฝัˆั– ัะตั€ะฒะตั€ะธ ะฟั–ะดั‚ั€ะธะผัƒัŽั‚ัŒ ะพะฟั†ั–ัŽ `--reload`, ะบะพั€ะธัะฝัƒ ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ. + +ะžะฟั†ั–ั `--reload` ัะฟะพะถะธะฒะฐั” ะทะฝะฐั‡ะฝะพ ะฑั–ะปัŒัˆะต ั€ะตััƒั€ัั–ะฒ, ั” ะผะตะฝัˆ ัั‚ะฐะฑั–ะปัŒะฝะพัŽ ั‚ะพั‰ะพ. + +ะ’ะพะฝะฐ ะดัƒะถะต ะดะพะฟะพะผะฐะณะฐั” ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ, ะฐะปะต ั—ั— ะฝะต ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒ ะฟั€ะพะดะฐะบัˆะฝั–. + +/// + +## ะšะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployment-concepts } + +ะฆั– ะฟั€ะธะบะปะฐะดะธ ะทะฐะฟัƒัะบะฐัŽั‚ัŒ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ (ะฝะฐะฟั€ะธะบะปะฐะด, Uvicorn), ะฟั–ะดะฝั–ะผะฐัŽั‡ะธ ะพะดะธะฝ ะฟั€ะพั†ะตั, ั‰ะพ ัะปัƒั…ะฐั” ะฒัั– IP (`0.0.0.0`) ะฝะฐ ะฒะธะทะฝะฐั‡ะตะฝะพะผัƒ ะฟะพั€ั‚ัƒ (ะฝะฐะฟั€ะธะบะปะฐะด, `80`). + +ะฆะต ะฑะฐะทะพะฒะฐ ั–ะดะตั. ะะปะต, ะนะผะพะฒั–ั€ะฝะพ, ะฒะฐะผ ะทะฝะฐะดะพะฑะธั‚ัŒัั ะฟะพะดะฑะฐั‚ะธ ั‰ะต ะฟั€ะพ ั‚ะฐะบะต: + +* ะ‘ะตะทะฟะตะบะฐ - HTTPS +* ะะฒั‚ะพะทะฐะฟัƒัะบ +* ะŸะตั€ะตะทะฐะฟัƒัะบะธ +* ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะทะฐะฟัƒั‰ะตะฝะธั… ะฟั€ะพั†ะตัั–ะฒ) +* ะŸะฐะผ'ัั‚ัŒ +* ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ + +ะฃ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั… ั ั€ะพะทะฟะพะฒั–ะผ ะฑั–ะปัŒัˆะต ะฟั€ะพ ะบะพะถะฝัƒ ะท ั†ะธั… ะบะพะฝั†ะตะฟั†ั–ะน, ัะบ ะฟั€ะพ ะฝะธั… ะดัƒะผะฐั‚ะธ, ั– ะฝะฐะฒะตะดัƒ ะบะพะฝะบั€ะตั‚ะฝั– ะฟั€ะธะบะปะฐะดะธ ั‚ะฐ ัั‚ั€ะฐั‚ะตะณั–ั— ะดะปั ั—ั… ะพะฟั€ะฐั†ัŽะฒะฐะฝะฝั. ๐Ÿš€ diff --git a/docs/uk/docs/deployment/server-workers.md b/docs/uk/docs/deployment/server-workers.md new file mode 100644 index 0000000000..81a8bd2a4d --- /dev/null +++ b/docs/uk/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# ะŸั€ะฐั†ั–ะฒะฝะธะบะธ ัะตั€ะฒะตั€ะฐ - Uvicorn ะท ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ { #server-workers-uvicorn-with-workers } + +ะŸะพะฒะตั€ะฝั–ะผะพัั ะดะพ ะฟะพะฟะตั€ะตะดะฝั–ั… ะบะพะฝั†ะตะฟั†ั–ะน ั€ะพะทะณะพั€ั‚ะฐะฝะฝั: + +- ะ‘ะตะทะฟะตะบะฐ - HTTPS +- ะ—ะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ +- ะŸะตั€ะตะทะฐะฟัƒัะบะธ +- ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะฟั€ะพั†ะตัั–ะฒ, ั‰ะพ ะฒะธะบะพะฝัƒัŽั‚ัŒัั) +- ะŸะฐะผ'ัั‚ัŒ +- ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ + +ะ”ะพ ั†ัŒะพะณะพ ะผะพะผะตะฝั‚ัƒ, ะฟั€ะพั…ะพะดัั‡ะธ ะฒัั– ะฝะฐะฒั‡ะฐะปัŒะฝั– ะฟะพัั–ะฑะฝะธะบะธ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะทะฐะฟัƒัะบะฐะปะธ ัะตั€ะฒะตั€ะฝัƒ ะฟั€ะพะณั€ะฐะผัƒ, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะบะพะผะฐะฝะดัƒ `fastapi`, ัะบะฐ ะทะฐะฟัƒัะบะฐั” Uvicorn ัƒ ะฒะธะณะปัะดั– ะพะดะฝะพะณะพ ะฟั€ะพั†ะตััƒ. + +ะŸั–ะด ั‡ะฐั ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะฒะธ, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะทะฐั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ะฟั€ะพั†ะตัั–ะฒ, ั‰ะพะฑ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบั–ะปัŒะบะฐ ัะดะตั€ ั– ะพะฑั€ะพะฑะปัั‚ะธ ะฑั–ะปัŒัˆะต ะทะฐะฟะธั‚ั–ะฒ. + +ะฏะบ ะฒะธ ะฑะฐั‡ะธะปะธ ะฒ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฟั€ะพ [ะšะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั](concepts.md){.internal-link target=_blank}, ั–ัะฝัƒั” ะบั–ะปัŒะบะฐ ัั‚ั€ะฐั‚ะตะณั–ะน, ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ. + +ะขัƒั‚ ั ะฟะพะบะฐะถัƒ, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Uvicorn ั–ะท ะฟั€ะพั†ะตัะฐะผะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะฐะผะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะบะพะผะฐะฝะดะธ `fastapi` ะฐะฑะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะบะพะผะฐะฝะดะธ `uvicorn`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะพะฝั‚ะตะนะฝะตั€ะธ, ะฝะฐะฟั€ะธะบะปะฐะด ะท Docker ะฐะฑะพ Kubernetes, ั ั€ะพะทะฟะพะฒั–ะผ ะฟั€ะพ ั†ะต ะฑั–ะปัŒัˆะต ะฒ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั–: [FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐั… - Docker](docker.md){.internal-link target=_blank}. + +ะ—ะพะบั€ะตะผะฐ, ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ ะฒ Kubernetes ะฒะฐะผ, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ะฝะต ะฒะฐั€ั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ, ะฝะฐั‚ะพะผั–ัั‚ัŒ ะทะฐะฟัƒัะบะฐั‚ะธ ะพะดะธะฝ ะฟั€ะพั†ะตั Uvicorn ะฝะฐ ะบะพะฝั‚ะตะนะฝะตั€. ะะปะต ะฟั€ะพ ั†ะต ั ั€ะพะทะฟะพะฒั–ะผ ะฟั–ะทะฝั–ัˆะต ะฒ ั‚ะพะผัƒ ั€ะพะทะดั–ะปั–. + +/// + +## ะšั–ะปัŒะบะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ { #multiple-workers } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ะบะพะผะฐะฝะดะฝะพะณะพ ั€ัะดะบะฐ `--workers`: + +//// tab | `fastapi` + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะพะผะฐะฝะดัƒ `fastapi`: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server ๐Ÿš€ + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module ๐Ÿ main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +ะฏะบั‰ะพ ะฒะธ ะฒั–ะดะดะฐั”ั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะพะผะฐะฝะดัƒ `uvicorn` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +ะ„ะดะธะฝะฐ ะฝะพะฒะฐ ะพะฟั†ั–ั ั‚ัƒั‚ โ€” `--workers`, ัะบะฐ ะฒะบะฐะทัƒั” Uvicorn ะทะฐะฟัƒัั‚ะธั‚ะธ 4 ะฟั€ะพั†ะตัะธ-ะฟั€ะฐั†ั–ะฒะฝะธะบะธ. + +ะขะฐะบะพะถ ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ, ั‰ะพ ะฒะธะฒะพะดะธั‚ัŒัั PID ะบะพะถะฝะพะณะพ ะฟั€ะพั†ะตััƒ: `27365` ะดะปั ะฑะฐั‚ัŒะบั–ะฒััŒะบะพะณะพ ะฟั€ะพั†ะตััƒ (ั†ะต ะผะตะฝะตะดะถะตั€ ะฟั€ะพั†ะตัั–ะฒ) ั– ะฟะพ ะพะดะฝะพะผัƒ ะดะปั ะบะพะถะฝะพะณะพ ะฟั€ะพั†ะตััƒ-ะฟั€ะฐั†ั–ะฒะฝะธะบะฐ: `27368`, `27369`, `27370` ั– `27367`. + +## ะšะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั { #deployment-concepts } + +ะขัƒั‚ ะฒะธ ะฟะพะฑะฐั‡ะธะปะธ, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ, ั‰ะพะฑ ะฟะฐั€ะฐะปะตะปั–ะทัƒะฒะฐั‚ะธ ะฒะธะบะพะฝะฐะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ, ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบั–ะปัŒะบะฐ ัะดะตั€ ะฟั€ะพั†ะตัะพั€ะฐ ั‚ะฐ ะพะฑัะปัƒะณะพะฒัƒะฒะฐั‚ะธ ะฑั–ะปัŒัˆะต ะทะฐะฟะธั‚ั–ะฒ. + +ะ†ะท ะฝะฐะฒะตะดะตะฝะพะณะพ ะฒะธั‰ะต ัะฟะธัะบัƒ ะบะพะฝั†ะตะฟั†ั–ะน ั€ะพะทะณะพั€ั‚ะฐะฝะฝั, ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ะณะพะปะพะฒะฝะธะผ ั‡ะธะฝะพะผ ะดะพะฟะพะผะพะถะต ะท ั‡ะฐัั‚ะธะฝะพัŽ ะฟั€ะพ ั€ะตะฟะปั–ะบะฐั†ั–ัŽ ั– ั‚ั€ะพั…ะธ ะท ะฟะตั€ะตะทะฐะฟัƒัะบะฐะผะธ, ะฐะปะต ะฟั€ะพ ั–ะฝัˆะต ะฒัะต ั‰ะต ั‚ั€ะตะฑะฐ ะฟะพะดะฑะฐั‚ะธ: + +- ะ‘ะตะทะฟะตะบะฐ - HTTPS +- ะ—ะฐะฟัƒัะบ ะฟั–ะด ั‡ะฐั ัั‚ะฐั€ั‚ัƒ +- ***ะŸะตั€ะตะทะฐะฟัƒัะบะธ*** +- ะ ะตะฟะปั–ะบะฐั†ั–ั (ะบั–ะปัŒะบั–ัั‚ัŒ ะฟั€ะพั†ะตัั–ะฒ, ั‰ะพ ะฒะธะบะพะฝัƒัŽั‚ัŒัั) +- ะŸะฐะผ'ัั‚ัŒ +- ะŸะพะฟะตั€ะตะดะฝั– ะบั€ะพะบะธ ะฟะตั€ะตะด ะทะฐะฟัƒัะบะพะผ + +## ะšะพะฝั‚ะตะนะฝะตั€ะธ ั– Docker { #containers-and-docker } + +ะฃ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั– ะฟั€ะพ [FastAPI ัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐั… - Docker](docker.md){.internal-link target=_blank} ั ะฟะพััะฝัŽ ะบั–ะปัŒะบะฐ ัั‚ั€ะฐั‚ะตะณั–ะน, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะดะปั ั–ะฝัˆะธั… ะบะพะฝั†ะตะฟั†ั–ะน ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. + +ะฏ ะฟะพะบะฐะถัƒ, ัะบ ะฟะพะฑัƒะดัƒะฒะฐั‚ะธ ะฒะปะฐัะฝะธะน ะพะฑั€ะฐะท ะท ะฝัƒะปั ะดะปั ะทะฐะฟัƒัะบัƒ ะพะดะฝะพะณะพ ะฟั€ะพั†ะตััƒ Uvicorn. ะฆะต ะฟั€ะพัั‚ะธะน ะฟั€ะพั†ะตั ั–, ะนะผะพะฒั–ั€ะฝะพ, ัะฐะผะต ั‚ะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ั€ะพะทะฟะพะดั–ะปะตะฝะพั— ัะธัั‚ะตะผะธ ะบะตั€ัƒะฒะฐะฝะฝั ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ, ั‚ะฐะบะพั— ัะบ Kubernetes. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ-ะฟั€ะฐั†ั–ะฒะฝะธะบั–ะฒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะฟะฐั€ะฐะผะตั‚ั€ะฐ CLI `--workers` ัƒ ะบะพะผะฐะฝะดะฐั… `fastapi` ะฐะฑะพ `uvicorn`, ั‰ะพะฑ ัะบะพั€ะธัั‚ะฐั‚ะธัั ะฟะตั€ะตะฒะฐะณะฐะผะธ ะฑะฐะณะฐั‚ะพัะดะตั€ะฝะธั… ะฟั€ะพั†ะตัะพั€ั–ะฒ ั– ะทะฐะฟัƒัะบะฐั‚ะธ ะบั–ะปัŒะบะฐ ะฟั€ะพั†ะตัั–ะฒ ะฟะฐั€ะฐะปะตะปัŒะฝะพ. + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐัั‚ะพััƒะฒะฐั‚ะธ ั†ั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั‚ะฐ ั–ะดะตั—, ัะบั‰ะพ ะฝะฐะปะฐัˆั‚ะพะฒัƒั”ั‚ะต ะฒะปะฐัะฝัƒ ัะธัั‚ะตะผัƒ ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ั– ัะฐะผะพัั‚ั–ะนะฝะพ ะดะฑะฐั”ั‚ะต ะฟั€ะพ ั–ะฝัˆั– ะบะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. + +ะŸะตั€ะตะณะปัะฝัŒั‚ะต ะฝะฐัั‚ัƒะฟะฝะธะน ั€ะพะทะดั–ะป, ั‰ะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฟั€ะพ FastAPI ะท ะบะพะฝั‚ะตะนะฝะตั€ะฐะผะธ (ะฝะฐะฟั€ะธะบะปะฐะด Docker ั– Kubernetes). ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ ั†ั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั‚ะฐะบะพะถ ะผะฐัŽั‚ัŒ ะฟั€ะพัั‚ั– ัะฟะพัะพะฑะธ ะฒะธั€ั–ัˆะธั‚ะธ ั–ะฝัˆั– ะบะพะฝั†ะตะฟั†ั–ั— ั€ะพะทะณะพั€ั‚ะฐะฝะฝั. โœจ diff --git a/docs/uk/docs/deployment/versions.md b/docs/uk/docs/deployment/versions.md new file mode 100644 index 0000000000..4f6d1b01a2 --- /dev/null +++ b/docs/uk/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# ะŸั€ะพ ะฒะตั€ัั–ั— FastAPI { #about-fastapi-versions } + +**FastAPI** ัƒะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัƒ ะฟั€ะพะดะฐะบัˆะฝั– ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะทะฐัั‚ะพััƒะฝะบะฐั… ั– ัะธัั‚ะตะผะฐั…. ะŸะพะบั€ะธั‚ั‚ั ั‚ะตัั‚ะฐะผะธ ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ะฝะฐ ั€ั–ะฒะฝั– 100%. ะะปะต ั€ะพะทั€ะพะฑะบะฐ ะฒัะต ั‰ะต ั€ัƒั…ะฐั”ั‚ัŒัั ัˆะฒะธะดะบะพ. + +ะะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– ะดะพะดะฐัŽั‚ัŒัั ั‡ะฐัั‚ะพ, ะฟะพะผะธะปะบะธ ั€ะตะณัƒะปัั€ะฝะพ ะฒะธะฟั€ะฐะฒะปััŽั‚ัŒัั, ะฐ ะบะพะด ะฟะพัั‚ั–ะนะฝะพ ะฟะพะปั–ะฟัˆัƒั”ั‚ัŒัั. + +ะขะพะผัƒ ะฟะพั‚ะพั‡ะฝั– ะฒะตั€ัั–ั— ะฒัะต ั‰ะต `0.x.x`, ั†ะต ะฒั–ะดะพะฑั€ะฐะถะฐั” ั‚ะต, ั‰ะพ ะบะพะถะฝะฐ ะฒะตั€ัั–ั ะฟะพั‚ะตะฝั†ั–ะนะฝะพ ะผะพะถะต ะผั–ัั‚ะธั‚ะธ ะฝะตััƒะผั–ัะฝั– ะทะผั–ะฝะธ. ะฆะต ะฒั–ะดะฟะพะฒั–ะดะฐั” ะฟั€ะฐะฒะธะปะฐะผ ะกะตะผะฐะฝั‚ะธั‡ะฝะพะณะพ ะฒะตั€ัั–ะพะฝัƒะฒะฐะฝะฝั. + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฟั€ะพะดะฐะบัˆะฝ-ะทะฐัั‚ะพััƒะฝะบะธ ะท **FastAPI** ะฒะถะต ะทะฐั€ะฐะท (ั–, ะนะผะพะฒั–ั€ะฝะพ, ั€ะพะฑะธั‚ะต ั†ะต ะฒะถะต ะฟะตะฒะฝะธะน ั‡ะฐั), ะฟั€ะพัั‚ะพ ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฒะตั€ัั–ัŽ, ัะบะฐ ะบะพั€ะตะบั‚ะฝะพ ะฟั€ะฐั†ัŽั” ะท ั€ะตัˆั‚ะพัŽ ะฒะฐัˆะพะณะพ ะบะพะดัƒ. + +## ะ—ะฐั„ั–ะบััƒะนั‚ะต ะฒะตั€ัั–ัŽ `fastapi` { #pin-your-fastapi-version } + +ะŸะตั€ัˆะต, ั‰ะพ ัะปั–ะด ะทั€ะพะฑะธั‚ะธ, - ยซะทะฐั„ั–ะบััƒะฒะฐั‚ะธยป ะฒะตั€ัั–ัŽ **FastAPI**, ัะบัƒ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต, ะดะพ ะบะพะฝะบั€ะตั‚ะฝะพั— ะพัั‚ะฐะฝะฝัŒะพั— ะฒะตั€ัั–ั—, ั‰ะพ, ัะบ ะฒะธ ะทะฝะฐั”ั‚ะต, ะฟั€ะฐะฒะธะปัŒะฝะพ ะฟั€ะฐั†ัŽั” ะดะปั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ัƒ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒะตั€ัั–ั `0.112.0`. + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั„ะฐะนะป `requirements.txt`, ะฒะธ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ ะฒะตั€ัั–ัŽ ั‚ะฐะบ: + +```txt +fastapi[standard]==0.112.0 +``` + +ั†ะต ะพะทะฝะฐั‡ะฐั‚ะธะผะต, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ัะฐะผะต ะฒะตั€ัั–ัŽ `0.112.0`. + +ะะฑะพ ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะทะฐั„ั–ะบััƒะฒะฐั‚ะธ ั‚ะฐะบ: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +ั†ะต ะพะทะฝะฐั‡ะฐั‚ะธะผะต, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ะฒะตั€ัั–ั— `0.112.0` ั– ะฒะธั‰ะต, ะฐะปะต ะผะตะฝัˆะต `0.113.0`, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะตั€ัั–ั `0.112.2` ะฒัะต ั‰ะต ะฑัƒะดะต ะฟั€ะธะนะฝัั‚ะฝะพัŽ. + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั–ะฝัˆะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ะบะตั€ัƒะฒะฐะฝะฝั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝัะผะธ, ัะบ-ะพั‚ `uv`, Poetry, Pipenv ั‡ะธ ั–ะฝัˆั–, ัƒ ะฒัั–ั… ะฝะธั… ั” ัะฟะพัั–ะฑ ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝั– ะฒะตั€ัั–ั— ะดะปั ะฒะฐัˆะธั… ะฟะฐะบะตั‚ั–ะฒ. + +## ะ”ะพัั‚ัƒะฟะฝั– ะฒะตั€ัั–ั— { #available-versions } + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะณะปัะฝัƒั‚ะธ ะดะพัั‚ัƒะฟะฝั– ะฒะตั€ัั–ั— (ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ะฟะพั‚ะพั‡ะฝัƒ ะพัั‚ะฐะฝะฝัŽ) ะฒ [ะŸั€ะธะผั–ั‚ะบะฐั… ะดะพ ะฒะธะฟัƒัะบั–ะฒ](../release-notes.md){.internal-link target=_blank}. + +## ะŸั€ะพ ะฒะตั€ัั–ั— { #about-versions } + +ะ’ั–ะดะฟะพะฒั–ะดะฝะพ ะดะพ ะฟั€ะฐะฒะธะป ะกะตะผะฐะฝั‚ะธั‡ะฝะพะณะพ ะฒะตั€ัั–ะพะฝัƒะฒะฐะฝะฝั, ะฑัƒะดัŒ-ัะบะฐ ะฒะตั€ัั–ั ะฝะธะถั‡ะต `1.0.0` ะฟะพั‚ะตะฝั†ั–ะนะฝะพ ะผะพะถะต ะผั–ัั‚ะธั‚ะธ ะฝะตััƒะผั–ัะฝั– ะทะผั–ะฝะธ. + +FastAPI ั‚ะฐะบะพะถ ะดะพั‚ั€ะธะผัƒั”ั‚ัŒัั ะฟั€ะฐะฒะธะปะฐ, ั‰ะพ ะฑัƒะดัŒ-ัะบะฐ ะทะผั–ะฝะฐ ยซPATCHยป-ะฒะตั€ัั–ั— - ั†ะต ะฒะธะฟั€ะฐะฒะปะตะฝะฝั ะฟะพะผะธะปะพะบ ั– ะทะผั–ะฝะธ ะฑะตะท ะฟะพั€ัƒัˆะตะฝัŒ ััƒะผั–ัะฝะพัั‚ั–. + +/// tip | ะŸะพั€ะฐะดะฐ + +ยซPATCHยป - ั†ะต ะพัั‚ะฐะฝะฝั” ั‡ะธัะปะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ `0.2.3` PATCH-ะฒะตั€ัั–ั - ั†ะต `3`. + +/// + +ะขะพะถ ะฒะธ ะผะพะถะตั‚ะต ะทะฐั„ั–ะบััƒะฒะฐั‚ะธ ะฒะตั€ัั–ัŽ ั‚ะฐะบ: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +ะะตััƒะผั–ัะฝั– ะทะผั–ะฝะธ ั‚ะฐ ะฝะพะฒั– ะผะพะถะปะธะฒะพัั‚ั– ะดะพะดะฐัŽั‚ัŒัั ัƒ ยซMINORยป-ะฒะตั€ัั–ัั…. + +/// tip | ะŸะพั€ะฐะดะฐ + +ยซMINORยป - ั†ะต ั‡ะธัะปะพ ะฟะพัะตั€ะตะดะธะฝั–, ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ `0.2.3` MINOR-ะฒะตั€ัั–ั - ั†ะต `2`. + +/// + +## ะžะฝะพะฒะปะตะฝะฝั ะฒะตั€ัั–ะน FastAPI { #upgrading-the-fastapi-versions } + +ะ’ะธ ะฟะพะฒะธะฝะฝั– ะดะพะดะฐั‚ะธ ั‚ะตัั‚ะธ ะดะปั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะ— **FastAPI** ั†ะต ะดัƒะถะต ะปะตะณะบะพ (ะทะฐะฒะดัะบะธ Starlette), ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ: [ะขะตัั‚ัƒะฒะฐะฝะฝั](../tutorial/testing.md){.internal-link target=_blank} + +ะŸั–ัะปั ั‚ะพะณะพ ัะบ ัƒ ะฒะฐั ั” ั‚ะตัั‚ะธ, ะฒะธ ะผะพะถะตั‚ะต ะพะฝะพะฒะธั‚ะธ ะฒะตั€ัั–ัŽ **FastAPI** ะดะพ ะฝะพะฒั–ัˆะพั— ั– ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะฒะตััŒ ะฒะฐัˆ ะบะพะด ะฟั€ะฐั†ัŽั” ะฟั€ะฐะฒะธะปัŒะฝะพ, ะทะฐะฟัƒัั‚ะธะฒัˆะธ ั‚ะตัั‚ะธ. + +ะฏะบั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั” ะฐะฑะพ ะฟั–ัะปั ะฒะฝะตัะตะฝะฝั ะฝะตะพะฑั…ั–ะดะฝะธั… ะทะผั–ะฝ ั– ะฟั€ะพั…ะพะดะถะตะฝะฝั ะฒัั–ั… ั‚ะตัั‚ั–ะฒ, ะทะฐั„ั–ะบััƒะนั‚ะต ะฒะฐัˆัƒ ะฒะตั€ัั–ัŽ `fastapi` ะฝะฐ ั†ั–ะน ะฝะพะฒั–ะน ะฒะตั€ัั–ั—. + +## ะŸั€ะพ Starlette { #about-starlette } + +ะะต ะฒะฐั€ั‚ะพ ั„ั–ะบััƒะฒะฐั‚ะธ ะฒะตั€ัั–ัŽ `starlette`. + +ะ ั–ะทะฝั– ะฒะตั€ัั–ั— **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒ ะบะพะฝะบั€ะตั‚ะฝัƒ ะฝะพะฒั–ัˆัƒ ะฒะตั€ัั–ัŽ Starlette. + +ะžั‚ะถะต, ะฟั€ะพัั‚ะพ ะดะพะทะฒะพะปัŒั‚ะต **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดะฝัƒ ะฒะตั€ัั–ัŽ Starlette. + +## ะŸั€ะพ Pydantic { #about-pydantic } + +Pydantic ะฒะบะปัŽั‡ะฐั” ั‚ะตัั‚ะธ ะดะปั **FastAPI** ั€ะฐะทะพะผ ั–ะท ะฒะปะฐัะฝะธะผะธ ั‚ะตัั‚ะฐะผะธ, ั‚ะพะผัƒ ะฝะพะฒั– ะฒะตั€ัั–ั— Pydantic (ะฒะธั‰ะต `1.0.0`) ะทะฐะฒะถะดะธ ััƒะผั–ัะฝั– ะท FastAPI. + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐั„ั–ะบััƒะฒะฐั‚ะธ Pydantic ะฝะฐ ะฑัƒะดัŒ-ัะบั–ะน ะฒะตั€ัั–ั— ะฒะธั‰ะต `1.0.0`, ัะบะฐ ะฒะฐะผ ะฟั–ะดั…ะพะดะธั‚ัŒ. + +ะะฐะฟั€ะธะบะปะฐะด: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/uk/docs/environment-variables.md b/docs/uk/docs/environment-variables.md new file mode 100644 index 0000000000..b61fd011f6 --- /dev/null +++ b/docs/uk/docs/environment-variables.md @@ -0,0 +1,298 @@ +# ะ—ะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั { #environment-variables } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฒะถะต ะทะฝะฐั”ั‚ะต, ั‰ะพ ั‚ะฐะบะต ยซะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝัยป ั– ัะบ ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะตะน ั€ะพะทะดั–ะป. + +/// + +ะ—ะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั (ั‚ะฐะบะพะถ ะฒั–ะดะพะผะฐ ัะบ ยซenv varยป) - ั†ะต ะทะผั–ะฝะฝะฐ, ั‰ะพ ั–ัะฝัƒั” ะฟะพะทะฐ ะบะพะดะพะผ Python, ะฒ ะพะฟะตั€ะฐั†ั–ะนะฝั–ะน ัะธัั‚ะตะผั–, ั– ะผะพะถะต ะฑัƒั‚ะธ ะฟั€ะพั‡ะธั‚ะฐะฝะฐ ะฒะฐัˆะธะผ ะบะพะดะพะผ Python (ะฐ ั‚ะฐะบะพะถ ั–ะฝัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ). + +ะ—ะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะบะพั€ะธัะฝั– ะดะปั ั€ะพะฑะพั‚ะธ ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ ะทะฐัั‚ะพััƒะฝะบัƒ, ัะบ ั‡ะฐัั‚ะธะฝะฐ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั Python ั‚ะพั‰ะพ. + +## ะกั‚ะฒะพั€ะตะฝะฝั ั– ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั { #create-and-use-env-vars } + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะฒ ะพะฑะพะปะพะฝั†ั– (ั‚ะตั€ะผั–ะฝะฐะปั–) ะฑะตะท ัƒั‡ะฐัั‚ั– Python: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั MY_NAME ะบะพะผะฐะฝะดะพัŽ +$ export MY_NAME="Wade Wilson" + +// ะŸะพั‚ั–ะผ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั—ั— ะท ั–ะฝัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ, ะฝะฐะฟั€ะธะบะปะฐะด +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ั—ั— ะท ั–ะฝัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ, ะฝะฐะฟั€ะธะบะปะฐะด +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## ะงะธั‚ะฐะฝะฝั ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั ะฒ Python { #read-env-vars-in-python } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะฟะพะทะฐ Python, ัƒ ั‚ะตั€ะผั–ะฝะฐะปั– (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธะผ ั–ะฝัˆะธะผ ัะฟะพัะพะฑะพะผ), ะฐ ะฟะพั‚ั–ะผ ะทั‡ะธั‚ะฐั‚ะธ ั—ั… ัƒ Python. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ั„ะฐะนะป `main.py` ะท: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ั€ัƒะณะธะน ะฐั€ะณัƒะผะตะฝั‚ ะดะพ `os.getenv()` - ั†ะต ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ัะบะต ะฑัƒะดะต ะฟะพะฒะตั€ะฝะตะฝะพ. + +ะฏะบั‰ะพ ะนะพะณะพ ะฝะต ะฒะบะฐะทะฐะฝะพ, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ั†ะต `None`. ะขัƒั‚ ะผะธ ะฝะฐะดะฐั”ะผะพ `"World"` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. + +/// + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ั†ัŽ ะฟั€ะพะณั€ะฐะผัƒ Python: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// ะขัƒั‚ ะผะธ ั‰ะต ะฝะต ะฒัั‚ะฐะฝะพะฒะปัŽั”ะผะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั +$ python main.py + +// ะžัะบั–ะปัŒะบะธ ะผะธ ะฝะต ะฒัั‚ะฐะฝะพะฒะธะปะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั, ะพั‚ั€ะธะผัƒั”ะผะพ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ + +Hello World from Python + +// ะะปะต ัะบั‰ะพ ัะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ะธะผะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั +$ export MY_NAME="Wade Wilson" + +// ะ ะฟะพั‚ั–ะผ ะทะฝะพะฒัƒ ะฒะธะบะปะธั‡ะตะผะพ ะฟั€ะพะณั€ะฐะผัƒ +$ python main.py + +// ะขะตะฟะตั€ ะฒะพะฝะฐ ะผะพะถะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// ะขัƒั‚ ะผะธ ั‰ะต ะฝะต ะฒัั‚ะฐะฝะพะฒะปัŽั”ะผะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั +$ python main.py + +// ะžัะบั–ะปัŒะบะธ ะผะธ ะฝะต ะฒัั‚ะฐะฝะพะฒะธะปะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั, ะพั‚ั€ะธะผัƒั”ะผะพ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ + +Hello World from Python + +// ะะปะต ัะบั‰ะพ ัะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ะธะผะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั +$ $Env:MY_NAME = "Wade Wilson" + +// ะ ะฟะพั‚ั–ะผ ะทะฝะพะฒัƒ ะฒะธะบะปะธั‡ะตะผะพ ะฟั€ะพะณั€ะฐะผัƒ +$ python main.py + +// ะขะตะฟะตั€ ะฒะพะฝะฐ ะผะพะถะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั + +Hello Wade Wilson from Python +``` + +
+ +//// + +ะžัะบั–ะปัŒะบะธ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะผะพะถะฝะฐ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฟะพะทะฐ ะบะพะดะพะผ, ะฐะปะต ั‡ะธั‚ะฐั‚ะธ ะฒ ะบะพะดั–, ั– ั—ั… ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะทะฑะตั€ั–ะณะฐั‚ะธ (ั„ั–ะบััƒะฒะฐั‚ะธ ัƒ `git`) ั€ะฐะทะพะผ ะท ั–ะฝัˆะธะผะธ ั„ะฐะนะปะฐะผะธ, ั—ั… ั‡ะฐัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ะน ะฐะฑะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ. + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั ะปะธัˆะต ะดะปั ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผะธ, ะฒะพะฝะฐ ะฑัƒะดะต ะดะพัั‚ัƒะฟะฝะฐ ั‚ั–ะปัŒะบะธ ั†ั–ะน ะฟั€ะพะณั€ะฐะผั– ั– ะปะธัˆะต ะฝะฐ ั‡ะฐั ั—ั— ะฒะธะบะพะฝะฐะฝะฝั. + +ะฉะพะฑ ะทั€ะพะฑะธั‚ะธ ั†ะต, ัั‚ะฒะพั€ั–ั‚ัŒ ั—ั— ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฟะตั€ะตะด ะบะพะผะฐะฝะดะพัŽ ะทะฐะฟัƒัะบัƒ ะฟั€ะพะณั€ะฐะผะธ, ะฒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ั€ัะดะบัƒ: + +
+ +```console +// ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั MY_NAME ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ั†ัŒะพะผัƒ ะฒะธะบะปะธะบัƒ ะฟั€ะพะณั€ะฐะผะธ +$ MY_NAME="Wade Wilson" python main.py + +// ะขะตะฟะตั€ ะฒะพะฝะฐ ะผะพะถะต ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั + +Hello Wade Wilson from Python + +// ะŸั–ัะปั ั†ัŒะพะณะพ ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั ะฑั–ะปัŒัˆะต ะฝะต ั–ัะฝัƒั” +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ัƒ The Twelve-Factor App: Config. + +/// + +## ะขะธะฟะธ ั– ะฟะตั€ะตะฒั–ั€ะบะฐ { #types-and-validation } + +ะฆั– ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะผะพะถัƒั‚ัŒ ะผั–ัั‚ะธั‚ะธ ะปะธัˆะต ั‚ะตะบัั‚ะพะฒั– ัั‚ั€ะพะบะธ, ะพัะบั–ะปัŒะบะธ ะฒะพะฝะธ ะทะพะฒะฝั–ัˆะฝั– ั‰ะพะดะพ Python ั– ะผะฐัŽั‚ัŒ ะฑัƒั‚ะธ ััƒะผั–ัะฝะธะผะธ ะท ั–ะฝัˆะธะผะธ ะฟั€ะพะณั€ะฐะผะฐะผะธ ั‚ะฐ ั€ะตัˆั‚ะพัŽ ัะธัั‚ะตะผะธ (ั– ะฝะฐะฒั–ั‚ัŒ ะท ั€ั–ะทะฝะธะผะธ ะพะฟะตั€ะฐั†ั–ะนะฝะธะผะธ ัะธัั‚ะตะผะฐะผะธ, ัะบ-ะพั‚ Linux, Windows, macOS). + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฑัƒะดัŒ-ัะบะต ะทะฝะฐั‡ะตะฝะฝั, ะฟั€ะพั‡ะธั‚ะฐะฝะต ะฒ Python ะทั– ะทะผั–ะฝะฝะพั— ะพั‚ะพั‡ะตะฝะฝั, ะฑัƒะดะต `str`, ะฐ ะฑัƒะดัŒ-ัะบะต ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะพ ั–ะฝัˆะพะณะพ ั‚ะธะฟัƒ ะฐะฑะพ ะฑัƒะดัŒ-ัะบะฐ ะฟะตั€ะตะฒั–ั€ะบะฐ ะผะฐั” ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั ะฒ ะบะพะดั–. + +ะ’ะธ ะดั–ะทะฝะฐั”ั‚ะตัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั ะดะปั ั€ะพะฑะพั‚ะธ ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒ ั€ะพะทะดั–ะปั– [ะŸั€ะพััƒะฝัƒั‚ะธะน ะฟะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ - ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั– ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั](./advanced/settings.md){.internal-link target=_blank}. + +## ะ—ะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั `PATH` { #path-environment-variable } + +ะ„ ัะฟะตั†ั–ะฐะปัŒะฝะฐ ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั `PATH`, ัะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะพะฟะตั€ะฐั†ั–ะนะฝั– ัะธัั‚ะตะผะธ (Linux, macOS, Windows) ะดะปั ะฟะพัˆัƒะบัƒ ะฟั€ะพะณั€ะฐะผ ะดะปั ะทะฐะฟัƒัะบัƒ. + +ะ—ะฝะฐั‡ะตะฝะฝั ะทะผั–ะฝะฝะพั— `PATH` - ั†ะต ะดะพะฒะณะฐ ัั‚ั€ะพะบะฐ, ั‰ะพ ัะบะปะฐะดะฐั”ั‚ัŒัั ะท ะบะฐั‚ะฐะปะพะณั–ะฒ, ั€ะพะทะดั–ะปะตะฝะธั… ะดะฒะพะบั€ะฐะฟะบะพัŽ `:` ัƒ Linux ั– macOS ั‚ะฐ ะบั€ะฐะฟะบะพัŽ ะท ะบะพะผะพัŽ `;` ัƒ Windows. + +ะะฐะฟั€ะธะบะปะฐะด, ะทะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั `PATH` ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ะผะฐั” ัˆัƒะบะฐั‚ะธ ะฟั€ะพะณั€ะฐะผะธ ะฒ ะบะฐั‚ะฐะปะพะณะฐั…: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ะผะฐั” ัˆัƒะบะฐั‚ะธ ะฟั€ะพะณั€ะฐะผะธ ะฒ ะบะฐั‚ะฐะปะพะณะฐั…: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +ะšะพะปะธ ะฒะธ ะฒะฒะพะดะธั‚ะต ะบะพะผะฐะฝะดัƒ ะฒ ั‚ะตั€ะผั–ะฝะฐะปั–, ะพะฟะตั€ะฐั†ั–ะนะฝะฐ ัะธัั‚ะตะผะฐ ัˆัƒะบะฐั” ะฟั€ะพะณั€ะฐะผัƒ ะฒ ะบะพะถะฝะพะผัƒ ะท ั‚ะธั… ะบะฐั‚ะฐะปะพะณั–ะฒ, ะฟะตั€ะตะปั–ั‡ะตะฝะธั… ัƒ ะทะผั–ะฝะฝั–ะน ะพั‚ะพั‡ะตะฝะฝั `PATH`. + +ะะฐะฟั€ะธะบะปะฐะด, ะบะพะปะธ ะฒะธ ะฒะฒะพะดะธั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ะพะฟะตั€ะฐั†ั–ะนะฝะฐ ัะธัั‚ะตะผะฐ ัˆัƒะบะฐั” ะฟั€ะพะณั€ะฐะผัƒ ะท ะฝะฐะทะฒะพัŽ `python` ัƒ ะฟะตั€ัˆะพะผัƒ ะบะฐั‚ะฐะปะพะทั– ั†ัŒะพะณะพ ัะฟะธัะบัƒ. + +ะฏะบั‰ะพ ะทะฝะฐะนะดะต, ะฒะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั” ั—ั—. ะ†ะฝะฐะบัˆะต ะฟั€ะพะดะพะฒะถะธั‚ัŒ ะฟะพัˆัƒะบ ะฒ ั–ะฝัˆะธั… ะบะฐั‚ะฐะปะพะณะฐั…. + +### ะ’ัั‚ะฐะฝะพะฒะปะตะฝะฝั Python ั– ะพะฝะพะฒะปะตะฝะฝั `PATH` { #installing-python-and-updating-the-path } + +ะŸั–ะด ั‡ะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั Python ะฒะฐั ะผะพะถัƒั‚ัŒ ะทะฐะฟะธั‚ะฐั‚ะธ, ั‡ะธ ั…ะพั‡ะตั‚ะต ะฒะธ ะพะฝะพะฒะธั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `PATH`. + +//// tab | Linux, macOS + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต Python ั– ะฒั–ะฝ ะพะฟะธะฝัั”ั‚ัŒัั ะฒ ะบะฐั‚ะฐะปะพะทั– `/opt/custompython/bin`. + +ะฏะบั‰ะพ ะฒะธ ะฟะพะณะพะดะธั‚ะตัั ะพะฝะพะฒะธั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `PATH`, ั–ะฝัั‚ะฐะปัั‚ะพั€ ะดะพะดะฐัั‚ัŒ `/opt/custompython/bin` ะดะพ ะทะผั–ะฝะฝะพั— `PATH`. + +ะฆะต ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +ะขะตะฟะตั€, ะบะพะปะธ ะฒะธ ะฒะฒะตะดะตั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ัะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ Python ัƒ `/opt/custompython/bin` (ะพัั‚ะฐะฝะฝั–ะน ะบะฐั‚ะฐะปะพะณ) ั– ะฒะธะบะพั€ะธัั‚ะฐั” ัะฐะผะต ั—ั—. + +//// + +//// tab | Windows + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต Python ั– ะฒั–ะฝ ะพะฟะธะฝัั”ั‚ัŒัั ะฒ ะบะฐั‚ะฐะปะพะทั– `C:\opt\custompython\bin`. + +ะฏะบั‰ะพ ะฒะธ ะฟะพะณะพะดะธั‚ะตัั ะพะฝะพะฒะธั‚ะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `PATH`, ั–ะฝัั‚ะฐะปัั‚ะพั€ ะดะพะดะฐัั‚ัŒ `C:\opt\custompython\bin` ะดะพ ะทะผั–ะฝะฝะพั— `PATH`. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +ะขะตะฟะตั€, ะบะพะปะธ ะฒะธ ะฒะฒะตะดะตั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ัะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ Python ัƒ `C:\opt\custompython\bin` (ะพัั‚ะฐะฝะฝั–ะน ะบะฐั‚ะฐะปะพะณ) ั– ะฒะธะบะพั€ะธัั‚ะฐั” ัะฐะผะต ั—ั—. + +//// + +ะžั‚ะถะต, ัะบั‰ะพ ะฒะธ ะฒะฒะตะดะตั‚ะต: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +ะกะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ `python` ัƒ `/opt/custompython/bin` ั– ะทะฐะฟัƒัั‚ะธั‚ัŒ ั—ั—. + +ะฆะต ะฟั€ะธะฑะปะธะทะฝะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ ะฒะฒะตะดะตะฝะฝัŽ: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +ะกะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ `python` ัƒ `C:\opt\custompython\bin\python` ั– ะทะฐะฟัƒัั‚ะธั‚ัŒ ั—ั—. + +ะฆะต ะฟั€ะธะฑะปะธะทะฝะพ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ ะฒะฒะตะดะตะฝะฝัŽ: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +ะฆั ั–ะฝั„ะพั€ะผะฐั†ั–ั ัั‚ะฐะฝะต ัƒ ะฟั€ะธะณะพะดั– ะฟั–ะด ั‡ะฐั ะฒะธะฒั‡ะตะฝะฝั [ะ’ั–ั€ั‚ัƒะฐะปัŒะฝะธั… ัะตั€ะตะดะพะฒะธั‰](virtual-environments.md){.internal-link target=_blank}. + +## ะ’ะธัะฝะพะฒะพะบ { #conclusion } + +ะขะตะฟะตั€ ะฒะธ ะผะฐั”ั‚ะต ะฑะฐะทะพะฒะต ั€ะพะทัƒะผั–ะฝะฝั ั‚ะพะณะพ, ั‰ะพ ั‚ะฐะบะต ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ั– ัะบ ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒ Python. + +ะขะฐะบะพะถ ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฑั–ะปัŒัˆะต ัƒ ะ’ั–ะบั–ะฟะตะดั–ั— ะฟั€ะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั. + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฝะต ะพะดั€ะฐะทัƒ ะพั‡ะตะฒะธะดะฝะพ, ัะบ ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั ะฑัƒะดัƒั‚ัŒ ะบะพั€ะธัะฝะธะผะธ ั‚ะฐ ะทะฐัั‚ะพัะพะฒะฝะธะผะธ. ะะปะต ะฒะพะฝะธ ะฟะพัั‚ั–ะนะฝะพ ะทโ€™ัะฒะปััŽั‚ัŒัั ะฒ ั€ั–ะทะฝะธั… ัั†ะตะฝะฐั€ั–ัั… ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ, ั‚ะพะถ ะฒะฐั€ั‚ะพ ะฟั€ะพ ะฝะธั… ะทะฝะฐั‚ะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะฐะผ ะทะฝะฐะดะพะฑะธั‚ัŒัั ั†ั ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฒ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั– ะฟั€ะพ [ะ’ั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ](virtual-environments.md). diff --git a/docs/uk/docs/help-fastapi.md b/docs/uk/docs/help-fastapi.md new file mode 100644 index 0000000000..a98e56c260 --- /dev/null +++ b/docs/uk/docs/help-fastapi.md @@ -0,0 +1,256 @@ +# ะ”ะพะฟะพะผะพะถั–ั‚ัŒ FastAPI - ะพั‚ั€ะธะผะฐะนั‚ะต ะดะพะฟะพะผะพะณัƒ { #help-fastapi-get-help } + +ะ’ะฐะผ ะฟะพะดะพะฑะฐั”ั‚ัŒัั **FastAPI**? + +ะฅะพั‡ะตั‚ะต ะดะพะฟะพะผะพะณั‚ะธ FastAPI, ั–ะฝัˆะธะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐะผ ั‚ะฐ ะฐะฒั‚ะพั€ัƒ? + +ะะฑะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะดะพะฟะพะผะพะณัƒ ั‰ะพะดะพ **FastAPI**? + +ะ„ ะดัƒะถะต ะฟั€ะพัั‚ั– ัะฟะพัะพะฑะธ ะดะพะฟะพะผะพะณั‚ะธ (ะดะตัะบั– ะฟะพั‚ั€ะตะฑัƒัŽั‚ัŒ ะปะธัˆะต ะพะดะฝะพะณะพ-ะดะฒะพั… ะบะปั–ะบั–ะฒ). + +ะ† ั” ะบั–ะปัŒะบะฐ ัะฟะพัะพะฑั–ะฒ ะพั‚ั€ะธะผะฐั‚ะธ ะดะพะฟะพะผะพะณัƒ. + +## ะŸั–ะดะฟะธัˆั–ั‚ัŒัั ะฝะฐ ั€ะพะทัะธะปะบัƒ { #subscribe-to-the-newsletter } + +ะ’ะธ ะผะพะถะตั‚ะต ะฟั–ะดะฟะธัะฐั‚ะธัั ะฝะฐ (ะฝะตั‡ะฐัั‚ัƒ) ั€ะพะทัะธะปะบัƒ [**FastAPI and friends**](newsletter.md){.internal-link target=_blank}, ั‰ะพะฑ ะฑัƒั‚ะธ ะฒ ะบัƒั€ัั–: + +* ะะพะฒะธะฝ ะฟั€ะพ FastAPI ั‚ะฐ ะดั€ัƒะทั–ะฒ ๐Ÿš€ +* ะŸะพัั–ะฑะฝะธะบั–ะฒ ๐Ÿ“ +* ะœะพะถะปะธะฒะพัั‚ะตะน โœจ +* ะะตััƒะผั–ัะฝะธั… ะทะผั–ะฝ ๐Ÿšจ +* ะŸะพั€ะฐะด ั– ั‚ั€ัŽะบั–ะฒ โœ… + +## ะกั‚ะตะถั‚ะต ะทะฐ FastAPI ะฒ X (Twitter) { #follow-fastapi-on-x-twitter } + +ะกั‚ะตะถั‚ะต ะทะฐ @fastapi ะฒ **X (Twitter)**, ั‰ะพะฑ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฝะฐะนัะฒั–ะถั–ัˆั– ะฝะพะฒะธะฝะธ ะฟั€ะพ **FastAPI**. ๐Ÿฆ + +## ะ”ะพะดะฐะนั‚ะต ะทั–ั€ะพั‡ะบัƒ **FastAPI** ะฝะฐ GitHub { #star-fastapi-in-github } + +ะ’ะธ ะผะพะถะตั‚ะต ยซะฟะพัั‚ะฐะฒะธั‚ะธ ะทั–ั€ะพั‡ะบัƒยป FastAPI ะฝะฐ GitHub (ะฝะฐั‚ะธัะฝัƒะฒัˆะธ ะบะฝะพะฟะบัƒ ะทั–ั€ะพั‡ะบะธ ัƒ ะฒะตั€ั…ะฝัŒะพะผัƒ ะฟั€ะฐะฒะพะผัƒ ะบัƒั‚ั–): https://github.com/fastapi/fastapi. โญ๏ธ + +ะ”ะพะดะฐะฒัˆะธ ะทั–ั€ะพั‡ะบัƒ, ั–ะฝัˆะธะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐะผ ะฑัƒะดะต ะปะตะณัˆะต ะนะพะณะพ ะทะฝะฐะนั‚ะธ ั– ะฟะพะฑะฐั‡ะธั‚ะธ, ั‰ะพ ะฒั–ะฝ ัƒะถะต ะฑัƒะฒ ะบะพั€ะธัะฝะธะผ ะดะปั ั–ะฝัˆะธั…. + +## ะกั‚ะตะถั‚ะต ะทะฐ ะฒะธะฟัƒัะบะฐะผะธ ะฒ ั€ะตะฟะพะทะธั‚ะพั€ั–ั— GitHub { #watch-the-github-repository-for-releases } + +ะ’ะธ ะผะพะถะตั‚ะต ยซัะฟะพัั‚ะตั€ั–ะณะฐั‚ะธยป ะทะฐ FastAPI ะฝะฐ GitHub (ะฝะฐั‚ะธัะฝัƒะฒัˆะธ ะบะฝะพะฟะบัƒ ยซwatchยป ัƒ ะฒะตั€ั…ะฝัŒะพะผัƒ ะฟั€ะฐะฒะพะผัƒ ะบัƒั‚ั–): https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +ะขะฐะผ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะฑั€ะฐั‚ะธ ยซReleases onlyยป. + +ะ—ั€ะพะฑะธะฒัˆะธ ั†ะต, ะฒะธ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผะตั‚ะต ัะฟะพะฒั–ั‰ะตะฝะฝั (ะฝะฐ ะฒะฐัˆัƒ ะตะปะตะบั‚ั€ะพะฝะฝัƒ ะฟะพัˆั‚ัƒ) ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะฒะธะนะดะต ะฝะพะฒะธะน ั€ะตะปั–ะท (ะฝะพะฒะฐ ะฒะตั€ัั–ั) **FastAPI** ะท ะฒะธะฟั€ะฐะฒะปะตะฝะฝัะผะธ ะฟะพะผะธะปะพะบ ั– ะฝะพะฒะธะผะธ ะผะพะถะปะธะฒะพัั‚ัะผะธ. + +## ะ—ะฒ'ัะถั–ั‚ัŒัั ะท ะฐะฒั‚ะพั€ะพะผ { #connect-with-the-author } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฒ'ัะทะฐั‚ะธัั ะทั– ะผะฝะพัŽ (Sebastiรกn Ramรญrez / `tiangolo`), ะฐะฒั‚ะพั€ะพะผ. + +ะ’ะธ ะผะพะถะตั‚ะต: + +* ะกั‚ะตะถะธั‚ะธ ะทะฐ ะผะฝะพัŽ ะฝะฐ **GitHub**. + * ะŸะพะดะธะฒะธั‚ะธัั ั–ะฝัˆั– Open Source-ะฟั€ะพั”ะบั‚ะธ, ัะบั– ั ัั‚ะฒะพั€ะธะฒ ั– ัะบั– ะผะพะถัƒั‚ัŒ ะฒะฐะผ ะดะพะฟะพะผะพะณั‚ะธ. + * ะกั‚ะตะถะธั‚ะธ, ั‰ะพะฑ ะฑะฐั‡ะธั‚ะธ, ะบะพะปะธ ั ัั‚ะฒะพั€ัŽัŽ ะฝะพะฒะธะน Open Source-ะฟั€ะพั”ะบั‚. +* ะกั‚ะตะถะธั‚ะธ ะทะฐ ะผะฝะพัŽ ะฒ **X (Twitter)** ะฐะฑะพ Mastodon. + * ะ ะพะทะบะฐะถั–ั‚ัŒ ะผะตะฝั–, ัะบ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต FastAPI (ะผะตะฝั– ะดัƒะถะต ะฟั€ะธั”ะผะฝะพ ั†ะต ั‡ัƒั‚ะธ). + * ะ”ั–ะทะฝะฐะฒะฐั‚ะธัั, ะบะพะปะธ ั ั€ะพะฑะปัŽ ะพะณะพะปะพัˆะตะฝะฝั ะฐะฑะพ ะฒะธะฟัƒัะบะฐัŽ ะฝะพะฒั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ. + * ะขะฐะบะพะถ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะตะถะธั‚ะธ ะทะฐ @fastapi ะฒ X (Twitter) (ะพะบั€ะตะผะธะน ะฐะบะฐัƒะฝั‚). +* ะกั‚ะตะถะธั‚ะธ ะทะฐ ะผะฝะพัŽ ะฒ **LinkedIn**. + * ะ”ั–ะทะฝะฐะฒะฐั‚ะธัั, ะบะพะปะธ ั ั€ะพะฑะปัŽ ะพะณะพะปะพัˆะตะฝะฝั ะฐะฑะพ ะฒะธะฟัƒัะบะฐัŽ ะฝะพะฒั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ (ั…ะพั‡ะฐ X (Twitter) ั ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽ ั‡ะฐัั‚ั–ัˆะต ๐Ÿคทโ€โ™‚). +* ะงะธั‚ะฐั‚ะธ, ั‰ะพ ั ะฟะธัˆัƒ (ะฐะฑะพ ัั‚ะตะถะธั‚ะธ ะทะฐ ะผะฝะพัŽ) ะฝะฐ **Dev.to** ะฐะฑะพ **Medium**. + * ะงะธั‚ะฐั‚ะธ ั–ะฝัˆั– ั–ะดะตั—, ัั‚ะฐั‚ั‚ั– ั‚ะฐ ะฟั€ะพ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ัะบั– ั ัั‚ะฒะพั€ะธะฒ. + * ะกั‚ะตะถะธั‚ะธ, ั‰ะพะฑ ั‡ะธั‚ะฐั‚ะธ ะฝะพะฒะต, ะบะพะปะธ ั ั‰ะพััŒ ะฟัƒะฑะปั–ะบัƒัŽ. + +## ะขะฒั–ั‚ะฝั–ั‚ัŒ ะฟั€ะพ **FastAPI** { #tweet-about-fastapi } + +ะขะฒั–ั‚ะฝั–ั‚ัŒ ะฟั€ะพ **FastAPI** ั– ะดะฐะนั‚ะต ะผะตะฝั– ั‚ะฐ ั–ะฝัˆะธะผ ะทะฝะฐั‚ะธ, ั‡ะพะผัƒ ะฒั–ะฝ ะฒะฐะผ ะฟะพะดะพะฑะฐั”ั‚ัŒัั. ๐ŸŽ‰ + +ะœะตะฝั– ะดัƒะถะต ะฟะพะดะพะฑะฐั”ั‚ัŒัั ะดั–ะทะฝะฐะฒะฐั‚ะธัั, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ **FastAPI**, ั‰ะพ ะฒะฐะผ ัƒ ะฝัŒะพะผัƒ ัะฟะพะดะพะฑะฐะปะพัั, ัƒ ัะบะพะผัƒ ะฟั€ะพั”ะบั‚ั–/ะบะพะผะฟะฐะฝั–ั— ะฒะธ ะนะพะณะพ ะทะฐัั‚ะพัะพะฒัƒั”ั‚ะต ั‚ะพั‰ะพ. + +## ะ“ะพะปะพััƒะนั‚ะต ะทะฐ FastAPI { #vote-for-fastapi } + +* ะŸั€ะพะณะพะปะพััƒะนั‚ะต ะทะฐ **FastAPI** ะฝะฐ Slant. +* ะŸั€ะพะณะพะปะพััƒะนั‚ะต ะทะฐ **FastAPI** ะฝะฐ AlternativeTo. +* ะŸะพะฒั–ะดะพะผั‚ะต, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต **FastAPI**, ะฝะฐ StackShare. + +## ะ”ะพะฟะพะผะฐะณะฐะนั‚ะต ั–ะฝัˆะธะผ ะท ะฟะธั‚ะฐะฝะฝัะผะธ ะฝะฐ GitHub { #help-others-with-questions-in-github } + +ะ’ะธ ะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ะดะพะฟะพะผะฐะณะฐั‚ะธ ั–ะฝัˆะธะผ ะท ั—ั…ะฝั–ะผะธ ะฟะธั‚ะฐะฝะฝัะผะธ ัƒ: + +* GitHub Discussions +* GitHub Issues + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะฒะถะต ะผะพะถะตั‚ะต ะทะฝะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฝะฐ ั†ั– ะฟะธั‚ะฐะฝะฝั. ๐Ÿค“ + +ะฏะบั‰ะพ ะฒะธ ะฑะฐะณะฐั‚ะพ ะดะพะฟะพะผะฐะณะฐั”ั‚ะต ะปัŽะดัะผ ั–ะท ั—ั…ะฝั–ะผะธ ะฟะธั‚ะฐะฝะฝัะผะธ, ะฒะธ ัั‚ะฐะฝะตั‚ะต ะพั„ั–ั†ั–ะนะฝะธะผ [ะ•ะบัะฟะตั€ั‚ะพะผ FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}. ๐ŸŽ‰ + +ะŸะฐะผ'ัั‚ะฐะนั‚ะต, ะฝะฐะนะฒะฐะถะปะธะฒั–ัˆะต: ะฝะฐะผะฐะณะฐะนั‚ะตัั ะฑัƒั‚ะธ ะดะพะฑั€ะธะผะธ. ะ›ัŽะดะธ ะฟั€ะธั…ะพะดัั‚ัŒ ะทั– ัะฒะพั”ัŽ ั„ั€ัƒัั‚ั€ะฐั†ั–ั”ัŽ ั– ั‡ะฐัั‚ะพ ะฟะธั‚ะฐัŽั‚ัŒ ะฝะต ะฝะฐะนะบั€ะฐั‰ะธะผ ั‡ะธะฝะพะผ, ะฐะปะต ะฟะพัั‚ะฐั€ะฐะนั‚ะตัั ะฑัƒั‚ะธ ัะบะพะผะพะณะฐ ะดะพะฑั€ะพะทะธั‡ะปะธะฒั–ัˆะธะผะธ. ๐Ÿค— + +ะ†ะดะตั ะฒ ั‚ะพะผัƒ, ั‰ะพะฑ ัะฟั–ะปัŒะฝะพั‚ะฐ **FastAPI** ะฑัƒะปะฐ ะดะพะฑั€ะพะทะธั‡ะปะธะฒะพัŽ ั‚ะฐ ะณะพัั‚ะธะฝะฝะพัŽ. ะ’ะพะดะฝะพั‡ะฐั ะฝะต ั‚ะตั€ะฟั–ั‚ัŒ ะฑัƒะปั–ะฝะณ ั‡ะธ ะฝะตะฟะพะฒะฐะถะฝัƒ ะฟะพะฒะตะดั–ะฝะบัƒ ั‰ะพะดะพ ั–ะฝัˆะธั…. ะœะธ ะผะฐั”ะผะพ ะฟั–ะบะปัƒะฒะฐั‚ะธัั ะพะดะฝะต ะฟั€ะพ ะพะดะฝะพะณะพ. + +--- + +ะžััŒ ัะบ ะดะพะฟะพะผะฐะณะฐั‚ะธ ั–ะฝัˆะธะผ ั–ะท ะฟะธั‚ะฐะฝะฝัะผะธ (ัƒ discussions ะฐะฑะพ issues): + +### ะ—ั€ะพะทัƒะผั–ะนั‚ะต ะฟะธั‚ะฐะฝะฝั { #understand-the-question } + +* ะŸะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ ั€ะพะทัƒะผั–ั”ั‚ะต ะฒะธ **ะผะตั‚ัƒ** ั‚ะฐ ะฒะฐั€ั–ะฐะฝั‚ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะปัŽะดะธะฝะธ, ัะบะฐ ะฟะธั‚ะฐั”. + +* ะŸะพั‚ั–ะผ ะฟะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ **ั‡ั–ั‚ะบะต** ัะฐะผะต ะฟะธั‚ะฐะฝะฝั (ะฟะตั€ะตะฒะฐะถะฝะฐ ะฑั–ะปัŒัˆั–ัั‚ัŒ โ€” ั†ะต ะฟะธั‚ะฐะฝะฝั). + +* ะงะฐัั‚ะพ ะทะฐะฟะธั‚ ัั‚ะพััƒั”ั‚ัŒัั ัƒัะฒะฝะพะณะพ ั€ั–ัˆะตะฝะฝั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ะฐะปะต ะผะพะถะต ะฑัƒั‚ะธ **ะบั€ะฐั‰ะต**. ะฏะบั‰ะพ ะฒะธ ะบั€ะฐั‰ะต ะทั€ะพะทัƒะผั–ั”ั‚ะต ะฟั€ะพะฑะปะตะผัƒ ั‚ะฐ ะฒะฐั€ั–ะฐะฝั‚ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั, ะทะผะพะถะตั‚ะต ะทะฐะฟั€ะพะฟะพะฝัƒะฒะฐั‚ะธ ะบั€ะฐั‰ัƒ **ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒัƒ**. + +* ะฏะบั‰ะพ ะฒะธ ะฝะต ั€ะพะทัƒะผั–ั”ั‚ะต ะฟะธั‚ะฐะฝะฝั, ะฟะพะฟั€ะพัั–ั‚ัŒ ะฑั–ะปัŒัˆะต **ะฟะพะดั€ะพะฑะธั†ัŒ**. + +### ะ’ั–ะดั‚ะฒะพั€ั–ั‚ัŒ ะฟั€ะพะฑะปะตะผัƒ { #reproduce-the-problem } + +ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ั– ะทะฐะฟะธั‚ะฐะฝัŒ ะผะพะฒะฐ ะนะดะต ะฟั€ะพ **ะพั€ะธะณั–ะฝะฐะปัŒะฝะธะน ะบะพะด** ะปัŽะดะธะฝะธ. + +ะงะฐัั‚ะพ ะฒะพะฝะธ ะฝะฐะฒะพะดัั‚ัŒ ะปะธัˆะต ั„ั€ะฐะณะผะตะฝั‚ ะบะพะดัƒ, ะฐะปะต ั†ัŒะพะณะพ ะฝะตะดะพัั‚ะฐั‚ะฝัŒะพ, ั‰ะพะฑ **ะฒั–ะดั‚ะฒะพั€ะธั‚ะธ ะฟั€ะพะฑะปะตะผัƒ**. + +* ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฟั€ะพัะธั‚ะธ ะฝะฐะดะฐั‚ะธ ะผั–ะฝั–ะผะฐะปัŒะฝะธะน, ะฒั–ะดั‚ะฒะพั€ัŽะฒะฐะฝะธะน ะฟั€ะธะบะปะฐะด, ัะบะธะน ะฒะธ ะทะผะพะถะตั‚ะต **ัะบะพะฟั–ัŽะฒะฐั‚ะธ-ะฒัั‚ะฐะฒะธั‚ะธ** ั– ะทะฐะฟัƒัั‚ะธั‚ะธ ะปะพะบะฐะปัŒะฝะพ, ั‰ะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ั‚ัƒ ัะฐะผัƒ ะฟะพะผะธะปะบัƒ ะฐะฑะพ ะฟะพะฒะตะดั–ะฝะบัƒ, ัะบัƒ ะฑะฐั‡ะฐั‚ัŒ ะฒะพะฝะธ, ะฐะฑะพ ะบั€ะฐั‰ะต ะทั€ะพะทัƒะผั–ั‚ะธ ั—ั…ะฝั–ะน ะฒะฐั€ั–ะฐะฝั‚ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. + +* ะฏะบั‰ะพ ะฒะธ ะดัƒะถะต ั‰ะตะดั€ั–, ะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ **ัั‚ะฒะพั€ะธั‚ะธ ั‚ะฐะบะธะน ะฟั€ะธะบะปะฐะด** ัะฐะผะพัั‚ั–ะนะฝะพ, ะปะธัˆะต ะฝะฐ ะพัะฝะพะฒั– ะพะฟะธััƒ ะฟั€ะพะฑะปะตะผะธ. ะŸั€ะพัั‚ะพ ะผะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ั†ะต ะผะพะถะต ะทะฐะนะฝัั‚ะธ ะฑะฐะณะฐั‚ะพ ั‡ะฐััƒ, ั– ะบั€ะฐั‰ะต ัะฟะพั‡ะฐั‚ะบัƒ ะฟะพะฟั€ะพัะธั‚ะธ ั—ั… ัƒั‚ะพั‡ะฝะธั‚ะธ ะฟั€ะพะฑะปะตะผัƒ. + +### ะ—ะฐะฟั€ะพะฟะพะฝัƒะนั‚ะต ั€ั–ัˆะตะฝะฝั { #suggest-solutions } + +* ะŸั–ัะปั ั‚ะพะณะพ ัะบ ะฒะธ ะทะผะพะณะปะธ ะทั€ะพะทัƒะผั–ั‚ะธ ะฟะธั‚ะฐะฝะฝั, ะดะฐะนั‚ะต ะผะพะถะปะธะฒัƒ **ะฒั–ะดะฟะพะฒั–ะดัŒ**. + +* ะงะฐัั‚ะพ ะบั€ะฐั‰ะต ะทั€ะพะทัƒะผั–ั‚ะธ ั—ั…ะฝัŽ **ะฟะตั€ะฒะธะฝะฝัƒ ะฟั€ะพะฑะปะตะผัƒ ะฐะฑะพ ะฒะฐั€ั–ะฐะฝั‚ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั**, ะฐะดะถะต ะผะพะถะต ะฑัƒั‚ะธ ะบั€ะฐั‰ะธะน ัะฟะพัั–ะฑ ั—ั— ะฒะธั€ั–ัˆะธั‚ะธ, ะฝั–ะถ ั‚ะต, ั‰ะพ ะฒะพะฝะธ ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะทั€ะพะฑะธั‚ะธ. + +### ะŸะพะฟั€ะพัั–ั‚ัŒ ะทะฐะบั€ะธั‚ะธ { #ask-to-close } + +ะฏะบั‰ะพ ะฒะพะฝะธ ะฒั–ะดะฟะพะฒั–ะปะธ, ะดัƒะถะต ะนะผะพะฒั–ั€ะฝะพ, ั‰ะพ ะฒะธ ั€ะพะทะฒ'ัะทะฐะปะธ ั—ั…ะฝัŽ ะฟั€ะพะฑะปะตะผัƒ. ะ’ั–ั‚ะฐัŽ, **ะฒะธ ะณะตั€ะพะน**! ๐Ÿฆธ + +* ะขะตะฟะตั€, ัะบั‰ะพ ั†ะต ะฒะธั€ั–ัˆะธะปะพ ั—ั…ะฝัŽ ะฟั€ะพะฑะปะตะผัƒ, ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฟั€ะพัะธั‚ะธ: + + * ะฃ GitHub Discussions: ะฟะพะทะฝะฐั‡ะธั‚ะธ ะบะพะผะตะฝั‚ะฐั€ ัะบ **ะฒั–ะดะฟะพะฒั–ะดัŒ**. + * ะฃ GitHub Issues: **ะทะฐะบั€ะธั‚ะธ** issue. + +## ะกั‚ะตะถั‚ะต ะทะฐ ั€ะตะฟะพะทะธั‚ะพั€ั–ั”ะผ GitHub { #watch-the-github-repository } + +ะ’ะธ ะผะพะถะตั‚ะต ยซัะฟะพัั‚ะตั€ั–ะณะฐั‚ะธยป ะทะฐ FastAPI ะฝะฐ GitHub (ะฝะฐั‚ะธัะฝัƒะฒัˆะธ ะบะฝะพะฟะบัƒ ยซwatchยป ัƒ ะฒะตั€ั…ะฝัŒะพะผัƒ ะฟั€ะฐะฒะพะผัƒ ะบัƒั‚ั–): https://github.com/fastapi/fastapi. ๐Ÿ‘€ + +ะฏะบั‰ะพ ะฒะธะฑั€ะฐั‚ะธ ยซWatchingยป ะทะฐะผั–ัั‚ัŒ ยซReleases onlyยป, ะฒะธ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธะผะตั‚ะต ัะฟะพะฒั–ั‰ะตะฝะฝั, ะบะพะปะธ ั…ั‚ะพััŒ ัั‚ะฒะพั€ัŽั” ะฝะพะฒะต issue ะฐะฑะพ ะฟะธั‚ะฐะฝะฝั. ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ, ั‰ะพ ั…ะพั‡ะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ัะฟะพะฒั–ั‰ะตะฝะฝั ะปะธัˆะต ะฟั€ะพ ะฝะพะฒั– issues, ะฐะฑะพ discussions, ะฐะฑะพ PR ั‚ะพั‰ะพ. + +ะขะพะดั– ะฒะธ ะทะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ะดะพะฟะพะผะพะณั‚ะธ ั—ะผ ะฒะธั€ั–ัˆะธั‚ะธ ั†ั– ะฟะธั‚ะฐะฝะฝั. + +## ะกั‚ะฐะฒั‚ะต ะฟะธั‚ะฐะฝะฝั { #ask-questions } + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฝะพะฒะต ะฟะธั‚ะฐะฝะฝั ัƒ ั€ะตะฟะพะทะธั‚ะพั€ั–ั— GitHub, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ: + +* ะŸะพัั‚ะฐะฒะธั‚ะธ **ะฟะธั‚ะฐะฝะฝั** ะฐะฑะพ ะทะฐะฟะธั‚ะฐั‚ะธ ะฟั€ะพ **ะฟั€ะพะฑะปะตะผัƒ**. +* ะ—ะฐะฟั€ะพะฟะพะฝัƒะฒะฐั‚ะธ ะฝะพะฒัƒ **ะผะพะถะปะธะฒั–ัั‚ัŒ**. + +**ะŸั€ะธะผั–ั‚ะบะฐ**: ัะบั‰ะพ ะฒะธ ั†ะต ะทั€ะพะฑะธั‚ะต, ั ะฟะพะฟั€ะพัˆัƒ ะฒะฐั ั‚ะฐะบะพะถ ะดะพะฟะพะผะฐะณะฐั‚ะธ ั–ะฝัˆะธะผ. ๐Ÿ˜‰ + +## ะŸะตั€ะตะณะปัะดะฐะนั‚ะต ะทะฐะฟะธั‚ะธ ะฝะฐ ะฒะธั‚ัะณ { #review-pull-requests } + +ะ’ะธ ะผะพะถะตั‚ะต ะดะพะฟะพะผะพะณั‚ะธ ะผะตะฝั– ะฟะตั€ะตะณะปัะดะฐั‚ะธ ะทะฐะฟะธั‚ะธ ะฝะฐ ะฒะธั‚ัะณ ั–ะฝัˆะธั…. + +ะ† ะทะฝะพะฒัƒ, ะฑัƒะดัŒ ะปะฐัะบะฐ, ะฝะฐะผะฐะณะฐะนั‚ะตัั ะฑัƒั‚ะธ ัะบะพะผะพะณะฐ ะดะพะฑั€ะพะทะธั‡ะปะธะฒั–ัˆะธะผะธ. ๐Ÿค— + +--- + +ะžััŒ ั‰ะพ ัะปั–ะด ะฟะฐะผ'ัั‚ะฐั‚ะธ ั– ัะบ ะฟะตั€ะตะณะปัะดะฐั‚ะธ ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ: + +### ะ—ั€ะพะทัƒะผั–ะนั‚ะต ะฟั€ะพะฑะปะตะผัƒ { #understand-the-problem } + +* ะกะฟะพั‡ะฐั‚ะบัƒ ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ **ั€ะพะทัƒะผั–ั”ั‚ะต ะฟั€ะพะฑะปะตะผัƒ**, ัะบัƒ ะฝะฐะผะฐะณะฐั”ั‚ัŒัั ะฒะธั€ั–ัˆะธั‚ะธ ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ. ะœะพะถะต ะฑัƒั‚ะธ ะดะพะฒัˆะฐ ะดะธัะบัƒัั–ั ัƒ GitHub Discussion ะฐะฑะพ issue. + +* ะขะฐะบะพะถ ั” ะฒะตะปะธะบะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ ะฝะฐัะฟั€ะฐะฒะดั– ะฝะต ะฟะพั‚ั€ั–ะฑะตะฝ, ะฑะพ ะฟั€ะพะฑะปะตะผัƒ ะผะพะถะฝะฐ ั€ะพะทะฒ'ัะทะฐั‚ะธ **ั–ะฝัˆะธะผ ัะฟะพัะพะฑะพะผ**. ะขะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพ ั†ะต ะทะฐะฟั€ะพะฟะพะฝัƒะฒะฐั‚ะธ ะฐะฑะพ ะทะฐะฟะธั‚ะฐั‚ะธ. + +### ะะต ะฟะตั€ะตะนะผะฐะนั‚ะตัั ัั‚ะธะปะตะผ { #dont-worry-about-style } + +* ะะต ะฝะฐะดั‚ะพ ั…ะฒะธะปัŽะนั‚ะตัั ะฟั€ะพ ัั‚ะธะปัŒ ะฟะพะฒั–ะดะพะผะปะตะฝัŒ ั„ั–ะบัะฐั†ั–ะน, ั ะทั€ะพะฑะปัŽ squash and merge, ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฒัˆะธ ั„ั–ะบัะฐั†ั–ัŽ ะฒั€ัƒั‡ะฝัƒ. + +* ะขะฐะบะพะถ ะฝะต ะฟะตั€ะตะนะผะฐะนั‚ะตัั ะฟั€ะฐะฒะธะปะฐะผะธ ัั‚ะธะปัŽ, ะฒะถะต ั” ะฐะฒั‚ะพะผะฐั‚ะธะทะพะฒะฐะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ั‰ะพ ั†ะต ะฟะตั€ะตะฒั–ั€ััŽั‚ัŒ. + +ะ ัะบั‰ะพ ะฑัƒะดัƒั‚ัŒ ั–ะฝัˆั– ะฒะธะผะพะณะธ ั‰ะพะดะพ ัั‚ะธะปัŽ ั‡ะธ ัƒะทะณะพะดะถะตะฝะพัั‚ั–, ั ะฟะพะฟั€ะพัˆัƒ ะฟั€ะพ ั†ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฐะฑะพ ะดะพะดะฐะผ ะทะฒะตั€ั…ัƒ ั„ั–ะบัะฐั†ั–ั— ะท ะฟะพั‚ั€ั–ะฑะฝะธะผะธ ะทะผั–ะฝะฐะผะธ. + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะบะพะด { #check-the-code } + +* ะŸะตั€ะตะณะปัะฝัŒั‚ะต ั‚ะฐ ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะบะพะด, ะพั†ั–ะฝั–ั‚ัŒ, ั‡ะธ ะฒั–ะฝ ะผะฐั” ัะตะฝั, **ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะนะพะณะพ ะปะพะบะฐะปัŒะฝะพ** ั– ะฟะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ ัะฟั€ะฐะฒะดั– ะฒั–ะฝ ั€ะพะทะฒ'ัะทัƒั” ะฟั€ะพะฑะปะตะผัƒ. + +* ะŸะพั‚ั–ะผ ะทะฐะปะธัˆั‚ะต **ะบะพะผะตะฝั‚ะฐั€**, ั‰ะพ ะฒะธ ั†ะต ะทั€ะพะฑะธะปะธ, ั‚ะฐะบ ั ะทะฝะฐั‚ะธะผัƒ, ั‰ะพ ะฒะธ ัะฟั€ะฐะฒะดั– ะฟะตั€ะตะฒั–ั€ะธะปะธ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะะฐ ะถะฐะปัŒ, ั ะฝะต ะผะพะถัƒ ะฟั€ะพัั‚ะพ ะดะพะฒั–ั€ัั‚ะธ PR, ัะบั– ะผะฐัŽั‚ัŒ ะบั–ะปัŒะบะฐ ัั…ะฒะฐะปะตะฝัŒ. + +ะ‘ัƒะฒะฐะปะพ ะฝะต ั€ะฐะท, ั‰ะพ PR ะผะฐะปะธ 3, 5 ะฐะฑะพ ะฑั–ะปัŒัˆะต ัั…ะฒะฐะปะตะฝัŒ, ะผะฐะฑัƒั‚ัŒ ั‚ะพะผัƒ, ั‰ะพ ะพะฟะธั ะฟั€ะธะฒะฐะฑะปะธะฒะธะน, ะฐะปะต ะบะพะปะธ ั ะฟะตั€ะตะฒั–ั€ัะฒ PR, ะฒะพะฝะธ ะฒะธัะฒะปัะปะธัั ะทะปะฐะผะฐะฝะธะผะธ, ะผะฐะปะธ ะฟะพะผะธะปะบัƒ ะฐะฑะพ ะฝะต ั€ะพะทะฒ'ัะทัƒะฒะฐะปะธ ะทะฐัะฒะปะตะฝัƒ ะฟั€ะพะฑะปะตะผัƒ. ๐Ÿ˜… + +ะขะพะถ ะดัƒะถะต ะฒะฐะถะปะธะฒะพ, ั‰ะพะฑ ะฒะธ ัะฟั€ะฐะฒะดั– ะฟั€ะพั‡ะธั‚ะฐะปะธ ั– ะทะฐะฟัƒัั‚ะธะปะธ ะบะพะด ั‚ะฐ ะฟะพะฒั–ะดะพะผะธะปะธ ะฒ ะบะพะผะตะฝั‚ะฐั€ัั…, ั‰ะพ ะฒะธ ั†ะต ะทั€ะพะฑะธะปะธ. ๐Ÿค“ + +/// + +* ะฏะบั‰ะพ PR ะผะพะถะฝะฐ ัะบะพััŒ ัะฟั€ะพัั‚ะธั‚ะธ, ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพ ั†ะต ะฟะพะฟั€ะพัะธั‚ะธ, ะฐะปะต ะฝะตะผะฐั” ะฟะพั‚ั€ะตะฑะธ ะฑัƒั‚ะธ ะฝะฐะดั‚ะพ ะฟั€ะธัะบั–ะฟะปะธะฒะธะผะธ, ะฐะดะถะต ะผะพะถะต ะฑัƒั‚ะธ ะฑะฐะณะฐั‚ะพ ััƒะฑ'ั”ะบั‚ะธะฒะฝะธั… ั‚ะพั‡ะพะบ ะทะพั€ัƒ (ั– ะฒ ะผะตะฝะต ั‚ะฐะบะพะถ ั” ัะฒะพั ๐Ÿ™ˆ), ั‚ะพะถ ะบั€ะฐั‰ะต ะทะพัะตั€ะตะดะธั‚ะธัั ะฝะฐ ั„ัƒะฝะดะฐะผะตะฝั‚ะฐะปัŒะฝะธั… ั€ะตั‡ะฐั…. + +### ะขะตัั‚ะธ { #tests } + +* ะ”ะพะฟะพะผะพะถั–ั‚ัŒ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ PR ะผะฐั” **ั‚ะตัั‚ะธ**. + +* ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ั‚ะตัั‚ะธ **ะฟะฐะดะฐัŽั‚ัŒ** ะดะพ PR. ๐Ÿšจ + +* ะŸะพั‚ั–ะผ ะฟะตั€ะตะฒั–ั€ั‚ะต, ั‰ะพ ั‚ะตัั‚ะธ **ะฟั€ะพั…ะพะดัั‚ัŒ** ะฟั–ัะปั PR. โœ… + +* ะ‘ะฐะณะฐั‚ะพ PRั–ะฒ ะฝะต ะผะฐัŽั‚ัŒ ั‚ะตัั‚ั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต **ะฝะฐะณะฐะดะฐั‚ะธ** ะดะพะดะฐั‚ะธ ั‚ะตัั‚ะธ ะฐะฑะพ ะฝะฐะฒั–ั‚ัŒ **ะทะฐะฟั€ะพะฟะพะฝัƒะฒะฐั‚ะธ** ะดะตัะบั– ั‚ะตัั‚ะธ ัะฐะผั–. ะฆะต ะพะดะฝะฐ ะท ั€ะตั‡ะตะน, ัะบะฐ ะฝะฐะนะฑั–ะปัŒัˆะต ะทะฐะฑะธั€ะฐั” ั‡ะฐััƒ, ั– ะฒะธ ะดัƒะถะต ะดะพะฟะพะผะพะถะตั‚ะต. + +* ะŸะพั‚ั–ะผ ั‚ะฐะบะพะถ ะฟั€ะพะบะพะผะตะฝั‚ัƒะนั‚ะต, ั‰ะพ ัะฐะผะต ะฒะธ ัะฟั€ะพะฑัƒะฒะฐะปะธ, ั‚ะฐะบ ั ะทะฝะฐั‚ะธะผัƒ, ั‰ะพ ะฒะธ ั†ะต ะฟะตั€ะตะฒั–ั€ะธะปะธ. ๐Ÿค“ + +## ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะฐะฟะธั‚ ะฝะฐ ะฒะธั‚ัะณ { #create-a-pull-request } + +ะ’ะธ ะผะพะถะตั‚ะต [ะทั€ะพะฑะธั‚ะธ ะฒะฝะตัะพะบ](contributing.md){.internal-link target=_blank} ัƒ ะฒะธั…ั–ะดะฝะธะน ะบะพะด ั–ะท ะทะฐะฟะธั‚ะฐะผะธ ะฝะฐ ะฒะธั‚ัะณ, ะฝะฐะฟั€ะธะบะปะฐะด: + +* ะฉะพะฑ ะฒะธะฟั€ะฐะฒะธั‚ะธ ะพะฟะธัะบัƒ, ะทะฝะฐะนะดะตะฝัƒ ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +* ะฉะพะฑ ะฟะพะดั–ะปะธั‚ะธัั ัั‚ะฐั‚ั‚ะตัŽ, ะฒั–ะดะตะพ ะฐะฑะพ ะฟะพะดะบะฐัั‚ะพะผ ะฟั€ะพ FastAPI, ัะบะธะน ะฒะธ ัั‚ะฒะพั€ะธะปะธ ะฐะฑะพ ะทะฝะฐะนัˆะปะธ, ะฒั–ะดั€ะตะดะฐะณัƒะฒะฐะฒัˆะธ ั†ะตะน ั„ะฐะนะป. + * ะžะฑะพะฒ'ัะทะบะพะฒะพ ะดะพะดะฐะนั‚ะต ะฒะฐัˆะต ะฟะพัะธะปะฐะฝะฝั ะฝะฐ ะฟะพั‡ะฐั‚ะพะบ ะฒั–ะดะฟะพะฒั–ะดะฝะพะณะพ ั€ะพะทะดั–ะปัƒ. +* ะฉะพะฑ ะดะพะฟะพะผะพะณั‚ะธ [ะฟะตั€ะตะบะปะฐัั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ](contributing.md#translations){.internal-link target=_blank} ะฒะฐัˆะพัŽ ะผะพะฒะพัŽ. + * ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะดะพะฟะพะผะพะณั‚ะธ ะท ะฟะตั€ะตะณะปัะดะพะผ ะฟะตั€ะตะบะปะฐะดั–ะฒ, ัั‚ะฒะพั€ะตะฝะธั… ั–ะฝัˆะธะผะธ. +* ะฉะพะฑ ะทะฐะฟั€ะพะฟะพะฝัƒะฒะฐั‚ะธ ะฝะพะฒั– ั€ะพะทะดั–ะปะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +* ะฉะพะฑ ะฒะธะฟั€ะฐะฒะธั‚ะธ ะฝะฐัะฒะฝัƒ ะฟั€ะพะฑะปะตะผัƒ/ะฟะพะผะธะปะบัƒ. + * ะžะฑะพะฒ'ัะทะบะพะฒะพ ะดะพะดะฐะนั‚ะต ั‚ะตัั‚ะธ. +* ะฉะพะฑ ะดะพะดะฐั‚ะธ ะฝะพะฒัƒ ะผะพะถะปะธะฒั–ัั‚ัŒ. + * ะžะฑะพะฒ'ัะทะบะพะฒะพ ะดะพะดะฐะนั‚ะต ั‚ะตัั‚ะธ. + * ะžะฑะพะฒ'ัะทะบะพะฒะพ ะดะพะดะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ, ัะบั‰ะพ ั†ะต ะดะพั€ะตั‡ะฝะพ. + +## ะ”ะพะฟะพะผะพะถั–ั‚ัŒ ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ FastAPI { #help-maintain-fastapi } + +ะ”ะพะฟะพะผะพะถั–ั‚ัŒ ะผะตะฝั– ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ **FastAPI**! ๐Ÿค“ + +ะ ะพะฑะพั‚ะธ ะฑะฐะณะฐั‚ะพ, ั– ะฑั–ะปัŒัˆัƒ ั—ั— ั‡ะฐัั‚ะธะฝัƒ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ **ะ’ะ˜**. + +ะžัะฝะพะฒะฝั– ะทะฐะฒะดะฐะฝะฝั, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฒะถะต ะทะฐั€ะฐะท: + +* [ะ”ะพะฟะพะผะฐะณะฐะนั‚ะต ั–ะฝัˆะธะผ ะท ะฟะธั‚ะฐะฝะฝัะผะธ ะฝะฐ GitHub](#help-others-with-questions-in-github){.internal-link target=_blank} (ะดะธะฒ. ั€ะพะทะดั–ะป ะฒะธั‰ะต). +* [ะŸะตั€ะตะณะปัะดะฐะนั‚ะต ะทะฐะฟะธั‚ะธ ะฝะฐ ะฒะธั‚ัะณ](#review-pull-requests){.internal-link target=_blank} (ะดะธะฒ. ั€ะพะทะดั–ะป ะฒะธั‰ะต). + +ะฆั– ะดะฒะฐ ะทะฐะฒะดะฐะฝะฝั **ะฝะฐะนะฑั–ะปัŒัˆะต ัะฟะพะถะธะฒะฐัŽั‚ัŒ ั‡ะฐั**. ะฆะต ะพัะฝะพะฒะฝะฐ ั€ะพะฑะพั‚ะฐ ะท ะฟั–ะดั‚ั€ะธะผะบะธ FastAPI. + +ะฏะบั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะดะพะฟะพะผะพะณั‚ะธ ะผะตะฝั– ะท ั†ะธะผ, **ะฒะธ ะดะพะฟะพะผะฐะณะฐั”ั‚ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐั‚ะธ FastAPI** ั– ะณะฐั€ะฐะฝั‚ัƒั”ั‚ะต, ั‰ะพ ะฒั–ะฝ **ั€ัƒั…ะฐั‚ะธะผะตั‚ัŒัั ัˆะฒะธะดัˆะต ะน ะบั€ะฐั‰ะต**. ๐Ÿš€ + +## ะ”ะพะปัƒั‡ะฐะนั‚ะตัั ะดะพ ั‡ะฐั‚ัƒ { #join-the-chat } + +ะ”ะพะปัƒั‡ะฐะนั‚ะตัั ะดะพ ๐Ÿ‘ฅ ัะตั€ะฒะตั€ัƒ ั‡ะฐั‚ัƒ Discord ๐Ÿ‘ฅ ั– ัะฟั–ะปะบัƒะนั‚ะตัั ะท ั–ะฝัˆะธะผะธ ะฒ ัะฟั–ะปัŒะฝะพั‚ั– FastAPI. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ะปั ะทะฐะฟะธั‚ะฐะฝัŒ ัั‚ะฐะฒั‚ะต ั—ั… ัƒ GitHub Discussions, ั‚ะฐะผ ะทะฝะฐั‡ะฝะพ ะฒะธั‰ะฐ ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ, ั‰ะพ ะฒะฐะผ ะดะพะฟะพะผะพะถัƒั‚ัŒ [ะ•ะบัะฟะตั€ั‚ะธ FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั‡ะฐั‚ ะปะธัˆะต ะดะปั ั–ะฝัˆะธั… ะทะฐะณะฐะปัŒะฝะธั… ั€ะพะทะผะพะฒ. + +/// + +### ะะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั‡ะฐั‚ ะดะปั ะทะฐะฟะธั‚ะฐะฝัŒ { #dont-use-the-chat-for-questions } + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ ั‡ะฐั‚ะธ ะดะพะทะฒะพะปััŽั‚ัŒ ะฑั–ะปัŒัˆะต ยซะฒั–ะปัŒะฝะพั— ั€ะพะทะผะพะฒะธยป, ะปะตะณะบะพ ัั‚ะฐะฒะธั‚ะธ ะฝะฐะดั‚ะพ ะทะฐะณะฐะปัŒะฝั– ะฟะธั‚ะฐะฝะฝั, ะฝะฐ ัะบั– ัะบะปะฐะดะฝั–ัˆะต ะฒั–ะดะฟะพะฒั–ัั‚ะธ, ั‚ะพะถ ะฒะธ ะผะพะถะตั‚ะต ะฝะต ะพั‚ั€ะธะผะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดะตะน. + +ะฃ GitHub ัˆะฐะฑะปะพะฝ ะฟั–ะดะบะฐะถะต ะฒะฐะผ, ัะบ ะฝะฐะฟะธัะฐั‚ะธ ะฟั€ะฐะฒะธะปัŒะฝะต ะฟะธั‚ะฐะฝะฝั, ั‰ะพะฑ ะฒะธ ะปะตะณัˆะต ะพั‚ั€ะธะผะฐะปะธ ั…ะพั€ะพัˆัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ะฐะฑะพ ะฝะฐะฒั–ั‚ัŒ ะฒะธั€ั–ัˆะธะปะธ ะฟั€ะพะฑะปะตะผัƒ ัะฐะผะพัั‚ั–ะนะฝะพ ั‰ะต ะดะพ ะทะฐะฟะธั‚ัƒ. ะ† ะฒ GitHub ั ะผะพะถัƒ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ, ั‰ะพ ะทะฐะฒะถะดะธ ะฝะฐ ะฒัะต ะฒั–ะดะฟะพะฒั–ะผ, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ั†ะต ะทะฐะนะผะต ั‚ั€ะพั…ะธ ั‡ะฐััƒ. ะžัะพะฑะธัั‚ะพ ั ะฝะต ะผะพะถัƒ ั€ะพะฑะธั‚ะธ ั†ะต ะฒ ั‡ะฐั‚ะฐั…. ๐Ÿ˜… + +ะ ะพะทะผะพะฒะธ ะฒ ั‡ะฐั‚ะฐั… ั‚ะฐะบะพะถ ะฝะต ั‚ะฐะบ ะฟั€ะพัั‚ะพ ัˆัƒะบะฐั‚ะธ, ัะบ ัƒ GitHub, ั‚ะพะถ ะฟะธั‚ะฐะฝะฝั ั‚ะฐ ะฒั–ะดะฟะพะฒั–ะดั– ะผะพะถัƒั‚ัŒ ะทะฐะณัƒะฑะธั‚ะธัั. ะ† ะปะธัˆะต ั‚ั–, ั‰ะพ ะฒ GitHub, ะทะฐั€ะฐั…ะพะฒัƒัŽั‚ัŒัั, ั‰ะพะฑ ัั‚ะฐั‚ะธ [ะ•ะบัะฟะตั€ั‚ะพะผ FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, ั‚ะพะถ ัˆะฒะธะดัˆะต ะทะฐ ะฒัะต ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฑั–ะปัŒัˆะต ัƒะฒะฐะณะธ ัะฐะผะต ะฒ GitHub. + +ะ— ั–ะฝัˆะพะณะพ ะฑะพะบัƒ, ัƒ ั‡ะฐั‚ะฐั… ั” ั‚ะธััั‡ั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, ั‚ะพะถ ะดัƒะถะต ะนะผะพะฒั–ั€ะฝะพ, ั‰ะพ ะฒะธ ะผะฐะนะถะต ะทะฐะฒะถะดะธ ะทะฝะฐะนะดะตั‚ะต ั‚ะฐะผ ัะฟั–ะฒั€ะพะทะผะพะฒะฝะธะบะฐ. ๐Ÿ˜„ + +## ะกะฟะพะฝัะพั€ัƒะนั‚ะต ะฐะฒั‚ะพั€ะฐ { #sponsor-the-author } + +ะฏะบั‰ะพ ะฒะฐัˆ **ะฟั€ะพะดัƒะบั‚/ะบะพะผะฟะฐะฝั–ั** ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด **FastAPI** ะฐะฑะพ ะฟะพะฒ'ัะทะฐะฝะฐ ะท ะฝะธะผ ั– ะฒะธ ั…ะพั‡ะตั‚ะต ะพั…ะพะฟะธั‚ะธ ะนะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต ัะฟะพะฝัะพั€ัƒะฒะฐั‚ะธ ะฐะฒั‚ะพั€ะฐ (ะผะตะฝะต) ั‡ะตั€ะตะท GitHub sponsors. ะ—ะฐะปะตะถะฝะพ ะฒั–ะด ั€ั–ะฒะฝั ะฒะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฟะตั€ะตะฒะฐะณะธ, ะฝะฐะฟั€ะธะบะปะฐะด ะทะฝะฐั‡ะพะบ ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. ๐ŸŽ + +--- + +ะ”ัะบัƒัŽ! ๐Ÿš€ diff --git a/docs/uk/docs/history-design-future.md b/docs/uk/docs/history-design-future.md new file mode 100644 index 0000000000..1897807c84 --- /dev/null +++ b/docs/uk/docs/history-design-future.md @@ -0,0 +1,79 @@ +# ะ†ัั‚ะพั€ั–ั, ะฟั€ะพั”ะบั‚ัƒะฒะฐะฝะฝั ั– ะผะฐะนะฑัƒั‚ะฝั” { #history-design-and-future } + +ะ”ะตัะบะธะน ั‡ะฐั ั‚ะพะผัƒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ **FastAPI** ะทะฐะฟะธั‚ะฐะฒ: + +> ะฏะบะฐ ั–ัั‚ะพั€ั–ั ั†ัŒะพะณะพ ะฟั€ะพั”ะบั‚ัƒ? ะ—ะดะฐั”ั‚ัŒัั, ะฒั–ะฝ ะฝั–ะทะฒั–ะดะบะธ ะทะฐ ะบั–ะปัŒะบะฐ ั‚ะธะถะฝั–ะฒ ัั‚ะฐะฒ ั‡ัƒะดะพะฒะธะผ [...] + +ะžััŒ ั‚ั€ะพั…ะธ ั†ั–ั”ั— ั–ัั‚ะพั€ั–ั—. + +## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ { #alternatives } + +ะฏ ัั‚ะฒะพั€ัŽะฒะฐะฒ API ะทั– ัะบะปะฐะดะฝะธะผะธ ะฒะธะผะพะณะฐะผะธ ะฟั€ะพั‚ัะณะพะผ ะบั–ะปัŒะบะพั… ั€ะพะบั–ะฒ (ะผะฐัˆะธะฝะฝะต ะฝะฐะฒั‡ะฐะฝะฝั, ั€ะพะทะฟะพะดั–ะปะตะฝั– ัะธัั‚ะตะผะธ, ะฐัะธะฝั…ั€ะพะฝะฝั– ะทะฐะฒะดะฐะฝะฝั, ะฑะฐะทะธ ะดะฐะฝะธั… NoSQL ั‚ะพั‰ะพ), ะพั‡ะพะปัŽัŽั‡ะธ ะบั–ะปัŒะบะฐ ะบะพะผะฐะฝะด ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ. + +ะฃ ะผะตะถะฐั… ั†ัŒะพะณะพ ะผะตะฝั– ะดะพะฒะตะปะพัั ะดะพัะปั–ะดะถัƒะฒะฐั‚ะธ, ั‚ะตัั‚ัƒะฒะฐั‚ะธ ะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑะฐะณะฐั‚ะพ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ. + +ะ†ัั‚ะพั€ั–ั **FastAPI** ะทะฝะฐั‡ะฝะพัŽ ะผั–ั€ะพัŽ - ั†ะต ั–ัั‚ะพั€ั–ั ะนะพะณะพ ะฟะพะฟะตั€ะตะดะฝะธะบั–ะฒ. + +ะฏะบ ัะบะฐะทะฐะฝะพ ะฒ ั€ะพะทะดั–ะปั– [ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ](alternatives.md){.internal-link target=_blank}: + +
+ +**FastAPI** ะฝะต ั–ัะฝัƒะฒะฐะฒ ะฑะธ ะฑะตะท ะฟะพะฟะตั€ะตะดะฝัŒะพั— ั€ะพะฑะพั‚ะธ ั–ะฝัˆะธั…. + +ะ‘ัƒะปะพ ัั‚ะฒะพั€ะตะฝะพ ะฑะฐะณะฐั‚ะพ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ัะบั– ะฝะฐะดะธั…ะฝัƒะปะธ ะฝะฐ ะนะพะณะพ ัั‚ะฒะพั€ะตะฝะฝั. + +ะฏ ั€ะพะบะฐะผะธ ัƒะฝะธะบะฐะฒ ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ั„ั€ะตะนะผะฒะพั€ะบัƒ. ะกะฟะพั‡ะฐั‚ะบัƒ ั ะฝะฐะผะฐะณะฐะฒัั ะฒะธั€ั–ัˆะธั‚ะธ ะฒัั– ะผะพะถะปะธะฒะพัั‚ั–, ัะบั– ะฟะพะบั€ะธะฒะฐั” **FastAPI**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั€ั–ะทะฝั– ั„ั€ะตะนะผะฒะพั€ะบะธ, ะฟะปะฐะณั–ะฝะธ ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ. + +ะะปะต ะฒ ะฟะตะฒะฝะธะน ะผะพะผะตะฝั‚ ะฝะต ะทะฐะปะธัˆะธะปะพัั ั–ะฝัˆะพะณะพ ะฒะฐั€ั–ะฐะฝั‚ัƒ, ะพะบั€ั–ะผ ัั‚ะฒะพั€ะธั‚ะธ ั‰ะพััŒ, ั‰ะพ ะฝะฐะดะฐั” ะฒัั– ั†ั– ะผะพะถะปะธะฒะพัั‚ั–, ัƒะทัะฒัˆะธ ะฝะฐะนะบั€ะฐั‰ั– ั–ะดะตั— ะท ะฟะพะฟะตั€ะตะดะฝั–ั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ั– ะฟะพั”ะดะฝะฐะฒัˆะธ ั—ั… ัะบะฝะฐะนะบั€ะฐั‰ะต, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะผะพะถะปะธะฒะพัั‚ั– ัะฐะผะพั— ะผะพะฒะธ, ัะบะธั… ั€ะฐะฝั–ัˆะต ะฒะทะฐะณะฐะปั– ะฝะต ะฑัƒะปะพ (ะฟั–ะดะบะฐะทะบะธ ั‚ะธะฟั–ะฒ Python 3.6+). + +
+ +## ะ”ะพัะปั–ะดะถะตะฝะฝั { #investigation } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒัั– ะฟะพะฟะตั€ะตะดะฝั– ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ, ั ะผะฐะฒ ะทะผะพะณัƒ ะฟะพะฒั‡ะธั‚ะธัั ะฒ ะบะพะถะฝะพั—, ัƒะทัั‚ะธ ั–ะดะตั— ะน ะฟะพั”ะดะฝะฐั‚ะธ ั—ั… ัะบะฝะฐะนะบั€ะฐั‰ะต ะดะปั ัะตะฑะต ั‚ะฐ ะบะพะผะฐะฝะด ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ, ะท ัะบะธะผะธ ะฟั€ะฐั†ัŽะฒะฐะฒ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฑัƒะปะพ ะพั‡ะตะฒะธะดะฝะพ, ั‰ะพ ะฒ ั–ะดะตะฐะปั– ะฒัะต ะผะฐั” า‘ั€ัƒะฝั‚ัƒะฒะฐั‚ะธัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธั… ะฟั–ะดะบะฐะทะบะฐั… ั‚ะธะฟั–ะฒ Python. + +ะขะฐะบะพะถ ะฝะฐะนะบั€ะฐั‰ะธะผ ะฟั–ะดั…ะพะดะพะผ ะฑัƒะปะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะถะต ะฝะฐัะฒะฝั– ัั‚ะฐะฝะดะฐั€ั‚ะธ. + +ะขะพะถ, ั‰ะต ะดะพ ะฟะพั‡ะฐั‚ะบัƒ ะฝะฐะฟะธัะฐะฝะฝั ะบะพะดัƒ **FastAPI**, ั ะฟั€ะพะฒั–ะฒ ะบั–ะปัŒะบะฐ ะผั–ััั†ั–ะฒ, ะฒะธะฒั‡ะฐัŽั‡ะธ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI, ะกั…ะตะผะธ JSON, OAuth2 ั‚ะพั‰ะพ. ะ ะพะทัƒะผั–ัŽั‡ะธ ั—ั…ะฝั– ะฒะทะฐั”ะผะพะทะฒ'ัะทะบะธ, ะฟะตั€ะตั‚ะธะฝะธ ั‚ะฐ ะฒั–ะดะผั–ะฝะฝะพัั‚ั–. + +## ะŸั€ะพั”ะบั‚ัƒะฒะฐะฝะฝั { #design } + +ะŸะพั‚ั–ะผ ั ะฟั€ะธะดั–ะปะธะฒ ั‡ะฐั ะฟั€ะพั”ะบั‚ัƒะฒะฐะฝะฝัŽ ยซAPIยป ะดะปั ั€ะพะทั€ะพะฑะฝะธะบะฐ, ัะบะต ั ั…ะพั‚ั–ะฒ ะผะฐั‚ะธ ัะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ (ัะบ ั€ะพะทั€ะพะฑะฝะธะบ, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” FastAPI). + +ะฏ ะฟั€ะพั‚ะตัั‚ัƒะฒะฐะฒ ะบั–ะปัŒะบะฐ ั–ะดะตะน ัƒ ะฝะฐะนะฟะพะฟัƒะปัั€ะฝั–ัˆะธั… Python-ั€ะตะดะฐะบั‚ะพั€ะฐั…: PyCharm, VS Code, ั€ะตะดะฐะบั‚ะพั€ะฐั… ะฝะฐ ะพัะฝะพะฒั– Jedi. + +ะ—ะฐ ะดะฐะฝะธะผะธ Python Developer Survey, ั†ะต ะพั…ะพะฟะปัŽั” ะฑะปะธะทัŒะบะพ 80% ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ. + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ **FastAPI** ัะฟะตั†ั–ะฐะปัŒะฝะพ ั‚ะตัั‚ัƒะฒะฐะฒัั ะท ั€ะตะดะฐะบั‚ะพั€ะฐะผะธ, ัะบะธะผะธ ะบะพั€ะธัั‚ัƒัŽั‚ัŒัั 80% ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ Python. ะ† ะพัะบั–ะปัŒะบะธ ะฑั–ะปัŒัˆั–ัั‚ัŒ ั–ะฝัˆะธั… ั€ะตะดะฐะบั‚ะพั€ั–ะฒ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฟะพะดั–ะฑะฝะพ, ัƒัั– ั†ั– ะฟะตั€ะตะฒะฐะณะธ ะผะฐัŽั‚ัŒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฟั€ะฐะบั‚ะธั‡ะฝะพ ัƒ ะฒัั–ั… ั€ะตะดะฐะบั‚ะพั€ะฐั…. + +ะขะฐะบ ั ะทะผั–ะณ ะทะฝะฐะนั‚ะธ ะฝะฐะนะบั€ะฐั‰ั– ัะฟะพัะพะฑะธ ะผะฐะบัะธะผะฐะปัŒะฝะพ ะทะผะตะฝัˆะธั‚ะธ ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ, ะทะฐะฑะตะทะฟะตั‡ะธั‚ะธ ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ะฒััŽะดะธ, ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะธะฟั–ะฒ ั– ะฟะพะผะธะปะพะบ ั‚ะพั‰ะพ. + +ะ† ะฒัะต ั†ะต ั‚ะฐะบ, ั‰ะพะฑ ะฝะฐะดะฐั‚ะธ ะฝะฐะนะบั€ะฐั‰ะธะน ะดะพัะฒั–ะด ั€ะพะทั€ะพะฑะบะธ ะดะปั ะฒัั–ั… ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ. + +## ะ’ะธะผะพะณะธ { #requirements } + +ะŸั–ัะปั ะฟะตั€ะตะฒั–ั€ะบะธ ะบั–ะปัŒะบะพั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ ั ะฒะธั€ั–ัˆะธะฒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **Pydantic** ั‡ะตั€ะตะท ะนะพะณะพ ะฟะตั€ะตะฒะฐะณะธ. + +ะŸะพั‚ั–ะผ ั ะทั€ะพะฑะธะฒ ะฒะฝะตัะบะธ ะดะพ ะฝัŒะพะณะพ, ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ะนะพะณะพ ะฟะพะฒะฝั–ัั‚ัŽ ััƒะผั–ัะฝะธะผ ั–ะท ะกั…ะตะผะพัŽ JSON, ะดะพะดะฐั‚ะธ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ั–ะทะฝะธั… ัะฟะพัะพะฑั–ะฒ ะพะณะพะปะพัˆะตะฝะฝั ะพะฑะผะตะถะตะฝัŒ ั– ะฟะพะปั–ะฟัˆะธั‚ะธ ะฟั–ะดั‚ั€ะธะผะบัƒ ั€ะตะดะฐะบั‚ะพั€ั–ะฒ (ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะธะฟั–ะฒ, ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั) ะฝะฐ ะพัะฝะพะฒั– ั‚ะตัั‚ั–ะฒ ัƒ ะบั–ะปัŒะบะพั… ั€ะตะดะฐะบั‚ะพั€ะฐั…. + +ะŸั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ ั ั‚ะฐะบะพะถ ะทั€ะพะฑะธะฒ ะฒะฝะตัะบะธ ะดะพ **Starlette**, ั–ะฝัˆะพั— ะบะปัŽั‡ะพะฒะพั— ะทะฐะปะตะถะฝะพัั‚ั–. + +## ะ ะพะทั€ะพะฑะบะฐ { #development } + +ะšะพะปะธ ั ะฒะทัะฒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทะฐ ัั‚ะฒะพั€ะตะฝะฝั **FastAPI**, ะฑั–ะปัŒัˆั–ัั‚ัŒ ัะบะปะฐะดะพะฒะธั… ัƒะถะต ะฑัƒะปะธ ะฝะฐ ะผั–ัั†ัั…: ะดะธะทะฐะนะฝ ะฒะธะทะฝะฐั‡ะตะฝะพ, ะฒะธะผะพะณะธ ั‚ะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะฟั–ะดะณะพั‚ะพะฒะปะตะฝะพ, ะทะฝะฐะฝะฝั ะฟั€ะพ ัั‚ะฐะฝะดะฐั€ั‚ะธ ะน ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— - ั‡ั–ั‚ะบั– ั‚ะฐ ัะฒั–ะถั–. + +## ะœะฐะนะฑัƒั‚ะฝั” { #future } + +ะะฐ ั†ะตะน ะผะพะผะตะฝั‚ ัƒะถะต ะทั€ะพะทัƒะผั–ะปะพ, ั‰ะพ **FastAPI** ะทั– ัะฒะพั—ะผะธ ั–ะดะตัะผะธ ะบะพั€ะธัะฝะธะน ะดะปั ะฑะฐะณะฐั‚ัŒะพั…. + +ะ™ะพะณะพ ะพะฑะธั€ะฐัŽั‚ัŒ ะทะฐะผั–ัั‚ัŒ ะฟะพะฟะตั€ะตะดะฝั–ั… ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ, ะฑะพ ะฒั–ะฝ ะบั€ะฐั‰ะต ะฒั–ะดะฟะพะฒั–ะดะฐั” ะฑะฐะณะฐั‚ัŒะพะผ ัั†ะตะฝะฐั€ั–ัะผ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. + +ะ‘ะฐะณะฐั‚ะพ ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ ั– ะบะพะผะฐะฝะด ัƒะถะต ะทะฐะปะตะถะฐั‚ัŒ ะฒั–ะด **FastAPI** ัƒ ัะฒะพั—ั… ะฟั€ะพั”ะบั‚ะฐั… (ะฒะบะปัŽั‡ะฝะพ ะทั– ะผะฝะพัŽ ั‚ะฐ ะผะพั”ัŽ ะบะพะผะฐะฝะดะพัŽ). + +ะะปะต ะฟะพะฟะตั€ะตะดัƒ ั‰ะต ะฑะฐะณะฐั‚ะพ ะฟะพะบั€ะฐั‰ะตะฝัŒ ั– ะผะพะถะปะธะฒะพัั‚ะตะน. + +**FastAPI** ะผะฐั” ะฒะตะปะธะบะต ะผะฐะนะฑัƒั‚ะฝั”. + +ะ† [ะฒะฐัˆะฐ ะดะพะฟะพะผะพะณะฐ](help-fastapi.md){.internal-link target=_blank} ะดัƒะถะต ั†ั–ะฝัƒั”ั‚ัŒัั. diff --git a/docs/uk/docs/how-to/authentication-error-status-code.md b/docs/uk/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000..58016f261b --- /dev/null +++ b/docs/uk/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ัั‚ะฐั€ั– ะบะพะดะธ ัั‚ะฐั‚ัƒััƒ ะฟะพะผะธะปะบะธ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— 403 { #use-old-403-authentication-error-status-codes } + +ะ”ะพ ะฒะตั€ัั–ั— FastAPI `0.122.0`, ะบะพะปะธ ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– ะทะฐัะพะฑะธ ะฑะตะทะฟะตะบะธ ะฟะพะฒะตั€ั‚ะฐะปะธ ะบะปั–ั”ะฝั‚ัƒ ะฟะพะผะธะปะบัƒ ะฟั–ัะปั ะฝะตะฒะดะฐะปะพั— ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—, ะฒะพะฝะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ HTTP ะบะพะด ัั‚ะฐั‚ัƒััƒ `403 Forbidden`. + +ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะท ะฒะตั€ัั–ั— FastAPI `0.122.0`, ะฒะพะฝะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฑั–ะปัŒัˆ ะดะพั€ะตั‡ะฝะธะน HTTP ะบะพะด ัั‚ะฐั‚ัƒััƒ `401 Unauthorized` ั– ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒ ะทะผั–ัั‚ะพะฒะฝะธะน ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate` ัƒ ะฒั–ะดะฟะพะฒั–ะดั–, ะฒั–ะดะฟะพะฒั–ะดะฝะพ ะดะพ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ะน HTTP, RFC 7235, RFC 9110. + +ะะปะต ัะบั‰ะพ ะท ัะบะพั—ััŒ ะฟั€ะธั‡ะธะฝะธ ะฒะฐัˆั– ะบะปั–ั”ะฝั‚ะธ ะทะฐะปะตะถะฐั‚ัŒ ะฒั–ะด ัั‚ะฐั€ะพั— ะฟะพะฒะตะดั–ะฝะบะธ, ะฒะธ ะผะพะถะตั‚ะต ะฟะพะฒะตั€ะฝัƒั‚ะธัั ะดะพ ะฝะตั—, ะฟะตั€ะตะฟะธัะฐะฒัˆะธ ะผะตั‚ะพะด `make_not_authenticated_error` ัƒ ะฒะฐัˆะธั… ะบะปะฐัะฐั… ะฑะตะทะฟะตะบะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฟั–ะดะบะปะฐั `HTTPBearer`, ัะบะธะน ะฟะพะฒะตั€ั‚ะฐั‚ะธะผะต ะฟะพะผะธะปะบัƒ `403 Forbidden` ะทะฐะผั–ัั‚ัŒ ั‚ะธะฟะพะฒะพะณะพ `401 Unauthorized`: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั„ัƒะฝะบั†ั–ั ะฟะพะฒะตั€ั‚ะฐั” ะตะบะทะตะผะฟะปัั€ ะฒะธะฝัั‚ะบัƒ, ะฒะพะฝะฐ ะฝะต ะฟะพั€ะพะดะถัƒั” ะนะพะณะพ. ะŸะพั€ะพะดะถะตะฝะฝั ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั ะฒ ั–ะฝัˆั–ะน ั‡ะฐัั‚ะธะฝั– ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพะณะพ ะบะพะดัƒ. + +/// diff --git a/docs/uk/docs/how-to/conditional-openapi.md b/docs/uk/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000..f8bbaa6498 --- /dev/null +++ b/docs/uk/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# ะฃะผะพะฒะฝะธะน OpenAPI { #conditional-openapi } + +ะฏะบั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ั– ะทะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั, ั‰ะพะฑ ัƒะผะพะฒะฝะพ ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธ OpenAPI ะทะฐะปะตะถะฝะพ ะฒั–ะด ัะตั€ะตะดะพะฒะธั‰ะฐ, ะฐ ั‚ะฐะบะพะถ ะฟะพะฒะฝั–ัั‚ัŽ ะฒะธะผะธะบะฐั‚ะธ ะนะพะณะพ. + +## ะŸั€ะพ ะฑะตะทะฟะตะบัƒ, API ั‚ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #about-security-apis-and-docs } + +ะŸั€ะธั…ะพะฒัƒะฒะฐะฝะฝั ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ัƒ ะฟั€ะพะดัƒะบั†ั–ะนะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั– *ะฝะต ะผะฐั”* ะฑัƒั‚ะธ ัะฟะพัะพะฑะพะผ ะทะฐั…ะธัั‚ัƒ ะฒะฐัˆะพะณะพ API. + +ะฆะต ะฝะต ะดะพะดะฐั” ะถะพะดะฝะพั— ะดะพะดะฐั‚ะบะพะฒะพั— ะฑะตะทะฟะตะบะธ ะฒะฐัˆะพะผัƒ API, *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะน ะฝะฐะดะฐะปั– ะฑัƒะดัƒั‚ัŒ ะดะพัั‚ัƒะฟะฝั– ั‚ะฐะผ, ะดะต ะฒะพะฝะธ ั”. + +ะฏะบั‰ะพ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั– ั” ะฒั€ะฐะทะปะธะฒั–ัั‚ัŒ, ะฒะพะฝะฐ ะทะฐะปะธัˆะธั‚ัŒัั. + +ะŸั€ะธั…ะพะฒัƒะฒะฐะฝะฝั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะปะธัˆะต ัƒัะบะปะฐะดะฝัŽั” ั€ะพะทัƒะผั–ะฝะฝั ั‚ะพะณะพ, ัะบ ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฒะฐัˆะธะผ API, ั– ะผะพะถะต ัƒัะบะปะฐะดะฝะธั‚ะธ ะดะปั ะฒะฐั ะนะพะณะพ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั ัƒ ะฟั€ะพะดะฐะบัˆะฝั–. ะฆะต ะผะพะถะฝะฐ ะฒะฒะฐะถะฐั‚ะธ ะฟั€ะพัั‚ะพ ั„ะพั€ะผะพัŽ ะ‘ะตะทะฟะตะบะฐ ั‡ะตั€ะตะท ะฝะตััะฝั–ัั‚ัŒ. + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะทะฐั…ะธัั‚ะธั‚ะธ ะฒะฐัˆ API, ั” ะบั–ะปัŒะบะฐ ะบั€ะฐั‰ะธั… ะดั–ะน, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ, ะฝะฐะฟั€ะธะบะปะฐะด: + +- ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ัƒ ะฒะฐั ะดะพะฑั€ะต ะฒะธะทะฝะฐั‡ะตะฝั– ะผะพะดะตะปั– Pydantic ะดะปั ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ ั– ะฒั–ะดะฟะพะฒั–ะดะตะน. +- ะะฐะปะฐัˆั‚ัƒะนั‚ะต ะฟะพั‚ั€ั–ะฑะฝั– ะดะพะทะฒะพะปะธ ั‚ะฐ ั€ะพะปั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะทะฐะปะตะถะฝะพัั‚ะตะน. +- ะั–ะบะพะปะธ ะฝะต ะทะฑะตั€ั–ะณะฐะนั‚ะต ะฟะฐั€ะพะปั– ัƒ ะฒั–ะดะบั€ะธั‚ะพะผัƒ ะฒะธะณะปัะดั–, ะปะธัˆะต ั…ะตัˆั– ะฟะฐั€ะพะปั–ะฒ. +- ะ ะตะฐะปั–ะทัƒะนั‚ะต ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฒั–ะดะพะผั– ะบั€ะธะฟั‚ะพะณั€ะฐั„ั–ั‡ะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ัะบ-ะพั‚ pwdlib ั– ั‚ะพะบะตะฝะธ JWT. +- ะ”ะพะดะฐะนั‚ะต ะฑั–ะปัŒัˆ ะดะตั‚ะฐะปัŒะฝะธะน ะบะพะฝั‚ั€ะพะปัŒ ะดะพะทะฒะพะปั–ะฒ ั–ะท ะพะฑะปะฐัั‚ัะผะธ OAuth2 ั‚ะฐะผ, ะดะต ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ. +- ...ั‚ะพั‰ะพ. + +ะ’ั‚ั–ะผ, ัƒ ะฒะฐั ะผะพะถะต ะฑัƒั‚ะธ ะดัƒะถะต ัะฟะตั†ะธั„ั–ั‡ะฝะธะน ะฒะธะฟะฐะดะพะบ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั, ะบะพะปะธ ัะฟั€ะฐะฒะดั– ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะผะบะฝัƒั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API ะดะปั ะฟะตะฒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ (ะฝะฐะฟั€ะธะบะปะฐะด, ะดะปั ะฟั€ะพะดะฐะบัˆะฝัƒ) ะฐะฑะพ ะทะฐะปะตะถะฝะพ ะฒั–ะด ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ะน ะทั– ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั. + +## ะฃะผะพะฒะฝะธะน OpenAPI ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ ั– ะทะผั–ะฝะฝะธั… ะพั‚ะพั‡ะตะฝะฝั { #conditional-openapi-from-settings-and-env-vars } + +ะ’ะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ั– ัะฐะผั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั Pydantic, ั‰ะพะฑ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน OpenAPI ั‚ะฐ ั–ะฝั‚ะตั€ั„ะตะนัะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะะฐะฟั€ะธะบะปะฐะด: + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +ะขัƒั‚ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั `openapi_url` ะท ั‚ะธะผ ัะฐะผะธะผ ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `"/openapi.json"`. + +ะŸะพั‚ั–ะผ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะนะพะณะพ ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`. + +ะ”ะฐะปั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะผะบะฝัƒั‚ะธ OpenAPI (ะฒะบะปัŽั‡ะฝะพ ะท ั–ะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—), ะฒัั‚ะฐะฝะพะฒะธะฒัˆะธ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `OPENAPI_URL` ัƒ ะฟัƒัั‚ัƒ ัั‚ั€ะพะบัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะŸะพั‚ั–ะผ, ัะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะทะฐ URL `/openapi.json`, `/docs` ะฐะฑะพ `/redoc`, ะฒะธ ะฟั€ะพัั‚ะพ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะพะผะธะปะบัƒ `404 Not Found` ะฝะฐ ะบัˆั‚ะฐะปั‚: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/uk/docs/how-to/configure-swagger-ui.md b/docs/uk/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000..f8c4470dfa --- /dev/null +++ b/docs/uk/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# ะะฐะปะฐัˆั‚ัƒะนั‚ะต Swagger UI { #configure-swagger-ui } + +ะ’ะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะดะพะดะฐั‚ะบะพะฒั– ะฟะฐั€ะฐะผะตั‚ั€ะธ Swagger UI. + +ะฉะพะฑ ั—ั… ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ, ะฟะตั€ะตะดะฐะนั‚ะต ะฐั€ะณัƒะผะตะฝั‚ `swagger_ui_parameters` ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะพะฑโ€™ั”ะบั‚ะฐ ะดะพะดะฐั‚ะบะฐ `FastAPI()` ะฐะฑะพ ะดะพ ั„ัƒะฝะบั†ั–ั— `get_swagger_ui_html()`. + +`swagger_ui_parameters` ะพั‚ั€ะธะผัƒั” ัะปะพะฒะฝะธะบ ั–ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ, ั‰ะพ ะฟะตั€ะตะดะฐัŽั‚ัŒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะดะพ Swagger UI. + +FastAPI ะฟะตั€ะตั‚ะฒะพั€ัŽั” ั†ั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะฝะฐ **JSON**, ั‰ะพะฑ ะทั€ะพะฑะธั‚ะธ ั—ั… ััƒะผั–ัะฝะธะผะธ ะท JavaScript, ะพัะบั–ะปัŒะบะธ ัะฐะผะต ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ Swagger UI. + +## ะ’ะธะผะบะฝั–ั‚ัŒ ะฟั–ะดัะฒั–ั‚ะบัƒ ัะธะฝั‚ะฐะบัะธััƒ { #disable-syntax-highlighting } + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะผะบะฝัƒั‚ะธ ะฟั–ะดัะฒั–ั‚ะบัƒ ัะธะฝั‚ะฐะบัะธััƒ ะฒ Swagger UI. + +ะ‘ะตะท ะทะผั–ะฝ ัƒ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัั… ะฟั–ะดัะฒั–ั‚ะบะฐ ัะธะฝั‚ะฐะบัะธััƒ ัƒะฒั–ะผะบะฝะตะฝะฐ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ: + + + +ะะปะต ะฒะธ ะผะพะถะตั‚ะต ะฒะธะผะบะฝัƒั‚ะธ ั—ั—, ะฒัั‚ะฐะฝะพะฒะธะฒัˆะธ `syntaxHighlight` ัƒ `False`: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...ะฟั–ัะปั ั†ัŒะพะณะพ Swagger UI ะฑั–ะปัŒัˆะต ะฝะต ะฟะพะบะฐะทัƒะฒะฐั‚ะธะผะต ะฟั–ะดัะฒั–ั‚ะบัƒ ัะธะฝั‚ะฐะบัะธััƒ: + + + +## ะ—ะผั–ะฝั–ั‚ัŒ ั‚ะตะผัƒ { #change-the-theme } + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะดะฐั‚ะธ ั‚ะตะผัƒ ะฟั–ะดัะฒั–ั‚ะบะธ ัะธะฝั‚ะฐะบัะธััƒ ะบะปัŽั‡ะตะผ `"syntaxHighlight.theme"` (ะทะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฟะพัะตั€ะตะดะธะฝั– ั” ะบั€ะฐะฟะบะฐ): + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +ะฆะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะทะผั–ะฝะธั‚ัŒ ะบะพะปั–ั€ะฝัƒ ั‚ะตะผัƒ ะฟั–ะดัะฒั–ั‚ะบะธ ัะธะฝั‚ะฐะบัะธััƒ: + + + +## ะ—ะผั–ะฝั–ั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ะธ Swagger UI ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ { #change-default-swagger-ui-parameters } + +FastAPI ะผั–ัั‚ะธั‚ัŒ ะดะตัะบั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะบะพะฝั„ั–ะณัƒั€ะฐั†ั–ั— ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ั‰ะพ ะฟั–ะดั…ะพะดัั‚ัŒ ะดะปั ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ. + +ะ’ะพะฝะธ ะฒะบะปัŽั‡ะฐัŽั‚ัŒ ั‚ะฐะบั– ั‚ะธะฟะพะฒั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฟะธัะฐั‚ะธ ะฑัƒะดัŒ-ัะบะต ะท ะฝะธั…, ะทะฐะดะฐะฒัˆะธ ั–ะฝัˆะต ะทะฝะฐั‡ะตะฝะฝั ะฒ ะฐั€ะณัƒะผะตะฝั‚ั– `swagger_ui_parameters`. + +ะะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฒะธะผะบะฝัƒั‚ะธ `deepLinking`, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั‚ะฐะบั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะดะพ `swagger_ui_parameters`: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## ะ†ะฝัˆั– ะฟะฐั€ะฐะผะตั‚ั€ะธ Swagger UI { #other-swagger-ui-parameters } + +ะฉะพะฑ ะฟะพะฑะฐั‡ะธั‚ะธ ะฒัั– ะผะพะถะปะธะฒั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะพั„ั–ั†ั–ะนะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ั‰ะพะดะพ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ Swagger UI. + +## ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะปะธัˆะต ะดะปั JavaScript { #javascript-only-settings } + +Swagger UI ั‚ะฐะบะพะถ ะดะพะทะฒะพะปัั” ั–ะฝัˆั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ัะบ ะพะฑโ€™ั”ะบั‚ะธ, ั‰ะพ ั” ั‚ั–ะปัŒะบะธ ะดะปั **JavaScript** (ะฝะฐะฟั€ะธะบะปะฐะด, ั„ัƒะฝะบั†ั–ั— JavaScript). + +FastAPI ั‚ะฐะบะพะถ ะฒะบะปัŽั‡ะฐั” ั‚ะฐะบั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั `presets`, ั‰ะพ ั” ะปะธัˆะต ะดะปั JavaScript: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +ะฆะต ะพะฑโ€™ั”ะบั‚ะธ **JavaScript**, ะฐ ะฝะต ัั‚ั€ะพะบะธ, ั‚ะพะผัƒ ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ั—ั… ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะท ะบะพะดัƒ Python. + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ะฐะบั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะปะธัˆะต ะดะปั JavaScript, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ะพะดะฝะธะผ ั–ะท ะผะตั‚ะพะดั–ะฒ ะฒะธั‰ะต. ะŸะพะฒะฝั–ัั‚ัŽ ะฟะตั€ะตะฟะธัˆั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ Swagger UI ั‚ะฐ ะฒั€ัƒั‡ะฝัƒ ะฝะฐะฟะธัˆั–ั‚ัŒ ะฟะพั‚ั€ั–ะฑะฝะธะน JavaScript. diff --git a/docs/uk/docs/how-to/custom-docs-ui-assets.md b/docs/uk/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000..faea3ccc4a --- /dev/null +++ b/docs/uk/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ัั‚ะฐั‚ะธั‡ะฝั– ั€ะตััƒั€ัะธ ั–ะฝั‚ะตั€ั„ะตะนััƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ัะฐะผะพั…ะพัั‚ะธะฝะณ) { #custom-docs-ui-static-assets-self-hosting } + +ะ”ะพะบัƒะผะตะฝั‚ะฐั†ั–ั API ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” **Swagger UI** ั– **ReDoc**, ั– ะบะพะถะฝะพะผัƒ ะท ะฝะธั… ะฟะพั‚ั€ั–ะฑะฝั– ั„ะฐะนะปะธ JavaScript ั‚ะฐ CSS. + +ะขะธะฟะพะฒะพ ั†ั– ั„ะฐะนะปะธ ะฒั–ะดะดะฐัŽั‚ัŒัั ะท CDN. + +ะะปะต ั†ะต ะผะพะถะฝะฐ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ: ะฒะธ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝะธะน CDN ะฐะฑะพ ะฒั–ะดะดะฐะฒะฐั‚ะธ ั„ะฐะนะปะธ ัะฐะผะพัั‚ั–ะนะฝะพ. + +## ะ’ะปะฐัะฝะธะน CDN ะดะปั JavaScript ั– CSS { #custom-cdn-for-javascript-and-css } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัˆะธะน CDN, ะฝะฐะฟั€ะธะบะปะฐะด `https://unpkg.com/`. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพ, ัะบั‰ะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะถะธะฒะตั‚ะต ะฒ ะบั€ะฐั—ะฝั–, ั‰ะพ ะพะฑะผะตะถัƒั” ะดะตัะบั– URL-ะฐะดั€ะตัะธ. + +### ะ’ะธะผะบะฝั–ั‚ัŒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #disable-the-automatic-docs } + +ะŸะตั€ัˆะธะน ะบั€ะพะบ - ะฒะธะผะบะฝัƒั‚ะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ, ะฐะดะถะต ั‚ะธะฟะพะฒะพ ะฒะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน CDN. + +ะฉะพะฑ ั—ั… ะฒะธะผะบะฝัƒั‚ะธ, ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ั—ั…ะฝั– URL ัƒ `None` ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### ะ”ะพะดะฐะนั‚ะต ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ { #include-the-custom-docs } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะดะปั ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั„ัƒะฝะบั†ั–ั— FastAPI ะดะปั ัั‚ะฒะพั€ะตะฝะฝั HTML-ัั‚ะพั€ั–ะฝะพะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั– ะฟะตั€ะตะดะฐั‚ะธ ั—ะผ ะฟะพั‚ั€ั–ะฑะฝั– ะฐั€ะณัƒะผะตะฝั‚ะธ: + +- `openapi_url`: URL, ะทะฐ ัะบะธะผ HTML-ัั‚ะพั€ั–ะฝะบะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ัั…ะตะผัƒ OpenAPI ะดะปั ะฒะฐัˆะพะณะพ API. ะขัƒั‚ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฐั‚ั€ะธะฑัƒั‚ `app.openapi_url`. +- `title`: ะทะฐะณะพะปะพะฒะพะบ ะฒะฐัˆะพะณะพ API. +- `oauth2_redirect_url`: ั‚ัƒั‚ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `app.swagger_ui_oauth2_redirect_url`, ั‰ะพะฑ ัƒะทัั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +- `swagger_js_url`: URL, ะทะฐ ัะบะธะผ HTML ะดะปั Swagger UI ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะนะป **JavaScript**. ะฆะต URL ะฒะฐัˆะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะณะพ CDN. +- `swagger_css_url`: URL, ะทะฐ ัะบะธะผ HTML ะดะปั Swagger UI ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะนะป **CSS**. ะฆะต URL ะฒะฐัˆะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะณะพ CDN. + +ะะฝะฐะปะพะณั–ั‡ะฝะพ ะดะปั ReDoc... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +*ะžะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะดะปั `swagger_ui_redirect` - ั†ะต ะดะพะฟะพะผั–ะถะฝะธะน ะผะฐั€ัˆั€ัƒั‚, ะบะพะปะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต OAuth2. + +ะฏะบั‰ะพ ะฒะธ ั–ะฝั‚ะตะณั€ัƒั”ั‚ะต ะฒะฐัˆ API ะท ะฟั€ะพะฒะฐะนะดะตั€ะพะผ OAuth2, ะฒะธ ะทะผะพะถะตั‚ะต ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธัั ั– ะฟะพะฒะตั€ะฝัƒั‚ะธัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API ะท ะพั‚ั€ะธะผะฐะฝะธะผะธ ะพะฑะปั–ะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ. ะ† ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฝะธะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั€ะตะฐะปัŒะฝัƒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ OAuth2. + +Swagger UI ะฒะฟะพั€ะฐั”ั‚ัŒัั ะท ั†ะธะผ ยซะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธยป, ะฐะปะต ะนะพะผัƒ ะฟะพั‚ั€ั–ะฑะตะฝ ั†ะตะน ยซredirectยป ั…ะตะปะฟะตั€. + +/// + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ { #create-a-path-operation-to-test-it } + +ะขะตะฟะตั€, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั”, ัั‚ะฒะพั€ั–ั‚ัŒ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ*: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต { #test-it } + +ะขะตะฟะตั€ ะฒะธ ะผะฐั”ั‚ะต ะทะผะพะณัƒ ะฒั–ะดะบั€ะธั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะทะฐ http://127.0.0.1:8000/docs ั– ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ัั‚ะพั€ั–ะฝะบัƒ, ะฒะพะฝะฐ ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ัŒ ั†ั– ั€ะตััƒั€ัะธ ะท ะฝะพะฒะพะณะพ CDN. + +## ะกะฐะผะพั…ะพัั‚ะธะฝะณ JavaScript ั– CSS ะดะปั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #self-hosting-javascript-and-css-for-docs } + +ะกะฐะผะพั…ะพัั‚ะธะฝะณ JavaScript ั– CSS ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะธะผ, ัะบั‰ะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ะผะฐั” ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะพั„ะปะฐะนะฝ, ะฑะตะท ะดะพัั‚ัƒะฟัƒ ะดะพ ะ†ะฝั‚ะตั€ะฝะตั‚ัƒ, ะฐะฑะพ ะฒ ะปะพะบะฐะปัŒะฝั–ะน ะผะตั€ะตะถั–. + +ะขัƒั‚ ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบ ะฒั–ะดะดะฐะฒะฐั‚ะธ ั†ั– ั„ะฐะนะปะธ ัะฐะผะพัั‚ั–ะนะฝะพ, ัƒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ FastAPI, ั– ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะฝะฐ ั—ั… ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. + +### ะกั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะฟั€ะพั”ะบั‚ัƒ { #project-file-structure } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ ะฒะธะณะปัะดะฐั” ั‚ะฐะบ: + +``` +. +โ”œโ”€โ”€ app +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py +``` + +ะขะตะฟะตั€ ัั‚ะฒะพั€ั–ั‚ัŒ ะบะฐั‚ะฐะปะพะณ ะดะปั ะทะฑะตั€ะตะถะตะฝะฝั ั†ะธั… ัั‚ะฐั‚ะธั‡ะฝะธั… ั„ะฐะนะปั–ะฒ. + +ะะพะฒะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static/ +``` + +### ะ—ะฐะฒะฐะฝั‚ะฐะถั‚ะต ั„ะฐะนะปะธ { #download-the-files } + +ะ—ะฐะฒะฐะฝั‚ะฐะถั‚ะต ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ, ะฟะพั‚ั€ั–ะฑะฝั– ะดะปั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ั– ะฟะพะผั–ัั‚ั–ั‚ัŒ ั—ั… ัƒ ะบะฐั‚ะฐะปะพะณ `static/`. + +ะ’ะธ, ะนะผะพะฒั–ั€ะฝะพ, ะผะพะถะตั‚ะต ะฝะฐั‚ะธัะฝัƒั‚ะธ ะฟั€ะฐะฒะพัŽ ะบะฝะพะฟะบะพัŽ ะฝะฐ ะบะพะถะฝะพะผัƒ ะฟะพัะธะปะฐะฝะฝั– ั– ะฒะธะฑั€ะฐั‚ะธ ะพะฟั†ั–ัŽ ะฝะฐ ะบัˆั‚ะฐะปั‚ ยซะ—ะฑะตั€ะตะณั‚ะธ ะฟะพัะธะปะฐะฝะฝั ัะบ...ยป. + +**Swagger UI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั„ะฐะนะปะธ: + +- `swagger-ui-bundle.js` +- `swagger-ui.css` + +ะ **ReDoc** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั„ะฐะนะป: + +- `redoc.standalone.js` + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒะฐัˆะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ””โ”€โ”€ static + โ”œโ”€โ”€ redoc.standalone.js + โ”œโ”€โ”€ swagger-ui-bundle.js + โ””โ”€โ”€ swagger-ui.css +``` + +### ะžะฑัะปัƒะณะพะฒัƒะนั‚ะต ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ { #serve-the-static-files } + +- ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `StaticFiles`. +- ะ—ะผะพะฝั‚ัƒะนั‚ะต ะตะบะทะตะผะฟะปัั€ `StaticFiles()` ัƒ ะฟะตะฒะฝะพะผัƒ ัˆะปัั…ัƒ. + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ { #test-the-static-files } + +ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ ั– ะฟะตั€ะตะนะดั–ั‚ัŒ ะดะพ http://127.0.0.1:8000/static/redoc.standalone.js. + +ะ’ะธ ะผะฐั”ั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ ะดัƒะถะต ะดะพะฒะณะธะน ั„ะฐะนะป JavaScript ะดะปั **ReDoc**. + +ะ’ั–ะฝ ะผะพะถะต ะฟะพั‡ะธะฝะฐั‚ะธัั ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบ: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +ะฆะต ะฟั–ะดั‚ะฒะตั€ะดะถัƒั”, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒั–ะดะดะฐะฒะฐั‚ะธ ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ ะท ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ั– ั‰ะพ ะฒะธ ั€ะพะทะผั–ัั‚ะธะปะธ ัั‚ะฐั‚ะธั‡ะฝั– ั„ะฐะนะปะธ ะดะปั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ัƒ ะฟั€ะฐะฒะธะปัŒะฝะพะผัƒ ะผั–ัั†ั–. + +ะขะตะฟะตั€ ะผะธ ะผะพะถะตะผะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั†ะธั… ัั‚ะฐั‚ะธั‡ะฝะธั… ั„ะฐะนะปั–ะฒ ะดะปั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +### ะ’ะธะผะบะฝั–ั‚ัŒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั ัั‚ะฐั‚ะธั‡ะฝะธั… ั„ะฐะนะปั–ะฒ { #disable-the-automatic-docs-for-static-files } + +ะฏะบ ั– ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะณะพ CDN, ะฟะตั€ัˆะธะผ ะบั€ะพะบะพะผ ั” ะฒะธะผะบะฝะตะฝะฝั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะพัะบั–ะปัŒะบะธ ั‚ะธะฟะพะฒะพ ะฒะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” CDN. + +ะฉะพะฑ ั—ั… ะฒะธะผะบะฝัƒั‚ะธ, ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ั—ั…ะฝั– URL ัƒ `None` ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### ะ”ะพะดะฐะนั‚ะต ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั ัั‚ะฐั‚ะธั‡ะฝะธั… ั„ะฐะนะปั–ะฒ { #include-the-custom-docs-for-static-files } + +ะะฝะฐะปะพะณั–ั‡ะฝะพ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะผัƒ CDN, ั‚ะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะดะปั ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +ะ—ะฝะพะฒัƒ ะถ, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฒะฝัƒั‚ั€ั–ัˆะฝั– ั„ัƒะฝะบั†ั–ั— FastAPI ะดะปั ัั‚ะฒะพั€ะตะฝะฝั HTML-ัั‚ะพั€ั–ะฝะพะบ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั– ะฟะตั€ะตะดะฐั‚ะธ ั—ะผ ะฟะพั‚ั€ั–ะฑะฝั– ะฐั€ะณัƒะผะตะฝั‚ะธ: + +- `openapi_url`: URL, ะทะฐ ัะบะธะผ HTML-ัั‚ะพั€ั–ะฝะบะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ัั…ะตะผัƒ OpenAPI ะดะปั ะฒะฐัˆะพะณะพ API. ะขัƒั‚ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฐั‚ั€ะธะฑัƒั‚ `app.openapi_url`. +- `title`: ะทะฐะณะพะปะพะฒะพะบ ะฒะฐัˆะพะณะพ API. +- `oauth2_redirect_url`: ั‚ัƒั‚ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `app.swagger_ui_oauth2_redirect_url`, ั‰ะพะฑ ัƒะทัั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +- `swagger_js_url`: URL, ะทะฐ ัะบะธะผ HTML ะดะปั Swagger UI ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะนะป **JavaScript**. **ะฆะต ั‚ะพะน ั„ะฐะนะป, ัะบะธะน ั‚ะตะฟะตั€ ะฒั–ะดะดะฐั” ะฒะฐัˆ ะฒะปะฐัะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ**. +- `swagger_css_url`: URL, ะทะฐ ัะบะธะผ HTML ะดะปั Swagger UI ะทะผะพะถะต ะพั‚ั€ะธะผะฐั‚ะธ ั„ะฐะนะป **CSS**. **ะฆะต ั‚ะพะน ั„ะฐะนะป, ัะบะธะน ั‚ะตะฟะตั€ ะฒั–ะดะดะฐั” ะฒะฐัˆ ะฒะปะฐัะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ**. + +ะะฝะฐะปะพะณั–ั‡ะฝะพ ะดะปั ReDoc... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +*ะžะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะดะปั `swagger_ui_redirect` - ั†ะต ะดะพะฟะพะผั–ะถะฝะธะน ะผะฐั€ัˆั€ัƒั‚, ะบะพะปะธ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต OAuth2. + +ะฏะบั‰ะพ ะฒะธ ั–ะฝั‚ะตะณั€ัƒั”ั‚ะต ะฒะฐัˆ API ะท ะฟั€ะพะฒะฐะนะดะตั€ะพะผ OAuth2, ะฒะธ ะทะผะพะถะตั‚ะต ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธัั ั– ะฟะพะฒะตั€ะฝัƒั‚ะธัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API ะท ะพั‚ั€ะธะผะฐะฝะธะผะธ ะพะฑะปั–ะบะพะฒะธะผะธ ะดะฐะฝะธะผะธ. ะ† ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฝะธะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั€ะตะฐะปัŒะฝัƒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ OAuth2. + +Swagger UI ะฒะฟะพั€ะฐั”ั‚ัŒัั ะท ั†ะธะผ ยซะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธยป, ะฐะปะต ะนะพะผัƒ ะฟะพั‚ั€ั–ะฑะตะฝ ั†ะตะน ยซredirectยป ั…ะตะปะฟะตั€. + +/// + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ ัั‚ะฐั‚ะธั‡ะฝะธั… ั„ะฐะนะปั–ะฒ { #create-a-path-operation-to-test-static-files } + +ะขะตะฟะตั€, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั”, ัั‚ะฒะพั€ั–ั‚ัŒ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ*: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต UI ะทั– ัั‚ะฐั‚ะธั‡ะฝะธะผะธ ั„ะฐะนะปะฐะผะธ { #test-static-files-ui } + +ะขะตะฟะตั€ ะฒะธ ะผะฐั”ั‚ะต ะทะผะพะณัƒ ะฒะธะผะบะฝัƒั‚ะธ WiFi, ะฒั–ะดะบั€ะธั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะทะฐ http://127.0.0.1:8000/docs ั– ะฟะตั€ะตะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ัั‚ะพั€ั–ะฝะบัƒ. + +ะ† ะฝะฐะฒั–ั‚ัŒ ะฑะตะท ะ†ะฝั‚ะตั€ะฝะตั‚ัƒ ะฒะธ ะทะผะพะถะตั‚ะต ะฟะพะฑะฐั‡ะธั‚ะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั ะฒะฐัˆะพะณะพ API ั– ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฝะธะผ. diff --git a/docs/uk/docs/how-to/custom-request-and-route.md b/docs/uk/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000..9f21da7a86 --- /dev/null +++ b/docs/uk/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– ะบะปะฐัะธ Request ั‚ะฐ APIRoute { #custom-request-and-apiroute-class } + +ะฃ ะดะตัะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะฟะตั€ะตะฒะธะทะฝะฐั‡ะธั‚ะธ ะปะพะณั–ะบัƒ, ัะบัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะบะปะฐัะธ `Request` ั‚ะฐ `APIRoute`. + +ะ—ะพะบั€ะตะผะฐ, ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ะดะพะฑั€ะพัŽ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะพัŽ ะปะพะณั–ั†ั– ะฒ ะฟั€ะพะผั–ะถะฝะพะผัƒ ะฟั€ะพะณั€ะฐะผะฝะพะผัƒ ะทะฐะฑะตะทะฟะตั‡ะตะฝะฝั–. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะฐะฑะพ ะทะผั–ะฝะธั‚ะธ ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ ะดะพ ั‚ะพะณะพ, ัะบ ะนะพะณะพ ะพะฑั€ะพะฑะธั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ. + +/// danger | ะžะฑะตั€ะตะถะฝะพ + +ะฆะต ยซะฟั€ะพััƒะฝัƒั‚ะฐยป ะผะพะถะปะธะฒั–ัั‚ัŒ. + +ะฏะบั‰ะพ ะฒะธ ั‚ั–ะปัŒะบะธ ะฟะพั‡ะธะฝะฐั”ั‚ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท **FastAPI**, ะผะพะถะปะธะฒะพ, ะฒะฐั€ั‚ะพ ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะตะน ั€ะพะทะดั–ะป. + +/// + +## ะ’ะธะฟะฐะดะบะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั { #use-cases } + +ะ”ะตัะบั– ะฒะฐั€ั–ะฐะฝั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั: + +- ะŸะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะฝะต-JSON ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ ะฝะฐ JSON (ะฝะฐะฟั€ะธะบะปะฐะด, `msgpack`). +- ะ ะพะทะฟะฐะบัƒะฒะฐะฝะฝั ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ, ัั‚ะธัะฝะตะฝะธั… gzip. +- ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะต ะปะพะณัƒะฒะฐะฝะฝั ะฒัั–ั… ั‚ั–ะป ะทะฐะฟะธั‚ั–ะฒ. + +## ะžะฑั€ะพะฑะบะฐ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธั… ะบะพะดัƒะฒะฐะฝัŒ ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ { #handling-custom-request-body-encodings } + +ะ ะพะทะณะปัะฝัŒะผะพ, ัะบ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะฟั–ะดะบะปะฐั `Request` ะดะปั ั€ะพะทะฟะฐะบัƒะฒะฐะฝะฝั gzip-ะทะฐะฟะธั‚ั–ะฒ. + +ะ ั‚ะฐะบะพะถ ะฟั–ะดะบะปะฐั `APIRoute`, ั‰ะพะฑ ะทะฐัั‚ะพััƒะฒะฐั‚ะธ ั†ะตะน ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะบะปะฐั ะทะฐะฟะธั‚ัƒ. + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะบะปะฐั `GzipRequest` { #create-a-custom-gziprequest-class } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฟั€ะพะดะตะผะพะฝัั‚ั€ัƒะฒะฐั‚ะธ ะฟั€ะธะฝั†ะธะฟ ั€ะพะฑะพั‚ะธ. ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ Gzip, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ะฒะฑัƒะดะพะฒะฐะฝะธะผ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}. + +/// + +ะกะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ะธะผะพ ะบะปะฐั `GzipRequest`, ัะบะธะน ะฟะตั€ะตะฒะธะทะฝะฐั‡ะธั‚ัŒ ะผะตั‚ะพะด `Request.body()`, ั‰ะพะฑ ั€ะพะทะฟะฐะบะพะฒัƒะฒะฐั‚ะธ ั‚ั–ะปะพ ะทะฐ ะฝะฐัะฒะฝะพัั‚ั– ะฒั–ะดะฟะพะฒั–ะดะฝะพะณะพ ะทะฐะณะพะปะพะฒะบะฐ. + +ะฏะบั‰ะพ ะฒ ะทะฐะณะพะปะพะฒะบัƒ ะฝะตะผะฐั” `gzip`, ะฒั–ะฝ ะฝะต ะฝะฐะผะฐะณะฐั‚ะธะผะตั‚ัŒัั ั€ะพะทะฟะฐะบะพะฒัƒะฒะฐั‚ะธ ั‚ั–ะปะพ. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะพะดะธะฝ ั– ั‚ะพะน ัะฐะผะธะน ะบะปะฐั ะผะฐั€ัˆั€ัƒั‚ัƒ ะทะผะพะถะต ะพะฑั€ะพะฑะปัั‚ะธ ัะบ ัั‚ะธัะฝะตะฝั– gzip, ั‚ะฐะบ ั– ะฝะตัั‚ะธัะฝะตะฝั– ะทะฐะฟะธั‚ะธ. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะบะปะฐั `GzipRoute` { #create-a-custom-gziproute-class } + +ะ”ะฐะปั– ัั‚ะฒะพั€ะธะผะพ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะฟั–ะดะบะปะฐั `fastapi.routing.APIRoute`, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต `GzipRequest`. + +ะฆัŒะพะณะพ ั€ะฐะทัƒ ะฒั–ะฝ ะฟะตั€ะตะฒะธะทะฝะฐั‡ะธั‚ัŒ ะผะตั‚ะพะด `APIRoute.get_route_handler()`. + +ะฆะตะน ะผะตั‚ะพะด ะฟะพะฒะตั€ั‚ะฐั” ั„ัƒะฝะบั†ั–ัŽ. ะ† ัะฐะผะต ั†ั ั„ัƒะฝะบั†ั–ั ะฟั€ะธะนะผะต ะทะฐะฟะธั‚ ั– ะฟะพะฒะตั€ะฝะต ะฒั–ะดะฟะพะฒั–ะดัŒ. + +ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั—ั—, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ `GzipRequest` ะท ะฟะพั‡ะฐั‚ะบะพะฒะพะณะพ ะทะฐะฟะธั‚ัƒ. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะฃ `Request` ั” ะฐั‚ั€ะธะฑัƒั‚ `request.scope` - ั†ะต ะฟั€ะพัั‚ะพ Python `dict`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะผะตั‚ะฐะดะฐะฝั–, ะฟะพะฒ'ัะทะฐะฝั– ั–ะท ะทะฐะฟะธั‚ะพะผ. + +ะขะฐะบะพะถ `Request` ะผะฐั” `request.receive` - ั†ะต ั„ัƒะฝะบั†ั–ั ะดะปั ยซะพั‚ั€ะธะผะฐะฝะฝัยป ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ. + +`scope` `dict` ั– ั„ัƒะฝะบั†ั–ั `receive` ั” ั‡ะฐัั‚ะธะฝะพัŽ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— ASGI. + +ะ† ัะฐะผะต ั†ั– ะดะฒั– ััƒั‚ะฝะพัั‚ั– - `scope` ั‚ะฐ `receive` - ะฟะพั‚ั€ั–ะฑะฝั– ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ะตะบะทะตะผะฟะปัั€ะฐ `Request`. + +ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ `Request`, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Starlette ะฟั€ะพ ะทะฐะฟะธั‚ะธ. + +/// + +ะ„ะดะธะฝะต, ั‰ะพ ั€ะพะฑะธั‚ัŒ ั–ะฝะฐะบัˆะต ั„ัƒะฝะบั†ั–ั, ะฟะพะฒะตั€ะฝะตะฝะฐ `GzipRequest.get_route_handler`, - ะฟะตั€ะตั‚ะฒะพั€ัŽั” `Request` ะฝะฐ `GzipRequest`. + +ะ—ะฐะฒะดัะบะธ ั†ัŒะพะผัƒ ะฝะฐัˆ `GzipRequest` ะฟะพะดะฑะฐั” ะฟั€ะพ ั€ะพะทะฟะฐะบัƒะฒะฐะฝะฝั ะดะฐะฝะธั… (ะทะฐ ะฟะพั‚ั€ะตะฑะธ) ะฟะตั€ะตะด ะฟะตั€ะตะดะฐะฒะฐะฝะฝัะผ ั—ั… ัƒ ะฝะฐัˆั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒัั ะปะพะณั–ะบะฐ ะพะฑั€ะพะฑะบะธ ะทะฐะปะธัˆะฐั”ั‚ัŒัั ั‚ั–ั”ัŽ ัะฐะผะพัŽ. + +ะ ะทะฐะฒะดัะบะธ ะทะผั–ะฝะฐะผ ัƒ `GzipRequest.body` ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ ะทะฐ ะฟะพั‚ั€ะตะฑะธ ะฑัƒะดะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ั€ะพะทะฟะฐะบะพะฒะฐะฝะต ะฟั–ะด ั‡ะฐั ะทะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั **FastAPI**. + +## ะ”ะพัั‚ัƒะฟ ะดะพ ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ ะฒ ะพะฑั€ะพะฑะฝะธะบัƒ ะฒะธะบะปัŽั‡ะตะฝัŒ { #accessing-the-request-body-in-an-exception-handler } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฉะพะฑ ั€ะพะทะฒโ€™ัะทะฐั‚ะธ ั†ะต ัะฐะผะต ะทะฐะฒะดะฐะฝะฝั, ัะบะพั€ั–ัˆ ะทะฐ ะฒัะต, ะฟั€ะพัั‚ั–ัˆะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `body` ัƒ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะผัƒ ะพะฑั€ะพะฑะฝะธะบัƒ `RequestValidationError` ([ะžะฑั€ะพะฑะบะฐ ะฟะพะผะธะปะพะบ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). + +ะะปะต ั†ะตะน ะฟั€ะธะบะปะฐะด ัƒัะต ั‰ะต ะบะพั€ะธัะฝะธะน ั– ะฟะพะบะฐะทัƒั”, ัะบ ะฒะทะฐั”ะผะพะดั–ัั‚ะธ ะท ะฒะฝัƒั‚ั€ั–ัˆะฝั–ะผะธ ะบะพะผะฟะพะฝะตะฝั‚ะฐะผะธ. + +/// + +ะœะธ ั‚ะฐะบะพะถ ะผะพะถะตะผะพ ัะบะพั€ะธัั‚ะฐั‚ะธัั ั†ะธะผ ะฟั–ะดั…ะพะดะพะผ, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ะดะพัั‚ัƒะฟ ะดะพ ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ ะฒ ะพะฑั€ะพะฑะฝะธะบัƒ ะฒะธะบะปัŽั‡ะตะฝัŒ. + +ะฃัะต, ั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ, - ะพะฑั€ะพะฑะธั‚ะธ ะทะฐะฟะธั‚ ัƒัะตั€ะตะดะธะฝั– ะฑะปะพะบัƒ `try`/`except`: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +ะฏะบั‰ะพ ัั‚ะฐะฝะตั‚ัŒัั ะฒะธะบะปัŽั‡ะตะฝะฝั, ะตะบะทะตะผะฟะปัั€ `Request` ัƒัะต ั‰ะต ะฑัƒะดะต ัƒ ะฒะธะดะธะผะพัั‚ั–, ั‚ะพะถ ะผะธ ะทะผะพะถะตะผะพ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ะน ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ั–ะปะพ ะทะฐะฟะธั‚ัƒ ะฟั–ะด ั‡ะฐั ะพะฑั€ะพะฑะบะธ ะฟะพะผะธะปะบะธ: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะบะปะฐั `APIRoute` ัƒ ะผะฐั€ัˆั€ัƒั‚ะธะทะฐั‚ะพั€ั– { #custom-apiroute-class-in-a-router } + +ะœะพะถะฝะฐ ั‚ะฐะบะพะถ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `route_class` ัƒ `APIRouter`: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒ `router` ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะบะปะฐั `TimedRoute` ั– ะผะฐั‚ะธะผัƒั‚ัŒ ะดะพะดะฐั‚ะบะพะฒะธะน ะทะฐะณะพะปะพะฒะพะบ ะฒั–ะดะฟะพะฒั–ะดั– `X-Response-Time` ั–ะท ั‡ะฐัะพะผ, ะฒะธั‚ั€ะฐั‡ะตะฝะธะผ ะฝะฐ ั„ะพั€ะผัƒะฒะฐะฝะฝั ะฒั–ะดะฟะพะฒั–ะดั–: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/uk/docs/how-to/extending-openapi.md b/docs/uk/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000..1597cbc762 --- /dev/null +++ b/docs/uk/docs/how-to/extending-openapi.md @@ -0,0 +1,80 @@ +# ะ ะพะทัˆะธั€ะตะฝะฝั OpenAPI { #extending-openapi } + +ะฃ ะดะตัะบะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะฐะผ ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะทะผั–ะฝะธั‚ะธ ะทะณะตะฝะตั€ะพะฒะฐะฝัƒ ัั…ะตะผัƒ OpenAPI. + +ะฃ ั†ัŒะพะผัƒ ั€ะพะทะดั–ะปั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ัะบ ั†ะต ะทั€ะพะฑะธั‚ะธ. + +## ะ—ะฒะธั‡ะฐะนะฝะธะน ะฟั€ะพั†ะตั { #the-normal-process } + +ะ—ะฒะธั‡ะฐะนะฝะธะน (ั‚ะธะฟะพะฒะธะน) ะฟั€ะพั†ะตั ั‚ะฐะบะธะน. + +ะ—ะฐัั‚ะพััƒะฝะพะบ `FastAPI` (ะตะบะทะตะผะฟะปัั€) ะผะฐั” ะผะตั‚ะพะด `.openapi()`, ัะบะธะน ะผะฐั” ะฟะพะฒะตั€ั‚ะฐั‚ะธ ัั…ะตะผัƒ OpenAPI. + +ะŸั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะพะฑ'ั”ะบั‚ะฐ ะทะฐัั‚ะพััƒะฝะบัƒ ั€ะตั”ัั‚ั€ัƒั”ั‚ัŒัั *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะดะปั `/openapi.json` (ะฐะฑะพ ะดะปั ั‚ะพะณะพ ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะฒะธ ะฒัั‚ะฐะฝะพะฒะธะปะธ ะฒ `openapi_url`). + +ะ’ะพะฝะฐ ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ั‚ะฐั” ะฒั–ะดะฟะพะฒั–ะดัŒ JSON ะท ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะผ ะผะตั‚ะพะดัƒ `.openapi()` ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะขะธะฟะพะฒะพ ะผะตั‚ะพะด `.openapi()` ะฟะตั€ะตะฒั–ั€ัั” ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `.openapi_schema`, ั– ัะบั‰ะพ ั‚ะฐะผ ะฒะถะต ั” ะดะฐะฝั–, ะฟะพะฒะตั€ั‚ะฐั” ั—ั…. + +ะฏะบั‰ะพ ะฝั–, ะฒั–ะฝ ะณะตะฝะตั€ัƒั” ั—ั… ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ัƒั‚ะธะปั–ั‚ะฐั€ะฝะพั— ั„ัƒะฝะบั†ั–ั— `fastapi.openapi.utils.get_openapi`. + +ะคัƒะฝะบั†ั–ั `get_openapi()` ะฟั€ะธะนะผะฐั” ั‚ะฐะบั– ะฟะฐั€ะฐะผะตั‚ั€ะธ: + +- `title`: ะ—ะฐะณะพะปะพะฒะพะบ OpenAPI, ะฟะพะบะฐะทัƒั”ั‚ัŒัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +- `version`: ะ’ะตั€ัั–ั ะฒะฐัˆะพะณะพ API, ะฝะฐะฟั€. `2.5.0`. +- `openapi_version`: ะ’ะตั€ัั–ั ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั. ะขะธะฟะพะฒะพ ะพัั‚ะฐะฝะฝั: `3.1.0`. +- `summary`: ะšะพั€ะพั‚ะบะธะน ะฟั–ะดััƒะผะพะบ API. +- `description`: ะžะฟะธั ะฒะฐัˆะพะณะพ API; ะผะพะถะต ะผั–ัั‚ะธั‚ะธ markdown ั– ะฑัƒะดะต ะฟะพะบะฐะทะฐะฝะธะน ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. +- `routes`: ะกะฟะธัะพะบ ะผะฐั€ัˆั€ัƒั‚ั–ะฒ, ั†ะต ะบะพะถะฝะฐ ะท ะทะฐั€ะตั”ัั‚ั€ะพะฒะฐะฝะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. ะ‡ั… ะฑะตั€ัƒั‚ัŒ ะท `app.routes`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะฐั€ะฐะผะตั‚ั€ `summary` ะดะพัั‚ัƒะฟะฝะธะน ะฒ OpenAPI 3.1.0 ั– ะฒะธั‰ะต, ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั FastAPI 0.99.0 ั– ะฒะธั‰ะต. + +/// + +## ะŸะตั€ะตะฟะธััƒะฒะฐะฝะฝั ั‚ะธะฟะพะฒะธั… ะทะฝะฐั‡ะตะฝัŒ { #overriding-the-defaults } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฝะฐะฒะตะดะตะฝะต ะฒะธั‰ะต, ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ั‚ั–ั”ัŽ ะถ ัƒั‚ะธะปั–ั‚ะฐั€ะฝะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ ะดะปั ะณะตะฝะตั€ะฐั†ั–ั— ัั…ะตะผะธ OpenAPI ั– ะฟะตั€ะตะฟะธัะฐั‚ะธ ะฟะพั‚ั€ั–ะฑะฝั– ั‡ะฐัั‚ะธะฝะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะดะพะดะฐะนะผะพ ั€ะพะทัˆะธั€ะตะฝะฝั OpenAPI ะดะปั ReDoc ะดะปั ะดะพะดะฐะฒะฐะฝะฝั ะฒะปะฐัะฝะพะณะพ ะปะพะณะพั‚ะธะฟะฐ. + +### ะ—ะฒะธั‡ะฐะนะฝะธะน **FastAPI** { #normal-fastapi } + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฝะฐะฟะธัˆั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ัะบ ะทะฐะทะฒะธั‡ะฐะน: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### ะ—ะณะตะฝะตั€ัƒะฒะฐั‚ะธ ัั…ะตะผัƒ OpenAPI { #generate-the-openapi-schema } + +ะ”ะฐะปั– ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ั‚ัƒ ะถ ัƒั‚ะธะปั–ั‚ะฐั€ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะดะปั ะณะตะฝะตั€ะฐั†ั–ั— ัั…ะตะผะธ OpenAPI ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— `custom_openapi()`: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### ะ—ะผั–ะฝะธั‚ะธ ัั…ะตะผัƒ OpenAPI { #modify-the-openapi-schema } + +ะขะตะฟะตั€ ะผะพะถะฝะฐ ะดะพะดะฐั‚ะธ ั€ะพะทัˆะธั€ะตะฝะฝั ReDoc, ะดะพะดะฐะฒัˆะธ ะฒะปะฐัะฝะธะน `x-logo` ะดะพ ยซะพะฑ'ั”ะบั‚ะฐยป `info` ัƒ ัั…ะตะผั– OpenAPI: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### ะšะตัˆัƒะฒะฐั‚ะธ ัั…ะตะผัƒ OpenAPI { #cache-the-openapi-schema } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒะปะฐัั‚ะธะฒั–ัั‚ัŒ `.openapi_schema` ัะบ ยซะบะตัˆยป ะดะปั ะทะฑะตั€ะตะถะตะฝะฝั ะทะณะตะฝะตั€ะพะฒะฐะฝะพั— ัั…ะตะผะธ. + +ะขะฐะบ ะฒะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฝะต ะดะพะฒะตะดะตั‚ัŒัั ั‰ะพั€ะฐะทัƒ ะณะตะฝะตั€ัƒะฒะฐั‚ะธ ัั…ะตะผัƒ, ะบะพะปะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฒั–ะดะบั€ะธะฒะฐั” ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะฒะฐัˆะพะณะพ API. + +ะ’ะพะฝะฐ ะฑัƒะดะต ะทะณะตะฝะตั€ะพะฒะฐะฝะฐ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท, ะฐ ะฟะพั‚ั–ะผ ั‚ะฐ ัะฐะผะฐ ะทะฐะบะตัˆะพะฒะฐะฝะฐ ัั…ะตะผะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ัŒัั ะดะปั ะฝะฐัั‚ัƒะฟะฝะธั… ะทะฐะฟะธั‚ั–ะฒ. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### ะŸะตั€ะตะฟะธัะฐั‚ะธ ะผะตั‚ะพะด { #override-the-method } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะผั–ะฝะธั‚ะธ ะผะตั‚ะพะด `.openapi()` ะฒะฐัˆะพัŽ ะฝะพะฒะพัŽ ั„ัƒะฝะบั†ั–ั”ัŽ. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะšะพะปะธ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/redoc, ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒะฐัˆ ะฒะปะฐัะฝะธะน ะปะพะณะพั‚ะธะฟ (ัƒ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะปะพะณะพั‚ะธะฟ **FastAPI**): + + diff --git a/docs/uk/docs/how-to/general.md b/docs/uk/docs/how-to/general.md new file mode 100644 index 0000000000..f33ae195c6 --- /dev/null +++ b/docs/uk/docs/how-to/general.md @@ -0,0 +1,39 @@ +# ะ—ะฐะณะฐะปัŒะฝะต - ะฏะบ ะทั€ะพะฑะธั‚ะธ - ะ ะตั†ะตะฟั‚ะธ { #general-how-to-recipes } + +ะะธะถั‡ะต ะฝะฐะฒะตะดะตะฝะพ ะบั–ะปัŒะบะฐ ะฒะบะฐะทั–ะฒะพะบ ะดะพ ั–ะฝัˆะธั… ั€ะพะทะดั–ะปั–ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะดะปั ะทะฐะณะฐะปัŒะฝะธั… ะฐะฑะพ ั‡ะฐัั‚ะธั… ะฟะธั‚ะฐะฝัŒ. + +## ะคั–ะปัŒั‚ั€ัƒะฒะฐะฝะฝั ะดะฐะฝะธั… - ะ‘ะตะทะฟะตะบะฐ { #filter-data-security } + +ะฉะพะฑ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ, ั‰ะพ ะฒะธ ะฝะต ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต ะฑั–ะปัŒัˆะต ะดะฐะฝะธั…, ะฝั–ะถ ัะปั–ะด, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะœะพะดะตะปัŒ ะฒั–ะดะฟะพะฒั–ะดั– - ะขะธะฟ ะฟะพะฒะตั€ะฝะตะฝะฝั](../tutorial/response-model.md){.internal-link target=_blank}. + +## ะœั–ั‚ะบะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— - OpenAPI { #documentation-tags-openapi } + +ะฉะพะฑ ะดะพะดะฐั‚ะธ ะผั–ั‚ะบะธ ะดะพ ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ั‚ะฐ ะทะณั€ัƒะฟัƒะฒะฐั‚ะธ ั—ั… ะฒ ั–ะฝั‚ะตั€ั„ะตะนัั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ - ะœั–ั‚ะบะธ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. + +## ะšะพั€ะพั‚ะบะธะน ะพะฟะธั ั– ะพะฟะธั - OpenAPI { #documentation-summary-and-description-openapi } + +ะฉะพะฑ ะดะพะดะฐั‚ะธ ะบะพั€ะพั‚ะบะธะน ะพะฟะธั ั– ะพะฟะธั ะดะพ ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ั– ะฟะพะบะฐะทะฐั‚ะธ ั—ั… ะฒ ั–ะฝั‚ะตั€ั„ะตะนัั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ - ะšะพั€ะพั‚ะบะธะน ะพะฟะธั ั– ะพะฟะธั](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. + +## ะžะฟะธั ะฒั–ะดะฟะพะฒั–ะดั– ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— - OpenAPI { #documentation-response-description-openapi } + +ะฉะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ะพะฟะธั ะฒั–ะดะฟะพะฒั–ะดั–, ั‰ะพ ะฒั–ะดะพะฑั€ะฐะถะฐั”ั‚ัŒัั ะฒ ั–ะฝั‚ะตั€ั„ะตะนัั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ - ะžะฟะธั ะฒั–ะดะฟะพะฒั–ะดั–](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. + +## ะŸะพะทะฝะฐั‡ะธั‚ะธ ะทะฐัั‚ะฐั€ั–ะปะพัŽ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +ะฉะพะฑ ะฟะพะทะฝะฐั‡ะธั‚ะธ *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* ัะบ ะทะฐัั‚ะฐั€ั–ะปัƒ ั– ะฟะพะบะฐะทะฐั‚ะธ ั†ะต ะฒ ั–ะฝั‚ะตั€ั„ะตะนัั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ - ะŸะพะทะฝะฐั‡ะตะฝะฝั ัะบ ะทะฐัั‚ะฐั€ั–ะปะต](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. + +## ะŸะตั€ะตั‚ะฒะพั€ะธั‚ะธ ะฑัƒะดัŒ-ัะบั– ะดะฐะฝั– ะฝะฐ ััƒะผั–ัะฝั– ะท JSON { #convert-any-data-to-json-compatible } + +ะฉะพะฑ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ะฑัƒะดัŒ-ัะบั– ะดะฐะฝั– ะฝะฐ ััƒะผั–ัะฝั– ะท JSON, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะšะพะดัƒะฒะฐะปัŒะฝะธะบ, ััƒะผั–ัะฝะธะน ะท JSON](../tutorial/encoder.md){.internal-link target=_blank}. + +## ะœะตั‚ะฐะดะฐะฝั– OpenAPI - ะ”ะพะบัƒะผะตะฝั‚ะฐั†ั–ั { #openapi-metadata-docs } + +ะฉะพะฑ ะดะพะดะฐั‚ะธ ะผะตั‚ะฐะดะฐะฝั– ะดะพ ะฒะฐัˆะพั— ัั…ะตะผะธ OpenAPI, ะทะพะบั€ะตะผะฐ ะปั–ั†ะตะฝะทั–ัŽ, ะฒะตั€ัั–ัŽ, ะบะพะฝั‚ะฐะบั‚ะฝั– ะดะฐะฝั– ั‚ะพั‰ะพ, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะœะตั‚ะฐะดะฐะฝั– ั‚ะฐ URL ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—](../tutorial/metadata.md){.internal-link target=_blank}. + +## ะ’ะปะฐัะฝะธะน URL OpenAPI { #openapi-custom-url } + +ะฉะพะฑ ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ URL OpenAPI (ะฐะฑะพ ะฟั€ะธะฑั€ะฐั‚ะธ ะนะพะณะพ), ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะœะตั‚ะฐะดะฐะฝั– ั‚ะฐ URL ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. + +## URL ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— OpenAPI { #openapi-docs-urls } + +ะฉะพะฑ ะพะฝะพะฒะธั‚ะธ URL, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะธั… ั–ะฝั‚ะตั€ั„ะตะนัั–ะฒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะœะตั‚ะฐะดะฐะฝั– ั‚ะฐ URL ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. diff --git a/docs/uk/docs/how-to/graphql.md b/docs/uk/docs/how-to/graphql.md new file mode 100644 index 0000000000..2d0e355ea4 --- /dev/null +++ b/docs/uk/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +ะžัะบั–ะปัŒะบะธ FastAPI ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ั– ASGI, ะดัƒะถะต ะฟั€ะพัั‚ะพ ั–ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบัƒ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ GraphQL, ััƒะผั–ัะฝัƒ ะท ASGI. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพั”ะดะฝัƒะฒะฐั‚ะธ ะทะฒะธั‡ะฐะนะฝั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* FastAPI ะท GraphQL ะฒ ะพะดะฝะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +GraphQL ั€ะพะทะฒโ€™ัะทัƒั” ะดะตัะบั– ะดัƒะถะต ัะฟะตั†ะธั„ั–ั‡ะฝั– ัั†ะตะฝะฐั€ั–ั— ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั. + +ะŸะพั€ั–ะฒะฝัะฝะพ ะทั– ะทะฒะธั‡ะฐะนะฝะธะผะธ ะฒะตะฑ-API ะฒั–ะฝ ะผะฐั” ะฟะตั€ะตะฒะฐะณะธ ั‚ะฐ ะฝะตะดะพะปั–ะบะธ. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฟะตั€ะตะฒะฐะณะธ ะดะปั ะฒะฐัˆะพะณะพ ะฒะธะฟะฐะดะบัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟะตั€ะตะฒะฐะถะฐัŽั‚ัŒ ะฝะตะดะพะปั–ะบะธ. ๐Ÿค“ + +/// + +## ะ‘ั–ะฑะปั–ะพั‚ะตะบะธ GraphQL { #graphql-libraries } + +ะžััŒ ะดะตัะบั– ะฑั–ะฑะปั–ะพั‚ะตะบะธ GraphQL ะท ะฟั–ะดั‚ั€ะธะผะบะพัŽ ASGI. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ั–ะท FastAPI: + +* Strawberry ๐Ÿ“ + * ะ— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ ะดะปั FastAPI +* Ariadne + * ะ— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ ะดะปั FastAPI +* Tartiflette + * ะ— Tartiflette ASGI ะดะปั ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะท ASGI +* Graphene + * ะ— starlette-graphene3 + +## GraphQL ะทั– Strawberry { #graphql-with-strawberry } + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะตะฝ ะฐะฑะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ GraphQL, Strawberry - ั€ะตะบะพะผะตะฝะดะพะฒะฐะฝะฐ ะฑั–ะฑะปั–ะพั‚ะตะบะฐ, ะฐะดะถะต ั—ั— ะดะธะทะฐะนะฝ ะฝะฐะนะฑะปะธะถั‡ะธะน ะดะพ ะดะธะทะฐะนะฝัƒ FastAPI; ัƒัะต ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ะฐะฝะพั‚ะฐั†ั–ัั… ั‚ะธะฟั–ะฒ. + +ะ—ะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะพะณะพ ัั†ะตะฝะฐั€ั–ัŽ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะดะฐั‚ะธ ะฟะตั€ะตะฒะฐะณัƒ ั–ะฝัˆั–ะน ะฑั–ะฑะปั–ะพั‚ะตั†ั–, ะฐะปะต ัะบะฑะธ ะฒะธ ะทะฐะฟะธั‚ะฐะปะธ ะผะตะฝะต, ั, ะนะผะพะฒั–ั€ะฝะพ, ะฟะพั€ะฐะดะธะฒ ะฑะธ ัะฟั€ะพะฑัƒะฒะฐั‚ะธ Strawberry. + +ะžััŒ ะฝะตะฒะตะปะธะบะธะน ะฟั€ะธะบะปะฐะด ั‚ะพะณะพ, ัะบ ั–ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ Strawberry ะท FastAPI: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +ะ‘ั–ะปัŒัˆะต ะฟั€ะพ Strawberry ะฒะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— Strawberry. + +ะ† ั‚ะฐะบะพะถ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะฟั€ะพ Strawberry ะท FastAPI. + +## ะ—ะฐัั‚ะฐั€ั–ะปะธะน `GraphQLApp` ะทั– Starlette { #older-graphqlapp-from-starlette } + +ะŸะพะฟะตั€ะตะดะฝั– ะฒะตั€ัั–ั— Starlette ะผั–ัั‚ะธะปะธ ะบะปะฐั `GraphQLApp` ะดะปั ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะท Graphene. + +ะ™ะพะณะพ ะฒะธะปัƒั‡ะตะฝะพ ะท Starlette ัะบ ะทะฐัั‚ะฐั€ั–ะปะธะน, ะฐะปะต ัะบั‰ะพ ัƒ ะฒะฐั ั” ะบะพะด, ั‰ะพ ะนะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะฒ, ะฒะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะผั–ะณั€ัƒะฒะฐั‚ะธ ะฝะฐ starlette-graphene3, ัะบะธะน ะฟะพะบั€ะธะฒะฐั” ั‚ะพะน ัะฐะผะธะน ัั†ะตะฝะฐั€ั–ะน ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ะฐ ะผะฐั” ะผะฐะนะถะต ั–ะดะตะฝั‚ะธั‡ะฝะธะน ั–ะฝั‚ะตั€ั„ะตะนั. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะตะฝ GraphQL, ั ะฒัะต ะถ ั€ะตะบะพะผะตะฝะดัƒัŽ ะทะฒะตั€ะฝัƒั‚ะธ ัƒะฒะฐะณัƒ ะฝะฐ Strawberry, ะฐะดะถะต ะฒั–ะฝ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ะฐะฝะพั‚ะฐั†ั–ัั… ั‚ะธะฟั–ะฒ, ะฐ ะฝะต ะฝะฐ ะฒะปะฐัะฝะธั… ะบะปะฐัะฐั… ั– ั‚ะธะฟะฐั…. + +/// + +## ะ”ั–ะทะฝะฐะนั‚ะตัั ะฑั–ะปัŒัˆะต { #learn-more } + +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ GraphQL ะฒ ะพั„ั–ั†ั–ะนะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— GraphQL. + +ะขะฐะบะพะถ ะฒะธ ะผะพะถะตั‚ะต ะฟะพั‡ะธั‚ะฐั‚ะธ ะฑั–ะปัŒัˆะต ะฟั€ะพ ะบะพะถะฝัƒ ะท ั†ะธั… ะฑั–ะฑะปั–ะพั‚ะตะบ ะทะฐ ะฝะฐะฒะตะดะตะฝะธะผะธ ะฟะพัะธะปะฐะฝะฝัะผะธ. diff --git a/docs/uk/docs/how-to/index.md b/docs/uk/docs/how-to/index.md new file mode 100644 index 0000000000..ac2dd16eb9 --- /dev/null +++ b/docs/uk/docs/how-to/index.md @@ -0,0 +1,13 @@ +# ะฏะบ ะทั€ะพะฑะธั‚ะธ - ะ ะตั†ะตะฟั‚ะธ { #how-to-recipes } + +ะขัƒั‚ ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ั€ั–ะทะฝั– ั€ะตั†ะตะฟั‚ะธ ะฐะฑะพ ะบะตั€ั–ะฒะฝะธั†ั‚ะฒะฐ ยซัะบ ะทั€ะพะฑะธั‚ะธยป ะท **ั€ั–ะทะฝะธั… ั‚ะตะผ**. + +ะ‘ั–ะปัŒัˆั–ัั‚ัŒ ั–ะท ั†ะธั… ั–ะดะตะน ั” ะฑั–ะปัŒัˆ-ะผะตะฝัˆ **ะฝะตะทะฐะปะตะถะฝะธะผะธ**, ั– ะฒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะฐะผ ัะปั–ะด ะฒะธะฒั‡ะฐั‚ะธ ั—ั… ะปะธัˆะต ั‚ะพะดั–, ะบะพะปะธ ะฒะพะฝะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัั‚ะพััƒัŽั‚ัŒัั **ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ**. + +ะฏะบั‰ะพ ั‰ะพััŒ ะทะดะฐั”ั‚ัŒัั ั†ั–ะบะฐะฒะธะผ ั– ะบะพั€ะธัะฝะธะผ ะดะปั ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ, ัะผั–ะปะธะฒะพ ะฟะตั€ะตะฒั–ั€ั‚ะต ั†ะต, ั–ะฝะฐะบัˆะต, ะนะผะพะฒั–ั€ะฝะพ, ะฟั€ะพัั‚ะพ ะฟั€ะพะฟัƒัั‚ั–ั‚ัŒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต **ะฒะธะฒั‡ะธั‚ะธ FastAPI** ัƒ ัั‚ั€ัƒะบั‚ัƒั€ะพะฒะฐะฝะธะน ัะฟะพัั–ะฑ (ั€ะตะบะพะผะตะฝะดัƒั”ั‚ัŒัั), ะฝะฐั‚ะพะผั–ัั‚ัŒ ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต [ะะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ - ะŸะพัั–ะฑะฝะธะบ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ](../tutorial/index.md){.internal-link target=_blank} ั€ะพะทะดั–ะป ะทะฐ ั€ะพะทะดั–ะปะพะผ. + +/// diff --git a/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000..0f5d1c924e --- /dev/null +++ b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,135 @@ +# ะŸะตั€ะตั…ั–ะด ะท Pydantic v1 ะฝะฐ Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ัั‚ะฐั€ะฐ ะฟั€ะพะณั€ะฐะผะฐ FastAPI, ะผะพะถะปะธะฒะพ, ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Pydantic ะฒะตั€ัั–ั— 1. + +FastAPI ะฒะตั€ัั–ั— 0.100.0 ะฟั–ะดั‚ั€ะธะผัƒะฒะฐะฒ ัะบ Pydantic v1, ั‚ะฐะบ ั– v2. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะฐัั ั‚ะฐ ะฒะตั€ัั–ั, ัะบัƒ ะฒะธ ะฒัั‚ะฐะฝะพะฒะธะปะธ. + +FastAPI ะฒะตั€ัั–ั— 0.119.0 ะทะฐะฟั€ะพะฒะฐะดะธะฒ ั‡ะฐัั‚ะบะพะฒัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ Pydantic v1 ะฒัะตั€ะตะดะธะฝั– Pydantic v2 (ัะบ `pydantic.v1`), ั‰ะพะฑ ัะฟั€ะพัั‚ะธั‚ะธ ะฟะตั€ะตั…ั–ะด ะฝะฐ v2. + +FastAPI 0.126.0 ะฟั€ะธะฟะธะฝะธะฒ ะฟั–ะดั‚ั€ะธะผะบัƒ Pydantic v1, ะฒะพะดะฝะพั‡ะฐั ั‰ะต ะฟะตะฒะฝะธะน ั‡ะฐั ะฟั–ะดั‚ั€ะธะผัƒะฒะฐะฒ `pydantic.v1`. + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะšะพะผะฐะฝะดะฐ Pydantic ะฟั€ะธะฟะธะฝะธะปะฐ ะฟั–ะดั‚ั€ะธะผะบัƒ Pydantic v1 ะดะปั ะพัั‚ะฐะฝะฝั–ั… ะฒะตั€ัั–ะน Python, ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท Python 3.14. + +ะฆะต ัั‚ะพััƒั”ั‚ัŒัั ั– `pydantic.v1`, ัะบะธะน ะฑั–ะปัŒัˆะต ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ะฒ Python 3.14 ั– ะฝะพะฒั–ัˆะธั…. + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฝะฐะนะฝะพะฒั–ัˆั– ะผะพะถะปะธะฒะพัั‚ั– Python, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Pydantic v2. + +/// + +ะฏะบั‰ะพ ัƒ ะฒะฐั ัั‚ะฐั€ะฐ ะฟั€ะพะณั€ะฐะผะฐ FastAPI ะท Pydantic v1, ะฝะธะถั‡ะต ั ะฟะพะบะฐะถัƒ, ัะบ ะผั–ะณั€ัƒะฒะฐั‚ะธ ะฝะฐ Pydantic v2, ะฐ ั‚ะฐะบะพะถ ะผะพะถะปะธะฒะพัั‚ั– FastAPI 0.119.0, ัะบั– ะดะพะฟะพะผะพะถัƒั‚ัŒ ะท ะฟะพัั‚ัƒะฟะพะฒะพัŽ ะผั–ะณั€ะฐั†ั–ั”ัŽ. + +## ะžั„ั–ั†ั–ะนะฝะธะน ะฟะพัั–ะฑะฝะธะบ { #official-guide } + +ะฃ Pydantic ั” ะพั„ั–ั†ั–ะนะฝะธะน ะŸะพัั–ะฑะฝะธะบ ะท ะผั–ะณั€ะฐั†ั–ั— ะท v1 ะฝะฐ v2. + +ะขะฐะผ ะพะฟะธัะฐะฝะพ, ั‰ะพ ะทะผั–ะฝะธะปะพัั, ัะบ ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะตะฟะตั€ ัั‚ะฐะปะธ ะบะพั€ะตะบั‚ะฝั–ัˆะธะผะธ ั‚ะฐ ััƒะฒะพั€ั–ัˆะธะผะธ, ะผะพะถะปะธะฒั– ะทะฐัั‚ะตั€ะตะถะตะฝะฝั ั‚ะพั‰ะพ. + +ะŸั€ะพั‡ะธั‚ะฐะนั‚ะต ะนะพะณะพ, ั‰ะพะฑ ะบั€ะฐั‰ะต ะทั€ะพะทัƒะผั–ั‚ะธ ะทะผั–ะฝะธ. + +## ะขะตัั‚ะธ { #tests } + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ัƒ ะฒะฐัˆั–ะน ะฟั€ะพะณั€ะฐะผั– ั” [ั‚ะตัั‚ะธ](../tutorial/testing.md){.internal-link target=_blank} ั– ั‰ะพ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต ั—ั… ัƒ ัะธัั‚ะตะผั– ะฑะตะทะฟะตั€ะตั€ะฒะฝะพั— ั–ะฝั‚ะตะณั€ะฐั†ั–ั— (CI). + +ะขะฐะบ ะฒะธ ะทะผะพะถะตั‚ะต ะฒะธะบะพะฝะฐั‚ะธ ะพะฝะพะฒะปะตะฝะฝั ั– ะฒะฟะตะฒะฝะธั‚ะธัั, ั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั” ัะบ ะพั‡ั–ะบัƒั”ั‚ัŒัั. + +## `bump-pydantic` { #bump-pydantic } + +ะฃ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั…, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะทะฒะธั‡ะฐะนะฝั– ะผะพะดะตะปั– Pydantic ะฑะตะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝัŒ, ะฑั–ะปัŒัˆัƒ ั‡ะฐัั‚ะธะฝัƒ ะฟั€ะพั†ะตััƒ ะผั–ะณั€ะฐั†ั–ั— ะท Pydantic v1 ะฝะฐ Pydantic v2 ะผะพะถะฝะฐ ะฐะฒั‚ะพะผะฐั‚ะธะทัƒะฒะฐั‚ะธ. + +ะ’ะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั `bump-pydantic` ะฒั–ะด ั‚ั–ั”ั— ะถ ะบะพะผะฐะฝะดะธ Pydantic. + +ะฆะตะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะพะฟะพะผะพะถะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะผั–ะฝะธั‚ะธ ะฑั–ะปัŒัˆั–ัั‚ัŒ ะบะพะดัƒ, ัะบะธะน ะฟะพั‚ั€ั–ะฑะฝะพ ะทะผั–ะฝะธั‚ะธ. + +ะŸั–ัะปั ั†ัŒะพะณะพ ะทะฐะฟัƒัั‚ั–ั‚ัŒ ั‚ะตัั‚ะธ ะน ะฟะตั€ะตะฒั–ั€ั‚ะต, ั‡ะธ ะฒัะต ะฟั€ะฐั†ัŽั”. ะฏะบั‰ะพ ั‚ะฐะบ - ะฒะธ ะฒัะต ะทะฐะฒะตั€ัˆะธะปะธ. ๐Ÿ˜Ž + +## Pydantic v1 ัƒ v2 { #pydantic-v1-in-v2 } + +Pydantic v2 ะผั–ัั‚ะธั‚ัŒ ัƒัะต ะท Pydantic v1 ัะบ ะฟั–ะดะผะพะดัƒะปัŒ `pydantic.v1`. ะะปะต ั†ะต ะฑั–ะปัŒัˆะต ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ัƒ ะฒะตั€ัั–ัั… Python ะฒะธั‰ะต 3.13. + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะพัั‚ะฐะฝะฝัŽ ะฒะตั€ัั–ัŽ Pydantic v2 ั‚ะฐ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัั‚ะฐั€ั– ะบะพะผะฟะพะฝะตะฝั‚ะธ Pydantic v1 ะท ั†ัŒะพะณะพ ะฟั–ะดะผะพะดัƒะปั, ะฝั–ะฑะธ ัƒ ะฒะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ัั‚ะฐั€ะธะน Pydantic v1. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### ะŸั–ะดั‚ั€ะธะผะบะฐ FastAPI ะดะปั Pydantic v1 ัƒ v2 { #fastapi-support-for-pydantic-v1-in-v2 } + +ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะท FastAPI 0.119.0, ั‚ะฐะบะพะถ ั” ั‡ะฐัั‚ะบะพะฒะฐ ะฟั–ะดั‚ั€ะธะผะบะฐ Pydantic v1 ะฒัะตั€ะตะดะธะฝั– Pydantic v2, ั‰ะพะฑ ัะฟั€ะพัั‚ะธั‚ะธ ะฟะตั€ะตั…ั–ะด ะฝะฐ v2. + +ะขะพะถ ะฒะธ ะผะพะถะตั‚ะต ะพะฝะพะฒะธั‚ะธ Pydantic ะดะพ ะพัั‚ะฐะฝะฝัŒะพั— ะฒะตั€ัั–ั— 2 ั– ะทะผั–ะฝะธั‚ะธ ั–ะผะฟะพั€ั‚ะธ ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฟั–ะดะผะพะดัƒะปั `pydantic.v1`, ั– ะฒ ะฑะฐะณะฐั‚ัŒะพั… ะฒะธะฟะฐะดะบะฐั… ัƒัะต ะฟั€ะพัั‚ะพ ะทะฐะฟั€ะฐั†ัŽั”. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะพัะบั–ะปัŒะบะธ ะบะพะผะฐะฝะดะฐ Pydantic ะฑั–ะปัŒัˆะต ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” Pydantic v1 ัƒ ะฝะพะฒะธั… ะฒะตั€ัั–ัั… Python, ะฟะพั‡ะธะฝะฐัŽั‡ะธ ะท Python 3.14, ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั `pydantic.v1` ั‚ะฐะบะพะถ ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั”ั‚ัŒัั ะฒ Python 3.14 ั– ะฝะพะฒั–ัˆะธั…. + +/// + +### Pydantic v1 ั– v2 ะฒ ะพะดะฝั–ะน ะฟั€ะพะณั€ะฐะผั– { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic ะฝะต ะฟั–ะดั‚ั€ะธะผัƒั” ัะธั‚ัƒะฐั†ั–ัŽ, ะบะพะปะธ ะผะพะดะตะปัŒ Pydantic v2 ะผะฐั” ะฒะปะฐัะฝั– ะฟะพะปั, ะฒะธะทะฝะฐั‡ะตะฝั– ัะบ ะผะพะดะตะปั– Pydantic v1, ะฐะฑะพ ะฝะฐะฒะฟะฐะบะธ. + +```mermaid +graph TB + subgraph "โŒ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...ะฐะปะต ะฒ ะพะดะฝั–ะน ะฟั€ะพะณั€ะฐะผั– ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะพะบั€ะตะผั– ะผะพะดะตะปั– ะฝะฐ Pydantic v1 ั– v2. + +```mermaid +graph TB + subgraph "โœ… Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +ะฃ ะดะตัะบะธั… ะฒะธะฟะฐะดะบะฐั… ะผะพะถะฝะฐ ะฝะฐะฒั–ั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะผะพะดะตะปั– ั– Pydantic v1, ั– v2 ะฒ ะพะดะฝั–ะน ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ัƒ ะฒะฐัˆั–ะน ะฟั€ะพะณั€ะฐะผั– FastAPI: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ะฃ ะฝะฐะฒะตะดะตะฝะพะผัƒ ะฒะธั‰ะต ะฟั€ะธะบะปะฐะดั– ะฒั…ั–ะดะฝะฐ ะผะพะดะตะปัŒ - ั†ะต ะผะพะดะตะปัŒ Pydantic v1, ะฐ ะฒะธั…ั–ะดะฝะฐ ะผะพะดะตะปัŒ (ะฒะธะทะฝะฐั‡ะตะฝะฐ ัะบ `response_model=ItemV2`) - ะผะพะดะตะปัŒ Pydantic v2. + +### ะŸะฐั€ะฐะผะตั‚ั€ะธ Pydantic v1 { #pydantic-v1-parameters } + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะดะตัะบั– ัะฟะตั†ะธั„ั–ั‡ะฝั– ะดะปั FastAPI ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะดะปั ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ัะบ-ะพั‚ `Body`, `Query`, `Form` ั‚ะพั‰ะพ, ะท ะผะพะดะตะปัะผะธ Pydantic v1, ะฒะธ ะผะพะถะตั‚ะต ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั—ั… ะท `fastapi.temp_pydantic_v1_params`, ะฟะพะบะธ ะทะฐะฒะตั€ัˆัƒั”ั‚ะต ะผั–ะณั€ะฐั†ั–ัŽ ะฝะฐ Pydantic v2: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### ะŸะพะบั€ะพะบะพะฒะฐ ะผั–ะณั€ะฐั†ั–ั { #migrate-in-steps } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะกะฟะตั€ัˆัƒ ัะฟั€ะพะฑัƒะนั‚ะต `bump-pydantic`: ัะบั‰ะพ ะฒะฐัˆั– ั‚ะตัั‚ะธ ะฟั€ะพั…ะพะดัั‚ัŒ ั– ะฒัะต ะฟั€ะฐั†ัŽั” - ะฒะธ ะฒะฟะพั€ะฐะปะธัั ะพะดะฝั–ั”ัŽ ะบะพะผะฐะฝะดะพัŽ. โœจ + +/// + +ะฏะบั‰ะพ `bump-pydantic` ะฝะต ะฟั–ะดั…ะพะดะธั‚ัŒ ะดะปั ะฒะฐัˆะพะณะพ ะฒะธะฟะฐะดะบัƒ, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ะฟั–ะดั‚ั€ะธะผะบะพัŽ ะพะดะฝะพั‡ะฐัะฝะพ Pydantic v1 ั– v2 ะฒ ะพะดะฝั–ะน ะฟั€ะพะณั€ะฐะผั–, ั‰ะพะฑ ะฒะธะบะพะฝะฐั‚ะธ ะฟะพัั‚ัƒะฟะพะฒัƒ ะผั–ะณั€ะฐั†ั–ัŽ ะฝะฐ Pydantic v2. + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฒะธ ะผะพะถะตั‚ะต ะพะฝะพะฒะธั‚ะธ Pydantic ะดะพ ะพัั‚ะฐะฝะฝัŒะพั— ะฒะตั€ัั–ั— 2 ั– ะทะผั–ะฝะธั‚ะธ ั–ะผะฟะพั€ั‚ะธ ะฝะฐ `pydantic.v1` ะดะปั ะฒัั–ั… ะฒะฐัˆะธั… ะผะพะดะตะปะตะน. + +ะŸะพั‚ั–ะผ ะฟะพั‡ะธะฝะฐะนั‚ะต ะฟะตั€ะตะฝะพัะธั‚ะธ ะผะพะดะตะปั– ะท Pydantic v1 ะฝะฐ v2 ะณั€ัƒะฟะฐะผะธ, ะฟะพัั‚ัƒะฟะพะฒะธะผะธ ะบั€ะพะบะฐะผะธ. ๐Ÿšถ diff --git a/docs/uk/docs/how-to/separate-openapi-schemas.md b/docs/uk/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000..7e6fcbf5f9 --- /dev/null +++ b/docs/uk/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,101 @@ +# ะžะบั€ะตะผั– ัั…ะตะผะธ OpenAPI ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั, ั‡ะธ ะฝั– { #separate-openapi-schemas-for-input-and-output-or-not } + +ะ’ั–ะดะบะพะปะธ ะฒะธะนัˆะพะฒ **Pydantic v2**, ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน OpenAPI ัั‚ะฐะฒ ั‚ั€ะพั…ะธ ั‚ะพั‡ะฝั–ัˆะธะผ ั– ะฑั–ะปัŒัˆ ะบะพั€ะตะบั‚ะฝะธะผ, ะฝั–ะถ ั€ะฐะฝั–ัˆะต. ๐Ÿ˜Ž + +ะะฐัะฟั€ะฐะฒะดั– ะฟะพะดะตะบัƒะดะธ ะฑัƒะดะต ะฝะฐะฒั–ั‚ัŒ **ะดะฒั– ัั…ะตะผะธ JSON** ะฒ OpenAPI ะดะปั ั‚ั–ั”ั— ัะฐะผะพั— ะผะพะดะตะปั– Pydantic: ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะดะปั ะฒะธะฒะตะดะตะฝะฝั - ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฝะฐัะฒะฝะพัั‚ั– ะทะฝะฐั‡ะตะฝัŒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. + +ะ ะพะทะณะปัะฝัŒะผะพ, ัะบ ั†ะต ะฟั€ะฐั†ัŽั”, ั– ัะบ ั†ะต ะทะผั–ะฝะธั‚ะธ ะทะฐ ะฟะพั‚ั€ะตะฑะธ. + +## ะœะพะดะตะปั– Pydantic ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั { #pydantic-models-for-input-and-output } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ัƒ ะฒะฐั ั” ะผะพะดะตะปัŒ Pydantic ะทั– ะทะฝะฐั‡ะตะฝะฝัะผะธ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ะฝะฐะฟั€ะธะบะปะฐะด: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### ะœะพะดะตะปัŒ ะดะปั ะฒะฒะตะดะตะฝะฝั { #model-for-input } + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั†ัŽ ะผะพะดะตะปัŒ ัะบ ะฒะฒะตะดะตะฝะฝั, ัะบ ั‚ัƒั‚: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +โ€ฆั‚ะพะดั– ะฟะพะปะต `description` ะฝะต ะฑัƒะดะต ะพะฑะพะฒ'ัะทะบะพะฒะธะผ, ะฐะดะถะต ะฒะพะฝะพ ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `None`. + +### ะœะพะดะตะปัŒ ะดะปั ะฒะฒะตะดะตะฝะฝั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #input-model-in-docs } + +ะฃ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ ะฟะพะปะต `description` ะฝะต ะผะฐั” **ั‡ะตั€ะฒะพะฝะพั— ะทั–ั€ะพั‡ะบะธ** - ะฒะพะฝะพ ะฝะต ะฟะพะทะฝะฐั‡ะตะฝะต ัะบ ะพะฑะพะฒ'ัะทะบะพะฒะต: + +
+ +
+ +### ะœะพะดะตะปัŒ ะดะปั ะฒะธะฒะตะดะตะฝะฝั { #model-for-output } + +ะะปะต ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั†ัŽ ัะฐะผัƒ ะผะพะดะตะปัŒ ะดะปั ะฒะธะฒะตะดะตะฝะฝั, ัะบ ั‚ัƒั‚: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +โ€ฆั‚ะพะดั–, ะพัะบั–ะปัŒะบะธ `description` ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ, ัะบั‰ะพ ะฒะธ ะฝั–ั‡ะพะณะพ ะฝะต ะฟะพะฒะตั€ะฝะตั‚ะต ะดะปั ั†ัŒะพะณะพ ะฟะพะปั, ะฒะพะฝะพ ะฒัะต ะพะดะฝะพ ะผะฐั‚ะธะผะต ั†ะต **ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ**. + +### ะœะพะดะตะปัŒ ะดะปั ะดะฐะฝะธั… ะฒั–ะดะฟะพะฒั–ะดั– ะฟั€ะธ ะฒะธะฒะตะดะตะฝะฝั– { #model-for-output-response-data } + +ะฏะบั‰ะพ ะฒะธ ัะบะพั€ะธัั‚ะฐั”ั‚ะตัั ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ ั‚ะฐ ะฟะตั€ะตะฒั–ั€ะธั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ, ะฝะฐะฒั–ั‚ัŒ ะฟะพะฟั€ะธ ั‚ะต, ั‰ะพ ะบะพะด ะฝั–ั‡ะพะณะพ ะฝะต ะดะพะดะฐะฒ ะฒ ะพะดะฝะต ะท ะฟะพะปั–ะฒ `description`, JSON-ะฒั–ะดะฟะพะฒั–ะดัŒ ะผั–ัั‚ะธั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ (`null`): + +
+ +
+ +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒะพะฝะพ **ะทะฐะฒะถะดะธ ะผะฐั‚ะธะผะต ะทะฝะฐั‡ะตะฝะฝั** - ะฟั€ะพัั‚ะพ ั–ะฝะพะดั– ั†ะต ะทะฝะฐั‡ะตะฝะฝั ะผะพะถะต ะฑัƒั‚ะธ `None` (ะฐะฑะพ `null` ัƒ JSON). + +ะžั‚ะถะต, ะบะปั–ั”ะฝั‚ะฐะผ, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฒะฐัˆ API, ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะฒั–ั€ัั‚ะธ, ั‡ะธ ั–ัะฝัƒั” ะทะฝะฐั‡ะตะฝะฝั - ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ **ะฟั€ะธะฟัƒัั‚ะธั‚ะธ, ั‰ะพ ะฟะพะปะต ะทะฐะฒะถะดะธ ะฑัƒะดะต ะฟั€ะธััƒั‚ะฝั”**, ะฐะปะต ะฒ ะพะบั€ะตะผะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะพะฝะพ ะผะฐั‚ะธะผะต ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `None`. + +ะฃ OpenAPI ั†ะต ะพะฟะธััƒั”ั‚ัŒัั ั‚ะธะผ, ั‰ะพ ะฟะพะปะต ะฟะพะทะฝะฐั‡ะฐั”ั‚ัŒัั ัะบ **ะพะฑะพะฒ'ัะทะบะพะฒะต**, ะฐะดะถะต ะฒะพะฝะพ ะทะฐะฒะถะดะธ ะฟั€ะธััƒั‚ะฝั”. + +ะขะพะผัƒ ะกั…ะตะผะฐ JSON ะดะปั ะผะพะดะตะปั– ะผะพะถะต ะฒั–ะดั€ั–ะทะฝัั‚ะธัั ะทะฐะปะตะถะฝะพ ะฒั–ะด ั‚ะพะณะพ, ั‡ะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒะพะฝะฐ ะดะปั **ะฒะฒะตะดะตะฝะฝั ะฐะฑะพ ะฒะธะฒะตะดะตะฝะฝั**: +- ะดะปั **ะฒะฒะตะดะตะฝะฝั** `description` ะฝะต ะฑัƒะดะต ะพะฑะพะฒ'ัะทะบะพะฒะธะผ +- ะดะปั **ะฒะธะฒะตะดะตะฝะฝั** ะฒะพะฝะพ ะฑัƒะดะต **ะพะฑะพะฒ'ัะทะบะพะฒะธะผ** (ั– ะผะพะถะปะธะฒะพ `None`, ะฐะฑะพ ะฒ ั‚ะตั€ะผั–ะฝะฐั… JSON - `null`) + +### ะœะพะดะตะปัŒ ะดะปั ะฒะธะฒะตะดะตะฝะฝั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #model-for-output-in-docs } + +ะฃ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ะผะพะดะตะปัŒ ะดะปั ะฒะธะฒะตะดะตะฝะฝั: **ั–** `name`, ั– `description` ะฟะพะทะฝะฐั‡ะตะฝั– ัะบ **ะพะฑะพะฒ'ัะทะบะพะฒั–** ั‡ะตั€ะฒะพะฝะพัŽ ะทั–ั€ะพั‡ะบะพัŽ: + +
+ +
+ +### ะœะพะดะตะปัŒ ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #model-for-input-and-output-in-docs } + +ะฏะบั‰ะพ ะฒั–ะดะบั€ะธั‚ะธ ะฒัั– ะฝะฐัะฒะฝั– ะกั…ะตะผะธ (ัั…ะตะผะธ JSON) ะฒ OpenAPI, ั‚ะพ ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ะดะฒั–: `Item-Input` ั– `Item-Output`. + +ะ”ะปั `Item-Input` ะฟะพะปะต `description` **ะฝะต ั” ะพะฑะพะฒ'ัะทะบะพะฒะธะผ** - ั‡ะตั€ะฒะพะฝะพั— ะทั–ั€ะพั‡ะบะธ ะฝะตะผะฐั”. + +ะ ะดะปั `Item-Output` `description` **ั” ะพะฑะพะฒ'ัะทะบะพะฒะธะผ** - ั” ั‡ะตั€ะฒะพะฝะฐ ะทั–ั€ะพั‡ะบะฐ. + +
+ +
+ +ะ—ะฐะฒะดัะบะธ ั†ั–ะน ะผะพะถะปะธะฒะพัั‚ั– ัƒ **Pydantic v2** ะฒะฐัˆะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั API ัั‚ะฐั” ะฑั–ะปัŒัˆ **ั‚ะพั‡ะฝะพัŽ**, ะฐ ัะบั‰ะพ ัƒ ะฒะฐั ั” ะทะณะตะฝะตั€ะพะฒะฐะฝั– ะบะปั–ั”ะฝั‚ะธ ั‚ะฐ SDK, ะฒะพะฝะธ ั‚ะฐะบะพะถ ะฑัƒะดัƒั‚ัŒ ั‚ะพั‡ะฝั–ัˆะธะผะธ - ะท ะบั€ะฐั‰ะธะผ **ะดะพัะฒั–ะดะพะผ ั€ะพะทั€ะพะฑะฝะธะบะฐ** ั‚ะฐ ัƒะทะณะพะดะถะตะฝั–ัั‚ัŽ. ๐ŸŽ‰ + +## ะะต ั€ะพะทะดั–ะปัั‚ะธ ัั…ะตะผะธ { #do-not-separate-schemas } + +ะ’ั‚ั–ะผ ั–ะฝะพะดั– ะผะพะถะต ะทะฝะฐะดะพะฑะธั‚ะธัั ะผะฐั‚ะธ **ะพะดะฝัƒ ะน ั‚ัƒ ัะฐะผัƒ ัั…ะตะผัƒ ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั**. + +ะžัะฝะพะฒะฝะธะน ะฒะธะฟะฐะดะพะบ - ะบะพะปะธ ัƒ ะฒะฐั ะฒะถะต ั” ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ะบะปั–ั”ะฝั‚ััŒะบะธะน ะบะพะด/SDK, ั– ะฒะธ ะฟะพะบะธ ะฝะต ะฑะฐะถะฐั”ั‚ะต ะพะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒะตััŒ ั‚ะฐะบะธะน ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ะบะพะด/SDK. ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะทั€ะพะฑะธั‚ะต ั†ะต ะฟั–ะทะฝั–ัˆะต, ะฐะปะต ะฝะต ะทะฐั€ะฐะท. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะธ ะผะพะถะตั‚ะต ะฒะธะผะบะฝัƒั‚ะธ ั†ัŽ ะผะพะถะปะธะฒั–ัั‚ัŒ ัƒ **FastAPI** ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `separate_input_output_schemas=False`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸั–ะดั‚ั€ะธะผะบัƒ `separate_input_output_schemas` ะดะพะดะฐะฝะพ ัƒ FastAPI `0.102.0`. ๐Ÿค“ + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### ะžะดะฝะฐ ัั…ะตะผะฐ ะดะปั ะผะพะดะตะปะตะน ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #same-schema-for-input-and-output-models-in-docs } + +ะขะตะฟะตั€ ะดะปั ั†ั–ั”ั— ะผะพะดะตะปั– ะฑัƒะดะต ะปะธัˆะต ะพะดะฝะฐ ัะฟั–ะปัŒะฝะฐ ัั…ะตะผะฐ ะดะปั ะฒะฒะตะดะตะฝะฝั ั‚ะฐ ะฒะธะฒะตะดะตะฝะฝั - ั‚ั–ะปัŒะบะธ `Item`, ั– ะฒ ะฝั–ะน `description` ะฑัƒะดะต **ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะธะผ**: + +
+ +
diff --git a/docs/uk/docs/how-to/testing-database.md b/docs/uk/docs/how-to/testing-database.md new file mode 100644 index 0000000000..2e6b21ced0 --- /dev/null +++ b/docs/uk/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# ะขะตัั‚ัƒะฒะฐะฝะฝั ะฑะฐะทะธ ะดะฐะฝะธั… { #testing-a-database } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะทะฝะฐะนะพะผะธั‚ะธัั ะท ะฑะฐะทะฐะผะธ ะดะฐะฝะธั…, SQL ั– SQLModel ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— SQLModel. ๐Ÿค“ + +ะ„ ะฝะตะฒะตะปะธะบะธะน ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะฟั€ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั SQLModel ะท FastAPI. โœจ + +ะฆะตะน ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะผั–ัั‚ะธั‚ัŒ ั€ะพะทะดั–ะป ะฟั€ะพ ั‚ะตัั‚ัƒะฒะฐะฝะฝั ะฑะฐะท ะดะฐะฝะธั… SQL. ๐Ÿ˜Ž diff --git a/docs/uk/docs/project-generation.md b/docs/uk/docs/project-generation.md new file mode 100644 index 0000000000..4899090d42 --- /dev/null +++ b/docs/uk/docs/project-generation.md @@ -0,0 +1,28 @@ +# ะจะฐะฑะปะพะฝ Full Stack FastAPI { #full-stack-fastapi-template } + +ะจะฐะฑะปะพะฝะธ, ั…ะพั‡ะฐ ะทะฐะทะฒะธั‡ะฐะน ะฟะพัั‚ะฐั‡ะฐัŽั‚ัŒัั ะท ะฟะตะฒะฝะธะผ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผ, ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝั– ะฑัƒั‚ะธ ะณะฝัƒั‡ะบะธะผะธ ั‚ะฐ ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐะฝะธะผะธ. ะฆะต ะดะฐั” ะทะผะพะณัƒ ะทะผั–ะฝัŽะฒะฐั‚ะธ ั—ั… ั– ะฐะดะฐะฟั‚ัƒะฒะฐั‚ะธ ะดะพ ะฒะธะผะพะณ ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ, ั‰ะพ ั€ะพะฑะธั‚ัŒ ั—ั… ั‡ัƒะดะพะฒะพัŽ ะฒั–ะดะฟั€ะฐะฒะฝะพัŽ ั‚ะพั‡ะบะพัŽ. ๐Ÿ + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะตะน ัˆะฐะฑะปะพะฝ ะดะปั ัั‚ะฐั€ั‚ัƒ, ะฐะดะถะต ะฒ ะฝัŒะพะผัƒ ะฒะถะต ะฒะธะบะพะฝะฐะฝะพ ะทะฝะฐั‡ะฝัƒ ั‡ะฐัั‚ะธะฝัƒ ะฟะพั‡ะฐั‚ะบะพะฒะพะณะพ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั, ะฑะตะทะฟะตะบะธ, ั€ะพะฑะพั‚ะธ ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั… ั– ะดะตัะบะธั… ะบั–ะฝั†ะตะฒะธั… ั‚ะพั‡ะพะบ API. + +ะ ะตะฟะพะทะธั‚ะพั€ั–ะน GitHub: ะจะฐะฑะปะพะฝ Full Stack FastAPI + +## ะจะฐะฑะปะพะฝ Full Stack FastAPI - ัั‚ะตะบ ั‚ะตั…ะฝะพะปะพะณั–ะน ั– ะผะพะถะปะธะฒะพัั‚ั– { #full-stack-fastapi-template-technology-stack-and-features } + +- โšก [**FastAPI**](https://fastapi.tiangolo.com/uk) ะดะปั ะฑะตะบะตะฝะด API ะฝะฐ Python. + - ๐Ÿงฐ [SQLModel](https://sqlmodel.tiangolo.com) ะดะปั ะฒะทะฐั”ะผะพะดั–ั— ะท SQL-ะฑะฐะทะพัŽ ะดะฐะฝะธั… ัƒ Python (ORM). + - ๐Ÿ” [Pydantic](https://docs.pydantic.dev), ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั FastAPI, ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ ะดะฐะฝะธั… ั– ะบะตั€ัƒะฒะฐะฝะฝั ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ. + - ๐Ÿ’พ [PostgreSQL](https://www.postgresql.org) ัะบ SQL-ะฑะฐะทะฐ ะดะฐะฝะธั…. +- ๐Ÿš€ [React](https://react.dev) ะดะปั ั„ั€ะพะฝั‚ะตะฝะดัƒ. + - ๐Ÿ’ƒ ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั TypeScript, ั…ัƒะบั–ะฒ, Vite ั‚ะฐ ั–ะฝัˆะธั… ั‡ะฐัั‚ะธะฝ ััƒั‡ะฐัะฝะพะณะพ ั„ั€ะพะฝั‚ะตะฝะด-ัั‚ะตะบัƒ. + - ๐ŸŽจ [Tailwind CSS](https://tailwindcss.com) ั– [shadcn/ui](https://ui.shadcn.com) ะดะปั ั„ั€ะพะฝั‚ะตะฝะด-ะบะพะผะฟะพะฝะตะฝั‚ั–ะฒ. + - ๐Ÿค– ะะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ั„ั€ะพะฝั‚ะตะฝะด-ะบะปั–ั”ะฝั‚. + - ๐Ÿงช [Playwright](https://playwright.dev) ะดะปั End-to-End ั‚ะตัั‚ัƒะฒะฐะฝะฝั. + - ๐Ÿฆ‡ ะŸั–ะดั‚ั€ะธะผะบะฐ ั‚ะตะผะฝะพะณะพ ั€ะตะถะธะผัƒ. +- ๐Ÿ‹ [Docker Compose](https://www.docker.com) ะดะปั ั€ะพะทั€ะพะฑะบะธ ั‚ะฐ ะฟั€ะพะดะฐะบัˆะตะฝัƒ. +- ๐Ÿ”’ ะ‘ะตะทะฟะตั‡ะฝะต ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. +- ๐Ÿ”‘ ะะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั JWT (JSON Web Token). +- ๐Ÿ“ซ ะ’ั–ะดะฝะพะฒะปะตะฝะฝั ะฟะฐั€ะพะปั ะฝะฐ ะพัะฝะพะฒั– ะตะปะตะบั‚ั€ะพะฝะฝะพั— ะฟะพัˆั‚ะธ. +- โœ… ะขะตัั‚ะธ ะท [Pytest](https://pytest.org). +- ๐Ÿ“ž [Traefik](https://traefik.io) ัะบ ะทะฒะพั€ะพั‚ะฝะธะน ะฟั€ะตะดัั‚ะฐะฒะฝะธะบ / ะฑะฐะปะฐะฝััƒะฒะฐะปัŒะฝะธะบ ะฝะฐะฒะฐะฝั‚ะฐะถะตะฝะฝั. +- ๐Ÿšข ะ†ะฝัั‚ั€ัƒะบั†ั–ั— ะท ั€ะพะทะณะพั€ั‚ะฐะฝะฝั ะท Docker Compose, ะฒะบะปัŽั‡ะฝะพ ะท ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผ ั„ั€ะพะฝั‚ะตะฝะด-ะฟั€ะตะดัั‚ะฐะฒะฝะธะบะฐ Traefik ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะธั… HTTPS-ัะตั€ั‚ะธั„ั–ะบะฐั‚ั–ะฒ. +- ๐Ÿญ CI (ะฑะตะทะฟะตั€ะตั€ะฒะฝะฐ ั–ะฝั‚ะตะณั€ะฐั†ั–ั) ั– CD (ะฑะตะทะฟะตั€ะตั€ะฒะฝะต ั€ะพะทะณะพั€ั‚ะฐะฝะฝั) ะฝะฐ ะฑะฐะทั– GitHub Actions. diff --git a/docs/uk/docs/resources/index.md b/docs/uk/docs/resources/index.md new file mode 100644 index 0000000000..353992fad4 --- /dev/null +++ b/docs/uk/docs/resources/index.md @@ -0,0 +1,3 @@ +# ะ ะตััƒั€ัะธ { #resources } + +ะ”ะพะดะฐั‚ะบะพะฒั– ั€ะตััƒั€ัะธ, ะทะพะฒะฝั–ัˆะฝั– ะฟะพัะธะปะฐะฝะฝั ั‚ะฐ ั–ะฝัˆะต. โœˆ๏ธ diff --git a/docs/uk/docs/translation-banner.md b/docs/uk/docs/translation-banner.md new file mode 100644 index 0000000000..8640803994 --- /dev/null +++ b/docs/uk/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ ะŸะตั€ะตะบะปะฐะด ะจะ† ั‚ะฐ ะปัŽะดัŒะผะธ + +ะฆะตะน ะฟะตั€ะตะบะปะฐะด ะฒะธะบะพะฝะฐะฝะพ ะจะ† ะฟั–ะด ะบะตั€ั–ะฒะฝะธั†ั‚ะฒะพะผ ะปัŽะดะตะน. ๐Ÿค + +ะœะพะถะปะธะฒั– ะฟะพะผะธะปะบะธ ั‡ะตั€ะตะท ะฝะตะฟั€ะฐะฒะธะปัŒะฝะต ั€ะพะทัƒะผั–ะฝะฝั ะฟะพั‡ะฐั‚ะบะพะฒะพะณะพ ะทะผั–ัั‚ัƒ ะฐะฑะพ ะฝะตะฟั€ะธั€ะพะดะฝั– ั„ะพั€ะผัƒะปัŽะฒะฐะฝะฝั ั‚ะพั‰ะพ. ๐Ÿค– + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะบั€ะฐั‰ะธั‚ะธ ั†ะตะน ะฟะตั€ะตะบะปะฐะด, [ะดะพะฟะพะผั–ะณัˆะธ ะฝะฐะผ ะบั€ะฐั‰ะต ัะฟั€ัะผะพะฒัƒะฒะฐั‚ะธ AI LLM](https://fastapi.tiangolo.com/uk/contributing/#translations). + +[ะะฝะณะปั–ะนััŒะบะฐ ะฒะตั€ัั–ั](ENGLISH_VERSION_URL) + +/// diff --git a/docs/uk/docs/tutorial/bigger-applications.md b/docs/uk/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000..a75da2ac6d --- /dev/null +++ b/docs/uk/docs/tutorial/bigger-applications.md @@ -0,0 +1,504 @@ +# ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ - ะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ { #bigger-applications-multiple-files } + +ะฏะบั‰ะพ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ ะฐะฑะพ ะฒะตะฑ-API, ั€ั–ะดะบะพ ะฒะดะฐั”ั‚ัŒัั ะฒะผั–ัั‚ะธั‚ะธ ะฒัะต ะฒ ะพะดะธะฝ ั„ะฐะนะป. + +**FastAPI** ะฝะฐะดะฐั” ะทั€ัƒั‡ะฝะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ัั‚ั€ัƒะบั‚ัƒั€ัƒะฒะฐะฝะฝั ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะทะฑะตั€ั–ะณะฐัŽั‡ะธ ะฒััŽ ะณะฝัƒั‡ะบั–ัั‚ัŒ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะฟั€ะธะนัˆะปะธ ะท Flask, ั†ะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ ยซBlueprintsยป ัƒ Flask. + +/// + +## ะŸั€ะธะบะปะฐะด ัั‚ั€ัƒะบั‚ัƒั€ะธ ั„ะฐะนะปั–ะฒ { #an-example-file-structure } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ัƒ ะฒะฐั ั‚ะฐะบะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ: + +``` +. +โ”œโ”€โ”€ app +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”œโ”€โ”€ main.py +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py +โ”‚ย ย  โ””โ”€โ”€ routers +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py +โ”‚ย ย  โ””โ”€โ”€ internal +โ”‚ย ย  โ”œโ”€โ”€ __init__.py +โ”‚ย ย  โ””โ”€โ”€ admin.py +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขัƒั‚ ะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ `__init__.py`: ะฟะพ ะพะดะฝะพะผัƒ ะฒ ะบะพะถะฝะพะผัƒ ะบะฐั‚ะฐะปะพะทั– ั‚ะฐ ะฟั–ะดะบะฐั‚ะฐะปะพะทั–. + +ะกะฐะผะต ั†ะต ะดะพะทะฒะพะปัั” ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะบะพะด ะท ะพะดะฝะพะณะพ ั„ะฐะนะปัƒ ะฒ ั–ะฝัˆะธะน. + +ะะฐะฟั€ะธะบะปะฐะด, ัƒ `app/main.py` ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ั€ัะดะพะบ: + +``` +from app.routers import items +``` + +/// + +* ะšะฐั‚ะฐะปะพะณ `app` ะผั–ัั‚ะธั‚ัŒ ัƒัะต. ะ† ะฒั–ะฝ ะผะฐั” ะฟะพั€ะพะถะฝั–ะน ั„ะฐะนะป `app/__init__.py`, ั‚ะพะถ ั†ะต ยซะฟะฐะบะตั‚ Pythonยป (ะทะฑั–ั€ะบะฐ ยซะผะพะดัƒะปั–ะฒ Pythonยป): `app`. +* ะ’ั–ะฝ ะผั–ัั‚ะธั‚ัŒ ั„ะฐะนะป `app/main.py`. ะžัะบั–ะปัŒะบะธ ะฒั–ะฝ ัƒัะตั€ะตะดะธะฝั– ะฟะฐะบะตั‚ะฐ Python (ะบะฐั‚ะฐะปะพะณ ะท ั„ะฐะนะปะพะผ `__init__.py`), ั†ะต ยซะผะพะดัƒะปัŒยป ั†ัŒะพะณะพ ะฟะฐะบะตั‚ะฐ: `app.main`. +* ะ„ ั‚ะฐะบะพะถ ั„ะฐะนะป `app/dependencies.py`, ั‚ะฐะบ ัะฐะผะพ ัะบ `app/main.py`, ั†ะต ยซะผะพะดัƒะปัŒยป: `app.dependencies`. +* ะ„ ะฟั–ะดะบะฐั‚ะฐะปะพะณ `app/routers/` ะท ั–ะฝัˆะธะผ ั„ะฐะนะปะพะผ `__init__.py`, ะพั‚ะถะต ั†ะต ยซะฟั–ะดะฟะฐะบะตั‚ Pythonยป: `app.routers`. +* ะคะฐะนะป `app/routers/items.py` ะทะฝะฐั…ะพะดะธั‚ัŒัั ะฒ ะฟะฐะบะตั‚ั– `app/routers/`, ะพั‚ะถะต ั†ะต ะฟั–ะดะผะพะดัƒะปัŒ: `app.routers.items`. +* ะขะฐะบ ัะฐะผะพ ั– `app/routers/users.py`, ั†ะต ั–ะฝัˆะธะน ะฟั–ะดะผะพะดัƒะปัŒ: `app.routers.users`. +* ะ„ ั‚ะฐะบะพะถ ะฟั–ะดะบะฐั‚ะฐะปะพะณ `app/internal/` ะท ั–ะฝัˆะธะผ ั„ะฐะนะปะพะผ `__init__.py`, ะพั‚ะถะต ั†ะต ั–ะฝัˆะธะน ยซะฟั–ะดะฟะฐะบะตั‚ Pythonยป: `app.internal`. +* ะ† ั„ะฐะนะป `app/internal/admin.py` - ั‰ะต ะพะดะธะฝ ะฟั–ะดะผะพะดัƒะปัŒ: `app.internal.admin`. + + + +ะขะฐ ัะฐะผะฐ ัั‚ั€ัƒะบั‚ัƒั€ะฐ ั„ะฐะนะปั–ะฒ ะท ะบะพะผะตะฝั‚ะฐั€ัะผะธ: + +```bash +. +โ”œโ”€โ”€ app # ยซappยป - ั†ะต ะฟะฐะบะตั‚ Python +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ั†ะตะน ั„ะฐะนะป ั€ะพะฑะธั‚ัŒ ยซappยป ยซะฟะฐะบะตั‚ะพะผ Pythonยป +โ”‚ย ย  โ”œโ”€โ”€ main.py # ะผะพะดัƒะปัŒ ยซmainยป, ะฝะฐะฟั€. import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # ะผะพะดัƒะปัŒ ยซdependenciesยป, ะฝะฐะฟั€. import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # ยซroutersยป - ั†ะต ยซะฟั–ะดะฟะฐะบะตั‚ Pythonยป +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # ั€ะพะฑะธั‚ัŒ ยซroutersยป ยซะฟั–ะดะฟะฐะบะตั‚ะพะผ Pythonยป +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # ะฟั–ะดะผะพะดัƒะปัŒ ยซitemsยป, ะฝะฐะฟั€. import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # ะฟั–ะดะผะพะดัƒะปัŒ ยซusersยป, ะฝะฐะฟั€. import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # ยซinternalยป - ั†ะต ยซะฟั–ะดะฟะฐะบะตั‚ Pythonยป +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ั€ะพะฑะธั‚ัŒ ยซinternalยป ยซะฟั–ะดะฟะฐะบะตั‚ะพะผ Pythonยป +โ”‚ย ย  โ””โ”€โ”€ admin.py # ะฟั–ะดะผะพะดัƒะปัŒ ยซadminยป, ะฝะฐะฟั€. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ั„ะฐะนะป, ะฟั€ะธัะฒัั‡ะตะฝะธะน ะพะฑั€ะพะฑั†ั– ะปะธัˆะต ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, - ั†ะต ะฟั–ะดะผะพะดัƒะปัŒ ัƒ `/app/routers/users.py`. + +ะ’ะธ ั…ะพั‡ะตั‚ะต ะผะฐั‚ะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฟะพะฒ'ัะทะฐะฝั– ะท ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐะผะธ, ะฒั–ะดะพะบั€ะตะผะปะตะฝะพ ะฒั–ะด ั€ะตัˆั‚ะธ ะบะพะดัƒ, ั‰ะพะฑ ะทะฑะตั€ะตะณั‚ะธ ะฟะพั€ัะดะพะบ. + +ะะปะต ั†ะต ะฒัะต ะพะดะฝะพ ั‡ะฐัั‚ะธะฝะฐ ั‚ะพะณะพ ัะฐะผะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ/ะฒะตะฑ-API **FastAPI** (ั†ะต ั‡ะฐัั‚ะธะฝะฐ ั‚ะพะณะพ ัะฐะผะพะณะพ ยซะฟะฐะบะตั‚ะฐ Pythonยป). + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะดะปั ั†ัŒะพะณะพ ะผะพะดัƒะปั, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `APIRouter`. + +### ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `APIRouter` { #import-apirouter } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ะนะพะณะพ ั‚ะฐ ัั‚ะฒะพั€ั–ั‚ัŒ ยซะตะบะทะตะผะฟะปัั€ยป ั‚ะฐะบ ัะฐะผะพ, ัะบ ะฒะธ ะฑ ั€ะพะฑะธะปะธ ะท ะบะปะฐัะพะผ `FastAPI`: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### *ะžะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะท `APIRouter` { #path-operations-with-apirouter } + +ะŸะพั‚ั–ะผ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะนะพะณะพ ะดะปั ะพะณะพะปะพัˆะตะฝะฝั *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะนะพะณะพ ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะบะปะฐั `FastAPI`: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +ะœะพะถะตั‚ะต ะดัƒะผะฐั‚ะธ ะฟั€ะพ `APIRouter` ัะบ ะฟั€ะพ ยซะผั–ะฝั– `FastAPI`ยป. + +ะŸั–ะดั‚ั€ะธะผัƒัŽั‚ัŒัั ั‚ั– ัะฐะผั– ะพะฟั†ั–ั—. + +ะขั– ัะฐะผั– `parameters`, `responses`, `dependencies`, `tags` ั‚ะพั‰ะพ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะทะผั–ะฝะฝะฐ ะฝะฐะทะธะฒะฐั”ั‚ัŒัั `router`, ะฐะปะต ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะทะฒะฐั‚ะธ ั—ั— ัะบ ะทะฐะฒะณะพะดะฝะพ. + +/// + +ะœะธ ะฒะบะปัŽั‡ะธะผะพ ั†ะตะน `APIRouter` ัƒ ะพัะฝะพะฒะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ `FastAPI`, ะฐะปะต ัะฟะพั‡ะฐั‚ะบัƒ ั€ะพะทะณะปัะฝัŒะผะพ ะทะฐะปะตะถะฝะพัั‚ั– ั‚ะฐ ั–ะฝัˆะธะน `APIRouter`. + +## ะ—ะฐะปะตะถะฝะพัั‚ั– { #dependencies } + +ะ‘ะฐั‡ะธะผะพ, ั‰ะพ ะฝะฐะผ ะทะฝะฐะดะพะฑะปัั‚ัŒัั ะบั–ะปัŒะบะฐ ะทะฐะปะตะถะฝะพัั‚ะตะน, ัะบั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒัั ะฒ ั€ั–ะทะฝะธั… ะผั–ัั†ัั… ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะขะพะถ ะฟะพะผั–ัั‚ะธะผะพ ั—ั… ัƒ ะฒะปะฐัะฝะธะน ะผะพะดัƒะปัŒ `dependencies` (`app/dependencies.py`). + +ะขะตะฟะตั€ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ ะฟั€ะพัั‚ัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะดะปั ั‡ะธั‚ะฐะฝะฝั ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะพะณะพ ะทะฐะณะพะปะพะฒะบะฐ `X-Token`: + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฒะธะณะฐะดะฐะฝะธะน ะทะฐะณะพะปะพะฒะพะบ, ั‰ะพะฑ ัะฟั€ะพัั‚ะธั‚ะธ ะฟั€ะธะบะปะฐะด. + +ะะปะต ะฒ ั€ะตะฐะปัŒะฝะธั… ะฒะธะฟะฐะดะบะฐั… ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะบั€ะฐั‰ั– ั€ะตะทัƒะปัŒั‚ะฐั‚ะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– [ะทะฐัะพะฑะธ ะฑะตะทะฟะตะบะธ](security/index.md){.internal-link target=_blank}. + +/// + +## ะ†ะฝัˆะธะน ะผะพะดัƒะปัŒ ะท `APIRouter` { #another-module-with-apirouter } + +ะŸั€ะธะฟัƒัั‚ั–ะผะพ, ัƒ ะฒะฐั ั‚ะฐะบะพะถ ั” ะบั–ะฝั†ะตะฒั– ั‚ะพั‡ะบะธ ะดะปั ะพะฑั€ะพะฑะบะธ ยซitemsยป ัƒ ะผะพะดัƒะปั– `app/routers/items.py`. + +ะฃ ะฒะฐั ั” *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะดะปั: + +* `/items/` +* `/items/{item_id}` + +ะกั‚ั€ัƒะบั‚ัƒั€ะฐ ั‚ะฐะบะฐ ัะฐะผะฐ, ัะบ ัƒ `app/routers/users.py`. + +ะะปะต ะผะธ ั…ะพั‡ะตะผะพ ะฑัƒั‚ะธ ั€ะพะทัƒะผะฝั–ัˆะธะผะธ ะน ั‚ั€ะพั…ะธ ัะฟั€ะพัั‚ะธั‚ะธ ะบะพะด. + +ะœะธ ะทะฝะฐั”ะผะพ, ั‰ะพ ะฒัั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒ ั†ัŒะพะผัƒ ะผะพะดัƒะปั– ะผะฐัŽั‚ัŒ ะพะดะฝะฐะบะพะฒั–: + +* ะŸั€ะตั„ั–ะบั ัˆะปัั…ัƒ `prefix`: `/items`. +* `tags`: (ะปะธัˆะต ะพะดะฝะฐ ะผั–ั‚ะบะฐ: `items`). +* ะ”ะพะดะฐั‚ะบะพะฒั– `responses`. +* `dependencies`: ัƒัั–ะผ ะฟะพั‚ั€ั–ะฑะฝะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ `X-Token`, ัะบัƒ ะผะธ ัั‚ะฒะพั€ะธะปะธ. + +ะขะพะถ ะทะฐะผั–ัั‚ัŒ ะดะพะดะฐะฒะฐะฝะฝั ั†ัŒะพะณะพ ะดะพ ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะผะธ ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ ั†ะต ะดะพ `APIRouter`. + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +ะžัะบั–ะปัŒะบะธ ัˆะปัั… ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะผะฐั” ะฟะพั‡ะธะฝะฐั‚ะธัั ะท `/`, ัะบ ัƒ: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...ะฟั€ะตั„ั–ะบั ะฝะต ะผะฐั” ะผั–ัั‚ะธั‚ะธ ะบั–ะฝั†ะตะฒะธะน `/`. + +ะžั‚ะถะต, ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟั€ะตั„ั–ะบั - ั†ะต `/items`. + +ะœะธ ั‚ะฐะบะพะถ ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ ัะฟะธัะพะบ `tags` ั‚ะฐ ะดะพะดะฐั‚ะบะพะฒั– `responses`, ัะบั– ะทะฐัั‚ะพัะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒัั ะดะพ ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*, ะฒะบะปัŽั‡ะตะฝะธั… ัƒ ั†ะตะน router. + +ะ† ะผะธ ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ ัะฟะธัะพะบ `dependencies`, ัะบั– ะฑัƒะดะต ะดะพะดะฐะฝะพ ะดะพ ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ัƒ router ั– ัะบั– ะฒะธะบะพะฝัƒะฒะฐั‚ะธะผัƒั‚ัŒัั/ะฒะธั€ั–ัˆัƒะฒะฐั‚ะธะผัƒั‚ัŒัั ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ ะดะพ ะฝะธั…. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะดะปั [ะทะฐะปะตะถะฝะพัั‚ะตะน ัƒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะถะพะดะฝะต ะทะฝะฐั‡ะตะฝะฝั ะฝะต ะฑัƒะดะต ะฟะตั€ะตะดะฐะฝะพ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +/// + +ะฃ ะฟั–ะดััƒะผะบัƒ ัˆะปัั…ะธ ะฟั€ะตะดะผะตั‚ั–ะฒ ั‚ะตะฟะตั€: + +* `/items/` +* `/items/{item_id}` + +...ัะบ ะผะธ ั– ะฟะปะฐะฝัƒะฒะฐะปะธ. + +* ะ’ะพะฝะธ ะฑัƒะดัƒั‚ัŒ ะฟะพะทะฝะฐั‡ะตะฝั– ัะฟะธัะบะพะผ ะผั–ั‚ะพะบ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะพะดะธะฝ ั€ัะดะพะบ `"items"`. + * ะฆั– ยซะผั–ั‚ะบะธยป ะพัะพะฑะปะธะฒะพ ะบะพั€ะธัะฝั– ะดะปั ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— (ะทะฐ ะดะพะฟะพะผะพะณะพัŽ OpenAPI). +* ะฃัั– ะฒะพะฝะธ ะฒะบะปัŽั‡ะฐั‚ะธะผัƒั‚ัŒ ะฝะฐะฟะตั€ะตะด ะฒะธะทะฝะฐั‡ะตะฝั– `responses`. +* ะ”ะปั ะฒัั–ั… ั†ะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ัะฟะธัะพะบ `dependencies` ะฑัƒะดะต ะพั†ั–ะฝะตะฝะธะน/ะฒะธะบะพะฝะฐะฝะธะน ะฟะตั€ะตะด ะฝะธะผะธ. + * ะฏะบั‰ะพ ะฒะธ ั‚ะฐะบะพะถ ะพะณะพะปะพัะธั‚ะต ะทะฐะปะตะถะฝะพัั‚ั– ะฒ ะบะพะฝะบั€ะตั‚ะฝั–ะน *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, **ะฒะพะฝะธ ั‚ะฐะบะพะถ ะฑัƒะดัƒั‚ัŒ ะฒะธะบะพะฝะฐะฝั–**. + * ะกะฟะพั‡ะฐั‚ะบัƒ ะฒะธะบะพะฝัƒัŽั‚ัŒัั ะทะฐะปะตะถะฝะพัั‚ั– router'ะฐ, ะฟะพั‚ั–ะผ [`dependencies` ัƒ ะดะตะบะพั€ะฐั‚ะพั€ั–](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะฐ ะฟะพั‚ั–ะผ ะทะฒะธั‡ะฐะนะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธั‡ะฝั– ะทะฐะปะตะถะฝะพัั‚ั–. + * ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ [`Security` ะทะฐะปะตะถะฝะพัั‚ั– ะท `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐัะฒะฝั–ัั‚ัŒ `dependencies` ัƒ `APIRouter` ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฒะธะผะฐะณะฐั‚ะธ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ ะดะปั ะฒัั–ั”ั— ะณั€ัƒะฟะธ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. ะะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะทะฐะปะตะถะฝะพัั‚ั– ะฝะต ะดะพะดะฐะฝั– ะดะพ ะบะพะถะฝะพั— ะท ะฝะธั… ะพะบั€ะตะผะพ. + +/// + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +ะŸะฐั€ะฐะผะตั‚ั€ะธ `prefix`, `tags`, `responses` ั– `dependencies` - ั†ะต (ัะบ ั– ะฒ ะฑะฐะณะฐั‚ัŒะพั… ั–ะฝัˆะธั… ะฒะธะฟะฐะดะบะฐั…) ะฟั€ะพัั‚ะพ ะผะพะถะปะธะฒั–ัั‚ัŒ **FastAPI**, ัะบะฐ ะดะพะฟะพะผะฐะณะฐั” ัƒะฝะธะบะฐั‚ะธ ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ. + +/// + +### ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ะทะฐะปะตะถะฝะพัั‚ั– { #import-the-dependencies } + +ะฆะตะน ะบะพะด ะถะธะฒะต ะฒ ะผะพะดัƒะปั– `app.routers.items`, ัƒ ั„ะฐะนะปั– `app/routers/items.py`. + +ะ† ะฝะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพั‚ั€ะธะผะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ ะทะฐะปะตะถะฝะพัั‚ั– ะท ะผะพะดัƒะปั `app.dependencies`, ั„ะฐะนะปัƒ `app/dependencies.py`. + +ะขะพะถ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฒั–ะดะฝะพัะฝะธะน ั–ะผะฟะพั€ั‚ ะท `..` ะดะปั ะทะฐะปะตะถะฝะพัั‚ะตะน: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### ะฏะบ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฒั–ะดะฝะพัะฝั– ั–ะผะฟะพั€ั‚ะธ { #how-relative-imports-work } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะดะพัะบะพะฝะฐะปะพ ะทะฝะฐั”ั‚ะต, ัะบ ะฟั€ะฐั†ัŽัŽั‚ัŒ ั–ะผะฟะพั€ั‚ะธ, ะฟะตั€ะตะนะดั–ั‚ัŒ ะดะพ ะฝะฐัั‚ัƒะฟะฝะพะณะพ ั€ะพะทะดั–ะปัƒ ะฝะธะถั‡ะต. + +/// + +ะžะดะฝะฐ ะบั€ะฐะฟะบะฐ `.`, ัะบ ัƒ: + +```Python +from .dependencies import get_token_header +``` + +ะพะทะฝะฐั‡ะฐั”: + +* ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะฒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะฟะฐะบะตั‚ั–, ะดะต ะทะฝะฐั…ะพะดะธั‚ัŒัั ั†ะตะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะทะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ัƒัะฒะฝะธะน ั„ะฐะนะป `app/routers/dependencies.py`)... +* ั– ะท ะฝัŒะพะณะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ `get_token_header`. + +ะะปะต ั‚ะฐะบะพะณะพ ั„ะฐะนะปัƒ ะฝะต ั–ัะฝัƒั”, ะฝะฐัˆั– ะทะฐะปะตะถะฝะพัั‚ั– ัƒ ั„ะฐะนะปั– `app/dependencies.py`. + +ะ—ะณะฐะดะฐะนั‚ะต, ัะบ ะฒะธะณะปัะดะฐั” ัั‚ั€ัƒะบั‚ัƒั€ะฐ ะฝะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ/ั„ะฐะนะปั–ะฒ: + + + +--- + +ะ”ะฒั– ะบั€ะฐะฟะบะธ `..`, ัะบ ัƒ: + +```Python +from ..dependencies import get_token_header +``` + +ะพะทะฝะฐั‡ะฐัŽั‚ัŒ: + +* ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะฒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะฟะฐะบะตั‚ั–, ะดะต ะทะฝะฐั…ะพะดะธั‚ัŒัั ั†ะตะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะฟะตั€ะตะนั‚ะธ ะดะพ ะฑะฐั‚ัŒะบั–ะฒััŒะบะพะณะพ ะฟะฐะบะตั‚ะฐ (ะบะฐั‚ะฐะปะพะณ `app/`)... +* ั– ั‚ะฐะผ ะทะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... +* ั– ะท ะฝัŒะพะณะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ `get_token_header`. + +ะฆะต ะฟั€ะฐั†ัŽั” ะฟั€ะฐะฒะธะปัŒะฝะพ! ๐ŸŽ‰ + +--- + +ะขะฐะบ ัะฐะผะพ, ัะบะฑะธ ะผะธ ะฒะธะบะพั€ะธัั‚ะฐะปะธ ั‚ั€ะธ ะบั€ะฐะฟะบะธ `...`, ัะบ ัƒ: + +```Python +from ...dependencies import get_token_header +``` + +ั†ะต ะฑ ะพะทะฝะฐั‡ะฐะปะพ: + +* ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะฒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะฟะฐะบะตั‚ั–, ะดะต ะทะฝะฐั…ะพะดะธั‚ัŒัั ั†ะตะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/routers/items.py`) (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ะฟะตั€ะตะนั‚ะธ ะดะพ ะฑะฐั‚ัŒะบั–ะฒััŒะบะพะณะพ ะฟะฐะบะตั‚ะฐ (ะบะฐั‚ะฐะปะพะณ `app/`)... +* ะฟะพั‚ั–ะผ ะฟะตั€ะตะนั‚ะธ ะดะพ ะฑะฐั‚ัŒะบั–ะฒััŒะบะพะณะพ ะฟะฐะบะตั‚ะฐ ะฒั–ะด ั‚ะพะณะพ (ะฝะตะผะฐั” ะฑะฐั‚ัŒะบั–ะฒััŒะบะพะณะพ ะฟะฐะบะตั‚ะฐ, `app` - ะฒะตั€ั…ะฝั–ะน ั€ั–ะฒะตะฝัŒ ๐Ÿ˜ฑ)... +* ั– ั‚ะฐะผ ะทะฝะฐะนั‚ะธ ะผะพะดัƒะปัŒ `dependencies` (ั„ะฐะนะป `app/dependencies.py`)... +* ั– ะท ะฝัŒะพะณะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั„ัƒะฝะบั†ั–ัŽ `get_token_header`. + +ะฆะต ะฑ ะฟะพัะธะปะฐะปะพัั ะฝะฐ ัะบะธะนััŒ ะฟะฐะบะตั‚ ะฒะธั‰ะต ะทะฐ `app/` ะท ะฒะปะฐัะฝะธะผ ั„ะฐะนะปะพะผ `__init__.py` ั‚ะพั‰ะพ. ะะปะต ะฒ ะฝะฐั ั‚ะฐะบะพะณะพ ะฝะตะผะฐั”. ะขะพะถ ัƒ ะฝะฐัˆะพะผัƒ ะฟั€ะธะบะปะฐะดั– ั†ะต ัะฟั€ะธั‡ะธะฝะธั‚ัŒ ะฟะพะผะธะปะบัƒ. ๐Ÿšจ + +ะะปะต ั‚ะตะฟะตั€ ะฒะธ ะทะฝะฐั”ั‚ะต, ัะบ ั†ะต ะฟั€ะฐั†ัŽั”, ั‚ะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ะดะฝะพัะฝั– ั–ะผะฟะพั€ั‚ะธ ัƒ ะฒะปะฐัะฝะธั… ะทะฐัั‚ะพััƒะฝะบะฐั…, ะฝะตะทะฐะปะตะถะฝะพ ะฒั–ะด ั—ั…ะฝัŒะพั— ัะบะปะฐะดะฝะพัั‚ั–. ๐Ÿค“ + +### ะ”ะพะดะฐะนั‚ะต ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบั– `tags`, `responses` ั– `dependencies` { #add-some-custom-tags-responses-and-dependencies } + +ะœะธ ะฝะต ะดะพะดะฐั”ะผะพ ะฟั€ะตั„ั–ะบั `/items` ะฐะฝั– `tags=["items"]` ะดะพ ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฑะพ ะดะพะดะฐะปะธ ั—ั… ะดะพ `APIRouter`. + +ะะปะต ะผะธ ะฒัะต ั‰ะต ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ _ั‰ะต_ `tags`, ัะบั– ะฑัƒะดัƒั‚ัŒ ะทะฐัั‚ะพัะพะฒะฐะฝั– ะดะพ ะบะพะฝะบั€ะตั‚ะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฐ ั‚ะฐะบะพะถ ะดะพะดะฐั‚ะบะพะฒั– `responses`, ัะฟะตั†ะธั„ั–ั‡ะฝั– ะดะปั ั†ั–ั”ั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะžัั‚ะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ ะผะฐั‚ะธะผะต ะบะพะผะฑั–ะฝะฐั†ั–ัŽ ะผั–ั‚ะพะบ: `["items", "custom"]`. + +ะ† ะฒะพะฝะฐ ั‚ะฐะบะพะถ ะผะฐั‚ะธะผะต ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะพะฑะธะดะฒั– ะฒั–ะดะฟะพะฒั–ะดั–: ะพะดะฝัƒ ะดะปั `404` ั– ะพะดะฝัƒ ะดะปั `403`. + +/// + +## ะžัะฝะพะฒะฝะธะน `FastAPI` { #the-main-fastapi } + +ะขะตะฟะตั€ ั€ะพะทะณะปัะฝัŒะผะพ ะผะพะดัƒะปัŒ `app/main.py`. + +ะขัƒั‚ ะฒะธ ั–ะผะฟะพั€ั‚ัƒั”ั‚ะต ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะปะฐั `FastAPI`. + +ะฆะต ะฑัƒะดะต ะณะพะปะพะฒะฝะธะน ั„ะฐะนะป ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ัะบะธะน ัƒัะต ะฟะพั”ะดะฝัƒั”. + +ะ† ะพัะบั–ะปัŒะบะธ ะฑั–ะปัŒัˆั–ัั‚ัŒ ะฒะฐัˆะพั— ะปะพะณั–ะบะธ ั‚ะตะฟะตั€ ะถะธั‚ะธะผะต ัƒ ะฒะปะฐัะฝะธั… ะผะพะดัƒะปัั…, ะณะพะปะพะฒะฝะธะน ั„ะฐะนะป ะฑัƒะดะต ะดะพัะธั‚ัŒ ะฟั€ะพัั‚ะธะผ. + +### ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `FastAPI` { #import-fastapi } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ั‚ะฐ ัั‚ะฒะพั€ั–ั‚ัŒ ะบะปะฐั `FastAPI`, ัะบ ะทะฐะทะฒะธั‡ะฐะน. + +ะ† ะผะธ ะฝะฐะฒั–ั‚ัŒ ะผะพะถะตะผะพ ะพะณะพะปะพัะธั‚ะธ [ะณะปะพะฑะฐะปัŒะฝั– ะทะฐะปะตะถะฝะพัั‚ั–](dependencies/global-dependencies.md){.internal-link target=_blank}, ัะบั– ะฑัƒะดัƒั‚ัŒ ะฟะพั”ะดะฝะฐะฝั– ั–ะท ะทะฐะปะตะถะฝะพัั‚ัะผะธ ะบะพะถะฝะพะณะพ `APIRouter`: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `APIRouter` { #import-the-apirouter } + +ะขะตะฟะตั€ ั–ะผะฟะพั€ั‚ัƒั”ะผะพ ั–ะฝัˆั– ะฟั–ะดะผะพะดัƒะปั–, ั‰ะพ ะผะฐัŽั‚ัŒ `APIRouter`: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +ะžัะบั–ะปัŒะบะธ ั„ะฐะนะปะธ `app/routers/users.py` ั‚ะฐ `app/routers/items.py` - ั†ะต ะฟั–ะดะผะพะดัƒะปั–, ั‰ะพ ั” ั‡ะฐัั‚ะธะฝะพัŽ ั‚ะพะณะพ ัะฐะผะพะณะพ ะฟะฐะบะตั‚ะฐ Python `app`, ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะดะฝัƒ ะบั€ะฐะฟะบัƒ `.` ะดะปั ยซะฒั–ะดะฝะพัะฝะธั… ั–ะผะฟะพั€ั‚ั–ะฒยป. + +### ะฏะบ ะฟั€ะฐั†ัŽั” ั–ะผะฟะพั€ั‚ { #how-the-importing-works } + +ะ ะพะทะดั–ะป: + +```Python +from .routers import items, users +``` + +ะพะทะฝะฐั‡ะฐั”: + +* ะŸะพั‡ะธะฝะฐัŽั‡ะธ ะฒ ั‚ะพะผัƒ ัะฐะผะพะผัƒ ะฟะฐะบะตั‚ั–, ะดะต ะทะฝะฐั…ะพะดะธั‚ัŒัั ั†ะตะน ะผะพะดัƒะปัŒ (ั„ะฐะนะป `app/main.py`) (ะบะฐั‚ะฐะปะพะณ `app/`)... +* ะทะฝะฐะนั‚ะธ ะฟั–ะดะฟะฐะบะตั‚ `routers` (ะบะฐั‚ะฐะปะพะณ `app/routers/`)... +* ั– ะท ะฝัŒะพะณะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะฟั–ะดะผะพะดัƒะปั– `items` (ั„ะฐะนะป `app/routers/items.py`) ั– `users` (ั„ะฐะนะป `app/routers/users.py`)... + +ะœะพะดัƒะปัŒ `items` ะผะฐั‚ะธะผะต ะทะผั–ะฝะฝัƒ `router` (`items.router`). ะฆะต ั‚ะฐ ัะฐะผะฐ, ั‰ะพ ะผะธ ัั‚ะฒะพั€ะธะปะธ ัƒ ั„ะฐะนะปั– `app/routers/items.py`, ั†ะต ะพะฑโ€™ั”ะบั‚ `APIRouter`. + +ะŸะพั‚ั–ะผ ะผะธ ั€ะพะฑะธะผะพ ั‚ะต ัะฐะผะต ะดะปั ะผะพะดัƒะปั `users`. + +ะœะธ ั‚ะฐะบะพะถ ะผะพะณะปะธ ะฑ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ั—ั… ั‚ะฐะบ: + +```Python +from app.routers import items, users +``` + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะตั€ัˆะฐ ะฒะตั€ัั–ั - ยซะฒั–ะดะฝะพัะฝะธะน ั–ะผะฟะพั€ั‚ยป: + +```Python +from .routers import items, users +``` + +ะ”ั€ัƒะณะฐ ะฒะตั€ัั–ั - ยซะฐะฑัะพะปัŽั‚ะฝะธะน ั–ะผะฟะพั€ั‚ยป: + +```Python +from app.routers import items, users +``` + +ะฉะพะฑ ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะฟะฐะบะตั‚ะธ ะน ะผะพะดัƒะปั– Python, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะพั„ั–ั†ั–ะนะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ Python ะฟั€ะพ ะผะพะดัƒะปั–. + +/// + +### ะฃะฝะธะบะฐะนั‚ะต ะบะพะปั–ะทั–ะน ั–ะผะตะฝ { #avoid-name-collisions } + +ะœะธ ั–ะผะฟะพั€ั‚ัƒั”ะผะพ ะฟั–ะดะผะพะดัƒะปัŒ `items` ะฝะฐะฟั€ัะผัƒ, ะทะฐะผั–ัั‚ัŒ ั–ะผะฟะพั€ั‚ัƒ ะปะธัˆะต ะนะพะณะพ ะทะผั–ะฝะฝะพั— `router`. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะฒ ะฟั–ะดะผะพะดัƒะปั– `users` ั‚ะฐะบะพะถ ั” ะทะผั–ะฝะฝะฐ ะท ะฝะฐะทะฒะพัŽ `router`. + +ะฏะบะฑะธ ะผะธ ั–ะผะฟะพั€ั‚ัƒะฒะฐะปะธ ะพะดะธะฝ ะทะฐ ะพะดะฝะธะผ, ัะบ: + +```Python +from .routers.items import router +from .routers.users import router +``` + +`router` ะท `users` ะฟะตั€ะตะทะฐะฟะธัะฐะฒ ะฑะธ ั‚ะพะน, ั‰ะพ ะท `items`, ั– ะผะธ ะฝะต ะทะผะพะณะปะธ ะฑ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ะพะดะฝะพั‡ะฐัะฝะพ. + +ะฉะพะฑ ะผะฐั‚ะธ ะทะผะพะณัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะพะฑะธะดะฒะฐ ะฒ ะพะดะฝะพะผัƒ ั„ะฐะนะปั–, ะผะธ ั–ะผะฟะพั€ั‚ัƒั”ะผะพ ะฟั–ะดะผะพะดัƒะปั– ะฝะฐะฟั€ัะผัƒ: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### ะ”ะพะดะฐะนั‚ะต `APIRouter` ะดะปั `users` ั– `items` { #include-the-apirouters-for-users-and-items } + +ะขะตะฟะตั€ ะดะพะดะฐะนะผะพ `router` ะท ะฟั–ะดะผะพะดัƒะปั–ะฒ `users` ั– `items`: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +`users.router` ะผั–ัั‚ะธั‚ัŒ `APIRouter` ัƒ ั„ะฐะนะปั– `app/routers/users.py`. + +ะ `items.router` ะผั–ัั‚ะธั‚ัŒ `APIRouter` ัƒ ั„ะฐะนะปั– `app/routers/items.py`. + +/// + +ะ—ะฐ ะดะพะฟะพะผะพะณะพัŽ `app.include_router()` ะผะธ ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ ะบะพะถะตะฝ `APIRouter` ะดะพ ะพัะฝะพะฒะฝะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`. + +ะฆะต ะฒะบะปัŽั‡ะธั‚ัŒ ัƒัั– ะผะฐั€ัˆั€ัƒั‚ะธ ะท ั†ัŒะพะณะพ router'ะฐ ัะบ ั‡ะฐัั‚ะธะฝัƒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะคะฐะบั‚ะธั‡ะฝะพ, ะฒัะตั€ะตะดะธะฝั– ะดะปั ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะพะณะพะปะพัˆะตะฝะพั— ะฒ `APIRouter`, ะฑัƒะดะต ัั‚ะฒะพั€ะตะฝะฐ ะพะบั€ะตะผะฐ *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ*. + +ะขะพะฑั‚ะพ ะทะฐ ะปะฐัˆั‚ัƒะฝะบะฐะผะธ ะฒัะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ั‚ะฐะบ, ะฝั–ะฑะธ ั†ะต ะพะดะธะฝ ั– ั‚ะพะน ัะฐะผะธะน ะทะฐัั‚ะพััƒะฝะพะบ. + +/// + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +ะ’ะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะนะผะฐั‚ะธัั ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŽ ะฟั–ะด ั‡ะฐั ะฒะบะปัŽั‡ะตะฝะฝั router'ั–ะฒ. + +ะฆะต ะทะฐะนะผะต ะผั–ะบั€ะพัะตะบัƒะฝะดะธ ั– ะฒั–ะดะฑัƒะฒะฐั‚ะธะผะตั‚ัŒัั ะปะธัˆะต ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ. + +ะขะพะถ ั†ะต ะฝะต ะฒะฟะปะธะฝะต ะฝะฐ ะฟั€ะพะดัƒะบั‚ะธะฒะฝั–ัั‚ัŒ. โšก + +/// + +### ะ”ะพะดะฐะนั‚ะต `APIRouter` ะท ะฒะปะฐัะฝะธะผะธ `prefix`, `tags`, `responses` ั– `dependencies` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +ะฃัะฒั–ะผะพ, ั‰ะพ ะฒะฐัˆะฐ ะพั€ะณะฐะฝั–ะทะฐั†ั–ั ะฝะฐะดะฐะปะฐ ะฒะฐะผ ั„ะฐะนะป `app/internal/admin.py`. + +ะ’ั–ะฝ ะผั–ัั‚ะธั‚ัŒ `APIRouter` ะท ะบั–ะปัŒะบะพะผะฐ ะฐะดะผั–ะฝั–ัั‚ั€ะฐั‚ะธะฒะฝะธะผะธ *ะพะฟะตั€ะฐั†ั–ัะผะธ ัˆะปัั…ัƒ*, ัะบั– ะพั€ะณะฐะฝั–ะทะฐั†ั–ั ัะฟั–ะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะผั–ะถ ะบั–ะปัŒะบะพะผะฐ ะฟั€ะพั”ะบั‚ะฐะผะธ. + +ะ”ะปั ั†ัŒะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ะฒั–ะฝ ะฑัƒะดะต ะดัƒะถะต ะฟั€ะพัั‚ะธะผ. ะะปะต ะฟั€ะธะฟัƒัั‚ั–ะผะพ, ั‰ะพ ะพัะบั–ะปัŒะบะธ ะนะพะณะพ ัะฟั–ะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะท ั–ะฝัˆะธะผะธ ะฟั€ะพั”ะบั‚ะฐะผะธ ะพั€ะณะฐะฝั–ะทะฐั†ั–ั—, ะผะธ ะฝะต ะผะพะถะตะผะพ ะผะพะดะธั„ั–ะบัƒะฒะฐั‚ะธ ะนะพะณะพ ั‚ะฐ ะดะพะดะฐะฒะฐั‚ะธ `prefix`, `dependencies`, `tags` ั‚ะพั‰ะพ ะฟั€ัะผะพ ะดะพ `APIRouter`: + +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +ะะปะต ะผะธ ะฒัะต ะพะดะฝะพ ั…ะพั‡ะตะผะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน `prefix` ะฟั–ะด ั‡ะฐั ะฒะบะปัŽั‡ะตะฝะฝั `APIRouter`, ั‰ะพะฑ ัƒัั– ะนะพะณะพ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฟะพั‡ะธะฝะฐะปะธัั ะท `/admin`, ั…ะพั‡ะตะผะพ ะทะฐั…ะธัั‚ะธั‚ะธ ะนะพะณะพ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `dependencies`, ัะบั– ะฒะถะต ั” ะฒ ั†ัŒะพะผัƒ ะฟั€ะพั”ะบั‚ั–, ั– ั…ะพั‡ะตะผะพ ะดะพะดะฐั‚ะธ `tags` ั‚ะฐ `responses`. + +ะœะธ ะผะพะถะตะผะพ ะพะณะพะปะพัะธั‚ะธ ะฒัะต ั†ะต, ะฝะต ะทะผั–ะฝัŽัŽั‡ะธ ะพั€ะธะณั–ะฝะฐะปัŒะฝะธะน `APIRouter`, ะฟะตั€ะตะดะฐะฒัˆะธ ั†ั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะดะพ `app.include_router()`: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะธั…ั–ะดะฝะธะน `APIRouter` ะทะฐะปะธัˆะธั‚ัŒัั ะฑะตะท ะทะผั–ะฝ, ั‚ะพะถ ะผะธ ะฒัะต ั‰ะต ะทะผะพะถะตะผะพ ัะฟั–ะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ั„ะฐะนะป `app/internal/admin.py` ะท ั–ะฝัˆะธะผะธ ะฟั€ะพั”ะบั‚ะฐะผะธ ะฒ ะพั€ะณะฐะฝั–ะทะฐั†ั–ั—. + +ะฃ ั€ะตะทัƒะปัŒั‚ะฐั‚ั– ะฒ ะฝะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะบะพะถะฝะฐ ะท *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะท ะผะพะดัƒะปั `admin` ะผะฐั‚ะธะผะต: + +* ะŸั€ะตั„ั–ะบั `/admin`. +* ะœั–ั‚ะบัƒ `admin`. +* ะ—ะฐะปะตะถะฝั–ัั‚ัŒ `get_token_header`. +* ะ’ั–ะดะฟะพะฒั–ะดัŒ `418`. ๐Ÿต + +ะะปะต ั†ะต ะฒะฟะปะธะฝะต ะปะธัˆะต ะฝะฐ ั†ะตะน `APIRouter` ัƒ ะฝะฐัˆะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฐ ะฝะต ะฝะฐ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะบะพะด, ัะบะธะน ะนะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”. + +ะะฐะฟั€ะธะบะปะฐะด, ั–ะฝัˆั– ะฟั€ะพั”ะบั‚ะธ ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน `APIRouter` ะท ั–ะฝัˆะธะผ ะผะตั‚ะพะดะพะผ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—. + +### ะ”ะพะดะฐะนั‚ะต *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ* { #include-a-path-operation } + +ะœะธ ั‚ะฐะบะพะถ ะผะพะถะตะผะพ ะดะพะดะฐะฒะฐั‚ะธ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`. + +ะขัƒั‚ ะผะธ ั†ะต ั€ะพะฑะธะผะพ... ะฟั€ะพัั‚ะพ ั‰ะพะฑ ะฟะพะบะฐะทะฐั‚ะธ, ั‰ะพ ั‚ะฐะบ ะผะพะถะฝะฐ ๐Ÿคท: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +ั– ั†ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะบะพั€ะตะบั‚ะฝะพ ั€ะฐะทะพะผ ะท ัƒัั–ะผะฐ ั–ะฝัˆะธะผะธ *ะพะฟะตั€ะฐั†ั–ัะผะธ ัˆะปัั…ัƒ*, ะดะพะดะฐะฝะธะผะธ ั‡ะตั€ะตะท `app.include_router()`. + +/// info | ะ”ัƒะถะต ั‚ะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะŸั€ะธะผั–ั‚ะบะฐ: ั†ะต ะดัƒะถะต ั‚ะตั…ะฝั–ั‡ะฝะฐ ะดะตั‚ะฐะปัŒ, ัะบัƒ ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ะฟั€ะพะฟัƒัั‚ะธั‚ะธ. + +--- + +`APIRouter` ะฝะต ยซะผะพะฝั‚ัƒัŽั‚ัŒััยป, ะฒะพะฝะธ ะฝะต ั–ะทะพะปัŒะพะฒะฐะฝั– ะฒั–ะด ั€ะตัˆั‚ะธ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะผะธ ั…ะพั‡ะตะผะพ ะฒะบะปัŽั‡ะฐั‚ะธ ั—ั…ะฝั– *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒ ัั…ะตะผัƒ OpenAPI ั‚ะฐ ั–ะฝั‚ะตั€ั„ะตะนัะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะžัะบั–ะปัŒะบะธ ะผะธ ะฝะต ะผะพะถะตะผะพ ะฟั€ะพัั‚ะพ ั–ะทะพะปัŽะฒะฐั‚ะธ ั—ั… ั– ยซะทะผะพะฝั‚ัƒะฒะฐั‚ะธยป ะฝะตะทะฐะปะตะถะฝะพ ะฒั–ะด ั€ะตัˆั‚ะธ, *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ยซะบะปะพะฝัƒัŽั‚ัŒััยป (ัั‚ะฒะพั€ัŽัŽั‚ัŒัั ะทะฐะฝะพะฒะพ), ะฐ ะฝะต ะฒะบะปัŽั‡ะฐัŽั‚ัŒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +/// + +## ะŸะตั€ะตะฒั–ั€ั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API { #check-the-automatic-api-docs } + +ะขะตะฟะตั€ ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆ ะทะฐัั‚ะพััƒะฝะพะบ: + +
+ +```console +$ fastapi dev app/main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะ† ะฒั–ะดะบั€ะธะนั‚ะต ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะทะฐ ะฐะดั€ะตัะพัŽ http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ API, ั‰ะพ ะฒะบะปัŽั‡ะฐั” ัˆะปัั…ะธ ะท ัƒัั–ั… ะฟั–ะดะผะพะดัƒะปั–ะฒ, ะท ะฟั€ะฐะฒะธะปัŒะฝะธะผะธ ัˆะปัั…ะฐะผะธ (ั– ะฟั€ะตั„ั–ะบัะฐะผะธ) ั‚ะฐ ะฟั€ะฐะฒะธะปัŒะฝะธะผะธ ะผั–ั‚ะบะฐะผะธ: + + + +## ะ’ะบะปัŽั‡ะฐะนั‚ะต ั‚ะพะน ัะฐะผะธะน router ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ ะท ั€ั–ะทะฝะธะผะธ `prefix` { #include-the-same-router-multiple-times-with-different-prefix } + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `.include_router()` ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ ะท ะพะดะฝะธะผ ั– ั‚ะธะผ ัะฐะผะธะผ router'ะพะผ, ะฐะปะต ะท ั€ั–ะทะฝะธะผะธ ะฟั€ะตั„ั–ะบัะฐะผะธ. + +ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพ, ะฝะฐะฟั€ะธะบะปะฐะด, ั‰ะพะฑ ะฟัƒะฑะปั–ะบัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน API ะฟั–ะด ั€ั–ะทะฝะธะผะธ ะฟั€ะตั„ั–ะบัะฐะผะธ, ะฝะฐะฟั€ะธะบะปะฐะด `/api/v1` ั– `/api/latest`. + +ะฆะต ะฟั€ะพััƒะฝัƒั‚ะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั, ัะบะต ะฒะฐะผ ะผะพะถะต ะน ะฝะต ะทะฝะฐะดะพะฑะธั‚ะธัั, ะฐะปะต ะฒะพะฝะพ ั” ะฝะฐ ะฒะธะฟะฐะดะพะบ, ัะบั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ. + +## ะ’ะบะปัŽั‡ั–ั‚ัŒ ะพะดะธะฝ `APIRouter` ะดะพ ั–ะฝัˆะพะณะพ { #include-an-apirouter-in-another } + +ะขะฐะบ ัะฐะผะพ ัะบ ะฒะธ ะผะพะถะตั‚ะต ะฒะบะปัŽั‡ะธั‚ะธ `APIRouter` ัƒ ะทะฐัั‚ะพััƒะฝะพะบ `FastAPI`, ะฒะธ ะผะพะถะตั‚ะต ะฒะบะปัŽั‡ะธั‚ะธ `APIRouter` ะฒ ั–ะฝัˆะธะน `APIRouter`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ: + +```Python +router.include_router(other_router) +``` + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ั€ะพะฑะธั‚ะต ั†ะต ะดะพ ะฒะบะปัŽั‡ะตะฝะฝั `router` ะฒ ะทะฐัั‚ะพััƒะฝะพะบ `FastAPI`, ั‰ะพะฑ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะท `other_router` ั‚ะฐะบะพะถ ะฑัƒะปะธ ะฒะบะปัŽั‡ะตะฝั–. diff --git a/docs/uk/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/uk/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 0000000000..e64f90ae24 --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# ะšะปะฐัะธ ัะบ ะทะฐะปะตะถะฝะพัั‚ั– { #classes-as-dependencies } + +ะŸะตั€ัˆ ะฝั–ะถ ะทะฐะณะปะธะฑะธั‚ะธัั ัƒ ัะธัั‚ะตะผัƒ **ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**, ะพะฝะพะฒั–ะผะพ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฟั€ะธะบะปะฐะด. + +## `dict` ะท ะฟะพะฟะตั€ะตะดะฝัŒะพะณะพ ะฟั€ะธะบะปะฐะดัƒ { #a-dict-from-the-previous-example } + +ะฃ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฟะพะฒะตั€ั‚ะฐะปะธ `dict` ั–ะท ะฝะฐัˆะพะณะพ ยซะทะฐะปะตะถะฝะพะณะพยป: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +ะะปะต ั‚ะพะดั– ะผะธ ะพั‚ั€ะธะผัƒั”ะผะพ `dict` ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– `commons` ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะ† ะผะธ ะทะฝะฐั”ะผะพ, ั‰ะพ ั€ะตะดะฐะบั‚ะพั€ะธ ะฝะต ะผะพะถัƒั‚ัŒ ะฝะฐะดะฐั‚ะธ ะฑะฐะณะฐั‚ะพ ะฟั–ะดั‚ั€ะธะผะบะธ (ะฝะฐะฟั€ะธะบะปะฐะด, ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั) ะดะปั `dict`, ะฐะดะถะต ะฒะพะฝะธ ะฝะต ะทะฝะฐัŽั‚ัŒ ั—ั…ะฝั–ั… ะบะปัŽั‡ั–ะฒ ั– ั‚ะธะฟั–ะฒ ะทะฝะฐั‡ะตะฝัŒ. + +ะœะพะถะฝะฐ ะทั€ะพะฑะธั‚ะธ ะบั€ะฐั‰ะตโ€ฆ + +## ะฉะพ ั€ะพะฑะธั‚ัŒ ะพะฑโ€™ั”ะบั‚ ะทะฐะปะตะถะฝั–ัั‚ัŽ { #what-makes-a-dependency } + +ะ”ะพั‚ะตะฟะตั€ ะฒะธ ะฑะฐั‡ะธะปะธ ะทะฐะปะตะถะฝะพัั‚ั–, ะพะณะพะปะพัˆะตะฝั– ัะบ ั„ัƒะฝะบั†ั–ั—. + +ะะปะต ั†ะต ะฝะต ั”ะดะธะฝะธะน ัะฟะพัั–ะฑ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– (ั…ะพั‡ะฐ, ะนะผะพะฒั–ั€ะฝะพ, ะฝะฐะนะฟะพัˆะธั€ะตะฝั–ัˆะธะน). + +ะšะปัŽั‡ะพะฒะธะน ะผะพะผะตะฝั‚ ัƒ ั‚ะพะผัƒ, ั‰ะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะผะฐั” ะฑัƒั‚ะธ ยซะฒะธะบะปะธะบะฐั”ะผะธะผยป. + +ยซะ’ะธะบะปะธะบะฐั”ะผะธะนยป ัƒ Python - ั†ะต ะฑัƒะดัŒ-ั‰ะพ, ั‰ะพ Python ะผะพะถะต ยซะฒะธะบะปะธะบะฐั‚ะธยป, ัะบ ั„ัƒะฝะบั†ั–ัŽ. + +ะžั‚ะถะต, ัะบั‰ะพ ัƒ ะฒะฐั ั” ะพะฑโ€™ั”ะบั‚ `something` (ัะบะธะน ะผะพะถะต ะน ะฝะต ะฑัƒั‚ะธ ั„ัƒะฝะบั†ั–ั”ัŽ) ั– ะฒะธ ะผะพะถะตั‚ะต ยซะฒะธะบะปะธะบะฐั‚ะธยป ะนะพะณะพ (ะฒะธะบะพะฝะฐั‚ะธ) ั‚ะฐะบ: + +```Python +something() +``` + +ะฐะฑะพ + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +ั‚ะพะดั– ั†ะต ยซะฒะธะบะปะธะบะฐั”ะผะธะนยป. + +## ะšะปะฐัะธ ัะบ ะทะฐะปะตะถะฝะพัั‚ั– { #classes-as-dependencies_1 } + +ะ’ะธ ะผะพะณะปะธ ะฟะพะผั–ั‚ะธั‚ะธ, ั‰ะพ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะตะบะทะตะผะฟะปัั€ะฐ ะบะปะฐััƒ Python ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั‚ะพะน ัะฐะผะธะน ัะธะฝั‚ะฐะบัะธั. + +ะะฐะฟั€ะธะบะปะฐะด: + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `fluffy` - ะตะบะทะตะผะฟะปัั€ ะบะปะฐััƒ `Cat`. + +ะ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั `fluffy` ะฒะธ ยซะฒะธะบะปะธะบะฐั”ั‚ะตยป `Cat`. + +ะžั‚ะถะต, ะบะปะฐั Python ั‚ะฐะบะพะถ ั” **ะฒะธะบะปะธะบะฐั”ะผะธะผ**. + +ะขะพะถ ัƒ **FastAPI** ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะบะปะฐั Python ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ. + +ะะฐัะฟั€ะฐะฒะดั– **FastAPI** ะฟะตั€ะตะฒั–ั€ัั”, ั‰ะพ ั†ะต ยซะฒะธะบะปะธะบะฐั”ะผะธะนยป ะพะฑโ€™ั”ะบั‚ (ั„ัƒะฝะบั†ั–ั, ะบะปะฐั ั‡ะธ ั‰ะพััŒ ั–ะฝัˆะต) ั– ัะบั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฒ ะฝัŒะพะณะพ ะพะณะพะปะพัˆะตะฝั–. + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ยซะฒะธะบะปะธะบะฐั”ะผะธะนยป ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒ **FastAPI**, ะฒั–ะฝ ะฟั€ะพะฐะฝะฐะปั–ะทัƒั” ะฟะฐั€ะฐะผะตั‚ั€ะธ ั†ัŒะพะณะพ ะพะฑโ€™ั”ะบั‚ะฐ ั– ะพะฑั€ะพะฑะธั‚ัŒ ั—ั… ั‚ะฐะบ ัะฐะผะพ, ัะบ ะฟะฐั€ะฐะผะตั‚ั€ะธ ะดะปั ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. ะ’ะบะปัŽั‡ะฝะพ ะท ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ัะผะธ. + +ะฆะต ั‚ะฐะบะพะถ ัั‚ะพััƒั”ั‚ัŒัั ะฒะธะบะปะธะบะฐั”ะผะธั… ะฑะตะท ะถะพะดะฝะธั… ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ. ะขะฐะบ ัะฐะผะพ, ัะบ ั– ะดะปั ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ ะฑะตะท ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ. + +ะขะพะดั– ะผะธ ะผะพะถะตะผะพ ะทะผั–ะฝะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ `common_parameters` ะฒะธั‰ะต ะฝะฐ ะบะปะฐั `CommonQueryParams`: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ ะผะตั‚ะพะด `__init__`, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะตะบะทะตะผะฟะปัั€ะฐ ะบะปะฐััƒ: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +โ€ฆะฒั–ะฝ ะผะฐั” ั‚ั– ัะฐะผั– ะฟะฐั€ะฐะผะตั‚ั€ะธ, ั‰ะพ ะน ะฝะฐัˆ ะฟะพะฟะตั€ะตะดะฝั–ะน `common_parameters`: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +ะกะฐะผะต ั†ั– ะฟะฐั€ะฐะผะตั‚ั€ะธ **FastAPI** ะฒะธะบะพั€ะธัั‚ะฐั”, ั‰ะพะฑ ยซั€ะพะทะฒโ€™ัะทะฐั‚ะธยป ะทะฐะปะตะถะฝั–ัั‚ัŒ. + +ะ’ ะพะฑะพั… ะฒะธะฟะฐะดะบะฐั… ะฑัƒะดะต: + +- ะะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `q`, ัะบะธะน ั” `str`. +- ะŸะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `skip`, ัะบะธะน ั” `int`, ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `0`. +- ะŸะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `limit`, ัะบะธะน ั” `int`, ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `100`. + +ะ’ ะพะฑะพั… ะฒะธะฟะฐะดะบะฐั… ะดะฐะฝั– ะฑัƒะดัƒั‚ัŒ ะฟะตั€ะตั‚ะฒะพั€ะตะฝั–, ะฟะตั€ะตะฒั–ั€ะตะฝั– ะน ะทะฐะดะพะบัƒะผะตะฝั‚ะพะฒะฐะฝั– ะฒ ัั…ะตะผั– OpenAPI ั‚ะพั‰ะพ. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั { #use-it } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั†ะตะน ะบะปะฐั. + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI** ะฒะธะบะปะธะบะฐั” ะบะปะฐั `CommonQueryParams`. ะฆะต ัั‚ะฒะพั€ัŽั” ยซะตะบะทะตะผะฟะปัั€ยป ั†ัŒะพะณะพ ะบะปะฐััƒ, ั– ั†ะตะน ะตะบะทะตะผะฟะปัั€ ะฑัƒะดะต ะฟะตั€ะตะดะฐะฝะพ ัะบ ะฟะฐั€ะฐะผะตั‚ั€ `commons` ัƒ ะฒะฐัˆัƒ ั„ัƒะฝะบั†ั–ัŽ. + +## ะะฝะพั‚ะฐั†ั–ั ั‚ะธะฟั–ะฒ ะฟั€ะพั‚ะธ `Depends` { #type-annotation-vs-depends } + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒะธั‰ะต ะผะธ ะดะฒั–ั‡ั– ะฟะธัˆะตะผะพ `CommonQueryParams`: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +ะžัั‚ะฐะฝะฝั–ะน `CommonQueryParams` ัƒ: + +```Python +... Depends(CommonQueryParams) +``` + + - ั†ะต ั‚ะต, ั‰ะพ **FastAPI** ั„ะฐะบั‚ะธั‡ะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั”, ั‰ะพะฑ ะดั–ะทะฝะฐั‚ะธัั, ัะบะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ. + +ะกะฐะผะต ะท ะฝัŒะพะณะพ **FastAPI** ะฒะธั‚ัะณะฝะต ะพะณะพะปะพัˆะตะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั– ัะฐะผะต ะนะพะณะพ **FastAPI** ะฑัƒะดะต ะฒะธะบะปะธะบะฐั‚ะธ. + +--- + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะตั€ัˆะธะน `CommonQueryParams` ัƒ: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +โ€ฆะฝะต ะผะฐั” ะถะพะดะฝะพะณะพ ะพัะพะฑะปะธะฒะพะณะพ ะทะฝะฐั‡ะตะฝะฝั ะดะปั **FastAPI**. FastAPI ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต ะนะพะณะพ ะดะปั ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะฐะฝะธั…, ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะพั‰ะพ (ะฐะดะถะต ะดะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั `Depends(CommonQueryParams)`). + +ะะฐัะฟั€ะฐะฒะดั– ะฒะธ ะผะพะณะปะธ ะฑ ะฝะฐะฟะธัะฐั‚ะธ ะฟั€ะพัั‚ะพ: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +โ€ฆัะบ ัƒ: + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +ะะปะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ั‚ะธะฟ ั€ะตะบะพะผะตะฝะดัƒั”ั‚ัŒัั - ั‚ะฐะบ ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€ ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะฑัƒะดะต ะฟะตั€ะตะดะฐะฝะพ ะฒ ะฟะฐั€ะฐะผะตั‚ั€ `commons`, ั– ะทะผะพะถะต ะดะพะฟะพะผะฐะณะฐั‚ะธ ะท ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัะผ, ะฟะตั€ะตะฒั–ั€ะบะฐะผะธ ั‚ะธะฟั–ะฒ ั‚ะพั‰ะพ: + + + +## ะกะบะพั€ะพั‡ะตะฝะฝั { #shortcut } + +ะะปะต ะฒะธ ะฑะฐั‡ะธั‚ะต, ั‰ะพ ั‚ัƒั‚ ะผะฐั”ะผะพ ะดะตัะบะต ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ - `CommonQueryParams` ะฟะธัˆะตะผะพ ะดะฒั–ั‡ั–: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI** ะฝะฐะดะฐั” ัะบะพั€ะพั‡ะตะฝะฝั ะดะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ, ะบะพะปะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ - ั†ะต ัะฐะผะต ะบะปะฐั, ัะบะธะน **FastAPI** ยซะฒะธะบะปะธั‡ะตยป, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะตะบะทะตะผะฟะปัั€ ั†ัŒะพะณะพ ะบะปะฐััƒ. + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั‚ะฐะบ: + +ะ—ะฐะผั–ัั‚ัŒ ั‚ะพะณะพ ั‰ะพะฑ ะฟะธัะฐั‚ะธ: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +โ€ฆะฝะฐะฟะธัˆั–ั‚ัŒ: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะฐั€ั–ะฐะฝั‚ัƒ ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +ะ’ะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ะทะฐะปะตะถะฝั–ัั‚ัŒ ัะบ ั‚ะธะฟ ะฟะฐั€ะฐะผะตั‚ั€ะฐ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Depends()` ะฑะตะท ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ ั‰ะพะฑ ะฒะดั€ัƒะณะต ะฟะธัะฐั‚ะธ ะฟะพะฒะฝะธะน ะบะปะฐั ัƒัะตั€ะตะดะธะฝั– `Depends(CommonQueryParams)`. + +ะขะพะน ัะฐะผะธะน ะฟั€ะธะบะปะฐะด ะฒะธะณะปัะดะฐั‚ะธะผะต ั‚ะฐะบ: + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +โ€ฆั– **FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ั€ะพะฑะธั‚ะธ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ั†ะต ะทะดะฐั”ั‚ัŒัั ะทะฐะฟะปัƒั‚ะฐะฝั–ัˆะธะผ, ะฝั–ะถ ะบะพั€ะธัะฝะธะผ, ะฟั€ะพัั‚ะพ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั†ะต - ะฒะพะฝะพ ะฝะต ั” ะพะฑะพะฒโ€™ัะทะบะพะฒะธะผ. + +ะฆะต ะปะธัˆะต ัะบะพั€ะพั‡ะตะฝะฝั. ะะดะถะต **FastAPI** ะดะฑะฐั” ะฟั€ะพ ะผั–ะฝั–ะผั–ะทะฐั†ั–ัŽ ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ. + +/// diff --git a/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 0000000000..4614c626c5 --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# ะ—ะฐะปะตะถะฝะพัั‚ั– ะฒ ะดะตะบะพั€ะฐั‚ะพั€ะฐั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ { #dependencies-in-path-operation-decorators } + +ะ†ะฝะพะดั– ะฒะฐะผ ะฝะฐัะฟั€ะฐะฒะดั– ะฝะต ะฟะพั‚ั€ั–ะฑะฝะต ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะฟะพะฒะตั€ั‚ะฐั” ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัƒ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะะฑะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒะทะฐะณะฐะปั– ะฝะต ะฟะพะฒะตั€ั‚ะฐั” ะทะฝะฐั‡ะตะฝะฝั. + +ะะปะต ั—ั— ะฒัะต ะพะดะฝะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพะฝะฐั‚ะธ/ะพะฟั€ะฐั†ัŽะฒะฐั‚ะธ. + +ะ”ะปั ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบั–ะฒ, ะทะฐะผั–ัั‚ัŒ ะพะณะพะปะพัˆะตะฝะฝั ะฟะฐั€ะฐะผะตั‚ั€ะฐ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะท `Depends`, ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ `list` `dependencies` ะดะพ *ะดะตะบะพั€ะฐั‚ะพั€ะฐ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +## ะ”ะพะดะฐะนั‚ะต `dependencies` ะดะพ *ะดะตะบะพั€ะฐั‚ะพั€ะฐ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* { #add-dependencies-to-the-path-operation-decorator } + +*ะ”ะตะบะพั€ะฐั‚ะพั€ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฟั€ะธะนะผะฐั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะน ะฐั€ะณัƒะผะตะฝั‚ `dependencies`. + +ะฆะต ะผะฐั” ะฑัƒั‚ะธ `list` ะท `Depends()`: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} + +ะฆั– ะทะฐะปะตะถะฝะพัั‚ั– ะฑัƒะดัƒั‚ัŒ ะฒะธะบะพะฝะฐะฝั–/ะพะฑั€ะพะฑะปะตะฝั– ั‚ะฐะบ ัะฐะผะพ, ัะบ ะทะฒะธั‡ะฐะนะฝั– ะทะฐะปะตะถะฝะพัั‚ั–. ะะปะต ั—ั…ะฝั– ะทะฝะฐั‡ะตะฝะฝั (ัะบั‰ะพ ั‰ะพััŒ ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒ) ะฝะต ะฟะตั€ะตะดะฐะฒะฐั‚ะธะผัƒั‚ัŒัั ัƒ ะฒะฐัˆัƒ *ั„ัƒะฝะบั†ั–ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ะตัะบั– ั€ะตะดะฐะบั‚ะพั€ะธ ะฟะตั€ะตะฒั–ั€ััŽั‚ัŒ ะฝะตะฒะธะบะพั€ะธัั‚ะฐะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ั„ัƒะฝะบั†ั–ะน ั– ะฟะพะบะฐะทัƒัŽั‚ัŒ ั—ั… ัะบ ะฟะพะผะธะปะบะธ. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั†ั– `dependencies` ัƒ *ะดะตะบะพั€ะฐั‚ะพั€ั– ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธ ะผะพะถะตั‚ะต ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ั—ั… ะฒะธะบะพะฝะฐะฝะฝั ั‚ะฐ ะฒะพะดะฝะพั‡ะฐั ัƒะฝะธะบะฝัƒั‚ะธ ะฟะพะผะธะปะพะบ ั€ะตะดะฐะบั‚ะพั€ะฐ/ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. + +ะฆะต ั‚ะฐะบะพะถ ะผะพะถะต ะดะพะฟะพะผะพะณั‚ะธ ัƒะฝะธะบะฝัƒั‚ะธ ะฟะปัƒั‚ะฐะฝะธะฝะธ ะดะปั ะฝะพะฒะธั… ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ, ัะบั– ะฑะฐั‡ะฐั‚ัŒ ะฝะตะฒะธะบะพั€ะธัั‚ะฐะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ ัƒ ะฒะฐัˆะพะผัƒ ะบะพะดั– ะน ะผะพะถัƒั‚ัŒ ะฒะธั€ั–ัˆะธั‚ะธ, ั‰ะพ ะฒั–ะฝ ะทะฐะนะฒะธะน. + +/// + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฒะธะณะฐะดะฐะฝั– ะฒะปะฐัะฝั– ะทะฐะณะพะปะพะฒะบะธ `X-Key` ั– `X-Token`. + +ะะปะต ะฒ ั€ะตะฐะปัŒะฝะธั… ะฒะธะฟะฐะดะบะฐั…, ะฟั–ะด ั‡ะฐั ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะฑะตะทะฟะตะบะธ, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฑั–ะปัŒัˆะต ะบะพั€ะธัั‚ั–, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒะฑัƒะดะพะฒะฐะฝั– [ะ†ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะฑะตะทะฟะตะบะธ (ะฝะฐัั‚ัƒะฟะฝะธะน ั€ะพะทะดั–ะป)](../security/index.md){.internal-link target=_blank}. + +/// + +## ะŸะพะผะธะปะบะธ ะทะฐะปะตะถะฝะพัั‚ะตะน ั– ะทะฝะฐั‡ะตะฝะฝั, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒัั { #dependencies-errors-and-return-values } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– *ั„ัƒะฝะบั†ั–ั—* ะทะฐะปะตะถะฝะพัั‚ะตะน, ั‰ะพ ะน ะทะฐะทะฒะธั‡ะฐะน. + +### ะ’ะธะผะพะณะธ ะทะฐะปะตะถะฝะพัั‚ะตะน { #dependency-requirements } + +ะ’ะพะฝะธ ะผะพะถัƒั‚ัŒ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะฒะธะผะพะณะธ ะดะพ ะทะฐะฟะธั‚ัƒ (ะฝะฐะฟั€ะธะบะปะฐะด, ะทะฐะณะพะปะพะฒะบะธ) ะฐะฑะพ ั–ะฝัˆั– ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} + +### ะŸั–ะดั–ะนะผะฐั‚ะธ ะฒะธะฝัั‚ะบะธ { #raise-exceptions } + +ะฆั– ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ `raise` ะฒะธะฝัั‚ะบะธ, ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะทะฒะธั‡ะฐะนะฝั– ะทะฐะปะตะถะฝะพัั‚ั–: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} + +### ะ—ะฝะฐั‡ะตะฝะฝั, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒัั { #return-values } + +ะ’ะพะฝะธ ะผะพะถัƒั‚ัŒ ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะทะฝะฐั‡ะตะฝะฝั ะฐะฑะพ ะฝั– - ั†ั– ะทะฝะฐั‡ะตะฝะฝั ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผัƒั‚ัŒัั. + +ะžั‚ะถะต, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะทะฒะธั‡ะฐะนะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ัะบะฐ ะฟะพะฒะตั€ั‚ะฐั” ะทะฝะฐั‡ะตะฝะฝั), ัะบัƒ ะฒะถะต ะทะฐัั‚ะพัะพะฒัƒั”ั‚ะต ะดะตั–ะฝะดะต, ั– ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะฝะต ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ, ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะฐ: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะดะปั ะณั€ัƒะฟะธ ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ { #dependencies-for-a-group-of-path-operations } + +ะ”ะฐะปั–, ั‡ะธั‚ะฐัŽั‡ะธ ะฟั€ะพ ัั‚ั€ัƒะบั‚ัƒั€ัƒะฒะฐะฝะฝั ะฒะตะปะธะบะธั… ะทะฐัั‚ะพััƒะฝะบั–ะฒ ([ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ - ะดะตะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ](../../tutorial/bigger-applications.md){.internal-link target=_blank}), ะผะพะถะปะธะฒะพ ะท ะบั–ะปัŒะบะพะผะฐ ั„ะฐะนะปะฐะผะธ, ะฒะธ ะดั–ะทะฝะฐั”ั‚ะตัั, ัะบ ะพะณะพะปะพัะธั‚ะธ ะพะดะธะฝ ะฟะฐั€ะฐะผะตั‚ั€ `dependencies` ะดะปั ะณั€ัƒะฟะธ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +## ะ“ะปะพะฑะฐะปัŒะฝั– ะทะฐะปะตะถะฝะพัั‚ั– { #global-dependencies } + +ะ”ะฐะปั– ะผะธ ะฟะพะฑะฐั‡ะธะผะพ, ัะบ ะดะพะดะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– ะดะพ ะฒััŒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`, ั‰ะพะฑ ะฒะพะฝะธ ะทะฐัั‚ะพัะพะฒัƒะฒะฐะปะธัั ะดะพ ะบะพะถะฝะพั— *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. diff --git a/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 0000000000..70d4210a1c --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,289 @@ +# ะ—ะฐะปะตะถะฝะพัั‚ั– ะท yield { #dependencies-with-yield } + +FastAPI ะฟั–ะดั‚ั€ะธะผัƒั” ะทะฐะปะตะถะฝะพัั‚ั–, ัะบั– ะฒะธะบะพะฝัƒัŽั‚ัŒ ะดะตัะบั– ะดะพะดะฐั‚ะบะพะฒั– ะบั€ะพะบะธ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั. + +ะฉะพะฑ ั†ะต ะทั€ะพะฑะธั‚ะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `yield` ะทะฐะผั–ัั‚ัŒ `return` ั– ะฝะฐะฟะธัˆั–ั‚ัŒ ะดะพะดะฐั‚ะบะพะฒั– ะบั€ะพะบะธ (ะบะพะด) ะฟั–ัะปั ะฝัŒะพะณะพ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตััŒ, ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `yield` ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท ะฝะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ. + +/// + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ‘ัƒะดัŒ-ัะบะฐ ั„ัƒะฝะบั†ั–ั, ัะบัƒ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท: + +* `@contextlib.contextmanager` ะฐะฑะพ +* `@contextlib.asynccontextmanager` + +ะฑัƒะดะต ะฟั€ะธะดะฐั‚ะฝะพัŽ ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒ **FastAPI**. + +ะะฐัะฟั€ะฐะฒะดั– FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั†ั– ะดะฒะฐ ะดะตะบะพั€ะฐั‚ะพั€ะธ ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ. + +/// + +## ะ—ะฐะปะตะถะฝั–ัั‚ัŒ ะฑะฐะทะธ ะดะฐะฝะธั… ะท `yield` { #a-database-dependency-with-yield } + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะต, ั‰ะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ัะตัั–ัŽ ะฑะฐะทะธ ะดะฐะฝะธั… ั– ะทะฐะบั€ะธั‚ะธ ั—ั— ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั. + +ะŸะตั€ะตะด ัั‚ะฒะพั€ะตะฝะฝัะผ ะฒั–ะดะฟะพะฒั–ะดั– ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะปะธัˆะต ะบะพะด ะดะพ ั– ะฒะบะปัŽั‡ะฝะพ ะท ะพะฟะตั€ะฐั‚ะพั€ะพะผ `yield`: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} + +ะ—ะฝะฐั‡ะตะฝะฝั, ะฟะตั€ะตะดะฐะฝะต `yield`, ะฒะฟั€ะพะฒะฐะดะถัƒั”ั‚ัŒัั ะฒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ั‚ะฐ ั–ะฝัˆั– ะทะฐะปะตะถะฝะพัั‚ั–: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} + +ะšะพะด ะฟั–ัะปั ะพะฟะตั€ะฐั‚ะพั€ะฐ `yield` ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟั–ัะปั ะฒั–ะดะฟะพะฒั–ะดั–: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะบ `async`, ั‚ะฐะบ ั– ะทะฒะธั‡ะฐะนะฝั– ั„ัƒะฝะบั†ั–ั—. + +**FastAPI** ะทั€ะพะฑะธั‚ัŒ ัƒัะต ะฟั€ะฐะฒะธะปัŒะฝะพ ะท ะบะพะถะฝะพัŽ ะท ะฝะธั…, ั‚ะฐะบ ัะฐะผะพ ัะบ ั– ะทั– ะทะฒะธั‡ะฐะนะฝะธะผะธ ะทะฐะปะตะถะฝะพัั‚ัะผะธ. + +/// + +## ะ—ะฐะปะตะถะฝั–ัั‚ัŒ ะท `yield` ั‚ะฐ `try` { #a-dependency-with-yield-and-try } + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฑะปะพะบ `try` ะฒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฑัƒะดัŒ-ัะบะธะน ะฒะธะฝัั‚ะพะบ, ัะบะธะน ะฑัƒะฒ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ะฟั–ะด ั‡ะฐั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั–. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ัะบะธะนััŒ ะบะพะด ะดะตััŒ ะฟะพัะตั€ะตะดะธะฝั–, ะฒ ั–ะฝัˆั–ะน ะทะฐะปะตะถะฝะพัั‚ั– ะฐะฑะพ ะฒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะทั€ะพะฑะธะฒ ยซrollbackยป ั‚ั€ะฐะฝะทะฐะบั†ั–ั— ะฑะฐะทะธ ะดะฐะฝะธั… ะฐะฑะพ ัั‚ะฒะพั€ะธะฒ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะฒะธะฝัั‚ะพะบ, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ั†ะตะน ะฒะธะฝัั‚ะพะบ ัƒ ัะฒะพั—ะน ะทะฐะปะตะถะฝะพัั‚ั–. + +ะขะพะถ ะฒะธ ะผะพะถะตั‚ะต ะพะฑั€ะพะฑะธั‚ะธ ั†ะตะน ะบะพะฝะบั€ะตั‚ะฝะธะน ะฒะธะฝัั‚ะพะบ ัƒัะตั€ะตะดะธะฝั– ะทะฐะปะตะถะฝะพัั‚ั– ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `except SomeException`. + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `finally`, ั‰ะพะฑ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ะฒะธะบะพะฝะฐะฝะฝั ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธั… ะบั€ะพะบั–ะฒ ะฝะตะทะฐะปะตะถะฝะพ ะฒั–ะด ั‚ะพะณะพ, ะฑัƒะฒ ะฒะธะฝัั‚ะพะบ ั‡ะธ ะฝั–. + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} + +## ะŸั–ะดะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` { #sub-dependencies-with-yield } + +ะ’ะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั– ั‚ะฐ ยซะดะตั€ะตะฒะฐยป ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ะตะน ะฑัƒะดัŒ-ัะบะพะณะพ ั€ะพะทะผั–ั€ัƒ ั– ั„ะพั€ะผะธ, ั– ะฑัƒะดัŒ-ัะบะฐ ะฐะฑะพ ะฒัั– ะท ะฝะธั… ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `yield`. + +**FastAPI** ะณะฐั€ะฐะฝั‚ัƒั”, ั‰ะพ ยซexit codeยป ัƒ ะบะพะถะฝั–ะน ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะพ ะฒ ะฟั€ะฐะฒะธะปัŒะฝะพะผัƒ ะฟะพั€ัะดะบัƒ. + +ะะฐะฟั€ะธะบะปะฐะด, `dependency_c` ะผะพะถะต ะทะฐะปะตะถะฐั‚ะธ ะฒั–ะด `dependency_b`, ะฐ `dependency_b` - ะฒั–ะด `dependency_a`: + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} + +ะ† ะฒัั– ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `yield`. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `dependency_c`, ั‰ะพะฑ ะฒะธะบะพะฝะฐั‚ะธ ัะฒั–ะน ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด, ะฟะพั‚ั€ะตะฑัƒั”, ั‰ะพะฑ ะทะฝะฐั‡ะตะฝะฝั ะท `dependency_b` (ั‚ัƒั‚ `dep_b`) ะฒัะต ั‰ะต ะฑัƒะปะพ ะดะพัั‚ัƒะฟะฝะธะผ. + +ะ†, ัƒ ัะฒะพัŽ ั‡ะตั€ะณัƒ, `dependency_b` ะฟะพั‚ั€ะตะฑัƒั”, ั‰ะพะฑ ะทะฝะฐั‡ะตะฝะฝั ะท `dependency_a` (ั‚ัƒั‚ `dep_a`) ะฑัƒะปะพ ะดะพัั‚ัƒะฟะฝะธะผ ะดะปั ัะฒะพะณะพ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะพะณะพ ะบะพะดัƒ. + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะดะตัะบั– ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ะฐ ั–ะฝัˆั– - ะท `return`, ั– ั‡ะฐัั‚ะธะฝะฐ ะท ะฝะธั… ะผะพะถะต ะทะฐะปะตะถะฐั‚ะธ ะฒั–ะด ั–ะฝัˆะธั…. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะพะดะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ัะบะฐ ะฒะธะผะฐะณะฐั” ะบั–ะปัŒะบะฐ ั–ะฝัˆะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield` ั‚ะพั‰ะพ. + +ะ’ะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ะบะพะผะฑั–ะฝะฐั†ั–ั— ะทะฐะปะตะถะฝะพัั‚ะตะน, ัะบั– ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–. + +**FastAPI** ะฟะพะดะฑะฐั”, ั‰ะพะฑ ัƒัะต ะฒะธะบะพะฝัƒะฒะฐะปะพัั ะฒ ะฟั€ะฐะฒะธะปัŒะฝะพะผัƒ ะฟะพั€ัะดะบัƒ. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะฆะต ะฟั€ะฐั†ัŽั” ะทะฐะฒะดัะบะธ ะœะตะฝะตะดะถะตั€ะฐะผ ะบะพะฝั‚ะตะบัั‚ัƒ Python. + +**FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั—ั… ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ, ั‰ะพะฑ ะดะพััะณั‚ะธ ั†ัŒะพะณะพ. + +/// + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั‚ะฐ `HTTPException` { #dependencies-with-yield-and-httpexception } + +ะ’ะธ ะฑะฐั‡ะธะปะธ, ั‰ะพ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั– ะผะฐั‚ะธ ะฑะปะพะบะธ `try`, ัะบั– ะฝะฐะผะฐะณะฐัŽั‚ัŒัั ะฒะธะบะพะฝะฐั‚ะธ ะดะตัะบะธะน ะบะพะด, ะฐ ะฟะพั‚ั–ะผ ะทะฐะฟัƒัะบะฐัŽั‚ัŒ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะฟั–ัะปั `finally`. + +ะขะฐะบะพะถ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `except`, ั‰ะพะฑ ะฟะตั€ะตั…ะพะฟะธั‚ะธ ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ะฒะธะฝัั‚ะพะบ ั– ั‰ะพััŒ ั–ะท ะฝะธะผ ะทั€ะพะฑะธั‚ะธ. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฟั–ะดะฝัั‚ะธ ั–ะฝัˆะธะน ะฒะธะฝัั‚ะพะบ, ัะบ-ะพั‚ `HTTPException`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะดะพะฒะพะปั– ะฟั€ะพััƒะฝัƒั‚ะฐ ั‚ะตั…ะฝั–ะบะฐ, ั– ะฒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะพะฝะฐ ะฒะฐะผ ะฝะต ะทะฝะฐะดะพะฑะธั‚ัŒัั, ะฐะดะถะต ะฒะธ ะผะพะถะตั‚ะต ะฟั–ะดะฝั–ะผะฐั‚ะธ ะฒะธะฝัั‚ะบะธ (ะฒะบะปัŽั‡ะฝะพ ะท `HTTPException`) ะฒัะตั€ะตะดะธะฝั– ั–ะฝัˆะพะณะพ ะบะพะดัƒ ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ, ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะะปะต ะฒะพะฝะฐ ั”, ัะบั‰ะพ ะฒะฐะผ ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ. ๐Ÿค“ + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟะตั€ะตั…ะพะฟะปัŽะฒะฐั‚ะธ ะฒะธะฝัั‚ะบะธ ั‚ะฐ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะฝะฐ ั—ั… ะพัะฝะพะฒั– ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ, ัั‚ะฒะพั€ั–ั‚ัŒ [ะšะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน ะพะฑั€ะพะฑะฝะธะบ ะฒะธะฝัั‚ะบั–ะฒ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั‚ะฐ `except` { #dependencies-with-yield-and-except } + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตั…ะพะฟะปัŽั”ั‚ะต ะฒะธะฝัั‚ะพะบ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ `except` ัƒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield` ั– ะฝะต ะฟั–ะดะฝั–ะผะฐั”ั‚ะต ะนะพะณะพ ะทะฝะพะฒัƒ (ะฐะฑะพ ะฝะต ะฟั–ะดะฝั–ะผะฐั”ั‚ะต ะฝะพะฒะธะน ะฒะธะฝัั‚ะพะบ), FastAPI ะฝะต ะทะผะพะถะต ะฟะพะผั–ั‚ะธั‚ะธ, ั‰ะพ ัั‚ะฐะฒัั ะฒะธะฝัั‚ะพะบ, ั‚ะฐะบ ัะฐะผะพ ัะบ ั†ะต ะฑัƒะปะพ ะฑ ัƒ ะทะฒะธั‡ะฐะนะฝะพะผัƒ Python: + +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะบะปั–ั”ะฝั‚ ะฟะพะฑะฐั‡ะธั‚ัŒ ะฒั–ะดะฟะพะฒั–ะดัŒ *HTTP 500 Internal Server Error*, ัะบ ั– ะผะฐั” ะฑัƒั‚ะธ, ะท ะพะณะปัะดัƒ ะฝะฐ ั‚ะต, ั‰ะพ ะผะธ ะฝะต ะฟั–ะดะฝั–ะผะฐั”ะผะพ `HTTPException` ะฐะฑะพ ะฟะพะดั–ะฑะฝะธะน ะฒะธะฝัั‚ะพะบ, ะฐะปะต ะฝะฐ ัะตั€ะฒะตั€ั– **ะฝะต ะฑัƒะดะต ะถะพะดะฝะธั… ะปะพะณั–ะฒ** ั‡ะธ ั–ะฝัˆะธั… ะพะทะฝะฐะบ ั‚ะพะณะพ, ั‰ะพ ั†ะต ะฑัƒะปะฐ ะทะฐ ะฟะพะผะธะปะบะฐ. ๐Ÿ˜ฑ + +### ะ—ะฐะฒะถะดะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `raise` ัƒ ะทะฐะปะตะถะฝะพัั‚ัั… ะท `yield` ั‚ะฐ `except` { #always-raise-in-dependencies-with-yield-and-except } + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตั…ะพะฟะปัŽั”ั‚ะต ะฒะธะฝัั‚ะพะบ ัƒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ัะบั‰ะพ ั‚ั–ะปัŒะบะธ ะฒะธ ะฝะต ะฟั–ะดะฝั–ะผะฐั”ั‚ะต ั–ะฝัˆะธะน `HTTPException` ะฐะฑะพ ะฟะพะดั–ะฑะฝะธะน, **ะฒะฐะผ ัะปั–ะด ะฟะพะฒั‚ะพั€ะฝะพ ะฟั–ะดะฝัั‚ะธ ะฟะพั‡ะฐั‚ะบะพะฒะธะน ะฒะธะฝัั‚ะพะบ**. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะพะฒั‚ะพั€ะฝะพ ะฟั–ะดะฝัั‚ะธ ั‚ะพะน ัะฐะผะธะน ะฒะธะฝัั‚ะพะบ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `raise`: + +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} + +ะขะตะฟะตั€ ะบะปั–ั”ะฝั‚ ะพั‚ั€ะธะผะฐั” ั‚ัƒ ัะฐะผัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ *HTTP 500 Internal Server Error*, ะฐะปะต ัะตั€ะฒะตั€ ะผะฐั‚ะธะผะต ะฝะฐัˆ ะบะพั€ะธัั‚ัƒะฒะฐั†ัŒะบะธะน `InternalError` ัƒ ะปะพะณะฐั…. ๐Ÿ˜Ž + +## ะ’ะธะบะพะฝะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield` { #execution-of-dependencies-with-yield } + +ะŸะพัะปั–ะดะพะฒะฝั–ัั‚ัŒ ะฒะธะบะพะฝะฐะฝะฝั ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบะฐ, ัะบ ะฝะฐ ั†ั–ะน ะดั–ะฐะณั€ะฐะผั–. ะงะฐั ั‚ะตั‡ะต ะทะฒะตั€ั…ัƒ ะฒะฝะธะท. ะ† ะบะพะถะฝะฐ ะบะพะปะพะฝะบะฐ - ั†ะต ะพะดะฝะฐ ะท ั‡ะฐัั‚ะธะฝ, ั‰ะพ ะฒะทะฐั”ะผะพะดั–ัŽั‚ัŒ ะฐะฑะพ ะฒะธะบะพะฝัƒัŽั‚ัŒ ะบะพะด. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ›ะธัˆะต **ะพะดะฝะฐ ะฒั–ะดะฟะพะฒั–ะดัŒ** ะฑัƒะดะต ะฝะฐะดั–ัะปะฐะฝะฐ ะบะปั–ั”ะฝั‚ัƒ. ะฆะต ะผะพะถะต ะฑัƒั‚ะธ ะพะดะฝะฐ ะท ะฟะพะผะธะปะบะพะฒะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ะฐะฑะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฒั–ะด *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +ะŸั–ัะปั ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฝั ะพะดะฝั–ั”ั— ะท ั†ะธั… ะฒั–ะดะฟะพะฒั–ะดะตะน ั–ะฝัˆัƒ ะฒั–ะดะฟั€ะฐะฒะธั‚ะธ ะฝะต ะผะพะถะฝะฐ. + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฟั–ะดะฝั–ะผะฐั”ั‚ะต ะฑัƒะดัŒ-ัะบะธะน ะฒะธะฝัั‚ะพะบ ัƒ ะบะพะดั– ะท *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒั–ะฝ ะฑัƒะดะต ะฟะตั€ะตะดะฐะฝะธะน ัƒ ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ะฒะบะปัŽั‡ะฝะพ ะท `HTTPException`. ะฃ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะฟะพะฒั‚ะพั€ะฝะพ ะฟั–ะดะฝัั‚ะธ ั‚ะพะน ัะฐะผะธะน ะฒะธะฝัั‚ะพะบ ะฐะฑะพ ะฝะพะฒะธะน ั–ะท ะทะฐะปะตะถะฝะพัั‚ั– ะท `yield`, ั‰ะพะฑ ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะนะพะณะพ ะบะพั€ะตะบั‚ะฝะพ ะพะฑั€ะพะฑะปะตะฝะพ. + +/// + +## ะ ะฐะฝะฝั–ะน ะฒะธั…ั–ะด ั– `scope` { #early-exit-and-scope } + +ะ—ะฐะทะฒะธั‡ะฐะน ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield` ะฒะธะบะพะฝัƒั”ั‚ัŒัั **ะฟั–ัะปั ั‚ะพะณะพ**, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฝะฐะดั–ัะปะฐะฝะพ ะบะปั–ั”ะฝั‚ัƒ. + +ะะปะต ัะบั‰ะพ ะฒะธ ะทะฝะฐั”ั‚ะต, ั‰ะพ ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟั–ัะปั ะฟะพะฒะตั€ะฝะตะฝะฝั ะท *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `Depends(scope="function")`, ั‰ะพะฑ ัะบะฐะทะฐั‚ะธ FastAPI, ั‰ะพ ัะปั–ะด ะทะฐะบั€ะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟั–ัะปั ะฟะพะฒะตั€ะฝะตะฝะฝั ะท *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฐะปะต **ะดะพ** ะฝะฐะดัะธะปะฐะฝะฝั **ะฒั–ะดะฟะพะฒั–ะดั–**. + +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} + +`Depends()` ะฟั€ะธะนะผะฐั” ะฟะฐั€ะฐะผะตั‚ั€ `scope`, ัะบะธะน ะผะพะถะต ะฑัƒั‚ะธ: + +* `"function"`: ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟะตั€ะตะด *ั„ัƒะฝะบั†ั–ั”ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั‰ะพ ะพะฑั€ะพะฑะปัั” ะทะฐะฟะธั‚, ะทะฐะฒะตั€ัˆะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟั–ัะปั ะทะฐะฒะตั€ัˆะตะฝะฝั *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฐะปะต **ะดะพ** ั‚ะพะณะพ, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฐ ะบะปั–ั”ะฝั‚ัƒ. ะขะพะฑั‚ะพ ั„ัƒะฝะบั†ั–ั ะทะฐะปะตะถะฝะพัั‚ั– ะฑัƒะดะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั **ะฝะฐะฒะบะพะปะพ** *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— **ัˆะปัั…ัƒ***. +* `"request"`: ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟะตั€ะตะด *ั„ัƒะฝะบั†ั–ั”ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั‰ะพ ะพะฑั€ะพะฑะปัั” ะทะฐะฟะธั‚ (ะฟะพะดั–ะฑะฝะพ ะดะพ `"function"`), ะฐะปะต ะทะฐะฒะตั€ัˆะธั‚ะธ **ะฟั–ัะปั** ั‚ะพะณะพ, ัะบ ะฒั–ะดะฟะพะฒั–ะดัŒ ะฑัƒะดะต ะฒั–ะดะฟั€ะฐะฒะปะตะฝะฐ ะบะปั–ั”ะฝั‚ัƒ. ะขะพะฑั‚ะพ ั„ัƒะฝะบั†ั–ั ะทะฐะปะตะถะฝะพัั‚ั– ะฑัƒะดะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธัั **ะฝะฐะฒะบะพะปะพ** ั†ะธะบะปัƒ **ะทะฐะฟะธั‚ัƒ** ั‚ะฐ ะฒั–ะดะฟะพะฒั–ะดั–. + +ะฏะบั‰ะพ ะฝะต ะฒะบะฐะทะฐะฝะพ, ั– ะทะฐะปะตะถะฝั–ัั‚ัŒ ะผะฐั” `yield`, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `scope` ะดะพั€ั–ะฒะฝัŽั” `"request"`. + +### `scope` ะดะปั ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ะตะน { #scope-for-sub-dependencies } + +ะšะพะปะธ ะฒะธ ะพะณะพะปะพัˆัƒั”ั‚ะต ะทะฐะปะตะถะฝั–ัั‚ัŒ ั–ะท `scope="request"` (ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ), ะฑัƒะดัŒ-ัะบะฐ ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ ั‚ะฐะบะพะถ ะผะฐั” ะผะฐั‚ะธ `scope` ั€ั–ะฒะฝะธะน `"request"`. + +ะะปะต ะทะฐะปะตะถะฝั–ัั‚ัŒ ะท `scope` ั€ั–ะฒะฝะธะผ `"function"` ะผะพะถะต ะผะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– ะท `scope` `"function"` ั– `scope` `"request"`. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะฑัƒะดัŒ-ัะบะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะผะฐั” ะฑัƒั‚ะธ ะทะดะฐั‚ะฝะพัŽ ะฒะธะบะพะฝะฐั‚ะธ ัะฒั–ะน ะทะฐะฒะตั€ัˆะฐะปัŒะฝะธะน ะบะพะด ั€ะฐะฝั–ัˆะต ะทะฐ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–, ะพัะบั–ะปัŒะบะธ ะฒะพะฝะฐ ะผะพะถะต ะฒัะต ั‰ะต ะฟะพั‚ั€ะตะฑัƒะฒะฐั‚ะธ ั—ั… ะฟั–ะด ั‡ะฐั ัะฒะพะณะพ ะทะฐะฒะตั€ัˆะฐะปัŒะฝะพะณะพ ะบะพะดัƒ. + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: โœ… Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: โœ… Dependency closed +``` + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield`, `HTTPException`, `except` ั– ั„ะพะฝะพะฒะธะผะธ ะทะฐะดะฐั‡ะฐะผะธ { #dependencies-with-yield-httpexception-except-and-background-tasks } + +ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield` ะตะฒะพะปัŽั†ั–ะพะฝัƒะฒะฐะปะธ ะท ั‡ะฐัะพะผ, ั‰ะพะฑ ะฟะพะบั€ะธั‚ะธ ั€ั–ะทะฝั– ัั†ะตะฝะฐั€ั–ั— ั‚ะฐ ะฒะธะฟั€ะฐะฒะธั‚ะธ ะดะตัะบั– ะฟั€ะพะฑะปะตะผะธ. + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั, ั‰ะพ ะทะผั–ะฝัŽะฒะฐะปะพัั ะฒ ั€ั–ะทะฝะธั… ะฒะตั€ัั–ัั… FastAPI, ะฟั€ะพั‡ะธั‚ะฐะนั‚ะต ะฟั€ะพ ั†ะต ะฒ ะฟั€ะพััƒะฝัƒั‚ะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ: [ะ ะพะทัˆะธั€ะตะฝั– ะทะฐะปะตะถะฝะพัั‚ั– - ะ—ะฐะปะตะถะฝะพัั‚ั– ะท `yield`, `HTTPException`, `except` ั– ั„ะพะฝะพะฒะธะผะธ ะทะฐะดะฐั‡ะฐะผะธ](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}. +## ะœะตะฝะตะดะถะตั€ะธ ะบะพะฝั‚ะตะบัั‚ัƒ { #context-managers } + +### ะฉะพ ั‚ะฐะบะต ยซะœะตะฝะตะดะถะตั€ะธ ะบะพะฝั‚ะตะบัั‚ัƒยป { #what-are-context-managers } + +ยซะœะตะฝะตะดะถะตั€ะธ ะบะพะฝั‚ะตะบัั‚ัƒยป - ั†ะต ะฑัƒะดัŒ-ัะบั– Python-ะพะฑ'ั”ะบั‚ะธ, ัะบั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒ ะพะฟะตั€ะฐั‚ะพั€ั– `with`. + +ะะฐะฟั€ะธะบะปะฐะด, ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `with`, ั‰ะพะฑ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ั„ะฐะนะป: + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +ะŸั–ะด ะบะฐะฟะพั‚ะพะผ `open("./somefile.txt")` ัั‚ะฒะพั€ัŽั” ะพะฑ'ั”ะบั‚, ัะบะธะน ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซะœะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒยป. + +ะšะพะปะธ ะฑะปะพะบ `with` ะทะฐะฒะตั€ัˆัƒั”ั‚ัŒัั, ะฒั–ะฝ ะณะฐั€ะฐะฝั‚ัƒั” ะทะฐะบั€ะธั‚ั‚ั ั„ะฐะนะปัƒ, ะฝะฐะฒั–ั‚ัŒ ัะบั‰ะพ ะฑัƒะปะธ ะฒะธะฝัั‚ะบะธ. + +ะšะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะทะฐะปะตะถะฝั–ัั‚ัŒ ะท `yield`, **FastAPI** ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ัั‚ะฒะพั€ะธั‚ัŒ ะดะปั ะฝะตั— ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ ะน ะฟะพั”ะดะฝะฐั” ะนะพะณะพ ะท ั–ะฝัˆะธะผะธ ะฟะพะฒ'ัะทะฐะฝะธะผะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ. + +### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะผะตะฝะตะดะถะตั€ั–ะฒ ะบะพะฝั‚ะตะบัั‚ัƒ ะฒ ะทะฐะปะตะถะฝะพัั‚ัั… ะท `yield` { #using-context-managers-in-dependencies-with-yield } + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะฆะต, ะทะฐะณะฐะปะพะผ, ยซะฟั€ะพััƒะฝัƒั‚ะฐยป ั–ะดะตั. + +ะฏะบั‰ะพ ะฒะธ ั‚ั–ะปัŒะบะธ ะฟะพั‡ะธะฝะฐั”ั‚ะต ะท **FastAPI**, ะผะพะถะปะธะฒะพ, ะฒะฐั€ั‚ะพ ะฝะฐั€ะฐะทั– ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะต. + +/// + +ะฃ Python ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะœะตะฝะตะดะถะตั€ะธ ะบะพะฝั‚ะตะบัั‚ัƒ, ัั‚ะฒะพั€ะธะฒัˆะธ ะบะปะฐั ั–ะท ะดะฒะพะผะฐ ะผะตั‚ะพะดะฐะผะธ: `__enter__()` ั– `__exit__()`. + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั… ัƒัะตั€ะตะดะธะฝั– ะทะฐะปะตะถะฝะพัั‚ะตะน **FastAPI** ะท `yield`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ +`with` ะฐะฑะพ `async with` ัƒ ัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— ะทะฐะปะตะถะฝะพัั‚ั–: + +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ†ะฝัˆะธะน ัะฟะพัั–ะฑ ัั‚ะฒะพั€ะธั‚ะธ ะผะตะฝะตะดะถะตั€ ะบะพะฝั‚ะตะบัั‚ัƒ: + +* `@contextlib.contextmanager` ะฐะฑะพ +* `@contextlib.asynccontextmanager` + +ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั—ั… ะดะปั ะดะตะบะพั€ัƒะฒะฐะฝะฝั ั„ัƒะฝะบั†ั–ั— ะท ะพะดะฝะธะผ `yield`. + +ะกะฐะผะต ั†ะต **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ ะดะปั ะทะฐะปะตะถะฝะพัั‚ะตะน ะท `yield`. + +ะะปะต ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั†ั– ะดะตะบะพั€ะฐั‚ะพั€ะธ ะดะปั ะทะฐะปะตะถะฝะพัั‚ะตะน FastAPI (ั– ะฝะต ะฒะฐั€ั‚ะพ). + +FastAPI ะทั€ะพะฑะธั‚ัŒ ั†ะต ะทะฐ ะฒะฐั ะฒะฝัƒั‚ั€ั–ัˆะฝัŒะพ. + +/// diff --git a/docs/uk/docs/tutorial/dependencies/global-dependencies.md b/docs/uk/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 0000000000..3cffa1752c --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,15 @@ +# ะ“ะปะพะฑะฐะปัŒะฝั– ะทะฐะปะตะถะฝะพัั‚ั– { #global-dependencies } + +ะ”ะปั ะดะตัะบะธั… ั‚ะธะฟั–ะฒ ะทะฐัั‚ะพััƒะฝะบั–ะฒ ะฒะธ ะผะพะถะตั‚ะต ะทะฐั…ะพั‚ั–ั‚ะธ ะดะพะดะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– ะดะพ ะฒััŒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะŸะพะดั–ะฑะฝะพ ะดะพ ั‚ะพะณะพ, ัะบ ะฒะธ ะผะพะถะตั‚ะต [ะดะพะดะฐะฒะฐั‚ะธ `dependencies` ะดะพ *ะดะตะบะพั€ะฐั‚ะพั€ั–ะฒ ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ั—ั… ะดะพ ะทะฐัั‚ะพััƒะฝะบัƒ `FastAPI`. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะฒะพะฝะธ ะฑัƒะดัƒั‚ัŒ ะทะฐัั‚ะพัะพะฒะฐะฝั– ะดะพ ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะฒ ะทะฐัั‚ะพััƒะฝะบัƒ: + +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} + +ะฃัั– ั–ะดะตั— ะท ั€ะพะทะดั–ะปัƒ ะฟั€ะพ [ะดะพะดะฐะฒะฐะฝะฝั `dependencies` ะดะพ *ะดะตะบะพั€ะฐั‚ะพั€ั–ะฒ ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ั‚ะฐะบ ัะฐะผะพ ะทะฐัั‚ะพัะพะฒะฝั–, ะฐะปะต ะฒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ - ะดะพ ะฒัั–ั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะฒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +## ะ—ะฐะปะตะถะฝะพัั‚ั– ะดะปั ะณั€ัƒะฟ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* { #dependencies-for-groups-of-path-operations } + +ะŸั–ะทะฝั–ัˆะต, ั‡ะธั‚ะฐัŽั‡ะธ ะฟั€ะพ ัั‚ั€ัƒะบั‚ัƒั€ัƒ ะฑั–ะปัŒัˆะธั… ะทะฐัั‚ะพััƒะฝะบั–ะฒ ([ะ‘ั–ะปัŒัˆั– ะทะฐัั‚ะพััƒะฝะบะธ - ะบั–ะปัŒะบะฐ ั„ะฐะนะปั–ะฒ](../../tutorial/bigger-applications.md){.internal-link target=_blank}), ะผะพะถะปะธะฒะพ ะท ะบั–ะปัŒะบะพะผะฐ ั„ะฐะนะปะฐะผะธ, ะฒะธ ะดั–ะทะฝะฐั”ั‚ะตัั, ัะบ ะพะณะพะปะพัะธั‚ะธ ั”ะดะธะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ `dependencies` ะดะปั ะณั€ัƒะฟะธ *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. diff --git a/docs/uk/docs/tutorial/dependencies/index.md b/docs/uk/docs/tutorial/dependencies/index.md new file mode 100644 index 0000000000..cbcf693077 --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/index.md @@ -0,0 +1,250 @@ +# ะ—ะฐะปะตะถะฝะพัั‚ั– { #dependencies } + +**FastAPI** ะผะฐั” ะดัƒะถะต ะฟะพั‚ัƒะถะฝัƒ, ะฐะปะต ั–ะฝั‚ัƒั—ั‚ะธะฒะฝัƒ ัะธัั‚ะตะผัƒ **ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**. + +ะ’ะพะฝะฐ ัั‚ะฒะพั€ะตะฝะฐ ั‚ะฐะบ, ั‰ะพะฑ ะฑัƒั‚ะธ ะดัƒะถะต ะฟั€ะพัั‚ะพัŽ ัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– ั‚ะฐ ั‰ะพะฑ ะฟะพะปะตะณัˆะธั‚ะธ ะฑัƒะดัŒ-ัะบะพะผัƒ ั€ะพะทั€ะพะฑะฝะธะบัƒ ั–ะฝั‚ะตะณั€ะฐั†ั–ัŽ ั–ะฝัˆะธั… ะบะพะผะฟะพะฝะตะฝั‚ั–ะฒ ะท **FastAPI**. + +## ะฉะพ ั‚ะฐะบะต ยซะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะนยป { #what-is-dependency-injection } + +ะฃ ะฟั€ะพะณั€ะฐะผัƒะฒะฐะฝะฝั– **ยซะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะนยป** ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ั–ัะฝัƒั” ัะฟะพัั–ะฑ ะดะปั ะฒะฐัˆะพะณะพ ะบะพะดัƒ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฒะฐัˆะธั… *ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*) ะทะฐะดะตะบะปะฐั€ัƒะฒะฐั‚ะธ ั€ะตั‡ั–, ัะบั– ะนะพะผัƒ ะฟะพั‚ั€ั–ะฑะฝั– ะดะปั ั€ะพะฑะพั‚ะธ: ยซะทะฐะปะตะถะฝะพัั‚ั–ยป. + +ะ ะฟะพั‚ั–ะผ ั†ั ัะธัั‚ะตะผะฐ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ **FastAPI**) ะฟะพะดะฑะฐั” ะฟั€ะพ ะฒัะต ะฝะตะพะฑั…ั–ะดะฝะต, ั‰ะพะฑ ะฝะฐะดะฐั‚ะธ ะฒะฐัˆะพะผัƒ ะบะพะดัƒ ั†ั– ะฟะพั‚ั€ั–ะฑะฝั– ะทะฐะปะตะถะฝะพัั‚ั– (ยซั–ะฝะถะตะบั‚ัƒะฒะฐั‚ะธยป ะทะฐะปะตะถะฝะพัั‚ั–). + +ะฆะต ะดัƒะถะต ะบะพั€ะธัะฝะพ, ะบะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ: + +* ะœะฐั‚ะธ ัะฟั–ะปัŒะฝัƒ ะปะพะณั–ะบัƒ (ะพะดะฝะฐ ะน ั‚ะฐ ัะฐะผะฐ ะปะพะณั–ะบะฐ ะทะฝะพะฒัƒ ั– ะทะฝะพะฒัƒ). +* ะ”ั–ะปะธั‚ะธัั ะทโ€™ั”ะดะฝะฐะฝะฝัะผะธ ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั…. +* ะŸั€ะธะผัƒัะพะฒะพ ะทะฐัั‚ะพัะพะฒัƒะฒะฐั‚ะธ ะฑะตะทะฟะตะบัƒ, ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ, ะฒะธะผะพะณะธ ะดะพ ั€ะพะปะตะน ั‚ะพั‰ะพ. +* ะ† ะฑะฐะณะฐั‚ะพ ั–ะฝัˆะพะณะพ... + +ะ’ัะต ั†ะต ะท ะผั–ะฝั–ะผั–ะทะฐั†ั–ั”ัŽ ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ. + +## ะŸะตั€ัˆั– ะบั€ะพะบะธ { #first-steps } + +ะ ะพะทะณะปัะฝัŒะผะพ ะดัƒะถะต ะฟั€ะพัั‚ะธะน ะฟั€ะธะบะปะฐะด. ะ’ั–ะฝ ะฑัƒะดะต ั‚ะฐะบะธะผ ะฟั€ะพัั‚ะธะผ, ั‰ะพ ะฟะพะบะธ ั‰ะพ ะฝะต ะดัƒะถะต ะบะพั€ะธัะฝะธะผ. + +ะะปะต ั‚ะฐะบ ะผะธ ะทะผะพะถะตะผะพ ะทะพัะตั€ะตะดะธั‚ะธัั ะฝะฐ ั‚ะพะผัƒ, ัะบ ะฟั€ะฐั†ัŽั” ัะธัั‚ะตะผะฐ **ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**. + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฐะฑะพ ยซะทะฐะปะตะถะฝะธะนยป { #create-a-dependency-or-dependable } + +ะกะฟะพั‡ะฐั‚ะบัƒ ะทะพัะตั€ะตะดัŒะผะพัั ะฝะฐ ะทะฐะปะตะถะฝะพัั‚ั–. + +ะฆะต ะฟั€ะพัั‚ะพ ั„ัƒะฝะบั†ั–ั, ัะบะฐ ะผะพะถะต ะฟั€ะธะนะผะฐั‚ะธ ั‚ั– ัะฐะผั– ะฟะฐั€ะฐะผะตั‚ั€ะธ, ั‰ะพ ะน *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +ะžััŒ ั– ะฒัะต. + +**2 ั€ัะดะบะธ**. + +ะ† ะฒะพะฝะฐ ะผะฐั” ั‚ัƒ ัะฐะผัƒ ั„ะพั€ะผัƒ ั‚ะฐ ัั‚ั€ัƒะบั‚ัƒั€ัƒ, ั‰ะพ ะน ัƒัั– ะฒะฐัˆั– *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +ะœะพะถะตั‚ะต ะดัƒะผะฐั‚ะธ ะฟั€ะพ ะฝะตั— ัะบ ะฟั€ะพ *ั„ัƒะฝะบั†ั–ัŽ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฑะตะท ยซะดะตะบะพั€ะฐั‚ะพั€ะฐยป (ะฑะตะท `@app.get("/some-path")`). + +ะ† ะฒะพะฝะฐ ะผะพะถะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะฑัƒะดัŒ-ั‰ะพ. + +ะฃ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั†ั ะทะฐะปะตะถะฝั–ัั‚ัŒ ะพั‡ั–ะบัƒั”: + +* ะะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `q` ั‚ะธะฟัƒ `str`. +* ะะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `skip` ั‚ะธะฟัƒ `int`, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `0`. +* ะะตะพะฑะพะฒโ€™ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `limit` ั‚ะธะฟัƒ `int`, ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ `100`. + +ะŸะพั‚ั–ะผ ะฒะพะฝะฐ ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ั‚ะฐั” `dict`, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ั†ั– ะทะฝะฐั‡ะตะฝะฝั. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +FastAPI ะดะพะดะฐะฒ ะฟั–ะดั‚ั€ะธะผะบัƒ `Annotated` (ั– ะฟะพั‡ะฐะฒ ั—ั— ั€ะตะบะพะผะตะฝะดัƒะฒะฐั‚ะธ) ัƒ ะฒะตั€ัั–ั— 0.95.0. + +ะฏะบั‰ะพ ัƒ ะฒะฐั ัั‚ะฐั€ั–ัˆะฐ ะฒะตั€ัั–ั, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะพะผะธะปะบะธ ะฟั€ะธ ัะฟั€ะพะฑั– ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `Annotated`. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ [ะžะฝะพะฒั–ั‚ัŒ ะฒะตั€ัั–ัŽ FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ั‰ะพะฝะฐะนะผะตะฝัˆะต ะดะพ 0.95.1 ะฟะตั€ะตะด ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ `Annotated`. + +/// + +### ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `Depends` { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### ะžะณะพะปะพัั–ั‚ัŒ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒ ยซะทะฐะปะตะถะฝะพะผัƒยป { #declare-the-dependency-in-the-dependant } + +ะขะฐะบ ัะฐะผะพ, ัะบ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Body`, `Query` ั‚ะพั‰ะพ ะท ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ ะฒะฐัˆะพั— *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `Depends` ะท ะฝะพะฒะธะผ ะฟะฐั€ะฐะผะตั‚ั€ะพะผ: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +ะฅะพั‡ะฐ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Depends` ัƒ ะฟะฐั€ะฐะผะตั‚ั€ะฐั… ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั— ั‚ะฐะบ ัะฐะผะพ, ัะบ `Body`, `Query` ั‚ะพั‰ะพ, `Depends` ะฟั€ะฐั†ัŽั” ั‚ั€ะพั…ะธ ั–ะฝะฐะบัˆะต. + +ะ’ะธ ะฟะตั€ะตะดะฐั”ั‚ะต ะฒ `Depends` ะปะธัˆะต ะพะดะธะฝ ะฟะฐั€ะฐะผะตั‚ั€. + +ะฆะตะน ะฟะฐั€ะฐะผะตั‚ั€ ะผะฐั” ะฑัƒั‚ะธ ั‡ะธะผะพััŒ ะฝะฐ ะบัˆั‚ะฐะปั‚ ั„ัƒะฝะบั†ั–ั—. + +ะ’ะธ ั—ั— ะฝะต ะฒะธะบะปะธะบะฐั”ั‚ะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ (ะฝะต ะดะพะดะฐะฒะฐะนั‚ะต ะดัƒะถะบะธ ะฒ ะบั–ะฝั†ั–), ะฒะธ ะฟั€ะพัั‚ะพ ะฟะตั€ะตะดะฐั”ั‚ะต ั—ั— ัะบ ะฟะฐั€ะฐะผะตั‚ั€ ัƒ `Depends()`. + +ะ† ั†ั ั„ัƒะฝะบั†ั–ั ะฟั€ะธะนะผะฐั” ะฟะฐั€ะฐะผะตั‚ั€ะธ ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบั– ั‰ะต ยซั€ะตั‡ั–ยป, ะพะบั€ั–ะผ ั„ัƒะฝะบั†ั–ะน, ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะบ ะทะฐะปะตะถะฝะพัั‚ั–. + +/// + +ะฉะพั€ะฐะทัƒ, ะบะพะปะธ ะฝะฐะดั…ะพะดะธั‚ัŒ ะฝะพะฒะธะน ะทะฐะฟะธั‚, **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ: + +* ะ’ะธะบะปะธะบ ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั—-ะทะฐะปะตะถะฝะพัั‚ั– (ยซะทะฐะปะตะถะฝะพะณะพยป) ะท ะฟั€ะฐะฒะธะปัŒะฝะธะผะธ ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ. +* ะžั‚ั€ะธะผะฐะฝะฝั ั€ะตะทัƒะปัŒั‚ะฐั‚ัƒ ะท ะฒะฐัˆะพั— ั„ัƒะฝะบั†ั–ั—. +* ะŸั€ะธัะฒะพั”ะฝะฝั ั†ัŒะพะณะพ ั€ะตะทัƒะปัŒั‚ะฐั‚ัƒ ะฟะฐั€ะฐะผะตั‚ั€ัƒ ัƒ ะฒะฐัˆั–ะน *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะฒะธ ะฟะธัˆะตั‚ะต ัะฟั–ะปัŒะฝะธะน ะบะพะด ะพะดะธะฝ ั€ะฐะท, ะฐ **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะนะพะณะพ ะฒะธะบะปะธะบ ะดะปั ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะบะปะฐั ั– ะฟะตั€ะตะดะฐะฒะฐั‚ะธ ะนะพะณะพ ะบัƒะดะธััŒ ัƒ **FastAPI**, ั‰ะพะฑ ยซะทะฐั€ะตั”ัั‚ั€ัƒะฒะฐั‚ะธยป ะนะพะณะพ ั‡ะธ ั‰ะพััŒ ะฟะพะดั–ะฑะฝะต. + +ะ’ะธ ะฟั€ะพัั‚ะพ ะฟะตั€ะตะดะฐั”ั‚ะต ะนะพะณะพ ะฒ `Depends`, ั– **FastAPI** ะทะฝะฐั”, ั‰ะพ ั€ะพะฑะธั‚ะธ ะดะฐะปั–. + +/// + +## ะกะฟั–ะปัŒะฝะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน `Annotated` { #share-annotated-dependencies } + +ะฃ ะฝะฐะฒะตะดะตะฝะธั… ะฒะธั‰ะต ะฟั€ะธะบะปะฐะดะฐั… ะฒะธะดะฝะพ ะฝะตะฒะตะปะธะบะต **ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ**. + +ะšะพะปะธ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ `common_parameters()`, ะดะพะฒะพะดะธั‚ัŒัั ะฟะธัะฐั‚ะธ ะฒะตััŒ ะฟะฐั€ะฐะผะตั‚ั€ ะท ะฐะฝะพั‚ะฐั†ั–ั”ัŽ ั‚ะธะฟัƒ ั‚ะฐ `Depends()`: + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +ะะปะต ะพัะบั–ะปัŒะบะธ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `Annotated`, ะผะธ ะผะพะถะตะผะพ ะทะฑะตั€ะตะณั‚ะธ ั†ะต ะทะฝะฐั‡ะตะฝะฝั `Annotated` ัƒ ะทะผั–ะฝะฝั–ะน ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ะฒ ะบั–ะปัŒะบะพั… ะผั–ัั†ัั…: + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะฟั€ะพัั‚ะพ ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน Python, ั†ะต ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ยซะฟัะตะฒะดะพะฝั–ะผ ั‚ะธะฟัƒยป ั– ะฝะฐัะฟั€ะฐะฒะดั– ะฝะต ั” ัะฟะตั†ะธั„ั–ั‡ะฝะธะผ ะดะปั **FastAPI**. + +ะะปะต ะพัะบั–ะปัŒะบะธ **FastAPI** ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัั‚ะฐะฝะดะฐั€ั‚ะฐั… Python, ะฒะบะปัŽั‡ะฝะพ ะท `Annotated`, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะตะน ั‚ั€ัŽะบ ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–. ๐Ÿ˜Ž + +/// + +ะ—ะฐะปะตะถะฝะพัั‚ั– ะฟั€ะพะดะพะฒะถะฐั‚ัŒ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ัะบ ะพั‡ั–ะบัƒั”ั‚ัŒัั, ั– **ะฝะฐะนะบั€ะฐั‰ะต** ั‚ะต, ั‰ะพ **ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ั‚ะธะฟะธ ะฑัƒะดะต ะทะฑะตั€ะตะถะตะฝะฐ**, ะฐ ั†ะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€ ะทะผะพะถะต ะน ะฝะฐะดะฐะปั– ะฝะฐะดะฐะฒะฐั‚ะธ **ะฐะฒั‚ะพะทะฐะฟะพะฒะฝะตะฝะฝั**, **ะฟะพะผะธะปะบะธ ะฒ ั€ัะดะบัƒ** ั‚ะพั‰ะพ. ะขะต ัะฐะผะต ั– ะดะปั ั–ะฝัˆะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ, ัะบ-ะพั‚ `mypy`. + +ะฆะต ะฑัƒะดะต ะพัะพะฑะปะธะฒะพ ะบะพั€ะธัะฝะพ ัƒ **ะฒะตะปะธะบั–ะน ะบะพะดะพะฒั–ะน ะฑะฐะทั–**, ะดะต ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต **ะพะดะฝั– ะน ั‚ั– ัะฐะผั– ะทะฐะปะตะถะฝะพัั‚ั–** ะทะฝะพะฒัƒ ั– ะทะฝะพะฒัƒ ะฒ **ะฑะฐะณะฐั‚ัŒะพั… *ะพะฟะตั€ะฐั†ั–ัั… ัˆะปัั…ัƒ***. + +## ะ‘ัƒั‚ะธ `async` ั‡ะธ ะฝะต ะฑัƒั‚ะธ `async` { #to-async-or-not-to-async } + +ะžัะบั–ะปัŒะบะธ ะทะฐะปะตะถะฝะพัั‚ั– ั‚ะฐะบะพะถ ะฒะธะบะปะธะบะฐั‚ะธะผัƒั‚ัŒัั **FastAPI** (ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะฒะฐัˆั– *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*), ะฟั–ะด ั‡ะฐั ะฒะธะทะฝะฐั‡ะตะฝะฝั ะฒะฐัˆะธั… ั„ัƒะฝะบั†ั–ะน ะดั–ัŽั‚ัŒ ั‚ั– ัะฐะผั– ะฟั€ะฐะฒะธะปะฐ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `async def` ะฐะฑะพ ะทะฒะธั‡ะฐะนะฝะธะน `def`. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั– ะท `async def` ะฒัะตั€ะตะดะธะฝั– ะทะฒะธั‡ะฐะนะฝะธั… *ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะท `def`, ะฐะฑะพ ะทะฐะปะตะถะฝะพัั‚ั– ะท `def` ะฒัะตั€ะตะดะธะฝั– *ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะท `async def` ั‚ะพั‰ะพ. + +ะฆะต ะฝะต ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั. **FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ั€ะพะฑะธั‚ะธ. + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะฏะบั‰ะพ ะฒะธ ะฝะต ะฒะฟะตะฒะฝะตะฝั–, ะฟะตั€ะตะณะปัะฝัŒั‚ะต ั€ะพะทะดั–ะป [Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank} ะฟั€ะพ `async` ั– `await` ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. + +/// + +## ะ†ะฝั‚ะตะณั€ะพะฒะฐะฝะพ ะท OpenAPI { #integrated-with-openapi } + +ะฃัั– ะดะตะบะปะฐั€ะฐั†ั–ั— ะทะฐะฟะธั‚ั–ะฒ, ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะฐ ะฒะธะผะพะณะธ ะฒะฐัˆะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน (ั– ััƒะฑะทะฐะปะตะถะฝะพัั‚ะตะน) ะฑัƒะดัƒั‚ัŒ ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– ะฒ ั‚ัƒ ัะฐะผัƒ ัั…ะตะผัƒ OpenAPI. + +ะขะพะถ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะฐ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ั‚ะฐะบะพะถ ะผั–ัั‚ะธั‚ะธะผะต ะฒััŽ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะท ั†ะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน: + + + +## ะŸั€ะพัั‚ะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั { #simple-usage } + +ะฏะบั‰ะพ ะฟั€ะธะดะธะฒะธั‚ะธัั, *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ* ะพะณะพะปะพัˆัƒัŽั‚ัŒัั ะดะปั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะทะฑั–ะณะฐัŽั‚ัŒัั *ัˆะปัั…* ั‚ะฐ *ะพะฟะตั€ะฐั†ั–ั*, ะฐ ะฟะพั‚ั–ะผ **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะฒะธะบะปะธะบ ั„ัƒะฝะบั†ั–ั— ะท ะฟั€ะฐะฒะธะปัŒะฝะธะผะธ ะฟะฐั€ะฐะผะตั‚ั€ะฐะผะธ, ะฒะธั‚ัะณัƒัŽั‡ะธ ะดะฐะฝั– ั–ะท ะทะฐะฟะธั‚ัƒ. + +ะะฐัะฟั€ะฐะฒะดั– ะฒัั– (ะฐะฑะพ ะฑั–ะปัŒัˆั–ัั‚ัŒ) ะฒะตะฑั„ั€ะตะนะผะฒะพั€ะบั–ะฒ ะฟั€ะฐั†ัŽัŽั‚ัŒ ั‚ะฐะบ ัะฐะผะพ. + +ะ’ะธ ะฝั–ะบะพะปะธ ะฝะต ะฒะธะบะปะธะบะฐั”ั‚ะต ั†ั– ั„ัƒะฝะบั†ั–ั— ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. ะ‡ั… ะฒะธะบะปะธะบะฐั” ะฒะฐัˆ ั„ั€ะตะนะผะฒะพั€ะบ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ **FastAPI**). + +ะ—ะฐ ะดะพะฟะพะผะพะณะพัŽ ัะธัั‚ะตะผะธ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะฒะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ **FastAPI**, ั‰ะพ ะฒะฐัˆะฐ *ั„ัƒะฝะบั†ั–ั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ั‚ะฐะบะพะถ ยซะทะฐะปะตะถะธั‚ัŒยป ะฒั–ะด ั‡ะพะณะพััŒ, ั‰ะพ ะผะฐั” ะฑัƒั‚ะธ ะฒะธะบะพะฝะฐะฝะพ ะดะพ ะฒะฐัˆะพั— *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*, ั– **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะฒะธะบะพะฝะฐะฝะฝั ั†ัŒะพะณะพ ั‚ะฐ ยซั–ะฝะถะตะบั‚ัƒะฒะฐะฝะฝัยป ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ. + +ะ†ะฝัˆั– ะฟะพัˆะธั€ะตะฝั– ั‚ะตั€ะผั–ะฝะธ ะดะปั ั†ั–ั”ั— ัะฐะผะพั— ั–ะดะตั— ยซะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะนยป: + +* ั€ะตััƒั€ัะธ +* ะฟั€ะพะฒะฐะนะดะตั€ะธ +* ัะตั€ะฒั–ัะธ +* ั–ะฝะถะตะบั‚ะพะฒะฐะฝั– ะพะฑโ€™ั”ะบั‚ะธ +* ะบะพะผะฟะพะฝะตะฝั‚ะธ + +## ะŸะปะฐะณั–ะฝะธ **FastAPI** { #fastapi-plug-ins } + +ะ†ะฝั‚ะตะณั€ะฐั†ั–ั— ั‚ะฐ ยซะฟะปะฐะณั–ะฝะธยป ะผะพะถะฝะฐ ะฑัƒะดัƒะฒะฐั‚ะธ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ัะธัั‚ะตะผะธ **ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**. ะะปะต ะฝะฐัะฟั€ะฐะฒะดั– **ะฝะตะผะฐั” ะฟะพั‚ั€ะตะฑะธ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ยซะฟะปะฐะณั–ะฝะธยป**, ะพัะบั–ะปัŒะบะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะทะฐะปะตะถะฝะพัั‚ั–, ะผะพะถะฝะฐ ะพะณะพะปะพัะธั‚ะธ ะฑะตะทะผะตะถะฝัƒ ะบั–ะปัŒะบั–ัั‚ัŒ ั–ะฝั‚ะตะณั€ะฐั†ั–ะน ั‚ะฐ ะฒะทะฐั”ะผะพะดั–ะน, ัะบั– ัั‚ะฐัŽั‚ัŒ ะดะพัั‚ัƒะฟะฝะธะผะธ ะดะปั ะฒะฐัˆะธั… *ั„ัƒะฝะบั†ั–ะน ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +ะ† ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถะฝะฐ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะดัƒะถะต ะฟั€ะพัั‚ะพ ั‚ะฐ ั–ะฝั‚ัƒั—ั‚ะธะฒะฝะพ, ั‰ะพ ะดะพะทะฒะพะปัั” ะฒะฐะผ ะฟั€ะพัั‚ะพ ั–ะผะฟะพั€ั‚ัƒะฒะฐั‚ะธ ะฟะพั‚ั€ั–ะฑะฝั– ะฟะฐะบัƒะฝะบะธ Python ั– ั–ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ั—ั… ะท ะฒะฐัˆะธะผะธ ั„ัƒะฝะบั†ั–ัะผะธ API ะทะฐ ะบั–ะปัŒะบะฐ ั€ัะดะบั–ะฒ ะบะพะดัƒ, ะฑัƒะบะฒะฐะปัŒะฝะพ. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ะฟั€ะธะบะปะฐะดะธ ั†ัŒะพะณะพ ะฒ ะฝะฐัั‚ัƒะฟะฝะธั… ั€ะพะทะดั–ะปะฐั…, ะฟั€ะพ ั€ะตะปัั†ั–ะนะฝั– ั‚ะฐ NoSQL ะฑะฐะทะธ ะดะฐะฝะธั…, ะฑะตะทะฟะตะบัƒ ั‚ะพั‰ะพ. + +## ะกัƒะผั–ัะฝั–ัั‚ัŒ **FastAPI** { #fastapi-compatibility } + +ะŸั€ะพัั‚ะพั‚ะฐ ัะธัั‚ะตะผะธ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ั€ะพะฑะธั‚ัŒ **FastAPI** ััƒะผั–ัะฝะธะผ ะท: + +* ัƒัั–ะผะฐ ั€ะตะปัั†ั–ะนะฝะธะผะธ ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… +* NoSQL ะฑะฐะทะฐะผะธ ะดะฐะฝะธั… +* ะทะพะฒะฝั–ัˆะฝั–ะผะธ ะฟะฐะบัƒะฝะบะฐะผะธ +* ะทะพะฒะฝั–ัˆะฝั–ะผะธ API +* ัะธัั‚ะตะผะฐะผะธ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ั‚ะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั— +* ัะธัั‚ะตะผะฐะผะธ ะผะพะฝั–ั‚ะพั€ะธะฝะณัƒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั API +* ัะธัั‚ะตะผะฐะผะธ ั–ะฝะถะตะบั†ั–ั— ะดะฐะฝะธั… ัƒ ะฒั–ะดะฟะพะฒั–ะดัŒ +* ั‚ะพั‰ะพ. + +## ะŸั€ะพัั‚ะพ ั– ะฟะพั‚ัƒะถะฝะพ { #simple-and-powerful } + +ะฅะพั‡ะฐ ั–ั”ั€ะฐั€ั…ั–ั‡ะฝะฐ ัะธัั‚ะตะผะฐ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะดัƒะถะต ะฟั€ะพัั‚ะฐ ัƒ ะฒะธะทะฝะฐั‡ะตะฝะฝั– ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั–, ะฒะพะฝะฐ ะฒัะต ั‰ะต ะดัƒะถะต ะฟะพั‚ัƒะถะฝะฐ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั–, ัะบั– ัะฒะพั”ัŽ ั‡ะตั€ะณะพัŽ ะผะพะถัƒั‚ัŒ ะฒะธะทะฝะฐั‡ะฐั‚ะธ ะฒะปะฐัะฝั– ะทะฐะปะตะถะฝะพัั‚ั–. + +ะ—ั€ะตัˆั‚ะพัŽ ะฑัƒะดัƒั”ั‚ัŒัั ั–ั”ั€ะฐั€ั…ั–ั‡ะฝะต ะดะตั€ะตะฒะพ ะทะฐะปะตะถะฝะพัั‚ะตะน, ั– ัะธัั‚ะตะผะฐ **ะ’ะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน** ะฟะพะดะฑะฐั” ะฟั€ะพ ั€ะพะทะฒโ€™ัะทะฐะฝะฝั ะฒัั–ั… ั†ะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน (ั– ั—ั…ะฝั–ั… ััƒะฑะทะฐะปะตะถะฝะพัั‚ะตะน) ั‚ะฐ ะฝะฐะดะฐะฝะฝั (ั–ะฝะถะตะบั‚ัƒะฒะฐะฝะฝั) ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ ะฝะฐ ะบะพะถะฝะพะผัƒ ะบั€ะพั†ั–. + +ะะฐะฟั€ะธะบะปะฐะด, ะฟั€ะธะฟัƒัั‚ั–ะผะพ, ัƒ ะฒะฐั ั” 4 ะบั–ะฝั†ะตะฒั– ั‚ะพั‡ะบะธ API (*ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*): + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +ั‚ะพะดั– ะฒะธ ะผะพะณะปะธ ะฑ ะดะพะดะฐั‚ะธ ั€ั–ะทะฝั– ะฒะธะผะพะณะธ ะดะพ ะดะพะทะฒะพะปั–ะฒ ะดะปั ะบะพะถะฝะพั— ะท ะฝะธั… ะปะธัˆะต ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะทะฐะปะตะถะฝะพัั‚ะตะน ั– ััƒะฑะทะฐะปะตะถะฝะพัั‚ะตะน: + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## ะ†ะฝั‚ะตะณั€ะพะฒะฐะฝะพ ะท **OpenAPI** { #integrated-with-openapi_1 } + +ะฃัั– ั†ั– ะทะฐะปะตะถะฝะพัั‚ั–, ะดะตะบะปะฐั€ัƒัŽั‡ะธ ัะฒะพั— ะฒะธะผะพะณะธ, ั‚ะฐะบะพะถ ะดะพะดะฐัŽั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ะธ, ะฟะตั€ะตะฒั–ั€ะบะธ ั‚ะพั‰ะพ ะดะพ ะฒะฐัˆะธั… *ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ*. + +**FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ะดะพะดะฐะฒะฐะฝะฝั ะฒััŒะพะณะพ ั†ัŒะพะณะพ ะดะพ ัั…ะตะผะธ OpenAPI, ั‰ะพะฑ ั†ะต ะฒั–ะดะพะฑั€ะฐะถะฐะปะพัั ะฒ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะธั… ัะธัั‚ะตะผะฐั… ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—. diff --git a/docs/uk/docs/tutorial/dependencies/sub-dependencies.md b/docs/uk/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000..4e7488086a --- /dev/null +++ b/docs/uk/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# ะŸั–ะดะทะฐะปะตะถะฝะพัั‚ั– { #sub-dependencies } + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ั–, ัะบั– ะผะฐัŽั‚ัŒ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–. + +ะ’ะพะฝะธ ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะฝะฐัั‚ั–ะปัŒะบะธ ะณะปะธะฑะพะบะธะผะธ, ะฝะฐัะบั–ะปัŒะบะธ ะฟะพั‚ั€ั–ะฑะฝะพ. + +FastAPI ะฟะพะดะฑะฐั” ะฟั€ะพ ั—ั… ั€ะพะทะฒ'ัะทะฐะฝะฝั. + +## ะŸะตั€ัˆะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ ยซdependableยป { #first-dependency-dependable } + +ะœะพะถะฝะฐ ัั‚ะฒะพั€ะธั‚ะธ ะฟะตั€ัˆัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ยซdependableยป) ั‚ะฐะบ: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +ะ’ะพะฝะฐ ะพะณะพะปะพัˆัƒั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะธะน ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `q` ั‚ะธะฟัƒ `str`, ะฐ ะฟะพั‚ั–ะผ ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ั‚ะฐั” ะนะพะณะพ. + +ะฆะต ะดะพัะธั‚ัŒ ะฟั€ะพัั‚ะพ (ะฝะต ะดัƒะถะต ะบะพั€ะธัะฝะพ), ะฐะปะต ะดะพะฟะพะผะพะถะต ะทะพัะตั€ะตะดะธั‚ะธัั ะฝะฐ ั‚ะพะผัƒ, ัะบ ะฟั€ะฐั†ัŽัŽั‚ัŒ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–. + +## ะ”ั€ัƒะณะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ยซdependableยป ั– ยซdependantยป { #second-dependency-dependable-and-dependant } + +ะ”ะฐะปั– ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ั–ะฝัˆัƒ ั„ัƒะฝะบั†ั–ัŽ ะทะฐะปะตะถะฝะพัั‚ั– (ยซdependableยป), ัะบะฐ ะฒะพะดะฝะพั‡ะฐั ะพะณะพะปะพัˆัƒั” ะฒะปะฐัะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ั‚ะพะถ ะฒะพะฝะฐ ั‚ะฐะบะพะถ ั” ยซdependantยป): + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +ะ—ะพัะตั€ะตะดัŒะผะพัั ะฝะฐ ะพะณะพะปะพัˆะตะฝะธั… ะฟะฐั€ะฐะผะตั‚ั€ะฐั…: + +- ะฅะพั‡ะฐ ั†ั ั„ัƒะฝะบั†ั–ั ัะฐะผะฐ ั” ะทะฐะปะตะถะฝั–ัั‚ัŽ (ยซdependableยป), ะฒะพะฝะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒั” ั–ะฝัˆัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ (ะฒะพะฝะฐ ยซะทะฐะปะตะถะธั‚ัŒยป ะฒั–ะด ั‡ะพะณะพััŒ). + - ะ’ะพะฝะฐ ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด `query_extractor` ั– ะฟั€ะธัะฒะพัŽั” ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะฒั–ะฝ ะฟะพะฒะตั€ั‚ะฐั”, ะฟะฐั€ะฐะผะตั‚ั€ัƒ `q`. +- ะ’ะพะฝะฐ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒั” ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะต ะบัƒะบั– `last_query` ั‚ะธะฟัƒ `str`. + - ะฏะบั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฝะต ะฝะฐะดะฐะฒ ะฟะฐั€ะฐะผะตั‚ั€ ะทะฐะฟะธั‚ัƒ `q`, ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะพัั‚ะฐะฝะฝั–ะน ะทะฐะฟะธั‚, ัะบะธะน ะทะฑะตั€ะตะณะปะธ ั€ะฐะฝั–ัˆะต ะฒ ะบัƒะบั–. + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะทะฐะปะตะถะฝะพัั‚ั– { #use-the-dependency } + +ะŸะพั‚ั–ะผ ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั‚ะฐะบ: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ะปะธัˆะต ะพะดะฝัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัƒ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ โ€” `query_or_cookie_extractor`. + +ะะปะต FastAPI ะทะฝะฐั‚ะธะผะต, ั‰ะพ ัะฟะพั‡ะฐั‚ะบัƒ ั‚ั€ะตะฑะฐ ั€ะพะทะฒ'ัะทะฐั‚ะธ `query_extractor`, ั‰ะพะฑ ะฟะตั€ะตะดะฐั‚ะธ ะนะพะณะพ ั€ะตะทัƒะปัŒั‚ะฐั‚ ัƒ `query_or_cookie_extractor` ะฟั–ะด ั‡ะฐั ะฒะธะบะปะธะบัƒ. + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ั–ั”ั— ะถ ะทะฐะปะตะถะฝะพัั‚ั– ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ { #using-the-same-dependency-multiple-times } + +ะฏะบั‰ะพ ะพะดะฝะฐ ะท ะฒะฐัˆะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน ะพะณะพะปะพัˆะตะฝะฐ ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ ะดะปั ะพะดะฝั–ั”ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฝะฐะฟั€ะธะบะปะฐะด, ะบั–ะปัŒะบะฐ ะทะฐะปะตะถะฝะพัั‚ะตะน ะผะฐัŽั‚ัŒ ัะฟั–ะปัŒะฝัƒ ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ, FastAPI ะทะฝะฐั‚ะธะผะต, ั‰ะพ ั†ัŽ ะฟั–ะดะทะฐะปะตะถะฝั–ัั‚ัŒ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะปะธะบะฐั‚ะธ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท ะฝะฐ ะทะฐะฟะธั‚. + +ะ† ะฒั–ะฝ ะทะฑะตั€ะตะถะต ะฟะพะฒะตั€ะฝัƒั‚ะต ะทะฝะฐั‡ะตะฝะฝั ัƒ ยซะบะตัˆยป ั– ะฟะตั€ะตะดะฐัั‚ัŒ ะนะพะณะพ ะฒัั–ะผ ยซdependantsยป, ัะบะธะผ ะฒะพะฝะพ ะฟะพั‚ั€ั–ะฑะฝะต ะฒ ั†ัŒะพะผัƒ ะบะพะฝะบั€ะตั‚ะฝะพะผัƒ ะทะฐะฟะธั‚ั–, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ ั‰ะพะฑ ะฒะธะบะปะธะบะฐั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ ะดะปั ะพะดะฝะพะณะพ ะน ั‚ะพะณะพ ะถ ะทะฐะฟะธั‚ัƒ. + +ะฃ ะฟั€ะพััƒะฝัƒั‚ะพะผัƒ ัั†ะตะฝะฐั€ั–ั—, ะบะพะปะธ ะฒะธ ะทะฝะฐั”ั‚ะต, ั‰ะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะผะฐั” ะฒะธะบะปะธะบะฐั‚ะธัั ะฝะฐ ะบะพะถะฝะพะผัƒ ะบั€ะพั†ั– (ะผะพะถะปะธะฒะพ, ะบั–ะปัŒะบะฐ ั€ะฐะทั–ะฒ) ัƒ ะผะตะถะฐั… ั‚ะพะณะพ ัะฐะผะพะณะพ ะทะฐะฟะธั‚ัƒ ะทะฐะผั–ัั‚ัŒ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ยซะบะตัˆะพะฒะฐะฝะพะณะพยป ะทะฝะฐั‡ะตะฝะฝั, ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ `use_cache=False` ะฟั€ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั– `Depends`: + +//// tab | Python 3.10+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.10+ ะฑะตะท Annotated + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐะดะฐะฒะฐะนั‚ะต ะฟะตั€ะตะฒะฐะณัƒ ะฒะตั€ัั–ั— ะท `Annotated`, ัะบั‰ะพ ั†ะต ะผะพะถะปะธะฒะพ. + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะŸะพะฟั€ะธ ะฒัั– ะผะพะดะฝั– ั‚ะตั€ะผั–ะฝะธ, ัะธัั‚ะตะผะฐ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน ะดะพัะธั‚ัŒ ะฟั€ะพัั‚ะฐ. + +ะฆะต ะฟั€ะพัั‚ะพ ั„ัƒะฝะบั†ั–ั—, ัะบั– ะฒะธะณะปัะดะฐัŽั‚ัŒ ั‚ะฐะบ ัะฐะผะพ, ัะบ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ. + +ะ’ั‚ั–ะผ ะฒะพะฝะฐ ะดัƒะถะต ะฟะพั‚ัƒะถะฝะฐ ั– ะดะพะทะฒะพะปัั” ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะดะพะฒั–ะปัŒะฝะพ ะณะปะธะฑะพะบะพ ะฒะบะปะฐะดะตะฝั– ยซะณั€ะฐั„ะธยป ะทะฐะปะตะถะฝะพัั‚ะตะน (ะดะตั€ะตะฒะฐ). + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃัะต ั†ะต ะผะพะถะต ะทะดะฐะฒะฐั‚ะธัั ะฝะต ะฝะฐะดั‚ะพ ะบะพั€ะธัะฝะธะผ ะฝะฐ ะฟั€ะพัั‚ะธั… ะฟั€ะธะบะปะฐะดะฐั…. + +ะะปะต ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ะฝะฐัะบั–ะปัŒะบะธ ั†ะต ะบะพั€ะธัะฝะพ, ัƒ ั€ะพะทะดั–ะปะฐั… ะฟั€ะพ **ะฑะตะทะฟะตะบัƒ**. + +ะ† ั‚ะฐะบะพะถ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบั–ะปัŒะบะธ ะบะพะดัƒ ั†ะต ะฒะฐะผ ะทะฐะพั‰ะฐะดะธั‚ัŒ. + +/// diff --git a/docs/uk/docs/tutorial/extra-models.md b/docs/uk/docs/tutorial/extra-models.md new file mode 100644 index 0000000000..25930b8c0b --- /dev/null +++ b/docs/uk/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# ะ”ะพะดะฐั‚ะบะพะฒั– ะผะพะดะตะปั– { #extra-models } + +ะŸั€ะพะดะพะฒะถัƒัŽั‡ะธ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฟั€ะธะบะปะฐะด, ั‡ะฐัั‚ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะผะฐั‚ะธ ะฑั–ะปัŒัˆะต ะฝั–ะถ ะพะดะฝัƒ ะฟะพะฒโ€™ัะทะฐะฝัƒ ะผะพะดะตะปัŒ. + +ะžัะพะฑะปะธะฒะพ ั†ะต ัั‚ะพััƒั”ั‚ัŒัั ะผะพะดะตะปะตะน ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ั‚ะพะผัƒ ั‰ะพ: + +* **ะฒั…ั–ะดะฝะฐ ะผะพะดะตะปัŒ** ะฟะพะฒะธะฝะฝะฐ ะผะฐั‚ะธ ะฟะฐั€ะพะปัŒ. +* **ะฒะธั…ั–ะดะฝะฐ ะผะพะดะตะปัŒ** ะฝะต ะฟะพะฒะธะฝะฝะฐ ะผั–ัั‚ะธั‚ะธ ะฟะฐั€ะพะปัŒ. +* **ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั…**, ะนะผะพะฒั–ั€ะฝะพ, ะฟะพะฒะธะฝะฝะฐ ะผั–ัั‚ะธั‚ะธ ั…ะตัˆ ะฟะฐั€ะพะปั. + +/// danger | ะžะฑะตั€ะตะถะฝะพ + +ะั–ะบะพะปะธ ะฝะต ะทะฑะตั€ั–ะณะฐะนั‚ะต ะฟะฐั€ะพะปั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ ัƒ ะฒั–ะดะบั€ะธั‚ะพะผัƒ ะฒะธะณะปัะดั–. ะ—ะฐะฒะถะดะธ ะทะฑะตั€ั–ะณะฐะนั‚ะต ยซะฑะตะทะฟะตั‡ะฝะธะน ั…ะตัˆยป, ัะบะธะน ะฟะพั‚ั–ะผ ะผะพะถะฝะฐ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ. + +ะฏะบั‰ะพ ะฒะธ ั‰ะต ะฝะต ะทะฝะฐั”ั‚ะต, ั‰ะพ ั‚ะฐะบะต ยซั…ะตัˆ ะฟะฐั€ะพะปัยป, ะฒะธ ะดั–ะทะฝะฐั”ั‚ะตััŒ ัƒ [ั€ะพะทะดั–ะปะฐั… ะฟั€ะพ ะฑะตะทะฟะตะบัƒ](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}. + +/// + +## ะšั–ะปัŒะบะฐ ะผะพะดะตะปะตะน { #multiple-models } + +ะžััŒ ะทะฐะณะฐะปัŒะฝะฐ ั–ะดะตั ั‚ะพะณะพ, ัะบ ะผะพะถัƒั‚ัŒ ะฒะธะณะปัะดะฐั‚ะธ ะผะพะดะตะปั– ะท ั—ั…ะฝั–ะผะธ ะฟะพะปัะผะธ ะฟะฐั€ะพะปั ั‚ะฐ ะผั–ัั†ัะผะธ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### ะŸั€ะพ `**user_in.model_dump()` { #about-user-in-model-dump } + +#### `.model_dump()` ัƒ Pydantic { #pydantics-model-dump } + +`user_in` - ั†ะต ะผะพะดะตะปัŒ Pydantic ะบะปะฐััƒ `UserIn`. + +ะœะพะดะตะปั– Pydantic ะผะฐัŽั‚ัŒ ะผะตั‚ะพะด `.model_dump()`, ัะบะธะน ะฟะพะฒะตั€ั‚ะฐั” `dict` ะท ะดะฐะฝะธะผะธ ะผะพะดะตะปั–. + +ะžั‚ะถะต, ัะบั‰ะพ ะผะธ ัั‚ะฒะพั€ะธะผะพ ะพะฑโ€™ั”ะบั‚ Pydantic `user_in` ั‚ะฐะบ: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +ั– ะฒะธะบะปะธั‡ะตะผะพ: + +```Python +user_dict = user_in.model_dump() +``` + +ั‚ะตะฟะตั€ ะผะธ ะผะฐั”ะผะพ `dict` ะท ะดะฐะฝะธะผะธ ัƒ ะทะผั–ะฝะฝั–ะน `user_dict` (ั†ะต `dict`, ะฐ ะฝะต ะพะฑโ€™ั”ะบั‚ ะผะพะดะตะปั– Pydantic). + +ะ ัะบั‰ะพ ะฒะธะบะปะธะบะฐั‚ะธ: + +```Python +print(user_dict) +``` + +ะผะธ ะพั‚ั€ะธะผะฐั”ะผะพ Python `dict` ะท: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### ะ ะพะทะฟะฐะบัƒะฒะฐะฝะฝั `dict` { #unpacking-a-dict } + +ะฏะบั‰ะพ ะฒะทัั‚ะธ `dict`, ะฝะฐะฟั€ะธะบะปะฐะด `user_dict`, ั– ะฟะตั€ะตะดะฐั‚ะธ ะนะพะณะพ ัƒ ั„ัƒะฝะบั†ั–ัŽ (ะฐะฑะพ ะบะปะฐั) ัะบ `**user_dict`, Python ยซั€ะพะทะฟะฐะบัƒั”ยป ะนะพะณะพ. ะšะปัŽั‡ั– ั‚ะฐ ะทะฝะฐั‡ะตะฝะฝั `user_dict` ะฑัƒะดัƒั‚ัŒ ะฟะตั€ะตะดะฐะฝั– ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัะบ ั–ะผะตะฝะพะฒะฐะฝั– ะฐั€ะณัƒะผะตะฝั‚ะธ. + +ะžั‚ะถะต, ะฟั€ะพะดะพะฒะถัƒัŽั‡ะธ ะท `user_dict` ะฒะธั‰ะต, ะทะฐะฟะธั: + +```Python +UserInDB(**user_dict) +``` + +ะดะฐัั‚ัŒ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะธะน ั€ะตะทัƒะปัŒั‚ะฐั‚: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +ะ ั‚ะพั‡ะฝั–ัˆะต, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ `user_dict`, ะท ะฑัƒะดัŒ-ัะบะธะผ ะนะพะณะพ ะฒะผั–ัั‚ะพะผ ัƒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### ะœะพะดะตะปัŒ Pydantic ะทั– ะฒะผั–ัั‚ัƒ ั–ะฝัˆะพั— { #a-pydantic-model-from-the-contents-of-another } + +ะฏะบ ัƒ ะฟั€ะธะบะปะฐะดั– ะฒะธั‰ะต ะผะธ ะพั‚ั€ะธะผะฐะปะธ `user_dict` ะท `user_in.model_dump()`, ั†ะตะน ะบะพะด: + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +ะฑัƒะดะต ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะธะผ: + +```Python +UserInDB(**user_in.model_dump()) +``` + +...ั‚ะพะผัƒ ั‰ะพ `user_in.model_dump()` ะฟะพะฒะตั€ั‚ะฐั” `dict`, ะฐ ะผะธ ะทะผัƒัˆัƒั”ะผะพ Python ยซั€ะพะทะฟะฐะบัƒะฒะฐั‚ะธยป ะนะพะณะพ, ะฟะตั€ะตะดะฐัŽั‡ะธ ะฒ `UserInDB` ะท ะฟั€ะตั„ั–ะบัะพะผ `**`. + +ะขะพะถ ะผะธ ะพั‚ั€ะธะผัƒั”ะผะพ ะผะพะดะตะปัŒ Pydantic ะท ะดะฐะฝะธั… ั–ะฝัˆะพั— ะผะพะดะตะปั– Pydantic. + +#### ะ ะพะทะฟะฐะบัƒะฒะฐะฝะฝั `dict` ั– ะดะพะดะฐั‚ะบะพะฒั– ะบะปัŽั‡ะพะฒั– ะฐั€ะณัƒะผะตะฝั‚ะธ { #unpacking-a-dict-and-extra-keywords } + +ะ”ะพะดะฐัŽั‡ะธ ะดะพะดะฐั‚ะบะพะฒะธะน ั–ะผะตะฝะพะฒะฐะฝะธะน ะฐั€ะณัƒะผะตะฝั‚ `hashed_password=hashed_password`, ัะบ ั‚ัƒั‚: + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +...ัƒ ะฟั–ะดััƒะผะบัƒ ั†ะต ะดะพั€ั–ะฒะฝัŽั”: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะ”ะพะดะฐั‚ะบะพะฒั– ะดะพะฟะพะผั–ะถะฝั– ั„ัƒะฝะบั†ั–ั— `fake_password_hasher` ั– `fake_save_user` ะปะธัˆะต ะดะตะผะพะฝัั‚ั€ัƒัŽั‚ัŒ ะผะพะถะปะธะฒะธะน ะฟะพั‚ั–ะบ ะดะฐะฝะธั… ั–, ะทะฒั–ัะฝะพ, ะฝะต ะทะฐะฑะตะทะฟะตั‡ัƒัŽั‚ัŒ ั€ะตะฐะปัŒะฝะพั— ะฑะตะทะฟะตะบะธ. + +/// + +## ะ—ะผะตะฝัˆะตะฝะฝั ะดัƒะฑะปัŽะฒะฐะฝะฝั { #reduce-duplication } + +ะ—ะผะตะฝัˆะตะฝะฝั ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ - ะพะดะฝะฐ ะท ะบะปัŽั‡ะพะฒะธั… ั–ะดะตะน ัƒ **FastAPI**. + +ะะดะถะต ะดัƒะฑะปัŽะฒะฐะฝะฝั ะบะพะดัƒ ะฟั–ะดะฒะธั‰ัƒั” ะนะผะพะฒั–ั€ะฝั–ัั‚ัŒ ะฟะพะผะธะปะพะบ, ะฟั€ะพะฑะปะตะผ ะฑะตะทะฟะตะบะธ, ั€ะพะทัะธะฝั…ั€ะพะฝั–ะทะฐั†ั–ั— ะบะพะดัƒ (ะบะพะปะธ ะฒะธ ะพะฝะพะฒะปัŽั”ั‚ะต ะฒ ะพะดะฝะพะผัƒ ะผั–ัั†ั–, ะฐะปะต ะฝะต ะฒ ั–ะฝัˆะธั…) ั‚ะพั‰ะพ. + +ะ† ั†ั– ะผะพะดะตะปั– ัะฟั–ะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฑะฐะณะฐั‚ะพ ะดะฐะฝะธั… ั‚ะฐ ะดัƒะฑะปัŽัŽั‚ัŒ ะฝะฐะทะฒะธ ั– ั‚ะธะฟะธ ะฐั‚ั€ะธะฑัƒั‚ั–ะฒ. + +ะœะพะถะฝะฐ ะทั€ะพะฑะธั‚ะธ ะบั€ะฐั‰ะต. + +ะœะพะถะฝะฐ ะพะณะพะปะพัะธั‚ะธ ะผะพะดะตะปัŒ `UserBase`, ัะบะฐ ะฑัƒะดะต ะฑะฐะทะพะฒะพัŽ ะดะปั ั–ะฝัˆะธั… ะผะพะดะตะปะตะน. ะŸะพั‚ั–ะผ ัั‚ะฒะพั€ะธั‚ะธ ะฟั–ะดะบะปะฐัะธ ั†ั–ั”ั— ะผะพะดะตะปั–, ั‰ะพ ะฝะฐัะปั–ะดัƒะฒะฐั‚ะธะผัƒั‚ัŒ ั—ั— ะฐั‚ั€ะธะฑัƒั‚ะธ (ะพะณะพะปะพัˆะตะฝะฝั ั‚ะธะฟั–ะฒ, ะฒะฐะปั–ะดะฐั†ั–ัŽ ั‚ะพั‰ะพ). + +ะฃัั ะบะพะฝะฒะตั€ั‚ะฐั†ั–ั ะดะฐะฝะธั…, ะฒะฐะปั–ะดะฐั†ั–ั, ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั ั‚ะพั‰ะพ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผัƒั‚ัŒ ัะบ ะทะฐะทะฒะธั‡ะฐะน. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ะปะธัˆะต ะฒั–ะดะผั–ะฝะฝะพัั‚ั– ะผั–ะถ ะผะพะดะตะปัะผะธ (ะท ะฒั–ะดะบั€ะธั‚ะธะผ `password`, ะท `hashed_password` ั– ะฑะตะท ะฟะฐั€ะพะปั): + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` ะฐะฑะพ `anyOf` { #union-or-anyof } + +ะ’ะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ ัะบ `Union` ะดะฒะพั… ะฐะฑะพ ะฑั–ะปัŒัˆะต ั‚ะธะฟั–ะฒ - ั†ะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฒั–ะดะฟะพะฒั–ะดัŒ ะผะพะถะต ะฑัƒั‚ะธ ะฑัƒะดัŒ-ัะบะพะณะพ ะท ะฝะธั…. + +ะ’ OpenAPI ั†ะต ะฑัƒะดะต ะฒะธะทะฝะฐั‡ะตะฝะพ ัะบ `anyOf`. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝัƒ ะฟั–ะดะบะฐะทะบัƒ ั‚ะธะฟัƒ Python `typing.Union`: + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะŸั–ะด ั‡ะฐั ะฒะธะทะฝะฐั‡ะตะฝะฝั `Union` ัะฟะพั‡ะฐั‚ะบัƒ ะฒะบะฐะทัƒะนั‚ะต ะฝะฐะนะบะพะฝะบั€ะตั‚ะฝั–ัˆะธะน ั‚ะธะฟ, ะฐ ะฟะพั‚ั–ะผ ะผะตะฝัˆ ะบะพะฝะบั€ะตั‚ะฝะธะน. ะฃ ะฟั€ะธะบะปะฐะดั– ะฝะธะถั‡ะต ะฑั–ะปัŒัˆ ะบะพะฝะบั€ะตั‚ะฝะธะน `PlaneItem` ัั‚ะพั—ั‚ัŒ ะฟะตั€ะตะด `CarItem` ัƒ `Union[PlaneItem, CarItem]`. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### `Union` ัƒ Python 3.10 { #union-in-python-3-10 } + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฟะตั€ะตะดะฐั”ะผะพ `Union[PlaneItem, CarItem]` ัะบ ะทะฝะฐั‡ะตะฝะฝั ะฐั€ะณัƒะผะตะฝั‚ัƒ `response_model`. + +ะžัะบั–ะปัŒะบะธ ะผะธ ะฟะตั€ะตะดะฐั”ะผะพ ะนะพะณะพ ัะบ ะทะฝะฐั‡ะตะฝะฝั ะฐั€ะณัƒะผะตะฝั‚ัƒ, ะฐ ะฝะต ะฒ ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟัƒ, ะฟะพั‚ั€ั–ะฑะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ `Union` ะฝะฐะฒั–ั‚ัŒ ัƒ Python 3.10. + +ะฏะบะฑะธ ั†ะต ะฑัƒะปะฐ ะฐะฝะพั‚ะฐั†ั–ั ั‚ะธะฟัƒ, ะผะพะถะฝะฐ ะฑัƒะปะพ ะฑ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฒะตั€ั‚ะธะบะฐะปัŒะฝัƒ ั€ะธัะบัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: + +```Python +some_variable: PlaneItem | CarItem +``` + +ะะปะต ัะบั‰ะพ ะทะฐะฟะธัะฐั‚ะธ ั†ะต ัะบ ะฟั€ะธัะฒะพั”ะฝะฝั `response_model=PlaneItem | CarItem`, ะพั‚ั€ะธะผะฐั”ะผะพ ะฟะพะผะธะปะบัƒ, ั‚ะพะผัƒ ั‰ะพ Python ัะฟั€ะพะฑัƒั” ะฒะธะบะพะฝะฐั‚ะธ ะฝะตะฒะฐะปั–ะดะฝัƒ ะพะฟะตั€ะฐั†ั–ัŽ ะผั–ะถ `PlaneItem` ั– `CarItem`, ะทะฐะผั–ัั‚ัŒ ั‚ะพะณะพ ั‰ะพะฑ ั‚ั€ะฐะบั‚ัƒะฒะฐั‚ะธ ั†ะต ัะบ ะฐะฝะพั‚ะฐั†ั–ัŽ ั‚ะธะฟัƒ. + +## ะกะฟะธัะพะบ ะผะพะดะตะปะตะน { #list-of-models } + +ะะฝะฐะปะพะณั–ั‡ะฝะพ ะผะพะถะฝะฐ ะพะณะพะปะพัˆัƒะฒะฐั‚ะธ ะฒั–ะดะฟะพะฒั–ะดั– ัะบ ัะฟะธัะบะธ ะพะฑโ€™ั”ะบั‚ั–ะฒ. + +ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ัั‚ะฐะฝะดะฐั€ั‚ะฝะธะน Python `list`: + +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} + +## ะ’ั–ะดะฟะพะฒั–ะดัŒ ะท ะดะพะฒั–ะปัŒะฝะธะผ `dict` { #response-with-arbitrary-dict } + +ะขะฐะบะพะถ ะผะพะถะฝะฐ ะพะณะพะปะพัะธั‚ะธ ะฒั–ะดะฟะพะฒั–ะดัŒ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะทะฒะธั‡ะฐะนะฝะธะน ะดะพะฒั–ะปัŒะฝะธะน `dict`, ะฒะบะฐะทะฐะฒัˆะธ ะปะธัˆะต ั‚ะธะฟะธ ะบะปัŽั‡ั–ะฒ ั– ะทะฝะฐั‡ะตะฝัŒ, ะฑะตะท ะผะพะดะตะปั– Pydantic. + +ะฆะต ะบะพั€ะธัะฝะพ, ัะบั‰ะพ ะฒะธ ะทะฐะทะดะฐะปะตะณั–ะดัŒ ะฝะต ะทะฝะฐั”ั‚ะต ะดะพะฟัƒัั‚ะธะผั– ะฝะฐะทะฒะธ ะฟะพะปั–ะฒ/ะฐั‚ั€ะธะฑัƒั‚ั–ะฒ (ัะบั– ะฑัƒะปะธ ะฑ ะฟะพั‚ั€ั–ะฑะฝั– ะดะปั ะผะพะดะตะปั– Pydantic). + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `dict`: + +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะบั–ะปัŒะบะฐ ะผะพะดะตะปะตะน Pydantic ั– ะฒั–ะปัŒะฝะพ ะฝะฐัะปั–ะดัƒะนั‚ะต ะดะปั ะบะพะถะฝะพะณะพ ะฒะธะฟะฐะดะบัƒ. + +ะะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ ะผะฐั‚ะธ ะพะดะฝัƒ ะผะพะดะตะปัŒ ะดะฐะฝะธั… ะฝะฐ ััƒั‚ะฝั–ัั‚ัŒ, ัะบั‰ะพ ั†ั ััƒั‚ะฝั–ัั‚ัŒ ะผะพะถะต ะผะฐั‚ะธ ั€ั–ะทะฝั– ยซัั‚ะฐะฝะธยป. ะฏะบ ัƒ ะฒะธะฟะฐะดะบัƒ ััƒั‚ะฝะพัั‚ั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะทั– ัั‚ะฐะฝะฐะผะธ: ะท `password`, ะท `password_hash` ั– ะฑะตะท ะฟะฐั€ะพะปั. diff --git a/docs/uk/docs/tutorial/path-operation-configuration.md b/docs/uk/docs/tutorial/path-operation-configuration.md new file mode 100644 index 0000000000..91b58b24ec --- /dev/null +++ b/docs/uk/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# ะะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ { #path-operation-configuration } + +ะ„ ะบั–ะปัŒะบะฐ ะฟะฐั€ะฐะผะตั‚ั€ั–ะฒ, ัะบั– ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ ะฒะฐัˆะพะผัƒ ยซะดะตะบะพั€ะฐั‚ะพั€ัƒ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป ะดะปั ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝั. + +/// warning | ะŸะพะฟะตั€ะตะดะถะตะฝะฝั + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ั†ั– ะฟะฐั€ะฐะผะตั‚ั€ะธ ะฟะตั€ะตะดะฐัŽั‚ัŒัั ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ยซะดะตะบะพั€ะฐั‚ะพั€ัƒ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป, ะฐ ะฝะต ะฒะฐัˆั–ะน ยซั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป. + +/// + +## ะšะพะด ัั‚ะฐั‚ัƒััƒ ะฒั–ะดะฟะพะฒั–ะดั– { #response-status-code } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะทะฝะฐั‡ะธั‚ะธ (HTTP) `status_code`, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ัƒ ะฒั–ะดะฟะพะฒั–ะดั– ะฒะฐัˆะพั— ยซะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป. + +ะœะพะถะฝะฐ ะฟะตั€ะตะดะฐั‚ะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ั†ั–ะปะธะน ะบะพะด, ะฝะฐะฟั€ะธะบะปะฐะด `404`. + +ะฏะบั‰ะพ ะฒะธ ะฝะต ะฟะฐะผ'ัั‚ะฐั”ั‚ะต ะฟั€ะธะทะฝะฐั‡ะตะฝะฝั ั‡ะธัะปะพะฒะธั… ะบะพะดั–ะฒ, ัะบะพั€ะธัั‚ะฐะนั‚ะตัั ัะบะพั€ะพั‡ะตะฝะธะผะธ ะบะพะฝัั‚ะฐะฝั‚ะฐะผะธ ะฒ `status`: + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +ะฆะตะน ะบะพะด ัั‚ะฐั‚ัƒััƒ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ัƒ ะฒั–ะดะฟะพะฒั–ะดั– ั‚ะฐ ะดะพะดะฐะฝะพ ะดะพ ัั…ะตะผะธ OpenAPI. + +/// note | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +ะ’ะธ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ `from starlette import status`. + +FastAPI ะฝะฐะดะฐั” ั‚ะพะน ัะฐะผะธะน `starlette.status` ัะบ `fastapi.status` ะดะปั ะฒะฐัˆะพั— ะทั€ัƒั‡ะฝะพัั‚ั– ัะบ ั€ะพะทั€ะพะฑะฝะธะบะฐ. ะะปะต ะฒั–ะฝ ะฟะพั…ะพะดะธั‚ัŒ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะทั– Starlette. + +/// + +## ะœั–ั‚ะบะธ { #tags } + +ะ’ะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะผั–ั‚ะบะธ ะดะพ ะฒะฐัˆะพั— ยซะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป, ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `tags` ะทั– `list` ั–ะท `str` (ะทะฐะทะฒะธั‡ะฐะน ะปะธัˆะต ะพะดะธะฝ `str`): + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +ะ’ะพะฝะธ ะฑัƒะดัƒั‚ัŒ ะดะพะดะฐะฝั– ะดะพ ัั…ะตะผะธ OpenAPI ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝั– ั–ะฝั‚ะตั€ั„ะตะนัะฐะผะธ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: + + + +### ะœั–ั‚ะบะธ ะท ะฟะตั€ะตะปั–ะบะฐะผะธ { #tags-with-enums } + +ะฃ ะฒะตะปะธะบะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะบะพะฟะธั‡ะธั‚ะธ ะฑะฐะณะฐั‚ะพ ะผั–ั‚ะพะบ ั– ะทะฐั…ะพั‡ะตั‚ะต ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะทะฐะฒะถะดะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั‚ัƒ ัะฐะผัƒ ะผั–ั‚ะบัƒ ะดะปั ะฟะพะฒ'ัะทะฐะฝะธั… ยซะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒยป. + +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะผะฐั” ัะตะฝั ะทะฑะตั€ั–ะณะฐั‚ะธ ะผั–ั‚ะบะธ ะฒ `Enum`. + +FastAPI ะฟั–ะดั‚ั€ะธะผัƒั” ั†ะต ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะทั– ะทะฒะธั‡ะฐะนะฝะธะผะธ ัั‚ั€ะพะบะฐะผะธ: + +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} + +## ะšะพั€ะพั‚ะบะธะน ะพะฟะธั ั– ะพะฟะธั { #summary-and-description } + +ะ’ะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ `summary` ั– `description`: + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## ะžะฟะธั ะทั– ัั‚ั€ะพะบะธ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— { #description-from-docstring } + +ะžัะบั–ะปัŒะบะธ ะพะฟะธัะธ ะทะฐะทะฒะธั‡ะฐะน ะดะพะฒะณั– ั‚ะฐ ะทะฐะนะผะฐัŽั‚ัŒ ะบั–ะปัŒะบะฐ ั€ัะดะบั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ะพะฟะธั ยซะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป ัƒ ัั‚ั€ะพั†ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ั„ัƒะฝะบั†ั–ั—, ั– FastAPI ะฟั€ะพั‡ะธั‚ะฐั” ะนะพะณะพ ะทะฒั–ะดั‚ะธ. + +ะ’ะธ ะผะพะถะตั‚ะต ะฟะธัะฐั‚ะธ Markdown ัƒ ัั‚ั€ะพั†ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—, ะนะพะณะพ ะฑัƒะดะต ั–ะฝั‚ะตั€ะฟั€ะตั‚ะพะฒะฐะฝะพ ั‚ะฐ ะฟะพะบะฐะทะฐะฝะพ ะบะพั€ะตะบั‚ะฝะพ (ะท ัƒั€ะฐั…ัƒะฒะฐะฝะฝัะผ ะฒั–ะดัั‚ัƒะฟั–ะฒ ัƒ ัั‚ั€ะพั†ั– ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—). + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +ะ™ะพะณะพ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะฒ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: + + + +## ะžะฟะธั ะฒั–ะดะฟะพะฒั–ะดั– { #response-description } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะบะฐะทะฐั‚ะธ ะพะฟะธั ะฒั–ะดะฟะพะฒั–ะดั– ะฟะฐั€ะฐะผะตั‚ั€ะพะผ `response_description`: + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ `response_description` ัั‚ะพััƒั”ั‚ัŒัั ัะฐะผะต ะฒั–ะดะฟะพะฒั–ะดั–, ะฐ `description` ัั‚ะพััƒั”ั‚ัŒัั ยซะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป ะทะฐะณะฐะปะพะผ. + +/// + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +OpenAPI ะฒะธะทะฝะฐั‡ะฐั”, ั‰ะพ ะบะพะถะฝะฐ ยซะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒยป ะฟะพั‚ั€ะตะฑัƒั” ะพะฟะธััƒ ะฒั–ะดะฟะพะฒั–ะดั–. + +ะขะพะผัƒ, ัะบั‰ะพ ะฒะธ ะนะพะณะพ ะฝะต ะฝะฐะดะฐัั‚ะต, FastAPI ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ัƒั” ยซSuccessful responseยป. + +/// + + + +## ะŸะพะทะฝะฐั‡ะธั‚ะธ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ ัะบ ะทะฐัั‚ะฐั€ั–ะปัƒ { #deprecate-a-path-operation } + +ะฏะบั‰ะพ ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะพะทะฝะฐั‡ะธั‚ะธ ยซะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒยป ัะบ ะทะฐัั‚ะฐั€ั–ะปัƒ, ะฐะปะต ะฝะต ะฒะธะดะฐะปััŽั‡ะธ ั—ั—, ะฟะตั€ะตะดะฐะนั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ `deprecated`: + +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} + +ะฃ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒะพะฝะฐ ะฑัƒะดะต ั‡ั–ั‚ะบะพ ะฟะพะทะฝะฐั‡ะตะฝะฐ ัะบ ะทะฐัั‚ะฐั€ั–ะปะฐ: + + + +ะŸะพะดะธะฒั–ั‚ัŒัั, ัะบ ะฒะธะณะปัะดะฐัŽั‚ัŒ ะทะฐัั‚ะฐั€ั–ะปั– ั‚ะฐ ะฝะตะทะฐัั‚ะฐั€ั–ะปั– ยซะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒยป: + + + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฝะฐะปะฐัˆั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะฐ ะดะพะดะฐะฒะฐั‚ะธ ะผะตั‚ะฐะดะฐะฝั– ะดะพ ะฒะฐัˆะธั… ยซะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒยป, ะฟะตั€ะตะดะฐัŽั‡ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ ยซะดะตะบะพั€ะฐั‚ะพั€ะฐะผ ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒยป. diff --git a/docs/uk/docs/tutorial/security/first-steps.md b/docs/uk/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000..491328d865 --- /dev/null +++ b/docs/uk/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# ะ‘ะตะทะฟะตะบะฐ - ะฟะตั€ัˆั– ะบั€ะพะบะธ { #security-first-steps } + +ะฃัะฒั–ะผะพ, ั‰ะพ ะฒะฐัˆ **backend** API ะฟั€ะฐั†ัŽั” ะฝะฐ ะฟะตะฒะฝะพะผัƒ ะดะพะผะตะฝั–. + +ะ **frontend** - ะฝะฐ ั–ะฝัˆะพะผัƒ ะดะพะผะตะฝั– ะฐะฑะพ ะฒ ั–ะฝัˆะพะผัƒ ัˆะปัั…ัƒ ั‚ะพะณะพ ะถ ะดะพะผะตะฝัƒ (ะฐะฑะพ ัƒ ะผะพะฑั–ะปัŒะฝะพะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ). + +ะ† ะฒะธ ั…ะพั‡ะตั‚ะต, ั‰ะพะฑ frontend ะผั–ะณ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธัั ะฒ backend, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฟะฐั€ะพะปัŒ. + +ะœะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ **OAuth2**, ั‰ะพะฑ ะทะฑัƒะดัƒะฒะฐั‚ะธ ั†ะต ะท **FastAPI**. + +ะะปะต ะทะฐะพั‰ะฐะดะธะผะพ ะฒะฐะผ ั‡ะฐั ะฝะฐ ั‡ะธั‚ะฐะฝะฝั ะฒัั–ั”ั— ะดะพะฒะณะพั— ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั—, ั‰ะพะฑ ะทะฝะฐะนั‚ะธ ะปะธัˆะต ะฟะพั‚ั€ั–ะฑะฝั– ะดั€ั–ะฑะฝะธั†ั–. + +ะกะบะพั€ะธัั‚ะฐะนะผะพัั ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ, ัะบั– ะฝะฐะดะฐั” **FastAPI**, ั‰ะพะฑ ะพะฑั€ะพะฑะปัั‚ะธ ะฑะตะทะฟะตะบัƒ. + +## ะฏะบ ั†ะต ะฒะธะณะปัะดะฐั” { #how-it-looks } + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฟั€ะพัั‚ะพ ะทะฐะฟัƒัั‚ั–ะผะพ ะบะพะด ั– ะฟะพะดะธะฒั–ะผะพัั, ัะบ ะฒั–ะฝ ะฟั€ะฐั†ัŽั”, ะฐ ะฟะพั‚ั–ะผ ะฟะพะฒะตั€ะฝะตะผะพัั, ั‰ะพะฑ ั€ะพะทั–ะฑั€ะฐั‚ะธัั, ั‰ะพ ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั. + +## ะกั‚ะฒะพั€ั–ั‚ัŒ `main.py` { #create-main-py } + +ะกะบะพะฟั–ัŽะนั‚ะต ะฟั€ะธะบะปะฐะด ัƒ ั„ะฐะนะป `main.py`: + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ { #run-it } + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะŸะฐะบะตั‚ `python-multipart` ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ัŒัั ะท **FastAPI**, ะบะพะปะธ ะฒะธ ะฒะธะบะพะฝัƒั”ั‚ะต ะบะพะผะฐะฝะดัƒ `pip install "fastapi[standard]"`. + +ะžะดะฝะฐะบ, ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะบะพะผะฐะฝะดัƒ `pip install fastapi`, ะฟะฐะบะตั‚ `python-multipart` ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ะฝะต ะฒะบะปัŽั‡ะตะฝะพ. + +ะฉะพะฑ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะนะพะณะพ ะฒั€ัƒั‡ะฝัƒ, ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ, ะฐ ะฟะพั‚ั–ะผ ะฒัั‚ะฐะฝะพะฒะธะปะธ: + +```console +$ pip install python-multipart +``` + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ **OAuth2** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ยซform dataยป ะดะปั ะฝะฐะดัะธะปะฐะฝะฝั `username` ั‚ะฐ `password`. + +/// + +ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ะฟั€ะธะบะปะฐะด: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะŸะตั€ะตะนะดั–ั‚ัŒ ะดะพ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ั‰ะพััŒ ะฟะพะดั–ะฑะฝะต: + + + +/// check | ะšะฝะพะฟะบะฐ Authorize! + +ะฃ ะฒะฐั ัƒะถะต ั” ะฝะพะฒะฐ ะฑะปะธัะบัƒั‡ะฐ ะบะฝะพะฟะบะฐ ยซAuthorizeยป. + +ะ ะฒะฐัˆะฐ *ะพะฟะตั€ะฐั†ั–ั ัˆะปัั…ัƒ* ะผะฐั” ะผะฐะปะตะฝัŒะบะธะน ะทะฐะผะพะบ ัƒ ะฟั€ะฐะฒะพะผัƒ ะฒะตั€ั…ะฝัŒะพะผัƒ ะบัƒั‚ั–, ะฝะฐ ัะบะธะน ะผะพะถะฝะฐ ะฝะฐั‚ะธัะฝัƒั‚ะธ. + +/// + +ะฏะบั‰ะพ ะฝะฐั‚ะธัะฝัƒั‚ะธ ั—ั—, ะทโ€™ัะฒะธั‚ัŒัั ะผะฐะปะตะฝัŒะบะฐ ั„ะพั€ะผะฐ ะฐะฒั‚ะพั€ะธะทะฐั†ั–ั—, ั‰ะพะฑ ะฒะฒะตัั‚ะธ `username` ั– `password` (ั‚ะฐ ั–ะฝัˆั– ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒั– ะฟะพะปั): + + + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะะตะฒะฐะถะปะธะฒะพ, ั‰ะพ ะฒะธ ะฒะฒะตะดะตั‚ะต ัƒ ั„ะพั€ะผัƒ, ะฟะพะบะธ ั‰ะพ ั†ะต ะฝะต ัะฟั€ะฐั†ัŽั”. ะะปะต ะผะธ ัะบะพั€ะพ ั†ะต ะดะพั€ะพะฑะธะผะพ. + +/// + +ะ—ะฒั–ัะฝะพ, ั†ะต ะฝะต frontend ะดะปั ะบั–ะฝั†ะตะฒะธั… ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, ะฐะปะต ั†ะต ั‡ัƒะดะพะฒะธะน ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะฒััŒะพะณะพ ะฒะฐัˆะพะณะพ API. + +ะะธะผ ะผะพะถะต ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธัั ะบะพะผะฐะฝะดะฐ frontend (ัะบะพัŽ ะผะพะถะตั‚ะต ะฑัƒั‚ะธ ั– ะฒะธ ัะฐะผั–). + +ะะธะผ ะผะพะถัƒั‚ัŒ ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธัั ัั‚ะพั€ะพะฝะฝั– ะทะฐัั‚ะพััƒะฝะบะธ ั‚ะฐ ัะธัั‚ะตะผะธ. + +ะ† ะฝะธะผ ั‚ะฐะบะพะถ ะผะพะถะตั‚ะต ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธัั ะฒะธ ัะฐะผั–, ั‰ะพะฑ ะฝะฐะปะฐะณะพะดะถัƒะฒะฐั‚ะธ, ะฟะตั€ะตะฒั–ั€ัั‚ะธ ั‚ะฐ ั‚ะตัั‚ัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ะทะฐัั‚ะพััƒะฝะพะบ. + +## ะŸะพั‚ั–ะบ ะฟะฐั€ะพะปัŽ { #the-password-flow } + +ะขะตะฟะตั€ ะฟะพะฒะตั€ะฝั–ะผะพัั ั‚ั€ะพั…ะธ ะฝะฐะทะฐะด ั– ั€ะพะทะฑะตั€ั–ะผะพัั, ั‰ะพ ั†ะต ะฒัะต ั‚ะฐะบะต. + +`password` ยซflowยป - ั†ะต ะพะดะธะฝ ะทั– ัะฟะพัะพะฑั–ะฒ (ยซflowsยป), ะฒะธะทะฝะฐั‡ะตะฝะธั… ะฒ OAuth2, ะดะปั ะพะฑั€ะพะฑะบะธ ะฑะตะทะฟะตะบะธ ั‚ะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—. + +OAuth2 ะฑัƒะฒ ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะธะน ั‚ะฐะบ, ั‰ะพะฑ backend ะฐะฑะพ API ะผะพะณะปะธ ะฑัƒั‚ะธ ะฝะตะทะฐะปะตะถะฝะธะผะธ ะฒั–ะด ัะตั€ะฒะตั€ะฐ, ัะบะธะน ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒั” ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะะปะต ะฒ ะฝะฐัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ ั‚ะพะน ัะฐะผะธะน ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI** ะพะฑั€ะพะฑะปัั‚ะธะผะต ั– API, ั– ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ัŽ. + +ะขะพะถ ั€ะพะทะณะปัะฝัŒะผะพ ั†ะต ัƒ ัะฟั€ะพั‰ะตะฝะพะผัƒ ะฒะธะณะปัะดั–: + +- ะšะพั€ะธัั‚ัƒะฒะฐั‡ ะฒะฒะพะดะธั‚ัŒ `username` ั– `password` ัƒ frontend ั– ะฝะฐั‚ะธัะบะฐั” `Enter`. +- Frontend (ัƒ ะฑั€ะฐัƒะทะตั€ั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ) ะฝะฐะดัะธะปะฐั” ั†ั– `username` ั– `password` ะฝะฐ ัะฟะตั†ะธั„ั–ั‡ะฝัƒ URL-ะฐะดั€ะตััƒ ะฝะฐัˆะพะณะพ API (ะพะณะพะปะพัˆะตะฝัƒ ัะบ `tokenUrl="token"`). +- API ะฟะตั€ะตะฒั–ั€ัั” ั†ั– `username` ั– `password` ั‚ะฐ ะฟะพะฒะตั€ั‚ะฐั” ยซั‚ะพะบะตะฝยป (ะผะธ ั‰ะต ะฝั–ั‡ะพะณะพ ะท ั†ัŒะพะณะพ ะฝะต ั€ะตะฐะปั–ะทัƒะฒะฐะปะธ). + - ยซะขะพะบะตะฝยป - ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะฐ ะท ะดะตัะบะธะผ ะฒะผั–ัั‚ะพะผ, ัะบะธะน ะผะธ ะผะพะถะตะผะพ ะฟั–ะทะฝั–ัˆะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ ั†ัŒะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + - ะ—ะฐะทะฒะธั‡ะฐะน ั‚ะพะบะตะฝ ะฝะฐะปะฐัˆั‚ะพะฒะฐะฝะธะน ะฝะฐ ะทะฐะฒะตั€ัˆะตะฝะฝั ัั‚ั€ะพะบัƒ ะดั–ั— ั‡ะตั€ะตะท ะฟะตะฒะฝะธะน ั‡ะฐั. + - ะขะพะถ ะบะพั€ะธัั‚ัƒะฒะฐั‡ัƒ ะดะพะฒะตะดะตั‚ัŒัั ะทะฝะพะฒัƒ ัƒะฒั–ะนั‚ะธ ะฟั–ะทะฝั–ัˆะต. + - ะ† ัะบั‰ะพ ั‚ะพะบะตะฝ ะฒะธะบั€ะฐะดัƒั‚ัŒ, ั€ะธะทะธะบ ะผะตะฝัˆะธะน. ะฆะต ะฝะต ัะบ ะฟะพัั‚ั–ะนะฝะธะน ะบะปัŽั‡, ัะบะธะน ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต ะทะฐะฒะถะดะธ (ัƒ ะฑั–ะปัŒัˆะพัั‚ั– ะฒะธะฟะฐะดะบั–ะฒ). +- Frontend ั‚ะธะผั‡ะฐัะพะฒะพ ะทะฑะตั€ั–ะณะฐั” ั†ะตะน ั‚ะพะบะตะฝ ะดะตััŒ. +- ะšะพั€ะธัั‚ัƒะฒะฐั‡ ะบะปั–ะบะฐั” ัƒ frontend, ั‰ะพะฑ ะฟะตั€ะตะนั‚ะธ ะดะพ ั–ะฝัˆะพะณะพ ั€ะพะทะดั–ะปัƒ ะฒะตะฑะทะฐัั‚ะพััƒะฝะบัƒ. +- Frontend ะผะฐั” ะพั‚ั€ะธะผะฐั‚ะธ ั‰ะต ะดะฐะฝั– ะท API. + - ะะปะต ะดะปั ั‚ะพะณะพ ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะบั–ะฝั†ะตะฒะพะณะพ ะฟัƒะฝะบั‚ัƒ ะฟะพั‚ั€ั–ะฑะฝะฐ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั. + - ะขะพะถ, ั‰ะพะฑ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธัั ะฒ ะฝะฐัˆะพะผัƒ API, ะฒั–ะฝ ะฝะฐะดัะธะปะฐั” ะทะฐะณะพะปะพะฒะพะบ `Authorization` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `Bearer ` ะฟะปัŽั ั‚ะพะบะตะฝ. + - ะฏะบั‰ะพ ั‚ะพะบะตะฝ ะผั–ัั‚ะธั‚ัŒ `foobar`, ะฒะผั–ัั‚ ะทะฐะณะพะปะพะฒะบะฐ `Authorization` ะฑัƒะดะต: `Bearer foobar`. + +## `OAuth2PasswordBearer` ัƒ **FastAPI** { #fastapis-oauth2passwordbearer } + +**FastAPI** ะฝะฐะดะฐั” ะบั–ะปัŒะบะฐ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ ะฝะฐ ั€ั–ะทะฝะธั… ั€ั–ะฒะฝัั… ะฐะฑัั‚ั€ะฐะบั†ั–ั—, ั‰ะพะฑ ั€ะตะฐะปั–ะทัƒะฒะฐั‚ะธ ั†ั– ั„ัƒะฝะบั†ั–ั— ะฑะตะทะฟะตะบะธ. + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ **OAuth2** ะท ะฟะพั‚ะพะบะพะผ **Password**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะบะตะฝ **Bearer**. ะฆะต ั€ะพะฑะธั‚ัŒัั ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะบะปะฐััƒ `OAuth2PasswordBearer`. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ยซBearerยป-ั‚ะพะบะตะฝ - ะฝะต ั”ะดะธะฝะธะน ะฒะฐั€ั–ะฐะฝั‚. + +ะะปะต ั†ะต ะฝะฐะนะบั€ะฐั‰ะธะน ะดะปั ะฝะฐัˆะพะณะพ ัั†ะตะฝะฐั€ั–ัŽ. + +ะ†, ะผะพะถะปะธะฒะพ, ะฝะฐะนะบั€ะฐั‰ะธะน ะดะปั ะฑั–ะปัŒัˆะพัั‚ั– ัั†ะตะฝะฐั€ั–ั—ะฒ, ัะบั‰ะพ ะฒะธ ะฝะต ะตะบัะฟะตั€ั‚ ะท OAuth2 ั– ั‚ะพั‡ะฝะพ ะฝะต ะทะฝะฐั”ั‚ะต, ั‡ะพะผัƒ ั–ะฝัˆะฐ ะพะฟั†ั–ั ะบั€ะฐั‰ะต ะฒั–ะดะฟะพะฒั–ะดะฐั” ะฒะฐัˆะธะผ ะฟะพั‚ั€ะตะฑะฐะผ. + +ะฃ ั‚ะฐะบะพะผัƒ ั€ะฐะทั– **FastAPI** ั‚ะตะถ ะฝะฐะดะฐั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ั‰ะพะฑ ั†ะต ะทะฑัƒะดัƒะฒะฐั‚ะธ. + +/// + +ะšะพะปะธ ะผะธ ัั‚ะฒะพั€ัŽั”ะผะพ ะตะบะทะตะผะฟะปัั€ ะบะปะฐััƒ `OAuth2PasswordBearer`, ะผะธ ะฟะตั€ะตะดะฐั”ะผะพ ะฟะฐั€ะฐะผะตั‚ั€ `tokenUrl`. ะฆะตะน ะฟะฐั€ะฐะผะตั‚ั€ ะผั–ัั‚ะธั‚ัŒ URL, ัะบะธะน ะบะปั–ั”ะฝั‚ (frontend ัƒ ะฑั€ะฐัƒะทะตั€ั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ) ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต, ั‰ะพะฑ ะฝะฐะดั–ัะปะฐั‚ะธ `username` ั– `password` ะดะปั ะพั‚ั€ะธะผะฐะฝะฝั ั‚ะพะบะตะฝะฐ. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขัƒั‚ `tokenUrl="token"` ะฒั–ะดะฝะพัะธั‚ัŒัั ะดะพ ะฒั–ะดะฝะพัะฝะพั— URL-ะฐะดั€ะตัะธ `token`, ัะบัƒ ะผะธ ั‰ะต ะฝะต ัั‚ะฒะพั€ะธะปะธ. ะžัะบั–ะปัŒะบะธ ั†ะต ะฒั–ะดะฝะพัะฝะฐ URL-ะฐะดั€ะตัะฐ, ะฒะพะฝะฐ ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะฐ `./token`. + +ะขะพะผัƒ, ัะบั‰ะพ ะฒะฐัˆ API ั€ะพะทะผั–ั‰ะตะฝะธะน ะฝะฐ `https://example.com/`, ั†ะต ะฑัƒะดะต `https://example.com/token`. ะ ัะบั‰ะพ ะฝะฐ `https://example.com/api/v1/`, ั‚ะพะดั– ั†ะต ะฑัƒะดะต `https://example.com/api/v1/token`. + +ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒั–ะดะฝะพัะฝะพั— URL-ะฐะดั€ะตัะธ ะฒะฐะถะปะธะฒะต, ั‰ะพะฑ ะฒะฐัˆะฐ ะฟั€ะพะณั€ะฐะผะฐ ะฟั€ะพะดะพะฒะถัƒะฒะฐะปะฐ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐะฒั–ั‚ัŒ ัƒ ะฟั€ะพััƒะฝัƒั‚ะพะผัƒ ัั†ะตะฝะฐั€ั–ั—, ัะบ-ะพั‚ [Behind a Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}. + +/// + +ะฆะตะน ะฟะฐั€ะฐะผะตั‚ั€ ะฝะต ัั‚ะฒะพั€ัŽั” ั‚ะพะน endpoint / *ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ*, ะฐ ะดะตะบะปะฐั€ัƒั”, ั‰ะพ URL `/token` ะฑัƒะดะต ั‚ะธะผ, ัะบะธะน ะบะปั–ั”ะฝั‚ ะผะฐั” ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ั‚ะพะบะตะฝ. ะฆั ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ะฒ OpenAPI, ะฐ ะฟะพั‚ั–ะผ - ัƒ ัะธัั‚ะตะผะฐั… ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝะพั— ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API. + +ะะตะทะฐะฑะฐั€ะพะผ ะผะธ ั‚ะฐะบะพะถ ัั‚ะฒะพั€ะธะผะพ ั„ะฐะบั‚ะธั‡ะฝัƒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะดัƒะถะต ัั‚ั€ะพะณะธะน ยซPythonistaยป, ะฒะฐะผ ะผะพะถะต ะฝะต ะฟะพะดะพะฑะฐั‚ะธัั ัั‚ะธะปัŒ ั–ะผะตะฝั– ะฟะฐั€ะฐะผะตั‚ั€ะฐ `tokenUrl` ะทะฐะผั–ัั‚ัŒ `token_url`. + +ะฆะต ั‚ะพะผัƒ, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ั‚ัƒ ัะฐะผัƒ ะฝะฐะทะฒัƒ, ั‰ะพ ั– ะฒ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั— OpenAPI. ะขะพะถ ัะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะดะต ะดะพัะปั–ะดะธั‚ะธ ั†ั– ัั…ะตะผะธ ะฑะตะทะฟะตะบะธ ะณะปะธะฑัˆะต, ะฒะธ ะทะผะพะถะตั‚ะต ะฟั€ะพัั‚ะพ ัะบะพะฟั–ัŽะฒะฐั‚ะธ ั‚ะฐ ะฒัั‚ะฐะฒะธั‚ะธ ั—ั—, ั‰ะพะฑ ะทะฝะฐะนั‚ะธ ะฑั–ะปัŒัˆะต ั–ะฝั„ะพั€ะผะฐั†ั–ั—. + +/// + +ะ—ะผั–ะฝะฝะฐ `oauth2_scheme` - ั†ะต ะตะบะทะตะผะฟะปัั€ `OAuth2PasswordBearer`, ะฐะปะต ั†ะต ั‚ะฐะบะพะถ ั– ยซะฒะธะบะปะธะบะฐั”ะผะธะนยป ะพะฑโ€™ั”ะบั‚. + +ะ™ะพะณะพ ะผะพะถะฝะฐ ะฒะธะบะปะธะบะฐั‚ะธ ั‚ะฐะบ: + +```Python +oauth2_scheme(some, parameters) +``` + +ะขะพะถ ะนะพะณะพ ะผะพะถะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะท `Depends`. + +### ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั { #use-it } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะดะฐั‚ะธ `oauth2_scheme` ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั‡ะตั€ะตะท `Depends`. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +ะฆั ะทะฐะปะตะถะฝั–ัั‚ัŒ ะฝะฐะดะฐัั‚ัŒ `str`, ัะบะธะน ะฑัƒะดะต ะฟั€ะธัะฒะพั”ะฝะธะน ะฟะฐั€ะฐะผะตั‚ั€ัƒ `token` *ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ*. + +**FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ัŽ ะทะฐะปะตะถะฝั–ัั‚ัŒ, ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ยซัั…ะตะผัƒ ะฑะตะทะฟะตะบะธยป ะฒ ัั…ะตะผั– OpenAPI (ั– ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API). + +/// info | ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– + +**FastAPI** ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะบะปะฐั `OAuth2PasswordBearer` (ะพะณะพะปะพัˆะตะฝะธะน ัƒ ะทะฐะปะตะถะฝะพัั‚ั–), ั‰ะพะฑ ะฒะธะทะฝะฐั‡ะธั‚ะธ ัั…ะตะผัƒ ะฑะตะทะฟะตะบะธ ะฒ OpenAPI, ั‚ะพะผัƒ ั‰ะพ ะฒั–ะฝ ะฝะฐัะปั–ะดัƒั” `fastapi.security.oauth2.OAuth2`, ัะบะธะน ัะฒะพั”ัŽ ั‡ะตั€ะณะพัŽ ะฝะฐัะปั–ะดัƒั” `fastapi.security.base.SecurityBase`. + +ะฃัั– ัƒั‚ะธะปั–ั‚ะธ ะฑะตะทะฟะตะบะธ, ัะบั– ั–ะฝั‚ะตะณั€ัƒัŽั‚ัŒัั ะท OpenAPI (ั– ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั”ัŽ API), ะฝะฐัะปั–ะดัƒัŽั‚ัŒ `SecurityBase`. ะขะฐะบ **FastAPI** ั€ะพะทัƒะผั–ั”, ัะบ ั–ะฝั‚ะตะณั€ัƒะฒะฐั‚ะธ ั—ั… ะฒ OpenAPI. + +/// + +## ะฉะพ ะฒั–ะดะฑัƒะฒะฐั”ั‚ัŒัั { #what-it-does } + +ะ’ะพะฝะฐ ัˆัƒะบะฐั‚ะธะผะต ะฒ ะทะฐะฟะธั‚ั– ะทะฐะณะพะปะพะฒะพะบ `Authorization`, ะฟะตั€ะตะฒั–ั€ะธั‚ัŒ, ั‡ะธ ะนะพะณะพ ะทะฝะฐั‡ะตะฝะฝั - ั†ะต `Bearer ` ะฟะปัŽั ะดะตัะบะธะน ั‚ะพะบะตะฝ, ั– ะฟะพะฒะตั€ะฝะต ั‚ะพะบะตะฝ ัะบ `str`. + +ะฏะบั‰ะพ ะทะฐะณะพะปะพะฒะบะฐ `Authorization` ะฝะตะผะฐั” ะฐะฑะพ ะทะฝะฐั‡ะตะฝะฝั ะฝะต ะผั–ัั‚ะธั‚ัŒ ั‚ะพะบะตะฝะฐ `Bearer `, ะฒะพะฝะฐ ะพะดั€ะฐะทัƒ ะฒั–ะดะฟะพะฒั–ัั‚ัŒ ะฟะพะผะธะปะบะพัŽ ะทั– ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ 401 (`UNAUTHORIZED`). + +ะ’ะฐะผ ะฝะฐะฒั–ั‚ัŒ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฟะตั€ะตะฒั–ั€ัั‚ะธ, ั‡ะธ ั–ัะฝัƒั” ั‚ะพะบะตะฝ, ั‰ะพะฑ ะฟะพะฒะตั€ะฝัƒั‚ะธ ะฟะพะผะธะปะบัƒ. ะ’ะธ ะผะพะถะตั‚ะต ะฑัƒั‚ะธ ะฟะตะฒะฝั–: ัะบั‰ะพ ะฒะฐัˆะฐ ั„ัƒะฝะบั†ั–ั ะฒะธะบะพะฝัƒั”ั‚ัŒัั, ัƒ ะฟะฐั€ะฐะผะตั‚ั€ั– ั‚ะพะบะตะฝะฐ ะฑัƒะดะต `str`. + +ะ’ะธ ะฒะถะต ะผะพะถะตั‚ะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ั†ะต ะฒ ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝั–ะน ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: + + + +ะœะธ ั‰ะต ะฝะต ะฟะตั€ะตะฒั–ั€ัั”ะผะพ ะดั–ะนัะฝั–ัั‚ัŒ ั‚ะพะบะตะฝะฐ, ะฐะปะต ั†ะต ะฒะถะต ะฟะพั‡ะฐั‚ะพะบ. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะžั‚ะถะต, ะปะธัˆะต 3-4 ะดะพะดะฐั‚ะบะพะฒะธะผะธ ั€ัะดะบะฐะผะธ ะฒะธ ะฒะถะต ะผะฐั”ั‚ะต ะดะตัะบัƒ ะฟั€ะธะผั–ั‚ะธะฒะฝัƒ ั„ะพั€ะผัƒ ะฑะตะทะฟะตะบะธ. diff --git a/docs/uk/docs/tutorial/security/get-current-user.md b/docs/uk/docs/tutorial/security/get-current-user.md new file mode 100644 index 0000000000..2371ad9fc0 --- /dev/null +++ b/docs/uk/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# ะžั‚ั€ะธะผะฐั‚ะธ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #get-current-user } + +ะฃ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั– ัะธัั‚ะตะผะฐ ะฑะตะทะฟะตะบะธ (ัะบะฐ ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ ัะธัั‚ะตะผั– ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน) ะฟะตั€ะตะดะฐะฒะฐะปะฐ ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ `token` ัะบ `str`: + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +ะะปะต ั†ะต ั‰ะต ะฝะต ะดัƒะถะต ะบะพั€ะธัะฝะพ. + +ะ—ั€ะพะฑั–ะผะพ ั‚ะฐะบ, ั‰ะพะฑ ะฒะพะฝะฐ ะฟะพะฒะตั€ั‚ะฐะปะฐ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +## ะกั‚ะฒะพั€ะธั‚ะธ ะผะพะดะตะปัŒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #create-a-user-model } + +ะกะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ั–ะผะพ ะผะพะดะตะปัŒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฒ Pydantic. + +ะขะฐะบ ัะฐะผะพ, ัะบ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ Pydantic ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ั‚ั–ะป, ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ะฑัƒะดัŒ-ะดะต: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} + +## ะกั‚ะฒะพั€ะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user` { #create-a-get-current-user-dependency } + +ะกั‚ะฒะพั€ั–ะผะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user`. + +ะŸะฐะผ'ัั‚ะฐั”ั‚ะต, ั‰ะพ ะทะฐะปะตะถะฝะพัั‚ั– ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั–? + +`get_current_user` ะผะฐั‚ะธะผะต ะทะฐะปะตะถะฝั–ัั‚ัŒ ั–ะท ั‚ะธะผ ัะฐะผะธะผ `oauth2_scheme`, ัะบะธะน ะผะธ ัั‚ะฒะพั€ะธะปะธ ั€ะฐะฝั–ัˆะต. + +ะขะฐะบ ัะฐะผะพ, ัะบ ะผะธ ั€ะพะฑะธะปะธ ั€ะฐะฝั–ัˆะต ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ, ะฝะฐัˆะฐ ะฝะพะฒะฐ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user` ะพั‚ั€ะธะผะฐั” `token` ัะบ `str` ะฒั–ะด ะฟั–ะดะทะฐะปะตะถะฝะพัั‚ั– `oauth2_scheme`: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## ะžั‚ั€ะธะผะฐั‚ะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #get-the-user } + +`get_current_user` ะฒะธะบะพั€ะธัั‚ะฐั” (ั„ะฐะปัŒัˆะธะฒัƒ) ัƒั‚ะธะปั–ั‚ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ, ัะบัƒ ะผะธ ัั‚ะฒะพั€ะธะปะธ, ั‰ะพ ะฟั€ะธะนะผะฐั” `token` ัะบ `str` ั– ะฟะพะฒะตั€ั‚ะฐั” ะฝะฐัˆัƒ Pydantic-ะผะพะดะตะปัŒ `User`: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## ะ’ะฟั€ะพะฒะฐะดะธั‚ะธ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #inject-the-current-user } + +ะขะตะฟะตั€ ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน `Depends` ะท ะฝะฐัˆะธะผ `get_current_user` ะฒ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ ั‚ะธะฟ `current_user` ัะบ Pydantic-ะผะพะดะตะปัŒ `User`. + +ะฆะต ะดะพะฟะพะผะพะถะต ะฒัะตั€ะตะดะธะฝั– ั„ัƒะฝะบั†ั–ั— ะท ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝัะผ ั– ะฟะตั€ะตะฒั–ั€ะบะฐะผะธ ั‚ะธะฟั–ะฒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะœะพะถะปะธะฒะพ, ะฒะธ ะฟะฐะผ'ัั‚ะฐั”ั‚ะต, ั‰ะพ ั‚ั–ะปะฐ ะทะฐะฟะธั‚ัƒ ั‚ะฐะบะพะถ ะพะณะพะปะพัˆัƒัŽั‚ัŒัั ะผะพะดะตะปัะผะธ Pydantic. + +ะขัƒั‚ **FastAPI** ะฝะต ะทะฐะฟะปัƒั‚ะฐั”ั‚ัŒัั, ั‚ะพะผัƒ ั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `Depends`. + +/// + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +ะขะต, ัะบ ัะฟั€ะพั”ะบั‚ะพะฒะฐะฝะฐ ั†ั ัะธัั‚ะตะผะฐ ะทะฐะปะตะถะฝะพัั‚ะตะน, ะดะพะทะฒะพะปัั” ะผะฐั‚ะธ ั€ั–ะทะฝั– ะทะฐะปะตะถะฝะพัั‚ั– (ั€ั–ะทะฝั– ยซะทะฐะปะตะถะฝั–ยป), ัะบั– ะฒัั– ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒ ะผะพะดะตะปัŒ `User`. + +ะœะธ ะฝะต ะพะฑะผะตะถะตะฝั– ะฝะฐัะฒะฝั–ัั‚ัŽ ะปะธัˆะต ะพะดะฝั–ั”ั— ะทะฐะปะตะถะฝะพัั‚ั–, ั‰ะพ ะผะพะถะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ ั‚ะฐะบั– ะดะฐะฝั–. + +/// + +## ะ†ะฝัˆั– ะผะพะดะตะปั– { #other-models } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ั„ัƒะฝะบั†ั–ัั… ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ ั‚ะฐ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท ะผะตั…ะฐะฝั–ะทะผะฐะผะธ ะฑะตะทะฟะตะบะธ ะฝะฐ ั€ั–ะฒะฝั– **ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `Depends`. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบัƒ ะผะพะดะตะปัŒ ะฐะฑะพ ะดะฐะฝั– ะดะปั ะฒะธะผะพะณ ะฑะตะทะฟะตะบะธ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ Pydantic-ะผะพะดะตะปัŒ `User`). + +ะะปะต ะฒะธ ะฝะต ะพะฑะผะตะถะตะฝั– ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ ัะบะพั—ััŒ ะบะพะฝะบั€ะตั‚ะฝะพั— ะผะพะดะตะปะธ ะดะฐะฝะธั…, ะบะปะฐััƒ ั‡ะธ ั‚ะธะฟัƒ. + +ะฅะพั‡ะตั‚ะต ะผะฐั‚ะธ id ั‚ะฐ email ั– ะฝะต ะผะฐั‚ะธ ะถะพะดะฝะพะณะพ username ัƒ ะฒะฐัˆั–ะน ะผะพะดะตะปั–? ะ‘ะตะท ะฟั€ะพะฑะปะตะผ. ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ. + +ะฅะพั‡ะตั‚ะต ะผะฐั‚ะธ ะฟั€ะพัั‚ะพ `str`? ะะฑะพ ะปะธัˆะต `dict`? ะะฑะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะตะบะทะตะผะฟะปัั€ ะบะปะฐััƒ ะผะพะดะตะปั– ะฑะฐะทะธ ะดะฐะฝะธั…? ะฃัะต ะฟั€ะฐั†ัŽั” ั‚ะฐะบ ัะฐะผะพ. + +ะฃ ะฒะฐัˆั–ะน ะฟั€ะพะณั€ะฐะผั– ะฝะฐัะฟั€ะฐะฒะดั– ะฒั…ะพะดัั‚ัŒ ะฝะต ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–, ะฐ ั€ะพะฑะพั‚ะธ, ะฑะพั‚ะธ ั‡ะธ ั–ะฝัˆั– ัะธัั‚ะตะผะธ, ั‰ะพ ะผะฐัŽั‚ัŒ ะปะธัˆะต ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟัƒ? ะ—ะฝะพะฒัƒ ะถ, ัƒัะต ะฟั€ะฐั†ัŽั” ั‚ะฐะบ ัะฐะผะพ. + +ะŸั€ะพัั‚ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะฑัƒะดัŒ-ัะบะธะน ั‚ะธะฟ ะผะพะดะตะปั–, ะฑัƒะดัŒ-ัะบะธะน ะบะปะฐั, ะฑัƒะดัŒ-ัะบัƒ ะฑะฐะทัƒ ะดะฐะฝะธั…, ัะบั– ะฟะพั‚ั€ั–ะฑะฝั– ะฒะฐัˆั–ะน ะฟั€ะพะณั€ะฐะผั–. **FastAPI** ะฟะพะดะฑะฐั” ะฟั€ะพ ั†ะต ะทะฐะฒะดัะบะธ ัะธัั‚ะตะผั– ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝั ะทะฐะปะตะถะฝะพัั‚ะตะน. + +## ะ ะพะทะผั–ั€ ะบะพะดัƒ { #code-size } + +ะฆะตะน ะฟั€ะธะบะปะฐะด ะผะพะถะต ะทะดะฐะฒะฐั‚ะธัั ะฑะฐะณะฐั‚ะพัะปั–ะฒะฝะธะผ. ะœะฐะนั‚ะต ะฝะฐ ัƒะฒะฐะทั–, ั‰ะพ ะผะธ ะทะผั–ัˆัƒั”ะผะพ ะฑะตะทะฟะตะบัƒ, ะผะพะดะตะปั– ะดะฐะฝะธั…, ัƒั‚ะธะปั–ั‚ะฝั– ั„ัƒะฝะบั†ั–ั— ั‚ะฐ ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ ะฒ ะพะดะฝะพะผัƒ ั„ะฐะนะปั–. + +ะะปะต ะพััŒ ะบะปัŽั‡ะพะฒะธะน ะผะพะผะตะฝั‚. + +ะ ะตั‡ั–, ะฟะพะฒ'ัะทะฐะฝั– ะท ะฑะตะทะฟะตะบะพัŽ ั‚ะฐ ะฒะฟั€ะพะฒะฐะดะถะตะฝะฝัะผ ะทะฐะปะตะถะฝะพัั‚ะตะน, ะฟะธัˆัƒั‚ัŒัั ะพะดะธะฝ ั€ะฐะท. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ั†ะต ะฝะฐัั‚ั–ะปัŒะบะธ ัะบะปะฐะดะฝะธะผ, ะฝะฐัะบั–ะปัŒะบะธ ะฟะพั‚ั€ั–ะฑะฝะพ. ะ† ะฒัะต ะพะดะฝะพ ะผะฐั‚ะธ ั†ะต ะฝะฐะฟะธัะฐะฝะธะผ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท, ะฒ ะพะดะฝะพะผัƒ ะผั–ัั†ั–. ะ— ัƒัั–ั”ัŽ ะณะฝัƒั‡ะบั–ัั‚ัŽ. + +ะ—ะฐั‚ะต ะฒะธ ะผะพะถะตั‚ะต ะผะฐั‚ะธ ั‚ะธััั‡ั– ะบั–ะฝั†ะตะฒะธั… ั‚ะพั‡ะพะบ (ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ), ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะพะดะฝัƒ ะน ั‚ัƒ ัะฐะผัƒ ัะธัั‚ะตะผัƒ ะฑะตะทะฟะตะบะธ. + +ะ† ะฒัั– ะฒะพะฝะธ (ะฐะฑะพ ะฑัƒะดัŒ-ัะบะฐ ั—ั…ะฝั ั‡ะฐัั‚ะธะฝะฐ, ัะบัƒ ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต) ะผะพะถัƒั‚ัŒ ัะบะพั€ะธัั‚ะฐั‚ะธัั ะฟะพะฒั‚ะพั€ะฝะธะผ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝัะผ ั†ะธั… ะทะฐะปะตะถะฝะพัั‚ะตะน ะฐะฑะพ ะฑัƒะดัŒ-ัะบะธั… ั–ะฝัˆะธั…, ัะบั– ะฒะธ ัั‚ะฒะพั€ะธั‚ะต. + +ะ† ะฒัั– ั†ั– ั‚ะธััั‡ั– ะพะฟะตั€ะฐั†ั–ะน ัˆะปัั…ัƒ ะผะพะถัƒั‚ัŒ ะฑัƒั‚ะธ ะฒััŒะพะณะพ ัƒ 3 ั€ัะดะบะธ: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะขะตะฟะตั€ ะฒะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัƒ ะฒะฐัˆั–ะน ั„ัƒะฝะบั†ั–ั— ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ. + +ะœะธ ะฒะถะต ะฝะฐ ะฟั–ะฒะดะพั€ะพะทั–. + +ะŸะพั‚ั€ั–ะฑะฝะพ ะปะธัˆะต ะดะพะดะฐั‚ะธ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ, ั‰ะพะฑ ะบะพั€ะธัั‚ัƒะฒะฐั‡/ะบะปั–ั”ะฝั‚ ะผั–ะณ ั„ะฐะบั‚ะธั‡ะฝะพ ะฝะฐะดั–ัะปะฐั‚ะธ `username` ั– `password`. + +ะ”ะฐะปั– ัะฐะผะต ั†ะต. diff --git a/docs/uk/docs/tutorial/security/oauth2-jwt.md b/docs/uk/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 0000000000..f94abb897b --- /dev/null +++ b/docs/uk/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# OAuth2 ะท ะฟะฐั€ะพะปะตะผ (ั– ั…ะตัˆัƒะฒะฐะฝะฝัะผ), Bearer ะท ั‚ะพะบะตะฝะฐะผะธ JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +ะขะตะฟะตั€, ะบะพะปะธ ะผะธ ะผะฐั”ะผะพ ะฒะตััŒ ะฟะพั‚ั–ะบ ะฑะตะทะฟะตะบะธ, ะทั€ะพะฑั–ะผะพ ะทะฐัั‚ะพััƒะฝะพะบ ัะฟั€ะฐะฒะดั– ะทะฐั…ะธั‰ะตะฝะธะผ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ะพะบะตะฝะธ JWT ั– ะฑะตะทะฟะตั‡ะฝะต ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ. + +ะฆะตะน ะบะพะด ะฒะธ ะผะพะถะตั‚ะต ั€ะตะฐะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัƒ ัะฒะพั”ะผัƒ ะทะฐัั‚ะพััƒะฝะบัƒ, ะทะฑะตั€ั–ะณะฐั‚ะธ ั…ะตัˆั– ะฟะฐั€ะพะปั–ะฒ ัƒ ัะฒะพั—ะน ะฑะฐะทั– ะดะฐะฝะธั… ั‚ะพั‰ะพ. + +ะœะธ ะฟะพั‡ะฝะตะผะพ ะท ั‚ะพะณะพ ะผั–ัั†ั, ะดะต ะทัƒะฟะธะฝะธะปะธัั ะฒ ะฟะพะฟะตั€ะตะดะฝัŒะพะผัƒ ั€ะพะทะดั–ะปั–, ั– ั€ะพะทัˆะธั€ะธะผะพ ะนะพะณะพ. + +## ะŸั€ะพ JWT { #about-jwt } + +JWT ะพะทะฝะฐั‡ะฐั” ยซJSON Web Tokensยป. + +ะฆะต ัั‚ะฐะฝะดะฐั€ั‚ ะบะพะดัƒะฒะฐะฝะฝั ะพะฑ'ั”ะบั‚ะฐ JSON ัƒ ะดะพะฒะณะธะน ั‰ั–ะปัŒะฝะธะน ั€ัะดะพะบ ะฑะตะท ะฟั€ะพะฑั–ะปั–ะฒ. ะ’ั–ะฝ ะฒะธะณะปัะดะฐั” ั‚ะฐะบ: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +ะ’ั–ะฝ ะฝะต ะทะฐัˆะธั„ั€ะพะฒะฐะฝะธะน, ั‚ะพะผัƒ ะบะพะถะตะฝ ะผะพะถะต ะฒั–ะดะฝะพะฒะธั‚ะธ ั–ะฝั„ะพั€ะผะฐั†ั–ัŽ ะท ะฒะผั–ัั‚ัƒ. + +ะะปะต ะฒั–ะฝ ะฟั–ะดะฟะธัะฐะฝะธะน. ะขะพะถ ะบะพะปะธ ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ั‚ะพะบะตะฝ, ัะบะธะน ะฒะธ ะฒะธะดะฐะปะธ, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ัะฟั€ะฐะฒะดั– ะนะพะณะพ ะฒะธะดะฐะปะธ ะฒะธ. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ั‚ะพะบะตะฝ ั–ะท ั‚ะตั€ะผั–ะฝะพะผ ะดั–ั—, ะฝะฐะฟั€ะธะบะปะฐะด, 1 ั‚ะธะถะดะตะฝัŒ. ะ† ะบะพะปะธ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฟะพะฒะตั€ะฝะตั‚ัŒัั ะฝะฐัั‚ัƒะฟะฝะพะณะพ ะดะฝั ะท ั‚ะพะบะตะฝะพะผ, ะฒะธ ะทะฝะฐั‚ะธะผะตั‚ะต, ั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะดะพัั– ัƒะฒั–ะนัˆะพะฒ ัƒ ะฒะฐัˆัƒ ัะธัั‚ะตะผัƒ. + +ะงะตั€ะตะท ั‚ะธะถะดะตะฝัŒ ั‚ะพะบะตะฝ ะทะฐะฒะตั€ัˆะธั‚ัŒ ั‚ะตั€ะผั–ะฝ ะดั–ั—, ั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฝะต ะฑัƒะดะต ะฐะฒั‚ะพั€ะธะทะพะฒะฐะฝะธะน ั‚ะฐ ะผะฐั” ะทะฝะพะฒัƒ ัƒะฒั–ะนั‚ะธ, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ะฝะพะฒะธะน ั‚ะพะบะตะฝ. ะ† ัะบั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ (ะฐะฑะพ ั‚ั€ะตั‚ั ัั‚ะพั€ะพะฝะฐ) ะฝะฐะผะฐะณะฐั‚ะธะผะตั‚ัŒัั ะทะผั–ะฝะธั‚ะธ ั‚ะพะบะตะฝ, ั‰ะพะฑ ะทะผั–ะฝะธั‚ะธ ั‚ะตั€ะผั–ะฝ ะดั–ั—, ะฒะธ ั†ะต ะฒะธัะฒะธั‚ะต, ะฑะพ ะฟั–ะดะฟะธัะธ ะฝะต ัะฟั–ะฒะฟะฐะดะฐั‚ะธะผัƒั‚ัŒ. + +ะฏะบั‰ะพ ั…ะพั‡ะตั‚ะต ยซะฟะพะณั€ะฐั‚ะธััยป ะท ั‚ะพะบะตะฝะฐะผะธ JWT ั– ะฟะพะฑะฐั‡ะธั‚ะธ, ัะบ ะฒะพะฝะธ ะฟั€ะฐั†ัŽัŽั‚ัŒ, ะฟะตั€ะตะณะปัะฝัŒั‚ะต https://jwt.io. + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ `PyJWT` { #install-pyjwt } + +ะะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `PyJWT`, ั‰ะพะฑ ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั‚ะฐ ะฟะตั€ะตะฒั–ั€ัั‚ะธ ั‚ะพะบะตะฝะธ JWT ัƒ Python. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ั– ั‚ะพะดั– ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ `pyjwt`: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะฟะปะฐะฝัƒั”ั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฐะปะณะพั€ะธั‚ะผะธ ั†ะธั„ั€ะพะฒะพะณะพ ะฟั–ะดะฟะธััƒ ะฝะฐ ะบัˆั‚ะฐะปั‚ RSA ะฐะฑะพ ECDSA, ัะปั–ะด ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ะทะฐะปะตะถะฝั–ัั‚ัŒ ะบั€ะธะฟั‚ะพะฑั–ะฑะปั–ะพั‚ะตะบะธ `pyjwt[crypto]`. + +ะ”ะพะบะปะฐะดะฝั–ัˆะต ะฟั€ะพ ั†ะต ะผะพะถะฝะฐ ะฟั€ะพั‡ะธั‚ะฐั‚ะธ ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— ะท ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั PyJWT. + +/// + +## ะฅะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ { #password-hashing } + +ยซะฅะตัˆัƒะฒะฐะฝะฝัยป ะพะทะฝะฐั‡ะฐั” ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะตัะบะพะณะพ ะฒะผั–ัั‚ัƒ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะฐั€ะพะปั) ะฝะฐ ะฟะพัะปั–ะดะพะฒะฝั–ัั‚ัŒ ะฑะฐะนั‚ั–ะฒ (ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบัƒ), ั‰ะพ ะฒะธะณะปัะดะฐั” ัะบ ะฝั–ัะตะฝั–ั‚ะฝะธั†ั. + +ะšะพะถะฝะพะณะพ ั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ั‚ะพั‡ะฝะพ ั‚ะพะน ัะฐะผะธะน ะฒะผั–ัั‚ (ั‚ะพั‡ะฝะพ ั‚ะพะน ัะฐะผะธะน ะฟะฐั€ะพะปัŒ), ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ั‚ะพั‡ะฝะพ ั‚ัƒ ัะฐะผัƒ ยซะฝั–ัะตะฝั–ั‚ะฝะธั†ัŽยป. + +ะะปะต ะฝะต ะผะพะถะฝะฐ ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ั†ัŽ ยซะฝั–ัะตะฝั–ั‚ะฝะธั†ัŽยป ะฝะฐะทะฐะด ัƒ ะฟะฐั€ะพะปัŒ. + +### ะะฐะฒั–ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ { #why-use-password-hashing } + +ะฏะบั‰ะพ ะฒะฐัˆัƒ ะฑะฐะทัƒ ะดะฐะฝะธั… ะฒะบั€ะฐะดัƒั‚ัŒ, ะทะปะพะฒะผะธัะฝะธะบ ะฝะต ะผะฐั‚ะธะผะต ะฒั–ะดะบั€ะธั‚ะธั… ะฟะฐั€ะพะปั–ะฒ ะฒะฐัˆะธั… ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ, ะฐ ะปะธัˆะต ั…ะตัˆั–. + +ะขะพะถ ะทะปะพะฒะผะธัะฝะธะบ ะฝะต ะทะผะพะถะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั†ะตะน ะฟะฐั€ะพะปัŒ ะฒ ั–ะฝัˆั–ะน ัะธัั‚ะตะผั– (ะพัะบั–ะปัŒะบะธ ะฑะฐะณะฐั‚ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ั‚ะพะน ัะฐะผะธะน ะฟะฐั€ะพะปัŒ ะฒััŽะดะธ, ั†ะต ะฑัƒะปะพ ะฑ ะฝะตะฑะตะทะฟะตั‡ะฝะพ). + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ `pwdlib` { #install-pwdlib } + +pwdlib - ั†ะต ั‡ัƒะดะพะฒะธะน ะฟะฐะบะตั‚ Python ะดะปั ั€ะพะฑะพั‚ะธ ะท ั…ะตัˆะฐะผะธ ะฟะฐั€ะพะปั–ะฒ. + +ะ’ั–ะฝ ะฟั–ะดั‚ั€ะธะผัƒั” ะฑะฐะณะฐั‚ะพ ะฑะตะทะฟะตั‡ะฝะธั… ะฐะปะณะพั€ะธั‚ะผั–ะฒ ั…ะตัˆัƒะฒะฐะฝะฝั ั‚ะฐ ัƒั‚ะธะปั–ั‚ ะดะปั ั€ะพะฑะพั‚ะธ ะท ะฝะธะผะธ. + +ะ ะตะบะพะผะตะฝะดะพะฒะฐะฝะธะน ะฐะปะณะพั€ะธั‚ะผ - ยซArgon2ยป. + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ั– ั‚ะพะดั– ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ pwdlib ะท Argon2: + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะ— `pwdlib` ะฒะธ ะฝะฐะฒั–ั‚ัŒ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะนะพะณะพ ั‚ะฐะบ, ั‰ะพะฑ ะฒั–ะฝ ัƒะผั–ะฒ ั‡ะธั‚ะฐั‚ะธ ะฟะฐั€ะพะปั–, ัั‚ะฒะพั€ะตะฝั– **Django**, ะฟะปะฐะณั–ะฝะพะผ ะฑะตะทะฟะตะบะธ **Flask** ะฐะฑะพ ะฑะฐะณะฐั‚ัŒะผะฐ ั–ะฝัˆะธะผะธ. + +ะขะพะถ ะฒะธ ะทะผะพะถะตั‚ะต, ะฝะฐะฟั€ะธะบะปะฐะด, ัะฟั–ะปัŒะฝะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ั– ัะฐะผั– ะดะฐะฝั– ะท ะทะฐัั‚ะพััƒะฝะบัƒ Django ะฒ ะฑะฐะทั– ะดะฐะฝะธั… ั–ะท ะทะฐัั‚ะพััƒะฝะบะพะผ FastAPI. ะะฑะพ ะฟะพัั‚ัƒะฟะพะฒะพ ะผั–ะณั€ัƒะฒะฐั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ Django, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั‚ัƒ ัะฐะผัƒ ะฑะฐะทัƒ ะดะฐะฝะธั…. + +ะ† ะฒะฐัˆั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั– ะทะผะพะถัƒั‚ัŒ ะฒั…ะพะดะธั‚ะธ ัะบ ั–ะท ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ Django, ั‚ะฐะบ ั– ะท ะฒะฐัˆะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ **FastAPI** ะพะดะฝะพั‡ะฐัะฝะพ. + +/// + +## ะฅะตัˆัƒะฒะฐะฝะฝั ั– ะฟะตั€ะตะฒั–ั€ะบะฐ ะฟะฐั€ะพะปั–ะฒ { #hash-and-verify-the-passwords } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ะฟะพั‚ั€ั–ะฑะฝั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะท `pwdlib`. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ะตะบะทะตะผะฟะปัั€ PasswordHash ะท ั€ะตะบะพะผะตะฝะดะพะฒะฐะฝะธะผะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะฝะฝัะผะธ - ะฒั–ะฝ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะธะน ะดะปั ั…ะตัˆัƒะฒะฐะฝะฝั ั‚ะฐ ะฟะตั€ะตะฒั–ั€ะบะธ ะฟะฐั€ะพะปั–ะฒ. + +/// tip | ะŸะพั€ะฐะดะฐ + +pwdlib ั‚ะฐะบะพะถ ะฟั–ะดั‚ั€ะธะผัƒั” ะฐะปะณะพั€ะธั‚ะผ ั…ะตัˆัƒะฒะฐะฝะฝั bcrypt, ะฐะปะต ะฝะต ะฒะบะปัŽั‡ะฐั” ะทะฐัั‚ะฐั€ั–ะปั– ะฐะปะณะพั€ะธั‚ะผะธ - ะดะปั ั€ะพะฑะพั‚ะธ ั–ะท ะทะฐัั‚ะฐั€ั–ะปะธะผะธ ั…ะตัˆะฐะผะธ ั€ะตะบะพะผะตะฝะดัƒั”ั‚ัŒัั ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ passlib. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั—ั— ะดะปั ั‡ะธั‚ะฐะฝะฝั ั– ะฟะตั€ะตะฒั–ั€ะบะธ ะฟะฐั€ะพะปั–ะฒ, ะทะณะตะฝะตั€ะพะฒะฐะฝะธั… ั–ะฝัˆะพัŽ ัะธัั‚ะตะผะพัŽ (ะฝะฐะฟั€ะธะบะปะฐะด, Django), ะฐะปะต ั…ะตัˆัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ะฝะพะฒั– ะฟะฐั€ะพะปั– ั–ะฝัˆะธะผ ะฐะปะณะพั€ะธั‚ะผะพะผ, ั‚ะฐะบะธะผ ัะบ Argon2 ะฐะฑะพ Bcrypt. + +ะ† ะฑัƒั‚ะธ ััƒะผั–ัะฝะธะผะธ ะท ัƒัั–ะผะฐ ะฝะธะผะธ ะพะดะฝะพั‡ะฐัะฝะพ. + +/// + +ะกั‚ะฒะพั€ั–ั‚ัŒ ัƒั‚ะธะปั–ั‚ะฐั€ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะดะปั ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั, ั‰ะพ ะฝะฐะดั…ะพะดะธั‚ัŒ ะฒั–ะด ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะ† ั‰ะต ะพะดะฝัƒ ัƒั‚ะธะปั–ั‚ัƒ ะดะปั ะฟะตั€ะตะฒั–ั€ะบะธ, ั‡ะธ ะพั‚ั€ะธะผะฐะฝะธะน ะฟะฐั€ะพะปัŒ ะฒั–ะดะฟะพะฒั–ะดะฐั” ะทะฑะตั€ะตะถะตะฝะพะผัƒ ั…ะตัˆัƒ. + +ะ† ั‰ะต ะพะดะฝัƒ - ะดะปั ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ั‚ะฐ ะฟะพะฒะตั€ะฝะตะฝะฝั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +ะšะพะปะธ `authenticate_user` ะฒะธะบะปะธะบะฐั”ั‚ัŒัั ะท ั–ะผ'ัะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ัะบะพะณะพ ะฝะตะผะฐั” ะฒ ะฑะฐะทั– ะดะฐะฝะธั…, ะผะธ ะฒัะต ะพะดะฝะพ ะทะฐะฟัƒัะบะฐั”ะผะพ `verify_password` ะดะปั ยซะฟั–ะดัั‚ะฐะฒะฝะพะณะพยป ั…ะตัˆัƒ. + +ะฆะต ะทะฐะฑะตะทะฟะตั‡ัƒั” ะฟั€ะธะฑะปะธะทะฝะพ ะพะดะฝะฐะบะพะฒะธะน ั‡ะฐั ะฒั–ะดะฟะพะฒั–ะดั– ะบั–ะฝั†ะตะฒะพั— ั‚ะพั‡ะบะธ ะฝะตะทะฐะปะตะถะฝะพ ะฒั–ะด ั‚ะพะณะพ, ั‡ะธ ั” ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะดั–ะนัะฝะธะผ, ะทะฐะฟะพะฑั–ะณะฐัŽั‡ะธ **ะฐั‚ะฐะบะฐะผ ะทะฐ ั‡ะฐัะพะผ**, ัะบั– ะผะพะณะปะธ ะฑ ะฑัƒั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐะฝั– ะดะปั ะฟะตั€ะตะปั–ั‡ะตะฝะฝั ะฝะฐัะฒะฝะธั… ั–ะผะตะฝ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ. + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะฒั–ั€ะธั‚ะต ะฝะพะฒัƒ (ั„ะฐะปัŒัˆะธะฒัƒ) ะฑะฐะทัƒ ะดะฐะฝะธั… `fake_users_db`, ะฟะพะฑะฐั‡ะธั‚ะต, ัะบ ะทะฐั€ะฐะท ะฒะธะณะปัะดะฐั” ั…ะตัˆ ะฟะฐั€ะพะปั: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + +/// + +## ะžะฟั€ะฐั†ัŽะฒะฐะฝะฝั ั‚ะพะบะตะฝั–ะฒ JWT { #handle-jwt-tokens } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต ะฒัั‚ะฐะฝะพะฒะปะตะฝั– ะผะพะดัƒะปั–. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ะฒะธะฟะฐะดะบะพะฒะธะน ัะตะบั€ะตั‚ะฝะธะน ะบะปัŽั‡, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะพ ะดะปั ะฟั–ะดะฟะธัะฐะฝะฝั ั‚ะพะบะตะฝั–ะฒ JWT. + +ะฉะพะฑ ะทะณะตะฝะตั€ัƒะฒะฐั‚ะธ ะฑะตะทะฟะตั‡ะฝะธะน ะฒะธะฟะฐะดะบะพะฒะธะน ัะตะบั€ะตั‚ะฝะธะน ะบะปัŽั‡, ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ะบะพะผะฐะฝะดัƒ: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +ะ† ัะบะพะฟั–ัŽะนั‚ะต ะฒะธะฒั–ะด ัƒ ะทะผั–ะฝะฝัƒ `SECRET_KEY` (ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ั‚ะพะน, ั‰ะพ ะฒ ะฟั€ะธะบะปะฐะดั–). + +ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะผั–ะฝะฝัƒ `ALGORITHM` ะท ะฐะปะณะพั€ะธั‚ะผะพะผ ะดะปั ะฟั–ะดะฟะธัะฐะฝะฝั ั‚ะพะบะตะฝะฐ JWT ั– ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ั—ั— ะฒ `"HS256"`. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะผั–ะฝะฝัƒ ะดะปั ั‚ะตั€ะผั–ะฝัƒ ะดั–ั— ั‚ะพะบะตะฝะฐ. + +ะ’ะธะทะฝะฐั‡ั‚ะต ะผะพะดะตะปัŒ Pydantic, ัะบะฐ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฐ ะฒ ะบั–ะฝั†ะตะฒั–ะน ั‚ะพั‡ั†ั– ั‚ะพะบะตะฝะฐ ะดะปั ะฒั–ะดะฟะพะฒั–ะดั–. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ัƒั‚ะธะปั–ั‚ะฐั€ะฝัƒ ั„ัƒะฝะบั†ั–ัŽ ะดะปั ะณะตะฝะตั€ะฐั†ั–ั— ะฝะพะฒะพะณะพ ั‚ะพะบะตะฝะฐ ะดะพัั‚ัƒะฟัƒ. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## ะžะฝะพะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– { #update-the-dependencies } + +ะžะฝะพะฒั–ั‚ัŒ `get_current_user`, ั‰ะพะฑ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ั‚ะพะน ัะฐะผะธะน ั‚ะพะบะตะฝ, ั‰ะพ ะน ั€ะฐะฝั–ัˆะต, ะฐะปะต ั†ัŒะพะณะพ ั€ะฐะทัƒ - ั‚ะพะบะตะฝ JWT. + +ะ”ะตะบะพะดัƒะนั‚ะต ะพั‚ั€ะธะผะฐะฝะธะน ั‚ะพะบะตะฝ, ะฟะตั€ะตะฒั–ั€ั‚ะต ะนะพะณะพ ั‚ะฐ ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะฟะพั‚ะพั‡ะฝะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะฏะบั‰ะพ ั‚ะพะบะตะฝ ะฝะตะดั–ะนัะฝะธะน, ะพะดั€ะฐะทัƒ ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะฟะพะผะธะปะบัƒ HTTP. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## ะžะฝะพะฒั–ั‚ัŒ ะพะฟะตั€ะฐั†ั–ัŽ ัˆะปัั…ัƒ `/token` { #update-the-token-path-operation } + +ะกั‚ะฒะพั€ั–ั‚ัŒ `timedelta` ะท ั‡ะฐัะพะผ ะถะธั‚ั‚ั ั‚ะพะบะตะฝะฐ. + +ะกั‚ะฒะพั€ั–ั‚ัŒ ัะฟั€ะฐะฒะถะฝั–ะน ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟัƒ JWT ั– ะฟะพะฒะตั€ะฝั–ั‚ัŒ ะนะพะณะพ. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### ะขะตั…ะฝั–ั‡ะฝั– ะดะตั‚ะฐะปั– ะฟั€ะพ ยซsubjectยป `sub` ัƒ JWT { #technical-details-about-the-jwt-subject-sub } + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั JWT ะบะฐะถะต, ั‰ะพ ั–ัะฝัƒั” ะบะปัŽั‡ `sub` ั–ะท ััƒะฑ'ั”ะบั‚ะพะผ ั‚ะพะบะตะฝะฐ. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะนะพะณะพ ะฝะต ะพะฑะพะฒ'ัะทะบะพะฒะพ, ะฐะปะต ัะฐะผะต ั‚ัƒะดะธ ะทะฐะทะฒะธั‡ะฐะน ะฟะพะผั–ั‰ะฐัŽั‚ัŒ ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ั‚ะพะถ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะนะพะณะพ ั‚ัƒั‚. + +JWT ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธัั ะน ะดะปั ั–ะฝัˆะธั… ั€ะตั‡ะตะน, ะพะบั€ั–ะผ ั–ะดะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะฝะฐะดะฐะฝะฝั ะนะพะผัƒ ะผะพะถะปะธะฒะพัั‚ั– ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะพะฟะตั€ะฐั†ั–ั— ะท ะฒะฐัˆะพัŽ API. + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ั–ะดะตะฝั‚ะธั„ั–ะบัƒะฒะฐั‚ะธ ยซะฐะฒั‚ะพะผะพะฑั–ะปัŒยป ะฐะฑะพ ยซะดะพะฟะธั ัƒ ะฑะปะพะทั–ยป. + +ะขะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะดะพะทะฒะพะปะธ ั‰ะพะดะพ ั†ั–ั”ั— ััƒั‚ะฝะพัั‚ั–, ัะบ-ะพั‚ ยซะบะตั€ัƒะฒะฐั‚ะธยป (ะดะปั ะฐะฒั‚ะพะผะพะฑั–ะปั) ะฐะฑะพ ยซั€ะตะดะฐะณัƒะฒะฐั‚ะธยป (ะดะปั ะดะพะฟะธััƒ). + +ะ† ะฟะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะดะฐั‚ะธ ั†ะตะน ั‚ะพะบะตะฝ JWT ะบะพั€ะธัั‚ัƒะฒะฐั‡ัƒ (ะฐะฑะพ ะฑะพั‚ัƒ), ั– ะฒั–ะฝ ะทะผะพะถะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ั†ั– ะดั–ั— (ะบะตั€ัƒะฒะฐั‚ะธ ะฐะฒั‚ะพะผะพะฑั–ะปะตะผ ะฐะฑะพ ั€ะตะดะฐะณัƒะฒะฐั‚ะธ ะดะพะฟะธั), ะฝะฐะฒั–ั‚ัŒ ะฝะต ะผะฐัŽั‡ะธ ะพะฑะปั–ะบะพะฒะพะณะพ ะทะฐะฟะธััƒ - ะปะธัˆะต ะท ั‚ะพะบะตะฝะพะผ JWT, ัะบะธะน ะฒะฐัˆะฐ API ะดะปั ั†ัŒะพะณะพ ะทะณะตะฝะตั€ัƒะฒะฐะปะฐ. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั†ั– ั–ะดะตั—, JWT ะผะพะถะฝะฐ ะทะฐัั‚ะพัะพะฒัƒะฒะฐั‚ะธ ัƒ ะทะฝะฐั‡ะฝะพ ัะบะปะฐะดะฝั–ัˆะธั… ัั†ะตะฝะฐั€ั–ัั…. + +ะฃ ั‚ะฐะบะธั… ะฒะธะฟะฐะดะบะฐั… ะบั–ะปัŒะบะฐ ััƒั‚ะฝะพัั‚ะตะน ะผะพะถัƒั‚ัŒ ะผะฐั‚ะธ ะพะดะฝะฐะบะพะฒั– ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€ะธ, ัะบะฐะถั–ะผะพ `foo` (ะบะพั€ะธัั‚ัƒะฒะฐั‡ `foo`, ะฐะฒั‚ะพะผะพะฑั–ะปัŒ `foo` ั– ะดะพะฟะธั `foo`). + +ะฉะพะฑ ัƒะฝะธะบะฝัƒั‚ะธ ะบะพะปั–ะทั–ะน ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€ั–ะฒ, ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ั‚ะพะบะตะฝะฐ JWT ะดะปั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฒะธ ะผะพะถะตั‚ะต ะดะพะดะฐั‚ะธ ะฟั€ะตั„ั–ะบั ะดะพ ะทะฝะฐั‡ะตะฝะฝั ะบะปัŽั‡ะฐ `sub`, ะฝะฐะฟั€ะธะบะปะฐะด `username:`. ะžั‚ะถะต, ัƒ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะทะฝะฐั‡ะตะฝะฝั `sub` ะผะพะณะปะพ ะฑ ะฑัƒั‚ะธ: `username:johndoe`. + +ะ’ะฐะถะปะธะฒะพ ะฟะฐะผ'ัั‚ะฐั‚ะธ, ั‰ะพ ะบะปัŽั‡ `sub` ะผะฐั” ะผั–ัั‚ะธั‚ะธ ัƒะฝั–ะบะฐะปัŒะฝะธะน ั–ะดะตะฝั‚ะธั„ั–ะบะฐั‚ะพั€ ัƒ ะผะตะถะฐั… ัƒััŒะพะณะพ ะทะฐัั‚ะพััƒะฝะบัƒ ั– ะผะฐั” ะฑัƒั‚ะธ ัั‚ั€ะพะบะพัŽ. + +## ะŸะตั€ะตะฒั–ั€ั‚ะต { #check-it } + +ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ัะตั€ะฒะตั€ ั– ะฟะตั€ะตะนะดั–ั‚ัŒ ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั—: http://127.0.0.1:8000/docs. + +ะ’ะธ ะฟะพะฑะฐั‡ะธั‚ะต ั‚ะฐะบะธะน ั–ะฝั‚ะตั€ั„ะตะนั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ: + + + +ะะฒั‚ะพั€ะธะทัƒะนั‚ะต ะทะฐัั‚ะพััƒะฝะพะบ ั‚ะฐะบ ัะฐะผะพ, ัะบ ั€ะฐะฝั–ัˆะต. + +ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั–: + +Username: `johndoe` +Password: `secret` + +/// check | ะŸะตั€ะตะฒั–ั€ั‚ะต + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ, ั‰ะพ ะฝั–ะดะต ะฒ ะบะพะดั– ะฝะตะผะฐั” ะฒั–ะดะบั€ะธั‚ะพะณะพ ะฟะฐั€ะพะปั "`secret`", ะผะธ ะผะฐั”ะผะพ ะปะธัˆะต ั…ะตัˆะพะฒะฐะฝัƒ ะฒะตั€ัั–ัŽ. + +/// + + + +ะ’ะธะบะปะธั‡ั‚ะต ะบั–ะฝั†ะตะฒัƒ ั‚ะพั‡ะบัƒ `/users/me/`, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฒั–ะดะฟะพะฒั–ะดัŒ: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +ะฏะบั‰ะพ ะฒั–ะดะบั€ะธั”ั‚ะต ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ั€ะพะทั€ะพะฑะฝะธะบะฐ, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ ัƒ ะฒั–ะดะฟั€ะฐะฒะปะตะฝะธั… ะดะฐะฝะธั… ั” ะปะธัˆะต ั‚ะพะบะตะฝ, ะฟะฐั€ะพะปัŒ ะฝะฐะดัะธะปะฐั”ั‚ัŒัั ั‚ั–ะปัŒะบะธ ะฒ ะฟะตั€ัˆะพะผัƒ ะทะฐะฟะธั‚ั– ะดะปั ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‚ะฐ ะพั‚ั€ะธะผะฐะฝะฝั ั‚ะพะบะตะฝะฐ ะดะพัั‚ัƒะฟัƒ, ะฐะปะต ะฝะต ะฝะฐะดัะธะปะฐั”ั‚ัŒัั ะดะฐะปั–: + + + +/// note | ะŸั€ะธะผั–ั‚ะบะฐ + +ะ—ะฒะตั€ะฝั–ั‚ัŒ ัƒะฒะฐะณัƒ ะฝะฐ ะทะฐะณะพะปะพะฒะพะบ `Authorization` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ, ั‰ะพ ะฟะพั‡ะธะฝะฐั”ั‚ัŒัั ะท `Bearer `. + +/// + +## ะŸั€ะพััƒะฝัƒั‚ะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะทั– `scopes` { #advanced-usage-with-scopes } + +OAuth2 ะผะฐั” ะฟะพะฝัั‚ั‚ั ยซscopesยป. + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั…, ั‰ะพะฑ ะดะพะดะฐั‚ะธ ะบะพะฝะบั€ะตั‚ะฝะธะน ะฝะฐะฑั–ั€ ะดะพะทะฒะพะปั–ะฒ ะดะพ ั‚ะพะบะตะฝะฐ JWT. + +ะŸะพั‚ั–ะผ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะดะฐั‚ะธ ั†ะตะน ั‚ะพะบะตะฝ ะบะพั€ะธัั‚ัƒะฒะฐั‡ัƒ ะฝะฐะฟั€ัะผัƒ ะฐะฑะพ ั‚ั€ะตั‚ั–ะน ัั‚ะพั€ะพะฝั– ะดะปั ะฒะทะฐั”ะผะพะดั–ั— ะท ะฒะฐัˆะพัŽ API ั–ะท ะฝะฐะฑะพั€ะพะผ ะพะฑะผะตะถะตะฝัŒ. + +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั, ัะบ ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั– ัะบ ะฒะพะฝะธ ั–ะฝั‚ะตะณั€ะพะฒะฐะฝั– ะท **FastAPI** ะฟั–ะทะฝั–ัˆะต ัƒ **ะฟั€ะพััƒะฝัƒั‚ะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ**. + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะœะฐัŽั‡ะธ ะฒัะต, ั‰ะพ ะฒะธ ะฑะฐั‡ะธะปะธ ะดะพัั–, ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ะทะฐั…ะธั‰ะตะฝะธะน ะทะฐัั‚ะพััƒะฝะพะบ **FastAPI**, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ัั‚ะฐะฝะดะฐั€ั‚ะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ OAuth2 ั– JWT. + +ะœะฐะนะถะต ะฒ ะฑัƒะดัŒ-ัะบะพะผัƒ ั„ั€ะตะนะผะฒะพั€ะบัƒ ะพะฟั€ะฐั†ัŽะฒะฐะฝะฝั ะฑะตะทะฟะตะบะธ ะดัƒะถะต ัˆะฒะธะดะบะพ ัั‚ะฐั” ะดะพัะธั‚ัŒ ัะบะปะฐะดะฝะพัŽ ั‚ะตะผะพัŽ. + +ะ‘ะฐะณะฐั‚ะพ ะฟะฐะบะตั‚ั–ะฒ, ั‰ะพ ัะธะปัŒะฝะพ ั†ะต ัะฟั€ะพั‰ัƒัŽั‚ัŒ, ะทะผัƒัˆะตะฝั– ะนั‚ะธ ะฝะฐ ั‡ะธัะปะตะฝะฝั– ะบะพะผะฟั€ะพะผั–ัะธ ะท ะผะพะดะตะปะปัŽ ะดะฐะฝะธั…, ะฑะฐะทะพัŽ ะดะฐะฝะธั… ั– ะดะพัั‚ัƒะฟะฝะธะผะธ ะผะพะถะปะธะฒะพัั‚ัะผะธ. ะ”ะตั…ั‚ะพ ะท ั†ะธั… ะฟะฐะบะตั‚ั–ะฒ, ัะบั– ะฝะฐะดั‚ะพ ะฒัะต ัะฟั€ะพั‰ัƒัŽั‚ัŒ, ะฝะฐัะฟั€ะฐะฒะดั– ะผะฐัŽั‚ัŒ ะฟั€ะธั…ะพะฒะฐะฝั– ะฒะฐะดะธ ะฑะตะทะฟะตะบะธ. + +--- + +**FastAPI** ะฝะต ะนะดะต ะฝะฐ ะถะพะดะฝั– ะบะพะผะฟั€ะพะผั–ัะธ ะท ะฑัƒะดัŒ-ัะบะพัŽ ะฑะฐะทะพัŽ ะดะฐะฝะธั…, ะผะพะดะตะปะปัŽ ะดะฐะฝะธั… ั‡ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะพะผ. + +ะ’ั–ะฝ ะดะฐั” ะฒะฐะผ ัƒััŽ ะณะฝัƒั‡ะบั–ัั‚ัŒ, ั‰ะพะฑ ะพะฑั€ะฐั‚ะธ ั‚ั–, ัะบั– ะฝะฐะนะบั€ะฐั‰ะต ะฟั–ะดั…ะพะดัั‚ัŒ ะฒะฐัˆะพะผัƒ ะฟั€ะพั”ะบั‚ัƒ. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะฟั€ัะผัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะดะพะฑั€ะต ะฟั–ะดั‚ั€ะธะผัƒะฒะฐะฝั– ั‚ะฐ ัˆะธั€ะพะบะพ ะทะฐัั‚ะพัะพะฒัƒะฒะฐะฝั– ะฟะฐะบะตั‚ะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ `pwdlib` ั– `PyJWT`, ะฐะดะถะต **FastAPI** ะฝะต ะฒะธะผะฐะณะฐั” ะถะพะดะฝะธั… ัะบะปะฐะดะฝะธั… ะผะตั…ะฐะฝั–ะทะผั–ะฒ ะดะปั ั–ะฝั‚ะตะณั€ะฐั†ั–ั— ะทะพะฒะฝั–ัˆะฝั–ั… ะฟะฐะบะตั‚ั–ะฒ. + +ะ’ะพะดะฝะพั‡ะฐั ะฒั–ะฝ ะฝะฐะดะฐั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ั‰ะพะฑ ะผะฐะบัะธะผะฐะปัŒะฝะพ ัะฟั€ะพัั‚ะธั‚ะธ ะฟั€ะพั†ะตั ะฑะตะท ะบะพะผะฟั€ะพะผั–ัั–ะฒ ัƒ ะณะฝัƒั‡ะบะพัั‚ั–, ะฝะฐะดั–ะนะฝะพัั‚ั– ั‡ะธ ะฑะตะทะฟะตั†ั–. + +ะ† ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ะฐ ะฒะฟั€ะพะฒะฐะดะถัƒะฒะฐั‚ะธ ะฑะตะทะฟะตั‡ะฝั– ัั‚ะฐะฝะดะฐั€ั‚ะฝั– ะฟั€ะพั‚ะพะบะพะปะธ, ัะบ-ะพั‚ OAuth2, ะฒั–ะดะฝะพัะฝะพ ะฟั€ะพัั‚ะธะผ ัะฟะพัะพะฑะพะผ. + +ะฃ **ะฟั€ะพััƒะฝัƒั‚ะพะผัƒ ะฟะพัั–ะฑะฝะธะบัƒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ** ะฒะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ยซscopesยป ะฒ OAuth2 ะดะปั ะฑั–ะปัŒัˆ ะดะตั‚ะฐะปัŒะฝะพั— ัะธัั‚ะตะผะธ ะดะพะทะฒะพะปั–ะฒ, ะดะพั‚ั€ะธะผัƒัŽั‡ะธััŒ ั‚ะธั… ัะฐะผะธั… ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ. OAuth2 ะทั– scopes - ั†ะต ะผะตั…ะฐะฝั–ะทะผ, ัะบะธะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะฑะฐะณะฐั‚ะพ ะฒะตะปะธะบะธั… ะฟั€ะพะฒะฐะนะดะตั€ั–ะฒ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั—, ัะบ-ะพั‚ Facebook, Google, GitHub, Microsoft, X (Twitter) ั‚ะพั‰ะพ, ั‰ะพะฑ ะฐะฒั‚ะพั€ะธะทัƒะฒะฐั‚ะธ ัั‚ะพั€ะพะฝะฝั– ะทะฐัั‚ะพััƒะฝะบะธ ะฝะฐ ะฒะทะฐั”ะผะพะดั–ัŽ ะท ั—ั…ะฝั–ะผะธ API ะฒั–ะด ั–ะผะตะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ. diff --git a/docs/uk/docs/tutorial/security/simple-oauth2.md b/docs/uk/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000..05f949738d --- /dev/null +++ b/docs/uk/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# ะŸั€ะพัั‚ะธะน OAuth2 ะท ะฟะฐั€ะพะปะตะผ ั– Bearer { #simple-oauth2-with-password-and-bearer } + +ะขะตะฟะตั€ ะฟั€ะพะดะพะฒะถะธะผะพ ะท ะฟะพะฟะตั€ะตะดะฝัŒะพะณะพ ั€ะพะทะดั–ะปัƒ ั– ะดะพะดะฐะผะพ ะฒั–ะดััƒั‚ะฝั– ั‡ะฐัั‚ะธะฝะธ, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ ะฟะพะฒะฝะธะน ะฟะพั‚ั–ะบ ะฑะตะทะฟะตะบะธ. + +## ะžั‚ั€ะธะผะฐะนั‚ะต `username` ั– `password` { #get-the-username-and-password } + +ะœะธ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ ัƒั‚ะธะปั–ั‚ะธ ะฑะตะทะฟะตะบะธ **FastAPI**, ั‰ะพะฑ ะพั‚ั€ะธะผะฐั‚ะธ `username` ั– `password`. + +OAuth2 ะฒะธะทะฝะฐั‡ะฐั”, ั‰ะพ ะฟั–ะด ั‡ะฐั ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ยซะฟะพั‚ะพะบัƒ ะฟะฐั€ะพะปัŽยป (ัะบะธะน ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ) ะบะปั–ั”ะฝั‚/ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะผะฐั” ะฝะฐะดั–ัะปะฐั‚ะธ ะฟะพะปั `username` ั– `password` ัะบ ะดะฐะฝั– ั„ะพั€ะผะธ. + +ะ† ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั ะบะฐะถะต, ั‰ะพ ะฟะพะปั ะผะฐัŽั‚ัŒ ะฝะฐะทะธะฒะฐั‚ะธัั ัะฐะผะต ั‚ะฐะบ. ะขะพะผัƒ `user-name` ะฐะฑะพ `email` ะฝะต ะฟั–ะดั–ะนะดัƒั‚ัŒ. + +ะะปะต ะฝะต ั…ะฒะธะปัŽะนั‚ะตัั, ัƒ ั„ั€ะพะฝั‚ะตะฝะดั– ะฒะธ ะผะพะถะตั‚ะต ะฒั–ะดะพะฑั€ะฐะถะฐั‚ะธ ั†ะต ั‚ะฐะบ, ัะบ ะทะฐะฑะฐะถะฐั”ั‚ะต, ะดะปั ะบั–ะฝั†ะตะฒะธั… ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ. + +ะ† ะฒะฐัˆั– ะผะพะดะตะปั– ะฑะฐะทะธ ะดะฐะฝะธั… ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบั– ั–ะฝัˆั– ะฝะฐะทะฒะธ. + +ะะปะต ะดะปั *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะฒั…ะพะดัƒ ะผะธ ะผะฐั”ะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ัะฐะผะต ั†ั– ะฝะฐะทะฒะธ, ั‰ะพะฑ ะฑัƒั‚ะธ ััƒะผั–ัะฝะธะผะธ ะทั– ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั”ัŽ (ั– ะผะฐั‚ะธ ะทะผะพะณัƒ, ะฝะฐะฟั€ะธะบะปะฐะด, ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธัั ะฒะฑัƒะดะพะฒะฐะฝะพัŽ ัะธัั‚ะตะผะพัŽ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API). + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั ั‚ะฐะบะพะถ ะฒะบะฐะทัƒั”, ั‰ะพ `username` ั– `password` ะผะฐัŽั‚ัŒ ะฝะฐะดัะธะปะฐั‚ะธัั ัะบ ะดะฐะฝั– ั„ะพั€ะผะธ (ั‚ะพะฑั‚ะพ ะฑะตะท JSON). + +### `scope` { #scope } + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั ั‚ะฐะบะพะถ ะบะฐะถะต, ั‰ะพ ะบะปั–ั”ะฝั‚ ะผะพะถะต ะฝะฐะดั–ัะปะฐั‚ะธ ั–ะฝัˆะต ะฟะพะปะต ั„ะพั€ะผะธ ยซ`scope`ยป. + +ะะฐะทะฒะฐ ะฟะพะปั ั„ะพั€ะผะธ โ€” `scope` (ะฒ ะพะดะฝะธะฝั–), ะฐะปะต ะฝะฐัะฟั€ะฐะฒะดั– ั†ะต ะดะพะฒะณะฐ ัั‚ั€ะพะบะฐ ะทั– ยซscopesยป, ั€ะพะทะดั–ะปะตะฝะธะผะธ ะฟั€ะพะฑั–ะปะฐะผะธ. + +ะšะพะถะตะฝ ยซscopeยป โ€” ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะฐ (ะฑะตะท ะฟั€ะพะฑั–ะปั–ะฒ). + +ะ‡ั… ะทะฐะทะฒะธั‡ะฐะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะบะพะฝะบั€ะตั‚ะฝะธั… ะฟั€ะฐะฒ ะดะพัั‚ัƒะฟัƒ, ะฝะฐะฟั€ะธะบะปะฐะด: + +- `users:read` ะฐะฑะพ `users:write` โ€” ะฟะพัˆะธั€ะตะฝั– ะฟั€ะธะบะปะฐะดะธ. +- `instagram_basic` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Facebook / Instagram. +- `https://www.googleapis.com/auth/drive` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั Google. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฃ OAuth2 ยซscopeยป โ€” ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะฐ, ั‰ะพ ะพะณะพะปะพัˆัƒั” ะบะพะฝะบั€ะตั‚ะฝะธะน ะฟะพั‚ั€ั–ะฑะฝะธะน ะดะพะทะฒั–ะป. + +ะะต ะผะฐั” ะทะฝะฐั‡ะตะฝะฝั, ั‡ะธ ะผั–ัั‚ะธั‚ัŒ ะฒะพะฝะฐ ั–ะฝัˆั– ัะธะผะฒะพะปะธ ะฝะฐ ะบัˆั‚ะฐะปั‚ `:` ะฐะฑะพ ั‡ะธ ั†ะต URL. + +ะฆั– ะดะตั‚ะฐะปั– ะทะฐะปะตะถะฐั‚ัŒ ะฒั–ะด ั€ะตะฐะปั–ะทะฐั†ั–ั—. + +ะ”ะปั OAuth2 ั†ะต ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบะธ. + +/// + +## ะšะพะด ะดะปั ะพั‚ั€ะธะผะฐะฝะฝั `username` ั– `password` { #code-to-get-the-username-and-password } + +ะขะตะฟะตั€ ัะบะพั€ะธัั‚ะฐะนะผะพัั ัƒั‚ะธะปั–ั‚ะฐะผะธ, ะฝะฐะดะฐะฝะธะผะธ **FastAPI**, ั‰ะพะฑ ะพะฑั€ะพะฑะธั‚ะธ ั†ะต. + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +ะกะฟะพั‡ะฐั‚ะบัƒ ั–ะผะฟะพั€ั‚ัƒะนั‚ะต `OAuth2PasswordRequestForm` ั– ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ะนะพะณะพ ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ ั–ะท `Depends` ะฒ *ะพะฟะตั€ะฐั†ั–ั— ัˆะปัั…ัƒ* ะดะปั `/token`: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` โ€” ั†ะต ะบะปะฐั ะทะฐะปะตะถะฝะพัั‚ั–, ั‰ะพ ะพะณะพะปะพัˆัƒั” ั‚ั–ะปะพ ั„ะพั€ะผะธ ะท: + +- `username`. +- `password`. +- ะะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ ะฟะพะปะตะผ `scope` ัะบ ะฒะตะปะธะบะพัŽ ัั‚ั€ะพะบะพัŽ, ัะบะปะฐะดะตะฝะพัŽ ะทั– ัั‚ั€ะพะบ, ั€ะพะทะดั–ะปะตะฝะธั… ะฟั€ะพะฑั–ะปะฐะผะธ. +- ะะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ `grant_type`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะกะฟะตั†ะธั„ั–ะบะฐั†ั–ั OAuth2 ะฝะฐัะฟั€ะฐะฒะดั– ะฒะธะผะฐะณะฐั” ะฟะพะปะต `grant_type` ั–ะท ั„ั–ะบัะพะฒะฐะฝะธะผ ะทะฝะฐั‡ะตะฝะฝัะผ `password`, ะฐะปะต `OAuth2PasswordRequestForm` ั†ัŒะพะณะพ ะฝะต ะฟั€ะธะผัƒัˆัƒั”. + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ั†ะต ะฟั€ะธะผัƒัะธั‚ะธ, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต `OAuth2PasswordRequestFormStrict` ะทะฐะผั–ัั‚ัŒ `OAuth2PasswordRequestForm`. + +/// + +- ะะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ `client_id` (ะดะปั ะฝะฐัˆะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ). +- ะะตะพะฑะพะฒ'ัะทะบะพะฒะธะผ `client_secret` (ะดะปั ะฝะฐัˆะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ). + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +`OAuth2PasswordRequestForm` โ€” ะฝะต ัะฟะตั†ั–ะฐะปัŒะฝะธะน ะบะปะฐั ะดะปั **FastAPI**, ัะบ `OAuth2PasswordBearer`. + +`OAuth2PasswordBearer` ั€ะพะฑะธั‚ัŒ ั‚ะฐะบ, ั‰ะพ **FastAPI** ะทะฝะฐั”, ั‰ะพ ั†ะต ัั…ะตะผะฐ ะฑะตะทะฟะตะบะธ. ะขะพะผัƒ ั—ั— ะดะพะดะฐัŽั‚ัŒ ั‚ะฐะบะธะผ ั‡ะธะฝะพะผ ะดะพ OpenAPI. + +ะะปะต `OAuth2PasswordRequestForm` โ€” ั†ะต ะฟั€ะพัั‚ะพ ะบะปะฐั ะทะฐะปะตะถะฝะพัั‚ั–, ัะบะธะน ะฒะธ ะผะพะณะปะธ ะฑ ะฝะฐะฟะธัะฐั‚ะธ ัะฐะผั–, ะฐะฑะพ ะฒะธ ะผะพะณะปะธ ะฑ ะฝะฐะฟั€ัะผัƒ ะพะณะพะปะพัะธั‚ะธ ะฟะฐั€ะฐะผะตั‚ั€ะธ `Form`. + +ะžัะบั–ะปัŒะบะธ ั†ะต ั‚ะธะฟะพะฒะฐ ะทะฐะดะฐั‡ะฐ, **FastAPI** ะฝะฐะดะฐั” ะนะพะณะพ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ, ั‰ะพะฑ ัะฟั€ะพัั‚ะธั‚ะธ ั€ะพะฑะพั‚ัƒ. + +/// + +### ะ’ะธะบะพั€ะธัั‚ะพะฒัƒะนั‚ะต ะดะฐะฝั– ั„ะพั€ะผะธ { #use-the-form-data } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ•ะบะทะตะผะฟะปัั€ ะบะปะฐััƒ ะทะฐะปะตะถะฝะพัั‚ั– `OAuth2PasswordRequestForm` ะฝะต ะผะฐั‚ะธะผะต ะฐั‚ั€ะธะฑัƒั‚ะฐ `scope` ะท ะดะพะฒะณะพัŽ ัั‚ั€ะพะบะพัŽ, ั€ะพะทะดั–ะปะตะฝะพัŽ ะฟั€ะพะฑั–ะปะฐะผะธ, ะฝะฐั‚ะพะผั–ัั‚ัŒ ะฒั–ะฝ ะผะฐั‚ะธะผะต ะฐั‚ั€ะธะฑัƒั‚ `scopes` ะทั– ัะฟั€ะฐะฒะถะฝั–ะผ ัะฟะธัะบะพะผ ัั‚ั€ะพะบ ะดะปั ะบะพะถะฝะพะณะพ ะฝะฐะดั–ัะปะฐะฝะพะณะพ scope. + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฝะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `scopes`, ะฐะปะต ั†ั ะผะพะถะปะธะฒั–ัั‚ัŒ ั”, ัะบั‰ะพ ะทะฝะฐะดะพะฑะธั‚ัŒัั. + +/// + +ะขะตะฟะตั€ ะพั‚ั€ะธะผะฐะนั‚ะต ะดะฐะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะท (ั„ะฐะปัŒัˆะธะฒะพั—) ะฑะฐะทะธ ะดะฐะฝะธั…, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `username` ะท ะฟะพะปั ั„ะพั€ะผะธ. + +ะฏะบั‰ะพ ั‚ะฐะบะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฝะตะผะฐั”, ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ะฟะพะผะธะปะบัƒ ยซIncorrect username or passwordยป. + +ะ”ะปั ะฟะพะผะธะปะบะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะฒะธะฝัั‚ะพะบ `HTTPException`: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### ะŸะตั€ะตะฒั–ั€ั‚ะต ะฟะฐั€ะพะปัŒ { #check-the-password } + +ะะฐ ั†ัŒะพะผัƒ ะตั‚ะฐะฟั– ะผะธ ะผะฐั”ะผะพ ะดะฐะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะท ะฝะฐัˆะพั— ะฑะฐะทะธ ะดะฐะฝะธั…, ะฐะปะต ั‰ะต ะฝะต ะฟะตั€ะตะฒั–ั€ะธะปะธ ะฟะฐั€ะพะปัŒ. + +ะกะฟะตั€ัˆัƒ ั€ะพะทะผั–ัั‚ะธะผะพ ั†ั– ะดะฐะฝั– ะฒ Pydantic-ะผะพะดะตะปั– `UserInDB`. + +ะ’ะธ ะฝั–ะบะพะปะธ ะฝะต ะฟะพะฒะธะฝะฝั– ะทะฑะตั€ั–ะณะฐั‚ะธ ะฟะฐั€ะพะปั– ัƒ ะฒั–ะดะบั€ะธั‚ะพะผัƒ ะฒะธะณะปัะดั–, ั‚ะพะถ ะผะธ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ (ั„ะฐะปัŒัˆะธะฒัƒ) ัะธัั‚ะตะผัƒ ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ. + +ะฏะบั‰ะพ ะฟะฐั€ะพะปั– ะฝะต ะทะฑั–ะณะฐัŽั‚ัŒัั, ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ั‚ัƒ ัะฐะผัƒ ะฟะพะผะธะปะบัƒ. + +#### ะฅะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ { #password-hashing } + +ยซะฅะตัˆัƒะฒะฐะฝะฝัยป ะพะทะฝะฐั‡ะฐั”: ะฟะตั€ะตั‚ะฒะพั€ะตะฝะฝั ะดะตัะบะพะณะพ ะฒะผั–ัั‚ัƒ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ ะฟะฐั€ะพะปั) ัƒ ะฟะพัะปั–ะดะพะฒะฝั–ัั‚ัŒ ะฑะฐะนั‚ั–ะฒ (ะฟั€ะพัั‚ะพ ัั‚ั€ะพะบัƒ), ัะบะฐ ะฒะธะณะปัะดะฐั” ัะบ ะฝั–ัะตะฝั–ั‚ะฝะธั†ั. + +ะšะพะถะฝะพะณะพ ั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะฟะตั€ะตะดะฐั”ั‚ะต ั‚ะพั‡ะฝะพ ั‚ะพะน ัะฐะผะธะน ะฒะผั–ัั‚ (ั‚ะพั‡ะฝะพ ั‚ะพะน ัะฐะผะธะน ะฟะฐั€ะพะปัŒ), ะฒะธ ะพั‚ั€ะธะผัƒั”ั‚ะต ั‚ะพั‡ะฝะพ ั‚ัƒ ัะฐะผัƒ ยซะฝั–ัะตะฝั–ั‚ะฝะธั†ัŽยป. + +ะะปะต ะฒะธ ะฝะต ะผะพะถะตั‚ะต ะฟะตั€ะตั‚ะฒะพั€ะธั‚ะธ ั†ัŽ ยซะฝั–ัะตะฝั–ั‚ะฝะธั†ัŽยป ะฝะฐะทะฐะด ัƒ ะฟะฐั€ะพะปัŒ. + +##### ะะฐะฒั–ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ { #why-use-password-hashing } + +ะฏะบั‰ะพ ะฒะฐัˆัƒ ะฑะฐะทัƒ ะดะฐะฝะธั… ะฒะบั€ะฐะดัƒั‚ัŒ, ะทะปะพะฒะผะธัะฝะธะบ ะฝะต ะผะฐั‚ะธะผะต ะฟะฐั€ะพะปั–ะฒ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ ัƒ ะฒั–ะดะบั€ะธั‚ะพะผัƒ ะฒะธะณะปัะดั–, ะปะธัˆะต ั…ะตัˆั–. + +ะขะพะถ ะทะปะพะฒะผะธัะฝะธะบ ะฝะต ะทะผะพะถะต ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ั‚ั– ัะฐะผั– ะฟะฐั€ะพะปั– ะฒ ั–ะฝัˆั–ะน ัะธัั‚ะตะผั– (ะพัะบั–ะปัŒะบะธ ะฑะฐะณะฐั‚ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ั–ะฒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ั‚ะพะน ัะฐะผะธะน ะฟะฐั€ะพะปัŒ ะฒััŽะดะธ, ั†ะต ะฑัƒะปะพ ะฑ ะฝะตะฑะตะทะฟะตั‡ะฝะพ). + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### ะŸั€ะพ `**user_dict` { #about-user-dict } + +`UserInDB(**user_dict)` ะพะทะฝะฐั‡ะฐั”: + +ะŸะตั€ะตะดะฐั‚ะธ ะบะปัŽั‡ั– ั‚ะฐ ะทะฝะฐั‡ะตะฝะฝั ะท `user_dict` ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ ัะบ ะฐั€ะณัƒะผะตะฝั‚ะธ ะบะปัŽั‡-ะทะฝะฐั‡ะตะฝะฝั, ะตะบะฒั–ะฒะฐะปะตะฝั‚ะฝะพ ะดะพ: + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ”ะปั ะฟะพะฒะฝั–ัˆะพะณะพ ะฟะพััะฝะตะฝะฝั `**user_dict` ะฟะตั€ะตะณะปัะฝัŒั‚ะต [ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ ะดะปั **ะ”ะพะดะฐั‚ะบะพะฒะธั… ะผะพะดะตะปะตะน**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}. + +/// + +## ะŸะพะฒะตั€ะฝั–ั‚ัŒ ั‚ะพะบะตะฝ { #return-the-token } + +ะ’ั–ะดะฟะพะฒั–ะดัŒ ั‚ะพั‡ะบะธ ะฒั…ะพะดัƒ `token` ะผะฐั” ะฑัƒั‚ะธ ะพะฑ'ั”ะบั‚ะพะผ JSON. + +ะ’ะพะฝะฐ ะฟะพะฒะธะฝะฝะฐ ะผั–ัั‚ะธั‚ะธ `token_type`. ะฃ ะฝะฐัˆะพะผัƒ ะฒะธะฟะฐะดะบัƒ, ะพัะบั–ะปัŒะบะธ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ั‚ะพะบะตะฝะธ ยซBearerยป, ั‚ะธะฟ ั‚ะพะบะตะฝะฐ ะผะฐั” ะฑัƒั‚ะธ ยซ`bearer`ยป. + +ะขะฐะบะพะถ ะผะฐั” ะฑัƒั‚ะธ `access_token` ะทั– ัั‚ั€ะพะบะพัŽ, ั‰ะพ ะผั–ัั‚ะธั‚ัŒ ะฝะฐัˆ ั‚ะพะบะตะฝ ะดะพัั‚ัƒะฟัƒ. + +ะ”ะปั ั†ัŒะพะณะพ ะฟั€ะพัั‚ะพะณะพ ะฟั€ะธะบะปะฐะดัƒ ะผะธ ะทั€ะพะฑะธะผะพ ะฟะพะฒะฝั–ัั‚ัŽ ะฝะตะฑะตะทะฟะตั‡ะฝะพ ั– ะฟะพะฒะตั€ะฝะตะผะพ ั‚ะพะน ัะฐะผะธะน `username` ัะบ ั‚ะพะบะตะฝ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ัะฟั€ะฐะฒะดั– ะฑะตะทะฟะตั‡ะฝัƒ ั€ะตะฐะปั–ะทะฐั†ั–ัŽ ะท ั…ะตัˆัƒะฒะฐะฝะฝัะผ ะฟะฐั€ะพะปั–ะฒ ั– ั‚ะพะบะตะฝะฐะผะธ JWT. + +ะ ะฟะพะบะธ ะทะพัะตั€ะตะดัŒะผะพัั ะฝะฐ ะบะพะฝะบั€ะตั‚ะฝะธั… ะดะตั‚ะฐะปัั…, ัะบั– ะฝะฐะผ ะฟะพั‚ั€ั–ะฑะฝั–. + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะณั–ะดะฝะพ ะทั– ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั”ัŽ, ะฒะธ ะผะฐั”ั‚ะต ะฟะพะฒะตั€ั‚ะฐั‚ะธ JSON ะท `access_token` ั– `token_type`, ัะบ ัƒ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั–. + +ะฆะต ั‚ะต, ั‰ะพ ะฒะธ ะผะฐั”ั‚ะต ะทั€ะพะฑะธั‚ะธ ัะฐะผะพัั‚ั–ะนะฝะพ ัƒ ัะฒะพั”ะผัƒ ะบะพะดั–, ั– ะฟะตั€ะตะบะพะฝะฐั‚ะธัั, ั‰ะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัะฐะผะต ั†ั– ะบะปัŽั‡ั– JSON. + +ะฆะต ะผะฐะนะถะต ั”ะดะธะฝะต, ั‰ะพ ะฒะธ ะผะฐั”ั‚ะต ะทั€ะพะฑะธั‚ะธ ะฟั€ะฐะฒะธะปัŒะฝะพ ัะฐะผั–, ั‰ะพะฑ ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั—. + +ะ ะตัˆั‚ัƒ **FastAPI** ะทั€ะพะฑะธั‚ัŒ ะทะฐ ะฒะฐั. + +/// + +## ะžะฝะพะฒั–ั‚ัŒ ะทะฐะปะตะถะฝะพัั‚ั– { #update-the-dependencies } + +ะขะตะฟะตั€ ะพะฝะพะฒะธะผะพ ะฝะฐัˆั– ะทะฐะปะตะถะฝะพัั‚ั–. + +ะœะธ ั…ะพั‡ะตะผะพ ะพั‚ั€ะธะผะฐั‚ะธ `current_user` ะปะธัˆะต ัะบั‰ะพ ั†ะตะน ะบะพั€ะธัั‚ัƒะฒะฐั‡ ะฐะบั‚ะธะฒะฝะธะน. + +ะขะพะผัƒ ัั‚ะฒะพั€ะธะผะพ ะดะพะดะฐั‚ะบะพะฒัƒ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_active_user`, ัะบะฐ ัะฒะพั”ัŽ ั‡ะตั€ะณะพัŽ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ัะบ ะทะฐะปะตะถะฝั–ัั‚ัŒ `get_current_user`. + +ะžะฑะธะดะฒั– ั†ั– ะทะฐะปะตะถะฝะพัั‚ั– ะฟั€ะพัั‚ะพ ะฟะพะฒะตั€ะฝัƒั‚ัŒ HTTP-ะฟะพะผะธะปะบัƒ, ัะบั‰ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะฝะต ั–ัะฝัƒั” ะฐะฑะพ ะฒั–ะฝ ะฝะตะฐะบั‚ะธะฒะฝะธะน. + +ะžั‚ะถะต, ัƒ ะฝะฐัˆั–ะน ะบั–ะฝั†ะตะฒั–ะน ั‚ะพั‡ั†ั– ะผะธ ะพั‚ั€ะธะผะฐั”ะผะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะปะธัˆะต ัะบั‰ะพ ะฒั–ะฝ ั–ัะฝัƒั”, ะฑัƒะฒ ะฟั€ะฐะฒะธะปัŒะฝะพ ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะพะฒะฐะฝะธะน ั– ั” ะฐะบั‚ะธะฒะฝะธะผ: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะ”ะพะดะฐั‚ะบะพะฒะธะน ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate` ะทั– ะทะฝะฐั‡ะตะฝะฝัะผ `Bearer`, ัะบะธะน ะผะธ ั‚ัƒั‚ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ, ั‚ะฐะบะพะถ ั” ั‡ะฐัั‚ะธะฝะพัŽ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ั—. + +ะ‘ัƒะดัŒ-ัะบะธะน HTTP (ะฟะพะผะธะปะบะฐ) ะทั– ัั‚ะฐั‚ัƒั-ะบะพะดะพะผ 401 ยซUNAUTHORIZEDยป ั‚ะฐะบะพะถ ะผะฐั” ะฟะพะฒะตั€ั‚ะฐั‚ะธ ะทะฐะณะพะปะพะฒะพะบ `WWW-Authenticate`. + +ะฃ ะฒะธะฟะฐะดะบัƒ ั‚ะพะบะตะฝั–ะฒ ะฝะพัั–ั (ะฝะฐัˆ ะฒะธะฟะฐะดะพะบ) ะทะฝะฐั‡ะตะฝะฝัะผ ั†ัŒะพะณะพ ะทะฐะณะพะปะพะฒะบะฐ ะผะฐั” ะฑัƒั‚ะธ `Bearer`. + +ะคะฐะบั‚ะธั‡ะฝะพ ะฒะธ ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะตะน ะดะพะดะฐั‚ะบะพะฒะธะน ะทะฐะณะพะปะพะฒะพะบ, ั– ะฒัะต ะพะดะฝะพ ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต. + +ะะปะต ะฒั–ะฝ ะฝะฐะดะฐะฝะธะน ั‚ัƒั‚, ั‰ะพะฑ ะฒั–ะดะฟะพะฒั–ะดะฐั‚ะธ ัะฟะตั†ะธั„ั–ะบะฐั†ั–ัะผ. + +ะขะฐะบะพะถ ะผะพะถัƒั‚ัŒ ั–ัะฝัƒะฒะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ัะบั– ะพั‡ั–ะบัƒัŽั‚ัŒ ั– ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะนะพะณะพ (ะทะฐั€ะฐะท ะฐะฑะพ ะฒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ), ั– ั†ะต ะผะพะถะต ะฑัƒั‚ะธ ะบะพั€ะธัะฝะพ ะฒะฐะผ ะฐะฑะพ ะฒะฐัˆะธะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐะผ, ะทะฐั€ะฐะท ะฐะฑะพ ะฒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ. + +ะฃ ั†ัŒะพะผัƒ ะบะพั€ะธัั‚ัŒ ัั‚ะฐะฝะดะฐั€ั‚ั–ะฒ... + +/// + +## ะŸะพะดะธะฒั–ั‚ัŒัั ะฒ ะดั–ั— { #see-it-in-action } + +ะ’ั–ะดะบั€ะธะนั‚ะต ั–ะฝั‚ะตั€ะฐะบั‚ะธะฒะฝัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ: http://127.0.0.1:8000/docs. + +### ะะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั { #authenticate } + +ะะฐั‚ะธัะฝั–ั‚ัŒ ะบะฝะพะฟะบัƒ ยซAuthorizeยป. + +ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ะพะฑะปั–ะบะพะฒั– ะดะฐะฝั–: + +ะšะพั€ะธัั‚ัƒะฒะฐั‡: `johndoe` + +ะŸะฐั€ะพะปัŒ: `secret` + + + +ะŸั–ัะปั ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบะฐั†ั–ั— ะฒ ัะธัั‚ะตะผั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต ั‚ะฐะบะต: + + + +### ะžั‚ั€ะธะผะฐะนั‚ะต ะฒะปะฐัะฝั– ะดะฐะฝั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ { #get-your-own-user-data } + +ะขะตะฟะตั€ ะฒะธะบะพั€ะธัั‚ะฐะนั‚ะต ะพะฟะตั€ะฐั†ั–ัŽ `GET` ะทั– ัˆะปัั…ะพะผ `/users/me`. + +ะ’ะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะดะฐะฝั– ัะฒะพะณะพ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ, ะฝะฐะฟั€ะธะบะปะฐะด: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +ะฏะบั‰ะพ ะฝะฐั‚ะธัะฝัƒั‚ะธ ะทะฝะฐั‡ะพะบ ะทะฐะผะบะฐ ะน ะฒะธะนั‚ะธ ะท ัะธัั‚ะตะผะธ, ะฐ ะฟะพั‚ั–ะผ ะทะฝะพะฒัƒ ัะฟั€ะพะฑัƒะฒะฐั‚ะธ ั‚ัƒ ัะฐะผัƒ ะพะฟะตั€ะฐั†ั–ัŽ, ะฒะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะพะผะธะปะบัƒ HTTP 401 ั‚ะฐะบะพะณะพ ะฒะธะณะปัะดัƒ: + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### ะะตะฐะบั‚ะธะฒะฝะธะน ะบะพั€ะธัั‚ัƒะฒะฐั‡ { #inactive-user } + +ะขะตะฟะตั€ ัะฟั€ะพะฑัƒะนั‚ะต ะท ะฝะตะฐะบั‚ะธะฒะฝะธะผ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะตะผ, ะฐะฒั‚ะตะฝั‚ะธั„ั–ะบัƒะนั‚ะตัั ะท: + +ะšะพั€ะธัั‚ัƒะฒะฐั‡: `alice` + +ะŸะฐั€ะพะปัŒ: `secret2` + +ะ† ัะฟั€ะพะฑัƒะนั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะพะฟะตั€ะฐั†ั–ัŽ `GET` ะทั– ัˆะปัั…ะพะผ `/users/me`. + +ะ’ะธ ะพั‚ั€ะธะผะฐั”ั‚ะต ะฟะพะผะธะปะบัƒ ยซInactive userยป, ะฝะฐะฟั€ะธะบะปะฐะด: + +```JSON +{ + "detail": "Inactive user" +} +``` + +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะขะตะฟะตั€ ัƒ ะฒะฐั ั” ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ ะดะปั ั€ะตะฐะปั–ะทะฐั†ั–ั— ะฟะพะฒะฝะพั— ัะธัั‚ะตะผะธ ะฑะตะทะฟะตะบะธ ะฝะฐ ะพัะฝะพะฒั– `username` ั– `password` ะดะปั ะฒะฐัˆะพะณะพ API. + +ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ั†ั– ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะธ, ะฒะธ ะผะพะถะตั‚ะต ะทั€ะพะฑะธั‚ะธ ัะธัั‚ะตะผัƒ ะฑะตะทะฟะตะบะธ ััƒะผั–ัะฝะพัŽ ะท ะฑัƒะดัŒ-ัะบะพัŽ ะฑะฐะทะพัŽ ะดะฐะฝะธั… ั– ะท ะฑัƒะดัŒ-ัะบะพัŽ ะผะพะดะตะปะปัŽ ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ั‡ะธ ะดะฐะฝะธั…. + +ะ„ะดะธะฝะฐ ะฒั–ะดััƒั‚ะฝั ะดะตั‚ะฐะปัŒ ัƒ ั‚ะพะผัƒ, ั‰ะพ ะฝะฐั€ะฐะทั– ั†ะต ั‰ะต ะฝะต ยซะฑะตะทะฟะตั‡ะฝะฐยป ั€ะตะฐะปั–ะทะฐั†ั–ั. + +ะฃ ะฝะฐัั‚ัƒะฟะฝะพะผัƒ ั€ะพะทะดั–ะปั– ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑะตะทะฟะตั‡ะฝัƒ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ ะดะปั ั…ะตัˆัƒะฒะฐะฝะฝั ะฟะฐั€ะพะปั–ะฒ ั– ั‚ะพะบะตะฝะธ JWT. diff --git a/docs/uk/docs/tutorial/sql-databases.md b/docs/uk/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..991d1e33aa --- /dev/null +++ b/docs/uk/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL (ั€ะตะปัั†ั–ะนะฝั–) ะฑะฐะทะธ ะดะฐะฝะธั… { #sql-relational-databases } + +**FastAPI** ะฝะต ะฒะธะผะฐะณะฐั” ะฒั–ะด ะฒะฐั ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ SQL (ั€ะตะปัั†ั–ะนะฝัƒ) ะฑะฐะทัƒ ะดะฐะฝะธั…. ะะปะต ะฒะธ ะผะพะถะตั‚ะต ัะบะพั€ะธัั‚ะฐั‚ะธัั ะฑัƒะดัŒ-ัะบะพัŽ ะฑะฐะทะพัŽ ะดะฐะฝะธั…, ัะบัƒ ะทะฐะฑะฐะถะฐั”ั‚ะต. + +ะขัƒั‚ ะผะธ ั€ะพะทะณะปัะฝะตะผะพ ะฟั€ะธะบะปะฐะด ะท SQLModel. + +**SQLModel** ะฟะพะฑัƒะดะพะฒะฐะฝะพ ะฟะพะฒะตั€ั… SQLAlchemy ั‚ะฐ Pydantic. ะ‡ั— ัั‚ะฒะพั€ะธะฒ ั‚ะพะน ัะฐะผะธะน ะฐะฒั‚ะพั€, ั‰ะพ ั– **FastAPI**, ัะบ ั–ะดะตะฐะปัŒะฝัƒ ะฟะฐั€ัƒ ะดะปั ะทะฐัั‚ะพััƒะฝะบั–ะฒ FastAPI, ัะบะธะผ ะฟะพั‚ั€ั–ะฑะฝั– **SQL ะฑะฐะทะธ ะดะฐะฝะธั…**. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบัƒ ั–ะฝัˆัƒ ะฑั–ะฑะปั–ะพั‚ะตะบัƒ ะดะปั SQL ะฐะฑะพ NoSQL ะฑะฐะท (ั–ะฝะบะพะปะธ ั—ั… ะฝะฐะทะธะฒะฐัŽั‚ัŒ "ORMs"), FastAPI ะฝั–ั‡ะพะณะพ ะฝะต ะฝะฐะฒโ€™ัะทัƒั”. ๐Ÿ˜Ž + +/// + +ะžัะบั–ะปัŒะบะธ SQLModel ะฑะฐะทัƒั”ั‚ัŒัั ะฝะฐ SQLAlchemy, ะฒะธ ะผะพะถะตั‚ะต ะปะตะณะบะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฑัƒะดัŒ-ัะบัƒ ะฑะฐะทัƒ ะดะฐะฝะธั…, ัะบัƒ ะฟั–ะดั‚ั€ะธะผัƒั” SQLAlchemy (ะฐ ะพั‚ะถะต ะน SQLModel), ะฝะฐะฟั€ะธะบะปะฐะด: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server ั‚ะพั‰ะพ + +ะฃ ั†ัŒะพะผัƒ ะฟั€ะธะบะปะฐะดั– ะผะธ ะฒะธะบะพั€ะธัั‚ะฐั”ะผะพ **SQLite**, ะพัะบั–ะปัŒะบะธ ะฒะพะฝะฐ ะทะฑะตั€ั–ะณะฐั”ั‚ัŒัั ะฒ ะพะดะฝะพะผัƒ ั„ะฐะนะปั–, ะฐ Python ะผะฐั” ะฒะฑัƒะดะพะฒะฐะฝัƒ ะฟั–ะดั‚ั€ะธะผะบัƒ. ะขะพะถ ะฒะธ ะผะพะถะตั‚ะต ัะบะพะฟั–ัŽะฒะฐั‚ะธ ั†ะตะน ะฟั€ะธะบะปะฐะด ั– ะทะฐะฟัƒัั‚ะธั‚ะธ ยซัะบ ั”ยป. + +ะŸั–ะทะฝั–ัˆะต, ะดะปั ะฒะฐัˆะพะณะพ ะฟั€ะพะดะฐะบัˆะฝ-ะทะฐัั‚ะพััƒะฝะบัƒ, ะฒะธ ะผะพะถะตั‚ะต ะฟะตั€ะตะนั‚ะธ ะฝะฐ ัะตั€ะฒะตั€ ะฑะฐะทะธ ะดะฐะฝะธั…, ะฝะฐะฟั€ะธะบะปะฐะด **PostgreSQL**. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ†ัะฝัƒั” ะพั„ั–ั†ั–ะนะฝะธะน ะณะตะฝะตั€ะฐั‚ะพั€ ะฟั€ะพั”ะบั‚ัƒ ะท **FastAPI** ั‚ะฐ **PostgreSQL**, ะฒะบะปัŽั‡ะฝะพ ะท ั„ั€ะพะฝั‚ะตะฝะดะพะผ ั‚ะฐ ั–ะฝัˆะธะผะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ะฐะผะธ: https://github.com/fastapi/full-stack-fastapi-template + +/// + +ะฆะต ะดัƒะถะต ะฟั€ะพัั‚ะธะน ั– ะบะพั€ะพั‚ะบะธะน ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ. ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะฒั‡ะธั‚ะธ ะฑะฐะทะธ ะดะฐะฝะธั… ะทะฐะณะฐะปะพะผ, SQL ะฐะฑะพ ะฑั–ะปัŒัˆ ะฟั€ะพััƒะฝัƒั‚ั– ะผะพะถะปะธะฒะพัั‚ั–, ะทะฒะตั€ะฝั–ั‚ัŒัั ะดะพ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— SQLModel. + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ `SQLModel` { #install-sqlmodel } + +ะกะฟะพั‡ะฐั‚ะบัƒ ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ัั‚ะฒะพั€ะธะปะธ [ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ะพั‚ะพั‡ะตะฝะฝั](../virtual-environments.md){.internal-link target=_blank}, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ั‚ะฐ ะฒัั‚ะฐะฝะพะฒะธะปะธ `sqlmodel`: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะฐัั‚ะพััƒะฝะพะบ ะท ะพะดะฝั–ั”ัŽ ะผะพะดะตะปะปัŽ { #create-the-app-with-a-single-model } + +ะกะฟะตั€ัˆัƒ ัั‚ะฒะพั€ะธะผะพ ะฝะฐะนะฟั€ะพัั‚ั–ัˆัƒ ะฒะตั€ัั–ัŽ ะทะฐัั‚ะพััƒะฝะบัƒ ะท ะพะดะฝั–ั”ัŽ ะผะพะดะตะปะปัŽ **SQLModel**. + +ะŸะพั‚ั–ะผ ะฝะธะถั‡ะต ะฟะพะบั€ะฐั‰ะธะผะพ ะฑะตะทะฟะตะบัƒ ั– ะณะฝัƒั‡ะบั–ัั‚ัŒ ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะบั–ะปัŒะบะพั… ะผะพะดะตะปะตะน. ๐Ÿค“ + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะผะพะดะตะปั– { #create-models } + +ะ†ะผะฟะพั€ั‚ัƒะนั‚ะต `SQLModel` ั– ัั‚ะฒะพั€ั–ั‚ัŒ ะผะพะดะตะปัŒ ะฑะฐะทะธ ะดะฐะฝะธั…: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +ะšะปะฐั `Hero` ะดัƒะถะต ัั…ะพะถะธะน ะฝะฐ ะผะพะดะตะปัŒ Pydantic (ั„ะฐะบั‚ะธั‡ะฝะพ, ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ั†ะต ั– ั” ะผะพะดะตะปัŒ Pydantic). + +ะ„ ะบั–ะปัŒะบะฐ ะฒั–ะดะผั–ะฝะฝะพัั‚ะตะน: + +* `table=True` ะบะฐะถะต SQLModel, ั‰ะพ ั†ะต ยซั‚ะฐะฑะปะธั‡ะฝะฐ ะผะพะดะตะปัŒยป - ะฒะพะฝะฐ ะผะฐั” ะฟั€ะตะดัั‚ะฐะฒะปัั‚ะธ **ั‚ะฐะฑะปะธั†ัŽ** ะฒ SQL ะฑะฐะทั– ะดะฐะฝะธั…, ะฐ ะฝะต ะฟั€ะพัั‚ะพ ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป (ัะบ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะทะฒะธั‡ะฐะนะฝะธะน ะบะปะฐั Pydantic). + +* `Field(primary_key=True)` ะบะฐะถะต SQLModel, ั‰ะพ `id` - ั†ะต **ะฟะตั€ะฒะธะฝะฝะธะน ะบะปัŽั‡** ัƒ SQL ะฑะฐะทั– ะดะฐะฝะธั… (ะฑั–ะปัŒัˆะต ะฟั€ะพ ะฟะตั€ะฒะธะฝะฝั– ะบะปัŽั‡ั– ะฒ SQL ะดะธะฒ. ัƒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— SQLModel). + + ะŸั€ะธะผั–ั‚ะบะฐ: ะœะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `int | None` ะดะปั ะฟะพะปั ะฟะตั€ะฒะธะฝะฝะพะณะพ ะบะปัŽั‡ะฐ, ั‰ะพะฑ ัƒ Python-ะบะพะดั– ะผะพะถะฝะฐ ะฑัƒะปะพ ัั‚ะฒะพั€ะธั‚ะธ ะพะฑโ€™ั”ะบั‚ ะฑะตะท `id` (`id=None`), ะฟั€ะธะฟัƒัะบะฐัŽั‡ะธ, ั‰ะพ ะฑะฐะทะฐ ะดะฐะฝะธั… ะทะณะตะฝะตั€ัƒั” ะนะพะณะพ ะฟั–ะด ั‡ะฐั ะทะฑะตั€ะตะถะตะฝะฝั. SQLModel ั€ะพะทัƒะผั–ั”, ั‰ะพ `id` ะฝะฐะดะฐัั‚ัŒ ะฑะฐะทะฐ ะดะฐะฝะธั…, ั– ะฒะธะทะฝะฐั‡ะฐั” ัั‚ะพะฒะฟะตั†ัŒ ัะบ ะฝะตะฝัƒะปัŒะพะฒะธะน `INTEGER` ัƒ ัั…ะตะผั– ะฑะฐะทะธ ะดะฐะฝะธั…. ะ”ะพะบะปะฐะดะฝั–ัˆะต ะดะธะฒ. ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ัŽ SQLModel ะฟั€ะพ ะฟะตั€ะฒะธะฝะฝั– ะบะปัŽั‡ั–. + +* `Field(index=True)` ะบะฐะถะต SQLModel ัั‚ะฒะพั€ะธั‚ะธ **SQL-ั–ะฝะดะตะบั** ะดะปั ั†ัŒะพะณะพ ัั‚ะพะฒะฟั†ั, ั‰ะพ ะดะพะทะฒะพะปะธั‚ัŒ ัˆะฒะธะดัˆะต ะฒะธะบะพะฝัƒะฒะฐั‚ะธ ะฟะพัˆัƒะบ ัƒ ะฑะฐะทั– ะดะฐะฝะธั… ะฟั–ะด ั‡ะฐั ั‡ะธั‚ะฐะฝะฝั ะดะฐะฝะธั…, ะฒั–ะดั„ั–ะปัŒั‚ั€ะพะฒะฐะฝะธั… ะทะฐ ั†ะธะผ ัั‚ะพะฒะฟั†ะตะผ. + + SQLModel ะทะฝะฐั‚ะธะผะต, ั‰ะพ ะพะณะพะปะพัˆะตะฝะต ัะบ `str` ัั‚ะฐะฝะต SQL-ัั‚ะพะฒะฟั†ะตะผ ั‚ะธะฟัƒ `TEXT` (ะฐะฑะพ `VARCHAR`, ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฑะฐะทะธ). + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ั€ัƒัˆั–ะน { #create-an-engine } + +`engine` SQLModel (ะฟั–ะด ะบะฐะฟะพั‚ะพะผ ั†ะต `engine` SQLAlchemy) - ั†ะต ั‚ะต, ั‰ะพ **ัƒั‚ั€ะธะผัƒั” ะทโ€™ั”ะดะฝะฐะฝะฝั** ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั…. + +ะฃ ะฒะฐั ะผะฐั” ะฑัƒั‚ะธ **ั”ะดะธะฝะธะน ะพะฑโ€™ั”ะบั‚ `engine`** ะดะปั ะฒััŒะพะณะพ ะบะพะดัƒ, ั‰ะพ ะฟั–ะดโ€™ั”ะดะฝัƒั”ั‚ัŒัั ะดะพ ั‚ั–ั”ั— ัะฐะผะพั— ะฑะฐะทะธ. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +ะ’ะธะบะพั€ะธัั‚ะฐะฝะฝั `check_same_thread=False` ะดะพะทะฒะพะปัั” FastAPI ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั‚ัƒ ัะฐะผัƒ ะฑะฐะทัƒ SQLite ัƒ ั€ั–ะทะฝะธั… ะฟะพั‚ะพะบะฐั…. ะฆะต ะฝะตะพะฑั…ั–ะดะฝะพ, ะฐะดะถะต **ะพะดะธะฝ ะทะฐะฟะธั‚** ะผะพะถะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ **ะฟะพะฝะฐะด ะพะดะธะฝ ะฟะพั‚ั–ะบ** (ะฝะฐะฟั€ะธะบะปะฐะด, ัƒ ะทะฐะปะตะถะฝะพัั‚ัั…). + +ะะต ะฟะตั€ะตะนะผะฐะนั‚ะตัั, ะทะฐะฒะดัะบะธ ัั‚ั€ัƒะบั‚ัƒั€ั– ะบะพะดัƒ ะผะธ ะดะฐะปั– ะทะฐะฑะตะทะฟะตั‡ะธะผะพ **ะพะดะฝัƒ ัะตัั–ัŽ SQLModel ะฝะฐ ะทะฐะฟะธั‚**, ะฒะปะฐัะฝะต ั†ัŒะพะณะพ ั– ะฟั€ะฐะณะฝะต `check_same_thread`. + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ั‚ะฐะฑะปะธั†ั– { #create-the-tables } + +ะ”ะพะดะฐะผะพ ั„ัƒะฝะบั†ั–ัŽ, ัะบะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `SQLModel.metadata.create_all(engine)`, ั‰ะพะฑ **ัั‚ะฒะพั€ะธั‚ะธ ั‚ะฐะฑะปะธั†ั–** ะดะปั ะฒัั–ั… ยซั‚ะฐะฑะปะธั‡ะฝะธั… ะผะพะดะตะปะตะนยป. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะทะฐะปะตะถะฝั–ัั‚ัŒ ัะตัั–ั— { #create-a-session-dependency } + +**`Session`** ะทะฑะตั€ั–ะณะฐั” **ะพะฑโ€™ั”ะบั‚ะธ ะฒ ะฟะฐะผโ€™ัั‚ั–** ั‚ะฐ ะฒั–ะดัั‚ะตะถัƒั” ะทะผั–ะฝะธ ัƒ ะดะฐะฝะธั…, ะฐ ะฟะพั‚ั–ะผ **ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” `engine`** ะดะปั ะฒะทะฐั”ะผะพะดั–ั— ะท ะฑะฐะทะพัŽ ะดะฐะฝะธั…. + +ะœะธ ัั‚ะฒะพั€ะธะผะพ **ะทะฐะปะตะถะฝั–ัั‚ัŒ** FastAPI ะท `yield`, ัะบะฐ ะฝะฐะดะฐะฒะฐั‚ะธะผะต ะฝะพะฒัƒ `Session` ะดะปั ะบะพะถะฝะพะณะพ ะทะฐะฟะธั‚ัƒ. ะฆะต ะน ะณะฐั€ะฐะฝั‚ัƒั”, ั‰ะพ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะพะดะฝัƒ ัะตัั–ัŽ ะฝะฐ ะทะฐะฟะธั‚. ๐Ÿค“ + +ะ”ะฐะปั– ัั‚ะฒะพั€ะธะผะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ `Annotated` - `SessionDep`, ั‰ะพะฑ ัะฟั€ะพัั‚ะธั‚ะธ ั€ะตัˆั‚ัƒ ะบะพะดัƒ, ัะบะธะน ั—ั— ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### ะกั‚ะฒะพั€ัŽะนั‚ะต ั‚ะฐะฑะปะธั†ั– ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ { #create-database-tables-on-startup } + +ะœะธ ัั‚ะฒะพั€ะธะผะพ ั‚ะฐะฑะปะธั†ั– ะฑะฐะทะธ ะฟั–ะด ั‡ะฐั ะทะฐะฟัƒัะบัƒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +ะขัƒั‚ ะผะธ ัั‚ะฒะพั€ัŽั”ะผะพ ั‚ะฐะฑะปะธั†ั– ะฝะฐ ะฟะพะดั–ั— ะทะฐะฟัƒัะบัƒ ะทะฐัั‚ะพััƒะฝะบัƒ. + +ะฃ ะฟั€ะพะดะฐะบัˆะฝั– ะฒะธ, ะนะผะพะฒั–ั€ะฝะพ, ะฒะธะบะพั€ะธัั‚ะฐั”ั‚ะต ะผั–ะณั€ะฐั†ั–ะนะฝะธะน ัะบั€ะธะฟั‚, ัะบะธะน ะฒะธะบะพะฝัƒั”ั‚ัŒัั ะฟะตั€ะตะด ัั‚ะฐั€ั‚ะพะผ ะทะฐัั‚ะพััƒะฝะบัƒ. ๐Ÿค“ + +/// tip | ะŸะพั€ะฐะดะฐ + +SQLModel ะผะฐั‚ะธะผะต ัƒั‚ะธะปั–ั‚ะธ ะผั–ะณั€ะฐั†ั–ะน-ะพะฑะณะพั€ั‚ะบะธ ะฝะฐะด Alembic, ะฐะปะต ะฟะพะบะธ ั‰ะพ ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Alembic ะฝะฐะฟั€ัะผัƒ. + +/// + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะณะตั€ะพั { #create-a-hero } + +ะžัะบั–ะปัŒะบะธ ะบะพะถะฝะฐ ะผะพะดะตะปัŒ SQLModel ั‚ะฐะบะพะถ ั” ะผะพะดะตะปะปัŽ Pydantic, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั—ั— ะฒ ั‚ะธั… ัะฐะผะธั… **ะฐะฝะพั‚ะฐั†ั–ัั… ั‚ะธะฟั–ะฒ**, ั‰ะพ ั– ะผะพะดะตะปั– Pydantic. + +ะะฐะฟั€ะธะบะปะฐะด, ัะบั‰ะพ ะฒะธ ะพะณะพะปะพัะธั‚ะต ะฟะฐั€ะฐะผะตั‚ั€ ั‚ะธะฟัƒ `Hero`, ะฒั–ะฝ ะฑัƒะดะต ะฟั€ะพั‡ะธั‚ะฐะฝะธะน ะท **JSON-ั‚ั–ะปะฐ**. + +ะขะฐะบ ัะฐะผะพ ะฒะธ ะผะพะถะตั‚ะต ะพะณะพะปะพัะธั‚ะธ ั—ั— ัะบ **ั‚ะธะฟ, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั** ั„ัƒะฝะบั†ั–ั—, ั– ั„ะพั€ะผะฐ ะดะฐะฝะธั… ะทโ€™ัะฒะธั‚ัŒัั ะฒ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพะผัƒ UI ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— API. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +ะขัƒั‚ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ ะทะฐะปะตะถะฝั–ัั‚ัŒ `SessionDep` (`Session`), ั‰ะพะฑ ะดะพะดะฐั‚ะธ ะฝะพะฒะพะณะพ `Hero` ะดะพ ะตะบะทะตะผะฟะปัั€ะฐ `Session`, ะทะฐะบะพะผั–ั‚ะธั‚ะธ ะทะผั–ะฝะธ ะดะพ ะฑะฐะทะธ, ะพะฝะพะฒะธั‚ะธ ะดะฐะฝั– ะฒ `hero`, ะฐ ะฟะพั‚ั–ะผ ะฟะพะฒะตั€ะฝัƒั‚ะธ ะนะพะณะพ. + +### ะงะธั‚ะฐะฝะฝั ะณะตั€ะพั—ะฒ { #read-heroes } + +ะœะธ ะผะพะถะตะผะพ **ั‡ะธั‚ะฐั‚ะธ** `Hero` ะท ะฑะฐะทะธ ะดะฐะฝะธั…, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ `select()`. ะœะธ ะผะพะถะตะผะพ ะดะพะดะฐั‚ะธ `limit` ั– `offset` ะดะปั ะฟะฐะณั–ะฝะฐั†ั–ั— ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### ะงะธั‚ะฐะฝะฝั ะพะดะฝะพะณะพ ะณะตั€ะพั { #read-one-hero } + +ะœะธ ะผะพะถะตะผะพ **ะฟั€ะพั‡ะธั‚ะฐั‚ะธ** ะพะดะฝะพะณะพ `Hero`. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### ะ’ะธะดะฐะปะตะฝะฝั ะณะตั€ะพั { #delete-a-hero } + +ะœะธ ั‚ะฐะบะพะถ ะผะพะถะตะผะพ **ะฒะธะดะฐะปะธั‚ะธ** `Hero`. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### ะ—ะฐะฟัƒัะบ ะทะฐัั‚ะพััƒะฝะบัƒ { #run-the-app } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะŸะพั‚ั–ะผ ะฟะตั€ะตะนะดั–ั‚ัŒ ะดะพ ั–ะฝั‚ะตั€ั„ะตะนััƒ `/docs`, ะฒะธ ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ **FastAPI** ะฒะธะบะพั€ะธัั‚ะพะฒัƒั” ั†ั– **ะผะพะดะตะปั–** ะดะปั **ะดะพะบัƒะผะตะฝั‚ัƒะฒะฐะฝะฝั** API, ะฐ ั‚ะฐะบะพะถ ะดะปั **ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั—** ั‚ะฐ **ะฒะฐะปั–ะดะฐั†ั–ั—** ะดะฐะฝะธั…. + +
+ +
+ +## ะžะฝะพะฒั–ั‚ัŒ ะทะฐัั‚ะพััƒะฝะพะบ ะบั–ะปัŒะบะพะผะฐ ะผะพะดะตะปัะผะธ { #update-the-app-with-multiple-models } + +ะขะตะฟะตั€ ั‚ั€ะพั…ะธ **ะฒั–ะดั€ะตั„ะฐะบั‚ะพั€ะธะผะพ** ะทะฐัั‚ะพััƒะฝะพะบ, ั‰ะพะฑ ะฟั–ะดะฒะธั‰ะธั‚ะธ **ะฑะตะทะฟะตะบัƒ** ั‚ะฐ **ะณะฝัƒั‡ะบั–ัั‚ัŒ**. + +ะฏะบั‰ะพ ะฟะพะดะธะฒะธั‚ะธัั ะฝะฐ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฒะฐั€ั–ะฐะฝั‚, ัƒ UI ะฒะธะดะฝะพ, ั‰ะพ ะฝะฐั€ะฐะทั– ะบะปั–ั”ะฝั‚ ะผะพะถะต ัะฐะผ ะพะฑะธั€ะฐั‚ะธ `id` ะดะปั ัั‚ะฒะพั€ัŽะฒะฐะฝะพะณะพ `Hero`. ๐Ÿ˜ฑ + +ะฆัŒะพะณะพ ะดะพะฟัƒัะบะฐั‚ะธ ะฝะต ะผะพะถะฝะฐ - ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ะฟะตั€ะตะทะฐะฟะธัะฐั‚ะธ `id`, ัะบะธะน ัƒะถะต ะฟั€ะธะทะฝะฐั‡ะตะฝะธะน ัƒ ะ‘ะ”. ะ’ะธะทะฝะฐั‡ะตะฝะฝั `id` ะผะฐั” ะฒะธะบะพะฝัƒะฒะฐั‚ะธ **ะฑะตะบะตะฝะด** ะฐะฑะพ **ะฑะฐะทะฐ ะดะฐะฝะธั…**, **ะฐ ะฝะต ะบะปั–ั”ะฝั‚**. + +ะšั€ั–ะผ ั‚ะพะณะพ, ะผะธ ัั‚ะฒะพั€ัŽั”ะผะพ ะดะปั ะณะตั€ะพั `secret_name`, ะฐะปะต ะฝะฐั€ะฐะทั– ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ะนะพะณะพ ะฒััŽะดะธ - ั†ะต ะฝะต ะดัƒะถะต ยซัะตะบั€ะตั‚ะฝะพยป... ๐Ÿ˜… + +ะ’ะธะฟั€ะฐะฒะธะผะพ ั†ะต, ะดะพะดะฐะฒัˆะธ ะบั–ะปัŒะบะฐ **ะดะพะดะฐั‚ะบะพะฒะธั… ะผะพะดะตะปะตะน**. ะžััŒ ะดะต SQLModel ะทะฐััั”. โœจ + +### ะกั‚ะฒะพั€ั–ั‚ัŒ ะบั–ะปัŒะบะฐ ะผะพะดะตะปะตะน { #create-multiple-models } + +ะฃ **SQLModel** ะฑัƒะดัŒ-ัะบะธะน ะบะปะฐั ะผะพะดะตะปั– ะท `table=True` - ั†ะต **ั‚ะฐะฑะปะธั‡ะฝะฐ ะผะพะดะตะปัŒ**. + +ะ ะฑัƒะดัŒ-ัะบะธะน ะบะปะฐั ะผะพะดะตะปั– ะฑะตะท `table=True` - ั†ะต **ะผะพะดะตะปัŒ ะดะฐะฝะธั…**; ั†ะต, ะฟะพ ััƒั‚ั–, ะฟั€ะพัั‚ะพ ะผะพะดะตะปั– Pydantic (ะท ะฟะฐั€ะพัŽ ะฝะตะฒะตะปะธะบะธั… ะดะพะฟะพะฒะฝะตะฝัŒ). ๐Ÿค“ + +ะ— SQLModel ะผะธ ะผะพะถะตะผะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **ัƒัะฟะฐะดะบัƒะฒะฐะฝะฝั**, ั‰ะพะฑ **ัƒะฝะธะบะฐั‚ะธ ะดัƒะฑะปัŽะฒะฐะฝะฝั** ะฟะพะปั–ะฒ ัƒ ะฒัั–ั… ะฒะธะฟะฐะดะบะฐั…. + +#### `HeroBase` - ะฑะฐะทะพะฒะธะน ะบะปะฐั { #herobase-the-base-class } + +ะŸะพั‡ะฝั–ะผะพ ะท ะผะพะดะตะปั– `HeroBase`, ัะบะฐ ะผั–ัั‚ะธั‚ัŒ ัƒัั– **ัะฟั–ะปัŒะฝั– ะฟะพะปั** ะดะปั ะฒัั–ั… ะผะพะดะตะปะตะน: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - ยซั‚ะฐะฑะปะธั‡ะฝะฐ ะผะพะดะตะปัŒยป { #hero-the-table-model } + +ะŸะพั‚ั–ะผ ัั‚ะฒะพั€ั–ะผะพ `Hero`, ั„ะฐะบั‚ะธั‡ะฝัƒ ยซั‚ะฐะฑะปะธั‡ะฝัƒ ะผะพะดะตะปัŒยป, ะท **ะดะพะดะฐั‚ะบะพะฒะธะผะธ ะฟะพะปัะผะธ**, ัะบะธั… ะฝะตะผะฐั” ะฒ ั–ะฝัˆะธั… ะผะพะดะตะปัั… ะทะฐะฒะถะดะธ: + +* `id` +* `secret_name` + +ะžัะบั–ะปัŒะบะธ `Hero` ัƒัะฟะฐะดะบะพะฒัƒั”ั‚ัŒัั ะฒั–ะด `HeroBase`, ะฒะพะฝะฐ **ั‚ะฐะบะพะถ** ะผั–ัั‚ะธั‚ัŒ **ะฟะพะปั**, ะพะณะพะปะพัˆะตะฝั– ะฒ `HeroBase`, ั‚ะพะถ ัƒัั– ะฟะพะปั `Hero` ั‚ะฐะบั–: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - ะฟัƒะฑะปั–ั‡ะฝะฐ ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป { #heropublic-the-public-data-model } + +ะ”ะฐะปั– ัั‚ะฒะพั€ะธะผะพ ะผะพะดะตะปัŒ `HeroPublic` - ั†ะต ั‚ะฐ, ั‰ะพ ะฑัƒะดะต **ะฟะพะฒะตั€ั‚ะฐั‚ะธัั** ะบะปั–ั”ะฝั‚ะฐะผ API. + +ะ’ะพะฝะฐ ะผะฐั” ั‚ั– ัะฐะผั– ะฟะพะปั, ั‰ะพ ะน `HeroBase`, ะพั‚ะถะต ะฝะต ะฒะบะปัŽั‡ะฐั‚ะธะผะต `secret_name`. + +ะะฐั€ะตัˆั‚ั–, ะพัะพะฑะธัั‚ะพัั‚ั– ะฝะฐัˆะธั… ะณะตั€ะพั—ะฒ ะทะฐั…ะธั‰ะตะฝะพ! ๐Ÿฅท + +ะ’ะพะฝะฐ ั‚ะฐะบะพะถ ะฟะตั€ะตะฒะธะทะฝะฐั‡ะฐั” `id: int`. ะ ะพะฑะปัั‡ะธ ั†ะต, ะผะธ ัƒะบะปะฐะดะฐั”ะผะพ **ะบะพะฝั‚ั€ะฐะบั‚** ะท ะบะปั–ั”ะฝั‚ะฐะผะธ API, ั‰ะพ `id` ะทะฐะฒะถะดะธ ะฑัƒะดะต ะฟั€ะธััƒั‚ะฝั–ะน ั– ะฑัƒะดะต ั‚ะธะฟัƒ `int` (ะฝั–ะบะพะปะธ ะฝะต `None`). + +/// tip | ะŸะพั€ะฐะดะฐ + +ะะฐัะฒะฝั–ัั‚ัŒ ัƒ ะผะพะดะตะปั– ะฒั–ะดะฟะพะฒั–ะดั– ะณะฐั€ะฐะฝั‚ั–ั—, ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั ะทะฐะฒะถะดะธ ะดะพัั‚ัƒะฟะฝะต ั– ะทะฐะฒะถะดะธ `int` (ะฝะต `None`), ะดัƒะถะต ะบะพั€ะธัะฝะฐ ะดะปั ะบะปั–ั”ะฝั‚ั–ะฒ API - ะฒะพะฝะธ ะผะพะถัƒั‚ัŒ ะฟะธัะฐั‚ะธ ะทะฝะฐั‡ะฝะพ ะฟั€ะพัั‚ั–ัˆะธะน ะบะพะด, ะผะฐัŽั‡ะธ ั†ัŽ ะฒะธะทะฝะฐั‡ะตะฝั–ัั‚ัŒ. + +ะขะฐะบะพะถ **ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะทะณะตะฝะตั€ะพะฒะฐะฝั– ะบะปั–ั”ะฝั‚ะธ** ะผะฐั‚ะธะผัƒั‚ัŒ ะฟั€ะพัั‚ั–ัˆั– ั–ะฝั‚ะตั€ั„ะตะนัะธ, ั‚ะพะถ ั€ะพะทั€ะพะฑะฝะธะบะฐะผ, ัะบั– ะฒะทะฐั”ะผะพะดั–ัŽั‚ัŒ ะท ะฒะฐัˆะธะผ API, ะฑัƒะดะต ะทะฝะฐั‡ะฝะพ ะทั€ัƒั‡ะฝั–ัˆะต. ๐Ÿ˜Ž + +/// + +ะฃัั– ะฟะพะปั ะฒ `HeroPublic` ั‚ะฐะบั– ัะฐะผั–, ัะบ ัƒ `HeroBase`, ะท `id`, ะพะณะพะปะพัˆะตะฝะธะผ ัะบ `int` (ะฝะต `None`): + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะณะตั€ะพั { #herocreate-the-data-model-to-create-a-hero } + +ะขะตะฟะตั€ ัั‚ะฒะพั€ะธะผะพ ะผะพะดะตะปัŒ `HeroCreate` - ะฒะพะฝะฐ **ะฒะฐะปั–ะดัƒะฒะฐั‚ะธะผะต** ะดะฐะฝั–, ะพั‚ั€ะธะผะฐะฝั– ะฒั–ะด ะบะปั–ั”ะฝั‚ั–ะฒ. + +ะ’ะพะฝะฐ ะผะฐั” ั‚ั– ะถ ะฟะพะปั, ั‰ะพ ะน `HeroBase`, ะฐ ั‚ะฐะบะพะถ `secret_name`. + +ะขะตะฟะตั€, ะบะพะปะธ ะบะปั–ั”ะฝั‚ะธ **ัั‚ะฒะพั€ัŽัŽั‚ัŒ ะฝะพะฒะพะณะพ ะณะตั€ะพั**, ะฒะพะฝะธ ะฝะฐะดัะธะปะฐัŽั‚ัŒ `secret_name`, ะฒั–ะฝ ะทะฑะตั€ั–ะณะฐั”ั‚ัŒัั ะฒ ะฑะฐะทั– ะดะฐะฝะธั…, ะฐะปะต ั†ั– ัะตะบั€ะตั‚ะฝั– ั–ะผะตะฝะฐ ะฝะต ะฟะพะฒะตั€ั‚ะฐัŽั‚ัŒัั ะบะปั–ั”ะฝั‚ะฐะผ ัƒ API. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขะฐะบ ัะปั–ะด ะฟะพะฒะพะดะธั‚ะธัั ะท **ะฟะฐั€ะพะปัะผะธ**. ะŸั€ะธะนะผะฐะนั‚ะต ั—ั…, ะฐะปะต ะฝะต ะฟะพะฒะตั€ั‚ะฐะนั‚ะต ะฒ API. + +ะขะฐะบะพะถ ะฟะพั‚ั€ั–ะฑะฝะพ **ั…ะตัˆัƒะฒะฐั‚ะธ** ะทะฝะฐั‡ะตะฝะฝั ะฟะฐั€ะพะปั–ะฒ ะฟะตั€ะตะด ะทะฑะตั€ะตะถะตะฝะฝัะผ, **ะฝั–ะบะพะปะธ ะฝะต ะทะฑะตั€ั–ะณะฐะนั‚ะต ั—ั… ัƒ ะฒั–ะดะบั€ะธั‚ะพะผัƒ ะฒะธะณะปัะดั–**. + +/// + +ะŸะพะปั `HeroCreate`: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป ะดะปั ะพะฝะพะฒะปะตะฝะฝั ะณะตั€ะพั { #heroupdate-the-data-model-to-update-a-hero } + +ะฃ ะฟะพะฟะตั€ะตะดะฝั–ะน ะฒะตั€ัั–ั— ัƒ ะฝะฐั ะฝะต ะฑัƒะปะพ ัะฟะพัะพะฑัƒ **ะพะฝะพะฒะปัŽะฒะฐั‚ะธ ะณะตั€ะพั**, ะฐะปะต ั‚ะตะฟะตั€, ะผะฐัŽั‡ะธ **ะบั–ะปัŒะบะฐ ะผะพะดะตะปะตะน**, ะผะธ ะผะพะถะตะผะพ ั†ะต ะทั€ะพะฑะธั‚ะธ. ๐ŸŽ‰ + +ยซะœะพะดะตะปัŒ ะดะฐะฝะธั…ยป `HeroUpdate` ะดะตั‰ะพ ะพัะพะฑะปะธะฒะฐ: ะฒะพะฝะฐ ะผะฐั” **ะฒัั– ั‚ั– ัะฐะผั– ะฟะพะปั**, ั‰ะพ ะน ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฝะพะฒะพะณะพ ะณะตั€ะพั, ะฐะปะต ะฒัั– ะฟะพะปั **ะฝะตะพะฑะพะฒโ€™ัะทะบะพะฒั–** (ัƒัั– ะผะฐัŽั‚ัŒ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ). ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะฟั–ะด ั‡ะฐั ะพะฝะพะฒะปะตะฝะฝั ะณะตั€ะพั ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะดั–ัะปะฐั‚ะธ ะปะธัˆะต ั‚ั– ะฟะพะปั, ัะบั– ั…ะพั‡ะตั‚ะต ะทะผั–ะฝะธั‚ะธ. + +ะžัะบั–ะปัŒะบะธ **ะฟะพะปั ั„ะฐะบั‚ะธั‡ะฝะพ ะทะผั–ะฝัŽัŽั‚ัŒัั** (ั‚ะธะฟ ั‚ะตะฟะตั€ ะฒะบะปัŽั‡ะฐั” `None` ั– ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ - `None`), ะฝะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ **ะพะณะพะปะพัะธั‚ะธ ั—ั… ะทะฐะฝะพะฒะพ**. + +ะะฐัะฟั€ะฐะฒะดั– ะฝะตะผะฐั” ะฟะพั‚ั€ะตะฑะธ ัƒัะฟะฐะดะบะพะฒัƒะฒะฐั‚ะธัั ะฒั–ะด `HeroBase`, ะฑะพ ะผะธ ะฟะตั€ะตะฒะธะทะฝะฐั‡ะฐั”ะผะพ ะฒัั– ะฟะพะปั. ะฏ ะทะฐะปะธัˆัƒ ัƒัะฟะฐะดะบัƒะฒะฐะฝะฝั ะดะปั ะฟะพัะปั–ะดะพะฒะฝะพัั‚ั–, ะฐะปะต ั†ะต ะฝะต ะพะฑะพะฒโ€™ัะทะบะพะฒะพ. ะฆะต ั€ะฐะดัˆะต ะฟะธั‚ะฐะฝะฝั ัะผะฐะบัƒ. ๐Ÿคท + +ะŸะพะปั `HeroUpdate`: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### ะกั‚ะฒะพั€ะตะฝะฝั ะท `HeroCreate` ั– ะฟะพะฒะตั€ะฝะตะฝะฝั `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } + +ะขะตะฟะตั€, ะบะพะปะธ ะฒ ะฝะฐั **ะบั–ะปัŒะบะฐ ะผะพะดะตะปะตะน**, ะผะธ ะผะพะถะตะผะพ ะพะฝะพะฒะธั‚ะธ ั‡ะฐัั‚ะธะฝะธ ะทะฐัั‚ะพััƒะฝะบัƒ, ั‰ะพ ั—ั… ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ. + +ะฃ ะทะฐะฟะธั‚ั– ะผะธ ะพั‚ั€ะธะผัƒั”ะผะพ ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป `HeroCreate`, ั– ะท ะฝะตั— ัั‚ะฒะพั€ัŽั”ะผะพ ยซั‚ะฐะฑะปะธั‡ะฝัƒ ะผะพะดะตะปัŒยป `Hero`. + +ะฆั ะฝะพะฒะฐ ยซั‚ะฐะฑะปะธั‡ะฝะฐ ะผะพะดะตะปัŒยป `Hero` ะผั–ัั‚ะธั‚ะธะผะต ะฟะพะปั, ะฝะฐะดั–ัะปะฐะฝั– ะบะปั–ั”ะฝั‚ะพะผ, ะฐ ั‚ะฐะบะพะถ ะผะฐั‚ะธะผะต `id`, ะทะณะตะฝะตั€ะพะฒะฐะฝะธะน ะฑะฐะทะพัŽ ะดะฐะฝะธั…. + +ะ”ะฐะปั– ะผะธ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ ะท ั„ัƒะฝะบั†ั–ั— ั†ัŽ ะถ ยซั‚ะฐะฑะปะธั‡ะฝัƒ ะผะพะดะตะปัŒยป `Hero`. ะะปะต ะพัะบั–ะปัŒะบะธ ะผะธ ะพะณะพะปะพัˆัƒั”ะผะพ `response_model` ัะบ ยซะผะพะดะตะปัŒ ะดะฐะฝะธั…ยป `HeroPublic`, **FastAPI** ะฒะธะบะพั€ะธัั‚ะฐั” `HeroPublic` ะดะปั ะฒะฐะปั–ะดะฐั†ั–ั— ั‚ะฐ ัะตั€ั–ะฐะปั–ะทะฐั†ั–ั— ะดะฐะฝะธั…. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | ะŸะพั€ะฐะดะฐ + +ะขะตะฟะตั€ ะผะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `response_model=HeroPublic` ะทะฐะผั–ัั‚ัŒ **ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟัƒ, ั‰ะพ ะฟะพะฒะตั€ั‚ะฐั”ั‚ัŒัั** `-> HeroPublic`, ั‚ะพะผัƒ ั‰ะพ ะทะฝะฐั‡ะตะฝะฝั, ัะบะต ะผะธ ะฟะพะฒะตั€ั‚ะฐั”ะผะพ, ะฝะฐัะฟั€ะฐะฒะดั– - ะฝะต `HeroPublic`. + +ะฏะบะฑะธ ะผะธ ะพะณะพะปะพัะธะปะธ `-> HeroPublic`, ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€ ั– ะปั–ะฝั‚ะตั€ ัะฟั€ะฐะฒะตะดะปะธะฒะพ ะทะฐัƒะฒะฐะถะธะปะธ ะฑ, ั‰ะพ ะฒะธ ะฟะพะฒะตั€ั‚ะฐั”ั‚ะต `Hero`, ะฐ ะฝะต `HeroPublic`. + +ะžะณะพะปะพัˆัƒัŽั‡ะธ ั†ะต ะฒ `response_model`, ะผะธ ะบะฐะถะตะผะพ **FastAPI** ะทั€ะพะฑะธั‚ะธ ัะฒะพัŽ ัะฟั€ะฐะฒัƒ, ะฝะต ะฒั‚ั€ัƒั‡ะฐัŽั‡ะธััŒ ะฒ ะฐะฝะพั‚ะฐั†ั–ั— ั‚ะธะฟั–ะฒ ั‚ะฐ ะฟั–ะดะบะฐะทะบะธ ะฒั–ะด ะฒะฐัˆะพะณะพ ั€ะตะดะฐะบั‚ะพั€ะฐ ะน ั–ะฝัˆะธั… ั–ะฝัั‚ั€ัƒะผะตะฝั‚ั–ะฒ. + +/// + +### ะงะธั‚ะฐะฝะฝั ะณะตั€ะพั—ะฒ ะท `HeroPublic` { #read-heroes-with-heropublic } + +ะœะพะถะตะผะพ ะทั€ะพะฑะธั‚ะธ ั‚ะต ัะฐะผะต, ั‰ะพ ะน ั€ะฐะฝั–ัˆะต, ั‰ะพะฑ **ั‡ะธั‚ะฐั‚ะธ** `Hero`, ะทะฝะพะฒัƒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `response_model=list[HeroPublic]`, ั‰ะพะฑ ะณะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ ะบะพั€ะตะบั‚ะฝัƒ ะฒะฐะปั–ะดะฐั†ั–ัŽ ั‚ะฐ ัะตั€ั–ะฐะปั–ะทะฐั†ั–ัŽ ะดะฐะฝะธั…. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### ะงะธั‚ะฐะฝะฝั ะพะดะฝะพะณะพ ะณะตั€ะพั ะท `HeroPublic` { #read-one-hero-with-heropublic } + +ะœะธ ะผะพะถะตะผะพ **ะฟั€ะพั‡ะธั‚ะฐั‚ะธ** ะพะดะฝะพะณะพ ะณะตั€ะพั: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### ะžะฝะพะฒะปะตะฝะฝั ะณะตั€ะพั ะท `HeroUpdate` { #update-a-hero-with-heroupdate } + +ะœะธ ะผะพะถะตะผะพ **ะพะฝะพะฒะธั‚ะธ ะณะตั€ะพั**. ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ HTTP-ะพะฟะตั€ะฐั†ั–ัŽ `PATCH`. + +ะฃ ะบะพะดั– ะผะธ ะพั‚ั€ะธะผัƒั”ะผะพ `dict` ะท ัƒัั–ะผะฐ ะดะฐะฝะธะผะธ, ัะบั– ะฝะฐะดั–ัะปะฐะฒ ะบะปั–ั”ะฝั‚, - ะปะธัˆะต ะท ั‚ะธะผะธ ะดะฐะฝะธะผะธ, ัะบั– ะฝะฐะดั–ัะปะฐะฒ ะบะปั–ั”ะฝั‚, ะฒะธะบะปัŽั‡ะฐัŽั‡ะธ ะฑัƒะดัŒ-ัะบั– ะทะฝะฐั‡ะตะฝะฝั, ะฟั€ะธััƒั‚ะฝั– ะปะธัˆะต ัะบ ะทะฝะฐั‡ะตะฝะฝั ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ. ะ”ะปั ั†ัŒะพะณะพ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `exclude_unset=True`. ะฆะต ะณะพะปะพะฒะฝะธะน ั‚ั€ัŽะบ. ๐Ÿช„ + +ะŸะพั‚ั–ะผ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ะผะพ `hero_db.sqlmodel_update(hero_data)`, ั‰ะพะฑ ะพะฝะพะฒะธั‚ะธ `hero_db` ะดะฐะฝะธะผะธ ะท `hero_data`. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### ะ—ะฝะพะฒัƒ ะฒะธะดะฐะปะตะฝะฝั ะณะตั€ะพั { #delete-a-hero-again } + +**ะ’ะธะดะฐะปะตะฝะฝั** ะณะตั€ะพั ะผะฐะนะถะต ะฝะต ะทะผั–ะฝะธะปะพัั. + +ะœะธ ะฝะต ะทะฐะดะพะฒะพะปัŒะฝะธะผะพ ะฑะฐะถะฐะฝะฝั ะฒั–ะดั€ะตั„ะฐะบั‚ะพั€ะธั‚ะธ ะฒัะต ะฒ ั†ัŒะพะผัƒ ะผั–ัั†ั–. ๐Ÿ˜… + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### ะ—ะฝะพะฒัƒ ะทะฐะฟัƒัั‚ั–ั‚ัŒ ะทะฐัั‚ะพััƒะฝะพะบ { #run-the-app-again } + +ะ’ะธ ะผะพะถะตั‚ะต ะทะฝะพะฒัƒ ะทะฐะฟัƒัั‚ะธั‚ะธ ะทะฐัั‚ะพััƒะฝะพะบ: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ะฏะบั‰ะพ ะฒะธ ะฟะตั€ะตะนะดะตั‚ะต ะดะพ UI `/docs`, ะฟะพะฑะฐั‡ะธั‚ะต, ั‰ะพ ะฒั–ะฝ ะพะฝะพะฒะธะฒัั ั– ะฑั–ะปัŒัˆะต ะฝะต ะพั‡ั–ะบัƒะฒะฐั‚ะธะผะต ะพั‚ั€ะธะผะฐั‚ะธ `id` ะฒั–ะด ะบะปั–ั”ะฝั‚ะฐ ะฟั–ะด ั‡ะฐั ัั‚ะฒะพั€ะตะฝะฝั ะณะตั€ะพั ั‚ะพั‰ะพ. + +
+ +
+ +## ะŸั–ะดััƒะผะพะบ { #recap } + +ะ’ะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ **SQLModel** ะดะปั ะฒะทะฐั”ะผะพะดั–ั— ะท SQL ะฑะฐะทะพัŽ ะดะฐะฝะธั… ั– ัะฟั€ะพัั‚ะธั‚ะธ ะบะพะด ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ยซะผะพะดะตะปะตะน ะดะฐะฝะธั…ยป ั‚ะฐ ยซั‚ะฐะฑะปะธั‡ะฝะธั… ะผะพะดะตะปะตะนยป. + +ะ‘ะฐะณะฐั‚ะพ ั‡ะพะณะพ ั‰ะต ะผะพะถะฝะฐ ะดั–ะทะฝะฐั‚ะธัั ะฒ ะดะพะบัƒะผะตะฝั‚ะฐั†ั–ั— **SQLModel**, ั‚ะฐะผ ั” ั€ะพะทัˆะธั€ะตะฝะธะน ะผั–ะฝั–-ะฝะฐะฒั‡ะฐะปัŒะฝะธะน ะฟะพัั–ะฑะฝะธะบ ะท ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั SQLModel ะท **FastAPI**. ๐Ÿš€ diff --git a/docs/uk/docs/virtual-environments.md b/docs/uk/docs/virtual-environments.md new file mode 100644 index 0000000000..78e7ab32f5 --- /dev/null +++ b/docs/uk/docs/virtual-environments.md @@ -0,0 +1,862 @@ +# ะ’ั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ { #virtual-environments } + +ะšะพะปะธ ะฒะธ ะฟั€ะฐั†ัŽั”ั‚ะต ะฝะฐะด ะฟั€ะพั”ะบั‚ะฐะผะธ Python, ะฒะฐะผ, ั–ะผะพะฒั–ั€ะฝะพ, ัะปั–ะด ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต (ะฐะฑะพ ัั…ะพะถะธะน ะผะตั…ะฐะฝั–ะทะผ), ั‰ะพะฑ ั–ะทะพะปัŽะฒะฐั‚ะธ ะฟะฐะบะตั‚ะธ, ัะบั– ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะดะปั ะบะพะถะฝะพะณะพ ะฟั€ะพั”ะบั‚ัƒ. + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะฏะบั‰ะพ ะฒะธ ะฒะถะต ะทะฝะฐั”ั‚ะต ะฟั€ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ, ัะบ ั—ั… ัั‚ะฒะพั€ัŽะฒะฐั‚ะธ ั‚ะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ, ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะตะน ั€ะพะทะดั–ะป. ๐Ÿค“ + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒั–ะดั€ั–ะทะฝัั”ั‚ัŒัั ะฒั–ะด ะทะผั–ะฝะฝะพั— ะพั‚ะพั‡ะตะฝะฝั. + +ะ—ะผั–ะฝะฝะฐ ะพั‚ะพั‡ะตะฝะฝั - ั†ะต ะทะผั–ะฝะฝะฐ ะฒ ัะธัั‚ะตะผั–, ัะบัƒ ะผะพะถัƒั‚ัŒ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฟั€ะพะณั€ะฐะผะธ. + +ะ’ั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต - ั†ะต ะบะฐั‚ะฐะปะพะณ ั–ะท ั„ะฐะนะปะฐะผะธ ะฒ ะฝัŒะพะผัƒ. + +/// + +/// info | ะ†ะฝั„ะพั€ะผะฐั†ั–ั + +ะะฐ ั†ั–ะน ัั‚ะพั€ั–ะฝั†ั– ะฒะธ ะดั–ะทะฝะฐั”ั‚ะตัั, ัะบ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ ั– ัะบ ะฒะพะฝะธ ะฟั€ะฐั†ัŽัŽั‚ัŒ. + +ะฏะบั‰ะพ ะฒะธ ะณะพั‚ะพะฒั– ะฟั€ะธะนะฝัั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚, ั‰ะพ ะบะตั€ัƒั” ะฒัั–ะผ ะทะฐ ะฒะฐั (ะฒะบะปัŽั‡ะฝะพ ะท ัƒัั‚ะฐะฝะพะฒะปะตะฝะฝัะผ Python), ัะฟั€ะพะฑัƒะนั‚ะต uv. + +/// + +## ะกั‚ะฒะพั€ั–ั‚ัŒ ะฟั€ะพั”ะบั‚ { #create-a-project } + +ะกะฟะพั‡ะฐั‚ะบัƒ ัั‚ะฒะพั€ั–ั‚ัŒ ะบะฐั‚ะฐะปะพะณ ะดะปั ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ. + +ะ—ะฐะทะฒะธั‡ะฐะน ั ัั‚ะฒะพั€ัŽัŽ ะบะฐั‚ะฐะปะพะณ ะท ะฝะฐะทะฒะพัŽ `code` ัƒ ะผะพั”ะผัƒ ะดะพะผะฐัˆะฝัŒะพะผัƒ ะบะฐั‚ะฐะปะพะทั– ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ. + +ะ† ะฒัะตั€ะตะดะธะฝั– ะฝัŒะพะณะพ ั ัั‚ะฒะพั€ัŽัŽ ะพะบั€ะตะผะธะน ะบะฐั‚ะฐะปะพะณ ะฝะฐ ะบะพะถะตะฝ ะฟั€ะพั”ะบั‚. + +
+ +```console +// ะŸะตั€ะตะนะดั–ั‚ัŒ ะดะพ ะดะพะผะฐัˆะฝัŒะพะณะพ ะบะฐั‚ะฐะปะพะณัƒ +$ cd +// ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะฐั‚ะฐะปะพะณ ะดะปั ะฒัั–ั… ะฒะฐัˆะธั… ะฟั€ะพั”ะบั‚ั–ะฒ ะท ะบะพะดะพะผ +$ mkdir code +// ะŸะตั€ะตะนะดั–ั‚ัŒ ัƒ ั†ะตะน ะบะฐั‚ะฐะปะพะณ code +$ cd code +// ะกั‚ะฒะพั€ั–ั‚ัŒ ะบะฐั‚ะฐะปะพะณ ะดะปั ั†ัŒะพะณะพ ะฟั€ะพั”ะบั‚ัƒ +$ mkdir awesome-project +// ะŸะตั€ะตะนะดั–ั‚ัŒ ะดะพ ะบะฐั‚ะฐะปะพะณัƒ ั†ัŒะพะณะพ ะฟั€ะพั”ะบั‚ัƒ +$ cd awesome-project +``` + +
+ +## ะกั‚ะฒะพั€ั–ั‚ัŒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต { #create-a-virtual-environment } + +ะšะพะปะธ ะฒะธ ะฟะพั‡ะธะฝะฐั”ั‚ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐะด ะฟั€ะพั”ะบั‚ะพะผ Python ัƒะฟะตั€ัˆะต, ัั‚ะฒะพั€ั–ั‚ัŒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ัƒ ะฒะฐัˆะพะผัƒ ะฟั€ะพั”ะบั‚ั– **ัƒ ะฒะฐัˆะพะผัƒ ะฟั€ะพั”ะบั‚ั–**. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะฟะพั‚ั€ั–ะฑะฝะพ ั€ะพะฑะธั‚ะธ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท ะฝะฐ ะฟั€ะพั”ะบั‚, ะฝะต ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะฟั€ะฐั†ัŽั”ั‚ะต. + +/// + +//// tab | `venv` + +ะฉะพะฑ ัั‚ะฒะพั€ะธั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะผะพะดัƒะปัŒ `venv`, ัะบะธะน ะฟะพัั‚ะฐั‡ะฐั”ั‚ัŒัั ั€ะฐะทะพะผ ั–ะท Python. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | ะฉะพ ะพะทะฝะฐั‡ะฐั” ั†ั ะบะพะผะฐะฝะดะฐ + +* `python`: ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะฟั€ะพะณั€ะฐะผัƒ ะท ะฝะฐะทะฒะพัŽ `python` +* `-m`: ะฒะธะบะปะธะบะฐั‚ะธ ะผะพะดัƒะปัŒ ัะบ ัะบั€ะธะฟั‚, ะดะฐะปั– ะผะธ ะฒะบะฐะถะตะผะพ, ัะบะธะน ะผะพะดัƒะปัŒ +* `venv`: ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะผะพะดัƒะปัŒ ะท ะฝะฐะทะฒะพัŽ `venv`, ัะบะธะน ะทะฐะทะฒะธั‡ะฐะน ัƒะถะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ะท Python +* `.venv`: ัั‚ะฒะพั€ะธั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒ ะฝะพะฒะพะผัƒ ะบะฐั‚ะฐะปะพะทั– `.venv` + +/// + +//// + +//// tab | `uv` + +ะฏะบั‰ะพ ัƒ ะฒะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ `uv`, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะนะพะณะพ ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะขะธะฟะพะฒะพ `uv` ัั‚ะฒะพั€ะธั‚ัŒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒ ะบะฐั‚ะฐะปะพะทั– ะท ะฝะฐะทะฒะพัŽ `.venv`. + +ะะปะต ะฒะธ ะผะพะถะตั‚ะต ะฝะฐะปะฐัˆั‚ัƒะฒะฐั‚ะธ ั†ะต, ะฟะตั€ะตะดะฐะฒัˆะธ ะดะพะดะฐั‚ะบะพะฒะธะน ะฐั€ะณัƒะผะตะฝั‚ ะท ะฝะฐะทะฒะพัŽ ะบะฐั‚ะฐะปะพะณัƒ. + +/// + +//// + +ะฆั ะบะพะผะฐะฝะดะฐ ัั‚ะฒะพั€ัŽั” ะฝะพะฒะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒ ะบะฐั‚ะฐะปะพะทั– ะท ะฝะฐะทะฒะพัŽ `.venv`. + +/// details | `.venv` ะฐะฑะพ ั–ะฝัˆะฐ ะฝะฐะทะฒะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒ ั–ะฝัˆะพะผัƒ ะบะฐั‚ะฐะปะพะทั–, ะฐะปะต ั–ัะฝัƒั” ัƒัั‚ะฐะปะตะฝะฐ ะดะพะผะพะฒะปะตะฝั–ัั‚ัŒ ะฝะฐะทะธะฒะฐั‚ะธ ะนะพะณะพ `.venv`. + +/// + +## ะะบั‚ะธะฒัƒะนั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต { #activate-the-virtual-environment } + +ะะบั‚ะธะฒัƒะนั‚ะต ะฝะพะฒะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ั‰ะพะฑ ะฑัƒะดัŒ-ัะบะฐ ะบะพะผะฐะฝะดะฐ Python, ัะบัƒ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต, ะฐะฑะพ ะฟะฐะบะตั‚, ัะบะธะน ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต, ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐะปะธ ะนะพะณะพ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ ะพะฑั–ั‚ัŒ ั†ะต ั‰ะพั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะฟะพั‡ะธะฝะฐั”ั‚ะต ะฝะพะฒัƒ ัะตัั–ัŽ ั‚ะตั€ะผั–ะฝะฐะปะฐ ะดะปั ั€ะพะฑะพั‚ะธ ะฝะฐะด ะฟั€ะพั”ะบั‚ะพะผ. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +ะะฑะพ ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Bash ะดะปั Windows (ะฝะฐะฟั€., Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะšะพะถะฝะพะณะพ ั€ะฐะทัƒ, ะบะพะปะธ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะฝะพะฒะธะน ะฟะฐะบะตั‚ ัƒ ั†ะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฐะบั‚ะธะฒัƒะนั‚ะต ัะตั€ะตะดะพะฒะธั‰ะต ะทะฝะพะฒัƒ. + +ะฆะต ะณะฐั€ะฐะฝั‚ัƒั”, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฟั€ะพะณั€ะฐะผัƒ ั‚ะตั€ะผั–ะฝะฐะปะฐ (CLI), ะฒัั‚ะฐะฝะพะฒะปะตะฝัƒ ั†ะธะผ ะฟะฐะบะตั‚ะพะผ, ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัะฐะผะต ั‚ัƒ ะท ะฒะฐัˆะพะณะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ, ะฐ ะฝะต ะฑัƒะดัŒ-ัะบัƒ ั–ะฝัˆัƒ, ัะบะฐ ะผะพะถะต ะฑัƒั‚ะธ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฐ ะณะปะพะฑะฐะปัŒะฝะพ, ั–ะผะพะฒั–ั€ะฝะพ ะท ั–ะฝัˆะพัŽ ะฒะตั€ัั–ั”ัŽ, ะฝั–ะถ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ. + +/// + +## ะŸะตั€ะตะฒั–ั€ั‚ะต ะฐะบั‚ะธะฒะฝั–ัั‚ัŒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ { #check-the-virtual-environment-is-active } + +ะŸะตั€ะตะฒั–ั€ั‚ะต, ั‰ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฐะบั‚ะธะฒะฝะต (ะฟะพะฟะตั€ะตะดะฝั ะบะพะผะฐะฝะดะฐ ัะฟั€ะฐั†ัŽะฒะฐะปะฐ). + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฆะต ะฝะตะพะฑะพะฒ'ัะทะบะพะฒะพ, ะฐะปะต ั†ะต ะณะฐั€ะฝะธะน ัะฟะพัั–ะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั” ัะบ ะพั‡ั–ะบัƒั”ั‚ัŒัั ั– ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ัะฐะผะต ั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ัะบะต ะฟะปะฐะฝัƒะฒะฐะปะธ. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +ะฏะบั‰ะพ ะฟะพะบะฐะทะฐะฝะพ ะฑั–ะฝะฐั€ะฝะธะน ั„ะฐะนะป `python` ะทะฐ ัˆะปัั…ะพะผ `.venv/bin/python` ัƒัะตั€ะตะดะธะฝั– ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `awesome-project`), ั‚ะพะดั– ะฒัะต ัะฟั€ะฐั†ัŽะฒะฐะปะพ. ๐ŸŽ‰ + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +ะฏะบั‰ะพ ะฟะพะบะฐะทะฐะฝะพ ะฑั–ะฝะฐั€ะฝะธะน ั„ะฐะนะป `python` ะทะฐ ัˆะปัั…ะพะผ `.venv\Scripts\python` ัƒัะตั€ะตะดะธะฝั– ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ (ัƒ ั†ัŒะพะผัƒ ะฒะธะฟะฐะดะบัƒ `awesome-project`), ั‚ะพะดั– ะฒัะต ัะฟั€ะฐั†ัŽะฒะฐะปะพ. ๐ŸŽ‰ + +//// + +## ะžะฝะพะฒั–ั‚ัŒ `pip` { #upgrade-pip } + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `uv`, ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะตั‚ะต ะนะพะณะพ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะทะฐะผั–ัั‚ัŒ `pip`, ั‚ะพะถ ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะพะฝะพะฒะปัŽะฒะฐั‚ะธ `pip`. ๐Ÿ˜Ž + +/// + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต `pip` ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฟะฐะบะตั‚ั–ะฒ (ะฒั–ะฝ ั–ะดะต ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ ั–ะท Python), ะฒะฐะผ ัะปั–ะด ะพะฝะพะฒะธั‚ะธ ะนะพะณะพ ะดะพ ะฝะฐะนะฝะพะฒั–ัˆะพั— ะฒะตั€ัั–ั—. + +ะ‘ะฐะณะฐั‚ะพ ะดะธะฒะฝะธั… ะฟะพะผะธะปะพะบ ะฟั–ะด ั‡ะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฟะฐะบะตั‚ะฐ ะฒะธั€ั–ัˆัƒัŽั‚ัŒัั ั‚ะธะผ, ั‰ะพ ัะฟะพั‡ะฐั‚ะบัƒ ะพะฝะพะฒะปัŽัŽั‚ัŒ `pip`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐะทะฒะธั‡ะฐะน ั†ะต ั€ะพะฑะปัั‚ัŒ ะพะดะธะฝ ั€ะฐะท, ะฒั–ะดั€ะฐะทัƒ ะฟั–ัะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ. + +/// + +ะŸะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฐะบั‚ะธะฒะฝะต (ะบะพะผะฐะฝะดะพัŽ ะฒะธั‰ะต), ะฐ ะฟะพั‚ั–ะผ ะฒะธะบะพะฝะฐะนั‚ะต: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +/// tip | ะŸะพั€ะฐะดะฐ + +ะ†ะฝะพะดั– ะฒะธ ะผะพะถะตั‚ะต ะพั‚ั€ะธะผะฐั‚ะธ ะฟะพะผะธะปะบัƒ **`No module named pip`** ะฟั€ะธ ัะฟั€ะพะฑั– ะพะฝะพะฒะธั‚ะธ pip. + +ะฏะบั‰ะพ ั†ะต ัั‚ะฐะปะพัั, ะฒัั‚ะฐะฝะพะฒั–ั‚ัŒ ั– ะพะฝะพะฒั–ั‚ัŒ pip ะทะฐ ะดะพะฟะพะผะพะณะพัŽ ะบะพะผะฐะฝะดะธ ะฝะธะถั‡ะต: + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +ะฆั ะบะพะผะฐะฝะดะฐ ะฒัั‚ะฐะฝะพะฒะธั‚ัŒ pip, ัะบั‰ะพ ะฒั–ะฝ ั‰ะต ะฝะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะธะน, ั– ั‚ะฐะบะพะถ ะณะฐั€ะฐะฝั‚ัƒั”, ั‰ะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฐ ะฒะตั€ัั–ั pip ะฟั€ะธะฝะฐะนะผะฝั– ั‚ะฐะบะฐ ะถ ะฝะพะฒะฐ, ัะบ ะดะพัั‚ัƒะฟะฝะฐ ะฒ `ensurepip`. + +/// + +## ะ”ะพะดะฐะนั‚ะต `.gitignore` { #add-gitignore } + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Git (ะฒะฐั€ั‚ะพ ั†ะต ั€ะพะฑะธั‚ะธ), ะดะพะดะฐะนั‚ะต ั„ะฐะนะป `.gitignore`, ั‰ะพะฑ ะฒะธะบะปัŽั‡ะธั‚ะธ ะท Git ัƒัะต ัƒ ะฒะฐัˆะพะผัƒ `.venv`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฏะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะฐะปะธ `uv` ะดะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ, ะฒั–ะฝ ัƒะถะต ะทั€ะพะฑะธะฒ ั†ะต ะทะฐ ะฒะฐั, ะผะพะถะตั‚ะต ะฟั€ะพะฟัƒัั‚ะธั‚ะธ ั†ะตะน ะบั€ะพะบ. ๐Ÿ˜Ž + +/// + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ั€ะพะฑั–ั‚ัŒ ั†ะต ะพะดะธะฝ ั€ะฐะท, ะฒั–ะดั€ะฐะทัƒ ะฟั–ัะปั ัั‚ะฒะพั€ะตะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | ะฉะพ ะพะทะฝะฐั‡ะฐั” ั†ั ะบะพะผะฐะฝะดะฐ + +* `echo "*"`: ยซะฒะธะฒะตะดะตยป ั‚ะตะบัั‚ `*` ัƒ ั‚ะตั€ะผั–ะฝะฐะป (ะฝะฐัั‚ัƒะฟะฝะฐ ั‡ะฐัั‚ะธะฝะฐ ั‚ั€ะพั…ะธ ั†ะต ะทะผั–ะฝัŽั”) +* `>`: ัƒัะต, ั‰ะพ ะบะพะผะฐะฝะดะฐ ะปั–ะฒะพั€ัƒั‡ ะฒั–ะด `>` ยซะฒะธะฒะพะดะธั‚ัŒยป ัƒ ั‚ะตั€ะผั–ะฝะฐะป, ะฝะต ัะปั–ะด ะดั€ัƒะบัƒะฒะฐั‚ะธ, ะฝะฐั‚ะพะผั–ัั‚ัŒ ะทะฐะฟะธัะฐั‚ะธ ัƒ ั„ะฐะนะป, ะฒะบะฐะทะฐะฝะธะน ะฟั€ะฐะฒะพั€ัƒั‡ ะฒั–ะด `>` +* `.gitignore`: ะฝะฐะทะฒะฐ ั„ะฐะนะปัƒ, ะบัƒะดะธ ัะปั–ะด ะทะฐะฟะธัะฐั‚ะธ ั‚ะตะบัั‚ + +ะ `*` ะดะปั Git ะพะทะฝะฐั‡ะฐั” ยซะฒัะตยป. ะขะพะถ ะฒั–ะฝ ั–ะณะฝะพั€ัƒะฒะฐั‚ะธะผะต ะฒัะต ะฒ ะบะฐั‚ะฐะปะพะทั– `.venv`. + +ะฆั ะบะพะผะฐะฝะดะฐ ัั‚ะฒะพั€ะธั‚ัŒ ั„ะฐะนะป `.gitignore` ั–ะท ะฒะผั–ัั‚ะพะผ: + +```gitignore +* +``` + +/// + +## ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะฟะฐะบะตั‚ะธ { #install-packages } + +ะŸั–ัะปั ะฐะบั‚ะธะฒะฐั†ั–ั— ัะตั€ะตะดะพะฒะธั‰ะฐ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฒ ะฝัŒะพะณะพ ะฟะฐะบะตั‚ะธ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ ะพะฑั–ั‚ัŒ ั†ะต ะพะดะธะฝ ั€ะฐะท ะฟั–ะด ั‡ะฐั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฐะฑะพ ะพะฝะพะฒะปะตะฝะฝั ะฟะฐะบะตั‚ั–ะฒ, ะฟะพั‚ั€ั–ะฑะฝะธั… ะฒะฐัˆะพะผัƒ ะฟั€ะพั”ะบั‚ัƒ. + +ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะพะฝะพะฒะธั‚ะธ ะฒะตั€ัั–ัŽ ะฐะฑะพ ะดะพะดะฐั‚ะธ ะฝะพะฒะธะน ะฟะฐะบะตั‚, ะฒะธ ะทั€ะพะฑะธั‚ะต ั†ะต ะทะฝะพะฒัƒ. + +/// + +### ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะฟะฐะบะตั‚ะธ ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ { #install-packages-directly } + +ะฏะบั‰ะพ ะฒะธ ะฟะพัะฟั–ัˆะฐั”ั‚ะต ั‚ะฐ ะฝะต ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั„ะฐะนะป ะดะปั ะพะณะพะปะพัˆะตะฝะฝั ะฒะธะผะพะณ ะฒะฐัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ ะดะพ ะฟะฐะบะตั‚ั–ะฒ, ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ ั—ั… ะฑะตะทะฟะพัะตั€ะตะดะฝัŒะพ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ”ัƒะถะต ะดะพะฑั€ะฐ ั–ะดะตั - ะทะฐะฟะธัะฐั‚ะธ ะฟะฐะบะตั‚ะธ ั‚ะฐ ะฒะตั€ัั–ั—, ะฟะพั‚ั€ั–ะฑะฝั– ะฒะฐัˆั–ะน ะฟั€ะพะณั€ะฐะผั–, ัƒ ั„ะฐะนะป (ะฝะฐะฟั€ะธะบะปะฐะด, `requirements.txt` ะฐะฑะพ `pyproject.toml`). + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” `uv`: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### ะ’ัั‚ะฐะฝะพะฒั–ั‚ัŒ ะท `requirements.txt` { #install-from-requirements-txt } + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” `requirements.txt`, ะฒะธ ะผะพะถะตั‚ะต ะฒะธะบะพั€ะธัั‚ะฐั‚ะธ ะนะพะณะพ ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฟะตั€ะตะปั–ั‡ะตะฝะธั… ั‚ะฐะผ ะฟะฐะบะตั‚ั–ะฒ. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +ะฏะบั‰ะพ ัƒ ะฒะฐั ั” `uv`: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +`requirements.txt` ั–ะท ะดะตัะบะธะผะธ ะฟะฐะบะตั‚ะฐะผะธ ะผะพะถะต ะฒะธะณะปัะดะฐั‚ะธ ั‚ะฐะบ: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## ะ—ะฐะฟัƒัั‚ั–ั‚ัŒ ะฒะฐัˆัƒ ะฟั€ะพะณั€ะฐะผัƒ { #run-your-program } + +ะŸั–ัะปั ะฐะบั‚ะธะฒะฐั†ั–ั— ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆัƒ ะฟั€ะพะณั€ะฐะผัƒ, ั– ะฒะพะฝะฐ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต Python ั–ะท ะฒะฐัˆะพะณะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะท ะฟะฐะบะตั‚ะฐะผะธ, ัะบั– ะฒะธ ั‚ะฐะผ ะฒัั‚ะฐะฝะพะฒะธะปะธ. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## ะะฐะปะฐัˆั‚ัƒะนั‚ะต ะฒะฐัˆ ั€ะตะดะฐะบั‚ะพั€ { #configure-your-editor } + +ะ™ะผะพะฒั–ั€ะฝะพ, ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ั€ะตะดะฐะบั‚ะพั€ ะบะพะดัƒ, ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ะฒะธ ะฝะฐะปะฐัˆั‚ัƒะฒะฐะปะธ ะนะพะณะพ ะฝะฐ ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ั‚ะพะณะพ ัะฐะผะพะณะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ, ัะบะต ะฒะธ ัั‚ะฒะพั€ะธะปะธ (ัˆะฒะธะดัˆะต ะทะฐ ะฒัะต, ะฒั–ะฝ ะฒะธะทะฝะฐั‡ะธั‚ัŒ ะนะพะณะพ ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ), ั‰ะพะฑ ะพั‚ั€ะธะผัƒะฒะฐั‚ะธ ะฐะฒั‚ะพะดะพะฟะพะฒะฝะตะฝะฝั ั‚ะฐ ะฟั–ะดัะฒั–ั‡ัƒะฒะฐะฝะฝั ะฟะพะผะธะปะพะบ. + +ะะฐะฟั€ะธะบะปะฐะด: + +* VS Code +* PyCharm + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ—ะฐะทะฒะธั‡ะฐะน ั†ะต ะฟะพั‚ั€ั–ะฑะฝะพ ั€ะพะฑะธั‚ะธ ะปะธัˆะต ะพะดะธะฝ ั€ะฐะท, ะบะพะปะธ ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต. + +/// + +## ะ”ะตะฐะบั‚ะธะฒัƒะนั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต { #deactivate-the-virtual-environment } + +ะšะพะปะธ ะฒะธ ะทะฐะฒะตั€ัˆะธะปะธ ั€ะพะฑะพั‚ัƒ ะฝะฐะด ะฟั€ะพั”ะบั‚ะพะผ, ะฒะธ ะผะพะถะตั‚ะต ะดะตะฐะบั‚ะธะฒัƒะฒะฐั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต. + +
+ +```console +$ deactivate +``` + +
+ +ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะบะพะปะธ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต `python`, ะฒั–ะฝ ะฝะต ะฝะฐะผะฐะณะฐั‚ะธะผะตั‚ัŒัั ะทะฐะฟัƒัะบะฐั‚ะธัั ะท ั‚ะพะณะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะท ัƒัั‚ะฐะฝะพะฒะปะตะฝะธะผะธ ั‚ะฐะผ ะฟะฐะบะตั‚ะฐะผะธ. + +## ะ“ะพั‚ะพะฒั– ะดะพ ั€ะพะฑะพั‚ะธ { #ready-to-work } + +ะขะตะฟะตั€ ะฒะธ ะณะพั‚ะพะฒั– ะฟะพั‡ะฐั‚ะธ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐะด ะฒะฐัˆะธะผ ะฟั€ะพั”ะบั‚ะพะผ. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฅะพั‡ะตั‚ะต ะทั€ะพะทัƒะผั–ั‚ะธ, ั‰ะพ ั†ะต ะฒัะต ะฑัƒะปะพ ะฒะธั‰ะต? + +ะŸั€ะพะดะพะฒะถัƒะนั‚ะต ั‡ะธั‚ะฐั‚ะธ. ๐Ÿ‘‡๐Ÿค“ + +/// + +## ะะฐะฒั–ั‰ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ { #why-virtual-environments } + +ะฉะพะฑ ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะท FastAPI, ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ Python. + +ะŸั–ัะปั ั†ัŒะพะณะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะธั‚ะธ FastAPI ั‚ะฐ ั–ะฝัˆั– ะฟะฐะบะตั‚ะธ, ัะบั– ะฒะธ ั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ. + +ะ”ะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฟะฐะบะตั‚ั–ะฒ ะทะฐะทะฒะธั‡ะฐะน ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ ะบะพะผะฐะฝะดัƒ `pip`, ั‰ะพ ะฟะพัั‚ะฐั‡ะฐั”ั‚ัŒัั ะท Python (ะฐะฑะพ ัั…ะพะถั– ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ). + +ะžะดะฝะฐะบ, ัะบั‰ะพ ะฒะธ ะฟั€ะพัั‚ะพ ะบะพั€ะธัั‚ัƒะฒะฐั‚ะธะผะตั‚ะตัั `pip` ะฝะฐะฟั€ัะผัƒ, ะฟะฐะบะตั‚ะธ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธะผัƒั‚ัŒัั ัƒ ะฒะฐัˆะต ะณะปะพะฑะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต Python (ะณะปะพะฑะฐะปัŒะฝัƒ ั–ะฝัั‚ะฐะปัั†ั–ัŽ Python). + +### ะŸั€ะพะฑะปะตะผะฐ { #the-problem } + +ะขะพ ะฒ ั‡ะพะผัƒ ะถ ะฟั€ะพะฑะปะตะผะฐ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฟะฐะบะตั‚ั–ะฒ ัƒ ะณะปะพะฑะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต Python? + +ะ— ั‡ะฐัะพะผ ะฒะธ, ะฒั–ั€ะพะณั–ะดะฝะพ, ะฟะธัะฐั‚ะธะผะตั‚ะต ะฑะฐะณะฐั‚ะพ ั€ั–ะทะฝะธั… ะฟั€ะพะณั€ะฐะผ, ัะบั– ะทะฐะปะตะถะฐั‚ัŒ ะฒั–ะด ั€ั–ะทะฝะธั… ะฟะฐะบะตั‚ั–ะฒ. ะ† ะดะตัะบั– ะท ั†ะธั… ะฒะฐัˆะธั… ะฟั€ะพั”ะบั‚ั–ะฒ ะทะฐะปะตะถะฐั‚ะธะผัƒั‚ัŒ ะฒั–ะด ั€ั–ะทะฝะธั… ะฒะตั€ัั–ะน ะพะดะฝะพะณะพ ะน ั‚ะพะณะพ ะถ ะฟะฐะบะตั‚ะฐ. ๐Ÿ˜ฑ + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะผะพะถะตั‚ะต ัั‚ะฒะพั€ะธั‚ะธ ะฟั€ะพั”ะบั‚ ั–ะท ะฝะฐะทะฒะพัŽ `philosophers-stone`, ั†ั ะฟั€ะพะณั€ะฐะผะฐ ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด ั–ะฝัˆะพะณะพ ะฟะฐะบะตั‚ะฐ ะท ะฝะฐะทะฒะพัŽ `harry`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะฒะตั€ัั–ัŽ `1`. ะขะพะถ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `harry`. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +ะŸะพั‚ั–ะผ, ั‚ั€ะพั…ะธ ะทะณะพะดะพะผ, ะฒะธ ัั‚ะฒะพั€ัŽั”ั‚ะต ั–ะฝัˆะธะน ะฟั€ะพั”ะบั‚ ั–ะท ะฝะฐะทะฒะพัŽ `prisoner-of-azkaban`, ั– ั†ะตะน ะฟั€ะพั”ะบั‚ ั‚ะฐะบะพะถ ะทะฐะปะตะถะธั‚ัŒ ะฒั–ะด `harry`, ะฐะปะต ะนะพะผัƒ ะฟะพั‚ั€ั–ะฑะฝะฐ ะฒะตั€ัั–ั `harry` `3`. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +ะะปะต ั‚ะตะฟะตั€ ะฟั€ะพะฑะปะตะผะฐ ะฒ ั‚ะพะผัƒ, ั‰ะพ ัะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะฟะฐะบะตั‚ะธ ะณะปะพะฑะฐะปัŒะฝะพ (ัƒ ะณะปะพะฑะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต), ะฐ ะฝะต ัƒ ะปะพะบะฐะปัŒะฝะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฒะฐะผ ะดะพะฒะตะดะตั‚ัŒัั ะฒะธะฑะธั€ะฐั‚ะธ, ัะบัƒ ะฒะตั€ัั–ัŽ `harry` ะฒัั‚ะฐะฝะพะฒะธั‚ะธ. + +ะฏะบั‰ะพ ะฒะธ ั…ะพั‡ะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ `philosophers-stone`, ะฒะฐะผ ัะฟะพั‡ะฐั‚ะบัƒ ะฟะพั‚ั€ั–ะฑะฝะพ ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `harry` ะฒะตั€ัั–ั— `1`, ะฝะฐะฟั€ะธะบะปะฐะด, ั‚ะฐะบ: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +ะฃ ะฟั–ะดััƒะผะบัƒ ัƒ ะฒะฐั ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ `harry` ะฒะตั€ัั–ั— `1` ัƒ ะณะปะพะฑะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั– Python. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +ะะปะต ัะบั‰ะพ ะฒะธ ะทะฐั…ะพั‡ะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ `prisoner-of-azkaban`, ะฒะฐะผ ะดะพะฒะตะดะตั‚ัŒัั ะฒะธะดะฐะปะธั‚ะธ `harry` ะฒะตั€ัั–ั— `1` ั– ะฒัั‚ะฐะฝะพะฒะธั‚ะธ `harry` ะฒะตั€ัั–ั— `3` (ะฐะฑะพ ะฟั€ะพัั‚ะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั ะฒะตั€ัั–ั— `3` ะฐะฒั‚ะพะผะฐั‚ะธั‡ะฝะพ ะฒะธะดะฐะปะธั‚ัŒ ะฒะตั€ัั–ัŽ `1`). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +ะฃ ะฟั–ะดััƒะผะบัƒ ัƒ ะฒะฐั ะฑัƒะดะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ `harry` ะฒะตั€ัั–ั— `3` ัƒ ะณะปะพะฑะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั– Python. + +ะ ัะบั‰ะพ ะฒะธ ะทะฝะพะฒัƒ ัะฟั€ะพะฑัƒั”ั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ `philosophers-stone`, ั” ัˆะฐะฝั, ั‰ะพ ะฒั–ะฝ ะฝะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต, ั‚ะพะผัƒ ั‰ะพ ะนะพะผัƒ ะฟะพั‚ั€ั–ะฑะตะฝ `harry` ะฒะตั€ัั–ั— `1`. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|โ›”๏ธ| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | ะŸะพั€ะฐะดะฐ + +ะฃ ะฟะฐะบะตั‚ะฐั… Python ะดัƒะถะต ะฟะพัˆะธั€ะตะฝะฐ ะฟั€ะฐะบั‚ะธะบะฐ ะฝะฐะผะฐะณะฐั‚ะธัั ัะบะฝะฐะนะบั€ะฐั‰ะต ัƒะฝะธะบะฐั‚ะธ ะฝะตััƒะผั–ัะฝะธั… ะทะผั–ะฝ ัƒ ะฝะพะฒะธั… ะฒะตั€ัั–ัั…, ะฐะปะต ะบั€ะฐั‰ะต ะฟั–ะดัั‚ั€ะฐั…ัƒะฒะฐั‚ะธัั ั‚ะฐ ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฝะพะฒั–ัˆั– ะฒะตั€ัั–ั— ัะฒั–ะดะพะผะพ ั– ั‚ะพะดั–, ะบะพะปะธ ะฒะธ ะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ั‚ะตัั‚ะธ, ั‰ะพะฑ ะฟะตั€ะตะฒั–ั€ะธั‚ะธ, ั‰ะพ ะฒัะต ะฟั€ะฐั†ัŽั” ะบะพั€ะตะบั‚ะฝะพ. + +/// + +ะขะตะฟะตั€ ัƒัะฒั–ั‚ัŒ ั‚ะต ัะฐะผะต ะท ะฑะฐะณะฐั‚ัŒะผะฐ ั–ะฝัˆะธะผะธ ะฟะฐะบะตั‚ะฐะผะธ, ะฒั–ะด ัะบะธั… ะทะฐะปะตะถะฐั‚ัŒ ัƒัั– ะฒะฐัˆั– ะฟั€ะพั”ะบั‚ะธ. ะฆะต ะดัƒะถะต ัะบะปะฐะดะฝะพ ะบะตั€ัƒะฒะฐั‚ะธ. ะ† ะฒะธ, ั–ะผะพะฒั–ั€ะฝะพ, ะทะฐะฟัƒัะบะฐั‚ะธะผะตั‚ะต ะดะตัะบั– ะฟั€ะพั”ะบั‚ะธ ะท ะดะตัะบะธะผะธ ะฝะตััƒะผั–ัะฝะธะผะธ ะฒะตั€ัั–ัะผะธ ะฟะฐะบะตั‚ั–ะฒ ั– ะฝะต ั€ะพะทัƒะผั–ั‚ะธะผะตั‚ะต, ั‡ะพะผัƒ ั‰ะพััŒ ะฝะต ะฟั€ะฐั†ัŽั”. + +ะขะฐะบะพะถ, ะทะฐะปะตะถะฝะพ ะฒั–ะด ะฒะฐัˆะพั— ะพะฟะตั€ะฐั†ั–ะนะฝะพั— ัะธัั‚ะตะผะธ (ะฝะฐะฟั€., Linux, Windows, macOS), ัƒ ะฝั–ะน ะผะพะถะต ะฑัƒั‚ะธ ะฒะถะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะธะน Python. ะ† ะฒ ั‚ะฐะบะพะผัƒ ั€ะฐะทั–, ั–ะผะพะฒั–ั€ะฝะพ, ัƒะถะต ะฑัƒะดัƒั‚ัŒ ะฟะพะฟะตั€ะตะดะฝัŒะพ ะฒัั‚ะฐะฝะพะฒะปะตะฝั– ะดะตัะบั– ะฟะฐะบะตั‚ะธ ะท ะฟะตะฒะฝะธะผะธ ะฒะตั€ัั–ัะผะธ, ะฟะพั‚ั€ั–ะฑะฝะธะผะธ ะฒะฐัˆั–ะน ัะธัั‚ะตะผั–. ะฏะบั‰ะพ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต ะฟะฐะบะตั‚ะธ ะฒ ะณะปะพะฑะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต Python, ะฒะธ ะผะพะถะตั‚ะต ะทะปะฐะผะฐั‚ะธ ะดะตัะบั– ะฟั€ะพะณั€ะฐะผะธ, ั‰ะพ ะฟะพัั‚ะฐั‡ะฐัŽั‚ัŒัั ะท ะฒะฐัˆะพัŽ ะพะฟะตั€ะฐั†ั–ะนะฝะพัŽ ัะธัั‚ะตะผะพัŽ. + +## ะ”ะต ะฒัั‚ะฐะฝะพะฒะปัŽัŽั‚ัŒัั ะฟะฐะบะตั‚ะธ { #where-are-packages-installed } + +ะšะพะปะธ ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต Python, ะฒั–ะฝ ัั‚ะฒะพั€ัŽั” ะฝะฐ ะฒะฐัˆะพะผัƒ ะบะพะผะฟ'ัŽั‚ะตั€ั– ะบั–ะปัŒะบะฐ ะบะฐั‚ะฐะปะพะณั–ะฒ ั–ะท ะดะตัะบะธะผะธ ั„ะฐะนะปะฐะผะธ. + +ะ”ะตัะบั– ะท ั†ะธั… ะบะฐั‚ะฐะปะพะณั–ะฒ ะฒั–ะดะฟะพะฒั–ะดะฐัŽั‚ัŒ ะทะฐ ะทะฑะตั€ั–ะณะฐะฝะฝั ะฒัั–ั… ะฟะฐะบะตั‚ั–ะฒ, ัะบั– ะฒะธ ะฒัั‚ะฐะฝะพะฒะปัŽั”ั‚ะต. + +ะšะพะปะธ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต: + +
+ +```console +// ะะต ะทะฐะฟัƒัะบะฐะนั‚ะต ั†ะต ะทะฐั€ะฐะท, ั†ะต ะปะธัˆะต ะฟั€ะธะบะปะฐะด ๐Ÿค“ +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +ะฆะต ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ัŒ ัั‚ะธัะฝะตะฝะธะน ั„ะฐะนะป ะท ะบะพะดะพะผ FastAPI, ะทะฐะทะฒะธั‡ะฐะน ั–ะท PyPI. + +ะขะฐะบะพะถ ะฑัƒะดัƒั‚ัŒ ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ั„ะฐะนะปะธ ะดะปั ั–ะฝัˆะธั… ะฟะฐะบะตั‚ั–ะฒ, ะฒั–ะด ัะบะธั… ะทะฐะปะตะถะธั‚ัŒ FastAPI. + +ะŸะพั‚ั–ะผ ัƒัะต ั†ะต ะฑัƒะดะต ั€ะพะทะฟะฐะบะพะฒะฐะฝะพ ั‚ะฐ ะฟะพะบะปะฐะดะตะฝะพ ะฒ ะบะฐั‚ะฐะปะพะณ ะฝะฐ ะฒะฐัˆะพะผัƒ ะบะพะผะฟ'ัŽั‚ะตั€ั–. + +ะขะธะฟะพะฒะพ ั†ั– ะทะฐะฒะฐะฝั‚ะฐะถะตะฝั– ั‚ะฐ ั€ะพะทะฟะฐะบะพะฒะฐะฝั– ั„ะฐะนะปะธ ะฑัƒะดัƒั‚ัŒ ะฟะพะบะปะฐะดะตะฝั– ะฒ ะบะฐั‚ะฐะปะพะณ, ั‰ะพ ะฟะพัั‚ะฐั‡ะฐั”ั‚ัŒัั ะท ะฒะฐัˆะพัŽ ั–ะฝัั‚ะฐะปัั†ั–ั”ัŽ Python, ั†ะต ะณะปะพะฑะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต. + +## ะฉะพ ั‚ะฐะบะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ { #what-are-virtual-environments } + +ะ ั–ัˆะตะฝะฝัะผ ะฟั€ะพะฑะปะตะผะธ ะท ะฝะฐัะฒะฝั–ัั‚ัŽ ะฒัั–ั… ะฟะฐะบะตั‚ั–ะฒ ัƒ ะณะปะพะฑะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั– ั” ะฒะธะบะพั€ะธัั‚ะฐะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะดะปั ะบะพะถะฝะพะณะพ ะฟั€ะพั”ะบั‚ัƒ, ะฝะฐะด ัะบะธะผ ะฒะธ ะฟั€ะฐั†ัŽั”ั‚ะต. + +ะ’ั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต - ั†ะต ะบะฐั‚ะฐะปะพะณ, ะดัƒะถะต ัั…ะพะถะธะน ะฝะฐ ะณะปะพะฑะฐะปัŒะฝะธะน, ัƒ ัะบะพะผัƒ ะฒะธ ะผะพะถะตั‚ะต ะฒัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฟะฐะบะตั‚ะธ ะดะปั ะบะพะฝะบั€ะตั‚ะฝะพะณะพ ะฟั€ะพั”ะบั‚ัƒ. + +ะขะฐะบะธะผ ั‡ะธะฝะพะผ ะบะพะถะตะฝ ะฟั€ะพั”ะบั‚ ะผะฐั‚ะธะผะต ะฒะปะฐัะฝะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต (ะบะฐั‚ะฐะปะพะณ `.venv`) ั–ะท ะฒะปะฐัะฝะธะผะธ ะฟะฐะบะตั‚ะฐะผะธ. + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## ะฉะพ ะพะทะฝะฐั‡ะฐั” ะฐะบั‚ะธะฒะฐั†ั–ั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ { #what-does-activating-a-virtual-environment-mean } + +ะšะพะปะธ ะฒะธ ะฐะบั‚ะธะฒัƒั”ั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฝะฐะฟั€ะธะบะปะฐะด ั‚ะฐะบ: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +ะะฑะพ ัะบั‰ะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต Bash ะดะปั Windows (ะฝะฐะฟั€., Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +ะฆั ะบะพะผะฐะฝะดะฐ ัั‚ะฒะพั€ะธั‚ัŒ ะฐะฑะพ ะทะผั–ะฝะธั‚ัŒ ะดะตัะบั– [ะ—ะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั](environment-variables.md){.internal-link target=_blank}, ัะบั– ะฑัƒะดัƒั‚ัŒ ะดะพัั‚ัƒะฟะฝั– ะดะปั ะฝะฐัั‚ัƒะฟะฝะธั… ะบะพะผะฐะฝะด. + +ะžะดะฝั–ั”ัŽ ะท ั†ะธั… ะทะผั–ะฝะฝะธั… ั” ะทะผั–ะฝะฝะฐ `PATH`. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ’ะธ ะผะพะถะตั‚ะต ะดั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฟั€ะพ ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `PATH` ัƒ ั€ะพะทะดั–ะปั– [ะ—ะผั–ะฝะฝั– ะพั‚ะพั‡ะตะฝะฝั](environment-variables.md#path-environment-variable){.internal-link target=_blank}. + +/// + +ะะบั‚ะธะฒะฐั†ั–ั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะดะพะดะฐั” ะนะพะณะพ ัˆะปัั… `.venv/bin` (ะฝะฐ Linux ั– macOS) ะฐะฑะพ `.venv\Scripts` (ะฝะฐ Windows) ะดะพ ะทะผั–ะฝะฝะพั— ะพั‚ะพั‡ะตะฝะฝั `PATH`. + +ะกะบะฐะถั–ะผะพ, ะดะพ ะฐะบั‚ะธะฒะฐั†ั–ั— ัะตั€ะตะดะพะฒะธั‰ะฐ ะทะผั–ะฝะฝะฐ `PATH` ะฒะธะณะปัะดะฐะปะฐ ั‚ะฐะบ: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ัˆัƒะบะฐั‚ะธะผะต ะฟั€ะพะณั€ะฐะผะธ ะฒ: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ัˆัƒะบะฐั‚ะธะผะต ะฟั€ะพะณั€ะฐะผะธ ะฒ: + +* `C:\Windows\System32` + +//// + +ะŸั–ัะปั ะฐะบั‚ะธะฒะฐั†ั–ั— ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะทะผั–ะฝะฝะฐ `PATH` ะฒะธะณะปัะดะฐั‚ะธะผะต ะฟั€ะธะฑะปะธะทะฝะพ ั‚ะฐะบ: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ั‚ะตะฟะตั€ ัะฟะพั‡ะฐั‚ะบัƒ ัˆัƒะบะฐั‚ะธะผะต ะฟั€ะพะณั€ะฐะผะธ ะฒ: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ัˆัƒะบะฐั‚ะธ ะฒ ั–ะฝัˆะธั… ะบะฐั‚ะฐะปะพะณะฐั…. + +ะขะพะถ ะบะพะปะธ ะฒะธ ะฒะฒะตะดะตั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ัะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ Python ัƒ + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +ั– ะฒะธะบะพั€ะธัั‚ะฐั” ัะฐะผะต ั—ั—. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ัะธัั‚ะตะผะฐ ั‚ะตะฟะตั€ ัะฟะพั‡ะฐั‚ะบัƒ ัˆัƒะบะฐั‚ะธะผะต ะฟั€ะพะณั€ะฐะผะธ ะฒ: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +ะฟะตั€ะตะด ั‚ะธะผ, ัะบ ัˆัƒะบะฐั‚ะธ ะฒ ั–ะฝัˆะธั… ะบะฐั‚ะฐะปะพะณะฐั…. + +ะขะพะถ ะบะพะปะธ ะฒะธ ะฒะฒะตะดะตั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ัะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะฟั€ะพะณั€ะฐะผัƒ Python ัƒ + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +ั– ะฒะธะบะพั€ะธัั‚ะฐั” ัะฐะผะต ั—ั—. + +//// + +ะ’ะฐะถะปะธะฒะฐ ะดะตั‚ะฐะปัŒ: ัˆะปัั… ะดะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะฑัƒะดะต ะดะพะดะฐะฝะพ ะฝะฐ ะฟะพั‡ะฐั‚ะพะบ ะทะผั–ะฝะฝะพั— `PATH`. ะกะธัั‚ะตะผะฐ ะทะฝะฐะนะดะต ะนะพะณะพ ั€ะฐะฝั–ัˆะต ะทะฐ ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน ะดะพัั‚ัƒะฟะฝะธะน Python. ะขะฐะบะธะผ ั‡ะธะฝะพะผ, ะบะพะปะธ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต `python`, ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั ัะฐะผะต Python ั–ะท ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ, ะฐ ะฝะต ะฑัƒะดัŒ-ัะบะธะน ั–ะฝัˆะธะน `python` (ะฝะฐะฟั€ะธะบะปะฐะด, ะท ะณะปะพะฑะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ). + +ะะบั‚ะธะฒะฐั†ั–ั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ั‚ะฐะบะพะถ ะทะผั–ะฝัŽั” ั‰ะต ะบั–ะปัŒะบะฐ ั€ะตั‡ะตะน, ะฐะปะต ั†ะต ะพะดะฝะฐ ะท ะฝะฐะนะฒะฐะถะปะธะฒั–ัˆะธั…. + +## ะŸะตั€ะตะฒั–ั€ะบะฐ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ { #checking-a-virtual-environment } + +ะšะพะปะธ ะฒะธ ะฟะตั€ะตะฒั–ั€ัั”ั‚ะต, ั‡ะธ ะฐะบั‚ะธะฒะฝะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฝะฐะฟั€ะธะบะปะฐะด ั‚ะฐะบ: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +ะฆะต ะพะทะฝะฐั‡ะฐั”, ั‰ะพ ะฟั€ะพะณั€ะฐะผะฐ `python`, ัะบะฐ ะฑัƒะดะต ะฒะธะบะพั€ะธัั‚ะฐะฝะฐ, ะทะฝะฐั…ะพะดะธั‚ัŒัั ัƒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั–. + +ะะฐ Linux ั– macOS ะฒะธะบะพั€ะธัั‚ะพะฒัƒัŽั‚ัŒ `which`, ะฐ ะฒ Windows PowerShell - `Get-Command`. + +ะŸั€ะธะฝั†ะธะฟ ั€ะพะฑะพั‚ะธ ั†ั–ั”ั— ะบะพะผะฐะฝะดะธ ะฒ ั‚ะพะผัƒ, ั‰ะพ ะฒะพะฝะฐ ะฟะตั€ะตะฒั–ั€ัั” ะทะผั–ะฝะฝัƒ ะพั‚ะพั‡ะตะฝะฝั `PATH`, ะฟั€ะพั…ะพะดัั‡ะธ ะฟะพ ะบะพะถะฝะพะผัƒ ัˆะปัั…ัƒ ะฟะพ ะฟะพั€ัะดะบัƒ, ัˆัƒะบะฐัŽั‡ะธ ะฟั€ะพะณั€ะฐะผัƒ ะท ะฝะฐะทะฒะพัŽ `python`. ะฉะพะนะฝะพ ะฒะพะฝะฐ ั—ั— ะทะฝะฐะนะดะต, ะฒะพะฝะฐ ะฟะพะบะฐะถะต ะฒะฐะผ ัˆะปัั… ะดะพ ั†ั–ั”ั— ะฟั€ะพะณั€ะฐะผะธ. + +ะะฐะนะฒะฐะถะปะธะฒั–ัˆะต, ั‰ะพ ะบะพะปะธ ะฒะธ ะฒะธะบะปะธะบะฐั”ั‚ะต `python`, ั†ะต ั€ั–ะฒะฝะพ ั‚ะพะน ยซ`python`ยป, ัะบะธะน ะฑัƒะดะต ะฒะธะบะพะฝะฐะฝะธะน. + +ะžั‚ะถะต, ะฒะธ ะผะพะถะตั‚ะต ะฟั–ะดั‚ะฒะตั€ะดะธั‚ะธ, ั‡ะธ ะฟะตั€ะตะฑัƒะฒะฐั”ั‚ะต ะฒ ะฟั€ะฐะฒะธะปัŒะฝะพะผัƒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั–. + +/// tip | ะŸะพั€ะฐะดะฐ + +ะ›ะตะณะบะพ ะฐะบั‚ะธะฒัƒะฒะฐั‚ะธ ะพะดะฝะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะพั‚ั€ะธะผะฐั‚ะธ ะพะดะธะฝ Python, ะฐ ะฟะพั‚ั–ะผ ะฟะตั€ะตะนั‚ะธ ะดะพ ั–ะฝัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ. + +ะ† ะดั€ัƒะณะธะน ะฟั€ะพั”ะบั‚ ะฝะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธะผะต, ะฑะพ ะฒะธ ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ะต ะฝะตะบะพั€ะตะบั‚ะฝะธะน Python ะท ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ั–ะฝัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ. + +ะšะพั€ะธัะฝะพ ะฒะผั–ั‚ะธ ะฟะตั€ะตะฒั–ั€ัั‚ะธ, ัะบะธะน ัะฐะผะต `python` ะฒะธะบะพั€ะธัั‚ะพะฒัƒั”ั‚ัŒัั. ๐Ÿค“ + +/// + +## ะะฐะฒั–ั‰ะพ ะดะตะฐะบั‚ะธะฒัƒะฒะฐั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต { #why-deactivate-a-virtual-environment } + +ะะฐะฟั€ะธะบะปะฐะด, ะฒะธ ะฟั€ะฐั†ัŽั”ั‚ะต ะฝะฐะด ะฟั€ะพั”ะบั‚ะพะผ `philosophers-stone`, ะฐะบั‚ะธะฒัƒะฒะฐะปะธ ะนะพะณะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต, ะฒัั‚ะฐะฝะพะฒะธะปะธ ะฟะฐะบะตั‚ะธ ั‚ะฐ ะฟั€ะฐั†ัŽั”ั‚ะต ะท ั†ะธะผ ัะตั€ะตะดะพะฒะธั‰ะตะผ. + +ะ ะฟะพั‚ั–ะผ ะฒะธ ั…ะพั‡ะตั‚ะต ะฟั€ะฐั†ัŽะฒะฐั‚ะธ ะฝะฐะด ั–ะฝัˆะธะผ ะฟั€ะพั”ะบั‚ะพะผ `prisoner-of-azkaban`. + +ะ’ะธ ะฟะตั€ะตั…ะพะดะธั‚ะต ะดะพ ั†ัŒะพะณะพ ะฟั€ะพั”ะบั‚ัƒ: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +ะฏะบั‰ะพ ะฒะธ ะฝะต ะดะตะฐะบั‚ะธะฒัƒั”ั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะดะปั `philosophers-stone`, ะบะพะปะธ ะฒะธ ะทะฐะฟัƒัั‚ะธั‚ะต `python` ัƒ ั‚ะตั€ะผั–ะฝะฐะปั–, ะฒั–ะฝ ัะฟั€ะพะฑัƒั” ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ Python ั–ะท `philosophers-stone`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// ะŸะพะผะธะปะบะฐ ั–ะผะฟะพั€ั‚ัƒ sirius, ะนะพะณะพ ะฝะต ะฒัั‚ะฐะฝะพะฒะปะตะฝะพ ๐Ÿ˜ฑ +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +ะะปะต ัะบั‰ะพ ะฒะธ ะดะตะฐะบั‚ะธะฒัƒั”ั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ั– ะฐะบั‚ะธะฒัƒั”ั‚ะต ะฝะพะฒะต ะดะปั `prisoner-of-askaban`, ั‚ะพะดั– ะฟั€ะธ ะทะฐะฟัƒัะบัƒ `python` ะฒั–ะฝ ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธะผะต Python ั–ะท ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะณะพ ัะตั€ะตะดะพะฒะธั‰ะฐ ะฒ `prisoner-of-azkaban`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// ะ’ะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะพ ะฑัƒั‚ะธ ะฒ ัั‚ะฐั€ะพะผัƒ ะบะฐั‚ะฐะปะพะทั–, ั‰ะพะฑ ะดะตะฐะบั‚ะธะฒัƒะฒะฐั‚ะธ, ั†ะต ะผะพะถะฝะฐ ะทั€ะพะฑะธั‚ะธ ะฑัƒะดัŒ-ะดะต, ะฝะฐะฒั–ั‚ัŒ ะฟั–ัะปั ะฟะตั€ะตั…ะพะดัƒ ะดะพ ั–ะฝัˆะพะณะพ ะฟั€ะพั”ะบั‚ัƒ ๐Ÿ˜Ž +$ deactivate + +// ะะบั‚ะธะฒัƒะนั‚ะต ะฒั–ั€ั‚ัƒะฐะปัŒะฝะต ัะตั€ะตะดะพะฒะธั‰ะต ะฒ prisoner-of-azkaban/.venv ๐Ÿš€ +$ source .venv/bin/activate + +// ะขะตะฟะตั€, ะบะพะปะธ ะฒะธ ะทะฐะฟัƒัะบะฐั”ั‚ะต python, ะฒั–ะฝ ะทะฝะฐะนะดะต ะฟะฐะบะตั‚ sirius, ะฒัั‚ะฐะฝะพะฒะปะตะฝะธะน ัƒ ั†ัŒะพะผัƒ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะพะผัƒ ัะตั€ะตะดะพะฒะธั‰ั– โœจ +$ python main.py + +I solemnly swear ๐Ÿบ +``` + +
+ +## ะะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ { #alternatives } + +ะฆะต ะฟั€ะพัั‚ะธะน ะฟะพัั–ะฑะฝะธะบ, ั‰ะพะฑ ะฒะธ ัˆะฒะธะดะบะพ ัั‚ะฐั€ั‚ัƒะฒะฐะปะธ ั‚ะฐ ะทั€ะพะทัƒะผั–ะปะธ, ัะบ ัƒัะต ะฟั€ะฐั†ัŽั” ยซะฟั–ะด ะบะฐะฟะพั‚ะพะผยป. + +ะ†ัะฝัƒั” ะฑะฐะณะฐั‚ะพ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒ ะบะตั€ัƒะฒะฐะฝะฝั ะฒั–ั€ั‚ัƒะฐะปัŒะฝะธะผะธ ัะตั€ะตะดะพะฒะธั‰ะฐะผะธ, ะทะฐะปะตะถะฝะพัั‚ัะผะธ ะฟะฐะบะตั‚ั–ะฒ (ะฒะธะผะพะณะฐะผะธ), ะฟั€ะพั”ะบั‚ะฐะผะธ. + +ะšะพะปะธ ะฑัƒะดะตั‚ะต ะณะพั‚ะพะฒั– ะน ะทะฐั…ะพั‡ะตั‚ะต ะฒะธะบะพั€ะธัั‚ะพะฒัƒะฒะฐั‚ะธ ั–ะฝัั‚ั€ัƒะผะตะฝั‚ ะดะปั ะบะตั€ัƒะฒะฐะฝะฝั ะฒัั–ะผ ะฟั€ะพั”ะบั‚ะพะผ, ะทะฐะปะตะถะฝะพัั‚ัะผะธ ะฟะฐะบะตั‚ั–ะฒ, ะฒั–ั€ั‚ัƒะฐะปัŒะฝะธะผะธ ัะตั€ะตะดะพะฒะธั‰ะฐะผะธ ั‚ะพั‰ะพ, ั ั€ะฐะดะถัƒ ัะฟั€ะพะฑัƒะฒะฐั‚ะธ uv. + +`uv` ัƒะผั–ั” ะฑะฐะณะฐั‚ะพ ั‡ะพะณะพ, ะทะพะบั€ะตะผะฐ: + +* ะ’ัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ Python ะดะปั ะฒะฐั, ะฒะบะปัŽั‡ะฝะพ ะท ั€ั–ะทะฝะธะผะธ ะฒะตั€ัั–ัะผะธ +* ะšะตั€ัƒะฒะฐั‚ะธ ะฒั–ั€ั‚ัƒะฐะปัŒะฝะธะผ ัะตั€ะตะดะพะฒะธั‰ะตะผ ะฒะฐัˆะธั… ะฟั€ะพั”ะบั‚ั–ะฒ +* ะ’ัั‚ะฐะฝะพะฒะปัŽะฒะฐั‚ะธ ะฟะฐะบะตั‚ะธ +* ะšะตั€ัƒะฒะฐั‚ะธ ะทะฐะปะตะถะฝะพัั‚ัะผะธ ะฟะฐะบะตั‚ั–ะฒ ั– ะฒะตั€ัั–ัะผะธ ัƒ ะฒะฐัˆะพะผัƒ ะฟั€ะพั”ะบั‚ั– +* ะ“ะฐั€ะฐะฝั‚ัƒะฒะฐั‚ะธ, ั‰ะพ ัƒ ะฒะฐั ั” ั‚ะพั‡ะฝะธะน ะฝะฐะฑั–ั€ ะฟะฐะบะตั‚ั–ะฒ ั– ะฒะตั€ัั–ะน ะดะปั ะฒัั‚ะฐะฝะพะฒะปะตะฝะฝั, ะฒะบะปัŽั‡ะฝะพ ะท ั—ั…ะฝั–ะผะธ ะทะฐะปะตะถะฝะพัั‚ัะผะธ, ั‰ะพะฑ ะฒะธ ะฑัƒะปะธ ะฟะตะฒะฝั–, ั‰ะพ ะทะผะพะถะตั‚ะต ะทะฐะฟัƒัั‚ะธั‚ะธ ะฒะฐัˆ ะฟั€ะพั”ะบั‚ ัƒ ะฟั€ะพะดะฐะบัˆะตะฝั– ั‚ะพั‡ะฝะพ ั‚ะฐะบ ัะฐะผะพ, ัะบ ั– ะฝะฐ ะฒะฐัˆะพะผัƒ ะบะพะผะฟ'ัŽั‚ะตั€ั– ะฟั–ะด ั‡ะฐั ั€ะพะทั€ะพะฑะบะธ - ั†ะต ะฝะฐะทะธะฒะฐั”ั‚ัŒัั ะฑะปะพะบัƒะฒะฐะฝะฝัะผ +* ะ† ะฑะฐะณะฐั‚ะพ ั–ะฝัˆะพะณะพ + +## ะ’ะธัะฝะพะฒะพะบ { #conclusion } + +ะฏะบั‰ะพ ะฒะธ ะฒัะต ั†ะต ะฟั€ะพั‡ะธั‚ะฐะปะธ ะน ะทั€ะพะทัƒะผั–ะปะธ, ั‚ะตะฟะตั€ ะฒะธ ะทะฝะฐั”ั‚ะต ะทะฝะฐั‡ะฝะพ ะฑั–ะปัŒัˆะต ะฟั€ะพ ะฒั–ั€ั‚ัƒะฐะปัŒะฝั– ัะตั€ะตะดะพะฒะธั‰ะฐ, ะฝั–ะถ ะฑะฐะณะฐั‚ะพ ั€ะพะทั€ะพะฑะฝะธะบั–ะฒ. ๐Ÿค“ + +ะ—ะฝะฐะฝะฝั ั†ะธั… ะดะตั‚ะฐะปะตะน, ะฝะฐะนั–ะผะพะฒั–ั€ะฝั–ัˆะต, ัั‚ะฐะฝะต ะฒ ะฟั€ะธะณะพะดั– ะฒ ะผะฐะนะฑัƒั‚ะฝัŒะพะผัƒ, ะบะพะปะธ ะฒะธ ะฝะฐะปะฐะณะพะดะถัƒะฒะฐั‚ะธะผะตั‚ะต ั‰ะพััŒ, ั‰ะพ ะฒะธะณะปัะดะฐั” ัะบะปะฐะดะฝะธะผ, ะฐะปะต ะฒะธ ะทะฝะฐั‚ะธะผะตั‚ะต, ัะบ ัƒัะต ะฟั€ะฐั†ัŽั” ยซะฟั–ะด ะบะฐะฟะพั‚ะพะผยป. ๐Ÿ˜Ž From 82d90c51b4ca557c6f942b6800fba2ff3cc900c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Feb 2026 08:43:37 +0000 Subject: [PATCH 242/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5e1eaf9372..61366bb84f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for uk (add-missing). PR [#14922](https://github.com/fastapi/fastapi/pull/14922) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh-hant (update-all and add-missing). PR [#14921](https://github.com/fastapi/fastapi/pull/14921) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for fr (update-all and add-missing). PR [#14920](https://github.com/fastapi/fastapi/pull/14920) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for de (update-all) . PR [#14910](https://github.com/fastapi/fastapi/pull/14910) by [@YuriiMotov](https://github.com/YuriiMotov). From 01e2e1088cc2bd80a707208234af6f9570e06963 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:57:01 +0100 Subject: [PATCH 243/367] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update-all=20and=20add-missing)=20(#14923)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update all and add missing * ๐ŸŽจ Auto format --------- Co-authored-by: github-actions[bot] --- docs/ko/docs/_llm-test.md | 12 +- docs/ko/docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 8 +- .../ko/docs/advanced/advanced-dependencies.md | 8 +- .../ko/docs/advanced/advanced-python-types.md | 61 ++++++ docs/ko/docs/advanced/async-tests.md | 8 +- docs/ko/docs/advanced/behind-a-proxy.md | 12 +- docs/ko/docs/advanced/custom-response.md | 32 +-- docs/ko/docs/advanced/dataclasses.md | 2 +- docs/ko/docs/advanced/events.md | 12 +- docs/ko/docs/advanced/generate-clients.md | 8 +- docs/ko/docs/advanced/index.md | 2 +- docs/ko/docs/advanced/middleware.md | 8 +- docs/ko/docs/advanced/openapi-callbacks.md | 34 ++-- docs/ko/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 16 +- .../advanced/response-change-status-code.md | 2 +- docs/ko/docs/advanced/response-cookies.md | 4 +- docs/ko/docs/advanced/response-directly.md | 2 +- docs/ko/docs/advanced/response-headers.md | 8 +- .../docs/advanced/security/http-basic-auth.md | 8 +- docs/ko/docs/advanced/settings.md | 24 +-- docs/ko/docs/advanced/sub-applications.md | 6 +- docs/ko/docs/advanced/templates.md | 2 +- docs/ko/docs/advanced/testing-events.md | 4 +- docs/ko/docs/advanced/testing-websockets.md | 4 +- .../docs/advanced/using-request-directly.md | 2 +- docs/ko/docs/advanced/websockets.md | 18 +- docs/ko/docs/advanced/wsgi.md | 2 +- docs/ko/docs/alternatives.md | 8 +- docs/ko/docs/deployment/docker.md | 10 +- docs/ko/docs/deployment/https.md | 4 +- docs/ko/docs/deployment/manually.md | 2 +- docs/ko/docs/deployment/server-workers.md | 12 +- docs/ko/docs/deployment/versions.md | 4 +- docs/ko/docs/environment-variables.md | 34 ++-- docs/ko/docs/features.md | 10 +- .../authentication-error-status-code.md | 4 +- docs/ko/docs/how-to/conditional-openapi.md | 4 +- docs/ko/docs/how-to/configure-swagger-ui.md | 8 +- docs/ko/docs/how-to/custom-docs-ui-assets.md | 16 +- docs/ko/docs/how-to/extending-openapi.md | 10 +- docs/ko/docs/how-to/graphql.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 4 +- .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/ko/docs/index.md | 10 +- docs/ko/docs/project-generation.md | 2 +- docs/ko/docs/python-types.md | 186 ++++-------------- docs/ko/docs/resources/index.md | 2 +- docs/ko/docs/translation-banner.md | 11 ++ docs/ko/docs/tutorial/background-tasks.md | 6 +- docs/ko/docs/tutorial/bigger-applications.md | 52 ++--- docs/ko/docs/tutorial/body-fields.md | 4 +- docs/ko/docs/tutorial/body-multiple-params.md | 7 - docs/ko/docs/tutorial/body-nested-models.md | 4 +- docs/ko/docs/tutorial/body.md | 8 +- docs/ko/docs/tutorial/cookie-param-models.md | 8 +- docs/ko/docs/tutorial/cookie-params.md | 4 +- docs/ko/docs/tutorial/cors.md | 4 +- docs/ko/docs/tutorial/debugging.md | 2 +- .../dependencies/classes-as-dependencies.md | 24 +-- ...pendencies-in-path-operation-decorators.md | 30 +-- .../dependencies/dependencies-with-yield.md | 24 +-- .../dependencies/global-dependencies.md | 5 +- docs/ko/docs/tutorial/dependencies/index.md | 6 +- .../tutorial/dependencies/sub-dependencies.md | 6 +- docs/ko/docs/tutorial/encoder.md | 2 +- docs/ko/docs/tutorial/extra-models.md | 16 +- docs/ko/docs/tutorial/first-steps.md | 22 +-- docs/ko/docs/tutorial/handling-errors.md | 16 +- docs/ko/docs/tutorial/header-param-models.md | 4 +- docs/ko/docs/tutorial/metadata.md | 12 +- docs/ko/docs/tutorial/middleware.md | 8 +- .../tutorial/path-operation-configuration.md | 8 +- .../path-params-numeric-validations.md | 14 +- docs/ko/docs/tutorial/path-params.md | 32 +-- .../tutorial/query-params-str-validations.md | 48 ++--- docs/ko/docs/tutorial/query-params.md | 6 +- docs/ko/docs/tutorial/request-files.md | 14 +- docs/ko/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/ko/docs/tutorial/request-forms.md | 8 +- docs/ko/docs/tutorial/response-model.md | 6 +- docs/ko/docs/tutorial/response-status-code.md | 10 +- docs/ko/docs/tutorial/schema-extra-example.md | 2 +- docs/ko/docs/tutorial/security/first-steps.md | 6 +- .../tutorial/security/get-current-user.md | 2 +- docs/ko/docs/tutorial/security/oauth2-jwt.md | 26 +-- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/ko/docs/tutorial/sql-databases.md | 2 +- docs/ko/docs/tutorial/static-files.md | 2 +- docs/ko/docs/tutorial/testing.md | 12 +- docs/ko/docs/virtual-environments.md | 24 +-- 93 files changed, 548 insertions(+), 620 deletions(-) create mode 100644 docs/ko/docs/advanced/advanced-python-types.md create mode 100644 docs/ko/docs/translation-banner.md diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md index 272af763a5..92bfb83f62 100644 --- a/docs/ko/docs/_llm-test.md +++ b/docs/ko/docs/_llm-test.md @@ -35,7 +35,7 @@ //// tab | ํ…Œ์ŠคํŠธ -์–ด์ œ ์ œ ์นœ๊ตฌ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ผ์Šต๋‹ˆ๋‹ค: "If you spell incorrectly correctly, you have spelled it incorrectly". ์ด์— ์ €๋Š” ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"". +์–ด์ œ ์ œ ์นœ๊ตฌ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ผ์Šต๋‹ˆ๋‹ค: "If you spell incorrectly correctly, you have spelled it incorrectly". ์ด์— ์ €๋Š” ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". /// note | ์ฐธ๊ณ  @@ -256,15 +256,15 @@ works(foo="bar") # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ //// tab | ํ…Œ์ŠคํŠธ -* ๋‹น์‹  -* ๋‹น์‹ ์˜ +* ์—ฌ๋Ÿฌ๋ถ„ +* ์—ฌ๋Ÿฌ๋ถ„์˜ * ์˜ˆ: (e.g.) * ๋“ฑ (etc.) -* `int`๋กœ์„œ์˜ `foo` -* `str`๋กœ์„œ์˜ `bar` -* `list`๋กœ์„œ์˜ `baz` +* `foo`๋กœ์„œ์˜ `int` +* `bar`๋กœ์„œ์˜ `str` +* `baz`๋กœ์„œ์˜ `list` * ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ * ๊ณ ๊ธ‰ ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ diff --git a/docs/ko/docs/advanced/additional-responses.md b/docs/ko/docs/advanced/additional-responses.md index a6f51f5b93..2ed6bc3fcf 100644 --- a/docs/ko/docs/advanced/additional-responses.md +++ b/docs/ko/docs/advanced/additional-responses.md @@ -26,7 +26,7 @@ ์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒํƒœ ์ฝ”๋“œ `404`์™€ Pydantic ๋ชจ๋ธ `Message`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์‘๋‹ต์„ ์„ ์–ธํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *} +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} /// note | ์ฐธ๊ณ  @@ -203,7 +203,7 @@ ๋˜ํ•œ `response_model`์„ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ ์ฝ”๋“œ `200` ์‘๋‹ต์„ ์„ ์–ธํ•˜๋˜, ์ปค์Šคํ…€ `example`์„ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *} +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} ์ด ๋ชจ๋“  ๋‚ด์šฉ์€ OpenAPI์— ๊ฒฐํ•ฉ๋˜์–ด ํฌํ•จ๋˜๊ณ , API ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/advanced/additional-status-codes.md b/docs/ko/docs/advanced/additional-status-codes.md index 64a7eabd5e..e3c898044e 100644 --- a/docs/ko/docs/advanced/additional-status-codes.md +++ b/docs/ko/docs/advanced/additional-status-codes.md @@ -1,14 +1,14 @@ # ์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ { #additional-status-codes } -๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋Š” ์‘๋‹ต์„ `JSONResponse`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, *๊ฒฝ๋กœ ์ž‘์—…(path operation)*์—์„œ ๋ฐ˜ํ™˜ํ•œ ๋‚ด์šฉ์„ ํ•ด๋‹น `JSONResponse` ์•ˆ์— ๋„ฃ์–ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. +๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋Š” ์‘๋‹ต์„ `JSONResponse`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ๋ฐ˜ํ™˜ํ•œ ๋‚ด์šฉ์„ ํ•ด๋‹น `JSONResponse` ์•ˆ์— ๋„ฃ์–ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -๊ธฐ๋ณธ ์ƒํƒœ ์ฝ”๋“œ ๋˜๋Š” *๊ฒฝ๋กœ ์ž‘์—…*์—์„œ ์„ค์ •ํ•œ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +๊ธฐ๋ณธ ์ƒํƒœ ์ฝ”๋“œ ๋˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ์„ค์ •ํ•œ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ## ์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ { #additional-status-codes_1 } ๊ธฐ๋ณธ ์ƒํƒœ ์ฝ”๋“œ์™€ ๋ณ„๋„๋กœ ์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด `JSONResponse`์™€ ๊ฐ™์ด `Response`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š” *๊ฒฝ๋กœ ์ž‘์—…*์ด ์žˆ๊ณ  ์„ฑ๊ณต ์‹œ 200 โ€œOKโ€์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์žˆ๊ณ  ์„ฑ๊ณต ์‹œ 200 โ€œOKโ€์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์„ ํ—ˆ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ญ๋ชฉ์ด ์ด์ „์— ์กด์žฌํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  HTTP ์ƒํƒœ ์ฝ”๋“œ 201 "Created"๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning | ๊ฒฝ๊ณ  +/// warning ์œ„์˜ ์˜ˆ์ œ์ฒ˜๋Ÿผ `Response`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/advanced-dependencies.md b/docs/ko/docs/advanced/advanced-dependencies.md index fe16062586..eb5d35d957 100644 --- a/docs/ko/docs/advanced/advanced-dependencies.md +++ b/docs/ko/docs/advanced/advanced-dependencies.md @@ -18,7 +18,7 @@ Python์—๋Š” ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ "ํ˜ธ์ถœ ๊ฐ€๋Šฅ"ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ์ด๋ฅผ ์œ„ํ•ด `__call__` ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} ์ด ๊ฒฝ์šฐ, **FastAPI**๋Š” ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํ•˜์œ„ ์˜์กด์„ฑ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด `__call__`์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉฐ, ๋‚˜์ค‘์— *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ ์ด๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. @@ -27,7 +27,7 @@ Python์—๋Š” ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ "ํ˜ธ์ถœ ๊ฐ€๋Šฅ"ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ์ด์ œ `__init__`์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ์„ "๋งค๊ฐœ๋ณ€์ˆ˜ํ™”"ํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} ์ด ๊ฒฝ์šฐ, **FastAPI**๋Š” `__init__`์— ์ „ํ˜€ ๊ด€์—ฌํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. @@ -35,7 +35,7 @@ Python์—๋Š” ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ "ํ˜ธ์ถœ ๊ฐ€๋Šฅ"ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด `checker.fixed_content` ์†์„ฑ์— `"bar"`๋ผ๋Š” ๊ฐ’์„ ๋‹ด์•„ ์˜์กด์„ฑ์„ "๋งค๊ฐœ๋ณ€์ˆ˜ํ™”"ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -51,7 +51,7 @@ checker(q="somequery") ...๊ทธ๋ฆฌ๊ณ  ์ด๋•Œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์„ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ์˜์กด์„ฑ ๊ฐ’์œผ๋กœ, `fixed_content_included` ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *} +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} /// tip | ํŒ diff --git a/docs/ko/docs/advanced/advanced-python-types.md b/docs/ko/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000..0bd8aa5433 --- /dev/null +++ b/docs/ko/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# ๊ณ ๊ธ‰ Python ํƒ€์ž… { #advanced-python-types } + +Python ํƒ€์ž…์„ ๋‹ค๋ฃฐ ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์•„์ด๋””์–ด๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. + +## `Union` ๋˜๋Š” `Optional` ์‚ฌ์šฉ { #using-union-or-optional } + +์–ด๋–ค ์ด์œ ๋กœ ์ฝ”๋“œ์—์„œ `|`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์ด ์•„๋‹ˆ๋ผ `response_model=` ๊ฐ™์€ ๊ณณ์ด๋ผ๋ฉด, ํŒŒ์ดํ”„ ๋ฌธ์ž(`|`) ๋Œ€์‹  `typing`์˜ `Union`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค ๊ฐ’์ด `str` ๋˜๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing`์—๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ์Œ์„ ์„ ์–ธํ•˜๋Š” ์ถ•์•ฝํ˜•์œผ๋กœ `Optional`๋„ ์žˆ์Šต๋‹ˆ๋‹ค. + +์•„์ฃผ ๊ฐœ์ธ์ ์ธ ๊ด€์ ์—์„œ์˜ ํŒ์ž…๋‹ˆ๋‹ค: + +- ๐Ÿšจ `Optional[SomeType]` ์‚ฌ์šฉ์€ ํ”ผํ•˜์„ธ์š” +- ๋Œ€์‹  โœจ **`Union[SomeType, None]`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”** โœจ. + +๋‘˜์€ ๋™๋“ฑํ•˜๋ฉฐ ๋‚ด๋ถ€์ ์œผ๋กœ๋„ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹จ์–ด "optional"์€ ๊ฐ’์ด ์„ ํƒ ์‚ฌํ•ญ์ด๋ผ๋Š” ์ธ์ƒ์„ ์ฃผ๋Š” ๋ฐ˜๋ฉด, ์‹ค์ œ ์˜๋ฏธ๋Š” "๊ฐ’์ด `None`์ด ๋  ์ˆ˜ ์žˆ๋‹ค"๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ฐ’์ด ์„ ํƒ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋ผ ์—ฌ์ „ํžˆ ํ•„์ˆ˜์ธ ๊ฒฝ์šฐ์—๋„ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. + +`Union[SomeType, None]`๊ฐ€ ์˜๋ฏธ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ธ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. + +์ด๋Š” ๋‹จ์ง€ ๋‹จ์–ด์™€ ๋ช…์นญ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋‹จ์–ด๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„๊ณผ ํŒ€์›์ด ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜๋Š”์ง€์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ํ•จ์ˆ˜๋ฅผ ๋ณด์„ธ์š”: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +๋งค๊ฐœ๋ณ€์ˆ˜ `name`์€ `Optional[str]`๋กœ ์ •์˜๋˜์–ด ์žˆ์ง€๋งŒ, ์‚ฌ์‹ค ์„ ํƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋งค๊ฐœ๋ณ€์ˆ˜ ์—†์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: + +```Python +say_hi() # ์ด๋Ÿฐ, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜ฑ +``` + +`name` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค(์„ ํƒ์ ์ด ์•„๋‹˜). ๋Œ€์‹ , `name`์—๋Š” `None`์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```Python +say_hi(name=None) # ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. None์€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰ +``` + +์ข‹์€ ์†Œ์‹์€, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ํƒ€์ž…์˜ ํ•ฉ์ง‘ํ•ฉ์„ ์ •์˜ํ•  ๋•Œ ๊ทธ๋ƒฅ `|`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +๊ทธ๋ž˜์„œ ๋ณดํ†ต์€ `Optional`๊ณผ `Union` ๊ฐ™์€ ์ด๋ฆ„์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•˜์ง€ ์•Š์œผ์…”๋„ ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Ž diff --git a/docs/ko/docs/advanced/async-tests.md b/docs/ko/docs/advanced/async-tests.md index 6c85936812..0479ac41d1 100644 --- a/docs/ko/docs/advanced/async-tests.md +++ b/docs/ko/docs/advanced/async-tests.md @@ -32,11 +32,11 @@ `main.py` ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/async_tests/app_a_py39/main.py *} +{* ../../docs_src/async_tests/app_a_py310/main.py *} `test_main.py` ํŒŒ์ผ์—๋Š” `main.py`์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด์ œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/async_tests/app_a_py39/test_main.py *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} ## ์‹คํ–‰ํ•˜๊ธฐ { #run-it } @@ -56,7 +56,7 @@ $ pytest `@pytest.mark.anyio` ๋งˆ์ปค๋Š” pytest์—๊ฒŒ ์ด ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค: -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} /// tip | ํŒ @@ -66,7 +66,7 @@ $ pytest ๊ทธ ๋‹ค์Œ ์•ฑ์œผ๋กœ `AsyncClient`๋ฅผ ๋งŒ๋“ค๊ณ , `await`๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *} +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} ์ด๋Š” ๋‹ค์Œ๊ณผ ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/advanced/behind-a-proxy.md b/docs/ko/docs/advanced/behind-a-proxy.md index 92bddac51a..825592c060 100644 --- a/docs/ko/docs/advanced/behind-a-proxy.md +++ b/docs/ko/docs/advanced/behind-a-proxy.md @@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*" ์˜ˆ๋ฅผ ๋“ค์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `/items/`๋ฅผ ์ •์˜ํ–ˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: -{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} ํด๋ผ์ด์–ธํŠธ๊ฐ€ `/items`๋กœ ์ ‘๊ทผํ•˜๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ `/items/`๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. @@ -115,7 +115,7 @@ sequenceDiagram ์ฝ”๋“œ๋Š” ๋ชจ๋‘ `/app`๋งŒ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ๋„ ๋ง์ž…๋‹ˆ๋‹ค. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} ๊ทธ๋ฆฌ๊ณ  ํ”„๋ก์‹œ๋Š” ์š”์ฒญ์„ ์•ฑ ์„œ๋ฒ„(์•„๋งˆ FastAPI CLI๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” Uvicorn)๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, ๋™์ ์œผ๋กœ **๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ**๋ฅผ **"์ œ๊ฑฐ"**ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—ฌ์ „ํžˆ `/app`์—์„œ ์„œ๋น„์Šค๋œ๋‹ค๊ณ  ๋ฏฟ๊ฒŒ ๋˜๊ณ , ์ฝ”๋“œ ์ „์ฒด๋ฅผ `/api/v1` ์ ‘๋‘์‚ฌ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง‘๋‹ˆ๋‹ค. @@ -193,7 +193,7 @@ ASGI ์‚ฌ์–‘์€ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด `root_path`๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ฐ๋ชจ ๋ชฉ์ ์„ ์œ„ํ•ด ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *} +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} ๊ทธ ๋‹ค์Œ Uvicorn์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ•˜๋ฉด: @@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ๋˜๋Š” `--root-path` ๊ฐ™์€ ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜(๋˜๋Š” ๋™๋“ฑํ•œ ๋ฐฉ๋ฒ•)์„ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, FastAPI ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ `root_path` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *} +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} `FastAPI`์— `root_path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ Uvicorn์ด๋‚˜ Hypercorn์— ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. @@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ์˜ˆ: -{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *} +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} ๋‹ค์Œ๊ณผ ๊ฐ™์€ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: @@ -455,7 +455,7 @@ OpenAPI ์‚ฌ์–‘์—์„œ `servers` ์†์„ฑ์€ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. **FastAPI**๊ฐ€ `root_path`๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ server๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๋ ค๋ฉด, `root_path_in_servers=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} ๊ทธ๋Ÿฌ๋ฉด OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/custom-response.md b/docs/ko/docs/advanced/custom-response.md index 55dc2a4be1..6d54eaf2b1 100644 --- a/docs/ko/docs/advanced/custom-response.md +++ b/docs/ko/docs/advanced/custom-response.md @@ -30,7 +30,7 @@ ํ•˜์ง€๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‚ด์šฉ์ด **JSON์œผ๋กœ ์ง๋ ฌํ™” ๊ฐ€๋Šฅ**ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ๋‚ด์šฉ์„ ์‘๋‹ต ํด๋ž˜์Šค์— ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI๊ฐ€ ๋ฐ˜ํ™˜ ๋‚ด์šฉ์„ `jsonable_encoder`๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•œ ๋’ค ์‘๋‹ต ํด๋ž˜์Šค์— ์ „๋‹ฌํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} /// info | ์ •๋ณด @@ -55,7 +55,7 @@ * `HTMLResponse`๋ฅผ ์ž„ํฌํŠธ ํ•ฉ๋‹ˆ๋‹ค. * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์˜ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ `HTMLResponse`๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | ์ •๋ณด @@ -73,7 +73,7 @@ ์œ„์˜ ์˜ˆ์ œ์™€ ๋™์ผํ•˜๊ฒŒ `HTMLResponse`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *} +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | ๊ฒฝ๊ณ  @@ -97,7 +97,7 @@ ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *} +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} ์ด ์˜ˆ์ œ์—์„œ, `generate_html_response()` ํ•จ์ˆ˜๋Š” HTML์„ `str`๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ์ด๋ฏธ `Response`๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. @@ -136,7 +136,7 @@ FastAPI (์‹ค์ œ๋กœ๋Š” Starlette)๊ฐ€ ์ž๋™์œผ๋กœ Content-Length ํ—ค๋”๋ฅผ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค. ๋˜ํ•œ `media_type`์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ Content-Type ํ—ค๋”๋ฅผ ํฌํ•จํ•˜๋ฉฐ, ํ…์ŠคํŠธ ํƒ€์ž…์˜ ๊ฒฝ์šฐ ๋ฌธ์ž ์ง‘ํ•ฉ์„ ์ถ”๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *} +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } @@ -146,7 +146,7 @@ FastAPI (์‹ค์ œ๋กœ๋Š” Starlette)๊ฐ€ ์ž๋™์œผ๋กœ Content-Length ํ—ค๋”๋ฅผ ํฌํ•จ ํ…์ŠคํŠธ ๋˜๋Š” ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•„ ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} ### `JSONResponse` { #jsonresponse } @@ -180,7 +180,7 @@ FastAPI (์‹ค์ œ๋กœ๋Š” Starlette)๊ฐ€ ์ž๋™์œผ๋กœ Content-Length ํ—ค๋”๋ฅผ ํฌํ•จ /// -{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *} +{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} /// tip | ํŒ @@ -194,14 +194,14 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 `RedirectResponse`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *} +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} --- ๋˜๋Š” `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} ์ด ๊ฒฝ์šฐ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ํ•จ์ˆ˜์—์„œ URL์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -211,13 +211,13 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 `status_code` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *} +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋˜๋Š” ์ผ๋ฐ˜ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ/์ดํ„ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์‘๋‹ต ๋ณธ๋ฌธ์„ ์ŠคํŠธ๋ฆฌ๋ฐ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} #### ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ `StreamingResponse` { #using-streamingresponse-with-file-like-objects } @@ -227,7 +227,7 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 ์ด ๋ฐฉ์‹์€ ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€, ๋น„๋””์˜ค ์ฒ˜๋ฆฌ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *} +{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} 1. ์ด๊ฒƒ์ด ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. `yield` ๋ฌธ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ "์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜"์ž…๋‹ˆ๋‹ค. 2. `with` ๋ธ”๋ก์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ๋‹ซํžˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์‘๋‹ต ์ „์†ก์ด ๋๋‚œ ํ›„ ๋‹ซํž™๋‹ˆ๋‹ค. @@ -256,11 +256,11 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 ํŒŒ์ผ ์‘๋‹ต์—๋Š” ์ ์ ˆํ•œ `Content-Length`, `Last-Modified`, ๋ฐ `ETag` ํ—ค๋”๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *} +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} ๋˜ํ•œ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *} +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} ์ด ๊ฒฝ์šฐ, ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜์—์„œ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -274,7 +274,7 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 `CustomORJSONResponse`๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ `Response.render(content)` ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋‚ด์šฉ์„ `bytes`๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *} +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} ์ด์ œ ๋‹ค์Œ ๋Œ€์‹ : @@ -300,7 +300,7 @@ HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 30 ์•„๋ž˜ ์˜ˆ์ œ์—์„œ **FastAPI**๋Š” ๋ชจ๋“  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ `JSONResponse` ๋Œ€์‹  `ORJSONResponse`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *} +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | ํŒ diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md index 92ad5545b3..0210812b6e 100644 --- a/docs/ko/docs/advanced/dataclasses.md +++ b/docs/ko/docs/advanced/dataclasses.md @@ -64,7 +64,7 @@ dataclass๋Š” ์ž๋™์œผ๋กœ Pydantic dataclass๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. 6. ์—ฌ๊ธฐ์„œ๋Š” dataclasses ๋ฆฌ์ŠคํŠธ์ธ `items`๋ฅผ ํฌํ•จํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. - FastAPI๋Š” ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ serializingํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + FastAPI๋Š” ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 7. ์—ฌ๊ธฐ์„œ `response_model`์€ `Author` dataclasses ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index 35223eaf39..f1dd8397a0 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -30,7 +30,7 @@ `yield`๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ํ•จ์ˆ˜ `lifespan()`์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} ์—ฌ๊ธฐ์„œ๋Š” `yield` ์ด์ „์— (๊ฐ€์งœ) ๋ชจ๋ธ ํ•จ์ˆ˜๋ฅผ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์ด ๋“ค์–ด ์žˆ๋Š” ๋”•์…”๋„ˆ๋ฆฌ์— ๋„ฃ์–ด ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜๋Š” ๋น„์šฉ์ด ํฐ *์‹œ์ž‘* ์ž‘์—…์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด **์š”์ฒญ์„ ๋ฐ›๊ธฐ ์‹œ์ž‘ํ•˜๊ธฐ ์ „**, *์‹œ์ž‘* ๋™์•ˆ์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. @@ -48,7 +48,7 @@ ๋จผ์ € ์ฃผ๋ชฉํ•  ์ ์€ `yield`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” `yield`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜์กด์„ฑ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *} +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„, ์ฆ‰ `yield` ์ด์ „์˜ ์ฝ”๋“œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋˜๊ธฐ **์ „์—** ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. @@ -60,7 +60,7 @@ ์ด๋Š” ํ•จ์ˆ˜๋ฅผ "**๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €**"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *} +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} ํŒŒ์ด์ฌ์—์„œ **์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €**๋Š” `with` ๋ฌธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, `open()`์€ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: @@ -82,7 +82,7 @@ async with lifespan(app): `FastAPI` ์•ฑ์˜ `lifespan` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” **๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €**๋ฅผ ๋ฐ›์œผ๋ฏ€๋กœ, ์ƒˆ `lifespan` ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/events/tutorial003_py39.py hl[22] *} +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} ## ๋Œ€์ฒด ์ด๋ฒคํŠธ(์‚ฌ์šฉ ์ค‘๋‹จ) { #alternative-events-deprecated } @@ -104,7 +104,7 @@ async with lifespan(app): ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด, `"startup"` ์ด๋ฒคํŠธ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/events/tutorial001_py39.py hl[8] *} +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} ์ด ๊ฒฝ์šฐ, `startup` ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋Š” "database"(๊ทธ๋ƒฅ `dict`) ํ•ญ๋ชฉ์„ ์ผ๋ถ€ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. @@ -116,7 +116,7 @@ async with lifespan(app): ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ข…๋ฃŒ๋  ๋•Œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด, `"shutdown"` ์ด๋ฒคํŠธ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/events/tutorial002_py39.py hl[6] *} +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} ์—ฌ๊ธฐ์„œ `shutdown` ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋Š” ํ…์ŠคํŠธ ํ•œ ์ค„ `"Application shutdown"`์„ `log.txt` ํŒŒ์ผ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md index 1def3efe12..3cfbb75784 100644 --- a/docs/ko/docs/advanced/generate-clients.md +++ b/docs/ko/docs/advanced/generate-clients.md @@ -40,7 +40,7 @@ FastAPI๋Š” **OpenAPI 3.1** ์‚ฌ์–‘์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} *path operation*์—์„œ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ์™€ ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์— ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋ธ์„ `Item`, `ResponseMessage` ๋ชจ๋ธ๋กœ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. @@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ์˜ˆ๋ฅผ ๋“ค์–ด **items** ์„น์…˜๊ณผ **users** ์„น์…˜์ด ์žˆ๊ณ , ์ด๋ฅผ ํƒœ๊ทธ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} ### ํƒœ๊ทธ๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-tags } @@ -145,7 +145,7 @@ FastAPI๋Š” ๊ฐ *path operation*์— ๋Œ€ํ•ด **์œ ์ผ ID**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋Š” ๊ทธ ๋‹ค์Œ ์ด ์ปค์Šคํ…€ ํ•จ์ˆ˜๋ฅผ `generate_unique_id_function` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ **FastAPI**์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} ### ์ปค์Šคํ…€ Operation ID๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-custom-operation-ids } @@ -167,7 +167,7 @@ OpenAPI ์ „๋ฐ˜์—์„œ๋Š” operation ID๊ฐ€ **์œ ์ผ**ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ OpenAPI JSON์„ `openapi.json` ํŒŒ์ผ๋กœ ๋‹ค์šด๋กœ๋“œํ•œ ๋’ค, ์•„๋ž˜์™€ ๊ฐ™์€ ์Šคํฌ๋ฆฝํŠธ๋กœ **์ ‘๋‘์‚ฌ ํƒœ๊ทธ๋ฅผ ์ œ๊ฑฐ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/generate_clients/tutorial004_py39.py *} +{* ../../docs_src/generate_clients/tutorial004_py310.py *} //// tab | Node.js diff --git a/docs/ko/docs/advanced/index.md b/docs/ko/docs/advanced/index.md index 78ef5ffece..6212a7279c 100644 --- a/docs/ko/docs/advanced/index.md +++ b/docs/ko/docs/advanced/index.md @@ -1,4 +1,4 @@ -# ์‹ฌํ™” ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ - ๋„์ž…๋ถ€ { #advanced-user-guide } +# ์‹ฌํ™” ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ { #advanced-user-guide } ## ์ถ”๊ฐ€ ๊ธฐ๋Šฅ { #additional-features } diff --git a/docs/ko/docs/advanced/middleware.md b/docs/ko/docs/advanced/middleware.md index be2c972a6b..f6f7bbc966 100644 --- a/docs/ko/docs/advanced/middleware.md +++ b/docs/ko/docs/advanced/middleware.md @@ -8,7 +8,7 @@ ## ASGI middleware ์ถ”๊ฐ€ํ•˜๊ธฐ { #adding-asgi-middlewares } -**FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ASGI ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ์–ด๋–ค ASGI middleware๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +**FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ASGI ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ์–ด๋–ค ASGI middleware๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ASGI ์‚ฌ์–‘์„ ๋”ฐ๋ฅด๊ธฐ๋งŒ ํ•˜๋ฉด, FastAPI๋‚˜ Starlette๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ middleware๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. @@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") `http` ๋˜๋Š” `ws`๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ ๋Œ€์‹  ๋ณด์•ˆ ์Šคํ‚ด์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} ## `TrustedHostMiddleware` { #trustedhostmiddleware } HTTP Host Header ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด, ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋œ `Host` ํ—ค๋”๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *} +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} ๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: @@ -78,7 +78,7 @@ HTTP Host Header ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด, ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์ด middleware๋Š” ์ผ๋ฐ˜ ์‘๋‹ต๊ณผ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *} +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} ๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md index e4bdea9d6c..95f90d73cc 100644 --- a/docs/ko/docs/advanced/openapi-callbacks.md +++ b/docs/ko/docs/advanced/openapi-callbacks.md @@ -1,8 +1,8 @@ # OpenAPI ์ฝœ๋ฐฑ { #openapi-callbacks } -๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  *external API*(์•„๋งˆ๋„ ๋‹น์‹ ์˜ API๋ฅผ *์‚ฌ์šฉ*ํ•  ๋™์ผํ•œ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์š”์ฒญ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“œ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ง„ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  *external API*(์•„๋งˆ๋„ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋ฅผ *์‚ฌ์šฉ*ํ•  ๋™์ผํ•œ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์š”์ฒญ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“œ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ง„ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -๋‹น์‹ ์˜ API ์•ฑ์ด *external API*๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ผ์–ด๋‚˜๋Š” ๊ณผ์ •์„ "callback"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋‹น์‹ ์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๋‹ค์Œ, ๋‹น์‹ ์˜ API๊ฐ€ ๋‹ค์‹œ *external API*๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด *๋˜๋Œ๋ ค ํ˜ธ์ถœ*ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์•„๋งˆ๋„ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  API์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค). +์—ฌ๋Ÿฌ๋ถ„์˜ API ์•ฑ์ด *external API*๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ผ์–ด๋‚˜๋Š” ๊ณผ์ •์„ "callback"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๋‹ค์Œ, ์—ฌ๋Ÿฌ๋ถ„์˜ API๊ฐ€ ๋‹ค์‹œ *external API*๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด *๋˜๋Œ๋ ค ํ˜ธ์ถœ*ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์•„๋งˆ๋„ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  API์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ์ด ๊ฒฝ์šฐ, ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๋Š”์ง€, ์–ด๋–ค body๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š”์ง€, ์–ด๋–ค ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ๋“ฑ์ž…๋‹ˆ๋‹ค. @@ -14,14 +14,14 @@ ์ด ์ฒญ๊ตฌ์„œ๋Š” `id`, `title`(์„ ํƒ ์‚ฌํ•ญ), `customer`, `total`์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. -๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๋Š” POST ์š”์ฒญ์œผ๋กœ ๋‹น์‹ ์˜ API์—์„œ ์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. +์—ฌ๋Ÿฌ๋ถ„์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๋Š” POST ์š”์ฒญ์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ API์—์„œ ์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. -๊ทธ ๋‹ค์Œ ๋‹น์‹ ์˜ API๋Š”(๊ฐ€์ •ํ•ด ๋ณด๋ฉด): +๊ทธ ๋‹ค์Œ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋Š”(๊ฐ€์ •ํ•ด ๋ณด๋ฉด): * ์ฒญ๊ตฌ์„œ๋ฅผ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ณ ๊ฐ์—๊ฒŒ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. * ๋ˆ์„ ์ˆ˜๊ธˆํ•ฉ๋‹ˆ๋‹ค. * API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)์˜ API๋กœ ๋‹ค์‹œ ์•Œ๋ฆผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. - * ์ด๋Š” (๋‹น์‹ ์˜ API์—์„œ) ๊ทธ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์–ด๋–ค *external API*๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค(์ด๊ฒƒ์ด "callback"์ž…๋‹ˆ๋‹ค). + * ์ด๋Š” (์—ฌ๋Ÿฌ๋ถ„์˜ API์—์„œ) ๊ทธ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์–ด๋–ค *external API*๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค(์ด๊ฒƒ์ด "callback"์ž…๋‹ˆ๋‹ค). ## ์ผ๋ฐ˜์ ์ธ **FastAPI** ์•ฑ { #the-normal-fastapi-app } @@ -43,7 +43,7 @@ ## ์ฝœ๋ฐฑ ๋ฌธ์„œํ™”ํ•˜๊ธฐ { #documenting-the-callback } -์‹ค์ œ ์ฝœ๋ฐฑ ์ฝ”๋“œ๋Š” ๋‹น์‹ ์˜ API ์•ฑ์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค. +์‹ค์ œ ์ฝœ๋ฐฑ ์ฝ”๋“œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ API ์•ฑ์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์•ฑ๋งˆ๋‹ค ๋งŽ์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -54,11 +54,11 @@ callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` -ํ•˜์ง€๋งŒ ์ฝœ๋ฐฑ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€, ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์ฝœ๋ฐฑ ์š”์ฒญ body๋กœ *๋‹น์‹ ์˜ API*๊ฐ€ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ ๋“ฑ์— ๋งž์ถฐ *external API*๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ ์ฝœ๋ฐฑ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€, ์—ฌ๋Ÿฌ๋ถ„์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์ฝœ๋ฐฑ ์š”์ฒญ body๋กœ *์—ฌ๋Ÿฌ๋ถ„์˜ API*๊ฐ€ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ ๋“ฑ์— ๋งž์ถฐ *external API*๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๊ทธ๋ž˜์„œ ๋‹ค์Œ์œผ๋กœ ํ•  ์ผ์€, *๋‹น์‹ ์˜ API*์—์„œ ๋ณด๋‚ด๋Š” ์ฝœ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๊ทธ๋ž˜์„œ ๋‹ค์Œ์œผ๋กœ ํ•  ์ผ์€, *์—ฌ๋Ÿฌ๋ถ„์˜ API*์—์„œ ๋ณด๋‚ด๋Š” ์ฝœ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๊ทธ ๋ฌธ์„œ๋Š” ๋‹น์‹ ์˜ API์—์„œ `/docs`์˜ Swagger UI์— ํ‘œ์‹œ๋˜๋ฉฐ, ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์ด *external API*๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. +๊ทธ ๋ฌธ์„œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ API์—์„œ `/docs`์˜ Swagger UI์— ํ‘œ์‹œ๋˜๋ฉฐ, ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์ด *external API*๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ด ์˜ˆ์‹œ๋Š” ์ฝœ๋ฐฑ ์ž์ฒด(ํ•œ ์ค„ ์ฝ”๋“œ๋กœ๋„ ๋  ์ˆ˜ ์žˆ์Œ)๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ๋ฌธ์„œํ™” ๋ถ€๋ถ„๋งŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. @@ -76,11 +76,11 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ํ•˜์ง€๋งŒ **FastAPI**๋กœ API์˜ ์ž๋™ ๋ฌธ์„œ๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. -๋”ฐ๋ผ์„œ ๊ทธ์™€ ๊ฐ™์€ ์ง€์‹์„ ์‚ฌ์šฉํ•ด *external API*๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒจ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค... ์ฆ‰ ์™ธ๋ถ€ API๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(๋‹น์‹ ์˜ API๊ฐ€ ํ˜ธ์ถœํ•  ๊ฒƒ๋“ค)์„ ๋งŒ๋“ค์–ด์„œ ๋ง์ž…๋‹ˆ๋‹ค. +๋”ฐ๋ผ์„œ ๊ทธ์™€ ๊ฐ™์€ ์ง€์‹์„ ์‚ฌ์šฉํ•ด *external API*๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒจ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค... ์ฆ‰ ์™ธ๋ถ€ API๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(์—ฌ๋Ÿฌ๋ถ„์˜ API๊ฐ€ ํ˜ธ์ถœํ•  ๊ฒƒ๋“ค)์„ ๋งŒ๋“ค์–ด์„œ ๋ง์ž…๋‹ˆ๋‹ค. /// tip | ํŒ -์ฝœ๋ฐฑ์„ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š”, ์ž์‹ ์ด ๊ทธ *์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž*๋ผ๊ณ  ์ƒ์ƒํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ์€ *๋‹น์‹ ์˜ API*๊ฐ€ ์•„๋‹ˆ๋ผ *external API*๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”. +์ฝœ๋ฐฑ์„ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š”, ์ž์‹ ์ด ๊ทธ *์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž*๋ผ๊ณ  ์ƒ์ƒํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ์€ *์—ฌ๋Ÿฌ๋ถ„์˜ API*๊ฐ€ ์•„๋‹ˆ๋ผ *external API*๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”. ์ด ๊ด€์ (์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ด€์ )์„ ์ž ์‹œ ์ฑ„ํƒํ•˜๋ฉด, ๊ทธ *external API*๋ฅผ ์œ„ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ, body์šฉ Pydantic ๋ชจ๋ธ, ์‘๋‹ต ๋“ฑ์„ ์–ด๋””์— ๋‘์–ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -105,12 +105,12 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ์ผ๋ฐ˜์ ์ธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€์˜ ์ฃผ์š” ์ฐจ์ด์ ์€ 2๊ฐ€์ง€์ž…๋‹ˆ๋‹ค: -* ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์งˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์˜ ์•ฑ์€ ์ด ์ฝ”๋“œ๋ฅผ ์ ˆ๋Œ€ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” *external API*๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋Š” ๊ทธ๋ƒฅ `pass`๋งŒ ์žˆ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. -* *path*์—๋Š” OpenAPI 3 expression(์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ๊ณ )์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด *๋‹น์‹ ์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ผ๋ถ€ ๊ฐ’์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +* ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์งˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์€ ์ด ์ฝ”๋“œ๋ฅผ ์ ˆ๋Œ€ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” *external API*๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋Š” ๊ทธ๋ƒฅ `pass`๋งŒ ์žˆ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค. +* *path*์—๋Š” OpenAPI 3 expression(์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ๊ณ )์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด *์—ฌ๋Ÿฌ๋ถ„์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ผ๋ถ€ ๊ฐ’์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### ์ฝœ๋ฐฑ ๊ฒฝ๋กœ ํ‘œํ˜„์‹ { #the-callback-path-expression } -์ฝœ๋ฐฑ *path*๋Š” *๋‹น์‹ ์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ์ผ๋ถ€๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” OpenAPI 3 expression์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ฝœ๋ฐฑ *path*๋Š” *์—ฌ๋Ÿฌ๋ถ„์˜ API*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ์ผ๋ถ€๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” OpenAPI 3 expression์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ๋‹ค์Œ `str`์ž…๋‹ˆ๋‹ค: @@ -118,7 +118,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) "{$callback_url}/invoices/{$request.body.id}" ``` -๋”ฐ๋ผ์„œ ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ *๋‹น์‹ ์˜ API*๋กœ ๋‹ค์Œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ : +๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ๋ถ„์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ *์—ฌ๋Ÿฌ๋ถ„์˜ API*๋กœ ๋‹ค์Œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ : ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events @@ -134,7 +134,7 @@ JSON body๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๋ฉด: } ``` -๊ทธ๋Ÿฌ๋ฉด *๋‹น์‹ ์˜ API*๋Š” ์ฒญ๊ตฌ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—์„œ `callback_url`(์ฆ‰ *external API*)๋กœ ์ฝœ๋ฐฑ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค: +๊ทธ๋Ÿฌ๋ฉด *์—ฌ๋Ÿฌ๋ถ„์˜ API*๋Š” ์ฒญ๊ตฌ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—์„œ `callback_url`(์ฆ‰ *external API*)๋กœ ์ฝœ๋ฐฑ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค: ``` https://www.external.org/events/invoices/2expen51ve @@ -167,7 +167,7 @@ https://www.external.org/events/invoices/2expen51ve ์ด ์‹œ์ ์—์„œ, ์œ„์—์„œ ๋งŒ๋“  ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ ์•ˆ์— *์ฝœ๋ฐฑ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(์ฆ‰ *external developer*๊ฐ€ *external API*์— ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค)์„ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค. -์ด์ œ *๋‹น์‹ ์˜ API ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ `callbacks` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด, ๊ทธ ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ์˜ `.routes` ์†์„ฑ(์‹ค์ œ๋กœ๋Š” routes/*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `list`)์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: +์ด์ œ *์—ฌ๋Ÿฌ๋ถ„์˜ API ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ `callbacks` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด, ๊ทธ ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ์˜ `.routes` ์†์„ฑ(์‹ค์ œ๋กœ๋Š” routes/*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `list`)์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} diff --git a/docs/ko/docs/advanced/openapi-webhooks.md b/docs/ko/docs/advanced/openapi-webhooks.md index 89cacf7b78..8651c4176c 100644 --- a/docs/ko/docs/advanced/openapi-webhooks.md +++ b/docs/ko/docs/advanced/openapi-webhooks.md @@ -32,7 +32,7 @@ Webhooks๋Š” OpenAPI 3.1.0 ์ด์ƒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI `0.99.0` **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ(์˜ˆ: `@app.webhooks.post()`), *webhooks*๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” `webhooks` ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *} +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} ์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ webhook์€ **OpenAPI** ์Šคํ‚ค๋งˆ์™€ ์ž๋™ **docs UI**์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/path-operation-advanced-configuration.md b/docs/ko/docs/advanced/path-operation-advanced-configuration.md index f20fa6d263..da8e43bd3e 100644 --- a/docs/ko/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ko/docs/advanced/path-operation-advanced-configuration.md @@ -12,7 +12,7 @@ OpenAPI โ€œ์ „๋ฌธ๊ฐ€โ€๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ์•„๋งˆ ์ด ๋‚ด์šฉ์€ ํ•„์š”ํ•˜์ง€ ์•Š ๊ฐ ์ž‘์—…๋งˆ๋‹ค ๊ณ ์œ ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} ### *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ์ด๋ฆ„์„ operationId๋กœ ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-path-operation-function-name-as-the-operationid } @@ -20,7 +20,7 @@ API์˜ ํ•จ์ˆ˜ ์ด๋ฆ„์„ `operationId`๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋ชจ๋“  API๋ฅผ ๋ชจ๋“  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} /// tip | ํŒ @@ -40,7 +40,7 @@ API์˜ ํ•จ์ˆ˜ ์ด๋ฆ„์„ `operationId`๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋ชจ๋“  API๋ฅผ ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ(๋”ฐ๋ผ์„œ ์ž๋™ ๋ฌธ์„œํ™” ์‹œ์Šคํ…œ)์—์„œ ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด, `include_in_schema` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `False`๋กœ ์„ค์ •ํ•˜์„ธ์š”: -{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} ## docstring์—์„œ ๊ณ ๊ธ‰ ์„ค๋ช… ๊ฐ€์ ธ์˜ค๊ธฐ { #advanced-description-from-docstring } @@ -92,7 +92,7 @@ OpenAPI ๋ช…์„ธ์—์„œ๋Š” ์ด๋ฅผ parsed
๋˜์ง€๋„ ์•Š๊ณ , `bytes`๋กœ ์ง์ ‘ ์ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ `magic_data_reader()`๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ด๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. +์ด ์˜ˆ์‹œ์—์„œ๋Š” ์–ด๋–ค Pydantic ๋ชจ๋ธ๋„ ์„ ์–ธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์š”์ฒญ ๋ฐ”๋””๋Š” JSON์œผ๋กœ ํŒŒ์‹ฑ๋˜์ง€๋„ ์•Š๊ณ , `bytes`๋กœ ์ง์ ‘ ์ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ `magic_data_reader()`๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ด๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์š”์ฒญ ๋ฐ”๋””์— ๋Œ€ํ•ด ๊ธฐ๋Œ€ํ•˜๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -153,7 +153,7 @@ OpenAPI ๋ช…์„ธ์—์„œ๋Š” ์ด๋ฅผ Pydantic: Concepts: Configuration์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. +`model_config` ์†์„ฑ์€ Pydantic ์„ค์ •์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Pydantic: Concepts: Configuration๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. /// @@ -226,11 +226,11 @@ def get_settings(): ํ•˜์ง€๋งŒ ์œ„์— `@lru_cache` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, `Settings` ๊ฐ์ฒด๋Š” ์ตœ์ดˆ ํ˜ธ์ถœ ์‹œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. โœ”๏ธ -{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} ๊ทธ ๋‹ค์Œ ์š”์ฒญ๋“ค์—์„œ ์˜์กด์„ฑ์œผ๋กœ `get_settings()`๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค, `get_settings()`์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์„œ ์ƒˆ `Settings` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ์ฒซ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ๊ณ„์† ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -#### `lru_cache` Technical Details { #lru-cache-technical-details } +#### `lru_cache` ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ { #lru-cache-technical-details } `@lru_cache`๋Š” ๋ฐ์ฝ”๋ ˆ์ด์…˜ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋งค๋ฒˆ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ๋Œ€์‹ , ์ฒซ ๋ฒˆ์งธ์— ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋งค๋ฒˆ ํ•จ์ˆ˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค). diff --git a/docs/ko/docs/advanced/sub-applications.md b/docs/ko/docs/advanced/sub-applications.md index e1554ca5d6..8da217aab6 100644 --- a/docs/ko/docs/advanced/sub-applications.md +++ b/docs/ko/docs/advanced/sub-applications.md @@ -10,7 +10,7 @@ ๋จผ์ €, ๋ฉ”์ธ ์ตœ์ƒ์œ„ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ทธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} ### ํ•˜์œ„ ์‘์šฉํ”„๋กœ๊ทธ๋žจ { #sub-application } @@ -18,7 +18,7 @@ ์ด ํ•˜์œ„ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์€ ๋˜ ๋‹ค๋ฅธ ํ‘œ์ค€ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด์ง€๋งŒ, "๋งˆ์šดํŠธ"๋  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} ### ํ•˜์œ„ ์‘์šฉํ”„๋กœ๊ทธ๋žจ ๋งˆ์šดํŠธ { #mount-the-sub-application } @@ -26,7 +26,7 @@ ์ด ๊ฒฝ์šฐ `/subapi` ๊ฒฝ๋กœ์— ๋งˆ์šดํŠธ๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *} +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} ### ์ž๋™ API ๋ฌธ์„œ ํ™•์ธ { #check-the-automatic-api-docs } diff --git a/docs/ko/docs/advanced/templates.md b/docs/ko/docs/advanced/templates.md index fffffa6a54..3ae718f153 100644 --- a/docs/ko/docs/advanced/templates.md +++ b/docs/ko/docs/advanced/templates.md @@ -27,7 +27,7 @@ $ pip install jinja2 * ํ…œํ”Œ๋ฆฟ์„ ๋ฐ˜ํ™˜ํ•  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— `Request` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. * ์ƒ์„ฑํ•œ `templates`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `TemplateResponse`๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ…œํ”Œ๋ฆฟ์˜ ์ด๋ฆ„, ์š”์ฒญ ๊ฐ์ฒด ๋ฐ Jinja2 ํ…œํ”Œ๋ฆฟ ๋‚ด์—์„œ ์‚ฌ์šฉ๋  ํ‚ค-๊ฐ’ ์Œ์ด ํฌํ•จ๋œ "์ปจํ…์ŠคํŠธ" ๋”•์…”๋„ˆ๋ฆฌ๋„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *} +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} /// note | ์ฐธ๊ณ  diff --git a/docs/ko/docs/advanced/testing-events.md b/docs/ko/docs/advanced/testing-events.md index 8dbd4f6e66..a1a7daff38 100644 --- a/docs/ko/docs/advanced/testing-events.md +++ b/docs/ko/docs/advanced/testing-events.md @@ -2,11 +2,11 @@ ํ…Œ์ŠคํŠธ์—์„œ `lifespan`์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, `with` ๋ฌธ๊ณผ ํ•จ๊ป˜ `TestClient`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *} +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} ["๊ณต์‹ Starlette ๋ฌธ์„œ ์‚ฌ์ดํŠธ์—์„œ ํ…Œ์ŠคํŠธ์—์„œ ๋ผ์ดํ”„์ŠคํŒฌ ์‹คํ–‰ํ•˜๊ธฐ."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๋” ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š” `startup` ๋ฐ `shutdown` ์ด๋ฒคํŠธ์˜ ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด `TestClient`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *} +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/ko/docs/advanced/testing-websockets.md b/docs/ko/docs/advanced/testing-websockets.md index 1cb3cad67e..23ff34cd3a 100644 --- a/docs/ko/docs/advanced/testing-websockets.md +++ b/docs/ko/docs/advanced/testing-websockets.md @@ -4,10 +4,10 @@ ์ด๋ฅผ ์œ„ํ•ด `with` ๋ฌธ์—์„œ `TestClient`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ WebSocket์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *} +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} /// note | ์ฐธ๊ณ  -์ž์„ธํ•œ ๋‚ด์šฉ์€ Starlette์˜ testing WebSockets ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. +์ž์„ธํ•œ ๋‚ด์šฉ์€ Starlette์˜ WebSocket ํ…Œ์ŠคํŠธ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. /// diff --git a/docs/ko/docs/advanced/using-request-directly.md b/docs/ko/docs/advanced/using-request-directly.md index e0a5e99f88..0c45e2e2f8 100644 --- a/docs/ko/docs/advanced/using-request-directly.md +++ b/docs/ko/docs/advanced/using-request-directly.md @@ -29,7 +29,7 @@ ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์š”์ฒญ์— ์ง์ ‘ ์ ‘๊ทผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *} +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `Request` ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜๋ฉด **FastAPI**๊ฐ€ ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜์— `Request`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/advanced/websockets.md b/docs/ko/docs/advanced/websockets.md index b6817870b7..384f93952b 100644 --- a/docs/ko/docs/advanced/websockets.md +++ b/docs/ko/docs/advanced/websockets.md @@ -24,7 +24,7 @@ $ pip install websockets ๊ทธ๋ฆฌ๊ณ  ๋ฐฑ์—”๋“œ์™€ WebSockets์„ ์‚ฌ์šฉํ•ด ํ†ต์‹ ํ•˜๋ ค๋ฉด ์•„๋งˆ๋„ ํ”„๋ŸฐํŠธ์—”๋“œ์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๋˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋กœ WebSocket ๋ฐฑ์—”๋“œ์™€ ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋ฐ”์ผ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +๋˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋กœ WebSocket ๋ฐฑ์—”๋“œ์™€ ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ WebSocket ์—”๋“œํฌ์ธํŠธ์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -38,13 +38,13 @@ $ pip install websockets ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” WebSockets์˜ ์„œ๋ฒ„ ์ธก์— ์ง‘์ค‘ํ•˜๊ณ  ๋™์ž‘ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *} ## `websocket` ์ƒ์„ฑํ•˜๊ธฐ { #create-a-websocket } -**FastAPI** ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ `websocket`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: +**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ `websocket`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *} /// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ @@ -58,13 +58,13 @@ $ pip install websockets WebSocket ๊ฒฝ๋กœ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋Œ€๊ธฐ(`await`)ํ•˜๊ณ  ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *} +{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *} ์—ฌ๋Ÿฌ๋ถ„์€ ์ด์ง„ ๋ฐ์ดํ„ฐ, ํ…์ŠคํŠธ, JSON ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ  ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ## ์‹œ๋„ํ•ด๋ณด๊ธฐ { #try-it } -ํŒŒ์ผ ์ด๋ฆ„์ด `main.py`๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค: +ํŒŒ์ผ ์ด๋ฆ„์ด `main.py`๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:
@@ -86,7 +86,7 @@ $ fastapi dev main.py -๊ทธ๋ฆฌ๊ณ  WebSockets๊ฐ€ ํฌํ•จ๋œ **FastAPI** ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์‘๋‹ต์„ ๋Œ๋ ค์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค: +๊ทธ๋ฆฌ๊ณ  WebSockets๊ฐ€ ํฌํ•จ๋œ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‘๋‹ต์„ ๋Œ๋ ค์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค: @@ -121,7 +121,7 @@ WebSocket์ด๊ธฐ ๋•Œ๋ฌธ์— `HTTPException`์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์€ ์ ์ ˆํ•˜์ง€ ### ์ข…์†์„ฑ์„ ๊ฐ€์ง„ WebSockets ์‹œ๋„ํ•ด๋ณด๊ธฐ { #try-the-websockets-with-dependencies } -ํŒŒ์ผ ์ด๋ฆ„์ด `main.py`๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค: +ํŒŒ์ผ ์ด๋ฆ„์ด `main.py`๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:
@@ -154,7 +154,7 @@ $ fastapi dev main.py WebSocket ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ๋ฉด, `await websocket.receive_text()`๊ฐ€ `WebSocketDisconnect` ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ด ์˜ˆ์ œ์ฒ˜๋Ÿผ ์ด๋ฅผ ์žก์•„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} +{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *} ํ…Œ์ŠคํŠธํ•ด๋ณด๊ธฐ: diff --git a/docs/ko/docs/advanced/wsgi.md b/docs/ko/docs/advanced/wsgi.md index 5e0e87c5e7..24b074443d 100644 --- a/docs/ko/docs/advanced/wsgi.md +++ b/docs/ko/docs/advanced/wsgi.md @@ -18,7 +18,7 @@ ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๊ฒฝ๋กœ์— ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *} +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} /// note | ์ฐธ๊ณ  diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md index d8c2df2d8d..f26fbe39dd 100644 --- a/docs/ko/docs/alternatives.md +++ b/docs/ko/docs/alternatives.md @@ -137,7 +137,7 @@ Flask REST framework๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์žˆ์ง€๋งŒ, ์‹œ๊ฐ„์„ ๋“ค์—ฌ ์กฐ์‚ฌํ•ด ๋ณธ ### Marshmallow { #marshmallow } -API ์‹œ์Šคํ…œ์— ํ•„์š”ํ•œ ์ฃผ์š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ "serialization"์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ(Python)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋„คํŠธ์›Œํฌ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ JSON ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, `datetime` ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค. +API ์‹œ์Šคํ…œ์— ํ•„์š”ํ•œ ์ฃผ์š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ "์ง๋ ฌํ™”"์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ(Python)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋„คํŠธ์›Œํฌ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ JSON ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, `datetime` ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค. API์— ๋˜ ํ•˜๋‚˜ ํฌ๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค ํ•„๋“œ๊ฐ€ `int`์ธ์ง€, ์ž„์˜์˜ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ์‹์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -145,7 +145,7 @@ API์— ๋˜ ํ•˜๋‚˜ ํฌ๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์ž…๋‹ˆ๋‹ค. ํŠน์ • ์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด Marshmallow๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ํ›Œ๋ฅญํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฉฐ, ์ €๋„ ์ด์ „์— ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ Python type hints๊ฐ€ ์กด์žฌํ•˜๊ธฐ ์ „์— ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ schema๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด Marshmallow๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +ํ•˜์ง€๋งŒ Python type hints๊ฐ€ ์กด์žฌํ•˜๊ธฐ ์ „์— ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด Marshmallow๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. /// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ @@ -155,7 +155,7 @@ API์— ๋˜ ํ•˜๋‚˜ ํฌ๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์ž…๋‹ˆ๋‹ค. ํŠน์ • ### Webargs { #webargs } -API์— ํ•„์š”ํ•œ ๋˜ ๋‹ค๋ฅธ ํฐ ๊ธฐ๋Šฅ์€ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ parsingํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. +API์— ํ•„์š”ํ•œ ๋˜ ๋‹ค๋ฅธ ํฐ ๊ธฐ๋Šฅ์€ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Webargs๋Š” Flask๋ฅผ ํฌํ•จํ•œ ์—ฌ๋Ÿฌ framework ์œ„์—์„œ ์ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. @@ -419,7 +419,7 @@ Marshmallow์™€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ benchmark์—์„œ Marshmallow๋ณด ### Starlette { #starlette } -Starlette๋Š” ๊ฒฝ๋Ÿ‰ ASGI framework/toolkit์œผ๋กœ, ๊ณ ์„ฑ๋Šฅ asyncio ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. +Starlette๋Š” ๊ฒฝ๋Ÿ‰ ASGI framework/toolkit์œผ๋กœ, ๊ณ ์„ฑ๋Šฅ asyncio ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๊ณ , ๋ชจ๋“ˆ์‹ component๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/deployment/docker.md b/docs/ko/docs/deployment/docker.md index 20e341c269..ca0136d836 100644 --- a/docs/ko/docs/deployment/docker.md +++ b/docs/ko/docs/deployment/docker.md @@ -14,7 +14,7 @@ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์€ **๋ฆฌ Dockerfile Preview ๐Ÿ‘€ ```Dockerfile -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None): ```{ .dockerfile .annotate } # (1)! -FROM python:3.9 +FROM python:3.14 # (2)! WORKDIR /code @@ -390,7 +390,7 @@ FastAPI๊ฐ€ ๋‹จ์ผ ํŒŒ์ผ(์˜ˆ: `./app` ๋””๋ ‰ํ„ฐ๋ฆฌ ์—†์ด `main.py`๋งŒ ์žˆ๋Š” ๊ทธ๋Ÿฐ ๋‹ค์Œ `Dockerfile`์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ ๋ณต์‚ฌํ•˜๋„๋ก ๊ฒฝ๋กœ๋งŒ ๋งž๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: ```{ .dockerfile .annotate hl_lines="10 13" } -FROM python:3.9 +FROM python:3.14 WORKDIR /code @@ -454,7 +454,7 @@ Traefik์€ Docker, Kubernetes ๋“ฑ๊ณผ ํ†ตํ•ฉ๋˜์–ด ์žˆ์–ด, ์ด๋ฅผ ์‚ฌ์šฉํ•ด ์ปจ ## ๋ณต์ œ - ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜ { #replication-number-of-processes } -**Kubernetes**, Docker Swarm Mode, Nomad ๋“ฑ์˜ ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์œผ๋กœ ์—ฌ๋Ÿฌ ๋จธ์‹ ์— ๋ถ„์‚ฐ๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—์„œ(**์›Œ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Uvicorn** ๊ฐ™์€) **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๋ฅผ ์“ฐ๋Š” ๋Œ€์‹ , **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ **๋ณต์ œ๋ฅผ ์ฒ˜๋ฆฌ**ํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. +**Kubernetes**, Docker Swarm Mode, Nomad ๋“ฑ์˜ ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์œผ๋กœ ์—ฌ๋Ÿฌ ๋จธ์‹ ์— ๋ถ„์‚ฐ๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—์„œ(**์›Œ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Uvicorn** ๊ฐ™์€) **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๋ฅผ ์“ฐ๋Š” ๋Œ€์‹ , **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ **๋ณต์ œ๋ฅผ ์ฒ˜๋ฆฌ**ํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. Kubernetes ๊ฐ™์€ ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์€ ๋ณดํ†ต ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ**์„ ์ง€์›ํ•˜๋ฉด์„œ๋„, **์ปจํ…Œ์ด๋„ˆ ๋ณต์ œ**๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ†ตํ•ฉ๋œ ๋ฐฉ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ์š”. @@ -499,7 +499,7 @@ HTTPS์— ์‚ฌ์šฉ๋˜๋Š” ๋™์ผํ•œ **TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ** ์ปดํฌ๋„ŒํŠธ๊ฐ€ **๋กœ ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” `--workers` ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด ์‹คํ–‰ํ•  ์›Œ์ปค ์ˆ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ```{ .dockerfile .annotate } -FROM python:3.9 +FROM python:3.14 WORKDIR /code diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md index 888ec61592..bda942af68 100644 --- a/docs/ko/docs/deployment/https.md +++ b/docs/ko/docs/deployment/https.md @@ -15,7 +15,7 @@ HTTPS๋Š” ๊ทธ๋ƒฅ โ€œ์ผœ์ ธ ์žˆ๊ฑฐ๋‚˜โ€ ์•„๋‹ˆ๋ฉด โ€œ๊บผ์ ธ ์žˆ๋Š”โ€ ๊ฒƒ์ด๋ผ ์ด์ œ **๊ฐœ๋ฐœ์ž ๊ด€์ **์—์„œ HTTPS๋ฅผ ์ƒ๊ฐํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: * HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, **์„œ๋ฒ„**๊ฐ€ **์ œ3์ž**๊ฐ€ ๋ฐœ๊ธ‰ํ•œ **"์ธ์ฆ์„œ(certificates)"**๋ฅผ **๋ณด์œ **ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - * ์ด ์ธ์ฆ์„œ๋Š” ์‹ค์ œ๋กœ ์ œ3์ž๊ฐ€ โ€œ์ƒ์„ฑโ€ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ œ3์ž๋กœ๋ถ€ํ„ฐ **๋ฐœ๊ธ‰/ํš๋“**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. + * ์ด ์ธ์ฆ์„œ๋Š” ์‹ค์ œ๋กœ '์ƒ์„ฑ'๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ œ3์ž๋กœ๋ถ€ํ„ฐ **๋ฐœ๊ธ‰/ํš๋“**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. * ์ธ์ฆ์„œ์—๋Š” **์œ ํšจ ๊ธฐ๊ฐ„**์ด ์žˆ์Šต๋‹ˆ๋‹ค. * ์ฆ‰, **๋งŒ๋ฃŒ**๋ฉ๋‹ˆ๋‹ค. * ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋ฉด ์ œ3์ž๋กœ๋ถ€ํ„ฐ ๋‹ค์‹œ **๊ฐฑ์‹ **ํ•ด์„œ **์žฌ๋ฐœ๊ธ‰/์žฌํš๋“**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -65,7 +65,7 @@ Let's Encrypt ์ด์ „์—๋Š” ์ด๋Ÿฌํ•œ **HTTPS ์ธ์ฆ์„œ**๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์•„๋งˆ๋„ ์‹œ์ž‘์€ **๋„๋ฉ”์ธ ์ด๋ฆ„**์„ **ํš๋“**ํ•˜๋Š” ๊ฒƒ์ผ ๊ฒ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ DNS ์„œ๋ฒ„(์•„๋งˆ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด)์—์„œ ์ด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. -๋Œ€๊ฐœ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„(๊ฐ€์ƒ ๋จธ์‹ ) ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ณ , ๊ฑฐ๊ธฐ์—๋Š” fixed **๊ณต๊ฐœ IP ์ฃผ์†Œ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +๋Œ€๊ฐœ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„(๊ฐ€์ƒ ๋จธ์‹ ) ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ณ , ๊ฑฐ๊ธฐ์—๋Š” ๊ณ ์ • **๊ณต๊ฐœ IP ์ฃผ์†Œ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. DNS ์„œ๋ฒ„(๋“ค)์—์„œ **๋„๋ฉ”์ธ**์ด ์„œ๋ฒ„์˜ **๊ณต๊ฐœ IP ์ฃผ์†Œ**๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ ˆ์ฝ”๋“œ(โ€œ`A record`โ€)๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md index e85dd02a32..93b1e76115 100644 --- a/docs/ko/docs/deployment/manually.md +++ b/docs/ko/docs/deployment/manually.md @@ -46,7 +46,7 @@ $ fastapi run ASGI๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”, Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. FastAPI๋Š” ASGI ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. +FastAPI๋Š” ASGI๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”, Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. FastAPI๋Š” ASGI ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์›๊ฒฉ ์„œ๋ฒ„ ๋จธ์‹ ์—์„œ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋˜๋Š” ๋‹ค๋ฅธ ASGI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํ•ต์‹ฌ ์š”์†Œ๋Š” **Uvicorn** ๊ฐ™์€ ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. `fastapi` ๋ช…๋ น์—๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์ด๊ฒƒ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/deployment/server-workers.md b/docs/ko/docs/deployment/server-workers.md index e98cfd1142..1be102925e 100644 --- a/docs/ko/docs/deployment/server-workers.md +++ b/docs/ko/docs/deployment/server-workers.md @@ -9,13 +9,13 @@ * ๋ฉ”๋ชจ๋ฆฌ * ์‹œ์ž‘ํ•˜๊ธฐ ์ „์˜ ์ด์ „ ๋‹จ๊ณ„ -์ง€๊ธˆ๊นŒ์ง€ ๋ฌธ์„œ์˜ ๋ชจ๋“  ํŠœํ† ๋ฆฌ์–ผ์„ ์ฐธ๊ณ ํ•˜๋ฉด์„œ, `fastapi` ๋ช…๋ น์ฒ˜๋Ÿผ Uvicorn์„ ์‹คํ–‰ํ•˜๋Š” **์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ**์„ ์‚ฌ์šฉํ•ด **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•ด ์™”์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. +์ง€๊ธˆ๊นŒ์ง€ ๋ฌธ์„œ์˜ ๋ชจ๋“  ํŠœํ† ๋ฆฌ์–ผ์„ ์ฐธ๊ณ ํ•˜๋ฉด์„œ, `fastapi` ๋ช…๋ น์–ด์ฒ˜๋Ÿผ Uvicorn์„ ์‹คํ–‰ํ•˜๋Š” **์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ**์„ ์‚ฌ์šฉํ•ด **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•ด ์™”์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•  ๋•Œ๋Š” **๋‹ค์ค‘ ์ฝ”์–ด**๋ฅผ ํ™œ์šฉํ•˜๊ณ  ๋” ๋งŽ์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก **ํ”„๋กœ์„ธ์Šค ๋ณต์ œ**๋ฅผ ํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ์ด์ „ ์žฅ์˜ [๋ฐฐํฌ ๊ฐœ๋…๋“ค](concepts.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋žต์ด ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žˆ์Šต๋‹ˆ๋‹ค. -์—ฌ๊ธฐ์„œ๋Š” `fastapi` ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ `uvicorn` ๋ช…๋ น์„ ์ง์ ‘ ์‚ฌ์šฉํ•ด์„œ, **์›Œ์ปค ํ”„๋กœ์„ธ์Šค**์™€ ํ•จ๊ป˜ **Uvicorn**์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. +์—ฌ๊ธฐ์„œ๋Š” `fastapi` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ `uvicorn` ๋ช…๋ น์–ด๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•ด์„œ, **์›Œ์ปค ํ”„๋กœ์„ธ์Šค**์™€ ํ•จ๊ป˜ **Uvicorn**์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. /// info | ์ •๋ณด @@ -27,11 +27,11 @@ Docker๋‚˜ Kubernetes ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค์Œ ์žฅ ## ์—ฌ๋Ÿฌ ์›Œ์ปค { #multiple-workers } -`--workers` ์ปค๋งจ๋“œ๋ผ์ธ ์˜ต์…˜์œผ๋กœ ์—ฌ๋Ÿฌ ์›Œ์ปค๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +`--workers` ๋ช…๋ น์–ด ์˜ต์…˜์œผ๋กœ ์—ฌ๋Ÿฌ ์›Œ์ปค๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: //// tab | `fastapi` -`fastapi` ๋ช…๋ น์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด: +`fastapi` ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด:
@@ -81,7 +81,7 @@ $ fastapi run --workers 4 @@ -132,7 +132,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## ์š”์•ฝ { #recap } -`fastapi` ๋˜๋Š” `uvicorn` ๋ช…๋ น์—์„œ `--workers` CLI ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, **๋ฉ€ํ‹ฐ ์ฝ”์–ด CPU**๋ฅผ ํ™œ์šฉํ•ด **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`fastapi` ๋˜๋Š” `uvicorn` ๋ช…๋ น์–ด์—์„œ `--workers` CLI ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, **๋ฉ€ํ‹ฐ ์ฝ”์–ด CPU**๋ฅผ ํ™œ์šฉํ•ด **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฐํฌ ๊ฐœ๋…๋“ค์„ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ **์ž์ฒด ๋ฐฐํฌ ์‹œ์Šคํ…œ**์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ๋„๊ตฌ์™€ ์•„์ด๋””์–ด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/deployment/versions.md b/docs/ko/docs/deployment/versions.md index 173ba925cf..b94832aa82 100644 --- a/docs/ko/docs/deployment/versions.md +++ b/docs/ko/docs/deployment/versions.md @@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0 ## ์ด์šฉ ๊ฐ€๋Šฅํ•œ ๋ฒ„์ „๋“ค { #available-versions } -์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฒ„์ „(์˜ˆ: ํ˜„์žฌ ์ตœ์‹  ๋ฒ„์ „์ด ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด)์€ [Release Notes](../release-notes.md){.internal-link target=_blank}์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฒ„์ „(์˜ˆ: ํ˜„์žฌ ์ตœ์‹  ๋ฒ„์ „์ด ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด)์€ [๋ฆด๋ฆฌ์Šค ๋…ธํŠธ](../release-notes.md){.internal-link target=_blank}์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ## ๋ฒ„์ „๋“ค์— ๋Œ€ํ•ด { #about-versions } @@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0 ์•ฑ์— ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -**FastAPI**์—์„œ๋Š” ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค(Starlette ๋•๋ถ„์—). ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”: [Testing](../tutorial/testing.md){.internal-link target=_blank} +**FastAPI**์—์„œ๋Š” ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค(Starlette ๋•๋ถ„์—). ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”: [ํ…Œ์ŠคํŠธ](../tutorial/testing.md){.internal-link target=_blank} ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ–์ถ˜ ๋’ค์—๋Š” **FastAPI** ๋ฒ„์ „์„ ๋” ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ชจ๋“  ์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. diff --git a/docs/ko/docs/environment-variables.md b/docs/ko/docs/environment-variables.md index dc231acb64..e8809573fd 100644 --- a/docs/ko/docs/environment-variables.md +++ b/docs/ko/docs/environment-variables.md @@ -19,10 +19,10 @@
```console -// You could create an env var MY_NAME with +// ํ™˜๊ฒฝ ๋ณ€์ˆ˜ MY_NAME์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค $ export MY_NAME="Wade Wilson" -// Then you could use it with other programs, like +// ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: $ echo "Hello $MY_NAME" Hello Wade Wilson @@ -37,10 +37,10 @@ Hello Wade Wilson
```console -// Create an env var MY_NAME +// ํ™˜๊ฒฝ ๋ณ€์ˆ˜ MY_NAME ์ƒ์„ฑ $ $Env:MY_NAME = "Wade Wilson" -// Use it with other programs, like +// ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ. ์˜ˆ: $ echo "Hello $Env:MY_NAME" Hello Wade Wilson @@ -78,20 +78,20 @@ print(f"Hello {name} from Python")
```console -// Here we don't set the env var yet +// ์—ฌ๊ธฐ์„œ๋Š” ์•„์ง ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค $ python main.py -// As we didn't set the env var, we get the default value +// ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๊ธฐ๋ณธ๊ฐ’์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค Hello World from Python -// But if we create an environment variable first +// ํ•˜์ง€๋งŒ ๋จผ์ € ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋ฉด $ export MY_NAME="Wade Wilson" -// And then call the program again +// ๊ทธ๋ฆฌ๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด $ python main.py -// Now it can read the environment variable +// ์ด์ œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค Hello Wade Wilson from Python ``` @@ -105,20 +105,20 @@ Hello Wade Wilson from Python
```console -// Here we don't set the env var yet +// ์—ฌ๊ธฐ์„œ๋Š” ์•„์ง ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค $ python main.py -// As we didn't set the env var, we get the default value +// ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๊ธฐ๋ณธ๊ฐ’์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค Hello World from Python -// But if we create an environment variable first +// ํ•˜์ง€๋งŒ ๋จผ์ € ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋ฉด $ $Env:MY_NAME = "Wade Wilson" -// And then call the program again +// ๊ทธ๋ฆฌ๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด $ python main.py -// Now it can read the environment variable +// ์ด์ œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค Hello Wade Wilson from Python ``` @@ -136,14 +136,14 @@ Hello Wade Wilson from Python
```console -// Create an env var MY_NAME in line for this program call +// ์ด ํ”„๋กœ๊ทธ๋žจ ํ˜ธ์ถœ์„ ์œ„ํ•ด ๊ฐ™์€ ์ค„์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ MY_NAME ์ƒ์„ฑ $ MY_NAME="Wade Wilson" python main.py -// Now it can read the environment variable +// ์ด์ œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค Hello Wade Wilson from Python -// The env var no longer exists afterwards +// ์ดํ›„์—๋Š” ํ•ด๋‹น ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค $ python main.py Hello World from Python diff --git a/docs/ko/docs/features.md b/docs/ko/docs/features.md index 17cc9289f7..b511ae4707 100644 --- a/docs/ko/docs/features.md +++ b/docs/ko/docs/features.md @@ -6,7 +6,7 @@ ### ๊ฐœ๋ฐฉํ˜• ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ { #based-on-open-standards } -* OpenAPI: path operations, ๋งค๊ฐœ๋ณ€์ˆ˜, ์š”์ฒญ ๋ณธ๋ฌธ, ๋ณด์•ˆ ๋“ฑ์˜ ์„ ์–ธ์„ ํฌํ•จํ•˜์—ฌ API๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. +* OpenAPI: ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ, ๋งค๊ฐœ๋ณ€์ˆ˜, ์š”์ฒญ ๋ณธ๋ฌธ, ๋ณด์•ˆ ๋“ฑ์˜ ์„ ์–ธ์„ ํฌํ•จํ•˜์—ฌ API๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. * JSON Schema๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๋ฌธ์„œํ™”(OpenAPI ์ž์ฒด๊ฐ€ JSON Schema๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค). * ๋‹จ์ˆœํžˆ ๋– ์˜ฌ๋ ค์„œ ๋ง๋ถ™์ธ ๋ ˆ์ด์–ด๊ฐ€ ์•„๋‹ˆ๋ผ, ์„ธ์‹ฌํ•œ ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์นœ ๋’ค ์ด๋Ÿฌํ•œ ํ‘œ์ค€์„ ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. * ์ด๋Š” ๋˜ํ•œ ๋‹ค์–‘ํ•œ ์–ธ์–ด๋กœ ์ž๋™ **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑ**์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. @@ -136,7 +136,7 @@ Python ๊ฐœ๋ฐœ์ž ์„ค๋ฌธ์กฐ์‚ฌ์—์„œ Dependency Injection ์‹œ์Šคํ…œ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. +FastAPI๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ๋งค์šฐ ์‰ฝ์ง€๋งŒ, ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. * ์˜์กด์„ฑ๋„ ์˜์กด์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์–ด, ์˜์กด์„ฑ์˜ ๊ณ„์ธต ๋˜๋Š” **์˜์กด์„ฑ์˜ "๊ทธ๋ž˜ํ”„"**๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. * ๋ชจ๋“  ๊ฒƒ์ด ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด **์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค**. @@ -153,8 +153,8 @@ FastAPI๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ๋งค์šฐ ์‰ฝ์ง€๋งŒ, ๋งค์šฐ ๊ฐ•๋ ฅํ•œ IDE/linter/๋‡Œ**์™€ ์ž˜ ์–ด์šธ๋ฆฝ๋‹ˆ๋‹ค: +* ์—ฌ๋Ÿฌ๋ถ„์˜ **IDE/๋ฆฐํ„ฐ/๋‡Œ**์™€ ์ž˜ ์–ด์šธ๋ฆฝ๋‹ˆ๋‹ค: * pydantic ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์ผ ๋ฟ์ด๋ฏ€๋กœ, ์ž๋™ ์™„์„ฑ, ๋ฆฐํŒ…, mypy, ๊ทธ๋ฆฌ๊ณ  ์ง๊ด€๊นŒ์ง€๋„ ๊ฒ€์ฆ๋œ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. * **๋ณต์žกํ•œ ๊ตฌ์กฐ**๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค: * ๊ณ„์ธต์ ์ธ Pydantic ๋ชจ๋ธ, Python `typing`์˜ `List`์™€ `Dict` ๋“ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/how-to/authentication-error-status-code.md b/docs/ko/docs/how-to/authentication-error-status-code.md index 47120cae68..e039c073e9 100644 --- a/docs/ko/docs/how-to/authentication-error-status-code.md +++ b/docs/ko/docs/how-to/authentication-error-status-code.md @@ -8,10 +8,10 @@ FastAPI ๋ฒ„์ „ `0.122.0`๋ถ€ํ„ฐ๋Š” ๋” ์ ์ ˆํ•œ HTTP ์ƒํƒœ ์ฝ”๋“œ `401 Unauthor ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ๋ณธ๊ฐ’์ธ `401 Unauthorized` ์˜ค๋ฅ˜ ๋Œ€์‹  `403 Forbidden` ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” `HTTPBearer`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} /// tip | ํŒ -ํ•จ์ˆ˜๋Š” ์˜ˆ์™ธ๋ฅผ `raise`ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์˜ˆ์™ธ ์ธ์Šคํ„ด์Šค๋ฅผ `return`ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š”(`raise`) ์ž‘์—…์€ ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. +ํ•จ์ˆ˜๋Š” ์˜ˆ์™ธ๋ฅผ `return`ํ•˜๋Š” ๊ฒƒ์ด์ง€ `raise`ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š”(`raise`) ์ž‘์—…์€ ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. /// diff --git a/docs/ko/docs/how-to/conditional-openapi.md b/docs/ko/docs/how-to/conditional-openapi.md index 16e6833661..3a87bf010b 100644 --- a/docs/ko/docs/how-to/conditional-openapi.md +++ b/docs/ko/docs/how-to/conditional-openapi.md @@ -4,7 +4,7 @@ ## ๋ณด์•ˆ, API ๋ฐ docs์— ๋Œ€ํ•ด์„œ { #about-security-apis-and-docs } -ํ”„๋กœ๋•์…˜์—์„œ, ๋ฌธ์„œํ™”๋œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(UI)๋ฅผ ์ˆจ๊ธฐ๋Š” ๊ฒƒ์ด API๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด *๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค*. +ํ”„๋กœ๋•์…˜์—์„œ, ๋ฌธ์„œํ™”๋œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(UI)๋ฅผ ์ˆจ๊ธฐ๋Š” ๊ฒƒ์ด API๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” API์— ์ถ”๊ฐ€์ ์ธ ๋ณด์•ˆ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฉฐ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” ์—ฌ์ „ํžˆ ๋™์ผํ•œ ์œ„์น˜์—์„œ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -29,7 +29,7 @@ API๋ฅผ ๋ณดํ˜ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋” ๋‚˜์€ ๋ฐฉ๋ฒ• ์˜ˆ๋ฅผ ๋“ค์–ด: -{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *} +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} ์—ฌ๊ธฐ์„œ `openapi_url` ์„ค์ •์„ ๊ธฐ๋ณธ๊ฐ’์ธ `"/openapi.json"`์œผ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/how-to/configure-swagger-ui.md b/docs/ko/docs/how-to/configure-swagger-ui.md index 174f976f67..b518fd8f72 100644 --- a/docs/ko/docs/how-to/configure-swagger-ui.md +++ b/docs/ko/docs/how-to/configure-swagger-ui.md @@ -18,7 +18,7 @@ FastAPI๋Š” ์ด ๊ตฌ์„ฑ์„ **JSON** ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ JavaScript์™€ ํ˜ธํ™˜ ๊ทธ๋Ÿฌ๋‚˜ `syntaxHighlight`๋ฅผ `False`๋กœ ์„ค์ •ํ•˜์—ฌ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} ...๊ทธ๋Ÿผ Swagger UI์—์„œ ๋” ์ด์ƒ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ๊ธฐ๋Šฅ์ด ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: @@ -28,7 +28,7 @@ FastAPI๋Š” ์ด ๊ตฌ์„ฑ์„ **JSON** ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ JavaScript์™€ ํ˜ธํ™˜ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ `"syntaxHighlight.theme"` ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ํ…Œ๋งˆ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์ค‘๊ฐ„์— ์ ์ด ํฌํ•จ๋œ ๊ฒƒ์„ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค). -{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} ์ด ์„ค์ •์€ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ์ƒ‰์ƒ ํ…Œ๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค: @@ -42,11 +42,11 @@ FastAPI๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ์ ํ•ฉํ•œ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ๋งค {* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} -`swagger_ui_parameters` ์ธ์ˆ˜์— ๋‹ค๋ฅธ ๊ฐ’์„ ์„ค์ •ํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ๊ฐ’ ์ค‘ ์ผ๋ถ€๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`swagger_ui_parameters` ์ธ์ˆ˜์— ๋‹ค๋ฅธ ๊ฐ’์„ ์„ค์ •ํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๊ธฐ๋ณธ๊ฐ’ ์ค‘ ์–ด๋А ๊ฒƒ์ด๋“  ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, `deepLinking`์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `swagger_ui_parameters`์— ๋‹ค์Œ ์„ค์ •์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *} +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} ## ๊ธฐํƒ€ Swagger UI ๋งค๊ฐœ๋ณ€์ˆ˜ { #other-swagger-ui-parameters } diff --git a/docs/ko/docs/how-to/custom-docs-ui-assets.md b/docs/ko/docs/how-to/custom-docs-ui-assets.md index d6383c29cb..7eb4b3cfdb 100644 --- a/docs/ko/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ko/docs/how-to/custom-docs-ui-assets.md @@ -8,7 +8,7 @@ API ๋ฌธ์„œ๋Š” **Swagger UI**์™€ **ReDoc**์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ๊ฐ JavaScript์™€ ## JavaScript์™€ CSS์šฉ ์ปค์Šคํ…€ CDN { #custom-cdn-for-javascript-and-css } -์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ CDN์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด `https://unpkg.com/`์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. +์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ CDN์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด `https://unpkg.com/`์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ๊ตญ๊ฐ€์—์„œ ์ผ๋ถ€ URL์„ ์ œํ•œํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -18,7 +18,7 @@ API ๋ฌธ์„œ๋Š” **Swagger UI**์™€ **ReDoc**์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ๊ฐ JavaScript์™€ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} ### ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs } @@ -34,7 +34,7 @@ FastAPI ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์šฉ HTML ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค... -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} /// tip | ํŒ @@ -50,7 +50,7 @@ Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”: -{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} ### ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-it } @@ -118,7 +118,7 @@ JavaScript์™€ CSS๋ฅผ ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜คํ”„๋ผ์ธ * `StaticFiles`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. * ํŠน์ • ๊ฒฝ๋กœ์— `StaticFiles()` ์ธ์Šคํ„ด์Šค๋ฅผ "๋งˆ์šดํŠธ(mount)"ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} ### ์ •์  ํŒŒ์ผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-the-static-files } @@ -144,7 +144,7 @@ JavaScript์™€ CSS๋ฅผ ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜คํ”„๋ผ์ธ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} ### ์ •์  ํŒŒ์ผ์„ ์œ„ํ•œ ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs-for-static-files } @@ -160,7 +160,7 @@ JavaScript์™€ CSS๋ฅผ ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜คํ”„๋ผ์ธ ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค... -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} /// tip | ํŒ @@ -176,7 +176,7 @@ Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”: -{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} ### ์ •์  ํŒŒ์ผ UI ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #test-static-files-ui } diff --git a/docs/ko/docs/how-to/extending-openapi.md b/docs/ko/docs/how-to/extending-openapi.md index d04d6c23e3..0589e479bf 100644 --- a/docs/ko/docs/how-to/extending-openapi.md +++ b/docs/ko/docs/how-to/extending-openapi.md @@ -43,19 +43,19 @@ ๋จผ์ €, ํ‰์†Œ์ฒ˜๋Ÿผ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ชจ๋‘ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} ### OpenAPI ์Šคํ‚ค๋งˆ ์ƒ์„ฑํ•˜๊ธฐ { #generate-the-openapi-schema } ๊ทธ๋‹ค์Œ `custom_openapi()` ํ•จ์ˆ˜ ์•ˆ์—์„œ, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} ### OpenAPI ์Šคํ‚ค๋งˆ ์ˆ˜์ •ํ•˜๊ธฐ { #modify-the-openapi-schema } ์ด์ œ OpenAPI ์Šคํ‚ค๋งˆ์˜ `info` "object"์— ์ปค์Šคํ…€ `x-logo`๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ReDoc ํ™•์žฅ์„ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} ### OpenAPI ์Šคํ‚ค๋งˆ ์บ์‹œํ•˜๊ธฐ { #cache-the-openapi-schema } @@ -65,13 +65,13 @@ ์Šคํ‚ค๋งˆ๋Š” ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜๊ณ , ์ดํ›„ ์š”์ฒญ์—์„œ๋Š” ๊ฐ™์€ ์บ์‹œ๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} ### ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-method } ์ด์ œ `.openapi()` ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ ํ•จ์ˆ˜๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *} +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} ### ํ™•์ธํ•˜๊ธฐ { #check-it } diff --git a/docs/ko/docs/how-to/graphql.md b/docs/ko/docs/how-to/graphql.md index 3cc467eb71..a960e6d8b2 100644 --- a/docs/ko/docs/how-to/graphql.md +++ b/docs/ko/docs/how-to/graphql.md @@ -35,7 +35,7 @@ ๋‹ค์Œ์€ Strawberry๋ฅผ FastAPI์™€ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *} +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Strawberry ๋ฌธ์„œ์—์„œ Strawberry์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 6e528ecaf5..5dd40cbdc2 100644 --- a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -22,7 +22,7 @@ Pydantic v1์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ค๋ž˜๋œ FastAPI ์•ฑ์ด ์žˆ๋‹ค๋ฉด, ์—ฌ๊ธฐ์„œ๋Š” ์ด ## ๊ณต์‹ ๊ฐ€์ด๋“œ { #official-guide } -Pydantic์—๋Š” v1์—์„œ v2๋กœ์˜ ๊ณต์‹ Migration Guide๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. +Pydantic์—๋Š” v1์—์„œ v2๋กœ์˜ ๊ณต์‹ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ฌด์—‡์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€, ๊ฒ€์ฆ์ด ์ด์ œ ์–ด๋–ป๊ฒŒ ๋” ์ •ํ™•ํ•˜๊ณ  ์—„๊ฒฉํ•ด์กŒ๋Š”์ง€, ๊ฐ€๋Šฅํ•œ ์ฃผ์˜์‚ฌํ•ญ ๋“ฑ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. @@ -30,7 +30,7 @@ Pydantic์—๋Š” v1์—์„œ v2๋กœ์˜ ๊ณต์‹ - +
**Pydantic v2**์˜ ์ด ๊ธฐ๋Šฅ ๋•๋ถ„์— API ๋ฌธ์„œ๋Š” ๋” **์ •๋ฐ€**ํ•ด์ง€๊ณ , ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ์™€ SDK๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ๋“ค๋„ ๋” ์ •๋ฐ€ํ•ด์ ธ์„œ ๋” ๋‚˜์€ **developer experience**์™€ ์ผ๊ด€์„ฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰ diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index 776b8c47c4..d2e08be16f 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -40,7 +40,7 @@ FastAPI๋Š” ํ˜„๋Œ€์ ์ด๊ณ , ๋น ๋ฅด๋ฉฐ(๊ณ ์„ฑ๋Šฅ), ํŒŒ์ด์ฌ ํ‘œ์ค€ ํƒ€์ž… ํžŒํŠธ * **๋น ๋ฆ„**: (Starlette๊ณผ Pydantic ๋•๋ถ„์—) **NodeJS** ๋ฐ **Go**์™€ ๋Œ€๋“ฑํ•  ์ •๋„๋กœ ๋งค์šฐ ๋†’์€ ์„ฑ๋Šฅ. [์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๋น ๋ฅธ ํŒŒ์ด์ฌ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜](#performance). * **๋น ๋ฅธ ์ฝ”๋“œ ์ž‘์„ฑ**: ์•ฝ 200%์—์„œ 300%๊นŒ์ง€ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ ์†๋„ ์ฆ๊ฐ€. * * **์ ์€ ๋ฒ„๊ทธ**: ์‚ฌ๋žŒ(๊ฐœ๋ฐœ์ž)์— ์˜ํ•œ ์—๋Ÿฌ ์•ฝ 40% ๊ฐ์†Œ. * -* **์ง๊ด€์ **: ํ›Œ๋ฅญํ•œ ํŽธ์ง‘๊ธฐ ์ง€์›. ๋ชจ๋“  ๊ณณ์—์„œ ์ž๋™์™„์„ฑ. ์ ์€ ๋””๋ฒ„๊น… ์‹œ๊ฐ„. +* **์ง๊ด€์ **: ํ›Œ๋ฅญํ•œ ํŽธ์ง‘๊ธฐ ์ง€์›. ์ž๋™์™„์„ฑ์ด ๋ชจ๋“  ๊ณณ์—์„œ ๋™์ž‘. ์ ์€ ๋””๋ฒ„๊น… ์‹œ๊ฐ„. * **์‰ฌ์›€**: ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ๋ฐฐ์šฐ๋„๋ก ์„ค๊ณ„. ์ ์€ ๋ฌธ์„œ ์ฝ๊ธฐ ์‹œ๊ฐ„. * **์งง์Œ**: ์ฝ”๋“œ ์ค‘๋ณต ์ตœ์†Œํ™”. ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ์˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ. ์ ์€ ๋ฒ„๊ทธ. * **๊ฒฌ๊ณ ํ•จ**: ์ค€๋น„๋œ ํ”„๋กœ๋•์…˜ ์šฉ ์ฝ”๋“œ๋ฅผ ์–ป์œผ์‹ญ์‹œ์˜ค. ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์™€ ํ•จ๊ป˜. @@ -368,7 +368,7 @@ item: Item * ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ: * ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์„ ๋•Œ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ช…ํ™•ํ•œ ์—๋Ÿฌ. * ๊นŠ์ด ์ค‘์ฒฉ๋œ JSON ๊ฐ์ฒด์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ. -* ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ๋„คํŠธ์›Œํฌ์—์„œ ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์œผ๋กœ ์ „์†ก. ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค: +* ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ๋„คํŠธ์›Œํฌ์—์„œ ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์œผ๋กœ ์ „์†ก. ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค: * JSON. * ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜. * ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜. @@ -376,7 +376,7 @@ item: Item * ํ—ค๋”. * ํผ(Forms). * ํŒŒ์ผ. -* ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์„ ๋„คํŠธ์›Œํฌ ๋ฐ์ดํ„ฐ๋กœ ์ „ํ™˜(JSON ํ˜•์‹์œผ๋กœ): +* ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: ํŒŒ์ด์ฌ ๋ฐ์ดํ„ฐ ๋ฐ ํƒ€์ž…์„ ๋„คํŠธ์›Œํฌ ๋ฐ์ดํ„ฐ๋กœ ์ „ํ™˜(JSON ํ˜•์‹์œผ๋กœ): * ํŒŒ์ด์ฌ ํƒ€์ž… ๋ณ€ํ™˜ (`str`, `int`, `float`, `bool`, `list`, ๋“ฑ). * `datetime` ๊ฐ์ฒด. * `UUID` ๊ฐ์ฒด. @@ -439,7 +439,7 @@ item: Item * ์„œ๋กœ ๋‹ค๋ฅธ ์žฅ์†Œ์—์„œ **๋งค๊ฐœ๋ณ€์ˆ˜** ์„ ์–ธ: **ํ—ค๋”**, **์ฟ ํ‚ค**, **ํผ ํ•„๋“œ** ๊ทธ๋ฆฌ๊ณ  **ํŒŒ์ผ**. * `maximum_length` ๋˜๋Š” `regex`์ฒ˜๋Ÿผ **์œ ํšจ์„ฑ ์ œ์•ฝ**ํ•˜๋Š” ๋ฐฉ๋ฒ•. -* ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด **์˜์กด์„ฑ ์ฃผ์ž…** ์‹œ์Šคํ…œ. +* ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด **์˜์กด์„ฑ ์ฃผ์ž…** ์‹œ์Šคํ…œ. * **OAuth2** ์ง€์›์„ ํฌํ•จํ•œ **JWT tokens** ๋ฐ **HTTP Basic**์„ ๊ฐ–๋Š” ๋ณด์•ˆ๊ณผ ์ธ์ฆ. * (Pydantic ๋•๋ถ„์—) **๊นŠ์€ ์ค‘์ฒฉ JSON ๋ชจ๋ธ**์„ ์„ ์–ธํ•˜๋Š”๋ฐ ๋” ์ง„๋ณดํ•œ (ํ•˜์ง€๋งŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‰ฌ์šด) ๊ธฐ์ˆ . * Strawberry ๋ฐ ๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ **GraphQL** ํ†ตํ•ฉ. @@ -524,7 +524,7 @@ Starlette์ด ์‚ฌ์šฉํ•˜๋Š”: * httpx - `TestClient`๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ•„์š”. * jinja2 - ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ ์„ค์ •์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ•„์š”. -* python-multipart - `request.form()`๊ณผ ํ•จ๊ป˜ form "parsing" ์ง€์›์„ ์›ํ•˜๋ฉด ํ•„์š”. +* python-multipart - `request.form()`๊ณผ ํ•จ๊ป˜ form "ํŒŒ์‹ฑ" ์ง€์›์„ ์›ํ•˜๋ฉด ํ•„์š”. FastAPI๊ฐ€ ์‚ฌ์šฉํ•˜๋Š”: diff --git a/docs/ko/docs/project-generation.md b/docs/ko/docs/project-generation.md index 73ea67d3e5..e3120e6f80 100644 --- a/docs/ko/docs/project-generation.md +++ b/docs/ko/docs/project-generation.md @@ -2,7 +2,7 @@ ํ…œํ”Œ๋ฆฟ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํŠน์ • ์„ค์ •๊ณผ ํ•จ๊ป˜ ์ œ๊ณต๋˜์ง€๋งŒ, ์œ ์—ฐํ•˜๊ณ  ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋””์ž์ธ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠน์„ฑ๋“ค์€ ์—ฌ๋Ÿฌ๋ถ„์ด ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ์ˆ˜์ •, ์ ์šฉ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ณ , ํ…œํ”Œ๋ฆฟ์ด ์™„๋ฒฝํ•œ ์‹œ์ž‘์ ์ด ๋˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๐Ÿ -๋งŽ์€ ์ดˆ๊ธฐ ์„ค์ •, ๋ณด์•ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ์ผ๋ถ€ API ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์ด๋ฏธ ์ค€๋น„๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ด ํ…œํ”Œ๋ฆฟ์„ (ํ”„๋กœ์ ํŠธ๋ฅผ) ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋งŽ์€ ์ดˆ๊ธฐ ์„ค์ •, ๋ณด์•ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ์ผ๋ถ€ API ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์ด๋ฏธ ์ค€๋น„๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ด ํ…œํ”Œ๋ฆฟ์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GitHub ์ €์žฅ์†Œ: Full Stack FastAPI ํ…œํ”Œ๋ฆฟ diff --git a/docs/ko/docs/python-types.md b/docs/ko/docs/python-types.md index dc264df805..d7d9021ed3 100644 --- a/docs/ko/docs/python-types.md +++ b/docs/ko/docs/python-types.md @@ -2,7 +2,7 @@ ํŒŒ์ด์ฌ์€ ์„ ํƒ์ ์œผ๋กœ "ํƒ€์ž… ํžŒํŠธ(type hints)"(โ€œtype annotationsโ€๋ผ๊ณ ๋„ ํ•จ)๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. -์ด๋Ÿฌํ•œ **"ํƒ€์ž… ํžŒํŠธ"** ๋˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜์€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํŠน์ˆ˜ํ•œ ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ **"ํƒ€์ž… ํžŒํŠธ"** ๋˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜์€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํŠน์ˆ˜ํ•œ ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋ฉด ์—๋””ํ„ฐ์™€ ๋„๊ตฌ๊ฐ€ ๋” ๋‚˜์€ ์ง€์›์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -22,7 +22,7 @@ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋กœ ์‹œ์ž‘ํ•ด๋ด…์‹œ๋‹ค: -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} ์ด ํ”„๋กœ๊ทธ๋žจ์„ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค: @@ -34,9 +34,9 @@ John Doe * `first_name`๊ณผ `last_name`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. * `title()`๋กœ ๊ฐ๊ฐ์˜ ์ฒซ ๊ธ€์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -* ๊ฐ€์šด๋ฐ์— ๊ณต๋ฐฑ์„ ๋‘๊ณ  ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. +* ๊ฐ€์šด๋ฐ์— ๊ณต๋ฐฑ์„ ๋‘๊ณ  ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} ### ์ˆ˜์ •ํ•˜๊ธฐ { #edit-it } @@ -80,7 +80,7 @@ John Doe ์ด๊ฒƒ๋“ค์ด "ํƒ€์ž… ํžŒํŠธ"์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} ์ด๊ฒƒ์€ ๋‹ค์Œ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค: @@ -108,7 +108,7 @@ John Doe ์ด ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”. ์ด๋ฏธ ํƒ€์ž… ํžŒํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} ์—๋””ํ„ฐ๊ฐ€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ž๋™์™„์„ฑ๋งŒ ๋˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์˜ค๋ฅ˜ ๊ฒ€์‚ฌ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: @@ -116,7 +116,7 @@ John Doe ์ด์ œ ๊ณ ์ณ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ , `age`๋ฅผ `str(age)`๋กœ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *} +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} ## ํƒ€์ž… ์„ ์–ธ { #declaring-types } @@ -135,29 +135,32 @@ John Doe * `bool` * `bytes` -{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} -### ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” Generic(์ œ๋„ค๋ฆญ) ํƒ€์ž… { #generic-types-with-type-parameters } +### `typing` ๋ชจ๋“ˆ { #typing-module } -`dict`, `list`, `set`, `tuple`์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๊ฐ’์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด๋ถ€ ๊ฐ’์—๋„ ๊ฐ์ž์˜ ํƒ€์ž…์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ `typing` ๋ชจ๋“ˆ์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ importํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค ๊ฐ’์ด "์•„๋ฌด ํƒ€์ž…"์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•˜๋ ค๋ฉด, `typing`์˜ `Any`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -์ด๋ ‡๊ฒŒ ๋‚ด๋ถ€ ํƒ€์ž…์„ ๊ฐ€์ง€๋Š” ํƒ€์ž…์„ "**generic**" ํƒ€์ž…์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด๋ถ€ ํƒ€์ž…๊นŒ์ง€ ํฌํ•จํ•ด ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +```python +from typing import Any -์ด๋Ÿฐ ํƒ€์ž…๊ณผ ๋‚ด๋ถ€ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋ ค๋ฉด ํ‘œ์ค€ ํŒŒ์ด์ฌ ๋ชจ๋“ˆ `typing`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ชจ๋“ˆ์€ ์ด๋Ÿฌํ•œ ํƒ€์ž… ํžŒํŠธ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. -#### ๋” ์ตœ์‹  ๋ฒ„์ „์˜ Python { #newer-versions-of-python } - -`typing`์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ๋ฒ•์€ Python 3.6๋ถ€ํ„ฐ ์ตœ์‹  ๋ฒ„์ „๊นŒ์ง€, Python 3.9, Python 3.10 ๋“ฑ์„ ํฌํ•จํ•œ ๋ชจ๋“  ๋ฒ„์ „๊ณผ **ํ˜ธํ™˜**๋ฉ๋‹ˆ๋‹ค. +def some_function(data: Any): + print(data) +``` -ํŒŒ์ด์ฌ์ด ๋ฐœ์ „ํ•จ์— ๋”ฐ๋ผ **๋” ์ตœ์‹  ๋ฒ„์ „**์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜ ์ง€์›์ด ๊ฐœ์„ ๋˜๋ฉฐ, ๋งŽ์€ ๊ฒฝ์šฐ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด `typing` ๋ชจ๋“ˆ์„ importํ•ด์„œ ์‚ฌ์šฉํ•  ํ•„์š”์กฐ์ฐจ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +### Generic(์ œ๋„ค๋ฆญ) ํƒ€์ž… { #generic-types } -ํ”„๋กœ์ ํŠธ์—์„œ ๋” ์ตœ์‹  ๋ฒ„์ „์˜ ํŒŒ์ด์ฌ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ๊ทธ ์ถ”๊ฐ€์ ์ธ ๋‹จ์ˆœํ•จ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ผ๋ถ€ ํƒ€์ž…์€ ๋Œ€๊ด„ํ˜ธ ์•ˆ์— "ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜"๋ฅผ ๋ฐ›์•„ ๋‚ด๋ถ€ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "๋ฌธ์ž์—ด์˜ ๋ฆฌ์ŠคํŠธ"๋Š” `list[str]`๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. -์ด ๋ฌธ์„œ ์ „์ฒด์—๋Š” ๊ฐ ํŒŒ์ด์ฌ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๋Š” ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ฐจ์ด๊ฐ€ ์žˆ์„ ๋•Œ). +์ด๋ ‡๊ฒŒ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์„ **Generic types** ๋˜๋Š” **Generics**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด "**Python 3.6+**"๋Š” Python 3.6 ์ด์ƒ(3.7, 3.8, 3.9, 3.10 ๋“ฑ ํฌํ•จ)๊ณผ ํ˜ธํ™˜๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  "**Python 3.9+**"๋Š” Python 3.9 ์ด์ƒ(3.10 ๋“ฑ ํฌํ•จ)๊ณผ ํ˜ธํ™˜๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. +๋Œ€๊ด„ํ˜ธ์™€ ๋‚ด๋ถ€ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ๋™์ผํ•œ ๋‚ด์žฅ ํƒ€์ž…๋“ค์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -**์ตœ์‹  ๋ฒ„์ „์˜ Python**์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ตœ์‹  ๋ฒ„์ „์šฉ ์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด "**Python 3.10+**"์ฒ˜๋Ÿผ, ๊ฐ€์žฅ **์ข‹๊ณ  ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฌธ๋ฒ•**์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +* `list` +* `tuple` +* `set` +* `dict` #### List { #list } @@ -169,7 +172,7 @@ John Doe `list`๋Š” ๋‚ด๋ถ€ ํƒ€์ž…์„ ํฌํ•จํ•˜๋Š” ํƒ€์ž…์ด๋ฏ€๋กœ, ๊ทธ ํƒ€์ž…๋“ค์„ ๋Œ€๊ด„ํ˜ธ ์•ˆ์— ๋„ฃ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} /// info | ์ •๋ณด @@ -195,7 +198,7 @@ John Doe `tuple`๊ณผ `set`๋„ ๋™์ผํ•˜๊ฒŒ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} ์ด๋Š” ๋‹ค์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค: @@ -210,7 +213,7 @@ John Doe ๋‘ ๋ฒˆ์งธ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” `dict`์˜ ๊ฐ’์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} ์ด๋Š” ๋‹ค์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค: @@ -222,44 +225,20 @@ John Doe ๋ณ€์ˆ˜๊ฐ€ **์—ฌ๋Ÿฌ ํƒ€์ž… ์ค‘ ์–ด๋–ค ๊ฒƒ์ด๋“ ** ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `int` ๋˜๋Š” `str`์ž…๋‹ˆ๋‹ค. -Python 3.6 ์ด์ƒ(3.10 ํฌํ•จ)์—์„œ๋Š” `typing`์˜ `Union` ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ณ , ๋Œ€๊ด„ํ˜ธ ์•ˆ์— ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…๋“ค์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - -Python 3.10์—๋Š” ๊ฐ€๋Šฅํ•œ ํƒ€์ž…๋“ค์„ ์„ธ๋กœ ๋ง‰๋Œ€(`|`)๋กœ ๊ตฌ๋ถ„ํ•ด ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” **์ƒˆ ๋ฌธ๋ฒ•**๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด ๋‘ ํƒ€์ž…์„ ์„ธ๋กœ ๋ง‰๋Œ€(`|`)๋กœ ๊ตฌ๋ถ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -//// tab | Python 3.10+ +์ด๋Š” ๋‘ ํƒ€์ž… ์ง‘ํ•ฉ์˜ ํ•ฉ์ง‘ํ•ฉ(union) ์•ˆ์˜ ์–ด๋А ๊ฒƒ์ด๋“  ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋ฏ€๋กœ "์œ ๋‹ˆ์˜จ"์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -//// - -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial008b_py39.py!} -``` - -//// - -๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์ด๋Š” `item`์ด `int` ๋˜๋Š” `str`์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. +์ด๋Š” `item`์ด `int` ๋˜๋Š” `str`์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. #### `None`์ผ ์ˆ˜๋„ ์žˆ์Œ { #possibly-none } ๊ฐ’์ด `str` ๊ฐ™์€ ํƒ€์ž…์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, `None`์ผ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -Python 3.6 ์ด์ƒ(3.10 ํฌํ•จ)์—์„œ๋Š” `typing` ๋ชจ๋“ˆ์—์„œ `Optional`์„ importํ•ด์„œ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - -```Python hl_lines="1 4" -{!../../docs_src/python_types/tutorial009_py39.py!} -``` - -๊ทธ๋ƒฅ `str` ๋Œ€์‹  `Optional[str]`์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐ’์ด ํ•ญ์ƒ `str`์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” `None`์ผ ์ˆ˜๋„ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ ์—๋””ํ„ฐ๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. - -`Optional[Something]`์€ ์‚ฌ์‹ค `Union[Something, None]`์˜ ์ถ•์•ฝ์ด๋ฉฐ, ์„œ๋กœ ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค. - -๋˜ํ•œ ์ด๋Š” Python 3.10์—์„œ `Something | None`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค: - //// tab | Python 3.10+ ```Python hl_lines="1" @@ -268,96 +247,7 @@ Python 3.6 ์ด์ƒ(3.10 ํฌํ•จ)์—์„œ๋Š” `typing` ๋ชจ๋“ˆ์—์„œ `Optional`์„ impo //// -//// tab | Python 3.9+ - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009_py39.py!} -``` - -//// - -//// tab | Python 3.9+ alternative - -```Python hl_lines="1 4" -{!> ../../docs_src/python_types/tutorial009b_py39.py!} -``` - -//// - -#### `Union` ๋˜๋Š” `Optional` ์‚ฌ์šฉํ•˜๊ธฐ { #using-union-or-optional } - -Python 3.10 ๋ฏธ๋งŒ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์•„์ฃผ **์ฃผ๊ด€์ ์ธ** ๊ด€์ ์—์„œ์˜ ํŒ์ž…๋‹ˆ๋‹ค: - -* ๐Ÿšจ `Optional[SomeType]` ์‚ฌ์šฉ์„ ํ”ผํ•˜์„ธ์š” -* ๋Œ€์‹  โœจ **`Union[SomeType, None]`์„ ์‚ฌ์šฉํ•˜์„ธ์š”** โœจ. - -๋‘˜์€ ๋™๋“ฑํ•˜๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๊ฐ™์€ ๊ฒƒ์ด์ง€๋งŒ, `Optional`์ด๋ผ๋Š” ๋‹จ์–ด๊ฐ€ ๊ฐ’์ด ์„ ํƒ ์‚ฌํ•ญ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— `Optional` ๋Œ€์‹  `Union`์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์˜๋ฏธ๋Š” ๊ฐ’์ด ์„ ํƒ ์‚ฌํ•ญ์ด๋ผ๋Š” ๋œป์ด ์•„๋‹ˆ๋ผ, "๊ฐ’์ด `None`์ผ ์ˆ˜ ์žˆ๋‹ค"๋Š” ๋œป์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์„ ํƒ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๊ณ  ์—ฌ์ „ํžˆ ํ•„์ˆ˜์ธ ๊ฒฝ์šฐ์—๋„์š”. - -`Union[SomeType, None]`์ด ์˜๋ฏธ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ธ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. - -์ด๊ฑด ๋‹จ์ง€ ๋‹จ์–ด์™€ ์ด๋ฆ„์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋Ÿฐ ๋‹จ์–ด๋“ค์ด ์—ฌ๋Ÿฌ๋ถ„๊ณผ ํŒ€์›์ด ์ฝ”๋“œ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - -์˜ˆ๋กœ, ์ด ํ•จ์ˆ˜๋ฅผ ๋ด…์‹œ๋‹ค: - -{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *} - -๋งค๊ฐœ๋ณ€์ˆ˜ `name`์€ `Optional[str]`๋กœ ์ •์˜๋˜์–ด ์žˆ์ง€๋งŒ, **์„ ํƒ ์‚ฌํ•ญ์ด ์•„๋‹™๋‹ˆ๋‹ค**. ๋งค๊ฐœ๋ณ€์ˆ˜ ์—†์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: - -```Python -say_hi() # Oh, no, this throws an error! ๐Ÿ˜ฑ -``` - -๊ธฐ๋ณธ๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— `name` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” **์—ฌ์ „ํžˆ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค**(*optional*์ด ์•„๋‹˜). ๊ทธ๋Ÿผ์—๋„ `name`์€ ๊ฐ’์œผ๋กœ `None`์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค: - -```Python -say_hi(name=None) # This works, None is valid ๐ŸŽ‰ -``` - -์ข‹์€ ์†Œ์‹์€ Python 3.10์„ ์‚ฌ์šฉํ•˜๋ฉด, ํƒ€์ž…์˜ ์œ ๋‹ˆ์˜จ์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํžˆ `|`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ด๋Ÿฐ ๊ฑฑ์ •์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค: - -{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} - -๊ทธ๋Ÿฌ๋ฉด `Optional`์ด๋‚˜ `Union` ๊ฐ™์€ ์ด๋ฆ„์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž - -#### Generic(์ œ๋„ค๋ฆญ) ํƒ€์ž… { #generic-types } - -๋Œ€๊ด„ํ˜ธ ์•ˆ์— ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ์ด๋Ÿฌํ•œ ํƒ€์ž…๋“ค์€ **Generic types** ๋˜๋Š” **Generics**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด: - -//// tab | Python 3.10+ - -๋Œ€๊ด„ํ˜ธ์™€ ๋‚ด๋ถ€ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด, ๋™์ผํ•œ ๋‚ด์žฅ ํƒ€์ž…๋“ค์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - -* `list` -* `tuple` -* `set` -* `dict` - -๊ทธ๋ฆฌ๊ณ  ์ด์ „ ํŒŒ์ด์ฌ ๋ฒ„์ „๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ `typing` ๋ชจ๋“ˆ์˜ ๋‹ค์Œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - -* `Union` -* `Optional` -* ...๊ทธ ๋ฐ–์˜ ๊ฒƒ๋“ค. - -Python 3.10์—์„œ๋Š” ์ œ๋„ค๋ฆญ `Union`๊ณผ `Optional`์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์œผ๋กœ, ํƒ€์ž… ์œ ๋‹ˆ์˜จ์„ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด ์„ธ๋กœ ๋ง‰๋Œ€(`|`)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ›จ์”ฌ ๋” ์ข‹๊ณ  ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. - -//// - -//// tab | Python 3.9+ - -๋Œ€๊ด„ํ˜ธ์™€ ๋‚ด๋ถ€ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด, ๋™์ผํ•œ ๋‚ด์žฅ ํƒ€์ž…๋“ค์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - -* `list` -* `tuple` -* `set` -* `dict` - -๊ทธ๋ฆฌ๊ณ  `typing` ๋ชจ๋“ˆ์˜ ์ œ๋„ค๋ฆญ๋“ค: - -* `Union` -* `Optional` -* ...๊ทธ ๋ฐ–์˜ ๊ฒƒ๋“ค. - -//// +๊ทธ๋ƒฅ `str` ๋Œ€์‹  `str | None`์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐ’์ด ํ•ญ์ƒ `str`์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” `None`์ผ ์ˆ˜๋„ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ ์—๋””ํ„ฐ๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ### ํƒ€์ž…์œผ๋กœ์„œ์˜ ํด๋ž˜์Šค { #classes-as-types } @@ -365,11 +255,11 @@ Python 3.10์—์„œ๋Š” ์ œ๋„ค๋ฆญ `Union`๊ณผ `Optional`์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์œผ ์ด๋ฆ„์„ ๊ฐ€์ง„ `Person` ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: -{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} ๊ทธ๋Ÿฌ๋ฉด `Person` ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *} +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} ๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ, ์—๋””ํ„ฐ์˜ ๋ชจ๋“  ์ง€์›์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: @@ -405,19 +295,13 @@ Pydantic ๊ณต์‹ ๋ฌธ์„œ์˜ ์˜ˆ์‹œ: ์ด ๋ชจ๋“  ๊ฒƒ์€ [์ž์Šต์„œ - ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ](tutorial/index.md){.internal-link target=_blank}์—์„œ ์‹ค์ œ๋กœ ๋งŽ์ด ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -/// tip | ํŒ - -Pydantic์€ ๊ธฐ๋ณธ๊ฐ’ ์—†์ด `Optional` ๋˜๋Š” `Union[Something, None]`์„ ์‚ฌ์šฉํ•  ๋•Œ ํŠน๋ณ„ํ•œ ๋™์ž‘์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด์„œ๋Š” Pydantic ๋ฌธ์„œ์˜ Required Optional fields์—์„œ ๋” ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - -/// - ## ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์• ๋„ˆํ…Œ์ด์…˜์ด ์žˆ๋Š” ํƒ€์ž… ํžŒํŠธ { #type-hints-with-metadata-annotations } -ํŒŒ์ด์ฌ์—๋Š” `Annotated`๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋Ÿฌํ•œ ํƒ€์ž… ํžŒํŠธ์— **์ถ”๊ฐ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ**๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. +ํŒŒ์ด์ฌ์—๋Š” `Annotated`๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋Ÿฌํ•œ ํƒ€์ž… ํžŒํŠธ์— **์ถ”๊ฐ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ**๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -Python 3.9๋ถ€ํ„ฐ `Annotated`๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ผ๋ถ€์ด๋ฏ€๋กœ, `typing`์—์„œ importํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`Annotated`๋Š” `typing`์—์„œ importํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *} +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} ํŒŒ์ด์ฌ ์ž์ฒด๋Š” ์ด `Annotated`๋กœ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—๋””ํ„ฐ์™€ ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค์—๊ฒŒ๋Š” ํƒ€์ž…์ด ์—ฌ์ „ํžˆ `str`์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/resources/index.md b/docs/ko/docs/resources/index.md index 477b93a584..f8ec8dddde 100644 --- a/docs/ko/docs/resources/index.md +++ b/docs/ko/docs/resources/index.md @@ -1,3 +1,3 @@ # ๋ฆฌ์†Œ์Šค { #resources } -์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค, ์™ธ๋ถ€ ๋งํฌ ๋“ฑ. โœˆ๏ธ +์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค, ์™ธ๋ถ€ ๋งํฌ, ๊ทธ๋ฆฌ๊ณ  ๋” ๋งŽ์€ ์ž๋ฃŒ. โœˆ๏ธ diff --git a/docs/ko/docs/translation-banner.md b/docs/ko/docs/translation-banner.md new file mode 100644 index 0000000000..7bcd907d56 --- /dev/null +++ b/docs/ko/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | ๐ŸŒ AI์™€ ์‚ฌ๋žŒ์ด ํ•จ๊ป˜ํ•œ ๋ฒˆ์—ญ + +์ด ๋ฒˆ์—ญ์€ ์‚ฌ๋žŒ์˜ ์•ˆ๋‚ด๋ฅผ ๋ฐ›์•„ AI๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค + +์›๋ฌธ์˜ ์˜๋ฏธ๋ฅผ ์˜คํ•ดํ•˜๊ฑฐ๋‚˜ ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์›Œ ๋ณด์ด๋Š” ๋“ฑ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค– + +[AI LLM์„ ๋” ์ž˜ ์•ˆ๋‚ดํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์„ธ์š”](https://fastapi.tiangolo.com/ko/contributing/#translations). + +[์˜๋ฌธ ๋ฒ„์ „](ENGLISH_VERSION_URL) + +/// diff --git a/docs/ko/docs/tutorial/background-tasks.md b/docs/ko/docs/tutorial/background-tasks.md index 9e868f2fa7..f23902e11f 100644 --- a/docs/ko/docs/tutorial/background-tasks.md +++ b/docs/ko/docs/tutorial/background-tasks.md @@ -15,7 +15,7 @@ FastAPI์—์„œ๋Š” ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ *ํ›„์—* ์‹คํ–‰ํ•  ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… ๋จผ์ € `BackgroundTasks`๋ฅผ ์ž„ํฌํŠธํ•˜๊ณ , `BackgroundTasks` ํƒ€์ž… ์„ ์–ธ์œผ๋กœ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} **FastAPI**๊ฐ€ `BackgroundTasks` ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. @@ -31,13 +31,13 @@ FastAPI์—์„œ๋Š” ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ *ํ›„์—* ์‹คํ–‰ํ•  ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… ๊ทธ๋ฆฌ๊ณ  ์“ฐ๊ธฐ ์ž‘์—…์€ `async`์™€ `await`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ผ๋ฐ˜ `def`๋กœ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} ## ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… ์ถ”๊ฐ€ { #add-the-background-task } *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ๋‚ด๋ถ€์—์„œ `.add_task()` ๋ฉ”์„œ๋“œ๋กœ ์ž‘์—… ํ•จ์ˆ˜๋ฅผ *๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…* ๊ฐ์ฒด์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *} +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} `.add_task()`๋Š” ๋‹ค์Œ ์ธ์ž๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md index cfc3900d4c..1b9d17e49a 100644 --- a/docs/ko/docs/tutorial/bigger-applications.md +++ b/docs/ko/docs/tutorial/bigger-applications.md @@ -58,17 +58,17 @@ from app.routers import items ```bash . -โ”œโ”€โ”€ app # "app" is a Python package -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # this file makes "app" a "Python package" -โ”‚ย ย  โ”œโ”€โ”€ main.py # "main" module, e.g. import app.main -โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # "dependencies" module, e.g. import app.dependencies -โ”‚ย ย  โ””โ”€โ”€ routers # "routers" is a "Python subpackage" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # makes "routers" a "Python subpackage" -โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # "items" submodule, e.g. import app.routers.items -โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # "users" submodule, e.g. import app.routers.users -โ”‚ย ย  โ””โ”€โ”€ internal # "internal" is a "Python subpackage" -โ”‚ย ย  โ”œโ”€โ”€ __init__.py # makes "internal" a "Python subpackage" -โ”‚ย ย  โ””โ”€โ”€ admin.py # "admin" submodule, e.g. import app.internal.admin +โ”œโ”€โ”€ app # 'app'์€ Python ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ์ด ํŒŒ์ผ๋กœ 'app'์ด 'Python ํŒจํ‚ค์ง€'๊ฐ€ ๋ฉ๋‹ˆ๋‹ค +โ”‚ย ย  โ”œโ”€โ”€ main.py # 'main' ๋ชจ๋“ˆ, ์˜ˆ: import app.main +โ”‚ย ย  โ”œโ”€โ”€ dependencies.py # 'dependencies' ๋ชจ๋“ˆ, ์˜ˆ: import app.dependencies +โ”‚ย ย  โ””โ”€โ”€ routers # 'routers'๋Š” 'Python ํ•˜์œ„ ํŒจํ‚ค์ง€'์ž…๋‹ˆ๋‹ค +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ __init__.py # ์ด ํŒŒ์ผ๋กœ 'routers'๊ฐ€ 'Python ํ•˜์œ„ ํŒจํ‚ค์ง€'๊ฐ€ ๋ฉ๋‹ˆ๋‹ค +โ”‚ย ย  โ”‚ โ”œโ”€โ”€ items.py # 'items' ์„œ๋ธŒ๋ชจ๋“ˆ, ์˜ˆ: import app.routers.items +โ”‚ย ย  โ”‚ โ””โ”€โ”€ users.py # 'users' ์„œ๋ธŒ๋ชจ๋“ˆ, ์˜ˆ: import app.routers.users +โ”‚ย ย  โ””โ”€โ”€ internal # 'internal'์€ 'Python ํ•˜์œ„ ํŒจํ‚ค์ง€'์ž…๋‹ˆ๋‹ค +โ”‚ย ย  โ”œโ”€โ”€ __init__.py # ์ด ํŒŒ์ผ๋กœ 'internal'์ด 'Python ํ•˜์œ„ ํŒจํ‚ค์ง€'๊ฐ€ ๋ฉ๋‹ˆ๋‹ค +โ”‚ย ย  โ””โ”€โ”€ admin.py # 'admin' ์„œ๋ธŒ๋ชจ๋“ˆ, ์˜ˆ: import app.internal.admin ``` ## `APIRouter` { #apirouter } @@ -85,7 +85,7 @@ from app.routers import items `FastAPI` ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ importํ•˜๊ณ  "instance"๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} ### `APIRouter`๋กœ *path operations* ๋งŒ๋“ค๊ธฐ { #path-operations-with-apirouter } @@ -93,7 +93,7 @@ from app.routers import items `FastAPI` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} `APIRouter`๋Š” "๋ฏธ๋‹ˆ `FastAPI`" ํด๋ž˜์Šค๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -117,7 +117,7 @@ from app.routers import items ์ด์ œ ๊ฐ„๋‹จํ•œ dependency๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ `X-Token` ํ—ค๋”๋ฅผ ์ฝ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} /// tip | ํŒ @@ -149,7 +149,7 @@ from app.routers import items ๋”ฐ๋ผ์„œ ๊ฐ *path operation*๋งˆ๋‹ค ๋งค๋ฒˆ ๋ชจ๋‘ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹ , `APIRouter`์— ํ•œ ๋ฒˆ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} ๊ฐ *path operation*์˜ ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ `/`๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๋ฏ€๋กœ: @@ -208,7 +208,7 @@ async def read_item(item_id: str): ๊ทธ๋ž˜์„œ dependencies์— ๋Œ€ํ•ด `..`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒ๋Œ€ import๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} #### ์ƒ๋Œ€ import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-relative-imports-work } @@ -279,7 +279,7 @@ from ...dependencies import get_token_header ํ•˜์ง€๋งŒ ํŠน์ • *path operation*์—๋งŒ ์ ์šฉ๋  _์ถ”๊ฐ€_ `tags`๋ฅผ ๋”ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ทธ *path operation* ์ „์šฉ์˜ ์ถ”๊ฐ€ `responses`๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} /// tip | ํŒ @@ -305,13 +305,13 @@ from ...dependencies import get_token_header ๋˜ํ•œ ๊ฐ `APIRouter`์˜ dependencies์™€ ๊ฒฐํ•ฉ๋  [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}๋„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} ### `APIRouter` importํ•˜๊ธฐ { #import-the-apirouter } ์ด์ œ `APIRouter`๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ submodule๋“ค์„ importํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} `app/routers/users.py`์™€ `app/routers/items.py` ํŒŒ์ผ์€ ๊ฐ™์€ Python package `app`์— ์†ํ•œ submodule๋“ค์ด๋ฏ€๋กœ, ์  ํ•˜๋‚˜ `.`๋ฅผ ์‚ฌ์šฉํ•ด "์ƒ๋Œ€ import"๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -374,13 +374,13 @@ from .routers.users import router ๋”ฐ๋ผ์„œ ๊ฐ™์€ ํŒŒ์ผ์—์„œ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก submodule๋“ค์„ ์ง์ ‘ importํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} ### `users`์™€ `items`์šฉ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-the-apirouters-for-users-and-items } ์ด์ œ submodule `users`์™€ `items`์˜ `router`๋ฅผ ํฌํ•จํ•ด ๋ด…์‹œ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} /// info | ์ •๋ณด @@ -394,7 +394,7 @@ from .routers.users import router ๊ทธ router์˜ ๋ชจ๋“  route๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. -/// note Technical Details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” `APIRouter`์— ์„ ์–ธ๋œ ๊ฐ *path operation*๋งˆ๋‹ค *path operation*์„ ์‹ค์ œ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. @@ -420,13 +420,13 @@ router๋ฅผ ํฌํ•จ(include)ํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์™€ ๊ณต์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์–ด `prefix`, `dependencies`, `tags` ๋“ฑ์„ `APIRouter`์— ์ง์ ‘ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ํ•˜์ง€๋งŒ `APIRouter`๋ฅผ ํฌํ•จํ•  ๋•Œ ์ปค์Šคํ…€ `prefix`๋ฅผ ์ง€์ •ํ•ด ๋ชจ๋“  *path operations*๊ฐ€ `/admin`์œผ๋กœ ์‹œ์ž‘ํ•˜๊ฒŒ ํ•˜๊ณ , ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ด๋ฏธ ๊ฐ€์ง„ `dependencies`๋กœ ๋ณดํ˜ธํ•˜๊ณ , `tags`์™€ `responses`๋„ ํฌํ•จํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์›๋ž˜ `APIRouter`๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ `app.include_router()`์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์„œ ์ด๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›๋ž˜ `APIRouter`๋Š” ์ˆ˜์ •๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ๋™์ผํ•œ `app/internal/admin.py` ํŒŒ์ผ์„ ๊ณ„์† ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -447,11 +447,11 @@ router๋ฅผ ํฌํ•จ(include)ํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด... ๊ทธ๋ƒฅ ํ•ด๋ด…๋‹ˆ๋‹ค ๐Ÿคท: -{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} ๊ทธ๋ฆฌ๊ณ  `app.include_router()`๋กœ ์ถ”๊ฐ€ํ•œ ๋‹ค๋ฅธ ๋ชจ๋“  *path operations*์™€ ํ•จ๊ป˜ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. -/// info | ์ •๋ณด +/// info | ๋งค์šฐ ๊ธฐ์ˆ ์ ์ธ ์„ธ๋ถ€์‚ฌํ•ญ **์ฐธ๊ณ **: ์ด๋Š” ๋งค์šฐ ๊ธฐ์ˆ ์ ์ธ ์„ธ๋ถ€์‚ฌํ•ญ์ด๋ผ ์•„๋งˆ **๊ทธ๋ƒฅ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค**. diff --git a/docs/ko/docs/tutorial/body-fields.md b/docs/ko/docs/tutorial/body-fields.md index c98734ab37..0774dc4413 100644 --- a/docs/ko/docs/tutorial/body-fields.md +++ b/docs/ko/docs/tutorial/body-fields.md @@ -48,8 +48,8 @@ /// warning | ๊ฒฝ๊ณ  -๋ณ„๋„ ํ‚ค๊ฐ€ ์ „๋‹ฌ๋œ `Field` ๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ OpenAPI ์Šคํ‚ค๋งˆ์— ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -์ด๋Ÿฐ ํ‚ค๊ฐ€ OpenAPI ๋ช…์„ธ์„œ, [the OpenAPI validator](https://validator.swagger.io/)๊ฐ™์€ ๋ช‡๋ช‡ OpenAPI ๋„๊ตฌ๋“ค์— ํฌํ•จ๋˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ์„ฑํ•œ ์Šคํ‚ค๋งˆ์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋ณ„๋„ ํ‚ค๊ฐ€ ์ „๋‹ฌ๋œ `Field` ๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ OpenAPI ์Šคํ‚ค๋งˆ์— ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +์ด๋Ÿฐ ํ‚ค๊ฐ€ OpenAPI ๋ช…์„ธ์„œ์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ ์ˆ˜๋„ ์žˆ์œผ๋ฏ€๋กœ, [OpenAPI validator](https://validator.swagger.io/) ๊ฐ™์€ ๋ช‡๋ช‡ OpenAPI ๋„๊ตฌ๋“ค์€ ์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ์„ฑํ•œ ์Šคํ‚ค๋งˆ์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. /// diff --git a/docs/ko/docs/tutorial/body-multiple-params.md b/docs/ko/docs/tutorial/body-multiple-params.md index bebdffed80..3db614d72b 100644 --- a/docs/ko/docs/tutorial/body-multiple-params.md +++ b/docs/ko/docs/tutorial/body-multiple-params.md @@ -106,13 +106,6 @@ q: str | None = None ``` -๋˜๋Š” Python 3.9์—์„œ๋Š”: - -```Python -q: Union[str, None] = None -``` - - ์˜ˆ๋ฅผ ๋“ค์–ด: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} diff --git a/docs/ko/docs/tutorial/body-nested-models.md b/docs/ko/docs/tutorial/body-nested-models.md index 4a8c1afc13..33f0f71e95 100644 --- a/docs/ko/docs/tutorial/body-nested-models.md +++ b/docs/ko/docs/tutorial/body-nested-models.md @@ -164,7 +164,7 @@ images: list[Image] ์ด๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ: -{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## ์–ด๋””์„œ๋‚˜ ํŽธ์ง‘๊ธฐ ์ง€์› { #editor-support-everywhere } @@ -194,7 +194,7 @@ Pydantic ๋ชจ๋ธ ๋Œ€์‹  `dict`๋กœ ์ง์ ‘ ์ž‘์—…ํ•œ๋‹ค๋ฉด ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ํŽธ์ง‘ ์ด ๊ฒฝ์šฐ, `int` ํ‚ค์™€ `float` ๊ฐ’์„ ๊ฐ€์ง„ ํ•œ ์–ด๋–ค `dict`๋“  ๋ฐ›์•„๋“ค์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | ํŒ diff --git a/docs/ko/docs/tutorial/body.md b/docs/ko/docs/tutorial/body.md index 1e66c60c22..b282d1cc92 100644 --- a/docs/ko/docs/tutorial/body.md +++ b/docs/ko/docs/tutorial/body.md @@ -74,7 +74,7 @@ * ๋งค๊ฐœ๋ณ€์ˆ˜ `item`์— ํฌํ•จ๋œ ์ˆ˜์‹  ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. * ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `Item` ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์™€ ๊ทธ์— ๋Œ€ํ•œ ํƒ€์ž…์— ๋Œ€ํ•œ ํŽธ์ง‘๊ธฐ ์ง€์›(์™„์„ฑ ๋“ฑ)์„ ๋˜ํ•œ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋ธ์„ ์œ„ํ•œ JSON Schema ์ •์˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉํ•˜๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ถ„์ด ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ณณ ์–ด๋””์—์„œ๋‚˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* ์ด๋Ÿฌํ•œ ์Šคํ‚ค๋งˆ๋Š”, ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ ์ผ๋ถ€๊ฐ€ ๋  ๊ฒƒ์ด๋ฉฐ, ์ž๋™ ๋ฌธ์„œํ™” UIs์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +* ์ด๋Ÿฌํ•œ ์Šคํ‚ค๋งˆ๋Š”, ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ ์ผ๋ถ€๊ฐ€ ๋  ๊ฒƒ์ด๋ฉฐ, ์ž๋™ ๋ฌธ์„œํ™” UIs์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ## ์ž๋™ ๋ฌธ์„œํ™” { #automatic-docs } @@ -141,7 +141,7 @@ **๋ณธ๋ฌธ**, **๊ฒฝ๋กœ** ๊ทธ๋ฆฌ๊ณ  **์ฟผ๋ฆฌ** ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชจ๋‘ ๋™์‹œ์— ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -**FastAPI**๋Š” ๊ฐ๊ฐ์„ ์ธ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์˜ณ๋ฐ”๋ฅธ ์œ„์น˜์— ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +**FastAPI**๋Š” ๊ฐ๊ฐ์„ ์ธ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค. {* ../../docs_src/body/tutorial004_py310.py hl[16] *} @@ -153,9 +153,9 @@ /// note | ์ฐธ๊ณ  -FastAPI๋Š” `q`์˜ ๊ฐ’์ด ํ•„์š”์—†์Œ์„ ์•Œ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์ด `= None`์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. +FastAPI๋Š” `q`์˜ ๊ฐ’์ด ํ•„์š”์—†์Œ์„ ๊ธฐ๋ณธ ๊ฐ’ `= None` ๋•Œ๋ฌธ์— ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -Python 3.10+์˜ `str | None` ๋˜๋Š” Python 3.9+์˜ `Union[str, None]`์— ์žˆ๋Š” `Union`์€ FastAPI๊ฐ€ `q` ๊ฐ’์ด ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜์„ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์ด `= None`์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +`str | None`์€ FastAPI๊ฐ€ ๊ฐ’์ด ํ•„์ˆ˜์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์ด `= None`์ด๋ฏ€๋กœ ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํŽธ์ง‘๊ธฐ๊ฐ€ ๋” ๋‚˜์€ ์ง€์›์„ ์ œ๊ณตํ•˜๊ณ  ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/cookie-param-models.md b/docs/ko/docs/tutorial/cookie-param-models.md index 00238d1b79..70b76e09ce 100644 --- a/docs/ko/docs/tutorial/cookie-param-models.md +++ b/docs/ko/docs/tutorial/cookie-param-models.md @@ -46,7 +46,7 @@ ์ผ๋ถ€ ํŠน๋ณ„ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€(ํ”ํ•˜์ง€๋Š” ์•Š๊ฒ ์ง€๋งŒ)์—์„œ๋Š” ์ˆ˜์‹ ํ•˜๋ ค๋Š” ์ฟ ํ‚ค๋ฅผ **์ œํ•œ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์ด์ œ API๋Š” ์ž์‹ ์˜ cookie consent๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿคช๐Ÿช +์ด์ œ API๋Š” ์ž์‹ ์˜ ์ฟ ํ‚ค ๋™์˜๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿคช๐Ÿช Pydantic์˜ ๋ชจ๋ธ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€(`extra`) ํ•„๋“œ๋ฅผ ๊ธˆ์ง€(`forbid`)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: @@ -54,9 +54,9 @@ Pydantic์˜ ๋ชจ๋ธ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€(`extra`) ํ•„๋“œ๋ฅผ ๊ธˆ์ง€(`forb ํด๋ผ์ด์–ธํŠธ๊ฐ€ **์ถ”๊ฐ€ ์ฟ ํ‚ค**๋ฅผ ๋ณด๋‚ด๋ ค๊ณ  ์‹œ๋„ํ•˜๋ฉด, **์˜ค๋ฅ˜** ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. -๋™์˜๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ์• ์“ฐ๋Š” ๋ถˆ์Œํ•œ ์ฟ ํ‚ค ๋ฐฐ๋„ˆ(ํŒ์—…)๋“ค, API๊ฐ€ ๊ฑฐ๋ถ€ํ•˜๋Š”๋ฐ๋„. ๐Ÿช +๋™์˜๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ์• ์“ฐ๋Š” ๋ถˆ์Œํ•œ ์ฟ ํ‚ค ๋ฐฐ๋„ˆ(ํŒ์—…)๋“ค, API๊ฐ€ ๊ฑฐ๋ถ€ํ•˜๋Š”๋ฐ๋„. ๐Ÿช -์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ผ์ด์–ธํŠธ๊ฐ€ `good-list-please` ๊ฐ’์œผ๋กœ `santa_tracker` ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ด๋ ค๊ณ  ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” `santa_tracker` ์ฟ ํ‚ค๊ฐ€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” **์˜ค๋ฅ˜** ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: +์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋ผ์ด์–ธํŠธ๊ฐ€ `good-list-please` ๊ฐ’์œผ๋กœ `santa_tracker` ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ด๋ ค๊ณ  ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” `santa_tracker` ์ฟ ํ‚ค๊ฐ€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” **์˜ค๋ฅ˜** ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: ```json { @@ -73,4 +73,4 @@ Pydantic์˜ ๋ชจ๋ธ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€(`extra`) ํ•„๋“œ๋ฅผ ๊ธˆ์ง€(`forb ## ์š”์•ฝ { #summary } -**Pydantic ๋ชจ๋ธ**์„ ์‚ฌ์šฉํ•˜์—ฌ **FastAPI**์—์„œ **์ฟ ํ‚ค**๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž +**Pydantic ๋ชจ๋ธ**์„ ์‚ฌ์šฉํ•˜์—ฌ **FastAPI**์—์„œ **์ฟ ํ‚ค**๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž diff --git a/docs/ko/docs/tutorial/cookie-params.md b/docs/ko/docs/tutorial/cookie-params.md index 0591a5e96b..6ea09101c3 100644 --- a/docs/ko/docs/tutorial/cookie-params.md +++ b/docs/ko/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ /// -/// info | ์ •๋ณด +/// info ์ฟ ํ‚ค๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” `Cookie`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•ด์„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. /// -/// info | ์ •๋ณด +/// info **๋ธŒ๋ผ์šฐ์ €๋Š” ์ฟ ํ‚ค๋ฅผ** ๋‚ด๋ถ€์ ์œผ๋กœ ํŠน๋ณ„ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, **JavaScript**๊ฐ€ ์‰ฝ๊ฒŒ ์ฟ ํ‚ค๋ฅผ ๋‹ค๋ฃจ๋„๋ก ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์—ผ๋‘์— ๋‘์„ธ์š”. diff --git a/docs/ko/docs/tutorial/cors.md b/docs/ko/docs/tutorial/cors.md index 0f3948a3dc..f78e1c0707 100644 --- a/docs/ko/docs/tutorial/cors.md +++ b/docs/ko/docs/tutorial/cors.md @@ -46,7 +46,7 @@ * ํŠน์ • HTTP ๋ฉ”์„œ๋“œ(`POST`, `PUT`) ๋˜๋Š” ์™€์ผ๋“œ์นด๋“œ `"*"`๋ฅผ ์‚ฌ์šฉํ•œ ๋ชจ๋“  ๋ฉ”์„œ๋“œ. * ํŠน์ • HTTP ํ—ค๋” ๋˜๋Š” ์™€์ผ๋“œ์นด๋“œ `"*"`๋ฅผ ์‚ฌ์šฉํ•œ ๋ชจ๋“  ํ—ค๋”. -{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *} +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} `CORSMiddleware` ๊ตฌํ˜„์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œํ•œ์ ์ด๋ฏ€๋กœ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ Cross-Domain ์ปจํ…์ŠคํŠธ์—์„œ ํŠน์ • ์ถœ์ฒ˜, ๋ฉ”์„œ๋“œ ๋˜๋Š” ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋ฉด ์ด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -78,7 +78,7 @@ ## ๋” ๋งŽ์€ ์ •๋ณด { #more-info } -CORS์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” Mozilla CORS ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. +CORS์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋Š” Mozilla CORS ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. /// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ diff --git a/docs/ko/docs/tutorial/debugging.md b/docs/ko/docs/tutorial/debugging.md index ca20acff64..c27b68bc1c 100644 --- a/docs/ko/docs/tutorial/debugging.md +++ b/docs/ko/docs/tutorial/debugging.md @@ -6,7 +6,7 @@ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ `uvicorn`์„ ์ง์ ‘ ์ž„ํฌํŠธํ•˜์—ฌ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *} +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} ### `__name__ == "__main__"` ์— ๋Œ€ํ•˜์—ฌ { #about-name-main } diff --git a/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md index 68bba669ae..83749f7b0a 100644 --- a/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md @@ -101,7 +101,7 @@ FastAPI๊ฐ€ ์‹ค์ œ๋กœ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๊ฒƒ์ด "ํ˜ธ์ถœ ๊ฐ€๋Šฅ(callable)"(ํ•จ ์œ„ ์ฝ”๋“œ์—์„œ `CommonQueryParams`๋ฅผ ๋‘ ๋ฒˆ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์— ์ฃผ๋ชฉํ•˜์„ธ์š”: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ @@ -137,7 +137,7 @@ FastAPI๋Š” ์—ฌ๊ธฐ์—์„œ ์„ ์–ธ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ์ถ”์ถœํ•˜๊ณ , ์‹ค์ œ๋กœ ์ด ์ด ๊ฒฝ์šฐ ์ฒซ ๋ฒˆ์งธ `CommonQueryParams`๋Š” ๋‹ค์Œ์—์„œ: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, ... @@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ... //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ @@ -163,7 +163,7 @@ commons: CommonQueryParams ... ์‹ค์ œ๋กœ๋Š” ์ด๋ ‡๊ฒŒ๋งŒ ์ž‘์„ฑํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[Any, Depends(CommonQueryParams)] @@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ @@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams) ํ•˜์ง€๋งŒ `CommonQueryParams`๋ฅผ ๋‘ ๋ฒˆ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ ๋ฐ˜๋ณต์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ @@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹ : -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] @@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ @@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams) ...์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค: -//// tab | Python 3.9+ +//// tab | Python 3.10+ ```Python commons: Annotated[CommonQueryParams, Depends()] @@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()] //// -//// tab | Python 3.9+ non-Annotated +//// tab | Python 3.10+ Annotated ๋ฏธ์‚ฌ์šฉ /// tip | ํŒ diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 39c78c0786..d269e7e774 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -1,28 +1,28 @@ -# ๊ฒฝ๋กœ ์ž‘๋™ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์—์„œ์˜ ์˜์กด์„ฑ { #dependencies-in-path-operation-decorators } +# ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์—์„œ์˜ ์˜์กด์„ฑ { #dependencies-in-path-operation-decorators } -๋ช‡๋ช‡ ๊ฒฝ์šฐ์—๋Š”, *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜* ์•ˆ์—์„œ ์˜์กด์„ฑ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +๋ช‡๋ช‡ ๊ฒฝ์šฐ์—๋Š”, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ์•ˆ์—์„œ ์˜์กด์„ฑ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ์˜์กด์„ฑ์ด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ์‹คํ–‰/ํ•ด๊ฒฐ๋  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. -๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—, `Depends`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค *๊ฒฝ๋กœ ์ž‘๋™ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `dependencies`์˜ `list`๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—, `Depends`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•˜๋Š” ๋Œ€์‹  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `dependencies`์˜ `list`๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -## *๊ฒฝ๋กœ ์ž‘๋™ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `dependencies` ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-dependencies-to-the-path-operation-decorator } +## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `dependencies` ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-dependencies-to-the-path-operation-decorator } -*๊ฒฝ๋กœ ์ž‘๋™ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*๋Š” `dependencies`๋ผ๋Š” ์„ ํƒ์ ์ธ ์ธ์ž๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*๋Š” ์„ ํƒ์ ์ธ ์ธ์ž `dependencies`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. -`Depends()`๋กœ ๋œ `list`์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค: +`Depends()`๋กœ ๋œ `list`์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} -์ด๋Ÿฌํ•œ ์˜์กด์„ฑ๋“ค์€ ๊ธฐ์กด ์˜์กด์„ฑ๋“ค๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰/ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ’์€ (๋ฌด์—‡์ด๋“  ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด) *๊ฒฝ๋กœ ์ž‘๋™ ํ•จ์ˆ˜*์— ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ ์˜์กด์„ฑ๋“ค์€ ๊ธฐ์กด ์˜์กด์„ฑ๋“ค๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰/ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ’์€ (๋ฌด์—‡์ด๋“  ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด) *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์— ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. /// tip | ํŒ ์ผ๋ถ€ ํŽธ์ง‘๊ธฐ์—์„œ๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ  ์˜ค๋ฅ˜๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. -*๊ฒฝ๋กœ ์ž‘๋™ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ ์ด๋Ÿฌํ•œ `dependencies`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽธ์ง‘๊ธฐ/๋„๊ตฌ ์˜ค๋ฅ˜๋ฅผ ํ”ผํ•˜๋ฉด์„œ๋„ ์‹คํ–‰๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ ์ด๋Ÿฌํ•œ `dependencies`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽธ์ง‘๊ธฐ/๋„๊ตฌ ์˜ค๋ฅ˜๋ฅผ ํ”ผํ•˜๋ฉด์„œ๋„ ์‹คํ–‰๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ณด๊ณ  ๋ถˆํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๊ฐœ๋ฐœ์ž์˜ ํ˜ผ๋ž€์„ ๋ฐฉ์ง€ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -44,13 +44,13 @@ (ํ—ค๋”๊ฐ™์€) ์š”์ฒญ ์š”๊ตฌ์‚ฌํ•ญ์ด๋‚˜ ํ•˜์œ„-์˜์กด์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} ### ์˜ค๋ฅ˜ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ { #raise-exceptions } ๋‹ค์Œ ์˜์กด์„ฑ์€ ๊ธฐ์กด ์˜์กด์„ฑ๊ณผ ๋™์ผํ•˜๊ฒŒ ์˜ˆ์™ธ๋ฅผ `raise`ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} ### ๊ฐ’ ๋ฐ˜ํ™˜ํ•˜๊ธฐ { #return-values } @@ -58,12 +58,12 @@ ๊ทธ๋ž˜์„œ ์ด๋ฏธ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉ๋œ (๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š”) ์ผ๋ฐ˜์ ์ธ ์˜์กด์„ฑ์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋น„๋ก ๊ฐ’์€ ์‚ฌ์šฉ๋˜์ง€ ์•Š์ง€๋งŒ ์˜์กด์„ฑ์€ ์‹คํ–‰๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค: -{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} -## *๊ฒฝ๋กœ ์ž‘๋™* ๋ชจ์Œ์— ๋Œ€ํ•œ ์˜์กด์„ฑ { #dependencies-for-a-group-of-path-operations } +## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋ชจ์Œ์— ๋Œ€ํ•œ ์˜์กด์„ฑ { #dependencies-for-a-group-of-path-operations } -๋‚˜์ค‘์— ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฒ•([๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ์—ฌ๋Ÿฌ ํŒŒ์ผ๋“ค](../../tutorial/bigger-applications.md){.internal-link target=_blank})์„ ์ฝ์„ ๋•Œ, *๊ฒฝ๋กœ ์ž‘๋™* ๋ชจ์Œ์— ๋Œ€ํ•œ ๋‹จ์ผ `dependencies` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋ฐฐ์šฐ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๋‚˜์ค‘์— ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฒ•([๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ์—ฌ๋Ÿฌ ํŒŒ์ผ๋“ค](../../tutorial/bigger-applications.md){.internal-link target=_blank})์„ ์ฝ์„ ๋•Œ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋ชจ์Œ์— ๋Œ€ํ•œ ๋‹จ์ผ `dependencies` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋ฐฐ์šฐ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ## ์ „์—ญ ์˜์กด์„ฑ { #global-dependencies } -๋‹ค์Œ์œผ๋กœ ๊ฐ *๊ฒฝ๋กœ ์ž‘๋™*์— ์ ์šฉ๋˜๋„๋ก `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์— ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฒ•์„ ๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๋‹ค์Œ์œผ๋กœ ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์ ์šฉ๋˜๋„๋ก `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์— ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฒ•์„ ๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md index 9bf6c0693a..7b50fd438b 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # `yield`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜์กด์„ฑ { #dependencies-with-yield } -FastAPI๋Š” ์ž‘์—… ์™„๋ฃŒ ํ›„ ์ถ”๊ฐ€ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์˜์กด์„ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +FastAPI๋Š” ์ž‘์—… ์™„๋ฃŒ ํ›„ ์ถ”๊ฐ€ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์˜์กด์„ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด `return` ๋Œ€์‹  `yield`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ถ”๊ฐ€๋กœ ์‹คํ–‰ํ•  ๋‹จ๊ณ„ (์ฝ”๋“œ)๋ฅผ ๊ทธ ๋’ค์— ์ž‘์„ฑํ•˜์„ธ์š”. @@ -29,15 +29,15 @@ FastAPI๋Š” CORS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. +๋‹ค์Œ ์„น์…˜์—์„œ ๋ฏธ๋“ค์›จ์–ด๋กœ CORS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/path-operation-configuration.md b/docs/ko/docs/tutorial/path-operation-configuration.md index baef3fb403..0d6a0d4229 100644 --- a/docs/ko/docs/tutorial/path-operation-configuration.md +++ b/docs/ko/docs/tutorial/path-operation-configuration.md @@ -46,7 +46,7 @@ **FastAPI**๋Š” ์ผ๋ฐ˜ ๋ฌธ์ž์—ด๊ณผ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *} +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} ## ์š”์•ฝ๊ณผ ์„ค๋ช… { #summary-and-description } @@ -56,7 +56,7 @@ ## ๋…์ŠคํŠธ๋ง์œผ๋กœ ๋งŒ๋“  ์„ค๋ช… { #description-from-docstring } -์„ค๋ช…์€ ๋ณดํ†ต ๊ธธ์–ด์ง€๊ณ  ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์ณ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์„ค๋ช…์„ ํ•จ์ˆ˜ docstring์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ๊ทธ๊ณณ์—์„œ ์ด๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. +์„ค๋ช…์€ ๋ณดํ†ต ๊ธธ์–ด์ง€๊ณ  ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์ณ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์„ค๋ช…์„ ํ•จ์ˆ˜ ๋…์ŠคํŠธ๋ง์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ๊ทธ๊ณณ์—์„œ ์ด๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ๋…์ŠคํŠธ๋ง์—๋Š” Markdown์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, (๋…์ŠคํŠธ๋ง์˜ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ) ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด์„๋˜๊ณ  ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. @@ -90,9 +90,9 @@ OpenAPI๋Š” ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์‘๋‹ต์— ๊ด€ํ•œ ์„ค๋ช…์„ ์š”๊ตฌํ•  ๊ฒƒ์„ ## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ง€์›์ค‘๋‹จํ•˜๊ธฐ { #deprecate-a-path-operation } -*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ  deprecated๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋ฉด, `deprecated` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ  ์ง€์›์ค‘๋‹จ์œผ๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋ฉด, `deprecated` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *} +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์—์„œ ์ง€์›์ค‘๋‹จ์œผ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/tutorial/path-params-numeric-validations.md b/docs/ko/docs/tutorial/path-params-numeric-validations.md index f2c52d4aac..51f9fe2c14 100644 --- a/docs/ko/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ko/docs/tutorial/path-params-numeric-validations.md @@ -54,11 +54,11 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} ํ•˜์ง€๋งŒ `Annotated`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. `Query()`๋‚˜ `Path()`์— ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ˆœ์„œ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} ## ํ•„์š”ํ•œ ๋Œ€๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •๋ ฌํ•˜๊ธฐ, ํŠธ๋ฆญ { #order-the-parameters-as-you-need-tricks } @@ -83,13 +83,13 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด ํŒŒ์ด์ฌ์€ `*`์œผ๋กœ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์ง€๋งŒ, ๋’ค๋”ฐ๋ฅด๋Š” ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ‚ค์›Œ๋“œ ์ธ์ž(ํ‚ค-๊ฐ’ ์Œ)๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•จ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” kwargs๋กœ๋„ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์ด ์—†๋”๋ผ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. -{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} ### `Annotated`๋ฅผ ์“ฐ๋ฉด ๋” ์ข‹์Šต๋‹ˆ๋‹ค { #better-with-annotated } `Annotated`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์•„๋งˆ `*`๋„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. -{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} ## ์ˆซ์ž ๊ฒ€์ฆ: ํฌ๊ฑฐ๋‚˜ ๊ฐ™์Œ { #number-validations-greater-than-or-equal } @@ -97,7 +97,7 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด ์—ฌ๊ธฐ์„œ `ge=1`์ธ ๊ฒฝ์šฐ, `item_id`๋Š” `1`๋ณด๋‹ค "`g`reater than or `e`qual"(ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€) ์ •์ˆ˜ํ˜• ์ˆซ์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} ## ์ˆซ์ž ๊ฒ€์ฆ: ํฌ๊ฑฐ๋‚˜ ๋ฐ ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์Œ { #number-validations-greater-than-and-less-than-or-equal } @@ -106,7 +106,7 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด * `gt`: `g`reater `t`han * `le`: `l`ess than or `e`qual -{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} ## ์ˆซ์ž ๊ฒ€์ฆ: ๋ถ€๋™์†Œ์ˆ˜, ํฌ๊ฑฐ๋‚˜ ๋ฐ ์ž‘๊ฑฐ๋‚˜ { #number-validations-floats-greater-than-and-less-than } @@ -118,7 +118,7 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด lt ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. -{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## ์š”์•ฝ { #recap } diff --git a/docs/ko/docs/tutorial/path-params.md b/docs/ko/docs/tutorial/path-params.md index ea5170eccb..c6e973709a 100644 --- a/docs/ko/docs/tutorial/path-params.md +++ b/docs/ko/docs/tutorial/path-params.md @@ -2,7 +2,7 @@ ํŒŒ์ด์ฌ์˜ ํฌ๋งท ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ๋ฒ•์„ ์ด์šฉํ•˜์—ฌ ๊ฒฝ๋กœ "๋งค๊ฐœ๋ณ€์ˆ˜" ๋˜๋Š” "๋ณ€์ˆ˜"๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *} +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ `item_id`์˜ ๊ฐ’์€ ํ•จ์ˆ˜์˜ `item_id` ์ธ์ž๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. @@ -16,7 +16,7 @@ ํŒŒ์ด์ฌ ํ‘œ์ค€ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜์— ์žˆ๋Š” ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *} +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} ์œ„์˜ ์˜ˆ์‹œ์—์„œ, `item_id`๋Š” `int`๋กœ ์„ ์–ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. @@ -26,7 +26,7 @@ /// -## ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ { #data-conversion } +## ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ { #data-conversion } ์ด ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  http://127.0.0.1:8000/items/3์„ ์—ด๋ฉด, ๋‹ค์Œ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: @@ -38,7 +38,7 @@ ํ•จ์ˆ˜๊ฐ€ ๋ฐ›์€(๋ฐ˜ํ™˜๋„ ํ•˜๋Š”) ๊ฐ’์€ ๋ฌธ์ž์—ด `"3"`์ด ์•„๋‹ˆ๋ผ ํŒŒ์ด์ฌ `int` ํ˜•์ธ `3`์ž…๋‹ˆ๋‹ค. -์ฆ‰, ํƒ€์ž… ์„ ์–ธ์„ ํ•˜๋ฉด **FastAPI**๋Š” ์ž๋™์œผ๋กœ ์š”์ฒญ์„ "ํŒŒ์‹ฑ"ํ•ฉ๋‹ˆ๋‹ค. +์ฆ‰, ํƒ€์ž… ์„ ์–ธ์„ ํ•˜๋ฉด **FastAPI**๋Š” ์ž๋™์œผ๋กœ ์š”์ฒญ์„ "ํŒŒ์‹ฑ"ํ•ฉ๋‹ˆ๋‹ค. /// @@ -116,21 +116,21 @@ ์‚ฌ์šฉ์ž ID๋ฅผ ์ด์šฉํ•ด ํŠน์ • ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ๋กœ `/users/{user_id}`๋„ ์žˆ์Šต๋‹ˆ๋‹ค. -*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” ์ˆœ์ฐจ์ ์œผ๋กœ ํ‰๊ฐ€๋˜๊ธฐ ๋•Œ๋ฌธ์— `/users/{user_id}` ์ด์ „์— `/users/me`์— ๋Œ€ํ•œ ๊ฒฝ๋กœ๊ฐ€ ๋จผ์ € ์„ ์–ธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: +*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” ์ˆœ์ฐจ์ ์œผ๋กœ ํ‰๊ฐ€๋˜๊ธฐ ๋•Œ๋ฌธ์— `/users/me`์— ๋Œ€ํ•œ ๊ฒฝ๋กœ๊ฐ€ `/users/{user_id}` ์ด์ „์— ๋จผ์ € ์„ ์–ธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `/users/{user_id}`์— ๋Œ€ํ•œ ๊ฒฝ๋กœ๊ฐ€ `/users/me`์—๋„ ๋งค์นญ๋˜์–ด, ๋งค๊ฐœ๋ณ€์ˆ˜ `user_id`์— `"me"` ๊ฐ’์ด ๋“ค์–ด์™”๋‹ค๊ณ  "์ƒ๊ฐํ•˜๊ฒŒ" ๋ฉ๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *} +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} ๊ฒฝ๋กœ๊ฐ€ ๋จผ์ € ๋งค์นญ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ๋ฒˆ์งธ ๊ฒƒ์ด ํ•ญ์ƒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ## ์‚ฌ์ „์ •์˜ ๊ฐ’ { #predefined-values } -๋งŒ์•ฝ *๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜*๋ฅผ ๋ฐ›๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์žˆ์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ์œ ํšจํ•œ *๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜* ๊ฐ’๋“ค์„ ๋ฏธ๋ฆฌ ์ •์˜ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํŒŒ์ด์ฌ ํ‘œ์ค€ `Enum`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋งŒ์•ฝ *๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜*๋ฅผ ๋ฐ›๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์žˆ์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ์œ ํšจํ•œ *๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜* ๊ฐ’๋“ค์„ ๋ฏธ๋ฆฌ ์ •์˜ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํŒŒ์ด์ฌ ํ‘œ์ค€ `Enum`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### `Enum` ํด๋ž˜์Šค ์ƒ์„ฑ { #create-an-enum-class } @@ -140,11 +140,11 @@ ๊ฐ€๋Šฅํ•œ ๊ฐ’๋“ค์— ํ•ด๋‹นํ•˜๋Š” ๊ณ ์ •๋œ ๊ฐ’์˜ ํด๋ž˜์Šค ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋“ค์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} /// tip | ํŒ -ํ˜น์‹œ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, "AlexNet", "ResNet", ๊ทธ๋ฆฌ๊ณ  "LeNet"์€ ๊ทธ์ € ๋จธ์‹  ๋Ÿฌ๋‹ ๋ชจ๋ธ๋“ค์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. +ํ˜น์‹œ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, "AlexNet", "ResNet", ๊ทธ๋ฆฌ๊ณ  "LeNet"์€ ๊ทธ์ € ๋จธ์‹  ๋Ÿฌ๋‹ ๋ชจ๋ธ๋“ค์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. /// @@ -152,7 +152,7 @@ ์ƒ์„ฑํ•œ ์—ด๊ฑฐํ˜• ํด๋ž˜์Šค(`ModelName`)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ *๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜*๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} ### ๋ฌธ์„œ ํ™•์ธ { #check-the-docs } @@ -168,13 +168,13 @@ ์ƒ์„ฑํ•œ ์—ด๊ฑฐํ˜• `ModelName`์˜ *์—ด๊ฑฐํ˜• ๋ฉค๋ฒ„*์™€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} #### *์—ด๊ฑฐํ˜• ๊ฐ’* ๊ฐ€์ ธ์˜ค๊ธฐ { #get-the-enumeration-value } `model_name.value` ๋˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ `your_enum_member.value`๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ค์ œ ๊ฐ’(์œ„ ์˜ˆ์‹œ์˜ ๊ฒฝ์šฐ `str`)์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} /// tip | ํŒ @@ -188,7 +188,7 @@ ํด๋ผ์ด์–ธํŠธ์— ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ํ•ด๋‹น ๊ฐ’(์ด ๊ฒฝ์šฐ ๋ฌธ์ž์—ด)์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *} +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} ํด๋ผ์ด์–ธํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ JSON ์‘๋‹ต์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: @@ -227,7 +227,7 @@ Starlette์˜ ์˜ต์…˜์„ ์ง์ ‘ ์ด์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์€ URL์„ ์‚ฌ์šฉํ•จ์œผ ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *} +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} /// tip | ํŒ @@ -242,7 +242,7 @@ Starlette์˜ ์˜ต์…˜์„ ์ง์ ‘ ์ด์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์€ URL์„ ์‚ฌ์šฉํ•จ์œผ **FastAPI**๋ฅผ ์ด์šฉํ•˜๋ฉด ์งง๊ณ  ์ง๊ด€์ ์ธ ํ‘œ์ค€ ํŒŒ์ด์ฌ ํƒ€์ž… ์„ ์–ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: * ํŽธ์ง‘๊ธฐ ์ง€์›: ์˜ค๋ฅ˜ ๊ฒ€์‚ฌ, ์ž๋™์™„์„ฑ ๋“ฑ -* ๋ฐ์ดํ„ฐ "parsing" +* ๋ฐ์ดํ„ฐ "ํŒŒ์‹ฑ" * ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ * API ์ฃผ์„(Annotation)๊ณผ ์ž๋™ ๋ฌธ์„œ diff --git a/docs/ko/docs/tutorial/query-params-str-validations.md b/docs/ko/docs/tutorial/query-params-str-validations.md index 68824932ee..2b608fd1d5 100644 --- a/docs/ko/docs/tutorial/query-params-str-validations.md +++ b/docs/ko/docs/tutorial/query-params-str-validations.md @@ -2,7 +2,7 @@ **FastAPI**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด ๋ฐ ๊ฒ€์ฆ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -์ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: +์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: {* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} @@ -41,46 +41,22 @@ FastAPI๋Š” 0.95.0 ๋ฒ„์ „์—์„œ `Annotated` ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ๊ณ (๊ทธ๋ฆฌ๊ณ  ์ด ## `q` ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์— `Annotated` ์‚ฌ์šฉํ•˜๊ธฐ { #use-annotated-in-the-type-for-the-q-parameter } -์ด์ „์— [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}์—์„œ `Annotated`๋ฅผ ์‚ฌ์šฉํ•ด ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ง์”€๋“œ๋ฆฐ ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? +์ด์ „์— [Python ํƒ€์ž… ์†Œ๊ฐœ](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}์—์„œ `Annotated`๋ฅผ ์‚ฌ์šฉํ•ด ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ง์”€๋“œ๋ฆฐ ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ์ด์ œ FastAPI์—์„œ ์‚ฌ์šฉํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค. ๐Ÿš€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค: -//// tab | Python 3.10+ - ```Python q: str | None = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Union[str, None] = None -``` - -//// - ์—ฌ๊ธฐ์„œ `Annotated`๋กœ ๊ฐ์‹ธ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งŒ๋“ญ๋‹ˆ๋‹ค: -//// tab | Python 3.10+ - ```Python q: Annotated[str | None] = None ``` -//// - -//// tab | Python 3.9+ - -```Python -q: Annotated[Union[str, None]] = None -``` - -//// - ๋‘ ๋ฒ„์ „ ๋ชจ๋‘ ๊ฐ™์€ ์˜๋ฏธ๋กœ, `q`๋Š” `str` ๋˜๋Š” `None`์ด ๋  ์ˆ˜ ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ’์€ `None`์ž…๋‹ˆ๋‹ค. ์ด์ œ ์žฌ๋ฏธ์žˆ๋Š” ๋ถ€๋ถ„์œผ๋กœ ๋„˜์–ด๊ฐ€ ๋ด…์‹œ๋‹ค. ๐ŸŽ‰ @@ -109,7 +85,7 @@ q: Annotated[Union[str, None]] = None ## ๋Œ€์•ˆ(์ด์ „ ๋ฐฉ์‹): ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ `Query` ์‚ฌ์šฉ { #alternative-old-query-as-the-default-value } -์ด์ „ FastAPI ๋ฒ„์ „(0.95.0 ์ด์ „)์—์„œ๋Š” `Annotated`์— ๋„ฃ๋Š” ๋Œ€์‹ , ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ `Query`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋ณ€์—์„œ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๊ธฐ ๋•Œ๋ฌธ์— ์„ค๋ช…ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. +์ด์ „ FastAPI ๋ฒ„์ „(0.95.0 ์ด์ „)์—์„œ๋Š” `Annotated`์— ๋„ฃ๋Š” ๋Œ€์‹ , ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ `Query`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋ณ€์—์„œ ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๊ธฐ ๋•Œ๋ฌธ์— ์„ค๋ช…ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. /// tip | ํŒ @@ -192,7 +168,7 @@ FastAPI ์—†์ด๋„ **๋‹ค๋ฅธ ๊ณณ์—์„œ** ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ **ํ˜ธ์ถœ**ํ•  ์ˆ˜ ์žˆ๊ณ  ## ์ •๊ทœ์‹ ์ถ”๊ฐ€ { #add-regular-expressions } -๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ผ์น˜ํ•ด์•ผ ํ•˜๋Š” ์ •๊ทœ ํ‘œํ˜„์‹ `pattern`์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ผ์น˜ํ•ด์•ผ ํ•˜๋Š” ์ •๊ทœ ํ‘œํ˜„์‹ `pattern`์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -212,7 +188,7 @@ FastAPI ์—†์ด๋„ **๋‹ค๋ฅธ ๊ณณ์—์„œ** ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ **ํ˜ธ์ถœ**ํ•  ์ˆ˜ ์žˆ๊ณ  `q` ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์— `min_length`๋ฅผ `3`์œผ๋กœ ์„ค์ •ํ•˜๊ณ , ๊ธฐ๋ณธ๊ฐ’์„ `"fixedquery"`๋กœ ์„ ์–ธํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค: -{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | ์ฐธ๊ณ  @@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None ๋”ฐ๋ผ์„œ `Query`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ฐ’์„ ํ•„์ˆ˜๋กœ ์„ ์–ธํ•ด์•ผ ํ•  ๋•Œ๋Š”, ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} ### ํ•„์ˆ˜์ง€๋งŒ `None` ๊ฐ€๋Šฅ { #required-can-be-none } @@ -293,7 +269,7 @@ http://localhost:8000/items/?q=foo&q=bar ์ œ๊ณต๋œ ๊ฐ’์ด ์—†์œผ๋ฉด ๊ธฐ๋ณธ `list` ๊ฐ’์„ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•˜๋ฉด: @@ -316,7 +292,7 @@ http://localhost:8000/items/ `list[str]` ๋Œ€์‹  `list`๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} /// note | ์ฐธ๊ณ  @@ -372,7 +348,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ์ด์ œ๋Š” ๋” ์ด์ƒ ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋งˆ์Œ์— ๋“ค์–ดํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. -์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๋™์•ˆ์€ ๋‚จ๊ฒจ๋‘ฌ์•ผ ํ•˜์ง€๋งŒ, ๋ฌธ์„œ์—์„œ deprecated๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. +์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๋™์•ˆ์€ ๋‚จ๊ฒจ๋‘ฌ์•ผ ํ•˜์ง€๋งŒ, ๋ฌธ์„œ์—์„œ ์‚ฌ์šฉ ์ค‘๋‹จ๋จ์œผ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด `deprecated=True` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `Query`๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค: @@ -402,7 +378,7 @@ Pydantic์—๋Š” ISBN ๋„์„œ ๋ฒˆํ˜ธ์˜ ๊ฒฝ์šฐ ์•„์ดํ…œ ID๊ฐ€ `isbn-`์œผ๋กœ ์‹œ์ž‘ํ•˜๊ณ , IMDB ์˜ํ™” URL ID์˜ ๊ฒฝ์šฐ `imdb-`๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค: +์˜ˆ๋ฅผ ๋“ค์–ด, ์ด ์ปค์Šคํ…€ validator๋Š” ISBN ๋„์„œ ๋ฒˆํ˜ธ์˜ ๊ฒฝ์šฐ ์•„์ดํ…œ ID๊ฐ€ `isbn-`์œผ๋กœ ์‹œ์ž‘ํ•˜๊ณ , IMDB ์˜ํ™” URL ID์˜ ๊ฒฝ์šฐ `imdb-`๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -436,9 +412,9 @@ Pydantic์—๋Š” iterable object๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. +`data.items()`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ๋”•์…”๋„ˆ๋ฆฌ ํ•ญ๋ชฉ์˜ ํ‚ค์™€ ๊ฐ’์„ ๋‹ด์€ ํŠœํ”Œ๋กœ ๊ตฌ์„ฑ๋œ ์ดํ„ฐ๋Ÿฌ๋ธ” ๊ฐ์ฒด๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. -์ด iterable object๋ฅผ `list(data.items())`๋กœ ์ ์ ˆํ•œ `list`๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. +์ด ์ดํ„ฐ๋Ÿฌ๋ธ” ๊ฐ์ฒด๋ฅผ `list(data.items())`๋กœ ์ ์ ˆํ•œ `list`๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ `random.choice()`๋กœ ๋ฆฌ์ŠคํŠธ์—์„œ **๋ฌด์ž‘์œ„ ๊ฐ’**์„ ์–ป์–ด `(id, name)` ํ˜•ํƒœ์˜ ํŠœํ”Œ์„ ์–ป์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` ๊ฐ™์€ ๊ฐ’์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/query-params.md b/docs/ko/docs/tutorial/query-params.md index 5124f73bf5..0a6b1f922c 100644 --- a/docs/ko/docs/tutorial/query-params.md +++ b/docs/ko/docs/tutorial/query-params.md @@ -2,7 +2,7 @@ ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด "์ฟผ๋ฆฌ" ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ž๋™ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *} +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} ์ฟผ๋ฆฌ๋Š” URL์—์„œ `?` ํ›„์— ๋‚˜์˜ค๊ณ  `&`์œผ๋กœ ๊ตฌ๋ถ„๋˜๋Š” ํ‚ค-๊ฐ’ ์Œ์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. @@ -24,7 +24,7 @@ URL์˜ ์ผ๋ถ€์ด๋ฏ€๋กœ "์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ" ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ ์šฉ๋œ ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋„ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค: * (๋‹น์—ฐํžˆ) ํŽธ์ง‘๊ธฐ ์ง€์› -* ๋ฐ์ดํ„ฐ "ํŒŒ์‹ฑ" +* ๋ฐ์ดํ„ฐ "ํŒŒ์‹ฑ" * ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ * ์ž๋™ ๋ฌธ์„œํ™” @@ -128,7 +128,7 @@ http://127.0.0.1:8000/items/foo?short=yes ๊ทธ๋Ÿฌ๋‚˜ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ•„์ˆ˜๋กœ ๋งŒ๋“ค๋ ค๋ฉด ๋‹จ์ˆœํžˆ ๊ธฐ๋ณธ๊ฐ’์„ ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *} +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} ์—ฌ๊ธฐ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ `needy`๋Š” `str`ํ˜•์ธ ํ•„์ˆ˜ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/request-files.md b/docs/ko/docs/tutorial/request-files.md index cc00009211..3ee0fa74c3 100644 --- a/docs/ko/docs/tutorial/request-files.md +++ b/docs/ko/docs/tutorial/request-files.md @@ -20,13 +20,13 @@ $ pip install python-multipart `fastapi` ์—์„œ `File` ๊ณผ `UploadFile` ์„ ์ž„ํฌํŠธ ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} ## `File` ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์˜ { #define-file-parameters } `Body` ๋ฐ `Form` ๊ณผ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํŒŒ์ผ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} /// info | ์ •๋ณด @@ -54,7 +54,7 @@ File์˜ ๋ณธ๋ฌธ์„ ์„ ์–ธํ•  ๋•Œ, ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋˜๋Š” ๋ณธ `File` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `UploadFile` ํƒ€์ž…์œผ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} `UploadFile` ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ `bytes` ๊ณผ ๋น„๊ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค: @@ -121,7 +121,7 @@ HTML์˜ ํผ๋“ค(`
`)์ด ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์€ ํ•˜์ง€๋งŒ ํŒŒ์ผ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ, `multipart/form-data`๋กœ ์ธ์ฝ”๋”ฉ๋ฉ๋‹ˆ๋‹ค. `File`์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค๋ฉด, **FastAPI**๋Š” ๋ณธ๋ฌธ์˜ ์ ํ•ฉํ•œ ๋ถ€๋ถ„์—์„œ ํŒŒ์ผ์„ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ง€ํ•ฉ๋‹ˆ๋‹ค. -์ธ์ฝ”๋”ฉ๊ณผ ํผ ํ•„๋“œ์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ ์‹ถ๋‹ค๋ฉด,
MDN web docs for POST๋ฅผ ์ฐธ๊ณ ํ•˜๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. +์ธ์ฝ”๋”ฉ๊ณผ ํผ ํ•„๋“œ์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ ์‹ถ๋‹ค๋ฉด, MDN web docs for POST๋ฅผ ์ฐธ๊ณ ํ•˜๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. /// @@ -143,7 +143,7 @@ HTML์˜ ํผ๋“ค(`
`)์ด ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์€ ์ถ”๊ฐ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์˜ˆ๋ฅผ ๋“ค์–ด `UploadFile`๊ณผ ํ•จ๊ป˜ `File()`์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} ## ๋‹ค์ค‘ ํŒŒ์ผ ์—…๋กœ๋“œ { #multiple-file-uploads } @@ -153,7 +153,7 @@ HTML์˜ ํผ๋“ค(`
`)์ด ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์€ ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด , `bytes` ์˜ `List` ๋˜๋Š” `UploadFile` ๋ฅผ ์„ ์–ธํ•˜๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} ์„ ์–ธํ•œ๋Œ€๋กœ, `bytes` ์˜ `list` ๋˜๋Š” `UploadFile` ๋“ค์„ ์ „์†ก๋ฐ›์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. @@ -169,7 +169,7 @@ HTML์˜ ํผ๋“ค(`
`)์ด ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์€ ์ด์ „๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ `UploadFile`์— ๋Œ€ํ•ด์„œ๋„ `File()`์„ ์‚ฌ์šฉํ•ด ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} ## ์š”์•ฝ { #recap } diff --git a/docs/ko/docs/tutorial/request-form-models.md b/docs/ko/docs/tutorial/request-form-models.md index b37186dfb8..20a2e95972 100644 --- a/docs/ko/docs/tutorial/request-form-models.md +++ b/docs/ko/docs/tutorial/request-form-models.md @@ -24,7 +24,7 @@ $ pip install python-multipart **ํผ ํ•„๋“œ**๋กœ ๋ฐ›๊ณ  ์‹ถ์€ ํ•„๋“œ๋ฅผ **Pydantic ๋ชจ๋ธ**๋กœ ์„ ์–ธํ•œ ๋‹ค์Œ, ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `Form`์œผ๋กœ ์„ ์–ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} **FastAPI**๋Š” ์š”์ฒญ์—์„œ ๋ฐ›์€ **ํผ ๋ฐ์ดํ„ฐ**์—์„œ **๊ฐ ํ•„๋“œ**์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ **์ถ”์ถœ**ํ•˜๊ณ  ์ •์˜ํ•œ Pydantic ๋ชจ๋ธ์„ ์ค๋‹ˆ๋‹ค. @@ -48,7 +48,7 @@ $ pip install python-multipart Pydantic์˜ ๋ชจ๋ธ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ `extra` ํ•„๋“œ๋ฅผ `forbid`ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋ ค๊ณ  ํ•˜๋ฉด **์˜ค๋ฅ˜** ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/request-forms-and-files.md b/docs/ko/docs/tutorial/request-forms-and-files.md index a5309b5c07..4c2d12bc06 100644 --- a/docs/ko/docs/tutorial/request-forms-and-files.md +++ b/docs/ko/docs/tutorial/request-forms-and-files.md @@ -16,13 +16,13 @@ $ pip install python-multipart ## `File` ๋ฐ `Form` ์ž„ํฌํŠธ { #import-file-and-form } -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} ## `File` ๋ฐ `Form` ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์˜ { #define-file-and-form-parameters } `Body` ๋ฐ `Query`์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํŒŒ์ผ๊ณผ ํผ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} ํŒŒ์ผ๊ณผ ํผ ํ•„๋“œ๋Š” ํผ ๋ฐ์ดํ„ฐ๋กœ ์—…๋กœ๋“œ๋˜๋ฉฐ, ํŒŒ์ผ๊ณผ ํผ ํ•„๋“œ๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/request-forms.md b/docs/ko/docs/tutorial/request-forms.md index 584cbba35c..a830bc5f8a 100644 --- a/docs/ko/docs/tutorial/request-forms.md +++ b/docs/ko/docs/tutorial/request-forms.md @@ -18,17 +18,17 @@ $ pip install python-multipart `fastapi`์—์„œ `Form`์„ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} ## `Form` ๋งค๊ฐœ๋ณ€์ˆ˜ ์ •์˜ํ•˜๊ธฐ { #define-form-parameters } `Body` ๋˜๋Š” `Query`์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค: -{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} ์˜ˆ๋ฅผ ๋“ค์–ด, OAuth2 ์‚ฌ์–‘์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜("ํŒจ์Šค์›Œ๋“œ ํ”Œ๋กœ์šฐ"๋ผ๊ณ  ํ•จ)๋กœ `username`๊ณผ `password`๋ฅผ ํผ ํ•„๋“œ๋กœ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -spec์—์„œ๋Š” ํ•„๋“œ ์ด๋ฆ„์ด `username` ๋ฐ `password`๋กœ ์ •ํ™•ํ•˜๊ฒŒ ๋ช…๋ช…๋˜์–ด์•ผ ํ•˜๊ณ , JSON์ด ์•„๋‹Œ ํผ ํ•„๋“œ๋กœ ์ „์†กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +์‚ฌ์–‘์—์„œ๋Š” ํ•„๋“œ ์ด๋ฆ„์ด `username` ๋ฐ `password`๋กœ ์ •ํ™•ํ•˜๊ฒŒ ๋ช…๋ช…๋˜์–ด์•ผ ํ•˜๊ณ , JSON์ด ์•„๋‹Œ ํผ ํ•„๋“œ๋กœ ์ „์†กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. `Form`์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ์˜ˆ์ œ, ๋ณ„์นญ(์˜ˆ: `username` ๋Œ€์‹  `user-name`) ๋“ฑ์„ ํฌํ•จํ•˜์—ฌ `Body`(๋ฐ `Query`, `Path`, `Cookie`)์™€ ๋™์ผํ•œ ๊ตฌ์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -56,7 +56,7 @@ HTML ํผ(`
`)์ด ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์€ ์ผ๋ฐ˜ ๊ทธ๋Ÿฌ๋‚˜ ํผ์— ํŒŒ์ผ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ, `multipart/form-data`๋กœ ์ธ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์žฅ์—์„œ ํŒŒ์ผ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•ด ์ฝ์„ ๊ฒ๋‹ˆ๋‹ค. -์ด๋Ÿฌํ•œ ์ธ์ฝ”๋”ฉ ๋ฐ ํผ ํ•„๋“œ์— ๋Œ€ํ•ด ๋” ์ฝ๊ณ  ์‹ถ๋‹ค๋ฉด, POST์— ๋Œ€ํ•œ MDN ์›น ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. +์ด๋Ÿฌํ•œ ์ธ์ฝ”๋”ฉ ๋ฐ ํผ ํ•„๋“œ์— ๋Œ€ํ•ด ๋” ์ฝ๊ณ  ์‹ถ๋‹ค๋ฉด, MDN ์›น ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š” POST์— ๋Œ€ํ•œ. /// diff --git a/docs/ko/docs/tutorial/response-model.md b/docs/ko/docs/tutorial/response-model.md index 6246ed9ad1..942901e7cc 100644 --- a/docs/ko/docs/tutorial/response-model.md +++ b/docs/ko/docs/tutorial/response-model.md @@ -183,7 +183,7 @@ FastAPI๋Š” Pydantic์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ, ํด๋ž˜ ๊ฐ€์žฅ ํ”ํ•œ ๊ฒฝ์šฐ๋Š” [๊ณ ๊ธ‰ ๋ฌธ์„œ์—์„œ ๋‚˜์ค‘์— ์„ค๋ช…ํ•˜๋Š” ๋Œ€๋กœ Response๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ](../advanced/response-directly.md){.internal-link target=_blank}์ž…๋‹ˆ๋‹ค. -{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *} +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} ์ด ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์ด `Response` ํด๋ž˜์Šค(๋˜๋Š” ๊ทธ ์„œ๋ธŒํด๋ž˜์Šค)์ด๊ธฐ ๋•Œ๋ฌธ์— FastAPI์—์„œ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. @@ -193,7 +193,7 @@ FastAPI๋Š” Pydantic์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ, ํด๋ž˜ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์— `Response`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *} +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} ์ด๋Š” `RedirectResponse`๊ฐ€ `Response`์˜ ์„œ๋ธŒํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘ํ•˜๋ฉฐ, FastAPI๊ฐ€ ์ด ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. @@ -201,7 +201,7 @@ FastAPI๋Š” Pydantic์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ, ํด๋ž˜ ํ•˜์ง€๋งŒ ์œ ํšจํ•œ Pydantic ํƒ€์ž…์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ž„์˜์˜ ๊ฐ์ฒด(์˜ˆ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ํ•จ์ˆ˜์—์„œ ๊ทธ๋ ‡๊ฒŒ ์–ด๋…ธํ…Œ์ด์…˜ํ•˜๋ฉด, FastAPI๋Š” ๊ทธ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ๋ถ€ํ„ฐ Pydantic ์‘๋‹ต ๋ชจ๋ธ์„ ๋งŒ๋“ค๋ ค๊ณ  ์‹œ๋„ํ•˜๋‹ค๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. -๋˜ํ•œ, ์œ ํšจํ•œ Pydantic ํƒ€์ž…์ด ์•„๋‹Œ ํƒ€์ž…์ด ํ•˜๋‚˜ ์ด์ƒ ํฌํ•จ๋œ ์—ฌ๋Ÿฌ ํƒ€์ž… ๊ฐ„์˜ union์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค ๐Ÿ’ฅ: +๋˜ํ•œ, ์œ ํšจํ•œ Pydantic ํƒ€์ž…์ด ์•„๋‹Œ ํƒ€์ž…์ด ํ•˜๋‚˜ ์ด์ƒ ํฌํ•จ๋œ ์—ฌ๋Ÿฌ ํƒ€์ž… ๊ฐ„์˜ union์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค ๐Ÿ’ฅ: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} diff --git a/docs/ko/docs/tutorial/response-status-code.md b/docs/ko/docs/tutorial/response-status-code.md index 257f6a8d6f..c81132dfb9 100644 --- a/docs/ko/docs/tutorial/response-status-code.md +++ b/docs/ko/docs/tutorial/response-status-code.md @@ -8,7 +8,7 @@ * `@app.delete()` * ๋“ฑ -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} /// note | ์ฐธ๊ณ  @@ -43,7 +43,7 @@ FastAPI๋Š” ์ด๋ฅผ ์•Œ๊ณ  ์žˆ์œผ๋ฉฐ, ์‘๋‹ต ๋ณธ๋ฌธ์ด ์—†๋‹ค๊ณ  ๋ช…์‹œํ•˜๋Š” Open /// note | ์ฐธ๊ณ  -๋งŒ์•ฝ HTTP ์ƒํƒœ ์ฝ”๋“œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค์Œ ์„น์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”. +๋งŒ์•ฝ HTTP ์ƒํƒœ ์ฝ”๋“œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค์Œ ์„ก์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”. /// @@ -66,7 +66,7 @@ HTTP์—์„œ๋Š” ์‘๋‹ต์˜ ์ผ๋ถ€๋กœ 3์ž๋ฆฌ ์ˆซ์ž ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. /// tip | ํŒ -๊ฐ ์ƒํƒœ ์ฝ”๋“œ์™€ ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ ์–ด๋–ค ์šฉ๋„์ธ์ง€ ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด MDN์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ์— ๊ด€ํ•œ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. +๊ฐ ์ƒํƒœ ์ฝ”๋“œ์™€ ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ ์–ด๋–ค ์šฉ๋„์ธ์ง€ ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด MDN์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ์— ๊ด€ํ•œ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. /// @@ -74,7 +74,7 @@ HTTP์—์„œ๋Š” ์‘๋‹ต์˜ ์ผ๋ถ€๋กœ 3์ž๋ฆฌ ์ˆซ์ž ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด์ „ ์˜ˆ์‹œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *} +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} `201` ์€ "์ƒ์„ฑ๋จ"์„ ์œ„ํ•œ ์ƒํƒœ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. @@ -82,7 +82,7 @@ HTTP์—์„œ๋Š” ์‘๋‹ต์˜ ์ผ๋ถ€๋กœ 3์ž๋ฆฌ ์ˆซ์ž ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. `fastapi.status` ์˜ ํŽธ์˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *} +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} ์ด๊ฒƒ๋“ค์€ ๋‹จ์ง€ ํŽธ์˜๋ฅผ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ, ๋™์ผํ•œ ์ˆซ์ž๋ฅผ ๊ฐ–๊ณ  ์žˆ์ง€๋งŒ, ์ด๋ฅผ ํ†ตํ•ด ํŽธ์ง‘๊ธฐ์˜ ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์œผ๋กœ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: diff --git a/docs/ko/docs/tutorial/schema-extra-example.md b/docs/ko/docs/tutorial/schema-extra-example.md index b2b54836ac..a1d0c84689 100644 --- a/docs/ko/docs/tutorial/schema-extra-example.md +++ b/docs/ko/docs/tutorial/schema-extra-example.md @@ -74,7 +74,7 @@ Pydantic ๋ชจ๋ธ๊ณผ ๊ฐ™์ด `Field()`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ถ”๊ฐ€์ ์ธ `examples`๋ฅผ ์ด์™€ ๊ฐ™์ด ํ•˜๋ฉด ์˜ˆ์ œ๋“ค์€ ๊ทธ ๋ณธ๋ฌธ ๋ฐ์ดํ„ฐ์˜ ๋‚ด๋ถ€ **JSON ์Šคํ‚ค๋งˆ**์˜ ์ผ๋ถ€๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์ง€๊ธˆ ์ด ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ๊ฐ„์—, ๋ฌธ์„œ UI๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ๋งก์€ Swagger UI๋Š” **JSON ์Šคํ‚ค๋งˆ** ์† ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ ์˜ˆ์ œ์˜ ํ‘œํ˜„์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ์„ ๋ฐ‘์—์„œ ์ฝ์–ด๋ณด์„ธ์š”. +๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์ง€๊ธˆ ์ด ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ๊ฐ„์—, ๋ฌธ์„œ UI๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ๋งก์€ Swagger UI๋Š” **JSON ์Šคํ‚ค๋งˆ** ์† ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ ์˜ˆ์ œ์˜ ํ‘œํ˜„์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ์„ ๋ฐ‘์—์„œ ์ฝ์–ด๋ณด์„ธ์š”. ### OpenAPI-ํŠนํ™” `examples` { #openapi-specific-examples } diff --git a/docs/ko/docs/tutorial/security/first-steps.md b/docs/ko/docs/tutorial/security/first-steps.md index 4c9181b31e..57b336d52d 100644 --- a/docs/ko/docs/tutorial/security/first-steps.md +++ b/docs/ko/docs/tutorial/security/first-steps.md @@ -20,7 +20,7 @@ ์˜ˆ์ œ๋ฅผ ํŒŒ์ผ `main.py`์— ๋ณต์‚ฌํ•˜์„ธ์š”: -{* ../../docs_src/security/tutorial001_an_py39.py *} +{* ../../docs_src/security/tutorial001_an_py310.py *} ## ์‹คํ–‰ํ•˜๊ธฐ { #run-it } @@ -132,7 +132,7 @@ OAuth2๋Š” backend ๋˜๋Š” API๊ฐ€ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๋Š” ์„œ๋ฒ„์™€ ๋…๋ฆฝ์ ์ผ `OAuth2PasswordBearer` ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ `tokenUrl` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ํด๋ผ์ด์–ธํŠธ(์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” frontend)๊ฐ€ token์„ ๋ฐ›๊ธฐ ์œ„ํ•ด `username`๊ณผ `password`๋ฅผ ๋ณด๋‚ผ URL์ด ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} /// tip | ํŒ @@ -170,7 +170,7 @@ oauth2_scheme(some, parameters) ์ด์ œ `Depends`๋กœ `oauth2_scheme`๋ฅผ ์˜์กด์„ฑ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ์ด ์˜์กด์„ฑ์€ `str`์„ ์ œ๊ณตํ•˜๊ณ , ๊ทธ ๊ฐ’์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ํŒŒ๋ผ๋ฏธํ„ฐ `token`์— ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/security/get-current-user.md b/docs/ko/docs/tutorial/security/get-current-user.md index f21a22b7a0..eab599e275 100644 --- a/docs/ko/docs/tutorial/security/get-current-user.md +++ b/docs/ko/docs/tutorial/security/get-current-user.md @@ -2,7 +2,7 @@ ์ด์ „ ์žฅ์—์„œ (์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ) ๋ณด์•ˆ ์‹œ์Šคํ…œ์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์— `str`๋กœ `token`์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *} +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} ํ•˜์ง€๋งŒ ์ด๋Š” ์—ฌ์ „ํžˆ ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md index 907795ca4b..f9c4cc2ff3 100644 --- a/docs/ko/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # ํŒจ์Šค์›Œ๋“œ(ํ•ด์‹ฑ ํฌํ•จ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” OAuth2, JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -๋ชจ๋“  ๋ณด์•ˆ ํ๋ฆ„์„ ๊ตฌ์„ฑํ–ˆ์œผ๋ฏ€๋กœ, ์ด์ œ JWT ํ† ํฐ๊ณผ ์•ˆ์ „ํ•œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ์„ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹ค์ œ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. +๋ชจ๋“  ๋ณด์•ˆ ํ๋ฆ„์„ ๊ตฌ์„ฑํ–ˆ์œผ๋ฏ€๋กœ, ์ด์ œ JWT ํ† ํฐ๊ณผ ์•ˆ์ „ํ•œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ์„ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹ค์ œ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŒจ์Šค์›Œ๋“œ ํ•ด์‹œ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info +/// info | ์ •๋ณด RSA๋‚˜ ECDSA ๊ฐ™์€ ์ „์ž ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•  ๊ณ„ํš์ด๋ผ๋ฉด, cryptography ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ์ธ `pyjwt[crypto]`๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @@ -84,7 +84,7 @@ $ pip install "pwdlib[argon2]"
-/// tip +/// tip | ํŒ `pwdlib`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด **Django**, **Flask** ๋ณด์•ˆ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋กœ ์ƒ์„ฑํ•œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -100,7 +100,7 @@ $ pip install "pwdlib[argon2]" ๊ถŒ์žฅ ์„ค์ •์œผ๋กœ PasswordHash ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•ด์‹ฑํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -/// tip +/// tip | ํŒ pwdlib๋Š” bcrypt ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ์ง€์›ํ•˜์ง€๋งŒ ๋ ˆ๊ฑฐ์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ค๋ž˜๋œ ํ•ด์‹œ๋กœ ์ž‘์—…ํ•ด์•ผ ํ•œ๋‹ค๋ฉด passlib ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. @@ -116,9 +116,13 @@ pwdlib๋Š” bcrypt ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ์ง€์›ํ•˜์ง€๋งŒ ๋ ˆ๊ฑฐ์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} -/// note +`authenticate_user`๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž์ด๋ฆ„์œผ๋กœ ํ˜ธ์ถœ๋˜๋”๋ผ๋„, ์—ฌ์ „ํžˆ `verify_password`๋ฅผ ๋”๋ฏธ ํ•ด์‹œ์— ๋Œ€ํ•ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž์ด๋ฆ„์ด ์œ ํšจํ•˜๋“  ์•„๋‹ˆ๋“  ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์‘๋‹ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์ด ๋Œ€๋žต ๋™์ผํ•ด์ ธ, ๊ธฐ์กด ์‚ฌ์šฉ์ž์ด๋ฆ„์„ ์—ด๊ฑฐํ•˜๋Š” ๋ฐ ์•…์šฉ๋  ์ˆ˜ ์žˆ๋Š” **ํƒ€์ด๋ฐ ๊ณต๊ฒฉ**์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. + +/// note | ์ฐธ๊ณ  ์ƒˆ๋กœ์šด (๊ฐ€์งœ) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค `fake_users_db`๋ฅผ ํ™•์ธํ•˜๋ฉด, ์ด์ œ ํ•ด์‹œ ์ฒ˜๋ฆฌ๋œ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. @@ -152,7 +156,7 @@ JWT ํ† ํฐ์„ ์„œ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•œ ๋ณ€์ˆ˜ `ALGORITH ์ƒˆ ์•ก์„ธ์Šค ํ† ํฐ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} ## ์˜์กด์„ฑ ์—…๋ฐ์ดํŠธ { #update-the-dependencies } @@ -162,7 +166,7 @@ JWT ํ† ํฐ์„ ์„œ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•œ ๋ณ€์ˆ˜ `ALGORITH ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด ์ฆ‰์‹œ HTTP ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} ## `/token` *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์—…๋ฐ์ดํŠธ { #update-the-token-path-operation } @@ -170,7 +174,7 @@ JWT ํ† ํฐ์„ ์„œ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•œ ๋ณ€์ˆ˜ `ALGORITH ์‹ค์ œ JWT ์•ก์„ธ์Šค ํ† ํฐ์„ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} ### JWT "์ฃผ์ฒด(subject)" `sub`์— ๋Œ€ํ•œ ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ { #technical-details-about-the-jwt-subject-sub } @@ -209,7 +213,7 @@ JWT๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ API์—์„œ ์ง์ ‘ ์ž‘์—…์„ ์ˆ˜ํ–‰ Username: `johndoe` Password: `secret` -/// check +/// check | ํ™•์ธ ์ฝ”๋“œ ์–ด๋””์—๋„ ํ‰๋ฌธ ํŒจ์Šค์›Œ๋“œ "`secret`"์€ ์—†๊ณ , ํ•ด์‹œ๋œ ๋ฒ„์ „๋งŒ ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค. @@ -234,7 +238,7 @@ Password: `secret` -/// note +/// note | ์ฐธ๊ณ  `Bearer `๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฐ’์„ ๊ฐ€์ง„ `Authorization` ํ—ค๋”์— ์ฃผ๋ชฉํ•˜์‹ญ์‹œ์˜ค. diff --git a/docs/ko/docs/tutorial/security/simple-oauth2.md b/docs/ko/docs/tutorial/security/simple-oauth2.md index 189dd89f2a..918c94b25f 100644 --- a/docs/ko/docs/tutorial/security/simple-oauth2.md +++ b/docs/ko/docs/tutorial/security/simple-oauth2.md @@ -162,7 +162,7 @@ UserInDB( /// tip | ํŒ -๋‹ค์Œ ์žฅ์—์„œ๋Š” ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ฐ JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ๋ณด์•ˆ ๊ตฌํ˜„์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๋‹ค์Œ ์žฅ์—์„œ๋Š” ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ฐ JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ๋ณด์•ˆ ๊ตฌํ˜„์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ํ•„์š”ํ•œ ์„ธ๋ถ€ ์ •๋ณด์— ์ง‘์ค‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. @@ -286,4 +286,4 @@ UserInDB( ์œ ์ผํ•œ ์˜ค์ ์€ ์•„์ง ์‹ค์ œ๋กœ "์•ˆ์ „"ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. -๋‹ค์Œ ์žฅ์—์„œ๋Š” ์•ˆ์ „ํ•œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. +๋‹ค์Œ ์žฅ์—์„œ๋Š” ์•ˆ์ „ํ•œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/tutorial/sql-databases.md b/docs/ko/docs/tutorial/sql-databases.md index 3d64cf627a..20c1367164 100644 --- a/docs/ko/docs/tutorial/sql-databases.md +++ b/docs/ko/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ /// tip | ํŒ -๋‹ค๋ฅธ SQL ๋˜๋Š” NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค (์ผ๋ถ€๋Š” "ORMs"์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค), FastAPI๋Š” ํŠน์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์‚ฌ์šฉ์„ ๊ฐ•์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž +๋‹ค๋ฅธ SQL ๋˜๋Š” NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค (์ผ๋ถ€๋Š” "ORMs"์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค), FastAPI๋Š” ํŠน์ • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์‚ฌ์šฉ์„ ๊ฐ•์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž /// diff --git a/docs/ko/docs/tutorial/static-files.md b/docs/ko/docs/tutorial/static-files.md index aa4c571793..0235d83c7f 100644 --- a/docs/ko/docs/tutorial/static-files.md +++ b/docs/ko/docs/tutorial/static-files.md @@ -7,7 +7,7 @@ * `StaticFiles`๋ฅผ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค. * ํŠน์ • ๊ฒฝ๋กœ์— `StaticFiles()` ์ธ์Šคํ„ด์Šค๋ฅผ "๋งˆ์šดํŠธ"ํ•ฉ๋‹ˆ๋‹ค. -{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *} +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} /// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ diff --git a/docs/ko/docs/tutorial/testing.md b/docs/ko/docs/tutorial/testing.md index db7fb17ead..57ab811515 100644 --- a/docs/ko/docs/tutorial/testing.md +++ b/docs/ko/docs/tutorial/testing.md @@ -2,7 +2,7 @@ Starlette ๋•๋ถ„์— **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ์ผ์€ ์‰ฝ๊ณ  ์ฆ๊ฑฐ์šด ์ผ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. -Starlette๋Š” HTTPX๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋Š” Requests๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ์นœ์ˆ™ํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. +์ด๋Š” HTTPX๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋Š” Requests๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ์นœ์ˆ™ํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด **FastAPI**์—์„œ pytest๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -30,7 +30,7 @@ $ pip install httpx ํ‘œ์ค€์ ์ธ ํŒŒ์ด์ฌ ํ‘œํ˜„์‹์œผ๋กœ ํ™•์ธ์ด ํ•„์š”ํ•œ ๊ณณ์— ๊ฐ„๋‹จํ•œ `assert` ๋ฌธ์žฅ์„ ์ž‘์„ฑํ•˜์„ธ์š”(์—ญ์‹œ ํ‘œ์ค€์ ์ธ `pytest` ๊ด€๋ก€์ž…๋‹ˆ๋‹ค). -{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *} +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip | ํŒ @@ -42,7 +42,7 @@ $ pip install httpx /// -/// note Technical Details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ +/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ `from starlette.testclient import TestClient` ์—ญ์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -76,7 +76,7 @@ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ ์™ธ์—๋„ ํ…Œ์ŠคํŠธ์—์„œ `main.py` ํŒŒ์ผ ์•ˆ์— **FastAPI** app ์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค: -{* ../../docs_src/app_testing/app_a_py39/main.py *} +{* ../../docs_src/app_testing/app_a_py310/main.py *} ### ํ…Œ์ŠคํŠธ ํŒŒ์ผ { #testing-file } @@ -92,7 +92,7 @@ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ ์™ธ์—๋„ ํ…Œ์ŠคํŠธ์—์„œ ํŒŒ์ผ๋“ค์ด ๋™์ผํ•œ ํŒจํ‚ค์ง€์— ์œ„์น˜ํ•ด ์žˆ์œผ๋ฏ€๋กœ, ์ƒ๋Œ€ ์ž„ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `main` ๋ชจ๋“ˆ(`main.py`)์—์„œ `app` ๊ฐ์ฒด๋ฅผ ์ž„ํฌํŠธ ํ•ด์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *} +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...๊ทธ๋ฆฌ๊ณ  ์ด์ „์— ์ž‘์„ฑํ–ˆ๋˜ ๊ฒƒ๊ณผ ๊ฐ™์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -115,7 +115,7 @@ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ ์™ธ์—๋„ ํ…Œ์ŠคํŠธ์—์„œ ์ด์ œ **FastAPI** ์•ฑ์ด ์žˆ๋Š” `main.py` ํŒŒ์ผ์— ๋ช‡ ๊ฐ€์ง€ ๋‹ค๋ฅธ **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ**๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค. -๋‹จ์ผ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” `GET` ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. +์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” `GET` ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” `POST` ์ž‘์—…์ด ์žˆ์Šต๋‹ˆ๋‹ค. diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md index b639f8a3e4..e6baef73b4 100644 --- a/docs/ko/docs/virtual-environments.md +++ b/docs/ko/docs/virtual-environments.md @@ -37,15 +37,15 @@ Python ์„ค์น˜๊นŒ์ง€ ํฌํ•จํ•ด **๋ชจ๋“  ๊ฒƒ์„ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๋„๊ตฌ**๋ฅผ ๋„์ž…
```console -// Go to the home directory +// ํ™ˆ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ $ cd -// Create a directory for all your code projects +// ๋ชจ๋“  ์ฝ”๋“œ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ $ mkdir code -// Enter into that code directory +// ๊ทธ code ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ $ cd code -// Create a directory for this project +// ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ $ mkdir awesome-project -// Enter into that project directory +// ๊ทธ ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ $ cd awesome-project ``` @@ -53,7 +53,7 @@ $ cd awesome-project ## ๊ฐ€์ƒ ํ™˜๊ฒฝ ์ƒ์„ฑ { #create-a-virtual-environment } -Python ํ”„๋กœ์ ํŠธ๋ฅผ **์ฒ˜์Œ ์‹œ์ž‘ํ•  ๋•Œ**, **ํ”„๋กœ์ ํŠธ ๋‚ด๋ถ€**์— ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ์ƒ์„ฑํ•˜์„ธ์š”. +Python ํ”„๋กœ์ ํŠธ๋ฅผ **์ฒ˜์Œ ์‹œ์ž‘ํ•  ๋•Œ**, ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ **ํ”„๋กœ์ ํŠธ ๋‚ด๋ถ€**์— ์ƒ์„ฑํ•˜์„ธ์š”. /// tip @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate ํ•ด๋‹น ํ™˜๊ฒฝ์— **์ƒˆ ํŒจํ‚ค์ง€**๋ฅผ ์„ค์น˜ํ•  ๋•Œ๋งˆ๋‹ค, ํ™˜๊ฒฝ์„ ๋‹ค์‹œ **ํ™œ์„ฑํ™”**ํ•˜์„ธ์š”. -์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ํŒจํ‚ค์ง€๊ฐ€ ์„ค์น˜ํ•œ **ํ„ฐ๋ฏธ๋„(CLI) ํ”„๋กœ๊ทธ๋žจ**์„ ์‚ฌ์šฉํ•  ๋•Œ, ์ „์—ญ์œผ๋กœ ์„ค์น˜๋˜์–ด ์žˆ์„ ์ˆ˜๋„ ์žˆ๋Š”(์•„๋งˆ ํ•„์š”ํ•œ ๋ฒ„์ „๊ณผ๋Š” ๋‹ค๋ฅธ ๋ฒ„์ „์ธ) ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์ด ์•„๋‹ˆ๋ผ ๊ฐ€์ƒ ํ™˜๊ฒฝ์— ์žˆ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. +์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ํŒจํ‚ค์ง€๊ฐ€ ์„ค์น˜ํ•œ **ํ„ฐ๋ฏธ๋„(CLI) ํ”„๋กœ๊ทธ๋žจ**์„ ์‚ฌ์šฉํ•  ๋•Œ, ์ „์—ญ์œผ๋กœ ์„ค์น˜๋˜์–ด ์žˆ์„ ์ˆ˜๋„ ์žˆ๋Š”(์•„๋งˆ ํ•„์š”ํ•œ ๋ฒ„์ „๊ณผ๋Š” ๋‹ค๋ฅธ ๋ฒ„์ „์ธ) ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์ด ์•„๋‹ˆ๋ผ ๊ฐ€์ƒ ํ™˜๊ฒฝ์— ์žˆ๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. /// @@ -557,7 +557,7 @@ Python์„ ์„ค์น˜ํ•˜๋ฉด ์ปดํ“จํ„ฐ์— ๋ช‡๋ช‡ ํŒŒ์ผ์ด ๋“ค์–ด ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ
```console -// Don't run this now, it's just an example ๐Ÿค“ +// ์ง€๊ธˆ์€ ์‹คํ–‰ํ•˜์ง€ ๋งˆ์„ธ์š”, ์˜ˆ์‹œ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค ๐Ÿค“ $ pip install "fastapi[standard]" ---> 100% ``` @@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Error importing sirius, it's not installed ๐Ÿ˜ฑ +// sirius ์ž„ํฌํŠธ ์˜ค๋ฅ˜, ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๐Ÿ˜ฑ Traceback (most recent call last): File "main.py", line 1, in import sirius @@ -826,13 +826,13 @@ Traceback (most recent call last): ```console $ cd ~/code/prisoner-of-azkaban -// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project ๐Ÿ˜Ž +// ๋น„ํ™œ์„ฑํ™”๋ฅผ ์œ„ํ•ด ์ด์ „ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ์„ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์–ด๋””์„œ๋“ , ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋กœ ์ด๋™ํ•œ ๋’ค์—๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜Ž $ deactivate -// Activate the virtual environment in prisoner-of-azkaban/.venv ๐Ÿš€ +// prisoner-of-azkaban/.venv์˜ ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ํ™œ์„ฑํ™”ํ•˜์„ธ์š” ๐Ÿš€ $ source .venv/bin/activate -// Now when you run python, it will find the package sirius installed in this virtual environment โœจ +// ์ด์ œ python์„ ์‹คํ–‰ํ•˜๋ฉด, ์ด ๊ฐ€์ƒ ํ™˜๊ฒฝ์— ์„ค์น˜๋œ sirius ํŒจํ‚ค์ง€๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค โœจ $ python main.py I solemnly swear ๐Ÿบ From ed12105cced91614d5833857f51f7ccff0eeb03d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 14 Feb 2026 08:57:26 +0000 Subject: [PATCH 244/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 61366bb84f..5e1435065c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* ๐ŸŒ Update translations for ko (update-all and add-missing). PR [#14923](https://github.com/fastapi/fastapi/pull/14923) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for uk (add-missing). PR [#14922](https://github.com/fastapi/fastapi/pull/14922) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh-hant (update-all and add-missing). PR [#14921](https://github.com/fastapi/fastapi/pull/14921) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for fr (update-all and add-missing). PR [#14920](https://github.com/fastapi/fastapi/pull/14920) by [@YuriiMotov](https://github.com/YuriiMotov). From bbb96d4a0abda689664582958eeb28e10179e6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 17 Feb 2026 00:08:04 -0800 Subject: [PATCH 245/367] =?UTF-8?q?=F0=9F=94=A5=20Remove=20Python=203.9=20?= =?UTF-8?q?specific=20files,=20no=20longer=20needed=20after=20updating=20t?= =?UTF-8?q?ranslations=20(#14931)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../additional_responses/tutorial001_py39.py | 22 ----- .../additional_responses/tutorial003_py39.py | 37 --------- .../advanced_middleware/tutorial001_py39.py | 11 --- .../advanced_middleware/tutorial002_py39.py | 13 --- .../advanced_middleware/tutorial003_py39.py | 11 --- docs_src/app_testing/app_a_py39/__init__.py | 0 docs_src/app_testing/app_a_py39/main.py | 8 -- docs_src/app_testing/app_a_py39/test_main.py | 11 --- docs_src/app_testing/tutorial001_py39.py | 18 ----- docs_src/app_testing/tutorial002_py39.py | 31 ------- docs_src/app_testing/tutorial003_py39.py | 24 ------ docs_src/app_testing/tutorial004_py39.py | 43 ---------- docs_src/async_tests/app_a_py39/__init__.py | 0 docs_src/async_tests/app_a_py39/main.py | 8 -- docs_src/async_tests/app_a_py39/test_main.py | 14 ---- .../tutorial001_an_py39.py | 21 ----- docs_src/background_tasks/tutorial001_py39.py | 15 ---- .../behind_a_proxy/tutorial001_01_py39.py | 8 -- docs_src/behind_a_proxy/tutorial001_py39.py | 8 -- docs_src/behind_a_proxy/tutorial002_py39.py | 8 -- docs_src/behind_a_proxy/tutorial003_py39.py | 14 ---- docs_src/behind_a_proxy/tutorial004_py39.py | 15 ---- .../app_an_py39/__init__.py | 0 .../app_an_py39/dependencies.py | 13 --- .../app_an_py39/internal/__init__.py | 0 .../app_an_py39/internal/admin.py | 8 -- .../bigger_applications/app_an_py39/main.py | 23 ------ .../app_an_py39/routers/__init__.py | 0 .../app_an_py39/routers/items.py | 38 --------- .../app_an_py39/routers/users.py | 18 ----- .../bigger_applications/app_py39/__init__.py | 0 .../app_py39/dependencies.py | 11 --- docs_src/bigger_applications/app_py39/main.py | 23 ------ .../body_nested_models/tutorial008_py39.py | 14 ---- .../body_nested_models/tutorial009_py39.py | 8 -- .../conditional_openapi/tutorial001_py39.py | 16 ---- .../configure_swagger_ui/tutorial001_py39.py | 8 -- .../configure_swagger_ui/tutorial002_py39.py | 8 -- .../configure_swagger_ui/tutorial003_py39.py | 8 -- docs_src/cors/tutorial001_py39.py | 24 ------ docs_src/custom_docs_ui/tutorial001_py39.py | 38 --------- docs_src/custom_docs_ui/tutorial002_py39.py | 41 ---------- docs_src/custom_response/tutorial001_py39.py | 9 --- docs_src/custom_response/tutorial001b_py39.py | 9 --- docs_src/custom_response/tutorial002_py39.py | 18 ----- docs_src/custom_response/tutorial003_py39.py | 19 ----- docs_src/custom_response/tutorial004_py39.py | 23 ------ docs_src/custom_response/tutorial005_py39.py | 9 --- docs_src/custom_response/tutorial006_py39.py | 9 --- docs_src/custom_response/tutorial006b_py39.py | 9 --- docs_src/custom_response/tutorial006c_py39.py | 9 --- docs_src/custom_response/tutorial007_py39.py | 14 ---- docs_src/custom_response/tutorial008_py39.py | 14 ---- docs_src/custom_response/tutorial009_py39.py | 10 --- docs_src/custom_response/tutorial009b_py39.py | 10 --- docs_src/custom_response/tutorial009c_py39.py | 19 ----- docs_src/custom_response/tutorial010_py39.py | 9 --- docs_src/debugging/tutorial001_py39.py | 15 ---- docs_src/dependencies/tutorial006_an_py39.py | 21 ----- docs_src/dependencies/tutorial006_py39.py | 19 ----- docs_src/dependencies/tutorial007_py39.py | 6 -- docs_src/dependencies/tutorial008_an_py39.py | 27 ------- docs_src/dependencies/tutorial008_py39.py | 25 ------ docs_src/dependencies/tutorial008b_an_py39.py | 32 -------- docs_src/dependencies/tutorial008b_py39.py | 30 ------- docs_src/dependencies/tutorial008c_an_py39.py | 29 ------- docs_src/dependencies/tutorial008c_py39.py | 27 ------- docs_src/dependencies/tutorial008d_an_py39.py | 30 ------- docs_src/dependencies/tutorial008d_py39.py | 28 ------- docs_src/dependencies/tutorial008e_an_py39.py | 17 ---- docs_src/dependencies/tutorial008e_py39.py | 15 ---- docs_src/dependencies/tutorial010_py39.py | 14 ---- docs_src/dependencies/tutorial011_an_py39.py | 23 ------ docs_src/dependencies/tutorial011_py39.py | 21 ----- docs_src/dependencies/tutorial012_an_py39.py | 27 ------- docs_src/dependencies/tutorial012_py39.py | 25 ------ docs_src/events/tutorial001_py39.py | 16 ---- docs_src/events/tutorial002_py39.py | 14 ---- docs_src/events/tutorial003_py39.py | 28 ------- .../extending_openapi/tutorial001_py39.py | 29 ------- docs_src/extra_models/tutorial004_py39.py | 20 ----- docs_src/extra_models/tutorial005_py39.py | 8 -- docs_src/first_steps/tutorial001_py39.py | 8 -- docs_src/first_steps/tutorial003_py39.py | 8 -- docs_src/generate_clients/tutorial001_py39.py | 26 ------ docs_src/generate_clients/tutorial002_py39.py | 36 --------- docs_src/generate_clients/tutorial003_py39.py | 42 ---------- docs_src/generate_clients/tutorial004_py39.py | 15 ---- docs_src/graphql_/tutorial001_py39.py | 25 ------ docs_src/handling_errors/tutorial001_py39.py | 12 --- docs_src/handling_errors/tutorial002_py39.py | 16 ---- docs_src/handling_errors/tutorial003_py39.py | 25 ------ docs_src/handling_errors/tutorial004_py39.py | 26 ------ docs_src/handling_errors/tutorial005_py39.py | 25 ------ docs_src/handling_errors/tutorial006_py39.py | 28 ------- docs_src/metadata/tutorial001_1_py39.py | 38 --------- docs_src/metadata/tutorial001_py39.py | 38 --------- docs_src/metadata/tutorial002_py39.py | 8 -- docs_src/metadata/tutorial003_py39.py | 8 -- docs_src/metadata/tutorial004_py39.py | 28 ------- docs_src/middleware/tutorial001_py39.py | 14 ---- docs_src/openapi_webhooks/tutorial001_py39.py | 25 ------ .../tutorial001_py39.py | 8 -- .../tutorial002_py39.py | 24 ------ .../tutorial003_py39.py | 8 -- .../tutorial005_py39.py | 8 -- .../tutorial006_py39.py | 41 ---------- .../tutorial007_py39.py | 32 -------- .../tutorial002b_py39.py | 20 ----- .../tutorial006_py39.py | 18 ----- docs_src/path_params/tutorial001_py39.py | 8 -- docs_src/path_params/tutorial002_py39.py | 8 -- docs_src/path_params/tutorial003_py39.py | 13 --- docs_src/path_params/tutorial003b_py39.py | 13 --- docs_src/path_params/tutorial004_py39.py | 8 -- docs_src/path_params/tutorial005_py39.py | 23 ------ .../tutorial002_an_py39.py | 15 ---- .../tutorial002_py39.py | 11 --- .../tutorial003_an_py39.py | 15 ---- .../tutorial003_py39.py | 11 --- .../tutorial004_an_py39.py | 15 ---- .../tutorial004_py39.py | 13 --- .../tutorial005_an_py39.py | 16 ---- .../tutorial005_py39.py | 15 ---- .../tutorial006_an_py39.py | 20 ----- .../tutorial006_py39.py | 18 ----- docs_src/python_types/tutorial001_py39.py | 6 -- docs_src/python_types/tutorial002_py39.py | 6 -- docs_src/python_types/tutorial003_py39.py | 3 - docs_src/python_types/tutorial004_py39.py | 3 - docs_src/python_types/tutorial006_py39.py | 3 - docs_src/python_types/tutorial007_py39.py | 2 - docs_src/python_types/tutorial008_py39.py | 4 - docs_src/python_types/tutorial008b_py39.py | 5 -- docs_src/python_types/tutorial009_py39.py | 8 -- docs_src/python_types/tutorial009b_py39.py | 8 -- docs_src/python_types/tutorial009c_py310.py | 2 - docs_src/python_types/tutorial009c_py39.py | 5 -- docs_src/python_types/tutorial010_py39.py | 7 -- docs_src/python_types/tutorial013_py39.py | 5 -- docs_src/query_params/tutorial001_py39.py | 10 --- docs_src/query_params/tutorial005_py39.py | 9 --- .../tutorial005_an_py39.py | 13 --- .../tutorial005_py39.py | 11 --- .../tutorial006_an_py39.py | 13 --- .../tutorial006_py39.py | 11 --- .../tutorial012_an_py39.py | 11 --- .../tutorial012_py39.py | 9 --- .../tutorial013_an_py39.py | 11 --- .../tutorial013_py39.py | 9 --- .../request_files/tutorial001_03_an_py39.py | 17 ---- docs_src/request_files/tutorial001_03_py39.py | 15 ---- docs_src/request_files/tutorial001_an_py39.py | 15 ---- docs_src/request_files/tutorial001_py39.py | 13 --- docs_src/request_files/tutorial002_an_py39.py | 33 -------- docs_src/request_files/tutorial002_py39.py | 31 ------- docs_src/request_files/tutorial003_an_py39.py | 39 --------- docs_src/request_files/tutorial003_py39.py | 35 -------- .../tutorial001_an_py39.py | 16 ---- .../request_form_models/tutorial001_py39.py | 14 ---- .../tutorial002_an_py39.py | 17 ---- .../request_form_models/tutorial002_py39.py | 15 ---- docs_src/request_forms/tutorial001_an_py39.py | 10 --- docs_src/request_forms/tutorial001_py39.py | 8 -- .../tutorial001_an_py39.py | 18 ----- .../tutorial001_py39.py | 14 ---- .../tutorial001_py39.py | 13 --- docs_src/response_cookies/tutorial001_py39.py | 12 --- docs_src/response_cookies/tutorial002_py39.py | 9 --- .../response_directly/tutorial002_py39.py | 18 ----- docs_src/response_headers/tutorial001_py39.py | 11 --- docs_src/response_headers/tutorial002_py39.py | 9 --- .../response_model/tutorial003_02_py39.py | 11 --- .../response_model/tutorial003_03_py39.py | 9 --- .../response_status_code/tutorial001_py39.py | 8 -- .../response_status_code/tutorial002_py39.py | 8 -- docs_src/security/tutorial001_an_py39.py | 13 --- docs_src/security/tutorial001_py39.py | 11 --- docs_src/security/tutorial006_an_py39.py | 13 --- docs_src/security/tutorial006_py39.py | 11 --- docs_src/security/tutorial007_an_py39.py | 36 --------- docs_src/security/tutorial007_py39.py | 33 -------- docs_src/settings/app01_py39/__init__.py | 0 docs_src/settings/app01_py39/config.py | 10 --- docs_src/settings/app01_py39/main.py | 14 ---- docs_src/settings/app02_an_py39/__init__.py | 0 docs_src/settings/app02_an_py39/config.py | 7 -- docs_src/settings/app02_an_py39/main.py | 22 ----- docs_src/settings/app02_an_py39/test_main.py | 23 ------ docs_src/settings/app02_py39/__init__.py | 0 docs_src/settings/app02_py39/config.py | 7 -- docs_src/settings/app02_py39/main.py | 21 ----- docs_src/settings/app02_py39/test_main.py | 23 ------ docs_src/settings/app03_an_py39/__init__.py | 0 docs_src/settings/app03_an_py39/config.py | 9 --- docs_src/settings/app03_an_py39/main.py | 22 ----- docs_src/settings/app03_py39/__init__.py | 0 docs_src/settings/app03_py39/config.py | 9 --- docs_src/settings/app03_py39/main.py | 21 ----- docs_src/settings/tutorial001_py39.py | 21 ----- docs_src/static_files/tutorial001_py39.py | 6 -- docs_src/sub_applications/tutorial001_py39.py | 19 ----- docs_src/templates/tutorial001_py39.py | 18 ----- .../tutorial001_py39.py | 9 --- docs_src/websockets/tutorial001_py39.py | 51 ------------ docs_src/websockets/tutorial003_py39.py | 81 ------------------- docs_src/wsgi/tutorial001_py39.py | 23 ------ .../test_code_includes/data/en_doc.md | 2 +- .../data/translated_doc_number_gt.md | 4 +- .../data/translated_doc_number_lt.md | 2 +- .../test_complex_doc/data/en_doc.md | 16 ++-- .../test_complex_doc/data/translated_doc.md | 16 ++-- .../data/translated_doc_expected.md | 16 ++-- .../test_python_types/test_tutorial009c.py | 33 -------- 214 files changed, 28 insertions(+), 3393 deletions(-) delete mode 100644 docs_src/additional_responses/tutorial001_py39.py delete mode 100644 docs_src/additional_responses/tutorial003_py39.py delete mode 100644 docs_src/advanced_middleware/tutorial001_py39.py delete mode 100644 docs_src/advanced_middleware/tutorial002_py39.py delete mode 100644 docs_src/advanced_middleware/tutorial003_py39.py delete mode 100644 docs_src/app_testing/app_a_py39/__init__.py delete mode 100644 docs_src/app_testing/app_a_py39/main.py delete mode 100644 docs_src/app_testing/app_a_py39/test_main.py delete mode 100644 docs_src/app_testing/tutorial001_py39.py delete mode 100644 docs_src/app_testing/tutorial002_py39.py delete mode 100644 docs_src/app_testing/tutorial003_py39.py delete mode 100644 docs_src/app_testing/tutorial004_py39.py delete mode 100644 docs_src/async_tests/app_a_py39/__init__.py delete mode 100644 docs_src/async_tests/app_a_py39/main.py delete mode 100644 docs_src/async_tests/app_a_py39/test_main.py delete mode 100644 docs_src/authentication_error_status_code/tutorial001_an_py39.py delete mode 100644 docs_src/background_tasks/tutorial001_py39.py delete mode 100644 docs_src/behind_a_proxy/tutorial001_01_py39.py delete mode 100644 docs_src/behind_a_proxy/tutorial001_py39.py delete mode 100644 docs_src/behind_a_proxy/tutorial002_py39.py delete mode 100644 docs_src/behind_a_proxy/tutorial003_py39.py delete mode 100644 docs_src/behind_a_proxy/tutorial004_py39.py delete mode 100644 docs_src/bigger_applications/app_an_py39/__init__.py delete mode 100644 docs_src/bigger_applications/app_an_py39/dependencies.py delete mode 100644 docs_src/bigger_applications/app_an_py39/internal/__init__.py delete mode 100644 docs_src/bigger_applications/app_an_py39/internal/admin.py delete mode 100644 docs_src/bigger_applications/app_an_py39/main.py delete mode 100644 docs_src/bigger_applications/app_an_py39/routers/__init__.py delete mode 100644 docs_src/bigger_applications/app_an_py39/routers/items.py delete mode 100644 docs_src/bigger_applications/app_an_py39/routers/users.py delete mode 100644 docs_src/bigger_applications/app_py39/__init__.py delete mode 100644 docs_src/bigger_applications/app_py39/dependencies.py delete mode 100644 docs_src/bigger_applications/app_py39/main.py delete mode 100644 docs_src/body_nested_models/tutorial008_py39.py delete mode 100644 docs_src/body_nested_models/tutorial009_py39.py delete mode 100644 docs_src/conditional_openapi/tutorial001_py39.py delete mode 100644 docs_src/configure_swagger_ui/tutorial001_py39.py delete mode 100644 docs_src/configure_swagger_ui/tutorial002_py39.py delete mode 100644 docs_src/configure_swagger_ui/tutorial003_py39.py delete mode 100644 docs_src/cors/tutorial001_py39.py delete mode 100644 docs_src/custom_docs_ui/tutorial001_py39.py delete mode 100644 docs_src/custom_docs_ui/tutorial002_py39.py delete mode 100644 docs_src/custom_response/tutorial001_py39.py delete mode 100644 docs_src/custom_response/tutorial001b_py39.py delete mode 100644 docs_src/custom_response/tutorial002_py39.py delete mode 100644 docs_src/custom_response/tutorial003_py39.py delete mode 100644 docs_src/custom_response/tutorial004_py39.py delete mode 100644 docs_src/custom_response/tutorial005_py39.py delete mode 100644 docs_src/custom_response/tutorial006_py39.py delete mode 100644 docs_src/custom_response/tutorial006b_py39.py delete mode 100644 docs_src/custom_response/tutorial006c_py39.py delete mode 100644 docs_src/custom_response/tutorial007_py39.py delete mode 100644 docs_src/custom_response/tutorial008_py39.py delete mode 100644 docs_src/custom_response/tutorial009_py39.py delete mode 100644 docs_src/custom_response/tutorial009b_py39.py delete mode 100644 docs_src/custom_response/tutorial009c_py39.py delete mode 100644 docs_src/custom_response/tutorial010_py39.py delete mode 100644 docs_src/debugging/tutorial001_py39.py delete mode 100644 docs_src/dependencies/tutorial006_an_py39.py delete mode 100644 docs_src/dependencies/tutorial006_py39.py delete mode 100644 docs_src/dependencies/tutorial007_py39.py delete mode 100644 docs_src/dependencies/tutorial008_an_py39.py delete mode 100644 docs_src/dependencies/tutorial008_py39.py delete mode 100644 docs_src/dependencies/tutorial008b_an_py39.py delete mode 100644 docs_src/dependencies/tutorial008b_py39.py delete mode 100644 docs_src/dependencies/tutorial008c_an_py39.py delete mode 100644 docs_src/dependencies/tutorial008c_py39.py delete mode 100644 docs_src/dependencies/tutorial008d_an_py39.py delete mode 100644 docs_src/dependencies/tutorial008d_py39.py delete mode 100644 docs_src/dependencies/tutorial008e_an_py39.py delete mode 100644 docs_src/dependencies/tutorial008e_py39.py delete mode 100644 docs_src/dependencies/tutorial010_py39.py delete mode 100644 docs_src/dependencies/tutorial011_an_py39.py delete mode 100644 docs_src/dependencies/tutorial011_py39.py delete mode 100644 docs_src/dependencies/tutorial012_an_py39.py delete mode 100644 docs_src/dependencies/tutorial012_py39.py delete mode 100644 docs_src/events/tutorial001_py39.py delete mode 100644 docs_src/events/tutorial002_py39.py delete mode 100644 docs_src/events/tutorial003_py39.py delete mode 100644 docs_src/extending_openapi/tutorial001_py39.py delete mode 100644 docs_src/extra_models/tutorial004_py39.py delete mode 100644 docs_src/extra_models/tutorial005_py39.py delete mode 100644 docs_src/first_steps/tutorial001_py39.py delete mode 100644 docs_src/first_steps/tutorial003_py39.py delete mode 100644 docs_src/generate_clients/tutorial001_py39.py delete mode 100644 docs_src/generate_clients/tutorial002_py39.py delete mode 100644 docs_src/generate_clients/tutorial003_py39.py delete mode 100644 docs_src/generate_clients/tutorial004_py39.py delete mode 100644 docs_src/graphql_/tutorial001_py39.py delete mode 100644 docs_src/handling_errors/tutorial001_py39.py delete mode 100644 docs_src/handling_errors/tutorial002_py39.py delete mode 100644 docs_src/handling_errors/tutorial003_py39.py delete mode 100644 docs_src/handling_errors/tutorial004_py39.py delete mode 100644 docs_src/handling_errors/tutorial005_py39.py delete mode 100644 docs_src/handling_errors/tutorial006_py39.py delete mode 100644 docs_src/metadata/tutorial001_1_py39.py delete mode 100644 docs_src/metadata/tutorial001_py39.py delete mode 100644 docs_src/metadata/tutorial002_py39.py delete mode 100644 docs_src/metadata/tutorial003_py39.py delete mode 100644 docs_src/metadata/tutorial004_py39.py delete mode 100644 docs_src/middleware/tutorial001_py39.py delete mode 100644 docs_src/openapi_webhooks/tutorial001_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial001_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial002_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial003_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial005_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial006_py39.py delete mode 100644 docs_src/path_operation_advanced_configuration/tutorial007_py39.py delete mode 100644 docs_src/path_operation_configuration/tutorial002b_py39.py delete mode 100644 docs_src/path_operation_configuration/tutorial006_py39.py delete mode 100644 docs_src/path_params/tutorial001_py39.py delete mode 100644 docs_src/path_params/tutorial002_py39.py delete mode 100644 docs_src/path_params/tutorial003_py39.py delete mode 100644 docs_src/path_params/tutorial003b_py39.py delete mode 100644 docs_src/path_params/tutorial004_py39.py delete mode 100644 docs_src/path_params/tutorial005_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial002_an_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial002_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial003_an_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial003_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial004_an_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial004_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial005_an_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial005_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial006_an_py39.py delete mode 100644 docs_src/path_params_numeric_validations/tutorial006_py39.py delete mode 100644 docs_src/python_types/tutorial001_py39.py delete mode 100644 docs_src/python_types/tutorial002_py39.py delete mode 100644 docs_src/python_types/tutorial003_py39.py delete mode 100644 docs_src/python_types/tutorial004_py39.py delete mode 100644 docs_src/python_types/tutorial006_py39.py delete mode 100644 docs_src/python_types/tutorial007_py39.py delete mode 100644 docs_src/python_types/tutorial008_py39.py delete mode 100644 docs_src/python_types/tutorial008b_py39.py delete mode 100644 docs_src/python_types/tutorial009_py39.py delete mode 100644 docs_src/python_types/tutorial009b_py39.py delete mode 100644 docs_src/python_types/tutorial009c_py310.py delete mode 100644 docs_src/python_types/tutorial009c_py39.py delete mode 100644 docs_src/python_types/tutorial010_py39.py delete mode 100644 docs_src/python_types/tutorial013_py39.py delete mode 100644 docs_src/query_params/tutorial001_py39.py delete mode 100644 docs_src/query_params/tutorial005_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial005_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial005_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial006_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial006_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial012_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial012_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial013_an_py39.py delete mode 100644 docs_src/query_params_str_validations/tutorial013_py39.py delete mode 100644 docs_src/request_files/tutorial001_03_an_py39.py delete mode 100644 docs_src/request_files/tutorial001_03_py39.py delete mode 100644 docs_src/request_files/tutorial001_an_py39.py delete mode 100644 docs_src/request_files/tutorial001_py39.py delete mode 100644 docs_src/request_files/tutorial002_an_py39.py delete mode 100644 docs_src/request_files/tutorial002_py39.py delete mode 100644 docs_src/request_files/tutorial003_an_py39.py delete mode 100644 docs_src/request_files/tutorial003_py39.py delete mode 100644 docs_src/request_form_models/tutorial001_an_py39.py delete mode 100644 docs_src/request_form_models/tutorial001_py39.py delete mode 100644 docs_src/request_form_models/tutorial002_an_py39.py delete mode 100644 docs_src/request_form_models/tutorial002_py39.py delete mode 100644 docs_src/request_forms/tutorial001_an_py39.py delete mode 100644 docs_src/request_forms/tutorial001_py39.py delete mode 100644 docs_src/request_forms_and_files/tutorial001_an_py39.py delete mode 100644 docs_src/request_forms_and_files/tutorial001_py39.py delete mode 100644 docs_src/response_change_status_code/tutorial001_py39.py delete mode 100644 docs_src/response_cookies/tutorial001_py39.py delete mode 100644 docs_src/response_cookies/tutorial002_py39.py delete mode 100644 docs_src/response_directly/tutorial002_py39.py delete mode 100644 docs_src/response_headers/tutorial001_py39.py delete mode 100644 docs_src/response_headers/tutorial002_py39.py delete mode 100644 docs_src/response_model/tutorial003_02_py39.py delete mode 100644 docs_src/response_model/tutorial003_03_py39.py delete mode 100644 docs_src/response_status_code/tutorial001_py39.py delete mode 100644 docs_src/response_status_code/tutorial002_py39.py delete mode 100644 docs_src/security/tutorial001_an_py39.py delete mode 100644 docs_src/security/tutorial001_py39.py delete mode 100644 docs_src/security/tutorial006_an_py39.py delete mode 100644 docs_src/security/tutorial006_py39.py delete mode 100644 docs_src/security/tutorial007_an_py39.py delete mode 100644 docs_src/security/tutorial007_py39.py delete mode 100644 docs_src/settings/app01_py39/__init__.py delete mode 100644 docs_src/settings/app01_py39/config.py delete mode 100644 docs_src/settings/app01_py39/main.py delete mode 100644 docs_src/settings/app02_an_py39/__init__.py delete mode 100644 docs_src/settings/app02_an_py39/config.py delete mode 100644 docs_src/settings/app02_an_py39/main.py delete mode 100644 docs_src/settings/app02_an_py39/test_main.py delete mode 100644 docs_src/settings/app02_py39/__init__.py delete mode 100644 docs_src/settings/app02_py39/config.py delete mode 100644 docs_src/settings/app02_py39/main.py delete mode 100644 docs_src/settings/app02_py39/test_main.py delete mode 100644 docs_src/settings/app03_an_py39/__init__.py delete mode 100644 docs_src/settings/app03_an_py39/config.py delete mode 100644 docs_src/settings/app03_an_py39/main.py delete mode 100644 docs_src/settings/app03_py39/__init__.py delete mode 100644 docs_src/settings/app03_py39/config.py delete mode 100644 docs_src/settings/app03_py39/main.py delete mode 100644 docs_src/settings/tutorial001_py39.py delete mode 100644 docs_src/static_files/tutorial001_py39.py delete mode 100644 docs_src/sub_applications/tutorial001_py39.py delete mode 100644 docs_src/templates/tutorial001_py39.py delete mode 100644 docs_src/using_request_directly/tutorial001_py39.py delete mode 100644 docs_src/websockets/tutorial001_py39.py delete mode 100644 docs_src/websockets/tutorial003_py39.py delete mode 100644 docs_src/wsgi/tutorial001_py39.py delete mode 100644 tests/test_tutorial/test_python_types/test_tutorial009c.py diff --git a/docs_src/additional_responses/tutorial001_py39.py b/docs_src/additional_responses/tutorial001_py39.py deleted file mode 100644 index ffa821b910..0000000000 --- a/docs_src/additional_responses/tutorial001_py39.py +++ /dev/null @@ -1,22 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import JSONResponse -from pydantic import BaseModel - - -class Item(BaseModel): - id: str - value: str - - -class Message(BaseModel): - message: str - - -app = FastAPI() - - -@app.get("/items/{item_id}", response_model=Item, responses={404: {"model": Message}}) -async def read_item(item_id: str): - if item_id == "foo": - return {"id": "foo", "value": "there goes my hero"} - return JSONResponse(status_code=404, content={"message": "Item not found"}) diff --git a/docs_src/additional_responses/tutorial003_py39.py b/docs_src/additional_responses/tutorial003_py39.py deleted file mode 100644 index f3e41e8d26..0000000000 --- a/docs_src/additional_responses/tutorial003_py39.py +++ /dev/null @@ -1,37 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import JSONResponse -from pydantic import BaseModel - - -class Item(BaseModel): - id: str - value: str - - -class Message(BaseModel): - message: str - - -app = FastAPI() - - -@app.get( - "/items/{item_id}", - response_model=Item, - responses={ - 404: {"model": Message, "description": "The item was not found"}, - 200: { - "description": "Item requested by ID", - "content": { - "application/json": { - "example": {"id": "bar", "value": "The bar tenders"} - } - }, - }, - }, -) -async def read_item(item_id: str): - if item_id == "foo": - return {"id": "foo", "value": "there goes my hero"} - else: - return JSONResponse(status_code=404, content={"message": "Item not found"}) diff --git a/docs_src/advanced_middleware/tutorial001_py39.py b/docs_src/advanced_middleware/tutorial001_py39.py deleted file mode 100644 index 35dbd30461..0000000000 --- a/docs_src/advanced_middleware/tutorial001_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware - -app = FastAPI() - -app.add_middleware(HTTPSRedirectMiddleware) - - -@app.get("/") -async def main(): - return {"message": "Hello World"} diff --git a/docs_src/advanced_middleware/tutorial002_py39.py b/docs_src/advanced_middleware/tutorial002_py39.py deleted file mode 100644 index 405235ab9b..0000000000 --- a/docs_src/advanced_middleware/tutorial002_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.trustedhost import TrustedHostMiddleware - -app = FastAPI() - -app.add_middleware( - TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"] -) - - -@app.get("/") -async def main(): - return {"message": "Hello World"} diff --git a/docs_src/advanced_middleware/tutorial003_py39.py b/docs_src/advanced_middleware/tutorial003_py39.py deleted file mode 100644 index e2c87e67d8..0000000000 --- a/docs_src/advanced_middleware/tutorial003_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.gzip import GZipMiddleware - -app = FastAPI() - -app.add_middleware(GZipMiddleware, minimum_size=1000, compresslevel=5) - - -@app.get("/") -async def main(): - return "somebigcontent" diff --git a/docs_src/app_testing/app_a_py39/__init__.py b/docs_src/app_testing/app_a_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/app_testing/app_a_py39/main.py b/docs_src/app_testing/app_a_py39/main.py deleted file mode 100644 index 4679aec9cc..0000000000 --- a/docs_src/app_testing/app_a_py39/main.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -async def read_main(): - return {"msg": "Hello World"} diff --git a/docs_src/app_testing/app_a_py39/test_main.py b/docs_src/app_testing/app_a_py39/test_main.py deleted file mode 100644 index ddc013f40c..0000000000 --- a/docs_src/app_testing/app_a_py39/test_main.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi.testclient import TestClient - -from .main import app - -client = TestClient(app) - - -def test_read_main(): - response = client.get("/") - assert response.status_code == 200 - assert response.json() == {"msg": "Hello World"} diff --git a/docs_src/app_testing/tutorial001_py39.py b/docs_src/app_testing/tutorial001_py39.py deleted file mode 100644 index 79a853b487..0000000000 --- a/docs_src/app_testing/tutorial001_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI -from fastapi.testclient import TestClient - -app = FastAPI() - - -@app.get("/") -async def read_main(): - return {"msg": "Hello World"} - - -client = TestClient(app) - - -def test_read_main(): - response = client.get("/") - assert response.status_code == 200 - assert response.json() == {"msg": "Hello World"} diff --git a/docs_src/app_testing/tutorial002_py39.py b/docs_src/app_testing/tutorial002_py39.py deleted file mode 100644 index 71c898b3cf..0000000000 --- a/docs_src/app_testing/tutorial002_py39.py +++ /dev/null @@ -1,31 +0,0 @@ -from fastapi import FastAPI -from fastapi.testclient import TestClient -from fastapi.websockets import WebSocket - -app = FastAPI() - - -@app.get("/") -async def read_main(): - return {"msg": "Hello World"} - - -@app.websocket("/ws") -async def websocket(websocket: WebSocket): - await websocket.accept() - await websocket.send_json({"msg": "Hello WebSocket"}) - await websocket.close() - - -def test_read_main(): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200 - assert response.json() == {"msg": "Hello World"} - - -def test_websocket(): - client = TestClient(app) - with client.websocket_connect("/ws") as websocket: - data = websocket.receive_json() - assert data == {"msg": "Hello WebSocket"} diff --git a/docs_src/app_testing/tutorial003_py39.py b/docs_src/app_testing/tutorial003_py39.py deleted file mode 100644 index ca6b45ce03..0000000000 --- a/docs_src/app_testing/tutorial003_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from fastapi import FastAPI -from fastapi.testclient import TestClient - -app = FastAPI() - -items = {} - - -@app.on_event("startup") -async def startup_event(): - items["foo"] = {"name": "Fighters"} - items["bar"] = {"name": "Tenders"} - - -@app.get("/items/{item_id}") -async def read_items(item_id: str): - return items[item_id] - - -def test_read_items(): - with TestClient(app) as client: - response = client.get("/items/foo") - assert response.status_code == 200 - assert response.json() == {"name": "Fighters"} diff --git a/docs_src/app_testing/tutorial004_py39.py b/docs_src/app_testing/tutorial004_py39.py deleted file mode 100644 index f83ac9ae9a..0000000000 --- a/docs_src/app_testing/tutorial004_py39.py +++ /dev/null @@ -1,43 +0,0 @@ -from contextlib import asynccontextmanager - -from fastapi import FastAPI -from fastapi.testclient import TestClient - -items = {} - - -@asynccontextmanager -async def lifespan(app: FastAPI): - items["foo"] = {"name": "Fighters"} - items["bar"] = {"name": "Tenders"} - yield - # clean up items - items.clear() - - -app = FastAPI(lifespan=lifespan) - - -@app.get("/items/{item_id}") -async def read_items(item_id: str): - return items[item_id] - - -def test_read_items(): - # Before the lifespan starts, "items" is still empty - assert items == {} - - with TestClient(app) as client: - # Inside the "with TestClient" block, the lifespan starts and items added - assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}} - - response = client.get("/items/foo") - assert response.status_code == 200 - assert response.json() == {"name": "Fighters"} - - # After the requests is done, the items are still there - assert items == {"foo": {"name": "Fighters"}, "bar": {"name": "Tenders"}} - - # The end of the "with TestClient" block simulates terminating the app, so - # the lifespan ends and items are cleaned up - assert items == {} diff --git a/docs_src/async_tests/app_a_py39/__init__.py b/docs_src/async_tests/app_a_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/async_tests/app_a_py39/main.py b/docs_src/async_tests/app_a_py39/main.py deleted file mode 100644 index 9594f859c7..0000000000 --- a/docs_src/async_tests/app_a_py39/main.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -async def root(): - return {"message": "Tomato"} diff --git a/docs_src/async_tests/app_a_py39/test_main.py b/docs_src/async_tests/app_a_py39/test_main.py deleted file mode 100644 index a57a31f7d8..0000000000 --- a/docs_src/async_tests/app_a_py39/test_main.py +++ /dev/null @@ -1,14 +0,0 @@ -import pytest -from httpx import ASGITransport, AsyncClient - -from .main import app - - -@pytest.mark.anyio -async def test_root(): - async with AsyncClient( - transport=ASGITransport(app=app), base_url="http://test" - ) as ac: - response = await ac.get("/") - assert response.status_code == 200 - assert response.json() == {"message": "Tomato"} diff --git a/docs_src/authentication_error_status_code/tutorial001_an_py39.py b/docs_src/authentication_error_status_code/tutorial001_an_py39.py deleted file mode 100644 index 7bbc2f717d..0000000000 --- a/docs_src/authentication_error_status_code/tutorial001_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer - -app = FastAPI() - - -class HTTPBearer403(HTTPBearer): - def make_not_authenticated_error(self) -> HTTPException: - return HTTPException( - status_code=status.HTTP_403_FORBIDDEN, detail="Not authenticated" - ) - - -CredentialsDep = Annotated[HTTPAuthorizationCredentials, Depends(HTTPBearer403())] - - -@app.get("/me") -def read_me(credentials: CredentialsDep): - return {"message": "You are authenticated", "token": credentials.credentials} diff --git a/docs_src/background_tasks/tutorial001_py39.py b/docs_src/background_tasks/tutorial001_py39.py deleted file mode 100644 index 1720a74333..0000000000 --- a/docs_src/background_tasks/tutorial001_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import BackgroundTasks, FastAPI - -app = FastAPI() - - -def write_notification(email: str, message=""): - with open("log.txt", mode="w") as email_file: - content = f"notification for {email}: {message}" - email_file.write(content) - - -@app.post("/send-notification/{email}") -async def send_notification(email: str, background_tasks: BackgroundTasks): - background_tasks.add_task(write_notification, email, message="some notification") - return {"message": "Notification sent in the background"} diff --git a/docs_src/behind_a_proxy/tutorial001_01_py39.py b/docs_src/behind_a_proxy/tutorial001_01_py39.py deleted file mode 100644 index 52b114395b..0000000000 --- a/docs_src/behind_a_proxy/tutorial001_01_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/") -def read_items(): - return ["plumbus", "portal gun"] diff --git a/docs_src/behind_a_proxy/tutorial001_py39.py b/docs_src/behind_a_proxy/tutorial001_py39.py deleted file mode 100644 index ede59ada11..0000000000 --- a/docs_src/behind_a_proxy/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI() - - -@app.get("/app") -def read_main(request: Request): - return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial002_py39.py b/docs_src/behind_a_proxy/tutorial002_py39.py deleted file mode 100644 index c1600cde9e..0000000000 --- a/docs_src/behind_a_proxy/tutorial002_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI(root_path="/api/v1") - - -@app.get("/app") -def read_main(request: Request): - return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial003_py39.py b/docs_src/behind_a_proxy/tutorial003_py39.py deleted file mode 100644 index 3b7d8be018..0000000000 --- a/docs_src/behind_a_proxy/tutorial003_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI( - servers=[ - {"url": "https://stag.example.com", "description": "Staging environment"}, - {"url": "https://prod.example.com", "description": "Production environment"}, - ], - root_path="/api/v1", -) - - -@app.get("/app") -def read_main(request: Request): - return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/behind_a_proxy/tutorial004_py39.py b/docs_src/behind_a_proxy/tutorial004_py39.py deleted file mode 100644 index 51bd5babc1..0000000000 --- a/docs_src/behind_a_proxy/tutorial004_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI( - servers=[ - {"url": "https://stag.example.com", "description": "Staging environment"}, - {"url": "https://prod.example.com", "description": "Production environment"}, - ], - root_path="/api/v1", - root_path_in_servers=False, -) - - -@app.get("/app") -def read_main(request: Request): - return {"message": "Hello World", "root_path": request.scope.get("root_path")} diff --git a/docs_src/bigger_applications/app_an_py39/__init__.py b/docs_src/bigger_applications/app_an_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/bigger_applications/app_an_py39/dependencies.py b/docs_src/bigger_applications/app_an_py39/dependencies.py deleted file mode 100644 index 5c7612aa09..0000000000 --- a/docs_src/bigger_applications/app_an_py39/dependencies.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated - -from fastapi import Header, HTTPException - - -async def get_token_header(x_token: Annotated[str, Header()]): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def get_query_token(token: str): - if token != "jessica": - raise HTTPException(status_code=400, detail="No Jessica token provided") diff --git a/docs_src/bigger_applications/app_an_py39/internal/__init__.py b/docs_src/bigger_applications/app_an_py39/internal/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/bigger_applications/app_an_py39/internal/admin.py b/docs_src/bigger_applications/app_an_py39/internal/admin.py deleted file mode 100644 index 99d3da86b9..0000000000 --- a/docs_src/bigger_applications/app_an_py39/internal/admin.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import APIRouter - -router = APIRouter() - - -@router.post("/") -async def update_admin(): - return {"message": "Admin getting schwifty"} diff --git a/docs_src/bigger_applications/app_an_py39/main.py b/docs_src/bigger_applications/app_an_py39/main.py deleted file mode 100644 index ae544a3aac..0000000000 --- a/docs_src/bigger_applications/app_an_py39/main.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi import Depends, FastAPI - -from .dependencies import get_query_token, get_token_header -from .internal import admin -from .routers import items, users - -app = FastAPI(dependencies=[Depends(get_query_token)]) - - -app.include_router(users.router) -app.include_router(items.router) -app.include_router( - admin.router, - prefix="/admin", - tags=["admin"], - dependencies=[Depends(get_token_header)], - responses={418: {"description": "I'm a teapot"}}, -) - - -@app.get("/") -async def root(): - return {"message": "Hello Bigger Applications!"} diff --git a/docs_src/bigger_applications/app_an_py39/routers/__init__.py b/docs_src/bigger_applications/app_an_py39/routers/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/bigger_applications/app_an_py39/routers/items.py b/docs_src/bigger_applications/app_an_py39/routers/items.py deleted file mode 100644 index bde9ff4d55..0000000000 --- a/docs_src/bigger_applications/app_an_py39/routers/items.py +++ /dev/null @@ -1,38 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException - -from ..dependencies import get_token_header - -router = APIRouter( - prefix="/items", - tags=["items"], - dependencies=[Depends(get_token_header)], - responses={404: {"description": "Not found"}}, -) - - -fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}} - - -@router.get("/") -async def read_items(): - return fake_items_db - - -@router.get("/{item_id}") -async def read_item(item_id: str): - if item_id not in fake_items_db: - raise HTTPException(status_code=404, detail="Item not found") - return {"name": fake_items_db[item_id]["name"], "item_id": item_id} - - -@router.put( - "/{item_id}", - tags=["custom"], - responses={403: {"description": "Operation forbidden"}}, -) -async def update_item(item_id: str): - if item_id != "plumbus": - raise HTTPException( - status_code=403, detail="You can only update the item: plumbus" - ) - return {"item_id": item_id, "name": "The great Plumbus"} diff --git a/docs_src/bigger_applications/app_an_py39/routers/users.py b/docs_src/bigger_applications/app_an_py39/routers/users.py deleted file mode 100644 index 39b3d7e7cf..0000000000 --- a/docs_src/bigger_applications/app_an_py39/routers/users.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import APIRouter - -router = APIRouter() - - -@router.get("/users/", tags=["users"]) -async def read_users(): - return [{"username": "Rick"}, {"username": "Morty"}] - - -@router.get("/users/me", tags=["users"]) -async def read_user_me(): - return {"username": "fakecurrentuser"} - - -@router.get("/users/{username}", tags=["users"]) -async def read_user(username: str): - return {"username": username} diff --git a/docs_src/bigger_applications/app_py39/__init__.py b/docs_src/bigger_applications/app_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/bigger_applications/app_py39/dependencies.py b/docs_src/bigger_applications/app_py39/dependencies.py deleted file mode 100644 index 8e45f004b4..0000000000 --- a/docs_src/bigger_applications/app_py39/dependencies.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import Header, HTTPException - - -async def get_token_header(x_token: str = Header()): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def get_query_token(token: str): - if token != "jessica": - raise HTTPException(status_code=400, detail="No Jessica token provided") diff --git a/docs_src/bigger_applications/app_py39/main.py b/docs_src/bigger_applications/app_py39/main.py deleted file mode 100644 index ae544a3aac..0000000000 --- a/docs_src/bigger_applications/app_py39/main.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi import Depends, FastAPI - -from .dependencies import get_query_token, get_token_header -from .internal import admin -from .routers import items, users - -app = FastAPI(dependencies=[Depends(get_query_token)]) - - -app.include_router(users.router) -app.include_router(items.router) -app.include_router( - admin.router, - prefix="/admin", - tags=["admin"], - dependencies=[Depends(get_token_header)], - responses={418: {"description": "I'm a teapot"}}, -) - - -@app.get("/") -async def root(): - return {"message": "Hello Bigger Applications!"} diff --git a/docs_src/body_nested_models/tutorial008_py39.py b/docs_src/body_nested_models/tutorial008_py39.py deleted file mode 100644 index 854a7a5a46..0000000000 --- a/docs_src/body_nested_models/tutorial008_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI -from pydantic import BaseModel, HttpUrl - -app = FastAPI() - - -class Image(BaseModel): - url: HttpUrl - name: str - - -@app.post("/images/multiple/") -async def create_multiple_images(images: list[Image]): - return images diff --git a/docs_src/body_nested_models/tutorial009_py39.py b/docs_src/body_nested_models/tutorial009_py39.py deleted file mode 100644 index 59c1e50828..0000000000 --- a/docs_src/body_nested_models/tutorial009_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.post("/index-weights/") -async def create_index_weights(weights: dict[int, float]): - return weights diff --git a/docs_src/conditional_openapi/tutorial001_py39.py b/docs_src/conditional_openapi/tutorial001_py39.py deleted file mode 100644 index eedb0d2742..0000000000 --- a/docs_src/conditional_openapi/tutorial001_py39.py +++ /dev/null @@ -1,16 +0,0 @@ -from fastapi import FastAPI -from pydantic_settings import BaseSettings - - -class Settings(BaseSettings): - openapi_url: str = "/openapi.json" - - -settings = Settings() - -app = FastAPI(openapi_url=settings.openapi_url) - - -@app.get("/") -def root(): - return {"message": "Hello World"} diff --git a/docs_src/configure_swagger_ui/tutorial001_py39.py b/docs_src/configure_swagger_ui/tutorial001_py39.py deleted file mode 100644 index 6c24ce7583..0000000000 --- a/docs_src/configure_swagger_ui/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI(swagger_ui_parameters={"syntaxHighlight": False}) - - -@app.get("/users/{username}") -async def read_user(username: str): - return {"message": f"Hello {username}"} diff --git a/docs_src/configure_swagger_ui/tutorial002_py39.py b/docs_src/configure_swagger_ui/tutorial002_py39.py deleted file mode 100644 index cc75c21968..0000000000 --- a/docs_src/configure_swagger_ui/tutorial002_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI(swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}}) - - -@app.get("/users/{username}") -async def read_user(username: str): - return {"message": f"Hello {username}"} diff --git a/docs_src/configure_swagger_ui/tutorial003_py39.py b/docs_src/configure_swagger_ui/tutorial003_py39.py deleted file mode 100644 index b4449f5c6a..0000000000 --- a/docs_src/configure_swagger_ui/tutorial003_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI(swagger_ui_parameters={"deepLinking": False}) - - -@app.get("/users/{username}") -async def read_user(username: str): - return {"message": f"Hello {username}"} diff --git a/docs_src/cors/tutorial001_py39.py b/docs_src/cors/tutorial001_py39.py deleted file mode 100644 index d59ab27acc..0000000000 --- a/docs_src/cors/tutorial001_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware - -app = FastAPI() - -origins = [ - "http://localhost.tiangolo.com", - "https://localhost.tiangolo.com", - "http://localhost", - "http://localhost:8080", -] - -app.add_middleware( - CORSMiddleware, - allow_origins=origins, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - - -@app.get("/") -async def main(): - return {"message": "Hello World"} diff --git a/docs_src/custom_docs_ui/tutorial001_py39.py b/docs_src/custom_docs_ui/tutorial001_py39.py deleted file mode 100644 index 1cfcce19aa..0000000000 --- a/docs_src/custom_docs_ui/tutorial001_py39.py +++ /dev/null @@ -1,38 +0,0 @@ -from fastapi import FastAPI -from fastapi.openapi.docs import ( - get_redoc_html, - get_swagger_ui_html, - get_swagger_ui_oauth2_redirect_html, -) - -app = FastAPI(docs_url=None, redoc_url=None) - - -@app.get("/docs", include_in_schema=False) -async def custom_swagger_ui_html(): - return get_swagger_ui_html( - openapi_url=app.openapi_url, - title=app.title + " - Swagger UI", - oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, - swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js", - swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css", - ) - - -@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) -async def swagger_ui_redirect(): - return get_swagger_ui_oauth2_redirect_html() - - -@app.get("/redoc", include_in_schema=False) -async def redoc_html(): - return get_redoc_html( - openapi_url=app.openapi_url, - title=app.title + " - ReDoc", - redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js", - ) - - -@app.get("/users/{username}") -async def read_user(username: str): - return {"message": f"Hello {username}"} diff --git a/docs_src/custom_docs_ui/tutorial002_py39.py b/docs_src/custom_docs_ui/tutorial002_py39.py deleted file mode 100644 index 23ea368f8b..0000000000 --- a/docs_src/custom_docs_ui/tutorial002_py39.py +++ /dev/null @@ -1,41 +0,0 @@ -from fastapi import FastAPI -from fastapi.openapi.docs import ( - get_redoc_html, - get_swagger_ui_html, - get_swagger_ui_oauth2_redirect_html, -) -from fastapi.staticfiles import StaticFiles - -app = FastAPI(docs_url=None, redoc_url=None) - -app.mount("/static", StaticFiles(directory="static"), name="static") - - -@app.get("/docs", include_in_schema=False) -async def custom_swagger_ui_html(): - return get_swagger_ui_html( - openapi_url=app.openapi_url, - title=app.title + " - Swagger UI", - oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, - swagger_js_url="/static/swagger-ui-bundle.js", - swagger_css_url="/static/swagger-ui.css", - ) - - -@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) -async def swagger_ui_redirect(): - return get_swagger_ui_oauth2_redirect_html() - - -@app.get("/redoc", include_in_schema=False) -async def redoc_html(): - return get_redoc_html( - openapi_url=app.openapi_url, - title=app.title + " - ReDoc", - redoc_js_url="/static/redoc.standalone.js", - ) - - -@app.get("/users/{username}") -async def read_user(username: str): - return {"message": f"Hello {username}"} diff --git a/docs_src/custom_response/tutorial001_py39.py b/docs_src/custom_response/tutorial001_py39.py deleted file mode 100644 index 0f09bdf77f..0000000000 --- a/docs_src/custom_response/tutorial001_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import UJSONResponse - -app = FastAPI() - - -@app.get("/items/", response_class=UJSONResponse) -async def read_items(): - return [{"item_id": "Foo"}] diff --git a/docs_src/custom_response/tutorial001b_py39.py b/docs_src/custom_response/tutorial001b_py39.py deleted file mode 100644 index 95e6ca7637..0000000000 --- a/docs_src/custom_response/tutorial001b_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import ORJSONResponse - -app = FastAPI() - - -@app.get("/items/", response_class=ORJSONResponse) -async def read_items(): - return ORJSONResponse([{"item_id": "Foo"}]) diff --git a/docs_src/custom_response/tutorial002_py39.py b/docs_src/custom_response/tutorial002_py39.py deleted file mode 100644 index 23c495867b..0000000000 --- a/docs_src/custom_response/tutorial002_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.get("/items/", response_class=HTMLResponse) -async def read_items(): - return """ - - - Some HTML in here - - -

Look ma! HTML!

- - - """ diff --git a/docs_src/custom_response/tutorial003_py39.py b/docs_src/custom_response/tutorial003_py39.py deleted file mode 100644 index 51ad3c146b..0000000000 --- a/docs_src/custom_response/tutorial003_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.get("/items/") -async def read_items(): - html_content = """ - - - Some HTML in here - - -

Look ma! HTML!

- - - """ - return HTMLResponse(content=html_content, status_code=200) diff --git a/docs_src/custom_response/tutorial004_py39.py b/docs_src/custom_response/tutorial004_py39.py deleted file mode 100644 index 0e90f20126..0000000000 --- a/docs_src/custom_response/tutorial004_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -def generate_html_response(): - html_content = """ - - - Some HTML in here - - -

Look ma! HTML!

- - - """ - return HTMLResponse(content=html_content, status_code=200) - - -@app.get("/items/", response_class=HTMLResponse) -async def read_items(): - return generate_html_response() diff --git a/docs_src/custom_response/tutorial005_py39.py b/docs_src/custom_response/tutorial005_py39.py deleted file mode 100644 index 3d58f57fb6..0000000000 --- a/docs_src/custom_response/tutorial005_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import PlainTextResponse - -app = FastAPI() - - -@app.get("/", response_class=PlainTextResponse) -async def main(): - return "Hello World" diff --git a/docs_src/custom_response/tutorial006_py39.py b/docs_src/custom_response/tutorial006_py39.py deleted file mode 100644 index 332f8f87f1..0000000000 --- a/docs_src/custom_response/tutorial006_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/typer") -async def redirect_typer(): - return RedirectResponse("https://typer.tiangolo.com") diff --git a/docs_src/custom_response/tutorial006b_py39.py b/docs_src/custom_response/tutorial006b_py39.py deleted file mode 100644 index 03a7be3995..0000000000 --- a/docs_src/custom_response/tutorial006b_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/fastapi", response_class=RedirectResponse) -async def redirect_fastapi(): - return "https://fastapi.tiangolo.com" diff --git a/docs_src/custom_response/tutorial006c_py39.py b/docs_src/custom_response/tutorial006c_py39.py deleted file mode 100644 index 87c720364b..0000000000 --- a/docs_src/custom_response/tutorial006c_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/pydantic", response_class=RedirectResponse, status_code=302) -async def redirect_pydantic(): - return "https://docs.pydantic.dev/" diff --git a/docs_src/custom_response/tutorial007_py39.py b/docs_src/custom_response/tutorial007_py39.py deleted file mode 100644 index e2a53a2119..0000000000 --- a/docs_src/custom_response/tutorial007_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import StreamingResponse - -app = FastAPI() - - -async def fake_video_streamer(): - for i in range(10): - yield b"some fake video bytes" - - -@app.get("/") -async def main(): - return StreamingResponse(fake_video_streamer()) diff --git a/docs_src/custom_response/tutorial008_py39.py b/docs_src/custom_response/tutorial008_py39.py deleted file mode 100644 index fc071cbee4..0000000000 --- a/docs_src/custom_response/tutorial008_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import StreamingResponse - -some_file_path = "large-video-file.mp4" -app = FastAPI() - - -@app.get("/") -def main(): - def iterfile(): # (1) - with open(some_file_path, mode="rb") as file_like: # (2) - yield from file_like # (3) - - return StreamingResponse(iterfile(), media_type="video/mp4") diff --git a/docs_src/custom_response/tutorial009_py39.py b/docs_src/custom_response/tutorial009_py39.py deleted file mode 100644 index 71cf50cc18..0000000000 --- a/docs_src/custom_response/tutorial009_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import FileResponse - -some_file_path = "large-video-file.mp4" -app = FastAPI() - - -@app.get("/") -async def main(): - return FileResponse(some_file_path) diff --git a/docs_src/custom_response/tutorial009b_py39.py b/docs_src/custom_response/tutorial009b_py39.py deleted file mode 100644 index 27200ee4ba..0000000000 --- a/docs_src/custom_response/tutorial009b_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import FileResponse - -some_file_path = "large-video-file.mp4" -app = FastAPI() - - -@app.get("/", response_class=FileResponse) -async def main(): - return some_file_path diff --git a/docs_src/custom_response/tutorial009c_py39.py b/docs_src/custom_response/tutorial009c_py39.py deleted file mode 100644 index de6b6688e6..0000000000 --- a/docs_src/custom_response/tutorial009c_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Any - -import orjson -from fastapi import FastAPI, Response - -app = FastAPI() - - -class CustomORJSONResponse(Response): - media_type = "application/json" - - def render(self, content: Any) -> bytes: - assert orjson is not None, "orjson must be installed" - return orjson.dumps(content, option=orjson.OPT_INDENT_2) - - -@app.get("/", response_class=CustomORJSONResponse) -async def main(): - return {"message": "Hello World"} diff --git a/docs_src/custom_response/tutorial010_py39.py b/docs_src/custom_response/tutorial010_py39.py deleted file mode 100644 index 57cb062604..0000000000 --- a/docs_src/custom_response/tutorial010_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import ORJSONResponse - -app = FastAPI(default_response_class=ORJSONResponse) - - -@app.get("/items/") -async def read_items(): - return [{"item_id": "Foo"}] diff --git a/docs_src/debugging/tutorial001_py39.py b/docs_src/debugging/tutorial001_py39.py deleted file mode 100644 index 3de21d2a82..0000000000 --- a/docs_src/debugging/tutorial001_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -import uvicorn -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -def root(): - a = "a" - b = "b" + a - return {"hello world": b} - - -if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/docs_src/dependencies/tutorial006_an_py39.py b/docs_src/dependencies/tutorial006_an_py39.py deleted file mode 100644 index 11976ed6a2..0000000000 --- a/docs_src/dependencies/tutorial006_an_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, Header, HTTPException - -app = FastAPI() - - -async def verify_token(x_token: Annotated[str, Header()]): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def verify_key(x_key: Annotated[str, Header()]): - if x_key != "fake-super-secret-key": - raise HTTPException(status_code=400, detail="X-Key header invalid") - return x_key - - -@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) -async def read_items(): - return [{"item": "Foo"}, {"item": "Bar"}] diff --git a/docs_src/dependencies/tutorial006_py39.py b/docs_src/dependencies/tutorial006_py39.py deleted file mode 100644 index 9aff4154f4..0000000000 --- a/docs_src/dependencies/tutorial006_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from fastapi import Depends, FastAPI, Header, HTTPException - -app = FastAPI() - - -async def verify_token(x_token: str = Header()): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def verify_key(x_key: str = Header()): - if x_key != "fake-super-secret-key": - raise HTTPException(status_code=400, detail="X-Key header invalid") - return x_key - - -@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) -async def read_items(): - return [{"item": "Foo"}, {"item": "Bar"}] diff --git a/docs_src/dependencies/tutorial007_py39.py b/docs_src/dependencies/tutorial007_py39.py deleted file mode 100644 index 2e4ab4777b..0000000000 --- a/docs_src/dependencies/tutorial007_py39.py +++ /dev/null @@ -1,6 +0,0 @@ -async def get_db(): - db = DBSession() - try: - yield db - finally: - db.close() diff --git a/docs_src/dependencies/tutorial008_an_py39.py b/docs_src/dependencies/tutorial008_an_py39.py deleted file mode 100644 index acc804c320..0000000000 --- a/docs_src/dependencies/tutorial008_an_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Annotated - -from fastapi import Depends - - -async def dependency_a(): - dep_a = generate_dep_a() - try: - yield dep_a - finally: - dep_a.close() - - -async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]): - dep_b = generate_dep_b() - try: - yield dep_b - finally: - dep_b.close(dep_a) - - -async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]): - dep_c = generate_dep_c() - try: - yield dep_c - finally: - dep_c.close(dep_b) diff --git a/docs_src/dependencies/tutorial008_py39.py b/docs_src/dependencies/tutorial008_py39.py deleted file mode 100644 index 8472f642de..0000000000 --- a/docs_src/dependencies/tutorial008_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import Depends - - -async def dependency_a(): - dep_a = generate_dep_a() - try: - yield dep_a - finally: - dep_a.close() - - -async def dependency_b(dep_a=Depends(dependency_a)): - dep_b = generate_dep_b() - try: - yield dep_b - finally: - dep_b.close(dep_a) - - -async def dependency_c(dep_b=Depends(dependency_b)): - dep_c = generate_dep_c() - try: - yield dep_c - finally: - dep_c.close(dep_b) diff --git a/docs_src/dependencies/tutorial008b_an_py39.py b/docs_src/dependencies/tutorial008b_an_py39.py deleted file mode 100644 index 3b8434c816..0000000000 --- a/docs_src/dependencies/tutorial008b_an_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -data = { - "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"}, - "portal-gun": {"description": "Gun to create portals", "owner": "Rick"}, -} - - -class OwnerError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except OwnerError as e: - raise HTTPException(status_code=400, detail=f"Owner error: {e}") - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): - if item_id not in data: - raise HTTPException(status_code=404, detail="Item not found") - item = data[item_id] - if item["owner"] != username: - raise OwnerError(username) - return item diff --git a/docs_src/dependencies/tutorial008b_py39.py b/docs_src/dependencies/tutorial008b_py39.py deleted file mode 100644 index 163e96600f..0000000000 --- a/docs_src/dependencies/tutorial008b_py39.py +++ /dev/null @@ -1,30 +0,0 @@ -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -data = { - "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"}, - "portal-gun": {"description": "Gun to create portals", "owner": "Rick"}, -} - - -class OwnerError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except OwnerError as e: - raise HTTPException(status_code=400, detail=f"Owner error: {e}") - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: str = Depends(get_username)): - if item_id not in data: - raise HTTPException(status_code=404, detail="Item not found") - item = data[item_id] - if item["owner"] != username: - raise OwnerError(username) - return item diff --git a/docs_src/dependencies/tutorial008c_an_py39.py b/docs_src/dependencies/tutorial008c_an_py39.py deleted file mode 100644 index da92efa9c3..0000000000 --- a/docs_src/dependencies/tutorial008c_an_py39.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -class InternalError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except InternalError: - print("Oops, we didn't raise again, Britney ๐Ÿ˜ฑ") - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): - if item_id == "portal-gun": - raise InternalError( - f"The portal gun is too dangerous to be owned by {username}" - ) - if item_id != "plumbus": - raise HTTPException( - status_code=404, detail="Item not found, there's only a plumbus here" - ) - return item_id diff --git a/docs_src/dependencies/tutorial008c_py39.py b/docs_src/dependencies/tutorial008c_py39.py deleted file mode 100644 index 4b99a5a311..0000000000 --- a/docs_src/dependencies/tutorial008c_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -class InternalError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except InternalError: - print("Oops, we didn't raise again, Britney ๐Ÿ˜ฑ") - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: str = Depends(get_username)): - if item_id == "portal-gun": - raise InternalError( - f"The portal gun is too dangerous to be owned by {username}" - ) - if item_id != "plumbus": - raise HTTPException( - status_code=404, detail="Item not found, there's only a plumbus here" - ) - return item_id diff --git a/docs_src/dependencies/tutorial008d_an_py39.py b/docs_src/dependencies/tutorial008d_an_py39.py deleted file mode 100644 index 99bd5cb911..0000000000 --- a/docs_src/dependencies/tutorial008d_an_py39.py +++ /dev/null @@ -1,30 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -class InternalError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except InternalError: - print("We don't swallow the internal error here, we raise again ๐Ÿ˜Ž") - raise - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): - if item_id == "portal-gun": - raise InternalError( - f"The portal gun is too dangerous to be owned by {username}" - ) - if item_id != "plumbus": - raise HTTPException( - status_code=404, detail="Item not found, there's only a plumbus here" - ) - return item_id diff --git a/docs_src/dependencies/tutorial008d_py39.py b/docs_src/dependencies/tutorial008d_py39.py deleted file mode 100644 index 93039343d1..0000000000 --- a/docs_src/dependencies/tutorial008d_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from fastapi import Depends, FastAPI, HTTPException - -app = FastAPI() - - -class InternalError(Exception): - pass - - -def get_username(): - try: - yield "Rick" - except InternalError: - print("We don't swallow the internal error here, we raise again ๐Ÿ˜Ž") - raise - - -@app.get("/items/{item_id}") -def get_item(item_id: str, username: str = Depends(get_username)): - if item_id == "portal-gun": - raise InternalError( - f"The portal gun is too dangerous to be owned by {username}" - ) - if item_id != "plumbus": - raise HTTPException( - status_code=404, detail="Item not found, there's only a plumbus here" - ) - return item_id diff --git a/docs_src/dependencies/tutorial008e_an_py39.py b/docs_src/dependencies/tutorial008e_an_py39.py deleted file mode 100644 index 80a44c7e23..0000000000 --- a/docs_src/dependencies/tutorial008e_an_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -def get_username(): - try: - yield "Rick" - finally: - print("Cleanup up before response is sent") - - -@app.get("/users/me") -def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): - return username diff --git a/docs_src/dependencies/tutorial008e_py39.py b/docs_src/dependencies/tutorial008e_py39.py deleted file mode 100644 index 1ed056e91e..0000000000 --- a/docs_src/dependencies/tutorial008e_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import Depends, FastAPI - -app = FastAPI() - - -def get_username(): - try: - yield "Rick" - finally: - print("Cleanup up before response is sent") - - -@app.get("/users/me") -def get_user_me(username: str = Depends(get_username, scope="function")): - return username diff --git a/docs_src/dependencies/tutorial010_py39.py b/docs_src/dependencies/tutorial010_py39.py deleted file mode 100644 index c27f1b1702..0000000000 --- a/docs_src/dependencies/tutorial010_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -class MySuperContextManager: - def __init__(self): - self.db = DBSession() - - def __enter__(self): - return self.db - - def __exit__(self, exc_type, exc_value, traceback): - self.db.close() - - -async def get_db(): - with MySuperContextManager() as db: - yield db diff --git a/docs_src/dependencies/tutorial011_an_py39.py b/docs_src/dependencies/tutorial011_an_py39.py deleted file mode 100644 index 68b7434ec2..0000000000 --- a/docs_src/dependencies/tutorial011_an_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -class FixedContentQueryChecker: - def __init__(self, fixed_content: str): - self.fixed_content = fixed_content - - def __call__(self, q: str = ""): - if q: - return self.fixed_content in q - return False - - -checker = FixedContentQueryChecker("bar") - - -@app.get("/query-checker/") -async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]): - return {"fixed_content_in_query": fixed_content_included} diff --git a/docs_src/dependencies/tutorial011_py39.py b/docs_src/dependencies/tutorial011_py39.py deleted file mode 100644 index 5d22f68237..0000000000 --- a/docs_src/dependencies/tutorial011_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from fastapi import Depends, FastAPI - -app = FastAPI() - - -class FixedContentQueryChecker: - def __init__(self, fixed_content: str): - self.fixed_content = fixed_content - - def __call__(self, q: str = ""): - if q: - return self.fixed_content in q - return False - - -checker = FixedContentQueryChecker("bar") - - -@app.get("/query-checker/") -async def read_query_check(fixed_content_included: bool = Depends(checker)): - return {"fixed_content_in_query": fixed_content_included} diff --git a/docs_src/dependencies/tutorial012_an_py39.py b/docs_src/dependencies/tutorial012_an_py39.py deleted file mode 100644 index 6503591fc3..0000000000 --- a/docs_src/dependencies/tutorial012_an_py39.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI, Header, HTTPException - - -async def verify_token(x_token: Annotated[str, Header()]): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def verify_key(x_key: Annotated[str, Header()]): - if x_key != "fake-super-secret-key": - raise HTTPException(status_code=400, detail="X-Key header invalid") - return x_key - - -app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]) - - -@app.get("/items/") -async def read_items(): - return [{"item": "Portal Gun"}, {"item": "Plumbus"}] - - -@app.get("/users/") -async def read_users(): - return [{"username": "Rick"}, {"username": "Morty"}] diff --git a/docs_src/dependencies/tutorial012_py39.py b/docs_src/dependencies/tutorial012_py39.py deleted file mode 100644 index 36ce6c7111..0000000000 --- a/docs_src/dependencies/tutorial012_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import Depends, FastAPI, Header, HTTPException - - -async def verify_token(x_token: str = Header()): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - - -async def verify_key(x_key: str = Header()): - if x_key != "fake-super-secret-key": - raise HTTPException(status_code=400, detail="X-Key header invalid") - return x_key - - -app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]) - - -@app.get("/items/") -async def read_items(): - return [{"item": "Portal Gun"}, {"item": "Plumbus"}] - - -@app.get("/users/") -async def read_users(): - return [{"username": "Rick"}, {"username": "Morty"}] diff --git a/docs_src/events/tutorial001_py39.py b/docs_src/events/tutorial001_py39.py deleted file mode 100644 index 128004c9fb..0000000000 --- a/docs_src/events/tutorial001_py39.py +++ /dev/null @@ -1,16 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - -items = {} - - -@app.on_event("startup") -async def startup_event(): - items["foo"] = {"name": "Fighters"} - items["bar"] = {"name": "Tenders"} - - -@app.get("/items/{item_id}") -async def read_items(item_id: str): - return items[item_id] diff --git a/docs_src/events/tutorial002_py39.py b/docs_src/events/tutorial002_py39.py deleted file mode 100644 index a71fea8025..0000000000 --- a/docs_src/events/tutorial002_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.on_event("shutdown") -def shutdown_event(): - with open("log.txt", mode="a") as log: - log.write("Application shutdown") - - -@app.get("/items/") -async def read_items(): - return [{"name": "Foo"}] diff --git a/docs_src/events/tutorial003_py39.py b/docs_src/events/tutorial003_py39.py deleted file mode 100644 index 2b650590b0..0000000000 --- a/docs_src/events/tutorial003_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from contextlib import asynccontextmanager - -from fastapi import FastAPI - - -def fake_answer_to_everything_ml_model(x: float): - return x * 42 - - -ml_models = {} - - -@asynccontextmanager -async def lifespan(app: FastAPI): - # Load the ML model - ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model - yield - # Clean up the ML models and release the resources - ml_models.clear() - - -app = FastAPI(lifespan=lifespan) - - -@app.get("/predict") -async def predict(x: float): - result = ml_models["answer_to_everything"](x) - return {"result": result} diff --git a/docs_src/extending_openapi/tutorial001_py39.py b/docs_src/extending_openapi/tutorial001_py39.py deleted file mode 100644 index 35e31c0e0c..0000000000 --- a/docs_src/extending_openapi/tutorial001_py39.py +++ /dev/null @@ -1,29 +0,0 @@ -from fastapi import FastAPI -from fastapi.openapi.utils import get_openapi - -app = FastAPI() - - -@app.get("/items/") -async def read_items(): - return [{"name": "Foo"}] - - -def custom_openapi(): - if app.openapi_schema: - return app.openapi_schema - openapi_schema = get_openapi( - title="Custom title", - version="2.5.0", - summary="This is a very custom OpenAPI schema", - description="Here's a longer description of the custom **OpenAPI** schema", - routes=app.routes, - ) - openapi_schema["info"]["x-logo"] = { - "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" - } - app.openapi_schema = openapi_schema - return app.openapi_schema - - -app.openapi = custom_openapi diff --git a/docs_src/extra_models/tutorial004_py39.py b/docs_src/extra_models/tutorial004_py39.py deleted file mode 100644 index 28cacde4d4..0000000000 --- a/docs_src/extra_models/tutorial004_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str - - -items = [ - {"name": "Foo", "description": "There comes my hero"}, - {"name": "Red", "description": "It's my aeroplane"}, -] - - -@app.get("/items/", response_model=list[Item]) -async def read_items(): - return items diff --git a/docs_src/extra_models/tutorial005_py39.py b/docs_src/extra_models/tutorial005_py39.py deleted file mode 100644 index 9da2a0a0f4..0000000000 --- a/docs_src/extra_models/tutorial005_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/keyword-weights/", response_model=dict[str, float]) -async def read_keyword_weights(): - return {"foo": 2.3, "bar": 3.4} diff --git a/docs_src/first_steps/tutorial001_py39.py b/docs_src/first_steps/tutorial001_py39.py deleted file mode 100644 index ee60be1f96..0000000000 --- a/docs_src/first_steps/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -async def root(): - return {"message": "Hello World"} diff --git a/docs_src/first_steps/tutorial003_py39.py b/docs_src/first_steps/tutorial003_py39.py deleted file mode 100644 index e30b827eab..0000000000 --- a/docs_src/first_steps/tutorial003_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -def root(): - return {"message": "Hello World"} diff --git a/docs_src/generate_clients/tutorial001_py39.py b/docs_src/generate_clients/tutorial001_py39.py deleted file mode 100644 index 6a5ae23202..0000000000 --- a/docs_src/generate_clients/tutorial001_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - price: float - - -class ResponseMessage(BaseModel): - message: str - - -@app.post("/items/", response_model=ResponseMessage) -async def create_item(item: Item): - return {"message": "item received"} - - -@app.get("/items/", response_model=list[Item]) -async def get_items(): - return [ - {"name": "Plumbus", "price": 3}, - {"name": "Portal Gun", "price": 9001}, - ] diff --git a/docs_src/generate_clients/tutorial002_py39.py b/docs_src/generate_clients/tutorial002_py39.py deleted file mode 100644 index 83309760b9..0000000000 --- a/docs_src/generate_clients/tutorial002_py39.py +++ /dev/null @@ -1,36 +0,0 @@ -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - price: float - - -class ResponseMessage(BaseModel): - message: str - - -class User(BaseModel): - username: str - email: str - - -@app.post("/items/", response_model=ResponseMessage, tags=["items"]) -async def create_item(item: Item): - return {"message": "Item received"} - - -@app.get("/items/", response_model=list[Item], tags=["items"]) -async def get_items(): - return [ - {"name": "Plumbus", "price": 3}, - {"name": "Portal Gun", "price": 9001}, - ] - - -@app.post("/users/", response_model=ResponseMessage, tags=["users"]) -async def create_user(user: User): - return {"message": "User received"} diff --git a/docs_src/generate_clients/tutorial003_py39.py b/docs_src/generate_clients/tutorial003_py39.py deleted file mode 100644 index 40722cf103..0000000000 --- a/docs_src/generate_clients/tutorial003_py39.py +++ /dev/null @@ -1,42 +0,0 @@ -from fastapi import FastAPI -from fastapi.routing import APIRoute -from pydantic import BaseModel - - -def custom_generate_unique_id(route: APIRoute): - return f"{route.tags[0]}-{route.name}" - - -app = FastAPI(generate_unique_id_function=custom_generate_unique_id) - - -class Item(BaseModel): - name: str - price: float - - -class ResponseMessage(BaseModel): - message: str - - -class User(BaseModel): - username: str - email: str - - -@app.post("/items/", response_model=ResponseMessage, tags=["items"]) -async def create_item(item: Item): - return {"message": "Item received"} - - -@app.get("/items/", response_model=list[Item], tags=["items"]) -async def get_items(): - return [ - {"name": "Plumbus", "price": 3}, - {"name": "Portal Gun", "price": 9001}, - ] - - -@app.post("/users/", response_model=ResponseMessage, tags=["users"]) -async def create_user(user: User): - return {"message": "User received"} diff --git a/docs_src/generate_clients/tutorial004_py39.py b/docs_src/generate_clients/tutorial004_py39.py deleted file mode 100644 index 894dc7f8df..0000000000 --- a/docs_src/generate_clients/tutorial004_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -import json -from pathlib import Path - -file_path = Path("./openapi.json") -openapi_content = json.loads(file_path.read_text()) - -for path_data in openapi_content["paths"].values(): - for operation in path_data.values(): - tag = operation["tags"][0] - operation_id = operation["operationId"] - to_remove = f"{tag}-" - new_operation_id = operation_id[len(to_remove) :] - operation["operationId"] = new_operation_id - -file_path.write_text(json.dumps(openapi_content)) diff --git a/docs_src/graphql_/tutorial001_py39.py b/docs_src/graphql_/tutorial001_py39.py deleted file mode 100644 index e92b2d71c4..0000000000 --- a/docs_src/graphql_/tutorial001_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -import strawberry -from fastapi import FastAPI -from strawberry.fastapi import GraphQLRouter - - -@strawberry.type -class User: - name: str - age: int - - -@strawberry.type -class Query: - @strawberry.field - def user(self) -> User: - return User(name="Patrick", age=100) - - -schema = strawberry.Schema(query=Query) - - -graphql_app = GraphQLRouter(schema) - -app = FastAPI() -app.include_router(graphql_app, prefix="/graphql") diff --git a/docs_src/handling_errors/tutorial001_py39.py b/docs_src/handling_errors/tutorial001_py39.py deleted file mode 100644 index e5f32aac29..0000000000 --- a/docs_src/handling_errors/tutorial001_py39.py +++ /dev/null @@ -1,12 +0,0 @@ -from fastapi import FastAPI, HTTPException - -app = FastAPI() - -items = {"foo": "The Foo Wrestlers"} - - -@app.get("/items/{item_id}") -async def read_item(item_id: str): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - return {"item": items[item_id]} diff --git a/docs_src/handling_errors/tutorial002_py39.py b/docs_src/handling_errors/tutorial002_py39.py deleted file mode 100644 index e48c295c9c..0000000000 --- a/docs_src/handling_errors/tutorial002_py39.py +++ /dev/null @@ -1,16 +0,0 @@ -from fastapi import FastAPI, HTTPException - -app = FastAPI() - -items = {"foo": "The Foo Wrestlers"} - - -@app.get("/items-header/{item_id}") -async def read_item_header(item_id: str): - if item_id not in items: - raise HTTPException( - status_code=404, - detail="Item not found", - headers={"X-Error": "There goes my error"}, - ) - return {"item": items[item_id]} diff --git a/docs_src/handling_errors/tutorial003_py39.py b/docs_src/handling_errors/tutorial003_py39.py deleted file mode 100644 index 791cd6838c..0000000000 --- a/docs_src/handling_errors/tutorial003_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import FastAPI, Request -from fastapi.responses import JSONResponse - - -class UnicornException(Exception): - def __init__(self, name: str): - self.name = name - - -app = FastAPI() - - -@app.exception_handler(UnicornException) -async def unicorn_exception_handler(request: Request, exc: UnicornException): - return JSONResponse( - status_code=418, - content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, - ) - - -@app.get("/unicorns/{name}") -async def read_unicorn(name: str): - if name == "yolo": - raise UnicornException(name=name) - return {"unicorn_name": name} diff --git a/docs_src/handling_errors/tutorial004_py39.py b/docs_src/handling_errors/tutorial004_py39.py deleted file mode 100644 index ae50807e97..0000000000 --- a/docs_src/handling_errors/tutorial004_py39.py +++ /dev/null @@ -1,26 +0,0 @@ -from fastapi import FastAPI, HTTPException -from fastapi.exceptions import RequestValidationError -from fastapi.responses import PlainTextResponse -from starlette.exceptions import HTTPException as StarletteHTTPException - -app = FastAPI() - - -@app.exception_handler(StarletteHTTPException) -async def http_exception_handler(request, exc): - return PlainTextResponse(str(exc.detail), status_code=exc.status_code) - - -@app.exception_handler(RequestValidationError) -async def validation_exception_handler(request, exc: RequestValidationError): - message = "Validation errors:" - for error in exc.errors(): - message += f"\nField: {error['loc']}, Error: {error['msg']}" - return PlainTextResponse(message, status_code=400) - - -@app.get("/items/{item_id}") -async def read_item(item_id: int): - if item_id == 3: - raise HTTPException(status_code=418, detail="Nope! I don't like 3.") - return {"item_id": item_id} diff --git a/docs_src/handling_errors/tutorial005_py39.py b/docs_src/handling_errors/tutorial005_py39.py deleted file mode 100644 index 0e04fa0864..0000000000 --- a/docs_src/handling_errors/tutorial005_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from fastapi import FastAPI, Request -from fastapi.encoders import jsonable_encoder -from fastapi.exceptions import RequestValidationError -from fastapi.responses import JSONResponse -from pydantic import BaseModel - -app = FastAPI() - - -@app.exception_handler(RequestValidationError) -async def validation_exception_handler(request: Request, exc: RequestValidationError): - return JSONResponse( - status_code=422, - content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), - ) - - -class Item(BaseModel): - title: str - size: int - - -@app.post("/items/") -async def create_item(item: Item): - return item diff --git a/docs_src/handling_errors/tutorial006_py39.py b/docs_src/handling_errors/tutorial006_py39.py deleted file mode 100644 index e05160d7e1..0000000000 --- a/docs_src/handling_errors/tutorial006_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from fastapi import FastAPI, HTTPException -from fastapi.exception_handlers import ( - http_exception_handler, - request_validation_exception_handler, -) -from fastapi.exceptions import RequestValidationError -from starlette.exceptions import HTTPException as StarletteHTTPException - -app = FastAPI() - - -@app.exception_handler(StarletteHTTPException) -async def custom_http_exception_handler(request, exc): - print(f"OMG! An HTTP error!: {repr(exc)}") - return await http_exception_handler(request, exc) - - -@app.exception_handler(RequestValidationError) -async def validation_exception_handler(request, exc): - print(f"OMG! The client sent invalid data!: {exc}") - return await request_validation_exception_handler(request, exc) - - -@app.get("/items/{item_id}") -async def read_item(item_id: int): - if item_id == 3: - raise HTTPException(status_code=418, detail="Nope! I don't like 3.") - return {"item_id": item_id} diff --git a/docs_src/metadata/tutorial001_1_py39.py b/docs_src/metadata/tutorial001_1_py39.py deleted file mode 100644 index 419232d861..0000000000 --- a/docs_src/metadata/tutorial001_1_py39.py +++ /dev/null @@ -1,38 +0,0 @@ -from fastapi import FastAPI - -description = """ -ChimichangApp API helps you do awesome stuff. ๐Ÿš€ - -## Items - -You can **read items**. - -## Users - -You will be able to: - -* **Create users** (_not implemented_). -* **Read users** (_not implemented_). -""" - -app = FastAPI( - title="ChimichangApp", - description=description, - summary="Deadpool's favorite app. Nuff said.", - version="0.0.1", - terms_of_service="http://example.com/terms/", - contact={ - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", - }, - license_info={ - "name": "Apache 2.0", - "identifier": "Apache-2.0", - }, -) - - -@app.get("/items/") -async def read_items(): - return [{"name": "Katana"}] diff --git a/docs_src/metadata/tutorial001_py39.py b/docs_src/metadata/tutorial001_py39.py deleted file mode 100644 index 76656e81b4..0000000000 --- a/docs_src/metadata/tutorial001_py39.py +++ /dev/null @@ -1,38 +0,0 @@ -from fastapi import FastAPI - -description = """ -ChimichangApp API helps you do awesome stuff. ๐Ÿš€ - -## Items - -You can **read items**. - -## Users - -You will be able to: - -* **Create users** (_not implemented_). -* **Read users** (_not implemented_). -""" - -app = FastAPI( - title="ChimichangApp", - description=description, - summary="Deadpool's favorite app. Nuff said.", - version="0.0.1", - terms_of_service="http://example.com/terms/", - contact={ - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", - }, - license_info={ - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html", - }, -) - - -@app.get("/items/") -async def read_items(): - return [{"name": "Katana"}] diff --git a/docs_src/metadata/tutorial002_py39.py b/docs_src/metadata/tutorial002_py39.py deleted file mode 100644 index cf9ed7087e..0000000000 --- a/docs_src/metadata/tutorial002_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI(openapi_url="/api/v1/openapi.json") - - -@app.get("/items/") -async def read_items(): - return [{"name": "Foo"}] diff --git a/docs_src/metadata/tutorial003_py39.py b/docs_src/metadata/tutorial003_py39.py deleted file mode 100644 index ee09c7f37b..0000000000 --- a/docs_src/metadata/tutorial003_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI(docs_url="/documentation", redoc_url=None) - - -@app.get("/items/") -async def read_items(): - return [{"name": "Foo"}] diff --git a/docs_src/metadata/tutorial004_py39.py b/docs_src/metadata/tutorial004_py39.py deleted file mode 100644 index 465bd659d5..0000000000 --- a/docs_src/metadata/tutorial004_py39.py +++ /dev/null @@ -1,28 +0,0 @@ -from fastapi import FastAPI - -tags_metadata = [ - { - "name": "users", - "description": "Operations with users. The **login** logic is also here.", - }, - { - "name": "items", - "description": "Manage items. So _fancy_ they have their own docs.", - "externalDocs": { - "description": "Items external docs", - "url": "https://fastapi.tiangolo.com/", - }, - }, -] - -app = FastAPI(openapi_tags=tags_metadata) - - -@app.get("/users/", tags=["users"]) -async def get_users(): - return [{"name": "Harry"}, {"name": "Ron"}] - - -@app.get("/items/", tags=["items"]) -async def get_items(): - return [{"name": "wand"}, {"name": "flying broom"}] diff --git a/docs_src/middleware/tutorial001_py39.py b/docs_src/middleware/tutorial001_py39.py deleted file mode 100644 index e65a7dade1..0000000000 --- a/docs_src/middleware/tutorial001_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -import time - -from fastapi import FastAPI, Request - -app = FastAPI() - - -@app.middleware("http") -async def add_process_time_header(request: Request, call_next): - start_time = time.perf_counter() - response = await call_next(request) - process_time = time.perf_counter() - start_time - response.headers["X-Process-Time"] = str(process_time) - return response diff --git a/docs_src/openapi_webhooks/tutorial001_py39.py b/docs_src/openapi_webhooks/tutorial001_py39.py deleted file mode 100644 index 55822bb48f..0000000000 --- a/docs_src/openapi_webhooks/tutorial001_py39.py +++ /dev/null @@ -1,25 +0,0 @@ -from datetime import datetime - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Subscription(BaseModel): - username: str - monthly_fee: float - start_date: datetime - - -@app.webhooks.post("new-subscription") -def new_subscription(body: Subscription): - """ - When a new user subscribes to your service we'll send you a POST request with this - data to the URL that you register for the event `new-subscription` in the dashboard. - """ - - -@app.get("/users/") -def read_users(): - return ["Rick", "Morty"] diff --git a/docs_src/path_operation_advanced_configuration/tutorial001_py39.py b/docs_src/path_operation_advanced_configuration/tutorial001_py39.py deleted file mode 100644 index fafa8ffb8e..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/", operation_id="some_specific_id_you_define") -async def read_items(): - return [{"item_id": "Foo"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial002_py39.py b/docs_src/path_operation_advanced_configuration/tutorial002_py39.py deleted file mode 100644 index 3aaae9b371..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial002_py39.py +++ /dev/null @@ -1,24 +0,0 @@ -from fastapi import FastAPI -from fastapi.routing import APIRoute - -app = FastAPI() - - -@app.get("/items/") -async def read_items(): - return [{"item_id": "Foo"}] - - -def use_route_names_as_operation_ids(app: FastAPI) -> None: - """ - Simplify operation IDs so that generated API clients have simpler function - names. - - Should be called only after all routes have been added. - """ - for route in app.routes: - if isinstance(route, APIRoute): - route.operation_id = route.name # in this case, 'read_items' - - -use_route_names_as_operation_ids(app) diff --git a/docs_src/path_operation_advanced_configuration/tutorial003_py39.py b/docs_src/path_operation_advanced_configuration/tutorial003_py39.py deleted file mode 100644 index dcc358e323..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial003_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/", include_in_schema=False) -async def read_items(): - return [{"item_id": "Foo"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial005_py39.py b/docs_src/path_operation_advanced_configuration/tutorial005_py39.py deleted file mode 100644 index 5837ad8351..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial005_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/", openapi_extra={"x-aperture-labs-portal": "blue"}) -async def read_items(): - return [{"item_id": "portal-gun"}] diff --git a/docs_src/path_operation_advanced_configuration/tutorial006_py39.py b/docs_src/path_operation_advanced_configuration/tutorial006_py39.py deleted file mode 100644 index 403c3ee3fb..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial006_py39.py +++ /dev/null @@ -1,41 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI() - - -def magic_data_reader(raw_body: bytes): - return { - "size": len(raw_body), - "content": { - "name": "Maaaagic", - "price": 42, - "description": "Just kiddin', no magic here. โœจ", - }, - } - - -@app.post( - "/items/", - openapi_extra={ - "requestBody": { - "content": { - "application/json": { - "schema": { - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"type": "string"}, - "price": {"type": "number"}, - "description": {"type": "string"}, - }, - } - } - }, - "required": True, - }, - }, -) -async def create_item(request: Request): - raw_body = await request.body() - data = magic_data_reader(raw_body) - return data diff --git a/docs_src/path_operation_advanced_configuration/tutorial007_py39.py b/docs_src/path_operation_advanced_configuration/tutorial007_py39.py deleted file mode 100644 index ff64ef7923..0000000000 --- a/docs_src/path_operation_advanced_configuration/tutorial007_py39.py +++ /dev/null @@ -1,32 +0,0 @@ -import yaml -from fastapi import FastAPI, HTTPException, Request -from pydantic import BaseModel, ValidationError - -app = FastAPI() - - -class Item(BaseModel): - name: str - tags: list[str] - - -@app.post( - "/items/", - openapi_extra={ - "requestBody": { - "content": {"application/x-yaml": {"schema": Item.model_json_schema()}}, - "required": True, - }, - }, -) -async def create_item(request: Request): - raw_body = await request.body() - try: - data = yaml.safe_load(raw_body) - except yaml.YAMLError: - raise HTTPException(status_code=422, detail="Invalid YAML") - try: - item = Item.model_validate(data) - except ValidationError as e: - raise HTTPException(status_code=422, detail=e.errors(include_url=False)) - return item diff --git a/docs_src/path_operation_configuration/tutorial002b_py39.py b/docs_src/path_operation_configuration/tutorial002b_py39.py deleted file mode 100644 index d53b4d817d..0000000000 --- a/docs_src/path_operation_configuration/tutorial002b_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from enum import Enum - -from fastapi import FastAPI - -app = FastAPI() - - -class Tags(Enum): - items = "items" - users = "users" - - -@app.get("/items/", tags=[Tags.items]) -async def get_items(): - return ["Portal gun", "Plumbus"] - - -@app.get("/users/", tags=[Tags.users]) -async def read_users(): - return ["Rick", "Morty"] diff --git a/docs_src/path_operation_configuration/tutorial006_py39.py b/docs_src/path_operation_configuration/tutorial006_py39.py deleted file mode 100644 index 7c1aa9b206..0000000000 --- a/docs_src/path_operation_configuration/tutorial006_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/", tags=["items"]) -async def read_items(): - return [{"name": "Foo", "price": 42}] - - -@app.get("/users/", tags=["users"]) -async def read_users(): - return [{"username": "johndoe"}] - - -@app.get("/elements/", tags=["items"], deprecated=True) -async def read_elements(): - return [{"item_id": "Foo"}] diff --git a/docs_src/path_params/tutorial001_py39.py b/docs_src/path_params/tutorial001_py39.py deleted file mode 100644 index 7bbf70e6c8..0000000000 --- a/docs_src/path_params/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_item(item_id): - return {"item_id": item_id} diff --git a/docs_src/path_params/tutorial002_py39.py b/docs_src/path_params/tutorial002_py39.py deleted file mode 100644 index 8272ad70d4..0000000000 --- a/docs_src/path_params/tutorial002_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_item(item_id: int): - return {"item_id": item_id} diff --git a/docs_src/path_params/tutorial003_py39.py b/docs_src/path_params/tutorial003_py39.py deleted file mode 100644 index 5f0aa09234..0000000000 --- a/docs_src/path_params/tutorial003_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/users/me") -async def read_user_me(): - return {"user_id": "the current user"} - - -@app.get("/users/{user_id}") -async def read_user(user_id: str): - return {"user_id": user_id} diff --git a/docs_src/path_params/tutorial003b_py39.py b/docs_src/path_params/tutorial003b_py39.py deleted file mode 100644 index 822d373694..0000000000 --- a/docs_src/path_params/tutorial003b_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/users") -async def read_users(): - return ["Rick", "Morty"] - - -@app.get("/users") -async def read_users2(): - return ["Bean", "Elfo"] diff --git a/docs_src/path_params/tutorial004_py39.py b/docs_src/path_params/tutorial004_py39.py deleted file mode 100644 index 2961e6178e..0000000000 --- a/docs_src/path_params/tutorial004_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/files/{file_path:path}") -async def read_file(file_path: str): - return {"file_path": file_path} diff --git a/docs_src/path_params/tutorial005_py39.py b/docs_src/path_params/tutorial005_py39.py deleted file mode 100644 index 9a24a4963a..0000000000 --- a/docs_src/path_params/tutorial005_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from enum import Enum - -from fastapi import FastAPI - - -class ModelName(str, Enum): - alexnet = "alexnet" - resnet = "resnet" - lenet = "lenet" - - -app = FastAPI() - - -@app.get("/models/{model_name}") -async def get_model(model_name: ModelName): - if model_name is ModelName.alexnet: - return {"model_name": model_name, "message": "Deep Learning FTW!"} - - if model_name.value == "lenet": - return {"model_name": model_name, "message": "LeCNN all the images"} - - return {"model_name": model_name, "message": "Have some residuals"} diff --git a/docs_src/path_params_numeric_validations/tutorial002_an_py39.py b/docs_src/path_params_numeric_validations/tutorial002_an_py39.py deleted file mode 100644 index cd882abb2c..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial002_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - q: str, item_id: Annotated[int, Path(title="The ID of the item to get")] -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial002_py39.py b/docs_src/path_params_numeric_validations/tutorial002_py39.py deleted file mode 100644 index 63ac691a83..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial002_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial003_an_py39.py b/docs_src/path_params_numeric_validations/tutorial003_an_py39.py deleted file mode 100644 index 1588556e78..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial003_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get")], q: str -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial003_py39.py b/docs_src/path_params_numeric_validations/tutorial003_py39.py deleted file mode 100644 index 8df0ffc620..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial003_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial004_an_py39.py b/docs_src/path_params_numeric_validations/tutorial004_an_py39.py deleted file mode 100644 index f67f6450e7..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial004_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial004_py39.py b/docs_src/path_params_numeric_validations/tutorial004_py39.py deleted file mode 100644 index 86651d47cf..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial004_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial005_an_py39.py b/docs_src/path_params_numeric_validations/tutorial005_an_py39.py deleted file mode 100644 index 571dd583ce..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial005_an_py39.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)], - q: str, -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial005_py39.py b/docs_src/path_params_numeric_validations/tutorial005_py39.py deleted file mode 100644 index 8f12f2da02..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial005_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import FastAPI, Path - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - *, - item_id: int = Path(title="The ID of the item to get", gt=0, le=1000), - q: str, -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial006_an_py39.py b/docs_src/path_params_numeric_validations/tutorial006_an_py39.py deleted file mode 100644 index 426ec37764..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial006_an_py39.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Path, Query - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - *, - item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], - q: str, - size: Annotated[float, Query(gt=0, lt=10.5)], -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - if size: - results.update({"size": size}) - return results diff --git a/docs_src/path_params_numeric_validations/tutorial006_py39.py b/docs_src/path_params_numeric_validations/tutorial006_py39.py deleted file mode 100644 index f07629aa0a..0000000000 --- a/docs_src/path_params_numeric_validations/tutorial006_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI, Path, Query - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_items( - *, - item_id: int = Path(title="The ID of the item to get", ge=0, le=1000), - q: str, - size: float = Query(gt=0, lt=10.5), -): - results = {"item_id": item_id} - if q: - results.update({"q": q}) - if size: - results.update({"size": size}) - return results diff --git a/docs_src/python_types/tutorial001_py39.py b/docs_src/python_types/tutorial001_py39.py deleted file mode 100644 index 09039435f1..0000000000 --- a/docs_src/python_types/tutorial001_py39.py +++ /dev/null @@ -1,6 +0,0 @@ -def get_full_name(first_name, last_name): - full_name = first_name.title() + " " + last_name.title() - return full_name - - -print(get_full_name("john", "doe")) diff --git a/docs_src/python_types/tutorial002_py39.py b/docs_src/python_types/tutorial002_py39.py deleted file mode 100644 index c0857a1160..0000000000 --- a/docs_src/python_types/tutorial002_py39.py +++ /dev/null @@ -1,6 +0,0 @@ -def get_full_name(first_name: str, last_name: str): - full_name = first_name.title() + " " + last_name.title() - return full_name - - -print(get_full_name("john", "doe")) diff --git a/docs_src/python_types/tutorial003_py39.py b/docs_src/python_types/tutorial003_py39.py deleted file mode 100644 index d021d82113..0000000000 --- a/docs_src/python_types/tutorial003_py39.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_name_with_age(name: str, age: int): - name_with_age = name + " is this old: " + age - return name_with_age diff --git a/docs_src/python_types/tutorial004_py39.py b/docs_src/python_types/tutorial004_py39.py deleted file mode 100644 index 9400269e26..0000000000 --- a/docs_src/python_types/tutorial004_py39.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_name_with_age(name: str, age: int): - name_with_age = name + " is this old: " + str(age) - return name_with_age diff --git a/docs_src/python_types/tutorial006_py39.py b/docs_src/python_types/tutorial006_py39.py deleted file mode 100644 index 486b67cafd..0000000000 --- a/docs_src/python_types/tutorial006_py39.py +++ /dev/null @@ -1,3 +0,0 @@ -def process_items(items: list[str]): - for item in items: - print(item) diff --git a/docs_src/python_types/tutorial007_py39.py b/docs_src/python_types/tutorial007_py39.py deleted file mode 100644 index ea96c79642..0000000000 --- a/docs_src/python_types/tutorial007_py39.py +++ /dev/null @@ -1,2 +0,0 @@ -def process_items(items_t: tuple[int, int, str], items_s: set[bytes]): - return items_t, items_s diff --git a/docs_src/python_types/tutorial008_py39.py b/docs_src/python_types/tutorial008_py39.py deleted file mode 100644 index a393385b05..0000000000 --- a/docs_src/python_types/tutorial008_py39.py +++ /dev/null @@ -1,4 +0,0 @@ -def process_items(prices: dict[str, float]): - for item_name, item_price in prices.items(): - print(item_name) - print(item_price) diff --git a/docs_src/python_types/tutorial008b_py39.py b/docs_src/python_types/tutorial008b_py39.py deleted file mode 100644 index e52539ead0..0000000000 --- a/docs_src/python_types/tutorial008b_py39.py +++ /dev/null @@ -1,5 +0,0 @@ -from typing import Union - - -def process_item(item: Union[int, str]): - print(item) diff --git a/docs_src/python_types/tutorial009_py39.py b/docs_src/python_types/tutorial009_py39.py deleted file mode 100644 index 6328a1495c..0000000000 --- a/docs_src/python_types/tutorial009_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Optional - - -def say_hi(name: Optional[str] = None): - if name is not None: - print(f"Hey {name}!") - else: - print("Hello World") diff --git a/docs_src/python_types/tutorial009b_py39.py b/docs_src/python_types/tutorial009b_py39.py deleted file mode 100644 index 9f1a05bc0f..0000000000 --- a/docs_src/python_types/tutorial009b_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Union - - -def say_hi(name: Union[str, None] = None): - if name is not None: - print(f"Hey {name}!") - else: - print("Hello World") diff --git a/docs_src/python_types/tutorial009c_py310.py b/docs_src/python_types/tutorial009c_py310.py deleted file mode 100644 index 96b1220fcc..0000000000 --- a/docs_src/python_types/tutorial009c_py310.py +++ /dev/null @@ -1,2 +0,0 @@ -def say_hi(name: str | None): - print(f"Hey {name}!") diff --git a/docs_src/python_types/tutorial009c_py39.py b/docs_src/python_types/tutorial009c_py39.py deleted file mode 100644 index 2f539a34b1..0000000000 --- a/docs_src/python_types/tutorial009c_py39.py +++ /dev/null @@ -1,5 +0,0 @@ -from typing import Optional - - -def say_hi(name: Optional[str]): - print(f"Hey {name}!") diff --git a/docs_src/python_types/tutorial010_py39.py b/docs_src/python_types/tutorial010_py39.py deleted file mode 100644 index 468cffc2dc..0000000000 --- a/docs_src/python_types/tutorial010_py39.py +++ /dev/null @@ -1,7 +0,0 @@ -class Person: - def __init__(self, name: str): - self.name = name - - -def get_person_name(one_person: Person): - return one_person.name diff --git a/docs_src/python_types/tutorial013_py39.py b/docs_src/python_types/tutorial013_py39.py deleted file mode 100644 index 65a0eaa939..0000000000 --- a/docs_src/python_types/tutorial013_py39.py +++ /dev/null @@ -1,5 +0,0 @@ -from typing import Annotated - - -def say_hello(name: Annotated[str, "this is just metadata"]) -> str: - return f"Hello {name}" diff --git a/docs_src/query_params/tutorial001_py39.py b/docs_src/query_params/tutorial001_py39.py deleted file mode 100644 index 74e1a17604..0000000000 --- a/docs_src/query_params/tutorial001_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -@app.get("/items/") -async def read_item(skip: int = 0, limit: int = 10): - return fake_items_db[skip : skip + limit] diff --git a/docs_src/query_params/tutorial005_py39.py b/docs_src/query_params/tutorial005_py39.py deleted file mode 100644 index e16a40574d..0000000000 --- a/docs_src/query_params/tutorial005_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_user_item(item_id: str, needy: str): - item = {"item_id": item_id, "needy": needy} - return item diff --git a/docs_src/query_params_str_validations/tutorial005_an_py39.py b/docs_src/query_params_str_validations/tutorial005_an_py39.py deleted file mode 100644 index b1f6046b50..0000000000 --- a/docs_src/query_params_str_validations/tutorial005_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial005_py39.py b/docs_src/query_params_str_validations/tutorial005_py39.py deleted file mode 100644 index 8ab42869e6..0000000000 --- a/docs_src/query_params_str_validations/tutorial005_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial006_an_py39.py b/docs_src/query_params_str_validations/tutorial006_an_py39.py deleted file mode 100644 index 3b4a676d2e..0000000000 --- a/docs_src/query_params_str_validations/tutorial006_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial006_py39.py b/docs_src/query_params_str_validations/tutorial006_py39.py deleted file mode 100644 index 9a90eb64ef..0000000000 --- a/docs_src/query_params_str_validations/tutorial006_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial012_an_py39.py b/docs_src/query_params_str_validations/tutorial012_an_py39.py deleted file mode 100644 index 9b5a9c2fb2..0000000000 --- a/docs_src/query_params_str_validations/tutorial012_an_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial012_py39.py b/docs_src/query_params_str_validations/tutorial012_py39.py deleted file mode 100644 index 070d0b04bf..0000000000 --- a/docs_src/query_params_str_validations/tutorial012_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial013_an_py39.py b/docs_src/query_params_str_validations/tutorial013_an_py39.py deleted file mode 100644 index 602734145d..0000000000 --- a/docs_src/query_params_str_validations/tutorial013_an_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/docs_src/query_params_str_validations/tutorial013_py39.py b/docs_src/query_params_str_validations/tutorial013_py39.py deleted file mode 100644 index 0b0f44869f..0000000000 --- a/docs_src/query_params_str_validations/tutorial013_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -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 diff --git a/docs_src/request_files/tutorial001_03_an_py39.py b/docs_src/request_files/tutorial001_03_an_py39.py deleted file mode 100644 index 93098a677a..0000000000 --- a/docs_src/request_files/tutorial001_03_an_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]): - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file( - file: Annotated[UploadFile, File(description="A file read as UploadFile")], -): - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_03_py39.py b/docs_src/request_files/tutorial001_03_py39.py deleted file mode 100644 index d8005cc7d2..0000000000 --- a/docs_src/request_files/tutorial001_03_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: bytes = File(description="A file read as bytes")): - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file( - file: UploadFile = File(description="A file read as UploadFile"), -): - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_an_py39.py b/docs_src/request_files/tutorial001_an_py39.py deleted file mode 100644 index 26a7672216..0000000000 --- a/docs_src/request_files/tutorial001_an_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: Annotated[bytes, File()]): - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file(file: UploadFile): - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial001_py39.py b/docs_src/request_files/tutorial001_py39.py deleted file mode 100644 index 2e0ea63912..0000000000 --- a/docs_src/request_files/tutorial001_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI, File, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file(file: bytes = File()): - return {"file_size": len(file)} - - -@app.post("/uploadfile/") -async def create_upload_file(file: UploadFile): - return {"filename": file.filename} diff --git a/docs_src/request_files/tutorial002_an_py39.py b/docs_src/request_files/tutorial002_an_py39.py deleted file mode 100644 index db524ceab6..0000000000 --- a/docs_src/request_files/tutorial002_an_py39.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, File, UploadFile -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.post("/files/") -async def create_files(files: Annotated[list[bytes], File()]): - return {"file_sizes": [len(file) for file in files]} - - -@app.post("/uploadfiles/") -async def create_upload_files(files: list[UploadFile]): - return {"filenames": [file.filename for file in files]} - - -@app.get("/") -async def main(): - content = """ - -
- - -
-
- - -
- - """ - return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial002_py39.py b/docs_src/request_files/tutorial002_py39.py deleted file mode 100644 index b64cf55987..0000000000 --- a/docs_src/request_files/tutorial002_py39.py +++ /dev/null @@ -1,31 +0,0 @@ -from fastapi import FastAPI, File, UploadFile -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.post("/files/") -async def create_files(files: list[bytes] = File()): - return {"file_sizes": [len(file) for file in files]} - - -@app.post("/uploadfiles/") -async def create_upload_files(files: list[UploadFile]): - return {"filenames": [file.filename for file in files]} - - -@app.get("/") -async def main(): - content = """ - -
- - -
-
- - -
- - """ - return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial003_an_py39.py b/docs_src/request_files/tutorial003_an_py39.py deleted file mode 100644 index 5a8c5dab5c..0000000000 --- a/docs_src/request_files/tutorial003_an_py39.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, File, UploadFile -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.post("/files/") -async def create_files( - files: Annotated[list[bytes], File(description="Multiple files as bytes")], -): - return {"file_sizes": [len(file) for file in files]} - - -@app.post("/uploadfiles/") -async def create_upload_files( - files: Annotated[ - list[UploadFile], File(description="Multiple files as UploadFile") - ], -): - return {"filenames": [file.filename for file in files]} - - -@app.get("/") -async def main(): - content = """ - -
- - -
-
- - -
- - """ - return HTMLResponse(content=content) diff --git a/docs_src/request_files/tutorial003_py39.py b/docs_src/request_files/tutorial003_py39.py deleted file mode 100644 index 96f5e8742d..0000000000 --- a/docs_src/request_files/tutorial003_py39.py +++ /dev/null @@ -1,35 +0,0 @@ -from fastapi import FastAPI, File, UploadFile -from fastapi.responses import HTMLResponse - -app = FastAPI() - - -@app.post("/files/") -async def create_files( - files: list[bytes] = File(description="Multiple files as bytes"), -): - return {"file_sizes": [len(file) for file in files]} - - -@app.post("/uploadfiles/") -async def create_upload_files( - files: list[UploadFile] = File(description="Multiple files as UploadFile"), -): - return {"filenames": [file.filename for file in files]} - - -@app.get("/") -async def main(): - content = """ - -
- - -
-
- - -
- - """ - return HTMLResponse(content=content) diff --git a/docs_src/request_form_models/tutorial001_an_py39.py b/docs_src/request_form_models/tutorial001_an_py39.py deleted file mode 100644 index 7cc81aae95..0000000000 --- a/docs_src/request_form_models/tutorial001_an_py39.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Form -from pydantic import BaseModel - -app = FastAPI() - - -class FormData(BaseModel): - username: str - password: str - - -@app.post("/login/") -async def login(data: Annotated[FormData, Form()]): - return data diff --git a/docs_src/request_form_models/tutorial001_py39.py b/docs_src/request_form_models/tutorial001_py39.py deleted file mode 100644 index 98feff0b9f..0000000000 --- a/docs_src/request_form_models/tutorial001_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI, Form -from pydantic import BaseModel - -app = FastAPI() - - -class FormData(BaseModel): - username: str - password: str - - -@app.post("/login/") -async def login(data: FormData = Form()): - return data diff --git a/docs_src/request_form_models/tutorial002_an_py39.py b/docs_src/request_form_models/tutorial002_an_py39.py deleted file mode 100644 index 3004e08524..0000000000 --- a/docs_src/request_form_models/tutorial002_an_py39.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Form -from pydantic import BaseModel - -app = FastAPI() - - -class FormData(BaseModel): - username: str - password: str - model_config = {"extra": "forbid"} - - -@app.post("/login/") -async def login(data: Annotated[FormData, Form()]): - return data diff --git a/docs_src/request_form_models/tutorial002_py39.py b/docs_src/request_form_models/tutorial002_py39.py deleted file mode 100644 index 59b329e8d8..0000000000 --- a/docs_src/request_form_models/tutorial002_py39.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import FastAPI, Form -from pydantic import BaseModel - -app = FastAPI() - - -class FormData(BaseModel): - username: str - password: str - model_config = {"extra": "forbid"} - - -@app.post("/login/") -async def login(data: FormData = Form()): - return data diff --git a/docs_src/request_forms/tutorial001_an_py39.py b/docs_src/request_forms/tutorial001_an_py39.py deleted file mode 100644 index 8e9d2ea53a..0000000000 --- a/docs_src/request_forms/tutorial001_an_py39.py +++ /dev/null @@ -1,10 +0,0 @@ -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} diff --git a/docs_src/request_forms/tutorial001_py39.py b/docs_src/request_forms/tutorial001_py39.py deleted file mode 100644 index a537700019..0000000000 --- a/docs_src/request_forms/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI, Form - -app = FastAPI() - - -@app.post("/login/") -async def login(username: str = Form(), password: str = Form()): - return {"username": username} diff --git a/docs_src/request_forms_and_files/tutorial001_an_py39.py b/docs_src/request_forms_and_files/tutorial001_an_py39.py deleted file mode 100644 index 12cc43e50a..0000000000 --- a/docs_src/request_forms_and_files/tutorial001_an_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, File, Form, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file( - file: Annotated[bytes, File()], - fileb: Annotated[UploadFile, File()], - token: Annotated[str, Form()], -): - return { - "file_size": len(file), - "token": token, - "fileb_content_type": fileb.content_type, - } diff --git a/docs_src/request_forms_and_files/tutorial001_py39.py b/docs_src/request_forms_and_files/tutorial001_py39.py deleted file mode 100644 index 7b5224ce53..0000000000 --- a/docs_src/request_forms_and_files/tutorial001_py39.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI, File, Form, UploadFile - -app = FastAPI() - - -@app.post("/files/") -async def create_file( - file: bytes = File(), fileb: UploadFile = File(), token: str = Form() -): - return { - "file_size": len(file), - "token": token, - "fileb_content_type": fileb.content_type, - } diff --git a/docs_src/response_change_status_code/tutorial001_py39.py b/docs_src/response_change_status_code/tutorial001_py39.py deleted file mode 100644 index 197decbfbf..0000000000 --- a/docs_src/response_change_status_code/tutorial001_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from fastapi import FastAPI, Response, status - -app = FastAPI() - -tasks = {"foo": "Listen to the Bar Fighters"} - - -@app.put("/get-or-create-task/{task_id}", status_code=200) -def get_or_create_task(task_id: str, response: Response): - if task_id not in tasks: - tasks[task_id] = "This didn't exist before" - response.status_code = status.HTTP_201_CREATED - return tasks[task_id] diff --git a/docs_src/response_cookies/tutorial001_py39.py b/docs_src/response_cookies/tutorial001_py39.py deleted file mode 100644 index 33f8e8f6e9..0000000000 --- a/docs_src/response_cookies/tutorial001_py39.py +++ /dev/null @@ -1,12 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import JSONResponse - -app = FastAPI() - - -@app.post("/cookie/") -def create_cookie(): - content = {"message": "Come to the dark side, we have cookies"} - response = JSONResponse(content=content) - response.set_cookie(key="fakesession", value="fake-cookie-session-value") - return response diff --git a/docs_src/response_cookies/tutorial002_py39.py b/docs_src/response_cookies/tutorial002_py39.py deleted file mode 100644 index 76c06fdb9f..0000000000 --- a/docs_src/response_cookies/tutorial002_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI, Response - -app = FastAPI() - - -@app.post("/cookie-and-object/") -def create_cookie(response: Response): - response.set_cookie(key="fakesession", value="fake-cookie-session-value") - return {"message": "Come to the dark side, we have cookies"} diff --git a/docs_src/response_directly/tutorial002_py39.py b/docs_src/response_directly/tutorial002_py39.py deleted file mode 100644 index 6643da6e6d..0000000000 --- a/docs_src/response_directly/tutorial002_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI, Response - -app = FastAPI() - - -@app.get("/legacy/") -def get_legacy_data(): - data = """ - -
- Apply shampoo here. -
- - You'll have to use soap here. - -
- """ - return Response(content=data, media_type="application/xml") diff --git a/docs_src/response_headers/tutorial001_py39.py b/docs_src/response_headers/tutorial001_py39.py deleted file mode 100644 index 2da02a470b..0000000000 --- a/docs_src/response_headers/tutorial001_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import JSONResponse - -app = FastAPI() - - -@app.get("/headers/") -def get_headers(): - content = {"message": "Hello World"} - headers = {"X-Cat-Dog": "alone in the world", "Content-Language": "en-US"} - return JSONResponse(content=content, headers=headers) diff --git a/docs_src/response_headers/tutorial002_py39.py b/docs_src/response_headers/tutorial002_py39.py deleted file mode 100644 index d2c4983051..0000000000 --- a/docs_src/response_headers/tutorial002_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI, Response - -app = FastAPI() - - -@app.get("/headers-and-object/") -def get_headers(response: Response): - response.headers["X-Cat-Dog"] = "alone in the world" - return {"message": "Hello World"} diff --git a/docs_src/response_model/tutorial003_02_py39.py b/docs_src/response_model/tutorial003_02_py39.py deleted file mode 100644 index df6a09646d..0000000000 --- a/docs_src/response_model/tutorial003_02_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI, Response -from fastapi.responses import JSONResponse, RedirectResponse - -app = FastAPI() - - -@app.get("/portal") -async def get_portal(teleport: bool = False) -> Response: - if teleport: - return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") - return JSONResponse(content={"message": "Here's your interdimensional portal."}) diff --git a/docs_src/response_model/tutorial003_03_py39.py b/docs_src/response_model/tutorial003_03_py39.py deleted file mode 100644 index 0d4bd8de57..0000000000 --- a/docs_src/response_model/tutorial003_03_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI -from fastapi.responses import RedirectResponse - -app = FastAPI() - - -@app.get("/teleport") -async def get_teleport() -> RedirectResponse: - return RedirectResponse(url="https://www.youtube.com/watch?v=dQw4w9WgXcQ") diff --git a/docs_src/response_status_code/tutorial001_py39.py b/docs_src/response_status_code/tutorial001_py39.py deleted file mode 100644 index 14b6d6e675..0000000000 --- a/docs_src/response_status_code/tutorial001_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.post("/items/", status_code=201) -async def create_item(name: str): - return {"name": name} diff --git a/docs_src/response_status_code/tutorial002_py39.py b/docs_src/response_status_code/tutorial002_py39.py deleted file mode 100644 index 4fcc9829db..0000000000 --- a/docs_src/response_status_code/tutorial002_py39.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import FastAPI, status - -app = FastAPI() - - -@app.post("/items/", status_code=status.HTTP_201_CREATED) -async def create_item(name: str): - return {"name": name} diff --git a/docs_src/security/tutorial001_an_py39.py b/docs_src/security/tutorial001_an_py39.py deleted file mode 100644 index de110402ef..0000000000 --- a/docs_src/security/tutorial001_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI -from fastapi.security import OAuth2PasswordBearer - -app = FastAPI() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -@app.get("/items/") -async def read_items(token: Annotated[str, Depends(oauth2_scheme)]): - return {"token": token} diff --git a/docs_src/security/tutorial001_py39.py b/docs_src/security/tutorial001_py39.py deleted file mode 100644 index 224e59602e..0000000000 --- a/docs_src/security/tutorial001_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import Depends, FastAPI -from fastapi.security import OAuth2PasswordBearer - -app = FastAPI() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") - - -@app.get("/items/") -async def read_items(token: str = Depends(oauth2_scheme)): - return {"token": token} diff --git a/docs_src/security/tutorial006_an_py39.py b/docs_src/security/tutorial006_an_py39.py deleted file mode 100644 index 03c696a4b6..0000000000 --- a/docs_src/security/tutorial006_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated - -from fastapi import Depends, FastAPI -from fastapi.security import HTTPBasic, HTTPBasicCredentials - -app = FastAPI() - -security = HTTPBasic() - - -@app.get("/users/me") -def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]): - return {"username": credentials.username, "password": credentials.password} diff --git a/docs_src/security/tutorial006_py39.py b/docs_src/security/tutorial006_py39.py deleted file mode 100644 index 29121ffd63..0000000000 --- a/docs_src/security/tutorial006_py39.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import Depends, FastAPI -from fastapi.security import HTTPBasic, HTTPBasicCredentials - -app = FastAPI() - -security = HTTPBasic() - - -@app.get("/users/me") -def read_current_user(credentials: HTTPBasicCredentials = Depends(security)): - return {"username": credentials.username, "password": credentials.password} diff --git a/docs_src/security/tutorial007_an_py39.py b/docs_src/security/tutorial007_an_py39.py deleted file mode 100644 index 87ef986574..0000000000 --- a/docs_src/security/tutorial007_an_py39.py +++ /dev/null @@ -1,36 +0,0 @@ -import secrets -from typing import Annotated - -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import HTTPBasic, HTTPBasicCredentials - -app = FastAPI() - -security = HTTPBasic() - - -def get_current_username( - credentials: Annotated[HTTPBasicCredentials, Depends(security)], -): - current_username_bytes = credentials.username.encode("utf8") - correct_username_bytes = b"stanleyjobson" - is_correct_username = secrets.compare_digest( - current_username_bytes, correct_username_bytes - ) - current_password_bytes = credentials.password.encode("utf8") - correct_password_bytes = b"swordfish" - is_correct_password = secrets.compare_digest( - current_password_bytes, correct_password_bytes - ) - if not (is_correct_username and is_correct_password): - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect username or password", - headers={"WWW-Authenticate": "Basic"}, - ) - return credentials.username - - -@app.get("/users/me") -def read_current_user(username: Annotated[str, Depends(get_current_username)]): - return {"username": username} diff --git a/docs_src/security/tutorial007_py39.py b/docs_src/security/tutorial007_py39.py deleted file mode 100644 index ac816eb0c1..0000000000 --- a/docs_src/security/tutorial007_py39.py +++ /dev/null @@ -1,33 +0,0 @@ -import secrets - -from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import HTTPBasic, HTTPBasicCredentials - -app = FastAPI() - -security = HTTPBasic() - - -def get_current_username(credentials: HTTPBasicCredentials = Depends(security)): - current_username_bytes = credentials.username.encode("utf8") - correct_username_bytes = b"stanleyjobson" - is_correct_username = secrets.compare_digest( - current_username_bytes, correct_username_bytes - ) - current_password_bytes = credentials.password.encode("utf8") - correct_password_bytes = b"swordfish" - is_correct_password = secrets.compare_digest( - current_password_bytes, correct_password_bytes - ) - if not (is_correct_username and is_correct_password): - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect username or password", - headers={"WWW-Authenticate": "Basic"}, - ) - return credentials.username - - -@app.get("/users/me") -def read_current_user(username: str = Depends(get_current_username)): - return {"username": username} diff --git a/docs_src/settings/app01_py39/__init__.py b/docs_src/settings/app01_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/settings/app01_py39/config.py b/docs_src/settings/app01_py39/config.py deleted file mode 100644 index b31b8811d6..0000000000 --- a/docs_src/settings/app01_py39/config.py +++ /dev/null @@ -1,10 +0,0 @@ -from pydantic_settings import BaseSettings - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 - - -settings = Settings() diff --git a/docs_src/settings/app01_py39/main.py b/docs_src/settings/app01_py39/main.py deleted file mode 100644 index 4a3a86ce20..0000000000 --- a/docs_src/settings/app01_py39/main.py +++ /dev/null @@ -1,14 +0,0 @@ -from fastapi import FastAPI - -from .config import settings - -app = FastAPI() - - -@app.get("/info") -async def info(): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/settings/app02_an_py39/__init__.py b/docs_src/settings/app02_an_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/settings/app02_an_py39/config.py b/docs_src/settings/app02_an_py39/config.py deleted file mode 100644 index e17b5035dc..0000000000 --- a/docs_src/settings/app02_an_py39/config.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic_settings import BaseSettings - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 diff --git a/docs_src/settings/app02_an_py39/main.py b/docs_src/settings/app02_an_py39/main.py deleted file mode 100644 index 6d5db12a87..0000000000 --- a/docs_src/settings/app02_an_py39/main.py +++ /dev/null @@ -1,22 +0,0 @@ -from functools import lru_cache -from typing import Annotated - -from fastapi import Depends, FastAPI - -from .config import Settings - -app = FastAPI() - - -@lru_cache -def get_settings(): - return Settings() - - -@app.get("/info") -async def info(settings: Annotated[Settings, Depends(get_settings)]): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/settings/app02_an_py39/test_main.py b/docs_src/settings/app02_an_py39/test_main.py deleted file mode 100644 index 7a04d7e8ee..0000000000 --- a/docs_src/settings/app02_an_py39/test_main.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi.testclient import TestClient - -from .config import Settings -from .main import app, get_settings - -client = TestClient(app) - - -def get_settings_override(): - return Settings(admin_email="testing_admin@example.com") - - -app.dependency_overrides[get_settings] = get_settings_override - - -def test_app(): - response = client.get("/info") - data = response.json() - assert data == { - "app_name": "Awesome API", - "admin_email": "testing_admin@example.com", - "items_per_user": 50, - } diff --git a/docs_src/settings/app02_py39/__init__.py b/docs_src/settings/app02_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/settings/app02_py39/config.py b/docs_src/settings/app02_py39/config.py deleted file mode 100644 index e17b5035dc..0000000000 --- a/docs_src/settings/app02_py39/config.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic_settings import BaseSettings - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 diff --git a/docs_src/settings/app02_py39/main.py b/docs_src/settings/app02_py39/main.py deleted file mode 100644 index 941f82e6b3..0000000000 --- a/docs_src/settings/app02_py39/main.py +++ /dev/null @@ -1,21 +0,0 @@ -from functools import lru_cache - -from fastapi import Depends, FastAPI - -from .config import Settings - -app = FastAPI() - - -@lru_cache -def get_settings(): - return Settings() - - -@app.get("/info") -async def info(settings: Settings = Depends(get_settings)): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/settings/app02_py39/test_main.py b/docs_src/settings/app02_py39/test_main.py deleted file mode 100644 index 7a04d7e8ee..0000000000 --- a/docs_src/settings/app02_py39/test_main.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi.testclient import TestClient - -from .config import Settings -from .main import app, get_settings - -client = TestClient(app) - - -def get_settings_override(): - return Settings(admin_email="testing_admin@example.com") - - -app.dependency_overrides[get_settings] = get_settings_override - - -def test_app(): - response = client.get("/info") - data = response.json() - assert data == { - "app_name": "Awesome API", - "admin_email": "testing_admin@example.com", - "items_per_user": 50, - } diff --git a/docs_src/settings/app03_an_py39/__init__.py b/docs_src/settings/app03_an_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/settings/app03_an_py39/config.py b/docs_src/settings/app03_an_py39/config.py deleted file mode 100644 index 08f8f88c28..0000000000 --- a/docs_src/settings/app03_an_py39/config.py +++ /dev/null @@ -1,9 +0,0 @@ -from pydantic_settings import BaseSettings, SettingsConfigDict - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 - - model_config = SettingsConfigDict(env_file=".env") diff --git a/docs_src/settings/app03_an_py39/main.py b/docs_src/settings/app03_an_py39/main.py deleted file mode 100644 index 2f64b9cd17..0000000000 --- a/docs_src/settings/app03_an_py39/main.py +++ /dev/null @@ -1,22 +0,0 @@ -from functools import lru_cache -from typing import Annotated - -from fastapi import Depends, FastAPI - -from . import config - -app = FastAPI() - - -@lru_cache -def get_settings(): - return config.Settings() - - -@app.get("/info") -async def info(settings: Annotated[config.Settings, Depends(get_settings)]): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/settings/app03_py39/__init__.py b/docs_src/settings/app03_py39/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs_src/settings/app03_py39/config.py b/docs_src/settings/app03_py39/config.py deleted file mode 100644 index 08f8f88c28..0000000000 --- a/docs_src/settings/app03_py39/config.py +++ /dev/null @@ -1,9 +0,0 @@ -from pydantic_settings import BaseSettings, SettingsConfigDict - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 - - model_config = SettingsConfigDict(env_file=".env") diff --git a/docs_src/settings/app03_py39/main.py b/docs_src/settings/app03_py39/main.py deleted file mode 100644 index ea64a5709c..0000000000 --- a/docs_src/settings/app03_py39/main.py +++ /dev/null @@ -1,21 +0,0 @@ -from functools import lru_cache - -from fastapi import Depends, FastAPI - -from . import config - -app = FastAPI() - - -@lru_cache -def get_settings(): - return config.Settings() - - -@app.get("/info") -async def info(settings: config.Settings = Depends(get_settings)): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/settings/tutorial001_py39.py b/docs_src/settings/tutorial001_py39.py deleted file mode 100644 index d48c4c060c..0000000000 --- a/docs_src/settings/tutorial001_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from fastapi import FastAPI -from pydantic_settings import BaseSettings - - -class Settings(BaseSettings): - app_name: str = "Awesome API" - admin_email: str - items_per_user: int = 50 - - -settings = Settings() -app = FastAPI() - - -@app.get("/info") -async def info(): - return { - "app_name": settings.app_name, - "admin_email": settings.admin_email, - "items_per_user": settings.items_per_user, - } diff --git a/docs_src/static_files/tutorial001_py39.py b/docs_src/static_files/tutorial001_py39.py deleted file mode 100644 index 460352c7e1..0000000000 --- a/docs_src/static_files/tutorial001_py39.py +++ /dev/null @@ -1,6 +0,0 @@ -from fastapi import FastAPI -from fastapi.staticfiles import StaticFiles - -app = FastAPI() - -app.mount("/static", StaticFiles(directory="static"), name="static") diff --git a/docs_src/sub_applications/tutorial001_py39.py b/docs_src/sub_applications/tutorial001_py39.py deleted file mode 100644 index 57e627e804..0000000000 --- a/docs_src/sub_applications/tutorial001_py39.py +++ /dev/null @@ -1,19 +0,0 @@ -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/app") -def read_main(): - return {"message": "Hello World from main app"} - - -subapi = FastAPI() - - -@subapi.get("/sub") -def read_sub(): - return {"message": "Hello World from sub API"} - - -app.mount("/subapi", subapi) diff --git a/docs_src/templates/tutorial001_py39.py b/docs_src/templates/tutorial001_py39.py deleted file mode 100644 index 81ccc8d4d0..0000000000 --- a/docs_src/templates/tutorial001_py39.py +++ /dev/null @@ -1,18 +0,0 @@ -from fastapi import FastAPI, Request -from fastapi.responses import HTMLResponse -from fastapi.staticfiles import StaticFiles -from fastapi.templating import Jinja2Templates - -app = FastAPI() - -app.mount("/static", StaticFiles(directory="static"), name="static") - - -templates = Jinja2Templates(directory="templates") - - -@app.get("/items/{id}", response_class=HTMLResponse) -async def read_item(request: Request, id: str): - return templates.TemplateResponse( - request=request, name="item.html", context={"id": id} - ) diff --git a/docs_src/using_request_directly/tutorial001_py39.py b/docs_src/using_request_directly/tutorial001_py39.py deleted file mode 100644 index 2d7288b54d..0000000000 --- a/docs_src/using_request_directly/tutorial001_py39.py +++ /dev/null @@ -1,9 +0,0 @@ -from fastapi import FastAPI, Request - -app = FastAPI() - - -@app.get("/items/{item_id}") -def read_root(item_id: str, request: Request): - client_host = request.client.host - return {"client_host": client_host, "item_id": item_id} diff --git a/docs_src/websockets/tutorial001_py39.py b/docs_src/websockets/tutorial001_py39.py deleted file mode 100644 index a43a2be17c..0000000000 --- a/docs_src/websockets/tutorial001_py39.py +++ /dev/null @@ -1,51 +0,0 @@ -from fastapi import FastAPI, WebSocket -from fastapi.responses import HTMLResponse - -app = FastAPI() - -html = """ - - - - Chat - - -

WebSocket Chat

-
- - -
-
    -
- - - -""" - - -@app.get("/") -async def get(): - return HTMLResponse(html) - - -@app.websocket("/ws") -async def websocket_endpoint(websocket: WebSocket): - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text(f"Message text was: {data}") diff --git a/docs_src/websockets/tutorial003_py39.py b/docs_src/websockets/tutorial003_py39.py deleted file mode 100644 index 3162180889..0000000000 --- a/docs_src/websockets/tutorial003_py39.py +++ /dev/null @@ -1,81 +0,0 @@ -from fastapi import FastAPI, WebSocket, WebSocketDisconnect -from fastapi.responses import HTMLResponse - -app = FastAPI() - -html = """ - - - - Chat - - -

WebSocket Chat

-

Your ID:

-
- - -
-
    -
- - - -""" - - -class ConnectionManager: - def __init__(self): - self.active_connections: list[WebSocket] = [] - - async def connect(self, websocket: WebSocket): - await websocket.accept() - self.active_connections.append(websocket) - - def disconnect(self, websocket: WebSocket): - self.active_connections.remove(websocket) - - async def send_personal_message(self, message: str, websocket: WebSocket): - await websocket.send_text(message) - - async def broadcast(self, message: str): - for connection in self.active_connections: - await connection.send_text(message) - - -manager = ConnectionManager() - - -@app.get("/") -async def get(): - return HTMLResponse(html) - - -@app.websocket("/ws/{client_id}") -async def websocket_endpoint(websocket: WebSocket, client_id: int): - await manager.connect(websocket) - try: - while True: - data = await websocket.receive_text() - await manager.send_personal_message(f"You wrote: {data}", websocket) - await manager.broadcast(f"Client #{client_id} says: {data}") - except WebSocketDisconnect: - manager.disconnect(websocket) - await manager.broadcast(f"Client #{client_id} left the chat") diff --git a/docs_src/wsgi/tutorial001_py39.py b/docs_src/wsgi/tutorial001_py39.py deleted file mode 100644 index 8eeceb829e..0000000000 --- a/docs_src/wsgi/tutorial001_py39.py +++ /dev/null @@ -1,23 +0,0 @@ -from a2wsgi import WSGIMiddleware -from fastapi import FastAPI -from flask import Flask, request -from markupsafe import escape - -flask_app = Flask(__name__) - - -@flask_app.route("/") -def flask_main(): - name = request.args.get("name", "World") - return f"Hello, {escape(name)} from Flask!" - - -app = FastAPI() - - -@app.get("/v2") -def read_main(): - return {"message": "Hello World"} - - -app.mount("/v1", WSGIMiddleware(flask_app)) diff --git a/scripts/tests/test_translation_fixer/test_code_includes/data/en_doc.md b/scripts/tests/test_translation_fixer/test_code_includes/data/en_doc.md index 593da0b327..0e021dadea 100644 --- a/scripts/tests/test_translation_fixer/test_code_includes/data/en_doc.md +++ b/scripts/tests/test_translation_fixer/test_code_includes/data/en_doc.md @@ -4,7 +4,7 @@ Some text -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Some more text diff --git a/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_gt.md b/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_gt.md index c1ad94d276..aca1464ff2 100644 --- a/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_gt.md +++ b/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_gt.md @@ -4,7 +4,7 @@ Some text -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Some more text @@ -12,4 +12,4 @@ Some more text And even more text -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} diff --git a/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_lt.md b/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_lt.md index 07eaf2c23d..12573aa196 100644 --- a/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_lt.md +++ b/scripts/tests/test_translation_fixer/test_code_includes/data/translated_doc_number_lt.md @@ -4,7 +4,7 @@ Some text -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} Some more text diff --git a/scripts/tests/test_translation_fixer/test_complex_doc/data/en_doc.md b/scripts/tests/test_translation_fixer/test_complex_doc/data/en_doc.md index 69cd3f3fd7..d6c1e3d2fe 100644 --- a/scripts/tests/test_translation_fixer/test_complex_doc/data/en_doc.md +++ b/scripts/tests/test_translation_fixer/test_complex_doc/data/en_doc.md @@ -141,16 +141,16 @@ def hello_world(): ## Simple code includes { #simple-code-includes } -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} -{* ../../docs_src/python_types/tutorial002_py39.py *} +{* ../../docs_src/python_types/tutorial002_py310.py *} ## Code includes with highlighting { #code-includes-with-highlighting } -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} -{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[10] *} ## Code includes with line ranges { #code-includes-with-line-ranges } @@ -169,19 +169,19 @@ def hello_world(): ## Code includes qith title { #code-includes-with-title } -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ## Code includes with unknown attributes { #code-includes-with-unknown-attributes } -{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *} +{* ../../docs_src/python_types/tutorial001_py310.py unknown[123] *} ## Some more code includes to test fixing { #some-more-code-includes-to-test-fixing } {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} diff --git a/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc.md b/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc.md index c922d7b133..b27eef202c 100644 --- a/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc.md +++ b/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc.md @@ -139,16 +139,16 @@ def hello_world(): ## ะŸั€ะพัั‚ั‹ะต ะฒะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ { #simple-code-includes } -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} -{* ../../docs_src/python_types/tutorial002_py39.py *} +{* ../../docs_src/python_types/tutorial002_py310.py *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะฟะพะดัะฒะตั‚ะบะพะน { #code-includes-with-highlighting } -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} -{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[10] *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะดะธะฐะฟะฐะทะพะฝะฐะผะธ ัั‚ั€ะพะบ { #code-includes-with-line-ranges } @@ -167,19 +167,19 @@ def hello_world(): ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะทะฐะณะพะปะพะฒะบะพะผ { #code-includes-with-title } -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะฝะตะธะทะฒะตัั‚ะฝั‹ะผะธ ะฐั‚ั€ะธะฑัƒั‚ะฐะผะธ { #code-includes-with-unknown-attributes } -{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *} +{* ../../docs_src/python_types/tutorial001_py310.py unknown[123] *} ## ะ•ั‰ั‘ ะฒะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ะดะปั ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั ะธัะฟั€ะฐะฒะปะตะฝะธั { #some-more-code-includes-to-test-fixing } {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19 : 21] *} -{* ../../docs_src/bigger_applications/app_an_py39/wrong.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/wrong.py hl[3] title["app/internal/admin.py"] *} {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[1:30] hl[1:10] *} diff --git a/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc_expected.md b/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc_expected.md index b33f36e772..8e2394f14f 100644 --- a/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc_expected.md +++ b/scripts/tests/test_translation_fixer/test_complex_doc/data/translated_doc_expected.md @@ -139,16 +139,16 @@ def hello_world(): ## ะŸั€ะพัั‚ั‹ะต ะฒะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ { #simple-code-includes } -{* ../../docs_src/python_types/tutorial001_py39.py *} +{* ../../docs_src/python_types/tutorial001_py310.py *} -{* ../../docs_src/python_types/tutorial002_py39.py *} +{* ../../docs_src/python_types/tutorial002_py310.py *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะฟะพะดัะฒะตั‚ะบะพะน { #code-includes-with-highlighting } -{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *} +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} -{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *} +{* ../../docs_src/python_types/tutorial006_py310.py hl[10] *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะดะธะฐะฟะฐะทะพะฝะฐะผะธ ัั‚ั€ะพะบ { #code-includes-with-line-ranges } @@ -167,19 +167,19 @@ def hello_world(): ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะทะฐะณะพะปะพะฒะบะพะผ { #code-includes-with-title } -{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} ## ะ’ะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ั ะฝะตะธะทะฒะตัั‚ะฝั‹ะผะธ ะฐั‚ั€ะธะฑัƒั‚ะฐะผะธ { #code-includes-with-unknown-attributes } -{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *} +{* ../../docs_src/python_types/tutorial001_py310.py unknown[123] *} ## ะ•ั‰ั‘ ะฒะบะปัŽั‡ะตะฝะธั ะบะพะดะฐ ะดะปั ั‚ะตัั‚ะธั€ะพะฒะฐะฝะธั ะธัะฟั€ะฐะฒะปะตะฝะธั { #some-more-code-includes-to-test-fixing } {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} -{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *} +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} {* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} diff --git a/tests/test_tutorial/test_python_types/test_tutorial009c.py b/tests/test_tutorial/test_python_types/test_tutorial009c.py deleted file mode 100644 index 17c4b9e0c2..0000000000 --- a/tests/test_tutorial/test_python_types/test_tutorial009c.py +++ /dev/null @@ -1,33 +0,0 @@ -import importlib -import re -from types import ModuleType -from unittest.mock import patch - -import pytest - -from ...utils import needs_py310 - - -@pytest.fixture( - name="module", - params=[ - pytest.param("tutorial009c_py310"), - pytest.param("tutorial009c_py310", marks=needs_py310), - ], -) -def get_module(request: pytest.FixtureRequest): - mod = importlib.import_module(f"docs_src.python_types.{request.param}") - return mod - - -def test_say_hi(module: ModuleType): - with patch("builtins.print") as mock_print: - module.say_hi("FastAPI") - - mock_print.assert_called_once_with("Hey FastAPI!") - - with pytest.raises( - TypeError, - match=re.escape("say_hi() missing 1 required positional argument: 'name'"), - ): - module.say_hi() From 6e5680c7ea3edbb092518832f16b5203c618c557 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 17 Feb 2026 08:08:30 +0000 Subject: [PATCH 246/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5e1435065c..1f72f883a2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ๐Ÿ”ฅ Remove Python 3.9 specific files, no longer needed after updating translations. PR [#14931](https://github.com/fastapi/fastapi/pull/14931) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update docs for JWT to prevent timing attacks. PR [#14908](https://github.com/fastapi/fastapi/pull/14908) by [@tiangolo](https://github.com/tiangolo). ### Translations From faee822574d3c202123f48eb09b9bd207385335b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 17 Feb 2026 01:59:14 -0800 Subject: [PATCH 247/367] =?UTF-8?q?=F0=9F=8E=A8=20Upgrade=20typing=20synta?= =?UTF-8?q?x=20for=20Python=203.10=20(#14932)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: tiangolo <1326112+tiangolo@users.noreply.github.com> Co-authored-by: github-actions[bot] --- docs_src/extra_models/tutorial003_py310.py | 4 +--- scripts/doc_parsing_utils.py | 22 ++++++++--------- scripts/mkdocs_hooks.py | 8 +++---- scripts/notify_translations.py | 24 +++++++++---------- scripts/people.py | 12 +++++----- tests/main.py | 5 ++-- tests/test_additional_properties_bool.py | 4 +--- ...itional_responses_union_duplicate_anyof.py | 4 +--- tests/test_callable_endpoint.py | 3 +-- tests/test_compat.py | 24 +++++++++---------- tests/test_custom_middleware_exception.py | 3 +-- tests/test_custom_schema_fields.py | 8 +++---- tests/test_dependency_contextvars.py | 6 ++--- tests/test_dependency_overrides.py | 4 +--- tests/test_dependency_paramless.py | 4 ++-- tests/test_enforce_once_required_parameter.py | 6 ++--- tests/test_extra_routes.py | 4 +--- tests/test_filter_pydantic_sub_model_pv2.py | 4 +--- tests/test_form_default.py | 8 +++---- tests/test_forms_single_model.py | 4 ++-- tests/test_infer_param_optionality.py | 6 ++--- tests/test_invalid_sequence_param.py | 4 +--- tests/test_jsonable_encoder.py | 4 ++-- tests/test_openapi_examples.py | 8 +++---- .../test_openapi_query_parameter_extension.py | 4 +--- tests/test_openapi_schema_type.py | 4 +--- ...t_openapi_separate_input_output_schemas.py | 8 +++---- tests/test_optional_file_list.py | 4 +--- tests/test_param_class.py | 4 +--- tests/test_param_include_in_schema.py | 8 +++---- tests/test_pydantic_v1_error.py | 3 +-- ...ataclasses_uuid_stringified_annotations.py | 5 ++-- .../test_body/test_list.py | 8 +++---- .../test_body/test_optional_list.py | 20 +++++++--------- .../test_body/test_optional_str.py | 20 +++++++--------- .../test_body/test_required_str.py | 12 ++++------ .../test_cookie/test_optional_str.py | 18 +++++++------- .../test_file/test_optional.py | 18 +++++++------- .../test_file/test_optional_list.py | 20 +++++++--------- .../test_form/test_optional_list.py | 20 +++++++--------- .../test_form/test_optional_str.py | 18 +++++++------- .../test_header/test_optional_list.py | 20 +++++++--------- .../test_header/test_optional_str.py | 18 +++++++------- .../test_query/test_optional_list.py | 20 +++++++--------- .../test_query/test_optional_str.py | 18 +++++++------- tests/test_required_noneable.py | 8 +++---- ...est_response_model_as_return_annotation.py | 12 ++++------ tests/test_router_events.py | 5 ++-- tests/test_schema_extra_examples.py | 20 +++++++--------- .../test_security_api_key_cookie_optional.py | 4 +--- .../test_security_api_key_header_optional.py | 6 ++--- tests/test_security_api_key_query_optional.py | 6 ++--- tests/test_security_http_base_optional.py | 4 +--- tests/test_security_http_basic_optional.py | 3 +-- tests/test_security_http_bearer_optional.py | 4 +--- tests/test_security_http_digest_optional.py | 4 +--- ...curity_oauth2_authorization_code_bearer.py | 4 +--- ...2_authorization_code_bearer_description.py | 4 +--- ...uthorization_code_bearer_scopes_openapi.py | 6 ++--- tests/test_security_oauth2_optional.py | 6 ++--- ...st_security_oauth2_optional_description.py | 6 ++--- ...ecurity_oauth2_password_bearer_optional.py | 4 +--- ...h2_password_bearer_optional_description.py | 4 +--- .../test_security_openid_connect_optional.py | 6 ++--- tests/test_serialize_response.py | 6 ++--- tests/test_serialize_response_dataclass.py | 5 ++-- tests/test_serialize_response_model.py | 6 ++--- tests/test_skip_defaults.py | 12 ++++------ tests/test_sub_callbacks.py | 6 ++--- tests/test_union_body.py | 6 ++--- tests/test_union_body_discriminator.py | 5 ++-- ...test_union_body_discriminator_annotated.py | 4 ++-- tests/test_union_forms.py | 4 ++-- tests/test_union_inherited_body.py | 6 ++--- tests/test_validate_response.py | 8 +++---- tests/test_validate_response_dataclass.py | 6 ++--- tests/utils.py | 1 - 77 files changed, 269 insertions(+), 375 deletions(-) diff --git a/docs_src/extra_models/tutorial003_py310.py b/docs_src/extra_models/tutorial003_py310.py index 06675cbc09..8fe6f7136e 100644 --- a/docs_src/extra_models/tutorial003_py310.py +++ b/docs_src/extra_models/tutorial003_py310.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import FastAPI from pydantic import BaseModel @@ -30,6 +28,6 @@ items = { } -@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem]) +@app.get("/items/{item_id}", response_model=PlaneItem | CarItem) async def read_item(item_id: str): return items[item_id] diff --git a/scripts/doc_parsing_utils.py b/scripts/doc_parsing_utils.py index 79f2e9ec0a..1cd2299e66 100644 --- a/scripts/doc_parsing_utils.py +++ b/scripts/doc_parsing_utils.py @@ -1,5 +1,5 @@ import re -from typing import TypedDict, Union +from typing import TypedDict CODE_INCLUDE_RE = re.compile(r"^\{\*\s*(\S+)\s*(.*)\*\}$") CODE_INCLUDE_PLACEHOLDER = "" @@ -50,8 +50,8 @@ class MarkdownLinkInfo(TypedDict): line_no: int url: str text: str - title: Union[str, None] - attributes: Union[str, None] + title: str | None + attributes: str | None full_match: str @@ -287,8 +287,8 @@ def _add_lang_code_to_url(url: str, lang_code: str) -> str: def _construct_markdown_link( url: str, text: str, - title: Union[str, None], - attributes: Union[str, None], + title: str | None, + attributes: str | None, lang_code: str, ) -> str: """ @@ -549,7 +549,7 @@ def extract_multiline_code_blocks(text: list[str]) -> list[MultilineCodeBlockInf return blocks -def _split_hash_comment(line: str) -> tuple[str, Union[str, None]]: +def _split_hash_comment(line: str) -> tuple[str, str | None]: match = HASH_COMMENT_RE.match(line) if match: code = match.group("code").rstrip() @@ -558,7 +558,7 @@ def _split_hash_comment(line: str) -> tuple[str, Union[str, None]]: return line.rstrip(), None -def _split_slashes_comment(line: str) -> tuple[str, Union[str, None]]: +def _split_slashes_comment(line: str) -> tuple[str, str | None]: match = SLASHES_COMMENT_RE.match(line) if match: code = match.group("code").rstrip() @@ -603,9 +603,9 @@ def replace_multiline_code_block( return block_a["content"].copy() # We don't handle mermaid code blocks for now code_block: list[str] = [] - for line_a, line_b in zip(block_a["content"], block_b["content"]): - line_a_comment: Union[str, None] = None - line_b_comment: Union[str, None] = None + for line_a, line_b in zip(block_a["content"], block_b["content"], strict=False): + line_a_comment: str | None = None + line_b_comment: str | None = None # Handle comments based on language if block_language in { @@ -659,7 +659,7 @@ def replace_multiline_code_blocks_in_text( ) modified_text = text.copy() - for block, original_block in zip(code_blocks, original_code_blocks): + for block, original_block in zip(code_blocks, original_code_blocks, strict=True): updated_content = replace_multiline_code_block(block, original_block) start_line_index = block["start_line_no"] - 1 diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py index 567c0111dc..97006953d6 100644 --- a/scripts/mkdocs_hooks.py +++ b/scripts/mkdocs_hooks.py @@ -1,6 +1,6 @@ from functools import lru_cache from pathlib import Path -from typing import Any, Union +from typing import Any import material from mkdocs.config.defaults import MkDocsConfig @@ -105,9 +105,9 @@ def on_files(files: Files, *, config: MkDocsConfig) -> Files: def generate_renamed_section_items( - items: list[Union[Page, Section, Link]], *, config: MkDocsConfig -) -> list[Union[Page, Section, Link]]: - new_items: list[Union[Page, Section, Link]] = [] + items: list[Page | Section | Link], *, config: MkDocsConfig +) -> list[Page | Section | Link]: + new_items: list[Page | Section | Link] = [] for item in items: if isinstance(item, Section): new_title = item.title diff --git a/scripts/notify_translations.py b/scripts/notify_translations.py index 74cdf0dffe..3484b69c70 100644 --- a/scripts/notify_translations.py +++ b/scripts/notify_translations.py @@ -3,7 +3,7 @@ import random import sys import time from pathlib import Path -from typing import Any, Union, cast +from typing import Any, cast import httpx from github import Github @@ -181,9 +181,9 @@ class Settings(BaseSettings): github_repository: str github_token: SecretStr github_event_path: Path - github_event_name: Union[str, None] = None + github_event_name: str | None = None httpx_timeout: int = 30 - debug: Union[bool, None] = False + debug: bool | None = False number: int | None = None @@ -199,12 +199,12 @@ def get_graphql_response( *, settings: Settings, query: str, - after: Union[str, None] = None, - category_id: Union[str, None] = None, - discussion_number: Union[int, None] = None, - discussion_id: Union[str, None] = None, - comment_id: Union[str, None] = None, - body: Union[str, None] = None, + after: str | None = None, + category_id: str | None = None, + discussion_number: int | None = None, + discussion_id: str | None = None, + comment_id: str | None = None, + body: str | None = None, ) -> dict[str, Any]: headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"} variables = { @@ -249,7 +249,7 @@ def get_graphql_translation_discussions( def get_graphql_translation_discussion_comments_edges( - *, settings: Settings, discussion_number: int, after: Union[str, None] = None + *, settings: Settings, discussion_number: int, after: str | None = None ) -> list[CommentsEdge]: data = get_graphql_response( settings=settings, @@ -372,8 +372,8 @@ def main() -> None: f"Found a translation discussion for language: {lang} in discussion: #{discussion.number}" ) - already_notified_comment: Union[Comment, None] = None - already_done_comment: Union[Comment, None] = None + already_notified_comment: Comment | None = None + already_done_comment: Comment | None = None logging.info( f"Checking current comments in discussion: #{discussion.number} to see if already notified about this PR: #{pr.number}" diff --git a/scripts/people.py b/scripts/people.py index 207ab46493..f3254ab606 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -6,7 +6,7 @@ from collections import Counter from collections.abc import Container from datetime import datetime, timedelta, timezone from pathlib import Path -from typing import Any, Union +from typing import Any import httpx import yaml @@ -70,7 +70,7 @@ class Author(BaseModel): class CommentsNode(BaseModel): createdAt: datetime - author: Union[Author, None] = None + author: Author | None = None class Replies(BaseModel): @@ -89,7 +89,7 @@ class DiscussionsComments(BaseModel): class DiscussionsNode(BaseModel): number: int - author: Union[Author, None] = None + author: Author | None = None title: str | None = None createdAt: datetime comments: DiscussionsComments @@ -127,8 +127,8 @@ def get_graphql_response( *, settings: Settings, query: str, - after: Union[str, None] = None, - category_id: Union[str, None] = None, + after: str | None = None, + category_id: str | None = None, ) -> dict[str, Any]: headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"} variables = {"after": after, "category_id": category_id} @@ -156,7 +156,7 @@ def get_graphql_response( def get_graphql_question_discussion_edges( *, settings: Settings, - after: Union[str, None] = None, + after: str | None = None, ) -> list[DiscussionsEdge]: data = get_graphql_response( settings=settings, diff --git a/tests/main.py b/tests/main.py index 7edb16c615..d2fbbe6153 100644 --- a/tests/main.py +++ b/tests/main.py @@ -1,5 +1,4 @@ import http -from typing import Optional from fastapi import FastAPI, Path, Query @@ -54,7 +53,7 @@ def get_bool_id(item_id: bool): @app.get("/path/param/{item_id}") -def get_path_param_id(item_id: Optional[str] = Path()): +def get_path_param_id(item_id: str | None = Path()): return item_id @@ -161,7 +160,7 @@ def get_query_type(query: int): @app.get("/query/int/optional") -def get_query_type_optional(query: Optional[int] = None): +def get_query_type_optional(query: int | None = None): if query is None: return "foo bar" return f"foo bar {query}" diff --git a/tests/test_additional_properties_bool.py b/tests/test_additional_properties_bool.py index c02841cde1..9a1e139eaa 100644 --- a/tests/test_additional_properties_bool.py +++ b/tests/test_additional_properties_bool.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -19,7 +17,7 @@ app = FastAPI() @app.post("/") async def post( - foo: Union[Foo, None] = None, + foo: Foo | None = None, ): return foo diff --git a/tests/test_additional_responses_union_duplicate_anyof.py b/tests/test_additional_responses_union_duplicate_anyof.py index 5d833fce4a..401bc0a744 100644 --- a/tests/test_additional_responses_union_duplicate_anyof.py +++ b/tests/test_additional_responses_union_duplicate_anyof.py @@ -4,8 +4,6 @@ don't accumulate duplicate $ref entries in anyOf arrays. See https://github.com/fastapi/fastapi/pull/14463 """ -from typing import Union - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -23,7 +21,7 @@ class ModelB(BaseModel): app = FastAPI( responses={ 500: { - "model": Union[ModelA, ModelB], + "model": ModelA | ModelB, "content": {"application/json": {"examples": {"Case A": {"value": "a"}}}}, } } diff --git a/tests/test_callable_endpoint.py b/tests/test_callable_endpoint.py index 1882e9053a..28999d3833 100644 --- a/tests/test_callable_endpoint.py +++ b/tests/test_callable_endpoint.py @@ -1,11 +1,10 @@ from functools import partial -from typing import Optional from fastapi import FastAPI from fastapi.testclient import TestClient -def main(some_arg, q: Optional[str] = None): +def main(some_arg, q: str | None = None): return {"some_arg": some_arg, "q": q} diff --git a/tests/test_compat.py b/tests/test_compat.py index 0b5600f8f5..772bd305eb 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import FastAPI, UploadFile from fastapi._compat import ( Undefined, @@ -10,8 +8,6 @@ from fastapi.testclient import TestClient from pydantic import BaseModel, ConfigDict from pydantic.fields import FieldInfo -from .utils import needs_py310 - def test_model_field_default_required(): from fastapi._compat import v2 @@ -26,7 +22,7 @@ def test_complex(): app = FastAPI() @app.post("/") - def foo(foo: Union[str, list[int]]): + def foo(foo: str | list[int]): return foo client = TestClient(app) @@ -49,17 +45,17 @@ def test_propagates_pydantic2_model_config(): class EmbeddedModel(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) - value: Union[str, Missing] = Missing() + value: str | Missing = Missing() class Model(BaseModel): model_config = ConfigDict( arbitrary_types_allowed=True, ) - value: Union[str, Missing] = Missing() + value: str | Missing = Missing() embedded_model: EmbeddedModel = EmbeddedModel() @app.post("/") - def foo(req: Model) -> dict[str, Union[str, None]]: + def foo(req: Model) -> dict[str, str | None]: return { "value": req.value or None, "embedded_value": req.embedded_model.value or None, @@ -89,7 +85,7 @@ def test_is_bytes_sequence_annotation_union(): # TODO: in theory this would allow declaring types that could be lists of bytes # to be read from files and other types, but I'm not even sure it's a good idea # to support it as a first class "feature" - assert is_bytes_sequence_annotation(Union[list[str], list[bytes]]) + assert is_bytes_sequence_annotation(list[str] | list[bytes]) def test_is_uploadfile_sequence_annotation(): @@ -97,21 +93,20 @@ def test_is_uploadfile_sequence_annotation(): # TODO: in theory this would allow declaring types that could be lists of UploadFile # and other types, but I'm not even sure it's a good idea to support it as a first # class "feature" - assert is_uploadfile_sequence_annotation(Union[list[str], list[UploadFile]]) + assert is_uploadfile_sequence_annotation(list[str] | list[UploadFile]) def test_serialize_sequence_value_with_optional_list(): """Test that serialize_sequence_value handles optional lists correctly.""" from fastapi._compat import v2 - field_info = FieldInfo(annotation=Union[list[str], None]) + field_info = FieldInfo(annotation=list[str] | None) field = v2.ModelField(name="items", field_info=field_info) result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"]) assert result == ["a", "b", "c"] assert isinstance(result, list) -@needs_py310 def test_serialize_sequence_value_with_optional_list_pipe_union(): """Test that serialize_sequence_value handles optional lists correctly (with new syntax).""" from fastapi._compat import v2 @@ -125,9 +120,12 @@ def test_serialize_sequence_value_with_optional_list_pipe_union(): def test_serialize_sequence_value_with_none_first_in_union(): """Test that serialize_sequence_value handles Union[None, List[...]] correctly.""" + from typing import Union + from fastapi._compat import v2 - field_info = FieldInfo(annotation=Union[None, list[str]]) + # Use Union[None, list[str]] to ensure None comes first in the union args + field_info = FieldInfo(annotation=Union[None, list[str]]) # noqa: UP007 field = v2.ModelField(name="items", field_info=field_info) result = v2.serialize_sequence_value(field=field, value=["x", "y"]) assert result == ["x", "y"] diff --git a/tests/test_custom_middleware_exception.py b/tests/test_custom_middleware_exception.py index d9b81e7c2e..cf548f4aed 100644 --- a/tests/test_custom_middleware_exception.py +++ b/tests/test_custom_middleware_exception.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import Optional from fastapi import APIRouter, FastAPI, File, UploadFile from fastapi.exceptions import HTTPException @@ -17,7 +16,7 @@ class ContentSizeLimitMiddleware: max_content_size (optional): the maximum content size allowed in bytes, None for no limit """ - def __init__(self, app: APIRouter, max_content_size: Optional[int] = None): + def __init__(self, app: APIRouter, max_content_size: int | None = None): self.app = app self.max_content_size = max_content_size diff --git a/tests/test_custom_schema_fields.py b/tests/test_custom_schema_fields.py index 60b795e9ba..c907c54242 100644 --- a/tests/test_custom_schema_fields.py +++ b/tests/test_custom_schema_fields.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated from fastapi import FastAPI from fastapi.testclient import TestClient @@ -10,9 +10,9 @@ app = FastAPI() class Item(BaseModel): name: str - description: Annotated[ - Optional[str], WithJsonSchema({"type": ["string", "null"]}) - ] = None + description: Annotated[str | None, WithJsonSchema({"type": ["string", "null"]})] = ( + None + ) model_config = { "json_schema_extra": { diff --git a/tests/test_dependency_contextvars.py b/tests/test_dependency_contextvars.py index 0c2e5594b6..eba135785b 100644 --- a/tests/test_dependency_contextvars.py +++ b/tests/test_dependency_contextvars.py @@ -1,11 +1,11 @@ -from collections.abc import Awaitable +from collections.abc import Awaitable, Callable from contextvars import ContextVar -from typing import Any, Callable, Optional +from typing import Any from fastapi import Depends, FastAPI, Request, Response from fastapi.testclient import TestClient -legacy_request_state_context_var: ContextVar[Optional[dict[str, Any]]] = ContextVar( +legacy_request_state_context_var: ContextVar[dict[str, Any] | None] = ContextVar( "legacy_request_state_context_var", default=None ) diff --git a/tests/test_dependency_overrides.py b/tests/test_dependency_overrides.py index e25db624d8..7c99d9d9d3 100644 --- a/tests/test_dependency_overrides.py +++ b/tests/test_dependency_overrides.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import APIRouter, Depends, FastAPI from fastapi.testclient import TestClient @@ -38,7 +36,7 @@ app.include_router(router) client = TestClient(app) -async def overrider_dependency_simple(q: Optional[str] = None): +async def overrider_dependency_simple(q: str | None = None): return {"q": q, "skip": 5, "limit": 10} diff --git a/tests/test_dependency_paramless.py b/tests/test_dependency_paramless.py index 1774196fe4..62c977b825 100644 --- a/tests/test_dependency_paramless.py +++ b/tests/test_dependency_paramless.py @@ -1,4 +1,4 @@ -from typing import Annotated, Union +from typing import Annotated from fastapi import FastAPI, HTTPException, Security from fastapi.security import ( @@ -13,7 +13,7 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") def process_auth( - credentials: Annotated[Union[str, None], Security(oauth2_scheme)], + credentials: Annotated[str | None, Security(oauth2_scheme)], security_scopes: SecurityScopes, ): # This is an incorrect way of using it, this is not checking if the scopes are diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index 0dee15c25d..9f8a964543 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Depends, FastAPI, Query from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -11,7 +9,7 @@ def _get_client_key(client_id: str = Query(...)) -> str: return f"{client_id}_key" -def _get_client_tag(client_id: Optional[str] = Query(None)) -> Optional[str]: +def _get_client_tag(client_id: str | None = Query(None)) -> str | None: if client_id is None: return None return f"{client_id}_tag" @@ -20,7 +18,7 @@ def _get_client_tag(client_id: Optional[str] = Query(None)) -> Optional[str]: @app.get("/foo") def foo_handler( client_key: str = Depends(_get_client_key), - client_tag: Optional[str] = Depends(_get_client_tag), + client_tag: str | None = Depends(_get_client_tag), ): return {"client_id": client_key, "client_tag": client_tag} diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index 96f85b4465..985adb9439 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.responses import JSONResponse from fastapi.testclient import TestClient @@ -11,7 +9,7 @@ app = FastAPI() class Item(BaseModel): name: str - price: Optional[float] = None + price: float | None = None @app.api_route("/items/{item_id}", methods=["GET"]) diff --git a/tests/test_filter_pydantic_sub_model_pv2.py b/tests/test_filter_pydantic_sub_model_pv2.py index 1de2b50f7f..1f39581c23 100644 --- a/tests/test_filter_pydantic_sub_model_pv2.py +++ b/tests/test_filter_pydantic_sub_model_pv2.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from dirty_equals import HasRepr from fastapi import Depends, FastAPI @@ -22,7 +20,7 @@ def get_client(): class ModelA(BaseModel): name: str - description: Optional[str] = None + description: str | None = None foo: ModelB tags: dict[str, str] = {} diff --git a/tests/test_form_default.py b/tests/test_form_default.py index 0b3eb8f2e2..c4d33e3fb6 100644 --- a/tests/test_form_default.py +++ b/tests/test_form_default.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated from fastapi import FastAPI, File, Form from starlette.testclient import TestClient @@ -7,14 +7,14 @@ app = FastAPI() @app.post("/urlencoded") -async def post_url_encoded(age: Annotated[Optional[int], Form()] = None): +async def post_url_encoded(age: Annotated[int | None, Form()] = None): return age @app.post("/multipart") async def post_multi_part( - age: Annotated[Optional[int], Form()] = None, - file: Annotated[Optional[bytes], File()] = None, + age: Annotated[int | None, Form()] = None, + file: Annotated[bytes | None, File()] = None, ): return {"file": file, "age": age} diff --git a/tests/test_forms_single_model.py b/tests/test_forms_single_model.py index 7d03d29572..4575e3335e 100644 --- a/tests/test_forms_single_model.py +++ b/tests/test_forms_single_model.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated from fastapi import FastAPI, Form from fastapi.testclient import TestClient @@ -10,7 +10,7 @@ app = FastAPI() class FormModel(BaseModel): username: str lastname: str - age: Optional[int] = None + age: int | None = None tags: list[str] = ["foo", "bar"] alias_with: str = Field(alias="with", default="nothing") diff --git a/tests/test_infer_param_optionality.py b/tests/test_infer_param_optionality.py index bb20a4a1aa..2cf74e187a 100644 --- a/tests/test_infer_param_optionality.py +++ b/tests/test_infer_param_optionality.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -22,7 +20,7 @@ def get_user(user_id: str): @item_router.get("/") -def get_items(user_id: Optional[str] = None): +def get_items(user_id: str | None = None): if user_id is None: return [{"item_id": "i1", "user_id": "u1"}, {"item_id": "i2", "user_id": "u2"}] else: @@ -30,7 +28,7 @@ def get_items(user_id: Optional[str] = None): @item_router.get("/{item_id}") -def get_item(item_id: str, user_id: Optional[str] = None): +def get_item(item_id: str, user_id: str | None = None): if user_id is None: return {"item_id": item_id} else: diff --git a/tests/test_invalid_sequence_param.py b/tests/test_invalid_sequence_param.py index 3695344f7a..d137f6805e 100644 --- a/tests/test_invalid_sequence_param.py +++ b/tests/test_invalid_sequence_param.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import FastAPI, Query from pydantic import BaseModel @@ -61,5 +59,5 @@ def test_invalid_simple_dict(): title: str @app.get("/items/") - def read_items(q: Optional[dict] = Query(default=None)): + def read_items(q: dict | None = Query(default=None)): pass # pragma: no cover diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index 4528dff440..595202beaf 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -6,7 +6,7 @@ from decimal import Decimal from enum import Enum from math import isinf, isnan from pathlib import PurePath, PurePosixPath, PureWindowsPath -from typing import Optional, TypedDict +from typing import TypedDict import pytest from fastapi._compat import Undefined @@ -57,7 +57,7 @@ class RoleEnum(Enum): class ModelWithConfig(BaseModel): - role: Optional[RoleEnum] = None + role: RoleEnum | None = None model_config = {"use_enum_values": True} diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index deb74d8a0f..e27dd2be08 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -57,7 +55,7 @@ def path_examples( @app.get("/query_examples/") def query_examples( - data: Union[str, None] = Query( + data: str | None = Query( default=None, examples=[ "json_schema_query1", @@ -80,7 +78,7 @@ def query_examples( @app.get("/header_examples/") def header_examples( - data: Union[str, None] = Header( + data: str | None = Header( default=None, examples=[ "json_schema_header1", @@ -103,7 +101,7 @@ def header_examples( @app.get("/cookie_examples/") def cookie_examples( - data: Union[str, None] = Cookie( + data: str | None = Cookie( default=None, examples=["json_schema_cookie1", "json_schema_cookie2"], openapi_examples={ diff --git a/tests/test_openapi_query_parameter_extension.py b/tests/test_openapi_query_parameter_extension.py index 836a0a7ee5..118d518149 100644 --- a/tests/test_openapi_query_parameter_extension.py +++ b/tests/test_openapi_query_parameter_extension.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -26,7 +24,7 @@ app = FastAPI() ] }, ) -def route_with_extra_query_parameters(standard_query_param: Optional[int] = 50): +def route_with_extra_query_parameters(standard_query_param: int | None = 50): return {} diff --git a/tests/test_openapi_schema_type.py b/tests/test_openapi_schema_type.py index 98d9787455..e8166d2fb9 100644 --- a/tests/test_openapi_schema_type.py +++ b/tests/test_openapi_schema_type.py @@ -1,5 +1,3 @@ -from typing import Optional, Union - import pytest from fastapi.openapi.models import Schema, SchemaType @@ -13,7 +11,7 @@ from fastapi.openapi.models import Schema, SchemaType ], ) def test_allowed_schema_type( - type_value: Optional[Union[SchemaType, list[SchemaType]]], + type_value: SchemaType | list[SchemaType] | None, ) -> None: """Test that Schema accepts SchemaType, List[SchemaType] and None for type field.""" schema = Schema(type=type_value) diff --git a/tests/test_openapi_separate_input_output_schemas.py b/tests/test_openapi_separate_input_output_schemas.py index 0efeece017..50255ed09a 100644 --- a/tests/test_openapi_separate_input_output_schemas.py +++ b/tests/test_openapi_separate_input_output_schemas.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -8,15 +6,15 @@ from pydantic import BaseModel, computed_field class SubItem(BaseModel): subname: str - sub_description: Optional[str] = None + sub_description: str | None = None tags: list[str] = [] model_config = {"json_schema_serialization_defaults_required": True} class Item(BaseModel): name: str - description: Optional[str] = None - sub: Optional[SubItem] = None + description: str | None = None + sub: SubItem | None = None model_config = {"json_schema_serialization_defaults_required": True} diff --git a/tests/test_optional_file_list.py b/tests/test_optional_file_list.py index 6860258643..a57e6358fd 100644 --- a/tests/test_optional_file_list.py +++ b/tests/test_optional_file_list.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, File from fastapi.testclient import TestClient @@ -7,7 +5,7 @@ app = FastAPI() @app.post("/files") -async def upload_files(files: Optional[list[bytes]] = File(None)): +async def upload_files(files: list[bytes] | None = File(None)): if files is None: return {"files_count": 0} return {"files_count": len(files), "sizes": [len(f) for f in files]} diff --git a/tests/test_param_class.py b/tests/test_param_class.py index 1fd40dcd21..e6642daeac 100644 --- a/tests/test_param_class.py +++ b/tests/test_param_class.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.params import Param from fastapi.testclient import TestClient @@ -8,7 +6,7 @@ app = FastAPI() @app.get("/items/") -def read_items(q: Optional[str] = Param(default=None)): # type: ignore +def read_items(q: str | None = Param(default=None)): # type: ignore return {"q": q} diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index 463fb51b10..727552b466 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient @@ -10,14 +8,14 @@ app = FastAPI() @app.get("/hidden_cookie") async def hidden_cookie( - hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False), + hidden_cookie: str | None = Cookie(default=None, include_in_schema=False), ): return {"hidden_cookie": hidden_cookie} @app.get("/hidden_header") async def hidden_header( - hidden_header: Optional[str] = Header(default=None, include_in_schema=False), + hidden_header: str | None = Header(default=None, include_in_schema=False), ): return {"hidden_header": hidden_header} @@ -29,7 +27,7 @@ async def hidden_path(hidden_path: str = Path(include_in_schema=False)): @app.get("/hidden_query") async def hidden_query( - hidden_query: Optional[str] = Query(default=None, include_in_schema=False), + hidden_query: str | None = Query(default=None, include_in_schema=False), ): return {"hidden_query": hidden_query} diff --git a/tests/test_pydantic_v1_error.py b/tests/test_pydantic_v1_error.py index 13229a3137..044fdf0d65 100644 --- a/tests/test_pydantic_v1_error.py +++ b/tests/test_pydantic_v1_error.py @@ -1,6 +1,5 @@ import sys import warnings -from typing import Union import pytest @@ -80,7 +79,7 @@ def test_raises_pydantic_v1_model_in_union() -> None: with pytest.raises(PydanticV1NotSupportedError): @app.post("/union") - def endpoint(data: Union[dict, ModelV1A]): # pragma: no cover + def endpoint(data: dict | ModelV1A): # pragma: no cover return data diff --git a/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py b/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py index b72b0518a1..4f7b0b2a0a 100644 --- a/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py +++ b/tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py @@ -2,7 +2,6 @@ from __future__ import annotations import uuid from dataclasses import dataclass, field -from typing import Union from dirty_equals import IsUUID from fastapi import FastAPI @@ -16,8 +15,8 @@ class Item: name: str price: float tags: list[str] = field(default_factory=list) - description: Union[str, None] = None - tax: Union[float, None] = None + description: str | None = None + tax: float | None = None app = FastAPI() diff --git a/tests/test_request_params/test_body/test_list.py b/tests/test_request_params/test_body/test_list.py index 970e6a6607..aa9745f84f 100644 --- a/tests/test_request_params/test_body/test_list.py +++ b/tests/test_request_params/test_body/test_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Union +from typing import Annotated import pytest from dirty_equals import IsOneOf, IsPartialDict @@ -55,7 +55,7 @@ def test_required_list_str_schema(path: str): "path", ["/required-list-str", "/model-required-list-str"], ) -def test_required_list_str_missing(path: str, json: Union[dict, None]): +def test_required_list_str_missing(path: str, json: dict | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 @@ -132,7 +132,7 @@ def test_required_list_str_alias_schema(path: str): "path", ["/required-list-alias", "/model-required-list-alias"], ) -def test_required_list_alias_missing(path: str, json: Union[dict, None]): +def test_required_list_alias_missing(path: str, json: dict | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 @@ -236,7 +236,7 @@ def test_required_list_validation_alias_schema(path: str): "/model-required-list-validation-alias", ], ) -def test_required_list_validation_alias_missing(path: str, json: Union[dict, None]): +def test_required_list_validation_alias_missing(path: str, json: dict | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 diff --git a/tests/test_request_params/test_body/test_optional_list.py b/tests/test_request_params/test_body/test_optional_list.py index ba8ba9092e..2c5c5d61b6 100644 --- a/tests/test_request_params/test_body/test_optional_list.py +++ b/tests/test_request_params/test_body/test_optional_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import Body, FastAPI @@ -15,13 +15,13 @@ app = FastAPI() @app.post("/optional-list-str", operation_id="optional_list_str") async def read_optional_list_str( - p: Annotated[Optional[list[str]], Body(embed=True)] = None, + p: Annotated[list[str] | None, Body(embed=True)] = None, ): return {"p": p} class BodyModelOptionalListStr(BaseModel): - p: Optional[list[str]] = None + p: list[str] | None = None @app.post("/model-optional-list-str", operation_id="model_optional_list_str") @@ -103,13 +103,13 @@ def test_optional_list_str(path: str): @app.post("/optional-list-alias", operation_id="optional_list_alias") async def read_optional_list_alias( - p: Annotated[Optional[list[str]], Body(embed=True, alias="p_alias")] = None, + p: Annotated[list[str] | None, Body(embed=True, alias="p_alias")] = None, ): return {"p": p} class BodyModelOptionalListAlias(BaseModel): - p: Optional[list[str]] = Field(None, alias="p_alias") + p: list[str] | None = Field(None, alias="p_alias") @app.post("/model-optional-list-alias", operation_id="model_optional_list_alias") @@ -208,14 +208,14 @@ def test_optional_list_alias_by_alias(path: str): ) def read_optional_list_validation_alias( p: Annotated[ - Optional[list[str]], Body(embed=True, validation_alias="p_val_alias") + list[str] | None, Body(embed=True, validation_alias="p_val_alias") ] = None, ): return {"p": p} class BodyModelOptionalListValidationAlias(BaseModel): - p: Optional[list[str]] = Field(None, validation_alias="p_val_alias") + p: list[str] | None = Field(None, validation_alias="p_val_alias") @app.post( @@ -323,7 +323,7 @@ def test_optional_list_validation_alias_by_validation_alias(path: str): ) def read_optional_list_alias_and_validation_alias( p: Annotated[ - Optional[list[str]], + list[str] | None, Body(embed=True, alias="p_alias", validation_alias="p_val_alias"), ] = None, ): @@ -331,9 +331,7 @@ def read_optional_list_alias_and_validation_alias( class BodyModelOptionalListAliasAndValidationAlias(BaseModel): - p: Optional[list[str]] = Field( - None, alias="p_alias", validation_alias="p_val_alias" - ) + p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.post( diff --git a/tests/test_request_params/test_body/test_optional_str.py b/tests/test_request_params/test_body/test_optional_str.py index b9c18034da..184fc94cb2 100644 --- a/tests/test_request_params/test_body/test_optional_str.py +++ b/tests/test_request_params/test_body/test_optional_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import Body, FastAPI @@ -14,12 +14,12 @@ app = FastAPI() @app.post("/optional-str", operation_id="optional_str") -async def read_optional_str(p: Annotated[Optional[str], Body(embed=True)] = None): +async def read_optional_str(p: Annotated[str | None, Body(embed=True)] = None): return {"p": p} class BodyModelOptionalStr(BaseModel): - p: Optional[str] = None + p: str | None = None @app.post("/model-optional-str", operation_id="model_optional_str") @@ -98,13 +98,13 @@ def test_optional_str(path: str): @app.post("/optional-alias", operation_id="optional_alias") async def read_optional_alias( - p: Annotated[Optional[str], Body(embed=True, alias="p_alias")] = None, + p: Annotated[str | None, Body(embed=True, alias="p_alias")] = None, ): return {"p": p} class BodyModelOptionalAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias") + p: str | None = Field(None, alias="p_alias") @app.post("/model-optional-alias", operation_id="model_optional_alias") @@ -197,15 +197,13 @@ def test_optional_alias_by_alias(path: str): @app.post("/optional-validation-alias", operation_id="optional_validation_alias") def read_optional_validation_alias( - p: Annotated[ - Optional[str], Body(embed=True, validation_alias="p_val_alias") - ] = None, + p: Annotated[str | None, Body(embed=True, validation_alias="p_val_alias")] = None, ): return {"p": p} class BodyModelOptionalValidationAlias(BaseModel): - p: Optional[str] = Field(None, validation_alias="p_val_alias") + p: str | None = Field(None, validation_alias="p_val_alias") @app.post( @@ -309,14 +307,14 @@ def test_optional_validation_alias_by_validation_alias(path: str): ) def read_optional_alias_and_validation_alias( p: Annotated[ - Optional[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias") + str | None, Body(embed=True, alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class BodyModelOptionalAliasAndValidationAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias") + p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.post( diff --git a/tests/test_request_params/test_body/test_required_str.py b/tests/test_request_params/test_body/test_required_str.py index 5b434fa1db..2e02f8d203 100644 --- a/tests/test_request_params/test_body/test_required_str.py +++ b/tests/test_request_params/test_body/test_required_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Any, Union +from typing import Annotated, Any import pytest from dirty_equals import IsOneOf @@ -51,7 +51,7 @@ def test_required_str_schema(path: str): "path", ["/required-str", "/model-required-str"], ) -def test_required_str_missing(path: str, json: Union[dict[str, Any], None]): +def test_required_str_missing(path: str, json: dict[str, Any] | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 @@ -124,7 +124,7 @@ def test_required_str_alias_schema(path: str): "path", ["/required-alias", "/model-required-alias"], ) -def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]): +def test_required_alias_missing(path: str, json: dict[str, Any] | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 @@ -221,9 +221,7 @@ def test_required_validation_alias_schema(path: str): "/model-required-validation-alias", ], ) -def test_required_validation_alias_missing( - path: str, json: Union[dict[str, Any], None] -): +def test_required_validation_alias_missing(path: str, json: dict[str, Any] | None): client = TestClient(app) response = client.post(path, json=json) assert response.status_code == 422 @@ -338,7 +336,7 @@ def test_required_alias_and_validation_alias_schema(path: str): ], ) def test_required_alias_and_validation_alias_missing( - path: str, json: Union[dict[str, Any], None] + path: str, json: dict[str, Any] | None ): client = TestClient(app) response = client.post(path, json=json) diff --git a/tests/test_request_params/test_cookie/test_optional_str.py b/tests/test_request_params/test_cookie/test_optional_str.py index 1b2a18b072..227d2bccc2 100644 --- a/tests/test_request_params/test_cookie/test_optional_str.py +++ b/tests/test_request_params/test_cookie/test_optional_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import Cookie, FastAPI @@ -13,12 +13,12 @@ app = FastAPI() @app.get("/optional-str") -async def read_optional_str(p: Annotated[Optional[str], Cookie()] = None): +async def read_optional_str(p: Annotated[str | None, Cookie()] = None): return {"p": p} class CookieModelOptionalStr(BaseModel): - p: Optional[str] = None + p: str | None = None @app.get("/model-optional-str") @@ -75,13 +75,13 @@ def test_optional_str(path: str): @app.get("/optional-alias") async def read_optional_alias( - p: Annotated[Optional[str], Cookie(alias="p_alias")] = None, + p: Annotated[str | None, Cookie(alias="p_alias")] = None, ): return {"p": p} class CookieModelOptionalAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias") + p: str | None = Field(None, alias="p_alias") @app.get("/model-optional-alias") @@ -153,13 +153,13 @@ def test_optional_alias_by_alias(path: str): @app.get("/optional-validation-alias") def read_optional_validation_alias( - p: Annotated[Optional[str], Cookie(validation_alias="p_val_alias")] = None, + p: Annotated[str | None, Cookie(validation_alias="p_val_alias")] = None, ): return {"p": p} class CookieModelOptionalValidationAlias(BaseModel): - p: Optional[str] = Field(None, validation_alias="p_val_alias") + p: str | None = Field(None, validation_alias="p_val_alias") @app.get("/model-optional-validation-alias") @@ -237,14 +237,14 @@ def test_optional_validation_alias_by_validation_alias(path: str): @app.get("/optional-alias-and-validation-alias") def read_optional_alias_and_validation_alias( p: Annotated[ - Optional[str], Cookie(alias="p_alias", validation_alias="p_val_alias") + str | None, Cookie(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class CookieModelOptionalAliasAndValidationAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias") + p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.get("/model-optional-alias-and-validation-alias") diff --git a/tests/test_request_params/test_file/test_optional.py b/tests/test_request_params/test_file/test_optional.py index 45ef7bdec4..b4dc11a06a 100644 --- a/tests/test_request_params/test_file/test_optional.py +++ b/tests/test_request_params/test_file/test_optional.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, File, UploadFile @@ -13,12 +13,12 @@ app = FastAPI() @app.post("/optional-bytes", operation_id="optional_bytes") -async def read_optional_bytes(p: Annotated[Optional[bytes], File()] = None): +async def read_optional_bytes(p: Annotated[bytes | None, File()] = None): return {"file_size": len(p) if p else None} @app.post("/optional-uploadfile", operation_id="optional_uploadfile") -async def read_optional_uploadfile(p: Annotated[Optional[UploadFile], File()] = None): +async def read_optional_uploadfile(p: Annotated[UploadFile | None, File()] = None): return {"file_size": p.size if p else None} @@ -82,14 +82,14 @@ def test_optional(path: str): @app.post("/optional-bytes-alias", operation_id="optional_bytes_alias") async def read_optional_bytes_alias( - p: Annotated[Optional[bytes], File(alias="p_alias")] = None, + p: Annotated[bytes | None, File(alias="p_alias")] = None, ): return {"file_size": len(p) if p else None} @app.post("/optional-uploadfile-alias", operation_id="optional_uploadfile_alias") async def read_optional_uploadfile_alias( - p: Annotated[Optional[UploadFile], File(alias="p_alias")] = None, + p: Annotated[UploadFile | None, File(alias="p_alias")] = None, ): return {"file_size": p.size if p else None} @@ -170,7 +170,7 @@ def test_optional_alias_by_alias(path: str): "/optional-bytes-validation-alias", operation_id="optional_bytes_validation_alias" ) def read_optional_bytes_validation_alias( - p: Annotated[Optional[bytes], File(validation_alias="p_val_alias")] = None, + p: Annotated[bytes | None, File(validation_alias="p_val_alias")] = None, ): return {"file_size": len(p) if p else None} @@ -180,7 +180,7 @@ def read_optional_bytes_validation_alias( operation_id="optional_uploadfile_validation_alias", ) def read_optional_uploadfile_validation_alias( - p: Annotated[Optional[UploadFile], File(validation_alias="p_val_alias")] = None, + p: Annotated[UploadFile | None, File(validation_alias="p_val_alias")] = None, ): return {"file_size": p.size if p else None} @@ -263,7 +263,7 @@ def test_optional_validation_alias_by_validation_alias(path: str): ) def read_optional_bytes_alias_and_validation_alias( p: Annotated[ - Optional[bytes], File(alias="p_alias", validation_alias="p_val_alias") + bytes | None, File(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"file_size": len(p) if p else None} @@ -275,7 +275,7 @@ def read_optional_bytes_alias_and_validation_alias( ) def read_optional_uploadfile_alias_and_validation_alias( p: Annotated[ - Optional[UploadFile], File(alias="p_alias", validation_alias="p_val_alias") + UploadFile | None, File(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"file_size": p.size if p else None} diff --git a/tests/test_request_params/test_file/test_optional_list.py b/tests/test_request_params/test_file/test_optional_list.py index 162fbe08ae..a506ec991f 100644 --- a/tests/test_request_params/test_file/test_optional_list.py +++ b/tests/test_request_params/test_file/test_optional_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, File, UploadFile @@ -13,13 +13,13 @@ app = FastAPI() @app.post("/optional-list-bytes") -async def read_optional_list_bytes(p: Annotated[Optional[list[bytes]], File()] = None): +async def read_optional_list_bytes(p: Annotated[list[bytes] | None, File()] = None): return {"file_size": [len(file) for file in p] if p else None} @app.post("/optional-list-uploadfile") async def read_optional_list_uploadfile( - p: Annotated[Optional[list[UploadFile]], File()] = None, + p: Annotated[list[UploadFile] | None, File()] = None, ): return {"file_size": [file.size for file in p] if p else None} @@ -87,14 +87,14 @@ def test_optional_list(path: str): @app.post("/optional-list-bytes-alias") async def read_optional_list_bytes_alias( - p: Annotated[Optional[list[bytes]], File(alias="p_alias")] = None, + p: Annotated[list[bytes] | None, File(alias="p_alias")] = None, ): return {"file_size": [len(file) for file in p] if p else None} @app.post("/optional-list-uploadfile-alias") async def read_optional_list_uploadfile_alias( - p: Annotated[Optional[list[UploadFile]], File(alias="p_alias")] = None, + p: Annotated[list[UploadFile] | None, File(alias="p_alias")] = None, ): return {"file_size": [file.size for file in p] if p else None} @@ -176,16 +176,14 @@ def test_optional_list_alias_by_alias(path: str): @app.post("/optional-list-bytes-validation-alias") def read_optional_list_bytes_validation_alias( - p: Annotated[Optional[list[bytes]], File(validation_alias="p_val_alias")] = None, + p: Annotated[list[bytes] | None, File(validation_alias="p_val_alias")] = None, ): return {"file_size": [len(file) for file in p] if p else None} @app.post("/optional-list-uploadfile-validation-alias") def read_optional_list_uploadfile_validation_alias( - p: Annotated[ - Optional[list[UploadFile]], File(validation_alias="p_val_alias") - ] = None, + p: Annotated[list[UploadFile] | None, File(validation_alias="p_val_alias")] = None, ): return {"file_size": [file.size for file in p] if p else None} @@ -270,7 +268,7 @@ def test_optional_validation_alias_by_validation_alias(path: str): @app.post("/optional-list-bytes-alias-and-validation-alias") def read_optional_list_bytes_alias_and_validation_alias( p: Annotated[ - Optional[list[bytes]], File(alias="p_alias", validation_alias="p_val_alias") + list[bytes] | None, File(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"file_size": [len(file) for file in p] if p else None} @@ -279,7 +277,7 @@ def read_optional_list_bytes_alias_and_validation_alias( @app.post("/optional-list-uploadfile-alias-and-validation-alias") def read_optional_list_uploadfile_alias_and_validation_alias( p: Annotated[ - Optional[list[UploadFile]], + list[UploadFile] | None, File(alias="p_alias", validation_alias="p_val_alias"), ] = None, ): diff --git a/tests/test_request_params/test_form/test_optional_list.py b/tests/test_request_params/test_form/test_optional_list.py index 6d1957a18c..7ecf9c9bfc 100644 --- a/tests/test_request_params/test_form/test_optional_list.py +++ b/tests/test_request_params/test_form/test_optional_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Form @@ -15,13 +15,13 @@ app = FastAPI() @app.post("/optional-list-str", operation_id="optional_list_str") async def read_optional_list_str( - p: Annotated[Optional[list[str]], Form()] = None, + p: Annotated[list[str] | None, Form()] = None, ): return {"p": p} class FormModelOptionalListStr(BaseModel): - p: Optional[list[str]] = None + p: list[str] | None = None @app.post("/model-optional-list-str", operation_id="model_optional_list_str") @@ -80,13 +80,13 @@ def test_optional_list_str(path: str): @app.post("/optional-list-alias", operation_id="optional_list_alias") async def read_optional_list_alias( - p: Annotated[Optional[list[str]], Form(alias="p_alias")] = None, + p: Annotated[list[str] | None, Form(alias="p_alias")] = None, ): return {"p": p} class FormModelOptionalListAlias(BaseModel): - p: Optional[list[str]] = Field(None, alias="p_alias") + p: list[str] | None = Field(None, alias="p_alias") @app.post("/model-optional-list-alias", operation_id="model_optional_list_alias") @@ -163,13 +163,13 @@ def test_optional_list_alias_by_alias(path: str): "/optional-list-validation-alias", operation_id="optional_list_validation_alias" ) def read_optional_list_validation_alias( - p: Annotated[Optional[list[str]], Form(validation_alias="p_val_alias")] = None, + p: Annotated[list[str] | None, Form(validation_alias="p_val_alias")] = None, ): return {"p": p} class FormModelOptionalListValidationAlias(BaseModel): - p: Optional[list[str]] = Field(None, validation_alias="p_val_alias") + p: list[str] | None = Field(None, validation_alias="p_val_alias") @app.post( @@ -251,16 +251,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str): ) def read_optional_list_alias_and_validation_alias( p: Annotated[ - Optional[list[str]], Form(alias="p_alias", validation_alias="p_val_alias") + list[str] | None, Form(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class FormModelOptionalListAliasAndValidationAlias(BaseModel): - p: Optional[list[str]] = Field( - None, alias="p_alias", validation_alias="p_val_alias" - ) + p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.post( diff --git a/tests/test_request_params/test_form/test_optional_str.py b/tests/test_request_params/test_form/test_optional_str.py index 810e83caa3..4ef16756ef 100644 --- a/tests/test_request_params/test_form/test_optional_str.py +++ b/tests/test_request_params/test_form/test_optional_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Form @@ -14,12 +14,12 @@ app = FastAPI() @app.post("/optional-str", operation_id="optional_str") -async def read_optional_str(p: Annotated[Optional[str], Form()] = None): +async def read_optional_str(p: Annotated[str | None, Form()] = None): return {"p": p} class FormModelOptionalStr(BaseModel): - p: Optional[str] = None + p: str | None = None @app.post("/model-optional-str", operation_id="model_optional_str") @@ -75,13 +75,13 @@ def test_optional_str(path: str): @app.post("/optional-alias", operation_id="optional_alias") async def read_optional_alias( - p: Annotated[Optional[str], Form(alias="p_alias")] = None, + p: Annotated[str | None, Form(alias="p_alias")] = None, ): return {"p": p} class FormModelOptionalAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias") + p: str | None = Field(None, alias="p_alias") @app.post("/model-optional-alias", operation_id="model_optional_alias") @@ -151,13 +151,13 @@ def test_optional_alias_by_alias(path: str): @app.post("/optional-validation-alias", operation_id="optional_validation_alias") def read_optional_validation_alias( - p: Annotated[Optional[str], Form(validation_alias="p_val_alias")] = None, + p: Annotated[str | None, Form(validation_alias="p_val_alias")] = None, ): return {"p": p} class FormModelOptionalValidationAlias(BaseModel): - p: Optional[str] = Field(None, validation_alias="p_val_alias") + p: str | None = Field(None, validation_alias="p_val_alias") @app.post( @@ -238,14 +238,14 @@ def test_optional_validation_alias_by_validation_alias(path: str): ) def read_optional_alias_and_validation_alias( p: Annotated[ - Optional[str], Form(alias="p_alias", validation_alias="p_val_alias") + str | None, Form(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class FormModelOptionalAliasAndValidationAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias") + p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.post( diff --git a/tests/test_request_params/test_header/test_optional_list.py b/tests/test_request_params/test_header/test_optional_list.py index 3bbb73d544..9f4eacc235 100644 --- a/tests/test_request_params/test_header/test_optional_list.py +++ b/tests/test_request_params/test_header/test_optional_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Header @@ -14,13 +14,13 @@ app = FastAPI() @app.get("/optional-list-str") async def read_optional_list_str( - p: Annotated[Optional[list[str]], Header()] = None, + p: Annotated[list[str] | None, Header()] = None, ): return {"p": p} class HeaderModelOptionalListStr(BaseModel): - p: Optional[list[str]] = None + p: list[str] | None = None @app.get("/model-optional-list-str") @@ -81,13 +81,13 @@ def test_optional_list_str(path: str): @app.get("/optional-list-alias") async def read_optional_list_alias( - p: Annotated[Optional[list[str]], Header(alias="p_alias")] = None, + p: Annotated[list[str] | None, Header(alias="p_alias")] = None, ): return {"p": p} class HeaderModelOptionalListAlias(BaseModel): - p: Optional[list[str]] = Field(None, alias="p_alias") + p: list[str] | None = Field(None, alias="p_alias") @app.get("/model-optional-list-alias") @@ -162,13 +162,13 @@ def test_optional_list_alias_by_alias(path: str): @app.get("/optional-list-validation-alias") def read_optional_list_validation_alias( - p: Annotated[Optional[list[str]], Header(validation_alias="p_val_alias")] = None, + p: Annotated[list[str] | None, Header(validation_alias="p_val_alias")] = None, ): return {"p": p} class HeaderModelOptionalListValidationAlias(BaseModel): - p: Optional[list[str]] = Field(None, validation_alias="p_val_alias") + p: list[str] | None = Field(None, validation_alias="p_val_alias") @app.get("/model-optional-list-validation-alias") @@ -246,16 +246,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str): @app.get("/optional-list-alias-and-validation-alias") def read_optional_list_alias_and_validation_alias( p: Annotated[ - Optional[list[str]], Header(alias="p_alias", validation_alias="p_val_alias") + list[str] | None, Header(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class HeaderModelOptionalListAliasAndValidationAlias(BaseModel): - p: Optional[list[str]] = Field( - None, alias="p_alias", validation_alias="p_val_alias" - ) + p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.get("/model-optional-list-alias-and-validation-alias") diff --git a/tests/test_request_params/test_header/test_optional_str.py b/tests/test_request_params/test_header/test_optional_str.py index a5174e59af..04773c83f9 100644 --- a/tests/test_request_params/test_header/test_optional_str.py +++ b/tests/test_request_params/test_header/test_optional_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Header @@ -13,12 +13,12 @@ app = FastAPI() @app.get("/optional-str") -async def read_optional_str(p: Annotated[Optional[str], Header()] = None): +async def read_optional_str(p: Annotated[str | None, Header()] = None): return {"p": p} class HeaderModelOptionalStr(BaseModel): - p: Optional[str] = None + p: str | None = None @app.get("/model-optional-str") @@ -74,13 +74,13 @@ def test_optional_str(path: str): @app.get("/optional-alias") async def read_optional_alias( - p: Annotated[Optional[str], Header(alias="p_alias")] = None, + p: Annotated[str | None, Header(alias="p_alias")] = None, ): return {"p": p} class HeaderModelOptionalAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias") + p: str | None = Field(None, alias="p_alias") @app.get("/model-optional-alias") @@ -150,13 +150,13 @@ def test_optional_alias_by_alias(path: str): @app.get("/optional-validation-alias") def read_optional_validation_alias( - p: Annotated[Optional[str], Header(validation_alias="p_val_alias")] = None, + p: Annotated[str | None, Header(validation_alias="p_val_alias")] = None, ): return {"p": p} class HeaderModelOptionalValidationAlias(BaseModel): - p: Optional[str] = Field(None, validation_alias="p_val_alias") + p: str | None = Field(None, validation_alias="p_val_alias") @app.get("/model-optional-validation-alias") @@ -232,14 +232,14 @@ def test_optional_validation_alias_by_validation_alias(path: str): @app.get("/optional-alias-and-validation-alias") def read_optional_alias_and_validation_alias( p: Annotated[ - Optional[str], Header(alias="p_alias", validation_alias="p_val_alias") + str | None, Header(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class HeaderModelOptionalAliasAndValidationAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias") + p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.get("/model-optional-alias-and-validation-alias") diff --git a/tests/test_request_params/test_query/test_optional_list.py b/tests/test_request_params/test_query/test_optional_list.py index 5608c6499b..6b70b75a4f 100644 --- a/tests/test_request_params/test_query/test_optional_list.py +++ b/tests/test_request_params/test_query/test_optional_list.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Query @@ -14,13 +14,13 @@ app = FastAPI() @app.get("/optional-list-str") async def read_optional_list_str( - p: Annotated[Optional[list[str]], Query()] = None, + p: Annotated[list[str] | None, Query()] = None, ): return {"p": p} class QueryModelOptionalListStr(BaseModel): - p: Optional[list[str]] = None + p: list[str] | None = None @app.get("/model-optional-list-str") @@ -81,13 +81,13 @@ def test_optional_list_str(path: str): @app.get("/optional-list-alias") async def read_optional_list_alias( - p: Annotated[Optional[list[str]], Query(alias="p_alias")] = None, + p: Annotated[list[str] | None, Query(alias="p_alias")] = None, ): return {"p": p} class QueryModelOptionalListAlias(BaseModel): - p: Optional[list[str]] = Field(None, alias="p_alias") + p: list[str] | None = Field(None, alias="p_alias") @app.get("/model-optional-list-alias") @@ -162,13 +162,13 @@ def test_optional_list_alias_by_alias(path: str): @app.get("/optional-list-validation-alias") def read_optional_list_validation_alias( - p: Annotated[Optional[list[str]], Query(validation_alias="p_val_alias")] = None, + p: Annotated[list[str] | None, Query(validation_alias="p_val_alias")] = None, ): return {"p": p} class QueryModelOptionalListValidationAlias(BaseModel): - p: Optional[list[str]] = Field(None, validation_alias="p_val_alias") + p: list[str] | None = Field(None, validation_alias="p_val_alias") @app.get("/model-optional-list-validation-alias") @@ -244,16 +244,14 @@ def test_optional_list_validation_alias_by_validation_alias(path: str): @app.get("/optional-list-alias-and-validation-alias") def read_optional_list_alias_and_validation_alias( p: Annotated[ - Optional[list[str]], Query(alias="p_alias", validation_alias="p_val_alias") + list[str] | None, Query(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class QueryModelOptionalListAliasAndValidationAlias(BaseModel): - p: Optional[list[str]] = Field( - None, alias="p_alias", validation_alias="p_val_alias" - ) + p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.get("/model-optional-list-alias-and-validation-alias") diff --git a/tests/test_request_params/test_query/test_optional_str.py b/tests/test_request_params/test_query/test_optional_str.py index b181686b05..f7f35860b6 100644 --- a/tests/test_request_params/test_query/test_optional_str.py +++ b/tests/test_request_params/test_query/test_optional_str.py @@ -1,4 +1,4 @@ -from typing import Annotated, Optional +from typing import Annotated import pytest from fastapi import FastAPI, Query @@ -13,12 +13,12 @@ app = FastAPI() @app.get("/optional-str") -async def read_optional_str(p: Optional[str] = None): +async def read_optional_str(p: str | None = None): return {"p": p} class QueryModelOptionalStr(BaseModel): - p: Optional[str] = None + p: str | None = None @app.get("/model-optional-str") @@ -74,13 +74,13 @@ def test_optional_str(path: str): @app.get("/optional-alias") async def read_optional_alias( - p: Annotated[Optional[str], Query(alias="p_alias")] = None, + p: Annotated[str | None, Query(alias="p_alias")] = None, ): return {"p": p} class QueryModelOptionalAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias") + p: str | None = Field(None, alias="p_alias") @app.get("/model-optional-alias") @@ -150,13 +150,13 @@ def test_optional_alias_by_alias(path: str): @app.get("/optional-validation-alias") def read_optional_validation_alias( - p: Annotated[Optional[str], Query(validation_alias="p_val_alias")] = None, + p: Annotated[str | None, Query(validation_alias="p_val_alias")] = None, ): return {"p": p} class QueryModelOptionalValidationAlias(BaseModel): - p: Optional[str] = Field(None, validation_alias="p_val_alias") + p: str | None = Field(None, validation_alias="p_val_alias") @app.get("/model-optional-validation-alias") @@ -232,14 +232,14 @@ def test_optional_validation_alias_by_validation_alias(path: str): @app.get("/optional-alias-and-validation-alias") def read_optional_alias_and_validation_alias( p: Annotated[ - Optional[str], Query(alias="p_alias", validation_alias="p_val_alias") + str | None, Query(alias="p_alias", validation_alias="p_val_alias") ] = None, ): return {"p": p} class QueryModelOptionalAliasAndValidationAlias(BaseModel): - p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias") + p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") @app.get("/model-optional-alias-and-validation-alias") diff --git a/tests/test_required_noneable.py b/tests/test_required_noneable.py index 5da8cd4d09..c99f20212f 100644 --- a/tests/test_required_noneable.py +++ b/tests/test_required_noneable.py @@ -1,5 +1,3 @@ -from typing import Union - from fastapi import Body, FastAPI, Query from fastapi.testclient import TestClient @@ -7,17 +5,17 @@ app = FastAPI() @app.get("/query") -def read_query(q: Union[str, None]): +def read_query(q: str | None): return q @app.get("/explicit-query") -def read_explicit_query(q: Union[str, None] = Query()): +def read_explicit_query(q: str | None = Query()): return q @app.post("/body-embed") -def send_body_embed(b: Union[str, None] = Body(embed=True)): +def send_body_embed(b: str | None = Body(embed=True)): return b diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index ded5971027..7be7902ada 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -1,5 +1,3 @@ -from typing import Union - import pytest from fastapi import FastAPI from fastapi.exceptions import FastAPIError, ResponseValidationError @@ -216,7 +214,7 @@ def no_response_model_annotation_forward_ref_list_of_model() -> "list[User]": @app.get( "/response_model_union-no_annotation-return_model1", - response_model=Union[User, Item], + response_model=User | Item, ) def response_model_union_no_annotation_return_model1(): return DBUser(name="John", surname="Doe", password_hash="secret") @@ -224,19 +222,19 @@ def response_model_union_no_annotation_return_model1(): @app.get( "/response_model_union-no_annotation-return_model2", - response_model=Union[User, Item], + response_model=User | Item, ) def response_model_union_no_annotation_return_model2(): return Item(name="Foo", price=42.0) @app.get("/no_response_model-annotation_union-return_model1") -def no_response_model_annotation_union_return_model1() -> Union[User, Item]: +def no_response_model_annotation_union_return_model1() -> User | Item: return DBUser(name="John", surname="Doe", password_hash="secret") @app.get("/no_response_model-annotation_union-return_model2") -def no_response_model_annotation_union_return_model2() -> Union[User, Item]: +def no_response_model_annotation_union_return_model2() -> User | Item: return Item(name="Foo", price=42.0) @@ -503,7 +501,7 @@ def test_invalid_response_model_field(): with pytest.raises(FastAPIError) as e: @app.get("/") - def read_root() -> Union[Response, None]: + def read_root() -> Response | None: return Response(content="Foo") # pragma: no cover assert "valid Pydantic field type" in e.value.args[0] diff --git a/tests/test_router_events.py b/tests/test_router_events.py index a47d119139..7869a7afcd 100644 --- a/tests/test_router_events.py +++ b/tests/test_router_events.py @@ -1,6 +1,5 @@ from collections.abc import AsyncGenerator from contextlib import asynccontextmanager -from typing import Union import pytest from fastapi import APIRouter, FastAPI, Request @@ -176,7 +175,7 @@ def test_router_nested_lifespan_state_overriding_by_parent() -> None: @asynccontextmanager async def lifespan( app: FastAPI, - ) -> AsyncGenerator[dict[str, Union[str, bool]], None]: + ) -> AsyncGenerator[dict[str, str | bool], None]: yield { "app_specific": True, "overridden": "app", @@ -185,7 +184,7 @@ def test_router_nested_lifespan_state_overriding_by_parent() -> None: @asynccontextmanager async def router_lifespan( app: FastAPI, - ) -> AsyncGenerator[dict[str, Union[str, bool]], None]: + ) -> AsyncGenerator[dict[str, str | bool], None]: yield { "router_specific": True, "overridden": "router", # should override parent diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py index 9ec41e7e84..32f5cea476 100644 --- a/tests/test_schema_extra_examples.py +++ b/tests/test_schema_extra_examples.py @@ -1,5 +1,3 @@ -from typing import Union - import pytest from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.exceptions import FastAPIDeprecationWarning @@ -117,7 +115,7 @@ def create_app(): @app.get("/query_example/") def query_example( - data: Union[str, None] = Query( + data: str | None = Query( default=None, example="query1", ), @@ -126,7 +124,7 @@ def create_app(): @app.get("/query_examples/") def query_examples( - data: Union[str, None] = Query( + data: str | None = Query( default=None, examples=["query1", "query2"], ), @@ -137,7 +135,7 @@ def create_app(): @app.get("/query_example_examples/") def query_example_examples( - data: Union[str, None] = Query( + data: str | None = Query( default=None, example="query_overridden", examples=["query1", "query2"], @@ -149,7 +147,7 @@ def create_app(): @app.get("/header_example/") def header_example( - data: Union[str, None] = Header( + data: str | None = Header( default=None, example="header1", ), @@ -158,7 +156,7 @@ def create_app(): @app.get("/header_examples/") def header_examples( - data: Union[str, None] = Header( + data: str | None = Header( default=None, examples=[ "header1", @@ -172,7 +170,7 @@ def create_app(): @app.get("/header_example_examples/") def header_example_examples( - data: Union[str, None] = Header( + data: str | None = Header( default=None, example="header_overridden", examples=["header1", "header2"], @@ -184,7 +182,7 @@ def create_app(): @app.get("/cookie_example/") def cookie_example( - data: Union[str, None] = Cookie( + data: str | None = Cookie( default=None, example="cookie1", ), @@ -193,7 +191,7 @@ def create_app(): @app.get("/cookie_examples/") def cookie_examples( - data: Union[str, None] = Cookie( + data: str | None = Cookie( default=None, examples=["cookie1", "cookie2"], ), @@ -204,7 +202,7 @@ def create_app(): @app.get("/cookie_example_examples/") def cookie_example_examples( - data: Union[str, None] = Cookie( + data: str | None = Cookie( default=None, example="cookie_overridden", examples=["cookie1", "cookie2"], diff --git a/tests/test_security_api_key_cookie_optional.py b/tests/test_security_api_key_cookie_optional.py index 7988d80443..e911654fac 100644 --- a/tests/test_security_api_key_cookie_optional.py +++ b/tests/test_security_api_key_cookie_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyCookie from fastapi.testclient import TestClient @@ -15,7 +13,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(api_key)): +def get_current_user(oauth_header: str | None = Security(api_key)): if oauth_header is None: return None user = User(username=oauth_header) diff --git a/tests/test_security_api_key_header_optional.py b/tests/test_security_api_key_header_optional.py index 51abd0bb96..0a8cf420ed 100644 --- a/tests/test_security_api_key_header_optional.py +++ b/tests/test_security_api_key_header_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyHeader from fastapi.testclient import TestClient @@ -15,7 +13,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(api_key)): +def get_current_user(oauth_header: str | None = Security(api_key)): if oauth_header is None: return None user = User(username=oauth_header) @@ -23,7 +21,7 @@ def get_current_user(oauth_header: Optional[str] = Security(api_key)): @app.get("/users/me") -def read_current_user(current_user: Optional[User] = Depends(get_current_user)): +def read_current_user(current_user: User | None = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user diff --git a/tests/test_security_api_key_query_optional.py b/tests/test_security_api_key_query_optional.py index 26fbb9ee4f..e9fba30435 100644 --- a/tests/test_security_api_key_query_optional.py +++ b/tests/test_security_api_key_query_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Depends, FastAPI, Security from fastapi.security import APIKeyQuery from fastapi.testclient import TestClient @@ -15,7 +13,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(api_key)): +def get_current_user(oauth_header: str | None = Security(api_key)): if oauth_header is None: return None user = User(username=oauth_header) @@ -23,7 +21,7 @@ def get_current_user(oauth_header: Optional[str] = Security(api_key)): @app.get("/users/me") -def read_current_user(current_user: Optional[User] = Depends(get_current_user)): +def read_current_user(current_user: User | None = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user diff --git a/tests/test_security_http_base_optional.py b/tests/test_security_http_base_optional.py index 612a7909fe..1d1944ab0a 100644 --- a/tests/test_security_http_base_optional.py +++ b/tests/test_security_http_base_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase from fastapi.testclient import TestClient @@ -12,7 +10,7 @@ security = HTTPBase(scheme="Other", auto_error=False) @app.get("/users/me") def read_current_user( - credentials: Optional[HTTPAuthorizationCredentials] = Security(security), + credentials: HTTPAuthorizationCredentials | None = Security(security), ): if credentials is None: return {"msg": "Create an account first"} diff --git a/tests/test_security_http_basic_optional.py b/tests/test_security_http_basic_optional.py index e94565c7bb..78abf2b680 100644 --- a/tests/test_security_http_basic_optional.py +++ b/tests/test_security_http_basic_optional.py @@ -1,5 +1,4 @@ from base64 import b64encode -from typing import Optional from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials @@ -12,7 +11,7 @@ security = HTTPBasic(auto_error=False) @app.get("/users/me") -def read_current_user(credentials: Optional[HTTPBasicCredentials] = Security(security)): +def read_current_user(credentials: HTTPBasicCredentials | None = Security(security)): if credentials is None: return {"msg": "Create an account first"} return {"username": credentials.username, "password": credentials.password} diff --git a/tests/test_security_http_bearer_optional.py b/tests/test_security_http_bearer_optional.py index b49a6593ec..06d9d03db4 100644 --- a/tests/test_security_http_bearer_optional.py +++ b/tests/test_security_http_bearer_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.testclient import TestClient @@ -12,7 +10,7 @@ security = HTTPBearer(auto_error=False) @app.get("/users/me") def read_current_user( - credentials: Optional[HTTPAuthorizationCredentials] = Security(security), + credentials: HTTPAuthorizationCredentials | None = Security(security), ): if credentials is None: return {"msg": "Create an account first"} diff --git a/tests/test_security_http_digest_optional.py b/tests/test_security_http_digest_optional.py index 97e62634d8..d1056b1918 100644 --- a/tests/test_security_http_digest_optional.py +++ b/tests/test_security_http_digest_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest from fastapi.testclient import TestClient @@ -12,7 +10,7 @@ security = HTTPDigest(auto_error=False) @app.get("/users/me") def read_current_user( - credentials: Optional[HTTPAuthorizationCredentials] = Security(security), + credentials: HTTPAuthorizationCredentials | None = Security(security), ): if credentials is None: return {"msg": "Create an account first"} diff --git a/tests/test_security_oauth2_authorization_code_bearer.py b/tests/test_security_oauth2_authorization_code_bearer.py index 1ba577e9ff..587486c76b 100644 --- a/tests/test_security_oauth2_authorization_code_bearer.py +++ b/tests/test_security_oauth2_authorization_code_bearer.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import OAuth2AuthorizationCodeBearer from fastapi.testclient import TestClient @@ -13,7 +11,7 @@ oauth2_scheme = OAuth2AuthorizationCodeBearer( @app.get("/items/") -async def read_items(token: Optional[str] = Security(oauth2_scheme)): +async def read_items(token: str | None = Security(oauth2_scheme)): return {"token": token} diff --git a/tests/test_security_oauth2_authorization_code_bearer_description.py b/tests/test_security_oauth2_authorization_code_bearer_description.py index 73807c31a3..f878ede643 100644 --- a/tests/test_security_oauth2_authorization_code_bearer_description.py +++ b/tests/test_security_oauth2_authorization_code_bearer_description.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import OAuth2AuthorizationCodeBearer from fastapi.testclient import TestClient @@ -16,7 +14,7 @@ oauth2_scheme = OAuth2AuthorizationCodeBearer( @app.get("/items/") -async def read_items(token: Optional[str] = Security(oauth2_scheme)): +async def read_items(token: str | None = Security(oauth2_scheme)): return {"token": token} diff --git a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py index 583007c8b7..6fcce6fed7 100644 --- a/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py +++ b/tests/test_security_oauth2_authorization_code_bearer_scopes_openapi.py @@ -1,6 +1,6 @@ # Ref: https://github.com/fastapi/fastapi/issues/14454 -from typing import Annotated, Optional +from typing import Annotated from fastapi import APIRouter, Depends, FastAPI, Security from fastapi.security import OAuth2AuthorizationCodeBearer @@ -46,13 +46,13 @@ router = APIRouter(dependencies=[Security(oauth2_scheme, scopes=["read"])]) @router.get("/items/") -async def read_items(token: Optional[str] = Depends(oauth2_scheme)): +async def read_items(token: str | None = Depends(oauth2_scheme)): return {"token": token} @router.post("/items/") async def create_item( - token: Optional[str] = Security(oauth2_scheme, scopes=["read", "write"]), + token: str | None = Security(oauth2_scheme, scopes=["read", "write"]), ): return {"token": token} diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index cb79afdb86..a7eaf59443 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict @@ -24,7 +22,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(reusable_oauth2)): +def get_current_user(oauth_header: str | None = Security(reusable_oauth2)): if oauth_header is None: return None user = User(username=oauth_header) @@ -37,7 +35,7 @@ def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): @app.get("/users/me") -def read_users_me(current_user: Optional[User] = Depends(get_current_user)): +def read_users_me(current_user: User | None = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index b3fae37a17..0918d352ea 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict @@ -25,7 +23,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(reusable_oauth2)): +def get_current_user(oauth_header: str | None = Security(reusable_oauth2)): if oauth_header is None: return None user = User(username=oauth_header) @@ -38,7 +36,7 @@ def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): @app.get("/users/me") -def read_users_me(current_user: Optional[User] = Depends(get_current_user)): +def read_users_me(current_user: User | None = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user diff --git a/tests/test_security_oauth2_password_bearer_optional.py b/tests/test_security_oauth2_password_bearer_optional.py index 01e2f65ed9..263359c950 100644 --- a/tests/test_security_oauth2_password_bearer_optional.py +++ b/tests/test_security_oauth2_password_bearer_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import OAuth2PasswordBearer from fastapi.testclient import TestClient @@ -11,7 +9,7 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token", auto_error=False) @app.get("/items/") -async def read_items(token: Optional[str] = Security(oauth2_scheme)): +async def read_items(token: str | None = Security(oauth2_scheme)): if token is None: return {"msg": "Create an account first"} return {"token": token} diff --git a/tests/test_security_oauth2_password_bearer_optional_description.py b/tests/test_security_oauth2_password_bearer_optional_description.py index fec8d03a7a..0deb7e48ff 100644 --- a/tests/test_security_oauth2_password_bearer_optional_description.py +++ b/tests/test_security_oauth2_password_bearer_optional_description.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI, Security from fastapi.security import OAuth2PasswordBearer from fastapi.testclient import TestClient @@ -15,7 +13,7 @@ oauth2_scheme = OAuth2PasswordBearer( @app.get("/items/") -async def read_items(token: Optional[str] = Security(oauth2_scheme)): +async def read_items(token: str | None = Security(oauth2_scheme)): if token is None: return {"msg": "Create an account first"} return {"token": token} diff --git a/tests/test_security_openid_connect_optional.py b/tests/test_security_openid_connect_optional.py index ebaf394dc9..44e1a4866e 100644 --- a/tests/test_security_openid_connect_optional.py +++ b/tests/test_security_openid_connect_optional.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Depends, FastAPI, Security from fastapi.security.open_id_connect_url import OpenIdConnect from fastapi.testclient import TestClient @@ -15,7 +13,7 @@ class User(BaseModel): username: str -def get_current_user(oauth_header: Optional[str] = Security(oid)): +def get_current_user(oauth_header: str | None = Security(oid)): if oauth_header is None: return None user = User(username=oauth_header) @@ -23,7 +21,7 @@ def get_current_user(oauth_header: Optional[str] = Security(oid)): @app.get("/users/me") -def read_current_user(current_user: Optional[User] = Depends(get_current_user)): +def read_current_user(current_user: User | None = Depends(get_current_user)): if current_user is None: return {"msg": "Create an account first"} return current_user diff --git a/tests/test_serialize_response.py b/tests/test_serialize_response.py index 14f88dd931..114c3c6cb2 100644 --- a/tests/test_serialize_response.py +++ b/tests/test_serialize_response.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.testclient import TestClient from pydantic import BaseModel @@ -9,8 +7,8 @@ app = FastAPI() class Item(BaseModel): name: str - price: Optional[float] = None - owner_ids: Optional[list[int]] = None + price: float | None = None + owner_ids: list[int] | None = None @app.get("/items/valid", response_model=Item) diff --git a/tests/test_serialize_response_dataclass.py b/tests/test_serialize_response_dataclass.py index ee695368b8..ae05f14d1a 100644 --- a/tests/test_serialize_response_dataclass.py +++ b/tests/test_serialize_response_dataclass.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from datetime import datetime -from typing import Optional from fastapi import FastAPI from fastapi.testclient import TestClient @@ -12,8 +11,8 @@ app = FastAPI() class Item: name: str date: datetime - price: Optional[float] = None - owner_ids: Optional[list[int]] = None + price: float | None = None + owner_ids: list[int] | None = None @app.get("/items/valid", response_model=Item) diff --git a/tests/test_serialize_response_model.py b/tests/test_serialize_response_model.py index 79c90c9c29..bb05f7bc40 100644 --- a/tests/test_serialize_response_model.py +++ b/tests/test_serialize_response_model.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from pydantic import BaseModel, Field from starlette.testclient import TestClient @@ -9,8 +7,8 @@ app = FastAPI() class Item(BaseModel): name: str = Field(alias="aliased_name") - price: Optional[float] = None - owner_ids: Optional[list[int]] = None + price: float | None = None + owner_ids: list[int] | None = None @app.get("/items/valid", response_model=Item) diff --git a/tests/test_skip_defaults.py b/tests/test_skip_defaults.py index 02765291cb..238da7392f 100644 --- a/tests/test_skip_defaults.py +++ b/tests/test_skip_defaults.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import FastAPI from fastapi.testclient import TestClient from pydantic import BaseModel @@ -8,23 +6,23 @@ app = FastAPI() class SubModel(BaseModel): - a: Optional[str] = "foo" + a: str | None = "foo" class Model(BaseModel): - x: Optional[int] = None + x: int | None = None sub: SubModel class ModelSubclass(Model): y: int z: int = 0 - w: Optional[int] = None + w: int | None = None class ModelDefaults(BaseModel): - w: Optional[str] = None - x: Optional[str] = None + w: str | None = None + x: str | None = None y: str = "y" z: str = "z" diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index 86dc4d00e2..b8a9dd2921 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import APIRouter, FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -10,7 +8,7 @@ app = FastAPI() class Invoice(BaseModel): id: str - title: Optional[str] = None + title: str | None = None customer: str total: float @@ -51,7 +49,7 @@ subrouter = APIRouter() @subrouter.post("/invoices/", callbacks=invoices_callback_router.routes) -def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None): +def create_invoice(invoice: Invoice, callback_url: HttpUrl | None = None): """ Create an invoice. diff --git a/tests/test_union_body.py b/tests/test_union_body.py index e333e2499f..88f9e06cc8 100644 --- a/tests/test_union_body.py +++ b/tests/test_union_body.py @@ -1,5 +1,3 @@ -from typing import Optional, Union - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -9,7 +7,7 @@ app = FastAPI() class Item(BaseModel): - name: Optional[str] = None + name: str | None = None class OtherItem(BaseModel): @@ -17,7 +15,7 @@ class OtherItem(BaseModel): @app.post("/items/") -def save_union_body(item: Union[OtherItem, Item]): +def save_union_body(item: OtherItem | Item): return {"item": item} diff --git a/tests/test_union_body_discriminator.py b/tests/test_union_body_discriminator.py index 4afe7be4b4..1b682c7751 100644 --- a/tests/test_union_body_discriminator.py +++ b/tests/test_union_body_discriminator.py @@ -1,10 +1,9 @@ -from typing import Annotated, Any, Union +from typing import Annotated, Any, Literal from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot from pydantic import BaseModel, Field -from typing_extensions import Literal def test_discriminator_pydantic_v2() -> None: @@ -21,7 +20,7 @@ def test_discriminator_pydantic_v2() -> None: price: float Item = Annotated[ - Union[Annotated[FirstItem, Tag("first")], Annotated[OtherItem, Tag("other")]], + Annotated[FirstItem, Tag("first")] | Annotated[OtherItem, Tag("other")], Field(discriminator="value"), ] diff --git a/tests/test_union_body_discriminator_annotated.py b/tests/test_union_body_discriminator_annotated.py index 6644d106c8..7e64ea75b4 100644 --- a/tests/test_union_body_discriminator_annotated.py +++ b/tests/test_union_body_discriminator_annotated.py @@ -1,6 +1,6 @@ # Ref: https://github.com/fastapi/fastapi/discussions/14495 -from typing import Annotated, Union +from typing import Annotated import pytest from fastapi import FastAPI @@ -27,7 +27,7 @@ def client_fixture() -> TestClient: return v.get("pet_type", "") Pet = Annotated[ - Union[Annotated[Cat, Tag("cat")], Annotated[Dog, Tag("dog")]], + Annotated[Cat, Tag("cat")] | Annotated[Dog, Tag("dog")], Discriminator(get_pet_type), ] diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py index f6c2658f96..8cd7b4f017 100644 --- a/tests/test_union_forms.py +++ b/tests/test_union_forms.py @@ -1,4 +1,4 @@ -from typing import Annotated, Union +from typing import Annotated from fastapi import FastAPI, Form from fastapi.testclient import TestClient @@ -19,7 +19,7 @@ class CompanyForm(BaseModel): @app.post("/form-union/") -def post_union_form(data: Annotated[Union[UserForm, CompanyForm], Form()]): +def post_union_form(data: Annotated[UserForm | CompanyForm, Form()]): return {"received": data} diff --git a/tests/test_union_inherited_body.py b/tests/test_union_inherited_body.py index 5378880a47..c997a87a35 100644 --- a/tests/test_union_inherited_body.py +++ b/tests/test_union_inherited_body.py @@ -1,5 +1,3 @@ -from typing import Optional, Union - from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -9,7 +7,7 @@ app = FastAPI() class Item(BaseModel): - name: Optional[str] = None + name: str | None = None class ExtendedItem(Item): @@ -17,7 +15,7 @@ class ExtendedItem(Item): @app.post("/items/") -def save_union_different_body(item: Union[ExtendedItem, Item]): +def save_union_different_body(item: ExtendedItem | Item): return {"item": item} diff --git a/tests/test_validate_response.py b/tests/test_validate_response.py index 938d419566..7288220eab 100644 --- a/tests/test_validate_response.py +++ b/tests/test_validate_response.py @@ -1,5 +1,3 @@ -from typing import Optional, Union - import pytest from fastapi import FastAPI from fastapi.exceptions import ResponseValidationError @@ -11,8 +9,8 @@ app = FastAPI() class Item(BaseModel): name: str - price: Optional[float] = None - owner_ids: Optional[list[int]] = None + price: float | None = None + owner_ids: list[int] | None = None @app.get("/items/invalid", response_model=Item) @@ -25,7 +23,7 @@ def get_invalid_none(): return None -@app.get("/items/validnone", response_model=Union[Item, None]) +@app.get("/items/validnone", response_model=Item | None) def get_valid_none(send_none: bool = False): if send_none: return None diff --git a/tests/test_validate_response_dataclass.py b/tests/test_validate_response_dataclass.py index 67282bcde1..03b7d5f338 100644 --- a/tests/test_validate_response_dataclass.py +++ b/tests/test_validate_response_dataclass.py @@ -1,5 +1,3 @@ -from typing import Optional - import pytest from fastapi import FastAPI from fastapi.exceptions import ResponseValidationError @@ -12,8 +10,8 @@ app = FastAPI() @dataclass class Item: name: str - price: Optional[float] = None - owner_ids: Optional[list[int]] = None + price: float | None = None + owner_ids: list[int] | None = None @app.get("/items/invalid", response_model=Item) diff --git a/tests/utils.py b/tests/utils.py index 4cbfee79f5..09c4e13b00 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,7 +2,6 @@ import sys import pytest -needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+") needs_py310 = pytest.mark.skipif( sys.version_info < (3, 10), reason="requires python3.10+" ) From da4135ce1eb4df17a4643a21101645951bfb3ab3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 17 Feb 2026 09:59:37 +0000 Subject: [PATCH 248/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1f72f883a2..34492bfc58 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -29,6 +29,7 @@ hide: ### Internal +* ๐ŸŽจ Upgrade typing syntax for Python 3.10. PR [#14932](https://github.com/fastapi/fastapi/pull/14932) by [@tiangolo](https://github.com/tiangolo). * โฌ† Bump cryptography from 46.0.4 to 46.0.5. PR [#14892](https://github.com/fastapi/fastapi/pull/14892) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pillow from 12.1.0 to 12.1.1. PR [#14899](https://github.com/fastapi/fastapi/pull/14899) by [@dependabot[bot]](https://github.com/apps/dependabot). From 339f7028105fdca80296974aeafa7beee59f1f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 18 Feb 2026 07:26:13 -0800 Subject: [PATCH 249/367] =?UTF-8?q?=F0=9F=94=A8=20Add=20Kapa.ai=20widget?= =?UTF-8?q?=20(AI=20chatbot)=20(#14938)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alejandra --- docs/en/docs/css/custom.css | 4 ++++ docs/en/docs/js/init_kapa_widget.js | 29 +++++++++++++++++++++++++++++ docs/en/mkdocs.yml | 1 + 3 files changed, 34 insertions(+) create mode 100644 docs/en/docs/js/init_kapa_widget.js diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index 7c50dbd9be..dc9c7d63b4 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -61,6 +61,10 @@ a.internal-link::after { padding-bottom: 2em; } +.md-footer-meta .md-social { + padding-right: 4rem; +} + .user-list { display: flex; flex-wrap: wrap; diff --git a/docs/en/docs/js/init_kapa_widget.js b/docs/en/docs/js/init_kapa_widget.js new file mode 100644 index 0000000000..eaf123bf3f --- /dev/null +++ b/docs/en/docs/js/init_kapa_widget.js @@ -0,0 +1,29 @@ +document.addEventListener("DOMContentLoaded", function () { + var script = document.createElement("script"); + script.src = "https://widget.kapa.ai/kapa-widget.bundle.js"; + script.setAttribute("data-website-id", "91f47f27-b405-4299-bf5f-a1c0ec07b3cc"); + script.setAttribute("data-project-name", "FastAPI"); + script.setAttribute("data-project-color", "#009485"); + script.setAttribute("data-project-logo", "https://fastapi.tiangolo.com/img/favicon.png"); + script.setAttribute("data-bot-protection-mechanism", "hcaptcha"); + script.setAttribute("data-button-height", "3rem"); + script.setAttribute("data-button-width", "3rem"); + script.setAttribute("data-button-border-radius", "50%"); + script.setAttribute("data-button-padding", "0"); + script.setAttribute("data-button-image", "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 8V4H8'/%3E%3Crect width='16' height='12' x='4' y='8' rx='2'/%3E%3Cpath d='M2 14h2'/%3E%3Cpath d='M20 14h2'/%3E%3Cpath d='M15 13v2'/%3E%3Cpath d='M9 13v2'/%3E%3C/svg%3E"); + script.setAttribute("data-button-image-height", "20px"); + script.setAttribute("data-button-image-width", "20px"); + script.setAttribute("data-button-text", "Ask AI"); + script.setAttribute("data-button-text-font-size", "0.5rem"); + script.setAttribute("data-button-text-font-family", "Roboto, sans-serif"); + script.setAttribute("data-button-text-color", "#FFFFFF"); + script.setAttribute("data-modal-border-radius", "0.5rem"); + script.setAttribute("data-modal-header-bg-color", "#009485"); + script.setAttribute("data-modal-title", "FastAPI AI Assistant"); + script.setAttribute("data-modal-title-color", "#FFFFFF"); + script.setAttribute("data-modal-title-font-family", "Roboto, sans-serif"); + script.setAttribute("data-modal-example-questions", "How to define a route?,How to validate models?,How to handle responses?,How to deploy FastAPI?"); + script.setAttribute("data-modal-disclaimer", "AI-generated answers based on FastAPI [documentation](https://fastapi.tiangolo.com/) and [community discussions](https://github.com/fastapi/fastapi/discussions). Always verify important information."); + script.async = true; + document.head.appendChild(script); +}); diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 66ad67e9d0..96ed3d5869 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -342,5 +342,6 @@ extra_css: extra_javascript: - js/termynal.js - js/custom.js +- js/init_kapa_widget.js hooks: - ../../scripts/mkdocs_hooks.py From d178b95695231e908c5ce398b2655223bcad16cf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 18 Feb 2026 21:19:34 +0000 Subject: [PATCH 250/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 34492bfc58..6242d037de 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ๐Ÿ”จ Add Kapa.ai widget (AI chatbot). PR [#14938](https://github.com/fastapi/fastapi/pull/14938) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ฅ Remove Python 3.9 specific files, no longer needed after updating translations. PR [#14931](https://github.com/fastapi/fastapi/pull/14931) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ“ Update docs for JWT to prevent timing attacks. PR [#14908](https://github.com/fastapi/fastapi/pull/14908) by [@tiangolo](https://github.com/tiangolo). From 3bdf470622e44a7a804225ab5c0976d7f4aba0b0 Mon Sep 17 00:00:00 2001 From: argoarsiks Date: Thu, 19 Feb 2026 00:30:43 +0300 Subject: [PATCH 251/367] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20several=20ty?= =?UTF-8?q?pos=20in=20ru=20translations=20(#14934)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: fix typos * Apply suggestion from @YuriiMotov --------- Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/ru/docs/advanced/middleware.md | 2 +- docs/ru/docs/deployment/docker.md | 2 +- docs/ru/docs/history-design-future.md | 2 +- docs/ru/docs/tutorial/security/oauth2-jwt.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ru/docs/advanced/middleware.md b/docs/ru/docs/advanced/middleware.md index 034feae7eb..1f1a160604 100644 --- a/docs/ru/docs/advanced/middleware.md +++ b/docs/ru/docs/advanced/middleware.md @@ -83,7 +83,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ะŸะพะดะดะตั€ะถะธะฒะฐัŽั‚ัั ัะปะตะดัƒัŽั‰ะธะต ะฐั€ะณัƒะผะตะฝั‚ั‹: - `minimum_size` โ€” ะฝะต ัะถะธะผะฐั‚ัŒ GZipโ€‘ะพะผ ะพั‚ะฒะตั‚ั‹, ั€ะฐะทะผะตั€ ะบะพั‚ะพั€ั‹ั… ะผะตะฝัŒัˆะต ัั‚ะพะณะพ ะผะธะฝะธะผะฐะปัŒะฝะพะณะพ ะทะฝะฐั‡ะตะฝะธั ะฒ ะฑะฐะนั‚ะฐั…. ะŸะพ ัƒะผะพะปั‡ะฐะฝะธัŽ โ€” `500`. -- `compresslevel` โ€” ัƒั€ะพะฒะตะฝัŒ GZipโ€‘ัะถะฐั‚ะธั. ะฆะตะปะพะต ั‡ะธัะปะพ ะพั‚ 1 ะดะพ 9. ะŸะพ ัƒะผะพะปั‡ะฐะฝะธัŽ โ€” `9`. ะ‘ะพะปะตะต ะฝะธะทะบะพะต ะทะฝะฐั‡ะตะฝะธะต โ€” ะฑั‹ัั‚ั€ะตะตะต ัะถะฐั‚ะธะต, ะฝะพ ะฑะพะปัŒัˆะธะน ั€ะฐะทะผะตั€ ั„ะฐะนะปะฐ; ะฑะพะปะตะต ะฒั‹ัะพะบะพะต ะทะฝะฐั‡ะตะฝะธะต โ€” ะฑะพะปะตะต ะผะตะดะปะตะฝะฝะพะต ัะถะฐั‚ะธะต, ะฝะพ ะผะตะฝัŒัˆะธะน ั€ะฐะทะผะตั€ ั„ะฐะนะปะฐ. +- `compresslevel` โ€” ัƒั€ะพะฒะตะฝัŒ GZipโ€‘ัะถะฐั‚ะธั. ะฆะตะปะพะต ั‡ะธัะปะพ ะพั‚ 1 ะดะพ 9. ะŸะพ ัƒะผะพะปั‡ะฐะฝะธัŽ โ€” `9`. ะ‘ะพะปะตะต ะฝะธะทะบะพะต ะทะฝะฐั‡ะตะฝะธะต โ€” ะฑั‹ัั‚ั€ะตะต ัะถะฐั‚ะธะต, ะฝะพ ะฑะพะปัŒัˆะธะน ั€ะฐะทะผะตั€ ั„ะฐะนะปะฐ; ะฑะพะปะตะต ะฒั‹ัะพะบะพะต ะทะฝะฐั‡ะตะฝะธะต โ€” ะฑะพะปะตะต ะผะตะดะปะตะฝะฝะพะต ัะถะฐั‚ะธะต, ะฝะพ ะผะตะฝัŒัˆะธะน ั€ะฐะทะผะตั€ ั„ะฐะนะปะฐ. ## ะ”ั€ัƒะณะธะต middleware { #other-middlewares } diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 791057fe56..5dfa211599 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -214,7 +214,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] 5. ะšะพะฟะธั€ัƒะตะผ ะดะธั€ะตะบั‚ะพั€ะธัŽ `./app` ะฒะฝัƒั‚ั€ัŒ ะดะธั€ะตะบั‚ะพั€ะธะธ `/code`. - ะขะฐะบ ะบะฐะบ ะทะดะตััŒ ะฒะตััŒ ะบะพะด, ะบะพั‚ะพั€ั‹ะน **ะผะตะฝัะตั‚ัั ั‡ะฐั‰ะต ะฒัะตะณะพ**, ะบััˆ Docker **ะฒั€ัะด ะปะธ** ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะดะปั ัั‚ะพะณะพ ัˆะฐะณa ะธะปะธ **ะฟะพัะปะตะดัƒัŽั‰ะธั… ัˆะฐะณะพะฒ**. + ะขะฐะบ ะบะฐะบ ะทะดะตััŒ ะฒะตััŒ ะบะพะด, ะบะพั‚ะพั€ั‹ะน **ะผะตะฝัะตั‚ัั ั‡ะฐั‰ะต ะฒัะตะณะพ**, ะบััˆ Docker **ะฒั€ัะด ะปะธ** ะฑัƒะดะตั‚ ะธัะฟะพะปัŒะทะพะฒะฐั‚ัŒัั ะดะปั ัั‚ะพะณะพ ัˆะฐะณะฐ ะธะปะธ **ะฟะพัะปะตะดัƒัŽั‰ะธั… ัˆะฐะณะพะฒ**. ะŸะพัั‚ะพะผัƒ ะฒะฐะถะฝะพ ั€ะฐะทะผะตัั‚ะธั‚ัŒ ัั‚ะพั‚ ัˆะฐะณ **ะฑะปะธะถะต ะบ ะบะพะฝั†ัƒ** `Dockerfile`, ั‡ั‚ะพะฑั‹ ะพะฟั‚ะธะผะธะทะธั€ะพะฒะฐั‚ัŒ ะฒั€ะตะผั ัะฑะพั€ะบะธ ะพะฑั€ะฐะทะฐ ะบะพะฝั‚ะตะนะฝะตั€ะฐ. diff --git a/docs/ru/docs/history-design-future.md b/docs/ru/docs/history-design-future.md index e2395fe8b9..5019157600 100644 --- a/docs/ru/docs/history-design-future.md +++ b/docs/ru/docs/history-design-future.md @@ -76,4 +76,4 @@ ะฃ **FastAPI** ะฒะตะปะธะบะพะต ะฑัƒะดัƒั‰ะตะต. -ะ˜ [ะฒะฐัˆ ะฒะบะปะฐะด ะฒ ัั‚ะพ](help-fastapi.md){.internal-link target=_blank} - ะพั‡ะตะฝัŒ ั†ะตะฝะฝะตะฝ. +ะ˜ [ะฒะฐัˆ ะฒะบะปะฐะด ะฒ ัั‚ะพ](help-fastapi.md){.internal-link target=_blank} - ะพั‡ะตะฝัŒ ั†ะตะฝะตะฝ. diff --git a/docs/ru/docs/tutorial/security/oauth2-jwt.md b/docs/ru/docs/tutorial/security/oauth2-jwt.md index 7838b07df4..f7853d48f7 100644 --- a/docs/ru/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ru/docs/tutorial/security/oauth2-jwt.md @@ -20,7 +20,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 ะะพ ะพะฝ ะฟะพะดะฟะธัะฐะฝ. ะกะปะตะดะพะฒะฐั‚ะตะปัŒะฝะพ, ะบะพะณะดะฐ ะฒั‹ ะฟะพะปัƒั‡ะฐะตั‚ะต ั‚ะพะบะตะฝ, ะบะพั‚ะพั€ั‹ะน ะฒั‹ ัะผะธั‚ะธั€ะพะฒะฐะปะธ (ะฒั‹ะดะฐะฒะฐะปะธ), ะฒั‹ ะผะพะถะตั‚ะต ัƒะฑะตะดะธั‚ัŒัั, ั‡ั‚ะพ ัั‚ะพ ะธะผะตะฝะฝะพ ะฒั‹ ะตะณะพ ัะผะธั‚ะธั€ะพะฒะฐะปะธ. -ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะผะพะถะฝะพ ัะพะทะดะฐั‚ัŒ ั‚ะพะบะตะฝ ัะพ ัั€ะพะบะพะผ ะดะตะนัั‚ะฒะธั, ัะบะฐะถะตะผ, 1 ะฝะตะดะตะปั. ะ ะบะพะณะดะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ ะฒะตั€ะฝะตั‚ัั ะฝะฐ ัะปะตะดัƒัŽั‰ะธะน ะดะตะฝัŒ ั ั‚ะตะผ ะถะต ั‚ะพะบะตะฝะพะผ, ะฒั‹ ะฑัƒะดะตั‚ะต ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะพะฝ ะฒัะต ะตั‰ะต ะฐะฒั‚ะพั€ะธะทะธั€ะพะฒะฐะฝ ะฒ ะฒะฐัˆะตะน ัะธัั‚ะตะผะต. +ะขะฐะบะธะผ ะพะฑั€ะฐะทะพะผ, ะผะพะถะฝะพ ัะพะทะดะฐั‚ัŒ ั‚ะพะบะตะฝ ัะพ ัั€ะพะบะพะผ ะดะตะนัั‚ะฒะธั, ัะบะฐะถะตะผ, 1 ะฝะตะดะตะปั. ะ ะบะพะณะดะฐ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ ะฒะตั€ะฝะตั‚ัั ะฝะฐ ัะปะตะดัƒัŽั‰ะธะน ะดะตะฝัŒ ั ั‚ะตะผ ะถะต ั‚ะพะบะตะฝะพะผ, ะฒั‹ ะฑัƒะดะตั‚ะต ะทะฝะฐั‚ัŒ, ั‡ั‚ะพ ะพะฝ ะฒัะต ะตั‰ะต ะฐะฒั‚ะพั€ะธะทะพะฒะฐะฝ ะฒ ะฒะฐัˆะตะน ัะธัั‚ะตะผะต. ะงะตั€ะตะท ะฝะตะดะตะปัŽ ัั€ะพะบ ะดะตะนัั‚ะฒะธั ั‚ะพะบะตะฝะฐ ะธัั‚ะตั‡ะตั‚, ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ ะฝะต ะฑัƒะดะตั‚ ะฐะฒั‚ะพั€ะธะทะพะฒะฐะฝ ะธ ะตะผัƒ ะฟั€ะธะดะตั‚ัั ะทะฐะฝะพะฒะพ ะฒั…ะพะดะธั‚ัŒ ะฒ ัะธัั‚ะตะผัƒ, ั‡ั‚ะพะฑั‹ ะฟะพะปัƒั‡ะธั‚ัŒ ะฝะพะฒั‹ะน ั‚ะพะบะตะฝ. ะ ะตัะปะธ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŒ (ะธะปะธ ั‚ั€ะตั‚ัŒะต ะปะธั†ะพ) ะฟะพะฟั‹ั‚ะฐะตั‚ัั ะผะพะดะธั„ะธั†ะธั€ะพะฒะฐั‚ัŒ ั‚ะพะบะตะฝ, ั‡ั‚ะพะฑั‹ ะธะทะผะตะฝะธั‚ัŒ ัั€ะพะบ ะดะตะนัั‚ะฒะธั, ะฒั‹ ัะผะพะถะตั‚ะต ัั‚ะพ ะพะฑะฝะฐั€ัƒะถะธั‚ัŒ, ะฟะพัะบะพะปัŒะบัƒ ะฟะพะดะฟะธัะธ ะฝะต ะฑัƒะดัƒั‚ ัะพะฒะฟะฐะดะฐั‚ัŒ. From c44158384c46c0ceab81dea8d34def67cb318c67 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 18 Feb 2026 21:31:13 +0000 Subject: [PATCH 252/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6242d037de..4bb2aa9908 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Translations +* โœ๏ธ Fix several typos in ru translations. PR [#14934](https://github.com/fastapi/fastapi/pull/14934) by [@argoarsiks](https://github.com/argoarsiks). * ๐ŸŒ Update translations for ko (update-all and add-missing). PR [#14923](https://github.com/fastapi/fastapi/pull/14923) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for uk (add-missing). PR [#14922](https://github.com/fastapi/fastapi/pull/14922) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŒ Update translations for zh-hant (update-all and add-missing). PR [#14921](https://github.com/fastapi/fastapi/pull/14921) by [@YuriiMotov](https://github.com/YuriiMotov). From cf058239d14f3957e69848c81bae42afe4270a30 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:40:05 +0100 Subject: [PATCH 253/367] =?UTF-8?q?=F0=9F=91=B7=20Always=20run=20tests=20o?= =?UTF-8?q?n=20push=20to=20`master`=20branch=20and=20when=20run=20by=20sch?= =?UTF-8?q?eduler=20(#14940)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 338f6c390f..d61b4add94 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,7 +45,7 @@ jobs: test: needs: - changes - if: needs.changes.outputs.src == 'true' + if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master' strategy: matrix: os: [ windows-latest, macos-latest ] From d2c17b603d2f986d5f3800d3bf24acba8e1f485b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Feb 2026 15:40:34 +0000 Subject: [PATCH 254/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4bb2aa9908..d579a3cb0a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* ๐Ÿ‘ท Always run tests on push to `master` branch and when run by scheduler. PR [#14940](https://github.com/fastapi/fastapi/pull/14940) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐ŸŽจ Upgrade typing syntax for Python 3.10. PR [#14932](https://github.com/fastapi/fastapi/pull/14932) by [@tiangolo](https://github.com/tiangolo). * โฌ† Bump cryptography from 46.0.4 to 46.0.5. PR [#14892](https://github.com/fastapi/fastapi/pull/14892) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Bump pillow from 12.1.0 to 12.1.1. PR [#14899](https://github.com/fastapi/fastapi/pull/14899) by [@dependabot[bot]](https://github.com/apps/dependabot). From e8b98d21871f64234520c1e770f39e6bfea3b0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 05:01:31 -0800 Subject: [PATCH 255/367] =?UTF-8?q?=F0=9F=90=9B=20Fix=20JSON=20Schema=20fo?= =?UTF-8?q?r=20files,=20use=20`contentMediaType`=20instead=20of=20`format:?= =?UTF-8?q?=20binary`=20(#14953)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/json-base64-bytes.md | 63 +++++ .../tutorial/json-base64-bytes/image01.png | Bin 0 -> 72638 bytes docs/en/mkdocs.yml | 1 + docs_src/json_base64_bytes/__init__.py | 0 .../json_base64_bytes/tutorial001_py310.py | 46 ++++ fastapi/_compat/v2.py | 19 +- fastapi/datastructures.py | 2 +- pyproject.toml | 1 + .../playwright/json_base64_bytes/image01.py | 37 +++ .../test_file/test_list.py | 20 +- .../test_file/test_optional.py | 8 +- .../test_file/test_optional_list.py | 20 +- .../test_file/test_required.py | 16 +- .../test_json_base64_bytes/__init__.py | 0 .../test_tutorial001.py | 225 ++++++++++++++++++ .../test_request_files/test_tutorial001.py | 4 +- .../test_request_files/test_tutorial001_02.py | 10 +- .../test_request_files/test_tutorial001_03.py | 4 +- .../test_request_files/test_tutorial002.py | 10 +- .../test_request_files/test_tutorial003.py | 10 +- .../test_tutorial001.py | 4 +- 21 files changed, 470 insertions(+), 30 deletions(-) create mode 100644 docs/en/docs/advanced/json-base64-bytes.md create mode 100644 docs/en/docs/img/tutorial/json-base64-bytes/image01.png create mode 100644 docs_src/json_base64_bytes/__init__.py create mode 100644 docs_src/json_base64_bytes/tutorial001_py310.py create mode 100644 scripts/playwright/json_base64_bytes/image01.py create mode 100644 tests/test_tutorial/test_json_base64_bytes/__init__.py create mode 100644 tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py diff --git a/docs/en/docs/advanced/json-base64-bytes.md b/docs/en/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000..c0dfec72b9 --- /dev/null +++ b/docs/en/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# JSON with Bytes as Base64 { #json-with-bytes-as-base64 } + +If your app needs to receive and send JSON data, but you need to include binary data in it, you can encode it as base64. + +## Base64 vs Files { #base64-vs-files } + +Consider first if you can use [Request Files](../tutorial/request-files.md){.internal-link target=_blank} for uploading binary data and [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-){.internal-link target=_blank} for sending binary data, instead of encoding it in JSON. + +JSON can only contain UTF-8 encoded strings, so it can't contain raw bytes. + +Base64 can encode binary data in strings, but to do it, it needs to use more characters than the original binary data, so it would normally be less efficient than regular files. + +Use base64 only if you definitely need to include binary data in JSON, and you can't use files for that. + +## Pydantic `bytes` { #pydantic-bytes } + +You can declare a Pydantic model with `bytes` fields, and then use `val_json_bytes` in the model config to tell it to use base64 to *validate* input JSON data, as part of that validation it will decode the base64 string into bytes. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +If you check the `/docs`, they will show that the field `data` expects base64 encoded bytes: + +
+ +
+ +You could send a request like: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip + +`aGVsbG8=` is the base64 encoding of `hello`. + +/// + +And then Pydantic will decode the base64 string and give you the original bytes in the `data` field of the model. + +You will receive a response like: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` for Output Data { #pydantic-bytes-for-output-data } + +You can also use `bytes` fields with `ser_json_bytes` in the model config for output data, and Pydantic will *serialize* the bytes as base64 when generating the JSON response. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` for Input and Output Data { #pydantic-bytes-for-input-and-output-data } + +And of course, you can use the same model configured to use base64 to handle both input (*validate*) with `val_json_bytes` and output (*serialize*) with `ser_json_bytes` when receiving and sending JSON data. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/en/docs/img/tutorial/json-base64-bytes/image01.png b/docs/en/docs/img/tutorial/json-base64-bytes/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..996732b7499a97cbb7ced1612cd87962ecc3292e GIT binary patch literal 72638 zcmeFZbx@mK)Gtbf(iSVFKq>a(?(XjH#ft`tLxNjNTZ$JaxLY8&1}R<$5ZqmZyW54n z-#7PsbLZMQXXehCxqm&$&a-Xpwbx$1-&#AtYAUjruRpv-K|#Tkmy^;!L3#EY1?4&4 z%cl<|^1~E7C@61Gqf^Kg`SFP;_tLrUcdbM)v)W9{A_{gLa8tv@#YImKTwY!-NA-d2lh}$kI~LdDk5%sB-Csn2 zNHsS%w-s-DdwW{dv{@(I|LCoteKd_s0fAwK#o4k%^Ym{GvDDSo)%*cj?Em;yQBm>m z?e8#A2A}@>P5}P@>rv|eJJbIanoxt0x-(w7>AN|I>(v+M<^2%S6c7;Tk`XenMOWAD zPTQON8NYn&mW!X-#~8_=yE^&?&xZdUT<#NH1@EbQO`=)Pw)lhSGmM5k*KJ-+jvR>!{q}(saoL-Zmx^W`mJF{JWtX-xI4uSmH~uwr(&JDkvT*4W1QhfutKww)--Bg941umNW8ciB5r~bbM7`wTKVfyvyG3ukD^=M*E=m7DN3}>?nKJDRxJ~n z+-RP?d|YPV&_5z?d1*}C0w3NG^Ztr5r(zTd8`Id- z3!D;k#ZaEdORt5T<^wSGweQ@I>>ky1_mw{1bm4KPZgNVg<0gm2FBoJnCEp;*n|8fp zYTImz5}xQz!qK}h6R#QPY;&Bs{r!Z}U`fvt`(%@{f`^x?VrO-6B*E+mPnlFQrhhPD zq}jTWHwFv+1%IQZBl5Q?jz*j=lc4YI9)R7_^PFI)+66~CqNa+1N|;@QscC0uRe@*6Li`3ci{-FMh-cdm6SSA0IpEXdZesQCC>!kELU)9A*cAgs{2 ziIGhLe?@@sS~|eYI1{iblW8lWk55IdzkCX=G}jK` z4y}@o{+VvYESPZpTPXB!q4>H0`&=HveO%A6Xkef>J*f|L-s85bbJT4esil11;IXmX z{8cthDeq+FL@)44=T?@jClOT2$C_YnIcNX7!`reYMLBK`5zXW}@dQ`4!9a7h9Eb@! zBjPB^573h9_->e40!Jp`4c{j0=?FFc)G@s z?k#%eFC&Ic)>@Jv`Fe!AJGYx~bWF>YBV7`3oQ6Z4zn0{q6n+2_9!<_KEvR#X{i7PW zGBRZGE#H|}c=}vPJ^QAgkhkEP-2ItEQEteG=2!k*|3Kpy++4zT=5M9Ltgu0PD`puB ztCY=Am3WWFE8|uSz1v)VIndpHs@@qsU<8P^>?agbrVhsr9q{#V5SRKGy#o$w(xLBH zR*YzVcQ#XV>Zt7LIMr&=BRXeyv|B~9v27q&KUpESbh_Y1cDFW2&91Bj`zb)k{d%#1 z*fo>8-gWb3Oc7Zvh|<L+a=#FMDTSzT%{_<;UbVSXeFbxF-r4b3F>sbPwCU%yNBbZO7zTch4x4H z>82RjOO+d@?7|I0ji@k{hod3j?Aenmc4YCdxt1H3g9}Hr$bErStsF?=weq~DvEVruT0|U&~pLyV;ZL_hzqElwSdgl~XvBmJ)Nov~qWmoAL zISZ~LOd^b13=Ss&QVWx_Dc!LNuAS7cT~sLs%oz}dM6OWd;|Qu!p(0a7!xfwwyY-m% zFJ)oRI;+Rl8LoOytM)k(ZQ8|CJ*o+HCwk|7-UQ_U-tDv)(NJFn3J^|UGUsco_kyYU z0}cDooWbs1%JXwoJ!mV&*br7DTe{wHvhd9&UT0T7yruUiRbvyh+O;kWL@lxBA?TvB z?kjVA;8-E6(e9h0_kV4{v!}ojWaGu4RIUz0?k!~&wenmP0ZCE;h*8niBE|5&|FFvc zO(wiInTc$BlhEa4lw4a~yZQ0EyyA65>}#ZhDxl^r$r2Md9k)4BUg7$T6vg?ecY4IRrm3Wc;rE_x`&@P{>pLGU)lrTOC zabkhwu`Wxio{(ot;QY0YBHNA1ee5?abH^74DwTqSN68{~frPl%j2oV}gN5r7Qg378 z_Jy5l74%O#o{X#kNgqzxfU~6*!QfvL=F4rmv(Hs+9oAodBhhbuk~Co2+Z8umoEa?> z)G>=dJne=SRn36D18h9xqC4_SGo~W9mo^ln;TF`LQ+kIJrO)TA4J))|_UGMe5X(a( z^ur-SmAr8ZF?t|U*V-#%U)(#sJOyS}zEstPn1r+eod{$HnW^e6*khlxFlzlL?LHI9 zhQpG1n{&-tq!TaU()?k}Os$DXlfXlZ7+Kb`iLCx;T#CO9DA(NdHAyK%heZ?N97Z?$t@qDO zuB1T@M`)ENE05Yqdd?%2@exv6rX;&n3WHrTjd>~*#YIJ0x(TOr5oyq?Q6XPp{6c6^ zW4;jtgvShcJ?Z6DO*CY=soCeP1X7&`&L#0j2d%$%w%byrXrzTGY5r<9RN=+Nr-zEZ z7VZVB7GAR}*wCBu13Au@*wSH4ZitFWqn2=SBjsX;g^?4R*_Z^9pLBv5X`>+I^yPu| z3~6ey4De4&)cs()MoP2O$_c6wz&#;j$*R(~_zaL^r2cEYjr!HY+D%8+u!p5GQ43HB zT%M)E2*G+iU{sDIW~4Rk)?}frYH4QRwLqefpK_d#u)wl{gua))j+dLCKqU)qGDh9g zFNN6!`^eu>ehxP>Lz<-J4og`v*zRk?hcIKJW{6w#ZskExbv6^(oT`J5)XA+3pgFlV zIYEJnPg6}dCcfiahvMxE-Z`NROowy!k*;)uLj$XJVoQC)c)QqCopdF;66U1WgGJF2 z^8DqT)#WvVs!af@G9HSYEGk|7+-}Z&>j84S=)Rkf?i0td6T!rpgVWgPHp45i_V2=)$cZeIF_pgFMV@*jt#^s5?Jw*Ur3CmE^yeCEKy zmpH*L-yVbk`U>T$@`UQ>(KWog?{p5Nu8pjK$wdb7pLi<1Asf`OAS&U?ONL{Tv9)IP7GFQ1Xbp$_@U7?q zKrMiGb9JPBxwh|`-h_r;oo!PsnK`sUfQBYtMBv`o&Bd?=l5UUCHLhe~FRK`*{T>zU z4i7GrUC@;gKw273`%tNyjE>ADwXYi#Dt42k+&m3qgu9rVRVew&G%cGZdT$;?loi)m z1baI|$Z@+tC0zJPl|`e;B_6X;LR|TkQw1~9{-5(8d#Mrc(res5n2sD?D50NzqVe*= zq9OLxNPQP`XY@m3Vc4q?HIy!-rP;|_*4e&mY=wF8%+TDCW5D=c%w-eR=Jcg^Xo+L8 zU#z-YsFTl*r&8+2B=rN?)>}S*Rb%IE(xHt+pG$@GS_Q}@$;o974ZWm`q9vbs!F2+U zwtrgPox=;jXR>1l;+jgrW7fPp0B;Z(Q*14VE6)N{t=97;hID)*=_5p$4jT7;OP&fc z>mRnn&fkzt(7T+wya@sTf=Z05@`6up{?WTRluqA`ymQaCC_wOqwX{%vNr)uUd`D1s zdA`Uqt!@n@_r#x+At8OQodk_#tRhB0^Sya-&9iCt>JkXNIQVFEGaVf)`!(^pf=KHV zS!@k`#?}%;XPcU4g$0Qqjz`6_-VNU8K&~||{k(?dv)oErTqg zYFy6l1LSwD+2VP&^_Sa@^2e1l`{DOHHHN)I?t8yMR>PHzcHQ6WGRdVqrAlRKD@nbS z{$UBBD-r!u)H~u1-)A?$1Fi`cJf2;t#PR-_b=+>@jeigx`l>Tid-#E)s!b7rO=}pcuv$BQP`ku=nPqWMT~>>nb*8OMA-bkHz5)ed&ARtx!=Xg!=$vK}u?wX?@_=Sqv?_-wLFAw? zVA+{}nxF>l+VlQW_aOTi^4gK?_VjEBZN2by>HX>HX#>&spc)?GPcy;0>8SdjpQqY7<*aSN!l%Hwosc}$r}7er0bMYo&@F3R~sBol=h`sXgJ?iBFc z^R?$@#9|!@wkXLO&9jshxYdMOptNyU}t#$RC1M(^b|g-A?d5!8O=Q(o9UbA0 zk^K1G->v9GT?NI~Cnb5CE;u=SWrCHcuII#ApK}<7Rf8`x?HEIUyS|EV7#>2&+yP7Q zj+r>5sg_3G93>|1DCdl2f0SVj=D~efaBJ0v*{~>ws@Mv>txSz<;VjJ@WpE;$?q2RV z{1M9(uG*WAHkyv}QBPx*&g)p|c^9^{l51%pXV<%Q=8Wg~Jmc}>HL1jRHqhM470H-= zvV2fvvjgULr!O;Qq&I`dAZehU&qv_=Z-3s^l$*02Uo_J98A(Q6EE23>%0h&T4IKqPhcDv{6MYPg&R#~o4BReiL zt_6t6#x;Fp~&HTVMr6q^V}M>B!}olHe1>Dbd>VZ7GrhXArYX(eLTN3 zKPL6hSQ9KX`&1M%B~rw3tuQ%veM_|NAi{!8-1xh*Tk#FPRzgPHA^9PH`)->4Zv68S zLR_h&R!Vf{Ej+sHoI7hqQ_5w=HTlX_|oM%OB};q9Ij4FOQCX89@)PwZvxc zGyPU;S(txv1}1SgtFh1oqC(rKjp(7}3}NejTAVINqx!qZ*dV}hAG1KB6aP0lDpe-A z$_tT79kNY#hkM6XKxwW#>2bekDoN#b=;{nvu`##GwHl)$dbk|rwE8?2ESl45`I+Qb zE`nr$!{-t8)fG`EBuXi*kw4Dk1k#f4S;WwPu*}!jIaacE$}Wgh-nX9EE%5?c+nlq0 zFt4T=@|zp=#X!p?=)TPStnZ6tViY(rQ~L-6y68A;W`hk#%e^W1E6A>kc`E>XVRa252Xcwz0;pL^&J ztp?N-RKKuppxXFyh5-f1YHqcnI&@n``3EcuoV-e$0W2aZA@eiuOvqZ}`1LfBtVcAM zU_@_+kSHG`_U#OByUe$Gfk#p2>w7Im={1f)(m9c?J6FXrPak#$O2ECEE#@FYlHcNv zXs*PW*!Fj-tBWtT*lC7xyi8(>Z_V3cDqUO^U5<`y7+dN&eaY(Y$ShY@7^iW_=GeX+ zuUu1GgHxJCJAfp5M{$E)6K-xNN1i@tFDZA{NIAQ9U`so?1>#TnxyIb$Rg+-)bHN3<1vRHsBUPeZA zk}E2z!2F-Qg9hH-9`4YEIDOdI>_ZO52FW~)q79PX;AybmU$Z>^7Q%rT=!WmzDQoLU zdFZ%at3Gy|!Tqo<*3aNj6`yDt`$Tfs8Qj3pU#tfWNZQcfi@=pZu23J9rX@_XBUZoTIUT zd(4|{cHaeJ6^me9ilYy6g?ob@3ZgF%LvZ++hm70pZXY8#eN4l-7y;VDP{fEv^bPnD zJ2tuPJJHg<=IyUu^%*t;>#}El;fN>`IMZ)0?cbMq$W7#9)!Hrc`CSsY-jX(^rGJ@2 zPCSE&Ky&q|!~M(r+o$20C!^|MWr0f%J+20$H#lwtM#PVcVXv}{IjHnIWu-#-1zr z;drYjYZ=>JsRX20xr`D(aQjE>9 zynlb%4*Y-0eE*Md$_=ahg;}b^h=uq<3g)j<*X6T#&L=VJk0U^_-mllrumomFl(sC^ zqn^-?WXquGNBSN86)MWEa6XEWrbh9f4Htp!?ZM6p`we(D!%Nf6GZ$XZY?w$-G}EiX zw@0=|@S(6!F}&{-0IcsDmc#v-2;8bsy#<7sia!z~$9 z&at+QD{s1tHrnEjCPTKOSEDgs36wt9zr6~vag@Kz<3lY`e5a6`*l%zXa*D{tuOBYOzMu2ayi`3Ug+Ii6kTr9ob3G!X)Nj{`KWBHf4Q*s zB9un|j<2v?vDiDI5`t_y+Gib^dtq>M^2h`kssCi`;iX$rdJ@Z|GEl9E0clu6=H5UnSBu{0?pkBlj{-++A-L{)aa!A_XPXBh&lp9wjhllr{dW(6 zduGTSjl6M((LYKH?NSNIiedp|bjat1zb8J5Py#+yLs+wRC#ho*q))d82=ZhiIW;69 zA(dVY`J5z6#{+T5OJmUu`h)ze0BwjfJQHVrt9h?BUIQjalz%LDQ!QH{s_5AP@Vk-HI*1)?q;om58I3tqjGg$$@MEojdQqh8rwqx*aiAm} z5$p36X%|k7<&E2cw!arPqse+Mu_$v+@xqpmgyVy>?JW{U2!`W;plZGnjXpDX9xE8% zR*%M7xusGORHaF;f>~u~G{BWRS_2Qa_WPAUjs{LzaV(uJSFWkNskBFwf>C;Nw$>3n zqucEV?OubPBZG<`SI(y;wy27%+P#oho#yWN$Rj!uB0*pHaL5}gP*wvdU&5|nAw1|` zL#6DEh4-L&@mk%vvb*v8SGX^T?9rnd3G|o?2M>|7?>`ku_Kpenf8B}x&dwl@X{#n` z%=?U_D0GupuP0CRxF+fY7|VN$O*lkoI;izsWPNIk0>NI)D-6A+R187cULL6mK-te+ zegmIs>v*kPt;j^vPelg)_~a!*-qm3kgZty<4(M}+VcsUpCa%Rw8qln8jE$3x1B^mX zk)r)T^Z}isqtBD27#nU@FVL*n|08_)KVroH|0e$TF!lfHvd9FX zTFaxM(>!R-zj*%gg>UPG!j(!fm{ok3mj z$DpH_cZKW503oLp8!jOsA)`+5Kf7XZRO`4KH{_P#(!T^DdY=Lw zA>{y~KMbGC3$7a)kux?Hw)r)AVqh*TB9hE*`lJokVpKzW>E|wGssp4ucD*WP5A{zu zuF}C25Cyh}SOQ*u=#NqyUcUcW%SB<@ihb-`;v7x>SDGJ&kH4c643CU}`FE)#Yn1}x zJIQYM5LYL&<@-b{zQi9dhiD^GUovZN%@@__(f=FOvVW6kT@1lMmaE*^9d zIsQ6}$~2%5kC6bEW#INXk%WK-BIOp4drwXXHmF-Ek_*L!q0 zk>De6U6sbodN13ns2`-T=sjHIp!%w1XOnpwja1L9qXqTR)=Hjn^dCp7Ui%c{{zR|} zC4L`<6Wc!>h^YdnCHJAe=;4Dhs-6IU-v;u~?Zx%Z9wFtZX%zcUL)AeE1TssHvLqON z$Un)xwLr$d9E`g>>;c{OekBz##-!|jCDnejb2phj=AkFR%0i*c*|Wd(xtkIb-Vp3z zio+q1-!U5-=2YfuNcN)kx~fxD)!T^_K02KO&jDCz=zPrjly&3p*Y&tyVnn&}2*>8j z^#~F{(uUBU!KB$6GXN6*)gWs9>BbD9p5DP;kZw_6HL7$4QU*T!U5_7Bn@bz7EIQON zel&6%+i`Xn-p6pco6!za>7E@=5x-#57k_9NB||UmR~k{{0bzr*KHp2D^eFxx*w0O{ zBC|e(%XDWjuAOM|$il7HR?ev-=Z~fuDQ!+`r=A)paz4{YON}#-|J%f+goH#|QX2OM zj;i$Z^p+M;&+;m%04p4j612ZGs!Gh zY=CXjXlZH>t5hH@-wTumb)7Uu^|#DD6*0qG4E^|i?Xz1d_*!wR>%u;r zxFMhA`lvg@1%xd;mnr@x69r78l#H#t0Ds5HNXL1WnQT6H;ZSkGIOKT>u4fZLPPeyD zs_QrygC@A5WYZ($O7~$IBVSweD$Ire+bvT#@pl(i7$Kk*>6}c*Zv$ai$~xl+t>|eV zCGf|jF_1an`?rM>BG(2E#?=nIS2k%stQ_=NB-bC)kUYez<94gzH~Vro>QDD+8=G zYd$=?gb(7aDBYPZy9>pX{mQ{C8+lwzRG=dL4rCMO^1k*{=esDHWQ8nM|5~s9ELOJ% zJ9fIr53#B{Bo%#0GB&gyo(U3+Hk{$!@1Jt?Ef* z1b=QVad?aGcYJ)q?#F_kWYOn(lKMc5xclx3SmUeFZ~ll!$6o-96Ua8FA9pz+_G%1I zk6!p(lQz5R-jiG!Ehr&kTz-cMj5PInMAiZ#Lfn>n0M(b>pCi5D}Xgg+QU>N^c(D5AYYy zkB35`D#F7qY0d%TR90~c+S=N=MV%eiUp4+FyxmYH757O2beM&Oh1Yp)hBQtpu?Ll` z^K1l+^l@WN6SayZ|K0e%Tg1zMx&|d>p5bBLd=AM<#JK(X+*1%k93`^h|5N|BO??lR6)|4^`}2;Z0%Fj!3-qu{tqz|`w$|LW z?(@H!UcLI_;?KQ0YLYx6fwKoa^3p@?n$7lC=97o|##;A7Q=v+`^|#i#*!T|x8BLdw z41=t08(osqV}Ym-CDx8kZy%2Xl>dwDz^X~^j!bsXQP%w?p}VG%!z0-}jl6VY9=980 z)V_U0G_S2e+@-qgx#NQ0s-4Dh{3Ceq7-uoUICOIB>yvXFXzMfEZxJ-VPfN`Sx30vq z_FZNiCUlVQ!*~h%@h&c^E-Z-?oKq0;hGcj`bHiwf5~39)x-3_kmSe7I&XpcnFqN#T z|031@a2_tjc<&u)qn)YM5g)qwNM3IJi4l;7;NIOZpWthSuekZut$NIDyu+Uu zHeMCo?AN{7N&9t_D{mUigzz&;Yo&c8v@Z~BUlM}{lmh%*emKY>%H?fxcC7=S=m+tE zD7H?RT58X;PWFAWD7ard4b=0KiP-tz{Y=NobMEU@EnKHVOPi~>0B*WnDY+l7HSwnA z72xotxh}~SBGfXUid#xn6)`9kDXkx%@Bzfc7x#0Xbg8RU6vc8N&VIW#P5IYb#oD24 z61?yP)(}xoCcY!DqmrP`Hxy6&+?15YH(nu?al_^S2f+R zZ4oltZfIYm0O&@-!e@ts<~c4DoT^!hGqOOuWOs979!pDdc{S4B*_6kuzp-I45Wm(D zv@_eV75de3p>YIWwW&?zoPYoG@DOR%#Z7ai0#%9>G#^;AE34w!-GGBfCV%-Dp8)(+f!R!T^ zzTCQLH!~BqD)S|&1CjTx-Z#(S1fA)^AG&fZY6`#S7X2ei%MaZ6P=D88X}Lmf3Nyq_w0h6Xg{aA0j41!$ zWx{!S@Al=u1o~4Z+sLSy-2GTQhdXMi40(j~p})hN=Q1?qjRN1N=^Yzi&sW#}lYZ2v z#={|{)Rm&Ifqr}>klMCt=N-!x`ULv`{`x<1gBP7_%{vjBx$qf$Vuzt z#BrSgouYdk6fyvkA#w8&9y4&EshZ_zMt{vnn?CRrPk%~F9%iD&sC^@ z89_7YVN5#d>{gZEuoHB5UolsoK$jr`?B1=t6Siwbq@!;Z_(E#-g|_cH>!KW0>Rfn> z?w2k5p3yf{oDHE0RL|!TJjm;xaE_Df{Q>JggZ2W#F*Q@qj1nS2AFG++#ajd8#jW_D zbG-4<6hw*1!530wl7tPW(OkoaC$aoEv~92Jn$|I33oD8Q3kvZZ_qO~8abm2Q^n{|+ z|EyMyU~ceM*v|?nK<}EiwTkM*G!)Q z#hMblsXZ;Z%6*2DdKK!U4~mtzRY{md8kXBjda8qs=ZGtcWq}?In;EK2V>4wZ#Jo}$ z{4wi6FMe5>m3zL6l3(j6-p{i4-L`6gx#vV5E5vm)3`Hxmi2Y3#*M|jha1{#Im+j^O zhH0JwwZmhrdixuA8b7#^tLu!Vh$MT*Ld!v$2g)W`g*x0}{ljzy#{bC$oPWZuieRzq z7Si>z+=f1Q&H@9Kxo7z+KJc|_7iIQmGr?p|>p5CAu zsgd4%?eSc7!2};?q3z60Ed{GF+HN%-)!&vw)ExaH^h=Xt{t=dEiJ+s~<2l5aj*Yu^VwX#%L_+J(_`M_g<@Jb`e%5!lCNeWLqPTXJNp2k@Js% zhvR8v6I|7UQbJYEuT6RB#iEi^`t4g>#YZ7VT;JijhV`W*7fs>85;>K=o?|_`30@f( z&mNAI>xu0OQ;Z#V5HxxLyPH}bpb8n`obl|-nxYiiQKI%Qy>hZ`JSx1_SThmyR7p(> zpPM&6SkKt2u{(@X#V3)sS9!thcJihdJ0-MtpYXuCFljl-t<2fm^Rhx6D||nOHp;3e zQUK4Gfq0=^!q0bNn(~s>zrt6WHsqa=9?W_}QceUu0Ab5m)MaDs`}R32V2D1X{oI(;TK-fY};OgYYSG+4spc{RxILARMbZk z;6AaoAoL%!7R?l2xs0`u6=dm&-stFF8%Y(6>Z`lx`;iDK`ZX4xC3tqSJ=Yms5-md= zLZ*UXBF&Ac=v_ABFA-VOsLayPD>RPT9jrA`l@*Z=b)*IGRDM;QIwhMsk1XZ&Jt_g7 zL7vR*Tx!YdTMRCVI^ag)2uUiI`tjr=(t(->poNngK}*Bd*h_9_=xOjeLM{tl^K8N4^L zU48#0D={X2L@vQ5+v|v|p}S(^jsH?y%<}4PsL0Js*lH;H9vRz2dGa$sAr-Kf&o)o{ z7aeeGi&3;lqor>%Zp`n_qv8e8Yqsf#?)7@rq~kM`k%0j>Di&oz_luxZplBe>|CV&& zX5-8L@j!!is@uNM&E@Q^(#s7&KJPl1^5sdm_+DS@u`IJk`h25n5Aiw+SZQJRG?HoZ zTgBVpKl{n^$uW)AW7oHRdyWcv@9x|C4n?gU-cMdC-yfwWjG0fWi%?#n-JkTNFzR#} z!i*(pP8wm?3F!j{`Lk5?1;w=E&agauwsg_g8;`eJe)}utKVFxh92*-`$kkv; zxZls(bZ;lK=D9=man2~FCNXGRf}@*tjY>pP)pR3E;5>ubCm;~`RtLiH8tNm$D7d>hb=9=8pT(jW;Wu4oYt!nP>y-G8WJ}9tK6=*H2Ktf#4lxNw z4##0lR*u)^JdZAQKn>de85Q2fx!vf;q2m2|Yj>;lQ4yeF(v#C4&nzJdM=8+^?KI)8QmX=%?|uAZrSs{L3p=@F<3dF&G9hUlH5k@wy2%C;}1D#^?SU;MggaX#zw z(S>YL6(recWNH)^K_K8uZf@?s!3Z(Mq>N%4*H3JldLwP(`U4N(tj|%|C^dM1yZSF5 z^SdR3p5Io5%x>z4(^F+dj5BezPe>x?A*JU5Nzia*)_0+lYZ2SVu$U2m72Rm&42k;4nex9w*%+I#XP%H=OF^eMqF370Hm=0wcMdG74 z3g>lFqEdk#talm2Pe>Y?OlQ&`JE_u%(lyudtGSyr0R&+m@9)gY<7Q-2EIV|~u`tv7 z&+60U$;{2c&W@aEcV}Ehz14$$*{bs<2D?S45hmo&KME=XZ+mx_-)dH|Ps+|N%W9yW zb16YGJN;K0VP8`pM_+V~?=|a>`#~e0_3%|I z=pUvYCe`V3d?Hco$C2p=r}Q;$G~A%C*Ps8rW+=v}n>)NmC1Ic7-}>+6L@`|AUHk5E z!Zszty7!*KXZT;dtd}0^2GCqwpI#nc)SH|WlW>*sevx^&J%+a$1;a0WN%KWpB=DPsC5;>)hnhJQvTP-VdR7j_r$uADk6E$MNl#z*zv zSkpA$0HIcSTKZ>mk+2@oXmC{d8DuO$vOVHO`j)k$>U41pP6oY0I>^XZV1YFOvKsQ0 zD0*`4vS)c3ix`?|T@*g?5A?TIq;wG;^|=e{yKiK_-t}^~+f_cli}y9=!E+nu&H4P! z^PH;CvK;2BNmuzB{&n%Sfxdw@nSrkHFEy({@dPz5A4cEx!ny?7 zgdy&4&{(;<_HmEP-Ozlf?nf-bq0&OOg(EFgad?7VSRq+*q^0%7l;h5J%n!G*tj3Z) z)iAlW>yt_wV&q!+H35@Is!5BUVi1d8Ouq72t*LE2$-_)NY7zywJo6qxCFL0-5np2CZE0@uuK85s zyPQgM-q0tk33ufNvtuV3L4qwQ?2LE3|xaH=$ZLzKNd%dS@MyCig0J{CMVn z80o$7T?Wcon9c4I+fXkhO#%0WPsRwJ4AAuR$b`uaioUG|Ui)U5BxT5?j z-(&ZsKDUTXbYq~CMD!1)4hv=#`3ss<*i6juYiF;_217fu`JTRCWpxqjURz$wsko=Q z2hw@-wx7&w^7>eNg9V!yE2FP(&B*NA=sMkz>__1#2f0g!{CG+M580vz5t8L^X{w1P zJ(Lr2`*O?-o@8Oa!soQ*tBhuph;vq5NO03 zT{Q`TWIhqFXmCHci?&QwiOjvIOT@e#vU8G`R>>0LEuvbI@FY~$ zPb%Wt)3T24wL1D3`Qsg<@=IZe3c_wfS0qL7r{T?EkR&gW(ez-4&FV73%iDeFfjMAU zuJJkCB;$7`a9j;9!+CwX0X?M6<*o54Q<-~q+j~FyNFC6lpBEng@PfI&EqDgu@)>Dl zrN~iFSPAiYq5pQbjIQVmH|S(*3551qmigYw0uW7Bu{**H6L^_$u|_8R-uA9_%Tq}$ zzKeLqn|$22>yK`b)H*?gQTYkIX(}@i#L16`r^%%u_qApRmL=-e8R7S}?I2y3jGxLy zkE3|VO(ARimRPEVYa^f4ZnL0$!A|haPB~SXD`e-(gDYcgORC(r(uMJ0|M?&8=6T`g z19(&rACfTopCfA$GiS5{tlW(kMcl>Pm9@v&4@;O-Of=dptg`m%tdR!eL+V?jDx;%p z?y)*QSR3Mb{!CAe{r)rGk=asT*5a9d*a^_FpxL;sJzWo?bEQ!If#>4gMB>zvo)}Lx zAN4>zOgXxI!p;l`^X+5>dOG>t&e;(WxXYhRk%+r@N>k@n6;sJJk;t3MQ+q0)acg$( z8o%*d{+&+Gk4o*LuTwCun9EffOA|l6s?zY!mbDy1DV$0%`pUhyVy4OuYimpi^!$NZ z`Zq6t+5768dmhMWv<2v;mM*7Ng*gSCzVUi7aB8tvOlPy+rDsPfZISCD0V1q-S&{2k zGIw{M$rksFQy4CAvmduziZBL^kU}NSQX7XEl-VDXqwlDdQLiMB)#wDJQPU^0BiYF` zV!SOM=6DWL{J~JQwiu0O4wkponfm=QA`8WmY0$5t)I=Yj*s}_U;_;SS{w^j zoc^p35#Rpc&NZmZ>aPm5px{c@Y-hk2=of|*LDk16^_m-}OJIXJwyX?m9ZmR+5h|S} zn&Lxo>y##YBXq4gJq)(n{WRnVlA>r(Arx2(bT>By$vmS~CWI?GX> zvl=)H{G~Fe=fY+Si~b1Icukj2+r($4%C-=q)7B^d`AWq#GybcDoC%=K2ct+NC2F}KKX z-D_H-^E_lz(9)j|F3$lIw@Odai4y6~HlOFxa7^vN=t=RA3@4CCD7dUbA*j`AduzKK z2(r$-NIFTY1+T$*pz53KwTWB>?VC(U&aRJ<^y)!z31#8FIy2rNojJqgw{CjE97f?^ zwZ$Q!>=B zD@Lbub>t8G>+K{Cg>M$j{E)-Q1)kdj_>jZgJeU2v-%<8gXzWzPDVO<%tlh$!UQhF$ zFPQjt4U3~8tbwG48XsIe<}%yV;r=&8oYEm#_eA@n|hKl zncTj^Bqp)}e(N7pD0~9As2D&0>_H*GT>!C=E*CLm!OK^j=r!UJoe!BxinMa6XODNR zcFG@;9!HOegCl--${8)izN4O1tNJt)-R!+&p;Z`s55N8XB78$LkHo%?N;WO#eY&dq zGLExdR^1XCgwe9vR1Z1TqN|HuQ^X~}e!X4ykDFsX`!^>^G$5F;KAJnMBHKPCnjFYf1}+Blo;y%+nj@r);WQgKb34yp~x3sLbB zwC4E(Ti%szE~UHhrsQ12I5~3;-QH*+#xQ94PZ~BhDqv~^q52-A;IlFDU2z~O%Ex)> z_Ge%9{`&8TpW5@nHQTy@emY=sv~~ru`HC;WF@wK;GFD)f8o#k=&#iNaS@44=EEFbV z2KTFVkeG2dxeJ5c)5s++WT(O-a(A-nap~6UeFG z+Q?Ja?hEdFg4HzC30yp`uPZh1{WwRuckb|GrGtq8N~PBu)}J^JPIDd6#v@EO1|4%` zS0lbFe(l5XO!Y7+T z)rvixWP&!Q`PsWdSs+Q2m;)kr=SG$wZO~j3F%Nvv&x?ir%2s0wr)@l6iBI5OIxnx2 z;HyLkhIiB2Nbvce)UTwDC5e*byXXztiP{#TCu0Gl?XB+I!hCRi{e^fq+ zI?1uFZ5G_D6EnfhkiFrO$<2tekutCernggC@a>@9F{ysqzM$*&0w1HT#XMV%dk1GClCLl z@lOnCrP~fz`e7_6`U#?u>DOp0!nM5rm36S*Klxbv2>)LEC5JMaDmSf94IiK%GI}Gj zT|NC?m-70&J+B(`is>(lWIe~Qx&^t^umd@imsca_B}e=4z|`P1`Tvc%w~mVI>9$3a zkc1EdBq4?ecL)+(65QQ2xH~j7jf4b(yEfK1L4r$=h6I-e8h3YVq_IYC!|(gfIrqFf z?t5?CG2VFpF{<|7C0*27HP>9T_)lgqTye;~JqrS-G*auQ71)pNHR0bv9+vGCr5(gK zNC)$l)>d&2i>`g2tE)yix$yL|H!iG|&nl^`=F>sgffYK(Ye&-KS@v`k$c-+6A>7N) zA~)}a??yMqyuWH>U(%nee#*%WLjC3tewe;ir;}J`BGfh2M}I!CTt+`zWL?->$Uu@t+;nX%9jecLYl-iX<`fo`C=JGs?yfRb zTWmDH3;5m*Uo8YZgxK9yXY96q0Nnm@?>~5>Ey$^I7;E=@`z0##mn@vT}TeXIn&m{*LKVr}vmH;(3# zO}rb|@P}0knoslc&|W!8!5a)1M~8p|>>-kveZVvYK`HqNE%ELgLC^&NN zFCYyHxDw+JvGf}sT#vU(Xe-B$6c3W|blRo0sR+ERGXHkfjH}?~91NF-~hT^Tq(yr}}2-DK1)yKmby_`sh^JWxx^P<#_`>263J18koAWrhNhz zGE93D89SNYJH`T_=c%^1fh5|`cV|CRNMD}w@(zilRtML3UuOw|XV;mK%zW1u1+NM( zeik4*wcBI!2TO9FkcoAvS!!AxzE z$IU_(acL`4hK!md(oru$+Vhe$IXP_Il`_9ay1RewOQTE~Bd#-;aoSJihVq*l%rlx3tZ!Sa|6GHPOPd>58i8@?l%B%7|z zUAdiC7pB^EO8*Qh^$M1iMI5yXgAD+t9nE(3X+FOqO`Z|=FzjQ8I`{a0gG9do7i}Q5; zd|GcdnajI+Ph26<$A$RsHa9rDdKRXxpZ^?vEU_4st1sw5#S{soodDG2NtKT$ZQ8f^ zEkAZucIyegzO)2Pkznl>0>#y5zKTNz_FCKYP-#_7!}%xx0iRcfU4Z&j-+)M^y}5>5 z4K?wx^A2J-!G|N&ef0t;s~}@mW5V@|xWA#?YHbJ!q_=9X`YFJj5?=-EM#-%Xb5&R3WDYLB}?q$I_sl^J@AHK%uFT%?YMK1jOMu>?BZ94`*A0Qy7x>Cn~a*!+3&K4EZ$ret?f4J zrKX@$TTfkEMl|{Id%qsc#GORQiO(~G$g2H*{n3_1sa&IP?D*BOmEa=*fTr%tMvL_e ze(n)(gRD4Cj$EK`5|1aJwSj&~b!_g^W%Nf(cV7*6K8BPMwGoHjs%+-SvI&x6Ijm?M zUcN)R7O&_*KMJ5+bV|aiSud7yhi#g$t<4qTV{IV&Q0Cy^U@nR`9;QjYo+!sR|Dlpj z(ZF2|N3w<8?bvxmd`6(&bxj!qTTyuaUUQT8ogG;Srjx8ie4C>8qsxdC-v_5?s^sA2 zvT-v?zlAjER|(UGC77;uJt^Ov8!qSaN|^w#(Y{rc8N!Yi#InpEg@|>D>86V(lBSCW zp4aOrqj%X-jjQx8@T*-jm!wis1-lt<65Mjq?X*g zU5Cm)UZEA?xg!u@ZJP7F|1A^ zSI<1OqU9w)Y{kZ9nA}>?SqC$P%(ul{vXPDwF)8pgR@W$Oh4J$`@5&T-8rECD5L5>M zWt@HwJzy$Mau7VUHx%%d)*$qxhy>@$H9HCZ)gK8PuE#rCGN^O)9(HfA5*|*X#AHbTK$;P;EO15|B zJtouT8loK(NhYGDN~mR%zBrhLaCzMhlqG%n&)+P;X@`#IHS1z~`C$m#FV<~sVJj}v zwK3)Rh6o#7NX@Tv1=8#Bc*^dEW|UBVU;&fRjxqfvkGb3@$q*H{iu@89J^nJI{2BF^ z0QLqSRVJ=>G^`K;^}?CEv%pO!?)Vj+K}zc0|5Bt~xc%kowlEg$H0Vj0?NagGIh9tGty zfrT}w_^W}tF}XJ5!~+$F;19k!?u|F-NywO_yAYZyk?Z;J9B0SmVC9@+w0zI>_-oxG z&3--UC{F8+FHVBU_mxsJ!Fh9~nu)-Vj}ILWT_GqaDbZkvUtL`-ot*?`?MdE7r542h ziqQm!l-u{|n0roIKw@qZsEmhGSJ%xj%pG*Oa^&6pO3n`%*G^m7LwSfJA|h}H=QbGU zcXto-qN87=^o@;rn^%89XM8D|U7a6C>YD%k_9!`+YpmtgYl4@+!J2ra&v5Hq1tZP4 zz4Z)JMMnw$aek`|Dyo9MTa@%ZnRc6k(c9}i_;v4&GW=_g@Oai=-|VZfWCw?3zxkznv|$7=!hs+uH=FyLGg)*A1n z1;#`*=|5pF%QyP^vj$L5{w$Q}*7p_t1d>C6fw+*xvp(hruW$bgzvi2SAMfAG&rffaE|UOs@^6)n;pac$^7$|q(ykb zGdQMm=?f3I+P2W`@1s-umhw@H@L0@!z8bw$x?Xan(!lb&Bg&`kAOGaY{ig}2y-N)b*mDIdK-Py6R{%*QWEeSOP= zs>BaReuhRrlDP{<+Zhx+gIn8D1W$q9D-=@L83vrS3<^_*TK=on#%?j=%)n29nmiD% z!xcO_y^_fvzZ4{xf{WStrbnA5&GWqZ0& zRnD!ChA->+=?aei@|(Kj{+c7`Ink{!TP|@c_@vtyEJGb2N&?^O^bW z)<@Ma9q409P8!=?f(^bDEyMyJ6Zn#n#52qnxP-{Y$OZe!6 z7TcS)(;{C+H(!hPu~|mpcVZ&kmtI>n=@-S+E})c&aD#f^d1BVsp-^F;=H;5c9M-Yj zDNazF)zUywWCt5wl=#G{^O8zmezA6?tN+}p{zVqfrSMdR*-d06rb;w_jUG%Ab$8-* zvxMGHE_*hUudqdnJ>|}q?Q~jpso`N6y?e$j@f%zIOy4_C?)b}mM3^t<7eZHpkHCz| z++ed)zwGmrb;*u3O_dgM3g7rvVUAp%36}XUV8rGEZwZErCZAhFg zaTs{*XL7a6%)IN}p-4o{^rY_c&)?Xrw*8bgo2`k=S>`ib!3SVT^3eJuwZAl;GA%Vk zuRfGjVnK!q=#&}go8rOb;}yN|fO&g;f-k}U+Kl1Jl8XyveKWN30PRMQuhM*g&#{Y{ zc)(L{4*ubKvF_@s*HK*p(yxJK-F|kq=0+;bVPAU_q-7bv-A5bHP6Y#bSYeTMO6Znn z@#F&+d>VrBENbrWrzB4!Wtc}z4Qni}?r)~-AKBD)FFofnvxb$Vnft`~=Sk-Zl$KF2 z0*DdAld8;XW>XPa_q~sm?oBg)P~R0yB}@ zkYcaV^s5CQGOe~hH2amW9f0qIK5(qpoV)9P%V+YQKdYI~xzr6FOcXsSnaDj#uQV^m zgWLgn8ST|eZ*Xxih?>U(b*PDjUorpcON@(-=iM_<){xd8_`yW0+p>iH2+#MWQV(`} zK(blkN`MM=q=SxrTuk;3m-CL2B2m-*==}NaxQ}cVsZ4_U##5jj4~Rm-kDQ7RAJq$O z*QDORnwR->IOM!?+}j%}vx--fQ1+-MA&yg)>DP35p-8gfdDmz7Vb+7X9(V<)G`jM- z);bff&TUr%>(+XI9m^QSv=sTRAK1j_PvXYJu$_KR(=5yCZhzhl{p-Y=i{ci=B@3eN z7eYjyJkc~yopI;W(Mu*HsM^!Z%*_wXWlNNdzKnZDGt#3fikr^5TDB2W5xC44Xd%_( ztb$~GqEG0(WGc`{6OXsPkVlXN#C27YAejZ7L{!BjbdX+{4^Cxsj|z?vb45!(rHXl4 zXSMEw*!e9QsM!9hYcr&Q)<^qta`9&%!%QwcDA60W+9XC_sj6;e?G+JbVPE(!eHlw^ zO$t+jdc~v_U(`j$)IIr!g67_+{&e}kW-#!R0+|1zxyks)O*RT_x4CE$d)5l0R570D z_MO69Zg9l0Y{r6$j@x=J&(Ii8+Ke575pQd*ey@cx%bJ6^bfV{NHhz}e)H+-jd;9MS zY_`@R8xXosU)0l+!xxHzN-{j2a~7sI5zwOfiBD%~`j>M_9FxOQ&qbpl*cQhpb<*Y7 z+%TfEzZ4aqn>lrC-(2~f`qT6($CyY0a^7$*6ZB5d5)5+RgK+bT>PQEHJBzR-d6BnA z*Lziu|Eo{uTz6SrB?y|ah)JLnJiTg!?%<909lX3tV)8JOi=3_*cj8OzHLIMguOBD| zi{ut=|J85yxmr%pF8ktVp2e*8kBYbs&OfT;_m~@#?k5YI&XthgIwAKKz@m4E-~SQm z?LQRK|7QgIe}xU+VV3_pk@bIn!o%Qxecqef)q2lE0xjMp#kjBcz*XK22Vy66TX-*> zo(4TBCp#Eb^@qiU{}9{;2xB>P8~YaP9$J1|yGsD`Al3N{*>~CUlemK`zpgK${h7P> zJ^cP9-u{2%$@~e;$b0bse!jseGR1Q{iC?)Cb5*FR=XuL+q-<>)(PXu+V}Y%i0s=F6 z3Mm^*TP?=rQo46)^6(nAO)p?EyW#R5VZLu3MI^ zXgQq1!a`i)voz@eQH;xZPoz3Nz6rY3IJBO1y^Eoe;}ax6zkJCA?cdf+_h!nXhmg@{ z{D4z_*vW|-Y?WhS*_Xski+p27lT^!y%(ENrJO6p>s8tyyKSl3|(srN7@BKv_gBO@Nj~t0zgUP!4CMIc$aykb~Hxm3~8>o^4Ho8r=wS z!$pkMDa+`kNl(eMn<~2{64eVE&^Y+0Fc-p6C>xS~#!-_vK4CJ-<+tNy5!<9J6o^;R z$HhK<>g#*+t}L|p2J6Xx#;qIWx{jCYB}JadN}ZYAty_4@fvqV-m)$e#hB2i?s!R60 z3(LQ;0AbO5Vqf1ju^Vv1%c_lNrI_i0oB=80^!(PGb%jz*R!~tMofNH}oPFw0ow9gd zlP0A~%u8zE;fGL|ZpID^{jM5EF>M`CkM@T?hr4*6qe&WmzMFF!AFXJR`j@^GQJc8j zhs@~MLq@cV(WJlCeU2IfW^(EmM6}_lZ_e5S1YV;wIj6n!p?$tT=`N9)Ba$&*n*<~; z|Cm&DJmpLSn0Kezv4vxPU)TP9vQNtGZTuBKvFg3{VIB%%cyR7DZ2Kaz>VZ9F(N%qH zR&PDZjLI$>Q8xvqvEsWFpx7`NhN^~FMD|av~}!cy}}#dvkH-KPoxzwPYe9$A<%E z9}9M_8mGMpYoudTRVd!wwcQ2YoJHMB&i+{Ih{o!7`IKP7tU!Cf=a$^&moc(kKT!8I za&o)=1*BV%O!&8!q>Ox|DrG4=sV;#kXS$p{C{T{H5G#z2j0=y4-Mr}kj&!A0X{I(7 ztTJEpC+u7Q{;ih}ww27hAS!V09%sPIlk_ulheJhpofEgpN)7^#f81x^6m-ZM7djlO z{zH(2*`tN!<_O)V+}D_v_yZ`LH#nT7X)MsX&F=$vW`@m4bU0;8!;_k)wnC2Ve6ncs zb{+;6JT+5vp|QkAE1rIwzwu#{?{_&Q9S^*AxpA}J$g(2~Hf{pfvd2BsJGn~yj@n{4 z#O%dg4PLX=VVjKhgyn67!RKrDgx#sdWnd(Nn9qDK`p6{`HTv{G`m;t(rjr}+zw@@q z!7rh*!cn>kt8j|v=$Ue9o%q;3#55QxoA!sr5(}lJN;1HYD3Ac?S@Gz!U;c4{S z%JmC7%+lA-U6lVQ>FUHPp*g*&gRf{I`US+OeI>1 zVAHpoasFE~oW;P&@(!s2{KSmmU-;7fl%r|rq~t0yYGp}ovN|t8`UZcyxnbX(;?3`= zVbanY=iJTVIbJl8xh16GU0)D{A2w%!_UC&bTiQ$`vMrZCmvbEO2kyjSuxT;i1!NlFf$lAo2TjwX zWQG+4I~07~R9NSZ$=lo9%@OQ`P7+ z33MjiNe;JCO3$^F;tBZQFwZ8gp3fZ`g$(-=hxae?;CXIeS$z+Hk*iA$JzZr&vLrml zBYm0Xw7C&6&!X3$D+AjBoe*(-2aas*Rf3z318Ybdy#%3gTpygAkJB&LR{o|vvpSeG zBim`T=LU=x&A0?A>eb7pUUqn&A<7c2o;J3dnVNoR-re0z;k^kM2Y6=KGzVlR&Br9k z%Z?+0qufZ4=c&pO?TNTd+6NaT+Pjwy0FF(t^UkJKjQ63G-Go_r0j({PEhR>O`f9Uq z-o(Ru9gQPd+&f)^q%=>FW)F8enBuwl=cYE&Mk1X*c$nG*Xu6YyMT4ic%h4&K4!SNM zwDS}OntcU)k%L5!U^*C}BpH>GJruhCM9wq>m=2dd1Jw_v^hPw>nt<#(5j3AtLLQuJ zMfI#O9#k`biQ(5oqu`C}pSZ70$O4S=ld=4A&XW4ML2eWMA7=w{*1HI~MSM^qv{iBY z6UlvJzf+=w$2QVgewA};jAy2dxX8)-;**%SFJuvx&V5Wsvyr%nO*P?5QP@n}*_i(8`GL;_@sYFN1s35$11D*Ug=Nlrf`3#1o2TJ7)9=#r zvsACofU|={?IJg)d8de|*L5a+ik%#VyBD~GUkVJ0vQNvpuhYT^#nH_ z)(GfpL%|9n+}p5p_O0e$;uti22pkeS_<>t(Ny2`UeOPGb0? zR+TTB&rUYn(oc(T`qD-t-H~UkhI@@Hnu7$i++Jt91x1@Z5l~N%E~9Ezzt7d^T#>lk z(3c{2r_-GqJ17-*`SYJL_}@?LuzK>O8vqAO?TH4SR-=XLczvz_fRCj)|6m9sJeQ3K z9b?PB*33|QWp2iP6J-a*&^wDc3w>LOHDIxI=^m){!r}AcQv3@xO?FyWI;b;sq_+84 zqK)~<>n;;6mh+8)Z?t=hY$=|=FFJ%s#q!V;hd)X$92^IlOibhIa{qiKUB&l0`Y}@2 znKYiyIf@}4Y+zVtT!Bv=Ji%#!Lh+B6n95bErsBzFU^)ERk?;MXrF`hW+dDT8dF?6$ z3=!{c_uyT0Gi+RojV7U&-uMAFG*E$j>soRr+p%(6gY^Za09%<0R(_`BwppM3LEx!3 z@U|pJHa7@+WyKmEclv}Q5Nb%o(_^UFxLY%{DE%*25ztP&&n6jUI9RL&&GX&8X;Pns z$F;B(fj`umi)1qc<$sBhYjnW8HH0amm5S4A|q9#&uWCuLE# z`9{kI$86-h?t2dFEvsV5j^1;qgXPZ}YT`@%uVLhA*wX1U+AdN%C8}>q2~CRRc#i&N zWrGQ7T~@D(rHq~;Ul)P1M=^4Z>*++VxM#boeg7=5=rxnhWt$RnV6&t-9qD~bEdw>7 zcLl5yHM5gwRv{EGVruhu`CNbXb~&um=d!)1pK5uda8h?Kht|ByuqJoPN%HuQ9|i{p z$LY>ws~oFtO&F?AuK5Dd0K5F9TN`td|MBz_BQ@9xr&Y(5m=8JZ9_ao8?p}dC%0bE1 z%x>#)l}1evGvq9NU-jTM53jpAw}PV`u^s*4%02nF+|YtTT>JDBHRqOev+Pqx{*wbz zL63}DEc}da)uai)tDiTaEtM*@_UrKpuQYp1!E)r_*;!dN5Z?IIV1i@?)#M}Umq0co z)?812PY&RlS%&xIQ(1>TTdIfupNk;IR^xDly$%c(uJb zS$$HPpIM!K9!13)u*%R!e!$P4#D1z|4j9vm(WZ|rN_ybRg`^!HnXGBWSWIVk*`188 zkM;N>zHq-a0(u^Hv^PK9)}p2!rJO^>bU}(3+iJ&=`4W!!V&9=h4O9F9s^y- zYLq5j#9ArW_BHQ*&*jmKObwrPWl-Z_mfm{#_LvSaA7Ihb^Rt9n*MKrP$g>I68knaz zi4j^j&HhyDn6wAJ%Ztu&hGWRP5ePZiN{Y~u&Ev<3;}?GaRrj^Kkkf2$Y<9S)==;~c z#$Mi6W>gCtWKqkdvo-~(}yNp;!?S4=5Vu~ ztO4Jtip|JbB<9l~CT99VU#4^=YaNAw2tqBVXu6j zc}%XV?>zaOV8hccQEGLdPt6LcG9)CifQ6C>d=S2cpzrP~xWcDngnemZ$UPhDh%9I- zPb&Qa7XIBc0~2xcXKtw6D|$`FG7aJt< zSWRP+;`wcd-y18I+R!RCHswq9jfT5=io$!HRyHE>cLc~ph73D~Al^VGDBBFvO=6vW zdo_S`!j#>(=lA^+yyMSkm0kNewH>il@l*?;VRwQBtAS;eYy$*Q6-owP6W`WADc$fc zPTXVGkYG5?LYo~P09u{ulegiXeWMKI9x5Z4E8s zQswkOmxkm`o*ovz1(4%F>s!5#s_VM7-pPkPLr7|`u$SgwtC;7m7Z>^3ToXk}$yx}_ z>+#6TL$^X^X{cvGm?P+9&qy>ni{|vp2H}U|_4$hu$W;A_fnxUMc7EwwXVCGUt(ATI z%Hk#eThZ3u+(d;{d^es5X!Jx8-nf5}5avy-AipWAJi^D9Ux8A>6LPbKlawyvIc9?W2amx&W0e_O;P&C`?*I&YS=rgZW{{ zNy+jB*(Kk~P(P$eVb?g048*4(?MCpiE)k2KdjFx^kFldqwJvrhuW%V5!KFuEVq0XV zBig#G18Y+dCfdYRpuWE;Tqfo>Ri1^6idT`|{gU|SQ!)I5Y*?=O2Xaz&TC;oMC=;;< ze5j4FVX(bPUXYYsBqnk`CXdUkW%pvO5!JfOem!$CIaDeP z0ObjWM5N=FVd?y_tNF=8zdfI8gXV~p{zYL5qzz+>-sut60PVlAfY0~UTB13)*^lio zoB2Bs7g4{6d?PA>+sk$Mv+{>5X##1V+{xIi%f4q`+MgA46(4p?zra0TDRO_H z-`$7Ik4ROdEV;&R)_K0Me@4QXOK*Hk;GY~DjW8kbRD@joRZ0n4<`=%P-Cfsh4Gp-O zOSy`{PE5k}*u4=V-LzA2+&n8V;kL^ETUv7NT8w?YB7)o)85xPP$f>W_DNsvDOl$^N ztOqxdMZbx6mk_k&_;?vRO9nigGQfy6Z;bF7aBsdg520*QcyRA)XF*{h12c0PpBoK_ z_g3k5F%TZkikBhUy`T>DX)?LknqoEoO&C)n%2Dz00Nk(|>!V?5Y;PvfBoKh|Uiia> zkB=`1^&NW3cHZL-YG|}FHElDmbaR7fGi#y2#)n$}6>O|>tYUSYtLA7X!E1OIEnfUM zk|gX1ouZi$5VK9|d$s%{6?Lus<*O{P)dhX&+!UQlNg6Mq@+Z26@;!y04bLgjHi#2j z--~1Ah=h8vK7xcsMDno!EvxO<8p5WXHpijIPJ-+9PryBOju7@6^z8RhpV;=uuKrGqJl*ZWoN|Yt)zi7x1{o=HxF;Ys=MuhEOfN zT?xtUh;K2!KcNflUDWsN{-598xQNzLPJMKnWqWTxw09kbPA4BV+1S`vkqV8Iq5hF| z3&wr5_=W|xK~5Gf+2QZ*CGrUdzZ1w*6@Z2 zr{DKWdgj2;N7+mHE+l1Lxzlz1b7aA`X5=fCNJA#tm0r9W$!R&gW}32CKhGbWXwD<6 z2ryPim!lH<)KA>%fNY*=LS>=Zxo>9f#|k*6BXtVI!+EF?5trn;HP?Ex%0>xgo`__k zX|D4{(X84O&F_1r58P^%e`*-=WQ5xW8i)$^O%_iPG1+rtVhj;#)t~()lrW48A0QYk z;J~k9RLREAWlAyfwyRrdR`Fb3$Wx8^%%RD$!vK%ZOP_AGZv~ue1yGXE-38MJw9%sS z4^j;H! zvN%lV^zZ2)iR8nwYz2Mh6#&`6$wQwrR!It(GYktDh!vjRhA?bA;`~TeR>?!P0tm=G zZ41Db1XwpZsEZE;r|J5H*6a2lR`@r+^WIM*Wcba5?JoQlF*@-xMVyjI?%%3uY;QOAUa=*ZV!!&K7iOIO$Mxp z?V_A+=*_XsS(fKOAm?V9!Y=tJS)}?KQg3~Kb2(!!S2E%C3qP3>&*XkQ;fjOxh2QL= z7W3tm=8u2keWnhdJz2#gcVEe4p_~VT>PsJ`09`u)_9#Yig^7f8llinw%ABX)G)fw} zwp(7$*HI_vq9Ts6Uy7OxA%j}aP%aM|h!|Y#FYC5FHtY&w-T|H_oy;+^c-_T8EFn{H zX@5DD)HifYI8$ys8#4z`qu2ehc@bNAv_eq3-g2=X&{FY>%MoFpNlz|G=_8&kp{RY% zA|KHPA{mEtgHw~Z%}>Ja-&;Z(@B-IAkS7Jluh^^AJ9f}ATGV&7;9Z_|l9*)+t_JSt zLFq;2%vOrQS3kEe#;+3S99&DyPK6LOJtJMyFO$34<>-?qj?u?&ucJ=p%z`zaO7o+< z60(cMM9YFLD?BN{`oL&P#4P&}g){;V{pq;kmEq-?d>HT$4+YcL_XJiX*JPLc9Tcr zi|iXCv#1Zoa}Z3+_SsTn5AXG zQadGfq4frs#(2KSO$y=hrsbfPoNGS$jCBD$KNnlH10D^1S>iva9w%ulZ2K+z6kCSz zNoLZszP;7G@!1~^+j~AdTofk?bFy4+7b@{Ih9U8UzhT}EFr{7@1LGCEXzsSsdLHB! zUI#1}Qe-41V(TnT){sPGY|K$o`U`loAic4D+@eiK)V0RSn{B;Tw( z$K{32gH7I}DFS7%s^+nXcAmUUeqIOvAuDSZpNkr2_wcqjsW4?2)4w#Rz{6>Z=FWO+ zq)akfuSM`2APJHk4zr(yO)&NJcc+SVy=sHoT)XRjY^ZT^V{TlN)${?z!KUnx`m56jKet$9PU)LQx2z0GO2Q*daD66O> zxgvUln@3r{w6Yec2^-mB^f?oUw40B&n{XAFSFlItOAyZhczE*4YF;|9$KB3FmEkY$ zPcFs8GoS{6xX-!DpJ^Q!>jYwsI1SItp zLn?J4`+Mp=EB?DlRFN%ZLuV;$BU6r#70vA8&K;7cKF~ zOP9u)W&>N$5+L0DZp;(4`@N!g$2=PqykgSBTT$rS7S_$(2-gpRFsGB0^Ep{J2)>8L zSfBJjPik9`Ye`}))RVcVP0(>`V#0yNT!xqCM~+I#wf`TAo~&o(VGgK`o_bsl^>q_kv_NrU9vT*_8}a4{QfpH!s0&yh&z+9D^$0Sqtf7K%bOJt9_vEHt9_g~8 zX6jc#XT8UoS%FX$zOc=zWH?wT+4rL9DTwpWWvU}_-}>apAiu&}>#$0n-sBd~7Ye}% ze#+;`F4KY7*|c^O{-hi9`1ihgfE75t2lPnUmxR}ocYRUJersr8_QQ>}*h{-PS&nN7 zJ7bNN**cG%32io2{eEc~=Hf!bRCexK&i4h0q9QFK*F1!bztXHW76wZ>bd!?}oFfzR ze~?`>Q%P%xC;PF;3!sKsL9Na!)uXPPzk))+ww?W4Z)QPSYhnh{rSB`kRJWVvoij6n z`^x3&QLfSYSiy`c4$@wLo6>xa^p`=5*w`|YE&Xe@BI|~D;ct55WyH`C<9n9P=)Fb< zOzOsPbuBL&09|ay_)L9L%5v=(m+_J2%qECx6`8@2Jej z(@#g7jr^(%$}Q@fh0aT^yhEpc*lA=4rm)mCv);HTBp_xEr}J2SDQE2OlQk}1?`Po4 zJu?#lNcpQxOw0ZxU9Ow%x>s6;@s``Jew+UQs=Wi@7AHApZnD{{Z=V#oA>bGq-+eOo zyTg1V$EUycyR4c_@;W>4fVe&K!dIUl(-eFGOWhr>({2@aX$S{jkn$dlpSp~#N~!+< z%!2ShzKc?dqFe+#+u`5B8P~6qOIH9y=v4Gj1BI3BBIJd9iu!Mt-k3-qvz~pX3wms@ zDHCYuI!yoZ37*dB>LDFRlU1!jYa>41b^U-ok4wgLJ2-m2;G~=XKJFwJ$oH%sjt`ye zI6*mkL1*y|<59`YDDwsypuW<*Y}}UECYIiRoDU?qWJCjr5^0Q$T3)o8; zZVeJpgU6PX zd#J$HR_}2fIT3*~ z&9VZ&oI}>y`tt5VIR!ZK^w*y*k>CY}*Z>IiCjo}|YfUqCp+ z`e_D7$`GSv%O-+t1D`BfN&TH6Y?FLt=E>wuv(}^Aw_MNZ!WF*F9u0I6iPR@-`I5O(pS=sbLm@jLMAV! z%O@@m&x6lbx=)iDZTpfPgh&_n+wvlurOyYuh!UT^#=(~xsV+N6ot^G(%icJ)(X zwXZ6PsV60t33H(mJTJ@!vC5k}+a%&N3JB8){NP&7CaR7TgL=T%m6I)T^CmA#;y;#m z;?k%eNE;VqIyyI#+A|qbIbOjvN5HBHIe7@9*6P&hYJ9VjJajZ9O@ExQJcbZOMz2=Sh4LwFC z@Io=`QuGzp&`xhke^cWX95KbmygG4_J4ce_xo^SI^pu5$si!MyhIL`68#M0Kuqn|R zwqzn)8cb|8Hb1?#Xd)}nxEN?R2@RVWf6RC4%6*NTm?K-7nRg-GF^)YtJ#n~^D++}b zSomBaoNuV17yKio-CGNb{C}d=z05}&SO11whXTBW%WuALS0aO}Pv?YcP=SKP1)#n0 zK3k?FQ#}K(V|ZRswR`Y3ZIy~aLWQ6n$K;34M_QiMdv6m&Sgsj)YHFAia+W5-d3pDy zg6aw0rb6F1AN_TdTQ|@rdPUHiGvhxs9kTMvXz7JszEGsA?7Z}oX%BTp2G=BeTid@z z@mM7FWoq255q*($>-hUynkC6ke)W6-(2fa|o!@TgUvJbdEEnM%?Ch&iAyuha&h=Sz zw56#$A6)1uWjV5^kh?6fV%?~kDz-u)m-F#msO{Rb^qSu{RqgG;oi)Cdi%}C@u#q4& zDr%c^QZ-lL@^#?hPD6X2HH*?Kv$ymchnJjr3LL7M2QhL3J+_=4Lq>|!<^XaJvh=LKk&(IIDksDw_7hbVwRe<8(%Y?Wgu}|p1-O~v;d67}n z)7$&X-^A1wM(+7)KyBFTGowsTQU=)Dy7eTq+OCx$i%z;nIqHxI^j1;8bl9eCBDfU# z<~a}j0&Ei!8Y0spt*ING{X&}gx)Za7t@7it(ob^wO)2f+d+pB41z7rQrAJmzzH? zs8|}ly_@DCY_|)NrD{#|;`=6+9@#@*lrie2uk(3hr>mJV6pD$-qGPj?rq<84oU?NU za33DW=XQ2qTD5`L-WLF!Ty?Dq}tK|BIfW5)vu)Lh_ znL&+j-@C2L#8MXF^kG6C~ z#tnc#`?7vlU@Dz-ubpSH4_~*Vs+M(Kgh=uY@_4NGPGY53{aJ)jqk+YTkrrX^1p3o{ zI``|b`pV^G69@V>0?cO@hPm#$XgrQuYEB#w{MDrGv+P{6yzo~E9kwNkhipz)#5ZH2>aLFDk9e}vw}RwHFfVkrgL05QK86}^H$jrr~m z4&!9!_cv)Wb&V|($lZII$2j7My%*(f*~UM6T1*@wUV5ILM;!hl3&;*W*8Z0G_)(MH zukOnZQ7=gx^4AuMi0RRhrkuLLdA$$UZJH~4YHw0>%}x4%*0e!uP(AUebhHs$s2eIk zOD+sZxw%!V6vXwemgeqGE(^t8suG+%l=k-^e6vdKuM2I%c(^kzOmm%~;Q+oq; z=STcB8Mb8C3+m9`mqK&CnJqR`Kjyxj|H%q^GS|%WS zF=OSKAae75tD%dr!C^}?Yx)^WUGXHS1D-EkIBz2XQ z6QW&Q6t!S=?D0w?Grq=eaPR9r&{r?_g*|6{HC6jltZip5UDnKiL z)k%9^w~KRcq5a#Nh%s5^;svcI#2t^d-qDZn{(;XRk%Q0%j%Wqt1jF`Y$FiCr<}SHl z!Hf@iTK>7T8|w^JN?oBuC01EK>Bc!+pV#--EHL1v@hDBT30Y&v&_it4#7ynf$b~@p zWxwT8wZ&m0|AV-tZJYqX-KCL0aQDXDH8|Z^aF^iT zfk5N#KArdderwj6nLBIN-0#l(+g(+s>Zx<;oU@<(>omxvxJm27 z9>*jT`{1i2Asv&cjYdvpierxx>JfT>hc?4dLqaUvCc47!YjmPxcQ(^m#2l>@#>1m! zy-N4DLB8fjUB195I@Ml_UMn`aQfu{64gfF5*R-rm7l*~#H&K{Y~^=qDjr-J z!<&F_yaQIKG48|pTg15D!}OU5Pa$1yejxy*Yqg?RZz3o-$z|s*RKm$FL?Df{9B*m> zJ#nxN)ghKbtV=(hT^W;!=7G7}q|B&_-tEUxvvZP##bq+ZNH3}h)9;4@g{d94A6HK~ zHQ$YmM~BgdJTx=K)_S0BIG@n^5c|79p>Mw8Q7qF~`JI(dZ7Aubwt+c)iRMqcUX0c9 z5XMcdgh>jTv0vcavbO;QSQMX9SBYcDc--^68J#qp7DeUXU2x6`)BO@+(9+P@Atv!~ z*}E15ee#cGwLG(=o1pg-Yv2gdg~JOatFJ9-27V&4Y-15(JAKV8?+ERhG(Tw&Obofc z{$l;3&nkX^-@o;bkJr4QxPzC1hMw0!=Yiu*-BN8Dz<|ro3U(mZ18iL&Vv0!Y!L+~e zbNJeYYdxlc1X`m=DP$DnI?9RG1yIGLdK}P~0Dr&nr>90{Q}10Bfp}OjRR=#jS=myl z*KLrJaHTbhh?+}5yuExkb$_g6mHOZSi05Vcv__EdS#RWP8n$M#q_dF7W{r$$OJd^o+n4o8kT+fc zX>`GmH=4auzZL-!&Nwmc{#5fF&`q~&#ct zxF}wB#Tx&J_Z1$%C|N+Dy&+SZ2dqQfoTpzEfw}nDsjVcPGOM&HT%rP^K#+=HwC~Hj ze8jmQ zI;PrYP6Z^ImH~jo@48RVP97y5t1ECK)nlZC$Vcf6I}-Ul*E%iR?kb|7f2q}qEavRCQaH>SxYIY=(qbFUm{SQHK za2?tc=pGKPQA*_k?{&8h;2h0~5z(CcWt6mR8!SA_9rDA=^iDF{zrECrr}Q}BPgiDT z<|xm|MWG`Bdp;4xt2#Mn=BxV?mREm~T@<=*$g81TbIo+7yk7cEd=6EPdE|S4bh{;_2W4BUpUScC+&Ja7(M&(i?Gu|ln4-rK~nUC@5Eb--dmHM!S*OCE# zI<~_Y!BXN#1LO0~(`;lSQE5S0IDjGIm6_~R^oA*;uX&771oaRUQE_r5g2!a`6kI4K zJwi-=24Ztt%goeF5FKIU7PHbg7anqSVvT)-CQ6kKMx(;;XMw`V_e=@`pdOzz`>7K$ zJi{CCN#*JJ%3$!wEIs~|o;$nxZo1m-Tkxo7rWJUP#?} zKIZx-fLN6?fc6P2sZPVmTiId4evUj!4No#JnvO|0!|-!g?U8*K6?~UwmEMG*sf>6& zOni4m%A;wi&5jLnCWkofv7dc%B7-5ukg&Y#3*P15Btt@KjrnDD+bFyBYZ;_-ZLYnb z>NaN~CV)bw_(?ioWw2|pvAiKwKpXjD3#>$8msWX{N9<0B_u$7S0Dvw*`MsnUiaq2^1ua z&y+IqX`!l}&Q!`U+Sdnm^0+VOU+*lt}MYhOuo(Qxi+g2NsH*h?wK{$=(ng9i9xs!o2lD}!jJ12WF{J22BoLME^iZ-+?_B)`_@E_HF z1fKBvx~;bX4}G}vT*P0-7iXp!EUPNjYI`$JmHqNI$P)61NamanjFcj-$dOBY>Fccx zE9WkF2~xjJEzq3NOko)hLA3j9gtYyHHrECpEy;w%WJ;6!$D5OVc>~DCXN`sQAQNIo zfl-;Gp<`lH-{z=mJemt1@&~9{#2o%m z1_$k`=B}G<12_T|Mz>9}hdb9!AEPx*p-vUEh?DZQg5hCqwl}8YI(EXR5=uB?xUl%W z$LHIvub*OB^8U`)OU&8P zGip7)2`()y{bPj5XJSqyYHo>{5`R8I=^%FF;i;i<^K{#efnsL+P-w3vw7nqv-TQKn z|6Xou8%74EnAeUCmv9Z1SMBPR6{VMfDkz7eG1-y{Y8wa%yP1~R7Zr+mOOoQgL!S-M z{xzvK@<3ix+4_3Hk>a_;0H4$a=5G-Q$iDq^`Dpx$*~GzOEXkW?=2BKvOjac!`2i47 zcok3vm!o_zE-fhmH+g_~yr_KN=bj@ZHcCu36>fx<~73P@ljagv|$n*KFjo*wk z(>05kH8~fRu*qGFO>ctPoN$u!r1^1SJ=iV}_^hU+9%%a%1guudx+aL{wtzAy_o!@* zObt(D5AUD1y6i&$&f|!>%)91bv4OaOBo;JUoUyJ74UE3|h?Ru`6GXFB(}+Z>BFxQ( zyWXbqZo7N`w4B`RLj3Zn;@GD0Cvg0Bl9;P?nY+W1tQ_4?#`oCv#%D#i+OJbw?~D&Gi6oLS<2B zgq%F8^8`RLv_g&7tsxz$RBhFiUZaun$~wcloIV zO6T^M_g7|C7l|3JB@^?Hxc|fVWs}S5sZGK|`YeqcNUcC-ltH+2lVtF;PqCxRs%K-& zK#+)!TF0_kh6B&_&sTa-Q{8!d*!H`G4%KNBe1~YOM_l~I82e`&Nd=|$!E+acD6lRKZdpW$XgVRTU+wE6x3u~*zU9wmzhigf~7p{HH`xyl)s&F zbffl$)8wcSu}WM!epWM_>kpx+Z^rsIkOvt$081y-_kYhgge2bV-`RxNlrQbRN8zW~ zrM2ug$FHrmC|+sX*_ttxq?~{wzEUQMS95EstjYpJhSDgnjE;^3xs*qJqQ4x^92>+_ zWs!C;2{mh88cAcfccl!NHpt>U?2Te2l#BIFhDVM@( zNlI*|-;DMaTLk4st#wgq_}ELFbld7fjo(XuXrl(}ms8_`Zm)8_?vO4!&UnQ*si<~| zw8IDxUNZSOregM0ZKfI^HdOp*t^veS?5^{dZ}y>@SejT@45*=ureVE6G&^$+ZYwKj ze;yUNAmhDPs*r)I`@8e}E)}ntu@9XMkSavIY>>};k`L;e;-3Kn3jIn*^thy9)tL;;e(FE%s zGpN+zUUS%5nJvAa}RYf00c>(_eRM8EZ0hvX`JVw*A zkikWd$uQ@E%+Uo6g7bmMNpO6LiVTSoiShkRjakO>t4Gfe@{jd0tq{RfQtY8)lntN! zurP&BZWk9AsdYnT5)+aV@epTRs0`1~OgsjLk4d6G5Ya;Ya+XoCBKSWBO;`TB z8o~-z-BqlUmKS4tGmBtS1?-&6CkZ3efsL&X0qVh+S!wdyV}*LL8zejr|8ob@D(e04r{U0nq-RI-zd0GJ{@y4Iy8o#t* z``+Rrkmf1*Ys8`Vprgyv%ikJdX!R8u!SH=Pvkk|@w;~v7UgEb;CIvPXr?-fsC3p-* z0Hk~z%C{r490Bq;I3PSm*Goza0) zxJH-Np5@RVo_nQ{(qW5i36sO+5|#370nG$bj%H8b8Kb}E2cHkbcC2J3qqYqE3VDNs z+bNM`#cz}y;~gQKdW@|u1sZgkv=7M}BG9ty=EN%dVI^R@O8^leKDpW6jvZUgJ*D6u zDmm*Th&bG`NHnlZB@iC;PXvCZF@iH2yI}G@&unU8%BKkVzWrFa^wqz*bI;ns#KGT{ zpKN;GY)`;qGtbKu^b1qn8_Ke7uWNuvLY=(kTkGqBPEOK1Ry)w#|6|ew=z5>?2vGJq zyr)T=wx`7}3&ZeQL$C5BPwnj3D46d~H6c0&@ye3%S@?I^h#AskkqMR3V!wY+C_lUH zdihomRc>*&F!KS4|I62--%=WgV3f|#;OEsAHf>F8Y!|j}!EbW3ucp#ToR!^bw7YiK zce?=mCIlg6NMB3I%bQqlD;^U_;Si3a+sOu_T4D`34q%XZs`LI)`$MOnDO~eDX^^s~ zI=f=|OJ6jeQ|+gjJXW^+>Y+wz>WA)^F~_fw@{rV<@CIySKMk2&r8paVeVPpv8>jg= zY8rLRe6z<}Ts(+}iQoG{)v@9oh=#$?yNK9KGnQrf{TAed!6=jTFt{N!!n&VAxqp=Z z68k;2cpsj8h9R7_vg#2bs6a;Q_l|0Qt#AagMse(2)E^qoqLldtMGzk>XN+|nDbk=5 z6D#}kc{X-!a*^gY3)W@sFPG{ew6MO64rNmtN}%gz<8&~yiSM&cM;4yfoPj_Wcw%Rh zRHkupq`%9}cD3Cs=|(y1qcYh=FBpt+jao?2k8f5qipD+`ZAfX}HYv+9n*0e(-95x8 zvN~GQHSI>XdU!rSny}D_qe}RT({M1NKc4cX>!k;d8;uziilS!Y!Af85c!(5(Kv)!N zUm2?L_7eRo-T0@++Qj6)7?+o;vGwLI)jefcr<*9+Wkj=qz#&hrWSwBt}sfpjNh zdy*1{_x_yk6Drhp+-tdKsVCiwZ|Yh2j}0L9j>u{)1q1T$U1#s6eN?hSeNp^ z1#U{*OGdIDk)V%#J~HLy)MR3S$E~FJ#_bK&?9BjG0c}Yn2CA}_L}ydkg)w18ozAj? zSsP}F3cL*|s`a_2wT?MSH$ibK6NSUiE9o!nERQan4Hh9$g|r4X)<&Zig|iGgd#VEZ zV=T10!ruci@yabzM6$g6Fh+3DQ0+57O1#@)ky~5k5!z1PxJdCV9q{^@-^BknSvzdc zm##mq9-ZnKG=V7LCQ}h7WA}FHbFEUtLum}^y@ikEtqsvZ;oVwBq3^LvG z%tebGkh}!0KmOMm@qSc!TYa|qqUwLQMhrkJ`|0x2g!uZc?mVU>t6-AuJGv@F=mI1( zI5(8V<;y5w?abUL@i>^;^~{KIY6JuzMkTv<`lS4UqMrla&g2^e9uXum++Tq|{R}h` z!cO8|nMhZJTV&c(yo8nm+3B%bngo^sv9w zH3Xh4f2;fQ8ozdZ`#P@)BI~{*bv1x z`>INfQ6uPlCNlN!u`fjU?FtbLBH5YP0jf>Z7J5?ukQXPZm(;$otBADhHh(Snrh;W8 z^0b@#zq9e+Hi)6vHPN{7Gv}QYVlM2}zJ{;h0f93SwDnLYWtw7|LR{4*uk2(Ktp2?m z!qP&phCmQwT-M(^%-w3pd!dx3vrJTr=PHQvkG*|EY7^Y1&G`2)c@8EFm%80Ykct%L zuM*x1UHN6?$vqZqzor{>CV2%#`9x~*zl}*mTG7Bw#hjdPZomH9O83%&T+rWBUa+D4 zj~p!jPo+k1DM!kP9;&}*oltwfOfa-TpEUIK{%a=i!V|mwgc8>oml&$_J=%fD)4AlSQB?8(1>BHZ2`}_M__`eEBW`ed_zJny=(#g z>tgVt;oJXX&9DD2A``rgpKJ4!(++%TS$=f?;wcvV-FEZM%bqTxK*rpcs6n|1^x7sU z#3m7-w%{~S#94|JiD4b163zSL2tuA$>a1M|8gIMM3QON1W75A099xKUA?vWnEf&+Q z9?13>ygnCOUwqCyhr;us_u0_foO*(PDYYnGur!OXmp1@}iz=9&Bzx@NK)n!AwH>E@ zhGzSGo72p09Q*fBIa3$d^F3#%KirD~eeLgI-~7M7jKX~a_5YXR?9a}1E3$udcwe00 zN&O>i_G0qYzi;as#lJocFE0KQcclMPeiQvKZ;GA&bZV^s>I>fgiTnSHON0>R?y`uF zr9qx}d{q+5G_kO9=KF(?+_wH1&)=TKL-Ye+>C1~^vb6!azEyR154DsNM&%4FP>eeI zzt8sK*$7=g0?oU#bwkR3B*khL+_IZPtCc;(s_{k#ZFe}+4tgZwS)Lzrl4VGAchvv@ z>eYS7;L#VVb32cG0^Y%3~LhgHOdw^-J(F4f<)}bc|Z@n-#Z=0yI@d1V<#4eG*_y5Fj<|C z8xU`oTXq;+8+Osi#GK&oN_L24eEfUIxno?^c8Idq->0M(rkz~Gp((4Ab~_7YQjiBf z+wII?C?Wq_H8ZU@{NT}-e0Rh}W-Mi4H|Mec{g+vyN@b@JsO56ej`4Qm+WzlmKSjNJw^5mRf*Xh5{ z412WbQ{J;H|D-3v0!!U^NcLVThU}E5r(W%yn>@cG9frn~wH^RCak;WV|rDAA_wx>kS3=UhKuA-(C&=K`g_lijzb z!MFj5d)AoeNoWH58r$} zz6w;i>DYg6^QYW5WeNrYd`5i7ASUxoM&*#Ur`ZU0S{nPQ1hV1t%d#3be!Dj3>I5o! zbCZ{#2Ezt`m+RK{o?+k}ZW(@%_9e=WJu^Kv$Frx&aZ%L>U`TY7#7{WAjM`l)^v$BG z>sAkcP{-Lw;O@Q(nh(7)+0Iur|0lIZd&Mw1mBM5CzY~{4#w=e)_~a7*14e9SOZ~vy z@#XPj)6tdtgm3Hlm%TasB+Z;W2Y(UkTwFbcBYv;bk9E$=*Y8Vo=dfL|fWWC$9^1Va z5h{iM!2;fMrV5dG{76T({Z8K@I`mydpzu1w1(dO8ZwhJv<*~Nj#G>Q~l3KEg$o<4*e2^Ap=7@1#5G{Qo}BmX#ZIw+0Ah`+pkiqd~$K&?&0)*I33v8 z7(=>iQ$d$ntxZlOpeXQ#8g^Rd@`nC>@e<3I!{Hpw!tJ*Q^%KrueVPIWJ`$aZS+S>X zyMlkqiNC!2&-eZ00?G2+@Aydg?B6Ne6X$cl-!hB;zovp`wQqiZSJCik&FlGD@O%hq z$0FM+7SgM$TeGQYK{1nRSeY zi!-L(Qnu=6t%70{ql3-4d2w6q+svOKE#pnR)XUN|w8oHJ$o|p%X-w0b!@Vly4%QVphA;3pPZ0LzfNn zJKYuGP>WSz+CViuF!E`@6FepILTMzSGn*V#W6mHbk{33@7*T(XXFMAIKoS~>@ubuvSkYYmF?P9lW)OI=j3A-`yI;e2j5%;;9 zd583}N&w=oZsKhi9^!DkcWu41^Fi4MvsLSC=_cubOJ-+B$a1qZ?1`YxV8p^s^DYFU zWkDdUNY-y_IIR|dX>!%rfaL-(H^-Yf7YS9#I%QtGeyaN_NF`lcFx(C580z))DM2vM zOKou<=^_Is&^ThE$EM@$e31v$i87SFf;s{oGPN8Hb_9K!(BN_6e3u@1dTw#7 zE+pI6i;hcBncaEwZRvWo`H^|roszlocvI->@B%Vr#r>XHqs5=?-r~VNDzt6s+tk6B zBb9|A8BF}zILIXiiD*jn%feNz-uIKk`P_ti$nmeGF>T}~Sciu__PW`i102ZsE}Fs1 zV!CAhE!tfkmzVYYRczxc7t#kE&LM9vg9{g0qNapQ_K%p$$L^?9+*)NJLM~fV3%8;C`0MRH}&&rQE_M9{A-pXiYUr z9bX7=MEwumsw(x5Z=w^AWw(YK)bXqAQwZ{|WZ= zT^QZWHpdP4v1PP%dlAJY`SB%MN9Ly0ha|y$3${VVPa|x^wsOjw0LyT@9VC{8GdokS zjmldTX^19~^aml*Vm1VNMXYO{5}^9o^+sg(z7R34fF6GCKiE}}^}9=jfwN@# z>gi&13WzC*f>m0OMi^~cIn|KvH@qY*?k>5&q-UctjufF)DF==W-D%P z_Nt6NHy^i^R6y?vq~6N^YT{|Y1?}|OwLuLDd@Putb)xr}3bGw#n)*p$B!oH`yo|wDLH8rn(EP(yH=&3Fkz2vN`s`w^xDjeCDIHv$O1K+5qWE?iMf0@Y2Sa_gGrG2*Uz$P$s&D8KyormLvL+~(N75mzueaC3XFaN ztp|6X?!|YZjt{f#Ntj$`>ZZzz6=wC zr7sqTqoU8x`RX{@JU(l<3Un%uy{#rTx*l#JP_tM?eBGefjG$t2J-Pp;1s0ehPKYaZ z56ZRwJdGus`?Z>7zoBIb>Fff!xW10=gw6x~HKOz}jFo2nb1kG%PBW9}zHdXP-og$tT3i1XC!dw2 z+uXs_A+gvr9gUkkzo-P>gHx@~{6tc{czl5?b3w0yG5lRZq}AgRQqq%sIhg=*tfH%S zo|%~Xn5qO@W(K8mJW#_hmQzgEb>_M&hN7G?u_V_M1e!Ax*ZOzxp>Wbri=0~P2@6`& zrxzDow`{DYpD(rMbV85JzSmg+>G3ID@-pnz-6Res4w6$)6r+Dy~w(_LiV7bY7aqoW?lqgcdj}AN)=W}lb3?|Ow3O$%In>N=z}QdZR@jtZm9SuVp8P!@ zaw~+q0G^tM`F&|~I_}Dh+9a#~yg?#lH52v(X%B>Q+j?t^?FBsqW|}~ajSG}KdMVWQ zWG>XSx_+HUv3b~vClL6@Z2!g;vd|B!X{YKqd|3N4_b76-el8%gZLHo&!grZXKWu!` zg7}?M-*7?LRoQ2!oh`u_?FzH?{O5}4(wyD2t9q4bLAX~AKcQl0vtEG3Ody+TGo?== zjvsKio7ZIB0{dDN-_2p7`)8Uk!rxWcgTHA~o%7bJELnGU^E`({eOfP_fXSD+vmWAQ z|BFcCdw0BcGvHau)(~6$fiHt1hP(Yhb1m@i@_ZA;%HH0bNTy0FwxiB2W0@8qBqrrh z@5#`|?aOF{)mjJ;U<+^ITWddFC3MXUJ!fLu87w2CV#`yfRWV?9i|#?j3IG4ax0jON z>?e*${{_cmU;P&{{NI5#{STMV=8j=1VBk-=9SKID`I$ zg8x_C#CPm}5Y!eaU*lsS4Iu+)vhe62{d5|>DEFI57+s}XCVo{V!F|?7$wyB<$^=kL zvG=2j|MNX_%n~u7u8KZM(SSSvS1pbk*Jlg`LW@q~1MMh4QUrH*z*tg(mJd#JTVl9zma( zc8FqlmhtlEIHG3L#XU?G*qikE;+klsvg@3OSuTd+cUG5s4)eO~QJ8p)F7B*Q-6MiV z$2`JjS})%Nkdrw}z7(z9WxEF1qKLmVpXu?@wfqk~fSRgIOU3 zeBxFB_heJc3rBGk?z4%L_MVc^CNgYnT?3ZRxUA$R-lhgB?;%<&s=wRmpQd1Tjw*{t z_24pwO~aa%>W*EmS_x*a%EF4WPF*QhgDORoyw^COPDc4DO~7U^mqhc| zZ9i;P*;2W=bRVf}N;lBk)JiAETybN-n#k==rRHZ7KQ&WaAS-hB9?3{)URvccxS`QWZc&=qg#D6) zjL)wHRB8tD{R))3D{gtzA+(+eVsO4D6?ZFiu-VG47E5m9KOK08M8){K)#VpB!!Qcp z?OD!Y3(EjA>J3%nlafQ$ScHllj=EbS00h;Rq9MP^>i|A@ENJ@Jq}4{~=Fp95trapQ z-&abmJpz_}zuIm1%=P1Jh}0D>lg7vx_a@<7s)EvSvA3CJMC^ z`K+xv;K)|kVf?4K0h1lxGj4Kh;)Z4sfSqrRr4_CBg5R$0+UV*~sb^d_yk{ssXyKSM zjEhMXIrf!x-n~Db^J||yI4ADf06NQ>+F9XaU)JU~L`Sg5o7P4PZkx-QHP%I?+=lv- ziK}LT-A=2ebe^iI2pYK%vD@Dj>Q0}#b?zXpvo{W%dk}c!h`7jbj1<>Z9-hiE8D!-@ zEL|)tg>qg*BF}EC;c$gRNqxx`(@AC;YRe{XuE_RuUbae=?vkc^r;qR-I^M(K9DGzp z7z84xutY1rb6_{YreH{s;Zv^Ivs2GZqhQqTIl{E@9=2Mh+LJkhv>_HVqHayO%06Kz z>MxZtXXCw+&Q`&2omX!{cqmdt8m0(3(jjeCIC^_}m0p!I=4GJkzuC%hjaNbWYy2_; zBIZ|E&osd=#3$%f+$reA)ewyjC@01ZNS3$;RE;j)p4K%8UB|QF%vGl0{}gX``!#Hf zIA&idayi1mmyL@aVc5d%ceJy%IdkX0zg32uVI+9)l$f1|5oJi;NoQ~UBDvYAFME!V zQTXEUVS#l++-q$7#w}9vBVc-tbtx~SNTEGF66tDNFN96M)7(I@bn$lc<}mo6CUOQ= zWpJ^ILUYW-Vlv;?u{*-CM$js#zEese6wtG0L!0>>&8IQ;|rR-ICwyoOn2^WPTIGk?Ir8ye333s80g8U%-B;K`F zF&6{FJlL{)kiITc;tr}-r#~wk>54sOX++FirRF9$D28a0_94SqAw8j?L1cs1^ro>h}JRnuh7g&YTuMw%@5a=OqY)grJ{&+5eRQ=oh@g zOyWglsybUg+#E998$QQ8&;folBPBU7FIE`Rkt23X$W4`F)3k`}Ql*K6>g9M#!icTu zIa<0u1qMp_xFS0IDkQdl+Hyl^`nguPKiDhAI65ETyG~t$9siPnVB6eC!waHmLBCaD z&<*u2*eXo$8oY4|Mr4^VC#(?3LRm%uka6B&a3Hy-=s>c_89-i$A`q%WxDg2`gNh-W$NlMM2 z+~?1=4A8!Z7!mFWa6V*+;6e8dI;T9o(v8obri?tLN}qx83vvY(WeW<$p}Rv#V~(ya?%GEPhhIIkw|Tb;g%ypnO`L|gpS>=x8vE$P=suGN)MZqd;Lk6hHgGeg z+8aTWC;BCUHFW5-o&=6e3@X%TR1JBv1a|vlcBIGK$;_FX(`v!Npvuoc)%t0K3AsAB z-L$0jQ71xxL^?WM6_7H+MeV?_FDz9zN^U@>k#`W0;53)j%juESgz02la$AfC%>OPr z?*6tFl1eUr>ulwln`1OGlXT$0P}BQPcrCRc7bSLx+gfgBhdk(mw8TUIqm+n;XnbEaRq;pT*cv((BH$ zp3;{0`%1XD{j>$PLj$-?@vRW#7v(Q{=|R9Z}SYQ9g;)Q>4*%Z z5EPRf;o+?VC&)TcG`Hu)8_QoQqb&m+xQ!}pzf}D0G50e|%zp5d?;ehN-Smsj@@^%* zBVV>DkpXUx>9`VC;@3>KEMj><+I(z0z*9aOU1$QWQ@uYj_`W|%A)vbPTLEV> z4p~n2D4!5I$^FyJ&t(te_v=o_w&b9V+7kLbP4sEc#9z)zO3y2{)hMwO#(TT1Sd{Kn z#bDW)Z8Qi&5iR)wajOGE#(?iYr>Ji#Zh;oRrDj@WvDsR4LrdN|{XIQA(e>?_s@M=< zi}}MI#gl$R?8DUe@Uq1tUZpwFg_Y6I`UbQ6SDXOd6rNR2_-=dIXQTHy{cIG*bN1K~6zmJ+CNU_vI9xHGAe^)gPFUANd2XXYr#nLlKT$C9fs{h> z=p>;0Z5eY7{bHCPQ4A@5YfHO*i8bM;{MDclH}o))Z8pd@NII?FALpP`B;06_r!%f} z>8#C29oM6%%FxcV_1z~)(YDpQ8bfTL{my&lnd{Zyo>^r*S1X;fs~!p$DYt9rx|&Z1 z3ic%>A+Lnb@eP@JYf6DRE=%*IlYJgdGF`BaIOUS>mwghOj8uNzCvDPX>pS-tGs|dQ z1w};tYB?nK&@!8w^CbM~!SM~XV*mPiN4CsBhB0)Ciuf$yG_ZsJ#@(e>LNJZujeg8e zkAn=VRnO}uZ|SQL?}-oasn5G?EBTThGP8X5c@zJ4+Kru>kSX71TV>V4l8VKE%A~-b zjFh<2<4-rf$uT|s;8nfM>F5`EV?ezV!E|OmIX!Rfv?)!{mXgP@=DaprB5wW56t-6d zR;$6`^a$sGR|l|Sx}057Gk<#balfO%H1#)fw+#wNFQAlQQH{;2`_l-MJ6EkWL!(m0s9ALm~!Eyvf*D}7wWgELE>I(Pd4 zZ%1;)#lMdlyn0|$$Jrb=V08s|i?VuGnoloXOA>P0`Y!n&AgN0pcOKS2V9w;VhbDbR zq+jb&G8UbZ2pyoa)n)thvebU)0j>6dvr+ztck#|@uavt}#xsv?UDMhv5e#xrl>tl=mwJO)wE+p)j zy{V+E(`2vsM5$LRulE8+dug19t$wf-iCs>*^L?L#o|7n6l2yv>h0mx{@paHA?+SaE zGa_T-K7Q5;D3Ic|I9%y?Oj>3&ikI8|##z%an=yYx9nT>cUtytkeV|lv9%INio)~Xo z8^Q94RK(9VuG!6Ws74McGVF3e*wm9`68|Xiq`S)k33&U-K_PXaPq{gQM|iI zmWw_3+0Ej;f2fCoG*F4s;V&sm*7A<(huJWT_jFbUrpxQ>V?S__+Y$%Q5=WBAA^I&l z*&$BoHlO<%YHJdu-}veeYMsT&sZvsVVYlIvl=Ox{mxtE8489|$+;8*$!2-NEOwjTc zOb7Bllvgn{K%B@Q?5SL|w8<6al_HHa2e4Z)GFwifB@9A<8m*?2EBFLVa#k7UhirD6 zf-Rot8QdZo{I(&4WTId(cbD$EJ`_kKT9M)R;(qjVd^c(=hmxbtu*r{PB5ux_57~{0 z`6i2|8C^Z0NX&mY-s(<}qB)blqLHeH9WT{0{B%ptk>GKhDltz(@>jfdRdLD+U+80V zyt~NDhSV!}sEbt^wt63@??@fUOUllFD{~3ONNSo(0IvpyxV5$cpAMoSI)=FB7!EqY z3Fv;nU}@c{Sm1Un8^9XewD!HA;LZNgah~_)6>_`GSa`lEzuoQ4+xv{|#jA_#AC{Jm zBaAc?rC#q1)Ulpg_S*5~sp~xU?_mQD??mC-5Rt}gu-iU?mt=ZI262dL#cV;1?J|rn z{KbQ~^(}SsP5)#~O5Eeop<_7PXFU2-b0}if zW$`EL$r&-4m7DEx{9j6)A!ks}Z^yALNQVA6B-iN*hON0+hNe$QsG!Rqs`d2{dhw_u zO_Rr}AF7Ca-CUAXlGqueQ1u&G+Qj(PSigA_Lc0&H#n(~o3N#dGU&&B7%7g|y9Bd&u$-nS+XaegZc#SgKLK^PlF6B>Vh9V;1(F% zhw}sTR{~>)aRh^Sn9Xz{8y@v)$wegvaTu#}>=ZG@+s_9*z1<)5Q=43D_(DgLm`Fd8 z$S5FhKW(ogue@pb-5fdIh+1a~^Py9Kx4(70=YI|O%kcXxO9 z?#A7%ad^e|H*@cuJ8#yTwPxK}k3Z?EQ|IhDwa>QCXOkWDMRfV z#fg}llTC?{6#2n!fq&k2V-H~63t0syWy)9bHA*1PU?vhIlUtO>% z8|+{ct!sjfr_o#Vj?d#P5hFPVrwt6bG7xjV(zwgVA3;PT(B&G$HRZ04yRV=(&VN78 zzfwZBE?*L%&Y&?i&Y71Sv+H=6m8g3@i)Lf!4Z(T#6f+zf(Rt&?oAHwNJ}a=Q$|S%q zX#Rkxm#Yz66Vlz_x*I#9B*3F*GXh(9yPnik^XOq7CQbnSUCqrEQ7;4=l-x(Qe%fuji^+x+3OXc57`Q~S)hiLbO=hc zm~&%Li*)4G;+fiON14w~5^x7Xa!Ne5nBRK0VnZ)CF?CC6$!OdwM{z|6BLA>3X z+DM}P=0Kz8_}Y~=*7VnT*K2vB>V;mdPng^GMd@5l-34ydB^X;b0pC0RVevir@}pKS zXJV{d%NMpte4320_0+}$VR`(&>km%^b4xJP3*l3W;UQqwA}kQTH0sQlHW^h&x;gC% z96CM6W3~8z&^cMoFYIBweCuX#QE{mUx3BGi{W1+&4>`6Ot;9#oAJHOKRu;``Q#V#roMi`?=;R$qhs!rRd4YN z_s$4`(vfv!XpA}s+?(Yo|FzuD`wADlws;flUq-BfpECVuO20kfML5KxegAOk)bgCz z@)H|z5%sj-Lc|^8?m}Rp$%KlDDGBp^?>~jJ$8@}&zKawA4p)h=_0+Ud%%tWbvYFzr zs|jq9to7DozoLByno?zKYWaXk5cDhXL{E?R&utSGQe)2#U~7i7N;5VzF0XtALvY5b zG4e;Rc85o;DVO}eQ;}0PCM8c>T&Xc?9q9t zNkeB1;R&@o!x?U5y`zNM!$cRa5L=q4B zHzEhS0@UAuCf}CMS0LVj1oE4xCLC3CJ5i81r#5c~p=JslR#AC}Y@y+DTl9EHtElaD zd6s0OJGV*!G1i2pyH`(TX#(^sU##KRl0~;WiTFSkG~0s}j1z;dAQUcD`>V{I#L+ol znt*k}d7I^*lsmY`3&FLotBWSwqhn($LD_OUdNqK_(B{$cX`3aFWpA+*-J@RQCO8o3 zNGO&43QCS=y;p699523OeT*vXKe{dZTO&R}FLBmrK1rR{iIlhryYyjo zg>EJ%hLz_OXKD*$i&o@nBco?wxG^mDT|NL ziDAPj)rPy}0i4wA^(cCKO&Cvd{GgLxta}4@Zj20m$swf}sz>=@oT|2di6UkWSy!&o zM3%ut9Ot{&L%ZHHuCky41Syn}KWTP{ou;h-C>2$IGY$htl@{G?uGBiso(9#V062Y_uaIwZ*FBf#PO#&z9yq{6CC_mVnDJFRm-zT7JIl;hCd#Ho!uS=)N@lVb zQ{)&~OcO3XwOWo}#ju+o7UrB2@;vgaL@w5LFEfNldVd1B^3S`^sWPm<_o2h;u~SaT zjoU2wQkrLeHFlBSp>TtJ{DF=d##D84Ga1wQ=e8Tu&bpgsXArlQl#1=~!B8q%Nd0$P z^3jn!pYXO8*mG(|b2}#*el|JO+L4BC$sv4FJ~{YKb=L~imhE96)WG?KBC`Cp`I;3rkApm zBOU|xwrY!iR@O?4S**HvWlOBULf*bYx-OOJDel%rS%Dere$=1Et#8O1Cfaqu+Tir- zb_Ykt-R;F!?4CBAS3B)2IyYZmAXTrsCBWlInlx(~2F{zGB`_5{Y|k;Ta<`t~^9@$UxYup|REa3M zo(5wN&>XWGaS|XneNRSP80xcz1NvH>NuA*h4B;^U z5lphwSq)5OwIq2N_B`g+fiREz>>mC!u4{2pq8Oh0#)3dU_jEAvYF}ve&R6HocvMJ_B z<4^A@eKhHgU%B#`SlgQ~P94h$jDl`=IM}+jVvnrd=bNIEV#81M_Q_6MkO(KdEELX; zXLHPp8ssG9l{5q|kK$D&M|xfnepYBe2?;)~_==fZs%fZ~2C(xOhv~RE&`E-7t`oCK zrADbvQ8B+qO@_ardnSu^_1?@^$o4gmU^KME4y_ShIErqEtKaB~?PL2r9((LXQo7q` zIgYld3yKTI9kG1z=V-mmtyJb*Xu6uIdJAsi+?#)i{C6go@L{8=XMtwD)8Tn`80~}{ z3jgMCn5(Q<>fO$9I-?lpQlI`2as}4K8{~`cB+RWvYLzuVxOCuEmaM$fJD1hDK5j~5xjyta6fKdu%fsCJqos##LLPMO{ln63<{qNfZER<;Nn%~`Hy2ut z6ahaK;jzFF44qD3`!~LT2EmjkL&jHU%H(33dap)HqF0J_1bm0c z&1Ffl1!7h@Og>v#&`sKNpLQ!7FFi>a??c+X2&ms#Oox=z`xdeagFGL}WeWEF@c3vB7YSegcbp zLYWF_`##>9Dh^T@`rsZ`#tWq<298w(B*f?Elbu5j3n@{?sPQ_w7%e8kY{qJNC3-y4 zc>KTx07>Bg# z@Apc%MxCHBFn#*=ZhV~49Z6mgx5oHlM(+I zj88o_j4Wih89tf;ZSqQD*L|v=;oSti2v(B{eevnbzeW_+cTl#^6$J2Yo^YTm2Y-9c z2Pr=kSNWDwuhhi8;{1RalWOT>7vg6rZ=j(AE1&S>UF{8-H*B5)2%d1nXA7QX_1+9D z1_0LxeZA9}fsGC0v+rC&LPDQ8Y_&~C&72J!lmWMBYy_~0u~@{LNU|u7%h5xIW9m4;NoojPTLzdPeTo zbFC7(V0{m5sv^=^-XHX6{5cPQi5FD5Bzo(0=aQg+vnXvCwR9JTQ*bYfC*-Cj{qUaE zdh&HkOv;h~@LYtHuYkNW`&AlT6d=QBCm3OmH}DhaZvud&E=f@a?nqr2NNaZeu;3BR zaip7hF#g)mVy!ZN_T&1J4fodVU25sX)AZAd+diOl%4w9}BHW)gJwt<1z-5K0cY?1@ zNED*{Aqx21^bR`~*Hja-zZk)=APXncOW}hMRwpT$5;+`s_=6jkx9J-8`T^Z{B^*3A z_6GPpPW1C}$dN+2`1BUXMGs{9 zOONLx38z7=`Cy8gjW>>mk(!z}4IA7`t&Z|1db@jjdxHv}A;PU!(^Is6$OKpap3~It zzfaFfF_8YKW{~UZb}A&SH?Yv$TO>$#^#-hY^Kg7yt{nA8N{*9+G@{B3E@)qA zN8hYRo*F<$>)2i7+L`hek!?m`@jf{`oA>#XpM88K^P7c&HOg+I>&|EE+JglrF|de2 zPNT-eIN*MjKDUDGDAA~j6K*@$_fk?Z^S(o44aI$P;%Y5FSg0{i6osesrR$lBH09#- zMIr%V$lOVbB1^jcWK_Pi)*hl@3!c_w0H0m0sbH{%vRKH$I72g3 zA{?&&_VFzH(DHo71YtvrRCvqn;1Q{UZkPJaHitvr*}QyuHRX2@$o%y$+pCiz9MXCI z-ud$SR`s2E>zrf!rqn0a;a37ay$p*5g(bptNnOGjp%`k zJKcI#H`;^G&a^prJHZ&F^vOXjf$92cbIW3%{lcbtb0Q_Pk<+<~p^oqz<{H$( z^=xp4cp;9dFscJ5QTU%YqbCfI@OM;DMtyo-A9;ofRASzE{LEgiySq}6dq|}B@SYSp z|B0Fj6J{g_1I^WDM)&oGN@f*^la~hFh!@Rw2dAD{?S-q$T>6RBdX`Vo4;5eS#Z$7= z%{6~KWI2bOG6F>J+eb5WS7OC4pN&R#3u6{MXuMR6-gy^9;i9+%%YLaYFG?zHv*B|oDA7)cFhJ+NH zG8ceZ6#{oFLSxVxu%)L*ZE?c-bkhh56`g+I=y zyhlx5$x>_AnmX2XTcMsZ{aZ(ixt{S+sFTWYU{xw?31-#48IJJ#X3K$kmb-xbxBgUM zMCAh{B~c%5?nl^Dmso_yH+7id<31gThekRR_dZgAO{NVlV5aG5wWJQe$~YmbKbjiK zQAu4H>BVJCIr>HHfH6z)Yx~K4n2e*SGFof?RWVnqYON@1g8Soj@4Hv&bf0Ot#%0%O zO`s1bpF=DP6p*f6Xz14Sio|9Q2yyTxYVUGnV+z3{#q)fpA*a;0(gpM8-?3EYmae$9 zcq^qHPqqQ+=SK>r9Lkl)C{68iHE2N!V9-~?j9ZE{q4y6LcnuNgdZ66{@K6+}t|a1z$@Gbl!LO;|XbY%$ zR)gQIa5Q1^O%IO!!i|q7s+VM9&7Q%hpqF16^_SsV+4ji-a=AE>0uEG-3BW1hujVOi ziUt|j+yD#D`*W>1C6)&vQs{-DoZYHqn;r7dnCaCTa*Dao-WKVc#Jb$lW=BirkSL*O zQ8DA)?4%WB$78(4SEj_n%N`k=S*XLS#MEjz-aYv+ni>#o1mPk~of!$C@e4hyaO9r| zw+Le9vzn z(a2%3S+gFRGa{E_H`w==_voUzj*0t}Su(o9tG6rd`|oimUNnS)gWXD~vj|$+^vg$2 z6p*DOaKQh+#rqHrWuk{%*5Zy^tUdylA>81}m$|#d(!27c4sPJ$aF;)iQz~@3^O5~` znB^Va8~j)T>!&yng7mZhN}&D!XZqpa;Ql1fwZlKo7Ch}5&lO(J*Dn<94sf3wmhW7j z{zV#)22cWYX7Ds`G}jvk-Yz({*eDOZ{TS{c4V`B`>d8?Hy)#kq_jW$l1@MEDtV!s8 z9@WHC?EGK1^hd^ia-KBV7$)3u04Q}K68 z>t3Jn=hKQQ*%kBF{Shz9S0W!Vr{|$oly)!3x&<5&OlC> z9EhPu)VmySQ_Q-^<>vtKhp z%rnXpaoC)0)0B1!gU{Q$I!wyaI0l))Z7NSZ$`;b_Ak+!9uk>o=VgB5ZWaN6 z8DXI)R&|&4Ky?%%OYhMDwW8JM8`M-D=Drp1t604atmT2x{!vb4yj6-#7KP2N*$@5N z(r~F66O)%?oya`$U#AdXUUa9gn0|X8ji^Jpp}QVJljZj@8CY^o3Wj%P=NlADMyQ4iPPDoWI2<^ z!&l57AIrYcUO%U^ysPsEGlPmC3ADNWYv1=a_wu+t)iQ2u&j;yK`F3IizBJ2Ep&Sfe za-4Uv9*U{UPYH~=da=Q37vFFk_~omC%bhYB1Y^l?5I5j-dvh8jk2V-vs>Z$JG@oMU zx85*YqNr6|8>SAQFJOlu?@+$7&(vLw9kMKCPm;^aVty5%Hi>(`S@dvPSns}@dPzX* z)N}w?}}B7-W{F zqc3ltzgwAZaN11`CKI5wK4&Q!aWe&BngF?;|8$A3Dbv=HtQO;c(`{gsuB`n-x_pdm z%v{>t-rZ_ie06a&TTz1}rj*GlnML2IEN{H(`{f>_vO+}JaFP>GZ)JDZE7pzYQSSbI zP44J`|5Y^)OAL2%izrTZ;^I%uM^ho)`RD?n(N=<~^oR|^sP7rdLLr2QVj40ATUiEM z)Lz|6>lX3;UYVfpl5-JNZhJiyxIG<|zt;Q4y|R(FMyR^nWqEXoNJD>~=zD{a&aDQ9 znAwKJiNBZx#7R@*;VK43ZsfR;IR(rGR?D}EPXt$0Dta})@vCrw^)Gl^9%K<$T4Q6s zr}e8iFcGc5OL#MS2Bn*==Bb`*3Hp+$X(xZl`6N+$q-P5s-nt1%IZdZ5aVWG2Y|ktV zv3zfdx%qJ`g}MMlL;m-JvXlyDa$<5 zU$v{{LRNA9ZscyuoB;$6;}uM3 z&|pSpG8iSKVIHit)*Ny1CvWs|ZoqZ1D&pZ;-uB6dYRY+d-4Py?B!vyZBAQmQaVE51 z%_N72+k<8$_GFVkG_#%jrbiJ{*XtOoqRnEwXn+)nueqjEHYU51;A?X2}+F@-2VJsZpQ#^6`FaK&Z#SAO^gaOY6vg zvt?skDF3*64UQrVmM%Etv>9ZetW9@ZgIpj1C!Hr8MK29mR>OT4e)Sn|w)VloLJZ6- zpICd}80?!ug8l7{!wl9T>~FSqW>O3heojl?7kxw3w~|w*8SfP(J(e1kV!Kgux3U4a zj_EQ7{7~oK(6eS2$Qk4n*IQRd)XOGcuEDa_P7yKc;|o*qq$48TB5KY}njeM4b-@Kx zBN9?P-}DLxPlHIAS&zO+si+1@i1eSFpJ(pe{ymMR3E^^a011~=WEDNUE~f2YsHDEv z?UX$IWTd##Zqc&nu22Hb&!MLKWvIDfZ}m~_;`~FujdYZ;2)~oqe!-PiA>qVl;pNr6 zDNEw!G^N?d{o~LOzkx@x53Dl^g>~q{;3uKa|24Hwmemz29WMnK@Mmw;$!FiU{sjxpOAF3KB-Y9u_kWP z1{bbI@0U&l(0Ckd>7<)2FHx$MOMQKb9x4%Ra4BRk9dy+{LVM60z9Vb zcA4oXS*Sj>3@)>$OMPCif2?m9vrteN-n?QzviLQ4jKAY=#Dc?mH+^PjeQ}hC+vw&QJQ@P@c_^iQg z3_pqH1~h!!TGotU&$o-q$(T(Wj;g}7W0Ks&A z?*JvE$D1gTLy4dF)2luAFM79z@IgzkIQ|F49=dZv8{364`pqUzjK@=qr^w5vmq;r{ zOJZl2$bIDhj57!19H>IYFCXN!EKk30$!6_z?4_N4Otr~J?wjC(+j#@wT zA1E0Av^e@1^QPdWI&!)P`gN1uwL1FN>Rx_2vBJ zY{|V2m~>{KRr;Q?M1mhgV=CysSk*WJFbdF!wmBp)Y|Ut$bGyder&;+)B)W%jsV>D`xcQZXPy4HQ7LXW=U+{Ahj5x6VV` zOV9|L`#-^xk`n>^s*O$g6x4HWYX<2J`Ea;*%#(Du?g1&M)Z~*<*5=sV9KM`R_oDZ+ z1lxaMEhPk9OxDauxHOxcjho)HYs?|Iu{;`?smPmVHFLAn=bLp(?*z;q*}Kxv@2RFV zI)MVNej9${@vxPYLd@=Rm&lb;>Pgx|cOegjL&nz~q?eA71MjMYO+6N@RUU9v2G^la zJHs=Vke1jiaeFV8RbPv0Z7~c9x5j2*eVCV9{Q-{NLN;C9i)){5-jF{1H?fM=&4wc! z#US~rCri}*UI^p1QcCb?b9%y&o;4Jk42(V+chxRQ-cw$RB$tb$UjB9f|FNpf-oIOy zqJd21&5PBP*U1a(!E@_9iJw+~fa7afCHb+`)Yj60xY2dDLA8_2;9!{3XC*NKPm-zJ zc4wE%e@bz-e^k@sYV4Oz?#O838E0bow0`KA#Kh>s&5_-7f#0{h;yNYSk^{(@PujJT zWGK|hd-;?X7~W_U*m`8eN*aB=wiAxb1s>}8CgqgG=8k&A-2Nc{XlH*7Mhr^DO zaFk#Th*!(DIqarwoO@f|ftWM-${5OzrKrhSeK#w0cH@A$@67$UU}t5hr%vErZCl%mo8W>NRJA^9bH)F@2*pk1#Xk5gALP5U* zRD@BdbUr+#N2=6--)gIv_t0mH{`q!){P#+ZKmU#R@4u9Q?teqk{kM9O|9^Pr|2Jm= zAd~rtYpRKWw{%?9N$#HLi(vj!)7|c=v9)LJXP%QqCLj>NplkL^WKQNueM-~8D^u>f z$j1zHkgD3_**Q7b);E?$lCq5xfM46>y)*K*T%787mb`wb0b}{kwNl?11A`%aBKt2` zSGzwjG6Di5y`}83IU*=h+(^#Be)!6G5LFpuBD#6__aImY(Wsb;6MjE78=F0#MmRYz zNofjm1KnlQuSA^bIV3AqwP>jhcfU~MAt1!OneeufZxvyqG89>yqL2=P=!L1QiO?Mko)<~>y;}y+ z-fWFajrX|oClI*-%7I44%OlS6Q&;Y(cG&Jwtm{h_Cc02VV!fXFw{P?h=zrD8{5tD` zW6=8TahX{QShTw(_O1l&FD~B#oVnVbC4=I7^M6!zcHh>|Qm@XSs%wy8iI4*8VZKl{ z_0KMhrX-5`u}bWC{?~RIlf4}2pT$^uDq$WjCYbK7fz@mqe;coJAmQUMu*m50`Lmhz z^+S+j*G-B^`M=#01AVFOS8e=%{oM9hv%(gSl8}ahq{1IPC}fX*utwI&_YMlxHJ%=^ z6b@8K^<8tnb_pcZYh^{dMR`y9h!2%f(wug@P4h8b!A0K@OZkE_TNG4iXz}c6e|!9H z*bL0bblKL{7gCM+_8r0-3uX=+WbW!143?BZJ{{6IhJ>>5RaUI@z$iN%+ zHLuPWFq0b3Zj7PhIBc-&migP{I{tR241DS({0>uKACJRYEXyyPLSK2F^kA40s&YOx zM^`iJEI5jsX?^)MXI<-CArUe8=rba;&Su;GgB{(nXR0>zP8P2**+}Bd=%`H1(cvfo zyKaU&#YF|=o3zhq{kDz=>hd^;hb~M6Nk}W!YunEueCxPl;$?RNGu^D}+`|^N`9apw z6faXUT>>Zo{IEqwnA0m#W)ot|?G0>tqM^&*3+6!VZnCxI1CzssBROrlzF)0-J!N54 z#MV9rK9=Q?HR?e@XZHo+D2#+W>v+wdY3qdk%$XpS6*Rb!i8XD0!*$+x^evz`OW`rrZ#AS^ZwOa`+$Hu63s) z&cEVI9<}hjVuRGtH!Zb%vp>~T1qIxSD9kfg11El(>5bH@$f*>6%hZ2ZA?%e_Fa&Ef z?a9Qnn)(YCOYjQNy~&?BcZJe9^VW%*pWY>RL&-;z#s@3%znQwY%84oGQncn4TNLBCg4b=Aki(A z?RhLVx4?yAC0zly)<_YX@oaBM{RQ;p?j&bysYIm8RfxNT!TFSS??TmFG-Wn&*uI1t z_%XJy(kQiGt5}PH##8j3cH?k+SJ+mNU0U_ZIFD2r|J-=BW)v0@U7 zYgRJ4Lo+^%PggMq*(Vj~8RFpCeA?JqCoGu@(}YjQT;X`JIpM9z(Xo8sF2Db<;Zp_8 z&2P&SjnGV})tu^m+TfRfGa9%s&8HZnJXEV+)@t)r(Z?@v)%@ zEa_i}SAv>v2j@SaXBh%kP454IGgeS-ksCDF-JQT4s0qTP6qOzzc?ML5--rql=X?AN zx3N*-RatA^W1QW*{Q5>(Z@$N3JR{Q5kQm zWme89Rj(HQ{QWZ1lGTQ<&}0{9m)*)R-ILrJH83>D>1KkFe(arXCYQOqN%CbD5x0}V zxW`a-p){%4)y;Rt?auy(43~wycah4aOEeCtEpx4ssgxf$Zk<$r>Fa-_c5Cv+=i3dM zl%^iOy<&g=X36d9?^SzOhgcq`%(*oq<)DVfl^V_cu}PtlV)$Q8lU-)Rs#334L|FX7 z%2-%MrDnD$L#=r8-Pg^J zZq-eE#Y(QVR6dTQA;@;%{(jfX^tIdGk`zwzQMxZzq*_ZUO6GPlZCVU%0Ha^%KHJYV zdY%QZkT6u3*dK1;veO_*>@E_X1RUp4{XfB67J5StDmm@r;=azRRVU)Sui($zXyn82 z>GCdg!#+e|OJU{Fytr%JvDVS!?=N-1n0zO`UclLkW5wS&?AIEmYS+xyN#L~rD_NB% zjx8bHwf7`D&unmhX{RqrLvm_g(PCq%d$>)N{!U*xDmXUWtq+r(9riFR-;={tQj?Q@ zLImYHC*~8=&cx%%Hdp!a)voRm9T6k3q&Cct=|Xwk1jB{3mlLsqOz9B%vOjl_3O9iE zhm9i&wEKy8a;#)0a9CZ8XeVy1q;Mv@t1nEIUCjAZ0d&b(? zAZdMryE4lW)E9}lEjL})&V2&Dc1JYX zc_=0$fX1kE4 zJ-`Sol>HE-$)+xk!N+Q{z34%{U)7Lqr@B;PYgPXuwv&nJ&MCpqcq*@2ec)V+htWnl zZZpyHZKlp)O0;&^2L+~`zOA)APvFo~&HInQRngPPi47Wu=`;aujp20_%2!nIOs$AY zkh@m)ns_^S^RlQE?-^gBL;14J97Zd1*92@Js-)qYMa9RZ5;az(!S$}9ApOBMqXo!# z4@6)YZsMt-qI!yhNg^GV%<;I#zhP1go@&dkwAQmyUd%nj!q1X)i>}?=J!zU)NSJWQ zL_e&VM}068UHUVmt1o)eOEP)L@*YvJw|OyU6g%$cIe~Voi>du)>H41;<1X%6j~otI zJ_W1h;6rs>It}6cTR#i^cD;84R3#Vzhv8mI>UBkFK<&3}_v#{>s^$B@z(U+)RX>F( zOw8R-s{dQk1w;Lu4cqtV z{fy}HQg+tpveAkcL!C>)p>5fzh2Obd%!@DsPHUqL!8hf>M3C0K0dIyChH9UA6~p`# z=wXhzF4YC94XBC32}*FHMx=BRFM5)Ax&vNmht55(3FP9bF>}p6o-%HK;bSVFSb~D( zQCZMO&DQr26m^8&;PB32EeanJ75)w5DhzJ$$gsHUAPq>5OEju;F3#?fp! z(6~FaU-?}Soxe?Gkf>&1cXCo-a6!UF!x5{=*%q?BQ&dhBxHEp%qFS244;hSEt0t`Lm zUElVdm$i2T*-h7x=pEjra9F!~xRO6noZd-u+w9HIoO&~{vN9rNDisQA&DRW@qd$47 z2#y*5iN9>0j{=}P3;aR_pj3dr{}VR+|Es|WlIOnOl;ZK9Syq~hyN94L8S9st$;T%= z>}Rv41Cz1RA%jKPbR}9`F7hW@bVao6E(H?&PYe9v0n|16?RLqhj?fqzxn)tZM`#IK z5qg+!iN5E-J35c0Hu@EByyKAabTPvDA0qtMex`?0&~@vXS0RbB;!-aNp{$aQxz{Yvs=7O1`sGH+dyYf&L!Ph=rvRb9*C^jYO|URYT;8mPb-b z!ZC+al~aR8Ea_2RlB)U;I*F87)8BI(xtJEyoEi~ECnCF@NTn49-2#92j> z8x1v{gMCUPjdl>$On*_Unh^K%riJH}8C2LCcJ?$&X+niGWK>eyJ(@b(CYgNF-3&-j zGK5=@W?tFKMEWm-Hh4(cirz+R246jutdI`WL>&ZjZg04HWzqa&7x!q#TdDAsrmPn2 zBbhs|!t5ZTJZ<685E`7|G$D4%p(Coc^X>({X@!j`4vV7J5FPW`X|-ESi{|hF>q+I+ zMrz9lchg>7k!DIcce1xz8_!Ol(d9%kXXVDf0>41z4uX|nvsM|0RmG2$E)WrR^9Lh$ z_Av8l1uV>u8(6LiF?~c?vXqk(n5~J?1>d+o`N3aX%Uol3}5&c2p&+RkEw+ zNX&nk_^!&wb_qfiUS?@yHkK|i)7HN4w=Q(|BK<6$Cj|#Xi{|1tp-BRw`up-9)hSwJ zYPMMe#j9|A{+KFeo?xFn1rL9?_yEBh3Pxp+l}S%&Z#{!}>l>m=Yw^OEBwWJN#TCS@%1sCSD82Qs~X~zCcTSoT2&6)-G4n z^mu(#z5JNC`yGvFqs@NCovj|@8-UO3eXF+ozO}Q7ZJxr!qQ<#fLf2Bt5<{EUZl7L7 z>n)q;d|NpZ{-Uxj+4t1%Stf(N-Jrrf+^ZC{HG!OeZHWH`-JK*{gTOy7k0{2 zR22X*+fJ=xPV1{Dz4iTv-n$u#BL?5mEuh2F6ES=o-#^6g031jUd840N>7dXqnQd0u z8*K!*93c$IHGO7`_N9GbIEP_H90C5rQ-lv8%=h1;vR*cO1TWi;xol9M4%>&PGU#F@ zmutEH7O3dfyOBvrB%l~NioP~iElh``qru+ce?%M7HpqNr^kA1H;qY3~MLm$(O5u+6 zaCaX{0@FgnfsiwR2=rw62+-e8z?$kU92gQ)yu6;1H{nozuq8(D70zyGv9jSaQRQfC zbZ2|y{?Ay$VWF*#CEBt{kx}iwx#UQw;QU*A2Ym-sq!~ou&Hk$%JRGRHuR($RaDM$_ zwjrpZk-Bk`_{R%ie|sUA{{SH9Z+|5INyY-AazrnU_J=HQkuqi4T^#Cwxk*v0A);n_;3txfT zJ;@OYUKxsmVfH>&s`j;LNYE6$|G`k3TI+mhg&%pS3)z;#$Gs ze;+#tD=L<%n>00wBuJ$mZ6lv%|3LF*%v{b*bE4KIEVcfp%4qdI<|iy>gCDa}Sv+fn zKx8M|m82stDQn-_Ua57(V%W9W4@V>Acm*PfIWZ>7U4W9i)rZ5l^~_@Q(?tfiomT3+ zDeQ(R2p*3Q^6+H#o5IGwvp@T-*G-jRF-dn-ePVGXdTnM^cPGe8w@IEiFi=n&R9#9ytUreGYlBcMTR%@t0XiUm$`RB^q2J`+4x59UzUTL zi(mPHKSf-wk#R>`Ozb1yXrx5cfiF)O^{EyF#;X0KyAsjpIF60xSHf~Ec=YgUzW(+2 zHTqjGJIl1qlo5tIRUvk(sHr*f5G9r!Hje_x@A0i(+G5&5kwvT6-3IXvBNamvp4;ZK zL#kO{@oWY2FWT(Eb`U-hPp0rIdwr8obIn?A>111TF?MDu&Tu}WZ6EJ*-$pgC86WyBkz!BDpup}SL%U+5WZ&+&(tmV<(X$t`&K6r1 zQaa=8HW?LP`6-)^OorIy;0;jkijq_3ce`C{CfDkX8;TlAxMlFfVQm;XgC8BlSyN?A zcTT;i4P9gY%Jih98fj0% z$at0=tEpP?tN%sF$jAsP6QCa2GSi+z;bW?i1ay8P!)|<<_N$k=BUoQGY3olp5AN0X z%tVh7Cp*-yamgi5g1ZKik|y4A7YExhI`UXZrJ$P$x=I!rl(5^Mtg8r?MLBOX8U=(1-sgrHX?yEw3)LS5SB`2vIs6SqBvwQe~L(Wlv?h z@60OP5S*QIpUK*+Q0M>F@N-F-D#vuNwCtq8G^~Y}j^pG7m#Z(+C$*m^JEvJBThrc) zrmMZ;nz3>r(Jt7-YHF6JGQ4qNHiORigJttU#L1#g6Mt)GF=H`f3bm@!7f$?5JUku? zl}o{kH6h6l+nHf=sr%<@7R}u?rE0aIPv5uR4^OZQ1tTIS>_oCrkHxJM0@gLU8M$mf z>1Nq%D7n#ml!txqqVnNfrJ4V*O)iLe&UaWLrwb78+(#K^WLzs@Upw4ouV=S4A zvlN@}`K|N&qM@qkjcTM75pD>_9u_OTP1GAvUP(oL5-4sO=e&qu13Ol-`Bm1>Vz3GE zL4pF+XKrUEPBaXR&WEbXN>fPyc6i756qE1uLV&^*?$ICneJg|IMb0_7hfHmhJt8#) zAIM8mmuhr}VGO*j0Y}I&3_dQbWFNn;xANiCVtKK9yW|GQMroL??`E+0QUa|R5#0f_JDpWX0H8Y7*^oHQ{ z&>+i4VVeW7K{C;Agl=ja4K*1Rp~ueiyHt~xuZ<@1ZZh>|{V(r&Y~Ij}s@|+5=;;eq zY$`XZSbF3aQ_{+#lT%Op)FPIz$OfBo5(zFx92yu|8-968xN`Bl+^*?`_)7XQ$4cXK z6LToXxoSEns+(I$@ouEe+);rZE@E*}f1j??0Tfd==SL%~CP2D;IKFv_hNhf|l)bkE z!@abHKsRuT=N!k8`_Jo(8}=26fre3wb7v*1&9Qjg7G*8rh-_xHW5th#2EXppxneT3 zV}A{tjbb@Bw_zW@&F`PDHka=dN8^6n&)r-8kgC-(c&&dXXRXOM5LTYpbwuwfg4!ZG z+^LmVQ@$(4EU99L32ikrVP?m}cD0q+;b3Cu82qb{)Z&~R@>^*$Ig8u(0@}=UKeuTS z6T`+`*auQ*lab;lZh9#oxJ*}ugF6mTC@iP8Yp^X47`H0FUbNW>qAb_Kf9QNHmd?4F zk67itwZ^2u)M;7t{IYuoOC8ZXFgjaRn{7U=mSHb-#)|!!@l9M_qaw#nT`n z&W;q%3OW^}bUV%M^c$f#a3zUtX6;j*B4L{944%5H01q!bKk=TQ?0~*h>_s8qkiNv{ zS{HOlX<(uztz8Xsxs5=IyWCkHBUp#fQM!24^Etm1^0?8=yU$FGlhusbDfv>x*y@3U zGHN(fwbQK~qZcaRfePunmIhSSmTO(j9NFoa;F`;^ z$l|!Oq3J3ojeANe^J{v%xNv3RGSFIW@y`EGu!acc6e&)dIM2sk>&yat5V@lE_V7%D z>zkVzsV7TRTs$ZtVIe6p*H!cQD}rwzR8VyAPz;bu3N3oTuhA6l$9W#ttK-H=z?<#r z>&u&cPvD1|Lvv#*xIOkkULNB597&eni^Iv|9cTMtiS+U7C-N8Hwwalj;Q`cNMm0X> zt+yWl3W~C=c23*v?-aj&Xh@pF`YVf{y=v2TYF-9z+LsCtc%g4ZFM>$1FU2-Bl~TtgTslCf8dQzl;Ifj1_%-QBX zcI=G(UScp?bGjseCM8#?9$?&M*m;uk)n;0=_4Is9OqqXNOMB|@Bu&Y}+Ik6dK}`mH zv>$Wod^mWOAkKuivW=}L@(gXq;NajnVkR{ggGt85#wXfB``6DF%F3(+Vx{UJYBX;= zSDZEp06!z`9 DataOutput: + data = "hello".encode("utf-8") + return DataOutput(description="A plumbus", data=data) + + +@app.post("/data-in-out") +def post_data_in_out(body: DataInputOutput) -> DataInputOutput: + return body diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index b83bc1b55b..0535c806f2 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -27,7 +27,7 @@ from pydantic._internal._schema_generation_shared import ( # type: ignore[attr- ) from pydantic._internal._typing_extra import eval_type_lenient from pydantic.fields import FieldInfo as FieldInfo -from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema +from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue from pydantic_core import CoreSchema as CoreSchema from pydantic_core import PydanticUndefined @@ -40,6 +40,23 @@ RequiredParam = PydanticUndefined Undefined = PydanticUndefined evaluate_forwardref = eval_type_lenient + +class GenerateJsonSchema(_GenerateJsonSchema): + # TODO: remove when this is merged (or equivalent): https://github.com/pydantic/pydantic/pull/12841 + # and dropping support for any version of Pydantic before that one (so, in a very long time) + def bytes_schema(self, schema: CoreSchema) -> JsonSchemaValue: + json_schema = {"type": "string", "contentMediaType": "application/octet-stream"} + bytes_mode = ( + self._config.ser_json_bytes + if self.mode == "serialization" + else self._config.val_json_bytes + ) + if bytes_mode == "base64": + json_schema["contentEncoding"] = "base64" + self.update_with_validations(json_schema, schema, self.ValidationsMapping.bytes) + return json_schema + + # TODO: remove when dropping support for Pydantic < v2.12.3 _Attrs = { "default": ..., diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py index c04b5f0f39..479e1a7c3b 100644 --- a/fastapi/datastructures.py +++ b/fastapi/datastructures.py @@ -139,7 +139,7 @@ class UploadFile(StarletteUploadFile): def __get_pydantic_json_schema__( cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler ) -> dict[str, Any]: - return {"type": "string", "format": "binary"} + return {"type": "string", "contentMediaType": "application/octet-stream"} @classmethod def __get_pydantic_core_schema__( diff --git a/pyproject.toml b/pyproject.toml index 1e6fda3b1c..92b4739458 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -548,6 +548,7 @@ ignore = [ "docs_src/security/tutorial005_an_py39.py" = ["B904"] "docs_src/security/tutorial005_py310.py" = ["B904"] "docs_src/security/tutorial005_py39.py" = ["B904"] +"docs_src/json_base64_bytes/tutorial001_py310.py" = ["UP012"] [tool.ruff.lint.isort] known-third-party = ["fastapi", "pydantic", "starlette"] diff --git a/scripts/playwright/json_base64_bytes/image01.py b/scripts/playwright/json_base64_bytes/image01.py new file mode 100644 index 0000000000..56c57e1c32 --- /dev/null +++ b/scripts/playwright/json_base64_bytes/image01.py @@ -0,0 +1,37 @@ +import subprocess +import time + +import httpx +from playwright.sync_api import Playwright, sync_playwright + + +# Run playwright codegen to generate the code below, copy paste the sections in run() +def run(playwright: Playwright) -> None: + browser = playwright.chromium.launch(headless=False) + # Update the viewport manually + context = browser.new_context(viewport={"width": 960, "height": 1080}) + page = context.new_page() + page.goto("http://localhost:8000/docs") + page.get_by_role("button", name="POST /data Post Data").click() + # Manually add the screenshot + page.screenshot(path="docs/en/docs/img/tutorial/json-base64-bytes/image01.png") + + # --------------------- + context.close() + browser.close() + + +process = subprocess.Popen( + ["fastapi", "run", "docs_src/json_base64_bytes/tutorial001_py310.py"] +) +try: + for _ in range(3): + try: + response = httpx.get("http://localhost:8000/docs") + except httpx.ConnectError: + time.sleep(1) + break + with sync_playwright() as playwright: + run(playwright) +finally: + process.terminate() diff --git a/tests/test_request_params/test_file/test_list.py b/tests/test_request_params/test_file/test_list.py index 68280fcf32..5332795f4c 100644 --- a/tests/test_request_params/test_file/test_list.py +++ b/tests/test_request_params/test_file/test_list.py @@ -37,7 +37,10 @@ def test_list_schema(path: str): "properties": { "p": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P", }, }, @@ -115,7 +118,10 @@ def test_list_alias_schema(path: str): "properties": { "p_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Alias", }, }, @@ -221,7 +227,10 @@ def test_list_validation_alias_schema(path: str): "properties": { "p_val_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Val Alias", }, }, @@ -338,7 +347,10 @@ def test_list_alias_and_validation_alias_schema(path: str): "properties": { "p_val_alias": { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "title": "P Val Alias", }, }, diff --git a/tests/test_request_params/test_file/test_optional.py b/tests/test_request_params/test_file/test_optional.py index b4dc11a06a..3d1aac25e2 100644 --- a/tests/test_request_params/test_file/test_optional.py +++ b/tests/test_request_params/test_file/test_optional.py @@ -37,7 +37,7 @@ def test_optional_schema(path: str): "properties": { "p": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P", @@ -109,7 +109,7 @@ def test_optional_alias_schema(path: str): "properties": { "p_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Alias", @@ -200,7 +200,7 @@ def test_optional_validation_alias_schema(path: str): "properties": { "p_val_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Val Alias", @@ -296,7 +296,7 @@ def test_optional_alias_and_validation_alias_schema(path: str): "properties": { "p_val_alias": { "anyOf": [ - {"type": "string", "format": "binary"}, + {"type": "string", "contentMediaType": "application/octet-stream"}, {"type": "null"}, ], "title": "P Val Alias", diff --git a/tests/test_request_params/test_file/test_optional_list.py b/tests/test_request_params/test_file/test_optional_list.py index a506ec991f..3c211b1e8e 100644 --- a/tests/test_request_params/test_file/test_optional_list.py +++ b/tests/test_request_params/test_file/test_optional_list.py @@ -41,7 +41,10 @@ def test_optional_list_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -116,7 +119,10 @@ def test_optional_list_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -205,7 +211,10 @@ def test_optional_validation_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], @@ -301,7 +310,10 @@ def test_optional_list_alias_and_validation_alias_schema(path: str): "anyOf": [ { "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, {"type": "null"}, ], diff --git a/tests/test_request_params/test_file/test_required.py b/tests/test_request_params/test_file/test_required.py index a0f9d23a6b..22d6c0fffd 100644 --- a/tests/test_request_params/test_file/test_required.py +++ b/tests/test_request_params/test_file/test_required.py @@ -35,7 +35,11 @@ def test_required_schema(path: str): assert app.openapi()["components"]["schemas"][body_model_name] == { "properties": { - "p": {"title": "P", "type": "string", "format": "binary"}, + "p": { + "title": "P", + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, "required": ["p"], "title": body_model_name, @@ -109,7 +113,11 @@ def test_required_alias_schema(path: str): assert app.openapi()["components"]["schemas"][body_model_name] == { "properties": { - "p_alias": {"title": "P Alias", "type": "string", "format": "binary"}, + "p_alias": { + "title": "P Alias", + "type": "string", + "contentMediaType": "application/octet-stream", + }, }, "required": ["p_alias"], "title": body_model_name, @@ -216,7 +224,7 @@ def test_required_validation_alias_schema(path: str): "p_val_alias": { "title": "P Val Alias", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, }, "required": ["p_val_alias"], @@ -329,7 +337,7 @@ def test_required_alias_and_validation_alias_schema(path: str): "p_val_alias": { "title": "P Val Alias", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, }, "required": ["p_val_alias"], diff --git a/tests/test_tutorial/test_json_base64_bytes/__init__.py b/tests/test_tutorial/test_json_base64_bytes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py b/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py new file mode 100644 index 0000000000..4d70bca5f3 --- /dev/null +++ b/tests/test_tutorial/test_json_base64_bytes/test_tutorial001.py @@ -0,0 +1,225 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +from tests.utils import needs_py310 + + +@pytest.fixture( + name="client", + params=[pytest.param("tutorial001_py310", marks=needs_py310)], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.json_base64_bytes.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_post_data(client: TestClient): + response = client.post( + "/data", + json={ + "description": "A file", + "data": "SGVsbG8sIFdvcmxkIQ==", + }, + ) + assert response.status_code == 200, response.text + assert response.json() == {"description": "A file", "content": "Hello, World!"} + + +def test_get_data(client: TestClient): + response = client.get("/data") + assert response.status_code == 200, response.text + assert response.json() == {"description": "A plumbus", "data": "aGVsbG8="} + + +def test_post_data_in_out(client: TestClient): + response = client.post( + "/data-in-out", + json={ + "description": "A plumbus", + "data": "SGVsbG8sIFdvcmxkIQ==", + }, + ) + assert response.status_code == 200, response.text + assert response.json() == { + "description": "A plumbus", + "data": "SGVsbG8sIFdvcmxkIQ==", + } + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/data": { + "get": { + "summary": "Get Data", + "operationId": "get_data_data_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataOutput" + } + } + }, + } + }, + }, + "post": { + "summary": "Post Data", + "operationId": "post_data_data_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/DataInput"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + }, + }, + "/data-in-out": { + "post": { + "summary": "Post Data In Out", + "operationId": "post_data_in_out_data_in_out_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataInputOutput" + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataInputOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + }, + "components": { + "schemas": { + "DataInput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataInput", + }, + "DataInputOutput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataInputOutput", + }, + "DataOutput": { + "properties": { + "description": {"type": "string", "title": "Description"}, + "data": { + "type": "string", + "contentEncoding": "base64", + "contentMediaType": "application/octet-stream", + "title": "Data", + }, + }, + "type": "object", + "required": ["description", "data"], + "title": "DataOutput", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "ctx": {"title": "Context", "type": "object"}, + "input": {"title": "Input"}, + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index 4d3c35d65d..797225bc2d 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -162,8 +162,8 @@ def test_openapi_schema(client: TestClient): "properties": { "file": { "title": "File", + "contentMediaType": "application/octet-stream", "type": "string", - "format": "binary", } }, }, @@ -175,7 +175,7 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index f199b992ae..4e3c33818e 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -134,7 +134,10 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "anyOf": [ - {"type": "string", "format": "binary"}, + { + "type": "string", + "contentMediaType": "application/octet-stream", + }, {"type": "null"}, ], } @@ -147,7 +150,10 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "anyOf": [ - {"type": "string", "format": "binary"}, + { + "type": "string", + "contentMediaType": "application/octet-stream", + }, {"type": "null"}, ], } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index ce22c1b5c4..bccc617046 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -123,7 +123,7 @@ def test_openapi_schema(client: TestClient): "title": "File", "type": "string", "description": "A file read as bytes", - "format": "binary", + "contentMediaType": "application/octet-stream", } }, }, @@ -134,9 +134,9 @@ def test_openapi_schema(client: TestClient): "properties": { "file": { "title": "File", + "contentMediaType": "application/octet-stream", "type": "string", "description": "A file read as UploadFile", - "format": "binary", } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index ebf76b3a07..123468d48f 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -195,7 +195,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, } }, }, @@ -207,7 +210,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, } }, }, diff --git a/tests/test_tutorial/test_request_files/test_tutorial003.py b/tests/test_tutorial/test_request_files/test_tutorial003.py index f11658d27c..2f554d9489 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial003.py +++ b/tests/test_tutorial/test_request_files/test_tutorial003.py @@ -165,7 +165,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "description": "Multiple files as bytes", } }, @@ -178,7 +181,10 @@ def test_openapi_schema(client: TestClient): "files": { "title": "Files", "type": "array", - "items": {"type": "string", "format": "binary"}, + "items": { + "type": "string", + "contentMediaType": "application/octet-stream", + }, "description": "Multiple files as UploadFile", } }, diff --git a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py index e2462e040b..cc10d8bec5 100644 --- a/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py @@ -198,12 +198,12 @@ def test_openapi_schema(client: TestClient): "file": { "title": "File", "type": "string", - "format": "binary", + "contentMediaType": "application/octet-stream", }, "fileb": { "title": "Fileb", + "contentMediaType": "application/octet-stream", "type": "string", - "format": "binary", }, "token": {"title": "Token", "type": "string"}, }, From 1bf99b9a112031090224bca6727b9b5fa8028d79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 21 Feb 2026 13:01:58 +0000 Subject: [PATCH 256/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d579a3cb0a..fe70b9e87c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* ๐Ÿ› Fix JSON Schema for files, use `contentMediaType` instead of `format: binary`. PR [#14953](https://github.com/fastapi/fastapi/pull/14953) by [@tiangolo](https://github.com/tiangolo). + ### Docs * ๐Ÿ”จ Add Kapa.ai widget (AI chatbot). PR [#14938](https://github.com/fastapi/fastapi/pull/14938) by [@tiangolo](https://github.com/tiangolo). From 04ff07fecd5273f4cd58d1de43a3b445c8e75852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 14:07:09 +0100 Subject: [PATCH 257/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fe70b9e87c..1b0c73dc92 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,7 +9,7 @@ hide: ### Fixes -* ๐Ÿ› Fix JSON Schema for files, use `contentMediaType` instead of `format: binary`. PR [#14953](https://github.com/fastapi/fastapi/pull/14953) by [@tiangolo](https://github.com/tiangolo). +* โ™ป๏ธ Fix JSON Schema for bytes, use `"contentMediaType": "application/octet-stream"` instead of `"format": "binary"`. PR [#14953](https://github.com/fastapi/fastapi/pull/14953) by [@tiangolo](https://github.com/tiangolo). ### Docs From c91fed958e46492be96ab8bc19a16f74c3c2048a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 14:08:06 +0100 Subject: [PATCH 258/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?9.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1b0c73dc92..ad31504891 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.129.1 + ### Fixes * โ™ป๏ธ Fix JSON Schema for bytes, use `"contentMediaType": "application/octet-stream"` instead of `"format": "binary"`. PR [#14953](https://github.com/fastapi/fastapi/pull/14953) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index de5a0be382..1591a81cf0 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.129.0" +__version__ = "0.129.1" from starlette import status as status From f55ab7e020701de7b5e467dad9bafcf1aeab30c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 08:16:03 -0800 Subject: [PATCH 259/367] =?UTF-8?q?=F0=9F=94=A7=20Update=20pyproject.toml,?= =?UTF-8?q?=20remove=20unneeded=20lines=20(#14956)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/labeler.yml | 1 - docs_src/python_types/tutorial005_py39.py | 2 - pyproject.toml | 213 +--------------------- 3 files changed, 3 insertions(+), 213 deletions(-) delete mode 100644 docs_src/python_types/tutorial005_py39.py diff --git a/.github/labeler.yml b/.github/labeler.yml index 57c5e1120f..2ee7541166 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -30,7 +30,6 @@ internal: - .gitignore - .pre-commit-config.yaml - pdm_build.py - - requirements*.txt - uv.lock - docs/en/data/sponsors.yml - docs/en/overrides/main.html diff --git a/docs_src/python_types/tutorial005_py39.py b/docs_src/python_types/tutorial005_py39.py deleted file mode 100644 index 6c8edb0ec4..0000000000 --- a/docs_src/python_types/tutorial005_py39.py +++ /dev/null @@ -1,2 +0,0 @@ -def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes): - return item_a, item_b, item_c, item_d, item_e diff --git a/pyproject.toml b/pyproject.toml index 92b4739458..d2a025a72e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,6 @@ Issues = "https://github.com/fastapi/fastapi/issues" Changelog = "https://fastapi.tiangolo.com/release-notes/" [project.optional-dependencies] - standard = [ "fastapi-cli[standard] >=0.0.8", # For the test client @@ -245,25 +244,16 @@ disallow_incomplete_defs = false disallow_untyped_defs = false disallow_untyped_calls = false -[tool.pytest.ini_options] +[tool.pytest] +minversion = "9.0" addopts = [ "--strict-config", "--strict-markers", "--ignore=docs_src", ] -xfail_strict = true -junit_family = "xunit2" +strict_xfail = true filterwarnings = [ "error", - # see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28 - "ignore:You seem to already have a custom.*:RuntimeWarning:trio", - # TODO: remove after upgrading SQLAlchemy to a version that includes the following changes - # https://github.com/sqlalchemy/sqlalchemy/commit/59521abcc0676e936b31a523bd968fc157fef0c2 - 'ignore:datetime\.datetime\.utcfromtimestamp\(\) is deprecated and scheduled for removal in a future version\..*:DeprecationWarning:sqlalchemy', - # Trio 24.1.0 raises a warning from attrs - # Ref: https://github.com/python-trio/trio/pull/3054 - # Remove once there's a new version of Trio - 'ignore:The `hash` argument is deprecated*:DeprecationWarning:trio', ] [tool.coverage.run] @@ -280,7 +270,6 @@ dynamic_context = "test_function" omit = [ "docs_src/response_model/tutorial003_04_py39.py", "docs_src/response_model/tutorial003_04_py310.py", - "docs_src/dependencies/tutorial008_an_py39.py", # difficult to mock "docs_src/dependencies/tutorial013_an_py310.py", # temporary code example? "docs_src/dependencies/tutorial014_an_py310.py", # temporary code example? # Pydantic v1 migration, no longer tested @@ -288,202 +277,6 @@ omit = [ "docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py", "docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py", "docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py", - # TODO: remove all the ignores below when all translations use the new Python 3.10 files - "docs_src/additional_responses/tutorial001_py39.py", - "docs_src/additional_responses/tutorial003_py39.py", - "docs_src/advanced_middleware/tutorial001_py39.py", - "docs_src/advanced_middleware/tutorial002_py39.py", - "docs_src/advanced_middleware/tutorial003_py39.py", - "docs_src/app_testing/app_a_py39/main.py", - "docs_src/app_testing/app_a_py39/test_main.py", - "docs_src/app_testing/tutorial001_py39.py", - "docs_src/app_testing/tutorial002_py39.py", - "docs_src/app_testing/tutorial003_py39.py", - "docs_src/app_testing/tutorial004_py39.py", - "docs_src/async_tests/app_a_py39/main.py", - "docs_src/async_tests/app_a_py39/test_main.py", - "docs_src/authentication_error_status_code/tutorial001_an_py39.py", - "docs_src/background_tasks/tutorial001_py39.py", - "docs_src/behind_a_proxy/tutorial001_01_py39.py", - "docs_src/behind_a_proxy/tutorial001_py39.py", - "docs_src/behind_a_proxy/tutorial002_py39.py", - "docs_src/behind_a_proxy/tutorial003_py39.py", - "docs_src/behind_a_proxy/tutorial004_py39.py", - "docs_src/bigger_applications/app_an_py39/dependencies.py", - "docs_src/bigger_applications/app_an_py39/internal/admin.py", - "docs_src/bigger_applications/app_an_py39/main.py", - "docs_src/bigger_applications/app_an_py39/routers/items.py", - "docs_src/bigger_applications/app_an_py39/routers/users.py", - "docs_src/bigger_applications/app_py39/dependencies.py", - "docs_src/bigger_applications/app_py39/main.py", - "docs_src/body_nested_models/tutorial008_py39.py", - "docs_src/body_nested_models/tutorial009_py39.py", - "docs_src/conditional_openapi/tutorial001_py39.py", - "docs_src/configure_swagger_ui/tutorial001_py39.py", - "docs_src/configure_swagger_ui/tutorial002_py39.py", - "docs_src/configure_swagger_ui/tutorial003_py39.py", - "docs_src/cors/tutorial001_py39.py", - "docs_src/custom_docs_ui/tutorial001_py39.py", - "docs_src/custom_docs_ui/tutorial002_py39.py", - "docs_src/custom_response/tutorial001_py39.py", - "docs_src/custom_response/tutorial001b_py39.py", - "docs_src/custom_response/tutorial002_py39.py", - "docs_src/custom_response/tutorial003_py39.py", - "docs_src/custom_response/tutorial004_py39.py", - "docs_src/custom_response/tutorial005_py39.py", - "docs_src/custom_response/tutorial006_py39.py", - "docs_src/custom_response/tutorial006b_py39.py", - "docs_src/custom_response/tutorial006c_py39.py", - "docs_src/custom_response/tutorial007_py39.py", - "docs_src/custom_response/tutorial008_py39.py", - "docs_src/custom_response/tutorial009_py39.py", - "docs_src/custom_response/tutorial009b_py39.py", - "docs_src/custom_response/tutorial009c_py39.py", - "docs_src/custom_response/tutorial010_py39.py", - "docs_src/debugging/tutorial001_py39.py", - "docs_src/dependencies/tutorial006_an_py39.py", - "docs_src/dependencies/tutorial006_py39.py", - "docs_src/dependencies/tutorial007_py39.py", - "docs_src/dependencies/tutorial008_py39.py", - "docs_src/dependencies/tutorial008b_an_py39.py", - "docs_src/dependencies/tutorial008b_py39.py", - "docs_src/dependencies/tutorial008c_an_py39.py", - "docs_src/dependencies/tutorial008c_py39.py", - "docs_src/dependencies/tutorial008d_an_py39.py", - "docs_src/dependencies/tutorial008d_py39.py", - "docs_src/dependencies/tutorial008e_an_py39.py", - "docs_src/dependencies/tutorial008e_py39.py", - "docs_src/dependencies/tutorial010_py39.py", - "docs_src/dependencies/tutorial011_an_py39.py", - "docs_src/dependencies/tutorial011_py39.py", - "docs_src/dependencies/tutorial012_an_py39.py", - "docs_src/dependencies/tutorial012_py39.py", - "docs_src/events/tutorial001_py39.py", - "docs_src/events/tutorial002_py39.py", - "docs_src/events/tutorial003_py39.py", - "docs_src/extending_openapi/tutorial001_py39.py", - "docs_src/extra_models/tutorial004_py39.py", - "docs_src/extra_models/tutorial005_py39.py", - "docs_src/first_steps/tutorial001_py39.py", - "docs_src/first_steps/tutorial003_py39.py", - "docs_src/generate_clients/tutorial001_py39.py", - "docs_src/generate_clients/tutorial002_py39.py", - "docs_src/generate_clients/tutorial003_py39.py", - "docs_src/generate_clients/tutorial004_py39.py", - "docs_src/graphql_/tutorial001_py39.py", - "docs_src/handling_errors/tutorial001_py39.py", - "docs_src/handling_errors/tutorial002_py39.py", - "docs_src/handling_errors/tutorial003_py39.py", - "docs_src/handling_errors/tutorial004_py39.py", - "docs_src/handling_errors/tutorial005_py39.py", - "docs_src/handling_errors/tutorial006_py39.py", - "docs_src/metadata/tutorial001_1_py39.py", - "docs_src/metadata/tutorial001_py39.py", - "docs_src/metadata/tutorial002_py39.py", - "docs_src/metadata/tutorial003_py39.py", - "docs_src/metadata/tutorial004_py39.py", - "docs_src/middleware/tutorial001_py39.py", - "docs_src/openapi_webhooks/tutorial001_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial001_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial002_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial003_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial005_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial006_py39.py", - "docs_src/path_operation_advanced_configuration/tutorial007_py39.py", - "docs_src/path_operation_configuration/tutorial002b_py39.py", - "docs_src/path_operation_configuration/tutorial006_py39.py", - "docs_src/path_params/tutorial001_py39.py", - "docs_src/path_params/tutorial002_py39.py", - "docs_src/path_params/tutorial003_py39.py", - "docs_src/path_params/tutorial003b_py39.py", - "docs_src/path_params/tutorial004_py39.py", - "docs_src/path_params/tutorial005_py39.py", - "docs_src/path_params_numeric_validations/tutorial002_an_py39.py", - "docs_src/path_params_numeric_validations/tutorial002_py39.py", - "docs_src/path_params_numeric_validations/tutorial003_an_py39.py", - "docs_src/path_params_numeric_validations/tutorial003_py39.py", - "docs_src/path_params_numeric_validations/tutorial004_an_py39.py", - "docs_src/path_params_numeric_validations/tutorial004_py39.py", - "docs_src/path_params_numeric_validations/tutorial005_an_py39.py", - "docs_src/path_params_numeric_validations/tutorial005_py39.py", - "docs_src/path_params_numeric_validations/tutorial006_an_py39.py", - "docs_src/path_params_numeric_validations/tutorial006_py39.py", - "docs_src/python_types/tutorial001_py39.py", - "docs_src/python_types/tutorial002_py39.py", - "docs_src/python_types/tutorial003_py39.py", - "docs_src/python_types/tutorial004_py39.py", - "docs_src/python_types/tutorial005_py39.py", - "docs_src/python_types/tutorial006_py39.py", - "docs_src/python_types/tutorial007_py39.py", - "docs_src/python_types/tutorial008_py39.py", - "docs_src/python_types/tutorial008b_py39.py", - "docs_src/python_types/tutorial009_py39.py", - "docs_src/python_types/tutorial009b_py39.py", - "docs_src/python_types/tutorial009c_py39.py", - "docs_src/python_types/tutorial010_py39.py", - "docs_src/python_types/tutorial013_py39.py", - "docs_src/query_params/tutorial001_py39.py", - "docs_src/query_params/tutorial005_py39.py", - "docs_src/query_params_str_validations/tutorial005_an_py39.py", - "docs_src/query_params_str_validations/tutorial005_py39.py", - "docs_src/query_params_str_validations/tutorial006_an_py39.py", - "docs_src/query_params_str_validations/tutorial006_py39.py", - "docs_src/query_params_str_validations/tutorial012_an_py39.py", - "docs_src/query_params_str_validations/tutorial012_py39.py", - "docs_src/query_params_str_validations/tutorial013_an_py39.py", - "docs_src/query_params_str_validations/tutorial013_py39.py", - "docs_src/request_files/tutorial001_03_an_py39.py", - "docs_src/request_files/tutorial001_03_py39.py", - "docs_src/request_files/tutorial001_an_py39.py", - "docs_src/request_files/tutorial001_py39.py", - "docs_src/request_files/tutorial002_an_py39.py", - "docs_src/request_files/tutorial002_py39.py", - "docs_src/request_files/tutorial003_an_py39.py", - "docs_src/request_files/tutorial003_py39.py", - "docs_src/request_form_models/tutorial001_an_py39.py", - "docs_src/request_form_models/tutorial001_py39.py", - "docs_src/request_form_models/tutorial002_an_py39.py", - "docs_src/request_form_models/tutorial002_py39.py", - "docs_src/request_forms/tutorial001_an_py39.py", - "docs_src/request_forms/tutorial001_py39.py", - "docs_src/request_forms_and_files/tutorial001_an_py39.py", - "docs_src/request_forms_and_files/tutorial001_py39.py", - "docs_src/response_change_status_code/tutorial001_py39.py", - "docs_src/response_cookies/tutorial001_py39.py", - "docs_src/response_cookies/tutorial002_py39.py", - "docs_src/response_directly/tutorial002_py39.py", - "docs_src/response_headers/tutorial001_py39.py", - "docs_src/response_headers/tutorial002_py39.py", - "docs_src/response_model/tutorial003_02_py39.py", - "docs_src/response_model/tutorial003_03_py39.py", - "docs_src/response_status_code/tutorial001_py39.py", - "docs_src/response_status_code/tutorial002_py39.py", - "docs_src/security/tutorial001_an_py39.py", - "docs_src/security/tutorial001_py39.py", - "docs_src/security/tutorial006_an_py39.py", - "docs_src/security/tutorial006_py39.py", - "docs_src/security/tutorial007_an_py39.py", - "docs_src/security/tutorial007_py39.py", - "docs_src/settings/app01_py39/config.py", - "docs_src/settings/app01_py39/main.py", - "docs_src/settings/app02_an_py39/config.py", - "docs_src/settings/app02_an_py39/main.py", - "docs_src/settings/app02_an_py39/test_main.py", - "docs_src/settings/app02_py39/config.py", - "docs_src/settings/app02_py39/main.py", - "docs_src/settings/app02_py39/test_main.py", - "docs_src/settings/app03_an_py39/config.py", - "docs_src/settings/app03_an_py39/main.py", - "docs_src/settings/app03_py39/config.py", - "docs_src/settings/app03_py39/main.py", - "docs_src/settings/tutorial001_py39.py", - "docs_src/static_files/tutorial001_py39.py", - "docs_src/sub_applications/tutorial001_py39.py", - "docs_src/templates/tutorial001_py39.py", - "docs_src/using_request_directly/tutorial001_py39.py", - "docs_src/websockets/tutorial001_py39.py", - "docs_src/websockets/tutorial003_py39.py", - "docs_src/wsgi/tutorial001_py39.py", ] [tool.coverage.report] From 1b9a351ee844ff49cdcfa3913f38a12b24b79173 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 21 Feb 2026 16:16:27 +0000 Subject: [PATCH 260/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ad31504891..1f348af999 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ๐Ÿ”ง Update pyproject.toml, remove unneeded lines. PR [#14956](https://github.com/fastapi/fastapi/pull/14956) by [@tiangolo](https://github.com/tiangolo). + ## 0.129.1 ### Fixes From 083b6ebe9efa76cdee3fe3f74ea686a2ea860f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 08:26:38 -0800 Subject: [PATCH 261/367] =?UTF-8?q?=E2=9E=96=20Drop=20support=20for=20`fas?= =?UTF-8?q?tapi-slim`,=20no=20more=20versions=20will=20be=20released,=20us?= =?UTF-8?q?e=20only=20`"fastapi[standard]"`=20or=20`fastapi`=20(#14957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/labeler.yml | 1 - pdm_build.py | 40 ---------------------------------------- pyproject.toml | 26 -------------------------- 3 files changed, 67 deletions(-) delete mode 100644 pdm_build.py diff --git a/.github/labeler.yml b/.github/labeler.yml index 2ee7541166..3c0bf473e0 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -29,7 +29,6 @@ internal: - scripts/** - .gitignore - .pre-commit-config.yaml - - pdm_build.py - uv.lock - docs/en/data/sponsors.yml - docs/en/overrides/main.html diff --git a/pdm_build.py b/pdm_build.py deleted file mode 100644 index b1b662bd39..0000000000 --- a/pdm_build.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -from typing import Any - -from pdm.backend.hooks import Context - -TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE") - - -def pdm_build_initialize(context: Context) -> None: - metadata = context.config.metadata - # Get main version - version = metadata["version"] - # Get custom config for the current package, from the env var - all_configs_config: dict[str, Any] = context.config.data["tool"]["tiangolo"][ - "_internal-slim-build" - ]["packages"] - - if TIANGOLO_BUILD_PACKAGE not in all_configs_config: - return - - config = all_configs_config[TIANGOLO_BUILD_PACKAGE] - project_config: dict[str, Any] = config["project"] - # Override main [project] configs with custom configs for this package - for key, value in project_config.items(): - metadata[key] = value - # Get custom build config for the current package - build_config: dict[str, Any] = ( - config.get("tool", {}).get("pdm", {}).get("build", {}) - ) - # Override PDM build config with custom build config for this package - for key, value in build_config.items(): - context.config.build_config[key] = value - # Get main dependencies - dependencies: list[str] = metadata.get("dependencies", []) - # Sync versions in dependencies - new_dependencies = [] - for dep in dependencies: - new_dep = f"{dep}>={version}" - new_dependencies.append(new_dep) - metadata["dependencies"] = new_dependencies diff --git a/pyproject.toml b/pyproject.toml index d2a025a72e..199dc2a6fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -198,32 +198,6 @@ source-includes = [ "docs/en/docs/img/favicon.png", ] -[tool.tiangolo._internal-slim-build.packages.fastapi-slim.project] -name = "fastapi-slim" -readme = "fastapi-slim/README.md" -dependencies = [ - "fastapi", -] -optional-dependencies = {} -scripts = {} - -[tool.tiangolo._internal-slim-build.packages.fastapi-slim.tool.pdm.build] -# excludes needs to explicitly exclude the top level python packages, -# otherwise PDM includes them by default -# A "*" glob pattern can't be used here because in PDM internals, the patterns are put -# in a set (unordered, order varies) and each excluded file is assigned one of the -# glob patterns that matches, as the set is unordered, the matched pattern could be "*" -# independent of the order here. And then the internal code would give it a lower score -# than the one for a default included file. -# By not using "*" and explicitly excluding the top level packages, they get a higher -# score than the default inclusion -excludes = ["fastapi", "tests", "pdm_build.py"] -# source-includes needs to explicitly define some value because PDM will check the -# truthy value of the list, and if empty, will include some defaults, including "tests", -# an empty string doesn't match anything, but makes the list truthy, so that PDM -# doesn't override it during the build. -source-includes = [""] - [tool.mypy] plugins = ["pydantic.mypy"] strict = true From 69ae1d0f287acea3bf02e968f963ee6d225f3c50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 21 Feb 2026 16:27:01 +0000 Subject: [PATCH 262/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1f348af999..ec5869516d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* โž– Drop support for `fastapi-slim`, no more versions will be released, use only `"fastapi[standard]"` or `fastapi`. PR [#14957](https://github.com/fastapi/fastapi/pull/14957) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update pyproject.toml, remove unneeded lines. PR [#14956](https://github.com/fastapi/fastapi/pull/14956) by [@tiangolo](https://github.com/tiangolo). ## 0.129.1 From c9455d54002a1a80dec884e96ada5cffccdc32bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 08:45:15 -0800 Subject: [PATCH 263/367] =?UTF-8?q?=F0=9F=91=B7=20Fix=20CI,=20do=20not=20a?= =?UTF-8?q?ttempt=20to=20publish=20`fastapi-slim`=20(#14958)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2232498cb1..58f4f6dd8a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,11 +8,6 @@ on: jobs: publish: runs-on: ubuntu-latest - strategy: - matrix: - package: - - fastapi - - fastapi-slim permissions: id-token: write contents: read @@ -26,14 +21,9 @@ jobs: uses: actions/setup-python@v6 with: python-version-file: ".python-version" - # Issue ref: https://github.com/actions/setup-python/issues/436 - # cache: "pip" - # cache-dependency-path: pyproject.toml - name: Install uv uses: astral-sh/setup-uv@v7 - name: Build distribution run: uv build - env: - TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} - name: Publish run: uv publish From 468d5173edf8d16342ee67f3cb433428b58dceac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 21 Feb 2026 16:45:38 +0000 Subject: [PATCH 264/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ec5869516d..7f42cd490f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ๐Ÿ‘ท Fix CI, do not attempt to publish `fastapi-slim`. PR [#14958](https://github.com/fastapi/fastapi/pull/14958) by [@tiangolo](https://github.com/tiangolo). * โž– Drop support for `fastapi-slim`, no more versions will be released, use only `"fastapi[standard]"` or `fastapi`. PR [#14957](https://github.com/fastapi/fastapi/pull/14957) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update pyproject.toml, remove unneeded lines. PR [#14956](https://github.com/fastapi/fastapi/pull/14956) by [@tiangolo](https://github.com/tiangolo). From 4ab8138554ed830ba543e57e810fe47f22441e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 09:22:54 -0800 Subject: [PATCH 265/367] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20pytest?= =?UTF-8?q?=20(#14959)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 199dc2a6fc..c51eb8ce9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -170,7 +170,7 @@ tests = [ "mypy >=1.14.1", "pwdlib[argon2] >=0.2.1", "pyjwt >=2.9.0", - "pytest >=7.1.3,<9.0.0", + "pytest >=9.0.0", "pytest-codspeed >=4.2.0", "pyyaml >=5.3.1,<7.0.0", "sqlmodel >=0.0.31", diff --git a/uv.lock b/uv.lock index aa8c558c7d..15ca8714f6 100644 --- a/uv.lock +++ b/uv.lock @@ -1276,7 +1276,7 @@ dev = [ { name = "pydantic-ai", specifier = ">=0.4.10" }, { name = "pygithub", specifier = ">=2.8.1" }, { name = "pyjwt", specifier = ">=2.9.0" }, - { name = "pytest", specifier = ">=7.1.3,<9.0.0" }, + { name = "pytest", specifier = ">=9.0.0" }, { name = "pytest-codspeed", specifier = ">=4.2.0" }, { name = "python-slugify", specifier = ">=8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, @@ -1329,7 +1329,7 @@ tests = [ { name = "mypy", specifier = ">=1.14.1" }, { name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" }, { name = "pyjwt", specifier = ">=2.9.0" }, - { name = "pytest", specifier = ">=7.1.3,<9.0.0" }, + { name = "pytest", specifier = ">=9.0.0" }, { name = "pytest-codspeed", specifier = ">=4.2.0" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = ">=0.14.14" }, @@ -4330,7 +4330,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.2" +version = "9.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -4341,9 +4341,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] [[package]] From f921de6495a9d770fafc62f81274bdb6c0ee1e31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 21 Feb 2026 17:23:22 +0000 Subject: [PATCH 266/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7f42cd490f..bf29c06135 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* โฌ†๏ธ Upgrade pytest. PR [#14959](https://github.com/fastapi/fastapi/pull/14959) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Fix CI, do not attempt to publish `fastapi-slim`. PR [#14958](https://github.com/fastapi/fastapi/pull/14958) by [@tiangolo](https://github.com/tiangolo). * โž– Drop support for `fastapi-slim`, no more versions will be released, use only `"fastapi[standard]"` or `fastapi`. PR [#14957](https://github.com/fastapi/fastapi/pull/14957) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ”ง Update pyproject.toml, remove unneeded lines. PR [#14956](https://github.com/fastapi/fastapi/pull/14956) by [@tiangolo](https://github.com/tiangolo). From 1e78a36b7310003f0ff634627d8a7bc53c6ccdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 21 Feb 2026 18:24:59 +0100 Subject: [PATCH 267/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.12?= =?UTF-8?q?9.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bf29c06135..edcb3db8d6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.129.2 + ### Internal * โฌ†๏ธ Upgrade pytest. PR [#14959](https://github.com/fastapi/fastapi/pull/14959) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 1591a81cf0..e6798ddc6d 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.129.1" +__version__ = "0.129.2" from starlette import status as status From 590a5e535587cc07041ba12d308c748433ccb168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 08:07:19 -0800 Subject: [PATCH 268/367] =?UTF-8?q?=E2=9C=A8=20Serialize=20JSON=20response?= =?UTF-8?q?=20with=20Pydantic=20(in=20Rust),=20when=20there's=20a=20Pydant?= =?UTF-8?q?ic=20return=20type=20or=20response=20model=20(#14962)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/custom-response.md | 80 +++++-------------- docs/en/docs/advanced/response-directly.md | 28 +++++-- docs/en/docs/how-to/general.md | 4 + docs/en/docs/tutorial/response-model.md | 1 + docs_src/custom_response/tutorial010_py310.py | 6 +- fastapi/_compat/v2.py | 26 ++++++ fastapi/routing.py | 23 +++++- tests/test_dump_json_fast_path.py | 51 ++++++++++++ .../test_custom_response/test_tutorial001.py | 1 - .../test_custom_response/test_tutorial010.py | 50 ++++++++++++ 10 files changed, 196 insertions(+), 74 deletions(-) create mode 100644 tests/test_dump_json_fast_path.py create mode 100644 tests/test_tutorial/test_custom_response/test_tutorial010.py diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index 8b4b3da339..e88e958657 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -1,6 +1,6 @@ # Custom Response - HTML, Stream, File, others { #custom-response-html-stream-file-others } -By default, **FastAPI** will return the responses using `JSONResponse`. +By default, **FastAPI** will return JSON responses. You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}. @@ -10,43 +10,27 @@ But you can also declare the `Response` that you want to be used (e.g. any `Resp The contents that you return from your *path operation function* will be put inside of that `Response`. -And if that `Response` has a JSON media type (`application/json`), like is the case with the `JSONResponse` and `UJSONResponse`, the data you return will be automatically converted (and filtered) with any Pydantic `response_model` that you declared in the *path operation decorator*. - /// note If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs. /// -## Use `ORJSONResponse` { #use-orjsonresponse } - -For example, if you are squeezing performance, you can install and use `orjson` and set the response to be `ORJSONResponse`. - -Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*. +## JSON Responses { #json-responses } -For large responses, returning a `Response` directly is much faster than returning a dictionary. +By default FastAPI returns JSON responses. -This is because by default, FastAPI will inspect every item inside and make sure it is serializable as JSON, using the same [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} explained in the tutorial. This is what allows you to return **arbitrary objects**, for example database models. +If you declare a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} FastAPI will use it to serialize the data to JSON, using Pydantic. -But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class. - -{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} - -/// info - -The parameter `response_class` will also be used to define the "media type" of the response. - -In this case, the HTTP header `Content-Type` will be set to `application/json`. - -And it will be documented as such in OpenAPI. +If you don't declare a response model, FastAPI will use the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} and put it in a `JSONResponse`. -/// +If you declare a `response_class` with a JSON media type (`application/json`), like is the case with the `JSONResponse`, the data you return will be automatically converted (and filtered) with any Pydantic `response_model` that you declared in the *path operation decorator*. But the data won't be serialized to JSON bytes with Pydantic, instead it will be converted with the `jsonable_encoder` and then passed to the `JSONResponse` class, which will serialize it to bytes using the standard JSON library in Python. -/// tip +### JSON Performance { #json-performance } -The `ORJSONResponse` is only available in FastAPI, not in Starlette. +In short, if you want the maximum performance, use a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} and don't declare a `response_class` in the *path operation decorator*. -/// +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} ## HTML Response { #html-response } @@ -154,40 +138,6 @@ Takes some data and returns an `application/json` encoded response. This is the default response used in **FastAPI**, as you read above. -### `ORJSONResponse` { #orjsonresponse } - -A fast alternative JSON response using `orjson`, as you read above. - -/// info - -This requires installing `orjson` for example with `pip install orjson`. - -/// - -### `UJSONResponse` { #ujsonresponse } - -An alternative JSON response using `ujson`. - -/// info - -This requires installing `ujson` for example with `pip install ujson`. - -/// - -/// warning - -`ujson` is less careful than Python's built-in implementation in how it handles some edge-cases. - -/// - -{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} - -/// tip - -It's possible that `ORJSONResponse` might be a faster alternative. - -/// - ### `RedirectResponse` { #redirectresponse } Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default. @@ -268,7 +218,7 @@ In this case, you can return the file path directly from your *path operation* f You can create your own custom response class, inheriting from `Response` and using it. -For example, let's say that you want to use `orjson`, but with some custom settings not used in the included `ORJSONResponse` class. +For example, let's say that you want to use `orjson` with some settings. Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`. @@ -292,13 +242,21 @@ Now instead of returning: Of course, you will probably find much better ways to take advantage of this than formatting JSON. ๐Ÿ˜‰ +### `orjson` or Response Model { #orjson-or-response-model } + +If what you are looking for is performance, you are probably better off using a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} than an `orjson` response. + +With a response model, FastAPI will use Pydantic to serialize the data to JSON, without using intermediate steps, like converting it with `jsonable_encoder`, which would happen in any other case. + +And under the hood, Pydantic uses the same underlying Rust mechanisms as `orjson` to serialize to JSON, so you will already get the best performance with a response model. + ## Default response class { #default-response-class } When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default. The parameter that defines this is `default_response_class`. -In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`. +In the example below, **FastAPI** will use `HTMLResponse` by default, in all *path operations*, instead of JSON. {* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index 76cc50d03c..9d58490eb1 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -2,19 +2,23 @@ When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc. -By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. +If you declare a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} FastAPI will use it to serialize the data to JSON, using Pydantic. -Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a `JSONResponse` that would be used to send the response to the client. +If you don't declare a response model, FastAPI will use the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} and put it in a `JSONResponse`. -But you can return a `JSONResponse` directly from your *path operations*. +You could also create a `JSONResponse` directly and return it. -It might be useful, for example, to return custom headers or cookies. +/// tip + +You will normally have much better performance using a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} than returning a `JSONResponse` directly, as that way it serializes the data using Pydantic, in Rust. + +/// ## Return a `Response` { #return-a-response } -In fact, you can return any `Response` or any sub-class of it. +You can return any `Response` or any sub-class of it. -/// tip +/// info `JSONResponse` itself is a sub-class of `Response`. @@ -56,6 +60,18 @@ You could put your XML content in a string, put that in a `Response`, and return {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} +## How a Response Model Works { #how-a-response-model-works } + +When you declare a [Response Model](../tutorial/response-model.md){.internal-link target=_blank} in a path operation, **FastAPI** will use it to serialize the data to JSON, using Pydantic. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +As that will happen on the Rust side, the performance will be much better than if it was done with regular Python and the `JSONResponse` class. + +When using a response model FastAPI won't use the `jsonable_encoder` to convert the data (which would be slower) nor the `JSONResponse` class. + +Instead it takes the JSON bytes generated with Pydantic using the response model and returns a `Response` with the right media type for JSON directly (`application/json`). + ## Notes { #notes } When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically. diff --git a/docs/en/docs/how-to/general.md b/docs/en/docs/how-to/general.md index 9347192607..4f611dab05 100644 --- a/docs/en/docs/how-to/general.md +++ b/docs/en/docs/how-to/general.md @@ -6,6 +6,10 @@ Here are several pointers to other places in the docs, for general or frequent q To ensure that you don't return more data than you should, read the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank}. +## Optimize Response Performance - Response Model - Return Type { #optimize-response-performance-response-model-return-type } + +To optimize performance when returning JSON data, use a return type or response model, that way Pydantic will handle the serialization to JSON on the Rust side, without going through Python. Read more in the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank}. + ## Documentation Tags - OpenAPI { #documentation-tags-openapi } To add tags to your *path operations*, and group them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md index 51492722ae..c8312d92c6 100644 --- a/docs/en/docs/tutorial/response-model.md +++ b/docs/en/docs/tutorial/response-model.md @@ -13,6 +13,7 @@ FastAPI will use this return type to: * Add a **JSON Schema** for the response, in the OpenAPI *path operation*. * This will be used by the **automatic docs**. * It will also be used by automatic client code generation tools. +* **Serialize** the returned data to JSON using Pydantic, which is written in **Rust**, so it will be **much faster**. But most importantly: diff --git a/docs_src/custom_response/tutorial010_py310.py b/docs_src/custom_response/tutorial010_py310.py index 57cb062604..d5bc783aa0 100644 --- a/docs_src/custom_response/tutorial010_py310.py +++ b/docs_src/custom_response/tutorial010_py310.py @@ -1,9 +1,9 @@ from fastapi import FastAPI -from fastapi.responses import ORJSONResponse +from fastapi.responses import HTMLResponse -app = FastAPI(default_response_class=ORJSONResponse) +app = FastAPI(default_response_class=HTMLResponse) @app.get("/items/") async def read_items(): - return [{"item_id": "Foo"}] + return "

Items

This is a list of items.

" diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 0535c806f2..79fba93188 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -199,6 +199,32 @@ class ModelField: exclude_none=exclude_none, ) + def serialize_json( + self, + value: Any, + *, + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> bytes: + # What calls this code passes a value that already called + # self._type_adapter.validate_python(value) + # This uses Pydantic's dump_json() which serializes directly to JSON + # bytes in one pass (via Rust), avoiding the intermediate Python dict + # step of dump_python(mode="json") + json.dumps(). + return self._type_adapter.dump_json( + value, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + def __hash__(self) -> int: # Each ModelField is unique for our purposes, to allow making a dict from # ModelField to its JSON Schema. diff --git a/fastapi/routing.py b/fastapi/routing.py index ea82ab14a3..528c962965 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -271,6 +271,7 @@ async def serialize_response( exclude_none: bool = False, is_coroutine: bool = True, endpoint_ctx: EndpointContext | None = None, + dump_json: bool = False, ) -> Any: if field: if is_coroutine: @@ -286,8 +287,8 @@ async def serialize_response( body=response_content, endpoint_ctx=ctx, ) - - return field.serialize( + serializer = field.serialize_json if dump_json else field.serialize + return serializer( value, include=include, exclude=exclude, @@ -443,6 +444,14 @@ def get_request_handler( response_args["status_code"] = current_status_code if solved_result.response.status_code: response_args["status_code"] = solved_result.response.status_code + # Use the fast path (dump_json) when no custom response + # class was set and a response field with a TypeAdapter + # exists. Serializes directly to JSON bytes via Pydantic's + # Rust core, skipping the intermediate Python dict + + # json.dumps() step. + use_dump_json = response_field is not None and isinstance( + response_class, DefaultPlaceholder + ) content = await serialize_response( field=response_field, response_content=raw_response, @@ -454,8 +463,16 @@ def get_request_handler( exclude_none=response_model_exclude_none, is_coroutine=is_coroutine, endpoint_ctx=endpoint_ctx, + dump_json=use_dump_json, ) - response = actual_response_class(content, **response_args) + if use_dump_json: + response = Response( + content=content, + media_type="application/json", + **response_args, + ) + else: + response = actual_response_class(content, **response_args) if not is_body_allowed_for_status_code(response.status_code): response.body = b"" response.headers.raw.extend(solved_result.response.headers.raw) diff --git a/tests/test_dump_json_fast_path.py b/tests/test_dump_json_fast_path.py new file mode 100644 index 0000000000..d41d5aa66f --- /dev/null +++ b/tests/test_dump_json_fast_path.py @@ -0,0 +1,51 @@ +from unittest.mock import patch + +from fastapi import FastAPI +from fastapi.responses import JSONResponse +from fastapi.testclient import TestClient +from pydantic import BaseModel + + +class Item(BaseModel): + name: str + price: float + + +app = FastAPI() + + +@app.get("/default") +def get_default() -> Item: + return Item(name="widget", price=9.99) + + +@app.get("/explicit", response_class=JSONResponse) +def get_explicit() -> Item: + return Item(name="widget", price=9.99) + + +client = TestClient(app) + + +def test_default_response_class_skips_json_dumps(): + """When no response_class is set, the fast path serializes directly to + JSON bytes via Pydantic's dump_json and never calls json.dumps.""" + with patch( + "starlette.responses.json.dumps", wraps=__import__("json").dumps + ) as mock_dumps: + response = client.get("/default") + assert response.status_code == 200 + assert response.json() == {"name": "widget", "price": 9.99} + mock_dumps.assert_not_called() + + +def test_explicit_response_class_uses_json_dumps(): + """When response_class is explicitly set to JSONResponse, the normal path + is used and json.dumps is called via JSONResponse.render().""" + with patch( + "starlette.responses.json.dumps", wraps=__import__("json").dumps + ) as mock_dumps: + response = client.get("/explicit") + assert response.status_code == 200 + assert response.json() == {"name": "widget", "price": 9.99} + mock_dumps.assert_called_once() diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index a5fe4c8f4c..cec5ebe6cb 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -9,7 +9,6 @@ from inline_snapshot import snapshot name="client", params=[ pytest.param("tutorial001_py310"), - pytest.param("tutorial010_py310"), ], ) def get_client(request: pytest.FixtureRequest): diff --git a/tests/test_tutorial/test_custom_response/test_tutorial010.py b/tests/test_tutorial/test_custom_response/test_tutorial010.py new file mode 100644 index 0000000000..ffb005cb67 --- /dev/null +++ b/tests/test_tutorial/test_custom_response/test_tutorial010.py @@ -0,0 +1,50 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + + +@pytest.fixture( + name="client", + params=[ + pytest.param("tutorial010_py310"), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.custom_response.{request.param}") + client = TestClient(mod.app) + return client + + +def test_get_custom_response(client: TestClient): + response = client.get("/items/") + assert response.status_code == 200, response.text + assert response.text == snapshot("

Items

This is a list of items.

") + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/html": {"schema": {"type": "string"}} + }, + } + }, + "summary": "Read Items", + "operationId": "read_items_items__get", + } + } + }, + } + ) From bc06e4296d588f39f38c7ac2fc96d3913c565962 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 16:07:56 +0000 Subject: [PATCH 269/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index edcb3db8d6..ba5ba420bd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* โœจ Serialize JSON response with Pydantic (in Rust), when there's a Pydantic return type or response model. PR [#14962](https://github.com/fastapi/fastapi/pull/14962) by [@tiangolo](https://github.com/tiangolo). + ## 0.129.2 ### Internal From eb544e704c02fd9bad34d23127cbb45255c00706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 17:14:53 +0100 Subject: [PATCH 270/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ba5ba420bd..a5c5241e1b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.130.0 + ### Features * โœจ Serialize JSON response with Pydantic (in Rust), when there's a Pydantic return type or response model. PR [#14962](https://github.com/fastapi/fastapi/pull/14962) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index e6798ddc6d..ffa56faaf1 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.129.2" +__version__ = "0.130.0" from starlette import status as status From 2e62fb151338c39c1f122d13fe6ad255b8ce1ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 17:18:26 +0100 Subject: [PATCH 271/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a5c5241e1b..4b7fba3368 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -12,6 +12,8 @@ hide: ### Features * โœจ Serialize JSON response with Pydantic (in Rust), when there's a Pydantic return type or response model. PR [#14962](https://github.com/fastapi/fastapi/pull/14962) by [@tiangolo](https://github.com/tiangolo). + * This results in 2x (or more) performance increase for JSON responses. + * New docs: [Custom Response - JSON Performance](https://fastapi.tiangolo.com/advanced/custom-response/#json-performance). ## 0.129.2 From 48e983573232eea970fb4e0261818d4ab9a481b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 08:34:59 -0800 Subject: [PATCH 272/367] =?UTF-8?q?=F0=9F=97=91=EF=B8=8F=20Deprecate=20`OR?= =?UTF-8?q?JSONResponse`=20and=20`UJSONResponse`=20(#14964)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/reference/responses.md | 8 +- fastapi/responses.py | 52 +++++++++++-- pyproject.toml | 8 +- tests/test_deprecated_responses.py | 73 +++++++++++++++++++ tests/test_orjson_response_class.py | 13 +++- .../test_custom_response/test_tutorial001.py | 2 + .../test_custom_response/test_tutorial001b.py | 10 ++- uv.lock | 20 ++++- 8 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 tests/test_deprecated_responses.py diff --git a/docs/en/docs/reference/responses.md b/docs/en/docs/reference/responses.md index bd57861294..2df53e9701 100644 --- a/docs/en/docs/reference/responses.md +++ b/docs/en/docs/reference/responses.md @@ -22,7 +22,13 @@ from fastapi.responses import ( ## FastAPI Responses -There are a couple of custom FastAPI response classes, you can use them to optimize JSON performance. +There were a couple of custom FastAPI response classes that were intended to optimize JSON performance. + +However, they are now deprecated as you will now get better performance by using a [Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/). + +That way, Pydantic will serialize the data into JSON bytes on the Rust side, which will achieve better performance than these custom JSON responses. + +Read more about it in [Custom Response - HTML, Stream, File, others - `orjson` or Response Model](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model). ::: fastapi.responses.UJSONResponse options: diff --git a/fastapi/responses.py b/fastapi/responses.py index 6c8db6f335..5b1154c046 100644 --- a/fastapi/responses.py +++ b/fastapi/responses.py @@ -1,5 +1,6 @@ from typing import Any +from fastapi.exceptions import FastAPIDeprecationWarning from starlette.responses import FileResponse as FileResponse # noqa from starlette.responses import HTMLResponse as HTMLResponse # noqa from starlette.responses import JSONResponse as JSONResponse # noqa @@ -7,6 +8,7 @@ from starlette.responses import PlainTextResponse as PlainTextResponse # noqa from starlette.responses import RedirectResponse as RedirectResponse # noqa from starlette.responses import Response as Response # noqa from starlette.responses import StreamingResponse as StreamingResponse # noqa +from typing_extensions import deprecated try: import ujson @@ -20,12 +22,29 @@ except ImportError: # pragma: nocover orjson = None # type: ignore +@deprecated( + "UJSONResponse is deprecated, FastAPI now serializes data directly to JSON " + "bytes via Pydantic when a return type or response model is set, which is " + "faster and doesn't need a custom response class. Read more in the FastAPI " + "docs: https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model " + "and https://fastapi.tiangolo.com/tutorial/response-model/", + category=FastAPIDeprecationWarning, + stacklevel=2, +) class UJSONResponse(JSONResponse): - """ - JSON response using the high-performance ujson library to serialize data to JSON. + """JSON response using the ujson library to serialize data to JSON. + + **Deprecated**: `UJSONResponse` is deprecated. FastAPI now serializes data + directly to JSON bytes via Pydantic when a return type or response model is + set, which is faster and doesn't need a custom response class. + + Read more in the + [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model) + and the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/). + **Note**: `ujson` is not included with FastAPI and must be installed + separately, e.g. `pip install ujson`. """ def render(self, content: Any) -> bytes: @@ -33,12 +52,29 @@ class UJSONResponse(JSONResponse): return ujson.dumps(content, ensure_ascii=False).encode("utf-8") +@deprecated( + "ORJSONResponse is deprecated, FastAPI now serializes data directly to JSON " + "bytes via Pydantic when a return type or response model is set, which is " + "faster and doesn't need a custom response class. Read more in the FastAPI " + "docs: https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model " + "and https://fastapi.tiangolo.com/tutorial/response-model/", + category=FastAPIDeprecationWarning, + stacklevel=2, +) class ORJSONResponse(JSONResponse): - """ - JSON response using the high-performance orjson library to serialize data to JSON. + """JSON response using the orjson library to serialize data to JSON. + + **Deprecated**: `ORJSONResponse` is deprecated. FastAPI now serializes data + directly to JSON bytes via Pydantic when a return type or response model is + set, which is faster and doesn't need a custom response class. + + Read more in the + [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model) + and the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/). + **Note**: `orjson` is not included with FastAPI and must be installed + separately, e.g. `pip install orjson`. """ def render(self, content: Any) -> bytes: diff --git a/pyproject.toml b/pyproject.toml index c51eb8ce9b..79dfc1fd35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,10 +105,6 @@ all = [ "itsdangerous >=1.1.0", # For Starlette's schema generation, would not be used with FastAPI "pyyaml >=5.3.1", - # For UJSONResponse - "ujson >=5.8.0", - # For ORJSONResponse - "orjson >=3.9.3", # To validate email fields "email-validator >=2.0.0", # Uvicorn with uvloop @@ -151,6 +147,10 @@ docs = [ docs-tests = [ "httpx >=0.23.0,<1.0.0", "ruff >=0.14.14", + # For UJSONResponse + "ujson >=5.8.0", + # For ORJSONResponse + "orjson >=3.9.3", ] github-actions = [ "httpx >=0.27.0,<1.0.0", diff --git a/tests/test_deprecated_responses.py b/tests/test_deprecated_responses.py new file mode 100644 index 0000000000..eff5792717 --- /dev/null +++ b/tests/test_deprecated_responses.py @@ -0,0 +1,73 @@ +import warnings + +import pytest +from fastapi import FastAPI +from fastapi.exceptions import FastAPIDeprecationWarning +from fastapi.responses import ORJSONResponse, UJSONResponse +from fastapi.testclient import TestClient +from pydantic import BaseModel + + +class Item(BaseModel): + name: str + price: float + + +# ORJSON + + +def _make_orjson_app() -> FastAPI: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + app = FastAPI(default_response_class=ORJSONResponse) + + @app.get("/items") + def get_items() -> Item: + return Item(name="widget", price=9.99) + + return app + + +def test_orjson_response_returns_correct_data(): + app = _make_orjson_app() + client = TestClient(app) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + response = client.get("/items") + assert response.status_code == 200 + assert response.json() == {"name": "widget", "price": 9.99} + + +def test_orjson_response_emits_deprecation_warning(): + with pytest.warns(FastAPIDeprecationWarning, match="ORJSONResponse is deprecated"): + ORJSONResponse(content={"hello": "world"}) + + +# UJSON + + +def _make_ujson_app() -> FastAPI: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + app = FastAPI(default_response_class=UJSONResponse) + + @app.get("/items") + def get_items() -> Item: + return Item(name="widget", price=9.99) + + return app + + +def test_ujson_response_returns_correct_data(): + app = _make_ujson_app() + client = TestClient(app) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + response = client.get("/items") + assert response.status_code == 200 + assert response.json() == {"name": "widget", "price": 9.99} + + +def test_ujson_response_emits_deprecation_warning(): + with pytest.warns(FastAPIDeprecationWarning, match="UJSONResponse is deprecated"): + UJSONResponse(content={"hello": "world"}) diff --git a/tests/test_orjson_response_class.py b/tests/test_orjson_response_class.py index 6fe62daf97..63ea054d1f 100644 --- a/tests/test_orjson_response_class.py +++ b/tests/test_orjson_response_class.py @@ -1,9 +1,14 @@ +import warnings + from fastapi import FastAPI +from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.responses import ORJSONResponse from fastapi.testclient import TestClient from sqlalchemy.sql.elements import quoted_name -app = FastAPI(default_response_class=ORJSONResponse) +with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + app = FastAPI(default_response_class=ORJSONResponse) @app.get("/orjson_non_str_keys") @@ -16,6 +21,8 @@ client = TestClient(app) def test_orjson_non_str_keys(): - with client: - response = client.get("/orjson_non_str_keys") + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + with client: + response = client.get("/orjson_non_str_keys") assert response.json() == {"msg": "Hello World", "1": 1} diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index cec5ebe6cb..a691dd3a84 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -17,12 +17,14 @@ def get_client(request: pytest.FixtureRequest): return client +@pytest.mark.filterwarnings("ignore::fastapi.exceptions.FastAPIDeprecationWarning") def test_get_custom_response(client: TestClient): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] +@pytest.mark.filterwarnings("ignore::fastapi.exceptions.FastAPIDeprecationWarning") def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index 32437db86b..11ce813b76 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -1,17 +1,25 @@ +import warnings + +import pytest +from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.testclient import TestClient from inline_snapshot import snapshot -from docs_src.custom_response.tutorial001b_py310 import app +with warnings.catch_warnings(): + warnings.simplefilter("ignore", FastAPIDeprecationWarning) + from docs_src.custom_response.tutorial001b_py310 import app client = TestClient(app) +@pytest.mark.filterwarnings("ignore::fastapi.exceptions.FastAPIDeprecationWarning") def test_get_custom_response(): response = client.get("/items/") assert response.status_code == 200, response.text assert response.json() == [{"item_id": "Foo"}] +@pytest.mark.filterwarnings("ignore::fastapi.exceptions.FastAPIDeprecationWarning") def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200, response.text diff --git a/uv.lock b/uv.lock index 15ca8714f6..0d16c930b1 100644 --- a/uv.lock +++ b/uv.lock @@ -1083,12 +1083,10 @@ all = [ { name = "httpx" }, { name = "itsdangerous" }, { name = "jinja2" }, - { name = "orjson" }, { name = "pydantic-extra-types" }, { name = "pydantic-settings" }, { name = "python-multipart" }, { name = "pyyaml" }, - { name = "ujson" }, { name = "uvicorn", extra = ["standard"] }, ] standard = [ @@ -1134,6 +1132,7 @@ dev = [ { name = "mkdocs-redirects" }, { name = "mkdocstrings", extra = ["python"] }, { name = "mypy" }, + { name = "orjson" }, { name = "pillow" }, { name = "playwright" }, { name = "prek" }, @@ -1151,6 +1150,7 @@ dev = [ { name = "typer" }, { name = "types-orjson" }, { name = "types-ujson" }, + { name = "ujson" }, ] docs = [ { name = "black" }, @@ -1165,15 +1165,19 @@ docs = [ { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, { name = "mkdocstrings", extra = ["python"] }, + { name = "orjson" }, { name = "pillow" }, { name = "python-slugify" }, { name = "pyyaml" }, { name = "ruff" }, { name = "typer" }, + { name = "ujson" }, ] docs-tests = [ { name = "httpx" }, + { name = "orjson" }, { name = "ruff" }, + { name = "ujson" }, ] github-actions = [ { name = "httpx" }, @@ -1192,6 +1196,7 @@ tests = [ { name = "httpx" }, { name = "inline-snapshot" }, { name = "mypy" }, + { name = "orjson" }, { name = "pwdlib", extra = ["argon2"] }, { name = "pyjwt" }, { name = "pytest" }, @@ -1202,6 +1207,7 @@ tests = [ { name = "strawberry-graphql" }, { name = "types-orjson" }, { name = "types-ujson" }, + { name = "ujson" }, ] translations = [ { name = "gitpython" }, @@ -1225,7 +1231,6 @@ requires-dist = [ { name = "jinja2", marker = "extra == 'all'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=3.1.5" }, - { name = "orjson", marker = "extra == 'all'", specifier = ">=3.9.3" }, { name = "pydantic", specifier = ">=2.7.0" }, { name = "pydantic-extra-types", marker = "extra == 'all'", specifier = ">=2.0.0" }, { name = "pydantic-extra-types", marker = "extra == 'standard'", specifier = ">=2.0.0" }, @@ -1240,7 +1245,6 @@ requires-dist = [ { name = "starlette", specifier = ">=0.40.0,<1.0.0" }, { name = "typing-extensions", specifier = ">=4.8.0" }, { name = "typing-inspection", specifier = ">=0.4.2" }, - { name = "ujson", marker = "extra == 'all'", specifier = ">=5.8.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.12.0" }, { name = "uvicorn", extras = ["standard"], marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=0.12.0" }, @@ -1269,6 +1273,7 @@ dev = [ { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, { name = "mypy", specifier = ">=1.14.1" }, + { name = "orjson", specifier = ">=3.9.3" }, { name = "pillow", specifier = ">=11.3.0" }, { name = "playwright", specifier = ">=1.57.0" }, { name = "prek", specifier = ">=0.2.22" }, @@ -1286,6 +1291,7 @@ dev = [ { name = "typer", specifier = ">=0.21.1" }, { name = "types-orjson", specifier = ">=3.6.2" }, { name = "types-ujson", specifier = ">=5.10.0.20240515" }, + { name = "ujson", specifier = ">=5.8.0" }, ] docs = [ { name = "black", specifier = ">=25.1.0" }, @@ -1300,15 +1306,19 @@ docs = [ { name = "mkdocs-material", specifier = ">=9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, + { name = "orjson", specifier = ">=3.9.3" }, { name = "pillow", specifier = ">=11.3.0" }, { name = "python-slugify", specifier = ">=8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = ">=0.14.14" }, { name = "typer", specifier = ">=0.21.1" }, + { name = "ujson", specifier = ">=5.8.0" }, ] docs-tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, + { name = "orjson", specifier = ">=3.9.3" }, { name = "ruff", specifier = ">=0.14.14" }, + { name = "ujson", specifier = ">=5.8.0" }, ] github-actions = [ { name = "httpx", specifier = ">=0.27.0,<1.0.0" }, @@ -1327,6 +1337,7 @@ tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, { name = "inline-snapshot", specifier = ">=0.21.1" }, { name = "mypy", specifier = ">=1.14.1" }, + { name = "orjson", specifier = ">=3.9.3" }, { name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" }, { name = "pyjwt", specifier = ">=2.9.0" }, { name = "pytest", specifier = ">=9.0.0" }, @@ -1337,6 +1348,7 @@ tests = [ { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "types-orjson", specifier = ">=3.6.2" }, { name = "types-ujson", specifier = ">=5.10.0.20240515" }, + { name = "ujson", specifier = ">=5.8.0" }, ] translations = [ { name = "gitpython", specifier = ">=3.1.46" }, From 70e8558352ef5f60dbd95c95725a427e06e86a24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 16:35:25 +0000 Subject: [PATCH 273/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4b7fba3368..b9848e4607 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Breaking Changes + +* ๐Ÿ—‘๏ธ Deprecate `ORJSONResponse` and `UJSONResponse`. PR [#14964](https://github.com/fastapi/fastapi/pull/14964) by [@tiangolo](https://github.com/tiangolo). + ## 0.130.0 ### Features From b423b73c355bc401cb49f43cb5ca14515ac088cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 17:36:21 +0100 Subject: [PATCH 274/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b9848e4607..c42133a201 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.131.0 + ### Breaking Changes * ๐Ÿ—‘๏ธ Deprecate `ORJSONResponse` and `UJSONResponse`. PR [#14964](https://github.com/fastapi/fastapi/pull/14964) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index ffa56faaf1..944fdd58f4 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.130.0" +__version__ = "0.131.0" from starlette import status as status From 1cea8f659c5ca6ffef1a62b3ac78b9d7c63c3c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 10:13:49 -0800 Subject: [PATCH 275/367] =?UTF-8?q?=F0=9F=91=B7=20Do=20not=20include=20ben?= =?UTF-8?q?chmark=20tests=20in=20coverage=20to=20speed=20up=20coverage=20p?= =?UTF-8?q?rocessing=20(#14965)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 49 ++++++++++++++++++++++++++++---------- pyproject.toml | 1 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d61b4add94..0d3515efb7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,10 +68,8 @@ jobs: python-version: "3.13" coverage: coverage uv-resolution: highest - # Ubuntu with 3.13 needs coverage for CodSpeed benchmarks - os: ubuntu-latest python-version: "3.13" - coverage: coverage uv-resolution: highest codspeed: codspeed - os: ubuntu-latest @@ -109,20 +107,10 @@ jobs: run: uv pip install "git+https://github.com/Kludex/starlette@main" - run: mkdir coverage - name: Test - if: matrix.codspeed != 'codspeed' run: uv run --no-sync bash scripts/test.sh env: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - - name: CodSpeed benchmarks - if: matrix.codspeed == 'codspeed' - uses: CodSpeedHQ/action@v4 - env: - COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} - CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - with: - mode: simulation - run: uv run --no-sync coverage run -m pytest tests/ --codspeed # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow - name: Store coverage files if: matrix.coverage == 'coverage' @@ -132,6 +120,42 @@ jobs: path: coverage include-hidden-files: true + benchmark: + needs: + - changes + if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + env: + UV_PYTHON: "3.13" + UV_RESOLUTION: highest + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + - name: Setup uv + uses: astral-sh/setup-uv@v7 + with: + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --no-dev --group tests --extra all + - name: CodSpeed benchmarks + uses: CodSpeedHQ/action@v4 + env: + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py3.13 + CONTEXT: ${{ runner.os }}-py3.13 + with: + mode: simulation + run: uv run --no-sync coverage run -m pytest tests/ --codspeed + coverage-combine: needs: - test @@ -176,6 +200,7 @@ jobs: if: always() needs: - coverage-combine + - benchmark runs-on: ubuntu-latest steps: - name: Dump GitHub context diff --git a/pyproject.toml b/pyproject.toml index 79dfc1fd35..76b53726ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -242,6 +242,7 @@ relative_files = true context = '${CONTEXT}' dynamic_context = "test_function" omit = [ + "tests/benchmarks/*", "docs_src/response_model/tutorial003_04_py39.py", "docs_src/response_model/tutorial003_04_py310.py", "docs_src/dependencies/tutorial013_an_py310.py", # temporary code example? From c5559a66dd76c229997c673dd48bbf4f46a2cf68 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 18:14:11 +0000 Subject: [PATCH 276/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c42133a201..7ac314280e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ๐Ÿ‘ท Do not include benchmark tests in coverage to speed up coverage processing. PR [#14965](https://github.com/fastapi/fastapi/pull/14965) by [@tiangolo](https://github.com/tiangolo). + ## 0.131.0 ### Breaking Changes From 4da264f0f32a1b0eb1c260997d0ab3453f4fdb98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 22 Feb 2026 10:21:38 -0800 Subject: [PATCH 277/367] =?UTF-8?q?=F0=9F=91=B7=20Do=20not=20run=20codspee?= =?UTF-8?q?d=20with=20coverage=20as=20it's=20not=20tracked=20(#14966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d3515efb7..86e6bfc148 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -149,12 +149,9 @@ jobs: run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks uses: CodSpeedHQ/action@v4 - env: - COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py3.13 - CONTEXT: ${{ runner.os }}-py3.13 with: mode: simulation - run: uv run --no-sync coverage run -m pytest tests/ --codspeed + run: uv run --no-sync pytest tests/benchmarks --codspeed coverage-combine: needs: From 282612437835fd1abbc37cf77c6f4e3bc76de557 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 18:22:03 +0000 Subject: [PATCH 278/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7ac314280e..f0fb43062b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ๐Ÿ‘ท Do not run codspeed with coverage as it's not tracked. PR [#14966](https://github.com/fastapi/fastapi/pull/14966) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Do not include benchmark tests in coverage to speed up coverage processing. PR [#14965](https://github.com/fastapi/fastapi/pull/14965) by [@tiangolo](https://github.com/tiangolo). ## 0.131.0 From a3c8c37272e456b331464b33603788ce1d244c94 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 23 Feb 2026 12:44:47 +0100 Subject: [PATCH 279/367] =?UTF-8?q?=F0=9F=94=A8=20Fix=20`FastAPI=20People`?= =?UTF-8?q?=20workflow=20(#14951)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/people.py | 83 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/scripts/people.py b/scripts/people.py index f3254ab606..2e84fcc455 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -5,6 +5,7 @@ import time from collections import Counter from collections.abc import Container from datetime import datetime, timedelta, timezone +from math import ceil from pathlib import Path from typing import Any @@ -15,12 +16,63 @@ from pydantic import BaseModel, SecretStr from pydantic_settings import BaseSettings github_graphql_url = "https://api.github.com/graphql" -questions_category_id = "MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMyMDAxNDM0" +questions_category_id = "DIC_kwDOCZduT84B6E2a" + + +POINTS_PER_MINUTE_LIMIT = 84 # 5000 points per hour + + +class RateLimiter: + def __init__(self) -> None: + self.last_query_cost: int = 1 + self.remaining_points: int = 5000 + self.reset_at: datetime = datetime.fromtimestamp(0, timezone.utc) + self.last_request_start_time: datetime = datetime.fromtimestamp(0, timezone.utc) + self.speed_multiplier: float = 1.0 + + def __enter__(self) -> "RateLimiter": + now = datetime.now(tz=timezone.utc) + + # Handle primary rate limits + primary_limit_wait_time = 0.0 + if self.remaining_points <= self.last_query_cost: + primary_limit_wait_time = (self.reset_at - now).total_seconds() + 2 + logging.warning( + f"Approaching GitHub API rate limit, remaining points: {self.remaining_points}, " + f"reset time in {primary_limit_wait_time} seconds" + ) + + # Handle secondary rate limits + secondary_limit_wait_time = 0.0 + points_per_minute = POINTS_PER_MINUTE_LIMIT * self.speed_multiplier + interval = 60 / (points_per_minute / self.last_query_cost) + time_since_last_request = (now - self.last_request_start_time).total_seconds() + if time_since_last_request < interval: + secondary_limit_wait_time = interval - time_since_last_request + + final_wait_time = ceil(max(primary_limit_wait_time, secondary_limit_wait_time)) + logging.info(f"Sleeping for {final_wait_time} seconds to respect rate limit") + time.sleep(max(final_wait_time, 1)) + + self.last_request_start_time = datetime.now(tz=timezone.utc) + return self + + def __exit__(self, exc_type, exc_val, exc_tb) -> None: + pass + + def update_request_info(self, cost: int, remaining: int, reset_at: str) -> None: + self.last_query_cost = cost + self.remaining_points = remaining + self.reset_at = datetime.fromisoformat(reset_at.replace("Z", "+00:00")) + + +rate_limiter = RateLimiter() + discussions_query = """ query Q($after: String, $category_id: ID) { repository(name: "fastapi", owner: "fastapi") { - discussions(first: 100, after: $after, categoryId: $category_id) { + discussions(first: 30, after: $after, categoryId: $category_id) { edges { cursor node { @@ -58,6 +110,11 @@ query Q($after: String, $category_id: ID) { } } } + rateLimit { + cost + remaining + resetAt + } } """ @@ -120,7 +177,7 @@ class Settings(BaseSettings): github_token: SecretStr github_repository: str httpx_timeout: int = 30 - sleep_interval: int = 5 + speed_multiplier: float = 1.0 def get_graphql_response( @@ -158,11 +215,18 @@ def get_graphql_question_discussion_edges( settings: Settings, after: str | None = None, ) -> list[DiscussionsEdge]: - data = get_graphql_response( - settings=settings, - query=discussions_query, - after=after, - category_id=questions_category_id, + with rate_limiter: + data = get_graphql_response( + settings=settings, + query=discussions_query, + after=after, + category_id=questions_category_id, + ) + + rate_limiter.update_request_info( + cost=data["data"]["rateLimit"]["cost"], + remaining=data["data"]["rateLimit"]["remaining"], + reset_at=data["data"]["rateLimit"]["resetAt"], ) graphql_response = DiscussionsResponse.model_validate(data) return graphql_response.data.repository.discussions.edges @@ -185,8 +249,6 @@ def get_discussion_nodes(settings: Settings) -> list[DiscussionsNode]: for discussion_edge in discussion_edges: discussion_nodes.append(discussion_edge.node) last_edge = discussion_edges[-1] - # Handle GitHub secondary rate limits, requests per minute - time.sleep(settings.sleep_interval) discussion_edges = get_graphql_question_discussion_edges( settings=settings, after=last_edge.cursor ) @@ -318,6 +380,7 @@ def main() -> None: logging.basicConfig(level=logging.INFO) settings = Settings() logging.info(f"Using config: {settings.model_dump_json()}") + rate_limiter.speed_multiplier = settings.speed_multiplier g = Github(settings.github_token.get_secret_value()) repo = g.get_repo(settings.github_repository) From fef2ce70d928d329af2fa14f9eefe16b716c5219 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 11:45:11 +0000 Subject: [PATCH 280/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f0fb43062b..fc3400034f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ๐Ÿ”จ Fix `FastAPI People` workflow. PR [#14951](https://github.com/fastapi/fastapi/pull/14951) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Do not run codspeed with coverage as it's not tracked. PR [#14966](https://github.com/fastapi/fastapi/pull/14966) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Do not include benchmark tests in coverage to speed up coverage processing. PR [#14965](https://github.com/fastapi/fastapi/pull/14965) by [@tiangolo](https://github.com/tiangolo). From 5161f7b42b131d945e68606cc4ffcd3b49d407a3 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Mon, 23 Feb 2026 16:04:24 +0100 Subject: [PATCH 281/367] =?UTF-8?q?=E2=AC=86=20Update=20all=20dependencies?= =?UTF-8?q?=20to=20use=20`griffelib`=20instead=20of=20`griffe`=20(#14973)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update to griffelib * also update pydantic-ai * move griffelib to get better GH diff * restore accidental edit --- uv.lock | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/uv.lock b/uv.lock index 0d16c930b1..0b14fde532 100644 --- a/uv.lock +++ b/uv.lock @@ -1923,40 +1923,36 @@ wheels = [ ] [[package]] -name = "griffe" -version = "1.15.0" +name = "griffelib" +version = "2.0.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0d/0c/3a471b6e31951dce2360477420d0a8d1e00dea6cf33b70f3e8c3ab6e28e1/griffe-1.15.0.tar.gz", hash = "sha256:7726e3afd6f298fbc3696e67958803e7ac843c1cfe59734b6251a40cdbfb5eea", size = 424112, upload-time = "2025-11-10T15:03:15.52Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/83/3b1d03d36f224edded98e9affd0467630fc09d766c0e56fb1498cbb04a9b/griffe-1.15.0-py3-none-any.whl", hash = "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", size = 150705, upload-time = "2025-11-10T15:03:13.549Z" }, + { url = "https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f", size = 142004, upload-time = "2026-02-09T19:09:40.561Z" }, ] [[package]] name = "griffe-typingdoc" -version = "0.3.0" +version = "0.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe" }, + { name = "griffelib" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/77/d5e5fa0a8391bc2890ae45255847197299739833108dd76ee3c9b2ff0bba/griffe_typingdoc-0.3.0.tar.gz", hash = "sha256:59d9ef98d02caa7aed88d8df1119c9e48c02ed049ea50ce4018ace9331d20f8b", size = 33169, upload-time = "2025-10-23T12:01:39.037Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/26/28182e0c8055842bf3da774dee1d5b789c0f236c078dcbdca1937b5214dc/griffe_typingdoc-0.3.1.tar.gz", hash = "sha256:2ff4703115cb7f8a65b9fdcdd1f3c3a15f813b6554621b52eaad094c4782ce96", size = 31218, upload-time = "2026-02-21T09:38:54.409Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/af/aa32c13f753e2625ec895b1f56eee3c9380a2088a88a2c028955e223856e/griffe_typingdoc-0.3.0-py3-none-any.whl", hash = "sha256:4f6483fff7733a679d1dce142fb029f314125f3caaf0d620eb82e7390c8564bb", size = 9923, upload-time = "2025-10-23T12:01:37.601Z" }, + { url = "https://files.pythonhosted.org/packages/b6/c4/cf543fbde49e1ae44830ef0840a4d6ee9f4e4f338138a7766d4e37cf6440/griffe_typingdoc-0.3.1-py3-none-any.whl", hash = "sha256:ecbd457ef6883126b8b6023abf12e08c58e1c152238a2f0e2afdd67a64b07021", size = 10092, upload-time = "2026-02-20T14:53:47.84Z" }, ] [[package]] name = "griffe-warnings-deprecated" -version = "1.1.0" +version = "1.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe" }, + { name = "griffelib" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7e/0e/f034e1714eb2c694d6196c75f77a02f9c69d19f9961c4804a016397bf3e5/griffe_warnings_deprecated-1.1.0.tar.gz", hash = "sha256:7bf21de327d59c66c7ce08d0166aa4292ce0577ff113de5878f428d102b6f7c5", size = 33260, upload-time = "2024-12-10T21:02:18.395Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/9e/fc86f1e9270f143a395a601de81aa42a871722c34d4b3c7763658dc2e04d/griffe_warnings_deprecated-1.1.1.tar.gz", hash = "sha256:9261369bf2acb8b5d24a0dc7895cce788208513d4349031d4ea315b979b2e99f", size = 26262, upload-time = "2026-02-21T09:38:55.858Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/4c/b7241f03ad1f22ec2eed33b0f90c4f8c949e3395c4b7488670b07225a20b/griffe_warnings_deprecated-1.1.0-py3-none-any.whl", hash = "sha256:e7b0e8bfd6e5add3945d4d9805b2a41c72409e456733965be276d55f01e8a7a2", size = 5854, upload-time = "2024-12-10T21:02:16.96Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3c/c2a9eee79bf2c8002d2fa370534bee93fdca39e8b1fc82e83d552d5d2c07/griffe_warnings_deprecated-1.1.1-py3-none-any.whl", hash = "sha256:4b7d765e82ca9139ed44ffe7bdebed0d3a46ce014ad5a35a2c22e9a16288737a", size = 6565, upload-time = "2026-02-20T15:35:23.577Z" }, ] [[package]] @@ -3003,17 +2999,17 @@ python = [ [[package]] name = "mkdocstrings-python" -version = "2.0.1" +version = "2.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "griffe" }, + { name = "griffelib" }, { name = "mkdocs-autorefs" }, { name = "mkdocstrings" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/24/75/d30af27a2906f00eb90143470272376d728521997800f5dce5b340ba35bc/mkdocstrings_python-2.0.1.tar.gz", hash = "sha256:843a562221e6a471fefdd4b45cc6c22d2607ccbad632879234fa9692e9cf7732", size = 199345, upload-time = "2025-12-03T14:26:11.755Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/33/c225eaf898634bdda489a6766fc35d1683c640bffe0e0acd10646b13536d/mkdocstrings_python-2.0.3.tar.gz", hash = "sha256:c518632751cc869439b31c9d3177678ad2bfa5c21b79b863956ad68fc92c13b8", size = 199083, upload-time = "2026-02-20T10:38:36.368Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/06/c5f8deba7d2cbdfa7967a716ae801aa9ca5f734b8f54fd473ef77a088dbe/mkdocstrings_python-2.0.1-py3-none-any.whl", hash = "sha256:66ecff45c5f8b71bf174e11d49afc845c2dfc7fc0ab17a86b6b337e0f24d8d90", size = 105055, upload-time = "2025-12-03T14:26:10.184Z" }, + { url = "https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl", hash = "sha256:0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12", size = 104779, upload-time = "2026-02-20T10:38:34.517Z" }, ] [[package]] @@ -3937,33 +3933,33 @@ email = [ [[package]] name = "pydantic-ai" -version = "1.56.0" +version = "1.62.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/1a/800a1e02b259152a49d4c11d9103784a7482c7e9b067eeea23e949d3d80f/pydantic_ai-1.56.0.tar.gz", hash = "sha256:643ff71612df52315b3b4c4b41543657f603f567223eb33245dc8098f005bdc4", size = 11795, upload-time = "2026-02-06T01:13:21.122Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/97/e3158fa976a29e9580ba1c59601590424bbb81179c359fd29de0dc23aa09/pydantic_ai-1.62.0.tar.gz", hash = "sha256:d6ae517e365ea3ea162ca8ae643f319e105b71b0b6218b83dcad1d1eb2e38c9b", size = 12130, upload-time = "2026-02-19T05:07:07.853Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/35/f4a7fd2b9962ddb9b021f76f293e74fda71da190bb74b57ed5b343c93022/pydantic_ai-1.56.0-py3-none-any.whl", hash = "sha256:b6b3ac74bdc004693834750da4420ea2cde0d3cbc3f134c0b7544f98f1c00859", size = 7222, upload-time = "2026-02-06T01:13:11.755Z" }, + { url = "https://files.pythonhosted.org/packages/bc/7a/053aebfab576603e95fcfce1139de4a87e12bd5a2ef1ba00007a931c3ff0/pydantic_ai-1.62.0-py3-none-any.whl", hash = "sha256:1eb88f745ae045e63da41ad68966e8876c964d0f023fbf5d6a3f5d243370bd04", size = 7227, upload-time = "2026-02-19T05:06:58.341Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "1.56.0" +version = "1.62.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "genai-prices" }, - { name = "griffe" }, + { name = "griffelib" }, { name = "httpx" }, { name = "opentelemetry-api" }, { name = "pydantic" }, { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/5c/3a577825b9c1da8f287be7f2ee6fe9aab48bc8a80e65c8518052c589f51c/pydantic_ai_slim-1.56.0.tar.gz", hash = "sha256:9f9f9c56b1c735837880a515ae5661b465b40207b25f3a3434178098b2137f05", size = 415265, upload-time = "2026-02-06T01:13:23.58Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8d/6350a49f2e4b636efbcfc233221420ab576e4ba4edba38254cb84ae4a1e6/pydantic_ai_slim-1.62.0.tar.gz", hash = "sha256:00d84f659107bbbd88823a3d3dbe7348385935a9870b9d7d4ba799256f6b6983", size = 422452, upload-time = "2026-02-19T05:07:10.292Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/4b/34682036528eeb9aaf093c2073540ddf399ab37b99d282a69ca41356f1aa/pydantic_ai_slim-1.56.0-py3-none-any.whl", hash = "sha256:d657e4113485020500b23b7390b0066e2a0277edc7577eaad2290735ca5dd7d5", size = 542270, upload-time = "2026-02-06T01:13:14.918Z" }, + { url = "https://files.pythonhosted.org/packages/3d/67/21e9b3b0944568662e3790c936226bd48a9f27c6b5f27b5916f5857bc4d8/pydantic_ai_slim-1.62.0-py3-none-any.whl", hash = "sha256:5210073fadd46f65859a67da67845093c487f025fa430ed027151f22ec684ab2", size = 549296, upload-time = "2026-02-19T05:07:01.624Z" }, ] [package.optional-dependencies] @@ -4181,7 +4177,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "1.56.0" +version = "1.62.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -4189,9 +4185,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ff/03/f92881cdb12d6f43e60e9bfd602e41c95408f06e2324d3729f7a194e2bcd/pydantic_graph-1.56.0.tar.gz", hash = "sha256:5e22972dbb43dbc379ab9944252ff864019abf3c7d465dcdf572fc8aec9a44a1", size = 58460, upload-time = "2026-02-06T01:13:26.708Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/b6/0b084c847ecd99624f4fbc5c8ecd3f67a2388a282a32612b2a68c3b3595f/pydantic_graph-1.62.0.tar.gz", hash = "sha256:efe56bee3a8ca35b11a3be6a5f7352419fe182ef1e1323a3267ee12dec95f3c7", size = 58529, upload-time = "2026-02-19T05:07:12.947Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/07/8c823eb4d196137c123d4d67434e185901d3cbaea3b0c2b7667da84e72c1/pydantic_graph-1.56.0-py3-none-any.whl", hash = "sha256:ec3f0a1d6fcedd4eb9c59fef45079c2ee4d4185878d70dae26440a9c974c6bb3", size = 72346, upload-time = "2026-02-06T01:13:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/f0/12/1a9cbcd59fd070ba72b0fe544caa6ca97758518643523ec2bf1162084e0d/pydantic_graph-1.62.0-py3-none-any.whl", hash = "sha256:abe0e7b356b4d3202b069ec020d8dd1f647f55e9a0e85cd272dab48250bde87d", size = 72350, upload-time = "2026-02-19T05:07:05.305Z" }, ] [[package]] From da1937443d80fa232ba3a401ddf9117e3cb43555 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 15:04:55 +0000 Subject: [PATCH 282/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fc3400034f..b423686147 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* โฌ† Update all dependencies to use `griffelib` instead of `griffe`. PR [#14973](https://github.com/fastapi/fastapi/pull/14973) by [@svlandeg](https://github.com/svlandeg). * ๐Ÿ”จ Fix `FastAPI People` workflow. PR [#14951](https://github.com/fastapi/fastapi/pull/14951) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Do not run codspeed with coverage as it's not tracked. PR [#14966](https://github.com/fastapi/fastapi/pull/14966) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Do not include benchmark tests in coverage to speed up coverage processing. PR [#14965](https://github.com/fastapi/fastapi/pull/14965) by [@tiangolo](https://github.com/tiangolo). From 248d7fb9f5d3d0ac8202f7a03546441cd0f53c1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:49:53 +0100 Subject: [PATCH 283/367] =?UTF-8?q?=E2=AC=86=20Bump=20flask=20from=203.1.2?= =?UTF-8?q?=20to=203.1.3=20(#14949)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [flask](https://github.com/pallets/flask) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/pallets/flask/releases) - [Changelog](https://github.com/pallets/flask/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/flask/compare/3.1.2...3.1.3) --- updated-dependencies: - dependency-name: flask dependency-version: 3.1.3 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 0b14fde532..6faba96621 100644 --- a/uv.lock +++ b/uv.lock @@ -1607,7 +1607,7 @@ wheels = [ [[package]] name = "flask" -version = "3.1.2" +version = "3.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blinker" }, @@ -1617,9 +1617,9 @@ dependencies = [ { name = "markupsafe" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dc/6d/cfe3c0fcc5e477df242b98bfe186a4c34357b4847e87ecaef04507332dab/flask-3.1.2.tar.gz", hash = "sha256:bf656c15c80190ed628ad08cdfd3aaa35beb087855e2f494910aa3774cc4fd87", size = 720160, upload-time = "2025-08-19T21:03:21.205Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/00/35d85dcce6c57fdc871f3867d465d780f302a175ea360f62533f12b27e2b/flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", size = 759004, upload-time = "2026-02-19T05:00:57.678Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" }, + { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, ] [[package]] From 94a1ee749e63591e6e275b726a66e07a25f6c407 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:50:41 +0000 Subject: [PATCH 284/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b423686147..51d82313fd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* โฌ† Bump flask from 3.1.2 to 3.1.3. PR [#14949](https://github.com/fastapi/fastapi/pull/14949) by [@dependabot[bot]](https://github.com/apps/dependabot). * โฌ† Update all dependencies to use `griffelib` instead of `griffe`. PR [#14973](https://github.com/fastapi/fastapi/pull/14973) by [@svlandeg](https://github.com/svlandeg). * ๐Ÿ”จ Fix `FastAPI People` workflow. PR [#14951](https://github.com/fastapi/fastapi/pull/14951) by [@YuriiMotov](https://github.com/YuriiMotov). * ๐Ÿ‘ท Do not run codspeed with coverage as it's not tracked. PR [#14966](https://github.com/fastapi/fastapi/pull/14966) by [@tiangolo](https://github.com/tiangolo). From 22354a253037e0fb23e55dabcb8767943e371702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Feb 2026 09:45:20 -0800 Subject: [PATCH 285/367] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Add=20`strict?= =?UTF-8?q?=5Fcontent=5Ftype`=20checking=20for=20JSON=20requests=20(#14978?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/strict-content-type.md | 88 ++++++++++++++++++ docs/en/mkdocs.yml | 1 + docs_src/strict_content_type/__init__.py | 0 .../strict_content_type/tutorial001_py310.py | 14 +++ fastapi/applications.py | 24 +++++ fastapi/routing.py | 44 ++++++++- tests/test_strict_content_type_app_level.py | 44 +++++++++ tests/test_strict_content_type_nested.py | 91 +++++++++++++++++++ .../test_strict_content_type_router_level.py | 61 +++++++++++++ .../test_body/test_tutorial001.py | 10 +- .../test_strict_content_type/__init__.py | 0 .../test_tutorial001.py | 43 +++++++++ 12 files changed, 411 insertions(+), 9 deletions(-) create mode 100644 docs/en/docs/advanced/strict-content-type.md create mode 100644 docs_src/strict_content_type/__init__.py create mode 100644 docs_src/strict_content_type/tutorial001_py310.py create mode 100644 tests/test_strict_content_type_app_level.py create mode 100644 tests/test_strict_content_type_nested.py create mode 100644 tests/test_strict_content_type_router_level.py create mode 100644 tests/test_tutorial/test_strict_content_type/__init__.py create mode 100644 tests/test_tutorial/test_strict_content_type/test_tutorial001.py diff --git a/docs/en/docs/advanced/strict-content-type.md b/docs/en/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000..54c099410c --- /dev/null +++ b/docs/en/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# Strict Content-Type Checking { #strict-content-type-checking } + +By default, **FastAPI** uses strict `Content-Type` header checking for JSON request bodies, this means that JSON requests **must** include a valid `Content-Type` header (e.g. `application/json`) in order for the body to be parsed as JSON. + +## CSRF Risk { #csrf-risk } + +This default behavior provides protection against a class of **Cross-Site Request Forgery (CSRF)** attacks in a very specific scenario. + +These attacks exploit the fact that browsers allow scripts to send requests without doing any CORS preflight check when they: + +* don't have a `Content-Type` header (e.g. using `fetch()` with a `Blob` body) +* and don't send any authentication credentials. + +This type of attack is mainly relevant when: + +* the application is running locally (e.g. on `localhost`) or in an internal network +* and the application doesn't have any authentication, it expects that any request from the same network can be trusted. + +## Example Attack { #example-attack } + +Imagine you build a way to run a local AI agent. + +It provides an API at + +``` +http://localhost:8000/v1/agents/multivac +``` + +There's also a frontend at + +``` +http://localhost:8000 +``` + +/// tip + +Note that both have the same host. + +/// + +Then using the frontend you can make the AI agent do things on your behalf. + +As it's running **locally**, and not in the open internet, you decide to **not have any authentication** set up, just trusting the access to the local network. + +Then one of your users could install it and run it locally. + +Then they could open a malicious website, e.g. something like + +``` +https://evilhackers.example.com +``` + +And that malicious website sends requests using `fetch()` with a `Blob` body to the local API at + +``` +http://localhost:8000/v1/agents/multivac +``` + +Even though the host of the malicious website and the local app is different, the browser won't trigger a CORS preflight request because: + +* It's running without any authentication, it doesn't have to send any credentials. +* The browser thinks it's not sending JSON (because of the missing `Content-Type` header). + +Then the malicious website could make the local AI agent send angry messages to the user's ex-boss... or worse. ๐Ÿ˜… + +## Open Internet { #open-internet } + +If your app is in the open internet, you wouldn't "trust the network" and let anyone send privileged requests without authentication. + +Attackers could simply run a script to send requests to your API, no need for browser interaction, so you are probably already securing any privileged endpoints. + +In that case **this attack / risk doesn't apply to you**. + +This risk and attack is mainly relevant when the app runs on the **local network** and that is the **only assumed protection**. + +## Allowing Requests Without Content-Type { #allowing-requests-without-content-type } + +If you need to support clients that don't send a `Content-Type` header, you can disable strict checking by setting `strict_content_type=False`: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +With this setting, requests without a `Content-Type` header will have their body parsed as JSON, which is the same behavior as older versions of FastAPI. + +/// info + +This behavior and configuration was added in FastAPI 0.132.0. + +/// diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index b276e55d95..e86e7b9c41 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -193,6 +193,7 @@ nav: - advanced/generate-clients.md - advanced/advanced-python-types.md - advanced/json-base64-bytes.md + - advanced/strict-content-type.md - fastapi-cli.md - Deployment: - deployment/index.md diff --git a/docs_src/strict_content_type/__init__.py b/docs_src/strict_content_type/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs_src/strict_content_type/tutorial001_py310.py b/docs_src/strict_content_type/tutorial001_py310.py new file mode 100644 index 0000000000..a44f4b1386 --- /dev/null +++ b/docs_src/strict_content_type/tutorial001_py310.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI(strict_content_type=False) + + +class Item(BaseModel): + name: str + price: float + + +@app.post("/items/") +async def create_item(item: Item): + return item diff --git a/fastapi/applications.py b/fastapi/applications.py index 41d86143ec..ed05a1ff9e 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -840,6 +840,29 @@ class FastAPI(Starlette): """ ), ] = None, + strict_content_type: Annotated[ + bool, + Doc( + """ + Enable strict checking for request Content-Type headers. + + When `True` (the default), requests with a body that do not include + a `Content-Type` header will **not** be parsed as JSON. + + This prevents potential cross-site request forgery (CSRF) attacks + that exploit the browser's ability to send requests without a + Content-Type header, bypassing CORS preflight checks. In particular + applicable for apps that need to be run locally (in localhost). + + When `False`, requests without a `Content-Type` header will have + their body parsed as JSON, which maintains compatibility with + certain clients that don't send `Content-Type` headers. + + Read more about it in the + [FastAPI docs for Strict Content-Type](https://fastapi.tiangolo.com/advanced/strict-content-type/). + """ + ), + ] = True, **extra: Annotated[ Any, Doc( @@ -974,6 +997,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, responses=responses, generate_unique_id_function=generate_unique_id_function, + strict_content_type=strict_content_type, ) self.exception_handlers: dict[ Any, Callable[[Request, Any], Response | Awaitable[Response]] diff --git a/fastapi/routing.py b/fastapi/routing.py index 528c962965..d17650a627 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -329,6 +329,7 @@ def get_request_handler( response_model_exclude_none: bool = False, dependency_overrides_provider: Any | None = None, embed_body_fields: bool = False, + strict_content_type: bool | DefaultPlaceholder = Default(True), ) -> Callable[[Request], Coroutine[Any, Any, Response]]: assert dependant.call is not None, "dependant.call must be a function" is_coroutine = dependant.is_coroutine_callable @@ -337,6 +338,10 @@ def get_request_handler( actual_response_class: type[Response] = response_class.value else: actual_response_class = response_class + if isinstance(strict_content_type, DefaultPlaceholder): + actual_strict_content_type: bool = strict_content_type.value + else: + actual_strict_content_type = strict_content_type async def app(request: Request) -> Response: response: Response | None = None @@ -370,7 +375,8 @@ def get_request_handler( json_body: Any = Undefined content_type_value = request.headers.get("content-type") if not content_type_value: - json_body = await request.json() + if not actual_strict_content_type: + json_body = await request.json() else: message = email.message.Message() message["content-type"] = content_type_value @@ -599,6 +605,7 @@ class APIRoute(routing.Route): openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[["APIRoute"], str] | DefaultPlaceholder = Default(generate_unique_id), + strict_content_type: bool | DefaultPlaceholder = Default(True), ) -> None: self.path = path self.endpoint = endpoint @@ -625,6 +632,7 @@ class APIRoute(routing.Route): self.callbacks = callbacks self.openapi_extra = openapi_extra self.generate_unique_id_function = generate_unique_id_function + self.strict_content_type = strict_content_type self.tags = tags or [] self.responses = responses or {} self.name = get_name(endpoint) if name is None else name @@ -713,6 +721,7 @@ class APIRoute(routing.Route): response_model_exclude_none=self.response_model_exclude_none, dependency_overrides_provider=self.dependency_overrides_provider, embed_body_fields=self._embed_body_fields, + strict_content_type=self.strict_content_type, ) def matches(self, scope: Scope) -> tuple[Match, Scope]: @@ -963,6 +972,29 @@ class APIRouter(routing.Router): """ ), ] = Default(generate_unique_id), + strict_content_type: Annotated[ + bool, + Doc( + """ + Enable strict checking for request Content-Type headers. + + When `True` (the default), requests with a body that do not include + a `Content-Type` header will **not** be parsed as JSON. + + This prevents potential cross-site request forgery (CSRF) attacks + that exploit the browser's ability to send requests without a + Content-Type header, bypassing CORS preflight checks. In particular + applicable for apps that need to be run locally (in localhost). + + When `False`, requests without a `Content-Type` header will have + their body parsed as JSON, which maintains compatibility with + certain clients that don't send `Content-Type` headers. + + Read more about it in the + [FastAPI docs for Strict Content-Type](https://fastapi.tiangolo.com/advanced/strict-content-type/). + """ + ), + ] = Default(True), ) -> None: # Determine the lifespan context to use if lifespan is None: @@ -1009,6 +1041,7 @@ class APIRouter(routing.Router): self.route_class = route_class self.default_response_class = default_response_class self.generate_unique_id_function = generate_unique_id_function + self.strict_content_type = strict_content_type def route( self, @@ -1059,6 +1092,7 @@ class APIRouter(routing.Router): openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[APIRoute], str] | DefaultPlaceholder = Default(generate_unique_id), + strict_content_type: bool | DefaultPlaceholder = Default(True), ) -> None: route_class = route_class_override or self.route_class responses = responses or {} @@ -1105,6 +1139,9 @@ class APIRouter(routing.Router): callbacks=current_callbacks, openapi_extra=openapi_extra, generate_unique_id_function=current_generate_unique_id, + strict_content_type=get_value_or_default( + strict_content_type, self.strict_content_type + ), ) self.routes.append(route) @@ -1480,6 +1517,11 @@ class APIRouter(routing.Router): callbacks=current_callbacks, openapi_extra=route.openapi_extra, generate_unique_id_function=current_generate_unique_id, + strict_content_type=get_value_or_default( + route.strict_content_type, + router.strict_content_type, + self.strict_content_type, + ), ) elif isinstance(route, routing.Route): methods = list(route.methods or []) diff --git a/tests/test_strict_content_type_app_level.py b/tests/test_strict_content_type_app_level.py new file mode 100644 index 0000000000..42a0821a47 --- /dev/null +++ b/tests/test_strict_content_type_app_level.py @@ -0,0 +1,44 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +app_default = FastAPI() + + +@app_default.post("/items/") +async def app_default_post(data: dict): + return data + + +app_lax = FastAPI(strict_content_type=False) + + +@app_lax.post("/items/") +async def app_lax_post(data: dict): + return data + + +client_default = TestClient(app_default) +client_lax = TestClient(app_lax) + + +def test_default_strict_rejects_no_content_type(): + response = client_default.post("/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_strict_accepts_json_content_type(): + response = client_default.post("/items/", json={"key": "value"}) + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_lax_accepts_no_content_type(): + response = client_lax.post("/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_lax_accepts_json_content_type(): + response = client_lax.post("/items/", json={"key": "value"}) + assert response.status_code == 200 + assert response.json() == {"key": "value"} diff --git a/tests/test_strict_content_type_nested.py b/tests/test_strict_content_type_nested.py new file mode 100644 index 0000000000..922d01571a --- /dev/null +++ b/tests/test_strict_content_type_nested.py @@ -0,0 +1,91 @@ +from fastapi import APIRouter, FastAPI +from fastapi.testclient import TestClient + +# Lax app with nested routers, inner overrides to strict + +app_nested = FastAPI(strict_content_type=False) # lax app +outer_router = APIRouter(prefix="/outer") # inherits lax from app +inner_strict = APIRouter(prefix="/strict", strict_content_type=True) +inner_default = APIRouter(prefix="/default") + + +@inner_strict.post("/items/") +async def inner_strict_post(data: dict): + return data + + +@inner_default.post("/items/") +async def inner_default_post(data: dict): + return data + + +outer_router.include_router(inner_strict) +outer_router.include_router(inner_default) +app_nested.include_router(outer_router) + +client_nested = TestClient(app_nested) + + +def test_strict_inner_on_lax_app_rejects_no_content_type(): + response = client_nested.post("/outer/strict/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_inner_inherits_lax_from_app(): + response = client_nested.post("/outer/default/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_inner_accepts_json_content_type(): + response = client_nested.post("/outer/strict/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_default_inner_accepts_json_content_type(): + response = client_nested.post("/outer/default/items/", json={"key": "value"}) + assert response.status_code == 200 + + +# Strict app -> lax outer router -> strict inner router + +app_mixed = FastAPI(strict_content_type=True) +mixed_outer = APIRouter(prefix="/outer", strict_content_type=False) +mixed_inner = APIRouter(prefix="/inner", strict_content_type=True) + + +@mixed_outer.post("/items/") +async def mixed_outer_post(data: dict): + return data + + +@mixed_inner.post("/items/") +async def mixed_inner_post(data: dict): + return data + + +mixed_outer.include_router(mixed_inner) +app_mixed.include_router(mixed_outer) + +client_mixed = TestClient(app_mixed) + + +def test_lax_outer_on_strict_app_accepts_no_content_type(): + response = client_mixed.post("/outer/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_inner_on_lax_outer_rejects_no_content_type(): + response = client_mixed.post("/outer/inner/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_lax_outer_accepts_json_content_type(): + response = client_mixed.post("/outer/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_strict_inner_on_lax_outer_accepts_json_content_type(): + response = client_mixed.post("/outer/inner/items/", json={"key": "value"}) + assert response.status_code == 200 diff --git a/tests/test_strict_content_type_router_level.py b/tests/test_strict_content_type_router_level.py new file mode 100644 index 0000000000..72a02d6c91 --- /dev/null +++ b/tests/test_strict_content_type_router_level.py @@ -0,0 +1,61 @@ +from fastapi import APIRouter, FastAPI +from fastapi.testclient import TestClient + +app = FastAPI() + +router_lax = APIRouter(prefix="/lax", strict_content_type=False) +router_strict = APIRouter(prefix="/strict", strict_content_type=True) +router_default = APIRouter(prefix="/default") + + +@router_lax.post("/items/") +async def router_lax_post(data: dict): + return data + + +@router_strict.post("/items/") +async def router_strict_post(data: dict): + return data + + +@router_default.post("/items/") +async def router_default_post(data: dict): + return data + + +app.include_router(router_lax) +app.include_router(router_strict) +app.include_router(router_default) + +client = TestClient(app) + + +def test_lax_router_on_strict_app_accepts_no_content_type(): + response = client.post("/lax/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_router_on_strict_app_rejects_no_content_type(): + response = client.post("/strict/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_router_inherits_strict_from_app(): + response = client.post("/default/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_lax_router_accepts_json_content_type(): + response = client.post("/lax/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_strict_router_accepts_json_content_type(): + response = client.post("/strict/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_default_router_accepts_json_content_type(): + response = client.post("/default/items/", json={"key": "value"}) + assert response.status_code == 200 diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index bdabf8d68b..8c883708a3 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -189,18 +189,12 @@ def test_geo_json(client: TestClient): assert response.status_code == 200, response.text -def test_no_content_type_is_json(client: TestClient): +def test_no_content_type_json(client: TestClient): response = client.post( "/items/", content='{"name": "Foo", "price": 50.5}', ) - assert response.status_code == 200, response.text - assert response.json() == { - "name": "Foo", - "description": None, - "price": 50.5, - "tax": None, - } + assert response.status_code == 422, response.text def test_wrong_headers(client: TestClient): diff --git a/tests/test_tutorial/test_strict_content_type/__init__.py b/tests/test_tutorial/test_strict_content_type/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_tutorial/test_strict_content_type/test_tutorial001.py b/tests/test_tutorial/test_strict_content_type/test_tutorial001.py new file mode 100644 index 0000000000..81e2d3a0be --- /dev/null +++ b/tests/test_tutorial/test_strict_content_type/test_tutorial001.py @@ -0,0 +1,43 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient + + +@pytest.fixture( + name="client", + params=[ + "tutorial001_py310", + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.strict_content_type.{request.param}") + client = TestClient(mod.app) + return client + + +def test_lax_post_without_content_type_is_parsed_as_json(client: TestClient): + response = client.post( + "/items/", + content='{"name": "Foo", "price": 50.5}', + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "Foo", "price": 50.5} + + +def test_lax_post_with_json_content_type(client: TestClient): + response = client.post( + "/items/", + json={"name": "Foo", "price": 50.5}, + ) + assert response.status_code == 200, response.text + assert response.json() == {"name": "Foo", "price": 50.5} + + +def test_lax_post_with_text_plain_is_still_rejected(client: TestClient): + response = client.post( + "/items/", + content='{"name": "Foo", "price": 50.5}', + headers={"Content-Type": "text/plain"}, + ) + assert response.status_code == 422, response.text From ac8621a76eba48c29cead5cd0dcdd77d446d37ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 17:46:11 +0000 Subject: [PATCH 286/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 51d82313fd..0be7bbc9c0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Breaking Changes + +* ๐Ÿ”’๏ธ Add `strict_content_type` checking for JSON requests. PR [#14978](https://github.com/fastapi/fastapi/pull/14978) by [@tiangolo](https://github.com/tiangolo). + ### Internal * โฌ† Bump flask from 3.1.2 to 3.1.3. PR [#14949](https://github.com/fastapi/fastapi/pull/14949) by [@dependabot[bot]](https://github.com/apps/dependabot). From 5c863d0718cea2e0ed812fbbfdc5844a0a34b039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Feb 2026 18:46:57 +0100 Subject: [PATCH 287/367] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0be7bbc9c0..7ea70eceb9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.132.0 + ### Breaking Changes * ๐Ÿ”’๏ธ Add `strict_content_type` checking for JSON requests. PR [#14978](https://github.com/fastapi/fastapi/pull/14978) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 944fdd58f4..d936bb7df3 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.131.0" +__version__ = "0.132.0" from starlette import status as status From acdf52e0c89f81952ab17bb7b34d67deb0d533dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Feb 2026 18:54:18 +0100 Subject: [PATCH 288/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7ea70eceb9..08826adff6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -12,6 +12,9 @@ hide: ### Breaking Changes * ๐Ÿ”’๏ธ Add `strict_content_type` checking for JSON requests. PR [#14978](https://github.com/fastapi/fastapi/pull/14978) by [@tiangolo](https://github.com/tiangolo). + * Now FastAPI checks, by default, that JSON requests have a `Content-Type` header with a valid JSON value, like `application/json`, and rejects requests that don't. + * If the clients for your app don't send a valid `Content-Type` header you can disable this with `strict_content_type=False`. + * Check the new docs: [Strict Content-Type Checking](https://fastapi.tiangolo.com/advanced/strict-content-type/). ### Internal From 6af38321261afde391dd28f60ec0dab9c15f0629 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 23 Feb 2026 19:31:54 +0100 Subject: [PATCH 289/367] =?UTF-8?q?=F0=9F=91=B7=20Allow=20skipping=20`benc?= =?UTF-8?q?hmark`=20job=20in=20`test`=20workflow=20(#14974)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 86e6bfc148..6046a4560d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -208,4 +208,4 @@ jobs: uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} - allowed-skips: coverage-combine,test + allowed-skips: coverage-combine,test,benchmark From 3f30ca1a5e2ed4cca1f8102b39a40e56151a018e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 18:32:32 +0000 Subject: [PATCH 290/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 08826adff6..2b068a5727 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ๐Ÿ‘ท Allow skipping `benchmark` job in `test` workflow. PR [#14974](https://github.com/fastapi/fastapi/pull/14974) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.132.0 ### Breaking Changes From 0cf27ecf8826ab8d1c8c21a4b9883ddae480d2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Feb 2026 10:47:59 -0800 Subject: [PATCH 291/367] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#14972)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/en/data/people.yml | 754 ++++++++++++++++++++-------------------- 1 file changed, 381 insertions(+), 373 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 2fdb21a059..89269ecd69 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,23 +1,23 @@ maintainers: - login: tiangolo - answers: 1900 + answers: 1923 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1900 + count: 1923 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 971 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 1107 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: github-actions - count: 769 + count: 770 avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 654 + count: 656 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 @@ -37,7 +37,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd - login: JarroVGIT - count: 190 + count: 192 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 @@ -53,11 +53,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 94 + count: 106 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 89 + count: 104 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -81,32 +81,32 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben - login: yinziyan1206 - count: 54 + count: 55 avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 url: https://github.com/yinziyan1206 +- login: acidjunk + count: 50 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: sm-Fifteen count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen -- login: acidjunk - count: 49 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: adriangb count: 46 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 url: https://github.com/adriangb -- login: Dustyposa - count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 - url: https://github.com/Dustyposa - login: insomnes count: 45 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes +- login: Dustyposa + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 + url: https://github.com/Dustyposa - login: frankie567 count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 url: https://github.com/frankie567 - login: odiseo0 count: 43 @@ -120,14 +120,14 @@ experts: count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 url: https://github.com/includeamin -- login: STeveShary - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 - url: https://github.com/STeveShary - login: chbndrhnns count: 37 avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 url: https://github.com/chbndrhnns +- login: STeveShary + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 + url: https://github.com/STeveShary - login: krishnardt count: 35 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 @@ -136,18 +136,22 @@ experts: count: 32 avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 url: https://github.com/panla +- login: valentinDruzhinin + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: prostomarkeloff count: 28 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 url: https://github.com/prostomarkeloff -- login: hasansezertasan - count: 27 - avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 - url: https://github.com/hasansezertasan - login: alv2017 - count: 26 + count: 27 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 +- login: hasansezertasan + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=d36995e41a00590da64e6204cfd112e0484ac1ca&v=4 + url: https://github.com/hasansezertasan - login: dbanty count: 26 avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9d726785d08e50b1e1cd96505800c8ea8405bce2&v=4 @@ -156,10 +160,6 @@ experts: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes -- login: valentinDruzhinin - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin - login: SirTelemak count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 @@ -176,6 +176,10 @@ experts: count: 22 avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 url: https://github.com/chrisK824 +- login: ceb10n + count: 21 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n - login: rafsaf count: 21 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4 @@ -194,7 +198,7 @@ experts: url: https://github.com/ebottos94 - login: estebanx64 count: 19 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=1900887aeed268699e5ea6f3fb7db614f7b77cd3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=2ca073ee47a625e495a9573bd374ddcd7be5ec91&v=4 url: https://github.com/estebanx64 - login: sehraramiz count: 18 @@ -236,467 +240,471 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli -- login: ghost - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 - url: https://github.com/ghost -- login: abhint +- login: mattmess1221 count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint + avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 + url: https://github.com/mattmess1221 last_month_experts: - login: YuriiMotov - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov +- login: Toygarmetu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: JavierSanchezCastro + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro - login: valentinDruzhinin - count: 5 + count: 2 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin -- login: yinziyan1206 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 -- login: tiangolo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: luzzodev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev three_months_experts: - login: YuriiMotov - count: 397 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 77 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: valentinDruzhinin - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin -- login: luzzodev - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: raceychan - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 - url: https://github.com/raceychan -- login: yinziyan1206 - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 -- login: DoctorJohn - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 - url: https://github.com/DoctorJohn - login: tiangolo - count: 4 + count: 13 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: sachinh35 +- login: Toygarmetu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: JavierSanchezCastro + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: ceb10n + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: valentinDruzhinin count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: RichieB2B + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: sachinh35 + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 -- login: eqsdxr - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 - url: https://github.com/eqsdxr -- login: Jelle-tenB - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 - url: https://github.com/Jelle-tenB -- login: pythonweb2 +- login: EmmanuelNiyonshuti count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: WilliamDEdwards + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti +- login: luzzodev count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 - url: https://github.com/WilliamDEdwards -- login: Brikas + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: davidbrochart count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 - url: https://github.com/Brikas -- login: purepani + avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 + url: https://github.com/davidbrochart +- login: CharlieReitzel count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 - url: https://github.com/purepani -- login: JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 + url: https://github.com/CharlieReitzel +- login: dotmitsu count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: TaigoFr + avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 + url: https://github.com/dotmitsu +- login: dolfinus count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr -- login: Garrett-R + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: garg-khushi count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 - url: https://github.com/Garrett-R -- login: jymchng + avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 + url: https://github.com/garg-khushi +- login: florentx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 - url: https://github.com/jymchng -- login: davidhuser + avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 + url: https://github.com/florentx +- login: JunjieAraoXiong count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 - url: https://github.com/davidhuser + avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 + url: https://github.com/JunjieAraoXiong six_months_experts: - login: YuriiMotov - count: 763 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 150 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: luzzodev - count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: valentinDruzhinin - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin -- login: alv2017 - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: sachinh35 - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: yauhen-sobaleu - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 - url: https://github.com/yauhen-sobaleu - login: tiangolo - count: 6 + count: 24 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: luzzodev + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: engripaye + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/155247530?u=645169bc81856b7f1bd20090ecb0171a56dcbeb4&v=4 + url: https://github.com/engripaye - login: JavierSanchezCastro - count: 6 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: raceychan +- login: Toygarmetu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: valentinDruzhinin count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 - url: https://github.com/raceychan -- login: yinziyan1206 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: ceb10n count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 -- login: DoctorJohn + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: RichieB2B count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 - url: https://github.com/DoctorJohn -- login: eqsdxr + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: JunjieAraoXiong + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 + url: https://github.com/JunjieAraoXiong +- login: CodeKraken-cmd + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 + url: https://github.com/CodeKraken-cmd +- login: svlandeg + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: ArmanShirzad count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 - url: https://github.com/eqsdxr -- login: Kludex + avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 + url: https://github.com/ArmanShirzad +- login: krylosov-aa count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: Jelle-tenB + avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 + url: https://github.com/krylosov-aa +- login: sachinh35 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 - url: https://github.com/Jelle-tenB -- login: adsouza + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: simone-trubian + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/5606840?u=65703af3c605feca61ce49e4009bb4e26495b425&v=4 + url: https://github.com/simone-trubian +- login: mahimairaja + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/81288263?u=4eef6b4a36b96e84bd666fc1937aa589036ccb9a&v=4 + url: https://github.com/mahimairaja +- login: pankeshpatel + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1482917?u=666f39197a88cfa38b8bd78d39ef04d95c948b6b&v=4 + url: https://github.com/pankeshpatel +- login: huynguyengl99 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/275832?u=f90f110cfafeafed2f14339e840941c2c328c186&v=4 - url: https://github.com/adsouza -- login: pythonweb2 + avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 + url: https://github.com/huynguyengl99 +- login: EmmanuelNiyonshuti count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: WilliamDEdwards + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti +- login: davidbrochart count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 - url: https://github.com/WilliamDEdwards -- login: Brikas + avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 + url: https://github.com/davidbrochart +- login: CharlieReitzel count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 - url: https://github.com/Brikas -- login: purepani + avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 + url: https://github.com/CharlieReitzel +- login: dotmitsu count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 - url: https://github.com/purepani -- login: TaigoFr + avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 + url: https://github.com/dotmitsu +- login: dolfinus count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr -- login: Garrett-R + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: Kludex count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 - url: https://github.com/Garrett-R -- login: EverStarck + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: garg-khushi count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck -- login: henrymcl + avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 + url: https://github.com/garg-khushi +- login: skion count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 - url: https://github.com/henrymcl -- login: jymchng + avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 + url: https://github.com/skion +- login: florentx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 - url: https://github.com/jymchng -- login: davidhuser + avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 + url: https://github.com/florentx +- login: jc-louis count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 - url: https://github.com/davidhuser -- login: PidgeyBE + avatarUrl: https://avatars.githubusercontent.com/u/51329768?v=4 + url: https://github.com/jc-louis +- login: WilliamDEdwards count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 - url: https://github.com/PidgeyBE -- login: KianAnbarestani + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: bughuntr7 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: jgould22 + avatarUrl: https://avatars.githubusercontent.com/u/236391583?u=7f51ff690e3a5711f845a115903c39e21c8af938&v=4 + url: https://github.com/bughuntr7 +- login: jymchng count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: marsboy02 + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: XieJiSS + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24671280?u=7ea0d9bfe46cf762594d62fd2f3c6d3813c3584c&v=4 + url: https://github.com/XieJiSS +- login: profatsky count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=04cc319d6605f8d1ba3a0bed9f4f55a582719ae6&v=4 - url: https://github.com/marsboy02 + avatarUrl: https://avatars.githubusercontent.com/u/92920843?u=81e54bb0b613c171f7cd0ab3cbb58873782c9c9c&v=4 + url: https://github.com/profatsky one_year_experts: - login: YuriiMotov - count: 824 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + count: 906 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 89 + count: 62 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: Kludex - count: 50 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: sinisaos - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: alv2017 - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 +- login: tiangolo + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo - login: valentinDruzhinin - count: 24 + count: 30 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin +- login: alv2017 + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: JavierSanchezCastro - count: 24 + count: 18 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: jgould22 - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: tiangolo +- login: engripaye count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: Kfir-G - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=a3bf923ab27bce3d1b13779a8dd22eb7675017fd&v=4 - url: https://github.com/Kfir-G -- login: sehraramiz - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz + avatarUrl: https://avatars.githubusercontent.com/u/155247530?u=645169bc81856b7f1bd20090ecb0171a56dcbeb4&v=4 + url: https://github.com/engripaye - login: sachinh35 - count: 9 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 - login: yauhen-sobaleu count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu -- login: estebanx64 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=1900887aeed268699e5ea6f3fb7db614f7b77cd3&v=4 - url: https://github.com/estebanx64 -- login: ceb10n - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n -- login: yvallois - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois +- login: Toygarmetu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: yinziyan1206 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 +- login: Kludex + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: raceychan count: 6 avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 url: https://github.com/raceychan -- login: yinziyan1206 +- login: ceb10n count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: RichieB2B + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: JunjieAraoXiong + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 + url: https://github.com/JunjieAraoXiong +- login: CodeKraken-cmd + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 + url: https://github.com/CodeKraken-cmd +- login: svlandeg + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg - login: DoctorJohn count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 url: https://github.com/DoctorJohn -- login: n8sty - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty -- login: pythonweb2 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: eqsdxr - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 - url: https://github.com/eqsdxr -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=4ba43bd63c169b5c015137d8916752a44001445a&v=4 - url: https://github.com/yokwejuste - login: WilliamDEdwards - count: 3 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 url: https://github.com/WilliamDEdwards -- login: mattmess1221 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 - url: https://github.com/mattmess1221 -- login: Jelle-tenB +- login: ArmanShirzad + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 + url: https://github.com/ArmanShirzad +- login: krylosov-aa + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 + url: https://github.com/krylosov-aa +- login: isgin01 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 + url: https://github.com/isgin01 +- login: sinisaos count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 - url: https://github.com/Jelle-tenB -- login: viniciusCalcantara + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos +- login: dolfinus count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=80f3ec7427fa6a41d5896984d0c526432f2299fa&v=4 - url: https://github.com/viniciusCalcantara -- login: davidhuser + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: jymchng count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 - url: https://github.com/davidhuser -- login: dbfreem + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: simone-trubian count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem -- login: SobikXexe + avatarUrl: https://avatars.githubusercontent.com/u/5606840?u=65703af3c605feca61ce49e4009bb4e26495b425&v=4 + url: https://github.com/simone-trubian +- login: mahimairaja count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 - url: https://github.com/SobikXexe -- login: pawelad + avatarUrl: https://avatars.githubusercontent.com/u/81288263?u=4eef6b4a36b96e84bd666fc1937aa589036ccb9a&v=4 + url: https://github.com/mahimairaja +- login: pankeshpatel count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 - url: https://github.com/pawelad -- login: Isuxiz + avatarUrl: https://avatars.githubusercontent.com/u/1482917?u=666f39197a88cfa38b8bd78d39ef04d95c948b6b&v=4 + url: https://github.com/pankeshpatel +- login: Jelle-tenB count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 - url: https://github.com/Isuxiz -- login: Minibrams + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: jgould22 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 - url: https://github.com/Minibrams -- login: adsouza + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: stan-dot count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/275832?u=f90f110cfafeafed2f14339e840941c2c328c186&v=4 - url: https://github.com/adsouza -- login: Synrom + avatarUrl: https://avatars.githubusercontent.com/u/56644812?u=a7dd773084f1c17c5f05019cc25a984e24873691&v=4 + url: https://github.com/stan-dot +- login: Damon0603 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom -- login: gaby + avatarUrl: https://avatars.githubusercontent.com/u/110039208?u=f24bf5c30317bc4959118d1b919587c473a865b6&v=4 + url: https://github.com/Damon0603 +- login: huynguyengl99 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/835733?u=8c72dec16fa560bdc81113354f2ffd79ad062bde&v=4 - url: https://github.com/gaby + avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 + url: https://github.com/huynguyengl99 +- login: EmmanuelNiyonshuti + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti - login: Ale-Cas count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas -- login: CharlesPerrotMinotHCHB +- login: tiborrr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112571330?u=e3a666718ff5ad1d1c49d6c31358a9f80c841b30&v=4 - url: https://github.com/CharlesPerrotMinotHCHB -- login: yanggeorge + avatarUrl: https://avatars.githubusercontent.com/u/16014746?u=0ce47015e53009e90393582fe86b7b90e809bc28&v=4 + url: https://github.com/tiborrr +- login: davidbrochart count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 - url: https://github.com/yanggeorge -- login: Brikas + avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 + url: https://github.com/davidbrochart +- login: CharlieReitzel count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 - url: https://github.com/Brikas -- login: dolfinus + avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 + url: https://github.com/CharlieReitzel +- login: kiranzo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 - url: https://github.com/dolfinus -- login: slafs + avatarUrl: https://avatars.githubusercontent.com/u/1070878?u=68f78a891c9751dd87571ac712a6309090c4bc01&v=4 + url: https://github.com/kiranzo +- login: dotmitsu count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs -- login: purepani + avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 + url: https://github.com/dotmitsu +- login: Brikas count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 - url: https://github.com/purepani -- login: ddahan + avatarUrl: https://avatars.githubusercontent.com/u/80290187?u=2b72e497ca4444ecec1f9dc2d1b8d5437a27b83f&v=4 + url: https://github.com/Brikas +- login: BloodyRain2k count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 - url: https://github.com/ddahan -- login: TaigoFr + avatarUrl: https://avatars.githubusercontent.com/u/1014362?v=4 + url: https://github.com/BloodyRain2k +- login: usiqwerty count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr -- login: Garrett-R + avatarUrl: https://avatars.githubusercontent.com/u/37992525?u=0c6e91d7b3887aa558755f4225ce74a003cbe852&v=4 + url: https://github.com/usiqwerty +- login: garg-khushi count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 - url: https://github.com/Garrett-R -- login: jd-solanki + avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 + url: https://github.com/garg-khushi +- login: sk- count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 - url: https://github.com/jd-solanki -- login: EverStarck + avatarUrl: https://avatars.githubusercontent.com/u/911768?u=3bfaf87089eb03ef0fa378f316b9c783f431aa9b&v=4 + url: https://github.com/sk- +- login: skion count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck -- login: henrymcl + avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 + url: https://github.com/skion +- login: Danstiv count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 - url: https://github.com/henrymcl -- login: jymchng + avatarUrl: https://avatars.githubusercontent.com/u/50794055?v=4 + url: https://github.com/Danstiv +- login: florentx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 - url: https://github.com/jymchng -- login: christiansicari + avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 + url: https://github.com/florentx +- login: jc-louis count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/29756552?v=4 - url: https://github.com/christiansicari -- login: JacobHayes + avatarUrl: https://avatars.githubusercontent.com/u/51329768?v=4 + url: https://github.com/jc-louis +- login: bughuntr7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/236391583?u=7f51ff690e3a5711f845a115903c39e21c8af938&v=4 + url: https://github.com/bughuntr7 +- login: purepani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 - url: https://github.com/JacobHayes -- login: iloveitaly + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: asmaier count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -- login: iiotsrc + avatarUrl: https://avatars.githubusercontent.com/u/3169297?v=4 + url: https://github.com/asmaier +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 - url: https://github.com/iiotsrc -- login: PidgeyBE + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: potiuk count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 - url: https://github.com/PidgeyBE -- login: KianAnbarestani + avatarUrl: https://avatars.githubusercontent.com/u/595491?v=4 + url: https://github.com/potiuk +- login: EverStarck count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: ykaiqx + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: sanderbollen-clockworks count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/ykaiqx -- login: AliYmn + avatarUrl: https://avatars.githubusercontent.com/u/183479560?v=4 + url: https://github.com/sanderbollen-clockworks +- login: davidhuser count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=a77e2605e3ce6aaf6fef8ad4a7b0d32954fba47a&v=4 - url: https://github.com/AliYmn -- login: gelezo43 + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: XieJiSS count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 -- login: jfeaver + avatarUrl: https://avatars.githubusercontent.com/u/24671280?u=7ea0d9bfe46cf762594d62fd2f3c6d3813c3584c&v=4 + url: https://github.com/XieJiSS +- login: profatsky count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1091338?u=0bcba366447d8fadad63f6705a52d128da4c7ec2&v=4 - url: https://github.com/jfeaver + avatarUrl: https://avatars.githubusercontent.com/u/92920843?u=81e54bb0b613c171f7cd0ab3cbb58873782c9c9c&v=4 + url: https://github.com/profatsky From 2f9c914d440e99fe8b62646b51e4d24c5bcd858b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 18:48:43 +0000 Subject: [PATCH 292/367] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2b068a5727..f56d34b5e7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ๐Ÿ‘ฅ Update FastAPI People - Experts. PR [#14972](https://github.com/fastapi/fastapi/pull/14972) by [@tiangolo](https://github.com/tiangolo). * ๐Ÿ‘ท Allow skipping `benchmark` job in `test` workflow. PR [#14974](https://github.com/fastapi/fastapi/pull/14974) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.132.0 From 2686c7fbbf9abb17902a2981a9d9fca01f5117b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 24 Feb 2026 01:28:10 -0800 Subject: [PATCH 293/367] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20logic?= =?UTF-8?q?=20to=20handle=20OpenAPI=20and=20Swagger=20UI=20escaping=20data?= =?UTF-8?q?=20(#14986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/applications.py | 16 +++--- fastapi/openapi/docs.py | 18 ++++++- tests/test_openapi_cache_root_path.py | 75 +++++++++++++++++++++++++++ tests/test_swagger_ui_escape.py | 37 +++++++++++++ 4 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 tests/test_openapi_cache_root_path.py create mode 100644 tests/test_swagger_ui_escape.py diff --git a/fastapi/applications.py b/fastapi/applications.py index ed05a1ff9e..e7e816c2e9 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1101,16 +1101,18 @@ class FastAPI(Starlette): def setup(self) -> None: if self.openapi_url: - urls = (server_data.get("url") for server_data in self.servers) - server_urls = {url for url in urls if url} async def openapi(req: Request) -> JSONResponse: root_path = req.scope.get("root_path", "").rstrip("/") - if root_path not in server_urls: - if root_path and self.root_path_in_servers: - self.servers.insert(0, {"url": root_path}) - server_urls.add(root_path) - return JSONResponse(self.openapi()) + schema = self.openapi() + if root_path and self.root_path_in_servers: + server_urls = {s.get("url") for s in schema.get("servers", [])} + if root_path not in server_urls: + schema = dict(schema) + schema["servers"] = [{"url": root_path}] + schema.get( + "servers", [] + ) + return JSONResponse(schema) self.add_route(self.openapi_url, openapi, include_in_schema=False) if self.openapi_url and self.docs_url: diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index b845f87c1c..0d9242f9fa 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -5,6 +5,20 @@ from annotated_doc import Doc from fastapi.encoders import jsonable_encoder from starlette.responses import HTMLResponse + +def _html_safe_json(value: Any) -> str: + """Serialize a value to JSON with HTML special characters escaped. + + This prevents injection when the JSON is embedded inside a " + html = get_swagger_ui_html( + openapi_url="/openapi.json", + title="Test", + init_oauth={"appName": xss_payload}, + ) + body = html.body.decode() + + assert "